summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig10
-rw-r--r--drivers/Makefile5
-rw-r--r--drivers/acpi/Kconfig29
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_lpss.c2
-rw-r--r--drivers/acpi/acpi_pad.c2
-rw-r--r--drivers/acpi/acpi_platform.c7
-rw-r--r--drivers/acpi/acpi_pnp.c4
-rw-r--r--drivers/acpi/acpi_processor.c18
-rw-r--r--drivers/acpi/acpi_video.c78
-rw-r--r--drivers/acpi/acpica/Makefile18
-rw-r--r--drivers/acpi/acpica/acapps.h2
-rw-r--r--drivers/acpi/acpica/acdebug.h6
-rw-r--r--drivers/acpi/acpica/acglobal.h8
-rw-r--r--drivers/acpi/acpica/acinterp.h2
-rw-r--r--drivers/acpi/acpica/aclocal.h22
-rw-r--r--drivers/acpi/acpica/acnamesp.h4
-rw-r--r--drivers/acpi/acpica/acopcode.h4
-rw-r--r--drivers/acpi/acpica/acparser.h4
-rw-r--r--drivers/acpi/acpica/actables.h4
-rw-r--r--drivers/acpi/acpica/acutils.h2
-rw-r--r--drivers/acpi/acpica/amlcode.h11
-rw-r--r--drivers/acpi/acpica/dbcmds.c1187
-rw-r--r--drivers/acpi/acpica/dbconvert.c484
-rw-r--r--drivers/acpi/acpica/dbdisply.c1108
-rw-r--r--drivers/acpi/acpica/dbexec.c764
-rw-r--r--drivers/acpi/acpica/dbfileio.c256
-rw-r--r--drivers/acpi/acpica/dbhistry.c239
-rw-r--r--drivers/acpi/acpica/dbinput.c1267
-rw-r--r--drivers/acpi/acpica/dbmethod.c369
-rw-r--r--drivers/acpi/acpica/dbnames.c947
-rw-r--r--drivers/acpi/acpica/dbobject.c533
-rw-r--r--drivers/acpi/acpica/dbstats.c546
-rw-r--r--drivers/acpi/acpica/dbtest.c1057
-rw-r--r--drivers/acpi/acpica/dbutils.c457
-rw-r--r--drivers/acpi/acpica/dbxface.c513
-rw-r--r--drivers/acpi/acpica/evxface.c2
-rw-r--r--drivers/acpi/acpica/evxfevnt.c2
-rw-r--r--drivers/acpi/acpica/exconvrt.c1
-rw-r--r--drivers/acpi/acpica/exresolv.c1
-rw-r--r--drivers/acpi/acpica/exresop.c2
-rw-r--r--drivers/acpi/acpica/exstore.c120
-rw-r--r--drivers/acpi/acpica/exstoren.c5
-rw-r--r--drivers/acpi/acpica/nsdump.c6
-rw-r--r--drivers/acpi/acpica/nspredef.c2
-rw-r--r--drivers/acpi/acpica/pstree.c2
-rw-r--r--drivers/acpi/acpica/psutils.c2
-rw-r--r--drivers/acpi/acpica/rsdump.c3
-rw-r--r--drivers/acpi/acpica/rsutils.c2
-rw-r--r--drivers/acpi/acpica/rsxface.c4
-rw-r--r--drivers/acpi/acpica/tbfadt.c10
-rw-r--r--drivers/acpi/acpica/tbutils.c26
-rw-r--r--drivers/acpi/acpica/utdecode.c21
-rw-r--r--drivers/acpi/acpica/utfileio.c6
-rw-r--r--drivers/acpi/acpica/utinit.c15
-rw-r--r--drivers/acpi/acpica/utmutex.c21
-rw-r--r--drivers/acpi/acpica/utxface.c19
-rw-r--r--drivers/acpi/apei/ghes.c10
-rw-r--r--drivers/acpi/cppc_acpi.c733
-rw-r--r--drivers/acpi/device_pm.c19
-rw-r--r--drivers/acpi/device_sysfs.c120
-rw-r--r--drivers/acpi/ec.c117
-rw-r--r--drivers/acpi/ec_sys.c2
-rw-r--r--drivers/acpi/glue.c13
-rw-r--r--drivers/acpi/gsi.c54
-rw-r--r--drivers/acpi/internal.h8
-rw-r--r--drivers/acpi/nfit.c306
-rw-r--r--drivers/acpi/nfit.h4
-rw-r--r--drivers/acpi/osl.c26
-rw-r--r--drivers/acpi/pci_root.c204
-rw-r--r--drivers/acpi/proc.c4
-rw-r--r--drivers/acpi/processor_driver.c6
-rw-r--r--drivers/acpi/property.c427
-rw-r--r--drivers/acpi/resource.c9
-rw-r--r--drivers/acpi/sbshc.c48
-rw-r--r--drivers/acpi/scan.c109
-rw-r--r--drivers/acpi/sleep.c9
-rw-r--r--drivers/acpi/sysfs.c3
-rw-r--r--drivers/acpi/tables.c94
-rw-r--r--drivers/acpi/thermal.c12
-rw-r--r--drivers/acpi/video_detect.c18
-rw-r--r--drivers/ata/Kconfig9
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci.c12
-rw-r--r--drivers/ata/ahci.h2
-rw-r--r--drivers/ata/ahci_platform.c1
-rw-r--r--drivers/ata/ahci_qoriq.c279
-rw-r--r--drivers/ata/libahci.c30
-rw-r--r--drivers/ata/libata-scsi.c62
-rw-r--r--drivers/ata/pata_it821x.c6
-rw-r--r--drivers/ata/pata_macio.c1
-rw-r--r--drivers/ata/pata_pxa.c171
-rw-r--r--drivers/ata/pata_samsung_cf.c2
-rw-r--r--drivers/atm/iphase.c5
-rw-r--r--drivers/base/class.c2
-rw-r--r--drivers/base/core.c2
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/devres.c19
-rw-r--r--drivers/base/dma-contiguous.c4
-rw-r--r--drivers/base/pinctrl.c15
-rw-r--r--drivers/base/platform-msi.c6
-rw-r--r--drivers/base/platform.c80
-rw-r--r--drivers/base/power/Makefile2
-rw-r--r--drivers/base/power/clock_ops.c12
-rw-r--r--drivers/base/power/domain.c391
-rw-r--r--drivers/base/power/domain_governor.c20
-rw-r--r--drivers/base/power/generic_ops.c23
-rw-r--r--drivers/base/power/opp/Makefile2
-rw-r--r--drivers/base/power/opp/core.c (renamed from drivers/base/power/opp.c)409
-rw-r--r--drivers/base/power/opp/cpu.c270
-rw-r--r--drivers/base/power/opp/opp.h146
-rw-r--r--drivers/base/power/wakeirq.c6
-rw-r--r--drivers/base/power/wakeup.c16
-rw-r--r--drivers/base/property.c120
-rw-r--r--drivers/base/regmap/internal.h9
-rw-r--r--drivers/base/regmap/regcache-lzo.c4
-rw-r--r--drivers/base/regmap/regcache.c24
-rw-r--r--drivers/base/regmap/regmap-debugfs.c23
-rw-r--r--drivers/base/regmap/regmap-irq.c43
-rw-r--r--drivers/base/regmap/regmap.c41
-rw-r--r--drivers/base/soc.c21
-rw-r--r--drivers/bcma/main.c9
-rw-r--r--drivers/block/Kconfig11
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/brd.c8
-rw-r--r--drivers/block/drbd/drbd_bitmap.c4
-rw-r--r--drivers/block/drbd/drbd_int.h2
-rw-r--r--drivers/block/drbd/drbd_receiver.c3
-rw-r--r--drivers/block/drbd/drbd_req.c3
-rw-r--r--drivers/block/loop.c274
-rw-r--r--drivers/block/loop.h13
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c2
-rw-r--r--drivers/block/nbd.c43
-rw-r--r--drivers/block/null_blk.c3
-rw-r--r--drivers/block/osdblk.c2
-rw-r--r--drivers/block/paride/pd.c2
-rw-r--r--drivers/block/pktcdvd.c16
-rw-r--r--drivers/block/ps3vram.c6
-rw-r--r--drivers/block/rbd.c191
-rw-r--r--drivers/block/rsxx/dev.c5
-rw-r--r--drivers/block/umem.c4
-rw-r--r--drivers/block/xen-blkback/blkback.c13
-rw-r--r--drivers/block/xen-blkback/common.h17
-rw-r--r--drivers/block/xen-blkback/xenbus.c11
-rw-r--r--drivers/block/xen-blkfront.c563
-rw-r--r--drivers/block/zram/zram_drv.c33
-rw-r--r--drivers/bluetooth/Kconfig8
-rw-r--r--drivers/bluetooth/ath3k.c4
-rw-r--r--drivers/bluetooth/bfusb.c11
-rw-r--r--drivers/bluetooth/bluecard_cs.c8
-rw-r--r--drivers/bluetooth/bpa10x.c186
-rw-r--r--drivers/bluetooth/bt3c_cs.c20
-rw-r--r--drivers/bluetooth/btbcm.c71
-rw-r--r--drivers/bluetooth/btintel.c369
-rw-r--r--drivers/bluetooth/btintel.h43
-rw-r--r--drivers/bluetooth/btmrvl_main.c33
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c54
-rw-r--r--drivers/bluetooth/btsdio.c14
-rw-r--r--drivers/bluetooth/btuart_cs.c10
-rw-r--r--drivers/bluetooth/btusb.c368
-rw-r--r--drivers/bluetooth/btwilink.c13
-rw-r--r--drivers/bluetooth/dtl1_cs.c5
-rw-r--r--drivers/bluetooth/hci_ath.c1
-rw-r--r--drivers/bluetooth/hci_bcm.c446
-rw-r--r--drivers/bluetooth/hci_h4.c1
-rw-r--r--drivers/bluetooth/hci_h5.c10
-rw-r--r--drivers/bluetooth/hci_intel.c600
-rw-r--r--drivers/bluetooth/hci_ldisc.c24
-rw-r--r--drivers/bluetooth/hci_qca.c21
-rw-r--r--drivers/bluetooth/hci_uart.h2
-rw-r--r--drivers/bluetooth/hci_vhci.c8
-rw-r--r--drivers/bus/Kconfig11
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/arm-ccn.c5
-rw-r--r--drivers/bus/sunxi-rsb.c783
-rw-r--r--drivers/cdrom/cdrom.c1
-rw-r--r--drivers/char/agp/uninorth-agp.c16
-rw-r--r--drivers/char/efirtc.c13
-rw-r--r--drivers/char/hpet.c25
-rw-r--r--drivers/char/hw_random/Kconfig24
-rw-r--r--drivers/char/hw_random/Makefile2
-rw-r--r--drivers/char/hw_random/core.c2
-rw-r--r--drivers/char/hw_random/exynos-rng.c58
-rw-r--r--drivers/char/hw_random/mxc-rnga.c14
-rw-r--r--drivers/char/hw_random/octeon-rng.c12
-rw-r--r--drivers/char/hw_random/pasemi-rng.c1
-rw-r--r--drivers/char/hw_random/ppc4xx-rng.c1
-rw-r--r--drivers/char/hw_random/st-rng.c151
-rw-r--r--drivers/char/hw_random/stm32-rng.c202
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c82
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c9
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c8
-rw-r--r--drivers/char/pcmcia/synclink_cs.c9
-rw-r--r--drivers/char/snsc.c5
-rw-r--r--drivers/char/tpm/st33zp24/Kconfig2
-rw-r--r--drivers/char/tpm/st33zp24/i2c.c1
-rw-r--r--drivers/char/tpm/st33zp24/spi.c1
-rw-r--r--drivers/char/tpm/tpm-chip.c28
-rw-r--r--drivers/char/tpm/tpm-interface.c76
-rw-r--r--drivers/char/tpm/tpm.h134
-rw-r--r--drivers/char/tpm/tpm2-cmd.c255
-rw-r--r--drivers/char/tpm/tpm_crb.c39
-rw-r--r--drivers/char/tpm/tpm_eventlog.c78
-rw-r--r--drivers/char/tpm/tpm_eventlog.h6
-rw-r--r--drivers/char/tpm/tpm_i2c_atmel.c1
-rw-r--r--drivers/char/tpm/tpm_i2c_infineon.c1
-rw-r--r--drivers/char/tpm/tpm_i2c_nuvoton.c1
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c2
-rw-r--r--drivers/char/tpm/tpm_of.c9
-rw-r--r--drivers/char/tpm/tpm_ppi.c34
-rw-r--r--drivers/char/tpm/tpm_tis.c200
-rw-r--r--drivers/clk/Kconfig29
-rw-r--r--drivers/clk/Makefile6
-rw-r--r--drivers/clk/at91/Makefile1
-rw-r--r--drivers/clk/at91/clk-generated.c306
-rw-r--r--drivers/clk/at91/clk-peripheral.c24
-rw-r--r--drivers/clk/at91/clk-system.c3
-rw-r--r--drivers/clk/at91/clk-utmi.c4
-rw-r--r--drivers/clk/at91/pmc.c21
-rw-r--r--drivers/clk/at91/pmc.h3
-rw-r--r--drivers/clk/bcm/Kconfig6
-rw-r--r--drivers/clk/bcm/Makefile4
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c1575
-rw-r--r--drivers/clk/bcm/clk-cygnus.c155
-rw-r--r--drivers/clk/bcm/clk-iproc-pll.c196
-rw-r--r--drivers/clk/bcm/clk-iproc.h22
-rw-r--r--drivers/clk/bcm/clk-ns2.c288
-rw-r--r--drivers/clk/bcm/clk-nsp.c139
-rw-r--r--drivers/clk/berlin/bg2.c4
-rw-r--r--drivers/clk/berlin/bg2q.c16
-rw-r--r--drivers/clk/clk-bcm2835.c55
-rw-r--r--drivers/clk/clk-divider.c20
-rw-r--r--drivers/clk/clk-fractional-divider.c53
-rw-r--r--drivers/clk/clk-max77802.c2
-rw-r--r--drivers/clk/clk-multiplier.c130
-rw-r--r--drivers/clk/clk-qoriq.c1354
-rw-r--r--drivers/clk/clk-scpi.c325
-rw-r--r--drivers/clk/clk-si514.c379
-rw-r--r--drivers/clk/clk-si5351.c17
-rw-r--r--drivers/clk/clk-xgene.c1
-rw-r--r--drivers/clk/clk.c38
-rw-r--r--drivers/clk/clkdev.c3
-rw-r--r--drivers/clk/h8300/clk-div.c6
-rw-r--r--drivers/clk/hisilicon/clk-hi6220-stub.c2
-rw-r--r--drivers/clk/imx/clk-imx25.c12
-rw-r--r--drivers/clk/imx/clk-imx27.c17
-rw-r--r--drivers/clk/imx/clk-imx31.c39
-rw-r--r--drivers/clk/imx/clk-imx35.c59
-rw-r--r--drivers/clk/imx/clk-imx51-imx53.c16
-rw-r--r--drivers/clk/imx/clk-imx6q.c12
-rw-r--r--drivers/clk/imx/clk-imx6sl.c12
-rw-r--r--drivers/clk/imx/clk-imx6sx.c9
-rw-r--r--drivers/clk/imx/clk-imx6ul.c18
-rw-r--r--drivers/clk/imx/clk-imx7d.c14
-rw-r--r--drivers/clk/imx/clk-pllv2.c12
-rw-r--r--drivers/clk/imx/clk-vf610.c1
-rw-r--r--drivers/clk/imx/clk.c38
-rw-r--r--drivers/clk/imx/clk.h1
-rw-r--r--drivers/clk/keystone/pll.c2
-rw-r--r--drivers/clk/mediatek/Makefile2
-rw-r--r--drivers/clk/mediatek/clk-apmixed.c107
-rw-r--r--drivers/clk/mediatek/clk-gate.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173.c347
-rw-r--r--drivers/clk/mediatek/clk-mtk.c36
-rw-r--r--drivers/clk/mediatek/clk-mtk.h24
-rw-r--r--drivers/clk/mediatek/clk-pll.c7
-rw-r--r--drivers/clk/mvebu/common.c2
-rw-r--r--drivers/clk/mxs/clk-frac.c12
-rw-r--r--drivers/clk/nxp/clk-lpc18xx-ccu.c17
-rw-r--r--drivers/clk/nxp/clk-lpc18xx-cgu.c42
-rw-r--r--drivers/clk/qcom/Kconfig9
-rw-r--r--drivers/clk/qcom/Makefile1
-rw-r--r--drivers/clk/qcom/clk-rcg.c230
-rw-r--r--drivers/clk/qcom/clk-rcg.h8
-rw-r--r--drivers/clk/qcom/clk-rcg2.c170
-rw-r--r--drivers/clk/qcom/common.c42
-rw-r--r--drivers/clk/qcom/common.h4
-rw-r--r--drivers/clk/qcom/gcc-apq8084.c49
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c7
-rw-r--r--drivers/clk/qcom/gcc-msm8660.c7
-rw-r--r--drivers/clk/qcom/gcc-msm8916.c569
-rw-r--r--drivers/clk/qcom/gcc-msm8960.c20
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c22
-rw-r--r--drivers/clk/qcom/gdsc.c237
-rw-r--r--drivers/clk/qcom/gdsc.h68
-rw-r--r--drivers/clk/qcom/lcc-ipq806x.c7
-rw-r--r--drivers/clk/qcom/lcc-msm8960.c7
-rw-r--r--drivers/clk/qcom/mmcc-apq8084.c111
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c411
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c92
-rw-r--r--drivers/clk/rockchip/clk-mmc-phase.c65
-rw-r--r--drivers/clk/rockchip/clk-pll.c135
-rw-r--r--drivers/clk/rockchip/clk.c6
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c14
-rw-r--r--drivers/clk/samsung/clk-exynos7.c467
-rw-r--r--drivers/clk/shmobile/clk-mstp.c6
-rw-r--r--drivers/clk/shmobile/clk-r8a7778.c8
-rw-r--r--drivers/clk/sirf/clk-atlas7.c358
-rw-r--r--drivers/clk/st/clk-flexgen.c7
-rw-r--r--drivers/clk/st/clkgen-mux.c3
-rw-r--r--drivers/clk/st/clkgen-pll.c469
-rw-r--r--drivers/clk/st/clkgen.h2
-rw-r--r--drivers/clk/sunxi/Makefile3
-rw-r--r--drivers/clk/sunxi/clk-a10-codec.c44
-rw-r--r--drivers/clk/sunxi/clk-a10-mod1.c81
-rw-r--r--drivers/clk/sunxi/clk-a10-pll2.c216
-rw-r--r--drivers/clk/sunxi/clk-simple-gates.c2
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0-gates.c1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0.c1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c1
-rw-r--r--drivers/clk/sunxi/clk-sun8i-apb0.c1
-rw-r--r--drivers/clk/sunxi/clk-sun9i-mmc.c1
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c1
-rw-r--r--drivers/clk/tegra/clk-dfll.c114
-rw-r--r--drivers/clk/tegra/clk-emc.c4
-rw-r--r--drivers/clk/tegra/clk-tegra-audio.c25
-rw-r--r--drivers/clk/tegra/clk-tegra114.c8
-rw-r--r--drivers/clk/tegra/clk-tegra124.c8
-rw-r--r--drivers/clk/tegra/clk-tegra30.c8
-rw-r--r--drivers/clk/tegra/clk.h106
-rw-r--r--drivers/clk/tegra/cvb.c7
-rw-r--r--drivers/clk/versatile/Kconfig2
-rw-r--r--drivers/clk/versatile/clk-icst.c4
-rw-r--r--drivers/clocksource/Kconfig22
-rw-r--r--drivers/clocksource/Makefile5
-rw-r--r--drivers/clocksource/arm_arch_timer.c10
-rw-r--r--drivers/clocksource/arm_global_timer.c9
-rw-r--r--drivers/clocksource/clksrc-probe.c (renamed from drivers/clocksource/clksrc-of.c)6
-rw-r--r--drivers/clocksource/em_sti.c2
-rw-r--r--drivers/clocksource/exynos_mct.c12
-rw-r--r--drivers/clocksource/fsl_ftm_timer.c6
-rw-r--r--drivers/clocksource/h8300_timer16.c1
-rw-r--r--drivers/clocksource/h8300_timer8.c1
-rw-r--r--drivers/clocksource/h8300_tpu.c1
-rw-r--r--drivers/clocksource/mips-gic-timer.c7
-rw-r--r--drivers/clocksource/mtk_timer.c26
-rw-r--r--drivers/clocksource/numachip.c95
-rw-r--r--drivers/clocksource/samsung_pwm_timer.c2
-rw-r--r--drivers/clocksource/sh_cmt.c1
-rw-r--r--drivers/clocksource/sh_mtu2.c4
-rw-r--r--drivers/clocksource/tango_xtal.c66
-rw-r--r--drivers/clocksource/tcb_clksrc.c12
-rw-r--r--drivers/clocksource/time-armada-370-xp.c14
-rw-r--r--drivers/clocksource/time-pistachio.c3
-rw-r--r--drivers/clocksource/timer-atmel-st.c31
-rw-r--r--drivers/clocksource/timer-digicolor.c2
-rw-r--r--drivers/clocksource/timer-imx-gpt.c3
-rw-r--r--drivers/clocksource/timer-prima2.c2
-rw-r--r--drivers/clocksource/timer-ti-32k.c126
-rw-r--r--drivers/clocksource/vf_pit_timer.c2
-rw-r--r--drivers/connector/connector.c3
-rw-r--r--drivers/cpufreq/Kconfig.arm28
-rw-r--r--drivers/cpufreq/Makefile4
-rw-r--r--drivers/cpufreq/arm_big_little.c22
-rw-r--r--drivers/cpufreq/arm_big_little.h2
-rw-r--r--drivers/cpufreq/arm_big_little_dt.c4
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c175
-rw-r--r--drivers/cpufreq/cpufreq-dt.c10
-rw-r--r--drivers/cpufreq/cpufreq.c112
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c31
-rw-r--r--drivers/cpufreq/cpufreq_governor.c65
-rw-r--r--drivers/cpufreq/cpufreq_governor.h1
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c10
-rw-r--r--drivers/cpufreq/cpufreq_opp.c114
-rw-r--r--drivers/cpufreq/exynos5440-cpufreq.c6
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c56
-rw-r--r--drivers/cpufreq/integrator-cpufreq.c2
-rw-r--r--drivers/cpufreq/intel_pstate.c285
-rw-r--r--drivers/cpufreq/mt8173-cpufreq.c6
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c10
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c4
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c124
-rw-r--r--drivers/cpufreq/tegra20-cpufreq.c2
-rw-r--r--drivers/cpuidle/cpuidle-mvebu-v7.c46
-rw-r--r--drivers/crypto/Kconfig5
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c23
-rw-r--r--drivers/crypto/atmel-aes.c44
-rw-r--r--drivers/crypto/atmel-sha.c33
-rw-r--r--drivers/crypto/atmel-tdes.c35
-rw-r--r--drivers/crypto/bfin_crc.c25
-rw-r--r--drivers/crypto/caam/caamalg.c232
-rw-r--r--drivers/crypto/caam/caamhash.c131
-rw-r--r--drivers/crypto/caam/desc.h1
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h72
-rw-r--r--drivers/crypto/ccp/Kconfig13
-rw-r--r--drivers/crypto/ccp/ccp-crypto-aes-cmac.c20
-rw-r--r--drivers/crypto/ccp/ccp-crypto-main.c6
-rw-r--r--drivers/crypto/ccp/ccp-crypto-sha.c13
-rw-r--r--drivers/crypto/ccp/ccp-ops.c108
-rw-r--r--drivers/crypto/ccp/ccp-pci.c2
-rw-r--r--drivers/crypto/ccp/ccp-platform.c21
-rw-r--r--drivers/crypto/hifn_795x.c2
-rw-r--r--drivers/crypto/marvell/cesa.h55
-rw-r--r--drivers/crypto/marvell/cipher.c13
-rw-r--r--drivers/crypto/marvell/hash.c471
-rw-r--r--drivers/crypto/marvell/tdma.c42
-rw-r--r--drivers/crypto/n2_core.c2
-rw-r--r--drivers/crypto/nx/nx-842-powernv.c4
-rw-r--r--drivers/crypto/nx/nx-842-pseries.c8
-rw-r--r--drivers/crypto/picoxcell_crypto.c1
-rw-r--r--drivers/crypto/qat/qat_common/Makefile12
-rw-r--r--drivers/crypto/qat/qat_common/adf_common_drv.h4
-rw-r--r--drivers/crypto/qat/qat_common/adf_ctl_drv.c8
-rw-r--r--drivers/crypto/qat/qat_common/adf_init.c8
-rw-r--r--drivers/crypto/qat/qat_common/adf_sriov.c7
-rw-r--r--drivers/crypto/qat/qat_common/qat_algs.c178
-rw-r--r--drivers/crypto/qat/qat_common/qat_asym_algs.c213
-rw-r--r--drivers/crypto/qat/qat_common/qat_crypto.c79
-rw-r--r--drivers/crypto/qat/qat_common/qat_hal.c5
-rw-r--r--drivers/crypto/qat/qat_common/qat_rsakey.asn15
-rw-r--r--drivers/crypto/qat/qat_common/qat_rsaprivkey.asn111
-rw-r--r--drivers/crypto/qat/qat_common/qat_rsapubkey.asn14
-rw-r--r--drivers/crypto/qce/ablkcipher.c30
-rw-r--r--drivers/crypto/qce/cipher.h4
-rw-r--r--drivers/crypto/qce/dma.c52
-rw-r--r--drivers/crypto/qce/dma.h5
-rw-r--r--drivers/crypto/qce/sha.c18
-rw-r--r--drivers/crypto/qce/sha.h2
-rw-r--r--drivers/crypto/sahara.c108
-rw-r--r--drivers/crypto/talitos.c104
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c71
-rw-r--r--drivers/crypto/ux500/hash/hash_core.c50
-rw-r--r--drivers/dma-buf/fence.c98
-rw-r--r--drivers/dma/Kconfig4
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/acpi-dma.c36
-rw-r--r--drivers/dma/at_hdmac.c184
-rw-r--r--drivers/dma/at_hdmac_regs.h8
-rw-r--r--drivers/dma/at_xdmac.c126
-rw-r--r--drivers/dma/dmaengine.c6
-rw-r--r--drivers/dma/dw/core.c75
-rw-r--r--drivers/dma/dw/pci.c20
-rw-r--r--drivers/dma/dw/platform.c17
-rw-r--r--drivers/dma/edma.c1858
-rw-r--r--drivers/dma/fsldma.c1
-rw-r--r--drivers/dma/hsu/Kconfig9
-rw-r--r--drivers/dma/hsu/hsu.c24
-rw-r--r--drivers/dma/hsu/hsu.h1
-rw-r--r--drivers/dma/hsu/pci.c2
-rw-r--r--drivers/dma/idma64.c22
-rw-r--r--drivers/dma/idma64.h14
-rw-r--r--drivers/dma/imx-sdma.c7
-rw-r--r--drivers/dma/ioat/dma.c3
-rw-r--r--drivers/dma/ioat/dma.h6
-rw-r--r--drivers/dma/ioat/init.c114
-rw-r--r--drivers/dma/ioat/prep.c34
-rw-r--r--drivers/dma/mic_x100_dma.c39
-rw-r--r--drivers/dma/moxart-dma.c1
-rw-r--r--drivers/dma/mpc512x_dma.c1
-rw-r--r--drivers/dma/omap-dma.c6
-rw-r--r--drivers/dma/sh/usb-dmac.c11
-rw-r--r--drivers/dma/sirf-dma.c1
-rw-r--r--drivers/dma/ste_dma40.c2
-rw-r--r--drivers/dma/sun6i-dma.c1
-rw-r--r--drivers/dma/ti-dma-crossbar.c251
-rw-r--r--drivers/dma/virt-dma.h18
-rw-r--r--drivers/dma/xgene-dma.c63
-rw-r--r--drivers/dma/xilinx/xilinx_vdma.c1
-rw-r--r--drivers/dma/zx296702_dma.c2
-rw-r--r--drivers/edac/Makefile2
-rw-r--r--drivers/edac/altera_edac.c20
-rw-r--r--drivers/edac/altera_edac.h5
-rw-r--r--drivers/edac/amd64_edac.c41
-rw-r--r--drivers/edac/amd64_edac.h58
-rw-r--r--drivers/edac/debugfs.c163
-rw-r--r--drivers/edac/edac_core.h2
-rw-r--r--drivers/edac/edac_mc.c2
-rw-r--r--drivers/edac/edac_mc_sysfs.c150
-rw-r--r--drivers/edac/edac_module.h34
-rw-r--r--drivers/edac/ghes_edac.c24
-rw-r--r--drivers/edac/i3200_edac.c2
-rw-r--r--drivers/edac/i5100_edac.c37
-rw-r--r--drivers/edac/ie31200_edac.c2
-rw-r--r--drivers/edac/ppc4xx_edac.c1
-rw-r--r--drivers/edac/sb_edac.c8
-rw-r--r--drivers/edac/x38_edac.c2
-rw-r--r--drivers/edac/xgene_edac.c1193
-rw-r--r--drivers/extcon/extcon-arizona.c164
-rw-r--r--drivers/extcon/extcon-axp288.c35
-rw-r--r--drivers/extcon/extcon-gpio.c130
-rw-r--r--drivers/extcon/extcon-max14577.c17
-rw-r--r--drivers/extcon/extcon-max77693.c32
-rw-r--r--drivers/extcon/extcon-max77843.c27
-rw-r--r--drivers/extcon/extcon-max8997.c21
-rw-r--r--drivers/extcon/extcon-rt8973a.c7
-rw-r--r--drivers/extcon/extcon-sm5502.c7
-rw-r--r--drivers/extcon/extcon.c61
-rw-r--r--drivers/firewire/core-cdev.c2
-rw-r--r--drivers/firewire/ohci.c5
-rw-r--r--drivers/firmware/Kconfig26
-rw-r--r--drivers/firmware/Makefile4
-rw-r--r--drivers/firmware/arm_scpi.c771
-rw-r--r--drivers/firmware/efi/Kconfig22
-rw-r--r--drivers/firmware/efi/Makefile9
-rw-r--r--drivers/firmware/efi/efi-pstore.c3
-rw-r--r--drivers/firmware/efi/efi.c107
-rw-r--r--drivers/firmware/efi/esrt.c19
-rw-r--r--drivers/firmware/efi/fake_mem.c238
-rw-r--r--drivers/firmware/efi/libstub/Makefile42
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c78
-rw-r--r--drivers/firmware/efi/libstub/fdt.c9
-rw-r--r--drivers/firmware/efi/libstub/string.c57
-rw-r--r--drivers/firmware/psci.c108
-rw-r--r--drivers/firmware/qcom_scm-32.c6
-rw-r--r--drivers/firmware/raspberrypi.c260
-rw-r--r--drivers/fpga/Kconfig29
-rw-r--r--drivers/fpga/Makefile10
-rw-r--r--drivers/fpga/fpga-mgr.c380
-rw-r--r--drivers/fpga/socfpga.c616
-rw-r--r--drivers/fpga/zynq-fpga.c514
-rw-r--r--drivers/gpio/Kconfig196
-rw-r--r--drivers/gpio/Makefile5
-rw-r--r--drivers/gpio/gpio-104-idio-16.c216
-rw-r--r--drivers/gpio/gpio-74x164.c1
-rw-r--r--drivers/gpio/gpio-altera.c15
-rw-r--r--drivers/gpio/gpio-amdpt.c261
-rw-r--r--drivers/gpio/gpio-arizona.c2
-rw-r--r--drivers/gpio/gpio-ath79.c119
-rw-r--r--drivers/gpio/gpio-etraxfs.c23
-rw-r--r--drivers/gpio/gpio-generic.c58
-rw-r--r--drivers/gpio/gpio-it87.c411
-rw-r--r--drivers/gpio/gpio-it8761e.c230
-rw-r--r--drivers/gpio/gpio-lpc18xx.c14
-rw-r--r--drivers/gpio/gpio-max7301.c1
-rw-r--r--drivers/gpio/gpio-max730x.c1
-rw-r--r--drivers/gpio/gpio-mc33880.c1
-rw-r--r--drivers/gpio/gpio-mcp23s08.c2
-rw-r--r--drivers/gpio/gpio-moxart.c14
-rw-r--r--drivers/gpio/gpio-msm-v2.c453
-rw-r--r--drivers/gpio/gpio-mvebu.c14
-rw-r--r--drivers/gpio/gpio-mxc.c2
-rw-r--r--drivers/gpio/gpio-omap.c82
-rw-r--r--drivers/gpio/gpio-pca953x.c45
-rw-r--r--drivers/gpio/gpio-pl061.c112
-rw-r--r--drivers/gpio/gpio-sodaville.c2
-rw-r--r--drivers/gpio/gpio-sx150x.c31
-rw-r--r--drivers/gpio/gpio-tb10x.c14
-rw-r--r--drivers/gpio/gpio-tz1090-pdc.c14
-rw-r--r--drivers/gpio/gpio-vf610.c43
-rw-r--r--drivers/gpio/gpio-xlp.c21
-rw-r--r--drivers/gpio/gpio-zx.c28
-rw-r--r--drivers/gpio/gpio-zynq.c32
-rw-r--r--drivers/gpio/gpiolib-acpi.c174
-rw-r--r--drivers/gpio/gpiolib-legacy.c8
-rw-r--r--drivers/gpio/gpiolib-of.c20
-rw-r--r--drivers/gpio/gpiolib.c178
-rw-r--r--drivers/gpio/gpiolib.h13
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h221
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c227
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c47
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c480
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c53
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c77
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c71
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c46
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_semaphore.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c65
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h106
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c200
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.c53
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c149
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_smc.c60
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c267
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c288
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c269
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c1118
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c57
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c175
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c213
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c53
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_d.h2791
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_enum.h6808
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_sh_mask.h21368
-rw-r--r--drivers/gpu/drm/amd/include/atombios.h2
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h24
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.c76
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.h13
-rw-r--r--drivers/gpu/drm/amd/scheduler/sched_fence.c10
-rw-r--r--drivers/gpu/drm/armada/Kconfig9
-rw-r--r--drivers/gpu/drm/armada/Makefile3
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c258
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h34
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h16
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c221
-rw-r--r--drivers/gpu/drm/armada/armada_output.c142
-rw-r--r--drivers/gpu/drm/armada/armada_output.h33
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c147
-rw-r--r--drivers/gpu/drm/armada/armada_slave.c139
-rw-r--r--drivers/gpu/drm/armada/armada_slave.h26
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h1
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c7
-rw-r--r--drivers/gpu/drm/ast/ast_main.c1
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c8
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c6
-rw-r--r--drivers/gpu/drm/bridge/Kconfig12
-rw-r--r--drivers/gpu/drm/bridge/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c653
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi-audio.h14
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c391
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.h3
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c1
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c1
-rw-r--r--drivers/gpu/drm/drm_agpsupport.c4
-rw-r--r--drivers/gpu/drm/drm_atomic.c89
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c340
-rw-r--r--drivers/gpu/drm/drm_bufs.c6
-rw-r--r--drivers/gpu/drm/drm_crtc.c152
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c44
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c10
-rw-r--r--drivers/gpu/drm/drm_drv.c67
-rw-r--r--drivers/gpu/drm/drm_edid.c60
-rw-r--r--drivers/gpu/drm/drm_edid_load.c43
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c189
-rw-r--r--drivers/gpu/drm/drm_gem.c49
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c3
-rw-r--r--drivers/gpu/drm/drm_internal.h2
-rw-r--r--drivers/gpu/drm/drm_ioc32.c6
-rw-r--r--drivers/gpu/drm/drm_ioctl.c93
-rw-r--r--drivers/gpu/drm/drm_irq.c375
-rw-r--r--drivers/gpu/drm/drm_lock.c41
-rw-r--r--drivers/gpu/drm/drm_memory.c6
-rw-r--r--drivers/gpu/drm/drm_mm.c6
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c2
-rw-r--r--drivers/gpu/drm/drm_of.c88
-rw-r--r--drivers/gpu/drm/drm_pci.c11
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c6
-rw-r--r--drivers/gpu/drm/drm_platform.c3
-rw-r--r--drivers/gpu/drm/drm_rect.c4
-rw-r--r--drivers/gpu/drm/drm_sysfs.c61
-rw-r--r--drivers/gpu/drm/drm_vm.c8
-rw-r--r--drivers/gpu/drm/drm_vma_manager.c40
-rw-r--r--drivers/gpu/drm/exynos/Kconfig75
-rw-r--r--drivers/gpu/drm/exynos/Makefile3
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c324
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c16
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c28
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c45
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c53
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c16
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c275
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c20
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c496
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c17
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.h20
-rw-r--r--drivers/gpu/drm/exynos/regs-hdmi.h33
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c7
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c2
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_dp.c1
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h6
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c8
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.h6
-rw-r--r--drivers/gpu/drm/i2c/ch7006_drv.c6
-rw-r--r--drivers/gpu/drm/i2c/ch7006_mode.c26
-rw-r--r--drivers/gpu/drm/i2c/ch7006_priv.h12
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c487
-rw-r--r--drivers/gpu/drm/i915/Makefile4
-rw-r--r--drivers/gpu/drm/i915/dvo.h4
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7017.c4
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7xxx.c4
-rw-r--r--drivers/gpu/drm/i915/dvo_ivch.c12
-rw-r--r--drivers/gpu/drm/i915/dvo_ns2501.c4
-rw-r--r--drivers/gpu/drm/i915/dvo_sil164.c4
-rw-r--r--drivers/gpu/drm/i915/dvo_tfp410.c4
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c17
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c264
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c246
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c83
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h156
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c285
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c31
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c45
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c167
-rw-r--r--drivers/gpu/drm/i915/i915_gem_fence.c47
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c878
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h77
-rw-r--r--drivers/gpu/drm/i915/i915_gem_shrinker.c21
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c181
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c338
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c78
-rw-r--r--drivers/gpu/drm/i915/i915_guc_reg.h21
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c975
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c686
-rw-r--r--drivers/gpu/drm/i915/i915_params.c38
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h593
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c45
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c34
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h78
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.h34
-rw-r--r--drivers/gpu/drm/i915/intel_acpi.c3
-rw-r--r--drivers/gpu/drm/i915/intel_atomic.c13
-rw-r--r--drivers/gpu/drm/i915/intel_atomic_plane.c6
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c220
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c43
-rw-r--r--drivers/gpu/drm/i915/intel_bios.h3
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c46
-rw-r--r--drivers/gpu/drm/i915/intel_csr.c41
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c257
-rw-r--r--drivers/gpu/drm/i915/intel_display.c1080
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c838
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c26
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h101
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c323
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.h7
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_pll.c243
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c64
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c264
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c23
-rw-r--r--drivers/gpu/drm/i915/intel_guc.h124
-rw-r--r--drivers/gpu/drm/i915/intel_guc_fwif.h31
-rw-r--r--drivers/gpu/drm/i915/intel_guc_loader.c608
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c306
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c54
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c428
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.h18
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c50
-rw-r--r--drivers/gpu/drm/i915/intel_modes.c9
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c92
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c525
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c579
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c18
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c264
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h15
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c492
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c51
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c59
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c14
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c49
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c16
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c65
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c16
-rw-r--r--drivers/gpu/drm/mga/mga_dma.c4
-rw-r--r--drivers/gpu/drm/mga/mga_drv.h6
-rw-r--r--drivers/gpu/drm/mga/mga_irq.c20
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_cursor.c11
-rw-r--r--drivers/gpu/drm/msm/Kconfig14
-rw-r--r--drivers/gpu/drm/msm/Makefile2
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h9
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h27
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h15
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h13
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h9
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h238
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h8
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c6
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h21
-rw-r--r--drivers/gpu/drm/msm/edp/edp.xml.h8
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c17
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h8
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c10
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h86
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c95
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h11
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c46
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c211
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h15
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h6
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c36
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gem_prime.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/os.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h15
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h10
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c84
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c38
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c41
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c24
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_platform.c19
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sysfs.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c36
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_usif.c15
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c83
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c17
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c17
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c141
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c123
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c121
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c17
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c51
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c377
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c64
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c39
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c (renamed from drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv50.c)14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c119
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c18
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_irq.c16
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c12
-rw-r--r--drivers/gpu/drm/panel/panel-lg-lg4573.c1
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-ld9040.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c10
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c7
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c19
-rw-r--r--drivers/gpu/drm/qxl/qxl_ioctl.c14
-rw-r--r--drivers/gpu/drm/qxl/qxl_release.c4
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c12
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h6
-rw-r--r--drivers/gpu/drm/r128/r128_irq.c16
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c1
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c19
-rw-r--r--drivers/gpu/drm/radeon/cayman_blit_shaders.c2
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c32
-rw-r--r--drivers/gpu/drm/radeon/evergreen_blit_shaders.c2
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c104
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_shaders.c2
-rw-r--r--drivers/gpu/drm/radeon/r600_cp.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_acpi.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_agp.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c51
-rw-r--r--drivers/gpu/drm/radeon/radeon_dp_mst.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h6
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq.c38
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c143
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c15
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c81
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c10
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c3
-rw-r--r--drivers/gpu/drm/rcar-du/Kconfig2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c48
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c45
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c8
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c3
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.c6
-rw-r--r--drivers/gpu/drm/sis/sis_drv.h4
-rw-r--r--drivers/gpu/drm/sti/Kconfig8
-rw-r--r--drivers/gpu/drm/sti/Makefile21
-rw-r--r--drivers/gpu/drm/sti/sti_awg_utils.c4
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c4
-rw-r--r--drivers/gpu/drm/sti/sti_crtc.c55
-rw-r--r--drivers/gpu/drm/sti/sti_crtc.h4
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c37
-rw-r--r--drivers/gpu/drm/sti/sti_drv.h9
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c7
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c7
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c69
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c306
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c14
-rw-r--r--drivers/gpu/drm/sti/sti_plane.c3
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c2
-rw-r--r--drivers/gpu/drm/sti/sti_vtac.c2
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.c22
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.h4
-rw-r--r--drivers/gpu/drm/tegra/dc.c16
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c3
-rw-r--r--drivers/gpu/drm/tegra/drm.c37
-rw-r--r--drivers/gpu/drm/tegra/fb.c1
-rw-r--r--drivers/gpu/drm/tegra/sor.c4
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c6
-rw-r--r--drivers/gpu/drm/vc4/Kconfig14
-rw-r--r--drivers/gpu/drm/vc4/Makefile17
-rw-r--r--drivers/gpu/drm/vc4/vc4_bo.c52
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c673
-rw-r--r--drivers/gpu/drm/vc4/vc4_debugfs.c39
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c297
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h145
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c590
-rw-r--r--drivers/gpu/drm/vc4/vc4_hvs.c163
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c67
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c330
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h570
-rw-r--r--drivers/gpu/drm/vgem/vgem_drv.c55
-rw-r--r--drivers/gpu/drm/via/via_drv.h10
-rw-r--r--drivers/gpu/drm/via/via_irq.c17
-rw-r--r--drivers/gpu/drm/virtio/Makefile3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_debugfs.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c57
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c28
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h72
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fence.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_gem.c41
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ioctl.c573
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c133
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_object.c11
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_prime.c71
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ttm.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c322
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c34
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c72
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h43
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c132
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c38
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c113
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c31
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c5
-rw-r--r--drivers/gpu/host1x/hw/debug_hw.c2
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x01_sync.h8
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x02_sync.h8
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x04_sync.h8
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c5
-rw-r--r--drivers/gpu/ipu-v3/ipu-cpmem.c87
-rw-r--r--drivers/gpu/ipu-v3/ipu-csi.c5
-rw-r--r--drivers/gpu/ipu-v3/ipu-dc.c15
-rw-r--r--drivers/gpu/ipu-v3/ipu-di.c129
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c382
-rw-r--r--drivers/gpu/vga/vgaarb.c4
-rw-r--r--drivers/hid/Kconfig21
-rw-r--r--drivers/hid/Makefile2
-rw-r--r--drivers/hid/hid-appleir.c4
-rw-r--r--drivers/hid/hid-aureal.c3
-rw-r--r--drivers/hid/hid-core.c10
-rw-r--r--drivers/hid/hid-corsair.c673
-rw-r--r--drivers/hid/hid-dr.c58
-rw-r--r--drivers/hid/hid-elecom.c2
-rw-r--r--drivers/hid/hid-elo.c4
-rw-r--r--drivers/hid/hid-gfrm.c159
-rw-r--r--drivers/hid/hid-ids.h7
-rw-r--r--drivers/hid/hid-input.c10
-rw-r--r--drivers/hid/hid-lenovo.c4
-rw-r--r--drivers/hid/hid-lg.c9
-rw-r--r--drivers/hid/hid-lg4ff.c127
-rw-r--r--drivers/hid/hid-logitech-hidpp.c163
-rw-r--r--drivers/hid/hid-magicmouse.c8
-rw-r--r--drivers/hid/hid-microsoft.c2
-rw-r--r--drivers/hid/hid-multitouch.c68
-rw-r--r--drivers/hid/hid-ntrig.c6
-rw-r--r--drivers/hid/hid-prodikeys.c4
-rw-r--r--drivers/hid/hid-rmi.c11
-rw-r--r--drivers/hid/hid-saitek.c2
-rw-r--r--drivers/hid/hid-sensor-hub.c25
-rw-r--r--drivers/hid/hid-sony.c13
-rw-r--r--drivers/hid/hid-uclogic.c6
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c1
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--drivers/hid/wacom_sys.c58
-rw-r--r--drivers/hid/wacom_wac.c194
-rw-r--r--drivers/hid/wacom_wac.h10
-rw-r--r--drivers/hsi/clients/ssi_protocol.c2
-rw-r--r--drivers/hsi/controllers/omap_ssi.c21
-rw-r--r--drivers/hsi/controllers/omap_ssi_port.c2
-rw-r--r--drivers/hsi/hsi.c13
-rw-r--r--drivers/hv/hyperv_vmbus.h5
-rw-r--r--drivers/hwmon/Kconfig20
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/abx500.c2
-rw-r--r--drivers/hwmon/ad7314.c1
-rw-r--r--drivers/hwmon/adcxx.c1
-rw-r--r--drivers/hwmon/ads7871.c1
-rw-r--r--drivers/hwmon/adt7310.c1
-rw-r--r--drivers/hwmon/applesmc.c6
-rw-r--r--drivers/hwmon/coretemp.c2
-rw-r--r--drivers/hwmon/fam15h_power.c87
-rw-r--r--drivers/hwmon/ibmpowernv.c7
-rw-r--r--drivers/hwmon/ina2xx.c243
-rw-r--r--drivers/hwmon/k10temp.c1
-rw-r--r--drivers/hwmon/lm70.c1
-rw-r--r--drivers/hwmon/lm75.c7
-rw-r--r--drivers/hwmon/max1111.c1
-rw-r--r--drivers/hwmon/max31790.c603
-rw-r--r--drivers/hwmon/nct6775.c101
-rw-r--r--drivers/hwmon/scpi-hwmon.c289
-rw-r--r--drivers/hwtracing/coresight/coresight-etm3x.c107
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c22
-rw-r--r--drivers/hwtracing/coresight/coresight.c5
-rw-r--r--drivers/hwtracing/intel_th/Kconfig72
-rw-r--r--drivers/hwtracing/intel_th/Makefile18
-rw-r--r--drivers/hwtracing/intel_th/core.c692
-rw-r--r--drivers/hwtracing/intel_th/debug.c36
-rw-r--r--drivers/hwtracing/intel_th/debug.h34
-rw-r--r--drivers/hwtracing/intel_th/gth.c706
-rw-r--r--drivers/hwtracing/intel_th/gth.h66
-rw-r--r--drivers/hwtracing/intel_th/intel_th.h244
-rw-r--r--drivers/hwtracing/intel_th/msu.c1509
-rw-r--r--drivers/hwtracing/intel_th/msu.h116
-rw-r--r--drivers/hwtracing/intel_th/pci.c86
-rw-r--r--drivers/hwtracing/intel_th/pti.c252
-rw-r--r--drivers/hwtracing/intel_th/pti.h29
-rw-r--r--drivers/hwtracing/intel_th/sth.c259
-rw-r--r--drivers/hwtracing/intel_th/sth.h42
-rw-r--r--drivers/hwtracing/stm/Kconfig26
-rw-r--r--drivers/hwtracing/stm/Makefile9
-rw-r--r--drivers/hwtracing/stm/console.c80
-rw-r--r--drivers/hwtracing/stm/core.c1032
-rw-r--r--drivers/hwtracing/stm/dummy_stm.c66
-rw-r--r--drivers/hwtracing/stm/policy.c472
-rw-r--r--drivers/hwtracing/stm/stm.h87
-rw-r--r--drivers/i2c/busses/Kconfig25
-rw-r--r--drivers/i2c/busses/Makefile2
-rw-r--r--drivers/i2c/busses/i2c-at91.c82
-rw-r--r--drivers/i2c/busses/i2c-au1550.c60
-rw-r--r--drivers/i2c/busses/i2c-davinci.c8
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c74
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h10
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c33
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c110
-rw-r--r--drivers/i2c/busses/i2c-i801.c22
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c1
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c73
-rw-r--r--drivers/i2c/busses/i2c-imx.c74
-rw-r--r--drivers/i2c/busses/i2c-ismt.c82
-rw-r--r--drivers/i2c/busses/i2c-meson.c1
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c16
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-ocores.c31
-rw-r--r--drivers/i2c/busses/i2c-pnx.c17
-rw-r--r--drivers/i2c/busses/i2c-pxa.c41
-rw-r--r--drivers/i2c/busses/i2c-rcar.c31
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c1
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c8
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c1
-rw-r--r--drivers/i2c/busses/i2c-sirf.c26
-rw-r--r--drivers/i2c/busses/i2c-stu300.c1
-rw-r--r--drivers/i2c/busses/i2c-tegra.c1
-rw-r--r--drivers/i2c/busses/i2c-uniphier-f.c584
-rw-r--r--drivers/i2c/busses/i2c-uniphier.c441
-rw-r--r--drivers/i2c/busses/i2c-xiic.c4
-rw-r--r--drivers/i2c/i2c-core.c96
-rw-r--r--drivers/i2c/i2c-dev.c23
-rw-r--r--drivers/i2c/i2c-mux.c8
-rw-r--r--drivers/ide/ide-atapi.c2
-rw-r--r--drivers/ide/ide-cd.c2
-rw-r--r--drivers/ide/ide-cd_ioctl.c2
-rw-r--r--drivers/ide/ide-devsets.c2
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-ioctls.c4
-rw-r--r--drivers/ide/ide-park.c2
-rw-r--r--drivers/ide/ide-pm.c4
-rw-r--r--drivers/ide/ide-tape.c4
-rw-r--r--drivers/ide/ide-taskfile.c4
-rw-r--r--drivers/ide/pdc202xx_new.c10
-rw-r--r--drivers/iio/accel/kxsd9.c1
-rw-r--r--drivers/iio/accel/st_accel_core.c6
-rw-r--r--drivers/iio/accel/st_accel_spi.c1
-rw-r--r--drivers/iio/adc/ad7266.c1
-rw-r--r--drivers/iio/adc/ad7298.c1
-rw-r--r--drivers/iio/adc/ad7476.c1
-rw-r--r--drivers/iio/adc/ad7791.c1
-rw-r--r--drivers/iio/adc/ad7793.c3
-rw-r--r--drivers/iio/adc/ad7887.c1
-rw-r--r--drivers/iio/adc/ad7923.c1
-rw-r--r--drivers/iio/adc/max1027.c1
-rw-r--r--drivers/iio/adc/mcp320x.c1
-rw-r--r--drivers/iio/adc/ti-adc128s052.c1
-rw-r--r--drivers/iio/adc/twl4030-madc.c34
-rw-r--r--drivers/iio/adc/vf610_adc.c22
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c1
-rw-r--r--drivers/iio/amplifiers/ad8366.c1
-rw-r--r--drivers/iio/common/ssp_sensors/ssp_dev.c1
-rw-r--r--drivers/iio/dac/ad5064.c92
-rw-r--r--drivers/iio/dac/ad5360.c1
-rw-r--r--drivers/iio/dac/ad5380.c1
-rw-r--r--drivers/iio/dac/ad5421.c1
-rw-r--r--drivers/iio/dac/ad5446.c1
-rw-r--r--drivers/iio/dac/ad5449.c1
-rw-r--r--drivers/iio/dac/ad5504.c1
-rw-r--r--drivers/iio/dac/ad5624r_spi.c1
-rw-r--r--drivers/iio/dac/ad5686.c1
-rw-r--r--drivers/iio/dac/ad5755.c1
-rw-r--r--drivers/iio/dac/ad5764.c1
-rw-r--r--drivers/iio/dac/ad5791.c1
-rw-r--r--drivers/iio/dac/ad7303.c1
-rw-r--r--drivers/iio/dac/mcp4922.c1
-rw-r--r--drivers/iio/dummy/iio_simple_dummy.c11
-rw-r--r--drivers/iio/dummy/iio_simple_dummy.h16
-rw-r--r--drivers/iio/dummy/iio_simple_dummy_buffer.c8
-rw-r--r--drivers/iio/frequency/ad9523.c1
-rw-r--r--drivers/iio/frequency/adf4350.c1
-rw-r--r--drivers/iio/gyro/adis16080.c1
-rw-r--r--drivers/iio/gyro/adis16130.c1
-rw-r--r--drivers/iio/gyro/adis16136.c1
-rw-r--r--drivers/iio/gyro/adis16260.c1
-rw-r--r--drivers/iio/gyro/adxrs450.c1
-rw-r--r--drivers/iio/gyro/st_gyro_spi.c1
-rw-r--r--drivers/iio/humidity/si7020.c8
-rw-r--r--drivers/iio/imu/adis16400_core.c1
-rw-r--r--drivers/iio/imu/adis16480.c1
-rw-r--r--drivers/iio/magnetometer/st_magn_spi.c1
-rw-r--r--drivers/iio/pressure/ms5611_spi.c1
-rw-r--r--drivers/iio/pressure/st_pressure_spi.c1
-rw-r--r--drivers/iio/proximity/as3935.c1
-rw-r--r--drivers/infiniband/core/addr.c20
-rw-r--r--drivers/infiniband/core/agent.c2
-rw-r--r--drivers/infiniband/core/cache.c114
-rw-r--r--drivers/infiniband/core/cm.c50
-rw-r--r--drivers/infiniband/core/cma.c233
-rw-r--r--drivers/infiniband/core/core_priv.h9
-rw-r--r--drivers/infiniband/core/device.c19
-rw-r--r--drivers/infiniband/core/mad.c42
-rw-r--r--drivers/infiniband/core/mad_priv.h2
-rw-r--r--drivers/infiniband/core/multicast.c3
-rw-r--r--drivers/infiniband/core/roce_gid_mgmt.c35
-rw-r--r--drivers/infiniband/core/sa_query.c21
-rw-r--r--drivers/infiniband/core/sysfs.c2
-rw-r--r--drivers/infiniband/core/ucma.c12
-rw-r--r--drivers/infiniband/core/uverbs.h1
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c402
-rw-r--r--drivers/infiniband/core/uverbs_main.c1
-rw-r--r--drivers/infiniband/core/uverbs_marshall.c4
-rw-r--r--drivers/infiniband/core/verbs.c295
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cq.c2
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c39
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.h2
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c43
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c331
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c10
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h25
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c63
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c5
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c73
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h5
-rw-r--r--drivers/infiniband/hw/mlx4/ah.c17
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c2
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c91
-rw-r--r--drivers/infiniband/hw/mlx4/main.c75
-rw-r--r--drivers/infiniband/hw/mlx4/mcg.c2
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h37
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c169
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c330
-rw-r--r--drivers/infiniband/hw/mlx5/cq.c4
-rw-r--r--drivers/infiniband/hw/mlx5/main.c5
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h54
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c187
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c227
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c84
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h6
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c3
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c170
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h4
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma.h5
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_ah.c22
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c60
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c19
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_stats.c2
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c184
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.h7
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_keys.c41
-rw-r--r--drivers/infiniband/hw/qib/qib_mr.c46
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_rc.c38
-rw-r--r--drivers/infiniband/hw/qib/qib_ruc.c20
-rw-r--r--drivers/infiniband/hw/qib/qib_uc.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_ud.c20
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.c29
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h19
-rw-r--r--drivers/infiniband/hw/usnic/usnic.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_abi.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_common_util.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_debugfs.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_debugfs.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_fwd.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_fwd.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_main.c30
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c29
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_sysfs.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_sysfs.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_verbs.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_verbs.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_log.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_transport.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_transport.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_uiom.c2
-rw-r--r--drivers/infiniband/hw/usnic/usnic_uiom.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_vnic.c21
-rw-r--r--drivers/infiniband/hw/usnic/usnic_vnic.h21
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c22
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c6
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c20
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h25
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c51
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c370
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c20
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c269
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h8
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c267
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h11
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c113
-rw-r--r--drivers/input/evdev.c270
-rw-r--r--drivers/input/ff-core.c9
-rw-r--r--drivers/input/input.c25
-rw-r--r--drivers/input/joydev.c22
-rw-r--r--drivers/input/joystick/db9.c113
-rw-r--r--drivers/input/joystick/gamecon.c103
-rw-r--r--drivers/input/joystick/turbografx.c104
-rw-r--r--drivers/input/joystick/walkera0701.c68
-rw-r--r--drivers/input/joystick/xpad.c534
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/gpio_keys.c8
-rw-r--r--drivers/input/keyboard/gpio_keys_polled.c88
-rw-r--r--drivers/input/keyboard/nomadik-ske-keypad.c2
-rw-r--r--drivers/input/keyboard/snvs_pwrkey.c3
-rw-r--r--drivers/input/keyboard/tegra-kbc.c5
-rw-r--r--drivers/input/misc/Kconfig12
-rw-r--r--drivers/input/misc/ad714x-i2c.c10
-rw-r--r--drivers/input/misc/ad714x-spi.c11
-rw-r--r--drivers/input/misc/ad714x.c214
-rw-r--r--drivers/input/misc/ad714x.h1
-rw-r--r--drivers/input/misc/adxl34x-spi.c1
-rw-r--r--drivers/input/misc/da9063_onkey.c129
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c52
-rw-r--r--drivers/input/misc/kxtj9.c3
-rw-r--r--drivers/input/misc/rotary_encoder.c129
-rw-r--r--drivers/input/misc/xen-kbdfront.c10
-rw-r--r--drivers/input/mouse/alps.c48
-rw-r--r--drivers/input/mouse/cyapa_gen6.c10
-rw-r--r--drivers/input/mouse/elantech.c7
-rw-r--r--drivers/input/serio/Kconfig14
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/i8042.c32
-rw-r--r--drivers/input/serio/parkbd.c57
-rw-r--r--drivers/input/serio/userio.c285
-rw-r--r--drivers/input/touchscreen/Kconfig42
-rw-r--r--drivers/input/touchscreen/Makefile4
-rw-r--r--drivers/input/touchscreen/ad7877.c1
-rw-r--r--drivers/input/touchscreen/ad7879-spi.c1
-rw-r--r--drivers/input/touchscreen/ads7846.c13
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c7
-rw-r--r--drivers/input/touchscreen/cyttsp4_i2c.c5
-rw-r--r--drivers/input/touchscreen/cyttsp4_spi.c1
-rw-r--r--drivers/input/touchscreen/cyttsp_spi.c1
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c246
-rw-r--r--drivers/input/touchscreen/ft6236.c326
-rw-r--r--drivers/input/touchscreen/lpc32xx_ts.c4
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c12
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c1218
-rw-r--r--drivers/input/touchscreen/sur40.c20
-rw-r--r--drivers/input/touchscreen/tps6507x-ts.c9
-rw-r--r--drivers/input/touchscreen/tsc2004.c83
-rw-r--r--drivers/input/touchscreen/tsc2005.c715
-rw-r--r--drivers/input/touchscreen/tsc200x-core.c665
-rw-r--r--drivers/input/touchscreen/tsc200x-core.h78
-rw-r--r--drivers/input/touchscreen/zforce_ts.c7
-rw-r--r--drivers/iommu/Kconfig28
-rw-r--r--drivers/iommu/Makefile3
-rw-r--r--drivers/iommu/amd_iommu.c188
-rw-r--r--drivers/iommu/amd_iommu_init.c125
-rw-r--r--drivers/iommu/amd_iommu_types.h16
-rw-r--r--drivers/iommu/amd_iommu_v2.c7
-rw-r--r--drivers/iommu/arm-smmu-v3.c176
-rw-r--r--drivers/iommu/arm-smmu.c132
-rw-r--r--drivers/iommu/dma-iommu.c524
-rw-r--r--drivers/iommu/dmar.c42
-rw-r--r--drivers/iommu/fsl_pamu.c2
-rw-r--r--drivers/iommu/fsl_pamu_domain.c41
-rw-r--r--drivers/iommu/intel-iommu.c401
-rw-r--r--drivers/iommu/intel-svm.c602
-rw-r--r--drivers/iommu/intel_irq_remapping.c64
-rw-r--r--drivers/iommu/io-pgtable-arm.c24
-rw-r--r--drivers/iommu/iommu.c46
-rw-r--r--drivers/iommu/irq_remapping.c12
-rw-r--r--drivers/iommu/omap-iommu.c58
-rw-r--r--drivers/iommu/omap-iommu.h9
-rw-r--r--drivers/iommu/s390-iommu.c356
-rw-r--r--drivers/irqchip/Kconfig6
-rw-r--r--drivers/irqchip/Makefile2
-rw-r--r--drivers/irqchip/alphascale_asm9260-icoll.h109
-rw-r--r--drivers/irqchip/exynos-combiner.c2
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c15
-rw-r--r--drivers/irqchip/irq-atmel-aic-common.c2
-rw-r--r--drivers/irqchip/irq-atmel-aic5.c62
-rw-r--r--drivers/irqchip/irq-crossbar.c62
-rw-r--r--drivers/irqchip/irq-gic-common.c24
-rw-r--r--drivers/irqchip/irq-gic-common.h9
-rw-r--r--drivers/irqchip/irq-gic-v2m.c163
-rw-r--r--drivers/irqchip/irq-gic-v3-its-pci-msi.c7
-rw-r--r--drivers/irqchip/irq-gic-v3-its-platform-msi.c21
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c83
-rw-r--r--drivers/irqchip/irq-gic-v3.c161
-rw-r--r--drivers/irqchip/irq-gic.c217
-rw-r--r--drivers/irqchip/irq-hip04.c2
-rw-r--r--drivers/irqchip/irq-i8259.c4
-rw-r--r--drivers/irqchip/irq-imx-gpcv2.c64
-rw-r--r--drivers/irqchip/irq-mips-gic.c14
-rw-r--r--drivers/irqchip/irq-mtk-sysirq.c49
-rw-r--r--drivers/irqchip/irq-mxs.c171
-rw-r--r--drivers/irqchip/irq-nvic.c18
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c6
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c86
-rw-r--r--drivers/irqchip/irq-s3c24xx.c4
-rw-r--r--drivers/irqchip/irq-sunxi-nmi.c22
-rw-r--r--drivers/irqchip/irq-tegra.c56
-rw-r--r--drivers/irqchip/irq-vf610-mscm-ir.c45
-rw-r--r--drivers/irqchip/irqchip.c5
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c10
-rw-r--r--drivers/isdn/hisax/isdnl2.c20
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c12
-rw-r--r--drivers/isdn/i4l/isdn_tty.c2
-rw-r--r--drivers/isdn/mISDN/dsp_pipeline.c12
-rw-r--r--drivers/isdn/mISDN/layer2.c54
-rw-r--r--drivers/leds/Kconfig10
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/led-class.c69
-rw-r--r--drivers/leds/led-core.c73
-rw-r--r--drivers/leds/leds-88pm860x.c1
-rw-r--r--drivers/leds/leds-bcm6328.c45
-rw-r--r--drivers/leds/leds-bcm6358.c4
-rw-r--r--drivers/leds/leds-cobalt-qube.c23
-rw-r--r--drivers/leds/leds-dac124s085.c1
-rw-r--r--drivers/leds/leds-gpio.c13
-rw-r--r--drivers/leds/leds-hp6xx.c17
-rw-r--r--drivers/leds/leds-ipaq-micro.c27
-rw-r--r--drivers/leds/leds-locomo.c15
-rw-r--r--drivers/leds/leds-menf21bmc.c26
-rw-r--r--drivers/leds/leds-net48xx.c9
-rw-r--r--drivers/leds/leds-netxbig.c336
-rw-r--r--drivers/leds/leds-ot200.c21
-rw-r--r--drivers/leds/leds-powernv.c8
-rw-r--r--drivers/leds/leds-sead3.c78
-rw-r--r--drivers/leds/leds-wrap.c28
-rw-r--r--drivers/leds/leds.h1
-rw-r--r--drivers/leds/trigger/ledtrig-heartbeat.c47
-rw-r--r--drivers/lightnvm/Kconfig42
-rw-r--r--drivers/lightnvm/Makefile7
-rw-r--r--drivers/lightnvm/core.c826
-rw-r--r--drivers/lightnvm/gennvm.c485
-rw-r--r--drivers/lightnvm/gennvm.h46
-rw-r--r--drivers/lightnvm/rrpc.c1324
-rw-r--r--drivers/lightnvm/rrpc.h239
-rw-r--r--drivers/macintosh/Kconfig5
-rw-r--r--drivers/mailbox/Kconfig14
-rw-r--r--drivers/mailbox/Makefile4
-rw-r--r--drivers/mailbox/mailbox-sti.c513
-rw-r--r--drivers/mailbox/mailbox-test.c361
-rw-r--r--drivers/mailbox/omap-mailbox.c49
-rw-r--r--drivers/mailbox/pcc.c2
-rw-r--r--drivers/mcb/mcb-core.c1
-rw-r--r--drivers/mcb/mcb-pci.c1
-rw-r--r--drivers/md/Kconfig1
-rw-r--r--drivers/md/Makefile2
-rw-r--r--drivers/md/bcache/closure.c4
-rw-r--r--drivers/md/bcache/request.c11
-rw-r--r--drivers/md/bitmap.c14
-rw-r--r--drivers/md/bitmap.h4
-rw-r--r--drivers/md/dm-bufio.c18
-rw-r--r--drivers/md/dm-cache-metadata.c10
-rw-r--r--drivers/md/dm-cache-policy-cleaner.c2
-rw-r--r--drivers/md/dm-cache-policy-mq.c2
-rw-r--r--drivers/md/dm-cache-policy-smq.c2
-rw-r--r--drivers/md/dm-cache-target.c3
-rw-r--r--drivers/md/dm-crypt.c12
-rw-r--r--drivers/md/dm-delay.c7
-rw-r--r--drivers/md/dm-era-target.c15
-rw-r--r--drivers/md/dm-exception-store.c2
-rw-r--r--drivers/md/dm-flakey.c16
-rw-r--r--drivers/md/dm-io.c3
-rw-r--r--drivers/md/dm-kcopyd.c2
-rw-r--r--drivers/md/dm-linear.c20
-rw-r--r--drivers/md/dm-log-userspace-base.c3
-rw-r--r--drivers/md/dm-log-writes.c13
-rw-r--r--drivers/md/dm-mpath.c34
-rw-r--r--drivers/md/dm-region-hash.c6
-rw-r--r--drivers/md/dm-snap-persistent.c17
-rw-r--r--drivers/md/dm-switch.c25
-rw-r--r--drivers/md/dm-table.c88
-rw-r--r--drivers/md/dm-thin-metadata.c16
-rw-r--r--drivers/md/dm-thin.c2
-rw-r--r--drivers/md/dm-verity.c15
-rw-r--r--drivers/md/dm.c217
-rw-r--r--drivers/md/md-cluster.c228
-rw-r--r--drivers/md/md-cluster.h12
-rw-r--r--drivers/md/md.c517
-rw-r--r--drivers/md/md.h17
-rw-r--r--drivers/md/multipath.c2
-rw-r--r--drivers/md/persistent-data/dm-array.c4
-rw-r--r--drivers/md/persistent-data/dm-block-manager.c4
-rw-r--r--drivers/md/persistent-data/dm-block-manager.h2
-rw-r--r--drivers/md/persistent-data/dm-btree-internal.h2
-rw-r--r--drivers/md/persistent-data/dm-btree-remove.c53
-rw-r--r--drivers/md/persistent-data/dm-btree-spine.c20
-rw-r--r--drivers/md/persistent-data/dm-btree.c6
-rw-r--r--drivers/md/persistent-data/dm-space-map-common.c32
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.c4
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.h2
-rw-r--r--drivers/md/raid1.c56
-rw-r--r--drivers/md/raid1.h7
-rw-r--r--drivers/md/raid10.c43
-rw-r--r--drivers/md/raid5-cache.c1191
-rw-r--r--drivers/md/raid5.c195
-rw-r--r--drivers/md/raid5.h24
-rw-r--r--drivers/media/dvb-core/demux.h619
-rw-r--r--drivers/media/dvb-core/dmxdev.c10
-rw-r--r--drivers/media/dvb-core/dvb-usb-ids.h1
-rw-r--r--drivers/media/dvb-core/dvb_ca_en50221.h99
-rw-r--r--drivers/media/dvb-core/dvb_demux.c11
-rw-r--r--drivers/media/dvb-core/dvb_net.c5
-rw-r--r--drivers/media/dvb-core/dvbdev.h4
-rw-r--r--drivers/media/dvb-frontends/drxd_hard.c3
-rw-r--r--drivers/media/dvb-frontends/horus3a.h4
-rw-r--r--drivers/media/dvb-frontends/lnbh25.h2
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c73
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c23
-rw-r--r--drivers/media/dvb-frontends/si2168.c4
-rw-r--r--drivers/media/i2c/ml86v7667.c11
-rw-r--r--drivers/media/i2c/ov9650.c2
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c2
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-spi.c2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c1
-rw-r--r--drivers/media/i2c/tvp5150.c14
-rw-r--r--drivers/media/media-entity.c4
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c5
-rw-r--r--drivers/media/pci/cobalt/Kconfig2
-rw-r--r--drivers/media/pci/cobalt/cobalt-cpld.c8
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.h6
-rw-r--r--drivers/media/pci/cobalt/cobalt-irq.c7
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.c24
-rw-r--r--drivers/media/pci/cx18/cx18-mailbox.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-417.c13
-rw-r--r--drivers/media/pci/cx23885/cx23885-core.c28
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c11
-rw-r--r--drivers/media/pci/cx23885/cx23885-vbi.c18
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c29
-rw-r--r--drivers/media/pci/cx23885/cx23885.h2
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c2
-rw-r--r--drivers/media/pci/cx25821/cx25821-core.c3
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c24
-rw-r--r--drivers/media/pci/cx25821/cx25821.h3
-rw-r--r--drivers/media/pci/cx88/cx88-alsa.c6
-rw-r--r--drivers/media/pci/cx88/cx88-blackbird.c15
-rw-r--r--drivers/media/pci/cx88/cx88-core.c8
-rw-r--r--drivers/media/pci/cx88/cx88-dvb.c13
-rw-r--r--drivers/media/pci/cx88/cx88-mpeg.c17
-rw-r--r--drivers/media/pci/cx88/cx88-vbi.c19
-rw-r--r--drivers/media/pci/cx88/cx88-video.c25
-rw-r--r--drivers/media/pci/cx88/cx88.h2
-rw-r--r--drivers/media/pci/dt3155/dt3155.c20
-rw-r--r--drivers/media/pci/dt3155/dt3155.h3
-rw-r--r--drivers/media/pci/ivtv/ivtv-alsa-main.c14
-rw-r--r--drivers/media/pci/ivtv/ivtv-yuv.c12
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb.h4
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_ci.c10
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_core.c37
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c2
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_spi.c16
-rw-r--r--drivers/media/pci/saa7134/saa7134-cards.c43
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c18
-rw-r--r--drivers/media/pci/saa7134/saa7134-input.c7
-rw-r--r--drivers/media/pci/saa7134/saa7134-ts.c16
-rw-r--r--drivers/media/pci/saa7134/saa7134-vbi.c12
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c23
-rw-r--r--drivers/media/pci/saa7134/saa7134.h5
-rw-r--r--drivers/media/pci/saa7164/Kconfig1
-rw-r--r--drivers/media/pci/saa7164/saa7164-core.c4
-rw-r--r--drivers/media/pci/saa7164/saa7164-encoder.c653
-rw-r--r--drivers/media/pci/saa7164/saa7164-vbi.c629
-rw-r--r--drivers/media/pci/saa7164/saa7164.h26
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c50
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2.c23
-rw-r--r--drivers/media/pci/solo6x10/solo6x10.h4
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c28
-rw-r--r--drivers/media/pci/ttpci/av7110.c9
-rw-r--r--drivers/media/pci/ttpci/av7110_av.c6
-rw-r--r--drivers/media/pci/tw68/tw68-core.c4
-rw-r--r--drivers/media/pci/tw68/tw68-video.c24
-rw-r--r--drivers/media/pci/tw68/tw68.h3
-rw-r--r--drivers/media/platform/Kconfig2
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.c43
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.h3
-rw-r--r--drivers/media/platform/blackfin/bfin_capture.c37
-rw-r--r--drivers/media/platform/coda/coda-bit.c135
-rw-r--r--drivers/media/platform/coda/coda-common.c26
-rw-r--r--drivers/media/platform/coda/coda-jpeg.c6
-rw-r--r--drivers/media/platform/coda/coda.h8
-rw-r--r--drivers/media/platform/coda/trace.h18
-rw-r--r--drivers/media/platform/davinci/vpbe_display.c34
-rw-r--r--drivers/media/platform/davinci/vpif_capture.c33
-rw-r--r--drivers/media/platform/davinci/vpif_capture.h2
-rw-r--r--drivers/media/platform/davinci/vpif_display.c42
-rw-r--r--drivers/media/platform/davinci/vpif_display.h2
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.h4
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-m2m.c25
-rw-r--r--drivers/media/platform/exynos4-is/fimc-capture.c33
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.h4
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is.h2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp-video.c18
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp-video.h2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp.h4
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.c25
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.h4
-rw-r--r--drivers/media/platform/exynos4-is/fimc-m2m.c23
-rw-r--r--drivers/media/platform/exynos4-is/mipi-csis.c3
-rw-r--r--drivers/media/platform/m2m-deinterlace.c25
-rw-r--r--drivers/media/platform/marvell-ccic/mcam-core.c46
-rw-r--r--drivers/media/platform/marvell-ccic/mcam-core.h2
-rw-r--r--drivers/media/platform/mx2_emmaprp.c17
-rw-r--r--drivers/media/platform/omap3isp/ispstat.c5
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h2
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c27
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.h4
-rw-r--r--drivers/media/platform/rcar_jpu.c68
-rw-r--r--drivers/media/platform/s3c-camif/camif-capture.c26
-rw-r--r--drivers/media/platform/s3c-camif/camif-core.c2
-rw-r--r--drivers/media/platform/s3c-camif/camif-core.h4
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.c19
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.c475
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.h41
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c80
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h11
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-regs.h85
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c106
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_common.h4
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c40
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_enc.c75
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c46
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c68
-rw-r--r--drivers/media/platform/s5p-tv/mixer.h4
-rw-r--r--drivers/media/platform/s5p-tv/mixer_grp_layer.c2
-rw-r--r--drivers/media/platform/s5p-tv/mixer_reg.c2
-rw-r--r--drivers/media/platform/s5p-tv/mixer_video.c13
-rw-r--r--drivers/media/platform/s5p-tv/mixer_vp_layer.c5
-rw-r--r--drivers/media/platform/sh_veu.c22
-rw-r--r--drivers/media/platform/sh_vou.c29
-rw-r--r--drivers/media/platform/soc_camera/atmel-isi.c153
-rw-r--r--drivers/media/platform/soc_camera/atmel-isi.h128
-rw-r--r--drivers/media/platform/soc_camera/mx2_camera.c24
-rw-r--r--drivers/media/platform/soc_camera/mx3_camera.c30
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c64
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c63
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c4
-rw-r--r--drivers/media/platform/sti/bdisp/bdisp-v4l2.c26
-rw-r--r--drivers/media/platform/sti/c8sectpfe/Kconfig1
-rw-r--r--drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c11
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c44
-rw-r--r--drivers/media/platform/vim2m.c57
-rw-r--r--drivers/media/platform/vivid/Kconfig8
-rw-r--r--drivers/media/platform/vivid/vivid-core.c7
-rw-r--r--drivers/media/platform/vivid/vivid-core.h6
-rw-r--r--drivers/media/platform/vivid/vivid-ctrls.c55
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-cap.c73
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-out.c34
-rw-r--r--drivers/media/platform/vivid/vivid-osd.c1
-rw-r--r--drivers/media/platform/vivid/vivid-sdr-cap.c83
-rw-r--r--drivers/media/platform/vivid/vivid-tpg-colors.c328
-rw-r--r--drivers/media/platform/vivid/vivid-tpg-colors.h4
-rw-r--r--drivers/media/platform/vivid/vivid-tpg.c91
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-cap.c40
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-out.c20
-rw-r--r--drivers/media/platform/vivid/vivid-vid-cap.c18
-rw-r--r--drivers/media/platform/vivid/vivid-vid-common.c56
-rw-r--r--drivers/media/platform/vivid/vivid-vid-out.c18
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c4
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c23
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.h8
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c4
-rw-r--r--drivers/media/platform/xilinx/xilinx-dma.c29
-rw-r--r--drivers/media/platform/xilinx/xilinx-dma.h2
-rw-r--r--drivers/media/rc/ir-hix5hd2.c2
-rw-r--r--drivers/media/tuners/msi001.c1
-rw-r--r--drivers/media/tuners/si2157.c4
-rw-r--r--drivers/media/usb/airspy/airspy.c26
-rw-r--r--drivers/media/usb/au0828/au0828-vbi.c10
-rw-r--r--drivers/media/usb/au0828/au0828-video.c48
-rw-r--r--drivers/media/usb/au0828/au0828.h3
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-video.c3
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvbsky.c4
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.c17
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.h2
-rw-r--r--drivers/media/usb/em28xx/em28xx-vbi.c10
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c37
-rw-r--r--drivers/media/usb/em28xx/em28xx.h3
-rw-r--r--drivers/media/usb/go7007/go7007-driver.c29
-rw-r--r--drivers/media/usb/go7007/go7007-fw.c6
-rw-r--r--drivers/media/usb/go7007/go7007-priv.h4
-rw-r--r--drivers/media/usb/go7007/go7007-v4l2.c22
-rw-r--r--drivers/media/usb/gspca/gspca.c4
-rw-r--r--drivers/media/usb/hackrf/hackrf.c1086
-rw-r--r--drivers/media/usb/msi2500/msi2500.c19
-rw-r--r--drivers/media/usb/pwc/pwc-if.c35
-rw-r--r--drivers/media/usb/pwc/pwc-uncompress.c6
-rw-r--r--drivers/media/usb/pwc/pwc.h4
-rw-r--r--drivers/media/usb/s2255/s2255drv.c29
-rw-r--r--drivers/media/usb/stk1160/stk1160-v4l.c17
-rw-r--r--drivers/media/usb/stk1160/stk1160-video.c12
-rw-r--r--drivers/media/usb/stk1160/stk1160.h4
-rw-r--r--drivers/media/usb/tm6000/tm6000-alsa.c2
-rw-r--r--drivers/media/usb/ttusb-dec/ttusb_dec.c12
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c24
-rw-r--r--drivers/media/usb/usbtv/usbtv.h3
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c3
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c29
-rw-r--r--drivers/media/usb/uvc/uvc_video.c23
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h7
-rw-r--r--drivers/media/v4l2-core/Kconfig2
-rw-r--r--drivers/media/v4l2-core/Makefile4
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c51
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c14
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c14
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c51
-rw-r--r--drivers/media/v4l2-core/v4l2-mem2mem.c33
-rw-r--r--drivers/media/v4l2-core/v4l2-trace.c10
-rw-r--r--drivers/media/v4l2-core/vb2-trace.c9
-rw-r--r--drivers/media/v4l2-core/videobuf-core.c4
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c2014
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-contig.c7
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-sg.c7
-rw-r--r--drivers/media/v4l2-core/videobuf2-internal.h161
-rw-r--r--drivers/media/v4l2-core/videobuf2-memops.c2
-rw-r--r--drivers/media/v4l2-core/videobuf2-v4l2.c1661
-rw-r--r--drivers/media/v4l2-core/videobuf2-vmalloc.c2
-rw-r--r--drivers/memory/Kconfig12
-rw-r--r--drivers/memory/fsl-corenet-cf.c1
-rw-r--r--drivers/memory/omap-gpmc.c2
-rw-r--r--drivers/memory/pl172.c26
-rw-r--r--drivers/memory/ti-aemif.c1
-rw-r--r--drivers/message/fusion/mptctl.c4
-rw-r--r--drivers/message/fusion/mptsas.c1
-rw-r--r--drivers/mfd/88pm80x.c2
-rw-r--r--drivers/mfd/Kconfig21
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/arizona-core.c300
-rw-r--r--drivers/mfd/arizona-i2c.c33
-rw-r--r--drivers/mfd/arizona-irq.c2
-rw-r--r--drivers/mfd/arizona-spi.c24
-rw-r--r--drivers/mfd/atmel-flexcom.c104
-rw-r--r--drivers/mfd/atmel-hlcdc.c1
-rw-r--r--drivers/mfd/axp20x.c20
-rw-r--r--drivers/mfd/bcm590xx.c1
-rw-r--r--drivers/mfd/cros_ec_i2c.c7
-rw-r--r--drivers/mfd/cros_ec_spi.c1
-rw-r--r--drivers/mfd/da903x.c6
-rw-r--r--drivers/mfd/da9052-core.c6
-rw-r--r--drivers/mfd/da9052-i2c.c6
-rw-r--r--drivers/mfd/da9052-spi.c7
-rw-r--r--drivers/mfd/da9062-core.c4
-rw-r--r--drivers/mfd/da9150-core.c191
-rw-r--r--drivers/mfd/ezx-pcap.c1
-rw-r--r--drivers/mfd/hi6421-pmic-core.c1
-rw-r--r--drivers/mfd/htc-i2cpld.c3
-rw-r--r--drivers/mfd/intel-lpss-acpi.c16
-rw-r--r--drivers/mfd/intel-lpss-pci.c45
-rw-r--r--drivers/mfd/intel-lpss.c11
-rw-r--r--drivers/mfd/intel-lpss.h2
-rw-r--r--drivers/mfd/intel_quark_i2c_gpio.c33
-rw-r--r--drivers/mfd/intel_soc_pmic_bxtwc.c477
-rw-r--r--drivers/mfd/kempld-core.c14
-rw-r--r--drivers/mfd/lm3533-core.c13
-rw-r--r--drivers/mfd/lpc_ich.c42
-rw-r--r--drivers/mfd/max77843.c2
-rw-r--r--drivers/mfd/max8997.c1
-rw-r--r--drivers/mfd/mc13xxx-spi.c1
-rw-r--r--drivers/mfd/mfd-core.c52
-rw-r--r--drivers/mfd/pcf50633-irq.c4
-rw-r--r--drivers/mfd/qcom_rpm.c2
-rw-r--r--drivers/mfd/rt5033.c4
-rw-r--r--drivers/mfd/rts5209.c6
-rw-r--r--drivers/mfd/rts5227.c83
-rw-r--r--drivers/mfd/rts5229.c6
-rw-r--r--drivers/mfd/rts5249.c6
-rw-r--r--drivers/mfd/rtsx_pcr.c13
-rw-r--r--drivers/mfd/rtsx_pcr.h3
-rw-r--r--drivers/mfd/sec-core.c73
-rw-r--r--drivers/mfd/sm501.c1
-rw-r--r--drivers/mfd/stmpe-spi.c1
-rw-r--r--drivers/mfd/stmpe.c1
-rw-r--r--drivers/mfd/tps6105x.c150
-rw-r--r--drivers/mfd/tps65217.c4
-rw-r--r--drivers/mfd/tps65912-spi.c1
-rw-r--r--drivers/mfd/twl6040.c2
-rw-r--r--drivers/mfd/wm5110-tables.c194
-rw-r--r--drivers/mfd/wm831x-core.c4
-rw-r--r--drivers/mfd/wm831x-spi.c1
-rw-r--r--drivers/mfd/wm8998-tables.c10
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c1
-rw-r--r--drivers/misc/ad525x_dpot-spi.c1
-rw-r--r--drivers/misc/atmel_tclib.c4
-rw-r--r--drivers/misc/bmp085-spi.c1
-rw-r--r--drivers/misc/c2port/core.c2
-rw-r--r--drivers/misc/cxl/api.c1
-rw-r--r--drivers/misc/cxl/context.c3
-rw-r--r--drivers/misc/cxl/cxl.h1
-rw-r--r--drivers/misc/cxl/file.c13
-rw-r--r--drivers/misc/cxl/irq.c4
-rw-r--r--drivers/misc/cxl/native.c2
-rw-r--r--drivers/misc/cxl/pci.c28
-rw-r--r--drivers/misc/cxl/vphb.c2
-rw-r--r--drivers/misc/eeprom/at24.c22
-rw-r--r--drivers/misc/eeprom/at25.c1
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c1
-rw-r--r--drivers/misc/genwqe/card_base.h2
-rw-r--r--drivers/misc/genwqe/card_ddcb.c2
-rw-r--r--drivers/misc/genwqe/card_dev.c4
-rw-r--r--drivers/misc/genwqe/card_utils.c5
-rw-r--r--drivers/misc/hpilo.c6
-rw-r--r--drivers/misc/kgdbts.c10
-rw-r--r--drivers/misc/lattice-ecp3-config.c1
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_spi.c1
-rw-r--r--drivers/misc/lkdtm.c8
-rw-r--r--drivers/misc/mei/amthif.c2
-rw-r--r--drivers/misc/mei/bus-fixup.c4
-rw-r--r--drivers/misc/mei/bus.c218
-rw-r--r--drivers/misc/mei/client.h12
-rw-r--r--drivers/misc/mei/debugfs.c2
-rw-r--r--drivers/misc/mei/hbm.c6
-rw-r--r--drivers/misc/mei/hw-me.c4
-rw-r--r--drivers/misc/mei/init.c4
-rw-r--r--drivers/misc/mei/interrupt.c4
-rw-r--r--drivers/misc/mei/mei_dev.h21
-rw-r--r--drivers/misc/mic/Kconfig25
-rw-r--r--drivers/misc/mic/Makefile2
-rw-r--r--drivers/misc/mic/bus/Makefile1
-rw-r--r--drivers/misc/mic/bus/cosm_bus.c141
-rw-r--r--drivers/misc/mic/bus/cosm_bus.h134
-rw-r--r--drivers/misc/mic/bus/mic_bus.c24
-rw-r--r--drivers/misc/mic/bus/scif_bus.c9
-rw-r--r--drivers/misc/mic/bus/scif_bus.h6
-rw-r--r--drivers/misc/mic/card/mic_device.c88
-rw-r--r--drivers/misc/mic/card/mic_x100.c2
-rw-r--r--drivers/misc/mic/common/mic_dev.h13
-rw-r--r--drivers/misc/mic/cosm/Makefile10
-rw-r--r--drivers/misc/mic/cosm/cosm_debugfs.c156
-rw-r--r--drivers/misc/mic/cosm/cosm_main.c388
-rw-r--r--drivers/misc/mic/cosm/cosm_main.h70
-rw-r--r--drivers/misc/mic/cosm/cosm_scif_server.c405
-rw-r--r--drivers/misc/mic/cosm/cosm_sysfs.c461
-rw-r--r--drivers/misc/mic/cosm_client/Makefile7
-rw-r--r--drivers/misc/mic/cosm_client/cosm_scif_client.c275
-rw-r--r--drivers/misc/mic/host/Makefile1
-rw-r--r--drivers/misc/mic/host/mic_boot.c317
-rw-r--r--drivers/misc/mic/host/mic_debugfs.c114
-rw-r--r--drivers/misc/mic/host/mic_device.h88
-rw-r--r--drivers/misc/mic/host/mic_fops.c4
-rw-r--r--drivers/misc/mic/host/mic_intr.c46
-rw-r--r--drivers/misc/mic/host/mic_main.c223
-rw-r--r--drivers/misc/mic/host/mic_smpt.c30
-rw-r--r--drivers/misc/mic/host/mic_sysfs.c459
-rw-r--r--drivers/misc/mic/host/mic_virtio.c17
-rw-r--r--drivers/misc/mic/host/mic_virtio.h2
-rw-r--r--drivers/misc/mic/host/mic_x100.c46
-rw-r--r--drivers/misc/mic/scif/Makefile5
-rw-r--r--drivers/misc/mic/scif/scif_api.c234
-rw-r--r--drivers/misc/mic/scif/scif_debugfs.c85
-rw-r--r--drivers/misc/mic/scif/scif_dma.c1979
-rw-r--r--drivers/misc/mic/scif/scif_epd.c26
-rw-r--r--drivers/misc/mic/scif/scif_epd.h50
-rw-r--r--drivers/misc/mic/scif/scif_fd.c178
-rw-r--r--drivers/misc/mic/scif/scif_fence.c771
-rw-r--r--drivers/misc/mic/scif/scif_main.c111
-rw-r--r--drivers/misc/mic/scif/scif_main.h37
-rw-r--r--drivers/misc/mic/scif/scif_map.h25
-rw-r--r--drivers/misc/mic/scif/scif_mmap.c699
-rw-r--r--drivers/misc/mic/scif/scif_nm.c20
-rw-r--r--drivers/misc/mic/scif/scif_nodeqp.c149
-rw-r--r--drivers/misc/mic/scif/scif_nodeqp.h42
-rw-r--r--drivers/misc/mic/scif/scif_peer_bus.c179
-rw-r--r--drivers/misc/mic/scif/scif_peer_bus.h42
-rw-r--r--drivers/misc/mic/scif/scif_rma.c1775
-rw-r--r--drivers/misc/mic/scif/scif_rma.h464
-rw-r--r--drivers/misc/mic/scif/scif_rma_list.c291
-rw-r--r--drivers/misc/mic/scif/scif_rma_list.h57
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c6
-rw-r--r--drivers/misc/sgi-gru/gruhandles.h1
-rw-r--r--drivers/misc/sgi-gru/grukdump.c16
-rw-r--r--drivers/misc/sgi-gru/grukservices.c15
-rw-r--r--drivers/misc/sgi-gru/grumain.c4
-rw-r--r--drivers/misc/sgi-gru/grutlbpurge.c25
-rw-r--r--drivers/misc/spear13xx_pcie_gadget.c216
-rw-r--r--drivers/misc/sram.c196
-rw-r--r--drivers/misc/ti-st/st_core.c18
-rw-r--r--drivers/misc/ti_dac7512.c1
-rw-r--r--drivers/misc/vmw_balloon.c845
-rw-r--r--drivers/misc/vmw_vmci/vmci_datagram.c3
-rw-r--r--drivers/mmc/card/block.c210
-rw-r--r--drivers/mmc/card/mmc_test.c9
-rw-r--r--drivers/mmc/core/Kconfig10
-rw-r--r--drivers/mmc/core/core.c291
-rw-r--r--drivers/mmc/core/core.h3
-rw-r--r--drivers/mmc/core/debugfs.c30
-rw-r--r--drivers/mmc/core/host.c247
-rw-r--r--drivers/mmc/core/mmc.c105
-rw-r--r--drivers/mmc/core/mmc_ops.c9
-rw-r--r--drivers/mmc/core/mmc_ops.h3
-rw-r--r--drivers/mmc/core/pwrseq_emmc.c8
-rw-r--r--drivers/mmc/core/pwrseq_simple.c45
-rw-r--r--drivers/mmc/core/quirks.c18
-rw-r--r--drivers/mmc/core/sd.c27
-rw-r--r--drivers/mmc/core/sdio.c27
-rw-r--r--drivers/mmc/core/sdio_irq.c14
-rw-r--r--drivers/mmc/core/sdio_ops.h7
-rw-r--r--drivers/mmc/host/Kconfig22
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c4
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c2
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c162
-rw-r--r--drivers/mmc/host/dw_mmc.c290
-rw-r--r--drivers/mmc/host/dw_mmc.h13
-rw-r--r--drivers/mmc/host/mmc_spi.c2
-rw-r--r--drivers/mmc/host/moxart-mmc.c1
-rw-r--r--drivers/mmc/host/mtk-sd.c306
-rw-r--r--drivers/mmc/host/omap.c1
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/sdhci-acpi.c11
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c6
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h2
-rw-r--r--drivers/mmc/host/sdhci-msm.c2
-rw-r--r--drivers/mmc/host/sdhci-of-at91.c1
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c463
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c (renamed from drivers/mmc/host/sdhci-pci.c)62
-rw-r--r--drivers/mmc/host/sdhci-pci-o2micro.c6
-rw-r--r--drivers/mmc/host/sdhci-pci-o2micro.h2
-rw-r--r--drivers/mmc/host/sdhci-pci.h7
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c6
-rw-r--r--drivers/mmc/host/sdhci-sirf.c5
-rw-r--r--drivers/mmc/host/sdhci.c29
-rw-r--r--drivers/mmc/host/sunxi-mmc.c8
-rw-r--r--drivers/mmc/host/vub300.c6
-rw-r--r--drivers/mmc/host/wbsd.c2
-rw-r--r--drivers/mtd/cmdlinepart.c28
-rw-r--r--drivers/mtd/devices/bcm47xxsflash.c7
-rw-r--r--drivers/mtd/devices/docg3.c24
-rw-r--r--drivers/mtd/devices/m25p80.c16
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/devices/mtdram.c21
-rw-r--r--drivers/mtd/devices/spear_smi.c1
-rw-r--r--drivers/mtd/devices/sst25l.c4
-rw-r--r--drivers/mtd/lpddr/lpddr2_nvm.c1
-rw-r--r--drivers/mtd/maps/gpio-addr-flash.c2
-rw-r--r--drivers/mtd/maps/intel_vr_nor.c2
-rw-r--r--drivers/mtd/maps/ixp4xx.c2
-rw-r--r--drivers/mtd/maps/lantiq-flash.c2
-rw-r--r--drivers/mtd/maps/latch-addr-flash.c2
-rw-r--r--drivers/mtd/maps/pcmciamtd.c1
-rw-r--r--drivers/mtd/maps/physmap.c1
-rw-r--r--drivers/mtd/maps/physmap_of.c1
-rw-r--r--drivers/mtd/maps/plat-ram.c1
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c8
-rw-r--r--drivers/mtd/maps/rbtx4939-flash.c2
-rw-r--r--drivers/mtd/maps/sa1100-flash.c2
-rw-r--r--drivers/mtd/mtd_blkdevs.c12
-rw-r--r--drivers/mtd/mtdchar.c42
-rw-r--r--drivers/mtd/mtdcore.c38
-rw-r--r--drivers/mtd/mtdpart.c23
-rw-r--r--drivers/mtd/nand/Kconfig13
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/atmel_nand.c8
-rw-r--r--drivers/mtd/nand/au1550nd.c2
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/main.c2
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c5
-rw-r--r--drivers/mtd/nand/brcmnand/bcm63138_nand.c18
-rw-r--r--drivers/mtd/nand/brcmnand/brcmnand.c61
-rw-r--r--drivers/mtd/nand/brcmnand/brcmnand.h2
-rw-r--r--drivers/mtd/nand/brcmnand/iproc_nand.c22
-rw-r--r--drivers/mtd/nand/cafe_nand.c4
-rw-r--r--drivers/mtd/nand/davinci_nand.c3
-rw-r--r--drivers/mtd/nand/denali.c19
-rw-r--r--drivers/mtd/nand/denali.h2
-rw-r--r--drivers/mtd/nand/docg4.c8
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c7
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c5
-rw-r--r--drivers/mtd/nand/fsl_upm.c2
-rw-r--r--drivers/mtd/nand/fsmc_nand.c67
-rw-r--r--drivers/mtd/nand/gpio.c2
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c10
-rw-r--r--drivers/mtd/nand/hisi504_nand.c4
-rw-r--r--drivers/mtd/nand/jz4740_nand.c3
-rw-r--r--drivers/mtd/nand/lpc32xx_mlc.c14
-rw-r--r--drivers/mtd/nand/lpc32xx_slc.c42
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c2
-rw-r--r--drivers/mtd/nand/mxc_nand.c2
-rw-r--r--drivers/mtd/nand/nand_base.c203
-rw-r--r--drivers/mtd/nand/nand_bbt.c2
-rw-r--r--drivers/mtd/nand/nandsim.c3
-rw-r--r--drivers/mtd/nand/ndfc.c2
-rw-r--r--drivers/mtd/nand/nuc900_nand.c2
-rw-r--r--drivers/mtd/nand/omap2.c6
-rw-r--r--drivers/mtd/nand/orion_nand.c3
-rw-r--r--drivers/mtd/nand/pasemi_nand.c2
-rw-r--r--drivers/mtd/nand/plat_nand.c3
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c570
-rw-r--r--drivers/mtd/nand/r852.c1
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/nand/sh_flctl.c4
-rw-r--r--drivers/mtd/nand/sharpsl.c2
-rw-r--r--drivers/mtd/nand/socrates_nand.c1
-rw-r--r--drivers/mtd/nand/sunxi_nand.c540
-rw-r--r--drivers/mtd/nand/tmio_nand.c1
-rw-r--r--drivers/mtd/nand/txx9ndfmc.c2
-rw-r--r--drivers/mtd/nand/vf610_nfc.c878
-rw-r--r--drivers/mtd/ofpart.c63
-rw-r--r--drivers/mtd/onenand/generic.c3
-rw-r--r--drivers/mtd/onenand/omap2.c2
-rw-r--r--drivers/mtd/onenand/samsung.c1
-rw-r--r--drivers/mtd/spi-nor/Kconfig3
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c46
-rw-r--r--drivers/mtd/spi-nor/nxp-spifi.c11
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c319
-rw-r--r--drivers/mtd/tests/speedtest.c10
-rw-r--r--drivers/mtd/tests/torturetest.c10
-rw-r--r--drivers/mtd/ubi/attach.c4
-rw-r--r--drivers/mtd/ubi/cdev.c2
-rw-r--r--drivers/mtd/ubi/eba.c2
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c29
-rw-r--r--drivers/mtd/ubi/fastmap.c4
-rw-r--r--drivers/mtd/ubi/gluebi.c4
-rw-r--r--drivers/mtd/ubi/ubi-media.h2
-rw-r--r--drivers/net/Kconfig5
-rw-r--r--drivers/net/arcnet/Kconfig1
-rw-r--r--drivers/net/arcnet/arc-rawmode.c142
-rw-r--r--drivers/net/arcnet/arc-rimi.c145
-rw-r--r--drivers/net/arcnet/arcdevice.h389
-rw-r--r--drivers/net/arcnet/arcnet.c700
-rw-r--r--drivers/net/arcnet/capmode.c138
-rw-r--r--drivers/net/arcnet/com20020-isa.c54
-rw-r--r--drivers/net/arcnet/com20020-pci.c175
-rw-r--r--drivers/net/arcnet/com20020.c263
-rw-r--r--drivers/net/arcnet/com20020.h132
-rw-r--r--drivers/net/arcnet/com20020_cs.c325
-rw-r--r--drivers/net/arcnet/com9026.h17
-rw-r--r--drivers/net/arcnet/com90io.c209
-rw-r--r--drivers/net/arcnet/com90xx.c323
-rw-r--r--drivers/net/arcnet/rfc1051.c77
-rw-r--r--drivers/net/arcnet/rfc1201.c238
-rw-r--r--drivers/net/bonding/bond_3ad.c113
-rw-r--r--drivers/net/bonding/bond_main.c21
-rw-r--r--drivers/net/caif/caif_spi.c7
-rw-r--r--drivers/net/can/Kconfig10
-rw-r--r--drivers/net/can/Makefile1
-rw-r--r--drivers/net/can/at91_can.c21
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/can/flexcan.c197
-rw-r--r--drivers/net/can/sja1000/peak_pci.c1
-rw-r--r--drivers/net/can/spi/mcp251x.c1
-rw-r--r--drivers/net/can/sun4i_can.c857
-rw-r--r--drivers/net/dsa/bcm_sf2.c338
-rw-r--r--drivers/net/dsa/bcm_sf2.h62
-rw-r--r--drivers/net/dsa/bcm_sf2_regs.h43
-rw-r--r--drivers/net/dsa/mv88e6060.c118
-rw-r--r--drivers/net/dsa/mv88e6060.h111
-rw-r--r--drivers/net/dsa/mv88e6123_61_65.c46
-rw-r--r--drivers/net/dsa/mv88e6131.c34
-rw-r--r--drivers/net/dsa/mv88e6171.c38
-rw-r--r--drivers/net/dsa/mv88e6352.c59
-rw-r--r--drivers/net/dsa/mv88e6xxx.c1087
-rw-r--r--drivers/net/dsa/mv88e6xxx.h64
-rw-r--r--drivers/net/dummy.c6
-rw-r--r--drivers/net/ethernet/8390/Kconfig2
-rw-r--r--drivers/net/ethernet/8390/mac8390.c32
-rw-r--r--drivers/net/ethernet/Kconfig1
-rw-r--r--drivers/net/ethernet/Makefile1
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c2
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c20
-rw-r--r--drivers/net/ethernet/amd/7990.c1
-rw-r--r--drivers/net/ethernet/amd/Kconfig2
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c1
-rw-r--r--drivers/net/ethernet/amd/pcnet32.c5
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c4
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dev.c85
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c18
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c107
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-main.c10
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-mdio.c16
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe.h18
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.c58
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.h2
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c66
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h7
-rw-r--r--drivers/net/ethernet/apple/Kconfig2
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c4
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c4
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c1
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c4
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig20
-rw-r--r--drivers/net/ethernet/broadcom/Makefile1
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c35
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c81
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c11
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/Makefile3
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c5742
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h1092
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c1149
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h17
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h104
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h4046
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h59
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c830
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h23
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c186
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h10
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c18
-rw-r--r--drivers/net/ethernet/cavium/Kconfig2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_ethtool.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c2
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_main.c42
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_reg.h4
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c12
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h49
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c21
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c206
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c61
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c36
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h85
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c1470
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.h5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h48
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h28
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c122
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.c4
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.h2
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c1
-rw-r--r--drivers/net/ethernet/dlink/Kconfig5
-rw-r--r--drivers/net/ethernet/dlink/dl2k.c55
-rw-r--r--drivers/net/ethernet/dlink/dl2k.h15
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h1
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c31
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h10
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c22
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c30
-rw-r--r--drivers/net/ethernet/ethoc.c14
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c5
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c6
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c34
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c165
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h12
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c49
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth_ethtool.c2
-rw-r--r--drivers/net/ethernet/hisilicon/Kconfig36
-rw-r--r--drivers/net/ethernet/hisilicon/Makefile4
-rw-r--r--drivers/net/ethernet/hisilicon/hip04_mdio.c185
-rw-r--r--drivers/net/ethernet/hisilicon/hix5hd2_gmac.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/Makefile12
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hnae.c457
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hnae.h585
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c783
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c704
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h45
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c902
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h456
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c2474
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h428
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c310
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h43
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c583
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h105
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c1021
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h139
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h972
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c837
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h15
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c1642
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.h84
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ethtool.c1214
-rw-r--r--drivers/net/ethernet/hisilicon/hns_mdio.c521
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c1
-rw-r--r--drivers/net/ethernet/ibm/emac/core.h2
-rw-r--r--drivers/net/ethernet/icplus/Kconfig13
-rw-r--r--drivers/net/ethernet/icplus/Makefile5
-rw-r--r--drivers/net/ethernet/icplus/ipg.c2300
-rw-r--r--drivers/net/ethernet/icplus/ipg.h748
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.c8
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c3
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k.h19
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c11
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c220
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_iov.c8
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_main.c50
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_mbx.c48
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_netdev.c39
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pci.c198
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pf.c105
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_type.h7
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_vf.c14
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h70
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.c83
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.h9
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h27
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c119
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb.c292
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb.h39
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c9
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c168
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_devids.h55
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c412
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_fcoe.c13
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c1162
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c430
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_osdep.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_prototype.h9
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c7
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c426
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.h57
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_type.h124
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c91
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h5
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.c61
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.h9
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h4
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_common.c41
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_devids.h55
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_osdep.h2
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_prototype.h6
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.c293
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.h41
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_type.h116
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h2
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf.h12
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c195
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c64
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c35
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c8
-rw-r--r--drivers/net/ethernet/intel/igbvf/ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c3
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h13
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c202
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c226
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c8
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c136
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c291
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h35
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c96
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h13
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c102
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c503
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h6
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c23
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c41
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h1
-rw-r--r--drivers/net/ethernet/marvell/Kconfig1
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c96
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c435
-rw-r--r--drivers/net/ethernet/marvell/sky2.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c167
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_resources.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mr.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c73
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c194
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cq.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c74
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tx.c102
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c224
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c573
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mr.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c78
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/port.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/qp.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/srq.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/transobj.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/Kconfig11
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/Makefile3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/cmd.h51
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/item.h54
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c71
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h1263
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c1949
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h122
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c422
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c903
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/switchx2.c43
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/txheader.h1
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c1
-rw-r--r--drivers/net/ethernet/microchip/Kconfig9
-rw-r--r--drivers/net/ethernet/microchip/Makefile1
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c1
-rw-r--r--drivers/net/ethernet/microchip/encx24j600-regmap.c513
-rw-r--r--drivers/net/ethernet/microchip/encx24j600.c1129
-rw-r--r--drivers/net/ethernet/microchip/encx24j600_hw.h437
-rw-r--r--drivers/net/ethernet/neterion/s2io.c2
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-ethtool.c4
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c24
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c13
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c4
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c1
-rw-r--r--drivers/net/ethernet/qlogic/Kconfig12
-rw-r--r--drivers/net/ethernet/qlogic/Makefile2
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/Makefile4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed.h496
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_cxt.c847
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_cxt.h139
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev.c1803
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev_api.h283
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hsi.h5291
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hw.c776
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hw.h263
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c798
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_init_ops.c531
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_init_ops.h110
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_int.c1129
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_int.h391
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c1704
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c1169
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c860
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.h369
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_reg_addr.h366
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sp.h360
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sp_commands.c170
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_spq.c860
-rw-r--r--drivers/net/ethernet/qlogic/qede/Makefile3
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede.h285
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_ethtool.c385
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c2584
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c7
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.c1
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c24
-rw-r--r--drivers/net/ethernet/realtek/8139too.c1
-rw-r--r--drivers/net/ethernet/realtek/r8169.c6
-rw-r--r--drivers/net/ethernet/renesas/ravb.h7
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c113
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c118
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h2
-rw-r--r--drivers/net/ethernet/rocker/rocker.c469
-rw-r--r--drivers/net/ethernet/sfc/ef10.c34
-rw-r--r--drivers/net/ethernet/sfc/efx.c14
-rw-r--r--drivers/net/ethernet/sfc/farch.c4
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c15
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h132
-rw-r--r--drivers/net/ethernet/sfc/ptp.c30
-rw-r--r--drivers/net/ethernet/sfc/tx.c30
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c29
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h99
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c18
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c10
-rw-r--r--drivers/net/ethernet/sun/cassini.c3
-rw-r--r--drivers/net/ethernet/synopsys/dwc_eth_qos.c3
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c5
-rw-r--r--drivers/net/ethernet/ti/cpmac.c1
-rw-r--r--drivers/net/ethernet/ti/cpsw-common.c64
-rw-r--r--drivers/net/ethernet/ti/cpsw-phy-sel.c10
-rw-r--r--drivers/net/ethernet/ti/cpsw.c61
-rw-r--r--drivers/net/ethernet/ti/cpsw.h3
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c52
-rw-r--r--drivers/net/ethernet/ti/netcp_core.c4
-rw-r--r--drivers/net/ethernet/ti/netcp_ethss.c8
-rw-r--r--drivers/net/ethernet/ti/tlan.c1
-rw-r--r--drivers/net/ethernet/via/via-rhine.c3
-rw-r--r--drivers/net/ethernet/via/via-velocity.c24
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_mdio.c9
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c1
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c5
-rw-r--r--drivers/net/fjes/fjes_ethtool.c2
-rw-r--r--drivers/net/fjes/fjes_hw.c6
-rw-r--r--drivers/net/geneve.c543
-rw-r--r--drivers/net/ieee802154/Kconfig8
-rw-r--r--drivers/net/ieee802154/at86rf230.c370
-rw-r--r--drivers/net/ieee802154/at86rf230.h8
-rw-r--r--drivers/net/ieee802154/atusb.c13
-rw-r--r--drivers/net/ieee802154/cc2520.c1
-rw-r--r--drivers/net/ieee802154/mrf24j40.c1425
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c28
-rw-r--r--drivers/net/irda/pxaficp_ir.c370
-rw-r--r--drivers/net/macvlan.c4
-rw-r--r--drivers/net/macvtap.c7
-rw-r--r--drivers/net/netconsole.c271
-rw-r--r--drivers/net/phy/Kconfig35
-rw-r--r--drivers/net/phy/Makefile4
-rw-r--r--drivers/net/phy/aquantia.c15
-rw-r--r--drivers/net/phy/at803x.c4
-rw-r--r--drivers/net/phy/bcm-cygnus.c158
-rw-r--r--drivers/net/phy/bcm-phy-lib.c213
-rw-r--r--drivers/net/phy/bcm-phy-lib.h37
-rw-r--r--drivers/net/phy/bcm63xx.c38
-rw-r--r--drivers/net/phy/bcm7xxx.c136
-rw-r--r--drivers/net/phy/broadcom.c149
-rw-r--r--drivers/net/phy/dp83640.c64
-rw-r--r--drivers/net/phy/dp83848.c99
-rw-r--r--drivers/net/phy/marvell.c16
-rw-r--r--drivers/net/phy/mdio-bcm-iproc.c213
-rw-r--r--drivers/net/phy/mdio-gpio.c2
-rw-r--r--drivers/net/phy/mdio-mux-mmioreg.c2
-rw-r--r--drivers/net/phy/mdio-mux.c1
-rw-r--r--drivers/net/phy/mdio_bus.c55
-rw-r--r--drivers/net/phy/micrel.c23
-rw-r--r--drivers/net/phy/phy.c3
-rw-r--r--drivers/net/phy/phy_device.c133
-rw-r--r--drivers/net/phy/smsc.c19
-rw-r--r--drivers/net/phy/spi_ks8995.c1
-rw-r--r--drivers/net/phy/teranetics.c15
-rw-r--r--drivers/net/phy/vitesse.c16
-rw-r--r--drivers/net/ppp/ppp_generic.c6
-rw-r--r--drivers/net/ppp/pppoe.c3
-rw-r--r--drivers/net/ppp/pptp.c7
-rw-r--r--drivers/net/slip/slhc.c12
-rw-r--r--drivers/net/slip/slip.c2
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/usb/Kconfig5
-rw-r--r--drivers/net/usb/asix.h2
-rw-r--r--drivers/net/usb/asix_common.c115
-rw-r--r--drivers/net/usb/asix_devices.c4
-rw-r--r--drivers/net/usb/cdc-phonet.c27
-rw-r--r--drivers/net/usb/cdc_ether.c235
-rw-r--r--drivers/net/usb/cdc_mbim.c2
-rw-r--r--drivers/net/usb/cdc_ncm.c69
-rw-r--r--drivers/net/usb/dm9601.c1
-rw-r--r--drivers/net/usb/kaweth.c6
-rw-r--r--drivers/net/usb/lan78xx.c672
-rw-r--r--drivers/net/usb/lan78xx.h193
-rw-r--r--drivers/net/usb/mcs7830.c1
-rw-r--r--drivers/net/usb/qmi_wwan.c96
-rw-r--r--drivers/net/usb/smsc75xx.c5
-rw-r--r--drivers/net/usb/smsc95xx.c5
-rw-r--r--drivers/net/usb/sr9800.c4
-rw-r--r--drivers/net/usb/usbnet.c144
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c7
-rw-r--r--drivers/net/vmxnet3/vmxnet3_ethtool.c122
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h4
-rw-r--r--drivers/net/vrf.c415
-rw-r--r--drivers/net/vxlan.c215
-rw-r--r--drivers/net/wireless/Kconfig7
-rw-r--r--drivers/net/wireless/Makefile4
-rw-r--r--drivers/net/wireless/airo.c139
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h10
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c67
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h23
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c387
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h71
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c516
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h11
-rw-r--r--drivers/net/wireless/ath/ath10k/hif.h26
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c51
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h10
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c48
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c112
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h39
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c640
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c333
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h11
-rw-r--r--drivers/net/wireless/ath/ath10k/targaddrs.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c202
-rw-r--r--drivers/net/wireless/ath/ath10k/thermal.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c19
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h57
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c15
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c979
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h195
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c149
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c55
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_mbox.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c106
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.h21
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h18
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c2
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.c10
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.h5
-rw-r--r--drivers/net/wireless/ath/dfs_pri_detector.c6
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c61
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.h1
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/Kconfig1
-rw-r--r--drivers/net/wireless/ath/wil6210/Makefile1
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c16
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c16
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/pmc.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c26
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c92
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.h7
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h14
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_crash_dump.c115
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c22
-rw-r--r--drivers/net/wireless/b43/Kconfig20
-rw-r--r--drivers/net/wireless/b43/Makefile1
-rw-r--r--drivers/net/wireless/b43/debugfs.c18
-rw-r--r--drivers/net/wireless/b43/debugfs.h2
-rw-r--r--drivers/net/wireless/b43/main.c10
-rw-r--r--drivers/net/wireless/b43/pcmcia.c145
-rw-r--r--drivers/net/wireless/b43/pcmcia.h20
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c10
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.h2
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcdc.c28
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/btcoex.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bus.h21
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c279
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h6
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/chip.c130
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/chip.h1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/common.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/core.c179
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/core.h21
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/debug.c42
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/debug.h11
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.c15
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/flowring.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/flowring.h2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.c42
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil.h1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h13
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c57
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c15
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c145
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.h5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/pcie.c178
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/proto.h18
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio.c55
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c29
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c2
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h13
-rw-r--r--drivers/net/wireless/cw1200/cw1200_spi.c1
-rw-r--r--drivers/net/wireless/cw1200/sta.c2
-rw-r--r--drivers/net/wireless/cw1200/sta.h2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c1
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965.h2
-rw-r--r--drivers/net/wireless/iwlegacy/common.h6
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig1
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-7000.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-file.h36
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h7
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/constants.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c30
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c100
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c134
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h238
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h41
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h259
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c28
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c39
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c96
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h81
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c180
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c109
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c122
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c67
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c122
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c88
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tof.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tof.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c23
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c15
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c141
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c5
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c10
-rw-r--r--drivers/net/wireless/libertas/if_spi.c1
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c9
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/main.c3
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c12
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c4
-rw-r--r--drivers/net/wireless/mwifiex/Kconfig4
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c22
-rw-r--r--drivers/net/wireless/mwifiex/debugfs.c66
-rw-r--r--drivers/net/wireless/mwifiex/fw.h34
-rw-r--r--drivers/net/wireless/mwifiex/init.c1
-rw-r--r--drivers/net/wireless/mwifiex/main.c81
-rw-r--r--drivers/net/wireless/mwifiex/main.h25
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c1
-rw-r--r--drivers/net/wireless/mwifiex/scan.c22
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c29
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c34
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c36
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c78
-rw-r--r--drivers/net/wireless/mwifiex/sta_tx.c7
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c12
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c19
-rw-r--r--drivers/net/wireless/mwifiex/uap_cmd.c16
-rw-r--r--drivers/net/wireless/mwifiex/uap_event.c11
-rw-r--r--drivers/net/wireless/mwifiex/uap_txrx.c10
-rw-r--r--drivers/net/wireless/mwifiex/usb.c238
-rw-r--r--drivers/net/wireless/mwifiex/usb.h20
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c69
-rw-r--r--drivers/net/wireless/mwl8k.c2
-rw-r--r--drivers/net/wireless/orinoco/cfg.c6
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c1
-rw-r--r--drivers/net/wireless/p54/p54spi.c1
-rw-r--r--drivers/net/wireless/realtek/Makefile9
-rw-r--r--drivers/net/wireless/realtek/rtl818x/Kconfig (renamed from drivers/net/wireless/rtl818x/Kconfig)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/Makefile (renamed from drivers/net/wireless/rtl818x/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile (renamed from drivers/net/wireless/rtl818x/rtl8180/Makefile)2
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c (renamed from drivers/net/wireless/rtl818x/rtl8180/dev.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c (renamed from drivers/net/wireless/rtl818x/rtl8180/grf5101.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h (renamed from drivers/net/wireless/rtl818x/rtl8180/grf5101.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c (renamed from drivers/net/wireless/rtl818x/rtl8180/max2820.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h (renamed from drivers/net/wireless/rtl818x/rtl8180/max2820.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8180.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c (renamed from drivers/net/wireless/rtl818x/rtl8180/sa2400.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h (renamed from drivers/net/wireless/rtl818x/rtl8180/sa2400.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile (renamed from drivers/net/wireless/rtl818x/rtl8187/Makefile)2
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c (renamed from drivers/net/wireless/rtl818x/rtl8187/dev.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c (renamed from drivers/net/wireless/rtl818x/rtl8187/leds.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h (renamed from drivers/net/wireless/rtl818x/rtl8187/leds.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c (renamed from drivers/net/wireless/rtl818x/rtl8187/rfkill.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h (renamed from drivers/net/wireless/rtl818x/rtl8187/rfkill.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h (renamed from drivers/net/wireless/rtl818x/rtl8187/rtl8187.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c (renamed from drivers/net/wireless/rtl818x/rtl8187/rtl8225.c)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h (renamed from drivers/net/wireless/rtl818x/rtl8187/rtl8225.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl818x.h (renamed from drivers/net/wireless/rtl818x/rtl818x.h)0
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/Kconfig34
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/Makefile1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c5993
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h676
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h981
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/Kconfig (renamed from drivers/net/wireless/rtlwifi/Kconfig)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/Makefile (renamed from drivers/net/wireless/rtlwifi/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c (renamed from drivers/net/wireless/rtlwifi/base.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h (renamed from drivers/net/wireless/rtlwifi/base.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile (renamed from drivers/net/wireless/rtlwifi/btcoexist/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/cam.c (renamed from drivers/net/wireless/rtlwifi/cam.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/cam.h (renamed from drivers/net/wireless/rtlwifi/cam.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c (renamed from drivers/net/wireless/rtlwifi/core.c)2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.h (renamed from drivers/net/wireless/rtlwifi/core.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.c (renamed from drivers/net/wireless/rtlwifi/debug.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.h (renamed from drivers/net/wireless/rtlwifi/debug.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/efuse.c (renamed from drivers/net/wireless/rtlwifi/efuse.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/efuse.h (renamed from drivers/net/wireless/rtlwifi/efuse.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c (renamed from drivers/net/wireless/rtlwifi/pci.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.h (renamed from drivers/net/wireless/rtlwifi/pci.h)2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.c (renamed from drivers/net/wireless/rtlwifi/ps.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.h (renamed from drivers/net/wireless/rtlwifi/ps.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h (renamed from drivers/net/wireless/rtlwifi/pwrseqcmd.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rc.c (renamed from drivers/net/wireless/rtlwifi/rc.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rc.h (renamed from drivers/net/wireless/rtlwifi/rc.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.c (renamed from drivers/net/wireless/rtlwifi/regd.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.h (renamed from drivers/net/wireless/rtlwifi/regd.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192c/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/main.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/hw.c)8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/mac.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/mac.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192de/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192se/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/btc.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8723be/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/hw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/sw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8723com/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/main.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/Makefile)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/def.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/dm.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/dm.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/fw.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/fw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/hw.c)17
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/hw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/led.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/led.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/phy.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/phy.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/reg.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/rf.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/rf.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/sw.c)5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/sw.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/table.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/table.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/trx.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/trx.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/stats.c (renamed from drivers/net/wireless/rtlwifi/stats.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/stats.h (renamed from drivers/net/wireless/rtlwifi/stats.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c (renamed from drivers/net/wireless/rtlwifi/usb.c)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.h (renamed from drivers/net/wireless/rtlwifi/usb.h)0
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h (renamed from drivers/net/wireless/rtlwifi/wifi.h)3
-rw-r--r--drivers/net/wireless/rndis_wlan.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/spi.c1
-rw-r--r--drivers/net/wireless/ti/wl12xx/scan.c3
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c1
-rw-r--r--drivers/net/wireless/ti/wl18xx/scan.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c1
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h2
-rw-r--r--drivers/net/xen-netback/common.h16
-rw-r--r--drivers/net/xen-netback/netback.c167
-rw-r--r--drivers/net/xen-netback/xenbus.c6
-rw-r--r--drivers/net/xen-netfront.c153
-rw-r--r--drivers/nfc/Kconfig1
-rw-r--r--drivers/nfc/Makefile1
-rw-r--r--drivers/nfc/fdp/Kconfig23
-rw-r--r--drivers/nfc/fdp/Makefile9
-rw-r--r--drivers/nfc/fdp/fdp.c817
-rw-r--r--drivers/nfc/fdp/fdp.h38
-rw-r--r--drivers/nfc/fdp/i2c.c388
-rw-r--r--drivers/nfc/mei_phy.c31
-rw-r--r--drivers/nfc/mei_phy.h4
-rw-r--r--drivers/nfc/microread/Kconfig18
-rw-r--r--drivers/nfc/microread/mei.c14
-rw-r--r--drivers/nfc/nfcmrvl/Kconfig34
-rw-r--r--drivers/nfc/nfcmrvl/Makefile8
-rw-r--r--drivers/nfc/nfcmrvl/fw_dnld.c559
-rw-r--r--drivers/nfc/nfcmrvl/fw_dnld.h98
-rw-r--r--drivers/nfc/nfcmrvl/i2c.c290
-rw-r--r--drivers/nfc/nfcmrvl/main.c88
-rw-r--r--drivers/nfc/nfcmrvl/nfcmrvl.h23
-rw-r--r--drivers/nfc/nfcmrvl/spi.c228
-rw-r--r--drivers/nfc/nfcmrvl/uart.c52
-rw-r--r--drivers/nfc/nfcmrvl/usb.c10
-rw-r--r--drivers/nfc/nfcsim.c2
-rw-r--r--drivers/nfc/nfcwilink.c2
-rw-r--r--drivers/nfc/nxp-nci/core.c3
-rw-r--r--drivers/nfc/nxp-nci/i2c.c2
-rw-r--r--drivers/nfc/nxp-nci/nxp-nci.h5
-rw-r--r--drivers/nfc/pn533.c2
-rw-r--r--drivers/nfc/pn544/Kconfig18
-rw-r--r--drivers/nfc/pn544/mei.c14
-rw-r--r--drivers/nfc/s3fwrn5/Kconfig1
-rw-r--r--drivers/nfc/s3fwrn5/Makefile2
-rw-r--r--drivers/nfc/s3fwrn5/i2c.c2
-rw-r--r--drivers/nfc/s3fwrn5/nci.c4
-rw-r--r--drivers/nfc/s3fwrn5/nci.h2
-rw-r--r--drivers/nfc/st-nci/Makefile4
-rw-r--r--drivers/nfc/st-nci/core.c20
-rw-r--r--drivers/nfc/st-nci/i2c.c35
-rw-r--r--drivers/nfc/st-nci/ndlc.c7
-rw-r--r--drivers/nfc/st-nci/ndlc.h5
-rw-r--r--drivers/nfc/st-nci/se.c (renamed from drivers/nfc/st-nci/st-nci_se.c)166
-rw-r--r--drivers/nfc/st-nci/spi.c38
-rw-r--r--drivers/nfc/st-nci/st-nci.h117
-rw-r--r--drivers/nfc/st-nci/st-nci_se.h61
-rw-r--r--drivers/nfc/st-nci/vendor_cmds.c516
-rw-r--r--drivers/nfc/st21nfca/Makefile2
-rw-r--r--drivers/nfc/st21nfca/core.c (renamed from drivers/nfc/st21nfca/st21nfca.c)48
-rw-r--r--drivers/nfc/st21nfca/dep.c (renamed from drivers/nfc/st21nfca/st21nfca_dep.c)2
-rw-r--r--drivers/nfc/st21nfca/i2c.c1
-rw-r--r--drivers/nfc/st21nfca/se.c (renamed from drivers/nfc/st21nfca/st21nfca_se.c)18
-rw-r--r--drivers/nfc/st21nfca/st21nfca.h148
-rw-r--r--drivers/nfc/st21nfca/st21nfca_dep.h43
-rw-r--r--drivers/nfc/st21nfca/st21nfca_se.h63
-rw-r--r--drivers/nfc/st21nfca/vendor_cmds.c375
-rw-r--r--drivers/nfc/trf7970a.c8
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.c16
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.h15
-rw-r--r--drivers/ntb/ntb_transport.c44
-rw-r--r--drivers/nvdimm/blk.c3
-rw-r--r--drivers/nvdimm/btt.c4
-rw-r--r--drivers/nvdimm/core.c21
-rw-r--r--drivers/nvdimm/e820.c15
-rw-r--r--drivers/nvdimm/pmem.c46
-rw-r--r--drivers/nvme/Kconfig1
-rw-r--r--drivers/nvme/Makefile2
-rw-r--r--drivers/nvme/host/Kconfig10
-rw-r--r--drivers/nvme/host/Makefile4
-rw-r--r--drivers/nvme/host/lightnvm.c526
-rw-r--r--drivers/nvme/host/nvme.h143
-rw-r--r--drivers/nvme/host/pci.c (renamed from drivers/block/nvme-core.c)458
-rw-r--r--drivers/nvme/host/scsi.c (renamed from drivers/block/nvme-scsi.c)2
-rw-r--r--drivers/nvmem/Kconfig42
-rw-r--r--drivers/nvmem/Makefile8
-rw-r--r--drivers/nvmem/imx-ocotp.c154
-rw-r--r--drivers/nvmem/mxs-ocotp.c257
-rw-r--r--drivers/nvmem/rockchip-efuse.c186
-rw-r--r--drivers/nvmem/vf610-ocotp.c302
-rw-r--r--drivers/of/Kconfig10
-rw-r--r--drivers/of/address.c6
-rw-r--r--drivers/of/base.c5
-rw-r--r--drivers/of/device.c11
-rw-r--r--drivers/of/fdt.c12
-rw-r--r--drivers/of/irq.c194
-rw-r--r--drivers/of/of_pci.c36
-rw-r--r--drivers/of/of_reserved_mem.c46
-rw-r--r--drivers/of/overlay.c5
-rw-r--r--drivers/of/platform.c8
-rw-r--r--drivers/of/unittest.c8
-rw-r--r--drivers/parisc/ccio-dma.c2
-rw-r--r--drivers/parisc/lba_pci.c12
-rw-r--r--drivers/pci/host/Kconfig33
-rw-r--r--drivers/pci/host/Makefile3
-rw-r--r--drivers/pci/host/pci-dra7xx.c7
-rw-r--r--drivers/pci/host/pci-exynos.c5
-rw-r--r--drivers/pci/host/pci-host-generic.c41
-rw-r--r--drivers/pci/host/pci-imx6.c5
-rw-r--r--drivers/pci/host/pci-keystone-dw.c8
-rw-r--r--drivers/pci/host/pci-keystone.h2
-rw-r--r--drivers/pci/host/pci-layerscape.c199
-rw-r--r--drivers/pci/host/pci-mvebu.c473
-rw-r--r--drivers/pci/host/pci-tegra.c4
-rw-r--r--drivers/pci/host/pci-xgene-msi.c2
-rw-r--r--drivers/pci/host/pci-xgene.c22
-rw-r--r--drivers/pci/host/pcie-altera-msi.c314
-rw-r--r--drivers/pci/host/pcie-altera.c579
-rw-r--r--drivers/pci/host/pcie-designware.c375
-rw-r--r--drivers/pci/host/pcie-designware.h20
-rw-r--r--drivers/pci/host/pcie-hisi.c198
-rw-r--r--drivers/pci/host/pcie-iproc-platform.c27
-rw-r--r--drivers/pci/host/pcie-iproc.c163
-rw-r--r--drivers/pci/host/pcie-iproc.h20
-rw-r--r--drivers/pci/host/pcie-rcar.c86
-rw-r--r--drivers/pci/host/pcie-spear13xx.c24
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c75
-rw-r--r--drivers/pci/iov.c101
-rw-r--r--drivers/pci/msi.c101
-rw-r--r--drivers/pci/of.c13
-rw-r--r--drivers/pci/pci-driver.c15
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/pci.c295
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c28
-rw-r--r--drivers/pci/probe.c81
-rw-r--r--drivers/pci/quirks.c58
-rw-r--r--drivers/pci/setup-bus.c50
-rw-r--r--drivers/pci/setup-res.c7
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/perf/Kconfig2
-rw-r--r--drivers/perf/arm_pmu.c10
-rw-r--r--drivers/phy/Kconfig18
-rw-r--r--drivers/phy/Makefile2
-rw-r--r--drivers/phy/phy-bcm-cygnus-pcie.c213
-rw-r--r--drivers/phy/phy-mt65xx-usb3.c506
-rw-r--r--drivers/phy/phy-rcar-gen2.c3
-rw-r--r--drivers/phy/phy-samsung-usb2.c25
-rw-r--r--drivers/phy/phy-samsung-usb2.h2
-rw-r--r--drivers/phy/phy-sun4i-usb.c22
-rw-r--r--drivers/pinctrl/Kconfig13
-rw-r--r--drivers/pinctrl/Makefile3
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c14
-rw-r--r--drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c131
-rw-r--r--drivers/pinctrl/berlin/Kconfig16
-rw-r--r--drivers/pinctrl/berlin/Makefile1
-rw-r--r--drivers/pinctrl/berlin/berlin-bg2.c4
-rw-r--r--drivers/pinctrl/berlin/berlin-bg2cd.c66
-rw-r--r--drivers/pinctrl/berlin/berlin-bg2q.c4
-rw-r--r--drivers/pinctrl/berlin/berlin-bg4ct.c503
-rw-r--r--drivers/pinctrl/berlin/berlin.c28
-rw-r--r--drivers/pinctrl/berlin/berlin.h6
-rw-r--r--drivers/pinctrl/core.c32
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c36
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.h2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx25.c4
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx7d.c30
-rw-r--r--drivers/pinctrl/freescale/pinctrl-mxs.c2
-rw-r--r--drivers/pinctrl/intel/Kconfig8
-rw-r--r--drivers/pinctrl/intel/Makefile1
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-broxton.c1065
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c14
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c122
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c18
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c18
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik.c22
-rw-r--r--drivers/pinctrl/pinconf-generic.c35
-rw-r--r--drivers/pinctrl/pinconf.c13
-rw-r--r--drivers/pinctrl/pinctrl-adi2.c14
-rw-r--r--drivers/pinctrl/pinctrl-as3722.c14
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c1094
-rw-r--r--drivers/pinctrl/pinctrl-at91.c31
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c22
-rw-r--r--drivers/pinctrl/pinctrl-digicolor.c14
-rw-r--r--drivers/pinctrl/pinctrl-pistachio.c14
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c31
-rw-r--r--drivers/pinctrl/pinctrl-st.c14
-rw-r--r--drivers/pinctrl/pinctrl-tegra-xusb.c9
-rw-r--r--drivers/pinctrl/pinctrl-tz1090-pdc.c4
-rw-r--r--drivers/pinctrl/pinctrl-tz1090.c4
-rw-r--r--drivers/pinctrl/pinctrl-xway.c18
-rw-r--r--drivers/pinctrl/pinctrl-zynq.c16
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c16
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c14
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-mpp.c14
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos5440.c2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c14
-rw-r--r--drivers/pinctrl/sh-pfc/Kconfig5
-rw-r--r--drivers/pinctrl/sh-pfc/Makefile1
-rw-r--r--drivers/pinctrl/sh-pfc/core.c16
-rw-r--r--drivers/pinctrl/sh-pfc/core.h3
-rw-r--r--drivers/pinctrl/sh-pfc/gpio.c37
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-emev2.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a73a4.c124
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7740.c68
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7778.c266
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7779.c425
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7790.c1062
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7791.c1103
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7794.c1035
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795.c2816
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7203.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7264.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7269.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh73a0.c68
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7720.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7722.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7723.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7724.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7734.c782
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7757.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7785.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7786.c4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-shx3.c4
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h93
-rw-r--r--drivers/pinctrl/sirf/pinctrl-atlas7.c1828
-rw-r--r--drivers/pinctrl/sunxi/Kconfig4
-rw-r--r--drivers/pinctrl/sunxi/Makefile1
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c24
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c603
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c22
-rw-r--r--drivers/pinctrl/uniphier/Kconfig14
-rw-r--r--drivers/pinctrl/uniphier/Makefile2
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c5
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c5
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c11
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c5
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c231
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-proxstream2.c5
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-core.c10
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c14
-rw-r--r--drivers/platform/chrome/Kconfig5
-rw-r--r--drivers/platform/chrome/Makefile3
-rw-r--r--drivers/platform/chrome/chromeos_laptop.c4
-rw-r--r--drivers/platform/chrome/cros_ec_dev.c7
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c31
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c21
-rw-r--r--drivers/platform/chrome/cros_ec_vbc.c137
-rw-r--r--drivers/platform/olpc/olpc-ec.c13
-rw-r--r--drivers/platform/x86/Kconfig24
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c92
-rw-r--r--drivers/platform/x86/apple-gmux.c2
-rw-r--r--drivers/platform/x86/asus-wmi.c23
-rw-r--r--drivers/platform/x86/compal-laptop.c43
-rw-r--r--drivers/platform/x86/ibm_rtl.c2
-rw-r--r--drivers/platform/x86/ideapad-laptop.c49
-rw-r--r--drivers/platform/x86/intel_ips.c2
-rw-r--r--drivers/platform/x86/intel_menlow.c8
-rw-r--r--drivers/platform/x86/intel_mid_powerbtn.c10
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c189
-rw-r--r--drivers/platform/x86/sony-laptop.c13
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c3
-rw-r--r--drivers/platform/x86/toshiba-wmi.c138
-rw-r--r--drivers/platform/x86/toshiba_acpi.c63
-rw-r--r--drivers/pnp/pnpacpi/core.c4
-rw-r--r--drivers/power/88pm860x_battery.c37
-rw-r--r--drivers/power/Kconfig66
-rw-r--r--drivers/power/Makefile6
-rw-r--r--drivers/power/avs/rockchip-io-domain.c1
-rw-r--r--drivers/power/axp20x_usb_power.c248
-rw-r--r--drivers/power/bq2415x_charger.c2
-rw-r--r--drivers/power/bq24190_charger.c1
-rw-r--r--drivers/power/bq24257_charger.c492
-rw-r--r--drivers/power/bq27x00_battery.c1129
-rw-r--r--drivers/power/bq27xxx_battery.c1375
-rw-r--r--drivers/power/charger-manager.c4
-rw-r--r--drivers/power/da9150-fg.c579
-rw-r--r--drivers/power/lp8727_charger.c31
-rw-r--r--drivers/power/max17042_battery.c26
-rw-r--r--drivers/power/max8903_charger.c93
-rw-r--r--drivers/power/max8998_charger.c29
-rw-r--r--drivers/power/pm2301_charger.c1
-rw-r--r--drivers/power/qcom_smbb.c951
-rw-r--r--drivers/power/reset/Kconfig4
-rw-r--r--drivers/power/reset/at91-poweroff.c33
-rw-r--r--drivers/power/reset/at91-reset.c69
-rw-r--r--drivers/power/rt9455_charger.c1
-rw-r--r--drivers/power/smb347-charger.c1
-rw-r--r--drivers/power/tps65090-charger.c1
-rw-r--r--drivers/power/tps65217_charger.c264
-rw-r--r--drivers/power/twl4030_charger.c39
-rw-r--r--drivers/power/wm831x_power.c15
-rw-r--r--drivers/powercap/intel_rapl.c1
-rw-r--r--drivers/pps/kapi.c4
-rw-r--r--drivers/ps3/ps3-lpm.c2
-rw-r--r--drivers/ps3/ps3-vuart.c3
-rw-r--r--drivers/pwm/Kconfig49
-rw-r--r--drivers/pwm/Makefile4
-rw-r--r--drivers/pwm/core.c37
-rw-r--r--drivers/pwm/pwm-atmel-hlcdc.c4
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c26
-rw-r--r--drivers/pwm/pwm-berlin.c219
-rw-r--r--drivers/pwm/pwm-brcmstb.c343
-rw-r--r--drivers/pwm/pwm-lpss-pci.c37
-rw-r--r--drivers/pwm/pwm-lpss-platform.c7
-rw-r--r--drivers/pwm/pwm-lpss.c62
-rw-r--r--drivers/pwm/pwm-lpss.h2
-rw-r--r--drivers/pwm/pwm-mtk-disp.c243
-rw-r--r--drivers/pwm/pwm-pca9685.c20
-rw-r--r--drivers/pwm/pwm-rcar.c274
-rw-r--r--drivers/pwm/pwm-sun4i.c27
-rw-r--r--drivers/pwm/sysfs.c75
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/act8865-regulator.c24
-rw-r--r--drivers/regulator/anatop-regulator.c3
-rw-r--r--drivers/regulator/arizona-ldo1.c20
-rw-r--r--drivers/regulator/axp20x-regulator.c54
-rw-r--r--drivers/regulator/bcm590xx-regulator.c2
-rw-r--r--drivers/regulator/core.c512
-rw-r--r--drivers/regulator/da9052-regulator.c1
-rw-r--r--drivers/regulator/da9063-regulator.c2
-rw-r--r--drivers/regulator/of_regulator.c3
-rw-r--r--drivers/regulator/pwm-regulator.c35
-rw-r--r--drivers/regulator/qcom_smd-regulator.c28
-rw-r--r--drivers/regulator/tps6105x-regulator.c16
-rw-r--r--drivers/regulator/tps65023-regulator.c282
-rw-r--r--drivers/regulator/tps6524x-regulator.c1
-rw-r--r--drivers/rtc/Kconfig13
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-ab8500.c6
-rw-r--r--drivers/rtc/rtc-at91rm9200.c2
-rw-r--r--drivers/rtc/rtc-da9063.c18
-rw-r--r--drivers/rtc/rtc-davinci.c1
-rw-r--r--drivers/rtc/rtc-ds1305.c1
-rw-r--r--drivers/rtc/rtc-ds1307.c4
-rw-r--r--drivers/rtc/rtc-ds1343.c10
-rw-r--r--drivers/rtc/rtc-ds1347.c1
-rw-r--r--drivers/rtc/rtc-ds1390.c66
-rw-r--r--drivers/rtc/rtc-ds3234.c1
-rw-r--r--drivers/rtc/rtc-isl12057.c10
-rw-r--r--drivers/rtc/rtc-isl1208.c2
-rw-r--r--drivers/rtc/rtc-m41t93.c1
-rw-r--r--drivers/rtc/rtc-m41t94.c1
-rw-r--r--drivers/rtc/rtc-max6902.c1
-rw-r--r--drivers/rtc/rtc-mcp795.c1
-rw-r--r--drivers/rtc/rtc-opal.c9
-rw-r--r--drivers/rtc/rtc-pcf2123.c1
-rw-r--r--drivers/rtc/rtc-pcf2127.c47
-rw-r--r--drivers/rtc/rtc-pcf85063.c8
-rw-r--r--drivers/rtc/rtc-pcf8563.c170
-rw-r--r--drivers/rtc/rtc-pl031.c13
-rw-r--r--drivers/rtc/rtc-r9701.c1
-rw-r--r--drivers/rtc/rtc-rs5c348.c1
-rw-r--r--drivers/rtc/rtc-rv8803.c521
-rw-r--r--drivers/rtc/rtc-rx4581.c1
-rw-r--r--drivers/rtc/rtc-rx8025.c4
-rw-r--r--drivers/rtc/rtc-s3c.c16
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c27
-rw-r--r--drivers/s390/block/dasd.c1
-rw-r--r--drivers/s390/block/dasd_alias.c5
-rw-r--r--drivers/s390/block/dasd_diag.c2
-rw-r--r--drivers/s390/block/dasd_eckd.c73
-rw-r--r--drivers/s390/block/dcssblk.c8
-rw-r--r--drivers/s390/block/xpram.c5
-rw-r--r--drivers/s390/char/diag_ftp.c2
-rw-r--r--drivers/s390/char/monreader.c4
-rw-r--r--drivers/s390/char/sclp_rw.c136
-rw-r--r--drivers/s390/char/sclp_rw.h17
-rw-r--r--drivers/s390/char/sclp_tty.c8
-rw-r--r--drivers/s390/char/vmlogrdr.c8
-rw-r--r--drivers/s390/cio/chsc.c37
-rw-r--r--drivers/s390/cio/chsc.h15
-rw-r--r--drivers/s390/cio/cio.c47
-rw-r--r--drivers/s390/cio/cmf.c220
-rw-r--r--drivers/s390/cio/css.c7
-rw-r--r--drivers/s390/cio/device.c4
-rw-r--r--drivers/s390/cio/device.h6
-rw-r--r--drivers/s390/cio/device_fsm.c38
-rw-r--r--drivers/s390/cio/device_ops.c107
-rw-r--r--drivers/s390/cio/device_pgid.c70
-rw-r--r--drivers/s390/cio/qdio_main.c4
-rw-r--r--drivers/s390/crypto/Makefile7
-rw-r--r--drivers/s390/crypto/ap_bus.c1816
-rw-r--r--drivers/s390/crypto/ap_bus.h67
-rw-r--r--drivers/s390/crypto/zcrypt_api.c13
-rw-r--r--drivers/s390/crypto/zcrypt_api.h1
-rw-r--r--drivers/s390/crypto/zcrypt_cca_key.h2
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype50.c29
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype6.c62
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c420
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.h115
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c627
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.h174
-rw-r--r--drivers/s390/net/netiucv.c21
-rw-r--r--drivers/s390/net/qeth_core.h30
-rw-r--r--drivers/s390/net/qeth_core_main.c241
-rw-r--r--drivers/s390/net/qeth_core_sys.c43
-rw-r--r--drivers/s390/net/qeth_l2_main.c228
-rw-r--r--drivers/s390/net/qeth_l2_sys.c2
-rw-r--r--drivers/s390/net/qeth_l3_main.c158
-rw-r--r--drivers/s390/net/smsgiucv.c5
-rw-r--r--drivers/s390/virtio/virtio_ccw.c15
-rw-r--r--drivers/scsi/53c700.c11
-rw-r--r--drivers/scsi/FlashPoint.c2
-rw-r--r--drivers/scsi/Kconfig8
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/aacraid/aachba.c265
-rw-r--r--drivers/scsi/aacraid/aacraid.h20
-rw-r--r--drivers/scsi/aacraid/comminit.c147
-rw-r--r--drivers/scsi/aacraid/commsup.c113
-rw-r--r--drivers/scsi/aacraid/linit.c152
-rw-r--r--drivers/scsi/aacraid/rx.c1
-rw-r--r--drivers/scsi/aacraid/sa.c1
-rw-r--r--drivers/scsi/aacraid/src.c64
-rw-r--r--drivers/scsi/advansys.c6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c1
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c3
-rw-r--r--drivers/scsi/be2iscsi/Kconfig4
-rw-r--r--drivers/scsi/be2iscsi/Makefile2
-rw-r--r--drivers/scsi/be2iscsi/be.h4
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c4
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h4
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c4
-rw-r--r--drivers/scsi/be2iscsi/be_main.c72
-rw-r--r--drivers/scsi/be2iscsi/be_main.h13
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c28
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h11
-rw-r--r--drivers/scsi/bfa/bfad_im.c2
-rw-r--r--drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h6
-rw-r--r--drivers/scsi/bnx2fc/Kconfig5
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h9
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_constants.h6
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.c6
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.h6
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c10
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c27
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c6
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c106
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c12
-rw-r--r--drivers/scsi/csiostor/csio_scsi.c2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kbuild2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kbuild2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c2
-rw-r--r--drivers/scsi/cxlflash/common.h30
-rw-r--r--drivers/scsi/cxlflash/lunmgt.c45
-rw-r--r--drivers/scsi/cxlflash/main.c1500
-rw-r--r--drivers/scsi/cxlflash/main.h1
-rw-r--r--drivers/scsi/cxlflash/sislite.h8
-rw-r--r--drivers/scsi/cxlflash/superpipe.c209
-rw-r--r--drivers/scsi/cxlflash/superpipe.h14
-rw-r--r--drivers/scsi/cxlflash/vlun.c68
-rw-r--r--drivers/scsi/esas2r/esas2r_main.c1
-rw-r--r--drivers/scsi/esp_scsi.c1
-rw-r--r--drivers/scsi/fcoe/fcoe.c4
-rw-r--r--drivers/scsi/fnic/fnic_fcs.c46
-rw-r--r--drivers/scsi/fnic/fnic_main.c8
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c16
-rw-r--r--drivers/scsi/hosts.c7
-rw-r--r--drivers/scsi/hpsa.c1346
-rw-r--r--drivers/scsi/hpsa.h47
-rw-r--r--drivers/scsi/hpsa_cmd.h30
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c10
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h1
-rw-r--r--drivers/scsi/ipr.c154
-rw-r--r--drivers/scsi/ipr.h22
-rw-r--r--drivers/scsi/isci/init.c5
-rw-r--r--drivers/scsi/libfc/fc_npiv.c2
-rw-r--r--drivers/scsi/lpfc/lpfc.h8
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c23
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c20
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c11
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c108
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c27
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c36
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c19
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c17
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h62
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c466
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c28
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c404
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h36
-rw-r--r--drivers/scsi/mpt2sas/Kconfig67
-rw-r--r--drivers/scsi/mpt2sas/Makefile7
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h1170
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h3068
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h461
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h1708
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_raid.h366
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_sas.h288
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_tool.h481
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_type.h61
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c4899
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h1235
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c1527
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c3101
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.h419
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_debug.h182
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c8855
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c2173
-rw-r--r--drivers/scsi/mpt3sas/Kconfig18
-rw-r--r--drivers/scsi/mpt3sas/Makefile3
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c668
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h233
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_config.c42
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c259
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.h6
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_debug.h16
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c1555
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_transport.c18
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_warpdrive.c344
-rw-r--r--drivers/scsi/mvsas/mv_init.c3
-rw-r--r--drivers/scsi/mvsas/mv_sas.c2
-rw-r--r--drivers/scsi/mvumi.c10
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h2
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c216
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h6
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c34
-rw-r--r--drivers/scsi/pmcraid.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c1
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c153
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c8
-rw-r--r--drivers/scsi/scsi.c27
-rw-r--r--drivers/scsi/scsi_devinfo.c181
-rw-r--r--drivers/scsi/scsi_dh.c8
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_lib.c4
-rw-r--r--drivers/scsi/scsi_priv.h2
-rw-r--r--drivers/scsi/scsi_scan.c9
-rw-r--r--drivers/scsi/scsi_sysfs.c58
-rw-r--r--drivers/scsi/sd.c98
-rw-r--r--drivers/scsi/sd_dif.c31
-rw-r--r--drivers/scsi/sg.c8
-rw-r--r--drivers/scsi/snic/snic_main.c10
-rw-r--r--drivers/scsi/snic/snic_trc.c4
-rw-r--r--drivers/scsi/snic/snic_trc.h2
-rw-r--r--drivers/scsi/st.c30
-rw-r--r--drivers/scsi/stex.c21
-rw-r--r--drivers/scsi/storvsc_drv.c294
-rw-r--r--drivers/scsi/ufs/Kconfig2
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c905
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h68
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c98
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.h41
-rw-r--r--drivers/scsi/ufs/ufshcd.c130
-rw-r--r--drivers/scsi/ufs/ufshcd.h149
-rw-r--r--drivers/sh/pm_runtime.c2
-rw-r--r--drivers/soc/Kconfig2
-rw-r--r--drivers/soc/Makefile2
-rw-r--r--drivers/soc/brcmstb/Kconfig9
-rw-r--r--drivers/soc/brcmstb/Makefile1
-rw-r--r--drivers/soc/brcmstb/biuctrl.c116
-rw-r--r--drivers/soc/brcmstb/common.c33
-rw-r--r--drivers/soc/dove/pmu.c1
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c10
-rw-r--r--drivers/soc/mediatek/mtk-scpsys.c83
-rw-r--r--drivers/soc/qcom/Kconfig17
-rw-r--r--drivers/soc/qcom/smd-rpm.c68
-rw-r--r--drivers/soc/qcom/smd.c296
-rw-r--r--drivers/soc/qcom/smem.c368
-rw-r--r--drivers/soc/rockchip/Kconfig18
-rw-r--r--drivers/soc/rockchip/Makefile4
-rw-r--r--drivers/soc/rockchip/pm_domains.c490
-rw-r--r--drivers/soc/ti/knav_qmss.h3
-rw-r--r--drivers/soc/ti/knav_qmss_acc.c14
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c67
-rw-r--r--drivers/spi/Kconfig15
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-ath79.c11
-rw-r--r--drivers/spi/spi-atmel.c24
-rw-r--r--drivers/spi/spi-au1550.c11
-rw-r--r--drivers/spi/spi-bcm2835.c14
-rw-r--r--drivers/spi/spi-bcm2835aux.c512
-rw-r--r--drivers/spi/spi-bcm53xx.c13
-rw-r--r--drivers/spi/spi-bcm63xx.c210
-rw-r--r--drivers/spi/spi-bfin-sport.c5
-rw-r--r--drivers/spi/spi-bfin5xx.c6
-rw-r--r--drivers/spi/spi-bitbang.c152
-rw-r--r--drivers/spi/spi-coldfire-qspi.c3
-rw-r--r--drivers/spi/spi-davinci.c15
-rw-r--r--drivers/spi/spi-dw-mmio.c7
-rw-r--r--drivers/spi/spi-dw-pci.c29
-rw-r--r--drivers/spi/spi-dw.c108
-rw-r--r--drivers/spi/spi-dw.h6
-rw-r--r--drivers/spi/spi-fsl-dspi.c3
-rw-r--r--drivers/spi/spi-imx.c7
-rw-r--r--drivers/spi/spi-mpc512x-psc.c8
-rw-r--r--drivers/spi/spi-mt65xx.c129
-rw-r--r--drivers/spi/spi-oc-tiny.c14
-rw-r--r--drivers/spi/spi-octeon.c2
-rw-r--r--drivers/spi/spi-omap-100k.c26
-rw-r--r--drivers/spi/spi-omap-uwire.c7
-rw-r--r--drivers/spi/spi-omap2-mcspi.c28
-rw-r--r--drivers/spi/spi-ppc4xx.c4
-rw-r--r--drivers/spi/spi-pxa2xx-dma.c4
-rw-r--r--drivers/spi/spi-pxa2xx.c257
-rw-r--r--drivers/spi/spi-pxa2xx.h9
-rw-r--r--drivers/spi/spi-s3c24xx.c4
-rw-r--r--drivers/spi/spi-s3c64xx.c46
-rw-r--r--drivers/spi/spi-ti-qspi.c88
-rw-r--r--drivers/spi/spi-tle62x0.c1
-rw-r--r--drivers/spi/spi-txx9.c2
-rw-r--r--drivers/spi/spi-xilinx.c38
-rw-r--r--drivers/spi/spi.c136
-rw-r--r--drivers/spi/spidev.c1
-rw-r--r--drivers/spmi/spmi-pmic-arb.c13
-rw-r--r--drivers/spmi/spmi.c5
-rw-r--r--drivers/ssb/Kconfig9
-rw-r--r--drivers/ssb/Makefile3
-rw-r--r--drivers/ssb/bridge_pcmcia_80211.c128
-rw-r--r--drivers/ssb/host_soc.c173
-rw-r--r--drivers/ssb/main.c173
-rw-r--r--drivers/ssb/pcmcia.c3
-rw-r--r--drivers/ssb/sdio.c2
-rw-r--r--drivers/ssb/ssb_private.h34
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/android/ion/compat_ion.c6
-rw-r--r--drivers/staging/android/ion/ion_heap.c2
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c2
-rw-r--r--drivers/staging/android/lowmemorykiller.c6
-rw-r--r--drivers/staging/android/sync.c22
-rw-r--r--drivers/staging/android/timed_gpio.c11
-rw-r--r--drivers/staging/board/board.c6
-rw-r--r--drivers/staging/comedi/Kconfig12
-rw-r--r--drivers/staging/comedi/drivers.c38
-rw-r--r--drivers/staging/comedi/drivers/Makefile1
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c228
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c109
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1720.c195
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c195
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c565
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c8
-rw-r--r--drivers/staging/comedi/drivers/das16.c3
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c18
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.c6
-rw-r--r--drivers/staging/dgap/dgap.c435
-rw-r--r--drivers/staging/dgnc/dgnc_utils.c1
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.c12
-rw-r--r--drivers/staging/fbtft/fb_st7789v.c83
-rw-r--r--drivers/staging/fbtft/fbtft.h1
-rw-r--r--drivers/staging/fbtft/fbtft_device.c15
-rw-r--r--drivers/staging/fbtft/flexfb.c1
-rw-r--r--drivers/staging/fsl-mc/bus/dprc-driver.c2
-rw-r--r--drivers/staging/fsl-mc/include/mc-private.h2
-rw-r--r--drivers/staging/ft1000/Kconfig22
-rw-r--r--drivers/staging/ft1000/Makefile3
-rw-r--r--drivers/staging/ft1000/TODO9
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/Makefile2
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/boot.h158
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.h70
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.imgbin305770 -> 0 bytes
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c158
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c762
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c2068
-rw-r--r--drivers/staging/ft1000/ft1000-usb/Makefile3
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_debug.c789
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_download.c1058
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_hw.c1586
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h123
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_usb.c248
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_usb.h150
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft3000.imgbin280414 -> 0 bytes
-rw-r--r--drivers/staging/ft1000/ft1000.h366
-rw-r--r--drivers/staging/fwserial/fwserial.c3
-rw-r--r--drivers/staging/fwserial/fwserial.h10
-rw-r--r--drivers/staging/gdm724x/gdm_lte.c42
-rw-r--r--drivers/staging/gdm724x/gdm_mux.c22
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c6
-rw-r--r--drivers/staging/gdm724x/gdm_usb.c50
-rw-r--r--drivers/staging/gdm724x/netlink_k.c15
-rw-r--r--drivers/staging/gdm724x/netlink_k.h1
-rw-r--r--drivers/staging/gdm72xx/gdm_qos.c52
-rw-r--r--drivers/staging/gdm72xx/gdm_wimax.c9
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c1
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c1
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c1
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c1
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c1
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c1
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c11
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c24
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c66
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c21
-rw-r--r--drivers/staging/iio/adc/ad7192.c1
-rw-r--r--drivers/staging/iio/adc/ad7280a.c1
-rw-r--r--drivers/staging/iio/adc/ad7606_spi.c1
-rw-r--r--drivers/staging/iio/adc/ad7780.c1
-rw-r--r--drivers/staging/iio/adc/ad7816.c6
-rw-r--r--drivers/staging/iio/adc/lpc32xx_adc.c4
-rw-r--r--drivers/staging/iio/adc/mxs-lradc.c9
-rw-r--r--drivers/staging/iio/addac/adt7316-spi.c1
-rw-r--r--drivers/staging/iio/cdc/ad7150.c2
-rw-r--r--drivers/staging/iio/cdc/ad7152.c2
-rw-r--r--drivers/staging/iio/frequency/ad9832.c1
-rw-r--r--drivers/staging/iio/frequency/ad9834.c3
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c18
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c11
-rw-r--r--drivers/staging/iio/light/isl29018.c6
-rw-r--r--drivers/staging/iio/light/tsl2583.c6
-rw-r--r--drivers/staging/iio/light/tsl2x7x_core.c6
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843_core.c2
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843_spi.c1
-rw-r--r--drivers/staging/iio/meter/ade7753.c3
-rw-r--r--drivers/staging/iio/meter/ade7754.c3
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c1
-rw-r--r--drivers/staging/iio/meter/ade7759.c3
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c3
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c1
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c4
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c2
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs.h2
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h327
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h2
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_private.h4
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_string.h5
-rw-r--r--drivers/staging/lustre/include/linux/lnet/nidstr.h47
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c30
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h6
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c35
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c15
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h3
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/Makefile2
-rw-r--r--drivers/staging/lustre/lnet/lnet/api-ni.c22
-rw-r--r--drivers/staging/lustre/lnet/lnet/config.c26
-rw-r--r--drivers/staging/lustre/lnet/lnet/module.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/nidstrings.c1260
-rw-r--r--drivers/staging/lustre/lnet/lnet/router.c4
-rw-r--r--drivers/staging/lustre/lnet/selftest/brw_test.c4
-rw-r--r--drivers/staging/lustre/lnet/selftest/conctl.c2
-rw-r--r--drivers/staging/lustre/lnet/selftest/conrpc.c6
-rw-r--r--drivers/staging/lustre/lnet/selftest/console.c88
-rw-r--r--drivers/staging/lustre/lnet/selftest/framework.c8
-rw-r--r--drivers/staging/lustre/lnet/selftest/rpc.c25
-rw-r--r--drivers/staging/lustre/lnet/selftest/selftest.h16
-rw-r--r--drivers/staging/lustre/lustre/fid/fid_internal.h2
-rw-r--r--drivers/staging/lustre/lustre/fid/fid_request.c23
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_cache.c34
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_internal.h9
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_request.c2
-rw-r--r--drivers/staging/lustre/lustre/include/lprocfs_status.h15
-rw-r--r--drivers/staging/lustre/lustre/include/lustre/lustre_lfsck_user.h95
-rw-r--r--drivers/staging/lustre/lustre/include/lustre/lustre_user.h22
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_disk.h1
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_dlm.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_log.h90
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_sec.h2
-rw-r--r--drivers/staging/lustre/lustre/include/obd.h322
-rw-r--r--drivers/staging/lustre/lustre/include/obd_cache.h38
-rw-r--r--drivers/staging/lustre/lustre/include/obd_cksum.h23
-rw-r--r--drivers/staging/lustre/lustre/include/obd_class.h36
-rw-r--r--drivers/staging/lustre/lustre/include/obd_support.h75
-rw-r--r--drivers/staging/lustre/lustre/lclient/lcommon_cl.c24
-rw-r--r--drivers/staging/lustre/lustre/ldlm/interval_tree.c19
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_extent.c6
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_lock.c4
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_pool.c48
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_resource.c28
-rw-r--r--drivers/staging/lustre/lustre/libcfs/Makefile2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/debug.c16
-rw-r--r--drivers/staging/lustre/lustre/libcfs/fail.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/hash.c491
-rw-r--r--drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c3
-rw-r--r--drivers/staging/lustre/lustre/libcfs/libcfs_mem.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/libcfs_string.c144
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c30
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c9
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c1
-rw-r--r--drivers/staging/lustre/lustre/libcfs/module.c10
-rw-r--r--drivers/staging/lustre/lustre/libcfs/nidstrings.c842
-rw-r--r--drivers/staging/lustre/lustre/libcfs/tracefile.c29
-rw-r--r--drivers/staging/lustre/lustre/libcfs/tracefile.h15
-rw-r--r--drivers/staging/lustre/lustre/libcfs/workitem.c10
-rw-r--r--drivers/staging/lustre/lustre/llite/dir.c13
-rw-r--r--drivers/staging/lustre/lustre/llite/file.c16
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_close.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_internal.h10
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_lib.c5
-rw-r--r--drivers/staging/lustre/lustre/llite/lloop.c7
-rw-r--r--drivers/staging/lustre/lustre/llite/namei.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/remote_perm.c11
-rw-r--r--drivers/staging/lustre/lustre/llite/super25.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_dev.c8
-rw-r--r--drivers/staging/lustre/lustre/llite/xattr_cache.c6
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_intent.c21
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_internal.h14
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_obd.c94
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_dev.c12
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_ea.c7
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_internal.h17
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_lock.c16
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_obd.c75
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_object.c4
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_pool.c9
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_request.c31
-rw-r--r--drivers/staging/lustre/lustre/lov/lovsub_dev.c4
-rw-r--r--drivers/staging/lustre/lustre/lov/lovsub_lock.c4
-rw-r--r--drivers/staging/lustre/lustre/lov/lovsub_object.c4
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_internal.h15
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_request.c116
-rw-r--r--drivers/staging/lustre/lustre/mgc/mgc_request.c46
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_lock.c7
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_object.c12
-rw-r--r--drivers/staging/lustre/lustre/obdclass/class_obd.c2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/genops.c10
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lprocfs_status.c64
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_object.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obd_config.c17
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obd_mount.c17
-rw-r--r--drivers/staging/lustre/lustre/obdecho/echo_client.c32
-rw-r--r--drivers/staging/lustre/lustre/osc/lproc_osc.c4
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_cache.c4
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_dev.c8
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_internal.h6
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_io.c4
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_lock.c4
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_object.c4
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_quota.c10
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_request.c87
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/client.c326
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/connection.c8
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c29
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h3
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c2
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c1
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec.c6
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_config.c4
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c413
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c45
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.h3
-rw-r--r--drivers/staging/media/lirc/lirc_sasem.c2
-rw-r--r--drivers/staging/media/lirc/lirc_serial.c32
-rw-r--r--drivers/staging/media/omap4iss/iss.c45
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c6
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.h4
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.c26
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.h4
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.c24
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.h8
-rw-r--r--drivers/staging/media/omap4iss/iss_regs.h316
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.c28
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c45
-rw-r--r--drivers/staging/media/omap4iss/iss_video.h6
-rw-r--r--drivers/staging/most/aim-cdev/cdev.c14
-rw-r--r--drivers/staging/most/aim-network/networking.c6
-rw-r--r--drivers/staging/most/aim-network/networking.h2
-rw-r--r--drivers/staging/most/aim-sound/sound.c1
-rw-r--r--drivers/staging/most/aim-v4l2/video.c30
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_errors.h2
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hal.c163
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hal.h53
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hdm.c71
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_reg.h5
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_sysfs.h3
-rw-r--r--drivers/staging/most/hdm-i2c/hdm_i2c.c13
-rw-r--r--drivers/staging/most/hdm-usb/hdm_usb.c17
-rw-r--r--drivers/staging/most/mostcore/core.c41
-rw-r--r--drivers/staging/most/mostcore/mostcore.h2
-rw-r--r--drivers/staging/mt29f_spinand/mt29f_spinand.c70
-rw-r--r--drivers/staging/mt29f_spinand/mt29f_spinand.h18
-rw-r--r--drivers/staging/netlogic/platform_net.c1
-rw-r--r--drivers/staging/nvec/README2
-rw-r--r--drivers/staging/nvec/nvec.c21
-rw-r--r--drivers/staging/octeon-usb/octeon-hcd.c6
-rw-r--r--drivers/staging/octeon/ethernet-defines.h3
-rw-r--r--drivers/staging/octeon/ethernet-tx.c2
-rw-r--r--drivers/staging/octeon/ethernet.c2
-rw-r--r--drivers/staging/panel/panel.c49
-rw-r--r--drivers/staging/rdma/amso1100/c2.c17
-rw-r--r--drivers/staging/rdma/amso1100/c2.h80
-rw-r--r--drivers/staging/rdma/amso1100/c2_cm.c3
-rw-r--r--drivers/staging/rdma/amso1100/c2_mq.h14
-rw-r--r--drivers/staging/rdma/amso1100/c2_provider.c12
-rw-r--r--drivers/staging/rdma/amso1100/c2_qp.c8
-rw-r--r--drivers/staging/rdma/amso1100/c2_rnic.c5
-rw-r--r--drivers/staging/rdma/amso1100/c2_vq.h20
-rw-r--r--drivers/staging/rdma/ehca/ehca_av.c3
-rw-r--r--drivers/staging/rdma/ehca/ehca_reqs.c53
-rw-r--r--drivers/staging/rdma/hfi1/chip.c327
-rw-r--r--drivers/staging/rdma/hfi1/chip.h3
-rw-r--r--drivers/staging/rdma/hfi1/common.h19
-rw-r--r--drivers/staging/rdma/hfi1/diag.c27
-rw-r--r--drivers/staging/rdma/hfi1/driver.c292
-rw-r--r--drivers/staging/rdma/hfi1/file_ops.c185
-rw-r--r--drivers/staging/rdma/hfi1/firmware.c35
-rw-r--r--drivers/staging/rdma/hfi1/hfi.h78
-rw-r--r--drivers/staging/rdma/hfi1/init.c88
-rw-r--r--drivers/staging/rdma/hfi1/iowait.h6
-rw-r--r--drivers/staging/rdma/hfi1/keys.c55
-rw-r--r--drivers/staging/rdma/hfi1/mad.c8
-rw-r--r--drivers/staging/rdma/hfi1/mr.c33
-rw-r--r--drivers/staging/rdma/hfi1/pcie.c25
-rw-r--r--drivers/staging/rdma/hfi1/pio.c33
-rw-r--r--drivers/staging/rdma/hfi1/qp.c50
-rw-r--r--drivers/staging/rdma/hfi1/qp.h51
-rw-r--r--drivers/staging/rdma/hfi1/qsfp.c18
-rw-r--r--drivers/staging/rdma/hfi1/rc.c128
-rw-r--r--drivers/staging/rdma/hfi1/ruc.c86
-rw-r--r--drivers/staging/rdma/hfi1/sdma.c210
-rw-r--r--drivers/staging/rdma/hfi1/sdma.h82
-rw-r--r--drivers/staging/rdma/hfi1/trace.c4
-rw-r--r--drivers/staging/rdma/hfi1/trace.h48
-rw-r--r--drivers/staging/rdma/hfi1/uc.c19
-rw-r--r--drivers/staging/rdma/hfi1/ud.c21
-rw-r--r--drivers/staging/rdma/hfi1/user_exp_rcv.h74
-rw-r--r--drivers/staging/rdma/hfi1/user_sdma.c130
-rw-r--r--drivers/staging/rdma/hfi1/user_sdma.h10
-rw-r--r--drivers/staging/rdma/hfi1/verbs.c172
-rw-r--r--drivers/staging/rdma/hfi1/verbs.h65
-rw-r--r--drivers/staging/rdma/ipath/ipath_driver.c8
-rw-r--r--drivers/staging/rdma/ipath/ipath_file_ops.c13
-rw-r--r--drivers/staging/rdma/ipath/ipath_init_chip.c18
-rw-r--r--drivers/staging/rdma/ipath/ipath_intr.c1
-rw-r--r--drivers/staging/rdma/ipath/ipath_kernel.h3
-rw-r--r--drivers/staging/rdma/ipath/ipath_qp.c1
-rw-r--r--drivers/staging/rdma/ipath/ipath_rc.c24
-rw-r--r--drivers/staging/rdma/ipath/ipath_ruc.c17
-rw-r--r--drivers/staging/rdma/ipath/ipath_sdma.c6
-rw-r--r--drivers/staging/rdma/ipath/ipath_uc.c4
-rw-r--r--drivers/staging/rdma/ipath/ipath_ud.c27
-rw-r--r--drivers/staging/rdma/ipath/ipath_user_pages.c1
-rw-r--r--drivers/staging/rdma/ipath/ipath_user_sdma.c1
-rw-r--r--drivers/staging/rdma/ipath/ipath_verbs.c26
-rw-r--r--drivers/staging/rdma/ipath/ipath_verbs.h8
-rw-r--r--drivers/staging/rdma/ipath/ipath_verbs_mcast.c1
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c56
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c100
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_debug.c3
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c54
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ioctl_set.c7
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c27
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c93
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_pwrctrl.c14
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_recv.c6
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_wlan_util.c4
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_xmit.c11
-rw-r--r--drivers/staging/rtl8188eu/hal/bb_cfg.c69
-rw-r--r--drivers/staging/rtl8188eu/hal/fw.c45
-rw-r--r--drivers/staging/rtl8188eu/hal/hal_com.c14
-rw-r--r--drivers/staging/rtl8188eu/hal/mac_cfg.c4
-rw-r--r--drivers/staging/rtl8188eu/hal/odm.c24
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_HWConfig.c6
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_RTL8188E.c122
-rw-r--r--drivers/staging/rtl8188eu/hal/phy.c32
-rw-r--r--drivers/staging/rtl8188eu/hal/rf_cfg.c4
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c22
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_dm.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c34
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_led.c6
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c34
-rw-r--r--drivers/staging/rtl8188eu/hal/usb_halinit.c66
-rw-r--r--drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h14
-rw-r--r--drivers/staging/rtl8188eu/include/HalVerDef.h33
-rw-r--r--drivers/staging/rtl8188eu/include/basic_types.h6
-rw-r--r--drivers/staging/rtl8188eu/include/hal_intf.h16
-rw-r--r--drivers/staging/rtl8188eu/include/odm.h90
-rw-r--r--drivers/staging/rtl8188eu/include/odm_debug.h42
-rw-r--r--drivers/staging/rtl8188eu/include/odm_reg.h2
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_service.h41
-rw-r--r--drivers/staging/rtl8188eu/include/pwrseq.h84
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_spec.h411
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_security.h3
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_sreset.h14
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_xmit.h1
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c28
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mlme_linux.c5
-rw-r--r--drivers/staging/rtl8188eu/os_dep/os_intfs.c10
-rw-r--r--drivers/staging/rtl8188eu/os_dep/osdep_service.c6
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c8
-rw-r--r--drivers/staging/rtl8188eu/os_dep/xmit_linux.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c58
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h4
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c8
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c263
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h19
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c5
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c22
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c76
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c7
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c17
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.c25
-rw-r--r--drivers/staging/rtl8712/hal_init.c11
-rw-r--r--drivers/staging/rtl8712/ieee80211.c36
-rw-r--r--drivers/staging/rtl8712/mlme_linux.c2
-rw-r--r--drivers/staging/rtl8712/os_intfs.c6
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c27
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c138
-rw-r--r--drivers/staging/rtl8712/rtl8712_io.c6
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c187
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c53
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c74
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c25
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.c22
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h8
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c153
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.c53
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c33
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c156
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h2
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c39
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.h1
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.c38
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c70
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c133
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c10
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c95
-rw-r--r--drivers/staging/rtl8712/usb_halinit.c13
-rw-r--r--drivers/staging/rtl8712/usb_intf.c18
-rw-r--r--drivers/staging/rtl8712/usb_ops.c20
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c20
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c4
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ap.c202
-rw-r--r--drivers/staging/rtl8723au/core/rtw_cmd.c16
-rw-r--r--drivers/staging/rtl8723au/core/rtw_efuse.c357
-rw-r--r--drivers/staging/rtl8723au/core/rtw_wlan_util.c2
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_cmd.c3
-rw-r--r--drivers/staging/skein/skein_api.c8
-rw-r--r--drivers/staging/skein/skein_block.c2
-rw-r--r--drivers/staging/slicoss/slic.h23
-rw-r--r--drivers/staging/slicoss/slichw.h38
-rw-r--r--drivers/staging/slicoss/slicoss.c174
-rw-r--r--drivers/staging/sm750fb/ddk750_chip.c64
-rw-r--r--drivers/staging/sm750fb/ddk750_help.h4
-rw-r--r--drivers/staging/sm750fb/ddk750_mode.c3
-rw-r--r--drivers/staging/sm750fb/ddk750_power.c8
-rw-r--r--drivers/staging/sm750fb/modedb.h233
-rw-r--r--drivers/staging/sm750fb/sm750.c378
-rw-r--r--drivers/staging/sm750fb/sm750.h123
-rw-r--r--drivers/staging/sm750fb/sm750_hw.c133
-rw-r--r--drivers/staging/sm750fb/sm750_hw.h98
-rw-r--r--drivers/staging/speakup/buffers.c3
-rw-r--r--drivers/staging/speakup/selection.c2
-rw-r--r--drivers/staging/unisys/include/channel.h114
-rw-r--r--drivers/staging/unisys/include/iochannel.h157
-rw-r--r--drivers/staging/unisys/include/vbushelper.h3
-rw-r--r--drivers/staging/unisys/include/visorbus.h4
-rw-r--r--drivers/staging/unisys/visorbus/Kconfig7
-rw-r--r--drivers/staging/unisys/visorbus/controlvmcompletionstatus.h24
-rw-r--r--drivers/staging/unisys/visorbus/periodic_work.c11
-rw-r--r--drivers/staging/unisys/visorbus/vbuschannel.h9
-rw-r--r--drivers/staging/unisys/visorbus/visorbus_main.c15
-rw-r--r--drivers/staging/unisys/visorbus/visorchannel.c4
-rw-r--r--drivers/staging/unisys/visorbus/vmcallinterface.h34
-rw-r--r--drivers/staging/unisys/visorhba/visorhba_main.c16
-rw-r--r--drivers/staging/unisys/visorinput/Kconfig7
-rw-r--r--drivers/staging/unisys/visorinput/visorinput.c4
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c1
-rw-r--r--drivers/staging/vme/devices/vme_pio2_cntr.c2
-rw-r--r--drivers/staging/vme/devices/vme_pio2_core.c22
-rw-r--r--drivers/staging/vme/devices/vme_pio2_gpio.c32
-rw-r--r--drivers/staging/vme/devices/vme_user.c22
-rw-r--r--drivers/staging/vme/devices/vme_user.h2
-rw-r--r--drivers/staging/vt6655/card.c4
-rw-r--r--drivers/staging/vt6656/baseband.c4
-rw-r--r--drivers/staging/vt6656/baseband.h4
-rw-r--r--drivers/staging/vt6656/card.c6
-rw-r--r--drivers/staging/vt6656/card.h3
-rw-r--r--drivers/staging/vt6656/channel.c4
-rw-r--r--drivers/staging/vt6656/channel.h4
-rw-r--r--drivers/staging/vt6656/desc.h3
-rw-r--r--drivers/staging/vt6656/device.h3
-rw-r--r--drivers/staging/vt6656/dpc.c3
-rw-r--r--drivers/staging/vt6656/dpc.h3
-rw-r--r--drivers/staging/vt6656/firmware.c4
-rw-r--r--drivers/staging/vt6656/firmware.h4
-rw-r--r--drivers/staging/vt6656/int.c4
-rw-r--r--drivers/staging/vt6656/int.h4
-rw-r--r--drivers/staging/vt6656/key.c5
-rw-r--r--drivers/staging/vt6656/key.h4
-rw-r--r--drivers/staging/vt6656/mac.c4
-rw-r--r--drivers/staging/vt6656/mac.h4
-rw-r--r--drivers/staging/vt6656/main_usb.c3
-rw-r--r--drivers/staging/vt6656/power.c12
-rw-r--r--drivers/staging/vt6656/power.h3
-rw-r--r--drivers/staging/vt6656/rf.c4
-rw-r--r--drivers/staging/vt6656/rf.h4
-rw-r--r--drivers/staging/vt6656/rxtx.c3
-rw-r--r--drivers/staging/vt6656/rxtx.h3
-rw-r--r--drivers/staging/vt6656/usbpipe.c4
-rw-r--r--drivers/staging/vt6656/usbpipe.h4
-rw-r--r--drivers/staging/vt6656/wcmd.c3
-rw-r--r--drivers/staging/vt6656/wcmd.h3
-rw-r--r--drivers/staging/wilc1000/Makefile6
-rw-r--r--drivers/staging/wilc1000/coreconfigurator.c20
-rw-r--r--drivers/staging/wilc1000/coreconfigurator.h2
-rw-r--r--drivers/staging/wilc1000/host_interface.c2978
-rw-r--r--drivers/staging/wilc1000/host_interface.h1067
-rw-r--r--drivers/staging/wilc1000/linux_mon.c2
-rw-r--r--drivers/staging/wilc1000/linux_wlan.c1151
-rw-r--r--drivers/staging/wilc1000/linux_wlan_sdio.c42
-rw-r--r--drivers/staging/wilc1000/linux_wlan_sdio.h2
-rw-r--r--drivers/staging/wilc1000/linux_wlan_spi.c2
-rw-r--r--drivers/staging/wilc1000/linux_wlan_spi.h2
-rw-r--r--drivers/staging/wilc1000/wilc_msgqueue.c25
-rw-r--r--drivers/staging/wilc1000/wilc_sdio.c91
-rw-r--r--drivers/staging/wilc1000/wilc_spi.c164
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c345
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.h2
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_netdevice.h30
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.c964
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.h332
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_cfg.c2
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_cfg.h2
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_if.h26
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c15
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c34
-rw-r--r--drivers/staging/wlan-ng/p80211meta.h90
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h1
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.h1
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c5
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c21
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c8
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c6
-rw-r--r--drivers/staging/xgifb/vb_init.c103
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c791
-rw-r--r--drivers/target/iscsi/iscsi_target_stat.c666
-rw-r--r--drivers/target/loopback/tcm_loop.c61
-rw-r--r--drivers/target/sbp/sbp_target.c87
-rw-r--r--drivers/target/target_core_configfs.c1209
-rw-r--r--drivers/target/target_core_fabric_configfs.c275
-rw-r--r--drivers/target/target_core_iblock.c10
-rw-r--r--drivers/target/target_core_internal.h3
-rw-r--r--drivers/target/target_core_stat.c918
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c1
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c44
-rw-r--r--drivers/target/tcm_fc/tfc_io.c1
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c1
-rw-r--r--drivers/thermal/Kconfig17
-rw-r--r--drivers/thermal/Makefile3
-rw-r--r--drivers/thermal/armada_thermal.c6
-rw-r--r--drivers/thermal/cpu_cooling.c8
-rw-r--r--drivers/thermal/devfreq_cooling.c573
-rw-r--r--drivers/thermal/imx_thermal.c21
-rw-r--r--drivers/thermal/power_allocator.c2
-rw-r--r--drivers/thermal/rockchip_thermal.c43
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c70
-rw-r--r--drivers/thermal/ti-soc-thermal/Kconfig15
-rw-r--r--drivers/thermal/ti-soc-thermal/Makefile1
-rw-r--r--drivers/thermal/ti-soc-thermal/omap3-thermal-data.c176
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c14
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.h11
-rw-r--r--drivers/tty/cyclades.c9
-rw-r--r--drivers/tty/hvc/Kconfig2
-rw-r--r--drivers/tty/hvc/hvc_console.c20
-rw-r--r--drivers/tty/hvc/hvc_dcc.c15
-rw-r--r--drivers/tty/hvc/hvc_iucv.c10
-rw-r--r--drivers/tty/hvc/hvc_xen.c4
-rw-r--r--drivers/tty/hvc/hvcs.c2
-rw-r--r--drivers/tty/mips_ejtag_fdc.c39
-rw-r--r--drivers/tty/n_r3964.c28
-rw-r--r--drivers/tty/n_tracerouter.c2
-rw-r--r--drivers/tty/n_tracesink.c2
-rw-r--r--drivers/tty/n_tty.c34
-rw-r--r--drivers/tty/pty.c7
-rw-r--r--drivers/tty/rocket.c13
-rw-r--r--drivers/tty/serial/68328serial.c5
-rw-r--r--drivers/tty/serial/8250/8250_core.c26
-rw-r--r--drivers/tty/serial/8250/8250_dma.c10
-rw-r--r--drivers/tty/serial/8250/8250_dw.c292
-rw-r--r--drivers/tty/serial/8250/8250_early.c4
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c1
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c88
-rw-r--r--drivers/tty/serial/8250/8250_mid.c326
-rw-r--r--drivers/tty/serial/8250/8250_omap.c8
-rw-r--r--drivers/tty/serial/8250/8250_pci.c229
-rw-r--r--drivers/tty/serial/8250/8250_port.c86
-rw-r--r--drivers/tty/serial/8250/Kconfig26
-rw-r--r--drivers/tty/serial/8250/Makefile1
-rw-r--r--drivers/tty/serial/Kconfig12
-rw-r--r--drivers/tty/serial/altera_uart.c26
-rw-r--r--drivers/tty/serial/amba-pl011.c4
-rw-r--r--drivers/tty/serial/apbuart.c1
-rw-r--r--drivers/tty/serial/atmel_serial.c27
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c2
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c1
-rw-r--r--drivers/tty/serial/crisv10.c34
-rw-r--r--drivers/tty/serial/etraxfs-uart.c2
-rw-r--r--drivers/tty/serial/fsl_lpuart.c39
-rw-r--r--drivers/tty/serial/ifx6x60.c2
-rw-r--r--drivers/tty/serial/imx.c175
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c7
-rw-r--r--drivers/tty/serial/max3100.c1
-rw-r--r--drivers/tty/serial/max310x.c1
-rw-r--r--drivers/tty/serial/men_z135_uart.c23
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c7
-rw-r--r--drivers/tty/serial/mpsc.c41
-rw-r--r--drivers/tty/serial/msm_serial.c622
-rw-r--r--drivers/tty/serial/msm_serial.h53
-rw-r--r--drivers/tty/serial/mux.c9
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/of_serial.c10
-rw-r--r--drivers/tty/serial/omap-serial.c2
-rw-r--r--drivers/tty/serial/samsung.c66
-rw-r--r--drivers/tty/serial/sc16is7xx.c8
-rw-r--r--drivers/tty/serial/serial-tegra.c94
-rw-r--r--drivers/tty/serial/serial_core.c9
-rw-r--r--drivers/tty/serial/serial_mctrl_gpio.c133
-rw-r--r--drivers/tty/serial/serial_mctrl_gpio.h40
-rw-r--r--drivers/tty/serial/sh-sci.c1192
-rw-r--r--drivers/tty/serial/sh-sci.h49
-rw-r--r--drivers/tty/serial/sprd_serial.c1
-rw-r--r--drivers/tty/serial/st-asc.c2
-rw-r--r--drivers/tty/serial/stm32-usart.c3
-rw-r--r--drivers/tty/synclink.c20
-rw-r--r--drivers/tty/synclink_gt.c14
-rw-r--r--drivers/tty/synclinkmp.c14
-rw-r--r--drivers/tty/sysrq.c6
-rw-r--r--drivers/tty/tty_audit.c2
-rw-r--r--drivers/tty/tty_buffer.c12
-rw-r--r--drivers/tty/tty_io.c63
-rw-r--r--drivers/tty/tty_ioctl.c4
-rw-r--r--drivers/tty/tty_ldisc.c4
-rw-r--r--drivers/tty/tty_port.c28
-rw-r--r--drivers/uio/uio.c1
-rw-r--r--drivers/uio/uio_fsl_elbc_gpcm.c1
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/chipidea/Kconfig1
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c153
-rw-r--r--drivers/usb/chipidea/ci_hdrc_pci.c6
-rw-r--r--drivers/usb/chipidea/core.c136
-rw-r--r--drivers/usb/chipidea/debug.c2
-rw-r--r--drivers/usb/chipidea/otg.c48
-rw-r--r--drivers/usb/chipidea/udc.c17
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c76
-rw-r--r--drivers/usb/class/usblp.c2
-rw-r--r--drivers/usb/common/common.c59
-rw-r--r--drivers/usb/core/Kconfig3
-rw-r--r--drivers/usb/core/config.c4
-rw-r--r--drivers/usb/core/driver.c14
-rw-r--r--drivers/usb/core/hcd.c110
-rw-r--r--drivers/usb/core/hub.c87
-rw-r--r--drivers/usb/core/message.c41
-rw-r--r--drivers/usb/core/sysfs.c36
-rw-r--r--drivers/usb/core/urb.c3
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--drivers/usb/dwc2/core.c478
-rw-r--r--drivers/usb/dwc2/core.h107
-rw-r--r--drivers/usb/dwc2/core_intr.c106
-rw-r--r--drivers/usb/dwc2/debugfs.c72
-rw-r--r--drivers/usb/dwc2/gadget.c1422
-rw-r--r--drivers/usb/dwc2/hcd.c353
-rw-r--r--drivers/usb/dwc2/hcd.h15
-rw-r--r--drivers/usb/dwc2/hcd_ddma.c10
-rw-r--r--drivers/usb/dwc2/hcd_intr.c152
-rw-r--r--drivers/usb/dwc2/hcd_queue.c21
-rw-r--r--drivers/usb/dwc2/hw.h1
-rw-r--r--drivers/usb/dwc2/platform.c239
-rw-r--r--drivers/usb/dwc3/core.c104
-rw-r--r--drivers/usb/dwc3/core.h27
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c43
-rw-r--r--drivers/usb/dwc3/dwc3-st.c12
-rw-r--r--drivers/usb/dwc3/gadget.c124
-rw-r--r--drivers/usb/dwc3/platform_data.h3
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/composite.c6
-rw-r--r--drivers/usb/gadget/configfs.c295
-rw-r--r--drivers/usb/gadget/epautoconf.c25
-rw-r--r--drivers/usb/gadget/function/f_acm.c49
-rw-r--r--drivers/usb/gadget/function/f_ecm.c39
-rw-r--r--drivers/usb/gadget/function/f_eem.c24
-rw-r--r--drivers/usb/gadget/function/f_hid.c46
-rw-r--r--drivers/usb/gadget/function/f_loopback.c193
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c133
-rw-r--r--drivers/usb/gadget/function/f_midi.c63
-rw-r--r--drivers/usb/gadget/function/f_ncm.c37
-rw-r--r--drivers/usb/gadget/function/f_obex.c36
-rw-r--r--drivers/usb/gadget/function/f_phonet.c33
-rw-r--r--drivers/usb/gadget/function/f_printer.c32
-rw-r--r--drivers/usb/gadget/function/f_rndis.c32
-rw-r--r--drivers/usb/gadget/function/f_serial.c36
-rw-r--r--drivers/usb/gadget/function/f_sourcesink.c250
-rw-r--r--drivers/usb/gadget/function/f_subset.c18
-rw-r--r--drivers/usb/gadget/function/f_uac1.c43
-rw-r--r--drivers/usb/gadget/function/f_uac2.c39
-rw-r--r--drivers/usb/gadget/function/f_uvc.c42
-rw-r--r--drivers/usb/gadget/function/u_ether.c11
-rw-r--r--drivers/usb/gadget/function/u_ether_configfs.h44
-rw-r--r--drivers/usb/gadget/function/u_serial.c11
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c387
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c28
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h4
-rw-r--r--drivers/usb/gadget/legacy/dbgp.c18
-rw-r--r--drivers/usb/gadget/legacy/tcm_usb_gadget.c62
-rw-r--r--drivers/usb/gadget/udc/Kconfig2
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.c609
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.h5
-rw-r--r--drivers/usb/gadget/udc/at91_udc.h8
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c6
-rw-r--r--drivers/usb/gadget/udc/net2280.c2
-rw-r--r--drivers/usb/gadget/udc/pch_udc.c10
-rw-r--r--drivers/usb/host/Kconfig10
-rw-r--r--drivers/usb/host/Makefile6
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-msm.c6
-rw-r--r--drivers/usb/host/ehci-orion.c3
-rw-r--r--drivers/usb/host/ehci-platform.c12
-rw-r--r--drivers/usb/host/ehci-spear.c1
-rw-r--r--drivers/usb/host/fotg210-hcd.c1962
-rw-r--r--drivers/usb/host/fotg210.h36
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c1
-rw-r--r--drivers/usb/host/fusbh200-hcd.c5894
-rw-r--r--drivers/usb/host/fusbh200.h675
-rw-r--r--drivers/usb/host/max3421-hcd.c1
-rw-r--r--drivers/usb/host/ohci-nxp.c18
-rw-r--r--drivers/usb/host/ohci-spear.c1
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c2
-rw-r--r--drivers/usb/host/u132-hcd.c5
-rw-r--r--drivers/usb/host/uhci-platform.c1
-rw-r--r--drivers/usb/host/whci/init.c3
-rw-r--r--drivers/usb/host/xhci-dbg.c17
-rw-r--r--drivers/usb/host/xhci-hub.c198
-rw-r--r--drivers/usb/host/xhci-mem.c50
-rw-r--r--drivers/usb/host/xhci-pci.c7
-rw-r--r--drivers/usb/host/xhci-plat.c29
-rw-r--r--drivers/usb/host/xhci-ring.c184
-rw-r--r--drivers/usb/host/xhci.c37
-rw-r--r--drivers/usb/host/xhci.h71
-rw-r--r--drivers/usb/misc/usb3503.c2
-rw-r--r--drivers/usb/misc/usbtest.c156
-rw-r--r--drivers/usb/musb/musb_core.c41
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/musb_dsps.c15
-rw-r--r--drivers/usb/musb/musb_host.c22
-rw-r--r--drivers/usb/musb/omap2430.c29
-rw-r--r--drivers/usb/musb/sunxi.c14
-rw-r--r--drivers/usb/phy/Kconfig4
-rw-r--r--drivers/usb/phy/phy-msm-usb.c2
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c7
-rw-r--r--drivers/usb/phy/phy-omap-otg.c2
-rw-r--r--drivers/usb/phy/phy-qcom-8x16-usb.c21
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c2
-rw-r--r--drivers/usb/renesas_usbhs/rcar2.c1
-rw-r--r--drivers/usb/serial/io_ti.c530
-rw-r--r--drivers/usb/serial/option.c75
-rw-r--r--drivers/usb/serial/qcserial.c109
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h4
-rw-r--r--drivers/usb/serial/usb-wwan.h2
-rw-r--r--drivers/usb/serial/usb_wwan.c42
-rw-r--r--drivers/usb/storage/isd200.c30
-rw-r--r--drivers/usb/storage/uas.c21
-rw-r--r--drivers/usb/usbip/vhci_hcd.c8
-rw-r--r--drivers/uwb/drp.c4
-rw-r--r--drivers/uwb/neh.c4
-rw-r--r--drivers/uwb/rsv.c9
-rw-r--r--drivers/uwb/uwb-debug.c2
-rw-r--r--drivers/vfio/Kconfig16
-rw-r--r--drivers/vfio/pci/Kconfig1
-rw-r--r--drivers/vfio/pci/vfio_pci.c8
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c74
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c9
-rw-r--r--drivers/vfio/pci/vfio_pci_private.h2
-rw-r--r--drivers/vfio/platform/Makefile6
-rw-r--r--drivers/vfio/platform/reset/Kconfig8
-rw-r--r--drivers/vfio/platform/reset/Makefile2
-rw-r--r--drivers/vfio/platform/reset/vfio_platform_amdxgbe.c127
-rw-r--r--drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c19
-rw-r--r--drivers/vfio/platform/vfio_amba.c1
-rw-r--r--drivers/vfio/platform/vfio_platform.c1
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c155
-rw-r--r--drivers/vfio/platform/vfio_platform_irq.c1
-rw-r--r--drivers/vfio/platform/vfio_platform_private.h40
-rw-r--r--drivers/vfio/vfio.c224
-rw-r--r--drivers/vfio/vfio_iommu_type1.c15
-rw-r--r--drivers/vhost/scsi.c41
-rw-r--r--drivers/vhost/vhost.h7
-rw-r--r--drivers/video/backlight/88pm860x_bl.c1
-rw-r--r--drivers/video/backlight/adp8860_bl.c1
-rw-r--r--drivers/video/backlight/adp8870_bl.c1
-rw-r--r--drivers/video/backlight/ams369fg06.c1
-rw-r--r--drivers/video/backlight/corgi_lcd.c1
-rw-r--r--drivers/video/backlight/ili922x.c1
-rw-r--r--drivers/video/backlight/l4f00242t03.c1
-rw-r--r--drivers/video/backlight/ld9040.c1
-rw-r--r--drivers/video/backlight/lms283gf05.c1
-rw-r--r--drivers/video/backlight/lms501kf03.c1
-rw-r--r--drivers/video/backlight/lp855x_bl.c1
-rw-r--r--drivers/video/backlight/ltv350qv.c1
-rw-r--r--drivers/video/backlight/pm8941-wled.c13
-rw-r--r--drivers/video/backlight/pwm_bl.c19
-rw-r--r--drivers/video/backlight/s6e63m0.c1
-rw-r--r--drivers/video/backlight/tdo24m.c1
-rw-r--r--drivers/video/backlight/tosa_lcd.c1
-rw-r--r--drivers/video/backlight/vgg2432a4.c1
-rw-r--r--drivers/video/console/fbcon.c1
-rw-r--r--drivers/video/fbdev/Kconfig7
-rw-r--r--drivers/video/fbdev/aty/radeon_base.c133
-rw-r--r--drivers/video/fbdev/aty/radeonfb.h144
-rw-r--r--drivers/video/fbdev/core/fb_ddc.c28
-rw-r--r--drivers/video/fbdev/efifb.c24
-rw-r--r--drivers/video/fbdev/gxt4500.c25
-rw-r--r--drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c1
-rw-r--r--drivers/video/fbdev/omap/lcd_mipid.c1
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c5
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c1
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c1
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c1
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c1
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c1
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi.h9
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4.c66
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5.c75
-rw-r--r--drivers/video/fbdev/ssd1307fb.c21
-rw-r--r--drivers/video/fbdev/tridentfb.c182
-rw-r--r--drivers/video/fbdev/vermilion/vermilion.c2
-rw-r--r--drivers/vme/vme_bridge.h4
-rw-r--r--drivers/w1/masters/omap_hdq.c224
-rw-r--r--drivers/w1/masters/w1-gpio.c20
-rw-r--r--drivers/w1/slaves/w1_bq27000.c5
-rw-r--r--drivers/w1/w1_int.c3
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/bcm7038_wdt.c237
-rw-r--r--drivers/watchdog/diag288_wdt.c4
-rw-r--r--drivers/watchdog/imx2_wdt.c6
-rw-r--r--drivers/watchdog/intel-mid_wdt.c2
-rw-r--r--drivers/watchdog/watchdog_core.c15
-rw-r--r--drivers/watchdog/watchdog_dev.c163
-rw-r--r--drivers/xen/Makefile2
-rw-r--r--drivers/xen/balloon.c341
-rw-r--r--drivers/xen/biomerge.c8
-rw-r--r--drivers/xen/cpu_hotplug.c14
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--drivers/xen/events/events_fifo.c2
-rw-r--r--drivers/xen/grant-table.c56
-rw-r--r--drivers/xen/privcmd.c10
-rw-r--r--drivers/xen/swiotlb-xen.c43
-rw-r--r--drivers/xen/xen-scsiback.c32
-rw-r--r--drivers/xen/xenbus/xenbus_client.c128
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c3
-rw-r--r--drivers/xen/xlate_mmu.c124
4421 files changed, 298866 insertions, 133977 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 46b4a8e0f859..d2ac339de85f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -18,6 +18,8 @@ source "drivers/pnp/Kconfig"
source "drivers/block/Kconfig"
+source "drivers/nvme/Kconfig"
+
# misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4
source "drivers/misc/Kconfig"
@@ -42,6 +44,8 @@ source "drivers/net/Kconfig"
source "drivers/isdn/Kconfig"
+source "drivers/lightnvm/Kconfig"
+
# input before char - char/joystick depends on it. As does USB.
source "drivers/input/Kconfig"
@@ -188,4 +192,10 @@ source "drivers/nvdimm/Kconfig"
source "drivers/nvmem/Kconfig"
+source "drivers/hwtracing/stm/Kconfig"
+
+source "drivers/hwtracing/intel_th/Kconfig"
+
+source "drivers/fpga/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index b250b36b54f2..73d039156ea7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -70,6 +70,8 @@ obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_SCSI) += scsi/
+obj-$(CONFIG_NVM) += lightnvm/
+obj-y += nvme/
obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
@@ -165,5 +167,8 @@ obj-$(CONFIG_PERF_EVENTS) += perf/
obj-$(CONFIG_RAS) += ras/
obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/
+obj-y += hwtracing/intel_th/
+obj-$(CONFIG_STM) += hwtracing/stm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_NVMEM) += nvmem/
+obj-$(CONFIG_FPGA) += fpga/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5d1015c26ff4..25dbb76c02cc 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -57,6 +57,15 @@ config ACPI_SYSTEM_POWER_STATES_SUPPORT
config ACPI_CCA_REQUIRED
bool
+config ACPI_DEBUGGER
+ bool "In-kernel debugger (EXPERIMENTAL)"
+ select ACPI_DEBUG
+ help
+ Enable in-kernel debugging facilities: statistics, internal
+ object dump, single step control method execution.
+ This is still under development, currently enabling this only
+ results in the compilation of the ACPICA debugger files.
+
config ACPI_SLEEP
bool
depends on SUSPEND || HIBERNATION
@@ -197,11 +206,25 @@ config ACPI_PROCESSOR_IDLE
bool
select CPU_IDLE
+config ACPI_CPPC_LIB
+ bool
+ depends on ACPI_PROCESSOR
+ depends on !ACPI_CPU_FREQ_PSS
+ select MAILBOX
+ select PCC
+ help
+ If this option is enabled, this file implements common functionality
+ to parse CPPC tables as described in the ACPI 5.1+ spec. The
+ routines implemented are meant to be used by other
+ drivers to control CPU performance using CPPC semantics.
+ If your platform does not support CPPC in firmware,
+ leave this option disabled.
+
config ACPI_PROCESSOR
tristate "Processor"
- depends on X86 || IA64
- select ACPI_PROCESSOR_IDLE
- select ACPI_CPU_FREQ_PSS
+ depends on X86 || IA64 || ARM64
+ select ACPI_PROCESSOR_IDLE if X86 || IA64
+ select ACPI_CPU_FREQ_PSS if X86 || IA64
default y
help
This driver adds support for the ACPI Processor package. It is required
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index b5e7cd8a9c71..675eaf337178 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
+obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index f51bd0d0bc17..f9e0d09f7c66 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -664,7 +664,7 @@ static struct dev_pm_domain acpi_lpss_pm_domain = {
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
.prepare = acpi_subsys_prepare,
- .complete = acpi_subsys_complete,
+ .complete = pm_complete_with_resume_check,
.suspend = acpi_subsys_suspend,
.suspend_late = acpi_lpss_suspend_late,
.resume_early = acpi_lpss_resume_early,
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index ae307ff36acb..8ea8211b2d58 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -148,8 +148,6 @@ static int power_saving_thread(void *data)
while (!kthread_should_stop()) {
unsigned long expire_time;
- try_to_freeze();
-
/* round robin to cpus */
expire_time = last_jiffies + round_robin_time * HZ;
if (time_before(expire_time, jiffies)) {
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 06a67d5f2846..296b7a14893a 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -103,7 +103,12 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
pdevinfo.res = resources;
pdevinfo.num_res = count;
pdevinfo.fwnode = acpi_fwnode_handle(adev);
- pdevinfo.dma_mask = acpi_check_dma(adev, NULL) ? DMA_BIT_MASK(32) : 0;
+
+ if (acpi_dma_supported(adev))
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+ else
+ pdevinfo.dma_mask = 0;
+
pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev))
dev_err(&adev->dev, "platform device creation failed: %ld\n",
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index c58940b231d6..48fc3ad13a4b 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -316,7 +316,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{""},
};
-static bool matching_id(char *idstr, char *list_id)
+static bool matching_id(const char *idstr, const char *list_id)
{
int i;
@@ -333,7 +333,7 @@ static bool matching_id(char *idstr, char *list_id)
return true;
}
-static bool acpi_pnp_match(char *idstr, const struct acpi_device_id **matchid)
+static bool acpi_pnp_match(const char *idstr, const struct acpi_device_id **matchid)
{
const struct acpi_device_id *devid;
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 985b8a83184e..6979186dbd4b 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -164,6 +164,24 @@ static int acpi_processor_errata(void)
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_HOTPLUG_CPU
+int __weak acpi_map_cpu(acpi_handle handle,
+ phys_cpuid_t physid, int *pcpu)
+{
+ return -ENODEV;
+}
+
+int __weak acpi_unmap_cpu(int cpu)
+{
+ return -ENODEV;
+}
+
+int __weak arch_register_cpu(int cpu)
+{
+ return -ENODEV;
+}
+
+void __weak arch_unregister_cpu(int cpu) {}
+
static int acpi_processor_hotadd_init(struct acpi_processor *pr)
{
unsigned long long sta;
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 5778e8e4313a..3405f7a41e25 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -77,6 +77,12 @@ module_param(allow_duplicates, bool, 0644);
static int disable_backlight_sysfs_if = -1;
module_param(disable_backlight_sysfs_if, int, 0444);
+static bool device_id_scheme = false;
+module_param(device_id_scheme, bool, 0444);
+
+static bool only_lcd = false;
+module_param(only_lcd, bool, 0444);
+
static int register_count;
static DEFINE_MUTEX(register_count_mutex);
static struct mutex video_list_lock;
@@ -394,6 +400,18 @@ static int video_disable_backlight_sysfs_if(
return 0;
}
+static int video_set_device_id_scheme(const struct dmi_system_id *d)
+{
+ device_id_scheme = true;
+ return 0;
+}
+
+static int video_enable_only_lcd(const struct dmi_system_id *d)
+{
+ only_lcd = true;
+ return 0;
+}
+
static struct dmi_system_id video_dmi_table[] = {
/*
* Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -455,6 +473,33 @@ static struct dmi_system_id video_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"),
},
},
+ /*
+ * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
+ * but the IDs actually follow the Device ID Scheme.
+ */
+ {
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=104121 */
+ .callback = video_set_device_id_scheme,
+ .ident = "ESPRIMO Mobile M9410",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile M9410"),
+ },
+ },
+ /*
+ * Some machines have multiple video output devices, but only the one
+ * that is the type of LCD can do the backlight control so we should not
+ * register backlight interface for other video output devices.
+ */
+ {
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=104121 */
+ .callback = video_enable_only_lcd,
+ .ident = "ESPRIMO Mobile M9410",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile M9410"),
+ },
+ },
{}
};
@@ -1003,7 +1048,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
attribute = acpi_video_get_device_attr(video, device_id);
- if (attribute && attribute->device_id_scheme) {
+ if (attribute && (attribute->device_id_scheme || device_id_scheme)) {
switch (attribute->display_type) {
case ACPI_VIDEO_DISPLAY_CRT:
data->flags.crt = 1;
@@ -1568,15 +1613,6 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
static int count;
char *name;
- /*
- * Do not create backlight device for video output
- * device that is not in the enumerated list.
- */
- if (!acpi_video_device_in_dod(device)) {
- dev_dbg(&device->dev->dev, "not in _DOD list, ignore\n");
- return;
- }
-
result = acpi_video_init_brightness(device);
if (result)
return;
@@ -1657,6 +1693,22 @@ static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video)
mutex_unlock(&video->device_list_lock);
}
+static bool acpi_video_should_register_backlight(struct acpi_video_device *dev)
+{
+ /*
+ * Do not create backlight device for video output
+ * device that is not in the enumerated list.
+ */
+ if (!acpi_video_device_in_dod(dev)) {
+ dev_dbg(&dev->dev->dev, "not in _DOD list, ignore\n");
+ return false;
+ }
+
+ if (only_lcd)
+ return dev->flags.lcd;
+ return true;
+}
+
static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
{
struct acpi_video_device *dev;
@@ -1670,8 +1722,10 @@ static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
return 0;
mutex_lock(&video->device_list_lock);
- list_for_each_entry(dev, &video->video_device_list, entry)
- acpi_video_dev_register_backlight(dev);
+ list_for_each_entry(dev, &video->video_device_list, entry) {
+ if (acpi_video_should_register_backlight(dev))
+ acpi_video_dev_register_backlight(dev);
+ }
mutex_unlock(&video->device_list_lock);
video->backlight_registered = true;
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index fedcc16b56cc..885936f79542 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -123,7 +123,6 @@ acpi-y += \
rsaddr.o \
rscalc.o \
rscreate.o \
- rsdump.o \
rsdumpinfo.o \
rsinfo.o \
rsio.o \
@@ -178,7 +177,24 @@ acpi-y += \
utxferror.o \
utxfmutex.o
+acpi-$(CONFIG_ACPI_DEBUGGER) += \
+ dbcmds.o \
+ dbconvert.o \
+ dbdisply.o \
+ dbexec.o \
+ dbhistry.o \
+ dbinput.o \
+ dbmethod.o \
+ dbnames.o \
+ dbobject.o \
+ dbstats.o \
+ dbutils.o \
+ dbxface.o \
+ rsdump.o \
+
acpi-$(ACPI_FUTURE_USAGE) += \
+ dbfileio.o \
+ dbtest.o \
utcache.o \
utfileio.o \
utprint.o \
diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h
index e9f0833e818d..e4cc48fbf4ee 100644
--- a/drivers/acpi/acpica/acapps.h
+++ b/drivers/acpi/acpica/acapps.h
@@ -88,7 +88,7 @@
acpi_os_printf (" %-18s%s\n", name, description);
#define FILE_SUFFIX_DISASSEMBLY "dsl"
-#define ACPI_TABLE_FILE_SUFFIX ".dat"
+#define FILE_SUFFIX_BINARY_TABLE ".dat" /* Needs the dot */
/*
* getopt
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index eb2e926d8218..c928ba494c40 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -44,6 +44,12 @@
#ifndef __ACDEBUG_H__
#define __ACDEBUG_H__
+/* The debugger is used in conjunction with the disassembler most of time */
+
+#ifdef ACPI_DISASSEMBLER
+#include "acdisasm.h"
+#endif
+
#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
struct acpi_db_command_info {
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 09f37b516808..faa97604d878 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -61,6 +61,7 @@ ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header);
ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX);
+ACPI_INIT_GLOBAL(u32, acpi_gbl_fadt_index, ACPI_INVALID_TABLE_INDEX);
#if (!ACPI_REDUCED_HARDWARE)
ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS);
@@ -324,9 +325,9 @@ ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list);
#ifdef ACPI_DEBUGGER
-ACPI_INIT_GLOBAL(u8, acpi_gbl_db_terminate_threads, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE);
+ACPI_INIT_GLOBAL(acpi_thread_id, acpi_gbl_db_thread_id, ACPI_INVALID_THREAD_ID);
ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_ini_methods);
ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_region_support);
@@ -336,6 +337,8 @@ ACPI_GLOBAL(char *, acpi_gbl_db_filename);
ACPI_GLOBAL(u32, acpi_gbl_db_debug_level);
ACPI_GLOBAL(u32, acpi_gbl_db_console_debug_level);
ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_db_scope_node);
+ACPI_GLOBAL(u8, acpi_gbl_db_terminate_loop);
+ACPI_GLOBAL(u8, acpi_gbl_db_threads_terminated);
ACPI_GLOBAL(char *, acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]);
ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]);
@@ -357,6 +360,9 @@ ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc);
ACPI_GLOBAL(u32, acpi_gbl_num_nodes);
ACPI_GLOBAL(u32, acpi_gbl_num_objects);
+ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_ready);
+ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_complete);
+
#endif /* ACPI_DEBUGGER */
/*****************************************************************************
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h
index e820ed8f173f..e9e936e78154 100644
--- a/drivers/acpi/acpica/acinterp.h
+++ b/drivers/acpi/acpica/acinterp.h
@@ -397,12 +397,10 @@ void
acpi_ex_dump_operands(union acpi_operand_object **operands,
const char *opcode_name, u32 num_opcodes);
-#ifdef ACPI_FUTURE_USAGE
void
acpi_ex_dump_object_descriptor(union acpi_operand_object *object, u32 flags);
void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags);
-#endif /* ACPI_FUTURE_USAGE */
/*
* exnames - AML namestring support
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 6f708267ad8c..e1dd784d8515 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -83,10 +83,8 @@ union acpi_parse_object;
#define ACPI_MTX_EVENTS 3 /* Data for ACPI events */
#define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */
#define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */
-#define ACPI_MTX_DEBUG_CMD_COMPLETE 6 /* AML debugger */
-#define ACPI_MTX_DEBUG_CMD_READY 7 /* AML debugger */
-#define ACPI_MAX_MUTEX 7
+#define ACPI_MAX_MUTEX 5
#define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1
/* Lock structure for reader/writer interfaces */
@@ -111,6 +109,14 @@ struct acpi_rw_lock {
#define ACPI_MUTEX_NOT_ACQUIRED (acpi_thread_id) 0
+/* This Thread ID means an invalid thread ID */
+
+#ifdef ACPI_OS_INVALID_THREAD_ID
+#define ACPI_INVALID_THREAD_ID ACPI_OS_INVALID_THREAD_ID
+#else
+#define ACPI_INVALID_THREAD_ID ((acpi_thread_id) 0xFFFFFFFF)
+#endif
+
/* Table for the global mutexes */
struct acpi_mutex_info {
@@ -287,13 +293,17 @@ acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
#define ACPI_BTYPE_BUFFER_FIELD 0x00002000
#define ACPI_BTYPE_DDB_HANDLE 0x00004000
#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000
-#define ACPI_BTYPE_REFERENCE 0x00010000
+#define ACPI_BTYPE_REFERENCE_OBJECT 0x00010000 /* From Index(), ref_of(), etc (type6_opcodes) */
#define ACPI_BTYPE_RESOURCE 0x00020000
+#define ACPI_BTYPE_NAMED_REFERENCE 0x00040000 /* Generic unresolved Name or Namepath */
#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER)
#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE)
-#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE)
+
+ /* Used by Copy, de_ref_of, Store, Printf, Fprintf */
+
+#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE_OBJECT | ACPI_BTYPE_DDB_HANDLE)
#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR)
#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */
#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF
@@ -848,7 +858,7 @@ struct acpi_parse_state {
#define ACPI_PARSEOP_PARAMLIST 0x02
#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
#define ACPI_PARSEOP_PREDEF_CHECKED 0x08
-#define ACPI_PARSEOP_SPECIAL 0x10
+#define ACPI_PARSEOP_CLOSING_PAREN 0x10
#define ACPI_PARSEOP_COMPOUND 0x20
#define ACPI_PARSEOP_ASSIGNMENT 0x40
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index ea0d9076d408..5d261c942a0d 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -193,9 +193,7 @@ acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
/*
* nsdump - Namespace dump/print utilities
*/
-#ifdef ACPI_FUTURE_USAGE
void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth);
-#endif /* ACPI_FUTURE_USAGE */
void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level);
@@ -208,7 +206,6 @@ acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
-#ifdef ACPI_FUTURE_USAGE
void
acpi_ns_dump_objects(acpi_object_type type,
u8 display_type,
@@ -220,7 +217,6 @@ acpi_ns_dump_object_paths(acpi_object_type type,
u8 display_type,
u32 max_depth,
acpi_owner_id owner_id, acpi_handle start_handle);
-#endif /* ACPI_FUTURE_USAGE */
/*
* nseval - Namespace evaluation functions
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h
index fd85ad05a24a..f9acf92fa0bc 100644
--- a/drivers/acpi/acpica/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
@@ -211,7 +211,7 @@
#define ARGI_ARG4 ARG_NONE
#define ARGI_ARG5 ARG_NONE
#define ARGI_ARG6 ARG_NONE
-#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE
+#define ARGI_BANK_FIELD_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
@@ -307,7 +307,7 @@
#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE
-#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_TARGETREF)
+#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_STORE_TARGET)
#define ARGI_STRING_OP ARGI_INVALID_OPCODE
#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index 6021ccfb0b1c..8fc8c7cea879 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -194,10 +194,8 @@ union acpi_parse_object *acpi_ps_find(union acpi_parse_object *scope,
union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn);
-#ifdef ACPI_FUTURE_USAGE
union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
union acpi_parse_object *op);
-#endif /* ACPI_FUTURE_USAGE */
/*
* pswalk - parse tree walk routines
@@ -235,9 +233,7 @@ void acpi_ps_free_op(union acpi_parse_object *op);
u8 acpi_ps_is_leading_char(u32 c);
-#ifdef ACPI_FUTURE_USAGE
u32 acpi_ps_get_name(union acpi_parse_object *op);
-#endif /* ACPI_FUTURE_USAGE */
void acpi_ps_set_name(union acpi_parse_object *op, u32 name);
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index f7731f260c31..591ea95319e2 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -85,7 +85,7 @@ void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
/*
* tbfadt - FADT parse/convert/validate
*/
-void acpi_tb_parse_fadt(u32 table_index);
+void acpi_tb_parse_fadt(void);
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length);
@@ -138,8 +138,6 @@ acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id);
*/
acpi_status acpi_tb_initialize_facs(void);
-u8 acpi_tb_tables_loaded(void);
-
void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header);
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index fb2aa5066f3f..8b8fef6cc32d 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -635,9 +635,7 @@ void
acpi_ut_free_and_track(void *address,
u32 component, const char *module, u32 line);
-#ifdef ACPI_FUTURE_USAGE
void acpi_ut_dump_allocation_info(void);
-#endif /* ACPI_FUTURE_USAGE */
void acpi_ut_dump_allocations(u32 component, const char *module);
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h
index be9fd009cb28..883f20cfa698 100644
--- a/drivers/acpi/acpica/amlcode.h
+++ b/drivers/acpi/acpica/amlcode.h
@@ -277,14 +277,15 @@
#define ARGI_TARGETREF 0x0F /* Target, subject to implicit conversion */
#define ARGI_FIXED_TARGET 0x10 /* Target, no implicit conversion */
#define ARGI_SIMPLE_TARGET 0x11 /* Name, Local, Arg -- no implicit conversion */
+#define ARGI_STORE_TARGET 0x12 /* Target for store is TARGETREF + package objects */
/* Multiple/complex types */
-#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a node - Used only by size_of operator */
-#define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */
-#define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */
-#define ARGI_REGION_OR_BUFFER 0x15 /* Used by LOAD op only */
-#define ARGI_DATAREFOBJ 0x16
+#define ARGI_DATAOBJECT 0x13 /* Buffer, String, package or reference to a node - Used only by size_of operator */
+#define ARGI_COMPLEXOBJ 0x14 /* Buffer, String, or package (Used by INDEX op only) */
+#define ARGI_REF_OR_STRING 0x15 /* Reference or String (Used by DEREFOF op only) */
+#define ARGI_REGION_OR_BUFFER 0x16 /* Used by LOAD op only */
+#define ARGI_DATAREFOBJ 0x17
/* Note: types above can expand to 0x1F maximum */
diff --git a/drivers/acpi/acpica/dbcmds.c b/drivers/acpi/acpica/dbcmds.c
new file mode 100644
index 000000000000..30414b3d7fdd
--- /dev/null
+++ b/drivers/acpi/acpica/dbcmds.c
@@ -0,0 +1,1187 @@
+/*******************************************************************************
+ *
+ * Module Name: dbcmds - Miscellaneous debug commands and output routines
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acdebug.h"
+#include "acnamesp.h"
+#include "acresrc.h"
+#include "actables.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbcmds")
+
+/* Local prototypes */
+static void
+acpi_dm_compare_aml_resources(u8 *aml1_buffer,
+ acpi_rsdesc_size aml1_buffer_length,
+ u8 *aml2_buffer,
+ acpi_rsdesc_size aml2_buffer_length);
+
+static acpi_status
+acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name);
+
+static acpi_status
+acpi_db_resource_callback(struct acpi_resource *resource, void *context);
+
+static acpi_status
+acpi_db_device_resources(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
+
+static void acpi_db_do_one_sleep_state(u8 sleep_state);
+
+static char *acpi_db_trace_method_name = NULL;
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_convert_to_node
+ *
+ * PARAMETERS: in_string - String to convert
+ *
+ * RETURN: Pointer to a NS node
+ *
+ * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
+ * alphanumeric strings.
+ *
+ ******************************************************************************/
+
+struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string)
+{
+ struct acpi_namespace_node *node;
+ acpi_size address;
+
+ if ((*in_string >= 0x30) && (*in_string <= 0x39)) {
+
+ /* Numeric argument, convert */
+
+ address = strtoul(in_string, NULL, 16);
+ node = ACPI_TO_POINTER(address);
+ if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) {
+ acpi_os_printf("Address %p is invalid", node);
+ return (NULL);
+ }
+
+ /* Make sure pointer is valid NS node */
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
+ acpi_os_printf
+ ("Address %p is not a valid namespace node [%s]\n",
+ node, acpi_ut_get_descriptor_name(node));
+ return (NULL);
+ }
+ } else {
+ /*
+ * Alpha argument: The parameter is a name string that must be
+ * resolved to a Namespace object.
+ */
+ node = acpi_db_local_ns_lookup(in_string);
+ if (!node) {
+ acpi_os_printf
+ ("Could not find [%s] in namespace, defaulting to root node\n",
+ in_string);
+ node = acpi_gbl_root_node;
+ }
+ }
+
+ return (node);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_sleep
+ *
+ * PARAMETERS: object_arg - Desired sleep state (0-5). NULL means
+ * invoke all possible sleep states.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Simulate sleep/wake sequences
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_sleep(char *object_arg)
+{
+ u8 sleep_state;
+ u32 i;
+
+ ACPI_FUNCTION_TRACE(acpi_db_sleep);
+
+ /* Null input (no arguments) means to invoke all sleep states */
+
+ if (!object_arg) {
+ acpi_os_printf("Invoking all possible sleep states, 0-%d\n",
+ ACPI_S_STATES_MAX);
+
+ for (i = 0; i <= ACPI_S_STATES_MAX; i++) {
+ acpi_db_do_one_sleep_state((u8)i);
+ }
+
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /* Convert argument to binary and invoke the sleep state */
+
+ sleep_state = (u8)strtoul(object_arg, NULL, 0);
+ acpi_db_do_one_sleep_state(sleep_state);
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_do_one_sleep_state
+ *
+ * PARAMETERS: sleep_state - Desired sleep state (0-5)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Simulate a sleep/wake sequence
+ *
+ ******************************************************************************/
+
+static void acpi_db_do_one_sleep_state(u8 sleep_state)
+{
+ acpi_status status;
+ u8 sleep_type_a;
+ u8 sleep_type_b;
+
+ /* Validate parameter */
+
+ if (sleep_state > ACPI_S_STATES_MAX) {
+ acpi_os_printf("Sleep state %d out of range (%d max)\n",
+ sleep_state, ACPI_S_STATES_MAX);
+ return;
+ }
+
+ acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n",
+ sleep_state, acpi_gbl_sleep_state_names[sleep_state]);
+
+ /* Get the values for the sleep type registers (for display only) */
+
+ status =
+ acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not evaluate [%s] method, %s\n",
+ acpi_gbl_sleep_state_names[sleep_state],
+ acpi_format_exception(status));
+ return;
+ }
+
+ acpi_os_printf
+ ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
+ sleep_state, sleep_type_a, sleep_type_b);
+
+ /* Invoke the various sleep/wake interfaces */
+
+ acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n",
+ sleep_state);
+ status = acpi_enter_sleep_state_prep(sleep_state);
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
+
+ acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state);
+ status = acpi_enter_sleep_state(sleep_state);
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
+
+ acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n",
+ sleep_state);
+ status = acpi_leave_sleep_state_prep(sleep_state);
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
+
+ acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n",
+ sleep_state);
+ status = acpi_leave_sleep_state(sleep_state);
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
+
+ return;
+
+error_exit:
+ ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d",
+ sleep_state));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_locks
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display information about internal mutexes.
+ *
+ ******************************************************************************/
+
+void acpi_db_display_locks(void)
+{
+ u32 i;
+
+ for (i = 0; i < ACPI_MAX_MUTEX; i++) {
+ acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i),
+ acpi_gbl_mutex_info[i].thread_id ==
+ ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked");
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_table_info
+ *
+ * PARAMETERS: table_arg - Name of table to be displayed
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display information about loaded tables. Current
+ * implementation displays all loaded tables.
+ *
+ ******************************************************************************/
+
+void acpi_db_display_table_info(char *table_arg)
+{
+ u32 i;
+ struct acpi_table_desc *table_desc;
+ acpi_status status;
+
+ /* Header */
+
+ acpi_os_printf("Idx ID Status Type "
+ "TableHeader (Sig, Address, Length, Misc)\n");
+
+ /* Walk the entire root table list */
+
+ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
+ table_desc = &acpi_gbl_root_table_list.tables[i];
+
+ /* Index and Table ID */
+
+ acpi_os_printf("%3u %.2u ", i, table_desc->owner_id);
+
+ /* Decode the table flags */
+
+ if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) {
+ acpi_os_printf("NotLoaded ");
+ } else {
+ acpi_os_printf(" Loaded ");
+ }
+
+ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
+
+ acpi_os_printf("External/virtual ");
+ break;
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
+
+ acpi_os_printf("Internal/physical ");
+ break;
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
+
+ acpi_os_printf("Internal/virtual ");
+ break;
+
+ default:
+
+ acpi_os_printf("INVALID TYPE ");
+ break;
+ }
+
+ /* Make sure that the table is mapped */
+
+ status = acpi_tb_validate_table(table_desc);
+ if (ACPI_FAILURE(status)) {
+ return;
+ }
+
+ /* Dump the table header */
+
+ if (table_desc->pointer) {
+ acpi_tb_print_table_header(table_desc->address,
+ table_desc->pointer);
+ } else {
+ /* If the pointer is null, the table has been unloaded */
+
+ ACPI_INFO((AE_INFO, "%4.4s - Table has been unloaded",
+ table_desc->signature.ascii));
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_unload_acpi_table
+ *
+ * PARAMETERS: object_name - Namespace pathname for an object that
+ * is owned by the table to be unloaded
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned
+ * by the table.
+ *
+ ******************************************************************************/
+
+void acpi_db_unload_acpi_table(char *object_name)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+
+ /* Translate name to an Named object */
+
+ node = acpi_db_convert_to_node(object_name);
+ if (!node) {
+ return;
+ }
+
+ status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node));
+ if (ACPI_SUCCESS(status)) {
+ acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n",
+ object_name, node);
+ } else {
+ acpi_os_printf("%s, while unloading parent table of [%s]\n",
+ acpi_format_exception(status), object_name);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_send_notify
+ *
+ * PARAMETERS: name - Name of ACPI object where to send notify
+ * value - Value of the notify to send.
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Send an ACPI notification. The value specified is sent to the
+ * named object as an ACPI notify.
+ *
+ ******************************************************************************/
+
+void acpi_db_send_notify(char *name, u32 value)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+
+ /* Translate name to an Named object */
+
+ node = acpi_db_convert_to_node(name);
+ if (!node) {
+ return;
+ }
+
+ /* Dispatch the notify if legal */
+
+ if (acpi_ev_is_notify_object(node)) {
+ status = acpi_ev_queue_notify_request(node, value);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not queue notify\n");
+ }
+ } else {
+ acpi_os_printf("Named object [%4.4s] Type %s, "
+ "must be Device/Thermal/Processor type\n",
+ acpi_ut_get_node_name(node),
+ acpi_ut_get_type_name(node->type));
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_interfaces
+ *
+ * PARAMETERS: action_arg - Null, "install", or "remove"
+ * interface_name_arg - Name for install/remove options
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display or modify the global _OSI interface list
+ *
+ ******************************************************************************/
+
+void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg)
+{
+ struct acpi_interface_info *next_interface;
+ char *sub_string;
+ acpi_status status;
+
+ /* If no arguments, just display current interface list */
+
+ if (!action_arg) {
+ (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex,
+ ACPI_WAIT_FOREVER);
+
+ next_interface = acpi_gbl_supported_interfaces;
+ while (next_interface) {
+ if (!(next_interface->flags & ACPI_OSI_INVALID)) {
+ acpi_os_printf("%s\n", next_interface->name);
+ }
+
+ next_interface = next_interface->next;
+ }
+
+ acpi_os_release_mutex(acpi_gbl_osi_mutex);
+ return;
+ }
+
+ /* If action_arg exists, so must interface_name_arg */
+
+ if (!interface_name_arg) {
+ acpi_os_printf("Missing Interface Name argument\n");
+ return;
+ }
+
+ /* Uppercase the action for match below */
+
+ acpi_ut_strupr(action_arg);
+
+ /* install - install an interface */
+
+ sub_string = strstr("INSTALL", action_arg);
+ if (sub_string) {
+ status = acpi_install_interface(interface_name_arg);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("%s, while installing \"%s\"\n",
+ acpi_format_exception(status),
+ interface_name_arg);
+ }
+ return;
+ }
+
+ /* remove - remove an interface */
+
+ sub_string = strstr("REMOVE", action_arg);
+ if (sub_string) {
+ status = acpi_remove_interface(interface_name_arg);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("%s, while removing \"%s\"\n",
+ acpi_format_exception(status),
+ interface_name_arg);
+ }
+ return;
+ }
+
+ /* Invalid action_arg */
+
+ acpi_os_printf("Invalid action argument: %s\n", action_arg);
+ return;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_template
+ *
+ * PARAMETERS: buffer_arg - Buffer name or address
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump a buffer that contains a resource template
+ *
+ ******************************************************************************/
+
+void acpi_db_display_template(char *buffer_arg)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ struct acpi_buffer return_buffer;
+
+ /* Translate buffer_arg to an Named object */
+
+ node = acpi_db_convert_to_node(buffer_arg);
+ if (!node || (node == acpi_gbl_root_node)) {
+ acpi_os_printf("Invalid argument: %s\n", buffer_arg);
+ return;
+ }
+
+ /* We must have a buffer object */
+
+ if (node->type != ACPI_TYPE_BUFFER) {
+ acpi_os_printf
+ ("Not a Buffer object, cannot be a template: %s\n",
+ buffer_arg);
+ return;
+ }
+
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+ return_buffer.pointer = acpi_gbl_db_buffer;
+
+ /* Attempt to convert the raw buffer to a resource list */
+
+ status = acpi_rs_create_resource_list(node->object, &return_buffer);
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ acpi_dbg_level |= ACPI_LV_RESOURCES;
+
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("Could not convert Buffer to a resource list: %s, %s\n",
+ buffer_arg, acpi_format_exception(status));
+ goto dump_buffer;
+ }
+
+ /* Now we can dump the resource list */
+
+ acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
+ return_buffer.pointer));
+
+dump_buffer:
+ acpi_os_printf("\nRaw data buffer:\n");
+ acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer,
+ node->object->buffer.length,
+ DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+ return;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_dm_compare_aml_resources
+ *
+ * PARAMETERS: aml1_buffer - Contains first resource list
+ * aml1_buffer_length - Length of first resource list
+ * aml2_buffer - Contains second resource list
+ * aml2_buffer_length - Length of second resource list
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in
+ * order to isolate a miscompare to an individual resource)
+ *
+ ******************************************************************************/
+
+static void
+acpi_dm_compare_aml_resources(u8 *aml1_buffer,
+ acpi_rsdesc_size aml1_buffer_length,
+ u8 *aml2_buffer,
+ acpi_rsdesc_size aml2_buffer_length)
+{
+ u8 *aml1;
+ u8 *aml2;
+ u8 *aml1_end;
+ u8 *aml2_end;
+ acpi_rsdesc_size aml1_length;
+ acpi_rsdesc_size aml2_length;
+ acpi_rsdesc_size offset = 0;
+ u8 resource_type;
+ u32 count = 0;
+ u32 i;
+
+ /* Compare overall buffer sizes (may be different due to size rounding) */
+
+ if (aml1_buffer_length != aml2_buffer_length) {
+ acpi_os_printf("**** Buffer length mismatch in converted "
+ "AML: Original %X, New %X ****\n",
+ aml1_buffer_length, aml2_buffer_length);
+ }
+
+ aml1 = aml1_buffer;
+ aml2 = aml2_buffer;
+ aml1_end = aml1_buffer + aml1_buffer_length;
+ aml2_end = aml2_buffer + aml2_buffer_length;
+
+ /* Walk the descriptor lists, comparing each descriptor */
+
+ while ((aml1 < aml1_end) && (aml2 < aml2_end)) {
+
+ /* Get the lengths of each descriptor */
+
+ aml1_length = acpi_ut_get_descriptor_length(aml1);
+ aml2_length = acpi_ut_get_descriptor_length(aml2);
+ resource_type = acpi_ut_get_resource_type(aml1);
+
+ /* Check for descriptor length match */
+
+ if (aml1_length != aml2_length) {
+ acpi_os_printf
+ ("**** Length mismatch in descriptor [%.2X] type %2.2X, "
+ "Offset %8.8X Len1 %X, Len2 %X ****\n", count,
+ resource_type, offset, aml1_length, aml2_length);
+ }
+
+ /* Check for descriptor byte match */
+
+ else if (memcmp(aml1, aml2, aml1_length)) {
+ acpi_os_printf
+ ("**** Data mismatch in descriptor [%.2X] type %2.2X, "
+ "Offset %8.8X ****\n", count, resource_type,
+ offset);
+
+ for (i = 0; i < aml1_length; i++) {
+ if (aml1[i] != aml2[i]) {
+ acpi_os_printf
+ ("Mismatch at byte offset %.2X: is %2.2X, "
+ "should be %2.2X\n", i, aml2[i],
+ aml1[i]);
+ }
+ }
+ }
+
+ /* Exit on end_tag descriptor */
+
+ if (resource_type == ACPI_RESOURCE_NAME_END_TAG) {
+ return;
+ }
+
+ /* Point to next descriptor in each buffer */
+
+ count++;
+ offset += aml1_length;
+ aml1 += aml1_length;
+ aml2 += aml2_length;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_dm_test_resource_conversion
+ *
+ * PARAMETERS: node - Parent device node
+ * name - resource method name (_CRS)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compare the original AML with a conversion of the AML to
+ * internal resource list, then back to AML.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name)
+{
+ acpi_status status;
+ struct acpi_buffer return_buffer;
+ struct acpi_buffer resource_buffer;
+ struct acpi_buffer new_aml;
+ union acpi_object *original_aml;
+
+ acpi_os_printf("Resource Conversion Comparison:\n");
+
+ new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
+ /* Get the original _CRS AML resource template */
+
+ status = acpi_evaluate_object(node, name, NULL, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not obtain %s: %s\n",
+ name, acpi_format_exception(status));
+ return (status);
+ }
+
+ /* Get the AML resource template, converted to internal resource structs */
+
+ status = acpi_get_current_resources(node, &resource_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
+ acpi_format_exception(status));
+ goto exit1;
+ }
+
+ /* Convert internal resource list to external AML resource template */
+
+ status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n",
+ acpi_format_exception(status));
+ goto exit2;
+ }
+
+ /* Compare original AML to the newly created AML resource list */
+
+ original_aml = return_buffer.pointer;
+
+ acpi_dm_compare_aml_resources(original_aml->buffer.pointer,
+ (acpi_rsdesc_size) original_aml->buffer.
+ length, new_aml.pointer,
+ (acpi_rsdesc_size) new_aml.length);
+
+ /* Cleanup and exit */
+
+ ACPI_FREE(new_aml.pointer);
+exit2:
+ ACPI_FREE(resource_buffer.pointer);
+exit1:
+ ACPI_FREE(return_buffer.pointer);
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_resource_callback
+ *
+ * PARAMETERS: acpi_walk_resource_callback
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Simple callback to exercise acpi_walk_resources and
+ * acpi_walk_resource_buffer.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_resource_callback(struct acpi_resource *resource, void *context)
+{
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_device_resources
+ *
+ * PARAMETERS: acpi_walk_callback
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_device_resources(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
+{
+ struct acpi_namespace_node *node;
+ struct acpi_namespace_node *prt_node = NULL;
+ struct acpi_namespace_node *crs_node = NULL;
+ struct acpi_namespace_node *prs_node = NULL;
+ struct acpi_namespace_node *aei_node = NULL;
+ char *parent_path;
+ struct acpi_buffer return_buffer;
+ acpi_status status;
+
+ node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
+ parent_path = acpi_ns_get_external_pathname(node);
+ if (!parent_path) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Get handles to the resource methods for this device */
+
+ (void)acpi_get_handle(node, METHOD_NAME__PRT,
+ ACPI_CAST_PTR(acpi_handle, &prt_node));
+ (void)acpi_get_handle(node, METHOD_NAME__CRS,
+ ACPI_CAST_PTR(acpi_handle, &crs_node));
+ (void)acpi_get_handle(node, METHOD_NAME__PRS,
+ ACPI_CAST_PTR(acpi_handle, &prs_node));
+ (void)acpi_get_handle(node, METHOD_NAME__AEI,
+ ACPI_CAST_PTR(acpi_handle, &aei_node));
+
+ if (!prt_node && !crs_node && !prs_node && !aei_node) {
+ goto cleanup; /* Nothing to do */
+ }
+
+ acpi_os_printf("\nDevice: %s\n", parent_path);
+
+ /* Prepare for a return object of arbitrary size */
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ /* _PRT */
+
+ if (prt_node) {
+ acpi_os_printf("Evaluating _PRT\n");
+
+ status =
+ acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not evaluate _PRT: %s\n",
+ acpi_format_exception(status));
+ goto get_crs;
+ }
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ status = acpi_get_irq_routing_table(node, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("GetIrqRoutingTable failed: %s\n",
+ acpi_format_exception(status));
+ goto get_crs;
+ }
+
+ acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
+ }
+
+ /* _CRS */
+
+get_crs:
+ if (crs_node) {
+ acpi_os_printf("Evaluating _CRS\n");
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ status =
+ acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not evaluate _CRS: %s\n",
+ acpi_format_exception(status));
+ goto get_prs;
+ }
+
+ /* This code exercises the acpi_walk_resources interface */
+
+ status = acpi_walk_resources(node, METHOD_NAME__CRS,
+ acpi_db_resource_callback, NULL);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiWalkResources failed: %s\n",
+ acpi_format_exception(status));
+ goto get_prs;
+ }
+
+ /* Get the _CRS resource list (test ALLOCATE buffer) */
+
+ return_buffer.pointer = NULL;
+ return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
+ status = acpi_get_current_resources(node, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
+ acpi_format_exception(status));
+ goto get_prs;
+ }
+
+ /* This code exercises the acpi_walk_resource_buffer interface */
+
+ status = acpi_walk_resource_buffer(&return_buffer,
+ acpi_db_resource_callback,
+ NULL);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
+ acpi_format_exception(status));
+ goto end_crs;
+ }
+
+ /* Dump the _CRS resource list */
+
+ acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
+ return_buffer.
+ pointer));
+
+ /*
+ * Perform comparison of original AML to newly created AML. This
+ * tests both the AML->Resource conversion and the Resource->AML
+ * conversion.
+ */
+ (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);
+
+ /* Execute _SRS with the resource list */
+
+ acpi_os_printf("Evaluating _SRS\n");
+
+ status = acpi_set_current_resources(node, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
+ acpi_format_exception(status));
+ goto end_crs;
+ }
+
+end_crs:
+ ACPI_FREE(return_buffer.pointer);
+ }
+
+ /* _PRS */
+
+get_prs:
+ if (prs_node) {
+ acpi_os_printf("Evaluating _PRS\n");
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ status =
+ acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not evaluate _PRS: %s\n",
+ acpi_format_exception(status));
+ goto get_aei;
+ }
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ status = acpi_get_possible_resources(node, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
+ acpi_format_exception(status));
+ goto get_aei;
+ }
+
+ acpi_rs_dump_resource_list(ACPI_CAST_PTR
+ (struct acpi_resource,
+ acpi_gbl_db_buffer));
+ }
+
+ /* _AEI */
+
+get_aei:
+ if (aei_node) {
+ acpi_os_printf("Evaluating _AEI\n");
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ status =
+ acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not evaluate _AEI: %s\n",
+ acpi_format_exception(status));
+ goto cleanup;
+ }
+
+ return_buffer.pointer = acpi_gbl_db_buffer;
+ return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
+
+ status = acpi_get_event_resources(node, &return_buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiGetEventResources failed: %s\n",
+ acpi_format_exception(status));
+ goto cleanup;
+ }
+
+ acpi_rs_dump_resource_list(ACPI_CAST_PTR
+ (struct acpi_resource,
+ acpi_gbl_db_buffer));
+ }
+
+cleanup:
+ ACPI_FREE(parent_path);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_resources
+ *
+ * PARAMETERS: object_arg - String object name or object pointer.
+ * NULL or "*" means "display resources for
+ * all devices"
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display the resource objects associated with a device.
+ *
+ ******************************************************************************/
+
+void acpi_db_display_resources(char *object_arg)
+{
+ struct acpi_namespace_node *node;
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ acpi_dbg_level |= ACPI_LV_RESOURCES;
+
+ /* Asterisk means "display resources for all devices" */
+
+ if (!object_arg || (!strcmp(object_arg, "*"))) {
+ (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_db_device_resources, NULL, NULL,
+ NULL);
+ } else {
+ /* Convert string to object pointer */
+
+ node = acpi_db_convert_to_node(object_arg);
+ if (node) {
+ if (node->type != ACPI_TYPE_DEVICE) {
+ acpi_os_printf
+ ("%4.4s: Name is not a device object (%s)\n",
+ node->name.ascii,
+ acpi_ut_get_type_name(node->type));
+ } else {
+ (void)acpi_db_device_resources(node, 0, NULL,
+ NULL);
+ }
+ }
+ }
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+}
+
+#if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_generate_gpe
+ *
+ * PARAMETERS: gpe_arg - Raw GPE number, ascii string
+ * block_arg - GPE block number, ascii string
+ * 0 or 1 for FADT GPE blocks
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Simulate firing of a GPE
+ *
+ ******************************************************************************/
+
+void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)
+{
+ u32 block_number = 0;
+ u32 gpe_number;
+ struct acpi_gpe_event_info *gpe_event_info;
+
+ gpe_number = strtoul(gpe_arg, NULL, 0);
+
+ /*
+ * If no block arg, or block arg == 0 or 1, use the FADT-defined
+ * GPE blocks.
+ */
+ if (block_arg) {
+ block_number = strtoul(block_arg, NULL, 0);
+ if (block_number == 1) {
+ block_number = 0;
+ }
+ }
+
+ gpe_event_info =
+ acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number),
+ gpe_number);
+ if (!gpe_event_info) {
+ acpi_os_printf("Invalid GPE\n");
+ return;
+ }
+
+ (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_generate_sci
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch.
+ *
+ ******************************************************************************/
+
+void acpi_db_generate_sci(void)
+{
+ acpi_ev_sci_dispatch();
+}
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_trace
+ *
+ * PARAMETERS: enable_arg - ENABLE/AML to enable tracer
+ * DISABLE to disable tracer
+ * method_arg - Method to trace
+ * once_arg - Whether trace once
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Control method tracing facility
+ *
+ ******************************************************************************/
+
+void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg)
+{
+ u32 debug_level = 0;
+ u32 debug_layer = 0;
+ u32 flags = 0;
+
+ if (enable_arg) {
+ acpi_ut_strupr(enable_arg);
+ }
+
+ if (once_arg) {
+ acpi_ut_strupr(once_arg);
+ }
+
+ if (method_arg) {
+ if (acpi_db_trace_method_name) {
+ ACPI_FREE(acpi_db_trace_method_name);
+ acpi_db_trace_method_name = NULL;
+ }
+
+ acpi_db_trace_method_name =
+ ACPI_ALLOCATE(strlen(method_arg) + 1);
+ if (!acpi_db_trace_method_name) {
+ acpi_os_printf("Failed to allocate method name (%s)\n",
+ method_arg);
+ return;
+ }
+
+ strcpy(acpi_db_trace_method_name, method_arg);
+ }
+
+ if (!strcmp(enable_arg, "ENABLE") ||
+ !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) {
+ if (!strcmp(enable_arg, "ENABLE")) {
+
+ /* Inherit current console settings */
+
+ debug_level = acpi_gbl_db_console_debug_level;
+ debug_layer = acpi_dbg_layer;
+ } else {
+ /* Restrict console output to trace points only */
+
+ debug_level = ACPI_LV_TRACE_POINT;
+ debug_layer = ACPI_EXECUTER;
+ }
+
+ flags = ACPI_TRACE_ENABLED;
+
+ if (!strcmp(enable_arg, "OPCODE")) {
+ flags |= ACPI_TRACE_OPCODE;
+ }
+
+ if (once_arg && !strcmp(once_arg, "ONCE")) {
+ flags |= ACPI_TRACE_ONESHOT;
+ }
+ }
+
+ (void)acpi_debug_trace(acpi_db_trace_method_name,
+ debug_level, debug_layer, flags);
+}
diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c
new file mode 100644
index 000000000000..a71632ca8a81
--- /dev/null
+++ b/drivers/acpi/acpica/dbconvert.c
@@ -0,0 +1,484 @@
+/*******************************************************************************
+ *
+ * Module Name: dbconvert - debugger miscellaneous conversion routines
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbconvert")
+
+#define DB_DEFAULT_PKG_ELEMENTS 33
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_hex_char_to_value
+ *
+ * PARAMETERS: hex_char - Ascii Hex digit, 0-9|a-f|A-F
+ * return_value - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
+ *
+ ******************************************************************************/
+acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value)
+{
+ u8 value;
+
+ /* Digit must be ascii [0-9a-fA-F] */
+
+ if (!isxdigit(hex_char)) {
+ return (AE_BAD_HEX_CONSTANT);
+ }
+
+ if (hex_char <= 0x39) {
+ value = (u8)(hex_char - 0x30);
+ } else {
+ value = (u8)(toupper(hex_char) - 0x37);
+ }
+
+ *return_value = value;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_hex_byte_to_binary
+ *
+ * PARAMETERS: hex_byte - Double hex digit (0x00 - 0xFF) in format:
+ * hi_byte then lo_byte.
+ * return_value - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_db_hex_byte_to_binary(char *hex_byte, u8 *return_value)
+{
+ u8 local0;
+ u8 local1;
+ acpi_status status;
+
+ /* High byte */
+
+ status = acpi_db_hex_char_to_value(hex_byte[0], &local0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Low byte */
+
+ status = acpi_db_hex_char_to_value(hex_byte[1], &local1);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ *return_value = (u8)((local0 << 4) | local1);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_convert_to_buffer
+ *
+ * PARAMETERS: string - Input string to be converted
+ * object - Where the buffer object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a buffer object. String is treated a list
+ * of buffer elements, each separated by a space or comma.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_convert_to_buffer(char *string, union acpi_object *object)
+{
+ u32 i;
+ u32 j;
+ u32 length;
+ u8 *buffer;
+ acpi_status status;
+
+ /* Generate the final buffer length */
+
+ for (i = 0, length = 0; string[i];) {
+ i += 2;
+ length++;
+
+ while (string[i] && ((string[i] == ',') || (string[i] == ' '))) {
+ i++;
+ }
+ }
+
+ buffer = ACPI_ALLOCATE(length);
+ if (!buffer) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Convert the command line bytes to the buffer */
+
+ for (i = 0, j = 0; string[i];) {
+ status = acpi_db_hex_byte_to_binary(&string[i], &buffer[j]);
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(buffer);
+ return (status);
+ }
+
+ j++;
+ i += 2;
+ while (string[i] && ((string[i] == ',') || (string[i] == ' '))) {
+ i++;
+ }
+ }
+
+ object->type = ACPI_TYPE_BUFFER;
+ object->buffer.pointer = buffer;
+ object->buffer.length = length;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_convert_to_package
+ *
+ * PARAMETERS: string - Input string to be converted
+ * object - Where the package object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a package object. Handles nested packages
+ * via recursion with acpi_db_convert_to_object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_convert_to_package(char *string, union acpi_object * object)
+{
+ char *this;
+ char *next;
+ u32 i;
+ acpi_object_type type;
+ union acpi_object *elements;
+ acpi_status status;
+
+ elements =
+ ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS *
+ sizeof(union acpi_object));
+
+ this = string;
+ for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) {
+ this = acpi_db_get_next_token(this, &next, &type);
+ if (!this) {
+ break;
+ }
+
+ /* Recursive call to convert each package element */
+
+ status = acpi_db_convert_to_object(type, this, &elements[i]);
+ if (ACPI_FAILURE(status)) {
+ acpi_db_delete_objects(i + 1, elements);
+ ACPI_FREE(elements);
+ return (status);
+ }
+
+ this = next;
+ }
+
+ object->type = ACPI_TYPE_PACKAGE;
+ object->package.count = i;
+ object->package.elements = elements;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_convert_to_object
+ *
+ * PARAMETERS: type - Object type as determined by parser
+ * string - Input string to be converted
+ * object - Where the new object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a typed and tokenized string to an union acpi_object. Typing:
+ * 1) String objects were surrounded by quotes.
+ * 2) Buffer objects were surrounded by parentheses.
+ * 3) Package objects were surrounded by brackets "[]".
+ * 4) All standalone tokens are treated as integers.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_db_convert_to_object(acpi_object_type type,
+ char *string, union acpi_object * object)
+{
+ acpi_status status = AE_OK;
+
+ switch (type) {
+ case ACPI_TYPE_STRING:
+
+ object->type = ACPI_TYPE_STRING;
+ object->string.pointer = string;
+ object->string.length = (u32)strlen(string);
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ status = acpi_db_convert_to_buffer(string, object);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ status = acpi_db_convert_to_package(string, object);
+ break;
+
+ default:
+
+ object->type = ACPI_TYPE_INTEGER;
+ status = acpi_ut_strtoul64(string, 16, &object->integer.value);
+ break;
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_encode_pld_buffer
+ *
+ * PARAMETERS: pld_info - _PLD buffer struct (Using local struct)
+ *
+ * RETURN: Encode _PLD buffer suitable for return value from _PLD
+ *
+ * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros
+ *
+ ******************************************************************************/
+
+u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info)
+{
+ u32 *buffer;
+ u32 dword;
+
+ buffer = ACPI_ALLOCATE_ZEROED(ACPI_PLD_BUFFER_SIZE);
+ if (!buffer) {
+ return (NULL);
+ }
+
+ /* First 32 bits */
+
+ dword = 0;
+ ACPI_PLD_SET_REVISION(&dword, pld_info->revision);
+ ACPI_PLD_SET_IGNORE_COLOR(&dword, pld_info->ignore_color);
+ ACPI_PLD_SET_RED(&dword, pld_info->red);
+ ACPI_PLD_SET_GREEN(&dword, pld_info->green);
+ ACPI_PLD_SET_BLUE(&dword, pld_info->blue);
+ ACPI_MOVE_32_TO_32(&buffer[0], &dword);
+
+ /* Second 32 bits */
+
+ dword = 0;
+ ACPI_PLD_SET_WIDTH(&dword, pld_info->width);
+ ACPI_PLD_SET_HEIGHT(&dword, pld_info->height);
+ ACPI_MOVE_32_TO_32(&buffer[1], &dword);
+
+ /* Third 32 bits */
+
+ dword = 0;
+ ACPI_PLD_SET_USER_VISIBLE(&dword, pld_info->user_visible);
+ ACPI_PLD_SET_DOCK(&dword, pld_info->dock);
+ ACPI_PLD_SET_LID(&dword, pld_info->lid);
+ ACPI_PLD_SET_PANEL(&dword, pld_info->panel);
+ ACPI_PLD_SET_VERTICAL(&dword, pld_info->vertical_position);
+ ACPI_PLD_SET_HORIZONTAL(&dword, pld_info->horizontal_position);
+ ACPI_PLD_SET_SHAPE(&dword, pld_info->shape);
+ ACPI_PLD_SET_ORIENTATION(&dword, pld_info->group_orientation);
+ ACPI_PLD_SET_TOKEN(&dword, pld_info->group_token);
+ ACPI_PLD_SET_POSITION(&dword, pld_info->group_position);
+ ACPI_PLD_SET_BAY(&dword, pld_info->bay);
+ ACPI_MOVE_32_TO_32(&buffer[2], &dword);
+
+ /* Fourth 32 bits */
+
+ dword = 0;
+ ACPI_PLD_SET_EJECTABLE(&dword, pld_info->ejectable);
+ ACPI_PLD_SET_OSPM_EJECT(&dword, pld_info->ospm_eject_required);
+ ACPI_PLD_SET_CABINET(&dword, pld_info->cabinet_number);
+ ACPI_PLD_SET_CARD_CAGE(&dword, pld_info->card_cage_number);
+ ACPI_PLD_SET_REFERENCE(&dword, pld_info->reference);
+ ACPI_PLD_SET_ROTATION(&dword, pld_info->rotation);
+ ACPI_PLD_SET_ORDER(&dword, pld_info->order);
+ ACPI_MOVE_32_TO_32(&buffer[3], &dword);
+
+ if (pld_info->revision >= 2) {
+
+ /* Fifth 32 bits */
+
+ dword = 0;
+ ACPI_PLD_SET_VERT_OFFSET(&dword, pld_info->vertical_offset);
+ ACPI_PLD_SET_HORIZ_OFFSET(&dword, pld_info->horizontal_offset);
+ ACPI_MOVE_32_TO_32(&buffer[4], &dword);
+ }
+
+ return (ACPI_CAST_PTR(u8, buffer));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_pld_buffer
+ *
+ * PARAMETERS: obj_desc - Object returned from _PLD method
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Dumps formatted contents of a _PLD return buffer.
+ *
+ ******************************************************************************/
+
+#define ACPI_PLD_OUTPUT "%20s : %-6X\n"
+
+void acpi_db_dump_pld_buffer(union acpi_object *obj_desc)
+{
+ union acpi_object *buffer_desc;
+ struct acpi_pld_info *pld_info;
+ u8 *new_buffer;
+ acpi_status status;
+
+ /* Object must be of type Package with at least one Buffer element */
+
+ if (obj_desc->type != ACPI_TYPE_PACKAGE) {
+ return;
+ }
+
+ buffer_desc = &obj_desc->package.elements[0];
+ if (buffer_desc->type != ACPI_TYPE_BUFFER) {
+ return;
+ }
+
+ /* Convert _PLD buffer to local _PLD struct */
+
+ status = acpi_decode_pld_buffer(buffer_desc->buffer.pointer,
+ buffer_desc->buffer.length, &pld_info);
+ if (ACPI_FAILURE(status)) {
+ return;
+ }
+
+ /* Encode local _PLD struct back to a _PLD buffer */
+
+ new_buffer = acpi_db_encode_pld_buffer(pld_info);
+ if (!new_buffer) {
+ return;
+ }
+
+ /* The two bit-packed buffers should match */
+
+ if (memcmp(new_buffer, buffer_desc->buffer.pointer,
+ buffer_desc->buffer.length)) {
+ acpi_os_printf
+ ("Converted _PLD buffer does not compare. New:\n");
+
+ acpi_ut_dump_buffer(new_buffer,
+ buffer_desc->buffer.length, DB_BYTE_DISPLAY,
+ 0);
+ }
+
+ /* First 32-bit dword */
+
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Revision", pld_info->revision);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_IgnoreColor",
+ pld_info->ignore_color);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Red", pld_info->red);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Green", pld_info->green);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Blue", pld_info->blue);
+
+ /* Second 32-bit dword */
+
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Width", pld_info->width);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Height", pld_info->height);
+
+ /* Third 32-bit dword */
+
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_UserVisible",
+ pld_info->user_visible);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Dock", pld_info->dock);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Lid", pld_info->lid);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Panel", pld_info->panel);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalPosition",
+ pld_info->vertical_position);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalPosition",
+ pld_info->horizontal_position);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Shape", pld_info->shape);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupOrientation",
+ pld_info->group_orientation);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupToken",
+ pld_info->group_token);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupPosition",
+ pld_info->group_position);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Bay", pld_info->bay);
+
+ /* Fourth 32-bit dword */
+
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Ejectable", pld_info->ejectable);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_EjectRequired",
+ pld_info->ospm_eject_required);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CabinetNumber",
+ pld_info->cabinet_number);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CardCageNumber",
+ pld_info->card_cage_number);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Reference", pld_info->reference);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Rotation", pld_info->rotation);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Order", pld_info->order);
+
+ /* Fifth 32-bit dword */
+
+ if (buffer_desc->buffer.length > 16) {
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalOffset",
+ pld_info->vertical_offset);
+ acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalOffset",
+ pld_info->horizontal_offset);
+ }
+
+ ACPI_FREE(pld_info);
+ ACPI_FREE(new_buffer);
+}
diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c
new file mode 100644
index 000000000000..672977ec7c7d
--- /dev/null
+++ b/drivers/acpi/acpica/dbdisply.c
@@ -0,0 +1,1108 @@
+/*******************************************************************************
+ *
+ * Module Name: dbdisply - debug display commands
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "acparser.h"
+#include "acinterp.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbdisply")
+
+/* Local prototypes */
+static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op);
+
+static void *acpi_db_get_pointer(void *target);
+
+static acpi_status
+acpi_db_display_non_root_handlers(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+/*
+ * System handler information.
+ * Used for Handlers command, in acpi_db_display_handlers.
+ */
+#define ACPI_PREDEFINED_PREFIX "%25s (%.2X) : "
+#define ACPI_HANDLER_NAME_STRING "%30s : "
+#define ACPI_HANDLER_PRESENT_STRING "%-9s (%p)\n"
+#define ACPI_HANDLER_PRESENT_STRING2 "%-9s (%p)"
+#define ACPI_HANDLER_NOT_PRESENT_STRING "%-9s\n"
+
+/* All predefined Address Space IDs */
+
+static acpi_adr_space_type acpi_gbl_space_id_list[] = {
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_EC,
+ ACPI_ADR_SPACE_SMBUS,
+ ACPI_ADR_SPACE_CMOS,
+ ACPI_ADR_SPACE_PCI_BAR_TARGET,
+ ACPI_ADR_SPACE_IPMI,
+ ACPI_ADR_SPACE_GPIO,
+ ACPI_ADR_SPACE_GSBUS,
+ ACPI_ADR_SPACE_DATA_TABLE,
+ ACPI_ADR_SPACE_FIXED_HARDWARE
+};
+
+/* Global handler information */
+
+typedef struct acpi_handler_info {
+ void *handler;
+ char *name;
+
+} acpi_handler_info;
+
+static struct acpi_handler_info acpi_gbl_handler_list[] = {
+ {&acpi_gbl_global_notify[0].handler, "System Notifications"},
+ {&acpi_gbl_global_notify[1].handler, "Device Notifications"},
+ {&acpi_gbl_table_handler, "ACPI Table Events"},
+ {&acpi_gbl_exception_handler, "Control Method Exceptions"},
+ {&acpi_gbl_interface_handler, "OSI Invocations"}
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_pointer
+ *
+ * PARAMETERS: target - Pointer to string to be converted
+ *
+ * RETURN: Converted pointer
+ *
+ * DESCRIPTION: Convert an ascii pointer value to a real value
+ *
+ ******************************************************************************/
+
+static void *acpi_db_get_pointer(void *target)
+{
+ void *obj_ptr;
+ acpi_size address;
+
+ address = strtoul(target, NULL, 16);
+ obj_ptr = ACPI_TO_POINTER(address);
+ return (obj_ptr);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_parser_descriptor
+ *
+ * PARAMETERS: op - A parser Op descriptor
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display a formatted parser object
+ *
+ ******************************************************************************/
+
+static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op)
+{
+ const struct acpi_opcode_info *info;
+
+ info = acpi_ps_get_opcode_info(op->common.aml_opcode);
+
+ acpi_os_printf("Parser Op Descriptor:\n");
+ acpi_os_printf("%20.20s : %4.4X\n", "Opcode", op->common.aml_opcode);
+
+ ACPI_DEBUG_ONLY_MEMBERS(acpi_os_printf("%20.20s : %s\n", "Opcode Name",
+ info->name));
+
+ acpi_os_printf("%20.20s : %p\n", "Value/ArgList", op->common.value.arg);
+ acpi_os_printf("%20.20s : %p\n", "Parent", op->common.parent);
+ acpi_os_printf("%20.20s : %p\n", "NextOp", op->common.next);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_decode_and_display_object
+ *
+ * PARAMETERS: target - String with object to be displayed. Names
+ * and hex pointers are supported.
+ * output_type - Byte, Word, Dword, or Qword (B|W|D|Q)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display a formatted ACPI object
+ *
+ ******************************************************************************/
+
+void acpi_db_decode_and_display_object(char *target, char *output_type)
+{
+ void *obj_ptr;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *obj_desc;
+ u32 display = DB_BYTE_DISPLAY;
+ char buffer[80];
+ struct acpi_buffer ret_buf;
+ acpi_status status;
+ u32 size;
+
+ if (!target) {
+ return;
+ }
+
+ /* Decode the output type */
+
+ if (output_type) {
+ acpi_ut_strupr(output_type);
+ if (output_type[0] == 'W') {
+ display = DB_WORD_DISPLAY;
+ } else if (output_type[0] == 'D') {
+ display = DB_DWORD_DISPLAY;
+ } else if (output_type[0] == 'Q') {
+ display = DB_QWORD_DISPLAY;
+ }
+ }
+
+ ret_buf.length = sizeof(buffer);
+ ret_buf.pointer = buffer;
+
+ /* Differentiate between a number and a name */
+
+ if ((target[0] >= 0x30) && (target[0] <= 0x39)) {
+ obj_ptr = acpi_db_get_pointer(target);
+ if (!acpi_os_readable(obj_ptr, 16)) {
+ acpi_os_printf
+ ("Address %p is invalid in this address space\n",
+ obj_ptr);
+ return;
+ }
+
+ /* Decode the object type */
+
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_ptr)) {
+ case ACPI_DESC_TYPE_NAMED:
+
+ /* This is a namespace Node */
+
+ if (!acpi_os_readable
+ (obj_ptr, sizeof(struct acpi_namespace_node))) {
+ acpi_os_printf
+ ("Cannot read entire Named object at address %p\n",
+ obj_ptr);
+ return;
+ }
+
+ node = obj_ptr;
+ goto dump_node;
+
+ case ACPI_DESC_TYPE_OPERAND:
+
+ /* This is a ACPI OPERAND OBJECT */
+
+ if (!acpi_os_readable
+ (obj_ptr, sizeof(union acpi_operand_object))) {
+ acpi_os_printf
+ ("Cannot read entire ACPI object at address %p\n",
+ obj_ptr);
+ return;
+ }
+
+ acpi_ut_debug_dump_buffer(obj_ptr,
+ sizeof(union
+ acpi_operand_object),
+ display, ACPI_UINT32_MAX);
+ acpi_ex_dump_object_descriptor(obj_ptr, 1);
+ break;
+
+ case ACPI_DESC_TYPE_PARSER:
+
+ /* This is a Parser Op object */
+
+ if (!acpi_os_readable
+ (obj_ptr, sizeof(union acpi_parse_object))) {
+ acpi_os_printf
+ ("Cannot read entire Parser object at address %p\n",
+ obj_ptr);
+ return;
+ }
+
+ acpi_ut_debug_dump_buffer(obj_ptr,
+ sizeof(union
+ acpi_parse_object),
+ display, ACPI_UINT32_MAX);
+ acpi_db_dump_parser_descriptor((union acpi_parse_object
+ *)obj_ptr);
+ break;
+
+ default:
+
+ /* Is not a recognizeable object */
+
+ acpi_os_printf
+ ("Not a known ACPI internal object, descriptor type %2.2X\n",
+ ACPI_GET_DESCRIPTOR_TYPE(obj_ptr));
+
+ size = 16;
+ if (acpi_os_readable(obj_ptr, 64)) {
+ size = 64;
+ }
+
+ /* Just dump some memory */
+
+ acpi_ut_debug_dump_buffer(obj_ptr, size, display,
+ ACPI_UINT32_MAX);
+ break;
+ }
+
+ return;
+ }
+
+ /* The parameter is a name string that must be resolved to a Named obj */
+
+ node = acpi_db_local_ns_lookup(target);
+ if (!node) {
+ return;
+ }
+
+dump_node:
+ /* Now dump the NS node */
+
+ status = acpi_get_name(node, ACPI_FULL_PATHNAME_NO_TRAILING, &ret_buf);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not convert name to pathname\n");
+ }
+
+ else {
+ acpi_os_printf("Object (%p) Pathname: %s\n",
+ node, (char *)ret_buf.pointer);
+ }
+
+ if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) {
+ acpi_os_printf("Invalid Named object at address %p\n", node);
+ return;
+ }
+
+ acpi_ut_debug_dump_buffer((void *)node,
+ sizeof(struct acpi_namespace_node), display,
+ ACPI_UINT32_MAX);
+ acpi_ex_dump_namespace_node(node, 1);
+
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (obj_desc) {
+ acpi_os_printf("\nAttached Object (%p):\n", obj_desc);
+ if (!acpi_os_readable
+ (obj_desc, sizeof(union acpi_operand_object))) {
+ acpi_os_printf
+ ("Invalid internal ACPI Object at address %p\n",
+ obj_desc);
+ return;
+ }
+
+ acpi_ut_debug_dump_buffer((void *)obj_desc,
+ sizeof(union acpi_operand_object),
+ display, ACPI_UINT32_MAX);
+ acpi_ex_dump_object_descriptor(obj_desc, 1);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_method_info
+ *
+ * PARAMETERS: start_op - Root of the control method parse tree
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display information about the current method
+ *
+ ******************************************************************************/
+
+void acpi_db_display_method_info(union acpi_parse_object *start_op)
+{
+ struct acpi_walk_state *walk_state;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *root_op;
+ union acpi_parse_object *op;
+ const struct acpi_opcode_info *op_info;
+ u32 num_ops = 0;
+ u32 num_operands = 0;
+ u32 num_operators = 0;
+ u32 num_remaining_ops = 0;
+ u32 num_remaining_operands = 0;
+ u32 num_remaining_operators = 0;
+ u8 count_remaining = FALSE;
+
+ walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
+ if (!walk_state) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ obj_desc = walk_state->method_desc;
+ node = walk_state->method_node;
+
+ acpi_os_printf("Currently executing control method is [%4.4s]\n",
+ acpi_ut_get_node_name(node));
+ acpi_os_printf("%X Arguments, SyncLevel = %X\n",
+ (u32)obj_desc->method.param_count,
+ (u32)obj_desc->method.sync_level);
+
+ root_op = start_op;
+ while (root_op->common.parent) {
+ root_op = root_op->common.parent;
+ }
+
+ op = root_op;
+
+ while (op) {
+ if (op == start_op) {
+ count_remaining = TRUE;
+ }
+
+ num_ops++;
+ if (count_remaining) {
+ num_remaining_ops++;
+ }
+
+ /* Decode the opcode */
+
+ op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
+ switch (op_info->class) {
+ case AML_CLASS_ARGUMENT:
+
+ if (count_remaining) {
+ num_remaining_operands++;
+ }
+
+ num_operands++;
+ break;
+
+ case AML_CLASS_UNKNOWN:
+
+ /* Bad opcode or ASCII character */
+
+ continue;
+
+ default:
+
+ if (count_remaining) {
+ num_remaining_operators++;
+ }
+
+ num_operators++;
+ break;
+ }
+
+ op = acpi_ps_get_depth_next(start_op, op);
+ }
+
+ acpi_os_printf
+ ("Method contains: %X AML Opcodes - %X Operators, %X Operands\n",
+ num_ops, num_operators, num_operands);
+
+ acpi_os_printf
+ ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n",
+ num_remaining_ops, num_remaining_operators,
+ num_remaining_operands);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_locals
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display all locals for the currently running control method
+ *
+ ******************************************************************************/
+
+void acpi_db_display_locals(void)
+{
+ struct acpi_walk_state *walk_state;
+
+ walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
+ if (!walk_state) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ acpi_db_decode_locals(walk_state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_arguments
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display all arguments for the currently running control method
+ *
+ ******************************************************************************/
+
+void acpi_db_display_arguments(void)
+{
+ struct acpi_walk_state *walk_state;
+
+ walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
+ if (!walk_state) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ acpi_db_decode_arguments(walk_state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_results
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display current contents of a method result stack
+ *
+ ******************************************************************************/
+
+void acpi_db_display_results(void)
+{
+ u32 i;
+ struct acpi_walk_state *walk_state;
+ union acpi_operand_object *obj_desc;
+ u32 result_count = 0;
+ struct acpi_namespace_node *node;
+ union acpi_generic_state *frame;
+ u32 index; /* Index onto current frame */
+
+ walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
+ if (!walk_state) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ obj_desc = walk_state->method_desc;
+ node = walk_state->method_node;
+
+ if (walk_state->results) {
+ result_count = walk_state->result_count;
+ }
+
+ acpi_os_printf("Method [%4.4s] has %X stacked result objects\n",
+ acpi_ut_get_node_name(node), result_count);
+
+ /* From the top element of result stack */
+
+ frame = walk_state->results;
+ index = (result_count - 1) % ACPI_RESULTS_FRAME_OBJ_NUM;
+
+ for (i = 0; i < result_count; i++) {
+ obj_desc = frame->results.obj_desc[index];
+ acpi_os_printf("Result%u: ", i);
+ acpi_db_display_internal_object(obj_desc, walk_state);
+
+ if (index == 0) {
+ frame = frame->results.next;
+ index = ACPI_RESULTS_FRAME_OBJ_NUM;
+ }
+
+ index--;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_calling_tree
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display current calling tree of nested control methods
+ *
+ ******************************************************************************/
+
+void acpi_db_display_calling_tree(void)
+{
+ struct acpi_walk_state *walk_state;
+ struct acpi_namespace_node *node;
+
+ walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
+ if (!walk_state) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ node = walk_state->method_node;
+ acpi_os_printf("Current Control Method Call Tree\n");
+
+ while (walk_state) {
+ node = walk_state->method_node;
+ acpi_os_printf(" [%4.4s]\n", acpi_ut_get_node_name(node));
+
+ walk_state = walk_state->next;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_object_type
+ *
+ * PARAMETERS: name - User entered NS node handle or name
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display type of an arbitrary NS node
+ *
+ ******************************************************************************/
+
+void acpi_db_display_object_type(char *name)
+{
+ struct acpi_namespace_node *node;
+ struct acpi_device_info *info;
+ acpi_status status;
+ u32 i;
+
+ node = acpi_db_convert_to_node(name);
+ if (!node) {
+ return;
+ }
+
+ status = acpi_get_object_info(ACPI_CAST_PTR(acpi_handle, node), &info);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not get object info, %s\n",
+ acpi_format_exception(status));
+ return;
+ }
+
+ if (info->valid & ACPI_VALID_ADR) {
+ acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
+ ACPI_FORMAT_UINT64(info->address),
+ info->current_status, info->flags);
+ }
+ if (info->valid & ACPI_VALID_SXDS) {
+ acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
+ info->highest_dstates[0],
+ info->highest_dstates[1],
+ info->highest_dstates[2],
+ info->highest_dstates[3]);
+ }
+ if (info->valid & ACPI_VALID_SXWS) {
+ acpi_os_printf
+ ("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n",
+ info->lowest_dstates[0], info->lowest_dstates[1],
+ info->lowest_dstates[2], info->lowest_dstates[3],
+ info->lowest_dstates[4]);
+ }
+
+ if (info->valid & ACPI_VALID_HID) {
+ acpi_os_printf("HID: %s\n", info->hardware_id.string);
+ }
+
+ if (info->valid & ACPI_VALID_UID) {
+ acpi_os_printf("UID: %s\n", info->unique_id.string);
+ }
+
+ if (info->valid & ACPI_VALID_SUB) {
+ acpi_os_printf("SUB: %s\n", info->subsystem_id.string);
+ }
+
+ if (info->valid & ACPI_VALID_CID) {
+ for (i = 0; i < info->compatible_id_list.count; i++) {
+ acpi_os_printf("CID %u: %s\n", i,
+ info->compatible_id_list.ids[i].string);
+ }
+ }
+
+ ACPI_FREE(info);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_result_object
+ *
+ * PARAMETERS: obj_desc - Object to be displayed
+ * walk_state - Current walk state
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display the result of an AML opcode
+ *
+ * Note: Curently 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.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_result_object(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
+{
+
+ /* Only display if single stepping */
+
+ if (!acpi_gbl_cm_single_step) {
+ return;
+ }
+
+ acpi_os_printf("ResultObj: ");
+ acpi_db_display_internal_object(obj_desc, walk_state);
+ acpi_os_printf("\n");
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_argument_object
+ *
+ * PARAMETERS: obj_desc - Object to be displayed
+ * walk_state - Current walk state
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display the result of an AML opcode
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
+{
+
+ if (!acpi_gbl_cm_single_step) {
+ return;
+ }
+
+ acpi_os_printf("ArgObj: ");
+ acpi_db_display_internal_object(obj_desc, walk_state);
+}
+
+#if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_gpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display the current GPE structures
+ *
+ ******************************************************************************/
+
+void acpi_db_display_gpes(void)
+{
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_gpe_register_info *gpe_register_info;
+ char *gpe_type;
+ struct acpi_gpe_notify_info *notify;
+ u32 gpe_index;
+ u32 block = 0;
+ u32 i;
+ u32 j;
+ u32 count;
+ char buffer[80];
+ struct acpi_buffer ret_buf;
+ acpi_status status;
+
+ ret_buf.length = sizeof(buffer);
+ ret_buf.pointer = buffer;
+
+ block = 0;
+
+ /* Walk the GPE lists */
+
+ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
+ while (gpe_xrupt_info) {
+ gpe_block = gpe_xrupt_info->gpe_block_list_head;
+ while (gpe_block) {
+ status = acpi_get_name(gpe_block->node,
+ ACPI_FULL_PATHNAME_NO_TRAILING,
+ &ret_buf);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("Could not convert name to pathname\n");
+ }
+
+ if (gpe_block->node == acpi_gbl_fadt_gpe_device) {
+ gpe_type = "FADT-defined GPE block";
+ } else {
+ gpe_type = "GPE Block Device";
+ }
+
+ acpi_os_printf
+ ("\nBlock %u - Info %p DeviceNode %p [%s] - %s\n",
+ block, gpe_block, gpe_block->node, buffer,
+ gpe_type);
+
+ acpi_os_printf(" Registers: %u (%u GPEs)\n",
+ gpe_block->register_count,
+ gpe_block->gpe_count);
+
+ acpi_os_printf
+ (" GPE range: 0x%X to 0x%X on interrupt %u\n",
+ gpe_block->block_base_number,
+ gpe_block->block_base_number +
+ (gpe_block->gpe_count - 1),
+ gpe_xrupt_info->interrupt_number);
+
+ acpi_os_printf
+ (" RegisterInfo: %p Status %8.8X%8.8X Enable %8.8X%8.8X\n",
+ gpe_block->register_info,
+ ACPI_FORMAT_UINT64(gpe_block->register_info->
+ status_address.address),
+ ACPI_FORMAT_UINT64(gpe_block->register_info->
+ enable_address.address));
+
+ acpi_os_printf(" EventInfo: %p\n",
+ gpe_block->event_info);
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < gpe_block->register_count; i++) {
+ gpe_register_info =
+ &gpe_block->register_info[i];
+
+ acpi_os_printf(" Reg %u: (GPE %.2X-%.2X) "
+ "RunEnable %2.2X WakeEnable %2.2X"
+ " Status %8.8X%8.8X Enable %8.8X%8.8X\n",
+ i,
+ gpe_register_info->
+ base_gpe_number,
+ gpe_register_info->
+ base_gpe_number +
+ (ACPI_GPE_REGISTER_WIDTH - 1),
+ gpe_register_info->
+ enable_for_run,
+ gpe_register_info->
+ enable_for_wake,
+ ACPI_FORMAT_UINT64
+ (gpe_register_info->
+ status_address.address),
+ ACPI_FORMAT_UINT64
+ (gpe_register_info->
+ enable_address.address));
+
+ /* Now look at the individual GPEs in this byte register */
+
+ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+ gpe_index =
+ (i * ACPI_GPE_REGISTER_WIDTH) + j;
+ gpe_event_info =
+ &gpe_block->event_info[gpe_index];
+
+ if (ACPI_GPE_DISPATCH_TYPE
+ (gpe_event_info->flags) ==
+ ACPI_GPE_DISPATCH_NONE) {
+
+ /* This GPE is not used (no method or handler), ignore it */
+
+ continue;
+ }
+
+ acpi_os_printf
+ (" GPE %.2X: %p RunRefs %2.2X Flags %2.2X (",
+ gpe_block->block_base_number +
+ gpe_index, gpe_event_info,
+ gpe_event_info->runtime_count,
+ gpe_event_info->flags);
+
+ /* Decode the flags byte */
+
+ if (gpe_event_info->
+ flags & ACPI_GPE_LEVEL_TRIGGERED) {
+ acpi_os_printf("Level, ");
+ } else {
+ acpi_os_printf("Edge, ");
+ }
+
+ if (gpe_event_info->
+ flags & ACPI_GPE_CAN_WAKE) {
+ acpi_os_printf("CanWake, ");
+ } else {
+ acpi_os_printf("RunOnly, ");
+ }
+
+ switch (ACPI_GPE_DISPATCH_TYPE
+ (gpe_event_info->flags)) {
+ case ACPI_GPE_DISPATCH_NONE:
+
+ acpi_os_printf("NotUsed");
+ break;
+
+ case ACPI_GPE_DISPATCH_METHOD:
+
+ acpi_os_printf("Method");
+ break;
+
+ case ACPI_GPE_DISPATCH_HANDLER:
+
+ acpi_os_printf("Handler");
+ break;
+
+ case ACPI_GPE_DISPATCH_NOTIFY:
+
+ count = 0;
+ notify =
+ gpe_event_info->dispatch.
+ notify_list;
+ while (notify) {
+ count++;
+ notify = notify->next;
+ }
+
+ acpi_os_printf
+ ("Implicit Notify on %u devices",
+ count);
+ break;
+
+ case ACPI_GPE_DISPATCH_RAW_HANDLER:
+
+ acpi_os_printf("RawHandler");
+ break;
+
+ default:
+
+ acpi_os_printf("UNKNOWN: %X",
+ ACPI_GPE_DISPATCH_TYPE
+ (gpe_event_info->
+ flags));
+ break;
+ }
+
+ acpi_os_printf(")\n");
+ }
+ }
+
+ block++;
+ gpe_block = gpe_block->next;
+ }
+
+ gpe_xrupt_info = gpe_xrupt_info->next;
+ }
+}
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_handlers
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display the currently installed global handlers
+ *
+ ******************************************************************************/
+
+void acpi_db_display_handlers(void)
+{
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ acpi_adr_space_type space_id;
+ u32 i;
+
+ /* Operation region handlers */
+
+ acpi_os_printf("\nOperation Region Handlers at the namespace root:\n");
+
+ obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
+ if (obj_desc) {
+ for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_space_id_list); i++) {
+ space_id = acpi_gbl_space_id_list[i];
+ handler_obj = obj_desc->device.handler;
+
+ acpi_os_printf(ACPI_PREDEFINED_PREFIX,
+ acpi_ut_get_region_name((u8)space_id),
+ space_id);
+
+ while (handler_obj) {
+ if (acpi_gbl_space_id_list[i] ==
+ handler_obj->address_space.space_id) {
+ acpi_os_printf
+ (ACPI_HANDLER_PRESENT_STRING,
+ (handler_obj->address_space.
+ handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
+ ? "Default" : "User",
+ handler_obj->address_space.
+ handler);
+
+ goto found_handler;
+ }
+
+ handler_obj = handler_obj->address_space.next;
+ }
+
+ /* There is no handler for this space_id */
+
+ acpi_os_printf("None\n");
+
+found_handler: ;
+ }
+
+ /* Find all handlers for user-defined space_IDs */
+
+ handler_obj = obj_desc->device.handler;
+ while (handler_obj) {
+ if (handler_obj->address_space.space_id >=
+ ACPI_USER_REGION_BEGIN) {
+ acpi_os_printf(ACPI_PREDEFINED_PREFIX,
+ "User-defined ID",
+ handler_obj->address_space.
+ space_id);
+ acpi_os_printf(ACPI_HANDLER_PRESENT_STRING,
+ (handler_obj->address_space.
+ handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
+ ? "Default" : "User",
+ handler_obj->address_space.
+ handler);
+ }
+
+ handler_obj = handler_obj->address_space.next;
+ }
+ }
+#if (!ACPI_REDUCED_HARDWARE)
+
+ /* Fixed event handlers */
+
+ acpi_os_printf("\nFixed Event Handlers:\n");
+
+ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+ acpi_os_printf(ACPI_PREDEFINED_PREFIX,
+ acpi_ut_get_event_name(i), i);
+ if (acpi_gbl_fixed_event_handlers[i].handler) {
+ acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User",
+ acpi_gbl_fixed_event_handlers[i].
+ handler);
+ } else {
+ acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None");
+ }
+ }
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+ /* Miscellaneous global handlers */
+
+ acpi_os_printf("\nMiscellaneous Global Handlers:\n");
+
+ for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_handler_list); i++) {
+ acpi_os_printf(ACPI_HANDLER_NAME_STRING,
+ acpi_gbl_handler_list[i].name);
+
+ if (acpi_gbl_handler_list[i].handler) {
+ acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User",
+ acpi_gbl_handler_list[i].handler);
+ } else {
+ acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None");
+ }
+ }
+
+ /* Other handlers that are installed throughout the namespace */
+
+ acpi_os_printf("\nOperation Region Handlers for specific devices:\n");
+
+ (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_db_display_non_root_handlers, NULL, NULL,
+ NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_non_root_handlers
+ *
+ * PARAMETERS: acpi_walk_callback
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Display information about all handlers installed for a
+ * device object.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_display_non_root_handlers(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_namespace_node *node =
+ ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ char *pathname;
+
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (!obj_desc) {
+ return (AE_OK);
+ }
+
+ pathname = acpi_ns_get_external_pathname(node);
+ if (!pathname) {
+ return (AE_OK);
+ }
+
+ /* Display all handlers associated with this device */
+
+ handler_obj = obj_desc->device.handler;
+ while (handler_obj) {
+ acpi_os_printf(ACPI_PREDEFINED_PREFIX,
+ acpi_ut_get_region_name((u8)handler_obj->
+ address_space.space_id),
+ handler_obj->address_space.space_id);
+
+ acpi_os_printf(ACPI_HANDLER_PRESENT_STRING2,
+ (handler_obj->address_space.handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default"
+ : "User", handler_obj->address_space.handler);
+
+ acpi_os_printf(" Device Name: %s (%p)\n", pathname, node);
+
+ handler_obj = handler_obj->address_space.next;
+ }
+
+ ACPI_FREE(pathname);
+ return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/dbexec.c b/drivers/acpi/acpica/dbexec.c
new file mode 100644
index 000000000000..d713e2df65b9
--- /dev/null
+++ b/drivers/acpi/acpica/dbexec.c
@@ -0,0 +1,764 @@
+/*******************************************************************************
+ *
+ * Module Name: dbexec - debugger control method execution
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+#include "acnamesp.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbexec")
+
+static struct acpi_db_method_info acpi_gbl_db_method_info;
+
+/* Local prototypes */
+
+static acpi_status
+acpi_db_execute_method(struct acpi_db_method_info *info,
+ struct acpi_buffer *return_obj);
+
+static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info);
+
+static u32 acpi_db_get_outstanding_allocations(void);
+
+static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context);
+
+static acpi_status
+acpi_db_execution_walk(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_delete_objects
+ *
+ * PARAMETERS: count - Count of objects in the list
+ * objects - Array of ACPI_OBJECTs to be deleted
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
+ * packages via recursion.
+ *
+ ******************************************************************************/
+
+void acpi_db_delete_objects(u32 count, union acpi_object *objects)
+{
+ u32 i;
+
+ for (i = 0; i < count; i++) {
+ switch (objects[i].type) {
+ case ACPI_TYPE_BUFFER:
+
+ ACPI_FREE(objects[i].buffer.pointer);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ /* Recursive call to delete package elements */
+
+ acpi_db_delete_objects(objects[i].package.count,
+ objects[i].package.elements);
+
+ /* Free the elements array */
+
+ ACPI_FREE(objects[i].package.elements);
+ break;
+
+ default:
+
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_execute_method
+ *
+ * PARAMETERS: info - Valid info segment
+ * return_obj - Where to put return object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute a control method.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_execute_method(struct acpi_db_method_info *info,
+ struct acpi_buffer *return_obj)
+{
+ acpi_status status;
+ struct acpi_object_list param_objects;
+ union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1];
+ u32 i;
+
+ ACPI_FUNCTION_TRACE(db_execute_method);
+
+ if (acpi_gbl_db_output_to_file && !acpi_dbg_level) {
+ acpi_os_printf("Warning: debug output is not enabled!\n");
+ }
+
+ param_objects.count = 0;
+ param_objects.pointer = NULL;
+
+ /* Pass through any command-line arguments */
+
+ if (info->args && info->args[0]) {
+
+ /* Get arguments passed on the command line */
+
+ for (i = 0; (info->args[i] && *(info->args[i])); i++) {
+
+ /* Convert input string (token) to an actual union acpi_object */
+
+ status = acpi_db_convert_to_object(info->types[i],
+ info->args[i],
+ &params[i]);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While parsing method arguments"));
+ goto cleanup;
+ }
+ }
+
+ param_objects.count = i;
+ param_objects.pointer = params;
+ }
+
+ /* Prepare for a return object of arbitrary size */
+
+ return_obj->pointer = acpi_gbl_db_buffer;
+ return_obj->length = ACPI_DEBUG_BUFFER_SIZE;
+
+ /* Do the actual method execution */
+
+ acpi_gbl_method_executing = TRUE;
+ status = acpi_evaluate_object(NULL, info->pathname,
+ &param_objects, return_obj);
+
+ acpi_gbl_cm_single_step = FALSE;
+ acpi_gbl_method_executing = FALSE;
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "while executing %s from debugger",
+ info->pathname));
+
+ if (status == AE_BUFFER_OVERFLOW) {
+ ACPI_ERROR((AE_INFO,
+ "Possible overflow of internal debugger "
+ "buffer (size 0x%X needed 0x%X)",
+ ACPI_DEBUG_BUFFER_SIZE,
+ (u32)return_obj->length));
+ }
+ }
+
+cleanup:
+ acpi_db_delete_objects(param_objects.count, params);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_execute_setup
+ *
+ * PARAMETERS: info - Valid method info
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Setup info segment prior to method execution
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_NAME(db_execute_setup);
+
+ /* Catenate the current scope to the supplied name */
+
+ info->pathname[0] = 0;
+ if ((info->name[0] != '\\') && (info->name[0] != '/')) {
+ if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
+ acpi_gbl_db_scope_buf)) {
+ status = AE_BUFFER_OVERFLOW;
+ goto error_exit;
+ }
+ }
+
+ if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
+ info->name)) {
+ status = AE_BUFFER_OVERFLOW;
+ goto error_exit;
+ }
+
+ acpi_db_prep_namestring(info->pathname);
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+ acpi_os_printf("Evaluating %s\n", info->pathname);
+
+ if (info->flags & EX_SINGLE_STEP) {
+ acpi_gbl_cm_single_step = TRUE;
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+ }
+
+ else {
+ /* No single step, allow redirection to a file */
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ }
+
+ return (AE_OK);
+
+error_exit:
+
+ ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution"));
+ return (status);
+}
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+u32 acpi_db_get_cache_info(struct acpi_memory_list *cache)
+{
+
+ return (cache->total_allocated - cache->total_freed -
+ cache->current_depth);
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_outstanding_allocations
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Current global allocation count minus cache entries
+ *
+ * DESCRIPTION: Determine the current number of "outstanding" allocations --
+ * those allocations that have not been freed and also are not
+ * in one of the various object caches.
+ *
+ ******************************************************************************/
+
+static u32 acpi_db_get_outstanding_allocations(void)
+{
+ u32 outstanding = 0;
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+ outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache);
+ outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache);
+ outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache);
+ outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache);
+#endif
+
+ return (outstanding);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_execution_walk
+ *
+ * PARAMETERS: WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute a control method. Name is relative to the current
+ * scope.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_execution_walk(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
+{
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ struct acpi_buffer return_obj;
+ acpi_status status;
+
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (obj_desc->method.param_count) {
+ return (AE_OK);
+ }
+
+ return_obj.pointer = NULL;
+ return_obj.length = ACPI_ALLOCATE_BUFFER;
+
+ acpi_ns_print_node_pathname(node, "Evaluating");
+
+ /* Do the actual method execution */
+
+ acpi_os_printf("\n");
+ acpi_gbl_method_executing = TRUE;
+
+ status = acpi_evaluate_object(node, NULL, NULL, &return_obj);
+
+ acpi_os_printf("Evaluation of [%4.4s] returned %s\n",
+ acpi_ut_get_node_name(node),
+ acpi_format_exception(status));
+
+ acpi_gbl_method_executing = FALSE;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_execute
+ *
+ * PARAMETERS: name - Name of method to execute
+ * args - Parameters to the method
+ * Types -
+ * flags - single step/no single step
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Execute a control method. Name is relative to the current
+ * scope.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags)
+{
+ acpi_status status;
+ struct acpi_buffer return_obj;
+ char *name_string;
+
+#ifdef ACPI_DEBUG_OUTPUT
+ u32 previous_allocations;
+ u32 allocations;
+#endif
+
+ /*
+ * Allow one execution to be performed by debugger or single step
+ * execution will be dead locked by the interpreter mutexes.
+ */
+ if (acpi_gbl_method_executing) {
+ acpi_os_printf("Only one debugger execution is allowed.\n");
+ return;
+ }
+#ifdef ACPI_DEBUG_OUTPUT
+ /* Memory allocation tracking */
+
+ previous_allocations = acpi_db_get_outstanding_allocations();
+#endif
+
+ if (*name == '*') {
+ (void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_db_execution_walk, NULL, NULL,
+ NULL);
+ return;
+ } else {
+ name_string = ACPI_ALLOCATE(strlen(name) + 1);
+ if (!name_string) {
+ return;
+ }
+
+ memset(&acpi_gbl_db_method_info, 0,
+ sizeof(struct acpi_db_method_info));
+
+ strcpy(name_string, name);
+ acpi_ut_strupr(name_string);
+ acpi_gbl_db_method_info.name = name_string;
+ acpi_gbl_db_method_info.args = args;
+ acpi_gbl_db_method_info.types = types;
+ acpi_gbl_db_method_info.flags = flags;
+
+ return_obj.pointer = NULL;
+ return_obj.length = ACPI_ALLOCATE_BUFFER;
+
+ status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(name_string);
+ return;
+ }
+
+ /* Get the NS node, determines existence also */
+
+ status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
+ &acpi_gbl_db_method_info.method);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_db_execute_method(&acpi_gbl_db_method_info,
+ &return_obj);
+ }
+ ACPI_FREE(name_string);
+ }
+
+ /*
+ * Allow any handlers in separate threads to complete.
+ * (Such as Notify handlers invoked from AML executed above).
+ */
+ acpi_os_sleep((u64)10);
+
+#ifdef ACPI_DEBUG_OUTPUT
+
+ /* Memory allocation tracking */
+
+ allocations =
+ acpi_db_get_outstanding_allocations() - previous_allocations;
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+
+ if (allocations > 0) {
+ acpi_os_printf
+ ("0x%X Outstanding allocations after evaluation of %s\n",
+ allocations, acpi_gbl_db_method_info.pathname);
+ }
+#endif
+
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Evaluation of %s failed with status %s\n",
+ acpi_gbl_db_method_info.pathname,
+ acpi_format_exception(status));
+ } else {
+ /* Display a return object, if any */
+
+ if (return_obj.length) {
+ acpi_os_printf("Evaluation of %s returned object %p, "
+ "external buffer length %X\n",
+ acpi_gbl_db_method_info.pathname,
+ return_obj.pointer,
+ (u32)return_obj.length);
+
+ acpi_db_dump_external_object(return_obj.pointer, 1);
+
+ /* Dump a _PLD buffer if present */
+
+ if (ACPI_COMPARE_NAME
+ ((ACPI_CAST_PTR
+ (struct acpi_namespace_node,
+ acpi_gbl_db_method_info.method)->name.ascii),
+ METHOD_NAME__PLD)) {
+ acpi_db_dump_pld_buffer(return_obj.pointer);
+ }
+ } else {
+ acpi_os_printf
+ ("No object was returned from evaluation of %s\n",
+ acpi_gbl_db_method_info.pathname);
+ }
+ }
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_method_thread
+ *
+ * PARAMETERS: context - Execution info segment
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Debugger execute thread. Waits for a command line, then
+ * simply dispatches it.
+ *
+ ******************************************************************************/
+
+static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context)
+{
+ acpi_status status;
+ struct acpi_db_method_info *info = context;
+ struct acpi_db_method_info local_info;
+ u32 i;
+ u8 allow;
+ struct acpi_buffer return_obj;
+
+ /*
+ * acpi_gbl_db_method_info.Arguments will be passed as method arguments.
+ * Prevent acpi_gbl_db_method_info from being modified by multiple threads
+ * concurrently.
+ *
+ * Note: The arguments we are passing are used by the ASL test suite
+ * (aslts). Do not change them without updating the tests.
+ */
+ (void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER);
+
+ if (info->init_args) {
+ acpi_db_uint32_to_hex_string(info->num_created,
+ info->index_of_thread_str);
+ acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(),
+ info->id_of_thread_str);
+ }
+
+ if (info->threads && (info->num_created < info->num_threads)) {
+ info->threads[info->num_created++] = acpi_os_get_thread_id();
+ }
+
+ local_info = *info;
+ local_info.args = local_info.arguments;
+ local_info.arguments[0] = local_info.num_threads_str;
+ local_info.arguments[1] = local_info.id_of_thread_str;
+ local_info.arguments[2] = local_info.index_of_thread_str;
+ local_info.arguments[3] = NULL;
+
+ local_info.types = local_info.arg_types;
+
+ (void)acpi_os_signal_semaphore(info->info_gate, 1);
+
+ for (i = 0; i < info->num_loops; i++) {
+ status = acpi_db_execute_method(&local_info, &return_obj);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("%s During evaluation of %s at iteration %X\n",
+ acpi_format_exception(status), info->pathname, i);
+ if (status == AE_ABORT_METHOD) {
+ break;
+ }
+ }
+#if 0
+ if ((i % 100) == 0) {
+ acpi_os_printf("%u loops, Thread 0x%x\n",
+ i, acpi_os_get_thread_id());
+ }
+
+ if (return_obj.length) {
+ acpi_os_printf
+ ("Evaluation of %s returned object %p Buflen %X\n",
+ info->pathname, return_obj.pointer,
+ (u32)return_obj.length);
+ acpi_db_dump_external_object(return_obj.pointer, 1);
+ }
+#endif
+ }
+
+ /* Signal our completion */
+
+ allow = 0;
+ (void)acpi_os_wait_semaphore(info->thread_complete_gate,
+ 1, ACPI_WAIT_FOREVER);
+ info->num_completed++;
+
+ if (info->num_completed == info->num_threads) {
+
+ /* Do signal for main thread once only */
+ allow = 1;
+ }
+
+ (void)acpi_os_signal_semaphore(info->thread_complete_gate, 1);
+
+ if (allow) {
+ status = acpi_os_signal_semaphore(info->main_thread_gate, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("Could not signal debugger thread sync semaphore, %s\n",
+ acpi_format_exception(status));
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_create_execution_threads
+ *
+ * PARAMETERS: num_threads_arg - Number of threads to create
+ * num_loops_arg - Loop count for the thread(s)
+ * method_name_arg - Control method to execute
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Create threads to execute method(s)
+ *
+ ******************************************************************************/
+
+void
+acpi_db_create_execution_threads(char *num_threads_arg,
+ char *num_loops_arg, char *method_name_arg)
+{
+ acpi_status status;
+ u32 num_threads;
+ u32 num_loops;
+ u32 i;
+ u32 size;
+ acpi_mutex main_thread_gate;
+ acpi_mutex thread_complete_gate;
+ acpi_mutex info_gate;
+
+ /* Get the arguments */
+
+ num_threads = strtoul(num_threads_arg, NULL, 0);
+ num_loops = strtoul(num_loops_arg, NULL, 0);
+
+ if (!num_threads || !num_loops) {
+ acpi_os_printf("Bad argument: Threads %X, Loops %X\n",
+ num_threads, num_loops);
+ return;
+ }
+
+ /*
+ * Create the semaphore for synchronization of
+ * the created threads with the main thread.
+ */
+ status = acpi_os_create_semaphore(1, 0, &main_thread_gate);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not create semaphore for "
+ "synchronization with the main thread, %s\n",
+ acpi_format_exception(status));
+ return;
+ }
+
+ /*
+ * Create the semaphore for synchronization
+ * between the created threads.
+ */
+ status = acpi_os_create_semaphore(1, 1, &thread_complete_gate);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not create semaphore for "
+ "synchronization between the created threads, %s\n",
+ acpi_format_exception(status));
+
+ (void)acpi_os_delete_semaphore(main_thread_gate);
+ return;
+ }
+
+ status = acpi_os_create_semaphore(1, 1, &info_gate);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not create semaphore for "
+ "synchronization of AcpiGbl_DbMethodInfo, %s\n",
+ acpi_format_exception(status));
+
+ (void)acpi_os_delete_semaphore(thread_complete_gate);
+ (void)acpi_os_delete_semaphore(main_thread_gate);
+ return;
+ }
+
+ memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
+
+ /* Array to store IDs of threads */
+
+ acpi_gbl_db_method_info.num_threads = num_threads;
+ size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads;
+
+ acpi_gbl_db_method_info.threads = acpi_os_allocate(size);
+ if (acpi_gbl_db_method_info.threads == NULL) {
+ acpi_os_printf("No memory for thread IDs array\n");
+ (void)acpi_os_delete_semaphore(main_thread_gate);
+ (void)acpi_os_delete_semaphore(thread_complete_gate);
+ (void)acpi_os_delete_semaphore(info_gate);
+ return;
+ }
+ memset(acpi_gbl_db_method_info.threads, 0, size);
+
+ /* Setup the context to be passed to each thread */
+
+ acpi_gbl_db_method_info.name = method_name_arg;
+ acpi_gbl_db_method_info.flags = 0;
+ acpi_gbl_db_method_info.num_loops = num_loops;
+ acpi_gbl_db_method_info.main_thread_gate = main_thread_gate;
+ acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate;
+ acpi_gbl_db_method_info.info_gate = info_gate;
+
+ /* Init arguments to be passed to method */
+
+ acpi_gbl_db_method_info.init_args = 1;
+ acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
+ acpi_gbl_db_method_info.arguments[0] =
+ acpi_gbl_db_method_info.num_threads_str;
+ acpi_gbl_db_method_info.arguments[1] =
+ acpi_gbl_db_method_info.id_of_thread_str;
+ acpi_gbl_db_method_info.arguments[2] =
+ acpi_gbl_db_method_info.index_of_thread_str;
+ acpi_gbl_db_method_info.arguments[3] = NULL;
+
+ acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
+ acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER;
+ acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER;
+ acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER;
+
+ acpi_db_uint32_to_hex_string(num_threads,
+ acpi_gbl_db_method_info.num_threads_str);
+
+ status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup_and_exit;
+ }
+
+ /* Get the NS node, determines existence also */
+
+ status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
+ &acpi_gbl_db_method_info.method);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("%s Could not get handle for %s\n",
+ acpi_format_exception(status),
+ acpi_gbl_db_method_info.pathname);
+ goto cleanup_and_exit;
+ }
+
+ /* Create the threads */
+
+ acpi_os_printf("Creating %X threads to execute %X times each\n",
+ num_threads, num_loops);
+
+ for (i = 0; i < (num_threads); i++) {
+ status =
+ acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
+ acpi_db_method_thread,
+ &acpi_gbl_db_method_info);
+ if (ACPI_FAILURE(status)) {
+ break;
+ }
+ }
+
+ /* Wait for all threads to complete */
+
+ (void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER);
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+ acpi_os_printf("All threads (%X) have completed\n", num_threads);
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+
+cleanup_and_exit:
+
+ /* Cleanup and exit */
+
+ (void)acpi_os_delete_semaphore(main_thread_gate);
+ (void)acpi_os_delete_semaphore(thread_complete_gate);
+ (void)acpi_os_delete_semaphore(info_gate);
+
+ acpi_os_free(acpi_gbl_db_method_info.threads);
+ acpi_gbl_db_method_info.threads = NULL;
+}
diff --git a/drivers/acpi/acpica/dbfileio.c b/drivers/acpi/acpica/dbfileio.c
new file mode 100644
index 000000000000..d0e6b20ce82a
--- /dev/null
+++ b/drivers/acpi/acpica/dbfileio.c
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ *
+ * Module Name: dbfileio - Debugger file I/O commands. These can't usually
+ * be used when running the debugger in Ring 0 (Kernel mode)
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+#include "actables.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbfileio")
+
+#ifdef ACPI_DEBUGGER
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_close_debug_file
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: If open, close the current debug output file
+ *
+ ******************************************************************************/
+void acpi_db_close_debug_file(void)
+{
+
+#ifdef ACPI_APPLICATION
+
+ if (acpi_gbl_debug_file) {
+ fclose(acpi_gbl_debug_file);
+ acpi_gbl_debug_file = NULL;
+ acpi_gbl_db_output_to_file = FALSE;
+ acpi_os_printf("Debug output file %s closed\n",
+ acpi_gbl_db_debug_filename);
+ }
+#endif
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_open_debug_file
+ *
+ * PARAMETERS: name - Filename to open
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Open a file where debug output will be directed.
+ *
+ ******************************************************************************/
+
+void acpi_db_open_debug_file(char *name)
+{
+
+#ifdef ACPI_APPLICATION
+
+ acpi_db_close_debug_file();
+ acpi_gbl_debug_file = fopen(name, "w+");
+ if (!acpi_gbl_debug_file) {
+ acpi_os_printf("Could not open debug file %s\n", name);
+ return;
+ }
+
+ acpi_os_printf("Debug output file %s opened\n", name);
+ strncpy(acpi_gbl_db_debug_filename, name,
+ sizeof(acpi_gbl_db_debug_filename));
+ acpi_gbl_db_output_to_file = TRUE;
+
+#endif
+}
+#endif
+
+#ifdef ACPI_APPLICATION
+#include "acapps.h"
+
+/*******************************************************************************
+ *
+ * FUNCTION: ae_local_load_table
+ *
+ * PARAMETERS: table - pointer to a buffer containing the entire
+ * table to be loaded
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function is called to load a table from the caller's
+ * buffer. The buffer must contain an entire ACPI Table including
+ * a valid header. The header fields will be verified, and if it
+ * is determined that the table is invalid, the call will fail.
+ *
+ ******************************************************************************/
+
+static acpi_status ae_local_load_table(struct acpi_table_header *table)
+{
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE(ae_local_load_table);
+
+#if 0
+/* struct acpi_table_desc table_info; */
+
+ if (!table) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ table_info.pointer = table;
+ status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Install the new table into the local data structures */
+
+ status = acpi_tb_init_table_descriptor(&table_info);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_ALREADY_EXISTS) {
+
+ /* Table already exists, no error */
+
+ status = AE_OK;
+ }
+
+ /* Free table allocated by acpi_tb_get_table */
+
+ acpi_tb_delete_single_table(&table_info);
+ return_ACPI_STATUS(status);
+ }
+#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
+
+ status =
+ acpi_ns_load_table(table_info.installed_desc, acpi_gbl_root_node);
+ if (ACPI_FAILURE(status)) {
+
+ /* Uninstall table and free the buffer */
+
+ acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_DSDT);
+ return_ACPI_STATUS(status);
+ }
+#endif
+#endif
+
+ return_ACPI_STATUS(status);
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_table_from_file
+ *
+ * PARAMETERS: filename - File where table is located
+ * return_table - Where a pointer to the table is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load an ACPI table from a file
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_db_get_table_from_file(char *filename,
+ struct acpi_table_header **return_table,
+ u8 must_be_aml_file)
+{
+#ifdef ACPI_APPLICATION
+ acpi_status status;
+ struct acpi_table_header *table;
+ u8 is_aml_table = TRUE;
+
+ status = acpi_ut_read_table_from_file(filename, &table);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ if (must_be_aml_file) {
+ is_aml_table = acpi_ut_is_aml_table(table);
+ if (!is_aml_table) {
+ ACPI_EXCEPTION((AE_INFO, AE_OK,
+ "Input for -e is not an AML table: "
+ "\"%4.4s\" (must be DSDT/SSDT)",
+ table->signature));
+ return (AE_TYPE);
+ }
+ }
+
+ if (is_aml_table) {
+
+ /* Attempt to recognize and install the table */
+
+ status = ae_local_load_table(table);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_ALREADY_EXISTS) {
+ acpi_os_printf
+ ("Table %4.4s is already installed\n",
+ table->signature);
+ } else {
+ acpi_os_printf("Could not install table, %s\n",
+ acpi_format_exception(status));
+ }
+
+ return (status);
+ }
+
+ acpi_tb_print_table_header(0, table);
+
+ fprintf(stderr,
+ "Acpi table [%4.4s] successfully installed and loaded\n",
+ table->signature);
+ }
+
+ acpi_gbl_acpi_hardware_present = FALSE;
+ if (return_table) {
+ *return_table = table;
+ }
+
+#endif /* ACPI_APPLICATION */
+ return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/dbhistry.c b/drivers/acpi/acpica/dbhistry.c
new file mode 100644
index 000000000000..9c66a9eadd38
--- /dev/null
+++ b/drivers/acpi/acpica/dbhistry.c
@@ -0,0 +1,239 @@
+/******************************************************************************
+ *
+ * Module Name: dbhistry - debugger HISTORY command
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbhistry")
+
+#define HI_NO_HISTORY 0
+#define HI_RECORD_HISTORY 1
+#define HISTORY_SIZE 40
+typedef struct history_info {
+ char *command;
+ u32 cmd_num;
+
+} HISTORY_INFO;
+
+static HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE];
+static u16 acpi_gbl_lo_history = 0;
+static u16 acpi_gbl_num_history = 0;
+static u16 acpi_gbl_next_history_index = 0;
+u32 acpi_gbl_next_cmd_num = 1;
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_add_to_history
+ *
+ * PARAMETERS: command_line - Command to add
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Add a command line to the history buffer.
+ *
+ ******************************************************************************/
+
+void acpi_db_add_to_history(char *command_line)
+{
+ u16 cmd_len;
+ u16 buffer_len;
+
+ /* Put command into the next available slot */
+
+ cmd_len = (u16)strlen(command_line);
+ if (!cmd_len) {
+ return;
+ }
+
+ if (acpi_gbl_history_buffer[acpi_gbl_next_history_index].command !=
+ NULL) {
+ buffer_len =
+ (u16)
+ strlen(acpi_gbl_history_buffer[acpi_gbl_next_history_index].
+ command);
+
+ if (cmd_len > buffer_len) {
+ acpi_os_free(acpi_gbl_history_buffer
+ [acpi_gbl_next_history_index].command);
+ acpi_gbl_history_buffer[acpi_gbl_next_history_index].
+ command = acpi_os_allocate(cmd_len + 1);
+ }
+ } else {
+ acpi_gbl_history_buffer[acpi_gbl_next_history_index].command =
+ acpi_os_allocate(cmd_len + 1);
+ }
+
+ strcpy(acpi_gbl_history_buffer[acpi_gbl_next_history_index].command,
+ command_line);
+
+ acpi_gbl_history_buffer[acpi_gbl_next_history_index].cmd_num =
+ acpi_gbl_next_cmd_num;
+
+ /* Adjust indexes */
+
+ if ((acpi_gbl_num_history == HISTORY_SIZE) &&
+ (acpi_gbl_next_history_index == acpi_gbl_lo_history)) {
+ acpi_gbl_lo_history++;
+ if (acpi_gbl_lo_history >= HISTORY_SIZE) {
+ acpi_gbl_lo_history = 0;
+ }
+ }
+
+ acpi_gbl_next_history_index++;
+ if (acpi_gbl_next_history_index >= HISTORY_SIZE) {
+ acpi_gbl_next_history_index = 0;
+ }
+
+ acpi_gbl_next_cmd_num++;
+ if (acpi_gbl_num_history < HISTORY_SIZE) {
+ acpi_gbl_num_history++;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_history
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display the contents of the history buffer
+ *
+ ******************************************************************************/
+
+void acpi_db_display_history(void)
+{
+ u32 i;
+ u16 history_index;
+
+ history_index = acpi_gbl_lo_history;
+
+ /* Dump entire history buffer */
+
+ for (i = 0; i < acpi_gbl_num_history; i++) {
+ if (acpi_gbl_history_buffer[history_index].command) {
+ acpi_os_printf("%3ld %s\n",
+ acpi_gbl_history_buffer[history_index].
+ cmd_num,
+ acpi_gbl_history_buffer[history_index].
+ command);
+ }
+
+ history_index++;
+ if (history_index >= HISTORY_SIZE) {
+ history_index = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_from_history
+ *
+ * PARAMETERS: command_num_arg - String containing the number of the
+ * command to be retrieved
+ *
+ * RETURN: Pointer to the retrieved command. Null on error.
+ *
+ * DESCRIPTION: Get a command from the history buffer
+ *
+ ******************************************************************************/
+
+char *acpi_db_get_from_history(char *command_num_arg)
+{
+ u32 cmd_num;
+
+ if (command_num_arg == NULL) {
+ cmd_num = acpi_gbl_next_cmd_num - 1;
+ }
+
+ else {
+ cmd_num = strtoul(command_num_arg, NULL, 0);
+ }
+
+ return (acpi_db_get_history_by_index(cmd_num));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_history_by_index
+ *
+ * PARAMETERS: cmd_num - Index of the desired history entry.
+ * Values are 0...(acpi_gbl_next_cmd_num - 1)
+ *
+ * RETURN: Pointer to the retrieved command. Null on error.
+ *
+ * DESCRIPTION: Get a command from the history buffer
+ *
+ ******************************************************************************/
+
+char *acpi_db_get_history_by_index(u32 cmd_num)
+{
+ u32 i;
+ u16 history_index;
+
+ /* Search history buffer */
+
+ history_index = acpi_gbl_lo_history;
+ for (i = 0; i < acpi_gbl_num_history; i++) {
+ if (acpi_gbl_history_buffer[history_index].cmd_num == cmd_num) {
+
+ /* Found the command, return it */
+
+ return (acpi_gbl_history_buffer[history_index].command);
+ }
+
+ /* History buffer is circular */
+
+ history_index++;
+ if (history_index >= HISTORY_SIZE) {
+ history_index = 0;
+ }
+ }
+
+ acpi_os_printf("Invalid history number: %u\n", history_index);
+ return (NULL);
+}
diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c
new file mode 100644
index 000000000000..0480254437f1
--- /dev/null
+++ b/drivers/acpi/acpica/dbinput.c
@@ -0,0 +1,1267 @@
+/*******************************************************************************
+ *
+ * Module Name: dbinput - user front-end to the AML debugger
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbinput")
+
+/* Local prototypes */
+static u32 acpi_db_get_line(char *input_buffer);
+
+static u32 acpi_db_match_command(char *user_command);
+
+static void acpi_db_single_thread(void);
+
+static void acpi_db_display_command_info(char *command, u8 display_all);
+
+static void acpi_db_display_help(char *command);
+
+static u8
+acpi_db_match_command_help(char *command,
+ const struct acpi_db_command_help *help);
+
+/*
+ * Top-level debugger commands.
+ *
+ * This list of commands must match the string table below it
+ */
+enum acpi_ex_debugger_commands {
+ CMD_NOT_FOUND = 0,
+ CMD_NULL,
+ CMD_ALLOCATIONS,
+ CMD_ARGS,
+ CMD_ARGUMENTS,
+ CMD_BREAKPOINT,
+ CMD_BUSINFO,
+ CMD_CALL,
+ CMD_DEBUG,
+ CMD_DISASSEMBLE,
+ CMD_DISASM,
+ CMD_DUMP,
+ CMD_EVALUATE,
+ CMD_EXECUTE,
+ CMD_EXIT,
+ CMD_FIND,
+ CMD_GO,
+ CMD_HANDLERS,
+ CMD_HELP,
+ CMD_HELP2,
+ CMD_HISTORY,
+ CMD_HISTORY_EXE,
+ CMD_HISTORY_LAST,
+ CMD_INFORMATION,
+ CMD_INTEGRITY,
+ CMD_INTO,
+ CMD_LEVEL,
+ CMD_LIST,
+ CMD_LOCALS,
+ CMD_LOCKS,
+ CMD_METHODS,
+ CMD_NAMESPACE,
+ CMD_NOTIFY,
+ CMD_OBJECTS,
+ CMD_OSI,
+ CMD_OWNER,
+ CMD_PATHS,
+ CMD_PREDEFINED,
+ CMD_PREFIX,
+ CMD_QUIT,
+ CMD_REFERENCES,
+ CMD_RESOURCES,
+ CMD_RESULTS,
+ CMD_SET,
+ CMD_STATS,
+ CMD_STOP,
+ CMD_TABLES,
+ CMD_TEMPLATE,
+ CMD_TRACE,
+ CMD_TREE,
+ CMD_TYPE,
+#ifdef ACPI_APPLICATION
+ CMD_ENABLEACPI,
+ CMD_EVENT,
+ CMD_GPE,
+ CMD_GPES,
+ CMD_SCI,
+ CMD_SLEEP,
+
+ CMD_CLOSE,
+ CMD_LOAD,
+ CMD_OPEN,
+ CMD_UNLOAD,
+
+ CMD_TERMINATE,
+ CMD_THREADS,
+
+ CMD_TEST,
+#endif
+};
+
+#define CMD_FIRST_VALID 2
+
+/* Second parameter is the required argument count */
+
+static const struct acpi_db_command_info acpi_gbl_db_commands[] = {
+ {"<NOT FOUND>", 0},
+ {"<NULL>", 0},
+ {"ALLOCATIONS", 0},
+ {"ARGS", 0},
+ {"ARGUMENTS", 0},
+ {"BREAKPOINT", 1},
+ {"BUSINFO", 0},
+ {"CALL", 0},
+ {"DEBUG", 1},
+ {"DISASSEMBLE", 1},
+ {"DISASM", 1},
+ {"DUMP", 1},
+ {"EVALUATE", 1},
+ {"EXECUTE", 1},
+ {"EXIT", 0},
+ {"FIND", 1},
+ {"GO", 0},
+ {"HANDLERS", 0},
+ {"HELP", 0},
+ {"?", 0},
+ {"HISTORY", 0},
+ {"!", 1},
+ {"!!", 0},
+ {"INFORMATION", 0},
+ {"INTEGRITY", 0},
+ {"INTO", 0},
+ {"LEVEL", 0},
+ {"LIST", 0},
+ {"LOCALS", 0},
+ {"LOCKS", 0},
+ {"METHODS", 0},
+ {"NAMESPACE", 0},
+ {"NOTIFY", 2},
+ {"OBJECTS", 0},
+ {"OSI", 0},
+ {"OWNER", 1},
+ {"PATHS", 0},
+ {"PREDEFINED", 0},
+ {"PREFIX", 0},
+ {"QUIT", 0},
+ {"REFERENCES", 1},
+ {"RESOURCES", 0},
+ {"RESULTS", 0},
+ {"SET", 3},
+ {"STATS", 1},
+ {"STOP", 0},
+ {"TABLES", 0},
+ {"TEMPLATE", 1},
+ {"TRACE", 1},
+ {"TREE", 0},
+ {"TYPE", 1},
+#ifdef ACPI_APPLICATION
+ {"ENABLEACPI", 0},
+ {"EVENT", 1},
+ {"GPE", 1},
+ {"GPES", 0},
+ {"SCI", 0},
+ {"SLEEP", 0},
+
+ {"CLOSE", 0},
+ {"LOAD", 1},
+ {"OPEN", 1},
+ {"UNLOAD", 1},
+
+ {"TERMINATE", 0},
+ {"THREADS", 3},
+
+ {"TEST", 1},
+#endif
+ {NULL, 0}
+};
+
+/*
+ * Help for all debugger commands. First argument is the number of lines
+ * of help to output for the command.
+ */
+static const struct acpi_db_command_help acpi_gbl_db_command_help[] = {
+ {0, "\nGeneral-Purpose Commands:", "\n"},
+ {1, " Allocations", "Display list of current memory allocations\n"},
+ {2, " Dump <Address>|<Namepath>", "\n"},
+ {0, " [Byte|Word|Dword|Qword]",
+ "Display ACPI objects or memory\n"},
+ {1, " Handlers", "Info about global handlers\n"},
+ {1, " Help [Command]", "This help screen or individual command\n"},
+ {1, " History", "Display command history buffer\n"},
+ {1, " Level <DebugLevel>] [console]",
+ "Get/Set debug level for file or console\n"},
+ {1, " Locks", "Current status of internal mutexes\n"},
+ {1, " Osi [Install|Remove <name>]",
+ "Display or modify global _OSI list\n"},
+ {1, " Quit or Exit", "Exit this command\n"},
+ {8, " Stats <SubCommand>",
+ "Display namespace and memory statistics\n"},
+ {1, " Allocations", "Display list of current memory allocations\n"},
+ {1, " Memory", "Dump internal memory lists\n"},
+ {1, " Misc", "Namespace search and mutex stats\n"},
+ {1, " Objects", "Summary of namespace objects\n"},
+ {1, " Sizes", "Sizes for each of the internal objects\n"},
+ {1, " Stack", "Display CPU stack usage\n"},
+ {1, " Tables", "Info about current ACPI table(s)\n"},
+ {1, " Tables", "Display info about loaded ACPI tables\n"},
+ {1, " ! <CommandNumber>", "Execute command from history buffer\n"},
+ {1, " !!", "Execute last command again\n"},
+
+ {0, "\nNamespace Access Commands:", "\n"},
+ {1, " Businfo", "Display system bus info\n"},
+ {1, " Disassemble <Method>", "Disassemble a control method\n"},
+ {1, " Find <AcpiName> (? is wildcard)",
+ "Find ACPI name(s) with wildcards\n"},
+ {1, " Integrity", "Validate namespace integrity\n"},
+ {1, " Methods", "Display list of loaded control methods\n"},
+ {1, " Namespace [Object] [Depth]",
+ "Display loaded namespace tree/subtree\n"},
+ {1, " Notify <Object> <Value>", "Send a notification on Object\n"},
+ {1, " Objects [ObjectType]",
+ "Display summary of all objects or just given type\n"},
+ {1, " Owner <OwnerId> [Depth]",
+ "Display loaded namespace by object owner\n"},
+ {1, " Paths", "Display full pathnames of namespace objects\n"},
+ {1, " Predefined", "Check all predefined names\n"},
+ {1, " Prefix [<Namepath>]", "Set or Get current execution prefix\n"},
+ {1, " References <Addr>", "Find all references to object at addr\n"},
+ {1, " Resources [DeviceName]",
+ "Display Device resources (no arg = all devices)\n"},
+ {1, " Set N <NamedObject> <Value>", "Set value for named integer\n"},
+ {1, " Template <Object>", "Format/dump a Buffer/ResourceTemplate\n"},
+ {1, " Type <Object>", "Display object type\n"},
+
+ {0, "\nControl Method Execution Commands:", "\n"},
+ {1, " Arguments (or Args)", "Display method arguments\n"},
+ {1, " Breakpoint <AmlOffset>", "Set an AML execution breakpoint\n"},
+ {1, " Call", "Run to next control method invocation\n"},
+ {1, " Debug <Namepath> [Arguments]", "Single Step a control method\n"},
+ {6, " Evaluate", "Synonym for Execute\n"},
+ {5, " Execute <Namepath> [Arguments]", "Execute control method\n"},
+ {1, " Hex Integer", "Integer method argument\n"},
+ {1, " \"Ascii String\"", "String method argument\n"},
+ {1, " (Hex Byte List)", "Buffer method argument\n"},
+ {1, " [Package Element List]", "Package method argument\n"},
+ {1, " Go", "Allow method to run to completion\n"},
+ {1, " Information", "Display info about the current method\n"},
+ {1, " Into", "Step into (not over) a method call\n"},
+ {1, " List [# of Aml Opcodes]", "Display method ASL statements\n"},
+ {1, " Locals", "Display method local variables\n"},
+ {1, " Results", "Display method result stack\n"},
+ {1, " Set <A|L> <#> <Value>", "Set method data (Arguments/Locals)\n"},
+ {1, " Stop", "Terminate control method\n"},
+ {5, " Trace <State> [<Namepath>] [Once]",
+ "Trace control method execution\n"},
+ {1, " Enable", "Enable all messages\n"},
+ {1, " Disable", "Disable tracing\n"},
+ {1, " Method", "Enable method execution messages\n"},
+ {1, " Opcode", "Enable opcode execution messages\n"},
+ {1, " Tree", "Display control method calling tree\n"},
+ {1, " <Enter>", "Single step next AML opcode (over calls)\n"},
+
+#ifdef ACPI_APPLICATION
+ {0, "\nHardware Simulation Commands:", "\n"},
+ {1, " EnableAcpi", "Enable ACPI (hardware) mode\n"},
+ {1, " Event <F|G> <Value>", "Generate AcpiEvent (Fixed/GPE)\n"},
+ {1, " Gpe <GpeNum> [GpeBlockDevice]", "Simulate a GPE\n"},
+ {1, " Gpes", "Display info on all GPE devices\n"},
+ {1, " Sci", "Generate an SCI\n"},
+ {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"},
+
+ {0, "\nFile I/O Commands:", "\n"},
+ {1, " Close", "Close debug output file\n"},
+ {1, " Load <Input Filename>", "Load ACPI table from a file\n"},
+ {1, " Open <Output Filename>", "Open a file for debug output\n"},
+ {1, " Unload <Namepath>",
+ "Unload an ACPI table via namespace object\n"},
+
+ {0, "\nUser Space Commands:", "\n"},
+ {1, " Terminate", "Delete namespace and all internal objects\n"},
+ {1, " Thread <Threads><Loops><NamePath>",
+ "Spawn threads to execute method(s)\n"},
+
+ {0, "\nDebug Test Commands:", "\n"},
+ {3, " Test <TestName>", "Invoke a debug test\n"},
+ {1, " Objects", "Read/write/compare all namespace data objects\n"},
+ {1, " Predefined",
+ "Execute all ACPI predefined names (_STA, etc.)\n"},
+#endif
+ {0, NULL, NULL}
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_match_command_help
+ *
+ * PARAMETERS: command - Command string to match
+ * help - Help table entry to attempt match
+ *
+ * RETURN: TRUE if command matched, FALSE otherwise
+ *
+ * DESCRIPTION: Attempt to match a command in the help table in order to
+ * print help information for a single command.
+ *
+ ******************************************************************************/
+
+static u8
+acpi_db_match_command_help(char *command,
+ const struct acpi_db_command_help *help)
+{
+ char *invocation = help->invocation;
+ u32 line_count;
+
+ /* Valid commands in the help table begin with a couple of spaces */
+
+ if (*invocation != ' ') {
+ return (FALSE);
+ }
+
+ while (*invocation == ' ') {
+ invocation++;
+ }
+
+ /* Match command name (full command or substring) */
+
+ while ((*command) && (*invocation) && (*invocation != ' ')) {
+ if (tolower((int)*command) != tolower((int)*invocation)) {
+ return (FALSE);
+ }
+
+ invocation++;
+ command++;
+ }
+
+ /* Print the appropriate number of help lines */
+
+ line_count = help->line_count;
+ while (line_count) {
+ acpi_os_printf("%-38s : %s", help->invocation,
+ help->description);
+ help++;
+ line_count--;
+ }
+
+ return (TRUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_command_info
+ *
+ * PARAMETERS: command - Command string to match
+ * display_all - Display all matching commands, or just
+ * the first one (substring match)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display help information for a Debugger command.
+ *
+ ******************************************************************************/
+
+static void acpi_db_display_command_info(char *command, u8 display_all)
+{
+ const struct acpi_db_command_help *next;
+ u8 matched;
+
+ next = acpi_gbl_db_command_help;
+ while (next->invocation) {
+ matched = acpi_db_match_command_help(command, next);
+ if (!display_all && matched) {
+ return;
+ }
+
+ next++;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_help
+ *
+ * PARAMETERS: command - Optional command string to display help.
+ * if not specified, all debugger command
+ * help strings are displayed
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display help for a single debugger command, or all of them.
+ *
+ ******************************************************************************/
+
+static void acpi_db_display_help(char *command)
+{
+ const struct acpi_db_command_help *next = acpi_gbl_db_command_help;
+
+ if (!command) {
+
+ /* No argument to help, display help for all commands */
+
+ while (next->invocation) {
+ acpi_os_printf("%-38s%s", next->invocation,
+ next->description);
+ next++;
+ }
+ } else {
+ /* Display help for all commands that match the subtring */
+
+ acpi_db_display_command_info(command, TRUE);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_next_token
+ *
+ * PARAMETERS: string - Command buffer
+ * next - Return value, end of next token
+ *
+ * RETURN: Pointer to the start of the next token.
+ *
+ * DESCRIPTION: Command line parsing. Get the next token on the command line
+ *
+ ******************************************************************************/
+
+char *acpi_db_get_next_token(char *string,
+ char **next, acpi_object_type * return_type)
+{
+ char *start;
+ u32 depth;
+ acpi_object_type type = ACPI_TYPE_INTEGER;
+
+ /* At end of buffer? */
+
+ if (!string || !(*string)) {
+ return (NULL);
+ }
+
+ /* Remove any spaces at the beginning */
+
+ if (*string == ' ') {
+ while (*string && (*string == ' ')) {
+ string++;
+ }
+
+ if (!(*string)) {
+ return (NULL);
+ }
+ }
+
+ switch (*string) {
+ case '"':
+
+ /* This is a quoted string, scan until closing quote */
+
+ string++;
+ start = string;
+ type = ACPI_TYPE_STRING;
+
+ /* Find end of string */
+
+ while (*string && (*string != '"')) {
+ string++;
+ }
+ break;
+
+ case '(':
+
+ /* This is the start of a buffer, scan until closing paren */
+
+ string++;
+ start = string;
+ type = ACPI_TYPE_BUFFER;
+
+ /* Find end of buffer */
+
+ while (*string && (*string != ')')) {
+ string++;
+ }
+ break;
+
+ case '[':
+
+ /* This is the start of a package, scan until closing bracket */
+
+ string++;
+ depth = 1;
+ start = string;
+ type = ACPI_TYPE_PACKAGE;
+
+ /* Find end of package (closing bracket) */
+
+ while (*string) {
+
+ /* Handle String package elements */
+
+ if (*string == '"') {
+ /* Find end of string */
+
+ string++;
+ while (*string && (*string != '"')) {
+ string++;
+ }
+ if (!(*string)) {
+ break;
+ }
+ } else if (*string == '[') {
+ depth++; /* A nested package declaration */
+ } else if (*string == ']') {
+ depth--;
+ if (depth == 0) { /* Found final package closing bracket */
+ break;
+ }
+ }
+
+ string++;
+ }
+ break;
+
+ default:
+
+ start = string;
+
+ /* Find end of token */
+
+ while (*string && (*string != ' ')) {
+ string++;
+ }
+ break;
+ }
+
+ if (!(*string)) {
+ *next = NULL;
+ } else {
+ *string = 0;
+ *next = string + 1;
+ }
+
+ *return_type = type;
+ return (start);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_line
+ *
+ * PARAMETERS: input_buffer - Command line buffer
+ *
+ * RETURN: Count of arguments to the command
+ *
+ * DESCRIPTION: Get the next command line from the user. Gets entire line
+ * up to the next newline
+ *
+ ******************************************************************************/
+
+static u32 acpi_db_get_line(char *input_buffer)
+{
+ u32 i;
+ u32 count;
+ char *next;
+ char *this;
+
+ if (acpi_ut_safe_strcpy
+ (acpi_gbl_db_parsed_buf, sizeof(acpi_gbl_db_parsed_buf),
+ input_buffer)) {
+ acpi_os_printf
+ ("Buffer overflow while parsing input line (max %u characters)\n",
+ sizeof(acpi_gbl_db_parsed_buf));
+ return (0);
+ }
+
+ this = acpi_gbl_db_parsed_buf;
+ for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++) {
+ acpi_gbl_db_args[i] = acpi_db_get_next_token(this, &next,
+ &acpi_gbl_db_arg_types
+ [i]);
+ if (!acpi_gbl_db_args[i]) {
+ break;
+ }
+
+ this = next;
+ }
+
+ /* Uppercase the actual command */
+
+ if (acpi_gbl_db_args[0]) {
+ acpi_ut_strupr(acpi_gbl_db_args[0]);
+ }
+
+ count = i;
+ if (count) {
+ count--; /* Number of args only */
+ }
+
+ return (count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_match_command
+ *
+ * PARAMETERS: user_command - User command line
+ *
+ * RETURN: Index into command array, -1 if not found
+ *
+ * DESCRIPTION: Search command array for a command match
+ *
+ ******************************************************************************/
+
+static u32 acpi_db_match_command(char *user_command)
+{
+ u32 i;
+
+ if (!user_command || user_command[0] == 0) {
+ return (CMD_NULL);
+ }
+
+ for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) {
+ if (strstr(acpi_gbl_db_commands[i].name, user_command) ==
+ acpi_gbl_db_commands[i].name) {
+ return (i);
+ }
+ }
+
+ /* Command not recognized */
+
+ return (CMD_NOT_FOUND);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_command_dispatch
+ *
+ * PARAMETERS: input_buffer - Command line buffer
+ * walk_state - Current walk
+ * op - Current (executing) parse op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Command dispatcher.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_db_command_dispatch(char *input_buffer,
+ struct acpi_walk_state * walk_state,
+ union acpi_parse_object * op)
+{
+ u32 temp;
+ u32 command_index;
+ u32 param_count;
+ char *command_line;
+ acpi_status status = AE_CTRL_TRUE;
+
+ /* If acpi_terminate has been called, terminate this thread */
+
+ if (acpi_gbl_db_terminate_loop) {
+ return (AE_CTRL_TERMINATE);
+ }
+
+ /* Find command and add to the history buffer */
+
+ param_count = acpi_db_get_line(input_buffer);
+ command_index = acpi_db_match_command(acpi_gbl_db_args[0]);
+ temp = 0;
+
+ /*
+ * We don't want to add the !! command to the history buffer. It
+ * would cause an infinite loop because it would always be the
+ * previous command.
+ */
+ if (command_index != CMD_HISTORY_LAST) {
+ acpi_db_add_to_history(input_buffer);
+ }
+
+ /* Verify that we have the minimum number of params */
+
+ if (param_count < acpi_gbl_db_commands[command_index].min_args) {
+ acpi_os_printf
+ ("%u parameters entered, [%s] requires %u parameters\n",
+ param_count, acpi_gbl_db_commands[command_index].name,
+ acpi_gbl_db_commands[command_index].min_args);
+
+ acpi_db_display_command_info(acpi_gbl_db_commands
+ [command_index].name, FALSE);
+ return (AE_CTRL_TRUE);
+ }
+
+ /* Decode and dispatch the command */
+
+ switch (command_index) {
+ case CMD_NULL:
+
+ if (op) {
+ return (AE_OK);
+ }
+ break;
+
+ case CMD_ALLOCATIONS:
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ acpi_ut_dump_allocations((u32)-1, NULL);
+#endif
+ break;
+
+ case CMD_ARGS:
+ case CMD_ARGUMENTS:
+
+ acpi_db_display_arguments();
+ break;
+
+ case CMD_BREAKPOINT:
+
+ acpi_db_set_method_breakpoint(acpi_gbl_db_args[1], walk_state,
+ op);
+ break;
+
+ case CMD_BUSINFO:
+
+ acpi_db_get_bus_info();
+ break;
+
+ case CMD_CALL:
+
+ acpi_db_set_method_call_breakpoint(op);
+ status = AE_OK;
+ break;
+
+ case CMD_DEBUG:
+
+ acpi_db_execute(acpi_gbl_db_args[1],
+ &acpi_gbl_db_args[2], &acpi_gbl_db_arg_types[2],
+ EX_SINGLE_STEP);
+ break;
+
+ case CMD_DISASSEMBLE:
+ case CMD_DISASM:
+
+ (void)acpi_db_disassemble_method(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_DUMP:
+
+ acpi_db_decode_and_display_object(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2]);
+ break;
+
+ case CMD_EVALUATE:
+ case CMD_EXECUTE:
+
+ acpi_db_execute(acpi_gbl_db_args[1],
+ &acpi_gbl_db_args[2], &acpi_gbl_db_arg_types[2],
+ EX_NO_SINGLE_STEP);
+ break;
+
+ case CMD_FIND:
+
+ status = acpi_db_find_name_in_namespace(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_GO:
+
+ acpi_gbl_cm_single_step = FALSE;
+ return (AE_OK);
+
+ case CMD_HANDLERS:
+
+ acpi_db_display_handlers();
+ break;
+
+ case CMD_HELP:
+ case CMD_HELP2:
+
+ acpi_db_display_help(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_HISTORY:
+
+ acpi_db_display_history();
+ break;
+
+ case CMD_HISTORY_EXE: /* ! command */
+
+ command_line = acpi_db_get_from_history(acpi_gbl_db_args[1]);
+ if (!command_line) {
+ return (AE_CTRL_TRUE);
+ }
+
+ status = acpi_db_command_dispatch(command_line, walk_state, op);
+ return (status);
+
+ case CMD_HISTORY_LAST: /* !! command */
+
+ command_line = acpi_db_get_from_history(NULL);
+ if (!command_line) {
+ return (AE_CTRL_TRUE);
+ }
+
+ status = acpi_db_command_dispatch(command_line, walk_state, op);
+ return (status);
+
+ case CMD_INFORMATION:
+
+ acpi_db_display_method_info(op);
+ break;
+
+ case CMD_INTEGRITY:
+
+ acpi_db_check_integrity();
+ break;
+
+ case CMD_INTO:
+
+ if (op) {
+ acpi_gbl_cm_single_step = TRUE;
+ return (AE_OK);
+ }
+ break;
+
+ case CMD_LEVEL:
+
+ if (param_count == 0) {
+ acpi_os_printf
+ ("Current debug level for file output is: %8.8lX\n",
+ acpi_gbl_db_debug_level);
+ acpi_os_printf
+ ("Current debug level for console output is: %8.8lX\n",
+ acpi_gbl_db_console_debug_level);
+ } else if (param_count == 2) {
+ temp = acpi_gbl_db_console_debug_level;
+ acpi_gbl_db_console_debug_level =
+ strtoul(acpi_gbl_db_args[1], NULL, 16);
+ acpi_os_printf
+ ("Debug Level for console output was %8.8lX, now %8.8lX\n",
+ temp, acpi_gbl_db_console_debug_level);
+ } else {
+ temp = acpi_gbl_db_debug_level;
+ acpi_gbl_db_debug_level =
+ strtoul(acpi_gbl_db_args[1], NULL, 16);
+ acpi_os_printf
+ ("Debug Level for file output was %8.8lX, now %8.8lX\n",
+ temp, acpi_gbl_db_debug_level);
+ }
+ break;
+
+ case CMD_LIST:
+
+ acpi_db_disassemble_aml(acpi_gbl_db_args[1], op);
+ break;
+
+ case CMD_LOCKS:
+
+ acpi_db_display_locks();
+ break;
+
+ case CMD_LOCALS:
+
+ acpi_db_display_locals();
+ break;
+
+ case CMD_METHODS:
+
+ status = acpi_db_display_objects("METHOD", acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_NAMESPACE:
+
+ acpi_db_dump_namespace(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2]);
+ break;
+
+ case CMD_NOTIFY:
+
+ temp = strtoul(acpi_gbl_db_args[2], NULL, 0);
+ acpi_db_send_notify(acpi_gbl_db_args[1], temp);
+ break;
+
+ case CMD_OBJECTS:
+
+ acpi_ut_strupr(acpi_gbl_db_args[1]);
+ status =
+ acpi_db_display_objects(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2]);
+ break;
+
+ case CMD_OSI:
+
+ acpi_db_display_interfaces(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2]);
+ break;
+
+ case CMD_OWNER:
+
+ acpi_db_dump_namespace_by_owner(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2]);
+ break;
+
+ case CMD_PATHS:
+
+ acpi_db_dump_namespace_paths();
+ break;
+
+ case CMD_PREFIX:
+
+ acpi_db_set_scope(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_REFERENCES:
+
+ acpi_db_find_references(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_RESOURCES:
+
+ acpi_db_display_resources(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_RESULTS:
+
+ acpi_db_display_results();
+ break;
+
+ case CMD_SET:
+
+ acpi_db_set_method_data(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2],
+ acpi_gbl_db_args[3]);
+ break;
+
+ case CMD_STATS:
+
+ status = acpi_db_display_statistics(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_STOP:
+
+ return (AE_NOT_IMPLEMENTED);
+
+ case CMD_TABLES:
+
+ acpi_db_display_table_info(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_TEMPLATE:
+
+ acpi_db_display_template(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_TRACE:
+
+ acpi_db_trace(acpi_gbl_db_args[1], acpi_gbl_db_args[2],
+ acpi_gbl_db_args[3]);
+ break;
+
+ case CMD_TREE:
+
+ acpi_db_display_calling_tree();
+ break;
+
+ case CMD_TYPE:
+
+ acpi_db_display_object_type(acpi_gbl_db_args[1]);
+ break;
+
+#ifdef ACPI_APPLICATION
+
+ /* Hardware simulation commands. */
+
+ case CMD_ENABLEACPI:
+#if (!ACPI_REDUCED_HARDWARE)
+
+ status = acpi_enable();
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("AcpiEnable failed (Status=%X)\n",
+ status);
+ return (status);
+ }
+#endif /* !ACPI_REDUCED_HARDWARE */
+ break;
+
+ case CMD_EVENT:
+
+ acpi_os_printf("Event command not implemented\n");
+ break;
+
+ case CMD_GPE:
+
+ acpi_db_generate_gpe(acpi_gbl_db_args[1], acpi_gbl_db_args[2]);
+ break;
+
+ case CMD_GPES:
+
+ acpi_db_display_gpes();
+ break;
+
+ case CMD_SCI:
+
+ acpi_db_generate_sci();
+ break;
+
+ case CMD_SLEEP:
+
+ status = acpi_db_sleep(acpi_gbl_db_args[1]);
+ break;
+
+ /* File I/O commands. */
+
+ case CMD_CLOSE:
+
+ acpi_db_close_debug_file();
+ break;
+
+ case CMD_LOAD:
+
+ status =
+ acpi_db_get_table_from_file(acpi_gbl_db_args[1], NULL,
+ FALSE);
+ break;
+
+ case CMD_OPEN:
+
+ acpi_db_open_debug_file(acpi_gbl_db_args[1]);
+ break;
+
+ /* User space commands. */
+
+ case CMD_TERMINATE:
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ acpi_ut_subsystem_shutdown();
+
+ /*
+ * TBD: [Restructure] Need some way to re-initialize without
+ * re-creating the semaphores!
+ */
+
+ acpi_gbl_db_terminate_loop = TRUE;
+ /* acpi_initialize (NULL); */
+ break;
+
+ case CMD_THREADS:
+
+ acpi_db_create_execution_threads(acpi_gbl_db_args[1],
+ acpi_gbl_db_args[2],
+ acpi_gbl_db_args[3]);
+ break;
+
+ /* Debug test commands. */
+
+ case CMD_PREDEFINED:
+
+ acpi_db_check_predefined_names();
+ break;
+
+ case CMD_TEST:
+
+ acpi_db_execute_test(acpi_gbl_db_args[1]);
+ break;
+
+ case CMD_UNLOAD:
+
+ acpi_db_unload_acpi_table(acpi_gbl_db_args[1]);
+ break;
+#endif
+
+ case CMD_EXIT:
+ case CMD_QUIT:
+
+ if (op) {
+ acpi_os_printf("Method execution terminated\n");
+ return (AE_CTRL_TERMINATE);
+ }
+
+ if (!acpi_gbl_db_output_to_file) {
+ acpi_dbg_level = ACPI_DEBUG_DEFAULT;
+ }
+#ifdef ACPI_APPLICATION
+ acpi_db_close_debug_file();
+#endif
+ acpi_gbl_db_terminate_loop = TRUE;
+ return (AE_CTRL_TERMINATE);
+
+ case CMD_NOT_FOUND:
+ default:
+
+ acpi_os_printf("%s: unknown command\n", acpi_gbl_db_args[0]);
+ return (AE_CTRL_TRUE);
+ }
+
+ if (ACPI_SUCCESS(status)) {
+ status = AE_CTRL_TRUE;
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_execute_thread
+ *
+ * PARAMETERS: context - Not used
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Debugger execute thread. Waits for a command line, then
+ * simply dispatches it.
+ *
+ ******************************************************************************/
+
+void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context)
+{
+ acpi_status status = AE_OK;
+ acpi_status Mstatus;
+
+ while (status != AE_CTRL_TERMINATE && !acpi_gbl_db_terminate_loop) {
+ acpi_gbl_method_executing = FALSE;
+ acpi_gbl_step_to_next_call = FALSE;
+
+ Mstatus = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
+ ACPI_WAIT_FOREVER);
+ if (ACPI_FAILURE(Mstatus)) {
+ return;
+ }
+
+ status =
+ acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL);
+
+ acpi_os_release_mutex(acpi_gbl_db_command_complete);
+ }
+ acpi_gbl_db_threads_terminated = TRUE;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_single_thread
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Debugger execute thread. Waits for a command line, then
+ * simply dispatches it.
+ *
+ ******************************************************************************/
+
+static void acpi_db_single_thread(void)
+{
+
+ acpi_gbl_method_executing = FALSE;
+ acpi_gbl_step_to_next_call = FALSE;
+
+ (void)acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_user_commands
+ *
+ * PARAMETERS: prompt - User prompt (depends on mode)
+ * op - Current executing parse op
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Command line execution for the AML debugger. Commands are
+ * matched and dispatched here.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op)
+{
+ acpi_status status = AE_OK;
+
+ acpi_os_printf("\n");
+
+ /* TBD: [Restructure] Need a separate command line buffer for step mode */
+
+ while (!acpi_gbl_db_terminate_loop) {
+
+ /* Force output to console until a command is entered */
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+
+ /* Different prompt if method is executing */
+
+ if (!acpi_gbl_method_executing) {
+ acpi_os_printf("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
+ } else {
+ acpi_os_printf("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
+ }
+
+ /* Get the user input line */
+
+ status = acpi_os_get_line(acpi_gbl_db_line_buf,
+ ACPI_DB_LINE_BUFFER_SIZE, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While parsing command line"));
+ return (status);
+ }
+
+ /* Check for single or multithreaded debug */
+
+ if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
+ /*
+ * Signal the debug thread that we have a command to execute,
+ * and wait for the command to complete.
+ */
+ acpi_os_release_mutex(acpi_gbl_db_command_ready);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ status =
+ acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
+ ACPI_WAIT_FOREVER);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ } else {
+ /* Just call to the command line interpreter */
+
+ acpi_db_single_thread();
+ }
+ }
+
+ return (status);
+}
diff --git a/drivers/acpi/acpica/dbmethod.c b/drivers/acpi/acpica/dbmethod.c
new file mode 100644
index 000000000000..01e5a71147fd
--- /dev/null
+++ b/drivers/acpi/acpica/dbmethod.c
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ *
+ * Module Name: dbmethod - Debug commands for control methods
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+#include "acparser.h"
+#include "acpredef.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbmethod")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_set_method_breakpoint
+ *
+ * PARAMETERS: location - AML offset of breakpoint
+ * walk_state - Current walk info
+ * op - Current Op (from parse walk)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set a breakpoint in a control method at the specified
+ * AML offset
+ *
+ ******************************************************************************/
+void
+acpi_db_set_method_breakpoint(char *location,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
+{
+ u32 address;
+ u32 aml_offset;
+
+ if (!op) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ /* Get and verify the breakpoint address */
+
+ address = strtoul(location, NULL, 16);
+ aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
+ walk_state->parser_state.aml_start);
+ if (address <= aml_offset) {
+ acpi_os_printf("Breakpoint %X is beyond current address %X\n",
+ address, aml_offset);
+ }
+
+ /* Save breakpoint in current walk */
+
+ walk_state->user_breakpoint = address;
+ acpi_os_printf("Breakpoint set at AML offset %X\n", address);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_set_method_call_breakpoint
+ *
+ * PARAMETERS: op - Current Op (from parse walk)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set a breakpoint in a control method at the specified
+ * AML offset
+ *
+ ******************************************************************************/
+
+void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op)
+{
+
+ if (!op) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ acpi_gbl_step_to_next_call = TRUE;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_set_method_data
+ *
+ * PARAMETERS: type_arg - L for local, A for argument
+ * index_arg - which one
+ * value_arg - Value to set.
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set a local or argument for the running control method.
+ * NOTE: only object supported is Number.
+ *
+ ******************************************************************************/
+
+void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg)
+{
+ char type;
+ u32 index;
+ u32 value;
+ struct acpi_walk_state *walk_state;
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+
+ /* Validate type_arg */
+
+ acpi_ut_strupr(type_arg);
+ type = type_arg[0];
+ if ((type != 'L') && (type != 'A') && (type != 'N')) {
+ acpi_os_printf("Invalid SET operand: %s\n", type_arg);
+ return;
+ }
+
+ value = strtoul(value_arg, NULL, 16);
+
+ if (type == 'N') {
+ node = acpi_db_convert_to_node(index_arg);
+ if (!node) {
+ return;
+ }
+
+ if (node->type != ACPI_TYPE_INTEGER) {
+ acpi_os_printf("Can only set Integer nodes\n");
+ return;
+ }
+ obj_desc = node->object;
+ obj_desc->integer.value = value;
+ return;
+ }
+
+ /* Get the index and value */
+
+ index = strtoul(index_arg, NULL, 16);
+
+ walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
+ if (!walk_state) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ /* Create and initialize the new object */
+
+ obj_desc = acpi_ut_create_integer_object((u64)value);
+ if (!obj_desc) {
+ acpi_os_printf("Could not create an internal object\n");
+ return;
+ }
+
+ /* Store the new object into the target */
+
+ switch (type) {
+ case 'A':
+
+ /* Set a method argument */
+
+ if (index > ACPI_METHOD_MAX_ARG) {
+ acpi_os_printf("Arg%u - Invalid argument name\n",
+ index);
+ goto cleanup;
+ }
+
+ status = acpi_ds_store_object_to_local(ACPI_REFCLASS_ARG,
+ index, obj_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
+
+ obj_desc = walk_state->arguments[index].object;
+
+ acpi_os_printf("Arg%u: ", index);
+ acpi_db_display_internal_object(obj_desc, walk_state);
+ break;
+
+ case 'L':
+
+ /* Set a method local */
+
+ if (index > ACPI_METHOD_MAX_LOCAL) {
+ acpi_os_printf
+ ("Local%u - Invalid local variable name\n", index);
+ goto cleanup;
+ }
+
+ status = acpi_ds_store_object_to_local(ACPI_REFCLASS_LOCAL,
+ index, obj_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
+
+ obj_desc = walk_state->local_variables[index].object;
+
+ acpi_os_printf("Local%u: ", index);
+ acpi_db_display_internal_object(obj_desc, walk_state);
+ break;
+
+ default:
+
+ break;
+ }
+
+cleanup:
+ acpi_ut_remove_reference(obj_desc);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_disassemble_aml
+ *
+ * PARAMETERS: statements - Number of statements to disassemble
+ * op - Current Op (from parse walk)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
+ * of statements specified.
+ *
+ ******************************************************************************/
+
+void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op)
+{
+ u32 num_statements = 8;
+
+ if (!op) {
+ acpi_os_printf("There is no method currently executing\n");
+ return;
+ }
+
+ if (statements) {
+ num_statements = strtoul(statements, NULL, 0);
+ }
+#ifdef ACPI_DISASSEMBLER
+ acpi_dm_disassemble(NULL, op, num_statements);
+#endif
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_disassemble_method
+ *
+ * PARAMETERS: name - Name of control method
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
+ * of statements specified.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_disassemble_method(char *name)
+{
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *method;
+
+ method = acpi_db_convert_to_node(name);
+ if (!method) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ if (method->type != ACPI_TYPE_METHOD) {
+ ACPI_ERROR((AE_INFO, "%s (%s): Object must be a control method",
+ name, acpi_ut_get_type_name(method->type)));
+ return (AE_BAD_PARAMETER);
+ }
+
+ obj_desc = method->object;
+
+ op = acpi_ps_create_scope_op(obj_desc->method.aml_start);
+ if (!op) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Create and initialize a new walk state */
+
+ walk_state = acpi_ds_create_walk_state(0, op, NULL, NULL);
+ if (!walk_state) {
+ return (AE_NO_MEMORY);
+ }
+
+ status = acpi_ds_init_aml_walk(walk_state, op, NULL,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, NULL,
+ ACPI_IMODE_LOAD_PASS1);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+ walk_state->owner_id = obj_desc->method.owner_id;
+
+ /* Push start scope on scope stack and make it current */
+
+ status = acpi_ds_scope_stack_push(method, method->type, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Parse the entire method AML including deferred operators */
+
+ walk_state->parse_flags &= ~ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags |= ACPI_PARSE_DISASSEMBLE;
+
+ status = acpi_ps_parse_aml(walk_state);
+
+#ifdef ACPI_DISASSEMBLER
+ (void)acpi_dm_parse_deferred_ops(op);
+
+ /* Now we can disassemble the method */
+
+ acpi_gbl_dm_opt_verbose = FALSE;
+ acpi_dm_disassemble(NULL, op, 0);
+ acpi_gbl_dm_opt_verbose = TRUE;
+#endif
+
+ acpi_ps_delete_parse_tree(op);
+
+ /* Method cleanup */
+
+ acpi_ns_delete_namespace_subtree(method);
+ acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
+ acpi_ut_release_owner_id(&obj_desc->method.owner_id);
+ return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c
new file mode 100644
index 000000000000..04ff1ebfda58
--- /dev/null
+++ b/drivers/acpi/acpica/dbnames.c
@@ -0,0 +1,947 @@
+/*******************************************************************************
+ *
+ * Module Name: dbnames - Debugger commands for the acpi namespace
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+#include "acpredef.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbnames")
+
+/* Local prototypes */
+static acpi_status
+acpi_db_walk_and_match_name(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+static acpi_status
+acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+static acpi_status
+acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+static acpi_status
+acpi_db_walk_for_object_counts(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+static acpi_status
+acpi_db_integrity_walk(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
+
+static acpi_status
+acpi_db_walk_for_references(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+static acpi_status
+acpi_db_bus_walk(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
+
+/*
+ * Arguments for the Objects command
+ * These object types map directly to the ACPI_TYPES
+ */
+static struct acpi_db_argument_info acpi_db_object_types[] = {
+ {"ANY"},
+ {"INTEGERS"},
+ {"STRINGS"},
+ {"BUFFERS"},
+ {"PACKAGES"},
+ {"FIELDS"},
+ {"DEVICES"},
+ {"EVENTS"},
+ {"METHODS"},
+ {"MUTEXES"},
+ {"REGIONS"},
+ {"POWERRESOURCES"},
+ {"PROCESSORS"},
+ {"THERMALZONES"},
+ {"BUFFERFIELDS"},
+ {"DDBHANDLES"},
+ {"DEBUG"},
+ {"REGIONFIELDS"},
+ {"BANKFIELDS"},
+ {"INDEXFIELDS"},
+ {"REFERENCES"},
+ {"ALIASES"},
+ {"METHODALIASES"},
+ {"NOTIFY"},
+ {"ADDRESSHANDLER"},
+ {"RESOURCE"},
+ {"RESOURCEFIELD"},
+ {"SCOPES"},
+ {NULL} /* Must be null terminated */
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_set_scope
+ *
+ * PARAMETERS: name - New scope path
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Set the "current scope" as maintained by this utility.
+ * The scope is used as a prefix to ACPI paths.
+ *
+ ******************************************************************************/
+
+void acpi_db_set_scope(char *name)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+
+ if (!name || name[0] == 0) {
+ acpi_os_printf("Current scope: %s\n", acpi_gbl_db_scope_buf);
+ return;
+ }
+
+ acpi_db_prep_namestring(name);
+
+ if (ACPI_IS_ROOT_PREFIX(name[0])) {
+
+ /* Validate new scope from the root */
+
+ status = acpi_ns_get_node(acpi_gbl_root_node, name,
+ ACPI_NS_NO_UPSEARCH, &node);
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
+
+ acpi_gbl_db_scope_buf[0] = 0;
+ } else {
+ /* Validate new scope relative to old scope */
+
+ status = acpi_ns_get_node(acpi_gbl_db_scope_node, name,
+ ACPI_NS_NO_UPSEARCH, &node);
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
+ }
+
+ /* Build the final pathname */
+
+ if (acpi_ut_safe_strcat
+ (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), name)) {
+ status = AE_BUFFER_OVERFLOW;
+ goto error_exit;
+ }
+
+ if (acpi_ut_safe_strcat
+ (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), "\\")) {
+ status = AE_BUFFER_OVERFLOW;
+ goto error_exit;
+ }
+
+ acpi_gbl_db_scope_node = node;
+ acpi_os_printf("New scope: %s\n", acpi_gbl_db_scope_buf);
+ return;
+
+error_exit:
+
+ acpi_os_printf("Could not attach scope: %s, %s\n",
+ name, acpi_format_exception(status));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_namespace
+ *
+ * PARAMETERS: start_arg - Node to begin namespace dump
+ * depth_arg - Maximum tree depth to be dumped
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed
+ * with type and other information.
+ *
+ ******************************************************************************/
+
+void acpi_db_dump_namespace(char *start_arg, char *depth_arg)
+{
+ acpi_handle subtree_entry = acpi_gbl_root_node;
+ u32 max_depth = ACPI_UINT32_MAX;
+
+ /* No argument given, just start at the root and dump entire namespace */
+
+ if (start_arg) {
+ subtree_entry = acpi_db_convert_to_node(start_arg);
+ if (!subtree_entry) {
+ return;
+ }
+
+ /* Now we can check for the depth argument */
+
+ if (depth_arg) {
+ max_depth = strtoul(depth_arg, NULL, 0);
+ }
+ }
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+ acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n",
+ ((struct acpi_namespace_node *)subtree_entry)->name.
+ ascii, subtree_entry);
+
+ /* Display the subtree */
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth,
+ ACPI_OWNER_ID_MAX, subtree_entry);
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_namespace_paths
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump entire namespace with full object pathnames and object
+ * type information. Alternative to "namespace" command.
+ *
+ ******************************************************************************/
+
+void acpi_db_dump_namespace_paths(void)
+{
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+ acpi_os_printf("ACPI Namespace (from root):\n");
+
+ /* Display the entire namespace */
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY,
+ ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX,
+ acpi_gbl_root_node);
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_namespace_by_owner
+ *
+ * PARAMETERS: owner_arg - Owner ID whose nodes will be displayed
+ * depth_arg - Maximum tree depth to be dumped
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump elements of the namespace that are owned by the owner_id.
+ *
+ ******************************************************************************/
+
+void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg)
+{
+ acpi_handle subtree_entry = acpi_gbl_root_node;
+ u32 max_depth = ACPI_UINT32_MAX;
+ acpi_owner_id owner_id;
+
+ owner_id = (acpi_owner_id) strtoul(owner_arg, NULL, 0);
+
+ /* Now we can check for the depth argument */
+
+ if (depth_arg) {
+ max_depth = strtoul(depth_arg, NULL, 0);
+ }
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+ acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id);
+
+ /* Display the subtree */
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+ acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth,
+ owner_id, subtree_entry);
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_walk_and_match_name
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find a particular name/names within the namespace. Wildcards
+ * are supported -- '?' matches any character.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_walk_and_match_name(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ acpi_status status;
+ char *requested_name = (char *)context;
+ u32 i;
+ struct acpi_buffer buffer;
+ struct acpi_walk_info info;
+
+ /* Check for a name match */
+
+ for (i = 0; i < 4; i++) {
+
+ /* Wildcard support */
+
+ if ((requested_name[i] != '?') &&
+ (requested_name[i] != ((struct acpi_namespace_node *)
+ obj_handle)->name.ascii[i])) {
+
+ /* No match, just exit */
+
+ return (AE_OK);
+ }
+ }
+
+ /* Get the full pathname to this object */
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could Not get pathname for object %p\n",
+ obj_handle);
+ } else {
+ info.owner_id = ACPI_OWNER_ID_MAX;
+ info.debug_level = ACPI_UINT32_MAX;
+ info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
+
+ acpi_os_printf("%32s", (char *)buffer.pointer);
+ (void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info,
+ NULL);
+ ACPI_FREE(buffer.pointer);
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_find_name_in_namespace
+ *
+ * PARAMETERS: name_arg - The 4-character ACPI name to find.
+ * wildcards are supported.
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Search the namespace for a given name (with wildcards)
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_find_name_in_namespace(char *name_arg)
+{
+ char acpi_name[5] = "____";
+ char *acpi_name_ptr = acpi_name;
+
+ if (strlen(name_arg) > ACPI_NAME_SIZE) {
+ acpi_os_printf("Name must be no longer than 4 characters\n");
+ return (AE_OK);
+ }
+
+ /* Pad out name with underscores as necessary to create a 4-char name */
+
+ acpi_ut_strupr(name_arg);
+ while (*name_arg) {
+ *acpi_name_ptr = *name_arg;
+ acpi_name_ptr++;
+ name_arg++;
+ }
+
+ /* Walk the namespace from the root */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_db_walk_and_match_name,
+ NULL, acpi_name, NULL);
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_walk_for_predefined_names
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Detect and display predefined ACPI names (names that start with
+ * an underscore)
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ u32 *count = (u32 *)context;
+ const union acpi_predefined_info *predefined;
+ const union acpi_predefined_info *package = NULL;
+ char *pathname;
+ char string_buffer[48];
+
+ predefined = acpi_ut_match_predefined_method(node->name.ascii);
+ if (!predefined) {
+ return (AE_OK);
+ }
+
+ pathname = acpi_ns_get_external_pathname(node);
+ if (!pathname) {
+ return (AE_OK);
+ }
+
+ /* If method returns a package, the info is in the next table entry */
+
+ if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) {
+ package = predefined + 1;
+ }
+
+ acpi_ut_get_expected_return_types(string_buffer,
+ predefined->info.expected_btypes);
+
+ acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname,
+ METHOD_GET_ARG_COUNT(predefined->info.argument_list),
+ string_buffer);
+
+ if (package) {
+ acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)",
+ package->ret_info.type,
+ package->ret_info.object_type1,
+ package->ret_info.count1);
+ }
+
+ acpi_os_printf("\n");
+
+ /* Check that the declared argument count matches the ACPI spec */
+
+ acpi_ns_check_acpi_compliance(pathname, node, predefined);
+
+ ACPI_FREE(pathname);
+ (*count)++;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_check_predefined_names
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Validate all predefined names in the namespace
+ *
+ ******************************************************************************/
+
+void acpi_db_check_predefined_names(void)
+{
+ u32 count = 0;
+
+ /* Search all nodes in namespace */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_db_walk_for_predefined_names, NULL,
+ (void *)&count, NULL);
+
+ acpi_os_printf("Found %u predefined names in the namespace\n", count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_walk_for_object_counts
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Display short info about objects in the namespace
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_walk_for_object_counts(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_object_info *info = (struct acpi_object_info *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+
+ if (node->type > ACPI_TYPE_NS_NODE_MAX) {
+ acpi_os_printf("[%4.4s]: Unknown object type %X\n",
+ node->name.ascii, node->type);
+ } else {
+ info->types[node->type]++;
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_walk_for_specific_objects
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Display short info about objects in the namespace
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_walk_info *info = (struct acpi_walk_info *)context;
+ struct acpi_buffer buffer;
+ acpi_status status;
+
+ info->count++;
+
+ /* Get and display the full pathname to this object */
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could Not get pathname for object %p\n",
+ obj_handle);
+ return (AE_OK);
+ }
+
+ acpi_os_printf("%32s", (char *)buffer.pointer);
+ ACPI_FREE(buffer.pointer);
+
+ /* Dump short info about the object */
+
+ (void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_objects
+ *
+ * PARAMETERS: obj_type_arg - Type of object to display
+ * display_count_arg - Max depth to display
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display objects in the namespace of the requested type
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg)
+{
+ struct acpi_walk_info info;
+ acpi_object_type type;
+ struct acpi_object_info *object_info;
+ u32 i;
+ u32 total_objects = 0;
+
+ /* No argument means display summary/count of all object types */
+
+ if (!obj_type_arg) {
+ object_info =
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
+
+ /* Walk the namespace from the root */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_db_walk_for_object_counts, NULL,
+ (void *)object_info, NULL);
+
+ acpi_os_printf("\nSummary of namespace objects:\n\n");
+
+ for (i = 0; i < ACPI_TOTAL_TYPES; i++) {
+ acpi_os_printf("%8u %s\n", object_info->types[i],
+ acpi_ut_get_type_name(i));
+
+ total_objects += object_info->types[i];
+ }
+
+ acpi_os_printf("\n%8u Total namespace objects\n\n",
+ total_objects);
+
+ ACPI_FREE(object_info);
+ return (AE_OK);
+ }
+
+ /* Get the object type */
+
+ type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types);
+ if (type == ACPI_TYPE_NOT_FOUND) {
+ acpi_os_printf("Invalid or unsupported argument\n");
+ return (AE_OK);
+ }
+
+ acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
+ acpi_os_printf
+ ("Objects of type [%s] defined in the current ACPI Namespace:\n",
+ acpi_ut_get_type_name(type));
+
+ acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
+
+ info.count = 0;
+ info.owner_id = ACPI_OWNER_ID_MAX;
+ info.debug_level = ACPI_UINT32_MAX;
+ info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
+
+ /* Walk the namespace from the root */
+
+ (void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ acpi_db_walk_for_specific_objects, NULL,
+ (void *)&info, NULL);
+
+ acpi_os_printf
+ ("\nFound %u objects of type [%s] in the current ACPI Namespace\n",
+ info.count, acpi_ut_get_type_name(type));
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_integrity_walk
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Examine one NS node for valid values.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_integrity_walk(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
+{
+ struct acpi_integrity_info *info =
+ (struct acpi_integrity_info *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ union acpi_operand_object *object;
+ u8 alias = TRUE;
+
+ info->nodes++;
+
+ /* Verify the NS node, and dereference aliases */
+
+ while (alias) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
+ acpi_os_printf
+ ("Invalid Descriptor Type for Node %p [%s] - "
+ "is %2.2X should be %2.2X\n", node,
+ acpi_ut_get_descriptor_name(node),
+ ACPI_GET_DESCRIPTOR_TYPE(node),
+ ACPI_DESC_TYPE_NAMED);
+ return (AE_OK);
+ }
+
+ if ((node->type == ACPI_TYPE_LOCAL_ALIAS) ||
+ (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
+ node = (struct acpi_namespace_node *)node->object;
+ } else {
+ alias = FALSE;
+ }
+ }
+
+ if (node->type > ACPI_TYPE_LOCAL_MAX) {
+ acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n",
+ node, node->type);
+ return (AE_OK);
+ }
+
+ if (!acpi_ut_valid_acpi_name(node->name.ascii)) {
+ acpi_os_printf("Invalid AcpiName for Node %p\n", node);
+ return (AE_OK);
+ }
+
+ object = acpi_ns_get_attached_object(node);
+ if (object) {
+ info->objects++;
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
+ acpi_os_printf
+ ("Invalid Descriptor Type for Object %p [%s]\n",
+ object, acpi_ut_get_descriptor_name(object));
+ }
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_check_integrity
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Check entire namespace for data structure integrity
+ *
+ ******************************************************************************/
+
+void acpi_db_check_integrity(void)
+{
+ struct acpi_integrity_info info = { 0, 0 };
+
+ /* Search all nodes in namespace */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL,
+ (void *)&info, NULL);
+
+ acpi_os_printf("Verified %u namespace nodes with %u Objects\n",
+ info.nodes, info.objects);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_walk_for_references
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check if this namespace object refers to the target object
+ * that is passed in as the context value.
+ *
+ * Note: Currently doesn't check subobjects within the Node's object
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_walk_for_references(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ union acpi_operand_object *obj_desc =
+ (union acpi_operand_object *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+
+ /* Check for match against the namespace node itself */
+
+ if (node == (void *)obj_desc) {
+ acpi_os_printf("Object is a Node [%4.4s]\n",
+ acpi_ut_get_node_name(node));
+ }
+
+ /* Check for match against the object attached to the node */
+
+ if (acpi_ns_get_attached_object(node) == obj_desc) {
+ acpi_os_printf("Reference at Node->Object %p [%4.4s]\n",
+ node, acpi_ut_get_node_name(node));
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_find_references
+ *
+ * PARAMETERS: object_arg - String with hex value of the object
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Search namespace for all references to the input object
+ *
+ ******************************************************************************/
+
+void acpi_db_find_references(char *object_arg)
+{
+ union acpi_operand_object *obj_desc;
+ acpi_size address;
+
+ /* Convert string to object pointer */
+
+ address = strtoul(object_arg, NULL, 16);
+ obj_desc = ACPI_TO_POINTER(address);
+
+ /* Search all nodes in namespace */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_db_walk_for_references,
+ NULL, (void *)obj_desc, NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_bus_walk
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Display info about device objects that have a corresponding
+ * _PRT method.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_bus_walk(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
+{
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ acpi_status status;
+ struct acpi_buffer buffer;
+ struct acpi_namespace_node *temp_node;
+ struct acpi_device_info *info;
+ u32 i;
+
+ if ((node->type != ACPI_TYPE_DEVICE) &&
+ (node->type != ACPI_TYPE_PROCESSOR)) {
+ return (AE_OK);
+ }
+
+ /* Exit if there is no _PRT under this device */
+
+ status = acpi_get_handle(node, METHOD_NAME__PRT,
+ ACPI_CAST_PTR(acpi_handle, &temp_node));
+ if (ACPI_FAILURE(status)) {
+ return (AE_OK);
+ }
+
+ /* Get the full path to this device object */
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could Not get pathname for object %p\n",
+ obj_handle);
+ return (AE_OK);
+ }
+
+ status = acpi_get_object_info(obj_handle, &info);
+ if (ACPI_FAILURE(status)) {
+ return (AE_OK);
+ }
+
+ /* Display the full path */
+
+ acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type);
+ ACPI_FREE(buffer.pointer);
+
+ if (info->flags & ACPI_PCI_ROOT_BRIDGE) {
+ acpi_os_printf(" - Is PCI Root Bridge");
+ }
+ acpi_os_printf("\n");
+
+ /* _PRT info */
+
+ acpi_os_printf("_PRT: %p\n", temp_node);
+
+ /* Dump _ADR, _HID, _UID, _CID */
+
+ if (info->valid & ACPI_VALID_ADR) {
+ acpi_os_printf("_ADR: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(info->address));
+ } else {
+ acpi_os_printf("_ADR: <Not Present>\n");
+ }
+
+ if (info->valid & ACPI_VALID_HID) {
+ acpi_os_printf("_HID: %s\n", info->hardware_id.string);
+ } else {
+ acpi_os_printf("_HID: <Not Present>\n");
+ }
+
+ if (info->valid & ACPI_VALID_UID) {
+ acpi_os_printf("_UID: %s\n", info->unique_id.string);
+ } else {
+ acpi_os_printf("_UID: <Not Present>\n");
+ }
+
+ if (info->valid & ACPI_VALID_CID) {
+ for (i = 0; i < info->compatible_id_list.count; i++) {
+ acpi_os_printf("_CID: %s\n",
+ info->compatible_id_list.ids[i].string);
+ }
+ } else {
+ acpi_os_printf("_CID: <Not Present>\n");
+ }
+
+ ACPI_FREE(info);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_get_bus_info
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display info about system busses.
+ *
+ ******************************************************************************/
+
+void acpi_db_get_bus_info(void)
+{
+ /* Search all nodes in namespace */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL,
+ NULL);
+}
diff --git a/drivers/acpi/acpica/dbobject.c b/drivers/acpi/acpica/dbobject.c
new file mode 100644
index 000000000000..116f6db8c2ed
--- /dev/null
+++ b/drivers/acpi/acpica/dbobject.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ *
+ * Module Name: dbobject - ACPI object decode and display
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbobject")
+
+/* Local prototypes */
+static void acpi_db_decode_node(struct acpi_namespace_node *node);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_method_info
+ *
+ * PARAMETERS: status - Method execution status
+ * walk_state - Current state of the parse tree walk
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Called when a method has been aborted because of an error.
+ * Dumps the method execution stack, and the method locals/args,
+ * and disassembles the AML opcode that failed.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_dump_method_info(acpi_status status, struct acpi_walk_state *walk_state)
+{
+ struct acpi_thread_state *thread;
+
+ /* Ignore control codes, they are not errors */
+
+ if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) {
+ return;
+ }
+
+ /* We may be executing a deferred opcode */
+
+ if (walk_state->deferred_node) {
+ acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
+ return;
+ }
+
+ /*
+ * If there is no Thread, we are not actually executing a method.
+ * This can happen when the iASL compiler calls the interpreter
+ * to perform constant folding.
+ */
+ thread = walk_state->thread;
+ if (!thread) {
+ return;
+ }
+
+ /* Display the method locals and arguments */
+
+ acpi_os_printf("\n");
+ acpi_db_decode_locals(walk_state);
+ acpi_os_printf("\n");
+ acpi_db_decode_arguments(walk_state);
+ acpi_os_printf("\n");
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_decode_internal_object
+ *
+ * PARAMETERS: obj_desc - Object to be displayed
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
+ *
+ ******************************************************************************/
+
+void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc)
+{
+ u32 i;
+
+ if (!obj_desc) {
+ acpi_os_printf(" Uninitialized");
+ return;
+ }
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ acpi_os_printf(" %p [%s]", obj_desc,
+ acpi_ut_get_descriptor_name(obj_desc));
+ return;
+ }
+
+ acpi_os_printf(" %s", acpi_ut_get_object_type_name(obj_desc));
+
+ switch (obj_desc->common.type) {
+ case ACPI_TYPE_INTEGER:
+
+ acpi_os_printf(" %8.8X%8.8X",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ acpi_os_printf("(%u) \"%.24s",
+ obj_desc->string.length,
+ obj_desc->string.pointer);
+
+ if (obj_desc->string.length > 24) {
+ acpi_os_printf("...");
+ } else {
+ acpi_os_printf("\"");
+ }
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ acpi_os_printf("(%u)", obj_desc->buffer.length);
+ for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) {
+ acpi_os_printf(" %2.2X", obj_desc->buffer.pointer[i]);
+ }
+ break;
+
+ default:
+
+ acpi_os_printf(" %p", obj_desc);
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_decode_node
+ *
+ * PARAMETERS: node - Object to be displayed
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Short display of a namespace node
+ *
+ ******************************************************************************/
+
+static void acpi_db_decode_node(struct acpi_namespace_node *node)
+{
+
+ acpi_os_printf("<Node> Name %4.4s",
+ acpi_ut_get_node_name(node));
+
+ if (node->flags & ANOBJ_METHOD_ARG) {
+ acpi_os_printf(" [Method Arg]");
+ }
+ if (node->flags & ANOBJ_METHOD_LOCAL) {
+ acpi_os_printf(" [Method Local]");
+ }
+
+ switch (node->type) {
+
+ /* These types have no attached object */
+
+ case ACPI_TYPE_DEVICE:
+
+ acpi_os_printf(" Device");
+ break;
+
+ case ACPI_TYPE_THERMAL:
+
+ acpi_os_printf(" Thermal Zone");
+ break;
+
+ default:
+
+ acpi_db_decode_internal_object(acpi_ns_get_attached_object
+ (node));
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_internal_object
+ *
+ * PARAMETERS: obj_desc - Object to be displayed
+ * walk_state - Current walk state
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Short display of an internal object
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_internal_object(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
+{
+ u8 type;
+
+ acpi_os_printf("%p ", obj_desc);
+
+ if (!obj_desc) {
+ acpi_os_printf("<Null Object>\n");
+ return;
+ }
+
+ /* Decode the object type */
+
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
+ case ACPI_DESC_TYPE_PARSER:
+
+ acpi_os_printf("<Parser> ");
+ break;
+
+ case ACPI_DESC_TYPE_NAMED:
+
+ acpi_db_decode_node((struct acpi_namespace_node *)obj_desc);
+ break;
+
+ case ACPI_DESC_TYPE_OPERAND:
+
+ type = obj_desc->common.type;
+ if (type > ACPI_TYPE_LOCAL_MAX) {
+ acpi_os_printf(" Type %X [Invalid Type]", (u32)type);
+ return;
+ }
+
+ /* Decode the ACPI object type */
+
+ switch (obj_desc->common.type) {
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ acpi_os_printf("[%s] ",
+ acpi_ut_get_reference_name(obj_desc));
+
+ /* Decode the refererence */
+
+ switch (obj_desc->reference.class) {
+ case ACPI_REFCLASS_LOCAL:
+
+ acpi_os_printf("%X ",
+ obj_desc->reference.value);
+ if (walk_state) {
+ obj_desc = walk_state->local_variables
+ [obj_desc->reference.value].object;
+ acpi_os_printf("%p", obj_desc);
+ acpi_db_decode_internal_object
+ (obj_desc);
+ }
+ break;
+
+ case ACPI_REFCLASS_ARG:
+
+ acpi_os_printf("%X ",
+ obj_desc->reference.value);
+ if (walk_state) {
+ obj_desc = walk_state->arguments
+ [obj_desc->reference.value].object;
+ acpi_os_printf("%p", obj_desc);
+ acpi_db_decode_internal_object
+ (obj_desc);
+ }
+ break;
+
+ case ACPI_REFCLASS_INDEX:
+
+ switch (obj_desc->reference.target_type) {
+ case ACPI_TYPE_BUFFER_FIELD:
+
+ acpi_os_printf("%p",
+ obj_desc->reference.
+ object);
+ acpi_db_decode_internal_object
+ (obj_desc->reference.object);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ acpi_os_printf("%p",
+ obj_desc->reference.
+ where);
+ if (!obj_desc->reference.where) {
+ acpi_os_printf
+ (" Uninitialized WHERE pointer");
+ } else {
+ acpi_db_decode_internal_object(*
+ (obj_desc->
+ reference.
+ where));
+ }
+ break;
+
+ default:
+
+ acpi_os_printf
+ ("Unknown index target type");
+ break;
+ }
+ break;
+
+ case ACPI_REFCLASS_REFOF:
+
+ if (!obj_desc->reference.object) {
+ acpi_os_printf
+ ("Uninitialized reference subobject pointer");
+ break;
+ }
+
+ /* Reference can be to a Node or an Operand object */
+
+ switch (ACPI_GET_DESCRIPTOR_TYPE
+ (obj_desc->reference.object)) {
+ case ACPI_DESC_TYPE_NAMED:
+
+ acpi_db_decode_node(obj_desc->reference.
+ object);
+ break;
+
+ case ACPI_DESC_TYPE_OPERAND:
+
+ acpi_db_decode_internal_object
+ (obj_desc->reference.object);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case ACPI_REFCLASS_NAME:
+
+ acpi_db_decode_node(obj_desc->reference.node);
+ break;
+
+ case ACPI_REFCLASS_DEBUG:
+ case ACPI_REFCLASS_TABLE:
+
+ acpi_os_printf("\n");
+ break;
+
+ default: /* Unknown reference class */
+
+ acpi_os_printf("%2.2X\n",
+ obj_desc->reference.class);
+ break;
+ }
+ break;
+
+ default:
+
+ acpi_os_printf("<Obj> ");
+ acpi_db_decode_internal_object(obj_desc);
+ break;
+ }
+ break;
+
+ default:
+
+ acpi_os_printf("<Not a valid ACPI Object Descriptor> [%s]",
+ acpi_ut_get_descriptor_name(obj_desc));
+ break;
+ }
+
+ acpi_os_printf("\n");
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_decode_locals
+ *
+ * PARAMETERS: walk_state - State for current method
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display all locals for the currently running control method
+ *
+ ******************************************************************************/
+
+void acpi_db_decode_locals(struct acpi_walk_state *walk_state)
+{
+ u32 i;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ u8 display_locals = FALSE;
+
+ obj_desc = walk_state->method_desc;
+ node = walk_state->method_node;
+
+ if (!node) {
+ acpi_os_printf
+ ("No method node (Executing subtree for buffer or opregion)\n");
+ return;
+ }
+
+ if (node->type != ACPI_TYPE_METHOD) {
+ acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
+ return;
+ }
+
+ /* Are any locals actually set? */
+
+ for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
+ obj_desc = walk_state->local_variables[i].object;
+ if (obj_desc) {
+ display_locals = TRUE;
+ break;
+ }
+ }
+
+ /* If any are set, only display the ones that are set */
+
+ if (display_locals) {
+ acpi_os_printf
+ ("\nInitialized Local Variables for method [%4.4s]:\n",
+ acpi_ut_get_node_name(node));
+
+ for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
+ obj_desc = walk_state->local_variables[i].object;
+ if (obj_desc) {
+ acpi_os_printf(" Local%X: ", i);
+ acpi_db_display_internal_object(obj_desc,
+ walk_state);
+ }
+ }
+ } else {
+ acpi_os_printf
+ ("No Local Variables are initialized for method [%4.4s]\n",
+ acpi_ut_get_node_name(node));
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_decode_arguments
+ *
+ * PARAMETERS: walk_state - State for current method
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display all arguments for the currently running control method
+ *
+ ******************************************************************************/
+
+void acpi_db_decode_arguments(struct acpi_walk_state *walk_state)
+{
+ u32 i;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ u8 display_args = FALSE;
+
+ node = walk_state->method_node;
+ obj_desc = walk_state->method_desc;
+
+ if (!node) {
+ acpi_os_printf
+ ("No method node (Executing subtree for buffer or opregion)\n");
+ return;
+ }
+
+ if (node->type != ACPI_TYPE_METHOD) {
+ acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
+ return;
+ }
+
+ /* Are any arguments actually set? */
+
+ for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
+ obj_desc = walk_state->arguments[i].object;
+ if (obj_desc) {
+ display_args = TRUE;
+ break;
+ }
+ }
+
+ /* If any are set, only display the ones that are set */
+
+ if (display_args) {
+ acpi_os_printf("Initialized Arguments for Method [%4.4s]: "
+ "(%X arguments defined for method invocation)\n",
+ acpi_ut_get_node_name(node),
+ obj_desc->method.param_count);
+
+ for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
+ obj_desc = walk_state->arguments[i].object;
+ if (obj_desc) {
+ acpi_os_printf(" Arg%u: ", i);
+ acpi_db_display_internal_object(obj_desc,
+ walk_state);
+ }
+ }
+ } else {
+ acpi_os_printf
+ ("No Arguments are initialized for method [%4.4s]\n",
+ acpi_ut_get_node_name(node));
+ }
+}
diff --git a/drivers/acpi/acpica/dbstats.c b/drivers/acpi/acpica/dbstats.c
new file mode 100644
index 000000000000..4ba0a20811eb
--- /dev/null
+++ b/drivers/acpi/acpica/dbstats.c
@@ -0,0 +1,546 @@
+/*******************************************************************************
+ *
+ * Module Name: dbstats - Generation and display of ACPI table statistics
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+#include "acnamesp.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbstats")
+
+/* Local prototypes */
+static void acpi_db_count_namespace_objects(void);
+
+static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc);
+
+static acpi_status
+acpi_db_classify_one_object(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
+static void acpi_db_list_info(struct acpi_memory_list *list);
+#endif
+
+/*
+ * Statistics subcommands
+ */
+static struct acpi_db_argument_info acpi_db_stat_types[] = {
+ {"ALLOCATIONS"},
+ {"OBJECTS"},
+ {"MEMORY"},
+ {"MISC"},
+ {"TABLES"},
+ {"SIZES"},
+ {"STACK"},
+ {NULL} /* Must be null terminated */
+};
+
+#define CMD_STAT_ALLOCATIONS 0
+#define CMD_STAT_OBJECTS 1
+#define CMD_STAT_MEMORY 2
+#define CMD_STAT_MISC 3
+#define CMD_STAT_TABLES 4
+#define CMD_STAT_SIZES 5
+#define CMD_STAT_STACK 6
+
+#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_list_info
+ *
+ * PARAMETERS: list - Memory list/cache to be displayed
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Display information about the input memory list or cache.
+ *
+ ******************************************************************************/
+
+static void acpi_db_list_info(struct acpi_memory_list *list)
+{
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ u32 outstanding;
+#endif
+
+ acpi_os_printf("\n%s\n", list->list_name);
+
+ /* max_depth > 0 indicates a cache object */
+
+ if (list->max_depth > 0) {
+ acpi_os_printf
+ (" Cache: [Depth MaxD Avail Size] "
+ "%8.2X %8.2X %8.2X %8.2X\n", list->current_depth,
+ list->max_depth, list->max_depth - list->current_depth,
+ (list->current_depth * list->object_size));
+ }
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ if (list->max_depth > 0) {
+ acpi_os_printf
+ (" Cache: [Requests Hits Misses ObjSize] "
+ "%8.2X %8.2X %8.2X %8.2X\n", list->requests, list->hits,
+ list->requests - list->hits, list->object_size);
+ }
+
+ outstanding = acpi_db_get_cache_info(list);
+
+ if (list->object_size) {
+ acpi_os_printf
+ (" Mem: [Alloc Free Max CurSize Outstanding] "
+ "%8.2X %8.2X %8.2X %8.2X %8.2X\n", list->total_allocated,
+ list->total_freed, list->max_occupied,
+ outstanding * list->object_size, outstanding);
+ } else {
+ acpi_os_printf
+ (" Mem: [Alloc Free Max CurSize Outstanding Total] "
+ "%8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n",
+ list->total_allocated, list->total_freed,
+ list->max_occupied, list->current_total_size, outstanding,
+ list->total_size);
+ }
+#endif
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_enumerate_object
+ *
+ * PARAMETERS: obj_desc - Object to be counted
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Add this object to the global counts, by object type.
+ * Limited recursion handles subobjects and packages, and this
+ * is probably acceptable within the AML debugger only.
+ *
+ ******************************************************************************/
+
+static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc)
+{
+ u32 i;
+
+ if (!obj_desc) {
+ return;
+ }
+
+ /* Enumerate this object first */
+
+ acpi_gbl_num_objects++;
+
+ if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) {
+ acpi_gbl_obj_type_count_misc++;
+ } else {
+ acpi_gbl_obj_type_count[obj_desc->common.type]++;
+ }
+
+ /* Count the sub-objects */
+
+ switch (obj_desc->common.type) {
+ case ACPI_TYPE_PACKAGE:
+
+ for (i = 0; i < obj_desc->package.count; i++) {
+ acpi_db_enumerate_object(obj_desc->package.elements[i]);
+ }
+ break;
+
+ case ACPI_TYPE_DEVICE:
+
+ acpi_db_enumerate_object(obj_desc->device.notify_list[0]);
+ acpi_db_enumerate_object(obj_desc->device.notify_list[1]);
+ acpi_db_enumerate_object(obj_desc->device.handler);
+ break;
+
+ case ACPI_TYPE_BUFFER_FIELD:
+
+ if (acpi_ns_get_secondary_object(obj_desc)) {
+ acpi_gbl_obj_type_count[ACPI_TYPE_BUFFER_FIELD]++;
+ }
+ break;
+
+ case ACPI_TYPE_REGION:
+
+ acpi_gbl_obj_type_count[ACPI_TYPE_LOCAL_REGION_FIELD]++;
+ acpi_db_enumerate_object(obj_desc->region.handler);
+ break;
+
+ case ACPI_TYPE_POWER:
+
+ acpi_db_enumerate_object(obj_desc->power_resource.
+ notify_list[0]);
+ acpi_db_enumerate_object(obj_desc->power_resource.
+ notify_list[1]);
+ break;
+
+ case ACPI_TYPE_PROCESSOR:
+
+ acpi_db_enumerate_object(obj_desc->processor.notify_list[0]);
+ acpi_db_enumerate_object(obj_desc->processor.notify_list[1]);
+ acpi_db_enumerate_object(obj_desc->processor.handler);
+ break;
+
+ case ACPI_TYPE_THERMAL:
+
+ acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[0]);
+ acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[1]);
+ acpi_db_enumerate_object(obj_desc->thermal_zone.handler);
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_classify_one_object
+ *
+ * PARAMETERS: Callback for walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and
+ * the parent namespace node.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_classify_one_object(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *obj_desc;
+ u32 type;
+
+ acpi_gbl_num_nodes++;
+
+ node = (struct acpi_namespace_node *)obj_handle;
+ obj_desc = acpi_ns_get_attached_object(node);
+
+ acpi_db_enumerate_object(obj_desc);
+
+ type = node->type;
+ if (type > ACPI_TYPE_NS_NODE_MAX) {
+ acpi_gbl_node_type_count_misc++;
+ } else {
+ acpi_gbl_node_type_count[type]++;
+ }
+
+ return (AE_OK);
+
+#ifdef ACPI_FUTURE_IMPLEMENTATION
+
+ /* TBD: These need to be counted during the initial parsing phase */
+
+ if (acpi_ps_is_named_op(op->opcode)) {
+ num_nodes++;
+ }
+
+ if (is_method) {
+ num_method_elements++;
+ }
+
+ num_grammar_elements++;
+ op = acpi_ps_get_depth_next(root, op);
+
+ size_of_parse_tree = (num_grammar_elements - num_method_elements) *
+ (u32)sizeof(union acpi_parse_object);
+ size_of_method_trees =
+ num_method_elements * (u32)sizeof(union acpi_parse_object);
+ size_of_node_entries =
+ num_nodes * (u32)sizeof(struct acpi_namespace_node);
+ size_of_acpi_objects =
+ num_nodes * (u32)sizeof(union acpi_operand_object);
+#endif
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_count_namespace_objects
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Count and classify the entire namespace, including all
+ * namespace nodes and attached objects.
+ *
+ ******************************************************************************/
+
+static void acpi_db_count_namespace_objects(void)
+{
+ u32 i;
+
+ acpi_gbl_num_nodes = 0;
+ acpi_gbl_num_objects = 0;
+
+ acpi_gbl_obj_type_count_misc = 0;
+ for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX - 1); i++) {
+ acpi_gbl_obj_type_count[i] = 0;
+ acpi_gbl_node_type_count[i] = 0;
+ }
+
+ (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE,
+ acpi_db_classify_one_object, NULL, NULL,
+ NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_display_statistics
+ *
+ * PARAMETERS: type_arg - Subcommand
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Display various statistics
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_display_statistics(char *type_arg)
+{
+ u32 i;
+ u32 temp;
+
+ acpi_ut_strupr(type_arg);
+ temp = acpi_db_match_argument(type_arg, acpi_db_stat_types);
+ if (temp == ACPI_TYPE_NOT_FOUND) {
+ acpi_os_printf("Invalid or unsupported argument\n");
+ return (AE_OK);
+ }
+
+ switch (temp) {
+ case CMD_STAT_ALLOCATIONS:
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ acpi_ut_dump_allocation_info();
+#endif
+ break;
+
+ case CMD_STAT_TABLES:
+
+ acpi_os_printf("ACPI Table Information (not implemented):\n\n");
+ break;
+
+ case CMD_STAT_OBJECTS:
+
+ acpi_db_count_namespace_objects();
+
+ acpi_os_printf
+ ("\nObjects defined in the current namespace:\n\n");
+
+ acpi_os_printf("%16.16s %10.10s %10.10s\n",
+ "ACPI_TYPE", "NODES", "OBJECTS");
+
+ for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
+ acpi_os_printf("%16.16s % 10ld% 10ld\n",
+ acpi_ut_get_type_name(i),
+ acpi_gbl_node_type_count[i],
+ acpi_gbl_obj_type_count[i]);
+ }
+ acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
+ acpi_gbl_node_type_count_misc,
+ acpi_gbl_obj_type_count_misc);
+
+ acpi_os_printf("%16.16s % 10ld% 10ld\n", "TOTALS:",
+ acpi_gbl_num_nodes, acpi_gbl_num_objects);
+ break;
+
+ case CMD_STAT_MEMORY:
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ acpi_os_printf
+ ("\n----Object Statistics (all in hex)---------\n");
+
+ acpi_db_list_info(acpi_gbl_global_list);
+ acpi_db_list_info(acpi_gbl_ns_node_list);
+#endif
+
+#ifdef ACPI_USE_LOCAL_CACHE
+ acpi_os_printf
+ ("\n----Cache Statistics (all in hex)---------\n");
+ acpi_db_list_info(acpi_gbl_operand_cache);
+ acpi_db_list_info(acpi_gbl_ps_node_cache);
+ acpi_db_list_info(acpi_gbl_ps_node_ext_cache);
+ acpi_db_list_info(acpi_gbl_state_cache);
+#endif
+
+ break;
+
+ case CMD_STAT_MISC:
+
+ acpi_os_printf("\nMiscellaneous Statistics:\n\n");
+ acpi_os_printf("Calls to AcpiPsFind:.. ........% 7ld\n",
+ acpi_gbl_ps_find_count);
+ acpi_os_printf("Calls to AcpiNsLookup:..........% 7ld\n",
+ acpi_gbl_ns_lookup_count);
+
+ acpi_os_printf("\n");
+
+ acpi_os_printf("Mutex usage:\n\n");
+ for (i = 0; i < ACPI_NUM_MUTEX; i++) {
+ acpi_os_printf("%-28s: % 7ld\n",
+ acpi_ut_get_mutex_name(i),
+ acpi_gbl_mutex_info[i].use_count);
+ }
+ break;
+
+ case CMD_STAT_SIZES:
+
+ acpi_os_printf("\nInternal object sizes:\n\n");
+
+ acpi_os_printf("Common %3d\n",
+ sizeof(struct acpi_object_common));
+ acpi_os_printf("Number %3d\n",
+ sizeof(struct acpi_object_integer));
+ acpi_os_printf("String %3d\n",
+ sizeof(struct acpi_object_string));
+ acpi_os_printf("Buffer %3d\n",
+ sizeof(struct acpi_object_buffer));
+ acpi_os_printf("Package %3d\n",
+ sizeof(struct acpi_object_package));
+ acpi_os_printf("BufferField %3d\n",
+ sizeof(struct acpi_object_buffer_field));
+ acpi_os_printf("Device %3d\n",
+ sizeof(struct acpi_object_device));
+ acpi_os_printf("Event %3d\n",
+ sizeof(struct acpi_object_event));
+ acpi_os_printf("Method %3d\n",
+ sizeof(struct acpi_object_method));
+ acpi_os_printf("Mutex %3d\n",
+ sizeof(struct acpi_object_mutex));
+ acpi_os_printf("Region %3d\n",
+ sizeof(struct acpi_object_region));
+ acpi_os_printf("PowerResource %3d\n",
+ sizeof(struct acpi_object_power_resource));
+ acpi_os_printf("Processor %3d\n",
+ sizeof(struct acpi_object_processor));
+ acpi_os_printf("ThermalZone %3d\n",
+ sizeof(struct acpi_object_thermal_zone));
+ acpi_os_printf("RegionField %3d\n",
+ sizeof(struct acpi_object_region_field));
+ acpi_os_printf("BankField %3d\n",
+ sizeof(struct acpi_object_bank_field));
+ acpi_os_printf("IndexField %3d\n",
+ sizeof(struct acpi_object_index_field));
+ acpi_os_printf("Reference %3d\n",
+ sizeof(struct acpi_object_reference));
+ acpi_os_printf("Notify %3d\n",
+ sizeof(struct acpi_object_notify_handler));
+ acpi_os_printf("AddressSpace %3d\n",
+ sizeof(struct acpi_object_addr_handler));
+ acpi_os_printf("Extra %3d\n",
+ sizeof(struct acpi_object_extra));
+ acpi_os_printf("Data %3d\n",
+ sizeof(struct acpi_object_data));
+
+ acpi_os_printf("\n");
+
+ acpi_os_printf("ParseObject %3d\n",
+ sizeof(struct acpi_parse_obj_common));
+ acpi_os_printf("ParseObjectNamed %3d\n",
+ sizeof(struct acpi_parse_obj_named));
+ acpi_os_printf("ParseObjectAsl %3d\n",
+ sizeof(struct acpi_parse_obj_asl));
+ acpi_os_printf("OperandObject %3d\n",
+ sizeof(union acpi_operand_object));
+ acpi_os_printf("NamespaceNode %3d\n",
+ sizeof(struct acpi_namespace_node));
+ acpi_os_printf("AcpiObject %3d\n",
+ sizeof(union acpi_object));
+
+ acpi_os_printf("\n");
+
+ acpi_os_printf("Generic State %3d\n",
+ sizeof(union acpi_generic_state));
+ acpi_os_printf("Common State %3d\n",
+ sizeof(struct acpi_common_state));
+ acpi_os_printf("Control State %3d\n",
+ sizeof(struct acpi_control_state));
+ acpi_os_printf("Update State %3d\n",
+ sizeof(struct acpi_update_state));
+ acpi_os_printf("Scope State %3d\n",
+ sizeof(struct acpi_scope_state));
+ acpi_os_printf("Parse Scope %3d\n",
+ sizeof(struct acpi_pscope_state));
+ acpi_os_printf("Package State %3d\n",
+ sizeof(struct acpi_pkg_state));
+ acpi_os_printf("Thread State %3d\n",
+ sizeof(struct acpi_thread_state));
+ acpi_os_printf("Result Values %3d\n",
+ sizeof(struct acpi_result_values));
+ acpi_os_printf("Notify Info %3d\n",
+ sizeof(struct acpi_notify_info));
+ break;
+
+ case CMD_STAT_STACK:
+#if defined(ACPI_DEBUG_OUTPUT)
+
+ temp =
+ (u32)ACPI_PTR_DIFF(acpi_gbl_entry_stack_pointer,
+ acpi_gbl_lowest_stack_pointer);
+
+ acpi_os_printf("\nSubsystem Stack Usage:\n\n");
+ acpi_os_printf("Entry Stack Pointer %p\n",
+ acpi_gbl_entry_stack_pointer);
+ acpi_os_printf("Lowest Stack Pointer %p\n",
+ acpi_gbl_lowest_stack_pointer);
+ acpi_os_printf("Stack Use %X (%u)\n", temp,
+ temp);
+ acpi_os_printf("Deepest Procedure Nesting %u\n",
+ acpi_gbl_deepest_nesting);
+#endif
+ break;
+
+ default:
+
+ break;
+ }
+
+ acpi_os_printf("\n");
+ return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/dbtest.c b/drivers/acpi/acpica/dbtest.c
new file mode 100644
index 000000000000..10ea8bf9b810
--- /dev/null
+++ b/drivers/acpi/acpica/dbtest.c
@@ -0,0 +1,1057 @@
+/*******************************************************************************
+ *
+ * Module Name: dbtest - Various debug-related tests
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acdebug.h"
+#include "acnamesp.h"
+#include "acpredef.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbtest")
+
+/* Local prototypes */
+static void acpi_db_test_all_objects(void);
+
+static acpi_status
+acpi_db_test_one_object(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
+
+static acpi_status
+acpi_db_test_integer_type(struct acpi_namespace_node *node, u32 bit_length);
+
+static acpi_status
+acpi_db_test_buffer_type(struct acpi_namespace_node *node, u32 bit_length);
+
+static acpi_status
+acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length);
+
+static acpi_status
+acpi_db_read_from_object(struct acpi_namespace_node *node,
+ acpi_object_type expected_type,
+ union acpi_object **value);
+
+static acpi_status
+acpi_db_write_to_object(struct acpi_namespace_node *node,
+ union acpi_object *value);
+
+static void acpi_db_evaluate_all_predefined_names(char *count_arg);
+
+static acpi_status
+acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
+
+/*
+ * Test subcommands
+ */
+static struct acpi_db_argument_info acpi_db_test_types[] = {
+ {"OBJECTS"},
+ {"PREDEFINED"},
+ {NULL} /* Must be null terminated */
+};
+
+#define CMD_TEST_OBJECTS 0
+#define CMD_TEST_PREDEFINED 1
+
+#define BUFFER_FILL_VALUE 0xFF
+
+/*
+ * Support for the special debugger read/write control methods.
+ * These methods are installed into the current namespace and are
+ * used to read and write the various namespace objects. The point
+ * is to force the AML interpreter do all of the work.
+ */
+#define ACPI_DB_READ_METHOD "\\_T98"
+#define ACPI_DB_WRITE_METHOD "\\_T99"
+
+static acpi_handle read_handle = NULL;
+static acpi_handle write_handle = NULL;
+
+/* ASL Definitions of the debugger read/write control methods */
+
+#if 0
+definition_block("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
+{
+ method(_T98, 1, not_serialized) { /* Read */
+ return (de_ref_of(arg0))
+ }
+}
+
+definition_block("ssdt2.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
+{
+ method(_T99, 2, not_serialized) { /* Write */
+ store(arg1, arg0)
+ }
+}
+#endif
+
+static unsigned char read_method_code[] = {
+ 0x53, 0x53, 0x44, 0x54, 0x2E, 0x00, 0x00, 0x00, /* 00000000 "SSDT...." */
+ 0x02, 0xC9, 0x49, 0x6E, 0x74, 0x65, 0x6C, 0x00, /* 00000008 "..Intel." */
+ 0x44, 0x45, 0x42, 0x55, 0x47, 0x00, 0x00, 0x00, /* 00000010 "DEBUG..." */
+ 0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* 00000018 "....INTL" */
+ 0x18, 0x12, 0x13, 0x20, 0x14, 0x09, 0x5F, 0x54, /* 00000020 "... .._T" */
+ 0x39, 0x38, 0x01, 0xA4, 0x83, 0x68 /* 00000028 "98...h" */
+};
+
+static unsigned char write_method_code[] = {
+ 0x53, 0x53, 0x44, 0x54, 0x2E, 0x00, 0x00, 0x00, /* 00000000 "SSDT...." */
+ 0x02, 0x15, 0x49, 0x6E, 0x74, 0x65, 0x6C, 0x00, /* 00000008 "..Intel." */
+ 0x44, 0x45, 0x42, 0x55, 0x47, 0x00, 0x00, 0x00, /* 00000010 "DEBUG..." */
+ 0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* 00000018 "....INTL" */
+ 0x18, 0x12, 0x13, 0x20, 0x14, 0x09, 0x5F, 0x54, /* 00000020 "... .._T" */
+ 0x39, 0x39, 0x02, 0x70, 0x69, 0x68 /* 00000028 "99.pih" */
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_execute_test
+ *
+ * PARAMETERS: type_arg - Subcommand
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Execute various debug tests.
+ *
+ * Note: Code is prepared for future expansion of the TEST command.
+ *
+ ******************************************************************************/
+
+void acpi_db_execute_test(char *type_arg)
+{
+ u32 temp;
+
+ acpi_ut_strupr(type_arg);
+ temp = acpi_db_match_argument(type_arg, acpi_db_test_types);
+ if (temp == ACPI_TYPE_NOT_FOUND) {
+ acpi_os_printf("Invalid or unsupported argument\n");
+ return;
+ }
+
+ switch (temp) {
+ case CMD_TEST_OBJECTS:
+
+ acpi_db_test_all_objects();
+ break;
+
+ case CMD_TEST_PREDEFINED:
+
+ acpi_db_evaluate_all_predefined_names(NULL);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_test_all_objects
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: This test implements the OBJECTS subcommand. It exercises the
+ * namespace by reading/writing/comparing all data objects such
+ * as integers, strings, buffers, fields, buffer fields, etc.
+ *
+ ******************************************************************************/
+
+static void acpi_db_test_all_objects(void)
+{
+ acpi_status status;
+
+ /* Install the debugger read-object control method if necessary */
+
+ if (!read_handle) {
+ status = acpi_install_method(read_method_code);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("%s, Could not install debugger read method\n",
+ acpi_format_exception(status));
+ return;
+ }
+
+ status =
+ acpi_get_handle(NULL, ACPI_DB_READ_METHOD, &read_handle);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("Could not obtain handle for debug method %s\n",
+ ACPI_DB_READ_METHOD);
+ return;
+ }
+ }
+
+ /* Install the debugger write-object control method if necessary */
+
+ if (!write_handle) {
+ status = acpi_install_method(write_method_code);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("%s, Could not install debugger write method\n",
+ acpi_format_exception(status));
+ return;
+ }
+
+ status =
+ acpi_get_handle(NULL, ACPI_DB_WRITE_METHOD, &write_handle);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("Could not obtain handle for debug method %s\n",
+ ACPI_DB_WRITE_METHOD);
+ return;
+ }
+ }
+
+ /* Walk the entire namespace, testing each supported named data object */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_db_test_one_object,
+ NULL, NULL, NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_test_one_object
+ *
+ * PARAMETERS: acpi_walk_callback
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_test_one_object(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
+{
+ 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;
+ acpi_status status = AE_OK;
+
+ node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
+ obj_desc = node->object;
+
+ /*
+ * For the supported types, get the actual bit length or
+ * byte length. Map the type to one of Integer/String/Buffer.
+ */
+ switch (node->type) {
+ case ACPI_TYPE_INTEGER:
+
+ /* Integer width is either 32 or 64 */
+
+ local_type = ACPI_TYPE_INTEGER;
+ bit_length = acpi_gbl_integer_bit_width;
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ local_type = ACPI_TYPE_STRING;
+ byte_length = obj_desc->string.length;
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ local_type = ACPI_TYPE_BUFFER;
+ byte_length = obj_desc->buffer.length;
+ bit_length = byte_length * 8;
+ 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_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) {
+ local_type = ACPI_TYPE_BUFFER;
+ }
+ }
+ break;
+
+ default:
+
+ /* Ignore all other types */
+
+ return (AE_OK);
+ }
+
+ /* Emit the common prefix: Type:Name */
+
+ acpi_os_printf("%14s: %4.4s",
+ acpi_ut_get_type_name(node->type), node->name.ascii);
+ if (!obj_desc) {
+ acpi_os_printf(" Ignoring, no attached object\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:
+ case ACPI_ADR_SPACE_EC:
+
+ break;
+
+ default:
+
+ acpi_os_printf
+ (" %s space is not supported [%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) {
+ case ACPI_TYPE_INTEGER:
+
+ status = acpi_db_test_integer_type(node, bit_length);
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ status = acpi_db_test_string_type(node, byte_length);
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ status = acpi_db_test_buffer_type(node, bit_length);
+ break;
+
+ default:
+
+ acpi_os_printf(" Ignoring, type not implemented (%2.2X)",
+ local_type);
+ break;
+ }
+
+ 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;
+ }
+
+ acpi_os_printf("\n");
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_test_integer_type
+ *
+ * PARAMETERS: node - Parent NS node for the object
+ * bit_length - Actual length of the object. Used for
+ * support of arbitrary length field_unit
+ * and buffer_field objects.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Test read/write for an Integer-valued object. Performs a
+ * write/read/compare of an arbitrary new value, then performs
+ * a write/read/compare of the original value.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_test_integer_type(struct acpi_namespace_node *node, u32 bit_length)
+{
+ union acpi_object *temp1 = NULL;
+ union acpi_object *temp2 = NULL;
+ union acpi_object *temp3 = NULL;
+ union acpi_object write_value;
+ u64 value_to_write;
+ acpi_status status;
+
+ if (bit_length > 64) {
+ acpi_os_printf(" Invalid length for an Integer: %u",
+ bit_length);
+ return (AE_OK);
+ }
+
+ /* Read the original value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_INTEGER, &temp1);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ acpi_os_printf(" (%4.4X/%3.3X) %8.8X%8.8X",
+ bit_length, ACPI_ROUND_BITS_UP_TO_BYTES(bit_length),
+ ACPI_FORMAT_UINT64(temp1->integer.value));
+
+ value_to_write = ACPI_UINT64_MAX >> (64 - bit_length);
+ if (temp1->integer.value == value_to_write) {
+ value_to_write = 0;
+ }
+
+ /* Write a new value */
+
+ write_value.type = ACPI_TYPE_INTEGER;
+ write_value.integer.value = value_to_write;
+ status = acpi_db_write_to_object(node, &write_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Ensure that we can read back the new value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_INTEGER, &temp2);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ if (temp2->integer.value != value_to_write) {
+ acpi_os_printf(" MISMATCH 2: %8.8X%8.8X, expecting %8.8X%8.8X",
+ ACPI_FORMAT_UINT64(temp2->integer.value),
+ ACPI_FORMAT_UINT64(value_to_write));
+ }
+
+ /* Write back the original value */
+
+ write_value.integer.value = temp1->integer.value;
+ status = acpi_db_write_to_object(node, &write_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Ensure that we can read back the original value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_INTEGER, &temp3);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ if (temp3->integer.value != temp1->integer.value) {
+ acpi_os_printf(" MISMATCH 3: %8.8X%8.8X, expecting %8.8X%8.8X",
+ ACPI_FORMAT_UINT64(temp3->integer.value),
+ ACPI_FORMAT_UINT64(temp1->integer.value));
+ }
+
+exit:
+ if (temp1) {
+ acpi_os_free(temp1);
+ }
+ if (temp2) {
+ acpi_os_free(temp2);
+ }
+ if (temp3) {
+ acpi_os_free(temp3);
+ }
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_test_buffer_type
+ *
+ * PARAMETERS: node - Parent NS node for the object
+ * bit_length - Actual length of the object.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Test read/write for an Buffer-valued object. Performs a
+ * write/read/compare of an arbitrary new value, then performs
+ * a write/read/compare of the original value.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_test_buffer_type(struct acpi_namespace_node *node, u32 bit_length)
+{
+ union acpi_object *temp1 = NULL;
+ union acpi_object *temp2 = NULL;
+ union acpi_object *temp3 = NULL;
+ u8 *buffer;
+ union acpi_object write_value;
+ acpi_status status;
+ u32 byte_length;
+ u32 i;
+ u8 extra_bits;
+
+ byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length);
+ if (byte_length == 0) {
+ acpi_os_printf(" Ignoring zero length buffer");
+ return (AE_OK);
+ }
+
+ /* Allocate a local buffer */
+
+ buffer = ACPI_ALLOCATE_ZEROED(byte_length);
+ if (!buffer) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Read the original value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_BUFFER, &temp1);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* 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(" %2.2X", temp1->buffer.pointer[i]);
+ }
+ acpi_os_printf("... ");
+
+ /*
+ * Write a new value.
+ *
+ * Handle possible extra bits at the end of the buffer. Can
+ * happen for field_units larger than an integer, but the bit
+ * count is not an integral number of bytes. Zero out the
+ * unused bits.
+ */
+ memset(buffer, BUFFER_FILL_VALUE, byte_length);
+ extra_bits = bit_length % 8;
+ if (extra_bits) {
+ buffer[byte_length - 1] = ACPI_MASK_BITS_ABOVE(extra_bits);
+ }
+
+ write_value.type = ACPI_TYPE_BUFFER;
+ write_value.buffer.length = byte_length;
+ write_value.buffer.pointer = buffer;
+
+ status = acpi_db_write_to_object(node, &write_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Ensure that we can read back the new value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_BUFFER, &temp2);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ if (memcmp(temp2->buffer.pointer, buffer, byte_length)) {
+ acpi_os_printf(" MISMATCH 2: New buffer value");
+ }
+
+ /* Write back the original value */
+
+ write_value.buffer.length = byte_length;
+ write_value.buffer.pointer = temp1->buffer.pointer;
+
+ status = acpi_db_write_to_object(node, &write_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Ensure that we can read back the original value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_BUFFER, &temp3);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ if (memcmp(temp1->buffer.pointer, temp3->buffer.pointer, byte_length)) {
+ acpi_os_printf(" MISMATCH 3: While restoring original buffer");
+ }
+
+exit:
+ ACPI_FREE(buffer);
+ if (temp1) {
+ acpi_os_free(temp1);
+ }
+ if (temp2) {
+ acpi_os_free(temp2);
+ }
+ if (temp3) {
+ acpi_os_free(temp3);
+ }
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_test_string_type
+ *
+ * PARAMETERS: node - Parent NS node for the object
+ * byte_length - Actual length of the object.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Test read/write for an String-valued object. Performs a
+ * write/read/compare of an arbitrary new value, then performs
+ * a write/read/compare of the original value.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length)
+{
+ union acpi_object *temp1 = NULL;
+ union acpi_object *temp2 = NULL;
+ union acpi_object *temp3 = NULL;
+ char *value_to_write = "Test String from AML Debugger";
+ union acpi_object write_value;
+ acpi_status status;
+
+ /* Read the original value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_STRING, &temp1);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ acpi_os_printf(" (%4.4X/%3.3X) \"%s\"", (temp1->string.length * 8),
+ temp1->string.length, temp1->string.pointer);
+
+ /* Write a new value */
+
+ write_value.type = ACPI_TYPE_STRING;
+ write_value.string.length = strlen(value_to_write);
+ write_value.string.pointer = value_to_write;
+
+ status = acpi_db_write_to_object(node, &write_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Ensure that we can read back the new value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_STRING, &temp2);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ if (strcmp(temp2->string.pointer, value_to_write)) {
+ acpi_os_printf(" MISMATCH 2: %s, expecting %s",
+ temp2->string.pointer, value_to_write);
+ }
+
+ /* Write back the original value */
+
+ write_value.string.length = strlen(temp1->string.pointer);
+ write_value.string.pointer = temp1->string.pointer;
+
+ status = acpi_db_write_to_object(node, &write_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Ensure that we can read back the original value */
+
+ status = acpi_db_read_from_object(node, ACPI_TYPE_STRING, &temp3);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ if (strcmp(temp1->string.pointer, temp3->string.pointer)) {
+ acpi_os_printf(" MISMATCH 3: %s, expecting %s",
+ temp3->string.pointer, temp1->string.pointer);
+ }
+
+exit:
+ if (temp1) {
+ acpi_os_free(temp1);
+ }
+ if (temp2) {
+ acpi_os_free(temp2);
+ }
+ if (temp3) {
+ acpi_os_free(temp3);
+ }
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_read_from_object
+ *
+ * PARAMETERS: node - Parent NS node for the object
+ * expected_type - Object type expected from the read
+ * value - Where the value read is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Performs a read from the specified object by invoking the
+ * special debugger control method that reads the object. Thus,
+ * the AML interpreter is doing all of the work, increasing the
+ * validity of the test.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_read_from_object(struct acpi_namespace_node *node,
+ acpi_object_type expected_type,
+ union acpi_object **value)
+{
+ union acpi_object *ret_value;
+ struct acpi_object_list param_objects;
+ union acpi_object params[2];
+ struct acpi_buffer return_obj;
+ acpi_status status;
+
+ params[0].type = ACPI_TYPE_LOCAL_REFERENCE;
+ params[0].reference.actual_type = node->type;
+ params[0].reference.handle = ACPI_CAST_PTR(acpi_handle, node);
+
+ param_objects.count = 1;
+ param_objects.pointer = params;
+
+ return_obj.length = ACPI_ALLOCATE_BUFFER;
+
+ acpi_gbl_method_executing = TRUE;
+ status = acpi_evaluate_object(read_handle, NULL,
+ &param_objects, &return_obj);
+ acpi_gbl_method_executing = FALSE;
+
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not read from object, %s",
+ acpi_format_exception(status));
+ return (status);
+ }
+
+ ret_value = (union acpi_object *)return_obj.pointer;
+
+ switch (ret_value->type) {
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_BUFFER:
+ case ACPI_TYPE_STRING:
+ /*
+ * Did we receive the type we wanted? Most important for the
+ * Integer/Buffer case (when a field is larger than an Integer,
+ * it should return a Buffer).
+ */
+ if (ret_value->type != expected_type) {
+ acpi_os_printf
+ (" Type mismatch: Expected %s, Received %s",
+ acpi_ut_get_type_name(expected_type),
+ acpi_ut_get_type_name(ret_value->type));
+
+ return (AE_TYPE);
+ }
+
+ *value = ret_value;
+ break;
+
+ default:
+
+ acpi_os_printf(" Unsupported return object type, %s",
+ acpi_ut_get_type_name(ret_value->type));
+
+ acpi_os_free(return_obj.pointer);
+ return (AE_TYPE);
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_write_to_object
+ *
+ * PARAMETERS: node - Parent NS node for the object
+ * value - Value to be written
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Performs a write to the specified object by invoking the
+ * special debugger control method that writes the object. Thus,
+ * the AML interpreter is doing all of the work, increasing the
+ * validity of the test.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_write_to_object(struct acpi_namespace_node *node,
+ union acpi_object *value)
+{
+ struct acpi_object_list param_objects;
+ union acpi_object params[2];
+ acpi_status status;
+
+ params[0].type = ACPI_TYPE_LOCAL_REFERENCE;
+ params[0].reference.actual_type = node->type;
+ params[0].reference.handle = ACPI_CAST_PTR(acpi_handle, node);
+
+ /* Copy the incoming user parameter */
+
+ memcpy(&params[1], value, sizeof(union acpi_object));
+
+ param_objects.count = 2;
+ param_objects.pointer = params;
+
+ acpi_gbl_method_executing = TRUE;
+ status = acpi_evaluate_object(write_handle, NULL, &param_objects, NULL);
+ acpi_gbl_method_executing = FALSE;
+
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not write to object, %s",
+ acpi_format_exception(status));
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_evaluate_all_predefined_names
+ *
+ * PARAMETERS: count_arg - Max number of methods to execute
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Namespace batch execution. Execute predefined names in the
+ * namespace, up to the max count, if specified.
+ *
+ ******************************************************************************/
+
+static void acpi_db_evaluate_all_predefined_names(char *count_arg)
+{
+ struct acpi_db_execute_walk info;
+
+ info.count = 0;
+ info.max_count = ACPI_UINT32_MAX;
+
+ if (count_arg) {
+ info.max_count = strtoul(count_arg, NULL, 0);
+ }
+
+ /* Search all nodes in namespace */
+
+ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_db_evaluate_one_predefined_name, NULL,
+ (void *)&info, NULL);
+
+ acpi_os_printf("Evaluated %u predefined names in the namespace\n",
+ info.count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_evaluate_one_predefined_name
+ *
+ * PARAMETERS: Callback from walk_namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Batch execution module. Currently only executes predefined
+ * ACPI names.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ struct acpi_db_execute_walk *info =
+ (struct acpi_db_execute_walk *)context;
+ char *pathname;
+ const union acpi_predefined_info *predefined;
+ struct acpi_device_info *obj_info;
+ struct acpi_object_list param_objects;
+ union acpi_object params[ACPI_METHOD_NUM_ARGS];
+ union acpi_object *this_param;
+ struct acpi_buffer return_obj;
+ acpi_status status;
+ u16 arg_type_list;
+ u8 arg_count;
+ u8 arg_type;
+ u32 i;
+
+ /* The name must be a predefined ACPI name */
+
+ predefined = acpi_ut_match_predefined_method(node->name.ascii);
+ if (!predefined) {
+ return (AE_OK);
+ }
+
+ if (node->type == ACPI_TYPE_LOCAL_SCOPE) {
+ return (AE_OK);
+ }
+
+ pathname = acpi_ns_get_external_pathname(node);
+ if (!pathname) {
+ return (AE_OK);
+ }
+
+ /* Get the object info for number of method parameters */
+
+ status = acpi_get_object_info(obj_handle, &obj_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(pathname);
+ return (status);
+ }
+
+ param_objects.count = 0;
+ param_objects.pointer = NULL;
+
+ if (obj_info->type == ACPI_TYPE_METHOD) {
+
+ /* Setup default parameters (with proper types) */
+
+ arg_type_list = predefined->info.argument_list;
+ arg_count = METHOD_GET_ARG_COUNT(arg_type_list);
+
+ /*
+ * Setup the ACPI-required number of arguments, regardless of what
+ * the actual method defines. If there is a difference, then the
+ * method is wrong and a warning will be issued during execution.
+ */
+ this_param = params;
+ for (i = 0; i < arg_count; i++) {
+ arg_type = METHOD_GET_NEXT_TYPE(arg_type_list);
+ this_param->type = arg_type;
+
+ switch (arg_type) {
+ case ACPI_TYPE_INTEGER:
+
+ this_param->integer.value = 1;
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ this_param->string.pointer =
+ "This is the default argument string";
+ this_param->string.length =
+ strlen(this_param->string.pointer);
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ this_param->buffer.pointer = (u8 *)params; /* just a garbage buffer */
+ this_param->buffer.length = 48;
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ this_param->package.elements = NULL;
+ this_param->package.count = 0;
+ break;
+
+ default:
+
+ acpi_os_printf
+ ("%s: Unsupported argument type: %u\n",
+ pathname, arg_type);
+ break;
+ }
+
+ this_param++;
+ }
+
+ param_objects.count = arg_count;
+ param_objects.pointer = params;
+ }
+
+ ACPI_FREE(obj_info);
+ return_obj.pointer = NULL;
+ return_obj.length = ACPI_ALLOCATE_BUFFER;
+
+ /* Do the actual method execution */
+
+ acpi_gbl_method_executing = TRUE;
+
+ status = acpi_evaluate_object(node, NULL, &param_objects, &return_obj);
+
+ acpi_os_printf("%-32s returned %s\n",
+ pathname, acpi_format_exception(status));
+ acpi_gbl_method_executing = FALSE;
+ ACPI_FREE(pathname);
+
+ /* Ignore status from method execution */
+
+ status = AE_OK;
+
+ /* Update count, check if we have executed enough methods */
+
+ info->count++;
+ if (info->count >= info->max_count) {
+ status = AE_CTRL_TERMINATE;
+ }
+
+ return (status);
+}
diff --git a/drivers/acpi/acpica/dbutils.c b/drivers/acpi/acpica/dbutils.c
new file mode 100644
index 000000000000..86790e080139
--- /dev/null
+++ b/drivers/acpi/acpica/dbutils.c
@@ -0,0 +1,457 @@
+/*******************************************************************************
+ *
+ * Module Name: dbutils - AML debugger utilities
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbutils")
+
+/* Local prototypes */
+#ifdef ACPI_OBSOLETE_FUNCTIONS
+acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root);
+
+void acpi_db_dump_buffer(u32 address);
+#endif
+
+static char *gbl_hex_to_ascii = "0123456789ABCDEF";
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_match_argument
+ *
+ * PARAMETERS: user_argument - User command line
+ * arguments - Array of commands to match against
+ *
+ * RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found
+ *
+ * DESCRIPTION: Search command array for a command match
+ *
+ ******************************************************************************/
+
+acpi_object_type
+acpi_db_match_argument(char *user_argument,
+ struct acpi_db_argument_info *arguments)
+{
+ u32 i;
+
+ if (!user_argument || user_argument[0] == 0) {
+ return (ACPI_TYPE_NOT_FOUND);
+ }
+
+ for (i = 0; arguments[i].name; i++) {
+ if (strstr(arguments[i].name, user_argument) ==
+ arguments[i].name) {
+ return (i);
+ }
+ }
+
+ /* Argument not recognized */
+
+ return (ACPI_TYPE_NOT_FOUND);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_set_output_destination
+ *
+ * PARAMETERS: output_flags - Current flags word
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set the current destination for debugger output. Also sets
+ * the debug output level accordingly.
+ *
+ ******************************************************************************/
+
+void acpi_db_set_output_destination(u32 output_flags)
+{
+
+ acpi_gbl_db_output_flags = (u8)output_flags;
+
+ if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) &&
+ acpi_gbl_db_output_to_file) {
+ acpi_dbg_level = acpi_gbl_db_debug_level;
+ } else {
+ acpi_dbg_level = acpi_gbl_db_console_debug_level;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_external_object
+ *
+ * PARAMETERS: obj_desc - External ACPI object to dump
+ * level - Nesting level.
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the contents of an ACPI external object
+ *
+ ******************************************************************************/
+
+void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level)
+{
+ u32 i;
+
+ if (!obj_desc) {
+ acpi_os_printf("[Null Object]\n");
+ return;
+ }
+
+ for (i = 0; i < level; i++) {
+ acpi_os_printf(" ");
+ }
+
+ switch (obj_desc->type) {
+ case ACPI_TYPE_ANY:
+
+ acpi_os_printf("[Null Object] (Type=0)\n");
+ break;
+
+ case ACPI_TYPE_INTEGER:
+
+ acpi_os_printf("[Integer] = %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ acpi_os_printf("[String] Length %.2X = ",
+ obj_desc->string.length);
+ acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
+ acpi_os_printf("\n");
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ acpi_os_printf("[Buffer] Length %.2X = ",
+ obj_desc->buffer.length);
+ if (obj_desc->buffer.length) {
+ if (obj_desc->buffer.length > 16) {
+ acpi_os_printf("\n");
+ }
+ acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
+ (u8,
+ obj_desc->buffer.pointer),
+ obj_desc->buffer.length,
+ DB_BYTE_DISPLAY, _COMPONENT);
+ } else {
+ acpi_os_printf("\n");
+ }
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ acpi_os_printf("[Package] Contains %u Elements:\n",
+ obj_desc->package.count);
+
+ for (i = 0; i < obj_desc->package.count; i++) {
+ acpi_db_dump_external_object(&obj_desc->package.
+ elements[i], level + 1);
+ }
+ break;
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ acpi_os_printf("[Object Reference] = ");
+ acpi_db_display_internal_object(obj_desc->reference.handle,
+ NULL);
+ break;
+
+ case ACPI_TYPE_PROCESSOR:
+
+ acpi_os_printf("[Processor]\n");
+ break;
+
+ case ACPI_TYPE_POWER:
+
+ acpi_os_printf("[Power Resource]\n");
+ break;
+
+ default:
+
+ acpi_os_printf("[Unknown Type] %X\n", obj_desc->type);
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_prep_namestring
+ *
+ * PARAMETERS: name - String to prepare
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Translate all forward slashes and dots to backslashes.
+ *
+ ******************************************************************************/
+
+void acpi_db_prep_namestring(char *name)
+{
+
+ if (!name) {
+ return;
+ }
+
+ acpi_ut_strupr(name);
+
+ /* Convert a leading forward slash to a backslash */
+
+ if (*name == '/') {
+ *name = '\\';
+ }
+
+ /* Ignore a leading backslash, this is the root prefix */
+
+ if (ACPI_IS_ROOT_PREFIX(*name)) {
+ name++;
+ }
+
+ /* Convert all slash path separators to dots */
+
+ while (*name) {
+ if ((*name == '/') || (*name == '\\')) {
+ *name = '.';
+ }
+
+ name++;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_local_ns_lookup
+ *
+ * PARAMETERS: name - Name to lookup
+ *
+ * RETURN: Pointer to a namespace node, null on failure
+ *
+ * DESCRIPTION: Lookup a name in the ACPI namespace
+ *
+ * Note: Currently begins search from the root. Could be enhanced to use
+ * the current prefix (scope) node as the search beginning point.
+ *
+ ******************************************************************************/
+
+struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name)
+{
+ char *internal_path;
+ acpi_status status;
+ struct acpi_namespace_node *node = NULL;
+
+ acpi_db_prep_namestring(name);
+
+ /* Build an internal namestring */
+
+ status = acpi_ns_internalize_name(name, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Invalid namestring: %s\n", name);
+ return (NULL);
+ }
+
+ /*
+ * Lookup the name.
+ * (Uses root node as the search starting point)
+ */
+ status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
+ NULL, &node);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not locate name: %s, %s\n",
+ name, acpi_format_exception(status));
+ }
+
+ ACPI_FREE(internal_path);
+ return (node);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_uint32_to_hex_string
+ *
+ * PARAMETERS: value - The value to be converted to string
+ * buffer - Buffer for result (not less than 11 bytes)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
+ *
+ * NOTE: It is the caller's responsibility to ensure that the length of buffer
+ * is sufficient.
+ *
+ ******************************************************************************/
+
+void acpi_db_uint32_to_hex_string(u32 value, char *buffer)
+{
+ int i;
+
+ if (value == 0) {
+ strcpy(buffer, "0");
+ return;
+ }
+
+ buffer[8] = '\0';
+
+ for (i = 7; i >= 0; i--) {
+ buffer[i] = gbl_hex_to_ascii[value & 0x0F];
+ value = value >> 4;
+ }
+}
+
+#ifdef ACPI_OBSOLETE_FUNCTIONS
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_second_pass_parse
+ *
+ * PARAMETERS: root - Root of the parse tree
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until
+ * second pass to parse the control methods
+ *
+ ******************************************************************************/
+
+acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root)
+{
+ union acpi_parse_object *op = root;
+ union acpi_parse_object *method;
+ union acpi_parse_object *search_op;
+ union acpi_parse_object *start_op;
+ acpi_status status = AE_OK;
+ u32 base_aml_offset;
+ struct acpi_walk_state *walk_state;
+
+ ACPI_FUNCTION_ENTRY();
+
+ acpi_os_printf("Pass two parse ....\n");
+
+ while (op) {
+ if (op->common.aml_opcode == AML_METHOD_OP) {
+ method = op;
+
+ /* Create a new walk state for the parse */
+
+ walk_state =
+ acpi_ds_create_walk_state(0, NULL, NULL, NULL);
+ if (!walk_state) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Init the Walk State */
+
+ walk_state->parser_state.aml =
+ walk_state->parser_state.aml_start =
+ method->named.data;
+ walk_state->parser_state.aml_end =
+ walk_state->parser_state.pkg_end =
+ method->named.data + method->named.length;
+ walk_state->parser_state.start_scope = op;
+
+ walk_state->descending_callback =
+ acpi_ds_load1_begin_op;
+ walk_state->ascending_callback = acpi_ds_load1_end_op;
+
+ /* Perform the AML parse */
+
+ status = acpi_ps_parse_aml(walk_state);
+
+ base_aml_offset =
+ (method->common.value.arg)->common.aml_offset + 1;
+ start_op = (method->common.value.arg)->common.next;
+ search_op = start_op;
+
+ while (search_op) {
+ search_op->common.aml_offset += base_aml_offset;
+ search_op =
+ acpi_ps_get_depth_next(start_op, search_op);
+ }
+ }
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+
+ /* TBD: [Investigate] this isn't quite the right thing to do! */
+ /*
+ *
+ * Method = (ACPI_DEFERRED_OP *) Op;
+ * Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length);
+ */
+ }
+
+ if (ACPI_FAILURE(status)) {
+ break;
+ }
+
+ op = acpi_ps_get_depth_next(root, op);
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_dump_buffer
+ *
+ * PARAMETERS: address - Pointer to the buffer
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Print a portion of a buffer
+ *
+ ******************************************************************************/
+
+void acpi_db_dump_buffer(u32 address)
+{
+
+ acpi_os_printf("\nLocation %X:\n", address);
+
+ acpi_dbg_level |= ACPI_LV_TABLES;
+ acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY,
+ ACPI_UINT32_MAX);
+}
+#endif
diff --git a/drivers/acpi/acpica/dbxface.c b/drivers/acpi/acpica/dbxface.c
new file mode 100644
index 000000000000..342298a6e10f
--- /dev/null
+++ b/drivers/acpi/acpica/dbxface.c
@@ -0,0 +1,513 @@
+/*******************************************************************************
+ *
+ * Module Name: dbxface - AML Debugger external interfaces
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acdebug.h"
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("dbxface")
+
+/* Local prototypes */
+static acpi_status
+acpi_db_start_command(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
+
+#ifdef ACPI_OBSOLETE_FUNCTIONS
+void acpi_db_method_end(struct acpi_walk_state *walk_state);
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_start_command
+ *
+ * PARAMETERS: walk_state - Current walk
+ * op - Current executing Op, from AML interpreter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enter debugger command loop
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_start_command(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
+{
+ acpi_status status;
+
+ /* TBD: [Investigate] are there namespace locking issues here? */
+
+ /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
+
+ /* Go into the command loop and await next user command */
+
+ acpi_gbl_method_executing = TRUE;
+ status = AE_CTRL_TRUE;
+ while (status == AE_CTRL_TRUE) {
+ if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) {
+
+ /* Handshake with the front-end that gets user command lines */
+
+ acpi_os_release_mutex(acpi_gbl_db_command_complete);
+
+ status =
+ acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
+ ACPI_WAIT_FOREVER);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ } else {
+ /* Single threaded, we must get a command line ourselves */
+
+ /* Force output to console until a command is entered */
+
+ acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+
+ /* Different prompt if method is executing */
+
+ if (!acpi_gbl_method_executing) {
+ acpi_os_printf("%1c ",
+ ACPI_DEBUGGER_COMMAND_PROMPT);
+ } else {
+ acpi_os_printf("%1c ",
+ ACPI_DEBUGGER_EXECUTE_PROMPT);
+ }
+
+ /* Get the user input line */
+
+ status = acpi_os_get_line(acpi_gbl_db_line_buf,
+ ACPI_DB_LINE_BUFFER_SIZE,
+ NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While parsing command line"));
+ return (status);
+ }
+ }
+
+ status =
+ acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
+ op);
+ }
+
+ /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_single_step
+ *
+ * PARAMETERS: walk_state - Current walk
+ * op - Current executing op (from aml interpreter)
+ * opcode_class - Class of the current AML Opcode
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Called just before execution of an AML opcode.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_db_single_step(struct acpi_walk_state * walk_state,
+ union acpi_parse_object * op, u32 opcode_class)
+{
+ union acpi_parse_object *next;
+ acpi_status status = AE_OK;
+ u32 original_debug_level;
+ union acpi_parse_object *display_op;
+ union acpi_parse_object *parent_op;
+ u32 aml_offset;
+
+ ACPI_FUNCTION_ENTRY();
+
+#ifndef ACPI_APPLICATION
+ if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+ return (AE_OK);
+ }
+#endif
+
+ /* Check the abort flag */
+
+ if (acpi_gbl_abort_method) {
+ acpi_gbl_abort_method = FALSE;
+ return (AE_ABORT_METHOD);
+ }
+
+ aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
+ walk_state->parser_state.aml_start);
+
+ /* Check for single-step breakpoint */
+
+ if (walk_state->method_breakpoint &&
+ (walk_state->method_breakpoint <= aml_offset)) {
+
+ /* Check if the breakpoint has been reached or passed */
+ /* Hit the breakpoint, resume single step, reset breakpoint */
+
+ acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
+ acpi_gbl_cm_single_step = TRUE;
+ acpi_gbl_step_to_next_call = FALSE;
+ walk_state->method_breakpoint = 0;
+ }
+
+ /* Check for user breakpoint (Must be on exact Aml offset) */
+
+ else if (walk_state->user_breakpoint &&
+ (walk_state->user_breakpoint == aml_offset)) {
+ acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
+ aml_offset);
+ acpi_gbl_cm_single_step = TRUE;
+ acpi_gbl_step_to_next_call = FALSE;
+ walk_state->method_breakpoint = 0;
+ }
+
+ /*
+ * Check if this is an opcode that we are interested in --
+ * namely, opcodes that have arguments
+ */
+ if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
+ return (AE_OK);
+ }
+
+ switch (opcode_class) {
+ case AML_CLASS_UNKNOWN:
+ case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */
+
+ return (AE_OK);
+
+ default:
+
+ /* All other opcodes -- continue */
+ break;
+ }
+
+ /*
+ * Under certain debug conditions, display this opcode and its operands
+ */
+ if ((acpi_gbl_db_output_to_file) ||
+ (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
+ if ((acpi_gbl_db_output_to_file) ||
+ (acpi_dbg_level & ACPI_LV_PARSE)) {
+ acpi_os_printf
+ ("\n[AmlDebug] Next AML Opcode to execute:\n");
+ }
+
+ /*
+ * Display this op (and only this op - zero out the NEXT field
+ * temporarily, and disable parser trace output for the duration of
+ * the display because we don't want the extraneous debug output)
+ */
+ original_debug_level = acpi_dbg_level;
+ acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
+ next = op->common.next;
+ op->common.next = NULL;
+
+ display_op = op;
+ parent_op = op->common.parent;
+ if (parent_op) {
+ if ((walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING)) {
+ /*
+ * We are executing the predicate of an IF or WHILE statement
+ * Search upwards for the containing IF or WHILE so that the
+ * entire predicate can be displayed.
+ */
+ while (parent_op) {
+ if ((parent_op->common.aml_opcode ==
+ AML_IF_OP)
+ || (parent_op->common.aml_opcode ==
+ AML_WHILE_OP)) {
+ display_op = parent_op;
+ break;
+ }
+ parent_op = parent_op->common.parent;
+ }
+ } else {
+ while (parent_op) {
+ if ((parent_op->common.aml_opcode ==
+ AML_IF_OP)
+ || (parent_op->common.aml_opcode ==
+ AML_ELSE_OP)
+ || (parent_op->common.aml_opcode ==
+ AML_SCOPE_OP)
+ || (parent_op->common.aml_opcode ==
+ AML_METHOD_OP)
+ || (parent_op->common.aml_opcode ==
+ AML_WHILE_OP)) {
+ break;
+ }
+ display_op = parent_op;
+ parent_op = parent_op->common.parent;
+ }
+ }
+ }
+
+ /* Now we can display it */
+
+#ifdef ACPI_DISASSEMBLER
+ acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX);
+#endif
+
+ if ((op->common.aml_opcode == AML_IF_OP) ||
+ (op->common.aml_opcode == AML_WHILE_OP)) {
+ if (walk_state->control_state->common.value) {
+ acpi_os_printf
+ ("Predicate = [True], IF block was executed\n");
+ } else {
+ acpi_os_printf
+ ("Predicate = [False], Skipping IF block\n");
+ }
+ } else if (op->common.aml_opcode == AML_ELSE_OP) {
+ acpi_os_printf
+ ("Predicate = [False], ELSE block was executed\n");
+ }
+
+ /* Restore everything */
+
+ op->common.next = next;
+ acpi_os_printf("\n");
+ if ((acpi_gbl_db_output_to_file) ||
+ (acpi_dbg_level & ACPI_LV_PARSE)) {
+ acpi_os_printf("\n");
+ }
+ acpi_dbg_level = original_debug_level;
+ }
+
+ /* If we are not single stepping, just continue executing the method */
+
+ if (!acpi_gbl_cm_single_step) {
+ return (AE_OK);
+ }
+
+ /*
+ * If we are executing a step-to-call command,
+ * Check if this is a method call.
+ */
+ if (acpi_gbl_step_to_next_call) {
+ if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
+
+ /* Not a method call, just keep executing */
+
+ return (AE_OK);
+ }
+
+ /* Found a method call, stop executing */
+
+ acpi_gbl_step_to_next_call = FALSE;
+ }
+
+ /*
+ * If the next opcode is a method call, we will "step over" it
+ * by default.
+ */
+ if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
+
+ /* Force no more single stepping while executing called method */
+
+ acpi_gbl_cm_single_step = FALSE;
+
+ /*
+ * Set the breakpoint on/before the call, it will stop execution
+ * as soon as we return
+ */
+ walk_state->method_breakpoint = 1; /* Must be non-zero! */
+ }
+
+ status = acpi_db_start_command(walk_state, op);
+
+ /* User commands complete, continue execution of the interrupted method */
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_initialize_debugger
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Init and start debugger
+ *
+ ******************************************************************************/
+
+acpi_status acpi_initialize_debugger(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
+
+ /* Init globals */
+
+ acpi_gbl_db_buffer = NULL;
+ acpi_gbl_db_filename = NULL;
+ acpi_gbl_db_output_to_file = FALSE;
+
+ acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
+ acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
+ acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
+
+ acpi_gbl_db_opt_no_ini_methods = FALSE;
+
+ acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
+ if (!acpi_gbl_db_buffer) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+ memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
+
+ /* Initial scope is the root */
+
+ acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
+ acpi_gbl_db_scope_buf[1] = 0;
+ acpi_gbl_db_scope_node = acpi_gbl_root_node;
+
+ /* Initialize user commands loop */
+
+ acpi_gbl_db_terminate_loop = FALSE;
+
+ /*
+ * If configured for multi-thread support, the debug executor runs in
+ * a separate thread so that the front end can be in another address
+ * space, environment, or even another machine.
+ */
+ if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
+
+ /* These were created with one unit, grab it */
+
+ status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
+ ACPI_WAIT_FOREVER);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not get debugger mutex\n");
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
+ ACPI_WAIT_FOREVER);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not get debugger mutex\n");
+ return_ACPI_STATUS(status);
+ }
+
+ /* Create the debug execution thread to execute commands */
+
+ acpi_gbl_db_threads_terminated = FALSE;
+ status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
+ acpi_db_execute_thread, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not start debugger thread"));
+ acpi_gbl_db_threads_terminated = TRUE;
+ return_ACPI_STATUS(status);
+ }
+ } else {
+ acpi_gbl_db_thread_id = acpi_os_get_thread_id();
+ }
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_terminate_debugger
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Stop debugger
+ *
+ ******************************************************************************/
+void acpi_terminate_debugger(void)
+{
+
+ /* Terminate the AML Debugger */
+
+ acpi_gbl_db_terminate_loop = TRUE;
+
+ if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
+ acpi_os_release_mutex(acpi_gbl_db_command_ready);
+
+ /* Wait the AML Debugger threads */
+
+ while (!acpi_gbl_db_threads_terminated) {
+ acpi_os_sleep(100);
+ }
+ }
+
+ if (acpi_gbl_db_buffer) {
+ acpi_os_free(acpi_gbl_db_buffer);
+ acpi_gbl_db_buffer = NULL;
+ }
+
+ /* Ensure that debug output is now disabled */
+
+ acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_set_debugger_thread_id
+ *
+ * PARAMETERS: thread_id - Debugger thread ID
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set debugger thread ID
+ *
+ ******************************************************************************/
+void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
+{
+ acpi_gbl_db_thread_id = thread_id;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 81f2d9e87fad..07d22bfbaa00 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -405,7 +405,7 @@ cleanup:
}
ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
-#endif /* ACPI_FUTURE_USAGE */
+#endif
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index faad911d46b5..10ce48e16ebf 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -71,7 +71,7 @@ acpi_status acpi_enable(void)
/* ACPI tables must be present */
- if (!acpi_tb_tables_loaded()) {
+ if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index 075d654c837f..1e4c5b6dc0b0 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -618,6 +618,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
break;
case ARGI_TARGETREF:
+ case ARGI_STORE_TARGET:
switch (destination_type) {
case ACPI_TYPE_INTEGER:
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index 7b109128b035..a1afe1a1e7c2 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -209,7 +209,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
* (i.e., dereference the package index)
* Delete the ref object, increment the returned object
*/
- acpi_ut_remove_reference(stack_desc);
acpi_ut_add_reference(obj_desc);
*stack_ptr = obj_desc;
} else {
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c
index d2964af9ad4d..424442d50b5e 100644
--- a/drivers/acpi/acpica/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -307,6 +307,8 @@ acpi_ex_resolve_operands(u16 opcode,
case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
case ARGI_SIMPLE_TARGET: /* Name, Local, or arg - no implicit conversion */
+ case ARGI_STORE_TARGET:
+
/*
* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE
* A Namespace Node is OK as-is
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c
index a7eee2400ce0..c076e9100d66 100644
--- a/drivers/acpi/acpica/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -137,7 +137,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
/* Destination is not a Reference object */
ACPI_ERROR((AE_INFO,
- "Target is not a Reference or Constant object - %s [%p]",
+ "Target is not a Reference or Constant object - [%s] %p",
acpi_ut_get_object_type_name(dest_desc),
dest_desc));
@@ -189,7 +189,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
* displayed and otherwise has no effect -- see ACPI Specification
*/
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "**** Write to Debug Object: Object %p %s ****:\n\n",
+ "**** Write to Debug Object: Object %p [%s] ****:\n\n",
source_desc,
acpi_ut_get_object_type_name(source_desc)));
@@ -341,7 +341,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
/* All other types are invalid */
ACPI_ERROR((AE_INFO,
- "Source must be Integer/Buffer/String type, not %s",
+ "Source must be type [Integer/Buffer/String], found [%s]",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -352,8 +352,9 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
break;
default:
- ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField"));
- status = AE_AML_OPERAND_TYPE;
+ ACPI_ERROR((AE_INFO,
+ "Target is not of type [Package/BufferField]"));
+ status = AE_AML_TARGET_TYPE;
break;
}
@@ -373,20 +374,20 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
*
* DESCRIPTION: Store the object to the named object.
*
- * The Assignment of an object to a named object is handled here
- * The value passed in will replace the current value (if any)
- * with the input value.
+ * The assignment of an object to a named object is handled here.
+ * The value passed in will replace the current value (if any)
+ * with the input value.
*
- * When storing into an object the data is converted to the
- * target object type then stored in the object. This means
- * that the target object type (for an initialized target) will
- * not be changed by a store operation. A copy_object can change
- * the target type, however.
+ * When storing into an object the data is converted to the
+ * target object type then stored in the object. This means
+ * that the target object type (for an initialized target) will
+ * not be changed by a store operation. A copy_object can change
+ * the target type, however.
*
- * The implicit_conversion flag is set to NO/FALSE only when
- * storing to an arg_x -- as per the rules of the ACPI spec.
+ * The implicit_conversion flag is set to NO/FALSE only when
+ * storing to an arg_x -- as per the rules of the ACPI spec.
*
- * Assumes parameters are already validated.
+ * Assumes parameters are already validated.
*
******************************************************************************/
@@ -408,11 +409,75 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
target_type = acpi_ns_get_type(node);
target_desc = acpi_ns_get_attached_object(node);
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n",
source_desc,
acpi_ut_get_object_type_name(source_desc), node,
acpi_ut_get_type_name(target_type)));
+ /* Only limited target types possible for everything except copy_object */
+
+ if (walk_state->opcode != AML_COPY_OP) {
+ /*
+ * Only copy_object allows all object types to be overwritten. For
+ * target_ref(s), there are restrictions on the object types that
+ * are allowed.
+ *
+ * Allowable operations/typing for Store:
+ *
+ * 1) Simple Store
+ * Integer --> Integer (Named/Local/Arg)
+ * String --> String (Named/Local/Arg)
+ * Buffer --> Buffer (Named/Local/Arg)
+ * Package --> Package (Named/Local/Arg)
+ *
+ * 2) Store with implicit conversion
+ * Integer --> String or Buffer (Named)
+ * String --> Integer or Buffer (Named)
+ * Buffer --> Integer or String (Named)
+ */
+ switch (target_type) {
+ case ACPI_TYPE_PACKAGE:
+ /*
+ * Here, can only store a package to an existing package.
+ * Storing a package to a Local/Arg is OK, and handled
+ * elsewhere.
+ */
+ if (walk_state->opcode == AML_STORE_OP) {
+ if (source_desc->common.type !=
+ ACPI_TYPE_PACKAGE) {
+ ACPI_ERROR((AE_INFO,
+ "Cannot assign type [%s] to [Package] "
+ "(source must be type Pkg)",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+
+ return_ACPI_STATUS(AE_AML_TARGET_TYPE);
+ }
+ break;
+ }
+
+ /* Fallthrough */
+
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_EVENT:
+ case ACPI_TYPE_MUTEX:
+ case ACPI_TYPE_REGION:
+ case ACPI_TYPE_POWER:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_THERMAL:
+
+ ACPI_ERROR((AE_INFO,
+ "Target must be [Buffer/Integer/String/Reference], found [%s] (%4.4s)",
+ acpi_ut_get_type_name(node->type),
+ node->name.ascii));
+
+ return_ACPI_STATUS(AE_AML_TARGET_TYPE);
+
+ default:
+ break;
+ }
+ }
+
/*
* Resolve the source object to an actual value
* (If it is a reference object)
@@ -425,13 +490,13 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
/* Do the actual store operation */
switch (target_type) {
- case ACPI_TYPE_INTEGER:
- case ACPI_TYPE_STRING:
- case ACPI_TYPE_BUFFER:
/*
* The simple data types all support implicit source operand
* conversion before the store.
*/
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) {
/*
@@ -467,7 +532,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
new_desc->common.type);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Store %s into %s via Convert/Attach\n",
+ "Store type [%s] into [%s] via Convert/Attach\n",
acpi_ut_get_object_type_name
(source_desc),
acpi_ut_get_object_type_name
@@ -491,15 +556,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
default:
/*
- * No conversions for all other types. Directly store a copy of
- * the source object. This is the ACPI spec-defined behavior for
- * the copy_object operator.
+ * copy_object operator: No conversions for all other types.
+ * Instead, directly store a copy of the source object.
*
- * NOTE: For the Store operator, this is a departure from the
- * ACPI spec, which states "If conversion is impossible, abort
- * the running control method". Instead, this code implements
- * "If conversion is impossible, treat the Store operation as
- * a CopyObject".
+ * This is the ACPI spec-defined behavior for the copy_object
+ * operator. (Note, for this default case, all normal
+ * Store/Target operations exited above with an error).
*/
status = acpi_ex_store_direct_to_node(source_desc, node,
walk_state);
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c
index 3101607b4efe..d1841defa669 100644
--- a/drivers/acpi/acpica/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -122,9 +122,10 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
/* Conversion successful but still not a valid type */
ACPI_ERROR((AE_INFO,
- "Cannot assign type %s to %s (must be type Int/Str/Buf)",
+ "Cannot assign type [%s] to [%s] (must be type Int/Str/Buf)",
acpi_ut_get_object_type_name(source_desc),
acpi_ut_get_type_name(target_type)));
+
status = AE_AML_OPERAND_TYPE;
}
break;
@@ -275,7 +276,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
/*
* All other types come here.
*/
- ACPI_WARNING((AE_INFO, "Store into type %s not implemented",
+ ACPI_WARNING((AE_INFO, "Store into type [%s] not implemented",
acpi_ut_get_object_type_name(dest_desc)));
status = AE_NOT_IMPLEMENTED;
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 0f1daba640e7..37aa5c45ca4b 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -60,7 +60,6 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-#ifdef ACPI_FUTURE_USAGE
static acpi_status
acpi_ns_dump_one_object_path(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
@@ -68,7 +67,6 @@ acpi_ns_dump_one_object_path(acpi_handle obj_handle,
static acpi_status
acpi_ns_get_max_depth(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
-#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -625,7 +623,6 @@ cleanup:
return (AE_OK);
}
-#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_objects
@@ -680,9 +677,7 @@ acpi_ns_dump_objects(acpi_object_type type,
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}
-#endif /* ACPI_FUTURE_USAGE */
-#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_one_object_path, acpi_ns_get_max_depth
@@ -810,7 +805,6 @@ acpi_ns_dump_object_paths(acpi_object_type type,
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}
-#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 0eb54315b4be..0c20980bbcf3 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -226,7 +226,7 @@ acpi_ns_check_object_type(struct acpi_evaluate_info *info,
{
union acpi_operand_object *return_object = *return_object_ptr;
acpi_status status = AE_OK;
- char type_buffer[48]; /* Room for 5 types */
+ char type_buffer[96]; /* Room for 10 types */
/* A Namespace node should not get here, but make sure */
diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c
index 89984f30addc..cf2f2faf4f92 100644
--- a/drivers/acpi/acpica/pstree.c
+++ b/drivers/acpi/acpica/pstree.c
@@ -183,7 +183,6 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
}
}
-#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_depth_next
@@ -317,4 +316,3 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
return (child);
}
#endif
-#endif /* ACPI_FUTURE_USAGE */
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c
index 183cc1efbc51..71d2877cd2ce 100644
--- a/drivers/acpi/acpica/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -205,7 +205,6 @@ u8 acpi_ps_is_leading_char(u32 c)
/*
* Get op's name (4-byte name segment) or 0 if unnamed
*/
-#ifdef ACPI_FUTURE_USAGE
u32 acpi_ps_get_name(union acpi_parse_object * op)
{
@@ -219,7 +218,6 @@ u32 acpi_ps_get_name(union acpi_parse_object * op)
return (op->named.name);
}
-#endif /* ACPI_FUTURE_USAGE */
/*
* Set op's name
diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c
index c428bb33204e..2a09288e7c57 100644
--- a/drivers/acpi/acpica/rsdump.c
+++ b/drivers/acpi/acpica/rsdump.c
@@ -51,7 +51,6 @@ ACPI_MODULE_NAME("rsdump")
/*
* All functions in this module are used by the AML Debugger only
*/
-#if defined(ACPI_DEBUGGER)
/* Local prototypes */
static void acpi_rs_out_string(char *title, char *value);
@@ -565,5 +564,3 @@ static void acpi_rs_dump_word_list(u16 length, u16 *data)
acpi_os_printf("%25s%2.2X : %4.4X\n", "Word", i, data[i]);
}
}
-
-#endif
diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c
index 52b024df0052..9486992edbb8 100644
--- a/drivers/acpi/acpica/rsutils.c
+++ b/drivers/acpi/acpica/rsutils.c
@@ -564,7 +564,6 @@ acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
*
******************************************************************************/
-#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer)
@@ -596,7 +595,6 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index de51f836ef68..1e8cd5723326 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -220,7 +220,7 @@ acpi_get_current_resources(acpi_handle device_handle,
}
ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
-#ifdef ACPI_FUTURE_USAGE
+
/*******************************************************************************
*
* FUNCTION: acpi_get_possible_resources
@@ -262,7 +262,7 @@ acpi_get_possible_resources(acpi_handle device_handle,
}
ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
-#endif /* ACPI_FUTURE_USAGE */
+
/*******************************************************************************
*
* FUNCTION: acpi_set_current_resources
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 455a0700db39..a6454f4a6fb3 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -298,7 +298,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64)
*
* FUNCTION: acpi_tb_parse_fadt
*
- * PARAMETERS: table_index - Index for the FADT
+ * PARAMETERS: None
*
* RETURN: None
*
@@ -307,7 +307,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64)
*
******************************************************************************/
-void acpi_tb_parse_fadt(u32 table_index)
+void acpi_tb_parse_fadt(void)
{
u32 length;
struct acpi_table_header *table;
@@ -319,11 +319,11 @@ void acpi_tb_parse_fadt(u32 table_index)
* Get a local copy of the FADT and convert it to a common format
* Map entire FADT, assumed to be smaller than one page.
*/
- length = acpi_gbl_root_table_list.tables[table_index].length;
+ length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
table =
- acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index].
- address, length);
+ acpi_os_map_memory(acpi_gbl_root_table_list.
+ tables[acpi_gbl_fadt_index].address, length);
if (!table) {
return;
}
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 4337990127cc..d8ddef38c947 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -99,29 +99,6 @@ acpi_status acpi_tb_initialize_facs(void)
/*******************************************************************************
*
- * FUNCTION: acpi_tb_tables_loaded
- *
- * PARAMETERS: None
- *
- * RETURN: TRUE if required ACPI tables are loaded
- *
- * DESCRIPTION: Determine if the minimum required ACPI tables are present
- * (FADT, FACS, DSDT)
- *
- ******************************************************************************/
-
-u8 acpi_tb_tables_loaded(void)
-{
-
- if (acpi_gbl_root_table_list.current_table_count >= 4) {
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_tb_check_dsdt_header
*
* PARAMETERS: None
@@ -392,7 +369,8 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
tables[table_index].signature,
ACPI_SIG_FADT)) {
- acpi_tb_parse_fadt(table_index);
+ acpi_gbl_fadt_index = table_index;
+ acpi_tb_parse_fadt();
}
next_table:
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
index 988e23b7795c..ecaaaffc0788 100644
--- a/drivers/acpi/acpica/utdecode.c
+++ b/drivers/acpi/acpica/utdecode.c
@@ -232,12 +232,27 @@ char *acpi_ut_get_type_name(acpi_object_type type)
char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
{
+ ACPI_FUNCTION_TRACE(ut_get_object_type_name);
if (!obj_desc) {
- return ("[NULL Object Descriptor]");
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n"));
+ return_PTR("[NULL Object Descriptor]");
}
- return (acpi_ut_get_type_name(obj_desc->common.type));
+ /* These descriptor types share a common area */
+
+ if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) &&
+ (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_NAMED)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Invalid object descriptor type: 0x%2.2X [%s] (%p)\n",
+ ACPI_GET_DESCRIPTOR_TYPE(obj_desc),
+ acpi_ut_get_descriptor_name(obj_desc),
+ obj_desc));
+
+ return_PTR("Invalid object");
+ }
+
+ return_PTR(acpi_ut_get_type_name(obj_desc->common.type));
}
/*******************************************************************************
@@ -407,8 +422,6 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
"ACPI_MTX_Events",
"ACPI_MTX_Caches",
"ACPI_MTX_Memory",
- "ACPI_MTX_CommandComplete",
- "ACPI_MTX_CommandReady"
};
char *acpi_ut_get_mutex_name(u32 mutex_id)
diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c
index 75a94f52b4be..d435b7b7eb94 100644
--- a/drivers/acpi/acpica/utfileio.c
+++ b/drivers/acpi/acpica/utfileio.c
@@ -45,6 +45,7 @@
#include "accommon.h"
#include "actables.h"
#include "acapps.h"
+#include "errno.h"
#ifdef ACPI_ASL_COMPILER
#include "aslcompiler.h"
@@ -301,6 +302,11 @@ acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
file = fopen(filename, "rb");
if (!file) {
perror("Could not open input file");
+
+ if (errno == ENOENT) {
+ return (AE_NOT_EXIST);
+ }
+
return (status);
}
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index 28ab3a1d5ec1..ccd0745f011e 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -241,8 +241,6 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_disable_mem_tracking = FALSE;
#endif
- ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE);
-
return_ACPI_STATUS(AE_OK);
}
@@ -284,6 +282,19 @@ void acpi_ut_subsystem_shutdown(void)
{
ACPI_FUNCTION_TRACE(ut_subsystem_shutdown);
+ /* Just exit if subsystem is already shutdown */
+
+ if (acpi_gbl_shutdown) {
+ ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
+ return_VOID;
+ }
+
+ /* Subsystem appears active, go ahead and shut it down */
+
+ acpi_gbl_shutdown = TRUE;
+ acpi_gbl_startup_flags = 0;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
+
#ifndef ACPI_ASL_COMPILER
/* Close the acpi_event Handling */
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 37b8b58fcd56..ce406e39b669 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -108,6 +108,21 @@ acpi_status acpi_ut_mutex_initialize(void)
/* Create the reader/writer lock for namespace access */
status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+#ifdef ACPI_DEBUGGER
+
+ /* Debugger Support */
+
+ status = acpi_os_create_mutex(&acpi_gbl_db_command_ready);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_os_create_mutex(&acpi_gbl_db_command_complete);
+#endif
+
return_ACPI_STATUS(status);
}
@@ -147,6 +162,12 @@ void acpi_ut_mutex_terminate(void)
/* Delete the reader/writer lock */
acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
+
+#ifdef ACPI_DEBUGGER
+ acpi_os_delete_mutex(acpi_gbl_db_command_ready);
+ acpi_os_delete_mutex(acpi_gbl_db_command_complete);
+#endif
+
return_VOID;
}
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 4f332815db00..f9c8f9ce1f0f 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -67,23 +67,6 @@ acpi_status __init acpi_terminate(void)
ACPI_FUNCTION_TRACE(acpi_terminate);
- /* Just exit if subsystem is already shutdown */
-
- if (acpi_gbl_shutdown) {
- ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
- return_ACPI_STATUS(AE_OK);
- }
-
- /* Subsystem appears active, go ahead and shut it down */
-
- acpi_gbl_shutdown = TRUE;
- acpi_gbl_startup_flags = 0;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
-
- /* Terminate the AML Debugger if present */
-
- ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE);
-
/* Shutdown and free all resources */
acpi_ut_subsystem_shutdown();
@@ -270,7 +253,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
}
ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
-#endif /* ACPI_FUTURE_USAGE */
+#endif
/*****************************************************************************
*
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 23981ac1c6c2..3dd9c462d22a 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -157,11 +157,15 @@ static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
{
- unsigned long vaddr;
+ unsigned long vaddr, paddr;
+ pgprot_t prot;
vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
- ioremap_page_range(vaddr, vaddr + PAGE_SIZE,
- pfn << PAGE_SHIFT, PAGE_KERNEL);
+
+ paddr = pfn << PAGE_SHIFT;
+ prot = arch_apei_get_mem_attribute(paddr);
+
+ ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
return (void __iomem *)vaddr;
}
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
new file mode 100644
index 000000000000..6730f965b379
--- /dev/null
+++ b/drivers/acpi/cppc_acpi.c
@@ -0,0 +1,733 @@
+/*
+ * CPPC (Collaborative Processor Performance Control) methods used by CPUfreq drivers.
+ *
+ * (C) Copyright 2014, 2015 Linaro Ltd.
+ * Author: Ashwin Chaugule <ashwin.chaugule@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * CPPC describes a few methods for controlling CPU performance using
+ * information from a per CPU table called CPC. This table is described in
+ * the ACPI v5.0+ specification. The table consists of a list of
+ * registers which may be memory mapped or hardware registers and also may
+ * include some static integer values.
+ *
+ * CPU performance is on an abstract continuous scale as against a discretized
+ * P-state scale which is tied to CPU frequency only. In brief, the basic
+ * operation involves:
+ *
+ * - OS makes a CPU performance request. (Can provide min and max bounds)
+ *
+ * - Platform (such as BMC) is free to optimize request within requested bounds
+ * depending on power/thermal budgets etc.
+ *
+ * - Platform conveys its decision back to OS
+ *
+ * The communication between OS and platform occurs through another medium
+ * called (PCC) Platform Communication Channel. This is a generic mailbox like
+ * mechanism which includes doorbell semantics to indicate register updates.
+ * See drivers/mailbox/pcc.c for details on PCC.
+ *
+ * Finer details about the PCC and CPPC spec are available in the ACPI v5.1 and
+ * above specifications.
+ */
+
+#define pr_fmt(fmt) "ACPI CPPC: " fmt
+
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+
+#include <acpi/cppc_acpi.h>
+/*
+ * Lock to provide mutually exclusive access to the PCC
+ * channel. e.g. When the remote updates the shared region
+ * with new data, the reader needs to be protected from
+ * other CPUs activity on the same channel.
+ */
+static DEFINE_SPINLOCK(pcc_lock);
+
+/*
+ * The cpc_desc structure contains the ACPI register details
+ * as described in the per CPU _CPC tables. The details
+ * include the type of register (e.g. PCC, System IO, FFH etc.)
+ * and destination addresses which lets us READ/WRITE CPU performance
+ * information using the appropriate I/O methods.
+ */
+static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
+
+/* This layer handles all the PCC specifics for CPPC. */
+static struct mbox_chan *pcc_channel;
+static void __iomem *pcc_comm_addr;
+static u64 comm_base_addr;
+static int pcc_subspace_idx = -1;
+static u16 pcc_cmd_delay;
+static bool pcc_channel_acquired;
+
+/*
+ * Arbitrary Retries in case the remote processor is slow to respond
+ * to PCC commands.
+ */
+#define NUM_RETRIES 500
+
+static int send_pcc_cmd(u16 cmd)
+{
+ int retries, result = -EIO;
+ struct acpi_pcct_hw_reduced *pcct_ss = pcc_channel->con_priv;
+ struct acpi_pcct_shared_memory *generic_comm_base =
+ (struct acpi_pcct_shared_memory *) pcc_comm_addr;
+ u32 cmd_latency = pcct_ss->latency;
+
+ /* Min time OS should wait before sending next command. */
+ udelay(pcc_cmd_delay);
+
+ /* Write to the shared comm region. */
+ writew(cmd, &generic_comm_base->command);
+
+ /* Flip CMD COMPLETE bit */
+ writew(0, &generic_comm_base->status);
+
+ /* Ring doorbell */
+ result = mbox_send_message(pcc_channel, &cmd);
+ if (result < 0) {
+ pr_err("Err sending PCC mbox message. cmd:%d, ret:%d\n",
+ cmd, result);
+ return result;
+ }
+
+ /* Wait for a nominal time to let platform process command. */
+ udelay(cmd_latency);
+
+ /* Retry in case the remote processor was too slow to catch up. */
+ for (retries = NUM_RETRIES; retries > 0; retries--) {
+ if (readw_relaxed(&generic_comm_base->status) & PCC_CMD_COMPLETE) {
+ result = 0;
+ break;
+ }
+ }
+
+ mbox_client_txdone(pcc_channel, result);
+ return result;
+}
+
+static void cppc_chan_tx_done(struct mbox_client *cl, void *msg, int ret)
+{
+ if (ret)
+ pr_debug("TX did not complete: CMD sent:%x, ret:%d\n",
+ *(u16 *)msg, ret);
+ else
+ pr_debug("TX completed. CMD sent:%x, ret:%d\n",
+ *(u16 *)msg, ret);
+}
+
+struct mbox_client cppc_mbox_cl = {
+ .tx_done = cppc_chan_tx_done,
+ .knows_txdone = true,
+};
+
+static int acpi_get_psd(struct cpc_desc *cpc_ptr, acpi_handle handle)
+{
+ int result = -EFAULT;
+ acpi_status status = AE_OK;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
+ struct acpi_buffer state = {0, NULL};
+ union acpi_object *psd = NULL;
+ struct acpi_psd_package *pdomain;
+
+ status = acpi_evaluate_object_typed(handle, "_PSD", NULL, &buffer,
+ ACPI_TYPE_PACKAGE);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ psd = buffer.pointer;
+ if (!psd || psd->package.count != 1) {
+ pr_debug("Invalid _PSD data\n");
+ goto end;
+ }
+
+ pdomain = &(cpc_ptr->domain_info);
+
+ state.length = sizeof(struct acpi_psd_package);
+ state.pointer = pdomain;
+
+ status = acpi_extract_package(&(psd->package.elements[0]),
+ &format, &state);
+ if (ACPI_FAILURE(status)) {
+ pr_debug("Invalid _PSD data for CPU:%d\n", cpc_ptr->cpu_id);
+ goto end;
+ }
+
+ if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
+ pr_debug("Unknown _PSD:num_entries for CPU:%d\n", cpc_ptr->cpu_id);
+ goto end;
+ }
+
+ if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
+ pr_debug("Unknown _PSD:revision for CPU: %d\n", cpc_ptr->cpu_id);
+ goto end;
+ }
+
+ if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
+ pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
+ pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
+ pr_debug("Invalid _PSD:coord_type for CPU:%d\n", cpc_ptr->cpu_id);
+ goto end;
+ }
+
+ result = 0;
+end:
+ kfree(buffer.pointer);
+ return result;
+}
+
+/**
+ * acpi_get_psd_map - Map the CPUs in a common freq domain.
+ * @all_cpu_data: Ptrs to CPU specific CPPC data including PSD info.
+ *
+ * Return: 0 for success or negative value for err.
+ */
+int acpi_get_psd_map(struct cpudata **all_cpu_data)
+{
+ int count_target;
+ int retval = 0;
+ unsigned int i, j;
+ cpumask_var_t covered_cpus;
+ struct cpudata *pr, *match_pr;
+ struct acpi_psd_package *pdomain;
+ struct acpi_psd_package *match_pdomain;
+ struct cpc_desc *cpc_ptr, *match_cpc_ptr;
+
+ if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
+ return -ENOMEM;
+
+ /*
+ * Now that we have _PSD data from all CPUs, lets setup P-state
+ * domain info.
+ */
+ for_each_possible_cpu(i) {
+ pr = all_cpu_data[i];
+ if (!pr)
+ continue;
+
+ if (cpumask_test_cpu(i, covered_cpus))
+ continue;
+
+ cpc_ptr = per_cpu(cpc_desc_ptr, i);
+ if (!cpc_ptr)
+ continue;
+
+ pdomain = &(cpc_ptr->domain_info);
+ cpumask_set_cpu(i, pr->shared_cpu_map);
+ cpumask_set_cpu(i, covered_cpus);
+ if (pdomain->num_processors <= 1)
+ continue;
+
+ /* Validate the Domain info */
+ count_target = pdomain->num_processors;
+ if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
+ pr->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+ else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
+ pr->shared_type = CPUFREQ_SHARED_TYPE_HW;
+ else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
+ pr->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+
+ for_each_possible_cpu(j) {
+ if (i == j)
+ continue;
+
+ match_cpc_ptr = per_cpu(cpc_desc_ptr, j);
+ if (!match_cpc_ptr)
+ continue;
+
+ match_pdomain = &(match_cpc_ptr->domain_info);
+ if (match_pdomain->domain != pdomain->domain)
+ continue;
+
+ /* Here i and j are in the same domain */
+ if (match_pdomain->num_processors != count_target) {
+ retval = -EFAULT;
+ goto err_ret;
+ }
+
+ if (pdomain->coord_type != match_pdomain->coord_type) {
+ retval = -EFAULT;
+ goto err_ret;
+ }
+
+ cpumask_set_cpu(j, covered_cpus);
+ cpumask_set_cpu(j, pr->shared_cpu_map);
+ }
+
+ for_each_possible_cpu(j) {
+ if (i == j)
+ continue;
+
+ match_pr = all_cpu_data[j];
+ if (!match_pr)
+ continue;
+
+ match_cpc_ptr = per_cpu(cpc_desc_ptr, j);
+ if (!match_cpc_ptr)
+ continue;
+
+ match_pdomain = &(match_cpc_ptr->domain_info);
+ if (match_pdomain->domain != pdomain->domain)
+ continue;
+
+ match_pr->shared_type = pr->shared_type;
+ cpumask_copy(match_pr->shared_cpu_map,
+ pr->shared_cpu_map);
+ }
+ }
+
+err_ret:
+ for_each_possible_cpu(i) {
+ pr = all_cpu_data[i];
+ if (!pr)
+ continue;
+
+ /* Assume no coordination on any error parsing domain info */
+ if (retval) {
+ cpumask_clear(pr->shared_cpu_map);
+ cpumask_set_cpu(i, pr->shared_cpu_map);
+ pr->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+ }
+ }
+
+ free_cpumask_var(covered_cpus);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(acpi_get_psd_map);
+
+static int register_pcc_channel(int pcc_subspace_idx)
+{
+ struct acpi_pcct_hw_reduced *cppc_ss;
+ unsigned int len;
+
+ if (pcc_subspace_idx >= 0) {
+ pcc_channel = pcc_mbox_request_channel(&cppc_mbox_cl,
+ pcc_subspace_idx);
+
+ if (IS_ERR(pcc_channel)) {
+ pr_err("Failed to find PCC communication channel\n");
+ return -ENODEV;
+ }
+
+ /*
+ * The PCC mailbox controller driver should
+ * have parsed the PCCT (global table of all
+ * PCC channels) and stored pointers to the
+ * subspace communication region in con_priv.
+ */
+ cppc_ss = pcc_channel->con_priv;
+
+ if (!cppc_ss) {
+ pr_err("No PCC subspace found for CPPC\n");
+ return -ENODEV;
+ }
+
+ /*
+ * This is the shared communication region
+ * for the OS and Platform to communicate over.
+ */
+ comm_base_addr = cppc_ss->base_address;
+ len = cppc_ss->length;
+ pcc_cmd_delay = cppc_ss->min_turnaround_time;
+
+ pcc_comm_addr = acpi_os_ioremap(comm_base_addr, len);
+ if (!pcc_comm_addr) {
+ pr_err("Failed to ioremap PCC comm region mem\n");
+ return -ENOMEM;
+ }
+
+ /* Set flag so that we dont come here for each CPU. */
+ pcc_channel_acquired = true;
+ }
+
+ return 0;
+}
+
+/*
+ * An example CPC table looks like the following.
+ *
+ * Name(_CPC, Package()
+ * {
+ * 17,
+ * NumEntries
+ * 1,
+ * // Revision
+ * ResourceTemplate(){Register(PCC, 32, 0, 0x120, 2)},
+ * // Highest Performance
+ * ResourceTemplate(){Register(PCC, 32, 0, 0x124, 2)},
+ * // Nominal Performance
+ * ResourceTemplate(){Register(PCC, 32, 0, 0x128, 2)},
+ * // Lowest Nonlinear Performance
+ * ResourceTemplate(){Register(PCC, 32, 0, 0x12C, 2)},
+ * // Lowest Performance
+ * ResourceTemplate(){Register(PCC, 32, 0, 0x130, 2)},
+ * // Guaranteed Performance Register
+ * ResourceTemplate(){Register(PCC, 32, 0, 0x110, 2)},
+ * // Desired Performance Register
+ * ResourceTemplate(){Register(SystemMemory, 0, 0, 0, 0)},
+ * ..
+ * ..
+ * ..
+ *
+ * }
+ * Each Register() encodes how to access that specific register.
+ * e.g. a sample PCC entry has the following encoding:
+ *
+ * Register (
+ * PCC,
+ * AddressSpaceKeyword
+ * 8,
+ * //RegisterBitWidth
+ * 8,
+ * //RegisterBitOffset
+ * 0x30,
+ * //RegisterAddress
+ * 9
+ * //AccessSize (subspace ID)
+ * 0
+ * )
+ * }
+ */
+
+/**
+ * acpi_cppc_processor_probe - Search for per CPU _CPC objects.
+ * @pr: Ptr to acpi_processor containing this CPUs logical Id.
+ *
+ * Return: 0 for success or negative value for err.
+ */
+int acpi_cppc_processor_probe(struct acpi_processor *pr)
+{
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *out_obj, *cpc_obj;
+ struct cpc_desc *cpc_ptr;
+ struct cpc_reg *gas_t;
+ acpi_handle handle = pr->handle;
+ unsigned int num_ent, i, cpc_rev;
+ acpi_status status;
+ int ret = -EFAULT;
+
+ /* Parse the ACPI _CPC table for this cpu. */
+ status = acpi_evaluate_object_typed(handle, "_CPC", NULL, &output,
+ ACPI_TYPE_PACKAGE);
+ if (ACPI_FAILURE(status)) {
+ ret = -ENODEV;
+ goto out_buf_free;
+ }
+
+ out_obj = (union acpi_object *) output.pointer;
+
+ cpc_ptr = kzalloc(sizeof(struct cpc_desc), GFP_KERNEL);
+ if (!cpc_ptr) {
+ ret = -ENOMEM;
+ goto out_buf_free;
+ }
+
+ /* First entry is NumEntries. */
+ cpc_obj = &out_obj->package.elements[0];
+ if (cpc_obj->type == ACPI_TYPE_INTEGER) {
+ num_ent = cpc_obj->integer.value;
+ } else {
+ pr_debug("Unexpected entry type(%d) for NumEntries\n",
+ cpc_obj->type);
+ goto out_free;
+ }
+
+ /* Only support CPPCv2. Bail otherwise. */
+ if (num_ent != CPPC_NUM_ENT) {
+ pr_debug("Firmware exports %d entries. Expected: %d\n",
+ num_ent, CPPC_NUM_ENT);
+ goto out_free;
+ }
+
+ /* Second entry should be revision. */
+ cpc_obj = &out_obj->package.elements[1];
+ if (cpc_obj->type == ACPI_TYPE_INTEGER) {
+ cpc_rev = cpc_obj->integer.value;
+ } else {
+ pr_debug("Unexpected entry type(%d) for Revision\n",
+ cpc_obj->type);
+ goto out_free;
+ }
+
+ if (cpc_rev != CPPC_REV) {
+ pr_debug("Firmware exports revision:%d. Expected:%d\n",
+ cpc_rev, CPPC_REV);
+ goto out_free;
+ }
+
+ /* Iterate through remaining entries in _CPC */
+ for (i = 2; i < num_ent; i++) {
+ cpc_obj = &out_obj->package.elements[i];
+
+ if (cpc_obj->type == ACPI_TYPE_INTEGER) {
+ cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_INTEGER;
+ cpc_ptr->cpc_regs[i-2].cpc_entry.int_value = cpc_obj->integer.value;
+ } else if (cpc_obj->type == ACPI_TYPE_BUFFER) {
+ gas_t = (struct cpc_reg *)
+ cpc_obj->buffer.pointer;
+
+ /*
+ * The PCC Subspace index is encoded inside
+ * the CPC table entries. The same PCC index
+ * will be used for all the PCC entries,
+ * so extract it only once.
+ */
+ if (gas_t->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+ if (pcc_subspace_idx < 0)
+ pcc_subspace_idx = gas_t->access_width;
+ else if (pcc_subspace_idx != gas_t->access_width) {
+ pr_debug("Mismatched PCC ids.\n");
+ goto out_free;
+ }
+ } else if (gas_t->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+ /* Support only PCC and SYS MEM type regs */
+ pr_debug("Unsupported register type: %d\n", gas_t->space_id);
+ goto out_free;
+ }
+
+ cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_BUFFER;
+ memcpy(&cpc_ptr->cpc_regs[i-2].cpc_entry.reg, gas_t, sizeof(*gas_t));
+ } else {
+ pr_debug("Err in entry:%d in CPC table of CPU:%d \n", i, pr->id);
+ goto out_free;
+ }
+ }
+ /* Store CPU Logical ID */
+ cpc_ptr->cpu_id = pr->id;
+
+ /* Plug it into this CPUs CPC descriptor. */
+ per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
+
+ /* Parse PSD data for this CPU */
+ ret = acpi_get_psd(cpc_ptr, handle);
+ if (ret)
+ goto out_free;
+
+ /* Register PCC channel once for all CPUs. */
+ if (!pcc_channel_acquired) {
+ ret = register_pcc_channel(pcc_subspace_idx);
+ if (ret)
+ goto out_free;
+ }
+
+ /* Everything looks okay */
+ pr_debug("Parsed CPC struct for CPU: %d\n", pr->id);
+
+ kfree(output.pointer);
+ return 0;
+
+out_free:
+ kfree(cpc_ptr);
+
+out_buf_free:
+ kfree(output.pointer);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(acpi_cppc_processor_probe);
+
+/**
+ * acpi_cppc_processor_exit - Cleanup CPC structs.
+ * @pr: Ptr to acpi_processor containing this CPUs logical Id.
+ *
+ * Return: Void
+ */
+void acpi_cppc_processor_exit(struct acpi_processor *pr)
+{
+ struct cpc_desc *cpc_ptr;
+ cpc_ptr = per_cpu(cpc_desc_ptr, pr->id);
+ kfree(cpc_ptr);
+}
+EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);
+
+static u64 get_phys_addr(struct cpc_reg *reg)
+{
+ /* PCC communication addr space begins at byte offset 0x8. */
+ if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM)
+ return (u64)comm_base_addr + 0x8 + reg->address;
+ else
+ return reg->address;
+}
+
+static void cpc_read(struct cpc_reg *reg, u64 *val)
+{
+ u64 addr = get_phys_addr(reg);
+
+ acpi_os_read_memory((acpi_physical_address)addr,
+ val, reg->bit_width);
+}
+
+static void cpc_write(struct cpc_reg *reg, u64 val)
+{
+ u64 addr = get_phys_addr(reg);
+
+ acpi_os_write_memory((acpi_physical_address)addr,
+ val, reg->bit_width);
+}
+
+/**
+ * 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
+ *
+ * Return: 0 for success with perf_caps populated else -ERRNO.
+ */
+int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
+{
+ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
+ struct cpc_register_resource *highest_reg, *lowest_reg, *ref_perf,
+ *nom_perf;
+ u64 high, low, ref, nom;
+ int ret = 0;
+
+ if (!cpc_desc) {
+ pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
+ return -ENODEV;
+ }
+
+ highest_reg = &cpc_desc->cpc_regs[HIGHEST_PERF];
+ lowest_reg = &cpc_desc->cpc_regs[LOWEST_PERF];
+ ref_perf = &cpc_desc->cpc_regs[REFERENCE_PERF];
+ nom_perf = &cpc_desc->cpc_regs[NOMINAL_PERF];
+
+ spin_lock(&pcc_lock);
+
+ /* Are any of the regs PCC ?*/
+ if ((highest_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) ||
+ (lowest_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) ||
+ (ref_perf->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) ||
+ (nom_perf->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM)) {
+ /* Ring doorbell once to update PCC subspace */
+ if (send_pcc_cmd(CMD_READ)) {
+ ret = -EIO;
+ goto out_err;
+ }
+ }
+
+ cpc_read(&highest_reg->cpc_entry.reg, &high);
+ perf_caps->highest_perf = high;
+
+ cpc_read(&lowest_reg->cpc_entry.reg, &low);
+ perf_caps->lowest_perf = low;
+
+ cpc_read(&ref_perf->cpc_entry.reg, &ref);
+ perf_caps->reference_perf = ref;
+
+ cpc_read(&nom_perf->cpc_entry.reg, &nom);
+ perf_caps->nominal_perf = nom;
+
+ if (!ref)
+ perf_caps->reference_perf = perf_caps->nominal_perf;
+
+ if (!high || !low || !nom)
+ ret = -EFAULT;
+
+out_err:
+ spin_unlock(&pcc_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cppc_get_perf_caps);
+
+/**
+ * cppc_get_perf_ctrs - Read a CPUs performance feedback counters.
+ * @cpunum: CPU from which to read counters.
+ * @perf_fb_ctrs: ptr to cppc_perf_fb_ctrs. See cppc_acpi.h
+ *
+ * Return: 0 for success with perf_fb_ctrs populated else -ERRNO.
+ */
+int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
+{
+ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
+ struct cpc_register_resource *delivered_reg, *reference_reg;
+ u64 delivered, reference;
+ int ret = 0;
+
+ if (!cpc_desc) {
+ pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
+ return -ENODEV;
+ }
+
+ delivered_reg = &cpc_desc->cpc_regs[DELIVERED_CTR];
+ reference_reg = &cpc_desc->cpc_regs[REFERENCE_CTR];
+
+ spin_lock(&pcc_lock);
+
+ /* Are any of the regs PCC ?*/
+ if ((delivered_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) ||
+ (reference_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM)) {
+ /* Ring doorbell once to update PCC subspace */
+ if (send_pcc_cmd(CMD_READ)) {
+ ret = -EIO;
+ goto out_err;
+ }
+ }
+
+ cpc_read(&delivered_reg->cpc_entry.reg, &delivered);
+ cpc_read(&reference_reg->cpc_entry.reg, &reference);
+
+ if (!delivered || !reference) {
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ perf_fb_ctrs->delivered = delivered;
+ perf_fb_ctrs->reference = reference;
+
+ perf_fb_ctrs->delivered -= perf_fb_ctrs->prev_delivered;
+ perf_fb_ctrs->reference -= perf_fb_ctrs->prev_reference;
+
+ perf_fb_ctrs->prev_delivered = delivered;
+ perf_fb_ctrs->prev_reference = reference;
+
+out_err:
+ spin_unlock(&pcc_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cppc_get_perf_ctrs);
+
+/**
+ * cppc_set_perf - Set a CPUs performance controls.
+ * @cpu: CPU for which to set performance controls.
+ * @perf_ctrls: ptr to cppc_perf_ctrls. See cppc_acpi.h
+ *
+ * Return: 0 for success, -ERRNO otherwise.
+ */
+int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
+{
+ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
+ struct cpc_register_resource *desired_reg;
+ int ret = 0;
+
+ if (!cpc_desc) {
+ pr_debug("No CPC descriptor for CPU:%d\n", cpu);
+ return -ENODEV;
+ }
+
+ desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF];
+
+ spin_lock(&pcc_lock);
+
+ /*
+ * Skip writing MIN/MAX until Linux knows how to come up with
+ * useful values.
+ */
+ cpc_write(&desired_reg->cpc_entry.reg, perf_ctrls->desired_perf);
+
+ /* Is this a PCC reg ?*/
+ if (desired_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+ /* Ring doorbell so Remote can get our perf request. */
+ if (send_pcc_cmd(CMD_WRITE))
+ ret = -EIO;
+ }
+
+ spin_unlock(&pcc_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cppc_set_perf);
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 4806b7f856c4..08a02cdc737c 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -963,23 +963,6 @@ int acpi_subsys_prepare(struct device *dev)
EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
/**
- * acpi_subsys_complete - Finalize device's resume during system resume.
- * @dev: Device to handle.
- */
-void acpi_subsys_complete(struct device *dev)
-{
- pm_generic_complete(dev);
- /*
- * If the device had been runtime-suspended before the system went into
- * the sleep state it is going out of and it has never been resumed till
- * now, resume it in case the firmware powered it up.
- */
- if (dev->power.direct_complete)
- pm_request_resume(dev);
-}
-EXPORT_SYMBOL_GPL(acpi_subsys_complete);
-
-/**
* acpi_subsys_suspend - Run the device driver's suspend callback.
* @dev: Device to handle.
*
@@ -1047,7 +1030,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
.runtime_resume = acpi_subsys_runtime_resume,
#ifdef CONFIG_PM_SLEEP
.prepare = acpi_subsys_prepare,
- .complete = acpi_subsys_complete,
+ .complete = pm_complete_with_resume_check,
.suspend = acpi_subsys_suspend,
.suspend_late = acpi_subsys_suspend_late,
.resume_early = acpi_subsys_resume_early,
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
index 4ab4582e586b..707cf6213bc2 100644
--- a/drivers/acpi/device_sysfs.c
+++ b/drivers/acpi/device_sysfs.c
@@ -26,6 +26,106 @@
#include "internal.h"
+static ssize_t acpi_object_path(acpi_handle handle, char *buf)
+{
+ struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+ int result;
+
+ result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path);
+ if (result)
+ return result;
+
+ result = sprintf(buf, "%s\n", (char*)path.pointer);
+ kfree(path.pointer);
+ return result;
+}
+
+struct acpi_data_node_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct acpi_data_node *, char *);
+ ssize_t (*store)(struct acpi_data_node *, const char *, size_t count);
+};
+
+#define DATA_NODE_ATTR(_name) \
+ static struct acpi_data_node_attr data_node_##_name = \
+ __ATTR(_name, 0444, data_node_show_##_name, NULL)
+
+static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf)
+{
+ return acpi_object_path(dn->handle, buf);
+}
+
+DATA_NODE_ATTR(path);
+
+static struct attribute *acpi_data_node_default_attrs[] = {
+ &data_node_path.attr,
+ NULL
+};
+
+#define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
+#define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)
+
+static ssize_t acpi_data_node_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct acpi_data_node *dn = to_data_node(kobj);
+ struct acpi_data_node_attr *dn_attr = to_attr(attr);
+
+ return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO;
+}
+
+static const struct sysfs_ops acpi_data_node_sysfs_ops = {
+ .show = acpi_data_node_attr_show,
+};
+
+static void acpi_data_node_release(struct kobject *kobj)
+{
+ struct acpi_data_node *dn = to_data_node(kobj);
+ complete(&dn->kobj_done);
+}
+
+static struct kobj_type acpi_data_node_ktype = {
+ .sysfs_ops = &acpi_data_node_sysfs_ops,
+ .default_attrs = acpi_data_node_default_attrs,
+ .release = acpi_data_node_release,
+};
+
+static void acpi_expose_nondev_subnodes(struct kobject *kobj,
+ struct acpi_device_data *data)
+{
+ struct list_head *list = &data->subnodes;
+ struct acpi_data_node *dn;
+
+ if (list_empty(list))
+ return;
+
+ list_for_each_entry(dn, list, sibling) {
+ int ret;
+
+ init_completion(&dn->kobj_done);
+ ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
+ kobj, dn->name);
+ if (ret)
+ acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
+ else
+ acpi_expose_nondev_subnodes(&dn->kobj, &dn->data);
+ }
+}
+
+static void acpi_hide_nondev_subnodes(struct acpi_device_data *data)
+{
+ struct list_head *list = &data->subnodes;
+ struct acpi_data_node *dn;
+
+ if (list_empty(list))
+ return;
+
+ list_for_each_entry_reverse(dn, list, sibling) {
+ acpi_hide_nondev_subnodes(&dn->data);
+ kobject_put(&dn->kobj);
+ }
+}
+
/**
* create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
* @acpi_dev: ACPI device object.
@@ -323,20 +423,12 @@ static ssize_t acpi_device_adr_show(struct device *dev,
}
static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
-static ssize_t
-acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t acpi_device_path_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
- int result;
-
- result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
- if (result)
- goto end;
- result = sprintf(buf, "%s\n", (char*)path.pointer);
- kfree(path.pointer);
-end:
- return result;
+ return acpi_object_path(acpi_dev->handle, buf);
}
static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
@@ -475,6 +567,8 @@ int acpi_device_setup_files(struct acpi_device *dev)
&dev_attr_real_power_state);
}
+ acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
+
end:
return result;
}
@@ -485,6 +579,8 @@ end:
*/
void acpi_device_remove_files(struct acpi_device *dev)
{
+ acpi_hide_nondev_subnodes(&dev->data);
+
if (dev->flags.power_manageable) {
device_remove_file(&dev->dev, &dev_attr_power_state);
if (dev->power.flags.power_resources)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 42c66b64c12c..b420fb46669d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -441,17 +441,31 @@ static void acpi_ec_complete_query(struct acpi_ec *ec)
static bool acpi_ec_guard_event(struct acpi_ec *ec)
{
+ bool guarded = true;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ec->lock, flags);
+ /*
+ * If firmware SCI_EVT clearing timing is "event", we actually
+ * don't know when the SCI_EVT will be cleared by firmware after
+ * evaluating _Qxx, so we need to re-check SCI_EVT after waiting an
+ * acceptable period.
+ *
+ * The guarding period begins when EC_FLAGS_QUERY_PENDING is
+ * flagged, which means SCI_EVT check has just been performed.
+ * But if the current transaction is ACPI_EC_COMMAND_QUERY, the
+ * guarding should have already been performed (via
+ * EC_FLAGS_QUERY_GUARDING) and should not be applied so that the
+ * ACPI_EC_COMMAND_QUERY transaction can be transitioned into
+ * ACPI_EC_COMMAND_POLL state immediately.
+ */
if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS ||
ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY ||
!test_bit(EC_FLAGS_QUERY_PENDING, &ec->flags) ||
(ec->curr && ec->curr->command == ACPI_EC_COMMAND_QUERY))
- return false;
-
- /*
- * Postpone the query submission to allow the firmware to proceed,
- * we shouldn't check SCI_EVT before the firmware reflagging it.
- */
- return true;
+ guarded = false;
+ spin_unlock_irqrestore(&ec->lock, flags);
+ return guarded;
}
static int ec_transaction_polled(struct acpi_ec *ec)
@@ -597,6 +611,7 @@ static int ec_guard(struct acpi_ec *ec)
unsigned long guard = usecs_to_jiffies(ec_polling_guard);
unsigned long timeout = ec->timestamp + guard;
+ /* Ensure guarding period before polling EC status */
do {
if (ec_busy_polling) {
/* Perform busy polling */
@@ -606,11 +621,13 @@ static int ec_guard(struct acpi_ec *ec)
} else {
/*
* Perform wait polling
- *
- * For SCI_EVT clearing timing of "event",
- * performing guarding before re-checking the
- * SCI_EVT. Otherwise, such guarding is not needed
- * due to the old practices.
+ * 1. Wait the transaction to be completed by the
+ * GPE handler after the transaction enters
+ * ACPI_EC_COMMAND_POLL state.
+ * 2. A special guarding logic is also required
+ * for event clearing mode "event" before the
+ * transaction enters ACPI_EC_COMMAND_POLL
+ * state.
*/
if (!ec_transaction_polled(ec) &&
!acpi_ec_guard_event(ec))
@@ -620,7 +637,6 @@ static int ec_guard(struct acpi_ec *ec)
guard))
return 0;
}
- /* Guard the register accesses for the polling modes */
} while (time_before(jiffies, timeout));
return -ETIME;
}
@@ -929,6 +945,23 @@ acpi_ec_get_query_handler(struct acpi_ec_query_handler *handler)
return handler;
}
+static struct acpi_ec_query_handler *
+acpi_ec_get_query_handler_by_value(struct acpi_ec *ec, u8 value)
+{
+ struct acpi_ec_query_handler *handler;
+ bool found = false;
+
+ mutex_lock(&ec->mutex);
+ list_for_each_entry(handler, &ec->list, node) {
+ if (value == handler->query_bit) {
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(&ec->mutex);
+ return found ? acpi_ec_get_query_handler(handler) : NULL;
+}
+
static void acpi_ec_query_handler_release(struct kref *kref)
{
struct acpi_ec_query_handler *handler =
@@ -964,14 +997,15 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
}
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
-void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
+static void acpi_ec_remove_query_handlers(struct acpi_ec *ec,
+ bool remove_all, u8 query_bit)
{
struct acpi_ec_query_handler *handler, *tmp;
LIST_HEAD(free_list);
mutex_lock(&ec->mutex);
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
- if (query_bit == handler->query_bit) {
+ if (remove_all || query_bit == handler->query_bit) {
list_del_init(&handler->node);
list_add(&handler->node, &free_list);
}
@@ -980,6 +1014,11 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
list_for_each_entry_safe(handler, tmp, &free_list, node)
acpi_ec_put_query_handler(handler);
}
+
+void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
+{
+ acpi_ec_remove_query_handlers(ec, false, query_bit);
+}
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
static struct acpi_ec_query *acpi_ec_create_query(u8 *pval)
@@ -1025,7 +1064,6 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
{
u8 value = 0;
int result;
- struct acpi_ec_query_handler *handler;
struct acpi_ec_query *q;
q = acpi_ec_create_query(&value);
@@ -1043,28 +1081,29 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
if (result)
goto err_exit;
- mutex_lock(&ec->mutex);
- result = -ENODATA;
- list_for_each_entry(handler, &ec->list, node) {
- if (value == handler->query_bit) {
- result = 0;
- q->handler = acpi_ec_get_query_handler(handler);
- ec_dbg_evt("Query(0x%02x) scheduled",
- q->handler->query_bit);
- /*
- * It is reported that _Qxx are evaluated in a
- * parallel way on Windows:
- * https://bugzilla.kernel.org/show_bug.cgi?id=94411
- */
- if (!schedule_work(&q->work))
- result = -EBUSY;
- break;
- }
+ q->handler = acpi_ec_get_query_handler_by_value(ec, value);
+ if (!q->handler) {
+ result = -ENODATA;
+ goto err_exit;
+ }
+
+ /*
+ * It is reported that _Qxx are evaluated in a parallel way on
+ * Windows:
+ * https://bugzilla.kernel.org/show_bug.cgi?id=94411
+ *
+ * Put this log entry before schedule_work() in order to make
+ * it appearing before any other log entries occurred during the
+ * work queue execution.
+ */
+ ec_dbg_evt("Query(0x%02x) scheduled", value);
+ if (!schedule_work(&q->work)) {
+ ec_dbg_evt("Query(0x%02x) overlapped", value);
+ result = -EBUSY;
}
- mutex_unlock(&ec->mutex);
err_exit:
- if (result && q)
+ if (result)
acpi_ec_delete_query(q);
if (data)
*data = value;
@@ -1354,19 +1393,13 @@ static int acpi_ec_add(struct acpi_device *device)
static int acpi_ec_remove(struct acpi_device *device)
{
struct acpi_ec *ec;
- struct acpi_ec_query_handler *handler, *tmp;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
ec_remove_handlers(ec);
- mutex_lock(&ec->mutex);
- list_for_each_entry_safe(handler, tmp, &ec->list, node) {
- list_del(&handler->node);
- kfree(handler);
- }
- mutex_unlock(&ec->mutex);
+ acpi_ec_remove_query_handlers(ec, true, 0);
release_region(ec->data_addr, 1);
release_region(ec->command_addr, 1);
device->driver_data = NULL;
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index b4c216bab22b..bea8e425a8de 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -128,7 +128,7 @@ static int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
if (!debugfs_create_x32("gpe", 0444, dev_dir, (u32 *)&first_ec->gpe))
goto error;
if (!debugfs_create_bool("use_global_lock", 0444, dev_dir,
- (u32 *)&first_ec->global_lock))
+ &first_ec->global_lock))
goto error;
if (write_support)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index b9657af751d1..5ea5dc219f56 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -168,7 +168,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
struct list_head *physnode_list;
unsigned int node_id;
int retval = -EINVAL;
- bool coherent;
+ enum dev_dma_attr attr;
if (has_acpi_companion(dev)) {
if (acpi_dev) {
@@ -225,8 +225,10 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
if (!has_acpi_companion(dev))
ACPI_COMPANION_SET(dev, acpi_dev);
- if (acpi_check_dma(acpi_dev, &coherent))
- arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+ attr = acpi_get_dma_attr(acpi_dev);
+ if (attr != DEV_DMA_NOT_SUPPORTED)
+ arch_setup_dma_ops(dev, 0, 0, NULL,
+ attr == DEV_DMA_COHERENT);
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
@@ -351,13 +353,12 @@ static int acpi_platform_notify_remove(struct device *dev)
return 0;
}
-int __init init_acpi_device_notify(void)
+void __init init_acpi_device_notify(void)
{
if (platform_notify || platform_notify_remove) {
printk(KERN_ERR PREFIX "Can't use platform_notify\n");
- return 0;
+ return;
}
platform_notify = acpi_platform_notify;
platform_notify_remove = acpi_platform_notify_remove;
- return 0;
}
diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2d0e69..fa4585a6914e 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -11,9 +11,12 @@
#include <linux/acpi.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
+#include <linux/of.h>
enum acpi_irq_model_id acpi_irq_model;
+static struct fwnode_handle *acpi_gsi_domain_id;
+
static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
{
switch (polarity) {
@@ -45,12 +48,10 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
*/
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
- /*
- * Only default domain is supported at present, always find
- * the mapping corresponding to default domain by passing NULL
- * as irq_domain parameter
- */
- *irq = irq_find_mapping(NULL, gsi);
+ struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+ DOMAIN_BUS_ANY);
+
+ *irq = irq_find_mapping(d, gsi);
/*
* *irq == 0 means no mapping, that should
* be reported as a failure
@@ -72,23 +73,19 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
- unsigned int irq;
- unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+ struct irq_fwspec fwspec;
- /*
- * There is no way at present to look-up the IRQ domain on ACPI,
- * hence always create mapping referring to the default domain
- * by passing NULL as irq_domain parameter
- */
- irq = irq_create_mapping(NULL, gsi);
- if (!irq)
+ if (WARN_ON(!acpi_gsi_domain_id)) {
+ pr_warn("GSI: No registered irqchip, giving up\n");
return -EINVAL;
+ }
- /* Set irq type if specified and different than the current one */
- if (irq_type != IRQ_TYPE_NONE &&
- irq_type != irq_get_trigger_type(irq))
- irq_set_irq_type(irq, irq_type);
- return irq;
+ fwspec.fwnode = acpi_gsi_domain_id;
+ fwspec.param[0] = gsi;
+ fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
+ fwspec.param_count = 2;
+
+ return irq_create_fwspec_mapping(&fwspec);
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);
@@ -98,8 +95,23 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
*/
void acpi_unregister_gsi(u32 gsi)
{
- int irq = irq_find_mapping(NULL, gsi);
+ struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
+ DOMAIN_BUS_ANY);
+ int irq = irq_find_mapping(d, gsi);
irq_dispose_mapping(irq);
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
+
+/**
+ * acpi_set_irq_model - Setup the GSI irqdomain information
+ * @model: the value assigned to acpi_irq_model
+ * @fwnode: the irq_domain identifier for mapping and looking up
+ * GSI interrupts
+ */
+void __init acpi_set_irq_model(enum acpi_irq_model_id model,
+ struct fwnode_handle *fwnode)
+{
+ acpi_irq_model = model;
+ acpi_gsi_domain_id = fwnode;
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 9e426210c2a8..11d87bf67e73 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -21,7 +21,7 @@
#define PREFIX "ACPI: "
acpi_status acpi_os_initialize1(void);
-int init_acpi_device_notify(void);
+void init_acpi_device_notify(void);
int acpi_scan_init(void);
void acpi_pci_root_init(void);
void acpi_pci_link_init(void);
@@ -138,7 +138,7 @@ struct acpi_ec {
unsigned long gpe;
unsigned long command_addr;
unsigned long data_addr;
- unsigned long global_lock;
+ bool global_lock;
unsigned long flags;
unsigned long reference_count;
struct mutex mutex;
@@ -179,13 +179,13 @@ static inline int acpi_sleep_init(void) { return -ENXIO; }
#endif
#ifdef CONFIG_ACPI_SLEEP
-int acpi_sleep_proc_init(void);
+void acpi_sleep_proc_init(void);
int suspend_nvs_alloc(void);
void suspend_nvs_free(void);
int suspend_nvs_save(void);
void suspend_nvs_restore(void);
#else
-static inline int acpi_sleep_proc_init(void) { return 0; }
+static inline void acpi_sleep_proc_init(void) {}
static inline int suspend_nvs_alloc(void) { return 0; }
static inline void suspend_nvs_free(void) {}
static inline int suspend_nvs_save(void) { return 0; }
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index c1b8d03e262e..f7dab53b352a 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -27,12 +27,21 @@
* For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
* irrelevant.
*/
-#include <asm-generic/io-64-nonatomic-hi-lo.h>
+#include <linux/io-64-nonatomic-hi-lo.h>
static bool force_enable_dimms;
module_param(force_enable_dimms, bool, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(force_enable_dimms, "Ignore _STA (ACPI DIMM device) status");
+struct nfit_table_prev {
+ struct list_head spas;
+ struct list_head memdevs;
+ struct list_head dcrs;
+ struct list_head bdws;
+ struct list_head idts;
+ struct list_head flushes;
+};
+
static u8 nfit_uuid[NFIT_UUID_MAX][16];
const u8 *to_nfit_uuid(enum nfit_uuids id)
@@ -221,12 +230,20 @@ static int nfit_spa_type(struct acpi_nfit_system_address *spa)
}
static bool add_spa(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev,
struct acpi_nfit_system_address *spa)
{
struct device *dev = acpi_desc->dev;
- struct nfit_spa *nfit_spa = devm_kzalloc(dev, sizeof(*nfit_spa),
- GFP_KERNEL);
+ struct nfit_spa *nfit_spa;
+
+ list_for_each_entry(nfit_spa, &prev->spas, list) {
+ if (memcmp(nfit_spa->spa, spa, sizeof(*spa)) == 0) {
+ list_move_tail(&nfit_spa->list, &acpi_desc->spas);
+ return true;
+ }
+ }
+ nfit_spa = devm_kzalloc(dev, sizeof(*nfit_spa), GFP_KERNEL);
if (!nfit_spa)
return false;
INIT_LIST_HEAD(&nfit_spa->list);
@@ -239,12 +256,19 @@ static bool add_spa(struct acpi_nfit_desc *acpi_desc,
}
static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev,
struct acpi_nfit_memory_map *memdev)
{
struct device *dev = acpi_desc->dev;
- struct nfit_memdev *nfit_memdev = devm_kzalloc(dev,
- sizeof(*nfit_memdev), GFP_KERNEL);
+ struct nfit_memdev *nfit_memdev;
+ list_for_each_entry(nfit_memdev, &prev->memdevs, list)
+ if (memcmp(nfit_memdev->memdev, memdev, sizeof(*memdev)) == 0) {
+ list_move_tail(&nfit_memdev->list, &acpi_desc->memdevs);
+ return true;
+ }
+
+ nfit_memdev = devm_kzalloc(dev, sizeof(*nfit_memdev), GFP_KERNEL);
if (!nfit_memdev)
return false;
INIT_LIST_HEAD(&nfit_memdev->list);
@@ -257,12 +281,19 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
}
static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev,
struct acpi_nfit_control_region *dcr)
{
struct device *dev = acpi_desc->dev;
- struct nfit_dcr *nfit_dcr = devm_kzalloc(dev, sizeof(*nfit_dcr),
- GFP_KERNEL);
+ struct nfit_dcr *nfit_dcr;
+
+ list_for_each_entry(nfit_dcr, &prev->dcrs, list)
+ if (memcmp(nfit_dcr->dcr, dcr, sizeof(*dcr)) == 0) {
+ list_move_tail(&nfit_dcr->list, &acpi_desc->dcrs);
+ return true;
+ }
+ nfit_dcr = devm_kzalloc(dev, sizeof(*nfit_dcr), GFP_KERNEL);
if (!nfit_dcr)
return false;
INIT_LIST_HEAD(&nfit_dcr->list);
@@ -274,12 +305,19 @@ static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
}
static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev,
struct acpi_nfit_data_region *bdw)
{
struct device *dev = acpi_desc->dev;
- struct nfit_bdw *nfit_bdw = devm_kzalloc(dev, sizeof(*nfit_bdw),
- GFP_KERNEL);
+ struct nfit_bdw *nfit_bdw;
+
+ list_for_each_entry(nfit_bdw, &prev->bdws, list)
+ if (memcmp(nfit_bdw->bdw, bdw, sizeof(*bdw)) == 0) {
+ list_move_tail(&nfit_bdw->list, &acpi_desc->bdws);
+ return true;
+ }
+ nfit_bdw = devm_kzalloc(dev, sizeof(*nfit_bdw), GFP_KERNEL);
if (!nfit_bdw)
return false;
INIT_LIST_HEAD(&nfit_bdw->list);
@@ -291,12 +329,19 @@ static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
}
static bool add_idt(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev,
struct acpi_nfit_interleave *idt)
{
struct device *dev = acpi_desc->dev;
- struct nfit_idt *nfit_idt = devm_kzalloc(dev, sizeof(*nfit_idt),
- GFP_KERNEL);
+ struct nfit_idt *nfit_idt;
+
+ list_for_each_entry(nfit_idt, &prev->idts, list)
+ if (memcmp(nfit_idt->idt, idt, sizeof(*idt)) == 0) {
+ list_move_tail(&nfit_idt->list, &acpi_desc->idts);
+ return true;
+ }
+ nfit_idt = devm_kzalloc(dev, sizeof(*nfit_idt), GFP_KERNEL);
if (!nfit_idt)
return false;
INIT_LIST_HEAD(&nfit_idt->list);
@@ -308,12 +353,19 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc,
}
static bool add_flush(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev,
struct acpi_nfit_flush_address *flush)
{
struct device *dev = acpi_desc->dev;
- struct nfit_flush *nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush),
- GFP_KERNEL);
+ struct nfit_flush *nfit_flush;
+ list_for_each_entry(nfit_flush, &prev->flushes, list)
+ if (memcmp(nfit_flush->flush, flush, sizeof(*flush)) == 0) {
+ list_move_tail(&nfit_flush->list, &acpi_desc->flushes);
+ return true;
+ }
+
+ nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush), GFP_KERNEL);
if (!nfit_flush)
return false;
INIT_LIST_HEAD(&nfit_flush->list);
@@ -324,8 +376,8 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc,
return true;
}
-static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table,
- const void *end)
+static void *add_table(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev, void *table, const void *end)
{
struct device *dev = acpi_desc->dev;
struct acpi_nfit_header *hdr;
@@ -335,29 +387,35 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table,
return NULL;
hdr = table;
+ if (!hdr->length) {
+ dev_warn(dev, "found a zero length table '%d' parsing nfit\n",
+ hdr->type);
+ return NULL;
+ }
+
switch (hdr->type) {
case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
- if (!add_spa(acpi_desc, table))
+ if (!add_spa(acpi_desc, prev, table))
return err;
break;
case ACPI_NFIT_TYPE_MEMORY_MAP:
- if (!add_memdev(acpi_desc, table))
+ if (!add_memdev(acpi_desc, prev, table))
return err;
break;
case ACPI_NFIT_TYPE_CONTROL_REGION:
- if (!add_dcr(acpi_desc, table))
+ if (!add_dcr(acpi_desc, prev, table))
return err;
break;
case ACPI_NFIT_TYPE_DATA_REGION:
- if (!add_bdw(acpi_desc, table))
+ if (!add_bdw(acpi_desc, prev, table))
return err;
break;
case ACPI_NFIT_TYPE_INTERLEAVE:
- if (!add_idt(acpi_desc, table))
+ if (!add_idt(acpi_desc, prev, table))
return err;
break;
case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
- if (!add_flush(acpi_desc, table))
+ if (!add_flush(acpi_desc, prev, table))
return err;
break;
case ACPI_NFIT_TYPE_SMBIOS:
@@ -706,7 +764,7 @@ static ssize_t flags_show(struct device *dev,
flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save_fail " : "",
flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore_fail " : "",
flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush_fail " : "",
- flags & ACPI_NFIT_MEM_ARMED ? "not_armed " : "",
+ flags & ACPI_NFIT_MEM_NOT_ARMED ? "not_armed " : "",
flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart_event " : "");
}
static DEVICE_ATTR_RO(flags);
@@ -802,12 +860,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
device_handle = __to_nfit_memdev(nfit_mem)->device_handle;
nvdimm = acpi_nfit_dimm_by_handle(acpi_desc, device_handle);
if (nvdimm) {
- /*
- * If for some reason we find multiple DCRs the
- * first one wins
- */
- dev_err(acpi_desc->dev, "duplicate DCR detected: %s\n",
- nvdimm_name(nvdimm));
+ dimm_count++;
continue;
}
@@ -815,7 +868,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
flags |= NDD_ALIASING;
mem_flags = __to_nfit_memdev(nfit_mem)->flags;
- if (mem_flags & ACPI_NFIT_MEM_ARMED)
+ if (mem_flags & ACPI_NFIT_MEM_NOT_ARMED)
flags |= NDD_UNARMED;
rc = acpi_nfit_add_dimm(acpi_desc, nfit_mem, device_handle);
@@ -839,7 +892,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? " flush_fail" : "",
- mem_flags & ACPI_NFIT_MEM_ARMED ? " not_armed" : "");
+ mem_flags & ACPI_NFIT_MEM_NOT_ARMED ? " not_armed" : "");
}
@@ -1476,6 +1529,9 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
struct resource res;
int count = 0, rc;
+ if (nfit_spa->is_registered)
+ return 0;
+
if (spa->range_index == 0) {
dev_dbg(acpi_desc->dev, "%s: detected invalid spa index\n",
__func__);
@@ -1529,6 +1585,8 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
if (!nvdimm_volatile_region_create(nvdimm_bus, ndr_desc))
return -ENOMEM;
}
+
+ nfit_spa->is_registered = 1;
return 0;
}
@@ -1545,71 +1603,101 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc)
return 0;
}
+static int acpi_nfit_check_deletions(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_table_prev *prev)
+{
+ struct device *dev = acpi_desc->dev;
+
+ if (!list_empty(&prev->spas) ||
+ !list_empty(&prev->memdevs) ||
+ !list_empty(&prev->dcrs) ||
+ !list_empty(&prev->bdws) ||
+ !list_empty(&prev->idts) ||
+ !list_empty(&prev->flushes)) {
+ dev_err(dev, "new nfit deletes entries (unsupported)\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
{
struct device *dev = acpi_desc->dev;
+ struct nfit_table_prev prev;
const void *end;
u8 *data;
int rc;
- INIT_LIST_HEAD(&acpi_desc->spa_maps);
- INIT_LIST_HEAD(&acpi_desc->spas);
- INIT_LIST_HEAD(&acpi_desc->dcrs);
- INIT_LIST_HEAD(&acpi_desc->bdws);
- INIT_LIST_HEAD(&acpi_desc->idts);
- INIT_LIST_HEAD(&acpi_desc->flushes);
- INIT_LIST_HEAD(&acpi_desc->memdevs);
- INIT_LIST_HEAD(&acpi_desc->dimms);
- mutex_init(&acpi_desc->spa_map_mutex);
+ mutex_lock(&acpi_desc->init_mutex);
+
+ INIT_LIST_HEAD(&prev.spas);
+ INIT_LIST_HEAD(&prev.memdevs);
+ INIT_LIST_HEAD(&prev.dcrs);
+ INIT_LIST_HEAD(&prev.bdws);
+ INIT_LIST_HEAD(&prev.idts);
+ INIT_LIST_HEAD(&prev.flushes);
+
+ list_cut_position(&prev.spas, &acpi_desc->spas,
+ acpi_desc->spas.prev);
+ list_cut_position(&prev.memdevs, &acpi_desc->memdevs,
+ acpi_desc->memdevs.prev);
+ list_cut_position(&prev.dcrs, &acpi_desc->dcrs,
+ acpi_desc->dcrs.prev);
+ list_cut_position(&prev.bdws, &acpi_desc->bdws,
+ acpi_desc->bdws.prev);
+ list_cut_position(&prev.idts, &acpi_desc->idts,
+ acpi_desc->idts.prev);
+ list_cut_position(&prev.flushes, &acpi_desc->flushes,
+ acpi_desc->flushes.prev);
data = (u8 *) acpi_desc->nfit;
end = data + sz;
data += sizeof(struct acpi_table_nfit);
while (!IS_ERR_OR_NULL(data))
- data = add_table(acpi_desc, data, end);
+ data = add_table(acpi_desc, &prev, data, end);
if (IS_ERR(data)) {
dev_dbg(dev, "%s: nfit table parsing error: %ld\n", __func__,
PTR_ERR(data));
- return PTR_ERR(data);
+ rc = PTR_ERR(data);
+ goto out_unlock;
}
- if (nfit_mem_init(acpi_desc) != 0)
- return -ENOMEM;
+ rc = acpi_nfit_check_deletions(acpi_desc, &prev);
+ if (rc)
+ goto out_unlock;
+
+ if (nfit_mem_init(acpi_desc) != 0) {
+ rc = -ENOMEM;
+ goto out_unlock;
+ }
acpi_nfit_init_dsms(acpi_desc);
rc = acpi_nfit_register_dimms(acpi_desc);
if (rc)
- return rc;
+ goto out_unlock;
+
+ rc = acpi_nfit_register_regions(acpi_desc);
- return acpi_nfit_register_regions(acpi_desc);
+ out_unlock:
+ mutex_unlock(&acpi_desc->init_mutex);
+ return rc;
}
EXPORT_SYMBOL_GPL(acpi_nfit_init);
-static int acpi_nfit_add(struct acpi_device *adev)
+static struct acpi_nfit_desc *acpi_nfit_desc_init(struct acpi_device *adev)
{
struct nvdimm_bus_descriptor *nd_desc;
struct acpi_nfit_desc *acpi_desc;
struct device *dev = &adev->dev;
- struct acpi_table_header *tbl;
- acpi_status status = AE_OK;
- acpi_size sz;
- int rc;
-
- status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz);
- if (ACPI_FAILURE(status)) {
- dev_err(dev, "failed to find NFIT\n");
- return -ENXIO;
- }
acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
if (!acpi_desc)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
dev_set_drvdata(dev, acpi_desc);
acpi_desc->dev = dev;
- acpi_desc->nfit = (struct acpi_table_nfit *) tbl;
acpi_desc->blk_do_io = acpi_nfit_blk_region_do_io;
nd_desc = &acpi_desc->nd_desc;
nd_desc->provider_name = "ACPI.NFIT";
@@ -1617,8 +1705,57 @@ static int acpi_nfit_add(struct acpi_device *adev)
nd_desc->attr_groups = acpi_nfit_attribute_groups;
acpi_desc->nvdimm_bus = nvdimm_bus_register(dev, nd_desc);
- if (!acpi_desc->nvdimm_bus)
- return -ENXIO;
+ if (!acpi_desc->nvdimm_bus) {
+ devm_kfree(dev, acpi_desc);
+ return ERR_PTR(-ENXIO);
+ }
+
+ INIT_LIST_HEAD(&acpi_desc->spa_maps);
+ INIT_LIST_HEAD(&acpi_desc->spas);
+ INIT_LIST_HEAD(&acpi_desc->dcrs);
+ INIT_LIST_HEAD(&acpi_desc->bdws);
+ INIT_LIST_HEAD(&acpi_desc->idts);
+ INIT_LIST_HEAD(&acpi_desc->flushes);
+ INIT_LIST_HEAD(&acpi_desc->memdevs);
+ INIT_LIST_HEAD(&acpi_desc->dimms);
+ mutex_init(&acpi_desc->spa_map_mutex);
+ mutex_init(&acpi_desc->init_mutex);
+
+ return acpi_desc;
+}
+
+static int acpi_nfit_add(struct acpi_device *adev)
+{
+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_nfit_desc *acpi_desc;
+ struct device *dev = &adev->dev;
+ struct acpi_table_header *tbl;
+ acpi_status status = AE_OK;
+ acpi_size sz;
+ int rc;
+
+ status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz);
+ if (ACPI_FAILURE(status)) {
+ /* This is ok, we could have an nvdimm hotplugged later */
+ dev_dbg(dev, "failed to find NFIT at startup\n");
+ return 0;
+ }
+
+ acpi_desc = acpi_nfit_desc_init(adev);
+ if (IS_ERR(acpi_desc)) {
+ dev_err(dev, "%s: error initializing acpi_desc: %ld\n",
+ __func__, PTR_ERR(acpi_desc));
+ return PTR_ERR(acpi_desc);
+ }
+
+ acpi_desc->nfit = (struct acpi_table_nfit *) tbl;
+
+ /* Evaluate _FIT and override with that if present */
+ status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
+ if (ACPI_SUCCESS(status) && buf.length > 0) {
+ acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer;
+ sz = buf.length;
+ }
rc = acpi_nfit_init(acpi_desc, sz);
if (rc) {
@@ -1636,6 +1773,54 @@ static int acpi_nfit_remove(struct acpi_device *adev)
return 0;
}
+static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
+{
+ struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev);
+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_table_nfit *nfit_saved;
+ struct device *dev = &adev->dev;
+ acpi_status status;
+ int ret;
+
+ dev_dbg(dev, "%s: event: %d\n", __func__, event);
+
+ device_lock(dev);
+ if (!dev->driver) {
+ /* dev->driver may be null if we're being removed */
+ dev_dbg(dev, "%s: no driver found for dev\n", __func__);
+ return;
+ }
+
+ if (!acpi_desc) {
+ acpi_desc = acpi_nfit_desc_init(adev);
+ if (IS_ERR(acpi_desc)) {
+ dev_err(dev, "%s: error initializing acpi_desc: %ld\n",
+ __func__, PTR_ERR(acpi_desc));
+ goto out_unlock;
+ }
+ }
+
+ /* Evaluate _FIT */
+ status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ dev_err(dev, "failed to evaluate _FIT\n");
+ goto out_unlock;
+ }
+
+ nfit_saved = acpi_desc->nfit;
+ acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer;
+ ret = acpi_nfit_init(acpi_desc, buf.length);
+ if (!ret) {
+ /* Merge failed, restore old nfit, and exit */
+ acpi_desc->nfit = nfit_saved;
+ dev_err(dev, "failed to merge updated NFIT\n");
+ }
+ kfree(buf.pointer);
+
+ out_unlock:
+ device_unlock(dev);
+}
+
static const struct acpi_device_id acpi_nfit_ids[] = {
{ "ACPI0012", 0 },
{ "", 0 },
@@ -1648,6 +1833,7 @@ static struct acpi_driver acpi_nfit_driver = {
.ops = {
.add = acpi_nfit_add,
.remove = acpi_nfit_remove,
+ .notify = acpi_nfit_notify,
},
};
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
index 7e740156b9c2..2ea5c0797c8f 100644
--- a/drivers/acpi/nfit.h
+++ b/drivers/acpi/nfit.h
@@ -24,7 +24,7 @@
#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
| ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
- | ACPI_NFIT_MEM_ARMED)
+ | ACPI_NFIT_MEM_NOT_ARMED)
enum nfit_uuids {
NFIT_SPA_VOLATILE,
@@ -48,6 +48,7 @@ enum {
struct nfit_spa {
struct acpi_nfit_system_address *spa;
struct list_head list;
+ int is_registered;
};
struct nfit_dcr {
@@ -97,6 +98,7 @@ struct acpi_nfit_desc {
struct nvdimm_bus_descriptor nd_desc;
struct acpi_table_nfit *nfit;
struct mutex spa_map_mutex;
+ struct mutex init_mutex;
struct list_head spa_maps;
struct list_head memdevs;
struct list_head flushes;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 739a4a6b3b9b..32d684af0ec7 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -43,7 +43,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include "internal.h"
@@ -66,8 +66,6 @@ struct acpi_os_dpc {
/* stuff for debugger support */
int acpi_in_debugger;
EXPORT_SYMBOL(acpi_in_debugger);
-
-extern char line_buf[80];
#endif /*ENABLE_DEBUGGER */
static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl,
@@ -81,6 +79,7 @@ static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
static struct workqueue_struct *kacpi_hotplug_wq;
static bool acpi_os_initialized;
+unsigned int acpi_sci_irq = INVALID_ACPI_IRQ;
/*
* This list of permanent mappings is for memory that may be accessed from
@@ -856,17 +855,19 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
}
+ acpi_sci_irq = irq;
return AE_OK;
}
-acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
+acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
{
- if (irq != acpi_gbl_FADT.sci_interrupt)
+ if (gsi != acpi_gbl_FADT.sci_interrupt || !acpi_sci_irq_valid())
return AE_BAD_PARAMETER;
- free_irq(irq, acpi_irq);
+ free_irq(acpi_sci_irq, acpi_irq);
acpi_irq_handler = NULL;
+ acpi_sci_irq = INVALID_ACPI_IRQ;
return AE_OK;
}
@@ -1180,8 +1181,8 @@ void acpi_os_wait_events_complete(void)
* Make sure the GPE handler or the fixed event handler is not used
* on another CPU after removal.
*/
- if (acpi_irq_handler)
- synchronize_hardirq(acpi_gbl_FADT.sci_interrupt);
+ if (acpi_sci_irq_valid())
+ synchronize_hardirq(acpi_sci_irq);
flush_workqueue(kacpid_wq);
flush_workqueue(kacpi_notify_wq);
}
@@ -1345,15 +1346,13 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
return AE_OK;
}
-#ifdef ACPI_FUTURE_USAGE
-u32 acpi_os_get_line(char *buffer)
+acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read)
{
-
#ifdef ENABLE_DEBUGGER
if (acpi_in_debugger) {
u32 chars;
- kdb_read(buffer, sizeof(line_buf));
+ kdb_read(buffer, buffer_length);
/* remove the CR kdb includes */
chars = strlen(buffer) - 1;
@@ -1361,9 +1360,8 @@ u32 acpi_os_get_line(char *buffer)
}
#endif
- return 0;
+ return AE_OK;
}
-#endif /* ACPI_FUTURE_USAGE */
acpi_status acpi_os_signal(u32 function, void *info)
{
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 393706a5261b..850d7bf0c873 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -652,6 +652,210 @@ static void acpi_pci_root_remove(struct acpi_device *device)
kfree(root);
}
+/*
+ * Following code to support acpi_pci_root_create() is copied from
+ * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
+ * and ARM64.
+ */
+static void acpi_pci_root_validate_resources(struct device *dev,
+ struct list_head *resources,
+ unsigned long type)
+{
+ LIST_HEAD(list);
+ struct resource *res1, *res2, *root = NULL;
+ struct resource_entry *tmp, *entry, *entry2;
+
+ BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
+ root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
+
+ list_splice_init(resources, &list);
+ resource_list_for_each_entry_safe(entry, tmp, &list) {
+ bool free = false;
+ resource_size_t end;
+
+ res1 = entry->res;
+ if (!(res1->flags & type))
+ goto next;
+
+ /* Exclude non-addressable range or non-addressable portion */
+ end = min(res1->end, root->end);
+ if (end <= res1->start) {
+ dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
+ res1);
+ free = true;
+ goto next;
+ } else if (res1->end != end) {
+ dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
+ res1, (unsigned long long)end + 1,
+ (unsigned long long)res1->end);
+ res1->end = end;
+ }
+
+ resource_list_for_each_entry(entry2, resources) {
+ res2 = entry2->res;
+ if (!(res2->flags & type))
+ continue;
+
+ /*
+ * I don't like throwing away windows because then
+ * our resources no longer match the ACPI _CRS, but
+ * the kernel resource tree doesn't allow overlaps.
+ */
+ if (resource_overlaps(res1, res2)) {
+ res2->start = min(res1->start, res2->start);
+ res2->end = max(res1->end, res2->end);
+ dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
+ res2, res1);
+ free = true;
+ goto next;
+ }
+ }
+
+next:
+ resource_list_del(entry);
+ if (free)
+ resource_list_free_entry(entry);
+ else
+ resource_list_add_tail(entry, resources);
+ }
+}
+
+int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
+{
+ int ret;
+ struct list_head *list = &info->resources;
+ struct acpi_device *device = info->bridge;
+ struct resource_entry *entry, *tmp;
+ unsigned long flags;
+
+ flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
+ ret = acpi_dev_get_resources(device, list,
+ acpi_dev_filter_resource_type_cb,
+ (void *)flags);
+ if (ret < 0)
+ dev_warn(&device->dev,
+ "failed to parse _CRS method, error code %d\n", ret);
+ else if (ret == 0)
+ dev_dbg(&device->dev,
+ "no IO and memory resources present in _CRS\n");
+ else {
+ resource_list_for_each_entry_safe(entry, tmp, list) {
+ if (entry->res->flags & IORESOURCE_DISABLED)
+ resource_list_destroy_entry(entry);
+ else
+ entry->res->name = info->name;
+ }
+ acpi_pci_root_validate_resources(&device->dev, list,
+ IORESOURCE_MEM);
+ acpi_pci_root_validate_resources(&device->dev, list,
+ IORESOURCE_IO);
+ }
+
+ return ret;
+}
+
+static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
+{
+ struct resource_entry *entry, *tmp;
+ struct resource *res, *conflict, *root = NULL;
+
+ resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
+ res = entry->res;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+ else if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ else
+ continue;
+
+ conflict = insert_resource_conflict(root, res);
+ if (conflict) {
+ dev_info(&info->bridge->dev,
+ "ignoring host bridge window %pR (conflicts with %s %pR)\n",
+ res, conflict->name, conflict);
+ resource_list_destroy_entry(entry);
+ }
+ }
+}
+
+static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
+{
+ struct resource *res;
+ struct resource_entry *entry, *tmp;
+
+ if (!info)
+ return;
+
+ resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
+ res = entry->res;
+ if (res->parent &&
+ (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ release_resource(res);
+ resource_list_destroy_entry(entry);
+ }
+
+ info->ops->release_info(info);
+}
+
+static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
+{
+ struct resource *res;
+ struct resource_entry *entry;
+
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ res = entry->res;
+ if (res->parent &&
+ (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ release_resource(res);
+ }
+ __acpi_pci_root_release_info(bridge->release_data);
+}
+
+struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+ struct acpi_pci_root_ops *ops,
+ struct acpi_pci_root_info *info,
+ void *sysdata)
+{
+ int ret, busnum = root->secondary.start;
+ struct acpi_device *device = root->device;
+ int node = acpi_get_node(device->handle);
+ struct pci_bus *bus;
+
+ info->root = root;
+ info->bridge = device;
+ info->ops = ops;
+ INIT_LIST_HEAD(&info->resources);
+ snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
+ root->segment, busnum);
+
+ if (ops->init_info && ops->init_info(info))
+ goto out_release_info;
+ if (ops->prepare_resources)
+ ret = ops->prepare_resources(info);
+ else
+ ret = acpi_pci_probe_root_resources(info);
+ if (ret < 0)
+ goto out_release_info;
+
+ pci_acpi_root_add_resources(info);
+ pci_add_resource(&info->resources, &root->secondary);
+ bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
+ sysdata, &info->resources);
+ if (!bus)
+ goto out_release_info;
+
+ pci_scan_child_bus(bus);
+ pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
+ acpi_pci_root_release_info, info);
+ if (node != NUMA_NO_NODE)
+ dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
+ return bus;
+
+out_release_info:
+ __acpi_pci_root_release_info(info);
+ return NULL;
+}
+
void __init acpi_pci_root_init(void)
{
acpi_hest_init();
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 75c28eae8860..2a358154b770 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -144,11 +144,9 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
.release = single_release,
};
-int __init acpi_sleep_proc_init(void)
+void __init acpi_sleep_proc_init(void)
{
/* 'wakeup device' [R/W] */
proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
acpi_root_dir, &acpi_system_wakeup_device_fops);
-
- return 0;
}
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 51e658f21e95..f4e02ae93f58 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -242,6 +242,10 @@ static int __acpi_processor_start(struct acpi_device *device)
if (pr->flags.need_hotplug_init)
return 0;
+ result = acpi_cppc_processor_probe(pr);
+ if (result)
+ return -ENODEV;
+
if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
acpi_processor_power_init(pr);
@@ -287,6 +291,8 @@ static int acpi_processor_stop(struct device *dev)
acpi_pss_perf_exit(pr, device);
+ acpi_cppc_processor_exit(pr);
+
return 0;
}
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 6d99450549c5..88f4306744c0 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -19,11 +19,133 @@
#include "internal.h"
+static int acpi_data_get_property_array(struct acpi_device_data *data,
+ const char *name,
+ acpi_object_type type,
+ const union acpi_object **obj);
+
/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
static const u8 prp_uuid[16] = {
0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
};
+/* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
+static const u8 ads_uuid[16] = {
+ 0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b,
+ 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b
+};
+
+static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
+ const union acpi_object *desc,
+ struct acpi_device_data *data);
+static bool acpi_extract_properties(const union acpi_object *desc,
+ struct acpi_device_data *data);
+
+static bool acpi_nondev_subnode_ok(acpi_handle scope,
+ const union acpi_object *link,
+ struct list_head *list)
+{
+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+ struct acpi_data_node *dn;
+ acpi_handle handle;
+ acpi_status status;
+
+ dn = kzalloc(sizeof(*dn), GFP_KERNEL);
+ if (!dn)
+ return false;
+
+ dn->name = link->package.elements[0].string.pointer;
+ dn->fwnode.type = FWNODE_ACPI_DATA;
+ INIT_LIST_HEAD(&dn->data.subnodes);
+
+ status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
+ &handle);
+ if (ACPI_FAILURE(status))
+ goto fail;
+
+ status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
+ ACPI_TYPE_PACKAGE);
+ if (ACPI_FAILURE(status))
+ goto fail;
+
+ if (acpi_extract_properties(buf.pointer, &dn->data))
+ dn->handle = handle;
+
+ /*
+ * The scope for the subnode object lookup is the one of the namespace
+ * node (device) containing the object that has returned the package.
+ * That is, it's the scope of that object's parent.
+ */
+ status = acpi_get_parent(handle, &scope);
+ if (ACPI_SUCCESS(status)
+ && acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data))
+ dn->handle = handle;
+
+ if (dn->handle) {
+ dn->data.pointer = buf.pointer;
+ list_add_tail(&dn->sibling, list);
+ return true;
+ }
+
+ acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
+
+ fail:
+ ACPI_FREE(buf.pointer);
+ kfree(dn);
+ return false;
+}
+
+static int acpi_add_nondev_subnodes(acpi_handle scope,
+ const union acpi_object *links,
+ struct list_head *list)
+{
+ bool ret = false;
+ int i;
+
+ for (i = 0; i < links->package.count; i++) {
+ const union acpi_object *link;
+
+ link = &links->package.elements[i];
+ /* Only two elements allowed, both must be strings. */
+ if (link->package.count == 2
+ && link->package.elements[0].type == ACPI_TYPE_STRING
+ && link->package.elements[1].type == ACPI_TYPE_STRING
+ && acpi_nondev_subnode_ok(scope, link, list))
+ ret = true;
+ }
+
+ return ret;
+}
+
+static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
+ const union acpi_object *desc,
+ struct acpi_device_data *data)
+{
+ int i;
+
+ /* Look for the ACPI data subnodes UUID. */
+ for (i = 0; i < desc->package.count; i += 2) {
+ const union acpi_object *uuid, *links;
+
+ uuid = &desc->package.elements[i];
+ links = &desc->package.elements[i + 1];
+
+ /*
+ * The first element must be a UUID and the second one must be
+ * a package.
+ */
+ if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
+ || links->type != ACPI_TYPE_PACKAGE)
+ break;
+
+ if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid)))
+ continue;
+
+ return acpi_add_nondev_subnodes(scope, links, &data->subnodes);
+ }
+
+ return false;
+}
static bool acpi_property_value_ok(const union acpi_object *value)
{
@@ -81,8 +203,8 @@ static void acpi_init_of_compatible(struct acpi_device *adev)
const union acpi_object *of_compatible;
int ret;
- ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
- &of_compatible);
+ ret = acpi_data_get_property_array(&adev->data, "compatible",
+ ACPI_TYPE_STRING, &of_compatible);
if (ret) {
ret = acpi_dev_get_property(adev, "compatible",
ACPI_TYPE_STRING, &of_compatible);
@@ -100,34 +222,13 @@ static void acpi_init_of_compatible(struct acpi_device *adev)
adev->flags.of_compatible_ok = 1;
}
-void acpi_init_properties(struct acpi_device *adev)
+static bool acpi_extract_properties(const union acpi_object *desc,
+ struct acpi_device_data *data)
{
- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
- bool acpi_of = false;
- struct acpi_hardware_id *hwid;
- const union acpi_object *desc;
- acpi_status status;
int i;
- /*
- * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
- * Device Tree compatible properties for this device.
- */
- list_for_each_entry(hwid, &adev->pnp.ids, list) {
- if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
- acpi_of = true;
- break;
- }
- }
-
- status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
- ACPI_TYPE_PACKAGE);
- if (ACPI_FAILURE(status))
- goto out;
-
- desc = buf.pointer;
if (desc->package.count % 2)
- goto fail;
+ return false;
/* Look for the device properties UUID. */
for (i = 0; i < desc->package.count; i += 2) {
@@ -154,18 +255,50 @@ void acpi_init_properties(struct acpi_device *adev)
if (!acpi_properties_format_valid(properties))
break;
- adev->data.pointer = buf.pointer;
- adev->data.properties = properties;
+ data->properties = properties;
+ return true;
+ }
- if (acpi_of)
- acpi_init_of_compatible(adev);
+ return false;
+}
+void acpi_init_properties(struct acpi_device *adev)
+{
+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+ struct acpi_hardware_id *hwid;
+ acpi_status status;
+ bool acpi_of = false;
+
+ INIT_LIST_HEAD(&adev->data.subnodes);
+
+ /*
+ * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
+ * Device Tree compatible properties for this device.
+ */
+ list_for_each_entry(hwid, &adev->pnp.ids, list) {
+ if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
+ acpi_of = true;
+ break;
+ }
+ }
+
+ status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
+ ACPI_TYPE_PACKAGE);
+ if (ACPI_FAILURE(status))
goto out;
+
+ if (acpi_extract_properties(buf.pointer, &adev->data)) {
+ adev->data.pointer = buf.pointer;
+ if (acpi_of)
+ acpi_init_of_compatible(adev);
}
+ if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer, &adev->data))
+ adev->data.pointer = buf.pointer;
- fail:
- dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n");
- ACPI_FREE(buf.pointer);
+ if (!adev->data.pointer) {
+ acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
+ ACPI_FREE(buf.pointer);
+ }
out:
if (acpi_of && !adev->flags.of_compatible_ok)
@@ -173,8 +306,25 @@ void acpi_init_properties(struct acpi_device *adev)
ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
}
+static void acpi_destroy_nondev_subnodes(struct list_head *list)
+{
+ struct acpi_data_node *dn, *next;
+
+ if (list_empty(list))
+ return;
+
+ list_for_each_entry_safe_reverse(dn, next, list, sibling) {
+ acpi_destroy_nondev_subnodes(&dn->data.subnodes);
+ wait_for_completion(&dn->kobj_done);
+ list_del(&dn->sibling);
+ ACPI_FREE((void *)dn->data.pointer);
+ kfree(dn);
+ }
+}
+
void acpi_free_properties(struct acpi_device *adev)
{
+ acpi_destroy_nondev_subnodes(&adev->data.subnodes);
ACPI_FREE((void *)adev->data.pointer);
adev->data.of_compatible = NULL;
adev->data.pointer = NULL;
@@ -182,8 +332,8 @@ void acpi_free_properties(struct acpi_device *adev)
}
/**
- * acpi_dev_get_property - return an ACPI property with given name
- * @adev: ACPI device to get property
+ * acpi_data_get_property - return an ACPI property with given name
+ * @data: ACPI device deta object to get the property from
* @name: Name of the property
* @type: Expected property type
* @obj: Location to store the property value (if not %NULL)
@@ -192,26 +342,27 @@ void acpi_free_properties(struct acpi_device *adev)
* object at the location pointed to by @obj if found.
*
* Callers must not attempt to free the returned objects. These objects will be
- * freed by the ACPI core automatically during the removal of @adev.
+ * freed by the ACPI core automatically during the removal of @data.
*
* Return: %0 if property with @name has been found (success),
* %-EINVAL if the arguments are invalid,
* %-ENODATA if the property doesn't exist,
* %-EPROTO if the property value type doesn't match @type.
*/
-int acpi_dev_get_property(struct acpi_device *adev, const char *name,
- acpi_object_type type, const union acpi_object **obj)
+static int acpi_data_get_property(struct acpi_device_data *data,
+ const char *name, acpi_object_type type,
+ const union acpi_object **obj)
{
const union acpi_object *properties;
int i;
- if (!adev || !name)
+ if (!data || !name)
return -EINVAL;
- if (!adev->data.pointer || !adev->data.properties)
+ if (!data->pointer || !data->properties)
return -ENODATA;
- properties = adev->data.properties;
+ properties = data->properties;
for (i = 0; i < properties->package.count; i++) {
const union acpi_object *propname, *propvalue;
const union acpi_object *property;
@@ -232,11 +383,50 @@ int acpi_dev_get_property(struct acpi_device *adev, const char *name,
}
return -ENODATA;
}
+
+/**
+ * acpi_dev_get_property - return an ACPI property with given name.
+ * @adev: ACPI device to get the property from.
+ * @name: Name of the property.
+ * @type: Expected property type.
+ * @obj: Location to store the property value (if not %NULL).
+ */
+int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+ acpi_object_type type, const union acpi_object **obj)
+{
+ return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
+}
EXPORT_SYMBOL_GPL(acpi_dev_get_property);
+static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode)
+{
+ if (fwnode->type == FWNODE_ACPI) {
+ struct acpi_device *adev = to_acpi_device_node(fwnode);
+ return &adev->data;
+ } else if (fwnode->type == FWNODE_ACPI_DATA) {
+ struct acpi_data_node *dn = to_acpi_data_node(fwnode);
+ return &dn->data;
+ }
+ return NULL;
+}
+
+/**
+ * acpi_node_prop_get - return an ACPI property with given name.
+ * @fwnode: Firmware node to get the property from.
+ * @propname: Name of the property.
+ * @valptr: Location to store a pointer to the property value (if not %NULL).
+ */
+int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
+ void **valptr)
+{
+ return acpi_data_get_property(acpi_device_data_of_node(fwnode),
+ propname, ACPI_TYPE_ANY,
+ (const union acpi_object **)valptr);
+}
+
/**
- * acpi_dev_get_property_array - return an ACPI array property with given name
- * @adev: ACPI device to get property
+ * acpi_data_get_property_array - return an ACPI array property with given name
+ * @adev: ACPI data object to get the property from
* @name: Name of the property
* @type: Expected type of array elements
* @obj: Location to store a pointer to the property value (if not NULL)
@@ -245,7 +435,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property);
* ACPI object at the location pointed to by @obj if found.
*
* Callers must not attempt to free the returned objects. Those objects will be
- * freed by the ACPI core automatically during the removal of @adev.
+ * freed by the ACPI core automatically during the removal of @data.
*
* Return: %0 if array property (package) with @name has been found (success),
* %-EINVAL if the arguments are invalid,
@@ -253,14 +443,15 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property);
* %-EPROTO if the property is not a package or the type of its elements
* doesn't match @type.
*/
-int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
- acpi_object_type type,
- const union acpi_object **obj)
+static int acpi_data_get_property_array(struct acpi_device_data *data,
+ const char *name,
+ acpi_object_type type,
+ const union acpi_object **obj)
{
const union acpi_object *prop;
int ret, i;
- ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
+ ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
if (ret)
return ret;
@@ -275,12 +466,11 @@ int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
return 0;
}
-EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
/**
- * acpi_dev_get_property_reference - returns handle to the referenced object
- * @adev: ACPI device to get property
- * @name: Name of the property
+ * acpi_data_get_property_reference - returns handle to the referenced object
+ * @data: ACPI device data object containing the property
+ * @propname: Name of the property
* @index: Index of the reference to return
* @args: Location to store the returned reference with optional arguments
*
@@ -294,16 +484,16 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
*
* Return: %0 on success, negative error code on failure.
*/
-int acpi_dev_get_property_reference(struct acpi_device *adev,
- const char *name, size_t index,
- struct acpi_reference_args *args)
+static int acpi_data_get_property_reference(struct acpi_device_data *data,
+ const char *propname, size_t index,
+ struct acpi_reference_args *args)
{
const union acpi_object *element, *end;
const union acpi_object *obj;
struct acpi_device *device;
int ret, idx = 0;
- ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
+ ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
if (ret)
return ret;
@@ -378,17 +568,27 @@ int acpi_dev_get_property_reference(struct acpi_device *adev,
return -EPROTO;
}
-EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
-int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
- void **valptr)
+/**
+ * acpi_node_get_property_reference - get a handle to the referenced object.
+ * @fwnode: Firmware node to get the property from.
+ * @propname: Name of the property.
+ * @index: Index of the reference to return.
+ * @args: Location to store the returned reference with optional arguments.
+ */
+int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
+ const char *name, size_t index,
+ struct acpi_reference_args *args)
{
- return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
- (const union acpi_object **)valptr);
+ struct acpi_device_data *data = acpi_device_data_of_node(fwnode);
+
+ return data ? acpi_data_get_property_reference(data, name, index, args) : -EINVAL;
}
+EXPORT_SYMBOL_GPL(acpi_node_get_property_reference);
-int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
- enum dev_prop_type proptype, void *val)
+static int acpi_data_prop_read_single(struct acpi_device_data *data,
+ const char *propname,
+ enum dev_prop_type proptype, void *val)
{
const union acpi_object *obj;
int ret;
@@ -397,7 +597,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
return -EINVAL;
if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
- ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
+ ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
if (ret)
return ret;
@@ -422,7 +622,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
break;
}
} else if (proptype == DEV_PROP_STRING) {
- ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
+ ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
if (ret)
return ret;
@@ -433,6 +633,12 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
return ret;
}
+int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
+ enum dev_prop_type proptype, void *val)
+{
+ return adev ? acpi_data_prop_read_single(&adev->data, propname, proptype, val) : -EINVAL;
+}
+
static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
size_t nval)
{
@@ -509,20 +715,22 @@ static int acpi_copy_property_array_string(const union acpi_object *items,
return 0;
}
-int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
- enum dev_prop_type proptype, void *val, size_t nval)
+static int acpi_data_prop_read(struct acpi_device_data *data,
+ const char *propname,
+ enum dev_prop_type proptype,
+ void *val, size_t nval)
{
const union acpi_object *obj;
const union acpi_object *items;
int ret;
if (val && nval == 1) {
- ret = acpi_dev_prop_read_single(adev, propname, proptype, val);
+ ret = acpi_data_prop_read_single(data, propname, proptype, val);
if (!ret)
return ret;
}
- ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
+ ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
if (ret)
return ret;
@@ -558,3 +766,84 @@ int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
}
return ret;
}
+
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+ enum dev_prop_type proptype, void *val, size_t nval)
+{
+ return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
+}
+
+/**
+ * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
+ * @fwnode: Firmware node to get the property from.
+ * @propname: Name of the property.
+ * @proptype: Expected property type.
+ * @val: Location to store the property value (if not %NULL).
+ * @nval: Size of the array pointed to by @val.
+ *
+ * If @val is %NULL, return the number of array elements comprising the value
+ * of the property. Otherwise, read at most @nval values to the array at the
+ * location pointed to by @val.
+ */
+int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname,
+ enum dev_prop_type proptype, void *val, size_t nval)
+{
+ return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
+ propname, proptype, val, nval);
+}
+
+/**
+ * acpi_get_next_subnode - Return the next child node handle for a device.
+ * @dev: Device to find the next child node for.
+ * @child: Handle to one of the device's child nodes or a null handle.
+ */
+struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
+ struct fwnode_handle *child)
+{
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ struct list_head *head, *next;
+
+ if (!adev)
+ return NULL;
+
+ if (!child || child->type == FWNODE_ACPI) {
+ head = &adev->children;
+ if (list_empty(head))
+ goto nondev;
+
+ if (child) {
+ adev = to_acpi_device_node(child);
+ next = adev->node.next;
+ if (next == head) {
+ child = NULL;
+ goto nondev;
+ }
+ adev = list_entry(next, struct acpi_device, node);
+ } else {
+ adev = list_first_entry(head, struct acpi_device, node);
+ }
+ return acpi_fwnode_handle(adev);
+ }
+
+ nondev:
+ if (!child || child->type == FWNODE_ACPI_DATA) {
+ struct acpi_data_node *dn;
+
+ head = &adev->data.subnodes;
+ if (list_empty(head))
+ return NULL;
+
+ if (child) {
+ dn = to_acpi_data_node(child);
+ next = dn->sibling.next;
+ if (next == head)
+ return NULL;
+
+ dn = list_entry(next, struct acpi_data_node, sibling);
+ } else {
+ dn = list_first_entry(head, struct acpi_data_node, sibling);
+ }
+ return &dn->fwnode;
+ }
+ return NULL;
+}
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 15d22db05054..cdc5c2599beb 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -119,7 +119,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
- u8 io_decode)
+ u8 io_decode, u8 translation_type)
{
res->flags = IORESOURCE_IO;
@@ -131,6 +131,8 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
if (io_decode == ACPI_DECODE_16)
res->flags |= IORESOURCE_IO_16BIT_ADDR;
+ if (translation_type == ACPI_SPARSE_TRANSLATION)
+ res->flags |= IORESOURCE_IO_SPARSE;
}
static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
@@ -138,7 +140,7 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
{
res->start = start;
res->end = start + len - 1;
- acpi_dev_ioresource_flags(res, len, io_decode);
+ acpi_dev_ioresource_flags(res, len, io_decode, 0);
}
/**
@@ -231,7 +233,8 @@ static bool acpi_decode_space(struct resource_win *win,
acpi_dev_memresource_flags(res, len, wp);
break;
case ACPI_IO_RANGE:
- acpi_dev_ioresource_flags(res, len, iodec);
+ acpi_dev_ioresource_flags(res, len, iodec,
+ addr->info.io.translation_type);
break;
case ACPI_BUS_NUMBER_RANGE:
res->flags = IORESOURCE_BUS;
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index bf034f8b7c1a..2fa8304171e0 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -14,7 +14,6 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/dmi.h>
#include "sbshc.h"
#define PREFIX "ACPI: "
@@ -30,6 +29,7 @@ struct acpi_smb_hc {
u8 query_bit;
smbus_alarm_callback callback;
void *context;
+ bool done;
};
static int acpi_smbus_hc_add(struct acpi_device *device);
@@ -88,8 +88,6 @@ enum acpi_smb_offset {
ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */
};
-static bool macbook;
-
static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
{
return ec_read(hc->offset + address, data);
@@ -100,27 +98,11 @@ static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data)
return ec_write(hc->offset + address, data);
}
-static inline int smb_check_done(struct acpi_smb_hc *hc)
-{
- union acpi_smb_status status = {.raw = 0};
- smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw);
- return status.fields.done && (status.fields.status == SMBUS_OK);
-}
-
static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
{
- if (wait_event_timeout(hc->wait, smb_check_done(hc),
- msecs_to_jiffies(timeout)))
+ if (wait_event_timeout(hc->wait, hc->done, msecs_to_jiffies(timeout)))
return 0;
- /*
- * After the timeout happens, OS will try to check the status of SMbus.
- * If the status is what OS expected, it will be regarded as the bogus
- * timeout.
- */
- if (smb_check_done(hc))
- return 0;
- else
- return -ETIME;
+ return -ETIME;
}
static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
@@ -135,8 +117,7 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
}
mutex_lock(&hc->lock);
- if (macbook)
- udelay(5);
+ hc->done = false;
if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
goto end;
if (temp) {
@@ -235,8 +216,10 @@ static int smbus_alarm(void *context)
if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
return 0;
/* Check if it is only a completion notify */
- if (status.fields.done)
+ if (status.fields.done && status.fields.status == SMBUS_OK) {
+ hc->done = true;
wake_up(&hc->wait);
+ }
if (!status.fields.alarm)
return 0;
mutex_lock(&hc->lock);
@@ -262,29 +245,12 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
acpi_handle handle, acpi_ec_query_func func,
void *data);
-static int macbook_dmi_match(const struct dmi_system_id *d)
-{
- pr_debug("Detected MacBook, enabling workaround\n");
- macbook = true;
- return 0;
-}
-
-static struct dmi_system_id acpi_smbus_dmi_table[] = {
- { macbook_dmi_match, "Apple MacBook", {
- DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
- },
- { },
-};
-
static int acpi_smbus_hc_add(struct acpi_device *device)
{
int status;
unsigned long long val;
struct acpi_smb_hc *hc;
- dmi_check_system(acpi_smbus_dmi_table);
-
if (!device)
return -EINVAL;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 01136b879038..78d5f02a073b 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -695,26 +695,6 @@ int acpi_device_add(struct acpi_device *device,
return result;
}
-struct acpi_device *acpi_get_next_child(struct device *dev,
- struct acpi_device *child)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
- struct list_head *head, *next;
-
- if (!adev)
- return NULL;
-
- head = &adev->children;
- if (list_empty(head))
- return NULL;
-
- if (!child)
- return list_first_entry(head, struct acpi_device, node);
-
- next = child->node.next;
- return next == head ? NULL : list_entry(next, struct acpi_device, node);
-}
-
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
@@ -1184,7 +1164,7 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
if (!id)
return;
- id->id = kstrdup(dev_id, GFP_KERNEL);
+ id->id = kstrdup_const(dev_id, GFP_KERNEL);
if (!id->id) {
kfree(id);
return;
@@ -1322,12 +1302,54 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
struct acpi_hardware_id *id, *tmp;
list_for_each_entry_safe(id, tmp, &pnp->ids, list) {
- kfree(id->id);
+ kfree_const(id->id);
kfree(id);
}
kfree(pnp->unique_id);
}
+/**
+ * acpi_dma_supported - Check DMA support for the specified device.
+ * @adev: The pointer to acpi device
+ *
+ * Return false if DMA is not supported. Otherwise, return true
+ */
+bool acpi_dma_supported(struct acpi_device *adev)
+{
+ if (!adev)
+ return false;
+
+ if (adev->flags.cca_seen)
+ return true;
+
+ /*
+ * Per ACPI 6.0 sec 6.2.17, assume devices can do cache-coherent
+ * DMA on "Intel platforms". Presumably that includes all x86 and
+ * ia64, and other arches will set CONFIG_ACPI_CCA_REQUIRED=y.
+ */
+ if (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED))
+ return true;
+
+ return false;
+}
+
+/**
+ * acpi_get_dma_attr - Check the supported DMA attr for the specified device.
+ * @adev: The pointer to acpi device
+ *
+ * Return enum dev_dma_attr.
+ */
+enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
+{
+ if (!acpi_dma_supported(adev))
+ return DEV_DMA_NOT_SUPPORTED;
+
+ if (adev->flags.coherent_dma)
+ return DEV_DMA_COHERENT;
+ else
+ return DEV_DMA_NON_COHERENT;
+}
+
static void acpi_init_coherency(struct acpi_device *adev)
{
unsigned long long cca = 0;
@@ -1472,7 +1494,7 @@ bool acpi_device_is_present(struct acpi_device *adev)
}
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
- char *idstr,
+ const char *idstr,
const struct acpi_device_id **matchid)
{
const struct acpi_device_id *devid;
@@ -1491,7 +1513,7 @@ static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
return false;
}
-static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
+static struct acpi_scan_handler *acpi_scan_match_handler(const char *idstr,
const struct acpi_device_id **matchid)
{
struct acpi_scan_handler *handler;
@@ -1933,3 +1955,42 @@ int __init acpi_scan_init(void)
mutex_unlock(&acpi_scan_lock);
return result;
}
+
+static struct acpi_probe_entry *ape;
+static int acpi_probe_count;
+static DEFINE_SPINLOCK(acpi_probe_lock);
+
+static int __init acpi_match_madt(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+ if (!ape->subtable_valid || ape->subtable_valid(header, ape))
+ if (!ape->probe_subtbl(header, end))
+ acpi_probe_count++;
+
+ return 0;
+}
+
+int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr)
+{
+ int count = 0;
+
+ if (acpi_disabled)
+ return 0;
+
+ spin_lock(&acpi_probe_lock);
+ for (ape = ap_head; nr; ape++, nr--) {
+ if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) {
+ acpi_probe_count = 0;
+ acpi_table_parse_madt(ape->type, acpi_match_madt, 0);
+ count += acpi_probe_count;
+ } else {
+ int res;
+ res = acpi_table_parse(ape->id, ape->probe_table);
+ if (!res)
+ count++;
+ }
+ }
+ spin_unlock(&acpi_probe_lock);
+
+ return count;
+}
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 2f0d4db40a9e..0d94621dc856 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -487,6 +487,8 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
pr_err("ACPI does not support sleep state S%u\n", acpi_state);
return -ENOSYS;
}
+ if (acpi_state > ACPI_STATE_S1)
+ pm_set_suspend_via_firmware();
acpi_pm_start(acpi_state);
return 0;
@@ -522,6 +524,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
if (error)
return error;
pr_info(PREFIX "Low-level resume complete\n");
+ pm_set_resume_via_firmware();
break;
}
trace_suspend_resume(TPS("acpi_suspend"), acpi_state, false);
@@ -632,14 +635,16 @@ static int acpi_freeze_prepare(void)
acpi_enable_wakeup_devices(ACPI_STATE_S0);
acpi_enable_all_wakeup_gpes();
acpi_os_wait_events_complete();
- enable_irq_wake(acpi_gbl_FADT.sci_interrupt);
+ if (acpi_sci_irq_valid())
+ enable_irq_wake(acpi_sci_irq);
return 0;
}
static void acpi_freeze_restore(void)
{
acpi_disable_wakeup_devices(ACPI_STATE_S0);
- disable_irq_wake(acpi_gbl_FADT.sci_interrupt);
+ if (acpi_sci_irq_valid())
+ disable_irq_wake(acpi_sci_irq);
acpi_enable_all_runtime_gpes();
}
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 40a42655227c..0243d375c6fd 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -878,6 +878,9 @@ int __init acpi_sysfs_init(void)
return result;
hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
+ if (!hotplug_kobj)
+ return -ENOMEM;
+
result = sysfs_create_file(hotplug_kobj, &force_remove_attr.attr);
if (result)
return result;
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 17a6fa01a338..6c0f0794aa82 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -210,20 +210,39 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
}
-int __init
-acpi_parse_entries(char *id, unsigned long table_size,
- acpi_tbl_entry_handler handler,
+/**
+ * acpi_parse_entries_array - for each proc_num find a suitable subtable
+ *
+ * @id: table id (for debugging purposes)
+ * @table_size: single entry size
+ * @table_header: where does the table start?
+ * @proc: array of acpi_subtable_proc struct containing entry id
+ * and associated handler with it
+ * @proc_num: how big proc is?
+ * @max_entries: how many entries can we process?
+ *
+ * For each proc_num find a subtable with proc->id and run proc->handler
+ * on it. Assumption is that there's only single handler for particular
+ * entry id.
+ *
+ * On success returns sum of all matching entries for all proc handlers.
+ * Otherwise, -ENODEV or -EINVAL is returned.
+ */
+static int __init
+acpi_parse_entries_array(char *id, unsigned long table_size,
struct acpi_table_header *table_header,
- int entry_id, unsigned int max_entries)
+ struct acpi_subtable_proc *proc, int proc_num,
+ unsigned int max_entries)
{
struct acpi_subtable_header *entry;
- int count = 0;
unsigned long table_end;
+ int count = 0;
+ int i;
if (acpi_disabled)
return -ENODEV;
- if (!id || !handler)
+ if (!id)
return -EINVAL;
if (!table_size)
@@ -243,20 +262,28 @@ acpi_parse_entries(char *id, unsigned long table_size,
while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
table_end) {
- if (entry->type == entry_id
- && (!max_entries || count < max_entries)) {
- if (handler(entry, table_end))
+ if (max_entries && count >= max_entries)
+ break;
+
+ for (i = 0; i < proc_num; i++) {
+ if (entry->type != proc[i].id)
+ continue;
+ if (!proc[i].handler ||
+ proc[i].handler(entry, table_end))
return -EINVAL;
- count++;
+ proc->count++;
+ break;
}
+ if (i != proc_num)
+ count++;
/*
* If entry->length is 0, break from this loop to avoid
* infinite loop.
*/
if (entry->length == 0) {
- pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
+ pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
return -EINVAL;
}
@@ -266,17 +293,32 @@ acpi_parse_entries(char *id, unsigned long table_size,
if (max_entries && count > max_entries) {
pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n",
- id, entry_id, count - max_entries, count);
+ id, proc->id, count - max_entries, count);
}
return count;
}
int __init
-acpi_table_parse_entries(char *id,
+acpi_parse_entries(char *id,
+ unsigned long table_size,
+ acpi_tbl_entry_handler handler,
+ struct acpi_table_header *table_header,
+ int entry_id, unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ };
+
+ return acpi_parse_entries_array(id, table_size, table_header,
+ &proc, 1, max_entries);
+}
+
+int __init
+acpi_table_parse_entries_array(char *id,
unsigned long table_size,
- int entry_id,
- acpi_tbl_entry_handler handler,
+ struct acpi_subtable_proc *proc, int proc_num,
unsigned int max_entries)
{
struct acpi_table_header *table_header = NULL;
@@ -287,7 +329,7 @@ acpi_table_parse_entries(char *id,
if (acpi_disabled)
return -ENODEV;
- if (!id || !handler)
+ if (!id)
return -EINVAL;
if (!strncmp(id, ACPI_SIG_MADT, 4))
@@ -299,14 +341,30 @@ acpi_table_parse_entries(char *id,
return -ENODEV;
}
- count = acpi_parse_entries(id, table_size, handler, table_header,
- entry_id, max_entries);
+ count = acpi_parse_entries_array(id, table_size, table_header,
+ proc, proc_num, max_entries);
early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return count;
}
int __init
+acpi_table_parse_entries(char *id,
+ unsigned long table_size,
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ };
+
+ return acpi_table_parse_entries_array(id, table_size, &proc, 1,
+ max_entries);
+}
+
+int __init
acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler, unsigned int max_entries)
{
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 30d8518b25fb..82707f9824ca 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -315,7 +315,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (crt == -1) {
tz->trips.critical.flags.valid = 0;
} else if (crt > 0) {
- unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
+ unsigned long crt_k = CELSIUS_TO_DECI_KELVIN(crt);
/*
* Allow override critical threshold
*/
@@ -351,7 +351,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (psv == -1) {
status = AE_SUPPORT;
} else if (psv > 0) {
- tmp = CELSIUS_TO_KELVIN(psv);
+ tmp = CELSIUS_TO_DECI_KELVIN(psv);
status = AE_OK;
} else {
status = acpi_evaluate_integer(tz->device->handle,
@@ -431,7 +431,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
break;
if (i == 1)
tz->trips.active[0].temperature =
- CELSIUS_TO_KELVIN(act);
+ CELSIUS_TO_DECI_KELVIN(act);
else
/*
* Don't allow override higher than
@@ -439,9 +439,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
*/
tz->trips.active[i - 1].temperature =
(tz->trips.active[i - 2].temperature <
- CELSIUS_TO_KELVIN(act) ?
+ CELSIUS_TO_DECI_KELVIN(act) ?
tz->trips.active[i - 2].temperature :
- CELSIUS_TO_KELVIN(act));
+ CELSIUS_TO_DECI_KELVIN(act));
break;
} else {
tz->trips.active[i].temperature = tmp;
@@ -1105,7 +1105,7 @@ static int acpi_thermal_add(struct acpi_device *device)
INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
- acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
+ acpi_device_bid(device), DECI_KELVIN_TO_CELSIUS(tz->temperature));
goto end;
free_memory:
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 2922f1f252d5..daaf1c4e1e0f 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -233,6 +233,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
{
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
+ .callback = video_detect_force_video,
+ .ident = "Dell XPS14 L421X",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+ },
+ },
+ {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
.callback = video_detect_force_video,
.ident = "Dell XPS15 L521X",
@@ -244,6 +253,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
/* Non win8 machines which need native backlight nevertheless */
{
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1201530 */
+ .callback = video_detect_force_native,
+ .ident = "Lenovo Ideapad S405",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
+ },
+ },
+ {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
.callback = video_detect_force_native,
.ident = "Lenovo Ideapad Z570",
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 15e40ee62a94..6aaa3f81755b 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -175,6 +175,15 @@ config AHCI_XGENE
help
This option enables support for APM X-Gene SoC SATA host controller.
+config AHCI_QORIQ
+ tristate "Freescale QorIQ AHCI SATA support"
+ depends on OF
+ help
+ This option enables support for the Freescale QorIQ AHCI SoC's
+ onboard AHCI SATA.
+
+ If unsure, say N.
+
config SATA_FSL
tristate "Freescale 3.0Gbps SATA support"
depends on FSL_SOC
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index af70919f7dde..af45effac18c 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_TEGRA) += ahci_tegra.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_XGENE) += ahci_xgene.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_QORIQ) += ahci_qoriq.o libahci.o libahci_platform.o
# SFF w/ custom DMA
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index a46660204e3a..ff02bb4218fc 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -314,6 +314,16 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
@@ -489,6 +499,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
.driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
.driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */
+ .driver_data = board_ahci_yes_fbs },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
.driver_data = board_ahci_yes_fbs },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 5b8e8a0fab48..45586c1dbbdc 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -181,6 +181,8 @@ enum {
PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */
+ PORT_CMD_ESP = (1 << 21), /* External Sata Port */
+ PORT_CMD_HPCP = (1 << 18), /* HotPlug Capable Port */
PORT_CMD_PMP = (1 << 17), /* PMP attached */
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 1befb114c384..04975b851c23 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -76,7 +76,6 @@ static const struct of_device_id ahci_of_match[] = {
{ .compatible = "ibm,476gtr-ahci", },
{ .compatible = "snps,dwc-ahci", },
{ .compatible = "hisilicon,hisi-ahci", },
- { .compatible = "fsl,qoriq-ahci", },
{},
};
MODULE_DEVICE_TABLE(of, ahci_of_match);
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
new file mode 100644
index 000000000000..d0f9de96e4ea
--- /dev/null
+++ b/drivers/ata/ahci_qoriq.c
@@ -0,0 +1,279 @@
+/*
+ * Freescale QorIQ AHCI SATA platform driver
+ *
+ * Copyright 2015 Freescale, Inc.
+ * Tang Yuantian <Yuantian.Tang@freescale.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, or (at your option)
+ * any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/ahci_platform.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/libata.h>
+#include "ahci.h"
+
+#define DRV_NAME "ahci-qoriq"
+
+/* port register definition */
+#define PORT_PHY1 0xA8
+#define PORT_PHY2 0xAC
+#define PORT_PHY3 0xB0
+#define PORT_PHY4 0xB4
+#define PORT_PHY5 0xB8
+#define PORT_TRANS 0xC8
+
+/* port register default value */
+#define AHCI_PORT_PHY_1_CFG 0xa003fffe
+#define AHCI_PORT_PHY_2_CFG 0x28183411
+#define AHCI_PORT_PHY_3_CFG 0x0e081004
+#define AHCI_PORT_PHY_4_CFG 0x00480811
+#define AHCI_PORT_PHY_5_CFG 0x192c96a4
+#define AHCI_PORT_TRANS_CFG 0x08000025
+
+#define SATA_ECC_DISABLE 0x00020000
+
+enum ahci_qoriq_type {
+ AHCI_LS1021A,
+ AHCI_LS1043A,
+ AHCI_LS2080A,
+};
+
+struct ahci_qoriq_priv {
+ struct ccsr_ahci *reg_base;
+ enum ahci_qoriq_type type;
+ void __iomem *ecc_addr;
+};
+
+static const struct of_device_id ahci_qoriq_of_match[] = {
+ { .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A},
+ { .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
+ { .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
+ {},
+};
+MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
+
+static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+ void __iomem *port_mmio = ahci_port_base(link->ap);
+ u32 px_cmd, px_is, px_val;
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_qoriq_priv *qoriq_priv = hpriv->plat_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
+ bool online;
+ int rc;
+ bool ls1021a_workaround = (qoriq_priv->type == AHCI_LS1021A);
+
+ DPRINTK("ENTER\n");
+
+ ahci_stop_engine(ap);
+
+ /*
+ * There is a errata on ls1021a Rev1.0 and Rev2.0 which is:
+ * A-009042: The device detection initialization sequence
+ * mistakenly resets some registers.
+ *
+ * Workaround for this is:
+ * The software should read and store PxCMD and PxIS values
+ * before issuing the device detection initialization sequence.
+ * After the sequence is complete, software should restore the
+ * PxCMD and PxIS with the stored values.
+ */
+ if (ls1021a_workaround) {
+ px_cmd = readl(port_mmio + PORT_CMD);
+ px_is = readl(port_mmio + PORT_IRQ_STAT);
+ }
+
+ /* clear D2H reception area to properly wait for D2H FIS */
+ ata_tf_init(link->device, &tf);
+ tf.command = ATA_BUSY;
+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+ rc = sata_link_hardreset(link, timing, deadline, &online,
+ ahci_check_ready);
+
+ /* restore the PxCMD and PxIS on ls1021 */
+ if (ls1021a_workaround) {
+ px_val = readl(port_mmio + PORT_CMD);
+ if (px_val != px_cmd)
+ writel(px_cmd, port_mmio + PORT_CMD);
+
+ px_val = readl(port_mmio + PORT_IRQ_STAT);
+ if (px_val != px_is)
+ writel(px_is, port_mmio + PORT_IRQ_STAT);
+ }
+
+ hpriv->start_engine(ap);
+
+ if (online)
+ *class = ahci_dev_classify(ap);
+
+ DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+ return rc;
+}
+
+static struct ata_port_operations ahci_qoriq_ops = {
+ .inherits = &ahci_ops,
+ .hardreset = ahci_qoriq_hardreset,
+};
+
+static struct ata_port_info ahci_qoriq_port_info = {
+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_qoriq_ops,
+};
+
+static struct scsi_host_template ahci_qoriq_sht = {
+ AHCI_SHT(DRV_NAME),
+};
+
+static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
+{
+ struct ahci_qoriq_priv *qpriv = hpriv->plat_data;
+ void __iomem *reg_base = hpriv->mmio;
+
+ switch (qpriv->type) {
+ case AHCI_LS1021A:
+ writel(SATA_ECC_DISABLE, qpriv->ecc_addr);
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ writel(AHCI_PORT_PHY_2_CFG, reg_base + PORT_PHY2);
+ writel(AHCI_PORT_PHY_3_CFG, reg_base + PORT_PHY3);
+ writel(AHCI_PORT_PHY_4_CFG, reg_base + PORT_PHY4);
+ writel(AHCI_PORT_PHY_5_CFG, reg_base + PORT_PHY5);
+ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+ break;
+
+ case AHCI_LS1043A:
+ case AHCI_LS2080A:
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ break;
+ }
+
+ return 0;
+}
+
+static int ahci_qoriq_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct ahci_host_priv *hpriv;
+ struct ahci_qoriq_priv *qoriq_priv;
+ const struct of_device_id *of_id;
+ struct resource *res;
+ int rc;
+
+ hpriv = ahci_platform_get_resources(pdev);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+ of_id = of_match_node(ahci_qoriq_of_match, np);
+ if (!of_id)
+ return -ENODEV;
+
+ qoriq_priv = devm_kzalloc(dev, sizeof(*qoriq_priv), GFP_KERNEL);
+ if (!qoriq_priv)
+ return -ENOMEM;
+
+ qoriq_priv->type = (enum ahci_qoriq_type)of_id->data;
+
+ if (qoriq_priv->type == AHCI_LS1021A) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "sata-ecc");
+ qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(qoriq_priv->ecc_addr))
+ return PTR_ERR(qoriq_priv->ecc_addr);
+ }
+
+ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+ hpriv->plat_data = qoriq_priv;
+ rc = ahci_qoriq_phy_init(hpriv);
+ if (rc)
+ goto disable_resources;
+
+ /* Workaround for ls2080a */
+ if (qoriq_priv->type == AHCI_LS2080A) {
+ hpriv->flags |= AHCI_HFLAG_NO_NCQ;
+ ahci_qoriq_port_info.flags &= ~ATA_FLAG_NCQ;
+ }
+
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_qoriq_port_info,
+ &ahci_qoriq_sht);
+ if (rc)
+ goto disable_resources;
+
+ return 0;
+
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
+
+ return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ahci_qoriq_resume(struct device *dev)
+{
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
+ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+ rc = ahci_qoriq_phy_init(hpriv);
+ if (rc)
+ goto disable_resources;
+
+ rc = ahci_platform_resume_host(dev);
+ if (rc)
+ goto disable_resources;
+
+ /* We resumed so update PM runtime state */
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
+
+ return rc;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend,
+ ahci_qoriq_resume);
+
+static struct platform_driver ahci_qoriq_driver = {
+ .probe = ahci_qoriq_probe,
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = ahci_qoriq_of_match,
+ .pm = &ahci_qoriq_pm_ops,
+ },
+};
+module_platform_driver(ahci_qoriq_driver);
+
+MODULE_DESCRIPTION("Freescale QorIQ AHCI SATA platform driver");
+MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index d256a66158be..096064cd6c52 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1117,6 +1117,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
int port_no, void __iomem *mmio,
void __iomem *port_mmio)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
const char *emsg = NULL;
int rc;
u32 tmp;
@@ -1138,6 +1139,12 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
writel(tmp, port_mmio + PORT_IRQ_STAT);
writel(1 << port_no, mmio + HOST_IRQ_STAT);
+
+ /* mark esata ports */
+ tmp = readl(port_mmio + PORT_CMD);
+ if ((tmp & PORT_CMD_HPCP) ||
+ ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
+ ap->pflags |= ATA_PFLAG_EXTERNAL;
}
void ahci_init_controller(struct ata_host *host)
@@ -2486,28 +2493,13 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq,
rc = devm_request_threaded_irq(host->dev, irq + i,
ahci_multi_irqs_intr,
- ahci_port_thread_fn, IRQF_SHARED,
+ ahci_port_thread_fn, 0,
pp->irq_desc, host->ports[i]);
if (rc)
- goto out_free_irqs;
- }
-
- for (i = 0; i < host->n_ports; i++)
+ return rc;
ata_port_desc(host->ports[i], "irq %d", irq + i);
-
- rc = ata_host_register(host, sht);
- if (rc)
- goto out_free_all_irqs;
-
- return 0;
-
-out_free_all_irqs:
- i = host->n_ports;
-out_free_irqs:
- for (i--; i >= 0; i--)
- devm_free_irq(host->dev, irq + i, host->ports[i]);
-
- return rc;
+ }
+ return ata_host_register(host, sht);
}
/**
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 0d7f0da3a269..7e959f90c020 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1757,6 +1757,15 @@ nothing_to_do:
return 1;
}
+static void ata_qc_done(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ void (*done)(struct scsi_cmnd *) = qc->scsidone;
+
+ ata_qc_free(qc);
+ done(cmd);
+}
+
static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@@ -1774,28 +1783,17 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
*/
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
- ((cdb[2] & 0x20) || need_sense)) {
+ ((cdb[2] & 0x20) || need_sense))
ata_gen_passthru_sense(qc);
- } else {
- if (!need_sense) {
- cmd->result = SAM_STAT_GOOD;
- } else {
- /* TODO: decide which descriptor format to use
- * for 48b LBA devices and call that here
- * instead of the fixed desc, which is only
- * good for smaller LBA (and maybe CHS?)
- * devices.
- */
- ata_gen_ata_sense(qc);
- }
- }
+ else if (need_sense)
+ ata_gen_ata_sense(qc);
+ else
+ cmd->result = SAM_STAT_GOOD;
if (need_sense && !ap->ops->error_handler)
ata_dump_status(ap->print_id, &qc->result_tf);
- qc->scsidone(cmd);
-
- ata_qc_free(qc);
+ ata_qc_done(qc);
}
/**
@@ -2015,8 +2013,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
VPRINTK("ENTER\n");
- /* set scsi removable (RMB) bit per ata bit */
- if (ata_id_removable(args->id))
+ /* set scsi removable (RMB) bit per ata bit, or if the
+ * AHCI port says it's external (Hotplug-capable, eSATA).
+ */
+ if (ata_id_removable(args->id) ||
+ (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL))
hdr[1] |= (1 << 7);
if (args->dev->class == ATA_DEV_ZAC) {
@@ -2594,8 +2595,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc)
ata_gen_passthru_sense(qc);
}
- qc->scsidone(qc->scsicmd);
- ata_qc_free(qc);
+ ata_qc_done(qc);
}
/* is it pointless to prefer PIO for "safety reasons"? */
@@ -2690,8 +2690,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
qc->dev->sdev->locked = 0;
qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
- qc->scsidone(cmd);
- ata_qc_free(qc);
+ ata_qc_done(qc);
return;
}
@@ -2735,8 +2734,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
cmd->result = SAM_STAT_GOOD;
}
- qc->scsidone(cmd);
- ata_qc_free(qc);
+ ata_qc_done(qc);
}
/**
* atapi_xlat - Initialize PACKET taskfile
@@ -2914,12 +2912,14 @@ ata_scsi_map_proto(u8 byte1)
case 5: /* PIO Data-out */
return ATA_PROT_PIO;
+ case 12: /* FPDMA */
+ return ATA_PROT_NCQ;
+
case 0: /* Hard Reset */
case 1: /* SRST */
case 8: /* Device Diagnostic */
case 9: /* Device Reset */
case 7: /* DMA Queued */
- case 12: /* FPDMA */
case 15: /* Return Response Info */
default: /* Reserved */
break;
@@ -2947,6 +2947,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
goto invalid_fld;
+ /* enable LBA */
+ tf->flags |= ATA_TFLAG_LBA;
+
/*
* 12 and 16 byte CDBs use different offsets to
* provide the various register values.
@@ -2992,6 +2995,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->command = cdb[9];
}
+ /* For NCQ commands with FPDMA protocol, copy the tag value */
+ if (tf->protocol == ATA_PROT_NCQ)
+ tf->nsect = qc->tag << 3;
+
/* enforce correct master/slave bit */
tf->device = dev->devno ?
tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
@@ -3689,9 +3696,6 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
*/
shost->max_host_blocked = 1;
- if (scsi_init_shared_tag_map(shost, host->n_tags))
- goto err_add;
-
rc = scsi_add_host_with_dma(ap->scsi_host,
&ap->tdev, ap->host->dev);
if (rc)
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index a5088ecb349f..7a21edf89e72 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -604,9 +604,9 @@ static void it821x_display_disk(int n, u8 *buf)
{
unsigned char id[41];
int mode = 0;
- char *mtype = "";
+ const char *mtype = "";
char mbuf[8];
- char *cbl = "(40 wire cable)";
+ const char *cbl = "(40 wire cable)";
static const char *types[5] = {
"RAID0", "RAID1", "RAID 0+1", "JBOD", "DISK"
@@ -903,7 +903,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
};
const struct ata_port_info *ppi[] = { NULL, NULL };
- static char *mode[2] = { "pass through", "smart" };
+ static const char *mode[2] = { "pass through", "smart" };
int rc;
rc = pcim_enable_device(pdev);
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index b0028588ff1c..e3d4b059fcd1 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -1344,6 +1344,7 @@ static struct of_device_id pata_macio_match[] =
},
{},
};
+MODULE_DEVICE_TABLE(of, pata_macio_match);
static struct macio_driver pata_macio_driver =
{
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index c36b3e6531d8..f6c46e9a4dc0 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -24,79 +24,36 @@
#include <linux/ata.h>
#include <linux/libata.h>
#include <linux/platform_device.h>
+#include <linux/dmaengine.h>
+#include <linux/dma/pxa-dma.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <scsi/scsi_host.h>
-#include <mach/pxa2xx-regs.h>
#include <linux/platform_data/ata-pxa.h>
-#include <mach/dma.h>
#define DRV_NAME "pata_pxa"
#define DRV_VERSION "0.1"
struct pata_pxa_data {
- uint32_t dma_channel;
- struct pxa_dma_desc *dma_desc;
- dma_addr_t dma_desc_addr;
- uint32_t dma_desc_id;
-
- /* DMA IO physical address */
- uint32_t dma_io_addr;
- /* PXA DREQ<0:2> pin selector */
- uint32_t dma_dreq;
- /* DMA DCSR register value */
- uint32_t dma_dcsr;
-
+ struct dma_chan *dma_chan;
+ dma_cookie_t dma_cookie;
struct completion dma_done;
};
/*
- * Setup the DMA descriptors. The size is transfer capped at 4k per descriptor,
- * if the transfer is longer, it is split into multiple chained descriptors.
+ * DMA interrupt handler.
*/
-static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc)
+static void pxa_ata_dma_irq(void *d)
{
- struct pata_pxa_data *pd = qc->ap->private_data;
-
- uint32_t cpu_len, seg_len;
- dma_addr_t cpu_addr;
-
- cpu_addr = sg_dma_address(sg);
- cpu_len = sg_dma_len(sg);
-
- do {
- seg_len = (cpu_len > 0x1000) ? 0x1000 : cpu_len;
-
- pd->dma_desc[pd->dma_desc_id].ddadr = pd->dma_desc_addr +
- ((pd->dma_desc_id + 1) * sizeof(struct pxa_dma_desc));
-
- pd->dma_desc[pd->dma_desc_id].dcmd = DCMD_BURST32 |
- DCMD_WIDTH2 | (DCMD_LENGTH & seg_len);
-
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
- pd->dma_desc[pd->dma_desc_id].dsadr = cpu_addr;
- pd->dma_desc[pd->dma_desc_id].dtadr = pd->dma_io_addr;
- pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCSRCADDR |
- DCMD_FLOWTRG;
- } else {
- pd->dma_desc[pd->dma_desc_id].dsadr = pd->dma_io_addr;
- pd->dma_desc[pd->dma_desc_id].dtadr = cpu_addr;
- pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCTRGADDR |
- DCMD_FLOWSRC;
- }
-
- cpu_len -= seg_len;
- cpu_addr += seg_len;
- pd->dma_desc_id++;
+ struct pata_pxa_data *pd = d;
+ enum dma_status status;
- } while (cpu_len);
-
- /* Should not happen */
- if (seg_len & 0x1f)
- DALGN |= (1 << pd->dma_dreq);
+ status = dmaengine_tx_status(pd->dma_chan, pd->dma_cookie, NULL);
+ if (status == DMA_ERROR || status == DMA_COMPLETE)
+ complete(&pd->dma_done);
}
/*
@@ -105,28 +62,22 @@ static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc)
static void pxa_qc_prep(struct ata_queued_cmd *qc)
{
struct pata_pxa_data *pd = qc->ap->private_data;
- int si = 0;
- struct scatterlist *sg;
+ struct dma_async_tx_descriptor *tx;
+ enum dma_transfer_direction dir;
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
- pd->dma_desc_id = 0;
-
- DCSR(pd->dma_channel) = 0;
- DALGN &= ~(1 << pd->dma_dreq);
-
- for_each_sg(qc->sg, sg, qc->n_elem, si)
- pxa_load_dmac(sg, qc);
-
- pd->dma_desc[pd->dma_desc_id - 1].ddadr = DDADR_STOP;
-
- /* Fire IRQ only at the end of last block */
- pd->dma_desc[pd->dma_desc_id - 1].dcmd |= DCMD_ENDIRQEN;
-
- DDADR(pd->dma_channel) = pd->dma_desc_addr;
- DRCMR(pd->dma_dreq) = DRCMR_MAPVLD | pd->dma_channel;
-
+ dir = (qc->dma_dir == DMA_TO_DEVICE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
+ tx = dmaengine_prep_slave_sg(pd->dma_chan, qc->sg, qc->n_elem, dir,
+ DMA_PREP_INTERRUPT);
+ if (!tx) {
+ ata_dev_err(qc->dev, "prep_slave_sg() failed\n");
+ return;
+ }
+ tx->callback = pxa_ata_dma_irq;
+ tx->callback_param = pd;
+ pd->dma_cookie = dmaengine_submit(tx);
}
/*
@@ -145,7 +96,7 @@ static void pxa_bmdma_start(struct ata_queued_cmd *qc)
{
struct pata_pxa_data *pd = qc->ap->private_data;
init_completion(&pd->dma_done);
- DCSR(pd->dma_channel) = DCSR_RUN;
+ dma_async_issue_pending(pd->dma_chan);
}
/*
@@ -154,12 +105,14 @@ static void pxa_bmdma_start(struct ata_queued_cmd *qc)
static void pxa_bmdma_stop(struct ata_queued_cmd *qc)
{
struct pata_pxa_data *pd = qc->ap->private_data;
+ enum dma_status status;
- if ((DCSR(pd->dma_channel) & DCSR_RUN) &&
- wait_for_completion_timeout(&pd->dma_done, HZ))
- dev_err(qc->ap->dev, "Timeout waiting for DMA completion!");
+ status = dmaengine_tx_status(pd->dma_chan, pd->dma_cookie, NULL);
+ if (status != DMA_ERROR && status != DMA_COMPLETE &&
+ wait_for_completion_timeout(&pd->dma_done, HZ))
+ ata_dev_err(qc->dev, "Timeout waiting for DMA completion!");
- DCSR(pd->dma_channel) = 0;
+ dmaengine_terminate_all(pd->dma_chan);
}
/*
@@ -170,8 +123,11 @@ static unsigned char pxa_bmdma_status(struct ata_port *ap)
{
struct pata_pxa_data *pd = ap->private_data;
unsigned char ret = ATA_DMA_INTR;
+ struct dma_tx_state state;
+ enum dma_status status;
- if (pd->dma_dcsr & DCSR_BUSERR)
+ status = dmaengine_tx_status(pd->dma_chan, pd->dma_cookie, &state);
+ if (status != DMA_COMPLETE)
ret |= ATA_DMA_ERR;
return ret;
@@ -213,21 +169,6 @@ static struct ata_port_operations pxa_ata_port_ops = {
.qc_prep = pxa_qc_prep,
};
-/*
- * DMA interrupt handler.
- */
-static void pxa_ata_dma_irq(int dma, void *port)
-{
- struct ata_port *ap = port;
- struct pata_pxa_data *pd = ap->private_data;
-
- pd->dma_dcsr = DCSR(dma);
- DCSR(dma) = pd->dma_dcsr;
-
- if (pd->dma_dcsr & DCSR_STOPSTATE)
- complete(&pd->dma_done);
-}
-
static int pxa_ata_probe(struct platform_device *pdev)
{
struct ata_host *host;
@@ -238,6 +179,9 @@ static int pxa_ata_probe(struct platform_device *pdev)
struct resource *dma_res;
struct resource *irq_res;
struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev);
+ struct dma_slave_config config;
+ dma_cap_mask_t mask;
+ struct pxad_param param;
int ret = 0;
/*
@@ -333,29 +277,32 @@ static int pxa_ata_probe(struct platform_device *pdev)
return -ENOMEM;
ap->private_data = data;
- data->dma_dreq = pdata->dma_dreq;
- data->dma_io_addr = dma_res->start;
- /*
- * Allocate space for the DMA descriptors
- */
- data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE,
- &data->dma_desc_addr, GFP_KERNEL);
- if (!data->dma_desc)
- return -EINVAL;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ param.prio = PXAD_PRIO_LOWEST;
+ param.drcmr = pdata->dma_dreq;
+ memset(&config, 0, sizeof(config));
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ config.src_addr = dma_res->start;
+ config.dst_addr = dma_res->start;
+ config.src_maxburst = 32;
+ config.dst_maxburst = 32;
/*
* Request the DMA channel
*/
- data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW,
- pxa_ata_dma_irq, ap);
- if (data->dma_channel < 0)
+ data->dma_chan =
+ dma_request_slave_channel_compat(mask, pxad_filter_fn,
+ &param, &pdev->dev, "data");
+ if (!data->dma_chan)
return -EBUSY;
-
- /*
- * Stop and clear the DMA channel
- */
- DCSR(data->dma_channel) = 0;
+ ret = dmaengine_slave_config(data->dma_chan, &config);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "dma configuration failed: %d\n", ret);
+ return ret;
+ }
/*
* Activate the ATA host
@@ -363,7 +310,7 @@ static int pxa_ata_probe(struct platform_device *pdev)
ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt,
pdata->irq_flags, &pxa_ata_sht);
if (ret)
- pxa_free_dma(data->dma_channel);
+ dma_release_channel(data->dma_chan);
return ret;
}
@@ -373,7 +320,7 @@ static int pxa_ata_remove(struct platform_device *pdev)
struct ata_host *host = platform_get_drvdata(pdev);
struct pata_pxa_data *data = host->ports[0]->private_data;
- pxa_free_dma(data->dma_channel);
+ dma_release_channel(data->dma_chan);
ata_host_detach(host);
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index cbb5a471eb9d..f6facd686f94 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -70,7 +70,7 @@ struct s3c_ide_info {
struct clk *clk;
void __iomem *ide_addr;
void __iomem *sfr_addr;
- unsigned int irq;
+ int irq;
enum s3c_cpu_type cpu_type;
unsigned int fifo_status_reg;
};
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 65e65903faa0..7d00f2994738 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -112,7 +112,8 @@ static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data)
static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {
IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry) return -1;
+ if (!entry)
+ return -ENOMEM;
entry->data = data;
entry->next = NULL;
if (que->next == NULL)
@@ -1175,7 +1176,7 @@ static int rx_pkt(struct atm_dev *dev)
if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) {
if (vcc->vci < 32)
printk("Drop control packets\n");
- goto out_free_desc;
+ goto out_free_desc;
}
skb_put(skb,len);
// pwang_test
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 6e810881e48b..71059e32bebc 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -406,7 +406,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
*
* Note, you will need to drop the reference with put_device() after use.
*
- * @fn is allowed to do anything including calling back into class
+ * @match is allowed to do anything including calling back into class
* code. There's no locking restriction.
*/
struct device *class_find_device(struct class *class, struct device *start,
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 334ec7ef1960..b7d56c5ea3c6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1066,7 +1066,7 @@ int device_add(struct device *dev)
dev->kobj.parent = kobj;
/* use parent numa_node */
- if (parent)
+ if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
set_dev_node(dev, dev_to_node(parent));
/* first, register with generic layer. */
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index be0eb4639128..a641cf3ccad6 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -322,6 +322,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
goto probe_failed;
}
+ pinctrl_init_done(dev);
+
if (dev->pm_domain && dev->pm_domain->sync)
dev->pm_domain->sync(dev);
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 875464690117..8fc654f0807b 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -82,12 +82,12 @@ static struct devres_group * node_to_group(struct devres_node *node)
}
static __always_inline struct devres * alloc_dr(dr_release_t release,
- size_t size, gfp_t gfp)
+ size_t size, gfp_t gfp, int nid)
{
size_t tot_size = sizeof(struct devres) + size;
struct devres *dr;
- dr = kmalloc_track_caller(tot_size, gfp);
+ dr = kmalloc_node_track_caller(tot_size, gfp, nid);
if (unlikely(!dr))
return NULL;
@@ -106,24 +106,25 @@ static void add_dr(struct device *dev, struct devres_node *node)
}
#ifdef CONFIG_DEBUG_DEVRES
-void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+void * __devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid,
const char *name)
{
struct devres *dr;
- dr = alloc_dr(release, size, gfp | __GFP_ZERO);
+ dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid);
if (unlikely(!dr))
return NULL;
set_node_dbginfo(&dr->node, name, size);
return dr->data;
}
-EXPORT_SYMBOL_GPL(__devres_alloc);
+EXPORT_SYMBOL_GPL(__devres_alloc_node);
#else
/**
* devres_alloc - Allocate device resource data
* @release: Release function devres will be associated with
* @size: Allocation size
* @gfp: Allocation flags
+ * @nid: NUMA node
*
* Allocate devres of @size bytes. The allocated area is zeroed, then
* associated with @release. The returned pointer can be passed to
@@ -132,16 +133,16 @@ EXPORT_SYMBOL_GPL(__devres_alloc);
* RETURNS:
* Pointer to allocated devres on success, NULL on failure.
*/
-void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+void * devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid)
{
struct devres *dr;
- dr = alloc_dr(release, size, gfp | __GFP_ZERO);
+ dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid);
if (unlikely(!dr))
return NULL;
return dr->data;
}
-EXPORT_SYMBOL_GPL(devres_alloc);
+EXPORT_SYMBOL_GPL(devres_alloc_node);
#endif
/**
@@ -776,7 +777,7 @@ void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
struct devres *dr;
/* use raw alloc_dr for kmalloc caller tracing */
- dr = alloc_dr(devm_kmalloc_release, size, gfp);
+ dr = alloc_dr(devm_kmalloc_release, size, gfp, dev_to_node(dev));
if (unlikely(!dr))
return NULL;
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 950fff9ce453..e167a1e1bccb 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -46,7 +46,7 @@ struct cma *dma_contiguous_default_area;
* Users, who want to set the size of global CMA area for their system
* should use cma= kernel parameter.
*/
-static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M;
+static const phys_addr_t size_bytes = (phys_addr_t)CMA_SIZE_MBYTES * SZ_1M;
static phys_addr_t size_cmdline = -1;
static phys_addr_t base_cmdline;
static phys_addr_t limit_cmdline;
@@ -187,7 +187,7 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
* global one. Requires architecture specific dev_get_cma_area() helper
* function.
*/
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
unsigned int align)
{
if (align > CONFIG_CMA_ALIGNMENT)
diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
index 5fb74b43848e..076297592754 100644
--- a/drivers/base/pinctrl.c
+++ b/drivers/base/pinctrl.c
@@ -42,9 +42,20 @@ int pinctrl_bind_pins(struct device *dev)
goto cleanup_get;
}
- ret = pinctrl_select_state(dev->pins->p, dev->pins->default_state);
+ dev->pins->init_state = pinctrl_lookup_state(dev->pins->p,
+ PINCTRL_STATE_INIT);
+ if (IS_ERR(dev->pins->init_state)) {
+ /* Not supplying this state is perfectly legal */
+ dev_dbg(dev, "no init pinctrl state\n");
+
+ ret = pinctrl_select_state(dev->pins->p,
+ dev->pins->default_state);
+ } else {
+ ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state);
+ }
+
if (ret) {
- dev_dbg(dev, "failed to activate default pinctrl state\n");
+ dev_dbg(dev, "failed to activate initial pinctrl state\n");
goto cleanup_get;
}
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 134483daac25..5df4575b5ba7 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -152,7 +152,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
/**
* platform_msi_create_irq_domain - Create a platform MSI interrupt domain
- * @np: Optional device-tree node of the interrupt controller
+ * @fwnode: Optional fwnode of the interrupt controller
* @info: MSI domain info
* @parent: Parent irq domain
*
@@ -162,7 +162,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
* Returns:
* A domain pointer or NULL in case of failure.
*/
-struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
struct msi_domain_info *info,
struct irq_domain *parent)
{
@@ -173,7 +173,7 @@ struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
platform_msi_update_chip_ops(info);
- domain = msi_create_irq_domain(np, info, parent);
+ domain = msi_create_irq_domain(fwnode, info, parent);
if (domain)
domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index f80aaaf9f610..1dd6d3bf1098 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -513,7 +513,7 @@ static int platform_drv_probe(struct device *_dev)
return ret;
ret = dev_pm_domain_attach(_dev, true);
- if (ret != -EPROBE_DEFER) {
+ if (ret != -EPROBE_DEFER && drv->probe) {
ret = drv->probe(dev);
if (ret)
dev_pm_domain_detach(_dev, true);
@@ -536,9 +536,10 @@ static int platform_drv_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
- int ret;
+ int ret = 0;
- ret = drv->remove(dev);
+ if (drv->remove)
+ ret = drv->remove(dev);
dev_pm_domain_detach(_dev, true);
return ret;
@@ -549,7 +550,8 @@ static void platform_drv_shutdown(struct device *_dev)
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
- drv->shutdown(dev);
+ if (drv->shutdown)
+ drv->shutdown(dev);
dev_pm_domain_detach(_dev, true);
}
@@ -563,12 +565,9 @@ int __platform_driver_register(struct platform_driver *drv,
{
drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
- if (drv->probe)
- drv->driver.probe = platform_drv_probe;
- if (drv->remove)
- drv->driver.remove = platform_drv_remove;
- if (drv->shutdown)
- drv->driver.shutdown = platform_drv_shutdown;
+ drv->driver.probe = platform_drv_probe;
+ drv->driver.remove = platform_drv_remove;
+ drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver);
}
@@ -711,6 +710,67 @@ err_out:
}
EXPORT_SYMBOL_GPL(__platform_create_bundle);
+/**
+ * __platform_register_drivers - register an array of platform drivers
+ * @drivers: an array of drivers to register
+ * @count: the number of drivers to register
+ * @owner: module owning the drivers
+ *
+ * Registers platform drivers specified by an array. On failure to register a
+ * driver, all previously registered drivers will be unregistered. Callers of
+ * this API should use platform_unregister_drivers() to unregister drivers in
+ * the reverse order.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int __platform_register_drivers(struct platform_driver * const *drivers,
+ unsigned int count, struct module *owner)
+{
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < count; i++) {
+ pr_debug("registering platform driver %ps\n", drivers[i]);
+
+ err = __platform_driver_register(drivers[i], owner);
+ if (err < 0) {
+ pr_err("failed to register platform driver %ps: %d\n",
+ drivers[i], err);
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ while (i--) {
+ pr_debug("unregistering platform driver %ps\n", drivers[i]);
+ platform_driver_unregister(drivers[i]);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(__platform_register_drivers);
+
+/**
+ * platform_unregister_drivers - unregister an array of platform drivers
+ * @drivers: an array of drivers to unregister
+ * @count: the number of drivers to unregister
+ *
+ * Unegisters platform drivers specified by an array. This is typically used
+ * to complement an earlier call to platform_register_drivers(). Drivers are
+ * unregistered in the reverse order in which they were registered.
+ */
+void platform_unregister_drivers(struct platform_driver * const *drivers,
+ unsigned int count)
+{
+ while (count--) {
+ pr_debug("unregistering platform driver %ps\n", drivers[count]);
+ platform_driver_unregister(drivers[count]);
+ }
+}
+EXPORT_SYMBOL_GPL(platform_unregister_drivers);
+
/* modalias support enables more hands-off userspace setup:
* (a) environment variable lets new-style hotplug events work once system is
* fully running: "modprobe $MODALIAS"
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index f94a6ccfe787..5998c53280f5 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o wakeirq.o
obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
-obj-$(CONFIG_PM_OPP) += opp.o
+obj-$(CONFIG_PM_OPP) += opp/
obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o
obj-$(CONFIG_HAVE_CLK) += clock_ops.o
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 652b5a367c1f..60ee5591ee8f 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -17,7 +17,7 @@
#include <linux/err.h>
#include <linux/pm_runtime.h>
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_CLK
enum pce_status {
PCE_STATUS_NONE = 0,
@@ -93,7 +93,7 @@ static int __pm_clk_add(struct device *dev, const char *con_id,
return -ENOMEM;
}
} else {
- if (IS_ERR(clk) || !__clk_get(clk)) {
+ if (IS_ERR(clk)) {
kfree(ce);
return -ENOENT;
}
@@ -127,7 +127,9 @@ int pm_clk_add(struct device *dev, const char *con_id)
* @clk: Clock pointer
*
* Add the clock to the list of clocks used for the power management of @dev.
- * It will increment refcount on clock pointer, use clk_put() on it when done.
+ * The power-management code will take control of the clock reference, so
+ * callers should not call clk_put() on @clk after this function sucessfully
+ * returned.
*/
int pm_clk_add_clk(struct device *dev, struct clk *clk)
{
@@ -404,7 +406,7 @@ int pm_clk_runtime_resume(struct device *dev)
return pm_generic_runtime_resume(dev);
}
-#else /* !CONFIG_PM */
+#else /* !CONFIG_PM_CLK */
/**
* enable_clock - Enable a device clock.
@@ -484,7 +486,7 @@ static int pm_clk_notify(struct notifier_block *nb,
return 0;
}
-#endif /* !CONFIG_PM */
+#endif /* !CONFIG_PM_CLK */
/**
* pm_clk_add_notifier - Add bus type notifier for power management clocks.
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 16550c63d611..e03b1ad25a90 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -34,43 +34,9 @@
__ret; \
})
-#define GENPD_DEV_TIMED_CALLBACK(genpd, type, callback, dev, field, name) \
-({ \
- ktime_t __start = ktime_get(); \
- type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev); \
- s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start)); \
- struct gpd_timing_data *__td = &dev_gpd_data(dev)->td; \
- if (!__retval && __elapsed > __td->field) { \
- __td->field = __elapsed; \
- dev_dbg(dev, name " latency exceeded, new value %lld ns\n", \
- __elapsed); \
- genpd->max_off_time_changed = true; \
- __td->constraint_changed = true; \
- } \
- __retval; \
-})
-
static LIST_HEAD(gpd_list);
static DEFINE_MUTEX(gpd_list_lock);
-static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name)
-{
- struct generic_pm_domain *genpd = NULL, *gpd;
-
- if (IS_ERR_OR_NULL(domain_name))
- return NULL;
-
- mutex_lock(&gpd_list_lock);
- list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
- if (!strcmp(gpd->name, domain_name)) {
- genpd = gpd;
- break;
- }
- }
- mutex_unlock(&gpd_list_lock);
- return genpd;
-}
-
/*
* Get the generic PM domain for a particular struct device.
* This validates the struct device pointer, the PM domain pointer,
@@ -110,18 +76,12 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
{
- return GENPD_DEV_TIMED_CALLBACK(genpd, int, stop, dev,
- stop_latency_ns, "stop");
+ return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
}
-static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev,
- bool timed)
+static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
{
- if (!timed)
- return GENPD_DEV_CALLBACK(genpd, int, start, dev);
-
- return GENPD_DEV_TIMED_CALLBACK(genpd, int, start, dev,
- start_latency_ns, "start");
+ return GENPD_DEV_CALLBACK(genpd, int, start, dev);
}
static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
@@ -140,19 +100,6 @@ static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
smp_mb__after_atomic();
}
-static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd)
-{
- s64 usecs64;
-
- if (!genpd->cpuidle_data)
- return;
-
- usecs64 = genpd->power_on_latency_ns;
- do_div(usecs64, NSEC_PER_USEC);
- usecs64 += genpd->cpuidle_data->saved_exit_latency;
- genpd->cpuidle_data->idle_state->exit_latency = usecs64;
-}
-
static int genpd_power_on(struct generic_pm_domain *genpd, bool timed)
{
ktime_t time_start;
@@ -176,7 +123,6 @@ static int genpd_power_on(struct generic_pm_domain *genpd, bool timed)
genpd->power_on_latency_ns = elapsed_ns;
genpd->max_off_time_changed = true;
- genpd_recalc_cpu_exit_latency(genpd);
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
genpd->name, "on", elapsed_ns);
@@ -213,10 +159,10 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool timed)
}
/**
- * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff().
+ * genpd_queue_power_off_work - Queue up the execution of genpd_poweroff().
* @genpd: PM domait to power off.
*
- * Queue up the execution of pm_genpd_poweroff() unless it's already been done
+ * Queue up the execution of genpd_poweroff() unless it's already been done
* before.
*/
static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
@@ -224,14 +170,16 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
queue_work(pm_wq, &genpd->power_off_work);
}
+static int genpd_poweron(struct generic_pm_domain *genpd);
+
/**
- * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * __genpd_poweron - Restore power to a given PM domain and its masters.
* @genpd: PM domain to power up.
*
* Restore power to @genpd and all of its masters so that it is possible to
* resume a device belonging to it.
*/
-static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
+static int __genpd_poweron(struct generic_pm_domain *genpd)
{
struct gpd_link *link;
int ret = 0;
@@ -240,13 +188,6 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
|| (genpd->prepared_count > 0 && genpd->suspend_power_off))
return 0;
- if (genpd->cpuidle_data) {
- cpuidle_pause_and_lock();
- genpd->cpuidle_data->idle_state->disabled = true;
- cpuidle_resume_and_unlock();
- goto out;
- }
-
/*
* The list is guaranteed not to change while the loop below is being
* executed, unless one of the masters' .power_on() callbacks fiddles
@@ -255,7 +196,7 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
list_for_each_entry(link, &genpd->slave_links, slave_node) {
genpd_sd_counter_inc(link->master);
- ret = pm_genpd_poweron(link->master);
+ ret = genpd_poweron(link->master);
if (ret) {
genpd_sd_counter_dec(link->master);
goto err;
@@ -266,7 +207,6 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
if (ret)
goto err;
- out:
genpd->status = GPD_STATE_ACTIVE;
return 0;
@@ -282,46 +222,28 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
}
/**
- * pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * genpd_poweron - Restore power to a given PM domain and its masters.
* @genpd: PM domain to power up.
*/
-int pm_genpd_poweron(struct generic_pm_domain *genpd)
+static int genpd_poweron(struct generic_pm_domain *genpd)
{
int ret;
mutex_lock(&genpd->lock);
- ret = __pm_genpd_poweron(genpd);
+ ret = __genpd_poweron(genpd);
mutex_unlock(&genpd->lock);
return ret;
}
-/**
- * pm_genpd_name_poweron - Restore power to a given PM domain and its masters.
- * @domain_name: Name of the PM domain to power up.
- */
-int pm_genpd_name_poweron(const char *domain_name)
-{
- struct generic_pm_domain *genpd;
-
- genpd = pm_genpd_lookup_name(domain_name);
- return genpd ? pm_genpd_poweron(genpd) : -EINVAL;
-}
-
static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
{
- return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
- save_state_latency_ns, "state save");
+ return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
}
static int genpd_restore_dev(struct generic_pm_domain *genpd,
- struct device *dev, bool timed)
+ struct device *dev)
{
- if (!timed)
- return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
-
- return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
- restore_state_latency_ns,
- "state restore");
+ return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
}
static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
@@ -365,13 +287,14 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
}
/**
- * pm_genpd_poweroff - Remove power from a given PM domain.
+ * genpd_poweroff - Remove power from a given PM domain.
* @genpd: PM domain to power down.
+ * @is_async: PM domain is powered down from a scheduled work
*
* If all of the @genpd's devices have been suspended and all of its subdomains
* have been powered down, remove power from @genpd.
*/
-static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
+static int genpd_poweroff(struct generic_pm_domain *genpd, bool is_async)
{
struct pm_domain_data *pdd;
struct gpd_link *link;
@@ -398,12 +321,11 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
if (stat > PM_QOS_FLAGS_NONE)
return -EBUSY;
- if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
- || pdd->dev->power.irq_safe))
+ if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe)
not_suspended++;
}
- if (not_suspended > genpd->in_progress)
+ if (not_suspended > 1 || (not_suspended == 1 && is_async))
return -EBUSY;
if (genpd->gov && genpd->gov->power_down_ok) {
@@ -411,21 +333,6 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
return -EAGAIN;
}
- if (genpd->cpuidle_data) {
- /*
- * If cpuidle_data is set, cpuidle should turn the domain off
- * when the CPU in it is idle. In that case we don't decrement
- * the subdomain counts of the master domains, so that power is
- * not removed from the current domain prematurely as a result
- * of cutting off the masters' power.
- */
- genpd->status = GPD_STATE_POWER_OFF;
- cpuidle_pause_and_lock();
- genpd->cpuidle_data->idle_state->disabled = false;
- cpuidle_resume_and_unlock();
- return 0;
- }
-
if (genpd->power_off) {
int ret;
@@ -434,10 +341,10 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
/*
* If sd_count > 0 at this point, one of the subdomains hasn't
- * managed to call pm_genpd_poweron() for the master yet after
- * incrementing it. In that case pm_genpd_poweron() will wait
+ * managed to call genpd_poweron() for the master yet after
+ * incrementing it. In that case genpd_poweron() will wait
* for us to drop the lock, so we can call .power_off() and let
- * the pm_genpd_poweron() restore power for us (this shouldn't
+ * the genpd_poweron() restore power for us (this shouldn't
* happen very often).
*/
ret = genpd_power_off(genpd, true);
@@ -466,7 +373,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
genpd = container_of(work, struct generic_pm_domain, power_off_work);
mutex_lock(&genpd->lock);
- pm_genpd_poweroff(genpd);
+ genpd_poweroff(genpd, true);
mutex_unlock(&genpd->lock);
}
@@ -482,6 +389,9 @@ static int pm_genpd_runtime_suspend(struct device *dev)
{
struct generic_pm_domain *genpd;
bool (*stop_ok)(struct device *__dev);
+ struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+ ktime_t time_start;
+ s64 elapsed_ns;
int ret;
dev_dbg(dev, "%s()\n", __func__);
@@ -494,16 +404,29 @@ static int pm_genpd_runtime_suspend(struct device *dev)
if (stop_ok && !stop_ok(dev))
return -EBUSY;
+ /* Measure suspend latency. */
+ time_start = ktime_get();
+
ret = genpd_save_dev(genpd, dev);
if (ret)
return ret;
ret = genpd_stop_dev(genpd, dev);
if (ret) {
- genpd_restore_dev(genpd, dev, true);
+ genpd_restore_dev(genpd, dev);
return ret;
}
+ /* Update suspend latency value if the measured time exceeds it. */
+ elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+ if (elapsed_ns > td->suspend_latency_ns) {
+ td->suspend_latency_ns = elapsed_ns;
+ dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
+ elapsed_ns);
+ genpd->max_off_time_changed = true;
+ td->constraint_changed = true;
+ }
+
/*
* If power.irq_safe is set, this routine will be run with interrupts
* off, so it can't use mutexes.
@@ -512,9 +435,7 @@ static int pm_genpd_runtime_suspend(struct device *dev)
return 0;
mutex_lock(&genpd->lock);
- genpd->in_progress++;
- pm_genpd_poweroff(genpd);
- genpd->in_progress--;
+ genpd_poweroff(genpd, false);
mutex_unlock(&genpd->lock);
return 0;
@@ -531,6 +452,9 @@ static int pm_genpd_runtime_suspend(struct device *dev)
static int pm_genpd_runtime_resume(struct device *dev)
{
struct generic_pm_domain *genpd;
+ struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+ ktime_t time_start;
+ s64 elapsed_ns;
int ret;
bool timed = true;
@@ -547,15 +471,31 @@ static int pm_genpd_runtime_resume(struct device *dev)
}
mutex_lock(&genpd->lock);
- ret = __pm_genpd_poweron(genpd);
+ ret = __genpd_poweron(genpd);
mutex_unlock(&genpd->lock);
if (ret)
return ret;
out:
- genpd_start_dev(genpd, dev, timed);
- genpd_restore_dev(genpd, dev, timed);
+ /* Measure resume latency. */
+ if (timed)
+ time_start = ktime_get();
+
+ genpd_start_dev(genpd, dev);
+ genpd_restore_dev(genpd, dev);
+
+ /* Update resume latency value if the measured time exceeds it. */
+ if (timed) {
+ elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+ if (elapsed_ns > td->resume_latency_ns) {
+ td->resume_latency_ns = elapsed_ns;
+ dev_dbg(dev, "resume latency exceeded, %lld ns\n",
+ elapsed_ns);
+ genpd->max_off_time_changed = true;
+ td->constraint_changed = true;
+ }
+ }
return 0;
}
@@ -569,15 +509,15 @@ static int __init pd_ignore_unused_setup(char *__unused)
__setup("pd_ignore_unused", pd_ignore_unused_setup);
/**
- * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
+ * genpd_poweroff_unused - Power off all PM domains with no devices in use.
*/
-void pm_genpd_poweroff_unused(void)
+static int __init genpd_poweroff_unused(void)
{
struct generic_pm_domain *genpd;
if (pd_ignore_unused) {
pr_warn("genpd: Not disabling unused power domains\n");
- return;
+ return 0;
}
mutex_lock(&gpd_list_lock);
@@ -586,11 +526,7 @@ void pm_genpd_poweroff_unused(void)
genpd_queue_power_off_work(genpd);
mutex_unlock(&gpd_list_lock);
-}
-static int __init genpd_poweroff_unused(void)
-{
- pm_genpd_poweroff_unused();
return 0;
}
late_initcall(genpd_poweroff_unused);
@@ -764,7 +700,7 @@ static int pm_genpd_prepare(struct device *dev)
/*
* The PM domain must be in the GPD_STATE_ACTIVE state at this point,
- * so pm_genpd_poweron() will return immediately, but if the device
+ * so genpd_poweron() will return immediately, but if the device
* is suspended (e.g. it's been stopped by genpd_stop_dev()), we need
* to make it operational.
*/
@@ -890,7 +826,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
pm_genpd_sync_poweron(genpd, true);
genpd->suspended_count--;
- return genpd_start_dev(genpd, dev, true);
+ return genpd_start_dev(genpd, dev);
}
/**
@@ -1018,7 +954,8 @@ static int pm_genpd_thaw_noirq(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;
- return genpd->suspend_power_off ? 0 : genpd_start_dev(genpd, dev, true);
+ return genpd->suspend_power_off ?
+ 0 : genpd_start_dev(genpd, dev);
}
/**
@@ -1112,7 +1049,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
pm_genpd_sync_poweron(genpd, true);
- return genpd_start_dev(genpd, dev, true);
+ return genpd_start_dev(genpd, dev);
}
/**
@@ -1317,18 +1254,6 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
}
/**
- * __pm_genpd_name_add_device - Find I/O PM domain and add a device to it.
- * @domain_name: Name of the PM domain to add the device to.
- * @dev: Device to be added.
- * @td: Set of PM QoS timing parameters to attach to the device.
- */
-int __pm_genpd_name_add_device(const char *domain_name, struct device *dev,
- struct gpd_timing_data *td)
-{
- return __pm_genpd_add_device(pm_genpd_lookup_name(domain_name), dev, td);
-}
-
-/**
* pm_genpd_remove_device - Remove a device from an I/O PM domain.
* @genpd: PM domain to remove the device from.
* @dev: Device to be removed.
@@ -1386,13 +1311,17 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *subdomain)
{
- struct gpd_link *link;
+ struct gpd_link *link, *itr;
int ret = 0;
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)
|| genpd == subdomain)
return -EINVAL;
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (!link)
+ return -ENOMEM;
+
mutex_lock(&genpd->lock);
mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
@@ -1402,18 +1331,13 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
goto out;
}
- list_for_each_entry(link, &genpd->master_links, master_node) {
- if (link->slave == subdomain && link->master == genpd) {
+ list_for_each_entry(itr, &genpd->master_links, master_node) {
+ if (itr->slave == subdomain && itr->master == genpd) {
ret = -EINVAL;
goto out;
}
}
- link = kzalloc(sizeof(*link), GFP_KERNEL);
- if (!link) {
- ret = -ENOMEM;
- goto out;
- }
link->master = genpd;
list_add_tail(&link->master_node, &genpd->master_links);
link->slave = subdomain;
@@ -1424,38 +1348,11 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
out:
mutex_unlock(&subdomain->lock);
mutex_unlock(&genpd->lock);
-
+ if (ret)
+ kfree(link);
return ret;
}
-
-/**
- * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain.
- * @master_name: Name of the master PM domain to add the subdomain to.
- * @subdomain_name: Name of the subdomain to be added.
- */
-int pm_genpd_add_subdomain_names(const char *master_name,
- const char *subdomain_name)
-{
- struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd;
-
- if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name))
- return -EINVAL;
-
- mutex_lock(&gpd_list_lock);
- list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
- if (!master && !strcmp(gpd->name, master_name))
- master = gpd;
-
- if (!subdomain && !strcmp(gpd->name, subdomain_name))
- subdomain = gpd;
-
- if (master && subdomain)
- break;
- }
- mutex_unlock(&gpd_list_lock);
-
- return pm_genpd_add_subdomain(master, subdomain);
-}
+EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
/**
* pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
@@ -1503,124 +1400,7 @@ out:
return ret;
}
-
-/**
- * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle.
- * @genpd: PM domain to be connected with cpuidle.
- * @state: cpuidle state this domain can disable/enable.
- *
- * Make a PM domain behave as though it contained a CPU core, that is, instead
- * of calling its power down routine it will enable the given cpuidle state so
- * that the cpuidle subsystem can power it down (if possible and desirable).
- */
-int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
-{
- struct cpuidle_driver *cpuidle_drv;
- struct gpd_cpuidle_data *cpuidle_data;
- struct cpuidle_state *idle_state;
- int ret = 0;
-
- if (IS_ERR_OR_NULL(genpd) || state < 0)
- return -EINVAL;
-
- mutex_lock(&genpd->lock);
-
- if (genpd->cpuidle_data) {
- ret = -EEXIST;
- goto out;
- }
- cpuidle_data = kzalloc(sizeof(*cpuidle_data), GFP_KERNEL);
- if (!cpuidle_data) {
- ret = -ENOMEM;
- goto out;
- }
- cpuidle_drv = cpuidle_driver_ref();
- if (!cpuidle_drv) {
- ret = -ENODEV;
- goto err_drv;
- }
- if (cpuidle_drv->state_count <= state) {
- ret = -EINVAL;
- goto err;
- }
- idle_state = &cpuidle_drv->states[state];
- if (!idle_state->disabled) {
- ret = -EAGAIN;
- goto err;
- }
- cpuidle_data->idle_state = idle_state;
- cpuidle_data->saved_exit_latency = idle_state->exit_latency;
- genpd->cpuidle_data = cpuidle_data;
- genpd_recalc_cpu_exit_latency(genpd);
-
- out:
- mutex_unlock(&genpd->lock);
- return ret;
-
- err:
- cpuidle_driver_unref();
-
- err_drv:
- kfree(cpuidle_data);
- goto out;
-}
-
-/**
- * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it.
- * @name: Name of the domain to connect to cpuidle.
- * @state: cpuidle state this domain can manipulate.
- */
-int pm_genpd_name_attach_cpuidle(const char *name, int state)
-{
- return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state);
-}
-
-/**
- * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain.
- * @genpd: PM domain to remove the cpuidle connection from.
- *
- * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the
- * given PM domain.
- */
-int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd)
-{
- struct gpd_cpuidle_data *cpuidle_data;
- struct cpuidle_state *idle_state;
- int ret = 0;
-
- if (IS_ERR_OR_NULL(genpd))
- return -EINVAL;
-
- mutex_lock(&genpd->lock);
-
- cpuidle_data = genpd->cpuidle_data;
- if (!cpuidle_data) {
- ret = -ENODEV;
- goto out;
- }
- idle_state = cpuidle_data->idle_state;
- if (!idle_state->disabled) {
- ret = -EAGAIN;
- goto out;
- }
- idle_state->exit_latency = cpuidle_data->saved_exit_latency;
- cpuidle_driver_unref();
- genpd->cpuidle_data = NULL;
- kfree(cpuidle_data);
-
- out:
- mutex_unlock(&genpd->lock);
- return ret;
-}
-
-/**
- * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it.
- * @name: Name of the domain to disconnect cpuidle from.
- */
-int pm_genpd_name_detach_cpuidle(const char *name)
-{
- return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name));
-}
+EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
/* Default device callbacks for generic PM domains. */
@@ -1688,7 +1468,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
mutex_init(&genpd->lock);
genpd->gov = gov;
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
- genpd->in_progress = 0;
atomic_set(&genpd->sd_count, 0);
genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
genpd->device_count = 0;
@@ -2023,7 +1802,7 @@ int genpd_dev_pm_attach(struct device *dev)
dev->pm_domain->detach = genpd_dev_pm_detach;
dev->pm_domain->sync = genpd_dev_pm_sync;
- ret = pm_genpd_poweron(pd);
+ ret = genpd_poweron(pd);
out:
return ret ? -EPROBE_DEFER : 0;
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 2a4154a09e4d..e60dd12e23aa 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -77,13 +77,14 @@ static bool default_stop_ok(struct device *dev)
dev_update_qos_constraint);
if (constraint_ns > 0) {
- constraint_ns -= td->start_latency_ns;
+ constraint_ns -= td->suspend_latency_ns +
+ td->resume_latency_ns;
if (constraint_ns == 0)
return false;
}
td->effective_constraint_ns = constraint_ns;
- td->cached_stop_ok = constraint_ns > td->stop_latency_ns ||
- constraint_ns == 0;
+ td->cached_stop_ok = constraint_ns >= 0;
+
/*
* The children have been suspended already, so we don't need to take
* their stop latencies into account here.
@@ -126,18 +127,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
off_on_time_ns = genpd->power_off_latency_ns +
genpd->power_on_latency_ns;
- /*
- * It doesn't make sense to remove power from the domain if saving
- * the state of all devices in it and the power off/power on operations
- * take too much time.
- *
- * All devices in this domain have been stopped already at this point.
- */
- list_for_each_entry(pdd, &genpd->dev_list, list_node) {
- if (pdd->dev->driver)
- off_on_time_ns +=
- to_gpd_data(pdd)->td.save_state_latency_ns;
- }
min_off_time_ns = -1;
/*
@@ -193,7 +182,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
* constraint_ns cannot be negative here, because the device has
* been suspended.
*/
- constraint_ns -= td->restore_state_latency_ns;
if (constraint_ns <= off_on_time_ns)
return false;
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index 96a92db83cad..07c3c4a9522d 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -9,6 +9,7 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/export.h>
+#include <linux/suspend.h>
#ifdef CONFIG_PM
/**
@@ -296,11 +297,27 @@ void pm_generic_complete(struct device *dev)
if (drv && drv->pm && drv->pm->complete)
drv->pm->complete(dev);
+}
+/**
+ * pm_complete_with_resume_check - Complete a device power transition.
+ * @dev: Device to handle.
+ *
+ * Complete a device power transition during a system-wide power transition and
+ * optionally schedule a runtime resume of the device if the system resume in
+ * progress has been initated by the platform firmware and the device had its
+ * power.direct_complete flag set.
+ */
+void pm_complete_with_resume_check(struct device *dev)
+{
+ pm_generic_complete(dev);
/*
- * Let runtime PM try to suspend devices that haven't been in use before
- * going into the system-wide sleep state we're resuming from.
+ * If the device had been runtime-suspended before the system went into
+ * the sleep state it is going out of and it has never been resumed till
+ * now, resume it in case the firmware powered it up.
*/
- pm_request_idle(dev);
+ if (dev->power.direct_complete && pm_resume_via_firmware())
+ pm_request_resume(dev);
}
+EXPORT_SYMBOL_GPL(pm_complete_with_resume_check);
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/base/power/opp/Makefile b/drivers/base/power/opp/Makefile
new file mode 100644
index 000000000000..33c1e18c41a4
--- /dev/null
+++ b/drivers/base/power/opp/Makefile
@@ -0,0 +1,2 @@
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
+obj-y += core.o cpu.o
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp/core.c
index 7ae7cd990fbf..b8e76f75073b 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp/core.c
@@ -11,131 +11,16 @@
* published by the Free Software Foundation.
*/
-#include <linux/cpu.h>
-#include <linux/kernel.h>
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/rculist.h>
-#include <linux/rcupdate.h>
-#include <linux/pm_opp.h>
#include <linux/of.h>
#include <linux/export.h>
-/*
- * Internal data structure organization with the OPP layer library is as
- * follows:
- * dev_opp_list (root)
- * |- device 1 (represents voltage domain 1)
- * | |- opp 1 (availability, freq, voltage)
- * | |- opp 2 ..
- * ... ...
- * | `- opp n ..
- * |- device 2 (represents the next voltage domain)
- * ...
- * `- device m (represents mth voltage domain)
- * device 1, 2.. are represented by dev_opp structure while each opp
- * is represented by the opp structure.
- */
-
-/**
- * struct dev_pm_opp - Generic OPP description structure
- * @node: opp list node. The nodes are maintained throughout the lifetime
- * of boot. It is expected only an optimal set of OPPs are
- * added to the library by the SoC framework.
- * RCU usage: opp list is traversed with RCU locks. node
- * modification is possible realtime, hence the modifications
- * are protected by the dev_opp_list_lock for integrity.
- * IMPORTANT: the opp nodes should be maintained in increasing
- * order.
- * @dynamic: not-created from static DT entries.
- * @available: true/false - marks if this OPP as available or not
- * @turbo: true if turbo (boost) OPP
- * @rate: Frequency in hertz
- * @u_volt: Target voltage in microvolts corresponding to this OPP
- * @u_volt_min: Minimum voltage in microvolts corresponding to this OPP
- * @u_volt_max: Maximum voltage in microvolts corresponding to this OPP
- * @u_amp: Maximum current drawn by the device in microamperes
- * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
- * frequency from any other OPP's frequency.
- * @dev_opp: points back to the device_opp struct this opp belongs to
- * @rcu_head: RCU callback head used for deferred freeing
- * @np: OPP's device node.
- *
- * This structure stores the OPP information for a given device.
- */
-struct dev_pm_opp {
- struct list_head node;
-
- bool available;
- bool dynamic;
- bool turbo;
- unsigned long rate;
-
- unsigned long u_volt;
- unsigned long u_volt_min;
- unsigned long u_volt_max;
- unsigned long u_amp;
- unsigned long clock_latency_ns;
-
- struct device_opp *dev_opp;
- struct rcu_head rcu_head;
-
- struct device_node *np;
-};
-
-/**
- * struct device_list_opp - devices managed by 'struct device_opp'
- * @node: list node
- * @dev: device to which the struct object belongs
- * @rcu_head: RCU callback head used for deferred freeing
- *
- * This is an internal data structure maintaining the list of devices that are
- * managed by 'struct device_opp'.
- */
-struct device_list_opp {
- struct list_head node;
- const struct device *dev;
- struct rcu_head rcu_head;
-};
-
-/**
- * struct device_opp - Device opp structure
- * @node: list node - contains the devices with OPPs that
- * have been registered. Nodes once added are not modified in this
- * list.
- * RCU usage: nodes are not modified in the list of device_opp,
- * however addition is possible and is secured by dev_opp_list_lock
- * @srcu_head: notifier head to notify the OPP availability changes.
- * @rcu_head: RCU callback head used for deferred freeing
- * @dev_list: list of devices that share these OPPs
- * @opp_list: list of opps
- * @np: struct device_node pointer for opp's DT node.
- * @shared_opp: OPP is shared between multiple devices.
- *
- * This is an internal data structure maintaining the link to opps attached to
- * a device. This structure is not meant to be shared to users as it is
- * meant for book keeping and private to OPP library.
- *
- * Because the opp structures can be used from both rcu and srcu readers, we
- * need to wait for the grace period of both of them before freeing any
- * resources. And so we have used kfree_rcu() from within call_srcu() handlers.
- */
-struct device_opp {
- struct list_head node;
-
- struct srcu_notifier_head srcu_head;
- struct rcu_head rcu_head;
- struct list_head dev_list;
- struct list_head opp_list;
-
- struct device_node *np;
- unsigned long clock_latency_ns_max;
- bool shared_opp;
- struct dev_pm_opp *suspend_opp;
-};
+#include "opp.h"
/*
* The root of the list of all devices. All device_opp structures branch off
@@ -144,7 +29,7 @@ struct device_opp {
*/
static LIST_HEAD(dev_opp_list);
/* Lock to allow exclusive modification to the device and opp lists */
-static DEFINE_MUTEX(dev_opp_list_lock);
+DEFINE_MUTEX(dev_opp_list_lock);
#define opp_rcu_lockdep_assert() \
do { \
@@ -196,14 +81,18 @@ static struct device_opp *_managed_opp(const struct device_node *np)
* Return: pointer to 'struct device_opp' if found, otherwise -ENODEV or
* -EINVAL based on type of error.
*
- * Locking: This function must be called under rcu_read_lock(). device_opp
- * is a RCU protected pointer. This means that device_opp is valid as long
- * as we are under RCU lock.
+ * Locking: For readers, this function must be called under rcu_read_lock().
+ * device_opp is a RCU protected pointer, which means that device_opp is valid
+ * as long as we are under RCU lock.
+ *
+ * For Writers, this function must be called with dev_opp_list_lock held.
*/
-static struct device_opp *_find_device_opp(struct device *dev)
+struct device_opp *_find_device_opp(struct device *dev)
{
struct device_opp *dev_opp;
+ opp_rcu_lockdep_assert();
+
if (IS_ERR_OR_NULL(dev)) {
pr_err("%s: Invalid parameters\n", __func__);
return ERR_PTR(-EINVAL);
@@ -217,7 +106,7 @@ static struct device_opp *_find_device_opp(struct device *dev)
}
/**
- * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp
* @opp: opp for which voltage has to be returned for
*
* Return: voltage in micro volt corresponding to the opp, else
@@ -239,7 +128,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
opp_rcu_lockdep_assert();
tmp_opp = rcu_dereference(opp);
- if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available)
+ if (IS_ERR_OR_NULL(tmp_opp))
pr_err("%s: Invalid parameters\n", __func__);
else
v = tmp_opp->u_volt;
@@ -579,8 +468,8 @@ static void _remove_list_dev(struct device_list_opp *list_dev,
_kfree_list_dev_rcu);
}
-static struct device_list_opp *_add_list_dev(const struct device *dev,
- struct device_opp *dev_opp)
+struct device_list_opp *_add_list_dev(const struct device *dev,
+ struct device_opp *dev_opp)
{
struct device_list_opp *list_dev;
@@ -818,7 +707,7 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
}
/**
- * _opp_add_dynamic() - Allocate a dynamic OPP.
+ * _opp_add_v1() - Allocate a OPP based on v1 bindings.
* @dev: device for which we do this operation
* @freq: Frequency in Hz for this OPP
* @u_volt: Voltage in uVolts for this OPP
@@ -828,8 +717,8 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
* The opp is made available by default and it can be controlled using
* dev_pm_opp_enable/disable functions and may be removed by dev_pm_opp_remove.
*
- * NOTE: "dynamic" parameter impacts OPPs added by the of_init_opp_table and
- * freed by of_free_opp_table.
+ * NOTE: "dynamic" parameter impacts OPPs added by the dev_pm_opp_of_add_table
+ * and freed by dev_pm_opp_of_remove_table.
*
* Locking: The internal device_opp and opp structures are RCU protected.
* Hence this function internally uses RCU updater strategy with mutex locks
@@ -844,8 +733,8 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
* Duplicate OPPs (both freq and volt are same) and !opp->available
* -ENOMEM Memory allocation failure
*/
-static int _opp_add_dynamic(struct device *dev, unsigned long freq,
- long u_volt, bool dynamic)
+static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
+ bool dynamic)
{
struct device_opp *dev_opp;
struct dev_pm_opp *new_opp;
@@ -887,9 +776,10 @@ unlock:
}
/* TODO: Support multiple regulators */
-static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
+static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev)
{
u32 microvolt[3] = {0};
+ u32 val;
int count, ret;
/* Missing property isn't a problem, but an invalid entry is */
@@ -922,6 +812,9 @@ static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
opp->u_volt_min = microvolt[1];
opp->u_volt_max = microvolt[2];
+ if (!of_property_read_u32(opp->np, "opp-microamp", &val))
+ opp->u_amp = val;
+
return 0;
}
@@ -986,13 +879,10 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
if (!of_property_read_u32(np, "clock-latency-ns", &val))
new_opp->clock_latency_ns = val;
- ret = opp_get_microvolt(new_opp, dev);
+ ret = opp_parse_supplies(new_opp, dev);
if (ret)
goto free_opp;
- if (!of_property_read_u32(new_opp->np, "opp-microamp", &val))
- new_opp->u_amp = val;
-
ret = _opp_add(dev, new_opp, dev_opp);
if (ret)
goto free_opp;
@@ -1056,7 +946,7 @@ unlock:
*/
int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
{
- return _opp_add_dynamic(dev, freq, u_volt, true);
+ return _opp_add_v1(dev, freq, u_volt, true);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_add);
@@ -1220,7 +1110,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
#ifdef CONFIG_OF
/**
- * of_free_opp_table() - Free OPP table entries created from static DT entries
+ * dev_pm_opp_of_remove_table() - Free OPP table entries created from static DT
+ * entries
* @dev: device pointer used to lookup device OPPs.
*
* Free OPPs created using static entries present in DT.
@@ -1231,7 +1122,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
* that this function is *NOT* called under RCU protection or in contexts where
* mutex cannot be locked.
*/
-void of_free_opp_table(struct device *dev)
+void dev_pm_opp_of_remove_table(struct device *dev)
{
struct device_opp *dev_opp;
struct dev_pm_opp *opp, *tmp;
@@ -1266,92 +1157,39 @@ void of_free_opp_table(struct device *dev)
unlock:
mutex_unlock(&dev_opp_list_lock);
}
-EXPORT_SYMBOL_GPL(of_free_opp_table);
-
-void of_cpumask_free_opp_table(cpumask_var_t cpumask)
-{
- struct device *cpu_dev;
- int cpu;
-
- WARN_ON(cpumask_empty(cpumask));
-
- for_each_cpu(cpu, cpumask) {
- cpu_dev = get_cpu_device(cpu);
- if (!cpu_dev) {
- pr_err("%s: failed to get cpu%d device\n", __func__,
- cpu);
- continue;
- }
-
- of_free_opp_table(cpu_dev);
- }
-}
-EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
-
-/* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
-static struct device_node *
-_of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
-{
- struct device_node *opp_np;
-
- opp_np = of_find_node_by_phandle(be32_to_cpup(prop->value));
- if (!opp_np) {
- dev_err(dev, "%s: Prop: %s contains invalid opp desc phandle\n",
- __func__, prop->name);
- return ERR_PTR(-EINVAL);
- }
-
- return opp_np;
-}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
-/* Returns opp descriptor node for a device. Caller must do of_node_put() */
-static struct device_node *_of_get_opp_desc_node(struct device *dev)
+/* Returns opp descriptor node for a device, caller must do of_node_put() */
+struct device_node *_of_get_opp_desc_node(struct device *dev)
{
- const struct property *prop;
-
- prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
- if (!prop)
- return ERR_PTR(-ENODEV);
- if (!prop->value)
- return ERR_PTR(-ENODATA);
-
/*
* TODO: Support for multiple OPP tables.
*
* There should be only ONE phandle present in "operating-points-v2"
* property.
*/
- if (prop->length != sizeof(__be32)) {
- dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
- return ERR_PTR(-EINVAL);
- }
- return _of_get_opp_desc_node_from_prop(dev, prop);
+ return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
}
/* Initializes OPP tables based on new bindings */
-static int _of_init_opp_table_v2(struct device *dev,
- const struct property *prop)
+static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
{
- struct device_node *opp_np, *np;
+ struct device_node *np;
struct device_opp *dev_opp;
int ret = 0, count = 0;
- if (!prop->value)
- return -ENODATA;
-
- /* Get opp node */
- opp_np = _of_get_opp_desc_node_from_prop(dev, prop);
- if (IS_ERR(opp_np))
- return PTR_ERR(opp_np);
+ mutex_lock(&dev_opp_list_lock);
dev_opp = _managed_opp(opp_np);
if (dev_opp) {
/* OPPs are already managed */
if (!_add_list_dev(dev, dev_opp))
ret = -ENOMEM;
- goto put_opp_np;
+ mutex_unlock(&dev_opp_list_lock);
+ return ret;
}
+ mutex_unlock(&dev_opp_list_lock);
/* We have opp-list node now, iterate over it and add OPPs */
for_each_available_child_of_node(opp_np, np) {
@@ -1366,33 +1204,33 @@ static int _of_init_opp_table_v2(struct device *dev,
}
/* There should be one of more OPP defined */
- if (WARN_ON(!count)) {
- ret = -ENOENT;
- goto put_opp_np;
- }
+ if (WARN_ON(!count))
+ return -ENOENT;
+
+ mutex_lock(&dev_opp_list_lock);
dev_opp = _find_device_opp(dev);
if (WARN_ON(IS_ERR(dev_opp))) {
ret = PTR_ERR(dev_opp);
+ mutex_unlock(&dev_opp_list_lock);
goto free_table;
}
dev_opp->np = opp_np;
dev_opp->shared_opp = of_property_read_bool(opp_np, "opp-shared");
- of_node_put(opp_np);
+ mutex_unlock(&dev_opp_list_lock);
+
return 0;
free_table:
- of_free_opp_table(dev);
-put_opp_np:
- of_node_put(opp_np);
+ dev_pm_opp_of_remove_table(dev);
return ret;
}
/* Initializes OPP tables based on old-deprecated bindings */
-static int _of_init_opp_table_v1(struct device *dev)
+static int _of_add_opp_table_v1(struct device *dev)
{
const struct property *prop;
const __be32 *val;
@@ -1419,7 +1257,7 @@ static int _of_init_opp_table_v1(struct device *dev)
unsigned long freq = be32_to_cpup(val++) * 1000;
unsigned long volt = be32_to_cpup(val++);
- if (_opp_add_dynamic(dev, freq, volt, false))
+ if (_opp_add_v1(dev, freq, volt, false))
dev_warn(dev, "%s: Failed to add OPP %ld\n",
__func__, freq);
nr -= 2;
@@ -1429,7 +1267,7 @@ static int _of_init_opp_table_v1(struct device *dev)
}
/**
- * of_init_opp_table() - Initialize opp table from device tree
+ * dev_pm_opp_of_add_table() - Initialize opp table from device tree
* @dev: device pointer used to lookup device OPPs.
*
* Register the initial OPP table with the OPP library for given device.
@@ -1451,153 +1289,28 @@ static int _of_init_opp_table_v1(struct device *dev)
* -ENODATA when empty 'operating-points' property is found
* -EINVAL when invalid entries are found in opp-v2 table
*/
-int of_init_opp_table(struct device *dev)
+int dev_pm_opp_of_add_table(struct device *dev)
{
- const struct property *prop;
+ struct device_node *opp_np;
+ int ret;
/*
* OPPs have two version of bindings now. The older one is deprecated,
* try for the new binding first.
*/
- prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
- if (!prop) {
+ opp_np = _of_get_opp_desc_node(dev);
+ if (!opp_np) {
/*
* Try old-deprecated bindings for backward compatibility with
* older dtbs.
*/
- return _of_init_opp_table_v1(dev);
+ return _of_add_opp_table_v1(dev);
}
- return _of_init_opp_table_v2(dev, prop);
-}
-EXPORT_SYMBOL_GPL(of_init_opp_table);
-
-int of_cpumask_init_opp_table(cpumask_var_t cpumask)
-{
- struct device *cpu_dev;
- int cpu, ret = 0;
-
- WARN_ON(cpumask_empty(cpumask));
-
- for_each_cpu(cpu, cpumask) {
- cpu_dev = get_cpu_device(cpu);
- if (!cpu_dev) {
- pr_err("%s: failed to get cpu%d device\n", __func__,
- cpu);
- continue;
- }
-
- ret = of_init_opp_table(cpu_dev);
- if (ret) {
- pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
- __func__, cpu, ret);
-
- /* Free all other OPPs */
- of_cpumask_free_opp_table(cpumask);
- break;
- }
- }
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
-
-/* Required only for V1 bindings, as v2 can manage it from DT itself */
-int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
-{
- struct device_list_opp *list_dev;
- struct device_opp *dev_opp;
- struct device *dev;
- int cpu, ret = 0;
-
- rcu_read_lock();
-
- dev_opp = _find_device_opp(cpu_dev);
- if (IS_ERR(dev_opp)) {
- ret = -EINVAL;
- goto out_rcu_read_unlock;
- }
-
- for_each_cpu(cpu, cpumask) {
- if (cpu == cpu_dev->id)
- continue;
-
- dev = get_cpu_device(cpu);
- if (!dev) {
- dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
- __func__, cpu);
- continue;
- }
-
- list_dev = _add_list_dev(dev, dev_opp);
- if (!list_dev) {
- dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
- __func__, cpu);
- continue;
- }
- }
-out_rcu_read_unlock:
- rcu_read_unlock();
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
-
-/*
- * Works only for OPP v2 bindings.
- *
- * cpumask should be already set to mask of cpu_dev->id.
- * Returns -ENOENT if operating-points-v2 bindings aren't supported.
- */
-int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
-{
- struct device_node *np, *tmp_np;
- struct device *tcpu_dev;
- int cpu, ret = 0;
-
- /* Get OPP descriptor node */
- np = _of_get_opp_desc_node(cpu_dev);
- if (IS_ERR(np)) {
- dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
- PTR_ERR(np));
- return -ENOENT;
- }
-
- /* OPPs are shared ? */
- if (!of_property_read_bool(np, "opp-shared"))
- goto put_cpu_node;
-
- for_each_possible_cpu(cpu) {
- if (cpu == cpu_dev->id)
- continue;
-
- tcpu_dev = get_cpu_device(cpu);
- if (!tcpu_dev) {
- dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
- __func__, cpu);
- ret = -ENODEV;
- goto put_cpu_node;
- }
-
- /* Get OPP descriptor node */
- tmp_np = _of_get_opp_desc_node(tcpu_dev);
- if (IS_ERR(tmp_np)) {
- dev_err(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
- __func__, PTR_ERR(tmp_np));
- ret = PTR_ERR(tmp_np);
- goto put_cpu_node;
- }
-
- /* CPUs are sharing opp node */
- if (np == tmp_np)
- cpumask_set_cpu(cpu, cpumask);
-
- of_node_put(tmp_np);
- }
+ ret = _of_add_opp_table_v2(dev, opp_np);
+ of_node_put(opp_np);
-put_cpu_node:
- of_node_put(np);
return ret;
}
-EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
#endif
diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c
new file mode 100644
index 000000000000..7b445e88a0d5
--- /dev/null
+++ b/drivers/base/power/opp/cpu.c
@@ -0,0 +1,270 @@
+/*
+ * Generic OPP helper interface for CPU device
+ *
+ * Copyright (C) 2009-2014 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * 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
+
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "opp.h"
+
+#ifdef CONFIG_CPU_FREQ
+
+/**
+ * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev: device for which we do this operation
+ * @table: Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Since we just use the regular accessor functions to access the internal data
+ * structures, we use RCU read lock inside this function. As a result, users of
+ * this function DONOT need to use explicit locks for invoking.
+ */
+int dev_pm_opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ struct dev_pm_opp *opp;
+ struct cpufreq_frequency_table *freq_table = NULL;
+ int i, max_opps, ret = 0;
+ unsigned long rate;
+
+ rcu_read_lock();
+
+ max_opps = dev_pm_opp_get_opp_count(dev);
+ if (max_opps <= 0) {
+ ret = max_opps ? max_opps : -ENODATA;
+ goto out;
+ }
+
+ freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
+ if (!freq_table) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0, rate = 0; i < max_opps; i++, rate++) {
+ /* find next rate */
+ opp = dev_pm_opp_find_freq_ceil(dev, &rate);
+ if (IS_ERR(opp)) {
+ ret = PTR_ERR(opp);
+ goto out;
+ }
+ freq_table[i].driver_data = i;
+ freq_table[i].frequency = rate / 1000;
+
+ /* Is Boost/turbo opp ? */
+ if (dev_pm_opp_is_turbo(opp))
+ freq_table[i].flags = CPUFREQ_BOOST_FREQ;
+ }
+
+ freq_table[i].driver_data = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *table = &freq_table[0];
+
+out:
+ rcu_read_unlock();
+ if (ret)
+ kfree(freq_table);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
+
+/**
+ * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
+ * @dev: device for which we do this operation
+ * @table: table to free
+ *
+ * Free up the table allocated by dev_pm_opp_init_cpufreq_table
+ */
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ if (!table)
+ return;
+
+ kfree(*table);
+ *table = NULL;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
+#endif /* CONFIG_CPU_FREQ */
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+ struct device_list_opp *list_dev;
+ struct device_opp *dev_opp;
+ struct device *dev;
+ int cpu, ret = 0;
+
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = _find_device_opp(cpu_dev);
+ if (IS_ERR(dev_opp)) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ for_each_cpu(cpu, cpumask) {
+ if (cpu == cpu_dev->id)
+ continue;
+
+ dev = get_cpu_device(cpu);
+ if (!dev) {
+ dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+ __func__, cpu);
+ continue;
+ }
+
+ list_dev = _add_list_dev(dev, dev_opp);
+ if (!list_dev) {
+ dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+ __func__, cpu);
+ continue;
+ }
+ }
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus);
+
+#ifdef CONFIG_OF
+void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask)
+{
+ struct device *cpu_dev;
+ int cpu;
+
+ WARN_ON(cpumask_empty(cpumask));
+
+ for_each_cpu(cpu, cpumask) {
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev) {
+ pr_err("%s: failed to get cpu%d device\n", __func__,
+ cpu);
+ continue;
+ }
+
+ dev_pm_opp_of_remove_table(cpu_dev);
+ }
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table);
+
+int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask)
+{
+ struct device *cpu_dev;
+ int cpu, ret = 0;
+
+ WARN_ON(cpumask_empty(cpumask));
+
+ for_each_cpu(cpu, cpumask) {
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev) {
+ pr_err("%s: failed to get cpu%d device\n", __func__,
+ cpu);
+ continue;
+ }
+
+ ret = dev_pm_opp_of_add_table(cpu_dev);
+ if (ret) {
+ pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+ __func__, cpu, ret);
+
+ /* Free all other OPPs */
+ dev_pm_opp_of_cpumask_remove_table(cpumask);
+ break;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+ struct device_node *np, *tmp_np;
+ struct device *tcpu_dev;
+ int cpu, ret = 0;
+
+ /* Get OPP descriptor node */
+ np = _of_get_opp_desc_node(cpu_dev);
+ if (!np) {
+ dev_dbg(cpu_dev, "%s: Couldn't find cpu_dev node.\n", __func__);
+ return -ENOENT;
+ }
+
+ /* OPPs are shared ? */
+ if (!of_property_read_bool(np, "opp-shared"))
+ goto put_cpu_node;
+
+ for_each_possible_cpu(cpu) {
+ if (cpu == cpu_dev->id)
+ continue;
+
+ tcpu_dev = get_cpu_device(cpu);
+ if (!tcpu_dev) {
+ dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+ __func__, cpu);
+ ret = -ENODEV;
+ goto put_cpu_node;
+ }
+
+ /* Get OPP descriptor node */
+ tmp_np = _of_get_opp_desc_node(tcpu_dev);
+ if (!tmp_np) {
+ dev_err(tcpu_dev, "%s: Couldn't find tcpu_dev node.\n",
+ __func__);
+ ret = -ENOENT;
+ goto put_cpu_node;
+ }
+
+ /* CPUs are sharing opp node */
+ if (np == tmp_np)
+ cpumask_set_cpu(cpu, cpumask);
+
+ of_node_put(tmp_np);
+ }
+
+put_cpu_node:
+ of_node_put(np);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus);
+#endif
diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h
new file mode 100644
index 000000000000..7366b2aa8997
--- /dev/null
+++ b/drivers/base/power/opp/opp.h
@@ -0,0 +1,146 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * 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 __DRIVER_OPP_H__
+#define __DRIVER_OPP_H__
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/pm_opp.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+
+/* Lock to allow exclusive modification to the device and opp lists */
+extern struct mutex dev_opp_list_lock;
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ * |- device 1 (represents voltage domain 1)
+ * | |- opp 1 (availability, freq, voltage)
+ * | |- opp 2 ..
+ * ... ...
+ * | `- opp n ..
+ * |- device 2 (represents the next voltage domain)
+ * ...
+ * `- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct dev_pm_opp - Generic OPP description structure
+ * @node: opp list node. The nodes are maintained throughout the lifetime
+ * of boot. It is expected only an optimal set of OPPs are
+ * added to the library by the SoC framework.
+ * RCU usage: opp list is traversed with RCU locks. node
+ * modification is possible realtime, hence the modifications
+ * are protected by the dev_opp_list_lock for integrity.
+ * IMPORTANT: the opp nodes should be maintained in increasing
+ * order.
+ * @dynamic: not-created from static DT entries.
+ * @available: true/false - marks if this OPP as available or not
+ * @turbo: true if turbo (boost) OPP
+ * @rate: Frequency in hertz
+ * @u_volt: Target voltage in microvolts corresponding to this OPP
+ * @u_volt_min: Minimum voltage in microvolts corresponding to this OPP
+ * @u_volt_max: Maximum voltage in microvolts corresponding to this OPP
+ * @u_amp: Maximum current drawn by the device in microamperes
+ * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
+ * frequency from any other OPP's frequency.
+ * @dev_opp: points back to the device_opp struct this opp belongs to
+ * @rcu_head: RCU callback head used for deferred freeing
+ * @np: OPP's device node.
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct dev_pm_opp {
+ struct list_head node;
+
+ bool available;
+ bool dynamic;
+ bool turbo;
+ unsigned long rate;
+
+ unsigned long u_volt;
+ unsigned long u_volt_min;
+ unsigned long u_volt_max;
+ unsigned long u_amp;
+ unsigned long clock_latency_ns;
+
+ struct device_opp *dev_opp;
+ struct rcu_head rcu_head;
+
+ struct device_node *np;
+};
+
+/**
+ * struct device_list_opp - devices managed by 'struct device_opp'
+ * @node: list node
+ * @dev: device to which the struct object belongs
+ * @rcu_head: RCU callback head used for deferred freeing
+ *
+ * This is an internal data structure maintaining the list of devices that are
+ * managed by 'struct device_opp'.
+ */
+struct device_list_opp {
+ struct list_head node;
+ const struct device *dev;
+ struct rcu_head rcu_head;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node: list node - contains the devices with OPPs that
+ * have been registered. Nodes once added are not modified in this
+ * list.
+ * RCU usage: nodes are not modified in the list of device_opp,
+ * however addition is possible and is secured by dev_opp_list_lock
+ * @srcu_head: notifier head to notify the OPP availability changes.
+ * @rcu_head: RCU callback head used for deferred freeing
+ * @dev_list: list of devices that share these OPPs
+ * @opp_list: list of opps
+ * @np: struct device_node pointer for opp's DT node.
+ * @shared_opp: OPP is shared between multiple devices.
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library.
+ *
+ * Because the opp structures can be used from both rcu and srcu readers, we
+ * need to wait for the grace period of both of them before freeing any
+ * resources. And so we have used kfree_rcu() from within call_srcu() handlers.
+ */
+struct device_opp {
+ struct list_head node;
+
+ struct srcu_notifier_head srcu_head;
+ struct rcu_head rcu_head;
+ struct list_head dev_list;
+ struct list_head opp_list;
+
+ struct device_node *np;
+ unsigned long clock_latency_ns_max;
+ bool shared_opp;
+ struct dev_pm_opp *suspend_opp;
+};
+
+/* Routines internal to opp core */
+struct device_opp *_find_device_opp(struct device *dev);
+struct device_list_opp *_add_list_dev(const struct device *dev,
+ struct device_opp *dev_opp);
+struct device_node *_of_get_opp_desc_node(struct device *dev);
+
+#endif /* __DRIVER_OPP_H__ */
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index eb6e67451dec..0d77cd6fd8d1 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -68,6 +68,9 @@ int dev_pm_set_wake_irq(struct device *dev, int irq)
struct wake_irq *wirq;
int err;
+ if (irq < 0)
+ return -EINVAL;
+
wirq = kzalloc(sizeof(*wirq), GFP_KERNEL);
if (!wirq)
return -ENOMEM;
@@ -167,6 +170,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
struct wake_irq *wirq;
int err;
+ if (irq < 0)
+ return -EINVAL;
+
wirq = kzalloc(sizeof(*wirq), GFP_KERNEL);
if (!wirq)
return -ENOMEM;
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 51f15bc15774..a1e0b9ab847a 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -25,6 +25,9 @@
*/
bool events_check_enabled __read_mostly;
+/* First wakeup IRQ seen by the kernel in the last cycle. */
+unsigned int pm_wakeup_irq __read_mostly;
+
/* If set and the system is suspending, terminate the suspend. */
static bool pm_abort_suspend __read_mostly;
@@ -91,7 +94,7 @@ struct wakeup_source *wakeup_source_create(const char *name)
if (!ws)
return NULL;
- wakeup_source_prepare(ws, name ? kstrdup(name, GFP_KERNEL) : NULL);
+ wakeup_source_prepare(ws, name ? kstrdup_const(name, GFP_KERNEL) : NULL);
return ws;
}
EXPORT_SYMBOL_GPL(wakeup_source_create);
@@ -154,7 +157,7 @@ void wakeup_source_destroy(struct wakeup_source *ws)
wakeup_source_drop(ws);
wakeup_source_record(ws);
- kfree(ws->name);
+ kfree_const(ws->name);
kfree(ws);
}
EXPORT_SYMBOL_GPL(wakeup_source_destroy);
@@ -868,6 +871,15 @@ EXPORT_SYMBOL_GPL(pm_system_wakeup);
void pm_wakeup_clear(void)
{
pm_abort_suspend = false;
+ pm_wakeup_irq = 0;
+}
+
+void pm_system_irq_wakeup(unsigned int irq_number)
+{
+ if (pm_wakeup_irq == 0) {
+ pm_wakeup_irq = irq_number;
+ pm_system_wakeup();
+ }
}
/**
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 2d75366c61e0..1325ff225cc4 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -134,7 +134,7 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
if (is_of_node(fwnode))
return of_property_read_bool(to_of_node(fwnode), propname);
else if (is_acpi_node(fwnode))
- return !acpi_dev_prop_get(to_acpi_node(fwnode), propname, NULL);
+ return !acpi_node_prop_get(fwnode, propname, NULL);
return !!pset_prop_get(to_pset(fwnode), propname);
}
@@ -287,6 +287,28 @@ int device_property_read_string(struct device *dev, const char *propname,
}
EXPORT_SYMBOL_GPL(device_property_read_string);
+/**
+ * device_property_match_string - find a string in an array and return index
+ * @dev: Device to get the property of
+ * @propname: Name of the property holding the array
+ * @string: String to look for
+ *
+ * Find a given string in a string array and if it is found return the
+ * index back.
+ *
+ * Return: %0 if the property was found (success),
+ * %-EINVAL if given arguments are not valid,
+ * %-ENODATA if the property does not have a value,
+ * %-EPROTO if the property is not an array of strings,
+ * %-ENXIO if no suitable firmware interface is present.
+ */
+int device_property_match_string(struct device *dev, const char *propname,
+ const char *string)
+{
+ return fwnode_property_match_string(dev_fwnode(dev), propname, string);
+}
+EXPORT_SYMBOL_GPL(device_property_match_string);
+
#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
: of_property_count_elems_of_size((node), (propname), sizeof(type))
@@ -298,8 +320,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string);
_ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
_type_, _val_, _nval_); \
else if (is_acpi_node(_fwnode_)) \
- _ret_ = acpi_dev_prop_read(to_acpi_node(_fwnode_), _propname_, \
- _proptype_, _val_, _nval_); \
+ _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
+ _val_, _nval_); \
else if (is_pset(_fwnode_)) \
_ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \
_proptype_, _val_, _nval_); \
@@ -440,8 +462,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
propname, val, nval) :
of_property_count_strings(to_of_node(fwnode), propname);
else if (is_acpi_node(fwnode))
- return acpi_dev_prop_read(to_acpi_node(fwnode), propname,
- DEV_PROP_STRING, val, nval);
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+ val, nval);
else if (is_pset(fwnode))
return pset_prop_read_array(to_pset(fwnode), propname,
DEV_PROP_STRING, val, nval);
@@ -470,8 +492,8 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
if (is_of_node(fwnode))
return of_property_read_string(to_of_node(fwnode), propname, val);
else if (is_acpi_node(fwnode))
- return acpi_dev_prop_read(to_acpi_node(fwnode), propname,
- DEV_PROP_STRING, val, 1);
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+ val, 1);
return pset_prop_read_array(to_pset(fwnode), propname,
DEV_PROP_STRING, val, 1);
@@ -479,6 +501,52 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
EXPORT_SYMBOL_GPL(fwnode_property_read_string);
/**
+ * fwnode_property_match_string - find a string in an array and return index
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property holding the array
+ * @string: String to look for
+ *
+ * Find a given string in a string array and if it is found return the
+ * index back.
+ *
+ * Return: %0 if the property was found (success),
+ * %-EINVAL if given arguments are not valid,
+ * %-ENODATA if the property does not have a value,
+ * %-EPROTO if the property is not an array of strings,
+ * %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_match_string(struct fwnode_handle *fwnode,
+ const char *propname, const char *string)
+{
+ const char **values;
+ int nval, ret, i;
+
+ nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
+ if (nval < 0)
+ return nval;
+
+ values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
+ if (!values)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
+ if (ret < 0)
+ goto out;
+
+ ret = -ENODATA;
+ for (i = 0; i < nval; i++) {
+ if (!strcmp(values[i], string)) {
+ ret = i;
+ break;
+ }
+ }
+out:
+ kfree(values);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_match_string);
+
+/**
* device_get_next_child_node - Return the next child node handle for a device
* @dev: Device to find the next child node for.
* @child: Handle to one of the device's child nodes or a null handle.
@@ -493,11 +561,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,
if (node)
return &node->fwnode;
} else if (IS_ENABLED(CONFIG_ACPI)) {
- struct acpi_device *node;
-
- node = acpi_get_next_child(dev, to_acpi_node(child));
- if (node)
- return acpi_fwnode_handle(node);
+ return acpi_get_next_subnode(dev, child);
}
return NULL;
}
@@ -534,18 +598,34 @@ unsigned int device_get_child_node_count(struct device *dev)
}
EXPORT_SYMBOL_GPL(device_get_child_node_count);
-bool device_dma_is_coherent(struct device *dev)
+bool device_dma_supported(struct device *dev)
{
- bool coherent = false;
-
+ /* For DT, this is always supported.
+ * For ACPI, this depends on CCA, which
+ * is determined by the acpi_dma_supported().
+ */
if (IS_ENABLED(CONFIG_OF) && dev->of_node)
- coherent = of_dma_is_coherent(dev->of_node);
- else
- acpi_check_dma(ACPI_COMPANION(dev), &coherent);
+ return true;
+
+ return acpi_dma_supported(ACPI_COMPANION(dev));
+}
+EXPORT_SYMBOL_GPL(device_dma_supported);
+
+enum dev_dma_attr device_get_dma_attr(struct device *dev)
+{
+ enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED;
- return coherent;
+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+ if (of_dma_is_coherent(dev->of_node))
+ attr = DEV_DMA_COHERENT;
+ else
+ attr = DEV_DMA_NON_COHERENT;
+ } else
+ attr = acpi_get_dma_attr(ACPI_COMPANION(dev));
+
+ return attr;
}
-EXPORT_SYMBOL_GPL(device_dma_is_coherent);
+EXPORT_SYMBOL_GPL(device_get_dma_attr);
/**
* device_get_phy_mode - Get phy mode for given device
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index cc557886ab23..3df977054781 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -59,6 +59,7 @@ struct regmap {
regmap_lock lock;
regmap_unlock unlock;
void *lock_arg; /* This is passed to lock/unlock functions */
+ gfp_t alloc_flags;
struct device *dev; /* Device we do I/O on */
void *work_buf; /* Scratch buffer used to format I/O */
@@ -98,6 +99,8 @@ struct regmap {
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+ int (*reg_update_bits)(void *context, unsigned int reg,
+ unsigned int mask, unsigned int val);
bool defer_caching;
@@ -122,9 +125,9 @@ struct regmap {
unsigned int num_reg_defaults_raw;
/* if set, only the cache is modified not the HW */
- u32 cache_only;
+ bool cache_only;
/* if set, only the HW is modified not the cache */
- u32 cache_bypass;
+ bool cache_bypass;
/* if set, remember to free reg_defaults_raw */
bool cache_free;
@@ -132,7 +135,7 @@ struct regmap {
const void *reg_defaults_raw;
void *cache;
/* if set, the cache contains newer data than the HW */
- u32 cache_dirty;
+ bool cache_dirty;
/* if set, the HW registers are known to match map->reg_defaults */
bool no_sync_defaults;
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
index 2d53f6f138e1..736e0d378567 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -355,9 +355,9 @@ static int regcache_lzo_sync(struct regmap *map, unsigned int min,
if (ret > 0 && val == map->reg_defaults[ret].def)
continue;
- map->cache_bypass = 1;
+ map->cache_bypass = true;
ret = _regmap_write(map, i, val);
- map->cache_bypass = 0;
+ map->cache_bypass = false;
if (ret)
return ret;
dev_dbg(map->dev, "Synced register %#x, value %#x\n",
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 6f8a13ec32a4..4c07802986b2 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -54,11 +54,11 @@ static int regcache_hw_init(struct regmap *map)
return -ENOMEM;
if (!map->reg_defaults_raw) {
- u32 cache_bypass = map->cache_bypass;
+ bool cache_bypass = map->cache_bypass;
dev_warn(map->dev, "No cache defaults, reading back from HW\n");
/* Bypass the cache access till data read from HW*/
- map->cache_bypass = 1;
+ map->cache_bypass = true;
tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
if (!tmp_buf) {
ret = -ENOMEM;
@@ -285,9 +285,9 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
if (!regcache_reg_needs_sync(map, reg, val))
continue;
- map->cache_bypass = 1;
+ map->cache_bypass = true;
ret = _regmap_write(map, reg, val);
- map->cache_bypass = 0;
+ map->cache_bypass = false;
if (ret) {
dev_err(map->dev, "Unable to sync register %#x. %d\n",
reg, ret);
@@ -315,7 +315,7 @@ int regcache_sync(struct regmap *map)
int ret = 0;
unsigned int i;
const char *name;
- unsigned int bypass;
+ bool bypass;
BUG_ON(!map->cache_ops);
@@ -333,7 +333,7 @@ int regcache_sync(struct regmap *map)
map->async = true;
/* Apply any patch first */
- map->cache_bypass = 1;
+ map->cache_bypass = true;
for (i = 0; i < map->patch_regs; i++) {
ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
if (ret != 0) {
@@ -342,7 +342,7 @@ int regcache_sync(struct regmap *map)
goto out;
}
}
- map->cache_bypass = 0;
+ map->cache_bypass = false;
if (map->cache_ops->sync)
ret = map->cache_ops->sync(map, 0, map->max_register);
@@ -384,7 +384,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
{
int ret = 0;
const char *name;
- unsigned int bypass;
+ bool bypass;
BUG_ON(!map->cache_ops);
@@ -637,11 +637,11 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
if (!regcache_reg_needs_sync(map, regtmp, val))
continue;
- map->cache_bypass = 1;
+ map->cache_bypass = true;
ret = _regmap_write(map, regtmp, val);
- map->cache_bypass = 0;
+ map->cache_bypass = false;
if (ret != 0) {
dev_err(map->dev, "Unable to sync register %#x. %d\n",
regtmp, ret);
@@ -668,14 +668,14 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n",
count * val_bytes, count, base, cur - map->reg_stride);
- map->cache_bypass = 1;
+ map->cache_bypass = true;
ret = _regmap_raw_write(map, base, *data, count * val_bytes);
if (ret)
dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n",
base, cur - map->reg_stride, ret);
- map->cache_bypass = 0;
+ map->cache_bypass = false;
*data = NULL;
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 4c55cfbad19e..3f0a7e262d69 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -30,7 +30,7 @@ static LIST_HEAD(regmap_debugfs_early_list);
static DEFINE_MUTEX(regmap_debugfs_early_lock);
/* Calculate the length of a fixed format */
-static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
+static size_t regmap_calc_reg_len(int max_val)
{
return snprintf(NULL, 0, "%x", max_val);
}
@@ -173,8 +173,7 @@ static inline void regmap_calc_tot_len(struct regmap *map,
{
/* Calculate the length of a fixed format */
if (!map->debugfs_tot_len) {
- map->debugfs_reg_len = regmap_calc_reg_len(map->max_register,
- buf, count);
+ map->debugfs_reg_len = regmap_calc_reg_len(map->max_register),
map->debugfs_val_len = 2 * map->format.val_bytes;
map->debugfs_tot_len = map->debugfs_reg_len +
map->debugfs_val_len + 3; /* : \n */
@@ -338,6 +337,7 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file,
char *buf;
char *entry;
int ret;
+ unsigned entry_len;
if (*ppos < 0 || !count)
return -EINVAL;
@@ -365,18 +365,15 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file,
p = 0;
mutex_lock(&map->cache_lock);
list_for_each_entry(c, &map->debugfs_off_cache, list) {
- snprintf(entry, PAGE_SIZE, "%x-%x",
- c->base_reg, c->max_reg);
+ entry_len = snprintf(entry, PAGE_SIZE, "%x-%x\n",
+ c->base_reg, c->max_reg);
if (p >= *ppos) {
- if (buf_pos + 1 + strlen(entry) > count)
+ if (buf_pos + entry_len > count)
break;
- snprintf(buf + buf_pos, count - buf_pos,
- "%s", entry);
- buf_pos += strlen(entry);
- buf[buf_pos] = '\n';
- buf_pos++;
+ memcpy(buf + buf_pos, entry, entry_len);
+ buf_pos += entry_len;
}
- p += strlen(entry) + 1;
+ p += entry_len;
}
mutex_unlock(&map->cache_lock);
@@ -420,7 +417,7 @@ static ssize_t regmap_access_read_file(struct file *file,
return -ENOMEM;
/* Calculate the length of a fixed format */
- reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+ reg_len = regmap_calc_reg_len(map->max_register);
tot_len = reg_len + 10; /* ': R W V P\n' */
for (i = 0; i <= map->max_register; i += map->reg_stride) {
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 38d1f72d869c..8d16db533527 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -63,6 +63,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
struct regmap *map = d->map;
int i, ret;
u32 reg;
+ u32 unmask_offset;
if (d->chip->runtime_pm) {
ret = pm_runtime_get_sync(map->dev);
@@ -79,12 +80,28 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
for (i = 0; i < d->chip->num_regs; i++) {
reg = d->chip->mask_base +
(i * map->reg_stride * d->irq_reg_stride);
- if (d->chip->mask_invert)
+ if (d->chip->mask_invert) {
ret = regmap_update_bits(d->map, reg,
d->mask_buf_def[i], ~d->mask_buf[i]);
- else
+ } else if (d->chip->unmask_base) {
+ /* set mask with mask_base register */
+ ret = regmap_update_bits(d->map, reg,
+ d->mask_buf_def[i], ~d->mask_buf[i]);
+ if (ret < 0)
+ dev_err(d->map->dev,
+ "Failed to sync unmasks in %x\n",
+ reg);
+ unmask_offset = d->chip->unmask_base -
+ d->chip->mask_base;
+ /* clear mask with unmask_base register */
+ ret = regmap_update_bits(d->map,
+ reg + unmask_offset,
+ d->mask_buf_def[i],
+ d->mask_buf[i]);
+ } else {
ret = regmap_update_bits(d->map, reg,
d->mask_buf_def[i], d->mask_buf[i]);
+ }
if (ret != 0)
dev_err(d->map->dev, "Failed to sync masks in %x\n",
reg);
@@ -116,7 +133,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) {
reg = d->chip->ack_base +
(i * map->reg_stride * d->irq_reg_stride);
- ret = regmap_write(map, reg, d->mask_buf[i]);
+ /* some chips ack by write 0 */
+ if (d->chip->ack_invert)
+ ret = regmap_write(map, reg, ~d->mask_buf[i]);
+ else
+ ret = regmap_write(map, reg, d->mask_buf[i]);
if (ret != 0)
dev_err(d->map->dev, "Failed to ack 0x%x: %d\n",
reg, ret);
@@ -339,6 +360,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
int i;
int ret = -ENOMEM;
u32 reg;
+ u32 unmask_offset;
if (chip->num_regs <= 0)
return -EINVAL;
@@ -420,7 +442,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
if (chip->mask_invert)
ret = regmap_update_bits(map, reg,
d->mask_buf[i], ~d->mask_buf[i]);
- else
+ else if (d->chip->unmask_base) {
+ unmask_offset = d->chip->unmask_base -
+ d->chip->mask_base;
+ ret = regmap_update_bits(d->map,
+ reg + unmask_offset,
+ d->mask_buf[i],
+ d->mask_buf[i]);
+ } else
ret = regmap_update_bits(map, reg,
d->mask_buf[i], d->mask_buf[i]);
if (ret != 0) {
@@ -445,7 +474,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
reg = chip->ack_base +
(i * map->reg_stride * d->irq_reg_stride);
- ret = regmap_write(map, reg,
+ if (chip->ack_invert)
+ ret = regmap_write(map, reg,
+ ~(d->status_buf[i] & d->mask_buf[i]));
+ else
+ ret = regmap_write(map, reg,
d->status_buf[i] & d->mask_buf[i]);
if (ret != 0) {
dev_err(map->dev, "Failed to ack 0x%x: %d\n",
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index afaf56200674..4ac63c0e50c7 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -561,6 +561,16 @@ struct regmap *__regmap_init(struct device *dev,
}
map->lock_arg = map;
}
+
+ /*
+ * When we write in fast-paths with regmap_bulk_write() don't allocate
+ * scratch buffers with sleeping allocations.
+ */
+ if ((bus && bus->fast_io) || config->fast_io)
+ map->alloc_flags = GFP_ATOMIC;
+ else
+ map->alloc_flags = GFP_KERNEL;
+
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
map->format.pad_bytes = config->pad_bits / 8;
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
@@ -619,6 +629,7 @@ struct regmap *__regmap_init(struct device *dev,
goto skip_format_initialization;
} else {
map->reg_read = _regmap_bus_read;
+ map->reg_update_bits = bus->reg_update_bits;
}
reg_endian = regmap_get_reg_endian(bus, config);
@@ -1786,7 +1797,7 @@ out:
if (!val_count)
return -EINVAL;
- wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL);
+ wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
if (!wval) {
dev_err(map->dev, "Error in memory allocation\n");
return -ENOMEM;
@@ -2509,20 +2520,26 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
int ret;
unsigned int tmp, orig;
- ret = _regmap_read(map, reg, &orig);
- if (ret != 0)
- return ret;
+ if (change)
+ *change = false;
- tmp = orig & ~mask;
- tmp |= val & mask;
-
- if (force_write || (tmp != orig)) {
- ret = _regmap_write(map, reg, tmp);
- if (change)
+ if (regmap_volatile(map, reg) && map->reg_update_bits) {
+ ret = map->reg_update_bits(map->bus_context, reg, mask, val);
+ if (ret == 0 && change)
*change = true;
} else {
- if (change)
- *change = false;
+ ret = _regmap_read(map, reg, &orig);
+ if (ret != 0)
+ return ret;
+
+ tmp = orig & ~mask;
+ tmp |= val & mask;
+
+ if (force_write || (tmp != orig)) {
+ ret = _regmap_write(map, reg, tmp);
+ if (ret == 0 && change)
+ *change = true;
+ }
}
return ret;
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index 39fca01c8fa1..75b98aad6faf 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -16,7 +16,6 @@
#include <linux/err.h>
static DEFINE_IDA(soc_ida);
-static DEFINE_SPINLOCK(soc_lock);
static ssize_t soc_info_get(struct device *dev,
struct device_attribute *attr,
@@ -122,20 +121,10 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
}
/* Fetch a unique (reclaimable) SOC ID. */
- do {
- if (!ida_pre_get(&soc_ida, GFP_KERNEL)) {
- ret = -ENOMEM;
- goto out2;
- }
-
- spin_lock(&soc_lock);
- ret = ida_get_new(&soc_ida, &soc_dev->soc_dev_num);
- spin_unlock(&soc_lock);
-
- } while (ret == -EAGAIN);
-
- if (ret)
+ ret = ida_simple_get(&soc_ida, 0, 0, GFP_KERNEL);
+ if (ret < 0)
goto out2;
+ soc_dev->soc_dev_num = ret;
soc_dev->attr = soc_dev_attr;
soc_dev->dev.bus = &soc_bus_type;
@@ -151,7 +140,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
return soc_dev;
out3:
- ida_remove(&soc_ida, soc_dev->soc_dev_num);
+ ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
out2:
kfree(soc_dev);
out1:
@@ -161,7 +150,7 @@ out1:
/* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */
void soc_device_unregister(struct soc_device *soc_dev)
{
- ida_remove(&soc_ida, soc_dev->soc_dev_num);
+ ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
device_unregister(&soc_dev->dev);
}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 24882c18fcbe..59d8d0d14824 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -436,13 +436,8 @@ int bcma_bus_register(struct bcma_bus *bus)
}
dev = bcma_bus_get_host_dev(bus);
- /* TODO: remove check for IS_BUILTIN(CONFIG_BCMA) check when
- * of_default_bus_match_table is exported or in some other way
- * accessible. This is just a temporary workaround.
- */
- if (IS_BUILTIN(CONFIG_BCMA) && dev) {
- of_platform_populate(dev->of_node, of_default_bus_match_table,
- NULL, dev);
+ if (dev) {
+ of_platform_default_populate(dev->of_node, NULL, dev);
}
/* Cores providing flash access go before SPROM init */
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 1b8094d4d7af..29819e719afa 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -310,17 +310,6 @@ config BLK_DEV_NBD
If unsure, say N.
-config BLK_DEV_NVME
- tristate "NVM Express block device"
- depends on PCI
- ---help---
- The NVM Express driver is for solid state drives directly
- connected to the PCI or PCI Express bus. If you know you
- don't have one of these, it is safe to answer N.
-
- To compile this driver as a module, choose M here: the
- module will be called nvme.
-
config BLK_DEV_SKD
tristate "STEC S1120 Block Driver"
depends on PCI
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 02b688d1438d..671329023ec2 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_MG_DISK) += mg_disk.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
-obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
obj-$(CONFIG_BLK_DEV_SKD) += skd.o
obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o
@@ -44,6 +43,5 @@ obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/
obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_blk.o
obj-$(CONFIG_ZRAM) += zram/
-nvme-y := nvme-core.o nvme-scsi.o
skd-y := skd_main.o
swim_mod-y := swim.o swim_asm.o
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index b9794aeeb878..a5880f4ab40e 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -323,7 +323,7 @@ out:
return err;
}
-static void brd_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
struct brd_device *brd = bdev->bd_disk->private_data;
@@ -337,6 +337,9 @@ static void brd_make_request(struct request_queue *q, struct bio *bio)
goto io_error;
if (unlikely(bio->bi_rw & REQ_DISCARD)) {
+ if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) ||
+ bio->bi_iter.bi_size & PAGE_MASK)
+ goto io_error;
discard_from_brd(brd, sector, bio->bi_iter.bi_size);
goto out;
}
@@ -358,9 +361,10 @@ static void brd_make_request(struct request_queue *q, struct bio *bio)
out:
bio_endio(bio);
- return;
+ return BLK_QC_T_NONE;
io_error:
bio_io_error(bio);
+ return BLK_QC_T_NONE;
}
static int brd_rw_page(struct block_device *bdev, sector_t sector,
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index e5e0f19ceda0..9462d2752850 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -29,7 +29,7 @@
#include <linux/string.h>
#include <linux/drbd.h>
#include <linux/slab.h>
-#include <asm/kmap_types.h>
+#include <linux/highmem.h>
#include "drbd_int.h"
@@ -1007,7 +1007,7 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho
bm_set_page_unchanged(b->bm_pages[page_nr]);
if (ctx->flags & BM_AIO_COPY_PAGES) {
- page = mempool_alloc(drbd_md_io_page_pool, __GFP_HIGHMEM|__GFP_WAIT);
+ page = mempool_alloc(drbd_md_io_page_pool, __GFP_HIGHMEM|__GFP_RECLAIM);
copy_highpage(page, b->bm_pages[page_nr]);
bm_store_page_idx(page, page_nr);
} else
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 015c6e91b756..e66d453a5f2b 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1448,7 +1448,7 @@ extern int proc_details;
/* drbd_req */
extern void do_submit(struct work_struct *ws);
extern void __drbd_make_request(struct drbd_device *, struct bio *, unsigned long);
-extern void drbd_make_request(struct request_queue *q, struct bio *bio);
+extern blk_qc_t drbd_make_request(struct request_queue *q, struct bio *bio);
extern int drbd_read_remote(struct drbd_device *device, struct drbd_request *req);
extern int is_valid_ar_handle(struct drbd_request *, sector_t);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index c097909c589c..b4b5680ac6ad 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -357,7 +357,8 @@ drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t secto
}
if (has_payload && data_size) {
- page = drbd_alloc_pages(peer_device, nr_pages, (gfp_mask & __GFP_WAIT));
+ page = drbd_alloc_pages(peer_device, nr_pages,
+ gfpflags_allow_blocking(gfp_mask));
if (!page)
goto fail;
}
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 211592682169..3ae2c0086563 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1494,7 +1494,7 @@ void do_submit(struct work_struct *ws)
}
}
-void drbd_make_request(struct request_queue *q, struct bio *bio)
+blk_qc_t drbd_make_request(struct request_queue *q, struct bio *bio)
{
struct drbd_device *device = (struct drbd_device *) q->queuedata;
unsigned long start_jif;
@@ -1510,6 +1510,7 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
inc_ap_bio(device);
__drbd_make_request(device, bio, start_jif);
+ return BLK_QC_T_NONE;
}
void request_timer_fn(unsigned long data)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 674f800a3b57..423f4ca7d712 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -164,6 +164,62 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file)
return get_size(lo->lo_offset, lo->lo_sizelimit, file);
}
+static void __loop_update_dio(struct loop_device *lo, bool dio)
+{
+ struct file *file = lo->lo_backing_file;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ unsigned short sb_bsize = 0;
+ unsigned dio_align = 0;
+ bool use_dio;
+
+ if (inode->i_sb->s_bdev) {
+ sb_bsize = bdev_logical_block_size(inode->i_sb->s_bdev);
+ dio_align = sb_bsize - 1;
+ }
+
+ /*
+ * We support direct I/O only if lo_offset is aligned with the
+ * logical I/O size of backing device, and the logical block
+ * size of loop is bigger than the backing device's and the loop
+ * needn't transform transfer.
+ *
+ * TODO: the above condition may be loosed in the future, and
+ * direct I/O may be switched runtime at that time because most
+ * of requests in sane appplications should be PAGE_SIZE algined
+ */
+ if (dio) {
+ if (queue_logical_block_size(lo->lo_queue) >= sb_bsize &&
+ !(lo->lo_offset & dio_align) &&
+ mapping->a_ops->direct_IO &&
+ !lo->transfer)
+ use_dio = true;
+ else
+ use_dio = false;
+ } else {
+ use_dio = false;
+ }
+
+ if (lo->use_dio == use_dio)
+ return;
+
+ /* flush dirty pages before changing direct IO */
+ vfs_fsync(file, 0);
+
+ /*
+ * The flag of LO_FLAGS_DIRECT_IO is handled similarly with
+ * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup
+ * will get updated by ioctl(LOOP_GET_STATUS)
+ */
+ blk_mq_freeze_queue(lo->lo_queue);
+ lo->use_dio = use_dio;
+ if (use_dio)
+ lo->lo_flags |= LO_FLAGS_DIRECT_IO;
+ else
+ lo->lo_flags &= ~LO_FLAGS_DIRECT_IO;
+ blk_mq_unfreeze_queue(lo->lo_queue);
+}
+
static int
figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
{
@@ -389,6 +445,89 @@ static int lo_req_flush(struct loop_device *lo, struct request *rq)
return ret;
}
+static inline void handle_partial_read(struct loop_cmd *cmd, long bytes)
+{
+ if (bytes < 0 || (cmd->rq->cmd_flags & REQ_WRITE))
+ return;
+
+ if (unlikely(bytes < blk_rq_bytes(cmd->rq))) {
+ struct bio *bio = cmd->rq->bio;
+
+ bio_advance(bio, bytes);
+ zero_fill_bio(bio);
+ }
+}
+
+static void lo_rw_aio_complete(struct kiocb *iocb, long ret, long ret2)
+{
+ struct loop_cmd *cmd = container_of(iocb, struct loop_cmd, iocb);
+ struct request *rq = cmd->rq;
+
+ handle_partial_read(cmd, ret);
+
+ if (ret > 0)
+ ret = 0;
+ else if (ret < 0)
+ ret = -EIO;
+
+ blk_mq_complete_request(rq, ret);
+}
+
+static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
+ loff_t pos, bool rw)
+{
+ struct iov_iter iter;
+ struct bio_vec *bvec;
+ struct bio *bio = cmd->rq->bio;
+ struct file *file = lo->lo_backing_file;
+ int ret;
+
+ /* nomerge for loop request queue */
+ WARN_ON(cmd->rq->bio != cmd->rq->biotail);
+
+ bvec = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
+ iov_iter_bvec(&iter, ITER_BVEC | rw, bvec,
+ bio_segments(bio), blk_rq_bytes(cmd->rq));
+
+ cmd->iocb.ki_pos = pos;
+ cmd->iocb.ki_filp = file;
+ cmd->iocb.ki_complete = lo_rw_aio_complete;
+ cmd->iocb.ki_flags = IOCB_DIRECT;
+
+ if (rw == WRITE)
+ ret = file->f_op->write_iter(&cmd->iocb, &iter);
+ else
+ ret = file->f_op->read_iter(&cmd->iocb, &iter);
+
+ if (ret != -EIOCBQUEUED)
+ cmd->iocb.ki_complete(&cmd->iocb, ret, 0);
+ return 0;
+}
+
+
+static inline int lo_rw_simple(struct loop_device *lo,
+ struct request *rq, loff_t pos, bool rw)
+{
+ struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
+
+ if (cmd->use_aio)
+ return lo_rw_aio(lo, cmd, pos, rw);
+
+ /*
+ * lo_write_simple and lo_read_simple should have been covered
+ * by io submit style function like lo_rw_aio(), one blocker
+ * is that lo_read_simple() need to call flush_dcache_page after
+ * the page is written from kernel, and it isn't easy to handle
+ * this in io submit style function which submits all segments
+ * of the req at one time. And direct read IO doesn't need to
+ * run flush_dcache_page().
+ */
+ if (rw == WRITE)
+ return lo_write_simple(lo, rq, pos);
+ else
+ return lo_read_simple(lo, rq, pos);
+}
+
static int do_req_filebacked(struct loop_device *lo, struct request *rq)
{
loff_t pos;
@@ -404,13 +543,13 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
else if (lo->transfer)
ret = lo_write_transfer(lo, rq, pos);
else
- ret = lo_write_simple(lo, rq, pos);
+ ret = lo_rw_simple(lo, rq, pos, WRITE);
} else {
if (lo->transfer)
ret = lo_read_transfer(lo, rq, pos);
else
- ret = lo_read_simple(lo, rq, pos);
+ ret = lo_rw_simple(lo, rq, pos, READ);
}
return ret;
@@ -421,6 +560,12 @@ struct switch_request {
struct completion wait;
};
+static inline void loop_update_dio(struct loop_device *lo)
+{
+ __loop_update_dio(lo, io_is_direct(lo->lo_backing_file) |
+ lo->use_dio);
+}
+
/*
* Do the actual switch; called from the BIO completion routine
*/
@@ -441,6 +586,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
+ loop_update_dio(lo);
}
/*
@@ -627,11 +773,19 @@ static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
return sprintf(buf, "%s\n", partscan ? "1" : "0");
}
+static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
+{
+ int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO);
+
+ return sprintf(buf, "%s\n", dio ? "1" : "0");
+}
+
LOOP_ATTR_RO(backing_file);
LOOP_ATTR_RO(offset);
LOOP_ATTR_RO(sizelimit);
LOOP_ATTR_RO(autoclear);
LOOP_ATTR_RO(partscan);
+LOOP_ATTR_RO(dio);
static struct attribute *loop_attrs[] = {
&loop_attr_backing_file.attr,
@@ -639,6 +793,7 @@ static struct attribute *loop_attrs[] = {
&loop_attr_sizelimit.attr,
&loop_attr_autoclear.attr,
&loop_attr_partscan.attr,
+ &loop_attr_dio.attr,
NULL,
};
@@ -688,6 +843,23 @@ static void loop_config_discard(struct loop_device *lo)
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
}
+static void loop_unprepare_queue(struct loop_device *lo)
+{
+ flush_kthread_worker(&lo->worker);
+ kthread_stop(lo->worker_task);
+}
+
+static int loop_prepare_queue(struct loop_device *lo)
+{
+ init_kthread_worker(&lo->worker);
+ lo->worker_task = kthread_run(kthread_worker_fn,
+ &lo->worker, "loop%d", lo->lo_number);
+ if (IS_ERR(lo->worker_task))
+ return -ENOMEM;
+ set_user_nice(lo->worker_task, MIN_NICE);
+ return 0;
+}
+
static int loop_set_fd(struct loop_device *lo, fmode_t mode,
struct block_device *bdev, unsigned int arg)
{
@@ -745,17 +917,15 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
size = get_loop_size(lo, file);
if ((loff_t)(sector_t)size != size)
goto out_putf;
- error = -ENOMEM;
- lo->wq = alloc_workqueue("kloopd%d",
- WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16,
- lo->lo_number);
- if (!lo->wq)
+ error = loop_prepare_queue(lo);
+ if (error)
goto out_putf;
error = 0;
set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
+ lo->use_dio = false;
lo->lo_blocksize = lo_blocksize;
lo->lo_device = bdev;
lo->lo_flags = lo_flags;
@@ -769,6 +939,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
blk_queue_flush(lo->lo_queue, REQ_FLUSH);
+ loop_update_dio(lo);
set_capacity(lo->lo_disk, size);
bd_set_size(bdev, size << 9);
loop_sysfs_init(lo);
@@ -903,8 +1074,7 @@ static int loop_clr_fd(struct loop_device *lo)
lo->lo_flags = 0;
if (!part_shift)
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
- destroy_workqueue(lo->wq);
- lo->wq = NULL;
+ loop_unprepare_queue(lo);
mutex_unlock(&lo->lo_ctl_mutex);
/*
* Need not hold lo_ctl_mutex to fput backing file.
@@ -988,6 +1158,9 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
lo->lo_key_owner = uid;
}
+ /* update dio if lo_offset or transfer is changed */
+ __loop_update_dio(lo, lo->use_dio);
+
return 0;
}
@@ -1138,6 +1311,20 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev)
return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
}
+static int loop_set_dio(struct loop_device *lo, unsigned long arg)
+{
+ int error = -ENXIO;
+ if (lo->lo_state != Lo_bound)
+ goto out;
+
+ __loop_update_dio(lo, !!arg);
+ if (lo->use_dio == !!arg)
+ return 0;
+ error = -EINVAL;
+ out:
+ return error;
+}
+
static int lo_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
@@ -1181,6 +1368,11 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
err = loop_set_capacity(lo, bdev);
break;
+ case LOOP_SET_DIRECT_IO:
+ err = -EPERM;
+ if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+ err = loop_set_dio(lo, arg);
+ break;
default:
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
}
@@ -1461,23 +1653,13 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
if (lo->lo_state != Lo_bound)
return -EIO;
- if (cmd->rq->cmd_flags & REQ_WRITE) {
- struct loop_device *lo = cmd->rq->q->queuedata;
- bool need_sched = true;
-
- spin_lock_irq(&lo->lo_lock);
- if (lo->write_started)
- need_sched = false;
- else
- lo->write_started = true;
- list_add_tail(&cmd->list, &lo->write_cmd_head);
- spin_unlock_irq(&lo->lo_lock);
+ if (lo->use_dio && !(cmd->rq->cmd_flags & (REQ_FLUSH |
+ REQ_DISCARD)))
+ cmd->use_aio = true;
+ else
+ cmd->use_aio = false;
- if (need_sched)
- queue_work(lo->wq, &lo->write_work);
- } else {
- queue_work(lo->wq, &cmd->read_work);
- }
+ queue_kthread_work(&lo->worker, &cmd->work);
return BLK_MQ_RQ_QUEUE_OK;
}
@@ -1495,38 +1677,15 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
ret = do_req_filebacked(lo, cmd->rq);
failed:
- blk_mq_complete_request(cmd->rq, ret ? -EIO : 0);
+ /* complete non-aio request */
+ if (!cmd->use_aio || ret)
+ blk_mq_complete_request(cmd->rq, ret ? -EIO : 0);
}
-static void loop_queue_write_work(struct work_struct *work)
-{
- struct loop_device *lo =
- container_of(work, struct loop_device, write_work);
- LIST_HEAD(cmd_list);
-
- spin_lock_irq(&lo->lo_lock);
- repeat:
- list_splice_init(&lo->write_cmd_head, &cmd_list);
- spin_unlock_irq(&lo->lo_lock);
-
- while (!list_empty(&cmd_list)) {
- struct loop_cmd *cmd = list_first_entry(&cmd_list,
- struct loop_cmd, list);
- list_del_init(&cmd->list);
- loop_handle_cmd(cmd);
- }
-
- spin_lock_irq(&lo->lo_lock);
- if (!list_empty(&lo->write_cmd_head))
- goto repeat;
- lo->write_started = false;
- spin_unlock_irq(&lo->lo_lock);
-}
-
-static void loop_queue_read_work(struct work_struct *work)
+static void loop_queue_work(struct kthread_work *work)
{
struct loop_cmd *cmd =
- container_of(work, struct loop_cmd, read_work);
+ container_of(work, struct loop_cmd, work);
loop_handle_cmd(cmd);
}
@@ -1538,7 +1697,7 @@ static int loop_init_request(void *data, struct request *rq,
struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
cmd->rq = rq;
- INIT_WORK(&cmd->read_work, loop_queue_read_work);
+ init_kthread_work(&cmd->work, loop_queue_work);
return 0;
}
@@ -1594,8 +1753,11 @@ static int loop_add(struct loop_device **l, int i)
}
lo->lo_queue->queuedata = lo;
- INIT_LIST_HEAD(&lo->write_cmd_head);
- INIT_WORK(&lo->write_work, loop_queue_write_work);
+ /*
+ * It doesn't make sense to enable merge because the I/O
+ * submitted to backing file is handled page by page.
+ */
+ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue);
disk = lo->lo_disk = alloc_disk(1 << part_shift);
if (!disk)
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index 25e8997ed246..fb2237c73e61 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -14,7 +14,7 @@
#include <linux/blk-mq.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include <linux/workqueue.h>
+#include <linux/kthread.h>
#include <uapi/linux/loop.h>
/* Possible states of device */
@@ -54,12 +54,11 @@ struct loop_device {
gfp_t old_gfp_mask;
spinlock_t lo_lock;
- struct workqueue_struct *wq;
- struct list_head write_cmd_head;
- struct work_struct write_work;
- bool write_started;
int lo_state;
struct mutex lo_ctl_mutex;
+ struct kthread_worker worker;
+ struct task_struct *worker_task;
+ bool use_dio;
struct request_queue *lo_queue;
struct blk_mq_tag_set tag_set;
@@ -67,9 +66,11 @@ struct loop_device {
};
struct loop_cmd {
- struct work_struct read_work;
+ struct kthread_work work;
struct request *rq;
struct list_head list;
+ bool use_aio; /* use AIO interface to handle I/O */
+ struct kiocb iocb;
};
/* Support for loadable transfer modules */
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index f504232c1ee7..a28a562f7b7f 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -173,7 +173,7 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd)
{
struct request *rq;
- rq = blk_mq_alloc_request(dd->queue, 0, __GFP_WAIT, true);
+ rq = blk_mq_alloc_request(dd->queue, 0, __GFP_RECLAIM, true);
return blk_mq_rq_to_pdu(rq);
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 293495a75d3d..93b3f99b6865 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -60,6 +60,7 @@ struct nbd_device {
bool disconnect; /* a disconnect has been requested by user */
struct timer_list timeout_timer;
+ spinlock_t tasks_lock;
struct task_struct *task_recv;
struct task_struct *task_send;
@@ -140,21 +141,23 @@ static void sock_shutdown(struct nbd_device *nbd)
static void nbd_xmit_timeout(unsigned long arg)
{
struct nbd_device *nbd = (struct nbd_device *)arg;
- struct task_struct *task;
+ unsigned long flags;
if (list_empty(&nbd->queue_head))
return;
nbd->disconnect = true;
- task = READ_ONCE(nbd->task_recv);
- if (task)
- force_sig(SIGKILL, task);
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
+
+ if (nbd->task_recv)
+ force_sig(SIGKILL, nbd->task_recv);
- task = READ_ONCE(nbd->task_send);
- if (task)
+ if (nbd->task_send)
force_sig(SIGKILL, nbd->task_send);
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
}
@@ -403,17 +406,24 @@ static int nbd_thread_recv(struct nbd_device *nbd)
{
struct request *req;
int ret;
+ unsigned long flags;
BUG_ON(nbd->magic != NBD_MAGIC);
sk_set_memalloc(nbd->sock->sk);
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_recv = current;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
if (ret) {
dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_recv = NULL;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
return ret;
}
@@ -429,12 +439,12 @@ static int nbd_thread_recv(struct nbd_device *nbd)
device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_recv = NULL;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
if (signal_pending(current)) {
- siginfo_t info;
-
- ret = dequeue_signal_lock(current, &current->blocked, &info);
+ ret = kernel_dequeue_signal(NULL);
dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
task_pid_nr(current), current->comm, ret);
mutex_lock(&nbd->tx_lock);
@@ -534,8 +544,11 @@ static int nbd_thread_send(void *data)
{
struct nbd_device *nbd = data;
struct request *req;
+ unsigned long flags;
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_send = current;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
set_user_nice(current, MIN_NICE);
while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -545,11 +558,8 @@ static int nbd_thread_send(void *data)
!list_empty(&nbd->waiting_queue));
if (signal_pending(current)) {
- siginfo_t info;
- int ret;
+ int ret = kernel_dequeue_signal(NULL);
- ret = dequeue_signal_lock(current, &current->blocked,
- &info);
dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
task_pid_nr(current), current->comm, ret);
mutex_lock(&nbd->tx_lock);
@@ -572,7 +582,13 @@ static int nbd_thread_send(void *data)
nbd_handle_req(nbd, req);
}
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_send = NULL;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
+ /* Clear maybe pending signals */
+ if (signal_pending(current))
+ kernel_dequeue_signal(NULL);
return 0;
}
@@ -1052,6 +1068,7 @@ static int __init nbd_init(void)
nbd_dev[i].magic = NBD_MAGIC;
INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
spin_lock_init(&nbd_dev[i].queue_lock);
+ spin_lock_init(&nbd_dev[i].tasks_lock);
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
mutex_init(&nbd_dev[i].tx_lock);
init_timer(&nbd_dev[i].timeout_timer);
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index 1c9e4fe5aa44..6255d1c4bba4 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -321,7 +321,7 @@ static struct nullb_queue *nullb_to_queue(struct nullb *nullb)
return &nullb->queues[index];
}
-static void null_queue_bio(struct request_queue *q, struct bio *bio)
+static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio)
{
struct nullb *nullb = q->queuedata;
struct nullb_queue *nq = nullb_to_queue(nullb);
@@ -331,6 +331,7 @@ static void null_queue_bio(struct request_queue *q, struct bio *bio)
cmd->bio = bio;
null_handle_cmd(cmd);
+ return BLK_QC_T_NONE;
}
static int null_rq_prep_fn(struct request_queue *q, struct request *req)
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index e22942596207..1b709a4e3b5e 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -271,7 +271,7 @@ static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
goto err_out;
tmp->bi_bdev = NULL;
- gfpmask &= ~__GFP_WAIT;
+ gfpmask &= ~__GFP_DIRECT_RECLAIM;
tmp->bi_next = NULL;
if (!new_chain)
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index b9242d78283d..562b5a4ca7b7 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -723,7 +723,7 @@ static int pd_special_command(struct pd_unit *disk,
struct request *rq;
int err = 0;
- rq = blk_get_request(disk->gd->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(disk->gd->queue, READ, __GFP_RECLAIM);
if (IS_ERR(rq))
return PTR_ERR(rq);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7be2375db7f2..d06c62eccdf0 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -704,14 +704,14 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
int ret = 0;
rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ?
- WRITE : READ, __GFP_WAIT);
+ WRITE : READ, __GFP_RECLAIM);
if (IS_ERR(rq))
return PTR_ERR(rq);
blk_rq_set_block_pc(rq);
if (cgc->buflen) {
ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen,
- __GFP_WAIT);
+ __GFP_RECLAIM);
if (ret)
goto out;
}
@@ -2441,7 +2441,7 @@ static void pkt_make_request_write(struct request_queue *q, struct bio *bio)
}
}
-static void pkt_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t pkt_make_request(struct request_queue *q, struct bio *bio)
{
struct pktcdvd_device *pd;
char b[BDEVNAME_SIZE];
@@ -2467,7 +2467,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
*/
if (bio_data_dir(bio) == READ) {
pkt_make_request_read(pd, bio);
- return;
+ return BLK_QC_T_NONE;
}
if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
@@ -2499,13 +2499,12 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
pkt_make_request_write(q, split);
} while (split != bio);
- return;
+ return BLK_QC_T_NONE;
end_io:
bio_io_error(bio);
+ return BLK_QC_T_NONE;
}
-
-
static void pkt_init_queue(struct pktcdvd_device *pd)
{
struct request_queue *q = pd->disk->queue;
@@ -2803,8 +2802,7 @@ out_new_dev:
out_mem2:
put_disk(disk);
out_mem:
- if (pd->rb_pool)
- mempool_destroy(pd->rb_pool);
+ mempool_destroy(pd->rb_pool);
kfree(pd);
out_mutex:
mutex_unlock(&ctl_mutex);
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index d89fcac59515..56847fcda086 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -598,7 +598,7 @@ out:
return next;
}
-static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t ps3vram_make_request(struct request_queue *q, struct bio *bio)
{
struct ps3_system_bus_device *dev = q->queuedata;
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
@@ -614,11 +614,13 @@ static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
spin_unlock_irq(&priv->lock);
if (busy)
- return;
+ return BLK_QC_T_NONE;
do {
bio = ps3vram_do_bio(dev, bio);
} while (bio);
+
+ return BLK_QC_T_NONE;
}
static int ps3vram_probe(struct ps3_system_bus_device *dev)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d93a0372b37b..235708c7c46e 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -96,6 +96,8 @@ static int atomic_dec_return_safe(atomic_t *v)
#define RBD_MINORS_PER_MAJOR 256
#define RBD_SINGLE_MAJOR_PART_SHIFT 4
+#define RBD_MAX_PARENT_CHAIN_LEN 16
+
#define RBD_SNAP_DEV_NAME_PREFIX "snap_"
#define RBD_MAX_SNAP_NAME_LEN \
(NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
@@ -416,8 +418,6 @@ MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (d
static int rbd_img_request_submit(struct rbd_img_request *img_request);
-static void rbd_dev_device_release(struct device *dev);
-
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,
@@ -426,7 +426,7 @@ 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 int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
static void rbd_spec_put(struct rbd_spec *spec);
static int rbd_dev_id_to_minor(int dev_id)
@@ -1863,9 +1863,11 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
rbd_osd_read_callback(obj_request);
break;
case CEPH_OSD_OP_SETALLOCHINT:
- rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE);
+ rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE ||
+ osd_req->r_ops[1].op == CEPH_OSD_OP_WRITEFULL);
/* fall through */
case CEPH_OSD_OP_WRITE:
+ case CEPH_OSD_OP_WRITEFULL:
rbd_osd_write_callback(obj_request);
break;
case CEPH_OSD_OP_STAT:
@@ -2401,7 +2403,10 @@ static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request,
opcode = CEPH_OSD_OP_ZERO;
}
} else if (op_type == OBJ_OP_WRITE) {
- opcode = CEPH_OSD_OP_WRITE;
+ if (!offset && length == object_size)
+ opcode = CEPH_OSD_OP_WRITEFULL;
+ else
+ opcode = CEPH_OSD_OP_WRITE;
osd_req_op_alloc_hint_init(osd_request, num_ops,
object_size, object_size);
num_ops++;
@@ -3760,6 +3765,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
/* set io sizes to object size */
segment_size = rbd_obj_bytes(&rbd_dev->header);
blk_queue_max_hw_sectors(q, segment_size / SECTOR_SIZE);
+ q->limits.max_sectors = queue_max_hw_sectors(q);
blk_queue_max_segments(q, segment_size / SECTOR_SIZE);
blk_queue_max_segment_size(q, segment_size);
blk_queue_io_min(q, segment_size);
@@ -3772,6 +3778,9 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE);
q->limits.discard_zeroes_data = 1;
+ if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
+ q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+
disk->queue = q;
q->queuedata = rbd_dev;
@@ -3980,14 +3989,12 @@ static const struct attribute_group *rbd_attr_groups[] = {
NULL
};
-static void rbd_sysfs_dev_release(struct device *dev)
-{
-}
+static void rbd_dev_release(struct device *dev);
static struct device_type rbd_device_type = {
.name = "rbd",
.groups = rbd_attr_groups,
- .release = rbd_sysfs_dev_release,
+ .release = rbd_dev_release,
};
static struct rbd_spec *rbd_spec_get(struct rbd_spec *spec)
@@ -4030,6 +4037,25 @@ static void rbd_spec_free(struct kref *kref)
kfree(spec);
}
+static void rbd_dev_release(struct device *dev)
+{
+ struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+ bool need_put = !!rbd_dev->opts;
+
+ rbd_put_client(rbd_dev->rbd_client);
+ rbd_spec_put(rbd_dev->spec);
+ kfree(rbd_dev->opts);
+ kfree(rbd_dev);
+
+ /*
+ * This is racy, but way better than putting module outside of
+ * the release callback. The race window is pretty small, so
+ * doing something similar to dm (dm-builtin.c) is overkill.
+ */
+ if (need_put)
+ module_put(THIS_MODULE);
+}
+
static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
struct rbd_spec *spec,
struct rbd_options *opts)
@@ -4046,6 +4072,11 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
INIT_LIST_HEAD(&rbd_dev->node);
init_rwsem(&rbd_dev->header_rwsem);
+ rbd_dev->dev.bus = &rbd_bus_type;
+ rbd_dev->dev.type = &rbd_device_type;
+ rbd_dev->dev.parent = &rbd_root_dev;
+ device_initialize(&rbd_dev->dev);
+
rbd_dev->rbd_client = rbdc;
rbd_dev->spec = spec;
rbd_dev->opts = opts;
@@ -4057,15 +4088,21 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
rbd_dev->layout.fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
rbd_dev->layout.fl_pg_pool = cpu_to_le32((u32) spec->pool_id);
+ /*
+ * If this is a mapping rbd_dev (as opposed to a parent one),
+ * pin our module. We have a ref from do_rbd_add(), so use
+ * __module_get().
+ */
+ if (rbd_dev->opts)
+ __module_get(THIS_MODULE);
+
return rbd_dev;
}
static void rbd_dev_destroy(struct rbd_device *rbd_dev)
{
- rbd_put_client(rbd_dev->rbd_client);
- rbd_spec_put(rbd_dev->spec);
- kfree(rbd_dev->opts);
- kfree(rbd_dev);
+ if (rbd_dev)
+ put_device(&rbd_dev->dev);
}
/*
@@ -4691,27 +4728,6 @@ static int rbd_dev_header_info(struct rbd_device *rbd_dev)
return rbd_dev_v2_header_info(rbd_dev);
}
-static int rbd_bus_add_dev(struct rbd_device *rbd_dev)
-{
- struct device *dev;
- int ret;
-
- dev = &rbd_dev->dev;
- dev->bus = &rbd_bus_type;
- dev->type = &rbd_device_type;
- dev->parent = &rbd_root_dev;
- dev->release = rbd_dev_device_release;
- dev_set_name(dev, "%d", rbd_dev->dev_id);
- ret = device_register(dev);
-
- return ret;
-}
-
-static void rbd_bus_del_dev(struct rbd_device *rbd_dev)
-{
- device_unregister(&rbd_dev->dev);
-}
-
/*
* Get a unique rbd identifier for the given new rbd_dev, and add
* the rbd_dev to the global list.
@@ -5125,44 +5141,51 @@ out_err:
return ret;
}
-static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
+/*
+ * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() ->
+ * rbd_dev_image_probe() recursion depth, which means it's also the
+ * length of the already discovered part of the parent chain.
+ */
+static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth)
{
struct rbd_device *parent = NULL;
- struct rbd_spec *parent_spec;
- struct rbd_client *rbdc;
int ret;
if (!rbd_dev->parent_spec)
return 0;
- /*
- * We need to pass a reference to the client and the parent
- * spec when creating the parent rbd_dev. Images related by
- * parent/child relationships always share both.
- */
- parent_spec = rbd_spec_get(rbd_dev->parent_spec);
- rbdc = __rbd_get_client(rbd_dev->rbd_client);
- ret = -ENOMEM;
- parent = rbd_dev_create(rbdc, parent_spec, NULL);
- if (!parent)
+ if (++depth > RBD_MAX_PARENT_CHAIN_LEN) {
+ pr_info("parent chain is too long (%d)\n", depth);
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+ parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec,
+ NULL);
+ if (!parent) {
+ ret = -ENOMEM;
goto out_err;
+ }
+
+ /*
+ * Images related by parent/child relationships always share
+ * rbd_client and spec/parent_spec, so bump their refcounts.
+ */
+ __rbd_get_client(rbd_dev->rbd_client);
+ rbd_spec_get(rbd_dev->parent_spec);
- ret = rbd_dev_image_probe(parent, false);
+ ret = rbd_dev_image_probe(parent, depth);
if (ret < 0)
goto out_err;
+
rbd_dev->parent = parent;
atomic_set(&rbd_dev->parent_ref, 1);
-
return 0;
+
out_err:
- if (parent) {
- rbd_dev_unparent(rbd_dev);
+ rbd_dev_unparent(rbd_dev);
+ if (parent)
rbd_dev_destroy(parent);
- } else {
- rbd_put_client(rbdc);
- rbd_spec_put(parent_spec);
- }
-
return ret;
}
@@ -5207,7 +5230,8 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
- ret = rbd_bus_add_dev(rbd_dev);
+ dev_set_name(&rbd_dev->dev, "%d", rbd_dev->dev_id);
+ ret = device_add(&rbd_dev->dev);
if (ret)
goto err_out_mapping;
@@ -5230,8 +5254,6 @@ err_out_blkdev:
unregister_blkdev(rbd_dev->major, rbd_dev->name);
err_out_id:
rbd_dev_id_put(rbd_dev);
- rbd_dev_mapping_clear(rbd_dev);
-
return ret;
}
@@ -5280,7 +5302,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
* parent), initiate a watch on its header object before using that
* object to get detailed information about the rbd image.
*/
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
{
int ret;
@@ -5298,7 +5320,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
if (ret)
goto err_out_format;
- if (mapping) {
+ if (!depth) {
ret = rbd_dev_header_watch_sync(rbd_dev);
if (ret) {
if (ret == -ENOENT)
@@ -5319,7 +5341,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
* Otherwise this is a parent image, identified by pool, image
* and snap ids - need to fill in names for those ids.
*/
- if (mapping)
+ if (!depth)
ret = rbd_spec_fill_snap_id(rbd_dev);
else
ret = rbd_spec_fill_names(rbd_dev);
@@ -5341,12 +5363,12 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
* Need to warn users if this image is the one being
* mapped and has a parent.
*/
- if (mapping && rbd_dev->parent_spec)
+ if (!depth && rbd_dev->parent_spec)
rbd_warn(rbd_dev,
"WARNING: kernel layering is EXPERIMENTAL!");
}
- ret = rbd_dev_probe_parent(rbd_dev);
+ ret = rbd_dev_probe_parent(rbd_dev, depth);
if (ret)
goto err_out_probe;
@@ -5357,7 +5379,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
err_out_probe:
rbd_dev_unprobe(rbd_dev);
err_out_watch:
- if (mapping)
+ if (!depth)
rbd_dev_header_unwatch_sync(rbd_dev);
out_header_name:
kfree(rbd_dev->header_name);
@@ -5379,7 +5401,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
struct rbd_spec *spec = NULL;
struct rbd_client *rbdc;
bool read_only;
- int rc = -ENOMEM;
+ int rc;
if (!try_module_get(THIS_MODULE))
return -ENODEV;
@@ -5387,7 +5409,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
/* parse add command */
rc = rbd_add_parse_args(buf, &ceph_opts, &rbd_opts, &spec);
if (rc < 0)
- goto err_out_module;
+ goto out;
rbdc = rbd_get_client(ceph_opts);
if (IS_ERR(rbdc)) {
@@ -5414,13 +5436,15 @@ static ssize_t do_rbd_add(struct bus_type *bus,
}
rbd_dev = rbd_dev_create(rbdc, spec, rbd_opts);
- if (!rbd_dev)
+ if (!rbd_dev) {
+ rc = -ENOMEM;
goto err_out_client;
+ }
rbdc = NULL; /* rbd_dev now owns this */
spec = NULL; /* rbd_dev now owns this */
rbd_opts = NULL; /* rbd_dev now owns this */
- rc = rbd_dev_image_probe(rbd_dev, true);
+ rc = rbd_dev_image_probe(rbd_dev, 0);
if (rc < 0)
goto err_out_rbd_dev;
@@ -5440,10 +5464,13 @@ static ssize_t do_rbd_add(struct bus_type *bus,
*/
rbd_dev_header_unwatch_sync(rbd_dev);
rbd_dev_image_release(rbd_dev);
- goto err_out_module;
+ goto out;
}
- return count;
+ rc = count;
+out:
+ module_put(THIS_MODULE);
+ return rc;
err_out_rbd_dev:
rbd_dev_destroy(rbd_dev);
@@ -5452,12 +5479,7 @@ err_out_client:
err_out_args:
rbd_spec_put(spec);
kfree(rbd_opts);
-err_out_module:
- module_put(THIS_MODULE);
-
- dout("Error adding device %s\n", buf);
-
- return (ssize_t)rc;
+ goto out;
}
static ssize_t rbd_add(struct bus_type *bus,
@@ -5477,17 +5499,15 @@ static ssize_t rbd_add_single_major(struct bus_type *bus,
return do_rbd_add(bus, buf, count);
}
-static void rbd_dev_device_release(struct device *dev)
+static void rbd_dev_device_release(struct rbd_device *rbd_dev)
{
- struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
-
rbd_free_disk(rbd_dev);
clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
+ device_del(&rbd_dev->dev);
rbd_dev_mapping_clear(rbd_dev);
if (!single_major)
unregister_blkdev(rbd_dev->major, rbd_dev->name);
rbd_dev_id_put(rbd_dev);
- rbd_dev_mapping_clear(rbd_dev);
}
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
@@ -5572,9 +5592,8 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
* rbd_bus_del_dev() will race with rbd_watch_cb(), resulting
* in a potential use after free of rbd_dev->disk or rbd_dev.
*/
- rbd_bus_del_dev(rbd_dev);
+ rbd_dev_device_release(rbd_dev);
rbd_dev_image_release(rbd_dev);
- module_put(THIS_MODULE);
return count;
}
@@ -5645,10 +5664,8 @@ static int rbd_slab_init(void)
if (rbd_segment_name_cache)
return 0;
out_err:
- if (rbd_obj_request_cache) {
- kmem_cache_destroy(rbd_obj_request_cache);
- rbd_obj_request_cache = NULL;
- }
+ kmem_cache_destroy(rbd_obj_request_cache);
+ rbd_obj_request_cache = NULL;
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c
index 3163e4cdc2cc..e1b8b7061d2f 100644
--- a/drivers/block/rsxx/dev.c
+++ b/drivers/block/rsxx/dev.c
@@ -145,7 +145,7 @@ static void bio_dma_done_cb(struct rsxx_cardinfo *card,
}
}
-static void rsxx_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t rsxx_make_request(struct request_queue *q, struct bio *bio)
{
struct rsxx_cardinfo *card = q->queuedata;
struct rsxx_bio_meta *bio_meta;
@@ -199,7 +199,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio)
if (st)
goto queue_err;
- return;
+ return BLK_QC_T_NONE;
queue_err:
kmem_cache_free(bio_meta_pool, bio_meta);
@@ -207,6 +207,7 @@ req_err:
if (st)
bio->bi_error = st;
bio_endio(bio);
+ return BLK_QC_T_NONE;
}
/*----------------- Device Setup -------------------*/
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 04d65790a886..7939b9f87441 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -524,7 +524,7 @@ static int mm_check_plugged(struct cardinfo *card)
return !!blk_check_plugged(mm_unplug, card, sizeof(struct blk_plug_cb));
}
-static void mm_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t mm_make_request(struct request_queue *q, struct bio *bio)
{
struct cardinfo *card = q->queuedata;
pr_debug("mm_make_request %llu %u\n",
@@ -541,7 +541,7 @@ static void mm_make_request(struct request_queue *q, struct bio *bio)
activate(card);
spin_unlock_irq(&card->lock);
- return;
+ return BLK_QC_T_NONE;
}
static irqreturn_t mm_interrupt(int irq, void *__card)
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 6a685aec6994..f9099940c272 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -87,7 +87,7 @@ MODULE_PARM_DESC(max_persistent_grants,
* Maximum order of pages to be used for the shared ring between front and
* backend, 4KB page granularity is used.
*/
-unsigned int xen_blkif_max_ring_order = XENBUS_MAX_RING_PAGE_ORDER;
+unsigned int xen_blkif_max_ring_order = XENBUS_MAX_RING_GRANT_ORDER;
module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, S_IRUGO);
MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
/*
@@ -961,7 +961,7 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
seg[n].nsec = segments[i].last_sect -
segments[i].first_sect + 1;
seg[n].offset = (segments[i].first_sect << 9);
- if ((segments[i].last_sect >= (PAGE_SIZE >> 9)) ||
+ if ((segments[i].last_sect >= (XEN_PAGE_SIZE >> 9)) ||
(segments[i].last_sect < segments[i].first_sect)) {
rc = -EINVAL;
goto unmap;
@@ -1210,6 +1210,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
req_operation = req->operation == BLKIF_OP_INDIRECT ?
req->u.indirect.indirect_op : req->operation;
+
if ((req->operation == BLKIF_OP_INDIRECT) &&
(req_operation != BLKIF_OP_READ) &&
(req_operation != BLKIF_OP_WRITE)) {
@@ -1268,7 +1269,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
seg[i].nsec = req->u.rw.seg[i].last_sect -
req->u.rw.seg[i].first_sect + 1;
seg[i].offset = (req->u.rw.seg[i].first_sect << 9);
- if ((req->u.rw.seg[i].last_sect >= (PAGE_SIZE >> 9)) ||
+ if ((req->u.rw.seg[i].last_sect >= (XEN_PAGE_SIZE >> 9)) ||
(req->u.rw.seg[i].last_sect <
req->u.rw.seg[i].first_sect))
goto fail_response;
@@ -1445,10 +1446,10 @@ static int __init xen_blkif_init(void)
if (!xen_domain())
return -ENODEV;
- if (xen_blkif_max_ring_order > XENBUS_MAX_RING_PAGE_ORDER) {
+ if (xen_blkif_max_ring_order > XENBUS_MAX_RING_GRANT_ORDER) {
pr_info("Invalid max_ring_order (%d), will use default max: %d.\n",
- xen_blkif_max_ring_order, XENBUS_MAX_RING_PAGE_ORDER);
- xen_blkif_max_ring_order = XENBUS_MAX_RING_PAGE_ORDER;
+ xen_blkif_max_ring_order, XENBUS_MAX_RING_GRANT_ORDER);
+ xen_blkif_max_ring_order = XENBUS_MAX_RING_GRANT_ORDER;
}
rc = xen_blkif_interface_init();
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 45a044a53d1e..68e87a037b99 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -39,6 +39,7 @@
#include <asm/pgalloc.h>
#include <asm/hypervisor.h>
#include <xen/grant_table.h>
+#include <xen/page.h>
#include <xen/xenbus.h>
#include <xen/interface/io/ring.h>
#include <xen/interface/io/blkif.h>
@@ -51,12 +52,20 @@ extern unsigned int xen_blkif_max_ring_order;
*/
#define MAX_INDIRECT_SEGMENTS 256
-#define SEGS_PER_INDIRECT_FRAME \
- (PAGE_SIZE/sizeof(struct blkif_request_segment))
+/*
+ * Xen use 4K pages. The guest may use different page size (4K or 64K)
+ * Number of Xen pages per segment
+ */
+#define XEN_PAGES_PER_SEGMENT (PAGE_SIZE / XEN_PAGE_SIZE)
+
+#define XEN_PAGES_PER_INDIRECT_FRAME \
+ (XEN_PAGE_SIZE/sizeof(struct blkif_request_segment))
+#define SEGS_PER_INDIRECT_FRAME \
+ (XEN_PAGES_PER_INDIRECT_FRAME / XEN_PAGES_PER_SEGMENT)
+
#define MAX_INDIRECT_PAGES \
((MAX_INDIRECT_SEGMENTS + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
-#define INDIRECT_PAGES(_segs) \
- ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
+#define INDIRECT_PAGES(_segs) DIV_ROUND_UP(_segs, XEN_PAGES_PER_INDIRECT_FRAME)
/* Not a real protocol. Used to generate ring structs which contain
* the elements common to all protocols only. This way we get a
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 767657565de6..f53cff42f8da 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -176,21 +176,24 @@ static int xen_blkif_map(struct xen_blkif *blkif, grant_ref_t *gref,
{
struct blkif_sring *sring;
sring = (struct blkif_sring *)blkif->blk_ring;
- BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE * nr_grefs);
+ BACK_RING_INIT(&blkif->blk_rings.native, sring,
+ XEN_PAGE_SIZE * nr_grefs);
break;
}
case BLKIF_PROTOCOL_X86_32:
{
struct blkif_x86_32_sring *sring_x86_32;
sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring;
- BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE * nr_grefs);
+ BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32,
+ XEN_PAGE_SIZE * nr_grefs);
break;
}
case BLKIF_PROTOCOL_X86_64:
{
struct blkif_x86_64_sring *sring_x86_64;
sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring;
- BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE * nr_grefs);
+ BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64,
+ XEN_PAGE_SIZE * nr_grefs);
break;
}
default:
@@ -826,7 +829,7 @@ again:
static int connect_ring(struct backend_info *be)
{
struct xenbus_device *dev = be->dev;
- unsigned int ring_ref[XENBUS_MAX_RING_PAGES];
+ unsigned int ring_ref[XENBUS_MAX_RING_GRANTS];
unsigned int evtchn, nr_grefs, ring_page_order;
unsigned int pers_grants;
char protocol[64] = "";
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 611170896b8c..2fee2eef988d 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -68,7 +68,7 @@ enum blkif_state {
struct grant {
grant_ref_t gref;
- unsigned long pfn;
+ struct page *page;
struct list_head node;
};
@@ -78,6 +78,7 @@ struct blk_shadow {
struct grant **grants_used;
struct grant **indirect_grants;
struct scatterlist *sg;
+ unsigned int num_sg;
};
struct split_bio {
@@ -106,8 +107,12 @@ static unsigned int xen_blkif_max_ring_order;
module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, S_IRUGO);
MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
-#define BLK_RING_SIZE(info) __CONST_RING_SIZE(blkif, PAGE_SIZE * (info)->nr_ring_pages)
-#define BLK_MAX_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE * XENBUS_MAX_RING_PAGES)
+#define BLK_RING_SIZE(info) \
+ __CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages)
+
+#define BLK_MAX_RING_SIZE \
+ __CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * XENBUS_MAX_RING_GRANTS)
+
/*
* ring-ref%i i=(-1UL) would take 11 characters + 'ring-ref' is 8, so 19
* characters are enough. Define to 20 to keep consist with backend.
@@ -128,7 +133,7 @@ struct blkfront_info
int vdevice;
blkif_vdev_t handle;
enum blkif_state connected;
- int ring_ref[XENBUS_MAX_RING_PAGES];
+ int ring_ref[XENBUS_MAX_RING_GRANTS];
unsigned int nr_ring_pages;
struct blkif_front_ring ring;
unsigned int evtchn, irq;
@@ -146,6 +151,7 @@ struct blkfront_info
unsigned int discard_granularity;
unsigned int discard_alignment;
unsigned int feature_persistent:1;
+ /* Number of 4KB segments handled */
unsigned int max_indirect_segments;
int is_ready;
struct blk_mq_tag_set tag_set;
@@ -174,10 +180,23 @@ static DEFINE_SPINLOCK(minor_lock);
#define DEV_NAME "xvd" /* name in /dev */
-#define SEGS_PER_INDIRECT_FRAME \
- (PAGE_SIZE/sizeof(struct blkif_request_segment))
-#define INDIRECT_GREFS(_segs) \
- ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
+/*
+ * Grants are always the same size as a Xen page (i.e 4KB).
+ * A physical segment is always the same size as a Linux page.
+ * Number of grants per physical segment
+ */
+#define GRANTS_PER_PSEG (PAGE_SIZE / XEN_PAGE_SIZE)
+
+#define GRANTS_PER_INDIRECT_FRAME \
+ (XEN_PAGE_SIZE / sizeof(struct blkif_request_segment))
+
+#define PSEGS_PER_INDIRECT_FRAME \
+ (GRANTS_INDIRECT_FRAME / GRANTS_PSEGS)
+
+#define INDIRECT_GREFS(_grants) \
+ DIV_ROUND_UP(_grants, GRANTS_PER_INDIRECT_FRAME)
+
+#define GREFS(_psegs) ((_psegs) * GRANTS_PER_PSEG)
static int blkfront_setup_indirect(struct blkfront_info *info);
static int blkfront_gather_backend_features(struct blkfront_info *info);
@@ -221,7 +240,7 @@ static int fill_grant_buffer(struct blkfront_info *info, int num)
kfree(gnt_list_entry);
goto out_of_memory;
}
- gnt_list_entry->pfn = page_to_pfn(granted_page);
+ gnt_list_entry->page = granted_page;
}
gnt_list_entry->gref = GRANT_INVALID_REF;
@@ -236,7 +255,7 @@ out_of_memory:
&info->grants, node) {
list_del(&gnt_list_entry->node);
if (info->feature_persistent)
- __free_page(pfn_to_page(gnt_list_entry->pfn));
+ __free_page(gnt_list_entry->page);
kfree(gnt_list_entry);
i--;
}
@@ -244,34 +263,77 @@ out_of_memory:
return -ENOMEM;
}
-static struct grant *get_grant(grant_ref_t *gref_head,
- unsigned long pfn,
- struct blkfront_info *info)
+static struct grant *get_free_grant(struct blkfront_info *info)
{
struct grant *gnt_list_entry;
- unsigned long buffer_gfn;
BUG_ON(list_empty(&info->grants));
gnt_list_entry = list_first_entry(&info->grants, struct grant,
- node);
+ node);
list_del(&gnt_list_entry->node);
- if (gnt_list_entry->gref != GRANT_INVALID_REF) {
+ if (gnt_list_entry->gref != GRANT_INVALID_REF)
info->persistent_gnts_c--;
+
+ return gnt_list_entry;
+}
+
+static inline void grant_foreign_access(const struct grant *gnt_list_entry,
+ const struct blkfront_info *info)
+{
+ gnttab_page_grant_foreign_access_ref_one(gnt_list_entry->gref,
+ info->xbdev->otherend_id,
+ gnt_list_entry->page,
+ 0);
+}
+
+static struct grant *get_grant(grant_ref_t *gref_head,
+ unsigned long gfn,
+ struct blkfront_info *info)
+{
+ struct grant *gnt_list_entry = get_free_grant(info);
+
+ if (gnt_list_entry->gref != GRANT_INVALID_REF)
return gnt_list_entry;
+
+ /* Assign a gref to this page */
+ gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
+ BUG_ON(gnt_list_entry->gref == -ENOSPC);
+ if (info->feature_persistent)
+ grant_foreign_access(gnt_list_entry, info);
+ else {
+ /* Grant access to the GFN passed by the caller */
+ gnttab_grant_foreign_access_ref(gnt_list_entry->gref,
+ info->xbdev->otherend_id,
+ gfn, 0);
}
+ return gnt_list_entry;
+}
+
+static struct grant *get_indirect_grant(grant_ref_t *gref_head,
+ struct blkfront_info *info)
+{
+ struct grant *gnt_list_entry = get_free_grant(info);
+
+ if (gnt_list_entry->gref != GRANT_INVALID_REF)
+ return gnt_list_entry;
+
/* Assign a gref to this page */
gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
BUG_ON(gnt_list_entry->gref == -ENOSPC);
if (!info->feature_persistent) {
- BUG_ON(!pfn);
- gnt_list_entry->pfn = pfn;
+ struct page *indirect_page;
+
+ /* Fetch a pre-allocated page to use for indirect grefs */
+ BUG_ON(list_empty(&info->indirect_pages));
+ indirect_page = list_first_entry(&info->indirect_pages,
+ struct page, lru);
+ list_del(&indirect_page->lru);
+ gnt_list_entry->page = indirect_page;
}
- buffer_gfn = pfn_to_gfn(gnt_list_entry->pfn);
- gnttab_grant_foreign_access_ref(gnt_list_entry->gref,
- info->xbdev->otherend_id,
- buffer_gfn, 0);
+ grant_foreign_access(gnt_list_entry, info);
+
return gnt_list_entry;
}
@@ -394,20 +456,128 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
return 0;
}
-/*
- * Generate a Xen blkfront IO request from a blk layer request. Reads
- * and writes are handled as expected.
- *
- * @req: a request struct
- */
-static int blkif_queue_request(struct request *req)
+static int blkif_queue_discard_req(struct request *req)
{
struct blkfront_info *info = req->rq_disk->private_data;
struct blkif_request *ring_req;
unsigned long id;
+
+ /* Fill out a communications ring structure. */
+ ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
+ id = get_id_from_freelist(info);
+ info->shadow[id].request = req;
+
+ ring_req->operation = BLKIF_OP_DISCARD;
+ ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+ ring_req->u.discard.id = id;
+ ring_req->u.discard.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard)
+ ring_req->u.discard.flag = BLKIF_DISCARD_SECURE;
+ else
+ ring_req->u.discard.flag = 0;
+
+ info->ring.req_prod_pvt++;
+
+ /* Keep a private copy so we can reissue requests when recovering. */
+ info->shadow[id].req = *ring_req;
+
+ return 0;
+}
+
+struct setup_rw_req {
+ unsigned int grant_idx;
+ struct blkif_request_segment *segments;
+ struct blkfront_info *info;
+ struct blkif_request *ring_req;
+ grant_ref_t gref_head;
+ unsigned int id;
+ /* Only used when persistent grant is used and it's a read request */
+ bool need_copy;
+ unsigned int bvec_off;
+ char *bvec_data;
+};
+
+static void blkif_setup_rw_req_grant(unsigned long gfn, unsigned int offset,
+ unsigned int len, void *data)
+{
+ struct setup_rw_req *setup = data;
+ int n, ref;
+ struct grant *gnt_list_entry;
unsigned int fsect, lsect;
- int i, ref, n;
- struct blkif_request_segment *segments = NULL;
+ /* Convenient aliases */
+ unsigned int grant_idx = setup->grant_idx;
+ struct blkif_request *ring_req = setup->ring_req;
+ struct blkfront_info *info = setup->info;
+ struct blk_shadow *shadow = &info->shadow[setup->id];
+
+ if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
+ (grant_idx % GRANTS_PER_INDIRECT_FRAME == 0)) {
+ if (setup->segments)
+ kunmap_atomic(setup->segments);
+
+ n = grant_idx / GRANTS_PER_INDIRECT_FRAME;
+ gnt_list_entry = get_indirect_grant(&setup->gref_head, info);
+ shadow->indirect_grants[n] = gnt_list_entry;
+ setup->segments = kmap_atomic(gnt_list_entry->page);
+ ring_req->u.indirect.indirect_grefs[n] = gnt_list_entry->gref;
+ }
+
+ gnt_list_entry = get_grant(&setup->gref_head, gfn, info);
+ ref = gnt_list_entry->gref;
+ shadow->grants_used[grant_idx] = gnt_list_entry;
+
+ if (setup->need_copy) {
+ void *shared_data;
+
+ shared_data = kmap_atomic(gnt_list_entry->page);
+ /*
+ * this does not wipe data stored outside the
+ * range sg->offset..sg->offset+sg->length.
+ * Therefore, blkback *could* see data from
+ * previous requests. This is OK as long as
+ * persistent grants are shared with just one
+ * domain. It may need refactoring if this
+ * changes
+ */
+ memcpy(shared_data + offset,
+ setup->bvec_data + setup->bvec_off,
+ len);
+
+ kunmap_atomic(shared_data);
+ setup->bvec_off += len;
+ }
+
+ fsect = offset >> 9;
+ lsect = fsect + (len >> 9) - 1;
+ if (ring_req->operation != BLKIF_OP_INDIRECT) {
+ ring_req->u.rw.seg[grant_idx] =
+ (struct blkif_request_segment) {
+ .gref = ref,
+ .first_sect = fsect,
+ .last_sect = lsect };
+ } else {
+ setup->segments[grant_idx % GRANTS_PER_INDIRECT_FRAME] =
+ (struct blkif_request_segment) {
+ .gref = ref,
+ .first_sect = fsect,
+ .last_sect = lsect };
+ }
+
+ (setup->grant_idx)++;
+}
+
+static int blkif_queue_rw_req(struct request *req)
+{
+ struct blkfront_info *info = req->rq_disk->private_data;
+ struct blkif_request *ring_req;
+ unsigned long id;
+ int i;
+ struct setup_rw_req setup = {
+ .grant_idx = 0,
+ .segments = NULL,
+ .info = info,
+ .need_copy = rq_data_dir(req) && info->feature_persistent,
+ };
/*
* Used to store if we are able to queue the request by just using
@@ -415,28 +585,23 @@ static int blkif_queue_request(struct request *req)
* as there are not sufficiently many free.
*/
bool new_persistent_gnts;
- grant_ref_t gref_head;
- struct grant *gnt_list_entry = NULL;
struct scatterlist *sg;
- int nseg, max_grefs;
+ int num_sg, max_grefs, num_grant;
- if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
- return 1;
-
- max_grefs = req->nr_phys_segments;
+ max_grefs = req->nr_phys_segments * GRANTS_PER_PSEG;
if (max_grefs > BLKIF_MAX_SEGMENTS_PER_REQUEST)
/*
* If we are using indirect segments we need to account
* for the indirect grefs used in the request.
*/
- max_grefs += INDIRECT_GREFS(req->nr_phys_segments);
+ max_grefs += INDIRECT_GREFS(max_grefs);
/* Check if we have enough grants to allocate a requests */
if (info->persistent_gnts_c < max_grefs) {
new_persistent_gnts = 1;
if (gnttab_alloc_grant_references(
max_grefs - info->persistent_gnts_c,
- &gref_head) < 0) {
+ &setup.gref_head) < 0) {
gnttab_request_free_callback(
&info->callback,
blkif_restart_queue_callback,
@@ -452,139 +617,82 @@ static int blkif_queue_request(struct request *req)
id = get_id_from_freelist(info);
info->shadow[id].request = req;
- if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) {
- ring_req->operation = BLKIF_OP_DISCARD;
- ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
- ring_req->u.discard.id = id;
- ring_req->u.discard.sector_number = (blkif_sector_t)blk_rq_pos(req);
- if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard)
- ring_req->u.discard.flag = BLKIF_DISCARD_SECURE;
- else
- ring_req->u.discard.flag = 0;
+ BUG_ON(info->max_indirect_segments == 0 &&
+ GREFS(req->nr_phys_segments) > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ BUG_ON(info->max_indirect_segments &&
+ GREFS(req->nr_phys_segments) > info->max_indirect_segments);
+
+ num_sg = blk_rq_map_sg(req->q, req, info->shadow[id].sg);
+ num_grant = 0;
+ /* Calculate the number of grant used */
+ for_each_sg(info->shadow[id].sg, sg, num_sg, i)
+ num_grant += gnttab_count_grant(sg->offset, sg->length);
+
+ ring_req->u.rw.id = id;
+ info->shadow[id].num_sg = num_sg;
+ if (num_grant > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+ /*
+ * The indirect operation can only be a BLKIF_OP_READ or
+ * BLKIF_OP_WRITE
+ */
+ BUG_ON(req->cmd_flags & (REQ_FLUSH | REQ_FUA));
+ ring_req->operation = BLKIF_OP_INDIRECT;
+ ring_req->u.indirect.indirect_op = rq_data_dir(req) ?
+ BLKIF_OP_WRITE : BLKIF_OP_READ;
+ ring_req->u.indirect.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ ring_req->u.indirect.handle = info->handle;
+ ring_req->u.indirect.nr_segments = num_grant;
} else {
- BUG_ON(info->max_indirect_segments == 0 &&
- req->nr_phys_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
- BUG_ON(info->max_indirect_segments &&
- req->nr_phys_segments > info->max_indirect_segments);
- nseg = blk_rq_map_sg(req->q, req, info->shadow[id].sg);
- ring_req->u.rw.id = id;
- if (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+ ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ ring_req->u.rw.handle = info->handle;
+ ring_req->operation = rq_data_dir(req) ?
+ BLKIF_OP_WRITE : BLKIF_OP_READ;
+ if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) {
/*
- * The indirect operation can only be a BLKIF_OP_READ or
- * BLKIF_OP_WRITE
+ * Ideally we can do an unordered flush-to-disk.
+ * In case the backend onlysupports barriers, use that.
+ * A barrier request a superset of FUA, so we can
+ * implement it the same way. (It's also a FLUSH+FUA,
+ * since it is guaranteed ordered WRT previous writes.)
*/
- BUG_ON(req->cmd_flags & (REQ_FLUSH | REQ_FUA));
- ring_req->operation = BLKIF_OP_INDIRECT;
- ring_req->u.indirect.indirect_op = rq_data_dir(req) ?
- BLKIF_OP_WRITE : BLKIF_OP_READ;
- ring_req->u.indirect.sector_number = (blkif_sector_t)blk_rq_pos(req);
- ring_req->u.indirect.handle = info->handle;
- ring_req->u.indirect.nr_segments = nseg;
- } else {
- ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
- ring_req->u.rw.handle = info->handle;
- ring_req->operation = rq_data_dir(req) ?
- BLKIF_OP_WRITE : BLKIF_OP_READ;
- if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) {
- /*
- * Ideally we can do an unordered flush-to-disk. In case the
- * backend onlysupports barriers, use that. A barrier request
- * a superset of FUA, so we can implement it the same
- * way. (It's also a FLUSH+FUA, since it is
- * guaranteed ordered WRT previous writes.)
- */
- switch (info->feature_flush &
- ((REQ_FLUSH|REQ_FUA))) {
- case REQ_FLUSH|REQ_FUA:
- ring_req->operation =
- BLKIF_OP_WRITE_BARRIER;
- break;
- case REQ_FLUSH:
- ring_req->operation =
- BLKIF_OP_FLUSH_DISKCACHE;
- break;
- default:
- ring_req->operation = 0;
- }
+ switch (info->feature_flush &
+ ((REQ_FLUSH|REQ_FUA))) {
+ case REQ_FLUSH|REQ_FUA:
+ ring_req->operation =
+ BLKIF_OP_WRITE_BARRIER;
+ break;
+ case REQ_FLUSH:
+ ring_req->operation =
+ BLKIF_OP_FLUSH_DISKCACHE;
+ break;
+ default:
+ ring_req->operation = 0;
}
- ring_req->u.rw.nr_segments = nseg;
}
- for_each_sg(info->shadow[id].sg, sg, nseg, i) {
- fsect = sg->offset >> 9;
- lsect = fsect + (sg->length >> 9) - 1;
-
- if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
- (i % SEGS_PER_INDIRECT_FRAME == 0)) {
- unsigned long uninitialized_var(pfn);
-
- if (segments)
- kunmap_atomic(segments);
-
- n = i / SEGS_PER_INDIRECT_FRAME;
- if (!info->feature_persistent) {
- struct page *indirect_page;
-
- /* Fetch a pre-allocated page to use for indirect grefs */
- BUG_ON(list_empty(&info->indirect_pages));
- indirect_page = list_first_entry(&info->indirect_pages,
- struct page, lru);
- list_del(&indirect_page->lru);
- pfn = page_to_pfn(indirect_page);
- }
- gnt_list_entry = get_grant(&gref_head, pfn, info);
- info->shadow[id].indirect_grants[n] = gnt_list_entry;
- segments = kmap_atomic(pfn_to_page(gnt_list_entry->pfn));
- ring_req->u.indirect.indirect_grefs[n] = gnt_list_entry->gref;
- }
-
- gnt_list_entry = get_grant(&gref_head, page_to_pfn(sg_page(sg)), info);
- ref = gnt_list_entry->gref;
-
- info->shadow[id].grants_used[i] = gnt_list_entry;
-
- if (rq_data_dir(req) && info->feature_persistent) {
- char *bvec_data;
- void *shared_data;
+ ring_req->u.rw.nr_segments = num_grant;
+ }
- BUG_ON(sg->offset + sg->length > PAGE_SIZE);
+ setup.ring_req = ring_req;
+ setup.id = id;
+ for_each_sg(info->shadow[id].sg, sg, num_sg, i) {
+ BUG_ON(sg->offset + sg->length > PAGE_SIZE);
- shared_data = kmap_atomic(pfn_to_page(gnt_list_entry->pfn));
- bvec_data = kmap_atomic(sg_page(sg));
+ if (setup.need_copy) {
+ setup.bvec_off = sg->offset;
+ setup.bvec_data = kmap_atomic(sg_page(sg));
+ }
- /*
- * this does not wipe data stored outside the
- * range sg->offset..sg->offset+sg->length.
- * Therefore, blkback *could* see data from
- * previous requests. This is OK as long as
- * persistent grants are shared with just one
- * domain. It may need refactoring if this
- * changes
- */
- memcpy(shared_data + sg->offset,
- bvec_data + sg->offset,
- sg->length);
+ gnttab_foreach_grant_in_range(sg_page(sg),
+ sg->offset,
+ sg->length,
+ blkif_setup_rw_req_grant,
+ &setup);
- kunmap_atomic(bvec_data);
- kunmap_atomic(shared_data);
- }
- if (ring_req->operation != BLKIF_OP_INDIRECT) {
- ring_req->u.rw.seg[i] =
- (struct blkif_request_segment) {
- .gref = ref,
- .first_sect = fsect,
- .last_sect = lsect };
- } else {
- n = i % SEGS_PER_INDIRECT_FRAME;
- segments[n] =
- (struct blkif_request_segment) {
- .gref = ref,
- .first_sect = fsect,
- .last_sect = lsect };
- }
- }
- if (segments)
- kunmap_atomic(segments);
+ if (setup.need_copy)
+ kunmap_atomic(setup.bvec_data);
}
+ if (setup.segments)
+ kunmap_atomic(setup.segments);
info->ring.req_prod_pvt++;
@@ -592,11 +700,29 @@ static int blkif_queue_request(struct request *req)
info->shadow[id].req = *ring_req;
if (new_persistent_gnts)
- gnttab_free_grant_references(gref_head);
+ gnttab_free_grant_references(setup.gref_head);
return 0;
}
+/*
+ * Generate a Xen blkfront IO request from a blk layer request. Reads
+ * and writes are handled as expected.
+ *
+ * @req: a request struct
+ */
+static int blkif_queue_request(struct request *req)
+{
+ struct blkfront_info *info = req->rq_disk->private_data;
+
+ if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
+ return 1;
+
+ if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE)))
+ return blkif_queue_discard_req(req);
+ else
+ return blkif_queue_rw_req(req);
+}
static inline void flush_requests(struct blkfront_info *info)
{
@@ -691,14 +817,14 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
/* Hard sector size and max sectors impersonate the equiv. hardware. */
blk_queue_logical_block_size(rq, sector_size);
blk_queue_physical_block_size(rq, physical_sector_size);
- blk_queue_max_hw_sectors(rq, (segments * PAGE_SIZE) / 512);
+ blk_queue_max_hw_sectors(rq, (segments * XEN_PAGE_SIZE) / 512);
/* Each segment in a request is up to an aligned page in size. */
blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
blk_queue_max_segment_size(rq, PAGE_SIZE);
/* Ensure a merged request will fit in a single I/O ring slot. */
- blk_queue_max_segments(rq, segments);
+ blk_queue_max_segments(rq, segments / GRANTS_PER_PSEG);
/* Make sure buffer addresses are sector-aligned. */
blk_queue_dma_alignment(rq, 511);
@@ -972,7 +1098,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
info->persistent_gnts_c--;
}
if (info->feature_persistent)
- __free_page(pfn_to_page(persistent_gnt->pfn));
+ __free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
}
@@ -1007,7 +1133,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
persistent_gnt = info->shadow[i].grants_used[j];
gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
if (info->feature_persistent)
- __free_page(pfn_to_page(persistent_gnt->pfn));
+ __free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
@@ -1021,7 +1147,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
for (j = 0; j < INDIRECT_GREFS(segs); j++) {
persistent_gnt = info->shadow[i].indirect_grants[j];
gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
- __free_page(pfn_to_page(persistent_gnt->pfn));
+ __free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
@@ -1057,33 +1183,65 @@ free_shadow:
}
+struct copy_from_grant {
+ const struct blk_shadow *s;
+ unsigned int grant_idx;
+ unsigned int bvec_offset;
+ char *bvec_data;
+};
+
+static void blkif_copy_from_grant(unsigned long gfn, unsigned int offset,
+ unsigned int len, void *data)
+{
+ struct copy_from_grant *info = data;
+ char *shared_data;
+ /* Convenient aliases */
+ const struct blk_shadow *s = info->s;
+
+ shared_data = kmap_atomic(s->grants_used[info->grant_idx]->page);
+
+ memcpy(info->bvec_data + info->bvec_offset,
+ shared_data + offset, len);
+
+ info->bvec_offset += len;
+ info->grant_idx++;
+
+ kunmap_atomic(shared_data);
+}
+
static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
struct blkif_response *bret)
{
int i = 0;
struct scatterlist *sg;
- char *bvec_data;
- void *shared_data;
- int nseg;
+ int num_sg, num_grant;
+ struct copy_from_grant data = {
+ .s = s,
+ .grant_idx = 0,
+ };
- nseg = s->req.operation == BLKIF_OP_INDIRECT ?
+ num_grant = s->req.operation == BLKIF_OP_INDIRECT ?
s->req.u.indirect.nr_segments : s->req.u.rw.nr_segments;
+ num_sg = s->num_sg;
if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
- for_each_sg(s->sg, sg, nseg, i) {
+ for_each_sg(s->sg, sg, num_sg, i) {
BUG_ON(sg->offset + sg->length > PAGE_SIZE);
- shared_data = kmap_atomic(
- pfn_to_page(s->grants_used[i]->pfn));
- bvec_data = kmap_atomic(sg_page(sg));
- memcpy(bvec_data + sg->offset,
- shared_data + sg->offset,
- sg->length);
- kunmap_atomic(bvec_data);
- kunmap_atomic(shared_data);
+
+ data.bvec_offset = sg->offset;
+ data.bvec_data = kmap_atomic(sg_page(sg));
+
+ gnttab_foreach_grant_in_range(sg_page(sg),
+ sg->offset,
+ sg->length,
+ blkif_copy_from_grant,
+ &data);
+
+ kunmap_atomic(data.bvec_data);
}
}
/* Add the persistent grant into the list of free grants */
- for (i = 0; i < nseg; i++) {
+ for (i = 0; i < num_grant; i++) {
if (gnttab_query_foreign_access(s->grants_used[i]->gref)) {
/*
* If the grant is still mapped by the backend (the
@@ -1109,7 +1267,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
}
}
if (s->req.operation == BLKIF_OP_INDIRECT) {
- for (i = 0; i < INDIRECT_GREFS(nseg); i++) {
+ for (i = 0; i < INDIRECT_GREFS(num_grant); i++) {
if (gnttab_query_foreign_access(s->indirect_grants[i]->gref)) {
if (!info->feature_persistent)
pr_alert_ratelimited("backed has not unmapped grant: %u\n",
@@ -1125,7 +1283,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
* available pages for indirect grefs.
*/
if (!info->feature_persistent) {
- indirect_page = pfn_to_page(s->indirect_grants[i]->pfn);
+ indirect_page = s->indirect_grants[i]->page;
list_add(&indirect_page->lru, &info->indirect_pages);
}
s->indirect_grants[i]->gref = GRANT_INVALID_REF;
@@ -1254,8 +1412,8 @@ static int setup_blkring(struct xenbus_device *dev,
{
struct blkif_sring *sring;
int err, i;
- unsigned long ring_size = info->nr_ring_pages * PAGE_SIZE;
- grant_ref_t gref[XENBUS_MAX_RING_PAGES];
+ unsigned long ring_size = info->nr_ring_pages * XEN_PAGE_SIZE;
+ grant_ref_t gref[XENBUS_MAX_RING_GRANTS];
for (i = 0; i < info->nr_ring_pages; i++)
info->ring_ref[i] = GRANT_INVALID_REF;
@@ -1583,8 +1741,8 @@ static int blkif_recover(struct blkfront_info *info)
atomic_set(&split_bio->pending, pending);
split_bio->bio = bio;
for (i = 0; i < pending; i++) {
- offset = (i * segs * PAGE_SIZE) >> 9;
- size = min((unsigned int)(segs * PAGE_SIZE) >> 9,
+ offset = (i * segs * XEN_PAGE_SIZE) >> 9;
+ size = min((unsigned int)(segs * XEN_PAGE_SIZE) >> 9,
(unsigned int)bio_sectors(bio) - offset);
cloned_bio = bio_clone(bio, GFP_NOIO);
BUG_ON(cloned_bio == NULL);
@@ -1695,15 +1853,17 @@ static void blkfront_setup_discard(struct blkfront_info *info)
static int blkfront_setup_indirect(struct blkfront_info *info)
{
- unsigned int segs;
+ unsigned int psegs, grants;
int err, i;
if (info->max_indirect_segments == 0)
- segs = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+ grants = BLKIF_MAX_SEGMENTS_PER_REQUEST;
else
- segs = info->max_indirect_segments;
+ grants = info->max_indirect_segments;
+ psegs = grants / GRANTS_PER_PSEG;
- err = fill_grant_buffer(info, (segs + INDIRECT_GREFS(segs)) * BLK_RING_SIZE(info));
+ err = fill_grant_buffer(info,
+ (grants + INDIRECT_GREFS(grants)) * BLK_RING_SIZE(info));
if (err)
goto out_of_memory;
@@ -1713,7 +1873,7 @@ static int blkfront_setup_indirect(struct blkfront_info *info)
* grants, we need to allocate a set of pages that can be
* used for mapping indirect grefs
*/
- int num = INDIRECT_GREFS(segs) * BLK_RING_SIZE(info);
+ int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info);
BUG_ON(!list_empty(&info->indirect_pages));
for (i = 0; i < num; i++) {
@@ -1726,20 +1886,20 @@ static int blkfront_setup_indirect(struct blkfront_info *info)
for (i = 0; i < BLK_RING_SIZE(info); i++) {
info->shadow[i].grants_used = kzalloc(
- sizeof(info->shadow[i].grants_used[0]) * segs,
+ sizeof(info->shadow[i].grants_used[0]) * grants,
GFP_NOIO);
- info->shadow[i].sg = kzalloc(sizeof(info->shadow[i].sg[0]) * segs, GFP_NOIO);
+ info->shadow[i].sg = kzalloc(sizeof(info->shadow[i].sg[0]) * psegs, GFP_NOIO);
if (info->max_indirect_segments)
info->shadow[i].indirect_grants = kzalloc(
sizeof(info->shadow[i].indirect_grants[0]) *
- INDIRECT_GREFS(segs),
+ INDIRECT_GREFS(grants),
GFP_NOIO);
if ((info->shadow[i].grants_used == NULL) ||
(info->shadow[i].sg == NULL) ||
(info->max_indirect_segments &&
(info->shadow[i].indirect_grants == NULL)))
goto out_of_memory;
- sg_init_table(info->shadow[i].sg, segs);
+ sg_init_table(info->shadow[i].sg, psegs);
}
@@ -1956,7 +2116,8 @@ static void blkback_changed(struct xenbus_device *dev,
break;
/* Missed the backend's Closing state -- fallthrough */
case XenbusStateClosing:
- blkfront_closing(info);
+ if (info)
+ blkfront_closing(info);
break;
}
}
@@ -2124,9 +2285,9 @@ static int __init xlblk_init(void)
if (!xen_domain())
return -ENODEV;
- if (xen_blkif_max_ring_order > XENBUS_MAX_RING_PAGE_ORDER) {
+ if (xen_blkif_max_ring_order > XENBUS_MAX_RING_GRANT_ORDER) {
pr_info("Invalid max_ring_order (%d), will use default max: %d.\n",
- xen_blkif_max_ring_order, XENBUS_MAX_RING_PAGE_ORDER);
+ xen_blkif_max_ring_order, XENBUS_MAX_RING_GRANT_ORDER);
xen_blkif_max_ring_order = 0;
}
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 9fa15bb9d118..47915d736f8d 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -106,7 +106,7 @@ static void zram_set_obj_size(struct zram_meta *meta,
meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
}
-static inline int is_partial_io(struct bio_vec *bvec)
+static inline bool is_partial_io(struct bio_vec *bvec)
{
return bvec->bv_len != PAGE_SIZE;
}
@@ -114,25 +114,25 @@ static inline int is_partial_io(struct bio_vec *bvec)
/*
* Check if request is within bounds and aligned on zram logical blocks.
*/
-static inline int valid_io_request(struct zram *zram,
+static inline bool valid_io_request(struct zram *zram,
sector_t start, unsigned int size)
{
u64 end, bound;
/* unaligned request */
if (unlikely(start & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
- return 0;
+ return false;
if (unlikely(size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
- return 0;
+ return false;
end = start + (size >> SECTOR_SHIFT);
bound = zram->disksize >> SECTOR_SHIFT;
/* out of range range */
if (unlikely(start >= bound || end > bound || start > end))
- return 0;
+ return false;
/* I/O request is valid */
- return 1;
+ return true;
}
static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
@@ -157,7 +157,7 @@ static inline void update_used_max(struct zram *zram,
} while (old_max != cur_max);
}
-static int page_zero_filled(void *ptr)
+static bool page_zero_filled(void *ptr)
{
unsigned int pos;
unsigned long *page;
@@ -166,10 +166,10 @@ static int page_zero_filled(void *ptr)
for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
if (page[pos])
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void handle_zero_page(struct bio_vec *bvec)
@@ -365,6 +365,9 @@ static ssize_t comp_algorithm_store(struct device *dev,
struct zram *zram = dev_to_zram(dev);
size_t sz;
+ if (!zcomp_available_algorithm(buf))
+ return -EINVAL;
+
down_write(&zram->init_lock);
if (init_done(zram)) {
up_write(&zram->init_lock);
@@ -378,9 +381,6 @@ static ssize_t comp_algorithm_store(struct device *dev,
if (sz > 0 && zram->compressor[sz - 1] == '\n')
zram->compressor[sz - 1] = 0x00;
- if (!zcomp_available_algorithm(zram->compressor))
- len = -EINVAL;
-
up_write(&zram->init_lock);
return len;
}
@@ -726,14 +726,14 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
}
alloced_pages = zs_get_total_pages(meta->mem_pool);
+ update_used_max(zram, alloced_pages);
+
if (zram->limit_pages && alloced_pages > zram->limit_pages) {
zs_free(meta->mem_pool, handle);
ret = -ENOMEM;
goto out;
}
- update_used_max(zram, alloced_pages);
-
cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO);
if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
@@ -894,7 +894,7 @@ out:
/*
* Handler function for all zram I/O requests.
*/
-static void zram_make_request(struct request_queue *queue, struct bio *bio)
+static blk_qc_t zram_make_request(struct request_queue *queue, struct bio *bio)
{
struct zram *zram = queue->queuedata;
@@ -911,11 +911,12 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio)
__zram_make_request(zram, bio);
zram_meta_put(zram);
- return;
+ return BLK_QC_T_NONE;
put_zram:
zram_meta_put(zram);
error:
bio_io_error(bio);
+ return BLK_QC_T_NONE;
}
static void zram_slot_free_notify(struct block_device *bdev,
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 0bd88c942a52..ec6af1595062 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -4,6 +4,7 @@ menu "Bluetooth device drivers"
config BT_INTEL
tristate
+ select REGMAP
config BT_BCM
tristate
@@ -182,7 +183,8 @@ config BT_HCIBCM203X
config BT_HCIBPA10X
tristate "HCI BPA10x USB driver"
- depends on USB
+ depends on USB && BT_HCIUART
+ select BT_HCIUART_H4
help
Bluetooth HCI BPA10x USB driver.
This driver provides support for the Digianswer BPA 100/105 Bluetooth
@@ -275,7 +277,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.
+ Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8997.
Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module.
@@ -289,7 +291,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
+ devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8997
chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index e527a3e13939..fa893c3ec408 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -93,6 +93,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x04CA, 0x300f) },
{ USB_DEVICE(0x04CA, 0x3010) },
{ USB_DEVICE(0x0930, 0x0219) },
+ { USB_DEVICE(0x0930, 0x021c) },
{ USB_DEVICE(0x0930, 0x0220) },
{ USB_DEVICE(0x0930, 0x0227) },
{ USB_DEVICE(0x0b05, 0x17d0) },
@@ -104,6 +105,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0x311F) },
{ USB_DEVICE(0x0cf3, 0x3121) },
{ USB_DEVICE(0x0CF3, 0x817a) },
+ { USB_DEVICE(0x0CF3, 0x817b) },
{ USB_DEVICE(0x0cf3, 0xe003) },
{ USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0CF3, 0xE005) },
@@ -153,6 +155,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -164,6 +167,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0CF3, 0x817b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe006), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index a5c4d0584389..616ec2ac1b22 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -422,17 +422,12 @@ static int bfusb_open(struct hci_dev *hdev)
BT_DBG("hdev %p bfusb %p", hdev, data);
- if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
write_lock_irqsave(&data->lock, flags);
err = bfusb_rx_submit(data, NULL);
if (!err) {
for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
bfusb_rx_submit(data, NULL);
- } else {
- clear_bit(HCI_RUNNING, &hdev->flags);
}
write_unlock_irqrestore(&data->lock, flags);
@@ -458,9 +453,6 @@ static int bfusb_close(struct hci_dev *hdev)
BT_DBG("hdev %p bfusb %p", hdev, data);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
write_lock_irqsave(&data->lock, flags);
write_unlock_irqrestore(&data->lock, flags);
@@ -479,9 +471,6 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 35e63aaa6f80..36fa1c958c74 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -390,7 +390,7 @@ static void bluecard_receive(struct bluecard_info *info,
for (i = 0; i < len; i++) {
/* Allocate packet */
- if (info->rx_skb == NULL) {
+ if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
@@ -628,9 +628,6 @@ static int bluecard_hci_open(struct hci_dev *hdev)
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
- if (test_and_set_bit(HCI_RUNNING, &(hdev->flags)))
- return 0;
-
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
unsigned int iobase = info->p_dev->resource[0]->start;
@@ -646,9 +643,6 @@ static int bluecard_hci_close(struct hci_dev *hdev)
{
struct bluecard_info *info = hci_get_drvdata(hdev);
- if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
- return 0;
-
bluecard_hci_flush(hdev);
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 8a319913c9a9..49c397e21b39 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -35,7 +35,9 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#define VERSION "0.10"
+#include "hci_uart.h"
+
+#define VERSION "0.11"
static const struct usb_device_id bpa10x_table[] = {
/* Tektronix BPA 100/105 (Digianswer) */
@@ -56,112 +58,6 @@ struct bpa10x_data {
struct sk_buff *rx_skb[2];
};
-#define HCI_VENDOR_HDR_SIZE 5
-
-struct hci_vendor_hdr {
- __u8 type;
- __le16 snum;
- __le16 dlen;
-} __packed;
-
-static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
-{
- struct bpa10x_data *data = hci_get_drvdata(hdev);
-
- BT_DBG("%s queue %d buffer %p count %d", hdev->name,
- queue, buf, count);
-
- if (queue < 0 || queue > 1)
- return -EILSEQ;
-
- hdev->stat.byte_rx += count;
-
- while (count) {
- struct sk_buff *skb = data->rx_skb[queue];
- struct { __u8 type; int expect; } *scb;
- int type, len = 0;
-
- if (!skb) {
- /* Start of the frame */
-
- type = *((__u8 *) buf);
- count--; buf++;
-
- switch (type) {
- case HCI_EVENT_PKT:
- if (count >= HCI_EVENT_HDR_SIZE) {
- struct hci_event_hdr *h = buf;
- len = HCI_EVENT_HDR_SIZE + h->plen;
- } else
- return -EILSEQ;
- break;
-
- case HCI_ACLDATA_PKT:
- if (count >= HCI_ACL_HDR_SIZE) {
- struct hci_acl_hdr *h = buf;
- len = HCI_ACL_HDR_SIZE +
- __le16_to_cpu(h->dlen);
- } else
- return -EILSEQ;
- break;
-
- case HCI_SCODATA_PKT:
- if (count >= HCI_SCO_HDR_SIZE) {
- struct hci_sco_hdr *h = buf;
- len = HCI_SCO_HDR_SIZE + h->dlen;
- } else
- return -EILSEQ;
- break;
-
- case HCI_VENDOR_PKT:
- if (count >= HCI_VENDOR_HDR_SIZE) {
- struct hci_vendor_hdr *h = buf;
- len = HCI_VENDOR_HDR_SIZE +
- __le16_to_cpu(h->dlen);
- } else
- return -EILSEQ;
- break;
- }
-
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("%s no memory for packet", hdev->name);
- return -ENOMEM;
- }
-
- data->rx_skb[queue] = skb;
-
- scb = (void *) skb->cb;
- scb->type = type;
- scb->expect = len;
- } else {
- /* Continuation */
-
- scb = (void *) skb->cb;
- len = scb->expect;
- }
-
- len = min(len, count);
-
- memcpy(skb_put(skb, len), buf, len);
-
- scb->expect -= len;
-
- if (scb->expect == 0) {
- /* Complete frame */
-
- data->rx_skb[queue] = NULL;
-
- bt_cb(skb)->pkt_type = scb->type;
- hci_recv_frame(hdev, skb);
- }
-
- count -= len; buf += len;
- }
-
- return 0;
-}
-
static void bpa10x_tx_complete(struct urb *urb)
{
struct sk_buff *skb = urb->context;
@@ -184,6 +80,22 @@ done:
kfree_skb(skb);
}
+#define HCI_VENDOR_HDR_SIZE 5
+
+#define HCI_RECV_VENDOR \
+ .type = HCI_VENDOR_PKT, \
+ .hlen = HCI_VENDOR_HDR_SIZE, \
+ .loff = 3, \
+ .lsize = 2, \
+ .maxlen = HCI_MAX_FRAME_SIZE
+
+static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
+ { H4_RECV_ACL, .recv = hci_recv_frame },
+ { H4_RECV_SCO, .recv = hci_recv_frame },
+ { H4_RECV_EVENT, .recv = hci_recv_frame },
+ { HCI_RECV_VENDOR, .recv = hci_recv_diag },
+};
+
static void bpa10x_rx_complete(struct urb *urb)
{
struct hci_dev *hdev = urb->context;
@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb)
return;
if (urb->status == 0) {
- if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe),
+ bool idx = usb_pipebulk(urb->pipe);
+
+ data->rx_skb[idx] = h4_recv_buf(hdev, data->rx_skb[idx],
urb->transfer_buffer,
- urb->actual_length) < 0) {
+ urb->actual_length,
+ bpa10x_recv_pkts,
+ ARRAY_SIZE(bpa10x_recv_pkts));
+ if (IS_ERR(data->rx_skb[idx])) {
BT_ERR("%s corrupted event packet", hdev->name);
hdev->stat.err_rx++;
+ data->rx_skb[idx] = NULL;
}
}
@@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
err = bpa10x_submit_intr_urb(hdev);
if (err < 0)
goto error;
@@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev)
error:
usb_kill_anchored_urbs(&data->rx_anchor);
- clear_bit(HCI_RUNNING, &hdev->flags);
-
return err;
}
@@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
usb_kill_anchored_urbs(&data->rx_anchor);
return 0;
@@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev)
return 0;
}
+static int bpa10x_setup(struct hci_dev *hdev)
+{
+ const u8 req[] = { 0x07 };
+ struct sk_buff *skb;
+
+ BT_DBG("%s", hdev->name);
+
+ /* Read revision string */
+ skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
+
+ kfree_skb(skb);
+ return 0;
+}
+
static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct bpa10x_data *data = hci_get_drvdata(hdev);
@@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
skb->dev = (void *) hdev;
urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
+static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
+{
+ const u8 req[] = { 0x00, enable };
+ struct sk_buff *skb;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return -ENETDOWN;
+
+ /* Enable sniffer operation */
+ skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ kfree_skb(skb);
+ return 0;
+}
+
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct bpa10x_data *data;
@@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
hdev->open = bpa10x_open;
hdev->close = bpa10x_close;
hdev->flush = bpa10x_flush;
+ hdev->setup = bpa10x_setup;
hdev->send = bpa10x_send_frame;
+ hdev->set_diag = bpa10x_set_diag;
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index a00bb82eb7c6..5803aaed958f 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -233,7 +233,7 @@ static void bt3c_receive(struct bt3c_info *info)
info->hdev->stat.byte_rx++;
/* Allocate packet */
- if (info->rx_skb == NULL) {
+ if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
@@ -270,7 +270,6 @@ static void bt3c_receive(struct bt3c_info *info)
/* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
- clear_bit(HCI_RUNNING, &(info->hdev->flags));
kfree_skb(info->rx_skb);
info->rx_skb = NULL;
@@ -395,17 +394,12 @@ static int bt3c_hci_flush(struct hci_dev *hdev)
static int bt3c_hci_open(struct hci_dev *hdev)
{
- set_bit(HCI_RUNNING, &(hdev->flags));
-
return 0;
}
static int bt3c_hci_close(struct hci_dev *hdev)
{
- if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
- return 0;
-
bt3c_hci_flush(hdev);
return 0;
@@ -453,7 +447,8 @@ static int bt3c_load_firmware(struct bt3c_info *info,
{
char *ptr = (char *) firmware;
char b[9];
- unsigned int iobase, size, addr, fcs, tmp;
+ unsigned int iobase, tmp;
+ unsigned long size, addr, fcs;
int i, err = 0;
iobase = info->p_dev->resource[0]->start;
@@ -478,15 +473,18 @@ static int bt3c_load_firmware(struct bt3c_info *info,
memset(b, 0, sizeof(b));
memcpy(b, ptr + 2, 2);
- size = simple_strtoul(b, NULL, 16);
+ if (kstrtoul(b, 16, &size) < 0)
+ return -EINVAL;
memset(b, 0, sizeof(b));
memcpy(b, ptr + 4, 8);
- addr = simple_strtoul(b, NULL, 16);
+ if (kstrtoul(b, 16, &addr) < 0)
+ return -EINVAL;
memset(b, 0, sizeof(b));
memcpy(b, ptr + (size * 2) + 2, 2);
- fcs = simple_strtoul(b, NULL, 16);
+ if (kstrtoul(b, 16, &fcs) < 0)
+ return -EINVAL;
memset(b, 0, sizeof(b));
for (tmp = 0, i = 0; i < size; i++) {
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c
index 02ed816a18f9..0b697946e9bc 100644
--- a/drivers/bluetooth/btbcm.c
+++ b/drivers/bluetooth/btbcm.c
@@ -181,6 +181,27 @@ static int btbcm_reset(struct hci_dev *hdev)
return 0;
}
+static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s: BCM: Reading local name failed (%ld)",
+ hdev->name, PTR_ERR(skb));
+ return skb;
+ }
+
+ if (skb->len != sizeof(struct hci_rp_read_local_name)) {
+ BT_ERR("%s: BCM: Local name length mismatch", hdev->name);
+ kfree_skb(skb);
+ return ERR_PTR(-EIO);
+ }
+
+ return skb;
+}
+
static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev)
{
struct sk_buff *skb;
@@ -302,7 +323,7 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
}
BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
- hw_name ? : "BCM", (subver & 0x7000) >> 13,
+ hw_name ? : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
return 0;
@@ -332,7 +353,7 @@ int btbcm_finalize(struct hci_dev *hdev)
kfree_skb(skb);
BT_INFO("%s: BCM (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
- (subver & 0x7000) >> 13, (subver & 0x1f00) >> 8,
+ (subver & 0xe000) >> 13, (subver & 0x1f00) >> 8,
(subver & 0x00ff), rev & 0x0fff);
btbcm_check_bdaddr(hdev);
@@ -393,6 +414,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
kfree_skb(skb);
+ /* Read Local Name */
+ skb = btbcm_read_local_name(hdev);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
+ kfree_skb(skb);
+
switch ((rev & 0xf000) >> 12) {
case 0:
case 3:
@@ -432,7 +461,7 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
}
BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
- hw_name ? : "BCM", (subver & 0x7000) >> 13,
+ hw_name ? : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
err = request_firmware(&fw, fw_name, &hdev->dev);
@@ -461,9 +490,17 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
kfree_skb(skb);
BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
- hw_name ? : "BCM", (subver & 0x7000) >> 13,
+ hw_name ? : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
+ /* Read Local Name */
+ skb = btbcm_read_local_name(hdev);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
+ kfree_skb(skb);
+
btbcm_check_bdaddr(hdev);
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
@@ -475,12 +512,34 @@ EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
int btbcm_setup_apple(struct hci_dev *hdev)
{
struct sk_buff *skb;
+ int err;
+
+ /* Reset */
+ err = btbcm_reset(hdev);
+ if (err)
+ return err;
/* Read Verbose Config Version Info */
skb = btbcm_read_verbose_config(hdev);
if (!IS_ERR(skb)) {
- BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1],
- get_unaligned_le16(skb->data + 5));
+ BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name,
+ skb->data[1], get_unaligned_le16(skb->data + 5));
+ kfree_skb(skb);
+ }
+
+ /* Read USB Product Info */
+ skb = btbcm_read_usb_product(hdev);
+ if (!IS_ERR(skb)) {
+ BT_INFO("%s: BCM: product %4.4x:%4.4x", hdev->name,
+ get_unaligned_le16(skb->data + 1),
+ get_unaligned_le16(skb->data + 3));
+ kfree_skb(skb);
+ }
+
+ /* Read Local Name */
+ skb = btbcm_read_local_name(hdev);
+ if (!IS_ERR(skb)) {
+ BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
kfree_skb(skb);
}
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 048423fd83bf..1f13e617bf56 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -22,6 +22,8 @@
*/
#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/regmap.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -89,6 +91,75 @@ int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(btintel_set_bdaddr);
+int btintel_set_diag(struct hci_dev *hdev, bool enable)
+{
+ struct sk_buff *skb;
+ u8 param[3];
+ int err;
+
+ if (enable) {
+ param[0] = 0x03;
+ param[1] = 0x03;
+ param[2] = 0x03;
+ } else {
+ param[0] = 0x00;
+ param[1] = 0x00;
+ param[2] = 0x00;
+ }
+
+ skb = __hci_cmd_sync(hdev, 0xfc43, 3, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ if (err == -ENODATA)
+ goto done;
+ BT_ERR("%s: Changing Intel diagnostic mode failed (%d)",
+ hdev->name, err);
+ return err;
+ }
+ kfree_skb(skb);
+
+done:
+ btintel_set_event_mask(hdev, enable);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_set_diag);
+
+int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable)
+{
+ struct sk_buff *skb;
+ u8 param[2];
+ int err;
+
+ param[0] = 0x01;
+ param[1] = 0x00;
+
+ skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
+ hdev->name, err);
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ err = btintel_set_diag(hdev, enable);
+
+ param[0] = 0x00;
+ param[1] = 0x00;
+
+ skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
+ hdev->name, err);
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(btintel_set_diag_mfg);
+
void btintel_hw_error(struct hci_dev *hdev, u8 code)
{
struct sk_buff *skb;
@@ -169,6 +240,304 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
}
EXPORT_SYMBOL_GPL(btintel_secure_send);
+int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)
+{
+ const struct firmware *fw;
+ struct sk_buff *skb;
+ const u8 *fw_ptr;
+ int err;
+
+ err = request_firmware_direct(&fw, ddc_name, &hdev->dev);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to load Intel DDC file %s (%d)",
+ ddc_name, err);
+ return err;
+ }
+
+ bt_dev_info(hdev, "Found Intel DDC parameters: %s", ddc_name);
+
+ fw_ptr = fw->data;
+
+ /* DDC file contains one or more DDC structure which has
+ * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
+ */
+ while (fw->size > fw_ptr - fw->data) {
+ u8 cmd_plen = fw_ptr[0] + sizeof(u8);
+
+ skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Failed to send Intel_Write_DDC (%ld)",
+ PTR_ERR(skb));
+ release_firmware(fw);
+ return PTR_ERR(skb);
+ }
+
+ fw_ptr += cmd_plen;
+ kfree_skb(skb);
+ }
+
+ release_firmware(fw);
+
+ bt_dev_info(hdev, "Applying Intel DDC parameters completed");
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_load_ddc_config);
+
+int btintel_set_event_mask(struct hci_dev *hdev, bool debug)
+{
+ u8 mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ struct sk_buff *skb;
+ int err;
+
+ if (debug)
+ mask[1] |= 0x62;
+
+ skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Setting Intel event mask failed (%d)",
+ hdev->name, err);
+ return err;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_set_event_mask);
+
+int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
+{
+ struct sk_buff *skb;
+ u8 param[2];
+ int err;
+
+ param[0] = 0x01;
+ param[1] = 0x00;
+
+ skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
+ hdev->name, err);
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ err = btintel_set_event_mask(hdev, debug);
+
+ param[0] = 0x00;
+ param[1] = 0x00;
+
+ skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
+ hdev->name, err);
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg);
+
+/* ------- REGMAP IBT SUPPORT ------- */
+
+#define IBT_REG_MODE_8BIT 0x00
+#define IBT_REG_MODE_16BIT 0x01
+#define IBT_REG_MODE_32BIT 0x02
+
+struct regmap_ibt_context {
+ struct hci_dev *hdev;
+ __u16 op_write;
+ __u16 op_read;
+};
+
+struct ibt_cp_reg_access {
+ __le32 addr;
+ __u8 mode;
+ __u8 len;
+ __u8 data[0];
+} __packed;
+
+struct ibt_rp_reg_access {
+ __u8 status;
+ __le32 addr;
+ __u8 data[0];
+} __packed;
+
+static int regmap_ibt_read(void *context, const void *addr, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct regmap_ibt_context *ctx = context;
+ struct ibt_cp_reg_access cp;
+ struct ibt_rp_reg_access *rp;
+ struct sk_buff *skb;
+ int err = 0;
+
+ if (reg_size != sizeof(__le32))
+ return -EINVAL;
+
+ switch (val_size) {
+ case 1:
+ cp.mode = IBT_REG_MODE_8BIT;
+ break;
+ case 2:
+ cp.mode = IBT_REG_MODE_16BIT;
+ break;
+ case 4:
+ cp.mode = IBT_REG_MODE_32BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* regmap provides a little-endian formatted addr */
+ cp.addr = *(__le32 *)addr;
+ cp.len = val_size;
+
+ bt_dev_dbg(ctx->hdev, "Register (0x%x) read", le32_to_cpu(cp.addr));
+
+ skb = hci_cmd_sync(ctx->hdev, ctx->op_read, sizeof(cp), &cp,
+ HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error (%d)",
+ le32_to_cpu(cp.addr), err);
+ return err;
+ }
+
+ if (skb->len != sizeof(*rp) + val_size) {
+ bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad len",
+ le32_to_cpu(cp.addr));
+ err = -EINVAL;
+ goto done;
+ }
+
+ rp = (struct ibt_rp_reg_access *)skb->data;
+
+ if (rp->addr != cp.addr) {
+ bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad addr",
+ le32_to_cpu(rp->addr));
+ err = -EINVAL;
+ goto done;
+ }
+
+ memcpy(val, rp->data, val_size);
+
+done:
+ kfree_skb(skb);
+ return err;
+}
+
+static int regmap_ibt_gather_write(void *context,
+ const void *addr, size_t reg_size,
+ const void *val, size_t val_size)
+{
+ struct regmap_ibt_context *ctx = context;
+ struct ibt_cp_reg_access *cp;
+ struct sk_buff *skb;
+ int plen = sizeof(*cp) + val_size;
+ u8 mode;
+ int err = 0;
+
+ if (reg_size != sizeof(__le32))
+ return -EINVAL;
+
+ switch (val_size) {
+ case 1:
+ mode = IBT_REG_MODE_8BIT;
+ break;
+ case 2:
+ mode = IBT_REG_MODE_16BIT;
+ break;
+ case 4:
+ mode = IBT_REG_MODE_32BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cp = kmalloc(plen, GFP_KERNEL);
+ if (!cp)
+ return -ENOMEM;
+
+ /* regmap provides a little-endian formatted addr/value */
+ cp->addr = *(__le32 *)addr;
+ cp->mode = mode;
+ cp->len = val_size;
+ memcpy(&cp->data, val, val_size);
+
+ bt_dev_dbg(ctx->hdev, "Register (0x%x) write", le32_to_cpu(cp->addr));
+
+ skb = hci_cmd_sync(ctx->hdev, ctx->op_write, plen, cp, HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(ctx->hdev, "regmap: Register (0x%x) write error (%d)",
+ le32_to_cpu(cp->addr), err);
+ goto done;
+ }
+ kfree_skb(skb);
+
+done:
+ kfree(cp);
+ return err;
+}
+
+static int regmap_ibt_write(void *context, const void *data, size_t count)
+{
+ /* data contains register+value, since we only support 32bit addr,
+ * minimum data size is 4 bytes.
+ */
+ if (WARN_ONCE(count < 4, "Invalid register access"))
+ return -EINVAL;
+
+ return regmap_ibt_gather_write(context, data, 4, data + 4, count - 4);
+}
+
+static void regmap_ibt_free_context(void *context)
+{
+ kfree(context);
+}
+
+static struct regmap_bus regmap_ibt = {
+ .read = regmap_ibt_read,
+ .write = regmap_ibt_write,
+ .gather_write = regmap_ibt_gather_write,
+ .free_context = regmap_ibt_free_context,
+ .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
+ .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
+};
+
+/* Config is the same for all register regions */
+static const struct regmap_config regmap_ibt_cfg = {
+ .name = "btintel_regmap",
+ .reg_bits = 32,
+ .val_bits = 32,
+};
+
+struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
+ u16 opcode_write)
+{
+ struct regmap_ibt_context *ctx;
+
+ bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read,
+ opcode_write);
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ ctx->op_read = opcode_read;
+ ctx->op_write = opcode_write;
+ ctx->hdev = hdev;
+
+ return regmap_init(&hdev->dev, &regmap_ibt, ctx, &regmap_ibt_cfg);
+}
+EXPORT_SYMBOL_GPL(btintel_regmap_init);
+
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index b278d14758d5..07e58e05a7fa 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -73,11 +73,19 @@ struct intel_secure_send_result {
int btintel_check_bdaddr(struct hci_dev *hdev);
int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+int btintel_set_diag(struct hci_dev *hdev, bool enable);
+int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
void btintel_hw_error(struct hci_dev *hdev, u8 code);
void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver);
int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param);
+int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
+int btintel_set_event_mask(struct hci_dev *hdev, bool debug);
+int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug);
+
+struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
+ u16 opcode_write);
#else
@@ -91,11 +99,22 @@ static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdadd
return -EOPNOTSUPP;
}
+static inline int btintel_set_diag(struct hci_dev *hdev, bool enable)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable)
+{
+ return -EOPNOTSUPP;
+}
+
static inline void btintel_hw_error(struct hci_dev *hdev, u8 code)
{
}
-static void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
+static inline void btintel_version_info(struct hci_dev *hdev,
+ struct intel_version *ver)
{
}
@@ -105,4 +124,26 @@ static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type,
return -EOPNOTSUPP;
}
+static inline int btintel_load_ddc_config(struct hci_dev *hdev,
+ const char *ddc_name)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int btintel_set_event_mask(struct hci_dev *hdev, bool debug)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
+ u16 opcode_read,
+ u16 opcode_write)
+{
+ return ERR_PTR(-EINVAL);
+}
#endif
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index de05deb444ce..6af917331962 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -184,7 +184,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
}
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
- if (skb == NULL) {
+ if (!skb) {
BT_ERR("No free skb");
return -ENOMEM;
}
@@ -377,20 +377,6 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
return -EINVAL;
}
- if (skb_headroom(skb) < BTM_HEADER_LEN) {
- struct sk_buff *tmp = skb;
-
- skb = skb_realloc_headroom(skb, BTM_HEADER_LEN);
- if (!skb) {
- BT_ERR("Tx Error: realloc_headroom failed %d",
- BTM_HEADER_LEN);
- skb = tmp;
- return -EINVAL;
- }
-
- kfree_skb(tmp);
- }
-
skb_push(skb, BTM_HEADER_LEN);
/* header type: byte[3]
@@ -450,13 +436,6 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
- if (!test_bit(HCI_RUNNING, &hdev->flags)) {
- BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
- print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
- skb->data, skb->len);
- return -EBUSY;
- }
-
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
@@ -491,9 +470,6 @@ static int btmrvl_close(struct hci_dev *hdev)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
skb_queue_purge(&priv->adapter->tx_queue);
return 0;
@@ -501,8 +477,6 @@ static int btmrvl_close(struct hci_dev *hdev)
static int btmrvl_open(struct hci_dev *hdev)
{
- set_bit(HCI_RUNNING, &hdev->flags);
-
return 0;
}
@@ -542,14 +516,17 @@ static int btmrvl_check_device_tree(struct btmrvl_private *priv)
ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data",
cal_data + BT_CAL_HDR_LEN,
BT_CAL_DATA_SIZE);
- if (ret)
+ if (ret) {
+ of_node_put(dt_node);
return ret;
+ }
BT_DBG("Use cal data from device tree");
ret = btmrvl_download_cal_data(priv, cal_data,
BT_CAL_DATA_SIZE);
if (ret) {
BT_ERR("Fail to download calibrate data");
+ of_node_put(dt_node);
return ret;
}
}
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index b9978a7ba0cc..71ea2a3af293 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -146,6 +146,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
.fw_dump_end = 0xea,
};
+static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
+ .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_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin",
@@ -191,25 +214,37 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.supports_fw_dump = true,
};
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
+ .helper = NULL,
+ .firmware = "mrvl/sd8997_uapsta.bin",
+ .reg = &btmrvl_reg_8997,
+ .support_pscan_win_report = true,
+ .sd_blksz_fw_dl = 256,
+ .supports_fw_dump = true,
+};
+
static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8688 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
- .driver_data = (unsigned long) &btmrvl_sdio_sd8688 },
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
/* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
- .driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
/* Marvell SD8787 Bluetooth AMP device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
- .driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
/* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
- .driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
/* Marvell SD8887 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
.driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
/* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
- .driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
+ /* Marvell SD8997 Bluetooth device */
+ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
{ } /* Terminating entry */
};
@@ -619,7 +654,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
/* Allocate buffer */
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
- if (skb == NULL) {
+ if (!skb) {
BT_ERR("No free skb");
ret = -ENOMEM;
goto exit;
@@ -1278,6 +1313,12 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
if (memory_size == 0) {
BT_INFO("Firmware dump finished!");
+ sdio_writeb(card->func, FW_DUMP_READ_DONE,
+ card->reg->fw_dump_ctrl, &ret);
+ if (ret) {
+ BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
+ goto done;
+ }
break;
}
@@ -1616,3 +1657,4 @@ 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/sd8997_uapsta.bin");
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 83f6437dd91d..7b624423a7e8 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -194,21 +194,15 @@ static int btsdio_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
sdio_claim_host(data->func);
err = sdio_enable_func(data->func);
- if (err < 0) {
- clear_bit(HCI_RUNNING, &hdev->flags);
+ if (err < 0)
goto release;
- }
err = sdio_claim_irq(data->func, btsdio_interrupt);
if (err < 0) {
sdio_disable_func(data->func);
- clear_bit(HCI_RUNNING, &hdev->flags);
goto release;
}
@@ -229,9 +223,6 @@ static int btsdio_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
sdio_claim_host(data->func);
sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL);
@@ -261,9 +252,6 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index abb4d2106db4..bb8e4025fb9e 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -38,7 +38,7 @@
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/bitops.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
@@ -188,7 +188,7 @@ static void btuart_receive(struct btuart_info *info)
info->hdev->stat.byte_rx++;
/* Allocate packet */
- if (info->rx_skb == NULL) {
+ if (!info->rx_skb) {
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
@@ -223,7 +223,6 @@ static void btuart_receive(struct btuart_info *info)
/* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
- clear_bit(HCI_RUNNING, &(info->hdev->flags));
kfree_skb(info->rx_skb);
info->rx_skb = NULL;
@@ -409,17 +408,12 @@ static int btuart_hci_flush(struct hci_dev *hdev)
static int btuart_hci_open(struct hci_dev *hdev)
{
- set_bit(HCI_RUNNING, &(hdev->flags));
-
return 0;
}
static int btuart_hci_close(struct hci_dev *hdev)
{
- if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
- return 0;
-
btuart_hci_flush(hdev);
return 0;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index b6aceaf82aa8..92f0ee388f9e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -60,6 +60,8 @@ static struct usb_driver btusb_driver;
#define BTUSB_QCA_ROME 0x8000
#define BTUSB_BCM_APPLE 0x10000
#define BTUSB_REALTEK 0x20000
+#define BTUSB_BCM2045 0x40000
+#define BTUSB_IFNUM_2 0x80000
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -73,7 +75,7 @@ static const struct usb_device_id btusb_table[] = {
/* Apple-specific (Broadcom) devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01),
- .driver_info = BTUSB_BCM_APPLE },
+ .driver_info = BTUSB_BCM_APPLE | BTUSB_IFNUM_2 },
/* MediaTek MT76x0E */
{ USB_DEVICE(0x0e8d, 0x763f) },
@@ -124,6 +126,9 @@ static const struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702B0 (Dynex/Insignia) */
{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
+ /* Broadcom BCM43142A0 (Foxconn/Lenovo) */
+ { USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM },
+
/* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
@@ -164,6 +169,9 @@ static const struct usb_device_id blacklist_table[] = {
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
+ /* Broadcom BCM2045 devices */
+ { USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BCM2045 },
+
/* Atheros 3011 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
@@ -195,6 +203,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -206,6 +215,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
@@ -341,12 +351,14 @@ static const struct usb_device_id blacklist_table[] = {
#define BTUSB_FIRMWARE_FAILED 8
#define BTUSB_BOOTING 9
#define BTUSB_RESET_RESUME 10
+#define BTUSB_DIAG_RUNNING 11
struct btusb_data {
struct hci_dev *hdev;
struct usb_device *udev;
struct usb_interface *intf;
struct usb_interface *isoc;
+ struct usb_interface *diag;
unsigned long flags;
@@ -361,6 +373,7 @@ struct btusb_data {
struct usb_anchor intr_anchor;
struct usb_anchor bulk_anchor;
struct usb_anchor isoc_anchor;
+ struct usb_anchor diag_anchor;
spinlock_t rxlock;
struct sk_buff *evt_skb;
@@ -372,6 +385,8 @@ struct btusb_data {
struct usb_endpoint_descriptor *bulk_rx_ep;
struct usb_endpoint_descriptor *isoc_tx_ep;
struct usb_endpoint_descriptor *isoc_rx_ep;
+ struct usb_endpoint_descriptor *diag_tx_ep;
+ struct usb_endpoint_descriptor *diag_rx_ep;
__u8 cmdreq_type;
__u8 cmdreq;
@@ -869,6 +884,92 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
return err;
}
+static void btusb_diag_complete(struct urb *urb)
+{
+ struct hci_dev *hdev = urb->context;
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ int err;
+
+ BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+ urb->actual_length);
+
+ if (urb->status == 0) {
+ struct sk_buff *skb;
+
+ skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC);
+ if (skb) {
+ memcpy(skb_put(skb, urb->actual_length),
+ urb->transfer_buffer, urb->actual_length);
+ hci_recv_diag(hdev, skb);
+ }
+ } else if (urb->status == -ENOENT) {
+ /* Avoid suspend failed when usb_kill_urb */
+ return;
+ }
+
+ if (!test_bit(BTUSB_DIAG_RUNNING, &data->flags))
+ return;
+
+ usb_anchor_urb(urb, &data->diag_anchor);
+ usb_mark_last_busy(data->udev);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ /* -EPERM: urb is being killed;
+ * -ENODEV: device got disconnected */
+ if (err != -EPERM && err != -ENODEV)
+ BT_ERR("%s urb %p failed to resubmit (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ }
+}
+
+static int btusb_submit_diag_urb(struct hci_dev *hdev, gfp_t mem_flags)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct urb *urb;
+ unsigned char *buf;
+ unsigned int pipe;
+ int err, size = HCI_MAX_FRAME_SIZE;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!data->diag_rx_ep)
+ return -ENODEV;
+
+ urb = usb_alloc_urb(0, mem_flags);
+ if (!urb)
+ return -ENOMEM;
+
+ buf = kmalloc(size, mem_flags);
+ if (!buf) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ pipe = usb_rcvbulkpipe(data->udev, data->diag_rx_ep->bEndpointAddress);
+
+ usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
+ btusb_diag_complete, hdev);
+
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ usb_mark_last_busy(data->udev);
+ usb_anchor_urb(urb, &data->diag_anchor);
+
+ err = usb_submit_urb(urb, mem_flags);
+ if (err < 0) {
+ if (err != -EPERM && err != -ENODEV)
+ BT_ERR("%s urb %p submission failed (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ }
+
+ usb_free_urb(urb);
+
+ return err;
+}
+
static void btusb_tx_complete(struct urb *urb)
{
struct sk_buff *skb = urb->context;
@@ -940,9 +1041,6 @@ static int btusb_open(struct hci_dev *hdev)
data->intf->needs_remote_wakeup = 1;
- if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- goto done;
-
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
goto done;
@@ -959,13 +1057,17 @@ static int btusb_open(struct hci_dev *hdev)
set_bit(BTUSB_BULK_RUNNING, &data->flags);
btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+ if (data->diag) {
+ if (!btusb_submit_diag_urb(hdev, GFP_KERNEL))
+ set_bit(BTUSB_DIAG_RUNNING, &data->flags);
+ }
+
done:
usb_autopm_put_interface(data->intf);
return 0;
failed:
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
- clear_bit(HCI_RUNNING, &hdev->flags);
usb_autopm_put_interface(data->intf);
return err;
}
@@ -975,6 +1077,7 @@ static void btusb_stop_traffic(struct btusb_data *data)
usb_kill_anchored_urbs(&data->intr_anchor);
usb_kill_anchored_urbs(&data->bulk_anchor);
usb_kill_anchored_urbs(&data->isoc_anchor);
+ usb_kill_anchored_urbs(&data->diag_anchor);
}
static int btusb_close(struct hci_dev *hdev)
@@ -984,15 +1087,13 @@ static int btusb_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
cancel_work_sync(&data->work);
cancel_work_sync(&data->waker);
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+ clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
btusb_stop_traffic(data);
btusb_free_frags(data);
@@ -1156,9 +1257,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
urb = alloc_ctrl_urb(hdev, skb);
@@ -1274,9 +1372,25 @@ static void btusb_work(struct work_struct *work)
}
if (data->isoc_altsetting != new_alts) {
+ unsigned long flags;
+
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
usb_kill_anchored_urbs(&data->isoc_anchor);
+ /* When isochronous alternate setting needs to be
+ * changed, because SCO connection has been added
+ * or removed, a packet fragment may be left in the
+ * reassembling state. This could lead to wrongly
+ * assembled fragments.
+ *
+ * Clear outstanding fragment when selecting a new
+ * alternate setting.
+ */
+ spin_lock_irqsave(&data->rxlock, flags);
+ kfree_skb(data->sco_skb);
+ data->sco_skb = NULL;
+ spin_unlock_irqrestore(&data->rxlock, flags);
+
if (__set_isoc_interface(hdev, new_alts) < 0)
return;
}
@@ -1348,7 +1462,9 @@ static int btusb_setup_csr(struct hci_dev *hdev)
rp = (struct hci_rp_read_local_version *)skb->data;
- if (le16_to_cpu(rp->manufacturer) != 10) {
+ /* Detect controllers which aren't real CSR ones. */
+ if (le16_to_cpu(rp->manufacturer) != 10 ||
+ le16_to_cpu(rp->lmp_subver) == 0x0c5c) {
/* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR.
*/
@@ -1587,8 +1703,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num);
kfree_skb(skb);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
}
/* Opens the firmware patch file based on the firmware version read
@@ -1600,8 +1715,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
fw = btusb_setup_intel_get_fw(hdev, ver);
if (!fw) {
kfree_skb(skb);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
}
fw_ptr = fw->data;
@@ -1674,8 +1788,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
exit_mfg_disable:
/* Disable the manufacturer mode without reset */
@@ -1690,8 +1803,7 @@ exit_mfg_disable:
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
exit_mfg_deactivate:
release_firmware(fw);
@@ -1711,6 +1823,12 @@ exit_mfg_deactivate:
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name);
+complete:
+ /* Set the event mask for Intel specific vendor events. This enables
+ * a few extra events that are useful during general operation.
+ */
+ btintel_set_event_mask_mfg(hdev, false);
+
btintel_check_bdaddr(hdev);
return 0;
}
@@ -1827,9 +1945,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
@@ -2003,6 +2118,15 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
BT_INFO("%s: Secure boot is %s", hdev->name,
params->secure_boot ? "enabled" : "disabled");
+ BT_INFO("%s: OTP lock is %s", hdev->name,
+ params->otp_lock ? "enabled" : "disabled");
+
+ BT_INFO("%s: API lock is %s", hdev->name,
+ params->api_lock ? "enabled" : "disabled");
+
+ BT_INFO("%s: Debug lock is %s", hdev->name,
+ params->debug_lock ? "enabled" : "disabled");
+
BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name,
params->min_fw_build_nn, params->min_fw_build_cw,
2000 + params->min_fw_build_yy);
@@ -2217,36 +2341,16 @@ done:
* The device can work without DDC parameters, so even if it fails
* to load the file, no need to fail the setup.
*/
- err = request_firmware_direct(&fw, fwname, &hdev->dev);
- if (err < 0)
- return 0;
-
- BT_INFO("%s: Found Intel DDC parameters: %s", hdev->name, fwname);
+ btintel_load_ddc_config(hdev, fwname);
- fw_ptr = fw->data;
-
- /* DDC file contains one or more DDC structure which has
- * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
+ /* Set the event mask for Intel specific vendor events. This enables
+ * a few extra events that are useful during general operation. It
+ * does not enable any debugging related events.
+ *
+ * The device will function correctly without these events enabled
+ * and thus no need to fail the setup.
*/
- while (fw->size > fw_ptr - fw->data) {
- u8 cmd_plen = fw_ptr[0] + sizeof(u8);
-
- skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
- HCI_INIT_TIMEOUT);
- if (IS_ERR(skb)) {
- BT_ERR("%s: Failed to send Intel_Write_DDC (%ld)",
- hdev->name, PTR_ERR(skb));
- release_firmware(fw);
- return PTR_ERR(skb);
- }
-
- fw_ptr += cmd_plen;
- kfree_skb(skb);
- }
-
- release_firmware(fw);
-
- BT_INFO("%s: Applying Intel DDC parameters completed", hdev->name);
+ btintel_set_event_mask(hdev, false);
return 0;
}
@@ -2573,19 +2677,115 @@ static int btusb_setup_qca(struct hci_dev *hdev)
return 0;
}
+#ifdef CONFIG_BT_HCIBTUSB_BCM
+static inline int __set_diag_interface(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct usb_interface *intf = data->diag;
+ int i;
+
+ if (!data->diag)
+ return -ENODEV;
+
+ data->diag_tx_ep = NULL;
+ data->diag_rx_ep = NULL;
+
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+ struct usb_endpoint_descriptor *ep_desc;
+
+ ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (!data->diag_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
+ data->diag_tx_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->diag_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
+ data->diag_rx_ep = ep_desc;
+ continue;
+ }
+ }
+
+ if (!data->diag_tx_ep || !data->diag_rx_ep) {
+ BT_ERR("%s invalid diagnostic descriptors", hdev->name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct sk_buff *skb;
+ struct urb *urb;
+ unsigned int pipe;
+
+ if (!data->diag_tx_ep)
+ return ERR_PTR(-ENODEV);
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return ERR_PTR(-ENOMEM);
+
+ skb = bt_skb_alloc(2, GFP_KERNEL);
+ if (!skb) {
+ usb_free_urb(urb);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ *skb_put(skb, 1) = 0xf0;
+ *skb_put(skb, 1) = enable;
+
+ pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress);
+
+ usb_fill_bulk_urb(urb, data->udev, pipe,
+ skb->data, skb->len, btusb_tx_complete, skb);
+
+ skb->dev = (void *)hdev;
+
+ return urb;
+}
+
+static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct urb *urb;
+
+ if (!data->diag)
+ return -ENODEV;
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return -ENETDOWN;
+
+ urb = alloc_diag_urb(hdev, enable);
+ if (IS_ERR(urb))
+ return PTR_ERR(urb);
+
+ return submit_or_queue_tx_urb(hdev, urb);
+}
+#endif
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *ep_desc;
struct btusb_data *data;
struct hci_dev *hdev;
+ unsigned ifnum_base;
int i, err;
BT_DBG("intf %p id %p", intf, id);
/* interface numbers are hardcoded in the spec */
- if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
- return -ENODEV;
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) {
+ if (!(id->driver_info & BTUSB_IFNUM_2))
+ return -ENODEV;
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
+ return -ENODEV;
+ }
+
+ ifnum_base = intf->cur_altsetting->desc.bInterfaceNumber;
if (!id->driver_info) {
const struct usb_device_id *match;
@@ -2653,6 +2853,7 @@ static int btusb_probe(struct usb_interface *intf,
init_usb_anchor(&data->intr_anchor);
init_usb_anchor(&data->bulk_anchor);
init_usb_anchor(&data->isoc_anchor);
+ init_usb_anchor(&data->diag_anchor);
spin_lock_init(&data->rxlock);
if (id->driver_info & BTUSB_INTEL_NEW) {
@@ -2686,33 +2887,53 @@ static int btusb_probe(struct usb_interface *intf,
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
+ if (id->driver_info & BTUSB_BCM2045)
+ set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
+
if (id->driver_info & BTUSB_BCM92035)
hdev->setup = btusb_setup_bcm92035;
#ifdef CONFIG_BT_HCIBTUSB_BCM
if (id->driver_info & BTUSB_BCM_PATCHRAM) {
+ hdev->manufacturer = 15;
hdev->setup = btbcm_setup_patchram;
+ hdev->set_diag = btusb_bcm_set_diag;
hdev->set_bdaddr = btbcm_set_bdaddr;
+
+ /* Broadcom LM_DIAG Interface numbers are hardcoded */
+ data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
}
- if (id->driver_info & BTUSB_BCM_APPLE)
+ if (id->driver_info & BTUSB_BCM_APPLE) {
+ hdev->manufacturer = 15;
hdev->setup = btbcm_setup_apple;
+ hdev->set_diag = btusb_bcm_set_diag;
+
+ /* Broadcom LM_DIAG Interface numbers are hardcoded */
+ data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
+ }
#endif
if (id->driver_info & BTUSB_INTEL) {
+ hdev->manufacturer = 2;
hdev->setup = btusb_setup_intel;
hdev->shutdown = btusb_shutdown_intel;
+ hdev->set_diag = btintel_set_diag_mfg;
hdev->set_bdaddr = btintel_set_bdaddr;
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);
}
if (id->driver_info & BTUSB_INTEL_NEW) {
+ hdev->manufacturer = 2;
hdev->send = btusb_send_frame_intel;
hdev->setup = btusb_setup_intel_new;
hdev->hw_error = btintel_hw_error;
+ hdev->set_diag = btintel_set_diag;
hdev->set_bdaddr = btintel_set_bdaddr;
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
+ set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
}
if (id->driver_info & BTUSB_MARVELL)
@@ -2723,8 +2944,10 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks);
}
- if (id->driver_info & BTUSB_INTEL_BOOT)
+ if (id->driver_info & BTUSB_INTEL_BOOT) {
+ hdev->manufacturer = 2;
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+ }
if (id->driver_info & BTUSB_ATH3012) {
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
@@ -2753,8 +2976,8 @@ static int btusb_probe(struct usb_interface *intf,
/* AMP controllers do not support SCO packets */
data->isoc = NULL;
} else {
- /* Interface numbers are hardcoded in the specification */
- data->isoc = usb_ifnum_to_if(data->udev, 1);
+ /* Interface orders are hardcoded in the specification */
+ data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1);
}
if (!reset)
@@ -2782,7 +3005,7 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
/* Fake CSR devices with broken commands */
- if (bcdDevice <= 0x100)
+ if (bcdDevice <= 0x100 || bcdDevice == 0x134)
hdev->setup = btusb_setup_csr;
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
@@ -2817,6 +3040,16 @@ static int btusb_probe(struct usb_interface *intf,
}
}
+#ifdef CONFIG_BT_HCIBTUSB_BCM
+ if (data->diag) {
+ if (!usb_driver_claim_interface(&btusb_driver,
+ data->diag, data))
+ __set_diag_interface(hdev);
+ else
+ data->diag = NULL;
+ }
+#endif
+
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
@@ -2844,12 +3077,25 @@ static void btusb_disconnect(struct usb_interface *intf)
if (data->isoc)
usb_set_intfdata(data->isoc, NULL);
+ if (data->diag)
+ usb_set_intfdata(data->diag, NULL);
+
hci_unregister_dev(hdev);
- if (intf == data->isoc)
+ if (intf == data->intf) {
+ if (data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->isoc);
+ if (data->diag)
+ usb_driver_release_interface(&btusb_driver, data->diag);
+ } else if (intf == data->isoc) {
+ if (data->diag)
+ usb_driver_release_interface(&btusb_driver, data->diag);
+ usb_driver_release_interface(&btusb_driver, data->intf);
+ } else if (intf == data->diag) {
usb_driver_release_interface(&btusb_driver, data->intf);
- else if (data->isoc)
- usb_driver_release_interface(&btusb_driver, data->isoc);
+ if (data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->isoc);
+ }
hci_free_dev(hdev);
}
diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c
index 7a722df97343..57eb935aedc7 100644
--- a/drivers/bluetooth/btwilink.c
+++ b/drivers/bluetooth/btwilink.c
@@ -155,9 +155,6 @@ static int ti_st_open(struct hci_dev *hdev)
BT_DBG("%s %p", hdev->name, hdev);
- if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
/* provide contexts for callbacks from ST */
hst = hci_get_drvdata(hdev);
@@ -181,7 +178,6 @@ static int ti_st_open(struct hci_dev *hdev)
goto done;
if (err != -EINPROGRESS) {
- clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("st_register failed %d", err);
return err;
}
@@ -195,7 +191,6 @@ static int ti_st_open(struct hci_dev *hdev)
(&hst->wait_reg_completion,
msecs_to_jiffies(BT_REGISTER_TIMEOUT));
if (!timeleft) {
- clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("Timeout(%d sec),didn't get reg "
"completion signal from ST",
BT_REGISTER_TIMEOUT / 1000);
@@ -205,7 +200,6 @@ static int ti_st_open(struct hci_dev *hdev)
/* Is ST registration callback
* called with ERROR status? */
if (hst->reg_status != 0) {
- clear_bit(HCI_RUNNING, &hdev->flags);
BT_ERR("ST registration completed with invalid "
"status %d", hst->reg_status);
return -EAGAIN;
@@ -215,7 +209,6 @@ done:
hst->st_write = ti_st_proto[i].write;
if (!hst->st_write) {
BT_ERR("undefined ST write function");
- clear_bit(HCI_RUNNING, &hdev->flags);
for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
/* Undo registration with ST */
err = st_unregister(&ti_st_proto[i]);
@@ -236,9 +229,6 @@ static int ti_st_close(struct hci_dev *hdev)
int err, i;
struct ti_st *hst = hci_get_drvdata(hdev);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {
err = st_unregister(&ti_st_proto[i]);
if (err)
@@ -256,9 +246,6 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct ti_st *hst;
long len;
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
hst = hci_get_drvdata(hdev);
/* Prepend skb with frame type */
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 84135c54ed2e..5026f66fac88 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -357,8 +357,6 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
static int dtl1_hci_open(struct hci_dev *hdev)
{
- set_bit(HCI_RUNNING, &(hdev->flags));
-
return 0;
}
@@ -376,9 +374,6 @@ static int dtl1_hci_flush(struct hci_dev *hdev)
static int dtl1_hci_close(struct hci_dev *hdev)
{
- if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
- return 0;
-
dtl1_hci_flush(hdev);
return 0;
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 6da5e4ca13ea..d776dfd51478 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -243,6 +243,7 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)
static const struct hci_uart_proto athp = {
.id = HCI_UART_ATH3K,
.name = "ATH3K",
+ .manufacturer = 69,
.open = ath_open,
.close = ath_close,
.flush = ath_flush,
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 835bfab88ef5..cb852cc750b7 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -31,6 +31,9 @@
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/tty.h>
+#include <linux/interrupt.h>
+#include <linux/dmi.h>
+#include <linux/pm_runtime.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -38,6 +41,11 @@
#include "btbcm.h"
#include "hci_uart.h"
+#define BCM_LM_DIAG_PKT 0x07
+#define BCM_LM_DIAG_SIZE 63
+
+#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
+
struct bcm_device {
struct list_head list;
@@ -51,8 +59,10 @@ struct bcm_device {
bool clk_enabled;
u32 init_speed;
+ int irq;
+ u8 irq_polarity;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
struct hci_uart *hu;
bool is_suspended; /* suspend/resume flag */
#endif
@@ -66,7 +76,7 @@ struct bcm_data {
};
/* List of BCM BT UART devices */
-static DEFINE_SPINLOCK(bcm_device_lock);
+static DEFINE_MUTEX(bcm_device_lock);
static LIST_HEAD(bcm_device_list);
static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
@@ -80,7 +90,7 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
clock.type = BCM_UART_CLOCK_48MHZ;
- BT_DBG("%s: Set Controller clock (%d)", hdev->name, clock.type);
+ bt_dev_dbg(hdev, "Set Controller clock (%d)", clock.type);
/* This Broadcom specific command changes the UART's controller
* clock for baud rate > 3000000.
@@ -88,15 +98,15 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
skb = __hci_cmd_sync(hdev, 0xfc45, 1, &clock, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
- BT_ERR("%s: BCM: failed to write clock command (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "BCM: failed to write clock (%d)",
+ err);
return err;
}
kfree_skb(skb);
}
- BT_DBG("%s: Set Controller UART speed to %d bit/s", hdev->name, speed);
+ bt_dev_dbg(hdev, "Set Controller UART speed to %d bit/s", speed);
param.zero = cpu_to_le16(0);
param.baud_rate = cpu_to_le32(speed);
@@ -108,8 +118,8 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
- BT_ERR("%s: BCM: failed to write update baudrate command (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "BCM: failed to write update baudrate (%d)",
+ err);
return err;
}
@@ -149,12 +159,125 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
return 0;
}
+#ifdef CONFIG_PM
+static irqreturn_t bcm_host_wake(int irq, void *data)
+{
+ struct bcm_device *bdev = data;
+
+ bt_dev_dbg(bdev, "Host wake IRQ");
+
+ pm_runtime_get(&bdev->pdev->dev);
+ pm_runtime_mark_last_busy(&bdev->pdev->dev);
+ pm_runtime_put_autosuspend(&bdev->pdev->dev);
+
+ return IRQ_HANDLED;
+}
+
+static int bcm_request_irq(struct bcm_data *bcm)
+{
+ struct bcm_device *bdev = bcm->dev;
+ int err = 0;
+
+ /* If this is not a platform device, do not enable PM functionalities */
+ mutex_lock(&bcm_device_lock);
+ if (!bcm_device_exists(bdev)) {
+ err = -ENODEV;
+ goto unlock;
+ }
+
+ if (bdev->irq > 0) {
+ err = devm_request_irq(&bdev->pdev->dev, bdev->irq,
+ bcm_host_wake, IRQF_TRIGGER_RISING,
+ "host_wake", bdev);
+ if (err)
+ goto unlock;
+
+ device_init_wakeup(&bdev->pdev->dev, true);
+
+ pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
+ BCM_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&bdev->pdev->dev);
+ pm_runtime_set_active(&bdev->pdev->dev);
+ pm_runtime_enable(&bdev->pdev->dev);
+ }
+
+unlock:
+ mutex_unlock(&bcm_device_lock);
+
+ return err;
+}
+
+static const struct bcm_set_sleep_mode default_sleep_params = {
+ .sleep_mode = 1, /* 0=Disabled, 1=UART, 2=Reserved, 3=USB */
+ .idle_host = 2, /* idle threshold HOST, in 300ms */
+ .idle_dev = 2, /* idle threshold device, in 300ms */
+ .bt_wake_active = 1, /* BT_WAKE active mode: 1 = high, 0 = low */
+ .host_wake_active = 0, /* HOST_WAKE active mode: 1 = high, 0 = low */
+ .allow_host_sleep = 1, /* Allow host sleep in SCO flag */
+ .combine_modes = 1, /* Combine sleep and LPM flag */
+ .tristate_control = 0, /* Allow tri-state control of UART tx flag */
+ /* Irrelevant USB flags */
+ .usb_auto_sleep = 0,
+ .usb_resume_timeout = 0,
+ .pulsed_host_wake = 0,
+ .break_to_host = 0
+};
+
+static int bcm_setup_sleep(struct hci_uart *hu)
+{
+ struct bcm_data *bcm = hu->priv;
+ struct sk_buff *skb;
+ struct bcm_set_sleep_mode sleep_params = default_sleep_params;
+
+ sleep_params.host_wake_active = !bcm->dev->irq_polarity;
+
+ skb = __hci_cmd_sync(hu->hdev, 0xfc27, sizeof(sleep_params),
+ &sleep_params, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ int err = PTR_ERR(skb);
+ bt_dev_err(hu->hdev, "Sleep VSC failed (%d)", err);
+ return err;
+ }
+ kfree_skb(skb);
+
+ bt_dev_dbg(hu->hdev, "Set Sleep Parameters VSC succeeded");
+
+ return 0;
+}
+#else
+static inline int bcm_request_irq(struct bcm_data *bcm) { return 0; }
+static inline int bcm_setup_sleep(struct hci_uart *hu) { return 0; }
+#endif
+
+static int bcm_set_diag(struct hci_dev *hdev, bool enable)
+{
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ struct bcm_data *bcm = hu->priv;
+ struct sk_buff *skb;
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return -ENETDOWN;
+
+ skb = bt_skb_alloc(3, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ *skb_put(skb, 1) = BCM_LM_DIAG_PKT;
+ *skb_put(skb, 1) = 0xf0;
+ *skb_put(skb, 1) = enable;
+
+ skb_queue_tail(&bcm->txq, skb);
+ hci_uart_tx_wakeup(hu);
+
+ return 0;
+}
+
static int bcm_open(struct hci_uart *hu)
{
struct bcm_data *bcm;
struct list_head *p;
- BT_DBG("hu %p", hu);
+ bt_dev_dbg(hu->hdev, "hu %p", hu);
bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
if (!bcm)
@@ -164,7 +287,7 @@ static int bcm_open(struct hci_uart *hu)
hu->priv = bcm;
- spin_lock(&bcm_device_lock);
+ mutex_lock(&bcm_device_lock);
list_for_each(p, &bcm_device_list) {
struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@@ -175,17 +298,15 @@ static int bcm_open(struct hci_uart *hu)
if (hu->tty->dev->parent == dev->pdev->dev.parent) {
bcm->dev = dev;
hu->init_speed = dev->init_speed;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
dev->hu = hu;
#endif
+ bcm_gpio_set_power(bcm->dev, true);
break;
}
}
- if (bcm->dev)
- bcm_gpio_set_power(bcm->dev, true);
-
- spin_unlock(&bcm_device_lock);
+ mutex_unlock(&bcm_device_lock);
return 0;
}
@@ -193,18 +314,27 @@ static int bcm_open(struct hci_uart *hu)
static int bcm_close(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
+ struct bcm_device *bdev = bcm->dev;
- BT_DBG("hu %p", hu);
+ bt_dev_dbg(hu->hdev, "hu %p", hu);
/* Protect bcm->dev against removal of the device or driver */
- spin_lock(&bcm_device_lock);
- if (bcm_device_exists(bcm->dev)) {
- bcm_gpio_set_power(bcm->dev, false);
-#ifdef CONFIG_PM_SLEEP
- bcm->dev->hu = NULL;
+ mutex_lock(&bcm_device_lock);
+ if (bcm_device_exists(bdev)) {
+ bcm_gpio_set_power(bdev, false);
+#ifdef CONFIG_PM
+ pm_runtime_disable(&bdev->pdev->dev);
+ pm_runtime_set_suspended(&bdev->pdev->dev);
+
+ if (device_can_wakeup(&bdev->pdev->dev)) {
+ devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
+ device_init_wakeup(&bdev->pdev->dev, false);
+ }
+
+ bdev->hu = NULL;
#endif
}
- spin_unlock(&bcm_device_lock);
+ mutex_unlock(&bcm_device_lock);
skb_queue_purge(&bcm->txq);
kfree_skb(bcm->rx_skb);
@@ -218,7 +348,7 @@ static int bcm_flush(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
- BT_DBG("hu %p", hu);
+ bt_dev_dbg(hu->hdev, "hu %p", hu);
skb_queue_purge(&bcm->txq);
@@ -227,13 +357,15 @@ static int bcm_flush(struct hci_uart *hu)
static int bcm_setup(struct hci_uart *hu)
{
+ struct bcm_data *bcm = hu->priv;
char fw_name[64];
const struct firmware *fw;
unsigned int speed;
int err;
- BT_DBG("hu %p", hu);
+ bt_dev_dbg(hu->hdev, "hu %p", hu);
+ hu->hdev->set_diag = bcm_set_diag;
hu->hdev->set_bdaddr = btbcm_set_bdaddr;
err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name));
@@ -242,13 +374,13 @@ static int bcm_setup(struct hci_uart *hu)
err = request_firmware(&fw, fw_name, &hu->hdev->dev);
if (err < 0) {
- BT_INFO("%s: BCM: Patch %s not found", hu->hdev->name, fw_name);
+ bt_dev_info(hu->hdev, "BCM: Patch %s not found", fw_name);
return 0;
}
err = btbcm_patchram(hu->hdev, fw);
if (err) {
- BT_INFO("%s: BCM: Patch failed (%d)", hu->hdev->name, err);
+ bt_dev_info(hu->hdev, "BCM: Patch failed (%d)", err);
goto finalize;
}
@@ -281,14 +413,28 @@ finalize:
release_firmware(fw);
err = btbcm_finalize(hu->hdev);
+ if (err)
+ return err;
+
+ err = bcm_request_irq(bcm);
+ if (!err)
+ err = bcm_setup_sleep(hu);
return err;
}
+#define BCM_RECV_LM_DIAG \
+ .type = BCM_LM_DIAG_PKT, \
+ .hlen = BCM_LM_DIAG_SIZE, \
+ .loff = 0, \
+ .lsize = 0, \
+ .maxlen = BCM_LM_DIAG_SIZE
+
static const struct h4_recv_pkt bcm_recv_pkts[] = {
- { H4_RECV_ACL, .recv = hci_recv_frame },
- { H4_RECV_SCO, .recv = hci_recv_frame },
- { H4_RECV_EVENT, .recv = hci_recv_frame },
+ { H4_RECV_ACL, .recv = hci_recv_frame },
+ { H4_RECV_SCO, .recv = hci_recv_frame },
+ { H4_RECV_EVENT, .recv = hci_recv_frame },
+ { BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
};
static int bcm_recv(struct hci_uart *hu, const void *data, int count)
@@ -302,9 +448,18 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
bcm_recv_pkts, ARRAY_SIZE(bcm_recv_pkts));
if (IS_ERR(bcm->rx_skb)) {
int err = PTR_ERR(bcm->rx_skb);
- BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
+ bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
bcm->rx_skb = NULL;
return err;
+ } else if (!bcm->rx_skb) {
+ /* Delay auto-suspend when receiving completed packet */
+ mutex_lock(&bcm_device_lock);
+ if (bcm->dev && bcm_device_exists(bcm->dev)) {
+ pm_runtime_get(&bcm->dev->pdev->dev);
+ pm_runtime_mark_last_busy(&bcm->dev->pdev->dev);
+ pm_runtime_put_autosuspend(&bcm->dev->pdev->dev);
+ }
+ mutex_unlock(&bcm_device_lock);
}
return count;
@@ -314,7 +469,7 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct bcm_data *bcm = hu->priv;
- BT_DBG("hu %p skb %p", hu, skb);
+ bt_dev_dbg(hu->hdev, "hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
@@ -326,39 +481,105 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
+ struct sk_buff *skb = NULL;
+ struct bcm_device *bdev = NULL;
+
+ mutex_lock(&bcm_device_lock);
+
+ if (bcm_device_exists(bcm->dev)) {
+ bdev = bcm->dev;
+ pm_runtime_get_sync(&bdev->pdev->dev);
+ /* Shall be resumed here */
+ }
+
+ skb = skb_dequeue(&bcm->txq);
+
+ if (bdev) {
+ pm_runtime_mark_last_busy(&bdev->pdev->dev);
+ pm_runtime_put_autosuspend(&bdev->pdev->dev);
+ }
+
+ mutex_unlock(&bcm_device_lock);
- return skb_dequeue(&bcm->txq);
+ return skb;
}
-#ifdef CONFIG_PM_SLEEP
-/* Platform suspend callback */
-static int bcm_suspend(struct device *dev)
+#ifdef CONFIG_PM
+static int bcm_suspend_device(struct device *dev)
{
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
- BT_DBG("suspend (%p): is_suspended %d", bdev, bdev->is_suspended);
+ bt_dev_dbg(bdev, "");
- spin_lock(&bcm_device_lock);
-
- if (!bdev->hu)
- goto unlock;
-
- if (!bdev->is_suspended) {
+ if (!bdev->is_suspended && bdev->hu) {
hci_uart_set_flow_control(bdev->hu, true);
- /* Once this callback returns, driver suspends BT via GPIO */
+ /* Once this returns, driver suspends BT via GPIO */
bdev->is_suspended = true;
}
/* Suspend the device */
if (bdev->device_wakeup) {
gpiod_set_value(bdev->device_wakeup, false);
- BT_DBG("suspend, delaying 15 ms");
+ bt_dev_dbg(bdev, "suspend, delaying 15 ms");
mdelay(15);
}
+ return 0;
+}
+
+static int bcm_resume_device(struct device *dev)
+{
+ struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
+
+ bt_dev_dbg(bdev, "");
+
+ if (bdev->device_wakeup) {
+ gpiod_set_value(bdev->device_wakeup, true);
+ bt_dev_dbg(bdev, "resume, delaying 15 ms");
+ mdelay(15);
+ }
+
+ /* When this executes, the device has woken up already */
+ if (bdev->is_suspended && bdev->hu) {
+ bdev->is_suspended = false;
+
+ hci_uart_set_flow_control(bdev->hu, false);
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+/* Platform suspend callback */
+static int bcm_suspend(struct device *dev)
+{
+ struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
+ int error;
+
+ bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
+
+ /* bcm_suspend can be called at any time as long as platform device is
+ * bound, so it should use bcm_device_lock to protect access to hci_uart
+ * and device_wake-up GPIO.
+ */
+ mutex_lock(&bcm_device_lock);
+
+ if (!bdev->hu)
+ goto unlock;
+
+ if (pm_runtime_active(dev))
+ bcm_suspend_device(dev);
+
+ if (device_may_wakeup(&bdev->pdev->dev)) {
+ error = enable_irq_wake(bdev->irq);
+ if (!error)
+ bt_dev_dbg(bdev, "BCM irq: enabled");
+ }
+
unlock:
- spin_unlock(&bcm_device_lock);
+ mutex_unlock(&bcm_device_lock);
return 0;
}
@@ -368,28 +589,30 @@ static int bcm_resume(struct device *dev)
{
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
- BT_DBG("resume (%p): is_suspended %d", bdev, bdev->is_suspended);
+ bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
- spin_lock(&bcm_device_lock);
+ /* bcm_resume can be called at any time as long as platform device is
+ * bound, so it should use bcm_device_lock to protect access to hci_uart
+ * and device_wake-up GPIO.
+ */
+ mutex_lock(&bcm_device_lock);
if (!bdev->hu)
goto unlock;
- if (bdev->device_wakeup) {
- gpiod_set_value(bdev->device_wakeup, true);
- BT_DBG("resume, delaying 15 ms");
- mdelay(15);
+ if (device_may_wakeup(&bdev->pdev->dev)) {
+ disable_irq_wake(bdev->irq);
+ bt_dev_dbg(bdev, "BCM irq: disabled");
}
- /* When this callback executes, the device has woken up already */
- if (bdev->is_suspended) {
- bdev->is_suspended = false;
-
- hci_uart_set_flow_control(bdev->hu, false);
- }
+ bcm_resume_device(dev);
unlock:
- spin_unlock(&bcm_device_lock);
+ mutex_unlock(&bcm_device_lock);
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
return 0;
}
@@ -397,24 +620,59 @@ unlock:
static const struct acpi_gpio_params device_wakeup_gpios = { 0, 0, false };
static const struct acpi_gpio_params shutdown_gpios = { 1, 0, false };
+static const struct acpi_gpio_params host_wakeup_gpios = { 2, 0, false };
static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
{ "device-wakeup-gpios", &device_wakeup_gpios, 1 },
{ "shutdown-gpios", &shutdown_gpios, 1 },
+ { "host-wakeup-gpios", &host_wakeup_gpios, 1 },
{ },
};
#ifdef CONFIG_ACPI
+static u8 acpi_active_low = ACPI_ACTIVE_LOW;
+
+/* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
+static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
+ {
+ .ident = "Asus T100TA",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR,
+ "ASUSTeK COMPUTER INC."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+ },
+ .driver_data = &acpi_active_low,
+ },
+ { }
+};
+
static int bcm_resource(struct acpi_resource *ares, void *data)
{
struct bcm_device *dev = data;
-
- if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- struct acpi_resource_uart_serialbus *sb;
-
+ struct acpi_resource_extended_irq *irq;
+ struct acpi_resource_gpio *gpio;
+ struct acpi_resource_uart_serialbus *sb;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ irq = &ares->data.extended_irq;
+ dev->irq_polarity = irq->polarity;
+ break;
+
+ case ACPI_RESOURCE_TYPE_GPIO:
+ gpio = &ares->data.gpio;
+ if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
+ dev->irq_polarity = gpio->polarity;
+ break;
+
+ case ACPI_RESOURCE_TYPE_SERIAL_BUS:
sb = &ares->data.uart_serial_bus;
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART)
dev->init_speed = sb->default_baud_rate;
+ break;
+
+ default:
+ break;
}
/* Always tell the ACPI core to skip this resource */
@@ -424,15 +682,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
static int bcm_acpi_probe(struct bcm_device *dev)
{
struct platform_device *pdev = dev->pdev;
- const struct acpi_device_id *id;
- struct acpi_device *adev;
LIST_HEAD(resources);
+ const struct dmi_system_id *dmi_id;
int ret;
- id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
- if (!id)
- return -ENODEV;
-
/* Retrieve GPIO data */
dev->name = dev_name(&pdev->dev);
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
@@ -453,6 +706,21 @@ static int bcm_acpi_probe(struct bcm_device *dev)
if (IS_ERR(dev->shutdown))
return PTR_ERR(dev->shutdown);
+ /* IRQ can be declared in ACPI table as Interrupt or GpioInt */
+ dev->irq = platform_get_irq(pdev, 0);
+ if (dev->irq <= 0) {
+ struct gpio_desc *gpio;
+
+ gpio = devm_gpiod_get_optional(&pdev->dev, "host-wakeup",
+ GPIOD_IN);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
+
+ dev->irq = gpiod_to_irq(gpio);
+ }
+
+ dev_info(&pdev->dev, "BCM irq: %d\n", dev->irq);
+
/* Make sure at-least one of the GPIO is defined and that
* a name is specified for this instance
*/
@@ -462,11 +730,18 @@ static int bcm_acpi_probe(struct bcm_device *dev)
}
/* Retrieve UART ACPI info */
- adev = ACPI_COMPANION(&dev->pdev->dev);
- if (!adev)
- return 0;
+ ret = acpi_dev_get_resources(ACPI_COMPANION(&dev->pdev->dev),
+ &resources, bcm_resource, dev);
+ if (ret < 0)
+ return ret;
+ acpi_dev_free_resource_list(&resources);
- acpi_dev_get_resources(adev, &resources, bcm_resource, dev);
+ dmi_id = dmi_first_match(bcm_wrong_irq_dmi_table);
+ if (dmi_id) {
+ bt_dev_warn(dev, "%s: Overwriting IRQ polarity to active low",
+ dmi_id->ident);
+ dev->irq_polarity = *(u8 *)dmi_id->driver_data;
+ }
return 0;
}
@@ -480,7 +755,6 @@ static int bcm_acpi_probe(struct bcm_device *dev)
static int bcm_probe(struct platform_device *pdev)
{
struct bcm_device *dev;
- struct acpi_device_id *pdata = pdev->dev.platform_data;
int ret;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -489,24 +763,18 @@ static int bcm_probe(struct platform_device *pdev)
dev->pdev = pdev;
- if (ACPI_HANDLE(&pdev->dev)) {
- ret = bcm_acpi_probe(dev);
- if (ret)
- return ret;
- } else if (pdata) {
- dev->name = pdata->id;
- } else {
- return -ENODEV;
- }
+ ret = bcm_acpi_probe(dev);
+ if (ret)
+ return ret;
platform_set_drvdata(pdev, dev);
dev_info(&pdev->dev, "%s device registered.\n", dev->name);
/* Place this instance on the device list */
- spin_lock(&bcm_device_lock);
+ mutex_lock(&bcm_device_lock);
list_add_tail(&dev->list, &bcm_device_list);
- spin_unlock(&bcm_device_lock);
+ mutex_unlock(&bcm_device_lock);
bcm_gpio_set_power(dev, false);
@@ -517,9 +785,9 @@ static int bcm_remove(struct platform_device *pdev)
{
struct bcm_device *dev = platform_get_drvdata(pdev);
- spin_lock(&bcm_device_lock);
+ mutex_lock(&bcm_device_lock);
list_del(&dev->list);
- spin_unlock(&bcm_device_lock);
+ mutex_unlock(&bcm_device_lock);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
@@ -531,6 +799,7 @@ static int bcm_remove(struct platform_device *pdev)
static const struct hci_uart_proto bcm_proto = {
.id = HCI_UART_BCM,
.name = "BCM",
+ .manufacturer = 15,
.init_speed = 115200,
.oper_speed = 4000000,
.open = bcm_open,
@@ -553,7 +822,10 @@ MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
#endif
/* Platform suspend and resume callbacks */
-static SIMPLE_DEV_PM_OPS(bcm_pm_ops, bcm_suspend, bcm_resume);
+static const struct dev_pm_ops bcm_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume)
+ SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL)
+};
static struct platform_driver bcm_driver = {
.probe = bcm_probe,
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index eec3f28e4bb9..a6fce48da0fb 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
return skb;
}
+EXPORT_SYMBOL_GPL(h4_recv_buf);
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index b35b238a0380..abee2216fdeb 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -128,7 +128,7 @@ static void h5_timed_event(unsigned long arg)
{
const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
- struct hci_uart *hu = (struct hci_uart *) arg;
+ struct hci_uart *hu = (struct hci_uart *)arg;
struct h5 *h5 = hu->priv;
struct sk_buff *skb;
unsigned long flags;
@@ -210,7 +210,7 @@ static int h5_open(struct hci_uart *hu)
init_timer(&h5->timer);
h5->timer.function = h5_timed_event;
- h5->timer.data = (unsigned long) hu;
+ h5->timer.data = (unsigned long)hu;
h5->tx_win = H5_TX_WIN_MAX;
@@ -453,7 +453,7 @@ static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c)
return -ENOMEM;
}
- h5->rx_skb->dev = (void *) hu->hdev;
+ h5->rx_skb->dev = (void *)hu->hdev;
return 0;
}
@@ -696,7 +696,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
}
skb = skb_dequeue(&h5->unrel);
- if (skb != NULL) {
+ if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len);
if (nskb) {
@@ -714,7 +714,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
goto unlock;
skb = skb_dequeue(&h5->rel);
- if (skb != NULL) {
+ if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len);
if (nskb) {
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index cf07d1121956..4a414a5a3165 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -31,6 +31,8 @@
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/acpi.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -43,19 +45,45 @@
#define STATE_FIRMWARE_LOADED 2
#define STATE_FIRMWARE_FAILED 3
#define STATE_BOOTING 4
+#define STATE_LPM_ENABLED 5
+#define STATE_TX_ACTIVE 6
+#define STATE_SUSPENDED 7
+#define STATE_LPM_TRANSACTION 8
+
+#define HCI_LPM_WAKE_PKT 0xf0
+#define HCI_LPM_PKT 0xf1
+#define HCI_LPM_MAX_SIZE 10
+#define HCI_LPM_HDR_SIZE HCI_EVENT_HDR_SIZE
+
+#define LPM_OP_TX_NOTIFY 0x00
+#define LPM_OP_SUSPEND_ACK 0x02
+#define LPM_OP_RESUME_ACK 0x03
+
+#define LPM_SUSPEND_DELAY_MS 1000
+
+struct hci_lpm_pkt {
+ __u8 opcode;
+ __u8 dlen;
+ __u8 data[0];
+} __packed;
struct intel_device {
struct list_head list;
struct platform_device *pdev;
struct gpio_desc *reset;
+ struct hci_uart *hu;
+ struct mutex hu_lock;
+ int irq;
};
static LIST_HEAD(intel_device_list);
-static DEFINE_SPINLOCK(intel_device_list_lock);
+static DEFINE_MUTEX(intel_device_list_lock);
struct intel_data {
struct sk_buff *rx_skb;
struct sk_buff_head txq;
+ struct work_struct busy_work;
+ struct hci_uart *hu;
unsigned long flags;
};
@@ -101,24 +129,185 @@ static int intel_wait_booting(struct hci_uart *hu)
msecs_to_jiffies(1000));
if (err == 1) {
- BT_ERR("%s: Device boot interrupted", hu->hdev->name);
+ bt_dev_err(hu->hdev, "Device boot interrupted");
return -EINTR;
}
if (err) {
- BT_ERR("%s: Device boot timeout", hu->hdev->name);
+ bt_dev_err(hu->hdev, "Device boot timeout");
return -ETIMEDOUT;
}
return err;
}
+#ifdef CONFIG_PM
+static int intel_wait_lpm_transaction(struct hci_uart *hu)
+{
+ struct intel_data *intel = hu->priv;
+ int err;
+
+ err = wait_on_bit_timeout(&intel->flags, STATE_LPM_TRANSACTION,
+ TASK_INTERRUPTIBLE,
+ msecs_to_jiffies(1000));
+
+ if (err == 1) {
+ bt_dev_err(hu->hdev, "LPM transaction interrupted");
+ return -EINTR;
+ }
+
+ if (err) {
+ bt_dev_err(hu->hdev, "LPM transaction timeout");
+ return -ETIMEDOUT;
+ }
+
+ return err;
+}
+
+static int intel_lpm_suspend(struct hci_uart *hu)
+{
+ static const u8 suspend[] = { 0x01, 0x01, 0x01 };
+ struct intel_data *intel = hu->priv;
+ struct sk_buff *skb;
+
+ if (!test_bit(STATE_LPM_ENABLED, &intel->flags) ||
+ test_bit(STATE_SUSPENDED, &intel->flags))
+ return 0;
+
+ if (test_bit(STATE_TX_ACTIVE, &intel->flags))
+ return -EAGAIN;
+
+ bt_dev_dbg(hu->hdev, "Suspending");
+
+ skb = bt_skb_alloc(sizeof(suspend), GFP_KERNEL);
+ if (!skb) {
+ bt_dev_err(hu->hdev, "Failed to alloc memory for LPM packet");
+ return -ENOMEM;
+ }
+
+ memcpy(skb_put(skb, sizeof(suspend)), suspend, sizeof(suspend));
+ bt_cb(skb)->pkt_type = HCI_LPM_PKT;
+
+ set_bit(STATE_LPM_TRANSACTION, &intel->flags);
+
+ /* LPM flow is a priority, enqueue packet at list head */
+ skb_queue_head(&intel->txq, skb);
+ hci_uart_tx_wakeup(hu);
+
+ intel_wait_lpm_transaction(hu);
+ /* Even in case of failure, continue and test the suspended flag */
+
+ clear_bit(STATE_LPM_TRANSACTION, &intel->flags);
+
+ if (!test_bit(STATE_SUSPENDED, &intel->flags)) {
+ bt_dev_err(hu->hdev, "Device suspend error");
+ return -EINVAL;
+ }
+
+ bt_dev_dbg(hu->hdev, "Suspended");
+
+ hci_uart_set_flow_control(hu, true);
+
+ return 0;
+}
+
+static int intel_lpm_resume(struct hci_uart *hu)
+{
+ struct intel_data *intel = hu->priv;
+ struct sk_buff *skb;
+
+ if (!test_bit(STATE_LPM_ENABLED, &intel->flags) ||
+ !test_bit(STATE_SUSPENDED, &intel->flags))
+ return 0;
+
+ bt_dev_dbg(hu->hdev, "Resuming");
+
+ hci_uart_set_flow_control(hu, false);
+
+ skb = bt_skb_alloc(0, GFP_KERNEL);
+ if (!skb) {
+ bt_dev_err(hu->hdev, "Failed to alloc memory for LPM packet");
+ return -ENOMEM;
+ }
+
+ bt_cb(skb)->pkt_type = HCI_LPM_WAKE_PKT;
+
+ set_bit(STATE_LPM_TRANSACTION, &intel->flags);
+
+ /* LPM flow is a priority, enqueue packet at list head */
+ skb_queue_head(&intel->txq, skb);
+ hci_uart_tx_wakeup(hu);
+
+ intel_wait_lpm_transaction(hu);
+ /* Even in case of failure, continue and test the suspended flag */
+
+ clear_bit(STATE_LPM_TRANSACTION, &intel->flags);
+
+ if (test_bit(STATE_SUSPENDED, &intel->flags)) {
+ bt_dev_err(hu->hdev, "Device resume error");
+ return -EINVAL;
+ }
+
+ bt_dev_dbg(hu->hdev, "Resumed");
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static int intel_lpm_host_wake(struct hci_uart *hu)
+{
+ static const u8 lpm_resume_ack[] = { LPM_OP_RESUME_ACK, 0x00 };
+ struct intel_data *intel = hu->priv;
+ struct sk_buff *skb;
+
+ hci_uart_set_flow_control(hu, false);
+
+ clear_bit(STATE_SUSPENDED, &intel->flags);
+
+ skb = bt_skb_alloc(sizeof(lpm_resume_ack), GFP_KERNEL);
+ if (!skb) {
+ bt_dev_err(hu->hdev, "Failed to alloc memory for LPM packet");
+ return -ENOMEM;
+ }
+
+ memcpy(skb_put(skb, sizeof(lpm_resume_ack)), lpm_resume_ack,
+ sizeof(lpm_resume_ack));
+ bt_cb(skb)->pkt_type = HCI_LPM_PKT;
+
+ /* LPM flow is a priority, enqueue packet at list head */
+ skb_queue_head(&intel->txq, skb);
+ hci_uart_tx_wakeup(hu);
+
+ bt_dev_dbg(hu->hdev, "Resumed by controller");
+
+ return 0;
+}
+
+static irqreturn_t intel_irq(int irq, void *dev_id)
+{
+ struct intel_device *idev = dev_id;
+
+ dev_info(&idev->pdev->dev, "hci_intel irq\n");
+
+ mutex_lock(&idev->hu_lock);
+ if (idev->hu)
+ intel_lpm_host_wake(idev->hu);
+ mutex_unlock(&idev->hu_lock);
+
+ /* Host/Controller are now LPM resumed, trigger a new delayed suspend */
+ pm_runtime_get(&idev->pdev->dev);
+ pm_runtime_mark_last_busy(&idev->pdev->dev);
+ pm_runtime_put_autosuspend(&idev->pdev->dev);
+
+ return IRQ_HANDLED;
+}
+
static int intel_set_power(struct hci_uart *hu, bool powered)
{
struct list_head *p;
int err = -ENODEV;
- spin_lock(&intel_device_list_lock);
+ mutex_lock(&intel_device_list_lock);
list_for_each(p, &intel_device_list) {
struct intel_device *idev = list_entry(p, struct intel_device,
@@ -139,13 +328,73 @@ static int intel_set_power(struct hci_uart *hu, bool powered)
hu, dev_name(&idev->pdev->dev), powered);
gpiod_set_value(idev->reset, powered);
+
+ /* Provide to idev a hu reference which is used to run LPM
+ * transactions (lpm suspend/resume) from PM callbacks.
+ * hu needs to be protected against concurrent removing during
+ * these PM ops.
+ */
+ mutex_lock(&idev->hu_lock);
+ idev->hu = powered ? hu : NULL;
+ mutex_unlock(&idev->hu_lock);
+
+ if (idev->irq < 0)
+ break;
+
+ if (powered && device_can_wakeup(&idev->pdev->dev)) {
+ err = devm_request_threaded_irq(&idev->pdev->dev,
+ idev->irq, NULL,
+ intel_irq,
+ IRQF_ONESHOT,
+ "bt-host-wake", idev);
+ if (err) {
+ BT_ERR("hu %p, unable to allocate irq-%d",
+ hu, idev->irq);
+ break;
+ }
+
+ device_wakeup_enable(&idev->pdev->dev);
+
+ pm_runtime_set_active(&idev->pdev->dev);
+ pm_runtime_use_autosuspend(&idev->pdev->dev);
+ pm_runtime_set_autosuspend_delay(&idev->pdev->dev,
+ LPM_SUSPEND_DELAY_MS);
+ pm_runtime_enable(&idev->pdev->dev);
+ } else if (!powered && device_may_wakeup(&idev->pdev->dev)) {
+ devm_free_irq(&idev->pdev->dev, idev->irq, idev);
+ device_wakeup_disable(&idev->pdev->dev);
+
+ pm_runtime_disable(&idev->pdev->dev);
+ }
}
- spin_unlock(&intel_device_list_lock);
+ mutex_unlock(&intel_device_list_lock);
return err;
}
+static void intel_busy_work(struct work_struct *work)
+{
+ struct list_head *p;
+ struct intel_data *intel = container_of(work, struct intel_data,
+ busy_work);
+
+ /* Link is busy, delay the suspend */
+ mutex_lock(&intel_device_list_lock);
+ list_for_each(p, &intel_device_list) {
+ struct intel_device *idev = list_entry(p, struct intel_device,
+ list);
+
+ if (intel->hu->tty->dev->parent == idev->pdev->dev.parent) {
+ pm_runtime_get(&idev->pdev->dev);
+ pm_runtime_mark_last_busy(&idev->pdev->dev);
+ pm_runtime_put_autosuspend(&idev->pdev->dev);
+ break;
+ }
+ }
+ mutex_unlock(&intel_device_list_lock);
+}
+
static int intel_open(struct hci_uart *hu)
{
struct intel_data *intel;
@@ -157,6 +406,9 @@ static int intel_open(struct hci_uart *hu)
return -ENOMEM;
skb_queue_head_init(&intel->txq);
+ INIT_WORK(&intel->busy_work, intel_busy_work);
+
+ intel->hu = hu;
hu->priv = intel;
@@ -172,6 +424,8 @@ static int intel_close(struct hci_uart *hu)
BT_DBG("hu %p", hu);
+ cancel_work_sync(&intel->busy_work);
+
intel_set_power(hu, false);
skb_queue_purge(&intel->txq);
@@ -237,11 +491,11 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
if (err && err != ETIMEDOUT)
return err;
- BT_INFO("%s: Change controller speed to %d", hdev->name, speed);
+ bt_dev_info(hdev, "Change controller speed to %d", speed);
speed_cmd[3] = intel_convert_speed(speed);
if (speed_cmd[3] == 0xff) {
- BT_ERR("%s: Unsupported speed", hdev->name);
+ bt_dev_err(hdev, "Unsupported speed");
return -EINVAL;
}
@@ -250,16 +504,15 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
*/
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
- BT_ERR("%s: Reading Intel version information failed (%ld)",
- hdev->name, PTR_ERR(skb));
+ bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
+ PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
skb = bt_skb_alloc(sizeof(speed_cmd), GFP_KERNEL);
if (!skb) {
- BT_ERR("%s: Failed to allocate memory for baudrate packet",
- hdev->name);
+ bt_dev_err(hdev, "Failed to alloc memory for baudrate packet");
return -ENOMEM;
}
@@ -284,11 +537,14 @@ static int intel_setup(struct hci_uart *hu)
{
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
0x00, 0x08, 0x04, 0x00 };
+ static const u8 lpm_param[] = { 0x03, 0x07, 0x01, 0x0b };
struct intel_data *intel = hu->priv;
+ struct intel_device *idev = NULL;
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
struct intel_version *ver;
struct intel_boot_params *params;
+ struct list_head *p;
const struct firmware *fw;
const u8 *fw_ptr;
char fwname[64];
@@ -299,8 +555,9 @@ static int intel_setup(struct hci_uart *hu)
int speed_change = 0;
int err;
- BT_DBG("%s", hdev->name);
+ bt_dev_dbg(hdev, "start intel_setup");
+ hu->hdev->set_diag = btintel_set_diag;
hu->hdev->set_bdaddr = btintel_set_bdaddr;
calltime = ktime_get();
@@ -335,21 +592,21 @@ static int intel_setup(struct hci_uart *hu)
*/
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
- BT_ERR("%s: Reading Intel version information failed (%ld)",
- hdev->name, PTR_ERR(skb));
+ bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
+ PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
- BT_ERR("%s: Intel version event size mismatch", hdev->name);
+ bt_dev_err(hdev, "Intel version event size mismatch");
kfree_skb(skb);
return -EILSEQ;
}
ver = (struct intel_version *)skb->data;
if (ver->status) {
- BT_ERR("%s: Intel version command failure (%02x)",
- hdev->name, ver->status);
+ bt_dev_err(hdev, "Intel version command failure (%02x)",
+ ver->status);
err = -bt_to_errno(ver->status);
kfree_skb(skb);
return err;
@@ -359,8 +616,8 @@ static int intel_setup(struct hci_uart *hu)
* for now only accept this single value.
*/
if (ver->hw_platform != 0x37) {
- BT_ERR("%s: Unsupported Intel hardware platform (%u)",
- hdev->name, ver->hw_platform);
+ bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
+ ver->hw_platform);
kfree_skb(skb);
return -EINVAL;
}
@@ -371,8 +628,8 @@ static int intel_setup(struct hci_uart *hu)
* when newer hardware variants come along.
*/
if (ver->hw_variant != 0x0b) {
- BT_ERR("%s: Unsupported Intel hardware variant (%u)",
- hdev->name, ver->hw_variant);
+ bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
+ ver->hw_variant);
kfree_skb(skb);
return -EINVAL;
}
@@ -403,8 +660,8 @@ static int intel_setup(struct hci_uart *hu)
* choice is to return an error and abort the device initialization.
*/
if (ver->fw_variant != 0x06) {
- BT_ERR("%s: Unsupported Intel firmware variant (%u)",
- hdev->name, ver->fw_variant);
+ bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
+ ver->fw_variant);
kfree_skb(skb);
return -ENODEV;
}
@@ -416,33 +673,33 @@ static int intel_setup(struct hci_uart *hu)
*/
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
- BT_ERR("%s: Reading Intel boot parameters failed (%ld)",
- hdev->name, PTR_ERR(skb));
+ bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
+ PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*params)) {
- BT_ERR("%s: Intel boot parameters size mismatch", hdev->name);
+ bt_dev_err(hdev, "Intel boot parameters size mismatch");
kfree_skb(skb);
return -EILSEQ;
}
params = (struct intel_boot_params *)skb->data;
if (params->status) {
- BT_ERR("%s: Intel boot parameters command failure (%02x)",
- hdev->name, params->status);
+ bt_dev_err(hdev, "Intel boot parameters command failure (%02x)",
+ params->status);
err = -bt_to_errno(params->status);
kfree_skb(skb);
return err;
}
- BT_INFO("%s: Device revision is %u", hdev->name,
- le16_to_cpu(params->dev_revid));
+ bt_dev_info(hdev, "Device revision is %u",
+ le16_to_cpu(params->dev_revid));
- BT_INFO("%s: Secure boot is %s", hdev->name,
- params->secure_boot ? "enabled" : "disabled");
+ bt_dev_info(hdev, "Secure boot is %s",
+ params->secure_boot ? "enabled" : "disabled");
- BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name,
+ bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
params->min_fw_build_nn, params->min_fw_build_cw,
2000 + params->min_fw_build_yy);
@@ -451,8 +708,8 @@ static int intel_setup(struct hci_uart *hu)
* that this bootloader does not send them, then abort the setup.
*/
if (params->limited_cce != 0x00) {
- BT_ERR("%s: Unsupported Intel firmware loading method (%u)",
- hdev->name, params->limited_cce);
+ bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
+ params->limited_cce);
kfree_skb(skb);
return -EINVAL;
}
@@ -461,7 +718,7 @@ static int intel_setup(struct hci_uart *hu)
* also be no valid address for the operational firmware.
*/
if (!bacmp(&params->otp_bdaddr, BDADDR_ANY)) {
- BT_INFO("%s: No device address configured", hdev->name);
+ bt_dev_info(hdev, "No device address configured");
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
@@ -476,19 +733,23 @@ static int intel_setup(struct hci_uart *hu)
err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
- BT_ERR("%s: Failed to load Intel firmware file (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "Failed to load Intel firmware file (%d)",
+ err);
kfree_skb(skb);
return err;
}
- BT_INFO("%s: Found device firmware: %s", hdev->name, fwname);
+ bt_dev_info(hdev, "Found device firmware: %s", fwname);
+
+ /* Save the DDC file name for later */
+ snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.ddc",
+ le16_to_cpu(params->dev_revid));
kfree_skb(skb);
if (fw->size < 644) {
- BT_ERR("%s: Invalid size of firmware file (%zu)",
- hdev->name, fw->size);
+ bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
+ fw->size);
err = -EBADF;
goto done;
}
@@ -500,8 +761,7 @@ static int intel_setup(struct hci_uart *hu)
*/
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
if (err < 0) {
- BT_ERR("%s: Failed to send firmware header (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
goto done;
}
@@ -510,8 +770,8 @@ static int intel_setup(struct hci_uart *hu)
*/
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
if (err < 0) {
- BT_ERR("%s: Failed to send firmware public key (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "Failed to send firmware public key (%d)",
+ err);
goto done;
}
@@ -520,8 +780,8 @@ static int intel_setup(struct hci_uart *hu)
*/
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
if (err < 0) {
- BT_ERR("%s: Failed to send firmware signature (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "Failed to send firmware signature (%d)",
+ err);
goto done;
}
@@ -533,8 +793,8 @@ static int intel_setup(struct hci_uart *hu)
frag_len += sizeof(*cmd) + cmd->plen;
- BT_DBG("%s: patching %td/%zu", hdev->name,
- (fw_ptr - fw->data), fw->size);
+ bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data),
+ fw->size);
/* The parameter length of the secure send command requires
* a 4 byte alignment. It happens so that the firmware file
@@ -552,8 +812,8 @@ static int intel_setup(struct hci_uart *hu)
*/
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
if (err < 0) {
- BT_ERR("%s: Failed to send firmware data (%d)",
- hdev->name, err);
+ bt_dev_err(hdev, "Failed to send firmware data (%d)",
+ err);
goto done;
}
@@ -563,7 +823,7 @@ static int intel_setup(struct hci_uart *hu)
set_bit(STATE_FIRMWARE_LOADED, &intel->flags);
- BT_INFO("%s: Waiting for firmware download to complete", hdev->name);
+ bt_dev_info(hdev, "Waiting for firmware download to complete");
/* Before switching the device into operational mode and with that
* booting the loaded firmware, wait for the bootloader notification
@@ -580,19 +840,19 @@ static int intel_setup(struct hci_uart *hu)
TASK_INTERRUPTIBLE,
msecs_to_jiffies(5000));
if (err == 1) {
- BT_ERR("%s: Firmware loading interrupted", hdev->name);
+ bt_dev_err(hdev, "Firmware loading interrupted");
err = -EINTR;
goto done;
}
if (err) {
- BT_ERR("%s: Firmware loading timeout", hdev->name);
+ bt_dev_err(hdev, "Firmware loading timeout");
err = -ETIMEDOUT;
goto done;
}
if (test_bit(STATE_FIRMWARE_FAILED, &intel->flags)) {
- BT_ERR("%s: Firmware loading failed", hdev->name);
+ bt_dev_err(hdev, "Firmware loading failed");
err = -ENOEXEC;
goto done;
}
@@ -601,7 +861,7 @@ static int intel_setup(struct hci_uart *hu)
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
- BT_INFO("%s: Firmware loaded in %llu usecs", hdev->name, duration);
+ bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
done:
release_firmware(fw);
@@ -634,7 +894,7 @@ done:
* 1 second. However if that happens, then just fail the setup
* since something went wrong.
*/
- BT_INFO("%s: Waiting for device to boot", hdev->name);
+ bt_dev_info(hdev, "Waiting for device to boot");
err = intel_wait_booting(hu);
if (err)
@@ -646,7 +906,39 @@ done:
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
- BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration);
+ bt_dev_info(hdev, "Device booted in %llu usecs", duration);
+
+ /* Enable LPM if matching pdev with wakeup enabled */
+ mutex_lock(&intel_device_list_lock);
+ list_for_each(p, &intel_device_list) {
+ struct intel_device *dev = list_entry(p, struct intel_device,
+ list);
+ if (hu->tty->dev->parent == dev->pdev->dev.parent) {
+ if (device_may_wakeup(&dev->pdev->dev))
+ idev = dev;
+ break;
+ }
+ }
+ mutex_unlock(&intel_device_list_lock);
+
+ if (!idev)
+ goto no_lpm;
+
+ bt_dev_info(hdev, "Enabling LPM");
+
+ skb = __hci_cmd_sync(hdev, 0xfc8b, sizeof(lpm_param), lpm_param,
+ HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Failed to enable LPM");
+ goto no_lpm;
+ }
+ kfree_skb(skb);
+
+ set_bit(STATE_LPM_ENABLED, &intel->flags);
+
+no_lpm:
+ /* Ignore errors, device can work without DDC parameters */
+ btintel_load_ddc_config(hdev, fwname);
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb))
@@ -659,7 +951,7 @@ done:
return err;
}
- BT_INFO("%s: Setup complete", hdev->name);
+ bt_dev_info(hdev, "Setup complete");
clear_bit(STATE_BOOTLOADER, &intel->flags);
@@ -708,10 +1000,71 @@ recv:
return hci_recv_frame(hdev, skb);
}
+static void intel_recv_lpm_notify(struct hci_dev *hdev, int value)
+{
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ struct intel_data *intel = hu->priv;
+
+ bt_dev_dbg(hdev, "TX idle notification (%d)", value);
+
+ if (value) {
+ set_bit(STATE_TX_ACTIVE, &intel->flags);
+ schedule_work(&intel->busy_work);
+ } else {
+ clear_bit(STATE_TX_ACTIVE, &intel->flags);
+ }
+}
+
+static int intel_recv_lpm(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_lpm_pkt *lpm = (void *)skb->data;
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ struct intel_data *intel = hu->priv;
+
+ switch (lpm->opcode) {
+ case LPM_OP_TX_NOTIFY:
+ if (lpm->dlen < 1) {
+ bt_dev_err(hu->hdev, "Invalid LPM notification packet");
+ break;
+ }
+ intel_recv_lpm_notify(hdev, lpm->data[0]);
+ break;
+ case LPM_OP_SUSPEND_ACK:
+ set_bit(STATE_SUSPENDED, &intel->flags);
+ if (test_and_clear_bit(STATE_LPM_TRANSACTION, &intel->flags)) {
+ smp_mb__after_atomic();
+ wake_up_bit(&intel->flags, STATE_LPM_TRANSACTION);
+ }
+ break;
+ case LPM_OP_RESUME_ACK:
+ clear_bit(STATE_SUSPENDED, &intel->flags);
+ if (test_and_clear_bit(STATE_LPM_TRANSACTION, &intel->flags)) {
+ smp_mb__after_atomic();
+ wake_up_bit(&intel->flags, STATE_LPM_TRANSACTION);
+ }
+ break;
+ default:
+ bt_dev_err(hdev, "Unknown LPM opcode (%02x)", lpm->opcode);
+ break;
+ }
+
+ kfree_skb(skb);
+
+ return 0;
+}
+
+#define INTEL_RECV_LPM \
+ .type = HCI_LPM_PKT, \
+ .hlen = HCI_LPM_HDR_SIZE, \
+ .loff = 1, \
+ .lsize = 1, \
+ .maxlen = HCI_LPM_MAX_SIZE
+
static const struct h4_recv_pkt intel_recv_pkts[] = {
- { H4_RECV_ACL, .recv = hci_recv_frame },
- { H4_RECV_SCO, .recv = hci_recv_frame },
- { H4_RECV_EVENT, .recv = intel_recv_event },
+ { H4_RECV_ACL, .recv = hci_recv_frame },
+ { H4_RECV_SCO, .recv = hci_recv_frame },
+ { H4_RECV_EVENT, .recv = intel_recv_event },
+ { INTEL_RECV_LPM, .recv = intel_recv_lpm },
};
static int intel_recv(struct hci_uart *hu, const void *data, int count)
@@ -726,7 +1079,7 @@ static int intel_recv(struct hci_uart *hu, const void *data, int count)
ARRAY_SIZE(intel_recv_pkts));
if (IS_ERR(intel->rx_skb)) {
int err = PTR_ERR(intel->rx_skb);
- BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
+ bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
intel->rx_skb = NULL;
return err;
}
@@ -737,9 +1090,27 @@ static int intel_recv(struct hci_uart *hu, const void *data, int count)
static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct intel_data *intel = hu->priv;
+ struct list_head *p;
BT_DBG("hu %p skb %p", hu, skb);
+ /* Be sure our controller is resumed and potential LPM transaction
+ * completed before enqueuing any packet.
+ */
+ mutex_lock(&intel_device_list_lock);
+ list_for_each(p, &intel_device_list) {
+ struct intel_device *idev = list_entry(p, struct intel_device,
+ list);
+
+ if (hu->tty->dev->parent == idev->pdev->dev.parent) {
+ pm_runtime_get_sync(&idev->pdev->dev);
+ pm_runtime_mark_last_busy(&idev->pdev->dev);
+ pm_runtime_put_autosuspend(&idev->pdev->dev);
+ break;
+ }
+ }
+ mutex_unlock(&intel_device_list_lock);
+
skb_queue_tail(&intel->txq, skb);
return 0;
@@ -777,6 +1148,7 @@ static struct sk_buff *intel_dequeue(struct hci_uart *hu)
static const struct hci_uart_proto intel_proto = {
.id = HCI_UART_INTEL,
.name = "Intel",
+ .manufacturer = 2,
.init_speed = 115200,
.oper_speed = 3000000,
.open = intel_open,
@@ -795,24 +1167,61 @@ static const struct acpi_device_id intel_acpi_match[] = {
{ },
};
MODULE_DEVICE_TABLE(acpi, intel_acpi_match);
+#endif
-static int intel_acpi_probe(struct intel_device *idev)
+#ifdef CONFIG_PM
+static int intel_suspend_device(struct device *dev)
{
- const struct acpi_device_id *id;
+ struct intel_device *idev = dev_get_drvdata(dev);
- id = acpi_match_device(intel_acpi_match, &idev->pdev->dev);
- if (!id)
- return -ENODEV;
+ mutex_lock(&idev->hu_lock);
+ if (idev->hu)
+ intel_lpm_suspend(idev->hu);
+ mutex_unlock(&idev->hu_lock);
return 0;
}
-#else
-static int intel_acpi_probe(struct intel_device *idev)
+
+static int intel_resume_device(struct device *dev)
+{
+ struct intel_device *idev = dev_get_drvdata(dev);
+
+ mutex_lock(&idev->hu_lock);
+ if (idev->hu)
+ intel_lpm_resume(idev->hu);
+ mutex_unlock(&idev->hu_lock);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int intel_suspend(struct device *dev)
+{
+ struct intel_device *idev = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(idev->irq);
+
+ return intel_suspend_device(dev);
+}
+
+static int intel_resume(struct device *dev)
{
- return -ENODEV;
+ struct intel_device *idev = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(idev->irq);
+
+ return intel_resume_device(dev);
}
#endif
+static const struct dev_pm_ops intel_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
+ SET_RUNTIME_PM_OPS(intel_suspend_device, intel_resume_device, NULL)
+};
+
static int intel_probe(struct platform_device *pdev)
{
struct intel_device *idev;
@@ -821,15 +1230,9 @@ static int intel_probe(struct platform_device *pdev)
if (!idev)
return -ENOMEM;
- idev->pdev = pdev;
+ mutex_init(&idev->hu_lock);
- if (ACPI_HANDLE(&pdev->dev)) {
- int err = intel_acpi_probe(idev);
- if (err)
- return err;
- } else {
- return -ENODEV;
- }
+ idev->pdev = pdev;
idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset",
GPIOD_OUT_LOW);
@@ -838,14 +1241,40 @@ static int intel_probe(struct platform_device *pdev)
return PTR_ERR(idev->reset);
}
+ idev->irq = platform_get_irq(pdev, 0);
+ if (idev->irq < 0) {
+ struct gpio_desc *host_wake;
+
+ dev_err(&pdev->dev, "No IRQ, falling back to gpio-irq\n");
+
+ host_wake = devm_gpiod_get_optional(&pdev->dev, "host-wake",
+ GPIOD_IN);
+ if (IS_ERR(host_wake)) {
+ dev_err(&pdev->dev, "Unable to retrieve IRQ\n");
+ goto no_irq;
+ }
+
+ idev->irq = gpiod_to_irq(host_wake);
+ if (idev->irq < 0) {
+ dev_err(&pdev->dev, "No corresponding irq for gpio\n");
+ goto no_irq;
+ }
+ }
+
+ /* Only enable wake-up/irq when controller is powered */
+ device_set_wakeup_capable(&pdev->dev, true);
+ device_wakeup_disable(&pdev->dev);
+
+no_irq:
platform_set_drvdata(pdev, idev);
/* Place this instance on the device list */
- spin_lock(&intel_device_list_lock);
+ mutex_lock(&intel_device_list_lock);
list_add_tail(&idev->list, &intel_device_list);
- spin_unlock(&intel_device_list_lock);
+ mutex_unlock(&intel_device_list_lock);
- dev_info(&pdev->dev, "registered.\n");
+ dev_info(&pdev->dev, "registered, gpio(%d)/irq(%d).\n",
+ desc_to_gpio(idev->reset), idev->irq);
return 0;
}
@@ -854,9 +1283,11 @@ static int intel_remove(struct platform_device *pdev)
{
struct intel_device *idev = platform_get_drvdata(pdev);
- spin_lock(&intel_device_list_lock);
+ device_wakeup_disable(&pdev->dev);
+
+ mutex_lock(&intel_device_list_lock);
list_del(&idev->list);
- spin_unlock(&intel_device_list_lock);
+ mutex_unlock(&intel_device_list_lock);
dev_info(&pdev->dev, "unregistered.\n");
@@ -869,6 +1300,7 @@ static struct platform_driver intel_driver = {
.driver = {
.name = "hci_intel",
.acpi_match_table = ACPI_PTR(intel_acpi_match),
+ .pm = &intel_pm_ops,
},
};
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 0d5a05a7c1fd..96bcec5598c2 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -208,9 +208,6 @@ static int hci_uart_open(struct hci_dev *hdev)
BT_DBG("%s %p", hdev->name, hdev);
/* Nothing to do for UART driver */
-
- set_bit(HCI_RUNNING, &hdev->flags);
-
return 0;
}
@@ -241,9 +238,6 @@ static int hci_uart_close(struct hci_dev *hdev)
{
BT_DBG("hdev %p", hdev);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
hci_uart_flush(hdev);
hdev->flush = NULL;
return 0;
@@ -254,9 +248,6 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
hu->proto->enqueue(hu, skb);
@@ -470,8 +461,6 @@ static int hci_uart_tty_open(struct tty_struct *tty)
INIT_WORK(&hu->init_ready, hci_uart_init_work);
INIT_WORK(&hu->write_work, hci_uart_write_work);
- spin_lock_init(&hu->rx_lock);
-
/* Flush any pending characters in the driver and line discipline. */
/* FIXME: why is this needed. Note don't use ldisc_ref here as the
@@ -569,14 +558,14 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
return;
- spin_lock(&hu->rx_lock);
+ /* It does not need a lock here as it is already protected by a mutex in
+ * tty caller
+ */
hu->proto->recv(hu, data, count);
if (hu->hdev)
hu->hdev->stat.byte_rx += count;
- spin_unlock(&hu->rx_lock);
-
tty_unthrottle(tty);
}
@@ -598,6 +587,13 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev->bus = HCI_UART;
hci_set_drvdata(hdev, hu);
+ /* Only when vendor specific setup callback is provided, consider
+ * the manufacturer information valid. This avoids filling in the
+ * value for Ericsson when nothing is specified.
+ */
+ if (hu->proto->setup)
+ hdev->manufacturer = hu->proto->manufacturer;
+
hdev->open = hci_uart_open;
hdev->close = hci_uart_close;
hdev->flush = hci_uart_flush;
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 6b9b91267959..71325e443e46 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -41,13 +41,13 @@
#define HCI_IBS_SLEEP_IND 0xFE
#define HCI_IBS_WAKE_IND 0xFD
#define HCI_IBS_WAKE_ACK 0xFC
-#define HCI_MAX_IBS_SIZE 10
+#define HCI_MAX_IBS_SIZE 10
/* Controller states */
#define STATE_IN_BAND_SLEEP_ENABLED 1
-#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
-#define IBS_TX_IDLE_TIMEOUT_MS 2000
+#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
+#define IBS_TX_IDLE_TIMEOUT_MS 2000
#define BAUDRATE_SETTLE_TIMEOUT_MS 300
/* HCI_IBS transmit side sleep protocol states */
@@ -80,8 +80,8 @@ struct qca_data {
spinlock_t hci_ibs_lock; /* HCI_IBS state lock */
u8 tx_ibs_state; /* HCI_IBS transmit side power state*/
u8 rx_ibs_state; /* HCI_IBS receive side power state */
- u32 tx_vote; /* Clock must be on for TX */
- u32 rx_vote; /* Clock must be on for RX */
+ bool tx_vote; /* Clock must be on for TX */
+ bool rx_vote; /* Clock must be on for RX */
struct timer_list tx_idle_timer;
u32 tx_idle_delay;
struct timer_list wake_retrans_timer;
@@ -181,8 +181,8 @@ static void serial_clock_vote(unsigned long vote, struct hci_uart *hu)
else
__serial_clock_off(hu->tty);
- BT_DBG("Vote serial clock %s(%s)", new_vote? "true" : "false",
- vote? "true" : "false");
+ BT_DBG("Vote serial clock %s(%s)", new_vote ? "true" : "false",
+ vote ? "true" : "false");
diff = jiffies_to_msecs(jiffies - qca->vote_last_jif);
@@ -347,7 +347,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
struct hci_uart *hu = (struct hci_uart *)arg;
struct qca_data *qca = hu->priv;
unsigned long flags, retrans_delay;
- unsigned long retransmit = 0;
+ bool retransmit = false;
BT_DBG("hu %p wake retransmit timeout in %d state",
hu, qca->tx_ibs_state);
@@ -358,7 +358,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
switch (qca->tx_ibs_state) {
case HCI_IBS_TX_WAKING:
/* No WAKE_ACK, retransmit WAKE */
- retransmit = 1;
+ retransmit = true;
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
BT_ERR("Failed to acknowledge device wake up");
break;
@@ -821,7 +821,7 @@ static struct sk_buff *qca_dequeue(struct hci_uart *hu)
static uint8_t qca_get_baudrate_value(int speed)
{
- switch(speed) {
+ switch (speed) {
case 9600:
return QCA_BAUDRATE_9600;
case 19200:
@@ -947,6 +947,7 @@ static int qca_setup(struct hci_uart *hu)
static struct hci_uart_proto qca_proto = {
.id = HCI_UART_QCA,
.name = "QCA",
+ .manufacturer = 29,
.init_speed = 115200,
.oper_speed = 3000000,
.open = qca_open,
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 495b9ef52bb0..82c92f1b65b4 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -59,6 +59,7 @@ struct hci_uart;
struct hci_uart_proto {
unsigned int id;
const char *name;
+ unsigned int manufacturer;
unsigned int init_speed;
unsigned int oper_speed;
int (*open)(struct hci_uart *hu);
@@ -85,7 +86,6 @@ struct hci_uart {
struct sk_buff *tx_skb;
unsigned long tx_state;
- spinlock_t rx_lock;
unsigned int init_speed;
unsigned int oper_speed;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 78653db2ef2b..ed888e302bc3 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -55,8 +55,6 @@ struct vhci_data {
static int vhci_open_dev(struct hci_dev *hdev)
{
- set_bit(HCI_RUNNING, &hdev->flags);
-
return 0;
}
@@ -64,9 +62,6 @@ static int vhci_close_dev(struct hci_dev *hdev)
{
struct vhci_data *data = hci_get_drvdata(hdev);
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- return 0;
-
skb_queue_purge(&data->readq);
return 0;
@@ -85,9 +80,6 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct vhci_data *data = hci_get_drvdata(hdev);
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return -EBUSY;
-
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&data->readq, skb);
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 0ebca8ba7bc4..116b363b7987 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -120,6 +120,17 @@ config SIMPLE_PM_BUS
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
"External Bus Interface") as found on several Renesas ARM SoCs.
+config SUNXI_RSB
+ tristate "Allwinner sunXi Reduced Serial Bus Driver"
+ default MACH_SUN8I || MACH_SUN9I
+ depends on ARCH_SUNXI
+ select REGMAP
+ help
+ Say y here to enable support for Allwinner's Reduced Serial Bus
+ (RSB) support. This controller is responsible for communicating
+ with various RSB based devices, such as AXP223, AXP8XX PMICs,
+ and AC100/AC200 ICs.
+
config VEXPRESS_CONFIG
bool "Versatile Express configuration bus"
default y if ARCH_VEXPRESS
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 790e7b933fb2..fcb9f9794a1f 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -15,5 +15,6 @@ obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
+obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index 7d9879e166cf..7082c7268845 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -1184,11 +1184,12 @@ static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
break;
target = cpumask_any_but(cpu_online_mask, cpu);
- if (target < 0)
+ if (target >= nr_cpu_ids)
break;
perf_pmu_migrate_context(&dt->pmu, cpu, target);
cpumask_set_cpu(target, &dt->cpu);
- WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
+ if (ccn->irq)
+ WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
default:
break;
}
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
new file mode 100644
index 000000000000..846bc29c157d
--- /dev/null
+++ b/drivers/bus/sunxi-rsb.c
@@ -0,0 +1,783 @@
+/*
+ * RSB (Reduced Serial Bus) driver.
+ *
+ * Author: Chen-Yu Tsai <wens@csie.org>
+ *
+ * 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.
+ *
+ * The RSB controller looks like an SMBus controller which only supports
+ * byte and word data transfers. But, it differs from standard SMBus
+ * protocol on several aspects:
+ * - it uses addresses set at runtime to address slaves. Runtime addresses
+ * are sent to slaves using their 12bit hardware addresses. Up to 15
+ * runtime addresses are available.
+ * - it adds a parity bit every 8bits of data and address for read and
+ * write accesses; this replaces the ack bit
+ * - only one read access is required to read a byte (instead of a write
+ * followed by a read access in standard SMBus protocol)
+ * - there's no Ack bit after each read access
+ *
+ * This means this bus cannot be used to interface with standard SMBus
+ * devices. Devices known to support this interface include the AXP223,
+ * AXP809, and AXP806 PMICs, and the AC100 audio codec, all from X-Powers.
+ *
+ * A description of the operation and wire protocol can be found in the
+ * RSB section of Allwinner's A80 user manual, which can be found at
+ *
+ * https://github.com/allwinner-zh/documents/tree/master/A80
+ *
+ * This document is officially released by Allwinner.
+ *
+ * This driver is based on i2c-sun6i-p2wi.c, the P2WI bus driver.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk/clk-conf.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/sunxi-rsb.h>
+#include <linux/types.h>
+
+/* RSB registers */
+#define RSB_CTRL 0x0 /* Global control */
+#define RSB_CCR 0x4 /* Clock control */
+#define RSB_INTE 0x8 /* Interrupt controls */
+#define RSB_INTS 0xc /* Interrupt status */
+#define RSB_ADDR 0x10 /* Address to send with read/write command */
+#define RSB_DATA 0x1c /* Data to read/write */
+#define RSB_LCR 0x24 /* Line control */
+#define RSB_DMCR 0x28 /* Device mode (init) control */
+#define RSB_CMD 0x2c /* RSB Command */
+#define RSB_DAR 0x30 /* Device address / runtime address */
+
+/* CTRL fields */
+#define RSB_CTRL_START_TRANS BIT(7)
+#define RSB_CTRL_ABORT_TRANS BIT(6)
+#define RSB_CTRL_GLOBAL_INT_ENB BIT(1)
+#define RSB_CTRL_SOFT_RST BIT(0)
+
+/* CLK CTRL fields */
+#define RSB_CCR_SDA_OUT_DELAY(v) (((v) & 0x7) << 8)
+#define RSB_CCR_MAX_CLK_DIV 0xff
+#define RSB_CCR_CLK_DIV(v) ((v) & RSB_CCR_MAX_CLK_DIV)
+
+/* STATUS fields */
+#define RSB_INTS_TRANS_ERR_ACK BIT(16)
+#define RSB_INTS_TRANS_ERR_DATA_BIT(v) (((v) >> 8) & 0xf)
+#define RSB_INTS_TRANS_ERR_DATA GENMASK(11, 8)
+#define RSB_INTS_LOAD_BSY BIT(2)
+#define RSB_INTS_TRANS_ERR BIT(1)
+#define RSB_INTS_TRANS_OVER BIT(0)
+
+/* LINE CTRL fields*/
+#define RSB_LCR_SCL_STATE BIT(5)
+#define RSB_LCR_SDA_STATE BIT(4)
+#define RSB_LCR_SCL_CTL BIT(3)
+#define RSB_LCR_SCL_CTL_EN BIT(2)
+#define RSB_LCR_SDA_CTL BIT(1)
+#define RSB_LCR_SDA_CTL_EN BIT(0)
+
+/* DEVICE MODE CTRL field values */
+#define RSB_DMCR_DEVICE_START BIT(31)
+#define RSB_DMCR_MODE_DATA (0x7c << 16)
+#define RSB_DMCR_MODE_REG (0x3e << 8)
+#define RSB_DMCR_DEV_ADDR 0x00
+
+/* CMD values */
+#define RSB_CMD_RD8 0x8b
+#define RSB_CMD_RD16 0x9c
+#define RSB_CMD_RD32 0xa6
+#define RSB_CMD_WR8 0x4e
+#define RSB_CMD_WR16 0x59
+#define RSB_CMD_WR32 0x63
+#define RSB_CMD_STRA 0xe8
+
+/* DAR fields */
+#define RSB_DAR_RTA(v) (((v) & 0xff) << 16)
+#define RSB_DAR_DA(v) ((v) & 0xffff)
+
+#define RSB_MAX_FREQ 20000000
+
+#define RSB_CTRL_NAME "sunxi-rsb"
+
+struct sunxi_rsb_addr_map {
+ u16 hwaddr;
+ u8 rtaddr;
+};
+
+struct sunxi_rsb {
+ struct device *dev;
+ void __iomem *regs;
+ struct clk *clk;
+ struct reset_control *rstc;
+ struct completion complete;
+ struct mutex lock;
+ unsigned int status;
+};
+
+/* bus / slave device related functions */
+static struct bus_type sunxi_rsb_bus;
+
+static int sunxi_rsb_device_match(struct device *dev, struct device_driver *drv)
+{
+ return of_driver_match_device(dev, drv);
+}
+
+static int sunxi_rsb_device_probe(struct device *dev)
+{
+ const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver);
+ struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev);
+ int ret;
+
+ if (!drv->probe)
+ return -ENODEV;
+
+ if (!rdev->irq) {
+ int irq = -ENOENT;
+
+ if (dev->of_node)
+ irq = of_irq_get(dev->of_node, 0);
+
+ if (irq == -EPROBE_DEFER)
+ return irq;
+ if (irq < 0)
+ irq = 0;
+
+ rdev->irq = irq;
+ }
+
+ ret = of_clk_set_defaults(dev->of_node, false);
+ if (ret < 0)
+ return ret;
+
+ return drv->probe(rdev);
+}
+
+static int sunxi_rsb_device_remove(struct device *dev)
+{
+ const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver);
+
+ return drv->remove(to_sunxi_rsb_device(dev));
+}
+
+static struct bus_type sunxi_rsb_bus = {
+ .name = RSB_CTRL_NAME,
+ .match = sunxi_rsb_device_match,
+ .probe = sunxi_rsb_device_probe,
+ .remove = sunxi_rsb_device_remove,
+};
+
+static void sunxi_rsb_dev_release(struct device *dev)
+{
+ struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev);
+
+ kfree(rdev);
+}
+
+/**
+ * sunxi_rsb_device_create() - allocate and add an RSB device
+ * @rsb: RSB controller
+ * @node: RSB slave device node
+ * @hwaddr: RSB slave hardware address
+ * @rtaddr: RSB slave runtime address
+ */
+static struct sunxi_rsb_device *sunxi_rsb_device_create(struct sunxi_rsb *rsb,
+ struct device_node *node, u16 hwaddr, u8 rtaddr)
+{
+ int err;
+ struct sunxi_rsb_device *rdev;
+
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
+ if (!rdev)
+ return ERR_PTR(-ENOMEM);
+
+ rdev->rsb = rsb;
+ rdev->hwaddr = hwaddr;
+ rdev->rtaddr = rtaddr;
+ rdev->dev.bus = &sunxi_rsb_bus;
+ rdev->dev.parent = rsb->dev;
+ rdev->dev.of_node = node;
+ rdev->dev.release = sunxi_rsb_dev_release;
+
+ dev_set_name(&rdev->dev, "%s-%x", RSB_CTRL_NAME, hwaddr);
+
+ err = device_register(&rdev->dev);
+ if (err < 0) {
+ dev_err(&rdev->dev, "Can't add %s, status %d\n",
+ dev_name(&rdev->dev), err);
+ goto err_device_add;
+ }
+
+ dev_dbg(&rdev->dev, "device %s registered\n", dev_name(&rdev->dev));
+
+err_device_add:
+ put_device(&rdev->dev);
+
+ return ERR_PTR(err);
+}
+
+/**
+ * sunxi_rsb_device_unregister(): unregister an RSB device
+ * @rdev: rsb_device to be removed
+ */
+static void sunxi_rsb_device_unregister(struct sunxi_rsb_device *rdev)
+{
+ device_unregister(&rdev->dev);
+}
+
+static int sunxi_rsb_remove_devices(struct device *dev, void *data)
+{
+ struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev);
+
+ if (dev->bus == &sunxi_rsb_bus)
+ sunxi_rsb_device_unregister(rdev);
+
+ return 0;
+}
+
+/**
+ * sunxi_rsb_driver_register() - Register device driver with RSB core
+ * @rdrv: device driver to be associated with slave-device.
+ *
+ * This API will register the client driver with the RSB framework.
+ * It is typically called from the driver's module-init function.
+ */
+int sunxi_rsb_driver_register(struct sunxi_rsb_driver *rdrv)
+{
+ rdrv->driver.bus = &sunxi_rsb_bus;
+ return driver_register(&rdrv->driver);
+}
+EXPORT_SYMBOL_GPL(sunxi_rsb_driver_register);
+
+/* common code that starts a transfer */
+static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)
+{
+ if (readl(rsb->regs + RSB_CTRL) & RSB_CTRL_START_TRANS) {
+ dev_dbg(rsb->dev, "RSB transfer still in progress\n");
+ return -EBUSY;
+ }
+
+ reinit_completion(&rsb->complete);
+
+ writel(RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER,
+ rsb->regs + RSB_INTE);
+ writel(RSB_CTRL_START_TRANS | RSB_CTRL_GLOBAL_INT_ENB,
+ rsb->regs + RSB_CTRL);
+
+ if (!wait_for_completion_io_timeout(&rsb->complete,
+ msecs_to_jiffies(100))) {
+ dev_dbg(rsb->dev, "RSB timeout\n");
+
+ /* abort the transfer */
+ writel(RSB_CTRL_ABORT_TRANS, rsb->regs + RSB_CTRL);
+
+ /* clear any interrupt flags */
+ writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS);
+
+ return -ETIMEDOUT;
+ }
+
+ if (rsb->status & RSB_INTS_LOAD_BSY) {
+ dev_dbg(rsb->dev, "RSB busy\n");
+ return -EBUSY;
+ }
+
+ if (rsb->status & RSB_INTS_TRANS_ERR) {
+ if (rsb->status & RSB_INTS_TRANS_ERR_ACK) {
+ dev_dbg(rsb->dev, "RSB slave nack\n");
+ return -EINVAL;
+ }
+
+ if (rsb->status & RSB_INTS_TRANS_ERR_DATA) {
+ dev_dbg(rsb->dev, "RSB transfer data error\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
+ u32 *buf, size_t len)
+{
+ u32 cmd;
+ int ret;
+
+ if (!buf)
+ return -EINVAL;
+
+ switch (len) {
+ case 1:
+ cmd = RSB_CMD_RD8;
+ break;
+ case 2:
+ cmd = RSB_CMD_RD16;
+ break;
+ case 4:
+ cmd = RSB_CMD_RD32;
+ break;
+ default:
+ dev_err(rsb->dev, "Invalid access width: %d\n", len);
+ return -EINVAL;
+ }
+
+ mutex_lock(&rsb->lock);
+
+ writel(addr, rsb->regs + RSB_ADDR);
+ writel(RSB_DAR_RTA(rtaddr), rsb->regs + RSB_DAR);
+ writel(cmd, rsb->regs + RSB_CMD);
+
+ ret = _sunxi_rsb_run_xfer(rsb);
+ if (ret)
+ goto out;
+
+ *buf = readl(rsb->regs + RSB_DATA);
+
+ mutex_unlock(&rsb->lock);
+
+out:
+ return ret;
+}
+
+static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
+ const u32 *buf, size_t len)
+{
+ u32 cmd;
+ int ret;
+
+ if (!buf)
+ return -EINVAL;
+
+ switch (len) {
+ case 1:
+ cmd = RSB_CMD_WR8;
+ break;
+ case 2:
+ cmd = RSB_CMD_WR16;
+ break;
+ case 4:
+ cmd = RSB_CMD_WR32;
+ break;
+ default:
+ dev_err(rsb->dev, "Invalid access width: %d\n", len);
+ return -EINVAL;
+ }
+
+ mutex_lock(&rsb->lock);
+
+ writel(addr, rsb->regs + RSB_ADDR);
+ writel(RSB_DAR_RTA(rtaddr), rsb->regs + RSB_DAR);
+ writel(*buf, rsb->regs + RSB_DATA);
+ writel(cmd, rsb->regs + RSB_CMD);
+ ret = _sunxi_rsb_run_xfer(rsb);
+
+ mutex_unlock(&rsb->lock);
+
+ return ret;
+}
+
+/* RSB regmap functions */
+struct sunxi_rsb_ctx {
+ struct sunxi_rsb_device *rdev;
+ int size;
+};
+
+static int regmap_sunxi_rsb_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ struct sunxi_rsb_ctx *ctx = context;
+ struct sunxi_rsb_device *rdev = ctx->rdev;
+
+ if (reg > 0xff)
+ return -EINVAL;
+
+ return sunxi_rsb_read(rdev->rsb, rdev->rtaddr, reg, val, ctx->size);
+}
+
+static int regmap_sunxi_rsb_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ struct sunxi_rsb_ctx *ctx = context;
+ struct sunxi_rsb_device *rdev = ctx->rdev;
+
+ return sunxi_rsb_write(rdev->rsb, rdev->rtaddr, reg, &val, ctx->size);
+}
+
+static void regmap_sunxi_rsb_free_ctx(void *context)
+{
+ struct sunxi_rsb_ctx *ctx = context;
+
+ kfree(ctx);
+}
+
+static struct regmap_bus regmap_sunxi_rsb = {
+ .reg_write = regmap_sunxi_rsb_reg_write,
+ .reg_read = regmap_sunxi_rsb_reg_read,
+ .free_context = regmap_sunxi_rsb_free_ctx,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static struct sunxi_rsb_ctx *regmap_sunxi_rsb_init_ctx(struct sunxi_rsb_device *rdev,
+ const struct regmap_config *config)
+{
+ struct sunxi_rsb_ctx *ctx;
+
+ switch (config->val_bits) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ ctx->rdev = rdev;
+ ctx->size = config->val_bits / 8;
+
+ return ctx;
+}
+
+struct regmap *__devm_regmap_init_sunxi_rsb(struct sunxi_rsb_device *rdev,
+ const struct regmap_config *config,
+ struct lock_class_key *lock_key,
+ const char *lock_name)
+{
+ struct sunxi_rsb_ctx *ctx = regmap_sunxi_rsb_init_ctx(rdev, config);
+
+ if (IS_ERR(ctx))
+ return ERR_CAST(ctx);
+
+ return __devm_regmap_init(&rdev->dev, &regmap_sunxi_rsb, ctx, config,
+ lock_key, lock_name);
+}
+EXPORT_SYMBOL_GPL(__devm_regmap_init_sunxi_rsb);
+
+/* RSB controller driver functions */
+static irqreturn_t sunxi_rsb_irq(int irq, void *dev_id)
+{
+ struct sunxi_rsb *rsb = dev_id;
+ u32 status;
+
+ status = readl(rsb->regs + RSB_INTS);
+ rsb->status = status;
+
+ /* Clear interrupts */
+ status &= (RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR |
+ RSB_INTS_TRANS_OVER);
+ writel(status, rsb->regs + RSB_INTS);
+
+ complete(&rsb->complete);
+
+ return IRQ_HANDLED;
+}
+
+static int sunxi_rsb_init_device_mode(struct sunxi_rsb *rsb)
+{
+ int ret = 0;
+ u32 reg;
+
+ /* send init sequence */
+ writel(RSB_DMCR_DEVICE_START | RSB_DMCR_MODE_DATA |
+ RSB_DMCR_MODE_REG | RSB_DMCR_DEV_ADDR, rsb->regs + RSB_DMCR);
+
+ readl_poll_timeout(rsb->regs + RSB_DMCR, reg,
+ !(reg & RSB_DMCR_DEVICE_START), 100, 250000);
+ if (reg & RSB_DMCR_DEVICE_START)
+ ret = -ETIMEDOUT;
+
+ /* clear interrupt status bits */
+ writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS);
+
+ return ret;
+}
+
+/*
+ * There are 15 valid runtime addresses, though Allwinner typically
+ * skips the first, for unknown reasons, and uses the following three.
+ *
+ * 0x17, 0x2d, 0x3a, 0x4e, 0x59, 0x63, 0x74, 0x8b,
+ * 0x9c, 0xa6, 0xb1, 0xc5, 0xd2, 0xe8, 0xff
+ *
+ * No designs with 2 RSB slave devices sharing identical hardware
+ * addresses on the same bus have been seen in the wild. All designs
+ * use 0x2d for the primary PMIC, 0x3a for the secondary PMIC if
+ * there is one, and 0x45 for peripheral ICs.
+ *
+ * The hardware does not seem to support re-setting runtime addresses.
+ * Attempts to do so result in the slave devices returning a NACK.
+ * Hence we just hardcode the mapping here, like Allwinner does.
+ */
+
+static const struct sunxi_rsb_addr_map sunxi_rsb_addr_maps[] = {
+ { 0x3e3, 0x2d }, /* Primary PMIC: AXP223, AXP809, AXP81X, ... */
+ { 0x745, 0x3a }, /* Secondary PMIC: AXP806, ... */
+ { 0xe89, 0x45 }, /* Peripheral IC: AC100, ... */
+};
+
+static u8 sunxi_rsb_get_rtaddr(u16 hwaddr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sunxi_rsb_addr_maps); i++)
+ if (hwaddr == sunxi_rsb_addr_maps[i].hwaddr)
+ return sunxi_rsb_addr_maps[i].rtaddr;
+
+ return 0; /* 0 is an invalid runtime address */
+}
+
+static int of_rsb_register_devices(struct sunxi_rsb *rsb)
+{
+ struct device *dev = rsb->dev;
+ struct device_node *child, *np = dev->of_node;
+ u32 hwaddr;
+ u8 rtaddr;
+ int ret;
+
+ if (!np)
+ return -EINVAL;
+
+ /* Runtime addresses for all slaves should be set first */
+ for_each_available_child_of_node(np, child) {
+ dev_dbg(dev, "setting child %s runtime address\n",
+ child->full_name);
+
+ ret = of_property_read_u32(child, "reg", &hwaddr);
+ if (ret) {
+ dev_err(dev, "%s: invalid 'reg' property: %d\n",
+ child->full_name, ret);
+ continue;
+ }
+
+ rtaddr = sunxi_rsb_get_rtaddr(hwaddr);
+ if (!rtaddr) {
+ dev_err(dev, "%s: unknown hardware device address\n",
+ child->full_name);
+ continue;
+ }
+
+ /*
+ * Since no devices have been registered yet, we are the
+ * only ones using the bus, we can skip locking the bus.
+ */
+
+ /* setup command parameters */
+ writel(RSB_CMD_STRA, rsb->regs + RSB_CMD);
+ writel(RSB_DAR_RTA(rtaddr) | RSB_DAR_DA(hwaddr),
+ rsb->regs + RSB_DAR);
+
+ /* send command */
+ ret = _sunxi_rsb_run_xfer(rsb);
+ if (ret)
+ dev_warn(dev, "%s: set runtime address failed: %d\n",
+ child->full_name, ret);
+ }
+
+ /* Then we start adding devices and probing them */
+ for_each_available_child_of_node(np, child) {
+ struct sunxi_rsb_device *rdev;
+
+ dev_dbg(dev, "adding child %s\n", child->full_name);
+
+ ret = of_property_read_u32(child, "reg", &hwaddr);
+ if (ret)
+ continue;
+
+ rtaddr = sunxi_rsb_get_rtaddr(hwaddr);
+ if (!rtaddr)
+ continue;
+
+ rdev = sunxi_rsb_device_create(rsb, child, hwaddr, rtaddr);
+ if (IS_ERR(rdev))
+ dev_err(dev, "failed to add child device %s: %ld\n",
+ child->full_name, PTR_ERR(rdev));
+ }
+
+ return 0;
+}
+
+static const struct of_device_id sunxi_rsb_of_match_table[] = {
+ { .compatible = "allwinner,sun8i-a23-rsb" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table);
+
+static int sunxi_rsb_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct resource *r;
+ struct sunxi_rsb *rsb;
+ unsigned long p_clk_freq;
+ u32 clk_delay, clk_freq = 3000000;
+ int clk_div, irq, ret;
+ u32 reg;
+
+ of_property_read_u32(np, "clock-frequency", &clk_freq);
+ if (clk_freq > RSB_MAX_FREQ) {
+ dev_err(dev,
+ "clock-frequency (%u Hz) is too high (max = 20MHz)\n",
+ clk_freq);
+ return -EINVAL;
+ }
+
+ rsb = devm_kzalloc(dev, sizeof(*rsb), GFP_KERNEL);
+ if (!rsb)
+ return -ENOMEM;
+
+ rsb->dev = dev;
+ platform_set_drvdata(pdev, rsb);
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rsb->regs = devm_ioremap_resource(dev, r);
+ if (IS_ERR(rsb->regs))
+ return PTR_ERR(rsb->regs);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "failed to retrieve irq: %d\n", irq);
+ return irq;
+ }
+
+ rsb->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(rsb->clk)) {
+ ret = PTR_ERR(rsb->clk);
+ dev_err(dev, "failed to retrieve clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(rsb->clk);
+ if (ret) {
+ dev_err(dev, "failed to enable clk: %d\n", ret);
+ return ret;
+ }
+
+ p_clk_freq = clk_get_rate(rsb->clk);
+
+ rsb->rstc = devm_reset_control_get(dev, NULL);
+ if (IS_ERR(rsb->rstc)) {
+ ret = PTR_ERR(rsb->rstc);
+ dev_err(dev, "failed to retrieve reset controller: %d\n", ret);
+ goto err_clk_disable;
+ }
+
+ ret = reset_control_deassert(rsb->rstc);
+ if (ret) {
+ dev_err(dev, "failed to deassert reset line: %d\n", ret);
+ goto err_clk_disable;
+ }
+
+ init_completion(&rsb->complete);
+ mutex_init(&rsb->lock);
+
+ /* reset the controller */
+ writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL);
+ readl_poll_timeout(rsb->regs + RSB_CTRL, reg,
+ !(reg & RSB_CTRL_SOFT_RST), 1000, 100000);
+
+ /*
+ * Clock frequency and delay calculation code is from
+ * Allwinner U-boot sources.
+ *
+ * From A83 user manual:
+ * bus clock frequency = parent clock frequency / (2 * (divider + 1))
+ */
+ clk_div = p_clk_freq / clk_freq / 2;
+ if (!clk_div)
+ clk_div = 1;
+ else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1)
+ clk_div = RSB_CCR_MAX_CLK_DIV + 1;
+
+ clk_delay = clk_div >> 1;
+ if (!clk_delay)
+ clk_delay = 1;
+
+ dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2);
+ writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1),
+ rsb->regs + RSB_CCR);
+
+ ret = devm_request_irq(dev, irq, sunxi_rsb_irq, 0, RSB_CTRL_NAME, rsb);
+ if (ret) {
+ dev_err(dev, "can't register interrupt handler irq %d: %d\n",
+ irq, ret);
+ goto err_reset_assert;
+ }
+
+ /* initialize all devices on the bus into RSB mode */
+ ret = sunxi_rsb_init_device_mode(rsb);
+ if (ret)
+ dev_warn(dev, "Initialize device mode failed: %d\n", ret);
+
+ of_rsb_register_devices(rsb);
+
+ return 0;
+
+err_reset_assert:
+ reset_control_assert(rsb->rstc);
+
+err_clk_disable:
+ clk_disable_unprepare(rsb->clk);
+
+ return ret;
+}
+
+static int sunxi_rsb_remove(struct platform_device *pdev)
+{
+ struct sunxi_rsb *rsb = platform_get_drvdata(pdev);
+
+ device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices);
+ reset_control_assert(rsb->rstc);
+ clk_disable_unprepare(rsb->clk);
+
+ return 0;
+}
+
+static struct platform_driver sunxi_rsb_driver = {
+ .probe = sunxi_rsb_probe,
+ .remove = sunxi_rsb_remove,
+ .driver = {
+ .name = RSB_CTRL_NAME,
+ .of_match_table = sunxi_rsb_of_match_table,
+ },
+};
+
+static int __init sunxi_rsb_init(void)
+{
+ int ret;
+
+ ret = bus_register(&sunxi_rsb_bus);
+ if (ret) {
+ pr_err("failed to register sunxi sunxi_rsb bus: %d\n", ret);
+ return ret;
+ }
+
+ return platform_driver_register(&sunxi_rsb_driver);
+}
+module_init(sunxi_rsb_init);
+
+static void __exit sunxi_rsb_exit(void)
+{
+ platform_driver_unregister(&sunxi_rsb_driver);
+ bus_unregister(&sunxi_rsb_bus);
+}
+module_exit(sunxi_rsb_exit);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_DESCRIPTION("Allwinner sunXi Reduced Serial Bus controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 5d28a45d2960..c206ccda899b 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -885,6 +885,7 @@ static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
switch (cdi->mmc3_profile) {
case 0x12: /* DVD-RAM */
case 0x1A: /* DVD+RW */
+ case 0x43: /* BD-RE */
return 0;
default:
return 1;
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a56ee9bedd11..05755441250c 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -361,6 +361,10 @@ static int agp_uninorth_resume(struct pci_dev *pdev)
}
#endif /* CONFIG_PM */
+static struct {
+ struct page **pages_arr;
+} uninorth_priv;
+
static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
{
char *table;
@@ -371,7 +375,6 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
int i;
void *temp;
struct page *page;
- struct page **pages;
/* We can't handle 2 level gatt's */
if (bridge->driver->size_type == LVL2_APER_SIZE)
@@ -400,8 +403,8 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
if (table == NULL)
return -ENOMEM;
- pages = kmalloc((1 << page_order) * sizeof(struct page*), GFP_KERNEL);
- if (pages == NULL)
+ uninorth_priv.pages_arr = kmalloc((1 << page_order) * sizeof(struct page*), GFP_KERNEL);
+ if (uninorth_priv.pages_arr == NULL)
goto enomem;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
@@ -409,14 +412,14 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table), i = 0; page <= virt_to_page(table_end);
page++, i++) {
SetPageReserved(page);
- pages[i] = page;
+ uninorth_priv.pages_arr[i] = page;
}
bridge->gatt_table_real = (u32 *) table;
/* Need to clear out any dirty data still sitting in caches */
flush_dcache_range((unsigned long)table,
(unsigned long)table_end + 1);
- bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG);
+ bridge->gatt_table = vmap(uninorth_priv.pages_arr, (1 << page_order), 0, PAGE_KERNEL_NCG);
if (bridge->gatt_table == NULL)
goto enomem;
@@ -434,7 +437,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
return 0;
enomem:
- kfree(pages);
+ kfree(uninorth_priv.pages_arr);
if (table)
free_pages((unsigned long)table, page_order);
return -ENOMEM;
@@ -456,6 +459,7 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
*/
vunmap(bridge->gatt_table);
+ kfree(uninorth_priv.pages_arr);
table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
index e39e7402e623..dc62568b7dde 100644
--- a/drivers/char/efirtc.c
+++ b/drivers/char/efirtc.c
@@ -30,7 +30,6 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/rtc.h>
#include <linux/proc_fs.h>
@@ -395,14 +394,8 @@ efi_rtc_init(void)
}
return 0;
}
+device_initcall(efi_rtc_init);
-static void __exit
-efi_rtc_exit(void)
-{
- /* not yet used */
-}
-
-module_init(efi_rtc_init);
-module_exit(efi_rtc_exit);
-
+/*
MODULE_LICENSE("GPL");
+*/
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5c0baa9ffc64..240b6cf1d97c 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -12,7 +12,6 @@
*/
#include <linux/interrupt.h>
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
@@ -1043,24 +1042,16 @@ static int hpet_acpi_add(struct acpi_device *device)
return hpet_alloc(&data);
}
-static int hpet_acpi_remove(struct acpi_device *device)
-{
- /* XXX need to unregister clocksource, dealloc mem, etc */
- return -EINVAL;
-}
-
static const struct acpi_device_id hpet_device_ids[] = {
{"PNP0103", 0},
{"", 0},
};
-MODULE_DEVICE_TABLE(acpi, hpet_device_ids);
static struct acpi_driver hpet_acpi_driver = {
.name = "hpet",
.ids = hpet_device_ids,
.ops = {
.add = hpet_acpi_add,
- .remove = hpet_acpi_remove,
},
};
@@ -1086,19 +1077,9 @@ static int __init hpet_init(void)
return 0;
}
+device_initcall(hpet_init);
-static void __exit hpet_exit(void)
-{
- acpi_bus_unregister_driver(&hpet_acpi_driver);
-
- if (sysctl_header)
- unregister_sysctl_table(sysctl_header);
- misc_deregister(&hpet_misc);
-
- return;
-}
-
-module_init(hpet_init);
-module_exit(hpet_exit);
+/*
MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>");
MODULE_LICENSE("GPL");
+*/
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index f48cf11c655e..dbf22719462f 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -10,7 +10,7 @@ menuconfig HW_RANDOM
To compile this driver as a module, choose M here: the
module will be called rng-core. This provides a device
- that's usually called /dev/hw_random, and which exposes one
+ that's usually called /dev/hwrng, and which exposes one
of possibly several hardware random number generators.
These hardware random number generators do not feed directly
@@ -346,6 +346,16 @@ config HW_RANDOM_MSM
If unsure, say Y.
+config HW_RANDOM_ST
+ tristate "ST Microelectronics HW Random Number Generator support"
+ depends on HW_RANDOM && ARCH_STI
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on STi series of SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called st-rng.
+
config HW_RANDOM_XGENE
tristate "APM X-Gene True Random Number Generator (TRNG) support"
depends on HW_RANDOM && ARCH_XGENE
@@ -359,6 +369,18 @@ config HW_RANDOM_XGENE
If unsure, say Y.
+config HW_RANDOM_STM32
+ tristate "STMicroelectronics STM32 random number generator"
+ depends on HW_RANDOM && (ARCH_STM32 || COMPILE_TEST)
+ help
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on STM32 microcontrollers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stm32-rng.
+
+ If unsure, say N.
+
endif # HW_RANDOM
config UML_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 055bb01510ad..5ad397635128 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -30,4 +30,6 @@ obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o
+obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
+obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 5643b65cee20..6f497aa1b276 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -323,7 +323,7 @@ static ssize_t hwrng_attr_current_store(struct device *dev,
return -ERESTARTSYS;
err = -ENODEV;
list_for_each_entry(rng, &rng_list, list) {
- if (strcmp(rng->name, buf) == 0) {
+ if (sysfs_streq(rng->name, buf)) {
err = 0;
if (rng != current_rng)
err = set_current_rng(rng);
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index dc4701fd814f..30cf4623184f 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -53,15 +53,11 @@ static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset)
__raw_writel(val, rng->mem + offset);
}
-static int exynos_init(struct hwrng *rng)
+static int exynos_rng_configure(struct exynos_rng *exynos_rng)
{
- struct exynos_rng *exynos_rng = container_of(rng,
- struct exynos_rng, rng);
int i;
int ret = 0;
- pm_runtime_get_sync(exynos_rng->dev);
-
for (i = 0 ; i < 5 ; i++)
exynos_rng_writel(exynos_rng, jiffies,
EXYNOS_PRNG_SEED_OFFSET + 4*i);
@@ -70,6 +66,17 @@ static int exynos_init(struct hwrng *rng)
& SEED_SETTING_DONE))
ret = -EIO;
+ return ret;
+}
+
+static int exynos_init(struct hwrng *rng)
+{
+ struct exynos_rng *exynos_rng = container_of(rng,
+ struct exynos_rng, rng);
+ int ret = 0;
+
+ pm_runtime_get_sync(exynos_rng->dev);
+ ret = exynos_rng_configure(exynos_rng);
pm_runtime_put_noidle(exynos_rng->dev);
return ret;
@@ -81,21 +88,24 @@ static int exynos_read(struct hwrng *rng, void *buf,
struct exynos_rng *exynos_rng = container_of(rng,
struct exynos_rng, rng);
u32 *data = buf;
+ int retry = 100;
pm_runtime_get_sync(exynos_rng->dev);
exynos_rng_writel(exynos_rng, PRNG_START, 0);
while (!(exynos_rng_readl(exynos_rng,
- EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE))
+ EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry)
cpu_relax();
+ if (!retry)
+ return -ETIMEDOUT;
exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
*data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
pm_runtime_mark_last_busy(exynos_rng->dev);
- pm_runtime_autosuspend(exynos_rng->dev);
+ pm_runtime_put_sync_autosuspend(exynos_rng->dev);
return 4;
}
@@ -152,15 +162,45 @@ static int exynos_rng_runtime_resume(struct device *dev)
return clk_prepare_enable(exynos_rng->clk);
}
+
+static int exynos_rng_suspend(struct device *dev)
+{
+ return pm_runtime_force_suspend(dev);
+}
+
+static int exynos_rng_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ return exynos_rng_configure(exynos_rng);
+}
#endif
-static UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend,
- exynos_rng_runtime_resume, NULL);
+static const struct dev_pm_ops exynos_rng_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(exynos_rng_suspend, exynos_rng_resume)
+ SET_RUNTIME_PM_OPS(exynos_rng_runtime_suspend,
+ exynos_rng_runtime_resume, NULL)
+};
+
+static const struct of_device_id exynos_rng_dt_match[] = {
+ {
+ .compatible = "samsung,exynos4-rng",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, exynos_rng_dt_match);
static struct platform_driver exynos_rng_driver = {
.driver = {
.name = "exynos-rng",
.pm = &exynos_rng_pm_ops,
+ .of_match_table = exynos_rng_dt_match,
},
.probe = exynos_rng_probe,
};
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index 6cbb72ec6013..467362262651 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -141,12 +141,11 @@ static void mxc_rnga_cleanup(struct hwrng *rng)
static int __init mxc_rnga_probe(struct platform_device *pdev)
{
- int err = -ENODEV;
+ int err;
struct resource *res;
struct mxc_rng *mxc_rng;
- mxc_rng = devm_kzalloc(&pdev->dev, sizeof(struct mxc_rng),
- GFP_KERNEL);
+ mxc_rng = devm_kzalloc(&pdev->dev, sizeof(*mxc_rng), GFP_KERNEL);
if (!mxc_rng)
return -ENOMEM;
@@ -160,13 +159,12 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
mxc_rng->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(mxc_rng->clk)) {
dev_err(&pdev->dev, "Could not get rng_clk!\n");
- err = PTR_ERR(mxc_rng->clk);
- goto out;
+ return PTR_ERR(mxc_rng->clk);
}
err = clk_prepare_enable(mxc_rng->clk);
if (err)
- goto out;
+ return err;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mxc_rng->mem = devm_ioremap_resource(&pdev->dev, res);
@@ -181,14 +179,10 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
goto err_ioremap;
}
- dev_info(&pdev->dev, "MXC RNGA Registered.\n");
-
return 0;
err_ioremap:
clk_disable_unprepare(mxc_rng->clk);
-
-out:
return err;
}
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index 6234a4a19b56..8c78aa090492 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -96,7 +96,7 @@ static int octeon_rng_probe(struct platform_device *pdev)
rng->ops = ops;
platform_set_drvdata(pdev, &rng->ops);
- ret = hwrng_register(&rng->ops);
+ ret = devm_hwrng_register(&pdev->dev, &rng->ops);
if (ret)
return -ENOENT;
@@ -105,21 +105,11 @@ static int octeon_rng_probe(struct platform_device *pdev)
return 0;
}
-static int octeon_rng_remove(struct platform_device *pdev)
-{
- struct hwrng *rng = platform_get_drvdata(pdev);
-
- hwrng_unregister(rng);
-
- return 0;
-}
-
static struct platform_driver octeon_rng_driver = {
.driver = {
.name = "octeon_rng",
},
.probe = octeon_rng_probe,
- .remove = octeon_rng_remove,
};
module_platform_driver(octeon_rng_driver);
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index 51cb1d5cc489..699b7259f5d7 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -138,6 +138,7 @@ static const struct of_device_id rng_match[] = {
{ .compatible = "pasemi,pwrficient-rng", },
{ },
};
+MODULE_DEVICE_TABLE(of, rng_match);
static struct platform_driver rng_driver = {
.driver = {
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index b2cfda0fa93e..c0db4387d2e2 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -129,6 +129,7 @@ static const struct of_device_id ppc4xx_rng_match[] = {
{ .compatible = "amcc,ppc440epx-rng", },
{},
};
+MODULE_DEVICE_TABLE(of, ppc4xx_rng_match);
static struct platform_driver ppc4xx_rng_driver = {
.driver = {
diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c
new file mode 100644
index 000000000000..1d35363d23c5
--- /dev/null
+++ b/drivers/char/hw_random/st-rng.c
@@ -0,0 +1,151 @@
+/*
+ * ST Random Number Generator Driver ST's Platforms
+ *
+ * Author: Pankaj Dev: <pankaj.dev@st.com>
+ * Lee Jones <lee.jones@linaro.org>
+ *
+ * Copyright (C) 2015 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* Registers */
+#define ST_RNG_STATUS_REG 0x20
+#define ST_RNG_DATA_REG 0x24
+
+/* Registers fields */
+#define ST_RNG_STATUS_BAD_SEQUENCE BIT(0)
+#define ST_RNG_STATUS_BAD_ALTERNANCE BIT(1)
+#define ST_RNG_STATUS_FIFO_FULL BIT(5)
+
+#define ST_RNG_SAMPLE_SIZE 2 /* 2 Byte (16bit) samples */
+#define ST_RNG_FIFO_DEPTH 4
+#define ST_RNG_FIFO_SIZE (ST_RNG_FIFO_DEPTH * ST_RNG_SAMPLE_SIZE)
+
+/*
+ * Samples are documented to be available every 0.667us, so in theory
+ * the 4 sample deep FIFO should take 2.668us to fill. However, during
+ * thorough testing, it became apparent that filling the FIFO actually
+ * takes closer to 12us. We then multiply by 2 in order to account for
+ * the lack of udelay()'s reliability, suggested by Russell King.
+ */
+#define ST_RNG_FILL_FIFO_TIMEOUT (12 * 2)
+
+struct st_rng_data {
+ void __iomem *base;
+ struct clk *clk;
+ struct hwrng ops;
+};
+
+static int st_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ struct st_rng_data *ddata = (struct st_rng_data *)rng->priv;
+ u32 status;
+ int i;
+
+ if (max < sizeof(u16))
+ return -EINVAL;
+
+ /* Wait until FIFO is full - max 4uS*/
+ for (i = 0; i < ST_RNG_FILL_FIFO_TIMEOUT; i++) {
+ status = readl_relaxed(ddata->base + ST_RNG_STATUS_REG);
+ if (status & ST_RNG_STATUS_FIFO_FULL)
+ break;
+ udelay(1);
+ }
+
+ if (i == ST_RNG_FILL_FIFO_TIMEOUT)
+ return 0;
+
+ for (i = 0; i < ST_RNG_FIFO_SIZE && i < max; i += 2)
+ *(u16 *)(data + i) =
+ readl_relaxed(ddata->base + ST_RNG_DATA_REG);
+
+ return i; /* No of bytes read */
+}
+
+static int st_rng_probe(struct platform_device *pdev)
+{
+ struct st_rng_data *ddata;
+ struct resource *res;
+ struct clk *clk;
+ void __iomem *base;
+ int ret;
+
+ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ 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);
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+
+ ddata->ops.priv = (unsigned long)ddata;
+ ddata->ops.read = st_rng_read;
+ ddata->ops.name = pdev->name;
+ ddata->base = base;
+ ddata->clk = clk;
+
+ dev_set_drvdata(&pdev->dev, ddata);
+
+ ret = hwrng_register(&ddata->ops);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register HW RNG\n");
+ return ret;
+ }
+
+ dev_info(&pdev->dev, "Successfully registered HW RNG\n");
+
+ return 0;
+}
+
+static int st_rng_remove(struct platform_device *pdev)
+{
+ struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev);
+
+ hwrng_unregister(&ddata->ops);
+
+ clk_disable_unprepare(ddata->clk);
+
+ return 0;
+}
+
+static const struct of_device_id st_rng_match[] = {
+ { .compatible = "st,rng" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_rng_match);
+
+static struct platform_driver st_rng_driver = {
+ .driver = {
+ .name = "st-hwrandom",
+ .of_match_table = of_match_ptr(st_rng_match),
+ },
+ .probe = st_rng_probe,
+ .remove = st_rng_remove
+};
+
+module_platform_driver(st_rng_driver);
+
+MODULE_AUTHOR("Pankaj Dev <pankaj.dev@st.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
new file mode 100644
index 000000000000..92a810648bd0
--- /dev/null
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2015, Daniel Thompson
+ *
+ * This file 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 file is distributed in the hope that it will be useful,
+ * but WITHOUT 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/clk.h>
+#include <linux/delay.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#define RNG_CR 0x00
+#define RNG_CR_RNGEN BIT(2)
+
+#define RNG_SR 0x04
+#define RNG_SR_SEIS BIT(6)
+#define RNG_SR_CEIS BIT(5)
+#define RNG_SR_DRDY BIT(0)
+
+#define RNG_DR 0x08
+
+/*
+ * It takes 40 cycles @ 48MHz to generate each random number (e.g. <1us).
+ * At the time of writing STM32 parts max out at ~200MHz meaning a timeout
+ * of 500 leaves us a very comfortable margin for error. The loop to which
+ * the timeout applies takes at least 4 instructions per iteration so the
+ * timeout is enough to take us up to multi-GHz parts!
+ */
+#define RNG_TIMEOUT 500
+
+struct stm32_rng_private {
+ struct hwrng rng;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ struct stm32_rng_private *priv =
+ container_of(rng, struct stm32_rng_private, rng);
+ u32 sr;
+ int retval = 0;
+
+ pm_runtime_get_sync((struct device *) priv->rng.priv);
+
+ while (max > sizeof(u32)) {
+ sr = readl_relaxed(priv->base + RNG_SR);
+ if (!sr && wait) {
+ unsigned int timeout = RNG_TIMEOUT;
+
+ do {
+ cpu_relax();
+ sr = readl_relaxed(priv->base + RNG_SR);
+ } while (!sr && --timeout);
+ }
+
+ /* If error detected or data not ready... */
+ if (sr != RNG_SR_DRDY)
+ break;
+
+ *(u32 *)data = readl_relaxed(priv->base + RNG_DR);
+
+ retval += sizeof(u32);
+ data += sizeof(u32);
+ max -= sizeof(u32);
+ }
+
+ if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
+ "bad RNG status - %x\n", sr))
+ writel_relaxed(0, priv->base + RNG_SR);
+
+ pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
+ pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
+
+ return retval || !wait ? retval : -EIO;
+}
+
+static int stm32_rng_init(struct hwrng *rng)
+{
+ struct stm32_rng_private *priv =
+ container_of(rng, struct stm32_rng_private, rng);
+ int err;
+
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ return err;
+
+ writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR);
+
+ /* clear error indicators */
+ writel_relaxed(0, priv->base + RNG_SR);
+
+ return 0;
+}
+
+static void stm32_rng_cleanup(struct hwrng *rng)
+{
+ struct stm32_rng_private *priv =
+ container_of(rng, struct stm32_rng_private, rng);
+
+ writel_relaxed(0, priv->base + RNG_CR);
+ clk_disable_unprepare(priv->clk);
+}
+
+static int stm32_rng_probe(struct platform_device *ofdev)
+{
+ struct device *dev = &ofdev->dev;
+ struct device_node *np = ofdev->dev.of_node;
+ struct stm32_rng_private *priv;
+ struct resource res;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(struct stm32_rng_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ err = of_address_to_resource(np, 0, &res);
+ if (err)
+ return err;
+
+ priv->base = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = devm_clk_get(&ofdev->dev, NULL);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ dev_set_drvdata(dev, priv);
+
+ priv->rng.name = dev_driver_string(dev),
+#ifndef CONFIG_PM
+ priv->rng.init = stm32_rng_init,
+ priv->rng.cleanup = stm32_rng_cleanup,
+#endif
+ priv->rng.read = stm32_rng_read,
+ priv->rng.priv = (unsigned long) dev;
+
+ pm_runtime_set_autosuspend_delay(dev, 100);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_enable(dev);
+
+ return devm_hwrng_register(dev, &priv->rng);
+}
+
+#ifdef CONFIG_PM
+static int stm32_rng_runtime_suspend(struct device *dev)
+{
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
+
+ stm32_rng_cleanup(&priv->rng);
+
+ return 0;
+}
+
+static int stm32_rng_runtime_resume(struct device *dev)
+{
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
+
+ return stm32_rng_init(&priv->rng);
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(stm32_rng_pm_ops, stm32_rng_runtime_suspend,
+ stm32_rng_runtime_resume, NULL);
+
+static const struct of_device_id stm32_rng_match[] = {
+ {
+ .compatible = "st,stm32-rng",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, stm32_rng_match);
+
+static struct platform_driver stm32_rng_driver = {
+ .driver = {
+ .name = "stm32-rng",
+ .pm = &stm32_rng_pm_ops,
+ .of_match_table = stm32_rng_match,
+ },
+ .probe = stm32_rng_probe,
+};
+
+module_platform_driver(stm32_rng_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Thompson <daniel.thompson@linaro.org>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 RNG device driver");
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 654f6f36a071..55fe9020459f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -412,18 +412,42 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
return rv;
}
-static void start_check_enables(struct smi_info *smi_info)
+static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
+{
+ smi_info->last_timeout_jiffies = jiffies;
+ mod_timer(&smi_info->si_timer, new_val);
+ smi_info->timer_running = true;
+}
+
+/*
+ * Start a new message and (re)start the timer and thread.
+ */
+static void start_new_msg(struct smi_info *smi_info, unsigned char *msg,
+ unsigned int size)
+{
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
+
+ if (smi_info->thread)
+ wake_up_process(smi_info->thread);
+
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, size);
+}
+
+static void start_check_enables(struct smi_info *smi_info, bool start_timer)
{
unsigned char msg[2];
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
- smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+ if (start_timer)
+ start_new_msg(smi_info, msg, 2);
+ else
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
smi_info->si_state = SI_CHECKING_ENABLES;
}
-static void start_clear_flags(struct smi_info *smi_info)
+static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
{
unsigned char msg[3];
@@ -432,7 +456,10 @@ static void start_clear_flags(struct smi_info *smi_info)
msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
msg[2] = WDT_PRE_TIMEOUT_INT;
- smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
+ if (start_timer)
+ start_new_msg(smi_info, msg, 3);
+ else
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
smi_info->si_state = SI_CLEARING_FLAGS;
}
@@ -442,10 +469,8 @@ static void start_getting_msg_queue(struct smi_info *smi_info)
smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
smi_info->curr_msg->data_size = 2;
- smi_info->handlers->start_transaction(
- smi_info->si_sm,
- smi_info->curr_msg->data,
- smi_info->curr_msg->data_size);
+ start_new_msg(smi_info, smi_info->curr_msg->data,
+ smi_info->curr_msg->data_size);
smi_info->si_state = SI_GETTING_MESSAGES;
}
@@ -455,20 +480,11 @@ static void start_getting_events(struct smi_info *smi_info)
smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
smi_info->curr_msg->data_size = 2;
- smi_info->handlers->start_transaction(
- smi_info->si_sm,
- smi_info->curr_msg->data,
- smi_info->curr_msg->data_size);
+ start_new_msg(smi_info, smi_info->curr_msg->data,
+ smi_info->curr_msg->data_size);
smi_info->si_state = SI_GETTING_EVENTS;
}
-static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
-{
- smi_info->last_timeout_jiffies = jiffies;
- mod_timer(&smi_info->si_timer, new_val);
- smi_info->timer_running = true;
-}
-
/*
* When we have a situtaion where we run out of memory and cannot
* allocate messages, we just leave them in the BMC and run the system
@@ -478,11 +494,11 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
* Note that we cannot just use disable_irq(), since the interrupt may
* be shared.
*/
-static inline bool disable_si_irq(struct smi_info *smi_info)
+static inline bool disable_si_irq(struct smi_info *smi_info, bool start_timer)
{
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
smi_info->interrupt_disabled = true;
- start_check_enables(smi_info);
+ start_check_enables(smi_info, start_timer);
return true;
}
return false;
@@ -492,7 +508,7 @@ static inline bool enable_si_irq(struct smi_info *smi_info)
{
if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
smi_info->interrupt_disabled = false;
- start_check_enables(smi_info);
+ start_check_enables(smi_info, true);
return true;
}
return false;
@@ -510,7 +526,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info)
msg = ipmi_alloc_smi_msg();
if (!msg) {
- if (!disable_si_irq(smi_info))
+ if (!disable_si_irq(smi_info, true))
smi_info->si_state = SI_NORMAL;
} else if (enable_si_irq(smi_info)) {
ipmi_free_smi_msg(msg);
@@ -526,7 +542,7 @@ static void handle_flags(struct smi_info *smi_info)
/* Watchdog pre-timeout */
smi_inc_stat(smi_info, watchdog_pretimeouts);
- start_clear_flags(smi_info);
+ start_clear_flags(smi_info, true);
smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
if (smi_info->intf)
ipmi_smi_watchdog_pretimeout(smi_info->intf);
@@ -879,8 +895,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
msg[1] = IPMI_GET_MSG_FLAGS_CMD;
- smi_info->handlers->start_transaction(
- smi_info->si_sm, msg, 2);
+ start_new_msg(smi_info, msg, 2);
smi_info->si_state = SI_GETTING_FLAGS;
goto restart;
}
@@ -910,7 +925,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
* disable and messages disabled.
*/
if (smi_info->supports_event_msg_buff || smi_info->irq) {
- start_check_enables(smi_info);
+ start_check_enables(smi_info, true);
} else {
smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
if (!smi_info->curr_msg)
@@ -920,6 +935,13 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
}
goto restart;
}
+
+ if (si_sm_result == SI_SM_IDLE && smi_info->timer_running) {
+ /* Ok it if fails, the timer will just go off. */
+ if (del_timer(&smi_info->si_timer))
+ smi_info->timer_running = false;
+ }
+
out:
return si_sm_result;
}
@@ -2560,6 +2582,7 @@ static const struct of_device_id of_ipmi_match[] = {
.data = (void *)(unsigned long) SI_BT },
{},
};
+MODULE_DEVICE_TABLE(of, of_ipmi_match);
static int of_ipmi_probe(struct platform_device *dev)
{
@@ -2646,7 +2669,6 @@ static int of_ipmi_probe(struct platform_device *dev)
}
return 0;
}
-MODULE_DEVICE_TABLE(of, of_ipmi_match);
#else
#define of_ipmi_match NULL
static int of_ipmi_probe(struct platform_device *dev)
@@ -3613,7 +3635,7 @@ static int try_smi_init(struct smi_info *new_smi)
* Start clearing the flags before we enable interrupts or the
* timer to avoid racing with the timer.
*/
- start_clear_flags(new_smi);
+ start_clear_flags(new_smi, false);
/*
* IRQ is defined to be set when non-zero. req_events will
@@ -3908,7 +3930,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
poll(to_clean);
schedule_timeout_uninterruptible(1);
}
- disable_si_irq(to_clean);
+ disable_si_irq(to_clean, false);
while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
poll(to_clean);
schedule_timeout_uninterruptible(1);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 877205d22046..90e624662257 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -52,6 +52,7 @@
#include <linux/kthread.h>
#include <linux/acpi.h>
#include <linux/ctype.h>
+#include <linux/time64.h>
#define PFX "ipmi_ssif: "
#define DEVICE_NAME "ipmi_ssif"
@@ -1041,12 +1042,12 @@ static void sender(void *send_info,
start_next_msg(ssif_info, flags);
if (ssif_info->ssif_debug & SSIF_DEBUG_TIMING) {
- struct timeval t;
+ struct timespec64 t;
- do_gettimeofday(&t);
- pr_info("**Enqueue %02x %02x: %ld.%6.6ld\n",
+ ktime_get_real_ts64(&t);
+ pr_info("**Enqueue %02x %02x: %lld.%6.6ld\n",
msg->data[0], msg->data[1],
- (long) t.tv_sec, (long) t.tv_usec);
+ (long long) t.tv_sec, (long) t.tv_nsec / NSEC_PER_USEC);
}
}
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 0ac3bd1a5497..096f0cef4da1 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -153,6 +153,9 @@ static int timeout = 10;
/* The pre-timeout is disabled by default. */
static int pretimeout;
+/* Default timeout to set on panic */
+static int panic_wdt_timeout = 255;
+
/* Default action is to reset the board on a timeout. */
static unsigned char action_val = WDOG_TIMEOUT_RESET;
@@ -293,6 +296,9 @@ MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
module_param(pretimeout, timeout, 0644);
MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
+module_param(panic_wdt_timeout, timeout, 0644);
+MODULE_PARM_DESC(timeout, "Timeout value on kernel panic in seconds.");
+
module_param_cb(action, &param_ops_str, action_op, 0644);
MODULE_PARM_DESC(action, "Timeout action. One of: "
"reset, none, power_cycle, power_off.");
@@ -1189,7 +1195,7 @@ static int wdog_panic_handler(struct notifier_block *this,
/* Make sure we do this only once. */
panic_event_handled = 1;
- timeout = 255;
+ timeout = panic_wdt_timeout;
pretimeout = 0;
panic_halt_ipmi_set_timeout();
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 7680d5213ff8..45df4bf914f8 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2507,15 +2507,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
__FILE__, __LINE__, tty->driver->name, port->count);
- /* If port is closing, signal caller to try again */
- if (port->flags & ASYNC_CLOSING){
- wait_event_interruptible_tty(tty, port->close_wait,
- !(port->flags & ASYNC_CLOSING));
- retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- goto cleanup;
- }
-
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 8a80ead8d316..94006f9c2e43 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -19,7 +19,7 @@
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/poll.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <asm/sn/io.h>
@@ -461,5 +461,4 @@ scdrv_init(void)
}
return 0;
}
-
-module_init(scdrv_init);
+device_initcall(scdrv_init);
diff --git a/drivers/char/tpm/st33zp24/Kconfig b/drivers/char/tpm/st33zp24/Kconfig
index 09cb727864f0..19c007461d1c 100644
--- a/drivers/char/tpm/st33zp24/Kconfig
+++ b/drivers/char/tpm/st33zp24/Kconfig
@@ -1,6 +1,6 @@
config TCG_TIS_ST33ZP24
tristate "STMicroelectronics TPM Interface Specification 1.2 Interface"
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
---help---
STMicroelectronics ST33ZP24 core driver. It implements the core
TPM1.2 logic and hooks into the TPM kernel APIs. Physical layers will
diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c
index ad1ee180e0c2..309d2767c6a1 100644
--- a/drivers/char/tpm/st33zp24/i2c.c
+++ b/drivers/char/tpm/st33zp24/i2c.c
@@ -258,7 +258,6 @@ static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
static struct i2c_driver st33zp24_i2c_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = TPM_ST33_I2C,
.pm = &st33zp24_i2c_ops,
.of_match_table = of_match_ptr(of_st33zp24_i2c_match),
diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c
index f0184a1b0c1c..f974c945c97a 100644
--- a/drivers/char/tpm/st33zp24/spi.c
+++ b/drivers/char/tpm/st33zp24/spi.c
@@ -381,7 +381,6 @@ static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
static struct spi_driver tpm_st33_spi_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = TPM_ST33_SPI,
.pm = &st33zp24_spi_ops,
.of_match_table = of_match_ptr(of_st33zp24_spi_match),
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 1082d4bb016a..45cc39aabeee 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -119,6 +119,9 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
chip->dev.parent = chip->pdev;
+#ifdef CONFIG_ACPI
+ chip->dev.groups = chip->groups;
+#endif
if (chip->dev_num == 0)
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
@@ -182,12 +185,6 @@ static int tpm1_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
- rc = tpm_add_ppi(chip);
- if (rc) {
- tpm_sysfs_del_device(chip);
- return rc;
- }
-
chip->bios_dir = tpm_bios_log_setup(chip->devname);
return 0;
@@ -201,8 +198,6 @@ static void tpm1_chip_unregister(struct tpm_chip *chip)
if (chip->bios_dir)
tpm_bios_log_teardown(chip->bios_dir);
- tpm_remove_ppi(chip);
-
tpm_sysfs_del_device(chip);
}
@@ -225,17 +220,29 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
+ tpm_add_ppi(chip);
+
rc = tpm_dev_add_device(chip);
if (rc)
goto out_err;
/* Make the chip available. */
spin_lock(&driver_lock);
- list_add_rcu(&chip->list, &tpm_chip_list);
+ list_add_tail_rcu(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
+ if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
+ rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
+ &chip->dev.kobj,
+ "ppi");
+ if (rc && rc != -ENOENT) {
+ tpm_chip_unregister(chip);
+ return rc;
+ }
+ }
+
return 0;
out_err:
tpm1_chip_unregister(chip);
@@ -263,6 +270,9 @@ void tpm_chip_unregister(struct tpm_chip *chip)
spin_unlock(&driver_lock);
synchronize_rcu();
+ if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+ sysfs_remove_link(&chip->pdev->kobj, "ppi");
+
tpm1_chip_unregister(chip);
tpm_dev_del_device(chip);
}
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e85d3416d899..c50637db3a8a 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -666,6 +666,30 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
}
/**
+ * tpm_is_tpm2 - is the chip a TPM2 chip?
+ * @chip_num: tpm idx # or ANY
+ *
+ * Returns < 0 on error, and 1 or 0 on success depending whether the chip
+ * is a TPM2 chip.
+ */
+int tpm_is_tpm2(u32 chip_num)
+{
+ struct tpm_chip *chip;
+ int rc;
+
+ chip = tpm_chip_find_get(chip_num);
+ if (chip == NULL)
+ return -ENODEV;
+
+ rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
+
+ tpm_chip_put(chip);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_is_tpm2);
+
+/**
* tpm_pcr_read - read a pcr value
* @chip_num: tpm idx # or ANY
* @pcr_idx: pcr idx to retrieve
@@ -1021,6 +1045,58 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
}
EXPORT_SYMBOL_GPL(tpm_get_random);
+/**
+ * tpm_seal_trusted() - seal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
+ * are supported.
+ */
+int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
+ struct trusted_key_options *options)
+{
+ struct tpm_chip *chip;
+ int rc;
+
+ chip = tpm_chip_find_get(chip_num);
+ if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
+ return -ENODEV;
+
+ rc = tpm2_seal_trusted(chip, payload, options);
+
+ tpm_chip_put(chip);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_seal_trusted);
+
+/**
+ * tpm_unseal_trusted() - unseal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
+ * are supported.
+ */
+int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
+ struct trusted_key_options *options)
+{
+ struct tpm_chip *chip;
+ int rc;
+
+ chip = tpm_chip_find_get(chip_num);
+ if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
+ return -ENODEV;
+
+ rc = tpm2_unseal_trusted(chip, payload, options);
+
+ tpm_chip_put(chip);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_unseal_trusted);
+
static int __init tpm_init(void)
{
int rc;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f8319a0860fd..a4257a32964f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004 IBM Corporation
+ * Copyright (C) 2015 Intel Corporation
*
* Authors:
* Leendert van Doorn <leendert@watson.ibm.com>
@@ -28,6 +29,7 @@
#include <linux/tpm.h>
#include <linux/acpi.h>
#include <linux/cdev.h>
+#include <linux/highmem.h>
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
@@ -88,6 +90,9 @@ enum tpm2_return_codes {
enum tpm2_algorithms {
TPM2_ALG_SHA1 = 0x0004,
+ TPM2_ALG_KEYEDHASH = 0x0008,
+ TPM2_ALG_SHA256 = 0x000B,
+ TPM2_ALG_NULL = 0x0010
};
enum tpm2_command_codes {
@@ -95,6 +100,10 @@ enum tpm2_command_codes {
TPM2_CC_SELF_TEST = 0x0143,
TPM2_CC_STARTUP = 0x0144,
TPM2_CC_SHUTDOWN = 0x0145,
+ TPM2_CC_CREATE = 0x0153,
+ TPM2_CC_LOAD = 0x0157,
+ TPM2_CC_UNSEAL = 0x015E,
+ TPM2_CC_FLUSH_CONTEXT = 0x0165,
TPM2_CC_GET_CAPABILITY = 0x017A,
TPM2_CC_GET_RANDOM = 0x017B,
TPM2_CC_PCR_READ = 0x017E,
@@ -115,6 +124,13 @@ enum tpm2_startup_types {
TPM2_SU_STATE = 0x0001,
};
+enum tpm2_start_method {
+ TPM2_START_ACPI = 2,
+ TPM2_START_FIFO = 6,
+ TPM2_START_CRB = 7,
+ TPM2_START_CRB_WITH_ACPI = 8,
+};
+
struct tpm_chip;
struct tpm_vendor_specific {
@@ -151,8 +167,7 @@ struct tpm_vendor_specific {
enum tpm_chip_flags {
TPM_CHIP_FLAG_REGISTERED = BIT(0),
- TPM_CHIP_FLAG_PPI = BIT(1),
- TPM_CHIP_FLAG_TPM2 = BIT(2),
+ TPM_CHIP_FLAG_TPM2 = BIT(1),
};
struct tpm_chip {
@@ -175,6 +190,8 @@ struct tpm_chip {
struct dentry **bios_dir;
#ifdef CONFIG_ACPI
+ const struct attribute_group *groups[2];
+ unsigned int groups_cnt;
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
@@ -182,7 +199,7 @@ struct tpm_chip {
struct list_head list;
};
-#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
static inline void tpm_chip_put(struct tpm_chip *chip)
{
@@ -382,6 +399,101 @@ struct tpm_cmd_t {
tpm_cmd_params params;
} __packed;
+/* A string buffer type for constructing TPM commands. This is based on the
+ * ideas of string buffer code in security/keys/trusted.h but is heap based
+ * in order to keep the stack usage minimal.
+ */
+
+enum tpm_buf_flags {
+ TPM_BUF_OVERFLOW = BIT(0),
+};
+
+struct tpm_buf {
+ struct page *data_page;
+ unsigned int flags;
+ u8 *data;
+};
+
+static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
+{
+ struct tpm_input_header *head;
+
+ buf->data_page = alloc_page(GFP_HIGHUSER);
+ if (!buf->data_page)
+ return -ENOMEM;
+
+ buf->flags = 0;
+ buf->data = kmap(buf->data_page);
+
+ head = (struct tpm_input_header *) buf->data;
+
+ head->tag = cpu_to_be16(tag);
+ head->length = cpu_to_be32(sizeof(*head));
+ head->ordinal = cpu_to_be32(ordinal);
+
+ return 0;
+}
+
+static inline void tpm_buf_destroy(struct tpm_buf *buf)
+{
+ kunmap(buf->data_page);
+ __free_page(buf->data_page);
+}
+
+static inline u32 tpm_buf_length(struct tpm_buf *buf)
+{
+ struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+
+ return be32_to_cpu(head->length);
+}
+
+static inline u16 tpm_buf_tag(struct tpm_buf *buf)
+{
+ struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+
+ return be16_to_cpu(head->tag);
+}
+
+static inline void tpm_buf_append(struct tpm_buf *buf,
+ const unsigned char *new_data,
+ unsigned int new_len)
+{
+ struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
+ u32 len = tpm_buf_length(buf);
+
+ /* Return silently if overflow has already happened. */
+ if (buf->flags & TPM_BUF_OVERFLOW)
+ return;
+
+ if ((len + new_len) > PAGE_SIZE) {
+ WARN(1, "tpm_buf: overflow\n");
+ buf->flags |= TPM_BUF_OVERFLOW;
+ return;
+ }
+
+ memcpy(&buf->data[len], new_data, new_len);
+ head->length = cpu_to_be32(len + new_len);
+}
+
+static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
+{
+ tpm_buf_append(buf, &value, 1);
+}
+
+static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
+{
+ __be16 value2 = cpu_to_be16(value);
+
+ tpm_buf_append(buf, (u8 *) &value2, 2);
+}
+
+static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
+{
+ __be32 value2 = cpu_to_be32(value);
+
+ tpm_buf_append(buf, (u8 *) &value2, 4);
+}
+
extern struct class *tpm_class;
extern dev_t tpm_devt;
extern const struct file_operations tpm_fops;
@@ -412,15 +524,9 @@ void tpm_sysfs_del_device(struct tpm_chip *chip);
int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
#ifdef CONFIG_ACPI
-extern int tpm_add_ppi(struct tpm_chip *chip);
-extern void tpm_remove_ppi(struct tpm_chip *chip);
+extern void tpm_add_ppi(struct tpm_chip *chip);
#else
-static inline int tpm_add_ppi(struct tpm_chip *chip)
-{
- return 0;
-}
-
-static inline void tpm_remove_ppi(struct tpm_chip *chip)
+static inline void tpm_add_ppi(struct tpm_chip *chip)
{
}
#endif
@@ -428,6 +534,12 @@ static inline void tpm_remove_ppi(struct tpm_chip *chip)
int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+int tpm2_seal_trusted(struct tpm_chip *chip,
+ struct trusted_key_payload *payload,
+ struct trusted_key_options *options);
+int tpm2_unseal_trusted(struct tpm_chip *chip,
+ struct trusted_key_payload *payload,
+ struct trusted_key_options *options);
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 011909a9be96..c12130485fc1 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Intel Corporation
+ * Copyright (C) 2014, 2015 Intel Corporation
*
* Authors:
* Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
@@ -16,6 +16,11 @@
*/
#include "tpm.h"
+#include <keys/trusted-type.h>
+
+enum tpm2_object_attributes {
+ TPM2_ATTR_USER_WITH_AUTH = BIT(6),
+};
struct tpm2_startup_in {
__be16 startup_type;
@@ -381,6 +386,254 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = {
};
/**
+ * Append TPMS_AUTH_COMMAND to the buffer. The buffer must be allocated with
+ * tpm_buf_alloc().
+ *
+ * @param buf: an allocated tpm_buf instance
+ * @param nonce: the session nonce, may be NULL if not used
+ * @param nonce_len: the session nonce length, may be 0 if not used
+ * @param attributes: the session attributes
+ * @param hmac: the session HMAC or password, may be NULL if not used
+ * @param hmac_len: the session HMAC or password length, maybe 0 if not used
+ */
+static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
+ const u8 *nonce, u16 nonce_len,
+ u8 attributes,
+ const u8 *hmac, u16 hmac_len)
+{
+ tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len);
+ tpm_buf_append_u32(buf, session_handle);
+ tpm_buf_append_u16(buf, nonce_len);
+
+ if (nonce && nonce_len)
+ tpm_buf_append(buf, nonce, nonce_len);
+
+ tpm_buf_append_u8(buf, attributes);
+ tpm_buf_append_u16(buf, hmac_len);
+
+ if (hmac && hmac_len)
+ tpm_buf_append(buf, hmac, hmac_len);
+}
+
+/**
+ * tpm2_seal_trusted() - seal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success.
+ */
+int tpm2_seal_trusted(struct tpm_chip *chip,
+ struct trusted_key_payload *payload,
+ struct trusted_key_options *options)
+{
+ unsigned int blob_len;
+ struct tpm_buf buf;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&buf, options->keyhandle);
+ tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+ NULL /* nonce */, 0,
+ 0 /* session_attributes */,
+ options->keyauth /* hmac */,
+ TPM_DIGEST_SIZE);
+
+ /* sensitive */
+ tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1);
+
+ tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
+ tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
+ tpm_buf_append_u16(&buf, payload->key_len + 1);
+ tpm_buf_append(&buf, payload->key, payload->key_len);
+ tpm_buf_append_u8(&buf, payload->migratable);
+
+ /* public */
+ tpm_buf_append_u16(&buf, 14);
+
+ tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
+ tpm_buf_append_u16(&buf, TPM2_ALG_SHA256);
+ tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
+ tpm_buf_append_u16(&buf, 0); /* policy digest size */
+ tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
+ tpm_buf_append_u16(&buf, 0);
+
+ /* outside info */
+ tpm_buf_append_u16(&buf, 0);
+
+ /* creation PCR */
+ tpm_buf_append_u32(&buf, 0);
+
+ if (buf.flags & TPM_BUF_OVERFLOW) {
+ rc = -E2BIG;
+ goto out;
+ }
+
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data");
+ if (rc)
+ goto out;
+
+ blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]);
+ if (blob_len > MAX_BLOB_SIZE) {
+ rc = -E2BIG;
+ goto out;
+ }
+
+ memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len);
+ payload->blob_len = blob_len;
+
+out:
+ tpm_buf_destroy(&buf);
+
+ if (rc > 0)
+ rc = -EPERM;
+
+ return rc;
+}
+
+static int tpm2_load(struct tpm_chip *chip,
+ struct trusted_key_payload *payload,
+ struct trusted_key_options *options,
+ u32 *blob_handle)
+{
+ struct tpm_buf buf;
+ unsigned int private_len;
+ unsigned int public_len;
+ unsigned int blob_len;
+ int rc;
+
+ private_len = be16_to_cpup((__be16 *) &payload->blob[0]);
+ if (private_len > (payload->blob_len - 2))
+ return -E2BIG;
+
+ public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]);
+ blob_len = private_len + public_len + 4;
+ if (blob_len > payload->blob_len)
+ return -E2BIG;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&buf, options->keyhandle);
+ tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+ NULL /* nonce */, 0,
+ 0 /* session_attributes */,
+ options->keyauth /* hmac */,
+ TPM_DIGEST_SIZE);
+
+ tpm_buf_append(&buf, payload->blob, blob_len);
+
+ if (buf.flags & TPM_BUF_OVERFLOW) {
+ rc = -E2BIG;
+ goto out;
+ }
+
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob");
+ if (!rc)
+ *blob_handle = be32_to_cpup(
+ (__be32 *) &buf.data[TPM_HEADER_SIZE]);
+
+out:
+ tpm_buf_destroy(&buf);
+
+ if (rc > 0)
+ rc = -EPERM;
+
+ return rc;
+}
+
+static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
+ if (rc) {
+ dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n",
+ handle);
+ return;
+ }
+
+ tpm_buf_append_u32(&buf, handle);
+
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
+ if (rc)
+ dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle,
+ rc);
+
+ tpm_buf_destroy(&buf);
+}
+
+static int tpm2_unseal(struct tpm_chip *chip,
+ struct trusted_key_payload *payload,
+ struct trusted_key_options *options,
+ u32 blob_handle)
+{
+ struct tpm_buf buf;
+ u16 data_len;
+ u8 *data;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&buf, blob_handle);
+ tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+ NULL /* nonce */, 0,
+ 0 /* session_attributes */,
+ options->blobauth /* hmac */,
+ TPM_DIGEST_SIZE);
+
+ rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing");
+ if (rc > 0)
+ rc = -EPERM;
+
+ if (!rc) {
+ data_len = be16_to_cpup(
+ (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
+ data = &buf.data[TPM_HEADER_SIZE + 6];
+
+ memcpy(payload->key, data, data_len - 1);
+ payload->key_len = data_len - 1;
+ payload->migratable = data[data_len - 1];
+ }
+
+ tpm_buf_destroy(&buf);
+ return rc;
+}
+
+/**
+ * tpm_unseal_trusted() - unseal a trusted key
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @options: authentication values and other options
+ * @payload: the key data in clear and encrypted form
+ *
+ * Returns < 0 on error and 0 on success.
+ */
+int tpm2_unseal_trusted(struct tpm_chip *chip,
+ struct trusted_key_payload *payload,
+ struct trusted_key_options *options)
+{
+ u32 blob_handle;
+ int rc;
+
+ rc = tpm2_load(chip, payload, options, &blob_handle);
+ if (rc)
+ return rc;
+
+ rc = tpm2_unseal(chip, payload, options, blob_handle);
+
+ tpm2_flush_context(chip, blob_handle);
+
+ return rc;
+}
+
+/**
* tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
* @chip: TPM chip to use.
* @property_id: property ID.
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 1267322595da..4bb9727c1047 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -34,12 +34,6 @@ enum crb_defaults {
CRB_ACPI_START_INDEX = 1,
};
-enum crb_start_method {
- CRB_SM_ACPI_START = 2,
- CRB_SM_CRB = 7,
- CRB_SM_CRB_WITH_ACPI_START = 8,
-};
-
struct acpi_tpm2 {
struct acpi_table_header hdr;
u16 platform_class;
@@ -74,7 +68,8 @@ struct crb_control_area {
u32 int_enable;
u32 int_sts;
u32 cmd_size;
- u64 cmd_pa;
+ u32 cmd_pa_low;
+ u32 cmd_pa_high;
u32 rsp_size;
u64 rsp_pa;
} __packed;
@@ -220,12 +215,6 @@ static int crb_acpi_add(struct acpi_device *device)
u64 pa;
int rc;
- chip = tpmm_chip_alloc(dev, &tpm_crb);
- if (IS_ERR(chip))
- return PTR_ERR(chip);
-
- chip->flags = TPM_CHIP_FLAG_TPM2;
-
status = acpi_get_table(ACPI_SIG_TPM2, 1,
(struct acpi_table_header **) &buf);
if (ACPI_FAILURE(status)) {
@@ -233,13 +222,15 @@ static int crb_acpi_add(struct acpi_device *device)
return -ENODEV;
}
- /* At least some versions of AMI BIOS have a bug that TPM2 table has
- * zero address for the control area and therefore we must fail.
- */
- if (!buf->control_area_pa) {
- dev_err(dev, "TPM2 ACPI table has a zero address for the control area\n");
- return -EINVAL;
- }
+ /* Should the FIFO driver handle this? */
+ if (buf->start_method == TPM2_START_FIFO)
+ return -ENODEV;
+
+ chip = tpmm_chip_alloc(dev, &tpm_crb);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ chip->flags = TPM_CHIP_FLAG_TPM2;
if (buf->hdr.length < sizeof(struct acpi_tpm2)) {
dev_err(dev, "TPM2 ACPI table has wrong size");
@@ -259,11 +250,11 @@ static int crb_acpi_add(struct acpi_device *device)
* report only ACPI start but in practice seems to require both
* ACPI start and CRB start.
*/
- if (sm == CRB_SM_CRB || sm == CRB_SM_CRB_WITH_ACPI_START ||
+ if (sm == TPM2_START_CRB || sm == TPM2_START_FIFO ||
!strcmp(acpi_device_hid(device), "MSFT0101"))
priv->flags |= CRB_FL_CRB_START;
- if (sm == CRB_SM_ACPI_START || sm == CRB_SM_CRB_WITH_ACPI_START)
+ if (sm == TPM2_START_ACPI || sm == TPM2_START_CRB_WITH_ACPI)
priv->flags |= CRB_FL_ACPI_START;
priv->cca = (struct crb_control_area __iomem *)
@@ -273,8 +264,8 @@ static int crb_acpi_add(struct acpi_device *device)
return -ENOMEM;
}
- memcpy_fromio(&pa, &priv->cca->cmd_pa, 8);
- pa = le64_to_cpu(pa);
+ pa = ((u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_high)) << 32) |
+ (u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_low));
priv->cmd = devm_ioremap_nocache(dev, pa,
ioread32(&priv->cca->cmd_size));
if (!priv->cmd) {
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c
index 3a56a131586c..bd72fb04225e 100644
--- a/drivers/char/tpm/tpm_eventlog.c
+++ b/drivers/char/tpm/tpm_eventlog.c
@@ -76,15 +76,25 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
void *addr = log->bios_event_log;
void *limit = log->bios_event_log_end;
struct tcpa_event *event;
+ u32 converted_event_size;
+ u32 converted_event_type;
+
/* read over *pos measurements */
for (i = 0; i < *pos; i++) {
event = addr;
+ converted_event_size =
+ do_endian_conversion(event->event_size);
+ converted_event_type =
+ do_endian_conversion(event->event_type);
+
if ((addr + sizeof(struct tcpa_event)) < limit) {
- if (event->event_type == 0 && event->event_size == 0)
+ if ((converted_event_type == 0) &&
+ (converted_event_size == 0))
return NULL;
- addr += sizeof(struct tcpa_event) + event->event_size;
+ addr += (sizeof(struct tcpa_event) +
+ converted_event_size);
}
}
@@ -94,8 +104,12 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
event = addr;
- if ((event->event_type == 0 && event->event_size == 0) ||
- ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
+ converted_event_size = do_endian_conversion(event->event_size);
+ converted_event_type = do_endian_conversion(event->event_type);
+
+ if (((converted_event_type == 0) && (converted_event_size == 0))
+ || ((addr + sizeof(struct tcpa_event) + converted_event_size)
+ >= limit))
return NULL;
return addr;
@@ -107,8 +121,12 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
struct tcpa_event *event = v;
struct tpm_bios_log *log = m->private;
void *limit = log->bios_event_log_end;
+ u32 converted_event_size;
+ u32 converted_event_type;
- v += sizeof(struct tcpa_event) + event->event_size;
+ converted_event_size = do_endian_conversion(event->event_size);
+
+ v += sizeof(struct tcpa_event) + converted_event_size;
/* now check if current entry is valid */
if ((v + sizeof(struct tcpa_event)) >= limit)
@@ -116,11 +134,11 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
event = v;
- if (event->event_type == 0 && event->event_size == 0)
- return NULL;
+ converted_event_size = do_endian_conversion(event->event_size);
+ converted_event_type = do_endian_conversion(event->event_type);
- if ((event->event_type == 0 && event->event_size == 0) ||
- ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
+ if (((converted_event_type == 0) && (converted_event_size == 0)) ||
+ ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
return NULL;
(*pos)++;
@@ -140,7 +158,7 @@ static int get_event_name(char *dest, struct tcpa_event *event,
int i, n_len = 0, d_len = 0;
struct tcpa_pc_event *pc_event;
- switch(event->event_type) {
+ switch (do_endian_conversion(event->event_type)) {
case PREBOOT:
case POST_CODE:
case UNUSED:
@@ -156,14 +174,16 @@ static int get_event_name(char *dest, struct tcpa_event *event,
case NONHOST_CODE:
case NONHOST_CONFIG:
case NONHOST_INFO:
- name = tcpa_event_type_strings[event->event_type];
+ name = tcpa_event_type_strings[do_endian_conversion
+ (event->event_type)];
n_len = strlen(name);
break;
case SEPARATOR:
case ACTION:
- if (MAX_TEXT_EVENT > event->event_size) {
+ if (MAX_TEXT_EVENT >
+ do_endian_conversion(event->event_size)) {
name = event_entry;
- n_len = event->event_size;
+ n_len = do_endian_conversion(event->event_size);
}
break;
case EVENT_TAG:
@@ -171,7 +191,7 @@ static int get_event_name(char *dest, struct tcpa_event *event,
/* ToDo Row data -> Base64 */
- switch (pc_event->event_id) {
+ switch (do_endian_conversion(pc_event->event_id)) {
case SMBIOS:
case BIS_CERT:
case CMOS:
@@ -179,7 +199,8 @@ static int get_event_name(char *dest, struct tcpa_event *event,
case OPTION_ROM_EXEC:
case OPTION_ROM_CONFIG:
case S_CRTM_VERSION:
- name = tcpa_pc_event_id_strings[pc_event->event_id];
+ name = tcpa_pc_event_id_strings[do_endian_conversion
+ (pc_event->event_id)];
n_len = strlen(name);
break;
/* hash data */
@@ -188,7 +209,8 @@ static int get_event_name(char *dest, struct tcpa_event *event,
case OPTION_ROM_MICROCODE:
case S_CRTM_CONTENTS:
case POST_CONTENTS:
- name = tcpa_pc_event_id_strings[pc_event->event_id];
+ name = tcpa_pc_event_id_strings[do_endian_conversion
+ (pc_event->event_id)];
n_len = strlen(name);
for (i = 0; i < 20; i++)
d_len += sprintf(&data[2*i], "%02x",
@@ -209,13 +231,24 @@ static int get_event_name(char *dest, struct tcpa_event *event,
static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
{
struct tcpa_event *event = v;
- char *data = v;
+ struct tcpa_event temp_event;
+ char *tempPtr;
int i;
- for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
- seq_putc(m, data[i]);
+ memcpy(&temp_event, event, sizeof(struct tcpa_event));
+
+ /* convert raw integers for endianness */
+ temp_event.pcr_index = do_endian_conversion(event->pcr_index);
+ temp_event.event_type = do_endian_conversion(event->event_type);
+ temp_event.event_size = do_endian_conversion(event->event_size);
+
+ tempPtr = (char *)&temp_event;
+
+ for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++)
+ seq_putc(m, tempPtr[i]);
return 0;
+
}
static int tpm_bios_measurements_release(struct inode *inode,
@@ -238,7 +271,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
char *eventname;
struct tcpa_event *event = v;
unsigned char *event_entry =
- (unsigned char *) (v + sizeof(struct tcpa_event));
+ (unsigned char *)(v + sizeof(struct tcpa_event));
eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
if (!eventname) {
@@ -247,13 +280,14 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
return -EFAULT;
}
- seq_printf(m, "%2d ", event->pcr_index);
+ /* 1st: PCR */
+ seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
/* 2nd: SHA1 */
seq_printf(m, "%20phN", event->pcr_value);
/* 3rd: event type identifier */
- seq_printf(m, " %02x", event->event_type);
+ seq_printf(m, " %02x", do_endian_conversion(event->event_type));
len += get_event_name(eventname, event, event_entry);
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
index e7da086d6928..267bfbd1b7bb 100644
--- a/drivers/char/tpm/tpm_eventlog.h
+++ b/drivers/char/tpm/tpm_eventlog.h
@@ -6,6 +6,12 @@
#define MAX_TEXT_EVENT 1000 /* Max event string length */
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
+#ifdef CONFIG_PPC64
+#define do_endian_conversion(x) be32_to_cpu(x)
+#else
+#define do_endian_conversion(x) x
+#endif
+
enum bios_platform_class {
BIOS_CLIENT = 0x00,
BIOS_SERVER = 0x01,
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
index 7a0ca78ad3c6..8dfb88b9739c 100644
--- a/drivers/char/tpm/tpm_i2c_atmel.c
+++ b/drivers/char/tpm/tpm_i2c_atmel.c
@@ -217,7 +217,6 @@ static struct i2c_driver i2c_atmel_driver = {
.remove = i2c_atmel_remove,
.driver = {
.name = I2C_DRIVER_NAME,
- .owner = THIS_MODULE,
.pm = &i2c_atmel_pm_ops,
.of_match_table = of_match_ptr(i2c_atmel_of_match),
},
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 33c5f360ab01..63d5d22e9e60 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -711,7 +711,6 @@ static struct i2c_driver tpm_tis_i2c_driver = {
.remove = tpm_tis_i2c_remove,
.driver = {
.name = "tpm_i2c_infineon",
- .owner = THIS_MODULE,
.pm = &tpm_tis_i2c_ops,
.of_match_table = of_match_ptr(tpm_tis_i2c_of_match),
},
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
index 9d42b7d78e50..847f1597fe9b 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -641,7 +641,6 @@ static struct i2c_driver i2c_nuvoton_driver = {
.remove = i2c_nuvoton_remove,
.driver = {
.name = I2C_DRIVER_NAME,
- .owner = THIS_MODULE,
.pm = &i2c_nuvoton_pm_ops,
.of_match_table = of_match_ptr(i2c_nuvoton_of_match),
},
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index 27ebf9511cb4..3e6a22658b63 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -491,7 +491,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
}
ibmvtpm->rtce_size = be16_to_cpu(crq->len);
ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
- GFP_KERNEL);
+ GFP_ATOMIC);
if (!ibmvtpm->rtce_buf) {
dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n");
return;
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
index eebe6256918f..570f30c5c5f4 100644
--- a/drivers/char/tpm/tpm_of.c
+++ b/drivers/char/tpm/tpm_of.c
@@ -24,14 +24,14 @@ int read_log(struct tpm_bios_log *log)
{
struct device_node *np;
const u32 *sizep;
- const __be64 *basep;
+ const u64 *basep;
if (log->bios_event_log != NULL) {
pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
return -EFAULT;
}
- np = of_find_node_by_name(NULL, "ibm,vtpm");
+ np = of_find_node_by_name(NULL, "vtpm");
if (!np) {
pr_err("%s: ERROR - IBMVTPM not supported\n", __func__);
return -ENODEV;
@@ -53,17 +53,18 @@ int read_log(struct tpm_bios_log *log)
goto cleanup_eio;
}
- of_node_put(np);
log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
if (!log->bios_event_log) {
pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
__func__);
+ of_node_put(np);
return -ENOMEM;
}
log->bios_event_log_end = log->bios_event_log + *sizep;
- memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep);
+ memcpy(log->bios_event_log, __va(*basep), *sizep);
+ of_node_put(np);
return 0;
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index 6ca9b5d78144..692a2c6ae036 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -53,7 +53,7 @@ tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
static ssize_t tpm_show_ppi_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
}
@@ -63,7 +63,7 @@ static ssize_t tpm_show_ppi_request(struct device *dev,
{
ssize_t size = -EINVAL;
union acpi_object *obj;
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
ACPI_TYPE_PACKAGE, NULL);
@@ -100,7 +100,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
int func = TPM_PPI_FN_SUBREQ;
union acpi_object *obj, tmp;
union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
/*
* the function to submit TPM operation request to pre-os environment
@@ -156,7 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
.buffer.length = 0,
.buffer.pointer = NULL
};
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
static char *info[] = {
"None",
@@ -197,7 +197,7 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
acpi_status status = -EINVAL;
union acpi_object *obj, *ret_obj;
u64 req, res;
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
ACPI_TYPE_PACKAGE, NULL);
@@ -296,7 +296,7 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
PPI_TPM_REQ_MAX);
@@ -306,7 +306,7 @@ static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = to_tpm_chip(dev);
return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
PPI_VS_REQ_END);
@@ -334,17 +334,16 @@ static struct attribute_group ppi_attr_grp = {
.attrs = ppi_attrs
};
-int tpm_add_ppi(struct tpm_chip *chip)
+void tpm_add_ppi(struct tpm_chip *chip)
{
union acpi_object *obj;
- int rc;
if (!chip->acpi_dev_handle)
- return 0;
+ return;
if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION))
- return 0;
+ return;
/* Cache PPI version string. */
obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid,
@@ -356,16 +355,5 @@ int tpm_add_ppi(struct tpm_chip *chip)
ACPI_FREE(obj);
}
- rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp);
-
- if (!rc)
- chip->flags |= TPM_CHIP_FLAG_PPI;
-
- return rc;
-}
-
-void tpm_remove_ppi(struct tpm_chip *chip)
-{
- if (chip->flags & TPM_CHIP_FLAG_PPI)
- sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp);
+ chip->groups[chip->groups_cnt++] = &ppi_attr_grp;
}
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index f2dffa770b8e..65f7eecc45b0 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005, 2006 IBM Corporation
- * Copyright (C) 2014 Intel Corporation
+ * Copyright (C) 2014, 2015 Intel Corporation
*
* Authors:
* Leendert van Doorn <leendert@watson.ibm.com>
@@ -28,6 +28,7 @@
#include <linux/wait.h>
#include <linux/acpi.h>
#include <linux/freezer.h>
+#include <acpi/actbl2.h>
#include "tpm.h"
enum tis_access {
@@ -65,6 +66,17 @@ enum tis_defaults {
TIS_LONG_TIMEOUT = 2000, /* 2 sec */
};
+struct tpm_info {
+ unsigned long start;
+ unsigned long len;
+ unsigned int irq;
+};
+
+static struct tpm_info tis_default_info = {
+ .start = TIS_MEM_BASE,
+ .len = TIS_MEM_LEN,
+ .irq = 0,
+};
/* Some timeout values are needed before it is known whether the chip is
* TPM 1.0 or TPM 2.0.
@@ -91,26 +103,54 @@ struct priv_data {
};
#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
-static int is_itpm(struct pnp_dev *dev)
+static int has_hid(struct acpi_device *dev, const char *hid)
{
- struct acpi_device *acpi = pnp_acpi_device(dev);
struct acpi_hardware_id *id;
- if (!acpi)
- return 0;
-
- list_for_each_entry(id, &acpi->pnp.ids, list) {
- if (!strcmp("INTC0102", id->id))
+ list_for_each_entry(id, &dev->pnp.ids, list)
+ if (!strcmp(hid, id->id))
return 1;
- }
return 0;
}
+
+static inline int is_itpm(struct acpi_device *dev)
+{
+ return has_hid(dev, "INTC0102");
+}
+
+static inline int is_fifo(struct acpi_device *dev)
+{
+ struct acpi_table_tpm2 *tbl;
+ acpi_status st;
+
+ /* TPM 1.2 FIFO */
+ if (!has_hid(dev, "MSFT0101"))
+ return 1;
+
+ st = acpi_get_table(ACPI_SIG_TPM2, 1,
+ (struct acpi_table_header **) &tbl);
+ if (ACPI_FAILURE(st)) {
+ dev_err(&dev->dev, "failed to get TPM2 ACPI table\n");
+ return 0;
+ }
+
+ if (le32_to_cpu(tbl->start_method) != TPM2_START_FIFO)
+ return 0;
+
+ /* TPM 2.0 FIFO */
+ return 1;
+}
#else
-static inline int is_itpm(struct pnp_dev *dev)
+static inline int is_itpm(struct acpi_device *dev)
{
return 0;
}
+
+static inline int is_fifo(struct acpi_device *dev)
+{
+ return 1;
+}
#endif
/* Before we attempt to access the TPM we must see that the valid bit is set.
@@ -600,12 +640,12 @@ static void tpm_tis_remove(struct tpm_chip *chip)
release_locality(chip, chip->vendor.locality, 1);
}
-static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
- resource_size_t start, resource_size_t len,
- unsigned int irq)
+static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
+ acpi_handle acpi_dev_handle)
{
u32 vendor, intfcaps, intmask;
int rc, i, irq_s, irq_e, probe;
+ int irq_r = -1;
struct tpm_chip *chip;
struct priv_data *priv;
@@ -622,7 +662,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
chip->acpi_dev_handle = acpi_dev_handle;
#endif
- chip->vendor.iobase = devm_ioremap(dev, start, len);
+ chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len);
if (!chip->vendor.iobase)
return -EIO;
@@ -707,11 +747,12 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality));
if (interrupts)
- chip->vendor.irq = irq;
+ chip->vendor.irq = tpm_info->irq;
if (interrupts && !chip->vendor.irq) {
irq_s =
ioread8(chip->vendor.iobase +
TPM_INT_VECTOR(chip->vendor.locality));
+ irq_r = irq_s;
if (irq_s) {
irq_e = irq_s;
} else {
@@ -766,6 +807,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
iowrite32(intmask,
chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality));
+
+ devm_free_irq(dev, i, chip);
}
}
if (chip->vendor.irq) {
@@ -792,7 +835,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality));
}
- }
+ } else if (irq_r != -1)
+ iowrite8(irq_r, chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
@@ -890,27 +935,27 @@ static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
const struct pnp_device_id *pnp_id)
{
- resource_size_t start, len;
- unsigned int irq = 0;
+ struct tpm_info tpm_info = tis_default_info;
acpi_handle acpi_dev_handle = NULL;
- start = pnp_mem_start(pnp_dev, 0);
- len = pnp_mem_len(pnp_dev, 0);
+ tpm_info.start = pnp_mem_start(pnp_dev, 0);
+ tpm_info.len = pnp_mem_len(pnp_dev, 0);
if (pnp_irq_valid(pnp_dev, 0))
- irq = pnp_irq(pnp_dev, 0);
+ tpm_info.irq = pnp_irq(pnp_dev, 0);
else
interrupts = false;
- if (is_itpm(pnp_dev))
- itpm = true;
-
#ifdef CONFIG_ACPI
- if (pnp_acpi_device(pnp_dev))
+ if (pnp_acpi_device(pnp_dev)) {
+ if (is_itpm(pnp_acpi_device(pnp_dev)))
+ itpm = true;
+
acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle;
+ }
#endif
- return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq);
+ return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle);
}
static struct pnp_device_id tpm_pnp_tbl[] = {
@@ -930,6 +975,7 @@ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
static void tpm_tis_pnp_remove(struct pnp_dev *dev)
{
struct tpm_chip *chip = pnp_get_drvdata(dev);
+
tpm_chip_unregister(chip);
tpm_tis_remove(chip);
}
@@ -950,6 +996,79 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
#endif
+#ifdef CONFIG_ACPI
+static int tpm_check_resource(struct acpi_resource *ares, void *data)
+{
+ struct tpm_info *tpm_info = (struct tpm_info *) data;
+ struct resource res;
+
+ if (acpi_dev_resource_interrupt(ares, 0, &res)) {
+ tpm_info->irq = res.start;
+ } else if (acpi_dev_resource_memory(ares, &res)) {
+ tpm_info->start = res.start;
+ tpm_info->len = resource_size(&res);
+ }
+
+ return 1;
+}
+
+static int tpm_tis_acpi_init(struct acpi_device *acpi_dev)
+{
+ struct list_head resources;
+ struct tpm_info tpm_info = tis_default_info;
+ int ret;
+
+ if (!is_fifo(acpi_dev))
+ return -ENODEV;
+
+ INIT_LIST_HEAD(&resources);
+ ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource,
+ &tpm_info);
+ if (ret < 0)
+ return ret;
+
+ acpi_dev_free_resource_list(&resources);
+
+ if (!tpm_info.irq)
+ interrupts = false;
+
+ if (is_itpm(acpi_dev))
+ itpm = true;
+
+ return tpm_tis_init(&acpi_dev->dev, &tpm_info, acpi_dev->handle);
+}
+
+static int tpm_tis_acpi_remove(struct acpi_device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+
+ tpm_chip_unregister(chip);
+ tpm_tis_remove(chip);
+
+ return 0;
+}
+
+static struct acpi_device_id tpm_acpi_tbl[] = {
+ {"MSFT0101", 0}, /* TPM 2.0 */
+ /* Add new here */
+ {"", 0}, /* User Specified */
+ {"", 0} /* Terminator */
+};
+MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl);
+
+static struct acpi_driver tis_acpi_driver = {
+ .name = "tpm_tis",
+ .ids = tpm_acpi_tbl,
+ .ops = {
+ .add = tpm_tis_acpi_init,
+ .remove = tpm_tis_acpi_remove,
+ },
+ .drv = {
+ .pm = &tpm_tis_pm,
+ },
+};
+#endif
+
static struct platform_driver tis_drv = {
.driver = {
.name = "tpm_tis",
@@ -966,9 +1085,25 @@ static int __init init_tis(void)
{
int rc;
#ifdef CONFIG_PNP
- if (!force)
- return pnp_register_driver(&tis_pnp_driver);
+ if (!force) {
+ rc = pnp_register_driver(&tis_pnp_driver);
+ if (rc)
+ return rc;
+ }
+#endif
+#ifdef CONFIG_ACPI
+ if (!force) {
+ rc = acpi_bus_register_driver(&tis_acpi_driver);
+ if (rc) {
+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&tis_pnp_driver);
#endif
+ return rc;
+ }
+ }
+#endif
+ if (!force)
+ return 0;
rc = platform_driver_register(&tis_drv);
if (rc < 0)
@@ -978,7 +1113,7 @@ static int __init init_tis(void)
rc = PTR_ERR(pdev);
goto err_dev;
}
- rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0);
+ rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL);
if (rc)
goto err_init;
return 0;
@@ -992,9 +1127,14 @@ err_dev:
static void __exit cleanup_tis(void)
{
struct tpm_chip *chip;
-#ifdef CONFIG_PNP
+#if defined(CONFIG_PNP) || defined(CONFIG_ACPI)
if (!force) {
+#ifdef CONFIG_ACPI
+ acpi_bus_unregister_driver(&tis_acpi_driver);
+#endif
+#ifdef CONFIG_PNP
pnp_unregister_driver(&tis_pnp_driver);
+#endif
return;
}
#endif
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 42f7120ca9ce..c3e3a02f7f1f 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -14,6 +14,7 @@ config COMMON_CLK
select HAVE_CLK_PREPARE
select CLKDEV_LOOKUP
select SRCU
+ select RATIONAL
---help---
The common clock framework is a single definition of struct
clk, useful across many platforms, as well as an
@@ -59,6 +60,16 @@ config COMMON_CLK_RK808
clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
by control register.
+config COMMON_CLK_SCPI
+ tristate "Clock driver controlled via SCPI interface"
+ depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
+ ---help---
+ This driver provides support for clocks that are controlled
+ by firmware that implements the SCPI interface.
+
+ This driver uses SCPI Message Protocol to interact with the
+ firmware providing all the clock controls.
+
config COMMON_CLK_SI5351
tristate "Clock driver for SiLabs 5351A/B/C"
depends on I2C
@@ -68,6 +79,16 @@ config COMMON_CLK_SI5351
This driver supports Silicon Labs 5351A/B/C programmable clock
generators.
+config COMMON_CLK_SI514
+ tristate "Clock driver for SiLabs 514 devices"
+ depends on I2C
+ depends on OF
+ select REGMAP_I2C
+ help
+ ---help---
+ This driver supports the Silicon Labs 514 programmable clock
+ generator.
+
config COMMON_CLK_SI570
tristate "Clock driver for SiLabs 570 and compatible devices"
depends on I2C
@@ -113,7 +134,7 @@ config CLK_TWL6040
config COMMON_CLK_AXI_CLKGEN
tristate "AXI clkgen driver"
- depends on ARCH_ZYNQ || MICROBLAZE
+ depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
help
---help---
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
@@ -121,7 +142,7 @@ config COMMON_CLK_AXI_CLKGEN
config CLK_QORIQ
bool "Clock driver for Freescale QorIQ platforms"
- depends on (PPC_E500MC || ARM) && OF
+ depends on (PPC_E500MC || ARM || ARM64 || COMPILE_TEST) && OF
---help---
This adds the clock driver support for Freescale QorIQ platforms
using common clock framework.
@@ -129,13 +150,13 @@ config CLK_QORIQ
config COMMON_CLK_XGENE
bool "Clock driver for APM XGene SoC"
default y
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
---help---
Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
config COMMON_CLK_KEYSTONE
tristate "Clock drivers for Keystone based SOCs"
- depends on ARCH_KEYSTONE && OF
+ depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
---help---
Supports clock drivers for Keystone based SOCs. These SOCs have local
a power sleep control module that gate the clock to the IPs and PLLs.
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d08b3e5985be..820714c72d36 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-divider.o
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
obj-$(CONFIG_COMMON_CLK) += clk-gate.o
+obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
@@ -19,7 +20,6 @@ endif
obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
-obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
@@ -36,7 +36,9 @@ obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
+obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
@@ -47,7 +49,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
-obj-$(CONFIG_ARCH_BCM) += bcm/
+obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_ARCH_MXC) += imx/
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 89a48a7bd5df..13e67bd35cff 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o
obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
+obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
new file mode 100644
index 000000000000..abc80949e1dd
--- /dev/null
+++ b/drivers/clk/at91/clk-generated.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2015 Atmel Corporation,
+ * Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON.
+ *
+ * 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/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "pmc.h"
+
+#define PERIPHERAL_MAX 64
+#define PERIPHERAL_ID_MIN 2
+
+#define GENERATED_SOURCE_MAX 6
+#define GENERATED_MAX_DIV 255
+
+struct clk_generated {
+ struct clk_hw hw;
+ struct at91_pmc *pmc;
+ struct clk_range range;
+ u32 id;
+ u32 gckdiv;
+ u8 parent_id;
+};
+
+#define to_clk_generated(hw) \
+ container_of(hw, struct clk_generated, hw)
+
+static int clk_generated_enable(struct clk_hw *hw)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+ struct at91_pmc *pmc = gck->pmc;
+ u32 tmp;
+
+ pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
+ __func__, gck->gckdiv, gck->parent_id);
+
+ pmc_lock(pmc);
+ pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
+ tmp = pmc_read(pmc, AT91_PMC_PCR) &
+ ~(AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK);
+ pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_GCKCSS(gck->parent_id)
+ | AT91_PMC_PCR_CMD
+ | AT91_PMC_PCR_GCKDIV(gck->gckdiv)
+ | AT91_PMC_PCR_GCKEN);
+ pmc_unlock(pmc);
+ return 0;
+}
+
+static void clk_generated_disable(struct clk_hw *hw)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+ struct at91_pmc *pmc = gck->pmc;
+ u32 tmp;
+
+ pmc_lock(pmc);
+ pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
+ tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_GCKEN;
+ pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD);
+ pmc_unlock(pmc);
+}
+
+static int clk_generated_is_enabled(struct clk_hw *hw)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+ struct at91_pmc *pmc = gck->pmc;
+ int ret;
+
+ pmc_lock(pmc);
+ pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
+ ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_GCKEN);
+ pmc_unlock(pmc);
+
+ return ret;
+}
+
+static unsigned long
+clk_generated_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+
+ return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1);
+}
+
+static int clk_generated_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+ struct clk_hw *parent = NULL;
+ long best_rate = -EINVAL;
+ unsigned long tmp_rate, min_rate;
+ int best_diff = -1;
+ int tmp_diff;
+ int i;
+
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+ u32 div;
+ unsigned long parent_rate;
+
+ parent = clk_hw_get_parent_by_index(hw, i);
+ if (!parent)
+ continue;
+
+ parent_rate = clk_hw_get_rate(parent);
+ min_rate = DIV_ROUND_CLOSEST(parent_rate, GENERATED_MAX_DIV + 1);
+ if (!parent_rate ||
+ (gck->range.max && min_rate > gck->range.max))
+ continue;
+
+ for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
+ tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
+ tmp_diff = abs(req->rate - tmp_rate);
+
+ if (best_diff < 0 || best_diff > tmp_diff) {
+ best_rate = tmp_rate;
+ best_diff = tmp_diff;
+ req->best_parent_rate = parent_rate;
+ req->best_parent_hw = parent;
+ }
+
+ if (!best_diff || tmp_rate < req->rate)
+ break;
+ }
+
+ if (!best_diff)
+ break;
+ }
+
+ pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
+ __func__, best_rate,
+ __clk_get_name((req->best_parent_hw)->clk),
+ req->best_parent_rate);
+
+ if (best_rate < 0)
+ return best_rate;
+
+ req->rate = best_rate;
+ return 0;
+}
+
+/* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */
+static int clk_generated_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+
+ if (index >= clk_hw_get_num_parents(hw))
+ return -EINVAL;
+
+ gck->parent_id = index;
+ return 0;
+}
+
+static u8 clk_generated_get_parent(struct clk_hw *hw)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+
+ return gck->parent_id;
+}
+
+/* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
+static int clk_generated_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+ u32 div;
+
+ if (!rate)
+ return -EINVAL;
+
+ if (gck->range.max && rate > gck->range.max)
+ return -EINVAL;
+
+ div = DIV_ROUND_CLOSEST(parent_rate, rate);
+ if (div > GENERATED_MAX_DIV + 1 || !div)
+ return -EINVAL;
+
+ gck->gckdiv = div - 1;
+ return 0;
+}
+
+static const struct clk_ops generated_ops = {
+ .enable = clk_generated_enable,
+ .disable = clk_generated_disable,
+ .is_enabled = clk_generated_is_enabled,
+ .recalc_rate = clk_generated_recalc_rate,
+ .determine_rate = clk_generated_determine_rate,
+ .get_parent = clk_generated_get_parent,
+ .set_parent = clk_generated_set_parent,
+ .set_rate = clk_generated_set_rate,
+};
+
+/**
+ * clk_generated_startup - Initialize a given clock to its default parent and
+ * divisor parameter.
+ *
+ * @gck: Generated clock to set the startup parameters for.
+ *
+ * Take parameters from the hardware and update local clock configuration
+ * accordingly.
+ */
+static void clk_generated_startup(struct clk_generated *gck)
+{
+ struct at91_pmc *pmc = gck->pmc;
+ u32 tmp;
+
+ pmc_lock(pmc);
+ pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
+ tmp = pmc_read(pmc, AT91_PMC_PCR);
+ pmc_unlock(pmc);
+
+ gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
+ >> AT91_PMC_PCR_GCKCSS_OFFSET;
+ gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK)
+ >> AT91_PMC_PCR_GCKDIV_OFFSET;
+}
+
+static struct clk * __init
+at91_clk_register_generated(struct at91_pmc *pmc, const char *name,
+ const char **parent_names, u8 num_parents,
+ u8 id, const struct clk_range *range)
+{
+ struct clk_generated *gck;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ gck = kzalloc(sizeof(*gck), GFP_KERNEL);
+ if (!gck)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &generated_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+ gck->id = id;
+ gck->hw.init = &init;
+ gck->pmc = pmc;
+ gck->range = *range;
+
+ clk = clk_register(NULL, &gck->hw);
+ if (IS_ERR(clk))
+ kfree(gck);
+ else
+ clk_generated_startup(gck);
+
+ return clk;
+}
+
+void __init of_sama5d2_clk_generated_setup(struct device_node *np,
+ struct at91_pmc *pmc)
+{
+ int num;
+ u32 id;
+ const char *name;
+ struct clk *clk;
+ int num_parents;
+ const char *parent_names[GENERATED_SOURCE_MAX];
+ struct device_node *gcknp;
+ struct clk_range range = CLK_RANGE(0, 0);
+
+ num_parents = of_clk_get_parent_count(np);
+ if (num_parents <= 0 || num_parents > GENERATED_SOURCE_MAX)
+ return;
+
+ of_clk_parent_fill(np, parent_names, num_parents);
+
+ num = of_get_child_count(np);
+ if (!num || num > PERIPHERAL_MAX)
+ return;
+
+ for_each_child_of_node(np, gcknp) {
+ if (of_property_read_u32(gcknp, "reg", &id))
+ continue;
+
+ if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
+ continue;
+
+ if (of_property_read_string(np, "clock-output-names", &name))
+ name = gcknp->name;
+
+ of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
+ &range);
+
+ clk = at91_clk_register_generated(pmc, name, parent_names,
+ num_parents, id, &range);
+ if (IS_ERR(clk))
+ continue;
+
+ of_clk_add_provider(gcknp, of_clk_src_simple_get, clk);
+ }
+}
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
index e4d7b574f1ea..58f3b568e9cb 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -161,14 +161,18 @@ static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
{
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
struct at91_pmc *pmc = periph->pmc;
+ u32 tmp;
if (periph->id < PERIPHERAL_ID_MIN)
return 0;
- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) |
- AT91_PMC_PCR_CMD |
- AT91_PMC_PCR_DIV(periph->div) |
- AT91_PMC_PCR_EN);
+ pmc_lock(pmc);
+ pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
+ tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_DIV_MASK;
+ pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_DIV(periph->div)
+ | AT91_PMC_PCR_CMD
+ | AT91_PMC_PCR_EN);
+ pmc_unlock(pmc);
return 0;
}
@@ -176,12 +180,16 @@ static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
{
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
struct at91_pmc *pmc = periph->pmc;
+ u32 tmp;
if (periph->id < PERIPHERAL_ID_MIN)
return;
- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) |
- AT91_PMC_PCR_CMD);
+ pmc_lock(pmc);
+ pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
+ tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_EN;
+ pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD);
+ pmc_unlock(pmc);
}
static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
@@ -194,7 +202,7 @@ static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
return 1;
pmc_lock(pmc);
- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID));
+ pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN);
pmc_unlock(pmc);
@@ -213,7 +221,7 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
return parent_rate;
pmc_lock(pmc);
- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID));
+ pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
tmp = pmc_read(pmc, AT91_PMC_PCR);
pmc_unlock(pmc);
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 58008b3e8bc1..3f5314344286 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -138,7 +138,8 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
clk = clk_register(NULL, &sys->hw);
if (IS_ERR(clk)) {
- free_irq(sys->irq, sys);
+ if (irq)
+ free_irq(sys->irq, sys);
kfree(sys);
}
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
index 30dd697b1668..ca561e90a60f 100644
--- a/drivers/clk/at91/clk-utmi.c
+++ b/drivers/clk/at91/clk-utmi.c
@@ -47,7 +47,7 @@ static int clk_utmi_prepare(struct clk_hw *hw)
{
struct clk_utmi *utmi = to_clk_utmi(hw);
struct at91_pmc *pmc = utmi->pmc;
- u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN |
+ u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) | AT91_PMC_UPLLEN |
AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN;
pmc_write(pmc, AT91_CKGR_UCKR, tmp);
@@ -73,7 +73,7 @@ static void clk_utmi_unprepare(struct clk_hw *hw)
{
struct clk_utmi *utmi = to_clk_utmi(hw);
struct at91_pmc *pmc = utmi->pmc;
- u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN;
+ u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN;
pmc_write(pmc, AT91_CKGR_UCKR, tmp);
}
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index d1844f1f3729..8476b570779b 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -206,6 +206,14 @@ static const struct at91_pmc_caps at91sam9x5_caps = {
AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
};
+static const struct at91_pmc_caps sama5d2_caps = {
+ .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
+ AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
+ AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
+ AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS |
+ AT91_PMC_CFDEV | AT91_PMC_GCKRDY,
+};
+
static const struct at91_pmc_caps sama5d3_caps = {
.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
@@ -369,6 +377,12 @@ static const struct of_device_id pmc_clk_ids[] __initconst = {
.data = of_sama5d4_clk_h32mx_setup,
},
#endif
+#if defined(CONFIG_HAVE_AT91_GENERATED_CLK)
+ {
+ .compatible = "atmel,sama5d2-clk-generated",
+ .data = of_sama5d2_clk_generated_setup,
+ },
+#endif
{ /*sentinel*/ }
};
@@ -436,6 +450,13 @@ static void __init of_at91sam9x5_pmc_setup(struct device_node *np)
CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc",
of_at91sam9x5_pmc_setup);
+static void __init of_sama5d2_pmc_setup(struct device_node *np)
+{
+ of_at91_pmc_setup(np, &sama5d2_caps);
+}
+CLK_OF_DECLARE(sama5d2_clk_pmc, "atmel,sama5d2-pmc",
+ of_sama5d2_pmc_setup);
+
static void __init of_sama5d3_pmc_setup(struct device_node *np)
{
of_at91_pmc_setup(np, &sama5d3_caps);
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 8b87771c69b2..f65739272779 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -118,4 +118,7 @@ void of_at91sam9x5_clk_smd_setup(struct device_node *np,
void of_sama5d4_clk_h32mx_setup(struct device_node *np,
struct at91_pmc *pmc);
+void of_sama5d2_clk_generated_setup(struct device_node *np,
+ struct at91_pmc *pmc);
+
#endif /* __PMC_H_ */
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index 88febf53b276..85260fb96b36 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -1,6 +1,6 @@
config CLK_BCM_KONA
bool "Broadcom Kona CCU clock support"
- depends on ARCH_BCM_MOBILE
+ depends on ARCH_BCM_MOBILE || COMPILE_TEST
depends on COMMON_CLK
default y
help
@@ -9,10 +9,8 @@ config CLK_BCM_KONA
in the BCM281xx and BCM21664 families.
config COMMON_CLK_IPROC
- bool "Broadcom iProc clock support"
- depends on ARCH_BCM_IPROC
+ bool
depends on COMMON_CLK
- default ARCH_BCM_IPROC
help
Enable common clock framework support for Broadcom SoCs
based on the iProc architecture
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 8a7a477862c7..3fc95060d875 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -3,4 +3,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
+obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
+obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o
obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
+obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o
+obj-$(CONFIG_ARCH_BCM_5301X) += clk-nsp.o
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
new file mode 100644
index 000000000000..39bf5820297e
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -0,0 +1,1575 @@
+/*
+ * Copyright (C) 2010,2015 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ *
+ * 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
+ */
+
+/**
+ * DOC: BCM2835 CPRMAN (clock manager for the "audio" domain)
+ *
+ * The clock tree on the 2835 has several levels. There's a root
+ * oscillator running at 19.2Mhz. After the oscillator there are 5
+ * PLLs, roughly divided as "camera", "ARM", "core", "DSI displays",
+ * and "HDMI displays". Those 5 PLLs each can divide their output to
+ * produce up to 4 channels. Finally, there is the level of clocks to
+ * be consumed by other hardware components (like "H264" or "HDMI
+ * state machine"), which divide off of some subset of the PLL
+ * channels.
+ *
+ * All of the clocks in the tree are exposed in the DT, because the DT
+ * may want to make assignments of the final layer of clocks to the
+ * PLL channels, and some components of the hardware will actually
+ * skip layers of the tree (for example, the pixel clock comes
+ * directly from the PLLH PIX channel without using a CM_*CTL clock
+ * generator).
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/bcm2835.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/bcm2835.h>
+
+#define CM_PASSWORD 0x5a000000
+
+#define CM_GNRICCTL 0x000
+#define CM_GNRICDIV 0x004
+# define CM_DIV_FRAC_BITS 12
+
+#define CM_VPUCTL 0x008
+#define CM_VPUDIV 0x00c
+#define CM_SYSCTL 0x010
+#define CM_SYSDIV 0x014
+#define CM_PERIACTL 0x018
+#define CM_PERIADIV 0x01c
+#define CM_PERIICTL 0x020
+#define CM_PERIIDIV 0x024
+#define CM_H264CTL 0x028
+#define CM_H264DIV 0x02c
+#define CM_ISPCTL 0x030
+#define CM_ISPDIV 0x034
+#define CM_V3DCTL 0x038
+#define CM_V3DDIV 0x03c
+#define CM_CAM0CTL 0x040
+#define CM_CAM0DIV 0x044
+#define CM_CAM1CTL 0x048
+#define CM_CAM1DIV 0x04c
+#define CM_CCP2CTL 0x050
+#define CM_CCP2DIV 0x054
+#define CM_DSI0ECTL 0x058
+#define CM_DSI0EDIV 0x05c
+#define CM_DSI0PCTL 0x060
+#define CM_DSI0PDIV 0x064
+#define CM_DPICTL 0x068
+#define CM_DPIDIV 0x06c
+#define CM_GP0CTL 0x070
+#define CM_GP0DIV 0x074
+#define CM_GP1CTL 0x078
+#define CM_GP1DIV 0x07c
+#define CM_GP2CTL 0x080
+#define CM_GP2DIV 0x084
+#define CM_HSMCTL 0x088
+#define CM_HSMDIV 0x08c
+#define CM_OTPCTL 0x090
+#define CM_OTPDIV 0x094
+#define CM_PWMCTL 0x0a0
+#define CM_PWMDIV 0x0a4
+#define CM_SMICTL 0x0b0
+#define CM_SMIDIV 0x0b4
+#define CM_TSENSCTL 0x0e0
+#define CM_TSENSDIV 0x0e4
+#define CM_TIMERCTL 0x0e8
+#define CM_TIMERDIV 0x0ec
+#define CM_UARTCTL 0x0f0
+#define CM_UARTDIV 0x0f4
+#define CM_VECCTL 0x0f8
+#define CM_VECDIV 0x0fc
+#define CM_PULSECTL 0x190
+#define CM_PULSEDIV 0x194
+#define CM_SDCCTL 0x1a8
+#define CM_SDCDIV 0x1ac
+#define CM_ARMCTL 0x1b0
+#define CM_EMMCCTL 0x1c0
+#define CM_EMMCDIV 0x1c4
+
+/* General bits for the CM_*CTL regs */
+# define CM_ENABLE BIT(4)
+# define CM_KILL BIT(5)
+# define CM_GATE_BIT 6
+# define CM_GATE BIT(CM_GATE_BIT)
+# define CM_BUSY BIT(7)
+# define CM_BUSYD BIT(8)
+# define CM_SRC_SHIFT 0
+# define CM_SRC_BITS 4
+# define CM_SRC_MASK 0xf
+# define CM_SRC_GND 0
+# define CM_SRC_OSC 1
+# define CM_SRC_TESTDEBUG0 2
+# define CM_SRC_TESTDEBUG1 3
+# define CM_SRC_PLLA_CORE 4
+# define CM_SRC_PLLA_PER 4
+# define CM_SRC_PLLC_CORE0 5
+# define CM_SRC_PLLC_PER 5
+# define CM_SRC_PLLC_CORE1 8
+# define CM_SRC_PLLD_CORE 6
+# define CM_SRC_PLLD_PER 6
+# define CM_SRC_PLLH_AUX 7
+# define CM_SRC_PLLC_CORE1 8
+# define CM_SRC_PLLC_CORE2 9
+
+#define CM_OSCCOUNT 0x100
+
+#define CM_PLLA 0x104
+# define CM_PLL_ANARST BIT(8)
+# define CM_PLLA_HOLDPER BIT(7)
+# define CM_PLLA_LOADPER BIT(6)
+# define CM_PLLA_HOLDCORE BIT(5)
+# define CM_PLLA_LOADCORE BIT(4)
+# define CM_PLLA_HOLDCCP2 BIT(3)
+# define CM_PLLA_LOADCCP2 BIT(2)
+# define CM_PLLA_HOLDDSI0 BIT(1)
+# define CM_PLLA_LOADDSI0 BIT(0)
+
+#define CM_PLLC 0x108
+# define CM_PLLC_HOLDPER BIT(7)
+# define CM_PLLC_LOADPER BIT(6)
+# define CM_PLLC_HOLDCORE2 BIT(5)
+# define CM_PLLC_LOADCORE2 BIT(4)
+# define CM_PLLC_HOLDCORE1 BIT(3)
+# define CM_PLLC_LOADCORE1 BIT(2)
+# define CM_PLLC_HOLDCORE0 BIT(1)
+# define CM_PLLC_LOADCORE0 BIT(0)
+
+#define CM_PLLD 0x10c
+# define CM_PLLD_HOLDPER BIT(7)
+# define CM_PLLD_LOADPER BIT(6)
+# define CM_PLLD_HOLDCORE BIT(5)
+# define CM_PLLD_LOADCORE BIT(4)
+# define CM_PLLD_HOLDDSI1 BIT(3)
+# define CM_PLLD_LOADDSI1 BIT(2)
+# define CM_PLLD_HOLDDSI0 BIT(1)
+# define CM_PLLD_LOADDSI0 BIT(0)
+
+#define CM_PLLH 0x110
+# define CM_PLLH_LOADRCAL BIT(2)
+# define CM_PLLH_LOADAUX BIT(1)
+# define CM_PLLH_LOADPIX BIT(0)
+
+#define CM_LOCK 0x114
+# define CM_LOCK_FLOCKH BIT(12)
+# define CM_LOCK_FLOCKD BIT(11)
+# define CM_LOCK_FLOCKC BIT(10)
+# define CM_LOCK_FLOCKB BIT(9)
+# define CM_LOCK_FLOCKA BIT(8)
+
+#define CM_EVENT 0x118
+#define CM_DSI1ECTL 0x158
+#define CM_DSI1EDIV 0x15c
+#define CM_DSI1PCTL 0x160
+#define CM_DSI1PDIV 0x164
+#define CM_DFTCTL 0x168
+#define CM_DFTDIV 0x16c
+
+#define CM_PLLB 0x170
+# define CM_PLLB_HOLDARM BIT(1)
+# define CM_PLLB_LOADARM BIT(0)
+
+#define A2W_PLLA_CTRL 0x1100
+#define A2W_PLLC_CTRL 0x1120
+#define A2W_PLLD_CTRL 0x1140
+#define A2W_PLLH_CTRL 0x1160
+#define A2W_PLLB_CTRL 0x11e0
+# define A2W_PLL_CTRL_PRST_DISABLE BIT(17)
+# define A2W_PLL_CTRL_PWRDN BIT(16)
+# define A2W_PLL_CTRL_PDIV_MASK 0x000007000
+# define A2W_PLL_CTRL_PDIV_SHIFT 12
+# define A2W_PLL_CTRL_NDIV_MASK 0x0000003ff
+# define A2W_PLL_CTRL_NDIV_SHIFT 0
+
+#define A2W_PLLA_ANA0 0x1010
+#define A2W_PLLC_ANA0 0x1030
+#define A2W_PLLD_ANA0 0x1050
+#define A2W_PLLH_ANA0 0x1070
+#define A2W_PLLB_ANA0 0x10f0
+
+#define A2W_PLL_KA_SHIFT 7
+#define A2W_PLL_KA_MASK GENMASK(9, 7)
+#define A2W_PLL_KI_SHIFT 19
+#define A2W_PLL_KI_MASK GENMASK(21, 19)
+#define A2W_PLL_KP_SHIFT 15
+#define A2W_PLL_KP_MASK GENMASK(18, 15)
+
+#define A2W_PLLH_KA_SHIFT 19
+#define A2W_PLLH_KA_MASK GENMASK(21, 19)
+#define A2W_PLLH_KI_LOW_SHIFT 22
+#define A2W_PLLH_KI_LOW_MASK GENMASK(23, 22)
+#define A2W_PLLH_KI_HIGH_SHIFT 0
+#define A2W_PLLH_KI_HIGH_MASK GENMASK(0, 0)
+#define A2W_PLLH_KP_SHIFT 1
+#define A2W_PLLH_KP_MASK GENMASK(4, 1)
+
+#define A2W_XOSC_CTRL 0x1190
+# define A2W_XOSC_CTRL_PLLB_ENABLE BIT(7)
+# define A2W_XOSC_CTRL_PLLA_ENABLE BIT(6)
+# define A2W_XOSC_CTRL_PLLD_ENABLE BIT(5)
+# define A2W_XOSC_CTRL_DDR_ENABLE BIT(4)
+# define A2W_XOSC_CTRL_CPR1_ENABLE BIT(3)
+# define A2W_XOSC_CTRL_USB_ENABLE BIT(2)
+# define A2W_XOSC_CTRL_HDMI_ENABLE BIT(1)
+# define A2W_XOSC_CTRL_PLLC_ENABLE BIT(0)
+
+#define A2W_PLLA_FRAC 0x1200
+#define A2W_PLLC_FRAC 0x1220
+#define A2W_PLLD_FRAC 0x1240
+#define A2W_PLLH_FRAC 0x1260
+#define A2W_PLLB_FRAC 0x12e0
+# define A2W_PLL_FRAC_MASK ((1 << A2W_PLL_FRAC_BITS) - 1)
+# define A2W_PLL_FRAC_BITS 20
+
+#define A2W_PLL_CHANNEL_DISABLE BIT(8)
+#define A2W_PLL_DIV_BITS 8
+#define A2W_PLL_DIV_SHIFT 0
+
+#define A2W_PLLA_DSI0 0x1300
+#define A2W_PLLA_CORE 0x1400
+#define A2W_PLLA_PER 0x1500
+#define A2W_PLLA_CCP2 0x1600
+
+#define A2W_PLLC_CORE2 0x1320
+#define A2W_PLLC_CORE1 0x1420
+#define A2W_PLLC_PER 0x1520
+#define A2W_PLLC_CORE0 0x1620
+
+#define A2W_PLLD_DSI0 0x1340
+#define A2W_PLLD_CORE 0x1440
+#define A2W_PLLD_PER 0x1540
+#define A2W_PLLD_DSI1 0x1640
+
+#define A2W_PLLH_AUX 0x1360
+#define A2W_PLLH_RCAL 0x1460
+#define A2W_PLLH_PIX 0x1560
+#define A2W_PLLH_STS 0x1660
+
+#define A2W_PLLH_CTRLR 0x1960
+#define A2W_PLLH_FRACR 0x1a60
+#define A2W_PLLH_AUXR 0x1b60
+#define A2W_PLLH_RCALR 0x1c60
+#define A2W_PLLH_PIXR 0x1d60
+#define A2W_PLLH_STSR 0x1e60
+
+#define A2W_PLLB_ARM 0x13e0
+#define A2W_PLLB_SP0 0x14e0
+#define A2W_PLLB_SP1 0x15e0
+#define A2W_PLLB_SP2 0x16e0
+
+#define LOCK_TIMEOUT_NS 100000000
+#define BCM2835_MAX_FB_RATE 1750000000u
+
+struct bcm2835_cprman {
+ struct device *dev;
+ void __iomem *regs;
+ spinlock_t regs_lock;
+ const char *osc_name;
+
+ struct clk_onecell_data onecell;
+ struct clk *clks[BCM2835_CLOCK_COUNT];
+};
+
+static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
+{
+ writel(CM_PASSWORD | val, cprman->regs + reg);
+}
+
+static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg)
+{
+ return readl(cprman->regs + reg);
+}
+
+/*
+ * These are fixed clocks. They're probably not all root clocks and it may
+ * be possible to turn them on and off but until this is mapped out better
+ * it's the only way they can be used.
+ */
+void __init bcm2835_init_clocks(void)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
+ 126000000);
+ if (IS_ERR(clk))
+ pr_err("apb_pclk not registered\n");
+
+ clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
+ 3000000);
+ if (IS_ERR(clk))
+ pr_err("uart0_pclk not registered\n");
+ ret = clk_register_clkdev(clk, NULL, "20201000.uart");
+ if (ret)
+ pr_err("uart0_pclk alias not registered\n");
+
+ clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
+ 125000000);
+ if (IS_ERR(clk))
+ pr_err("uart1_pclk not registered\n");
+ ret = clk_register_clkdev(clk, NULL, "20215000.uart");
+ if (ret)
+ pr_err("uart1_pclk alias not registered\n");
+}
+
+struct bcm2835_pll_data {
+ const char *name;
+ u32 cm_ctrl_reg;
+ u32 a2w_ctrl_reg;
+ u32 frac_reg;
+ u32 ana_reg_base;
+ u32 reference_enable_mask;
+ /* Bit in CM_LOCK to indicate when the PLL has locked. */
+ u32 lock_mask;
+
+ const struct bcm2835_pll_ana_bits *ana;
+
+ unsigned long min_rate;
+ unsigned long max_rate;
+ /*
+ * Highest rate for the VCO before we have to use the
+ * pre-divide-by-2.
+ */
+ unsigned long max_fb_rate;
+};
+
+struct bcm2835_pll_ana_bits {
+ u32 mask0;
+ u32 set0;
+ u32 mask1;
+ u32 set1;
+ u32 mask3;
+ u32 set3;
+ u32 fb_prediv_mask;
+};
+
+static const struct bcm2835_pll_ana_bits bcm2835_ana_default = {
+ .mask0 = 0,
+ .set0 = 0,
+ .mask1 = ~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK),
+ .set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
+ .mask3 = ~A2W_PLL_KA_MASK,
+ .set3 = (2 << A2W_PLL_KA_SHIFT),
+ .fb_prediv_mask = BIT(14),
+};
+
+static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
+ .mask0 = ~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK),
+ .set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
+ .mask1 = ~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK),
+ .set1 = (6 << A2W_PLLH_KP_SHIFT),
+ .mask3 = 0,
+ .set3 = 0,
+ .fb_prediv_mask = BIT(11),
+};
+
+/*
+ * PLLA is the auxiliary PLL, used to drive the CCP2 (Compact Camera
+ * Port 2) transmitter clock.
+ *
+ * It is in the PX LDO power domain, which is on when the AUDIO domain
+ * is on.
+ */
+static const struct bcm2835_pll_data bcm2835_plla_data = {
+ .name = "plla",
+ .cm_ctrl_reg = CM_PLLA,
+ .a2w_ctrl_reg = A2W_PLLA_CTRL,
+ .frac_reg = A2W_PLLA_FRAC,
+ .ana_reg_base = A2W_PLLA_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKA,
+
+ .ana = &bcm2835_ana_default,
+
+ .min_rate = 600000000u,
+ .max_rate = 2400000000u,
+ .max_fb_rate = BCM2835_MAX_FB_RATE,
+};
+
+/* PLLB is used for the ARM's clock. */
+static const struct bcm2835_pll_data bcm2835_pllb_data = {
+ .name = "pllb",
+ .cm_ctrl_reg = CM_PLLB,
+ .a2w_ctrl_reg = A2W_PLLB_CTRL,
+ .frac_reg = A2W_PLLB_FRAC,
+ .ana_reg_base = A2W_PLLB_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKB,
+
+ .ana = &bcm2835_ana_default,
+
+ .min_rate = 600000000u,
+ .max_rate = 3000000000u,
+ .max_fb_rate = BCM2835_MAX_FB_RATE,
+};
+
+/*
+ * PLLC is the core PLL, used to drive the core VPU clock.
+ *
+ * It is in the PX LDO power domain, which is on when the AUDIO domain
+ * is on.
+*/
+static const struct bcm2835_pll_data bcm2835_pllc_data = {
+ .name = "pllc",
+ .cm_ctrl_reg = CM_PLLC,
+ .a2w_ctrl_reg = A2W_PLLC_CTRL,
+ .frac_reg = A2W_PLLC_FRAC,
+ .ana_reg_base = A2W_PLLC_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKC,
+
+ .ana = &bcm2835_ana_default,
+
+ .min_rate = 600000000u,
+ .max_rate = 3000000000u,
+ .max_fb_rate = BCM2835_MAX_FB_RATE,
+};
+
+/*
+ * PLLD is the display PLL, used to drive DSI display panels.
+ *
+ * It is in the PX LDO power domain, which is on when the AUDIO domain
+ * is on.
+ */
+static const struct bcm2835_pll_data bcm2835_plld_data = {
+ .name = "plld",
+ .cm_ctrl_reg = CM_PLLD,
+ .a2w_ctrl_reg = A2W_PLLD_CTRL,
+ .frac_reg = A2W_PLLD_FRAC,
+ .ana_reg_base = A2W_PLLD_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKD,
+
+ .ana = &bcm2835_ana_default,
+
+ .min_rate = 600000000u,
+ .max_rate = 2400000000u,
+ .max_fb_rate = BCM2835_MAX_FB_RATE,
+};
+
+/*
+ * PLLH is used to supply the pixel clock or the AUX clock for the TV
+ * encoder.
+ *
+ * It is in the HDMI power domain.
+ */
+static const struct bcm2835_pll_data bcm2835_pllh_data = {
+ "pllh",
+ .cm_ctrl_reg = CM_PLLH,
+ .a2w_ctrl_reg = A2W_PLLH_CTRL,
+ .frac_reg = A2W_PLLH_FRAC,
+ .ana_reg_base = A2W_PLLH_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKH,
+
+ .ana = &bcm2835_ana_pllh,
+
+ .min_rate = 600000000u,
+ .max_rate = 3000000000u,
+ .max_fb_rate = BCM2835_MAX_FB_RATE,
+};
+
+struct bcm2835_pll_divider_data {
+ const char *name;
+ const struct bcm2835_pll_data *source_pll;
+ u32 cm_reg;
+ u32 a2w_reg;
+
+ u32 load_mask;
+ u32 hold_mask;
+ u32 fixed_divider;
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_plla_core_data = {
+ .name = "plla_core",
+ .source_pll = &bcm2835_plla_data,
+ .cm_reg = CM_PLLA,
+ .a2w_reg = A2W_PLLA_CORE,
+ .load_mask = CM_PLLA_LOADCORE,
+ .hold_mask = CM_PLLA_HOLDCORE,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_plla_per_data = {
+ .name = "plla_per",
+ .source_pll = &bcm2835_plla_data,
+ .cm_reg = CM_PLLA,
+ .a2w_reg = A2W_PLLA_PER,
+ .load_mask = CM_PLLA_LOADPER,
+ .hold_mask = CM_PLLA_HOLDPER,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllb_arm_data = {
+ .name = "pllb_arm",
+ .source_pll = &bcm2835_pllb_data,
+ .cm_reg = CM_PLLB,
+ .a2w_reg = A2W_PLLB_ARM,
+ .load_mask = CM_PLLB_LOADARM,
+ .hold_mask = CM_PLLB_HOLDARM,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllc_core0_data = {
+ .name = "pllc_core0",
+ .source_pll = &bcm2835_pllc_data,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_CORE0,
+ .load_mask = CM_PLLC_LOADCORE0,
+ .hold_mask = CM_PLLC_HOLDCORE0,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllc_core1_data = {
+ .name = "pllc_core1", .source_pll = &bcm2835_pllc_data,
+ .cm_reg = CM_PLLC, A2W_PLLC_CORE1,
+ .load_mask = CM_PLLC_LOADCORE1,
+ .hold_mask = CM_PLLC_HOLDCORE1,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllc_core2_data = {
+ .name = "pllc_core2",
+ .source_pll = &bcm2835_pllc_data,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_CORE2,
+ .load_mask = CM_PLLC_LOADCORE2,
+ .hold_mask = CM_PLLC_HOLDCORE2,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllc_per_data = {
+ .name = "pllc_per",
+ .source_pll = &bcm2835_pllc_data,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_PER,
+ .load_mask = CM_PLLC_LOADPER,
+ .hold_mask = CM_PLLC_HOLDPER,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_plld_core_data = {
+ .name = "plld_core",
+ .source_pll = &bcm2835_plld_data,
+ .cm_reg = CM_PLLD,
+ .a2w_reg = A2W_PLLD_CORE,
+ .load_mask = CM_PLLD_LOADCORE,
+ .hold_mask = CM_PLLD_HOLDCORE,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_plld_per_data = {
+ .name = "plld_per",
+ .source_pll = &bcm2835_plld_data,
+ .cm_reg = CM_PLLD,
+ .a2w_reg = A2W_PLLD_PER,
+ .load_mask = CM_PLLD_LOADPER,
+ .hold_mask = CM_PLLD_HOLDPER,
+ .fixed_divider = 1,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllh_rcal_data = {
+ .name = "pllh_rcal",
+ .source_pll = &bcm2835_pllh_data,
+ .cm_reg = CM_PLLH,
+ .a2w_reg = A2W_PLLH_RCAL,
+ .load_mask = CM_PLLH_LOADRCAL,
+ .hold_mask = 0,
+ .fixed_divider = 10,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllh_aux_data = {
+ .name = "pllh_aux",
+ .source_pll = &bcm2835_pllh_data,
+ .cm_reg = CM_PLLH,
+ .a2w_reg = A2W_PLLH_AUX,
+ .load_mask = CM_PLLH_LOADAUX,
+ .hold_mask = 0,
+ .fixed_divider = 10,
+};
+
+static const struct bcm2835_pll_divider_data bcm2835_pllh_pix_data = {
+ .name = "pllh_pix",
+ .source_pll = &bcm2835_pllh_data,
+ .cm_reg = CM_PLLH,
+ .a2w_reg = A2W_PLLH_PIX,
+ .load_mask = CM_PLLH_LOADPIX,
+ .hold_mask = 0,
+ .fixed_divider = 10,
+};
+
+struct bcm2835_clock_data {
+ const char *name;
+
+ const char *const *parents;
+ int num_mux_parents;
+
+ u32 ctl_reg;
+ u32 div_reg;
+
+ /* Number of integer bits in the divider */
+ u32 int_bits;
+ /* Number of fractional bits in the divider */
+ u32 frac_bits;
+
+ bool is_vpu_clock;
+};
+
+static const char *const bcm2835_clock_per_parents[] = {
+ "gnd",
+ "xosc",
+ "testdebug0",
+ "testdebug1",
+ "plla_per",
+ "pllc_per",
+ "plld_per",
+ "pllh_aux",
+};
+
+static const char *const bcm2835_clock_vpu_parents[] = {
+ "gnd",
+ "xosc",
+ "testdebug0",
+ "testdebug1",
+ "plla_core",
+ "pllc_core0",
+ "plld_core",
+ "pllh_aux",
+ "pllc_core1",
+ "pllc_core2",
+};
+
+static const char *const bcm2835_clock_osc_parents[] = {
+ "gnd",
+ "xosc",
+ "testdebug0",
+ "testdebug1"
+};
+
+/*
+ * Used for a 1Mhz clock for the system clocksource, and also used by
+ * the watchdog timer and the camera pulse generator.
+ */
+static const struct bcm2835_clock_data bcm2835_clock_timer_data = {
+ .name = "timer",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
+ .parents = bcm2835_clock_osc_parents,
+ .ctl_reg = CM_TIMERCTL,
+ .div_reg = CM_TIMERDIV,
+ .int_bits = 6,
+ .frac_bits = 12,
+};
+
+/* One Time Programmable Memory clock. Maximum 10Mhz. */
+static const struct bcm2835_clock_data bcm2835_clock_otp_data = {
+ .name = "otp",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
+ .parents = bcm2835_clock_osc_parents,
+ .ctl_reg = CM_OTPCTL,
+ .div_reg = CM_OTPDIV,
+ .int_bits = 4,
+ .frac_bits = 0,
+};
+
+/*
+ * VPU clock. This doesn't have an enable bit, since it drives the
+ * bus for everything else, and is special so it doesn't need to be
+ * gated for rate changes. It is also known as "clk_audio" in various
+ * hardware documentation.
+ */
+static const struct bcm2835_clock_data bcm2835_clock_vpu_data = {
+ .name = "vpu",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
+ .parents = bcm2835_clock_vpu_parents,
+ .ctl_reg = CM_VPUCTL,
+ .div_reg = CM_VPUDIV,
+ .int_bits = 12,
+ .frac_bits = 8,
+ .is_vpu_clock = true,
+};
+
+static const struct bcm2835_clock_data bcm2835_clock_v3d_data = {
+ .name = "v3d",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
+ .parents = bcm2835_clock_vpu_parents,
+ .ctl_reg = CM_V3DCTL,
+ .div_reg = CM_V3DDIV,
+ .int_bits = 4,
+ .frac_bits = 8,
+};
+
+static const struct bcm2835_clock_data bcm2835_clock_isp_data = {
+ .name = "isp",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
+ .parents = bcm2835_clock_vpu_parents,
+ .ctl_reg = CM_ISPCTL,
+ .div_reg = CM_ISPDIV,
+ .int_bits = 4,
+ .frac_bits = 8,
+};
+
+static const struct bcm2835_clock_data bcm2835_clock_h264_data = {
+ .name = "h264",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
+ .parents = bcm2835_clock_vpu_parents,
+ .ctl_reg = CM_H264CTL,
+ .div_reg = CM_H264DIV,
+ .int_bits = 4,
+ .frac_bits = 8,
+};
+
+/* TV encoder clock. Only operating frequency is 108Mhz. */
+static const struct bcm2835_clock_data bcm2835_clock_vec_data = {
+ .name = "vec",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
+ .parents = bcm2835_clock_per_parents,
+ .ctl_reg = CM_VECCTL,
+ .div_reg = CM_VECDIV,
+ .int_bits = 4,
+ .frac_bits = 0,
+};
+
+static const struct bcm2835_clock_data bcm2835_clock_uart_data = {
+ .name = "uart",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
+ .parents = bcm2835_clock_per_parents,
+ .ctl_reg = CM_UARTCTL,
+ .div_reg = CM_UARTDIV,
+ .int_bits = 10,
+ .frac_bits = 12,
+};
+
+/* HDMI state machine */
+static const struct bcm2835_clock_data bcm2835_clock_hsm_data = {
+ .name = "hsm",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
+ .parents = bcm2835_clock_per_parents,
+ .ctl_reg = CM_HSMCTL,
+ .div_reg = CM_HSMDIV,
+ .int_bits = 4,
+ .frac_bits = 8,
+};
+
+/*
+ * Secondary SDRAM clock. Used for low-voltage modes when the PLL in
+ * the SDRAM controller can't be used.
+ */
+static const struct bcm2835_clock_data bcm2835_clock_sdram_data = {
+ .name = "sdram",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
+ .parents = bcm2835_clock_vpu_parents,
+ .ctl_reg = CM_SDCCTL,
+ .div_reg = CM_SDCDIV,
+ .int_bits = 6,
+ .frac_bits = 0,
+};
+
+/* Clock for the temperature sensor. Generally run at 2Mhz, max 5Mhz. */
+static const struct bcm2835_clock_data bcm2835_clock_tsens_data = {
+ .name = "tsens",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
+ .parents = bcm2835_clock_osc_parents,
+ .ctl_reg = CM_TSENSCTL,
+ .div_reg = CM_TSENSDIV,
+ .int_bits = 5,
+ .frac_bits = 0,
+};
+
+/* Arasan EMMC clock */
+static const struct bcm2835_clock_data bcm2835_clock_emmc_data = {
+ .name = "emmc",
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
+ .parents = bcm2835_clock_per_parents,
+ .ctl_reg = CM_EMMCCTL,
+ .div_reg = CM_EMMCDIV,
+ .int_bits = 4,
+ .frac_bits = 8,
+};
+
+struct bcm2835_pll {
+ struct clk_hw hw;
+ struct bcm2835_cprman *cprman;
+ const struct bcm2835_pll_data *data;
+};
+
+static int bcm2835_pll_is_on(struct clk_hw *hw)
+{
+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+ struct bcm2835_cprman *cprman = pll->cprman;
+ const struct bcm2835_pll_data *data = pll->data;
+
+ return cprman_read(cprman, data->a2w_ctrl_reg) &
+ A2W_PLL_CTRL_PRST_DISABLE;
+}
+
+static void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate,
+ unsigned long parent_rate,
+ u32 *ndiv, u32 *fdiv)
+{
+ u64 div;
+
+ div = (u64)rate << A2W_PLL_FRAC_BITS;
+ do_div(div, parent_rate);
+
+ *ndiv = div >> A2W_PLL_FRAC_BITS;
+ *fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
+}
+
+static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
+ u32 ndiv, u32 fdiv, u32 pdiv)
+{
+ u64 rate;
+
+ if (pdiv == 0)
+ return 0;
+
+ rate = (u64)parent_rate * ((ndiv << A2W_PLL_FRAC_BITS) + fdiv);
+ do_div(rate, pdiv);
+ return rate >> A2W_PLL_FRAC_BITS;
+}
+
+static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u32 ndiv, fdiv;
+
+ bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
+
+ return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
+}
+
+static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+ struct bcm2835_cprman *cprman = pll->cprman;
+ const struct bcm2835_pll_data *data = pll->data;
+ u32 a2wctrl = cprman_read(cprman, data->a2w_ctrl_reg);
+ u32 ndiv, pdiv, fdiv;
+ bool using_prediv;
+
+ if (parent_rate == 0)
+ return 0;
+
+ fdiv = cprman_read(cprman, data->frac_reg) & A2W_PLL_FRAC_MASK;
+ ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;
+ pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;
+ using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
+ data->ana->fb_prediv_mask;
+
+ if (using_prediv)
+ ndiv *= 2;
+
+ return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv);
+}
+
+static void bcm2835_pll_off(struct clk_hw *hw)
+{
+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+ struct bcm2835_cprman *cprman = pll->cprman;
+ const struct bcm2835_pll_data *data = pll->data;
+
+ cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
+ cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
+}
+
+static int bcm2835_pll_on(struct clk_hw *hw)
+{
+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+ struct bcm2835_cprman *cprman = pll->cprman;
+ const struct bcm2835_pll_data *data = pll->data;
+ ktime_t timeout;
+
+ /* Take the PLL out of reset. */
+ cprman_write(cprman, data->cm_ctrl_reg,
+ cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
+
+ /* Wait for the PLL to lock. */
+ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
+ while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
+ if (ktime_after(ktime_get(), timeout)) {
+ dev_err(cprman->dev, "%s: couldn't lock PLL\n",
+ clk_hw_get_name(hw));
+ return -ETIMEDOUT;
+ }
+
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static void
+bcm2835_pll_write_ana(struct bcm2835_cprman *cprman, u32 ana_reg_base, u32 *ana)
+{
+ int i;
+
+ /*
+ * ANA register setup is done as a series of writes to
+ * ANA3-ANA0, in that order. This lets us write all 4
+ * registers as a single cycle of the serdes interface (taking
+ * 100 xosc clocks), whereas if we were to update ana0, 1, and
+ * 3 individually through their partial-write registers, each
+ * would be their own serdes cycle.
+ */
+ for (i = 3; i >= 0; i--)
+ cprman_write(cprman, ana_reg_base + i * 4, ana[i]);
+}
+
+static int bcm2835_pll_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+ struct bcm2835_cprman *cprman = pll->cprman;
+ const struct bcm2835_pll_data *data = pll->data;
+ bool was_using_prediv, use_fb_prediv, do_ana_setup_first;
+ u32 ndiv, fdiv, a2w_ctl;
+ u32 ana[4];
+ int i;
+
+ if (rate < data->min_rate || rate > data->max_rate) {
+ dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n",
+ clk_hw_get_name(hw), rate,
+ data->min_rate, data->max_rate);
+ return -EINVAL;
+ }
+
+ if (rate > data->max_fb_rate) {
+ use_fb_prediv = true;
+ rate /= 2;
+ } else {
+ use_fb_prediv = false;
+ }
+
+ bcm2835_pll_choose_ndiv_and_fdiv(rate, parent_rate, &ndiv, &fdiv);
+
+ for (i = 3; i >= 0; i--)
+ ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);
+
+ was_using_prediv = ana[1] & data->ana->fb_prediv_mask;
+
+ ana[0] &= ~data->ana->mask0;
+ ana[0] |= data->ana->set0;
+ ana[1] &= ~data->ana->mask1;
+ ana[1] |= data->ana->set1;
+ ana[3] &= ~data->ana->mask3;
+ ana[3] |= data->ana->set3;
+
+ if (was_using_prediv && !use_fb_prediv) {
+ ana[1] &= ~data->ana->fb_prediv_mask;
+ do_ana_setup_first = true;
+ } else if (!was_using_prediv && use_fb_prediv) {
+ ana[1] |= data->ana->fb_prediv_mask;
+ do_ana_setup_first = false;
+ } else {
+ do_ana_setup_first = true;
+ }
+
+ /* Unmask the reference clock from the oscillator. */
+ cprman_write(cprman, A2W_XOSC_CTRL,
+ cprman_read(cprman, A2W_XOSC_CTRL) |
+ data->reference_enable_mask);
+
+ if (do_ana_setup_first)
+ bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
+
+ /* Set the PLL multiplier from the oscillator. */
+ cprman_write(cprman, data->frac_reg, fdiv);
+
+ a2w_ctl = cprman_read(cprman, data->a2w_ctrl_reg);
+ a2w_ctl &= ~A2W_PLL_CTRL_NDIV_MASK;
+ a2w_ctl |= ndiv << A2W_PLL_CTRL_NDIV_SHIFT;
+ a2w_ctl &= ~A2W_PLL_CTRL_PDIV_MASK;
+ a2w_ctl |= 1 << A2W_PLL_CTRL_PDIV_SHIFT;
+ cprman_write(cprman, data->a2w_ctrl_reg, a2w_ctl);
+
+ if (!do_ana_setup_first)
+ bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
+
+ return 0;
+}
+
+static const struct clk_ops bcm2835_pll_clk_ops = {
+ .is_prepared = bcm2835_pll_is_on,
+ .prepare = bcm2835_pll_on,
+ .unprepare = bcm2835_pll_off,
+ .recalc_rate = bcm2835_pll_get_rate,
+ .set_rate = bcm2835_pll_set_rate,
+ .round_rate = bcm2835_pll_round_rate,
+};
+
+struct bcm2835_pll_divider {
+ struct clk_divider div;
+ struct bcm2835_cprman *cprman;
+ const struct bcm2835_pll_divider_data *data;
+};
+
+static struct bcm2835_pll_divider *
+bcm2835_pll_divider_from_hw(struct clk_hw *hw)
+{
+ return container_of(hw, struct bcm2835_pll_divider, div.hw);
+}
+
+static int bcm2835_pll_divider_is_on(struct clk_hw *hw)
+{
+ struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+ struct bcm2835_cprman *cprman = divider->cprman;
+ const struct bcm2835_pll_divider_data *data = divider->data;
+
+ return !(cprman_read(cprman, data->a2w_reg) & A2W_PLL_CHANNEL_DISABLE);
+}
+
+static long bcm2835_pll_divider_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return clk_divider_ops.round_rate(hw, rate, parent_rate);
+}
+
+static unsigned long bcm2835_pll_divider_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+ struct bcm2835_cprman *cprman = divider->cprman;
+ const struct bcm2835_pll_divider_data *data = divider->data;
+ u32 div = cprman_read(cprman, data->a2w_reg);
+
+ div &= (1 << A2W_PLL_DIV_BITS) - 1;
+ if (div == 0)
+ div = 256;
+
+ return parent_rate / div;
+}
+
+static void bcm2835_pll_divider_off(struct clk_hw *hw)
+{
+ struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+ struct bcm2835_cprman *cprman = divider->cprman;
+ const struct bcm2835_pll_divider_data *data = divider->data;
+
+ cprman_write(cprman, data->cm_reg,
+ (cprman_read(cprman, data->cm_reg) &
+ ~data->load_mask) | data->hold_mask);
+ cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+}
+
+static int bcm2835_pll_divider_on(struct clk_hw *hw)
+{
+ struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+ struct bcm2835_cprman *cprman = divider->cprman;
+ const struct bcm2835_pll_divider_data *data = divider->data;
+
+ cprman_write(cprman, data->a2w_reg,
+ cprman_read(cprman, data->a2w_reg) &
+ ~A2W_PLL_CHANNEL_DISABLE);
+
+ cprman_write(cprman, data->cm_reg,
+ cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
+
+ return 0;
+}
+
+static int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+ struct bcm2835_cprman *cprman = divider->cprman;
+ const struct bcm2835_pll_divider_data *data = divider->data;
+ u32 cm;
+ int ret;
+
+ ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
+ if (ret)
+ return ret;
+
+ cm = cprman_read(cprman, data->cm_reg);
+ cprman_write(cprman, data->cm_reg, cm | data->load_mask);
+ cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);
+
+ return 0;
+}
+
+static const struct clk_ops bcm2835_pll_divider_clk_ops = {
+ .is_prepared = bcm2835_pll_divider_is_on,
+ .prepare = bcm2835_pll_divider_on,
+ .unprepare = bcm2835_pll_divider_off,
+ .recalc_rate = bcm2835_pll_divider_get_rate,
+ .set_rate = bcm2835_pll_divider_set_rate,
+ .round_rate = bcm2835_pll_divider_round_rate,
+};
+
+/*
+ * The CM dividers do fixed-point division, so we can't use the
+ * generic integer divider code like the PLL dividers do (and we can't
+ * fake it by having some fixed shifts preceding it in the clock tree,
+ * because we'd run out of bits in a 32-bit unsigned long).
+ */
+struct bcm2835_clock {
+ struct clk_hw hw;
+ struct bcm2835_cprman *cprman;
+ const struct bcm2835_clock_data *data;
+};
+
+static struct bcm2835_clock *bcm2835_clock_from_hw(struct clk_hw *hw)
+{
+ return container_of(hw, struct bcm2835_clock, hw);
+}
+
+static int bcm2835_clock_is_on(struct clk_hw *hw)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+
+ return (cprman_read(cprman, data->ctl_reg) & CM_ENABLE) != 0;
+}
+
+static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ const struct bcm2835_clock_data *data = clock->data;
+ u32 unused_frac_mask = GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0);
+ u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
+ u32 div;
+
+ do_div(temp, rate);
+ div = temp;
+
+ /* Round and mask off the unused bits */
+ if (unused_frac_mask != 0) {
+ div += unused_frac_mask >> 1;
+ div &= ~unused_frac_mask;
+ }
+
+ /* Clamp to the limits. */
+ div = max(div, unused_frac_mask + 1);
+ div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
+ CM_DIV_FRAC_BITS - data->frac_bits));
+
+ return div;
+}
+
+static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
+ unsigned long parent_rate,
+ u32 div)
+{
+ const struct bcm2835_clock_data *data = clock->data;
+ u64 temp;
+
+ /*
+ * The divisor is a 12.12 fixed point field, but only some of
+ * the bits are populated in any given clock.
+ */
+ div >>= CM_DIV_FRAC_BITS - data->frac_bits;
+ div &= (1 << (data->int_bits + data->frac_bits)) - 1;
+
+ if (div == 0)
+ return 0;
+
+ temp = (u64)parent_rate << data->frac_bits;
+
+ do_div(temp, div);
+
+ return temp;
+}
+
+static long bcm2835_clock_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ u32 div = bcm2835_clock_choose_div(hw, rate, *parent_rate);
+
+ return bcm2835_clock_rate_from_divisor(clock, *parent_rate, div);
+}
+
+static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+ u32 div = cprman_read(cprman, data->div_reg);
+
+ return bcm2835_clock_rate_from_divisor(clock, parent_rate, div);
+}
+
+static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
+{
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+ ktime_t timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
+
+ while (cprman_read(cprman, data->ctl_reg) & CM_BUSY) {
+ if (ktime_after(ktime_get(), timeout)) {
+ dev_err(cprman->dev, "%s: couldn't lock PLL\n",
+ clk_hw_get_name(&clock->hw));
+ return;
+ }
+ cpu_relax();
+ }
+}
+
+static void bcm2835_clock_off(struct clk_hw *hw)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+
+ spin_lock(&cprman->regs_lock);
+ cprman_write(cprman, data->ctl_reg,
+ cprman_read(cprman, data->ctl_reg) & ~CM_ENABLE);
+ spin_unlock(&cprman->regs_lock);
+
+ /* BUSY will remain high until the divider completes its cycle. */
+ bcm2835_clock_wait_busy(clock);
+}
+
+static int bcm2835_clock_on(struct clk_hw *hw)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+
+ spin_lock(&cprman->regs_lock);
+ cprman_write(cprman, data->ctl_reg,
+ cprman_read(cprman, data->ctl_reg) |
+ CM_ENABLE |
+ CM_GATE);
+ spin_unlock(&cprman->regs_lock);
+
+ return 0;
+}
+
+static int bcm2835_clock_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+ u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
+
+ cprman_write(cprman, data->div_reg, div);
+
+ return 0;
+}
+
+static const struct clk_ops bcm2835_clock_clk_ops = {
+ .is_prepared = bcm2835_clock_is_on,
+ .prepare = bcm2835_clock_on,
+ .unprepare = bcm2835_clock_off,
+ .recalc_rate = bcm2835_clock_get_rate,
+ .set_rate = bcm2835_clock_set_rate,
+ .round_rate = bcm2835_clock_round_rate,
+};
+
+static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
+{
+ return true;
+}
+
+/*
+ * The VPU clock can never be disabled (it doesn't have an ENABLE
+ * bit), so it gets its own set of clock ops.
+ */
+static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
+ .is_prepared = bcm2835_vpu_clock_is_on,
+ .recalc_rate = bcm2835_clock_get_rate,
+ .set_rate = bcm2835_clock_set_rate,
+ .round_rate = bcm2835_clock_round_rate,
+};
+
+static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
+ const struct bcm2835_pll_data *data)
+{
+ struct bcm2835_pll *pll;
+ struct clk_init_data init;
+
+ memset(&init, 0, sizeof(init));
+
+ /* All of the PLLs derive from the external oscillator. */
+ init.parent_names = &cprman->osc_name;
+ init.num_parents = 1;
+ init.name = data->name;
+ init.ops = &bcm2835_pll_clk_ops;
+ init.flags = CLK_IGNORE_UNUSED;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return NULL;
+
+ pll->cprman = cprman;
+ pll->data = data;
+ pll->hw.init = &init;
+
+ return devm_clk_register(cprman->dev, &pll->hw);
+}
+
+static struct clk *
+bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
+ const struct bcm2835_pll_divider_data *data)
+{
+ struct bcm2835_pll_divider *divider;
+ struct clk_init_data init;
+ struct clk *clk;
+ const char *divider_name;
+
+ if (data->fixed_divider != 1) {
+ divider_name = devm_kasprintf(cprman->dev, GFP_KERNEL,
+ "%s_prediv", data->name);
+ if (!divider_name)
+ return NULL;
+ } else {
+ divider_name = data->name;
+ }
+
+ memset(&init, 0, sizeof(init));
+
+ init.parent_names = &data->source_pll->name;
+ init.num_parents = 1;
+ init.name = divider_name;
+ init.ops = &bcm2835_pll_divider_clk_ops;
+ init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED;
+
+ divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL);
+ if (!divider)
+ return NULL;
+
+ divider->div.reg = cprman->regs + data->a2w_reg;
+ divider->div.shift = A2W_PLL_DIV_SHIFT;
+ divider->div.width = A2W_PLL_DIV_BITS;
+ divider->div.flags = 0;
+ divider->div.lock = &cprman->regs_lock;
+ divider->div.hw.init = &init;
+ divider->div.table = NULL;
+
+ divider->cprman = cprman;
+ divider->data = data;
+
+ clk = devm_clk_register(cprman->dev, &divider->div.hw);
+ if (IS_ERR(clk))
+ return clk;
+
+ /*
+ * PLLH's channels have a fixed divide by 10 afterwards, which
+ * is what our consumers are actually using.
+ */
+ if (data->fixed_divider != 1) {
+ return clk_register_fixed_factor(cprman->dev, data->name,
+ divider_name,
+ CLK_SET_RATE_PARENT,
+ 1,
+ data->fixed_divider);
+ }
+
+ return clk;
+}
+
+static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
+ const struct bcm2835_clock_data *data)
+{
+ struct bcm2835_clock *clock;
+ struct clk_init_data init;
+ const char *parent;
+
+ /*
+ * Most of the clock generators have a mux field, so we
+ * instantiate a generic mux as our parent to handle it.
+ */
+ if (data->num_mux_parents) {
+ const char *parents[1 << CM_SRC_BITS];
+ int i;
+
+ parent = devm_kasprintf(cprman->dev, GFP_KERNEL,
+ "mux_%s", data->name);
+ if (!parent)
+ return NULL;
+
+ /*
+ * Replace our "xosc" references with the oscillator's
+ * actual name.
+ */
+ for (i = 0; i < data->num_mux_parents; i++) {
+ if (strcmp(data->parents[i], "xosc") == 0)
+ parents[i] = cprman->osc_name;
+ else
+ parents[i] = data->parents[i];
+ }
+
+ clk_register_mux(cprman->dev, parent,
+ parents, data->num_mux_parents,
+ CLK_SET_RATE_PARENT,
+ cprman->regs + data->ctl_reg,
+ CM_SRC_SHIFT, CM_SRC_BITS,
+ 0, &cprman->regs_lock);
+ } else {
+ parent = data->parents[0];
+ }
+
+ memset(&init, 0, sizeof(init));
+ init.parent_names = &parent;
+ init.num_parents = 1;
+ init.name = data->name;
+ init.flags = CLK_IGNORE_UNUSED;
+
+ if (data->is_vpu_clock) {
+ init.ops = &bcm2835_vpu_clock_clk_ops;
+ } else {
+ init.ops = &bcm2835_clock_clk_ops;
+ init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+ }
+
+ clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
+ if (!clock)
+ return NULL;
+
+ clock->cprman = cprman;
+ clock->data = data;
+ clock->hw.init = &init;
+
+ return devm_clk_register(cprman->dev, &clock->hw);
+}
+
+static int bcm2835_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct clk **clks;
+ struct bcm2835_cprman *cprman;
+ struct resource *res;
+
+ cprman = devm_kzalloc(dev, sizeof(*cprman), GFP_KERNEL);
+ if (!cprman)
+ return -ENOMEM;
+
+ spin_lock_init(&cprman->regs_lock);
+ cprman->dev = dev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ cprman->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(cprman->regs))
+ return PTR_ERR(cprman->regs);
+
+ cprman->osc_name = of_clk_get_parent_name(dev->of_node, 0);
+ if (!cprman->osc_name)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, cprman);
+
+ cprman->onecell.clk_num = BCM2835_CLOCK_COUNT;
+ cprman->onecell.clks = cprman->clks;
+ clks = cprman->clks;
+
+ clks[BCM2835_PLLA] = bcm2835_register_pll(cprman, &bcm2835_plla_data);
+ clks[BCM2835_PLLB] = bcm2835_register_pll(cprman, &bcm2835_pllb_data);
+ clks[BCM2835_PLLC] = bcm2835_register_pll(cprman, &bcm2835_pllc_data);
+ clks[BCM2835_PLLD] = bcm2835_register_pll(cprman, &bcm2835_plld_data);
+ clks[BCM2835_PLLH] = bcm2835_register_pll(cprman, &bcm2835_pllh_data);
+
+ clks[BCM2835_PLLA_CORE] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_plla_core_data);
+ clks[BCM2835_PLLA_PER] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_plla_per_data);
+ clks[BCM2835_PLLC_CORE0] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core0_data);
+ clks[BCM2835_PLLC_CORE1] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core1_data);
+ clks[BCM2835_PLLC_CORE2] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core2_data);
+ clks[BCM2835_PLLC_PER] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllc_per_data);
+ clks[BCM2835_PLLD_CORE] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_plld_core_data);
+ clks[BCM2835_PLLD_PER] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_plld_per_data);
+ clks[BCM2835_PLLH_RCAL] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllh_rcal_data);
+ clks[BCM2835_PLLH_AUX] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllh_aux_data);
+ clks[BCM2835_PLLH_PIX] =
+ bcm2835_register_pll_divider(cprman, &bcm2835_pllh_pix_data);
+
+ clks[BCM2835_CLOCK_TIMER] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_timer_data);
+ clks[BCM2835_CLOCK_OTP] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_otp_data);
+ clks[BCM2835_CLOCK_TSENS] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_tsens_data);
+ clks[BCM2835_CLOCK_VPU] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_vpu_data);
+ clks[BCM2835_CLOCK_V3D] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data);
+ clks[BCM2835_CLOCK_ISP] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_isp_data);
+ clks[BCM2835_CLOCK_H264] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_h264_data);
+ clks[BCM2835_CLOCK_V3D] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data);
+ clks[BCM2835_CLOCK_SDRAM] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_sdram_data);
+ clks[BCM2835_CLOCK_UART] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_uart_data);
+ clks[BCM2835_CLOCK_VEC] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_vec_data);
+ clks[BCM2835_CLOCK_HSM] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_hsm_data);
+ clks[BCM2835_CLOCK_EMMC] =
+ bcm2835_register_clock(cprman, &bcm2835_clock_emmc_data);
+
+ /*
+ * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if
+ * you have the debug bit set in the power manager, which we
+ * don't bother exposing) are individual gates off of the
+ * non-stop vpu clock.
+ */
+ clks[BCM2835_CLOCK_PERI_IMAGE] =
+ clk_register_gate(dev, "peri_image", "vpu",
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+ cprman->regs + CM_PERIICTL, CM_GATE_BIT,
+ 0, &cprman->regs_lock);
+
+ return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ &cprman->onecell);
+}
+
+static const struct of_device_id bcm2835_clk_of_match[] = {
+ { .compatible = "brcm,bcm2835-cprman", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
+
+static struct platform_driver bcm2835_clk_driver = {
+ .driver = {
+ .name = "bcm2835-clk",
+ .of_match_table = bcm2835_clk_of_match,
+ },
+ .probe = bcm2835_clk_probe,
+};
+
+builtin_platform_driver(bcm2835_clk_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("BCM2835 clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/bcm/clk-cygnus.c b/drivers/clk/bcm/clk-cygnus.c
index 316c60337661..3a228b6d4fee 100644
--- a/drivers/clk/bcm/clk-cygnus.c
+++ b/drivers/clk/bcm/clk-cygnus.c
@@ -23,28 +23,30 @@
#include <dt-bindings/clock/bcm-cygnus.h>
#include "clk-iproc.h"
-#define reg_val(o, s, w) { .offset = o, .shift = s, .width = w, }
+#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
-#define aon_val(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
+#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
.pwr_shift = ps, .iso_shift = is }
-#define sw_ctrl_val(o, s) { .offset = o, .shift = s, }
+#define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
-#define asiu_div_val(o, es, hs, hw, ls, lw) \
+#define ASIU_DIV_VAL(o, es, hs, hw, ls, lw) \
{ .offset = o, .en_shift = es, .high_shift = hs, \
.high_width = hw, .low_shift = ls, .low_width = lw }
-#define reset_val(o, rs, prs, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
- .reset_shift = rs, .p_reset_shift = prs, .ki_shift = kis, \
- .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
+#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
+ .p_reset_shift = prs }
+
+#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
+ .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
.ka_width = kaw }
-#define vco_ctrl_val(uo, lo) { .u_offset = uo, .l_offset = lo }
+#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
-#define enable_val(o, es, hs, bs) { .offset = o, .enable_shift = es, \
+#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
.hold_shift = hs, .bypass_shift = bs }
-#define asiu_gate_val(o, es) { .offset = o, .en_shift = es }
+#define ASIU_GATE_VAL(o, es) { .offset = o, .en_shift = es }
static void __init cygnus_armpll_init(struct device_node *node)
{
@@ -55,52 +57,53 @@ CLK_OF_DECLARE(cygnus_armpll, "brcm,cygnus-armpll", cygnus_armpll_init);
static const struct iproc_pll_ctrl genpll = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_PLL_NEEDS_SW_CFG,
- .aon = aon_val(0x0, 2, 1, 0),
- .reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 3),
- .sw_ctrl = sw_ctrl_val(0x10, 31),
- .ndiv_int = reg_val(0x10, 20, 10),
- .ndiv_frac = reg_val(0x10, 0, 20),
- .pdiv = reg_val(0x14, 0, 4),
- .vco_ctrl = vco_ctrl_val(0x18, 0x1c),
- .status = reg_val(0x28, 12, 1),
+ .aon = AON_VAL(0x0, 2, 1, 0),
+ .reset = RESET_VAL(0x0, 11, 10),
+ .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+ .sw_ctrl = SW_CTRL_VAL(0x10, 31),
+ .ndiv_int = REG_VAL(0x10, 20, 10),
+ .ndiv_frac = REG_VAL(0x10, 0, 20),
+ .pdiv = REG_VAL(0x14, 0, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
+ .status = REG_VAL(0x28, 12, 1),
};
static const struct iproc_clk_ctrl genpll_clk[] = {
[BCM_CYGNUS_GENPLL_AXI21_CLK] = {
.channel = BCM_CYGNUS_GENPLL_AXI21_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x4, 6, 0, 12),
- .mdiv = reg_val(0x20, 0, 8),
+ .enable = ENABLE_VAL(0x4, 6, 0, 12),
+ .mdiv = REG_VAL(0x20, 0, 8),
},
[BCM_CYGNUS_GENPLL_250MHZ_CLK] = {
.channel = BCM_CYGNUS_GENPLL_250MHZ_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x4, 7, 1, 13),
- .mdiv = reg_val(0x20, 10, 8),
+ .enable = ENABLE_VAL(0x4, 7, 1, 13),
+ .mdiv = REG_VAL(0x20, 10, 8),
},
[BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = {
.channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x4, 8, 2, 14),
- .mdiv = reg_val(0x20, 20, 8),
+ .enable = ENABLE_VAL(0x4, 8, 2, 14),
+ .mdiv = REG_VAL(0x20, 20, 8),
},
[BCM_CYGNUS_GENPLL_ENET_SW_CLK] = {
.channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x4, 9, 3, 15),
- .mdiv = reg_val(0x24, 0, 8),
+ .enable = ENABLE_VAL(0x4, 9, 3, 15),
+ .mdiv = REG_VAL(0x24, 0, 8),
},
[BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = {
.channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x4, 10, 4, 16),
- .mdiv = reg_val(0x24, 10, 8),
+ .enable = ENABLE_VAL(0x4, 10, 4, 16),
+ .mdiv = REG_VAL(0x24, 10, 8),
},
[BCM_CYGNUS_GENPLL_CAN_CLK] = {
.channel = BCM_CYGNUS_GENPLL_CAN_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x4, 11, 5, 17),
- .mdiv = reg_val(0x24, 20, 8),
+ .enable = ENABLE_VAL(0x4, 11, 5, 17),
+ .mdiv = REG_VAL(0x24, 20, 8),
},
};
@@ -113,51 +116,52 @@ CLK_OF_DECLARE(cygnus_genpll, "brcm,cygnus-genpll", cygnus_genpll_clk_init);
static const struct iproc_pll_ctrl lcpll0 = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
- .aon = aon_val(0x0, 2, 5, 4),
- .reset = reset_val(0x0, 31, 30, 27, 3, 23, 4, 19, 4),
- .sw_ctrl = sw_ctrl_val(0x4, 31),
- .ndiv_int = reg_val(0x4, 16, 10),
- .pdiv = reg_val(0x4, 26, 4),
- .vco_ctrl = vco_ctrl_val(0x10, 0x14),
- .status = reg_val(0x18, 12, 1),
+ .aon = AON_VAL(0x0, 2, 5, 4),
+ .reset = RESET_VAL(0x0, 31, 30),
+ .dig_filter = DF_VAL(0x0, 27, 3, 23, 4, 19, 4),
+ .sw_ctrl = SW_CTRL_VAL(0x4, 31),
+ .ndiv_int = REG_VAL(0x4, 16, 10),
+ .pdiv = REG_VAL(0x4, 26, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x10, 0x14),
+ .status = REG_VAL(0x18, 12, 1),
};
static const struct iproc_clk_ctrl lcpll0_clk[] = {
[BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x0, 7, 1, 13),
- .mdiv = reg_val(0x8, 0, 8),
+ .enable = ENABLE_VAL(0x0, 7, 1, 13),
+ .mdiv = REG_VAL(0x8, 0, 8),
},
[BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x0, 8, 2, 14),
- .mdiv = reg_val(0x8, 10, 8),
+ .enable = ENABLE_VAL(0x0, 8, 2, 14),
+ .mdiv = REG_VAL(0x8, 10, 8),
},
[BCM_CYGNUS_LCPLL0_SDIO_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_SDIO_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x0, 9, 3, 15),
- .mdiv = reg_val(0x8, 20, 8),
+ .enable = ENABLE_VAL(0x0, 9, 3, 15),
+ .mdiv = REG_VAL(0x8, 20, 8),
},
[BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x0, 10, 4, 16),
- .mdiv = reg_val(0xc, 0, 8),
+ .enable = ENABLE_VAL(0x0, 10, 4, 16),
+ .mdiv = REG_VAL(0xc, 0, 8),
},
[BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x0, 11, 5, 17),
- .mdiv = reg_val(0xc, 10, 8),
+ .enable = ENABLE_VAL(0x0, 11, 5, 17),
+ .mdiv = REG_VAL(0xc, 10, 8),
},
[BCM_CYGNUS_LCPLL0_CH5_UNUSED] = {
.channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED,
.flags = IPROC_CLK_AON,
- .enable = enable_val(0x0, 12, 6, 18),
- .mdiv = reg_val(0xc, 20, 8),
+ .enable = ENABLE_VAL(0x0, 12, 6, 18),
+ .mdiv = REG_VAL(0xc, 20, 8),
},
};
@@ -189,52 +193,53 @@ static const struct iproc_pll_vco_param mipipll_vco_params[] = {
static const struct iproc_pll_ctrl mipipll = {
.flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_NEEDS_READ_BACK,
- .aon = aon_val(0x0, 4, 17, 16),
- .asiu = asiu_gate_val(0x0, 3),
- .reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 4),
- .ndiv_int = reg_val(0x10, 20, 10),
- .ndiv_frac = reg_val(0x10, 0, 20),
- .pdiv = reg_val(0x14, 0, 4),
- .vco_ctrl = vco_ctrl_val(0x18, 0x1c),
- .status = reg_val(0x28, 12, 1),
+ .aon = AON_VAL(0x0, 4, 17, 16),
+ .asiu = ASIU_GATE_VAL(0x0, 3),
+ .reset = RESET_VAL(0x0, 11, 10),
+ .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 4),
+ .ndiv_int = REG_VAL(0x10, 20, 10),
+ .ndiv_frac = REG_VAL(0x10, 0, 20),
+ .pdiv = REG_VAL(0x14, 0, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
+ .status = REG_VAL(0x28, 12, 1),
};
static const struct iproc_clk_ctrl mipipll_clk[] = {
[BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK,
- .enable = enable_val(0x4, 12, 6, 18),
- .mdiv = reg_val(0x20, 0, 8),
+ .enable = ENABLE_VAL(0x4, 12, 6, 18),
+ .mdiv = REG_VAL(0x20, 0, 8),
},
[BCM_CYGNUS_MIPIPLL_CH1_LCD] = {
.channel = BCM_CYGNUS_MIPIPLL_CH1_LCD,
.flags = IPROC_CLK_NEEDS_READ_BACK,
- .enable = enable_val(0x4, 13, 7, 19),
- .mdiv = reg_val(0x20, 10, 8),
+ .enable = ENABLE_VAL(0x4, 13, 7, 19),
+ .mdiv = REG_VAL(0x20, 10, 8),
},
[BCM_CYGNUS_MIPIPLL_CH2_V3D] = {
.channel = BCM_CYGNUS_MIPIPLL_CH2_V3D,
.flags = IPROC_CLK_NEEDS_READ_BACK,
- .enable = enable_val(0x4, 14, 8, 20),
- .mdiv = reg_val(0x20, 20, 8),
+ .enable = ENABLE_VAL(0x4, 14, 8, 20),
+ .mdiv = REG_VAL(0x20, 20, 8),
},
[BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK,
- .enable = enable_val(0x4, 15, 9, 21),
- .mdiv = reg_val(0x24, 0, 8),
+ .enable = ENABLE_VAL(0x4, 15, 9, 21),
+ .mdiv = REG_VAL(0x24, 0, 8),
},
[BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK,
- .enable = enable_val(0x4, 16, 10, 22),
- .mdiv = reg_val(0x24, 10, 8),
+ .enable = ENABLE_VAL(0x4, 16, 10, 22),
+ .mdiv = REG_VAL(0x24, 10, 8),
},
[BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK,
- .enable = enable_val(0x4, 17, 11, 23),
- .mdiv = reg_val(0x24, 20, 8),
+ .enable = ENABLE_VAL(0x4, 17, 11, 23),
+ .mdiv = REG_VAL(0x24, 20, 8),
},
};
@@ -247,15 +252,15 @@ static void __init cygnus_mipipll_clk_init(struct device_node *node)
CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init);
static const struct iproc_asiu_div asiu_div[] = {
- [BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_div_val(0x0, 31, 16, 10, 0, 10),
- [BCM_CYGNUS_ASIU_ADC_CLK] = asiu_div_val(0x4, 31, 16, 10, 0, 10),
- [BCM_CYGNUS_ASIU_PWM_CLK] = asiu_div_val(0x8, 31, 16, 10, 0, 10),
+ [BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_DIV_VAL(0x0, 31, 16, 10, 0, 10),
+ [BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_DIV_VAL(0x4, 31, 16, 10, 0, 10),
+ [BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_DIV_VAL(0x8, 31, 16, 10, 0, 10),
};
static const struct iproc_asiu_gate asiu_gate[] = {
- [BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_gate_val(0x0, 7),
- [BCM_CYGNUS_ASIU_ADC_CLK] = asiu_gate_val(0x0, 9),
- [BCM_CYGNUS_ASIU_PWM_CLK] = asiu_gate_val(IPROC_CLK_INVALID_OFFSET, 0),
+ [BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_GATE_VAL(0x0, 7),
+ [BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_GATE_VAL(0x0, 9),
+ [BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_GATE_VAL(IPROC_CLK_INVALID_OFFSET, 0),
};
static void __init cygnus_asiu_init(struct device_node *node)
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c
index 2dda4e8295a9..afd5891ac9e6 100644
--- a/drivers/clk/bcm/clk-iproc-pll.c
+++ b/drivers/clk/bcm/clk-iproc-pll.c
@@ -74,7 +74,8 @@ struct iproc_clk {
};
struct iproc_pll {
- void __iomem *pll_base;
+ void __iomem *status_base;
+ void __iomem *control_base;
void __iomem *pwr_base;
void __iomem *asiu_base;
@@ -127,7 +128,7 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
for (i = 0; i < LOCK_DELAY; i++) {
- u32 val = readl(pll->pll_base + ctrl->status.offset);
+ u32 val = readl(pll->status_base + ctrl->status.offset);
if (val & (1 << ctrl->status.shift))
return 0;
@@ -137,6 +138,18 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
return -EIO;
}
+static void iproc_pll_write(const struct iproc_pll *pll, void __iomem *base,
+ const u32 offset, u32 val)
+{
+ const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+
+ writel(val, base + offset);
+
+ if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
+ (base == pll->status_base || base == pll->control_base)))
+ val = readl(base + offset);
+}
+
static void __pll_disable(struct iproc_pll *pll)
{
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
@@ -145,17 +158,25 @@ static void __pll_disable(struct iproc_pll *pll)
if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
val = readl(pll->asiu_base + ctrl->asiu.offset);
val &= ~(1 << ctrl->asiu.en_shift);
- writel(val, pll->asiu_base + ctrl->asiu.offset);
+ iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
+ }
+
+ if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
+ val = readl(pll->control_base + ctrl->aon.offset);
+ val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
+ iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
}
- /* latch input value so core power can be shut down */
- val = readl(pll->pwr_base + ctrl->aon.offset);
- val |= (1 << ctrl->aon.iso_shift);
- writel(val, pll->pwr_base + ctrl->aon.offset);
+ if (pll->pwr_base) {
+ /* latch input value so core power can be shut down */
+ val = readl(pll->pwr_base + ctrl->aon.offset);
+ val |= 1 << ctrl->aon.iso_shift;
+ iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
- /* power down the core */
- val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
- writel(val, pll->pwr_base + ctrl->aon.offset);
+ /* power down the core */
+ val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
+ iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
+ }
}
static int __pll_enable(struct iproc_pll *pll)
@@ -163,17 +184,25 @@ static int __pll_enable(struct iproc_pll *pll)
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
u32 val;
- /* power up the PLL and make sure it's not latched */
- val = readl(pll->pwr_base + ctrl->aon.offset);
- val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
- val &= ~(1 << ctrl->aon.iso_shift);
- writel(val, pll->pwr_base + ctrl->aon.offset);
+ if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
+ val = readl(pll->control_base + ctrl->aon.offset);
+ val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
+ iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
+ }
+
+ if (pll->pwr_base) {
+ /* power up the PLL and make sure it's not latched */
+ val = readl(pll->pwr_base + ctrl->aon.offset);
+ val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
+ val &= ~(1 << ctrl->aon.iso_shift);
+ iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
+ }
/* certain PLLs also need to be ungated from the ASIU top level */
if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
val = readl(pll->asiu_base + ctrl->asiu.offset);
val |= (1 << ctrl->asiu.en_shift);
- writel(val, pll->asiu_base + ctrl->asiu.offset);
+ iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
}
return 0;
@@ -185,11 +214,9 @@ static void __pll_put_in_reset(struct iproc_pll *pll)
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
- val = readl(pll->pll_base + reset->offset);
+ val = readl(pll->control_base + reset->offset);
val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
- writel(val, pll->pll_base + reset->offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + reset->offset);
+ iproc_pll_write(pll, pll->control_base, reset->offset, val);
}
static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
@@ -198,17 +225,19 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
u32 val;
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
+ const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter;
+
+ val = readl(pll->control_base + dig_filter->offset);
+ val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift |
+ bit_mask(dig_filter->kp_width) << dig_filter->kp_shift |
+ bit_mask(dig_filter->ka_width) << dig_filter->ka_shift);
+ val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift |
+ ka << dig_filter->ka_shift;
+ iproc_pll_write(pll, pll->control_base, dig_filter->offset, val);
- val = readl(pll->pll_base + reset->offset);
- val &= ~(bit_mask(reset->ki_width) << reset->ki_shift |
- bit_mask(reset->kp_width) << reset->kp_shift |
- bit_mask(reset->ka_width) << reset->ka_shift);
- val |= ki << reset->ki_shift | kp << reset->kp_shift |
- ka << reset->ka_shift;
+ val = readl(pll->control_base + reset->offset);
val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
- writel(val, pll->pll_base + reset->offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + reset->offset);
+ iproc_pll_write(pll, pll->control_base, reset->offset, val);
}
static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
@@ -263,10 +292,9 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
/* put PLL in reset */
__pll_put_in_reset(pll);
- writel(0, pll->pll_base + ctrl->vco_ctrl.u_offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->vco_ctrl.u_offset);
- val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0);
+
+ val = readl(pll->control_base + ctrl->vco_ctrl.l_offset);
if (rate >= VCO_LOW && rate < VCO_MID)
val |= (1 << PLL_VCO_LOW_SHIFT);
@@ -276,36 +304,29 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
else
val |= (1 << PLL_VCO_HIGH_SHIFT);
- writel(val, pll->pll_base + ctrl->vco_ctrl.l_offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val);
/* program integer part of NDIV */
- val = readl(pll->pll_base + ctrl->ndiv_int.offset);
+ val = readl(pll->control_base + ctrl->ndiv_int.offset);
val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
val |= vco->ndiv_int << ctrl->ndiv_int.shift;
- writel(val, pll->pll_base + ctrl->ndiv_int.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->ndiv_int.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val);
/* program fractional part of NDIV */
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
- val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
+ val = readl(pll->control_base + ctrl->ndiv_frac.offset);
val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
ctrl->ndiv_frac.shift);
val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
- writel(val, pll->pll_base + ctrl->ndiv_frac.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->ndiv_frac.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset,
+ val);
}
/* program PDIV */
- val = readl(pll->pll_base + ctrl->pdiv.offset);
+ val = readl(pll->control_base + ctrl->pdiv.offset);
val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
val |= vco->pdiv << ctrl->pdiv.shift;
- writel(val, pll->pll_base + ctrl->pdiv.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->pdiv.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val);
__pll_bring_out_reset(pll, kp, ka, ki);
@@ -345,14 +366,14 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
struct iproc_pll *pll = clk->pll;
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
u32 val;
- u64 ndiv;
- unsigned int ndiv_int, ndiv_frac, pdiv;
+ u64 ndiv, ndiv_int, ndiv_frac;
+ unsigned int pdiv;
if (parent_rate == 0)
return 0;
/* PLL needs to be locked */
- val = readl(pll->pll_base + ctrl->status.offset);
+ val = readl(pll->status_base + ctrl->status.offset);
if ((val & (1 << ctrl->status.shift)) == 0) {
clk->rate = 0;
return 0;
@@ -363,25 +384,22 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
*
* ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
*/
- val = readl(pll->pll_base + ctrl->ndiv_int.offset);
+ val = readl(pll->control_base + ctrl->ndiv_int.offset);
ndiv_int = (val >> ctrl->ndiv_int.shift) &
bit_mask(ctrl->ndiv_int.width);
- ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift;
+ ndiv = ndiv_int << 20;
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
- val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
+ val = readl(pll->control_base + ctrl->ndiv_frac.offset);
ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
bit_mask(ctrl->ndiv_frac.width);
-
- if (ndiv_frac != 0)
- ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) |
- ndiv_frac;
+ ndiv += ndiv_frac;
}
- val = readl(pll->pll_base + ctrl->pdiv.offset);
+ val = readl(pll->control_base + ctrl->pdiv.offset);
pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
- clk->rate = (ndiv * parent_rate) >> ctrl->ndiv_int.shift;
+ clk->rate = (ndiv * parent_rate) >> 20;
if (pdiv == 0)
clk->rate *= 2;
@@ -443,16 +461,14 @@ static int iproc_clk_enable(struct clk_hw *hw)
u32 val;
/* channel enable is active low */
- val = readl(pll->pll_base + ctrl->enable.offset);
+ val = readl(pll->control_base + ctrl->enable.offset);
val &= ~(1 << ctrl->enable.enable_shift);
- writel(val, pll->pll_base + ctrl->enable.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
/* also make sure channel is not held */
- val = readl(pll->pll_base + ctrl->enable.offset);
+ val = readl(pll->control_base + ctrl->enable.offset);
val &= ~(1 << ctrl->enable.hold_shift);
- writel(val, pll->pll_base + ctrl->enable.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->enable.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
return 0;
}
@@ -467,11 +483,9 @@ static void iproc_clk_disable(struct clk_hw *hw)
if (ctrl->flags & IPROC_CLK_AON)
return;
- val = readl(pll->pll_base + ctrl->enable.offset);
+ val = readl(pll->control_base + ctrl->enable.offset);
val |= 1 << ctrl->enable.enable_shift;
- writel(val, pll->pll_base + ctrl->enable.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->enable.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
}
static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
@@ -486,7 +500,7 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
if (parent_rate == 0)
return 0;
- val = readl(pll->pll_base + ctrl->mdiv.offset);
+ val = readl(pll->control_base + ctrl->mdiv.offset);
mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
if (mdiv == 0)
mdiv = 256;
@@ -533,16 +547,14 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
if (div > 256)
return -EINVAL;
- val = readl(pll->pll_base + ctrl->mdiv.offset);
+ val = readl(pll->control_base + ctrl->mdiv.offset);
if (div == 256) {
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
} else {
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
val |= div << ctrl->mdiv.shift;
}
- writel(val, pll->pll_base + ctrl->mdiv.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->mdiv.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val);
clk->rate = parent_rate / div;
return 0;
@@ -567,11 +579,10 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
u32 val;
- val = readl(pll->pll_base + ctrl->sw_ctrl.offset);
+ val = readl(pll->control_base + ctrl->sw_ctrl.offset);
val |= BIT(ctrl->sw_ctrl.shift);
- writel(val, pll->pll_base + ctrl->sw_ctrl.offset);
- if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
- readl(pll->pll_base + ctrl->sw_ctrl.offset);
+ iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset,
+ val);
}
}
@@ -606,13 +617,12 @@ void __init iproc_pll_clk_setup(struct device_node *node,
if (WARN_ON(!pll->clks))
goto err_clks;
- pll->pll_base = of_iomap(node, 0);
- if (WARN_ON(!pll->pll_base))
+ pll->control_base = of_iomap(node, 0);
+ if (WARN_ON(!pll->control_base))
goto err_pll_iomap;
+ /* Some SoCs do not require the pwr_base, thus failing is not fatal */
pll->pwr_base = of_iomap(node, 1);
- if (WARN_ON(!pll->pwr_base))
- goto err_pwr_iomap;
/* some PLLs require gating control at the top ASIU level */
if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
@@ -621,6 +631,16 @@ void __init iproc_pll_clk_setup(struct device_node *node,
goto err_asiu_iomap;
}
+ if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) {
+ /* Some SoCs have a split status/control. If this does not
+ * exist, assume they are unified.
+ */
+ pll->status_base = of_iomap(node, 2);
+ if (!pll->status_base)
+ goto err_status_iomap;
+ } else
+ pll->status_base = pll->control_base;
+
/* initialize and register the PLL itself */
pll->ctrl = pll_ctrl;
@@ -691,14 +711,18 @@ err_clk_register:
clk_unregister(pll->clk_data.clks[i]);
err_pll_register:
+ if (pll->status_base != pll->control_base)
+ iounmap(pll->status_base);
+
+err_status_iomap:
if (pll->asiu_base)
iounmap(pll->asiu_base);
err_asiu_iomap:
- iounmap(pll->pwr_base);
+ if (pll->pwr_base)
+ iounmap(pll->pwr_base);
-err_pwr_iomap:
- iounmap(pll->pll_base);
+ iounmap(pll->control_base);
err_pll_iomap:
kfree(pll->clks);
diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h
index d834b7abd5c6..8988de70a98c 100644
--- a/drivers/clk/bcm/clk-iproc.h
+++ b/drivers/clk/bcm/clk-iproc.h
@@ -49,6 +49,18 @@
#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
/*
+ * Some PLLs use a different way to control clock power, via the PWRDWN bit in
+ * the PLL control register
+ */
+#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
+
+/*
+ * Some PLLs have separate registers for Status and Control. Identify this to
+ * let the driver know if additional registers need to be used
+ */
+#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
+
+/*
* Parameters for VCO frequency configuration
*
* VCO frequency =
@@ -88,12 +100,19 @@ struct iproc_pll_aon_pwr_ctrl {
};
/*
- * Control of the PLL reset, with Ki, Kp, and Ka parameters
+ * Control of the PLL reset
*/
struct iproc_pll_reset_ctrl {
unsigned int offset;
unsigned int reset_shift;
unsigned int p_reset_shift;
+};
+
+/*
+ * Control of the Ki, Kp, and Ka parameters
+ */
+struct iproc_pll_dig_filter_ctrl {
+ unsigned int offset;
unsigned int ki_shift;
unsigned int ki_width;
unsigned int kp_shift;
@@ -123,6 +142,7 @@ struct iproc_pll_ctrl {
struct iproc_pll_aon_pwr_ctrl aon;
struct iproc_asiu_gate asiu;
struct iproc_pll_reset_ctrl reset;
+ struct iproc_pll_dig_filter_ctrl dig_filter;
struct iproc_pll_sw_ctrl sw_ctrl;
struct iproc_clk_reg_op ndiv_int;
struct iproc_clk_reg_op ndiv_frac;
diff --git a/drivers/clk/bcm/clk-ns2.c b/drivers/clk/bcm/clk-ns2.c
new file mode 100644
index 000000000000..a564e9248814
--- /dev/null
+++ b/drivers/clk/bcm/clk-ns2.c
@@ -0,0 +1,288 @@
+/*
+ * 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/kernel.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/bcm-ns2.h>
+#include "clk-iproc.h"
+
+#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
+
+#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
+ .pwr_shift = ps, .iso_shift = is }
+
+#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
+ .p_reset_shift = prs }
+
+#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
+ .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
+ .ka_width = kaw }
+
+#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
+
+#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
+ .hold_shift = hs, .bypass_shift = bs }
+
+static const struct iproc_pll_ctrl genpll_scr = {
+ .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
+ .aon = AON_VAL(0x0, 1, 15, 12),
+ .reset = RESET_VAL(0x4, 2, 1),
+ .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
+ .ndiv_int = REG_VAL(0x8, 4, 10),
+ .pdiv = REG_VAL(0x8, 0, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
+ .status = REG_VAL(0x0, 27, 1),
+};
+
+
+static const struct iproc_clk_ctrl genpll_scr_clk[] = {
+ /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
+ * in NS2. However, it doesn't appear to be used anywhere, so setting
+ * it to 0.
+ */
+ [BCM_NS2_GENPLL_SCR_SCR_CLK] = {
+ .channel = BCM_NS2_GENPLL_SCR_SCR_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 18, 12, 0),
+ .mdiv = REG_VAL(0x18, 0, 8),
+ },
+ [BCM_NS2_GENPLL_SCR_FS_CLK] = {
+ .channel = BCM_NS2_GENPLL_SCR_FS_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 19, 13, 0),
+ .mdiv = REG_VAL(0x18, 8, 8),
+ },
+ [BCM_NS2_GENPLL_SCR_AUDIO_CLK] = {
+ .channel = BCM_NS2_GENPLL_SCR_AUDIO_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 20, 14, 0),
+ .mdiv = REG_VAL(0x14, 0, 8),
+ },
+ [BCM_NS2_GENPLL_SCR_CH3_UNUSED] = {
+ .channel = BCM_NS2_GENPLL_SCR_CH3_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 21, 15, 0),
+ .mdiv = REG_VAL(0x14, 8, 8),
+ },
+ [BCM_NS2_GENPLL_SCR_CH4_UNUSED] = {
+ .channel = BCM_NS2_GENPLL_SCR_CH4_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 22, 16, 0),
+ .mdiv = REG_VAL(0x14, 16, 8),
+ },
+ [BCM_NS2_GENPLL_SCR_CH5_UNUSED] = {
+ .channel = BCM_NS2_GENPLL_SCR_CH5_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 23, 17, 0),
+ .mdiv = REG_VAL(0x14, 24, 8),
+ },
+};
+
+static void __init ns2_genpll_scr_clk_init(struct device_node *node)
+{
+ iproc_pll_clk_setup(node, &genpll_scr, NULL, 0, genpll_scr_clk,
+ ARRAY_SIZE(genpll_scr_clk));
+}
+CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
+ ns2_genpll_scr_clk_init);
+
+static const struct iproc_pll_ctrl genpll_sw = {
+ .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
+ .aon = AON_VAL(0x0, 2, 9, 8),
+ .reset = RESET_VAL(0x4, 2, 1),
+ .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
+ .ndiv_int = REG_VAL(0x8, 4, 10),
+ .pdiv = REG_VAL(0x8, 0, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
+ .status = REG_VAL(0x0, 13, 1),
+};
+
+static const struct iproc_clk_ctrl genpll_sw_clk[] = {
+ /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
+ * in NS2. However, it doesn't appear to be used anywhere, so setting
+ * it to 0.
+ */
+ [BCM_NS2_GENPLL_SW_RPE_CLK] = {
+ .channel = BCM_NS2_GENPLL_SW_RPE_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 18, 12, 0),
+ .mdiv = REG_VAL(0x18, 0, 8),
+ },
+ [BCM_NS2_GENPLL_SW_250_CLK] = {
+ .channel = BCM_NS2_GENPLL_SW_250_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 19, 13, 0),
+ .mdiv = REG_VAL(0x18, 8, 8),
+ },
+ [BCM_NS2_GENPLL_SW_NIC_CLK] = {
+ .channel = BCM_NS2_GENPLL_SW_NIC_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 20, 14, 0),
+ .mdiv = REG_VAL(0x14, 0, 8),
+ },
+ [BCM_NS2_GENPLL_SW_CHIMP_CLK] = {
+ .channel = BCM_NS2_GENPLL_SW_CHIMP_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 21, 15, 0),
+ .mdiv = REG_VAL(0x14, 8, 8),
+ },
+ [BCM_NS2_GENPLL_SW_PORT_CLK] = {
+ .channel = BCM_NS2_GENPLL_SW_PORT_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 22, 16, 0),
+ .mdiv = REG_VAL(0x14, 16, 8),
+ },
+ [BCM_NS2_GENPLL_SW_SDIO_CLK] = {
+ .channel = BCM_NS2_GENPLL_SW_SDIO_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 23, 17, 0),
+ .mdiv = REG_VAL(0x14, 24, 8),
+ },
+};
+
+static void __init ns2_genpll_sw_clk_init(struct device_node *node)
+{
+ iproc_pll_clk_setup(node, &genpll_sw, NULL, 0, genpll_sw_clk,
+ ARRAY_SIZE(genpll_sw_clk));
+}
+CLK_OF_DECLARE(ns2_genpll_sw_clk, "brcm,ns2-genpll-sw",
+ ns2_genpll_sw_clk_init);
+
+static const struct iproc_pll_ctrl lcpll_ddr = {
+ .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
+ .aon = AON_VAL(0x0, 2, 1, 0),
+ .reset = RESET_VAL(0x4, 2, 1),
+ .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
+ .ndiv_int = REG_VAL(0x8, 4, 10),
+ .pdiv = REG_VAL(0x8, 0, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
+ .status = REG_VAL(0x0, 0, 1),
+};
+
+static const struct iproc_clk_ctrl lcpll_ddr_clk[] = {
+ /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
+ * in NS2. However, it doesn't appear to be used anywhere, so setting
+ * it to 0.
+ */
+ [BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK] = {
+ .channel = BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 18, 12, 0),
+ .mdiv = REG_VAL(0x14, 0, 8),
+ },
+ [BCM_NS2_LCPLL_DDR_DDR_CLK] = {
+ .channel = BCM_NS2_LCPLL_DDR_DDR_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 19, 13, 0),
+ .mdiv = REG_VAL(0x14, 8, 8),
+ },
+ [BCM_NS2_LCPLL_DDR_CH2_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_DDR_CH2_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 20, 14, 0),
+ .mdiv = REG_VAL(0x10, 0, 8),
+ },
+ [BCM_NS2_LCPLL_DDR_CH3_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_DDR_CH3_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 21, 15, 0),
+ .mdiv = REG_VAL(0x10, 8, 8),
+ },
+ [BCM_NS2_LCPLL_DDR_CH4_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_DDR_CH4_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 22, 16, 0),
+ .mdiv = REG_VAL(0x10, 16, 8),
+ },
+ [BCM_NS2_LCPLL_DDR_CH5_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_DDR_CH5_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 23, 17, 0),
+ .mdiv = REG_VAL(0x10, 24, 8),
+ },
+};
+
+static void __init ns2_lcpll_ddr_clk_init(struct device_node *node)
+{
+ iproc_pll_clk_setup(node, &lcpll_ddr, NULL, 0, lcpll_ddr_clk,
+ ARRAY_SIZE(lcpll_ddr_clk));
+}
+CLK_OF_DECLARE(ns2_lcpll_ddr_clk, "brcm,ns2-lcpll-ddr",
+ ns2_lcpll_ddr_clk_init);
+
+static const struct iproc_pll_ctrl lcpll_ports = {
+ .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
+ .aon = AON_VAL(0x0, 2, 5, 4),
+ .reset = RESET_VAL(0x4, 2, 1),
+ .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
+ .ndiv_int = REG_VAL(0x8, 4, 10),
+ .pdiv = REG_VAL(0x8, 0, 4),
+ .vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
+ .status = REG_VAL(0x0, 0, 1),
+};
+
+static const struct iproc_clk_ctrl lcpll_ports_clk[] = {
+ /* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
+ * in NS2. However, it doesn't appear to be used anywhere, so setting
+ * it to 0.
+ */
+ [BCM_NS2_LCPLL_PORTS_WAN_CLK] = {
+ .channel = BCM_NS2_LCPLL_PORTS_WAN_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 18, 12, 0),
+ .mdiv = REG_VAL(0x14, 0, 8),
+ },
+ [BCM_NS2_LCPLL_PORTS_RGMII_CLK] = {
+ .channel = BCM_NS2_LCPLL_PORTS_RGMII_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 19, 13, 0),
+ .mdiv = REG_VAL(0x14, 8, 8),
+ },
+ [BCM_NS2_LCPLL_PORTS_CH2_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_PORTS_CH2_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 20, 14, 0),
+ .mdiv = REG_VAL(0x10, 0, 8),
+ },
+ [BCM_NS2_LCPLL_PORTS_CH3_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_PORTS_CH3_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 21, 15, 0),
+ .mdiv = REG_VAL(0x10, 8, 8),
+ },
+ [BCM_NS2_LCPLL_PORTS_CH4_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_PORTS_CH4_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 22, 16, 0),
+ .mdiv = REG_VAL(0x10, 16, 8),
+ },
+ [BCM_NS2_LCPLL_PORTS_CH5_UNUSED] = {
+ .channel = BCM_NS2_LCPLL_PORTS_CH5_UNUSED,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 23, 17, 0),
+ .mdiv = REG_VAL(0x10, 24, 8),
+ },
+};
+
+static void __init ns2_lcpll_ports_clk_init(struct device_node *node)
+{
+ iproc_pll_clk_setup(node, &lcpll_ports, NULL, 0, lcpll_ports_clk,
+ ARRAY_SIZE(lcpll_ports_clk));
+}
+CLK_OF_DECLARE(ns2_lcpll_ports_clk, "brcm,ns2-lcpll-ports",
+ ns2_lcpll_ports_clk_init);
diff --git a/drivers/clk/bcm/clk-nsp.c b/drivers/clk/bcm/clk-nsp.c
new file mode 100644
index 000000000000..cf66f640a47d
--- /dev/null
+++ b/drivers/clk/bcm/clk-nsp.c
@@ -0,0 +1,139 @@
+/*
+ * 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/kernel.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/bcm-nsp.h>
+#include "clk-iproc.h"
+
+#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
+
+#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
+ .pwr_shift = ps, .iso_shift = is }
+
+#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
+ .p_reset_shift = prs }
+
+#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
+ .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
+ .ka_width = kaw }
+
+#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
+ .hold_shift = hs, .bypass_shift = bs }
+
+static void __init nsp_armpll_init(struct device_node *node)
+{
+ iproc_armpll_setup(node);
+}
+CLK_OF_DECLARE(nsp_armpll, "brcm,nsp-armpll", nsp_armpll_init);
+
+static const struct iproc_pll_ctrl genpll = {
+ .flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
+ .aon = AON_VAL(0x0, 1, 12, 0),
+ .reset = RESET_VAL(0x0, 11, 10),
+ .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+ .ndiv_int = REG_VAL(0x14, 20, 10),
+ .ndiv_frac = REG_VAL(0x14, 0, 20),
+ .pdiv = REG_VAL(0x18, 24, 3),
+ .status = REG_VAL(0x20, 12, 1),
+};
+
+static const struct iproc_clk_ctrl genpll_clk[] = {
+ [BCM_NSP_GENPLL_PHY_CLK] = {
+ .channel = BCM_NSP_GENPLL_PHY_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x4, 12, 6, 18),
+ .mdiv = REG_VAL(0x18, 16, 8),
+ },
+ [BCM_NSP_GENPLL_ENET_SW_CLK] = {
+ .channel = BCM_NSP_GENPLL_ENET_SW_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x4, 13, 7, 19),
+ .mdiv = REG_VAL(0x18, 8, 8),
+ },
+ [BCM_NSP_GENPLL_USB_PHY_REF_CLK] = {
+ .channel = BCM_NSP_GENPLL_USB_PHY_REF_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x4, 14, 8, 20),
+ .mdiv = REG_VAL(0x18, 0, 8),
+ },
+ [BCM_NSP_GENPLL_IPROCFAST_CLK] = {
+ .channel = BCM_NSP_GENPLL_IPROCFAST_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x4, 15, 9, 21),
+ .mdiv = REG_VAL(0x1c, 16, 8),
+ },
+ [BCM_NSP_GENPLL_SATA1_CLK] = {
+ .channel = BCM_NSP_GENPLL_SATA1_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x4, 16, 10, 22),
+ .mdiv = REG_VAL(0x1c, 8, 8),
+ },
+ [BCM_NSP_GENPLL_SATA2_CLK] = {
+ .channel = BCM_NSP_GENPLL_SATA2_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x4, 17, 11, 23),
+ .mdiv = REG_VAL(0x1c, 0, 8),
+ },
+};
+
+static void __init nsp_genpll_clk_init(struct device_node *node)
+{
+ iproc_pll_clk_setup(node, &genpll, NULL, 0, genpll_clk,
+ ARRAY_SIZE(genpll_clk));
+}
+CLK_OF_DECLARE(nsp_genpll_clk, "brcm,nsp-genpll", nsp_genpll_clk_init);
+
+static const struct iproc_pll_ctrl lcpll0 = {
+ .flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
+ .aon = AON_VAL(0x0, 1, 24, 0),
+ .reset = RESET_VAL(0x0, 23, 22),
+ .dig_filter = DF_VAL(0x0, 16, 3, 12, 4, 19, 4),
+ .ndiv_int = REG_VAL(0x4, 20, 8),
+ .ndiv_frac = REG_VAL(0x4, 0, 20),
+ .pdiv = REG_VAL(0x4, 28, 3),
+ .status = REG_VAL(0x10, 12, 1),
+};
+
+static const struct iproc_clk_ctrl lcpll0_clk[] = {
+ [BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK] = {
+ .channel = BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 6, 3, 9),
+ .mdiv = REG_VAL(0x8, 24, 8),
+ },
+ [BCM_NSP_LCPLL0_SDIO_CLK] = {
+ .channel = BCM_NSP_LCPLL0_SDIO_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 7, 4, 10),
+ .mdiv = REG_VAL(0x8, 16, 8),
+ },
+ [BCM_NSP_LCPLL0_DDR_PHY_CLK] = {
+ .channel = BCM_NSP_LCPLL0_DDR_PHY_CLK,
+ .flags = IPROC_CLK_AON,
+ .enable = ENABLE_VAL(0x0, 8, 5, 11),
+ .mdiv = REG_VAL(0x8, 8, 8),
+ },
+};
+
+static void __init nsp_lcpll0_clk_init(struct device_node *node)
+{
+ iproc_pll_clk_setup(node, &lcpll0, NULL, 0, lcpll0_clk,
+ ARRAY_SIZE(lcpll0_clk));
+}
+CLK_OF_DECLARE(nsp_lcpll0_clk, "brcm,nsp-lcpll0", nsp_lcpll0_clk_init);
diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
index 73153fc45ee9..23e0e3be6c37 100644
--- a/drivers/clk/berlin/bg2.c
+++ b/drivers/clk/berlin/bg2.c
@@ -490,8 +490,8 @@ static const struct berlin2_gate_data bg2_gates[] __initconst = {
{ "usb0", "perif", 11 },
{ "usb1", "perif", 12 },
{ "pbridge", "perif", 13, CLK_IGNORE_UNUSED },
- { "sdio0", "perif", 14, CLK_IGNORE_UNUSED },
- { "sdio1", "perif", 15, CLK_IGNORE_UNUSED },
+ { "sdio0", "perif", 14 },
+ { "sdio1", "perif", 15 },
{ "nfc", "perif", 17 },
{ "smemc", "perif", 19 },
{ "audiohd", "audiohd_pll", 26 },
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
index 221f40c2b850..f144547cf76c 100644
--- a/drivers/clk/berlin/bg2q.c
+++ b/drivers/clk/berlin/bg2q.c
@@ -45,7 +45,7 @@
#define REG_SDIO0XIN_CLKCTL 0x0158
#define REG_SDIO1XIN_CLKCTL 0x015c
-#define MAX_CLKS 27
+#define MAX_CLKS 28
static struct clk *clks[MAX_CLKS];
static struct clk_onecell_data clk_data;
static DEFINE_SPINLOCK(lock);
@@ -283,7 +283,7 @@ static const struct berlin2_gate_data bg2q_gates[] __initconst = {
{ "usb2", "perif", 13 },
{ "usb3", "perif", 14 },
{ "pbridge", "perif", 15, CLK_IGNORE_UNUSED },
- { "sdio", "perif", 16, CLK_IGNORE_UNUSED },
+ { "sdio", "perif", 16 },
{ "nfc", "perif", 18 },
{ "pcie", "perif", 22 },
};
@@ -356,13 +356,13 @@ static void __init berlin2q_clock_setup(struct device_node *np)
gd->bit_idx, 0, &lock);
}
- /*
- * twdclk is derived from cpu/3
- * TODO: use cpupll until cpuclk is not available
- */
+ /* cpuclk divider is fixed to 1 */
+ clks[CLKID_CPU] =
+ clk_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
+ 0, 1, 1);
+ /* twdclk is derived from cpu/3 */
clks[CLKID_TWD] =
- clk_register_fixed_factor(NULL, "twd", clk_names[CPUPLL],
- 0, 1, 3);
+ clk_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
/* check for errors on leaf clocks */
for (n = 0; n < MAX_CLKS; n++) {
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
deleted file mode 100644
index dd295e498309..000000000000
--- a/drivers/clk/clk-bcm2835.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010 Broadcom
- * Copyright (C) 2012 Stephen Warren
- *
- * 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/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/clk/bcm2835.h>
-#include <linux/of.h>
-
-/*
- * These are fixed clocks. They're probably not all root clocks and it may
- * be possible to turn them on and off but until this is mapped out better
- * it's the only way they can be used.
- */
-void __init bcm2835_init_clocks(void)
-{
- struct clk *clk;
- int ret;
-
- clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
- 126000000);
- if (IS_ERR(clk))
- pr_err("apb_pclk not registered\n");
-
- clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
- 3000000);
- if (IS_ERR(clk))
- pr_err("uart0_pclk not registered\n");
- ret = clk_register_clkdev(clk, NULL, "20201000.uart");
- if (ret)
- pr_err("uart0_pclk alias not registered\n");
-
- clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
- 125000000);
- if (IS_ERR(clk))
- pr_err("uart1_pclk not registered\n");
- ret = clk_register_clkdev(clk, NULL, "20215000.uart");
- if (ret)
- pr_err("uart1_pclk alias not registered\n");
-}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index f24d0a19ae70..3ace102a2a0a 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -24,7 +24,7 @@
* Traits of this clock:
* prepare - clk_prepare only ensures that parents are prepared
* enable - clk_enable only ensures that parents are enabled
- * rate - rate is adjustable. clk->rate = DIV_ROUND_UP(parent->rate / divisor)
+ * rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor)
* parent - fixed parent. No clk_set_parent support
*/
@@ -132,7 +132,7 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
return parent_rate;
}
- return DIV_ROUND_UP(parent_rate, div);
+ return DIV_ROUND_UP_ULL((u64)parent_rate, div);
}
EXPORT_SYMBOL_GPL(divider_recalc_rate);
@@ -210,7 +210,7 @@ static int _div_round_up(const struct clk_div_table *table,
unsigned long parent_rate, unsigned long rate,
unsigned long flags)
{
- int div = DIV_ROUND_UP(parent_rate, rate);
+ int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
if (flags & CLK_DIVIDER_POWER_OF_TWO)
div = __roundup_pow_of_two(div);
@@ -227,7 +227,7 @@ static int _div_round_closest(const struct clk_div_table *table,
int up, down;
unsigned long up_rate, down_rate;
- up = DIV_ROUND_UP(parent_rate, rate);
+ up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
down = parent_rate / rate;
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
@@ -238,8 +238,8 @@ static int _div_round_closest(const struct clk_div_table *table,
down = _round_down_table(table, down);
}
- up_rate = DIV_ROUND_UP(parent_rate, up);
- down_rate = DIV_ROUND_UP(parent_rate, down);
+ up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
+ down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
return (rate - up_rate) <= (down_rate - rate) ? up : down;
}
@@ -318,7 +318,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
}
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
rate * i);
- now = DIV_ROUND_UP(parent_rate, i);
+ now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
if (_is_best_div(rate, now, best, flags)) {
bestdiv = i;
best = now;
@@ -342,7 +342,7 @@ long divider_round_rate(struct clk_hw *hw, unsigned long rate,
div = clk_divider_bestdiv(hw, rate, prate, table, width, flags);
- return DIV_ROUND_UP(*prate, div);
+ return DIV_ROUND_UP_ULL((u64)*prate, div);
}
EXPORT_SYMBOL_GPL(divider_round_rate);
@@ -358,7 +358,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
bestdiv &= div_mask(divider->width);
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
divider->width);
- return DIV_ROUND_UP(*prate, bestdiv);
+ return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
}
return divider_round_rate(hw, rate, prate, divider->table,
@@ -371,7 +371,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
{
unsigned int div, value;
- div = DIV_ROUND_UP(parent_rate, rate);
+ div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
if (!_is_valid_div(table, div, flags))
return -EINVAL;
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index e85f856b8592..5c4955e33f7a 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -7,13 +7,14 @@
*
* Adjustable fractional divider clock implementation.
* Output rate = (m / n) * parent_rate.
+ * Uses rational best approximation algorithm.
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
-#include <linux/gcd.h>
+#include <linux/rational.h>
#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
@@ -22,7 +23,8 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
- u32 val, m, n;
+ unsigned long m, n;
+ u32 val;
u64 ret;
if (fd->lock)
@@ -50,23 +52,33 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
}
static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+ unsigned long *parent_rate)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
- unsigned maxn = (fd->nmask >> fd->nshift) + 1;
- unsigned div;
+ unsigned long scale;
+ unsigned long m, n;
+ u64 ret;
- if (!rate || rate >= *prate)
- return *prate;
+ if (!rate || rate >= *parent_rate)
+ return *parent_rate;
- div = gcd(*prate, rate);
+ /*
+ * Get rate closer to *parent_rate to guarantee there is no overflow
+ * for m and n. In the result it will be the nearest rate left shifted
+ * by (scale - fd->nwidth) bits.
+ */
+ scale = fls_long(*parent_rate / rate - 1);
+ if (scale > fd->nwidth)
+ rate <<= scale - fd->nwidth;
- while ((*prate / div) > maxn) {
- div <<= 1;
- rate <<= 1;
- }
+ rational_best_approximation(rate, *parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ &m, &n);
- return rate;
+ ret = (u64)*parent_rate * m;
+ do_div(ret, n);
+
+ return ret;
}
static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -74,13 +86,12 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
- unsigned long div;
- unsigned n, m;
+ unsigned long m, n;
u32 val;
- div = gcd(parent_rate, rate);
- m = rate / div;
- n = parent_rate / div;
+ rational_best_approximation(rate, parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ &m, &n);
if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
@@ -128,9 +139,11 @@ struct clk *clk_register_fractional_divider(struct device *dev,
fd->reg = reg;
fd->mshift = mshift;
- fd->mmask = (BIT(mwidth) - 1) << mshift;
+ fd->mwidth = mwidth;
+ fd->mmask = GENMASK(mwidth - 1, 0) << mshift;
fd->nshift = nshift;
- fd->nmask = (BIT(nwidth) - 1) << nshift;
+ fd->nwidth = nwidth;
+ fd->nmask = GENMASK(nwidth - 1, 0) << nshift;
fd->flags = clk_divider_flags;
fd->lock = lock;
fd->hw.init = &init;
diff --git a/drivers/clk/clk-max77802.c b/drivers/clk/clk-max77802.c
index 74c49b93a6eb..4a89f7979ba0 100644
--- a/drivers/clk/clk-max77802.c
+++ b/drivers/clk/clk-max77802.c
@@ -94,5 +94,5 @@ static struct platform_driver max77802_clk_driver = {
module_platform_driver(max77802_clk_driver);
MODULE_DESCRIPTION("MAXIM 77802 Clock Driver");
-MODULE_AUTHOR("Javier Martinez Canillas <javier.martinez@collabora.co.uk>");
+MODULE_AUTHOR("Javier Martinez Canillas <javier@osg.samsung.com");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c
new file mode 100644
index 000000000000..fe7806506bf3
--- /dev/null
+++ b/drivers/clk/clk-multiplier.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.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/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw)
+
+static unsigned long __get_mult(struct clk_multiplier *mult,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
+ return DIV_ROUND_CLOSEST(rate, parent_rate);
+
+ return rate / parent_rate;
+}
+
+static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_multiplier *mult = to_clk_multiplier(hw);
+ unsigned long val;
+
+ val = clk_readl(mult->reg) >> mult->shift;
+ val &= GENMASK(mult->width - 1, 0);
+
+ if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
+ val = 1;
+
+ return parent_rate * val;
+}
+
+static bool __is_best_rate(unsigned long rate, unsigned long new,
+ unsigned long best, unsigned long flags)
+{
+ if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
+ return abs(rate - new) < abs(rate - best);
+
+ return new >= rate && new < best;
+}
+
+static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ u8 width, unsigned long flags)
+{
+ unsigned long orig_parent_rate = *best_parent_rate;
+ unsigned long parent_rate, current_rate, best_rate = ~0;
+ unsigned int i, bestmult = 0;
+
+ if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT))
+ return rate / *best_parent_rate;
+
+ for (i = 1; i < ((1 << width) - 1); i++) {
+ if (rate == orig_parent_rate * i) {
+ /*
+ * This is the best case for us if we have a
+ * perfect match without changing the parent
+ * rate.
+ */
+ *best_parent_rate = orig_parent_rate;
+ return i;
+ }
+
+ parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+ rate / i);
+ current_rate = parent_rate * i;
+
+ if (__is_best_rate(rate, current_rate, best_rate, flags)) {
+ bestmult = i;
+ best_rate = current_rate;
+ *best_parent_rate = parent_rate;
+ }
+ }
+
+ return bestmult;
+}
+
+static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_multiplier *mult = to_clk_multiplier(hw);
+ unsigned long factor = __bestmult(hw, rate, parent_rate,
+ mult->width, mult->flags);
+
+ return *parent_rate * factor;
+}
+
+static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_multiplier *mult = to_clk_multiplier(hw);
+ unsigned long factor = __get_mult(mult, rate, parent_rate);
+ unsigned long flags = 0;
+ unsigned long val;
+
+ if (mult->lock)
+ spin_lock_irqsave(mult->lock, flags);
+ else
+ __acquire(mult->lock);
+
+ val = clk_readl(mult->reg);
+ val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
+ val |= factor << mult->shift;
+ clk_writel(val, mult->reg);
+
+ if (mult->lock)
+ spin_unlock_irqrestore(mult->lock, flags);
+ else
+ __release(mult->lock);
+
+ return 0;
+}
+
+const struct clk_ops clk_multiplier_ops = {
+ .recalc_rate = clk_multiplier_recalc_rate,
+ .round_rate = clk_multiplier_round_rate,
+ .set_rate = clk_multiplier_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_multiplier_ops);
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index cda90a971e39..1ab0fb81c6a0 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -10,7 +10,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/fsl/guts.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -19,213 +21,1029 @@
#include <linux/of.h>
#include <linux/slab.h>
-struct cmux_clk {
+#define PLL_DIV1 0
+#define PLL_DIV2 1
+#define PLL_DIV3 2
+#define PLL_DIV4 3
+
+#define PLATFORM_PLL 0
+#define CGA_PLL1 1
+#define CGA_PLL2 2
+#define CGA_PLL3 3
+#define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */
+#define CGB_PLL1 4
+#define CGB_PLL2 5
+
+struct clockgen_pll_div {
+ struct clk *clk;
+ char name[32];
+};
+
+struct clockgen_pll {
+ struct clockgen_pll_div div[4];
+};
+
+#define CLKSEL_VALID 1
+#define CLKSEL_80PCT 2 /* Only allowed if PLL <= 80% of max cpu freq */
+
+struct clockgen_sourceinfo {
+ u32 flags; /* CLKSEL_xxx */
+ int pll; /* CGx_PLLn */
+ int div; /* PLL_DIVn */
+};
+
+#define NUM_MUX_PARENTS 16
+
+struct clockgen_muxinfo {
+ struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
+};
+
+#define NUM_HWACCEL 5
+#define NUM_CMUX 8
+
+struct clockgen;
+
+/*
+ * cmux freq must be >= platform pll.
+ * If not set, cmux freq must be >= platform pll/2
+ */
+#define CG_CMUX_GE_PLAT 1
+
+#define CG_PLL_8BIT 2 /* PLLCnGSR[CFG] is 8 bits, not 6 */
+#define CG_VER3 4 /* version 3 cg: reg layout different */
+#define CG_LITTLE_ENDIAN 8
+
+struct clockgen_chipinfo {
+ const char *compat, *guts_compat;
+ const struct clockgen_muxinfo *cmux_groups[2];
+ const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
+ void (*init_periph)(struct clockgen *cg);
+ int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
+ u32 pll_mask; /* 1 << n bit set if PLL n is valid */
+ u32 flags; /* CG_xxx */
+};
+
+struct clockgen {
+ struct device_node *node;
+ void __iomem *regs;
+ struct clockgen_chipinfo info; /* mutable copy */
+ struct clk *sysclk;
+ struct clockgen_pll pll[6];
+ struct clk *cmux[NUM_CMUX];
+ struct clk *hwaccel[NUM_HWACCEL];
+ struct clk *fman[2];
+ struct ccsr_guts __iomem *guts;
+};
+
+static struct clockgen clockgen;
+
+static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
+{
+ if (cg->info.flags & CG_LITTLE_ENDIAN)
+ iowrite32(val, reg);
+ else
+ iowrite32be(val, reg);
+}
+
+static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
+{
+ u32 val;
+
+ if (cg->info.flags & CG_LITTLE_ENDIAN)
+ val = ioread32(reg);
+ else
+ val = ioread32be(reg);
+
+ return val;
+}
+
+static const struct clockgen_muxinfo p2041_cmux_grp1 = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ }
+};
+
+static const struct clockgen_muxinfo p2041_cmux_grp2 = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ }
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp1 = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+ }
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp2 = {
+ {
+ [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ }
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp1 = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+ [5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
+ }
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp2 = {
+ {
+ [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
+ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ }
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp1 = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ [8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
+ }
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp2 = {
+ {
+ [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+ [8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+ [9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+ [12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
+ [13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
+ }
+};
+
+static const struct clockgen_muxinfo t1023_cmux = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ }
+};
+
+static const struct clockgen_muxinfo t1040_cmux = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ }
+};
+
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga = {
+ {
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
+ },
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
+ {
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ },
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
+ {
+ { CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1043a_hwa1 = {
+ {
+ {},
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ {},
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1043a_hwa2 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo t1023_hwa1 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo t1023_hwa2 = {
+ {
+ [6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ },
+};
+
+static const struct clockgen_muxinfo t2080_hwa1 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo t2080_hwa2 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo t4240_hwa1 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo t4240_hwa4 = {
+ {
+ [2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+ [3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+ [4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+ [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ [6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+ },
+};
+
+static const struct clockgen_muxinfo t4240_hwa5 = {
+ {
+ [2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+ [3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
+ [4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+ [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ [6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+ [7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+ },
+};
+
+#define RCWSR7_FM1_CLK_SEL 0x40000000
+#define RCWSR7_FM2_CLK_SEL 0x20000000
+#define RCWSR7_HWA_ASYNC_DIV 0x04000000
+
+static void __init p2041_init_periph(struct clockgen *cg)
+{
+ u32 reg;
+
+ reg = ioread32be(&cg->guts->rcwsr[7]);
+
+ if (reg & RCWSR7_FM1_CLK_SEL)
+ cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
+ else
+ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p4080_init_periph(struct clockgen *cg)
+{
+ u32 reg;
+
+ reg = ioread32be(&cg->guts->rcwsr[7]);
+
+ if (reg & RCWSR7_FM1_CLK_SEL)
+ cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+ else
+ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+ if (reg & RCWSR7_FM2_CLK_SEL)
+ cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+ else
+ cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5020_init_periph(struct clockgen *cg)
+{
+ u32 reg;
+ int div = PLL_DIV2;
+
+ reg = ioread32be(&cg->guts->rcwsr[7]);
+ if (reg & RCWSR7_HWA_ASYNC_DIV)
+ div = PLL_DIV4;
+
+ if (reg & RCWSR7_FM1_CLK_SEL)
+ cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
+ else
+ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5040_init_periph(struct clockgen *cg)
+{
+ u32 reg;
+ int div = PLL_DIV2;
+
+ reg = ioread32be(&cg->guts->rcwsr[7]);
+ if (reg & RCWSR7_HWA_ASYNC_DIV)
+ div = PLL_DIV4;
+
+ if (reg & RCWSR7_FM1_CLK_SEL)
+ cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
+ else
+ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+ if (reg & RCWSR7_FM2_CLK_SEL)
+ cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
+ else
+ cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init t1023_init_periph(struct clockgen *cg)
+{
+ cg->fman[0] = cg->hwaccel[1];
+}
+
+static void __init t1040_init_periph(struct clockgen *cg)
+{
+ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
+}
+
+static void __init t2080_init_periph(struct clockgen *cg)
+{
+ cg->fman[0] = cg->hwaccel[0];
+}
+
+static void __init t4240_init_periph(struct clockgen *cg)
+{
+ cg->fman[0] = cg->hwaccel[3];
+ cg->fman[1] = cg->hwaccel[4];
+}
+
+static const struct clockgen_chipinfo chipinfo[] = {
+ {
+ .compat = "fsl,b4420-clockgen",
+ .guts_compat = "fsl,b4860-device-config",
+ .init_periph = t2080_init_periph,
+ .cmux_groups = {
+ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+ },
+ .hwaccel = {
+ &t2080_hwa1
+ },
+ .cmux_to_group = {
+ 0, 1, 1, 1, -1
+ },
+ .pll_mask = 0x3f,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,b4860-clockgen",
+ .guts_compat = "fsl,b4860-device-config",
+ .init_periph = t2080_init_periph,
+ .cmux_groups = {
+ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+ },
+ .hwaccel = {
+ &t2080_hwa1
+ },
+ .cmux_to_group = {
+ 0, 1, 1, 1, -1
+ },
+ .pll_mask = 0x3f,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,ls1021a-clockgen",
+ .cmux_groups = {
+ &t1023_cmux
+ },
+ .cmux_to_group = {
+ 0, -1
+ },
+ .pll_mask = 0x03,
+ },
+ {
+ .compat = "fsl,ls1043a-clockgen",
+ .init_periph = t2080_init_periph,
+ .cmux_groups = {
+ &t1040_cmux
+ },
+ .hwaccel = {
+ &ls1043a_hwa1, &ls1043a_hwa2
+ },
+ .cmux_to_group = {
+ 0, -1
+ },
+ .pll_mask = 0x07,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,ls2080a-clockgen",
+ .cmux_groups = {
+ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+ },
+ .cmux_to_group = {
+ 0, 0, 1, 1, -1
+ },
+ .pll_mask = 0x37,
+ .flags = CG_VER3 | CG_LITTLE_ENDIAN,
+ },
+ {
+ .compat = "fsl,p2041-clockgen",
+ .guts_compat = "fsl,qoriq-device-config-1.0",
+ .init_periph = p2041_init_periph,
+ .cmux_groups = {
+ &p2041_cmux_grp1, &p2041_cmux_grp2
+ },
+ .cmux_to_group = {
+ 0, 0, 1, 1, -1
+ },
+ .pll_mask = 0x07,
+ },
+ {
+ .compat = "fsl,p3041-clockgen",
+ .guts_compat = "fsl,qoriq-device-config-1.0",
+ .init_periph = p2041_init_periph,
+ .cmux_groups = {
+ &p2041_cmux_grp1, &p2041_cmux_grp2
+ },
+ .cmux_to_group = {
+ 0, 0, 1, 1, -1
+ },
+ .pll_mask = 0x07,
+ },
+ {
+ .compat = "fsl,p4080-clockgen",
+ .guts_compat = "fsl,qoriq-device-config-1.0",
+ .init_periph = p4080_init_periph,
+ .cmux_groups = {
+ &p4080_cmux_grp1, &p4080_cmux_grp2
+ },
+ .cmux_to_group = {
+ 0, 0, 0, 0, 1, 1, 1, 1
+ },
+ .pll_mask = 0x1f,
+ },
+ {
+ .compat = "fsl,p5020-clockgen",
+ .guts_compat = "fsl,qoriq-device-config-1.0",
+ .init_periph = p5020_init_periph,
+ .cmux_groups = {
+ &p2041_cmux_grp1, &p2041_cmux_grp2
+ },
+ .cmux_to_group = {
+ 0, 1, -1
+ },
+ .pll_mask = 0x07,
+ },
+ {
+ .compat = "fsl,p5040-clockgen",
+ .guts_compat = "fsl,p5040-device-config",
+ .init_periph = p5040_init_periph,
+ .cmux_groups = {
+ &p5040_cmux_grp1, &p5040_cmux_grp2
+ },
+ .cmux_to_group = {
+ 0, 0, 1, 1, -1
+ },
+ .pll_mask = 0x0f,
+ },
+ {
+ .compat = "fsl,t1023-clockgen",
+ .guts_compat = "fsl,t1023-device-config",
+ .init_periph = t1023_init_periph,
+ .cmux_groups = {
+ &t1023_cmux
+ },
+ .hwaccel = {
+ &t1023_hwa1, &t1023_hwa2
+ },
+ .cmux_to_group = {
+ 0, 0, -1
+ },
+ .pll_mask = 0x03,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,t1040-clockgen",
+ .guts_compat = "fsl,t1040-device-config",
+ .init_periph = t1040_init_periph,
+ .cmux_groups = {
+ &t1040_cmux
+ },
+ .cmux_to_group = {
+ 0, 0, 0, 0, -1
+ },
+ .pll_mask = 0x07,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,t2080-clockgen",
+ .guts_compat = "fsl,t2080-device-config",
+ .init_periph = t2080_init_periph,
+ .cmux_groups = {
+ &clockgen2_cmux_cga12
+ },
+ .hwaccel = {
+ &t2080_hwa1, &t2080_hwa2
+ },
+ .cmux_to_group = {
+ 0, -1
+ },
+ .pll_mask = 0x07,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,t4240-clockgen",
+ .guts_compat = "fsl,t4240-device-config",
+ .init_periph = t4240_init_periph,
+ .cmux_groups = {
+ &clockgen2_cmux_cga, &clockgen2_cmux_cgb
+ },
+ .hwaccel = {
+ &t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
+ },
+ .cmux_to_group = {
+ 0, 0, 1, -1
+ },
+ .pll_mask = 0x3f,
+ .flags = CG_PLL_8BIT,
+ },
+ {},
+};
+
+struct mux_hwclock {
struct clk_hw hw;
- void __iomem *reg;
- unsigned int clk_per_pll;
- u32 flags;
+ struct clockgen *cg;
+ const struct clockgen_muxinfo *info;
+ u32 __iomem *reg;
+ u8 parent_to_clksel[NUM_MUX_PARENTS];
+ s8 clksel_to_parent[NUM_MUX_PARENTS];
+ int num_parents;
};
-#define PLL_KILL BIT(31)
+#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, hw)
+#define CLKSEL_MASK 0x78000000
#define CLKSEL_SHIFT 27
-#define CLKSEL_ADJUST BIT(0)
-#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw)
-static int cmux_set_parent(struct clk_hw *hw, u8 idx)
+static int mux_set_parent(struct clk_hw *hw, u8 idx)
{
- struct cmux_clk *clk = to_cmux_clk(hw);
+ struct mux_hwclock *hwc = to_mux_hwclock(hw);
u32 clksel;
- clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll;
- if (clk->flags & CLKSEL_ADJUST)
- clksel += 8;
- clksel = (clksel & 0xf) << CLKSEL_SHIFT;
- iowrite32be(clksel, clk->reg);
+ if (idx >= hwc->num_parents)
+ return -EINVAL;
+
+ clksel = hwc->parent_to_clksel[idx];
+ cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
return 0;
}
-static u8 cmux_get_parent(struct clk_hw *hw)
+static u8 mux_get_parent(struct clk_hw *hw)
{
- struct cmux_clk *clk = to_cmux_clk(hw);
+ struct mux_hwclock *hwc = to_mux_hwclock(hw);
u32 clksel;
+ s8 ret;
- clksel = ioread32be(clk->reg);
- clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
- if (clk->flags & CLKSEL_ADJUST)
- clksel -= 8;
- clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4;
+ clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
- return clksel;
+ ret = hwc->clksel_to_parent[clksel];
+ if (ret < 0) {
+ pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg);
+ return 0;
+ }
+
+ return ret;
}
static const struct clk_ops cmux_ops = {
- .get_parent = cmux_get_parent,
- .set_parent = cmux_set_parent,
+ .get_parent = mux_get_parent,
+ .set_parent = mux_set_parent,
};
-static void __init core_mux_init(struct device_node *np)
+/*
+ * Don't allow setting for now, as the clock options haven't been
+ * sanitized for additional restrictions.
+ */
+static const struct clk_ops hwaccel_ops = {
+ .get_parent = mux_get_parent,
+};
+
+static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
+ struct mux_hwclock *hwc,
+ int idx)
{
- struct clk *clk;
- struct clk_init_data init;
- struct cmux_clk *cmux_clk;
- struct device_node *node;
- int rc, count, i;
- u32 offset;
- const char *clk_name;
- const char **parent_names;
- struct of_phandle_args clkspec;
+ int pll, div;
- rc = of_property_read_u32(np, "reg", &offset);
- if (rc) {
- pr_err("%s: could not get reg property\n", np->name);
- return;
- }
+ if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
+ return NULL;
- /* get the input clock source count */
- count = of_property_count_strings(np, "clock-names");
- if (count < 0) {
- pr_err("%s: get clock count error\n", np->name);
- return;
- }
- parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
- if (!parent_names)
- return;
+ pll = hwc->info->clksel[idx].pll;
+ div = hwc->info->clksel[idx].div;
- for (i = 0; i < count; i++)
- parent_names[i] = of_clk_get_parent_name(np, i);
+ return &cg->pll[pll].div[div];
+}
- cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL);
- if (!cmux_clk)
- goto err_name;
+static struct clk * __init create_mux_common(struct clockgen *cg,
+ struct mux_hwclock *hwc,
+ const struct clk_ops *ops,
+ unsigned long min_rate,
+ unsigned long pct80_rate,
+ const char *fmt, int idx)
+{
+ struct clk_init_data init = {};
+ struct clk *clk;
+ const struct clockgen_pll_div *div;
+ const char *parent_names[NUM_MUX_PARENTS];
+ char name[32];
+ int i, j;
- cmux_clk->reg = of_iomap(np, 0);
- if (!cmux_clk->reg) {
- pr_err("%s: could not map register\n", __func__);
- goto err_clk;
- }
+ snprintf(name, sizeof(name), fmt, idx);
- rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
- &clkspec);
- if (rc) {
- pr_err("%s: parse clock node error\n", __func__);
- goto err_clk;
- }
+ for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
+ unsigned long rate;
- cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np,
- "clock-output-names");
- of_node_put(clkspec.np);
+ hwc->clksel_to_parent[i] = -1;
- node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
- if (node && (offset >= 0x80))
- cmux_clk->flags = CLKSEL_ADJUST;
+ div = get_pll_div(cg, hwc, i);
+ if (!div)
+ continue;
- rc = of_property_read_string_index(np, "clock-output-names",
- 0, &clk_name);
- if (rc) {
- pr_err("%s: read clock names error\n", np->name);
- goto err_clk;
+ rate = clk_get_rate(div->clk);
+
+ if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
+ rate > pct80_rate)
+ continue;
+ if (rate < min_rate)
+ continue;
+
+ parent_names[j] = div->name;
+ hwc->parent_to_clksel[j] = i;
+ hwc->clksel_to_parent[i] = j;
+ j++;
}
- init.name = clk_name;
- init.ops = &cmux_ops;
+ init.name = name;
+ init.ops = ops;
init.parent_names = parent_names;
- init.num_parents = count;
+ init.num_parents = hwc->num_parents = j;
init.flags = 0;
- cmux_clk->hw.init = &init;
+ hwc->hw.init = &init;
+ hwc->cg = cg;
- clk = clk_register(NULL, &cmux_clk->hw);
+ clk = clk_register(NULL, &hwc->hw);
if (IS_ERR(clk)) {
- pr_err("%s: could not register clock\n", clk_name);
- goto err_clk;
+ pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+ PTR_ERR(clk));
+ kfree(hwc);
+ return NULL;
+ }
+
+ return clk;
+}
+
+static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
+{
+ struct mux_hwclock *hwc;
+ const struct clockgen_pll_div *div;
+ unsigned long plat_rate, min_rate;
+ u64 pct80_rate;
+ u32 clksel;
+
+ hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+ if (!hwc)
+ return NULL;
+
+ hwc->reg = cg->regs + 0x20 * idx;
+ hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
+
+ /*
+ * Find the rate for the default clksel, and treat it as the
+ * maximum rated core frequency. If this is an incorrect
+ * assumption, certain clock options (possibly including the
+ * default clksel) may be inappropriately excluded on certain
+ * chips.
+ */
+ clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+ div = get_pll_div(cg, hwc, clksel);
+ if (!div)
+ return NULL;
+
+ pct80_rate = clk_get_rate(div->clk);
+ pct80_rate *= 8;
+ do_div(pct80_rate, 10);
+
+ plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
+
+ if (cg->info.flags & CG_CMUX_GE_PLAT)
+ min_rate = plat_rate;
+ else
+ min_rate = plat_rate / 2;
+
+ return create_mux_common(cg, hwc, &cmux_ops, min_rate,
+ pct80_rate, "cg-cmux%d", idx);
+}
+
+static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
+{
+ struct mux_hwclock *hwc;
+
+ hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+ if (!hwc)
+ return NULL;
+
+ hwc->reg = cg->regs + 0x20 * idx + 0x10;
+ hwc->info = cg->info.hwaccel[idx];
+
+ return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
+ "cg-hwaccel%d", idx);
+}
+
+static void __init create_muxes(struct clockgen *cg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
+ if (cg->info.cmux_to_group[i] < 0)
+ break;
+ if (cg->info.cmux_to_group[i] >=
+ ARRAY_SIZE(cg->info.cmux_groups)) {
+ WARN_ON_ONCE(1);
+ continue;
+ }
+
+ cg->cmux[i] = create_one_cmux(cg, i);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
+ if (!cg->info.hwaccel[i])
+ continue;
+
+ cg->hwaccel[i] = create_one_hwaccel(cg, i);
}
+}
+
+static void __init clockgen_init(struct device_node *np);
+
+/* Legacy nodes may get probed before the parent clockgen node */
+static void __init legacy_init_clockgen(struct device_node *np)
+{
+ if (!clockgen.node)
+ clockgen_init(of_get_parent(np));
+}
+
+/* Legacy node */
+static void __init core_mux_init(struct device_node *np)
+{
+ struct clk *clk;
+ struct resource res;
+ int idx, rc;
+
+ legacy_init_clockgen(np);
+
+ if (of_address_to_resource(np, 0, &res))
+ return;
+
+ idx = (res.start & 0xf0) >> 5;
+ clk = clockgen.cmux[idx];
rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
if (rc) {
- pr_err("Could not register clock provider for node:%s\n",
- np->name);
- goto err_clk;
+ pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+ __func__, np->name, rc);
+ return;
}
- goto err_name;
+}
+
+static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
+{
+ u32 rate;
+
+ if (of_property_read_u32(node, "clock-frequency", &rate))
+ return ERR_PTR(-ENODEV);
-err_clk:
- kfree(cmux_clk);
-err_name:
- /* free *_names because they are reallocated when registered */
- kfree(parent_names);
+ return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
}
-static void __init core_pll_init(struct device_node *np)
+static struct clk *sysclk_from_parent(const char *name)
+{
+ struct clk *clk;
+ const char *parent_name;
+
+ clk = of_clk_get(clockgen.node, 0);
+ if (IS_ERR(clk))
+ return clk;
+
+ /* Register the input clock under the desired name. */
+ parent_name = __clk_get_name(clk);
+ clk = clk_register_fixed_factor(NULL, name, parent_name,
+ 0, 1, 1);
+ if (IS_ERR(clk))
+ pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+ PTR_ERR(clk));
+
+ return clk;
+}
+
+static struct clk * __init create_sysclk(const char *name)
+{
+ struct device_node *sysclk;
+ struct clk *clk;
+
+ clk = sysclk_from_fixed(clockgen.node, name);
+ if (!IS_ERR(clk))
+ return clk;
+
+ clk = sysclk_from_parent(name);
+ if (!IS_ERR(clk))
+ return clk;
+
+ sysclk = of_get_child_by_name(clockgen.node, "sysclk");
+ if (sysclk) {
+ clk = sysclk_from_fixed(sysclk, name);
+ if (!IS_ERR(clk))
+ return clk;
+ }
+
+ pr_err("%s: No input clock\n", __func__);
+ return NULL;
+}
+
+/* Legacy node */
+static void __init sysclk_init(struct device_node *node)
{
+ struct clk *clk;
+
+ legacy_init_clockgen(node);
+
+ clk = clockgen.sysclk;
+ if (clk)
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+#define PLL_KILL BIT(31)
+
+static void __init create_one_pll(struct clockgen *cg, int idx)
+{
+ u32 __iomem *reg;
u32 mult;
- int i, rc, count;
- const char *clk_name, *parent_name;
- struct clk_onecell_data *onecell_data;
- struct clk **subclks;
- void __iomem *base;
+ struct clockgen_pll *pll = &cg->pll[idx];
+ int i;
- base = of_iomap(np, 0);
- if (!base) {
- pr_err("iomap error\n");
+ if (!(cg->info.pll_mask & (1 << idx)))
return;
+
+ if (cg->info.flags & CG_VER3) {
+ switch (idx) {
+ case PLATFORM_PLL:
+ reg = cg->regs + 0x60080;
+ break;
+ case CGA_PLL1:
+ reg = cg->regs + 0x80;
+ break;
+ case CGA_PLL2:
+ reg = cg->regs + 0xa0;
+ break;
+ case CGB_PLL1:
+ reg = cg->regs + 0x10080;
+ break;
+ case CGB_PLL2:
+ reg = cg->regs + 0x100a0;
+ break;
+ default:
+ WARN_ONCE(1, "index %d\n", idx);
+ return;
+ }
+ } else {
+ if (idx == PLATFORM_PLL)
+ reg = cg->regs + 0xc00;
+ else
+ reg = cg->regs + 0x800 + 0x20 * (idx - 1);
}
- /* get the multiple of PLL */
- mult = ioread32be(base);
+ /* Get the multiple of PLL */
+ mult = cg_in(cg, reg);
- /* check if this PLL is disabled */
+ /* Check if this PLL is disabled */
if (mult & PLL_KILL) {
- pr_debug("PLL:%s is disabled\n", np->name);
- goto err_map;
+ pr_debug("%s(): pll %p disabled\n", __func__, reg);
+ return;
}
- mult = (mult >> 1) & 0x3f;
- parent_name = of_clk_get_parent_name(np, 0);
- if (!parent_name) {
- pr_err("PLL: %s must have a parent\n", np->name);
- goto err_map;
+ if ((cg->info.flags & CG_VER3) ||
+ ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
+ mult = (mult & GENMASK(8, 1)) >> 1;
+ else
+ mult = (mult & GENMASK(6, 1)) >> 1;
+
+ for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
+ struct clk *clk;
+
+ snprintf(pll->div[i].name, sizeof(pll->div[i].name),
+ "cg-pll%d-div%d", idx, i + 1);
+
+ clk = clk_register_fixed_factor(NULL,
+ pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
+ if (IS_ERR(clk)) {
+ pr_err("%s: %s: register failed %ld\n",
+ __func__, pll->div[i].name, PTR_ERR(clk));
+ continue;
+ }
+
+ pll->div[i].clk = clk;
}
+}
+static void __init create_plls(struct clockgen *cg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
+ create_one_pll(cg, i);
+}
+
+static void __init legacy_pll_init(struct device_node *np, int idx)
+{
+ struct clockgen_pll *pll;
+ struct clk_onecell_data *onecell_data;
+ struct clk **subclks;
+ int count, rc;
+
+ legacy_init_clockgen(np);
+
+ pll = &clockgen.pll[idx];
count = of_property_count_strings(np, "clock-output-names");
- if (count < 0 || count > 4) {
- pr_err("%s: clock is not supported\n", np->name);
- goto err_map;
- }
- subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
+ BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
+ subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
if (!subclks)
- goto err_map;
+ return;
onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
if (!onecell_data)
goto err_clks;
- for (i = 0; i < count; i++) {
- rc = of_property_read_string_index(np, "clock-output-names",
- i, &clk_name);
- if (rc) {
- pr_err("%s: could not get clock names\n", np->name);
- goto err_cell;
- }
-
- /*
- * when count == 4, there are 4 output clocks:
- * /1, /2, /3, /4 respectively
- * when count < 4, there are at least 2 output clocks:
- * /1, /2, (/4, if count == 3) respectively.
- */
- if (count == 4)
- subclks[i] = clk_register_fixed_factor(NULL, clk_name,
- parent_name, 0, mult, 1 + i);
- else
-
- subclks[i] = clk_register_fixed_factor(NULL, clk_name,
- parent_name, 0, mult, 1 << i);
-
- if (IS_ERR(subclks[i])) {
- pr_err("%s: could not register clock\n", clk_name);
- goto err_cell;
- }
+ if (count <= 3) {
+ subclks[0] = pll->div[0].clk;
+ subclks[1] = pll->div[1].clk;
+ subclks[2] = pll->div[3].clk;
+ } else {
+ subclks[0] = pll->div[0].clk;
+ subclks[1] = pll->div[1].clk;
+ subclks[2] = pll->div[2].clk;
+ subclks[3] = pll->div[3].clk;
}
onecell_data->clks = subclks;
@@ -233,125 +1051,223 @@ static void __init core_pll_init(struct device_node *np)
rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
if (rc) {
- pr_err("Could not register clk provider for node:%s\n",
- np->name);
+ pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+ __func__, np->name, rc);
goto err_cell;
}
- iounmap(base);
return;
err_cell:
kfree(onecell_data);
err_clks:
kfree(subclks);
-err_map:
- iounmap(base);
}
-static void __init sysclk_init(struct device_node *node)
+/* Legacy node */
+static void __init pltfrm_pll_init(struct device_node *np)
{
- struct clk *clk;
- const char *clk_name = node->name;
- struct device_node *np = of_get_parent(node);
- u32 rate;
+ legacy_pll_init(np, PLATFORM_PLL);
+}
- if (!np) {
- pr_err("could not get parent node\n");
+/* Legacy node */
+static void __init core_pll_init(struct device_node *np)
+{
+ struct resource res;
+ int idx;
+
+ if (of_address_to_resource(np, 0, &res))
return;
+
+ if ((res.start & 0xfff) == 0xc00) {
+ /*
+ * ls1021a devtree labels the platform PLL
+ * with the core PLL compatible
+ */
+ pltfrm_pll_init(np);
+ } else {
+ idx = (res.start & 0xf0) >> 5;
+ legacy_pll_init(np, CGA_PLL1 + idx);
}
+}
- if (of_property_read_u32(np, "clock-frequency", &rate)) {
- of_node_put(node);
- return;
+static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct clockgen *cg = data;
+ struct clk *clk;
+ struct clockgen_pll *pll;
+ u32 type, idx;
+
+ if (clkspec->args_count < 2) {
+ pr_err("%s: insufficient phandle args\n", __func__);
+ return ERR_PTR(-EINVAL);
}
- of_property_read_string(np, "clock-output-names", &clk_name);
+ type = clkspec->args[0];
+ idx = clkspec->args[1];
- clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
- if (!IS_ERR(clk))
- of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ switch (type) {
+ case 0:
+ if (idx != 0)
+ goto bad_args;
+ clk = cg->sysclk;
+ break;
+ case 1:
+ if (idx >= ARRAY_SIZE(cg->cmux))
+ goto bad_args;
+ clk = cg->cmux[idx];
+ break;
+ case 2:
+ if (idx >= ARRAY_SIZE(cg->hwaccel))
+ goto bad_args;
+ clk = cg->hwaccel[idx];
+ break;
+ case 3:
+ if (idx >= ARRAY_SIZE(cg->fman))
+ goto bad_args;
+ clk = cg->fman[idx];
+ break;
+ case 4:
+ pll = &cg->pll[PLATFORM_PLL];
+ if (idx >= ARRAY_SIZE(pll->div))
+ goto bad_args;
+ clk = pll->div[idx].clk;
+ break;
+ default:
+ goto bad_args;
+ }
+
+ if (!clk)
+ return ERR_PTR(-ENOENT);
+ return clk;
+
+bad_args:
+ pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx);
+ return ERR_PTR(-EINVAL);
}
-static void __init pltfrm_pll_init(struct device_node *np)
+#ifdef CONFIG_PPC
+#include <asm/mpc85xx.h>
+
+static const u32 a4510_svrs[] __initconst = {
+ (SVR_P2040 << 8) | 0x10, /* P2040 1.0 */
+ (SVR_P2040 << 8) | 0x11, /* P2040 1.1 */
+ (SVR_P2041 << 8) | 0x10, /* P2041 1.0 */
+ (SVR_P2041 << 8) | 0x11, /* P2041 1.1 */
+ (SVR_P3041 << 8) | 0x10, /* P3041 1.0 */
+ (SVR_P3041 << 8) | 0x11, /* P3041 1.1 */
+ (SVR_P4040 << 8) | 0x20, /* P4040 2.0 */
+ (SVR_P4080 << 8) | 0x20, /* P4080 2.0 */
+ (SVR_P5010 << 8) | 0x10, /* P5010 1.0 */
+ (SVR_P5010 << 8) | 0x20, /* P5010 2.0 */
+ (SVR_P5020 << 8) | 0x10, /* P5020 1.0 */
+ (SVR_P5021 << 8) | 0x10, /* P5021 1.0 */
+ (SVR_P5040 << 8) | 0x10, /* P5040 1.0 */
+};
+
+#define SVR_SECURITY 0x80000 /* The Security (E) bit */
+
+static bool __init has_erratum_a4510(void)
{
- void __iomem *base;
- uint32_t mult;
- const char *parent_name, *clk_name;
- int i, _errno;
- struct clk_onecell_data *cod;
+ u32 svr = mfspr(SPRN_SVR);
+ int i;
- base = of_iomap(np, 0);
- if (!base) {
- pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
- return;
+ svr &= ~SVR_SECURITY;
+
+ for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
+ if (svr == a4510_svrs[i])
+ return true;
}
- /* Get the multiple of PLL */
- mult = ioread32be(base);
+ return false;
+}
+#else
+static bool __init has_erratum_a4510(void)
+{
+ return false;
+}
+#endif
- iounmap(base);
+static void __init clockgen_init(struct device_node *np)
+{
+ int i, ret;
+ bool is_old_ls1021a = false;
- /* Check if this PLL is disabled */
- if (mult & PLL_KILL) {
- pr_debug("%s(): %s: Disabled\n", __func__, np->name);
+ /* May have already been called by a legacy probe */
+ if (clockgen.node)
return;
- }
- mult = (mult & GENMASK(6, 1)) >> 1;
- parent_name = of_clk_get_parent_name(np, 0);
- if (!parent_name) {
- pr_err("%s(): %s: of_clk_get_parent_name() failed\n",
- __func__, np->name);
+ clockgen.node = np;
+ clockgen.regs = of_iomap(np, 0);
+ if (!clockgen.regs &&
+ of_device_is_compatible(of_root, "fsl,ls1021a")) {
+ /* Compatibility hack for old, broken device trees */
+ clockgen.regs = ioremap(0x1ee1000, 0x1000);
+ is_old_ls1021a = true;
+ }
+ if (!clockgen.regs) {
+ pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
return;
}
- i = of_property_count_strings(np, "clock-output-names");
- if (i < 0) {
- pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n",
- __func__, np->name, i);
- return;
+ for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
+ if (of_device_is_compatible(np, chipinfo[i].compat))
+ break;
+ if (is_old_ls1021a &&
+ !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
+ break;
}
- cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL);
- if (!cod)
- return;
- cod->clks = (struct clk **)(cod + 1);
- cod->clk_num = i;
-
- for (i = 0; i < cod->clk_num; i++) {
- _errno = of_property_read_string_index(np, "clock-output-names",
- i, &clk_name);
- if (_errno < 0) {
- pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n",
- __func__, np->name, _errno);
- goto return_clk_unregister;
- }
+ if (i == ARRAY_SIZE(chipinfo)) {
+ pr_err("%s: unknown clockgen node %s\n", __func__,
+ np->full_name);
+ goto err;
+ }
+ clockgen.info = chipinfo[i];
+
+ if (clockgen.info.guts_compat) {
+ struct device_node *guts;
- cod->clks[i] = clk_register_fixed_factor(NULL, clk_name,
- parent_name, 0, mult, 1 + i);
- if (IS_ERR(cod->clks[i])) {
- pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n",
- __func__, np->name,
- clk_name, PTR_ERR(cod->clks[i]));
- goto return_clk_unregister;
+ guts = of_find_compatible_node(NULL, NULL,
+ clockgen.info.guts_compat);
+ if (guts) {
+ clockgen.guts = of_iomap(guts, 0);
+ if (!clockgen.guts) {
+ pr_err("%s: Couldn't map %s regs\n", __func__,
+ guts->full_name);
+ }
}
+
}
- _errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod);
- if (_errno < 0) {
- pr_err("%s(): %s: of_clk_add_provider() = %d\n",
- __func__, np->name, _errno);
- goto return_clk_unregister;
+ if (has_erratum_a4510())
+ clockgen.info.flags |= CG_CMUX_GE_PLAT;
+
+ clockgen.sysclk = create_sysclk("cg-sysclk");
+ create_plls(&clockgen);
+ create_muxes(&clockgen);
+
+ if (clockgen.info.init_periph)
+ clockgen.info.init_periph(&clockgen);
+
+ ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
+ if (ret) {
+ pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+ __func__, np->name, ret);
}
return;
-
-return_clk_unregister:
- while (--i >= 0)
- clk_unregister(cod->clks[i]);
- kfree(cod);
+err:
+ iounmap(clockgen.regs);
+ clockgen.regs = NULL;
}
+CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
+
+/* Legacy nodes */
CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c
new file mode 100644
index 000000000000..0b501a9fef92
--- /dev/null
+++ b/drivers/clk/clk-scpi.c
@@ -0,0 +1,325 @@
+/*
+ * System Control and Power Interface (SCPI) Protocol based clock driver
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/scpi_protocol.h>
+
+struct scpi_clk {
+ u32 id;
+ struct clk_hw hw;
+ struct scpi_dvfs_info *info;
+ struct scpi_ops *scpi_ops;
+};
+
+#define to_scpi_clk(clk) container_of(clk, struct scpi_clk, hw)
+
+static struct platform_device *cpufreq_dev;
+
+static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct scpi_clk *clk = to_scpi_clk(hw);
+
+ return clk->scpi_ops->clk_get_val(clk->id);
+}
+
+static long scpi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ /*
+ * We can't figure out what rate it will be, so just return the
+ * rate back to the caller. scpi_clk_recalc_rate() will be called
+ * after the rate is set and we'll know what rate the clock is
+ * running at then.
+ */
+ return rate;
+}
+
+static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct scpi_clk *clk = to_scpi_clk(hw);
+
+ return clk->scpi_ops->clk_set_val(clk->id, rate);
+}
+
+static const struct clk_ops scpi_clk_ops = {
+ .recalc_rate = scpi_clk_recalc_rate,
+ .round_rate = scpi_clk_round_rate,
+ .set_rate = scpi_clk_set_rate,
+};
+
+/* find closest match to given frequency in OPP table */
+static int __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate)
+{
+ int idx;
+ u32 fmin = 0, fmax = ~0, ftmp;
+ const struct scpi_opp *opp = clk->info->opps;
+
+ for (idx = 0; idx < clk->info->count; idx++, opp++) {
+ ftmp = opp->freq;
+ if (ftmp >= (u32)rate) {
+ if (ftmp <= fmax)
+ fmax = ftmp;
+ break;
+ } else if (ftmp >= fmin) {
+ fmin = ftmp;
+ }
+ }
+ return fmax != ~0 ? fmax : fmin;
+}
+
+static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct scpi_clk *clk = to_scpi_clk(hw);
+ int idx = clk->scpi_ops->dvfs_get_idx(clk->id);
+ const struct scpi_opp *opp;
+
+ if (idx < 0)
+ return 0;
+
+ opp = clk->info->opps + idx;
+ return opp->freq;
+}
+
+static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct scpi_clk *clk = to_scpi_clk(hw);
+
+ return __scpi_dvfs_round_rate(clk, rate);
+}
+
+static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate)
+{
+ int idx, max_opp = clk->info->count;
+ const struct scpi_opp *opp = clk->info->opps;
+
+ for (idx = 0; idx < max_opp; idx++, opp++)
+ if (opp->freq == rate)
+ return idx;
+ return -EINVAL;
+}
+
+static int scpi_dvfs_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct scpi_clk *clk = to_scpi_clk(hw);
+ int ret = __scpi_find_dvfs_index(clk, rate);
+
+ if (ret < 0)
+ return ret;
+ return clk->scpi_ops->dvfs_set_idx(clk->id, (u8)ret);
+}
+
+static const struct clk_ops scpi_dvfs_ops = {
+ .recalc_rate = scpi_dvfs_recalc_rate,
+ .round_rate = scpi_dvfs_round_rate,
+ .set_rate = scpi_dvfs_set_rate,
+};
+
+static const struct of_device_id scpi_clk_match[] = {
+ { .compatible = "arm,scpi-dvfs-clocks", .data = &scpi_dvfs_ops, },
+ { .compatible = "arm,scpi-variable-clocks", .data = &scpi_clk_ops, },
+ {}
+};
+
+static struct clk *
+scpi_clk_ops_init(struct device *dev, const struct of_device_id *match,
+ struct scpi_clk *sclk, const char *name)
+{
+ struct clk_init_data init;
+ struct clk *clk;
+ unsigned long min = 0, max = 0;
+
+ init.name = name;
+ init.flags = CLK_IS_ROOT;
+ init.num_parents = 0;
+ init.ops = match->data;
+ sclk->hw.init = &init;
+ sclk->scpi_ops = get_scpi_ops();
+
+ if (init.ops == &scpi_dvfs_ops) {
+ sclk->info = sclk->scpi_ops->dvfs_get_info(sclk->id);
+ if (IS_ERR(sclk->info))
+ return NULL;
+ } else if (init.ops == &scpi_clk_ops) {
+ if (sclk->scpi_ops->clk_get_range(sclk->id, &min, &max) || !max)
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+ clk = devm_clk_register(dev, &sclk->hw);
+ if (!IS_ERR(clk) && max)
+ clk_hw_set_rate_range(&sclk->hw, min, max);
+ return clk;
+}
+
+struct scpi_clk_data {
+ struct scpi_clk **clk;
+ unsigned int clk_num;
+};
+
+static struct clk *
+scpi_of_clk_src_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct scpi_clk *sclk;
+ struct scpi_clk_data *clk_data = data;
+ unsigned int idx = clkspec->args[0], count;
+
+ for (count = 0; count < clk_data->clk_num; count++) {
+ sclk = clk_data->clk[count];
+ if (idx == sclk->id)
+ return sclk->hw.clk;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static int scpi_clk_add(struct device *dev, struct device_node *np,
+ const struct of_device_id *match)
+{
+ struct clk **clks;
+ int idx, count;
+ struct scpi_clk_data *clk_data;
+
+ count = of_property_count_strings(np, "clock-output-names");
+ if (count < 0) {
+ dev_err(dev, "%s: invalid clock output count\n", np->name);
+ return -EINVAL;
+ }
+
+ clk_data = devm_kmalloc(dev, sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->clk_num = count;
+ clk_data->clk = devm_kcalloc(dev, count, sizeof(*clk_data->clk),
+ GFP_KERNEL);
+ if (!clk_data->clk)
+ return -ENOMEM;
+
+ clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ return -ENOMEM;
+
+ for (idx = 0; idx < count; idx++) {
+ struct scpi_clk *sclk;
+ const char *name;
+ u32 val;
+
+ sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
+ if (!sclk)
+ return -ENOMEM;
+
+ if (of_property_read_string_index(np, "clock-output-names",
+ idx, &name)) {
+ dev_err(dev, "invalid clock name @ %s\n", np->name);
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32_index(np, "clock-indices",
+ idx, &val)) {
+ dev_err(dev, "invalid clock index @ %s\n", np->name);
+ return -EINVAL;
+ }
+
+ sclk->id = val;
+
+ clks[idx] = scpi_clk_ops_init(dev, match, sclk, name);
+ if (IS_ERR_OR_NULL(clks[idx]))
+ dev_err(dev, "failed to register clock '%s'\n", name);
+ else
+ dev_dbg(dev, "Registered clock '%s'\n", name);
+ clk_data->clk[idx] = sclk;
+ }
+
+ return of_clk_add_provider(np, scpi_of_clk_src_get, clk_data);
+}
+
+static int scpi_clocks_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *child, *np = dev->of_node;
+
+ if (cpufreq_dev) {
+ platform_device_unregister(cpufreq_dev);
+ cpufreq_dev = NULL;
+ }
+
+ for_each_available_child_of_node(np, child)
+ of_clk_del_provider(np);
+ return 0;
+}
+
+static int scpi_clocks_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct device *dev = &pdev->dev;
+ struct device_node *child, *np = dev->of_node;
+ const struct of_device_id *match;
+
+ if (!get_scpi_ops())
+ return -ENXIO;
+
+ for_each_available_child_of_node(np, child) {
+ match = of_match_node(scpi_clk_match, child);
+ if (!match)
+ continue;
+ ret = scpi_clk_add(dev, child, match);
+ if (ret) {
+ scpi_clocks_remove(pdev);
+ return ret;
+ }
+ }
+ /* Add the virtual cpufreq device */
+ cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
+ -1, NULL, 0);
+ if (!cpufreq_dev)
+ pr_warn("unable to register cpufreq device");
+
+ return 0;
+}
+
+static const struct of_device_id scpi_clocks_ids[] = {
+ { .compatible = "arm,scpi-clocks", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, scpi_clocks_ids);
+
+static struct platform_driver scpi_clocks_driver = {
+ .driver = {
+ .name = "scpi_clocks",
+ .of_match_table = scpi_clocks_ids,
+ },
+ .probe = scpi_clocks_probe,
+ .remove = scpi_clocks_remove,
+};
+module_platform_driver(scpi_clocks_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCPI clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c
new file mode 100644
index 000000000000..6af7dce54241
--- /dev/null
+++ b/drivers/clk/clk-si514.c
@@ -0,0 +1,379 @@
+/*
+ * Driver for Silicon Labs Si514 Programmable Oscillator
+ *
+ * Copyright (C) 2015 Topic Embedded Products
+ *
+ * Author: Mike Looijmans <mike.looijmans@topic.nl>
+ *
+ * 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/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* I2C registers */
+#define SI514_REG_LP 0
+#define SI514_REG_M_FRAC1 5
+#define SI514_REG_M_FRAC2 6
+#define SI514_REG_M_FRAC3 7
+#define SI514_REG_M_INT_FRAC 8
+#define SI514_REG_M_INT 9
+#define SI514_REG_HS_DIV 10
+#define SI514_REG_LS_HS_DIV 11
+#define SI514_REG_OE_STATE 14
+#define SI514_REG_RESET 128
+#define SI514_REG_CONTROL 132
+
+/* Register values */
+#define SI514_RESET_RST BIT(7)
+
+#define SI514_CONTROL_FCAL BIT(0)
+#define SI514_CONTROL_OE BIT(2)
+
+#define SI514_MIN_FREQ 100000U
+#define SI514_MAX_FREQ 250000000U
+
+#define FXO 31980000U
+
+#define FVCO_MIN 2080000000U
+#define FVCO_MAX 2500000000U
+
+#define HS_DIV_MAX 1022
+
+struct clk_si514 {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ struct i2c_client *i2c_client;
+};
+#define to_clk_si514(_hw) container_of(_hw, struct clk_si514, hw)
+
+/* Multiplier/divider settings */
+struct clk_si514_muldiv {
+ u32 m_frac; /* 29-bit Fractional part of multiplier M */
+ u8 m_int; /* Integer part of multiplier M, 65..78 */
+ u8 ls_div_bits; /* 2nd divider, as 2^x */
+ u16 hs_div; /* 1st divider, must be even and 10<=x<=1022 */
+};
+
+/* Enables or disables the output driver */
+static int si514_enable_output(struct clk_si514 *data, bool enable)
+{
+ return regmap_update_bits(data->regmap, SI514_REG_CONTROL,
+ SI514_CONTROL_OE, enable ? SI514_CONTROL_OE : 0);
+}
+
+/* Retrieve clock multiplier and dividers from hardware */
+static int si514_get_muldiv(struct clk_si514 *data,
+ struct clk_si514_muldiv *settings)
+{
+ int err;
+ u8 reg[7];
+
+ err = regmap_bulk_read(data->regmap, SI514_REG_M_FRAC1,
+ reg, ARRAY_SIZE(reg));
+ if (err)
+ return err;
+
+ settings->m_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
+ (reg[3] & 0x1F) << 24;
+ settings->m_int = (reg[4] & 0x3f) << 3 | reg[3] >> 5;
+ settings->ls_div_bits = (reg[6] >> 4) & 0x07;
+ settings->hs_div = (reg[6] & 0x03) << 8 | reg[5];
+ return 0;
+}
+
+static int si514_set_muldiv(struct clk_si514 *data,
+ struct clk_si514_muldiv *settings)
+{
+ u8 lp;
+ u8 reg[7];
+ int err;
+
+ /* Calculate LP1/LP2 according to table 13 in the datasheet */
+ /* 65.259980246 */
+ if (settings->m_int < 65 ||
+ (settings->m_int == 65 && settings->m_frac <= 139575831))
+ lp = 0x22;
+ /* 67.859763463 */
+ else if (settings->m_int < 67 ||
+ (settings->m_int == 67 && settings->m_frac <= 461581994))
+ lp = 0x23;
+ /* 72.937624981 */
+ else if (settings->m_int < 72 ||
+ (settings->m_int == 72 && settings->m_frac <= 503383578))
+ lp = 0x33;
+ /* 75.843265046 */
+ else if (settings->m_int < 75 ||
+ (settings->m_int == 75 && settings->m_frac <= 452724474))
+ lp = 0x34;
+ else
+ lp = 0x44;
+
+ err = regmap_write(data->regmap, SI514_REG_LP, lp);
+ if (err < 0)
+ return err;
+
+ reg[0] = settings->m_frac;
+ reg[1] = settings->m_frac >> 8;
+ reg[2] = settings->m_frac >> 16;
+ reg[3] = settings->m_frac >> 24 | settings->m_int << 5;
+ reg[4] = settings->m_int >> 3;
+ reg[5] = settings->hs_div;
+ reg[6] = (settings->hs_div >> 8) | (settings->ls_div_bits << 4);
+
+ err = regmap_bulk_write(data->regmap, SI514_REG_HS_DIV, reg + 5, 2);
+ if (err < 0)
+ return err;
+ /*
+ * Writing to SI514_REG_M_INT_FRAC triggers the clock change, so that
+ * must be written last
+ */
+ return regmap_bulk_write(data->regmap, SI514_REG_M_FRAC1, reg, 5);
+}
+
+/* Calculate divider settings for a given frequency */
+static int si514_calc_muldiv(struct clk_si514_muldiv *settings,
+ unsigned long frequency)
+{
+ u64 m;
+ u32 ls_freq;
+ u32 tmp;
+ u8 res;
+
+ if ((frequency < SI514_MIN_FREQ) || (frequency > SI514_MAX_FREQ))
+ return -EINVAL;
+
+ /* Determine the minimum value of LS_DIV and resulting target freq. */
+ ls_freq = frequency;
+ if (frequency >= (FVCO_MIN / HS_DIV_MAX))
+ settings->ls_div_bits = 0;
+ else {
+ res = 1;
+ tmp = 2 * HS_DIV_MAX;
+ while (tmp <= (HS_DIV_MAX * 32)) {
+ if ((frequency * tmp) >= FVCO_MIN)
+ break;
+ ++res;
+ tmp <<= 1;
+ }
+ settings->ls_div_bits = res;
+ ls_freq = frequency << res;
+ }
+
+ /* Determine minimum HS_DIV, round up to even number */
+ settings->hs_div = DIV_ROUND_UP(FVCO_MIN >> 1, ls_freq) << 1;
+
+ /* M = LS_DIV x HS_DIV x frequency / F_XO (in fixed-point) */
+ m = ((u64)(ls_freq * settings->hs_div) << 29) + (FXO / 2);
+ do_div(m, FXO);
+ settings->m_frac = (u32)m & (BIT(29) - 1);
+ settings->m_int = (u32)(m >> 29);
+
+ return 0;
+}
+
+/* Calculate resulting frequency given the register settings */
+static unsigned long si514_calc_rate(struct clk_si514_muldiv *settings)
+{
+ u64 m = settings->m_frac | ((u64)settings->m_int << 29);
+ u32 d = settings->hs_div * BIT(settings->ls_div_bits);
+
+ return ((u32)(((m * FXO) + (FXO / 2)) >> 29)) / d;
+}
+
+static unsigned long si514_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_si514 *data = to_clk_si514(hw);
+ struct clk_si514_muldiv settings;
+ int err;
+
+ err = si514_get_muldiv(data, &settings);
+ if (err) {
+ dev_err(&data->i2c_client->dev, "unable to retrieve settings\n");
+ return 0;
+ }
+
+ return si514_calc_rate(&settings);
+}
+
+static long si514_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_si514_muldiv settings;
+ int err;
+
+ if (!rate)
+ return 0;
+
+ err = si514_calc_muldiv(&settings, rate);
+ if (err)
+ return err;
+
+ return si514_calc_rate(&settings);
+}
+
+/*
+ * Update output frequency for big frequency changes (> 1000 ppm).
+ * The chip supports <1000ppm changes "on the fly", we haven't implemented
+ * that here.
+ */
+static int si514_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_si514 *data = to_clk_si514(hw);
+ struct clk_si514_muldiv settings;
+ int err;
+
+ err = si514_calc_muldiv(&settings, rate);
+ if (err)
+ return err;
+
+ si514_enable_output(data, false);
+
+ err = si514_set_muldiv(data, &settings);
+ if (err < 0)
+ return err; /* Undefined state now, best to leave disabled */
+
+ /* Trigger calibration */
+ err = regmap_write(data->regmap, SI514_REG_CONTROL, SI514_CONTROL_FCAL);
+ if (err < 0)
+ return err;
+
+ /* Applying a new frequency can take up to 10ms */
+ usleep_range(10000, 12000);
+
+ si514_enable_output(data, true);
+
+ return err;
+}
+
+static const struct clk_ops si514_clk_ops = {
+ .recalc_rate = si514_recalc_rate,
+ .round_rate = si514_round_rate,
+ .set_rate = si514_set_rate,
+};
+
+static bool si514_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SI514_REG_CONTROL:
+ case SI514_REG_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool si514_regmap_is_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SI514_REG_LP:
+ case SI514_REG_M_FRAC1 ... SI514_REG_LS_HS_DIV:
+ case SI514_REG_OE_STATE:
+ case SI514_REG_RESET:
+ case SI514_REG_CONTROL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config si514_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = SI514_REG_CONTROL,
+ .writeable_reg = si514_regmap_is_writeable,
+ .volatile_reg = si514_regmap_is_volatile,
+};
+
+static int si514_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct clk_si514 *data;
+ struct clk_init_data init;
+ struct clk *clk;
+ int err;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ init.ops = &si514_clk_ops;
+ init.flags = CLK_IS_ROOT;
+ init.num_parents = 0;
+ data->hw.init = &init;
+ data->i2c_client = client;
+
+ if (of_property_read_string(client->dev.of_node, "clock-output-names",
+ &init.name))
+ init.name = client->dev.of_node->name;
+
+ data->regmap = devm_regmap_init_i2c(client, &si514_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "failed to allocate register map\n");
+ return PTR_ERR(data->regmap);
+ }
+
+ i2c_set_clientdata(client, data);
+
+ clk = devm_clk_register(&client->dev, &data->hw);
+ if (IS_ERR(clk)) {
+ dev_err(&client->dev, "clock registration failed\n");
+ return PTR_ERR(clk);
+ }
+ err = of_clk_add_provider(client->dev.of_node, of_clk_src_simple_get,
+ clk);
+ if (err) {
+ dev_err(&client->dev, "unable to add clk provider\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int si514_remove(struct i2c_client *client)
+{
+ of_clk_del_provider(client->dev.of_node);
+ return 0;
+}
+
+static const struct i2c_device_id si514_id[] = {
+ { "si514", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, si514_id);
+
+static const struct of_device_id clk_si514_of_match[] = {
+ { .compatible = "silabs,si514" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, clk_si514_of_match);
+
+static struct i2c_driver si514_driver = {
+ .driver = {
+ .name = "si514",
+ .of_match_table = clk_si514_of_match,
+ },
+ .probe = si514_probe,
+ .remove = si514_remove,
+ .id_table = si514_id,
+};
+module_i2c_driver(si514_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("Si514 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 5596c0aac22f..e346b223199d 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -1183,13 +1183,13 @@ static int si5351_dt_parse(struct i2c_client *client,
if (of_property_read_u32(child, "reg", &num)) {
dev_err(&client->dev, "missing reg property of %s\n",
child->name);
- return -EINVAL;
+ goto put_child;
}
if (num >= 8 ||
(variant == SI5351_VARIANT_A3 && num >= 3)) {
dev_err(&client->dev, "invalid clkout %d\n", num);
- return -EINVAL;
+ goto put_child;
}
if (!of_property_read_u32(child, "silabs,multisynth-source",
@@ -1207,7 +1207,7 @@ static int si5351_dt_parse(struct i2c_client *client,
dev_err(&client->dev,
"invalid parent %d for multisynth %d\n",
val, num);
- return -EINVAL;
+ goto put_child;
}
}
@@ -1230,7 +1230,7 @@ static int si5351_dt_parse(struct i2c_client *client,
dev_err(&client->dev,
"invalid parent %d for clkout %d\n",
val, num);
- return -EINVAL;
+ goto put_child;
}
pdata->clkout[num].clkout_src =
SI5351_CLKOUT_SRC_CLKIN;
@@ -1239,7 +1239,7 @@ static int si5351_dt_parse(struct i2c_client *client,
dev_err(&client->dev,
"invalid parent %d for clkout %d\n",
val, num);
- return -EINVAL;
+ goto put_child;
}
}
@@ -1256,7 +1256,7 @@ static int si5351_dt_parse(struct i2c_client *client,
dev_err(&client->dev,
"invalid drive strength %d for clkout %d\n",
val, num);
- return -EINVAL;
+ goto put_child;
}
}
@@ -1283,7 +1283,7 @@ static int si5351_dt_parse(struct i2c_client *client,
dev_err(&client->dev,
"invalid disable state %d for clkout %d\n",
val, num);
- return -EINVAL;
+ goto put_child;
}
}
@@ -1296,6 +1296,9 @@ static int si5351_dt_parse(struct i2c_client *client,
client->dev.platform_data = pdata;
return 0;
+put_child:
+ of_node_put(child);
+ return -EINVAL;
}
#else
static int si5351_dt_parse(struct i2c_client *client, enum si5351_variant variant)
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index 96a6190acac2..27c0da29eca3 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -27,7 +27,6 @@
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
-#include <asm/setup.h>
/* Register SCU_PCPPLL bit fields */
#define N_DIV_RD(src) (((src) & 0x000001ff))
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0ebcf449778a..f13c3f4228d4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -272,7 +272,7 @@ late_initcall_sync(clk_disable_unused);
/*** helper functions ***/
-const char *__clk_get_name(struct clk *clk)
+const char *__clk_get_name(const struct clk *clk)
{
return !clk ? NULL : clk->core->name;
}
@@ -427,6 +427,11 @@ bool clk_hw_is_prepared(const struct clk_hw *hw)
return clk_core_is_prepared(hw->core);
}
+bool clk_hw_is_enabled(const struct clk_hw *hw)
+{
+ return clk_core_is_enabled(hw->core);
+}
+
bool __clk_is_enabled(struct clk *clk)
{
if (!clk)
@@ -1685,7 +1690,7 @@ static struct clk_core *__clk_init_parent(struct clk_core *core)
"%s: multi-parent clocks must implement .get_parent\n",
__func__);
goto out;
- };
+ }
/*
* Do our best to cache parent clocks in core->parents. This prevents
@@ -2932,7 +2937,7 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
unsigned int idx = clkspec->args[0];
if (idx >= clk_data->clk_num) {
- pr_err("%s: invalid clock index %d\n", __func__, idx);
+ pr_err("%s: invalid clock index %u\n", __func__, idx);
return ERR_PTR(-EINVAL);
}
@@ -3055,6 +3060,7 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
u32 pv;
int rc;
int count;
+ struct clk *clk;
if (index < 0)
return NULL;
@@ -3080,8 +3086,25 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
if (of_property_read_string_index(clkspec.np, "clock-output-names",
index,
- &clk_name) < 0)
- clk_name = clkspec.np->name;
+ &clk_name) < 0) {
+ /*
+ * Best effort to get the name if the clock has been
+ * registered with the framework. If the clock isn't
+ * registered, we return the node name as the name of
+ * the clock as long as #clock-cells = 0.
+ */
+ clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(clk)) {
+ if (clkspec.args_count == 0)
+ clk_name = clkspec.np->name;
+ else
+ clk_name = NULL;
+ } else {
+ clk_name = __clk_get_name(clk);
+ clk_put(clk);
+ }
+ }
+
of_node_put(clkspec.np);
return clk_name;
@@ -3179,13 +3202,15 @@ void __init of_clk_init(const struct of_device_id *matches)
list_for_each_entry_safe(clk_provider, next,
&clk_provider_list, node) {
list_del(&clk_provider->node);
+ of_node_put(clk_provider->np);
kfree(clk_provider);
}
+ of_node_put(np);
return;
}
parent->clk_init_cb = match->data;
- parent->np = np;
+ parent->np = of_node_get(np);
list_add_tail(&parent->node, &clk_provider_list);
}
@@ -3199,6 +3224,7 @@ void __init of_clk_init(const struct of_device_id *matches)
of_clk_set_defaults(clk_provider->np, true);
list_del(&clk_provider->node);
+ of_node_put(clk_provider->np);
kfree(clk_provider);
is_init_done = true;
}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c0eaf0973bd2..779b6ff0c7ad 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -333,7 +333,8 @@ int clk_add_alias(const char *alias, const char *alias_dev_name,
if (IS_ERR(r))
return PTR_ERR(r);
- l = clkdev_create(r, alias, "%s", alias_dev_name);
+ l = clkdev_create(r, alias, alias_dev_name ? "%s" : NULL,
+ alias_dev_name);
clk_put(r);
return l ? 0 : -ENODEV;
diff --git a/drivers/clk/h8300/clk-div.c b/drivers/clk/h8300/clk-div.c
index 1dd5d14d5dbe..d71d01157dbb 100644
--- a/drivers/clk/h8300/clk-div.c
+++ b/drivers/clk/h8300/clk-div.c
@@ -19,6 +19,7 @@ static void __init h8300_div_clk_setup(struct device_node *node)
const char *parent_name;
void __iomem *divcr = NULL;
int width;
+ int offset;
num_parents = of_clk_get_parent_count(node);
if (num_parents < 1) {
@@ -31,11 +32,14 @@ static void __init h8300_div_clk_setup(struct device_node *node)
pr_err("%s: failed to map divide register", clk_name);
goto error;
}
+ offset = (unsigned long)divcr & 3;
+ offset = (3 - offset) * 8;
+ divcr = (void *)((unsigned long)divcr & ~3);
parent_name = of_clk_get_parent_name(node, 0);
of_property_read_u32(node, "renesas,width", &width);
clk = clk_register_divider(NULL, clk_name, parent_name,
- CLK_SET_RATE_GATE, divcr, 0, width,
+ CLK_SET_RATE_GATE, divcr, offset, width,
CLK_DIVIDER_POWER_OF_TWO, &clklock);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
diff --git a/drivers/clk/hisilicon/clk-hi6220-stub.c b/drivers/clk/hisilicon/clk-hi6220-stub.c
index 2c4add11c1ca..8afb40ef40ce 100644
--- a/drivers/clk/hisilicon/clk-hi6220-stub.c
+++ b/drivers/clk/hisilicon/clk-hi6220-stub.c
@@ -230,7 +230,7 @@ static int hi6220_stub_clk_probe(struct platform_device *pdev)
if (IS_ERR(stub_clk->mbox)) {
dev_err(dev, "failed get mailbox channel\n");
return PTR_ERR(stub_clk->mbox);
- };
+ }
init.name = "acpu0";
init.ops = &hi6220_stub_clk_ops;
diff --git a/drivers/clk/imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c
index ec1a4c1dacf1..c4c141cab444 100644
--- a/drivers/clk/imx/clk-imx25.c
+++ b/drivers/clk/imx/clk-imx25.c
@@ -86,6 +86,16 @@ enum mx25_clks {
static struct clk *clk[clk_max];
+static struct clk ** const uart_clks[] __initconst = {
+ &clk[uart_ipg_per],
+ &clk[uart1_ipg],
+ &clk[uart2_ipg],
+ &clk[uart3_ipg],
+ &clk[uart4_ipg],
+ &clk[uart5_ipg],
+ NULL
+};
+
static int __init __mx25_clocks_init(unsigned long osc_rate,
void __iomem *ccm_base)
{
@@ -233,6 +243,8 @@ static int __init __mx25_clocks_init(unsigned long osc_rate,
*/
clk_set_parent(clk[cko_sel], clk[ipg]);
+ imx_register_uart_clocks(uart_clks);
+
return 0;
}
diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c
index d9d50d54ef2a..cf5cf75a4848 100644
--- a/drivers/clk/imx/clk-imx27.c
+++ b/drivers/clk/imx/clk-imx27.c
@@ -47,6 +47,17 @@ static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
static struct clk *clk[IMX27_CLK_MAX];
static struct clk_onecell_data clk_data;
+static struct clk ** const uart_clks[] __initconst = {
+ &clk[IMX27_CLK_PER1_GATE],
+ &clk[IMX27_CLK_UART1_IPG_GATE],
+ &clk[IMX27_CLK_UART2_IPG_GATE],
+ &clk[IMX27_CLK_UART3_IPG_GATE],
+ &clk[IMX27_CLK_UART4_IPG_GATE],
+ &clk[IMX27_CLK_UART5_IPG_GATE],
+ &clk[IMX27_CLK_UART6_IPG_GATE],
+ NULL
+};
+
static void __init _mx27_clocks_init(unsigned long fref)
{
BUG_ON(!ccm);
@@ -163,6 +174,8 @@ static void __init _mx27_clocks_init(unsigned long fref)
clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]);
+ imx_register_uart_clocks(uart_clks);
+
imx_print_silicon_rev("i.MX27", mx27_revision());
}
@@ -248,8 +261,10 @@ static void __init mx27_clocks_init_dt(struct device_node *np)
if (!of_device_is_compatible(refnp, "fsl,imx-osc26m"))
continue;
- if (!of_property_read_u32(refnp, "clock-frequency", &fref))
+ if (!of_property_read_u32(refnp, "clock-frequency", &fref)) {
+ of_node_put(refnp);
break;
+ }
}
ccm = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c
index 1f8383475bb3..6a964144a5b5 100644
--- a/drivers/clk/imx/clk-imx31.c
+++ b/drivers/clk/imx/clk-imx31.c
@@ -62,7 +62,17 @@ enum mx31_clks {
static struct clk *clk[clk_max];
static struct clk_onecell_data clk_data;
-int __init mx31_clocks_init(unsigned long fref)
+static struct clk ** const uart_clks[] __initconst = {
+ &clk[ipg],
+ &clk[uart1_gate],
+ &clk[uart2_gate],
+ &clk[uart3_gate],
+ &clk[uart4_gate],
+ &clk[uart5_gate],
+ NULL
+};
+
+static void __init _mx31_clocks_init(unsigned long fref)
{
void __iomem *base;
struct device_node *np;
@@ -132,6 +142,12 @@ int __init mx31_clocks_init(unsigned long fref)
imx_check_clocks(clk, ARRAY_SIZE(clk));
+ clk_set_parent(clk[csi], clk[upll]);
+ clk_prepare_enable(clk[emi_gate]);
+ clk_prepare_enable(clk[iim_gate]);
+ mx31_revision();
+ clk_disable_unprepare(clk[iim_gate]);
+
np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
if (np) {
@@ -139,6 +155,13 @@ int __init mx31_clocks_init(unsigned long fref)
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
+}
+
+int __init mx31_clocks_init(void)
+{
+ u32 fref = 26000000; /* default */
+
+ _mx31_clocks_init(fref);
clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
@@ -194,12 +217,8 @@ int __init mx31_clocks_init(unsigned long fref)
clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
clk_register_clkdev(clk[iim_gate], "iim", NULL);
- clk_set_parent(clk[csi], clk[upll]);
- clk_prepare_enable(clk[emi_gate]);
- clk_prepare_enable(clk[iim_gate]);
- mx31_revision();
- clk_disable_unprepare(clk[iim_gate]);
+ imx_register_uart_clocks(uart_clks);
mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31);
return 0;
@@ -214,9 +233,13 @@ int __init mx31_clocks_init_dt(void)
if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
continue;
- if (!of_property_read_u32(np, "clock-frequency", &fref))
+ if (!of_property_read_u32(np, "clock-frequency", &fref)) {
+ of_node_put(np);
break;
+ }
}
- return mx31_clocks_init(fref);
+ _mx31_clocks_init(fref);
+
+ return 0;
}
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index 8623cd4e49fd..a71d24cb4c06 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -84,7 +84,15 @@ enum mx35_clks {
static struct clk *clk[clk_max];
-int __init mx35_clocks_init(void)
+static struct clk ** const uart_clks[] __initconst = {
+ &clk[ipg],
+ &clk[uart1_gate],
+ &clk[uart2_gate],
+ &clk[uart3_gate],
+ NULL
+};
+
+static void __init _mx35_clocks_init(void)
{
void __iomem *base;
u32 pdr0, consumer_sel, hsp_sel;
@@ -220,6 +228,32 @@ int __init mx35_clocks_init(void)
imx_check_clocks(clk, ARRAY_SIZE(clk));
+ clk_prepare_enable(clk[spba_gate]);
+ clk_prepare_enable(clk[gpio1_gate]);
+ clk_prepare_enable(clk[gpio2_gate]);
+ clk_prepare_enable(clk[gpio3_gate]);
+ clk_prepare_enable(clk[iim_gate]);
+ clk_prepare_enable(clk[emi_gate]);
+ clk_prepare_enable(clk[max_gate]);
+ clk_prepare_enable(clk[iomuxc_gate]);
+
+ /*
+ * SCC is needed to boot via mmc after a watchdog reset. The clock code
+ * before conversion to common clk also enabled UART1 (which isn't
+ * handled here and not needed for mmc) and IIM (which is enabled
+ * unconditionally above).
+ */
+ clk_prepare_enable(clk[scc_gate]);
+
+ imx_register_uart_clocks(uart_clks);
+
+ imx_print_silicon_rev("i.MX35", mx35_revision());
+}
+
+int __init mx35_clocks_init(void)
+{
+ _mx35_clocks_init();
+
clk_register_clkdev(clk[pata_gate], NULL, "pata_imx");
clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0");
clk_register_clkdev(clk[can2_gate], NULL, "flexcan.1");
@@ -279,25 +313,6 @@ int __init mx35_clocks_init(void)
clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
clk_register_clkdev(clk[admux_gate], "audmux", NULL);
- clk_prepare_enable(clk[spba_gate]);
- clk_prepare_enable(clk[gpio1_gate]);
- clk_prepare_enable(clk[gpio2_gate]);
- clk_prepare_enable(clk[gpio3_gate]);
- clk_prepare_enable(clk[iim_gate]);
- clk_prepare_enable(clk[emi_gate]);
- clk_prepare_enable(clk[max_gate]);
- clk_prepare_enable(clk[iomuxc_gate]);
-
- /*
- * SCC is needed to boot via mmc after a watchdog reset. The clock code
- * before conversion to common clk also enabled UART1 (which isn't
- * handled here and not needed for mmc) and IIM (which is enabled
- * unconditionally above).
- */
- clk_prepare_enable(clk[scc_gate]);
-
- imx_print_silicon_rev("i.MX35", mx35_revision());
-
mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31);
return 0;
@@ -305,10 +320,10 @@ int __init mx35_clocks_init(void)
static void __init mx35_clocks_init_dt(struct device_node *ccm_node)
{
+ _mx35_clocks_init();
+
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data);
-
- mx35_clocks_init();
}
CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt);
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c
index a7e4f394be0d..c6770348d2ab 100644
--- a/drivers/clk/imx/clk-imx51-imx53.c
+++ b/drivers/clk/imx/clk-imx51-imx53.c
@@ -130,6 +130,20 @@ static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
static struct clk *clk[IMX5_CLK_END];
static struct clk_onecell_data clk_data;
+static struct clk ** const uart_clks[] __initconst = {
+ &clk[IMX5_CLK_UART1_IPG_GATE],
+ &clk[IMX5_CLK_UART1_PER_GATE],
+ &clk[IMX5_CLK_UART2_IPG_GATE],
+ &clk[IMX5_CLK_UART2_PER_GATE],
+ &clk[IMX5_CLK_UART3_IPG_GATE],
+ &clk[IMX5_CLK_UART3_PER_GATE],
+ &clk[IMX5_CLK_UART4_IPG_GATE],
+ &clk[IMX5_CLK_UART4_PER_GATE],
+ &clk[IMX5_CLK_UART5_IPG_GATE],
+ &clk[IMX5_CLK_UART5_PER_GATE],
+ NULL
+};
+
static void __init mx5_clocks_common_init(void __iomem *ccm_base)
{
clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
@@ -310,6 +324,8 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
+
+ imx_register_uart_clocks(uart_clks);
}
static void __init mx50_clocks_init(struct device_node *np)
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index b2c1c047dc94..c1935081d34a 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -119,6 +119,7 @@ static unsigned int share_count_ssi1;
static unsigned int share_count_ssi2;
static unsigned int share_count_ssi3;
static unsigned int share_count_mipi_core_cfg;
+static unsigned int share_count_spdif;
static inline int clk_on_imx6q(void)
{
@@ -130,6 +131,12 @@ static inline int clk_on_imx6dl(void)
return of_machine_is_compatible("fsl,imx6dl");
}
+static struct clk ** const uart_clks[] __initconst = {
+ &clk[IMX6QDL_CLK_UART_IPG],
+ &clk[IMX6QDL_CLK_UART_SERIAL],
+ NULL
+};
+
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -456,7 +463,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4);
clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
- clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14);
+ clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_spdif);
+ clk[IMX6QDL_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_spdif);
clk[IMX6QDL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
clk[IMX6QDL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
clk[IMX6QDL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
@@ -541,5 +549,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
/* All existing boards with PCIe use LVDS1 */
if (IS_ENABLED(CONFIG_PCI_IMX6))
clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
+
+ imx_register_uart_clocks(uart_clks);
}
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c
index a0d4cf26cfa9..1be6230a07af 100644
--- a/drivers/clk/imx/clk-imx6sl.c
+++ b/drivers/clk/imx/clk-imx6sl.c
@@ -97,6 +97,7 @@ static struct clk_div_table video_div_table[] = {
static unsigned int share_count_ssi1;
static unsigned int share_count_ssi2;
static unsigned int share_count_ssi3;
+static unsigned int share_count_spdif;
static struct clk *clks[IMX6SL_CLK_END];
static struct clk_onecell_data clk_data;
@@ -184,6 +185,12 @@ void imx6sl_set_wait_clk(bool enter)
imx6sl_enable_pll_arm(false);
}
+static struct clk ** const uart_clks[] __initconst = {
+ &clks[IMX6SL_CLK_UART],
+ &clks[IMX6SL_CLK_UART_SERIAL],
+ NULL
+};
+
static void __init imx6sl_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -391,7 +398,8 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6);
clks[IMX6SL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
- clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif0_podf", base + 0x7c, 14);
+ clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif0_podf", base + 0x7c, 14, &share_count_spdif);
+ clks[IMX6SL_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_spdif);
clks[IMX6SL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
clks[IMX6SL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
clks[IMX6SL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
@@ -439,5 +447,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
clks[IMX6SL_CLK_PLL2_PFD2]);
+
+ imx_register_uart_clocks(uart_clks);
}
CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index 5b95c2c2bf52..fea125eb4330 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -135,6 +135,12 @@ static u32 share_count_ssi1;
static u32 share_count_ssi2;
static u32 share_count_ssi3;
+static struct clk ** const uart_clks[] __initconst = {
+ &clks[IMX6SX_CLK_UART_IPG],
+ &clks[IMX6SX_CLK_UART_SERIAL],
+ NULL
+};
+
static void __init imx6sx_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -454,6 +460,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
clks[IMX6SX_CLK_AUDIO] = imx_clk_gate2_shared("audio", "audio_podf", base + 0x7c, 14, &share_count_audio);
clks[IMX6SX_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SX_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_audio);
clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
@@ -557,5 +564,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
+
+ imx_register_uart_clocks(uart_clks);
}
CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index aaa36650695f..01718d05e952 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -407,6 +407,24 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ /*
+ * Lower the AHB clock rate before changing the parent clock source,
+ * as AHB clock rate can NOT be higher than 133MHz, but its parent
+ * will be switched from 396MHz PFD to 528MHz PLL in order to increase
+ * AXI clock rate, so we need to lower AHB rate first to make sure at
+ * any time, AHB rate is <= 133MHz.
+ */
+ clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000);
+
+ /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]);
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]);
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]);
+
+ /* Make sure AHB rate is 132MHz */
+ clk_set_rate(clks[IMX6UL_CLK_AHB], 132000000);
+
/* set perclk to from OSC */
clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 71f3a94b472c..448ef321948b 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -363,6 +363,17 @@ static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_
static struct clk_onecell_data clk_data;
+static struct clk ** const uart_clks[] __initconst = {
+ &clks[IMX7D_UART1_ROOT_CLK],
+ &clks[IMX7D_UART2_ROOT_CLK],
+ &clks[IMX7D_UART3_ROOT_CLK],
+ &clks[IMX7D_UART4_ROOT_CLK],
+ &clks[IMX7D_UART5_ROOT_CLK],
+ &clks[IMX7D_UART6_ROOT_CLK],
+ &clks[IMX7D_UART7_ROOT_CLK],
+ NULL
+};
+
static void __init imx7d_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -818,6 +829,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
+ clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate2("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
@@ -856,5 +868,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
/* set uart module clock's parent clock source that must be great then 80MHz */
clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
+ imx_register_uart_clocks(uart_clks);
+
}
CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init);
diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c
index 20889d59b44d..b18f875eac6a 100644
--- a/drivers/clk/imx/clk-pllv2.c
+++ b/drivers/clk/imx/clk-pllv2.c
@@ -77,7 +77,7 @@ struct clk_pllv2 {
static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn)
{
- long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+ long mfi, mfn, mfd, pdf, ref_clk;
unsigned long dbl;
s64 temp;
@@ -87,19 +87,15 @@ static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
mfi = (mfi <= 5) ? 5 : mfi;
mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
- mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
- /* Sign extend to 32-bits */
- if (mfn >= 0x04000000) {
- mfn |= 0xFC000000;
- mfn_abs = -mfn;
- }
+ mfn = dp_mfn & MXC_PLL_DP_MFN_MASK;
+ mfn = sign_extend32(mfn, 26);
ref_clk = 2 * parent_rate;
if (dbl != 0)
ref_clk *= 2;
ref_clk /= (pdf + 1);
- temp = (u64) ref_clk * mfn_abs;
+ temp = (u64) ref_clk * abs(mfn);
do_div(temp, mfd + 1);
if (mfn < 0)
temp = -temp;
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
index bff45ead7389..d1b1c95177bb 100644
--- a/drivers/clk/imx/clk-vf610.c
+++ b/drivers/clk/imx/clk-vf610.c
@@ -387,6 +387,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24);
+ clk[VF610_CLK_OCOTP] = imx_clk_gate("ocotp", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(5));
imx_check_clocks(clk, ARRAY_SIZE(clk));
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index df12b5307175..a634b1185be3 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -73,3 +73,41 @@ void imx_cscmr1_fixup(u32 *val)
*val ^= CSCMR1_FIXUP;
return;
}
+
+static int imx_keep_uart_clocks __initdata;
+static struct clk ** const *imx_uart_clocks __initdata;
+
+static int __init imx_keep_uart_clocks_param(char *str)
+{
+ imx_keep_uart_clocks = 1;
+
+ return 0;
+}
+__setup_param("earlycon", imx_keep_uart_earlycon,
+ imx_keep_uart_clocks_param, 0);
+__setup_param("earlyprintk", imx_keep_uart_earlyprintk,
+ imx_keep_uart_clocks_param, 0);
+
+void __init imx_register_uart_clocks(struct clk ** const clks[])
+{
+ if (imx_keep_uart_clocks) {
+ int i;
+
+ imx_uart_clocks = clks;
+ for (i = 0; imx_uart_clocks[i]; i++)
+ clk_prepare_enable(*imx_uart_clocks[i]);
+ }
+}
+
+static int __init imx_clk_disable_uart(void)
+{
+ if (imx_keep_uart_clocks && imx_uart_clocks) {
+ int i;
+
+ for (i = 0; imx_uart_clocks[i]; i++)
+ clk_disable_unprepare(*imx_uart_clocks[i]);
+ }
+
+ return 0;
+}
+late_initcall_sync(imx_clk_disable_uart);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 1049b0c7d818..c94ac5c26226 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -7,6 +7,7 @@
extern spinlock_t imx_ccm_lock;
void imx_check_clocks(struct clk *clks[], unsigned int count);
+void imx_register_uart_clocks(struct clk ** const clks[]);
extern void imx_cscmr1_fixup(u32 *val);
diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
index 3f553d0ae0b5..a26ba2184454 100644
--- a/drivers/clk/keystone/pll.c
+++ b/drivers/clk/keystone/pll.c
@@ -157,7 +157,7 @@ out:
* _of_clk_init - PLL initialisation via DT
* @node: device tree node for this clock
* @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
- * pll controller, else it is in the control regsiter0(bit 11-6)
+ * pll controller, else it is in the control register0(bit 11-6)
*/
static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
{
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 8e4b2a4635b9..95fdfacb2ebf 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,4 @@
-obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-y += clk-mt8135.o
obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-apmixed.c b/drivers/clk/mediatek/clk-apmixed.c
new file mode 100644
index 000000000000..5303c5980867
--- /dev/null
+++ b/drivers/clk/mediatek/clk-apmixed.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+
+#define REF2USB_TX_EN BIT(0)
+#define REF2USB_TX_LPF_EN BIT(1)
+#define REF2USB_TX_OUT_EN BIT(2)
+#define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
+ REF2USB_TX_OUT_EN)
+
+struct mtk_ref2usb_tx {
+ struct clk_hw hw;
+ void __iomem *base_addr;
+};
+
+static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_ref2usb_tx, hw);
+}
+
+static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
+{
+ struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
+
+ return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
+}
+
+static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
+{
+ struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
+ u32 val;
+
+ val = readl(tx->base_addr);
+
+ val |= REF2USB_TX_EN;
+ writel(val, tx->base_addr);
+ udelay(100);
+
+ val |= REF2USB_TX_LPF_EN;
+ writel(val, tx->base_addr);
+
+ val |= REF2USB_TX_OUT_EN;
+ writel(val, tx->base_addr);
+
+ return 0;
+}
+
+static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
+{
+ struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
+ u32 val;
+
+ val = readl(tx->base_addr);
+ val &= ~REF2USB_EN_MASK;
+ writel(val, tx->base_addr);
+}
+
+static const struct clk_ops mtk_ref2usb_tx_ops = {
+ .is_prepared = mtk_ref2usb_tx_is_prepared,
+ .prepare = mtk_ref2usb_tx_prepare,
+ .unprepare = mtk_ref2usb_tx_unprepare,
+};
+
+struct clk * __init mtk_clk_register_ref2usb_tx(const char *name,
+ const char *parent_name, void __iomem *reg)
+{
+ struct mtk_ref2usb_tx *tx;
+ struct clk_init_data init = {};
+ struct clk *clk;
+
+ tx = kzalloc(sizeof(*tx), GFP_KERNEL);
+ if (!tx)
+ return ERR_PTR(-ENOMEM);
+
+ tx->base_addr = reg;
+ tx->hw.init = &init;
+
+ init.name = name;
+ init.ops = &mtk_ref2usb_tx_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(NULL, &tx->hw);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
+ kfree(tx);
+ }
+
+ return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index 57020368a693..576bdb7c98b8 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -97,7 +97,7 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
.disable = mtk_cg_disable_inv,
};
-struct clk *mtk_clk_register_gate(
+struct clk * __init mtk_clk_register_gate(
const char *name,
const char *parent_name,
struct regmap *regmap,
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 90eff85f4285..227e356403d9 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -15,21 +15,28 @@
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/mfd/syscon.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt8173-clk.h>
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+#define DUMMY_RATE 0
+
static DEFINE_SPINLOCK(mt8173_clk_lock);
-static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
- FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
- FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
- FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
- FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
+static const struct mtk_fixed_clk fixed_clks[] __initconst = {
+ FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk26m", DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk26m", 125 * MHZ),
+ FIXED_CLK(CLK_TOP_DSI0_DIG, "dsi0_dig", "clk26m", DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_DSI1_DIG, "dsi1_dig", "clk26m", DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_LVDS_PXL, "lvds_pxl", "lvdspll", DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_LVDS_CTS, "lvds_cts", "lvdspll", DUMMY_RATE),
};
static const struct mtk_fixed_factor top_divs[] __initconst = {
@@ -54,6 +61,7 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
+ FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "tvdpll_445p5m", 1, 3),
FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
@@ -590,7 +598,7 @@ static const struct mtk_composite top_muxes[] __initconst = {
MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
};
-static const struct mtk_gate_regs infra_cg_regs = {
+static const struct mtk_gate_regs infra_cg_regs __initconst = {
.set_ofs = 0x0040,
.clr_ofs = 0x0044,
.sta_ofs = 0x0048,
@@ -612,20 +620,24 @@ static const struct mtk_gate infra_clks[] __initconst = {
GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
- GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
+ GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "cpum_ck", 15),
GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
};
-static const struct mtk_gate_regs peri0_cg_regs = {
+static const struct mtk_fixed_factor infra_divs[] __initconst = {
+ FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs __initconst = {
.set_ofs = 0x0008,
.clr_ofs = 0x0010,
.sta_ofs = 0x0018,
};
-static const struct mtk_gate_regs peri1_cg_regs = {
+static const struct mtk_gate_regs peri1_cg_regs __initconst = {
.set_ofs = 0x000c,
.clr_ofs = 0x0014,
.sta_ofs = 0x001c,
@@ -701,6 +713,183 @@ static const struct mtk_composite peri_clks[] __initconst = {
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
};
+static const struct mtk_gate_regs cg_regs_4_8_0 __initconst = {
+ .set_ofs = 0x0004,
+ .clr_ofs = 0x0008,
+ .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cg_regs_4_8_0, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate img_clks[] __initconst = {
+ GATE_IMG(CLK_IMG_LARB2_SMI, "img_larb2_smi", "mm_sel", 0),
+ GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "mm_sel", 5),
+ GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "mm_sel", 6),
+ GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "camtg_sel", 7),
+ GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "mm_sel", 8),
+ GATE_IMG(CLK_IMG_CAM_SV, "img_cam_sv", "mm_sel", 9),
+ GATE_IMG(CLK_IMG_FD, "img_fd", "mm_sel", 11),
+};
+
+static const struct mtk_gate_regs mm0_cg_regs __initconst = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs __initconst = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_MM1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate mm_clks[] __initconst = {
+ /* MM0 */
+ GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
+ GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+ GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2),
+ GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3),
+ GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4),
+ GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5),
+ GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6),
+ GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7),
+ GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8),
+ GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9),
+ GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+ GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
+ GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
+ GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
+ GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 15),
+ GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16),
+ GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17),
+ GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18),
+ GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+ GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20),
+ GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
+ GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
+ GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23),
+ GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24),
+ GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
+ GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
+ GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27),
+ GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28),
+ GATE_MM0(CLK_MM_DISP_SPLIT1, "mm_disp_split1", "mm_sel", 29),
+ GATE_MM0(CLK_MM_DISP_MERGE, "mm_disp_merge", "mm_sel", 30),
+ GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31),
+ /* MM1 */
+ GATE_MM1(CLK_MM_DISP_PWM0MM, "mm_disp_pwm0mm", "mm_sel", 0),
+ GATE_MM1(CLK_MM_DISP_PWM026M, "mm_disp_pwm026m", "pwm_sel", 1),
+ GATE_MM1(CLK_MM_DISP_PWM1MM, "mm_disp_pwm1mm", "mm_sel", 2),
+ GATE_MM1(CLK_MM_DISP_PWM126M, "mm_disp_pwm126m", "pwm_sel", 3),
+ GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4),
+ GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_dig", 5),
+ GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6),
+ GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_dig", 7),
+ GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "dpi0_sel", 8),
+ GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9),
+ GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "lvds_pxl", 10),
+ GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11),
+ GATE_MM1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi0_sel", 12),
+ GATE_MM1(CLK_MM_HDMI_PLLCK, "mm_hdmi_pllck", "hdmi_sel", 13),
+ GATE_MM1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll1", 14),
+ GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll2", 15),
+ GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "lvds_pxl", 16),
+ GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvds_cts", 17),
+ GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18),
+ GATE_MM1(CLK_MM_HDMI_HDCP, "mm_hdmi_hdcp", "hdcp_sel", 19),
+ GATE_MM1(CLK_MM_HDMI_HDCP24M, "mm_hdmi_hdcp24m", "hdcp_24m_sel", 20),
+};
+
+static const struct mtk_gate_regs vdec0_cg_regs __initconst = {
+ .set_ofs = 0x0000,
+ .clr_ofs = 0x0004,
+ .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs __initconst = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x000c,
+ .sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate vdec_clks[] __initconst = {
+ GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LARB_CKEN, "vdec_larb_cken", "mm_sel", 0),
+};
+
+#define GATE_VENC(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cg_regs_4_8_0, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate venc_clks[] __initconst = {
+ GATE_VENC(CLK_VENC_CKE0, "venc_cke0", "mm_sel", 0),
+ GATE_VENC(CLK_VENC_CKE1, "venc_cke1", "venc_sel", 4),
+ GATE_VENC(CLK_VENC_CKE2, "venc_cke2", "venc_sel", 8),
+ GATE_VENC(CLK_VENC_CKE3, "venc_cke3", "venc_sel", 12),
+};
+
+#define GATE_VENCLT(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cg_regs_4_8_0, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate venclt_clks[] __initconst = {
+ GATE_VENCLT(CLK_VENCLT_CKE0, "venclt_cke0", "mm_sel", 0),
+ GATE_VENCLT(CLK_VENCLT_CKE1, "venclt_cke1", "venclt_sel", 4),
+};
+
static struct clk_onecell_data *mt8173_top_clk_data __initdata;
static struct clk_onecell_data *mt8173_pll_clk_data __initdata;
@@ -731,7 +920,7 @@ static void __init mtk_topckgen_init(struct device_node *node)
mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
- mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+ mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data);
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
&mt8173_clk_lock, clk_data);
@@ -754,6 +943,7 @@ static void __init mtk_infrasys_init(struct device_node *node)
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
+ mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
@@ -792,6 +982,24 @@ static void __init mtk_pericfg_init(struct device_node *node)
}
CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
+struct mtk_clk_usb {
+ int id;
+ const char *name;
+ const char *parent;
+ u32 reg_ofs;
+};
+
+#define APMIXED_USB(_id, _name, _parent, _reg_ofs) { \
+ .id = _id, \
+ .name = _name, \
+ .parent = _parent, \
+ .reg_ofs = _reg_ofs, \
+ }
+
+static const struct mtk_clk_usb apmixed_usb[] __initconst = {
+ APMIXED_USB(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
+};
+
#define MT8173_PLL_FMAX (3000UL * MHZ)
#define CON0_MT8173_RST_BAR BIT(24)
@@ -852,6 +1060,15 @@ static const struct mtk_pll_data plls[] = {
static void __init mtk_apmixedsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ struct clk *clk;
+ int r, i;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
@@ -859,7 +1076,113 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+ for (i = 0; i < ARRAY_SIZE(apmixed_usb); i++) {
+ const struct mtk_clk_usb *cku = &apmixed_usb[i];
+
+ clk = mtk_clk_register_ref2usb_tx(cku->name, cku->parent,
+ base + cku->reg_ofs);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n", cku->name,
+ PTR_ERR(clk));
+ continue;
+ }
+
+ clk_data->clks[cku->id] = clk;
+ }
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
mtk_clk_enable_critical();
}
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
mtk_apmixedsys_init);
+
+static void __init mtk_imgsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
+
+ mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init);
+
+static void __init mtk_mmsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+
+ mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt8173-mmsys", mtk_mmsys_init);
+
+static void __init mtk_vdecsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+
+ mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8173-vdecsys", mtk_vdecsys_init);
+
+static void __init mtk_vencsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+
+ mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt8173-vencsys", mtk_vencsys_init);
+
+static void __init mtk_vencltsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK);
+
+ mtk_clk_register_gates(node, venclt_clks, ARRAY_SIZE(venclt_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_vencltsys, "mediatek,mt8173-vencltsys", mtk_vencltsys_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 18444aea63c9..cf08db6c130c 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -24,7 +24,7 @@
#include "clk-mtk.h"
#include "clk-gate.h"
-struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
+struct clk_onecell_data * __init mtk_alloc_clk_data(unsigned int clk_num)
{
int i;
struct clk_onecell_data *clk_data;
@@ -49,8 +49,31 @@ err_out:
return NULL;
}
-void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
- struct clk_onecell_data *clk_data)
+void __init mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
+ int num, struct clk_onecell_data *clk_data)
+{
+ int i;
+ struct clk *clk;
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_fixed_clk *rc = &clks[i];
+
+ clk = clk_register_fixed_rate(NULL, rc->name, rc->parent,
+ rc->parent ? 0 : CLK_IS_ROOT, rc->rate);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ rc->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[rc->id] = clk;
+ }
+}
+
+void __init mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+ int num, struct clk_onecell_data *clk_data)
{
int i;
struct clk *clk;
@@ -72,7 +95,8 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
}
}
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+int __init mtk_clk_register_gates(struct device_node *node,
+ const struct mtk_gate *clks,
int num, struct clk_onecell_data *clk_data)
{
int i;
@@ -111,7 +135,7 @@ int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks
return 0;
}
-struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+struct clk * __init mtk_clk_register_composite(const struct mtk_composite *mc,
void __iomem *base, spinlock_t *lock)
{
struct clk *clk;
@@ -196,7 +220,7 @@ err_out:
return ERR_PTR(ret);
}
-void mtk_clk_register_composites(const struct mtk_composite *mcs,
+void __init mtk_clk_register_composites(const struct mtk_composite *mcs,
int num, void __iomem *base, spinlock_t *lock,
struct clk_onecell_data *clk_data)
{
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index c5cbecb3d218..32d2e455eb3f 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -26,6 +26,23 @@ struct clk;
#define MHZ (1000 * 1000)
+struct mtk_fixed_clk {
+ int id;
+ const char *name;
+ const char *parent;
+ unsigned long rate;
+};
+
+#define FIXED_CLK(_id, _name, _parent, _rate) { \
+ .id = _id, \
+ .name = _name, \
+ .parent = _parent, \
+ .rate = _rate, \
+ }
+
+void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
+ int num, struct clk_onecell_data *clk_data);
+
struct mtk_fixed_factor {
int id;
const char *name;
@@ -42,7 +59,7 @@ struct mtk_fixed_factor {
.div = _div, \
}
-extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
int num, struct clk_onecell_data *clk_data);
struct mtk_composite {
@@ -159,10 +176,13 @@ struct mtk_pll_data {
const struct mtk_pll_div_table *div_table;
};
-void __init mtk_clk_register_plls(struct device_node *node,
+void mtk_clk_register_plls(struct device_node *node,
const struct mtk_pll_data *plls, int num_plls,
struct clk_onecell_data *clk_data);
+struct clk *mtk_clk_register_ref2usb_tx(const char *name,
+ const char *parent_name, void __iomem *reg);
+
#ifdef CONFIG_RESET_CONTROLLER
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs);
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 622e7b6c62b4..966cab1348da 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -317,7 +317,7 @@ void __init mtk_clk_register_plls(struct device_node *node,
const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
{
void __iomem *base;
- int r, i;
+ int i;
struct clk *clk;
base = of_iomap(node, 0);
@@ -339,9 +339,4 @@ void __init mtk_clk_register_plls(struct device_node *node,
clk_data->clks[pll->id] = clk;
}
-
- r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
- if (r)
- pr_err("%s(): could not register clock provider: %d\n",
- __func__, r);
}
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 4a22429cd7a2..28aac67e7b92 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -165,7 +165,7 @@ void __init mvebu_coreclk_setup(struct device_node *np,
clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
cpuclk_name, 0, mult, div);
WARN_ON(IS_ERR(clk_data.clks[2+n]));
- };
+ }
/* Register optional refclk */
if (desc->get_refclk_freq) {
diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c
index 73f0240569ac..f8dd10f6df3d 100644
--- a/drivers/clk/mxs/clk-frac.c
+++ b/drivers/clk/mxs/clk-frac.c
@@ -41,11 +41,13 @@ static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
{
struct clk_frac *frac = to_clk_frac(hw);
u32 div;
+ u64 tmp_rate;
div = readl_relaxed(frac->reg) >> frac->shift;
div &= (1 << frac->width) - 1;
- return (parent_rate >> frac->width) * div;
+ tmp_rate = (u64)parent_rate * div;
+ return tmp_rate >> frac->width;
}
static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -54,7 +56,7 @@ static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
struct clk_frac *frac = to_clk_frac(hw);
unsigned long parent_rate = *prate;
u32 div;
- u64 tmp;
+ u64 tmp, tmp_rate, result;
if (rate > parent_rate)
return -EINVAL;
@@ -67,7 +69,11 @@ static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
if (!div)
return -EINVAL;
- return (parent_rate >> frac->width) * div;
+ tmp_rate = (u64)parent_rate * div;
+ result = tmp_rate >> frac->width;
+ if ((result << frac->width) < tmp_rate)
+ result += 1;
+ return result;
}
static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c
index eeaee97da110..13aabbb3acbe 100644
--- a/drivers/clk/nxp/clk-lpc18xx-ccu.c
+++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c
@@ -179,9 +179,22 @@ static void lpc18xx_ccu_gate_disable(struct clk_hw *hw)
static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
{
- struct clk_gate *gate = to_clk_gate(hw);
+ const struct clk_hw *parent;
+
+ /*
+ * The branch clock registers are only accessible
+ * if the base (parent) clock is enabled. Register
+ * access with a disabled base clock will hang the
+ * system.
+ */
+ parent = clk_hw_get_parent(hw);
+ if (!parent)
+ return 0;
+
+ if (!clk_hw_is_enabled(parent))
+ return 0;
- return clk_readl(gate->reg) & LPC18XX_CCU_RUN;
+ return clk_gate_ops.is_enabled(hw);
}
static const struct clk_ops lpc18xx_ccu_gate_ops = {
diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c
index e0a3cb8970ab..c924572fc9bc 100644
--- a/drivers/clk/nxp/clk-lpc18xx-cgu.c
+++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c
@@ -480,6 +480,42 @@ static const struct clk_ops lpc18xx_pll1_ops = {
.recalc_rate = lpc18xx_pll1_recalc_rate,
};
+static int lpc18xx_cgu_gate_enable(struct clk_hw *hw)
+{
+ return clk_gate_ops.enable(hw);
+}
+
+static void lpc18xx_cgu_gate_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static int lpc18xx_cgu_gate_is_enabled(struct clk_hw *hw)
+{
+ const struct clk_hw *parent;
+
+ /*
+ * The consumer of base clocks needs know if the
+ * base clock is really enabled before it can be
+ * accessed. It is therefore necessary to verify
+ * this all the way up.
+ */
+ parent = clk_hw_get_parent(hw);
+ if (!parent)
+ return 0;
+
+ if (!clk_hw_is_enabled(parent))
+ return 0;
+
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops lpc18xx_gate_ops = {
+ .enable = lpc18xx_cgu_gate_enable,
+ .disable = lpc18xx_cgu_gate_disable,
+ .is_enabled = lpc18xx_cgu_gate_is_enabled,
+};
+
static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
LPC1XX_CGU_CLK_PLL(PLL0USB, pll0_src_ids, pll0_ops),
LPC1XX_CGU_CLK_PLL(PLL0AUDIO, pll0_src_ids, pll0_ops),
@@ -510,7 +546,7 @@ static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk,
return clk_register_composite(NULL, name, parents, clk->n_parents,
&clk->mux.hw, &clk_mux_ops,
&clk->div.hw, &clk_divider_ops,
- &clk->gate.hw, &clk_gate_ops, 0);
+ &clk->gate.hw, &lpc18xx_gate_ops, 0);
}
@@ -538,7 +574,7 @@ static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk,
return clk_register_composite(NULL, name, parents, clk->n_parents,
&clk->mux.hw, &clk_mux_ops,
NULL, NULL,
- &clk->gate.hw, &clk_gate_ops, 0);
+ &clk->gate.hw, &lpc18xx_gate_ops, 0);
}
@@ -557,7 +593,7 @@ static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk,
return clk_register_composite(NULL, name, parents, clk->n_parents,
&clk->mux.hw, &clk_mux_ops,
&clk->pll.hw, clk->pll_ops,
- &clk->gate.hw, &clk_gate_ops, 0);
+ &clk->gate.hw, &lpc18xx_gate_ops, 0);
}
static void __init lpc18xx_cgu_register_source_clks(struct device_node *np,
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 59d16668bdf5..ee4c83aab4f4 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -1,3 +1,7 @@
+config QCOM_GDSC
+ bool
+ select PM_GENERIC_DOMAINS if PM
+
config COMMON_CLK_QCOM
tristate "Support for Qualcomm's clock controllers"
depends on OF
@@ -7,6 +11,7 @@ config COMMON_CLK_QCOM
config APQ_GCC_8084
tristate "APQ8084 Global Clock Controller"
+ select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on apq8084 devices.
@@ -16,6 +21,7 @@ config APQ_GCC_8084
config APQ_MMCC_8084
tristate "APQ8084 Multimedia Clock Controller"
select APQ_GCC_8084
+ select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the multimedia clock controller on apq8084 devices.
@@ -49,6 +55,7 @@ config MSM_GCC_8660
config MSM_GCC_8916
tristate "MSM8916 Global Clock Controller"
+ select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on msm8916 devices.
@@ -83,6 +90,7 @@ config MSM_MMCC_8960
config MSM_GCC_8974
tristate "MSM8974 Global Clock Controller"
+ select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on msm8974 devices.
@@ -92,6 +100,7 @@ config MSM_GCC_8974
config MSM_MMCC_8974
tristate "MSM8974 Multimedia Clock Controller"
select MSM_GCC_8974
+ select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the multimedia clock controller on msm8974 devices.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 50b337a24a87..fe6252349e55 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -9,6 +9,7 @@ clk-qcom-y += clk-branch.o
clk-qcom-y += clk-regmap-divider.o
clk-qcom-y += clk-regmap-mux.o
clk-qcom-y += reset.o
+clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index bccedc4b5756..bfbb28f450c2 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -542,6 +542,200 @@ static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
}
+static int clk_rcg_bypass2_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_hw *p;
+
+ p = req->best_parent_hw;
+ req->best_parent_rate = clk_hw_round_rate(p, req->rate);
+ req->rate = req->best_parent_rate;
+
+ return 0;
+}
+
+static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+ struct freq_tbl f = { 0 };
+ u32 ns, src;
+ int i, ret, num_parents = clk_hw_get_num_parents(hw);
+
+ ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+ if (ret)
+ return ret;
+
+ src = ns_to_src(&rcg->s, ns);
+ f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
+
+ for (i = 0; i < num_parents; i++) {
+ if (src == rcg->s.parent_map[i].cfg) {
+ f.src = rcg->s.parent_map[i].src;
+ return __clk_rcg_set_rate(rcg, &f);
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int clk_rcg_bypass2_set_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ /* Read the hardware to determine parent during set_rate */
+ return clk_rcg_bypass2_set_rate(hw, rate, parent_rate);
+}
+
+struct frac_entry {
+ int num;
+ int den;
+};
+
+static const struct frac_entry pixel_table[] = {
+ { 1, 2 },
+ { 1, 3 },
+ { 3, 16 },
+ { }
+};
+
+static int clk_rcg_pixel_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int delta = 100000;
+ const struct frac_entry *frac = pixel_table;
+ unsigned long request, src_rate;
+
+ for (; frac->num; frac++) {
+ request = (req->rate * frac->den) / frac->num;
+
+ src_rate = clk_hw_round_rate(req->best_parent_hw, request);
+
+ if ((src_rate < (request - delta)) ||
+ (src_rate > (request + delta)))
+ continue;
+
+ req->best_parent_rate = src_rate;
+ req->rate = (src_rate * frac->num) / frac->den;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+ int delta = 100000;
+ const struct frac_entry *frac = pixel_table;
+ unsigned long request;
+ struct freq_tbl f = { 0 };
+ u32 ns, src;
+ int i, ret, num_parents = clk_hw_get_num_parents(hw);
+
+ ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+ if (ret)
+ return ret;
+
+ src = ns_to_src(&rcg->s, ns);
+ f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
+
+ for (i = 0; i < num_parents; i++) {
+ if (src == rcg->s.parent_map[i].cfg) {
+ f.src = rcg->s.parent_map[i].src;
+ break;
+ }
+ }
+
+ /* let us find appropriate m/n values for this */
+ for (; frac->num; frac++) {
+ request = (rate * frac->den) / frac->num;
+
+ if ((parent_rate < (request - delta)) ||
+ (parent_rate > (request + delta)))
+ continue;
+
+ f.m = frac->num;
+ f.n = frac->den;
+
+ return __clk_rcg_set_rate(rcg, &f);
+ }
+
+ return -EINVAL;
+}
+
+static int clk_rcg_pixel_set_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ return clk_rcg_pixel_set_rate(hw, rate, parent_rate);
+}
+
+static int clk_rcg_esc_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+ int pre_div_max = BIT(rcg->p.pre_div_width);
+ int div;
+ unsigned long src_rate;
+
+ if (req->rate == 0)
+ return -EINVAL;
+
+ src_rate = clk_hw_get_rate(req->best_parent_hw);
+
+ div = src_rate / req->rate;
+
+ if (div >= 1 && div <= pre_div_max) {
+ req->best_parent_rate = src_rate;
+ req->rate = src_rate / div;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+ struct freq_tbl f = { 0 };
+ int pre_div_max = BIT(rcg->p.pre_div_width);
+ int div;
+ u32 ns;
+ int i, ret, num_parents = clk_hw_get_num_parents(hw);
+
+ if (rate == 0)
+ return -EINVAL;
+
+ ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+ if (ret)
+ return ret;
+
+ ns = ns_to_src(&rcg->s, ns);
+
+ for (i = 0; i < num_parents; i++) {
+ if (ns == rcg->s.parent_map[i].cfg) {
+ f.src = rcg->s.parent_map[i].src;
+ break;
+ }
+ }
+
+ div = parent_rate / rate;
+
+ if (div >= 1 && div <= pre_div_max) {
+ f.pre_div = div;
+ return __clk_rcg_set_rate(rcg, &f);
+ }
+
+ return -EINVAL;
+}
+
+static int clk_rcg_esc_set_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ return clk_rcg_esc_set_rate(hw, rate, parent_rate);
+}
+
/*
* This type of clock has a glitch-free mux that switches between the output of
* the M/N counter and an always on clock source (XO). When clk_set_rate() is
@@ -639,6 +833,42 @@ const struct clk_ops clk_rcg_bypass_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
+const struct clk_ops clk_rcg_bypass2_ops = {
+ .enable = clk_enable_regmap,
+ .disable = clk_disable_regmap,
+ .get_parent = clk_rcg_get_parent,
+ .set_parent = clk_rcg_set_parent,
+ .recalc_rate = clk_rcg_recalc_rate,
+ .determine_rate = clk_rcg_bypass2_determine_rate,
+ .set_rate = clk_rcg_bypass2_set_rate,
+ .set_rate_and_parent = clk_rcg_bypass2_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_bypass2_ops);
+
+const struct clk_ops clk_rcg_pixel_ops = {
+ .enable = clk_enable_regmap,
+ .disable = clk_disable_regmap,
+ .get_parent = clk_rcg_get_parent,
+ .set_parent = clk_rcg_set_parent,
+ .recalc_rate = clk_rcg_recalc_rate,
+ .determine_rate = clk_rcg_pixel_determine_rate,
+ .set_rate = clk_rcg_pixel_set_rate,
+ .set_rate_and_parent = clk_rcg_pixel_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_pixel_ops);
+
+const struct clk_ops clk_rcg_esc_ops = {
+ .enable = clk_enable_regmap,
+ .disable = clk_disable_regmap,
+ .get_parent = clk_rcg_get_parent,
+ .set_parent = clk_rcg_set_parent,
+ .recalc_rate = clk_rcg_recalc_rate,
+ .determine_rate = clk_rcg_esc_determine_rate,
+ .set_rate = clk_rcg_esc_set_rate,
+ .set_rate_and_parent = clk_rcg_esc_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_esc_ops);
+
const struct clk_ops clk_rcg_lcc_ops = {
.enable = clk_rcg_lcc_enable,
.disable = clk_rcg_lcc_disable,
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 56028bb31d87..4b1e94bdf29e 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -106,6 +106,9 @@ struct clk_rcg {
extern const struct clk_ops clk_rcg_ops;
extern const struct clk_ops clk_rcg_bypass_ops;
+extern const struct clk_ops clk_rcg_bypass2_ops;
+extern const struct clk_ops clk_rcg_pixel_ops;
+extern const struct clk_ops clk_rcg_esc_ops;
extern const struct clk_ops clk_rcg_lcc_ops;
#define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
@@ -153,8 +156,8 @@ extern const struct clk_ops clk_dyn_rcg_ops;
* @hid_width: number of bits in half integer divider
* @parent_map: map from software's parent index to hardware's src_sel field
* @freq_tbl: frequency table
+ * @current_freq: last cached frequency when using branches with shared RCGs
* @clkr: regmap clock handle
- * @lock: register lock
*
*/
struct clk_rcg2 {
@@ -163,14 +166,17 @@ struct clk_rcg2 {
u8 hid_width;
const struct parent_map *parent_map;
const struct freq_tbl *freq_tbl;
+ unsigned long current_freq;
struct clk_regmap clkr;
};
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
extern const struct clk_ops clk_rcg2_ops;
+extern const struct clk_ops clk_rcg2_shared_ops;
extern const struct clk_ops clk_edp_pixel_ops;
extern const struct clk_ops clk_byte_ops;
+extern const struct clk_ops clk_byte2_ops;
extern const struct clk_ops clk_pixel_ops;
#endif
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 9aec1761fd29..b544bb302f79 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -300,6 +300,85 @@ const struct clk_ops clk_rcg2_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
+static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ const char *name = clk_hw_get_name(hw);
+ int ret, count;
+
+ /* force enable RCG */
+ ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+ CMD_ROOT_EN, CMD_ROOT_EN);
+ if (ret)
+ return ret;
+
+ /* wait for RCG to turn ON */
+ for (count = 500; count > 0; count--) {
+ ret = clk_rcg2_is_enabled(hw);
+ if (ret)
+ break;
+ udelay(1);
+ }
+ if (!count)
+ pr_err("%s: RCG did not turn on\n", name);
+
+ /* set clock rate */
+ ret = __clk_rcg2_set_rate(hw, rate);
+ if (ret)
+ return ret;
+
+ /* clear force enable RCG */
+ return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+ CMD_ROOT_EN, 0);
+}
+
+static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ /* cache the rate */
+ rcg->current_freq = rate;
+
+ if (!__clk_is_enabled(hw->clk))
+ return 0;
+
+ return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
+}
+
+static unsigned long
+clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ return rcg->current_freq = clk_rcg2_recalc_rate(hw, parent_rate);
+}
+
+static int clk_rcg2_shared_enable(struct clk_hw *hw)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
+}
+
+static void clk_rcg2_shared_disable(struct clk_hw *hw)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ /* switch to XO, which is the lowest entry in the freq table */
+ clk_rcg2_shared_set_rate(hw, rcg->freq_tbl[0].freq, 0);
+}
+
+const struct clk_ops clk_rcg2_shared_ops = {
+ .enable = clk_rcg2_shared_enable,
+ .disable = clk_rcg2_shared_disable,
+ .get_parent = clk_rcg2_get_parent,
+ .recalc_rate = clk_rcg2_shared_recalc_rate,
+ .determine_rate = clk_rcg2_determine_rate,
+ .set_rate = clk_rcg2_shared_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops);
+
struct frac_entry {
int num;
int den;
@@ -485,6 +564,76 @@ const struct clk_ops clk_byte_ops = {
};
EXPORT_SYMBOL_GPL(clk_byte_ops);
+static int clk_byte2_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ unsigned long parent_rate, div;
+ u32 mask = BIT(rcg->hid_width) - 1;
+ struct clk_hw *p;
+ unsigned long rate = req->rate;
+
+ if (rate == 0)
+ return -EINVAL;
+
+ p = req->best_parent_hw;
+ req->best_parent_rate = parent_rate = clk_hw_round_rate(p, rate);
+
+ div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
+ div = min_t(u32, div, mask);
+
+ req->rate = calc_rate(parent_rate, 0, 0, 0, div);
+
+ return 0;
+}
+
+static int clk_byte2_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ struct freq_tbl f = { 0 };
+ unsigned long div;
+ int i, num_parents = clk_hw_get_num_parents(hw);
+ u32 mask = BIT(rcg->hid_width) - 1;
+ u32 cfg;
+
+ div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
+ div = min_t(u32, div, mask);
+
+ f.pre_div = div;
+
+ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+ cfg &= CFG_SRC_SEL_MASK;
+ cfg >>= CFG_SRC_SEL_SHIFT;
+
+ for (i = 0; i < num_parents; i++) {
+ if (cfg == rcg->parent_map[i].cfg) {
+ f.src = rcg->parent_map[i].src;
+ return clk_rcg2_configure(rcg, &f);
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int clk_byte2_set_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ /* Read the hardware to determine parent during set_rate */
+ return clk_byte2_set_rate(hw, rate, parent_rate);
+}
+
+const struct clk_ops clk_byte2_ops = {
+ .is_enabled = clk_rcg2_is_enabled,
+ .get_parent = clk_rcg2_get_parent,
+ .set_parent = clk_rcg2_set_parent,
+ .recalc_rate = clk_rcg2_recalc_rate,
+ .set_rate = clk_byte2_set_rate,
+ .set_rate_and_parent = clk_byte2_set_rate_and_parent,
+ .determine_rate = clk_byte2_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_byte2_ops);
+
static const struct frac_entry frac_table_pixel[] = {
{ 3, 8 },
{ 2, 9 },
@@ -496,14 +645,9 @@ static const struct frac_entry frac_table_pixel[] = {
static int clk_pixel_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- struct clk_rcg2 *rcg = to_clk_rcg2(hw);
unsigned long request, src_rate;
int delta = 100000;
- const struct freq_tbl *f = rcg->freq_tbl;
const struct frac_entry *frac = frac_table_pixel;
- int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
-
- req->best_parent_hw = clk_hw_get_parent_by_index(hw, index);
for (; frac->num; frac++) {
request = (req->rate * frac->den) / frac->num;
@@ -525,12 +669,23 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- struct freq_tbl f = *rcg->freq_tbl;
+ struct freq_tbl f = { 0 };
const struct frac_entry *frac = frac_table_pixel;
unsigned long request;
int delta = 100000;
u32 mask = BIT(rcg->hid_width) - 1;
- u32 hid_div;
+ u32 hid_div, cfg;
+ int i, num_parents = clk_hw_get_num_parents(hw);
+
+ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+ cfg &= CFG_SRC_SEL_MASK;
+ cfg >>= CFG_SRC_SEL_SHIFT;
+
+ for (i = 0; i < num_parents; i++)
+ if (cfg == rcg->parent_map[i].cfg) {
+ f.src = rcg->parent_map[i].src;
+ break;
+ }
for (; frac->num; frac++) {
request = (rate * frac->den) / frac->num;
@@ -555,7 +710,6 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate, u8 index)
{
- /* Parent index is set statically in frequency table */
return clk_pixel_set_rate(hw, rate, parent_rate);
}
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 2dedceefd21d..8fa477293ae0 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -22,6 +22,7 @@
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "reset.h"
+#include "gdsc.h"
struct qcom_cc {
struct qcom_reset_controller reset;
@@ -72,6 +73,21 @@ qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
}
EXPORT_SYMBOL_GPL(qcom_cc_map);
+static void qcom_cc_del_clk_provider(void *data)
+{
+ of_clk_del_provider(data);
+}
+
+static void qcom_cc_reset_unregister(void *data)
+{
+ reset_controller_unregister(data);
+}
+
+static void qcom_cc_gdsc_unregister(void *data)
+{
+ gdsc_unregister(data);
+}
+
int qcom_cc_really_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc, struct regmap *regmap)
{
@@ -110,6 +126,8 @@ int qcom_cc_really_probe(struct platform_device *pdev,
if (ret)
return ret;
+ devm_add_action(dev, qcom_cc_del_clk_provider, pdev->dev.of_node);
+
reset = &cc->reset;
reset->rcdev.of_node = dev->of_node;
reset->rcdev.ops = &qcom_reset_ops;
@@ -117,13 +135,24 @@ int qcom_cc_really_probe(struct platform_device *pdev,
reset->rcdev.nr_resets = desc->num_resets;
reset->regmap = regmap;
reset->reset_map = desc->resets;
- platform_set_drvdata(pdev, &reset->rcdev);
ret = reset_controller_register(&reset->rcdev);
if (ret)
- of_clk_del_provider(dev->of_node);
+ return ret;
+
+ devm_add_action(dev, qcom_cc_reset_unregister, &reset->rcdev);
+
+ if (desc->gdscs && desc->num_gdscs) {
+ ret = gdsc_register(dev, desc->gdscs, desc->num_gdscs,
+ &reset->rcdev, regmap);
+ if (ret)
+ return ret;
+ }
+
+ devm_add_action(dev, qcom_cc_gdsc_unregister, dev);
- return ret;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
@@ -139,11 +168,4 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
}
EXPORT_SYMBOL_GPL(qcom_cc_probe);
-void qcom_cc_remove(struct platform_device *pdev)
-{
- of_clk_del_provider(pdev->dev.of_node);
- reset_controller_unregister(platform_get_drvdata(pdev));
-}
-EXPORT_SYMBOL_GPL(qcom_cc_remove);
-
MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 7a0e73713063..7c1fba3ebc03 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -28,6 +28,8 @@ struct qcom_cc_desc {
size_t num_clks;
const struct qcom_reset_map *resets;
size_t num_resets;
+ struct gdsc **gdscs;
+ size_t num_gdscs;
};
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
@@ -43,6 +45,4 @@ extern int qcom_cc_really_probe(struct platform_device *pdev,
extern int qcom_cc_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
-extern void qcom_cc_remove(struct platform_device *pdev);
-
#endif
diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c
index 3563019b8e3c..1567c3a79534 100644
--- a/drivers/clk/qcom/gcc-apq8084.c
+++ b/drivers/clk/qcom/gcc-apq8084.c
@@ -31,6 +31,7 @@
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
+#include "gdsc.h"
enum {
P_XO,
@@ -3254,6 +3255,38 @@ static struct clk_branch gcc_usb_hsic_system_clk = {
},
};
+static struct gdsc usb_hs_hsic_gdsc = {
+ .gdscr = 0x404,
+ .pd = {
+ .name = "usb_hs_hsic",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc pcie0_gdsc = {
+ .gdscr = 0x1ac4,
+ .pd = {
+ .name = "pcie0",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc pcie1_gdsc = {
+ .gdscr = 0x1b44,
+ .pd = {
+ .name = "pcie1",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc usb30_gdsc = {
+ .gdscr = 0x1e84,
+ .pd = {
+ .name = "usb30",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct clk_regmap *gcc_apq8084_clocks[] = {
[GPLL0] = &gpll0.clkr,
[GPLL0_VOTE] = &gpll0_vote,
@@ -3447,6 +3480,13 @@ static struct clk_regmap *gcc_apq8084_clocks[] = {
[GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr,
};
+static struct gdsc *gcc_apq8084_gdscs[] = {
+ [USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc,
+ [PCIE0_GDSC] = &pcie0_gdsc,
+ [PCIE1_GDSC] = &pcie1_gdsc,
+ [USB30_GDSC] = &usb30_gdsc,
+};
+
static const struct qcom_reset_map gcc_apq8084_resets[] = {
[GCC_SYSTEM_NOC_BCR] = { 0x0100 },
[GCC_CONFIG_NOC_BCR] = { 0x0140 },
@@ -3555,6 +3595,8 @@ static const struct qcom_cc_desc gcc_apq8084_desc = {
.num_clks = ARRAY_SIZE(gcc_apq8084_clocks),
.resets = gcc_apq8084_resets,
.num_resets = ARRAY_SIZE(gcc_apq8084_resets),
+ .gdscs = gcc_apq8084_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_apq8084_gdscs),
};
static const struct of_device_id gcc_apq8084_match_table[] = {
@@ -3581,15 +3623,8 @@ static int gcc_apq8084_probe(struct platform_device *pdev)
return qcom_cc_probe(pdev, &gcc_apq8084_desc);
}
-static int gcc_apq8084_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver gcc_apq8084_driver = {
.probe = gcc_apq8084_probe,
- .remove = gcc_apq8084_remove,
.driver = {
.name = "gcc-apq8084",
.of_match_table = gcc_apq8084_match_table,
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 40e480220cd3..16fc64c082a5 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -3058,15 +3058,8 @@ static int gcc_ipq806x_probe(struct platform_device *pdev)
return 0;
}
-static int gcc_ipq806x_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver gcc_ipq806x_driver = {
.probe = gcc_ipq806x_probe,
- .remove = gcc_ipq806x_remove,
.driver = {
.name = "gcc-ipq806x",
.of_match_table = gcc_ipq806x_match_table,
diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c
index b02826ed770a..f110bb5a1df3 100644
--- a/drivers/clk/qcom/gcc-msm8660.c
+++ b/drivers/clk/qcom/gcc-msm8660.c
@@ -2735,15 +2735,8 @@ static int gcc_msm8660_probe(struct platform_device *pdev)
return qcom_cc_probe(pdev, &gcc_msm8660_desc);
}
-static int gcc_msm8660_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver gcc_msm8660_driver = {
.probe = gcc_msm8660_probe,
- .remove = gcc_msm8660_remove,
.driver = {
.name = "gcc-msm8660",
.of_match_table = gcc_msm8660_match_table,
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index 22a4e1e732c0..d0a0313d6bef 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -31,6 +31,7 @@
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
+#include "gdsc.h"
enum {
P_XO,
@@ -44,6 +45,9 @@ enum {
P_SLEEP_CLK,
P_DSI0_PHYPLL_BYTE,
P_DSI0_PHYPLL_DSI,
+ P_EXT_PRI_I2S,
+ P_EXT_SEC_I2S,
+ P_EXT_MCLK,
};
static const struct parent_map gcc_xo_gpll0_map[] = {
@@ -190,6 +194,76 @@ static const char * const gcc_xo_gpll0a_gpll1_gpll2[] = {
"gpll2_vote",
};
+static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL1, 2 },
+ { P_SLEEP_CLK, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll1_sleep[] = {
+ "xo",
+ "gpll0_vote",
+ "gpll1_vote",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll1_epi2s_emclk_sleep_map[] = {
+ { P_XO, 0 },
+ { P_GPLL1, 1 },
+ { P_EXT_PRI_I2S, 2 },
+ { P_EXT_MCLK, 3 },
+ { P_SLEEP_CLK, 6 }
+};
+
+static const char * const gcc_xo_gpll1_epi2s_emclk_sleep[] = {
+ "xo",
+ "gpll1_vote",
+ "ext_pri_i2s",
+ "ext_mclk",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll1_esi2s_emclk_sleep_map[] = {
+ { P_XO, 0 },
+ { P_GPLL1, 1 },
+ { P_EXT_SEC_I2S, 2 },
+ { P_EXT_MCLK, 3 },
+ { P_SLEEP_CLK, 6 }
+};
+
+static const char * const gcc_xo_gpll1_esi2s_emclk_sleep[] = {
+ "xo",
+ "gpll1_vote",
+ "ext_sec_i2s",
+ "ext_mclk",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_xo_sleep_map[] = {
+ { P_XO, 0 },
+ { P_SLEEP_CLK, 6 }
+};
+
+static const char * const gcc_xo_sleep[] = {
+ "xo",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll1_emclk_sleep_map[] = {
+ { P_XO, 0 },
+ { P_GPLL1, 1 },
+ { P_EXT_MCLK, 2 },
+ { P_SLEEP_CLK, 6 }
+};
+
+static const char * const gcc_xo_gpll1_emclk_sleep[] = {
+ "xo",
+ "gpll1_vote",
+ "ext_mclk",
+ "sleep_clk",
+};
+
#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
static struct clk_pll gpll0 = {
@@ -906,21 +980,15 @@ static struct clk_rcg2 gp3_clk_src = {
},
};
-static struct freq_tbl ftbl_gcc_mdss_byte0_clk[] = {
- { .src = P_DSI0_PHYPLL_BYTE },
- { }
-};
-
static struct clk_rcg2 byte0_clk_src = {
.cmd_rcgr = 0x4d044,
.hid_width = 5,
.parent_map = gcc_xo_gpll0a_dsibyte_map,
- .freq_tbl = ftbl_gcc_mdss_byte0_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "byte0_clk_src",
.parent_names = gcc_xo_gpll0a_dsibyte,
.num_parents = 3,
- .ops = &clk_byte_ops,
+ .ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -968,17 +1036,11 @@ static struct clk_rcg2 mdp_clk_src = {
},
};
-static struct freq_tbl ftbl_gcc_mdss_pclk[] = {
- { .src = P_DSI0_PHYPLL_DSI },
- { }
-};
-
static struct clk_rcg2 pclk0_clk_src = {
.cmd_rcgr = 0x4d000,
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0a_dsiphy_map,
- .freq_tbl = ftbl_gcc_mdss_pclk,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk0_clk_src",
.parent_names = gcc_xo_gpll0a_dsiphy,
@@ -1094,6 +1156,30 @@ static struct clk_rcg2 apss_tcu_clk_src = {
},
};
+static const struct freq_tbl ftbl_gcc_bimc_gpu_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266500000, P_BIMC, 4, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(533000000, P_BIMC, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 bimc_gpu_clk_src = {
+ .cmd_rcgr = 0x31028,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_bimc_map,
+ .freq_tbl = ftbl_gcc_bimc_gpu_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "bimc_gpu_clk_src",
+ .parent_names = gcc_xo_gpll0_bimc,
+ .num_parents = 3,
+ .flags = CLK_GET_RATE_NOCACHE,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
F(80000000, P_GPLL0, 10, 0, 0),
{ }
@@ -1112,6 +1198,305 @@ static struct clk_rcg2 usb_hs_system_clk_src = {
},
};
+static const struct freq_tbl ftbl_gcc_ultaudio_ahb_clk[] = {
+ F(3200000, P_XO, 6, 0, 0),
+ F(6400000, P_XO, 3, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(19200000, P_XO, 1, 0, 0),
+ F(40000000, P_GPLL0, 10, 1, 2),
+ F(66670000, P_GPLL0, 12, 0, 0),
+ F(80000000, P_GPLL0, 10, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ultaudio_ahbfabric_clk_src = {
+ .cmd_rcgr = 0x1c010,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .parent_map = gcc_xo_gpll0_gpll1_sleep_map,
+ .freq_tbl = ftbl_gcc_ultaudio_ahb_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ultaudio_ahbfabric_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll1_sleep,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_clk = {
+ .halt_reg = 0x1c028,
+ .clkr = {
+ .enable_reg = 0x1c028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_ahbfabric_ixfabric_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_ahbfabric_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_lpm_clk = {
+ .halt_reg = 0x1c024,
+ .clkr = {
+ .enable_reg = 0x1c024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_ahbfabric_ixfabric_lpm_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_ahbfabric_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ultaudio_lpaif_i2s_clk[] = {
+ F(256000, P_XO, 5, 1, 15),
+ F(512000, P_XO, 5, 2, 15),
+ F(705600, P_GPLL1, 16, 1, 80),
+ F(768000, P_XO, 5, 1, 5),
+ F(800000, P_XO, 5, 5, 24),
+ F(1024000, P_GPLL1, 14, 1, 63),
+ F(1152000, P_XO, 1, 3, 50),
+ F(1411200, P_GPLL1, 16, 1, 40),
+ F(1536000, P_XO, 1, 2, 25),
+ F(1600000, P_XO, 12, 0, 0),
+ F(2048000, P_GPLL1, 9, 1, 49),
+ F(2400000, P_XO, 8, 0, 0),
+ F(2822400, P_GPLL1, 16, 1, 20),
+ F(3072000, P_GPLL1, 14, 1, 21),
+ F(4096000, P_GPLL1, 9, 2, 49),
+ F(4800000, P_XO, 4, 0, 0),
+ F(5644800, P_GPLL1, 16, 1, 10),
+ F(6144000, P_GPLL1, 7, 1, 21),
+ F(8192000, P_GPLL1, 9, 4, 49),
+ F(9600000, P_XO, 2, 0, 0),
+ F(11289600, P_GPLL1, 16, 1, 5),
+ F(12288000, P_GPLL1, 7, 2, 21),
+ { }
+};
+
+static struct clk_rcg2 ultaudio_lpaif_pri_i2s_clk_src = {
+ .cmd_rcgr = 0x1c054,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .parent_map = gcc_xo_gpll1_epi2s_emclk_sleep_map,
+ .freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ultaudio_lpaif_pri_i2s_clk_src",
+ .parent_names = gcc_xo_gpll1_epi2s_emclk_sleep,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_ultaudio_lpaif_pri_i2s_clk = {
+ .halt_reg = 0x1c068,
+ .clkr = {
+ .enable_reg = 0x1c068,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_lpaif_pri_i2s_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_lpaif_pri_i2s_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_rcg2 ultaudio_lpaif_sec_i2s_clk_src = {
+ .cmd_rcgr = 0x1c06c,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .parent_map = gcc_xo_gpll1_esi2s_emclk_sleep_map,
+ .freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ultaudio_lpaif_sec_i2s_clk_src",
+ .parent_names = gcc_xo_gpll1_esi2s_emclk_sleep,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_ultaudio_lpaif_sec_i2s_clk = {
+ .halt_reg = 0x1c080,
+ .clkr = {
+ .enable_reg = 0x1c080,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_lpaif_sec_i2s_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_lpaif_sec_i2s_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_rcg2 ultaudio_lpaif_aux_i2s_clk_src = {
+ .cmd_rcgr = 0x1c084,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .parent_map = gcc_xo_gpll1_emclk_sleep_map,
+ .freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ultaudio_lpaif_aux_i2s_clk_src",
+ .parent_names = gcc_xo_gpll1_esi2s_emclk_sleep,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_ultaudio_lpaif_aux_i2s_clk = {
+ .halt_reg = 0x1c098,
+ .clkr = {
+ .enable_reg = 0x1c098,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_lpaif_aux_i2s_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_lpaif_aux_i2s_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ultaudio_xo_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ultaudio_xo_clk_src = {
+ .cmd_rcgr = 0x1c034,
+ .hid_width = 5,
+ .parent_map = gcc_xo_sleep_map,
+ .freq_tbl = ftbl_gcc_ultaudio_xo_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ultaudio_xo_clk_src",
+ .parent_names = gcc_xo_sleep,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_ultaudio_avsync_xo_clk = {
+ .halt_reg = 0x1c04c,
+ .clkr = {
+ .enable_reg = 0x1c04c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_avsync_xo_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_xo_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ultaudio_stc_xo_clk = {
+ .halt_reg = 0x1c050,
+ .clkr = {
+ .enable_reg = 0x1c050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_stc_xo_clk",
+ .parent_names = (const char *[]){
+ "ultaudio_xo_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_codec_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(11289600, P_EXT_MCLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 codec_digcodec_clk_src = {
+ .cmd_rcgr = 0x1c09c,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll1_emclk_sleep_map,
+ .freq_tbl = ftbl_codec_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "codec_digcodec_clk_src",
+ .parent_names = gcc_xo_gpll1_emclk_sleep,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_codec_digcodec_clk = {
+ .halt_reg = 0x1c0b0,
+ .clkr = {
+ .enable_reg = 0x1c0b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_codec_digcodec_clk",
+ .parent_names = (const char *[]){
+ "codec_digcodec_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ultaudio_pcnoc_mport_clk = {
+ .halt_reg = 0x1c000,
+ .clkr = {
+ .enable_reg = 0x1c000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_pcnoc_mport_clk",
+ .parent_names = (const char *[]){
+ "pcnoc_bfdcd_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ultaudio_pcnoc_sway_clk = {
+ .halt_reg = 0x1c004,
+ .clkr = {
+ .enable_reg = 0x1c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ultaudio_pcnoc_sway_clk",
+ .parent_names = (const char *[]){
+ "pcnoc_bfdcd_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = {
F(100000000, P_GPLL0, 8, 0, 0),
F(160000000, P_GPLL0, 5, 0, 0),
@@ -2358,6 +2743,51 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
},
};
+static struct clk_rcg2 bimc_ddr_clk_src = {
+ .cmd_rcgr = 0x32004,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_bimc_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "bimc_ddr_clk_src",
+ .parent_names = gcc_xo_gpll0_bimc,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_branch gcc_apss_tcu_clk = {
+ .halt_reg = 0x12018,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_apss_tcu_clk",
+ .parent_names = (const char *[]){
+ "bimc_ddr_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gfx_tcu_clk = {
+ .halt_reg = 0x12020,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gfx_tcu_clk",
+ .parent_names = (const char *[]){
+ "bimc_ddr_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static struct clk_branch gcc_gtcu_ahb_clk = {
.halt_reg = 0x12044,
.clkr = {
@@ -2375,6 +2805,40 @@ static struct clk_branch gcc_gtcu_ahb_clk = {
},
};
+static struct clk_branch gcc_bimc_gfx_clk = {
+ .halt_reg = 0x31024,
+ .clkr = {
+ .enable_reg = 0x31024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_gfx_clk",
+ .parent_names = (const char *[]){
+ "bimc_gpu_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_gpu_clk = {
+ .halt_reg = 0x31040,
+ .clkr = {
+ .enable_reg = 0x31040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_gpu_clk",
+ .parent_names = (const char *[]){
+ "bimc_gpu_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static struct clk_branch gcc_jpeg_tbu_clk = {
.halt_reg = 0x12034,
.clkr = {
@@ -2562,6 +3026,46 @@ static struct clk_branch gcc_venus0_vcodec0_clk = {
},
};
+static struct gdsc venus_gdsc = {
+ .gdscr = 0x4c018,
+ .pd = {
+ .name = "venus",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc mdss_gdsc = {
+ .gdscr = 0x4d078,
+ .pd = {
+ .name = "mdss",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc jpeg_gdsc = {
+ .gdscr = 0x5701c,
+ .pd = {
+ .name = "jpeg",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc vfe_gdsc = {
+ .gdscr = 0x58034,
+ .pd = {
+ .name = "vfe",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxili_gdsc = {
+ .gdscr = 0x5901c,
+ .pd = {
+ .name = "oxili",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct clk_regmap *gcc_msm8916_clocks[] = {
[GPLL0] = &gpll0.clkr,
[GPLL0_VOTE] = &gpll0_vote,
@@ -2701,6 +3205,36 @@ static struct clk_regmap *gcc_msm8916_clocks[] = {
[GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr,
[GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr,
[GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr,
+ [BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr,
+ [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr,
+ [GCC_GFX_TCU_CLK] = &gcc_gfx_tcu_clk.clkr,
+ [BIMC_GPU_CLK_SRC] = &bimc_gpu_clk_src.clkr,
+ [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+ [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr,
+ [ULTAUDIO_AHBFABRIC_CLK_SRC] = &ultaudio_ahbfabric_clk_src.clkr,
+ [ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC] = &ultaudio_lpaif_pri_i2s_clk_src.clkr,
+ [ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC] = &ultaudio_lpaif_sec_i2s_clk_src.clkr,
+ [ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC] = &ultaudio_lpaif_aux_i2s_clk_src.clkr,
+ [ULTAUDIO_XO_CLK_SRC] = &ultaudio_xo_clk_src.clkr,
+ [CODEC_DIGCODEC_CLK_SRC] = &codec_digcodec_clk_src.clkr,
+ [GCC_ULTAUDIO_PCNOC_MPORT_CLK] = &gcc_ultaudio_pcnoc_mport_clk.clkr,
+ [GCC_ULTAUDIO_PCNOC_SWAY_CLK] = &gcc_ultaudio_pcnoc_sway_clk.clkr,
+ [GCC_ULTAUDIO_AVSYNC_XO_CLK] = &gcc_ultaudio_avsync_xo_clk.clkr,
+ [GCC_ULTAUDIO_STC_XO_CLK] = &gcc_ultaudio_stc_xo_clk.clkr,
+ [GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_clk.clkr,
+ [GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_lpm_clk.clkr,
+ [GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK] = &gcc_ultaudio_lpaif_pri_i2s_clk.clkr,
+ [GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK] = &gcc_ultaudio_lpaif_sec_i2s_clk.clkr,
+ [GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK] = &gcc_ultaudio_lpaif_aux_i2s_clk.clkr,
+ [GCC_CODEC_DIGCODEC_CLK] = &gcc_codec_digcodec_clk.clkr,
+};
+
+static struct gdsc *gcc_msm8916_gdscs[] = {
+ [VENUS_GDSC] = &venus_gdsc,
+ [MDSS_GDSC] = &mdss_gdsc,
+ [JPEG_GDSC] = &jpeg_gdsc,
+ [VFE_GDSC] = &vfe_gdsc,
+ [OXILI_GDSC] = &oxili_gdsc,
};
static const struct qcom_reset_map gcc_msm8916_resets[] = {
@@ -2810,6 +3344,8 @@ static const struct qcom_cc_desc gcc_msm8916_desc = {
.num_clks = ARRAY_SIZE(gcc_msm8916_clocks),
.resets = gcc_msm8916_resets,
.num_resets = ARRAY_SIZE(gcc_msm8916_resets),
+ .gdscs = gcc_msm8916_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_msm8916_gdscs),
};
static const struct of_device_id gcc_msm8916_match_table[] = {
@@ -2836,15 +3372,8 @@ static int gcc_msm8916_probe(struct platform_device *pdev)
return qcom_cc_probe(pdev, &gcc_msm8916_desc);
}
-static int gcc_msm8916_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver gcc_msm8916_driver = {
.probe = gcc_msm8916_probe,
- .remove = gcc_msm8916_remove,
.driver = {
.name = "gcc-msm8916",
.of_match_table = gcc_msm8916_match_table,
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index aa294b1bad34..66c18bc97857 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -3506,6 +3506,8 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
struct clk *clk;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
+ struct platform_device *tsens;
+ int ret;
match = of_match_device(gcc_msm8960_match_table, &pdev->dev);
if (!match)
@@ -3520,12 +3522,26 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
- return qcom_cc_probe(pdev, match->data);
+ ret = qcom_cc_probe(pdev, match->data);
+ if (ret)
+ return ret;
+
+ tsens = platform_device_register_data(&pdev->dev, "qcom-tsens", -1,
+ NULL, 0);
+ if (IS_ERR(tsens))
+ return PTR_ERR(tsens);
+
+ platform_set_drvdata(pdev, tsens);
+
+ return 0;
}
static int gcc_msm8960_remove(struct platform_device *pdev)
{
- qcom_cc_remove(pdev);
+ struct platform_device *tsens = platform_get_drvdata(pdev);
+
+ platform_device_unregister(tsens);
+
return 0;
}
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index 2bcf87538f9d..28abb8f8f293 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -31,6 +31,7 @@
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
+#include "gdsc.h"
enum {
P_XO,
@@ -2432,6 +2433,14 @@ static struct clk_branch gcc_usb_hsic_system_clk = {
},
};
+static struct gdsc usb_hs_hsic_gdsc = {
+ .gdscr = 0x404,
+ .pd = {
+ .name = "usb_hs_hsic",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct clk_regmap *gcc_msm8974_clocks[] = {
[GPLL0] = &gpll0.clkr,
[GPLL0_VOTE] = &gpll0_vote,
@@ -2661,6 +2670,10 @@ static const struct qcom_reset_map gcc_msm8974_resets[] = {
[GCC_VENUS_RESTART] = { 0x1740 },
};
+static struct gdsc *gcc_msm8974_gdscs[] = {
+ [USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc,
+};
+
static const struct regmap_config gcc_msm8974_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -2675,6 +2688,8 @@ static const struct qcom_cc_desc gcc_msm8974_desc = {
.num_clks = ARRAY_SIZE(gcc_msm8974_clocks),
.resets = gcc_msm8974_resets,
.num_resets = ARRAY_SIZE(gcc_msm8974_resets),
+ .gdscs = gcc_msm8974_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_msm8974_gdscs),
};
static const struct of_device_id gcc_msm8974_match_table[] = {
@@ -2729,15 +2744,8 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
return qcom_cc_probe(pdev, &gcc_msm8974_desc);
}
-static int gcc_msm8974_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver gcc_msm8974_driver = {
.probe = gcc_msm8974_probe,
- .remove = gcc_msm8974_remove,
.driver = {
.name = "gcc-msm8974",
.of_match_table = gcc_msm8974_match_table,
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
new file mode 100644
index 000000000000..da9fad8b642b
--- /dev/null
+++ b/drivers/clk/qcom/gdsc.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2015, 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 and
+ * only 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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include "gdsc.h"
+
+#define PWR_ON_MASK BIT(31)
+#define EN_REST_WAIT_MASK GENMASK_ULL(23, 20)
+#define EN_FEW_WAIT_MASK GENMASK_ULL(19, 16)
+#define CLK_DIS_WAIT_MASK GENMASK_ULL(15, 12)
+#define SW_OVERRIDE_MASK BIT(2)
+#define HW_CONTROL_MASK BIT(1)
+#define SW_COLLAPSE_MASK BIT(0)
+
+/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+#define EN_REST_WAIT_VAL (0x2 << 20)
+#define EN_FEW_WAIT_VAL (0x8 << 16)
+#define CLK_DIS_WAIT_VAL (0x2 << 12)
+
+#define RETAIN_MEM BIT(14)
+#define RETAIN_PERIPH BIT(13)
+
+#define TIMEOUT_US 100
+
+#define domain_to_gdsc(domain) container_of(domain, struct gdsc, pd)
+
+static int gdsc_is_enabled(struct gdsc *sc)
+{
+ u32 val;
+ int ret;
+
+ ret = regmap_read(sc->regmap, sc->gdscr, &val);
+ if (ret)
+ return ret;
+
+ return !!(val & PWR_ON_MASK);
+}
+
+static int gdsc_toggle_logic(struct gdsc *sc, bool en)
+{
+ int ret;
+ u32 val = en ? 0 : SW_COLLAPSE_MASK;
+ u32 check = en ? PWR_ON_MASK : 0;
+ unsigned long timeout;
+
+ ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
+ if (ret)
+ return ret;
+
+ timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
+ do {
+ ret = regmap_read(sc->regmap, sc->gdscr, &val);
+ if (ret)
+ return ret;
+
+ if ((val & PWR_ON_MASK) == check)
+ return 0;
+ } while (time_before(jiffies, timeout));
+
+ ret = regmap_read(sc->regmap, sc->gdscr, &val);
+ if (ret)
+ return ret;
+
+ if ((val & PWR_ON_MASK) == check)
+ return 0;
+
+ return -ETIMEDOUT;
+}
+
+static inline int gdsc_deassert_reset(struct gdsc *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->reset_count; i++)
+ sc->rcdev->ops->deassert(sc->rcdev, sc->resets[i]);
+ return 0;
+}
+
+static inline int gdsc_assert_reset(struct gdsc *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->reset_count; i++)
+ sc->rcdev->ops->assert(sc->rcdev, sc->resets[i]);
+ return 0;
+}
+
+static inline void gdsc_force_mem_on(struct gdsc *sc)
+{
+ int i;
+ u32 mask = RETAIN_MEM | RETAIN_PERIPH;
+
+ for (i = 0; i < sc->cxc_count; i++)
+ regmap_update_bits(sc->regmap, sc->cxcs[i], mask, mask);
+}
+
+static inline void gdsc_clear_mem_on(struct gdsc *sc)
+{
+ int i;
+ u32 mask = RETAIN_MEM | RETAIN_PERIPH;
+
+ for (i = 0; i < sc->cxc_count; i++)
+ regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
+}
+
+static int gdsc_enable(struct generic_pm_domain *domain)
+{
+ struct gdsc *sc = domain_to_gdsc(domain);
+ int ret;
+
+ if (sc->pwrsts == PWRSTS_ON)
+ return gdsc_deassert_reset(sc);
+
+ ret = gdsc_toggle_logic(sc, true);
+ if (ret)
+ return ret;
+
+ if (sc->pwrsts & PWRSTS_OFF)
+ gdsc_force_mem_on(sc);
+
+ /*
+ * If clocks to this power domain were already on, they will take an
+ * additional 4 clock cycles to re-enable after the power domain is
+ * enabled. Delay to account for this. A delay is also needed to ensure
+ * clocks are not enabled within 400ns of enabling power to the
+ * memories.
+ */
+ udelay(1);
+
+ return 0;
+}
+
+static int gdsc_disable(struct generic_pm_domain *domain)
+{
+ struct gdsc *sc = domain_to_gdsc(domain);
+
+ if (sc->pwrsts == PWRSTS_ON)
+ return gdsc_assert_reset(sc);
+
+ if (sc->pwrsts & PWRSTS_OFF)
+ gdsc_clear_mem_on(sc);
+
+ return gdsc_toggle_logic(sc, false);
+}
+
+static int gdsc_init(struct gdsc *sc)
+{
+ u32 mask, val;
+ int on, ret;
+
+ /*
+ * Disable HW trigger: collapse/restore occur based on registers writes.
+ * Disable SW override: Use hardware state-machine for sequencing.
+ * Configure wait time between states.
+ */
+ mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK |
+ EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK;
+ val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+ ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val);
+ if (ret)
+ return ret;
+
+ /* Force gdsc ON if only ON state is supported */
+ if (sc->pwrsts == PWRSTS_ON) {
+ ret = gdsc_toggle_logic(sc, true);
+ if (ret)
+ return ret;
+ }
+
+ on = gdsc_is_enabled(sc);
+ if (on < 0)
+ return on;
+
+ if (on || (sc->pwrsts & PWRSTS_RET))
+ gdsc_force_mem_on(sc);
+ else
+ gdsc_clear_mem_on(sc);
+
+ sc->pd.power_off = gdsc_disable;
+ sc->pd.power_on = gdsc_enable;
+ pm_genpd_init(&sc->pd, NULL, !on);
+
+ return 0;
+}
+
+int gdsc_register(struct device *dev, struct gdsc **scs, size_t num,
+ struct reset_controller_dev *rcdev, struct regmap *regmap)
+{
+ int i, ret;
+ struct genpd_onecell_data *data;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->domains = devm_kcalloc(dev, num, sizeof(*data->domains),
+ GFP_KERNEL);
+ if (!data->domains)
+ return -ENOMEM;
+
+ data->num_domains = num;
+ for (i = 0; i < num; i++) {
+ if (!scs[i])
+ continue;
+ scs[i]->regmap = regmap;
+ scs[i]->rcdev = rcdev;
+ ret = gdsc_init(scs[i]);
+ if (ret)
+ return ret;
+ data->domains[i] = &scs[i]->pd;
+ }
+
+ return of_genpd_add_provider_onecell(dev->of_node, data);
+}
+
+void gdsc_unregister(struct device *dev)
+{
+ of_genpd_del_provider(dev->of_node);
+}
diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
new file mode 100644
index 000000000000..5ded26884f08
--- /dev/null
+++ b/drivers/clk/qcom/gdsc.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 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 and
+ * only 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.
+ */
+
+#ifndef __QCOM_GDSC_H__
+#define __QCOM_GDSC_H__
+
+#include <linux/err.h>
+#include <linux/pm_domain.h>
+
+struct regmap;
+struct reset_controller_dev;
+
+/* Powerdomain allowable state bitfields */
+#define PWRSTS_OFF BIT(0)
+#define PWRSTS_RET BIT(1)
+#define PWRSTS_ON BIT(2)
+#define PWRSTS_OFF_ON (PWRSTS_OFF | PWRSTS_ON)
+#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON)
+
+/**
+ * struct gdsc - Globally Distributed Switch Controller
+ * @pd: generic power domain
+ * @regmap: regmap for MMIO accesses
+ * @gdscr: gsdc control register
+ * @cxcs: offsets of branch registers to toggle mem/periph bits in
+ * @cxc_count: number of @cxcs
+ * @pwrsts: Possible powerdomain power states
+ * @resets: ids of resets associated with this gdsc
+ * @reset_count: number of @resets
+ * @rcdev: reset controller
+ */
+struct gdsc {
+ struct generic_pm_domain pd;
+ struct regmap *regmap;
+ unsigned int gdscr;
+ unsigned int *cxcs;
+ unsigned int cxc_count;
+ const u8 pwrsts;
+ struct reset_controller_dev *rcdev;
+ unsigned int *resets;
+ unsigned int reset_count;
+};
+
+#ifdef CONFIG_QCOM_GDSC
+int gdsc_register(struct device *, struct gdsc **, size_t n,
+ struct reset_controller_dev *, struct regmap *);
+void gdsc_unregister(struct device *);
+#else
+static inline int gdsc_register(struct device *d, struct gdsc **g, size_t n,
+ struct reset_controller_dev *rcdev,
+ struct regmap *r)
+{
+ return -ENOSYS;
+}
+
+static inline void gdsc_unregister(struct device *d) {};
+#endif /* CONFIG_QCOM_GDSC */
+#endif /* __QCOM_GDSC_H__ */
diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c
index 93ad42b14366..db3998e5e2d8 100644
--- a/drivers/clk/qcom/lcc-ipq806x.c
+++ b/drivers/clk/qcom/lcc-ipq806x.c
@@ -452,15 +452,8 @@ static int lcc_ipq806x_probe(struct platform_device *pdev)
return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
}
-static int lcc_ipq806x_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver lcc_ipq806x_driver = {
.probe = lcc_ipq806x_probe,
- .remove = lcc_ipq806x_remove,
.driver = {
.name = "lcc-ipq806x",
.of_match_table = lcc_ipq806x_match_table,
diff --git a/drivers/clk/qcom/lcc-msm8960.c b/drivers/clk/qcom/lcc-msm8960.c
index ecb96c284675..4fcf9d1d233c 100644
--- a/drivers/clk/qcom/lcc-msm8960.c
+++ b/drivers/clk/qcom/lcc-msm8960.c
@@ -565,15 +565,8 @@ static int lcc_msm8960_probe(struct platform_device *pdev)
return qcom_cc_really_probe(pdev, &lcc_msm8960_desc, regmap);
}
-static int lcc_msm8960_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver lcc_msm8960_driver = {
.probe = lcc_msm8960_probe,
- .remove = lcc_msm8960_remove,
.driver = {
.name = "lcc-msm8960",
.of_match_table = lcc_msm8960_match_table,
diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c
index f0ee6bde11af..30777f9f1a43 100644
--- a/drivers/clk/qcom/mmcc-apq8084.c
+++ b/drivers/clk/qcom/mmcc-apq8084.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -26,6 +26,7 @@
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
+#include "gdsc.h"
enum {
P_XO,
@@ -571,17 +572,11 @@ static struct clk_rcg2 jpeg2_clk_src = {
},
};
-static struct freq_tbl pixel_freq_tbl[] = {
- { .src = P_DSI0PLL },
- { }
-};
-
static struct clk_rcg2 pclk0_clk_src = {
.cmd_rcgr = 0x2000,
.mnd_width = 8,
.hid_width = 5,
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
- .freq_tbl = pixel_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk0_clk_src",
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -596,7 +591,6 @@ static struct clk_rcg2 pclk1_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
- .freq_tbl = pixel_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk1_clk_src",
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -844,21 +838,15 @@ static struct clk_rcg2 cpp_clk_src = {
},
};
-static struct freq_tbl byte_freq_tbl[] = {
- { .src = P_DSI0PLL_BYTE },
- { }
-};
-
static struct clk_rcg2 byte0_clk_src = {
.cmd_rcgr = 0x2120,
.hid_width = 5,
.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
- .freq_tbl = byte_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "byte0_clk_src",
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
.num_parents = 6,
- .ops = &clk_byte_ops,
+ .ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -867,12 +855,11 @@ static struct clk_rcg2 byte1_clk_src = {
.cmd_rcgr = 0x2140,
.hid_width = 5,
.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
- .freq_tbl = byte_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "byte1_clk_src",
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
.num_parents = 6,
- .ops = &clk_byte_ops,
+ .ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -3077,6 +3064,76 @@ static const struct pll_config mmpll3_config = {
.aux_output_mask = BIT(1),
};
+static struct gdsc venus0_gdsc = {
+ .gdscr = 0x1024,
+ .pd = {
+ .name = "venus0",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc venus0_core0_gdsc = {
+ .gdscr = 0x1040,
+ .pd = {
+ .name = "venus0_core0",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc venus0_core1_gdsc = {
+ .gdscr = 0x1044,
+ .pd = {
+ .name = "venus0_core1",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc mdss_gdsc = {
+ .gdscr = 0x2304,
+ .cxcs = (unsigned int []){ 0x231c, 0x2320 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "mdss",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc camss_jpeg_gdsc = {
+ .gdscr = 0x35a4,
+ .pd = {
+ .name = "camss_jpeg",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc camss_vfe_gdsc = {
+ .gdscr = 0x36a4,
+ .cxcs = (unsigned int []){ 0x36a8, 0x36ac, 0x36b0 },
+ .cxc_count = 3,
+ .pd = {
+ .name = "camss_vfe",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxili_gdsc = {
+ .gdscr = 0x4024,
+ .cxcs = (unsigned int []){ 0x4028 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "oxili",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxilicx_gdsc = {
+ .gdscr = 0x4034,
+ .pd = {
+ .name = "oxilicx",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct clk_regmap *mmcc_apq8084_clocks[] = {
[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
@@ -3294,6 +3351,17 @@ static const struct qcom_reset_map mmcc_apq8084_resets[] = {
[MMSSNOCAXI_RESET] = { 0x5060 },
};
+static struct gdsc *mmcc_apq8084_gdscs[] = {
+ [VENUS0_GDSC] = &venus0_gdsc,
+ [VENUS0_CORE0_GDSC] = &venus0_core0_gdsc,
+ [VENUS0_CORE1_GDSC] = &venus0_core1_gdsc,
+ [MDSS_GDSC] = &mdss_gdsc,
+ [CAMSS_JPEG_GDSC] = &camss_jpeg_gdsc,
+ [CAMSS_VFE_GDSC] = &camss_vfe_gdsc,
+ [OXILI_GDSC] = &oxili_gdsc,
+ [OXILICX_GDSC] = &oxilicx_gdsc,
+};
+
static const struct regmap_config mmcc_apq8084_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -3308,6 +3376,8 @@ static const struct qcom_cc_desc mmcc_apq8084_desc = {
.num_clks = ARRAY_SIZE(mmcc_apq8084_clocks),
.resets = mmcc_apq8084_resets,
.num_resets = ARRAY_SIZE(mmcc_apq8084_resets),
+ .gdscs = mmcc_apq8084_gdscs,
+ .num_gdscs = ARRAY_SIZE(mmcc_apq8084_gdscs),
};
static const struct of_device_id mmcc_apq8084_match_table[] = {
@@ -3332,15 +3402,8 @@ static int mmcc_apq8084_probe(struct platform_device *pdev)
return 0;
}
-static int mmcc_apq8084_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver mmcc_apq8084_driver = {
.probe = mmcc_apq8084_probe,
- .remove = mmcc_apq8084_remove,
.driver = {
.name = "mmcc-apq8084",
.of_match_table = mmcc_apq8084_match_table,
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index bad02aebf959..00e36192a1de 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -41,6 +41,10 @@ enum {
P_PLL3,
P_PLL15,
P_HDMI_PLL,
+ P_DSI1_PLL_DSICLK,
+ P_DSI2_PLL_DSICLK,
+ P_DSI1_PLL_BYTECLK,
+ P_DSI2_PLL_BYTECLK,
};
#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
@@ -85,6 +89,30 @@ static const char * const mmcc_pxo_pll8_pll2_pll3[] = {
"pll3",
};
+static const struct parent_map mmcc_pxo_dsi2_dsi1_map[] = {
+ { P_PXO, 0 },
+ { P_DSI2_PLL_DSICLK, 1 },
+ { P_DSI1_PLL_DSICLK, 3 },
+};
+
+static const char * const mmcc_pxo_dsi2_dsi1[] = {
+ "pxo",
+ "dsi2pll",
+ "dsi1pll",
+};
+
+static const struct parent_map mmcc_pxo_dsi1_dsi2_byte_map[] = {
+ { P_PXO, 0 },
+ { P_DSI1_PLL_BYTECLK, 1 },
+ { P_DSI2_PLL_BYTECLK, 2 },
+};
+
+static const char * const mmcc_pxo_dsi1_dsi2_byte[] = {
+ "pxo",
+ "dsi1pllbyte",
+ "dsi2pllbyte",
+};
+
static struct clk_pll pll2 = {
.l_reg = 0x320,
.m_reg = 0x324,
@@ -2042,6 +2070,350 @@ static struct clk_branch dsi2_s_ahb_clk = {
},
};
+static struct clk_rcg dsi1_src = {
+ .ns_reg = 0x0054,
+ .md_reg = 0x0050,
+ .mn = {
+ .mnctr_en_bit = 5,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 6,
+ .n_val_shift = 24,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 14,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi2_dsi1_map,
+ },
+ .clkr = {
+ .enable_reg = 0x004c,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_src",
+ .parent_names = mmcc_pxo_dsi2_dsi1,
+ .num_parents = 3,
+ .ops = &clk_rcg_bypass2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch dsi1_clk = {
+ .halt_reg = 0x01d0,
+ .halt_bit = 2,
+ .clkr = {
+ .enable_reg = 0x004c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_clk",
+ .parent_names = (const char *[]){ "dsi1_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi2_src = {
+ .ns_reg = 0x012c,
+ .md_reg = 0x00a8,
+ .mn = {
+ .mnctr_en_bit = 5,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 6,
+ .n_val_shift = 24,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 14,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi2_dsi1_map,
+ },
+ .clkr = {
+ .enable_reg = 0x003c,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_src",
+ .parent_names = mmcc_pxo_dsi2_dsi1,
+ .num_parents = 3,
+ .ops = &clk_rcg_bypass2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch dsi2_clk = {
+ .halt_reg = 0x01d0,
+ .halt_bit = 20,
+ .clkr = {
+ .enable_reg = 0x003c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_clk",
+ .parent_names = (const char *[]){ "dsi2_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi1_byte_src = {
+ .ns_reg = 0x00b0,
+ .p = {
+ .pre_div_shift = 12,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+ },
+ .clkr = {
+ .enable_reg = 0x0090,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_byte_src",
+ .parent_names = mmcc_pxo_dsi1_dsi2_byte,
+ .num_parents = 3,
+ .ops = &clk_rcg_bypass2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch dsi1_byte_clk = {
+ .halt_reg = 0x01cc,
+ .halt_bit = 21,
+ .clkr = {
+ .enable_reg = 0x0090,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_byte_clk",
+ .parent_names = (const char *[]){ "dsi1_byte_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi2_byte_src = {
+ .ns_reg = 0x012c,
+ .p = {
+ .pre_div_shift = 12,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+ },
+ .clkr = {
+ .enable_reg = 0x0130,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_byte_src",
+ .parent_names = mmcc_pxo_dsi1_dsi2_byte,
+ .num_parents = 3,
+ .ops = &clk_rcg_bypass2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch dsi2_byte_clk = {
+ .halt_reg = 0x01cc,
+ .halt_bit = 20,
+ .clkr = {
+ .enable_reg = 0x00b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_byte_clk",
+ .parent_names = (const char *[]){ "dsi2_byte_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi1_esc_src = {
+ .ns_reg = 0x0011c,
+ .p = {
+ .pre_div_shift = 12,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+ },
+ .clkr = {
+ .enable_reg = 0x00cc,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_esc_src",
+ .parent_names = mmcc_pxo_dsi1_dsi2_byte,
+ .num_parents = 3,
+ .ops = &clk_rcg_esc_ops,
+ },
+ },
+};
+
+static struct clk_branch dsi1_esc_clk = {
+ .halt_reg = 0x01e8,
+ .halt_bit = 1,
+ .clkr = {
+ .enable_reg = 0x00cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_esc_clk",
+ .parent_names = (const char *[]){ "dsi1_esc_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi2_esc_src = {
+ .ns_reg = 0x0150,
+ .p = {
+ .pre_div_shift = 12,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+ },
+ .clkr = {
+ .enable_reg = 0x013c,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_esc_src",
+ .parent_names = mmcc_pxo_dsi1_dsi2_byte,
+ .num_parents = 3,
+ .ops = &clk_rcg_esc_ops,
+ },
+ },
+};
+
+static struct clk_branch dsi2_esc_clk = {
+ .halt_reg = 0x01e8,
+ .halt_bit = 3,
+ .clkr = {
+ .enable_reg = 0x013c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_esc_clk",
+ .parent_names = (const char *[]){ "dsi2_esc_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi1_pixel_src = {
+ .ns_reg = 0x0138,
+ .md_reg = 0x0134,
+ .mn = {
+ .mnctr_en_bit = 5,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 6,
+ .n_val_shift = 16,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 12,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi2_dsi1_map,
+ },
+ .clkr = {
+ .enable_reg = 0x0130,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1_pixel_src",
+ .parent_names = mmcc_pxo_dsi2_dsi1,
+ .num_parents = 3,
+ .ops = &clk_rcg_pixel_ops,
+ },
+ },
+};
+
+static struct clk_branch dsi1_pixel_clk = {
+ .halt_reg = 0x01d0,
+ .halt_bit = 6,
+ .clkr = {
+ .enable_reg = 0x0130,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdp_pclk1_clk",
+ .parent_names = (const char *[]){ "dsi1_pixel_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg dsi2_pixel_src = {
+ .ns_reg = 0x00e4,
+ .md_reg = 0x00b8,
+ .mn = {
+ .mnctr_en_bit = 5,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 6,
+ .n_val_shift = 16,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 12,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_dsi2_dsi1_map,
+ },
+ .clkr = {
+ .enable_reg = 0x0094,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi2_pixel_src",
+ .parent_names = mmcc_pxo_dsi2_dsi1,
+ .num_parents = 3,
+ .ops = &clk_rcg_pixel_ops,
+ },
+ },
+};
+
+static struct clk_branch dsi2_pixel_clk = {
+ .halt_reg = 0x01d0,
+ .halt_bit = 19,
+ .clkr = {
+ .enable_reg = 0x0094,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdp_pclk2_clk",
+ .parent_names = (const char *[]){ "dsi2_pixel_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
static struct clk_branch gfx2d0_ahb_clk = {
.hwcg_reg = 0x0038,
.hwcg_bit = 28,
@@ -2325,6 +2697,8 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
[CSI2_SRC] = &csi2_src.clkr,
[CSI2_CLK] = &csi2_clk.clkr,
[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
+ [DSI_SRC] = &dsi1_src.clkr,
+ [DSI_CLK] = &dsi1_clk.clkr,
[CSI_PIX_CLK] = &csi_pix_clk.clkr,
[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
@@ -2345,6 +2719,18 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
[MDP_SRC] = &mdp_src.clkr,
[MDP_CLK] = &mdp_clk.clkr,
[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
+ [DSI2_PIXEL_SRC] = &dsi2_pixel_src.clkr,
+ [DSI2_PIXEL_CLK] = &dsi2_pixel_clk.clkr,
+ [DSI2_SRC] = &dsi2_src.clkr,
+ [DSI2_CLK] = &dsi2_clk.clkr,
+ [DSI1_BYTE_SRC] = &dsi1_byte_src.clkr,
+ [DSI1_BYTE_CLK] = &dsi1_byte_clk.clkr,
+ [DSI2_BYTE_SRC] = &dsi2_byte_src.clkr,
+ [DSI2_BYTE_CLK] = &dsi2_byte_clk.clkr,
+ [DSI1_ESC_SRC] = &dsi1_esc_src.clkr,
+ [DSI1_ESC_CLK] = &dsi1_esc_clk.clkr,
+ [DSI2_ESC_SRC] = &dsi2_esc_src.clkr,
+ [DSI2_ESC_CLK] = &dsi2_esc_clk.clkr,
[ROT_SRC] = &rot_src.clkr,
[ROT_CLK] = &rot_clk.clkr,
[TV_ENC_CLK] = &tv_enc_clk.clkr,
@@ -2359,6 +2745,8 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
[VPE_SRC] = &vpe_src.clkr,
[VPE_CLK] = &vpe_clk.clkr,
+ [DSI_PIXEL_SRC] = &dsi1_pixel_src.clkr,
+ [DSI_PIXEL_CLK] = &dsi1_pixel_clk.clkr,
[CAMCLK0_SRC] = &camclk0_src.clkr,
[CAMCLK0_CLK] = &camclk0_clk.clkr,
[CAMCLK1_SRC] = &camclk1_src.clkr,
@@ -2490,6 +2878,8 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
[CSI2_SRC] = &csi2_src.clkr,
[CSI2_CLK] = &csi2_clk.clkr,
[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
+ [DSI_SRC] = &dsi1_src.clkr,
+ [DSI_CLK] = &dsi1_clk.clkr,
[CSI_PIX_CLK] = &csi_pix_clk.clkr,
[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
@@ -2506,6 +2896,18 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
[MDP_SRC] = &mdp_src.clkr,
[MDP_CLK] = &mdp_clk.clkr,
[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
+ [DSI2_PIXEL_SRC] = &dsi2_pixel_src.clkr,
+ [DSI2_PIXEL_CLK] = &dsi2_pixel_clk.clkr,
+ [DSI2_SRC] = &dsi2_src.clkr,
+ [DSI2_CLK] = &dsi2_clk.clkr,
+ [DSI1_BYTE_SRC] = &dsi1_byte_src.clkr,
+ [DSI1_BYTE_CLK] = &dsi1_byte_clk.clkr,
+ [DSI2_BYTE_SRC] = &dsi2_byte_src.clkr,
+ [DSI2_BYTE_CLK] = &dsi2_byte_clk.clkr,
+ [DSI1_ESC_SRC] = &dsi1_esc_src.clkr,
+ [DSI1_ESC_CLK] = &dsi1_esc_clk.clkr,
+ [DSI2_ESC_SRC] = &dsi2_esc_src.clkr,
+ [DSI2_ESC_CLK] = &dsi2_esc_clk.clkr,
[ROT_SRC] = &rot_src.clkr,
[ROT_CLK] = &rot_clk.clkr,
[TV_DAC_CLK] = &tv_dac_clk.clkr,
@@ -2519,6 +2921,8 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
[VPE_SRC] = &vpe_src.clkr,
[VPE_CLK] = &vpe_clk.clkr,
+ [DSI_PIXEL_SRC] = &dsi1_pixel_src.clkr,
+ [DSI_PIXEL_CLK] = &dsi1_pixel_clk.clkr,
[CAMCLK0_SRC] = &camclk0_src.clkr,
[CAMCLK0_CLK] = &camclk0_clk.clkr,
[CAMCLK1_SRC] = &camclk1_src.clkr,
@@ -2686,15 +3090,8 @@ static int mmcc_msm8960_probe(struct platform_device *pdev)
return qcom_cc_really_probe(pdev, match->data, regmap);
}
-static int mmcc_msm8960_remove(struct platform_device *pdev)
-{
- qcom_cc_remove(pdev);
- return 0;
-}
-
static struct platform_driver mmcc_msm8960_driver = {
.probe = mmcc_msm8960_probe,
- .remove = mmcc_msm8960_remove,
.driver = {
.name = "mmcc-msm8960",
.of_match_table = mmcc_msm8960_match_table,
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index 0987bf443e1f..9d790bcadf25 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -31,6 +31,7 @@
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
+#include "gdsc.h"
enum {
P_XO,
@@ -522,17 +523,11 @@ static struct clk_rcg2 jpeg2_clk_src = {
},
};
-static struct freq_tbl pixel_freq_tbl[] = {
- { .src = P_DSI0PLL },
- { }
-};
-
static struct clk_rcg2 pclk0_clk_src = {
.cmd_rcgr = 0x2000,
.mnd_width = 8,
.hid_width = 5,
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
- .freq_tbl = pixel_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk0_clk_src",
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -547,7 +542,6 @@ static struct clk_rcg2 pclk1_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
- .freq_tbl = pixel_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk1_clk_src",
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -785,7 +779,7 @@ static struct clk_rcg2 byte0_clk_src = {
.name = "byte0_clk_src",
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
.num_parents = 6,
- .ops = &clk_byte_ops,
+ .ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -799,7 +793,7 @@ static struct clk_rcg2 byte1_clk_src = {
.name = "byte1_clk_src",
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
.num_parents = 6,
- .ops = &clk_byte_ops,
+ .ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -2349,6 +2343,66 @@ static struct pll_config mmpll3_config = {
.aux_output_mask = BIT(1),
};
+static struct gdsc venus0_gdsc = {
+ .gdscr = 0x1024,
+ .cxcs = (unsigned int []){ 0x1028 },
+ .cxc_count = 1,
+ .resets = (unsigned int []){ VENUS0_RESET },
+ .reset_count = 1,
+ .pd = {
+ .name = "venus0",
+ },
+ .pwrsts = PWRSTS_ON,
+};
+
+static struct gdsc mdss_gdsc = {
+ .gdscr = 0x2304,
+ .cxcs = (unsigned int []){ 0x231c, 0x2320 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "mdss",
+ },
+ .pwrsts = PWRSTS_RET_ON,
+};
+
+static struct gdsc camss_jpeg_gdsc = {
+ .gdscr = 0x35a4,
+ .cxcs = (unsigned int []){ 0x35a8, 0x35ac, 0x35b0 },
+ .cxc_count = 3,
+ .pd = {
+ .name = "camss_jpeg",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc camss_vfe_gdsc = {
+ .gdscr = 0x36a4,
+ .cxcs = (unsigned int []){ 0x36a8, 0x36ac, 0x3704, 0x3714, 0x36b0 },
+ .cxc_count = 5,
+ .pd = {
+ .name = "camss_vfe",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxili_gdsc = {
+ .gdscr = 0x4024,
+ .cxcs = (unsigned int []){ 0x4028 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "oxili",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxilicx_gdsc = {
+ .gdscr = 0x4034,
+ .pd = {
+ .name = "oxilicx",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct clk_regmap *mmcc_msm8974_clocks[] = {
[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
@@ -2525,6 +2579,15 @@ static const struct qcom_reset_map mmcc_msm8974_resets[] = {
[OCMEMNOC_RESET] = { 0x50b0 },
};
+static struct gdsc *mmcc_msm8974_gdscs[] = {
+ [VENUS0_GDSC] = &venus0_gdsc,
+ [MDSS_GDSC] = &mdss_gdsc,
+ [CAMSS_JPEG_GDSC] = &camss_jpeg_gdsc,
+ [CAMSS_VFE_GDSC] = &camss_vfe_gdsc,
+ [OXILI_GDSC] = &oxili_gdsc,
+ [OXILICX_GDSC] = &oxilicx_gdsc,
+};
+
static const struct regmap_config mmcc_msm8974_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -2539,6 +2602,8 @@ static const struct qcom_cc_desc mmcc_msm8974_desc = {
.num_clks = ARRAY_SIZE(mmcc_msm8974_clocks),
.resets = mmcc_msm8974_resets,
.num_resets = ARRAY_SIZE(mmcc_msm8974_resets),
+ .gdscs = mmcc_msm8974_gdscs,
+ .num_gdscs = ARRAY_SIZE(mmcc_msm8974_gdscs),
};
static const struct of_device_id mmcc_msm8974_match_table[] = {
@@ -2550,6 +2615,7 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
static int mmcc_msm8974_probe(struct platform_device *pdev)
{
struct regmap *regmap;
+ int ret;
regmap = qcom_cc_map(pdev, &mmcc_msm8974_desc);
if (IS_ERR(regmap))
@@ -2558,12 +2624,16 @@ static int mmcc_msm8974_probe(struct platform_device *pdev)
clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
- return qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
+ ret = qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
+ if (ret)
+ return ret;
+
+ return pm_genpd_add_subdomain(&oxili_gdsc.pd, &oxilicx_gdsc.pd);
}
static int mmcc_msm8974_remove(struct platform_device *pdev)
{
- qcom_cc_remove(pdev);
+ pm_genpd_remove_subdomain(&oxili_gdsc.pd, &oxilicx_gdsc.pd);
return 0;
}
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index 9b613426e968..2685644826a0 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -41,12 +41,14 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
#define ROCKCHIP_MMC_DEGREE_MASK 0x3
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
+#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
+#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
#define PSECS_PER_SEC 1000000000000LL
/*
- * Each fine delay is between 40ps-80ps. Assume each fine delay is 60ps to
- * simplify calculations. So 45degs could be anywhere between 33deg and 66deg.
+ * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
+ * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
*/
#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
@@ -69,7 +71,7 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
- degrees += delay_num * factor / 10000;
+ degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
}
return degrees % 360;
@@ -82,25 +84,41 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
u8 nineties, remainder;
u8 delay_num;
u32 raw_value;
- u64 delay;
-
- /* allow 22 to be 22.5 */
- degrees++;
- /* floor to 22.5 increment */
- degrees -= ((degrees) * 10 % 225) / 10;
+ u32 delay;
nineties = degrees / 90;
- /* 22.5 multiples */
- remainder = (degrees % 90) / 22;
-
- delay = PSECS_PER_SEC;
- do_div(delay, rate);
- /* / 360 / 22.5 */
- do_div(delay, 16);
- do_div(delay, ROCKCHIP_MMC_DELAY_ELEMENT_PSEC);
-
+ remainder = (degrees % 90);
+
+ /*
+ * Due to the inexact nature of the "fine" delay, we might
+ * actually go non-monotonic. We don't go _too_ monotonic
+ * though, so we should be OK. Here are options of how we may
+ * work:
+ *
+ * Ideally we end up with:
+ * 1.0, 2.0, ..., 69.0, 70.0, ..., 89.0, 90.0
+ *
+ * On one extreme (if delay is actually 44ps):
+ * .73, 1.5, ..., 50.6, 51.3, ..., 65.3, 90.0
+ * The other (if delay is actually 77ps):
+ * 1.3, 2.6, ..., 88.6. 89.8, ..., 114.0, 90
+ *
+ * It's possible we might make a delay that is up to 25
+ * degrees off from what we think we're making. That's OK
+ * though because we should be REALLY far from any bad range.
+ */
+
+ /*
+ * Convert to delay; do a little extra work to make sure we
+ * don't overflow 32-bit / 64-bit numbers.
+ */
+ delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
delay *= remainder;
- delay_num = (u8) min(delay, 255ULL);
+ delay = DIV_ROUND_CLOSEST(delay,
+ (rate / 1000) * 36 *
+ (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
+
+ delay_num = (u8) min_t(u32, delay, 255);
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
@@ -143,6 +161,15 @@ struct clk *rockchip_clk_register_mmc(const char *name,
mmc_clock->reg = reg;
mmc_clock->shift = shift;
+ /*
+ * Assert init_state to soft reset the CLKGEN
+ * for mmc tuning phase and degree
+ */
+ if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
+ writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
+ ROCKCHIP_MMC_INIT_STATE_RESET,
+ mmc_clock->shift), mmc_clock->reg);
+
clk = clk_register(NULL, &mmc_clock->hw);
if (IS_ERR(clk))
goto err_free;
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 7737a1df1e4b..4881eb8a1576 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -126,11 +126,32 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
#define RK3066_PLLCON3_PWRDOWN (1 << 1)
#define RK3066_PLLCON3_BYPASS (1 << 0)
+static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll,
+ struct rockchip_pll_rate_table *rate)
+{
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
+ rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT)
+ & RK3066_PLLCON0_NR_MASK) + 1;
+ rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT)
+ & RK3066_PLLCON0_OD_MASK) + 1;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
+ rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT)
+ & RK3066_PLLCON1_NF_MASK) + 1;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
+ rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT)
+ & RK3066_PLLCON2_NB_MASK) + 1;
+}
+
static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
- u64 nf, nr, no, rate64 = prate;
+ struct rockchip_pll_rate_table cur;
+ u64 rate64 = prate;
u32 pllcon;
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
@@ -140,53 +161,31 @@ static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
return prate;
}
- pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
- nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK;
-
- pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
- nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK;
- no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK;
+ rockchip_rk3066_pll_get_params(pll, &cur);
- rate64 *= (nf + 1);
- do_div(rate64, nr + 1);
- do_div(rate64, no + 1);
+ rate64 *= cur.nf;
+ do_div(rate64, cur.nr);
+ do_div(rate64, cur.no);
return (unsigned long)rate64;
}
-static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
- unsigned long prate)
+static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll,
+ const struct rockchip_pll_rate_table *rate)
{
- struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
- const struct rockchip_pll_rate_table *rate;
- unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
- struct regmap *grf = rockchip_clk_get_grf();
- struct clk_mux *pll_mux = &pll->pll_mux;
const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ struct rockchip_pll_rate_table cur;
int rate_change_remuxed = 0;
int cur_parent;
int ret;
- if (IS_ERR(grf)) {
- pr_debug("%s: grf regmap not available, aborting rate change\n",
- __func__);
- return PTR_ERR(grf);
- }
-
- pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
- __func__, clk_hw_get_name(hw), old_rate, drate, prate);
-
- /* Get required rate settings from table */
- rate = rockchip_get_pll_settings(pll, drate);
- if (!rate) {
- pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
- drate, clk_hw_get_name(hw));
- return -EINVAL;
- }
-
pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
__func__, rate->rate, rate->nr, rate->no, rate->nf);
+ rockchip_rk3066_pll_get_params(pll, &cur);
+ cur.rate = 0;
+
cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
if (cur_parent == PLL_MODE_NORM) {
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
@@ -219,9 +218,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
/* wait for the pll to lock */
ret = rockchip_pll_wait_lock(pll);
if (ret) {
- pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
- __func__, old_rate);
- rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
+ pr_warn("%s: pll update unsucessful, trying to restore old params\n",
+ __func__);
+ rockchip_rk3066_pll_set_params(pll, &cur);
}
if (rate_change_remuxed)
@@ -230,6 +229,34 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
return ret;
}
+static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+ unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
+ struct regmap *grf = rockchip_clk_get_grf();
+
+ if (IS_ERR(grf)) {
+ pr_debug("%s: grf regmap not available, aborting rate change\n",
+ __func__);
+ return PTR_ERR(grf);
+ }
+
+ pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
+ __func__, clk_hw_get_name(hw), old_rate, drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ return rockchip_rk3066_pll_set_params(pll, rate);
+}
+
static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
@@ -261,9 +288,8 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
const struct rockchip_pll_rate_table *rate;
- unsigned int nf, nr, no, nb;
+ struct rockchip_pll_rate_table cur;
unsigned long drate;
- u32 pllcon;
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
return;
@@ -275,34 +301,21 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
if (!rate)
return;
- pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
- nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1;
- no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1;
-
- pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
- nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
-
- pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
- nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1;
+ rockchip_rk3066_pll_get_params(pll, &cur);
pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
- __func__, clk_hw_get_name(hw), drate, rate->nr, nr,
- rate->no, no, rate->nf, nf, rate->nb, nb);
- if (rate->nr != nr || rate->no != no || rate->nf != nf
- || rate->nb != nb) {
- struct clk_hw *parent = clk_hw_get_parent(hw);
- unsigned long prate;
-
- if (!parent) {
- pr_warn("%s: parent of %s not available\n",
- __func__, clk_hw_get_name(hw));
+ __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr,
+ rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
+ if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf
+ || rate->nb != cur.nb) {
+ struct regmap *grf = rockchip_clk_get_grf();
+
+ if (IS_ERR(grf))
return;
- }
pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
__func__, clk_hw_get_name(hw));
- prate = clk_hw_get_rate(parent);
- rockchip_rk3066_pll_set_rate(hw, drate, prate);
+ rockchip_rk3066_pll_set_params(pll, rate);
}
}
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 24938815655f..be6c7fd8315d 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -135,9 +135,11 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
div->flags = div_flags;
div->reg = base + muxdiv_offset;
div->mshift = 16;
- div->mmask = 0xffff0000;
+ div->mwidth = 16;
+ div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
div->nshift = 0;
- div->nmask = 0xffff;
+ div->nwidth = 16;
+ div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
div->lock = lock;
div_ops = &clk_fractional_divider_ops;
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 55b83c7ef878..5bebf8cb0d70 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -222,9 +222,13 @@ PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" };
PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" };
PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" };
PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" };
+PNAME(mout_aclk300_p) = { "mout_aclk300_disp1_mid",
+ "mout_aclk300_disp1_mid1" };
PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" };
PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" };
PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" };
+PNAME(mout_aclk300_sub_p) = { "fin_pll", "div_aclk300_disp" };
+PNAME(mout_aclk300_disp1_mid1_p) = { "mout_vpll", "mout_cpll" };
PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" };
PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" };
PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
@@ -303,9 +307,13 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
*/
MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
+ MUX(0, "mout_aclk300_disp1_mid", mout_aclk200_p, SRC_TOP0, 14, 1),
+ MUX(0, "mout_aclk300", mout_aclk300_p, SRC_TOP0, 15, 1),
MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1),
+ MUX(0, "mout_aclk300_disp1_mid1", mout_aclk300_disp1_mid1_p, SRC_TOP1,
+ 8, 1),
MUX(0, "mout_aclk400_isp", mout_aclk200_p, SRC_TOP1, 24, 1),
MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1),
@@ -316,7 +324,10 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
MUX(CLK_MOUT_GPLL, "mout_gpll", mout_gpll_p, SRC_TOP2, 28, 1),
- MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1),
+ MUX(CLK_MOUT_ACLK200_DISP1_SUB, "mout_aclk200_disp1_sub",
+ mout_aclk200_sub_p, SRC_TOP3, 4, 1),
+ MUX(CLK_MOUT_ACLK300_DISP1_SUB, "mout_aclk300_disp1_sub",
+ mout_aclk300_sub_p, SRC_TOP3, 6, 1),
MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1),
MUX(0, "mout_aclk_266_isp_sub", mout_aclk266_sub_p, SRC_TOP3, 16, 1),
MUX(0, "mout_aclk_400_isp_sub", mout_aclk400_isp_sub_p,
@@ -392,6 +403,7 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0,
24, 3),
+ DIV(0, "div_aclk300_disp", "mout_aclk300", DIV_TOP0, 28, 3),
DIV(0, "div_aclk400_isp", "mout_aclk400_isp", DIV_TOP1, 20, 3),
DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index 8524e667097e..55f8e2e24ab8 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -32,39 +32,41 @@
#define DIV_TOPC0 0x0600
#define DIV_TOPC1 0x0604
#define DIV_TOPC3 0x060C
+#define ENABLE_ACLK_TOPC0 0x0800
#define ENABLE_ACLK_TOPC1 0x0804
+#define ENABLE_SCLK_TOPC1 0x0A04
static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
- FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
+ FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_topc_bus0_pll", 1, 2, 0),
FFACTOR(0, "ffac_topc_bus0_pll_div4",
"ffac_topc_bus0_pll_div2", 1, 2, 0),
- FFACTOR(0, "ffac_topc_bus1_pll_div2", "mout_bus1_pll_ctrl", 1, 2, 0),
- FFACTOR(0, "ffac_topc_cc_pll_div2", "mout_cc_pll_ctrl", 1, 2, 0),
- FFACTOR(0, "ffac_topc_mfc_pll_div2", "mout_mfc_pll_ctrl", 1, 2, 0),
+ FFACTOR(0, "ffac_topc_bus1_pll_div2", "mout_topc_bus1_pll", 1, 2, 0),
+ FFACTOR(0, "ffac_topc_cc_pll_div2", "mout_topc_cc_pll", 1, 2, 0),
+ FFACTOR(0, "ffac_topc_mfc_pll_div2", "mout_topc_mfc_pll", 1, 2, 0),
};
/* List of parent clocks for Muxes in CMU_TOPC */
-PNAME(mout_aud_pll_ctrl_p) = { "fin_pll", "fout_aud_pll" };
-PNAME(mout_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" };
-PNAME(mout_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" };
-PNAME(mout_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" };
-PNAME(mout_mfc_pll_ctrl_p) = { "fin_pll", "fout_mfc_pll" };
+PNAME(mout_topc_aud_pll_ctrl_p) = { "fin_pll", "fout_aud_pll" };
+PNAME(mout_topc_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" };
+PNAME(mout_topc_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" };
+PNAME(mout_topc_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" };
+PNAME(mout_topc_mfc_pll_ctrl_p) = { "fin_pll", "fout_mfc_pll" };
-PNAME(mout_topc_group2) = { "mout_sclk_bus0_pll_cmuc",
- "mout_sclk_bus1_pll_cmuc", "mout_sclk_cc_pll_cmuc",
- "mout_sclk_mfc_pll_cmuc" };
+PNAME(mout_topc_group2) = { "mout_topc_bus0_pll_half",
+ "mout_topc_bus1_pll_half", "mout_topc_cc_pll_half",
+ "mout_topc_mfc_pll_half" };
-PNAME(mout_sclk_bus0_pll_cmuc_p) = { "mout_bus0_pll_ctrl",
+PNAME(mout_topc_bus0_pll_half_p) = { "mout_topc_bus0_pll",
"ffac_topc_bus0_pll_div2", "ffac_topc_bus0_pll_div4"};
-PNAME(mout_sclk_bus1_pll_cmuc_p) = { "mout_bus1_pll_ctrl",
+PNAME(mout_topc_bus1_pll_half_p) = { "mout_topc_bus1_pll",
"ffac_topc_bus1_pll_div2"};
-PNAME(mout_sclk_cc_pll_cmuc_p) = { "mout_cc_pll_ctrl",
+PNAME(mout_topc_cc_pll_half_p) = { "mout_topc_cc_pll",
"ffac_topc_cc_pll_div2"};
-PNAME(mout_sclk_mfc_pll_cmuc_p) = { "mout_mfc_pll_ctrl",
+PNAME(mout_topc_mfc_pll_half_p) = { "mout_topc_mfc_pll",
"ffac_topc_mfc_pll_div2"};
-PNAME(mout_sclk_bus0_pll_out_p) = {"mout_bus0_pll_ctrl",
+PNAME(mout_topc_bus0_pll_out_p) = {"mout_topc_bus0_pll",
"ffac_topc_bus0_pll_div2"};
static unsigned long topc_clk_regs[] __initdata = {
@@ -88,23 +90,27 @@ static unsigned long topc_clk_regs[] __initdata = {
};
static struct samsung_mux_clock topc_mux_clks[] __initdata = {
- MUX(0, "mout_bus0_pll_ctrl", mout_bus0_pll_ctrl_p, MUX_SEL_TOPC0, 0, 1),
- MUX(0, "mout_bus1_pll_ctrl", mout_bus1_pll_ctrl_p, MUX_SEL_TOPC0, 4, 1),
- MUX(0, "mout_cc_pll_ctrl", mout_cc_pll_ctrl_p, MUX_SEL_TOPC0, 8, 1),
- MUX(0, "mout_mfc_pll_ctrl", mout_mfc_pll_ctrl_p, MUX_SEL_TOPC0, 12, 1),
-
- MUX(0, "mout_sclk_bus0_pll_cmuc", mout_sclk_bus0_pll_cmuc_p,
+ MUX(0, "mout_topc_bus0_pll", mout_topc_bus0_pll_ctrl_p,
+ MUX_SEL_TOPC0, 0, 1),
+ MUX(0, "mout_topc_bus1_pll", mout_topc_bus1_pll_ctrl_p,
+ MUX_SEL_TOPC0, 4, 1),
+ MUX(0, "mout_topc_cc_pll", mout_topc_cc_pll_ctrl_p,
+ MUX_SEL_TOPC0, 8, 1),
+ MUX(0, "mout_topc_mfc_pll", mout_topc_mfc_pll_ctrl_p,
+ MUX_SEL_TOPC0, 12, 1),
+ MUX(0, "mout_topc_bus0_pll_half", mout_topc_bus0_pll_half_p,
MUX_SEL_TOPC0, 16, 2),
- MUX(0, "mout_sclk_bus1_pll_cmuc", mout_sclk_bus1_pll_cmuc_p,
+ MUX(0, "mout_topc_bus1_pll_half", mout_topc_bus1_pll_half_p,
MUX_SEL_TOPC0, 20, 1),
- MUX(0, "mout_sclk_cc_pll_cmuc", mout_sclk_cc_pll_cmuc_p,
+ MUX(0, "mout_topc_cc_pll_half", mout_topc_cc_pll_half_p,
MUX_SEL_TOPC0, 24, 1),
- MUX(0, "mout_sclk_mfc_pll_cmuc", mout_sclk_mfc_pll_cmuc_p,
+ MUX(0, "mout_topc_mfc_pll_half", mout_topc_mfc_pll_half_p,
MUX_SEL_TOPC0, 28, 1),
- MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p,
+ MUX(0, "mout_topc_aud_pll", mout_topc_aud_pll_ctrl_p,
+ MUX_SEL_TOPC1, 0, 1),
+ MUX(0, "mout_topc_bus0_pll_out", mout_topc_bus0_pll_out_p,
MUX_SEL_TOPC1, 16, 1),
- MUX(0, "mout_aud_pll_ctrl", mout_aud_pll_ctrl_p, MUX_SEL_TOPC1, 0, 1),
MUX(0, "mout_aclk_ccore_133", mout_topc_group2, MUX_SEL_TOPC2, 4, 2),
@@ -121,16 +127,16 @@ static struct samsung_div_clock topc_div_clks[] __initdata = {
DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66",
DIV_TOPC1, 24, 4),
- DIV(DOUT_SCLK_BUS0_PLL, "dout_sclk_bus0_pll", "mout_sclk_bus0_pll_out",
- DIV_TOPC3, 0, 3),
- DIV(DOUT_SCLK_BUS1_PLL, "dout_sclk_bus1_pll", "mout_bus1_pll_ctrl",
- DIV_TOPC3, 8, 3),
- DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_cc_pll_ctrl",
- DIV_TOPC3, 12, 3),
- DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_mfc_pll_ctrl",
- DIV_TOPC3, 16, 3),
- DIV(DOUT_SCLK_AUD_PLL, "dout_sclk_aud_pll", "mout_aud_pll_ctrl",
- DIV_TOPC3, 28, 3),
+ DIV(DOUT_SCLK_BUS0_PLL, "dout_sclk_bus0_pll", "mout_topc_bus0_pll_out",
+ DIV_TOPC3, 0, 4),
+ DIV(DOUT_SCLK_BUS1_PLL, "dout_sclk_bus1_pll", "mout_topc_bus1_pll",
+ DIV_TOPC3, 8, 4),
+ DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_topc_cc_pll",
+ DIV_TOPC3, 12, 4),
+ DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_topc_mfc_pll",
+ DIV_TOPC3, 16, 4),
+ DIV(DOUT_SCLK_AUD_PLL, "dout_sclk_aud_pll", "mout_topc_aud_pll",
+ DIV_TOPC3, 28, 4),
};
static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
@@ -139,8 +145,33 @@ static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
};
static struct samsung_gate_clock topc_gate_clks[] __initdata = {
+ GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133",
+ ENABLE_ACLK_TOPC0, 4, 0, 0),
+
GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532",
ENABLE_ACLK_TOPC1, 20, 0, 0),
+
+ GATE(ACLK_PERIS_66, "aclk_peris_66", "dout_aclk_peris_66",
+ ENABLE_ACLK_TOPC1, 24, 0, 0),
+
+ GATE(SCLK_AUD_PLL, "sclk_aud_pll", "dout_sclk_aud_pll",
+ ENABLE_SCLK_TOPC1, 20, 0, 0),
+ GATE(SCLK_MFC_PLL_B, "sclk_mfc_pll_b", "dout_sclk_mfc_pll",
+ ENABLE_SCLK_TOPC1, 17, 0, 0),
+ GATE(SCLK_MFC_PLL_A, "sclk_mfc_pll_a", "dout_sclk_mfc_pll",
+ ENABLE_SCLK_TOPC1, 16, 0, 0),
+ GATE(SCLK_BUS1_PLL_B, "sclk_bus1_pll_b", "dout_sclk_bus1_pll",
+ ENABLE_SCLK_TOPC1, 13, 0, 0),
+ GATE(SCLK_BUS1_PLL_A, "sclk_bus1_pll_a", "dout_sclk_bus1_pll",
+ ENABLE_SCLK_TOPC1, 12, 0, 0),
+ GATE(SCLK_BUS0_PLL_B, "sclk_bus0_pll_b", "dout_sclk_bus0_pll",
+ ENABLE_SCLK_TOPC1, 5, 0, 0),
+ GATE(SCLK_BUS0_PLL_A, "sclk_bus0_pll_a", "dout_sclk_bus0_pll",
+ ENABLE_SCLK_TOPC1, 4, 0, 0),
+ GATE(SCLK_CC_PLL_B, "sclk_cc_pll_b", "dout_sclk_cc_pll",
+ ENABLE_SCLK_TOPC1, 1, 0, 0),
+ GATE(SCLK_CC_PLL_A, "sclk_cc_pll_a", "dout_sclk_cc_pll",
+ ENABLE_SCLK_TOPC1, 0, 0, 0),
};
static struct samsung_pll_clock topc_pll_clks[] __initdata = {
@@ -193,36 +224,37 @@ CLK_OF_DECLARE(exynos7_clk_topc, "samsung,exynos7-clock-topc",
#define DIV_TOP0_PERIC1 0x0634
#define DIV_TOP0_PERIC2 0x0638
#define DIV_TOP0_PERIC3 0x063C
+#define ENABLE_ACLK_TOP03 0x080C
#define ENABLE_SCLK_TOP0_PERIC0 0x0A30
#define ENABLE_SCLK_TOP0_PERIC1 0x0A34
#define ENABLE_SCLK_TOP0_PERIC2 0x0A38
#define ENABLE_SCLK_TOP0_PERIC3 0x0A3C
/* List of parent clocks for Muxes in CMU_TOP0 */
-PNAME(mout_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" };
-PNAME(mout_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll" };
-PNAME(mout_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll" };
-PNAME(mout_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll" };
-PNAME(mout_aud_pll_p) = { "fin_pll", "dout_sclk_aud_pll" };
+PNAME(mout_top0_bus0_pll_user_p) = { "fin_pll", "sclk_bus0_pll_a" };
+PNAME(mout_top0_bus1_pll_user_p) = { "fin_pll", "sclk_bus1_pll_a" };
+PNAME(mout_top0_cc_pll_user_p) = { "fin_pll", "sclk_cc_pll_a" };
+PNAME(mout_top0_mfc_pll_user_p) = { "fin_pll", "sclk_mfc_pll_a" };
+PNAME(mout_top0_aud_pll_user_p) = { "fin_pll", "sclk_aud_pll" };
-PNAME(mout_top0_half_bus0_pll_p) = {"mout_top0_bus0_pll",
+PNAME(mout_top0_bus0_pll_half_p) = {"mout_top0_bus0_pll_user",
"ffac_top0_bus0_pll_div2"};
-PNAME(mout_top0_half_bus1_pll_p) = {"mout_top0_bus1_pll",
+PNAME(mout_top0_bus1_pll_half_p) = {"mout_top0_bus1_pll_user",
"ffac_top0_bus1_pll_div2"};
-PNAME(mout_top0_half_cc_pll_p) = {"mout_top0_cc_pll",
+PNAME(mout_top0_cc_pll_half_p) = {"mout_top0_cc_pll_user",
"ffac_top0_cc_pll_div2"};
-PNAME(mout_top0_half_mfc_pll_p) = {"mout_top0_mfc_pll",
+PNAME(mout_top0_mfc_pll_half_p) = {"mout_top0_mfc_pll_user",
"ffac_top0_mfc_pll_div2"};
-PNAME(mout_top0_group1) = {"mout_top0_half_bus0_pll",
- "mout_top0_half_bus1_pll", "mout_top0_half_cc_pll",
- "mout_top0_half_mfc_pll"};
+PNAME(mout_top0_group1) = {"mout_top0_bus0_pll_half",
+ "mout_top0_bus1_pll_half", "mout_top0_cc_pll_half",
+ "mout_top0_mfc_pll_half"};
PNAME(mout_top0_group3) = {"ioclk_audiocdclk0",
"ioclk_audiocdclk1", "ioclk_spdif_extclk",
- "mout_top0_aud_pll", "mout_top0_half_bus0_pll",
- "mout_top0_half_bus1_pll"};
-PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll",
- "mout_top0_half_bus0_pll", "mout_top0_half_bus1_pll"};
+ "mout_top0_aud_pll_user", "mout_top0_bus0_pll_half",
+ "mout_top0_bus1_pll_half"};
+PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll_user",
+ "mout_top0_bus0_pll_half", "mout_top0_bus1_pll_half"};
static unsigned long top0_clk_regs[] __initdata = {
MUX_SEL_TOP00,
@@ -244,19 +276,24 @@ static unsigned long top0_clk_regs[] __initdata = {
};
static struct samsung_mux_clock top0_mux_clks[] __initdata = {
- MUX(0, "mout_top0_aud_pll", mout_aud_pll_p, MUX_SEL_TOP00, 0, 1),
- MUX(0, "mout_top0_mfc_pll", mout_mfc_pll_p, MUX_SEL_TOP00, 4, 1),
- MUX(0, "mout_top0_cc_pll", mout_cc_pll_p, MUX_SEL_TOP00, 8, 1),
- MUX(0, "mout_top0_bus1_pll", mout_bus1_pll_p, MUX_SEL_TOP00, 12, 1),
- MUX(0, "mout_top0_bus0_pll", mout_bus0_pll_p, MUX_SEL_TOP00, 16, 1),
-
- MUX(0, "mout_top0_half_mfc_pll", mout_top0_half_mfc_pll_p,
+ MUX(0, "mout_top0_aud_pll_user", mout_top0_aud_pll_user_p,
+ MUX_SEL_TOP00, 0, 1),
+ MUX(0, "mout_top0_mfc_pll_user", mout_top0_mfc_pll_user_p,
+ MUX_SEL_TOP00, 4, 1),
+ MUX(0, "mout_top0_cc_pll_user", mout_top0_cc_pll_user_p,
+ MUX_SEL_TOP00, 8, 1),
+ MUX(0, "mout_top0_bus1_pll_user", mout_top0_bus1_pll_user_p,
+ MUX_SEL_TOP00, 12, 1),
+ MUX(0, "mout_top0_bus0_pll_user", mout_top0_bus0_pll_user_p,
+ MUX_SEL_TOP00, 16, 1),
+
+ MUX(0, "mout_top0_mfc_pll_half", mout_top0_mfc_pll_half_p,
MUX_SEL_TOP01, 4, 1),
- MUX(0, "mout_top0_half_cc_pll", mout_top0_half_cc_pll_p,
+ MUX(0, "mout_top0_cc_pll_half", mout_top0_cc_pll_half_p,
MUX_SEL_TOP01, 8, 1),
- MUX(0, "mout_top0_half_bus1_pll", mout_top0_half_bus1_pll_p,
+ MUX(0, "mout_top0_bus1_pll_half", mout_top0_bus1_pll_half_p,
MUX_SEL_TOP01, 12, 1),
- MUX(0, "mout_top0_half_bus0_pll", mout_top0_half_bus0_pll_p,
+ MUX(0, "mout_top0_bus0_pll_half", mout_top0_bus0_pll_half_p,
MUX_SEL_TOP01, 16, 1),
MUX(0, "mout_aclk_peric1_66", mout_top0_group1, MUX_SEL_TOP03, 12, 2),
@@ -302,6 +339,11 @@ static struct samsung_div_clock top0_div_clks[] __initdata = {
};
static struct samsung_gate_clock top0_gate_clks[] __initdata = {
+ GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66",
+ ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_ACLK_PERIC1_66, "aclk_peric1_66", "dout_aclk_peric1_66",
+ ENABLE_ACLK_TOP03, 12, CLK_SET_RATE_PARENT, 0),
+
GATE(CLK_SCLK_SPDIF, "sclk_spdif", "dout_sclk_spdif",
ENABLE_SCLK_TOP0_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_sclk_pcm1",
@@ -331,10 +373,12 @@ static struct samsung_gate_clock top0_gate_clks[] __initdata = {
};
static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
- FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll", 1, 2, 0),
- FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll", 1, 2, 0),
- FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll", 1, 2, 0),
- FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll", 1, 2, 0),
+ FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll_user",
+ 1, 2, 0),
+ FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll_user",
+ 1, 2, 0),
+ FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll_user", 1, 2, 0),
+ FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll_user", 1, 2, 0),
};
static struct samsung_cmu_info top0_cmu_info __initdata = {
@@ -365,31 +409,34 @@ CLK_OF_DECLARE(exynos7_clk_top0, "samsung,exynos7-clock-top0",
#define MUX_SEL_TOP13 0x020C
#define MUX_SEL_TOP1_FSYS0 0x0224
#define MUX_SEL_TOP1_FSYS1 0x0228
+#define MUX_SEL_TOP1_FSYS11 0x022C
#define DIV_TOP13 0x060C
#define DIV_TOP1_FSYS0 0x0624
#define DIV_TOP1_FSYS1 0x0628
+#define DIV_TOP1_FSYS11 0x062C
#define ENABLE_ACLK_TOP13 0x080C
#define ENABLE_SCLK_TOP1_FSYS0 0x0A24
#define ENABLE_SCLK_TOP1_FSYS1 0x0A28
+#define ENABLE_SCLK_TOP1_FSYS11 0x0A2C
/* List of parent clocks for Muxes in CMU_TOP1 */
-PNAME(mout_top1_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" };
-PNAME(mout_top1_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll_b" };
-PNAME(mout_top1_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll_b" };
-PNAME(mout_top1_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll_b" };
+PNAME(mout_top1_bus0_pll_user_p) = { "fin_pll", "sclk_bus0_pll_b" };
+PNAME(mout_top1_bus1_pll_user_p) = { "fin_pll", "sclk_bus1_pll_b" };
+PNAME(mout_top1_cc_pll_user_p) = { "fin_pll", "sclk_cc_pll_b" };
+PNAME(mout_top1_mfc_pll_user_p) = { "fin_pll", "sclk_mfc_pll_b" };
-PNAME(mout_top1_half_bus0_pll_p) = {"mout_top1_bus0_pll",
+PNAME(mout_top1_bus0_pll_half_p) = {"mout_top1_bus0_pll_user",
"ffac_top1_bus0_pll_div2"};
-PNAME(mout_top1_half_bus1_pll_p) = {"mout_top1_bus1_pll",
+PNAME(mout_top1_bus1_pll_half_p) = {"mout_top1_bus1_pll_user",
"ffac_top1_bus1_pll_div2"};
-PNAME(mout_top1_half_cc_pll_p) = {"mout_top1_cc_pll",
+PNAME(mout_top1_cc_pll_half_p) = {"mout_top1_cc_pll_user",
"ffac_top1_cc_pll_div2"};
-PNAME(mout_top1_half_mfc_pll_p) = {"mout_top1_mfc_pll",
+PNAME(mout_top1_mfc_pll_half_p) = {"mout_top1_mfc_pll_user",
"ffac_top1_mfc_pll_div2"};
-PNAME(mout_top1_group1) = {"mout_top1_half_bus0_pll",
- "mout_top1_half_bus1_pll", "mout_top1_half_cc_pll",
- "mout_top1_half_mfc_pll"};
+PNAME(mout_top1_group1) = {"mout_top1_bus0_pll_half",
+ "mout_top1_bus1_pll_half", "mout_top1_cc_pll_half",
+ "mout_top1_mfc_pll_half"};
static unsigned long top1_clk_regs[] __initdata = {
MUX_SEL_TOP10,
@@ -397,40 +444,54 @@ static unsigned long top1_clk_regs[] __initdata = {
MUX_SEL_TOP13,
MUX_SEL_TOP1_FSYS0,
MUX_SEL_TOP1_FSYS1,
+ MUX_SEL_TOP1_FSYS11,
DIV_TOP13,
DIV_TOP1_FSYS0,
DIV_TOP1_FSYS1,
+ DIV_TOP1_FSYS11,
ENABLE_ACLK_TOP13,
ENABLE_SCLK_TOP1_FSYS0,
ENABLE_SCLK_TOP1_FSYS1,
+ ENABLE_SCLK_TOP1_FSYS11,
};
static struct samsung_mux_clock top1_mux_clks[] __initdata = {
- MUX(0, "mout_top1_mfc_pll", mout_top1_mfc_pll_p, MUX_SEL_TOP10, 4, 1),
- MUX(0, "mout_top1_cc_pll", mout_top1_cc_pll_p, MUX_SEL_TOP10, 8, 1),
- MUX(0, "mout_top1_bus1_pll", mout_top1_bus1_pll_p,
+ MUX(0, "mout_top1_mfc_pll_user", mout_top1_mfc_pll_user_p,
+ MUX_SEL_TOP10, 4, 1),
+ MUX(0, "mout_top1_cc_pll_user", mout_top1_cc_pll_user_p,
+ MUX_SEL_TOP10, 8, 1),
+ MUX(0, "mout_top1_bus1_pll_user", mout_top1_bus1_pll_user_p,
MUX_SEL_TOP10, 12, 1),
- MUX(0, "mout_top1_bus0_pll", mout_top1_bus0_pll_p,
+ MUX(0, "mout_top1_bus0_pll_user", mout_top1_bus0_pll_user_p,
MUX_SEL_TOP10, 16, 1),
- MUX(0, "mout_top1_half_mfc_pll", mout_top1_half_mfc_pll_p,
+ MUX(0, "mout_top1_mfc_pll_half", mout_top1_mfc_pll_half_p,
MUX_SEL_TOP11, 4, 1),
- MUX(0, "mout_top1_half_cc_pll", mout_top1_half_cc_pll_p,
+ MUX(0, "mout_top1_cc_pll_half", mout_top1_cc_pll_half_p,
MUX_SEL_TOP11, 8, 1),
- MUX(0, "mout_top1_half_bus1_pll", mout_top1_half_bus1_pll_p,
+ MUX(0, "mout_top1_bus1_pll_half", mout_top1_bus1_pll_half_p,
MUX_SEL_TOP11, 12, 1),
- MUX(0, "mout_top1_half_bus0_pll", mout_top1_half_bus0_pll_p,
+ MUX(0, "mout_top1_bus0_pll_half", mout_top1_bus0_pll_half_p,
MUX_SEL_TOP11, 16, 1),
MUX(0, "mout_aclk_fsys1_200", mout_top1_group1, MUX_SEL_TOP13, 24, 2),
MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2),
- MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 24, 2),
+ MUX(0, "mout_sclk_phy_fsys0_26m", mout_top1_group1,
+ MUX_SEL_TOP1_FSYS0, 0, 2),
+ MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 16, 2),
MUX(0, "mout_sclk_usbdrd300", mout_top1_group1,
MUX_SEL_TOP1_FSYS0, 28, 2),
- MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 24, 2),
- MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 28, 2),
+ MUX(0, "mout_sclk_phy_fsys1", mout_top1_group1,
+ MUX_SEL_TOP1_FSYS1, 0, 2),
+ MUX(0, "mout_sclk_ufsunipro20", mout_top1_group1,
+ MUX_SEL_TOP1_FSYS1, 16, 2),
+
+ MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS11, 0, 2),
+ MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS11, 12, 2),
+ MUX(0, "mout_sclk_phy_fsys1_26m", mout_top1_group1,
+ MUX_SEL_TOP1_FSYS11, 24, 2),
};
static struct samsung_div_clock top1_div_clks[] __initdata = {
@@ -439,34 +500,61 @@ static struct samsung_div_clock top1_div_clks[] __initdata = {
DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200",
DIV_TOP13, 28, 4),
+ DIV(DOUT_SCLK_PHY_FSYS1, "dout_sclk_phy_fsys1",
+ "mout_sclk_phy_fsys1", DIV_TOP1_FSYS1, 0, 6),
+
+ DIV(DOUT_SCLK_UFSUNIPRO20, "dout_sclk_ufsunipro20",
+ "mout_sclk_ufsunipro20",
+ DIV_TOP1_FSYS1, 16, 6),
+
DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2",
- DIV_TOP1_FSYS0, 24, 4),
+ DIV_TOP1_FSYS0, 16, 10),
DIV(0, "dout_sclk_usbdrd300", "mout_sclk_usbdrd300",
DIV_TOP1_FSYS0, 28, 4),
DIV(DOUT_SCLK_MMC1, "dout_sclk_mmc1", "mout_sclk_mmc1",
- DIV_TOP1_FSYS1, 24, 4),
+ DIV_TOP1_FSYS11, 0, 10),
DIV(DOUT_SCLK_MMC0, "dout_sclk_mmc0", "mout_sclk_mmc0",
- DIV_TOP1_FSYS1, 28, 4),
+ DIV_TOP1_FSYS11, 12, 10),
+
+ DIV(DOUT_SCLK_PHY_FSYS1_26M, "dout_sclk_phy_fsys1_26m",
+ "mout_sclk_phy_fsys1_26m", DIV_TOP1_FSYS11, 24, 6),
};
static struct samsung_gate_clock top1_gate_clks[] __initdata = {
GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2",
- ENABLE_SCLK_TOP1_FSYS0, 24, CLK_SET_RATE_PARENT, 0),
+ ENABLE_SCLK_TOP1_FSYS0, 16, CLK_SET_RATE_PARENT, 0),
GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300",
ENABLE_SCLK_TOP1_FSYS0, 28, 0, 0),
+ GATE(CLK_SCLK_PHY_FSYS1, "sclk_phy_fsys1", "dout_sclk_phy_fsys1",
+ ENABLE_SCLK_TOP1_FSYS1, 0, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_UFSUNIPRO20, "sclk_ufsunipro20", "dout_sclk_ufsunipro20",
+ ENABLE_SCLK_TOP1_FSYS1, 16, CLK_SET_RATE_PARENT, 0),
+
GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1",
- ENABLE_SCLK_TOP1_FSYS1, 24, CLK_SET_RATE_PARENT, 0),
+ ENABLE_SCLK_TOP1_FSYS11, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0",
- ENABLE_SCLK_TOP1_FSYS1, 28, CLK_SET_RATE_PARENT, 0),
+ ENABLE_SCLK_TOP1_FSYS11, 12, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200",
+ ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200",
+ ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_PHY_FSYS1_26M, "sclk_phy_fsys1_26m",
+ "dout_sclk_phy_fsys1_26m", ENABLE_SCLK_TOP1_FSYS11,
+ 24, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
- FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll", 1, 2, 0),
- FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll", 1, 2, 0),
- FFACTOR(0, "ffac_top1_cc_pll_div2", "mout_top1_cc_pll", 1, 2, 0),
- FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll", 1, 2, 0),
+ FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll_user",
+ 1, 2, 0),
+ FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll_user",
+ 1, 2, 0),
+ FFACTOR(0, "ffac_top1_cc_pll_div2", "mout_top1_cc_pll_user", 1, 2, 0),
+ FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll_user", 1, 2, 0),
};
static struct samsung_cmu_info top1_cmu_info __initdata = {
@@ -501,7 +589,7 @@ CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1",
/*
* List of parent clocks for Muxes in CMU_CCORE
*/
-PNAME(mout_aclk_ccore_133_p) = { "fin_pll", "dout_aclk_ccore_133" };
+PNAME(mout_aclk_ccore_133_user_p) = { "fin_pll", "aclk_ccore_133" };
static unsigned long ccore_clk_regs[] __initdata = {
MUX_SEL_CCORE,
@@ -509,7 +597,7 @@ static unsigned long ccore_clk_regs[] __initdata = {
};
static struct samsung_mux_clock ccore_mux_clks[] __initdata = {
- MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_p,
+ MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_user_p,
MUX_SEL_CCORE, 1, 1),
};
@@ -542,8 +630,8 @@ CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore",
#define ENABLE_SCLK_PERIC0 0x0A00
/* List of parent clocks for Muxes in CMU_PERIC0 */
-PNAME(mout_aclk_peric0_66_p) = { "fin_pll", "dout_aclk_peric0_66" };
-PNAME(mout_sclk_uart0_p) = { "fin_pll", "sclk_uart0" };
+PNAME(mout_aclk_peric0_66_user_p) = { "fin_pll", "aclk_peric0_66" };
+PNAME(mout_sclk_uart0_user_p) = { "fin_pll", "sclk_uart0" };
static unsigned long peric0_clk_regs[] __initdata = {
MUX_SEL_PERIC0,
@@ -552,9 +640,9 @@ static unsigned long peric0_clk_regs[] __initdata = {
};
static struct samsung_mux_clock peric0_mux_clks[] __initdata = {
- MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_p,
+ MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_user_p,
MUX_SEL_PERIC0, 0, 1),
- MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_p,
+ MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_user_p,
MUX_SEL_PERIC0, 16, 1),
};
@@ -611,15 +699,15 @@ CLK_OF_DECLARE(exynos7_clk_peric0, "samsung,exynos7-clock-peric0",
exynos7_clk_peric0_init);
/* List of parent clocks for Muxes in CMU_PERIC1 */
-PNAME(mout_aclk_peric1_66_p) = { "fin_pll", "dout_aclk_peric1_66" };
-PNAME(mout_sclk_uart1_p) = { "fin_pll", "sclk_uart1" };
-PNAME(mout_sclk_uart2_p) = { "fin_pll", "sclk_uart2" };
-PNAME(mout_sclk_uart3_p) = { "fin_pll", "sclk_uart3" };
-PNAME(mout_sclk_spi0_p) = { "fin_pll", "sclk_spi0" };
-PNAME(mout_sclk_spi1_p) = { "fin_pll", "sclk_spi1" };
-PNAME(mout_sclk_spi2_p) = { "fin_pll", "sclk_spi2" };
-PNAME(mout_sclk_spi3_p) = { "fin_pll", "sclk_spi3" };
-PNAME(mout_sclk_spi4_p) = { "fin_pll", "sclk_spi4" };
+PNAME(mout_aclk_peric1_66_user_p) = { "fin_pll", "aclk_peric1_66" };
+PNAME(mout_sclk_uart1_user_p) = { "fin_pll", "sclk_uart1" };
+PNAME(mout_sclk_uart2_user_p) = { "fin_pll", "sclk_uart2" };
+PNAME(mout_sclk_uart3_user_p) = { "fin_pll", "sclk_uart3" };
+PNAME(mout_sclk_spi0_user_p) = { "fin_pll", "sclk_spi0" };
+PNAME(mout_sclk_spi1_user_p) = { "fin_pll", "sclk_spi1" };
+PNAME(mout_sclk_spi2_user_p) = { "fin_pll", "sclk_spi2" };
+PNAME(mout_sclk_spi3_user_p) = { "fin_pll", "sclk_spi3" };
+PNAME(mout_sclk_spi4_user_p) = { "fin_pll", "sclk_spi4" };
static unsigned long peric1_clk_regs[] __initdata = {
MUX_SEL_PERIC10,
@@ -630,24 +718,24 @@ static unsigned long peric1_clk_regs[] __initdata = {
};
static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
- MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_p,
+ MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_user_p,
MUX_SEL_PERIC10, 0, 1),
- MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_p,
+ MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_user_p,
MUX_SEL_PERIC11, 0, 1, CLK_SET_RATE_PARENT, 0),
- MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_p,
+ MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_user_p,
MUX_SEL_PERIC11, 4, 1, CLK_SET_RATE_PARENT, 0),
- MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_p,
+ MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_user_p,
MUX_SEL_PERIC11, 8, 1, CLK_SET_RATE_PARENT, 0),
- MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_p,
+ MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_user_p,
MUX_SEL_PERIC11, 12, 1, CLK_SET_RATE_PARENT, 0),
- MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_p,
+ MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_user_p,
MUX_SEL_PERIC11, 16, 1, CLK_SET_RATE_PARENT, 0),
- MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_p,
+ MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_user_p,
MUX_SEL_PERIC11, 20, 1),
- MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_p,
+ MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_user_p,
MUX_SEL_PERIC11, 24, 1),
- MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_p,
+ MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_user_p,
MUX_SEL_PERIC11, 28, 1),
};
@@ -735,7 +823,7 @@ CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1",
#define ENABLE_SCLK_PERIS_SECURE_CHIPID 0x0A10
/* List of parent clocks for Muxes in CMU_PERIS */
-PNAME(mout_aclk_peris_66_p) = { "fin_pll", "dout_aclk_peris_66" };
+PNAME(mout_aclk_peris_66_user_p) = { "fin_pll", "aclk_peris_66" };
static unsigned long peris_clk_regs[] __initdata = {
MUX_SEL_PERIS,
@@ -747,7 +835,7 @@ static unsigned long peris_clk_regs[] __initdata = {
static struct samsung_mux_clock peris_mux_clks[] __initdata = {
MUX(0, "mout_aclk_peris_66_user",
- mout_aclk_peris_66_p, MUX_SEL_PERIS, 0, 1),
+ mout_aclk_peris_66_user_p, MUX_SEL_PERIS, 0, 1),
};
static struct samsung_gate_clock peris_gate_clks[] __initdata = {
@@ -795,17 +883,17 @@ CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris",
/*
* List of parent clocks for Muxes in CMU_FSYS0
*/
-PNAME(mout_aclk_fsys0_200_p) = { "fin_pll", "dout_aclk_fsys0_200" };
-PNAME(mout_sclk_mmc2_p) = { "fin_pll", "sclk_mmc2" };
+PNAME(mout_aclk_fsys0_200_user_p) = { "fin_pll", "aclk_fsys0_200" };
+PNAME(mout_sclk_mmc2_user_p) = { "fin_pll", "sclk_mmc2" };
-PNAME(mout_sclk_usbdrd300_p) = { "fin_pll", "sclk_usbdrd300" };
-PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_p) = { "fin_pll",
+PNAME(mout_sclk_usbdrd300_user_p) = { "fin_pll", "sclk_usbdrd300" };
+PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_user_p) = { "fin_pll",
"phyclk_usbdrd300_udrd30_phyclock" };
-PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_p) = { "fin_pll",
+PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p) = { "fin_pll",
"phyclk_usbdrd300_udrd30_pipe_pclk" };
/* fixed rate clocks used in the FSYS0 block */
-struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
+static struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL,
CLK_IS_ROOT, 60000000),
FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL,
@@ -824,29 +912,30 @@ static unsigned long fsys0_clk_regs[] __initdata = {
};
static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
- MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_p,
+ MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_user_p,
MUX_SEL_FSYS00, 24, 1),
- MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_p, MUX_SEL_FSYS01, 24, 1),
- MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_p,
+ MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_user_p,
+ MUX_SEL_FSYS01, 24, 1),
+ MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_user_p,
MUX_SEL_FSYS01, 28, 1),
MUX(0, "mout_phyclk_usbdrd300_udrd30_pipe_pclk_user",
- mout_phyclk_usbdrd300_udrd30_pipe_pclk_p,
+ mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p,
MUX_SEL_FSYS02, 24, 1),
MUX(0, "mout_phyclk_usbdrd300_udrd30_phyclk_user",
- mout_phyclk_usbdrd300_udrd30_phyclk_p,
+ mout_phyclk_usbdrd300_udrd30_phyclk_user_p,
MUX_SEL_FSYS02, 28, 1),
};
static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
- GATE(ACLK_AXIUS_USBDRD30X_FSYS0X, "aclk_axius_usbdrd30x_fsys0x",
- "mout_aclk_fsys0_200_user",
- ENABLE_ACLK_FSYS00, 19, 0, 0),
GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user",
ENABLE_ACLK_FSYS00, 3, 0, 0),
GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user",
ENABLE_ACLK_FSYS00, 4, 0, 0),
+ GATE(ACLK_AXIUS_USBDRD30X_FSYS0X, "aclk_axius_usbdrd30x_fsys0x",
+ "mout_aclk_fsys0_200_user",
+ ENABLE_ACLK_FSYS00, 19, 0, 0),
GATE(ACLK_USBDRD300, "aclk_usbdrd300", "mout_aclk_fsys0_200_user",
ENABLE_ACLK_FSYS01, 29, 0, 0),
@@ -874,11 +963,13 @@ static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
};
static struct samsung_cmu_info fsys0_cmu_info __initdata = {
+ .fixed_clks = fixed_rate_clks_fsys0,
+ .nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys0),
.mux_clks = fsys0_mux_clks,
.nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks),
.gate_clks = fsys0_gate_clks,
.nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks),
- .nr_clk_ids = TOP1_NR_CLK,
+ .nr_clk_ids = FSYS0_NR_CLK,
.clk_regs = fsys0_clk_regs,
.nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs),
};
@@ -894,42 +985,122 @@ CLK_OF_DECLARE(exynos7_clk_fsys0, "samsung,exynos7-clock-fsys0",
/* Register Offset definitions for CMU_FSYS1 (0x156E0000) */
#define MUX_SEL_FSYS10 0x0200
#define MUX_SEL_FSYS11 0x0204
+#define MUX_SEL_FSYS12 0x0208
+#define DIV_FSYS1 0x0600
#define ENABLE_ACLK_FSYS1 0x0800
+#define ENABLE_PCLK_FSYS1 0x0900
+#define ENABLE_SCLK_FSYS11 0x0A04
+#define ENABLE_SCLK_FSYS12 0x0A08
+#define ENABLE_SCLK_FSYS13 0x0A0C
/*
* List of parent clocks for Muxes in CMU_FSYS1
*/
-PNAME(mout_aclk_fsys1_200_p) = { "fin_pll", "dout_aclk_fsys1_200" };
-PNAME(mout_sclk_mmc0_p) = { "fin_pll", "sclk_mmc0" };
-PNAME(mout_sclk_mmc1_p) = { "fin_pll", "sclk_mmc1" };
+PNAME(mout_aclk_fsys1_200_user_p) = { "fin_pll", "aclk_fsys1_200" };
+PNAME(mout_fsys1_group_p) = { "fin_pll", "fin_pll_26m",
+ "sclk_phy_fsys1_26m" };
+PNAME(mout_sclk_mmc0_user_p) = { "fin_pll", "sclk_mmc0" };
+PNAME(mout_sclk_mmc1_user_p) = { "fin_pll", "sclk_mmc1" };
+PNAME(mout_sclk_ufsunipro20_user_p) = { "fin_pll", "sclk_ufsunipro20" };
+PNAME(mout_phyclk_ufs20_tx0_user_p) = { "fin_pll", "phyclk_ufs20_tx0_symbol" };
+PNAME(mout_phyclk_ufs20_rx0_user_p) = { "fin_pll", "phyclk_ufs20_rx0_symbol" };
+PNAME(mout_phyclk_ufs20_rx1_user_p) = { "fin_pll", "phyclk_ufs20_rx1_symbol" };
+
+/* fixed rate clocks used in the FSYS1 block */
+static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = {
+ FRATE(PHYCLK_UFS20_TX0_SYMBOL, "phyclk_ufs20_tx0_symbol", NULL,
+ CLK_IS_ROOT, 300000000),
+ FRATE(PHYCLK_UFS20_RX0_SYMBOL, "phyclk_ufs20_rx0_symbol", NULL,
+ CLK_IS_ROOT, 300000000),
+ FRATE(PHYCLK_UFS20_RX1_SYMBOL, "phyclk_ufs20_rx1_symbol", NULL,
+ CLK_IS_ROOT, 300000000),
+};
static unsigned long fsys1_clk_regs[] __initdata = {
MUX_SEL_FSYS10,
MUX_SEL_FSYS11,
+ MUX_SEL_FSYS12,
+ DIV_FSYS1,
ENABLE_ACLK_FSYS1,
+ ENABLE_PCLK_FSYS1,
+ ENABLE_SCLK_FSYS11,
+ ENABLE_SCLK_FSYS12,
+ ENABLE_SCLK_FSYS13,
};
static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
- MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_p,
+ MUX(MOUT_FSYS1_PHYCLK_SEL1, "mout_fsys1_phyclk_sel1",
+ mout_fsys1_group_p, MUX_SEL_FSYS10, 16, 2),
+ MUX(0, "mout_fsys1_phyclk_sel0", mout_fsys1_group_p,
+ MUX_SEL_FSYS10, 20, 2),
+ MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_user_p,
MUX_SEL_FSYS10, 28, 1),
- MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_p, MUX_SEL_FSYS11, 24, 1),
- MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_p, MUX_SEL_FSYS11, 28, 1),
+ MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_user_p,
+ MUX_SEL_FSYS11, 24, 1),
+ MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_user_p,
+ MUX_SEL_FSYS11, 28, 1),
+ MUX(0, "mout_sclk_ufsunipro20_user", mout_sclk_ufsunipro20_user_p,
+ MUX_SEL_FSYS11, 20, 1),
+
+ MUX(0, "mout_phyclk_ufs20_rx1_symbol_user",
+ mout_phyclk_ufs20_rx1_user_p, MUX_SEL_FSYS12, 16, 1),
+ MUX(0, "mout_phyclk_ufs20_rx0_symbol_user",
+ mout_phyclk_ufs20_rx0_user_p, MUX_SEL_FSYS12, 24, 1),
+ MUX(0, "mout_phyclk_ufs20_tx0_symbol_user",
+ mout_phyclk_ufs20_tx0_user_p, MUX_SEL_FSYS12, 28, 1),
+};
+
+static struct samsung_div_clock fsys1_div_clks[] __initdata = {
+ DIV(DOUT_PCLK_FSYS1, "dout_pclk_fsys1", "mout_aclk_fsys1_200_user",
+ DIV_FSYS1, 0, 2),
};
static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
+ GATE(SCLK_UFSUNIPRO20_USER, "sclk_ufsunipro20_user",
+ "mout_sclk_ufsunipro20_user",
+ ENABLE_SCLK_FSYS11, 20, 0, 0),
+
GATE(ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys1_200_user",
ENABLE_ACLK_FSYS1, 29, 0, 0),
GATE(ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys1_200_user",
ENABLE_ACLK_FSYS1, 30, 0, 0),
+
+ GATE(ACLK_UFS20_LINK, "aclk_ufs20_link", "dout_pclk_fsys1",
+ ENABLE_ACLK_FSYS1, 31, 0, 0),
+ GATE(PCLK_GPIO_FSYS1, "pclk_gpio_fsys1", "mout_aclk_fsys1_200_user",
+ ENABLE_PCLK_FSYS1, 30, 0, 0),
+
+ GATE(PHYCLK_UFS20_RX1_SYMBOL_USER, "phyclk_ufs20_rx1_symbol_user",
+ "mout_phyclk_ufs20_rx1_symbol_user",
+ ENABLE_SCLK_FSYS12, 16, 0, 0),
+ GATE(PHYCLK_UFS20_RX0_SYMBOL_USER, "phyclk_ufs20_rx0_symbol_user",
+ "mout_phyclk_ufs20_rx0_symbol_user",
+ ENABLE_SCLK_FSYS12, 24, 0, 0),
+ GATE(PHYCLK_UFS20_TX0_SYMBOL_USER, "phyclk_ufs20_tx0_symbol_user",
+ "mout_phyclk_ufs20_tx0_symbol_user",
+ ENABLE_SCLK_FSYS12, 28, 0, 0),
+
+ GATE(OSCCLK_PHY_CLKOUT_EMBEDDED_COMBO_PHY,
+ "oscclk_phy_clkout_embedded_combo_phy",
+ "fin_pll",
+ ENABLE_SCLK_FSYS12, 4, CLK_IGNORE_UNUSED, 0),
+
+ GATE(SCLK_COMBO_PHY_EMBEDDED_26M, "sclk_combo_phy_embedded_26m",
+ "mout_fsys1_phyclk_sel1",
+ ENABLE_SCLK_FSYS13, 24, CLK_IGNORE_UNUSED, 0),
};
static struct samsung_cmu_info fsys1_cmu_info __initdata = {
+ .fixed_clks = fixed_rate_clks_fsys1,
+ .nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys1),
.mux_clks = fsys1_mux_clks,
.nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks),
+ .div_clks = fsys1_div_clks,
+ .nr_div_clks = ARRAY_SIZE(fsys1_div_clks),
.gate_clks = fsys1_gate_clks,
.nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks),
- .nr_clk_ids = TOP1_NR_CLK,
+ .nr_clk_ids = FSYS1_NR_CLK,
.clk_regs = fsys1_clk_regs,
.nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs),
};
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c
index b1df7b2f1e97..3b09716ebda2 100644
--- a/drivers/clk/shmobile/clk-mstp.c
+++ b/drivers/clk/shmobile/clk-mstp.c
@@ -214,7 +214,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
break;
if (clkidx >= MSTP_MAX_CLOCKS) {
- pr_err("%s: invalid clock %s %s index %u)\n",
+ pr_err("%s: invalid clock %s %s index %u\n",
__func__, np->name, name, clkidx);
continue;
}
@@ -259,6 +259,10 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
"renesas,cpg-mstp-clocks"))
goto found;
+ /* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */
+ if (!strcmp(clkspec.np->name, "zb_clk"))
+ goto found;
+
of_node_put(clkspec.np);
i++;
}
diff --git a/drivers/clk/shmobile/clk-r8a7778.c b/drivers/clk/shmobile/clk-r8a7778.c
index 87c1d2f2fb57..b1741551fff2 100644
--- a/drivers/clk/shmobile/clk-r8a7778.c
+++ b/drivers/clk/shmobile/clk-r8a7778.c
@@ -20,10 +20,10 @@ struct r8a7778_cpg {
};
/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
-struct {
+static const struct {
unsigned long plla_mult;
unsigned long pllb_mult;
-} r8a7778_rates[] __initdata = {
+} r8a7778_rates[] __initconst = {
[0] = { 21, 21 },
[1] = { 24, 24 },
[2] = { 28, 28 },
@@ -34,10 +34,10 @@ struct {
};
/* Clock dividers per bits 1 and 2 of MODEMR */
-struct {
+static const struct {
const char *name;
unsigned int div[4];
-} r8a7778_divs[6] __initdata = {
+} r8a7778_divs[6] __initconst = {
{ "b", { 12, 12, 16, 18 } },
{ "out", { 12, 12, 16, 18 } },
{ "p", { 16, 12, 16, 12 } },
diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c
index a98e21fe773a..957aae63e7cc 100644
--- a/drivers/clk/sirf/clk-atlas7.c
+++ b/drivers/clk/sirf/clk-atlas7.c
@@ -205,18 +205,11 @@
#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET 0x0530
#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET 0x0548
-
-static void __iomem *sirfsoc_clk_vbase;
-static struct clk_onecell_data clk_data;
-
-static const struct clk_div_table pll_div_table[] = {
- { .val = 0, .div = 1 },
- { .val = 1, .div = 2 },
- { .val = 2, .div = 4 },
- { .val = 3, .div = 8 },
- { .val = 4, .div = 16 },
- { .val = 5, .div = 32 },
-};
+#define SIRFSOC_NOC_CLK_IDLEREQ_SET 0x02D0
+#define SIRFSOC_NOC_CLK_IDLEREQ_CLR 0x02D4
+#define SIRFSOC_NOC_CLK_SLVRDY_SET 0x02E8
+#define SIRFSOC_NOC_CLK_SLVRDY_CLR 0x02EC
+#define SIRFSOC_NOC_CLK_IDLE_STATUS 0x02F4
struct clk_pll {
struct clk_hw hw;
@@ -231,10 +224,18 @@ struct clk_dto {
};
#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw)
+enum clk_unit_type {
+ CLK_UNIT_NOC_OTHER,
+ CLK_UNIT_NOC_CLOCK,
+ CLK_UNIT_NOC_SOCKET,
+};
+
struct clk_unit {
struct clk_hw hw;
u16 regofs;
u16 bit;
+ u32 type;
+ u8 idle_bit;
spinlock_t *lock;
};
#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw)
@@ -272,6 +273,8 @@ struct atlas7_unit_init_data {
unsigned long flags;
u32 regofs;
u8 bit;
+ u32 type;
+ u8 idle_bit;
spinlock_t *lock;
};
@@ -284,6 +287,18 @@ struct atlas7_reset_desc {
spinlock_t *lock;
};
+static void __iomem *sirfsoc_clk_vbase;
+static struct clk_onecell_data clk_data;
+
+static const struct clk_div_table pll_div_table[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 8 },
+ { .val = 4, .div = 16 },
+ { .val = 5, .div = 32 },
+};
+
static DEFINE_SPINLOCK(cpupll_ctrl1_lock);
static DEFINE_SPINLOCK(mempll_ctrl1_lock);
static DEFINE_SPINLOCK(sys0pll_ctrl1_lock);
@@ -1040,148 +1055,148 @@ static struct atlas7_mux_init_data mux_list[] __initdata = {
/* new unit should add start from the tail of list */
static struct atlas7_unit_init_data unit_list[] __initdata = {
/* unit_name, parent_name, flags, regofs, bit, lock */
- { 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, &root0_gate_lock },
- { 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, &root0_gate_lock },
- { 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, &root0_gate_lock },
- { 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, &root0_gate_lock },
- { 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, &root0_gate_lock },
- { 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, &root0_gate_lock },
- { 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, &root0_gate_lock },
- { 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, &root0_gate_lock },
- { 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, &root0_gate_lock },
- { 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, &root0_gate_lock },
- { 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, &root0_gate_lock },
- { 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, &root0_gate_lock },
- { 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, &root0_gate_lock },
- { 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, &root0_gate_lock },
- { 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, &root0_gate_lock },
- { 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, &root0_gate_lock },
- { 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, &root0_gate_lock },
- { 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, &root0_gate_lock },
- { 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, &root0_gate_lock },
- { 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, &root0_gate_lock },
- { 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, &root0_gate_lock },
- { 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, &root0_gate_lock },
- { 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, &root0_gate_lock },
- { 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, &root1_gate_lock },
- { 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, &root1_gate_lock },
- { 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, &root1_gate_lock },
- { 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, &root1_gate_lock },
- { 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, &root1_gate_lock },
- { 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, &root1_gate_lock },
- { 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, &root1_gate_lock },
- { 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, &root1_gate_lock },
- { 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, &root1_gate_lock },
- { 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, &root1_gate_lock },
- { 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, &root1_gate_lock },
- { 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, &root1_gate_lock },
- { 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, &root1_gate_lock },
- { 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, &root1_gate_lock },
- { 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, &root1_gate_lock },
- { 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, &root1_gate_lock },
- { 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, &root1_gate_lock },
- { 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, &root1_gate_lock },
- { 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, &root1_gate_lock },
- { 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, &root1_gate_lock },
- { 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, &root1_gate_lock },
- { 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, &root1_gate_lock },
- { 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, &root1_gate_lock },
- { 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, &leaf1_gate_lock },
- { 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, &leaf1_gate_lock },
- { 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, &leaf1_gate_lock },
- { 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, &leaf1_gate_lock },
- { 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, &leaf1_gate_lock },
- { 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, &leaf1_gate_lock },
- { 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, &leaf1_gate_lock },
- { 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, &leaf1_gate_lock },
- { 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, &leaf1_gate_lock },
- { 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, &leaf1_gate_lock },
- { 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, &leaf1_gate_lock },
- { 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, &leaf1_gate_lock },
- { 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, &leaf1_gate_lock },
- { 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, &leaf1_gate_lock },
- { 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, &leaf1_gate_lock },
- { 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, &leaf1_gate_lock },
- { 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, &leaf1_gate_lock },
- { 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, &leaf1_gate_lock },
- { 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, &leaf1_gate_lock },
- { 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, &leaf1_gate_lock },
- { 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, &leaf2_gate_lock },
- { 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, &leaf2_gate_lock },
- { 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, &leaf2_gate_lock },
- { 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, &leaf2_gate_lock },
- { 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, &leaf2_gate_lock },
- { 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, &leaf2_gate_lock },
- { 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, &leaf2_gate_lock },
- { 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, &leaf2_gate_lock },
- { 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, &leaf2_gate_lock },
- { 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, &leaf2_gate_lock },
- { 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, &leaf2_gate_lock },
- { 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, &leaf2_gate_lock },
- { 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, &leaf2_gate_lock },
- { 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, &leaf2_gate_lock },
- { 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, &leaf2_gate_lock },
- { 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, &leaf2_gate_lock },
- { 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, &leaf2_gate_lock },
- { 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, &leaf2_gate_lock },
- { 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, &leaf2_gate_lock },
- { 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, &leaf2_gate_lock },
- { 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, &leaf3_gate_lock },
- { 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, &leaf3_gate_lock },
- { 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, &leaf3_gate_lock },
- { 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, &leaf3_gate_lock },
- { 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, &leaf3_gate_lock },
- { 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, &leaf3_gate_lock },
- { 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, &leaf3_gate_lock },
- { 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, &leaf3_gate_lock },
- { 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, &leaf3_gate_lock },
- { 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, &leaf3_gate_lock },
- { 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, &leaf3_gate_lock },
- { 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, &leaf3_gate_lock },
- { 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, &leaf3_gate_lock },
- { 99, "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, &leaf3_gate_lock },
- { 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, &leaf3_gate_lock },
- { 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, &leaf3_gate_lock },
- { 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, &leaf4_gate_lock },
- { 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, &leaf4_gate_lock },
- { 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, &leaf4_gate_lock },
- { 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, &leaf4_gate_lock },
- { 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, &leaf4_gate_lock },
- { 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, &leaf4_gate_lock },
- { 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, &leaf4_gate_lock },
- { 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, &leaf4_gate_lock },
- { 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, &leaf4_gate_lock },
- { 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, &leaf4_gate_lock },
- { 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, &leaf4_gate_lock },
- { 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, &leaf4_gate_lock },
- { 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, &leaf4_gate_lock },
- { 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, &leaf4_gate_lock },
- { 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, &leaf4_gate_lock },
- { 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, &leaf4_gate_lock },
- { 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, &leaf5_gate_lock },
- { 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, &leaf5_gate_lock },
- { 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, &leaf5_gate_lock },
- { 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, &leaf5_gate_lock },
- { 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
- { 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
- { 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
- { 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
- { 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
- { 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
- { 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
- { 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, &leaf8_gate_lock },
- { 130, "dmac4_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, &leaf8_gate_lock },
- { 131, "uart6_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, &leaf8_gate_lock },
- { 132, "usp3_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, &leaf8_gate_lock },
- { 133, "a7ca_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, &leaf8_gate_lock },
- { 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, &leaf8_gate_lock },
- { 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
- { 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
- { 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
- { 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, &leaf0_gate_lock },
- { 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, &leaf0_gate_lock },
- { 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, &leaf0_gate_lock },
- { 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, &leaf0_gate_lock },
+ { 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, 0, 0, &root0_gate_lock },
+ { 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, 0, 0, &root0_gate_lock },
+ { 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, 0, 0, &root0_gate_lock },
+ { 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, 0, 0, &root0_gate_lock },
+ { 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, 0, 0, &root0_gate_lock },
+ { 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, 0, 0, &root0_gate_lock },
+ { 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, 0, 0, &root0_gate_lock },
+ { 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, 0, 0, &root0_gate_lock },
+ { 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, 0, 0, &root0_gate_lock },
+ { 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, 0, 0, &root0_gate_lock },
+ { 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, 0, 0, &root0_gate_lock },
+ { 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, 0, 0, &root0_gate_lock },
+ { 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, 0, 0, &root0_gate_lock },
+ { 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, 0, 0, &root0_gate_lock },
+ { 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, 0, 0, &root0_gate_lock },
+ { 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, 0, 0, &root0_gate_lock },
+ { 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, 0, 0, &root0_gate_lock },
+ { 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, 0, 0, &root0_gate_lock },
+ { 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, 0, 0, &root0_gate_lock },
+ { 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, 0, 0, &root0_gate_lock },
+ { 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, 0, 0, &root0_gate_lock },
+ { 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, 0, 0, &root0_gate_lock },
+ { 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, 0, 0, &root0_gate_lock },
+ { 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, 0, 0, &root1_gate_lock },
+ { 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, 0, 0, &root1_gate_lock },
+ { 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, 0, 0, &root1_gate_lock },
+ { 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, 0, 0, &root1_gate_lock },
+ { 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, 0, 0, &root1_gate_lock },
+ { 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, 0, 0, &root1_gate_lock },
+ { 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, 0, 0, &root1_gate_lock },
+ { 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, 0, 0, &root1_gate_lock },
+ { 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, 0, 0, &root1_gate_lock },
+ { 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, 0, 0, &root1_gate_lock },
+ { 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, 0, 0, &root1_gate_lock },
+ { 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, 0, 0, &root1_gate_lock },
+ { 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, 0, 0, &root1_gate_lock },
+ { 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, 0, 0, &root1_gate_lock },
+ { 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, 0, 0, &root1_gate_lock },
+ { 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, 0, 0, &root1_gate_lock },
+ { 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, 0, 0, &root1_gate_lock },
+ { 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, 0, 0, &root1_gate_lock },
+ { 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, 0, 0, &root1_gate_lock },
+ { 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, 0, 0, &root1_gate_lock },
+ { 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, 0, 0, &root1_gate_lock },
+ { 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, 0, 0, &root1_gate_lock },
+ { 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, 0, 0, &root1_gate_lock },
+ { 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, CLK_UNIT_NOC_CLOCK, 4, &leaf1_gate_lock },
+ { 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, 0, 0, &leaf1_gate_lock },
+ { 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, 0, 0, &leaf1_gate_lock },
+ { 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, 0, 0, &leaf1_gate_lock },
+ { 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, 0, 0, &leaf1_gate_lock },
+ { 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, 0, 0, &leaf1_gate_lock },
+ { 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, 0, 0, &leaf1_gate_lock },
+ { 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, CLK_UNIT_NOC_SOCKET, 7, &leaf1_gate_lock },
+ { 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, CLK_UNIT_NOC_SOCKET, 8, &leaf1_gate_lock },
+ { 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, CLK_UNIT_NOC_CLOCK, 2, &leaf1_gate_lock },
+ { 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, 0, 0, &leaf1_gate_lock },
+ { 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, CLK_UNIT_NOC_SOCKET, 4, &leaf1_gate_lock },
+ { 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, CLK_UNIT_NOC_SOCKET, 5, &leaf1_gate_lock },
+ { 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, CLK_UNIT_NOC_SOCKET, 6, &leaf1_gate_lock },
+ { 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, CLK_UNIT_NOC_SOCKET, 1, &leaf1_gate_lock },
+ { 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, CLK_UNIT_NOC_SOCKET, 2, &leaf1_gate_lock },
+ { 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, CLK_UNIT_NOC_SOCKET, 0, &leaf1_gate_lock },
+ { 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, CLK_UNIT_NOC_CLOCK, 2, &leaf1_gate_lock },
+ { 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, 0, 0, &leaf1_gate_lock },
+ { 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, 0, 0, &leaf1_gate_lock },
+ { 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, CLK_UNIT_NOC_CLOCK, 20, &leaf2_gate_lock },
+ { 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, 0, 0, &leaf2_gate_lock },
+ { 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, 0, 0, &leaf2_gate_lock },
+ { 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, 0, 0, &leaf2_gate_lock },
+ { 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, 0, 0, &leaf2_gate_lock },
+ { 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, 0, 0, &leaf2_gate_lock },
+ { 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, 0, 0, &leaf2_gate_lock },
+ { 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, 0, 0, &leaf2_gate_lock },
+ { 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, CLK_UNIT_NOC_CLOCK, 21, &leaf2_gate_lock },
+ { 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, 0, 0, &leaf2_gate_lock },
+ { 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, 0, 0, &leaf2_gate_lock },
+ { 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, 0, 0, &leaf2_gate_lock },
+ { 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, CLK_UNIT_NOC_CLOCK, 22, &leaf2_gate_lock },
+ { 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, CLK_UNIT_NOC_CLOCK, 18, &leaf2_gate_lock },
+ { 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, CLK_UNIT_NOC_CLOCK, 23, &leaf2_gate_lock },
+ { 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, CLK_UNIT_NOC_CLOCK, 19, &leaf2_gate_lock },
+ { 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, CLK_UNIT_NOC_CLOCK, 17, &leaf2_gate_lock },
+ { 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, 0, 0, &leaf2_gate_lock },
+ { 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, 0, 0, &leaf2_gate_lock },
+ { 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, 0, 0, &leaf2_gate_lock },
+ { 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, 0, 0, &leaf3_gate_lock },
+ { 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, CLK_UNIT_NOC_CLOCK, 10, &leaf3_gate_lock },
+ { 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, CLK_UNIT_NOC_SOCKET, 14, &leaf3_gate_lock },
+ { 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, CLK_UNIT_NOC_SOCKET, 11, &leaf3_gate_lock },
+ { 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, CLK_UNIT_NOC_SOCKET, 13, &leaf3_gate_lock },
+ { 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, CLK_UNIT_NOC_SOCKET, 15, &leaf3_gate_lock },
+ { 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, CLK_UNIT_NOC_SOCKET, 16, &leaf3_gate_lock },
+ { 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, CLK_UNIT_NOC_SOCKET, 17, &leaf3_gate_lock },
+ { 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, CLK_UNIT_NOC_SOCKET, 18, &leaf3_gate_lock },
+ { 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, CLK_UNIT_NOC_SOCKET, 12, &leaf3_gate_lock },
+ { 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, 0, 0, &leaf3_gate_lock },
+ { 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, CLK_UNIT_NOC_CLOCK, 7, &leaf3_gate_lock },
+ { 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, CLK_UNIT_NOC_CLOCK, 9, &leaf3_gate_lock },
+ { 99, "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, CLK_UNIT_NOC_CLOCK, 8, &leaf3_gate_lock },
+ { 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, 0, 0, &leaf3_gate_lock },
+ { 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, 0, 0, &leaf3_gate_lock },
+ { 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, CLK_UNIT_NOC_CLOCK, 3, &leaf4_gate_lock },
+ { 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, CLK_UNIT_NOC_CLOCK, 1, &leaf4_gate_lock },
+ { 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, CLK_UNIT_NOC_CLOCK, 12, &leaf4_gate_lock },
+ { 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, CLK_UNIT_NOC_SOCKET, 21, &leaf4_gate_lock },
+ { 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, CLK_UNIT_NOC_SOCKET, 20, &leaf4_gate_lock },
+ { 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, CLK_UNIT_NOC_SOCKET, 19, &leaf4_gate_lock },
+ { 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, 0, 0, &leaf4_gate_lock },
+ { 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, 0, 0, &leaf4_gate_lock },
+ { 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, CLK_UNIT_NOC_CLOCK, 13, &leaf4_gate_lock },
+ { 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, 0, 0, &leaf4_gate_lock },
+ { 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, CLK_UNIT_NOC_CLOCK, 14, &leaf4_gate_lock },
+ { 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, CLK_UNIT_NOC_CLOCK, 15, &leaf4_gate_lock },
+ { 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, CLK_UNIT_NOC_CLOCK, 16, &leaf4_gate_lock },
+ { 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, 0, 0, &leaf4_gate_lock },
+ { 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, 0, 0, &leaf4_gate_lock },
+ { 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, 0, 0, &leaf4_gate_lock },
+ { 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, 0, 0, &leaf5_gate_lock },
+ { 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, 0, 0, &leaf5_gate_lock },
+ { 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, 0, 0, &leaf5_gate_lock },
+ { 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, 0, 0, &leaf5_gate_lock },
+ { 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, CLK_UNIT_NOC_SOCKET, 9, &leaf6_gate_lock },
+ { 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, CLK_UNIT_NOC_SOCKET, 10, &leaf6_gate_lock },
+ { 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, 0, 0, &leaf6_gate_lock },
+ { 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, 0, 0, &leaf6_gate_lock },
+ { 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, CLK_UNIT_NOC_CLOCK, 0, &leaf7_gate_lock },
+ { 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, CLK_UNIT_NOC_CLOCK, 11, &leaf7_gate_lock },
+ { 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, 0, 0, &leaf7_gate_lock },
+ { 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, 0, 0, &leaf8_gate_lock },
+ { 130, "dmac4_io", "a7ca_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, 0, 0, &leaf8_gate_lock },
+ { 131, "uart6_io", "dmac4_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, 0, 0, &leaf8_gate_lock },
+ { 132, "usp3_io", "dmac4_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, 0, 0, &leaf8_gate_lock },
+ { 133, "a7ca_io", "noc_btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, 0, 0, &leaf8_gate_lock },
+ { 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, 0, 0, &leaf8_gate_lock },
+ { 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, 0, 0, &leaf8_gate_lock },
+ { 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, 0, 0, &root1_gate_lock },
+ { 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, 0, 0, &leaf8_gate_lock },
+ { 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, 0, 0, &leaf0_gate_lock },
+ { 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, 0, 0, &leaf0_gate_lock },
+ { 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, 0, 0, &leaf0_gate_lock },
+ { 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, 0, 0, &leaf0_gate_lock },
};
static struct clk *atlas7_clks[ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list)];
@@ -1206,20 +1221,44 @@ static int unit_clk_enable(struct clk_hw *hw)
spin_lock_irqsave(clk->lock, flags);
clkc_writel(BIT(clk->bit), reg);
+ if (clk->type == CLK_UNIT_NOC_CLOCK)
+ clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_CLR);
+ else if (clk->type == CLK_UNIT_NOC_SOCKET)
+ clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_SLVRDY_SET);
+
spin_unlock_irqrestore(clk->lock, flags);
return 0;
}
static void unit_clk_disable(struct clk_hw *hw)
{
- u32 reg;
+ u32 reg;
+ u32 i = 0;
struct clk_unit *clk = to_unitclk(hw);
unsigned long flags;
reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
-
spin_lock_irqsave(clk->lock, flags);
+ if (clk->type == CLK_UNIT_NOC_CLOCK) {
+ clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_SET);
+ while (!(clkc_readl(SIRFSOC_NOC_CLK_IDLE_STATUS) &
+ BIT(clk->idle_bit)) && (i++ < 100)) {
+ cpu_relax();
+ udelay(10);
+ }
+
+ if (i == 100) {
+ pr_err("unit NoC Clock disconnect Error:timeout\n");
+ /*once timeout, undo idlereq by CLR*/
+ clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_CLR);
+ goto err;
+ }
+
+ } else if (clk->type == CLK_UNIT_NOC_SOCKET)
+ clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_SLVRDY_CLR);
+
clkc_writel(BIT(clk->bit), reg);
+err:
spin_unlock_irqrestore(clk->lock, flags);
}
@@ -1232,7 +1271,7 @@ static const struct clk_ops unit_clk_ops = {
static struct clk * __init
atlas7_unit_clk_register(struct device *dev, const char *name,
const char * const parent_name, unsigned long flags,
- u32 regofs, u8 bit, spinlock_t *lock)
+ u32 regofs, u8 bit, u32 type, u8 idle_bit, spinlock_t *lock)
{
struct clk *clk;
struct clk_unit *unit;
@@ -1251,6 +1290,9 @@ atlas7_unit_clk_register(struct device *dev, const char *name,
unit->hw.init = &init;
unit->regofs = regofs;
unit->bit = bit;
+
+ unit->type = type;
+ unit->idle_bit = idle_bit;
unit->lock = lock;
clk = clk_register(dev, &unit->hw);
@@ -1624,7 +1666,7 @@ static void __init atlas7_clk_init(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(unit_list); i++) {
unit = &unit_list[i];
atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name,
- unit->flags, unit->regofs, unit->bit, unit->lock);
+ unit->flags, unit->regofs, unit->bit, unit->type, unit->idle_bit, unit->lock);
BUG_ON(!atlas7_clks[i]);
}
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index bd355ee33766..24d99594c0b3 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -268,6 +268,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
int num_parents, i;
spinlock_t *rlock = NULL;
unsigned long flex_flags = 0;
+ int ret;
pnode = of_get_parent(np);
if (!pnode)
@@ -285,13 +286,13 @@ static void __init st_of_flexgen_setup(struct device_node *np)
if (!clk_data)
goto err;
- clk_data->clk_num = of_property_count_strings(np ,
- "clock-output-names");
- if (clk_data->clk_num <= 0) {
+ ret = of_property_count_strings(np, "clock-output-names");
+ if (ret <= 0) {
pr_err("%s: Failed to get number of output clocks (%d)",
__func__, clk_data->clk_num);
goto err;
}
+ clk_data->clk_num = ret;
clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
GFP_KERNEL);
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 4f7f6c00b219..5dc5ce217960 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include "clkgen.h"
static DEFINE_SPINLOCK(clkgena_divmux_lock);
static DEFINE_SPINLOCK(clkgenf_lock);
@@ -576,6 +577,7 @@ static struct clkgen_mux_data stih415_a9_mux_data = {
.offset = 0,
.shift = 1,
.width = 2,
+ .lock = &clkgen_a9_lock,
};
static struct clkgen_mux_data stih416_a9_mux_data = {
.offset = 0,
@@ -586,6 +588,7 @@ static struct clkgen_mux_data stih407_a9_mux_data = {
.offset = 0x1a4,
.shift = 0,
.width = 2,
+ .lock = &clkgen_a9_lock,
};
static const struct of_device_id mux_of_match[] = {
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index b2a332cf8985..38f6f3a9098e 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -18,10 +18,12 @@
#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/iopoll.h>
#include "clkgen.h"
static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
+DEFINE_SPINLOCK(clkgen_a9_lock);
/*
* Common PLL configuration register bits for PLL800 and PLL1600 C65
@@ -38,30 +40,46 @@ static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
#define C32_IDF_MASK (0x7)
#define C32_ODF_MASK (0x3f)
#define C32_LDF_MASK (0x7f)
+#define C32_CP_MASK (0x1f)
#define C32_MAX_ODFS (4)
+/*
+ * PLL configuration register bits for PLL4600 C28
+ */
+#define C28_NDIV_MASK (0xff)
+#define C28_IDF_MASK (0x7)
+#define C28_ODF_MASK (0x3f)
+
struct clkgen_pll_data {
struct clkgen_field pdn_status;
+ struct clkgen_field pdn_ctrl;
struct clkgen_field locked_status;
struct clkgen_field mdiv;
struct clkgen_field ndiv;
struct clkgen_field pdiv;
struct clkgen_field idf;
struct clkgen_field ldf;
+ struct clkgen_field cp;
unsigned int num_odfs;
struct clkgen_field odf[C32_MAX_ODFS];
struct clkgen_field odf_gate[C32_MAX_ODFS];
+ bool switch2pll_en;
+ struct clkgen_field switch2pll;
+ spinlock_t *lock;
const struct clk_ops *ops;
};
static const struct clk_ops st_pll1600c65_ops;
static const struct clk_ops st_pll800c65_ops;
static const struct clk_ops stm_pll3200c32_ops;
+static const struct clk_ops stm_pll3200c32_a9_ops;
static const struct clk_ops st_pll1200c32_ops;
+static const struct clk_ops stm_pll4600c28_ops;
static const struct clkgen_pll_data st_pll1600c65_ax = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 19),
+ .pdn_ctrl = CLKGEN_FIELD(0x10, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x0, 0x1, 31),
.mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK, 0),
.ndiv = CLKGEN_FIELD(0x0, C65_NDIV_MASK, 8),
@@ -70,6 +88,7 @@ static const struct clkgen_pll_data st_pll1600c65_ax = {
static const struct clkgen_pll_data st_pll800c65_ax = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 19),
+ .pdn_ctrl = CLKGEN_FIELD(0xC, 0x1, 1),
.locked_status = CLKGEN_FIELD(0x0, 0x1, 31),
.mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL800_MASK, 0),
.ndiv = CLKGEN_FIELD(0x0, C65_NDIV_MASK, 8),
@@ -79,6 +98,7 @@ static const struct clkgen_pll_data st_pll800c65_ax = {
static const struct clkgen_pll_data st_pll3200c32_a1x_0 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 31),
+ .pdn_ctrl = CLKGEN_FIELD(0x18, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x4, 0x1, 31),
.ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 0x0),
.idf = CLKGEN_FIELD(0x4, C32_IDF_MASK, 0x0),
@@ -96,6 +116,7 @@ static const struct clkgen_pll_data st_pll3200c32_a1x_0 = {
static const struct clkgen_pll_data st_pll3200c32_a1x_1 = {
.pdn_status = CLKGEN_FIELD(0xC, 0x1, 31),
+ .pdn_ctrl = CLKGEN_FIELD(0x18, 0x1, 1),
.locked_status = CLKGEN_FIELD(0x10, 0x1, 31),
.ndiv = CLKGEN_FIELD(0xC, C32_NDIV_MASK, 0x0),
.idf = CLKGEN_FIELD(0x10, C32_IDF_MASK, 0x0),
@@ -114,6 +135,7 @@ static const struct clkgen_pll_data st_pll3200c32_a1x_1 = {
/* 415 specific */
static const struct clkgen_pll_data st_pll3200c32_a9_415 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x6C, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 9),
.idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 22),
@@ -125,6 +147,7 @@ static const struct clkgen_pll_data st_pll3200c32_a9_415 = {
static const struct clkgen_pll_data st_pll3200c32_ddr_415 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x100, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0),
.idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25),
@@ -137,7 +160,8 @@ static const struct clkgen_pll_data st_pll3200c32_ddr_415 = {
};
static const struct clkgen_pll_data st_pll1200c32_gpu_415 = {
- .pdn_status = CLKGEN_FIELD(0x144, 0x1, 3),
+ .pdn_status = CLKGEN_FIELD(0x4, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x4, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x168, 0x1, 0),
.ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3),
.idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 0),
@@ -149,6 +173,7 @@ static const struct clkgen_pll_data st_pll1200c32_gpu_415 = {
/* 416 specific */
static const struct clkgen_pll_data st_pll3200c32_a9_416 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x6C, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0),
.idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25),
@@ -160,6 +185,7 @@ static const struct clkgen_pll_data st_pll3200c32_a9_416 = {
static const struct clkgen_pll_data st_pll3200c32_ddr_416 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x10C, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0),
.idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25),
@@ -173,6 +199,7 @@ static const struct clkgen_pll_data st_pll3200c32_ddr_416 = {
static const struct clkgen_pll_data st_pll1200c32_gpu_416 = {
.pdn_status = CLKGEN_FIELD(0x8E4, 0x1, 3),
+ .pdn_ctrl = CLKGEN_FIELD(0x8E4, 0x1, 3),
.locked_status = CLKGEN_FIELD(0x90C, 0x1, 0),
.ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3),
.idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 0),
@@ -184,6 +211,7 @@ static const struct clkgen_pll_data st_pll1200c32_gpu_416 = {
static const struct clkgen_pll_data st_pll3200c32_407_a0 = {
/* 407 A0 */
.pdn_status = CLKGEN_FIELD(0x2a0, 0x1, 8),
+ .pdn_ctrl = CLKGEN_FIELD(0x2a0, 0x1, 8),
.locked_status = CLKGEN_FIELD(0x2a0, 0x1, 24),
.ndiv = CLKGEN_FIELD(0x2a4, C32_NDIV_MASK, 16),
.idf = CLKGEN_FIELD(0x2a4, C32_IDF_MASK, 0x0),
@@ -196,6 +224,7 @@ static const struct clkgen_pll_data st_pll3200c32_407_a0 = {
static const struct clkgen_pll_data st_pll3200c32_cx_0 = {
/* 407 C0 PLL0 */
.pdn_status = CLKGEN_FIELD(0x2a0, 0x1, 8),
+ .pdn_ctrl = CLKGEN_FIELD(0x2a0, 0x1, 8),
.locked_status = CLKGEN_FIELD(0x2a0, 0x1, 24),
.ndiv = CLKGEN_FIELD(0x2a4, C32_NDIV_MASK, 16),
.idf = CLKGEN_FIELD(0x2a4, C32_IDF_MASK, 0x0),
@@ -208,6 +237,7 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = {
static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
/* 407 C0 PLL1 */
.pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8),
+ .pdn_ctrl = CLKGEN_FIELD(0x2c8, 0x1, 8),
.locked_status = CLKGEN_FIELD(0x2c8, 0x1, 24),
.ndiv = CLKGEN_FIELD(0x2cc, C32_NDIV_MASK, 16),
.idf = CLKGEN_FIELD(0x2cc, C32_IDF_MASK, 0x0),
@@ -220,13 +250,34 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
/* 407 A9 */
.pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x1a8, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x87c, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x1b0, C32_NDIV_MASK, 0),
.idf = CLKGEN_FIELD(0x1a8, C32_IDF_MASK, 25),
.num_odfs = 1,
.odf = { CLKGEN_FIELD(0x1b0, C32_ODF_MASK, 8) },
.odf_gate = { CLKGEN_FIELD(0x1ac, 0x1, 28) },
- .ops = &stm_pll3200c32_ops,
+ .switch2pll_en = true,
+ .cp = CLKGEN_FIELD(0x1a8, C32_CP_MASK, 1),
+ .switch2pll = CLKGEN_FIELD(0x1a4, 0x1, 1),
+ .lock = &clkgen_a9_lock,
+ .ops = &stm_pll3200c32_a9_ops,
+};
+
+static struct clkgen_pll_data st_pll4600c28_418_a9 = {
+ /* 418 A9 */
+ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
+ .pdn_ctrl = CLKGEN_FIELD(0x1a8, 0x1, 0),
+ .locked_status = CLKGEN_FIELD(0x87c, 0x1, 0),
+ .ndiv = CLKGEN_FIELD(0x1b0, C28_NDIV_MASK, 0),
+ .idf = CLKGEN_FIELD(0x1a8, C28_IDF_MASK, 25),
+ .num_odfs = 1,
+ .odf = { CLKGEN_FIELD(0x1b0, C28_ODF_MASK, 8) },
+ .odf_gate = { CLKGEN_FIELD(0x1ac, 0x1, 28) },
+ .switch2pll_en = true,
+ .switch2pll = CLKGEN_FIELD(0x1a4, 0x1, 1),
+ .lock = &clkgen_a9_lock,
+ .ops = &stm_pll4600c28_ops,
};
/**
@@ -252,10 +303,26 @@ struct clkgen_pll {
struct clk_hw hw;
struct clkgen_pll_data *data;
void __iomem *regs_base;
+ spinlock_t *lock;
+
+ u32 ndiv;
+ u32 idf;
+ u32 odf;
+ u32 cp;
};
#define to_clkgen_pll(_hw) container_of(_hw, struct clkgen_pll, hw)
+struct stm_pll {
+ unsigned long mdiv;
+ unsigned long ndiv;
+ unsigned long pdiv;
+ unsigned long odf;
+ unsigned long idf;
+ unsigned long ldf;
+ unsigned long cp;
+};
+
static int clkgen_pll_is_locked(struct clk_hw *hw)
{
struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -271,6 +338,78 @@ static int clkgen_pll_is_enabled(struct clk_hw *hw)
return !poweroff;
}
+static int __clkgen_pll_enable(struct clk_hw *hw)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+ void __iomem *base = pll->regs_base;
+ struct clkgen_field *field = &pll->data->locked_status;
+ int ret = 0;
+ u32 reg;
+
+ if (clkgen_pll_is_enabled(hw))
+ return 0;
+
+ CLKGEN_WRITE(pll, pdn_ctrl, 0);
+
+ ret = readl_relaxed_poll_timeout(base + field->offset, reg,
+ !!((reg >> field->shift) & field->mask), 0, 10000);
+
+ if (!ret) {
+ if (pll->data->switch2pll_en)
+ CLKGEN_WRITE(pll, switch2pll, 0);
+
+ pr_debug("%s:%s enabled\n", __clk_get_name(hw->clk), __func__);
+ }
+
+ return ret;
+}
+
+static int clkgen_pll_enable(struct clk_hw *hw)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+ unsigned long flags = 0;
+ int ret = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ ret = __clkgen_pll_enable(hw);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static void __clkgen_pll_disable(struct clk_hw *hw)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+
+ if (!clkgen_pll_is_enabled(hw))
+ return;
+
+ if (pll->data->switch2pll_en)
+ CLKGEN_WRITE(pll, switch2pll, 1);
+
+ CLKGEN_WRITE(pll, pdn_ctrl, 1);
+
+ pr_debug("%s:%s disabled\n", __clk_get_name(hw->clk), __func__);
+}
+
+static void clkgen_pll_disable(struct clk_hw *hw)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+ unsigned long flags = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ __clkgen_pll_disable(hw);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+
static unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -322,6 +461,67 @@ static unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
return rate;
}
+static int clk_pll3200c32_get_params(unsigned long input, unsigned long output,
+ struct stm_pll *pll)
+{
+ unsigned long i, n;
+ unsigned long deviation = ~0;
+ unsigned long new_freq;
+ long new_deviation;
+ /* Charge pump table: highest ndiv value for cp=6 to 25 */
+ static const unsigned char cp_table[] = {
+ 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,
+ 128, 136, 144, 152, 160, 168, 176, 184, 192
+ };
+
+ /* Output clock range: 800Mhz to 1600Mhz */
+ if (output < 800000000 || output > 1600000000)
+ return -EINVAL;
+
+ input /= 1000;
+ output /= 1000;
+
+ for (i = 1; i <= 7 && deviation; i++) {
+ n = i * output / (2 * input);
+
+ /* Checks */
+ if (n < 8)
+ continue;
+ if (n > 200)
+ break;
+
+ new_freq = (input * 2 * n) / i;
+
+ new_deviation = abs(new_freq - output);
+
+ if (!new_deviation || new_deviation < deviation) {
+ pll->idf = i;
+ pll->ndiv = n;
+ deviation = new_deviation;
+ }
+ }
+
+ if (deviation == ~0) /* No solution found */
+ return -EINVAL;
+
+ /* Computing recommended charge pump value */
+ for (pll->cp = 6; pll->ndiv > cp_table[pll->cp-6]; (pll->cp)++)
+ ;
+
+ return 0;
+}
+
+static int clk_pll3200c32_get_rate(unsigned long input, struct stm_pll *pll,
+ unsigned long *rate)
+{
+ if (!pll->idf)
+ pll->idf = 1;
+
+ *rate = ((2 * (input / 1000) * pll->ndiv) / pll->idf) * 1000;
+
+ return 0;
+}
+
static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -344,6 +544,70 @@ static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
return rate;
}
+static long round_rate_stm_pll3200c32(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct stm_pll params;
+
+ if (!clk_pll3200c32_get_params(*prate, rate, &params))
+ clk_pll3200c32_get_rate(*prate, &params, &rate);
+ else {
+ pr_debug("%s: %s rate %ld Invalid\n", __func__,
+ __clk_get_name(hw->clk), rate);
+ return 0;
+ }
+
+ pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n",
+ __func__, __clk_get_name(hw->clk),
+ rate, (unsigned int)params.ndiv,
+ (unsigned int)params.idf);
+
+ return rate;
+}
+
+static int set_rate_stm_pll3200c32(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+ struct stm_pll params;
+ long hwrate = 0;
+ unsigned long flags = 0;
+
+ if (!rate || !parent_rate)
+ return -EINVAL;
+
+ if (!clk_pll3200c32_get_params(parent_rate, rate, &params))
+ clk_pll3200c32_get_rate(parent_rate, &params, &hwrate);
+
+ pr_debug("%s: %s new rate %ld [ndiv=0x%x] [idf=0x%x]\n",
+ __func__, __clk_get_name(hw->clk),
+ hwrate, (unsigned int)params.ndiv,
+ (unsigned int)params.idf);
+
+ if (!hwrate)
+ return -EINVAL;
+
+ pll->ndiv = params.ndiv;
+ pll->idf = params.idf;
+ pll->cp = params.cp;
+
+ __clkgen_pll_disable(hw);
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ CLKGEN_WRITE(pll, ndiv, pll->ndiv);
+ CLKGEN_WRITE(pll, idf, pll->idf);
+ CLKGEN_WRITE(pll, cp, pll->cp);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ __clkgen_pll_enable(hw);
+
+ return 0;
+}
+
static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -371,30 +635,213 @@ static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
return rate;
}
+/* PLL output structure
+ * FVCO >> /2 >> FVCOBY2 (no output)
+ * |> Divider (ODF) >> PHI
+ *
+ * FVCOby2 output = (input * 2 * NDIV) / IDF (assuming FRAC_CONTROL==L)
+ *
+ * Rules:
+ * 4Mhz <= INFF input <= 350Mhz
+ * 4Mhz <= INFIN (INFF / IDF) <= 50Mhz
+ * 19.05Mhz <= FVCOby2 output (PHI w ODF=1) <= 3000Mhz
+ * 1 <= i (register/dec value for IDF) <= 7
+ * 8 <= n (register/dec value for NDIV) <= 246
+ */
+
+static int clk_pll4600c28_get_params(unsigned long input, unsigned long output,
+ struct stm_pll *pll)
+{
+
+ unsigned long i, infin, n;
+ unsigned long deviation = ~0;
+ unsigned long new_freq, new_deviation;
+
+ /* Output clock range: 19Mhz to 3000Mhz */
+ if (output < 19000000 || output > 3000000000u)
+ return -EINVAL;
+
+ /* For better jitter, IDF should be smallest and NDIV must be maximum */
+ for (i = 1; i <= 7 && deviation; i++) {
+ /* INFIN checks */
+ infin = input / i;
+ if (infin < 4000000 || infin > 50000000)
+ continue; /* Invalid case */
+
+ n = output / (infin * 2);
+ if (n < 8 || n > 246)
+ continue; /* Invalid case */
+ if (n < 246)
+ n++; /* To work around 'y' when n=x.y */
+
+ for (; n >= 8 && deviation; n--) {
+ new_freq = infin * 2 * n;
+ if (new_freq < output)
+ break; /* Optimization: shorting loop */
+
+ new_deviation = new_freq - output;
+ if (!new_deviation || new_deviation < deviation) {
+ pll->idf = i;
+ pll->ndiv = n;
+ deviation = new_deviation;
+ }
+ }
+ }
+
+ if (deviation == ~0) /* No solution found */
+ return -EINVAL;
+
+ return 0;
+}
+
+static int clk_pll4600c28_get_rate(unsigned long input, struct stm_pll *pll,
+ unsigned long *rate)
+{
+ if (!pll->idf)
+ pll->idf = 1;
+
+ *rate = (input / pll->idf) * 2 * pll->ndiv;
+
+ return 0;
+}
+
+static unsigned long recalc_stm_pll4600c28(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+ struct stm_pll params;
+ unsigned long rate;
+
+ if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+ return 0;
+
+ params.ndiv = CLKGEN_READ(pll, ndiv);
+ params.idf = CLKGEN_READ(pll, idf);
+
+ clk_pll4600c28_get_rate(parent_rate, &params, &rate);
+
+ pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+ return rate;
+}
+
+static long round_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct stm_pll params;
+
+ if (!clk_pll4600c28_get_params(*prate, rate, &params)) {
+ clk_pll4600c28_get_rate(*prate, &params, &rate);
+ } else {
+ pr_debug("%s: %s rate %ld Invalid\n", __func__,
+ __clk_get_name(hw->clk), rate);
+ return 0;
+ }
+
+ pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n",
+ __func__, __clk_get_name(hw->clk),
+ rate, (unsigned int)params.ndiv,
+ (unsigned int)params.idf);
+
+ return rate;
+}
+
+static int set_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clkgen_pll *pll = to_clkgen_pll(hw);
+ struct stm_pll params;
+ long hwrate;
+ unsigned long flags = 0;
+
+ if (!rate || !parent_rate)
+ return -EINVAL;
+
+ if (!clk_pll4600c28_get_params(parent_rate, rate, &params)) {
+ clk_pll4600c28_get_rate(parent_rate, &params, &hwrate);
+ } else {
+ pr_debug("%s: %s rate %ld Invalid\n", __func__,
+ __clk_get_name(hw->clk), rate);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: %s new rate %ld [ndiv=0x%x] [idf=0x%x]\n",
+ __func__, __clk_get_name(hw->clk),
+ hwrate, (unsigned int)params.ndiv,
+ (unsigned int)params.idf);
+
+ if (!hwrate)
+ return -EINVAL;
+
+ pll->ndiv = params.ndiv;
+ pll->idf = params.idf;
+
+ __clkgen_pll_disable(hw);
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ CLKGEN_WRITE(pll, ndiv, pll->ndiv);
+ CLKGEN_WRITE(pll, idf, pll->idf);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ __clkgen_pll_enable(hw);
+
+ return 0;
+}
+
static const struct clk_ops st_pll1600c65_ops = {
+ .enable = clkgen_pll_enable,
+ .disable = clkgen_pll_disable,
.is_enabled = clkgen_pll_is_enabled,
.recalc_rate = recalc_stm_pll1600c65,
};
static const struct clk_ops st_pll800c65_ops = {
+ .enable = clkgen_pll_enable,
+ .disable = clkgen_pll_disable,
.is_enabled = clkgen_pll_is_enabled,
.recalc_rate = recalc_stm_pll800c65,
};
static const struct clk_ops stm_pll3200c32_ops = {
+ .enable = clkgen_pll_enable,
+ .disable = clkgen_pll_disable,
.is_enabled = clkgen_pll_is_enabled,
.recalc_rate = recalc_stm_pll3200c32,
};
+static const struct clk_ops stm_pll3200c32_a9_ops = {
+ .enable = clkgen_pll_enable,
+ .disable = clkgen_pll_disable,
+ .is_enabled = clkgen_pll_is_enabled,
+ .recalc_rate = recalc_stm_pll3200c32,
+ .round_rate = round_rate_stm_pll3200c32,
+ .set_rate = set_rate_stm_pll3200c32,
+};
+
static const struct clk_ops st_pll1200c32_ops = {
+ .enable = clkgen_pll_enable,
+ .disable = clkgen_pll_disable,
.is_enabled = clkgen_pll_is_enabled,
.recalc_rate = recalc_stm_pll1200c32,
};
+static const struct clk_ops stm_pll4600c28_ops = {
+ .enable = clkgen_pll_enable,
+ .disable = clkgen_pll_disable,
+ .is_enabled = clkgen_pll_is_enabled,
+ .recalc_rate = recalc_stm_pll4600c28,
+ .round_rate = round_rate_stm_pll4600c28,
+ .set_rate = set_rate_stm_pll4600c28,
+};
+
static struct clk * __init clkgen_pll_register(const char *parent_name,
struct clkgen_pll_data *pll_data,
void __iomem *reg,
- const char *clk_name)
+ const char *clk_name, spinlock_t *lock)
{
struct clkgen_pll *pll;
struct clk *clk;
@@ -414,6 +861,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name,
pll->data = pll_data;
pll->regs_base = reg;
pll->hw.init = &init;
+ pll->lock = lock;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
@@ -500,7 +948,7 @@ static void __init clkgena_c65_pll_setup(struct device_node *np)
*/
clk_data->clks[0] = clkgen_pll_register(parent_name,
(struct clkgen_pll_data *) &st_pll1600c65_ax,
- reg + CLKGENAx_PLL0_OFFSET, clk_name);
+ reg + CLKGENAx_PLL0_OFFSET, clk_name, NULL);
if (IS_ERR(clk_data->clks[0]))
goto err;
@@ -529,7 +977,7 @@ static void __init clkgena_c65_pll_setup(struct device_node *np)
*/
clk_data->clks[2] = clkgen_pll_register(parent_name,
(struct clkgen_pll_data *) &st_pll800c65_ax,
- reg + CLKGENAx_PLL1_OFFSET, clk_name);
+ reg + CLKGENAx_PLL1_OFFSET, clk_name, NULL);
if (IS_ERR(clk_data->clks[2]))
goto err;
@@ -556,7 +1004,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
struct clk_gate *gate;
struct clk_divider *div;
- flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;
+ flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
@@ -635,6 +1083,10 @@ static const struct of_device_id c32_pll_of_match[] = {
.compatible = "st,stih407-plls-c32-a9",
.data = &st_pll3200c32_407_a9,
},
+ {
+ .compatible = "st,stih418-plls-c28-a9",
+ .data = &st_pll4600c28_418_a9,
+ },
{}
};
@@ -664,7 +1116,8 @@ static void __init clkgen_c32_pll_setup(struct device_node *np)
if (!pll_base)
return;
- clk = clkgen_pll_register(parent_name, data, pll_base, np->name);
+ clk = clkgen_pll_register(parent_name, data, pll_base, np->name,
+ data->lock);
if (IS_ERR(clk))
return;
@@ -753,7 +1206,7 @@ static void __init clkgengpu_c32_pll_setup(struct device_node *np)
/*
* PLL 1200MHz output
*/
- clk = clkgen_pll_register(parent_name, data, reg, clk_name);
+ clk = clkgen_pll_register(parent_name, data, reg, clk_name, data->lock);
if (!IS_ERR(clk))
of_clk_add_provider(np, of_clk_src_simple_get, clk);
diff --git a/drivers/clk/st/clkgen.h b/drivers/clk/st/clkgen.h
index 35c863295268..f7ec2d9139d6 100644
--- a/drivers/clk/st/clkgen.h
+++ b/drivers/clk/st/clkgen.h
@@ -9,6 +9,8 @@ Copyright (C) 2014 STMicroelectronics
#ifndef __CLKGEN_INFO_H
#define __CLKGEN_INFO_H
+extern spinlock_t clkgen_a9_lock;
+
struct clkgen_field {
unsigned int offset;
unsigned int mask;
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index f5a35b82cc1a..cb4c299214ce 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -3,7 +3,10 @@
#
obj-y += clk-sunxi.o clk-factors.o
+obj-y += clk-a10-codec.o
obj-y += clk-a10-hosc.o
+obj-y += clk-a10-mod1.o
+obj-y += clk-a10-pll2.o
obj-y += clk-a20-gmac.o
obj-y += clk-mod0.o
obj-y += clk-simple-gates.o
diff --git a/drivers/clk/sunxi/clk-a10-codec.c b/drivers/clk/sunxi/clk-a10-codec.c
new file mode 100644
index 000000000000..ac321d6a0df5
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-codec.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * 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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SUN4I_CODEC_GATE 31
+
+static void __init sun4i_codec_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ const char *clk_name = node->name, *parent_name;
+ void __iomem *reg;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg))
+ return;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ parent_name = of_clk_get_parent_name(node, 0);
+
+ clk = clk_register_gate(NULL, clk_name, parent_name,
+ CLK_SET_RATE_PARENT, reg,
+ SUN4I_CODEC_GATE, 0, NULL);
+
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(sun4i_codec, "allwinner,sun4i-a10-codec-clk",
+ sun4i_codec_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a10-mod1.c b/drivers/clk/sunxi/clk-a10-mod1.c
new file mode 100644
index 000000000000..e9d870de165c
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-mod1.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * 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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+static DEFINE_SPINLOCK(mod1_lock);
+
+#define SUN4I_MOD1_ENABLE 31
+#define SUN4I_MOD1_MUX 16
+#define SUN4I_MOD1_MUX_WIDTH 2
+#define SUN4I_MOD1_MAX_PARENTS 4
+
+static void __init sun4i_mod1_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ struct clk_mux *mux;
+ struct clk_gate *gate;
+ const char *parents[4];
+ const char *clk_name = node->name;
+ void __iomem *reg;
+ int i;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg))
+ return;
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ goto err_unmap;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ goto err_free_mux;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ i = of_clk_parent_fill(node, parents, SUN4I_MOD1_MAX_PARENTS);
+
+ gate->reg = reg;
+ gate->bit_idx = SUN4I_MOD1_ENABLE;
+ gate->lock = &mod1_lock;
+ mux->reg = reg;
+ mux->shift = SUN4I_MOD1_MUX;
+ mux->mask = BIT(SUN4I_MOD1_MUX_WIDTH) - 1;
+ mux->lock = &mod1_lock;
+
+ clk = clk_register_composite(NULL, clk_name, parents, i,
+ &mux->hw, &clk_mux_ops,
+ NULL, NULL,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk))
+ goto err_free_gate;
+
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return;
+
+err_free_gate:
+ kfree(gate);
+err_free_mux:
+ kfree(mux);
+err_unmap:
+ iounmap(reg);
+}
+CLK_OF_DECLARE(sun4i_mod1, "allwinner,sun4i-a10-mod1-clk",
+ sun4i_mod1_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a10-pll2.c b/drivers/clk/sunxi/clk-a10-pll2.c
new file mode 100644
index 000000000000..5484c31ec568
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-pll2.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2013 Emilio López
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * Copyright 2015 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/sun4i-a10-pll2.h>
+
+#define SUN4I_PLL2_ENABLE 31
+
+#define SUN4I_PLL2_PRE_DIV_SHIFT 0
+#define SUN4I_PLL2_PRE_DIV_WIDTH 5
+#define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0)
+
+#define SUN4I_PLL2_N_SHIFT 8
+#define SUN4I_PLL2_N_WIDTH 7
+#define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0)
+
+#define SUN4I_PLL2_POST_DIV_SHIFT 26
+#define SUN4I_PLL2_POST_DIV_WIDTH 4
+#define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0)
+
+#define SUN4I_PLL2_POST_DIV_VALUE 4
+
+#define SUN4I_PLL2_OUTPUTS 4
+
+struct sun4i_pll2_data {
+ u32 post_div_offset;
+ u32 pre_div_flags;
+};
+
+static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);
+
+static void __init sun4i_pll2_setup(struct device_node *node,
+ struct sun4i_pll2_data *data)
+{
+ const char *clk_name = node->name, *parent;
+ struct clk **clks, *base_clk, *prediv_clk;
+ struct clk_onecell_data *clk_data;
+ struct clk_multiplier *mult;
+ struct clk_gate *gate;
+ void __iomem *reg;
+ u32 val;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg))
+ return;
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ goto err_unmap;
+
+ clks = kcalloc(SUN4I_PLL2_OUTPUTS, sizeof(struct clk *), GFP_KERNEL);
+ if (!clks)
+ goto err_free_data;
+
+ parent = of_clk_get_parent_name(node, 0);
+ prediv_clk = clk_register_divider(NULL, "pll2-prediv",
+ parent, 0, reg,
+ SUN4I_PLL2_PRE_DIV_SHIFT,
+ SUN4I_PLL2_PRE_DIV_WIDTH,
+ data->pre_div_flags,
+ &sun4i_a10_pll2_lock);
+ if (!prediv_clk) {
+ pr_err("Couldn't register the prediv clock\n");
+ goto err_free_array;
+ }
+
+ /* Setup the gate part of the PLL2 */
+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+ if (!gate)
+ goto err_unregister_prediv;
+
+ gate->reg = reg;
+ gate->bit_idx = SUN4I_PLL2_ENABLE;
+ gate->lock = &sun4i_a10_pll2_lock;
+
+ /* Setup the multiplier part of the PLL2 */
+ mult = kzalloc(sizeof(struct clk_multiplier), GFP_KERNEL);
+ if (!mult)
+ goto err_free_gate;
+
+ mult->reg = reg;
+ mult->shift = SUN4I_PLL2_N_SHIFT;
+ mult->width = 7;
+ mult->flags = CLK_MULTIPLIER_ZERO_BYPASS |
+ CLK_MULTIPLIER_ROUND_CLOSEST;
+ mult->lock = &sun4i_a10_pll2_lock;
+
+ parent = __clk_get_name(prediv_clk);
+ base_clk = clk_register_composite(NULL, "pll2-base",
+ &parent, 1,
+ NULL, NULL,
+ &mult->hw, &clk_multiplier_ops,
+ &gate->hw, &clk_gate_ops,
+ CLK_SET_RATE_PARENT);
+ if (!base_clk) {
+ pr_err("Couldn't register the base multiplier clock\n");
+ goto err_free_multiplier;
+ }
+
+ parent = __clk_get_name(base_clk);
+
+ /*
+ * PLL2-1x
+ *
+ * This is supposed to have a post divider, but we won't need
+ * to use it, we just need to initialise it to 4, and use a
+ * fixed divider.
+ */
+ val = readl(reg);
+ val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT);
+ val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
+ writel(val, reg);
+
+ of_property_read_string_index(node, "clock-output-names",
+ SUN4I_A10_PLL2_1X, &clk_name);
+ clks[SUN4I_A10_PLL2_1X] = clk_register_fixed_factor(NULL, clk_name,
+ parent,
+ CLK_SET_RATE_PARENT,
+ 1,
+ SUN4I_PLL2_POST_DIV_VALUE);
+ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_1X]));
+
+ /*
+ * PLL2-2x
+ *
+ * This clock doesn't use the post divider, and really is just
+ * a fixed divider from the PLL2 base clock.
+ */
+ of_property_read_string_index(node, "clock-output-names",
+ SUN4I_A10_PLL2_2X, &clk_name);
+ clks[SUN4I_A10_PLL2_2X] = clk_register_fixed_factor(NULL, clk_name,
+ parent,
+ CLK_SET_RATE_PARENT,
+ 1, 2);
+ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_2X]));
+
+ /* PLL2-4x */
+ of_property_read_string_index(node, "clock-output-names",
+ SUN4I_A10_PLL2_4X, &clk_name);
+ clks[SUN4I_A10_PLL2_4X] = clk_register_fixed_factor(NULL, clk_name,
+ parent,
+ CLK_SET_RATE_PARENT,
+ 1, 1);
+ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_4X]));
+
+ /* PLL2-8x */
+ of_property_read_string_index(node, "clock-output-names",
+ SUN4I_A10_PLL2_8X, &clk_name);
+ clks[SUN4I_A10_PLL2_8X] = clk_register_fixed_factor(NULL, clk_name,
+ parent,
+ CLK_SET_RATE_PARENT,
+ 2, 1);
+ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_8X]));
+
+ clk_data->clks = clks;
+ clk_data->clk_num = SUN4I_PLL2_OUTPUTS;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ return;
+
+err_free_multiplier:
+ kfree(mult);
+err_free_gate:
+ kfree(gate);
+err_unregister_prediv:
+ clk_unregister_divider(prediv_clk);
+err_free_array:
+ kfree(clks);
+err_free_data:
+ kfree(clk_data);
+err_unmap:
+ iounmap(reg);
+}
+
+static struct sun4i_pll2_data sun4i_a10_pll2_data = {
+ .pre_div_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+};
+
+static void __init sun4i_a10_pll2_setup(struct device_node *node)
+{
+ sun4i_pll2_setup(node, &sun4i_a10_pll2_data);
+}
+
+CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk",
+ sun4i_a10_pll2_setup);
+
+static struct sun4i_pll2_data sun5i_a13_pll2_data = {
+ .post_div_offset = 1,
+};
+
+static void __init sun5i_a13_pll2_setup(struct device_node *node)
+{
+ sun4i_pll2_setup(node, &sun5i_a13_pll2_data);
+}
+
+CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk",
+ sun5i_a13_pll2_setup);
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
index 6ce91180da1b..0214c6548afd 100644
--- a/drivers/clk/sunxi/clk-simple-gates.c
+++ b/drivers/clk/sunxi/clk-simple-gates.c
@@ -128,6 +128,8 @@ CLK_OF_DECLARE(sun8i_a23_apb1, "allwinner,sun8i-a23-apb1-gates-clk",
sunxi_simple_gates_init);
CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk",
sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a33_ahb1, "allwinner,sun8i-a33-ahb1-gates-clk",
+ sunxi_simple_gates_init);
CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk",
sunxi_simple_gates_init);
CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk",
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
index 64f3e46d383c..23d042aabb4f 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
@@ -34,6 +34,7 @@ static const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
{ .compatible = "allwinner,sun8i-a23-apb0-gates-clk", .data = &sun8i_a23_apb0_gates },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, sun6i_a31_apb0_gates_clk_dt_ids);
static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
{
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
index 70763600aeae..e703e1895b76 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0.c
@@ -61,6 +61,7 @@ static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-apb0-clk" },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, sun6i_a31_apb0_clk_dt_ids);
static struct platform_driver sun6i_a31_apb0_clk_driver = {
.driver = {
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 806fd019c05d..20887686bdbe 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -219,6 +219,7 @@ static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-ar100-clk" },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, sun6i_a31_ar100_clk_dt_ids);
static struct platform_driver sun6i_a31_ar100_clk_driver = {
.driver = {
diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c
index 155d0022194f..7ae5d2c2cde1 100644
--- a/drivers/clk/sunxi/clk-sun8i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun8i-apb0.c
@@ -52,6 +52,7 @@ static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
{ .compatible = "allwinner,sun8i-a23-apb0-clk" },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, sun8i_a23_apb0_clk_dt_ids);
static struct platform_driver sun8i_a23_apb0_clk_driver = {
.driver = {
diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c
index 3436a948b796..a9b176139aca 100644
--- a/drivers/clk/sunxi/clk-sun9i-mmc.c
+++ b/drivers/clk/sunxi/clk-sun9i-mmc.c
@@ -204,6 +204,7 @@ static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = {
{ .compatible = "allwinner,sun9i-a80-mmc-config-clk" },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, sun9i_a80_mmc_config_clk_dt_ids);
static struct platform_driver sun9i_a80_mmc_config_clk_driver = {
.driver = {
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 413070d07b3f..9c79af0c03b2 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1196,6 +1196,7 @@ static void __init sun5i_init_clocks(struct device_node *node)
}
CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
+CLK_OF_DECLARE(sun5i_r8_clk_init, "allwinner,sun5i-r8", sun5i_init_clocks);
CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
static const char *sun6i_critical_clocks[] __initdata = {
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index c4e3a52e225b..86a307b17eb0 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -469,56 +469,6 @@ static unsigned long dfll_scale_dvco_rate(int scale_bits,
}
/*
- * Monitor control
- */
-
-/**
- * dfll_calc_monitored_rate - convert DFLL_MONITOR_DATA_VAL rate into real freq
- * @monitor_data: value read from the DFLL_MONITOR_DATA_VAL bitfield
- * @ref_rate: DFLL reference clock rate
- *
- * Convert @monitor_data from DFLL_MONITOR_DATA_VAL units into cycles
- * per second. Returns the converted value.
- */
-static u64 dfll_calc_monitored_rate(u32 monitor_data,
- unsigned long ref_rate)
-{
- return monitor_data * (ref_rate / REF_CLK_CYC_PER_DVCO_SAMPLE);
-}
-
-/**
- * dfll_read_monitor_rate - return the DFLL's output rate from internal monitor
- * @td: DFLL instance
- *
- * If the DFLL is enabled, return the last rate reported by the DFLL's
- * internal monitoring hardware. This works in both open-loop and
- * closed-loop mode, and takes the output scaler setting into account.
- * Assumes that the monitor was programmed to monitor frequency before
- * the sample period started. If the driver believes that the DFLL is
- * currently uninitialized or disabled, it will return 0, since
- * otherwise the DFLL monitor data register will return the last
- * measured rate from when the DFLL was active.
- */
-static u64 dfll_read_monitor_rate(struct tegra_dfll *td)
-{
- u32 v, s;
- u64 pre_scaler_rate, post_scaler_rate;
-
- if (!dfll_is_running(td))
- return 0;
-
- v = dfll_readl(td, DFLL_MONITOR_DATA);
- v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
- pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);
-
- s = dfll_readl(td, DFLL_FREQ_REQ);
- s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
- post_scaler_rate = dfll_scale_dvco_rate(s, pre_scaler_rate);
-
- return post_scaler_rate;
-}
-
-/*
* DFLL mode switching
*/
@@ -1006,24 +956,25 @@ static unsigned long dfll_clk_recalc_rate(struct clk_hw *hw,
return td->last_unrounded_rate;
}
-static long dfll_clk_round_rate(struct clk_hw *hw,
- unsigned long rate,
- unsigned long *parent_rate)
+/* Must use determine_rate since it allows for rates exceeding 2^31-1 */
+static int dfll_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *clk_req)
{
struct tegra_dfll *td = clk_hw_to_dfll(hw);
struct dfll_rate_req req;
int ret;
- ret = dfll_calculate_rate_request(td, &req, rate);
+ ret = dfll_calculate_rate_request(td, &req, clk_req->rate);
if (ret)
return ret;
/*
- * Don't return the rounded rate, since it doesn't really matter as
+ * Don't set the rounded rate, since it doesn't really matter as
* the output rate will be voltage controlled anyway, and cpufreq
* freaks out if any rounding happens.
*/
- return rate;
+
+ return 0;
}
static int dfll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1039,7 +990,7 @@ static const struct clk_ops dfll_clk_ops = {
.enable = dfll_clk_enable,
.disable = dfll_clk_disable,
.recalc_rate = dfll_clk_recalc_rate,
- .round_rate = dfll_clk_round_rate,
+ .determine_rate = dfll_clk_determine_rate,
.set_rate = dfll_clk_set_rate,
};
@@ -1101,6 +1052,55 @@ static void dfll_unregister_clk(struct tegra_dfll *td)
*/
#ifdef CONFIG_DEBUG_FS
+/*
+ * Monitor control
+ */
+
+/**
+ * dfll_calc_monitored_rate - convert DFLL_MONITOR_DATA_VAL rate into real freq
+ * @monitor_data: value read from the DFLL_MONITOR_DATA_VAL bitfield
+ * @ref_rate: DFLL reference clock rate
+ *
+ * Convert @monitor_data from DFLL_MONITOR_DATA_VAL units into cycles
+ * per second. Returns the converted value.
+ */
+static u64 dfll_calc_monitored_rate(u32 monitor_data,
+ unsigned long ref_rate)
+{
+ return monitor_data * (ref_rate / REF_CLK_CYC_PER_DVCO_SAMPLE);
+}
+
+/**
+ * dfll_read_monitor_rate - return the DFLL's output rate from internal monitor
+ * @td: DFLL instance
+ *
+ * If the DFLL is enabled, return the last rate reported by the DFLL's
+ * internal monitoring hardware. This works in both open-loop and
+ * closed-loop mode, and takes the output scaler setting into account.
+ * Assumes that the monitor was programmed to monitor frequency before
+ * the sample period started. If the driver believes that the DFLL is
+ * currently uninitialized or disabled, it will return 0, since
+ * otherwise the DFLL monitor data register will return the last
+ * measured rate from when the DFLL was active.
+ */
+static u64 dfll_read_monitor_rate(struct tegra_dfll *td)
+{
+ u32 v, s;
+ u64 pre_scaler_rate, post_scaler_rate;
+
+ if (!dfll_is_running(td))
+ return 0;
+
+ v = dfll_readl(td, DFLL_MONITOR_DATA);
+ v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
+ pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);
+
+ s = dfll_readl(td, DFLL_FREQ_REQ);
+ s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
+ post_scaler_rate = dfll_scale_dvco_rate(s, pre_scaler_rate);
+
+ return post_scaler_rate;
+}
static int attr_enable_get(void *data, u64 *val)
{
diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c
index 138a94b99b5b..e1fe8f35d45c 100644
--- a/drivers/clk/tegra/clk-emc.c
+++ b/drivers/clk/tegra/clk-emc.c
@@ -491,10 +491,8 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
for_each_child_of_node(np, node) {
err = of_property_read_u32(node, "nvidia,ram-code",
&node_ram_code);
- if (err) {
- of_node_put(node);
+ if (err)
continue;
- }
/*
* Store timings for all ram codes as we cannot read the
diff --git a/drivers/clk/tegra/clk-tegra-audio.c b/drivers/clk/tegra/clk-tegra-audio.c
index 11e3ad7ad7a3..e2bfa9b368f6 100644
--- a/drivers/clk/tegra/clk-tegra-audio.c
+++ b/drivers/clk/tegra/clk-tegra-audio.c
@@ -125,18 +125,29 @@ static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
void __init tegra_audio_clk_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
- struct tegra_clk_pll_params *pll_a_params)
+ struct tegra_audio_clk_info *audio_info,
+ unsigned int num_plls)
{
struct clk *clk;
struct clk **dt_clk;
int i;
- /* PLLA */
- dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks);
- if (dt_clk) {
- clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base,
- pmc_base, 0, pll_a_params, NULL);
- *dt_clk = clk;
+ if (!audio_info || num_plls < 1) {
+ pr_err("No audio data passed to tegra_audio_clk_init\n");
+ WARN_ON(1);
+ return;
+ }
+
+ for (i = 0; i < num_plls; i++) {
+ struct tegra_audio_clk_info *info = &audio_info[i];
+
+ dt_clk = tegra_lookup_dt_id(info->clk_id, tegra_clks);
+ if (dt_clk) {
+ clk = tegra_clk_register_pll(info->name, info->parent,
+ clk_base, pmc_base, 0, info->pll_params,
+ NULL);
+ *dt_clk = clk;
+ }
}
/* PLLA_OUT0 */
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index db5871519bf5..b7d03e9add97 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -933,6 +933,10 @@ static u32 mux_pllm_pllc2_c_c3_pllp_plla_idx[] = {
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
};
+static struct tegra_audio_clk_info tegra114_audio_plls[] = {
+ { "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
+};
+
static struct clk **clks;
static unsigned long osc_freq;
@@ -1481,7 +1485,9 @@ static void __init tegra114_clock_init(struct device_node *np)
tegra114_fixed_clk_init(clk_base);
tegra114_pll_init(clk_base, pmc_base);
tegra114_periph_clk_init(clk_base, pmc_base);
- tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params);
+ tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks,
+ tegra114_audio_plls,
+ ARRAY_SIZE(tegra114_audio_plls));
tegra_pmc_clk_init(pmc_base, tegra114_clks);
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks,
&pll_x_params);
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 824d75883d2b..87975f7adddc 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1417,6 +1417,10 @@ static struct tegra_clk_init_table tegra132_init_table[] __initdata = {
{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
};
+static struct tegra_audio_clk_info tegra124_audio_plls[] = {
+ { "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
+};
+
/**
* tegra124_clock_apply_init_table - initialize clocks on Tegra124 SoCs
*
@@ -1555,7 +1559,9 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
tegra_fixed_clk_init(tegra124_clks);
tegra124_pll_init(clk_base, pmc_base);
tegra124_periph_clk_init(clk_base, pmc_base);
- tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks, &pll_a_params);
+ tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks,
+ tegra124_audio_plls,
+ ARRAY_SIZE(tegra124_audio_plls));
tegra_pmc_clk_init(pmc_base, tegra124_clks);
/* For Tegra124 & Tegra132, PLLD is the only source for DSIA & DSIB */
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index fad561a5896b..b90db615c29e 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -1405,6 +1405,10 @@ static const struct of_device_id pmc_match[] __initconst = {
{},
};
+static struct tegra_audio_clk_info tegra30_audio_plls[] = {
+ { "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
+};
+
static void __init tegra30_clock_init(struct device_node *np)
{
struct device_node *node;
@@ -1442,7 +1446,9 @@ static void __init tegra30_clock_init(struct device_node *np)
tegra30_pll_init();
tegra30_super_clk_init();
tegra30_periph_clk_init();
- tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks, &pll_a_params);
+ tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks,
+ tegra30_audio_plls,
+ ARRAY_SIZE(tegra30_audio_plls));
tegra_pmc_clk_init(pmc_base, tegra30_clks);
tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX);
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 0621887e06f7..5d2678914160 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -157,7 +157,7 @@ struct div_nmp {
};
/**
- * struct clk_pll_params - PLL parameters
+ * struct tegra_clk_pll_params - PLL parameters
*
* @input_min: Minimum input frequency
* @input_max: Maximum input frequency
@@ -168,9 +168,45 @@ struct div_nmp {
* @base_reg: PLL base reg offset
* @misc_reg: PLL misc reg offset
* @lock_reg: PLL lock reg offset
- * @lock_bit_idx: Bit index for PLL lock status
+ * @lock_mask: Bitmask for PLL lock status
* @lock_enable_bit_idx: Bit index to enable PLL lock
+ * @iddq_reg: PLL IDDQ register offset
+ * @iddq_bit_idx: Bit index to enable PLL IDDQ
+ * @aux_reg: AUX register offset
+ * @dyn_ramp_reg: Dynamic ramp control register offset
+ * @ext_misc_reg: Miscellaneous control register offsets
+ * @pmc_divnm_reg: n, m divider PMC override register offset (PLLM)
+ * @pmc_divp_reg: p divider PMC override register offset (PLLM)
+ * @flags: PLL flags
+ * @stepa_shift: Dynamic ramp step A field shift
+ * @stepb_shift: Dynamic ramp step B field shift
* @lock_delay: Delay in us if PLL lock is not used
+ * @max_p: maximum value for the p divider
+ * @pdiv_tohw: mapping of p divider to register values
+ * @div_nmp: offsets and widths on n, m and p fields
+ * @freq_table: array of frequencies supported by PLL
+ * @fixed_rate: PLL rate if it is fixed
+ *
+ * Flags:
+ * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
+ * PLL locking. If not set it will use lock_delay value to wait.
+ * TEGRA_PLL_HAS_CPCON - This flag indicates that CPCON value needs
+ * to be programmed to change output frequency of the PLL.
+ * TEGRA_PLL_SET_LFCON - This flag indicates that LFCON value needs
+ * to be programmed to change output frequency of the PLL.
+ * TEGRA_PLL_SET_DCCON - This flag indicates that DCCON value needs
+ * to be programmed to change output frequency of the PLL.
+ * TEGRA_PLLU - PLLU has inverted post divider. This flags indicated
+ * that it is PLLU and invert post divider value.
+ * TEGRA_PLLM - PLLM has additional override settings in PMC. This
+ * flag indicates that it is PLLM and use override settings.
+ * TEGRA_PLL_FIXED - We are not supposed to change output frequency
+ * of some plls.
+ * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
+ * TEGRA_PLL_LOCK_MISC - Lock bit is in the misc register instead of the
+ * base register.
+ * TEGRA_PLL_BYPASS - PLL has bypass bit
+ * TEGRA_PLL_HAS_LOCK_ENABLE - PLL has bit to enable lock monitoring
*/
struct tegra_clk_pll_params {
unsigned long input_min;
@@ -203,38 +239,26 @@ struct tegra_clk_pll_params {
unsigned long fixed_rate;
};
+#define TEGRA_PLL_USE_LOCK BIT(0)
+#define TEGRA_PLL_HAS_CPCON BIT(1)
+#define TEGRA_PLL_SET_LFCON BIT(2)
+#define TEGRA_PLL_SET_DCCON BIT(3)
+#define TEGRA_PLLU BIT(4)
+#define TEGRA_PLLM BIT(5)
+#define TEGRA_PLL_FIXED BIT(6)
+#define TEGRA_PLLE_CONFIGURE BIT(7)
+#define TEGRA_PLL_LOCK_MISC BIT(8)
+#define TEGRA_PLL_BYPASS BIT(9)
+#define TEGRA_PLL_HAS_LOCK_ENABLE BIT(10)
+
/**
* struct tegra_clk_pll - Tegra PLL clock
*
* @hw: handle between common and hardware-specifix interfaces
* @clk_base: address of CAR controller
* @pmc: address of PMC, required to read override bits
- * @freq_table: array of frequencies supported by PLL
- * @params: PLL parameters
- * @flags: PLL flags
- * @fixed_rate: PLL rate if it is fixed
* @lock: register lock
- *
- * Flags:
- * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
- * PLL locking. If not set it will use lock_delay value to wait.
- * TEGRA_PLL_HAS_CPCON - This flag indicates that CPCON value needs
- * to be programmed to change output frequency of the PLL.
- * TEGRA_PLL_SET_LFCON - This flag indicates that LFCON value needs
- * to be programmed to change output frequency of the PLL.
- * TEGRA_PLL_SET_DCCON - This flag indicates that DCCON value needs
- * to be programmed to change output frequency of the PLL.
- * TEGRA_PLLU - PLLU has inverted post divider. This flags indicated
- * that it is PLLU and invert post divider value.
- * TEGRA_PLLM - PLLM has additional override settings in PMC. This
- * flag indicates that it is PLLM and use override settings.
- * TEGRA_PLL_FIXED - We are not supposed to change output frequency
- * of some plls.
- * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
- * TEGRA_PLL_LOCK_MISC - Lock bit is in the misc register instead of the
- * base register.
- * TEGRA_PLL_BYPASS - PLL has bypass bit
- * TEGRA_PLL_HAS_LOCK_ENABLE - PLL has bit to enable lock monitoring
+ * @params: PLL parameters
*/
struct tegra_clk_pll {
struct clk_hw hw;
@@ -246,17 +270,20 @@ struct tegra_clk_pll {
#define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw)
-#define TEGRA_PLL_USE_LOCK BIT(0)
-#define TEGRA_PLL_HAS_CPCON BIT(1)
-#define TEGRA_PLL_SET_LFCON BIT(2)
-#define TEGRA_PLL_SET_DCCON BIT(3)
-#define TEGRA_PLLU BIT(4)
-#define TEGRA_PLLM BIT(5)
-#define TEGRA_PLL_FIXED BIT(6)
-#define TEGRA_PLLE_CONFIGURE BIT(7)
-#define TEGRA_PLL_LOCK_MISC BIT(8)
-#define TEGRA_PLL_BYPASS BIT(9)
-#define TEGRA_PLL_HAS_LOCK_ENABLE BIT(10)
+/**
+ * struct tegra_audio_clk_info - Tegra Audio Clk Information
+ *
+ * @name: name for the audio pll
+ * @pll_params: pll_params for audio pll
+ * @clk_id: clk_ids for the audio pll
+ * @parent: name of the parent of the audio pll
+ */
+struct tegra_audio_clk_info {
+ char *name;
+ struct tegra_clk_pll_params *pll_params;
+ int clk_id;
+ char *parent;
+};
extern const struct clk_ops tegra_clk_pll_ops;
extern const struct clk_ops tegra_clk_plle_ops;
@@ -610,7 +637,8 @@ void tegra_register_devclks(struct tegra_devclk *dev_clks, int num);
void tegra_audio_clk_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
- struct tegra_clk_pll_params *pll_params);
+ struct tegra_audio_clk_info *audio_info,
+ unsigned int num_plls);
void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
struct tegra_clk *tegra_clks,
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
index 0204e0861134..69c74eec3a4b 100644
--- a/drivers/clk/tegra/cvb.c
+++ b/drivers/clk/tegra/cvb.c
@@ -78,13 +78,6 @@ static int build_opp_table(const struct cvb_table *d,
if (!table->freq || (table->freq > max_freq))
break;
- /*
- * FIXME after clk_round_rate/clk_determine_rate prototypes
- * have been updated
- */
- if (table->freq & (1<<31))
- continue;
-
dfll_mv = get_cvb_voltage(
speedo_value, d->speedo_scale, &table->coefficients);
dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align);
diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
index 1530c9352a76..fc50b6264bed 100644
--- a/drivers/clk/versatile/Kconfig
+++ b/drivers/clk/versatile/Kconfig
@@ -1,6 +1,6 @@
config COMMON_CLK_VERSATILE
bool "Clock driver for ARM Reference designs"
- depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
+ depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64 || COMPILE_TEST
---help---
Supports clocking on ARM Reference designs:
- Integrator/AP and Integrator/CP
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index a3893ea2199d..08c5ee976879 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -157,8 +157,10 @@ struct clk *icst_clk_register(struct device *dev,
icst->lockreg = base + desc->lock_offset;
clk = clk_register(dev, &icst->hw);
- if (IS_ERR(clk))
+ if (IS_ERR(clk)) {
+ kfree(pclone);
kfree(icst);
+ }
return clk;
}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a7726db13abb..2eb5f0efae90 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,7 +1,16 @@
menu "Clock Source drivers"
+ depends on !ARCH_USES_GETTIMEOFFSET
config CLKSRC_OF
bool
+ select CLKSRC_PROBE
+
+config CLKSRC_ACPI
+ bool
+ select CLKSRC_PROBE
+
+config CLKSRC_PROBE
+ bool
config CLKSRC_I8253
bool
@@ -115,6 +124,14 @@ config CLKSRC_PISTACHIO
bool
select CLKSRC_OF
+config CLKSRC_TI_32K
+ bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
+ depends on GENERIC_SCHED_CLOCK
+ select CLKSRC_OF if OF
+ help
+ This option enables support for Texas Instruments 32.768 Hz clocksource
+ available on many OMAP-like platforms.
+
config CLKSRC_STM32
bool "Clocksource for STM32 SoCs" if !ARCH_STM32
depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
@@ -123,6 +140,7 @@ config CLKSRC_STM32
config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF
+ select CLKSRC_ACPI if ACPI
config ARM_ARCH_TIMER_EVTSTREAM
bool "Support for ARM architected timer event stream generation"
@@ -279,6 +297,10 @@ config CLKSRC_MIPS_GIC
depends on MIPS_GIC
select CLKSRC_OF
+config CLKSRC_TANGO_XTAL
+ bool
+ select CLKSRC_OF
+
config CLKSRC_PXA
def_bool y if ARCH_PXA || ARCH_SA1100
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 5c00863c3e33..56bd16e77ae3 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o
+obj-$(CONFIG_CLKSRC_PROBE) += clksrc-probe.o
obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
@@ -45,6 +45,7 @@ obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o
obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o
obj-$(CONFIG_MTK_TIMER) += mtk_timer.o
obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o
+obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
@@ -56,9 +57,11 @@ obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o
obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o
obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
+obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
obj-$(CONFIG_H8300) += h8300_timer8.o
obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
+obj-$(CONFIG_X86_NUMACHIP) += numachip.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index d6e3e49399dd..c64d543d64bf 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -864,13 +864,5 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
arch_timer_init();
return 0;
}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
- if (acpi_disabled)
- return;
-
- acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
-}
+CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
#endif
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index 29ea50ac366a..a2cb6fae9295 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -60,7 +60,7 @@ static struct clock_event_device __percpu *gt_evt;
* different to the 32-bit upper value read previously, go back to step 2.
* Otherwise the 64-bit timer counter value is correct.
*/
-static u64 gt_counter_read(void)
+static u64 notrace _gt_counter_read(void)
{
u64 counter;
u32 lower;
@@ -79,6 +79,11 @@ static u64 gt_counter_read(void)
return counter;
}
+static u64 gt_counter_read(void)
+{
+ return _gt_counter_read();
+}
+
/**
* To ensure that updates to comparator value register do not set the
* Interrupt Status Register proceed as follows:
@@ -201,7 +206,7 @@ static struct clocksource gt_clocksource = {
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
static u64 notrace gt_sched_clock_read(void)
{
- return gt_counter_read();
+ return _gt_counter_read();
}
#endif
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-probe.c
index 0093a8e49e14..7cb6c923a836 100644
--- a/drivers/clocksource/clksrc-of.c
+++ b/drivers/clocksource/clksrc-probe.c
@@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/clocksource.h>
@@ -23,7 +24,7 @@ extern struct of_device_id __clksrc_of_table[];
static const struct of_device_id __clksrc_of_table_sentinel
__used __section(__clksrc_of_table_end);
-void __init clocksource_of_init(void)
+void __init clocksource_probe(void)
{
struct device_node *np;
const struct of_device_id *match;
@@ -38,6 +39,9 @@ void __init clocksource_of_init(void)
init_func(np);
clocksources++;
}
+
+ clocksources += acpi_probe_device_table(clksrc);
+
if (!clocksources)
pr_crit("%s: no matching clocksources found\n", __func__);
}
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
index 7a97a34dba70..19bb1792d647 100644
--- a/drivers/clocksource/em_sti.c
+++ b/drivers/clocksource/em_sti.c
@@ -228,7 +228,6 @@ static int em_sti_register_clocksource(struct em_sti_priv *p)
{
struct clocksource *cs = &p->cs;
- memset(cs, 0, sizeof(*cs));
cs->name = dev_name(&p->pdev->dev);
cs->rating = 200;
cs->read = em_sti_clocksource_read;
@@ -285,7 +284,6 @@ static void em_sti_register_clockevent(struct em_sti_priv *p)
{
struct clock_event_device *ced = &p->ced;
- memset(ced, 0, sizeof(*ced));
ced->name = dev_name(&p->pdev->dev);
ced->features = CLOCK_EVT_FEAT_ONESHOT;
ced->rating = 200;
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 029f96ab131a..ff44082a0827 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -382,24 +382,28 @@ static void exynos4_mct_tick_start(unsigned long cycles,
static int exynos4_tick_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+ struct mct_clock_event_device *mevt;
+ mevt = container_of(evt, struct mct_clock_event_device, evt);
exynos4_mct_tick_start(cycles, mevt);
-
return 0;
}
static int set_state_shutdown(struct clock_event_device *evt)
{
- exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick));
+ struct mct_clock_event_device *mevt;
+
+ mevt = container_of(evt, struct mct_clock_event_device, evt);
+ exynos4_mct_tick_stop(mevt);
return 0;
}
static int set_state_periodic(struct clock_event_device *evt)
{
- struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+ struct mct_clock_event_device *mevt;
unsigned long cycles_per_jiffy;
+ mevt = container_of(evt, struct mct_clock_event_device, evt);
cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
>> evt->shift);
exynos4_mct_tick_stop(mevt);
diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c
index ef434699c80a..517e1c7624d4 100644
--- a/drivers/clocksource/fsl_ftm_timer.c
+++ b/drivers/clocksource/fsl_ftm_timer.c
@@ -118,7 +118,7 @@ static inline void ftm_reset_counter(void __iomem *base)
ftm_writel(0x00, base + FTM_CNT);
}
-static u64 ftm_read_sched_clock(void)
+static u64 notrace ftm_read_sched_clock(void)
{
return ftm_readl(priv->clksrc_base + FTM_CNT);
}
@@ -203,7 +203,7 @@ static int __init ftm_clockevent_init(unsigned long freq, int irq)
int err;
ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN);
- ftm_writel(~0UL, priv->clkevt_base + FTM_MOD);
+ ftm_writel(~0u, priv->clkevt_base + FTM_MOD);
ftm_reset_counter(priv->clkevt_base);
@@ -230,7 +230,7 @@ static int __init ftm_clocksource_init(unsigned long freq)
int err;
ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN);
- ftm_writel(~0UL, priv->clksrc_base + FTM_MOD);
+ ftm_writel(~0u, priv->clksrc_base + FTM_MOD);
ftm_reset_counter(priv->clksrc_base);
diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c
index 82941c1e9e33..0e076c6fc006 100644
--- a/drivers/clocksource/h8300_timer16.c
+++ b/drivers/clocksource/h8300_timer16.c
@@ -153,7 +153,6 @@ static int timer16_setup(struct timer16_priv *p, struct platform_device *pdev)
int ret, irq;
unsigned int ch;
- memset(p, 0, sizeof(*p));
p->pdev = pdev;
res[REG_CH] = platform_get_resource(p->pdev,
diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c
index f9b3b7033a97..44375d8b9bc4 100644
--- a/drivers/clocksource/h8300_timer8.c
+++ b/drivers/clocksource/h8300_timer8.c
@@ -215,7 +215,6 @@ static int timer8_setup(struct timer8_priv *p,
int irq;
int ret;
- memset(p, 0, sizeof(*p));
p->pdev = pdev;
res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c
index 64195fdd78bf..5487410bfabb 100644
--- a/drivers/clocksource/h8300_tpu.c
+++ b/drivers/clocksource/h8300_tpu.c
@@ -123,7 +123,6 @@ static int __init tpu_setup(struct tpu_priv *p, struct platform_device *pdev)
{
struct resource *res[2];
- memset(p, 0, sizeof(*p));
p->pdev = pdev;
res[CH_L] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_L);
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 02a1945e5093..89d3e4d7900c 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -140,9 +140,10 @@ static cycle_t gic_hpt_read(struct clocksource *cs)
}
static struct clocksource gic_clocksource = {
- .name = "GIC",
- .read = gic_hpt_read,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .name = "GIC",
+ .read = gic_hpt_read,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .archdata = { .vdso_clock_mode = VDSO_CLOCK_GIC },
};
static void __init __gic_clocksource_init(void)
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index 50f0641c65b6..fbfc74685e6a 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -24,6 +24,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
#include <linux/slab.h>
#define GPT_IRQ_EN_REG 0x00
@@ -59,6 +60,13 @@ struct mtk_clock_event_device {
struct clock_event_device dev;
};
+static void __iomem *gpt_sched_reg __read_mostly;
+
+static u64 notrace mtk_read_sched_clock(void)
+{
+ return readl_relaxed(gpt_sched_reg);
+}
+
static inline struct mtk_clock_event_device *to_mtk_clk(
struct clock_event_device *c)
{
@@ -141,14 +149,6 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void mtk_timer_global_reset(struct mtk_clock_event_device *evt)
-{
- /* Disable all interrupts */
- writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
- /* Acknowledge all interrupts */
- writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
-}
-
static void
mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
{
@@ -168,6 +168,12 @@ static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer)
{
u32 val;
+ /* Disable all interrupts */
+ writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
+
+ /* Acknowledge all spurious pending interrupts */
+ writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
+
val = readl(evt->gpt_base + GPT_IRQ_EN_REG);
writel(val | GPT_IRQ_ENABLE(timer),
evt->gpt_base + GPT_IRQ_EN_REG);
@@ -220,8 +226,6 @@ static void __init mtk_timer_init(struct device_node *node)
}
rate = clk_get_rate(clk);
- mtk_timer_global_reset(evt);
-
if (request_irq(evt->dev.irq, mtk_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
pr_warn("failed to setup irq %d\n", evt->dev.irq);
@@ -234,6 +238,8 @@ static void __init mtk_timer_init(struct device_node *node)
mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
node->name, rate, 300, 32, clocksource_mmio_readl_up);
+ gpt_sched_reg = evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC);
+ sched_clock_register(mtk_read_sched_clock, 32, rate);
/* Configure clock event */
mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
diff --git a/drivers/clocksource/numachip.c b/drivers/clocksource/numachip.c
new file mode 100644
index 000000000000..4e0f11fd2617
--- /dev/null
+++ b/drivers/clocksource/numachip.c
@@ -0,0 +1,95 @@
+/*
+ *
+ * Copyright (C) 2015 Numascale AS. All rights reserved.
+ *
+ * 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/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/numachip/numachip.h>
+#include <asm/numachip/numachip_csr.h>
+
+static DEFINE_PER_CPU(struct clock_event_device, numachip2_ced);
+
+static cycles_t numachip2_timer_read(struct clocksource *cs)
+{
+ return numachip2_read64_lcsr(NUMACHIP2_TIMER_NOW);
+}
+
+static struct clocksource numachip2_clocksource = {
+ .name = "numachip2",
+ .rating = 295,
+ .read = numachip2_timer_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .mult = 1,
+ .shift = 0,
+};
+
+static int numachip2_set_next_event(unsigned long delta, struct clock_event_device *ced)
+{
+ numachip2_write64_lcsr(NUMACHIP2_TIMER_DEADLINE + numachip2_timer(),
+ delta);
+ return 0;
+}
+
+static struct clock_event_device numachip2_clockevent = {
+ .name = "numachip2",
+ .rating = 400,
+ .set_next_event = numachip2_set_next_event,
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .mult = 1,
+ .shift = 0,
+ .min_delta_ns = 1250,
+ .max_delta_ns = LONG_MAX,
+};
+
+static void numachip_timer_interrupt(void)
+{
+ struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
+
+ ced->event_handler(ced);
+}
+
+static __init void numachip_timer_each(struct work_struct *work)
+{
+ unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff;
+ struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
+
+ /* Setup IPI vector to local core and relative timing mode */
+ numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(),
+ (3 << 22) | (X86_PLATFORM_IPI_VECTOR << 14) |
+ (local_apicid << 6));
+
+ *ced = numachip2_clockevent;
+ ced->cpumask = cpumask_of(smp_processor_id());
+ clockevents_register_device(ced);
+}
+
+static int __init numachip_timer_init(void)
+{
+ if (numachip_system != 2)
+ return -ENODEV;
+
+ /* Reset timer */
+ numachip2_write64_lcsr(NUMACHIP2_TIMER_RESET, 0);
+ clocksource_register_hz(&numachip2_clocksource, NSEC_PER_SEC);
+
+ /* Setup per-cpu clockevents */
+ x86_platform_ipi_callback = numachip_timer_interrupt;
+ schedule_on_each_cpu(&numachip_timer_each);
+
+ return 0;
+}
+
+arch_initcall(numachip_timer_init);
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index bc90e13338cc..9502bc4c3f6d 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -307,7 +307,7 @@ static void samsung_clocksource_resume(struct clocksource *cs)
samsung_time_start(pwm.source_id, true);
}
-static cycle_t samsung_clocksource_read(struct clocksource *c)
+static cycle_t notrace samsung_clocksource_read(struct clocksource *c)
{
return ~readl_relaxed(pwm.source_reg);
}
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index ba73a6eb8d66..103c49362c68 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -962,7 +962,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
unsigned int i;
int ret;
- memset(cmt, 0, sizeof(*cmt));
cmt->pdev = pdev;
raw_spin_lock_init(&cmt->lock);
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index f1985da8113f..53aa7e92a7d7 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -280,7 +280,9 @@ static int sh_mtu2_clock_event_shutdown(struct clock_event_device *ced)
{
struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced);
- sh_mtu2_disable(ch);
+ if (clockevent_state_periodic(ced))
+ sh_mtu2_disable(ch);
+
return 0;
}
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c
new file mode 100644
index 000000000000..d297b30d2bc0
--- /dev/null
+++ b/drivers/clocksource/tango_xtal.c
@@ -0,0 +1,66 @@
+#include <linux/clocksource.h>
+#include <linux/sched_clock.h>
+#include <linux/of_address.h>
+#include <linux/printk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+static void __iomem *xtal_in_cnt;
+static struct delay_timer delay_timer;
+
+static unsigned long notrace read_xtal_counter(void)
+{
+ return readl_relaxed(xtal_in_cnt);
+}
+
+static u64 notrace read_sched_clock(void)
+{
+ return read_xtal_counter();
+}
+
+static cycle_t read_clocksource(struct clocksource *cs)
+{
+ return read_xtal_counter();
+}
+
+static struct clocksource tango_xtal = {
+ .name = "tango-xtal",
+ .rating = 350,
+ .read = read_clocksource,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init tango_clocksource_init(struct device_node *np)
+{
+ struct clk *clk;
+ int xtal_freq, ret;
+
+ xtal_in_cnt = of_iomap(np, 0);
+ if (xtal_in_cnt == NULL) {
+ pr_err("%s: invalid address\n", np->full_name);
+ return;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ pr_err("%s: invalid clock\n", np->full_name);
+ return;
+ }
+
+ xtal_freq = clk_get_rate(clk);
+ delay_timer.freq = xtal_freq;
+ delay_timer.read_current_timer = read_xtal_counter;
+
+ ret = clocksource_register_hz(&tango_xtal, xtal_freq);
+ if (ret != 0) {
+ pr_err("%s: registration failed\n", np->full_name);
+ return;
+ }
+
+ sched_clock_register(read_sched_clock, 32, xtal_freq);
+ register_current_timer_delay(&delay_timer);
+}
+
+CLOCKSOURCE_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init);
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index d28d2fe798d5..6ee91401918e 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -193,10 +193,17 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
struct clk *t2_clk = tc->clk[2];
int irq = tc->irq[2];
+ ret = clk_prepare_enable(tc->slow_clk);
+ if (ret)
+ return ret;
+
/* try to enable t2 clk to avoid future errors in mode change */
ret = clk_prepare_enable(t2_clk);
- if (ret)
+ if (ret) {
+ clk_disable_unprepare(tc->slow_clk);
return ret;
+ }
+
clk_disable(t2_clk);
clkevt.regs = tc->regs;
@@ -208,7 +215,8 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
ret = request_irq(irq, ch2_irq, IRQF_TIMER, "tc_clkevt", &clkevt);
if (ret) {
- clk_disable_unprepare(t2_clk);
+ clk_unprepare(t2_clk);
+ clk_disable_unprepare(tc->slow_clk);
return ret;
}
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 2162796fd504..d93ec3c4f139 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -45,6 +45,8 @@
#include <linux/percpu.h>
#include <linux/syscore_ops.h>
+#include <asm/delay.h>
+
/*
* Timer block registers.
*/
@@ -249,6 +251,15 @@ struct syscore_ops armada_370_xp_timer_syscore_ops = {
.resume = armada_370_xp_timer_resume,
};
+static unsigned long armada_370_delay_timer_read(void)
+{
+ return ~readl(timer_base + TIMER0_VAL_OFF);
+}
+
+static struct delay_timer armada_370_delay_timer = {
+ .read_current_timer = armada_370_delay_timer_read,
+};
+
static void __init armada_370_xp_timer_common_init(struct device_node *np)
{
u32 clr = 0, set = 0;
@@ -287,6 +298,9 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
TIMER0_RELOAD_EN | enable_mask,
TIMER0_RELOAD_EN | enable_mask);
+ armada_370_delay_timer.freq = timer_clk;
+ register_current_timer_delay(&armada_370_delay_timer);
+
/*
* Set scale and timer for sched_clock.
*/
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index 18d4266c2986..bba679900054 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -67,7 +67,8 @@ static inline void gpt_writel(void __iomem *base, u32 value, u32 offset,
writel(value, base + 0x20 * gpt_id + offset);
}
-static cycle_t pistachio_clocksource_read_cycles(struct clocksource *cs)
+static cycle_t notrace
+pistachio_clocksource_read_cycles(struct clocksource *cs)
{
struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
u32 counter, overflw;
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
index 41b7b6dc1d0d..29d21d68df5a 100644
--- a/drivers/clocksource/timer-atmel-st.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/export.h>
#include <linux/mfd/syscon.h>
@@ -33,9 +34,7 @@ static unsigned long last_crtr;
static u32 irqmask;
static struct clock_event_device clkevt;
static struct regmap *regmap_st;
-
-#define AT91_SLOW_CLOCK 32768
-#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ)
+static int timer_latch;
/*
* The ST_CRTR is updated asynchronously to the master clock ... but
@@ -82,8 +81,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
if (sr & AT91_ST_PITS) {
u32 crtr = read_CRTR();
- while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) {
- last_crtr += RM9200_TIMER_LATCH;
+ while (((crtr - last_crtr) & AT91_ST_CRTV) >= timer_latch) {
+ last_crtr += timer_latch;
clkevt.event_handler(&clkevt);
}
return IRQ_HANDLED;
@@ -144,7 +143,7 @@ static int clkevt32k_set_periodic(struct clock_event_device *dev)
/* PIT for periodic irqs; fixed rate of 1/HZ */
irqmask = AT91_ST_PITS;
- regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
+ regmap_write(regmap_st, AT91_ST_PIMR, timer_latch);
regmap_write(regmap_st, AT91_ST_IER, irqmask);
return 0;
}
@@ -197,7 +196,8 @@ static struct clock_event_device clkevt = {
*/
static void __init atmel_st_timer_init(struct device_node *node)
{
- unsigned int val;
+ struct clk *sclk;
+ unsigned int sclk_rate, val;
int irq, ret;
regmap_st = syscon_node_to_regmap(node);
@@ -221,6 +221,19 @@ static void __init atmel_st_timer_init(struct device_node *node)
if (ret)
panic(pr_fmt("Unable to setup IRQ\n"));
+ sclk = of_clk_get(node, 0);
+ if (IS_ERR(sclk))
+ panic(pr_fmt("Unable to get slow clock\n"));
+
+ clk_prepare_enable(sclk);
+ if (ret)
+ panic(pr_fmt("Could not enable slow clock\n"));
+
+ sclk_rate = clk_get_rate(sclk);
+ if (!sclk_rate)
+ panic(pr_fmt("Invalid slow clock rate\n"));
+ timer_latch = (sclk_rate + HZ / 2) / HZ;
+
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
* directly for the clocksource and all clockevents, after adjusting
* its prescaler from the 1 Hz default.
@@ -229,11 +242,11 @@ static void __init atmel_st_timer_init(struct device_node *node)
/* Setup timer clockevent, with minimum of two ticks (important!!) */
clkevt.cpumask = cpumask_of(0);
- clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
+ clockevents_config_and_register(&clkevt, sclk_rate,
2, AT91_ST_ALMV);
/* register clocksource */
- clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
+ clocksource_register_hz(&clk32k, sclk_rate);
}
CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
atmel_st_timer_init);
diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c
index e73947f0f86d..a536eeb634d8 100644
--- a/drivers/clocksource/timer-digicolor.c
+++ b/drivers/clocksource/timer-digicolor.c
@@ -143,7 +143,7 @@ static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static u64 digicolor_timer_sched_read(void)
+static u64 notrace digicolor_timer_sched_read(void)
{
return ~readl(dc_timer_dev.base + COUNT(TIMER_B));
}
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index 839aba92fc39..99ec96769dda 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -305,13 +305,14 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm)
struct irqaction *act = &imxtm->act;
ced->name = "mxc_timer1";
- ced->features = CLOCK_EVT_FEAT_ONESHOT;
+ ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
ced->set_state_shutdown = mxc_shutdown;
ced->set_state_oneshot = mxc_set_oneshot;
ced->tick_resume = mxc_shutdown;
ced->set_next_event = imxtm->gpt->set_next_event;
ced->rating = 200;
ced->cpumask = cpumask_of(0);
+ ced->irq = imxtm->irq;
clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per),
0xff, 0xfffffffe);
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index 78de982cc640..2854c663e8b5 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -73,7 +73,7 @@ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
}
/* read 64-bit timer counter */
-static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+static cycle_t notrace sirfsoc_timer_read(struct clocksource *cs)
{
u64 cycles;
diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c
new file mode 100644
index 000000000000..8518d9dfba5c
--- /dev/null
+++ b/drivers/clocksource/timer-ti-32k.c
@@ -0,0 +1,126 @@
+/**
+ * timer-ti-32k.c - OMAP2 32k Timer Support
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Update to use new clocksource/clockevent layers
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * Original driver:
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ * Juha Yrjölä <juha.yrjola@nokia.com>
+ * OMAP Dual-mode timer framework support by Timo Teras
+ *
+ * Some parts based off of TI's 24xx code:
+ *
+ * Copyright (C) 2004-2009 Texas Instruments, Inc.
+ *
+ * Roughly modelled after the OMAP1 MPU timer code.
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Copyright (C) 2015 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 version 2 of
+ * the 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/sched_clock.h>
+#include <linux/clocksource.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+/*
+ * 32KHz clocksource ... always available, on pretty most chips except
+ * OMAP 730 and 1510. Other timers could be used as clocksources, with
+ * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
+ * but systems won't necessarily want to spend resources that way.
+ */
+
+#define OMAP2_32KSYNCNT_REV_OFF 0x0
+#define OMAP2_32KSYNCNT_REV_SCHEME (0x3 << 30)
+#define OMAP2_32KSYNCNT_CR_OFF_LOW 0x10
+#define OMAP2_32KSYNCNT_CR_OFF_HIGH 0x30
+
+struct ti_32k {
+ void __iomem *base;
+ void __iomem *counter;
+ struct clocksource cs;
+};
+
+static inline struct ti_32k *to_ti_32k(struct clocksource *cs)
+{
+ return container_of(cs, struct ti_32k, cs);
+}
+
+static cycle_t ti_32k_read_cycles(struct clocksource *cs)
+{
+ struct ti_32k *ti = to_ti_32k(cs);
+
+ return (cycle_t)readl_relaxed(ti->counter);
+}
+
+static struct ti_32k ti_32k_timer = {
+ .cs = {
+ .name = "32k_counter",
+ .rating = 250,
+ .read = ti_32k_read_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS |
+ CLOCK_SOURCE_SUSPEND_NONSTOP,
+ },
+};
+
+static u64 notrace omap_32k_read_sched_clock(void)
+{
+ return ti_32k_read_cycles(&ti_32k_timer.cs);
+}
+
+static void __init ti_32k_timer_init(struct device_node *np)
+{
+ int ret;
+
+ ti_32k_timer.base = of_iomap(np, 0);
+ if (!ti_32k_timer.base) {
+ pr_err("Can't ioremap 32k timer base\n");
+ return;
+ }
+
+ ti_32k_timer.counter = ti_32k_timer.base;
+
+ /*
+ * 32k sync Counter IP register offsets vary between the highlander
+ * version and the legacy ones.
+ *
+ * The 'SCHEME' bits(30-31) of the revision register is used to identify
+ * the version.
+ */
+ if (readl_relaxed(ti_32k_timer.base + OMAP2_32KSYNCNT_REV_OFF) &
+ OMAP2_32KSYNCNT_REV_SCHEME)
+ ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_HIGH;
+ else
+ ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_LOW;
+
+ ret = clocksource_register_hz(&ti_32k_timer.cs, 32768);
+ if (ret) {
+ pr_err("32k_counter: can't register clocksource\n");
+ return;
+ }
+
+ sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
+ pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
+}
+CLOCKSOURCE_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
+ ti_32k_timer_init);
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c
index f07ba9932171..a0e6c68536a1 100644
--- a/drivers/clocksource/vf_pit_timer.c
+++ b/drivers/clocksource/vf_pit_timer.c
@@ -52,7 +52,7 @@ static inline void pit_irq_acknowledge(void)
__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
}
-static u64 pit_read_sched_clock(void)
+static u64 notrace pit_read_sched_clock(void)
{
return ~__raw_readl(clksrc_base + PITCVAL);
}
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 30f522848c73..d7373ca69c99 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -124,7 +124,8 @@ int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group,
if (group)
return netlink_broadcast(dev->nls, skb, portid, group,
gfp_mask);
- return netlink_unicast(dev->nls, skb, portid, !(gfp_mask&__GFP_WAIT));
+ return netlink_unicast(dev->nls, skb, portid,
+ !gfpflags_allow_blocking(gfp_mask));
}
EXPORT_SYMBOL_GPL(cn_netlink_send_mult);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index cd0391e46c6d..8014c2307332 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -84,6 +84,7 @@ config ARM_KIRKWOOD_CPUFREQ
config ARM_MT8173_CPUFREQ
bool "Mediatek MT8173 CPUFreq support"
depends on ARCH_MEDIATEK && REGULATOR
+ depends on ARM64 || (ARM_CPU_TOPOLOGY && COMPILE_TEST)
depends on !CPU_THERMAL || THERMAL=y
select PM_OPP
help
@@ -199,6 +200,16 @@ config ARM_SA1100_CPUFREQ
config ARM_SA1110_CPUFREQ
bool
+config ARM_SCPI_CPUFREQ
+ tristate "SCPI based CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL
+ help
+ This adds the CPUfreq driver support for ARM big.LITTLE platforms
+ using SCPI protocol for CPU power management.
+
+ This driver uses SCPI Message Protocol driver to interact with the
+ firmware providing the CPU DVFS functionality.
+
config ARM_SPEAR_CPUFREQ
bool "SPEAr CPUFreq support"
depends on PLAT_SPEAR
@@ -227,3 +238,20 @@ config ARM_PXA2xx_CPUFREQ
This add the CPUFreq driver support for Intel PXA2xx SOCs.
If in doubt, say N.
+
+config ACPI_CPPC_CPUFREQ
+ tristate "CPUFreq driver based on the ACPI CPPC spec"
+ depends on ACPI
+ select ACPI_CPPC_LIB
+ default n
+ help
+ This adds a CPUFreq driver which uses CPPC methods
+ as described in the ACPIv5.1 spec. CPPC stands for
+ Collaborative Processor Performance Controls. It
+ is based on an abstract continuous scale of CPU
+ performance values which allows the remote power
+ processor to flexibly optimize for power and
+ performance. CPPC relies on power management firmware
+ support for its operation.
+
+ If in doubt, say N.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 41340384f11f..c0af1a1281c8 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -1,6 +1,5 @@
# CPUfreq core
obj-$(CONFIG_CPU_FREQ) += cpufreq.o freq_table.o
-obj-$(CONFIG_PM_OPP) += cpufreq_opp.o
# CPUfreq stats
obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o
@@ -72,10 +71,13 @@ obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
+obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o
obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
+obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
+
##################################################################################
# PowerPC platform drivers
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index f1e42f8ce0fc..c5d256caa664 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -149,6 +149,19 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
__func__, cpu, old_cluster, new_cluster, new_rate);
ret = clk_set_rate(clk[new_cluster], new_rate * 1000);
+ if (!ret) {
+ /*
+ * FIXME: clk_set_rate hasn't returned an error here however it
+ * may be that clk_change_rate failed due to hardware or
+ * firmware issues and wasn't able to report that due to the
+ * current design of the clk core layer. To work around this
+ * problem we will read back the clock rate and check it is
+ * correct. This needs to be removed once clk core is fixed.
+ */
+ if (clk_get_rate(clk[new_cluster]) != new_rate * 1000)
+ ret = -EIO;
+ }
+
if (WARN_ON(ret)) {
pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
new_cluster);
@@ -189,15 +202,6 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
mutex_unlock(&cluster_lock[old_cluster]);
}
- /*
- * FIXME: clk_set_rate has to handle the case where clk_change_rate
- * can fail due to hardware or firmware issues. Until the clk core
- * layer is fixed, we can check here. In most of the cases we will
- * be reading only the cached value anyway. This needs to be removed
- * once clk core is fixed.
- */
- if (bL_cpufreq_get_rate(cpu) != new_rate)
- return -EIO;
return 0;
}
diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h
index a211f7db9d32..b88889d9387e 100644
--- a/drivers/cpufreq/arm_big_little.h
+++ b/drivers/cpufreq/arm_big_little.h
@@ -28,7 +28,7 @@ struct cpufreq_arm_bL_ops {
/*
* This must set opp table for cpu_dev in a similar way as done by
- * of_init_opp_table().
+ * dev_pm_opp_of_add_table().
*/
int (*init_opp_table)(struct device *cpu_dev);
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index 36d91dba2965..16ddeefe9443 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -54,7 +54,7 @@ static int dt_init_opp_table(struct device *cpu_dev)
return -ENOENT;
}
- ret = of_init_opp_table(cpu_dev);
+ ret = dev_pm_opp_of_add_table(cpu_dev);
of_node_put(np);
return ret;
@@ -82,7 +82,7 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = {
.name = "dt-bl",
.get_transition_latency = dt_get_transition_latency,
.init_opp_table = dt_init_opp_table,
- .free_opp_table = of_free_opp_table,
+ .free_opp_table = dev_pm_opp_of_remove_table,
};
static int generic_bL_probe(struct platform_device *pdev)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
new file mode 100644
index 000000000000..e8cb334094b0
--- /dev/null
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -0,0 +1,175 @@
+/*
+ * CPPC (Collaborative Processor Performance Control) driver for
+ * interfacing with the CPUfreq layer and governors. See
+ * cppc_acpi.c for CPPC specific methods.
+ *
+ * (C) Copyright 2014, 2015 Linaro Ltd.
+ * Author: Ashwin Chaugule <ashwin.chaugule@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#define pr_fmt(fmt) "CPPC Cpufreq:" fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/vmalloc.h>
+
+#include <acpi/cppc_acpi.h>
+
+/*
+ * These structs contain information parsed from per CPU
+ * ACPI _CPC structures.
+ * e.g. For each CPU the highest, lowest supported
+ * performance capabilities, desired performance level
+ * requested etc.
+ */
+static struct cpudata **all_cpu_data;
+
+static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpudata *cpu;
+ struct cpufreq_freqs freqs;
+ int ret = 0;
+
+ cpu = all_cpu_data[policy->cpu];
+
+ cpu->perf_ctrls.desired_perf = target_freq;
+ freqs.old = policy->cur;
+ freqs.new = target_freq;
+
+ cpufreq_freq_transition_begin(policy, &freqs);
+ ret = cppc_set_perf(cpu->cpu, &cpu->perf_ctrls);
+ cpufreq_freq_transition_end(policy, &freqs, ret != 0);
+
+ if (ret)
+ pr_debug("Failed to set target on CPU:%d. ret:%d\n",
+ cpu->cpu, ret);
+
+ return ret;
+}
+
+static int cppc_verify_policy(struct cpufreq_policy *policy)
+{
+ cpufreq_verify_within_cpu_limits(policy);
+ return 0;
+}
+
+static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy)
+{
+ int cpu_num = policy->cpu;
+ struct cpudata *cpu = all_cpu_data[cpu_num];
+ int ret;
+
+ cpu->perf_ctrls.desired_perf = cpu->perf_caps.lowest_perf;
+
+ ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls);
+ if (ret)
+ pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
+ cpu->perf_caps.lowest_perf, cpu_num, ret);
+}
+
+static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ struct cpudata *cpu;
+ unsigned int cpu_num = policy->cpu;
+ int ret = 0;
+
+ cpu = all_cpu_data[policy->cpu];
+
+ cpu->cpu = cpu_num;
+ ret = cppc_get_perf_caps(policy->cpu, &cpu->perf_caps);
+
+ if (ret) {
+ pr_debug("Err reading CPU%d perf capabilities. ret:%d\n",
+ cpu_num, ret);
+ return ret;
+ }
+
+ policy->min = cpu->perf_caps.lowest_perf;
+ policy->max = cpu->perf_caps.highest_perf;
+ policy->cpuinfo.min_freq = policy->min;
+ policy->cpuinfo.max_freq = policy->max;
+
+ if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+ cpumask_copy(policy->cpus, cpu->shared_cpu_map);
+ else {
+ /* Support only SW_ANY for now. */
+ pr_debug("Unsupported CPU co-ord type\n");
+ return -EFAULT;
+ }
+
+ cpumask_set_cpu(policy->cpu, policy->cpus);
+ cpu->cur_policy = policy;
+
+ /* Set policy->cur to max now. The governors will adjust later. */
+ policy->cur = cpu->perf_ctrls.desired_perf = cpu->perf_caps.highest_perf;
+
+ ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls);
+ if (ret)
+ pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
+ cpu->perf_caps.highest_perf, cpu_num, ret);
+
+ return ret;
+}
+
+static struct cpufreq_driver cppc_cpufreq_driver = {
+ .flags = CPUFREQ_CONST_LOOPS,
+ .verify = cppc_verify_policy,
+ .target = cppc_cpufreq_set_target,
+ .init = cppc_cpufreq_cpu_init,
+ .stop_cpu = cppc_cpufreq_stop_cpu,
+ .name = "cppc_cpufreq",
+};
+
+static int __init cppc_cpufreq_init(void)
+{
+ int i, ret = 0;
+ struct cpudata *cpu;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ all_cpu_data = kzalloc(sizeof(void *) * num_possible_cpus(), GFP_KERNEL);
+ if (!all_cpu_data)
+ return -ENOMEM;
+
+ for_each_possible_cpu(i) {
+ all_cpu_data[i] = kzalloc(sizeof(struct cpudata), GFP_KERNEL);
+ if (!all_cpu_data[i])
+ goto out;
+
+ cpu = all_cpu_data[i];
+ if (!zalloc_cpumask_var(&cpu->shared_cpu_map, GFP_KERNEL))
+ goto out;
+ }
+
+ ret = acpi_get_psd_map(all_cpu_data);
+ if (ret) {
+ pr_debug("Error parsing PSD data. Aborting cpufreq registration.\n");
+ goto out;
+ }
+
+ ret = cpufreq_register_driver(&cppc_cpufreq_driver);
+ if (ret)
+ goto out;
+
+ return ret;
+
+out:
+ for_each_possible_cpu(i)
+ kfree(all_cpu_data[i]);
+
+ kfree(all_cpu_data);
+ return -ENODEV;
+}
+
+late_initcall(cppc_cpufreq_init);
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 7c0d70e2a861..90d64081ddb3 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -216,7 +216,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
}
/* Get OPP-sharing information from "operating-points-v2" bindings */
- ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus);
+ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus);
if (ret) {
/*
* operating-points-v2 not supported, fallback to old method of
@@ -238,7 +238,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
*
* OPPs might be populated at runtime, don't check for error here
*/
- of_cpumask_init_opp_table(policy->cpus);
+ dev_pm_opp_of_cpumask_add_table(policy->cpus);
/*
* But we need OPP table to function so if it is not there let's
@@ -261,7 +261,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
* OPP tables are initialized only for policy->cpu, do it for
* others as well.
*/
- ret = set_cpus_sharing_opps(cpu_dev, policy->cpus);
+ ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
if (ret)
dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
__func__, ret);
@@ -368,7 +368,7 @@ out_free_cpufreq_table:
out_free_priv:
kfree(priv);
out_free_opp:
- of_cpumask_free_opp_table(policy->cpus);
+ dev_pm_opp_of_cpumask_remove_table(policy->cpus);
out_node_put:
of_node_put(np);
out_put_reg_clk:
@@ -385,7 +385,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
- of_cpumask_free_opp_table(policy->related_cpus);
+ dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
clk_put(policy->clk);
if (!IS_ERR(priv->cpu_reg))
regulator_put(priv->cpu_reg);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 25c4c15103a0..7c48e7316d91 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -843,18 +843,11 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
down_write(&policy->rwsem);
- /* Updating inactive policies is invalid, so avoid doing that. */
- if (unlikely(policy_is_inactive(policy))) {
- ret = -EBUSY;
- goto unlock_policy_rwsem;
- }
-
if (fattr->store)
ret = fattr->store(policy, buf, count);
else
ret = -EIO;
-unlock_policy_rwsem:
up_write(&policy->rwsem);
unlock:
put_online_cpus();
@@ -880,49 +873,6 @@ static struct kobj_type ktype_cpufreq = {
.release = cpufreq_sysfs_release,
};
-struct kobject *cpufreq_global_kobject;
-EXPORT_SYMBOL(cpufreq_global_kobject);
-
-static int cpufreq_global_kobject_usage;
-
-int cpufreq_get_global_kobject(void)
-{
- if (!cpufreq_global_kobject_usage++)
- return kobject_add(cpufreq_global_kobject,
- &cpu_subsys.dev_root->kobj, "%s", "cpufreq");
-
- return 0;
-}
-EXPORT_SYMBOL(cpufreq_get_global_kobject);
-
-void cpufreq_put_global_kobject(void)
-{
- if (!--cpufreq_global_kobject_usage)
- kobject_del(cpufreq_global_kobject);
-}
-EXPORT_SYMBOL(cpufreq_put_global_kobject);
-
-int cpufreq_sysfs_create_file(const struct attribute *attr)
-{
- int ret = cpufreq_get_global_kobject();
-
- if (!ret) {
- ret = sysfs_create_file(cpufreq_global_kobject, attr);
- if (ret)
- cpufreq_put_global_kobject();
- }
-
- return ret;
-}
-EXPORT_SYMBOL(cpufreq_sysfs_create_file);
-
-void cpufreq_sysfs_remove_file(const struct attribute *attr)
-{
- sysfs_remove_file(cpufreq_global_kobject, attr);
- cpufreq_put_global_kobject();
-}
-EXPORT_SYMBOL(cpufreq_sysfs_remove_file);
-
static int add_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu)
{
struct device *cpu_dev;
@@ -960,9 +910,6 @@ static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy)
/* Some related CPUs might not be present (physically hotplugged) */
for_each_cpu(j, policy->real_cpus) {
- if (j == policy->kobj_cpu)
- continue;
-
ret = add_cpu_dev_symlink(policy, j);
if (ret)
break;
@@ -976,12 +923,8 @@ static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy)
unsigned int j;
/* Some related CPUs might not be present (physically hotplugged) */
- for_each_cpu(j, policy->real_cpus) {
- if (j == policy->kobj_cpu)
- continue;
-
+ for_each_cpu(j, policy->real_cpus)
remove_cpu_dev_symlink(policy, j);
- }
}
static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
@@ -1079,7 +1022,6 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
{
struct device *dev = get_cpu_device(cpu);
struct cpufreq_policy *policy;
- int ret;
if (WARN_ON(!dev))
return NULL;
@@ -1097,13 +1039,7 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
goto err_free_rcpumask;
- ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &dev->kobj,
- "cpufreq");
- if (ret) {
- pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
- goto err_free_real_cpus;
- }
-
+ kobject_init(&policy->kobj, &ktype_cpufreq);
INIT_LIST_HEAD(&policy->policy_list);
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
@@ -1112,14 +1048,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
INIT_WORK(&policy->update, handle_update);
policy->cpu = cpu;
-
- /* Set this once on allocation */
- policy->kobj_cpu = cpu;
-
return policy;
-err_free_real_cpus:
- free_cpumask_var(policy->real_cpus);
err_free_rcpumask:
free_cpumask_var(policy->related_cpus);
err_free_cpumask:
@@ -1221,9 +1151,19 @@ static int cpufreq_online(unsigned int cpu)
if (new_policy) {
/* related_cpus should at least include policy->cpus. */
- cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
+ cpumask_copy(policy->related_cpus, policy->cpus);
/* Remember CPUs present at the policy creation time. */
cpumask_and(policy->real_cpus, policy->cpus, cpu_present_mask);
+
+ /* Name and add the kobject */
+ ret = kobject_add(&policy->kobj, cpufreq_global_kobject,
+ "policy%u",
+ cpumask_first(policy->related_cpus));
+ if (ret) {
+ pr_err("%s: failed to add policy->kobj: %d\n", __func__,
+ ret);
+ goto out_exit_policy;
+ }
}
/*
@@ -1467,22 +1407,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
return;
}
- if (cpu != policy->kobj_cpu) {
- remove_cpu_dev_symlink(policy, cpu);
- } else {
- /*
- * The CPU owning the policy object is going away. Move it to
- * another suitable CPU.
- */
- unsigned int new_cpu = cpumask_first(policy->real_cpus);
- struct device *new_dev = get_cpu_device(new_cpu);
-
- dev_dbg(dev, "%s: Moving policy object to CPU%u\n", __func__, new_cpu);
-
- sysfs_remove_link(&new_dev->kobj, "cpufreq");
- policy->kobj_cpu = new_cpu;
- WARN_ON(kobject_move(&policy->kobj, &new_dev->kobj));
- }
+ remove_cpu_dev_symlink(policy, cpu);
}
static void handle_update(struct work_struct *work)
@@ -2425,7 +2350,7 @@ static int create_boost_sysfs_file(void)
if (!cpufreq_driver->set_boost)
cpufreq_driver->set_boost = cpufreq_boost_set_sw;
- ret = cpufreq_sysfs_create_file(&boost.attr);
+ ret = sysfs_create_file(cpufreq_global_kobject, &boost.attr);
if (ret)
pr_err("%s: cannot register global BOOST sysfs file\n",
__func__);
@@ -2436,7 +2361,7 @@ static int create_boost_sysfs_file(void)
static void remove_boost_sysfs_file(void)
{
if (cpufreq_boost_supported())
- cpufreq_sysfs_remove_file(&boost.attr);
+ sysfs_remove_file(cpufreq_global_kobject, &boost.attr);
}
int cpufreq_enable_boost_support(void)
@@ -2584,12 +2509,15 @@ static struct syscore_ops cpufreq_syscore_ops = {
.shutdown = cpufreq_suspend,
};
+struct kobject *cpufreq_global_kobject;
+EXPORT_SYMBOL(cpufreq_global_kobject);
+
static int __init cpufreq_core_init(void)
{
if (cpufreq_disabled())
return -ENODEV;
- cpufreq_global_kobject = kobject_create();
+ cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
BUG_ON(!cpufreq_global_kobject);
register_syscore_ops(&cpufreq_syscore_ops);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 84a1506950a7..1fa1deb6e91f 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -23,6 +23,19 @@
static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
+static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
+ unsigned int event);
+
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
+static
+#endif
+struct cpufreq_governor cpufreq_gov_conservative = {
+ .name = "conservative",
+ .governor = cs_cpufreq_governor_dbs,
+ .max_transition_latency = TRANSITION_LATENCY_LIMIT,
+ .owner = THIS_MODULE,
+};
+
static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
struct cpufreq_policy *policy)
{
@@ -119,12 +132,14 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
struct cpufreq_freqs *freq = data;
struct cs_cpu_dbs_info_s *dbs_info =
&per_cpu(cs_cpu_dbs_info, freq->cpu);
- struct cpufreq_policy *policy;
+ struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
- if (!dbs_info->enable)
+ if (!policy)
return 0;
- policy = dbs_info->cdbs.shared->policy;
+ /* policy isn't governed by conservative governor */
+ if (policy->governor != &cpufreq_gov_conservative)
+ return 0;
/*
* we only care if our internally tracked freq moves outside the 'valid'
@@ -367,16 +382,6 @@ static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
return cpufreq_governor_dbs(policy, &cs_dbs_cdata, event);
}
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
-static
-#endif
-struct cpufreq_governor cpufreq_gov_conservative = {
- .name = "conservative",
- .governor = cs_cpufreq_governor_dbs,
- .max_transition_latency = TRANSITION_LATENCY_LIMIT,
- .owner = THIS_MODULE,
-};
-
static int __init cpufreq_gov_dbs_init(void)
{
return cpufreq_register_governor(&cpufreq_gov_conservative);
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 939197ffa4ac..b260576ddb12 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -171,10 +171,6 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
{
int i;
- mutex_lock(&cpufreq_governor_lock);
- if (!policy->governor_enabled)
- goto out_unlock;
-
if (!all_cpus) {
/*
* Use raw_smp_processor_id() to avoid preemptible warnings.
@@ -188,9 +184,6 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
for_each_cpu(i, policy->cpus)
__gov_queue_work(i, dbs_data, delay);
}
-
-out_unlock:
- mutex_unlock(&cpufreq_governor_lock);
}
EXPORT_SYMBOL_GPL(gov_queue_work);
@@ -229,13 +222,24 @@ static void dbs_timer(struct work_struct *work)
struct cpu_dbs_info *cdbs = container_of(work, struct cpu_dbs_info,
dwork.work);
struct cpu_common_dbs_info *shared = cdbs->shared;
- struct cpufreq_policy *policy = shared->policy;
- struct dbs_data *dbs_data = policy->governor_data;
+ struct cpufreq_policy *policy;
+ struct dbs_data *dbs_data;
unsigned int sampling_rate, delay;
bool modify_all = true;
mutex_lock(&shared->timer_mutex);
+ policy = shared->policy;
+
+ /*
+ * Governor might already be disabled and there is no point continuing
+ * with the work-handler.
+ */
+ if (!policy)
+ goto unlock;
+
+ dbs_data = policy->governor_data;
+
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
@@ -252,6 +256,7 @@ static void dbs_timer(struct work_struct *work)
delay = dbs_data->cdata->gov_dbs_timer(cdbs, dbs_data, modify_all);
gov_queue_work(dbs_data, policy, delay, modify_all);
+unlock:
mutex_unlock(&shared->timer_mutex);
}
@@ -348,29 +353,21 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
latency * LATENCY_MULTIPLIER));
- if (!have_governor_per_policy()) {
- if (WARN_ON(cpufreq_get_global_kobject())) {
- ret = -EINVAL;
- goto cdata_exit;
- }
+ if (!have_governor_per_policy())
cdata->gdbs_data = dbs_data;
- }
ret = sysfs_create_group(get_governor_parent_kobj(policy),
get_sysfs_attr(dbs_data));
if (ret)
- goto put_kobj;
+ goto reset_gdbs_data;
policy->governor_data = dbs_data;
return 0;
-put_kobj:
- if (!have_governor_per_policy()) {
+reset_gdbs_data:
+ if (!have_governor_per_policy())
cdata->gdbs_data = NULL;
- cpufreq_put_global_kobject();
- }
-cdata_exit:
cdata->exit(dbs_data, !policy->governor->initialized);
free_common_dbs_info:
free_common_dbs_info(policy, cdata);
@@ -394,10 +391,8 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy,
sysfs_remove_group(get_governor_parent_kobj(policy),
get_sysfs_attr(dbs_data));
- if (!have_governor_per_policy()) {
+ if (!have_governor_per_policy())
cdata->gdbs_data = NULL;
- cpufreq_put_global_kobject();
- }
cdata->exit(dbs_data, policy->governor->initialized == 1);
kfree(dbs_data);
@@ -463,7 +458,6 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
cdata->get_cpu_dbs_info_s(cpu);
cs_dbs_info->down_skip = 0;
- cs_dbs_info->enable = 1;
cs_dbs_info->requested_freq = policy->cur;
} else {
struct od_ops *od_ops = cdata->gov_ops;
@@ -482,25 +476,24 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
static int cpufreq_governor_stop(struct cpufreq_policy *policy,
struct dbs_data *dbs_data)
{
- struct common_dbs_data *cdata = dbs_data->cdata;
- unsigned int cpu = policy->cpu;
- struct cpu_dbs_info *cdbs = cdata->get_cpu_cdbs(cpu);
+ struct cpu_dbs_info *cdbs = dbs_data->cdata->get_cpu_cdbs(policy->cpu);
struct cpu_common_dbs_info *shared = cdbs->shared;
/* State should be equivalent to START */
if (!shared || !shared->policy)
return -EBUSY;
- gov_cancel_work(dbs_data, policy);
-
- if (cdata->governor == GOV_CONSERVATIVE) {
- struct cs_cpu_dbs_info_s *cs_dbs_info =
- cdata->get_cpu_dbs_info_s(cpu);
+ /*
+ * Work-handler must see this updated, as it should not proceed any
+ * further after governor is disabled. And so timer_mutex is taken while
+ * updating this value.
+ */
+ mutex_lock(&shared->timer_mutex);
+ shared->policy = NULL;
+ mutex_unlock(&shared->timer_mutex);
- cs_dbs_info->enable = 0;
- }
+ gov_cancel_work(dbs_data, policy);
- shared->policy = NULL;
mutex_destroy(&shared->timer_mutex);
return 0;
}
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 50f171796632..5621bb03e874 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -170,7 +170,6 @@ struct cs_cpu_dbs_info_s {
struct cpu_dbs_info cdbs;
unsigned int down_skip;
unsigned int requested_freq;
- unsigned int enable:1;
};
/* Per policy Governors sysfs tunables */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 1fa9088c84a8..03ac6ce54042 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -267,27 +267,19 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
cpufreq_cpu_put(policy);
- mutex_lock(&dbs_info->cdbs.shared->timer_mutex);
-
- if (!delayed_work_pending(&dbs_info->cdbs.dwork)) {
- mutex_unlock(&dbs_info->cdbs.shared->timer_mutex);
+ if (!delayed_work_pending(&dbs_info->cdbs.dwork))
continue;
- }
next_sampling = jiffies + usecs_to_jiffies(new_rate);
appointed_at = dbs_info->cdbs.dwork.timer.expires;
if (time_before(next_sampling, appointed_at)) {
-
- mutex_unlock(&dbs_info->cdbs.shared->timer_mutex);
cancel_delayed_work_sync(&dbs_info->cdbs.dwork);
- mutex_lock(&dbs_info->cdbs.shared->timer_mutex);
gov_queue_work(dbs_data, policy,
usecs_to_jiffies(new_rate), true);
}
- mutex_unlock(&dbs_info->cdbs.shared->timer_mutex);
}
}
diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c
deleted file mode 100644
index 0f5e6d5f6da0..000000000000
--- a/drivers/cpufreq/cpufreq_opp.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Generic OPP helper interface for CPUFreq drivers
- *
- * Copyright (C) 2009-2014 Texas Instruments Incorporated.
- * Nishanth Menon
- * Romit Dasgupta
- * Kevin Hilman
- *
- * 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/cpufreq.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/pm_opp.h>
-#include <linux/rcupdate.h>
-#include <linux/slab.h>
-
-/**
- * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
- * @dev: device for which we do this operation
- * @table: Cpufreq table returned back to caller
- *
- * Generate a cpufreq table for a provided device- this assumes that the
- * opp list is already initialized and ready for usage.
- *
- * This function allocates required memory for the cpufreq table. It is
- * expected that the caller does the required maintenance such as freeing
- * the table as required.
- *
- * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
- * if no memory available for the operation (table is not populated), returns 0
- * if successful and table is populated.
- *
- * WARNING: It is important for the callers to ensure refreshing their copy of
- * the table if any of the mentioned functions have been invoked in the interim.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Since we just use the regular accessor functions to access the internal data
- * structures, we use RCU read lock inside this function. As a result, users of
- * this function DONOT need to use explicit locks for invoking.
- */
-int dev_pm_opp_init_cpufreq_table(struct device *dev,
- struct cpufreq_frequency_table **table)
-{
- struct dev_pm_opp *opp;
- struct cpufreq_frequency_table *freq_table = NULL;
- int i, max_opps, ret = 0;
- unsigned long rate;
-
- rcu_read_lock();
-
- max_opps = dev_pm_opp_get_opp_count(dev);
- if (max_opps <= 0) {
- ret = max_opps ? max_opps : -ENODATA;
- goto out;
- }
-
- freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
- if (!freq_table) {
- ret = -ENOMEM;
- goto out;
- }
-
- for (i = 0, rate = 0; i < max_opps; i++, rate++) {
- /* find next rate */
- opp = dev_pm_opp_find_freq_ceil(dev, &rate);
- if (IS_ERR(opp)) {
- ret = PTR_ERR(opp);
- goto out;
- }
- freq_table[i].driver_data = i;
- freq_table[i].frequency = rate / 1000;
-
- /* Is Boost/turbo opp ? */
- if (dev_pm_opp_is_turbo(opp))
- freq_table[i].flags = CPUFREQ_BOOST_FREQ;
- }
-
- freq_table[i].driver_data = i;
- freq_table[i].frequency = CPUFREQ_TABLE_END;
-
- *table = &freq_table[0];
-
-out:
- rcu_read_unlock();
- if (ret)
- kfree(freq_table);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
-
-/**
- * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
- * @dev: device for which we do this operation
- * @table: table to free
- *
- * Free up the table allocated by dev_pm_opp_init_cpufreq_table
- */
-void dev_pm_opp_free_cpufreq_table(struct device *dev,
- struct cpufreq_frequency_table **table)
-{
- if (!table)
- return;
-
- kfree(*table);
- *table = NULL;
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
index 21a90ed7f3d8..c0f3373706f4 100644
--- a/drivers/cpufreq/exynos5440-cpufreq.c
+++ b/drivers/cpufreq/exynos5440-cpufreq.c
@@ -360,7 +360,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
goto err_put_node;
}
- ret = of_init_opp_table(dvfs_info->dev);
+ ret = dev_pm_opp_of_add_table(dvfs_info->dev);
if (ret) {
dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret);
goto err_put_node;
@@ -424,7 +424,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
err_free_table:
dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
err_free_opp:
- of_free_opp_table(dvfs_info->dev);
+ dev_pm_opp_of_remove_table(dvfs_info->dev);
err_put_node:
of_node_put(np);
dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
@@ -435,7 +435,7 @@ static int exynos_cpufreq_remove(struct platform_device *pdev)
{
cpufreq_unregister_driver(&exynos_driver);
dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
- of_free_opp_table(dvfs_info->dev);
+ dev_pm_opp_of_remove_table(dvfs_info->dev);
return 0;
}
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 380a90d3c57e..ef1fa8145419 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -30,6 +30,10 @@ static struct clk *pll1_sw_clk;
static struct clk *step_clk;
static struct clk *pll2_pfd2_396m_clk;
+/* clk used by i.MX6UL */
+static struct clk *pll2_bus_clk;
+static struct clk *secondary_sel_clk;
+
static struct device *cpu_dev;
static bool free_opp;
static struct cpufreq_frequency_table *freq_table;
@@ -91,16 +95,36 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
* The setpoints are selected per PLL/PDF frequencies, so we need to
* reprogram PLL for frequency scaling. The procedure of reprogramming
* PLL1 is as below.
- *
+ * For i.MX6UL, it has a secondary clk mux, the cpu frequency change
+ * flow is slightly different from other i.MX6 OSC.
+ * The cpu frequeny change flow for i.MX6(except i.MX6UL) is as below:
* - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it
* - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
* - Disable pll2_pfd2_396m_clk
*/
- clk_set_parent(step_clk, pll2_pfd2_396m_clk);
- clk_set_parent(pll1_sw_clk, step_clk);
- if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
- clk_set_rate(pll1_sys_clk, new_freq * 1000);
+ if (of_machine_is_compatible("fsl,imx6ul")) {
+ /*
+ * When changing pll1_sw_clk's parent to pll1_sys_clk,
+ * CPU may run at higher than 528MHz, this will lead to
+ * the system unstable if the voltage is lower than the
+ * voltage of 528MHz, so lower the CPU frequency to one
+ * half before changing CPU frequency.
+ */
+ clk_set_rate(arm_clk, (old_freq >> 1) * 1000);
clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+ if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk))
+ clk_set_parent(secondary_sel_clk, pll2_bus_clk);
+ else
+ clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk);
+ clk_set_parent(step_clk, secondary_sel_clk);
+ clk_set_parent(pll1_sw_clk, step_clk);
+ } else {
+ clk_set_parent(step_clk, pll2_pfd2_396m_clk);
+ clk_set_parent(pll1_sw_clk, step_clk);
+ if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
+ clk_set_rate(pll1_sys_clk, new_freq * 1000);
+ clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+ }
}
/* Ensure the arm clock divider is what we expect */
@@ -186,6 +210,16 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
goto put_clk;
}
+ if (of_machine_is_compatible("fsl,imx6ul")) {
+ pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
+ secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
+ if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
+ dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
+ ret = -ENOENT;
+ goto put_clk;
+ }
+ }
+
arm_reg = regulator_get(cpu_dev, "arm");
pu_reg = regulator_get_optional(cpu_dev, "pu");
soc_reg = regulator_get(cpu_dev, "soc");
@@ -202,7 +236,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
*/
num = dev_pm_opp_get_opp_count(cpu_dev);
if (num < 0) {
- ret = of_init_opp_table(cpu_dev);
+ ret = dev_pm_opp_of_add_table(cpu_dev);
if (ret < 0) {
dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
goto put_reg;
@@ -312,7 +346,7 @@ free_freq_table:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_opp:
if (free_opp)
- of_free_opp_table(cpu_dev);
+ dev_pm_opp_of_remove_table(cpu_dev);
put_reg:
if (!IS_ERR(arm_reg))
regulator_put(arm_reg);
@@ -331,6 +365,10 @@ put_clk:
clk_put(step_clk);
if (!IS_ERR(pll2_pfd2_396m_clk))
clk_put(pll2_pfd2_396m_clk);
+ if (!IS_ERR(pll2_bus_clk))
+ clk_put(pll2_bus_clk);
+ if (!IS_ERR(secondary_sel_clk))
+ clk_put(secondary_sel_clk);
of_node_put(np);
return ret;
}
@@ -340,7 +378,7 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
if (free_opp)
- of_free_opp_table(cpu_dev);
+ dev_pm_opp_of_remove_table(cpu_dev);
regulator_put(arm_reg);
if (!IS_ERR(pu_reg))
regulator_put(pu_reg);
@@ -350,6 +388,8 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
clk_put(pll1_sw_clk);
clk_put(step_clk);
clk_put(pll2_pfd2_396m_clk);
+ clk_put(pll2_bus_clk);
+ clk_put(secondary_sel_clk);
return 0;
}
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c
index 2faa4216bf2a..79e3ff2771a6 100644
--- a/drivers/cpufreq/integrator-cpufreq.c
+++ b/drivers/cpufreq/integrator-cpufreq.c
@@ -221,6 +221,8 @@ static const struct of_device_id integrator_cpufreq_match[] = {
{ },
};
+MODULE_DEVICE_TABLE(of, integrator_cpufreq_match);
+
static struct platform_driver integrator_cpufreq_driver = {
.driver = {
.name = "integrator-cpufreq",
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 3af9dd7332e6..001a532e342e 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -34,16 +34,15 @@
#include <asm/cpu_device_id.h>
#include <asm/cpufeature.h>
-#define BYT_RATIOS 0x66a
-#define BYT_VIDS 0x66b
-#define BYT_TURBO_RATIOS 0x66c
-#define BYT_TURBO_VIDS 0x66d
+#define ATOM_RATIOS 0x66a
+#define ATOM_VIDS 0x66b
+#define ATOM_TURBO_RATIOS 0x66c
+#define ATOM_TURBO_VIDS 0x66d
#define FRAC_BITS 8
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
#define fp_toint(X) ((X) >> FRAC_BITS)
-
static inline int32_t mul_fp(int32_t x, int32_t y)
{
return ((int64_t)x * (int64_t)y) >> FRAC_BITS;
@@ -78,6 +77,7 @@ struct pstate_data {
int current_pstate;
int min_pstate;
int max_pstate;
+ int max_pstate_physical;
int scaling;
int turbo_pstate;
};
@@ -127,6 +127,7 @@ struct pstate_adjust_policy {
struct pstate_funcs {
int (*get_max)(void);
+ int (*get_max_physical)(void);
int (*get_min)(void);
int (*get_turbo)(void);
int (*get_scaling)(void);
@@ -156,7 +157,20 @@ struct perf_limits {
int min_sysfs_pct;
};
-static struct perf_limits limits = {
+static struct perf_limits performance_limits = {
+ .no_turbo = 0,
+ .turbo_disabled = 0,
+ .max_perf_pct = 100,
+ .max_perf = int_tofp(1),
+ .min_perf_pct = 100,
+ .min_perf = int_tofp(1),
+ .max_policy_pct = 100,
+ .max_sysfs_pct = 100,
+ .min_policy_pct = 0,
+ .min_sysfs_pct = 0,
+};
+
+static struct perf_limits powersave_limits = {
.no_turbo = 0,
.turbo_disabled = 0,
.max_perf_pct = 100,
@@ -169,6 +183,12 @@ static struct perf_limits limits = {
.min_sysfs_pct = 0,
};
+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
+static struct perf_limits *limits = &performance_limits;
+#else
+static struct perf_limits *limits = &powersave_limits;
+#endif
+
static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
int deadband, int integral) {
pid->setpoint = setpoint;
@@ -255,7 +275,7 @@ static inline void update_turbo_state(void)
cpu = all_cpu_data[0];
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
- limits.turbo_disabled =
+ limits->turbo_disabled =
(misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
}
@@ -274,14 +294,14 @@ static void intel_pstate_hwp_set(void)
for_each_online_cpu(cpu) {
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
- adj_range = limits.min_perf_pct * range / 100;
+ adj_range = limits->min_perf_pct * range / 100;
min = hw_min + adj_range;
value &= ~HWP_MIN_PERF(~0L);
value |= HWP_MIN_PERF(min);
- adj_range = limits.max_perf_pct * range / 100;
+ adj_range = limits->max_perf_pct * range / 100;
max = hw_min + adj_range;
- if (limits.no_turbo) {
+ if (limits->no_turbo) {
hw_max = HWP_GUARANTEED_PERF(cap);
if (hw_max < max)
max = hw_max;
@@ -350,7 +370,7 @@ static void __init intel_pstate_debug_expose_params(void)
static ssize_t show_##file_name \
(struct kobject *kobj, struct attribute *attr, char *buf) \
{ \
- return sprintf(buf, "%u\n", limits.object); \
+ return sprintf(buf, "%u\n", limits->object); \
}
static ssize_t show_turbo_pct(struct kobject *kobj,
@@ -386,10 +406,10 @@ static ssize_t show_no_turbo(struct kobject *kobj,
ssize_t ret;
update_turbo_state();
- if (limits.turbo_disabled)
- ret = sprintf(buf, "%u\n", limits.turbo_disabled);
+ if (limits->turbo_disabled)
+ ret = sprintf(buf, "%u\n", limits->turbo_disabled);
else
- ret = sprintf(buf, "%u\n", limits.no_turbo);
+ ret = sprintf(buf, "%u\n", limits->no_turbo);
return ret;
}
@@ -405,12 +425,12 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
return -EINVAL;
update_turbo_state();
- if (limits.turbo_disabled) {
+ if (limits->turbo_disabled) {
pr_warn("intel_pstate: Turbo disabled by BIOS or unavailable on processor\n");
return -EPERM;
}
- limits.no_turbo = clamp_t(int, input, 0, 1);
+ limits->no_turbo = clamp_t(int, input, 0, 1);
if (hwp_active)
intel_pstate_hwp_set();
@@ -428,11 +448,15 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
- limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
- limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
- limits.max_perf_pct = max(limits.min_policy_pct, limits.max_perf_pct);
- limits.max_perf_pct = max(limits.min_perf_pct, limits.max_perf_pct);
- limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
+ limits->max_sysfs_pct = clamp_t(int, input, 0 , 100);
+ limits->max_perf_pct = min(limits->max_policy_pct,
+ limits->max_sysfs_pct);
+ limits->max_perf_pct = max(limits->min_policy_pct,
+ limits->max_perf_pct);
+ limits->max_perf_pct = max(limits->min_perf_pct,
+ limits->max_perf_pct);
+ limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
+ int_tofp(100));
if (hwp_active)
intel_pstate_hwp_set();
@@ -449,11 +473,15 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
- limits.min_sysfs_pct = clamp_t(int, input, 0 , 100);
- limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct);
- limits.min_perf_pct = min(limits.max_policy_pct, limits.min_perf_pct);
- limits.min_perf_pct = min(limits.max_perf_pct, limits.min_perf_pct);
- limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
+ limits->min_sysfs_pct = clamp_t(int, input, 0 , 100);
+ limits->min_perf_pct = max(limits->min_policy_pct,
+ limits->min_sysfs_pct);
+ limits->min_perf_pct = min(limits->max_policy_pct,
+ limits->min_perf_pct);
+ limits->min_perf_pct = min(limits->max_perf_pct,
+ limits->min_perf_pct);
+ limits->min_perf = div_fp(int_tofp(limits->min_perf_pct),
+ int_tofp(100));
if (hwp_active)
intel_pstate_hwp_set();
@@ -497,43 +525,41 @@ static void __init intel_pstate_sysfs_expose_params(void)
static void intel_pstate_hwp_enable(struct cpudata *cpudata)
{
- pr_info("intel_pstate: HWP enabled\n");
-
wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
}
-static int byt_get_min_pstate(void)
+static int atom_get_min_pstate(void)
{
u64 value;
- rdmsrl(BYT_RATIOS, value);
+ rdmsrl(ATOM_RATIOS, value);
return (value >> 8) & 0x7F;
}
-static int byt_get_max_pstate(void)
+static int atom_get_max_pstate(void)
{
u64 value;
- rdmsrl(BYT_RATIOS, value);
+ rdmsrl(ATOM_RATIOS, value);
return (value >> 16) & 0x7F;
}
-static int byt_get_turbo_pstate(void)
+static int atom_get_turbo_pstate(void)
{
u64 value;
- rdmsrl(BYT_TURBO_RATIOS, value);
+ rdmsrl(ATOM_TURBO_RATIOS, value);
return value & 0x7F;
}
-static void byt_set_pstate(struct cpudata *cpudata, int pstate)
+static void atom_set_pstate(struct cpudata *cpudata, int pstate)
{
u64 val;
int32_t vid_fp;
u32 vid;
val = (u64)pstate << 8;
- if (limits.no_turbo && !limits.turbo_disabled)
+ if (limits->no_turbo && !limits->turbo_disabled)
val |= (u64)1 << 32;
vid_fp = cpudata->vid.min + mul_fp(
@@ -551,27 +577,42 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val);
}
-#define BYT_BCLK_FREQS 5
-static int byt_freq_table[BYT_BCLK_FREQS] = { 833, 1000, 1333, 1167, 800};
-
-static int byt_get_scaling(void)
+static int silvermont_get_scaling(void)
{
u64 value;
int i;
+ /* Defined in Table 35-6 from SDM (Sept 2015) */
+ static int silvermont_freq_table[] = {
+ 83300, 100000, 133300, 116700, 80000};
rdmsrl(MSR_FSB_FREQ, value);
- i = value & 0x3;
+ i = value & 0x7;
+ WARN_ON(i > 4);
+
+ return silvermont_freq_table[i];
+}
+
+static int airmont_get_scaling(void)
+{
+ u64 value;
+ int i;
+ /* Defined in Table 35-10 from SDM (Sept 2015) */
+ static int airmont_freq_table[] = {
+ 83300, 100000, 133300, 116700, 80000,
+ 93300, 90000, 88900, 87500};
- BUG_ON(i > BYT_BCLK_FREQS);
+ rdmsrl(MSR_FSB_FREQ, value);
+ i = value & 0xF;
+ WARN_ON(i > 8);
- return byt_freq_table[i] * 100;
+ return airmont_freq_table[i];
}
-static void byt_get_vid(struct cpudata *cpudata)
+static void atom_get_vid(struct cpudata *cpudata)
{
u64 value;
- rdmsrl(BYT_VIDS, value);
+ rdmsrl(ATOM_VIDS, value);
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
cpudata->vid.ratio = div_fp(
@@ -579,7 +620,7 @@ static void byt_get_vid(struct cpudata *cpudata)
int_tofp(cpudata->pstate.max_pstate -
cpudata->pstate.min_pstate));
- rdmsrl(BYT_TURBO_VIDS, value);
+ rdmsrl(ATOM_TURBO_VIDS, value);
cpudata->vid.turbo = value & 0x7f;
}
@@ -591,7 +632,7 @@ static int core_get_min_pstate(void)
return (value >> 40) & 0xFF;
}
-static int core_get_max_pstate(void)
+static int core_get_max_pstate_physical(void)
{
u64 value;
@@ -599,6 +640,46 @@ static int core_get_max_pstate(void)
return (value >> 8) & 0xFF;
}
+static int core_get_max_pstate(void)
+{
+ u64 tar;
+ u64 plat_info;
+ int max_pstate;
+ int err;
+
+ rdmsrl(MSR_PLATFORM_INFO, plat_info);
+ max_pstate = (plat_info >> 8) & 0xFF;
+
+ err = rdmsrl_safe(MSR_TURBO_ACTIVATION_RATIO, &tar);
+ if (!err) {
+ /* Do some sanity checking for safety */
+ if (plat_info & 0x600000000) {
+ u64 tdp_ctrl;
+ u64 tdp_ratio;
+ int tdp_msr;
+
+ err = rdmsrl_safe(MSR_CONFIG_TDP_CONTROL, &tdp_ctrl);
+ if (err)
+ goto skip_tar;
+
+ tdp_msr = MSR_CONFIG_TDP_NOMINAL + tdp_ctrl;
+ err = rdmsrl_safe(tdp_msr, &tdp_ratio);
+ if (err)
+ goto skip_tar;
+
+ if (tdp_ratio - 1 == tar) {
+ max_pstate = tar;
+ pr_debug("max_pstate=TAC %x\n", max_pstate);
+ } else {
+ goto skip_tar;
+ }
+ }
+ }
+
+skip_tar:
+ return max_pstate;
+}
+
static int core_get_turbo_pstate(void)
{
u64 value;
@@ -622,7 +703,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
u64 val;
val = (u64)pstate << 8;
- if (limits.no_turbo && !limits.turbo_disabled)
+ if (limits->no_turbo && !limits->turbo_disabled)
val |= (u64)1 << 32;
wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val);
@@ -652,6 +733,7 @@ static struct cpu_defaults core_params = {
},
.funcs = {
.get_max = core_get_max_pstate,
+ .get_max_physical = core_get_max_pstate_physical,
.get_min = core_get_min_pstate,
.get_turbo = core_get_turbo_pstate,
.get_scaling = core_get_scaling,
@@ -659,7 +741,7 @@ static struct cpu_defaults core_params = {
},
};
-static struct cpu_defaults byt_params = {
+static struct cpu_defaults silvermont_params = {
.pid_policy = {
.sample_rate_ms = 10,
.deadband = 0,
@@ -669,12 +751,33 @@ static struct cpu_defaults byt_params = {
.i_gain_pct = 4,
},
.funcs = {
- .get_max = byt_get_max_pstate,
- .get_min = byt_get_min_pstate,
- .get_turbo = byt_get_turbo_pstate,
- .set = byt_set_pstate,
- .get_scaling = byt_get_scaling,
- .get_vid = byt_get_vid,
+ .get_max = atom_get_max_pstate,
+ .get_max_physical = atom_get_max_pstate,
+ .get_min = atom_get_min_pstate,
+ .get_turbo = atom_get_turbo_pstate,
+ .set = atom_set_pstate,
+ .get_scaling = silvermont_get_scaling,
+ .get_vid = atom_get_vid,
+ },
+};
+
+static struct cpu_defaults airmont_params = {
+ .pid_policy = {
+ .sample_rate_ms = 10,
+ .deadband = 0,
+ .setpoint = 60,
+ .p_gain_pct = 14,
+ .d_gain_pct = 0,
+ .i_gain_pct = 4,
+ },
+ .funcs = {
+ .get_max = atom_get_max_pstate,
+ .get_max_physical = atom_get_max_pstate,
+ .get_min = atom_get_min_pstate,
+ .get_turbo = atom_get_turbo_pstate,
+ .set = atom_set_pstate,
+ .get_scaling = airmont_get_scaling,
+ .get_vid = atom_get_vid,
},
};
@@ -689,6 +792,7 @@ static struct cpu_defaults knl_params = {
},
.funcs = {
.get_max = core_get_max_pstate,
+ .get_max_physical = core_get_max_pstate_physical,
.get_min = core_get_min_pstate,
.get_turbo = knl_get_turbo_pstate,
.get_scaling = core_get_scaling,
@@ -702,7 +806,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
int max_perf_adj;
int min_perf;
- if (limits.no_turbo || limits.turbo_disabled)
+ if (limits->no_turbo || limits->turbo_disabled)
max_perf = cpu->pstate.max_pstate;
/*
@@ -710,11 +814,11 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
* policy, or by cpu specific default values determined through
* experimentation.
*/
- max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
+ max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits->max_perf));
*max = clamp_t(int, max_perf_adj,
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
- min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
+ min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits->min_perf));
*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
}
@@ -743,6 +847,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
{
cpu->pstate.min_pstate = pstate_funcs.get_min();
cpu->pstate.max_pstate = pstate_funcs.get_max();
+ cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical();
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
cpu->pstate.scaling = pstate_funcs.get_scaling();
@@ -761,7 +866,8 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
sample->freq = fp_toint(
mul_fp(int_tofp(
- cpu->pstate.max_pstate * cpu->pstate.scaling / 100),
+ cpu->pstate.max_pstate_physical *
+ cpu->pstate.scaling / 100),
core_pct));
sample->core_pct_busy = (int32_t)core_pct;
@@ -776,6 +882,11 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
local_irq_save(flags);
rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf);
+ if (cpu->prev_mperf == mperf) {
+ local_irq_restore(flags);
+ return;
+ }
+
tsc = rdtsc();
local_irq_restore(flags);
@@ -829,7 +940,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
* specified pstate.
*/
core_busy = cpu->sample.core_pct_busy;
- max_pstate = int_tofp(cpu->pstate.max_pstate);
+ max_pstate = int_tofp(cpu->pstate.max_pstate_physical);
current_pstate = int_tofp(cpu->pstate.current_pstate);
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
@@ -907,7 +1018,7 @@ static void intel_pstate_timer_func(unsigned long __data)
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
ICPU(0x2a, core_params),
ICPU(0x2d, core_params),
- ICPU(0x37, byt_params),
+ ICPU(0x37, silvermont_params),
ICPU(0x3a, core_params),
ICPU(0x3c, core_params),
ICPU(0x3d, core_params),
@@ -916,7 +1027,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
ICPU(0x45, core_params),
ICPU(0x46, core_params),
ICPU(0x47, core_params),
- ICPU(0x4c, byt_params),
+ ICPU(0x4c, airmont_params),
ICPU(0x4e, core_params),
ICPU(0x4f, core_params),
ICPU(0x5e, core_params),
@@ -988,32 +1099,35 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
if (policy->policy == CPUFREQ_POLICY_PERFORMANCE &&
policy->max >= policy->cpuinfo.max_freq) {
- limits.min_policy_pct = 100;
- limits.min_perf_pct = 100;
- limits.min_perf = int_tofp(1);
- limits.max_policy_pct = 100;
- limits.max_perf_pct = 100;
- limits.max_perf = int_tofp(1);
- limits.no_turbo = 0;
+ pr_debug("intel_pstate: set performance\n");
+ limits = &performance_limits;
return 0;
}
- limits.min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
- limits.min_policy_pct = clamp_t(int, limits.min_policy_pct, 0 , 100);
- limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
- limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
+ pr_debug("intel_pstate: set powersave\n");
+ limits = &powersave_limits;
+ limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
+ limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100);
+ limits->max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
+ limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100);
/* Normalize user input to [min_policy_pct, max_policy_pct] */
- limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct);
- limits.min_perf_pct = min(limits.max_policy_pct, limits.min_perf_pct);
- limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
- limits.max_perf_pct = max(limits.min_policy_pct, limits.max_perf_pct);
+ limits->min_perf_pct = max(limits->min_policy_pct,
+ limits->min_sysfs_pct);
+ limits->min_perf_pct = min(limits->max_policy_pct,
+ limits->min_perf_pct);
+ limits->max_perf_pct = min(limits->max_policy_pct,
+ limits->max_sysfs_pct);
+ limits->max_perf_pct = max(limits->min_policy_pct,
+ limits->max_perf_pct);
/* Make sure min_perf_pct <= max_perf_pct */
- limits.min_perf_pct = min(limits.max_perf_pct, limits.min_perf_pct);
+ limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
- limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
- limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
+ limits->min_perf = div_fp(int_tofp(limits->min_perf_pct),
+ int_tofp(100));
+ limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
+ int_tofp(100));
if (hwp_active)
intel_pstate_hwp_set();
@@ -1057,7 +1171,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
cpu = all_cpu_data[policy->cpu];
- if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100)
+ if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100)
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
else
policy->policy = CPUFREQ_POLICY_POWERSAVE;
@@ -1113,6 +1227,7 @@ static void copy_pid_params(struct pstate_adjust_policy *policy)
static void copy_cpu_funcs(struct pstate_funcs *funcs)
{
pstate_funcs.get_max = funcs->get_max;
+ pstate_funcs.get_max_physical = funcs->get_max_physical;
pstate_funcs.get_min = funcs->get_min;
pstate_funcs.get_turbo = funcs->get_turbo;
pstate_funcs.get_scaling = funcs->get_scaling;
@@ -1271,8 +1386,10 @@ static int __init intel_pstate_init(void)
if (!all_cpu_data)
return -ENOMEM;
- if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp)
+ if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) {
+ pr_info("intel_pstate: HWP enabled\n");
hwp_active++;
+ }
if (!hwp_active && hwp_only)
goto out;
@@ -1307,8 +1424,10 @@ static int __init intel_pstate_setup(char *str)
if (!strcmp(str, "disable"))
no_load = 1;
- if (!strcmp(str, "no_hwp"))
+ if (!strcmp(str, "no_hwp")) {
+ pr_info("intel_pstate: HWP disabled\n");
no_hwp = 1;
+ }
if (!strcmp(str, "force"))
force_load = 1;
if (!strcmp(str, "hwp_only"))
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
index 49caed293a3b..83001dc5b646 100644
--- a/drivers/cpufreq/mt8173-cpufreq.c
+++ b/drivers/cpufreq/mt8173-cpufreq.c
@@ -344,7 +344,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
/* Both presence and absence of sram regulator are valid cases. */
sram_reg = regulator_get_exclusive(cpu_dev, "sram");
- ret = of_init_opp_table(cpu_dev);
+ ret = dev_pm_opp_of_add_table(cpu_dev);
if (ret) {
pr_warn("no OPP table for cpu%d\n", cpu);
goto out_free_resources;
@@ -378,7 +378,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
return 0;
out_free_opp_table:
- of_free_opp_table(cpu_dev);
+ dev_pm_opp_of_remove_table(cpu_dev);
out_free_resources:
if (!IS_ERR(proc_reg))
@@ -404,7 +404,7 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
if (!IS_ERR(info->inter_clk))
clk_put(info->inter_clk);
- of_free_opp_table(info->cpu_dev);
+ dev_pm_opp_of_remove_table(info->cpu_dev);
}
static int mtk_cpufreq_init(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 64994e10638e..cb501386eb6e 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -327,8 +327,14 @@ static void powernv_cpufreq_throttle_check(void *data)
if (chips[i].throttled)
goto next;
chips[i].throttled = true;
- pr_info("CPU %d on Chip %u has Pmax reduced to %d\n", cpu,
- chips[i].id, pmsr_pmax);
+ if (pmsr_pmax < powernv_pstate_info.nominal)
+ pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
+ cpu, chips[i].id, pmsr_pmax,
+ powernv_pstate_info.nominal);
+ else
+ pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n",
+ cpu, chips[i].id, pmsr_pmax,
+ powernv_pstate_info.max);
} else if (chips[i].throttled) {
chips[i].throttled = false;
pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu,
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 9e231f52150c..051a8a8224cd 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -212,11 +212,11 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
/* Find current DRAM frequency */
tmp = s5pv210_dram_conf[ch].freq;
- do_div(tmp, freq);
+ tmp /= freq;
tmp1 = s5pv210_dram_conf[ch].refresh;
- do_div(tmp1, tmp);
+ tmp1 /= tmp;
__raw_writel(tmp1, reg);
}
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
new file mode 100644
index 000000000000..2c3b16fd3a01
--- /dev/null
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -0,0 +1,124 @@
+/*
+ * System Control and Power Interface (SCPI) based CPUFreq Interface driver
+ *
+ * It provides necessary ops to arm_big_little cpufreq driver.
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Sudeep Holla <sudeep.holla@arm.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 "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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/scpi_protocol.h>
+#include <linux/types.h>
+
+#include "arm_big_little.h"
+
+static struct scpi_ops *scpi_ops;
+
+static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev)
+{
+ u8 domain = topology_physical_package_id(cpu_dev->id);
+
+ if (domain < 0)
+ return ERR_PTR(-EINVAL);
+ return scpi_ops->dvfs_get_info(domain);
+}
+
+static int scpi_opp_table_ops(struct device *cpu_dev, bool remove)
+{
+ int idx, ret = 0;
+ struct scpi_opp *opp;
+ struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
+
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+
+ if (!info->opps)
+ return -EIO;
+
+ for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) {
+ if (remove)
+ dev_pm_opp_remove(cpu_dev, opp->freq);
+ else
+ ret = dev_pm_opp_add(cpu_dev, opp->freq,
+ opp->m_volt * 1000);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to add opp %uHz %umV\n",
+ opp->freq, opp->m_volt);
+ while (idx-- > 0)
+ dev_pm_opp_remove(cpu_dev, (--opp)->freq);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int scpi_get_transition_latency(struct device *cpu_dev)
+{
+ struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
+
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+ return info->latency;
+}
+
+static int scpi_init_opp_table(struct device *cpu_dev)
+{
+ return scpi_opp_table_ops(cpu_dev, false);
+}
+
+static void scpi_free_opp_table(struct device *cpu_dev)
+{
+ scpi_opp_table_ops(cpu_dev, true);
+}
+
+static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = {
+ .name = "scpi",
+ .get_transition_latency = scpi_get_transition_latency,
+ .init_opp_table = scpi_init_opp_table,
+ .free_opp_table = scpi_free_opp_table,
+};
+
+static int scpi_cpufreq_probe(struct platform_device *pdev)
+{
+ scpi_ops = get_scpi_ops();
+ if (!scpi_ops)
+ return -EIO;
+
+ return bL_cpufreq_register(&scpi_cpufreq_ops);
+}
+
+static int scpi_cpufreq_remove(struct platform_device *pdev)
+{
+ bL_cpufreq_unregister(&scpi_cpufreq_ops);
+ scpi_ops = NULL;
+ return 0;
+}
+
+static struct platform_driver scpi_cpufreq_platdrv = {
+ .driver = {
+ .name = "scpi-cpufreq",
+ .owner = THIS_MODULE,
+ },
+ .probe = scpi_cpufreq_probe,
+ .remove = scpi_cpufreq_remove,
+};
+module_platform_driver(scpi_cpufreq_platdrv);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCPI CPUFreq interface driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
index 8084c7f7e206..2bd62845e9d5 100644
--- a/drivers/cpufreq/tegra20-cpufreq.c
+++ b/drivers/cpufreq/tegra20-cpufreq.c
@@ -175,9 +175,7 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
.exit = tegra_cpu_exit,
.name = "tegra",
.attr = cpufreq_generic_attr,
-#ifdef CONFIG_PM
.suspend = cpufreq_generic_suspend,
-#endif
};
static int __init tegra_cpufreq_init(void)
diff --git a/drivers/cpuidle/cpuidle-mvebu-v7.c b/drivers/cpuidle/cpuidle-mvebu-v7.c
index 980151f34707..01a856971f05 100644
--- a/drivers/cpuidle/cpuidle-mvebu-v7.c
+++ b/drivers/cpuidle/cpuidle-mvebu-v7.c
@@ -99,44 +99,40 @@ static struct cpuidle_driver armada38x_idle_driver = {
static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
{
- mvebu_v7_cpu_suspend = pdev->dev.platform_data;
+ const struct platform_device_id *id = pdev->id_entry;
- if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-xp"))
- return cpuidle_register(&armadaxp_idle_driver, NULL);
- else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
- return cpuidle_register(&armada370_idle_driver, NULL);
- else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
- return cpuidle_register(&armada38x_idle_driver, NULL);
- else
+ if (!id)
return -EINVAL;
-}
-static struct platform_driver armadaxp_cpuidle_plat_driver = {
- .driver = {
- .name = "cpuidle-armada-xp",
- },
- .probe = mvebu_v7_cpuidle_probe,
-};
+ mvebu_v7_cpu_suspend = pdev->dev.platform_data;
-module_platform_driver(armadaxp_cpuidle_plat_driver);
+ return cpuidle_register((struct cpuidle_driver *)id->driver_data, NULL);
+}
-static struct platform_driver armada370_cpuidle_plat_driver = {
- .driver = {
+static const struct platform_device_id mvebu_cpuidle_ids[] = {
+ {
+ .name = "cpuidle-armada-xp",
+ .driver_data = (unsigned long)&armadaxp_idle_driver,
+ }, {
.name = "cpuidle-armada-370",
+ .driver_data = (unsigned long)&armada370_idle_driver,
+ }, {
+ .name = "cpuidle-armada-38x",
+ .driver_data = (unsigned long)&armada38x_idle_driver,
},
- .probe = mvebu_v7_cpuidle_probe,
+ {}
};
-module_platform_driver(armada370_cpuidle_plat_driver);
-
-static struct platform_driver armada38x_cpuidle_plat_driver = {
+static struct platform_driver mvebu_cpuidle_driver = {
+ .probe = mvebu_v7_cpuidle_probe,
.driver = {
- .name = "cpuidle-armada-38x",
+ .name = "cpuidle-mbevu",
+ .suppress_bind_attrs = true,
},
- .probe = mvebu_v7_cpuidle_probe,
+ .id_table = mvebu_cpuidle_ids,
};
-module_platform_driver(armada38x_cpuidle_plat_driver);
+builtin_platform_driver(mvebu_cpuidle_driver);
MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index d234719065a5..2569e043317e 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -420,7 +420,7 @@ config CRYPTO_DEV_CCP
bool "Support for AMD Cryptographic Coprocessor"
depends on ((X86 && PCI) || (ARM64 && (OF_ADDRESS || ACPI))) && HAS_IOMEM
help
- The AMD Cryptographic Coprocessor provides hardware support
+ The AMD Cryptographic Coprocessor provides hardware offload support
for encryption, hashing and related operations.
if CRYPTO_DEV_CCP
@@ -429,7 +429,8 @@ endif
config CRYPTO_DEV_MXS_DCP
tristate "Support for Freescale MXS DCP"
- depends on ARCH_MXS
+ depends on (ARCH_MXS || ARCH_MXC)
+ select STMP_DEVICE
select CRYPTO_CBC
select CRYPTO_ECB
select CRYPTO_AES
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 192a8fa325c1..58a630e55d5d 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -740,26 +740,6 @@ void crypto4xx_return_pd(struct crypto4xx_device *dev,
pd_uinfo->state = PD_ENTRY_FREE;
}
-/*
- * derive number of elements in scatterlist
- * Shamlessly copy from talitos.c
- */
-static int get_sg_count(struct scatterlist *sg_list, int nbytes)
-{
- struct scatterlist *sg = sg_list;
- int sg_nents = 0;
-
- while (nbytes) {
- sg_nents++;
- if (sg->length > nbytes)
- break;
- nbytes -= sg->length;
- sg = sg_next(sg);
- }
-
- return sg_nents;
-}
-
static u32 get_next_gd(u32 current)
{
if (current != PPC4XX_LAST_GD)
@@ -800,7 +780,7 @@ u32 crypto4xx_build_pd(struct crypto_async_request *req,
u32 gd_idx = 0;
/* figure how many gd is needed */
- num_gd = get_sg_count(src, datalen);
+ num_gd = sg_nents_for_len(src, datalen);
if (num_gd == 1)
num_gd = 0;
@@ -1284,6 +1264,7 @@ static const struct of_device_id crypto4xx_match[] = {
{ .compatible = "amcc,ppc4xx-crypto",},
{ },
};
+MODULE_DEVICE_TABLE(of, crypto4xx_match);
static struct platform_driver crypto4xx_driver = {
.driver = {
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 0f9a9dc06a83..fb16d812c8f5 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -260,7 +260,11 @@ static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
{
- clk_prepare_enable(dd->iclk);
+ int err;
+
+ err = clk_prepare_enable(dd->iclk);
+ if (err)
+ return err;
if (!(dd->flags & AES_FLAGS_INIT)) {
atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
@@ -1320,7 +1324,6 @@ static int atmel_aes_probe(struct platform_device *pdev)
struct crypto_platform_data *pdata;
struct device *dev = &pdev->dev;
struct resource *aes_res;
- unsigned long aes_phys_size;
int err;
pdata = pdev->dev.platform_data;
@@ -1337,7 +1340,7 @@ static int atmel_aes_probe(struct platform_device *pdev)
goto aes_dd_err;
}
- aes_dd = kzalloc(sizeof(struct atmel_aes_dev), GFP_KERNEL);
+ aes_dd = devm_kzalloc(&pdev->dev, sizeof(*aes_dd), GFP_KERNEL);
if (aes_dd == NULL) {
dev_err(dev, "unable to alloc data struct.\n");
err = -ENOMEM;
@@ -1368,36 +1371,35 @@ static int atmel_aes_probe(struct platform_device *pdev)
goto res_err;
}
aes_dd->phys_base = aes_res->start;
- aes_phys_size = resource_size(aes_res);
/* Get the IRQ */
aes_dd->irq = platform_get_irq(pdev, 0);
if (aes_dd->irq < 0) {
dev_err(dev, "no IRQ resource info\n");
err = aes_dd->irq;
- goto aes_irq_err;
+ goto res_err;
}
- err = request_irq(aes_dd->irq, atmel_aes_irq, IRQF_SHARED, "atmel-aes",
- aes_dd);
+ err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq,
+ IRQF_SHARED, "atmel-aes", aes_dd);
if (err) {
dev_err(dev, "unable to request aes irq.\n");
- goto aes_irq_err;
+ goto res_err;
}
/* Initializing the clock */
- aes_dd->iclk = clk_get(&pdev->dev, "aes_clk");
+ aes_dd->iclk = devm_clk_get(&pdev->dev, "aes_clk");
if (IS_ERR(aes_dd->iclk)) {
dev_err(dev, "clock initialization failed.\n");
err = PTR_ERR(aes_dd->iclk);
- goto clk_err;
+ goto res_err;
}
- aes_dd->io_base = ioremap(aes_dd->phys_base, aes_phys_size);
+ aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
if (!aes_dd->io_base) {
dev_err(dev, "can't ioremap\n");
err = -ENOMEM;
- goto aes_io_err;
+ goto res_err;
}
atmel_aes_hw_version_init(aes_dd);
@@ -1434,17 +1436,9 @@ err_algs:
err_aes_dma:
atmel_aes_buff_cleanup(aes_dd);
err_aes_buff:
- iounmap(aes_dd->io_base);
-aes_io_err:
- clk_put(aes_dd->iclk);
-clk_err:
- free_irq(aes_dd->irq, aes_dd);
-aes_irq_err:
res_err:
tasklet_kill(&aes_dd->done_task);
tasklet_kill(&aes_dd->queue_task);
- kfree(aes_dd);
- aes_dd = NULL;
aes_dd_err:
dev_err(dev, "initialization failed.\n");
@@ -1469,16 +1463,6 @@ static int atmel_aes_remove(struct platform_device *pdev)
atmel_aes_dma_cleanup(aes_dd);
- iounmap(aes_dd->io_base);
-
- clk_put(aes_dd->iclk);
-
- if (aes_dd->irq > 0)
- free_irq(aes_dd->irq, aes_dd);
-
- kfree(aes_dd);
- aes_dd = NULL;
-
return 0;
}
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 5b35433c5399..660d8c06540b 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -794,7 +794,11 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err)
static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
{
- clk_prepare_enable(dd->iclk);
+ int err;
+
+ err = clk_prepare_enable(dd->iclk);
+ if (err)
+ return err;
if (!(SHA_FLAGS_INIT & dd->flags)) {
atmel_sha_write(dd, SHA_CR, SHA_CR_SWRST);
@@ -1345,11 +1349,9 @@ static int atmel_sha_probe(struct platform_device *pdev)
struct crypto_platform_data *pdata;
struct device *dev = &pdev->dev;
struct resource *sha_res;
- unsigned long sha_phys_size;
int err;
- sha_dd = devm_kzalloc(&pdev->dev, sizeof(struct atmel_sha_dev),
- GFP_KERNEL);
+ sha_dd = devm_kzalloc(&pdev->dev, sizeof(*sha_dd), GFP_KERNEL);
if (sha_dd == NULL) {
dev_err(dev, "unable to alloc data struct.\n");
err = -ENOMEM;
@@ -1378,7 +1380,6 @@ static int atmel_sha_probe(struct platform_device *pdev)
goto res_err;
}
sha_dd->phys_base = sha_res->start;
- sha_phys_size = resource_size(sha_res);
/* Get the IRQ */
sha_dd->irq = platform_get_irq(pdev, 0);
@@ -1388,26 +1389,26 @@ static int atmel_sha_probe(struct platform_device *pdev)
goto res_err;
}
- err = request_irq(sha_dd->irq, atmel_sha_irq, IRQF_SHARED, "atmel-sha",
- sha_dd);
+ err = devm_request_irq(&pdev->dev, sha_dd->irq, atmel_sha_irq,
+ IRQF_SHARED, "atmel-sha", sha_dd);
if (err) {
dev_err(dev, "unable to request sha irq.\n");
goto res_err;
}
/* Initializing the clock */
- sha_dd->iclk = clk_get(&pdev->dev, "sha_clk");
+ sha_dd->iclk = devm_clk_get(&pdev->dev, "sha_clk");
if (IS_ERR(sha_dd->iclk)) {
dev_err(dev, "clock initialization failed.\n");
err = PTR_ERR(sha_dd->iclk);
- goto clk_err;
+ goto res_err;
}
- sha_dd->io_base = ioremap(sha_dd->phys_base, sha_phys_size);
+ sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res);
if (!sha_dd->io_base) {
dev_err(dev, "can't ioremap\n");
err = -ENOMEM;
- goto sha_io_err;
+ goto res_err;
}
atmel_sha_hw_version_init(sha_dd);
@@ -1421,12 +1422,12 @@ static int atmel_sha_probe(struct platform_device *pdev)
if (IS_ERR(pdata)) {
dev_err(&pdev->dev, "platform data not available\n");
err = PTR_ERR(pdata);
- goto err_pdata;
+ goto res_err;
}
}
if (!pdata->dma_slave) {
err = -ENXIO;
- goto err_pdata;
+ goto res_err;
}
err = atmel_sha_dma_init(sha_dd, pdata);
if (err)
@@ -1457,12 +1458,6 @@ err_algs:
if (sha_dd->caps.has_dma)
atmel_sha_dma_cleanup(sha_dd);
err_sha_dma:
-err_pdata:
- iounmap(sha_dd->io_base);
-sha_io_err:
- clk_put(sha_dd->iclk);
-clk_err:
- free_irq(sha_dd->irq, sha_dd);
res_err:
tasklet_kill(&sha_dd->done_task);
sha_dd_err:
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index ca2999709eb4..2c7a628d0375 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -218,7 +218,11 @@ static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx)
static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
{
- clk_prepare_enable(dd->iclk);
+ int err;
+
+ err = clk_prepare_enable(dd->iclk);
+ if (err)
+ return err;
if (!(dd->flags & TDES_FLAGS_INIT)) {
atmel_tdes_write(dd, TDES_CR, TDES_CR_SWRST);
@@ -1355,7 +1359,6 @@ static int atmel_tdes_probe(struct platform_device *pdev)
struct crypto_platform_data *pdata;
struct device *dev = &pdev->dev;
struct resource *tdes_res;
- unsigned long tdes_phys_size;
int err;
tdes_dd = devm_kmalloc(&pdev->dev, sizeof(*tdes_dd), GFP_KERNEL);
@@ -1389,7 +1392,6 @@ static int atmel_tdes_probe(struct platform_device *pdev)
goto res_err;
}
tdes_dd->phys_base = tdes_res->start;
- tdes_phys_size = resource_size(tdes_res);
/* Get the IRQ */
tdes_dd->irq = platform_get_irq(pdev, 0);
@@ -1399,26 +1401,26 @@ static int atmel_tdes_probe(struct platform_device *pdev)
goto res_err;
}
- err = request_irq(tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED,
- "atmel-tdes", tdes_dd);
+ err = devm_request_irq(&pdev->dev, tdes_dd->irq, atmel_tdes_irq,
+ IRQF_SHARED, "atmel-tdes", tdes_dd);
if (err) {
dev_err(dev, "unable to request tdes irq.\n");
- goto tdes_irq_err;
+ goto res_err;
}
/* Initializing the clock */
- tdes_dd->iclk = clk_get(&pdev->dev, "tdes_clk");
+ tdes_dd->iclk = devm_clk_get(&pdev->dev, "tdes_clk");
if (IS_ERR(tdes_dd->iclk)) {
dev_err(dev, "clock initialization failed.\n");
err = PTR_ERR(tdes_dd->iclk);
- goto clk_err;
+ goto res_err;
}
- tdes_dd->io_base = ioremap(tdes_dd->phys_base, tdes_phys_size);
+ tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res);
if (!tdes_dd->io_base) {
dev_err(dev, "can't ioremap\n");
err = -ENOMEM;
- goto tdes_io_err;
+ goto res_err;
}
atmel_tdes_hw_version_init(tdes_dd);
@@ -1474,12 +1476,6 @@ err_tdes_dma:
err_pdata:
atmel_tdes_buff_cleanup(tdes_dd);
err_tdes_buff:
- iounmap(tdes_dd->io_base);
-tdes_io_err:
- clk_put(tdes_dd->iclk);
-clk_err:
- free_irq(tdes_dd->irq, tdes_dd);
-tdes_irq_err:
res_err:
tasklet_kill(&tdes_dd->done_task);
tasklet_kill(&tdes_dd->queue_task);
@@ -1510,13 +1506,6 @@ static int atmel_tdes_remove(struct platform_device *pdev)
atmel_tdes_buff_cleanup(tdes_dd);
- iounmap(tdes_dd->io_base);
-
- clk_put(tdes_dd->iclk);
-
- if (tdes_dd->irq >= 0)
- free_irq(tdes_dd->irq, tdes_dd);
-
return 0;
}
diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c
index 2f0b3337505d..95b73968cf72 100644
--- a/drivers/crypto/bfin_crc.c
+++ b/drivers/crypto/bfin_crc.c
@@ -96,26 +96,6 @@ struct bfin_crypto_crc_ctx {
u32 key;
};
-
-/*
- * derive number of elements in scatterlist
- */
-static int sg_count(struct scatterlist *sg_list)
-{
- struct scatterlist *sg = sg_list;
- int sg_nents = 1;
-
- if (sg_list == NULL)
- return 0;
-
- while (!sg_is_last(sg)) {
- sg_nents++;
- sg = sg_next(sg);
- }
-
- return sg_nents;
-}
-
/*
* get element in scatter list by given index
*/
@@ -160,7 +140,7 @@ static int bfin_crypto_crc_init(struct ahash_request *req)
}
spin_unlock_bh(&crc_list.lock);
- if (sg_count(req->src) > CRC_MAX_DMA_DESC) {
+ if (sg_nents(req->src) > CRC_MAX_DMA_DESC) {
dev_dbg(ctx->crc->dev, "init: requested sg list is too big > %d\n",
CRC_MAX_DMA_DESC);
return -EINVAL;
@@ -376,7 +356,8 @@ static int bfin_crypto_crc_handle_queue(struct bfin_crypto_crc *crc,
ctx->sg = req->src;
/* Chop crc buffer size to multiple of 32 bit */
- nsg = ctx->sg_nents = sg_count(ctx->sg);
+ nsg = sg_nents(ctx->sg);
+ ctx->sg_nents = nsg;
ctx->sg_buflen = ctx->buflast_len + req->nbytes;
ctx->bufnext_len = ctx->sg_buflen % 4;
ctx->sg_buflen &= ~0x3;
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index ba79d638f782..ea8189f4b021 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -1705,14 +1705,131 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
return ret;
}
+static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
+ const u8 *key, unsigned int keylen)
+{
+ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+ struct device *jrdev = ctx->jrdev;
+ u32 *key_jump_cmd, *desc;
+ __be64 sector_size = cpu_to_be64(512);
+
+ if (keylen != 2 * AES_MIN_KEY_SIZE && keylen != 2 * AES_MAX_KEY_SIZE) {
+ crypto_ablkcipher_set_flags(ablkcipher,
+ CRYPTO_TFM_RES_BAD_KEY_LEN);
+ dev_err(jrdev, "key size mismatch\n");
+ return -EINVAL;
+ }
+
+ memcpy(ctx->key, key, keylen);
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+ ctx->enckeylen = keylen;
+
+ /* xts_ablkcipher_encrypt shared descriptor */
+ desc = ctx->sh_desc_enc;
+ init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ /* Load class1 keys only */
+ append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+ /* Load sector size with index 40 bytes (0x28) */
+ append_cmd(desc, CMD_LOAD | IMMEDIATE | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | (0x28 << LDST_OFFSET_SHIFT) | 8);
+ append_data(desc, (void *)&sector_size, 8);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /*
+ * create sequence for loading the sector index
+ * Upper 8B of IV - will be used as sector index
+ * Lower 8B of IV - will be discarded
+ */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | (0x20 << LDST_OFFSET_SHIFT) | 8);
+ append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
+
+ /* Load operation */
+ append_operation(desc, ctx->class1_alg_type | OP_ALG_AS_INITFINAL |
+ OP_ALG_ENCRYPT);
+
+ /* Perform operation */
+ ablkcipher_append_src_dst(desc);
+
+ ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR,
+ "xts ablkcipher enc shdesc@" __stringify(__LINE__) ": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ /* xts_ablkcipher_decrypt shared descriptor */
+ desc = ctx->sh_desc_dec;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ /* Load class1 key only */
+ append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+ /* Load sector size with index 40 bytes (0x28) */
+ append_cmd(desc, CMD_LOAD | IMMEDIATE | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | (0x28 << LDST_OFFSET_SHIFT) | 8);
+ append_data(desc, (void *)&sector_size, 8);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /*
+ * create sequence for loading the sector index
+ * Upper 8B of IV - will be used as sector index
+ * Lower 8B of IV - will be discarded
+ */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | (0x20 << LDST_OFFSET_SHIFT) | 8);
+ append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
+
+ /* Load operation */
+ append_dec_op1(desc, ctx->class1_alg_type);
+
+ /* Perform operation */
+ ablkcipher_append_src_dst(desc);
+
+ ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+ dma_unmap_single(jrdev, ctx->sh_desc_enc_dma,
+ desc_bytes(ctx->sh_desc_enc), DMA_TO_DEVICE);
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR,
+ "xts ablkcipher dec shdesc@" __stringify(__LINE__) ": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ return 0;
+}
+
/*
* aead_edesc - s/w-extended aead descriptor
* @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
- * @assoc_chained: if source is chained
* @src_nents: number of segments in input scatterlist
- * @src_chained: if source is chained
* @dst_nents: number of segments in output scatterlist
- * @dst_chained: if destination is chained
* @iv_dma: dma address of iv for checking continuity and link table
* @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
* @sec4_sg_bytes: length of dma mapped sec4_sg space
@@ -1721,11 +1838,8 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
*/
struct aead_edesc {
int assoc_nents;
- bool assoc_chained;
int src_nents;
- bool src_chained;
int dst_nents;
- bool dst_chained;
dma_addr_t iv_dma;
int sec4_sg_bytes;
dma_addr_t sec4_sg_dma;
@@ -1736,9 +1850,7 @@ struct aead_edesc {
/*
* ablkcipher_edesc - s/w-extended ablkcipher descriptor
* @src_nents: number of segments in input scatterlist
- * @src_chained: if source is chained
* @dst_nents: number of segments in output scatterlist
- * @dst_chained: if destination is chained
* @iv_dma: dma address of iv for checking continuity and link table
* @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
* @sec4_sg_bytes: length of dma mapped sec4_sg space
@@ -1747,9 +1859,7 @@ struct aead_edesc {
*/
struct ablkcipher_edesc {
int src_nents;
- bool src_chained;
int dst_nents;
- bool dst_chained;
dma_addr_t iv_dma;
int sec4_sg_bytes;
dma_addr_t sec4_sg_dma;
@@ -1759,18 +1869,15 @@ struct ablkcipher_edesc {
static void caam_unmap(struct device *dev, struct scatterlist *src,
struct scatterlist *dst, int src_nents,
- bool src_chained, int dst_nents, bool dst_chained,
+ int dst_nents,
dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma,
int sec4_sg_bytes)
{
if (dst != src) {
- dma_unmap_sg_chained(dev, src, src_nents ? : 1, DMA_TO_DEVICE,
- src_chained);
- dma_unmap_sg_chained(dev, dst, dst_nents ? : 1, DMA_FROM_DEVICE,
- dst_chained);
+ dma_unmap_sg(dev, src, src_nents ? : 1, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, dst, dst_nents ? : 1, DMA_FROM_DEVICE);
} else {
- dma_unmap_sg_chained(dev, src, src_nents ? : 1,
- DMA_BIDIRECTIONAL, src_chained);
+ dma_unmap_sg(dev, src, src_nents ? : 1, DMA_BIDIRECTIONAL);
}
if (iv_dma)
@@ -1785,8 +1892,7 @@ static void aead_unmap(struct device *dev,
struct aead_request *req)
{
caam_unmap(dev, req->src, req->dst,
- edesc->src_nents, edesc->src_chained, edesc->dst_nents,
- edesc->dst_chained, 0, 0,
+ edesc->src_nents, edesc->dst_nents, 0, 0,
edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
}
@@ -1798,8 +1904,8 @@ static void ablkcipher_unmap(struct device *dev,
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
caam_unmap(dev, req->src, req->dst,
- edesc->src_nents, edesc->src_chained, edesc->dst_nents,
- edesc->dst_chained, edesc->iv_dma, ivsize,
+ edesc->src_nents, edesc->dst_nents,
+ edesc->iv_dma, ivsize,
edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
}
@@ -2169,22 +2275,18 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
struct aead_edesc *edesc;
int sgc;
bool all_contig = true;
- bool src_chained = false, dst_chained = false;
int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
unsigned int authsize = ctx->authsize;
if (unlikely(req->dst != req->src)) {
- src_nents = sg_count(req->src, req->assoclen + req->cryptlen,
- &src_chained);
+ src_nents = sg_count(req->src, req->assoclen + req->cryptlen);
dst_nents = sg_count(req->dst,
req->assoclen + req->cryptlen +
- (encrypt ? authsize : (-authsize)),
- &dst_chained);
+ (encrypt ? authsize : (-authsize)));
} else {
src_nents = sg_count(req->src,
req->assoclen + req->cryptlen +
- (encrypt ? authsize : 0),
- &src_chained);
+ (encrypt ? authsize : 0));
}
/* Check if data are contiguous. */
@@ -2207,37 +2309,35 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
}
if (likely(req->src == req->dst)) {
- sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL, src_chained);
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL);
if (unlikely(!sgc)) {
dev_err(jrdev, "unable to map source\n");
kfree(edesc);
return ERR_PTR(-ENOMEM);
}
} else {
- sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE, src_chained);
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
if (unlikely(!sgc)) {
dev_err(jrdev, "unable to map source\n");
kfree(edesc);
return ERR_PTR(-ENOMEM);
}
- sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
- DMA_FROM_DEVICE, dst_chained);
+ sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE);
if (unlikely(!sgc)) {
dev_err(jrdev, "unable to map destination\n");
- dma_unmap_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE, src_chained);
+ dma_unmap_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
kfree(edesc);
return ERR_PTR(-ENOMEM);
}
}
edesc->src_nents = src_nents;
- edesc->src_chained = src_chained;
edesc->dst_nents = dst_nents;
- edesc->dst_chained = dst_chained;
edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
desc_bytes;
*all_contig_ptr = all_contig;
@@ -2467,22 +2567,21 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
bool iv_contig = false;
int sgc;
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
- bool src_chained = false, dst_chained = false;
int sec4_sg_index;
- src_nents = sg_count(req->src, req->nbytes, &src_chained);
+ src_nents = sg_count(req->src, req->nbytes);
if (req->dst != req->src)
- dst_nents = sg_count(req->dst, req->nbytes, &dst_chained);
+ dst_nents = sg_count(req->dst, req->nbytes);
if (likely(req->src == req->dst)) {
- sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL, src_chained);
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL);
} else {
- sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE, src_chained);
- sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
- DMA_FROM_DEVICE, dst_chained);
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
+ sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE);
}
iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
@@ -2511,9 +2610,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
}
edesc->src_nents = src_nents;
- edesc->src_chained = src_chained;
edesc->dst_nents = dst_nents;
- edesc->dst_chained = dst_chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
desc_bytes;
@@ -2646,22 +2743,21 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
bool iv_contig = false;
int sgc;
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
- bool src_chained = false, dst_chained = false;
int sec4_sg_index;
- src_nents = sg_count(req->src, req->nbytes, &src_chained);
+ src_nents = sg_count(req->src, req->nbytes);
if (unlikely(req->dst != req->src))
- dst_nents = sg_count(req->dst, req->nbytes, &dst_chained);
+ dst_nents = sg_count(req->dst, req->nbytes);
if (likely(req->src == req->dst)) {
- sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL, src_chained);
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL);
} else {
- sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE, src_chained);
- sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
- DMA_FROM_DEVICE, dst_chained);
+ sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE);
+ sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE);
}
/*
@@ -2690,9 +2786,7 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
}
edesc->src_nents = src_nents;
- edesc->src_chained = src_chained;
edesc->dst_nents = dst_nents;
- edesc->dst_chained = dst_chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
desc_bytes;
@@ -2871,7 +2965,23 @@ static struct caam_alg_template driver_algs[] = {
.ivsize = CTR_RFC3686_IV_SIZE,
},
.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
- }
+ },
+ {
+ .name = "xts(aes)",
+ .driver_name = "xts-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = xts_ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XTS,
+ },
};
static struct caam_aead_alg driver_aeads[] = {
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 94433b9fc200..49106ea42887 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -134,6 +134,15 @@ struct caam_hash_state {
int current_buf;
};
+struct caam_export_state {
+ u8 buf[CAAM_MAX_HASH_BLOCK_SIZE];
+ u8 caam_ctx[MAX_CTX_LEN];
+ int buflen;
+ int (*update)(struct ahash_request *req);
+ int (*final)(struct ahash_request *req);
+ int (*finup)(struct ahash_request *req);
+};
+
/* Common job descriptor seq in/out ptr routines */
/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
@@ -181,10 +190,9 @@ static inline dma_addr_t buf_map_to_sec4_sg(struct device *jrdev,
/* Map req->src and put it in link table */
static inline void src_map_to_sec4_sg(struct device *jrdev,
struct scatterlist *src, int src_nents,
- struct sec4_sg_entry *sec4_sg,
- bool chained)
+ struct sec4_sg_entry *sec4_sg)
{
- dma_map_sg_chained(jrdev, src, src_nents, DMA_TO_DEVICE, chained);
+ dma_map_sg(jrdev, src, src_nents, DMA_TO_DEVICE);
sg_to_sec4_sg_last(src, src_nents, sec4_sg, 0);
}
@@ -585,7 +593,6 @@ badkey:
* 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
- * @chained: if source is chained
* @src_nents: number of segments in input scatterlist
* @sec4_sg_bytes: length of dma mapped sec4_sg space
* @sec4_sg: pointer to h/w link table
@@ -594,7 +601,6 @@ badkey:
struct ahash_edesc {
dma_addr_t dst_dma;
dma_addr_t sec4_sg_dma;
- bool chained;
int src_nents;
int sec4_sg_bytes;
struct sec4_sg_entry *sec4_sg;
@@ -606,8 +612,7 @@ static inline void ahash_unmap(struct device *dev,
struct ahash_request *req, int dst_len)
{
if (edesc->src_nents)
- dma_unmap_sg_chained(dev, req->src, edesc->src_nents,
- DMA_TO_DEVICE, edesc->chained);
+ 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);
@@ -788,7 +793,6 @@ static int ahash_update_ctx(struct ahash_request *req)
dma_addr_t ptr = ctx->sh_desc_update_dma;
int src_nents, sec4_sg_bytes, sec4_sg_src_index;
struct ahash_edesc *edesc;
- bool chained = false;
int ret = 0;
int sh_len;
@@ -797,8 +801,8 @@ static int ahash_update_ctx(struct ahash_request *req)
to_hash = in_len - *next_buflen;
if (to_hash) {
- src_nents = __sg_count(req->src, req->nbytes - (*next_buflen),
- &chained);
+ src_nents = sg_nents_for_len(req->src,
+ req->nbytes - (*next_buflen));
sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -816,7 +820,6 @@ static int ahash_update_ctx(struct ahash_request *req)
}
edesc->src_nents = src_nents;
- edesc->chained = chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
@@ -829,12 +832,11 @@ static int ahash_update_ctx(struct ahash_request *req)
state->buf_dma = try_buf_map_to_sec4_sg(jrdev,
edesc->sec4_sg + 1,
buf, state->buf_dma,
- *next_buflen, *buflen);
+ *buflen, last_buflen);
if (src_nents) {
src_map_to_sec4_sg(jrdev, req->src, src_nents,
- edesc->sec4_sg + sec4_sg_src_index,
- chained);
+ edesc->sec4_sg + sec4_sg_src_index);
if (*next_buflen)
scatterwalk_map_and_copy(next_buf, req->src,
to_hash - *buflen,
@@ -996,11 +998,10 @@ static int ahash_finup_ctx(struct ahash_request *req)
int src_nents;
int digestsize = crypto_ahash_digestsize(ahash);
struct ahash_edesc *edesc;
- bool chained = false;
int ret = 0;
int sh_len;
- src_nents = __sg_count(req->src, req->nbytes, &chained);
+ src_nents = sg_nents_for_len(req->src, req->nbytes);
sec4_sg_src_index = 1 + (buflen ? 1 : 0);
sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -1018,7 +1019,6 @@ static int ahash_finup_ctx(struct ahash_request *req)
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
edesc->src_nents = src_nents;
- edesc->chained = chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
@@ -1033,7 +1033,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
last_buflen);
src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg +
- sec4_sg_src_index, chained);
+ sec4_sg_src_index);
edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
sec4_sg_bytes, DMA_TO_DEVICE);
@@ -1081,14 +1081,12 @@ static int ahash_digest(struct ahash_request *req)
int src_nents, sec4_sg_bytes;
dma_addr_t src_dma;
struct ahash_edesc *edesc;
- bool chained = false;
int ret = 0;
u32 options;
int sh_len;
- src_nents = sg_count(req->src, req->nbytes, &chained);
- dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE,
- chained);
+ src_nents = sg_count(req->src, req->nbytes);
+ dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE);
sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
@@ -1102,7 +1100,6 @@ static int ahash_digest(struct ahash_request *req)
DESC_JOB_IO_LEN;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->src_nents = src_nents;
- edesc->chained = chained;
sh_len = desc_len(sh_desc);
desc = edesc->hw_desc;
@@ -1228,7 +1225,6 @@ static int ahash_update_no_ctx(struct ahash_request *req)
struct ahash_edesc *edesc;
u32 *desc, *sh_desc = ctx->sh_desc_update_first;
dma_addr_t ptr = ctx->sh_desc_update_first_dma;
- bool chained = false;
int ret = 0;
int sh_len;
@@ -1236,8 +1232,8 @@ static int ahash_update_no_ctx(struct ahash_request *req)
to_hash = in_len - *next_buflen;
if (to_hash) {
- src_nents = __sg_count(req->src, req->nbytes - (*next_buflen),
- &chained);
+ src_nents = sg_nents_for_len(req->src,
+ req->nbytes - (*next_buflen));
sec4_sg_bytes = (1 + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -1254,7 +1250,6 @@ static int ahash_update_no_ctx(struct ahash_request *req)
}
edesc->src_nents = src_nents;
- edesc->chained = chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
@@ -1263,7 +1258,7 @@ static int ahash_update_no_ctx(struct ahash_request *req)
state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg,
buf, *buflen);
src_map_to_sec4_sg(jrdev, req->src, src_nents,
- edesc->sec4_sg + 1, chained);
+ edesc->sec4_sg + 1);
if (*next_buflen) {
scatterwalk_map_and_copy(next_buf, req->src,
to_hash - *buflen,
@@ -1343,11 +1338,10 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
int sec4_sg_bytes, sec4_sg_src_index, src_nents;
int digestsize = crypto_ahash_digestsize(ahash);
struct ahash_edesc *edesc;
- bool chained = false;
int sh_len;
int ret = 0;
- src_nents = __sg_count(req->src, req->nbytes, &chained);
+ src_nents = sg_nents_for_len(req->src, req->nbytes);
sec4_sg_src_index = 2;
sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -1365,7 +1359,6 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
edesc->src_nents = src_nents;
- edesc->chained = chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
@@ -1374,8 +1367,7 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
state->buf_dma, buflen,
last_buflen);
- src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1,
- chained);
+ src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1);
edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
sec4_sg_bytes, DMA_TO_DEVICE);
@@ -1429,7 +1421,6 @@ static int ahash_update_first(struct ahash_request *req)
dma_addr_t src_dma;
u32 options;
struct ahash_edesc *edesc;
- bool chained = false;
int ret = 0;
int sh_len;
@@ -1438,10 +1429,8 @@ static int ahash_update_first(struct ahash_request *req)
to_hash = req->nbytes - *next_buflen;
if (to_hash) {
- src_nents = sg_count(req->src, req->nbytes - (*next_buflen),
- &chained);
- dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE, chained);
+ src_nents = sg_count(req->src, req->nbytes - (*next_buflen));
+ dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE);
sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
/*
@@ -1457,7 +1446,6 @@ static int ahash_update_first(struct ahash_request *req)
}
edesc->src_nents = src_nents;
- edesc->chained = chained;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
@@ -1574,25 +1562,42 @@ static int ahash_final(struct ahash_request *req)
static int ahash_export(struct ahash_request *req, void *out)
{
- 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);
+ struct caam_export_state *export = out;
+ int len;
+ u8 *buf;
+
+ if (state->current_buf) {
+ buf = state->buf_1;
+ len = state->buflen_1;
+ } else {
+ buf = state->buf_0;
+ len = state->buflen_1;
+ }
+
+ memcpy(export->buf, buf, len);
+ memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx));
+ export->buflen = len;
+ export->update = state->update;
+ export->final = state->final;
+ export->finup = state->finup;
- memcpy(out, ctx, sizeof(struct caam_hash_ctx));
- memcpy(out + sizeof(struct caam_hash_ctx), state,
- sizeof(struct caam_hash_state));
return 0;
}
static int ahash_import(struct ahash_request *req, const void *in)
{
- 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);
+ const struct caam_export_state *export = in;
+
+ memset(state, 0, sizeof(*state));
+ memcpy(state->buf_0, export->buf, export->buflen);
+ memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx));
+ state->buflen_0 = export->buflen;
+ state->update = export->update;
+ state->final = export->final;
+ state->finup = export->finup;
- memcpy(ctx, in, sizeof(struct caam_hash_ctx));
- memcpy(state, in + sizeof(struct caam_hash_ctx),
- sizeof(struct caam_hash_state));
return 0;
}
@@ -1626,8 +1631,9 @@ static struct caam_hash_template driver_hash[] = {
.setkey = ahash_setkey,
.halg = {
.digestsize = SHA1_DIGEST_SIZE,
- },
+ .statesize = sizeof(struct caam_export_state),
},
+ },
.alg_type = OP_ALG_ALGSEL_SHA1,
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
}, {
@@ -1647,8 +1653,9 @@ static struct caam_hash_template driver_hash[] = {
.setkey = ahash_setkey,
.halg = {
.digestsize = SHA224_DIGEST_SIZE,
- },
+ .statesize = sizeof(struct caam_export_state),
},
+ },
.alg_type = OP_ALG_ALGSEL_SHA224,
.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
}, {
@@ -1668,8 +1675,9 @@ static struct caam_hash_template driver_hash[] = {
.setkey = ahash_setkey,
.halg = {
.digestsize = SHA256_DIGEST_SIZE,
- },
+ .statesize = sizeof(struct caam_export_state),
},
+ },
.alg_type = OP_ALG_ALGSEL_SHA256,
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
}, {
@@ -1689,8 +1697,9 @@ static struct caam_hash_template driver_hash[] = {
.setkey = ahash_setkey,
.halg = {
.digestsize = SHA384_DIGEST_SIZE,
- },
+ .statesize = sizeof(struct caam_export_state),
},
+ },
.alg_type = OP_ALG_ALGSEL_SHA384,
.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
}, {
@@ -1710,8 +1719,9 @@ static struct caam_hash_template driver_hash[] = {
.setkey = ahash_setkey,
.halg = {
.digestsize = SHA512_DIGEST_SIZE,
- },
+ .statesize = sizeof(struct caam_export_state),
},
+ },
.alg_type = OP_ALG_ALGSEL_SHA512,
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
}, {
@@ -1731,8 +1741,9 @@ static struct caam_hash_template driver_hash[] = {
.setkey = ahash_setkey,
.halg = {
.digestsize = MD5_DIGEST_SIZE,
- },
+ .statesize = sizeof(struct caam_export_state),
},
+ },
.alg_type = OP_ALG_ALGSEL_MD5,
.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
},
@@ -1952,8 +1963,9 @@ static int __init caam_algapi_hash_init(void)
err = crypto_register_ahash(&t_alg->ahash_alg);
if (err) {
- pr_warn("%s alg registration failed\n",
- t_alg->ahash_alg.halg.base.cra_driver_name);
+ pr_warn("%s alg registration failed: %d\n",
+ t_alg->ahash_alg.halg.base.cra_driver_name,
+ err);
kfree(t_alg);
} else
list_add_tail(&t_alg->entry, &hash_list);
@@ -1968,8 +1980,9 @@ static int __init caam_algapi_hash_init(void)
err = crypto_register_ahash(&t_alg->ahash_alg);
if (err) {
- pr_warn("%s alg registration failed\n",
- t_alg->ahash_alg.halg.base.cra_driver_name);
+ pr_warn("%s alg registration failed: %d\n",
+ t_alg->ahash_alg.halg.base.cra_driver_name,
+ err);
kfree(t_alg);
} else
list_add_tail(&t_alg->entry, &hash_list);
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 983d663ef671..1e93c6af2275 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1492,7 +1492,6 @@ struct sec4_sg_entry {
#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
#define JUMP_TYPE_SHIFT 22
-#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index 18cd6d1f5870..12ec6616e89d 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -69,81 +69,13 @@ static inline struct sec4_sg_entry *sg_to_sec4_sg_len(
return sec4_sg_ptr - 1;
}
-/* count number of elements in scatterlist */
-static inline int __sg_count(struct scatterlist *sg_list, int nbytes,
- bool *chained)
-{
- struct scatterlist *sg = sg_list;
- int sg_nents = 0;
-
- while (nbytes > 0) {
- sg_nents++;
- nbytes -= sg->length;
- if (!sg_is_last(sg) && (sg + 1)->length == 0)
- *chained = true;
- sg = sg_next(sg);
- }
-
- return sg_nents;
-}
-
/* derive number of elements in scatterlist, but return 0 for 1 */
-static inline int sg_count(struct scatterlist *sg_list, int nbytes,
- bool *chained)
+static inline int sg_count(struct scatterlist *sg_list, int nbytes)
{
- int sg_nents = __sg_count(sg_list, nbytes, chained);
+ int sg_nents = sg_nents_for_len(sg_list, nbytes);
if (likely(sg_nents == 1))
return 0;
return sg_nents;
}
-
-static inline void dma_unmap_sg_chained(
- struct device *dev, struct scatterlist *sg, unsigned int nents,
- enum dma_data_direction dir, bool chained)
-{
- if (unlikely(chained)) {
- int i;
- struct scatterlist *tsg = sg;
-
- /*
- * Use a local copy of the sg pointer to avoid moving the
- * head of the list pointed to by sg as we walk the list.
- */
- for (i = 0; i < nents; i++) {
- dma_unmap_sg(dev, tsg, 1, dir);
- tsg = sg_next(tsg);
- }
- } else if (nents) {
- dma_unmap_sg(dev, sg, nents, dir);
- }
-}
-
-static inline int dma_map_sg_chained(
- struct device *dev, struct scatterlist *sg, unsigned int nents,
- enum dma_data_direction dir, bool chained)
-{
- if (unlikely(chained)) {
- int i;
- struct scatterlist *tsg = sg;
-
- /*
- * Use a local copy of the sg pointer to avoid moving the
- * head of the list pointed to by sg as we walk the list.
- */
- for (i = 0; i < nents; i++) {
- if (!dma_map_sg(dev, tsg, 1, dir)) {
- dma_unmap_sg_chained(dev, sg, i, dir,
- chained);
- nents = 0;
- break;
- }
-
- tsg = sg_next(tsg);
- }
- } else
- nents = dma_map_sg(dev, sg, nents, dir);
-
- return nents;
-}
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
index ae38f6b6cc10..3cd8481065f8 100644
--- a/drivers/crypto/ccp/Kconfig
+++ b/drivers/crypto/ccp/Kconfig
@@ -5,12 +5,12 @@ config CRYPTO_DEV_CCP_DD
select HW_RANDOM
help
Provides the interface to use the AMD Cryptographic Coprocessor
- which can be used to accelerate or offload encryption operations
- such as SHA, AES and more. If you choose 'M' here, this module
- will be called ccp.
+ which can be used to offload encryption operations such as SHA,
+ AES and more. If you choose 'M' here, this module will be called
+ ccp.
config CRYPTO_DEV_CCP_CRYPTO
- tristate "Encryption and hashing acceleration support"
+ tristate "Encryption and hashing offload support"
depends on CRYPTO_DEV_CCP_DD
default m
select CRYPTO_HASH
@@ -18,6 +18,5 @@ config CRYPTO_DEV_CCP_CRYPTO
select CRYPTO_AUTHENC
help
Support for using the cryptographic API with the AMD Cryptographic
- Coprocessor. This module supports acceleration and offload of SHA
- and AES algorithms. If you choose 'M' here, this module will be
- called ccp_crypto.
+ Coprocessor. This module supports offload of SHA and AES algorithms.
+ If you choose 'M' here, this module will be called ccp_crypto.
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
index ea7e8446956a..d89f20c04266 100644
--- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
+++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
@@ -118,10 +118,19 @@ static int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes,
if (rctx->buf_count) {
sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count);
sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg);
+ if (!sg) {
+ ret = -EINVAL;
+ goto e_free;
+ }
}
- if (nbytes)
+ if (nbytes) {
sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src);
+ if (!sg) {
+ ret = -EINVAL;
+ goto e_free;
+ }
+ }
if (need_pad) {
int pad_length = block_size - (len & (block_size - 1));
@@ -132,6 +141,10 @@ static int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes,
rctx->pad[0] = 0x80;
sg_init_one(&rctx->pad_sg, rctx->pad, pad_length);
sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg);
+ if (!sg) {
+ ret = -EINVAL;
+ goto e_free;
+ }
}
if (sg) {
sg_mark_end(sg);
@@ -163,6 +176,11 @@ static int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes,
ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
return ret;
+
+e_free:
+ sg_free_table(&rctx->data_sg);
+
+ return ret;
}
static int ccp_aes_cmac_init(struct ahash_request *req)
diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c
index bdec01ec608f..e0380e59c361 100644
--- a/drivers/crypto/ccp/ccp-crypto-main.c
+++ b/drivers/crypto/ccp/ccp-crypto-main.c
@@ -305,14 +305,16 @@ struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table,
for (sg = table->sgl; sg; sg = sg_next(sg))
if (!sg_page(sg))
break;
- BUG_ON(!sg);
+ if (WARN_ON(!sg))
+ return NULL;
for (; sg && sg_add; sg = sg_next(sg), sg_add = sg_next(sg_add)) {
sg_set_page(sg, sg_page(sg_add), sg_add->length,
sg_add->offset);
sg_last = sg;
}
- BUG_ON(sg_add);
+ if (WARN_ON(sg_add))
+ return NULL;
return sg_last;
}
diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
index 507b34e0cc19..d14b3f28e010 100644
--- a/drivers/crypto/ccp/ccp-crypto-sha.c
+++ b/drivers/crypto/ccp/ccp-crypto-sha.c
@@ -107,7 +107,15 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count);
sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg);
+ if (!sg) {
+ ret = -EINVAL;
+ goto e_free;
+ }
sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src);
+ if (!sg) {
+ ret = -EINVAL;
+ goto e_free;
+ }
sg_mark_end(sg);
sg = rctx->data_sg.sgl;
@@ -142,6 +150,11 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
return ret;
+
+e_free:
+ sg_free_table(&rctx->data_sg);
+
+ return ret;
}
static int ccp_sha_init(struct ahash_request *req)
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index d09c6c4af4aa..c6e883b296a9 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -611,15 +611,16 @@ static void ccp_get_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset,
1);
}
-static void ccp_reverse_set_dm_area(struct ccp_dm_workarea *wa,
- struct scatterlist *sg,
- unsigned int len, unsigned int se_len,
- bool sign_extend)
+static int ccp_reverse_set_dm_area(struct ccp_dm_workarea *wa,
+ struct scatterlist *sg,
+ unsigned int len, unsigned int se_len,
+ bool sign_extend)
{
unsigned int nbytes, sg_offset, dm_offset, ksb_len, i;
u8 buffer[CCP_REVERSE_BUF_SIZE];
- BUG_ON(se_len > sizeof(buffer));
+ if (WARN_ON(se_len > sizeof(buffer)))
+ return -EINVAL;
sg_offset = len;
dm_offset = 0;
@@ -642,6 +643,8 @@ static void ccp_reverse_set_dm_area(struct ccp_dm_workarea *wa,
se_len - ksb_len);
}
}
+
+ return 0;
}
static void ccp_reverse_get_dm_area(struct ccp_dm_workarea *wa,
@@ -1606,8 +1609,10 @@ static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
if (ret)
goto e_ksb;
- ccp_reverse_set_dm_area(&exp, rsa->exp, rsa->exp_len, CCP_KSB_BYTES,
- false);
+ ret = ccp_reverse_set_dm_area(&exp, rsa->exp, rsa->exp_len,
+ CCP_KSB_BYTES, false);
+ if (ret)
+ goto e_exp;
ret = ccp_copy_to_ksb(cmd_q, &exp, op.jobid, op.ksb_key,
CCP_PASSTHRU_BYTESWAP_NOOP);
if (ret) {
@@ -1623,11 +1628,15 @@ static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
if (ret)
goto e_exp;
- ccp_reverse_set_dm_area(&src, rsa->mod, rsa->mod_len, CCP_KSB_BYTES,
- false);
+ ret = ccp_reverse_set_dm_area(&src, rsa->mod, rsa->mod_len,
+ CCP_KSB_BYTES, false);
+ if (ret)
+ goto e_src;
src.address += o_len; /* Adjust the address for the copy operation */
- ccp_reverse_set_dm_area(&src, rsa->src, rsa->src_len, CCP_KSB_BYTES,
- false);
+ ret = ccp_reverse_set_dm_area(&src, rsa->src, rsa->src_len,
+ CCP_KSB_BYTES, false);
+ if (ret)
+ goto e_src;
src.address -= o_len; /* Reset the address to original value */
/* Prepare the output area for the operation */
@@ -1841,21 +1850,27 @@ static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
save = src.address;
/* Copy the ECC modulus */
- ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
/* Copy the first operand */
- ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_1,
- ecc->u.mm.operand_1_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_1,
+ ecc->u.mm.operand_1_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT) {
/* Copy the second operand */
- ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_2,
- ecc->u.mm.operand_2_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_2,
+ ecc->u.mm.operand_2_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
}
@@ -1960,18 +1975,24 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
save = src.address;
/* Copy the ECC modulus */
- ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
/* Copy the first point X and Y coordinate */
- ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.x,
- ecc->u.pm.point_1.x_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.x,
+ ecc->u.pm.point_1.x_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
- ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.y,
- ecc->u.pm.point_1.y_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.y,
+ ecc->u.pm.point_1.y_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
/* Set the first point Z coordianate to 1 */
@@ -1980,13 +2001,17 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
if (ecc->function == CCP_ECC_FUNCTION_PADD_384BIT) {
/* Copy the second point X and Y coordinate */
- ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.x,
- ecc->u.pm.point_2.x_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.x,
+ ecc->u.pm.point_2.x_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
- ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.y,
- ecc->u.pm.point_2.y_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.y,
+ ecc->u.pm.point_2.y_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
/* Set the second point Z coordianate to 1 */
@@ -1994,16 +2019,21 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
src.address += CCP_ECC_OPERAND_SIZE;
} else {
/* Copy the Domain "a" parameter */
- ccp_reverse_set_dm_area(&src, ecc->u.pm.domain_a,
- ecc->u.pm.domain_a_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.pm.domain_a,
+ ecc->u.pm.domain_a_len,
+ CCP_ECC_OPERAND_SIZE, false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT) {
/* Copy the scalar value */
- ccp_reverse_set_dm_area(&src, ecc->u.pm.scalar,
- ecc->u.pm.scalar_len,
- CCP_ECC_OPERAND_SIZE, false);
+ ret = ccp_reverse_set_dm_area(&src, ecc->u.pm.scalar,
+ ecc->u.pm.scalar_len,
+ CCP_ECC_OPERAND_SIZE,
+ false);
+ if (ret)
+ goto e_src;
src.address += CCP_ECC_OPERAND_SIZE;
}
}
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index af190d4795a8..6ade02f04f91 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -319,7 +319,7 @@ static const struct pci_device_id ccp_pci_table[] = {
MODULE_DEVICE_TABLE(pci, ccp_pci_table);
static struct pci_driver ccp_pci_driver = {
- .name = "AMD Cryptographic Coprocessor",
+ .name = "ccp",
.id_table = ccp_pci_table,
.probe = ccp_pci_probe,
.remove = ccp_pci_remove,
diff --git a/drivers/crypto/ccp/ccp-platform.c b/drivers/crypto/ccp/ccp-platform.c
index bb241c3ab6b9..01b50cb4c982 100644
--- a/drivers/crypto/ccp/ccp-platform.c
+++ b/drivers/crypto/ccp/ccp-platform.c
@@ -29,7 +29,6 @@
#include "ccp-dev.h"
struct ccp_platform {
- int use_acpi;
int coherent;
};
@@ -95,7 +94,7 @@ static int ccp_platform_probe(struct platform_device *pdev)
struct ccp_device *ccp;
struct ccp_platform *ccp_platform;
struct device *dev = &pdev->dev;
- struct acpi_device *adev = ACPI_COMPANION(dev);
+ enum dev_dma_attr attr;
struct resource *ior;
int ret;
@@ -112,8 +111,6 @@ static int ccp_platform_probe(struct platform_device *pdev)
ccp->get_irq = ccp_get_irqs;
ccp->free_irq = ccp_free_irqs;
- ccp_platform->use_acpi = (!adev || acpi_disabled) ? 0 : 1;
-
ior = ccp_find_mmio_area(ccp);
ccp->io_map = devm_ioremap_resource(dev, ior);
if (IS_ERR(ccp->io_map)) {
@@ -122,18 +119,24 @@ static int ccp_platform_probe(struct platform_device *pdev)
}
ccp->io_regs = ccp->io_map;
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
- if (ret) {
- dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
+ attr = device_get_dma_attr(dev);
+ if (attr == DEV_DMA_NOT_SUPPORTED) {
+ dev_err(dev, "DMA is not supported");
goto e_err;
}
- ccp_platform->coherent = device_dma_is_coherent(ccp->dev);
+ ccp_platform->coherent = (attr == DEV_DMA_COHERENT);
if (ccp_platform->coherent)
ccp->axcache = CACHE_WB_NO_ALLOC;
else
ccp->axcache = CACHE_NONE;
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+ if (ret) {
+ dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
+ goto e_err;
+ }
+
dev_set_drvdata(dev, ccp);
ret = ccp_init(ccp);
@@ -229,7 +232,7 @@ MODULE_DEVICE_TABLE(of, ccp_of_match);
static struct platform_driver ccp_platform_driver = {
.driver = {
- .name = "AMD Cryptographic Coprocessor",
+ .name = "ccp",
#ifdef CONFIG_ACPI
.acpi_match_table = ccp_acpi_match,
#endif
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index 8d2a7728434d..ca5c71ab4b4d 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -36,8 +36,6 @@
#include <crypto/algapi.h>
#include <crypto/des.h>
-#include <asm/kmap_types.h>
-
//#define HIFN_DEBUG
#ifdef HIFN_DEBUG
diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h
index bc2a55bc35e4..bd985e72520b 100644
--- a/drivers/crypto/marvell/cesa.h
+++ b/drivers/crypto/marvell/cesa.h
@@ -174,19 +174,19 @@
#define CESA_SA_DESC_MAC_DATA(offset) \
cpu_to_le32(CESA_SA_DATA_SRAM_OFFSET + (offset))
-#define CESA_SA_DESC_MAC_DATA_MSK GENMASK(15, 0)
+#define CESA_SA_DESC_MAC_DATA_MSK cpu_to_le32(GENMASK(15, 0))
#define CESA_SA_DESC_MAC_TOTAL_LEN(total_len) cpu_to_le32((total_len) << 16)
-#define CESA_SA_DESC_MAC_TOTAL_LEN_MSK GENMASK(31, 16)
+#define CESA_SA_DESC_MAC_TOTAL_LEN_MSK cpu_to_le32(GENMASK(31, 16))
#define CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX 0xffff
#define CESA_SA_DESC_MAC_DIGEST(offset) \
cpu_to_le32(CESA_SA_MAC_DIG_SRAM_OFFSET + (offset))
-#define CESA_SA_DESC_MAC_DIGEST_MSK GENMASK(15, 0)
+#define CESA_SA_DESC_MAC_DIGEST_MSK cpu_to_le32(GENMASK(15, 0))
#define CESA_SA_DESC_MAC_FRAG_LEN(frag_len) cpu_to_le32((frag_len) << 16)
-#define CESA_SA_DESC_MAC_FRAG_LEN_MSK GENMASK(31, 16)
+#define CESA_SA_DESC_MAC_FRAG_LEN_MSK cpu_to_le32(GENMASK(31, 16))
#define CESA_SA_DESC_MAC_IV(offset) \
cpu_to_le32((CESA_SA_MAC_IIV_SRAM_OFFSET + (offset)) | \
@@ -219,14 +219,14 @@
* to be executed.
*/
struct mv_cesa_sec_accel_desc {
- u32 config;
- u32 enc_p;
- u32 enc_len;
- u32 enc_key_p;
- u32 enc_iv;
- u32 mac_src_p;
- u32 mac_digest;
- u32 mac_iv;
+ __le32 config;
+ __le32 enc_p;
+ __le32 enc_len;
+ __le32 enc_key_p;
+ __le32 enc_iv;
+ __le32 mac_src_p;
+ __le32 mac_digest;
+ __le32 mac_iv;
};
/**
@@ -293,11 +293,13 @@ struct mv_cesa_op_ctx {
* operation.
*/
struct mv_cesa_tdma_desc {
- u32 byte_cnt;
- u32 src;
- u32 dst;
- u32 next_dma;
- u32 cur_dma;
+ __le32 byte_cnt;
+ __le32 src;
+ __le32 dst;
+ __le32 next_dma;
+
+ /* Software state */
+ dma_addr_t cur_dma;
struct mv_cesa_tdma_desc *next;
union {
struct mv_cesa_op_ctx *op;
@@ -612,7 +614,8 @@ struct mv_cesa_ahash_req {
u64 len;
int src_nents;
bool last_req;
- __be32 state[8];
+ bool algo_le;
+ u32 state[8];
};
/* CESA functions */
@@ -626,7 +629,7 @@ static inline void mv_cesa_update_op_cfg(struct mv_cesa_op_ctx *op,
op->desc.config |= cpu_to_le32(cfg);
}
-static inline u32 mv_cesa_get_op_cfg(struct mv_cesa_op_ctx *op)
+static inline u32 mv_cesa_get_op_cfg(const struct mv_cesa_op_ctx *op)
{
return le32_to_cpu(op->desc.config);
}
@@ -676,7 +679,7 @@ static inline void mv_cesa_set_int_mask(struct mv_cesa_engine *engine,
if (int_mask == engine->int_mask)
return;
- writel(int_mask, engine->regs + CESA_SA_INT_MSK);
+ writel_relaxed(int_mask, engine->regs + CESA_SA_INT_MSK);
engine->int_mask = int_mask;
}
@@ -685,6 +688,12 @@ static inline u32 mv_cesa_get_int_mask(struct mv_cesa_engine *engine)
return engine->int_mask;
}
+static inline bool mv_cesa_mac_op_is_first_frag(const struct mv_cesa_op_ctx *op)
+{
+ return (mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) ==
+ CESA_SA_DESC_CFG_FIRST_FRAG;
+}
+
int mv_cesa_queue_req(struct crypto_async_request *req);
/*
@@ -789,10 +798,8 @@ int mv_cesa_dma_add_data_transfer(struct mv_cesa_tdma_chain *chain,
dma_addr_t dst, dma_addr_t src, u32 size,
u32 flags, gfp_t gfp_flags);
-int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain,
- u32 flags);
-
-int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, u32 flags);
+int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain, gfp_t flags);
+int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, gfp_t flags);
int mv_cesa_dma_add_op_transfers(struct mv_cesa_tdma_chain *chain,
struct mv_cesa_dma_iter *dma_iter,
diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c
index 3df2f4e7adb2..6edae64bb387 100644
--- a/drivers/crypto/marvell/cipher.c
+++ b/drivers/crypto/marvell/cipher.c
@@ -98,14 +98,14 @@ static void mv_cesa_ablkcipher_std_step(struct ablkcipher_request *req)
/* FIXME: only update enc_len field */
if (!sreq->skip_ctx) {
- memcpy(engine->sram, &sreq->op, sizeof(sreq->op));
+ memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op));
sreq->skip_ctx = true;
} else {
- memcpy(engine->sram, &sreq->op, sizeof(sreq->op.desc));
+ memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op.desc));
}
mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE);
- writel(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
+ writel_relaxed(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
}
@@ -145,8 +145,9 @@ static int mv_cesa_ablkcipher_process(struct crypto_async_request *req,
if (ret)
return ret;
- memcpy(ablkreq->info, engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
- crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ablkreq)));
+ memcpy_fromio(ablkreq->info,
+ engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
+ crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ablkreq)));
return 0;
}
@@ -181,7 +182,7 @@ mv_cesa_ablkcipher_std_prepare(struct ablkcipher_request *req)
sreq->size = 0;
sreq->offset = 0;
mv_cesa_adjust_op(engine, &sreq->op);
- memcpy(engine->sram, &sreq->op, sizeof(sreq->op));
+ memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op));
}
static inline void mv_cesa_ablkcipher_prepare(struct crypto_async_request *req,
diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
index e8d0d7128137..6ec55b4a087b 100644
--- a/drivers/crypto/marvell/hash.c
+++ b/drivers/crypto/marvell/hash.c
@@ -27,10 +27,10 @@ mv_cesa_ahash_req_iter_init(struct mv_cesa_ahash_dma_iter *iter,
struct ahash_request *req)
{
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
- unsigned int len = req->nbytes;
+ unsigned int len = req->nbytes + creq->cache_ptr;
if (!creq->last_req)
- len = (len + creq->cache_ptr) & ~CESA_HASH_BLOCK_SIZE_MSK;
+ len &= ~CESA_HASH_BLOCK_SIZE_MSK;
mv_cesa_req_dma_iter_init(&iter->base, len);
mv_cesa_sg_dma_iter_init(&iter->src, req->src, DMA_TO_DEVICE);
@@ -179,7 +179,6 @@ static int mv_cesa_ahash_pad_len(struct mv_cesa_ahash_req *creq)
static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf)
{
- __be64 bits = cpu_to_be64(creq->len << 3);
unsigned int index, padlen;
buf[0] = 0x80;
@@ -187,7 +186,14 @@ static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf)
index = creq->len & CESA_HASH_BLOCK_SIZE_MSK;
padlen = mv_cesa_ahash_pad_len(creq);
memset(buf + 1, 0, padlen - 1);
- memcpy(buf + padlen, &bits, sizeof(bits));
+
+ if (creq->algo_le) {
+ __le64 bits = cpu_to_le64(creq->len << 3);
+ memcpy(buf + padlen, &bits, sizeof(bits));
+ } else {
+ __be64 bits = cpu_to_be64(creq->len << 3);
+ memcpy(buf + padlen, &bits, sizeof(bits));
+ }
return padlen + 8;
}
@@ -203,8 +209,8 @@ static void mv_cesa_ahash_std_step(struct ahash_request *req)
size_t len;
if (creq->cache_ptr)
- memcpy(engine->sram + CESA_SA_DATA_SRAM_OFFSET, creq->cache,
- creq->cache_ptr);
+ memcpy_toio(engine->sram + CESA_SA_DATA_SRAM_OFFSET,
+ creq->cache, creq->cache_ptr);
len = min_t(size_t, req->nbytes + creq->cache_ptr - sreq->offset,
CESA_SA_SRAM_PAYLOAD_SIZE);
@@ -245,10 +251,10 @@ static void mv_cesa_ahash_std_step(struct ahash_request *req)
if (len + trailerlen > CESA_SA_SRAM_PAYLOAD_SIZE) {
len &= CESA_HASH_BLOCK_SIZE_MSK;
new_cache_ptr = 64 - trailerlen;
- memcpy(creq->cache,
- engine->sram +
- CESA_SA_DATA_SRAM_OFFSET + len,
- new_cache_ptr);
+ memcpy_fromio(creq->cache,
+ engine->sram +
+ CESA_SA_DATA_SRAM_OFFSET + len,
+ new_cache_ptr);
} else {
len += mv_cesa_ahash_pad_req(creq,
engine->sram + len +
@@ -266,7 +272,7 @@ static void mv_cesa_ahash_std_step(struct ahash_request *req)
mv_cesa_update_op_cfg(op, frag_mode, CESA_SA_DESC_CFG_FRAG_MSK);
/* FIXME: only update enc_len field */
- memcpy(engine->sram, op, sizeof(*op));
+ memcpy_toio(engine->sram, op, sizeof(*op));
if (frag_mode == CESA_SA_DESC_CFG_FIRST_FRAG)
mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
@@ -275,7 +281,7 @@ static void mv_cesa_ahash_std_step(struct ahash_request *req)
creq->cache_ptr = new_cache_ptr;
mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE);
- writel(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
+ writel_relaxed(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
}
@@ -306,7 +312,7 @@ static void mv_cesa_ahash_std_prepare(struct ahash_request *req)
sreq->offset = 0;
mv_cesa_adjust_op(engine, &creq->op_tmpl);
- memcpy(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
+ memcpy_toio(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
}
static void mv_cesa_ahash_step(struct crypto_async_request *req)
@@ -338,7 +344,7 @@ static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status)
digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
for (i = 0; i < digsize / 4; i++)
- creq->state[i] = readl(engine->regs + CESA_IVDIG(i));
+ creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i));
if (creq->cache_ptr)
sg_pcopy_to_buffer(ahashreq->src, creq->src_nents,
@@ -347,18 +353,21 @@ static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status)
ahashreq->nbytes - creq->cache_ptr);
if (creq->last_req) {
- for (i = 0; i < digsize / 4; i++) {
- /*
- * Hardware provides MD5 digest in a different
- * endianness than SHA-1 and SHA-256 ones.
- */
- if (digsize == MD5_DIGEST_SIZE)
- creq->state[i] = cpu_to_le32(creq->state[i]);
- else
- creq->state[i] = cpu_to_be32(creq->state[i]);
- }
+ /*
+ * Hardware's MD5 digest is in little endian format, but
+ * SHA in big endian format
+ */
+ if (creq->algo_le) {
+ __le32 *result = (void *)ahashreq->result;
+
+ for (i = 0; i < digsize / 4; i++)
+ result[i] = cpu_to_le32(creq->state[i]);
+ } else {
+ __be32 *result = (void *)ahashreq->result;
- memcpy(ahashreq->result, creq->state, digsize);
+ for (i = 0; i < digsize / 4; i++)
+ result[i] = cpu_to_be32(creq->state[i]);
+ }
}
return ret;
@@ -381,8 +390,7 @@ static void mv_cesa_ahash_prepare(struct crypto_async_request *req,
digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
for (i = 0; i < digsize / 4; i++)
- writel(creq->state[i],
- engine->regs + CESA_IVDIG(i));
+ writel_relaxed(creq->state[i], engine->regs + CESA_IVDIG(i));
}
static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req)
@@ -404,7 +412,7 @@ static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = {
};
static int mv_cesa_ahash_init(struct ahash_request *req,
- struct mv_cesa_op_ctx *tmpl)
+ struct mv_cesa_op_ctx *tmpl, bool algo_le)
{
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
@@ -418,6 +426,7 @@ static int mv_cesa_ahash_init(struct ahash_request *req,
mv_cesa_set_mac_op_frag_len(tmpl, 0);
creq->op_tmpl = *tmpl;
creq->len = 0;
+ creq->algo_le = algo_le;
return 0;
}
@@ -462,145 +471,114 @@ static int mv_cesa_ahash_cache_req(struct ahash_request *req, bool *cached)
}
static struct mv_cesa_op_ctx *
-mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
- struct mv_cesa_ahash_dma_iter *dma_iter,
- struct mv_cesa_ahash_req *creq,
- gfp_t flags)
+mv_cesa_dma_add_frag(struct mv_cesa_tdma_chain *chain,
+ struct mv_cesa_op_ctx *tmpl, unsigned int frag_len,
+ gfp_t flags)
{
- struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
- struct mv_cesa_op_ctx *op = NULL;
+ struct mv_cesa_op_ctx *op;
int ret;
- if (!creq->cache_ptr)
- return NULL;
+ op = mv_cesa_dma_add_op(chain, tmpl, false, flags);
+ if (IS_ERR(op))
+ return op;
- ret = mv_cesa_dma_add_data_transfer(chain,
- CESA_SA_DATA_SRAM_OFFSET,
- ahashdreq->cache_dma,
- creq->cache_ptr,
- CESA_TDMA_DST_IN_SRAM,
- flags);
+ /* Set the operation block fragment length. */
+ mv_cesa_set_mac_op_frag_len(op, frag_len);
+
+ /* Append dummy desc to launch operation */
+ ret = mv_cesa_dma_add_dummy_launch(chain, flags);
if (ret)
return ERR_PTR(ret);
- if (!dma_iter->base.op_len) {
- op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
- if (IS_ERR(op))
- return op;
-
- mv_cesa_set_mac_op_frag_len(op, creq->cache_ptr);
-
- /* Add dummy desc to launch crypto operation */
- ret = mv_cesa_dma_add_dummy_launch(chain, flags);
- if (ret)
- return ERR_PTR(ret);
- }
+ if (mv_cesa_mac_op_is_first_frag(tmpl))
+ mv_cesa_update_op_cfg(tmpl,
+ CESA_SA_DESC_CFG_MID_FRAG,
+ CESA_SA_DESC_CFG_FRAG_MSK);
return op;
}
-static struct mv_cesa_op_ctx *
-mv_cesa_ahash_dma_add_data(struct mv_cesa_tdma_chain *chain,
- struct mv_cesa_ahash_dma_iter *dma_iter,
- struct mv_cesa_ahash_req *creq,
- gfp_t flags)
+static int
+mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
+ struct mv_cesa_ahash_dma_iter *dma_iter,
+ struct mv_cesa_ahash_req *creq,
+ gfp_t flags)
{
- struct mv_cesa_op_ctx *op;
- int ret;
-
- op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
- if (IS_ERR(op))
- return op;
-
- mv_cesa_set_mac_op_frag_len(op, dma_iter->base.op_len);
-
- if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) ==
- CESA_SA_DESC_CFG_FIRST_FRAG)
- mv_cesa_update_op_cfg(&creq->op_tmpl,
- CESA_SA_DESC_CFG_MID_FRAG,
- CESA_SA_DESC_CFG_FRAG_MSK);
-
- /* Add input transfers */
- ret = mv_cesa_dma_add_op_transfers(chain, &dma_iter->base,
- &dma_iter->src, flags);
- if (ret)
- return ERR_PTR(ret);
+ struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
- /* Add dummy desc to launch crypto operation */
- ret = mv_cesa_dma_add_dummy_launch(chain, flags);
- if (ret)
- return ERR_PTR(ret);
+ if (!creq->cache_ptr)
+ return 0;
- return op;
+ return mv_cesa_dma_add_data_transfer(chain,
+ CESA_SA_DATA_SRAM_OFFSET,
+ ahashdreq->cache_dma,
+ creq->cache_ptr,
+ CESA_TDMA_DST_IN_SRAM,
+ flags);
}
static struct mv_cesa_op_ctx *
mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
struct mv_cesa_ahash_dma_iter *dma_iter,
struct mv_cesa_ahash_req *creq,
- struct mv_cesa_op_ctx *op,
- gfp_t flags)
+ unsigned int frag_len, gfp_t flags)
{
struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
unsigned int len, trailerlen, padoff = 0;
+ struct mv_cesa_op_ctx *op;
int ret;
- if (!creq->last_req)
- return op;
-
- if (op && creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
- u32 frag = CESA_SA_DESC_CFG_NOT_FRAG;
-
- if ((mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) !=
- CESA_SA_DESC_CFG_FIRST_FRAG)
- frag = CESA_SA_DESC_CFG_LAST_FRAG;
+ /*
+ * If the transfer is smaller than our maximum length, and we have
+ * some data outstanding, we can ask the engine to finish the hash.
+ */
+ if (creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX && frag_len) {
+ op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len,
+ flags);
+ if (IS_ERR(op))
+ return op;
- mv_cesa_update_op_cfg(op, frag, CESA_SA_DESC_CFG_FRAG_MSK);
+ mv_cesa_set_mac_op_total_len(op, creq->len);
+ mv_cesa_update_op_cfg(op, mv_cesa_mac_op_is_first_frag(op) ?
+ CESA_SA_DESC_CFG_NOT_FRAG :
+ CESA_SA_DESC_CFG_LAST_FRAG,
+ CESA_SA_DESC_CFG_FRAG_MSK);
return op;
}
+ /*
+ * The request is longer than the engine can handle, or we have
+ * no data outstanding. Manually generate the padding, adding it
+ * as a "mid" fragment.
+ */
ret = mv_cesa_ahash_dma_alloc_padding(ahashdreq, flags);
if (ret)
return ERR_PTR(ret);
trailerlen = mv_cesa_ahash_pad_req(creq, ahashdreq->padding);
- if (op) {
- len = min(CESA_SA_SRAM_PAYLOAD_SIZE - dma_iter->base.op_len,
- trailerlen);
- if (len) {
- ret = mv_cesa_dma_add_data_transfer(chain,
+ len = min(CESA_SA_SRAM_PAYLOAD_SIZE - frag_len, trailerlen);
+ if (len) {
+ ret = mv_cesa_dma_add_data_transfer(chain,
CESA_SA_DATA_SRAM_OFFSET +
- dma_iter->base.op_len,
+ frag_len,
ahashdreq->padding_dma,
len, CESA_TDMA_DST_IN_SRAM,
flags);
- if (ret)
- return ERR_PTR(ret);
-
- mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
- CESA_SA_DESC_CFG_FRAG_MSK);
- mv_cesa_set_mac_op_frag_len(op,
- dma_iter->base.op_len + len);
- padoff += len;
- }
- }
-
- if (padoff >= trailerlen)
- return op;
+ if (ret)
+ return ERR_PTR(ret);
- if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) !=
- CESA_SA_DESC_CFG_FIRST_FRAG)
- mv_cesa_update_op_cfg(&creq->op_tmpl,
- CESA_SA_DESC_CFG_MID_FRAG,
- CESA_SA_DESC_CFG_FRAG_MSK);
+ op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len + len,
+ flags);
+ if (IS_ERR(op))
+ return op;
- op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
- if (IS_ERR(op))
- return op;
+ if (len == trailerlen)
+ return op;
- mv_cesa_set_mac_op_frag_len(op, trailerlen - padoff);
+ padoff += len;
+ }
ret = mv_cesa_dma_add_data_transfer(chain,
CESA_SA_DATA_SRAM_OFFSET,
@@ -612,12 +590,8 @@ mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
if (ret)
return ERR_PTR(ret);
- /* Add dummy desc to launch crypto operation */
- ret = mv_cesa_dma_add_dummy_launch(chain, flags);
- if (ret)
- return ERR_PTR(ret);
-
- return op;
+ return mv_cesa_dma_add_frag(chain, &creq->op_tmpl, trailerlen - padoff,
+ flags);
}
static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
@@ -627,9 +601,9 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
GFP_KERNEL : GFP_ATOMIC;
struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
struct mv_cesa_tdma_req *dreq = &ahashdreq->base;
- struct mv_cesa_tdma_chain chain;
struct mv_cesa_ahash_dma_iter iter;
struct mv_cesa_op_ctx *op = NULL;
+ unsigned int frag_len;
int ret;
dreq->chain.first = NULL;
@@ -644,29 +618,59 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
}
}
- mv_cesa_tdma_desc_iter_init(&chain);
+ mv_cesa_tdma_desc_iter_init(&dreq->chain);
mv_cesa_ahash_req_iter_init(&iter, req);
- op = mv_cesa_ahash_dma_add_cache(&chain, &iter,
- creq, flags);
- if (IS_ERR(op)) {
- ret = PTR_ERR(op);
+ /*
+ * Add the cache (left-over data from a previous block) first.
+ * This will never overflow the SRAM size.
+ */
+ ret = mv_cesa_ahash_dma_add_cache(&dreq->chain, &iter, creq, flags);
+ if (ret)
goto err_free_tdma;
- }
- do {
- if (!iter.base.op_len)
- break;
+ if (iter.src.sg) {
+ /*
+ * Add all the new data, inserting an operation block and
+ * launch command between each full SRAM block-worth of
+ * data. We intentionally do not add the final op block.
+ */
+ while (true) {
+ ret = mv_cesa_dma_add_op_transfers(&dreq->chain,
+ &iter.base,
+ &iter.src, flags);
+ if (ret)
+ goto err_free_tdma;
+
+ frag_len = iter.base.op_len;
- op = mv_cesa_ahash_dma_add_data(&chain, &iter,
- creq, flags);
- if (IS_ERR(op)) {
- ret = PTR_ERR(op);
- goto err_free_tdma;
+ if (!mv_cesa_ahash_req_iter_next_op(&iter))
+ break;
+
+ op = mv_cesa_dma_add_frag(&dreq->chain, &creq->op_tmpl,
+ frag_len, flags);
+ if (IS_ERR(op)) {
+ ret = PTR_ERR(op);
+ goto err_free_tdma;
+ }
}
- } while (mv_cesa_ahash_req_iter_next_op(&iter));
+ } else {
+ /* Account for the data that was in the cache. */
+ frag_len = iter.base.op_len;
+ }
+
+ /*
+ * At this point, frag_len indicates whether we have any data
+ * outstanding which needs an operation. Queue up the final
+ * operation, which depends whether this is the final request.
+ */
+ if (creq->last_req)
+ op = mv_cesa_ahash_dma_last_req(&dreq->chain, &iter, creq,
+ frag_len, flags);
+ else if (frag_len)
+ op = mv_cesa_dma_add_frag(&dreq->chain, &creq->op_tmpl,
+ frag_len, flags);
- op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, op, flags);
if (IS_ERR(op)) {
ret = PTR_ERR(op);
goto err_free_tdma;
@@ -674,7 +678,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
if (op) {
/* Add dummy desc to wait for crypto operation end */
- ret = mv_cesa_dma_add_dummy_end(&chain, flags);
+ ret = mv_cesa_dma_add_dummy_end(&dreq->chain, flags);
if (ret)
goto err_free_tdma;
}
@@ -685,8 +689,6 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
else
creq->cache_ptr = 0;
- dreq->chain = chain;
-
return 0;
err_free_tdma:
@@ -795,47 +797,50 @@ static int mv_cesa_ahash_finup(struct ahash_request *req)
return ret;
}
-static int mv_cesa_md5_init(struct ahash_request *req)
+static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,
+ u64 *len, void *cache)
{
- struct mv_cesa_op_ctx tmpl;
-
- mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
-
- mv_cesa_ahash_init(req, &tmpl);
-
- return 0;
-}
-
-static int mv_cesa_md5_export(struct ahash_request *req, void *out)
-{
- struct md5_state *out_state = out;
struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
unsigned int digsize = crypto_ahash_digestsize(ahash);
+ unsigned int blocksize;
+
+ blocksize = crypto_ahash_blocksize(ahash);
- out_state->byte_count = creq->len;
- memcpy(out_state->hash, creq->state, digsize);
- memset(out_state->block, 0, sizeof(out_state->block));
+ *len = creq->len;
+ memcpy(hash, creq->state, digsize);
+ memset(cache, 0, blocksize);
if (creq->cache)
- memcpy(out_state->block, creq->cache, creq->cache_ptr);
+ memcpy(cache, creq->cache, creq->cache_ptr);
return 0;
}
-static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash,
+ u64 len, const void *cache)
{
- const struct md5_state *in_state = in;
struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
unsigned int digsize = crypto_ahash_digestsize(ahash);
+ unsigned int blocksize;
unsigned int cache_ptr;
int ret;
- creq->len = in_state->byte_count;
- memcpy(creq->state, in_state->hash, digsize);
+ ret = crypto_ahash_init(req);
+ if (ret)
+ return ret;
+
+ blocksize = crypto_ahash_blocksize(ahash);
+ if (len >= blocksize)
+ mv_cesa_update_op_cfg(&creq->op_tmpl,
+ CESA_SA_DESC_CFG_MID_FRAG,
+ CESA_SA_DESC_CFG_FRAG_MSK);
+
+ creq->len = len;
+ memcpy(creq->state, hash, digsize);
creq->cache_ptr = 0;
- cache_ptr = creq->len % sizeof(in_state->block);
+ cache_ptr = do_div(len, blocksize);
if (!cache_ptr)
return 0;
@@ -843,12 +848,39 @@ static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
if (ret)
return ret;
- memcpy(creq->cache, in_state->block, cache_ptr);
+ memcpy(creq->cache, cache, cache_ptr);
creq->cache_ptr = cache_ptr;
return 0;
}
+static int mv_cesa_md5_init(struct ahash_request *req)
+{
+ struct mv_cesa_op_ctx tmpl = { };
+
+ mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
+
+ mv_cesa_ahash_init(req, &tmpl, true);
+
+ return 0;
+}
+
+static int mv_cesa_md5_export(struct ahash_request *req, void *out)
+{
+ struct md5_state *out_state = out;
+
+ return mv_cesa_ahash_export(req, out_state->hash,
+ &out_state->byte_count, out_state->block);
+}
+
+static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+{
+ const struct md5_state *in_state = in;
+
+ return mv_cesa_ahash_import(req, in_state->hash, in_state->byte_count,
+ in_state->block);
+}
+
static int mv_cesa_md5_digest(struct ahash_request *req)
{
int ret;
@@ -870,6 +902,7 @@ struct ahash_alg mv_md5_alg = {
.import = mv_cesa_md5_import,
.halg = {
.digestsize = MD5_DIGEST_SIZE,
+ .statesize = sizeof(struct md5_state),
.base = {
.cra_name = "md5",
.cra_driver_name = "mv-md5",
@@ -886,11 +919,11 @@ struct ahash_alg mv_md5_alg = {
static int mv_cesa_sha1_init(struct ahash_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1);
- mv_cesa_ahash_init(req, &tmpl);
+ mv_cesa_ahash_init(req, &tmpl, false);
return 0;
}
@@ -898,44 +931,17 @@ static int mv_cesa_sha1_init(struct ahash_request *req)
static int mv_cesa_sha1_export(struct ahash_request *req, void *out)
{
struct sha1_state *out_state = out;
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
- struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
- unsigned int digsize = crypto_ahash_digestsize(ahash);
-
- out_state->count = creq->len;
- memcpy(out_state->state, creq->state, digsize);
- memset(out_state->buffer, 0, sizeof(out_state->buffer));
- if (creq->cache)
- memcpy(out_state->buffer, creq->cache, creq->cache_ptr);
- return 0;
+ return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
+ out_state->buffer);
}
static int mv_cesa_sha1_import(struct ahash_request *req, const void *in)
{
const struct sha1_state *in_state = in;
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
- struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
- unsigned int digsize = crypto_ahash_digestsize(ahash);
- unsigned int cache_ptr;
- int ret;
- creq->len = in_state->count;
- memcpy(creq->state, in_state->state, digsize);
- creq->cache_ptr = 0;
-
- cache_ptr = creq->len % SHA1_BLOCK_SIZE;
- if (!cache_ptr)
- return 0;
-
- ret = mv_cesa_ahash_alloc_cache(req);
- if (ret)
- return ret;
-
- memcpy(creq->cache, in_state->buffer, cache_ptr);
- creq->cache_ptr = cache_ptr;
-
- return 0;
+ return mv_cesa_ahash_import(req, in_state->state, in_state->count,
+ in_state->buffer);
}
static int mv_cesa_sha1_digest(struct ahash_request *req)
@@ -959,6 +965,7 @@ struct ahash_alg mv_sha1_alg = {
.import = mv_cesa_sha1_import,
.halg = {
.digestsize = SHA1_DIGEST_SIZE,
+ .statesize = sizeof(struct sha1_state),
.base = {
.cra_name = "sha1",
.cra_driver_name = "mv-sha1",
@@ -975,11 +982,11 @@ struct ahash_alg mv_sha1_alg = {
static int mv_cesa_sha256_init(struct ahash_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256);
- mv_cesa_ahash_init(req, &tmpl);
+ mv_cesa_ahash_init(req, &tmpl, false);
return 0;
}
@@ -998,44 +1005,17 @@ static int mv_cesa_sha256_digest(struct ahash_request *req)
static int mv_cesa_sha256_export(struct ahash_request *req, void *out)
{
struct sha256_state *out_state = out;
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
- struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
- unsigned int ds = crypto_ahash_digestsize(ahash);
- out_state->count = creq->len;
- memcpy(out_state->state, creq->state, ds);
- memset(out_state->buf, 0, sizeof(out_state->buf));
- if (creq->cache)
- memcpy(out_state->buf, creq->cache, creq->cache_ptr);
-
- return 0;
+ return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
+ out_state->buf);
}
static int mv_cesa_sha256_import(struct ahash_request *req, const void *in)
{
const struct sha256_state *in_state = in;
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
- struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
- unsigned int digsize = crypto_ahash_digestsize(ahash);
- unsigned int cache_ptr;
- int ret;
-
- creq->len = in_state->count;
- memcpy(creq->state, in_state->state, digsize);
- creq->cache_ptr = 0;
-
- cache_ptr = creq->len % SHA256_BLOCK_SIZE;
- if (!cache_ptr)
- return 0;
-
- ret = mv_cesa_ahash_alloc_cache(req);
- if (ret)
- return ret;
-
- memcpy(creq->cache, in_state->buf, cache_ptr);
- creq->cache_ptr = cache_ptr;
- return 0;
+ return mv_cesa_ahash_import(req, in_state->state, in_state->count,
+ in_state->buf);
}
struct ahash_alg mv_sha256_alg = {
@@ -1048,6 +1028,7 @@ struct ahash_alg mv_sha256_alg = {
.import = mv_cesa_sha256_import,
.halg = {
.digestsize = SHA256_DIGEST_SIZE,
+ .statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "mv-sha256",
@@ -1231,12 +1212,12 @@ static int mv_cesa_ahmac_cra_init(struct crypto_tfm *tfm)
static int mv_cesa_ahmac_md5_init(struct ahash_request *req)
{
struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_MD5);
memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
- mv_cesa_ahash_init(req, &tmpl);
+ mv_cesa_ahash_init(req, &tmpl, true);
return 0;
}
@@ -1301,12 +1282,12 @@ struct ahash_alg mv_ahmac_md5_alg = {
static int mv_cesa_ahmac_sha1_init(struct ahash_request *req)
{
struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA1);
memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
- mv_cesa_ahash_init(req, &tmpl);
+ mv_cesa_ahash_init(req, &tmpl, false);
return 0;
}
@@ -1391,12 +1372,12 @@ static int mv_cesa_ahmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
static int mv_cesa_ahmac_sha256_init(struct ahash_request *req)
{
struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA256);
memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
- mv_cesa_ahash_init(req, &tmpl);
+ mv_cesa_ahash_init(req, &tmpl, false);
return 0;
}
diff --git a/drivers/crypto/marvell/tdma.c b/drivers/crypto/marvell/tdma.c
index 64a366c50174..76427981275b 100644
--- a/drivers/crypto/marvell/tdma.c
+++ b/drivers/crypto/marvell/tdma.c
@@ -41,18 +41,18 @@ void mv_cesa_dma_step(struct mv_cesa_tdma_req *dreq)
{
struct mv_cesa_engine *engine = dreq->base.engine;
- writel(0, engine->regs + CESA_SA_CFG);
+ writel_relaxed(0, engine->regs + CESA_SA_CFG);
mv_cesa_set_int_mask(engine, CESA_SA_INT_ACC0_IDMA_DONE);
- writel(CESA_TDMA_DST_BURST_128B | CESA_TDMA_SRC_BURST_128B |
- CESA_TDMA_NO_BYTE_SWAP | CESA_TDMA_EN,
- engine->regs + CESA_TDMA_CONTROL);
-
- writel(CESA_SA_CFG_ACT_CH0_IDMA | CESA_SA_CFG_MULTI_PKT |
- CESA_SA_CFG_CH0_W_IDMA | CESA_SA_CFG_PARA_DIS,
- engine->regs + CESA_SA_CFG);
- writel(dreq->chain.first->cur_dma,
- engine->regs + CESA_TDMA_NEXT_ADDR);
+ writel_relaxed(CESA_TDMA_DST_BURST_128B | CESA_TDMA_SRC_BURST_128B |
+ CESA_TDMA_NO_BYTE_SWAP | CESA_TDMA_EN,
+ engine->regs + CESA_TDMA_CONTROL);
+
+ writel_relaxed(CESA_SA_CFG_ACT_CH0_IDMA | CESA_SA_CFG_MULTI_PKT |
+ CESA_SA_CFG_CH0_W_IDMA | CESA_SA_CFG_PARA_DIS,
+ engine->regs + CESA_SA_CFG);
+ writel_relaxed(dreq->chain.first->cur_dma,
+ engine->regs + CESA_TDMA_NEXT_ADDR);
writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
}
@@ -69,7 +69,7 @@ void mv_cesa_dma_cleanup(struct mv_cesa_tdma_req *dreq)
tdma = tdma->next;
dma_pool_free(cesa_dev->dma->tdma_desc_pool, old_tdma,
- le32_to_cpu(old_tdma->cur_dma));
+ old_tdma->cur_dma);
}
dreq->chain.first = NULL;
@@ -105,9 +105,9 @@ mv_cesa_dma_add_desc(struct mv_cesa_tdma_chain *chain, gfp_t flags)
return ERR_PTR(-ENOMEM);
memset(new_tdma, 0, sizeof(*new_tdma));
- new_tdma->cur_dma = cpu_to_le32(dma_handle);
+ new_tdma->cur_dma = dma_handle;
if (chain->last) {
- chain->last->next_dma = new_tdma->cur_dma;
+ chain->last->next_dma = cpu_to_le32(dma_handle);
chain->last->next = new_tdma;
} else {
chain->first = new_tdma;
@@ -126,6 +126,7 @@ struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain,
struct mv_cesa_tdma_desc *tdma;
struct mv_cesa_op_ctx *op;
dma_addr_t dma_handle;
+ unsigned int size;
tdma = mv_cesa_dma_add_desc(chain, flags);
if (IS_ERR(tdma))
@@ -137,10 +138,12 @@ struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain,
*op = *op_templ;
+ size = skip_ctx ? sizeof(op->desc) : sizeof(*op);
+
tdma = chain->last;
tdma->op = op;
- tdma->byte_cnt = (skip_ctx ? sizeof(op->desc) : sizeof(*op)) | BIT(31);
- tdma->src = dma_handle;
+ tdma->byte_cnt = cpu_to_le32(size | BIT(31));
+ tdma->src = cpu_to_le32(dma_handle);
tdma->flags = CESA_TDMA_DST_IN_SRAM | CESA_TDMA_OP;
return op;
@@ -156,7 +159,7 @@ int mv_cesa_dma_add_data_transfer(struct mv_cesa_tdma_chain *chain,
if (IS_ERR(tdma))
return PTR_ERR(tdma);
- tdma->byte_cnt = size | BIT(31);
+ tdma->byte_cnt = cpu_to_le32(size | BIT(31));
tdma->src = src;
tdma->dst = dst;
@@ -166,8 +169,7 @@ int mv_cesa_dma_add_data_transfer(struct mv_cesa_tdma_chain *chain,
return 0;
}
-int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain,
- u32 flags)
+int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain, gfp_t flags)
{
struct mv_cesa_tdma_desc *tdma;
@@ -178,7 +180,7 @@ int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain,
return 0;
}
-int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, u32 flags)
+int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, gfp_t flags)
{
struct mv_cesa_tdma_desc *tdma;
@@ -186,7 +188,7 @@ int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, u32 flags)
if (IS_ERR(tdma))
return PTR_ERR(tdma);
- tdma->byte_cnt = BIT(31);
+ tdma->byte_cnt = cpu_to_le32(BIT(31));
return 0;
}
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 2e8dab9d4263..5450880abb7b 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -34,7 +34,7 @@
#define DRV_MODULE_VERSION "0.2"
#define DRV_MODULE_RELDATE "July 28, 2011"
-static char version[] =
+static const char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
diff --git a/drivers/crypto/nx/nx-842-powernv.c b/drivers/crypto/nx/nx-842-powernv.c
index 3750e13d8721..9ef51fafdbff 100644
--- a/drivers/crypto/nx/nx-842-powernv.c
+++ b/drivers/crypto/nx/nx-842-powernv.c
@@ -491,7 +491,7 @@ static int nx842_powernv_compress(const unsigned char *in, unsigned int inlen,
void *wmem)
{
return nx842_powernv_function(in, inlen, out, outlenp,
- wmem, CCW_FC_842_COMP_NOCRC);
+ wmem, CCW_FC_842_COMP_CRC);
}
/**
@@ -519,7 +519,7 @@ static int nx842_powernv_decompress(const unsigned char *in, unsigned int inlen,
void *wmem)
{
return nx842_powernv_function(in, inlen, out, outlenp,
- wmem, CCW_FC_842_DECOMP_NOCRC);
+ wmem, CCW_FC_842_DECOMP_CRC);
}
static int __init nx842_powernv_probe(struct device_node *dn)
diff --git a/drivers/crypto/nx/nx-842-pseries.c b/drivers/crypto/nx/nx-842-pseries.c
index f4cbde03c6ad..cddc6d8b55d9 100644
--- a/drivers/crypto/nx/nx-842-pseries.c
+++ b/drivers/crypto/nx/nx-842-pseries.c
@@ -234,6 +234,10 @@ static int nx842_validate_result(struct device *dev,
dev_dbg(dev, "%s: Out of space in output buffer\n",
__func__);
return -ENOSPC;
+ case 65: /* Calculated CRC doesn't match the passed value */
+ dev_dbg(dev, "%s: CRC mismatch for decompression\n",
+ __func__);
+ return -EINVAL;
case 66: /* Input data contains an illegal template field */
case 67: /* Template indicates data past the end of the input stream */
dev_dbg(dev, "%s: Bad data for decompression (code:%d)\n",
@@ -324,7 +328,7 @@ static int nx842_pseries_compress(const unsigned char *in, unsigned int inlen,
slout.entries = (struct nx842_slentry *)workmem->slout;
/* Init operation */
- op.flags = NX842_OP_COMPRESS;
+ op.flags = NX842_OP_COMPRESS_CRC;
csbcpb = &workmem->csbcpb;
memset(csbcpb, 0, sizeof(*csbcpb));
op.csbcpb = nx842_get_pa(csbcpb);
@@ -457,7 +461,7 @@ static int nx842_pseries_decompress(const unsigned char *in, unsigned int inlen,
slout.entries = (struct nx842_slentry *)workmem->slout;
/* Init operation */
- op.flags = NX842_OP_DECOMPRESS;
+ op.flags = NX842_OP_DECOMPRESS_CRC;
csbcpb = &workmem->csbcpb;
memset(csbcpb, 0, sizeof(*csbcpb));
op.csbcpb = nx842_get_pa(csbcpb);
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index da36de26a4dc..615da961c4d8 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1591,6 +1591,7 @@ static const struct of_device_id spacc_of_id_table[] = {
{ .compatible = "picochip,spacc-l2" },
{}
};
+MODULE_DEVICE_TABLE(of, spacc_of_id_table);
#endif /* CONFIG_OF */
static bool spacc_is_compatible(struct platform_device *pdev,
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
index df20a9de1c58..9e9e196c6d51 100644
--- a/drivers/crypto/qat/qat_common/Makefile
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -1,5 +1,10 @@
-$(obj)/qat_rsakey-asn1.o: $(obj)/qat_rsakey-asn1.c $(obj)/qat_rsakey-asn1.h
-clean-files += qat_rsakey-asn1.c qat_rsakey-asn1.h
+$(obj)/qat_rsapubkey-asn1.o: $(obj)/qat_rsapubkey-asn1.c \
+ $(obj)/qat_rsapubkey-asn1.h
+$(obj)/qat_rsaprivkey-asn1.o: $(obj)/qat_rsaprivkey-asn1.c \
+ $(obj)/qat_rsaprivkey-asn1.h
+
+clean-files += qat_rsapubkey-asn1.c qat_rsapubkey-asn1.h
+clean-files += qat_rsaprivkey-asn1.c qat_rsapvivkey-asn1.h
obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
intel_qat-objs := adf_cfg.o \
@@ -13,7 +18,8 @@ intel_qat-objs := adf_cfg.o \
adf_hw_arbiter.o \
qat_crypto.o \
qat_algs.o \
- qat_rsakey-asn1.o \
+ qat_rsapubkey-asn1.o \
+ qat_rsaprivkey-asn1.o \
qat_asym_algs.o \
qat_uclo.o \
qat_hal.o
diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
index 7836dffc3d47..3f76bd495bcb 100644
--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
@@ -163,10 +163,8 @@ struct qat_crypto_instance *qat_crypto_get_instance_node(int node);
void qat_crypto_put_instance(struct qat_crypto_instance *inst);
void qat_alg_callback(void *resp);
void qat_alg_asym_callback(void *resp);
-int qat_algs_init(void);
-void qat_algs_exit(void);
int qat_algs_register(void);
-int qat_algs_unregister(void);
+void qat_algs_unregister(void);
int qat_asym_algs_register(void);
void qat_asym_algs_unregister(void);
diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
index cd8a12af8ec5..473d36d91644 100644
--- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
@@ -198,7 +198,7 @@ static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
goto out_err;
}
- params_head = section_head->params;
+ params_head = section.params;
while (params_head) {
if (copy_from_user(&key_val, (void __user *)params_head,
@@ -463,9 +463,6 @@ static int __init adf_register_ctl_device_driver(void)
{
mutex_init(&adf_ctl_lock);
- if (qat_algs_init())
- goto err_algs_init;
-
if (adf_chr_drv_create())
goto err_chr_dev;
@@ -482,8 +479,6 @@ err_crypto_register:
err_aer:
adf_chr_drv_destroy();
err_chr_dev:
- qat_algs_exit();
-err_algs_init:
mutex_destroy(&adf_ctl_lock);
return -EFAULT;
}
@@ -493,7 +488,6 @@ static void __exit adf_unregister_ctl_device_driver(void)
adf_chr_drv_destroy();
adf_exit_aer();
qat_crypto_unregister();
- qat_algs_exit();
adf_clean_vf_map(false);
mutex_destroy(&adf_ctl_lock);
}
diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c
index ac37a89965ac..d873eeecc363 100644
--- a/drivers/crypto/qat/qat_common/adf_init.c
+++ b/drivers/crypto/qat/qat_common/adf_init.c
@@ -272,12 +272,10 @@ int adf_dev_stop(struct adf_accel_dev *accel_dev)
clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
- if (!list_empty(&accel_dev->crypto_list) && qat_algs_unregister())
- dev_err(&GET_DEV(accel_dev),
- "Failed to unregister crypto algs\n");
-
- if (!list_empty(&accel_dev->crypto_list))
+ if (!list_empty(&accel_dev->crypto_list)) {
+ qat_algs_unregister();
qat_asym_algs_unregister();
+ }
list_for_each(list_itr, &service_table) {
service = list_entry(list_itr, struct service_hndl, list);
diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c
index 2f77a4a8cecb..1117a8b58280 100644
--- a/drivers/crypto/qat/qat_common/adf_sriov.c
+++ b/drivers/crypto/qat/qat_common/adf_sriov.c
@@ -244,11 +244,8 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
return -EFAULT;
}
- if (!iommu_present(&pci_bus_type)) {
- dev_err(&pdev->dev,
- "IOMMU must be enabled for SR-IOV to work\n");
- return -EINVAL;
- }
+ if (!iommu_present(&pci_bus_type))
+ dev_warn(&pdev->dev, "IOMMU should be enabled for SR-IOV to work correctly\n");
if (accel_dev->pf.vf_info) {
dev_info(&pdev->dev, "Already enabled for this device\n");
diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
index 2bd913aceaeb..59e4c3af15ed 100644
--- a/drivers/crypto/qat/qat_common/qat_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_algs.c
@@ -62,13 +62,13 @@
#include "icp_qat_fw.h"
#include "icp_qat_fw_la.h"
-#define QAT_AES_HW_CONFIG_CBC_ENC(alg) \
- ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \
+#define QAT_AES_HW_CONFIG_ENC(alg, mode) \
+ ICP_QAT_HW_CIPHER_CONFIG_BUILD(mode, alg, \
ICP_QAT_HW_CIPHER_NO_CONVERT, \
ICP_QAT_HW_CIPHER_ENCRYPT)
-#define QAT_AES_HW_CONFIG_CBC_DEC(alg) \
- ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \
+#define QAT_AES_HW_CONFIG_DEC(alg, mode) \
+ ICP_QAT_HW_CIPHER_CONFIG_BUILD(mode, alg, \
ICP_QAT_HW_CIPHER_KEY_CONVERT, \
ICP_QAT_HW_CIPHER_DECRYPT)
@@ -271,7 +271,8 @@ static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header)
static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm,
int alg,
- struct crypto_authenc_keys *keys)
+ struct crypto_authenc_keys *keys,
+ int mode)
{
struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(aead_tfm);
unsigned int digestsize = crypto_aead_authsize(aead_tfm);
@@ -288,7 +289,7 @@ static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm,
struct icp_qat_fw_auth_cd_ctrl_hdr *hash_cd_ctrl = ptr;
/* CD setup */
- cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_ENC(alg);
+ cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_ENC(alg, mode);
memcpy(cipher->aes.key, keys->enckey, keys->enckeylen);
hash->sha.inner_setup.auth_config.config =
ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
@@ -351,7 +352,8 @@ static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm,
static int qat_alg_aead_init_dec_session(struct crypto_aead *aead_tfm,
int alg,
- struct crypto_authenc_keys *keys)
+ struct crypto_authenc_keys *keys,
+ int mode)
{
struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(aead_tfm);
unsigned int digestsize = crypto_aead_authsize(aead_tfm);
@@ -373,7 +375,7 @@ static int qat_alg_aead_init_dec_session(struct crypto_aead *aead_tfm,
sizeof(struct icp_qat_fw_la_cipher_req_params));
/* CD setup */
- cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_DEC(alg);
+ cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_DEC(alg, mode);
memcpy(cipher->aes.key, keys->enckey, keys->enckeylen);
hash->sha.inner_setup.auth_config.config =
ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
@@ -464,7 +466,7 @@ static void qat_alg_ablkcipher_init_com(struct qat_alg_ablkcipher_ctx *ctx,
static void qat_alg_ablkcipher_init_enc(struct qat_alg_ablkcipher_ctx *ctx,
int alg, const uint8_t *key,
- unsigned int keylen)
+ unsigned int keylen, int mode)
{
struct icp_qat_hw_cipher_algo_blk *enc_cd = ctx->enc_cd;
struct icp_qat_fw_la_bulk_req *req = &ctx->enc_fw_req;
@@ -472,12 +474,12 @@ static void qat_alg_ablkcipher_init_enc(struct qat_alg_ablkcipher_ctx *ctx,
qat_alg_ablkcipher_init_com(ctx, req, enc_cd, key, keylen);
cd_pars->u.s.content_desc_addr = ctx->enc_cd_paddr;
- enc_cd->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_ENC(alg);
+ enc_cd->aes.cipher_config.val = QAT_AES_HW_CONFIG_ENC(alg, mode);
}
static void qat_alg_ablkcipher_init_dec(struct qat_alg_ablkcipher_ctx *ctx,
int alg, const uint8_t *key,
- unsigned int keylen)
+ unsigned int keylen, int mode)
{
struct icp_qat_hw_cipher_algo_blk *dec_cd = ctx->dec_cd;
struct icp_qat_fw_la_bulk_req *req = &ctx->dec_fw_req;
@@ -485,29 +487,48 @@ static void qat_alg_ablkcipher_init_dec(struct qat_alg_ablkcipher_ctx *ctx,
qat_alg_ablkcipher_init_com(ctx, req, dec_cd, key, keylen);
cd_pars->u.s.content_desc_addr = ctx->dec_cd_paddr;
- dec_cd->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_DEC(alg);
+
+ if (mode != ICP_QAT_HW_CIPHER_CTR_MODE)
+ dec_cd->aes.cipher_config.val =
+ QAT_AES_HW_CONFIG_DEC(alg, mode);
+ else
+ dec_cd->aes.cipher_config.val =
+ QAT_AES_HW_CONFIG_ENC(alg, mode);
}
-static int qat_alg_validate_key(int key_len, int *alg)
+static int qat_alg_validate_key(int key_len, int *alg, int mode)
{
- switch (key_len) {
- case AES_KEYSIZE_128:
- *alg = ICP_QAT_HW_CIPHER_ALGO_AES128;
- break;
- case AES_KEYSIZE_192:
- *alg = ICP_QAT_HW_CIPHER_ALGO_AES192;
- break;
- case AES_KEYSIZE_256:
- *alg = ICP_QAT_HW_CIPHER_ALGO_AES256;
- break;
- default:
- return -EINVAL;
+ if (mode != ICP_QAT_HW_CIPHER_XTS_MODE) {
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ *alg = ICP_QAT_HW_CIPHER_ALGO_AES128;
+ break;
+ case AES_KEYSIZE_192:
+ *alg = ICP_QAT_HW_CIPHER_ALGO_AES192;
+ break;
+ case AES_KEYSIZE_256:
+ *alg = ICP_QAT_HW_CIPHER_ALGO_AES256;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (key_len) {
+ case AES_KEYSIZE_128 << 1:
+ *alg = ICP_QAT_HW_CIPHER_ALGO_AES128;
+ break;
+ case AES_KEYSIZE_256 << 1:
+ *alg = ICP_QAT_HW_CIPHER_ALGO_AES256;
+ break;
+ default:
+ return -EINVAL;
+ }
}
return 0;
}
-static int qat_alg_aead_init_sessions(struct crypto_aead *tfm,
- const uint8_t *key, unsigned int keylen)
+static int qat_alg_aead_init_sessions(struct crypto_aead *tfm, const u8 *key,
+ unsigned int keylen, int mode)
{
struct crypto_authenc_keys keys;
int alg;
@@ -515,13 +536,13 @@ static int qat_alg_aead_init_sessions(struct crypto_aead *tfm,
if (crypto_authenc_extractkeys(&keys, key, keylen))
goto bad_key;
- if (qat_alg_validate_key(keys.enckeylen, &alg))
+ if (qat_alg_validate_key(keys.enckeylen, &alg, mode))
goto bad_key;
- if (qat_alg_aead_init_enc_session(tfm, alg, &keys))
+ if (qat_alg_aead_init_enc_session(tfm, alg, &keys, mode))
goto error;
- if (qat_alg_aead_init_dec_session(tfm, alg, &keys))
+ if (qat_alg_aead_init_dec_session(tfm, alg, &keys, mode))
goto error;
return 0;
@@ -534,15 +555,16 @@ error:
static int qat_alg_ablkcipher_init_sessions(struct qat_alg_ablkcipher_ctx *ctx,
const uint8_t *key,
- unsigned int keylen)
+ unsigned int keylen,
+ int mode)
{
int alg;
- if (qat_alg_validate_key(keylen, &alg))
+ if (qat_alg_validate_key(keylen, &alg, mode))
goto bad_key;
- qat_alg_ablkcipher_init_enc(ctx, alg, key, keylen);
- qat_alg_ablkcipher_init_dec(ctx, alg, key, keylen);
+ qat_alg_ablkcipher_init_enc(ctx, alg, key, keylen, mode);
+ qat_alg_ablkcipher_init_dec(ctx, alg, key, keylen, mode);
return 0;
bad_key:
crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
@@ -586,7 +608,8 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
goto out_free_enc;
}
}
- if (qat_alg_aead_init_sessions(tfm, key, keylen))
+ if (qat_alg_aead_init_sessions(tfm, key, keylen,
+ ICP_QAT_HW_CIPHER_CBC_MODE))
goto out_free_all;
return 0;
@@ -876,8 +899,8 @@ static int qat_alg_aead_enc(struct aead_request *areq)
}
static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
- const uint8_t *key,
- unsigned int keylen)
+ const u8 *key, unsigned int keylen,
+ int mode)
{
struct qat_alg_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
struct device *dev;
@@ -918,7 +941,7 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
}
}
spin_unlock(&ctx->lock);
- if (qat_alg_ablkcipher_init_sessions(ctx, key, keylen))
+ if (qat_alg_ablkcipher_init_sessions(ctx, key, keylen, mode))
goto out_free_all;
return 0;
@@ -936,6 +959,27 @@ out_free_enc:
return -ENOMEM;
}
+static int qat_alg_ablkcipher_cbc_setkey(struct crypto_ablkcipher *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ return qat_alg_ablkcipher_setkey(tfm, key, keylen,
+ ICP_QAT_HW_CIPHER_CBC_MODE);
+}
+
+static int qat_alg_ablkcipher_ctr_setkey(struct crypto_ablkcipher *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ return qat_alg_ablkcipher_setkey(tfm, key, keylen,
+ ICP_QAT_HW_CIPHER_CTR_MODE);
+}
+
+static int qat_alg_ablkcipher_xts_setkey(struct crypto_ablkcipher *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ return qat_alg_ablkcipher_setkey(tfm, key, keylen,
+ ICP_QAT_HW_CIPHER_XTS_MODE);
+}
+
static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req)
{
struct crypto_ablkcipher *atfm = crypto_ablkcipher_reqtfm(req);
@@ -1171,7 +1215,51 @@ static struct crypto_alg qat_algs[] = { {
.cra_exit = qat_alg_ablkcipher_exit,
.cra_u = {
.ablkcipher = {
- .setkey = qat_alg_ablkcipher_setkey,
+ .setkey = qat_alg_ablkcipher_cbc_setkey,
+ .decrypt = qat_alg_ablkcipher_decrypt,
+ .encrypt = qat_alg_ablkcipher_encrypt,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ },
+ },
+}, {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "qat_aes_ctr",
+ .cra_priority = 4001,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct qat_alg_ablkcipher_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = qat_alg_ablkcipher_init,
+ .cra_exit = qat_alg_ablkcipher_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .setkey = qat_alg_ablkcipher_ctr_setkey,
+ .decrypt = qat_alg_ablkcipher_decrypt,
+ .encrypt = qat_alg_ablkcipher_encrypt,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ },
+ },
+}, {
+ .cra_name = "xts(aes)",
+ .cra_driver_name = "qat_aes_xts",
+ .cra_priority = 4001,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct qat_alg_ablkcipher_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = qat_alg_ablkcipher_init,
+ .cra_exit = qat_alg_ablkcipher_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .setkey = qat_alg_ablkcipher_xts_setkey,
.decrypt = qat_alg_ablkcipher_decrypt,
.encrypt = qat_alg_ablkcipher_encrypt,
.min_keysize = AES_MIN_KEY_SIZE,
@@ -1212,7 +1300,7 @@ unreg_algs:
goto unlock;
}
-int qat_algs_unregister(void)
+void qat_algs_unregister(void)
{
mutex_lock(&algs_lock);
if (--active_devs != 0)
@@ -1223,14 +1311,4 @@ int qat_algs_unregister(void)
unlock:
mutex_unlock(&algs_lock);
- return 0;
-}
-
-int qat_algs_init(void)
-{
- return 0;
-}
-
-void qat_algs_exit(void)
-{
}
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index e87f51023ba4..51c594fdacdc 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -51,7 +51,9 @@
#include <crypto/akcipher.h>
#include <linux/dma-mapping.h>
#include <linux/fips.h>
-#include "qat_rsakey-asn1.h"
+#include <crypto/scatterwalk.h>
+#include "qat_rsapubkey-asn1.h"
+#include "qat_rsaprivkey-asn1.h"
#include "icp_qat_fw_pke.h"
#include "adf_accel_devices.h"
#include "adf_transport.h"
@@ -106,6 +108,7 @@ struct qat_rsa_request {
dma_addr_t phy_in;
dma_addr_t phy_out;
char *src_align;
+ char *dst_align;
struct icp_qat_fw_pke_request req;
struct qat_rsa_ctx *ctx;
int err;
@@ -118,7 +121,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
struct device *dev = &GET_DEV(req->ctx->inst->accel_dev);
int err = ICP_QAT_FW_PKE_RESP_PKE_STAT_GET(
resp->pke_resp_hdr.comn_resp_flags);
- char *ptr = areq->dst;
err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;
@@ -129,24 +131,44 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
dma_unmap_single(dev, req->in.enc.m, req->ctx->key_sz,
DMA_TO_DEVICE);
- dma_unmap_single(dev, req->out.enc.c, req->ctx->key_sz,
- DMA_FROM_DEVICE);
+ areq->dst_len = req->ctx->key_sz;
+ if (req->dst_align) {
+ char *ptr = req->dst_align;
+
+ while (!(*ptr) && areq->dst_len) {
+ areq->dst_len--;
+ ptr++;
+ }
+
+ if (areq->dst_len != req->ctx->key_sz)
+ memmove(req->dst_align, ptr, areq->dst_len);
+
+ scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
+ areq->dst_len, 1);
+
+ dma_free_coherent(dev, req->ctx->key_sz, req->dst_align,
+ req->out.enc.c);
+ } else {
+ char *ptr = sg_virt(areq->dst);
+
+ while (!(*ptr) && areq->dst_len) {
+ areq->dst_len--;
+ ptr++;
+ }
+
+ if (sg_virt(areq->dst) != ptr && areq->dst_len)
+ memmove(sg_virt(areq->dst), ptr, areq->dst_len);
+
+ dma_unmap_single(dev, req->out.enc.c, req->ctx->key_sz,
+ DMA_FROM_DEVICE);
+ }
+
dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
dma_unmap_single(dev, req->phy_out,
sizeof(struct qat_rsa_output_params),
DMA_TO_DEVICE);
- areq->dst_len = req->ctx->key_sz;
- /* Need to set the corect length of the output */
- while (!(*ptr) && areq->dst_len) {
- areq->dst_len--;
- ptr++;
- }
-
- if (areq->dst_len != req->ctx->key_sz)
- memmove(areq->dst, ptr, areq->dst_len);
-
akcipher_request_complete(areq, err);
}
@@ -255,8 +277,16 @@ static int qat_rsa_enc(struct akcipher_request *req)
* same as modulo n so in case it is different we need to allocate a
* new buf and copy src data.
* In other case we just need to map the user provided buffer.
+ * Also need to make sure that it is in contiguous buffer.
*/
- if (req->src_len < ctx->key_sz) {
+ if (sg_is_last(req->src) && req->src_len == ctx->key_sz) {
+ qat_req->src_align = NULL;
+ qat_req->in.enc.m = dma_map_single(dev, sg_virt(req->src),
+ req->src_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->in.enc.m)))
+ return ret;
+
+ } else {
int shift = ctx->key_sz - req->src_len;
qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
@@ -265,29 +295,39 @@ static int qat_rsa_enc(struct akcipher_request *req)
if (unlikely(!qat_req->src_align))
return ret;
- memcpy(qat_req->src_align + shift, req->src, req->src_len);
+ scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
+ 0, req->src_len, 0);
+ }
+ if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
+ qat_req->dst_align = NULL;
+ qat_req->out.enc.c = dma_map_single(dev, sg_virt(req->dst),
+ req->dst_len,
+ DMA_FROM_DEVICE);
+
+ if (unlikely(dma_mapping_error(dev, qat_req->out.enc.c)))
+ goto unmap_src;
+
} else {
- qat_req->src_align = NULL;
- qat_req->in.enc.m = dma_map_single(dev, req->src, req->src_len,
- DMA_TO_DEVICE);
+ qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ &qat_req->out.enc.c,
+ GFP_KERNEL);
+ if (unlikely(!qat_req->dst_align))
+ goto unmap_src;
+
}
qat_req->in.in_tab[3] = 0;
- qat_req->out.enc.c = dma_map_single(dev, req->dst, req->dst_len,
- DMA_FROM_DEVICE);
qat_req->out.out_tab[1] = 0;
qat_req->phy_in = dma_map_single(dev, &qat_req->in.enc.m,
sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_in)))
+ goto unmap_dst;
+
qat_req->phy_out = dma_map_single(dev, &qat_req->out.enc.c,
sizeof(struct qat_rsa_output_params),
- DMA_TO_DEVICE);
-
- if (unlikely((!qat_req->src_align &&
- dma_mapping_error(dev, qat_req->in.enc.m)) ||
- dma_mapping_error(dev, qat_req->out.enc.c) ||
- dma_mapping_error(dev, qat_req->phy_in) ||
- dma_mapping_error(dev, qat_req->phy_out)))
- goto unmap;
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_out)))
+ goto unmap_in_params;
msg->pke_mid.src_data_addr = qat_req->phy_in;
msg->pke_mid.dest_data_addr = qat_req->phy_out;
@@ -300,7 +340,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
if (!ret)
return -EINPROGRESS;
-unmap:
+unmap_src:
if (qat_req->src_align)
dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
qat_req->in.enc.m);
@@ -308,9 +348,15 @@ unmap:
if (!dma_mapping_error(dev, qat_req->in.enc.m))
dma_unmap_single(dev, qat_req->in.enc.m, ctx->key_sz,
DMA_TO_DEVICE);
- if (!dma_mapping_error(dev, qat_req->out.enc.c))
- dma_unmap_single(dev, qat_req->out.enc.c, ctx->key_sz,
- DMA_FROM_DEVICE);
+unmap_dst:
+ if (qat_req->dst_align)
+ dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align,
+ qat_req->out.enc.c);
+ else
+ if (!dma_mapping_error(dev, qat_req->out.enc.c))
+ dma_unmap_single(dev, qat_req->out.enc.c, ctx->key_sz,
+ DMA_FROM_DEVICE);
+unmap_in_params:
if (!dma_mapping_error(dev, qat_req->phy_in))
dma_unmap_single(dev, qat_req->phy_in,
sizeof(struct qat_rsa_input_params),
@@ -362,8 +408,16 @@ static int qat_rsa_dec(struct akcipher_request *req)
* same as modulo n so in case it is different we need to allocate a
* new buf and copy src data.
* In other case we just need to map the user provided buffer.
+ * Also need to make sure that it is in contiguous buffer.
*/
- if (req->src_len < ctx->key_sz) {
+ if (sg_is_last(req->src) && req->src_len == ctx->key_sz) {
+ qat_req->src_align = NULL;
+ qat_req->in.dec.c = dma_map_single(dev, sg_virt(req->src),
+ req->dst_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->in.dec.c)))
+ return ret;
+
+ } else {
int shift = ctx->key_sz - req->src_len;
qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
@@ -372,29 +426,40 @@ static int qat_rsa_dec(struct akcipher_request *req)
if (unlikely(!qat_req->src_align))
return ret;
- memcpy(qat_req->src_align + shift, req->src, req->src_len);
+ scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
+ 0, req->src_len, 0);
+ }
+ if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
+ qat_req->dst_align = NULL;
+ qat_req->out.dec.m = dma_map_single(dev, sg_virt(req->dst),
+ req->dst_len,
+ DMA_FROM_DEVICE);
+
+ if (unlikely(dma_mapping_error(dev, qat_req->out.dec.m)))
+ goto unmap_src;
+
} else {
- qat_req->src_align = NULL;
- qat_req->in.dec.c = dma_map_single(dev, req->src, req->src_len,
- DMA_TO_DEVICE);
+ qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ &qat_req->out.dec.m,
+ GFP_KERNEL);
+ if (unlikely(!qat_req->dst_align))
+ goto unmap_src;
+
}
+
qat_req->in.in_tab[3] = 0;
- qat_req->out.dec.m = dma_map_single(dev, req->dst, req->dst_len,
- DMA_FROM_DEVICE);
qat_req->out.out_tab[1] = 0;
qat_req->phy_in = dma_map_single(dev, &qat_req->in.dec.c,
sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_in)))
+ goto unmap_dst;
+
qat_req->phy_out = dma_map_single(dev, &qat_req->out.dec.m,
sizeof(struct qat_rsa_output_params),
- DMA_TO_DEVICE);
-
- if (unlikely((!qat_req->src_align &&
- dma_mapping_error(dev, qat_req->in.dec.c)) ||
- dma_mapping_error(dev, qat_req->out.dec.m) ||
- dma_mapping_error(dev, qat_req->phy_in) ||
- dma_mapping_error(dev, qat_req->phy_out)))
- goto unmap;
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_out)))
+ goto unmap_in_params;
msg->pke_mid.src_data_addr = qat_req->phy_in;
msg->pke_mid.dest_data_addr = qat_req->phy_out;
@@ -407,7 +472,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
if (!ret)
return -EINPROGRESS;
-unmap:
+unmap_src:
if (qat_req->src_align)
dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
qat_req->in.dec.c);
@@ -415,9 +480,15 @@ unmap:
if (!dma_mapping_error(dev, qat_req->in.dec.c))
dma_unmap_single(dev, qat_req->in.dec.c, ctx->key_sz,
DMA_TO_DEVICE);
- if (!dma_mapping_error(dev, qat_req->out.dec.m))
- dma_unmap_single(dev, qat_req->out.dec.m, ctx->key_sz,
- DMA_FROM_DEVICE);
+unmap_dst:
+ if (qat_req->dst_align)
+ dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align,
+ qat_req->out.dec.m);
+ else
+ if (!dma_mapping_error(dev, qat_req->out.dec.m))
+ dma_unmap_single(dev, qat_req->out.dec.m, ctx->key_sz,
+ DMA_FROM_DEVICE);
+unmap_in_params:
if (!dma_mapping_error(dev, qat_req->phy_in))
dma_unmap_single(dev, qat_req->phy_in,
sizeof(struct qat_rsa_input_params),
@@ -531,7 +602,7 @@ err:
}
static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
- unsigned int keylen)
+ unsigned int keylen, bool private)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct device *dev = &GET_DEV(ctx->inst->accel_dev);
@@ -550,7 +621,13 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
ctx->n = NULL;
ctx->e = NULL;
ctx->d = NULL;
- ret = asn1_ber_decoder(&qat_rsakey_decoder, ctx, key, keylen);
+
+ if (private)
+ ret = asn1_ber_decoder(&qat_rsaprivkey_decoder, ctx, key,
+ keylen);
+ else
+ ret = asn1_ber_decoder(&qat_rsapubkey_decoder, ctx, key,
+ keylen);
if (ret < 0)
goto free;
@@ -559,6 +636,11 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
ret = -EINVAL;
goto free;
}
+ if (private && !ctx->d) {
+ /* invalid private key provided */
+ ret = -EINVAL;
+ goto free;
+ }
return 0;
free:
@@ -579,6 +661,25 @@ free:
return ret;
}
+static int qat_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ return qat_rsa_setkey(tfm, key, keylen, false);
+}
+
+static int qat_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ return qat_rsa_setkey(tfm, key, keylen, true);
+}
+
+static int qat_rsa_max_size(struct crypto_akcipher *tfm)
+{
+ struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ return (ctx->n) ? ctx->key_sz : -EINVAL;
+}
+
static int qat_rsa_init_tfm(struct crypto_akcipher *tfm)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -617,7 +718,9 @@ static struct akcipher_alg rsa = {
.decrypt = qat_rsa_dec,
.sign = qat_rsa_dec,
.verify = qat_rsa_enc,
- .setkey = qat_rsa_setkey,
+ .set_pub_key = qat_rsa_setpubkey,
+ .set_priv_key = qat_rsa_setprivkey,
+ .max_size = qat_rsa_max_size,
.init = qat_rsa_init_tfm,
.exit = qat_rsa_exit_tfm,
.reqsize = sizeof(struct qat_rsa_request) + 64,
diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c
index 07c2f9f9d1fc..9cab15497f04 100644
--- a/drivers/crypto/qat/qat_common/qat_crypto.c
+++ b/drivers/crypto/qat/qat_common/qat_crypto.c
@@ -60,8 +60,8 @@ static struct service_hndl qat_crypto;
void qat_crypto_put_instance(struct qat_crypto_instance *inst)
{
- if (atomic_sub_return(1, &inst->refctr) == 0)
- adf_dev_put(inst->accel_dev);
+ atomic_dec(&inst->refctr);
+ adf_dev_put(inst->accel_dev);
}
static int qat_crypto_free_instances(struct adf_accel_dev *accel_dev)
@@ -97,49 +97,66 @@ static int qat_crypto_free_instances(struct adf_accel_dev *accel_dev)
struct qat_crypto_instance *qat_crypto_get_instance_node(int node)
{
struct adf_accel_dev *accel_dev = NULL;
- struct qat_crypto_instance *inst_best = NULL;
+ struct qat_crypto_instance *inst = NULL;
struct list_head *itr;
unsigned long best = ~0;
list_for_each(itr, adf_devmgr_get_head()) {
- accel_dev = list_entry(itr, struct adf_accel_dev, list);
+ struct adf_accel_dev *tmp_dev;
+ unsigned long ctr;
+
+ tmp_dev = list_entry(itr, struct adf_accel_dev, list);
+
+ if ((node == dev_to_node(&GET_DEV(tmp_dev)) ||
+ dev_to_node(&GET_DEV(tmp_dev)) < 0) &&
+ adf_dev_started(tmp_dev) &&
+ !list_empty(&tmp_dev->crypto_list)) {
+ ctr = atomic_read(&tmp_dev->ref_count);
+ if (best > ctr) {
+ accel_dev = tmp_dev;
+ best = ctr;
+ }
+ }
+ }
+ if (!accel_dev)
+ pr_info("QAT: Could not find a device on node %d\n", node);
+
+ /* Get any started device */
+ list_for_each(itr, adf_devmgr_get_head()) {
+ struct adf_accel_dev *tmp_dev;
- if ((node == dev_to_node(&GET_DEV(accel_dev)) ||
- dev_to_node(&GET_DEV(accel_dev)) < 0) &&
- adf_dev_started(accel_dev) &&
- !list_empty(&accel_dev->crypto_list))
+ tmp_dev = list_entry(itr, struct adf_accel_dev, list);
+
+ if (adf_dev_started(tmp_dev) &&
+ !list_empty(&tmp_dev->crypto_list)) {
+ accel_dev = tmp_dev;
break;
- accel_dev = NULL;
- }
- if (!accel_dev) {
- pr_err("QAT: Could not find a device on node %d\n", node);
- accel_dev = adf_devmgr_get_first();
+ }
}
- if (!accel_dev || !adf_dev_started(accel_dev))
+
+ if (!accel_dev)
return NULL;
+ best = ~0;
list_for_each(itr, &accel_dev->crypto_list) {
- struct qat_crypto_instance *inst;
- unsigned long cur;
-
- inst = list_entry(itr, struct qat_crypto_instance, list);
- cur = atomic_read(&inst->refctr);
- if (best > cur) {
- inst_best = inst;
- best = cur;
+ struct qat_crypto_instance *tmp_inst;
+ unsigned long ctr;
+
+ tmp_inst = list_entry(itr, struct qat_crypto_instance, list);
+ ctr = atomic_read(&tmp_inst->refctr);
+ if (best > ctr) {
+ inst = tmp_inst;
+ best = ctr;
}
}
- if (inst_best) {
- if (atomic_add_return(1, &inst_best->refctr) == 1) {
- if (adf_dev_get(accel_dev)) {
- atomic_dec(&inst_best->refctr);
- dev_err(&GET_DEV(accel_dev),
- "Could not increment dev refctr\n");
- return NULL;
- }
+ if (inst) {
+ if (adf_dev_get(accel_dev)) {
+ dev_err(&GET_DEV(accel_dev), "Could not increment dev refctr\n");
+ return NULL;
}
+ atomic_inc(&inst->refctr);
}
- return inst_best;
+ return inst;
}
static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c
index 8e711d1c3084..380e761801a7 100644
--- a/drivers/crypto/qat/qat_common/qat_hal.c
+++ b/drivers/crypto/qat/qat_common/qat_hal.c
@@ -1034,7 +1034,7 @@ static int qat_hal_concat_micro_code(uint64_t *micro_inst,
unsigned int inst_num, unsigned int size,
unsigned int addr, unsigned int *value)
{
- int i, val_indx;
+ int i;
unsigned int cur_value;
const uint64_t *inst_arr;
int fixup_offset;
@@ -1042,8 +1042,7 @@ static int qat_hal_concat_micro_code(uint64_t *micro_inst,
int orig_num;
orig_num = inst_num;
- val_indx = 0;
- cur_value = value[val_indx++];
+ cur_value = value[0];
inst_arr = inst_4b;
usize = ARRAY_SIZE(inst_4b);
fixup_offset = inst_num;
diff --git a/drivers/crypto/qat/qat_common/qat_rsakey.asn1 b/drivers/crypto/qat/qat_common/qat_rsakey.asn1
deleted file mode 100644
index 97b0e02b600a..000000000000
--- a/drivers/crypto/qat/qat_common/qat_rsakey.asn1
+++ /dev/null
@@ -1,5 +0,0 @@
-RsaKey ::= SEQUENCE {
- n INTEGER ({ qat_rsa_get_n }),
- e INTEGER ({ qat_rsa_get_e }),
- d INTEGER ({ qat_rsa_get_d })
-}
diff --git a/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
new file mode 100644
index 000000000000..f0066adb79b8
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
@@ -0,0 +1,11 @@
+RsaPrivKey ::= SEQUENCE {
+ version INTEGER,
+ n INTEGER ({ qat_rsa_get_n }),
+ e INTEGER ({ qat_rsa_get_e }),
+ d INTEGER ({ qat_rsa_get_d }),
+ prime1 INTEGER,
+ prime2 INTEGER,
+ exponent1 INTEGER,
+ exponent2 INTEGER,
+ coefficient INTEGER
+}
diff --git a/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
new file mode 100644
index 000000000000..bd667b31a21a
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
@@ -0,0 +1,4 @@
+RsaPubKey ::= SEQUENCE {
+ n INTEGER ({ qat_rsa_get_n }),
+ e INTEGER ({ qat_rsa_get_e })
+}
diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/ablkcipher.c
index ad592de475a4..2c0d63d48747 100644
--- a/drivers/crypto/qce/ablkcipher.c
+++ b/drivers/crypto/qce/ablkcipher.c
@@ -44,10 +44,8 @@ static void qce_ablkcipher_done(void *data)
error);
if (diff_dst)
- qce_unmapsg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src,
- rctx->dst_chained);
- qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
- rctx->dst_chained);
+ dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
sg_free_table(&rctx->dst_tbl);
@@ -80,15 +78,11 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
- rctx->src_nents = qce_countsg(req->src, req->nbytes,
- &rctx->src_chained);
- if (diff_dst) {
- rctx->dst_nents = qce_countsg(req->dst, req->nbytes,
- &rctx->dst_chained);
- } else {
+ rctx->src_nents = sg_nents_for_len(req->src, req->nbytes);
+ if (diff_dst)
+ rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes);
+ else
rctx->dst_nents = rctx->src_nents;
- rctx->dst_chained = rctx->src_chained;
- }
rctx->dst_nents += 1;
@@ -116,14 +110,12 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
sg_mark_end(sg);
rctx->dst_sg = rctx->dst_tbl.sgl;
- ret = qce_mapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
- rctx->dst_chained);
+ ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
if (ret < 0)
goto error_free;
if (diff_dst) {
- ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, dir_src,
- rctx->src_chained);
+ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
if (ret < 0)
goto error_unmap_dst;
rctx->src_sg = req->src;
@@ -149,11 +141,9 @@ error_terminate:
qce_dma_terminate_all(&qce->dma);
error_unmap_src:
if (diff_dst)
- qce_unmapsg(qce->dev, req->src, rctx->src_nents, dir_src,
- rctx->src_chained);
+ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
error_unmap_dst:
- qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
- rctx->dst_chained);
+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
error_free:
sg_free_table(&rctx->dst_tbl);
return ret;
diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h
index d5757cfcda2d..5c6a5f8633e5 100644
--- a/drivers/crypto/qce/cipher.h
+++ b/drivers/crypto/qce/cipher.h
@@ -32,8 +32,6 @@ struct qce_cipher_ctx {
* @ivsize: IV size
* @src_nents: source entries
* @dst_nents: destination entries
- * @src_chained: is source chained
- * @dst_chained: is destination chained
* @result_sg: scatterlist used for result buffer
* @dst_tbl: destination sg table
* @dst_sg: destination sg pointer table beginning
@@ -47,8 +45,6 @@ struct qce_cipher_reqctx {
unsigned int ivsize;
int src_nents;
int dst_nents;
- bool src_chained;
- bool dst_chained;
struct scatterlist result_sg;
struct sg_table dst_tbl;
struct scatterlist *dst_sg;
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
index 378cb768647f..4797e795c9b9 100644
--- a/drivers/crypto/qce/dma.c
+++ b/drivers/crypto/qce/dma.c
@@ -54,58 +54,6 @@ void qce_dma_release(struct qce_dma_data *dma)
kfree(dma->result_buf);
}
-int qce_mapsg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, bool chained)
-{
- int err;
-
- if (chained) {
- while (sg) {
- err = dma_map_sg(dev, sg, 1, dir);
- if (!err)
- return -EFAULT;
- sg = sg_next(sg);
- }
- } else {
- err = dma_map_sg(dev, sg, nents, dir);
- if (!err)
- return -EFAULT;
- }
-
- return nents;
-}
-
-void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, bool chained)
-{
- if (chained)
- while (sg) {
- dma_unmap_sg(dev, sg, 1, dir);
- sg = sg_next(sg);
- }
- else
- dma_unmap_sg(dev, sg, nents, dir);
-}
-
-int qce_countsg(struct scatterlist *sglist, int nbytes, bool *chained)
-{
- struct scatterlist *sg = sglist;
- int nents = 0;
-
- if (chained)
- *chained = false;
-
- while (nbytes > 0 && sg) {
- nents++;
- nbytes -= sg->length;
- if (!sg_is_last(sg) && (sg + 1)->length == 0 && chained)
- *chained = true;
- sg = sg_next(sg);
- }
-
- return nents;
-}
-
struct scatterlist *
qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl)
{
diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h
index 65bedb81de0b..130235d17bb4 100644
--- a/drivers/crypto/qce/dma.h
+++ b/drivers/crypto/qce/dma.h
@@ -49,11 +49,6 @@ int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in,
dma_async_tx_callback cb, void *cb_param);
void qce_dma_issue_pending(struct qce_dma_data *dma);
int qce_dma_terminate_all(struct qce_dma_data *dma);
-int qce_countsg(struct scatterlist *sg_list, int nbytes, bool *chained);
-void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, bool chained);
-int qce_mapsg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, bool chained);
struct scatterlist *
qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add);
diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c
index be2f5049256a..0c9973ec80eb 100644
--- a/drivers/crypto/qce/sha.c
+++ b/drivers/crypto/qce/sha.c
@@ -51,9 +51,8 @@ static void qce_ahash_done(void *data)
if (error)
dev_dbg(qce->dev, "ahash dma termination error (%d)\n", error);
- qce_unmapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
- rctx->src_chained);
- qce_unmapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
+ dma_unmap_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE);
memcpy(rctx->digest, result->auth_iv, digestsize);
if (req->result)
@@ -92,16 +91,14 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req)
rctx->authklen = AES_KEYSIZE_128;
}
- rctx->src_nents = qce_countsg(req->src, req->nbytes,
- &rctx->src_chained);
- ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
- rctx->src_chained);
+ rctx->src_nents = sg_nents_for_len(req->src, req->nbytes);
+ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
if (ret < 0)
return ret;
sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
- ret = qce_mapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+ ret = dma_map_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE);
if (ret < 0)
goto error_unmap_src;
@@ -121,10 +118,9 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req)
error_terminate:
qce_dma_terminate_all(&qce->dma);
error_unmap_dst:
- qce_unmapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+ dma_unmap_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE);
error_unmap_src:
- qce_unmapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
- rctx->src_chained);
+ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
return ret;
}
diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h
index 286f0d5397f3..236bb5e9ae75 100644
--- a/drivers/crypto/qce/sha.h
+++ b/drivers/crypto/qce/sha.h
@@ -36,7 +36,6 @@ struct qce_sha_ctx {
* @flags: operation flags
* @src_orig: original request sg list
* @nbytes_orig: original request number of bytes
- * @src_chained: is source scatterlist chained
* @src_nents: source number of entries
* @byte_count: byte count
* @count: save count in states during update, import and export
@@ -55,7 +54,6 @@ struct qce_sha_reqctx {
unsigned long flags;
struct scatterlist *src_orig;
unsigned int nbytes_orig;
- bool src_chained;
int src_nents;
__be32 byte_count[2];
u64 count;
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
index 820dc3acb28c..f68c24a98277 100644
--- a/drivers/crypto/sahara.c
+++ b/drivers/crypto/sahara.c
@@ -173,7 +173,6 @@ struct sahara_aes_reqctx {
* @sg_in_idx: number of hw links
* @in_sg: scatterlist for input data
* @in_sg_chain: scatterlists for chained input data
- * @in_sg_chained: specifies if chained scatterlists are used or not
* @total: total number of bytes for transfer
* @last: is this the last block
* @first: is this the first block
@@ -191,7 +190,6 @@ struct sahara_sha_reqctx {
unsigned int sg_in_idx;
struct scatterlist *in_sg;
struct scatterlist in_sg_chain[2];
- bool in_sg_chained;
size_t total;
unsigned int last;
unsigned int first;
@@ -274,31 +272,7 @@ static u32 sahara_aes_data_link_hdr(struct sahara_dev *dev)
SAHARA_HDR_CHA_SKHA | SAHARA_HDR_PARITY_BIT;
}
-static int sahara_sg_length(struct scatterlist *sg,
- unsigned int total)
-{
- int sg_nb;
- unsigned int len;
- struct scatterlist *sg_list;
-
- sg_nb = 0;
- sg_list = sg;
-
- while (total) {
- len = min(sg_list->length, total);
-
- sg_nb++;
- total -= len;
-
- sg_list = sg_next(sg_list);
- if (!sg_list)
- total = 0;
- }
-
- return sg_nb;
-}
-
-static char *sahara_err_src[16] = {
+static const char *sahara_err_src[16] = {
"No error",
"Header error",
"Descriptor length error",
@@ -317,14 +291,14 @@ static char *sahara_err_src[16] = {
"DMA error"
};
-static char *sahara_err_dmasize[4] = {
+static const char *sahara_err_dmasize[4] = {
"Byte transfer",
"Half-word transfer",
"Word transfer",
"Reserved"
};
-static char *sahara_err_dmasrc[8] = {
+static const char *sahara_err_dmasrc[8] = {
"No error",
"AHB bus error",
"Internal IP bus error",
@@ -335,7 +309,7 @@ static char *sahara_err_dmasrc[8] = {
"DMA HW error"
};
-static char *sahara_cha_errsrc[12] = {
+static const char *sahara_cha_errsrc[12] = {
"Input buffer non-empty",
"Illegal address",
"Illegal mode",
@@ -350,7 +324,7 @@ static char *sahara_cha_errsrc[12] = {
"Reserved"
};
-static char *sahara_cha_err[4] = { "No error", "SKHA", "MDHA", "RNG" };
+static const char *sahara_cha_err[4] = { "No error", "SKHA", "MDHA", "RNG" };
static void sahara_decode_error(struct sahara_dev *dev, unsigned int error)
{
@@ -380,7 +354,7 @@ static void sahara_decode_error(struct sahara_dev *dev, unsigned int error)
dev_err(dev->device, "\n");
}
-static char *sahara_state[4] = { "Idle", "Busy", "Error", "HW Fault" };
+static const char *sahara_state[4] = { "Idle", "Busy", "Error", "HW Fault" };
static void sahara_decode_status(struct sahara_dev *dev, unsigned int status)
{
@@ -502,8 +476,8 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev)
idx++;
}
- dev->nb_in_sg = sahara_sg_length(dev->in_sg, dev->total);
- dev->nb_out_sg = sahara_sg_length(dev->out_sg, dev->total);
+ dev->nb_in_sg = sg_nents_for_len(dev->in_sg, dev->total);
+ dev->nb_out_sg = sg_nents_for_len(dev->out_sg, dev->total);
if ((dev->nb_in_sg + dev->nb_out_sg) > SAHARA_MAX_HW_LINK) {
dev_err(dev->device, "not enough hw links (%d)\n",
dev->nb_in_sg + dev->nb_out_sg);
@@ -818,45 +792,26 @@ static int sahara_sha_hw_links_create(struct sahara_dev *dev,
dev->in_sg = rctx->in_sg;
- dev->nb_in_sg = sahara_sg_length(dev->in_sg, rctx->total);
+ dev->nb_in_sg = sg_nents_for_len(dev->in_sg, rctx->total);
if ((dev->nb_in_sg) > SAHARA_MAX_HW_LINK) {
dev_err(dev->device, "not enough hw links (%d)\n",
dev->nb_in_sg + dev->nb_out_sg);
return -EINVAL;
}
- if (rctx->in_sg_chained) {
- i = start;
- sg = dev->in_sg;
- while (sg) {
- ret = dma_map_sg(dev->device, sg, 1,
- DMA_TO_DEVICE);
- if (!ret)
- return -EFAULT;
-
- dev->hw_link[i]->len = sg->length;
- dev->hw_link[i]->p = sg->dma_address;
+ sg = dev->in_sg;
+ ret = dma_map_sg(dev->device, dev->in_sg, dev->nb_in_sg, DMA_TO_DEVICE);
+ if (!ret)
+ return -EFAULT;
+
+ for (i = start; i < dev->nb_in_sg + start; i++) {
+ dev->hw_link[i]->len = sg->length;
+ dev->hw_link[i]->p = sg->dma_address;
+ if (i == (dev->nb_in_sg + start - 1)) {
+ dev->hw_link[i]->next = 0;
+ } else {
dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
sg = sg_next(sg);
- i += 1;
- }
- dev->hw_link[i-1]->next = 0;
- } else {
- sg = dev->in_sg;
- ret = dma_map_sg(dev->device, dev->in_sg, dev->nb_in_sg,
- DMA_TO_DEVICE);
- if (!ret)
- return -EFAULT;
-
- for (i = start; i < dev->nb_in_sg + start; i++) {
- dev->hw_link[i]->len = sg->length;
- dev->hw_link[i]->p = sg->dma_address;
- if (i == (dev->nb_in_sg + start - 1)) {
- dev->hw_link[i]->next = 0;
- } else {
- dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
- sg = sg_next(sg);
- }
}
}
@@ -1004,7 +959,6 @@ static int sahara_sha_prepare_request(struct ahash_request *req)
rctx->total = req->nbytes + rctx->buf_cnt;
rctx->in_sg = rctx->in_sg_chain;
- rctx->in_sg_chained = true;
req->src = rctx->in_sg_chain;
/* only data from previous operation */
} else if (rctx->buf_cnt) {
@@ -1015,13 +969,11 @@ static int sahara_sha_prepare_request(struct ahash_request *req)
/* buf was copied into rembuf above */
sg_init_one(rctx->in_sg, rctx->rembuf, rctx->buf_cnt);
rctx->total = rctx->buf_cnt;
- rctx->in_sg_chained = false;
/* no data from previous operation */
} else {
rctx->in_sg = req->src;
rctx->total = req->nbytes;
req->src = rctx->in_sg;
- rctx->in_sg_chained = false;
}
/* on next call, we only have the remaining data in the buffer */
@@ -1030,23 +982,6 @@ static int sahara_sha_prepare_request(struct ahash_request *req)
return -EINPROGRESS;
}
-static void sahara_sha_unmap_sg(struct sahara_dev *dev,
- struct sahara_sha_reqctx *rctx)
-{
- struct scatterlist *sg;
-
- if (rctx->in_sg_chained) {
- sg = dev->in_sg;
- while (sg) {
- dma_unmap_sg(dev->device, sg, 1, DMA_TO_DEVICE);
- sg = sg_next(sg);
- }
- } else {
- dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
- DMA_TO_DEVICE);
- }
-}
-
static int sahara_sha_process(struct ahash_request *req)
{
struct sahara_dev *dev = dev_ptr;
@@ -1086,7 +1021,8 @@ static int sahara_sha_process(struct ahash_request *req)
}
if (rctx->sg_in_idx)
- sahara_sha_unmap_sg(dev, rctx);
+ dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
+ DMA_TO_DEVICE);
memcpy(rctx->context, dev->context_base, rctx->context_size);
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 3b20a1bce703..46f531e19ccf 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -857,8 +857,6 @@ badkey:
* talitos_edesc - s/w-extended descriptor
* @src_nents: number of segments in input scatterlist
* @dst_nents: number of segments in output scatterlist
- * @src_chained: whether src is chained or not
- * @dst_chained: whether dst is chained or not
* @icv_ool: whether ICV is out-of-line
* @iv_dma: dma address of iv for checking continuity and link table
* @dma_len: length of dma mapped link_tbl space
@@ -874,8 +872,6 @@ badkey:
struct talitos_edesc {
int src_nents;
int dst_nents;
- bool src_chained;
- bool dst_chained;
bool icv_ool;
dma_addr_t iv_dma;
int dma_len;
@@ -887,29 +883,6 @@ struct talitos_edesc {
};
};
-static int talitos_map_sg(struct device *dev, struct scatterlist *sg,
- unsigned int nents, enum dma_data_direction dir,
- bool chained)
-{
- if (unlikely(chained))
- while (sg) {
- dma_map_sg(dev, sg, 1, dir);
- sg = sg_next(sg);
- }
- else
- dma_map_sg(dev, sg, nents, dir);
- return nents;
-}
-
-static void talitos_unmap_sg_chain(struct device *dev, struct scatterlist *sg,
- enum dma_data_direction dir)
-{
- while (sg) {
- dma_unmap_sg(dev, sg, 1, dir);
- sg = sg_next(sg);
- }
-}
-
static void talitos_sg_unmap(struct device *dev,
struct talitos_edesc *edesc,
struct scatterlist *src,
@@ -919,24 +892,13 @@ static void talitos_sg_unmap(struct device *dev,
unsigned int dst_nents = edesc->dst_nents ? : 1;
if (src != dst) {
- if (edesc->src_chained)
- talitos_unmap_sg_chain(dev, src, DMA_TO_DEVICE);
- else
- dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
if (dst) {
- if (edesc->dst_chained)
- talitos_unmap_sg_chain(dev, dst,
- DMA_FROM_DEVICE);
- else
- dma_unmap_sg(dev, dst, dst_nents,
- DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
}
} else
- if (edesc->src_chained)
- talitos_unmap_sg_chain(dev, src, DMA_BIDIRECTIONAL);
- else
- dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
+ dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
}
static void ipsec_esp_unmap(struct device *dev,
@@ -1118,10 +1080,9 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
DMA_TO_DEVICE);
- sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ?: 1,
- (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
- : DMA_TO_DEVICE,
- edesc->src_chained);
+ sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ?: 1,
+ (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
+ : DMA_TO_DEVICE);
/* hmac data */
desc->ptr[1].len = cpu_to_be16(areq->assoclen);
@@ -1185,9 +1146,8 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
desc->ptr[5].j_extent = authsize;
if (areq->src != areq->dst)
- sg_count = talitos_map_sg(dev, areq->dst,
- edesc->dst_nents ? : 1,
- DMA_FROM_DEVICE, edesc->dst_chained);
+ sg_count = dma_map_sg(dev, areq->dst, edesc->dst_nents ? : 1,
+ DMA_FROM_DEVICE);
edesc->icv_ool = false;
@@ -1234,26 +1194,6 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
}
/*
- * derive number of elements in scatterlist
- */
-static int sg_count(struct scatterlist *sg_list, int nbytes, bool *chained)
-{
- struct scatterlist *sg = sg_list;
- int sg_nents = 0;
-
- *chained = false;
- while (nbytes > 0 && sg) {
- sg_nents++;
- nbytes -= sg->length;
- if (!sg_is_last(sg) && (sg + 1)->length == 0)
- *chained = true;
- sg = sg_next(sg);
- }
-
- return sg_nents;
-}
-
-/*
* allocate and map the extended descriptor
*/
static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
@@ -1270,7 +1210,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
{
struct talitos_edesc *edesc;
int src_nents, dst_nents, alloc_len, dma_len;
- bool src_chained = false, dst_chained = false;
dma_addr_t iv_dma = 0;
gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
GFP_ATOMIC;
@@ -1287,18 +1226,16 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
if (!dst || dst == src) {
- src_nents = sg_count(src, assoclen + cryptlen + authsize,
- &src_chained);
+ src_nents = sg_nents_for_len(src,
+ assoclen + cryptlen + authsize);
src_nents = (src_nents == 1) ? 0 : src_nents;
dst_nents = dst ? src_nents : 0;
} else { /* dst && dst != src*/
- src_nents = sg_count(src, assoclen + cryptlen +
- (encrypt ? 0 : authsize),
- &src_chained);
+ src_nents = sg_nents_for_len(src, assoclen + cryptlen +
+ (encrypt ? 0 : authsize));
src_nents = (src_nents == 1) ? 0 : src_nents;
- dst_nents = sg_count(dst, assoclen + cryptlen +
- (encrypt ? authsize : 0),
- &dst_chained);
+ dst_nents = sg_nents_for_len(dst, assoclen + cryptlen +
+ (encrypt ? authsize : 0));
dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
@@ -1332,8 +1269,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
edesc->src_nents = src_nents;
edesc->dst_nents = dst_nents;
- edesc->src_chained = src_chained;
- edesc->dst_chained = dst_chained;
edesc->iv_dma = iv_dma;
edesc->dma_len = dma_len;
if (dma_len)
@@ -1518,8 +1453,7 @@ int map_sg_in_talitos_ptr(struct device *dev, struct scatterlist *src,
} else {
to_talitos_ptr_extent_clear(ptr, is_sec1);
- sg_count = talitos_map_sg(dev, src, edesc->src_nents ? : 1, dir,
- edesc->src_chained);
+ sg_count = dma_map_sg(dev, src, edesc->src_nents ? : 1, dir);
if (sg_count == 1) {
to_talitos_ptr(ptr, sg_dma_address(src), is_sec1);
@@ -1552,8 +1486,7 @@ void map_sg_out_talitos_ptr(struct device *dev, struct scatterlist *dst,
bool is_sec1 = has_ftr_sec1(priv);
if (dir != DMA_NONE)
- sg_count = talitos_map_sg(dev, dst, edesc->dst_nents ? : 1,
- dir, edesc->dst_chained);
+ sg_count = dma_map_sg(dev, dst, edesc->dst_nents ? : 1, dir);
to_talitos_ptr_len(ptr, len, is_sec1);
@@ -1897,12 +1830,11 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
unsigned int nbytes_to_hash;
unsigned int to_hash_later;
unsigned int nsg;
- bool chained;
if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
/* Buffer up to one whole block */
sg_copy_to_buffer(areq->src,
- sg_count(areq->src, nbytes, &chained),
+ sg_nents_for_len(areq->src, nbytes),
req_ctx->buf + req_ctx->nbuf, nbytes);
req_ctx->nbuf += nbytes;
return 0;
@@ -1935,7 +1867,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
req_ctx->psrc = areq->src;
if (to_hash_later) {
- int nents = sg_count(areq->src, nbytes, &chained);
+ int nents = sg_nents_for_len(areq->src, nbytes);
sg_pcopy_to_buffer(areq->src, nents,
req_ctx->bufnext,
to_hash_later,
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index fded0a5cfcd7..4c243c1ffc7f 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -1414,7 +1414,7 @@ static int ux500_cryp_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
dev_dbg(dev, "[%s]", __func__);
- device_data = kzalloc(sizeof(struct cryp_device_data), GFP_ATOMIC);
+ device_data = devm_kzalloc(dev, sizeof(*device_data), GFP_ATOMIC);
if (!device_data) {
dev_err(dev, "[%s]: kzalloc() failed!", __func__);
ret = -ENOMEM;
@@ -1435,23 +1435,15 @@ static int ux500_cryp_probe(struct platform_device *pdev)
dev_err(dev, "[%s]: platform_get_resource() failed",
__func__);
ret = -ENODEV;
- goto out_kfree;
- }
-
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
- dev_err(dev, "[%s]: request_mem_region() failed",
- __func__);
- ret = -EBUSY;
- goto out_kfree;
+ goto out;
}
device_data->phybase = res->start;
- device_data->base = ioremap(res->start, resource_size(res));
+ device_data->base = devm_ioremap_resource(dev, res);
if (!device_data->base) {
dev_err(dev, "[%s]: ioremap failed!", __func__);
ret = -ENOMEM;
- goto out_free_mem;
+ goto out;
}
spin_lock_init(&device_data->ctx_lock);
@@ -1463,11 +1455,11 @@ static int ux500_cryp_probe(struct platform_device *pdev)
dev_err(dev, "[%s]: could not get cryp regulator", __func__);
ret = PTR_ERR(device_data->pwr_regulator);
device_data->pwr_regulator = NULL;
- goto out_unmap;
+ goto out;
}
/* Enable the clk for CRYP hardware block */
- device_data->clk = clk_get(&pdev->dev, NULL);
+ device_data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(device_data->clk)) {
dev_err(dev, "[%s]: clk_get() failed!", __func__);
ret = PTR_ERR(device_data->clk);
@@ -1477,7 +1469,7 @@ static int ux500_cryp_probe(struct platform_device *pdev)
ret = clk_prepare(device_data->clk);
if (ret) {
dev_err(dev, "[%s]: clk_prepare() failed!", __func__);
- goto out_clk;
+ goto out_regulator;
}
/* Enable device power (and clock) */
@@ -1510,11 +1502,8 @@ static int ux500_cryp_probe(struct platform_device *pdev)
goto out_power;
}
- ret = request_irq(res_irq->start,
- cryp_interrupt_handler,
- 0,
- "cryp1",
- device_data);
+ ret = devm_request_irq(&pdev->dev, res_irq->start,
+ cryp_interrupt_handler, 0, "cryp1", device_data);
if (ret) {
dev_err(dev, "[%s]: Unable to request IRQ", __func__);
goto out_power;
@@ -1550,28 +1539,15 @@ out_power:
out_clk_unprepare:
clk_unprepare(device_data->clk);
-out_clk:
- clk_put(device_data->clk);
-
out_regulator:
regulator_put(device_data->pwr_regulator);
-out_unmap:
- iounmap(device_data->base);
-
-out_free_mem:
- release_mem_region(res->start, resource_size(res));
-
-out_kfree:
- kfree(device_data);
out:
return ret;
}
static int ux500_cryp_remove(struct platform_device *pdev)
{
- struct resource *res = NULL;
- struct resource *res_irq = NULL;
struct cryp_device_data *device_data;
dev_dbg(&pdev->dev, "[%s]", __func__);
@@ -1607,37 +1583,18 @@ static int ux500_cryp_remove(struct platform_device *pdev)
if (list_empty(&driver_data.device_list.k_list))
cryp_algs_unregister_all();
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
- dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
- __func__);
- else {
- disable_irq(res_irq->start);
- free_irq(res_irq->start, device_data);
- }
-
if (cryp_disable_power(&pdev->dev, device_data, false))
dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed",
__func__);
clk_unprepare(device_data->clk);
- clk_put(device_data->clk);
regulator_put(device_data->pwr_regulator);
- iounmap(device_data->base);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res)
- release_mem_region(res->start, resource_size(res));
-
- kfree(device_data);
-
return 0;
}
static void ux500_cryp_shutdown(struct platform_device *pdev)
{
- struct resource *res_irq = NULL;
struct cryp_device_data *device_data;
dev_dbg(&pdev->dev, "[%s]", __func__);
@@ -1673,15 +1630,6 @@ static void ux500_cryp_shutdown(struct platform_device *pdev)
if (list_empty(&driver_data.device_list.k_list))
cryp_algs_unregister_all();
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
- dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
- __func__);
- else {
- disable_irq(res_irq->start);
- free_irq(res_irq->start, device_data);
- }
-
if (cryp_disable_power(&pdev->dev, device_data, false))
dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed",
__func__);
@@ -1777,6 +1725,7 @@ static const struct of_device_id ux500_cryp_match[] = {
{ .compatible = "stericsson,ux500-cryp" },
{ },
};
+MODULE_DEVICE_TABLE(of, ux500_cryp_match);
static struct platform_driver cryp_driver = {
.probe = ux500_cryp_probe,
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 5f5f360628fc..f47d112041b2 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -1657,7 +1657,7 @@ static int ux500_hash_probe(struct platform_device *pdev)
struct hash_device_data *device_data;
struct device *dev = &pdev->dev;
- device_data = kzalloc(sizeof(*device_data), GFP_ATOMIC);
+ device_data = devm_kzalloc(dev, sizeof(*device_data), GFP_ATOMIC);
if (!device_data) {
ret = -ENOMEM;
goto out;
@@ -1670,22 +1670,15 @@ static int ux500_hash_probe(struct platform_device *pdev)
if (!res) {
dev_dbg(dev, "%s: platform_get_resource() failed!\n", __func__);
ret = -ENODEV;
- goto out_kfree;
- }
-
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
- dev_dbg(dev, "%s: request_mem_region() failed!\n", __func__);
- ret = -EBUSY;
- goto out_kfree;
+ goto out;
}
device_data->phybase = res->start;
- device_data->base = ioremap(res->start, resource_size(res));
+ device_data->base = devm_ioremap_resource(dev, res);
if (!device_data->base) {
dev_err(dev, "%s: ioremap() failed!\n", __func__);
ret = -ENOMEM;
- goto out_free_mem;
+ goto out;
}
spin_lock_init(&device_data->ctx_lock);
spin_lock_init(&device_data->power_state_lock);
@@ -1696,11 +1689,11 @@ static int ux500_hash_probe(struct platform_device *pdev)
dev_err(dev, "%s: regulator_get() failed!\n", __func__);
ret = PTR_ERR(device_data->regulator);
device_data->regulator = NULL;
- goto out_unmap;
+ goto out;
}
/* Enable the clock for HASH1 hardware block */
- device_data->clk = clk_get(dev, NULL);
+ device_data->clk = devm_clk_get(dev, NULL);
if (IS_ERR(device_data->clk)) {
dev_err(dev, "%s: clk_get() failed!\n", __func__);
ret = PTR_ERR(device_data->clk);
@@ -1710,7 +1703,7 @@ static int ux500_hash_probe(struct platform_device *pdev)
ret = clk_prepare(device_data->clk);
if (ret) {
dev_err(dev, "%s: clk_prepare() failed!\n", __func__);
- goto out_clk;
+ goto out_regulator;
}
/* Enable device power (and clock) */
@@ -1752,20 +1745,9 @@ out_power:
out_clk_unprepare:
clk_unprepare(device_data->clk);
-out_clk:
- clk_put(device_data->clk);
-
out_regulator:
regulator_put(device_data->regulator);
-out_unmap:
- iounmap(device_data->base);
-
-out_free_mem:
- release_mem_region(res->start, resource_size(res));
-
-out_kfree:
- kfree(device_data);
out:
return ret;
}
@@ -1776,7 +1758,6 @@ out:
*/
static int ux500_hash_remove(struct platform_device *pdev)
{
- struct resource *res;
struct hash_device_data *device_data;
struct device *dev = &pdev->dev;
@@ -1816,17 +1797,8 @@ static int ux500_hash_remove(struct platform_device *pdev)
__func__);
clk_unprepare(device_data->clk);
- clk_put(device_data->clk);
regulator_put(device_data->regulator);
- iounmap(device_data->base);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res)
- release_mem_region(res->start, resource_size(res));
-
- kfree(device_data);
-
return 0;
}
@@ -1836,7 +1808,6 @@ static int ux500_hash_remove(struct platform_device *pdev)
*/
static void ux500_hash_shutdown(struct platform_device *pdev)
{
- struct resource *res = NULL;
struct hash_device_data *device_data;
device_data = platform_get_drvdata(pdev);
@@ -1870,12 +1841,6 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
if (list_empty(&driver_data.device_list.k_list))
ahash_algs_unregister_all(device_data);
- iounmap(device_data->base);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res)
- release_mem_region(res->start, resource_size(res));
-
if (hash_disable_power(device_data, false))
dev_err(&pdev->dev, "%s: hash_disable_power() failed\n",
__func__);
@@ -1958,6 +1923,7 @@ static const struct of_device_id ux500_hash_match[] = {
{ .compatible = "stericsson,ux500-hash" },
{ },
};
+MODULE_DEVICE_TABLE(of, ux500_hash_match);
static struct platform_driver hash_driver = {
.probe = ux500_hash_probe,
diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c
index 50ef8bd8708b..7b05dbe9b296 100644
--- a/drivers/dma-buf/fence.c
+++ b/drivers/dma-buf/fence.c
@@ -397,6 +397,104 @@ out:
}
EXPORT_SYMBOL(fence_default_wait);
+static bool
+fence_test_signaled_any(struct fence **fences, uint32_t count)
+{
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ struct fence *fence = fences[i];
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return true;
+ }
+ return false;
+}
+
+/**
+ * fence_wait_any_timeout - sleep until any fence gets signaled
+ * or until timeout elapses
+ * @fences: [in] array of fences to wait on
+ * @count: [in] number of fences to wait on
+ * @intr: [in] if true, do an interruptible wait
+ * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
+ *
+ * Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if
+ * interrupted, 0 if the wait timed out, or the remaining timeout in jiffies
+ * on success.
+ *
+ * Synchronous waits for the first fence in the array to be signaled. The
+ * caller needs to hold a reference to all fences in the array, otherwise a
+ * fence might be freed before return, resulting in undefined behavior.
+ */
+signed long
+fence_wait_any_timeout(struct fence **fences, uint32_t count,
+ bool intr, signed long timeout)
+{
+ struct default_wait_cb *cb;
+ signed long ret = timeout;
+ unsigned i;
+
+ if (WARN_ON(!fences || !count || timeout < 0))
+ return -EINVAL;
+
+ if (timeout == 0) {
+ for (i = 0; i < count; ++i)
+ if (fence_is_signaled(fences[i]))
+ return 1;
+
+ return 0;
+ }
+
+ cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL);
+ if (cb == NULL) {
+ ret = -ENOMEM;
+ goto err_free_cb;
+ }
+
+ for (i = 0; i < count; ++i) {
+ struct fence *fence = fences[i];
+
+ if (fence->ops->wait != fence_default_wait) {
+ ret = -EINVAL;
+ goto fence_rm_cb;
+ }
+
+ cb[i].task = current;
+ if (fence_add_callback(fence, &cb[i].base,
+ fence_default_wait_cb)) {
+ /* This fence is already signaled */
+ goto fence_rm_cb;
+ }
+ }
+
+ while (ret > 0) {
+ if (intr)
+ set_current_state(TASK_INTERRUPTIBLE);
+ else
+ set_current_state(TASK_UNINTERRUPTIBLE);
+
+ if (fence_test_signaled_any(fences, count))
+ break;
+
+ ret = schedule_timeout(ret);
+
+ if (ret > 0 && intr && signal_pending(current))
+ ret = -ERESTARTSYS;
+ }
+
+ __set_current_state(TASK_RUNNING);
+
+fence_rm_cb:
+ while (i-- > 0)
+ fence_remove_callback(fences[i], &cb[i].base);
+
+err_free_cb:
+ kfree(cb);
+
+ return ret;
+}
+EXPORT_SYMBOL(fence_wait_any_timeout);
+
/**
* fence_init - Initialize a custom fence.
* @fence: [in] the fence to initialize
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b4584757dae0..e6cd1a32025a 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -229,7 +229,7 @@ config IMX_SDMA
Support the i.MX SDMA engine. This engine is integrated into
Freescale i.MX25/31/35/51/53/6 chips.
-config IDMA64
+config INTEL_IDMA64
tristate "Intel integrated DMA 64-bit support"
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
@@ -486,7 +486,7 @@ config TI_EDMA
depends on ARCH_DAVINCI || ARCH_OMAP || ARCH_KEYSTONE
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
- select TI_PRIV_EDMA
+ select TI_DMA_CROSSBAR if ARCH_OMAP
default n
help
Enable support for the TI EDMA controller. This DMA
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 7711a7180726..ef9c099bd2b6 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_HSU_DMA) += hsu/
obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
obj-$(CONFIG_IMX_DMA) += imx-dma.o
obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
-obj-$(CONFIG_IDMA64) += idma64.o
+obj-$(CONFIG_INTEL_IDMA64) += idma64.o
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index 5a635646e05c..16d0daa058a5 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/acpi.h>
#include <linux/acpi_dma.h>
+#include <linux/property.h>
static LIST_HEAD(acpi_dma_list);
static DEFINE_MUTEX(acpi_dma_lock);
@@ -160,10 +161,8 @@ int acpi_dma_controller_register(struct device *dev,
return -EINVAL;
/* Check if the device was enumerated by ACPI */
- if (!ACPI_HANDLE(dev))
- return -EINVAL;
-
- if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
return -EINVAL;
adma = kzalloc(sizeof(*adma), GFP_KERNEL);
@@ -358,10 +357,11 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
int found;
/* Check if the device was enumerated by ACPI */
- if (!dev || !ACPI_HANDLE(dev))
+ if (!dev)
return ERR_PTR(-ENODEV);
- if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
return ERR_PTR(-ENODEV);
memset(&pdata, 0, sizeof(pdata));
@@ -413,21 +413,29 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
* translate the names "tx" and "rx" here based on the most common case where
* the first FixedDMA descriptor is TX and second is RX.
*
+ * If the device has "dma-names" property the FixedDMA descriptor indices
+ * are retrieved based on those. Otherwise the function falls back using
+ * hardcoded indices.
+ *
* Return:
* Pointer to appropriate dma channel on success or an error pointer.
*/
struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
const char *name)
{
- size_t index;
-
- if (!strcmp(name, "tx"))
- index = 0;
- else if (!strcmp(name, "rx"))
- index = 1;
- else
- return ERR_PTR(-ENODEV);
+ int index;
+
+ index = device_property_match_string(dev, "dma-names", name);
+ if (index < 0) {
+ if (!strcmp(name, "tx"))
+ index = 0;
+ else if (!strcmp(name, "rx"))
+ index = 1;
+ else
+ return ERR_PTR(-ENODEV);
+ }
+ dev_dbg(dev, "found DMA channel \"%s\" at index %d\n", name, index);
return acpi_dma_request_slave_chan_by_index(dev, index);
}
EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 58d406230d89..53d22eb73b56 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -458,10 +458,10 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
dma_cookie_complete(txd);
/* If the transfer was a memset, free our temporary buffer */
- if (desc->memset) {
+ if (desc->memset_buffer) {
dma_pool_free(atdma->memset_pool, desc->memset_vaddr,
desc->memset_paddr);
- desc->memset = false;
+ desc->memset_buffer = false;
}
/* move children to free_list */
@@ -729,8 +729,8 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
return NULL;
dev_info(chan2dev(chan),
- "%s: src=0x%08x, dest=0x%08x, numf=%d, frame_size=%d, flags=0x%lx\n",
- __func__, xt->src_start, xt->dst_start, xt->numf,
+ "%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n",
+ __func__, &xt->src_start, &xt->dst_start, xt->numf,
xt->frame_size, flags);
/*
@@ -824,8 +824,8 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
u32 ctrla;
u32 ctrlb;
- dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d0x%x s0x%x l0x%zx f0x%lx\n",
- dest, src, len, flags);
+ dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d%pad s%pad l0x%zx f0x%lx\n",
+ &dest, &src, len, flags);
if (unlikely(!len)) {
dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
@@ -881,6 +881,46 @@ err_desc_get:
return NULL;
}
+static struct at_desc *atc_create_memset_desc(struct dma_chan *chan,
+ dma_addr_t psrc,
+ dma_addr_t pdst,
+ size_t len)
+{
+ struct at_dma_chan *atchan = to_at_dma_chan(chan);
+ struct at_desc *desc;
+ size_t xfer_count;
+
+ u32 ctrla = ATC_SRC_WIDTH(2) | ATC_DST_WIDTH(2);
+ u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN |
+ ATC_SRC_ADDR_MODE_FIXED |
+ ATC_DST_ADDR_MODE_INCR |
+ ATC_FC_MEM2MEM;
+
+ xfer_count = len >> 2;
+ if (xfer_count > ATC_BTSIZE_MAX) {
+ dev_err(chan2dev(chan), "%s: buffer is too big\n",
+ __func__);
+ return NULL;
+ }
+
+ desc = atc_desc_get(atchan);
+ if (!desc) {
+ dev_err(chan2dev(chan), "%s: can't get a descriptor\n",
+ __func__);
+ return NULL;
+ }
+
+ desc->lli.saddr = psrc;
+ desc->lli.daddr = pdst;
+ desc->lli.ctrla = ctrla | xfer_count;
+ desc->lli.ctrlb = ctrlb;
+
+ desc->txd.cookie = 0;
+ desc->len = len;
+
+ return desc;
+}
+
/**
* atc_prep_dma_memset - prepare a memcpy operation
* @chan: the channel to prepare operation on
@@ -893,15 +933,13 @@ static struct dma_async_tx_descriptor *
atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
size_t len, unsigned long flags)
{
- struct at_dma_chan *atchan = to_at_dma_chan(chan);
struct at_dma *atdma = to_at_dma(chan->device);
- struct at_desc *desc = NULL;
- size_t xfer_count;
- u32 ctrla;
- u32 ctrlb;
+ struct at_desc *desc;
+ void __iomem *vaddr;
+ dma_addr_t paddr;
- dev_vdbg(chan2dev(chan), "%s: d0x%x v0x%x l0x%zx f0x%lx\n", __func__,
- dest, value, len, flags);
+ dev_vdbg(chan2dev(chan), "%s: d%pad v0x%x l0x%zx f0x%lx\n", __func__,
+ &dest, value, len, flags);
if (unlikely(!len)) {
dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__);
@@ -914,61 +952,117 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
return NULL;
}
- xfer_count = len >> 2;
- if (xfer_count > ATC_BTSIZE_MAX) {
- dev_err(chan2dev(chan), "%s: buffer is too big\n",
+ vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr);
+ if (!vaddr) {
+ dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n",
__func__);
return NULL;
}
+ *(u32*)vaddr = value;
- ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN
- | ATC_SRC_ADDR_MODE_FIXED
- | ATC_DST_ADDR_MODE_INCR
- | ATC_FC_MEM2MEM;
+ desc = atc_create_memset_desc(chan, paddr, dest, len);
+ if (!desc) {
+ dev_err(chan2dev(chan), "%s: couldn't get a descriptor\n",
+ __func__);
+ goto err_free_buffer;
+ }
- ctrla = ATC_SRC_WIDTH(2) |
- ATC_DST_WIDTH(2);
+ desc->memset_paddr = paddr;
+ desc->memset_vaddr = vaddr;
+ desc->memset_buffer = true;
- desc = atc_desc_get(atchan);
- if (!desc) {
- dev_err(chan2dev(chan), "%s: can't get a descriptor\n",
+ desc->txd.cookie = -EBUSY;
+ desc->total_len = len;
+
+ /* set end-of-link on the descriptor */
+ set_desc_eol(desc);
+
+ desc->txd.flags = flags;
+
+ return &desc->txd;
+
+err_free_buffer:
+ dma_pool_free(atdma->memset_pool, vaddr, paddr);
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+atc_prep_dma_memset_sg(struct dma_chan *chan,
+ struct scatterlist *sgl,
+ unsigned int sg_len, int value,
+ unsigned long flags)
+{
+ struct at_dma_chan *atchan = to_at_dma_chan(chan);
+ struct at_dma *atdma = to_at_dma(chan->device);
+ struct at_desc *desc = NULL, *first = NULL, *prev = NULL;
+ struct scatterlist *sg;
+ void __iomem *vaddr;
+ dma_addr_t paddr;
+ size_t total_len = 0;
+ int i;
+
+ dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%zx f0x%lx\n", __func__,
+ value, sg_len, flags);
+
+ if (unlikely(!sgl || !sg_len)) {
+ dev_dbg(chan2dev(chan), "%s: scatterlist is empty!\n",
__func__);
return NULL;
}
- desc->memset_vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC,
- &desc->memset_paddr);
- if (!desc->memset_vaddr) {
+ vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr);
+ if (!vaddr) {
dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n",
__func__);
- goto err_put_desc;
+ return NULL;
}
+ *(u32*)vaddr = value;
- *desc->memset_vaddr = value;
- desc->memset = true;
+ for_each_sg(sgl, sg, sg_len, i) {
+ dma_addr_t dest = sg_dma_address(sg);
+ size_t len = sg_dma_len(sg);
- desc->lli.saddr = desc->memset_paddr;
- desc->lli.daddr = dest;
- desc->lli.ctrla = ctrla | xfer_count;
- desc->lli.ctrlb = ctrlb;
+ dev_vdbg(chan2dev(chan), "%s: d%pad, l0x%zx\n",
+ __func__, &dest, len);
- desc->txd.cookie = -EBUSY;
- desc->len = len;
- desc->total_len = len;
+ if (!is_dma_fill_aligned(chan->device, dest, 0, len)) {
+ dev_err(chan2dev(chan), "%s: buffer is not aligned\n",
+ __func__);
+ goto err_put_desc;
+ }
+
+ desc = atc_create_memset_desc(chan, paddr, dest, len);
+ if (!desc)
+ goto err_put_desc;
+
+ atc_desc_chain(&first, &prev, desc);
+
+ total_len += len;
+ }
+
+ /*
+ * Only set the buffer pointers on the last descriptor to
+ * avoid free'ing while we have our transfer still going
+ */
+ desc->memset_paddr = paddr;
+ desc->memset_vaddr = vaddr;
+ desc->memset_buffer = true;
+
+ first->txd.cookie = -EBUSY;
+ first->total_len = total_len;
/* set end-of-link on the descriptor */
set_desc_eol(desc);
- desc->txd.flags = flags;
+ first->txd.flags = flags;
- return &desc->txd;
+ return &first->txd;
err_put_desc:
- atc_desc_put(atchan, desc);
+ atc_desc_put(atchan, first);
return NULL;
}
-
/**
* atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
* @chan: DMA channel
@@ -1345,9 +1439,9 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
unsigned int periods = buf_len / period_len;
unsigned int i;
- dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@0x%08x - %d (%d/%d)\n",
+ dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@%pad - %d (%d/%d)\n",
direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE",
- buf_addr,
+ &buf_addr,
periods, buf_len, period_len);
if (unlikely(!atslave || !buf_len || !period_len)) {
@@ -1851,6 +1945,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
dma_cap_set(DMA_INTERLEAVE, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_MEMSET, at91sam9g45_config.cap_mask);
+ dma_cap_set(DMA_MEMSET_SG, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_PRIVATE, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_SG, at91sam9g45_config.cap_mask);
@@ -1972,6 +2067,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
if (dma_has_cap(DMA_MEMSET, atdma->dma_common.cap_mask)) {
atdma->dma_common.device_prep_dma_memset = atc_prep_dma_memset;
+ atdma->dma_common.device_prep_dma_memset_sg = atc_prep_dma_memset_sg;
atdma->dma_common.fill_align = DMAENGINE_ALIGN_4_BYTES;
}
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index c3bebbe899ac..7f58f06157f6 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -202,7 +202,7 @@ struct at_desc {
size_t src_hole;
/* Memset temporary buffer */
- bool memset;
+ bool memset_buffer;
dma_addr_t memset_paddr;
int *memset_vaddr;
};
@@ -385,9 +385,9 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
{
dev_crit(chan2dev(&atchan->chan_common),
- " desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
- lli->saddr, lli->daddr,
- lli->ctrla, lli->ctrlb, lli->dscr);
+ " desc: s%pad d%pad ctrl0x%x:0x%x l0x%pad\n",
+ &lli->saddr, &lli->daddr,
+ lli->ctrla, lli->ctrlb, &lli->dscr);
}
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index dd24375b76dd..7f039de143f0 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -920,8 +920,8 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan,
desc->lld.mbr_cfg = chan_cc;
dev_dbg(chan2dev(chan),
- "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
- __func__, desc->lld.mbr_sa, desc->lld.mbr_da,
+ "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+ __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da,
desc->lld.mbr_ubc, desc->lld.mbr_cfg);
/* Chain lld. */
@@ -938,82 +938,82 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
{
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
struct at_xdmac_desc *prev = NULL, *first = NULL;
- struct data_chunk *chunk, *prev_chunk = NULL;
dma_addr_t dst_addr, src_addr;
- size_t dst_skip, src_skip, len = 0;
- size_t prev_dst_icg = 0, prev_src_icg = 0;
+ size_t src_skip = 0, dst_skip = 0, len = 0;
+ struct data_chunk *chunk;
int i;
- if (!xt || (xt->numf != 1) || (xt->dir != DMA_MEM_TO_MEM))
+ if (!xt || !xt->numf || (xt->dir != DMA_MEM_TO_MEM))
return NULL;
- dev_dbg(chan2dev(chan), "%s: src=0x%08x, dest=0x%08x, numf=%d, frame_size=%d, flags=0x%lx\n",
- __func__, xt->src_start, xt->dst_start, xt->numf,
+ /*
+ * TODO: Handle the case where we have to repeat a chain of
+ * descriptors...
+ */
+ if ((xt->numf > 1) && (xt->frame_size > 1))
+ return NULL;
+
+ dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n",
+ __func__, &xt->src_start, &xt->dst_start, xt->numf,
xt->frame_size, flags);
src_addr = xt->src_start;
dst_addr = xt->dst_start;
- for (i = 0; i < xt->frame_size; i++) {
- struct at_xdmac_desc *desc;
- size_t src_icg, dst_icg;
+ if (xt->numf > 1) {
+ first = at_xdmac_interleaved_queue_desc(chan, atchan,
+ NULL,
+ src_addr, dst_addr,
+ xt, xt->sgl);
+ for (i = 0; i < xt->numf; i++)
+ at_xdmac_increment_block_count(chan, first);
- chunk = xt->sgl + i;
+ dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+ __func__, first, first);
+ list_add_tail(&first->desc_node, &first->descs_list);
+ } else {
+ for (i = 0; i < xt->frame_size; i++) {
+ size_t src_icg = 0, dst_icg = 0;
+ struct at_xdmac_desc *desc;
- dst_icg = dmaengine_get_dst_icg(xt, chunk);
- src_icg = dmaengine_get_src_icg(xt, chunk);
+ chunk = xt->sgl + i;
- src_skip = chunk->size + src_icg;
- dst_skip = chunk->size + dst_icg;
+ dst_icg = dmaengine_get_dst_icg(xt, chunk);
+ src_icg = dmaengine_get_src_icg(xt, chunk);
- dev_dbg(chan2dev(chan),
- "%s: chunk size=%d, src icg=%d, dst icg=%d\n",
- __func__, chunk->size, src_icg, dst_icg);
+ src_skip = chunk->size + src_icg;
+ dst_skip = chunk->size + dst_icg;
- /*
- * Handle the case where we just have the same
- * transfer to setup, we can just increase the
- * block number and reuse the same descriptor.
- */
- if (prev_chunk && prev &&
- (prev_chunk->size == chunk->size) &&
- (prev_src_icg == src_icg) &&
- (prev_dst_icg == dst_icg)) {
dev_dbg(chan2dev(chan),
- "%s: same configuration that the previous chunk, merging the descriptors...\n",
- __func__);
- at_xdmac_increment_block_count(chan, prev);
- continue;
- }
-
- desc = at_xdmac_interleaved_queue_desc(chan, atchan,
- prev,
- src_addr, dst_addr,
- xt, chunk);
- if (!desc) {
- list_splice_init(&first->descs_list,
- &atchan->free_descs_list);
- return NULL;
- }
+ "%s: chunk size=%d, src icg=%d, dst icg=%d\n",
+ __func__, chunk->size, src_icg, dst_icg);
+
+ desc = at_xdmac_interleaved_queue_desc(chan, atchan,
+ prev,
+ src_addr, dst_addr,
+ xt, chunk);
+ if (!desc) {
+ list_splice_init(&first->descs_list,
+ &atchan->free_descs_list);
+ return NULL;
+ }
- if (!first)
- first = desc;
+ if (!first)
+ first = desc;
- dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
- __func__, desc, first);
- list_add_tail(&desc->desc_node, &first->descs_list);
+ dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+ __func__, desc, first);
+ list_add_tail(&desc->desc_node, &first->descs_list);
- if (xt->src_sgl)
- src_addr += src_skip;
+ if (xt->src_sgl)
+ src_addr += src_skip;
- if (xt->dst_sgl)
- dst_addr += dst_skip;
+ if (xt->dst_sgl)
+ dst_addr += dst_skip;
- len += chunk->size;
- prev_chunk = chunk;
- prev_dst_icg = dst_icg;
- prev_src_icg = src_icg;
- prev = desc;
+ len += chunk->size;
+ prev = desc;
+ }
}
first->tx_dma_desc.cookie = -EBUSY;
@@ -1179,8 +1179,8 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan,
desc->lld.mbr_cfg = chan_cc;
dev_dbg(chan2dev(chan),
- "%s: lld: mbr_da=0x%08x, mbr_ds=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
- __func__, desc->lld.mbr_da, desc->lld.mbr_ds, desc->lld.mbr_ubc,
+ "%s: lld: mbr_da=%pad, mbr_ds=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+ __func__, &desc->lld.mbr_da, &desc->lld.mbr_ds, desc->lld.mbr_ubc,
desc->lld.mbr_cfg);
return desc;
@@ -1193,8 +1193,8 @@ at_xdmac_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
struct at_xdmac_desc *desc;
- dev_dbg(chan2dev(chan), "%s: dest=0x%08x, len=%d, pattern=0x%x, flags=0x%lx\n",
- __func__, dest, len, value, flags);
+ dev_dbg(chan2dev(chan), "%s: dest=%pad, len=%d, pattern=0x%x, flags=0x%lx\n",
+ __func__, &dest, len, value, flags);
if (unlikely(!len))
return NULL;
@@ -1229,8 +1229,8 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl,
/* Prepare descriptors. */
for_each_sg(sgl, sg, sg_len, i) {
- dev_dbg(chan2dev(chan), "%s: dest=0x%08x, len=%d, pattern=0x%x, flags=0x%lx\n",
- __func__, sg_dma_address(sg), sg_dma_len(sg),
+ dev_dbg(chan2dev(chan), "%s: dest=%pad, len=%d, pattern=0x%x, flags=0x%lx\n",
+ __func__, &sg_dma_address(sg), sg_dma_len(sg),
value, flags);
desc = at_xdmac_memset_create_desc(chan, atchan,
sg_dma_address(sg),
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 09479d4be4db..3ecec1445adf 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -1074,11 +1074,9 @@ static void dmaengine_destroy_unmap_pool(void)
for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) {
struct dmaengine_unmap_pool *p = &unmap_pool[i];
- if (p->pool)
- mempool_destroy(p->pool);
+ mempool_destroy(p->pool);
p->pool = NULL;
- if (p->cache)
- kmem_cache_destroy(p->cache);
+ kmem_cache_destroy(p->cache);
p->cache = NULL;
}
}
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index bedce038c6e2..7067b6ddc1db 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -163,7 +163,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
/*----------------------------------------------------------------------*/
-static inline unsigned int dwc_fast_fls(unsigned long long v)
+static inline unsigned int dwc_fast_ffs(unsigned long long v)
{
/*
* We can be a lot more clever here, but this should take care
@@ -712,7 +712,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
dw->data_width[dwc->dst_master]);
src_width = dst_width = min_t(unsigned int, data_width,
- dwc_fast_fls(src | dest | len));
+ dwc_fast_ffs(src | dest | len));
ctllo = DWC_DEFAULT_CTLLO(chan)
| DWC_CTLL_DST_WIDTH(dst_width)
@@ -791,7 +791,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
switch (direction) {
case DMA_MEM_TO_DEV:
- reg_width = __fls(sconfig->dst_addr_width);
+ reg_width = __ffs(sconfig->dst_addr_width);
reg = sconfig->dst_addr;
ctllo = (DWC_DEFAULT_CTLLO(chan)
| DWC_CTLL_DST_WIDTH(reg_width)
@@ -811,7 +811,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
len = sg_dma_len(sg);
mem_width = min_t(unsigned int,
- data_width, dwc_fast_fls(mem | len));
+ data_width, dwc_fast_ffs(mem | len));
slave_sg_todev_fill_desc:
desc = dwc_desc_get(dwc);
@@ -848,7 +848,7 @@ slave_sg_todev_fill_desc:
}
break;
case DMA_DEV_TO_MEM:
- reg_width = __fls(sconfig->src_addr_width);
+ reg_width = __ffs(sconfig->src_addr_width);
reg = sconfig->src_addr;
ctllo = (DWC_DEFAULT_CTLLO(chan)
| DWC_CTLL_SRC_WIDTH(reg_width)
@@ -868,7 +868,7 @@ slave_sg_todev_fill_desc:
len = sg_dma_len(sg);
mem_width = min_t(unsigned int,
- data_width, dwc_fast_fls(mem | len));
+ data_width, dwc_fast_ffs(mem | len));
slave_sg_fromdev_fill_desc:
desc = dwc_desc_get(dwc);
@@ -1499,9 +1499,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free);
int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
{
struct dw_dma *dw;
- bool autocfg;
+ bool autocfg = false;
unsigned int dw_params;
- unsigned int nr_channels;
unsigned int max_blk_size = 0;
int err;
int i;
@@ -1515,33 +1514,42 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
pm_runtime_get_sync(chip->dev);
- dw_params = dma_read_byaddr(chip->regs, DW_PARAMS);
- autocfg = dw_params >> DW_PARAMS_EN & 0x1;
+ if (!pdata) {
+ dw_params = dma_read_byaddr(chip->regs, DW_PARAMS);
+ dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params);
- dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params);
+ autocfg = dw_params >> DW_PARAMS_EN & 1;
+ if (!autocfg) {
+ err = -EINVAL;
+ goto err_pdata;
+ }
- if (!pdata && autocfg) {
pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
err = -ENOMEM;
goto err_pdata;
}
+ /* Get hardware configuration parameters */
+ pdata->nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 7) + 1;
+ pdata->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
+ for (i = 0; i < pdata->nr_masters; i++) {
+ pdata->data_width[i] =
+ (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
+ }
+ max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
+
/* Fill platform data with the default values */
pdata->is_private = true;
+ pdata->is_memcpy = true;
pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING;
pdata->chan_priority = CHAN_PRIORITY_ASCENDING;
- } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) {
+ } else if (pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) {
err = -EINVAL;
goto err_pdata;
}
- if (autocfg)
- nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1;
- else
- nr_channels = pdata->nr_channels;
-
- dw->chan = devm_kcalloc(chip->dev, nr_channels, sizeof(*dw->chan),
+ dw->chan = devm_kcalloc(chip->dev, pdata->nr_channels, sizeof(*dw->chan),
GFP_KERNEL);
if (!dw->chan) {
err = -ENOMEM;
@@ -1549,22 +1557,12 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
}
/* Get hardware configuration parameters */
- if (autocfg) {
- max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
-
- dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
- for (i = 0; i < dw->nr_masters; i++) {
- dw->data_width[i] =
- (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
- }
- } else {
- dw->nr_masters = pdata->nr_masters;
- for (i = 0; i < dw->nr_masters; i++)
- dw->data_width[i] = pdata->data_width[i];
- }
+ dw->nr_masters = pdata->nr_masters;
+ for (i = 0; i < dw->nr_masters; i++)
+ dw->data_width[i] = pdata->data_width[i];
/* Calculate all channel mask before DMA setup */
- dw->all_chan_mask = (1 << nr_channels) - 1;
+ dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
/* Force dma off, just in case */
dw_dma_off(dw);
@@ -1589,7 +1587,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
goto err_pdata;
INIT_LIST_HEAD(&dw->dma.channels);
- for (i = 0; i < nr_channels; i++) {
+ for (i = 0; i < pdata->nr_channels; i++) {
struct dw_dma_chan *dwc = &dw->chan[i];
dwc->chan.device = &dw->dma;
@@ -1602,7 +1600,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
/* 7 is highest priority & 0 is lowest. */
if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
- dwc->priority = nr_channels - i - 1;
+ dwc->priority = pdata->nr_channels - i - 1;
else
dwc->priority = i;
@@ -1656,10 +1654,13 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask);
dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask);
- dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+ /* Set capabilities */
dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
if (pdata->is_private)
dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask);
+ if (pdata->is_memcpy)
+ dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+
dw->dma.dev = chip->dev;
dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
dw->dma.device_free_chan_resources = dwc_free_chan_resources;
@@ -1687,7 +1688,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
goto err_dma_register;
dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n",
- nr_channels);
+ pdata->nr_channels);
pm_runtime_put_sync_suspend(chip->dev);
diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c
index b144706b3d85..4c30fdd092b3 100644
--- a/drivers/dma/dw/pci.c
+++ b/drivers/dma/dw/pci.c
@@ -15,12 +15,6 @@
#include "internal.h"
-static struct dw_dma_platform_data dw_pci_pdata = {
- .is_private = 1,
- .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
- .chan_priority = CHAN_PRIORITY_ASCENDING,
-};
-
static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
{
struct dw_dma_chip *chip;
@@ -101,19 +95,19 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = {
static const struct pci_device_id dw_pci_id_table[] = {
/* Medfield */
- { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_pci_pdata },
- { PCI_VDEVICE(INTEL, 0x0830), (kernel_ulong_t)&dw_pci_pdata },
+ { PCI_VDEVICE(INTEL, 0x0827) },
+ { PCI_VDEVICE(INTEL, 0x0830) },
/* BayTrail */
- { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_pdata },
- { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_pdata },
+ { PCI_VDEVICE(INTEL, 0x0f06) },
+ { PCI_VDEVICE(INTEL, 0x0f40) },
/* Braswell */
- { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_pci_pdata },
- { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_pci_pdata },
+ { PCI_VDEVICE(INTEL, 0x2286) },
+ { PCI_VDEVICE(INTEL, 0x22c0) },
/* Haswell */
- { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_pdata },
+ { PCI_VDEVICE(INTEL, 0x9c60) },
{ }
};
MODULE_DEVICE_TABLE(pci, dw_pci_id_table);
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index b2c3ae071429..68a4815750b5 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -155,6 +155,7 @@ static int dw_probe(struct platform_device *pdev)
struct dw_dma_chip *chip;
struct device *dev = &pdev->dev;
struct resource *mem;
+ const struct acpi_device_id *id;
struct dw_dma_platform_data *pdata;
int err;
@@ -178,6 +179,11 @@ static int dw_probe(struct platform_device *pdev)
pdata = dev_get_platdata(dev);
if (!pdata)
pdata = dw_dma_parse_dt(pdev);
+ if (!pdata && has_acpi_companion(dev)) {
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (id)
+ pdata = (struct dw_dma_platform_data *)id->driver_data;
+ }
chip->dev = dev;
@@ -246,8 +252,17 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
#endif
#ifdef CONFIG_ACPI
+static struct dw_dma_platform_data dw_dma_acpi_pdata = {
+ .nr_channels = 8,
+ .is_private = true,
+ .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .block_size = 4095,
+ .nr_masters = 2,
+};
+
static const struct acpi_device_id dw_dma_acpi_id_table[] = {
- { "INTL9C60", 0 },
+ { "INTL9C60", (kernel_ulong_t)&dw_dma_acpi_pdata },
{ }
};
MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 3e5d4f193005..0675e268d577 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -25,28 +25,93 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
#include <linux/platform_data/edma.h>
#include "dmaengine.h"
#include "virt-dma.h"
-/*
- * This will go away when the private EDMA API is folded
- * into this driver and the platform device(s) are
- * instantiated in the arch code. We can only get away
- * with this simplification because DA8XX may not be built
- * in the same kernel image with other DaVinci parts. This
- * avoids having to sprinkle dmaengine driver platform devices
- * and data throughout all the existing board files.
- */
-#ifdef CONFIG_ARCH_DAVINCI_DA8XX
-#define EDMA_CTLRS 2
-#define EDMA_CHANS 32
-#else
-#define EDMA_CTLRS 1
-#define EDMA_CHANS 64
-#endif /* CONFIG_ARCH_DAVINCI_DA8XX */
+/* Offsets matching "struct edmacc_param" */
+#define PARM_OPT 0x00
+#define PARM_SRC 0x04
+#define PARM_A_B_CNT 0x08
+#define PARM_DST 0x0c
+#define PARM_SRC_DST_BIDX 0x10
+#define PARM_LINK_BCNTRLD 0x14
+#define PARM_SRC_DST_CIDX 0x18
+#define PARM_CCNT 0x1c
+
+#define PARM_SIZE 0x20
+
+/* Offsets for EDMA CC global channel registers and their shadows */
+#define SH_ER 0x00 /* 64 bits */
+#define SH_ECR 0x08 /* 64 bits */
+#define SH_ESR 0x10 /* 64 bits */
+#define SH_CER 0x18 /* 64 bits */
+#define SH_EER 0x20 /* 64 bits */
+#define SH_EECR 0x28 /* 64 bits */
+#define SH_EESR 0x30 /* 64 bits */
+#define SH_SER 0x38 /* 64 bits */
+#define SH_SECR 0x40 /* 64 bits */
+#define SH_IER 0x50 /* 64 bits */
+#define SH_IECR 0x58 /* 64 bits */
+#define SH_IESR 0x60 /* 64 bits */
+#define SH_IPR 0x68 /* 64 bits */
+#define SH_ICR 0x70 /* 64 bits */
+#define SH_IEVAL 0x78
+#define SH_QER 0x80
+#define SH_QEER 0x84
+#define SH_QEECR 0x88
+#define SH_QEESR 0x8c
+#define SH_QSER 0x90
+#define SH_QSECR 0x94
+#define SH_SIZE 0x200
+
+/* Offsets for EDMA CC global registers */
+#define EDMA_REV 0x0000
+#define EDMA_CCCFG 0x0004
+#define EDMA_QCHMAP 0x0200 /* 8 registers */
+#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
+#define EDMA_QDMAQNUM 0x0260
+#define EDMA_QUETCMAP 0x0280
+#define EDMA_QUEPRI 0x0284
+#define EDMA_EMR 0x0300 /* 64 bits */
+#define EDMA_EMCR 0x0308 /* 64 bits */
+#define EDMA_QEMR 0x0310
+#define EDMA_QEMCR 0x0314
+#define EDMA_CCERR 0x0318
+#define EDMA_CCERRCLR 0x031c
+#define EDMA_EEVAL 0x0320
+#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
+#define EDMA_QRAE 0x0380 /* 4 registers */
+#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
+#define EDMA_QSTAT 0x0600 /* 2 registers */
+#define EDMA_QWMTHRA 0x0620
+#define EDMA_QWMTHRB 0x0624
+#define EDMA_CCSTAT 0x0640
+
+#define EDMA_M 0x1000 /* global channel registers */
+#define EDMA_ECR 0x1008
+#define EDMA_ECRH 0x100C
+#define EDMA_SHADOW0 0x2000 /* 4 shadow regions */
+#define EDMA_PARM 0x4000 /* PaRAM entries */
+
+#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
+
+#define EDMA_DCHMAP 0x0100 /* 64 registers */
+
+/* CCCFG register */
+#define GET_NUM_DMACH(x) (x & 0x7) /* bits 0-2 */
+#define GET_NUM_QDMACH(x) ((x & 0x70) >> 4) /* bits 4-6 */
+#define GET_NUM_PAENTRY(x) ((x & 0x7000) >> 12) /* bits 12-14 */
+#define GET_NUM_EVQUE(x) ((x & 0x70000) >> 16) /* bits 16-18 */
+#define GET_NUM_REGN(x) ((x & 0x300000) >> 20) /* bits 20-21 */
+#define CHMAP_EXIST BIT(24)
/*
* Max of 20 segments per channel to conserve PaRAM slots
@@ -59,6 +124,37 @@
#define EDMA_MAX_SLOTS MAX_NR_SG
#define EDMA_DESCRIPTORS 16
+#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
+#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
+#define EDMA_CONT_PARAMS_ANY 1001
+#define EDMA_CONT_PARAMS_FIXED_EXACT 1002
+#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
+
+/* PaRAM slots are laid out like this */
+struct edmacc_param {
+ u32 opt;
+ u32 src;
+ u32 a_b_cnt;
+ u32 dst;
+ u32 src_dst_bidx;
+ u32 link_bcntrld;
+ u32 src_dst_cidx;
+ u32 ccnt;
+} __packed;
+
+/* fields in edmacc_param.opt */
+#define SAM BIT(0)
+#define DAM BIT(1)
+#define SYNCDIM BIT(2)
+#define STATIC BIT(3)
+#define EDMA_FWID (0x07 << 8)
+#define TCCMODE BIT(11)
+#define EDMA_TCC(t) ((t) << 12)
+#define TCINTEN BIT(20)
+#define ITCINTEN BIT(21)
+#define TCCHEN BIT(22)
+#define ITCCHEN BIT(23)
+
struct edma_pset {
u32 len;
dma_addr_t addr;
@@ -105,26 +201,524 @@ struct edma_desc {
struct edma_cc;
+struct edma_tc {
+ struct device_node *node;
+ u16 id;
+};
+
struct edma_chan {
struct virt_dma_chan vchan;
struct list_head node;
struct edma_desc *edesc;
struct edma_cc *ecc;
+ struct edma_tc *tc;
int ch_num;
bool alloced;
+ bool hw_triggered;
int slot[EDMA_MAX_SLOTS];
int missed;
struct dma_slave_config cfg;
};
struct edma_cc {
- int ctlr;
+ struct device *dev;
+ struct edma_soc_info *info;
+ void __iomem *base;
+ int id;
+ bool legacy_mode;
+
+ /* eDMA3 resource information */
+ unsigned num_channels;
+ unsigned num_qchannels;
+ unsigned num_region;
+ unsigned num_slots;
+ unsigned num_tc;
+ bool chmap_exist;
+ enum dma_event_q default_queue;
+
+ /*
+ * The slot_inuse bit for each PaRAM slot is clear unless the slot is
+ * in use by Linux or if it is allocated to be used by DSP.
+ */
+ unsigned long *slot_inuse;
+
struct dma_device dma_slave;
- struct edma_chan slave_chans[EDMA_CHANS];
- int num_slave_chans;
+ struct dma_device *dma_memcpy;
+ struct edma_chan *slave_chans;
+ struct edma_tc *tc_list;
int dummy_slot;
};
+/* dummy param set used to (re)initialize parameter RAM slots */
+static const struct edmacc_param dummy_paramset = {
+ .link_bcntrld = 0xffff,
+ .ccnt = 1,
+};
+
+#define EDMA_BINDING_LEGACY 0
+#define EDMA_BINDING_TPCC 1
+static const struct of_device_id edma_of_ids[] = {
+ {
+ .compatible = "ti,edma3",
+ .data = (void *)EDMA_BINDING_LEGACY,
+ },
+ {
+ .compatible = "ti,edma3-tpcc",
+ .data = (void *)EDMA_BINDING_TPCC,
+ },
+ {}
+};
+
+static const struct of_device_id edma_tptc_of_ids[] = {
+ { .compatible = "ti,edma3-tptc", },
+ {}
+};
+
+static inline unsigned int edma_read(struct edma_cc *ecc, int offset)
+{
+ return (unsigned int)__raw_readl(ecc->base + offset);
+}
+
+static inline void edma_write(struct edma_cc *ecc, int offset, int val)
+{
+ __raw_writel(val, ecc->base + offset);
+}
+
+static inline void edma_modify(struct edma_cc *ecc, int offset, unsigned and,
+ unsigned or)
+{
+ unsigned val = edma_read(ecc, offset);
+
+ val &= and;
+ val |= or;
+ edma_write(ecc, offset, val);
+}
+
+static inline void edma_and(struct edma_cc *ecc, int offset, unsigned and)
+{
+ unsigned val = edma_read(ecc, offset);
+
+ val &= and;
+ edma_write(ecc, offset, val);
+}
+
+static inline void edma_or(struct edma_cc *ecc, int offset, unsigned or)
+{
+ unsigned val = edma_read(ecc, offset);
+
+ val |= or;
+ edma_write(ecc, offset, val);
+}
+
+static inline unsigned int edma_read_array(struct edma_cc *ecc, int offset,
+ int i)
+{
+ return edma_read(ecc, offset + (i << 2));
+}
+
+static inline void edma_write_array(struct edma_cc *ecc, int offset, int i,
+ unsigned val)
+{
+ edma_write(ecc, offset + (i << 2), val);
+}
+
+static inline void edma_modify_array(struct edma_cc *ecc, int offset, int i,
+ unsigned and, unsigned or)
+{
+ edma_modify(ecc, offset + (i << 2), and, or);
+}
+
+static inline void edma_or_array(struct edma_cc *ecc, int offset, int i,
+ unsigned or)
+{
+ edma_or(ecc, offset + (i << 2), or);
+}
+
+static inline void edma_or_array2(struct edma_cc *ecc, int offset, int i, int j,
+ unsigned or)
+{
+ edma_or(ecc, offset + ((i * 2 + j) << 2), or);
+}
+
+static inline void edma_write_array2(struct edma_cc *ecc, int offset, int i,
+ int j, unsigned val)
+{
+ edma_write(ecc, offset + ((i * 2 + j) << 2), val);
+}
+
+static inline unsigned int edma_shadow0_read(struct edma_cc *ecc, int offset)
+{
+ return edma_read(ecc, EDMA_SHADOW0 + offset);
+}
+
+static inline unsigned int edma_shadow0_read_array(struct edma_cc *ecc,
+ int offset, int i)
+{
+ return edma_read(ecc, EDMA_SHADOW0 + offset + (i << 2));
+}
+
+static inline void edma_shadow0_write(struct edma_cc *ecc, int offset,
+ unsigned val)
+{
+ edma_write(ecc, EDMA_SHADOW0 + offset, val);
+}
+
+static inline void edma_shadow0_write_array(struct edma_cc *ecc, int offset,
+ int i, unsigned val)
+{
+ edma_write(ecc, EDMA_SHADOW0 + offset + (i << 2), val);
+}
+
+static inline unsigned int edma_param_read(struct edma_cc *ecc, int offset,
+ int param_no)
+{
+ return edma_read(ecc, EDMA_PARM + offset + (param_no << 5));
+}
+
+static inline void edma_param_write(struct edma_cc *ecc, int offset,
+ int param_no, unsigned val)
+{
+ edma_write(ecc, EDMA_PARM + offset + (param_no << 5), val);
+}
+
+static inline void edma_param_modify(struct edma_cc *ecc, int offset,
+ int param_no, unsigned and, unsigned or)
+{
+ edma_modify(ecc, EDMA_PARM + offset + (param_no << 5), and, or);
+}
+
+static inline void edma_param_and(struct edma_cc *ecc, int offset, int param_no,
+ unsigned and)
+{
+ edma_and(ecc, EDMA_PARM + offset + (param_no << 5), and);
+}
+
+static inline void edma_param_or(struct edma_cc *ecc, int offset, int param_no,
+ unsigned or)
+{
+ edma_or(ecc, EDMA_PARM + offset + (param_no << 5), or);
+}
+
+static inline void set_bits(int offset, int len, unsigned long *p)
+{
+ for (; len > 0; len--)
+ set_bit(offset + (len - 1), p);
+}
+
+static inline void clear_bits(int offset, int len, unsigned long *p)
+{
+ for (; len > 0; len--)
+ clear_bit(offset + (len - 1), p);
+}
+
+static void edma_assign_priority_to_queue(struct edma_cc *ecc, int queue_no,
+ int priority)
+{
+ int bit = queue_no * 4;
+
+ edma_modify(ecc, EDMA_QUEPRI, ~(0x7 << bit), ((priority & 0x7) << bit));
+}
+
+static void edma_set_chmap(struct edma_chan *echan, int slot)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+
+ if (ecc->chmap_exist) {
+ slot = EDMA_CHAN_SLOT(slot);
+ edma_write_array(ecc, EDMA_DCHMAP, channel, (slot << 5));
+ }
+}
+
+static void edma_setup_interrupt(struct edma_chan *echan, bool enable)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+
+ if (enable) {
+ edma_shadow0_write_array(ecc, SH_ICR, channel >> 5,
+ BIT(channel & 0x1f));
+ edma_shadow0_write_array(ecc, SH_IESR, channel >> 5,
+ BIT(channel & 0x1f));
+ } else {
+ edma_shadow0_write_array(ecc, SH_IECR, channel >> 5,
+ BIT(channel & 0x1f));
+ }
+}
+
+/*
+ * paRAM slot management functions
+ */
+static void edma_write_slot(struct edma_cc *ecc, unsigned slot,
+ const struct edmacc_param *param)
+{
+ slot = EDMA_CHAN_SLOT(slot);
+ if (slot >= ecc->num_slots)
+ return;
+ memcpy_toio(ecc->base + PARM_OFFSET(slot), param, PARM_SIZE);
+}
+
+static void edma_read_slot(struct edma_cc *ecc, unsigned slot,
+ struct edmacc_param *param)
+{
+ slot = EDMA_CHAN_SLOT(slot);
+ if (slot >= ecc->num_slots)
+ return;
+ memcpy_fromio(param, ecc->base + PARM_OFFSET(slot), PARM_SIZE);
+}
+
+/**
+ * edma_alloc_slot - allocate DMA parameter RAM
+ * @ecc: pointer to edma_cc struct
+ * @slot: specific slot to allocate; negative for "any unused slot"
+ *
+ * This allocates a parameter RAM slot, initializing it to hold a
+ * dummy transfer. Slots allocated using this routine have not been
+ * mapped to a hardware DMA channel, and will normally be used by
+ * linking to them from a slot associated with a DMA channel.
+ *
+ * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
+ * slots may be allocated on behalf of DSP firmware.
+ *
+ * Returns the number of the slot, else negative errno.
+ */
+static int edma_alloc_slot(struct edma_cc *ecc, int slot)
+{
+ if (slot > 0) {
+ slot = EDMA_CHAN_SLOT(slot);
+ /* Requesting entry paRAM slot for a HW triggered channel. */
+ if (ecc->chmap_exist && slot < ecc->num_channels)
+ slot = EDMA_SLOT_ANY;
+ }
+
+ if (slot < 0) {
+ if (ecc->chmap_exist)
+ slot = 0;
+ else
+ slot = ecc->num_channels;
+ for (;;) {
+ slot = find_next_zero_bit(ecc->slot_inuse,
+ ecc->num_slots,
+ slot);
+ if (slot == ecc->num_slots)
+ return -ENOMEM;
+ if (!test_and_set_bit(slot, ecc->slot_inuse))
+ break;
+ }
+ } else if (slot >= ecc->num_slots) {
+ return -EINVAL;
+ } else if (test_and_set_bit(slot, ecc->slot_inuse)) {
+ return -EBUSY;
+ }
+
+ edma_write_slot(ecc, slot, &dummy_paramset);
+
+ return EDMA_CTLR_CHAN(ecc->id, slot);
+}
+
+static void edma_free_slot(struct edma_cc *ecc, unsigned slot)
+{
+ slot = EDMA_CHAN_SLOT(slot);
+ if (slot >= ecc->num_slots)
+ return;
+
+ edma_write_slot(ecc, slot, &dummy_paramset);
+ clear_bit(slot, ecc->slot_inuse);
+}
+
+/**
+ * edma_link - link one parameter RAM slot to another
+ * @ecc: pointer to edma_cc struct
+ * @from: parameter RAM slot originating the link
+ * @to: parameter RAM slot which is the link target
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ */
+static void edma_link(struct edma_cc *ecc, unsigned from, unsigned to)
+{
+ if (unlikely(EDMA_CTLR(from) != EDMA_CTLR(to)))
+ dev_warn(ecc->dev, "Ignoring eDMA instance for linking\n");
+
+ from = EDMA_CHAN_SLOT(from);
+ to = EDMA_CHAN_SLOT(to);
+ if (from >= ecc->num_slots || to >= ecc->num_slots)
+ return;
+
+ edma_param_modify(ecc, PARM_LINK_BCNTRLD, from, 0xffff0000,
+ PARM_OFFSET(to));
+}
+
+/**
+ * edma_get_position - returns the current transfer point
+ * @ecc: pointer to edma_cc struct
+ * @slot: parameter RAM slot being examined
+ * @dst: true selects the dest position, false the source
+ *
+ * Returns the position of the current active slot
+ */
+static dma_addr_t edma_get_position(struct edma_cc *ecc, unsigned slot,
+ bool dst)
+{
+ u32 offs;
+
+ slot = EDMA_CHAN_SLOT(slot);
+ offs = PARM_OFFSET(slot);
+ offs += dst ? PARM_DST : PARM_SRC;
+
+ return edma_read(ecc, offs);
+}
+
+/*
+ * Channels with event associations will be triggered by their hardware
+ * events, and channels without such associations will be triggered by
+ * software. (At this writing there is no interface for using software
+ * triggers except with channels that don't support hardware triggers.)
+ */
+static void edma_start(struct edma_chan *echan)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ int j = (channel >> 5);
+ unsigned int mask = BIT(channel & 0x1f);
+
+ if (!echan->hw_triggered) {
+ /* EDMA channels without event association */
+ dev_dbg(ecc->dev, "ESR%d %08x\n", j,
+ edma_shadow0_read_array(ecc, SH_ESR, j));
+ edma_shadow0_write_array(ecc, SH_ESR, j, mask);
+ } else {
+ /* EDMA channel with event association */
+ dev_dbg(ecc->dev, "ER%d %08x\n", j,
+ edma_shadow0_read_array(ecc, SH_ER, j));
+ /* Clear any pending event or error */
+ edma_write_array(ecc, EDMA_ECR, j, mask);
+ edma_write_array(ecc, EDMA_EMCR, j, mask);
+ /* Clear any SER */
+ edma_shadow0_write_array(ecc, SH_SECR, j, mask);
+ edma_shadow0_write_array(ecc, SH_EESR, j, mask);
+ dev_dbg(ecc->dev, "EER%d %08x\n", j,
+ edma_shadow0_read_array(ecc, SH_EER, j));
+ }
+}
+
+static void edma_stop(struct edma_chan *echan)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ int j = (channel >> 5);
+ unsigned int mask = BIT(channel & 0x1f);
+
+ edma_shadow0_write_array(ecc, SH_EECR, j, mask);
+ edma_shadow0_write_array(ecc, SH_ECR, j, mask);
+ edma_shadow0_write_array(ecc, SH_SECR, j, mask);
+ edma_write_array(ecc, EDMA_EMCR, j, mask);
+
+ /* clear possibly pending completion interrupt */
+ edma_shadow0_write_array(ecc, SH_ICR, j, mask);
+
+ dev_dbg(ecc->dev, "EER%d %08x\n", j,
+ edma_shadow0_read_array(ecc, SH_EER, j));
+
+ /* REVISIT: consider guarding against inappropriate event
+ * chaining by overwriting with dummy_paramset.
+ */
+}
+
+/*
+ * Temporarily disable EDMA hardware events on the specified channel,
+ * preventing them from triggering new transfers
+ */
+static void edma_pause(struct edma_chan *echan)
+{
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ unsigned int mask = BIT(channel & 0x1f);
+
+ edma_shadow0_write_array(echan->ecc, SH_EECR, channel >> 5, mask);
+}
+
+/* Re-enable EDMA hardware events on the specified channel. */
+static void edma_resume(struct edma_chan *echan)
+{
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ unsigned int mask = BIT(channel & 0x1f);
+
+ edma_shadow0_write_array(echan->ecc, SH_EESR, channel >> 5, mask);
+}
+
+static void edma_trigger_channel(struct edma_chan *echan)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ unsigned int mask = BIT(channel & 0x1f);
+
+ edma_shadow0_write_array(ecc, SH_ESR, (channel >> 5), mask);
+
+ dev_dbg(ecc->dev, "ESR%d %08x\n", (channel >> 5),
+ edma_shadow0_read_array(ecc, SH_ESR, (channel >> 5)));
+}
+
+static void edma_clean_channel(struct edma_chan *echan)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ int j = (channel >> 5);
+ unsigned int mask = BIT(channel & 0x1f);
+
+ dev_dbg(ecc->dev, "EMR%d %08x\n", j, edma_read_array(ecc, EDMA_EMR, j));
+ edma_shadow0_write_array(ecc, SH_ECR, j, mask);
+ /* Clear the corresponding EMR bits */
+ edma_write_array(ecc, EDMA_EMCR, j, mask);
+ /* Clear any SER */
+ edma_shadow0_write_array(ecc, SH_SECR, j, mask);
+ edma_write(ecc, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
+}
+
+/* Move channel to a specific event queue */
+static void edma_assign_channel_eventq(struct edma_chan *echan,
+ enum dma_event_q eventq_no)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+ int bit = (channel & 0x7) * 4;
+
+ /* default to low priority queue */
+ if (eventq_no == EVENTQ_DEFAULT)
+ eventq_no = ecc->default_queue;
+ if (eventq_no >= ecc->num_tc)
+ return;
+
+ eventq_no &= 7;
+ edma_modify_array(ecc, EDMA_DMAQNUM, (channel >> 3), ~(0x7 << bit),
+ eventq_no << bit);
+}
+
+static int edma_alloc_channel(struct edma_chan *echan,
+ enum dma_event_q eventq_no)
+{
+ struct edma_cc *ecc = echan->ecc;
+ int channel = EDMA_CHAN_SLOT(echan->ch_num);
+
+ /* ensure access through shadow region 0 */
+ edma_or_array2(ecc, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
+
+ /* ensure no events are pending */
+ edma_stop(echan);
+
+ edma_setup_interrupt(echan, true);
+
+ edma_assign_channel_eventq(echan, eventq_no);
+
+ return 0;
+}
+
+static void edma_free_channel(struct edma_chan *echan)
+{
+ /* ensure no events are pending */
+ edma_stop(echan);
+ /* REVISIT should probably take out of shadow region 0 */
+ edma_setup_interrupt(echan, false);
+}
+
static inline struct edma_cc *to_edma_cc(struct dma_device *d)
{
return container_of(d, struct edma_cc, dma_slave);
@@ -135,8 +729,7 @@ static inline struct edma_chan *to_edma_chan(struct dma_chan *c)
return container_of(c, struct edma_chan, vchan.chan);
}
-static inline struct edma_desc
-*to_edma_desc(struct dma_async_tx_descriptor *tx)
+static inline struct edma_desc *to_edma_desc(struct dma_async_tx_descriptor *tx)
{
return container_of(tx, struct edma_desc, vdesc.tx);
}
@@ -149,20 +742,17 @@ static void edma_desc_free(struct virt_dma_desc *vdesc)
/* Dispatch a queued descriptor to the controller (caller holds lock) */
static void edma_execute(struct edma_chan *echan)
{
+ struct edma_cc *ecc = echan->ecc;
struct virt_dma_desc *vdesc;
struct edma_desc *edesc;
struct device *dev = echan->vchan.chan.device->dev;
int i, j, left, nslots;
- /* If either we processed all psets or we're still not started */
- if (!echan->edesc ||
- echan->edesc->pset_nr == echan->edesc->processed) {
- /* Get next vdesc */
+ if (!echan->edesc) {
+ /* Setup is needed for the first transfer */
vdesc = vchan_next_desc(&echan->vchan);
- if (!vdesc) {
- echan->edesc = NULL;
+ if (!vdesc)
return;
- }
list_del(&vdesc->node);
echan->edesc = to_edma_desc(&vdesc->tx);
}
@@ -177,32 +767,32 @@ static void edma_execute(struct edma_chan *echan)
/* Write descriptor PaRAM set(s) */
for (i = 0; i < nslots; i++) {
j = i + edesc->processed;
- edma_write_slot(echan->slot[i], &edesc->pset[j].param);
+ edma_write_slot(ecc, echan->slot[i], &edesc->pset[j].param);
edesc->sg_len += edesc->pset[j].len;
- dev_vdbg(echan->vchan.chan.device->dev,
- "\n pset[%d]:\n"
- " chnum\t%d\n"
- " slot\t%d\n"
- " opt\t%08x\n"
- " src\t%08x\n"
- " dst\t%08x\n"
- " abcnt\t%08x\n"
- " ccnt\t%08x\n"
- " bidx\t%08x\n"
- " cidx\t%08x\n"
- " lkrld\t%08x\n",
- j, echan->ch_num, echan->slot[i],
- edesc->pset[j].param.opt,
- edesc->pset[j].param.src,
- edesc->pset[j].param.dst,
- edesc->pset[j].param.a_b_cnt,
- edesc->pset[j].param.ccnt,
- edesc->pset[j].param.src_dst_bidx,
- edesc->pset[j].param.src_dst_cidx,
- edesc->pset[j].param.link_bcntrld);
+ dev_vdbg(dev,
+ "\n pset[%d]:\n"
+ " chnum\t%d\n"
+ " slot\t%d\n"
+ " opt\t%08x\n"
+ " src\t%08x\n"
+ " dst\t%08x\n"
+ " abcnt\t%08x\n"
+ " ccnt\t%08x\n"
+ " bidx\t%08x\n"
+ " cidx\t%08x\n"
+ " lkrld\t%08x\n",
+ j, echan->ch_num, echan->slot[i],
+ edesc->pset[j].param.opt,
+ edesc->pset[j].param.src,
+ edesc->pset[j].param.dst,
+ edesc->pset[j].param.a_b_cnt,
+ edesc->pset[j].param.ccnt,
+ edesc->pset[j].param.src_dst_bidx,
+ edesc->pset[j].param.src_dst_cidx,
+ edesc->pset[j].param.link_bcntrld);
/* Link to the previous slot if not the last set */
if (i != (nslots - 1))
- edma_link(echan->slot[i], echan->slot[i+1]);
+ edma_link(ecc, echan->slot[i], echan->slot[i + 1]);
}
edesc->processed += nslots;
@@ -214,34 +804,32 @@ static void edma_execute(struct edma_chan *echan)
*/
if (edesc->processed == edesc->pset_nr) {
if (edesc->cyclic)
- edma_link(echan->slot[nslots-1], echan->slot[1]);
+ edma_link(ecc, echan->slot[nslots - 1], echan->slot[1]);
else
- edma_link(echan->slot[nslots-1],
+ edma_link(ecc, echan->slot[nslots - 1],
echan->ecc->dummy_slot);
}
- if (edesc->processed <= MAX_NR_SG) {
+ if (echan->missed) {
+ /*
+ * This happens due to setup times between intermediate
+ * transfers in long SG lists which have to be broken up into
+ * transfers of MAX_NR_SG
+ */
+ dev_dbg(dev, "missed event on channel %d\n", echan->ch_num);
+ edma_clean_channel(echan);
+ edma_stop(echan);
+ edma_start(echan);
+ edma_trigger_channel(echan);
+ echan->missed = 0;
+ } else if (edesc->processed <= MAX_NR_SG) {
dev_dbg(dev, "first transfer starting on channel %d\n",
echan->ch_num);
- edma_start(echan->ch_num);
+ edma_start(echan);
} else {
dev_dbg(dev, "chan: %d: completed %d elements, resuming\n",
echan->ch_num, edesc->processed);
- edma_resume(echan->ch_num);
- }
-
- /*
- * This happens due to setup times between intermediate transfers
- * in long SG lists which have to be broken up into transfers of
- * MAX_NR_SG
- */
- if (echan->missed) {
- dev_dbg(dev, "missed event on channel %d\n", echan->ch_num);
- edma_clean_channel(echan->ch_num);
- edma_stop(echan->ch_num);
- edma_start(echan->ch_num);
- edma_trigger_channel(echan->ch_num);
- echan->missed = 0;
+ edma_resume(echan);
}
}
@@ -259,20 +847,16 @@ static int edma_terminate_all(struct dma_chan *chan)
* echan->edesc is NULL and exit.)
*/
if (echan->edesc) {
- int cyclic = echan->edesc->cyclic;
-
+ edma_stop(echan);
+ /* Move the cyclic channel back to default queue */
+ if (!echan->tc && echan->edesc->cyclic)
+ edma_assign_channel_eventq(echan, EVENTQ_DEFAULT);
/*
* free the running request descriptor
* since it is not in any of the vdesc lists
*/
edma_desc_free(&echan->edesc->vdesc);
-
echan->edesc = NULL;
- edma_stop(echan->ch_num);
- /* Move the cyclic channel back to default queue */
- if (cyclic)
- edma_assign_channel_eventq(echan->ch_num,
- EVENTQ_DEFAULT);
}
vchan_get_all_descriptors(&echan->vchan, &head);
@@ -303,7 +887,7 @@ static int edma_dma_pause(struct dma_chan *chan)
if (!echan->edesc)
return -EINVAL;
- edma_pause(echan->ch_num);
+ edma_pause(echan);
return 0;
}
@@ -311,7 +895,7 @@ static int edma_dma_resume(struct dma_chan *chan)
{
struct edma_chan *echan = to_edma_chan(chan);
- edma_resume(echan->ch_num);
+ edma_resume(echan);
return 0;
}
@@ -327,19 +911,17 @@ static int edma_dma_resume(struct dma_chan *chan)
* @direction: Direction of the transfer
*/
static int edma_config_pset(struct dma_chan *chan, struct edma_pset *epset,
- dma_addr_t src_addr, dma_addr_t dst_addr, u32 burst,
- enum dma_slave_buswidth dev_width, unsigned int dma_length,
- enum dma_transfer_direction direction)
+ dma_addr_t src_addr, dma_addr_t dst_addr, u32 burst,
+ unsigned int acnt, unsigned int dma_length,
+ enum dma_transfer_direction direction)
{
struct edma_chan *echan = to_edma_chan(chan);
struct device *dev = chan->device->dev;
struct edmacc_param *param = &epset->param;
- int acnt, bcnt, ccnt, cidx;
+ int bcnt, ccnt, cidx;
int src_bidx, dst_bidx, src_cidx, dst_cidx;
int absync;
- acnt = dev_width;
-
/* src/dst_maxburst == 0 is the same case as src/dst_maxburst == 1 */
if (!burst)
burst = 1;
@@ -475,8 +1057,8 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
return NULL;
}
- edesc = kzalloc(sizeof(*edesc) + sg_len *
- sizeof(edesc->pset[0]), GFP_ATOMIC);
+ edesc = kzalloc(sizeof(*edesc) + sg_len * sizeof(edesc->pset[0]),
+ GFP_ATOMIC);
if (!edesc) {
dev_err(dev, "%s: Failed to allocate a descriptor\n", __func__);
return NULL;
@@ -493,8 +1075,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
for (i = 0; i < nslots; i++) {
if (echan->slot[i] < 0) {
echan->slot[i] =
- edma_alloc_slot(EDMA_CTLR(echan->ch_num),
- EDMA_SLOT_ANY);
+ edma_alloc_slot(echan->ecc, EDMA_SLOT_ANY);
if (echan->slot[i] < 0) {
kfree(edesc);
dev_err(dev, "%s: Failed to allocate slot\n",
@@ -541,36 +1122,98 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy(
struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
size_t len, unsigned long tx_flags)
{
- int ret;
+ int ret, nslots;
struct edma_desc *edesc;
struct device *dev = chan->device->dev;
struct edma_chan *echan = to_edma_chan(chan);
+ unsigned int width, pset_len;
if (unlikely(!echan || !len))
return NULL;
- edesc = kzalloc(sizeof(*edesc) + sizeof(edesc->pset[0]), GFP_ATOMIC);
+ if (len < SZ_64K) {
+ /*
+ * Transfer size less than 64K can be handled with one paRAM
+ * slot and with one burst.
+ * ACNT = length
+ */
+ width = len;
+ pset_len = len;
+ nslots = 1;
+ } else {
+ /*
+ * Transfer size bigger than 64K will be handled with maximum of
+ * two paRAM slots.
+ * slot1: (full_length / 32767) times 32767 bytes bursts.
+ * ACNT = 32767, length1: (full_length / 32767) * 32767
+ * slot2: the remaining amount of data after slot1.
+ * ACNT = full_length - length1, length2 = ACNT
+ *
+ * When the full_length is multibple of 32767 one slot can be
+ * used to complete the transfer.
+ */
+ width = SZ_32K - 1;
+ pset_len = rounddown(len, width);
+ /* One slot is enough for lengths multiple of (SZ_32K -1) */
+ if (unlikely(pset_len == len))
+ nslots = 1;
+ else
+ nslots = 2;
+ }
+
+ edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
+ GFP_ATOMIC);
if (!edesc) {
dev_dbg(dev, "Failed to allocate a descriptor\n");
return NULL;
}
- edesc->pset_nr = 1;
+ edesc->pset_nr = nslots;
+ edesc->residue = edesc->residue_stat = len;
+ edesc->direction = DMA_MEM_TO_MEM;
+ edesc->echan = echan;
ret = edma_config_pset(chan, &edesc->pset[0], src, dest, 1,
- DMA_SLAVE_BUSWIDTH_4_BYTES, len, DMA_MEM_TO_MEM);
- if (ret < 0)
+ width, pset_len, DMA_MEM_TO_MEM);
+ if (ret < 0) {
+ kfree(edesc);
return NULL;
+ }
edesc->absync = ret;
- /*
- * Enable intermediate transfer chaining to re-trigger channel
- * on completion of every TR, and enable transfer-completion
- * interrupt on completion of the whole transfer.
- */
edesc->pset[0].param.opt |= ITCCHEN;
- edesc->pset[0].param.opt |= TCINTEN;
+ if (nslots == 1) {
+ /* Enable transfer complete interrupt */
+ edesc->pset[0].param.opt |= TCINTEN;
+ } else {
+ /* Enable transfer complete chaining for the first slot */
+ edesc->pset[0].param.opt |= TCCHEN;
+
+ if (echan->slot[1] < 0) {
+ echan->slot[1] = edma_alloc_slot(echan->ecc,
+ EDMA_SLOT_ANY);
+ if (echan->slot[1] < 0) {
+ kfree(edesc);
+ dev_err(dev, "%s: Failed to allocate slot\n",
+ __func__);
+ return NULL;
+ }
+ }
+ dest += pset_len;
+ src += pset_len;
+ pset_len = width = len % (SZ_32K - 1);
+
+ ret = edma_config_pset(chan, &edesc->pset[1], src, dest, 1,
+ width, pset_len, DMA_MEM_TO_MEM);
+ if (ret < 0) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ edesc->pset[1].param.opt |= ITCCHEN;
+ edesc->pset[1].param.opt |= TCINTEN;
+ }
return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
}
@@ -629,8 +1272,8 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
if (nslots > MAX_NR_SG)
return NULL;
- edesc = kzalloc(sizeof(*edesc) + nslots *
- sizeof(edesc->pset[0]), GFP_ATOMIC);
+ edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
+ GFP_ATOMIC);
if (!edesc) {
dev_err(dev, "%s: Failed to allocate a descriptor\n", __func__);
return NULL;
@@ -649,8 +1292,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
/* Allocate a PaRAM slot, if needed */
if (echan->slot[i] < 0) {
echan->slot[i] =
- edma_alloc_slot(EDMA_CTLR(echan->ch_num),
- EDMA_SLOT_ANY);
+ edma_alloc_slot(echan->ecc, EDMA_SLOT_ANY);
if (echan->slot[i] < 0) {
kfree(edesc);
dev_err(dev, "%s: Failed to allocate slot\n",
@@ -711,128 +1353,281 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
}
/* Place the cyclic channel to highest priority queue */
- edma_assign_channel_eventq(echan->ch_num, EVENTQ_0);
+ if (!echan->tc)
+ edma_assign_channel_eventq(echan, EVENTQ_0);
return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
}
-static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
+static void edma_completion_handler(struct edma_chan *echan)
{
- struct edma_chan *echan = data;
struct device *dev = echan->vchan.chan.device->dev;
- struct edma_desc *edesc;
- struct edmacc_param p;
+ struct edma_desc *edesc = echan->edesc;
- edesc = echan->edesc;
+ if (!edesc)
+ return;
- /* Pause the channel for non-cyclic */
- if (!edesc || (edesc && !edesc->cyclic))
- edma_pause(echan->ch_num);
-
- switch (ch_status) {
- case EDMA_DMA_COMPLETE:
- spin_lock(&echan->vchan.lock);
-
- if (edesc) {
- if (edesc->cyclic) {
- vchan_cyclic_callback(&edesc->vdesc);
- } else if (edesc->processed == edesc->pset_nr) {
- dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num);
- edesc->residue = 0;
- edma_stop(echan->ch_num);
- vchan_cookie_complete(&edesc->vdesc);
- edma_execute(echan);
- } else {
- dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num);
-
- /* Update statistics for tx_status */
- edesc->residue -= edesc->sg_len;
- edesc->residue_stat = edesc->residue;
- edesc->processed_stat = edesc->processed;
-
- edma_execute(echan);
- }
+ spin_lock(&echan->vchan.lock);
+ if (edesc->cyclic) {
+ vchan_cyclic_callback(&edesc->vdesc);
+ spin_unlock(&echan->vchan.lock);
+ return;
+ } else if (edesc->processed == edesc->pset_nr) {
+ edesc->residue = 0;
+ edma_stop(echan);
+ vchan_cookie_complete(&edesc->vdesc);
+ echan->edesc = NULL;
+
+ dev_dbg(dev, "Transfer completed on channel %d\n",
+ echan->ch_num);
+ } else {
+ dev_dbg(dev, "Sub transfer completed on channel %d\n",
+ echan->ch_num);
+
+ edma_pause(echan);
+
+ /* Update statistics for tx_status */
+ edesc->residue -= edesc->sg_len;
+ edesc->residue_stat = edesc->residue;
+ edesc->processed_stat = edesc->processed;
+ }
+ edma_execute(echan);
+
+ spin_unlock(&echan->vchan.lock);
+}
+
+/* eDMA interrupt handler */
+static irqreturn_t dma_irq_handler(int irq, void *data)
+{
+ struct edma_cc *ecc = data;
+ int ctlr;
+ u32 sh_ier;
+ u32 sh_ipr;
+ u32 bank;
+
+ ctlr = ecc->id;
+ if (ctlr < 0)
+ return IRQ_NONE;
+
+ dev_vdbg(ecc->dev, "dma_irq_handler\n");
+
+ sh_ipr = edma_shadow0_read_array(ecc, SH_IPR, 0);
+ if (!sh_ipr) {
+ sh_ipr = edma_shadow0_read_array(ecc, SH_IPR, 1);
+ if (!sh_ipr)
+ return IRQ_NONE;
+ sh_ier = edma_shadow0_read_array(ecc, SH_IER, 1);
+ bank = 1;
+ } else {
+ sh_ier = edma_shadow0_read_array(ecc, SH_IER, 0);
+ bank = 0;
+ }
+
+ do {
+ u32 slot;
+ u32 channel;
+
+ slot = __ffs(sh_ipr);
+ sh_ipr &= ~(BIT(slot));
+
+ if (sh_ier & BIT(slot)) {
+ channel = (bank << 5) | slot;
+ /* Clear the corresponding IPR bits */
+ edma_shadow0_write_array(ecc, SH_ICR, bank, BIT(slot));
+ edma_completion_handler(&ecc->slave_chans[channel]);
}
+ } while (sh_ipr);
- spin_unlock(&echan->vchan.lock);
+ edma_shadow0_write(ecc, SH_IEVAL, 1);
+ return IRQ_HANDLED;
+}
+
+static void edma_error_handler(struct edma_chan *echan)
+{
+ struct edma_cc *ecc = echan->ecc;
+ struct device *dev = echan->vchan.chan.device->dev;
+ struct edmacc_param p;
- break;
- case EDMA_DMA_CC_ERROR:
- spin_lock(&echan->vchan.lock);
+ if (!echan->edesc)
+ return;
- edma_read_slot(EDMA_CHAN_SLOT(echan->slot[0]), &p);
+ spin_lock(&echan->vchan.lock);
+ edma_read_slot(ecc, echan->slot[0], &p);
+ /*
+ * Issue later based on missed flag which will be sure
+ * to happen as:
+ * (1) we finished transmitting an intermediate slot and
+ * edma_execute is coming up.
+ * (2) or we finished current transfer and issue will
+ * call edma_execute.
+ *
+ * Important note: issuing can be dangerous here and
+ * lead to some nasty recursion when we are in a NULL
+ * slot. So we avoid doing so and set the missed flag.
+ */
+ if (p.a_b_cnt == 0 && p.ccnt == 0) {
+ dev_dbg(dev, "Error on null slot, setting miss\n");
+ echan->missed = 1;
+ } else {
/*
- * Issue later based on missed flag which will be sure
- * to happen as:
- * (1) we finished transmitting an intermediate slot and
- * edma_execute is coming up.
- * (2) or we finished current transfer and issue will
- * call edma_execute.
- *
- * Important note: issuing can be dangerous here and
- * lead to some nasty recursion when we are in a NULL
- * slot. So we avoid doing so and set the missed flag.
+ * The slot is already programmed but the event got
+ * missed, so its safe to issue it here.
*/
- if (p.a_b_cnt == 0 && p.ccnt == 0) {
- dev_dbg(dev, "Error occurred, looks like slot is null, just setting miss\n");
- echan->missed = 1;
- } else {
- /*
- * The slot is already programmed but the event got
- * missed, so its safe to issue it here.
- */
- dev_dbg(dev, "Error occurred but slot is non-null, TRIGGERING\n");
- edma_clean_channel(echan->ch_num);
- edma_stop(echan->ch_num);
- edma_start(echan->ch_num);
- edma_trigger_channel(echan->ch_num);
+ dev_dbg(dev, "Missed event, TRIGGERING\n");
+ edma_clean_channel(echan);
+ edma_stop(echan);
+ edma_start(echan);
+ edma_trigger_channel(echan);
+ }
+ spin_unlock(&echan->vchan.lock);
+}
+
+static inline bool edma_error_pending(struct edma_cc *ecc)
+{
+ if (edma_read_array(ecc, EDMA_EMR, 0) ||
+ edma_read_array(ecc, EDMA_EMR, 1) ||
+ edma_read(ecc, EDMA_QEMR) || edma_read(ecc, EDMA_CCERR))
+ return true;
+
+ return false;
+}
+
+/* eDMA error interrupt handler */
+static irqreturn_t dma_ccerr_handler(int irq, void *data)
+{
+ struct edma_cc *ecc = data;
+ int i, j;
+ int ctlr;
+ unsigned int cnt = 0;
+ unsigned int val;
+
+ ctlr = ecc->id;
+ if (ctlr < 0)
+ return IRQ_NONE;
+
+ dev_vdbg(ecc->dev, "dma_ccerr_handler\n");
+
+ if (!edma_error_pending(ecc))
+ return IRQ_NONE;
+
+ while (1) {
+ /* Event missed register(s) */
+ for (j = 0; j < 2; j++) {
+ unsigned long emr;
+
+ val = edma_read_array(ecc, EDMA_EMR, j);
+ if (!val)
+ continue;
+
+ dev_dbg(ecc->dev, "EMR%d 0x%08x\n", j, val);
+ emr = val;
+ for (i = find_next_bit(&emr, 32, 0); i < 32;
+ i = find_next_bit(&emr, 32, i + 1)) {
+ int k = (j << 5) + i;
+
+ /* Clear the corresponding EMR bits */
+ edma_write_array(ecc, EDMA_EMCR, j, BIT(i));
+ /* Clear any SER */
+ edma_shadow0_write_array(ecc, SH_SECR, j,
+ BIT(i));
+ edma_error_handler(&ecc->slave_chans[k]);
+ }
}
- spin_unlock(&echan->vchan.lock);
+ val = edma_read(ecc, EDMA_QEMR);
+ if (val) {
+ dev_dbg(ecc->dev, "QEMR 0x%02x\n", val);
+ /* Not reported, just clear the interrupt reason. */
+ edma_write(ecc, EDMA_QEMCR, val);
+ edma_shadow0_write(ecc, SH_QSECR, val);
+ }
+
+ val = edma_read(ecc, EDMA_CCERR);
+ if (val) {
+ dev_warn(ecc->dev, "CCERR 0x%08x\n", val);
+ /* Not reported, just clear the interrupt reason. */
+ edma_write(ecc, EDMA_CCERRCLR, val);
+ }
- break;
- default:
- break;
+ if (!edma_error_pending(ecc))
+ break;
+ cnt++;
+ if (cnt > 10)
+ break;
}
+ edma_write(ecc, EDMA_EEVAL, 1);
+ return IRQ_HANDLED;
+}
+
+static void edma_tc_set_pm_state(struct edma_tc *tc, bool enable)
+{
+ struct platform_device *tc_pdev;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_OF) || !tc)
+ return;
+
+ tc_pdev = of_find_device_by_node(tc->node);
+ if (!tc_pdev) {
+ pr_err("%s: TPTC device is not found\n", __func__);
+ return;
+ }
+ if (!pm_runtime_enabled(&tc_pdev->dev))
+ pm_runtime_enable(&tc_pdev->dev);
+
+ if (enable)
+ ret = pm_runtime_get_sync(&tc_pdev->dev);
+ else
+ ret = pm_runtime_put_sync(&tc_pdev->dev);
+
+ if (ret < 0)
+ pr_err("%s: pm_runtime_%s_sync() failed for %s\n", __func__,
+ enable ? "get" : "put", dev_name(&tc_pdev->dev));
}
/* Alloc channel resources */
static int edma_alloc_chan_resources(struct dma_chan *chan)
{
struct edma_chan *echan = to_edma_chan(chan);
- struct device *dev = chan->device->dev;
+ struct edma_cc *ecc = echan->ecc;
+ struct device *dev = ecc->dev;
+ enum dma_event_q eventq_no = EVENTQ_DEFAULT;
int ret;
- int a_ch_num;
- LIST_HEAD(descs);
- a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
- echan, EVENTQ_DEFAULT);
-
- if (a_ch_num < 0) {
- ret = -ENODEV;
- goto err_no_chan;
+ if (echan->tc) {
+ eventq_no = echan->tc->id;
+ } else if (ecc->tc_list) {
+ /* memcpy channel */
+ echan->tc = &ecc->tc_list[ecc->info->default_queue];
+ eventq_no = echan->tc->id;
}
- if (a_ch_num != echan->ch_num) {
- dev_err(dev, "failed to allocate requested channel %u:%u\n",
- EDMA_CTLR(echan->ch_num),
+ ret = edma_alloc_channel(echan, eventq_no);
+ if (ret)
+ return ret;
+
+ echan->slot[0] = edma_alloc_slot(ecc, echan->ch_num);
+ if (echan->slot[0] < 0) {
+ dev_err(dev, "Entry slot allocation failed for channel %u\n",
EDMA_CHAN_SLOT(echan->ch_num));
- ret = -ENODEV;
- goto err_wrong_chan;
+ goto err_slot;
}
+ /* Set up channel -> slot mapping for the entry slot */
+ edma_set_chmap(echan, echan->slot[0]);
echan->alloced = true;
- echan->slot[0] = echan->ch_num;
- dev_dbg(dev, "allocated channel %d for %u:%u\n", echan->ch_num,
- EDMA_CTLR(echan->ch_num), EDMA_CHAN_SLOT(echan->ch_num));
+ dev_dbg(dev, "Got eDMA channel %d for virt channel %d (%s trigger)\n",
+ EDMA_CHAN_SLOT(echan->ch_num), chan->chan_id,
+ echan->hw_triggered ? "HW" : "SW");
+
+ edma_tc_set_pm_state(echan->tc, true);
return 0;
-err_wrong_chan:
- edma_free_channel(a_ch_num);
-err_no_chan:
+err_slot:
+ edma_free_channel(echan);
return ret;
}
@@ -840,29 +1635,37 @@ err_no_chan:
static void edma_free_chan_resources(struct dma_chan *chan)
{
struct edma_chan *echan = to_edma_chan(chan);
- struct device *dev = chan->device->dev;
+ struct device *dev = echan->ecc->dev;
int i;
/* Terminate transfers */
- edma_stop(echan->ch_num);
+ edma_stop(echan);
vchan_free_chan_resources(&echan->vchan);
/* Free EDMA PaRAM slots */
- for (i = 1; i < EDMA_MAX_SLOTS; i++) {
+ for (i = 0; i < EDMA_MAX_SLOTS; i++) {
if (echan->slot[i] >= 0) {
- edma_free_slot(echan->slot[i]);
+ edma_free_slot(echan->ecc, echan->slot[i]);
echan->slot[i] = -1;
}
}
+ /* Set entry slot to the dummy slot */
+ edma_set_chmap(echan, echan->ecc->dummy_slot);
+
/* Free EDMA channel */
if (echan->alloced) {
- edma_free_channel(echan->ch_num);
+ edma_free_channel(echan);
echan->alloced = false;
}
- dev_dbg(dev, "freeing channel for %u\n", echan->ch_num);
+ edma_tc_set_pm_state(echan->tc, false);
+ echan->tc = NULL;
+ echan->hw_triggered = false;
+
+ dev_dbg(dev, "Free eDMA channel %d for virt channel %d\n",
+ EDMA_CHAN_SLOT(echan->ch_num), chan->chan_id);
}
/* Send pending descriptor to hardware */
@@ -888,7 +1691,7 @@ static u32 edma_residue(struct edma_desc *edesc)
* We always read the dst/src position from the first RamPar
* pset. That's the one which is active now.
*/
- pos = edma_get_position(edesc->echan->slot[0], dst);
+ pos = edma_get_position(edesc->echan->ecc, edesc->echan->slot[0], dst);
/*
* Cyclic is simple. Just subtract pset[0].addr from pos.
@@ -949,19 +1752,101 @@ static enum dma_status edma_tx_status(struct dma_chan *chan,
return ret;
}
-static void __init edma_chan_init(struct edma_cc *ecc,
- struct dma_device *dma,
- struct edma_chan *echans)
+static bool edma_is_memcpy_channel(int ch_num, u16 *memcpy_channels)
{
+ s16 *memcpy_ch = memcpy_channels;
+
+ if (!memcpy_channels)
+ return false;
+ while (*memcpy_ch != -1) {
+ if (*memcpy_ch == ch_num)
+ return true;
+ memcpy_ch++;
+ }
+ return false;
+}
+
+#define EDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+ BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
+
+static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
+{
+ struct dma_device *s_ddev = &ecc->dma_slave;
+ struct dma_device *m_ddev = NULL;
+ s16 *memcpy_channels = ecc->info->memcpy_channels;
int i, j;
- for (i = 0; i < EDMA_CHANS; i++) {
- struct edma_chan *echan = &echans[i];
- echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
+ dma_cap_zero(s_ddev->cap_mask);
+ dma_cap_set(DMA_SLAVE, s_ddev->cap_mask);
+ dma_cap_set(DMA_CYCLIC, s_ddev->cap_mask);
+ if (ecc->legacy_mode && !memcpy_channels) {
+ dev_warn(ecc->dev,
+ "Legacy memcpy is enabled, things might not work\n");
+
+ dma_cap_set(DMA_MEMCPY, s_ddev->cap_mask);
+ s_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy;
+ s_ddev->directions = BIT(DMA_MEM_TO_MEM);
+ }
+
+ s_ddev->device_prep_slave_sg = edma_prep_slave_sg;
+ s_ddev->device_prep_dma_cyclic = edma_prep_dma_cyclic;
+ s_ddev->device_alloc_chan_resources = edma_alloc_chan_resources;
+ s_ddev->device_free_chan_resources = edma_free_chan_resources;
+ s_ddev->device_issue_pending = edma_issue_pending;
+ s_ddev->device_tx_status = edma_tx_status;
+ s_ddev->device_config = edma_slave_config;
+ s_ddev->device_pause = edma_dma_pause;
+ s_ddev->device_resume = edma_dma_resume;
+ s_ddev->device_terminate_all = edma_terminate_all;
+
+ s_ddev->src_addr_widths = EDMA_DMA_BUSWIDTHS;
+ s_ddev->dst_addr_widths = EDMA_DMA_BUSWIDTHS;
+ s_ddev->directions |= (BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV));
+ s_ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+ s_ddev->dev = ecc->dev;
+ INIT_LIST_HEAD(&s_ddev->channels);
+
+ if (memcpy_channels) {
+ m_ddev = devm_kzalloc(ecc->dev, sizeof(*m_ddev), GFP_KERNEL);
+ ecc->dma_memcpy = m_ddev;
+
+ dma_cap_zero(m_ddev->cap_mask);
+ dma_cap_set(DMA_MEMCPY, m_ddev->cap_mask);
+
+ m_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy;
+ m_ddev->device_alloc_chan_resources = edma_alloc_chan_resources;
+ m_ddev->device_free_chan_resources = edma_free_chan_resources;
+ m_ddev->device_issue_pending = edma_issue_pending;
+ m_ddev->device_tx_status = edma_tx_status;
+ m_ddev->device_config = edma_slave_config;
+ m_ddev->device_pause = edma_dma_pause;
+ m_ddev->device_resume = edma_dma_resume;
+ m_ddev->device_terminate_all = edma_terminate_all;
+
+ m_ddev->src_addr_widths = EDMA_DMA_BUSWIDTHS;
+ m_ddev->dst_addr_widths = EDMA_DMA_BUSWIDTHS;
+ m_ddev->directions = BIT(DMA_MEM_TO_MEM);
+ m_ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+ m_ddev->dev = ecc->dev;
+ INIT_LIST_HEAD(&m_ddev->channels);
+ } else if (!ecc->legacy_mode) {
+ dev_info(ecc->dev, "memcpy is disabled\n");
+ }
+
+ for (i = 0; i < ecc->num_channels; i++) {
+ struct edma_chan *echan = &ecc->slave_chans[i];
+ echan->ch_num = EDMA_CTLR_CHAN(ecc->id, i);
echan->ecc = ecc;
echan->vchan.desc_free = edma_desc_free;
- vchan_init(&echan->vchan, dma);
+ if (m_ddev && edma_is_memcpy_channel(i, memcpy_channels))
+ vchan_init(&echan->vchan, m_ddev);
+ else
+ vchan_init(&echan->vchan, s_ddev);
INIT_LIST_HEAD(&echan->node);
for (j = 0; j < EDMA_MAX_SLOTS; j++)
@@ -969,85 +1854,474 @@ static void __init edma_chan_init(struct edma_cc *ecc,
}
}
-#define EDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
- BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
- BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
- BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
-
-static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
- struct device *dev)
+static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
+ struct edma_cc *ecc)
{
- dma->device_prep_slave_sg = edma_prep_slave_sg;
- dma->device_prep_dma_cyclic = edma_prep_dma_cyclic;
- dma->device_prep_dma_memcpy = edma_prep_dma_memcpy;
- dma->device_alloc_chan_resources = edma_alloc_chan_resources;
- dma->device_free_chan_resources = edma_free_chan_resources;
- dma->device_issue_pending = edma_issue_pending;
- dma->device_tx_status = edma_tx_status;
- dma->device_config = edma_slave_config;
- dma->device_pause = edma_dma_pause;
- dma->device_resume = edma_dma_resume;
- dma->device_terminate_all = edma_terminate_all;
+ int i;
+ u32 value, cccfg;
+ s8 (*queue_priority_map)[2];
+
+ /* Decode the eDMA3 configuration from CCCFG register */
+ cccfg = edma_read(ecc, EDMA_CCCFG);
+
+ value = GET_NUM_REGN(cccfg);
+ ecc->num_region = BIT(value);
+
+ value = GET_NUM_DMACH(cccfg);
+ ecc->num_channels = BIT(value + 1);
- dma->src_addr_widths = EDMA_DMA_BUSWIDTHS;
- dma->dst_addr_widths = EDMA_DMA_BUSWIDTHS;
- dma->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
- dma->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ value = GET_NUM_QDMACH(cccfg);
+ ecc->num_qchannels = value * 2;
- dma->dev = dev;
+ value = GET_NUM_PAENTRY(cccfg);
+ ecc->num_slots = BIT(value + 4);
+
+ value = GET_NUM_EVQUE(cccfg);
+ ecc->num_tc = value + 1;
+
+ ecc->chmap_exist = (cccfg & CHMAP_EXIST) ? true : false;
+
+ dev_dbg(dev, "eDMA3 CC HW configuration (cccfg: 0x%08x):\n", cccfg);
+ dev_dbg(dev, "num_region: %u\n", ecc->num_region);
+ dev_dbg(dev, "num_channels: %u\n", ecc->num_channels);
+ dev_dbg(dev, "num_qchannels: %u\n", ecc->num_qchannels);
+ dev_dbg(dev, "num_slots: %u\n", ecc->num_slots);
+ dev_dbg(dev, "num_tc: %u\n", ecc->num_tc);
+ dev_dbg(dev, "chmap_exist: %s\n", ecc->chmap_exist ? "yes" : "no");
+
+ /* Nothing need to be done if queue priority is provided */
+ if (pdata->queue_priority_mapping)
+ return 0;
/*
- * code using dma memcpy must make sure alignment of
- * length is at dma->copy_align boundary.
+ * Configure TC/queue priority as follows:
+ * Q0 - priority 0
+ * Q1 - priority 1
+ * Q2 - priority 2
+ * ...
+ * The meaning of priority numbers: 0 highest priority, 7 lowest
+ * priority. So Q0 is the highest priority queue and the last queue has
+ * the lowest priority.
*/
- dma->copy_align = DMAENGINE_ALIGN_4_BYTES;
+ queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1, sizeof(s8),
+ GFP_KERNEL);
+ if (!queue_priority_map)
+ return -ENOMEM;
+
+ for (i = 0; i < ecc->num_tc; i++) {
+ queue_priority_map[i][0] = i;
+ queue_priority_map[i][1] = i;
+ }
+ queue_priority_map[i][0] = -1;
+ queue_priority_map[i][1] = -1;
+
+ pdata->queue_priority_mapping = queue_priority_map;
+ /* Default queue has the lowest priority */
+ pdata->default_queue = i - 1;
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_OF)
+static int edma_xbar_event_map(struct device *dev, struct edma_soc_info *pdata,
+ size_t sz)
+{
+ const char pname[] = "ti,edma-xbar-event-map";
+ struct resource res;
+ void __iomem *xbar;
+ s16 (*xbar_chans)[2];
+ size_t nelm = sz / sizeof(s16);
+ u32 shift, offset, mux;
+ int ret, i;
+
+ xbar_chans = devm_kcalloc(dev, nelm + 2, sizeof(s16), GFP_KERNEL);
+ if (!xbar_chans)
+ return -ENOMEM;
+
+ ret = of_address_to_resource(dev->of_node, 1, &res);
+ if (ret)
+ return -ENOMEM;
+
+ xbar = devm_ioremap(dev, res.start, resource_size(&res));
+ if (!xbar)
+ return -ENOMEM;
+
+ ret = of_property_read_u16_array(dev->of_node, pname, (u16 *)xbar_chans,
+ nelm);
+ if (ret)
+ return -EIO;
+
+ /* Invalidate last entry for the other user of this mess */
+ nelm >>= 1;
+ xbar_chans[nelm][0] = -1;
+ xbar_chans[nelm][1] = -1;
+
+ for (i = 0; i < nelm; i++) {
+ shift = (xbar_chans[i][1] & 0x03) << 3;
+ offset = xbar_chans[i][1] & 0xfffffffc;
+ mux = readl(xbar + offset);
+ mux &= ~(0xff << shift);
+ mux |= xbar_chans[i][0] << shift;
+ writel(mux, (xbar + offset));
+ }
- INIT_LIST_HEAD(&dma->channels);
+ pdata->xbar_chans = (const s16 (*)[2]) xbar_chans;
+ return 0;
+}
+
+static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
+ bool legacy_mode)
+{
+ struct edma_soc_info *info;
+ struct property *prop;
+ size_t sz;
+ int ret;
+
+ info = devm_kzalloc(dev, sizeof(struct edma_soc_info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ if (legacy_mode) {
+ prop = of_find_property(dev->of_node, "ti,edma-xbar-event-map",
+ &sz);
+ if (prop) {
+ ret = edma_xbar_event_map(dev, info, sz);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+ return info;
+ }
+
+ /* Get the list of channels allocated to be used for memcpy */
+ prop = of_find_property(dev->of_node, "ti,edma-memcpy-channels", &sz);
+ if (prop) {
+ const char pname[] = "ti,edma-memcpy-channels";
+ size_t nelm = sz / sizeof(s16);
+ s16 *memcpy_ch;
+
+ memcpy_ch = devm_kcalloc(dev, nelm + 1, sizeof(s16),
+ GFP_KERNEL);
+ if (!memcpy_ch)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u16_array(dev->of_node, pname,
+ (u16 *)memcpy_ch, nelm);
+ if (ret)
+ return ERR_PTR(ret);
+
+ memcpy_ch[nelm] = -1;
+ info->memcpy_channels = memcpy_ch;
+ }
+
+ prop = of_find_property(dev->of_node, "ti,edma-reserved-slot-ranges",
+ &sz);
+ if (prop) {
+ const char pname[] = "ti,edma-reserved-slot-ranges";
+ s16 (*rsv_slots)[2];
+ size_t nelm = sz / sizeof(*rsv_slots);
+ struct edma_rsv_info *rsv_info;
+
+ if (!nelm)
+ return info;
+
+ rsv_info = devm_kzalloc(dev, sizeof(*rsv_info), GFP_KERNEL);
+ if (!rsv_info)
+ return ERR_PTR(-ENOMEM);
+
+ rsv_slots = devm_kcalloc(dev, nelm + 1, sizeof(*rsv_slots),
+ GFP_KERNEL);
+ if (!rsv_slots)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u16_array(dev->of_node, pname,
+ (u16 *)rsv_slots, nelm * 2);
+ if (ret)
+ return ERR_PTR(ret);
+
+ rsv_slots[nelm][0] = -1;
+ rsv_slots[nelm][1] = -1;
+ info->rsv = rsv_info;
+ info->rsv->rsv_slots = (const s16 (*)[2])rsv_slots;
+ }
+
+ return info;
+}
+
+static struct dma_chan *of_edma_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct edma_cc *ecc = ofdma->of_dma_data;
+ struct dma_chan *chan = NULL;
+ struct edma_chan *echan;
+ int i;
+
+ if (!ecc || dma_spec->args_count < 1)
+ return NULL;
+
+ for (i = 0; i < ecc->num_channels; i++) {
+ echan = &ecc->slave_chans[i];
+ if (echan->ch_num == dma_spec->args[0]) {
+ chan = &echan->vchan.chan;
+ break;
+ }
+ }
+
+ if (!chan)
+ return NULL;
+
+ if (echan->ecc->legacy_mode && dma_spec->args_count == 1)
+ goto out;
+
+ if (!echan->ecc->legacy_mode && dma_spec->args_count == 2 &&
+ dma_spec->args[1] < echan->ecc->num_tc) {
+ echan->tc = &echan->ecc->tc_list[dma_spec->args[1]];
+ goto out;
+ }
+
+ return NULL;
+out:
+ /* The channel is going to be used as HW synchronized */
+ echan->hw_triggered = true;
+ return dma_get_slave_channel(chan);
+}
+#else
+static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
+ bool legacy_mode)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static struct dma_chan *of_edma_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ return NULL;
}
+#endif
static int edma_probe(struct platform_device *pdev)
{
- struct edma_cc *ecc;
+ struct edma_soc_info *info = pdev->dev.platform_data;
+ s8 (*queue_priority_mapping)[2];
+ int i, off, ln;
+ const s16 (*rsv_slots)[2];
+ const s16 (*xbar_chans)[2];
+ int irq;
+ char *irq_name;
+ struct resource *mem;
+ struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct edma_cc *ecc;
+ bool legacy_mode = true;
int ret;
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (node) {
+ const struct of_device_id *match;
+
+ match = of_match_node(edma_of_ids, node);
+ if (match && (u32)match->data == EDMA_BINDING_TPCC)
+ legacy_mode = false;
+
+ info = edma_setup_info_from_dt(dev, legacy_mode);
+ if (IS_ERR(info)) {
+ dev_err(dev, "failed to get DT data\n");
+ return PTR_ERR(info);
+ }
+ }
+
+ if (!info)
+ return -ENODEV;
+
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ dev_err(dev, "pm_runtime_get_sync() failed\n");
+ return ret;
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
return ret;
- ecc = devm_kzalloc(&pdev->dev, sizeof(*ecc), GFP_KERNEL);
+ ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL);
if (!ecc) {
- dev_err(&pdev->dev, "Can't allocate controller\n");
+ dev_err(dev, "Can't allocate controller\n");
return -ENOMEM;
}
- ecc->ctlr = pdev->id;
- ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
+ ecc->dev = dev;
+ ecc->id = pdev->id;
+ ecc->legacy_mode = legacy_mode;
+ /* When booting with DT the pdev->id is -1 */
+ if (ecc->id < 0)
+ ecc->id = 0;
+
+ mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edma3_cc");
+ if (!mem) {
+ dev_dbg(dev, "mem resource not found, using index 0\n");
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(dev, "no mem resource?\n");
+ return -ENODEV;
+ }
+ }
+ ecc->base = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(ecc->base))
+ return PTR_ERR(ecc->base);
+
+ platform_set_drvdata(pdev, ecc);
+
+ /* Get eDMA3 configuration from IP */
+ ret = edma_setup_from_hw(dev, info, ecc);
+ if (ret)
+ return ret;
+
+ /* Allocate memory based on the information we got from the IP */
+ ecc->slave_chans = devm_kcalloc(dev, ecc->num_channels,
+ sizeof(*ecc->slave_chans), GFP_KERNEL);
+ if (!ecc->slave_chans)
+ return -ENOMEM;
+
+ ecc->slot_inuse = devm_kcalloc(dev, BITS_TO_LONGS(ecc->num_slots),
+ sizeof(unsigned long), GFP_KERNEL);
+ if (!ecc->slot_inuse)
+ return -ENOMEM;
+
+ ecc->default_queue = info->default_queue;
+
+ for (i = 0; i < ecc->num_slots; i++)
+ edma_write_slot(ecc, i, &dummy_paramset);
+
+ if (info->rsv) {
+ /* Set the reserved slots in inuse list */
+ rsv_slots = info->rsv->rsv_slots;
+ if (rsv_slots) {
+ for (i = 0; rsv_slots[i][0] != -1; i++) {
+ off = rsv_slots[i][0];
+ ln = rsv_slots[i][1];
+ set_bits(off, ln, ecc->slot_inuse);
+ }
+ }
+ }
+
+ /* Clear the xbar mapped channels in unused list */
+ xbar_chans = info->xbar_chans;
+ if (xbar_chans) {
+ for (i = 0; xbar_chans[i][1] != -1; i++) {
+ off = xbar_chans[i][1];
+ }
+ }
+
+ irq = platform_get_irq_byname(pdev, "edma3_ccint");
+ if (irq < 0 && node)
+ irq = irq_of_parse_and_map(node, 0);
+
+ if (irq >= 0) {
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint",
+ dev_name(dev));
+ ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name,
+ ecc);
+ if (ret) {
+ dev_err(dev, "CCINT (%d) failed --> %d\n", irq, ret);
+ return ret;
+ }
+ }
+
+ irq = platform_get_irq_byname(pdev, "edma3_ccerrint");
+ if (irq < 0 && node)
+ irq = irq_of_parse_and_map(node, 2);
+
+ if (irq >= 0) {
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint",
+ dev_name(dev));
+ ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name,
+ ecc);
+ if (ret) {
+ dev_err(dev, "CCERRINT (%d) failed --> %d\n", irq, ret);
+ return ret;
+ }
+ }
+
+ ecc->dummy_slot = edma_alloc_slot(ecc, EDMA_SLOT_ANY);
if (ecc->dummy_slot < 0) {
- dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
+ dev_err(dev, "Can't allocate PaRAM dummy slot\n");
return ecc->dummy_slot;
}
- dma_cap_zero(ecc->dma_slave.cap_mask);
- dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
- dma_cap_set(DMA_CYCLIC, ecc->dma_slave.cap_mask);
- dma_cap_set(DMA_MEMCPY, ecc->dma_slave.cap_mask);
+ queue_priority_mapping = info->queue_priority_mapping;
+
+ if (!ecc->legacy_mode) {
+ int lowest_priority = 0;
+ struct of_phandle_args tc_args;
+
+ ecc->tc_list = devm_kcalloc(dev, ecc->num_tc,
+ sizeof(*ecc->tc_list), GFP_KERNEL);
+ if (!ecc->tc_list)
+ return -ENOMEM;
+
+ for (i = 0;; i++) {
+ ret = of_parse_phandle_with_fixed_args(node, "ti,tptcs",
+ 1, i, &tc_args);
+ if (ret || i == ecc->num_tc)
+ break;
+
+ ecc->tc_list[i].node = tc_args.np;
+ ecc->tc_list[i].id = i;
+ queue_priority_mapping[i][1] = tc_args.args[0];
+ if (queue_priority_mapping[i][1] > lowest_priority) {
+ lowest_priority = queue_priority_mapping[i][1];
+ info->default_queue = i;
+ }
+ }
+ }
+
+ /* Event queue priority mapping */
+ for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+ edma_assign_priority_to_queue(ecc, queue_priority_mapping[i][0],
+ queue_priority_mapping[i][1]);
+
+ for (i = 0; i < ecc->num_region; i++) {
+ edma_write_array2(ecc, EDMA_DRAE, i, 0, 0x0);
+ edma_write_array2(ecc, EDMA_DRAE, i, 1, 0x0);
+ edma_write_array(ecc, EDMA_QRAE, i, 0x0);
+ }
+ ecc->info = info;
- edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
+ /* Init the dma device and channels */
+ edma_dma_init(ecc, legacy_mode);
- edma_chan_init(ecc, &ecc->dma_slave, ecc->slave_chans);
+ for (i = 0; i < ecc->num_channels; i++) {
+ /* Assign all channels to the default queue */
+ edma_assign_channel_eventq(&ecc->slave_chans[i],
+ info->default_queue);
+ /* Set entry slot to the dummy slot */
+ edma_set_chmap(&ecc->slave_chans[i], ecc->dummy_slot);
+ }
ret = dma_async_device_register(&ecc->dma_slave);
- if (ret)
+ if (ret) {
+ dev_err(dev, "slave ddev registration failed (%d)\n", ret);
goto err_reg1;
+ }
- platform_set_drvdata(pdev, ecc);
+ if (ecc->dma_memcpy) {
+ ret = dma_async_device_register(ecc->dma_memcpy);
+ if (ret) {
+ dev_err(dev, "memcpy ddev registration failed (%d)\n",
+ ret);
+ dma_async_device_unregister(&ecc->dma_slave);
+ goto err_reg1;
+ }
+ }
+
+ if (node)
+ of_dma_controller_register(node, of_edma_xlate, ecc);
- dev_info(&pdev->dev, "TI EDMA DMA engine driver\n");
+ dev_info(dev, "TI EDMA DMA engine driver\n");
return 0;
err_reg1:
- edma_free_slot(ecc->dummy_slot);
+ edma_free_slot(ecc, ecc->dummy_slot);
return ret;
}
@@ -1056,33 +2330,112 @@ static int edma_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct edma_cc *ecc = dev_get_drvdata(dev);
+ if (dev->of_node)
+ of_dma_controller_free(dev->of_node);
dma_async_device_unregister(&ecc->dma_slave);
- edma_free_slot(ecc->dummy_slot);
+ if (ecc->dma_memcpy)
+ dma_async_device_unregister(ecc->dma_memcpy);
+ edma_free_slot(ecc, ecc->dummy_slot);
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int edma_pm_suspend(struct device *dev)
+{
+ struct edma_cc *ecc = dev_get_drvdata(dev);
+ struct edma_chan *echan = ecc->slave_chans;
+ int i;
+
+ for (i = 0; i < ecc->num_channels; i++) {
+ if (echan[i].alloced) {
+ edma_setup_interrupt(&echan[i], false);
+ edma_tc_set_pm_state(echan[i].tc, false);
+ }
+ }
+
+ return 0;
+}
+
+static int edma_pm_resume(struct device *dev)
+{
+ struct edma_cc *ecc = dev_get_drvdata(dev);
+ struct edma_chan *echan = ecc->slave_chans;
+ int i;
+ s8 (*queue_priority_mapping)[2];
+
+ queue_priority_mapping = ecc->info->queue_priority_mapping;
+
+ /* Event queue priority mapping */
+ for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+ edma_assign_priority_to_queue(ecc, queue_priority_mapping[i][0],
+ queue_priority_mapping[i][1]);
+
+ for (i = 0; i < ecc->num_channels; i++) {
+ if (echan[i].alloced) {
+ /* ensure access through shadow region 0 */
+ edma_or_array2(ecc, EDMA_DRAE, 0, i >> 5,
+ BIT(i & 0x1f));
+
+ edma_setup_interrupt(&echan[i], true);
+
+ /* Set up channel -> slot mapping for the entry slot */
+ edma_set_chmap(&echan[i], echan[i].slot[0]);
+
+ edma_tc_set_pm_state(echan[i].tc, true);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops edma_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(edma_pm_suspend, edma_pm_resume)
+};
+
static struct platform_driver edma_driver = {
.probe = edma_probe,
.remove = edma_remove,
.driver = {
- .name = "edma-dma-engine",
+ .name = "edma",
+ .pm = &edma_pm_ops,
+ .of_match_table = edma_of_ids,
+ },
+};
+
+static struct platform_driver edma_tptc_driver = {
+ .driver = {
+ .name = "edma3-tptc",
+ .of_match_table = edma_tptc_of_ids,
},
};
bool edma_filter_fn(struct dma_chan *chan, void *param)
{
+ bool match = false;
+
if (chan->device->dev->driver == &edma_driver.driver) {
struct edma_chan *echan = to_edma_chan(chan);
unsigned ch_req = *(unsigned *)param;
- return ch_req == echan->ch_num;
+ if (ch_req == echan->ch_num) {
+ /* The channel is going to be used as HW synchronized */
+ echan->hw_triggered = true;
+ match = true;
+ }
}
- return false;
+ return match;
}
EXPORT_SYMBOL(edma_filter_fn);
static int edma_init(void)
{
+ int ret;
+
+ ret = platform_driver_register(&edma_tptc_driver);
+ if (ret)
+ return ret;
+
return platform_driver_register(&edma_driver);
}
subsys_initcall(edma_init);
@@ -1090,6 +2443,7 @@ subsys_initcall(edma_init);
static void __exit edma_exit(void)
{
platform_driver_unregister(&edma_driver);
+ platform_driver_unregister(&edma_tptc_driver);
}
module_exit(edma_exit);
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 300f821f1890..2209f75fdf05 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1512,6 +1512,7 @@ static const struct of_device_id fsldma_of_ids[] = {
{ .compatible = "fsl,elo-dma", },
{}
};
+MODULE_DEVICE_TABLE(of, fsldma_of_ids);
static struct platform_driver fsldma_of_driver = {
.driver = {
diff --git a/drivers/dma/hsu/Kconfig b/drivers/dma/hsu/Kconfig
index 2810dca70612..c70841731a80 100644
--- a/drivers/dma/hsu/Kconfig
+++ b/drivers/dma/hsu/Kconfig
@@ -5,10 +5,5 @@ config HSU_DMA
select DMA_VIRTUAL_CHANNELS
config HSU_DMA_PCI
- tristate "High Speed UART DMA PCI driver"
- depends on PCI
- select HSU_DMA
- help
- Support the High Speed UART DMA on the platfroms that
- enumerate it as a PCI device. For example, Intel Medfield
- has integrated this HSU DMA controller.
+ tristate
+ depends on HSU_DMA && PCI
diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c
index 7669c7dd1e34..823ad728aecf 100644
--- a/drivers/dma/hsu/hsu.c
+++ b/drivers/dma/hsu/hsu.c
@@ -146,7 +146,7 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
u32 sr;
/* Sanity check */
- if (nr >= chip->pdata->nr_channels)
+ if (nr >= chip->hsu->nr_channels)
return IRQ_NONE;
hsuc = &chip->hsu->chan[nr];
@@ -375,7 +375,6 @@ static void hsu_dma_free_chan_resources(struct dma_chan *chan)
int hsu_dma_probe(struct hsu_dma_chip *chip)
{
struct hsu_dma *hsu;
- struct hsu_dma_platform_data *pdata = chip->pdata;
void __iomem *addr = chip->regs + chip->offset;
unsigned short i;
int ret;
@@ -386,25 +385,16 @@ int hsu_dma_probe(struct hsu_dma_chip *chip)
chip->hsu = hsu;
- if (!pdata) {
- pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
+ /* Calculate nr_channels from the IO space length */
+ hsu->nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH;
- chip->pdata = pdata;
-
- /* Guess nr_channels from the IO space length */
- pdata->nr_channels = (chip->length - chip->offset) /
- HSU_DMA_CHAN_LENGTH;
- }
-
- hsu->chan = devm_kcalloc(chip->dev, pdata->nr_channels,
+ hsu->chan = devm_kcalloc(chip->dev, hsu->nr_channels,
sizeof(*hsu->chan), GFP_KERNEL);
if (!hsu->chan)
return -ENOMEM;
INIT_LIST_HEAD(&hsu->dma.channels);
- for (i = 0; i < pdata->nr_channels; i++) {
+ for (i = 0; i < hsu->nr_channels; i++) {
struct hsu_dma_chan *hsuc = &hsu->chan[i];
hsuc->vchan.desc_free = hsu_dma_desc_free;
@@ -440,7 +430,7 @@ int hsu_dma_probe(struct hsu_dma_chip *chip)
if (ret)
return ret;
- dev_info(chip->dev, "Found HSU DMA, %d channels\n", pdata->nr_channels);
+ dev_info(chip->dev, "Found HSU DMA, %d channels\n", hsu->nr_channels);
return 0;
}
EXPORT_SYMBOL_GPL(hsu_dma_probe);
@@ -452,7 +442,7 @@ int hsu_dma_remove(struct hsu_dma_chip *chip)
dma_async_device_unregister(&hsu->dma);
- for (i = 0; i < chip->pdata->nr_channels; i++) {
+ for (i = 0; i < hsu->nr_channels; i++) {
struct hsu_dma_chan *hsuc = &hsu->chan[i];
tasklet_kill(&hsuc->vchan.task);
diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h
index eeb9fff66967..f06579c6d548 100644
--- a/drivers/dma/hsu/hsu.h
+++ b/drivers/dma/hsu/hsu.h
@@ -107,6 +107,7 @@ struct hsu_dma {
/* channels */
struct hsu_dma_chan *chan;
+ unsigned short nr_channels;
};
static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c
index 77879e6ddc4c..e2db76bd56d8 100644
--- a/drivers/dma/hsu/pci.c
+++ b/drivers/dma/hsu/pci.c
@@ -31,7 +31,7 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev)
irqreturn_t ret = IRQ_NONE;
dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
- for (i = 0; i < chip->pdata->nr_channels; i++) {
+ for (i = 0; i < chip->hsu->nr_channels; i++) {
if (dmaisr & 0x1)
ret |= hsu_dma_irq(chip, i);
dmaisr >>= 1;
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 48d6d9e94f67..7d56b47e4fcf 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -65,9 +65,6 @@ static void idma64_chan_init(struct idma64 *idma64, struct idma64_chan *idma64c)
u32 cfghi = IDMA64C_CFGH_SRC_PER(1) | IDMA64C_CFGH_DST_PER(0);
u32 cfglo = 0;
- /* Enforce FIFO drain when channel is suspended */
- cfglo |= IDMA64C_CFGL_CH_DRAIN;
-
/* Set default burst alignment */
cfglo |= IDMA64C_CFGL_DST_BURST_ALIGN | IDMA64C_CFGL_SRC_BURST_ALIGN;
@@ -257,15 +254,15 @@ static u64 idma64_hw_desc_fill(struct idma64_hw_desc *hw,
dar = config->dst_addr;
ctllo |= IDMA64C_CTLL_DST_FIX | IDMA64C_CTLL_SRC_INC |
IDMA64C_CTLL_FC_M2P;
- src_width = min_t(u32, 2, __fls(sar | hw->len));
- dst_width = __fls(config->dst_addr_width);
+ src_width = __ffs(sar | hw->len | 4);
+ dst_width = __ffs(config->dst_addr_width);
} else { /* DMA_DEV_TO_MEM */
sar = config->src_addr;
dar = hw->phys;
ctllo |= IDMA64C_CTLL_DST_INC | IDMA64C_CTLL_SRC_FIX |
IDMA64C_CTLL_FC_P2M;
- src_width = __fls(config->src_addr_width);
- dst_width = min_t(u32, 2, __fls(dar | hw->len));
+ src_width = __ffs(config->src_addr_width);
+ dst_width = __ffs(dar | hw->len | 4);
}
lli->sar = sar;
@@ -428,12 +425,17 @@ static int idma64_slave_config(struct dma_chan *chan,
return 0;
}
-static void idma64_chan_deactivate(struct idma64_chan *idma64c)
+static void idma64_chan_deactivate(struct idma64_chan *idma64c, bool drain)
{
unsigned short count = 100;
u32 cfglo;
cfglo = channel_readl(idma64c, CFG_LO);
+ if (drain)
+ cfglo |= IDMA64C_CFGL_CH_DRAIN;
+ else
+ cfglo &= ~IDMA64C_CFGL_CH_DRAIN;
+
channel_writel(idma64c, CFG_LO, cfglo | IDMA64C_CFGL_CH_SUSP);
do {
udelay(1);
@@ -456,7 +458,7 @@ static int idma64_pause(struct dma_chan *chan)
spin_lock_irqsave(&idma64c->vchan.lock, flags);
if (idma64c->desc && idma64c->desc->status == DMA_IN_PROGRESS) {
- idma64_chan_deactivate(idma64c);
+ idma64_chan_deactivate(idma64c, false);
idma64c->desc->status = DMA_PAUSED;
}
spin_unlock_irqrestore(&idma64c->vchan.lock, flags);
@@ -486,7 +488,7 @@ static int idma64_terminate_all(struct dma_chan *chan)
LIST_HEAD(head);
spin_lock_irqsave(&idma64c->vchan.lock, flags);
- idma64_chan_deactivate(idma64c);
+ idma64_chan_deactivate(idma64c, true);
idma64_stop_transfer(idma64c);
if (idma64c->desc) {
idma64_vdesc_free(&idma64c->desc->vdesc);
diff --git a/drivers/dma/idma64.h b/drivers/dma/idma64.h
index a4d99685a7c4..f6aeff0af8a5 100644
--- a/drivers/dma/idma64.h
+++ b/drivers/dma/idma64.h
@@ -16,6 +16,8 @@
#include <linux/spinlock.h>
#include <linux/types.h>
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
#include "virt-dma.h"
/* Channel registers */
@@ -166,19 +168,13 @@ static inline void idma64c_writel(struct idma64_chan *idma64c, int offset,
static inline u64 idma64c_readq(struct idma64_chan *idma64c, int offset)
{
- u64 l, h;
-
- l = idma64c_readl(idma64c, offset);
- h = idma64c_readl(idma64c, offset + 4);
-
- return l | (h << 32);
+ return lo_hi_readq(idma64c->regs + offset);
}
static inline void idma64c_writeq(struct idma64_chan *idma64c, int offset,
u64 value)
{
- idma64c_writel(idma64c, offset, value);
- idma64c_writel(idma64c, offset + 4, value >> 32);
+ lo_hi_writeq(value, idma64c->regs + offset);
}
#define channel_readq(idma64c, reg) \
@@ -217,7 +213,7 @@ static inline void idma64_writel(struct idma64 *idma64, int offset, u32 value)
idma64_writel(idma64, IDMA64_##reg, (value))
/**
- * struct idma64_chip - representation of DesignWare DMA controller hardware
+ * struct idma64_chip - representation of iDMA 64-bit controller hardware
* @dev: struct device of the DMA controller
* @irq: irq line
* @regs: memory mapped I/O space
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 9d375bc7590a..0f6fd42f55ca 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1462,7 +1462,7 @@ err_firmware:
#define EVENT_REMAP_CELLS 3
-static int __init sdma_event_remap(struct sdma_engine *sdma)
+static int sdma_event_remap(struct sdma_engine *sdma)
{
struct device_node *np = sdma->dev->of_node;
struct device_node *gpr_np = of_parse_phandle(np, "gpr", 0);
@@ -1478,7 +1478,7 @@ static int __init sdma_event_remap(struct sdma_engine *sdma)
event_remap = of_find_property(np, propname, NULL);
num_map = event_remap ? (event_remap->length / sizeof(u32)) : 0;
if (!num_map) {
- dev_warn(sdma->dev, "no event needs to be remapped\n");
+ dev_dbg(sdma->dev, "no event needs to be remapped\n");
goto out;
} else if (num_map % EVENT_REMAP_CELLS) {
dev_err(sdma->dev, "the property %s must modulo %d\n",
@@ -1826,8 +1826,6 @@ static int sdma_probe(struct platform_device *pdev)
of_node_put(spba_bus);
}
- dev_info(sdma->dev, "initialized\n");
-
return 0;
err_register:
@@ -1852,7 +1850,6 @@ static int sdma_remove(struct platform_device *pdev)
}
platform_set_drvdata(pdev, NULL);
- dev_info(&pdev->dev, "Removed...\n");
return 0;
}
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index f66b7e640610..1d5df2ef148b 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -197,7 +197,8 @@ static void __ioat_start_null_desc(struct ioatdma_chan *ioat_chan)
void ioat_start_null_desc(struct ioatdma_chan *ioat_chan)
{
spin_lock_bh(&ioat_chan->prep_lock);
- __ioat_start_null_desc(ioat_chan);
+ if (!test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ __ioat_start_null_desc(ioat_chan);
spin_unlock_bh(&ioat_chan->prep_lock);
}
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 1bc084986646..8f4e607d5817 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -82,8 +82,9 @@ struct ioatdma_device {
struct dma_pool *sed_hw_pool[MAX_SED_POOLS];
struct dma_device dma_dev;
u8 version;
- struct msix_entry msix_entries[4];
- struct ioatdma_chan *idx[4];
+#define IOAT_MAX_CHANS 4
+ struct msix_entry msix_entries[IOAT_MAX_CHANS];
+ struct ioatdma_chan *idx[IOAT_MAX_CHANS];
struct dca_provider *dca;
enum ioat_irq_mode irq_mode;
u32 cap;
@@ -95,6 +96,7 @@ struct ioatdma_chan {
dma_addr_t last_completion;
spinlock_t cleanup_lock;
unsigned long state;
+ #define IOAT_CHAN_DOWN 0
#define IOAT_COMPLETION_ACK 1
#define IOAT_RESET_PENDING 2
#define IOAT_KOBJ_INIT_FAIL 3
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
index 1c3c9b0abf4e..4ef0c5e07912 100644
--- a/drivers/dma/ioat/init.c
+++ b/drivers/dma/ioat/init.c
@@ -27,6 +27,7 @@
#include <linux/workqueue.h>
#include <linux/prefetch.h>
#include <linux/dca.h>
+#include <linux/aer.h>
#include "dma.h"
#include "registers.h"
#include "hw.h"
@@ -1186,13 +1187,116 @@ static int ioat3_dma_probe(struct ioatdma_device *ioat_dma, int dca)
return 0;
}
+static void ioat_shutdown(struct pci_dev *pdev)
+{
+ struct ioatdma_device *ioat_dma = pci_get_drvdata(pdev);
+ struct ioatdma_chan *ioat_chan;
+ int i;
+
+ if (!ioat_dma)
+ return;
+
+ for (i = 0; i < IOAT_MAX_CHANS; i++) {
+ ioat_chan = ioat_dma->idx[i];
+ if (!ioat_chan)
+ continue;
+
+ spin_lock_bh(&ioat_chan->prep_lock);
+ set_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
+ del_timer_sync(&ioat_chan->timer);
+ spin_unlock_bh(&ioat_chan->prep_lock);
+ /* this should quiesce then reset */
+ ioat_reset_hw(ioat_chan);
+ }
+
+ ioat_disable_interrupts(ioat_dma);
+}
+
+void ioat_resume(struct ioatdma_device *ioat_dma)
+{
+ struct ioatdma_chan *ioat_chan;
+ u32 chanerr;
+ int i;
+
+ for (i = 0; i < IOAT_MAX_CHANS; i++) {
+ ioat_chan = ioat_dma->idx[i];
+ if (!ioat_chan)
+ continue;
+
+ spin_lock_bh(&ioat_chan->prep_lock);
+ clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
+ spin_unlock_bh(&ioat_chan->prep_lock);
+
+ chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+
+ /* no need to reset as shutdown already did that */
+ }
+}
+
#define DRV_NAME "ioatdma"
+static pci_ers_result_t ioat_pcie_error_detected(struct pci_dev *pdev,
+ enum pci_channel_state error)
+{
+ dev_dbg(&pdev->dev, "%s: PCIe AER error %d\n", DRV_NAME, error);
+
+ /* quiesce and block I/O */
+ ioat_shutdown(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t ioat_pcie_error_slot_reset(struct pci_dev *pdev)
+{
+ pci_ers_result_t result = PCI_ERS_RESULT_RECOVERED;
+ int err;
+
+ dev_dbg(&pdev->dev, "%s post reset handling\n", DRV_NAME);
+
+ if (pci_enable_device_mem(pdev) < 0) {
+ dev_err(&pdev->dev,
+ "Failed to enable PCIe device after reset.\n");
+ result = PCI_ERS_RESULT_DISCONNECT;
+ } else {
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
+ pci_save_state(pdev);
+ pci_wake_from_d3(pdev, false);
+ }
+
+ err = pci_cleanup_aer_uncorrect_error_status(pdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "AER uncorrect error status clear failed: %#x\n", err);
+ }
+
+ return result;
+}
+
+static void ioat_pcie_error_resume(struct pci_dev *pdev)
+{
+ struct ioatdma_device *ioat_dma = pci_get_drvdata(pdev);
+
+ dev_dbg(&pdev->dev, "%s: AER handling resuming\n", DRV_NAME);
+
+ /* initialize and bring everything back */
+ ioat_resume(ioat_dma);
+}
+
+static const struct pci_error_handlers ioat_err_handler = {
+ .error_detected = ioat_pcie_error_detected,
+ .slot_reset = ioat_pcie_error_slot_reset,
+ .resume = ioat_pcie_error_resume,
+};
+
static struct pci_driver ioat_pci_driver = {
.name = DRV_NAME,
.id_table = ioat_pci_tbl,
.probe = ioat_pci_probe,
.remove = ioat_remove,
+ .shutdown = ioat_shutdown,
+ .err_handler = &ioat_err_handler,
};
static struct ioatdma_device *
@@ -1245,13 +1349,17 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, device);
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
- if (device->version >= IOAT_VER_3_0)
+ if (device->version >= IOAT_VER_3_0) {
err = ioat3_dma_probe(device, ioat_dca_enabled);
- else
+
+ if (device->version >= IOAT_VER_3_3)
+ pci_enable_pcie_error_reporting(pdev);
+ } else
return -ENODEV;
if (err) {
dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n");
+ pci_disable_pcie_error_reporting(pdev);
return -ENODEV;
}
@@ -1271,6 +1379,8 @@ static void ioat_remove(struct pci_dev *pdev)
free_dca_provider(device->dca);
device->dca = NULL;
}
+
+ pci_disable_pcie_error_reporting(pdev);
ioat_dma_remove(device);
}
diff --git a/drivers/dma/ioat/prep.c b/drivers/dma/ioat/prep.c
index ad4fb41cd23b..6bb4a13a8fbd 100644
--- a/drivers/dma/ioat/prep.c
+++ b/drivers/dma/ioat/prep.c
@@ -121,6 +121,9 @@ ioat_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,
size_t total_len = len;
int num_descs, idx, i;
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
+
num_descs = ioat_xferlen_to_descs(ioat_chan, len);
if (likely(num_descs) &&
ioat_check_space_lock(ioat_chan, num_descs) == 0)
@@ -254,6 +257,11 @@ struct dma_async_tx_descriptor *
ioat_prep_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
unsigned int src_cnt, size_t len, unsigned long flags)
{
+ struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
+
return __ioat_prep_xor_lock(chan, NULL, dest, src, src_cnt, len, flags);
}
@@ -262,6 +270,11 @@ ioat_prep_xor_val(struct dma_chan *chan, dma_addr_t *src,
unsigned int src_cnt, size_t len,
enum sum_check_flags *result, unsigned long flags)
{
+ struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
+
/* the cleanup routine only sets bits on validate failure, it
* does not clear bits on validate success... so clear it here
*/
@@ -574,6 +587,11 @@ ioat_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
unsigned int src_cnt, const unsigned char *scf, size_t len,
unsigned long flags)
{
+ struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
+
/* specify valid address for disabled result */
if (flags & DMA_PREP_PQ_DISABLE_P)
dst[0] = dst[1];
@@ -614,6 +632,11 @@ ioat_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
unsigned int src_cnt, const unsigned char *scf, size_t len,
enum sum_check_flags *pqres, unsigned long flags)
{
+ struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
+
/* specify valid address for disabled result */
if (flags & DMA_PREP_PQ_DISABLE_P)
pq[0] = pq[1];
@@ -638,6 +661,10 @@ ioat_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
{
unsigned char scf[MAX_SCF];
dma_addr_t pq[2];
+ struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
if (src_cnt > MAX_SCF)
return NULL;
@@ -661,6 +688,10 @@ ioat_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src,
{
unsigned char scf[MAX_SCF];
dma_addr_t pq[2];
+ struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
if (src_cnt > MAX_SCF)
return NULL;
@@ -689,6 +720,9 @@ ioat_prep_interrupt_lock(struct dma_chan *c, unsigned long flags)
struct ioat_ring_ent *desc;
struct ioat_dma_descriptor *hw;
+ if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state))
+ return NULL;
+
if (ioat_check_space_lock(ioat_chan, 1) == 0)
desc = ioat_get_ring_ent(ioat_chan, ioat_chan->head);
else
diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c
index 74d9db05a5ad..068e920ecb68 100644
--- a/drivers/dma/mic_x100_dma.c
+++ b/drivers/dma/mic_x100_dma.c
@@ -193,8 +193,16 @@ static void mic_dma_prog_intr(struct mic_dma_chan *ch)
static int mic_dma_do_dma(struct mic_dma_chan *ch, int flags, dma_addr_t src,
dma_addr_t dst, size_t len)
{
- if (-ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len))
+ if (len && -ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len)) {
return -ENOMEM;
+ } else {
+ /* 3 is the maximum number of status descriptors */
+ int ret = mic_dma_avail_desc_ring_space(ch, 3);
+
+ if (ret < 0)
+ return ret;
+ }
+
/* Above mic_dma_prog_memcpy_desc() makes sure we have enough space */
if (flags & DMA_PREP_FENCE) {
mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
@@ -270,6 +278,33 @@ allocate_tx(struct mic_dma_chan *ch)
return tx;
}
+/* Program a status descriptor with dst as address and value to be written */
+static struct dma_async_tx_descriptor *
+mic_dma_prep_status_lock(struct dma_chan *ch, dma_addr_t dst, u64 src_val,
+ unsigned long flags)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+ int result;
+
+ spin_lock(&mic_ch->prep_lock);
+ result = mic_dma_avail_desc_ring_space(mic_ch, 4);
+ if (result < 0)
+ goto error;
+ mic_dma_prep_status_desc(&mic_ch->desc_ring[mic_ch->head], src_val, dst,
+ false);
+ mic_dma_hw_ring_inc_head(mic_ch);
+ result = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
+ if (result < 0)
+ goto error;
+
+ return allocate_tx(mic_ch);
+error:
+ dev_err(mic_dma_ch_to_device(mic_ch),
+ "Error enqueueing dma status descriptor, error=%d\n", result);
+ spin_unlock(&mic_ch->prep_lock);
+ return NULL;
+}
+
/*
* Prepare a memcpy descriptor to be added to the ring.
* Note that the temporary descriptor adds an extra overhead of copying the
@@ -587,6 +622,8 @@ static int mic_dma_register_dma_device(struct mic_dma_device *mic_dma_dev,
mic_dma_free_chan_resources;
mic_dma_dev->dma_dev.device_tx_status = mic_dma_tx_status;
mic_dma_dev->dma_dev.device_prep_dma_memcpy = mic_dma_prep_memcpy_lock;
+ mic_dma_dev->dma_dev.device_prep_dma_imm_data =
+ mic_dma_prep_status_lock;
mic_dma_dev->dma_dev.device_prep_dma_interrupt =
mic_dma_prep_interrupt_lock;
mic_dma_dev->dma_dev.device_issue_pending = mic_dma_issue_pending;
diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c
index b4634109e010..631c4435e075 100644
--- a/drivers/dma/moxart-dma.c
+++ b/drivers/dma/moxart-dma.c
@@ -652,6 +652,7 @@ static const struct of_device_id moxart_dma_match[] = {
{ .compatible = "moxa,moxart-dma" },
{ }
};
+MODULE_DEVICE_TABLE(of, moxart_dma_match);
static struct platform_driver moxart_driver = {
.probe = moxart_probe,
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index e6281e7aa46e..aae76fb39adc 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -1073,6 +1073,7 @@ static const struct of_device_id mpc_dma_match[] = {
{ .compatible = "fsl,mpc8308-dma", },
{},
};
+MODULE_DEVICE_TABLE(of, mpc_dma_match);
static struct platform_driver mpc_dma_driver = {
.probe = mpc_dma_probe,
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 249445c8a4c6..1dfc71c90123 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -935,8 +935,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
else
d->ccr |= CCR_SYNC_ELEMENT;
- if (dir == DMA_DEV_TO_MEM)
+ if (dir == DMA_DEV_TO_MEM) {
d->ccr |= CCR_TRIGGER_SRC;
+ d->csdp |= CSDP_DST_PACKED;
+ } else {
+ d->csdp |= CSDP_SRC_PACKED;
+ }
d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index ebd8a5f398b0..f1bcc2a163b3 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -679,8 +679,11 @@ static int usb_dmac_runtime_suspend(struct device *dev)
struct usb_dmac *dmac = dev_get_drvdata(dev);
int i;
- for (i = 0; i < dmac->n_channels; ++i)
+ for (i = 0; i < dmac->n_channels; ++i) {
+ if (!dmac->channels[i].iomem)
+ break;
usb_dmac_chan_halt(&dmac->channels[i]);
+ }
return 0;
}
@@ -799,11 +802,10 @@ static int usb_dmac_probe(struct platform_device *pdev)
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
- return ret;
+ goto error_pm;
}
ret = usb_dmac_init(dmac);
- pm_runtime_put(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "failed to reset device\n");
@@ -851,10 +853,13 @@ static int usb_dmac_probe(struct platform_device *pdev)
if (ret < 0)
goto error;
+ pm_runtime_put(&pdev->dev);
return 0;
error:
of_dma_controller_free(pdev->dev.of_node);
+ pm_runtime_put(&pdev->dev);
+error_pm:
pm_runtime_disable(&pdev->dev);
return ret;
}
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 7d5598d874e1..22ea2419ee56 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -1149,6 +1149,7 @@ static const struct of_device_id sirfsoc_dma_match[] = {
{ .compatible = "sirf,atlas7-dmac-v2", .data = &sirfsoc_dmadata_a7v2,},
{},
};
+MODULE_DEVICE_TABLE(of, sirfsoc_dma_match);
static struct platform_driver sirfsoc_dma_driver = {
.probe = sirfsoc_dma_probe,
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 750d1b313684..dd3e7ba273ad 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2907,7 +2907,7 @@ static int __init d40_dmaengine_init(struct d40_base *base,
if (err) {
d40_err(base->dev,
- "Failed to regsiter memcpy only channels\n");
+ "Failed to register memcpy only channels\n");
goto failure2;
}
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 73e0be6e2100..2db12e493c53 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -908,6 +908,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, sun6i_dma_match);
static int sun6i_dma_probe(struct platform_device *pdev)
{
diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c
index 5cce8c9d0026..a415edbe61b1 100644
--- a/drivers/dma/ti-dma-crossbar.c
+++ b/drivers/dma/ti-dma-crossbar.c
@@ -17,13 +17,184 @@
#include <linux/of_device.h>
#include <linux/of_dma.h>
-#define TI_XBAR_OUTPUTS 127
-#define TI_XBAR_INPUTS 256
+#define TI_XBAR_DRA7 0
+#define TI_XBAR_AM335X 1
+
+static const struct of_device_id ti_dma_xbar_match[] = {
+ {
+ .compatible = "ti,dra7-dma-crossbar",
+ .data = (void *)TI_XBAR_DRA7,
+ },
+ {
+ .compatible = "ti,am335x-edma-crossbar",
+ .data = (void *)TI_XBAR_AM335X,
+ },
+ {},
+};
+
+/* Crossbar on AM335x/AM437x family */
+#define TI_AM335X_XBAR_LINES 64
+
+struct ti_am335x_xbar_data {
+ void __iomem *iomem;
+
+ struct dma_router dmarouter;
+
+ u32 xbar_events; /* maximum number of events to select in xbar */
+ u32 dma_requests; /* number of DMA requests on eDMA */
+};
+
+struct ti_am335x_xbar_map {
+ u16 dma_line;
+ u16 mux_val;
+};
+
+static inline void ti_am335x_xbar_write(void __iomem *iomem, int event, u16 val)
+{
+ writeb_relaxed(val & 0x1f, iomem + event);
+}
+
+static void ti_am335x_xbar_free(struct device *dev, void *route_data)
+{
+ struct ti_am335x_xbar_data *xbar = dev_get_drvdata(dev);
+ struct ti_am335x_xbar_map *map = route_data;
+
+ dev_dbg(dev, "Unmapping XBAR event %u on channel %u\n",
+ map->mux_val, map->dma_line);
+
+ ti_am335x_xbar_write(xbar->iomem, map->dma_line, 0);
+ kfree(map);
+}
+
+static void *ti_am335x_xbar_route_allocate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
+ struct ti_am335x_xbar_data *xbar = platform_get_drvdata(pdev);
+ struct ti_am335x_xbar_map *map;
+
+ if (dma_spec->args_count != 3)
+ return ERR_PTR(-EINVAL);
+
+ if (dma_spec->args[2] >= xbar->xbar_events) {
+ dev_err(&pdev->dev, "Invalid XBAR event number: %d\n",
+ dma_spec->args[2]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (dma_spec->args[0] >= xbar->dma_requests) {
+ dev_err(&pdev->dev, "Invalid DMA request line number: %d\n",
+ dma_spec->args[0]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* The of_node_put() will be done in the core for the node */
+ dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
+ if (!dma_spec->np) {
+ dev_err(&pdev->dev, "Can't get DMA master\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (!map) {
+ of_node_put(dma_spec->np);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ map->dma_line = (u16)dma_spec->args[0];
+ map->mux_val = (u16)dma_spec->args[2];
+
+ dma_spec->args[2] = 0;
+ dma_spec->args_count = 2;
+
+ dev_dbg(&pdev->dev, "Mapping XBAR event%u to DMA%u\n",
+ map->mux_val, map->dma_line);
+
+ ti_am335x_xbar_write(xbar->iomem, map->dma_line, map->mux_val);
+
+ return map;
+}
+
+static const struct of_device_id ti_am335x_master_match[] = {
+ { .compatible = "ti,edma3-tpcc", },
+ {},
+};
+
+static int ti_am335x_xbar_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ const struct of_device_id *match;
+ struct device_node *dma_node;
+ struct ti_am335x_xbar_data *xbar;
+ struct resource *res;
+ void __iomem *iomem;
+ int i, ret;
+
+ if (!node)
+ return -ENODEV;
+
+ xbar = devm_kzalloc(&pdev->dev, sizeof(*xbar), GFP_KERNEL);
+ if (!xbar)
+ return -ENOMEM;
+
+ dma_node = of_parse_phandle(node, "dma-masters", 0);
+ if (!dma_node) {
+ dev_err(&pdev->dev, "Can't get DMA master node\n");
+ return -ENODEV;
+ }
+
+ match = of_match_node(ti_am335x_master_match, dma_node);
+ if (!match) {
+ dev_err(&pdev->dev, "DMA master is not supported\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(dma_node, "dma-requests",
+ &xbar->dma_requests)) {
+ dev_info(&pdev->dev,
+ "Missing XBAR output information, using %u.\n",
+ TI_AM335X_XBAR_LINES);
+ xbar->dma_requests = TI_AM335X_XBAR_LINES;
+ }
+ of_node_put(dma_node);
+
+ if (of_property_read_u32(node, "dma-requests", &xbar->xbar_events)) {
+ dev_info(&pdev->dev,
+ "Missing XBAR input information, using %u.\n",
+ TI_AM335X_XBAR_LINES);
+ xbar->xbar_events = TI_AM335X_XBAR_LINES;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iomem = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(iomem))
+ return PTR_ERR(iomem);
+
+ xbar->iomem = iomem;
+
+ xbar->dmarouter.dev = &pdev->dev;
+ xbar->dmarouter.route_free = ti_am335x_xbar_free;
+
+ platform_set_drvdata(pdev, xbar);
+
+ /* Reset the crossbar */
+ for (i = 0; i < xbar->dma_requests; i++)
+ ti_am335x_xbar_write(xbar->iomem, i, 0);
+
+ ret = of_dma_router_register(node, ti_am335x_xbar_route_allocate,
+ &xbar->dmarouter);
+
+ return ret;
+}
+
+/* Crossbar on DRA7xx family */
+#define TI_DRA7_XBAR_OUTPUTS 127
+#define TI_DRA7_XBAR_INPUTS 256
#define TI_XBAR_EDMA_OFFSET 0
#define TI_XBAR_SDMA_OFFSET 1
-struct ti_dma_xbar_data {
+struct ti_dra7_xbar_data {
void __iomem *iomem;
struct dma_router dmarouter;
@@ -35,35 +206,35 @@ struct ti_dma_xbar_data {
u32 dma_offset;
};
-struct ti_dma_xbar_map {
+struct ti_dra7_xbar_map {
u16 xbar_in;
int xbar_out;
};
-static inline void ti_dma_xbar_write(void __iomem *iomem, int xbar, u16 val)
+static inline void ti_dra7_xbar_write(void __iomem *iomem, int xbar, u16 val)
{
writew_relaxed(val, iomem + (xbar * 2));
}
-static void ti_dma_xbar_free(struct device *dev, void *route_data)
+static void ti_dra7_xbar_free(struct device *dev, void *route_data)
{
- struct ti_dma_xbar_data *xbar = dev_get_drvdata(dev);
- struct ti_dma_xbar_map *map = route_data;
+ struct ti_dra7_xbar_data *xbar = dev_get_drvdata(dev);
+ struct ti_dra7_xbar_map *map = route_data;
dev_dbg(dev, "Unmapping XBAR%u (was routed to %d)\n",
map->xbar_in, map->xbar_out);
- ti_dma_xbar_write(xbar->iomem, map->xbar_out, xbar->safe_val);
+ ti_dra7_xbar_write(xbar->iomem, map->xbar_out, xbar->safe_val);
idr_remove(&xbar->map_idr, map->xbar_out);
kfree(map);
}
-static void *ti_dma_xbar_route_allocate(struct of_phandle_args *dma_spec,
- struct of_dma *ofdma)
+static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
{
struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
- struct ti_dma_xbar_data *xbar = platform_get_drvdata(pdev);
- struct ti_dma_xbar_map *map;
+ struct ti_dra7_xbar_data *xbar = platform_get_drvdata(pdev);
+ struct ti_dra7_xbar_map *map;
if (dma_spec->args[0] >= xbar->xbar_requests) {
dev_err(&pdev->dev, "Invalid XBAR request number: %d\n",
@@ -93,12 +264,12 @@ static void *ti_dma_xbar_route_allocate(struct of_phandle_args *dma_spec,
dev_dbg(&pdev->dev, "Mapping XBAR%u to DMA%d\n",
map->xbar_in, map->xbar_out);
- ti_dma_xbar_write(xbar->iomem, map->xbar_out, map->xbar_in);
+ ti_dra7_xbar_write(xbar->iomem, map->xbar_out, map->xbar_in);
return map;
}
-static const struct of_device_id ti_dma_master_match[] = {
+static const struct of_device_id ti_dra7_master_match[] = {
{
.compatible = "ti,omap4430-sdma",
.data = (void *)TI_XBAR_SDMA_OFFSET,
@@ -110,12 +281,12 @@ static const struct of_device_id ti_dma_master_match[] = {
{},
};
-static int ti_dma_xbar_probe(struct platform_device *pdev)
+static int ti_dra7_xbar_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
const struct of_device_id *match;
struct device_node *dma_node;
- struct ti_dma_xbar_data *xbar;
+ struct ti_dra7_xbar_data *xbar;
struct resource *res;
u32 safe_val;
void __iomem *iomem;
@@ -136,7 +307,7 @@ static int ti_dma_xbar_probe(struct platform_device *pdev)
return -ENODEV;
}
- match = of_match_node(ti_dma_master_match, dma_node);
+ match = of_match_node(ti_dra7_master_match, dma_node);
if (!match) {
dev_err(&pdev->dev, "DMA master is not supported\n");
return -EINVAL;
@@ -146,16 +317,16 @@ static int ti_dma_xbar_probe(struct platform_device *pdev)
&xbar->dma_requests)) {
dev_info(&pdev->dev,
"Missing XBAR output information, using %u.\n",
- TI_XBAR_OUTPUTS);
- xbar->dma_requests = TI_XBAR_OUTPUTS;
+ TI_DRA7_XBAR_OUTPUTS);
+ xbar->dma_requests = TI_DRA7_XBAR_OUTPUTS;
}
of_node_put(dma_node);
if (of_property_read_u32(node, "dma-requests", &xbar->xbar_requests)) {
dev_info(&pdev->dev,
"Missing XBAR input information, using %u.\n",
- TI_XBAR_INPUTS);
- xbar->xbar_requests = TI_XBAR_INPUTS;
+ TI_DRA7_XBAR_INPUTS);
+ xbar->xbar_requests = TI_DRA7_XBAR_INPUTS;
}
if (!of_property_read_u32(node, "ti,dma-safe-map", &safe_val))
@@ -169,30 +340,50 @@ static int ti_dma_xbar_probe(struct platform_device *pdev)
xbar->iomem = iomem;
xbar->dmarouter.dev = &pdev->dev;
- xbar->dmarouter.route_free = ti_dma_xbar_free;
+ xbar->dmarouter.route_free = ti_dra7_xbar_free;
xbar->dma_offset = (u32)match->data;
platform_set_drvdata(pdev, xbar);
/* Reset the crossbar */
for (i = 0; i < xbar->dma_requests; i++)
- ti_dma_xbar_write(xbar->iomem, i, xbar->safe_val);
+ ti_dra7_xbar_write(xbar->iomem, i, xbar->safe_val);
- ret = of_dma_router_register(node, ti_dma_xbar_route_allocate,
+ ret = of_dma_router_register(node, ti_dra7_xbar_route_allocate,
&xbar->dmarouter);
if (ret) {
/* Restore the defaults for the crossbar */
for (i = 0; i < xbar->dma_requests; i++)
- ti_dma_xbar_write(xbar->iomem, i, i);
+ ti_dra7_xbar_write(xbar->iomem, i, i);
}
return ret;
}
-static const struct of_device_id ti_dma_xbar_match[] = {
- { .compatible = "ti,dra7-dma-crossbar" },
- {},
-};
+static int ti_dma_xbar_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ int ret;
+
+ match = of_match_node(ti_dma_xbar_match, pdev->dev.of_node);
+ if (unlikely(!match))
+ return -EINVAL;
+
+ switch ((u32)match->data) {
+ case TI_XBAR_DRA7:
+ ret = ti_dra7_xbar_probe(pdev);
+ break;
+ case TI_XBAR_AM335X:
+ ret = ti_am335x_xbar_probe(pdev);
+ break;
+ default:
+ dev_err(&pdev->dev, "Unsupported crossbar\n");
+ ret = -ENODEV;
+ break;
+ }
+
+ return ret;
+}
static struct platform_driver ti_dma_xbar_driver = {
.driver = {
diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h
index 181b95267866..2fa47745a41f 100644
--- a/drivers/dma/virt-dma.h
+++ b/drivers/dma/virt-dma.h
@@ -47,9 +47,9 @@ struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t);
/**
* vchan_tx_prep - prepare a descriptor
- * vc: virtual channel allocating this descriptor
- * vd: virtual descriptor to prepare
- * tx_flags: flags argument passed in to prepare function
+ * @vc: virtual channel allocating this descriptor
+ * @vd: virtual descriptor to prepare
+ * @tx_flags: flags argument passed in to prepare function
*/
static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc,
struct virt_dma_desc *vd, unsigned long tx_flags)
@@ -65,7 +65,7 @@ static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan
/**
* vchan_issue_pending - move submitted descriptors to issued list
- * vc: virtual channel to update
+ * @vc: virtual channel to update
*
* vc.lock must be held by caller
*/
@@ -77,7 +77,7 @@ static inline bool vchan_issue_pending(struct virt_dma_chan *vc)
/**
* vchan_cookie_complete - report completion of a descriptor
- * vd: virtual descriptor to update
+ * @vd: virtual descriptor to update
*
* vc.lock must be held by caller
*/
@@ -97,7 +97,7 @@ static inline void vchan_cookie_complete(struct virt_dma_desc *vd)
/**
* vchan_cyclic_callback - report the completion of a period
- * vd: virtual descriptor
+ * @vd: virtual descriptor
*/
static inline void vchan_cyclic_callback(struct virt_dma_desc *vd)
{
@@ -109,7 +109,7 @@ static inline void vchan_cyclic_callback(struct virt_dma_desc *vd)
/**
* vchan_next_desc - peek at the next descriptor to be processed
- * vc: virtual channel to obtain descriptor from
+ * @vc: virtual channel to obtain descriptor from
*
* vc.lock must be held by caller
*/
@@ -123,8 +123,8 @@ static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc)
/**
* vchan_get_all_descriptors - obtain all submitted and issued descriptors
- * vc: virtual channel to get descriptors from
- * head: list of descriptors found
+ * @vc: virtual channel to get descriptors from
+ * @head: list of descriptors found
*
* vc.lock must be held by caller
*
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index 8d57b1b12e41..9dfa2b0fa5da 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -547,14 +547,12 @@ static struct xgene_dma_desc_sw *xgene_dma_alloc_descriptor(
struct xgene_dma_desc_sw *desc;
dma_addr_t phys;
- desc = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &phys);
+ desc = dma_pool_zalloc(chan->desc_pool, GFP_NOWAIT, &phys);
if (!desc) {
chan_err(chan, "Failed to allocate LDs\n");
return NULL;
}
- memset(desc, 0, sizeof(*desc));
-
INIT_LIST_HEAD(&desc->tx_list);
desc->tx.phys = phys;
desc->tx.tx_submit = xgene_dma_tx_submit;
@@ -894,60 +892,6 @@ static void xgene_dma_free_chan_resources(struct dma_chan *dchan)
chan->desc_pool = NULL;
}
-static struct dma_async_tx_descriptor *xgene_dma_prep_memcpy(
- struct dma_chan *dchan, dma_addr_t dst, dma_addr_t src,
- size_t len, unsigned long flags)
-{
- struct xgene_dma_desc_sw *first = NULL, *new;
- struct xgene_dma_chan *chan;
- size_t copy;
-
- if (unlikely(!dchan || !len))
- return NULL;
-
- chan = to_dma_chan(dchan);
-
- do {
- /* Allocate the link descriptor from DMA pool */
- new = xgene_dma_alloc_descriptor(chan);
- if (!new)
- goto fail;
-
- /* Create the largest transaction possible */
- copy = min_t(size_t, len, XGENE_DMA_MAX_64B_DESC_BYTE_CNT);
-
- /* Prepare DMA descriptor */
- xgene_dma_prep_cpy_desc(chan, new, dst, src, copy);
-
- if (!first)
- first = new;
-
- new->tx.cookie = 0;
- async_tx_ack(&new->tx);
-
- /* Update metadata */
- len -= copy;
- dst += copy;
- src += copy;
-
- /* Insert the link descriptor to the LD ring */
- list_add_tail(&new->node, &first->tx_list);
- } while (len);
-
- new->tx.flags = flags; /* client is in control of this ack */
- new->tx.cookie = -EBUSY;
- list_splice(&first->tx_list, &new->tx_list);
-
- return &new->tx;
-
-fail:
- if (!first)
- return NULL;
-
- xgene_dma_free_desc_list(chan, &first->tx_list);
- return NULL;
-}
-
static struct dma_async_tx_descriptor *xgene_dma_prep_sg(
struct dma_chan *dchan, struct scatterlist *dst_sg,
u32 dst_nents, struct scatterlist *src_sg,
@@ -1707,7 +1651,6 @@ static void xgene_dma_set_caps(struct xgene_dma_chan *chan,
dma_cap_zero(dma_dev->cap_mask);
/* Set DMA device capability */
- dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
dma_cap_set(DMA_SG, dma_dev->cap_mask);
/* Basically here, the X-Gene SoC DMA engine channel 0 supports XOR
@@ -1734,7 +1677,6 @@ static void xgene_dma_set_caps(struct xgene_dma_chan *chan,
dma_dev->device_free_chan_resources = xgene_dma_free_chan_resources;
dma_dev->device_issue_pending = xgene_dma_issue_pending;
dma_dev->device_tx_status = xgene_dma_tx_status;
- dma_dev->device_prep_dma_memcpy = xgene_dma_prep_memcpy;
dma_dev->device_prep_dma_sg = xgene_dma_prep_sg;
if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
@@ -1787,8 +1729,7 @@ static int xgene_dma_async_register(struct xgene_dma *pdma, int id)
/* DMA capability info */
dev_info(pdma->dev,
- "%s: CAPABILITY ( %s%s%s%s)\n", dma_chan_name(&chan->dma_chan),
- dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "MEMCPY " : "",
+ "%s: CAPABILITY ( %s%s%s)\n", dma_chan_name(&chan->dma_chan),
dma_has_cap(DMA_SG, dma_dev->cap_mask) ? "SGCPY " : "",
dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "XOR " : "",
dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "PQ " : "");
diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index d8434d465885..6f4b5017ca3b 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -1349,6 +1349,7 @@ static const struct of_device_id xilinx_vdma_of_ids[] = {
{ .compatible = "xlnx,axi-vdma-1.00.a",},
{}
};
+MODULE_DEVICE_TABLE(of, xilinx_vdma_of_ids);
static struct platform_driver xilinx_vdma_driver = {
.driver = {
diff --git a/drivers/dma/zx296702_dma.c b/drivers/dma/zx296702_dma.c
index c017fcd8e07c..245d759d5ffc 100644
--- a/drivers/dma/zx296702_dma.c
+++ b/drivers/dma/zx296702_dma.c
@@ -441,7 +441,7 @@ static struct zx_dma_desc_sw *zx_alloc_desc_resource(int num,
kfree(ds);
return NULL;
}
- memset(ds->desc_hw, sizeof(struct zx_desc_hw) * num, 0);
+ memset(ds->desc_hw, 0, sizeof(struct zx_desc_hw) * num);
ds->desc_num = num;
return ds;
}
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ae3c5f3ce405..dbf53e08bdd1 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -12,6 +12,8 @@ obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o
edac_core-y += edac_module.o edac_device_sysfs.o
+edac_core-$(CONFIG_EDAC_DEBUG) += debugfs.o
+
ifdef CONFIG_PCI
edac_core-y += edac_pci.o edac_pci_sysfs.o
endif
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 23ef0917483c..929640981d8a 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -51,11 +51,9 @@ static const struct altr_sdram_prv_data c5_data = {
.ecc_irq_clr_mask = (CV_DRAMINTR_INTRCLR | CV_DRAMINTR_INTREN),
.ecc_cnt_rst_offset = CV_DRAMINTR_OFST,
.ecc_cnt_rst_mask = CV_DRAMINTR_INTRCLR,
-#ifdef CONFIG_EDAC_DEBUG
.ce_ue_trgr_offset = CV_CTLCFG_OFST,
.ce_set_mask = CV_CTLCFG_GEN_SB_ERR,
.ue_set_mask = CV_CTLCFG_GEN_DB_ERR,
-#endif
};
static const struct altr_sdram_prv_data a10_data = {
@@ -72,11 +70,9 @@ static const struct altr_sdram_prv_data a10_data = {
.ecc_irq_clr_mask = (A10_INTSTAT_SBEERR | A10_INTSTAT_DBEERR),
.ecc_cnt_rst_offset = A10_ECCCTRL1_OFST,
.ecc_cnt_rst_mask = A10_ECC_CNT_RESET_MASK,
-#ifdef CONFIG_EDAC_DEBUG
.ce_ue_trgr_offset = A10_DIAGINTTEST_OFST,
.ce_set_mask = A10_DIAGINT_TSERRA_MASK,
.ue_set_mask = A10_DIAGINT_TDERRA_MASK,
-#endif
};
static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id)
@@ -116,7 +112,6 @@ static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id)
return IRQ_NONE;
}
-#ifdef CONFIG_EDAC_DEBUG
static ssize_t altr_sdr_mc_err_inject_write(struct file *file,
const char __user *data,
size_t count, loff_t *ppos)
@@ -191,14 +186,15 @@ static const struct file_operations altr_sdr_mc_debug_inject_fops = {
static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
{
- if (mci->debugfs)
- debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
- &altr_sdr_mc_debug_inject_fops);
+ if (!IS_ENABLED(CONFIG_EDAC_DEBUG))
+ return;
+
+ if (!mci->debugfs)
+ return;
+
+ edac_debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
+ &altr_sdr_mc_debug_inject_fops);
}
-#else
-static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
-{}
-#endif
/* Get total memory size from Open Firmware DTB */
static unsigned long get_total_mem(void)
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h
index 7b64dc7c4eb7..953077d3e4f3 100644
--- a/drivers/edac/altera_edac.h
+++ b/drivers/edac/altera_edac.h
@@ -30,8 +30,7 @@
#define CV_CTLCFG_GEN_SB_ERR 0x2000
#define CV_CTLCFG_GEN_DB_ERR 0x4000
-#define CV_CTLCFG_ECC_AUTO_EN (CV_CTLCFG_ECC_EN | \
- CV_CTLCFG_ECC_CORR_EN)
+#define CV_CTLCFG_ECC_AUTO_EN (CV_CTLCFG_ECC_EN)
/* SDRAM Controller Address Width Register */
#define CV_DRAMADDRW_OFST 0x2C
@@ -181,13 +180,11 @@ struct altr_sdram_prv_data {
int ecc_irq_clr_mask;
int ecc_cnt_rst_offset;
int ecc_cnt_rst_mask;
-#ifdef CONFIG_EDAC_DEBUG
struct edac_dev_sysfs_attribute *eccmgr_sysfs_attr;
int ecc_enable_mask;
int ce_set_mask;
int ue_set_mask;
int ce_ue_trgr_offset;
-#endif
};
/* Altera SDRAM Memory Controller data */
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 73aea40a9c89..9eee13ef83a5 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -173,7 +173,7 @@ static inline int amd64_read_dct_pci_cfg(struct amd64_pvt *pvt, u8 dct,
* scan the scrub rate mapping table for a close or matching bandwidth value to
* issue. If requested is too big, then use last maximum value found.
*/
-static int __set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
+static int __set_scrub_rate(struct amd64_pvt *pvt, u32 new_bw, u32 min_rate)
{
u32 scrubval;
int i;
@@ -201,7 +201,14 @@ static int __set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
scrubval = scrubrates[i].scrubval;
- pci_write_bits32(ctl, SCRCTRL, scrubval, 0x001F);
+ if (pvt->fam == 0x15 && pvt->model == 0x60) {
+ f15h_select_dct(pvt, 0);
+ pci_write_bits32(pvt->F2, F15H_M60H_SCRCTRL, scrubval, 0x001F);
+ f15h_select_dct(pvt, 1);
+ pci_write_bits32(pvt->F2, F15H_M60H_SCRCTRL, scrubval, 0x001F);
+ } else {
+ pci_write_bits32(pvt->F3, SCRCTRL, scrubval, 0x001F);
+ }
if (scrubval)
return scrubrates[i].bandwidth;
@@ -217,11 +224,15 @@ static int set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
if (pvt->fam == 0xf)
min_scrubrate = 0x0;
- /* Erratum #505 */
- if (pvt->fam == 0x15 && pvt->model < 0x10)
- f15h_select_dct(pvt, 0);
+ if (pvt->fam == 0x15) {
+ /* Erratum #505 */
+ if (pvt->model < 0x10)
+ f15h_select_dct(pvt, 0);
- return __set_scrub_rate(pvt->F3, bw, min_scrubrate);
+ if (pvt->model == 0x60)
+ min_scrubrate = 0x6;
+ }
+ return __set_scrub_rate(pvt, bw, min_scrubrate);
}
static int get_scrub_rate(struct mem_ctl_info *mci)
@@ -230,11 +241,15 @@ static int get_scrub_rate(struct mem_ctl_info *mci)
u32 scrubval = 0;
int i, retval = -EINVAL;
- /* Erratum #505 */
- if (pvt->fam == 0x15 && pvt->model < 0x10)
- f15h_select_dct(pvt, 0);
+ if (pvt->fam == 0x15) {
+ /* Erratum #505 */
+ if (pvt->model < 0x10)
+ f15h_select_dct(pvt, 0);
- amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
+ if (pvt->model == 0x60)
+ amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval);
+ } else
+ amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
scrubval = scrubval & 0x001F;
@@ -2770,7 +2785,7 @@ static int init_one_instance(struct pci_dev *F2)
struct mem_ctl_info *mci = NULL;
struct edac_mc_layer layers[2];
int err = 0, ret;
- u16 nid = amd_get_node_id(F2);
+ u16 nid = amd_pci_dev_to_node_id(F2);
ret = -ENOMEM;
pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
@@ -2860,7 +2875,7 @@ err_ret:
static int probe_one_instance(struct pci_dev *pdev,
const struct pci_device_id *mc_type)
{
- u16 nid = amd_get_node_id(pdev);
+ u16 nid = amd_pci_dev_to_node_id(pdev);
struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
struct ecc_settings *s;
int ret = 0;
@@ -2910,7 +2925,7 @@ static void remove_one_instance(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
struct amd64_pvt *pvt;
- u16 nid = amd_get_node_id(pdev);
+ u16 nid = amd_pci_dev_to_node_id(pdev);
struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
struct ecc_settings *s = ecc_stngs[nid];
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 4bdec752d330..c0f248f3aaf9 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -2,64 +2,10 @@
* AMD64 class Memory Controller kernel module
*
* Copyright (c) 2009 SoftwareBitMaker.
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * Copyright (c) 2009-15 Advanced Micro Devices, Inc.
*
* This file may be distributed under the terms of the
* GNU General Public License.
- *
- * Originally Written by Thayne Harbaugh
- *
- * Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>:
- * - K8 CPU Revision D and greater support
- *
- * Changes by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>:
- * - Module largely rewritten, with new (and hopefully correct)
- * code for dealing with node and chip select interleaving,
- * various code cleanup, and bug fixes
- * - Added support for memory hoisting using DRAM hole address
- * register
- *
- * Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>:
- * -K8 Rev (1207) revision support added, required Revision
- * specific mini-driver code to support Rev F as well as
- * prior revisions
- *
- * Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>:
- * -Family 10h revision support added. New PCI Device IDs,
- * indicating new changes. Actual registers modified
- * were slight, less than the Rev E to Rev F transition
- * but changing the PCI Device ID was the proper thing to
- * do, as it provides for almost automactic family
- * detection. The mods to Rev F required more family
- * information detection.
- *
- * Changes/Fixes by Borislav Petkov <bp@alien8.de>:
- * - misc fixes and code cleanups
- *
- * This module is based on the following documents
- * (available from http://www.amd.com/):
- *
- * Title: BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD
- * Opteron Processors
- * AMD publication #: 26094
- *` Revision: 3.26
- *
- * Title: BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh
- * Processors
- * AMD publication #: 32559
- * Revision: 3.00
- * Issue Date: May 2006
- *
- * Title: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h
- * Processors
- * AMD publication #: 31116
- * Revision: 3.00
- * Issue Date: September 07, 2007
- *
- * Sections in the first 2 documents are no longer in sync with each other.
- * The Family 10h BKDG was totally re-written from scratch with a new
- * presentation model.
- * Therefore, comments that refer to a Document section might be off.
*/
#include <linux/module.h>
@@ -255,6 +201,8 @@
#define DCT_SEL_HI 0x114
+#define F15H_M60H_SCRCTRL 0x1C8
+
/*
* Function 3 - Misc Control
*/
diff --git a/drivers/edac/debugfs.c b/drivers/edac/debugfs.c
new file mode 100644
index 000000000000..54d2f668cb0a
--- /dev/null
+++ b/drivers/edac/debugfs.c
@@ -0,0 +1,163 @@
+#include "edac_module.h"
+
+static struct dentry *edac_debugfs;
+
+static ssize_t edac_fake_inject_write(struct file *file,
+ const char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct device *dev = file->private_data;
+ struct mem_ctl_info *mci = to_mci(dev);
+ static enum hw_event_mc_err_type type;
+ u16 errcount = mci->fake_inject_count;
+
+ if (!errcount)
+ errcount = 1;
+
+ type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED
+ : HW_EVENT_ERR_CORRECTED;
+
+ printk(KERN_DEBUG
+ "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n",
+ errcount,
+ (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE",
+ errcount > 1 ? "s" : "",
+ mci->fake_inject_layer[0],
+ mci->fake_inject_layer[1],
+ mci->fake_inject_layer[2]
+ );
+ edac_mc_handle_error(type, mci, errcount, 0, 0, 0,
+ mci->fake_inject_layer[0],
+ mci->fake_inject_layer[1],
+ mci->fake_inject_layer[2],
+ "FAKE ERROR", "for EDAC testing only");
+
+ return count;
+}
+
+static const struct file_operations debug_fake_inject_fops = {
+ .open = simple_open,
+ .write = edac_fake_inject_write,
+ .llseek = generic_file_llseek,
+};
+
+int __init edac_debugfs_init(void)
+{
+ edac_debugfs = debugfs_create_dir("edac", NULL);
+ if (IS_ERR(edac_debugfs)) {
+ edac_debugfs = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void edac_debugfs_exit(void)
+{
+ debugfs_remove(edac_debugfs);
+}
+
+int edac_create_debugfs_nodes(struct mem_ctl_info *mci)
+{
+ struct dentry *d, *parent;
+ char name[80];
+ int i;
+
+ if (!edac_debugfs)
+ return -ENODEV;
+
+ d = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs);
+ if (!d)
+ return -ENOMEM;
+ parent = d;
+
+ for (i = 0; i < mci->n_layers; i++) {
+ sprintf(name, "fake_inject_%s",
+ edac_layer_name[mci->layers[i].type]);
+ d = debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent,
+ &mci->fake_inject_layer[i]);
+ if (!d)
+ goto nomem;
+ }
+
+ d = debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent,
+ &mci->fake_inject_ue);
+ if (!d)
+ goto nomem;
+
+ d = debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent,
+ &mci->fake_inject_count);
+ if (!d)
+ goto nomem;
+
+ d = debugfs_create_file("fake_inject", S_IWUSR, parent,
+ &mci->dev,
+ &debug_fake_inject_fops);
+ if (!d)
+ goto nomem;
+
+ mci->debugfs = parent;
+ return 0;
+nomem:
+ edac_debugfs_remove_recursive(mci->debugfs);
+ return -ENOMEM;
+}
+
+/* Create a toplevel dir under EDAC's debugfs hierarchy */
+struct dentry *edac_debugfs_create_dir(const char *dirname)
+{
+ if (!edac_debugfs)
+ return NULL;
+
+ return debugfs_create_dir(dirname, edac_debugfs);
+}
+EXPORT_SYMBOL_GPL(edac_debugfs_create_dir);
+
+/* Create a toplevel dir under EDAC's debugfs hierarchy with parent @parent */
+struct dentry *
+edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent)
+{
+ return debugfs_create_dir(dirname, parent);
+}
+EXPORT_SYMBOL_GPL(edac_debugfs_create_dir_at);
+
+/*
+ * Create a file under EDAC's hierarchy or a sub-hierarchy:
+ *
+ * @name: file name
+ * @mode: file permissions
+ * @parent: parent dentry. If NULL, it becomes the toplevel EDAC dir
+ * @data: private data of caller
+ * @fops: file operations of this file
+ */
+struct dentry *
+edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
+ void *data, const struct file_operations *fops)
+{
+ if (!parent)
+ parent = edac_debugfs;
+
+ return debugfs_create_file(name, mode, parent, data, fops);
+}
+EXPORT_SYMBOL_GPL(edac_debugfs_create_file);
+
+/* Wrapper for debugfs_create_x8() */
+struct dentry *edac_debugfs_create_x8(const char *name, umode_t mode,
+ struct dentry *parent, u8 *value)
+{
+ if (!parent)
+ parent = edac_debugfs;
+
+ return debugfs_create_x8(name, mode, parent, value);
+}
+EXPORT_SYMBOL_GPL(edac_debugfs_create_x8);
+
+/* Wrapper for debugfs_create_x16() */
+struct dentry *edac_debugfs_create_x16(const char *name, umode_t mode,
+ struct dentry *parent, u16 *value)
+{
+ if (!parent)
+ parent = edac_debugfs;
+
+ return debugfs_create_x16(name, mode, parent, value);
+}
+EXPORT_SYMBOL_GPL(edac_debugfs_create_x16);
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index ad42587c3f4d..4861542163d7 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -94,6 +94,8 @@ do { \
#define edac_dev_name(dev) (dev)->dev_name
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
/*
* The following are the structures to provide for a generic
* or abstract 'edac_device'. This set of structures and the
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 943ed8cf71b9..77ecd6a4179a 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1302,7 +1302,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
grain_bits = fls_long(e->grain) + 1;
trace_mc_event(type, e->msg, e->label, e->error_count,
mci->mc_idx, e->top_layer, e->mid_layer, e->low_layer,
- PAGES_TO_MiB(e->page_frame_number) | e->offset_in_page,
+ (e->page_frame_number << PAGE_SHIFT) | e->offset_in_page,
grain_bits, e->syndrome, e->other_detail);
edac_raw_mc_handle_error(type, mci, e);
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 33df7d93c857..a75acea0f674 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -229,7 +229,7 @@ static ssize_t channel_dimm_label_show(struct device *dev,
if (!rank->dimm->label[0])
return 0;
- return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
+ return snprintf(data, sizeof(rank->dimm->label) + 1, "%s\n",
rank->dimm->label);
}
@@ -240,14 +240,21 @@ static ssize_t channel_dimm_label_store(struct device *dev,
struct csrow_info *csrow = to_csrow(dev);
unsigned chan = to_channel(mattr);
struct rank_info *rank = csrow->channels[chan];
+ size_t copy_count = count;
- ssize_t max_size = 0;
+ if (count == 0)
+ return -EINVAL;
+
+ if (data[count - 1] == '\0' || data[count - 1] == '\n')
+ copy_count -= 1;
+
+ if (copy_count == 0 || copy_count >= sizeof(rank->dimm->label))
+ return -EINVAL;
- max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
- strncpy(rank->dimm->label, data, max_size);
- rank->dimm->label[max_size] = '\0';
+ strncpy(rank->dimm->label, data, copy_count);
+ rank->dimm->label[copy_count] = '\0';
- return max_size;
+ return count;
}
/* show function for dynamic chX_ce_count attribute */
@@ -485,7 +492,7 @@ static ssize_t dimmdev_label_show(struct device *dev,
if (!dimm->label[0])
return 0;
- return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", dimm->label);
+ return snprintf(data, sizeof(dimm->label) + 1, "%s\n", dimm->label);
}
static ssize_t dimmdev_label_store(struct device *dev,
@@ -494,14 +501,21 @@ static ssize_t dimmdev_label_store(struct device *dev,
size_t count)
{
struct dimm_info *dimm = to_dimm(dev);
+ size_t copy_count = count;
- ssize_t max_size = 0;
+ if (count == 0)
+ return -EINVAL;
- max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
- strncpy(dimm->label, data, max_size);
- dimm->label[max_size] = '\0';
+ if (data[count - 1] == '\0' || data[count - 1] == '\n')
+ copy_count -= 1;
- return max_size;
+ if (copy_count == 0 || copy_count >= sizeof(dimm->label))
+ return -EINVAL;
+
+ strncpy(dimm->label, data, copy_count);
+ dimm->label[copy_count] = '\0';
+
+ return count;
}
static ssize_t dimmdev_size_show(struct device *dev,
@@ -785,47 +799,6 @@ static ssize_t mci_max_location_show(struct device *dev,
return p - data;
}
-#ifdef CONFIG_EDAC_DEBUG
-static ssize_t edac_fake_inject_write(struct file *file,
- const char __user *data,
- size_t count, loff_t *ppos)
-{
- struct device *dev = file->private_data;
- struct mem_ctl_info *mci = to_mci(dev);
- static enum hw_event_mc_err_type type;
- u16 errcount = mci->fake_inject_count;
-
- if (!errcount)
- errcount = 1;
-
- type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED
- : HW_EVENT_ERR_CORRECTED;
-
- printk(KERN_DEBUG
- "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n",
- errcount,
- (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE",
- errcount > 1 ? "s" : "",
- mci->fake_inject_layer[0],
- mci->fake_inject_layer[1],
- mci->fake_inject_layer[2]
- );
- edac_mc_handle_error(type, mci, errcount, 0, 0, 0,
- mci->fake_inject_layer[0],
- mci->fake_inject_layer[1],
- mci->fake_inject_layer[2],
- "FAKE ERROR", "for EDAC testing only");
-
- return count;
-}
-
-static const struct file_operations debug_fake_inject_fops = {
- .open = simple_open,
- .write = edac_fake_inject_write,
- .llseek = generic_file_llseek,
-};
-#endif
-
/* default Control file */
static DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store);
@@ -896,71 +869,6 @@ static struct device_type mci_attr_type = {
.release = mci_attr_release,
};
-#ifdef CONFIG_EDAC_DEBUG
-static struct dentry *edac_debugfs;
-
-int __init edac_debugfs_init(void)
-{
- edac_debugfs = debugfs_create_dir("edac", NULL);
- if (IS_ERR(edac_debugfs)) {
- edac_debugfs = NULL;
- return -ENOMEM;
- }
- return 0;
-}
-
-void edac_debugfs_exit(void)
-{
- debugfs_remove(edac_debugfs);
-}
-
-static int edac_create_debug_nodes(struct mem_ctl_info *mci)
-{
- struct dentry *d, *parent;
- char name[80];
- int i;
-
- if (!edac_debugfs)
- return -ENODEV;
-
- d = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs);
- if (!d)
- return -ENOMEM;
- parent = d;
-
- for (i = 0; i < mci->n_layers; i++) {
- sprintf(name, "fake_inject_%s",
- edac_layer_name[mci->layers[i].type]);
- d = debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent,
- &mci->fake_inject_layer[i]);
- if (!d)
- goto nomem;
- }
-
- d = debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent,
- &mci->fake_inject_ue);
- if (!d)
- goto nomem;
-
- d = debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent,
- &mci->fake_inject_count);
- if (!d)
- goto nomem;
-
- d = debugfs_create_file("fake_inject", S_IWUSR, parent,
- &mci->dev,
- &debug_fake_inject_fops);
- if (!d)
- goto nomem;
-
- mci->debugfs = parent;
- return 0;
-nomem:
- debugfs_remove(mci->debugfs);
- return -ENOMEM;
-}
-#endif
-
/*
* Create a new Memory Controller kobject instance,
* mc<id> under the 'mc' directory
@@ -1039,9 +947,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
goto fail_unregister_dimm;
#endif
-#ifdef CONFIG_EDAC_DEBUG
- edac_create_debug_nodes(mci);
-#endif
+ edac_create_debugfs_nodes(mci);
return 0;
fail_unregister_dimm:
@@ -1070,7 +976,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
edac_dbg(0, "\n");
#ifdef CONFIG_EDAC_DEBUG
- debugfs_remove(mci->debugfs);
+ edac_debugfs_remove_recursive(mci->debugfs);
#endif
#ifdef CONFIG_EDAC_LEGACY_SYSFS
edac_delete_csrow_objects(mci);
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 26ecc52e073d..b95a48fc723d 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -60,15 +60,39 @@ extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
/*
* EDAC debugfs functions
*/
+
+#define edac_debugfs_remove_recursive debugfs_remove_recursive
+#define edac_debugfs_remove debugfs_remove
#ifdef CONFIG_EDAC_DEBUG
int edac_debugfs_init(void);
void edac_debugfs_exit(void);
+int edac_create_debugfs_nodes(struct mem_ctl_info *mci);
+struct dentry *edac_debugfs_create_dir(const char *dirname);
+struct dentry *
+edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent);
+struct dentry *
+edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
+ void *data, const struct file_operations *fops);
+struct dentry *
+edac_debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value);
+struct dentry *
+edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value);
#else
-static inline int edac_debugfs_init(void)
-{
- return -ENODEV;
-}
-static inline void edac_debugfs_exit(void) {}
+static inline int edac_debugfs_init(void) { return -ENODEV; }
+static inline void edac_debugfs_exit(void) { }
+static inline int edac_create_debugfs_nodes(struct mem_ctl_info *mci) { return 0; }
+static inline struct dentry *edac_debugfs_create_dir(const char *dirname) { return NULL; }
+static inline struct dentry *
+edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent) { return NULL; }
+static inline struct dentry *
+edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
+ void *data, const struct file_operations *fops) { return NULL; }
+static inline struct dentry *
+edac_debugfs_create_x8(const char *name, umode_t mode,
+ struct dentry *parent, u8 *value) { return NULL; }
+static inline struct dentry *
+edac_debugfs_create_x16(const char *name, umode_t mode,
+ struct dentry *parent, u16 *value) { return NULL; }
#endif
/*
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index b24681998740..e3fa4390f846 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -66,26 +66,6 @@ struct ghes_edac_dimm_fill {
unsigned count;
};
-char *memory_type[] = {
- [MEM_EMPTY] = "EMPTY",
- [MEM_RESERVED] = "RESERVED",
- [MEM_UNKNOWN] = "UNKNOWN",
- [MEM_FPM] = "FPM",
- [MEM_EDO] = "EDO",
- [MEM_BEDO] = "BEDO",
- [MEM_SDR] = "SDR",
- [MEM_RDR] = "RDR",
- [MEM_DDR] = "DDR",
- [MEM_RDDR] = "RDDR",
- [MEM_RMBS] = "RMBS",
- [MEM_DDR2] = "DDR2",
- [MEM_FB_DDR2] = "FB_DDR2",
- [MEM_RDDR2] = "RDDR2",
- [MEM_XDR] = "XDR",
- [MEM_DDR3] = "DDR3",
- [MEM_RDDR3] = "RDDR3",
-};
-
static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg)
{
int *num_dimm = arg;
@@ -173,7 +153,7 @@ static void ghes_edac_dmidecode(const struct dmi_header *dh, void *arg)
if (dimm->nr_pages) {
edac_dbg(1, "DIMM%i: %s size = %d MB%s\n",
- dimm_fill->count, memory_type[dimm->mtype],
+ dimm_fill->count, edac_mem_types[dimm->mtype],
PAGES_TO_MiB(dimm->nr_pages),
(dimm->edac_mode != EDAC_NONE) ? "(ECC)" : "");
edac_dbg(2, "\ttype %d, detail 0x%02x, width %d(total %d)\n",
@@ -417,7 +397,7 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
"APEI location: %s %s", e->location, e->other_detail);
trace_mc_event(type, e->msg, e->label, e->error_count,
mci->mc_idx, e->top_layer, e->mid_layer, e->low_layer,
- PAGES_TO_MiB(e->page_frame_number) | e->offset_in_page,
+ (e->page_frame_number << PAGE_SHIFT) | e->offset_in_page,
grain_bits, e->syndrome, pvt->detail_location);
/* Report the error via EDAC API */
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c
index 4ad062b0ef26..1f453382258a 100644
--- a/drivers/edac/i3200_edac.c
+++ b/drivers/edac/i3200_edac.c
@@ -15,7 +15,7 @@
#include <linux/io.h>
#include "edac_core.h"
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#define I3200_REVISION "1.1"
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index e9f8a393915a..40917775dca1 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -30,6 +30,7 @@
#include <linux/debugfs.h>
#include "edac_core.h"
+#include "edac_module.h"
/* register addresses */
@@ -966,25 +967,25 @@ static int i5100_setup_debugfs(struct mem_ctl_info *mci)
if (!i5100_debugfs)
return -ENODEV;
- priv->debugfs = debugfs_create_dir(mci->bus->name, i5100_debugfs);
+ priv->debugfs = edac_debugfs_create_dir_at(mci->bus->name, i5100_debugfs);
if (!priv->debugfs)
return -ENOMEM;
- debugfs_create_x8("inject_channel", S_IRUGO | S_IWUSR, priv->debugfs,
- &priv->inject_channel);
- debugfs_create_x8("inject_hlinesel", S_IRUGO | S_IWUSR, priv->debugfs,
- &priv->inject_hlinesel);
- debugfs_create_x8("inject_deviceptr1", S_IRUGO | S_IWUSR, priv->debugfs,
- &priv->inject_deviceptr1);
- debugfs_create_x8("inject_deviceptr2", S_IRUGO | S_IWUSR, priv->debugfs,
- &priv->inject_deviceptr2);
- debugfs_create_x16("inject_eccmask1", S_IRUGO | S_IWUSR, priv->debugfs,
- &priv->inject_eccmask1);
- debugfs_create_x16("inject_eccmask2", S_IRUGO | S_IWUSR, priv->debugfs,
- &priv->inject_eccmask2);
- debugfs_create_file("inject_enable", S_IWUSR, priv->debugfs,
- &mci->dev, &i5100_inject_enable_fops);
+ edac_debugfs_create_x8("inject_channel", S_IRUGO | S_IWUSR, priv->debugfs,
+ &priv->inject_channel);
+ edac_debugfs_create_x8("inject_hlinesel", S_IRUGO | S_IWUSR, priv->debugfs,
+ &priv->inject_hlinesel);
+ edac_debugfs_create_x8("inject_deviceptr1", S_IRUGO | S_IWUSR, priv->debugfs,
+ &priv->inject_deviceptr1);
+ edac_debugfs_create_x8("inject_deviceptr2", S_IRUGO | S_IWUSR, priv->debugfs,
+ &priv->inject_deviceptr2);
+ edac_debugfs_create_x16("inject_eccmask1", S_IRUGO | S_IWUSR, priv->debugfs,
+ &priv->inject_eccmask1);
+ edac_debugfs_create_x16("inject_eccmask2", S_IRUGO | S_IWUSR, priv->debugfs,
+ &priv->inject_eccmask2);
+ edac_debugfs_create_file("inject_enable", S_IWUSR, priv->debugfs,
+ &mci->dev, &i5100_inject_enable_fops);
return 0;
@@ -1189,7 +1190,7 @@ static void i5100_remove_one(struct pci_dev *pdev)
priv = mci->pvt_info;
- debugfs_remove_recursive(priv->debugfs);
+ edac_debugfs_remove_recursive(priv->debugfs);
priv->scrub_enable = 0;
cancel_delayed_work_sync(&(priv->i5100_scrubbing));
@@ -1223,7 +1224,7 @@ static int __init i5100_init(void)
{
int pci_rc;
- i5100_debugfs = debugfs_create_dir("i5100_edac", NULL);
+ i5100_debugfs = edac_debugfs_create_dir_at("i5100_edac", NULL);
pci_rc = pci_register_driver(&i5100_driver);
return (pci_rc < 0) ? pci_rc : 0;
@@ -1231,7 +1232,7 @@ static int __init i5100_init(void)
static void __exit i5100_exit(void)
{
- debugfs_remove(i5100_debugfs);
+ edac_debugfs_remove(i5100_debugfs);
pci_unregister_driver(&i5100_driver);
}
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
index a981dc6fd88e..18d77ace4813 100644
--- a/drivers/edac/ie31200_edac.c
+++ b/drivers/edac/ie31200_edac.c
@@ -39,7 +39,7 @@
#include <linux/pci_ids.h>
#include <linux/edac.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include "edac_core.h"
#define IE31200_REVISION "1.0"
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c
index 711d8ad74f11..d3a64ba61fa3 100644
--- a/drivers/edac/ppc4xx_edac.c
+++ b/drivers/edac/ppc4xx_edac.c
@@ -199,6 +199,7 @@ static const struct of_device_id ppc4xx_edac_match[] = {
},
{ }
};
+MODULE_DEVICE_TABLE(of, ppc4xx_edac_match);
static struct platform_driver ppc4xx_edac_driver = {
.probe = ppc4xx_edac_probe,
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index cf1268ddef0c..429309c62699 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -1688,6 +1688,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct pci_dev *pdev;
+ u8 saw_chan_mask = 0;
int i;
for (i = 0; i < sbridge_dev->n_devs; i++) {
@@ -1721,6 +1722,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
{
int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
pvt->pci_tad[id] = pdev;
+ saw_chan_mask |= 1 << id;
}
break;
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
@@ -1741,10 +1743,8 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
!pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta)
goto enodev;
- for (i = 0; i < NUM_CHANNELS; i++) {
- if (!pvt->pci_tad[i])
- goto enodev;
- }
+ if (saw_chan_mask != 0x0f)
+ goto enodev;
return 0;
enodev:
diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c
index 7c5cdc62f31c..314cf5cf268c 100644
--- a/drivers/edac/x38_edac.c
+++ b/drivers/edac/x38_edac.c
@@ -15,7 +15,7 @@
#include <linux/pci_ids.h>
#include <linux/edac.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include "edac_core.h"
#define X38_REVISION "1.1"
diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c
index ba06904af2e1..41f876414a18 100644
--- a/drivers/edac/xgene_edac.c
+++ b/drivers/edac/xgene_edac.c
@@ -29,6 +29,7 @@
#include <linux/regmap.h>
#include "edac_core.h"
+#include "edac_module.h"
#define EDAC_MOD_STR "xgene_edac"
@@ -62,10 +63,12 @@ struct xgene_edac {
struct regmap *efuse_map;
void __iomem *pcp_csr;
spinlock_t lock;
- struct dentry *dfs;
+ struct dentry *dfs;
struct list_head mcus;
struct list_head pmds;
+ struct list_head l3s;
+ struct list_head socs;
struct mutex mc_lock;
int mc_active_mask;
@@ -172,12 +175,12 @@ static void xgene_edac_mc_create_debugfs_node(struct mem_ctl_info *mci)
{
if (!IS_ENABLED(CONFIG_EDAC_DEBUG))
return;
-#ifdef CONFIG_EDAC_DEBUG
+
if (!mci->debugfs)
return;
- debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
- &xgene_edac_mc_debug_inject_fops);
-#endif
+
+ edac_debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
+ &xgene_edac_mc_debug_inject_fops);
}
static void xgene_edac_mc_check(struct mem_ctl_info *mci)
@@ -536,140 +539,134 @@ static void xgene_edac_pmd_l1_check(struct edac_device_ctl_info *edac_dev,
pg_f = ctx->pmd_csr + cpu_idx * CPU_CSR_STRIDE + CPU_MEMERR_CPU_PAGE;
val = readl(pg_f + MEMERR_CPU_ICFESR_PAGE_OFFSET);
- if (val) {
- dev_err(edac_dev->dev,
- "CPU%d L1 memory error ICF 0x%08X Way 0x%02X Index 0x%02X Info 0x%02X\n",
- ctx->pmd * MAX_CPU_PER_PMD + cpu_idx, val,
- MEMERR_CPU_ICFESR_ERRWAY_RD(val),
- MEMERR_CPU_ICFESR_ERRINDEX_RD(val),
- MEMERR_CPU_ICFESR_ERRINFO_RD(val));
- if (val & MEMERR_CPU_ICFESR_CERR_MASK)
- dev_err(edac_dev->dev,
- "One or more correctable error\n");
- if (val & MEMERR_CPU_ICFESR_MULTCERR_MASK)
- dev_err(edac_dev->dev, "Multiple correctable error\n");
- switch (MEMERR_CPU_ICFESR_ERRTYPE_RD(val)) {
- case 1:
- dev_err(edac_dev->dev, "L1 TLB multiple hit\n");
- break;
- case 2:
- dev_err(edac_dev->dev, "Way select multiple hit\n");
- break;
- case 3:
- dev_err(edac_dev->dev, "Physical tag parity error\n");
- break;
- case 4:
- case 5:
- dev_err(edac_dev->dev, "L1 data parity error\n");
- break;
- case 6:
- dev_err(edac_dev->dev, "L1 pre-decode parity error\n");
- break;
- }
+ if (!val)
+ goto chk_lsu;
+ dev_err(edac_dev->dev,
+ "CPU%d L1 memory error ICF 0x%08X Way 0x%02X Index 0x%02X Info 0x%02X\n",
+ ctx->pmd * MAX_CPU_PER_PMD + cpu_idx, val,
+ MEMERR_CPU_ICFESR_ERRWAY_RD(val),
+ MEMERR_CPU_ICFESR_ERRINDEX_RD(val),
+ MEMERR_CPU_ICFESR_ERRINFO_RD(val));
+ if (val & MEMERR_CPU_ICFESR_CERR_MASK)
+ dev_err(edac_dev->dev, "One or more correctable error\n");
+ if (val & MEMERR_CPU_ICFESR_MULTCERR_MASK)
+ dev_err(edac_dev->dev, "Multiple correctable error\n");
+ switch (MEMERR_CPU_ICFESR_ERRTYPE_RD(val)) {
+ case 1:
+ dev_err(edac_dev->dev, "L1 TLB multiple hit\n");
+ break;
+ case 2:
+ dev_err(edac_dev->dev, "Way select multiple hit\n");
+ break;
+ case 3:
+ dev_err(edac_dev->dev, "Physical tag parity error\n");
+ break;
+ case 4:
+ case 5:
+ dev_err(edac_dev->dev, "L1 data parity error\n");
+ break;
+ case 6:
+ dev_err(edac_dev->dev, "L1 pre-decode parity error\n");
+ break;
+ }
- /* Clear any HW errors */
- writel(val, pg_f + MEMERR_CPU_ICFESR_PAGE_OFFSET);
+ /* Clear any HW errors */
+ writel(val, pg_f + MEMERR_CPU_ICFESR_PAGE_OFFSET);
- if (val & (MEMERR_CPU_ICFESR_CERR_MASK |
- MEMERR_CPU_ICFESR_MULTCERR_MASK))
- edac_device_handle_ce(edac_dev, 0, 0,
- edac_dev->ctl_name);
- }
+ if (val & (MEMERR_CPU_ICFESR_CERR_MASK |
+ MEMERR_CPU_ICFESR_MULTCERR_MASK))
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+chk_lsu:
val = readl(pg_f + MEMERR_CPU_LSUESR_PAGE_OFFSET);
- if (val) {
+ if (!val)
+ goto chk_mmu;
+ dev_err(edac_dev->dev,
+ "CPU%d memory error LSU 0x%08X Way 0x%02X Index 0x%02X Info 0x%02X\n",
+ ctx->pmd * MAX_CPU_PER_PMD + cpu_idx, val,
+ MEMERR_CPU_LSUESR_ERRWAY_RD(val),
+ MEMERR_CPU_LSUESR_ERRINDEX_RD(val),
+ MEMERR_CPU_LSUESR_ERRINFO_RD(val));
+ if (val & MEMERR_CPU_LSUESR_CERR_MASK)
+ dev_err(edac_dev->dev, "One or more correctable error\n");
+ if (val & MEMERR_CPU_LSUESR_MULTCERR_MASK)
+ dev_err(edac_dev->dev, "Multiple correctable error\n");
+ switch (MEMERR_CPU_LSUESR_ERRTYPE_RD(val)) {
+ case 0:
+ dev_err(edac_dev->dev, "Load tag error\n");
+ break;
+ case 1:
+ dev_err(edac_dev->dev, "Load data error\n");
+ break;
+ case 2:
+ dev_err(edac_dev->dev, "WSL multihit error\n");
+ break;
+ case 3:
+ dev_err(edac_dev->dev, "Store tag error\n");
+ break;
+ case 4:
dev_err(edac_dev->dev,
- "CPU%d memory error LSU 0x%08X Way 0x%02X Index 0x%02X Info 0x%02X\n",
- ctx->pmd * MAX_CPU_PER_PMD + cpu_idx, val,
- MEMERR_CPU_LSUESR_ERRWAY_RD(val),
- MEMERR_CPU_LSUESR_ERRINDEX_RD(val),
- MEMERR_CPU_LSUESR_ERRINFO_RD(val));
- if (val & MEMERR_CPU_LSUESR_CERR_MASK)
- dev_err(edac_dev->dev,
- "One or more correctable error\n");
- if (val & MEMERR_CPU_LSUESR_MULTCERR_MASK)
- dev_err(edac_dev->dev, "Multiple correctable error\n");
- switch (MEMERR_CPU_LSUESR_ERRTYPE_RD(val)) {
- case 0:
- dev_err(edac_dev->dev, "Load tag error\n");
- break;
- case 1:
- dev_err(edac_dev->dev, "Load data error\n");
- break;
- case 2:
- dev_err(edac_dev->dev, "WSL multihit error\n");
- break;
- case 3:
- dev_err(edac_dev->dev, "Store tag error\n");
- break;
- case 4:
- dev_err(edac_dev->dev,
- "DTB multihit from load pipeline error\n");
- break;
- case 5:
- dev_err(edac_dev->dev,
- "DTB multihit from store pipeline error\n");
- break;
- }
+ "DTB multihit from load pipeline error\n");
+ break;
+ case 5:
+ dev_err(edac_dev->dev,
+ "DTB multihit from store pipeline error\n");
+ break;
+ }
- /* Clear any HW errors */
- writel(val, pg_f + MEMERR_CPU_LSUESR_PAGE_OFFSET);
+ /* Clear any HW errors */
+ writel(val, pg_f + MEMERR_CPU_LSUESR_PAGE_OFFSET);
- if (val & (MEMERR_CPU_LSUESR_CERR_MASK |
- MEMERR_CPU_LSUESR_MULTCERR_MASK))
- edac_device_handle_ce(edac_dev, 0, 0,
- edac_dev->ctl_name);
- }
+ if (val & (MEMERR_CPU_LSUESR_CERR_MASK |
+ MEMERR_CPU_LSUESR_MULTCERR_MASK))
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+chk_mmu:
val = readl(pg_f + MEMERR_CPU_MMUESR_PAGE_OFFSET);
- if (val) {
- dev_err(edac_dev->dev,
- "CPU%d memory error MMU 0x%08X Way 0x%02X Index 0x%02X Info 0x%02X %s\n",
- ctx->pmd * MAX_CPU_PER_PMD + cpu_idx, val,
- MEMERR_CPU_MMUESR_ERRWAY_RD(val),
- MEMERR_CPU_MMUESR_ERRINDEX_RD(val),
- MEMERR_CPU_MMUESR_ERRINFO_RD(val),
- val & MEMERR_CPU_MMUESR_ERRREQSTR_LSU_MASK ? "LSU" :
- "ICF");
- if (val & MEMERR_CPU_MMUESR_CERR_MASK)
- dev_err(edac_dev->dev,
- "One or more correctable error\n");
- if (val & MEMERR_CPU_MMUESR_MULTCERR_MASK)
- dev_err(edac_dev->dev, "Multiple correctable error\n");
- switch (MEMERR_CPU_MMUESR_ERRTYPE_RD(val)) {
- case 0:
- dev_err(edac_dev->dev, "Stage 1 UTB hit error\n");
- break;
- case 1:
- dev_err(edac_dev->dev, "Stage 1 UTB miss error\n");
- break;
- case 2:
- dev_err(edac_dev->dev, "Stage 1 UTB allocate error\n");
- break;
- case 3:
- dev_err(edac_dev->dev,
- "TMO operation single bank error\n");
- break;
- case 4:
- dev_err(edac_dev->dev, "Stage 2 UTB error\n");
- break;
- case 5:
- dev_err(edac_dev->dev, "Stage 2 UTB miss error\n");
- break;
- case 6:
- dev_err(edac_dev->dev, "Stage 2 UTB allocate error\n");
- break;
- case 7:
- dev_err(edac_dev->dev,
- "TMO operation multiple bank error\n");
- break;
- }
+ if (!val)
+ return;
+ dev_err(edac_dev->dev,
+ "CPU%d memory error MMU 0x%08X Way 0x%02X Index 0x%02X Info 0x%02X %s\n",
+ ctx->pmd * MAX_CPU_PER_PMD + cpu_idx, val,
+ MEMERR_CPU_MMUESR_ERRWAY_RD(val),
+ MEMERR_CPU_MMUESR_ERRINDEX_RD(val),
+ MEMERR_CPU_MMUESR_ERRINFO_RD(val),
+ val & MEMERR_CPU_MMUESR_ERRREQSTR_LSU_MASK ? "LSU" : "ICF");
+ if (val & MEMERR_CPU_MMUESR_CERR_MASK)
+ dev_err(edac_dev->dev, "One or more correctable error\n");
+ if (val & MEMERR_CPU_MMUESR_MULTCERR_MASK)
+ dev_err(edac_dev->dev, "Multiple correctable error\n");
+ switch (MEMERR_CPU_MMUESR_ERRTYPE_RD(val)) {
+ case 0:
+ dev_err(edac_dev->dev, "Stage 1 UTB hit error\n");
+ break;
+ case 1:
+ dev_err(edac_dev->dev, "Stage 1 UTB miss error\n");
+ break;
+ case 2:
+ dev_err(edac_dev->dev, "Stage 1 UTB allocate error\n");
+ break;
+ case 3:
+ dev_err(edac_dev->dev, "TMO operation single bank error\n");
+ break;
+ case 4:
+ dev_err(edac_dev->dev, "Stage 2 UTB error\n");
+ break;
+ case 5:
+ dev_err(edac_dev->dev, "Stage 2 UTB miss error\n");
+ break;
+ case 6:
+ dev_err(edac_dev->dev, "Stage 2 UTB allocate error\n");
+ break;
+ case 7:
+ dev_err(edac_dev->dev, "TMO operation multiple bank error\n");
+ break;
+ }
- /* Clear any HW errors */
- writel(val, pg_f + MEMERR_CPU_MMUESR_PAGE_OFFSET);
+ /* Clear any HW errors */
+ writel(val, pg_f + MEMERR_CPU_MMUESR_PAGE_OFFSET);
- edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
- }
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
}
static void xgene_edac_pmd_l2_check(struct edac_device_ctl_info *edac_dev)
@@ -684,60 +681,56 @@ static void xgene_edac_pmd_l2_check(struct edac_device_ctl_info *edac_dev)
/* Check L2 */
pg_e = ctx->pmd_csr + CPU_MEMERR_L2C_PAGE;
val = readl(pg_e + MEMERR_L2C_L2ESR_PAGE_OFFSET);
- if (val) {
- val_lo = readl(pg_e + MEMERR_L2C_L2EALR_PAGE_OFFSET);
- val_hi = readl(pg_e + MEMERR_L2C_L2EAHR_PAGE_OFFSET);
- dev_err(edac_dev->dev,
- "PMD%d memory error L2C L2ESR 0x%08X @ 0x%08X.%08X\n",
- ctx->pmd, val, val_hi, val_lo);
- dev_err(edac_dev->dev,
- "ErrSyndrome 0x%02X ErrWay 0x%02X ErrCpu %d ErrGroup 0x%02X ErrAction 0x%02X\n",
- MEMERR_L2C_L2ESR_ERRSYN_RD(val),
- MEMERR_L2C_L2ESR_ERRWAY_RD(val),
- MEMERR_L2C_L2ESR_ERRCPU_RD(val),
- MEMERR_L2C_L2ESR_ERRGROUP_RD(val),
- MEMERR_L2C_L2ESR_ERRACTION_RD(val));
-
- if (val & MEMERR_L2C_L2ESR_ERR_MASK)
- dev_err(edac_dev->dev,
- "One or more correctable error\n");
- if (val & MEMERR_L2C_L2ESR_MULTICERR_MASK)
- dev_err(edac_dev->dev, "Multiple correctable error\n");
- if (val & MEMERR_L2C_L2ESR_UCERR_MASK)
- dev_err(edac_dev->dev,
- "One or more uncorrectable error\n");
- if (val & MEMERR_L2C_L2ESR_MULTUCERR_MASK)
- dev_err(edac_dev->dev,
- "Multiple uncorrectable error\n");
-
- switch (MEMERR_L2C_L2ESR_ERRTYPE_RD(val)) {
- case 0:
- dev_err(edac_dev->dev, "Outbound SDB parity error\n");
- break;
- case 1:
- dev_err(edac_dev->dev, "Inbound SDB parity error\n");
- break;
- case 2:
- dev_err(edac_dev->dev, "Tag ECC error\n");
- break;
- case 3:
- dev_err(edac_dev->dev, "Data ECC error\n");
- break;
- }
+ if (!val)
+ goto chk_l2c;
+ val_lo = readl(pg_e + MEMERR_L2C_L2EALR_PAGE_OFFSET);
+ val_hi = readl(pg_e + MEMERR_L2C_L2EAHR_PAGE_OFFSET);
+ dev_err(edac_dev->dev,
+ "PMD%d memory error L2C L2ESR 0x%08X @ 0x%08X.%08X\n",
+ ctx->pmd, val, val_hi, val_lo);
+ dev_err(edac_dev->dev,
+ "ErrSyndrome 0x%02X ErrWay 0x%02X ErrCpu %d ErrGroup 0x%02X ErrAction 0x%02X\n",
+ MEMERR_L2C_L2ESR_ERRSYN_RD(val),
+ MEMERR_L2C_L2ESR_ERRWAY_RD(val),
+ MEMERR_L2C_L2ESR_ERRCPU_RD(val),
+ MEMERR_L2C_L2ESR_ERRGROUP_RD(val),
+ MEMERR_L2C_L2ESR_ERRACTION_RD(val));
+
+ if (val & MEMERR_L2C_L2ESR_ERR_MASK)
+ dev_err(edac_dev->dev, "One or more correctable error\n");
+ if (val & MEMERR_L2C_L2ESR_MULTICERR_MASK)
+ dev_err(edac_dev->dev, "Multiple correctable error\n");
+ if (val & MEMERR_L2C_L2ESR_UCERR_MASK)
+ dev_err(edac_dev->dev, "One or more uncorrectable error\n");
+ if (val & MEMERR_L2C_L2ESR_MULTUCERR_MASK)
+ dev_err(edac_dev->dev, "Multiple uncorrectable error\n");
+
+ switch (MEMERR_L2C_L2ESR_ERRTYPE_RD(val)) {
+ case 0:
+ dev_err(edac_dev->dev, "Outbound SDB parity error\n");
+ break;
+ case 1:
+ dev_err(edac_dev->dev, "Inbound SDB parity error\n");
+ break;
+ case 2:
+ dev_err(edac_dev->dev, "Tag ECC error\n");
+ break;
+ case 3:
+ dev_err(edac_dev->dev, "Data ECC error\n");
+ break;
+ }
- /* Clear any HW errors */
- writel(val, pg_e + MEMERR_L2C_L2ESR_PAGE_OFFSET);
+ /* Clear any HW errors */
+ writel(val, pg_e + MEMERR_L2C_L2ESR_PAGE_OFFSET);
- if (val & (MEMERR_L2C_L2ESR_ERR_MASK |
- MEMERR_L2C_L2ESR_MULTICERR_MASK))
- edac_device_handle_ce(edac_dev, 0, 0,
- edac_dev->ctl_name);
- if (val & (MEMERR_L2C_L2ESR_UCERR_MASK |
- MEMERR_L2C_L2ESR_MULTUCERR_MASK))
- edac_device_handle_ue(edac_dev, 0, 0,
- edac_dev->ctl_name);
- }
+ if (val & (MEMERR_L2C_L2ESR_ERR_MASK |
+ MEMERR_L2C_L2ESR_MULTICERR_MASK))
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+ if (val & (MEMERR_L2C_L2ESR_UCERR_MASK |
+ MEMERR_L2C_L2ESR_MULTUCERR_MASK))
+ edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+chk_l2c:
/* Check if any memory request timed out on L2 cache */
pg_d = ctx->pmd_csr + CPU_L2C_PAGE;
val = readl(pg_d + CPUX_L2C_L2RTOSR_PAGE_OFFSET);
@@ -877,35 +870,25 @@ static const struct file_operations xgene_edac_pmd_debug_inject_fops[] = {
{ }
};
-static void xgene_edac_pmd_create_debugfs_nodes(
- struct edac_device_ctl_info *edac_dev)
+static void
+xgene_edac_pmd_create_debugfs_nodes(struct edac_device_ctl_info *edac_dev)
{
struct xgene_edac_pmd_ctx *ctx = edac_dev->pvt_info;
- struct dentry *edac_debugfs;
- char name[30];
+ struct dentry *dbgfs_dir;
+ char name[10];
- if (!IS_ENABLED(CONFIG_EDAC_DEBUG))
+ if (!IS_ENABLED(CONFIG_EDAC_DEBUG) || !ctx->edac->dfs)
return;
- /*
- * Todo: Switch to common EDAC debug file system for edac device
- * when available.
- */
- if (!ctx->edac->dfs) {
- ctx->edac->dfs = debugfs_create_dir(edac_dev->dev->kobj.name,
- NULL);
- if (!ctx->edac->dfs)
- return;
- }
- sprintf(name, "PMD%d", ctx->pmd);
- edac_debugfs = debugfs_create_dir(name, ctx->edac->dfs);
- if (!edac_debugfs)
+ snprintf(name, sizeof(name), "PMD%d", ctx->pmd);
+ dbgfs_dir = edac_debugfs_create_dir_at(name, ctx->edac->dfs);
+ if (!dbgfs_dir)
return;
- debugfs_create_file("l1_inject_ctrl", S_IWUSR, edac_debugfs, edac_dev,
- &xgene_edac_pmd_debug_inject_fops[0]);
- debugfs_create_file("l2_inject_ctrl", S_IWUSR, edac_debugfs, edac_dev,
- &xgene_edac_pmd_debug_inject_fops[1]);
+ edac_debugfs_create_file("l1_inject_ctrl", S_IWUSR, dbgfs_dir, edac_dev,
+ &xgene_edac_pmd_debug_inject_fops[0]);
+ edac_debugfs_create_file("l2_inject_ctrl", S_IWUSR, dbgfs_dir, edac_dev,
+ &xgene_edac_pmd_debug_inject_fops[1]);
}
static int xgene_edac_pmd_available(u32 efuse, int pmd)
@@ -941,7 +924,7 @@ static int xgene_edac_pmd_add(struct xgene_edac *edac, struct device_node *np,
goto err_group;
}
- sprintf(edac_name, "l2c%d", pmd);
+ snprintf(edac_name, sizeof(edac_name), "l2c%d", pmd);
edac_dev = edac_device_alloc_ctl_info(sizeof(*ctx),
edac_name, 1, "l2c", 1, 2, NULL,
0, edac_device_alloc_index());
@@ -1016,10 +999,780 @@ static int xgene_edac_pmd_remove(struct xgene_edac_pmd_ctx *pmd)
return 0;
}
+/* L3 Error device */
+#define L3C_ESR (0x0A * 4)
+#define L3C_ESR_DATATAG_MASK BIT(9)
+#define L3C_ESR_MULTIHIT_MASK BIT(8)
+#define L3C_ESR_UCEVICT_MASK BIT(6)
+#define L3C_ESR_MULTIUCERR_MASK BIT(5)
+#define L3C_ESR_MULTICERR_MASK BIT(4)
+#define L3C_ESR_UCERR_MASK BIT(3)
+#define L3C_ESR_CERR_MASK BIT(2)
+#define L3C_ESR_UCERRINTR_MASK BIT(1)
+#define L3C_ESR_CERRINTR_MASK BIT(0)
+#define L3C_ECR (0x0B * 4)
+#define L3C_ECR_UCINTREN BIT(3)
+#define L3C_ECR_CINTREN BIT(2)
+#define L3C_UCERREN BIT(1)
+#define L3C_CERREN BIT(0)
+#define L3C_ELR (0x0C * 4)
+#define L3C_ELR_ERRSYN(src) ((src & 0xFF800000) >> 23)
+#define L3C_ELR_ERRWAY(src) ((src & 0x007E0000) >> 17)
+#define L3C_ELR_AGENTID(src) ((src & 0x0001E000) >> 13)
+#define L3C_ELR_ERRGRP(src) ((src & 0x00000F00) >> 8)
+#define L3C_ELR_OPTYPE(src) ((src & 0x000000F0) >> 4)
+#define L3C_ELR_PADDRHIGH(src) (src & 0x0000000F)
+#define L3C_AELR (0x0D * 4)
+#define L3C_BELR (0x0E * 4)
+#define L3C_BELR_BANK(src) (src & 0x0000000F)
+
+struct xgene_edac_dev_ctx {
+ struct list_head next;
+ struct device ddev;
+ char *name;
+ struct xgene_edac *edac;
+ struct edac_device_ctl_info *edac_dev;
+ int edac_idx;
+ void __iomem *dev_csr;
+ int version;
+};
+
+/*
+ * Version 1 of the L3 controller has broken single bit correctable logic for
+ * certain error syndromes. Log them as uncorrectable in that case.
+ */
+static bool xgene_edac_l3_promote_to_uc_err(u32 l3cesr, u32 l3celr)
+{
+ if (l3cesr & L3C_ESR_DATATAG_MASK) {
+ switch (L3C_ELR_ERRSYN(l3celr)) {
+ case 0x13C:
+ case 0x0B4:
+ case 0x007:
+ case 0x00D:
+ case 0x00E:
+ case 0x019:
+ case 0x01A:
+ case 0x01C:
+ case 0x04E:
+ case 0x041:
+ return true;
+ }
+ } else if (L3C_ELR_ERRSYN(l3celr) == 9)
+ return true;
+
+ return false;
+}
+
+static void xgene_edac_l3_check(struct edac_device_ctl_info *edac_dev)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ u32 l3cesr;
+ u32 l3celr;
+ u32 l3caelr;
+ u32 l3cbelr;
+
+ l3cesr = readl(ctx->dev_csr + L3C_ESR);
+ if (!(l3cesr & (L3C_ESR_UCERR_MASK | L3C_ESR_CERR_MASK)))
+ return;
+
+ if (l3cesr & L3C_ESR_UCERR_MASK)
+ dev_err(edac_dev->dev, "L3C uncorrectable error\n");
+ if (l3cesr & L3C_ESR_CERR_MASK)
+ dev_warn(edac_dev->dev, "L3C correctable error\n");
+
+ l3celr = readl(ctx->dev_csr + L3C_ELR);
+ l3caelr = readl(ctx->dev_csr + L3C_AELR);
+ l3cbelr = readl(ctx->dev_csr + L3C_BELR);
+ if (l3cesr & L3C_ESR_MULTIHIT_MASK)
+ dev_err(edac_dev->dev, "L3C multiple hit error\n");
+ if (l3cesr & L3C_ESR_UCEVICT_MASK)
+ dev_err(edac_dev->dev,
+ "L3C dropped eviction of line with error\n");
+ if (l3cesr & L3C_ESR_MULTIUCERR_MASK)
+ dev_err(edac_dev->dev, "L3C multiple uncorrectable error\n");
+ if (l3cesr & L3C_ESR_DATATAG_MASK)
+ dev_err(edac_dev->dev,
+ "L3C data error syndrome 0x%X group 0x%X\n",
+ L3C_ELR_ERRSYN(l3celr), L3C_ELR_ERRGRP(l3celr));
+ else
+ dev_err(edac_dev->dev,
+ "L3C tag error syndrome 0x%X Way of Tag 0x%X Agent ID 0x%X Operation type 0x%X\n",
+ L3C_ELR_ERRSYN(l3celr), L3C_ELR_ERRWAY(l3celr),
+ L3C_ELR_AGENTID(l3celr), L3C_ELR_OPTYPE(l3celr));
+ /*
+ * NOTE: Address [41:38] in L3C_ELR_PADDRHIGH(l3celr).
+ * Address [37:6] in l3caelr. Lower 6 bits are zero.
+ */
+ dev_err(edac_dev->dev, "L3C error address 0x%08X.%08X bank %d\n",
+ L3C_ELR_PADDRHIGH(l3celr) << 6 | (l3caelr >> 26),
+ (l3caelr & 0x3FFFFFFF) << 6, L3C_BELR_BANK(l3cbelr));
+ dev_err(edac_dev->dev,
+ "L3C error status register value 0x%X\n", l3cesr);
+
+ /* Clear L3C error interrupt */
+ writel(0, ctx->dev_csr + L3C_ESR);
+
+ if (ctx->version <= 1 &&
+ xgene_edac_l3_promote_to_uc_err(l3cesr, l3celr)) {
+ edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+ return;
+ }
+ if (l3cesr & L3C_ESR_CERR_MASK)
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+ if (l3cesr & L3C_ESR_UCERR_MASK)
+ edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+}
+
+static void xgene_edac_l3_hw_init(struct edac_device_ctl_info *edac_dev,
+ bool enable)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ u32 val;
+
+ val = readl(ctx->dev_csr + L3C_ECR);
+ val |= L3C_UCERREN | L3C_CERREN;
+ /* On disable, we just disable interrupt but keep error enabled */
+ if (edac_dev->op_state == OP_RUNNING_INTERRUPT) {
+ if (enable)
+ val |= L3C_ECR_UCINTREN | L3C_ECR_CINTREN;
+ else
+ val &= ~(L3C_ECR_UCINTREN | L3C_ECR_CINTREN);
+ }
+ writel(val, ctx->dev_csr + L3C_ECR);
+
+ if (edac_dev->op_state == OP_RUNNING_INTERRUPT) {
+ /* Enable/disable L3 error top level interrupt */
+ if (enable) {
+ xgene_edac_pcp_clrbits(ctx->edac, PCPHPERRINTMSK,
+ L3C_UNCORR_ERR_MASK);
+ xgene_edac_pcp_clrbits(ctx->edac, PCPLPERRINTMSK,
+ L3C_CORR_ERR_MASK);
+ } else {
+ xgene_edac_pcp_setbits(ctx->edac, PCPHPERRINTMSK,
+ L3C_UNCORR_ERR_MASK);
+ xgene_edac_pcp_setbits(ctx->edac, PCPLPERRINTMSK,
+ L3C_CORR_ERR_MASK);
+ }
+ }
+}
+
+static ssize_t xgene_edac_l3_inject_ctrl_write(struct file *file,
+ const char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct edac_device_ctl_info *edac_dev = file->private_data;
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+
+ /* Generate all errors */
+ writel(0xFFFFFFFF, ctx->dev_csr + L3C_ESR);
+ return count;
+}
+
+static const struct file_operations xgene_edac_l3_debug_inject_fops = {
+ .open = simple_open,
+ .write = xgene_edac_l3_inject_ctrl_write,
+ .llseek = generic_file_llseek
+};
+
+static void
+xgene_edac_l3_create_debugfs_nodes(struct edac_device_ctl_info *edac_dev)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ struct dentry *dbgfs_dir;
+ char name[10];
+
+ if (!IS_ENABLED(CONFIG_EDAC_DEBUG) || !ctx->edac->dfs)
+ return;
+
+ snprintf(name, sizeof(name), "l3c%d", ctx->edac_idx);
+ dbgfs_dir = edac_debugfs_create_dir_at(name, ctx->edac->dfs);
+ if (!dbgfs_dir)
+ return;
+
+ debugfs_create_file("l3_inject_ctrl", S_IWUSR, dbgfs_dir, edac_dev,
+ &xgene_edac_l3_debug_inject_fops);
+}
+
+static int xgene_edac_l3_add(struct xgene_edac *edac, struct device_node *np,
+ int version)
+{
+ struct edac_device_ctl_info *edac_dev;
+ struct xgene_edac_dev_ctx *ctx;
+ struct resource res;
+ void __iomem *dev_csr;
+ int edac_idx;
+ int rc = 0;
+
+ if (!devres_open_group(edac->dev, xgene_edac_l3_add, GFP_KERNEL))
+ return -ENOMEM;
+
+ rc = of_address_to_resource(np, 0, &res);
+ if (rc < 0) {
+ dev_err(edac->dev, "no L3 resource address\n");
+ goto err_release_group;
+ }
+ dev_csr = devm_ioremap_resource(edac->dev, &res);
+ if (IS_ERR(dev_csr)) {
+ dev_err(edac->dev,
+ "devm_ioremap_resource failed for L3 resource address\n");
+ rc = PTR_ERR(dev_csr);
+ goto err_release_group;
+ }
+
+ edac_idx = edac_device_alloc_index();
+ edac_dev = edac_device_alloc_ctl_info(sizeof(*ctx),
+ "l3c", 1, "l3c", 1, 0, NULL, 0,
+ edac_idx);
+ if (!edac_dev) {
+ rc = -ENOMEM;
+ goto err_release_group;
+ }
+
+ ctx = edac_dev->pvt_info;
+ ctx->dev_csr = dev_csr;
+ ctx->name = "xgene_l3_err";
+ ctx->edac_idx = edac_idx;
+ ctx->edac = edac;
+ ctx->edac_dev = edac_dev;
+ ctx->ddev = *edac->dev;
+ ctx->version = version;
+ edac_dev->dev = &ctx->ddev;
+ edac_dev->ctl_name = ctx->name;
+ edac_dev->dev_name = ctx->name;
+ edac_dev->mod_name = EDAC_MOD_STR;
+
+ if (edac_op_state == EDAC_OPSTATE_POLL)
+ edac_dev->edac_check = xgene_edac_l3_check;
+
+ xgene_edac_l3_create_debugfs_nodes(edac_dev);
+
+ rc = edac_device_add_device(edac_dev);
+ if (rc > 0) {
+ dev_err(edac->dev, "failed edac_device_add_device()\n");
+ rc = -ENOMEM;
+ goto err_ctl_free;
+ }
+
+ if (edac_op_state == EDAC_OPSTATE_INT)
+ edac_dev->op_state = OP_RUNNING_INTERRUPT;
+
+ list_add(&ctx->next, &edac->l3s);
+
+ xgene_edac_l3_hw_init(edac_dev, 1);
+
+ devres_remove_group(edac->dev, xgene_edac_l3_add);
+
+ dev_info(edac->dev, "X-Gene EDAC L3 registered\n");
+ return 0;
+
+err_ctl_free:
+ edac_device_free_ctl_info(edac_dev);
+err_release_group:
+ devres_release_group(edac->dev, xgene_edac_l3_add);
+ return rc;
+}
+
+static int xgene_edac_l3_remove(struct xgene_edac_dev_ctx *l3)
+{
+ struct edac_device_ctl_info *edac_dev = l3->edac_dev;
+
+ xgene_edac_l3_hw_init(edac_dev, 0);
+ edac_device_del_device(l3->edac->dev);
+ edac_device_free_ctl_info(edac_dev);
+ return 0;
+}
+
+/* SoC error device */
+#define IOBAXIS0TRANSERRINTSTS 0x0000
+#define IOBAXIS0_M_ILLEGAL_ACCESS_MASK BIT(1)
+#define IOBAXIS0_ILLEGAL_ACCESS_MASK BIT(0)
+#define IOBAXIS0TRANSERRINTMSK 0x0004
+#define IOBAXIS0TRANSERRREQINFOL 0x0008
+#define IOBAXIS0TRANSERRREQINFOH 0x000c
+#define REQTYPE_RD(src) (((src) & BIT(0)))
+#define ERRADDRH_RD(src) (((src) & 0xffc00000) >> 22)
+#define IOBAXIS1TRANSERRINTSTS 0x0010
+#define IOBAXIS1TRANSERRINTMSK 0x0014
+#define IOBAXIS1TRANSERRREQINFOL 0x0018
+#define IOBAXIS1TRANSERRREQINFOH 0x001c
+#define IOBPATRANSERRINTSTS 0x0020
+#define IOBPA_M_REQIDRAM_CORRUPT_MASK BIT(7)
+#define IOBPA_REQIDRAM_CORRUPT_MASK BIT(6)
+#define IOBPA_M_TRANS_CORRUPT_MASK BIT(5)
+#define IOBPA_TRANS_CORRUPT_MASK BIT(4)
+#define IOBPA_M_WDATA_CORRUPT_MASK BIT(3)
+#define IOBPA_WDATA_CORRUPT_MASK BIT(2)
+#define IOBPA_M_RDATA_CORRUPT_MASK BIT(1)
+#define IOBPA_RDATA_CORRUPT_MASK BIT(0)
+#define IOBBATRANSERRINTSTS 0x0030
+#define M_ILLEGAL_ACCESS_MASK BIT(15)
+#define ILLEGAL_ACCESS_MASK BIT(14)
+#define M_WIDRAM_CORRUPT_MASK BIT(13)
+#define WIDRAM_CORRUPT_MASK BIT(12)
+#define M_RIDRAM_CORRUPT_MASK BIT(11)
+#define RIDRAM_CORRUPT_MASK BIT(10)
+#define M_TRANS_CORRUPT_MASK BIT(9)
+#define TRANS_CORRUPT_MASK BIT(8)
+#define M_WDATA_CORRUPT_MASK BIT(7)
+#define WDATA_CORRUPT_MASK BIT(6)
+#define M_RBM_POISONED_REQ_MASK BIT(5)
+#define RBM_POISONED_REQ_MASK BIT(4)
+#define M_XGIC_POISONED_REQ_MASK BIT(3)
+#define XGIC_POISONED_REQ_MASK BIT(2)
+#define M_WRERR_RESP_MASK BIT(1)
+#define WRERR_RESP_MASK BIT(0)
+#define IOBBATRANSERRREQINFOL 0x0038
+#define IOBBATRANSERRREQINFOH 0x003c
+#define REQTYPE_F2_RD(src) ((src) & BIT(0))
+#define ERRADDRH_F2_RD(src) (((src) & 0xffc00000) >> 22)
+#define IOBBATRANSERRCSWREQID 0x0040
+#define XGICTRANSERRINTSTS 0x0050
+#define M_WR_ACCESS_ERR_MASK BIT(3)
+#define WR_ACCESS_ERR_MASK BIT(2)
+#define M_RD_ACCESS_ERR_MASK BIT(1)
+#define RD_ACCESS_ERR_MASK BIT(0)
+#define XGICTRANSERRINTMSK 0x0054
+#define XGICTRANSERRREQINFO 0x0058
+#define REQTYPE_MASK BIT(26)
+#define ERRADDR_RD(src) ((src) & 0x03ffffff)
+#define GLBL_ERR_STS 0x0800
+#define MDED_ERR_MASK BIT(3)
+#define DED_ERR_MASK BIT(2)
+#define MSEC_ERR_MASK BIT(1)
+#define SEC_ERR_MASK BIT(0)
+#define GLBL_SEC_ERRL 0x0810
+#define GLBL_SEC_ERRH 0x0818
+#define GLBL_MSEC_ERRL 0x0820
+#define GLBL_MSEC_ERRH 0x0828
+#define GLBL_DED_ERRL 0x0830
+#define GLBL_DED_ERRLMASK 0x0834
+#define GLBL_DED_ERRH 0x0838
+#define GLBL_DED_ERRHMASK 0x083c
+#define GLBL_MDED_ERRL 0x0840
+#define GLBL_MDED_ERRLMASK 0x0844
+#define GLBL_MDED_ERRH 0x0848
+#define GLBL_MDED_ERRHMASK 0x084c
+
+static const char * const soc_mem_err_v1[] = {
+ "10GbE0",
+ "10GbE1",
+ "Security",
+ "SATA45",
+ "SATA23/ETH23",
+ "SATA01/ETH01",
+ "USB1",
+ "USB0",
+ "QML",
+ "QM0",
+ "QM1 (XGbE01)",
+ "PCIE4",
+ "PCIE3",
+ "PCIE2",
+ "PCIE1",
+ "PCIE0",
+ "CTX Manager",
+ "OCM",
+ "1GbE",
+ "CLE",
+ "AHBC",
+ "PktDMA",
+ "GFC",
+ "MSLIM",
+ "10GbE2",
+ "10GbE3",
+ "QM2 (XGbE23)",
+ "IOB",
+ "unknown",
+ "unknown",
+ "unknown",
+ "unknown",
+};
+
+static void xgene_edac_iob_gic_report(struct edac_device_ctl_info *edac_dev)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ u32 err_addr_lo;
+ u32 err_addr_hi;
+ u32 reg;
+ u32 info;
+
+ /* GIC transaction error interrupt */
+ reg = readl(ctx->dev_csr + XGICTRANSERRINTSTS);
+ if (!reg)
+ goto chk_iob_err;
+ dev_err(edac_dev->dev, "XGIC transaction error\n");
+ if (reg & RD_ACCESS_ERR_MASK)
+ dev_err(edac_dev->dev, "XGIC read size error\n");
+ if (reg & M_RD_ACCESS_ERR_MASK)
+ dev_err(edac_dev->dev, "Multiple XGIC read size error\n");
+ if (reg & WR_ACCESS_ERR_MASK)
+ dev_err(edac_dev->dev, "XGIC write size error\n");
+ if (reg & M_WR_ACCESS_ERR_MASK)
+ dev_err(edac_dev->dev, "Multiple XGIC write size error\n");
+ info = readl(ctx->dev_csr + XGICTRANSERRREQINFO);
+ dev_err(edac_dev->dev, "XGIC %s access @ 0x%08X (0x%08X)\n",
+ info & REQTYPE_MASK ? "read" : "write", ERRADDR_RD(info),
+ info);
+ writel(reg, ctx->dev_csr + XGICTRANSERRINTSTS);
+
+chk_iob_err:
+ /* IOB memory error */
+ reg = readl(ctx->dev_csr + GLBL_ERR_STS);
+ if (!reg)
+ return;
+ if (reg & SEC_ERR_MASK) {
+ err_addr_lo = readl(ctx->dev_csr + GLBL_SEC_ERRL);
+ err_addr_hi = readl(ctx->dev_csr + GLBL_SEC_ERRH);
+ dev_err(edac_dev->dev,
+ "IOB single-bit correctable memory at 0x%08X.%08X error\n",
+ err_addr_lo, err_addr_hi);
+ writel(err_addr_lo, ctx->dev_csr + GLBL_SEC_ERRL);
+ writel(err_addr_hi, ctx->dev_csr + GLBL_SEC_ERRH);
+ }
+ if (reg & MSEC_ERR_MASK) {
+ err_addr_lo = readl(ctx->dev_csr + GLBL_MSEC_ERRL);
+ err_addr_hi = readl(ctx->dev_csr + GLBL_MSEC_ERRH);
+ dev_err(edac_dev->dev,
+ "IOB multiple single-bit correctable memory at 0x%08X.%08X error\n",
+ err_addr_lo, err_addr_hi);
+ writel(err_addr_lo, ctx->dev_csr + GLBL_MSEC_ERRL);
+ writel(err_addr_hi, ctx->dev_csr + GLBL_MSEC_ERRH);
+ }
+ if (reg & (SEC_ERR_MASK | MSEC_ERR_MASK))
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+
+ if (reg & DED_ERR_MASK) {
+ err_addr_lo = readl(ctx->dev_csr + GLBL_DED_ERRL);
+ err_addr_hi = readl(ctx->dev_csr + GLBL_DED_ERRH);
+ dev_err(edac_dev->dev,
+ "IOB double-bit uncorrectable memory at 0x%08X.%08X error\n",
+ err_addr_lo, err_addr_hi);
+ writel(err_addr_lo, ctx->dev_csr + GLBL_DED_ERRL);
+ writel(err_addr_hi, ctx->dev_csr + GLBL_DED_ERRH);
+ }
+ if (reg & MDED_ERR_MASK) {
+ err_addr_lo = readl(ctx->dev_csr + GLBL_MDED_ERRL);
+ err_addr_hi = readl(ctx->dev_csr + GLBL_MDED_ERRH);
+ dev_err(edac_dev->dev,
+ "Multiple IOB double-bit uncorrectable memory at 0x%08X.%08X error\n",
+ err_addr_lo, err_addr_hi);
+ writel(err_addr_lo, ctx->dev_csr + GLBL_MDED_ERRL);
+ writel(err_addr_hi, ctx->dev_csr + GLBL_MDED_ERRH);
+ }
+ if (reg & (DED_ERR_MASK | MDED_ERR_MASK))
+ edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+}
+
+static void xgene_edac_rb_report(struct edac_device_ctl_info *edac_dev)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ u32 err_addr_lo;
+ u32 err_addr_hi;
+ u32 reg;
+
+ /* IOB Bridge agent transaction error interrupt */
+ reg = readl(ctx->dev_csr + IOBBATRANSERRINTSTS);
+ if (!reg)
+ return;
+
+ dev_err(edac_dev->dev, "IOB bridge agent (BA) transaction error\n");
+ if (reg & WRERR_RESP_MASK)
+ dev_err(edac_dev->dev, "IOB BA write response error\n");
+ if (reg & M_WRERR_RESP_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB BA write response error\n");
+ if (reg & XGIC_POISONED_REQ_MASK)
+ dev_err(edac_dev->dev, "IOB BA XGIC poisoned write error\n");
+ if (reg & M_XGIC_POISONED_REQ_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB BA XGIC poisoned write error\n");
+ if (reg & RBM_POISONED_REQ_MASK)
+ dev_err(edac_dev->dev, "IOB BA RBM poisoned write error\n");
+ if (reg & M_RBM_POISONED_REQ_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB BA RBM poisoned write error\n");
+ if (reg & WDATA_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "IOB BA write error\n");
+ if (reg & M_WDATA_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "Multiple IOB BA write error\n");
+ if (reg & TRANS_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "IOB BA transaction error\n");
+ if (reg & M_TRANS_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "Multiple IOB BA transaction error\n");
+ if (reg & RIDRAM_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "IOB BA RDIDRAM read transaction ID error\n");
+ if (reg & M_RIDRAM_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB BA RDIDRAM read transaction ID error\n");
+ if (reg & WIDRAM_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "IOB BA RDIDRAM write transaction ID error\n");
+ if (reg & M_WIDRAM_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB BA RDIDRAM write transaction ID error\n");
+ if (reg & ILLEGAL_ACCESS_MASK)
+ dev_err(edac_dev->dev,
+ "IOB BA XGIC/RB illegal access error\n");
+ if (reg & M_ILLEGAL_ACCESS_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB BA XGIC/RB illegal access error\n");
+
+ err_addr_lo = readl(ctx->dev_csr + IOBBATRANSERRREQINFOL);
+ err_addr_hi = readl(ctx->dev_csr + IOBBATRANSERRREQINFOH);
+ dev_err(edac_dev->dev, "IOB BA %s access at 0x%02X.%08X (0x%08X)\n",
+ REQTYPE_F2_RD(err_addr_hi) ? "read" : "write",
+ ERRADDRH_F2_RD(err_addr_hi), err_addr_lo, err_addr_hi);
+ if (reg & WRERR_RESP_MASK)
+ dev_err(edac_dev->dev, "IOB BA requestor ID 0x%08X\n",
+ readl(ctx->dev_csr + IOBBATRANSERRCSWREQID));
+ writel(reg, ctx->dev_csr + IOBBATRANSERRINTSTS);
+}
+
+static void xgene_edac_pa_report(struct edac_device_ctl_info *edac_dev)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ u32 err_addr_lo;
+ u32 err_addr_hi;
+ u32 reg;
+
+ /* IOB Processing agent transaction error interrupt */
+ reg = readl(ctx->dev_csr + IOBPATRANSERRINTSTS);
+ if (!reg)
+ goto chk_iob_axi0;
+ dev_err(edac_dev->dev, "IOB procesing agent (PA) transaction error\n");
+ if (reg & IOBPA_RDATA_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "IOB PA read data RAM error\n");
+ if (reg & IOBPA_M_RDATA_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "Mutilple IOB PA read data RAM error\n");
+ if (reg & IOBPA_WDATA_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "IOB PA write data RAM error\n");
+ if (reg & IOBPA_M_WDATA_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "Mutilple IOB PA write data RAM error\n");
+ if (reg & IOBPA_TRANS_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "IOB PA transaction error\n");
+ if (reg & IOBPA_M_TRANS_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "Mutilple IOB PA transaction error\n");
+ if (reg & IOBPA_REQIDRAM_CORRUPT_MASK)
+ dev_err(edac_dev->dev, "IOB PA transaction ID RAM error\n");
+ if (reg & IOBPA_M_REQIDRAM_CORRUPT_MASK)
+ dev_err(edac_dev->dev,
+ "Multiple IOB PA transaction ID RAM error\n");
+ writel(reg, ctx->dev_csr + IOBPATRANSERRINTSTS);
+
+chk_iob_axi0:
+ /* IOB AXI0 Error */
+ reg = readl(ctx->dev_csr + IOBAXIS0TRANSERRINTSTS);
+ if (!reg)
+ goto chk_iob_axi1;
+ err_addr_lo = readl(ctx->dev_csr + IOBAXIS0TRANSERRREQINFOL);
+ err_addr_hi = readl(ctx->dev_csr + IOBAXIS0TRANSERRREQINFOH);
+ dev_err(edac_dev->dev,
+ "%sAXI slave 0 illegal %s access @ 0x%02X.%08X (0x%08X)\n",
+ reg & IOBAXIS0_M_ILLEGAL_ACCESS_MASK ? "Multiple " : "",
+ REQTYPE_RD(err_addr_hi) ? "read" : "write",
+ ERRADDRH_RD(err_addr_hi), err_addr_lo, err_addr_hi);
+ writel(reg, ctx->dev_csr + IOBAXIS0TRANSERRINTSTS);
+
+chk_iob_axi1:
+ /* IOB AXI1 Error */
+ reg = readl(ctx->dev_csr + IOBAXIS1TRANSERRINTSTS);
+ if (!reg)
+ return;
+ err_addr_lo = readl(ctx->dev_csr + IOBAXIS1TRANSERRREQINFOL);
+ err_addr_hi = readl(ctx->dev_csr + IOBAXIS1TRANSERRREQINFOH);
+ dev_err(edac_dev->dev,
+ "%sAXI slave 1 illegal %s access @ 0x%02X.%08X (0x%08X)\n",
+ reg & IOBAXIS0_M_ILLEGAL_ACCESS_MASK ? "Multiple " : "",
+ REQTYPE_RD(err_addr_hi) ? "read" : "write",
+ ERRADDRH_RD(err_addr_hi), err_addr_lo, err_addr_hi);
+ writel(reg, ctx->dev_csr + IOBAXIS1TRANSERRINTSTS);
+}
+
+static void xgene_edac_soc_check(struct edac_device_ctl_info *edac_dev)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+ const char * const *soc_mem_err = NULL;
+ u32 pcp_hp_stat;
+ u32 pcp_lp_stat;
+ u32 reg;
+ int i;
+
+ xgene_edac_pcp_rd(ctx->edac, PCPHPERRINTSTS, &pcp_hp_stat);
+ xgene_edac_pcp_rd(ctx->edac, PCPLPERRINTSTS, &pcp_lp_stat);
+ xgene_edac_pcp_rd(ctx->edac, MEMERRINTSTS, &reg);
+ if (!((pcp_hp_stat & (IOB_PA_ERR_MASK | IOB_BA_ERR_MASK |
+ IOB_XGIC_ERR_MASK | IOB_RB_ERR_MASK)) ||
+ (pcp_lp_stat & CSW_SWITCH_TRACE_ERR_MASK) || reg))
+ return;
+
+ if (pcp_hp_stat & IOB_XGIC_ERR_MASK)
+ xgene_edac_iob_gic_report(edac_dev);
+
+ if (pcp_hp_stat & (IOB_RB_ERR_MASK | IOB_BA_ERR_MASK))
+ xgene_edac_rb_report(edac_dev);
+
+ if (pcp_hp_stat & IOB_PA_ERR_MASK)
+ xgene_edac_pa_report(edac_dev);
+
+ if (pcp_lp_stat & CSW_SWITCH_TRACE_ERR_MASK) {
+ dev_info(edac_dev->dev,
+ "CSW switch trace correctable memory parity error\n");
+ edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+ }
+
+ if (!reg)
+ return;
+ if (ctx->version == 1)
+ soc_mem_err = soc_mem_err_v1;
+ if (!soc_mem_err) {
+ dev_err(edac_dev->dev, "SoC memory parity error 0x%08X\n",
+ reg);
+ edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+ return;
+ }
+ for (i = 0; i < 31; i++) {
+ if (reg & (1 << i)) {
+ dev_err(edac_dev->dev, "%s memory parity error\n",
+ soc_mem_err[i]);
+ edac_device_handle_ue(edac_dev, 0, 0,
+ edac_dev->ctl_name);
+ }
+ }
+}
+
+static void xgene_edac_soc_hw_init(struct edac_device_ctl_info *edac_dev,
+ bool enable)
+{
+ struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
+
+ /* Enable SoC IP error interrupt */
+ if (edac_dev->op_state == OP_RUNNING_INTERRUPT) {
+ if (enable) {
+ xgene_edac_pcp_clrbits(ctx->edac, PCPHPERRINTMSK,
+ IOB_PA_ERR_MASK |
+ IOB_BA_ERR_MASK |
+ IOB_XGIC_ERR_MASK |
+ IOB_RB_ERR_MASK);
+ xgene_edac_pcp_clrbits(ctx->edac, PCPLPERRINTMSK,
+ CSW_SWITCH_TRACE_ERR_MASK);
+ } else {
+ xgene_edac_pcp_setbits(ctx->edac, PCPHPERRINTMSK,
+ IOB_PA_ERR_MASK |
+ IOB_BA_ERR_MASK |
+ IOB_XGIC_ERR_MASK |
+ IOB_RB_ERR_MASK);
+ xgene_edac_pcp_setbits(ctx->edac, PCPLPERRINTMSK,
+ CSW_SWITCH_TRACE_ERR_MASK);
+ }
+
+ writel(enable ? 0x0 : 0xFFFFFFFF,
+ ctx->dev_csr + IOBAXIS0TRANSERRINTMSK);
+ writel(enable ? 0x0 : 0xFFFFFFFF,
+ ctx->dev_csr + IOBAXIS1TRANSERRINTMSK);
+ writel(enable ? 0x0 : 0xFFFFFFFF,
+ ctx->dev_csr + XGICTRANSERRINTMSK);
+
+ xgene_edac_pcp_setbits(ctx->edac, MEMERRINTMSK,
+ enable ? 0x0 : 0xFFFFFFFF);
+ }
+}
+
+static int xgene_edac_soc_add(struct xgene_edac *edac, struct device_node *np,
+ int version)
+{
+ struct edac_device_ctl_info *edac_dev;
+ struct xgene_edac_dev_ctx *ctx;
+ void __iomem *dev_csr;
+ struct resource res;
+ int edac_idx;
+ int rc;
+
+ if (!devres_open_group(edac->dev, xgene_edac_soc_add, GFP_KERNEL))
+ return -ENOMEM;
+
+ rc = of_address_to_resource(np, 0, &res);
+ if (rc < 0) {
+ dev_err(edac->dev, "no SoC resource address\n");
+ goto err_release_group;
+ }
+ dev_csr = devm_ioremap_resource(edac->dev, &res);
+ if (IS_ERR(dev_csr)) {
+ dev_err(edac->dev,
+ "devm_ioremap_resource failed for soc resource address\n");
+ rc = PTR_ERR(dev_csr);
+ goto err_release_group;
+ }
+
+ edac_idx = edac_device_alloc_index();
+ edac_dev = edac_device_alloc_ctl_info(sizeof(*ctx),
+ "SOC", 1, "SOC", 1, 2, NULL, 0,
+ edac_idx);
+ if (!edac_dev) {
+ rc = -ENOMEM;
+ goto err_release_group;
+ }
+
+ ctx = edac_dev->pvt_info;
+ ctx->dev_csr = dev_csr;
+ ctx->name = "xgene_soc_err";
+ ctx->edac_idx = edac_idx;
+ ctx->edac = edac;
+ ctx->edac_dev = edac_dev;
+ ctx->ddev = *edac->dev;
+ ctx->version = version;
+ edac_dev->dev = &ctx->ddev;
+ edac_dev->ctl_name = ctx->name;
+ edac_dev->dev_name = ctx->name;
+ edac_dev->mod_name = EDAC_MOD_STR;
+
+ if (edac_op_state == EDAC_OPSTATE_POLL)
+ edac_dev->edac_check = xgene_edac_soc_check;
+
+ rc = edac_device_add_device(edac_dev);
+ if (rc > 0) {
+ dev_err(edac->dev, "failed edac_device_add_device()\n");
+ rc = -ENOMEM;
+ goto err_ctl_free;
+ }
+
+ if (edac_op_state == EDAC_OPSTATE_INT)
+ edac_dev->op_state = OP_RUNNING_INTERRUPT;
+
+ list_add(&ctx->next, &edac->socs);
+
+ xgene_edac_soc_hw_init(edac_dev, 1);
+
+ devres_remove_group(edac->dev, xgene_edac_soc_add);
+
+ dev_info(edac->dev, "X-Gene EDAC SoC registered\n");
+
+ return 0;
+
+err_ctl_free:
+ edac_device_free_ctl_info(edac_dev);
+err_release_group:
+ devres_release_group(edac->dev, xgene_edac_soc_add);
+ return rc;
+}
+
+static int xgene_edac_soc_remove(struct xgene_edac_dev_ctx *soc)
+{
+ struct edac_device_ctl_info *edac_dev = soc->edac_dev;
+
+ xgene_edac_soc_hw_init(edac_dev, 0);
+ edac_device_del_device(soc->edac->dev);
+ edac_device_free_ctl_info(edac_dev);
+ return 0;
+}
+
static irqreturn_t xgene_edac_isr(int irq, void *dev_id)
{
struct xgene_edac *ctx = dev_id;
struct xgene_edac_pmd_ctx *pmd;
+ struct xgene_edac_dev_ctx *node;
unsigned int pcp_hp_stat;
unsigned int pcp_lp_stat;
@@ -1030,9 +1783,8 @@ static irqreturn_t xgene_edac_isr(int irq, void *dev_id)
(MCU_CORR_ERR_MASK & pcp_lp_stat)) {
struct xgene_edac_mc_ctx *mcu;
- list_for_each_entry(mcu, &ctx->mcus, next) {
+ list_for_each_entry(mcu, &ctx->mcus, next)
xgene_edac_mc_check(mcu->mci);
- }
}
list_for_each_entry(pmd, &ctx->pmds, next) {
@@ -1040,6 +1792,12 @@ static irqreturn_t xgene_edac_isr(int irq, void *dev_id)
xgene_edac_pmd_check(pmd->edac_dev);
}
+ list_for_each_entry(node, &ctx->l3s, next)
+ xgene_edac_l3_check(node->edac_dev);
+
+ list_for_each_entry(node, &ctx->socs, next)
+ xgene_edac_soc_check(node->edac_dev);
+
return IRQ_HANDLED;
}
@@ -1058,6 +1816,8 @@ static int xgene_edac_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, edac);
INIT_LIST_HEAD(&edac->mcus);
INIT_LIST_HEAD(&edac->pmds);
+ INIT_LIST_HEAD(&edac->l3s);
+ INIT_LIST_HEAD(&edac->socs);
spin_lock_init(&edac->lock);
mutex_init(&edac->mc_lock);
@@ -1122,6 +1882,8 @@ static int xgene_edac_probe(struct platform_device *pdev)
}
}
+ edac->dfs = edac_debugfs_create_dir(pdev->dev.kobj.name);
+
for_each_child_of_node(pdev->dev.of_node, child) {
if (!of_device_is_available(child))
continue;
@@ -1131,6 +1893,14 @@ static int xgene_edac_probe(struct platform_device *pdev)
xgene_edac_pmd_add(edac, child, 1);
if (of_device_is_compatible(child, "apm,xgene-edac-pmd-v2"))
xgene_edac_pmd_add(edac, child, 2);
+ if (of_device_is_compatible(child, "apm,xgene-edac-l3"))
+ xgene_edac_l3_add(edac, child, 1);
+ if (of_device_is_compatible(child, "apm,xgene-edac-l3-v2"))
+ xgene_edac_l3_add(edac, child, 2);
+ if (of_device_is_compatible(child, "apm,xgene-edac-soc"))
+ xgene_edac_soc_add(edac, child, 0);
+ if (of_device_is_compatible(child, "apm,xgene-edac-soc-v1"))
+ xgene_edac_soc_add(edac, child, 1);
}
return 0;
@@ -1146,14 +1916,21 @@ static int xgene_edac_remove(struct platform_device *pdev)
struct xgene_edac_mc_ctx *temp_mcu;
struct xgene_edac_pmd_ctx *pmd;
struct xgene_edac_pmd_ctx *temp_pmd;
+ struct xgene_edac_dev_ctx *node;
+ struct xgene_edac_dev_ctx *temp_node;
- list_for_each_entry_safe(mcu, temp_mcu, &edac->mcus, next) {
+ list_for_each_entry_safe(mcu, temp_mcu, &edac->mcus, next)
xgene_edac_mc_remove(mcu);
- }
- list_for_each_entry_safe(pmd, temp_pmd, &edac->pmds, next) {
+ list_for_each_entry_safe(pmd, temp_pmd, &edac->pmds, next)
xgene_edac_pmd_remove(pmd);
- }
+
+ list_for_each_entry_safe(node, temp_node, &edac->l3s, next)
+ xgene_edac_l3_remove(node);
+
+ list_for_each_entry_safe(node, temp_node, &edac->socs, next)
+ xgene_edac_soc_remove(node);
+
return 0;
}
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 4b9f09cc38d8..e4890dd4fefd 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -1,7 +1,7 @@
/*
* extcon-arizona.c - Extcon driver Wolfson Arizona devices
*
- * Copyright (C) 2012 Wolfson Microelectronics plc
+ * Copyright (C) 2012-2014 Wolfson Microelectronics plc
*
* 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
@@ -43,11 +43,18 @@
#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
+#define ARIZONA_TST_CAP_DEFAULT 0x3
+#define ARIZONA_TST_CAP_CLAMP 0x1
+
#define ARIZONA_HPDET_MAX 10000
#define HPDET_DEBOUNCE 500
#define DEFAULT_MICD_TIMEOUT 2000
+#define QUICK_HEADPHONE_MAX_OHM 3
+#define MICROPHONE_MIN_OHM 1257
+#define MICROPHONE_MAX_OHM 30000
+
#define MICD_DBTIME_TWO_READINGS 2
#define MICD_DBTIME_FOUR_READINGS 4
@@ -117,19 +124,22 @@ static const struct arizona_micd_range micd_default_ranges[] = {
{ .max = 430, .key = BTN_5 },
};
+/* The number of levels in arizona_micd_levels valid for button thresholds */
+#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
+
static const int arizona_micd_levels[] = {
3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
- 1257,
+ 1257, 30000,
};
static const unsigned int arizona_cable[] = {
EXTCON_MECHANICAL,
- EXTCON_MICROPHONE,
- EXTCON_HEADPHONE,
- EXTCON_LINE_OUT,
+ EXTCON_JACK_MICROPHONE,
+ EXTCON_JACK_HEADPHONE,
+ EXTCON_JACK_LINE_OUT,
EXTCON_NONE,
};
@@ -140,17 +150,33 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
{
struct arizona *arizona = info->arizona;
unsigned int mask = 0, val = 0;
+ unsigned int cap_sel = 0;
int ret;
switch (arizona->type) {
+ case WM8998:
+ case WM1814:
+ mask = 0;
+ break;
case WM5110:
case WM8280:
mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
ARIZONA_HP1L_SHRTI;
- if (clamp)
+ if (clamp) {
val = ARIZONA_HP1L_SHRTO;
- else
+ cap_sel = ARIZONA_TST_CAP_CLAMP;
+ } else {
val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
+ cap_sel = ARIZONA_TST_CAP_DEFAULT;
+ }
+
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_HP_TEST_CTRL_1,
+ ARIZONA_HP1_TST_CAP_SEL_MASK,
+ cap_sel);
+ if (ret != 0)
+ dev_warn(arizona->dev,
+ "Failed to set TST_CAP_SEL: %d\n", ret);
break;
default:
mask = ARIZONA_RMV_SHRT_HP1L;
@@ -175,17 +201,19 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
ret);
}
- ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
- mask, val);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to do clamp: %d\n",
+ if (mask) {
+ ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
+ mask, val);
+ if (ret != 0)
+ dev_warn(arizona->dev, "Failed to do clamp: %d\n",
ret);
- ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
- mask, val);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to do clamp: %d\n",
- ret);
+ ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
+ mask, val);
+ if (ret != 0)
+ dev_warn(arizona->dev, "Failed to do clamp: %d\n",
+ ret);
+ }
/* Restore the desired state while not doing the clamp */
if (!clamp) {
@@ -270,6 +298,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
struct arizona *arizona = info->arizona;
bool change;
int ret;
+ unsigned int mode;
/* Microphone detection can't use idle mode */
pm_runtime_get(info->dev);
@@ -295,9 +324,14 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
regmap_write(arizona->regmap, 0x80, 0x0);
}
+ if (info->detecting && arizona->pdata.micd_software_compare)
+ mode = ARIZONA_ACCDET_MODE_ADC;
+ else
+ mode = ARIZONA_ACCDET_MODE_MIC;
+
regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
+ ARIZONA_ACCDET_MODE_MASK, mode);
arizona_extcon_pulse_micbias(info);
@@ -443,9 +477,6 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
arizona_hpdet_b_ranges[range].factor_a);
break;
- default:
- dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
- info->hpdet_ip_version);
case 2:
if (!(val & ARIZONA_HP_DONE_B)) {
dev_err(arizona->dev, "HPDET did not complete: %x\n",
@@ -482,6 +513,12 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
arizona_hpdet_c_ranges[range].min);
val = arizona_hpdet_c_ranges[range].min;
}
+ break;
+
+ default:
+ dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
+ info->hpdet_ip_version);
+ return -EINVAL;
}
dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
@@ -563,7 +600,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
struct arizona_extcon_info *info = data;
struct arizona *arizona = info->arizona;
int id_gpio = arizona->pdata.hpdet_id_gpio;
- unsigned int report = EXTCON_HEADPHONE;
+ unsigned int report = EXTCON_JACK_HEADPHONE;
int ret, reading;
bool mic = false;
@@ -608,9 +645,9 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
/* Report high impedence cables as line outputs */
if (reading >= 5000)
- report = EXTCON_LINE_OUT;
+ report = EXTCON_JACK_LINE_OUT;
else
- report = EXTCON_HEADPHONE;
+ report = EXTCON_JACK_HEADPHONE;
ret = extcon_set_cable_state_(info->edev, report, true);
if (ret != 0)
@@ -695,7 +732,7 @@ err:
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
+ ret = extcon_set_cable_state_(info->edev, EXTCON_JACK_HEADPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
@@ -752,7 +789,7 @@ err:
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
+ ret = extcon_set_cable_state_(info->edev, EXTCON_JACK_HEADPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
@@ -804,6 +841,37 @@ static void arizona_micd_detect(struct work_struct *work)
return;
}
+ if (info->detecting && arizona->pdata.micd_software_compare) {
+ /* Must disable MICD before we read the ADCVAL */
+ regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
+ ARIZONA_MICD_ENA, 0);
+ ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
+ if (ret != 0) {
+ dev_err(arizona->dev,
+ "Failed to read MICDET_ADCVAL: %d\n",
+ ret);
+ mutex_unlock(&info->lock);
+ return;
+ }
+
+ dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
+
+ val &= ARIZONA_MICDET_ADCVAL_MASK;
+ if (val < ARRAY_SIZE(arizona_micd_levels))
+ val = arizona_micd_levels[val];
+ else
+ val = INT_MAX;
+
+ if (val <= QUICK_HEADPHONE_MAX_OHM)
+ val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
+ else if (val <= MICROPHONE_MIN_OHM)
+ val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
+ else if (val <= MICROPHONE_MAX_OHM)
+ val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
+ else
+ val = ARIZONA_MICD_LVL_8;
+ }
+
for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
if (ret != 0) {
@@ -847,7 +915,7 @@ static void arizona_micd_detect(struct work_struct *work)
arizona_identify_headphone(info);
ret = extcon_set_cable_state_(info->edev,
- EXTCON_MICROPHONE, true);
+ EXTCON_JACK_MICROPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Headset report failed: %d\n",
ret);
@@ -932,10 +1000,17 @@ static void arizona_micd_detect(struct work_struct *work)
}
handled:
- if (info->detecting)
+ if (info->detecting) {
+ if (arizona->pdata.micd_software_compare)
+ regmap_update_bits(arizona->regmap,
+ ARIZONA_MIC_DETECT_1,
+ ARIZONA_MICD_ENA,
+ ARIZONA_MICD_ENA);
+
queue_delayed_work(system_power_efficient_wq,
&info->micd_timeout_work,
msecs_to_jiffies(info->micd_timeout));
+ }
pm_runtime_mark_last_busy(info->dev);
mutex_unlock(&info->lock);
@@ -991,12 +1066,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
mutex_lock(&info->lock);
- if (arizona->pdata.jd_gpio5) {
+ if (info->micd_clamp) {
mask = ARIZONA_MICD_CLAMP_STS;
- if (arizona->pdata.jd_invert)
- present = ARIZONA_MICD_CLAMP_STS;
- else
- present = 0;
+ present = 0;
} else {
mask = ARIZONA_JD1_STS;
if (arizona->pdata.jd_invert)
@@ -1055,9 +1127,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
msecs_to_jiffies(HPDET_DEBOUNCE));
}
- regmap_update_bits(arizona->regmap,
- ARIZONA_JACK_DETECT_DEBOUNCE,
- ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
+ if (info->micd_clamp || !arizona->pdata.jd_invert)
+ regmap_update_bits(arizona->regmap,
+ ARIZONA_JACK_DETECT_DEBOUNCE,
+ ARIZONA_MICD_CLAMP_DB |
+ ARIZONA_JD1_DB, 0);
} else {
dev_dbg(arizona->dev, "Detected jack removal\n");
@@ -1224,6 +1298,11 @@ static int arizona_extcon_probe(struct platform_device *pdev)
break;
}
break;
+ case WM8998:
+ case WM1814:
+ info->micd_clamp = true;
+ info->hpdet_ip_version = 2;
+ break;
default:
break;
}
@@ -1259,6 +1338,10 @@ static int arizona_extcon_probe(struct platform_device *pdev)
info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
}
+ if (arizona->pdata.gpsw > 0)
+ regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
+ ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
+
if (arizona->pdata.micd_pol_gpio > 0) {
if (info->micd_modes[0].gpio)
mode = GPIOF_OUT_INIT_HIGH;
@@ -1335,7 +1418,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
break;
}
- BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
+ BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
+ ARIZONA_NUM_MICD_BUTTON_LEVELS);
if (arizona->pdata.num_micd_ranges) {
info->micd_ranges = pdata->micd_ranges;
@@ -1368,11 +1452,11 @@ static int arizona_extcon_probe(struct platform_device *pdev)
/* Set up all the buttons the user specified */
for (i = 0; i < info->num_micd_ranges; i++) {
- for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++)
+ for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
break;
- if (j == ARRAY_SIZE(arizona_micd_levels)) {
+ if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
dev_err(arizona->dev, "Unsupported MICD level %d\n",
info->micd_ranges[i].max);
ret = -EINVAL;
@@ -1436,7 +1520,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
pm_runtime_idle(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
- if (arizona->pdata.jd_gpio5) {
+ if (info->micd_clamp) {
jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
} else {
@@ -1541,7 +1625,7 @@ static int arizona_extcon_remove(struct platform_device *pdev)
ARIZONA_MICD_CLAMP_CONTROL,
ARIZONA_MICD_CLAMP_MODE_MASK, 0);
- if (arizona->pdata.jd_gpio5) {
+ if (info->micd_clamp) {
jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
} else {
diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c
index ea962bc547b8..fd55c2f2080a 100644
--- a/drivers/extcon/extcon-axp288.c
+++ b/drivers/extcon/extcon-axp288.c
@@ -102,9 +102,9 @@ enum axp288_extcon_irq {
};
static const unsigned int axp288_extcon_cables[] = {
- EXTCON_SLOW_CHARGER,
- EXTCON_CHARGE_DOWNSTREAM,
- EXTCON_FAST_CHARGER,
+ EXTCON_CHG_USB_SDP,
+ EXTCON_CHG_USB_CDP,
+ EXTCON_CHG_USB_DCP,
EXTCON_NONE,
};
@@ -192,18 +192,18 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
dev_dbg(info->dev, "sdp cable is connecetd\n");
notify_otg = true;
notify_charger = true;
- cable = EXTCON_SLOW_CHARGER;
+ cable = EXTCON_CHG_USB_SDP;
break;
case DET_STAT_CDP:
dev_dbg(info->dev, "cdp cable is connecetd\n");
notify_otg = true;
notify_charger = true;
- cable = EXTCON_CHARGE_DOWNSTREAM;
+ cable = EXTCON_CHG_USB_CDP;
break;
case DET_STAT_DCP:
dev_dbg(info->dev, "dcp cable is connecetd\n");
notify_charger = true;
- cable = EXTCON_FAST_CHARGER;
+ cable = EXTCON_CHG_USB_DCP;
break;
default:
dev_warn(info->dev,
@@ -309,7 +309,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
}
/* Get otg transceiver phy */
- info->otg = usb_get_phy(USB_PHY_TYPE_USB2);
+ info->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR(info->otg)) {
dev_err(&pdev->dev, "failed to get otg transceiver\n");
return PTR_ERR(info->otg);
@@ -318,11 +318,11 @@ static int axp288_extcon_probe(struct platform_device *pdev)
/* Set up gpio control for USB Mux */
if (info->pdata->gpio_mux_cntl) {
gpio = desc_to_gpio(info->pdata->gpio_mux_cntl);
- ret = gpio_request(gpio, "USB_MUX");
+ ret = devm_gpio_request(&pdev->dev, gpio, "USB_MUX");
if (ret < 0) {
dev_err(&pdev->dev,
"failed to request the gpio=%d\n", gpio);
- goto gpio_req_failed;
+ return ret;
}
gpiod_direction_output(info->pdata->gpio_mux_cntl,
EXTCON_GPIO_MUX_SEL_PMIC);
@@ -335,7 +335,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"failed to get virtual interrupt=%d\n", pirq);
ret = info->irq[i];
- goto gpio_req_failed;
+ return ret;
}
ret = devm_request_threaded_irq(&pdev->dev, info->irq[i],
@@ -345,7 +345,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to request interrupt=%d\n",
info->irq[i]);
- goto gpio_req_failed;
+ return ret;
}
}
@@ -353,23 +353,10 @@ static int axp288_extcon_probe(struct platform_device *pdev)
axp288_extcon_enable_irq(info);
return 0;
-
-gpio_req_failed:
- usb_put_phy(info->otg);
- return ret;
-}
-
-static int axp288_extcon_remove(struct platform_device *pdev)
-{
- struct axp288_extcon_info *info = platform_get_drvdata(pdev);
-
- usb_put_phy(info->otg);
- return 0;
}
static struct platform_driver axp288_extcon_driver = {
.probe = axp288_extcon_probe,
- .remove = axp288_extcon_remove,
.driver = {
.name = "axp288_extcon",
},
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 57c24fa52edb..279ff8f6637d 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -1,7 +1,5 @@
/*
- * drivers/extcon/extcon_gpio.c
- *
- * Single-state GPIO extcon driver based on extcon class
+ * extcon_gpio.c - Single-state GPIO extcon driver based on extcon class
*
* Copyright (C) 2008 Google, Inc.
* Author: Mike Lockwood <lockwood@android.com>
@@ -17,12 +15,12 @@
* but WITHOUT 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/extcon.h>
#include <linux/extcon/extcon-gpio.h>
#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -33,14 +31,12 @@
struct gpio_extcon_data {
struct extcon_dev *edev;
- unsigned gpio;
- bool gpio_active_low;
- const char *state_on;
- const char *state_off;
int irq;
struct delayed_work work;
unsigned long debounce_jiffies;
- bool check_on_resume;
+
+ struct gpio_desc *id_gpiod;
+ struct gpio_extcon_pdata *pdata;
};
static void gpio_extcon_work(struct work_struct *work)
@@ -50,93 +46,107 @@ static void gpio_extcon_work(struct work_struct *work)
container_of(to_delayed_work(work), struct gpio_extcon_data,
work);
- state = gpio_get_value(data->gpio);
- if (data->gpio_active_low)
+ state = gpiod_get_value_cansleep(data->id_gpiod);
+ if (data->pdata->gpio_active_low)
state = !state;
extcon_set_state(data->edev, state);
}
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
- struct gpio_extcon_data *extcon_data = dev_id;
+ struct gpio_extcon_data *data = dev_id;
- queue_delayed_work(system_power_efficient_wq, &extcon_data->work,
- extcon_data->debounce_jiffies);
+ queue_delayed_work(system_power_efficient_wq, &data->work,
+ data->debounce_jiffies);
return IRQ_HANDLED;
}
+static int gpio_extcon_init(struct device *dev, struct gpio_extcon_data *data)
+{
+ struct gpio_extcon_pdata *pdata = data->pdata;
+ int ret;
+
+ ret = devm_gpio_request_one(dev, pdata->gpio, GPIOF_DIR_IN,
+ dev_name(dev));
+ if (ret < 0)
+ return ret;
+
+ data->id_gpiod = gpio_to_desc(pdata->gpio);
+ if (!data->id_gpiod)
+ return -EINVAL;
+
+ if (pdata->debounce) {
+ ret = gpiod_set_debounce(data->id_gpiod,
+ pdata->debounce * 1000);
+ if (ret < 0)
+ data->debounce_jiffies =
+ msecs_to_jiffies(pdata->debounce);
+ }
+
+ data->irq = gpiod_to_irq(data->id_gpiod);
+ if (data->irq < 0)
+ return data->irq;
+
+ return 0;
+}
+
static int gpio_extcon_probe(struct platform_device *pdev)
{
- struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct gpio_extcon_data *extcon_data;
+ struct gpio_extcon_pdata *pdata = dev_get_platdata(&pdev->dev);
+ struct gpio_extcon_data *data;
int ret;
if (!pdata)
return -EBUSY;
- if (!pdata->irq_flags) {
- dev_err(&pdev->dev, "IRQ flag is not specified.\n");
+ if (!pdata->irq_flags || pdata->extcon_id > EXTCON_NONE)
return -EINVAL;
- }
- extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
+ data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
GFP_KERNEL);
- if (!extcon_data)
+ if (!data)
return -ENOMEM;
+ data->pdata = pdata;
- extcon_data->edev = devm_extcon_dev_allocate(&pdev->dev, NULL);
- if (IS_ERR(extcon_data->edev)) {
- dev_err(&pdev->dev, "failed to allocate extcon device\n");
- return -ENOMEM;
- }
-
- extcon_data->gpio = pdata->gpio;
- extcon_data->gpio_active_low = pdata->gpio_active_low;
- extcon_data->state_on = pdata->state_on;
- extcon_data->state_off = pdata->state_off;
- extcon_data->check_on_resume = pdata->check_on_resume;
-
- ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
- pdev->name);
+ /* Initialize the gpio */
+ ret = gpio_extcon_init(&pdev->dev, data);
if (ret < 0)
return ret;
- if (pdata->debounce) {
- ret = gpio_set_debounce(extcon_data->gpio,
- pdata->debounce * 1000);
- if (ret < 0)
- extcon_data->debounce_jiffies =
- msecs_to_jiffies(pdata->debounce);
+ /* Allocate the memory of extcon devie and register extcon device */
+ data->edev = devm_extcon_dev_allocate(&pdev->dev, &pdata->extcon_id);
+ if (IS_ERR(data->edev)) {
+ dev_err(&pdev->dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
}
- ret = devm_extcon_dev_register(&pdev->dev, extcon_data->edev);
+ ret = devm_extcon_dev_register(&pdev->dev, data->edev);
if (ret < 0)
return ret;
- INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work);
-
- extcon_data->irq = gpio_to_irq(extcon_data->gpio);
- if (extcon_data->irq < 0)
- return extcon_data->irq;
+ INIT_DELAYED_WORK(&data->work, gpio_extcon_work);
- ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler,
- pdata->irq_flags, pdev->name,
- extcon_data);
+ /*
+ * Request the interrput of gpio to detect whether external connector
+ * is attached or detached.
+ */
+ ret = devm_request_any_context_irq(&pdev->dev, data->irq,
+ gpio_irq_handler, pdata->irq_flags,
+ pdev->name, data);
if (ret < 0)
return ret;
- platform_set_drvdata(pdev, extcon_data);
+ platform_set_drvdata(pdev, data);
/* Perform initial detection */
- gpio_extcon_work(&extcon_data->work.work);
+ gpio_extcon_work(&data->work.work);
return 0;
}
static int gpio_extcon_remove(struct platform_device *pdev)
{
- struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
+ struct gpio_extcon_data *data = platform_get_drvdata(pdev);
- cancel_delayed_work_sync(&extcon_data->work);
- free_irq(extcon_data->irq, extcon_data);
+ cancel_delayed_work_sync(&data->work);
return 0;
}
@@ -144,12 +154,12 @@ static int gpio_extcon_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int gpio_extcon_resume(struct device *dev)
{
- struct gpio_extcon_data *extcon_data;
+ struct gpio_extcon_data *data;
- extcon_data = dev_get_drvdata(dev);
- if (extcon_data->check_on_resume)
+ data = dev_get_drvdata(dev);
+ if (data->pdata->check_on_resume)
queue_delayed_work(system_power_efficient_wq,
- &extcon_data->work, extcon_data->debounce_jiffies);
+ &data->work, data->debounce_jiffies);
return 0;
}
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index df0659d98e5a..601dbd996487 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -150,10 +150,10 @@ enum max14577_muic_acc_type {
static const unsigned int max14577_extcon_cable[] = {
EXTCON_USB,
- EXTCON_TA,
- EXTCON_FAST_CHARGER,
- EXTCON_SLOW_CHARGER,
- EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_CHG_USB_DCP,
+ EXTCON_CHG_USB_FAST,
+ EXTCON_CHG_USB_SLOW,
+ EXTCON_CHG_USB_CDP,
EXTCON_JIG,
EXTCON_NONE,
};
@@ -456,18 +456,19 @@ static int max14577_muic_chg_handler(struct max14577_muic_info *info)
extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
break;
case MAX14577_CHARGER_TYPE_DEDICATED_CHG:
- extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ attached);
break;
case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_CDP,
attached);
break;
case MAX14577_CHARGER_TYPE_SPECIAL_500MA:
- extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SLOW,
attached);
break;
case MAX14577_CHARGER_TYPE_SPECIAL_1A:
- extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_FAST,
attached);
break;
case MAX14577_CHARGER_TYPE_NONE:
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 35b9e118b2fb..44c499e1beee 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -204,11 +204,11 @@ enum max77693_muic_acc_type {
static const unsigned int max77693_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
- EXTCON_TA,
- EXTCON_FAST_CHARGER,
- EXTCON_SLOW_CHARGER,
- EXTCON_CHARGE_DOWNSTREAM,
- EXTCON_MHL,
+ EXTCON_CHG_USB_DCP,
+ EXTCON_CHG_USB_FAST,
+ EXTCON_CHG_USB_SLOW,
+ EXTCON_CHG_USB_CDP,
+ EXTCON_DISP_MHL,
EXTCON_JIG,
EXTCON_DOCK,
EXTCON_NONE,
@@ -505,7 +505,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
return ret;
extcon_set_cable_state_(info->edev, EXTCON_DOCK, attached);
- extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DISP_MHL, attached);
goto out;
case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */
dock_id = EXTCON_DOCK;
@@ -605,7 +605,7 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_GND_MHL:
case MAX77693_MUIC_GND_MHL_VB:
/* MHL or MHL with USB/TA cable */
- extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DISP_MHL, attached);
break;
default:
dev_err(info->dev, "failed to detect %s cable of gnd type\n",
@@ -801,10 +801,11 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
* - Support charging through micro-usb port without
* data connection
*/
- extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ attached);
if (!cable_attached)
- extcon_set_cable_state_(info->edev, EXTCON_MHL,
- cable_attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_DISP_MHL, cable_attached);
break;
}
@@ -862,7 +863,7 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
extcon_set_cable_state_(info->edev, EXTCON_DOCK,
attached);
- extcon_set_cable_state_(info->edev, EXTCON_MHL,
+ extcon_set_cable_state_(info->edev, EXTCON_DISP_MHL,
attached);
break;
}
@@ -901,20 +902,21 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
break;
case MAX77693_CHARGER_TYPE_DEDICATED_CHG:
/* Only TA cable */
- extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ attached);
break;
}
break;
case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_CDP,
attached);
break;
case MAX77693_CHARGER_TYPE_APPLE_500MA:
- extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SLOW,
attached);
break;
case MAX77693_CHARGER_TYPE_APPLE_1A_2A:
- extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_FAST,
attached);
break;
case MAX77693_CHARGER_TYPE_DEAD_BATTERY:
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
index fdd928542c19..9f9ea334399c 100644
--- a/drivers/extcon/extcon-max77843.c
+++ b/drivers/extcon/extcon-max77843.c
@@ -122,11 +122,11 @@ enum max77843_muic_charger_type {
static const unsigned int max77843_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
- EXTCON_TA,
- EXTCON_CHARGE_DOWNSTREAM,
- EXTCON_FAST_CHARGER,
- EXTCON_SLOW_CHARGER,
- EXTCON_MHL,
+ EXTCON_CHG_USB_DCP,
+ EXTCON_CHG_USB_CDP,
+ EXTCON_CHG_USB_FAST,
+ EXTCON_CHG_USB_SLOW,
+ EXTCON_DISP_MHL,
EXTCON_JIG,
EXTCON_NONE,
};
@@ -355,7 +355,7 @@ static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DISP_MHL, attached);
break;
default:
dev_err(info->dev, "failed to detect %s accessory(gnd:0x%x)\n",
@@ -494,7 +494,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_CDP,
attached);
break;
case MAX77843_MUIC_CHG_DEDICATED:
@@ -504,7 +504,8 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ attached);
break;
case MAX77843_MUIC_CHG_SPECIAL_500MA:
ret = max77843_muic_set_path(info,
@@ -513,7 +514,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SLOW,
attached);
break;
case MAX77843_MUIC_CHG_SPECIAL_1A:
@@ -523,7 +524,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_FAST,
attached);
break;
case MAX77843_MUIC_CHG_GND:
@@ -532,9 +533,11 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
/* Charger cable on MHL accessory is attach or detach */
if (gnd_type == MAX77843_MUIC_GND_MHL_VB)
- extcon_set_cable_state_(info->edev, EXTCON_TA, true);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ true);
else if (gnd_type == MAX77843_MUIC_GND_MHL)
- extcon_set_cable_state_(info->edev, EXTCON_TA, false);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ false);
break;
case MAX77843_MUIC_CHG_NONE:
break;
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 7b1ef200b121..b2b13b3dce14 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -148,11 +148,11 @@ struct max8997_muic_info {
static const unsigned int max8997_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
- EXTCON_TA,
- EXTCON_FAST_CHARGER,
- EXTCON_SLOW_CHARGER,
- EXTCON_CHARGE_DOWNSTREAM,
- EXTCON_MHL,
+ EXTCON_CHG_USB_DCP,
+ EXTCON_CHG_USB_FAST,
+ EXTCON_CHG_USB_SLOW,
+ EXTCON_CHG_USB_CDP,
+ EXTCON_DISP_MHL,
EXTCON_DOCK,
EXTCON_JIG,
EXTCON_NONE,
@@ -403,7 +403,7 @@ static int max8997_muic_adc_handler(struct max8997_muic_info *info)
return ret;
break;
case MAX8997_MUIC_ADC_MHL:
- extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DISP_MHL, attached);
break;
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
@@ -486,18 +486,19 @@ static int max8997_muic_chg_handler(struct max8997_muic_info *info)
}
break;
case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_CDP,
attached);
break;
case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
- extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP,
+ attached);
break;
case MAX8997_CHARGER_TYPE_500MA:
- extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SLOW,
attached);
break;
case MAX8997_CHARGER_TYPE_1A:
- extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_FAST,
attached);
break;
default:
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c
index 11592e980bc1..36bf1d63791c 100644
--- a/drivers/extcon/extcon-rt8973a.c
+++ b/drivers/extcon/extcon-rt8973a.c
@@ -93,7 +93,7 @@ static struct reg_data rt8973a_reg_data[] = {
static const unsigned int rt8973a_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
- EXTCON_TA,
+ EXTCON_CHG_USB_DCP,
EXTCON_JIG,
EXTCON_NONE,
};
@@ -333,7 +333,7 @@ static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info,
con_sw = DM_DP_SWITCH_USB;
break;
case RT8973A_MUIC_ADC_TA:
- id = EXTCON_TA;
+ id = EXTCON_CHG_USB_DCP;
con_sw = DM_DP_SWITCH_OPEN;
break;
case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
@@ -594,7 +594,7 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < info->num_muic_irqs; i++) {
struct muic_irq *muic_irq = &info->muic_irqs[i];
- unsigned int virq = 0;
+ int virq = 0;
virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
if (virq <= 0)
@@ -658,6 +658,7 @@ static const struct of_device_id rt8973a_dt_match[] = {
{ .compatible = "richtek,rt8973a-muic" },
{ },
};
+MODULE_DEVICE_TABLE(of, rt8973a_dt_match);
#ifdef CONFIG_PM_SLEEP
static int rt8973a_muic_suspend(struct device *dev)
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
index 0ffefefa2e26..7aac3cc7efd7 100644
--- a/drivers/extcon/extcon-sm5502.c
+++ b/drivers/extcon/extcon-sm5502.c
@@ -95,7 +95,7 @@ static struct reg_data sm5502_reg_data[] = {
static const unsigned int sm5502_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
- EXTCON_TA,
+ EXTCON_CHG_USB_DCP,
EXTCON_NONE,
};
@@ -389,7 +389,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB;
break;
case SM5502_MUIC_ADC_OPEN_TA:
- id = EXTCON_TA;
+ id = EXTCON_CHG_USB_DCP;
con_sw = DM_DP_SWITCH_OPEN;
vbus_sw = VBUSIN_SWITCH_VBUSOUT;
break;
@@ -586,7 +586,7 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < info->num_muic_irqs; i++) {
struct muic_irq *muic_irq = &info->muic_irqs[i];
- unsigned int virq = 0;
+ int virq = 0;
virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
if (virq <= 0)
@@ -650,6 +650,7 @@ static const struct of_device_id sm5502_dt_match[] = {
{ .compatible = "siliconmitus,sm5502-muic" },
{ },
};
+MODULE_DEVICE_TABLE(of, sm5502_dt_match);
#ifdef CONFIG_PM_SLEEP
static int sm5502_muic_suspend(struct device *dev)
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 8dd0af1d50bc..21a123cadf78 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -39,37 +39,40 @@
#define CABLE_NAME_MAX 30
static const char *extcon_name[] = {
- [EXTCON_NONE] = "NONE",
+ [EXTCON_NONE] = "NONE",
/* USB external connector */
- [EXTCON_USB] = "USB",
- [EXTCON_USB_HOST] = "USB-HOST",
-
- /* Charger external connector */
- [EXTCON_TA] = "TA",
- [EXTCON_FAST_CHARGER] = "FAST-CHARGER",
- [EXTCON_SLOW_CHARGER] = "SLOW-CHARGER",
- [EXTCON_CHARGE_DOWNSTREAM] = "CHARGE-DOWNSTREAM",
-
- /* Audio/Video external connector */
- [EXTCON_LINE_IN] = "LINE-IN",
- [EXTCON_LINE_OUT] = "LINE-OUT",
- [EXTCON_MICROPHONE] = "MICROPHONE",
- [EXTCON_HEADPHONE] = "HEADPHONE",
-
- [EXTCON_HDMI] = "HDMI",
- [EXTCON_MHL] = "MHL",
- [EXTCON_DVI] = "DVI",
- [EXTCON_VGA] = "VGA",
- [EXTCON_SPDIF_IN] = "SPDIF-IN",
- [EXTCON_SPDIF_OUT] = "SPDIF-OUT",
- [EXTCON_VIDEO_IN] = "VIDEO-IN",
- [EXTCON_VIDEO_OUT] = "VIDEO-OUT",
-
- /* Etc external connector */
- [EXTCON_DOCK] = "DOCK",
- [EXTCON_JIG] = "JIG",
- [EXTCON_MECHANICAL] = "MECHANICAL",
+ [EXTCON_USB] = "USB",
+ [EXTCON_USB_HOST] = "USB-HOST",
+
+ /* Charging external connector */
+ [EXTCON_CHG_USB_SDP] = "SDP",
+ [EXTCON_CHG_USB_DCP] = "DCP",
+ [EXTCON_CHG_USB_CDP] = "CDP",
+ [EXTCON_CHG_USB_ACA] = "ACA",
+ [EXTCON_CHG_USB_FAST] = "FAST-CHARGER",
+ [EXTCON_CHG_USB_SLOW] = "SLOW-CHARGER",
+
+ /* Jack external connector */
+ [EXTCON_JACK_MICROPHONE] = "MICROPHONE",
+ [EXTCON_JACK_HEADPHONE] = "HEADPHONE",
+ [EXTCON_JACK_LINE_IN] = "LINE-IN",
+ [EXTCON_JACK_LINE_OUT] = "LINE-OUT",
+ [EXTCON_JACK_VIDEO_IN] = "VIDEO-IN",
+ [EXTCON_JACK_VIDEO_OUT] = "VIDEO-OUT",
+ [EXTCON_JACK_SPDIF_IN] = "SPDIF-IN",
+ [EXTCON_JACK_SPDIF_OUT] = "SPDIF-OUT",
+
+ /* Display external connector */
+ [EXTCON_DISP_HDMI] = "HDMI",
+ [EXTCON_DISP_MHL] = "MHL",
+ [EXTCON_DISP_DVI] = "DVI",
+ [EXTCON_DISP_VGA] = "VGA",
+
+ /* Miscellaneous external connector */
+ [EXTCON_DOCK] = "DOCK",
+ [EXTCON_JIG] = "JIG",
+ [EXTCON_MECHANICAL] = "MECHANICAL",
NULL,
};
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 2a3973a7c441..36a7c2d89a01 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -486,7 +486,7 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
static int add_client_resource(struct client *client,
struct client_resource *resource, gfp_t gfp_mask)
{
- bool preload = !!(gfp_mask & __GFP_WAIT);
+ bool preload = gfpflags_allow_blocking(gfp_mask);
unsigned long flags;
int ret;
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index f51d376d10ba..c2f5117fd8cb 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -3675,6 +3675,11 @@ static int pci_probe(struct pci_dev *dev,
reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+ /* JMicron JMB38x often shows 0 at first read, just ignore it */
+ if (!ohci->it_context_support) {
+ ohci_notice(ohci, "overriding IsoXmitIntMask\n");
+ ohci->it_context_support = 0xf;
+ }
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
ohci->it_context_mask = ohci->it_context_support;
ohci->n_it = hweight32(ohci->it_context_mask);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 665efca59487..cf478fe6b335 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -8,6 +8,25 @@ menu "Firmware Drivers"
config ARM_PSCI_FW
bool
+config ARM_SCPI_PROTOCOL
+ tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
+ depends on ARM_MHU
+ help
+ System Control and Power Interface (SCPI) Message Protocol is
+ defined for the purpose of communication between the Application
+ Cores(AP) and the System Control Processor(SCP). The MHU peripheral
+ provides a mechanism for inter-processor communication between SCP
+ and AP.
+
+ SCP controls most of the power managament on the Application
+ Processors. It offers control and management of: the core/cluster
+ power states, various power domain DVFS including the core/cluster,
+ certain system clocks configuration, thermal sensors and many
+ others.
+
+ This protocol library provides interface for all the client drivers
+ making use of the features offered by the SCP.
+
config EDD
tristate "BIOS Enhanced Disk Drive calls determine boot disk"
depends on X86
@@ -135,6 +154,13 @@ config ISCSI_IBFT
detect iSCSI boot parameters dynamically during system boot, say Y.
Otherwise, say N.
+config RASPBERRYPI_FIRMWARE
+ tristate "Raspberry Pi Firmware Driver"
+ depends on BCM2835_MBOX
+ help
+ This option enables support for communicating with the firmware on the
+ Raspberry Pi.
+
config QCOM_SCM
bool
depends on ARM || ARM64
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 2ee83474a3c1..48dd4175297e 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -2,6 +2,7 @@
# Makefile for the linux kernel.
#
obj-$(CONFIG_ARM_PSCI_FW) += psci.o
+obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o
obj-$(CONFIG_DMI) += dmi_scan.o
obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
obj-$(CONFIG_EDD) += edd.o
@@ -12,10 +13,11 @@ obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
+obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_QCOM_SCM) += qcom_scm.o
obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o
obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
-CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
obj-y += broadcom/
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
new file mode 100644
index 000000000000..6174db80c663
--- /dev/null
+++ b/drivers/firmware/arm_scpi.c
@@ -0,0 +1,771 @@
+/*
+ * System Control and Power Interface (SCPI) Message Protocol driver
+ *
+ * SCPI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ *
+ * 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/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitmap.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/printk.h>
+#include <linux/scpi_protocol.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/spinlock.h>
+
+#define CMD_ID_SHIFT 0
+#define CMD_ID_MASK 0x7f
+#define CMD_TOKEN_ID_SHIFT 8
+#define CMD_TOKEN_ID_MASK 0xff
+#define CMD_DATA_SIZE_SHIFT 16
+#define CMD_DATA_SIZE_MASK 0x1ff
+#define PACK_SCPI_CMD(cmd_id, tx_sz) \
+ ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
+ (((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
+#define ADD_SCPI_TOKEN(cmd, token) \
+ ((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
+
+#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
+#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
+#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK)
+
+#define SCPI_SLOT 0
+
+#define MAX_DVFS_DOMAINS 8
+#define MAX_DVFS_OPPS 8
+#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16)
+#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff)
+
+#define PROTOCOL_REV_MINOR_BITS 16
+#define PROTOCOL_REV_MINOR_MASK ((1U << PROTOCOL_REV_MINOR_BITS) - 1)
+#define PROTOCOL_REV_MAJOR(x) ((x) >> PROTOCOL_REV_MINOR_BITS)
+#define PROTOCOL_REV_MINOR(x) ((x) & PROTOCOL_REV_MINOR_MASK)
+
+#define FW_REV_MAJOR_BITS 24
+#define FW_REV_MINOR_BITS 16
+#define FW_REV_PATCH_MASK ((1U << FW_REV_MINOR_BITS) - 1)
+#define FW_REV_MINOR_MASK ((1U << FW_REV_MAJOR_BITS) - 1)
+#define FW_REV_MAJOR(x) ((x) >> FW_REV_MAJOR_BITS)
+#define FW_REV_MINOR(x) (((x) & FW_REV_MINOR_MASK) >> FW_REV_MINOR_BITS)
+#define FW_REV_PATCH(x) ((x) & FW_REV_PATCH_MASK)
+
+#define MAX_RX_TIMEOUT (msecs_to_jiffies(20))
+
+enum scpi_error_codes {
+ SCPI_SUCCESS = 0, /* Success */
+ SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
+ SCPI_ERR_ALIGN = 2, /* Invalid alignment */
+ SCPI_ERR_SIZE = 3, /* Invalid size */
+ SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
+ SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
+ SCPI_ERR_RANGE = 6, /* Value out of range */
+ SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
+ SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
+ SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
+ SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
+ SCPI_ERR_DEVICE = 11, /* Device error */
+ SCPI_ERR_BUSY = 12, /* Device busy */
+ SCPI_ERR_MAX
+};
+
+enum scpi_std_cmd {
+ SCPI_CMD_INVALID = 0x00,
+ SCPI_CMD_SCPI_READY = 0x01,
+ SCPI_CMD_SCPI_CAPABILITIES = 0x02,
+ SCPI_CMD_SET_CSS_PWR_STATE = 0x03,
+ SCPI_CMD_GET_CSS_PWR_STATE = 0x04,
+ SCPI_CMD_SET_SYS_PWR_STATE = 0x05,
+ SCPI_CMD_SET_CPU_TIMER = 0x06,
+ SCPI_CMD_CANCEL_CPU_TIMER = 0x07,
+ SCPI_CMD_DVFS_CAPABILITIES = 0x08,
+ SCPI_CMD_GET_DVFS_INFO = 0x09,
+ SCPI_CMD_SET_DVFS = 0x0a,
+ SCPI_CMD_GET_DVFS = 0x0b,
+ SCPI_CMD_GET_DVFS_STAT = 0x0c,
+ SCPI_CMD_CLOCK_CAPABILITIES = 0x0d,
+ SCPI_CMD_GET_CLOCK_INFO = 0x0e,
+ SCPI_CMD_SET_CLOCK_VALUE = 0x0f,
+ SCPI_CMD_GET_CLOCK_VALUE = 0x10,
+ SCPI_CMD_PSU_CAPABILITIES = 0x11,
+ SCPI_CMD_GET_PSU_INFO = 0x12,
+ SCPI_CMD_SET_PSU = 0x13,
+ SCPI_CMD_GET_PSU = 0x14,
+ SCPI_CMD_SENSOR_CAPABILITIES = 0x15,
+ SCPI_CMD_SENSOR_INFO = 0x16,
+ SCPI_CMD_SENSOR_VALUE = 0x17,
+ SCPI_CMD_SENSOR_CFG_PERIODIC = 0x18,
+ SCPI_CMD_SENSOR_CFG_BOUNDS = 0x19,
+ SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1a,
+ SCPI_CMD_SET_DEVICE_PWR_STATE = 0x1b,
+ SCPI_CMD_GET_DEVICE_PWR_STATE = 0x1c,
+ SCPI_CMD_COUNT
+};
+
+struct scpi_xfer {
+ u32 slot; /* has to be first element */
+ u32 cmd;
+ u32 status;
+ const void *tx_buf;
+ void *rx_buf;
+ unsigned int tx_len;
+ unsigned int rx_len;
+ struct list_head node;
+ struct completion done;
+};
+
+struct scpi_chan {
+ struct mbox_client cl;
+ struct mbox_chan *chan;
+ void __iomem *tx_payload;
+ void __iomem *rx_payload;
+ struct list_head rx_pending;
+ struct list_head xfers_list;
+ struct scpi_xfer *xfers;
+ spinlock_t rx_lock; /* locking for the rx pending list */
+ struct mutex xfers_lock;
+ u8 token;
+};
+
+struct scpi_drvinfo {
+ u32 protocol_version;
+ u32 firmware_version;
+ int num_chans;
+ atomic_t next_chan;
+ struct scpi_ops *scpi_ops;
+ struct scpi_chan *channels;
+ struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
+};
+
+/*
+ * The SCP firmware only executes in little-endian mode, so any buffers
+ * shared through SCPI should have their contents converted to little-endian
+ */
+struct scpi_shared_mem {
+ __le32 command;
+ __le32 status;
+ u8 payload[0];
+} __packed;
+
+struct scp_capabilities {
+ __le32 protocol_version;
+ __le32 event_version;
+ __le32 platform_version;
+ __le32 commands[4];
+} __packed;
+
+struct clk_get_info {
+ __le16 id;
+ __le16 flags;
+ __le32 min_rate;
+ __le32 max_rate;
+ u8 name[20];
+} __packed;
+
+struct clk_get_value {
+ __le32 rate;
+} __packed;
+
+struct clk_set_value {
+ __le16 id;
+ __le16 reserved;
+ __le32 rate;
+} __packed;
+
+struct dvfs_info {
+ __le32 header;
+ struct {
+ __le32 freq;
+ __le32 m_volt;
+ } opps[MAX_DVFS_OPPS];
+} __packed;
+
+struct dvfs_get {
+ u8 index;
+} __packed;
+
+struct dvfs_set {
+ u8 domain;
+ u8 index;
+} __packed;
+
+struct sensor_capabilities {
+ __le16 sensors;
+} __packed;
+
+struct _scpi_sensor_info {
+ __le16 sensor_id;
+ u8 class;
+ u8 trigger_type;
+ char name[20];
+};
+
+struct sensor_value {
+ __le32 val;
+} __packed;
+
+static struct scpi_drvinfo *scpi_info;
+
+static int scpi_linux_errmap[SCPI_ERR_MAX] = {
+ /* better than switch case as long as return value is continuous */
+ 0, /* SCPI_SUCCESS */
+ -EINVAL, /* SCPI_ERR_PARAM */
+ -ENOEXEC, /* SCPI_ERR_ALIGN */
+ -EMSGSIZE, /* SCPI_ERR_SIZE */
+ -EINVAL, /* SCPI_ERR_HANDLER */
+ -EACCES, /* SCPI_ERR_ACCESS */
+ -ERANGE, /* SCPI_ERR_RANGE */
+ -ETIMEDOUT, /* SCPI_ERR_TIMEOUT */
+ -ENOMEM, /* SCPI_ERR_NOMEM */
+ -EINVAL, /* SCPI_ERR_PWRSTATE */
+ -EOPNOTSUPP, /* SCPI_ERR_SUPPORT */
+ -EIO, /* SCPI_ERR_DEVICE */
+ -EBUSY, /* SCPI_ERR_BUSY */
+};
+
+static inline int scpi_to_linux_errno(int errno)
+{
+ if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
+ return scpi_linux_errmap[errno];
+ return -EIO;
+}
+
+static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
+{
+ unsigned long flags;
+ struct scpi_xfer *t, *match = NULL;
+
+ spin_lock_irqsave(&ch->rx_lock, flags);
+ if (list_empty(&ch->rx_pending)) {
+ spin_unlock_irqrestore(&ch->rx_lock, flags);
+ return;
+ }
+
+ list_for_each_entry(t, &ch->rx_pending, node)
+ if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
+ list_del(&t->node);
+ match = t;
+ break;
+ }
+ /* check if wait_for_completion is in progress or timed-out */
+ if (match && !completion_done(&match->done)) {
+ struct scpi_shared_mem *mem = ch->rx_payload;
+ unsigned int len = min(match->rx_len, CMD_SIZE(cmd));
+
+ match->status = le32_to_cpu(mem->status);
+ memcpy_fromio(match->rx_buf, mem->payload, len);
+ if (match->rx_len > len)
+ memset(match->rx_buf + len, 0, match->rx_len - len);
+ complete(&match->done);
+ }
+ spin_unlock_irqrestore(&ch->rx_lock, flags);
+}
+
+static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
+{
+ struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
+ struct scpi_shared_mem *mem = ch->rx_payload;
+ u32 cmd = le32_to_cpu(mem->command);
+
+ scpi_process_cmd(ch, cmd);
+}
+
+static void scpi_tx_prepare(struct mbox_client *c, void *msg)
+{
+ unsigned long flags;
+ struct scpi_xfer *t = msg;
+ struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
+ struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
+
+ if (t->tx_buf)
+ memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
+ if (t->rx_buf) {
+ if (!(++ch->token))
+ ++ch->token;
+ ADD_SCPI_TOKEN(t->cmd, ch->token);
+ spin_lock_irqsave(&ch->rx_lock, flags);
+ list_add_tail(&t->node, &ch->rx_pending);
+ spin_unlock_irqrestore(&ch->rx_lock, flags);
+ }
+ mem->command = cpu_to_le32(t->cmd);
+}
+
+static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
+{
+ struct scpi_xfer *t;
+
+ mutex_lock(&ch->xfers_lock);
+ if (list_empty(&ch->xfers_list)) {
+ mutex_unlock(&ch->xfers_lock);
+ return NULL;
+ }
+ t = list_first_entry(&ch->xfers_list, struct scpi_xfer, node);
+ list_del(&t->node);
+ mutex_unlock(&ch->xfers_lock);
+ return t;
+}
+
+static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
+{
+ mutex_lock(&ch->xfers_lock);
+ list_add_tail(&t->node, &ch->xfers_list);
+ mutex_unlock(&ch->xfers_lock);
+}
+
+static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+ void *rx_buf, unsigned int rx_len)
+{
+ int ret;
+ u8 chan;
+ struct scpi_xfer *msg;
+ struct scpi_chan *scpi_chan;
+
+ chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
+ scpi_chan = scpi_info->channels + chan;
+
+ msg = get_scpi_xfer(scpi_chan);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->slot = BIT(SCPI_SLOT);
+ msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+ msg->tx_buf = tx_buf;
+ msg->tx_len = tx_len;
+ msg->rx_buf = rx_buf;
+ msg->rx_len = rx_len;
+ init_completion(&msg->done);
+
+ ret = mbox_send_message(scpi_chan->chan, msg);
+ if (ret < 0 || !rx_buf)
+ goto out;
+
+ if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
+ ret = -ETIMEDOUT;
+ else
+ /* first status word */
+ ret = le32_to_cpu(msg->status);
+out:
+ if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */
+ scpi_process_cmd(scpi_chan, msg->cmd);
+
+ put_scpi_xfer(msg, scpi_chan);
+ /* SCPI error codes > 0, translate them to Linux scale*/
+ return ret > 0 ? scpi_to_linux_errno(ret) : ret;
+}
+
+static u32 scpi_get_version(void)
+{
+ return scpi_info->protocol_version;
+}
+
+static int
+scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
+{
+ int ret;
+ struct clk_get_info clk;
+ __le16 le_clk_id = cpu_to_le16(clk_id);
+
+ ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
+ sizeof(le_clk_id), &clk, sizeof(clk));
+ if (!ret) {
+ *min = le32_to_cpu(clk.min_rate);
+ *max = le32_to_cpu(clk.max_rate);
+ }
+ return ret;
+}
+
+static unsigned long scpi_clk_get_val(u16 clk_id)
+{
+ int ret;
+ struct clk_get_value clk;
+ __le16 le_clk_id = cpu_to_le16(clk_id);
+
+ ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+ sizeof(le_clk_id), &clk, sizeof(clk));
+ return ret ? ret : le32_to_cpu(clk.rate);
+}
+
+static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+ int stat;
+ struct clk_set_value clk = {
+ .id = cpu_to_le16(clk_id),
+ .rate = cpu_to_le32(rate)
+ };
+
+ return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+ &stat, sizeof(stat));
+}
+
+static int scpi_dvfs_get_idx(u8 domain)
+{
+ int ret;
+ struct dvfs_get dvfs;
+
+ ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
+ &dvfs, sizeof(dvfs));
+ return ret ? ret : dvfs.index;
+}
+
+static int scpi_dvfs_set_idx(u8 domain, u8 index)
+{
+ int stat;
+ struct dvfs_set dvfs = {domain, index};
+
+ return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
+ &stat, sizeof(stat));
+}
+
+static int opp_cmp_func(const void *opp1, const void *opp2)
+{
+ const struct scpi_opp *t1 = opp1, *t2 = opp2;
+
+ return t1->freq - t2->freq;
+}
+
+static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
+{
+ struct scpi_dvfs_info *info;
+ struct scpi_opp *opp;
+ struct dvfs_info buf;
+ int ret, i;
+
+ if (domain >= MAX_DVFS_DOMAINS)
+ return ERR_PTR(-EINVAL);
+
+ if (scpi_info->dvfs[domain]) /* data already populated */
+ return scpi_info->dvfs[domain];
+
+ ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
+ &buf, sizeof(buf));
+
+ if (ret)
+ return ERR_PTR(ret);
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ info->count = DVFS_OPP_COUNT(buf.header);
+ info->latency = DVFS_LATENCY(buf.header) * 1000; /* uS to nS */
+
+ info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL);
+ if (!info->opps) {
+ kfree(info);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (i = 0, opp = info->opps; i < info->count; i++, opp++) {
+ opp->freq = le32_to_cpu(buf.opps[i].freq);
+ opp->m_volt = le32_to_cpu(buf.opps[i].m_volt);
+ }
+
+ sort(info->opps, info->count, sizeof(*opp), opp_cmp_func, NULL);
+
+ scpi_info->dvfs[domain] = info;
+ return info;
+}
+
+static int scpi_sensor_get_capability(u16 *sensors)
+{
+ struct sensor_capabilities cap_buf;
+ int ret;
+
+ ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
+ sizeof(cap_buf));
+ if (!ret)
+ *sensors = le16_to_cpu(cap_buf.sensors);
+
+ return ret;
+}
+
+static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
+{
+ __le16 id = cpu_to_le16(sensor_id);
+ struct _scpi_sensor_info _info;
+ int ret;
+
+ ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+ &_info, sizeof(_info));
+ if (!ret) {
+ memcpy(info, &_info, sizeof(*info));
+ info->sensor_id = le16_to_cpu(_info.sensor_id);
+ }
+
+ return ret;
+}
+
+int scpi_sensor_get_value(u16 sensor, u32 *val)
+{
+ struct sensor_value buf;
+ int ret;
+
+ ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &sensor, sizeof(sensor),
+ &buf, sizeof(buf));
+ if (!ret)
+ *val = le32_to_cpu(buf.val);
+
+ return ret;
+}
+
+static struct scpi_ops scpi_ops = {
+ .get_version = scpi_get_version,
+ .clk_get_range = scpi_clk_get_range,
+ .clk_get_val = scpi_clk_get_val,
+ .clk_set_val = scpi_clk_set_val,
+ .dvfs_get_idx = scpi_dvfs_get_idx,
+ .dvfs_set_idx = scpi_dvfs_set_idx,
+ .dvfs_get_info = scpi_dvfs_get_info,
+ .sensor_get_capability = scpi_sensor_get_capability,
+ .sensor_get_info = scpi_sensor_get_info,
+ .sensor_get_value = scpi_sensor_get_value,
+};
+
+struct scpi_ops *get_scpi_ops(void)
+{
+ return scpi_info ? scpi_info->scpi_ops : NULL;
+}
+EXPORT_SYMBOL_GPL(get_scpi_ops);
+
+static int scpi_init_versions(struct scpi_drvinfo *info)
+{
+ int ret;
+ struct scp_capabilities caps;
+
+ ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+ &caps, sizeof(caps));
+ if (!ret) {
+ info->protocol_version = le32_to_cpu(caps.protocol_version);
+ info->firmware_version = le32_to_cpu(caps.platform_version);
+ }
+ return ret;
+}
+
+static ssize_t protocol_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d.%d\n",
+ PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
+ PROTOCOL_REV_MINOR(scpi_info->protocol_version));
+}
+static DEVICE_ATTR_RO(protocol_version);
+
+static ssize_t firmware_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d.%d.%d\n",
+ FW_REV_MAJOR(scpi_info->firmware_version),
+ FW_REV_MINOR(scpi_info->firmware_version),
+ FW_REV_PATCH(scpi_info->firmware_version));
+}
+static DEVICE_ATTR_RO(firmware_version);
+
+static struct attribute *versions_attrs[] = {
+ &dev_attr_firmware_version.attr,
+ &dev_attr_protocol_version.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(versions);
+
+static void
+scpi_free_channels(struct device *dev, struct scpi_chan *pchan, int count)
+{
+ int i;
+
+ for (i = 0; i < count && pchan->chan; i++, pchan++) {
+ mbox_free_channel(pchan->chan);
+ devm_kfree(dev, pchan->xfers);
+ devm_iounmap(dev, pchan->rx_payload);
+ }
+}
+
+static int scpi_remove(struct platform_device *pdev)
+{
+ int i;
+ struct device *dev = &pdev->dev;
+ struct scpi_drvinfo *info = platform_get_drvdata(pdev);
+
+ scpi_info = NULL; /* stop exporting SCPI ops through get_scpi_ops */
+
+ of_platform_depopulate(dev);
+ sysfs_remove_groups(&dev->kobj, versions_groups);
+ scpi_free_channels(dev, info->channels, info->num_chans);
+ platform_set_drvdata(pdev, NULL);
+
+ for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) {
+ kfree(info->dvfs[i]->opps);
+ kfree(info->dvfs[i]);
+ }
+ devm_kfree(dev, info->channels);
+ devm_kfree(dev, info);
+
+ return 0;
+}
+
+#define MAX_SCPI_XFERS 10
+static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
+{
+ int i;
+ struct scpi_xfer *xfers;
+
+ xfers = devm_kzalloc(dev, MAX_SCPI_XFERS * sizeof(*xfers), GFP_KERNEL);
+ if (!xfers)
+ return -ENOMEM;
+
+ ch->xfers = xfers;
+ for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++)
+ list_add_tail(&xfers->node, &ch->xfers_list);
+ return 0;
+}
+
+static int scpi_probe(struct platform_device *pdev)
+{
+ int count, idx, ret;
+ struct resource res;
+ struct scpi_chan *scpi_chan;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+
+ scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
+ if (!scpi_info)
+ return -ENOMEM;
+
+ count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+ if (count < 0) {
+ dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
+ return -ENODEV;
+ }
+
+ scpi_chan = devm_kcalloc(dev, count, sizeof(*scpi_chan), GFP_KERNEL);
+ if (!scpi_chan)
+ return -ENOMEM;
+
+ for (idx = 0; idx < count; idx++) {
+ resource_size_t size;
+ struct scpi_chan *pchan = scpi_chan + idx;
+ struct mbox_client *cl = &pchan->cl;
+ struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
+
+ if (of_address_to_resource(shmem, 0, &res)) {
+ dev_err(dev, "failed to get SCPI payload mem resource\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ size = resource_size(&res);
+ pchan->rx_payload = devm_ioremap(dev, res.start, size);
+ if (!pchan->rx_payload) {
+ dev_err(dev, "failed to ioremap SCPI payload\n");
+ ret = -EADDRNOTAVAIL;
+ goto err;
+ }
+ pchan->tx_payload = pchan->rx_payload + (size >> 1);
+
+ cl->dev = dev;
+ cl->rx_callback = scpi_handle_remote_msg;
+ cl->tx_prepare = scpi_tx_prepare;
+ cl->tx_block = true;
+ cl->tx_tout = 50;
+ cl->knows_txdone = false; /* controller can't ack */
+
+ INIT_LIST_HEAD(&pchan->rx_pending);
+ INIT_LIST_HEAD(&pchan->xfers_list);
+ spin_lock_init(&pchan->rx_lock);
+ mutex_init(&pchan->xfers_lock);
+
+ ret = scpi_alloc_xfer_list(dev, pchan);
+ if (!ret) {
+ pchan->chan = mbox_request_channel(cl, idx);
+ if (!IS_ERR(pchan->chan))
+ continue;
+ ret = PTR_ERR(pchan->chan);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to get channel%d err %d\n",
+ idx, ret);
+ }
+err:
+ scpi_free_channels(dev, scpi_chan, idx);
+ scpi_info = NULL;
+ return ret;
+ }
+
+ scpi_info->channels = scpi_chan;
+ scpi_info->num_chans = count;
+ platform_set_drvdata(pdev, scpi_info);
+
+ ret = scpi_init_versions(scpi_info);
+ if (ret) {
+ dev_err(dev, "incorrect or no SCP firmware found\n");
+ scpi_remove(pdev);
+ return ret;
+ }
+
+ _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
+ PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
+ PROTOCOL_REV_MINOR(scpi_info->protocol_version),
+ FW_REV_MAJOR(scpi_info->firmware_version),
+ FW_REV_MINOR(scpi_info->firmware_version),
+ FW_REV_PATCH(scpi_info->firmware_version));
+ scpi_info->scpi_ops = &scpi_ops;
+
+ ret = sysfs_create_groups(&dev->kobj, versions_groups);
+ if (ret)
+ dev_err(dev, "unable to create sysfs version group\n");
+
+ return of_platform_populate(dev->of_node, NULL, NULL, dev);
+}
+
+static const struct of_device_id scpi_of_match[] = {
+ {.compatible = "arm,scpi"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, scpi_of_match);
+
+static struct platform_driver scpi_driver = {
+ .driver = {
+ .name = "scpi_protocol",
+ .of_match_table = scpi_of_match,
+ },
+ .probe = scpi_probe,
+ .remove = scpi_remove,
+};
+module_platform_driver(scpi_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCPI mailbox protocol driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 84533e02fbf8..e1670d533f97 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -52,6 +52,28 @@ config EFI_RUNTIME_MAP
See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
+config EFI_FAKE_MEMMAP
+ bool "Enable EFI fake memory map"
+ depends on EFI && X86
+ default n
+ help
+ Saying Y here will enable "efi_fake_mem" boot option.
+ By specifying this parameter, you can add arbitrary attribute
+ to specific memory range by updating original (firmware provided)
+ EFI memmap.
+ This is useful for debugging of EFI memmap related feature.
+ e.g. Address Range Mirroring feature.
+
+config EFI_MAX_FAKE_MEM
+ int "maximum allowable number of ranges in efi_fake_mem boot option"
+ depends on EFI_FAKE_MEMMAP
+ range 1 128
+ default 8
+ help
+ Maximum allowable number of ranges in efi_fake_mem boot option.
+ Ranges can be set up to this value using comma-separated list.
+ The default value is 8.
+
config EFI_PARAMS_FROM_FDT
bool
help
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 6fd3da938717..ec379a4164cc 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -1,6 +1,14 @@
#
# Makefile for linux kernel
#
+
+#
+# ARM64 maps efi runtime services in userspace addresses
+# which don't have KASAN shadow. So dereference of these addresses
+# in efi_call_virt() will cause crash if this code instrumented.
+#
+KASAN_SANITIZE_runtime-wrappers.o := n
+
obj-$(CONFIG_EFI) += efi.o vars.o reboot.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_ESRT) += esrt.o
@@ -9,3 +17,4 @@ obj-$(CONFIG_UEFI_CPER) += cper.o
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
obj-$(CONFIG_EFI_STUB) += libstub/
+obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index e992abc5ef26..eac76a79a880 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -103,7 +103,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
/**
* efi_pstore_scan_sysfs_enter
- * @entry: scanning entry
+ * @pos: scanning entry
* @next: next entry
* @head: list head
*/
@@ -400,3 +400,4 @@ module_exit(efivars_pstore_exit);
MODULE_DESCRIPTION("EFI variable backend for pstore");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:efivars");
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index d6144e3b97c5..027ca212179f 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -26,20 +26,21 @@
#include <linux/platform_device.h>
struct efi __read_mostly efi = {
- .mps = EFI_INVALID_TABLE_ADDR,
- .acpi = EFI_INVALID_TABLE_ADDR,
- .acpi20 = EFI_INVALID_TABLE_ADDR,
- .smbios = EFI_INVALID_TABLE_ADDR,
- .smbios3 = EFI_INVALID_TABLE_ADDR,
- .sal_systab = EFI_INVALID_TABLE_ADDR,
- .boot_info = EFI_INVALID_TABLE_ADDR,
- .hcdp = EFI_INVALID_TABLE_ADDR,
- .uga = EFI_INVALID_TABLE_ADDR,
- .uv_systab = EFI_INVALID_TABLE_ADDR,
- .fw_vendor = EFI_INVALID_TABLE_ADDR,
- .runtime = EFI_INVALID_TABLE_ADDR,
- .config_table = EFI_INVALID_TABLE_ADDR,
- .esrt = EFI_INVALID_TABLE_ADDR,
+ .mps = EFI_INVALID_TABLE_ADDR,
+ .acpi = EFI_INVALID_TABLE_ADDR,
+ .acpi20 = EFI_INVALID_TABLE_ADDR,
+ .smbios = EFI_INVALID_TABLE_ADDR,
+ .smbios3 = EFI_INVALID_TABLE_ADDR,
+ .sal_systab = EFI_INVALID_TABLE_ADDR,
+ .boot_info = EFI_INVALID_TABLE_ADDR,
+ .hcdp = EFI_INVALID_TABLE_ADDR,
+ .uga = EFI_INVALID_TABLE_ADDR,
+ .uv_systab = EFI_INVALID_TABLE_ADDR,
+ .fw_vendor = EFI_INVALID_TABLE_ADDR,
+ .runtime = EFI_INVALID_TABLE_ADDR,
+ .config_table = EFI_INVALID_TABLE_ADDR,
+ .esrt = EFI_INVALID_TABLE_ADDR,
+ .properties_table = EFI_INVALID_TABLE_ADDR,
};
EXPORT_SYMBOL(efi);
@@ -63,6 +64,9 @@ static int __init parse_efi_cmdline(char *str)
return -EINVAL;
}
+ if (parse_option_str(str, "debug"))
+ set_bit(EFI_DBG, &efi.flags);
+
if (parse_option_str(str, "noruntime"))
disable_runtime = true;
@@ -250,7 +254,7 @@ subsys_initcall(efisubsys_init);
int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
{
struct efi_memory_map *map = efi.memmap;
- void *p, *e;
+ phys_addr_t p, e;
if (!efi_enabled(EFI_MEMMAP)) {
pr_err_once("EFI_MEMMAP is not enabled.\n");
@@ -282,10 +286,10 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
* So just always get our own virtual map on the CPU.
*
*/
- md = early_memremap((phys_addr_t)p, sizeof (*md));
+ md = early_memremap(p, sizeof (*md));
if (!md) {
- pr_err_once("early_memremap(%p, %zu) failed.\n",
- p, sizeof (*md));
+ pr_err_once("early_memremap(%pa, %zu) failed.\n",
+ &p, sizeof (*md));
return -ENOMEM;
}
@@ -362,6 +366,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
+ {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
{NULL_GUID, NULL, NULL},
};
@@ -421,6 +426,24 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
}
pr_cont("\n");
set_bit(EFI_CONFIG_TABLES, &efi.flags);
+
+ /* Parse the EFI Properties table if it exists */
+ if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
+ efi_properties_table_t *tbl;
+
+ tbl = early_memremap(efi.properties_table, sizeof(*tbl));
+ if (tbl == NULL) {
+ pr_err("Could not map Properties table!\n");
+ return -ENOMEM;
+ }
+
+ if (tbl->memory_protection_attribute &
+ EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
+ set_bit(EFI_NX_PE_DATA, &efi.flags);
+
+ early_memunmap(tbl, sizeof(*tbl));
+ }
+
return 0;
}
@@ -489,7 +512,6 @@ static __initdata struct {
};
struct param_info {
- int verbose;
int found;
void *params;
};
@@ -520,21 +542,20 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
else
*(u64 *)dest = val;
- if (info->verbose)
+ if (efi_enabled(EFI_DBG))
pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
dt_params[i].size * 2, val);
}
return 1;
}
-int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
+int __init efi_get_fdt_params(struct efi_fdt_params *params)
{
struct param_info info;
int ret;
pr_info("Getting EFI parameters from FDT:\n");
- info.verbose = verbose;
info.found = 0;
info.params = params;
@@ -588,16 +609,19 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
attr = md->attribute;
if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
- EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
- EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
+ EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
+ EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
+ EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
snprintf(pos, size, "|attr=0x%016llx]",
(unsigned long long)attr);
else
- snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
+ snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
+ attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
attr & EFI_MEMORY_XP ? "XP" : "",
attr & EFI_MEMORY_RP ? "RP" : "",
attr & EFI_MEMORY_WP ? "WP" : "",
+ attr & EFI_MEMORY_RO ? "RO" : "",
attr & EFI_MEMORY_UCE ? "UCE" : "",
attr & EFI_MEMORY_WB ? "WB" : "",
attr & EFI_MEMORY_WT ? "WT" : "",
@@ -605,3 +629,36 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
attr & EFI_MEMORY_UC ? "UC" : "");
return buf;
}
+
+/*
+ * efi_mem_attributes - lookup memmap attributes for physical address
+ * @phys_addr: the physical address to lookup
+ *
+ * Search in the EFI memory map for the region covering
+ * @phys_addr. Returns the EFI memory attributes if the region
+ * was found in the memory map, 0 otherwise.
+ *
+ * Despite being marked __weak, most architectures should *not*
+ * override this function. It is __weak solely for the benefit
+ * of ia64 which has a funky EFI memory map that doesn't work
+ * the same way as other architectures.
+ */
+u64 __weak efi_mem_attributes(unsigned long phys_addr)
+{
+ struct efi_memory_map *map;
+ efi_memory_desc_t *md;
+ void *p;
+
+ if (!efi_enabled(EFI_MEMMAP))
+ return 0;
+
+ map = efi.memmap;
+ for (p = map->map; p < map->map_end; p += map->desc_size) {
+ md = p;
+ if ((md->phys_addr <= phys_addr) &&
+ (phys_addr < (md->phys_addr +
+ (md->num_pages << EFI_PAGE_SHIFT))))
+ return md->attribute;
+ }
+ return 0;
+}
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index a5b95d61ae71..22c5285f7705 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -20,7 +20,6 @@
#include <linux/kobject.h>
#include <linux/list.h>
#include <linux/memblock.h>
-#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -450,22 +449,10 @@ err:
esrt = NULL;
return error;
}
+device_initcall(esrt_sysfs_init);
-static void __exit esrt_sysfs_exit(void)
-{
- pr_debug("esrt-sysfs: unloading.\n");
- cleanup_entry_list();
- kset_unregister(esrt_kset);
- sysfs_remove_group(esrt_kobj, &esrt_attr_group);
- kfree(esrt);
- esrt = NULL;
- kobject_del(esrt_kobj);
- kobject_put(esrt_kobj);
-}
-
-module_init(esrt_sysfs_init);
-module_exit(esrt_sysfs_exit);
-
+/*
MODULE_AUTHOR("Peter Jones <pjones@redhat.com>");
MODULE_DESCRIPTION("EFI System Resource Table support");
MODULE_LICENSE("GPL");
+*/
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
new file mode 100644
index 000000000000..ed3a854950cc
--- /dev/null
+++ b/drivers/firmware/efi/fake_mem.c
@@ -0,0 +1,238 @@
+/*
+ * fake_mem.c
+ *
+ * Copyright (C) 2015 FUJITSU LIMITED
+ * Author: Taku Izumi <izumi.taku@jp.fujitsu.com>
+ *
+ * This code introduces new boot option named "efi_fake_mem"
+ * 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>
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/types.h>
+#include <linux/sort.h>
+#include <asm/efi.h>
+
+#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM
+
+struct fake_mem {
+ struct range range;
+ u64 attribute;
+};
+static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
+static int nr_fake_mem;
+
+static int __init cmp_fake_mem(const void *x1, const void *x2)
+{
+ const struct fake_mem *m1 = x1;
+ const struct fake_mem *m2 = x2;
+
+ if (m1->range.start < m2->range.start)
+ return -1;
+ if (m1->range.start > m2->range.start)
+ return 1;
+ return 0;
+}
+
+void __init efi_fake_memmap(void)
+{
+ u64 start, end, m_start, m_end, m_attr;
+ int new_nr_map = memmap.nr_map;
+ efi_memory_desc_t *md;
+ phys_addr_t new_memmap_phy;
+ void *new_memmap;
+ void *old, *new;
+ int i;
+
+ if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP))
+ return;
+
+ /* count up the number of EFI memory descriptor */
+ for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
+ md = old;
+ start = md->phys_addr;
+ end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+ for (i = 0; i < nr_fake_mem; i++) {
+ /* modifying range */
+ m_start = fake_mems[i].range.start;
+ m_end = fake_mems[i].range.end;
+
+ if (m_start <= start) {
+ /* split into 2 parts */
+ if (start < m_end && m_end < end)
+ new_nr_map++;
+ }
+ if (start < m_start && m_start < end) {
+ /* split into 3 parts */
+ if (m_end < end)
+ new_nr_map += 2;
+ /* split into 2 parts */
+ if (end <= m_end)
+ new_nr_map++;
+ }
+ }
+ }
+
+ /* allocate memory for new EFI memmap */
+ new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
+ PAGE_SIZE);
+ if (!new_memmap_phy)
+ return;
+
+ /* create new EFI memmap */
+ new_memmap = early_memremap(new_memmap_phy,
+ memmap.desc_size * new_nr_map);
+ if (!new_memmap) {
+ memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
+ return;
+ }
+
+ for (old = memmap.map, new = new_memmap;
+ old < memmap.map_end;
+ old += memmap.desc_size, new += memmap.desc_size) {
+
+ /* copy original EFI memory descriptor */
+ memcpy(new, old, memmap.desc_size);
+ md = new;
+ start = md->phys_addr;
+ end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+ for (i = 0; i < nr_fake_mem; i++) {
+ /* modifying range */
+ m_start = fake_mems[i].range.start;
+ m_end = fake_mems[i].range.end;
+ m_attr = fake_mems[i].attribute;
+
+ if (m_start <= start && end <= m_end)
+ md->attribute |= m_attr;
+
+ if (m_start <= start &&
+ (start < m_end && m_end < end)) {
+ /* first part */
+ md->attribute |= m_attr;
+ md->num_pages = (m_end - md->phys_addr + 1) >>
+ EFI_PAGE_SHIFT;
+ /* latter part */
+ new += memmap.desc_size;
+ memcpy(new, old, memmap.desc_size);
+ md = new;
+ md->phys_addr = m_end + 1;
+ md->num_pages = (end - md->phys_addr + 1) >>
+ EFI_PAGE_SHIFT;
+ }
+
+ if ((start < m_start && m_start < end) && m_end < end) {
+ /* first part */
+ md->num_pages = (m_start - md->phys_addr) >>
+ EFI_PAGE_SHIFT;
+ /* middle part */
+ new += memmap.desc_size;
+ memcpy(new, old, memmap.desc_size);
+ md = new;
+ md->attribute |= m_attr;
+ md->phys_addr = m_start;
+ md->num_pages = (m_end - m_start + 1) >>
+ EFI_PAGE_SHIFT;
+ /* last part */
+ new += memmap.desc_size;
+ memcpy(new, old, memmap.desc_size);
+ md = new;
+ md->phys_addr = m_end + 1;
+ md->num_pages = (end - m_end) >>
+ EFI_PAGE_SHIFT;
+ }
+
+ if ((start < m_start && m_start < end) &&
+ (end <= m_end)) {
+ /* first part */
+ md->num_pages = (m_start - md->phys_addr) >>
+ EFI_PAGE_SHIFT;
+ /* latter part */
+ new += memmap.desc_size;
+ memcpy(new, old, memmap.desc_size);
+ md = new;
+ md->phys_addr = m_start;
+ md->num_pages = (end - md->phys_addr + 1) >>
+ EFI_PAGE_SHIFT;
+ md->attribute |= m_attr;
+ }
+ }
+ }
+
+ /* swap into new EFI memmap */
+ efi_unmap_memmap();
+ memmap.map = new_memmap;
+ memmap.phys_map = new_memmap_phy;
+ memmap.nr_map = new_nr_map;
+ memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
+ set_bit(EFI_MEMMAP, &efi.flags);
+
+ /* print new EFI memmap */
+ efi_print_memmap();
+}
+
+static int __init setup_fake_mem(char *p)
+{
+ u64 start = 0, mem_size = 0, attribute = 0;
+ int i;
+
+ if (!p)
+ return -EINVAL;
+
+ while (*p != '\0') {
+ mem_size = memparse(p, &p);
+ if (*p == '@')
+ start = memparse(p+1, &p);
+ else
+ break;
+
+ if (*p == ':')
+ attribute = simple_strtoull(p+1, &p, 0);
+ else
+ break;
+
+ if (nr_fake_mem >= EFI_MAX_FAKEMEM)
+ break;
+
+ fake_mems[nr_fake_mem].range.start = start;
+ fake_mems[nr_fake_mem].range.end = start + mem_size - 1;
+ fake_mems[nr_fake_mem].attribute = attribute;
+ nr_fake_mem++;
+
+ if (*p == ',')
+ p++;
+ }
+
+ sort(fake_mems, nr_fake_mem, sizeof(struct fake_mem),
+ cmp_fake_mem, NULL);
+
+ for (i = 0; i < nr_fake_mem; i++)
+ pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]",
+ fake_mems[i].attribute, fake_mems[i].range.start,
+ fake_mems[i].range.end);
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+early_param("efi_fake_mem", setup_fake_mem);
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 816dbe9f4b82..3c0467d3688c 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -14,6 +14,8 @@ cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \
-fno-builtin -fpic -mno-single-pic-base
+cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt
+
KBUILD_CFLAGS := $(cflags-y) \
$(call cc-option,-ffreestanding) \
$(call cc-option,-fno-stack-protector)
@@ -22,7 +24,18 @@ GCOV_PROFILE := n
KASAN_SANITIZE := n
lib-y := efi-stub-helper.o
-lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o
+
+# include the stub's generic dependencies from lib/ when building for ARM/arm64
+arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
+
+$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
+ $(call if_changed_rule,cc_o_c)
+
+lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \
+ $(patsubst %.c,lib-%.o,$(arm-deps))
+
+lib-$(CONFIG_ARM64) += arm64-stub.o
+CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
#
# arm64 puts the stub in the kernel proper, which will unnecessarily retain all
@@ -30,10 +43,27 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o
# So let's apply the __init annotations at the section level, by prefixing
# the section names directly. This will ensure that even all the inline string
# literals are covered.
+# The fact that the stub and the kernel proper are essentially the same binary
+# also means that we need to be extra careful to make sure that the stub does
+# not rely on any absolute symbol references, considering that the virtual
+# kernel mapping that the linker uses is not active yet when the stub is
+# executing. So build all C dependencies of the EFI stub into libstub, and do
+# a verification pass to see if any absolute relocations exist in any of the
+# object files.
#
-extra-$(CONFIG_ARM64) := $(lib-y)
-lib-$(CONFIG_ARM64) := $(patsubst %.o,%.init.o,$(lib-y))
+extra-$(CONFIG_EFI_ARMSTUB) := $(lib-y)
+lib-$(CONFIG_EFI_ARMSTUB) := $(patsubst %.o,%.stub.o,$(lib-y))
+
+STUBCOPY_FLAGS-y := -R .debug* -R *ksymtab* -R *kcrctab*
+STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \
+ --prefix-symbols=__efistub_
+STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
+
+$(obj)/%.stub.o: $(obj)/%.o FORCE
+ $(call if_changed,stubcopy)
-OBJCOPYFLAGS := --prefix-alloc-sections=.init
-$(obj)/%.init.o: $(obj)/%.o FORCE
- $(call if_changed,objcopy)
+quiet_cmd_stubcopy = STUBCPY $@
+ cmd_stubcopy = if $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; then \
+ $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \
+ && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \
+ rm -f $@; /bin/false); else /bin/false; fi
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
new file mode 100644
index 000000000000..78dfbd34b6bf
--- /dev/null
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ *
+ */
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include <asm/sections.h>
+
+efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
+ unsigned long *image_addr,
+ unsigned long *image_size,
+ unsigned long *reserve_addr,
+ unsigned long *reserve_size,
+ unsigned long dram_base,
+ efi_loaded_image_t *image)
+{
+ efi_status_t status;
+ unsigned long kernel_size, kernel_memsize = 0;
+ unsigned long nr_pages;
+ void *old_image_addr = (void *)*image_addr;
+ unsigned long preferred_offset;
+
+ /*
+ * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
+ * a 2 MB aligned base, which itself may be lower than dram_base, as
+ * long as the resulting offset equals or exceeds it.
+ */
+ preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
+ if (preferred_offset < dram_base)
+ preferred_offset += SZ_2M;
+
+ /* Relocate the image, if required. */
+ kernel_size = _edata - _text;
+ if (*image_addr != preferred_offset) {
+ kernel_memsize = kernel_size + (_end - _edata);
+
+ /*
+ * First, try a straight allocation at the preferred offset.
+ * This will work around the issue where, if dram_base == 0x0,
+ * efi_low_alloc() refuses to allocate at 0x0 (to prevent the
+ * address of the allocation to be mistaken for a FAIL return
+ * value or a NULL pointer). It will also ensure that, on
+ * platforms where the [dram_base, dram_base + TEXT_OFFSET)
+ * interval is partially occupied by the firmware (like on APM
+ * Mustang), we can still place the kernel at the address
+ * 'dram_base + TEXT_OFFSET'.
+ */
+ *image_addr = *reserve_addr = preferred_offset;
+ nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
+ EFI_PAGE_SIZE;
+ status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
+ EFI_LOADER_DATA, nr_pages,
+ (efi_physical_addr_t *)reserve_addr);
+ if (status != EFI_SUCCESS) {
+ kernel_memsize += TEXT_OFFSET;
+ status = efi_low_alloc(sys_table_arg, kernel_memsize,
+ SZ_2M, reserve_addr);
+
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
+ return status;
+ }
+ *image_addr = *reserve_addr + TEXT_OFFSET;
+ }
+ memcpy((void *)*image_addr, old_image_addr, kernel_size);
+ *reserve_size = kernel_memsize;
+ }
+
+
+ return EFI_SUCCESS;
+}
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index ef5d764e2a27..b62e2f5dcab3 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -147,15 +147,6 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
if (status)
goto fdt_set_fail;
- /*
- * Add kernel version banner so stub/kernel match can be
- * verified.
- */
- status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
- linux_banner);
- if (status)
- goto fdt_set_fail;
-
return EFI_SUCCESS;
fdt_set_fail:
diff --git a/drivers/firmware/efi/libstub/string.c b/drivers/firmware/efi/libstub/string.c
new file mode 100644
index 000000000000..09d5a0894343
--- /dev/null
+++ b/drivers/firmware/efi/libstub/string.c
@@ -0,0 +1,57 @@
+/*
+ * Taken from:
+ * linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+
+#ifndef __HAVE_ARCH_STRSTR
+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char *strstr(const char *s1, const char *s2)
+{
+ size_t l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *)s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1++;
+ }
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCMP
+/**
+ * strncmp - Compare two length-limited strings
+ * @cs: One string
+ * @ct: Another string
+ * @count: The maximum number of bytes to compare
+ */
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+ unsigned char c1, c2;
+
+ while (count) {
+ c1 = *cs++;
+ c2 = *ct++;
+ if (c1 != c2)
+ return c1 < c2 ? -1 : 1;
+ if (!c1)
+ break;
+ count--;
+ }
+ return 0;
+}
+#endif
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 42700f09a8c5..d24f35d74b27 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -20,23 +20,25 @@
#include <linux/printk.h>
#include <linux/psci.h>
#include <linux/reboot.h>
+#include <linux/suspend.h>
#include <uapi/linux/psci.h>
#include <asm/cputype.h>
#include <asm/system_misc.h>
#include <asm/smp_plat.h>
+#include <asm/suspend.h>
/*
* While a 64-bit OS can make calls with SMC32 calling conventions, for some
- * calls it is necessary to use SMC64 to pass or return 64-bit values. For such
- * calls PSCI_0_2_FN_NATIVE(x) will choose the appropriate (native-width)
- * function ID.
+ * calls it is necessary to use SMC64 to pass or return 64-bit values.
+ * For such calls PSCI_FN_NATIVE(version, name) will choose the appropriate
+ * (native-width) function ID.
*/
#ifdef CONFIG_64BIT
-#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN64_##name
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
#else
-#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN_##name
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
#endif
/*
@@ -70,6 +72,41 @@ enum psci_function {
static u32 psci_function_id[PSCI_FN_MAX];
+#define PSCI_0_2_POWER_STATE_MASK \
+ (PSCI_0_2_POWER_STATE_ID_MASK | \
+ PSCI_0_2_POWER_STATE_TYPE_MASK | \
+ PSCI_0_2_POWER_STATE_AFFL_MASK)
+
+#define PSCI_1_0_EXT_POWER_STATE_MASK \
+ (PSCI_1_0_EXT_POWER_STATE_ID_MASK | \
+ PSCI_1_0_EXT_POWER_STATE_TYPE_MASK)
+
+static u32 psci_cpu_suspend_feature;
+
+static inline bool psci_has_ext_power_state(void)
+{
+ return psci_cpu_suspend_feature &
+ PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
+}
+
+bool psci_power_state_loses_context(u32 state)
+{
+ const u32 mask = psci_has_ext_power_state() ?
+ PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
+ PSCI_0_2_POWER_STATE_TYPE_MASK;
+
+ return state & mask;
+}
+
+bool psci_power_state_is_valid(u32 state)
+{
+ const u32 valid_mask = psci_has_ext_power_state() ?
+ PSCI_1_0_EXT_POWER_STATE_MASK :
+ PSCI_0_2_POWER_STATE_MASK;
+
+ return !(state & ~valid_mask);
+}
+
static int psci_to_linux_errno(int errno)
{
switch (errno) {
@@ -78,6 +115,7 @@ static int psci_to_linux_errno(int errno)
case PSCI_RET_NOT_SUPPORTED:
return -EOPNOTSUPP;
case PSCI_RET_INVALID_PARAMS:
+ case PSCI_RET_INVALID_ADDRESS:
return -EINVAL;
case PSCI_RET_DENIED:
return -EPERM;
@@ -134,7 +172,7 @@ static int psci_migrate(unsigned long cpuid)
static int psci_affinity_info(unsigned long target_affinity,
unsigned long lowest_affinity_level)
{
- return invoke_psci_fn(PSCI_0_2_FN_NATIVE(AFFINITY_INFO),
+ return invoke_psci_fn(PSCI_FN_NATIVE(0_2, AFFINITY_INFO),
target_affinity, lowest_affinity_level, 0);
}
@@ -145,7 +183,7 @@ static int psci_migrate_info_type(void)
static unsigned long psci_migrate_info_up_cpu(void)
{
- return invoke_psci_fn(PSCI_0_2_FN_NATIVE(MIGRATE_INFO_UP_CPU),
+ return invoke_psci_fn(PSCI_FN_NATIVE(0_2, MIGRATE_INFO_UP_CPU),
0, 0, 0);
}
@@ -181,6 +219,49 @@ static void psci_sys_poweroff(void)
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
}
+static int __init psci_features(u32 psci_func_id)
+{
+ return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
+ psci_func_id, 0, 0);
+}
+
+static int psci_system_suspend(unsigned long unused)
+{
+ return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
+ virt_to_phys(cpu_resume), 0, 0);
+}
+
+static int psci_system_suspend_enter(suspend_state_t state)
+{
+ return cpu_suspend(0, psci_system_suspend);
+}
+
+static const struct platform_suspend_ops psci_suspend_ops = {
+ .valid = suspend_valid_only_mem,
+ .enter = psci_system_suspend_enter,
+};
+
+static void __init psci_init_system_suspend(void)
+{
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_SUSPEND))
+ return;
+
+ ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
+
+ if (ret != PSCI_RET_NOT_SUPPORTED)
+ suspend_set_ops(&psci_suspend_ops);
+}
+
+static void __init psci_init_cpu_suspend(void)
+{
+ int feature = psci_features(psci_function_id[PSCI_FN_CPU_SUSPEND]);
+
+ if (feature != PSCI_RET_NOT_SUPPORTED)
+ psci_cpu_suspend_feature = feature;
+}
+
/*
* Detect the presence of a resident Trusted OS which may cause CPU_OFF to
* return DENIED (which would be fatal).
@@ -224,16 +305,17 @@ static void __init psci_init_migrate(void)
static void __init psci_0_2_set_functions(void)
{
pr_info("Using standard PSCI v0.2 function IDs\n");
- psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN_NATIVE(CPU_SUSPEND);
+ psci_function_id[PSCI_FN_CPU_SUSPEND] =
+ PSCI_FN_NATIVE(0_2, CPU_SUSPEND);
psci_ops.cpu_suspend = psci_cpu_suspend;
psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
psci_ops.cpu_off = psci_cpu_off;
- psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN_NATIVE(CPU_ON);
+ psci_function_id[PSCI_FN_CPU_ON] = PSCI_FN_NATIVE(0_2, CPU_ON);
psci_ops.cpu_on = psci_cpu_on;
- psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN_NATIVE(MIGRATE);
+ psci_function_id[PSCI_FN_MIGRATE] = PSCI_FN_NATIVE(0_2, MIGRATE);
psci_ops.migrate = psci_migrate;
psci_ops.affinity_info = psci_affinity_info;
@@ -265,6 +347,11 @@ static int __init psci_probe(void)
psci_init_migrate();
+ if (PSCI_VERSION_MAJOR(ver) >= 1) {
+ psci_init_cpu_suspend();
+ psci_init_system_suspend();
+ }
+
return 0;
}
@@ -340,6 +427,7 @@ out_put_node:
static const struct of_device_id const psci_of_match[] __initconst = {
{ .compatible = "arm,psci", .data = psci_0_1_init},
{ .compatible = "arm,psci-0.2", .data = psci_0_2_init},
+ { .compatible = "arm,psci-1.0", .data = psci_0_2_init},
{},
};
diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 29e6850665eb..0883292f640f 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -480,15 +480,15 @@ void __qcom_scm_cpu_power_down(u32 flags)
int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
{
int ret;
- u32 svc_cmd = (svc_id << 10) | cmd_id;
- u32 ret_val = 0;
+ __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
+ __le32 ret_val = 0;
ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
sizeof(svc_cmd), &ret_val, sizeof(ret_val));
if (ret)
return ret;
- return ret_val;
+ return le32_to_cpu(ret_val);
}
int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
new file mode 100644
index 000000000000..dd506cd3a5b8
--- /dev/null
+++ b/drivers/firmware/raspberrypi.c
@@ -0,0 +1,260 @@
+/*
+ * Defines interfaces for interacting wtih the Raspberry Pi firmware's
+ * property channel.
+ *
+ * Copyright © 2015 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.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf))
+#define MBOX_CHAN(msg) ((msg) & 0xf)
+#define MBOX_DATA28(msg) ((msg) & ~0xf)
+#define MBOX_CHAN_PROPERTY 8
+
+struct rpi_firmware {
+ struct mbox_client cl;
+ struct mbox_chan *chan; /* The property channel. */
+ struct completion c;
+ u32 enabled;
+};
+
+static DEFINE_MUTEX(transaction_lock);
+
+static void response_callback(struct mbox_client *cl, void *msg)
+{
+ struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl);
+ complete(&fw->c);
+}
+
+/*
+ * Sends a request to the firmware through the BCM2835 mailbox driver,
+ * and synchronously waits for the reply.
+ */
+static int
+rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data)
+{
+ u32 message = MBOX_MSG(chan, data);
+ int ret;
+
+ WARN_ON(data & 0xf);
+
+ mutex_lock(&transaction_lock);
+ reinit_completion(&fw->c);
+ ret = mbox_send_message(fw->chan, &message);
+ if (ret >= 0) {
+ wait_for_completion(&fw->c);
+ ret = 0;
+ } else {
+ dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret);
+ }
+ mutex_unlock(&transaction_lock);
+
+ return ret;
+}
+
+/**
+ * rpi_firmware_property_list - Submit firmware property list
+ * @fw: Pointer to firmware structure from rpi_firmware_get().
+ * @data: Buffer holding tags.
+ * @tag_size: Size of tags buffer.
+ *
+ * Submits a set of concatenated tags to the VPU firmware through the
+ * mailbox property interface.
+ *
+ * The buffer header and the ending tag are added by this function and
+ * don't need to be supplied, just the actual tags for your operation.
+ * See struct rpi_firmware_property_tag_header for the per-tag
+ * structure.
+ */
+int rpi_firmware_property_list(struct rpi_firmware *fw,
+ void *data, size_t tag_size)
+{
+ size_t size = tag_size + 12;
+ u32 *buf;
+ dma_addr_t bus_addr;
+ int ret;
+
+ /* Packets are processed a dword at a time. */
+ if (size & 3)
+ return -EINVAL;
+
+ buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr,
+ GFP_ATOMIC);
+ if (!buf)
+ return -ENOMEM;
+
+ /* The firmware will error out without parsing in this case. */
+ WARN_ON(size >= 1024 * 1024);
+
+ buf[0] = size;
+ buf[1] = RPI_FIRMWARE_STATUS_REQUEST;
+ memcpy(&buf[2], data, tag_size);
+ buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END;
+ wmb();
+
+ ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr);
+
+ rmb();
+ memcpy(data, &buf[2], tag_size);
+ if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) {
+ /*
+ * The tag name here might not be the one causing the
+ * error, if there were multiple tags in the request.
+ * But single-tag is the most common, so go with it.
+ */
+ dev_err(fw->cl.dev, "Request 0x%08x returned status 0x%08x\n",
+ buf[2], buf[1]);
+ ret = -EINVAL;
+ }
+
+ dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_property_list);
+
+/**
+ * rpi_firmware_property - Submit single firmware property
+ * @fw: Pointer to firmware structure from rpi_firmware_get().
+ * @tag: One of enum_mbox_property_tag.
+ * @tag_data: Tag data buffer.
+ * @buf_size: Buffer size.
+ *
+ * Submits a single tag to the VPU firmware through the mailbox
+ * property interface.
+ *
+ * This is a convenience wrapper around
+ * rpi_firmware_property_list() to avoid some of the
+ * boilerplate in property calls.
+ */
+int rpi_firmware_property(struct rpi_firmware *fw,
+ u32 tag, void *tag_data, size_t buf_size)
+{
+ /* Single tags are very small (generally 8 bytes), so the
+ * stack should be safe.
+ */
+ u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)];
+ struct rpi_firmware_property_tag_header *header =
+ (struct rpi_firmware_property_tag_header *)data;
+ int ret;
+
+ header->tag = tag;
+ header->buf_size = buf_size;
+ header->req_resp_size = 0;
+ memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
+ tag_data, buf_size);
+
+ ret = rpi_firmware_property_list(fw, &data, sizeof(data));
+ memcpy(tag_data,
+ data + sizeof(struct rpi_firmware_property_tag_header),
+ buf_size);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_property);
+
+static void
+rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
+{
+ u32 packet;
+ int ret = rpi_firmware_property(fw,
+ RPI_FIRMWARE_GET_FIRMWARE_REVISION,
+ &packet, sizeof(packet));
+
+ if (ret == 0) {
+ struct tm tm;
+
+ time_to_tm(packet, 0, &tm);
+
+ dev_info(fw->cl.dev,
+ "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min);
+ }
+}
+
+static int rpi_firmware_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rpi_firmware *fw;
+
+ fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
+ if (!fw)
+ return -ENOMEM;
+
+ fw->cl.dev = dev;
+ fw->cl.rx_callback = response_callback;
+ fw->cl.tx_block = true;
+
+ fw->chan = mbox_request_channel(&fw->cl, 0);
+ if (IS_ERR(fw->chan)) {
+ int ret = PTR_ERR(fw->chan);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get mbox channel: %d\n", ret);
+ return ret;
+ }
+
+ init_completion(&fw->c);
+
+ platform_set_drvdata(pdev, fw);
+
+ rpi_firmware_print_firmware_revision(fw);
+
+ return 0;
+}
+
+static int rpi_firmware_remove(struct platform_device *pdev)
+{
+ struct rpi_firmware *fw = platform_get_drvdata(pdev);
+
+ mbox_free_channel(fw->chan);
+
+ return 0;
+}
+
+/**
+ * rpi_firmware_get - Get pointer to rpi_firmware structure.
+ * @firmware_node: Pointer to the firmware Device Tree node.
+ *
+ * Returns NULL is the firmware device is not ready.
+ */
+struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
+{
+ struct platform_device *pdev = of_find_device_by_node(firmware_node);
+
+ if (!pdev)
+ return NULL;
+
+ return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_get);
+
+static const struct of_device_id rpi_firmware_of_match[] = {
+ { .compatible = "raspberrypi,bcm2835-firmware", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
+
+static struct platform_driver rpi_firmware_driver = {
+ .driver = {
+ .name = "raspberrypi-firmware",
+ .of_match_table = rpi_firmware_of_match,
+ },
+ .probe = rpi_firmware_probe,
+ .remove = rpi_firmware_remove,
+};
+module_platform_driver(rpi_firmware_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("Raspberry Pi firmware driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 000000000000..c9b9fdf6cfbb
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,29 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA Configuration Support"
+
+config FPGA
+ tristate "FPGA Configuration Framework"
+ help
+ Say Y here if you want support for configuring FPGAs from the
+ kernel. The FPGA framework adds a FPGA manager class and FPGA
+ manager drivers.
+
+if FPGA
+
+config FPGA_MGR_SOCFPGA
+ tristate "Altera SOCFPGA FPGA Manager"
+ depends on ARCH_SOCFPGA
+ help
+ FPGA manager driver support for Altera SOCFPGA.
+
+config FPGA_MGR_ZYNQ_FPGA
+ tristate "Xilinx Zynq FPGA"
+ help
+ FPGA manager driver support for Xilinx Zynq FPGAs.
+
+endif # FPGA
+
+endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
new file mode 100644
index 000000000000..8d83fc6b1613
--- /dev/null
+++ b/drivers/fpga/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+# Core FPGA Manager Framework
+obj-$(CONFIG_FPGA) += fpga-mgr.o
+
+# FPGA Manager Drivers
+obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
+obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
new file mode 100644
index 000000000000..a24f5cb877e0
--- /dev/null
+++ b/drivers/fpga/fpga-mgr.c
@@ -0,0 +1,380 @@
+/*
+ * FPGA Manager Core
+ *
+ * Copyright (C) 2013-2015 Altera Corporation
+ *
+ * With code from the mailing list:
+ * Copyright (C) 2013 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/firmware.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+static DEFINE_IDA(fpga_mgr_ida);
+static struct class *fpga_mgr_class;
+
+/**
+ * fpga_mgr_buf_load - load fpga from image in buffer
+ * @mgr: fpga manager
+ * @flags: flags setting fpga confuration modes
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ *
+ * Step the low level fpga manager through the device-specific steps of getting
+ * an FPGA ready to be configured, writing the image to it, then doing whatever
+ * post-configuration steps necessary. This code assumes the caller got the
+ * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf,
+ size_t count)
+{
+ struct device *dev = &mgr->dev;
+ int ret;
+
+ /*
+ * Call the low level driver's write_init function. This will do the
+ * device-specific things to get the FPGA into the state where it is
+ * ready to receive an FPGA image.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+ ret = mgr->mops->write_init(mgr, flags, buf, count);
+ if (ret) {
+ dev_err(dev, "Error preparing FPGA for writing\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+ return ret;
+ }
+
+ /*
+ * Write the FPGA image to the FPGA.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE;
+ ret = mgr->mops->write(mgr, buf, count);
+ if (ret) {
+ dev_err(dev, "Error while writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+ return ret;
+ }
+
+ /*
+ * After all the FPGA image has been written, do the device specific
+ * steps to finish and set the FPGA into operating mode.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+ ret = mgr->mops->write_complete(mgr, flags);
+ if (ret) {
+ dev_err(dev, "Error after writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+ return ret;
+ }
+ mgr->state = FPGA_MGR_STATE_OPERATING;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
+
+/**
+ * fpga_mgr_firmware_load - request firmware and load to fpga
+ * @mgr: fpga manager
+ * @flags: flags setting fpga confuration modes
+ * @image_name: name of image file on the firmware search path
+ *
+ * Request an FPGA image using the firmware class, then write out to the FPGA.
+ * Update the state before each step to provide info on what step failed if
+ * there is a failure. This code assumes the caller got the mgr pointer
+ * from of_fpga_mgr_get() and checked that it is not an error code.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
+ const char *image_name)
+{
+ struct device *dev = &mgr->dev;
+ const struct firmware *fw;
+ int ret;
+
+ dev_info(dev, "writing %s to %s\n", image_name, mgr->name);
+
+ mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
+
+ ret = request_firmware(&fw, image_name, dev);
+ if (ret) {
+ mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
+ dev_err(dev, "Error requesting firmware %s\n", image_name);
+ return ret;
+ }
+
+ ret = fpga_mgr_buf_load(mgr, flags, fw->data, fw->size);
+ if (ret)
+ return ret;
+
+ release_firmware(fw);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_firmware_load);
+
+static const char * const state_str[] = {
+ [FPGA_MGR_STATE_UNKNOWN] = "unknown",
+ [FPGA_MGR_STATE_POWER_OFF] = "power off",
+ [FPGA_MGR_STATE_POWER_UP] = "power up",
+ [FPGA_MGR_STATE_RESET] = "reset",
+
+ /* requesting FPGA image from firmware */
+ [FPGA_MGR_STATE_FIRMWARE_REQ] = "firmware request",
+ [FPGA_MGR_STATE_FIRMWARE_REQ_ERR] = "firmware request error",
+
+ /* Preparing FPGA to receive image */
+ [FPGA_MGR_STATE_WRITE_INIT] = "write init",
+ [FPGA_MGR_STATE_WRITE_INIT_ERR] = "write init error",
+
+ /* Writing image to FPGA */
+ [FPGA_MGR_STATE_WRITE] = "write",
+ [FPGA_MGR_STATE_WRITE_ERR] = "write error",
+
+ /* Finishing configuration after image has been written */
+ [FPGA_MGR_STATE_WRITE_COMPLETE] = "write complete",
+ [FPGA_MGR_STATE_WRITE_COMPLETE_ERR] = "write complete error",
+
+ /* FPGA reports to be in normal operating mode */
+ [FPGA_MGR_STATE_OPERATING] = "operating",
+};
+
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_manager *mgr = to_fpga_manager(dev);
+
+ return sprintf(buf, "%s\n", mgr->name);
+}
+
+static ssize_t state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_manager *mgr = to_fpga_manager(dev);
+
+ return sprintf(buf, "%s\n", state_str[mgr->state]);
+}
+
+static DEVICE_ATTR_RO(name);
+static DEVICE_ATTR_RO(state);
+
+static struct attribute *fpga_mgr_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_state.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(fpga_mgr);
+
+static int fpga_mgr_of_node_match(struct device *dev, const void *data)
+{
+ return dev->of_node == data;
+}
+
+/**
+ * of_fpga_mgr_get - get an exclusive reference to a fpga mgr
+ * @node: device node
+ *
+ * Given a device node, get an exclusive reference to a fpga mgr.
+ *
+ * Return: fpga manager struct or IS_ERR() condition containing error code.
+ */
+struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
+{
+ struct fpga_manager *mgr;
+ struct device *dev;
+ int ret = -ENODEV;
+
+ dev = class_find_device(fpga_mgr_class, NULL, node,
+ fpga_mgr_of_node_match);
+ if (!dev)
+ return ERR_PTR(-ENODEV);
+
+ mgr = to_fpga_manager(dev);
+ if (!mgr)
+ goto err_dev;
+
+ /* Get exclusive use of fpga manager */
+ if (!mutex_trylock(&mgr->ref_mutex)) {
+ ret = -EBUSY;
+ goto err_dev;
+ }
+
+ if (!try_module_get(dev->parent->driver->owner))
+ goto err_ll_mod;
+
+ return mgr;
+
+err_ll_mod:
+ mutex_unlock(&mgr->ref_mutex);
+err_dev:
+ put_device(dev);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
+
+/**
+ * fpga_mgr_put - release a reference to a fpga manager
+ * @mgr: fpga manager structure
+ */
+void fpga_mgr_put(struct fpga_manager *mgr)
+{
+ module_put(mgr->dev.parent->driver->owner);
+ mutex_unlock(&mgr->ref_mutex);
+ put_device(&mgr->dev);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_put);
+
+/**
+ * fpga_mgr_register - register a low level fpga manager driver
+ * @dev: fpga manager device from pdev
+ * @name: fpga manager name
+ * @mops: pointer to structure of fpga manager ops
+ * @priv: fpga manager private data
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_mgr_register(struct device *dev, const char *name,
+ const struct fpga_manager_ops *mops,
+ void *priv)
+{
+ struct fpga_manager *mgr;
+ const char *dt_label;
+ int id, ret;
+
+ if (!mops || !mops->write_init || !mops->write ||
+ !mops->write_complete || !mops->state) {
+ dev_err(dev, "Attempt to register without fpga_manager_ops\n");
+ return -EINVAL;
+ }
+
+ if (!name || !strlen(name)) {
+ dev_err(dev, "Attempt to register with no name!\n");
+ return -EINVAL;
+ }
+
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+ if (!mgr)
+ return -ENOMEM;
+
+ id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
+ if (id < 0) {
+ ret = id;
+ goto error_kfree;
+ }
+
+ mutex_init(&mgr->ref_mutex);
+
+ mgr->name = name;
+ mgr->mops = mops;
+ mgr->priv = priv;
+
+ /*
+ * Initialize framework state by requesting low level driver read state
+ * from device. FPGA may be in reset mode or may have been programmed
+ * by bootloader or EEPROM.
+ */
+ mgr->state = mgr->mops->state(mgr);
+
+ device_initialize(&mgr->dev);
+ mgr->dev.class = fpga_mgr_class;
+ mgr->dev.parent = dev;
+ mgr->dev.of_node = dev->of_node;
+ mgr->dev.id = id;
+ dev_set_drvdata(dev, mgr);
+
+ dt_label = of_get_property(mgr->dev.of_node, "label", NULL);
+ if (dt_label)
+ ret = dev_set_name(&mgr->dev, "%s", dt_label);
+ else
+ ret = dev_set_name(&mgr->dev, "fpga%d", id);
+
+ ret = device_add(&mgr->dev);
+ if (ret)
+ goto error_device;
+
+ dev_info(&mgr->dev, "%s registered\n", mgr->name);
+
+ return 0;
+
+error_device:
+ ida_simple_remove(&fpga_mgr_ida, id);
+error_kfree:
+ kfree(mgr);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_register);
+
+/**
+ * fpga_mgr_unregister - unregister a low level fpga manager driver
+ * @dev: fpga manager device from pdev
+ */
+void fpga_mgr_unregister(struct device *dev)
+{
+ struct fpga_manager *mgr = dev_get_drvdata(dev);
+
+ dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);
+
+ /*
+ * If the low level driver provides a method for putting fpga into
+ * a desired state upon unregister, do it.
+ */
+ if (mgr->mops->fpga_remove)
+ mgr->mops->fpga_remove(mgr);
+
+ device_unregister(&mgr->dev);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_unregister);
+
+static void fpga_mgr_dev_release(struct device *dev)
+{
+ struct fpga_manager *mgr = to_fpga_manager(dev);
+
+ ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
+ kfree(mgr);
+}
+
+static int __init fpga_mgr_class_init(void)
+{
+ pr_info("FPGA manager framework\n");
+
+ fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
+ if (IS_ERR(fpga_mgr_class))
+ return PTR_ERR(fpga_mgr_class);
+
+ fpga_mgr_class->dev_groups = fpga_mgr_groups;
+ fpga_mgr_class->dev_release = fpga_mgr_dev_release;
+
+ return 0;
+}
+
+static void __exit fpga_mgr_class_exit(void)
+{
+ class_destroy(fpga_mgr_class);
+ ida_destroy(&fpga_mgr_ida);
+}
+
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_DESCRIPTION("FPGA manager framework");
+MODULE_LICENSE("GPL v2");
+
+subsys_initcall(fpga_mgr_class_init);
+module_exit(fpga_mgr_class_exit);
diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c
new file mode 100644
index 000000000000..27d2ff28132c
--- /dev/null
+++ b/drivers/fpga/socfpga.c
@@ -0,0 +1,616 @@
+/*
+ * FPGA Manager Driver for Altera SOCFPGA
+ *
+ * Copyright (C) 2013-2015 Altera 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.
+ *
+ * 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/completion.h>
+#include <linux/delay.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/pm.h>
+
+/* Register offsets */
+#define SOCFPGA_FPGMGR_STAT_OFST 0x0
+#define SOCFPGA_FPGMGR_CTL_OFST 0x4
+#define SOCFPGA_FPGMGR_DCLKCNT_OFST 0x8
+#define SOCFPGA_FPGMGR_DCLKSTAT_OFST 0xc
+#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST 0x830
+#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST 0x834
+#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST 0x838
+#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST 0x83c
+#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST 0x840
+#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST 0x844
+#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST 0x84c
+#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST 0x850
+
+/* Register bit defines */
+/* SOCFPGA_FPGMGR_STAT register mode field values */
+#define SOCFPGA_FPGMGR_STAT_POWER_UP 0x0 /*ramping*/
+#define SOCFPGA_FPGMGR_STAT_RESET 0x1
+#define SOCFPGA_FPGMGR_STAT_CFG 0x2
+#define SOCFPGA_FPGMGR_STAT_INIT 0x3
+#define SOCFPGA_FPGMGR_STAT_USER_MODE 0x4
+#define SOCFPGA_FPGMGR_STAT_UNKNOWN 0x5
+#define SOCFPGA_FPGMGR_STAT_STATE_MASK 0x7
+/* This is a flag value that doesn't really happen in this register field */
+#define SOCFPGA_FPGMGR_STAT_POWER_OFF 0x0
+
+#define MSEL_PP16_FAST_NOAES_NODC 0x0
+#define MSEL_PP16_FAST_AES_NODC 0x1
+#define MSEL_PP16_FAST_AESOPT_DC 0x2
+#define MSEL_PP16_SLOW_NOAES_NODC 0x4
+#define MSEL_PP16_SLOW_AES_NODC 0x5
+#define MSEL_PP16_SLOW_AESOPT_DC 0x6
+#define MSEL_PP32_FAST_NOAES_NODC 0x8
+#define MSEL_PP32_FAST_AES_NODC 0x9
+#define MSEL_PP32_FAST_AESOPT_DC 0xa
+#define MSEL_PP32_SLOW_NOAES_NODC 0xc
+#define MSEL_PP32_SLOW_AES_NODC 0xd
+#define MSEL_PP32_SLOW_AESOPT_DC 0xe
+#define SOCFPGA_FPGMGR_STAT_MSEL_MASK 0x000000f8
+#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT 3
+
+/* SOCFPGA_FPGMGR_CTL register */
+#define SOCFPGA_FPGMGR_CTL_EN 0x00000001
+#define SOCFPGA_FPGMGR_CTL_NCE 0x00000002
+#define SOCFPGA_FPGMGR_CTL_NCFGPULL 0x00000004
+
+#define CDRATIO_X1 0x00000000
+#define CDRATIO_X2 0x00000040
+#define CDRATIO_X4 0x00000080
+#define CDRATIO_X8 0x000000c0
+#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK 0x000000c0
+
+#define SOCFPGA_FPGMGR_CTL_AXICFGEN 0x00000100
+
+#define CFGWDTH_16 0x00000000
+#define CFGWDTH_32 0x00000200
+#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK 0x00000200
+
+/* SOCFPGA_FPGMGR_DCLKSTAT register */
+#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE 0x1
+
+/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */
+#define SOCFPGA_FPGMGR_MON_NSTATUS 0x0001
+#define SOCFPGA_FPGMGR_MON_CONF_DONE 0x0002
+#define SOCFPGA_FPGMGR_MON_INIT_DONE 0x0004
+#define SOCFPGA_FPGMGR_MON_CRC_ERROR 0x0008
+#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE 0x0010
+#define SOCFPGA_FPGMGR_MON_PR_READY 0x0020
+#define SOCFPGA_FPGMGR_MON_PR_ERROR 0x0040
+#define SOCFPGA_FPGMGR_MON_PR_DONE 0x0080
+#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN 0x0100
+#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN 0x0200
+#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN 0x0400
+#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON 0x0800
+#define SOCFPGA_FPGMGR_MON_STATUS_MASK 0x0fff
+
+#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3
+#define SOCFPGA_RESUME_TIMEOUT 3
+
+/* In power-up order. Reverse for power-down. */
+static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = {
+ "FPGA-1.5V",
+ "FPGA-1.1V",
+ "FPGA-2.5V",
+};
+
+struct socfpga_fpga_priv {
+ void __iomem *fpga_base_addr;
+ void __iomem *fpga_data_addr;
+ struct completion status_complete;
+ int irq;
+};
+
+struct cfgmgr_mode {
+ /* Values to set in the CTRL register */
+ u32 ctrl;
+
+ /* flag that this table entry is a valid mode */
+ bool valid;
+};
+
+/* For SOCFPGA_FPGMGR_STAT_MSEL field */
+static struct cfgmgr_mode cfgmgr_modes[] = {
+ [MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
+ [MSEL_PP16_FAST_AES_NODC] = { CFGWDTH_16 | CDRATIO_X2, 1 },
+ [MSEL_PP16_FAST_AESOPT_DC] = { CFGWDTH_16 | CDRATIO_X4, 1 },
+ [MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
+ [MSEL_PP16_SLOW_AES_NODC] = { CFGWDTH_16 | CDRATIO_X2, 1 },
+ [MSEL_PP16_SLOW_AESOPT_DC] = { CFGWDTH_16 | CDRATIO_X4, 1 },
+ [MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
+ [MSEL_PP32_FAST_AES_NODC] = { CFGWDTH_32 | CDRATIO_X4, 1 },
+ [MSEL_PP32_FAST_AESOPT_DC] = { CFGWDTH_32 | CDRATIO_X8, 1 },
+ [MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
+ [MSEL_PP32_SLOW_AES_NODC] = { CFGWDTH_32 | CDRATIO_X4, 1 },
+ [MSEL_PP32_SLOW_AESOPT_DC] = { CFGWDTH_32 | CDRATIO_X8, 1 },
+};
+
+static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset)
+{
+ return readl(priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset,
+ u32 value)
+{
+ writel(value, priv->fpga_base_addr + reg_offset);
+}
+
+static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv,
+ u32 reg_offset)
+{
+ return __raw_readl(priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv,
+ u32 reg_offset, u32 value)
+{
+ __raw_writel(value, priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value)
+{
+ writel(value, priv->fpga_data_addr);
+}
+
+static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv,
+ u32 offset, u32 bits)
+{
+ u32 val;
+
+ val = socfpga_fpga_readl(priv, offset);
+ val |= bits;
+ socfpga_fpga_writel(priv, offset, val);
+}
+
+static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv,
+ u32 offset, u32 bits)
+{
+ u32 val;
+
+ val = socfpga_fpga_readl(priv, offset);
+ val &= ~bits;
+ socfpga_fpga_writel(priv, offset, val);
+}
+
+static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv)
+{
+ return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) &
+ SOCFPGA_FPGMGR_MON_STATUS_MASK;
+}
+
+static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv)
+{
+ u32 status = socfpga_fpga_mon_status_get(priv);
+
+ if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0)
+ return SOCFPGA_FPGMGR_STAT_POWER_OFF;
+
+ return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) &
+ SOCFPGA_FPGMGR_STAT_STATE_MASK;
+}
+
+static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv)
+{
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST,
+ SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE);
+}
+
+/*
+ * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear
+ * the complete status.
+ */
+static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv,
+ u32 count)
+{
+ int timeout = 2;
+ u32 done;
+
+ /* Clear any existing DONE status. */
+ if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST))
+ socfpga_fpga_clear_done_status(priv);
+
+ /* Issue the DCLK count. */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count);
+
+ /* Poll DCLKSTAT to see if it completed in the timeout period. */
+ do {
+ done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST);
+ if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) {
+ socfpga_fpga_clear_done_status(priv);
+ return 0;
+ }
+ udelay(1);
+ } while (timeout--);
+
+ return -ETIMEDOUT;
+}
+
+static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv,
+ u32 state)
+{
+ int timeout = 2;
+
+ /*
+ * HW doesn't support an interrupt for changes in state, so poll to see
+ * if it matches the requested state within the timeout period.
+ */
+ do {
+ if ((socfpga_fpga_state_get(priv) & state) != 0)
+ return 0;
+ msleep(20);
+ } while (timeout--);
+
+ return -ETIMEDOUT;
+}
+
+static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs)
+{
+ /* set irqs to level sensitive */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0);
+
+ /* set interrupt polarity */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs);
+
+ /* clear irqs */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
+
+ /* unmask interrupts */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0);
+
+ /* enable interrupts */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs);
+}
+
+static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv)
+{
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
+}
+
+static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
+{
+ struct socfpga_fpga_priv *priv = dev_id;
+ u32 irqs, st;
+ bool conf_done, nstatus;
+
+ /* clear irqs */
+ irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST);
+
+ socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
+
+ st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST);
+ conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0;
+ nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0;
+
+ /* success */
+ if (conf_done && nstatus) {
+ /* disable irqs */
+ socfpga_fpga_raw_writel(priv,
+ SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
+ complete(&priv->status_complete);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
+{
+ int timeout, ret = 0;
+
+ socfpga_fpga_disable_irqs(priv);
+ init_completion(&priv->status_complete);
+ socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
+
+ timeout = wait_for_completion_interruptible_timeout(
+ &priv->status_complete,
+ msecs_to_jiffies(10));
+ if (timeout == 0)
+ ret = -ETIMEDOUT;
+
+ socfpga_fpga_disable_irqs(priv);
+ return ret;
+}
+
+static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv)
+{
+ u32 msel;
+
+ msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST);
+ msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK;
+ msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT;
+
+ /* Check that this MSEL setting is supported */
+ if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid)
+ return -EINVAL;
+
+ return msel;
+}
+
+static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv)
+{
+ u32 ctrl_reg;
+ int mode;
+
+ /* get value from MSEL pins */
+ mode = socfpga_fpga_cfg_mode_get(priv);
+ if (mode < 0)
+ return mode;
+
+ /* Adjust CTRL for the CDRATIO */
+ ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
+ ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK;
+ ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK;
+ ctrl_reg |= cfgmgr_modes[mode].ctrl;
+
+ /* Set NCE to 0. */
+ ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE;
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+ return 0;
+}
+
+static int socfpga_fpga_reset(struct fpga_manager *mgr)
+{
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ u32 ctrl_reg, status;
+ int ret;
+
+ /*
+ * Step 1:
+ * - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode
+ * - Set CTRL.NCE to 0
+ */
+ ret = socfpga_fpga_cfg_mode_set(priv);
+ if (ret)
+ return ret;
+
+ /* Step 2: Set CTRL.EN to 1 */
+ socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+ SOCFPGA_FPGMGR_CTL_EN);
+
+ /* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */
+ ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
+ ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL;
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+ /* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */
+ status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET);
+
+ /* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */
+ ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL;
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+ /* Timeout waiting for reset */
+ if (status)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/*
+ * Prepare the FPGA to receive the configuration data.
+ */
+static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr, u32 flags,
+ const char *buf, size_t count)
+{
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ int ret;
+
+ if (flags & FPGA_MGR_PARTIAL_RECONFIG) {
+ dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
+ return -EINVAL;
+ }
+ /* Steps 1 - 5: Reset the FPGA */
+ ret = socfpga_fpga_reset(mgr);
+ if (ret)
+ return ret;
+
+ /* Step 6: Wait for FPGA to enter configuration phase */
+ if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG))
+ return -ETIMEDOUT;
+
+ /* Step 7: Clear nSTATUS interrupt */
+ socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST,
+ SOCFPGA_FPGMGR_MON_NSTATUS);
+
+ /* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */
+ socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+ SOCFPGA_FPGMGR_CTL_AXICFGEN);
+
+ return 0;
+}
+
+/*
+ * Step 9: write data to the FPGA data register
+ */
+static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr,
+ const char *buf, size_t count)
+{
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ u32 *buffer_32 = (u32 *)buf;
+ size_t i = 0;
+
+ if (count <= 0)
+ return -EINVAL;
+
+ /* Write out the complete 32-bit chunks. */
+ while (count >= sizeof(u32)) {
+ socfpga_fpga_data_writel(priv, buffer_32[i++]);
+ count -= sizeof(u32);
+ }
+
+ /* Write out remaining non 32-bit chunks. */
+ switch (count) {
+ case 3:
+ socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
+ break;
+ case 2:
+ socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
+ break;
+ case 1:
+ socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
+ break;
+ case 0:
+ break;
+ default:
+ /* This will never happen. */
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr,
+ u32 flags)
+{
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ u32 status;
+
+ /*
+ * Step 10:
+ * - Observe CONF_DONE and nSTATUS (active low)
+ * - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful
+ * - if CONF_DONE = 0 and nSTATUS = 0, configuration failed
+ */
+ status = socfpga_fpga_wait_for_config_done(priv);
+ if (status)
+ return status;
+
+ /* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */
+ socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+ SOCFPGA_FPGMGR_CTL_AXICFGEN);
+
+ /*
+ * Step 12:
+ * - Write 4 to DCLKCNT
+ * - Wait for STATUS.DCNTDONE = 1
+ * - Clear W1C bit in STATUS.DCNTDONE
+ */
+ if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4))
+ return -ETIMEDOUT;
+
+ /* Step 13: Wait for STATUS.MODE to report USER MODE */
+ if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE))
+ return -ETIMEDOUT;
+
+ /* Step 14: Set CTRL.EN to 0 */
+ socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+ SOCFPGA_FPGMGR_CTL_EN);
+
+ return 0;
+}
+
+/* Translate state register values to FPGA framework state */
+static const enum fpga_mgr_states socfpga_state_to_framework_state[] = {
+ [SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF,
+ [SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET,
+ [SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT,
+ [SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT,
+ [SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING,
+ [SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN,
+};
+
+static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr)
+{
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ enum fpga_mgr_states ret;
+ u32 state;
+
+ state = socfpga_fpga_state_get(priv);
+
+ if (state < ARRAY_SIZE(socfpga_state_to_framework_state))
+ ret = socfpga_state_to_framework_state[state];
+ else
+ ret = FPGA_MGR_STATE_UNKNOWN;
+
+ return ret;
+}
+
+static const struct fpga_manager_ops socfpga_fpga_ops = {
+ .state = socfpga_fpga_ops_state,
+ .write_init = socfpga_fpga_ops_configure_init,
+ .write = socfpga_fpga_ops_configure_write,
+ .write_complete = socfpga_fpga_ops_configure_complete,
+};
+
+static int socfpga_fpga_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct socfpga_fpga_priv *priv;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->fpga_base_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->fpga_base_addr))
+ return PTR_ERR(priv->fpga_base_addr);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->fpga_data_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->fpga_data_addr))
+ return PTR_ERR(priv->fpga_data_addr);
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0)
+ return priv->irq;
+
+ ret = devm_request_irq(dev, priv->irq, socfpga_fpga_isr, 0,
+ dev_name(dev), priv);
+ if (ret)
+ return ret;
+
+ return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
+ &socfpga_fpga_ops, priv);
+}
+
+static int socfpga_fpga_remove(struct platform_device *pdev)
+{
+ fpga_mgr_unregister(&pdev->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id socfpga_fpga_of_match[] = {
+ { .compatible = "altr,socfpga-fpga-mgr", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, socfpga_fpga_of_match);
+#endif
+
+static struct platform_driver socfpga_fpga_driver = {
+ .probe = socfpga_fpga_probe,
+ .remove = socfpga_fpga_remove,
+ .driver = {
+ .name = "socfpga_fpga_manager",
+ .of_match_table = of_match_ptr(socfpga_fpga_of_match),
+ },
+};
+
+module_platform_driver(socfpga_fpga_driver);
+
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_DESCRIPTION("Altera SOCFPGA FPGA Manager");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
new file mode 100644
index 000000000000..c2fb4120bd62
--- /dev/null
+++ b/drivers/fpga/zynq-fpga.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2011-2015 Xilinx Inc.
+ * Copyright (c) 2015, National Instruments Corp.
+ *
+ * FPGA Manager Driver for Xilinx Zynq, heavily based on xdevcfg driver
+ * in their vendor tree.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/string.h>
+
+/* Offsets into SLCR regmap */
+
+/* FPGA Software Reset Control */
+#define SLCR_FPGA_RST_CTRL_OFFSET 0x240
+/* Level Shifters Enable */
+#define SLCR_LVL_SHFTR_EN_OFFSET 0x900
+
+/* Constant Definitions */
+
+/* Control Register */
+#define CTRL_OFFSET 0x00
+/* Lock Register */
+#define LOCK_OFFSET 0x04
+/* Interrupt Status Register */
+#define INT_STS_OFFSET 0x0c
+/* Interrupt Mask Register */
+#define INT_MASK_OFFSET 0x10
+/* Status Register */
+#define STATUS_OFFSET 0x14
+/* DMA Source Address Register */
+#define DMA_SRC_ADDR_OFFSET 0x18
+/* DMA Destination Address Reg */
+#define DMA_DST_ADDR_OFFSET 0x1c
+/* DMA Source Transfer Length */
+#define DMA_SRC_LEN_OFFSET 0x20
+/* DMA Destination Transfer */
+#define DMA_DEST_LEN_OFFSET 0x24
+/* Unlock Register */
+#define UNLOCK_OFFSET 0x34
+/* Misc. Control Register */
+#define MCTRL_OFFSET 0x80
+
+/* Control Register Bit definitions */
+
+/* Signal to reset FPGA */
+#define CTRL_PCFG_PROG_B_MASK BIT(30)
+/* Enable PCAP for PR */
+#define CTRL_PCAP_PR_MASK BIT(27)
+/* Enable PCAP */
+#define CTRL_PCAP_MODE_MASK BIT(26)
+
+/* Miscellaneous Control Register bit definitions */
+/* Internal PCAP loopback */
+#define MCTRL_PCAP_LPBK_MASK BIT(4)
+
+/* Status register bit definitions */
+
+/* FPGA init status */
+#define STATUS_DMA_Q_F BIT(31)
+#define STATUS_PCFG_INIT_MASK BIT(4)
+
+/* Interrupt Status/Mask Register Bit definitions */
+/* DMA command done */
+#define IXR_DMA_DONE_MASK BIT(13)
+/* DMA and PCAP cmd done */
+#define IXR_D_P_DONE_MASK BIT(12)
+ /* FPGA programmed */
+#define IXR_PCFG_DONE_MASK BIT(2)
+#define IXR_ERROR_FLAGS_MASK 0x00F0F860
+#define IXR_ALL_MASK 0xF8F7F87F
+
+/* Miscellaneous constant values */
+
+/* Invalid DMA addr */
+#define DMA_INVALID_ADDRESS GENMASK(31, 0)
+/* Used to unlock the dev */
+#define UNLOCK_MASK 0x757bdf0d
+/* Timeout for DMA to complete */
+#define DMA_DONE_TIMEOUT msecs_to_jiffies(1000)
+/* Timeout for polling reset bits */
+#define INIT_POLL_TIMEOUT 2500000
+/* Delay for polling reset bits */
+#define INIT_POLL_DELAY 20
+
+/* Masks for controlling stuff in SLCR */
+/* Disable all Level shifters */
+#define LVL_SHFTR_DISABLE_ALL_MASK 0x0
+/* Enable Level shifters from PS to PL */
+#define LVL_SHFTR_ENABLE_PS_TO_PL 0xa
+/* Enable Level shifters from PL to PS */
+#define LVL_SHFTR_ENABLE_PL_TO_PS 0xf
+/* Enable global resets */
+#define FPGA_RST_ALL_MASK 0xf
+/* Disable global resets */
+#define FPGA_RST_NONE_MASK 0x0
+
+struct zynq_fpga_priv {
+ struct device *dev;
+ int irq;
+ struct clk *clk;
+
+ void __iomem *io_base;
+ struct regmap *slcr;
+
+ struct completion dma_done;
+};
+
+static inline void zynq_fpga_write(struct zynq_fpga_priv *priv, u32 offset,
+ u32 val)
+{
+ writel(val, priv->io_base + offset);
+}
+
+static inline u32 zynq_fpga_read(const struct zynq_fpga_priv *priv,
+ u32 offset)
+{
+ return readl(priv->io_base + offset);
+}
+
+#define zynq_fpga_poll_timeout(priv, addr, val, cond, sleep_us, timeout_us) \
+ readl_poll_timeout(priv->io_base + addr, val, cond, sleep_us, \
+ timeout_us)
+
+static void zynq_fpga_mask_irqs(struct zynq_fpga_priv *priv)
+{
+ u32 intr_mask;
+
+ intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
+ zynq_fpga_write(priv, INT_MASK_OFFSET,
+ intr_mask | IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK);
+}
+
+static void zynq_fpga_unmask_irqs(struct zynq_fpga_priv *priv)
+{
+ u32 intr_mask;
+
+ intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
+ zynq_fpga_write(priv, INT_MASK_OFFSET,
+ intr_mask
+ & ~(IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK));
+}
+
+static irqreturn_t zynq_fpga_isr(int irq, void *data)
+{
+ struct zynq_fpga_priv *priv = data;
+
+ /* disable DMA and error IRQs */
+ zynq_fpga_mask_irqs(priv);
+
+ complete(&priv->dma_done);
+
+ return IRQ_HANDLED;
+}
+
+static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
+ const char *buf, size_t count)
+{
+ struct zynq_fpga_priv *priv;
+ u32 ctrl, status;
+ int err;
+
+ priv = mgr->priv;
+
+ err = clk_enable(priv->clk);
+ if (err)
+ return err;
+
+ /* don't globally reset PL if we're doing partial reconfig */
+ if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ /* assert AXI interface resets */
+ regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
+ FPGA_RST_ALL_MASK);
+
+ /* disable all level shifters */
+ regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
+ LVL_SHFTR_DISABLE_ALL_MASK);
+ /* enable level shifters from PS to PL */
+ regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
+ LVL_SHFTR_ENABLE_PS_TO_PL);
+
+ /* create a rising edge on PCFG_INIT. PCFG_INIT follows
+ * PCFG_PROG_B, so we need to poll it after setting PCFG_PROG_B
+ * to make sure the rising edge actually happens.
+ * Note: PCFG_PROG_B is low active, sequence as described in
+ * UG585 v1.10 page 211
+ */
+ ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
+ ctrl |= CTRL_PCFG_PROG_B_MASK;
+
+ zynq_fpga_write(priv, CTRL_OFFSET, ctrl);
+
+ err = zynq_fpga_poll_timeout(priv, STATUS_OFFSET, status,
+ status & STATUS_PCFG_INIT_MASK,
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+ dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+ goto out_err;
+ }
+
+ ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
+ ctrl &= ~CTRL_PCFG_PROG_B_MASK;
+
+ zynq_fpga_write(priv, CTRL_OFFSET, ctrl);
+
+ err = zynq_fpga_poll_timeout(priv, STATUS_OFFSET, status,
+ !(status & STATUS_PCFG_INIT_MASK),
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+ dev_err(priv->dev, "Timeout waiting for !PCFG_INIT");
+ goto out_err;
+ }
+
+ ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
+ ctrl |= CTRL_PCFG_PROG_B_MASK;
+
+ zynq_fpga_write(priv, CTRL_OFFSET, ctrl);
+
+ err = zynq_fpga_poll_timeout(priv, STATUS_OFFSET, status,
+ status & STATUS_PCFG_INIT_MASK,
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+ dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+ goto out_err;
+ }
+ }
+
+ /* set configuration register with following options:
+ * - enable PCAP interface
+ * - set throughput for maximum speed
+ * - set CPU in user mode
+ */
+ ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
+ zynq_fpga_write(priv, CTRL_OFFSET,
+ (CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK | ctrl));
+
+ /* check that we have room in the command queue */
+ status = zynq_fpga_read(priv, STATUS_OFFSET);
+ if (status & STATUS_DMA_Q_F) {
+ dev_err(priv->dev, "DMA command queue full");
+ err = -EBUSY;
+ goto out_err;
+ }
+
+ /* ensure internal PCAP loopback is disabled */
+ ctrl = zynq_fpga_read(priv, MCTRL_OFFSET);
+ zynq_fpga_write(priv, MCTRL_OFFSET, (~MCTRL_PCAP_LPBK_MASK & ctrl));
+
+ clk_disable(priv->clk);
+
+ return 0;
+
+out_err:
+ clk_disable(priv->clk);
+
+ return err;
+}
+
+static int zynq_fpga_ops_write(struct fpga_manager *mgr,
+ const char *buf, size_t count)
+{
+ struct zynq_fpga_priv *priv;
+ int err;
+ char *kbuf;
+ size_t in_count;
+ dma_addr_t dma_addr;
+ u32 transfer_length;
+ u32 intr_status;
+
+ in_count = count;
+ priv = mgr->priv;
+
+ kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+ memcpy(kbuf, buf, count);
+
+ /* enable clock */
+ err = clk_enable(priv->clk);
+ if (err)
+ goto out_free;
+
+ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+
+ reinit_completion(&priv->dma_done);
+
+ /* enable DMA and error IRQs */
+ zynq_fpga_unmask_irqs(priv);
+
+ /* the +1 in the src addr is used to hold off on DMA_DONE IRQ
+ * until both AXI and PCAP are done ...
+ */
+ zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, (u32)(dma_addr) + 1);
+ zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, (u32)DMA_INVALID_ADDRESS);
+
+ /* convert #bytes to #words */
+ transfer_length = (count + 3) / 4;
+
+ zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, transfer_length);
+ zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
+
+ wait_for_completion(&priv->dma_done);
+
+ intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
+ zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
+
+ if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
+ dev_err(priv->dev, "Error configuring FPGA");
+ err = -EFAULT;
+ }
+
+ clk_disable(priv->clk);
+
+out_free:
+ dma_free_coherent(priv->dev, in_count, kbuf, dma_addr);
+
+ return err;
+}
+
+static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr, u32 flags)
+{
+ struct zynq_fpga_priv *priv = mgr->priv;
+ int err;
+ u32 intr_status;
+
+ err = clk_enable(priv->clk);
+ if (err)
+ return err;
+
+ err = zynq_fpga_poll_timeout(priv, INT_STS_OFFSET, intr_status,
+ intr_status & IXR_PCFG_DONE_MASK,
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+
+ clk_disable(priv->clk);
+
+ if (err)
+ return err;
+
+ /* for the partial reconfig case we didn't touch the level shifters */
+ if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ /* enable level shifters from PL to PS */
+ regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
+ LVL_SHFTR_ENABLE_PL_TO_PS);
+
+ /* deassert AXI interface resets */
+ regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
+ FPGA_RST_NONE_MASK);
+ }
+
+ return 0;
+}
+
+static enum fpga_mgr_states zynq_fpga_ops_state(struct fpga_manager *mgr)
+{
+ int err;
+ u32 intr_status;
+ struct zynq_fpga_priv *priv;
+
+ priv = mgr->priv;
+
+ err = clk_enable(priv->clk);
+ if (err)
+ return FPGA_MGR_STATE_UNKNOWN;
+
+ intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
+ clk_disable(priv->clk);
+
+ if (intr_status & IXR_PCFG_DONE_MASK)
+ return FPGA_MGR_STATE_OPERATING;
+
+ return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static const struct fpga_manager_ops zynq_fpga_ops = {
+ .state = zynq_fpga_ops_state,
+ .write_init = zynq_fpga_ops_write_init,
+ .write = zynq_fpga_ops_write,
+ .write_complete = zynq_fpga_ops_write_complete,
+};
+
+static int zynq_fpga_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct zynq_fpga_priv *priv;
+ struct resource *res;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->io_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->io_base))
+ return PTR_ERR(priv->io_base);
+
+ priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "syscon");
+ if (IS_ERR(priv->slcr)) {
+ dev_err(dev, "unable to get zynq-slcr regmap");
+ return PTR_ERR(priv->slcr);
+ }
+
+ init_completion(&priv->dma_done);
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0) {
+ dev_err(dev, "No IRQ available");
+ return priv->irq;
+ }
+
+ err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
+ dev_name(dev), priv);
+ if (err) {
+ dev_err(dev, "unable to request IRQ");
+ return err;
+ }
+
+ priv->clk = devm_clk_get(dev, "ref_clk");
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "input clock not found");
+ return PTR_ERR(priv->clk);
+ }
+
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+ dev_err(dev, "unable to enable clock");
+ return err;
+ }
+
+ /* unlock the device */
+ zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
+
+ clk_disable(priv->clk);
+
+ err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
+ &zynq_fpga_ops, priv);
+ if (err) {
+ dev_err(dev, "unable to register FPGA manager");
+ clk_unprepare(priv->clk);
+ return err;
+ }
+
+ return 0;
+}
+
+static int zynq_fpga_remove(struct platform_device *pdev)
+{
+ struct zynq_fpga_priv *priv;
+ struct fpga_manager *mgr;
+
+ mgr = platform_get_drvdata(pdev);
+ priv = mgr->priv;
+
+ fpga_mgr_unregister(&pdev->dev);
+
+ clk_unprepare(priv->clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id zynq_fpga_of_match[] = {
+ { .compatible = "xlnx,zynq-devcfg-1.0", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, zynq_fpga_of_match);
+#endif
+
+static struct platform_driver zynq_fpga_driver = {
+ .probe = zynq_fpga_probe,
+ .remove = zynq_fpga_remove,
+ .driver = {
+ .name = "zynq_fpga_manager",
+ .of_match_table = of_match_ptr(zynq_fpga_of_match),
+ },
+};
+
+module_platform_driver(zynq_fpga_driver);
+
+MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
+MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx Zynq FPGA Manager");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8949b3f6f74d..b18bea08ff25 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -119,6 +119,13 @@ config GPIO_ALTERA
If driver is built as a module it will be called gpio-altera.
+config GPIO_AMDPT
+ tristate "AMD Promontory GPIO support"
+ depends on ACPI
+ help
+ driver for GPIO functionality on Promontory IOHub
+ Require ACPI ASL code to enumerate as a platform device.
+
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
@@ -176,16 +183,6 @@ config GPIO_ETRAXFS
help
Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
-config GPIO_F7188X
- tristate "F71869, F71869A, F71882FG and F71889F GPIO support"
- depends on X86
- help
- This option enables support for GPIOs found on Fintek Super-I/O
- chips F71869, F71869A, F71882FG and F71889F.
-
- To compile this driver as a module, choose M here: the module will
- be called f7188x-gpio.
-
config GPIO_GE_FPGA
bool "GE FPGA based GPIO"
depends on GE_FPGA
@@ -235,12 +232,6 @@ config GPIO_IOP
If unsure, say N.
-config GPIO_IT8761E
- tristate "IT8761E GPIO support"
- depends on X86 # unconditional access to IO space.
- help
- Say yes here to support GPIO functionality of IT8761E super I/O chip.
-
config GPIO_LOONGSON
bool "Loongson-2/3 GPIO support"
depends on CPU_LOONGSON2 || CPU_LOONGSON3
@@ -297,14 +288,6 @@ config GPIO_MPC8XXX
Say Y here if you're going to use hardware that connects to the
MPC512x/831x/834x/837x/8572/8610 GPIOs.
-config GPIO_MSM_V2
- tristate "Qualcomm MSM GPIO v2"
- depends on GPIOLIB && OF && ARCH_QCOM
- help
- Say yes here to support the GPIO interface on ARM v7 based
- Qualcomm MSM chips. Most of the pins on the MSM can be
- selected for GPIO, and are controlled by this driver.
-
config GPIO_MVEBU
def_bool y
depends on PLAT_ORION
@@ -368,42 +351,6 @@ config GPIO_SAMSUNG
Legacy GPIO support. Use only for platforms without support for
pinctrl.
-config GPIO_SCH
- tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
- depends on PCI && X86
- select MFD_CORE
- select LPC_SCH
- help
- Say yes here to support GPIO interface on Intel Poulsbo SCH,
- Intel Tunnel Creek processor, Intel Centerton processor or
- Intel Quark X1000 SoC.
-
- The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
- powered by the core power rail and are turned off during sleep
- modes (S3 and higher). The remaining four GPIOs are powered by
- the Intel SCH suspend power supply. These GPIOs remain
- active during S3. The suspend powered GPIOs can be used to wake the
- system from the Suspend-to-RAM state.
-
- The Intel Tunnel Creek processor has 5 GPIOs powered by the
- core power rail and 9 from suspend power supply.
-
- The Intel Centerton processor has a total of 30 GPIO pins.
- Twenty-one are powered by the core power rail and 9 from the
- suspend power supply.
-
- The Intel Quark X1000 SoC has 2 GPIOs powered by the core
- power well and 6 from the suspend power well.
-
-config GPIO_SCH311X
- tristate "SMSC SCH311x SuperI/O GPIO"
- help
- Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and
- SCH3116 "Super I/O" chipsets.
-
- To compile this driver as a module, choose M here: the module will
- be called gpio-sch311x.
-
config GPIO_SPEAR_SPICS
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
depends on PLAT_SPEAR
@@ -440,15 +387,6 @@ config GPIO_TB10X
select GENERIC_IRQ_CHIP
select OF_GPIO
-config GPIO_TS5500
- tristate "TS-5500 DIO blocks and compatibles"
- depends on TS5500 || COMPILE_TEST
- help
- This driver supports Digital I/O exposed by pin blocks found on some
- Technologic Systems platforms. It includes, but is not limited to, 3
- blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
- LCD port.
-
config GPIO_TZ1090
bool "Toumaz Xenif TZ1090 GPIO support"
depends on SOC_TZ1090
@@ -508,13 +446,13 @@ config GPIO_XGENE_SB
config GPIO_XILINX
tristate "Xilinx GPIO support"
- depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86)
+ depends on OF_GPIO
help
Say yes here to support the Xilinx FPGA GPIO device
config GPIO_XLP
tristate "Netlogic XLP GPIO support"
- depends on CPU_XLP
+ depends on CPU_XLP && OF_GPIO
select GPIOLIB_IRQCHIP
help
This driver provides support for GPIO interface on Netlogic XLP MIPS64
@@ -545,6 +483,87 @@ config GPIO_ZYNQ
help
Say yes here to support Xilinx Zynq GPIO controller.
+config GPIO_ZX
+ bool "ZTE ZX GPIO support"
+ select GPIOLIB_IRQCHIP
+ help
+ Say yes here to support the GPIO device on ZTE ZX SoCs.
+
+endmenu
+
+menu "Port-mapped I/O GPIO drivers"
+ depends on X86 # Unconditional I/O space access
+
+config GPIO_104_IDIO_16
+ tristate "ACCES 104-IDIO-16 GPIO support"
+ help
+ Enables GPIO support for the ACCES 104-IDIO-16 family.
+
+config GPIO_F7188X
+ tristate "F71869, F71869A, F71882FG and F71889F GPIO support"
+ help
+ This option enables support for GPIOs found on Fintek Super-I/O
+ chips F71869, F71869A, F71882FG and F71889F.
+
+ To compile this driver as a module, choose M here: the module will
+ be called f7188x-gpio.
+
+config GPIO_IT87
+ tristate "IT87xx GPIO support"
+ help
+ Say yes here to support GPIO functionality of IT87xx Super I/O chips.
+
+ This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and
+ supports the IT8761E Super I/O chip as well.
+
+ To compile this driver as a module, choose M here: the module will
+ be called gpio_it87
+
+config GPIO_SCH
+ tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
+ depends on PCI
+ select MFD_CORE
+ select LPC_SCH
+ help
+ Say yes here to support GPIO interface on Intel Poulsbo SCH,
+ Intel Tunnel Creek processor, Intel Centerton processor or
+ Intel Quark X1000 SoC.
+
+ The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
+ powered by the core power rail and are turned off during sleep
+ modes (S3 and higher). The remaining four GPIOs are powered by
+ the Intel SCH suspend power supply. These GPIOs remain
+ active during S3. The suspend powered GPIOs can be used to wake the
+ system from the Suspend-to-RAM state.
+
+ The Intel Tunnel Creek processor has 5 GPIOs powered by the
+ core power rail and 9 from suspend power supply.
+
+ The Intel Centerton processor has a total of 30 GPIO pins.
+ Twenty-one are powered by the core power rail and 9 from the
+ suspend power supply.
+
+ The Intel Quark X1000 SoC has 2 GPIOs powered by the core
+ power well and 6 from the suspend power well.
+
+config GPIO_SCH311X
+ tristate "SMSC SCH311x SuperI/O GPIO"
+ help
+ Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and
+ SCH3116 "Super I/O" chipsets.
+
+ To compile this driver as a module, choose M here: the module will
+ be called gpio-sch311x.
+
+config GPIO_TS5500
+ tristate "TS-5500 DIO blocks and compatibles"
+ depends on TS5500 || COMPILE_TEST
+ help
+ This driver supports Digital I/O exposed by pin blocks found on some
+ Technologic Systems platforms. It includes, but is not limited to, 3
+ blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
+ LCD port.
+
endmenu
menu "I2C GPIO expanders"
@@ -552,7 +571,6 @@ menu "I2C GPIO expanders"
config GPIO_ADP5588
tristate "ADP5588 I2C GPIO expander"
- depends on I2C
help
This option enables support for 18 GPIOs found
on Analog Devices ADP5588 GPIO Expanders.
@@ -566,7 +584,7 @@ config GPIO_ADP5588_IRQ
config GPIO_ADNP
tristate "Avionic Design N-bit GPIO expander"
- depends on I2C && OF_GPIO
+ depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
This option enables support for N GPIOs found on Avionic Design
@@ -578,14 +596,12 @@ config GPIO_ADNP
config GPIO_MAX7300
tristate "Maxim MAX7300 GPIO expander"
- depends on I2C
select GPIO_MAX730X
help
GPIO driver for Maxim MAX7300 I2C-based GPIO expander.
config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
- depends on I2C
help
Say yes here to support the MAX7319, MAX7320-7327 series of I2C
Port Expanders. Each IO port on these chips has a fixed role of
@@ -618,7 +634,6 @@ config GPIO_MC9S08DZ60
config GPIO_PCA953X
tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
- depends on I2C
help
Say yes here to provide access to several register-oriented
SMBus I/O expanders, made mostly by NXP or TI. Compatible
@@ -646,7 +661,6 @@ config GPIO_PCA953X_IRQ
config GPIO_PCF857X
tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
- depends on I2C
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN
help
@@ -976,7 +990,7 @@ menu "SPI GPIO expanders"
config GPIO_74X164
tristate "74x164 serial-in/parallel-out 8-bits shift register"
- depends on SPI_MASTER && OF
+ depends on OF
help
Driver for 74x164 compatible serial-in/parallel-out 8-outputs
shift registers. This driver can be used to provide access
@@ -984,32 +998,28 @@ config GPIO_74X164
config GPIO_MAX7301
tristate "Maxim MAX7301 GPIO expander"
- depends on SPI_MASTER
select GPIO_MAX730X
help
GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
-config GPIO_MCP23S08
- tristate "Microchip MCP23xxx I/O expander"
- depends on (SPI_MASTER && !I2C) || I2C
- help
- SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
- I/O expanders.
- This provides a GPIO interface supporting inputs and outputs.
- The I2C versions of the chips can be used as interrupt-controller.
-
config GPIO_MC33880
tristate "Freescale MC33880 high-side/low-side switch"
- depends on SPI_MASTER
help
SPI driver for Freescale MC33880 high-side/low-side switch.
This provides GPIO interface supporting inputs and outputs.
-config GPIO_ZX
- bool "ZTE ZX GPIO support"
- select GPIOLIB_IRQCHIP
+endmenu
+
+menu "SPI or I2C GPIO expanders"
+ depends on (SPI_MASTER && !I2C) || I2C
+
+config GPIO_MCP23S08
+ tristate "Microchip MCP23xxx I/O expander"
help
- Say yes here to support the GPIO device on ZTE ZX SoCs.
+ SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
+ I/O expanders.
+ This provides a GPIO interface supporting inputs and outputs.
+ The I2C versions of the chips can be used as interrupt-controller.
endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index f79a7c482a99..986dbd838cea 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
+obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
+obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
@@ -40,7 +42,7 @@ obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
-obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
+obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
@@ -64,7 +66,6 @@ obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
-obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c
new file mode 100644
index 000000000000..5400d7d4d8fd
--- /dev/null
+++ b/drivers/gpio/gpio-104-idio-16.c
@@ -0,0 +1,216 @@
+/*
+ * GPIO driver for the ACCES 104-IDIO-16 family
+ * Copyright (C) 2015 William Breathitt Gray
+ *
+ * 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.
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+static unsigned idio_16_base;
+module_param(idio_16_base, uint, 0);
+MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address");
+
+/**
+ * struct idio_16_gpio - GPIO device private data structure
+ * @chip: instance of the gpio_chip
+ * @lock: synchronization lock to prevent gpio_set race conditions
+ * @base: base port address of the GPIO device
+ * @extent: extent of port address region of the GPIO device
+ * @out_state: output bits state
+ */
+struct idio_16_gpio {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ unsigned base;
+ unsigned extent;
+ unsigned out_state;
+};
+
+static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset > 15)
+ return 1;
+
+ return 0;
+}
+
+static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ return 0;
+}
+
+static int idio_16_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ chip->set(chip, offset, value);
+ return 0;
+}
+
+static struct idio_16_gpio *to_idio16gpio(struct gpio_chip *gc)
+{
+ return container_of(gc, struct idio_16_gpio, chip);
+}
+
+static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct idio_16_gpio *const idio16gpio = to_idio16gpio(chip);
+ const unsigned BIT_MASK = 1U << (offset-16);
+
+ if (offset < 16)
+ return -EINVAL;
+
+ if (offset < 24)
+ return !!(inb(idio16gpio->base + 1) & BIT_MASK);
+
+ return !!(inb(idio16gpio->base + 5) & (BIT_MASK>>8));
+}
+
+static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct idio_16_gpio *const idio16gpio = to_idio16gpio(chip);
+ const unsigned BIT_MASK = 1U << offset;
+ unsigned long flags;
+
+ if (offset > 15)
+ return;
+
+ spin_lock_irqsave(&idio16gpio->lock, flags);
+
+ if (value)
+ idio16gpio->out_state |= BIT_MASK;
+ else
+ idio16gpio->out_state &= ~BIT_MASK;
+
+ if (offset > 7)
+ outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
+ else
+ outb(idio16gpio->out_state, idio16gpio->base);
+
+ spin_unlock_irqrestore(&idio16gpio->lock, flags);
+}
+
+static int __init idio_16_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct idio_16_gpio *idio16gpio;
+ int err;
+
+ const unsigned BASE = idio_16_base;
+ const unsigned EXTENT = 8;
+ const char *const NAME = dev_name(dev);
+
+ idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
+ if (!idio16gpio)
+ return -ENOMEM;
+
+ if (!request_region(BASE, EXTENT, NAME)) {
+ dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n",
+ NAME, BASE, BASE + EXTENT);
+ err = -EBUSY;
+ goto err_lock_io_port;
+ }
+
+ idio16gpio->chip.label = NAME;
+ idio16gpio->chip.dev = dev;
+ idio16gpio->chip.owner = THIS_MODULE;
+ idio16gpio->chip.base = -1;
+ idio16gpio->chip.ngpio = 32;
+ idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
+ idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
+ idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
+ idio16gpio->chip.get = idio_16_gpio_get;
+ idio16gpio->chip.set = idio_16_gpio_set;
+ idio16gpio->base = BASE;
+ idio16gpio->extent = EXTENT;
+ idio16gpio->out_state = 0xFFFF;
+
+ spin_lock_init(&idio16gpio->lock);
+
+ dev_set_drvdata(dev, idio16gpio);
+
+ err = gpiochip_add(&idio16gpio->chip);
+ if (err) {
+ dev_err(dev, "GPIO registering failed (%d)\n", err);
+ goto err_gpio_register;
+ }
+
+ return 0;
+
+err_gpio_register:
+ release_region(BASE, EXTENT);
+err_lock_io_port:
+ return err;
+}
+
+static int idio_16_remove(struct platform_device *pdev)
+{
+ struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&idio16gpio->chip);
+ release_region(idio16gpio->base, idio16gpio->extent);
+
+ return 0;
+}
+
+static struct platform_device *idio_16_device;
+
+static struct platform_driver idio_16_driver = {
+ .driver = {
+ .name = "104-idio-16"
+ },
+ .remove = idio_16_remove
+};
+
+static void __exit idio_16_exit(void)
+{
+ platform_device_unregister(idio_16_device);
+ platform_driver_unregister(&idio_16_driver);
+}
+
+static int __init idio_16_init(void)
+{
+ int err;
+
+ idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1);
+ if (!idio_16_device)
+ return -ENOMEM;
+
+ err = platform_device_add(idio_16_device);
+ if (err)
+ goto err_platform_device;
+
+ err = platform_driver_probe(&idio_16_driver, idio_16_probe);
+ if (err)
+ goto err_platform_driver;
+
+ return 0;
+
+err_platform_driver:
+ platform_device_del(idio_16_device);
+err_platform_device:
+ platform_device_put(idio_16_device);
+ return err;
+}
+
+module_init(idio_16_init);
+module_exit(idio_16_exit);
+
+MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
+MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index e3d968f751f1..60172f835d15 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -183,7 +183,6 @@ MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
static struct spi_driver gen_74x164_driver = {
.driver = {
.name = "74x164",
- .owner = THIS_MODULE,
.of_match_table = gen_74x164_dt_ids,
},
.probe = gen_74x164_probe,
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 1b44941574fa..3e6661bab54a 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -42,6 +42,11 @@ struct altera_gpio_chip {
int mapped_irq;
};
+static struct altera_gpio_chip *to_altera(struct gpio_chip *gc)
+{
+ return container_of(gc, struct altera_gpio_chip, mmchip.gc);
+}
+
static void altera_gpio_irq_unmask(struct irq_data *d)
{
struct altera_gpio_chip *altera_gc;
@@ -49,7 +54,7 @@ static void altera_gpio_irq_unmask(struct irq_data *d)
unsigned long flags;
u32 intmask;
- altera_gc = irq_data_get_irq_chip_data(d);
+ altera_gc = to_altera(irq_data_get_irq_chip_data(d));
mm_gc = &altera_gc->mmchip;
spin_lock_irqsave(&altera_gc->gpio_lock, flags);
@@ -67,7 +72,7 @@ static void altera_gpio_irq_mask(struct irq_data *d)
unsigned long flags;
u32 intmask;
- altera_gc = irq_data_get_irq_chip_data(d);
+ altera_gc = to_altera(irq_data_get_irq_chip_data(d));
mm_gc = &altera_gc->mmchip;
spin_lock_irqsave(&altera_gc->gpio_lock, flags);
@@ -87,7 +92,7 @@ static int altera_gpio_irq_set_type(struct irq_data *d,
{
struct altera_gpio_chip *altera_gc;
- altera_gc = irq_data_get_irq_chip_data(d);
+ altera_gc = to_altera(irq_data_get_irq_chip_data(d));
if (type == IRQ_TYPE_NONE)
return 0;
@@ -210,7 +215,7 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
unsigned long status;
int i;
- altera_gc = irq_desc_get_handler_data(desc);
+ altera_gc = to_altera(irq_desc_get_handler_data(desc));
chip = irq_desc_get_chip(desc);
mm_gc = &altera_gc->mmchip;
irqdomain = altera_gc->mmchip.gc.irqdomain;
@@ -239,7 +244,7 @@ static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
unsigned long status;
int i;
- altera_gc = irq_desc_get_handler_data(desc);
+ altera_gc = to_altera(irq_desc_get_handler_data(desc));
chip = irq_desc_get_chip(desc);
mm_gc = &altera_gc->mmchip;
irqdomain = altera_gc->mmchip.gc.irqdomain;
diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c
new file mode 100644
index 000000000000..cbbb966d4fc0
--- /dev/null
+++ b/drivers/gpio/gpio-amdpt.c
@@ -0,0 +1,261 @@
+/*
+ * AMD Promontory GPIO driver
+ *
+ * Copyright (C) 2015 ASMedia Technology Inc.
+ * Author: YD Tseng <yd_tseng@asmedia.com.tw>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio/driver.h>
+#include <linux/spinlock.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+
+#define PT_TOTAL_GPIO 8
+
+/* PCI-E MMIO register offsets */
+#define PT_DIRECTION_REG 0x00
+#define PT_INPUTDATA_REG 0x04
+#define PT_OUTPUTDATA_REG 0x08
+#define PT_CLOCKRATE_REG 0x0C
+#define PT_SYNC_REG 0x28
+
+struct pt_gpio_chip {
+ struct gpio_chip gc;
+ void __iomem *reg_base;
+ spinlock_t lock;
+};
+
+#define to_pt_gpio(c) container_of(c, struct pt_gpio_chip, gc)
+
+static int pt_gpio_request(struct gpio_chip *gc, unsigned offset)
+{
+ struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
+ unsigned long flags;
+ u32 using_pins;
+
+ dev_dbg(gc->dev, "pt_gpio_request offset=%x\n", offset);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
+ if (using_pins & BIT(offset)) {
+ dev_warn(gc->dev, "PT GPIO pin %x reconfigured\n",
+ offset);
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+ return -EINVAL;
+ }
+
+ writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG);
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+
+ return 0;
+}
+
+static void pt_gpio_free(struct gpio_chip *gc, unsigned offset)
+{
+ struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
+ unsigned long flags;
+ u32 using_pins;
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
+ using_pins &= ~BIT(offset);
+ writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG);
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+
+ dev_dbg(gc->dev, "pt_gpio_free offset=%x\n", offset);
+}
+
+static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+ struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
+ unsigned long flags;
+ u32 data;
+
+ dev_dbg(gc->dev, "pt_gpio_set_value offset=%x, value=%x\n",
+ offset, value);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
+ data &= ~BIT(offset);
+ if (value)
+ data |= BIT(offset);
+ writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG);
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+}
+
+static int pt_gpio_get_value(struct gpio_chip *gc, unsigned offset)
+{
+ struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
+ unsigned long flags;
+ u32 data;
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
+
+ /* configure as output */
+ if (data & BIT(offset))
+ data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
+ else /* configure as input */
+ data = readl(pt_gpio->reg_base + PT_INPUTDATA_REG);
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+
+ data >>= offset;
+ data &= 1;
+
+ dev_dbg(gc->dev, "pt_gpio_get_value offset=%x, value=%x\n",
+ offset, data);
+
+ return data;
+}
+
+static int pt_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
+ unsigned long flags;
+ u32 data;
+
+ dev_dbg(gc->dev, "pt_gpio_dirction_input offset=%x\n", offset);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
+ data &= ~BIT(offset);
+ writel(data, pt_gpio->reg_base + PT_DIRECTION_REG);
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+
+ return 0;
+}
+
+static int pt_gpio_direction_output(struct gpio_chip *gc,
+ unsigned offset, int value)
+{
+ struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
+ unsigned long flags;
+ u32 data;
+
+ dev_dbg(gc->dev, "pt_gpio_direction_output offset=%x, value=%x\n",
+ offset, value);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
+ if (value)
+ data |= BIT(offset);
+ else
+ data &= ~BIT(offset);
+ writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG);
+
+ data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
+ data |= BIT(offset);
+ writel(data, pt_gpio->reg_base + PT_DIRECTION_REG);
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+
+ return 0;
+}
+
+static int pt_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct acpi_device *acpi_dev;
+ acpi_handle handle = ACPI_HANDLE(dev);
+ struct pt_gpio_chip *pt_gpio;
+ struct resource *res_mem;
+ int ret = 0;
+
+ if (acpi_bus_get_device(handle, &acpi_dev)) {
+ dev_err(dev, "PT GPIO device node not found\n");
+ return -ENODEV;
+ }
+
+ pt_gpio = devm_kzalloc(dev, sizeof(struct pt_gpio_chip), GFP_KERNEL);
+ if (!pt_gpio)
+ return -ENOMEM;
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res_mem) {
+ dev_err(&pdev->dev, "Failed to get MMIO resource for PT GPIO.\n");
+ return -EINVAL;
+ }
+ pt_gpio->reg_base = devm_ioremap_resource(dev, res_mem);
+ if (IS_ERR(pt_gpio->reg_base)) {
+ dev_err(&pdev->dev, "Failed to map MMIO resource for PT GPIO.\n");
+ return PTR_ERR(pt_gpio->reg_base);
+ }
+
+ spin_lock_init(&pt_gpio->lock);
+
+ pt_gpio->gc.label = pdev->name;
+ pt_gpio->gc.owner = THIS_MODULE;
+ pt_gpio->gc.dev = dev;
+ pt_gpio->gc.request = pt_gpio_request;
+ pt_gpio->gc.free = pt_gpio_free;
+ pt_gpio->gc.direction_input = pt_gpio_direction_input;
+ pt_gpio->gc.direction_output = pt_gpio_direction_output;
+ pt_gpio->gc.get = pt_gpio_get_value;
+ pt_gpio->gc.set = pt_gpio_set_value;
+ pt_gpio->gc.base = -1;
+ pt_gpio->gc.ngpio = PT_TOTAL_GPIO;
+#if defined(CONFIG_OF_GPIO)
+ pt_gpio->gc.of_node = pdev->dev.of_node;
+#endif
+ ret = gpiochip_add(&pt_gpio->gc);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register GPIO lib\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pt_gpio);
+
+ /* initialize register setting */
+ writel(0, pt_gpio->reg_base + PT_SYNC_REG);
+ writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG);
+
+ dev_dbg(&pdev->dev, "PT GPIO driver loaded\n");
+ return ret;
+}
+
+static int pt_gpio_remove(struct platform_device *pdev)
+{
+ struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&pt_gpio->gc);
+
+ return 0;
+}
+
+static const struct acpi_device_id pt_gpio_acpi_match[] = {
+ { "AMDF030", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);
+
+static struct platform_driver pt_gpio_driver = {
+ .driver = {
+ .name = "pt-gpio",
+ .acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
+ },
+ .probe = pt_gpio_probe,
+ .remove = pt_gpio_remove,
+};
+
+module_platform_driver(pt_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("YD Tseng <yd_tseng@asmedia.com.tw>");
+MODULE_DESCRIPTION("AMD Promontory GPIO Driver");
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 052fbc8fdaaa..ca002739616a 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -118,6 +118,8 @@ static int arizona_gpio_probe(struct platform_device *pdev)
case WM5110:
case WM8280:
case WM8997:
+ case WM8998:
+ case WM1814:
arizona_gpio->gpio_chip.ngpio = 5;
break;
default:
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index 03b995304ad6..e5827a56ff3b 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -12,61 +12,51 @@
* by the Free Software Foundation.
*/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/platform_data/gpio-ath79.h>
#include <linux/of_device.h>
#include <asm/mach-ath79/ar71xx_regs.h>
-static void __iomem *ath79_gpio_base;
-static u32 ath79_gpio_count;
-static DEFINE_SPINLOCK(ath79_gpio_lock);
+struct ath79_gpio_ctrl {
+ struct gpio_chip chip;
+ void __iomem *base;
+ spinlock_t lock;
+};
+
+#define to_ath79_gpio_ctrl(c) container_of(c, struct ath79_gpio_ctrl, chip)
-static void __ath79_gpio_set_value(unsigned gpio, int value)
+static void ath79_gpio_set_value(struct gpio_chip *chip,
+ unsigned gpio, int value)
{
- void __iomem *base = ath79_gpio_base;
+ struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
if (value)
- __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
+ __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET);
else
- __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
+ __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR);
}
-static int __ath79_gpio_get_value(unsigned gpio)
+static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
- return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
-}
+ struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
-static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
-{
- return __ath79_gpio_get_value(offset);
-}
-
-static void ath79_gpio_set_value(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- __ath79_gpio_set_value(offset, value);
+ return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
}
static int ath79_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
- void __iomem *base = ath79_gpio_base;
+ struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
+ spin_lock_irqsave(&ctrl->lock, flags);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
- base + AR71XX_GPIO_REG_OE);
+ __raw_writel(
+ __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
+ ctrl->base + AR71XX_GPIO_REG_OE);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
@@ -74,35 +64,37 @@ static int ath79_gpio_direction_input(struct gpio_chip *chip,
static int ath79_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
- void __iomem *base = ath79_gpio_base;
+ struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
+ spin_lock_irqsave(&ctrl->lock, flags);
if (value)
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+ __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
else
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+ __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
- base + AR71XX_GPIO_REG_OE);
+ __raw_writel(
+ __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
+ ctrl->base + AR71XX_GPIO_REG_OE);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
- void __iomem *base = ath79_gpio_base;
+ struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
+ spin_lock_irqsave(&ctrl->lock, flags);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
- base + AR71XX_GPIO_REG_OE);
+ __raw_writel(
+ __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
+ ctrl->base + AR71XX_GPIO_REG_OE);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
@@ -110,25 +102,26 @@ static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
- void __iomem *base = ath79_gpio_base;
+ struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
+ spin_lock_irqsave(&ctrl->lock, flags);
if (value)
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+ __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
else
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+ __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
- base + AR71XX_GPIO_REG_OE);
+ __raw_writel(
+ __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & BIT(offset),
+ ctrl->base + AR71XX_GPIO_REG_OE);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
-static struct gpio_chip ath79_gpio_chip = {
+static const struct gpio_chip ath79_gpio_chip = {
.label = "ath79",
.get = ath79_gpio_get_value,
.set = ath79_gpio_set_value,
@@ -147,10 +140,16 @@ static int ath79_gpio_probe(struct platform_device *pdev)
{
struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
+ struct ath79_gpio_ctrl *ctrl;
struct resource *res;
+ u32 ath79_gpio_count;
bool oe_inverted;
int err;
+ ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
if (np) {
err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
if (err) {
@@ -171,19 +170,21 @@ static int ath79_gpio_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ath79_gpio_base = devm_ioremap_nocache(
+ ctrl->base = devm_ioremap_nocache(
&pdev->dev, res->start, resource_size(res));
- if (!ath79_gpio_base)
+ if (!ctrl->base)
return -ENOMEM;
- ath79_gpio_chip.dev = &pdev->dev;
- ath79_gpio_chip.ngpio = ath79_gpio_count;
+ spin_lock_init(&ctrl->lock);
+ memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip));
+ ctrl->chip.dev = &pdev->dev;
+ ctrl->chip.ngpio = ath79_gpio_count;
if (oe_inverted) {
- ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
- ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
+ ctrl->chip.direction_input = ar934x_gpio_direction_input;
+ ctrl->chip.direction_output = ar934x_gpio_direction_output;
}
- err = gpiochip_add(&ath79_gpio_chip);
+ err = gpiochip_add(&ctrl->chip);
if (err) {
dev_err(&pdev->dev,
"cannot add AR71xx GPIO chip, error=%d", err);
diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c
index 2ffcd9fdd1f2..5c15dd12172d 100644
--- a/drivers/gpio/gpio-etraxfs.c
+++ b/drivers/gpio/gpio-etraxfs.c
@@ -176,6 +176,11 @@ static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = {
.rw_intr_pins = ARTPEC3_rw_intr_pins,
};
+static struct etraxfs_gpio_chip *to_etraxfs(struct gpio_chip *gc)
+{
+ return container_of(gc, struct etraxfs_gpio_chip, bgc.gc);
+}
+
static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc)
{
return gc->label[0] - 'A';
@@ -220,7 +225,8 @@ static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip,
static void etraxfs_gpio_irq_ack(struct irq_data *d)
{
- struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct etraxfs_gpio_chip *chip =
+ to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
@@ -229,7 +235,8 @@ static void etraxfs_gpio_irq_ack(struct irq_data *d)
static void etraxfs_gpio_irq_mask(struct irq_data *d)
{
- struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct etraxfs_gpio_chip *chip =
+ to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
@@ -241,7 +248,8 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d)
static void etraxfs_gpio_irq_unmask(struct irq_data *d)
{
- struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct etraxfs_gpio_chip *chip =
+ to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
@@ -253,7 +261,8 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d)
static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
{
- struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct etraxfs_gpio_chip *chip =
+ to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
u32 cfg;
@@ -289,7 +298,8 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
{
- struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct etraxfs_gpio_chip *chip =
+ to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
int ret = -EBUSY;
@@ -319,7 +329,8 @@ out:
static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
{
- struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct etraxfs_gpio_chip *chip =
+ to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index a3f07537fe62..bd5193c67a9c 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -579,40 +579,20 @@ EXPORT_SYMBOL_GPL(bgpio_init);
static void __iomem *bgpio_map(struct platform_device *pdev,
const char *name,
- resource_size_t sane_sz,
- int *err)
+ resource_size_t sane_sz)
{
- struct device *dev = &pdev->dev;
struct resource *r;
- resource_size_t start;
resource_size_t sz;
- void __iomem *ret;
-
- *err = 0;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
if (!r)
return NULL;
sz = resource_size(r);
- if (sz != sane_sz) {
- *err = -EINVAL;
- return NULL;
- }
-
- start = r->start;
- if (!devm_request_mem_region(dev, start, sz, r->name)) {
- *err = -EBUSY;
- return NULL;
- }
-
- ret = devm_ioremap(dev, start, sz);
- if (!ret) {
- *err = -ENOMEM;
- return NULL;
- }
+ if (sz != sane_sz)
+ return IOMEM_ERR_PTR(-EINVAL);
- return ret;
+ return devm_ioremap_resource(&pdev->dev, r);
}
static int bgpio_pdev_probe(struct platform_device *pdev)
@@ -636,25 +616,25 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
sz = resource_size(r);
- dat = bgpio_map(pdev, "dat", sz, &err);
- if (!dat)
- return err ? err : -EINVAL;
+ dat = bgpio_map(pdev, "dat", sz);
+ if (IS_ERR(dat))
+ return PTR_ERR(dat);
- set = bgpio_map(pdev, "set", sz, &err);
- if (err)
- return err;
+ set = bgpio_map(pdev, "set", sz);
+ if (IS_ERR(set))
+ return PTR_ERR(set);
- clr = bgpio_map(pdev, "clr", sz, &err);
- if (err)
- return err;
+ clr = bgpio_map(pdev, "clr", sz);
+ if (IS_ERR(clr))
+ return PTR_ERR(clr);
- dirout = bgpio_map(pdev, "dirout", sz, &err);
- if (err)
- return err;
+ dirout = bgpio_map(pdev, "dirout", sz);
+ if (IS_ERR(dirout))
+ return PTR_ERR(dirout);
- dirin = bgpio_map(pdev, "dirin", sz, &err);
- if (err)
- return err;
+ dirin = bgpio_map(pdev, "dirin", sz);
+ if (IS_ERR(dirin))
+ return PTR_ERR(dirin);
bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)
diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c
new file mode 100644
index 000000000000..21f6f7c0eb34
--- /dev/null
+++ b/drivers/gpio/gpio-it87.c
@@ -0,0 +1,411 @@
+/*
+ * GPIO interface for IT87xx Super I/O chips
+ *
+ * Author: Diego Elio Pettenò <flameeyes@flameeyes.eu>
+ *
+ * Based on it87_wdt.c by Oliver Schuster
+ * gpio-it8761e.c by Denis Turischev
+ * gpio-stmpe.c by Rabin Vincent
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+/* Chip Id numbers */
+#define NO_DEV_ID 0xffff
+#define IT8728_ID 0x8728
+#define IT8732_ID 0x8732
+#define IT8761_ID 0x8761
+
+/* IO Ports */
+#define REG 0x2e
+#define VAL 0x2f
+
+/* Logical device Numbers LDN */
+#define GPIO 0x07
+
+/* Configuration Registers and Functions */
+#define LDNREG 0x07
+#define CHIPID 0x20
+#define CHIPREV 0x22
+
+/**
+ * struct it87_gpio - it87-specific GPIO chip
+ * @chip the underlying gpio_chip structure
+ * @lock a lock to avoid races between operations
+ * @io_base base address for gpio ports
+ * @io_size size of the port rage starting from io_base.
+ * @output_base Super I/O register address for Output Enable register
+ * @simple_base Super I/O 'Simple I/O' Enable register
+ * @simple_size Super IO 'Simple I/O' Enable register size; this is
+ * required because IT87xx chips might only provide Simple I/O
+ * switches on a subset of lines, whereas the others keep the
+ * same status all time.
+ */
+struct it87_gpio {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ u16 io_base;
+ u16 io_size;
+ u8 output_base;
+ u8 simple_base;
+ u8 simple_size;
+};
+
+static struct it87_gpio it87_gpio_chip = {
+ .lock = __SPIN_LOCK_UNLOCKED(it87_gpio_chip.lock),
+};
+
+static inline struct it87_gpio *to_it87_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct it87_gpio, chip);
+}
+
+/* Superio chip access functions; copied from wdt_it87 */
+
+static inline int superio_enter(void)
+{
+ /*
+ * Try to reserve REG and REG + 1 for exclusive access.
+ */
+ if (!request_muxed_region(REG, 2, KBUILD_MODNAME))
+ return -EBUSY;
+
+ outb(0x87, REG);
+ outb(0x01, REG);
+ outb(0x55, REG);
+ outb(0x55, REG);
+ return 0;
+}
+
+static inline void superio_exit(void)
+{
+ outb(0x02, REG);
+ outb(0x02, VAL);
+ release_region(REG, 2);
+}
+
+static inline void superio_select(int ldn)
+{
+ outb(LDNREG, REG);
+ outb(ldn, VAL);
+}
+
+static inline int superio_inb(int reg)
+{
+ outb(reg, REG);
+ return inb(VAL);
+}
+
+static inline void superio_outb(int val, int reg)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static inline int superio_inw(int reg)
+{
+ int val;
+
+ outb(reg++, REG);
+ val = inb(VAL) << 8;
+ outb(reg, REG);
+ val |= inb(VAL);
+ return val;
+}
+
+static inline void superio_outw(int val, int reg)
+{
+ outb(reg++, REG);
+ outb(val >> 8, VAL);
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static inline void superio_set_mask(int mask, int reg)
+{
+ u8 curr_val = superio_inb(reg);
+ u8 new_val = curr_val | mask;
+
+ if (curr_val != new_val)
+ superio_outb(new_val, reg);
+}
+
+static inline void superio_clear_mask(int mask, int reg)
+{
+ u8 curr_val = superio_inb(reg);
+ u8 new_val = curr_val & ~mask;
+
+ if (curr_val != new_val)
+ superio_outb(new_val, reg);
+}
+
+static int it87_gpio_request(struct gpio_chip *chip, unsigned gpio_num)
+{
+ u8 mask, group;
+ int rc = 0;
+ struct it87_gpio *it87_gpio = to_it87_gpio(chip);
+
+ mask = 1 << (gpio_num % 8);
+ group = (gpio_num / 8);
+
+ spin_lock(&it87_gpio->lock);
+
+ rc = superio_enter();
+ if (rc)
+ goto exit;
+
+ /* not all the IT87xx chips support Simple I/O and not all of
+ * them allow all the lines to be set/unset to Simple I/O.
+ */
+ if (group < it87_gpio->simple_size)
+ superio_set_mask(mask, group + it87_gpio->simple_base);
+
+ /* clear output enable, setting the pin to input, as all the
+ * newly-exported GPIO interfaces are set to input.
+ */
+ superio_clear_mask(mask, group + it87_gpio->output_base);
+
+ superio_exit();
+
+exit:
+ spin_unlock(&it87_gpio->lock);
+ return rc;
+}
+
+static int it87_gpio_get(struct gpio_chip *chip, unsigned gpio_num)
+{
+ u16 reg;
+ u8 mask;
+ struct it87_gpio *it87_gpio = to_it87_gpio(chip);
+
+ mask = 1 << (gpio_num % 8);
+ reg = (gpio_num / 8) + it87_gpio->io_base;
+
+ return !!(inb(reg) & mask);
+}
+
+static int it87_gpio_direction_in(struct gpio_chip *chip, unsigned gpio_num)
+{
+ u8 mask, group;
+ int rc = 0;
+ struct it87_gpio *it87_gpio = to_it87_gpio(chip);
+
+ mask = 1 << (gpio_num % 8);
+ group = (gpio_num / 8);
+
+ spin_lock(&it87_gpio->lock);
+
+ rc = superio_enter();
+ if (rc)
+ goto exit;
+
+ /* clear the output enable bit */
+ superio_clear_mask(mask, group + it87_gpio->output_base);
+
+ superio_exit();
+
+exit:
+ spin_unlock(&it87_gpio->lock);
+ return rc;
+}
+
+static void it87_gpio_set(struct gpio_chip *chip,
+ unsigned gpio_num, int val)
+{
+ u8 mask, curr_vals;
+ u16 reg;
+ struct it87_gpio *it87_gpio = to_it87_gpio(chip);
+
+ mask = 1 << (gpio_num % 8);
+ reg = (gpio_num / 8) + it87_gpio->io_base;
+
+ curr_vals = inb(reg);
+ if (val)
+ outb(curr_vals | mask, reg);
+ else
+ outb(curr_vals & ~mask, reg);
+}
+
+static int it87_gpio_direction_out(struct gpio_chip *chip,
+ unsigned gpio_num, int val)
+{
+ u8 mask, group;
+ int rc = 0;
+ struct it87_gpio *it87_gpio = to_it87_gpio(chip);
+
+ mask = 1 << (gpio_num % 8);
+ group = (gpio_num / 8);
+
+ spin_lock(&it87_gpio->lock);
+
+ rc = superio_enter();
+ if (rc)
+ goto exit;
+
+ /* set the output enable bit */
+ superio_set_mask(mask, group + it87_gpio->output_base);
+
+ it87_gpio_set(chip, gpio_num, val);
+
+ superio_exit();
+
+exit:
+ spin_unlock(&it87_gpio->lock);
+ return rc;
+}
+
+static struct gpio_chip it87_template_chip = {
+ .label = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .request = it87_gpio_request,
+ .get = it87_gpio_get,
+ .direction_input = it87_gpio_direction_in,
+ .set = it87_gpio_set,
+ .direction_output = it87_gpio_direction_out,
+ .base = -1
+};
+
+static int __init it87_gpio_init(void)
+{
+ int rc = 0, i;
+ u16 chip_type;
+ u8 chip_rev, gpio_ba_reg;
+ char *labels, **labels_table;
+
+ struct it87_gpio *it87_gpio = &it87_gpio_chip;
+
+ rc = superio_enter();
+ if (rc)
+ return rc;
+
+ chip_type = superio_inw(CHIPID);
+ chip_rev = superio_inb(CHIPREV) & 0x0f;
+ superio_exit();
+
+ it87_gpio->chip = it87_template_chip;
+
+ switch (chip_type) {
+ case IT8728_ID:
+ case IT8732_ID:
+ gpio_ba_reg = 0x62;
+ it87_gpio->io_size = 8;
+ it87_gpio->output_base = 0xc8;
+ it87_gpio->simple_base = 0xc0;
+ it87_gpio->simple_size = 5;
+ it87_gpio->chip.ngpio = 64;
+ break;
+ case IT8761_ID:
+ gpio_ba_reg = 0x60;
+ it87_gpio->io_size = 4;
+ it87_gpio->output_base = 0xf0;
+ it87_gpio->simple_size = 0;
+ it87_gpio->chip.ngpio = 16;
+ break;
+ case NO_DEV_ID:
+ pr_err("no device\n");
+ return -ENODEV;
+ default:
+ pr_err("Unknown Chip found, Chip %04x Revision %x\n",
+ chip_type, chip_rev);
+ return -ENODEV;
+ }
+
+ rc = superio_enter();
+ if (rc)
+ return rc;
+
+ superio_select(GPIO);
+
+ /* fetch GPIO base address */
+ it87_gpio->io_base = superio_inw(gpio_ba_reg);
+
+ superio_exit();
+
+ pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n",
+ chip_type, chip_rev, it87_gpio->chip.ngpio,
+ it87_gpio->io_base);
+
+ if (!request_region(it87_gpio->io_base, it87_gpio->io_size,
+ KBUILD_MODNAME))
+ return -EBUSY;
+
+ /* Set up aliases for the GPIO connection.
+ *
+ * ITE documentation for recent chips such as the IT8728F
+ * refers to the GPIO lines as GPxy, with a coordinates system
+ * where x is the GPIO group (starting from 1) and y is the
+ * bit within the group.
+ *
+ * By creating these aliases, we make it easier to understand
+ * to which GPIO pin we're referring to.
+ */
+ labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"),
+ GFP_KERNEL);
+ labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *),
+ GFP_KERNEL);
+
+ if (!labels || !labels_table) {
+ rc = -ENOMEM;
+ goto labels_free;
+ }
+
+ for (i = 0; i < it87_gpio->chip.ngpio; i++) {
+ char *label = &labels[i * sizeof("it87_gpXY")];
+
+ sprintf(label, "it87_gp%u%u", 1+(i/8), i%8);
+ labels_table[i] = label;
+ }
+
+ it87_gpio->chip.names = (const char *const*)labels_table;
+
+ rc = gpiochip_add(&it87_gpio->chip);
+ if (rc)
+ goto labels_free;
+
+ return 0;
+
+labels_free:
+ kfree(labels_table);
+ kfree(labels);
+ release_region(it87_gpio->io_base, it87_gpio->io_size);
+ return rc;
+}
+
+static void __exit it87_gpio_exit(void)
+{
+ struct it87_gpio *it87_gpio = &it87_gpio_chip;
+
+ gpiochip_remove(&it87_gpio->chip);
+ release_region(it87_gpio->io_base, it87_gpio->io_size);
+ kfree(it87_gpio->chip.names[0]);
+ kfree(it87_gpio->chip.names);
+}
+
+module_init(it87_gpio_init);
+module_exit(it87_gpio_exit);
+
+MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>");
+MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-it8761e.c b/drivers/gpio/gpio-it8761e.c
deleted file mode 100644
index 30a8f24c92c5..000000000000
--- a/drivers/gpio/gpio-it8761e.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * GPIO interface for IT8761E Super I/O chip
- *
- * Author: Denis Turischev <denis@compulab.co.il>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-
-#include <linux/gpio.h>
-
-#define SIO_CHIP_ID 0x8761
-#define CHIP_ID_HIGH_BYTE 0x20
-#define CHIP_ID_LOW_BYTE 0x21
-
-static u8 ports[2] = { 0x2e, 0x4e };
-static u8 port;
-
-static DEFINE_SPINLOCK(sio_lock);
-
-#define GPIO_NAME "it8761-gpio"
-#define GPIO_BA_HIGH_BYTE 0x60
-#define GPIO_BA_LOW_BYTE 0x61
-#define GPIO_IOSIZE 4
-#define GPIO1X_IO 0xf0
-#define GPIO2X_IO 0xf1
-
-static u16 gpio_ba;
-
-static u8 read_reg(u8 addr, u8 port)
-{
- outb(addr, port);
- return inb(port + 1);
-}
-
-static void write_reg(u8 data, u8 addr, u8 port)
-{
- outb(addr, port);
- outb(data, port + 1);
-}
-
-static void enter_conf_mode(u8 port)
-{
- outb(0x87, port);
- outb(0x61, port);
- outb(0x55, port);
- outb((port == 0x2e) ? 0x55 : 0xaa, port);
-}
-
-static void exit_conf_mode(u8 port)
-{
- outb(0x2, port);
- outb(0x2, port + 1);
-}
-
-static void enter_gpio_mode(u8 port)
-{
- write_reg(0x2, 0x7, port);
-}
-
-static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
-{
- u16 reg;
- u8 bit;
-
- bit = gpio_num % 8;
- reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
-
- return !!(inb(reg) & (1 << bit));
-}
-
-static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
-{
- u8 curr_dirs;
- u8 io_reg, bit;
-
- bit = gpio_num % 8;
- io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
-
- spin_lock(&sio_lock);
-
- enter_conf_mode(port);
- enter_gpio_mode(port);
-
- curr_dirs = read_reg(io_reg, port);
-
- if (curr_dirs & (1 << bit))
- write_reg(curr_dirs & ~(1 << bit), io_reg, port);
-
- exit_conf_mode(port);
-
- spin_unlock(&sio_lock);
- return 0;
-}
-
-static void it8761e_gpio_set(struct gpio_chip *gc,
- unsigned gpio_num, int val)
-{
- u8 curr_vals, bit;
- u16 reg;
-
- bit = gpio_num % 8;
- reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
-
- spin_lock(&sio_lock);
-
- curr_vals = inb(reg);
- if (val)
- outb(curr_vals | (1 << bit), reg);
- else
- outb(curr_vals & ~(1 << bit), reg);
-
- spin_unlock(&sio_lock);
-}
-
-static int it8761e_gpio_direction_out(struct gpio_chip *gc,
- unsigned gpio_num, int val)
-{
- u8 curr_dirs, io_reg, bit;
-
- bit = gpio_num % 8;
- io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
-
- it8761e_gpio_set(gc, gpio_num, val);
-
- spin_lock(&sio_lock);
-
- enter_conf_mode(port);
- enter_gpio_mode(port);
-
- curr_dirs = read_reg(io_reg, port);
-
- if (!(curr_dirs & (1 << bit)))
- write_reg(curr_dirs | (1 << bit), io_reg, port);
-
- exit_conf_mode(port);
-
- spin_unlock(&sio_lock);
- return 0;
-}
-
-static struct gpio_chip it8761e_gpio_chip = {
- .label = GPIO_NAME,
- .owner = THIS_MODULE,
- .get = it8761e_gpio_get,
- .direction_input = it8761e_gpio_direction_in,
- .set = it8761e_gpio_set,
- .direction_output = it8761e_gpio_direction_out,
-};
-
-static int __init it8761e_gpio_init(void)
-{
- int i, id, err;
-
- /* chip and port detection */
- for (i = 0; i < ARRAY_SIZE(ports); i++) {
- spin_lock(&sio_lock);
- enter_conf_mode(ports[i]);
-
- id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
- read_reg(CHIP_ID_LOW_BYTE, ports[i]);
-
- exit_conf_mode(ports[i]);
- spin_unlock(&sio_lock);
-
- if (id == SIO_CHIP_ID) {
- port = ports[i];
- break;
- }
- }
-
- if (!port)
- return -ENODEV;
-
- /* fetch GPIO base address */
- enter_conf_mode(port);
- enter_gpio_mode(port);
- gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
- read_reg(GPIO_BA_LOW_BYTE, port);
- exit_conf_mode(port);
-
- if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
- return -EBUSY;
-
- it8761e_gpio_chip.base = -1;
- it8761e_gpio_chip.ngpio = 16;
-
- err = gpiochip_add(&it8761e_gpio_chip);
- if (err < 0)
- goto gpiochip_add_err;
-
- return 0;
-
-gpiochip_add_err:
- release_region(gpio_ba, GPIO_IOSIZE);
- gpio_ba = 0;
- return err;
-}
-
-static void __exit it8761e_gpio_exit(void)
-{
- if (gpio_ba) {
- gpiochip_remove(&it8761e_gpio_chip);
- release_region(gpio_ba, GPIO_IOSIZE);
- gpio_ba = 0;
- }
-}
-module_init(it8761e_gpio_init);
-module_exit(it8761e_gpio_exit);
-
-MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
-MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c
index eb68603136b0..e39dcb0af8ae 100644
--- a/drivers/gpio/gpio-lpc18xx.c
+++ b/drivers/gpio/gpio-lpc18xx.c
@@ -36,16 +36,6 @@ static inline struct lpc18xx_gpio_chip *to_lpc18xx_gpio(struct gpio_chip *chip)
return container_of(chip, struct lpc18xx_gpio_chip, gpio);
}
-static int lpc18xx_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(offset);
-}
-
-static void lpc18xx_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(offset);
-}
-
static void lpc18xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct lpc18xx_gpio_chip *gc = to_lpc18xx_gpio(chip);
@@ -95,8 +85,8 @@ static int lpc18xx_gpio_direction_output(struct gpio_chip *chip,
static struct gpio_chip lpc18xx_chip = {
.label = "lpc18xx/43xx-gpio",
- .request = lpc18xx_gpio_request,
- .free = lpc18xx_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.direction_input = lpc18xx_gpio_direction_input,
.direction_output = lpc18xx_gpio_direction_output,
.set = lpc18xx_gpio_set,
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
index 6e1c984a75d4..05813fbf3daf 100644
--- a/drivers/gpio/gpio-max7301.c
+++ b/drivers/gpio/gpio-max7301.c
@@ -87,7 +87,6 @@ MODULE_DEVICE_TABLE(spi, max7301_id);
static struct spi_driver max7301_driver = {
.driver = {
.name = "max7301",
- .owner = THIS_MODULE,
},
.probe = max7301_probe,
.remove = max7301_remove,
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 18ab89e20806..0f57d2d248ec 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -236,7 +236,6 @@ int __max730x_remove(struct device *dev)
ts->write(dev, 0x04, 0x00);
gpiochip_remove(&ts->chip);
mutex_destroy(&ts->lock);
- kfree(ts);
return 0;
}
EXPORT_SYMBOL_GPL(__max730x_remove);
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index a431604c9e67..2853731db5bc 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -163,7 +163,6 @@ static int mc33880_remove(struct spi_device *spi)
static struct spi_driver mc33880_driver = {
.driver = {
.name = DRIVER_NAME,
- .owner = THIS_MODULE,
},
.probe = mc33880_probe,
.remove = mc33880_remove,
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 73db7ecd7ffd..4a41694919da 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -848,7 +848,6 @@ MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
static struct i2c_driver mcp230xx_driver = {
.driver = {
.name = "mcp230xx",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(mcp23s08_i2c_of_match),
},
.probe = mcp230xx_probe,
@@ -1021,7 +1020,6 @@ static struct spi_driver mcp23s08_driver = {
.id_table = mcp23s08_ids,
.driver = {
.name = "mcp23s08",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(mcp23s08_spi_of_match),
},
};
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
index abd8676ce2b6..d3355a6dc9b1 100644
--- a/drivers/gpio/gpio-moxart.c
+++ b/drivers/gpio/gpio-moxart.c
@@ -29,16 +29,6 @@
#define GPIO_DATA_IN 0x04
#define GPIO_PIN_DIRECTION 0x08
-static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(offset);
-}
-
-static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(offset);
-}
-
static int moxart_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -66,8 +56,8 @@ static int moxart_gpio_probe(struct platform_device *pdev)
}
bgc->gc.label = "moxart-gpio";
- bgc->gc.request = moxart_gpio_request;
- bgc->gc.free = moxart_gpio_free;
+ bgc->gc.request = gpiochip_generic_request;
+ bgc->gc.free = gpiochip_generic_free;
bgc->data = bgc->read_reg(bgc->reg_set);
bgc->gc.base = 0;
bgc->gc.ngpio = 32;
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
deleted file mode 100644
index 4b4222145f10..000000000000
--- a/drivers/gpio/gpio-msm-v2.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
- * only 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., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/bitmap.h>
-#include <linux/bitops.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-
-#define MAX_NR_GPIO 300
-
-/* Bits of interest in the GPIO_IN_OUT register.
- */
-enum {
- GPIO_IN = 0,
- GPIO_OUT = 1
-};
-
-/* Bits of interest in the GPIO_INTR_STATUS register.
- */
-enum {
- INTR_STATUS = 0,
-};
-
-/* Bits of interest in the GPIO_CFG register.
- */
-enum {
- GPIO_OE = 9,
-};
-
-/* Bits of interest in the GPIO_INTR_CFG register.
- * When a GPIO triggers, two separate decisions are made, controlled
- * by two separate flags.
- *
- * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
- * register for that GPIO will be updated to reflect the triggering of that
- * gpio. If this bit is 0, this register will not be updated.
- * - Second, INTR_ENABLE controls whether an interrupt is triggered.
- *
- * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
- * can be triggered but the status register will not reflect it.
- */
-enum {
- INTR_ENABLE = 0,
- INTR_POL_CTL = 1,
- INTR_DECT_CTL = 2,
- INTR_RAW_STATUS_EN = 3,
-};
-
-/* Codes of interest in GPIO_INTR_CFG_SU.
- */
-enum {
- TARGET_PROC_SCORPION = 4,
- TARGET_PROC_NONE = 7,
-};
-
-/**
- * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
- *
- * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By
- * keeping track of which gpios are unmasked as irq sources, we avoid
- * having to do readl calls on hundreds of iomapped registers each time
- * the summary interrupt fires in order to locate the active interrupts.
- *
- * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
- * as wakeup sources. When the device is suspended, interrupts which are
- * not wakeup sources are disabled.
- *
- * @dual_edge_irqs: a bitmap used to track which irqs are configured
- * as dual-edge, as this is not supported by the hardware and requires
- * some special handling in the driver.
- */
-struct msm_gpio_dev {
- struct gpio_chip gpio_chip;
- DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
- DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO);
- DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
- struct irq_domain *domain;
- int summary_irq;
- void __iomem *msm_tlmm_base;
-};
-
-static struct msm_gpio_dev msm_gpio;
-
-#define GPIO_INTR_CFG_SU(gpio) (msm_gpio.msm_tlmm_base + 0x0400 + \
- (0x04 * (gpio)))
-#define GPIO_CONFIG(gpio) (msm_gpio.msm_tlmm_base + 0x1000 + \
- (0x10 * (gpio)))
-#define GPIO_IN_OUT(gpio) (msm_gpio.msm_tlmm_base + 0x1004 + \
- (0x10 * (gpio)))
-#define GPIO_INTR_CFG(gpio) (msm_gpio.msm_tlmm_base + 0x1008 + \
- (0x10 * (gpio)))
-#define GPIO_INTR_STATUS(gpio) (msm_gpio.msm_tlmm_base + 0x100c + \
- (0x10 * (gpio)))
-
-static DEFINE_SPINLOCK(tlmm_lock);
-
-static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
-{
- return container_of(chip, struct msm_gpio_dev, gpio_chip);
-}
-
-static inline void set_gpio_bits(unsigned n, void __iomem *reg)
-{
- writel(readl(reg) | n, reg);
-}
-
-static inline void clear_gpio_bits(unsigned n, void __iomem *reg)
-{
- writel(readl(reg) & ~n, reg);
-}
-
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN);
-}
-
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
- writel(val ? BIT(GPIO_OUT) : 0, GPIO_IN_OUT(offset));
-}
-
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- clear_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
- return 0;
-}
-
-static int msm_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset,
- int val)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- msm_gpio_set(chip, offset, val);
- set_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
- return 0;
-}
-
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return 0;
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- return;
-}
-
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
- struct irq_domain *domain = g_dev->domain;
-
- return irq_create_mapping(domain, offset);
-}
-
-/* For dual-edge interrupts in software, since the hardware has no
- * such support:
- *
- * At appropriate moments, this function may be called to flip the polarity
- * settings of both-edge irq lines to try and catch the next edge.
- *
- * The attempt is considered successful if:
- * - the status bit goes high, indicating that an edge was caught, or
- * - the input value of the gpio doesn't change during the attempt.
- * If the value changes twice during the process, that would cause the first
- * test to fail but would force the second, as two opposite
- * transitions would cause a detection no matter the polarity setting.
- *
- * The do-loop tries to sledge-hammer closed the timing hole between
- * the initial value-read and the polarity-write - if the line value changes
- * during that window, an interrupt is lost, the new polarity setting is
- * incorrect, and the first success test will fail, causing a retry.
- *
- * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
- */
-static void msm_gpio_update_dual_edge_pos(unsigned gpio)
-{
- int loop_limit = 100;
- unsigned val, val2, intstat;
-
- do {
- val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
- if (val)
- clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
- else
- set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
- val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
- intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS);
- if (intstat || val == val2)
- return;
- } while (loop_limit-- > 0);
- pr_err("%s: dual-edge irq failed to stabilize, "
- "interrupts dropped. %#08x != %#08x\n",
- __func__, val, val2);
-}
-
-static void msm_gpio_irq_ack(struct irq_data *d)
-{
- int gpio = d->hwirq;
-
- writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
- if (test_bit(gpio, msm_gpio.dual_edge_irqs))
- msm_gpio_update_dual_edge_pos(gpio);
-}
-
-static void msm_gpio_irq_mask(struct irq_data *d)
-{
- unsigned long irq_flags;
- int gpio = d->hwirq;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
- clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
- __clear_bit(gpio, msm_gpio.enabled_irqs);
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
- unsigned long irq_flags;
- int gpio = d->hwirq;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- __set_bit(gpio, msm_gpio.enabled_irqs);
- set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
- writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-}
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
- unsigned long irq_flags;
- int gpio = d->hwirq;
- uint32_t bits;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
-
- bits = readl(GPIO_INTR_CFG(gpio));
-
- if (flow_type & IRQ_TYPE_EDGE_BOTH) {
- bits |= BIT(INTR_DECT_CTL);
- irq_set_handler_locked(d, handle_edge_irq);
- if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- __set_bit(gpio, msm_gpio.dual_edge_irqs);
- else
- __clear_bit(gpio, msm_gpio.dual_edge_irqs);
- } else {
- bits &= ~BIT(INTR_DECT_CTL);
- irq_set_handler_locked(d, handle_level_irq);
- __clear_bit(gpio, msm_gpio.dual_edge_irqs);
- }
-
- if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
- bits |= BIT(INTR_POL_CTL);
- else
- bits &= ~BIT(INTR_POL_CTL);
-
- writel(bits, GPIO_INTR_CFG(gpio));
-
- if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- msm_gpio_update_dual_edge_pos(gpio);
-
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
- return 0;
-}
-
-/*
- * When the summary IRQ is raised, any number of GPIO lines may be high.
- * It is the job of the summary handler to find all those GPIO lines
- * which have been set as summary IRQ lines and which are triggered,
- * and to call their interrupt handlers.
- */
-static void msm_summary_irq_handler(struct irq_desc *desc)
-{
- unsigned long i;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
-
- for_each_set_bit(i, msm_gpio.enabled_irqs, MAX_NR_GPIO) {
- if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
- generic_handle_irq(irq_find_mapping(msm_gpio.domain,
- i));
- }
-
- chained_irq_exit(chip, desc);
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
- int gpio = d->hwirq;
-
- if (on) {
- if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
- irq_set_irq_wake(msm_gpio.summary_irq, 1);
- set_bit(gpio, msm_gpio.wake_irqs);
- } else {
- clear_bit(gpio, msm_gpio.wake_irqs);
- if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
- irq_set_irq_wake(msm_gpio.summary_irq, 0);
- }
-
- return 0;
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
- .name = "msmgpio",
- .irq_mask = msm_gpio_irq_mask,
- .irq_unmask = msm_gpio_irq_unmask,
- .irq_ack = msm_gpio_irq_ack,
- .irq_set_type = msm_gpio_irq_set_type,
- .irq_set_wake = msm_gpio_irq_set_wake,
-};
-
-static struct lock_class_key msm_gpio_lock_class;
-
-static int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_lockdep_class(irq, &msm_gpio_lock_class);
- irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
- handle_level_irq);
-
- return 0;
-}
-
-static const struct irq_domain_ops msm_gpio_irq_domain_ops = {
- .xlate = irq_domain_xlate_twocell,
- .map = msm_gpio_irq_domain_map,
-};
-
-static int msm_gpio_probe(struct platform_device *pdev)
-{
- int ret, ngpio;
- struct resource *res;
-
- if (of_property_read_u32(pdev->dev.of_node, "ngpio", &ngpio)) {
- dev_err(&pdev->dev, "%s: ngpio property missing\n", __func__);
- return -EINVAL;
- }
-
- if (ngpio > MAX_NR_GPIO)
- WARN(1, "ngpio exceeds the MAX_NR_GPIO. Increase MAX_NR_GPIO\n");
-
- bitmap_zero(msm_gpio.enabled_irqs, MAX_NR_GPIO);
- bitmap_zero(msm_gpio.wake_irqs, MAX_NR_GPIO);
- bitmap_zero(msm_gpio.dual_edge_irqs, MAX_NR_GPIO);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- msm_gpio.msm_tlmm_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(msm_gpio.msm_tlmm_base))
- return PTR_ERR(msm_gpio.msm_tlmm_base);
-
- msm_gpio.gpio_chip.ngpio = ngpio;
- msm_gpio.gpio_chip.label = pdev->name;
- msm_gpio.gpio_chip.dev = &pdev->dev;
- msm_gpio.gpio_chip.base = 0;
- msm_gpio.gpio_chip.direction_input = msm_gpio_direction_input;
- msm_gpio.gpio_chip.direction_output = msm_gpio_direction_output;
- msm_gpio.gpio_chip.get = msm_gpio_get;
- msm_gpio.gpio_chip.set = msm_gpio_set;
- msm_gpio.gpio_chip.to_irq = msm_gpio_to_irq;
- msm_gpio.gpio_chip.request = msm_gpio_request;
- msm_gpio.gpio_chip.free = msm_gpio_free;
-
- ret = gpiochip_add(&msm_gpio.gpio_chip);
- if (ret < 0) {
- dev_err(&pdev->dev, "gpiochip_add failed with error %d\n", ret);
- return ret;
- }
-
- msm_gpio.summary_irq = platform_get_irq(pdev, 0);
- if (msm_gpio.summary_irq < 0) {
- dev_err(&pdev->dev, "No Summary irq defined for msmgpio\n");
- return msm_gpio.summary_irq;
- }
-
- msm_gpio.domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
- &msm_gpio_irq_domain_ops,
- &msm_gpio);
- if (!msm_gpio.domain)
- return -ENODEV;
-
- irq_set_chained_handler(msm_gpio.summary_irq, msm_summary_irq_handler);
-
- return 0;
-}
-
-static const struct of_device_id msm_gpio_of_match[] = {
- { .compatible = "qcom,msm-gpio", },
- { },
-};
-MODULE_DEVICE_TABLE(of, msm_gpio_of_match);
-
-static int msm_gpio_remove(struct platform_device *dev)
-{
- gpiochip_remove(&msm_gpio.gpio_chip);
-
- irq_set_handler(msm_gpio.summary_irq, NULL);
-
- return 0;
-}
-
-static struct platform_driver msm_gpio_driver = {
- .probe = msm_gpio_probe,
- .remove = msm_gpio_remove,
- .driver = {
- .name = "msmgpio",
- .of_match_table = msm_gpio_of_match,
- },
-};
-
-module_platform_driver(msm_gpio_driver)
-
-MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
-MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:msmgpio");
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index df418b81456d..d428b97876c5 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -185,16 +185,6 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
* Functions implementing the gpio_chip methods
*/
-static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
-{
- return pinctrl_request_gpio(chip->base + pin);
-}
-
-static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
-{
- pinctrl_free_gpio(chip->base + pin);
-}
-
static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
{
struct mvebu_gpio_chip *mvchip =
@@ -709,8 +699,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip->soc_variant = soc_variant;
mvchip->chip.label = dev_name(&pdev->dev);
mvchip->chip.dev = &pdev->dev;
- mvchip->chip.request = mvebu_gpio_request;
- mvchip->chip.free = mvebu_gpio_free;
+ mvchip->chip.request = gpiochip_generic_request;
+ mvchip->chip.free = gpiochip_generic_free;
mvchip->chip.direction_input = mvebu_gpio_direction_input;
mvchip->chip.get = mvebu_gpio_get;
mvchip->chip.direction_output = mvebu_gpio_direction_output;
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index b8dd847443c5..6ea8df6c7397 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -33,7 +33,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/module.h>
-#include <asm-generic/bug.h>
+#include <linux/bug.h>
enum mxc_gpio_hwtype {
IMX1_GPIO, /* runs on i.mx1 */
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 5236db161e76..56d2d026e62e 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -51,7 +51,7 @@ struct gpio_regs {
struct gpio_bank {
struct list_head node;
void __iomem *base;
- u16 irq;
+ int irq;
u32 non_wakeup_gpios;
u32 enabled_non_wakeup_gpios;
struct gpio_regs context;
@@ -59,6 +59,7 @@ struct gpio_bank {
u32 level_mask;
u32 toggle_mask;
raw_spinlock_t lock;
+ raw_spinlock_t wa_lock;
struct gpio_chip chip;
struct clk *dbck;
u32 mod_usage;
@@ -496,9 +497,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
(type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
return -EINVAL;
- if (!BANK_USED(bank))
- pm_runtime_get_sync(bank->dev);
-
raw_spin_lock_irqsave(&bank->lock, flags);
retval = omap_set_gpio_triggering(bank, offset, type);
if (retval) {
@@ -521,8 +519,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
return 0;
error:
- if (!BANK_USED(bank))
- pm_runtime_put(bank->dev);
return retval;
}
@@ -654,8 +650,13 @@ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned offset = d->hwirq;
+ int ret;
+
+ ret = omap_set_gpio_wakeup(bank, offset, enable);
+ if (!ret)
+ ret = irq_set_irq_wake(bank->irq, enable);
- return omap_set_gpio_wakeup(bank, offset, enable);
+ return ret;
}
static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -709,26 +710,21 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
* line's interrupt handler has been run, we may miss some nested
* interrupts.
*/
-static void omap_gpio_irq_handler(struct irq_desc *desc)
+static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
{
void __iomem *isr_reg = NULL;
u32 isr;
unsigned int bit;
- struct gpio_bank *bank;
- int unmasked = 0;
- struct irq_chip *irqchip = irq_desc_get_chip(desc);
- struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+ struct gpio_bank *bank = gpiobank;
+ unsigned long wa_lock_flags;
unsigned long lock_flags;
- chained_irq_enter(irqchip, desc);
-
- bank = container_of(chip, struct gpio_bank, chip);
isr_reg = bank->base + bank->regs->irqstatus;
- pm_runtime_get_sync(bank->dev);
-
if (WARN_ON(!isr_reg))
goto exit;
+ pm_runtime_get_sync(bank->dev);
+
while (1) {
u32 isr_saved, level_mask = 0;
u32 enabled;
@@ -750,13 +746,6 @@ static void omap_gpio_irq_handler(struct irq_desc *desc)
raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
- /* if there is only edge sensitive GPIO pin interrupts
- configured, we could unmask GPIO bank interrupt immediately */
- if (!level_mask && !unmasked) {
- unmasked = 1;
- chained_irq_exit(irqchip, desc);
- }
-
if (!isr)
break;
@@ -777,18 +766,18 @@ static void omap_gpio_irq_handler(struct irq_desc *desc)
raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+ raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
+
generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
bit));
+
+ raw_spin_unlock_irqrestore(&bank->wa_lock,
+ wa_lock_flags);
}
}
- /* if bank has any level sensitive GPIO pin interrupt
- configured, we must unmask the bank interrupt only after
- handler(s) are executed in order to avoid spurious bank
- interrupt */
exit:
- if (!unmasked)
- chained_irq_exit(irqchip, desc);
pm_runtime_put(bank->dev);
+ return IRQ_HANDLED;
}
static unsigned int omap_gpio_irq_startup(struct irq_data *d)
@@ -797,9 +786,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
unsigned long flags;
unsigned offset = d->hwirq;
- if (!BANK_USED(bank))
- pm_runtime_get_sync(bank->dev);
-
raw_spin_lock_irqsave(&bank->lock, flags);
if (!LINE_USED(bank->mod_usage, offset))
@@ -815,8 +801,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
return 0;
err:
raw_spin_unlock_irqrestore(&bank->lock, flags);
- if (!BANK_USED(bank))
- pm_runtime_put(bank->dev);
return -EINVAL;
}
@@ -835,6 +819,19 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
omap_clear_gpio_debounce(bank, offset);
omap_disable_gpio_module(bank, offset);
raw_spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void omap_gpio_irq_bus_lock(struct irq_data *data)
+{
+ struct gpio_bank *bank = omap_irq_data_get_bank(data);
+
+ if (!BANK_USED(bank))
+ pm_runtime_get_sync(bank->dev);
+}
+
+static void gpio_irq_bus_sync_unlock(struct irq_data *data)
+{
+ struct gpio_bank *bank = omap_irq_data_get_bank(data);
/*
* If this is the last IRQ to be freed in the bank,
@@ -1132,7 +1129,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
}
ret = gpiochip_irqchip_add(&bank->chip, irqc,
- irq_base, omap_gpio_irq_handler,
+ irq_base, handle_bad_irq,
IRQ_TYPE_NONE);
if (ret) {
@@ -1141,10 +1138,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
return -ENODEV;
}
- gpiochip_set_chained_irqchip(&bank->chip, irqc,
- bank->irq, omap_gpio_irq_handler);
+ gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL);
- return 0;
+ ret = devm_request_irq(bank->dev, bank->irq, omap_gpio_irq_handler,
+ 0, dev_name(bank->dev), bank);
+ if (ret)
+ gpiochip_remove(&bank->chip);
+
+ return ret;
}
static const struct of_device_id omap_gpio_match[];
@@ -1183,6 +1184,8 @@ static int omap_gpio_probe(struct platform_device *pdev)
irqc->irq_unmask = omap_gpio_unmask_irq,
irqc->irq_set_type = omap_gpio_irq_type,
irqc->irq_set_wake = omap_gpio_wake_enable,
+ irqc->irq_bus_lock = omap_gpio_irq_bus_lock,
+ irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock,
irqc->name = dev_name(&pdev->dev);
bank->irq = platform_get_irq(pdev, 0);
@@ -1224,6 +1227,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank->set_dataout = omap_set_gpio_dataout_mask;
raw_spin_lock_init(&bank->lock);
+ raw_spin_lock_init(&bank->wa_lock);
/* Static mapping, never released */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 50caeb1ee350..2d4892cc70fb 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -21,6 +21,7 @@
#ifdef CONFIG_OF_GPIO
#include <linux/of_platform.h>
#endif
+#include <linux/acpi.h>
#define PCA953X_INPUT 0
#define PCA953X_OUTPUT 1
@@ -42,6 +43,9 @@
#define PCA_INT 0x0100
#define PCA953X_TYPE 0x1000
#define PCA957X_TYPE 0x2000
+#define PCA_TYPE_MASK 0xF000
+
+#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK)
static const struct i2c_device_id pca953x_id[] = {
{ "pca9505", 40 | PCA953X_TYPE | PCA_INT, },
@@ -67,11 +71,18 @@ static const struct i2c_device_id pca953x_id[] = {
{ "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
+ { "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
{ "xra1202", 8 | PCA953X_TYPE },
{ }
};
MODULE_DEVICE_TABLE(i2c, pca953x_id);
+static const struct acpi_device_id pca953x_acpi_ids[] = {
+ { "INT3491", 16 | PCA953X_TYPE | PCA_INT, },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
+
#define MAX_BANK 5
#define BANK_SZ 8
@@ -95,6 +106,7 @@ struct pca953x_chip {
struct gpio_chip gpio_chip;
const char *const *names;
int chip_type;
+ unsigned long driver_data;
};
static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
@@ -517,14 +529,13 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
}
static int pca953x_irq_setup(struct pca953x_chip *chip,
- const struct i2c_device_id *id,
int irq_base)
{
struct i2c_client *client = chip->client;
int ret, i, offset = 0;
if (client->irq && irq_base != -1
- && (id->driver_data & PCA_INT)) {
+ && (chip->driver_data & PCA_INT)) {
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -581,12 +592,11 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
#else /* CONFIG_GPIO_PCA953X_IRQ */
static int pca953x_irq_setup(struct pca953x_chip *chip,
- const struct i2c_device_id *id,
int irq_base)
{
struct i2c_client *client = chip->client;
- if (irq_base != -1 && (id->driver_data & PCA_INT))
+ if (irq_base != -1 && (chip->driver_data & PCA_INT))
dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0;
@@ -635,11 +645,15 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
memset(val, 0xFF, NBANK(chip));
else
memset(val, 0, NBANK(chip));
- pca953x_write_regs(chip, PCA957X_INVRT, val);
+ ret = pca953x_write_regs(chip, PCA957X_INVRT, val);
+ if (ret)
+ goto out;
/* To enable register 6, 7 to control pull up and pull down */
memset(val, 0x02, NBANK(chip));
- pca953x_write_regs(chip, PCA957X_BKEN, val);
+ ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
+ if (ret)
+ goto out;
return 0;
out:
@@ -673,14 +687,26 @@ static int pca953x_probe(struct i2c_client *client,
chip->client = client;
- chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
+ if (id) {
+ chip->driver_data = id->driver_data;
+ } else {
+ const struct acpi_device_id *id;
+
+ id = acpi_match_device(pca953x_acpi_ids, &client->dev);
+ if (!id)
+ return -ENODEV;
+
+ chip->driver_data = id->driver_data;
+ }
+
+ chip->chip_type = PCA_CHIP_TYPE(chip->driver_data);
mutex_init(&chip->i2c_lock);
/* initialize cached registers from their original values.
* we can't share this chip with another i2c master.
*/
- pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
+ pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
if (chip->chip_type == PCA953X_TYPE)
ret = device_pca953x_init(chip, invert);
@@ -693,7 +719,7 @@ static int pca953x_probe(struct i2c_client *client,
if (ret)
return ret;
- ret = pca953x_irq_setup(chip, id, irq_base);
+ ret = pca953x_irq_setup(chip, irq_base);
if (ret)
return ret;
@@ -765,6 +791,7 @@ static struct i2c_driver pca953x_driver = {
.driver = {
.name = "pca953x",
.of_match_table = pca953x_dt_ids,
+ .acpi_match_table = ACPI_PTR(pca953x_acpi_ids),
},
.probe = pca953x_probe,
.remove = pca953x_remove,
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 229ef653e0f8..4d4b37676702 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -52,36 +52,12 @@ struct pl061_gpio {
void __iomem *base;
struct gpio_chip gc;
- bool uses_pinctrl;
#ifdef CONFIG_PM
struct pl061_context_save_regs csave_regs;
#endif
};
-static int pl061_gpio_request(struct gpio_chip *gc, unsigned offset)
-{
- /*
- * Map back to global GPIO space and request muxing, the direction
- * parameter does not matter for this controller.
- */
- struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- int gpio = gc->base + offset;
-
- if (chip->uses_pinctrl)
- return pinctrl_request_gpio(gpio);
- return 0;
-}
-
-static void pl061_gpio_free(struct gpio_chip *gc, unsigned offset)
-{
- struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- int gpio = gc->base + offset;
-
- if (chip->uses_pinctrl)
- pinctrl_free_gpio(gpio);
-}
-
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@@ -152,6 +128,17 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
if (offset < 0 || offset >= PL061_GPIO_NR)
return -EINVAL;
+ if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
+ (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
+ {
+ dev_err(gc->dev,
+ "trying to configure line %d for both level and edge "
+ "detection, choose one!\n",
+ offset);
+ return -EINVAL;
+ }
+
+
spin_lock_irqsave(&chip->lock, flags);
gpioiev = readb(chip->base + GPIOIEV);
@@ -159,23 +146,53 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
gpioibe = readb(chip->base + GPIOIBE);
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+ bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
+
+ /* Disable edge detection */
+ gpioibe &= ~bit;
+ /* Enable level detection */
gpiois |= bit;
- if (trigger & IRQ_TYPE_LEVEL_HIGH)
+ /* Select polarity */
+ if (polarity)
gpioiev |= bit;
else
gpioiev &= ~bit;
- } else
+ irq_set_handler_locked(d, handle_level_irq);
+ dev_dbg(gc->dev, "line %d: IRQ on %s level\n",
+ offset,
+ polarity ? "HIGH" : "LOW");
+ } else if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+ /* Disable level detection */
gpiois &= ~bit;
-
- if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- /* Setting this makes GPIOEV be ignored */
+ /* Select both edges, setting this makes GPIOEV be ignored */
gpioibe |= bit;
- else {
+ irq_set_handler_locked(d, handle_edge_irq);
+ dev_dbg(gc->dev, "line %d: IRQ on both edges\n", offset);
+ } else if ((trigger & IRQ_TYPE_EDGE_RISING) ||
+ (trigger & IRQ_TYPE_EDGE_FALLING)) {
+ bool rising = trigger & IRQ_TYPE_EDGE_RISING;
+
+ /* Disable level detection */
+ gpiois &= ~bit;
+ /* Clear detection on both edges */
gpioibe &= ~bit;
- if (trigger & IRQ_TYPE_EDGE_RISING)
+ /* Select edge */
+ if (rising)
gpioiev |= bit;
- else if (trigger & IRQ_TYPE_EDGE_FALLING)
+ else
gpioiev &= ~bit;
+ irq_set_handler_locked(d, handle_edge_irq);
+ dev_dbg(gc->dev, "line %d: IRQ on %s edge\n",
+ offset,
+ rising ? "RISING" : "FALLING");
+ } else {
+ /* No trigger: disable everything */
+ gpiois &= ~bit;
+ gpioibe &= ~bit;
+ gpioiev &= ~bit;
+ irq_set_handler_locked(d, handle_bad_irq);
+ dev_warn(gc->dev, "no trigger selected for line %d\n",
+ offset);
}
writeb(gpiois, chip->base + GPIOIS);
@@ -198,7 +215,6 @@ static void pl061_irq_handler(struct irq_desc *desc)
chained_irq_enter(irqchip, desc);
pending = readb(chip->base + GPIOMIS);
- writeb(pending, chip->base + GPIOIC);
if (pending) {
for_each_set_bit(offset, &pending, PL061_GPIO_NR)
generic_handle_irq(irq_find_mapping(gc->irqdomain,
@@ -234,8 +250,28 @@ static void pl061_irq_unmask(struct irq_data *d)
spin_unlock(&chip->lock);
}
+/**
+ * pl061_irq_ack() - ACK an edge IRQ
+ * @d: IRQ data for this IRQ
+ *
+ * This gets called from the edge IRQ handler to ACK the edge IRQ
+ * in the GPIOIC (interrupt-clear) register. For level IRQs this is
+ * not needed: these go away when the level signal goes away.
+ */
+static void pl061_irq_ack(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+ u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
+
+ spin_lock(&chip->lock);
+ writeb(mask, chip->base + GPIOIC);
+ spin_unlock(&chip->lock);
+}
+
static struct irq_chip pl061_irqchip = {
.name = "pl061",
+ .irq_ack = pl061_irq_ack,
.irq_mask = pl061_irq_mask,
.irq_unmask = pl061_irq_unmask,
.irq_set_type = pl061_irq_type,
@@ -269,11 +305,11 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(chip->base);
spin_lock_init(&chip->lock);
- if (of_property_read_bool(dev->of_node, "gpio-ranges"))
- chip->uses_pinctrl = true;
+ if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
+ chip->gc.request = gpiochip_generic_request;
+ chip->gc.free = gpiochip_generic_free;
+ }
- chip->gc.request = pl061_gpio_request;
- chip->gc.free = pl061_gpio_free;
chip->gc.direction_input = pl061_direction_input;
chip->gc.direction_output = pl061_direction_output;
chip->gc.get = pl061_get_value;
@@ -298,7 +334,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
}
ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip,
- irq_base, handle_simple_irq,
+ irq_base, handle_bad_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_info(&adev->dev, "could not add irqchip\n");
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 65bc9f47a68e..34b02b42ab9e 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -102,7 +102,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node,
{
u32 line, type;
- if (node != h->of_node)
+ if (node != irq_domain_get_of_node(h))
return -EINVAL;
if (intsize < 2)
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index 9c6b96707c9f..76f920173a2f 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -160,6 +160,11 @@ static const struct of_device_id sx150x_of_match[] = {
};
MODULE_DEVICE_TABLE(of, sx150x_of_match);
+struct sx150x_chip *to_sx150x(struct gpio_chip *gc)
+{
+ return container_of(gc, struct sx150x_chip, gpio_chip);
+}
+
static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
{
s32 err = i2c_smbus_write_byte_data(client, reg, val);
@@ -296,11 +301,9 @@ static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
{
- struct sx150x_chip *chip;
+ struct sx150x_chip *chip = to_sx150x(gc);
int status = -EINVAL;
- chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
if (!offset_is_oscio(chip, offset)) {
mutex_lock(&chip->lock);
status = sx150x_get_io(chip, offset);
@@ -312,9 +315,7 @@ static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
{
- struct sx150x_chip *chip;
-
- chip = container_of(gc, struct sx150x_chip, gpio_chip);
+ struct sx150x_chip *chip = to_sx150x(gc);
mutex_lock(&chip->lock);
if (offset_is_oscio(chip, offset))
@@ -326,11 +327,9 @@ static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
- struct sx150x_chip *chip;
+ struct sx150x_chip *chip = to_sx150x(gc);
int status = -EINVAL;
- chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
if (!offset_is_oscio(chip, offset)) {
mutex_lock(&chip->lock);
status = sx150x_io_input(chip, offset);
@@ -343,11 +342,9 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc,
unsigned offset,
int val)
{
- struct sx150x_chip *chip;
+ struct sx150x_chip *chip = to_sx150x(gc);
int status = 0;
- chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
if (!offset_is_oscio(chip, offset)) {
mutex_lock(&chip->lock);
status = sx150x_io_output(chip, offset, val);
@@ -358,7 +355,7 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc,
static void sx150x_irq_mask(struct irq_data *d)
{
- struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n = d->hwirq;
chip->irq_masked |= (1 << n);
@@ -367,7 +364,7 @@ static void sx150x_irq_mask(struct irq_data *d)
static void sx150x_irq_unmask(struct irq_data *d)
{
- struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n = d->hwirq;
chip->irq_masked &= ~(1 << n);
@@ -376,7 +373,7 @@ static void sx150x_irq_unmask(struct irq_data *d)
static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
- struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n, val = 0;
if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
@@ -431,14 +428,14 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
static void sx150x_irq_bus_lock(struct irq_data *d)
{
- struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
mutex_lock(&chip->lock);
}
static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
{
- struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n;
if (chip->irq_update == NO_UPDATE_PENDING)
diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c
index 12c99d969b98..4356e6c20fc5 100644
--- a/drivers/gpio/gpio-tb10x.c
+++ b/drivers/gpio/gpio-tb10x.c
@@ -138,16 +138,6 @@ static int tb10x_gpio_direction_out(struct gpio_chip *chip,
return 0;
}
-static int tb10x_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void tb10x_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
@@ -213,8 +203,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
tb10x_gpio->gc.get = tb10x_gpio_get;
tb10x_gpio->gc.direction_output = tb10x_gpio_direction_out;
tb10x_gpio->gc.set = tb10x_gpio_set;
- tb10x_gpio->gc.request = tb10x_gpio_request;
- tb10x_gpio->gc.free = tb10x_gpio_free;
+ tb10x_gpio->gc.request = gpiochip_generic_request;
+ tb10x_gpio->gc.free = gpiochip_generic_free;
tb10x_gpio->gc.base = -1;
tb10x_gpio->gc.ngpio = ngpio;
tb10x_gpio->gc.can_sleep = false;
diff --git a/drivers/gpio/gpio-tz1090-pdc.c b/drivers/gpio/gpio-tz1090-pdc.c
index ede7e403ffde..3623d009d808 100644
--- a/drivers/gpio/gpio-tz1090-pdc.c
+++ b/drivers/gpio/gpio-tz1090-pdc.c
@@ -137,16 +137,6 @@ static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset,
__global_unlock2(lstat);
}
-static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
@@ -203,8 +193,8 @@ static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
priv->chip.direction_output = tz1090_pdc_gpio_direction_output;
priv->chip.get = tz1090_pdc_gpio_get;
priv->chip.set = tz1090_pdc_gpio_set;
- priv->chip.free = tz1090_pdc_gpio_free;
- priv->chip.request = tz1090_pdc_gpio_request;
+ priv->chip.free = gpiochip_generic_free;
+ priv->chip.request = gpiochip_generic_request;
priv->chip.to_irq = tz1090_pdc_gpio_to_irq;
priv->chip.of_node = np;
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 069f9e4b7daa..87b950cec6ec 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -62,6 +62,11 @@ struct vf610_gpio_port {
static struct irq_chip vf610_gpio_irq_chip;
+static struct vf610_gpio_port *to_vf610_gp(struct gpio_chip *gc)
+{
+ return container_of(gc, struct vf610_gpio_port, gc);
+}
+
static const struct of_device_id vf610_gpio_dt_ids[] = {
{ .compatible = "fsl,vf610-gpio" },
{ /* sentinel */ }
@@ -77,28 +82,16 @@ static inline u32 vf610_gpio_readl(void __iomem *reg)
return readl_relaxed(reg);
}
-static int vf610_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void vf610_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
- struct vf610_gpio_port *port =
- container_of(gc, struct vf610_gpio_port, gc);
+ struct vf610_gpio_port *port = to_vf610_gp(gc);
return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
}
static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
- struct vf610_gpio_port *port =
- container_of(gc, struct vf610_gpio_port, gc);
+ struct vf610_gpio_port *port = to_vf610_gp(gc);
unsigned long mask = BIT(gpio);
if (val)
@@ -122,7 +115,8 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
static void vf610_gpio_irq_handler(struct irq_desc *desc)
{
- struct vf610_gpio_port *port = irq_desc_get_handler_data(desc);
+ struct vf610_gpio_port *port =
+ to_vf610_gp(irq_desc_get_handler_data(desc));
struct irq_chip *chip = irq_desc_get_chip(desc);
int pin;
unsigned long irq_isfr;
@@ -142,7 +136,8 @@ static void vf610_gpio_irq_handler(struct irq_desc *desc)
static void vf610_gpio_irq_ack(struct irq_data *d)
{
- struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct vf610_gpio_port *port =
+ to_vf610_gp(irq_data_get_irq_chip_data(d));
int gpio = d->hwirq;
vf610_gpio_writel(BIT(gpio), port->base + PORT_ISFR);
@@ -150,7 +145,8 @@ static void vf610_gpio_irq_ack(struct irq_data *d)
static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
{
- struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct vf610_gpio_port *port =
+ to_vf610_gp(irq_data_get_irq_chip_data(d));
u8 irqc;
switch (type) {
@@ -185,7 +181,8 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
static void vf610_gpio_irq_mask(struct irq_data *d)
{
- struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct vf610_gpio_port *port =
+ to_vf610_gp(irq_data_get_irq_chip_data(d));
void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
vf610_gpio_writel(0, pcr_base);
@@ -193,7 +190,8 @@ static void vf610_gpio_irq_mask(struct irq_data *d)
static void vf610_gpio_irq_unmask(struct irq_data *d)
{
- struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct vf610_gpio_port *port =
+ to_vf610_gp(irq_data_get_irq_chip_data(d));
void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
vf610_gpio_writel(port->irqc[d->hwirq] << PORT_PCR_IRQC_OFFSET,
@@ -202,7 +200,8 @@ static void vf610_gpio_irq_unmask(struct irq_data *d)
static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
{
- struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct vf610_gpio_port *port =
+ to_vf610_gp(irq_data_get_irq_chip_data(d));
if (enable)
enable_irq_wake(port->irq);
@@ -255,8 +254,8 @@ static int vf610_gpio_probe(struct platform_device *pdev)
gc->ngpio = VF610_GPIO_PER_PORT;
gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
- gc->request = vf610_gpio_request;
- gc->free = vf610_gpio_free;
+ gc->request = gpiochip_generic_request;
+ gc->free = gpiochip_generic_free;
gc->direction_input = vf610_gpio_direction_input;
gc->get = vf610_gpio_get;
gc->direction_output = vf610_gpio_direction_output;
diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c
index e02499a15e72..bc06a2cd2c1d 100644
--- a/drivers/gpio/gpio-xlp.c
+++ b/drivers/gpio/gpio-xlp.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
/*
* XLP GPIO has multiple 32 bit registers for each feature where each register
@@ -208,25 +209,28 @@ static struct irq_chip xlp_gpio_irq_chip = {
.flags = IRQCHIP_ONESHOT_SAFE,
};
-static irqreturn_t xlp_gpio_generic_handler(int irq, void *data)
+static void xlp_gpio_generic_handler(struct irq_desc *desc)
{
- struct xlp_gpio_priv *priv = data;
+ struct xlp_gpio_priv *priv = irq_desc_get_handler_data(desc);
+ struct irq_chip *irqchip = irq_desc_get_chip(desc);
int gpio, regoff;
u32 gpio_stat;
regoff = -1;
gpio_stat = 0;
+
+ chained_irq_enter(irqchip, desc);
for_each_set_bit(gpio, priv->gpio_enabled_mask, XLP_MAX_NR_GPIO) {
if (regoff != gpio / XLP_GPIO_REGSZ) {
regoff = gpio / XLP_GPIO_REGSZ;
gpio_stat = readl(priv->gpio_intr_stat + regoff * 4);
}
+
if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ))
generic_handle_irq(irq_find_mapping(
priv->chip.irqdomain, gpio));
}
-
- return IRQ_HANDLED;
+ chained_irq_exit(irqchip, desc);
}
static int xlp_gpio_dir_output(struct gpio_chip *gc, unsigned gpio, int state)
@@ -378,12 +382,6 @@ static int xlp_gpio_probe(struct platform_device *pdev)
gc->get = xlp_gpio_get;
spin_lock_init(&priv->lock);
-
- err = devm_request_irq(&pdev->dev, irq, xlp_gpio_generic_handler,
- IRQ_TYPE_NONE, pdev->name, priv);
- if (err)
- return err;
-
irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
@@ -401,6 +399,9 @@ static int xlp_gpio_probe(struct platform_device *pdev)
goto out_gpio_remove;
}
+ gpiochip_set_chained_irqchip(gc, &xlp_gpio_irq_chip, irq,
+ xlp_gpio_generic_handler);
+
dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio);
return 0;
diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c
index 4b8a26910705..1dcf7a66dd36 100644
--- a/drivers/gpio/gpio-zx.c
+++ b/drivers/gpio/gpio-zx.c
@@ -41,7 +41,6 @@ struct zx_gpio {
void __iomem *base;
struct gpio_chip gc;
- bool uses_pinctrl;
};
static inline struct zx_gpio *to_zx(struct gpio_chip *gc)
@@ -49,25 +48,6 @@ static inline struct zx_gpio *to_zx(struct gpio_chip *gc)
return container_of(gc, struct zx_gpio, gc);
}
-static int zx_gpio_request(struct gpio_chip *gc, unsigned offset)
-{
- struct zx_gpio *chip = to_zx(gc);
- int gpio = gc->base + offset;
-
- if (chip->uses_pinctrl)
- return pinctrl_request_gpio(gpio);
- return 0;
-}
-
-static void zx_gpio_free(struct gpio_chip *gc, unsigned offset)
-{
- struct zx_gpio *chip = to_zx(gc);
- int gpio = gc->base + offset;
-
- if (chip->uses_pinctrl)
- pinctrl_free_gpio(gpio);
-}
-
static int zx_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct zx_gpio *chip = to_zx(gc);
@@ -252,12 +232,12 @@ static int zx_gpio_probe(struct platform_device *pdev)
return PTR_ERR(chip->base);
spin_lock_init(&chip->lock);
- if (of_property_read_bool(dev->of_node, "gpio-ranges"))
- chip->uses_pinctrl = true;
+ if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
+ chip->gc.request = gpiochip_generic_request;
+ chip->gc.free = gpiochip_generic_free;
+ }
id = of_alias_get_id(dev->of_node, "gpio");
- chip->gc.request = zx_gpio_request;
- chip->gc.free = zx_gpio_free;
chip->gc.direction_input = zx_direction_input;
chip->gc.direction_output = zx_direction_output;
chip->gc.get = zx_get_value;
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 1d1a5865ede9..8abeacac5885 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -130,6 +130,12 @@ struct zynq_platform_data {
static struct irq_chip zynq_gpio_level_irqchip;
static struct irq_chip zynq_gpio_edge_irqchip;
+
+static struct zynq_gpio *to_zynq_gpio(struct gpio_chip *gc)
+{
+ return container_of(gc, struct zynq_gpio, chip);
+}
+
/**
* zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
* for a given pin in the GPIO device
@@ -177,7 +183,7 @@ static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
{
u32 data;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+ struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@@ -201,7 +207,7 @@ static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
int state)
{
unsigned int reg_offset, bank_num, bank_pin_num;
- struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+ struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@@ -238,7 +244,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+ struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@@ -271,7 +277,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
{
u32 reg;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+ struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@@ -301,7 +307,8 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
static void zynq_gpio_irq_mask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
- struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+ struct zynq_gpio *gpio =
+ to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@@ -321,7 +328,8 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data)
static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
- struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+ struct zynq_gpio *gpio =
+ to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@@ -340,7 +348,8 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
static void zynq_gpio_irq_ack(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
- struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+ struct zynq_gpio *gpio =
+ to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@@ -390,7 +399,8 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
{
u32 int_type, int_pol, int_any;
unsigned int device_pin_num, bank_num, bank_pin_num;
- struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+ struct zynq_gpio *gpio =
+ to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@@ -453,7 +463,8 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
{
- struct zynq_gpio *gpio = irq_data_get_irq_chip_data(data);
+ struct zynq_gpio *gpio =
+ to_zynq_gpio(irq_data_get_irq_chip_data(data));
irq_set_irq_wake(gpio->irq, on);
@@ -518,7 +529,8 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc)
{
u32 int_sts, int_enb;
unsigned int bank_num;
- struct zynq_gpio *gpio = irq_desc_get_handler_data(desc);
+ struct zynq_gpio *gpio =
+ to_zynq_gpio(irq_desc_get_handler_data(desc));
struct irq_chip *irqchip = irq_desc_get_chip(desc);
chained_irq_enter(irqchip, desc);
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 143a9bdbaa53..16a7b6816744 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -304,7 +304,6 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
if (ACPI_FAILURE(status))
return;
- INIT_LIST_HEAD(&acpi_gpio->events);
acpi_walk_resources(handle, "_AEI",
acpi_gpiochip_request_interrupt, acpi_gpio);
}
@@ -389,6 +388,8 @@ struct acpi_gpio_lookup {
struct acpi_gpio_info info;
int index;
int pin_index;
+ bool active_low;
+ struct acpi_device *adev;
struct gpio_desc *desc;
int n;
};
@@ -425,6 +426,65 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
return 1;
}
+static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
+ struct acpi_gpio_info *info)
+{
+ struct list_head res_list;
+ int ret;
+
+ INIT_LIST_HEAD(&res_list);
+
+ ret = acpi_dev_get_resources(lookup->adev, &res_list, acpi_find_gpio,
+ lookup);
+ if (ret < 0)
+ return ret;
+
+ acpi_dev_free_resource_list(&res_list);
+
+ if (!lookup->desc)
+ return -ENOENT;
+
+ if (info) {
+ *info = lookup->info;
+ if (lookup->active_low)
+ info->active_low = lookup->active_low;
+ }
+ return 0;
+}
+
+static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
+ const char *propname, int index,
+ struct acpi_gpio_lookup *lookup)
+{
+ struct acpi_reference_args args;
+ int ret;
+
+ memset(&args, 0, sizeof(args));
+ ret = acpi_node_get_property_reference(fwnode, propname, index, &args);
+ if (ret) {
+ struct acpi_device *adev = to_acpi_device_node(fwnode);
+
+ if (!adev)
+ return ret;
+
+ if (!acpi_get_driver_gpio_data(adev, propname, index, &args))
+ return ret;
+ }
+ /*
+ * The property was found and resolved, so need to lookup the GPIO based
+ * on returned args.
+ */
+ lookup->adev = args.adev;
+ if (args.nargs >= 2) {
+ lookup->index = args.args[0];
+ lookup->pin_index = args.args[1];
+ /* 3rd argument, if present is used to specify active_low. */
+ if (args.nargs >= 3)
+ lookup->active_low = !!args.args[2];
+ }
+ return 0;
+}
+
/**
* acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
* @adev: pointer to a ACPI device to get GPIO from
@@ -452,8 +512,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
struct acpi_gpio_info *info)
{
struct acpi_gpio_lookup lookup;
- struct list_head resource_list;
- bool active_low = false;
int ret;
if (!adev)
@@ -463,58 +521,64 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
lookup.index = index;
if (propname) {
- struct acpi_reference_args args;
-
dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
- memset(&args, 0, sizeof(args));
- ret = acpi_dev_get_property_reference(adev, propname,
- index, &args);
- if (ret) {
- bool found = acpi_get_driver_gpio_data(adev, propname,
- index, &args);
- if (!found)
- return ERR_PTR(ret);
- }
-
- /*
- * The property was found and resolved so need to
- * lookup the GPIO based on returned args instead.
- */
- adev = args.adev;
- if (args.nargs >= 2) {
- lookup.index = args.args[0];
- lookup.pin_index = args.args[1];
- /*
- * 3rd argument, if present is used to
- * specify active_low.
- */
- if (args.nargs >= 3)
- active_low = !!args.args[2];
- }
+ ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev),
+ propname, index, &lookup);
+ if (ret)
+ return ERR_PTR(ret);
- dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n",
- dev_name(&adev->dev), args.nargs,
- args.args[0], args.args[1], args.args[2]);
+ dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n",
+ dev_name(&lookup.adev->dev), lookup.index,
+ lookup.pin_index, lookup.active_low);
} else {
dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
+ lookup.adev = adev;
}
- INIT_LIST_HEAD(&resource_list);
- ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
- &lookup);
- if (ret < 0)
- return ERR_PTR(ret);
+ ret = acpi_gpio_resource_lookup(&lookup, info);
+ return ret ? ERR_PTR(ret) : lookup.desc;
+}
- acpi_dev_free_resource_list(&resource_list);
+/**
+ * acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources
+ * @fwnode: pointer to an ACPI firmware node to get the GPIO information from
+ * @propname: Property name of the GPIO
+ * @index: index of GpioIo/GpioInt resource (starting from %0)
+ * @info: info pointer to fill in (optional)
+ *
+ * If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it.
+ * Otherwise (ie. it is a data-only non-device object), use the property-based
+ * GPIO lookup to get to the GPIO resource with the relevant information and use
+ * that to obtain the GPIO descriptor to return.
+ */
+struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
+ const char *propname, int index,
+ struct acpi_gpio_info *info)
+{
+ struct acpi_gpio_lookup lookup;
+ struct acpi_device *adev;
+ int ret;
- if (lookup.desc && info) {
- *info = lookup.info;
- if (active_low)
- info->active_low = active_low;
- }
+ adev = to_acpi_device_node(fwnode);
+ if (adev)
+ return acpi_get_gpiod_by_index(adev, propname, index, info);
+
+ if (!is_acpi_data_node(fwnode))
+ return ERR_PTR(-ENODEV);
+
+ if (!propname)
+ return ERR_PTR(-EINVAL);
- return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.index = index;
+
+ ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = acpi_gpio_resource_lookup(&lookup, info);
+ return ret ? ERR_PTR(ret) : lookup.desc;
}
/**
@@ -603,6 +667,25 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
break;
}
}
+
+ /*
+ * The same GPIO can be shared between operation region and
+ * 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 &&
+ function == ACPI_READ) {
+ struct acpi_gpio_event *event;
+
+ list_for_each_entry(event, &achip->events, node) {
+ if (event->pin == pin) {
+ desc = event->desc;
+ found = true;
+ break;
+ }
+ }
+ }
+
if (!found) {
desc = gpiochip_request_own_desc(chip, pin,
"ACPI:OpRegion");
@@ -719,6 +802,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
}
acpi_gpio->chip = chip;
+ INIT_LIST_HEAD(&acpi_gpio->events);
status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
index 8b830996fe02..3a5c7011ad3b 100644
--- a/drivers/gpio/gpiolib-legacy.c
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -28,10 +28,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (!desc && gpio_is_valid(gpio))
return -EPROBE_DEFER;
- err = gpiod_request(desc, label);
- if (err)
- return err;
-
if (flags & GPIOF_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
@@ -41,6 +37,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (flags & GPIOF_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ err = gpiod_request(desc, label);
+ if (err)
+ return err;
+
if (flags & GPIOF_DIR_IN)
err = gpiod_direction_input(desc);
else
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index fa6e3c8823d6..5fe34a9df3e6 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -119,20 +119,20 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
EXPORT_SYMBOL(of_get_named_gpio_flags);
/**
- * of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API
+ * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API
* @np: device node to get GPIO from
* @name: GPIO line name
* @lflags: gpio_lookup_flags - returned from of_find_gpio() or
- * of_get_gpio_hog()
+ * of_parse_own_gpio()
* @dflags: gpiod_flags - optional GPIO initialization flags
*
* Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
* value on the error condition.
*/
-static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
- const char **name,
- enum gpio_lookup_flags *lflags,
- enum gpiod_flags *dflags)
+static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
+ const char **name,
+ enum gpio_lookup_flags *lflags,
+ enum gpiod_flags *dflags)
{
struct device_node *chip_np;
enum of_gpio_flags xlate_flags;
@@ -196,13 +196,13 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
}
/**
- * of_gpiochip_scan_hogs - Scan gpio-controller and apply GPIO hog as requested
+ * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
* @chip: gpio chip to act on
*
* This is only used by of_gpiochip_add to request/set GPIO initial
* configuration.
*/
-static void of_gpiochip_scan_hogs(struct gpio_chip *chip)
+static void of_gpiochip_scan_gpios(struct gpio_chip *chip)
{
struct gpio_desc *desc = NULL;
struct device_node *np;
@@ -214,7 +214,7 @@ static void of_gpiochip_scan_hogs(struct gpio_chip *chip)
if (!of_property_read_bool(np, "gpio-hog"))
continue;
- desc = of_get_gpio_hog(np, &name, &lflags, &dflags);
+ desc = of_parse_own_gpio(np, &name, &lflags, &dflags);
if (IS_ERR(desc))
continue;
@@ -440,7 +440,7 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_node_get(chip->of_node);
- of_gpiochip_scan_hogs(chip);
+ of_gpiochip_scan_gpios(chip);
return 0;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5db3445552b1..a18f00fc1bb8 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -15,6 +15,7 @@
#include <linux/acpi.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
+#include <linux/pinctrl/consumer.h>
#include "gpiolib.h"
@@ -47,8 +48,6 @@
*/
DEFINE_SPINLOCK(gpio_lock);
-#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
-
static DEFINE_MUTEX(gpio_lookup_lock);
static LIST_HEAD(gpio_lookup_list);
LIST_HEAD(gpio_chips);
@@ -219,6 +218,68 @@ static int gpiochip_add_to_list(struct gpio_chip *chip)
}
/**
+ * Convert a GPIO name to its descriptor
+ */
+static struct gpio_desc *gpio_name_to_desc(const char * const name)
+{
+ struct gpio_chip *chip;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ list_for_each_entry(chip, &gpio_chips, list) {
+ int i;
+
+ for (i = 0; i != chip->ngpio; ++i) {
+ struct gpio_desc *gpio = &chip->desc[i];
+
+ if (!gpio->name)
+ continue;
+
+ if (!strcmp(gpio->name, name)) {
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ return gpio;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return NULL;
+}
+
+/*
+ * Takes the names from gc->names and checks if they are all unique. If they
+ * are, they are assigned to their gpio descriptors.
+ *
+ * Returns -EEXIST if one of the names is already used for a different GPIO.
+ */
+static int gpiochip_set_desc_names(struct gpio_chip *gc)
+{
+ int i;
+
+ if (!gc->names)
+ return 0;
+
+ /* First check all names if they are unique */
+ for (i = 0; i != gc->ngpio; ++i) {
+ struct gpio_desc *gpio;
+
+ gpio = gpio_name_to_desc(gc->names[i]);
+ if (gpio)
+ dev_warn(gc->dev, "Detected name collision for "
+ "GPIO name '%s'\n",
+ gc->names[i]);
+ }
+
+ /* Then add all names to the GPIO descriptors */
+ for (i = 0; i != gc->ngpio; ++i)
+ gc->desc[i].name = gc->names[i];
+
+ return 0;
+}
+
+/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
* Context: potentially before irqs will work
@@ -290,6 +351,10 @@ int gpiochip_add(struct gpio_chip *chip)
if (!chip->owner && chip->dev && chip->dev->driver)
chip->owner = chip->dev->driver->owner;
+ status = gpiochip_set_desc_names(chip);
+ if (status)
+ goto err_remove_from_list;
+
status = of_gpiochip_add(chip);
if (status)
goto err_remove_chip;
@@ -310,6 +375,7 @@ err_remove_chip:
acpi_gpiochip_remove(chip);
gpiochip_free_hogs(chip);
of_gpiochip_remove(chip);
+err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags);
list_del(&chip->list);
spin_unlock_irqrestore(&gpio_lock, flags);
@@ -680,6 +746,28 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
#endif /* CONFIG_GPIOLIB_IRQCHIP */
+/**
+ * gpiochip_generic_request() - request the gpio function for a pin
+ * @chip: the gpiochip owning the GPIO
+ * @offset: the offset of the GPIO to request for GPIO function
+ */
+int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+EXPORT_SYMBOL_GPL(gpiochip_generic_request);
+
+/**
+ * gpiochip_generic_free() - free the gpio function from a pin
+ * @chip: the gpiochip to request the gpio function for
+ * @offset: the offset of the GPIO to free from GPIO function
+ */
+void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+EXPORT_SYMBOL_GPL(gpiochip_generic_free);
+
#ifdef CONFIG_PINCTRL
/**
@@ -839,6 +927,14 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
}
done:
+ if (status < 0) {
+ /* Clear flags that might have been set by the caller before
+ * requesting the GPIO.
+ */
+ clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
+ clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
+ }
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
@@ -928,7 +1024,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
{
struct gpio_desc *desc;
- if (!GPIO_OFFSET_VALID(chip, offset))
+ if (offset >= chip->ngpio)
return NULL;
desc = &chip->desc[offset];
@@ -1735,6 +1831,13 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_ACTIVE_LOW;
+ if (of_flags & OF_GPIO_SINGLE_ENDED) {
+ if (of_flags & OF_GPIO_ACTIVE_LOW)
+ *flags |= GPIO_OPEN_DRAIN;
+ else
+ *flags |= GPIO_OPEN_SOURCE;
+ }
+
return desc;
}
@@ -1953,13 +2056,28 @@ struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
}
EXPORT_SYMBOL_GPL(gpiod_get_optional);
+/**
+ * gpiod_parse_flags - helper function to parse GPIO lookup flags
+ * @desc: gpio to be setup
+ * @lflags: gpio_lookup_flags - returned from of_find_gpio() or
+ * of_get_gpio_hog()
+ *
+ * Set the GPIO descriptor flags based on the given GPIO lookup flags.
+ */
+static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
+{
+ if (lflags & GPIO_ACTIVE_LOW)
+ set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ if (lflags & GPIO_OPEN_DRAIN)
+ set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+ if (lflags & GPIO_OPEN_SOURCE)
+ set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+}
/**
* gpiod_configure_flags - helper function to configure a given GPIO
* @desc: gpio whose value will be assigned
* @con_id: function within the GPIO consumer
- * @lflags: gpio_lookup_flags - returned from of_find_gpio() or
- * of_get_gpio_hog()
* @dflags: gpiod_flags - optional GPIO initialization flags
*
* Return 0 on success, -ENOENT if no GPIO has been assigned to the
@@ -1967,17 +2085,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
* occurred while trying to acquire the GPIO.
*/
static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
- unsigned long lflags, enum gpiod_flags dflags)
+ enum gpiod_flags dflags)
{
int status;
- if (lflags & GPIO_ACTIVE_LOW)
- set_bit(FLAG_ACTIVE_LOW, &desc->flags);
- if (lflags & GPIO_OPEN_DRAIN)
- set_bit(FLAG_OPEN_DRAIN, &desc->flags);
- if (lflags & GPIO_OPEN_SOURCE)
- set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-
/* No particular flag request, return here... */
if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
pr_debug("no flags found for %s\n", con_id);
@@ -2044,11 +2155,13 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
return desc;
}
+ gpiod_parse_flags(desc, lookupflags);
+
status = gpiod_request(desc, con_id);
if (status < 0)
return ERR_PTR(status);
- status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
+ status = gpiod_configure_flags(desc, con_id, flags);
if (status < 0) {
dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
gpiod_put(desc);
@@ -2078,6 +2191,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
{
struct gpio_desc *desc = ERR_PTR(-ENODEV);
bool active_low = false;
+ bool single_ended = false;
int ret;
if (!fwnode)
@@ -2088,13 +2202,14 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
desc = of_get_named_gpiod_flags(to_of_node(fwnode), propname, 0,
&flags);
- if (!IS_ERR(desc))
+ if (!IS_ERR(desc)) {
active_low = flags & OF_GPIO_ACTIVE_LOW;
+ single_ended = flags & OF_GPIO_SINGLE_ENDED;
+ }
} else if (is_acpi_node(fwnode)) {
struct acpi_gpio_info info;
- desc = acpi_get_gpiod_by_index(to_acpi_node(fwnode), propname, 0,
- &info);
+ desc = acpi_node_get_gpiod(fwnode, propname, 0, &info);
if (!IS_ERR(desc))
active_low = info.active_low;
}
@@ -2102,14 +2217,20 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
if (IS_ERR(desc))
return desc;
+ if (active_low)
+ set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+ if (single_ended) {
+ if (active_low)
+ set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+ else
+ set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+ }
+
ret = gpiod_request(desc, NULL);
if (ret)
return ERR_PTR(ret);
- /* Only value flag can be set from both DT and ACPI is active_low */
- if (active_low)
- set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-
return desc;
}
EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@@ -2162,6 +2283,8 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
chip = gpiod_to_chip(desc);
hwnum = gpio_chip_hwgpio(desc);
+ gpiod_parse_flags(desc, lflags);
+
local_desc = gpiochip_request_own_desc(chip, hwnum, name);
if (IS_ERR(local_desc)) {
pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n",
@@ -2169,7 +2292,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
return PTR_ERR(local_desc);
}
- status = gpiod_configure_flags(desc, name, lflags, dflags);
+ status = gpiod_configure_flags(desc, name, dflags);
if (status < 0) {
pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n",
name, chip->label, hwnum);
@@ -2309,14 +2432,19 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
int is_irq;
for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
- if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
+ if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) {
+ if (gdesc->name) {
+ seq_printf(s, " gpio-%-3d (%-20.20s)\n",
+ gpio, gdesc->name);
+ }
continue;
+ }
gpiod_get_direction(gdesc);
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
is_irq = test_bit(FLAG_USED_AS_IRQ, &gdesc->flags);
- seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s",
- gpio, gdesc->label,
+ seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s",
+ gpio, gdesc->name ? gdesc->name : "", gdesc->label,
is_out ? "out" : "in ",
chip->get
? (chip->get(chip, i) ? "hi" : "lo")
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index bf343004b008..98ab08c0aa2d 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -42,6 +42,9 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
const char *propname, int index,
struct acpi_gpio_info *info);
+struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
+ const char *propname, int index,
+ struct acpi_gpio_info *info);
int acpi_gpio_count(struct device *dev, const char *con_id);
#else
@@ -60,7 +63,12 @@ acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
{
return ERR_PTR(-ENOSYS);
}
-
+static inline struct gpio_desc *
+acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
+ int index, struct acpi_gpio_info *info)
+{
+ return ERR_PTR(-ENXIO);
+}
static inline int acpi_gpio_count(struct device *dev, const char *con_id)
{
return -ENODEV;
@@ -89,7 +97,10 @@ struct gpio_desc {
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
+ /* Connection label */
const char *label;
+ /* Name of the GPIO */
+ const char *name;
};
int gpiod_request(struct gpio_desc *desc, const char *label);
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1a0a8df2eed8..c4bf9a1cf4a6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -264,3 +264,5 @@ source "drivers/gpu/drm/sti/Kconfig"
source "drivers/gpu/drm/amd/amdkfd/Kconfig"
source "drivers/gpu/drm/imx/Kconfig"
+
+source "drivers/gpu/drm/vc4/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 45e7719846b1..1e9ff4c3e3db 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -6,7 +6,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \
drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_drv.o drm_vm.o \
- drm_agpsupport.o drm_scatter.o drm_pci.o \
+ drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_modes.o drm_edid.o \
drm_info.o drm_debugfs.o drm_encoder_slave.o \
@@ -19,6 +19,9 @@ drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drm-$(CONFIG_PCI) += ati_pcigart.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
+drm-$(CONFIG_AGP) += drm_agpsupport.o
+
+drm-y += $(drm-m)
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
@@ -42,6 +45,7 @@ obj-$(CONFIG_DRM_MGA) += mga/
obj-$(CONFIG_DRM_I810) += i810/
obj-$(CONFIG_DRM_I915) += i915/
obj-$(CONFIG_DRM_MGAG200) += mgag200/
+obj-$(CONFIG_DRM_VC4) += vc4/
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
obj-$(CONFIG_DRM_SIS) += sis/
obj-$(CONFIG_DRM_SAVAGE)+= savage/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 6647fb26ef25..306f75700bf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -79,6 +79,8 @@ extern int amdgpu_bapm;
extern int amdgpu_deep_color;
extern int amdgpu_vm_size;
extern int amdgpu_vm_block_size;
+extern int amdgpu_vm_fault_stop;
+extern int amdgpu_vm_debug;
extern int amdgpu_enable_scheduler;
extern int amdgpu_sched_jobs;
extern int amdgpu_sched_hw_submission;
@@ -343,7 +345,6 @@ struct amdgpu_ring_funcs {
/* testing functions */
int (*test_ring)(struct amdgpu_ring *ring);
int (*test_ib)(struct amdgpu_ring *ring);
- bool (*is_lockup)(struct amdgpu_ring *ring);
/* insert NOP packets */
void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
};
@@ -388,7 +389,6 @@ struct amdgpu_clock {
* Fences.
*/
struct amdgpu_fence_driver {
- struct amdgpu_ring *ring;
uint64_t gpu_addr;
volatile uint32_t *cpu_addr;
/* sync_seq is protected by ring emission lock */
@@ -397,14 +397,13 @@ struct amdgpu_fence_driver {
bool initialized;
struct amdgpu_irq_src *irq_src;
unsigned irq_type;
- struct delayed_work lockup_work;
+ struct timer_list fallback_timer;
wait_queue_head_t fence_queue;
};
/* some special values for the owner field */
#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)
#define AMDGPU_FENCE_OWNER_VM ((void*)1ul)
-#define AMDGPU_FENCE_OWNER_MOVE ((void*)2ul)
#define AMDGPU_FENCE_FLAG_64BIT (1 << 0)
#define AMDGPU_FENCE_FLAG_INT (1 << 1)
@@ -446,58 +445,11 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
-signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
- struct fence **array,
- uint32_t count,
- bool intr,
- signed long t);
-struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
-void amdgpu_fence_unref(struct amdgpu_fence **fence);
-
bool amdgpu_fence_need_sync(struct amdgpu_fence *fence,
struct amdgpu_ring *ring);
void amdgpu_fence_note_sync(struct amdgpu_fence *fence,
struct amdgpu_ring *ring);
-static inline struct amdgpu_fence *amdgpu_fence_later(struct amdgpu_fence *a,
- struct amdgpu_fence *b)
-{
- if (!a) {
- return b;
- }
-
- if (!b) {
- return a;
- }
-
- BUG_ON(a->ring != b->ring);
-
- if (a->seq > b->seq) {
- return a;
- } else {
- return b;
- }
-}
-
-static inline bool amdgpu_fence_is_earlier(struct amdgpu_fence *a,
- struct amdgpu_fence *b)
-{
- if (!a) {
- return false;
- }
-
- if (!b) {
- return true;
- }
-
- BUG_ON(a->ring != b->ring);
-
- return a->seq < b->seq;
-}
-
-int amdgpu_user_fence_emit(struct amdgpu_ring *ring, struct amdgpu_user_fence *user,
- void *owner, struct amdgpu_fence **fence);
-
/*
* TTM.
*/
@@ -708,7 +660,7 @@ void amdgpu_semaphore_free(struct amdgpu_device *adev,
*/
struct amdgpu_sync {
struct amdgpu_semaphore *semaphores[AMDGPU_NUM_SYNCS];
- struct amdgpu_fence *sync_to[AMDGPU_MAX_RINGS];
+ struct fence *sync_to[AMDGPU_MAX_RINGS];
DECLARE_HASHTABLE(fences, 4);
struct fence *last_vm_update;
};
@@ -905,8 +857,6 @@ struct amdgpu_ring {
unsigned ring_size;
unsigned ring_free_dw;
int count_dw;
- atomic_t last_rptr;
- atomic64_t last_activity;
uint64_t gpu_addr;
uint32_t align_mask;
uint32_t ptr_mask;
@@ -960,9 +910,14 @@ struct amdgpu_ring {
#define AMDGPU_PTE_FRAG_64KB (4 << 7)
#define AMDGPU_LOG2_PAGES_PER_FRAG 4
+/* How to programm VM fault handling */
+#define AMDGPU_VM_FAULT_STOP_NEVER 0
+#define AMDGPU_VM_FAULT_STOP_FIRST 1
+#define AMDGPU_VM_FAULT_STOP_ALWAYS 2
+
struct amdgpu_vm_pt {
- struct amdgpu_bo *bo;
- uint64_t addr;
+ struct amdgpu_bo *bo;
+ uint64_t addr;
};
struct amdgpu_vm_id {
@@ -970,8 +925,6 @@ struct amdgpu_vm_id {
uint64_t pd_gpu_addr;
/* last flushed PD/PT update */
struct fence *flushed_updates;
- /* last use of vmid */
- struct amdgpu_fence *last_id_use;
};
struct amdgpu_vm {
@@ -1001,24 +954,70 @@ struct amdgpu_vm {
/* for id and flush management per ring */
struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS];
+ /* for interval tree */
+ spinlock_t it_lock;
};
struct amdgpu_vm_manager {
- struct amdgpu_fence *active[AMDGPU_NUM_VM];
- uint32_t max_pfn;
+ struct {
+ struct fence *active;
+ atomic_long_t owner;
+ } ids[AMDGPU_NUM_VM];
+
+ uint32_t max_pfn;
/* number of VMIDs */
- unsigned nvm;
+ unsigned nvm;
/* vram base address for page table entry */
- u64 vram_base_offset;
+ u64 vram_base_offset;
/* is vm enabled? */
- bool enabled;
- /* for hw to save the PD addr on suspend/resume */
- uint32_t saved_table_addr[AMDGPU_NUM_VM];
+ bool enabled;
/* vm pte handling */
const struct amdgpu_vm_pte_funcs *vm_pte_funcs;
struct amdgpu_ring *vm_pte_funcs_ring;
};
+void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm,
+ struct list_head *head);
+int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
+ struct amdgpu_sync *sync);
+void amdgpu_vm_flush(struct amdgpu_ring *ring,
+ struct amdgpu_vm *vm,
+ struct fence *updates);
+void amdgpu_vm_fence(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm,
+ struct fence *fence);
+uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
+int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm);
+int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm);
+int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct amdgpu_sync *sync);
+int amdgpu_vm_bo_update(struct amdgpu_device *adev,
+ struct amdgpu_bo_va *bo_va,
+ struct ttm_mem_reg *mem);
+void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
+ struct amdgpu_bo *bo);
+struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
+ struct amdgpu_bo *bo);
+struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm,
+ struct amdgpu_bo *bo);
+int amdgpu_vm_bo_map(struct amdgpu_device *adev,
+ struct amdgpu_bo_va *bo_va,
+ uint64_t addr, uint64_t offset,
+ uint64_t size, uint32_t flags);
+int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
+ struct amdgpu_bo_va *bo_va,
+ uint64_t addr);
+void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
+ struct amdgpu_bo_va *bo_va);
+int amdgpu_vm_free_job(struct amdgpu_job *job);
+
/*
* context related structures
*/
@@ -1223,8 +1222,6 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring);
void amdgpu_ring_unlock_commit(struct amdgpu_ring *ring);
void amdgpu_ring_undo(struct amdgpu_ring *ring);
void amdgpu_ring_unlock_undo(struct amdgpu_ring *ring);
-void amdgpu_ring_lockup_update(struct amdgpu_ring *ring);
-bool amdgpu_ring_test_lockup(struct amdgpu_ring *ring);
unsigned amdgpu_ring_backup(struct amdgpu_ring *ring,
uint32_t **data);
int amdgpu_ring_restore(struct amdgpu_ring *ring,
@@ -1234,6 +1231,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
struct amdgpu_irq_src *irq_src, unsigned irq_type,
enum amdgpu_ring_type ring_type);
void amdgpu_ring_fini(struct amdgpu_ring *ring);
+struct amdgpu_ring *amdgpu_ring_from_fence(struct fence *f);
/*
* CS.
@@ -1256,6 +1254,7 @@ struct amdgpu_cs_parser {
/* relocations */
struct amdgpu_bo_list_entry *vm_bos;
struct list_head validated;
+ struct fence *fence;
struct amdgpu_ib *ibs;
uint32_t num_ibs;
@@ -1271,7 +1270,7 @@ struct amdgpu_job {
struct amdgpu_device *adev;
struct amdgpu_ib *ibs;
uint32_t num_ibs;
- struct mutex job_lock;
+ void *owner;
struct amdgpu_user_fence uf;
int (*free_job)(struct amdgpu_job *job);
};
@@ -1654,6 +1653,7 @@ struct amdgpu_pm {
u8 fan_max_rpm;
/* dpm */
bool dpm_enabled;
+ bool sysfs_initialized;
struct amdgpu_dpm dpm;
const struct firmware *fw; /* SMC firmware */
uint32_t fw_version;
@@ -1708,7 +1708,7 @@ struct amdgpu_vce {
/*
* SDMA
*/
-struct amdgpu_sdma {
+struct amdgpu_sdma_instance {
/* SDMA firmware */
const struct firmware *fw;
uint32_t fw_version;
@@ -1718,6 +1718,13 @@ struct amdgpu_sdma {
bool burst_nop;
};
+struct amdgpu_sdma {
+ struct amdgpu_sdma_instance instance[AMDGPU_MAX_SDMA_INSTANCES];
+ struct amdgpu_irq_src trap_irq;
+ struct amdgpu_irq_src illegal_inst_irq;
+ int num_instances;
+};
+
/*
* Firmware
*/
@@ -1750,11 +1757,11 @@ void amdgpu_test_syncing(struct amdgpu_device *adev);
int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr);
void amdgpu_mn_unregister(struct amdgpu_bo *bo);
#else
-static int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
+static inline int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
{
return -ENODEV;
}
-static void amdgpu_mn_unregister(struct amdgpu_bo *bo) {}
+static inline void amdgpu_mn_unregister(struct amdgpu_bo *bo) {}
#endif
/*
@@ -1946,7 +1953,6 @@ struct amdgpu_device {
struct device *dev;
struct drm_device *ddev;
struct pci_dev *pdev;
- struct rw_semaphore exclusive_lock;
/* ASIC */
enum amd_asic_type asic_type;
@@ -1960,7 +1966,6 @@ struct amdgpu_device {
bool suspend;
bool need_dma32;
bool accel_working;
- bool needs_reset;
struct work_struct reset_work;
struct notifier_block acpi_nb;
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
@@ -2064,9 +2069,7 @@ struct amdgpu_device {
struct amdgpu_gfx gfx;
/* sdma */
- struct amdgpu_sdma sdma[AMDGPU_MAX_SDMA_INSTANCES];
- struct amdgpu_irq_src sdma_trap_irq;
- struct amdgpu_irq_src sdma_illegal_inst_irq;
+ struct amdgpu_sdma sdma;
/* uvd */
bool has_uvd;
@@ -2203,17 +2206,18 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
ring->ring_free_dw--;
}
-static inline struct amdgpu_sdma * amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
+static inline struct amdgpu_sdma_instance *
+amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
int i;
- for (i = 0; i < AMDGPU_MAX_SDMA_INSTANCES; i++)
- if (&adev->sdma[i].ring == ring)
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ if (&adev->sdma.instance[i].ring == ring)
break;
if (i < AMDGPU_MAX_SDMA_INSTANCES)
- return &adev->sdma[i];
+ return &adev->sdma.instance[i];
else
return NULL;
}
@@ -2240,7 +2244,6 @@ static inline struct amdgpu_sdma * amdgpu_get_sdma_instance(struct amdgpu_ring *
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
#define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r))
#define amdgpu_ring_test_ib(r) (r)->funcs->test_ib((r))
-#define amdgpu_ring_is_lockup(r) (r)->funcs->is_lockup((r))
#define amdgpu_ring_get_rptr(r) (r)->funcs->get_rptr((r))
#define amdgpu_ring_get_wptr(r) (r)->funcs->get_wptr((r))
#define amdgpu_ring_set_wptr(r) (r)->funcs->set_wptr((r))
@@ -2298,11 +2301,6 @@ void amdgpu_pci_config_reset(struct amdgpu_device *adev);
bool amdgpu_card_posted(struct amdgpu_device *adev);
void amdgpu_update_display_priority(struct amdgpu_device *adev);
bool amdgpu_boot_test_post_card(struct amdgpu_device *adev);
-struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
- struct drm_file *filp,
- struct amdgpu_ctx *ctx,
- struct amdgpu_ib *ibs,
- uint32_t num_ibs);
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
@@ -2349,10 +2347,10 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev,
struct drm_file *file_priv);
int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
-u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, int crtc);
-int amdgpu_enable_vblank_kms(struct drm_device *dev, int crtc);
-void amdgpu_disable_vblank_kms(struct drm_device *dev, int crtc);
-int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
+int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
+void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
+int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
int *max_error,
struct timeval *vblank_time,
unsigned flags);
@@ -2360,49 +2358,6 @@ long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
/*
- * vm
- */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
- struct list_head *head);
-int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
- struct amdgpu_sync *sync);
-void amdgpu_vm_flush(struct amdgpu_ring *ring,
- struct amdgpu_vm *vm,
- struct fence *updates);
-void amdgpu_vm_fence(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
- struct amdgpu_fence *fence);
-uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
-int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
- struct amdgpu_vm *vm);
-int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
- struct amdgpu_vm *vm);
-int amdgpu_vm_clear_invalids(struct amdgpu_device *adev,
- struct amdgpu_vm *vm, struct amdgpu_sync *sync);
-int amdgpu_vm_bo_update(struct amdgpu_device *adev,
- struct amdgpu_bo_va *bo_va,
- struct ttm_mem_reg *mem);
-void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
- struct amdgpu_bo *bo);
-struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
- struct amdgpu_bo *bo);
-struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
- struct amdgpu_bo *bo);
-int amdgpu_vm_bo_map(struct amdgpu_device *adev,
- struct amdgpu_bo_va *bo_va,
- uint64_t addr, uint64_t offset,
- uint64_t size, uint32_t flags);
-int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
- struct amdgpu_bo_va *bo_va,
- uint64_t addr);
-void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
- struct amdgpu_bo_va *bo_va);
-int amdgpu_vm_free_job(struct amdgpu_job *job);
-/*
* functions used by amdgpu_encoder.c
*/
struct amdgpu_afmt_acr {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index aef4a7aac0f7..a142d5ae148d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -25,7 +25,6 @@
#include <linux/acpi.h>
#include <linux/slab.h>
#include <linux/power_supply.h>
-#include <linux/vga_switcheroo.h>
#include <acpi/video.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
index dd2037bc0b4a..0e1376317683 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
@@ -649,12 +649,12 @@ static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
case KGD_ENGINE_SDMA1:
hdr = (const union amdgpu_firmware_header *)
- adev->sdma[0].fw->data;
+ adev->sdma.instance[0].fw->data;
break;
case KGD_ENGINE_SDMA2:
hdr = (const union amdgpu_firmware_header *)
- adev->sdma[1].fw->data;
+ adev->sdma.instance[1].fw->data;
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
index dfd1d503bccf..79fa5c7de856 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
@@ -523,12 +523,12 @@ static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
case KGD_ENGINE_SDMA1:
hdr = (const union amdgpu_firmware_header *)
- adev->sdma[0].fw->data;
+ adev->sdma.instance[0].fw->data;
break;
case KGD_ENGINE_SDMA2:
hdr = (const union amdgpu_firmware_header *)
- adev->sdma[1].fw->data;
+ adev->sdma.instance[1].fw->data;
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 77f1d7c6ea3a..9416e0f5c1db 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -672,8 +672,12 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)
/* disp clock */
adev->clock.default_dispclk =
le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
- if (adev->clock.default_dispclk == 0)
- adev->clock.default_dispclk = 54000; /* 540 Mhz */
+ /* set a reasonable default for DP */
+ if (adev->clock.default_dispclk < 53900) {
+ DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
+ adev->clock.default_dispclk / 100);
+ adev->clock.default_dispclk = 60000;
+ }
adev->clock.dp_extclk =
le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
adev->clock.current_dispclk = adev->clock.default_dispclk;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 3f7aaa45bf8e..5a8fbadbd27b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -501,7 +501,7 @@ static int amdgpu_atpx_get_client_id(struct pci_dev *pdev)
return VGA_SWITCHEROO_DIS;
}
-static struct vga_switcheroo_handler amdgpu_atpx_handler = {
+static const struct vga_switcheroo_handler amdgpu_atpx_handler = {
.switchto = amdgpu_atpx_switchto,
.power_state = amdgpu_atpx_power_state,
.init = amdgpu_atpx_init,
@@ -536,7 +536,7 @@ static bool amdgpu_atpx_detect(void)
if (has_atpx && vga_count == 2) {
acpi_get_name(amdgpu_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
- printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
+ printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n",
acpi_method_name);
amdgpu_atpx_priv.atpx_detected = true;
return true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 02add0a508cb..c44c0c6afd1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -29,7 +29,6 @@
#include "amdgpu.h"
#include "atom.h"
-#include <linux/vga_switcheroo.h>
#include <linux/slab.h>
#include <linux/acpi.h>
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index cb3c274edb0a..3afcf0237c25 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -104,10 +104,11 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
}
break;
case AMDGPU_HW_IP_DMA:
- if (ring < 2) {
- *out_ring = &adev->sdma[ring].ring;
+ if (ring < adev->sdma.num_instances) {
+ *out_ring = &adev->sdma.instance[ring].ring;
} else {
- DRM_ERROR("only two SDMA rings are supported\n");
+ DRM_ERROR("only %d SDMA rings are supported\n",
+ adev->sdma.num_instances);
return -EINVAL;
}
break;
@@ -126,30 +127,6 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
return 0;
}
-struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
- struct drm_file *filp,
- struct amdgpu_ctx *ctx,
- struct amdgpu_ib *ibs,
- uint32_t num_ibs)
-{
- struct amdgpu_cs_parser *parser;
- int i;
-
- parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL);
- if (!parser)
- return NULL;
-
- parser->adev = adev;
- parser->filp = filp;
- parser->ctx = ctx;
- parser->ibs = ibs;
- parser->num_ibs = num_ibs;
- for (i = 0; i < num_ibs; i++)
- ibs[i].ctx = ctx;
-
- return parser;
-}
-
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
{
union drm_amdgpu_cs *cs = data;
@@ -177,7 +154,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
/* get chunks */
INIT_LIST_HEAD(&p->validated);
- chunk_array_user = (uint64_t __user *)(cs->in.chunks);
+ chunk_array_user = (uint64_t __user *)(unsigned long)(cs->in.chunks);
if (copy_from_user(chunk_array, chunk_array_user,
sizeof(uint64_t)*cs->in.num_chunks)) {
ret = -EFAULT;
@@ -197,7 +174,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
struct drm_amdgpu_cs_chunk user_chunk;
uint32_t __user *cdata;
- chunk_ptr = (void __user *)chunk_array[i];
+ chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
if (copy_from_user(&user_chunk, chunk_ptr,
sizeof(struct drm_amdgpu_cs_chunk))) {
ret = -EFAULT;
@@ -208,7 +185,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
p->chunks[i].length_dw = user_chunk.length_dw;
size = p->chunks[i].length_dw;
- cdata = (void __user *)user_chunk.chunk_data;
+ cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
p->chunks[i].user_ptr = cdata;
p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
@@ -462,8 +439,18 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,
return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
}
-static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff)
+/**
+ * cs_parser_fini() - clean parser states
+ * @parser: parser structure holding parsing context.
+ * @error: error number
+ *
+ * If error is set than unvalidate buffer, otherwise just free memory
+ * used by parsing context.
+ **/
+static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
{
+ unsigned i;
+
if (!error) {
/* Sort the buffer list from the smallest to largest buffer,
* which affects the order of buffers in the LRU list.
@@ -478,17 +465,14 @@ static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int err
list_sort(NULL, &parser->validated, cmp_size_smaller_first);
ttm_eu_fence_buffer_objects(&parser->ticket,
- &parser->validated,
- &parser->ibs[parser->num_ibs-1].fence->base);
+ &parser->validated,
+ parser->fence);
} else if (backoff) {
ttm_eu_backoff_reservation(&parser->ticket,
&parser->validated);
}
-}
+ fence_put(parser->fence);
-static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
-{
- unsigned i;
if (parser->ctx)
amdgpu_ctx_put(parser->ctx);
if (parser->bo_list)
@@ -498,31 +482,12 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
for (i = 0; i < parser->nchunks; i++)
drm_free_large(parser->chunks[i].kdata);
kfree(parser->chunks);
- if (!amdgpu_enable_scheduler)
- {
- if (parser->ibs)
- for (i = 0; i < parser->num_ibs; i++)
- amdgpu_ib_free(parser->adev, &parser->ibs[i]);
- kfree(parser->ibs);
- if (parser->uf.bo)
- drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
- }
-
- kfree(parser);
-}
-
-/**
- * cs_parser_fini() - clean parser states
- * @parser: parser structure holding parsing context.
- * @error: error number
- *
- * If error is set than unvalidate buffer, otherwise just free memory
- * used by parsing context.
- **/
-static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
-{
- amdgpu_cs_parser_fini_early(parser, error, backoff);
- amdgpu_cs_parser_fini_late(parser);
+ if (parser->ibs)
+ for (i = 0; i < parser->num_ibs; i++)
+ amdgpu_ib_free(parser->adev, &parser->ibs[i]);
+ kfree(parser->ibs);
+ if (parser->uf.bo)
+ drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
}
static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
@@ -567,9 +532,24 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
if (r)
return r;
}
+
}
- return amdgpu_vm_clear_invalids(adev, vm, &p->ibs[0].sync);
+ r = amdgpu_vm_clear_invalids(adev, vm, &p->ibs[0].sync);
+
+ if (amdgpu_vm_debug && p->bo_list) {
+ /* Invalidate all BOs to test for userspace bugs */
+ for (i = 0; i < p->bo_list->num_entries; i++) {
+ /* ignore duplicates */
+ bo = p->bo_list->array[i].robj;
+ if (!bo)
+ continue;
+
+ amdgpu_vm_bo_invalidate(adev, bo);
+ }
+ }
+
+ return r;
}
static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
@@ -593,18 +573,10 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
}
}
- mutex_lock(&vm->mutex);
r = amdgpu_bo_vm_update_pte(parser, vm);
- if (r) {
- goto out;
- }
- amdgpu_cs_sync_rings(parser);
- if (!amdgpu_enable_scheduler)
- r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs,
- parser->filp);
+ if (!r)
+ amdgpu_cs_sync_rings(parser);
-out:
- mutex_unlock(&vm->mutex);
return r;
}
@@ -812,40 +784,38 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{
struct amdgpu_device *adev = dev->dev_private;
union drm_amdgpu_cs *cs = data;
- struct amdgpu_cs_parser *parser;
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_vm *vm = &fpriv->vm;
+ struct amdgpu_cs_parser parser = {};
bool reserved_buffers = false;
int i, r;
- down_read(&adev->exclusive_lock);
- if (!adev->accel_working) {
- up_read(&adev->exclusive_lock);
+ if (!adev->accel_working)
return -EBUSY;
- }
- parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
- if (!parser)
- return -ENOMEM;
- r = amdgpu_cs_parser_init(parser, data);
+ parser.adev = adev;
+ parser.filp = filp;
+
+ r = amdgpu_cs_parser_init(&parser, data);
if (r) {
DRM_ERROR("Failed to initialize parser !\n");
- kfree(parser);
- up_read(&adev->exclusive_lock);
+ amdgpu_cs_parser_fini(&parser, r, false);
r = amdgpu_cs_handle_lockup(adev, r);
return r;
}
-
- r = amdgpu_cs_parser_relocs(parser);
+ mutex_lock(&vm->mutex);
+ r = amdgpu_cs_parser_relocs(&parser);
if (r == -ENOMEM)
DRM_ERROR("Not enough memory for command submission!\n");
else if (r && r != -ERESTARTSYS)
DRM_ERROR("Failed to process the buffer list %d!\n", r);
else if (!r) {
reserved_buffers = true;
- r = amdgpu_cs_ib_fill(adev, parser);
+ r = amdgpu_cs_ib_fill(adev, &parser);
}
if (!r) {
- r = amdgpu_cs_dependencies(adev, parser);
+ r = amdgpu_cs_dependencies(adev, &parser);
if (r)
DRM_ERROR("Failed in the dependencies handling %d!\n", r);
}
@@ -853,61 +823,72 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
if (r)
goto out;
- for (i = 0; i < parser->num_ibs; i++)
- trace_amdgpu_cs(parser, i);
+ for (i = 0; i < parser.num_ibs; i++)
+ trace_amdgpu_cs(&parser, i);
- r = amdgpu_cs_ib_vm_chunk(adev, parser);
+ r = amdgpu_cs_ib_vm_chunk(adev, &parser);
if (r)
goto out;
- if (amdgpu_enable_scheduler && parser->num_ibs) {
+ if (amdgpu_enable_scheduler && parser.num_ibs) {
+ struct amdgpu_ring * ring = parser.ibs->ring;
+ struct amd_sched_fence *fence;
struct amdgpu_job *job;
- struct amdgpu_ring * ring = parser->ibs->ring;
+
job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
- if (!job)
- return -ENOMEM;
+ if (!job) {
+ r = -ENOMEM;
+ goto out;
+ }
+
job->base.sched = &ring->sched;
- job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
- job->adev = parser->adev;
- job->ibs = parser->ibs;
- job->num_ibs = parser->num_ibs;
- job->base.owner = parser->filp;
- mutex_init(&job->job_lock);
+ job->base.s_entity = &parser.ctx->rings[ring->idx].entity;
+ job->adev = parser.adev;
+ job->owner = parser.filp;
+ job->free_job = amdgpu_cs_free_job;
+
+ job->ibs = parser.ibs;
+ job->num_ibs = parser.num_ibs;
+ parser.ibs = NULL;
+ parser.num_ibs = 0;
+
if (job->ibs[job->num_ibs - 1].user) {
- memcpy(&job->uf, &parser->uf,
- sizeof(struct amdgpu_user_fence));
+ job->uf = parser.uf;
job->ibs[job->num_ibs - 1].user = &job->uf;
+ parser.uf.bo = NULL;
}
- job->free_job = amdgpu_cs_free_job;
- mutex_lock(&job->job_lock);
- r = amd_sched_entity_push_job(&job->base);
- if (r) {
- mutex_unlock(&job->job_lock);
+ fence = amd_sched_fence_create(job->base.s_entity,
+ parser.filp);
+ if (!fence) {
+ r = -ENOMEM;
amdgpu_cs_free_job(job);
kfree(job);
goto out;
}
- cs->out.handle =
- amdgpu_ctx_add_fence(parser->ctx, ring,
- &job->base.s_fence->base);
- parser->ibs[parser->num_ibs - 1].sequence = cs->out.handle;
+ job->base.s_fence = fence;
+ parser.fence = fence_get(&fence->base);
- list_sort(NULL, &parser->validated, cmp_size_smaller_first);
- ttm_eu_fence_buffer_objects(&parser->ticket,
- &parser->validated,
- &job->base.s_fence->base);
+ cs->out.handle = amdgpu_ctx_add_fence(parser.ctx, ring,
+ &fence->base);
+ job->ibs[job->num_ibs - 1].sequence = cs->out.handle;
- mutex_unlock(&job->job_lock);
- amdgpu_cs_parser_fini_late(parser);
- up_read(&adev->exclusive_lock);
- return 0;
+ trace_amdgpu_cs_ioctl(job);
+ amd_sched_entity_push_job(&job->base);
+
+ } else {
+ struct amdgpu_fence *fence;
+
+ r = amdgpu_ib_schedule(adev, parser.num_ibs, parser.ibs,
+ parser.filp);
+ fence = parser.ibs[parser.num_ibs - 1].fence;
+ parser.fence = fence_get(&fence->base);
+ cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;
}
- cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
out:
- amdgpu_cs_parser_fini(parser, r, reserved_buffers);
- up_read(&adev->exclusive_lock);
+ amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
+ mutex_unlock(&vm->mutex);
r = amdgpu_cs_handle_lockup(adev, r);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index e0b80ccdfe8a..fec65f01c031 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -69,6 +69,9 @@ void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
struct amdgpu_device *adev = ctx->adev;
unsigned i, j;
+ if (!adev)
+ return;
+
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j)
fence_put(ctx->rings[i].fences[j]);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 6068d8207d10..d5b421330145 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -57,6 +57,7 @@ static const char *amdgpu_asic_name[] = {
"TONGA",
"FIJI",
"CARRIZO",
+ "STONEY",
"LAST",
};
@@ -1022,7 +1023,7 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev)
* amdgpu_switcheroo_set_state - set switcheroo state
*
* @pdev: pci dev pointer
- * @state: vga switcheroo state
+ * @state: vga_switcheroo state
*
* Callback for the switcheroo driver. Suspends or resumes the
* the asics before or after it is powered up using ACPI methods.
@@ -1165,7 +1166,8 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
case CHIP_TONGA:
case CHIP_FIJI:
case CHIP_CARRIZO:
- if (adev->asic_type == CHIP_CARRIZO)
+ case CHIP_STONEY:
+ if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
adev->family = AMDGPU_FAMILY_CZ;
else
adev->family = AMDGPU_FAMILY_VI;
@@ -1418,7 +1420,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
mutex_init(&adev->gfx.gpu_clock_mutex);
mutex_init(&adev->srbm_mutex);
mutex_init(&adev->grbm_idx_mutex);
- init_rwsem(&adev->exclusive_lock);
mutex_init(&adev->mn_lock);
hash_init(adev->mn_hash);
@@ -1657,11 +1658,21 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
}
drm_modeset_unlock_all(dev);
- /* unpin the front buffers */
+ /* unpin the front buffers and cursors */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct amdgpu_framebuffer *rfb = to_amdgpu_framebuffer(crtc->primary->fb);
struct amdgpu_bo *robj;
+ if (amdgpu_crtc->cursor_bo) {
+ struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+ r = amdgpu_bo_reserve(aobj, false);
+ if (r == 0) {
+ amdgpu_bo_unpin(aobj);
+ amdgpu_bo_unreserve(aobj);
+ }
+ }
+
if (rfb == NULL || rfb->obj == NULL) {
continue;
}
@@ -1713,6 +1724,7 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
{
struct drm_connector *connector;
struct amdgpu_device *adev = dev->dev_private;
+ struct drm_crtc *crtc;
int r;
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
@@ -1746,6 +1758,24 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
if (r)
return r;
+ /* pin cursors */
+ 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) {
+ struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+ r = amdgpu_bo_reserve(aobj, false);
+ if (r == 0) {
+ r = amdgpu_bo_pin(aobj,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &amdgpu_crtc->cursor_addr);
+ if (r != 0)
+ DRM_ERROR("Failed to pin cursor BO (%d)\n", r);
+ amdgpu_bo_unreserve(aobj);
+ }
+ }
+ }
+
/* blat the mode back in */
if (fbcon) {
drm_helper_resume_force_mode(dev);
@@ -1785,14 +1815,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
int i, r;
int resched;
- down_write(&adev->exclusive_lock);
-
- if (!adev->needs_reset) {
- up_write(&adev->exclusive_lock);
- return 0;
- }
-
- adev->needs_reset = false;
atomic_inc(&adev->gpu_reset_counter);
/* block TTM */
@@ -1856,7 +1878,6 @@ retry:
dev_info(adev->dev, "GPU reset failed\n");
}
- up_write(&adev->exclusive_lock);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index e3d70772b531..e173a5a02f0d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -47,11 +47,8 @@ static void amdgpu_flip_wait_fence(struct amdgpu_device *adev,
fence = to_amdgpu_fence(*f);
if (fence) {
r = fence_wait(&fence->base, false);
- if (r == -EDEADLK) {
- up_read(&adev->exclusive_lock);
+ if (r == -EDEADLK)
r = amdgpu_gpu_reset(adev);
- down_read(&adev->exclusive_lock);
- }
} else
r = fence_wait(*f, false);
@@ -77,7 +74,6 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
unsigned long flags;
unsigned i;
- down_read(&adev->exclusive_lock);
amdgpu_flip_wait_fence(adev, &work->excl);
for (i = 0; i < work->shared_count; ++i)
amdgpu_flip_wait_fence(adev, &work->shared[i]);
@@ -85,15 +81,12 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
/* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
- /* set the proper interrupt */
- amdgpu_irq_get(adev, &adev->pageflip_irq, work->crtc_id);
/* do the flip (mmio) */
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
/* set the flip status */
amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
- up_read(&adev->exclusive_lock);
}
/*
@@ -186,10 +179,6 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup;
}
- fence_get(work->excl);
- for (i = 0; i < work->shared_count; ++i)
- fence_get(work->shared[i]);
-
amdgpu_bo_get_tiling_flags(new_rbo, &tiling_flags);
amdgpu_bo_unreserve(new_rbo);
@@ -721,7 +710,7 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
* an optional accurate timestamp of when query happened.
*
* \param dev Device to query.
- * \param crtc Crtc to query.
+ * \param pipe Crtc to query.
* \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
* \param *vpos Location where vertical scanout position should be stored.
* \param *hpos Location where horizontal scanout position should go.
@@ -744,8 +733,10 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
* unknown small number of scanlines wrt. real scanout position.
*
*/
-int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
- int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+ unsigned int flags, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode)
{
u32 vbl = 0, position = 0;
int vbl_start, vbl_end, vtotal, ret = 0;
@@ -759,7 +750,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
if (stime)
*stime = ktime_get();
- if (amdgpu_display_page_flip_get_scanoutpos(adev, crtc, &vbl, &position) == 0)
+ if (amdgpu_display_page_flip_get_scanoutpos(adev, pipe, &vbl, &position) == 0)
ret |= DRM_SCANOUTPOS_VALID;
/* Get optional system timestamp after query. */
@@ -781,7 +772,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
}
else {
/* No: Fake something reasonable which gives at least ok results. */
- vbl_start = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
+ vbl_start = mode->crtc_vdisplay;
vbl_end = 0;
}
@@ -797,7 +788,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
/* Inside "upper part" of vblank area? Apply corrective offset if so: */
if (in_vbl && (*vpos >= vbl_start)) {
- vtotal = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+ vtotal = mode->crtc_vtotal;
*vpos = *vpos - vtotal;
}
@@ -819,8 +810,8 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
- vbl_start = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
- vtotal = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+ vbl_start = mode->crtc_vdisplay;
+ vtotal = mode->crtc_vtotal;
if (vbl_start - *vpos < vtotal / 100) {
*vpos -= vtotal;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index adb48353f2e1..0508c5cd103a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -73,13 +73,15 @@ int amdgpu_hard_reset = 0;
unsigned amdgpu_ip_block_mask = 0xffffffff;
int amdgpu_bapm = -1;
int amdgpu_deep_color = 0;
-int amdgpu_vm_size = 8;
+int amdgpu_vm_size = 64;
int amdgpu_vm_block_size = -1;
+int amdgpu_vm_fault_stop = 0;
+int amdgpu_vm_debug = 0;
int amdgpu_exp_hw_support = 0;
-int amdgpu_enable_scheduler = 0;
+int amdgpu_enable_scheduler = 1;
int amdgpu_sched_jobs = 16;
int amdgpu_sched_hw_submission = 2;
-int amdgpu_enable_semaphores = 1;
+int amdgpu_enable_semaphores = 0;
MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -135,16 +137,22 @@ module_param_named(bapm, amdgpu_bapm, int, 0444);
MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))");
module_param_named(deep_color, amdgpu_deep_color, int, 0444);
-MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 8GB)");
+MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 64GB)");
module_param_named(vm_size, amdgpu_vm_size, int, 0444);
MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default depending on vm_size)");
module_param_named(vm_block_size, amdgpu_vm_block_size, int, 0444);
+MODULE_PARM_DESC(vm_fault_stop, "Stop on VM fault (0 = never (default), 1 = print first, 2 = always)");
+module_param_named(vm_fault_stop, amdgpu_vm_fault_stop, int, 0444);
+
+MODULE_PARM_DESC(vm_debug, "Debug VM handling (0 = disabled (default), 1 = enabled)");
+module_param_named(vm_debug, amdgpu_vm_debug, int, 0644);
+
MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))");
module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444);
-MODULE_PARM_DESC(enable_scheduler, "enable SW GPU scheduler (1 = enable, 0 = disable ((default))");
+MODULE_PARM_DESC(enable_scheduler, "enable SW GPU scheduler (1 = enable (default), 0 = disable)");
module_param_named(enable_scheduler, amdgpu_enable_scheduler, int, 0444);
MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 16)");
@@ -153,7 +161,7 @@ module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444);
MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)");
module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444);
-MODULE_PARM_DESC(enable_semaphores, "Enable semaphores (1 = enable (default), 0 = disable)");
+MODULE_PARM_DESC(enable_semaphores, "Enable semaphores (1 = enable, 0 = disable (default))");
module_param_named(enable_semaphores, amdgpu_enable_semaphores, int, 0644);
static struct pci_device_id pciidlist[] = {
@@ -242,11 +250,11 @@ static struct pci_device_id pciidlist[] = {
{0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
#endif
/* topaz */
- {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
+ {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
/* tonga */
{0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
@@ -265,6 +273,8 @@ static struct pci_device_id pciidlist[] = {
{0x1002, 0x9875, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9876, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9877, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
+ /* stoney */
+ {0x1002, 0x98E4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_STONEY|AMD_IS_APU},
{0, 0, 0}
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 8a122b1b7786..093a8c618931 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -207,6 +207,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
}
info->par = rfbdev;
+ info->skip_vt_switch = true;
ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
if (ret) {
@@ -402,3 +403,19 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
return true;
return false;
}
+
+void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev)
+{
+ struct amdgpu_fbdev *afbdev = adev->mode_info.rfbdev;
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ if (!afbdev)
+ return;
+
+ fb_helper = &afbdev->helper;
+
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+ if (ret)
+ DRM_DEBUG("failed to restore crtc mode\n");
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index b3fc26c59787..3671f9f220bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -47,6 +47,9 @@
* that the the relevant GPU caches have been flushed.
*/
+static struct kmem_cache *amdgpu_fence_slab;
+static atomic_t amdgpu_fence_slab_ref = ATOMIC_INIT(0);
+
/**
* amdgpu_fence_write - write a fence value
*
@@ -85,24 +88,6 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
}
/**
- * amdgpu_fence_schedule_check - schedule lockup check
- *
- * @ring: pointer to struct amdgpu_ring
- *
- * Queues a delayed work item to check for lockups.
- */
-static void amdgpu_fence_schedule_check(struct amdgpu_ring *ring)
-{
- /*
- * Do not reset the timer here with mod_delayed_work,
- * this can livelock in an interaction with TTM delayed destroy.
- */
- queue_delayed_work(system_power_efficient_wq,
- &ring->fence_drv.lockup_work,
- AMDGPU_FENCE_JIFFIES_TIMEOUT);
-}
-
-/**
* amdgpu_fence_emit - emit a fence on the requested ring
*
* @ring: ring the fence is associated with
@@ -118,7 +103,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
struct amdgpu_device *adev = ring->adev;
/* we are protected by the ring emission mutex */
- *fence = kmalloc(sizeof(struct amdgpu_fence), GFP_KERNEL);
+ *fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
if ((*fence) == NULL) {
return -ENOMEM;
}
@@ -132,44 +117,20 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
(*fence)->seq,
AMDGPU_FENCE_FLAG_INT);
- trace_amdgpu_fence_emit(ring->adev->ddev, ring->idx, (*fence)->seq);
return 0;
}
/**
- * amdgpu_fence_check_signaled - callback from fence_queue
+ * amdgpu_fence_schedule_fallback - schedule fallback check
*
- * this function is called with fence_queue lock held, which is also used
- * for the fence locking itself, so unlocked variants are used for
- * fence_signal, and remove_wait_queue.
+ * @ring: pointer to struct amdgpu_ring
+ *
+ * Start a timer as fallback to our interrupts.
*/
-static int amdgpu_fence_check_signaled(wait_queue_t *wait, unsigned mode, int flags, void *key)
+static void amdgpu_fence_schedule_fallback(struct amdgpu_ring *ring)
{
- struct amdgpu_fence *fence;
- struct amdgpu_device *adev;
- u64 seq;
- int ret;
-
- fence = container_of(wait, struct amdgpu_fence, fence_wake);
- adev = fence->ring->adev;
-
- /*
- * We cannot use amdgpu_fence_process here because we're already
- * in the waitqueue, in a call from wake_up_all.
- */
- seq = atomic64_read(&fence->ring->fence_drv.last_seq);
- if (seq >= fence->seq) {
- ret = fence_signal_locked(&fence->base);
- if (!ret)
- FENCE_TRACE(&fence->base, "signaled from irq context\n");
- else
- FENCE_TRACE(&fence->base, "was already signaled\n");
-
- __remove_wait_queue(&fence->ring->fence_drv.fence_queue, &fence->fence_wake);
- fence_put(&fence->base);
- } else
- FENCE_TRACE(&fence->base, "pending\n");
- return 0;
+ mod_timer(&ring->fence_drv.fallback_timer,
+ jiffies + AMDGPU_FENCE_JIFFIES_TIMEOUT);
}
/**
@@ -238,52 +199,12 @@ static bool amdgpu_fence_activity(struct amdgpu_ring *ring)
} while (atomic64_xchg(&ring->fence_drv.last_seq, seq) > seq);
if (seq < last_emitted)
- amdgpu_fence_schedule_check(ring);
+ amdgpu_fence_schedule_fallback(ring);
return wake;
}
/**
- * amdgpu_fence_check_lockup - check for hardware lockup
- *
- * @work: delayed work item
- *
- * Checks for fence activity and if there is none probe
- * the hardware if a lockup occured.
- */
-static void amdgpu_fence_check_lockup(struct work_struct *work)
-{
- struct amdgpu_fence_driver *fence_drv;
- struct amdgpu_ring *ring;
-
- fence_drv = container_of(work, struct amdgpu_fence_driver,
- lockup_work.work);
- ring = fence_drv->ring;
-
- if (!down_read_trylock(&ring->adev->exclusive_lock)) {
- /* just reschedule the check if a reset is going on */
- amdgpu_fence_schedule_check(ring);
- return;
- }
-
- if (amdgpu_fence_activity(ring)) {
- wake_up_all(&ring->fence_drv.fence_queue);
- }
- else if (amdgpu_ring_is_lockup(ring)) {
- /* good news we believe it's a lockup */
- dev_warn(ring->adev->dev, "GPU lockup (current fence id "
- "0x%016llx last fence id 0x%016llx on ring %d)\n",
- (uint64_t)atomic64_read(&fence_drv->last_seq),
- fence_drv->sync_seq[ring->idx], ring->idx);
-
- /* remember that we need an reset */
- ring->adev->needs_reset = true;
- wake_up_all(&ring->fence_drv.fence_queue);
- }
- up_read(&ring->adev->exclusive_lock);
-}
-
-/**
* amdgpu_fence_process - process a fence
*
* @adev: amdgpu_device pointer
@@ -299,6 +220,20 @@ void amdgpu_fence_process(struct amdgpu_ring *ring)
}
/**
+ * amdgpu_fence_fallback - fallback for hardware interrupts
+ *
+ * @work: delayed work item
+ *
+ * Checks for fence activity.
+ */
+static void amdgpu_fence_fallback(unsigned long arg)
+{
+ struct amdgpu_ring *ring = (void *)arg;
+
+ amdgpu_fence_process(ring);
+}
+
+/**
* amdgpu_fence_seq_signaled - check if a fence sequence number has signaled
*
* @ring: ring the fence is associated with
@@ -324,50 +259,6 @@ static bool amdgpu_fence_seq_signaled(struct amdgpu_ring *ring, u64 seq)
return false;
}
-static bool amdgpu_fence_is_signaled(struct fence *f)
-{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- struct amdgpu_ring *ring = fence->ring;
- struct amdgpu_device *adev = ring->adev;
-
- if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
- return true;
-
- if (down_read_trylock(&adev->exclusive_lock)) {
- amdgpu_fence_process(ring);
- up_read(&adev->exclusive_lock);
-
- if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
- return true;
- }
- return false;
-}
-
-/**
- * amdgpu_fence_enable_signaling - enable signalling on fence
- * @fence: fence
- *
- * This function is called with fence_queue lock held, and adds a callback
- * to fence_queue that checks if this fence is signaled, and if so it
- * signals the fence and removes itself.
- */
-static bool amdgpu_fence_enable_signaling(struct fence *f)
-{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- struct amdgpu_ring *ring = fence->ring;
-
- if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
- return false;
-
- fence->fence_wake.flags = 0;
- fence->fence_wake.private = NULL;
- fence->fence_wake.func = amdgpu_fence_check_signaled;
- __add_wait_queue(&ring->fence_drv.fence_queue, &fence->fence_wake);
- fence_get(f);
- FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
- return true;
-}
-
/*
* amdgpu_ring_wait_seq_timeout - wait for seq of the specific ring to signal
* @ring: ring to wait on for the seq number
@@ -380,7 +271,6 @@ static bool amdgpu_fence_enable_signaling(struct fence *f)
*/
static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
{
- struct amdgpu_device *adev = ring->adev;
bool signaled = false;
BUG_ON(!ring);
@@ -390,9 +280,9 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
if (atomic64_read(&ring->fence_drv.last_seq) >= seq)
return 0;
+ amdgpu_fence_schedule_fallback(ring);
wait_event(ring->fence_drv.fence_queue, (
- (signaled = amdgpu_fence_seq_signaled(ring, seq))
- || adev->needs_reset));
+ (signaled = amdgpu_fence_seq_signaled(ring, seq))));
if (signaled)
return 0;
@@ -441,36 +331,6 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring)
}
/**
- * amdgpu_fence_ref - take a ref on a fence
- *
- * @fence: amdgpu fence object
- *
- * Take a reference on a fence (all asics).
- * Returns the fence.
- */
-struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence)
-{
- fence_get(&fence->base);
- return fence;
-}
-
-/**
- * amdgpu_fence_unref - remove a ref on a fence
- *
- * @fence: amdgpu fence object
- *
- * Remove a reference on a fence (all asics).
- */
-void amdgpu_fence_unref(struct amdgpu_fence **fence)
-{
- struct amdgpu_fence *tmp = *fence;
-
- *fence = NULL;
- if (tmp)
- fence_put(&tmp->base);
-}
-
-/**
* amdgpu_fence_count_emitted - get the count of emitted fences
*
* @ring: ring the fence is associated with
@@ -621,15 +481,26 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
atomic64_set(&ring->fence_drv.last_seq, 0);
ring->fence_drv.initialized = false;
- INIT_DELAYED_WORK(&ring->fence_drv.lockup_work,
- amdgpu_fence_check_lockup);
- ring->fence_drv.ring = ring;
+ setup_timer(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback,
+ (unsigned long)ring);
init_waitqueue_head(&ring->fence_drv.fence_queue);
if (amdgpu_enable_scheduler) {
+ long timeout = msecs_to_jiffies(amdgpu_lockup_timeout);
+ if (timeout == 0) {
+ /*
+ * FIXME:
+ * Delayed workqueue cannot use it directly,
+ * so the scheduler will not use delayed workqueue if
+ * MAX_SCHEDULE_TIMEOUT is set.
+ * Currently keep it simple and silly.
+ */
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ }
r = amd_sched_init(&ring->sched, &amdgpu_sched_ops,
- amdgpu_sched_hw_submission, ring->name);
+ amdgpu_sched_hw_submission,
+ timeout, ring->name);
if (r) {
DRM_ERROR("Failed to create scheduler on ring %s.\n",
ring->name);
@@ -654,6 +525,13 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
*/
int amdgpu_fence_driver_init(struct amdgpu_device *adev)
{
+ if (atomic_inc_return(&amdgpu_fence_slab_ref) == 1) {
+ amdgpu_fence_slab = kmem_cache_create(
+ "amdgpu_fence", sizeof(struct amdgpu_fence), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!amdgpu_fence_slab)
+ return -ENOMEM;
+ }
if (amdgpu_debugfs_fence_init(adev))
dev_err(adev->dev, "fence debugfs file creation failed\n");
@@ -672,9 +550,12 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
{
int i, r;
+ if (atomic_dec_and_test(&amdgpu_fence_slab_ref))
+ kmem_cache_destroy(amdgpu_fence_slab);
mutex_lock(&adev->ring_lock);
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
struct amdgpu_ring *ring = adev->rings[i];
+
if (!ring || !ring->fence_drv.initialized)
continue;
r = amdgpu_fence_wait_empty(ring);
@@ -686,6 +567,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
ring->fence_drv.irq_type);
amd_sched_fini(&ring->sched);
+ del_timer_sync(&ring->fence_drv.fallback_timer);
ring->fence_drv.initialized = false;
}
mutex_unlock(&adev->ring_lock);
@@ -773,6 +655,122 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev)
}
}
+/*
+ * Common fence implementation
+ */
+
+static const char *amdgpu_fence_get_driver_name(struct fence *fence)
+{
+ return "amdgpu";
+}
+
+static const char *amdgpu_fence_get_timeline_name(struct fence *f)
+{
+ struct amdgpu_fence *fence = to_amdgpu_fence(f);
+ return (const char *)fence->ring->name;
+}
+
+/**
+ * amdgpu_fence_is_signaled - test if fence is signaled
+ *
+ * @f: fence to test
+ *
+ * Test the fence sequence number if it is already signaled. If it isn't
+ * signaled start fence processing. Returns True if the fence is signaled.
+ */
+static bool amdgpu_fence_is_signaled(struct fence *f)
+{
+ struct amdgpu_fence *fence = to_amdgpu_fence(f);
+ struct amdgpu_ring *ring = fence->ring;
+
+ if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
+ return true;
+
+ amdgpu_fence_process(ring);
+
+ if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
+ return true;
+
+ return false;
+}
+
+/**
+ * amdgpu_fence_check_signaled - callback from fence_queue
+ *
+ * this function is called with fence_queue lock held, which is also used
+ * for the fence locking itself, so unlocked variants are used for
+ * fence_signal, and remove_wait_queue.
+ */
+static int amdgpu_fence_check_signaled(wait_queue_t *wait, unsigned mode, int flags, void *key)
+{
+ struct amdgpu_fence *fence;
+ struct amdgpu_device *adev;
+ u64 seq;
+ int ret;
+
+ fence = container_of(wait, struct amdgpu_fence, fence_wake);
+ adev = fence->ring->adev;
+
+ /*
+ * We cannot use amdgpu_fence_process here because we're already
+ * in the waitqueue, in a call from wake_up_all.
+ */
+ seq = atomic64_read(&fence->ring->fence_drv.last_seq);
+ if (seq >= fence->seq) {
+ ret = fence_signal_locked(&fence->base);
+ if (!ret)
+ FENCE_TRACE(&fence->base, "signaled from irq context\n");
+ else
+ FENCE_TRACE(&fence->base, "was already signaled\n");
+
+ __remove_wait_queue(&fence->ring->fence_drv.fence_queue, &fence->fence_wake);
+ fence_put(&fence->base);
+ } else
+ FENCE_TRACE(&fence->base, "pending\n");
+ return 0;
+}
+
+/**
+ * amdgpu_fence_enable_signaling - enable signalling on fence
+ * @fence: fence
+ *
+ * This function is called with fence_queue lock held, and adds a callback
+ * to fence_queue that checks if this fence is signaled, and if so it
+ * signals the fence and removes itself.
+ */
+static bool amdgpu_fence_enable_signaling(struct fence *f)
+{
+ struct amdgpu_fence *fence = to_amdgpu_fence(f);
+ struct amdgpu_ring *ring = fence->ring;
+
+ if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
+ return false;
+
+ fence->fence_wake.flags = 0;
+ fence->fence_wake.private = NULL;
+ fence->fence_wake.func = amdgpu_fence_check_signaled;
+ __add_wait_queue(&ring->fence_drv.fence_queue, &fence->fence_wake);
+ fence_get(f);
+ if (!timer_pending(&ring->fence_drv.fallback_timer))
+ amdgpu_fence_schedule_fallback(ring);
+ FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
+ return true;
+}
+
+static void amdgpu_fence_release(struct fence *f)
+{
+ struct amdgpu_fence *fence = to_amdgpu_fence(f);
+ kmem_cache_free(amdgpu_fence_slab, fence);
+}
+
+const struct fence_ops amdgpu_fence_ops = {
+ .get_driver_name = amdgpu_fence_get_driver_name,
+ .get_timeline_name = amdgpu_fence_get_timeline_name,
+ .enable_signaling = amdgpu_fence_enable_signaling,
+ .signaled = amdgpu_fence_is_signaled,
+ .wait = fence_default_wait,
+ .release = amdgpu_fence_release,
+};
/*
* Fence debugfs
@@ -823,141 +821,3 @@ int amdgpu_debugfs_fence_init(struct amdgpu_device *adev)
#endif
}
-static const char *amdgpu_fence_get_driver_name(struct fence *fence)
-{
- return "amdgpu";
-}
-
-static const char *amdgpu_fence_get_timeline_name(struct fence *f)
-{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- return (const char *)fence->ring->name;
-}
-
-static inline bool amdgpu_test_signaled(struct amdgpu_fence *fence)
-{
- return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
-}
-
-static bool amdgpu_test_signaled_any(struct fence **fences, uint32_t count)
-{
- int idx;
- struct fence *fence;
-
- for (idx = 0; idx < count; ++idx) {
- fence = fences[idx];
- if (fence) {
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
- return true;
- }
- }
- return false;
-}
-
-struct amdgpu_wait_cb {
- struct fence_cb base;
- struct task_struct *task;
-};
-
-static void amdgpu_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
-{
- struct amdgpu_wait_cb *wait =
- container_of(cb, struct amdgpu_wait_cb, base);
- wake_up_process(wait->task);
-}
-
-static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
- signed long t)
-{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- struct amdgpu_device *adev = fence->ring->adev;
-
- return amdgpu_fence_wait_any(adev, &f, 1, intr, t);
-}
-
-/**
- * Wait the fence array with timeout
- *
- * @adev: amdgpu device
- * @array: the fence array with amdgpu fence pointer
- * @count: the number of the fence array
- * @intr: when sleep, set the current task interruptable or not
- * @t: timeout to wait
- *
- * It will return when any fence is signaled or timeout.
- */
-signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
- struct fence **array, uint32_t count,
- bool intr, signed long t)
-{
- struct amdgpu_wait_cb *cb;
- struct fence *fence;
- unsigned idx;
-
- BUG_ON(!array);
-
- cb = kcalloc(count, sizeof(struct amdgpu_wait_cb), GFP_KERNEL);
- if (cb == NULL) {
- t = -ENOMEM;
- goto err_free_cb;
- }
-
- for (idx = 0; idx < count; ++idx) {
- fence = array[idx];
- if (fence) {
- cb[idx].task = current;
- if (fence_add_callback(fence,
- &cb[idx].base, amdgpu_fence_wait_cb)) {
- /* The fence is already signaled */
- goto fence_rm_cb;
- }
- }
- }
-
- while (t > 0) {
- if (intr)
- set_current_state(TASK_INTERRUPTIBLE);
- else
- set_current_state(TASK_UNINTERRUPTIBLE);
-
- /*
- * amdgpu_test_signaled_any must be called after
- * set_current_state to prevent a race with wake_up_process
- */
- if (amdgpu_test_signaled_any(array, count))
- break;
-
- if (adev->needs_reset) {
- t = -EDEADLK;
- break;
- }
-
- t = schedule_timeout(t);
-
- if (t > 0 && intr && signal_pending(current))
- t = -ERESTARTSYS;
- }
-
- __set_current_state(TASK_RUNNING);
-
-fence_rm_cb:
- for (idx = 0; idx < count; ++idx) {
- fence = array[idx];
- if (fence && cb[idx].base.func)
- fence_remove_callback(fence, &cb[idx].base);
- }
-
-err_free_cb:
- kfree(cb);
-
- return t;
-}
-
-const struct fence_ops amdgpu_fence_ops = {
- .get_driver_name = amdgpu_fence_get_driver_name,
- .get_timeline_name = amdgpu_fence_get_timeline_name,
- .enable_signaling = amdgpu_fence_enable_signaling,
- .signaled = amdgpu_fence_is_signaled,
- .wait = amdgpu_fence_default_wait,
- .release = NULL,
-};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 7297ca3a0ba7..00c5b580f56c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -115,9 +115,10 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_va *bo_va;
int r;
-
+ mutex_lock(&vm->mutex);
r = amdgpu_bo_reserve(rbo, false);
if (r) {
+ mutex_unlock(&vm->mutex);
return r;
}
@@ -128,7 +129,7 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri
++bo_va->ref_count;
}
amdgpu_bo_unreserve(rbo);
-
+ mutex_unlock(&vm->mutex);
return 0;
}
@@ -141,9 +142,10 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_va *bo_va;
int r;
-
+ mutex_lock(&vm->mutex);
r = amdgpu_bo_reserve(rbo, true);
if (r) {
+ mutex_unlock(&vm->mutex);
dev_err(adev->dev, "leaking bo va because "
"we fail to reserve bo (%d)\n", r);
return;
@@ -155,6 +157,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
}
}
amdgpu_bo_unreserve(rbo);
+ mutex_unlock(&vm->mutex);
}
static int amdgpu_gem_handle_lockup(struct amdgpu_device *adev, int r)
@@ -181,7 +184,6 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
bool kernel = false;
int r;
- down_read(&adev->exclusive_lock);
/* create a gem object to contain this object in */
if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS |
AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) {
@@ -214,11 +216,9 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
memset(args, 0, sizeof(*args));
args->out.handle = handle;
- up_read(&adev->exclusive_lock);
return 0;
error_unlock:
- up_read(&adev->exclusive_lock);
r = amdgpu_gem_handle_lockup(adev, r);
return r;
}
@@ -250,8 +250,6 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
return -EACCES;
}
- down_read(&adev->exclusive_lock);
-
/* create a gem object to contain this object in */
r = amdgpu_gem_object_create(adev, args->size, 0,
AMDGPU_GEM_DOMAIN_CPU, 0,
@@ -293,14 +291,12 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
goto handle_lockup;
args->handle = handle;
- up_read(&adev->exclusive_lock);
return 0;
release_object:
drm_gem_object_unreference_unlocked(gobj);
handle_lockup:
- up_read(&adev->exclusive_lock);
r = amdgpu_gem_handle_lockup(adev, r);
return r;
@@ -487,19 +483,17 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
if (domain == AMDGPU_GEM_DOMAIN_CPU)
goto error_unreserve;
}
+ r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
+ if (r)
+ goto error_unreserve;
- mutex_lock(&bo_va->vm->mutex);
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
if (r)
- goto error_unlock;
-
+ goto error_unreserve;
if (operation == AMDGPU_VA_OP_MAP)
r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem);
-error_unlock:
- mutex_unlock(&bo_va->vm->mutex);
-
error_unreserve:
ttm_eu_backoff_reservation(&ticket, &list);
@@ -521,6 +515,9 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_bo *rbo;
struct amdgpu_bo_va *bo_va;
+ struct ttm_validate_buffer tv, tv_pd;
+ struct ww_acquire_ctx ticket;
+ struct list_head list, duplicates;
uint32_t invalid_flags, va_flags = 0;
int r = 0;
@@ -556,17 +553,31 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL)
return -ENOENT;
-
+ mutex_lock(&fpriv->vm.mutex);
rbo = gem_to_amdgpu_bo(gobj);
- r = amdgpu_bo_reserve(rbo, false);
+ INIT_LIST_HEAD(&list);
+ INIT_LIST_HEAD(&duplicates);
+ tv.bo = &rbo->tbo;
+ tv.shared = true;
+ list_add(&tv.head, &list);
+
+ if (args->operation == AMDGPU_VA_OP_MAP) {
+ tv_pd.bo = &fpriv->vm.page_directory->tbo;
+ tv_pd.shared = true;
+ list_add(&tv_pd.head, &list);
+ }
+ r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
if (r) {
+ mutex_unlock(&fpriv->vm.mutex);
drm_gem_object_unreference_unlocked(gobj);
return r;
}
bo_va = amdgpu_vm_bo_find(&fpriv->vm, rbo);
if (!bo_va) {
- amdgpu_bo_unreserve(rbo);
+ ttm_eu_backoff_reservation(&ticket, &list);
+ drm_gem_object_unreference_unlocked(gobj);
+ mutex_unlock(&fpriv->vm.mutex);
return -ENOENT;
}
@@ -588,10 +599,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
default:
break;
}
-
+ ttm_eu_backoff_reservation(&ticket, &list);
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
-
+ mutex_unlock(&fpriv->vm.mutex);
drm_gem_object_unreference_unlocked(gobj);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index c439735ee670..9e25edafa721 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -62,7 +62,7 @@ int amdgpu_ib_get(struct amdgpu_ring *ring, struct amdgpu_vm *vm,
int r;
if (size) {
- r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
+ r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
&ib->sa_bo, size, 256);
if (r) {
dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
@@ -95,7 +95,8 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib)
{
amdgpu_sync_free(adev, &ib->sync, &ib->fence->base);
amdgpu_sa_bo_free(adev, &ib->sa_bo, &ib->fence->base);
- amdgpu_fence_unref(&ib->fence);
+ if (ib->fence)
+ fence_put(&ib->fence->base);
}
/**
@@ -215,7 +216,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
}
if (ib->vm)
- amdgpu_vm_fence(adev, ib->vm, ib->fence);
+ amdgpu_vm_fence(adev, ib->vm, &ib->fence->base);
amdgpu_ring_unlock_commit(ring);
return 0;
@@ -298,7 +299,6 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
r = amdgpu_ring_test_ib(ring);
if (r) {
ring->ready = false;
- adev->needs_reset = false;
if (ring == &adev->gfx.gfx_ring[0]) {
/* oh, oh, that's really bad */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 8c735f544b66..1618e2294a16 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -218,8 +218,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
break;
case AMDGPU_HW_IP_DMA:
type = AMD_IP_BLOCK_TYPE_SDMA;
- ring_mask = adev->sdma[0].ring.ready ? 1 : 0;
- ring_mask |= ((adev->sdma[1].ring.ready ? 1 : 0) << 1);
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ ring_mask |= ((adev->sdma.instance[i].ring.ready ? 1 : 0) << i);
ib_start_alignment = AMDGPU_GPU_PAGE_SIZE;
ib_size_alignment = 1;
break;
@@ -341,10 +341,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
fw_info.feature = 0;
break;
case AMDGPU_INFO_FW_SDMA:
- if (info->query_fw.index >= 2)
+ if (info->query_fw.index >= adev->sdma.num_instances)
return -EINVAL;
- fw_info.ver = adev->sdma[info->query_fw.index].fw_version;
- fw_info.feature = adev->sdma[info->query_fw.index].feature_version;
+ fw_info.ver = adev->sdma.instance[info->query_fw.index].fw_version;
+ fw_info.feature = adev->sdma.instance[info->query_fw.index].feature_version;
break;
default:
return -EINVAL;
@@ -485,14 +485,17 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
* Outdated mess for old drm with Xorg being in charge (void function now).
*/
/**
- * amdgpu_driver_firstopen_kms - drm callback for last close
+ * amdgpu_driver_lastclose_kms - drm callback for last close
*
* @dev: drm dev pointer
*
- * Switch vga switcheroo state after last close (all asics).
+ * Switch vga_switcheroo state after last close (all asics).
*/
void amdgpu_driver_lastclose_kms(struct drm_device *dev)
{
+ struct amdgpu_device *adev = dev->dev_private;
+
+ amdgpu_fbdev_restore_mode(adev);
vga_switcheroo_process_delayed_switch();
}
@@ -600,36 +603,36 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev,
* amdgpu_get_vblank_counter_kms - get frame count
*
* @dev: drm dev pointer
- * @crtc: crtc to get the frame count from
+ * @pipe: crtc to get the frame count from
*
* Gets the frame count on the requested crtc (all asics).
* Returns frame count on success, -EINVAL on failure.
*/
-u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, int crtc)
+u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
{
struct amdgpu_device *adev = dev->dev_private;
- if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
- DRM_ERROR("Invalid crtc %d\n", crtc);
+ if (pipe >= adev->mode_info.num_crtc) {
+ DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
- return amdgpu_display_vblank_get_counter(adev, crtc);
+ return amdgpu_display_vblank_get_counter(adev, pipe);
}
/**
* amdgpu_enable_vblank_kms - enable vblank interrupt
*
* @dev: drm dev pointer
- * @crtc: crtc to enable vblank interrupt for
+ * @pipe: crtc to enable vblank interrupt for
*
* Enable the interrupt on the requested crtc (all asics).
* Returns 0 on success, -EINVAL on failure.
*/
-int amdgpu_enable_vblank_kms(struct drm_device *dev, int crtc)
+int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe)
{
struct amdgpu_device *adev = dev->dev_private;
- int idx = amdgpu_crtc_idx_to_irq_type(adev, crtc);
+ int idx = amdgpu_crtc_idx_to_irq_type(adev, pipe);
return amdgpu_irq_get(adev, &adev->crtc_irq, idx);
}
@@ -638,14 +641,14 @@ int amdgpu_enable_vblank_kms(struct drm_device *dev, int crtc)
* amdgpu_disable_vblank_kms - disable vblank interrupt
*
* @dev: drm dev pointer
- * @crtc: crtc to disable vblank interrupt for
+ * @pipe: crtc to disable vblank interrupt for
*
* Disable the interrupt on the requested crtc (all asics).
*/
-void amdgpu_disable_vblank_kms(struct drm_device *dev, int crtc)
+void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe)
{
struct amdgpu_device *adev = dev->dev_private;
- int idx = amdgpu_crtc_idx_to_irq_type(adev, crtc);
+ int idx = amdgpu_crtc_idx_to_irq_type(adev, pipe);
amdgpu_irq_put(adev, &adev->crtc_irq, idx);
}
@@ -663,41 +666,41 @@ void amdgpu_disable_vblank_kms(struct drm_device *dev, int crtc)
* scanout position. (all asics).
* Returns postive status flags on success, negative error on failure.
*/
-int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
int *max_error,
struct timeval *vblank_time,
unsigned flags)
{
- struct drm_crtc *drmcrtc;
+ struct drm_crtc *crtc;
struct amdgpu_device *adev = dev->dev_private;
- if (crtc < 0 || crtc >= dev->num_crtcs) {
- DRM_ERROR("Invalid crtc %d\n", crtc);
+ if (pipe >= dev->num_crtcs) {
+ DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
/* Get associated drm_crtc: */
- drmcrtc = &adev->mode_info.crtcs[crtc]->base;
+ crtc = &adev->mode_info.crtcs[pipe]->base;
/* Helper routine in DRM core does all the work: */
- return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
+ return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
vblank_time, flags,
- drmcrtc, &drmcrtc->hwmode);
+ &crtc->hwmode);
}
const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_BO_LIST, amdgpu_bo_list_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_BO_LIST, amdgpu_bo_list_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
/* KMS */
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_MMAP, amdgpu_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_WAIT_IDLE, amdgpu_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_MMAP, amdgpu_gem_mmap_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_WAIT_IDLE, amdgpu_gem_wait_idle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
};
int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 64efe5b52e65..b62c1710cab6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -373,6 +373,10 @@ struct amdgpu_crtc {
uint32_t crtc_offset;
struct drm_gem_object *cursor_bo;
uint64_t cursor_addr;
+ int cursor_x;
+ int cursor_y;
+ int cursor_hot_x;
+ int cursor_hot_y;
int cursor_width;
int cursor_height;
int max_cursor_width;
@@ -540,10 +544,10 @@ bool amdgpu_ddc_probe(struct amdgpu_connector *amdgpu_connector, bool use_aux);
void amdgpu_encoder_set_active_device(struct drm_encoder *encoder);
-int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
- unsigned int flags,
- int *vpos, int *hpos, ktime_t *stime,
- ktime_t *etime);
+int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+ unsigned int flags, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode);
int amdgpu_framebuffer_init(struct drm_device *dev,
struct amdgpu_framebuffer *rfb,
@@ -567,6 +571,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev);
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj);
+void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev);
void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 1a7708f365f3..0d524384ff79 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -132,6 +132,8 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM;
+ if (!(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED))
+ placements[c - 1].flags |= TTM_PL_FLAG_TOPDOWN;
}
if (domain & AMDGPU_GEM_DOMAIN_GTT) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 3c2ff4567798..ea756e77b023 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -189,10 +189,9 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
struct amdgpu_sa_manager *sa_manager);
int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev,
struct amdgpu_sa_manager *sa_manager);
-int amdgpu_sa_bo_new(struct amdgpu_device *adev,
- struct amdgpu_sa_manager *sa_manager,
- struct amdgpu_sa_bo **sa_bo,
- unsigned size, unsigned align);
+int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
+ struct amdgpu_sa_bo **sa_bo,
+ unsigned size, unsigned align);
void amdgpu_sa_bo_free(struct amdgpu_device *adev,
struct amdgpu_sa_bo **sa_bo,
struct fence *fence);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index efed11509f4a..22a8c7d3a3ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -294,10 +294,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
struct amdgpu_device *adev = dev_get_drvdata(dev);
umode_t effective_mode = attr->mode;
- /* Skip limit attributes if DPM is not enabled */
+ /* Skip attributes if DPM is not enabled */
if (!adev->pm.dpm_enabled &&
(attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
- attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+ attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
return 0;
/* Skip fan attributes if fan is not present */
@@ -691,6 +695,9 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
{
int ret;
+ if (adev->pm.sysfs_initialized)
+ return 0;
+
if (adev->pm.funcs->get_temperature == NULL)
return 0;
adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
@@ -719,6 +726,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
return ret;
}
+ adev->pm.sysfs_initialized = true;
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 30dce235ddeb..78e9b0f14661 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -67,8 +67,6 @@ void amdgpu_ring_free_size(struct amdgpu_ring *ring)
if (!ring->ring_free_dw) {
/* this is an empty ring */
ring->ring_free_dw = ring->ring_size / 4;
- /* update lockup info to avoid false positive */
- amdgpu_ring_lockup_update(ring);
}
}
@@ -209,46 +207,6 @@ void amdgpu_ring_unlock_undo(struct amdgpu_ring *ring)
}
/**
- * amdgpu_ring_lockup_update - update lockup variables
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Update the last rptr value and timestamp (all asics).
- */
-void amdgpu_ring_lockup_update(struct amdgpu_ring *ring)
-{
- atomic_set(&ring->last_rptr, amdgpu_ring_get_rptr(ring));
- atomic64_set(&ring->last_activity, jiffies_64);
-}
-
-/**
- * amdgpu_ring_test_lockup() - check if ring is lockedup by recording information
- * @ring: amdgpu_ring structure holding ring information
- *
- */
-bool amdgpu_ring_test_lockup(struct amdgpu_ring *ring)
-{
- uint32_t rptr = amdgpu_ring_get_rptr(ring);
- uint64_t last = atomic64_read(&ring->last_activity);
- uint64_t elapsed;
-
- if (rptr != atomic_read(&ring->last_rptr)) {
- /* ring is still working, no lockup */
- amdgpu_ring_lockup_update(ring);
- return false;
- }
-
- elapsed = jiffies_to_msecs(jiffies_64 - last);
- if (amdgpu_lockup_timeout && elapsed >= amdgpu_lockup_timeout) {
- dev_err(ring->adev->dev, "ring %d stalled for more than %llumsec\n",
- ring->idx, elapsed);
- return true;
- }
- /* give a chance to the GPU ... */
- return false;
-}
-
-/**
* amdgpu_ring_backup - Back up the content of a ring
*
* @ring: the ring we want to back up
@@ -436,7 +394,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
if (amdgpu_debugfs_ring_init(adev, ring)) {
DRM_ERROR("Failed to register debugfs file for rings !\n");
}
- amdgpu_ring_lockup_update(ring);
return 0;
}
@@ -479,6 +436,30 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
}
}
+/**
+ * amdgpu_ring_from_fence - get ring from fence
+ *
+ * @f: fence structure
+ *
+ * Extract the ring a fence belongs to. Handles both scheduler as
+ * well as hardware fences.
+ */
+struct amdgpu_ring *amdgpu_ring_from_fence(struct fence *f)
+{
+ struct amdgpu_fence *a_fence;
+ struct amd_sched_fence *s_fence;
+
+ s_fence = to_amd_sched_fence(f);
+ if (s_fence)
+ return container_of(s_fence->sched, struct amdgpu_ring, sched);
+
+ a_fence = to_amdgpu_fence(f);
+ if (a_fence)
+ return a_fence->ring;
+
+ return NULL;
+}
+
/*
* Debugfs info
*/
@@ -540,8 +521,8 @@ static int amdgpu_debugfs_ring_info(struct seq_file *m, void *data)
static int amdgpu_gfx_index = offsetof(struct amdgpu_device, gfx.gfx_ring[0]);
static int cayman_cp1_index = offsetof(struct amdgpu_device, gfx.compute_ring[0]);
static int cayman_cp2_index = offsetof(struct amdgpu_device, gfx.compute_ring[1]);
-static int amdgpu_dma1_index = offsetof(struct amdgpu_device, sdma[0].ring);
-static int amdgpu_dma2_index = offsetof(struct amdgpu_device, sdma[1].ring);
+static int amdgpu_dma1_index = offsetof(struct amdgpu_device, sdma.instance[0].ring);
+static int amdgpu_dma2_index = offsetof(struct amdgpu_device, sdma.instance[1].ring);
static int r600_uvd_index = offsetof(struct amdgpu_device, uvd.ring);
static int si_vce1_index = offsetof(struct amdgpu_device, vce.ring[0]);
static int si_vce2_index = offsetof(struct amdgpu_device, vce.ring[1]);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
index e90712443fe9..8b88edb0434b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
@@ -139,25 +139,6 @@ int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev,
return r;
}
-static uint32_t amdgpu_sa_get_ring_from_fence(struct fence *f)
-{
- struct amdgpu_fence *a_fence;
- struct amd_sched_fence *s_fence;
-
- s_fence = to_amd_sched_fence(f);
- if (s_fence) {
- struct amdgpu_ring *ring;
-
- ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
- return ring->idx;
- }
-
- a_fence = to_amdgpu_fence(f);
- if (a_fence)
- return a_fence->ring->idx;
- return 0;
-}
-
static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo)
{
struct amdgpu_sa_manager *sa_manager = sa_bo->manager;
@@ -318,7 +299,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
}
if (best_bo) {
- uint32_t idx = amdgpu_sa_get_ring_from_fence(best_bo->fence);
+ uint32_t idx = amdgpu_ring_from_fence(best_bo->fence)->idx;
++tries[idx];
sa_manager->hole = best_bo->olist.prev;
@@ -330,13 +311,13 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
return false;
}
-int amdgpu_sa_bo_new(struct amdgpu_device *adev,
- struct amdgpu_sa_manager *sa_manager,
+int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
struct amdgpu_sa_bo **sa_bo,
unsigned size, unsigned align)
{
struct fence *fences[AMDGPU_MAX_RINGS];
unsigned tries[AMDGPU_MAX_RINGS];
+ unsigned count;
int i, r;
signed long t;
@@ -371,13 +352,18 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
/* see if we can skip over some allocations */
} while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries));
- spin_unlock(&sa_manager->wq.lock);
- t = amdgpu_fence_wait_any(adev, fences, AMDGPU_MAX_RINGS,
- false, MAX_SCHEDULE_TIMEOUT);
- r = (t > 0) ? 0 : t;
- spin_lock(&sa_manager->wq.lock);
- /* if we have nothing to wait for block */
- if (r == -ENOENT) {
+ for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i)
+ if (fences[i])
+ fences[count++] = fences[i];
+
+ if (count) {
+ spin_unlock(&sa_manager->wq.lock);
+ t = fence_wait_any_timeout(fences, count, false,
+ MAX_SCHEDULE_TIMEOUT);
+ r = (t > 0) ? 0 : t;
+ spin_lock(&sa_manager->wq.lock);
+ } else {
+ /* if we have nothing to wait for block */
r = wait_event_interruptible_locked(
sa_manager->wq,
amdgpu_sa_event(sa_manager, size, align)
@@ -406,7 +392,7 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
if (fence && !fence_is_signaled(fence)) {
uint32_t idx;
(*sa_bo)->fence = fence_get(fence);
- idx = amdgpu_sa_get_ring_from_fence(fence);
+ idx = amdgpu_ring_from_fence(fence)->idx;
list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]);
} else {
amdgpu_sa_bo_remove_locked(*sa_bo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
index 2e946b2cad88..438c05254695 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
@@ -26,6 +26,7 @@
#include <linux/sched.h>
#include <drm/drmP.h>
#include "amdgpu.h"
+#include "amdgpu_trace.h"
static struct fence *amdgpu_sched_dependency(struct amd_sched_job *sched_job)
{
@@ -44,24 +45,20 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
return NULL;
}
job = to_amdgpu_job(sched_job);
- mutex_lock(&job->job_lock);
- r = amdgpu_ib_schedule(job->adev,
- job->num_ibs,
- job->ibs,
- job->base.owner);
+ trace_amdgpu_sched_run_job(job);
+ r = amdgpu_ib_schedule(job->adev, job->num_ibs, job->ibs, job->owner);
if (r) {
DRM_ERROR("Error scheduling IBs (%d)\n", r);
goto err;
}
- fence = amdgpu_fence_ref(job->ibs[job->num_ibs - 1].fence);
+ fence = job->ibs[job->num_ibs - 1].fence;
+ fence_get(&fence->base);
err:
if (job->free_job)
job->free_job(job);
- mutex_unlock(&job->job_lock);
- fence_put(&job->base.s_fence->base);
kfree(job);
return fence ? &fence->base : NULL;
}
@@ -87,21 +84,19 @@ int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
return -ENOMEM;
job->base.sched = &ring->sched;
job->base.s_entity = &adev->kernel_ctx.rings[ring->idx].entity;
+ job->base.s_fence = amd_sched_fence_create(job->base.s_entity, owner);
+ if (!job->base.s_fence) {
+ kfree(job);
+ return -ENOMEM;
+ }
+ *f = fence_get(&job->base.s_fence->base);
+
job->adev = adev;
job->ibs = ibs;
job->num_ibs = num_ibs;
- job->base.owner = owner;
- mutex_init(&job->job_lock);
+ job->owner = owner;
job->free_job = free_job;
- mutex_lock(&job->job_lock);
- r = amd_sched_entity_push_job(&job->base);
- if (r) {
- mutex_unlock(&job->job_lock);
- kfree(job);
- return r;
- }
- *f = fence_get(&job->base.s_fence->base);
- mutex_unlock(&job->job_lock);
+ amd_sched_entity_push_job(&job->base);
} else {
r = amdgpu_ib_schedule(adev, num_ibs, ibs, owner);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_semaphore.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_semaphore.c
index ff3ca52ec6fe..1caaf201b708 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_semaphore.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_semaphore.c
@@ -40,7 +40,7 @@ int amdgpu_semaphore_create(struct amdgpu_device *adev,
if (*semaphore == NULL) {
return -ENOMEM;
}
- r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
+ r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
&(*semaphore)->sa_bo, 8, 8);
if (r) {
kfree(*semaphore);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index 4921de15b451..dd005c336c97 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -87,6 +87,15 @@ static bool amdgpu_sync_test_owner(struct fence *f, void *owner)
return false;
}
+static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence)
+{
+ if (*keep && fence_is_later(*keep, fence))
+ return;
+
+ fence_put(*keep);
+ *keep = fence_get(fence);
+}
+
/**
* amdgpu_sync_fence - remember to sync to this fence
*
@@ -99,35 +108,21 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
{
struct amdgpu_sync_entry *e;
struct amdgpu_fence *fence;
- struct amdgpu_fence *other;
- struct fence *tmp, *later;
if (!f)
return 0;
if (amdgpu_sync_same_dev(adev, f) &&
- amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM)) {
- if (sync->last_vm_update) {
- tmp = sync->last_vm_update;
- BUG_ON(f->context != tmp->context);
- later = (f->seqno - tmp->seqno <= INT_MAX) ? f : tmp;
- sync->last_vm_update = fence_get(later);
- fence_put(tmp);
- } else
- sync->last_vm_update = fence_get(f);
- }
+ amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM))
+ amdgpu_sync_keep_later(&sync->last_vm_update, f);
fence = to_amdgpu_fence(f);
if (!fence || fence->ring->adev != adev) {
hash_for_each_possible(sync->fences, e, node, f->context) {
- struct fence *new;
if (unlikely(e->fence->context != f->context))
continue;
- new = fence_get(fence_later(e->fence, f));
- if (new) {
- fence_put(e->fence);
- e->fence = new;
- }
+
+ amdgpu_sync_keep_later(&e->fence, f);
return 0;
}
@@ -140,10 +135,7 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
return 0;
}
- other = sync->sync_to[fence->ring->idx];
- sync->sync_to[fence->ring->idx] = amdgpu_fence_ref(
- amdgpu_fence_later(fence, other));
- amdgpu_fence_unref(&other);
+ amdgpu_sync_keep_later(&sync->sync_to[fence->ring->idx], f);
return 0;
}
@@ -199,8 +191,8 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
* for other VM updates and moves.
*/
fence_owner = amdgpu_sync_get_owner(f);
- if ((owner != AMDGPU_FENCE_OWNER_MOVE) &&
- (fence_owner != AMDGPU_FENCE_OWNER_MOVE) &&
+ if ((owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
+ (fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
((owner == AMDGPU_FENCE_OWNER_VM) !=
(fence_owner == AMDGPU_FENCE_OWNER_VM)))
continue;
@@ -262,11 +254,11 @@ int amdgpu_sync_wait(struct amdgpu_sync *sync)
return 0;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
- struct amdgpu_fence *fence = sync->sync_to[i];
+ struct fence *fence = sync->sync_to[i];
if (!fence)
continue;
- r = fence_wait(&fence->base, false);
+ r = fence_wait(fence, false);
if (r)
return r;
}
@@ -291,9 +283,14 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
int i, r;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
- struct amdgpu_fence *fence = sync->sync_to[i];
- struct amdgpu_semaphore *semaphore;
struct amdgpu_ring *other = adev->rings[i];
+ struct amdgpu_semaphore *semaphore;
+ struct amdgpu_fence *fence;
+
+ if (!sync->sync_to[i])
+ continue;
+
+ fence = to_amdgpu_fence(sync->sync_to[i]);
/* check if we really need to sync */
if (!amdgpu_fence_need_sync(fence, ring))
@@ -305,8 +302,14 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
return -EINVAL;
}
- if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores ||
- (count >= AMDGPU_NUM_SYNCS)) {
+ if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) {
+ r = fence_wait(&fence->base, true);
+ if (r)
+ return r;
+ continue;
+ }
+
+ if (count >= AMDGPU_NUM_SYNCS) {
/* not enough room, wait manually */
r = fence_wait(&fence->base, false);
if (r)
@@ -378,7 +381,7 @@ void amdgpu_sync_free(struct amdgpu_device *adev,
amdgpu_semaphore_free(adev, &sync->semaphores[i], fence);
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
- amdgpu_fence_unref(&sync->sync_to[i]);
+ fence_put(sync->sync_to[i]);
fence_put(sync->last_vm_update);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index 961d7265c286..8f9834ab1bd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -48,6 +48,57 @@ TRACE_EVENT(amdgpu_cs,
__entry->fences)
);
+TRACE_EVENT(amdgpu_cs_ioctl,
+ TP_PROTO(struct amdgpu_job *job),
+ TP_ARGS(job),
+ TP_STRUCT__entry(
+ __field(struct amdgpu_device *, adev)
+ __field(struct amd_sched_job *, sched_job)
+ __field(struct amdgpu_ib *, ib)
+ __field(struct fence *, fence)
+ __field(char *, ring_name)
+ __field(u32, num_ibs)
+ ),
+
+ TP_fast_assign(
+ __entry->adev = job->adev;
+ __entry->sched_job = &job->base;
+ __entry->ib = job->ibs;
+ __entry->fence = &job->base.s_fence->base;
+ __entry->ring_name = job->ibs[0].ring->name;
+ __entry->num_ibs = job->num_ibs;
+ ),
+ TP_printk("adev=%p, sched_job=%p, first ib=%p, sched fence=%p, ring name:%s, num_ibs:%u",
+ __entry->adev, __entry->sched_job, __entry->ib,
+ __entry->fence, __entry->ring_name, __entry->num_ibs)
+);
+
+TRACE_EVENT(amdgpu_sched_run_job,
+ TP_PROTO(struct amdgpu_job *job),
+ TP_ARGS(job),
+ TP_STRUCT__entry(
+ __field(struct amdgpu_device *, adev)
+ __field(struct amd_sched_job *, sched_job)
+ __field(struct amdgpu_ib *, ib)
+ __field(struct fence *, fence)
+ __field(char *, ring_name)
+ __field(u32, num_ibs)
+ ),
+
+ TP_fast_assign(
+ __entry->adev = job->adev;
+ __entry->sched_job = &job->base;
+ __entry->ib = job->ibs;
+ __entry->fence = &job->base.s_fence->base;
+ __entry->ring_name = job->ibs[0].ring->name;
+ __entry->num_ibs = job->num_ibs;
+ ),
+ TP_printk("adev=%p, sched_job=%p, first ib=%p, sched fence=%p, ring name:%s, num_ibs:%u",
+ __entry->adev, __entry->sched_job, __entry->ib,
+ __entry->fence, __entry->ring_name, __entry->num_ibs)
+);
+
+
TRACE_EVENT(amdgpu_vm_grab_id,
TP_PROTO(unsigned vmid, int ring),
TP_ARGS(vmid, ring),
@@ -111,7 +162,7 @@ TRACE_EVENT(amdgpu_vm_bo_unmap,
__entry->offset, __entry->flags)
);
-TRACE_EVENT(amdgpu_vm_bo_update,
+DECLARE_EVENT_CLASS(amdgpu_vm_mapping,
TP_PROTO(struct amdgpu_bo_va_mapping *mapping),
TP_ARGS(mapping),
TP_STRUCT__entry(
@@ -129,6 +180,16 @@ TRACE_EVENT(amdgpu_vm_bo_update,
__entry->soffset, __entry->eoffset, __entry->flags)
);
+DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_update,
+ TP_PROTO(struct amdgpu_bo_va_mapping *mapping),
+ TP_ARGS(mapping)
+);
+
+DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_mapping,
+ TP_PROTO(struct amdgpu_bo_va_mapping *mapping),
+ TP_ARGS(mapping)
+);
+
TRACE_EVENT(amdgpu_vm_set_page,
TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags),
@@ -186,49 +247,6 @@ TRACE_EVENT(amdgpu_bo_list_set,
TP_printk("list=%p, bo=%p", __entry->list, __entry->bo)
);
-DECLARE_EVENT_CLASS(amdgpu_fence_request,
-
- TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
- TP_ARGS(dev, ring, seqno),
-
- TP_STRUCT__entry(
- __field(u32, dev)
- __field(int, ring)
- __field(u32, seqno)
- ),
-
- TP_fast_assign(
- __entry->dev = dev->primary->index;
- __entry->ring = ring;
- __entry->seqno = seqno;
- ),
-
- TP_printk("dev=%u, ring=%d, seqno=%u",
- __entry->dev, __entry->ring, __entry->seqno)
-);
-
-DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_emit,
-
- TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
- TP_ARGS(dev, ring, seqno)
-);
-
-DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_wait_begin,
-
- TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
- TP_ARGS(dev, ring, seqno)
-);
-
-DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_wait_end,
-
- TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
- TP_ARGS(dev, ring, seqno)
-);
-
DECLARE_EVENT_CLASS(amdgpu_semaphore_request,
TP_PROTO(int ring, struct amdgpu_semaphore *sem),
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 364cbe975332..d4bac5f49939 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1041,7 +1041,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
WARN_ON(ib->length_dw > num_dw);
r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1,
&amdgpu_vm_free_job,
- AMDGPU_FENCE_OWNER_MOVE,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
fence);
if (r)
goto error_free;
@@ -1072,6 +1072,11 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
spin_lock(&glob->lru_lock);
ret = drm_mm_dump_table(m, mm);
spin_unlock(&glob->lru_lock);
+ if (ttm_pl == TTM_PL_VRAM)
+ seq_printf(m, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
+ adev->mman.bdev.man[ttm_pl].size,
+ (u64)atomic64_read(&adev->vram_usage) >> 20,
+ (u64)atomic64_read(&adev->vram_vis_usage) >> 20);
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index d0312364d950..53f987aeeacf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -53,6 +53,7 @@
#define FIRMWARE_TONGA "amdgpu/tonga_uvd.bin"
#define FIRMWARE_CARRIZO "amdgpu/carrizo_uvd.bin"
#define FIRMWARE_FIJI "amdgpu/fiji_uvd.bin"
+#define FIRMWARE_STONEY "amdgpu/stoney_uvd.bin"
/**
* amdgpu_uvd_cs_ctx - Command submission parser context
@@ -83,6 +84,7 @@ MODULE_FIRMWARE(FIRMWARE_MULLINS);
MODULE_FIRMWARE(FIRMWARE_TONGA);
MODULE_FIRMWARE(FIRMWARE_CARRIZO);
MODULE_FIRMWARE(FIRMWARE_FIJI);
+MODULE_FIRMWARE(FIRMWARE_STONEY);
static void amdgpu_uvd_note_usage(struct amdgpu_device *adev);
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
@@ -124,6 +126,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
case CHIP_CARRIZO:
fw_name = FIRMWARE_CARRIZO;
break;
+ case CHIP_STONEY:
+ fw_name = FIRMWARE_STONEY;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 74f2038ac747..03f0c3bae516 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -49,6 +49,7 @@
#define FIRMWARE_TONGA "amdgpu/tonga_vce.bin"
#define FIRMWARE_CARRIZO "amdgpu/carrizo_vce.bin"
#define FIRMWARE_FIJI "amdgpu/fiji_vce.bin"
+#define FIRMWARE_STONEY "amdgpu/stoney_vce.bin"
#ifdef CONFIG_DRM_AMDGPU_CIK
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
@@ -60,6 +61,7 @@ MODULE_FIRMWARE(FIRMWARE_MULLINS);
MODULE_FIRMWARE(FIRMWARE_TONGA);
MODULE_FIRMWARE(FIRMWARE_CARRIZO);
MODULE_FIRMWARE(FIRMWARE_FIJI);
+MODULE_FIRMWARE(FIRMWARE_STONEY);
static void amdgpu_vce_idle_work_handler(struct work_struct *work);
@@ -106,6 +108,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
case CHIP_FIJI:
fw_name = FIRMWARE_FIJI;
break;
+ case CHIP_STONEY:
+ fw_name = FIRMWARE_STONEY;
+ break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 1e14531353e0..159ce54bbd8d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -90,11 +90,9 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
struct amdgpu_bo_list_entry *list;
unsigned i, idx;
- mutex_lock(&vm->mutex);
list = drm_malloc_ab(vm->max_pde_used + 2,
sizeof(struct amdgpu_bo_list_entry));
if (!list) {
- mutex_unlock(&vm->mutex);
return NULL;
}
@@ -119,7 +117,6 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
list[idx].tv.shared = true;
list_add(&list[idx++].tv.head, head);
}
- mutex_unlock(&vm->mutex);
return list;
}
@@ -138,7 +135,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
struct amdgpu_sync *sync)
{
- struct amdgpu_fence *best[AMDGPU_MAX_RINGS] = {};
+ struct fence *best[AMDGPU_MAX_RINGS] = {};
struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx];
struct amdgpu_device *adev = ring->adev;
@@ -146,16 +143,24 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
unsigned i;
/* check if the id is still valid */
- if (vm_id->id && vm_id->last_id_use &&
- vm_id->last_id_use == adev->vm_manager.active[vm_id->id])
- return 0;
+ if (vm_id->id) {
+ unsigned id = vm_id->id;
+ long owner;
+
+ owner = atomic_long_read(&adev->vm_manager.ids[id].owner);
+ if (owner == (long)vm) {
+ trace_amdgpu_vm_grab_id(vm_id->id, ring->idx);
+ return 0;
+ }
+ }
/* we definately need to flush */
vm_id->pd_gpu_addr = ~0ll;
/* skip over VMID 0, since it is the system VM */
for (i = 1; i < adev->vm_manager.nvm; ++i) {
- struct amdgpu_fence *fence = adev->vm_manager.active[i];
+ struct fence *fence = adev->vm_manager.ids[i].active;
+ struct amdgpu_ring *fring;
if (fence == NULL) {
/* found a free one */
@@ -164,21 +169,23 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
return 0;
}
- if (amdgpu_fence_is_earlier(fence, best[fence->ring->idx])) {
- best[fence->ring->idx] = fence;
- choices[fence->ring == ring ? 0 : 1] = i;
+ fring = amdgpu_ring_from_fence(fence);
+ if (best[fring->idx] == NULL ||
+ fence_is_later(best[fring->idx], fence)) {
+ best[fring->idx] = fence;
+ choices[fring == ring ? 0 : 1] = i;
}
}
for (i = 0; i < 2; ++i) {
if (choices[i]) {
- struct amdgpu_fence *fence;
+ struct fence *fence;
- fence = adev->vm_manager.active[choices[i]];
+ fence = adev->vm_manager.ids[choices[i]].active;
vm_id->id = choices[i];
trace_amdgpu_vm_grab_id(choices[i], ring->idx);
- return amdgpu_sync_fence(ring->adev, sync, &fence->base);
+ return amdgpu_sync_fence(ring->adev, sync, fence);
}
}
@@ -205,24 +212,21 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx];
struct fence *flushed_updates = vm_id->flushed_updates;
- bool is_earlier = false;
-
- if (flushed_updates && updates) {
- BUG_ON(flushed_updates->context != updates->context);
- is_earlier = (updates->seqno - flushed_updates->seqno <=
- INT_MAX) ? true : false;
- }
+ bool is_later;
- if (pd_addr != vm_id->pd_gpu_addr || !flushed_updates ||
- is_earlier) {
+ if (!flushed_updates)
+ is_later = true;
+ else if (!updates)
+ is_later = false;
+ else
+ is_later = fence_is_later(updates, flushed_updates);
+ if (pd_addr != vm_id->pd_gpu_addr || is_later) {
trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id->id);
- if (is_earlier) {
+ if (is_later) {
vm_id->flushed_updates = fence_get(updates);
fence_put(flushed_updates);
}
- if (!flushed_updates)
- vm_id->flushed_updates = fence_get(updates);
vm_id->pd_gpu_addr = pd_addr;
amdgpu_ring_emit_vm_flush(ring, vm_id->id, vm_id->pd_gpu_addr);
}
@@ -242,16 +246,14 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
*/
void amdgpu_vm_fence(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
- struct amdgpu_fence *fence)
+ struct fence *fence)
{
- unsigned ridx = fence->ring->idx;
- unsigned vm_id = vm->ids[ridx].id;
+ struct amdgpu_ring *ring = amdgpu_ring_from_fence(fence);
+ unsigned vm_id = vm->ids[ring->idx].id;
- amdgpu_fence_unref(&adev->vm_manager.active[vm_id]);
- adev->vm_manager.active[vm_id] = amdgpu_fence_ref(fence);
-
- amdgpu_fence_unref(&vm->ids[ridx].last_id_use);
- vm->ids[ridx].last_id_use = amdgpu_fence_ref(fence);
+ fence_put(adev->vm_manager.ids[vm_id].active);
+ adev->vm_manager.ids[vm_id].active = fence_get(fence);
+ atomic_long_set(&adev->vm_manager.ids[vm_id].owner, (long)vm);
}
/**
@@ -330,6 +332,8 @@ int amdgpu_vm_free_job(struct amdgpu_job *job)
*
* @adev: amdgpu_device pointer
* @bo: bo to clear
+ *
+ * need to reserve bo first before calling it.
*/
static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
struct amdgpu_bo *bo)
@@ -341,24 +345,20 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
uint64_t addr;
int r;
- r = amdgpu_bo_reserve(bo, false);
- if (r)
- return r;
-
r = reservation_object_reserve_shared(bo->tbo.resv);
if (r)
return r;
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
if (r)
- goto error_unreserve;
+ goto error;
addr = amdgpu_bo_gpu_offset(bo);
entries = amdgpu_bo_size(bo) / 8;
ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL);
if (!ib)
- goto error_unreserve;
+ goto error;
r = amdgpu_ib_get(ring, NULL, entries * 2 + 64, ib);
if (r)
@@ -376,16 +376,14 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
if (!r)
amdgpu_bo_fence(bo, fence, true);
fence_put(fence);
- if (amdgpu_enable_scheduler) {
- amdgpu_bo_unreserve(bo);
+ if (amdgpu_enable_scheduler)
return 0;
- }
+
error_free:
amdgpu_ib_free(adev, ib);
kfree(ib);
-error_unreserve:
- amdgpu_bo_unreserve(bo);
+error:
return r;
}
@@ -455,8 +453,10 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
return -ENOMEM;
r = amdgpu_ib_get(ring, NULL, ndw * 4, ib);
- if (r)
+ if (r) {
+ kfree(ib);
return r;
+ }
ib->length_dw = 0;
/* walk over the address space and update the page directory */
@@ -850,6 +850,14 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
return r;
}
+ if (trace_amdgpu_vm_bo_mapping_enabled()) {
+ list_for_each_entry(mapping, &bo_va->valids, list)
+ trace_amdgpu_vm_bo_mapping(mapping);
+
+ list_for_each_entry(mapping, &bo_va->invalids, list)
+ trace_amdgpu_vm_bo_mapping(mapping);
+ }
+
spin_lock(&vm->status_lock);
list_splice_init(&bo_va->invalids, &bo_va->valids);
list_del_init(&bo_va->vm_status);
@@ -960,9 +968,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
INIT_LIST_HEAD(&bo_va->invalids);
INIT_LIST_HEAD(&bo_va->vm_status);
- mutex_lock(&vm->mutex);
list_add_tail(&bo_va->bo_list, &bo->va);
- mutex_unlock(&vm->mutex);
return bo_va;
}
@@ -979,7 +985,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
* Add a mapping of the BO at the specefied addr into the VM.
* Returns 0 for success, error for failure.
*
- * Object has to be reserved and gets unreserved by this function!
+ * Object has to be reserved and unreserved outside!
*/
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
@@ -995,32 +1001,27 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
/* validate the parameters */
if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
- size == 0 || size & AMDGPU_GPU_PAGE_MASK) {
- amdgpu_bo_unreserve(bo_va->bo);
+ size == 0 || size & AMDGPU_GPU_PAGE_MASK)
return -EINVAL;
- }
/* make sure object fit at this offset */
eaddr = saddr + size;
- if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo))) {
- amdgpu_bo_unreserve(bo_va->bo);
+ if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo)))
return -EINVAL;
- }
last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
if (last_pfn > adev->vm_manager.max_pfn) {
dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n",
last_pfn, adev->vm_manager.max_pfn);
- amdgpu_bo_unreserve(bo_va->bo);
return -EINVAL;
}
- mutex_lock(&vm->mutex);
-
saddr /= AMDGPU_GPU_PAGE_SIZE;
eaddr /= AMDGPU_GPU_PAGE_SIZE;
+ spin_lock(&vm->it_lock);
it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1);
+ spin_unlock(&vm->it_lock);
if (it) {
struct amdgpu_bo_va_mapping *tmp;
tmp = container_of(it, struct amdgpu_bo_va_mapping, it);
@@ -1028,16 +1029,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with "
"0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr,
tmp->it.start, tmp->it.last + 1);
- amdgpu_bo_unreserve(bo_va->bo);
r = -EINVAL;
- goto error_unlock;
+ goto error;
}
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
if (!mapping) {
- amdgpu_bo_unreserve(bo_va->bo);
r = -ENOMEM;
- goto error_unlock;
+ goto error;
}
INIT_LIST_HEAD(&mapping->list);
@@ -1047,7 +1046,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
mapping->flags = flags;
list_add(&mapping->list, &bo_va->invalids);
+ spin_lock(&vm->it_lock);
interval_tree_insert(&mapping->it, &vm->va);
+ spin_unlock(&vm->it_lock);
trace_amdgpu_vm_bo_map(bo_va, mapping);
/* Make sure the page tables are allocated */
@@ -1059,8 +1060,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
if (eaddr > vm->max_pde_used)
vm->max_pde_used = eaddr;
- amdgpu_bo_unreserve(bo_va->bo);
-
/* walk over the address space and allocate the page tables */
for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
struct reservation_object *resv = vm->page_directory->tbo.resv;
@@ -1069,16 +1068,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
if (vm->page_tables[pt_idx].bo)
continue;
- /* drop mutex to allocate and clear page table */
- mutex_unlock(&vm->mutex);
-
- ww_mutex_lock(&resv->lock, NULL);
r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
AMDGPU_GPU_PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
NULL, resv, &pt);
- ww_mutex_unlock(&resv->lock);
if (r)
goto error_free;
@@ -1088,32 +1082,21 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
goto error_free;
}
- /* aquire mutex again */
- mutex_lock(&vm->mutex);
- if (vm->page_tables[pt_idx].bo) {
- /* someone else allocated the pt in the meantime */
- mutex_unlock(&vm->mutex);
- amdgpu_bo_unref(&pt);
- mutex_lock(&vm->mutex);
- continue;
- }
-
vm->page_tables[pt_idx].addr = 0;
vm->page_tables[pt_idx].bo = pt;
}
- mutex_unlock(&vm->mutex);
return 0;
error_free:
- mutex_lock(&vm->mutex);
list_del(&mapping->list);
+ spin_lock(&vm->it_lock);
interval_tree_remove(&mapping->it, &vm->va);
+ spin_unlock(&vm->it_lock);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
kfree(mapping);
-error_unlock:
- mutex_unlock(&vm->mutex);
+error:
return r;
}
@@ -1127,7 +1110,7 @@ error_unlock:
* Remove a mapping of the BO at the specefied addr from the VM.
* Returns 0 for success, error for failure.
*
- * Object has to be reserved and gets unreserved by this function!
+ * Object has to be reserved and unreserved outside!
*/
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
@@ -1152,23 +1135,20 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
break;
}
- if (&mapping->list == &bo_va->invalids) {
- amdgpu_bo_unreserve(bo_va->bo);
+ if (&mapping->list == &bo_va->invalids)
return -ENOENT;
- }
}
- mutex_lock(&vm->mutex);
list_del(&mapping->list);
+ spin_lock(&vm->it_lock);
interval_tree_remove(&mapping->it, &vm->va);
+ spin_unlock(&vm->it_lock);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
if (valid)
list_add(&mapping->list, &vm->freed);
else
kfree(mapping);
- mutex_unlock(&vm->mutex);
- amdgpu_bo_unreserve(bo_va->bo);
return 0;
}
@@ -1191,28 +1171,28 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
list_del(&bo_va->bo_list);
- mutex_lock(&vm->mutex);
-
spin_lock(&vm->status_lock);
list_del(&bo_va->vm_status);
spin_unlock(&vm->status_lock);
list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
list_del(&mapping->list);
+ spin_lock(&vm->it_lock);
interval_tree_remove(&mapping->it, &vm->va);
+ spin_unlock(&vm->it_lock);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
list_add(&mapping->list, &vm->freed);
}
list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) {
list_del(&mapping->list);
+ spin_lock(&vm->it_lock);
interval_tree_remove(&mapping->it, &vm->va);
+ spin_unlock(&vm->it_lock);
kfree(mapping);
}
fence_put(bo_va->last_pt_update);
kfree(bo_va);
-
- mutex_unlock(&vm->mutex);
}
/**
@@ -1255,7 +1235,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
vm->ids[i].id = 0;
vm->ids[i].flushed_updates = NULL;
- vm->ids[i].last_id_use = NULL;
}
mutex_init(&vm->mutex);
vm->va = RB_ROOT;
@@ -1263,7 +1242,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
INIT_LIST_HEAD(&vm->invalidated);
INIT_LIST_HEAD(&vm->cleared);
INIT_LIST_HEAD(&vm->freed);
-
+ spin_lock_init(&vm->it_lock);
pd_size = amdgpu_vm_directory_size(adev);
pd_entries = amdgpu_vm_num_pdes(adev);
@@ -1283,8 +1262,14 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
NULL, NULL, &vm->page_directory);
if (r)
return r;
-
+ r = amdgpu_bo_reserve(vm->page_directory, false);
+ if (r) {
+ amdgpu_bo_unref(&vm->page_directory);
+ vm->page_directory = NULL;
+ return r;
+ }
r = amdgpu_vm_clear_bo(adev, vm->page_directory);
+ amdgpu_bo_unreserve(vm->page_directory);
if (r) {
amdgpu_bo_unref(&vm->page_directory);
vm->page_directory = NULL;
@@ -1327,11 +1312,28 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
amdgpu_bo_unref(&vm->page_directory);
fence_put(vm->page_directory_fence);
-
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
+ unsigned id = vm->ids[i].id;
+
+ atomic_long_cmpxchg(&adev->vm_manager.ids[id].owner,
+ (long)vm, 0);
fence_put(vm->ids[i].flushed_updates);
- amdgpu_fence_unref(&vm->ids[i].last_id_use);
}
mutex_destroy(&vm->mutex);
}
+
+/**
+ * amdgpu_vm_manager_fini - cleanup VM manager
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Cleanup the VM manager and free resources.
+ */
+void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ for (i = 0; i < AMDGPU_NUM_VM; ++i)
+ fence_put(adev->vm_manager.ids[i].active);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index a0346a90d805..1b50e6c13fb3 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -685,6 +685,27 @@ static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg)
}
}
+static void atom_op_div32(atom_exec_context *ctx, int *ptr, int arg)
+{
+ uint64_t val64;
+ uint8_t attr = U8((*ptr)++);
+ uint32_t dst, src;
+ SDEBUG(" src1: ");
+ dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
+ SDEBUG(" src2: ");
+ src = atom_get_src(ctx, attr, ptr);
+ if (src != 0) {
+ val64 = dst;
+ val64 |= ((uint64_t)ctx->ctx->divmul[1]) << 32;
+ do_div(val64, src);
+ ctx->ctx->divmul[0] = lower_32_bits(val64);
+ ctx->ctx->divmul[1] = upper_32_bits(val64);
+ } else {
+ ctx->ctx->divmul[0] = 0;
+ ctx->ctx->divmul[1] = 0;
+ }
+}
+
static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg)
{
/* functionally, a nop */
@@ -788,6 +809,20 @@ static void atom_op_mul(atom_exec_context *ctx, int *ptr, int arg)
ctx->ctx->divmul[0] = dst * src;
}
+static void atom_op_mul32(atom_exec_context *ctx, int *ptr, int arg)
+{
+ uint64_t val64;
+ uint8_t attr = U8((*ptr)++);
+ uint32_t dst, src;
+ SDEBUG(" src1: ");
+ dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
+ SDEBUG(" src2: ");
+ src = atom_get_src(ctx, attr, ptr);
+ val64 = (uint64_t)dst * (uint64_t)src;
+ ctx->ctx->divmul[0] = lower_32_bits(val64);
+ ctx->ctx->divmul[1] = upper_32_bits(val64);
+}
+
static void atom_op_nop(atom_exec_context *ctx, int *ptr, int arg)
{
/* nothing */
@@ -1022,7 +1057,15 @@ static void atom_op_xor(atom_exec_context *ctx, int *ptr, int arg)
static void atom_op_debug(atom_exec_context *ctx, int *ptr, int arg)
{
- printk(KERN_INFO "unimplemented!\n");
+ uint8_t val = U8((*ptr)++);
+ SDEBUG("DEBUG output: 0x%02X\n", val);
+}
+
+static void atom_op_processds(atom_exec_context *ctx, int *ptr, int arg)
+{
+ uint16_t val = U16(*ptr);
+ (*ptr) += val + 2;
+ SDEBUG("PROCESSDS output: 0x%02X\n", val);
}
static struct {
@@ -1151,7 +1194,13 @@ static struct {
atom_op_shr, ATOM_ARG_FB}, {
atom_op_shr, ATOM_ARG_PLL}, {
atom_op_shr, ATOM_ARG_MC}, {
-atom_op_debug, 0},};
+ atom_op_debug, 0}, {
+ atom_op_processds, 0}, {
+ atom_op_mul32, ATOM_ARG_PS}, {
+ atom_op_mul32, ATOM_ARG_WS}, {
+ atom_op_div32, ATOM_ARG_PS}, {
+ atom_op_div32, ATOM_ARG_WS},
+};
static int amdgpu_atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.h b/drivers/gpu/drm/amd/amdgpu/atom.h
index 09d0f8230708..fece8f45dc7a 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.h
+++ b/drivers/gpu/drm/amd/amdgpu/atom.h
@@ -60,7 +60,7 @@
#define ATOM_CT_PS_MASK 0x7F
#define ATOM_CT_CODE_PTR 6
-#define ATOM_OP_CNT 123
+#define ATOM_OP_CNT 127
#define ATOM_OP_EOT 91
#define ATOM_CASE_MAGIC 0x63
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 82e8d0730517..57a2e347f04d 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -6185,6 +6185,11 @@ static int ci_dpm_late_init(void *handle)
if (!amdgpu_dpm)
return 0;
+ /* init the sysfs and debugfs files late */
+ ret = amdgpu_pm_sysfs_init(adev);
+ if (ret)
+ return ret;
+
ret = ci_set_temperature_range(adev);
if (ret)
return ret;
@@ -6232,9 +6237,6 @@ static int ci_dpm_sw_init(void *handle)
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- goto dpm_failed;
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");
@@ -6567,12 +6569,12 @@ static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
- cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+ cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
- cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+ cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
break;
default:
@@ -6584,12 +6586,12 @@ static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
- cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+ cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
- cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+ cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 4b6ce74753cd..484710cfdf82 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1567,6 +1567,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev)
int ret, i;
u16 tmp16;
+ if (pci_is_root_bus(adev->pdev->bus))
+ return;
+
if (amdgpu_pcie_gen2 == 0)
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 9ea9de457da3..5f712ceddf08 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -96,7 +96,7 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
char fw_name[30];
- int err, i;
+ int err = 0, i;
DRM_DEBUG("\n");
@@ -119,24 +119,24 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev)
default: BUG();
}
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma1.bin", chip_name);
- err = request_firmware(&adev->sdma[i].fw, fw_name, adev->dev);
+ err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->sdma[i].fw);
+ err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
}
out:
if (err) {
printk(KERN_ERR
"cik_sdma: Failed to load firmware \"%s\"\n",
fw_name);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- release_firmware(adev->sdma[i].fw);
- adev->sdma[i].fw = NULL;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ release_firmware(adev->sdma.instance[i].fw);
+ adev->sdma.instance[i].fw = NULL;
}
}
return err;
@@ -168,7 +168,7 @@ static uint32_t cik_sdma_ring_get_rptr(struct amdgpu_ring *ring)
static uint32_t cik_sdma_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- u32 me = (ring == &adev->sdma[0].ring) ? 0 : 1;
+ u32 me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1;
return (RREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me]) & 0x3fffc) >> 2;
}
@@ -183,14 +183,14 @@ static uint32_t cik_sdma_ring_get_wptr(struct amdgpu_ring *ring)
static void cik_sdma_ring_set_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- u32 me = (ring == &adev->sdma[0].ring) ? 0 : 1;
+ u32 me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1;
WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], (ring->wptr << 2) & 0x3fffc);
}
static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
{
- struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ring);
+ struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ring);
int i;
for (i = 0; i < count; i++)
@@ -248,7 +248,7 @@ static void cik_sdma_ring_emit_hdp_flush(struct amdgpu_ring *ring)
SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */
u32 ref_and_mask;
- if (ring == &ring->adev->sdma[0].ring)
+ if (ring == &ring->adev->sdma.instance[0].ring)
ref_and_mask = GPU_HDP_FLUSH_DONE__SDMA0_MASK;
else
ref_and_mask = GPU_HDP_FLUSH_DONE__SDMA1_MASK;
@@ -327,8 +327,8 @@ static bool cik_sdma_ring_emit_semaphore(struct amdgpu_ring *ring,
*/
static void cik_sdma_gfx_stop(struct amdgpu_device *adev)
{
- struct amdgpu_ring *sdma0 = &adev->sdma[0].ring;
- struct amdgpu_ring *sdma1 = &adev->sdma[1].ring;
+ struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
+ struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl;
int i;
@@ -336,7 +336,7 @@ static void cik_sdma_gfx_stop(struct amdgpu_device *adev)
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK;
WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
@@ -376,7 +376,7 @@ static void cik_sdma_enable(struct amdgpu_device *adev, bool enable)
cik_sdma_rlc_stop(adev);
}
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
me_cntl = RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]);
if (enable)
me_cntl &= ~SDMA0_F32_CNTL__HALT_MASK;
@@ -402,8 +402,8 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
u32 wb_offset;
int i, j, r;
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- ring = &adev->sdma[i].ring;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ ring = &adev->sdma.instance[i].ring;
wb_offset = (ring->rptr_offs * 4);
mutex_lock(&adev->srbm_mutex);
@@ -502,26 +502,25 @@ static int cik_sdma_load_microcode(struct amdgpu_device *adev)
u32 fw_size;
int i, j;
- if (!adev->sdma[0].fw || !adev->sdma[1].fw)
- return -EINVAL;
-
/* halt the MEs */
cik_sdma_enable(adev, false);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ if (!adev->sdma.instance[i].fw)
+ return -EINVAL;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
amdgpu_ucode_print_sdma_hdr(&hdr->header);
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
- adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
- if (adev->sdma[i].feature_version >= 20)
- adev->sdma[i].burst_nop = true;
+ adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
+ if (adev->sdma.instance[i].feature_version >= 20)
+ adev->sdma.instance[i].burst_nop = true;
fw_data = (const __le32 *)
- (adev->sdma[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ (adev->sdma.instance[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
for (j = 0; j < fw_size; j++)
WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma[i].fw_version);
+ WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version);
}
return 0;
@@ -830,7 +829,7 @@ static void cik_sdma_vm_set_pte_pde(struct amdgpu_ib *ib,
*/
static void cik_sdma_vm_pad_ib(struct amdgpu_ib *ib)
{
- struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ib->ring);
+ struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ib->ring);
u32 pad_count;
int i;
@@ -934,6 +933,8 @@ static int cik_sdma_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->sdma.num_instances = SDMA_MAX_INSTANCE;
+
cik_sdma_set_ring_funcs(adev);
cik_sdma_set_irq_funcs(adev);
cik_sdma_set_buffer_funcs(adev);
@@ -946,7 +947,7 @@ static int cik_sdma_sw_init(void *handle)
{
struct amdgpu_ring *ring;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int r;
+ int r, i;
r = cik_sdma_init_microcode(adev);
if (r) {
@@ -955,43 +956,33 @@ static int cik_sdma_sw_init(void *handle)
}
/* SDMA trap event */
- r = amdgpu_irq_add_id(adev, 224, &adev->sdma_trap_irq);
+ r = amdgpu_irq_add_id(adev, 224, &adev->sdma.trap_irq);
if (r)
return r;
/* SDMA Privileged inst */
- r = amdgpu_irq_add_id(adev, 241, &adev->sdma_illegal_inst_irq);
+ r = amdgpu_irq_add_id(adev, 241, &adev->sdma.illegal_inst_irq);
if (r)
return r;
/* SDMA Privileged inst */
- r = amdgpu_irq_add_id(adev, 247, &adev->sdma_illegal_inst_irq);
+ r = amdgpu_irq_add_id(adev, 247, &adev->sdma.illegal_inst_irq);
if (r)
return r;
- ring = &adev->sdma[0].ring;
- ring->ring_obj = NULL;
-
- ring = &adev->sdma[1].ring;
- ring->ring_obj = NULL;
-
- ring = &adev->sdma[0].ring;
- sprintf(ring->name, "sdma0");
- r = amdgpu_ring_init(adev, ring, 256 * 1024,
- SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf,
- &adev->sdma_trap_irq, AMDGPU_SDMA_IRQ_TRAP0,
- AMDGPU_RING_TYPE_SDMA);
- if (r)
- return r;
-
- ring = &adev->sdma[1].ring;
- sprintf(ring->name, "sdma1");
- r = amdgpu_ring_init(adev, ring, 256 * 1024,
- SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf,
- &adev->sdma_trap_irq, AMDGPU_SDMA_IRQ_TRAP1,
- AMDGPU_RING_TYPE_SDMA);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ ring = &adev->sdma.instance[i].ring;
+ ring->ring_obj = NULL;
+ sprintf(ring->name, "sdma%d", i);
+ r = amdgpu_ring_init(adev, ring, 256 * 1024,
+ SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf,
+ &adev->sdma.trap_irq,
+ (i == 0) ?
+ AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
+ AMDGPU_RING_TYPE_SDMA);
+ if (r)
+ return r;
+ }
return r;
}
@@ -999,9 +990,10 @@ static int cik_sdma_sw_init(void *handle)
static int cik_sdma_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i;
- amdgpu_ring_fini(&adev->sdma[0].ring);
- amdgpu_ring_fini(&adev->sdma[1].ring);
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ring_fini(&adev->sdma.instance[i].ring);
return 0;
}
@@ -1078,7 +1070,7 @@ static void cik_sdma_print_status(void *handle)
dev_info(adev->dev, "CIK SDMA registers\n");
dev_info(adev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(mmSRBM_STATUS2));
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
dev_info(adev->dev, " SDMA%d_STATUS_REG=0x%08X\n",
i, RREG32(mmSDMA0_STATUS_REG + sdma_offsets[i]));
dev_info(adev->dev, " SDMA%d_ME_CNTL=0x%08X\n",
@@ -1223,7 +1215,7 @@ static int cik_sdma_process_trap_irq(struct amdgpu_device *adev,
case 0:
switch (queue_id) {
case 0:
- amdgpu_fence_process(&adev->sdma[0].ring);
+ amdgpu_fence_process(&adev->sdma.instance[0].ring);
break;
case 1:
/* XXX compute */
@@ -1236,7 +1228,7 @@ static int cik_sdma_process_trap_irq(struct amdgpu_device *adev,
case 1:
switch (queue_id) {
case 0:
- amdgpu_fence_process(&adev->sdma[1].ring);
+ amdgpu_fence_process(&adev->sdma.instance[1].ring);
break;
case 1:
/* XXX compute */
@@ -1298,24 +1290,6 @@ const struct amd_ip_funcs cik_sdma_ip_funcs = {
.set_powergating_state = cik_sdma_set_powergating_state,
};
-/**
- * cik_sdma_ring_is_lockup - Check if the DMA engine is locked up
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the async DMA engine is locked up (CIK).
- * Returns true if the engine appears to be locked up, false if not.
- */
-static bool cik_sdma_ring_is_lockup(struct amdgpu_ring *ring)
-{
-
- if (cik_sdma_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
.get_rptr = cik_sdma_ring_get_rptr,
.get_wptr = cik_sdma_ring_get_wptr,
@@ -1328,14 +1302,15 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
.emit_hdp_flush = cik_sdma_ring_emit_hdp_flush,
.test_ring = cik_sdma_ring_test_ring,
.test_ib = cik_sdma_ring_test_ib,
- .is_lockup = cik_sdma_ring_is_lockup,
.insert_nop = cik_sdma_ring_insert_nop,
};
static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev)
{
- adev->sdma[0].ring.funcs = &cik_sdma_ring_funcs;
- adev->sdma[1].ring.funcs = &cik_sdma_ring_funcs;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ adev->sdma.instance[i].ring.funcs = &cik_sdma_ring_funcs;
}
static const struct amdgpu_irq_src_funcs cik_sdma_trap_irq_funcs = {
@@ -1349,9 +1324,9 @@ static const struct amdgpu_irq_src_funcs cik_sdma_illegal_inst_irq_funcs = {
static void cik_sdma_set_irq_funcs(struct amdgpu_device *adev)
{
- adev->sdma_trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
- adev->sdma_trap_irq.funcs = &cik_sdma_trap_irq_funcs;
- adev->sdma_illegal_inst_irq.funcs = &cik_sdma_illegal_inst_irq_funcs;
+ adev->sdma.trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
+ adev->sdma.trap_irq.funcs = &cik_sdma_trap_irq_funcs;
+ adev->sdma.illegal_inst_irq.funcs = &cik_sdma_illegal_inst_irq_funcs;
}
/**
@@ -1416,7 +1391,7 @@ static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev)
{
if (adev->mman.buffer_funcs == NULL) {
adev->mman.buffer_funcs = &cik_sdma_buffer_funcs;
- adev->mman.buffer_funcs_ring = &adev->sdma[0].ring;
+ adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring;
}
}
@@ -1431,7 +1406,7 @@ static void cik_sdma_set_vm_pte_funcs(struct amdgpu_device *adev)
{
if (adev->vm_manager.vm_pte_funcs == NULL) {
adev->vm_manager.vm_pte_funcs = &cik_sdma_vm_pte_funcs;
- adev->vm_manager.vm_pte_funcs_ring = &adev->sdma[0].ring;
+ adev->vm_manager.vm_pte_funcs_ring = &adev->sdma.instance[0].ring;
adev->vm_manager.vm_pte_funcs_ring->is_pte_ring = true;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 44fa96ad4709..8035d4d6a4f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -596,6 +596,12 @@ static int cz_dpm_late_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_dpm) {
+ int ret;
+ /* init the sysfs and debugfs files late */
+ ret = amdgpu_pm_sysfs_init(adev);
+ if (ret)
+ return ret;
+
/* powerdown unused blocks for now */
cz_dpm_powergate_uvd(adev, true);
cz_dpm_powergate_vce(adev, true);
@@ -632,10 +638,6 @@ static int cz_dpm_sw_init(void *handle)
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- goto dpm_init_failed;
-
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");
@@ -1262,6 +1264,7 @@ static void cz_apply_state_adjust_rules(struct amdgpu_device *adev,
static int cz_dpm_enable(struct amdgpu_device *adev)
{
+ const char *chip_name;
int ret = 0;
/* renable will hang up SMU, so check first */
@@ -1270,21 +1273,33 @@ static int cz_dpm_enable(struct amdgpu_device *adev)
cz_program_voting_clients(adev);
+ switch (adev->asic_type) {
+ case CHIP_CARRIZO:
+ chip_name = "carrizo";
+ break;
+ case CHIP_STONEY:
+ chip_name = "stoney";
+ break;
+ default:
+ BUG();
+ }
+
+
ret = cz_start_dpm(adev);
if (ret) {
- DRM_ERROR("Carrizo DPM enable failed\n");
+ DRM_ERROR("%s DPM enable failed\n", chip_name);
return -EINVAL;
}
ret = cz_program_bootup_state(adev);
if (ret) {
- DRM_ERROR("Carrizo bootup state program failed\n");
+ DRM_ERROR("%s bootup state program failed\n", chip_name);
return -EINVAL;
}
ret = cz_enable_didt(adev, true);
if (ret) {
- DRM_ERROR("Carrizo enable di/dt failed\n");
+ DRM_ERROR("%s enable di/dt failed\n", chip_name);
return -EINVAL;
}
@@ -1351,7 +1366,7 @@ static int cz_dpm_disable(struct amdgpu_device *adev)
ret = cz_enable_didt(adev, false);
if (ret) {
- DRM_ERROR("Carrizo disable di/dt failed\n");
+ DRM_ERROR("disable di/dt failed\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_smc.c b/drivers/gpu/drm/amd/amdgpu/cz_smc.c
index e33180d3314a..ac7fee7b7eca 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_smc.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_smc.c
@@ -312,13 +312,16 @@ int cz_smu_start(struct amdgpu_device *adev)
UCODE_ID_CP_MEC_JT1_MASK |
UCODE_ID_CP_MEC_JT2_MASK;
+ if (adev->asic_type == CHIP_STONEY)
+ fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
+
cz_smu_request_load_fw(adev);
ret = cz_smu_check_fw_load_finish(adev, fw_to_check);
if (ret)
return ret;
/* manually load MEC firmware for CZ */
- if (adev->asic_type == CHIP_CARRIZO) {
+ if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) {
ret = cz_load_mec_firmware(adev);
if (ret) {
dev_err(adev->dev, "(%d) Mec Firmware load failed\n", ret);
@@ -336,6 +339,9 @@ int cz_smu_start(struct amdgpu_device *adev)
AMDGPU_CPMEC2_UCODE_LOADED |
AMDGPU_CPRLC_UCODE_LOADED;
+ if (adev->asic_type == CHIP_STONEY)
+ adev->smu.fw_flags &= ~(AMDGPU_SDMA1_UCODE_LOADED | AMDGPU_CPMEC2_UCODE_LOADED);
+
return ret;
}
@@ -601,8 +607,13 @@ static int cz_smu_construct_toc_for_vddgfx_exit(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- cz_smu_populate_single_ucode_load_task(adev,
+ if (adev->asic_type == CHIP_STONEY) {
+ cz_smu_populate_single_ucode_load_task(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+ } else {
+ cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+ }
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
}
@@ -642,8 +653,13 @@ static int cz_smu_construct_toc_for_bootup(struct amdgpu_device *adev)
if (adev->firmware.smu_load) {
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
- cz_smu_populate_single_ucode_load_task(adev,
+ if (adev->asic_type == CHIP_STONEY) {
+ cz_smu_populate_single_ucode_load_task(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
+ } else {
+ cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
+ }
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
cz_smu_populate_single_ucode_load_task(adev,
@@ -652,8 +668,13 @@ static int cz_smu_construct_toc_for_bootup(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- cz_smu_populate_single_ucode_load_task(adev,
+ if (adev->asic_type == CHIP_STONEY) {
+ cz_smu_populate_single_ucode_load_task(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+ } else {
+ cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+ }
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
}
@@ -888,10 +909,18 @@ int cz_smu_init(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
&priv->driver_buffer[priv->driver_buffer_length++]))
goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
+
+ if (adev->asic_type == CHIP_STONEY) {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ } else {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ }
if (cz_smu_populate_single_firmware_entry(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
&priv->driver_buffer[priv->driver_buffer_length++]))
@@ -908,10 +937,17 @@ int cz_smu_init(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
&priv->driver_buffer[priv->driver_buffer_length++]))
goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
+ if (adev->asic_type == CHIP_STONEY) {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ } else {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ }
if (cz_smu_populate_single_firmware_entry(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
&priv->driver_buffer[priv->driver_buffer_length++]))
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index e4d101b1252a..cb0f7747e3dc 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -255,6 +255,24 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
+static void dce_v10_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Enable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v10_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Disable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
/**
* dce_v10_0_page_flip - pageflip callback.
*
@@ -262,46 +280,22 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
* @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address)
*
- * Does the actual pageflip (evergreen+).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
- * Returns the current update pending status.
+ * Triggers the actual pageflip by updating the primary
+ * surface base address.
*/
static void dce_v10_0_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base)
{
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
- u32 tmp = RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset);
- int i;
-
- /* Lock the graphics update lock */
- tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
- WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
-
- /* update the scanout addresses */
- WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
- upper_32_bits(crtc_base));
- WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- lower_32_bits(crtc_base));
+ /* update the primary scanout address */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
+ /* writing to the low address triggers the update */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(crtc_base));
-
- /* Wait for update_pending to go high. */
- for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset) &
- GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK)
- break;
- udelay(1);
- }
- DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
- /* Unlock the lock, so double-buffering can take place inside vblank */
- tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
- WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
+ /* post the write */
+ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
@@ -2499,26 +2493,19 @@ static void dce_v10_0_show_cursor(struct drm_crtc *crtc)
struct amdgpu_device *adev = crtc->dev->dev_private;
u32 tmp;
+ WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ upper_32_bits(amdgpu_crtc->cursor_addr));
+ WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ lower_32_bits(amdgpu_crtc->cursor_addr));
+
tmp = RREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset);
tmp = REG_SET_FIELD(tmp, CUR_CONTROL, CURSOR_EN, 1);
tmp = REG_SET_FIELD(tmp, CUR_CONTROL, CURSOR_MODE, 2);
WREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset, tmp);
}
-static void dce_v10_0_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
- uint64_t gpu_addr)
-{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- struct amdgpu_device *adev = crtc->dev->dev_private;
-
- WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
- upper_32_bits(gpu_addr));
- WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- lower_32_bits(gpu_addr));
-}
-
-static int dce_v10_0_crtc_cursor_move(struct drm_crtc *crtc,
- int x, int y)
+static int dce_v10_0_cursor_move_locked(struct drm_crtc *crtc,
+ int x, int y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct amdgpu_device *adev = crtc->dev->dev_private;
@@ -2538,26 +2525,40 @@ static int dce_v10_0_crtc_cursor_move(struct drm_crtc *crtc,
y = 0;
}
- dce_v10_0_lock_cursor(crtc, true);
WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
- dce_v10_0_lock_cursor(crtc, false);
+
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
return 0;
}
-static int dce_v10_0_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width,
- uint32_t height)
+static int dce_v10_0_crtc_cursor_move(struct drm_crtc *crtc,
+ int x, int y)
+{
+ int ret;
+
+ dce_v10_0_lock_cursor(crtc, true);
+ ret = dce_v10_0_cursor_move_locked(crtc, x, y);
+ dce_v10_0_lock_cursor(crtc, false);
+
+ return ret;
+}
+
+static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
+ struct drm_file *file_priv,
+ uint32_t handle,
+ uint32_t width,
+ uint32_t height,
+ int32_t hot_x,
+ int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct drm_gem_object *obj;
- struct amdgpu_bo *robj;
- uint64_t gpu_addr;
+ struct amdgpu_bo *aobj;
int ret;
if (!handle) {
@@ -2579,41 +2580,71 @@ static int dce_v10_0_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOENT;
}
- robj = gem_to_amdgpu_bo(obj);
- ret = amdgpu_bo_reserve(robj, false);
- if (unlikely(ret != 0))
- goto fail;
- ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM,
- 0, 0, &gpu_addr);
- amdgpu_bo_unreserve(robj);
- if (ret)
- goto fail;
+ aobj = gem_to_amdgpu_bo(obj);
+ ret = amdgpu_bo_reserve(aobj, false);
+ if (ret != 0) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
+
+ ret = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM, &amdgpu_crtc->cursor_addr);
+ amdgpu_bo_unreserve(aobj);
+ if (ret) {
+ DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
amdgpu_crtc->cursor_width = width;
amdgpu_crtc->cursor_height = height;
dce_v10_0_lock_cursor(crtc, true);
- dce_v10_0_set_cursor(crtc, obj, gpu_addr);
+
+ if (hot_x != amdgpu_crtc->cursor_hot_x ||
+ hot_y != amdgpu_crtc->cursor_hot_y) {
+ int x, y;
+
+ x = amdgpu_crtc->cursor_x + amdgpu_crtc->cursor_hot_x - hot_x;
+ y = amdgpu_crtc->cursor_y + amdgpu_crtc->cursor_hot_y - hot_y;
+
+ dce_v10_0_cursor_move_locked(crtc, x, y);
+
+ amdgpu_crtc->cursor_hot_x = hot_x;
+ amdgpu_crtc->cursor_hot_y = hot_y;
+ }
+
dce_v10_0_show_cursor(crtc);
dce_v10_0_lock_cursor(crtc, false);
unpin:
if (amdgpu_crtc->cursor_bo) {
- robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
- ret = amdgpu_bo_reserve(robj, false);
+ struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+ ret = amdgpu_bo_reserve(aobj, false);
if (likely(ret == 0)) {
- amdgpu_bo_unpin(robj);
- amdgpu_bo_unreserve(robj);
+ amdgpu_bo_unpin(aobj);
+ amdgpu_bo_unreserve(aobj);
}
drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo);
}
amdgpu_crtc->cursor_bo = obj;
return 0;
-fail:
- drm_gem_object_unreference_unlocked(obj);
+}
- return ret;
+static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
+{
+ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+ if (amdgpu_crtc->cursor_bo) {
+ dce_v10_0_lock_cursor(crtc, true);
+
+ dce_v10_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
+ amdgpu_crtc->cursor_y);
+
+ dce_v10_0_show_cursor(crtc);
+
+ dce_v10_0_lock_cursor(crtc, false);
+ }
}
static void dce_v10_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
@@ -2641,7 +2672,7 @@ static void dce_v10_0_crtc_destroy(struct drm_crtc *crtc)
}
static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = {
- .cursor_set = dce_v10_0_crtc_cursor_set,
+ .cursor_set2 = dce_v10_0_crtc_cursor_set2,
.cursor_move = dce_v10_0_crtc_cursor_move,
.gamma_set = dce_v10_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config,
@@ -2663,9 +2694,10 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v10_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v10_0_vga_enable(crtc, false);
- /* Make sure VBLANK interrupt is still enabled */
+ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
+ amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v10_0_crtc_load_lut(crtc);
break;
@@ -2774,6 +2806,7 @@ static int dce_v10_0_crtc_mode_set(struct drm_crtc *crtc,
dce_v10_0_crtc_do_set_base(crtc, old_fb, x, y, 0);
amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
amdgpu_atombios_crtc_scaler_setup(crtc);
+ dce_v10_0_cursor_reset(crtc);
/* update the hw version fpr dpm */
amdgpu_crtc->hw_mode = *adjusted_mode;
@@ -3025,6 +3058,8 @@ static int dce_v10_0_hw_init(void *handle)
dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v10_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3039,6 +3074,8 @@ static int dce_v10_0_hw_fini(void *handle)
dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v10_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -3048,22 +3085,18 @@ static int dce_v10_0_suspend(void *handle)
amdgpu_atombios_scratch_regs_save(adev);
- dce_v10_0_hpd_fini(adev);
-
- return 0;
+ return dce_v10_0_hw_fini(handle);
}
static int dce_v10_0_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
- dce_v10_0_init_golden_registers(adev);
+ ret = dce_v10_0_hw_init(handle);
amdgpu_atombios_scratch_regs_restore(adev);
- /* init dig PHYs, disp eng pll */
- amdgpu_atombios_encoder_init_dig(adev);
- amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
/* turn on the BL */
if (adev->mode_info.bl_encoder) {
u8 bl_level = amdgpu_display_backlight_get_level(adev,
@@ -3072,10 +3105,7 @@ static int dce_v10_0_resume(void *handle)
bl_level);
}
- /* initialize hpd */
- dce_v10_0_hpd_init(adev);
-
- return 0;
+ return ret;
}
static bool dce_v10_0_is_idle(void *handle)
@@ -3267,37 +3297,20 @@ static int dce_v10_0_set_pageflip_irq_state(struct amdgpu_device *adev,
unsigned type,
enum amdgpu_interrupt_state state)
{
- u32 reg, reg_block;
- /* now deal with page flip IRQ */
- switch (type) {
- case AMDGPU_PAGEFLIP_IRQ_D1:
- reg_block = CRTC0_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D2:
- reg_block = CRTC1_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D3:
- reg_block = CRTC2_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D4:
- reg_block = CRTC3_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D5:
- reg_block = CRTC4_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D6:
- reg_block = CRTC5_REGISTER_OFFSET;
- break;
- default:
- DRM_ERROR("invalid pageflip crtc %d\n", type);
- return -EINVAL;
+ u32 reg;
+
+ if (type >= adev->mode_info.num_crtc) {
+ DRM_ERROR("invalid pageflip crtc %d\n", type);
+ return -EINVAL;
}
- reg = RREG32(mmGRPH_INTERRUPT_CONTROL + reg_block);
+ reg = RREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type]);
if (state == AMDGPU_IRQ_STATE_DISABLE)
- WREG32(mmGRPH_INTERRUPT_CONTROL + reg_block, reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
+ reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
else
- WREG32(mmGRPH_INTERRUPT_CONTROL + reg_block, reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
+ reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
return 0;
}
@@ -3306,7 +3319,6 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- int reg_block;
unsigned long flags;
unsigned crtc_id;
struct amdgpu_crtc *amdgpu_crtc;
@@ -3315,33 +3327,15 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev,
crtc_id = (entry->src_id - 8) >> 1;
amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
- /* ack the interrupt */
- switch(crtc_id){
- case AMDGPU_PAGEFLIP_IRQ_D1:
- reg_block = CRTC0_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D2:
- reg_block = CRTC1_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D3:
- reg_block = CRTC2_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D4:
- reg_block = CRTC3_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D5:
- reg_block = CRTC4_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D6:
- reg_block = CRTC5_REGISTER_OFFSET;
- break;
- default:
- DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
- return -EINVAL;
+ if (crtc_id >= adev->mode_info.num_crtc) {
+ DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
+ return -EINVAL;
}
- if (RREG32(mmGRPH_INTERRUPT_STATUS + reg_block) & GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
- WREG32(mmGRPH_INTERRUPT_STATUS + reg_block, GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
+ if (RREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id]) &
+ GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
+ WREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id],
+ GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
/* IRQ could occur when in initial stage */
if (amdgpu_crtc == NULL)
@@ -3369,7 +3363,6 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
- amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 6411e8244671..5af3721851d6 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -126,6 +126,13 @@ static const u32 cz_mgcg_cgcg_init[] =
mmXDMA_MEM_POWER_CNTL, 0x00000101, 0x00000000,
};
+static const u32 stoney_golden_settings_a11[] =
+{
+ mmCRTC_DOUBLE_BUFFER_CONTROL, 0x00010101, 0x00010000,
+ mmFBC_MISC, 0x1f311fff, 0x14302000,
+};
+
+
static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
{
switch (adev->asic_type) {
@@ -137,6 +144,11 @@ static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
cz_golden_settings_a11,
(const u32)ARRAY_SIZE(cz_golden_settings_a11));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_settings_a11,
+ (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
+ break;
default:
break;
}
@@ -233,6 +245,24 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
+static void dce_v11_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Enable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v11_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Disable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
/**
* dce_v11_0_page_flip - pageflip callback.
*
@@ -240,46 +270,22 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
* @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address)
*
- * Does the actual pageflip (evergreen+).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
- * Returns the current update pending status.
+ * Triggers the actual pageflip by updating the primary
+ * surface base address.
*/
static void dce_v11_0_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base)
{
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
- u32 tmp = RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset);
- int i;
-
- /* Lock the graphics update lock */
- tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
- WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
/* update the scanout addresses */
- WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
- upper_32_bits(crtc_base));
- WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- lower_32_bits(crtc_base));
-
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
+ /* writing to the low address triggers the update */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(crtc_base));
-
- /* Wait for update_pending to go high. */
- for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset) &
- GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK)
- break;
- udelay(1);
- }
- DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
- /* Unlock the lock, so double-buffering can take place inside vblank */
- tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
- WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
+ /* post the write */
+ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
static int dce_v11_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
@@ -2425,7 +2431,7 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc)
/* XXX need to determine what plls are available on each DCE11 part */
pll_in_use = amdgpu_pll_get_use_mask(crtc);
- if (adev->asic_type == CHIP_CARRIZO) {
+ if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) {
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
if (!(pll_in_use & (1 << ATOM_PPLL0)))
@@ -2476,26 +2482,19 @@ static void dce_v11_0_show_cursor(struct drm_crtc *crtc)
struct amdgpu_device *adev = crtc->dev->dev_private;
u32 tmp;
+ WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ upper_32_bits(amdgpu_crtc->cursor_addr));
+ WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ lower_32_bits(amdgpu_crtc->cursor_addr));
+
tmp = RREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset);
tmp = REG_SET_FIELD(tmp, CUR_CONTROL, CURSOR_EN, 1);
tmp = REG_SET_FIELD(tmp, CUR_CONTROL, CURSOR_MODE, 2);
WREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset, tmp);
}
-static void dce_v11_0_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
- uint64_t gpu_addr)
-{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- struct amdgpu_device *adev = crtc->dev->dev_private;
-
- WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
- upper_32_bits(gpu_addr));
- WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- lower_32_bits(gpu_addr));
-}
-
-static int dce_v11_0_crtc_cursor_move(struct drm_crtc *crtc,
- int x, int y)
+static int dce_v11_0_cursor_move_locked(struct drm_crtc *crtc,
+ int x, int y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct amdgpu_device *adev = crtc->dev->dev_private;
@@ -2515,26 +2514,40 @@ static int dce_v11_0_crtc_cursor_move(struct drm_crtc *crtc,
y = 0;
}
- dce_v11_0_lock_cursor(crtc, true);
WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
- dce_v11_0_lock_cursor(crtc, false);
+
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
return 0;
}
-static int dce_v11_0_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width,
- uint32_t height)
+static int dce_v11_0_crtc_cursor_move(struct drm_crtc *crtc,
+ int x, int y)
+{
+ int ret;
+
+ dce_v11_0_lock_cursor(crtc, true);
+ ret = dce_v11_0_cursor_move_locked(crtc, x, y);
+ dce_v11_0_lock_cursor(crtc, false);
+
+ return ret;
+}
+
+static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
+ struct drm_file *file_priv,
+ uint32_t handle,
+ uint32_t width,
+ uint32_t height,
+ int32_t hot_x,
+ int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct drm_gem_object *obj;
- struct amdgpu_bo *robj;
- uint64_t gpu_addr;
+ struct amdgpu_bo *aobj;
int ret;
if (!handle) {
@@ -2556,41 +2569,71 @@ static int dce_v11_0_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOENT;
}
- robj = gem_to_amdgpu_bo(obj);
- ret = amdgpu_bo_reserve(robj, false);
- if (unlikely(ret != 0))
- goto fail;
- ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM,
- 0, 0, &gpu_addr);
- amdgpu_bo_unreserve(robj);
- if (ret)
- goto fail;
+ aobj = gem_to_amdgpu_bo(obj);
+ ret = amdgpu_bo_reserve(aobj, false);
+ if (ret != 0) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
+
+ ret = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM, &amdgpu_crtc->cursor_addr);
+ amdgpu_bo_unreserve(aobj);
+ if (ret) {
+ DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
amdgpu_crtc->cursor_width = width;
amdgpu_crtc->cursor_height = height;
dce_v11_0_lock_cursor(crtc, true);
- dce_v11_0_set_cursor(crtc, obj, gpu_addr);
+
+ if (hot_x != amdgpu_crtc->cursor_hot_x ||
+ hot_y != amdgpu_crtc->cursor_hot_y) {
+ int x, y;
+
+ x = amdgpu_crtc->cursor_x + amdgpu_crtc->cursor_hot_x - hot_x;
+ y = amdgpu_crtc->cursor_y + amdgpu_crtc->cursor_hot_y - hot_y;
+
+ dce_v11_0_cursor_move_locked(crtc, x, y);
+
+ amdgpu_crtc->cursor_hot_x = hot_x;
+ amdgpu_crtc->cursor_hot_y = hot_y;
+ }
+
dce_v11_0_show_cursor(crtc);
dce_v11_0_lock_cursor(crtc, false);
unpin:
if (amdgpu_crtc->cursor_bo) {
- robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
- ret = amdgpu_bo_reserve(robj, false);
+ struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+ ret = amdgpu_bo_reserve(aobj, false);
if (likely(ret == 0)) {
- amdgpu_bo_unpin(robj);
- amdgpu_bo_unreserve(robj);
+ amdgpu_bo_unpin(aobj);
+ amdgpu_bo_unreserve(aobj);
}
drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo);
}
amdgpu_crtc->cursor_bo = obj;
return 0;
-fail:
- drm_gem_object_unreference_unlocked(obj);
+}
- return ret;
+static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
+{
+ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+ if (amdgpu_crtc->cursor_bo) {
+ dce_v11_0_lock_cursor(crtc, true);
+
+ dce_v11_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
+ amdgpu_crtc->cursor_y);
+
+ dce_v11_0_show_cursor(crtc);
+
+ dce_v11_0_lock_cursor(crtc, false);
+ }
}
static void dce_v11_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
@@ -2618,7 +2661,7 @@ static void dce_v11_0_crtc_destroy(struct drm_crtc *crtc)
}
static const struct drm_crtc_funcs dce_v11_0_crtc_funcs = {
- .cursor_set = dce_v11_0_crtc_cursor_set,
+ .cursor_set2 = dce_v11_0_crtc_cursor_set2,
.cursor_move = dce_v11_0_crtc_cursor_move,
.gamma_set = dce_v11_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config,
@@ -2640,9 +2683,10 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v11_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v11_0_vga_enable(crtc, false);
- /* Make sure VBLANK interrupt is still enabled */
+ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
+ amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v11_0_crtc_load_lut(crtc);
break;
@@ -2751,6 +2795,7 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc,
dce_v11_0_crtc_do_set_base(crtc, old_fb, x, y, 0);
amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
amdgpu_atombios_crtc_scaler_setup(crtc);
+ dce_v11_0_cursor_reset(crtc);
/* update the hw version fpr dpm */
amdgpu_crtc->hw_mode = *adjusted_mode;
@@ -2888,7 +2933,12 @@ static int dce_v11_0_early_init(void *handle)
switch (adev->asic_type) {
case CHIP_CARRIZO:
- adev->mode_info.num_crtc = 4;
+ adev->mode_info.num_crtc = 3;
+ adev->mode_info.num_hpd = 6;
+ adev->mode_info.num_dig = 9;
+ break;
+ case CHIP_STONEY:
+ adev->mode_info.num_crtc = 2;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9;
break;
@@ -2990,6 +3040,7 @@ static int dce_v11_0_hw_init(void *handle)
dce_v11_0_init_golden_registers(adev);
/* init dig PHYs, disp eng pll */
+ amdgpu_atombios_crtc_powergate_init(adev);
amdgpu_atombios_encoder_init_dig(adev);
amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
@@ -3000,6 +3051,8 @@ static int dce_v11_0_hw_init(void *handle)
dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v11_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3014,6 +3067,8 @@ static int dce_v11_0_hw_fini(void *handle)
dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v11_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -3023,23 +3078,18 @@ static int dce_v11_0_suspend(void *handle)
amdgpu_atombios_scratch_regs_save(adev);
- dce_v11_0_hpd_fini(adev);
-
- return 0;
+ return dce_v11_0_hw_fini(handle);
}
static int dce_v11_0_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
- dce_v11_0_init_golden_registers(adev);
+ ret = dce_v11_0_hw_init(handle);
amdgpu_atombios_scratch_regs_restore(adev);
- /* init dig PHYs, disp eng pll */
- amdgpu_atombios_crtc_powergate_init(adev);
- amdgpu_atombios_encoder_init_dig(adev);
- amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
/* turn on the BL */
if (adev->mode_info.bl_encoder) {
u8 bl_level = amdgpu_display_backlight_get_level(adev,
@@ -3048,10 +3098,7 @@ static int dce_v11_0_resume(void *handle)
bl_level);
}
- /* initialize hpd */
- dce_v11_0_hpd_init(adev);
-
- return 0;
+ return ret;
}
static bool dce_v11_0_is_idle(void *handle)
@@ -3243,37 +3290,20 @@ static int dce_v11_0_set_pageflip_irq_state(struct amdgpu_device *adev,
unsigned type,
enum amdgpu_interrupt_state state)
{
- u32 reg, reg_block;
- /* now deal with page flip IRQ */
- switch (type) {
- case AMDGPU_PAGEFLIP_IRQ_D1:
- reg_block = CRTC0_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D2:
- reg_block = CRTC1_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D3:
- reg_block = CRTC2_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D4:
- reg_block = CRTC3_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D5:
- reg_block = CRTC4_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D6:
- reg_block = CRTC5_REGISTER_OFFSET;
- break;
- default:
- DRM_ERROR("invalid pageflip crtc %d\n", type);
- return -EINVAL;
+ u32 reg;
+
+ if (type >= adev->mode_info.num_crtc) {
+ DRM_ERROR("invalid pageflip crtc %d\n", type);
+ return -EINVAL;
}
- reg = RREG32(mmGRPH_INTERRUPT_CONTROL + reg_block);
+ reg = RREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type]);
if (state == AMDGPU_IRQ_STATE_DISABLE)
- WREG32(mmGRPH_INTERRUPT_CONTROL + reg_block, reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
+ reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
else
- WREG32(mmGRPH_INTERRUPT_CONTROL + reg_block, reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
+ reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
return 0;
}
@@ -3282,7 +3312,6 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- int reg_block;
unsigned long flags;
unsigned crtc_id;
struct amdgpu_crtc *amdgpu_crtc;
@@ -3291,33 +3320,15 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev,
crtc_id = (entry->src_id - 8) >> 1;
amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
- /* ack the interrupt */
- switch(crtc_id){
- case AMDGPU_PAGEFLIP_IRQ_D1:
- reg_block = CRTC0_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D2:
- reg_block = CRTC1_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D3:
- reg_block = CRTC2_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D4:
- reg_block = CRTC3_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D5:
- reg_block = CRTC4_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D6:
- reg_block = CRTC5_REGISTER_OFFSET;
- break;
- default:
- DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
- return -EINVAL;
+ if (crtc_id >= adev->mode_info.num_crtc) {
+ DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
+ return -EINVAL;
}
- if (RREG32(mmGRPH_INTERRUPT_STATUS + reg_block) & GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
- WREG32(mmGRPH_INTERRUPT_STATUS + reg_block, GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
+ if (RREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id]) &
+ GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
+ WREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id],
+ GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
/* IRQ could occur when in initial stage */
if(amdgpu_crtc == NULL)
@@ -3345,7 +3356,6 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
- amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index c86911c2ea2a..4f7b49a6dc50 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -204,6 +204,24 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
+static void dce_v8_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Enable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v8_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Disable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
/**
* dce_v8_0_page_flip - pageflip callback.
*
@@ -211,46 +229,22 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
* @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address)
*
- * Does the actual pageflip (evergreen+).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
- * Returns the current update pending status.
+ * Triggers the actual pageflip by updating the primary
+ * surface base address.
*/
static void dce_v8_0_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base)
{
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
- u32 tmp = RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset);
- int i;
-
- /* Lock the graphics update lock */
- tmp |= GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK;
- WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
-
- /* update the scanout addresses */
- WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
- upper_32_bits(crtc_base));
- WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- (u32)crtc_base);
+ /* update the primary scanout addresses */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
+ /* writing to the low address triggers the update */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- (u32)crtc_base);
-
- /* Wait for update_pending to go high. */
- for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset) &
- GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK)
- break;
- udelay(1);
- }
- DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
- /* Unlock the lock, so double-buffering can take place inside vblank */
- tmp &= ~GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK;
- WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
+ lower_32_bits(crtc_base));
+ /* post the write */
+ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
static int dce_v8_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
@@ -2411,26 +2405,19 @@ static void dce_v8_0_show_cursor(struct drm_crtc *crtc)
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct amdgpu_device *adev = crtc->dev->dev_private;
+ WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ upper_32_bits(amdgpu_crtc->cursor_addr));
+ WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ lower_32_bits(amdgpu_crtc->cursor_addr));
+
WREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset,
CUR_CONTROL__CURSOR_EN_MASK |
(CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) |
(CURSOR_URGENT_1_2 << CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT));
}
-static void dce_v8_0_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
- uint64_t gpu_addr)
-{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- struct amdgpu_device *adev = crtc->dev->dev_private;
-
- WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
- upper_32_bits(gpu_addr));
- WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- gpu_addr & 0xffffffff);
-}
-
-static int dce_v8_0_crtc_cursor_move(struct drm_crtc *crtc,
- int x, int y)
+static int dce_v8_0_cursor_move_locked(struct drm_crtc *crtc,
+ int x, int y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct amdgpu_device *adev = crtc->dev->dev_private;
@@ -2450,26 +2437,40 @@ static int dce_v8_0_crtc_cursor_move(struct drm_crtc *crtc,
y = 0;
}
- dce_v8_0_lock_cursor(crtc, true);
WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
- dce_v8_0_lock_cursor(crtc, false);
+
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
return 0;
}
-static int dce_v8_0_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width,
- uint32_t height)
+static int dce_v8_0_crtc_cursor_move(struct drm_crtc *crtc,
+ int x, int y)
+{
+ int ret;
+
+ dce_v8_0_lock_cursor(crtc, true);
+ ret = dce_v8_0_cursor_move_locked(crtc, x, y);
+ dce_v8_0_lock_cursor(crtc, false);
+
+ return ret;
+}
+
+static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
+ struct drm_file *file_priv,
+ uint32_t handle,
+ uint32_t width,
+ uint32_t height,
+ int32_t hot_x,
+ int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct drm_gem_object *obj;
- struct amdgpu_bo *robj;
- uint64_t gpu_addr;
+ struct amdgpu_bo *aobj;
int ret;
if (!handle) {
@@ -2491,41 +2492,71 @@ static int dce_v8_0_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOENT;
}
- robj = gem_to_amdgpu_bo(obj);
- ret = amdgpu_bo_reserve(robj, false);
- if (unlikely(ret != 0))
- goto fail;
- ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM,
- 0, 0, &gpu_addr);
- amdgpu_bo_unreserve(robj);
- if (ret)
- goto fail;
+ aobj = gem_to_amdgpu_bo(obj);
+ ret = amdgpu_bo_reserve(aobj, false);
+ if (ret != 0) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
+
+ ret = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM, &amdgpu_crtc->cursor_addr);
+ amdgpu_bo_unreserve(aobj);
+ if (ret) {
+ DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
amdgpu_crtc->cursor_width = width;
amdgpu_crtc->cursor_height = height;
dce_v8_0_lock_cursor(crtc, true);
- dce_v8_0_set_cursor(crtc, obj, gpu_addr);
+
+ if (hot_x != amdgpu_crtc->cursor_hot_x ||
+ hot_y != amdgpu_crtc->cursor_hot_y) {
+ int x, y;
+
+ x = amdgpu_crtc->cursor_x + amdgpu_crtc->cursor_hot_x - hot_x;
+ y = amdgpu_crtc->cursor_y + amdgpu_crtc->cursor_hot_y - hot_y;
+
+ dce_v8_0_cursor_move_locked(crtc, x, y);
+
+ amdgpu_crtc->cursor_hot_x = hot_x;
+ amdgpu_crtc->cursor_hot_y = hot_y;
+ }
+
dce_v8_0_show_cursor(crtc);
dce_v8_0_lock_cursor(crtc, false);
unpin:
if (amdgpu_crtc->cursor_bo) {
- robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
- ret = amdgpu_bo_reserve(robj, false);
+ struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+ ret = amdgpu_bo_reserve(aobj, false);
if (likely(ret == 0)) {
- amdgpu_bo_unpin(robj);
- amdgpu_bo_unreserve(robj);
+ amdgpu_bo_unpin(aobj);
+ amdgpu_bo_unreserve(aobj);
}
drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo);
}
amdgpu_crtc->cursor_bo = obj;
return 0;
-fail:
- drm_gem_object_unreference_unlocked(obj);
+}
- return ret;
+static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
+{
+ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+ if (amdgpu_crtc->cursor_bo) {
+ dce_v8_0_lock_cursor(crtc, true);
+
+ dce_v8_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
+ amdgpu_crtc->cursor_y);
+
+ dce_v8_0_show_cursor(crtc);
+
+ dce_v8_0_lock_cursor(crtc, false);
+ }
}
static void dce_v8_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
@@ -2553,7 +2584,7 @@ static void dce_v8_0_crtc_destroy(struct drm_crtc *crtc)
}
static const struct drm_crtc_funcs dce_v8_0_crtc_funcs = {
- .cursor_set = dce_v8_0_crtc_cursor_set,
+ .cursor_set2 = dce_v8_0_crtc_cursor_set2,
.cursor_move = dce_v8_0_crtc_cursor_move,
.gamma_set = dce_v8_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config,
@@ -2575,9 +2606,10 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v8_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v8_0_vga_enable(crtc, false);
- /* Make sure VBLANK interrupt is still enabled */
+ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
+ amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v8_0_crtc_load_lut(crtc);
break;
@@ -2693,6 +2725,7 @@ static int dce_v8_0_crtc_mode_set(struct drm_crtc *crtc,
dce_v8_0_crtc_do_set_base(crtc, old_fb, x, y, 0);
amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
amdgpu_atombios_crtc_scaler_setup(crtc);
+ dce_v8_0_cursor_reset(crtc);
/* update the hw version fpr dpm */
amdgpu_crtc->hw_mode = *adjusted_mode;
@@ -2933,6 +2966,8 @@ static int dce_v8_0_hw_init(void *handle)
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v8_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -2947,6 +2982,8 @@ static int dce_v8_0_hw_fini(void *handle)
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v8_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -2956,20 +2993,18 @@ static int dce_v8_0_suspend(void *handle)
amdgpu_atombios_scratch_regs_save(adev);
- dce_v8_0_hpd_fini(adev);
-
- return 0;
+ return dce_v8_0_hw_fini(handle);
}
static int dce_v8_0_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ ret = dce_v8_0_hw_init(handle);
amdgpu_atombios_scratch_regs_restore(adev);
- /* init dig PHYs, disp eng pll */
- amdgpu_atombios_encoder_init_dig(adev);
- amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
/* turn on the BL */
if (adev->mode_info.bl_encoder) {
u8 bl_level = amdgpu_display_backlight_get_level(adev,
@@ -2978,10 +3013,7 @@ static int dce_v8_0_resume(void *handle)
bl_level);
}
- /* initialize hpd */
- dce_v8_0_hpd_init(adev);
-
- return 0;
+ return ret;
}
static bool dce_v8_0_is_idle(void *handle)
@@ -3274,37 +3306,20 @@ static int dce_v8_0_set_pageflip_interrupt_state(struct amdgpu_device *adev,
unsigned type,
enum amdgpu_interrupt_state state)
{
- u32 reg, reg_block;
- /* now deal with page flip IRQ */
- switch (type) {
- case AMDGPU_PAGEFLIP_IRQ_D1:
- reg_block = CRTC0_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D2:
- reg_block = CRTC1_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D3:
- reg_block = CRTC2_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D4:
- reg_block = CRTC3_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D5:
- reg_block = CRTC4_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D6:
- reg_block = CRTC5_REGISTER_OFFSET;
- break;
- default:
- DRM_ERROR("invalid pageflip crtc %d\n", type);
- return -EINVAL;
+ u32 reg;
+
+ if (type >= adev->mode_info.num_crtc) {
+ DRM_ERROR("invalid pageflip crtc %d\n", type);
+ return -EINVAL;
}
- reg = RREG32(mmGRPH_INTERRUPT_CONTROL + reg_block);
+ reg = RREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type]);
if (state == AMDGPU_IRQ_STATE_DISABLE)
- WREG32(mmGRPH_INTERRUPT_CONTROL + reg_block, reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
+ reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
else
- WREG32(mmGRPH_INTERRUPT_CONTROL + reg_block, reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
+ reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
return 0;
}
@@ -3313,7 +3328,6 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- int reg_block;
unsigned long flags;
unsigned crtc_id;
struct amdgpu_crtc *amdgpu_crtc;
@@ -3322,33 +3336,15 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev,
crtc_id = (entry->src_id - 8) >> 1;
amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
- /* ack the interrupt */
- switch(crtc_id){
- case AMDGPU_PAGEFLIP_IRQ_D1:
- reg_block = CRTC0_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D2:
- reg_block = CRTC1_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D3:
- reg_block = CRTC2_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D4:
- reg_block = CRTC3_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D5:
- reg_block = CRTC4_REGISTER_OFFSET;
- break;
- case AMDGPU_PAGEFLIP_IRQ_D6:
- reg_block = CRTC5_REGISTER_OFFSET;
- break;
- default:
- DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
- return -EINVAL;
+ if (crtc_id >= adev->mode_info.num_crtc) {
+ DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
+ return -EINVAL;
}
- if (RREG32(mmGRPH_INTERRUPT_STATUS + reg_block) & GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
- WREG32(mmGRPH_INTERRUPT_STATUS + reg_block, GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
+ if (RREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id]) &
+ GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
+ WREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id],
+ GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
/* IRQ could occur when in initial stage */
if (amdgpu_crtc == NULL)
@@ -3376,7 +3372,6 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
- amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index e992bf2ff66c..72793f93e2fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -5542,24 +5542,6 @@ const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
.set_powergating_state = gfx_v7_0_set_powergating_state,
};
-/**
- * gfx_v7_0_ring_is_lockup - check if the 3D engine is locked up
- *
- * @adev: amdgpu_device pointer
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the 3D engine is locked up (CIK).
- * Returns true if the engine is locked, false if not.
- */
-static bool gfx_v7_0_ring_is_lockup(struct amdgpu_ring *ring)
-{
- if (gfx_v7_0_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
.get_rptr = gfx_v7_0_ring_get_rptr_gfx,
.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
@@ -5573,7 +5555,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
.emit_hdp_flush = gfx_v7_0_ring_emit_hdp_flush,
.test_ring = gfx_v7_0_ring_test_ring,
.test_ib = gfx_v7_0_ring_test_ib,
- .is_lockup = gfx_v7_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
@@ -5590,7 +5571,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
.emit_hdp_flush = gfx_v7_0_ring_emit_hdp_flush,
.test_ring = gfx_v7_0_ring_test_ring,
.test_ib = gfx_v7_0_ring_test_ib,
- .is_lockup = gfx_v7_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index cb4f68f53f24..e1dcab98e249 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -73,6 +73,12 @@ MODULE_FIRMWARE("amdgpu/carrizo_mec.bin");
MODULE_FIRMWARE("amdgpu/carrizo_mec2.bin");
MODULE_FIRMWARE("amdgpu/carrizo_rlc.bin");
+MODULE_FIRMWARE("amdgpu/stoney_ce.bin");
+MODULE_FIRMWARE("amdgpu/stoney_pfp.bin");
+MODULE_FIRMWARE("amdgpu/stoney_me.bin");
+MODULE_FIRMWARE("amdgpu/stoney_mec.bin");
+MODULE_FIRMWARE("amdgpu/stoney_rlc.bin");
+
MODULE_FIRMWARE("amdgpu/tonga_ce.bin");
MODULE_FIRMWARE("amdgpu/tonga_pfp.bin");
MODULE_FIRMWARE("amdgpu/tonga_me.bin");
@@ -229,11 +235,13 @@ static const u32 fiji_golden_common_all[] =
mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
mmPA_SC_RASTER_CONFIG, 0xffffffff, 0x3a00161a,
mmPA_SC_RASTER_CONFIG_1, 0xffffffff, 0x0000002e,
- mmGB_ADDR_CONFIG, 0xffffffff, 0x12011003,
+ mmGB_ADDR_CONFIG, 0xffffffff, 0x22011003,
mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800,
mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800,
mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF,
- mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF
+ mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF,
+ mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+ mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x00000009,
};
static const u32 golden_settings_fiji_a10[] =
@@ -241,18 +249,19 @@ static const u32 golden_settings_fiji_a10[] =
mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
mmDB_DEBUG2, 0xf00fffff, 0x00000400,
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
- mmPA_SC_FIFO_DEPTH_CNTL, 0x000003ff, 0x00000100,
mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+ mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
+ mmSQ_RANDOM_WAVE_PRI, 0x001fffff, 0x000006fd,
mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
- mmTCC_CTRL, 0x00100000, 0xf30fff7f,
+ mmTCC_CTRL, 0x00100000, 0xf31fff7f,
+ mmTCC_EXE_DISABLE, 0x00000002, 0x00000002,
mmTCP_ADDR_CONFIG, 0x000003ff, 0x000000ff,
- mmTCP_CHAN_STEER_HI, 0xffffffff, 0x7d6cf5e4,
- mmTCP_CHAN_STEER_LO, 0xffffffff, 0x3928b1a0,
+ mmVGT_RESET_DEBUG, 0x00000004, 0x00000004,
};
static const u32 fiji_mgcg_cgcg_init[] =
{
- mmRLC_CGTT_MGCG_OVERRIDE, 0xffffffff, 0xffffffc0,
+ mmRLC_CGTT_MGCG_OVERRIDE, 0xffffffff, 0xffffffff,
mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
mmCB_CGTT_SCLK_CTRL, 0xffffffff, 0x00000100,
mmCGTT_BCI_CLK_CTRL, 0xffffffff, 0x00000100,
@@ -493,6 +502,42 @@ static const u32 cz_mgcg_cgcg_init[] =
mmCP_MEM_SLP_CNTL, 0x00000001, 0x00000001,
};
+static const u32 stoney_golden_settings_a11[] =
+{
+ mmDB_DEBUG2, 0xf00fffff, 0x00000400,
+ mmGB_GPU_ID, 0x0000000f, 0x00000000,
+ mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
+ mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+ mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
+ mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
+ mmTCC_CTRL, 0x00100000, 0xf31fff7f,
+ mmTCC_EXE_DISABLE, 0x00000002, 0x00000002,
+ mmTCP_ADDR_CONFIG, 0x0000000f, 0x000000f1,
+ mmTCP_CHAN_STEER_LO, 0xffffffff, 0x10101010,
+};
+
+static const u32 stoney_golden_common_all[] =
+{
+ mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+ mmPA_SC_RASTER_CONFIG, 0xffffffff, 0x00000000,
+ mmPA_SC_RASTER_CONFIG_1, 0xffffffff, 0x00000000,
+ mmGB_ADDR_CONFIG, 0xffffffff, 0x12010001,
+ mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800,
+ mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800,
+ mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF,
+ mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF,
+};
+
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+ mmRLC_CGCG_CGLS_CTRL, 0xffffffff, 0x0020003f,
+ mmCP_MEM_SLP_CNTL, 0xffffffff, 0x00020201,
+ mmRLC_MEM_SLP_CNTL, 0xffffffff, 0x00020201,
+ mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96940200,
+ mmATC_MISC_CG, 0xffffffff, 0x000c0200,
+};
+
static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev);
static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev);
static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev);
@@ -545,6 +590,17 @@ static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
cz_golden_common_all,
(const u32)ARRAY_SIZE(cz_golden_common_all));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_settings_a11,
+ (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_common_all,
+ (const u32)ARRAY_SIZE(stoney_golden_common_all));
+ break;
default:
break;
}
@@ -691,6 +747,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
case CHIP_FIJI:
chip_name = "fiji";
break;
+ case CHIP_STONEY:
+ chip_name = "stoney";
+ break;
default:
BUG();
}
@@ -748,21 +807,23 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
- if (!err) {
- err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
- if (err)
- goto out;
- cp_hdr = (const struct gfx_firmware_header_v1_0 *)
- adev->gfx.mec2_fw->data;
- adev->gfx.mec2_fw_version = le32_to_cpu(
- cp_hdr->header.ucode_version);
- adev->gfx.mec2_feature_version = le32_to_cpu(
- cp_hdr->ucode_feature_version);
- } else {
- err = 0;
- adev->gfx.mec2_fw = NULL;
+ if (adev->asic_type != CHIP_STONEY) {
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
+ err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ if (!err) {
+ err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
+ if (err)
+ goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)
+ adev->gfx.mec2_fw->data;
+ adev->gfx.mec2_fw_version =
+ le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.mec2_feature_version =
+ le32_to_cpu(cp_hdr->ucode_feature_version);
+ } else {
+ err = 0;
+ adev->gfx.mec2_fw = NULL;
+ }
}
if (adev->firmware.smu_load) {
@@ -903,6 +964,232 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
return 0;
}
+static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
+{
+ u32 gb_addr_config;
+ u32 mc_shared_chmap, mc_arb_ramcfg;
+ u32 dimm00_addr_map, dimm01_addr_map, dimm10_addr_map, dimm11_addr_map;
+ u32 tmp;
+
+ switch (adev->asic_type) {
+ case CHIP_TOPAZ:
+ adev->gfx.config.max_shader_engines = 1;
+ adev->gfx.config.max_tile_pipes = 2;
+ adev->gfx.config.max_cu_per_sh = 6;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 2;
+ adev->gfx.config.max_texture_channel_caches = 2;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 32;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = TOPAZ_GB_ADDR_CONFIG_GOLDEN;
+ break;
+ case CHIP_FIJI:
+ adev->gfx.config.max_shader_engines = 4;
+ adev->gfx.config.max_tile_pipes = 16;
+ adev->gfx.config.max_cu_per_sh = 16;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 4;
+ adev->gfx.config.max_texture_channel_caches = 16;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 32;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
+ break;
+ case CHIP_TONGA:
+ adev->gfx.config.max_shader_engines = 4;
+ adev->gfx.config.max_tile_pipes = 8;
+ adev->gfx.config.max_cu_per_sh = 8;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 2;
+ adev->gfx.config.max_texture_channel_caches = 8;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 32;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
+ break;
+ case CHIP_CARRIZO:
+ adev->gfx.config.max_shader_engines = 1;
+ adev->gfx.config.max_tile_pipes = 2;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 2;
+
+ switch (adev->pdev->revision) {
+ case 0xc4:
+ case 0x84:
+ case 0xc8:
+ case 0xcc:
+ case 0xe1:
+ case 0xe3:
+ /* B10 */
+ adev->gfx.config.max_cu_per_sh = 8;
+ break;
+ case 0xc5:
+ case 0x81:
+ case 0x85:
+ case 0xc9:
+ case 0xcd:
+ case 0xe2:
+ case 0xe4:
+ /* B8 */
+ adev->gfx.config.max_cu_per_sh = 6;
+ break;
+ case 0xc6:
+ case 0xca:
+ case 0xce:
+ case 0x88:
+ /* B6 */
+ adev->gfx.config.max_cu_per_sh = 6;
+ break;
+ case 0xc7:
+ case 0x87:
+ case 0xcb:
+ case 0xe5:
+ case 0x89:
+ default:
+ /* B4 */
+ adev->gfx.config.max_cu_per_sh = 4;
+ break;
+ }
+
+ adev->gfx.config.max_texture_channel_caches = 2;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 32;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = CARRIZO_GB_ADDR_CONFIG_GOLDEN;
+ break;
+ case CHIP_STONEY:
+ adev->gfx.config.max_shader_engines = 1;
+ adev->gfx.config.max_tile_pipes = 2;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 1;
+
+ switch (adev->pdev->revision) {
+ case 0xc0:
+ case 0xc1:
+ case 0xc2:
+ case 0xc4:
+ case 0xc8:
+ case 0xc9:
+ adev->gfx.config.max_cu_per_sh = 3;
+ break;
+ case 0xd0:
+ case 0xd1:
+ case 0xd2:
+ default:
+ adev->gfx.config.max_cu_per_sh = 2;
+ break;
+ }
+
+ adev->gfx.config.max_texture_channel_caches = 2;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 16;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = CARRIZO_GB_ADDR_CONFIG_GOLDEN;
+ break;
+ default:
+ adev->gfx.config.max_shader_engines = 2;
+ adev->gfx.config.max_tile_pipes = 4;
+ adev->gfx.config.max_cu_per_sh = 2;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 2;
+ adev->gfx.config.max_texture_channel_caches = 4;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 32;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
+ break;
+ }
+
+ mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
+ adev->gfx.config.mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
+ mc_arb_ramcfg = adev->gfx.config.mc_arb_ramcfg;
+
+ adev->gfx.config.num_tile_pipes = adev->gfx.config.max_tile_pipes;
+ adev->gfx.config.mem_max_burst_length_bytes = 256;
+ if (adev->flags & AMD_IS_APU) {
+ /* Get memory bank mapping mode. */
+ tmp = RREG32(mmMC_FUS_DRAM0_BANK_ADDR_MAPPING);
+ dimm00_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM0_BANK_ADDR_MAPPING, DIMM0ADDRMAP);
+ dimm01_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM0_BANK_ADDR_MAPPING, DIMM1ADDRMAP);
+
+ tmp = RREG32(mmMC_FUS_DRAM1_BANK_ADDR_MAPPING);
+ dimm10_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM1_BANK_ADDR_MAPPING, DIMM0ADDRMAP);
+ dimm11_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM1_BANK_ADDR_MAPPING, DIMM1ADDRMAP);
+
+ /* Validate settings in case only one DIMM installed. */
+ if ((dimm00_addr_map == 0) || (dimm00_addr_map == 3) || (dimm00_addr_map == 4) || (dimm00_addr_map > 12))
+ dimm00_addr_map = 0;
+ if ((dimm01_addr_map == 0) || (dimm01_addr_map == 3) || (dimm01_addr_map == 4) || (dimm01_addr_map > 12))
+ dimm01_addr_map = 0;
+ if ((dimm10_addr_map == 0) || (dimm10_addr_map == 3) || (dimm10_addr_map == 4) || (dimm10_addr_map > 12))
+ dimm10_addr_map = 0;
+ if ((dimm11_addr_map == 0) || (dimm11_addr_map == 3) || (dimm11_addr_map == 4) || (dimm11_addr_map > 12))
+ dimm11_addr_map = 0;
+
+ /* If DIMM Addr map is 8GB, ROW size should be 2KB. Otherwise 1KB. */
+ /* If ROW size(DIMM1) != ROW size(DMIMM0), ROW size should be larger one. */
+ if ((dimm00_addr_map == 11) || (dimm01_addr_map == 11) || (dimm10_addr_map == 11) || (dimm11_addr_map == 11))
+ adev->gfx.config.mem_row_size_in_kb = 2;
+ else
+ adev->gfx.config.mem_row_size_in_kb = 1;
+ } else {
+ tmp = REG_GET_FIELD(mc_arb_ramcfg, MC_ARB_RAMCFG, NOOFCOLS);
+ adev->gfx.config.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
+ if (adev->gfx.config.mem_row_size_in_kb > 4)
+ adev->gfx.config.mem_row_size_in_kb = 4;
+ }
+
+ adev->gfx.config.shader_engine_tile_size = 32;
+ adev->gfx.config.num_gpus = 1;
+ adev->gfx.config.multi_gpu_tile_size = 64;
+
+ /* fix up row size */
+ switch (adev->gfx.config.mem_row_size_in_kb) {
+ case 1:
+ default:
+ gb_addr_config = REG_SET_FIELD(gb_addr_config, GB_ADDR_CONFIG, ROW_SIZE, 0);
+ break;
+ case 2:
+ gb_addr_config = REG_SET_FIELD(gb_addr_config, GB_ADDR_CONFIG, ROW_SIZE, 1);
+ break;
+ case 4:
+ gb_addr_config = REG_SET_FIELD(gb_addr_config, GB_ADDR_CONFIG, ROW_SIZE, 2);
+ break;
+ }
+ adev->gfx.config.gb_addr_config = gb_addr_config;
+}
+
static int gfx_v8_0_sw_init(void *handle)
{
int i, r;
@@ -1010,6 +1297,8 @@ static int gfx_v8_0_sw_init(void *handle)
adev->gfx.ce_ram_size = 0x8000;
+ gfx_v8_0_gpu_early_init(adev);
+
return 0;
}
@@ -1319,6 +1608,296 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
}
case CHIP_FIJI:
+ for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+ switch (reg_offset) {
+ case 0:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 1:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 2:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 3:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 4:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 5:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 6:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 7:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 8:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16));
+ break;
+ case 9:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 10:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 11:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 12:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 13:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 14:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 15:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 16:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 17:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 18:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 19:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 20:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 21:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 22:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 23:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 24:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 25:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 26:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 27:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 28:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 29:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 30:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ default:
+ gb_tile_moden = 0;
+ break;
+ }
+ adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
+ }
+ for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
+ switch (reg_offset) {
+ case 0:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 1:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 2:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 3:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 4:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 5:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 6:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 8:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 9:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 10:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 11:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 12:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 13:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 14:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+ NUM_BANKS(ADDR_SURF_4_BANK));
+ break;
+ case 7:
+ /* unused idx */
+ continue;
+ default:
+ gb_tile_moden = 0;
+ break;
+ }
+ adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
+ }
+ break;
case CHIP_TONGA:
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
switch (reg_offset) {
@@ -1610,6 +2189,273 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
}
break;
+ case CHIP_STONEY:
+ for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+ switch (reg_offset) {
+ case 0:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 1:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 2:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 3:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 4:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 5:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 6:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 8:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+ PIPE_CONFIG(ADDR_SURF_P2));
+ break;
+ case 9:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 10:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 11:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 13:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 14:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 15:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 16:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 18:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 19:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 20:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 21:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 22:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 24:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 25:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 26:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 27:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 28:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 29:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 7:
+ case 12:
+ case 17:
+ case 23:
+ /* unused idx */
+ continue;
+ default:
+ gb_tile_moden = 0;
+ break;
+ };
+ adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
+ }
+ for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
+ switch (reg_offset) {
+ case 0:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 1:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 2:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 3:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 4:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 5:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 6:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 8:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 9:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 10:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 11:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 12:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 13:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 14:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 7:
+ /* unused idx */
+ continue;
+ default:
+ gb_tile_moden = 0;
+ break;
+ };
+ adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
+ }
+ break;
case CHIP_CARRIZO:
default:
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
@@ -2043,203 +2889,23 @@ static void gfx_v8_0_init_compute_vmid(struct amdgpu_device *adev)
static void gfx_v8_0_gpu_init(struct amdgpu_device *adev)
{
- u32 gb_addr_config;
- u32 mc_shared_chmap, mc_arb_ramcfg;
- u32 dimm00_addr_map, dimm01_addr_map, dimm10_addr_map, dimm11_addr_map;
u32 tmp;
int i;
- switch (adev->asic_type) {
- case CHIP_TOPAZ:
- adev->gfx.config.max_shader_engines = 1;
- adev->gfx.config.max_tile_pipes = 2;
- adev->gfx.config.max_cu_per_sh = 6;
- adev->gfx.config.max_sh_per_se = 1;
- adev->gfx.config.max_backends_per_se = 2;
- adev->gfx.config.max_texture_channel_caches = 2;
- adev->gfx.config.max_gprs = 256;
- adev->gfx.config.max_gs_threads = 32;
- adev->gfx.config.max_hw_contexts = 8;
-
- adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
- adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
- adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
- adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
- gb_addr_config = TOPAZ_GB_ADDR_CONFIG_GOLDEN;
- break;
- case CHIP_FIJI:
- adev->gfx.config.max_shader_engines = 4;
- adev->gfx.config.max_tile_pipes = 16;
- adev->gfx.config.max_cu_per_sh = 16;
- adev->gfx.config.max_sh_per_se = 1;
- adev->gfx.config.max_backends_per_se = 4;
- adev->gfx.config.max_texture_channel_caches = 8;
- adev->gfx.config.max_gprs = 256;
- adev->gfx.config.max_gs_threads = 32;
- adev->gfx.config.max_hw_contexts = 8;
-
- adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
- adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
- adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
- adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
- gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
- break;
- case CHIP_TONGA:
- adev->gfx.config.max_shader_engines = 4;
- adev->gfx.config.max_tile_pipes = 8;
- adev->gfx.config.max_cu_per_sh = 8;
- adev->gfx.config.max_sh_per_se = 1;
- adev->gfx.config.max_backends_per_se = 2;
- adev->gfx.config.max_texture_channel_caches = 8;
- adev->gfx.config.max_gprs = 256;
- adev->gfx.config.max_gs_threads = 32;
- adev->gfx.config.max_hw_contexts = 8;
-
- adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
- adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
- adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
- adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
- gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
- break;
- case CHIP_CARRIZO:
- adev->gfx.config.max_shader_engines = 1;
- adev->gfx.config.max_tile_pipes = 2;
- adev->gfx.config.max_sh_per_se = 1;
- adev->gfx.config.max_backends_per_se = 2;
-
- switch (adev->pdev->revision) {
- case 0xc4:
- case 0x84:
- case 0xc8:
- case 0xcc:
- /* B10 */
- adev->gfx.config.max_cu_per_sh = 8;
- break;
- case 0xc5:
- case 0x81:
- case 0x85:
- case 0xc9:
- case 0xcd:
- /* B8 */
- adev->gfx.config.max_cu_per_sh = 6;
- break;
- case 0xc6:
- case 0xca:
- case 0xce:
- /* B6 */
- adev->gfx.config.max_cu_per_sh = 6;
- break;
- case 0xc7:
- case 0x87:
- case 0xcb:
- default:
- /* B4 */
- adev->gfx.config.max_cu_per_sh = 4;
- break;
- }
-
- adev->gfx.config.max_texture_channel_caches = 2;
- adev->gfx.config.max_gprs = 256;
- adev->gfx.config.max_gs_threads = 32;
- adev->gfx.config.max_hw_contexts = 8;
-
- adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
- adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
- adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
- adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
- gb_addr_config = CARRIZO_GB_ADDR_CONFIG_GOLDEN;
- break;
- default:
- adev->gfx.config.max_shader_engines = 2;
- adev->gfx.config.max_tile_pipes = 4;
- adev->gfx.config.max_cu_per_sh = 2;
- adev->gfx.config.max_sh_per_se = 1;
- adev->gfx.config.max_backends_per_se = 2;
- adev->gfx.config.max_texture_channel_caches = 4;
- adev->gfx.config.max_gprs = 256;
- adev->gfx.config.max_gs_threads = 32;
- adev->gfx.config.max_hw_contexts = 8;
-
- adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
- adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
- adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
- adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
- gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
- break;
- }
-
tmp = RREG32(mmGRBM_CNTL);
tmp = REG_SET_FIELD(tmp, GRBM_CNTL, READ_TIMEOUT, 0xff);
WREG32(mmGRBM_CNTL, tmp);
- mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
- adev->gfx.config.mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
- mc_arb_ramcfg = adev->gfx.config.mc_arb_ramcfg;
-
- adev->gfx.config.num_tile_pipes = adev->gfx.config.max_tile_pipes;
- adev->gfx.config.mem_max_burst_length_bytes = 256;
- if (adev->flags & AMD_IS_APU) {
- /* Get memory bank mapping mode. */
- tmp = RREG32(mmMC_FUS_DRAM0_BANK_ADDR_MAPPING);
- dimm00_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM0_BANK_ADDR_MAPPING, DIMM0ADDRMAP);
- dimm01_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM0_BANK_ADDR_MAPPING, DIMM1ADDRMAP);
-
- tmp = RREG32(mmMC_FUS_DRAM1_BANK_ADDR_MAPPING);
- dimm10_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM1_BANK_ADDR_MAPPING, DIMM0ADDRMAP);
- dimm11_addr_map = REG_GET_FIELD(tmp, MC_FUS_DRAM1_BANK_ADDR_MAPPING, DIMM1ADDRMAP);
-
- /* Validate settings in case only one DIMM installed. */
- if ((dimm00_addr_map == 0) || (dimm00_addr_map == 3) || (dimm00_addr_map == 4) || (dimm00_addr_map > 12))
- dimm00_addr_map = 0;
- if ((dimm01_addr_map == 0) || (dimm01_addr_map == 3) || (dimm01_addr_map == 4) || (dimm01_addr_map > 12))
- dimm01_addr_map = 0;
- if ((dimm10_addr_map == 0) || (dimm10_addr_map == 3) || (dimm10_addr_map == 4) || (dimm10_addr_map > 12))
- dimm10_addr_map = 0;
- if ((dimm11_addr_map == 0) || (dimm11_addr_map == 3) || (dimm11_addr_map == 4) || (dimm11_addr_map > 12))
- dimm11_addr_map = 0;
-
- /* If DIMM Addr map is 8GB, ROW size should be 2KB. Otherwise 1KB. */
- /* If ROW size(DIMM1) != ROW size(DMIMM0), ROW size should be larger one. */
- if ((dimm00_addr_map == 11) || (dimm01_addr_map == 11) || (dimm10_addr_map == 11) || (dimm11_addr_map == 11))
- adev->gfx.config.mem_row_size_in_kb = 2;
- else
- adev->gfx.config.mem_row_size_in_kb = 1;
- } else {
- tmp = REG_GET_FIELD(mc_arb_ramcfg, MC_ARB_RAMCFG, NOOFCOLS);
- adev->gfx.config.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
- if (adev->gfx.config.mem_row_size_in_kb > 4)
- adev->gfx.config.mem_row_size_in_kb = 4;
- }
-
- adev->gfx.config.shader_engine_tile_size = 32;
- adev->gfx.config.num_gpus = 1;
- adev->gfx.config.multi_gpu_tile_size = 64;
-
- /* fix up row size */
- switch (adev->gfx.config.mem_row_size_in_kb) {
- case 1:
- default:
- gb_addr_config = REG_SET_FIELD(gb_addr_config, GB_ADDR_CONFIG, ROW_SIZE, 0);
- break;
- case 2:
- gb_addr_config = REG_SET_FIELD(gb_addr_config, GB_ADDR_CONFIG, ROW_SIZE, 1);
- break;
- case 4:
- gb_addr_config = REG_SET_FIELD(gb_addr_config, GB_ADDR_CONFIG, ROW_SIZE, 2);
- break;
- }
- adev->gfx.config.gb_addr_config = gb_addr_config;
-
- WREG32(mmGB_ADDR_CONFIG, gb_addr_config);
- WREG32(mmHDP_ADDR_CONFIG, gb_addr_config);
- WREG32(mmDMIF_ADDR_CALC, gb_addr_config);
+ WREG32(mmGB_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
+ WREG32(mmHDP_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
+ WREG32(mmDMIF_ADDR_CALC, adev->gfx.config.gb_addr_config);
WREG32(mmSDMA0_TILING_CONFIG + SDMA0_REGISTER_OFFSET,
- gb_addr_config & 0x70);
+ adev->gfx.config.gb_addr_config & 0x70);
WREG32(mmSDMA0_TILING_CONFIG + SDMA1_REGISTER_OFFSET,
- gb_addr_config & 0x70);
- WREG32(mmUVD_UDEC_ADDR_CONFIG, gb_addr_config);
- WREG32(mmUVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
- WREG32(mmUVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
+ adev->gfx.config.gb_addr_config & 0x70);
+ WREG32(mmUVD_UDEC_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
+ WREG32(mmUVD_UDEC_DB_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
+ WREG32(mmUVD_UDEC_DBW_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
gfx_v8_0_tiling_mode_table_init(adev);
@@ -2256,13 +2922,13 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev)
if (i == 0) {
tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, DEFAULT_MTYPE, MTYPE_UC);
tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, APE1_MTYPE, MTYPE_UC);
- tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, ALIGNMENT_MODE,
+ tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, ALIGNMENT_MODE,
SH_MEM_ALIGNMENT_MODE_UNALIGNED);
WREG32(mmSH_MEM_CONFIG, tmp);
} else {
tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, DEFAULT_MTYPE, MTYPE_NC);
tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, APE1_MTYPE, MTYPE_NC);
- tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, ALIGNMENT_MODE,
+ tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, ALIGNMENT_MODE,
SH_MEM_ALIGNMENT_MODE_UNALIGNED);
WREG32(mmSH_MEM_CONFIG, tmp);
}
@@ -2377,7 +3043,7 @@ static void gfx_v8_0_rlc_start(struct amdgpu_device *adev)
WREG32(mmRLC_CNTL, tmp);
/* carrizo do enable cp interrupt after cp inited */
- if (adev->asic_type != CHIP_CARRIZO)
+ if (!(adev->flags & AMD_IS_APU))
gfx_v8_0_enable_gui_idle_interrupt(adev, true);
udelay(50);
@@ -2590,15 +3256,22 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
amdgpu_ring_write(ring, mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
switch (adev->asic_type) {
case CHIP_TONGA:
- case CHIP_FIJI:
amdgpu_ring_write(ring, 0x16000012);
amdgpu_ring_write(ring, 0x0000002A);
break;
+ case CHIP_FIJI:
+ amdgpu_ring_write(ring, 0x3a00161a);
+ amdgpu_ring_write(ring, 0x0000002e);
+ break;
case CHIP_TOPAZ:
case CHIP_CARRIZO:
amdgpu_ring_write(ring, 0x00000002);
amdgpu_ring_write(ring, 0x00000000);
break;
+ case CHIP_STONEY:
+ amdgpu_ring_write(ring, 0x00000000);
+ amdgpu_ring_write(ring, 0x00000000);
+ break;
default:
BUG();
}
@@ -3233,7 +3906,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
/* enable the doorbell if requested */
if (use_doorbell) {
if ((adev->asic_type == CHIP_CARRIZO) ||
- (adev->asic_type == CHIP_FIJI)) {
+ (adev->asic_type == CHIP_FIJI) ||
+ (adev->asic_type == CHIP_STONEY)) {
WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
AMDGPU_DOORBELL_KIQ << 2);
WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -3305,7 +3979,7 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
{
int r;
- if (adev->asic_type != CHIP_CARRIZO)
+ if (!(adev->flags & AMD_IS_APU))
gfx_v8_0_enable_gui_idle_interrupt(adev, false);
if (!adev->firmware.smu_load) {
@@ -4068,15 +4742,6 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
}
}
-static bool gfx_v8_0_ring_is_lockup(struct amdgpu_ring *ring)
-{
- if (gfx_v8_0_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static u32 gfx_v8_0_ring_get_rptr_compute(struct amdgpu_ring *ring)
{
return ring->adev->wb.wb[ring->rptr_offs];
@@ -4107,6 +4772,7 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 5));
amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
EOP_TC_ACTION_EN |
+ EOP_TC_WB_ACTION_EN |
EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
EVENT_INDEX(5)));
amdgpu_ring_write(ring, DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
@@ -4357,7 +5023,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
.emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
.test_ring = gfx_v8_0_ring_test_ring,
.test_ib = gfx_v8_0_ring_test_ib,
- .is_lockup = gfx_v8_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
@@ -4374,7 +5039,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
.emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
.test_ring = gfx_v8_0_ring_test_ring,
.test_ib = gfx_v8_0_ring_test_ib,
- .is_lockup = gfx_v8_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index fab5471d25d7..7427d8cd4c43 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -40,7 +40,7 @@
static void gmc_v7_0_set_gart_funcs(struct amdgpu_device *adev);
static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev);
-MODULE_FIRMWARE("radeon/boniare_mc.bin");
+MODULE_FIRMWARE("radeon/bonaire_mc.bin");
MODULE_FIRMWARE("radeon/hawaii_mc.bin");
/**
@@ -436,6 +436,33 @@ static int gmc_v7_0_gart_set_pte_pde(struct amdgpu_device *adev,
}
/**
+ * gmc_v8_0_set_fault_enable_default - update VM fault handling
+ *
+ * @adev: amdgpu_device pointer
+ * @value: true redirects VM faults to the default page
+ */
+static void gmc_v7_0_set_fault_enable_default(struct amdgpu_device *adev,
+ bool value)
+{
+ u32 tmp;
+
+ tmp = RREG32(mmVM_CONTEXT1_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ WREG32(mmVM_CONTEXT1_CNTL, tmp);
+}
+
+/**
* gmc_v7_0_gart_enable - gart enable
*
* @adev: amdgpu_device pointer
@@ -474,6 +501,7 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE, 1);
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, EFFECTIVE_L2_QUEUE_SIZE, 7);
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
WREG32(mmVM_L2_CNTL, tmp);
tmp = REG_SET_FIELD(0, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
@@ -523,15 +551,13 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
tmp = RREG32(mmVM_CONTEXT1_CNTL);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_BLOCK_SIZE,
amdgpu_vm_block_size - 9);
WREG32(mmVM_CONTEXT1_CNTL, tmp);
+ if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
+ gmc_v7_0_set_fault_enable_default(adev, false);
+ else
+ gmc_v7_0_set_fault_enable_default(adev, true);
if (adev->asic_type == CHIP_KAVERI) {
tmp = RREG32(mmCHUB_CONTROL);
@@ -935,12 +961,10 @@ static int gmc_v7_0_sw_init(void *handle)
static int gmc_v7_0_sw_fini(void *handle)
{
- int i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) {
- for (i = 0; i < AMDGPU_NUM_VM; ++i)
- amdgpu_fence_unref(&adev->vm_manager.active[i]);
+ amdgpu_vm_manager_fini(adev);
gmc_v7_0_vm_fini(adev);
adev->vm_manager.enabled = false;
}
@@ -985,12 +1009,10 @@ static int gmc_v7_0_hw_fini(void *handle)
static int gmc_v7_0_suspend(void *handle)
{
- int i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) {
- for (i = 0; i < AMDGPU_NUM_VM; ++i)
- amdgpu_fence_unref(&adev->vm_manager.active[i]);
+ amdgpu_vm_manager_fini(adev);
gmc_v7_0_vm_fini(adev);
adev->vm_manager.enabled = false;
}
@@ -1268,6 +1290,9 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
if (!addr && !status)
return 0;
+ if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
+ gmc_v7_0_set_fault_enable_default(adev, false);
+
dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
entry->src_id, entry->src_data);
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 7bc9e9fcf3d2..cb0e50ebb528 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -93,6 +93,12 @@ static const u32 cz_mgcg_cgcg_init[] =
mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
};
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+};
+
+
static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
{
switch (adev->asic_type) {
@@ -125,6 +131,11 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
cz_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(cz_mgcg_cgcg_init));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ break;
default:
break;
}
@@ -228,6 +239,7 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
chip_name = "fiji";
break;
case CHIP_CARRIZO:
+ case CHIP_STONEY:
return 0;
default: BUG();
}
@@ -550,6 +562,35 @@ static int gmc_v8_0_gart_set_pte_pde(struct amdgpu_device *adev,
}
/**
+ * gmc_v8_0_set_fault_enable_default - update VM fault handling
+ *
+ * @adev: amdgpu_device pointer
+ * @value: true redirects VM faults to the default page
+ */
+static void gmc_v8_0_set_fault_enable_default(struct amdgpu_device *adev,
+ bool value)
+{
+ u32 tmp;
+
+ tmp = RREG32(mmVM_CONTEXT1_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ WREG32(mmVM_CONTEXT1_CNTL, tmp);
+}
+
+/**
* gmc_v8_0_gart_enable - gart enable
*
* @adev: amdgpu_device pointer
@@ -588,6 +629,7 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE, 1);
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, EFFECTIVE_L2_QUEUE_SIZE, 7);
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
WREG32(mmVM_L2_CNTL, tmp);
tmp = RREG32(mmVM_L2_CNTL2);
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
@@ -663,6 +705,10 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_BLOCK_SIZE,
amdgpu_vm_block_size - 9);
WREG32(mmVM_CONTEXT1_CNTL, tmp);
+ if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
+ gmc_v8_0_set_fault_enable_default(adev, false);
+ else
+ gmc_v8_0_set_fault_enable_default(adev, true);
gmc_v8_0_gart_flush_gpu_tlb(adev, 0);
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
@@ -934,12 +980,10 @@ static int gmc_v8_0_sw_init(void *handle)
static int gmc_v8_0_sw_fini(void *handle)
{
- int i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) {
- for (i = 0; i < AMDGPU_NUM_VM; ++i)
- amdgpu_fence_unref(&adev->vm_manager.active[i]);
+ amdgpu_vm_manager_fini(adev);
gmc_v8_0_vm_fini(adev);
adev->vm_manager.enabled = false;
}
@@ -986,12 +1030,10 @@ static int gmc_v8_0_hw_fini(void *handle)
static int gmc_v8_0_suspend(void *handle)
{
- int i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) {
- for (i = 0; i < AMDGPU_NUM_VM; ++i)
- amdgpu_fence_unref(&adev->vm_manager.active[i]);
+ amdgpu_vm_manager_fini(adev);
gmc_v8_0_vm_fini(adev);
adev->vm_manager.enabled = false;
}
@@ -1268,6 +1310,9 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
if (!addr && !status)
return 0;
+ if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
+ gmc_v8_0_set_fault_enable_default(adev, false);
+
dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
entry->src_id, entry->src_data);
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index 94ec04a9c4d5..7e9154c7f1db 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -2995,6 +2995,15 @@ static int kv_dpm_late_init(void *handle)
{
/* powerdown unused blocks for now */
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ if (!amdgpu_dpm)
+ return 0;
+
+ /* init the sysfs and debugfs files late */
+ ret = amdgpu_pm_sysfs_init(adev);
+ if (ret)
+ return ret;
kv_dpm_powergate_acp(adev, true);
kv_dpm_powergate_samu(adev, true);
@@ -3038,9 +3047,6 @@ static int kv_dpm_sw_init(void *handle)
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- goto dpm_failed;
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index 14e87234171a..2cf50180cc51 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -118,7 +118,7 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
char fw_name[30];
- int err, i;
+ int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct sdma_firmware_header_v1_0 *hdr;
@@ -132,27 +132,27 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
default: BUG();
}
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = request_firmware(&adev->sdma[i].fw, fw_name, adev->dev);
+ err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->sdma[i].fw);
+ err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
if (err)
goto out;
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
- adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
- adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
- if (adev->sdma[i].feature_version >= 20)
- adev->sdma[i].burst_nop = true;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
+ adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
+ if (adev->sdma.instance[i].feature_version >= 20)
+ adev->sdma.instance[i].burst_nop = true;
if (adev->firmware.smu_load) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
- info->fw = adev->sdma[i].fw;
+ info->fw = adev->sdma.instance[i].fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
@@ -164,9 +164,9 @@ out:
printk(KERN_ERR
"sdma_v2_4: Failed to load firmware \"%s\"\n",
fw_name);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- release_firmware(adev->sdma[i].fw);
- adev->sdma[i].fw = NULL;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ release_firmware(adev->sdma.instance[i].fw);
+ adev->sdma.instance[i].fw = NULL;
}
}
return err;
@@ -199,7 +199,7 @@ static uint32_t sdma_v2_4_ring_get_rptr(struct amdgpu_ring *ring)
static uint32_t sdma_v2_4_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- int me = (ring == &ring->adev->sdma[0].ring) ? 0 : 1;
+ int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1;
u32 wptr = RREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me]) >> 2;
return wptr;
@@ -215,14 +215,14 @@ static uint32_t sdma_v2_4_ring_get_wptr(struct amdgpu_ring *ring)
static void sdma_v2_4_ring_set_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- int me = (ring == &ring->adev->sdma[0].ring) ? 0 : 1;
+ int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1;
WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], ring->wptr << 2);
}
static void sdma_v2_4_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
{
- struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ring);
+ struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ring);
int i;
for (i = 0; i < count; i++)
@@ -284,7 +284,7 @@ static void sdma_v2_4_ring_emit_hdp_flush(struct amdgpu_ring *ring)
{
u32 ref_and_mask = 0;
- if (ring == &ring->adev->sdma[0].ring)
+ if (ring == &ring->adev->sdma.instance[0].ring)
ref_and_mask = REG_SET_FIELD(ref_and_mask, GPU_HDP_FLUSH_DONE, SDMA0, 1);
else
ref_and_mask = REG_SET_FIELD(ref_and_mask, GPU_HDP_FLUSH_DONE, SDMA1, 1);
@@ -368,8 +368,8 @@ static bool sdma_v2_4_ring_emit_semaphore(struct amdgpu_ring *ring,
*/
static void sdma_v2_4_gfx_stop(struct amdgpu_device *adev)
{
- struct amdgpu_ring *sdma0 = &adev->sdma[0].ring;
- struct amdgpu_ring *sdma1 = &adev->sdma[1].ring;
+ struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
+ struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl, ib_cntl;
int i;
@@ -377,7 +377,7 @@ static void sdma_v2_4_gfx_stop(struct amdgpu_device *adev)
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
@@ -419,7 +419,7 @@ static void sdma_v2_4_enable(struct amdgpu_device *adev, bool enable)
sdma_v2_4_rlc_stop(adev);
}
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
f32_cntl = RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]);
if (enable)
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 0);
@@ -445,8 +445,8 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
u32 wb_offset;
int i, j, r;
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- ring = &adev->sdma[i].ring;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ ring = &adev->sdma.instance[i].ring;
wb_offset = (ring->rptr_offs * 4);
mutex_lock(&adev->srbm_mutex);
@@ -545,29 +545,23 @@ static int sdma_v2_4_load_microcode(struct amdgpu_device *adev)
const __le32 *fw_data;
u32 fw_size;
int i, j;
- bool smc_loads_fw = false; /* XXX fix me */
-
- if (!adev->sdma[0].fw || !adev->sdma[1].fw)
- return -EINVAL;
/* halt the MEs */
sdma_v2_4_enable(adev, false);
- if (smc_loads_fw) {
- /* XXX query SMC for fw load complete */
- } else {
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
- amdgpu_ucode_print_sdma_hdr(&hdr->header);
- fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- fw_data = (const __le32 *)
- (adev->sdma[i].fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
- for (j = 0; j < fw_size; j++)
- WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma[i].fw_version);
- }
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ if (!adev->sdma.instance[i].fw)
+ return -EINVAL;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
+ amdgpu_ucode_print_sdma_hdr(&hdr->header);
+ fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ fw_data = (const __le32 *)
+ (adev->sdma.instance[i].fw->data +
+ le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
+ for (j = 0; j < fw_size; j++)
+ WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
+ WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version);
}
return 0;
@@ -894,7 +888,7 @@ static void sdma_v2_4_vm_set_pte_pde(struct amdgpu_ib *ib,
*/
static void sdma_v2_4_vm_pad_ib(struct amdgpu_ib *ib)
{
- struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ib->ring);
+ struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ib->ring);
u32 pad_count;
int i;
@@ -952,6 +946,8 @@ static int sdma_v2_4_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->sdma.num_instances = SDMA_MAX_INSTANCE;
+
sdma_v2_4_set_ring_funcs(adev);
sdma_v2_4_set_buffer_funcs(adev);
sdma_v2_4_set_vm_pte_funcs(adev);
@@ -963,21 +959,21 @@ static int sdma_v2_4_early_init(void *handle)
static int sdma_v2_4_sw_init(void *handle)
{
struct amdgpu_ring *ring;
- int r;
+ int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* SDMA trap event */
- r = amdgpu_irq_add_id(adev, 224, &adev->sdma_trap_irq);
+ r = amdgpu_irq_add_id(adev, 224, &adev->sdma.trap_irq);
if (r)
return r;
/* SDMA Privileged inst */
- r = amdgpu_irq_add_id(adev, 241, &adev->sdma_illegal_inst_irq);
+ r = amdgpu_irq_add_id(adev, 241, &adev->sdma.illegal_inst_irq);
if (r)
return r;
/* SDMA Privileged inst */
- r = amdgpu_irq_add_id(adev, 247, &adev->sdma_illegal_inst_irq);
+ r = amdgpu_irq_add_id(adev, 247, &adev->sdma.illegal_inst_irq);
if (r)
return r;
@@ -987,31 +983,20 @@ static int sdma_v2_4_sw_init(void *handle)
return r;
}
- ring = &adev->sdma[0].ring;
- ring->ring_obj = NULL;
- ring->use_doorbell = false;
-
- ring = &adev->sdma[1].ring;
- ring->ring_obj = NULL;
- ring->use_doorbell = false;
-
- ring = &adev->sdma[0].ring;
- sprintf(ring->name, "sdma0");
- r = amdgpu_ring_init(adev, ring, 256 * 1024,
- SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
- &adev->sdma_trap_irq, AMDGPU_SDMA_IRQ_TRAP0,
- AMDGPU_RING_TYPE_SDMA);
- if (r)
- return r;
-
- ring = &adev->sdma[1].ring;
- sprintf(ring->name, "sdma1");
- r = amdgpu_ring_init(adev, ring, 256 * 1024,
- SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
- &adev->sdma_trap_irq, AMDGPU_SDMA_IRQ_TRAP1,
- AMDGPU_RING_TYPE_SDMA);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ ring = &adev->sdma.instance[i].ring;
+ ring->ring_obj = NULL;
+ ring->use_doorbell = false;
+ sprintf(ring->name, "sdma%d", i);
+ r = amdgpu_ring_init(adev, ring, 256 * 1024,
+ SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
+ &adev->sdma.trap_irq,
+ (i == 0) ?
+ AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
+ AMDGPU_RING_TYPE_SDMA);
+ if (r)
+ return r;
+ }
return r;
}
@@ -1019,9 +1004,10 @@ static int sdma_v2_4_sw_init(void *handle)
static int sdma_v2_4_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i;
- amdgpu_ring_fini(&adev->sdma[0].ring);
- amdgpu_ring_fini(&adev->sdma[1].ring);
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ring_fini(&adev->sdma.instance[i].ring);
return 0;
}
@@ -1100,7 +1086,7 @@ static void sdma_v2_4_print_status(void *handle)
dev_info(adev->dev, "VI SDMA registers\n");
dev_info(adev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(mmSRBM_STATUS2));
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
dev_info(adev->dev, " SDMA%d_STATUS_REG=0x%08X\n",
i, RREG32(mmSDMA0_STATUS_REG + sdma_offsets[i]));
dev_info(adev->dev, " SDMA%d_F32_CNTL=0x%08X\n",
@@ -1243,7 +1229,7 @@ static int sdma_v2_4_process_trap_irq(struct amdgpu_device *adev,
case 0:
switch (queue_id) {
case 0:
- amdgpu_fence_process(&adev->sdma[0].ring);
+ amdgpu_fence_process(&adev->sdma.instance[0].ring);
break;
case 1:
/* XXX compute */
@@ -1256,7 +1242,7 @@ static int sdma_v2_4_process_trap_irq(struct amdgpu_device *adev,
case 1:
switch (queue_id) {
case 0:
- amdgpu_fence_process(&adev->sdma[1].ring);
+ amdgpu_fence_process(&adev->sdma.instance[1].ring);
break;
case 1:
/* XXX compute */
@@ -1309,24 +1295,6 @@ const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
.set_powergating_state = sdma_v2_4_set_powergating_state,
};
-/**
- * sdma_v2_4_ring_is_lockup - Check if the DMA engine is locked up
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the async DMA engine is locked up (VI).
- * Returns true if the engine appears to be locked up, false if not.
- */
-static bool sdma_v2_4_ring_is_lockup(struct amdgpu_ring *ring)
-{
-
- if (sdma_v2_4_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
.get_rptr = sdma_v2_4_ring_get_rptr,
.get_wptr = sdma_v2_4_ring_get_wptr,
@@ -1339,14 +1307,15 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
.emit_hdp_flush = sdma_v2_4_ring_emit_hdp_flush,
.test_ring = sdma_v2_4_ring_test_ring,
.test_ib = sdma_v2_4_ring_test_ib,
- .is_lockup = sdma_v2_4_ring_is_lockup,
.insert_nop = sdma_v2_4_ring_insert_nop,
};
static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev)
{
- adev->sdma[0].ring.funcs = &sdma_v2_4_ring_funcs;
- adev->sdma[1].ring.funcs = &sdma_v2_4_ring_funcs;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ adev->sdma.instance[i].ring.funcs = &sdma_v2_4_ring_funcs;
}
static const struct amdgpu_irq_src_funcs sdma_v2_4_trap_irq_funcs = {
@@ -1360,9 +1329,9 @@ static const struct amdgpu_irq_src_funcs sdma_v2_4_illegal_inst_irq_funcs = {
static void sdma_v2_4_set_irq_funcs(struct amdgpu_device *adev)
{
- adev->sdma_trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
- adev->sdma_trap_irq.funcs = &sdma_v2_4_trap_irq_funcs;
- adev->sdma_illegal_inst_irq.funcs = &sdma_v2_4_illegal_inst_irq_funcs;
+ adev->sdma.trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
+ adev->sdma.trap_irq.funcs = &sdma_v2_4_trap_irq_funcs;
+ adev->sdma.illegal_inst_irq.funcs = &sdma_v2_4_illegal_inst_irq_funcs;
}
/**
@@ -1428,7 +1397,7 @@ static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev)
{
if (adev->mman.buffer_funcs == NULL) {
adev->mman.buffer_funcs = &sdma_v2_4_buffer_funcs;
- adev->mman.buffer_funcs_ring = &adev->sdma[0].ring;
+ adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring;
}
}
@@ -1443,7 +1412,7 @@ static void sdma_v2_4_set_vm_pte_funcs(struct amdgpu_device *adev)
{
if (adev->vm_manager.vm_pte_funcs == NULL) {
adev->vm_manager.vm_pte_funcs = &sdma_v2_4_vm_pte_funcs;
- adev->vm_manager.vm_pte_funcs_ring = &adev->sdma[0].ring;
+ adev->vm_manager.vm_pte_funcs_ring = &adev->sdma.instance[0].ring;
adev->vm_manager.vm_pte_funcs_ring->is_pte_ring = true;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 9bfe92df15f7..7253132f04b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -55,6 +55,7 @@ MODULE_FIRMWARE("amdgpu/carrizo_sdma.bin");
MODULE_FIRMWARE("amdgpu/carrizo_sdma1.bin");
MODULE_FIRMWARE("amdgpu/fiji_sdma.bin");
MODULE_FIRMWARE("amdgpu/fiji_sdma1.bin");
+MODULE_FIRMWARE("amdgpu/stoney_sdma.bin");
static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
{
@@ -122,6 +123,19 @@ static const u32 cz_mgcg_cgcg_init[] =
mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
};
+static const u32 stoney_golden_settings_a11[] =
+{
+ mmSDMA0_GFX_IB_CNTL, 0x00000100, 0x00000100,
+ mmSDMA0_POWER_CNTL, 0x00000800, 0x0003c800,
+ mmSDMA0_RLC0_IB_CNTL, 0x00000100, 0x00000100,
+ mmSDMA0_RLC1_IB_CNTL, 0x00000100, 0x00000100,
+};
+
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmSDMA0_CLK_CTRL, 0xffffffff, 0x00000100,
+};
+
/*
* sDMA - System DMA
* Starting with CIK, the GPU has new asynchronous
@@ -166,6 +180,14 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
cz_golden_settings_a11,
(const u32)ARRAY_SIZE(cz_golden_settings_a11));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_settings_a11,
+ (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
+ break;
default:
break;
}
@@ -184,7 +206,7 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
char fw_name[30];
- int err, i;
+ int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct sdma_firmware_header_v1_0 *hdr;
@@ -201,30 +223,33 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
case CHIP_CARRIZO:
chip_name = "carrizo";
break;
+ case CHIP_STONEY:
+ chip_name = "stoney";
+ break;
default: BUG();
}
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = request_firmware(&adev->sdma[i].fw, fw_name, adev->dev);
+ err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->sdma[i].fw);
+ err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
if (err)
goto out;
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
- adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
- adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
- if (adev->sdma[i].feature_version >= 20)
- adev->sdma[i].burst_nop = true;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
+ adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
+ if (adev->sdma.instance[i].feature_version >= 20)
+ adev->sdma.instance[i].burst_nop = true;
if (adev->firmware.smu_load) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
- info->fw = adev->sdma[i].fw;
+ info->fw = adev->sdma.instance[i].fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
@@ -235,9 +260,9 @@ out:
printk(KERN_ERR
"sdma_v3_0: Failed to load firmware \"%s\"\n",
fw_name);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- release_firmware(adev->sdma[i].fw);
- adev->sdma[i].fw = NULL;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ release_firmware(adev->sdma.instance[i].fw);
+ adev->sdma.instance[i].fw = NULL;
}
}
return err;
@@ -276,7 +301,7 @@ static uint32_t sdma_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
/* XXX check if swapping is necessary on BE */
wptr = ring->adev->wb.wb[ring->wptr_offs] >> 2;
} else {
- int me = (ring == &ring->adev->sdma[0].ring) ? 0 : 1;
+ int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1;
wptr = RREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me]) >> 2;
}
@@ -300,7 +325,7 @@ static void sdma_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
adev->wb.wb[ring->wptr_offs] = ring->wptr << 2;
WDOORBELL32(ring->doorbell_index, ring->wptr << 2);
} else {
- int me = (ring == &ring->adev->sdma[0].ring) ? 0 : 1;
+ int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1;
WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], ring->wptr << 2);
}
@@ -308,7 +333,7 @@ static void sdma_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
static void sdma_v3_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
{
- struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ring);
+ struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ring);
int i;
for (i = 0; i < count; i++)
@@ -369,7 +394,7 @@ static void sdma_v3_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
{
u32 ref_and_mask = 0;
- if (ring == &ring->adev->sdma[0].ring)
+ if (ring == &ring->adev->sdma.instance[0].ring)
ref_and_mask = REG_SET_FIELD(ref_and_mask, GPU_HDP_FLUSH_DONE, SDMA0, 1);
else
ref_and_mask = REG_SET_FIELD(ref_and_mask, GPU_HDP_FLUSH_DONE, SDMA1, 1);
@@ -454,8 +479,8 @@ static bool sdma_v3_0_ring_emit_semaphore(struct amdgpu_ring *ring,
*/
static void sdma_v3_0_gfx_stop(struct amdgpu_device *adev)
{
- struct amdgpu_ring *sdma0 = &adev->sdma[0].ring;
- struct amdgpu_ring *sdma1 = &adev->sdma[1].ring;
+ struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
+ struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl, ib_cntl;
int i;
@@ -463,7 +488,7 @@ static void sdma_v3_0_gfx_stop(struct amdgpu_device *adev)
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
@@ -500,7 +525,7 @@ static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
u32 f32_cntl;
int i;
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]);
if (enable)
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
@@ -530,7 +555,7 @@ static void sdma_v3_0_enable(struct amdgpu_device *adev, bool enable)
sdma_v3_0_rlc_stop(adev);
}
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
f32_cntl = RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]);
if (enable)
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 0);
@@ -557,8 +582,8 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
u32 doorbell;
int i, j, r;
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- ring = &adev->sdma[i].ring;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ ring = &adev->sdma.instance[i].ring;
wb_offset = (ring->rptr_offs * 4);
mutex_lock(&adev->srbm_mutex);
@@ -669,23 +694,22 @@ static int sdma_v3_0_load_microcode(struct amdgpu_device *adev)
u32 fw_size;
int i, j;
- if (!adev->sdma[0].fw || !adev->sdma[1].fw)
- return -EINVAL;
-
/* halt the MEs */
sdma_v3_0_enable(adev, false);
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ if (!adev->sdma.instance[i].fw)
+ return -EINVAL;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
amdgpu_ucode_print_sdma_hdr(&hdr->header);
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
fw_data = (const __le32 *)
- (adev->sdma[i].fw->data +
+ (adev->sdma.instance[i].fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
for (j = 0; j < fw_size; j++)
WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma[i].fw_version);
+ WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version);
}
return 0;
@@ -701,21 +725,21 @@ static int sdma_v3_0_load_microcode(struct amdgpu_device *adev)
*/
static int sdma_v3_0_start(struct amdgpu_device *adev)
{
- int r;
+ int r, i;
if (!adev->firmware.smu_load) {
r = sdma_v3_0_load_microcode(adev);
if (r)
return r;
} else {
- r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
- AMDGPU_UCODE_ID_SDMA0);
- if (r)
- return -EINVAL;
- r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
- AMDGPU_UCODE_ID_SDMA1);
- if (r)
- return -EINVAL;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+ (i == 0) ?
+ AMDGPU_UCODE_ID_SDMA0 :
+ AMDGPU_UCODE_ID_SDMA1);
+ if (r)
+ return -EINVAL;
+ }
}
/* unhalt the MEs */
@@ -1013,7 +1037,7 @@ static void sdma_v3_0_vm_set_pte_pde(struct amdgpu_ib *ib,
*/
static void sdma_v3_0_vm_pad_ib(struct amdgpu_ib *ib)
{
- struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ib->ring);
+ struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ib->ring);
u32 pad_count;
int i;
@@ -1071,6 +1095,15 @@ static int sdma_v3_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ switch (adev->asic_type) {
+ case CHIP_STONEY:
+ adev->sdma.num_instances = 1;
+ break;
+ default:
+ adev->sdma.num_instances = SDMA_MAX_INSTANCE;
+ break;
+ }
+
sdma_v3_0_set_ring_funcs(adev);
sdma_v3_0_set_buffer_funcs(adev);
sdma_v3_0_set_vm_pte_funcs(adev);
@@ -1082,21 +1115,21 @@ static int sdma_v3_0_early_init(void *handle)
static int sdma_v3_0_sw_init(void *handle)
{
struct amdgpu_ring *ring;
- int r;
+ int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* SDMA trap event */
- r = amdgpu_irq_add_id(adev, 224, &adev->sdma_trap_irq);
+ r = amdgpu_irq_add_id(adev, 224, &adev->sdma.trap_irq);
if (r)
return r;
/* SDMA Privileged inst */
- r = amdgpu_irq_add_id(adev, 241, &adev->sdma_illegal_inst_irq);
+ r = amdgpu_irq_add_id(adev, 241, &adev->sdma.illegal_inst_irq);
if (r)
return r;
/* SDMA Privileged inst */
- r = amdgpu_irq_add_id(adev, 247, &adev->sdma_illegal_inst_irq);
+ r = amdgpu_irq_add_id(adev, 247, &adev->sdma.illegal_inst_irq);
if (r)
return r;
@@ -1106,33 +1139,23 @@ static int sdma_v3_0_sw_init(void *handle)
return r;
}
- ring = &adev->sdma[0].ring;
- ring->ring_obj = NULL;
- ring->use_doorbell = true;
- ring->doorbell_index = AMDGPU_DOORBELL_sDMA_ENGINE0;
-
- ring = &adev->sdma[1].ring;
- ring->ring_obj = NULL;
- ring->use_doorbell = true;
- ring->doorbell_index = AMDGPU_DOORBELL_sDMA_ENGINE1;
-
- ring = &adev->sdma[0].ring;
- sprintf(ring->name, "sdma0");
- r = amdgpu_ring_init(adev, ring, 256 * 1024,
- SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
- &adev->sdma_trap_irq, AMDGPU_SDMA_IRQ_TRAP0,
- AMDGPU_RING_TYPE_SDMA);
- if (r)
- return r;
-
- ring = &adev->sdma[1].ring;
- sprintf(ring->name, "sdma1");
- r = amdgpu_ring_init(adev, ring, 256 * 1024,
- SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
- &adev->sdma_trap_irq, AMDGPU_SDMA_IRQ_TRAP1,
- AMDGPU_RING_TYPE_SDMA);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ ring = &adev->sdma.instance[i].ring;
+ ring->ring_obj = NULL;
+ ring->use_doorbell = true;
+ ring->doorbell_index = (i == 0) ?
+ AMDGPU_DOORBELL_sDMA_ENGINE0 : AMDGPU_DOORBELL_sDMA_ENGINE1;
+
+ sprintf(ring->name, "sdma%d", i);
+ r = amdgpu_ring_init(adev, ring, 256 * 1024,
+ SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
+ &adev->sdma.trap_irq,
+ (i == 0) ?
+ AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
+ AMDGPU_RING_TYPE_SDMA);
+ if (r)
+ return r;
+ }
return r;
}
@@ -1140,9 +1163,10 @@ static int sdma_v3_0_sw_init(void *handle)
static int sdma_v3_0_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i;
- amdgpu_ring_fini(&adev->sdma[0].ring);
- amdgpu_ring_fini(&adev->sdma[1].ring);
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ring_fini(&adev->sdma.instance[i].ring);
return 0;
}
@@ -1222,7 +1246,7 @@ static void sdma_v3_0_print_status(void *handle)
dev_info(adev->dev, "VI SDMA registers\n");
dev_info(adev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(mmSRBM_STATUS2));
- for (i = 0; i < SDMA_MAX_INSTANCE; i++) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
dev_info(adev->dev, " SDMA%d_STATUS_REG=0x%08X\n",
i, RREG32(mmSDMA0_STATUS_REG + sdma_offsets[i]));
dev_info(adev->dev, " SDMA%d_F32_CNTL=0x%08X\n",
@@ -1367,7 +1391,7 @@ static int sdma_v3_0_process_trap_irq(struct amdgpu_device *adev,
case 0:
switch (queue_id) {
case 0:
- amdgpu_fence_process(&adev->sdma[0].ring);
+ amdgpu_fence_process(&adev->sdma.instance[0].ring);
break;
case 1:
/* XXX compute */
@@ -1380,7 +1404,7 @@ static int sdma_v3_0_process_trap_irq(struct amdgpu_device *adev,
case 1:
switch (queue_id) {
case 0:
- amdgpu_fence_process(&adev->sdma[1].ring);
+ amdgpu_fence_process(&adev->sdma.instance[1].ring);
break;
case 1:
/* XXX compute */
@@ -1432,24 +1456,6 @@ const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
.set_powergating_state = sdma_v3_0_set_powergating_state,
};
-/**
- * sdma_v3_0_ring_is_lockup - Check if the DMA engine is locked up
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the async DMA engine is locked up (VI).
- * Returns true if the engine appears to be locked up, false if not.
- */
-static bool sdma_v3_0_ring_is_lockup(struct amdgpu_ring *ring)
-{
-
- if (sdma_v3_0_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
.get_rptr = sdma_v3_0_ring_get_rptr,
.get_wptr = sdma_v3_0_ring_get_wptr,
@@ -1462,14 +1468,15 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
.emit_hdp_flush = sdma_v3_0_ring_emit_hdp_flush,
.test_ring = sdma_v3_0_ring_test_ring,
.test_ib = sdma_v3_0_ring_test_ib,
- .is_lockup = sdma_v3_0_ring_is_lockup,
.insert_nop = sdma_v3_0_ring_insert_nop,
};
static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev)
{
- adev->sdma[0].ring.funcs = &sdma_v3_0_ring_funcs;
- adev->sdma[1].ring.funcs = &sdma_v3_0_ring_funcs;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ adev->sdma.instance[i].ring.funcs = &sdma_v3_0_ring_funcs;
}
static const struct amdgpu_irq_src_funcs sdma_v3_0_trap_irq_funcs = {
@@ -1483,9 +1490,9 @@ static const struct amdgpu_irq_src_funcs sdma_v3_0_illegal_inst_irq_funcs = {
static void sdma_v3_0_set_irq_funcs(struct amdgpu_device *adev)
{
- adev->sdma_trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
- adev->sdma_trap_irq.funcs = &sdma_v3_0_trap_irq_funcs;
- adev->sdma_illegal_inst_irq.funcs = &sdma_v3_0_illegal_inst_irq_funcs;
+ adev->sdma.trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
+ adev->sdma.trap_irq.funcs = &sdma_v3_0_trap_irq_funcs;
+ adev->sdma.illegal_inst_irq.funcs = &sdma_v3_0_illegal_inst_irq_funcs;
}
/**
@@ -1551,7 +1558,7 @@ static void sdma_v3_0_set_buffer_funcs(struct amdgpu_device *adev)
{
if (adev->mman.buffer_funcs == NULL) {
adev->mman.buffer_funcs = &sdma_v3_0_buffer_funcs;
- adev->mman.buffer_funcs_ring = &adev->sdma[0].ring;
+ adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring;
}
}
@@ -1566,7 +1573,7 @@ static void sdma_v3_0_set_vm_pte_funcs(struct amdgpu_device *adev)
{
if (adev->vm_manager.vm_pte_funcs == NULL) {
adev->vm_manager.vm_pte_funcs = &sdma_v3_0_vm_pte_funcs;
- adev->vm_manager.vm_pte_funcs_ring = &adev->sdma[0].ring;
+ adev->vm_manager.vm_pte_funcs_ring = &adev->sdma.instance[0].ring;
adev->vm_manager.vm_pte_funcs_ring->is_pte_ring = true;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index ed50dd725788..5e9f73af83a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -885,7 +885,6 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = {
.emit_semaphore = uvd_v4_2_ring_emit_semaphore,
.test_ring = uvd_v4_2_ring_test_ring,
.test_ib = uvd_v4_2_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
index 9ad8b9906c0b..38864f562981 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
@@ -824,7 +824,6 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = {
.emit_semaphore = uvd_v5_0_ring_emit_semaphore,
.test_ring = uvd_v5_0_ring_test_ring,
.test_ib = uvd_v5_0_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 7e9934fa4193..121915bbc3b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -808,7 +808,6 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_funcs = {
.emit_semaphore = uvd_v6_0_ring_emit_semaphore,
.test_ring = uvd_v6_0_ring_test_ring,
.test_ib = uvd_v6_0_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
index cd16df543f64..52ac7a8f1e58 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
@@ -642,7 +642,6 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
.emit_semaphore = amdgpu_vce_ring_emit_semaphore,
.test_ring = amdgpu_vce_ring_test_ring,
.test_ib = amdgpu_vce_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index f0656dfb53f3..6a52db6ad8d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -205,8 +205,9 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
u32 tmp;
unsigned ret;
- /* Fiji is single pipe */
- if (adev->asic_type == CHIP_FIJI) {
+ /* Fiji, Stoney are single pipe */
+ if ((adev->asic_type == CHIP_FIJI) ||
+ (adev->asic_type == CHIP_STONEY)){
ret = AMDGPU_VCE_HARVEST_VCE1;
return ret;
}
@@ -643,7 +644,6 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
.emit_semaphore = amdgpu_vce_ring_emit_semaphore,
.test_ring = amdgpu_vce_ring_test_ring,
.test_ib = amdgpu_vce_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index b55ceb14fdcd..2adc1c855e85 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -232,6 +232,13 @@ static const u32 cz_mgcg_cgcg_init[] =
mmHDP_XDP_CGTT_BLK_CTRL, 0xc0000fff, 0x00000104,
};
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmCGTT_DRM_CLK_CTRL0, 0xffffffff, 0x00000100,
+ mmHDP_XDP_CGTT_BLK_CTRL, 0xffffffff, 0x00000104,
+ mmHDP_HOST_PATH_CNTL, 0xffffffff, 0x0f000027,
+};
+
static void vi_init_golden_registers(struct amdgpu_device *adev)
{
/* Some of the registers might be dependent on GRBM_GFX_INDEX */
@@ -258,6 +265,11 @@ static void vi_init_golden_registers(struct amdgpu_device *adev)
cz_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(cz_mgcg_cgcg_init));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ break;
default:
break;
}
@@ -488,6 +500,7 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
case CHIP_FIJI:
case CHIP_TONGA:
case CHIP_CARRIZO:
+ case CHIP_STONEY:
asic_register_table = cz_allowed_read_registers;
size = ARRAY_SIZE(cz_allowed_read_registers);
break;
@@ -543,8 +556,10 @@ static void vi_print_gpu_status_regs(struct amdgpu_device *adev)
RREG32(mmSRBM_STATUS2));
dev_info(adev->dev, " SDMA0_STATUS_REG = 0x%08X\n",
RREG32(mmSDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET));
- dev_info(adev->dev, " SDMA1_STATUS_REG = 0x%08X\n",
- RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET));
+ if (adev->sdma.num_instances > 1) {
+ dev_info(adev->dev, " SDMA1_STATUS_REG = 0x%08X\n",
+ RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET));
+ }
dev_info(adev->dev, " CP_STAT = 0x%08x\n", RREG32(mmCP_STAT));
dev_info(adev->dev, " CP_STALLED_STAT1 = 0x%08x\n",
RREG32(mmCP_STALLED_STAT1));
@@ -639,9 +654,11 @@ u32 vi_gpu_check_soft_reset(struct amdgpu_device *adev)
reset_mask |= AMDGPU_RESET_DMA;
/* SDMA1_STATUS_REG */
- tmp = RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET);
- if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK))
- reset_mask |= AMDGPU_RESET_DMA1;
+ if (adev->sdma.num_instances > 1) {
+ tmp = RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET);
+ if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK))
+ reset_mask |= AMDGPU_RESET_DMA1;
+ }
#if 0
/* VCE_STATUS */
if (adev->asic_type != CHIP_TOPAZ) {
@@ -1005,6 +1022,9 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
u32 mask;
int ret;
+ if (pci_is_root_bus(adev->pdev->bus))
+ return;
+
if (amdgpu_pcie_gen2 == 0)
return;
@@ -1316,6 +1336,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
break;
case CHIP_CARRIZO:
+ case CHIP_STONEY:
adev->ip_blocks = cz_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
break;
@@ -1327,11 +1348,18 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
return 0;
}
+#define ATI_REV_ID_FUSE_MACRO__ADDRESS 0xC0014044
+#define ATI_REV_ID_FUSE_MACRO__SHIFT 9
+#define ATI_REV_ID_FUSE_MACRO__MASK 0x00001E00
+
static uint32_t vi_get_rev_id(struct amdgpu_device *adev)
{
if (adev->asic_type == CHIP_TOPAZ)
return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK)
>> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT;
+ else if (adev->flags & AMD_IS_APU)
+ return (RREG32_SMC(ATI_REV_ID_FUSE_MACRO__ADDRESS) & ATI_REV_ID_FUSE_MACRO__MASK)
+ >> ATI_REV_ID_FUSE_MACRO__SHIFT;
else
return (RREG32(mmCC_DRM_ID_STRAPS) & CC_DRM_ID_STRAPS__ATI_REV_ID_MASK)
>> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT;
@@ -1385,32 +1413,35 @@ static int vi_common_early_init(void *handle)
adev->cg_flags = 0;
adev->pg_flags = 0;
adev->external_rev_id = 0x1;
- if (amdgpu_smc_load_fw && smc_enabled)
- adev->firmware.smu_load = true;
break;
case CHIP_FIJI:
+ adev->has_uvd = true;
+ adev->cg_flags = 0;
+ adev->pg_flags = 0;
+ adev->external_rev_id = adev->rev_id + 0x3c;
+ break;
case CHIP_TONGA:
adev->has_uvd = true;
adev->cg_flags = 0;
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x14;
- if (amdgpu_smc_load_fw && smc_enabled)
- adev->firmware.smu_load = true;
break;
case CHIP_CARRIZO:
+ case CHIP_STONEY:
adev->has_uvd = true;
adev->cg_flags = 0;
/* Disable UVD pg */
adev->pg_flags = /* AMDGPU_PG_SUPPORT_UVD | */AMDGPU_PG_SUPPORT_VCE;
adev->external_rev_id = adev->rev_id + 0x1;
- if (amdgpu_smc_load_fw && smc_enabled)
- adev->firmware.smu_load = true;
break;
default:
/* FIXME: not supported yet */
return -EINVAL;
}
+ if (amdgpu_smc_load_fw && smc_enabled)
+ adev->firmware.smu_load = true;
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index 68a8eaa1b7d0..fe28fb353fab 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -47,6 +47,7 @@ enum amd_asic_type {
CHIP_TONGA,
CHIP_FIJI,
CHIP_CARRIZO,
+ CHIP_STONEY,
CHIP_LAST,
};
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_d.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_d.h
new file mode 100644
index 000000000000..2d672b3d2fed
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_d.h
@@ -0,0 +1,2791 @@
+/*
+ * GFX_8_1 Register documentation
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) 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.
+ */
+
+#ifndef GFX_8_1_D_H
+#define GFX_8_1_D_H
+
+#define mmCB_BLEND_RED 0xa105
+#define mmCB_BLEND_GREEN 0xa106
+#define mmCB_BLEND_BLUE 0xa107
+#define mmCB_BLEND_ALPHA 0xa108
+#define mmCB_DCC_CONTROL 0xa109
+#define mmCB_COLOR_CONTROL 0xa202
+#define mmCB_BLEND0_CONTROL 0xa1e0
+#define mmCB_BLEND1_CONTROL 0xa1e1
+#define mmCB_BLEND2_CONTROL 0xa1e2
+#define mmCB_BLEND3_CONTROL 0xa1e3
+#define mmCB_BLEND4_CONTROL 0xa1e4
+#define mmCB_BLEND5_CONTROL 0xa1e5
+#define mmCB_BLEND6_CONTROL 0xa1e6
+#define mmCB_BLEND7_CONTROL 0xa1e7
+#define mmCB_COLOR0_BASE 0xa318
+#define mmCB_COLOR1_BASE 0xa327
+#define mmCB_COLOR2_BASE 0xa336
+#define mmCB_COLOR3_BASE 0xa345
+#define mmCB_COLOR4_BASE 0xa354
+#define mmCB_COLOR5_BASE 0xa363
+#define mmCB_COLOR6_BASE 0xa372
+#define mmCB_COLOR7_BASE 0xa381
+#define mmCB_COLOR0_PITCH 0xa319
+#define mmCB_COLOR1_PITCH 0xa328
+#define mmCB_COLOR2_PITCH 0xa337
+#define mmCB_COLOR3_PITCH 0xa346
+#define mmCB_COLOR4_PITCH 0xa355
+#define mmCB_COLOR5_PITCH 0xa364
+#define mmCB_COLOR6_PITCH 0xa373
+#define mmCB_COLOR7_PITCH 0xa382
+#define mmCB_COLOR0_SLICE 0xa31a
+#define mmCB_COLOR1_SLICE 0xa329
+#define mmCB_COLOR2_SLICE 0xa338
+#define mmCB_COLOR3_SLICE 0xa347
+#define mmCB_COLOR4_SLICE 0xa356
+#define mmCB_COLOR5_SLICE 0xa365
+#define mmCB_COLOR6_SLICE 0xa374
+#define mmCB_COLOR7_SLICE 0xa383
+#define mmCB_COLOR0_VIEW 0xa31b
+#define mmCB_COLOR1_VIEW 0xa32a
+#define mmCB_COLOR2_VIEW 0xa339
+#define mmCB_COLOR3_VIEW 0xa348
+#define mmCB_COLOR4_VIEW 0xa357
+#define mmCB_COLOR5_VIEW 0xa366
+#define mmCB_COLOR6_VIEW 0xa375
+#define mmCB_COLOR7_VIEW 0xa384
+#define mmCB_COLOR0_INFO 0xa31c
+#define mmCB_COLOR1_INFO 0xa32b
+#define mmCB_COLOR2_INFO 0xa33a
+#define mmCB_COLOR3_INFO 0xa349
+#define mmCB_COLOR4_INFO 0xa358
+#define mmCB_COLOR5_INFO 0xa367
+#define mmCB_COLOR6_INFO 0xa376
+#define mmCB_COLOR7_INFO 0xa385
+#define mmCB_COLOR0_ATTRIB 0xa31d
+#define mmCB_COLOR1_ATTRIB 0xa32c
+#define mmCB_COLOR2_ATTRIB 0xa33b
+#define mmCB_COLOR3_ATTRIB 0xa34a
+#define mmCB_COLOR4_ATTRIB 0xa359
+#define mmCB_COLOR5_ATTRIB 0xa368
+#define mmCB_COLOR6_ATTRIB 0xa377
+#define mmCB_COLOR7_ATTRIB 0xa386
+#define mmCB_COLOR0_DCC_CONTROL 0xa31e
+#define mmCB_COLOR1_DCC_CONTROL 0xa32d
+#define mmCB_COLOR2_DCC_CONTROL 0xa33c
+#define mmCB_COLOR3_DCC_CONTROL 0xa34b
+#define mmCB_COLOR4_DCC_CONTROL 0xa35a
+#define mmCB_COLOR5_DCC_CONTROL 0xa369
+#define mmCB_COLOR6_DCC_CONTROL 0xa378
+#define mmCB_COLOR7_DCC_CONTROL 0xa387
+#define mmCB_COLOR0_CMASK 0xa31f
+#define mmCB_COLOR1_CMASK 0xa32e
+#define mmCB_COLOR2_CMASK 0xa33d
+#define mmCB_COLOR3_CMASK 0xa34c
+#define mmCB_COLOR4_CMASK 0xa35b
+#define mmCB_COLOR5_CMASK 0xa36a
+#define mmCB_COLOR6_CMASK 0xa379
+#define mmCB_COLOR7_CMASK 0xa388
+#define mmCB_COLOR0_CMASK_SLICE 0xa320
+#define mmCB_COLOR1_CMASK_SLICE 0xa32f
+#define mmCB_COLOR2_CMASK_SLICE 0xa33e
+#define mmCB_COLOR3_CMASK_SLICE 0xa34d
+#define mmCB_COLOR4_CMASK_SLICE 0xa35c
+#define mmCB_COLOR5_CMASK_SLICE 0xa36b
+#define mmCB_COLOR6_CMASK_SLICE 0xa37a
+#define mmCB_COLOR7_CMASK_SLICE 0xa389
+#define mmCB_COLOR0_FMASK 0xa321
+#define mmCB_COLOR1_FMASK 0xa330
+#define mmCB_COLOR2_FMASK 0xa33f
+#define mmCB_COLOR3_FMASK 0xa34e
+#define mmCB_COLOR4_FMASK 0xa35d
+#define mmCB_COLOR5_FMASK 0xa36c
+#define mmCB_COLOR6_FMASK 0xa37b
+#define mmCB_COLOR7_FMASK 0xa38a
+#define mmCB_COLOR0_FMASK_SLICE 0xa322
+#define mmCB_COLOR1_FMASK_SLICE 0xa331
+#define mmCB_COLOR2_FMASK_SLICE 0xa340
+#define mmCB_COLOR3_FMASK_SLICE 0xa34f
+#define mmCB_COLOR4_FMASK_SLICE 0xa35e
+#define mmCB_COLOR5_FMASK_SLICE 0xa36d
+#define mmCB_COLOR6_FMASK_SLICE 0xa37c
+#define mmCB_COLOR7_FMASK_SLICE 0xa38b
+#define mmCB_COLOR0_CLEAR_WORD0 0xa323
+#define mmCB_COLOR1_CLEAR_WORD0 0xa332
+#define mmCB_COLOR2_CLEAR_WORD0 0xa341
+#define mmCB_COLOR3_CLEAR_WORD0 0xa350
+#define mmCB_COLOR4_CLEAR_WORD0 0xa35f
+#define mmCB_COLOR5_CLEAR_WORD0 0xa36e
+#define mmCB_COLOR6_CLEAR_WORD0 0xa37d
+#define mmCB_COLOR7_CLEAR_WORD0 0xa38c
+#define mmCB_COLOR0_CLEAR_WORD1 0xa324
+#define mmCB_COLOR1_CLEAR_WORD1 0xa333
+#define mmCB_COLOR2_CLEAR_WORD1 0xa342
+#define mmCB_COLOR3_CLEAR_WORD1 0xa351
+#define mmCB_COLOR4_CLEAR_WORD1 0xa360
+#define mmCB_COLOR5_CLEAR_WORD1 0xa36f
+#define mmCB_COLOR6_CLEAR_WORD1 0xa37e
+#define mmCB_COLOR7_CLEAR_WORD1 0xa38d
+#define mmCB_COLOR0_DCC_BASE 0xa325
+#define mmCB_COLOR1_DCC_BASE 0xa334
+#define mmCB_COLOR2_DCC_BASE 0xa343
+#define mmCB_COLOR3_DCC_BASE 0xa352
+#define mmCB_COLOR4_DCC_BASE 0xa361
+#define mmCB_COLOR5_DCC_BASE 0xa370
+#define mmCB_COLOR6_DCC_BASE 0xa37f
+#define mmCB_COLOR7_DCC_BASE 0xa38e
+#define mmCB_TARGET_MASK 0xa08e
+#define mmCB_SHADER_MASK 0xa08f
+#define mmCB_HW_CONTROL 0x2684
+#define mmCB_HW_CONTROL_1 0x2685
+#define mmCB_HW_CONTROL_2 0x2686
+#define mmCB_HW_CONTROL_3 0x2683
+#define mmCB_DCC_CONFIG 0x2687
+#define mmCB_PERFCOUNTER_FILTER 0xdc00
+#define mmCB_PERFCOUNTER0_SELECT 0xdc01
+#define mmCB_PERFCOUNTER0_SELECT1 0xdc02
+#define mmCB_PERFCOUNTER1_SELECT 0xdc03
+#define mmCB_PERFCOUNTER2_SELECT 0xdc04
+#define mmCB_PERFCOUNTER3_SELECT 0xdc05
+#define mmCB_PERFCOUNTER0_LO 0xd406
+#define mmCB_PERFCOUNTER1_LO 0xd408
+#define mmCB_PERFCOUNTER2_LO 0xd40a
+#define mmCB_PERFCOUNTER3_LO 0xd40c
+#define mmCB_PERFCOUNTER0_HI 0xd407
+#define mmCB_PERFCOUNTER1_HI 0xd409
+#define mmCB_PERFCOUNTER2_HI 0xd40b
+#define mmCB_PERFCOUNTER3_HI 0xd40d
+#define mmCB_CGTT_SCLK_CTRL 0xf0a8
+#define mmCB_DEBUG_BUS_1 0x2699
+#define mmCB_DEBUG_BUS_2 0x269a
+#define mmCB_DEBUG_BUS_3 0x269b
+#define mmCB_DEBUG_BUS_4 0x269c
+#define mmCB_DEBUG_BUS_5 0x269d
+#define mmCB_DEBUG_BUS_6 0x269e
+#define mmCB_DEBUG_BUS_7 0x269f
+#define mmCB_DEBUG_BUS_8 0x26a0
+#define mmCB_DEBUG_BUS_9 0x26a1
+#define mmCB_DEBUG_BUS_10 0x26a2
+#define mmCB_DEBUG_BUS_11 0x26a3
+#define mmCB_DEBUG_BUS_12 0x26a4
+#define mmCB_DEBUG_BUS_13 0x26a5
+#define mmCB_DEBUG_BUS_14 0x26a6
+#define mmCB_DEBUG_BUS_15 0x26a7
+#define mmCB_DEBUG_BUS_16 0x26a8
+#define mmCB_DEBUG_BUS_17 0x26a9
+#define mmCB_DEBUG_BUS_18 0x26aa
+#define mmCB_DEBUG_BUS_19 0x26ab
+#define mmCB_DEBUG_BUS_20 0x26ac
+#define mmCB_DEBUG_BUS_21 0x26ad
+#define mmCB_DEBUG_BUS_22 0x26ae
+#define mmCP_DFY_CNTL 0x3020
+#define mmCP_DFY_STAT 0x3021
+#define mmCP_DFY_ADDR_HI 0x3022
+#define mmCP_DFY_ADDR_LO 0x3023
+#define mmCP_DFY_DATA_0 0x3024
+#define mmCP_DFY_DATA_1 0x3025
+#define mmCP_DFY_DATA_2 0x3026
+#define mmCP_DFY_DATA_3 0x3027
+#define mmCP_DFY_DATA_4 0x3028
+#define mmCP_DFY_DATA_5 0x3029
+#define mmCP_DFY_DATA_6 0x302a
+#define mmCP_DFY_DATA_7 0x302b
+#define mmCP_DFY_DATA_8 0x302c
+#define mmCP_DFY_DATA_9 0x302d
+#define mmCP_DFY_DATA_10 0x302e
+#define mmCP_DFY_DATA_11 0x302f
+#define mmCP_DFY_DATA_12 0x3030
+#define mmCP_DFY_DATA_13 0x3031
+#define mmCP_DFY_DATA_14 0x3032
+#define mmCP_DFY_DATA_15 0x3033
+#define mmCP_DFY_CMD 0x3034
+#define mmCP_CPC_MGCG_SYNC_CNTL 0x3036
+#define mmCP_ATCL1_CNTL 0x303c
+#define mmCP_RB0_BASE 0x3040
+#define mmCP_RB0_BASE_HI 0x30b1
+#define mmCP_RB_BASE 0x3040
+#define mmCP_RB1_BASE 0x3060
+#define mmCP_RB1_BASE_HI 0x30b2
+#define mmCP_RB2_BASE 0x3065
+#define mmCP_RB0_CNTL 0x3041
+#define mmCP_RB_CNTL 0x3041
+#define mmCP_RB1_CNTL 0x3061
+#define mmCP_RB2_CNTL 0x3066
+#define mmCP_RB_RPTR_WR 0x3042
+#define mmCP_RB0_RPTR_ADDR 0x3043
+#define mmCP_RB_RPTR_ADDR 0x3043
+#define mmCP_RB1_RPTR_ADDR 0x3062
+#define mmCP_RB2_RPTR_ADDR 0x3067
+#define mmCP_RB0_RPTR_ADDR_HI 0x3044
+#define mmCP_RB_RPTR_ADDR_HI 0x3044
+#define mmCP_RB1_RPTR_ADDR_HI 0x3063
+#define mmCP_RB2_RPTR_ADDR_HI 0x3068
+#define mmCP_RB0_WPTR 0x3045
+#define mmCP_RB_WPTR 0x3045
+#define mmCP_RB1_WPTR 0x3064
+#define mmCP_RB2_WPTR 0x3069
+#define mmCP_RB_WPTR_POLL_ADDR_LO 0x3046
+#define mmCP_RB_WPTR_POLL_ADDR_HI 0x3047
+#define mmGC_PRIV_MODE 0x3048
+#define mmCP_INT_CNTL 0x3049
+#define mmCP_INT_CNTL_RING0 0x306a
+#define mmCP_INT_CNTL_RING1 0x306b
+#define mmCP_INT_CNTL_RING2 0x306c
+#define mmCP_INT_STATUS 0x304a
+#define mmCP_INT_STATUS_RING0 0x306d
+#define mmCP_INT_STATUS_RING1 0x306e
+#define mmCP_INT_STATUS_RING2 0x306f
+#define mmCP_DEVICE_ID 0x304b
+#define mmCP_RING_PRIORITY_CNTS 0x304c
+#define mmCP_ME0_PIPE_PRIORITY_CNTS 0x304c
+#define mmCP_RING0_PRIORITY 0x304d
+#define mmCP_ME0_PIPE0_PRIORITY 0x304d
+#define mmCP_RING1_PRIORITY 0x304e
+#define mmCP_ME0_PIPE1_PRIORITY 0x304e
+#define mmCP_RING2_PRIORITY 0x304f
+#define mmCP_ME0_PIPE2_PRIORITY 0x304f
+#define mmCP_ENDIAN_SWAP 0x3050
+#define mmCP_RB_VMID 0x3051
+#define mmCP_ME0_PIPE0_VMID 0x3052
+#define mmCP_ME0_PIPE1_VMID 0x3053
+#define mmCP_RB_DOORBELL_CONTROL 0x3059
+#define mmCP_RB_DOORBELL_RANGE_LOWER 0x305a
+#define mmCP_RB_DOORBELL_RANGE_UPPER 0x305b
+#define mmCP_MEC_DOORBELL_RANGE_LOWER 0x305c
+#define mmCP_MEC_DOORBELL_RANGE_UPPER 0x305d
+#define mmCP_PFP_UCODE_ADDR 0xf814
+#define mmCP_PFP_UCODE_DATA 0xf815
+#define mmCP_ME_RAM_RADDR 0xf816
+#define mmCP_ME_RAM_WADDR 0xf816
+#define mmCP_ME_RAM_DATA 0xf817
+#define mmCGTT_CPC_CLK_CTRL 0xf0b2
+#define mmCGTT_CPF_CLK_CTRL 0xf0b1
+#define mmCGTT_CP_CLK_CTRL 0xf0b0
+#define mmCP_CE_UCODE_ADDR 0xf818
+#define mmCP_CE_UCODE_DATA 0xf819
+#define mmCP_MEC_ME1_UCODE_ADDR 0xf81a
+#define mmCP_MEC_ME1_UCODE_DATA 0xf81b
+#define mmCP_MEC_ME2_UCODE_ADDR 0xf81c
+#define mmCP_MEC_ME2_UCODE_DATA 0xf81d
+#define mmCP_MEC1_F32_INT_DIS 0x30bd
+#define mmCP_MEC2_F32_INT_DIS 0x30be
+#define mmCP_PWR_CNTL 0x3078
+#define mmCP_MEM_SLP_CNTL 0x3079
+#define mmCP_ECC_FIRSTOCCURRENCE 0x307a
+#define mmCP_ECC_FIRSTOCCURRENCE_RING0 0x307b
+#define mmCP_ECC_FIRSTOCCURRENCE_RING1 0x307c
+#define mmCP_ECC_FIRSTOCCURRENCE_RING2 0x307d
+#define mmCP_CPF_DEBUG 0x3080
+#define mmCP_PQ_WPTR_POLL_CNTL 0x3083
+#define mmCP_PQ_WPTR_POLL_CNTL1 0x3084
+#define mmCPC_INT_CNTL 0x30b4
+#define mmCP_ME1_PIPE0_INT_CNTL 0x3085
+#define mmCP_ME1_PIPE1_INT_CNTL 0x3086
+#define mmCP_ME1_PIPE2_INT_CNTL 0x3087
+#define mmCP_ME1_PIPE3_INT_CNTL 0x3088
+#define mmCP_ME2_PIPE0_INT_CNTL 0x3089
+#define mmCP_ME2_PIPE1_INT_CNTL 0x308a
+#define mmCP_ME2_PIPE2_INT_CNTL 0x308b
+#define mmCP_ME2_PIPE3_INT_CNTL 0x308c
+#define mmCPC_INT_STATUS 0x30b5
+#define mmCP_ME1_PIPE0_INT_STATUS 0x308d
+#define mmCP_ME1_PIPE1_INT_STATUS 0x308e
+#define mmCP_ME1_PIPE2_INT_STATUS 0x308f
+#define mmCP_ME1_PIPE3_INT_STATUS 0x3090
+#define mmCP_ME2_PIPE0_INT_STATUS 0x3091
+#define mmCP_ME2_PIPE1_INT_STATUS 0x3092
+#define mmCP_ME2_PIPE2_INT_STATUS 0x3093
+#define mmCP_ME2_PIPE3_INT_STATUS 0x3094
+#define mmCP_ME1_INT_STAT_DEBUG 0x3095
+#define mmCP_ME2_INT_STAT_DEBUG 0x3096
+#define mmCP_ME1_PIPE_PRIORITY_CNTS 0x3099
+#define mmCP_ME1_PIPE0_PRIORITY 0x309a
+#define mmCP_ME1_PIPE1_PRIORITY 0x309b
+#define mmCP_ME1_PIPE2_PRIORITY 0x309c
+#define mmCP_ME1_PIPE3_PRIORITY 0x309d
+#define mmCP_ME2_PIPE_PRIORITY_CNTS 0x309e
+#define mmCP_ME2_PIPE0_PRIORITY 0x309f
+#define mmCP_ME2_PIPE1_PRIORITY 0x30a0
+#define mmCP_ME2_PIPE2_PRIORITY 0x30a1
+#define mmCP_ME2_PIPE3_PRIORITY 0x30a2
+#define mmCP_CE_PRGRM_CNTR_START 0x30a3
+#define mmCP_PFP_PRGRM_CNTR_START 0x30a4
+#define mmCP_ME_PRGRM_CNTR_START 0x30a5
+#define mmCP_MEC1_PRGRM_CNTR_START 0x30a6
+#define mmCP_MEC2_PRGRM_CNTR_START 0x30a7
+#define mmCP_CE_INTR_ROUTINE_START 0x30a8
+#define mmCP_PFP_INTR_ROUTINE_START 0x30a9
+#define mmCP_ME_INTR_ROUTINE_START 0x30aa
+#define mmCP_MEC1_INTR_ROUTINE_START 0x30ab
+#define mmCP_MEC2_INTR_ROUTINE_START 0x30ac
+#define mmCP_CONTEXT_CNTL 0x30ad
+#define mmCP_MAX_CONTEXT 0x30ae
+#define mmCP_IQ_WAIT_TIME1 0x30af
+#define mmCP_IQ_WAIT_TIME2 0x30b0
+#define mmCP_VMID_RESET 0x30b3
+#define mmCP_VMID_PREEMPT 0x30b6
+#define mmCP_VMID_STATUS 0x30bf
+#define mmCPC_INT_CNTX_ID 0x30b7
+#define mmCP_PQ_STATUS 0x30b8
+#define mmCP_CPC_IC_BASE_LO 0x30b9
+#define mmCP_CPC_IC_BASE_HI 0x30ba
+#define mmCP_CPC_IC_BASE_CNTL 0x30bb
+#define mmCP_CPC_IC_OP_CNTL 0x30bc
+#define mmCP_CPC_STATUS 0x2084
+#define mmCP_CPC_BUSY_STAT 0x2085
+#define mmCP_CPC_STALLED_STAT1 0x2086
+#define mmCP_CPF_STATUS 0x2087
+#define mmCP_CPF_BUSY_STAT 0x2088
+#define mmCP_CPF_STALLED_STAT1 0x2089
+#define mmCP_CPC_GRBM_FREE_COUNT 0x208b
+#define mmCP_MEC_CNTL 0x208d
+#define mmCP_MEC_ME1_HEADER_DUMP 0x208e
+#define mmCP_MEC_ME2_HEADER_DUMP 0x208f
+#define mmCP_CPC_SCRATCH_INDEX 0x2090
+#define mmCP_CPC_SCRATCH_DATA 0x2091
+#define mmCPG_PERFCOUNTER1_SELECT 0xd800
+#define mmCPG_PERFCOUNTER1_LO 0xd000
+#define mmCPG_PERFCOUNTER1_HI 0xd001
+#define mmCPG_PERFCOUNTER0_SELECT1 0xd801
+#define mmCPG_PERFCOUNTER0_SELECT 0xd802
+#define mmCPG_PERFCOUNTER0_LO 0xd002
+#define mmCPG_PERFCOUNTER0_HI 0xd003
+#define mmCPC_PERFCOUNTER1_SELECT 0xd803
+#define mmCPC_PERFCOUNTER1_LO 0xd004
+#define mmCPC_PERFCOUNTER1_HI 0xd005
+#define mmCPC_PERFCOUNTER0_SELECT1 0xd804
+#define mmCPC_PERFCOUNTER0_SELECT 0xd809
+#define mmCPC_PERFCOUNTER0_LO 0xd006
+#define mmCPC_PERFCOUNTER0_HI 0xd007
+#define mmCPF_PERFCOUNTER1_SELECT 0xd805
+#define mmCPF_PERFCOUNTER1_LO 0xd008
+#define mmCPF_PERFCOUNTER1_HI 0xd009
+#define mmCPF_PERFCOUNTER0_SELECT1 0xd806
+#define mmCPF_PERFCOUNTER0_SELECT 0xd807
+#define mmCPF_PERFCOUNTER0_LO 0xd00a
+#define mmCPF_PERFCOUNTER0_HI 0xd00b
+#define mmCP_CPC_HALT_HYST_COUNT 0x20a7
+#define mmCP_DRAW_OBJECT 0xd810
+#define mmCP_DRAW_OBJECT_COUNTER 0xd811
+#define mmCP_DRAW_WINDOW_MASK_HI 0xd812
+#define mmCP_DRAW_WINDOW_HI 0xd813
+#define mmCP_DRAW_WINDOW_LO 0xd814
+#define mmCP_DRAW_WINDOW_CNTL 0xd815
+#define mmCP_PRT_LOD_STATS_CNTL0 0x20ad
+#define mmCP_PRT_LOD_STATS_CNTL1 0x20ae
+#define mmCP_PRT_LOD_STATS_CNTL2 0x20af
+#define mmCP_CE_COMPARE_COUNT 0x20c0
+#define mmCP_CE_DE_COUNT 0x20c1
+#define mmCP_DE_CE_COUNT 0x20c2
+#define mmCP_DE_LAST_INVAL_COUNT 0x20c3
+#define mmCP_DE_DE_COUNT 0x20c4
+#define mmCP_EOP_DONE_EVENT_CNTL 0xc0d5
+#define mmCP_EOP_DONE_DATA_CNTL 0xc0d6
+#define mmCP_EOP_DONE_CNTX_ID 0xc0d7
+#define mmCP_EOP_DONE_ADDR_LO 0xc000
+#define mmCP_EOP_DONE_ADDR_HI 0xc001
+#define mmCP_EOP_DONE_DATA_LO 0xc002
+#define mmCP_EOP_DONE_DATA_HI 0xc003
+#define mmCP_EOP_LAST_FENCE_LO 0xc004
+#define mmCP_EOP_LAST_FENCE_HI 0xc005
+#define mmCP_STREAM_OUT_ADDR_LO 0xc006
+#define mmCP_STREAM_OUT_ADDR_HI 0xc007
+#define mmCP_NUM_PRIM_WRITTEN_COUNT0_LO 0xc008
+#define mmCP_NUM_PRIM_WRITTEN_COUNT0_HI 0xc009
+#define mmCP_NUM_PRIM_NEEDED_COUNT0_LO 0xc00a
+#define mmCP_NUM_PRIM_NEEDED_COUNT0_HI 0xc00b
+#define mmCP_NUM_PRIM_WRITTEN_COUNT1_LO 0xc00c
+#define mmCP_NUM_PRIM_WRITTEN_COUNT1_HI 0xc00d
+#define mmCP_NUM_PRIM_NEEDED_COUNT1_LO 0xc00e
+#define mmCP_NUM_PRIM_NEEDED_COUNT1_HI 0xc00f
+#define mmCP_NUM_PRIM_WRITTEN_COUNT2_LO 0xc010
+#define mmCP_NUM_PRIM_WRITTEN_COUNT2_HI 0xc011
+#define mmCP_NUM_PRIM_NEEDED_COUNT2_LO 0xc012
+#define mmCP_NUM_PRIM_NEEDED_COUNT2_HI 0xc013
+#define mmCP_NUM_PRIM_WRITTEN_COUNT3_LO 0xc014
+#define mmCP_NUM_PRIM_WRITTEN_COUNT3_HI 0xc015
+#define mmCP_NUM_PRIM_NEEDED_COUNT3_LO 0xc016
+#define mmCP_NUM_PRIM_NEEDED_COUNT3_HI 0xc017
+#define mmCP_PIPE_STATS_ADDR_LO 0xc018
+#define mmCP_PIPE_STATS_ADDR_HI 0xc019
+#define mmCP_VGT_IAVERT_COUNT_LO 0xc01a
+#define mmCP_VGT_IAVERT_COUNT_HI 0xc01b
+#define mmCP_VGT_IAPRIM_COUNT_LO 0xc01c
+#define mmCP_VGT_IAPRIM_COUNT_HI 0xc01d
+#define mmCP_VGT_GSPRIM_COUNT_LO 0xc01e
+#define mmCP_VGT_GSPRIM_COUNT_HI 0xc01f
+#define mmCP_VGT_VSINVOC_COUNT_LO 0xc020
+#define mmCP_VGT_VSINVOC_COUNT_HI 0xc021
+#define mmCP_VGT_GSINVOC_COUNT_LO 0xc022
+#define mmCP_VGT_GSINVOC_COUNT_HI 0xc023
+#define mmCP_VGT_HSINVOC_COUNT_LO 0xc024
+#define mmCP_VGT_HSINVOC_COUNT_HI 0xc025
+#define mmCP_VGT_DSINVOC_COUNT_LO 0xc026
+#define mmCP_VGT_DSINVOC_COUNT_HI 0xc027
+#define mmCP_PA_CINVOC_COUNT_LO 0xc028
+#define mmCP_PA_CINVOC_COUNT_HI 0xc029
+#define mmCP_PA_CPRIM_COUNT_LO 0xc02a
+#define mmCP_PA_CPRIM_COUNT_HI 0xc02b
+#define mmCP_SC_PSINVOC_COUNT0_LO 0xc02c
+#define mmCP_SC_PSINVOC_COUNT0_HI 0xc02d
+#define mmCP_SC_PSINVOC_COUNT1_LO 0xc02e
+#define mmCP_SC_PSINVOC_COUNT1_HI 0xc02f
+#define mmCP_VGT_CSINVOC_COUNT_LO 0xc030
+#define mmCP_VGT_CSINVOC_COUNT_HI 0xc031
+#define mmCP_PIPE_STATS_CONTROL 0xc03d
+#define mmCP_STREAM_OUT_CONTROL 0xc03e
+#define mmCP_STRMOUT_CNTL 0xc03f
+#define mmSCRATCH_REG0 0xc040
+#define mmSCRATCH_REG1 0xc041
+#define mmSCRATCH_REG2 0xc042
+#define mmSCRATCH_REG3 0xc043
+#define mmSCRATCH_REG4 0xc044
+#define mmSCRATCH_REG5 0xc045
+#define mmSCRATCH_REG6 0xc046
+#define mmSCRATCH_REG7 0xc047
+#define mmSCRATCH_UMSK 0xc050
+#define mmSCRATCH_ADDR 0xc051
+#define mmCP_PFP_ATOMIC_PREOP_LO 0xc052
+#define mmCP_PFP_ATOMIC_PREOP_HI 0xc053
+#define mmCP_PFP_GDS_ATOMIC0_PREOP_LO 0xc054
+#define mmCP_PFP_GDS_ATOMIC0_PREOP_HI 0xc055
+#define mmCP_PFP_GDS_ATOMIC1_PREOP_LO 0xc056
+#define mmCP_PFP_GDS_ATOMIC1_PREOP_HI 0xc057
+#define mmCP_APPEND_ADDR_LO 0xc058
+#define mmCP_APPEND_ADDR_HI 0xc059
+#define mmCP_APPEND_DATA 0xc05a
+#define mmCP_APPEND_LAST_CS_FENCE 0xc05b
+#define mmCP_APPEND_LAST_PS_FENCE 0xc05c
+#define mmCP_ATOMIC_PREOP_LO 0xc05d
+#define mmCP_ME_ATOMIC_PREOP_LO 0xc05d
+#define mmCP_ATOMIC_PREOP_HI 0xc05e
+#define mmCP_ME_ATOMIC_PREOP_HI 0xc05e
+#define mmCP_GDS_ATOMIC0_PREOP_LO 0xc05f
+#define mmCP_ME_GDS_ATOMIC0_PREOP_LO 0xc05f
+#define mmCP_GDS_ATOMIC0_PREOP_HI 0xc060
+#define mmCP_ME_GDS_ATOMIC0_PREOP_HI 0xc060
+#define mmCP_GDS_ATOMIC1_PREOP_LO 0xc061
+#define mmCP_ME_GDS_ATOMIC1_PREOP_LO 0xc061
+#define mmCP_GDS_ATOMIC1_PREOP_HI 0xc062
+#define mmCP_ME_GDS_ATOMIC1_PREOP_HI 0xc062
+#define mmCP_ME_MC_WADDR_LO 0xc069
+#define mmCP_ME_MC_WADDR_HI 0xc06a
+#define mmCP_ME_MC_WDATA_LO 0xc06b
+#define mmCP_ME_MC_WDATA_HI 0xc06c
+#define mmCP_ME_MC_RADDR_LO 0xc06d
+#define mmCP_ME_MC_RADDR_HI 0xc06e
+#define mmCP_SEM_WAIT_TIMER 0xc06f
+#define mmCP_SIG_SEM_ADDR_LO 0xc070
+#define mmCP_SIG_SEM_ADDR_HI 0xc071
+#define mmCP_WAIT_SEM_ADDR_LO 0xc075
+#define mmCP_WAIT_SEM_ADDR_HI 0xc076
+#define mmCP_WAIT_REG_MEM_TIMEOUT 0xc074
+#define mmCP_COHER_START_DELAY 0xc07b
+#define mmCP_COHER_CNTL 0xc07c
+#define mmCP_COHER_SIZE 0xc07d
+#define mmCP_COHER_SIZE_HI 0xc08c
+#define mmCP_COHER_BASE 0xc07e
+#define mmCP_COHER_BASE_HI 0xc079
+#define mmCP_COHER_STATUS 0xc07f
+#define mmCOHER_DEST_BASE_0 0xa092
+#define mmCOHER_DEST_BASE_1 0xa093
+#define mmCOHER_DEST_BASE_2 0xa07e
+#define mmCOHER_DEST_BASE_3 0xa07f
+#define mmCOHER_DEST_BASE_HI_0 0xa07a
+#define mmCOHER_DEST_BASE_HI_1 0xa07b
+#define mmCOHER_DEST_BASE_HI_2 0xa07c
+#define mmCOHER_DEST_BASE_HI_3 0xa07d
+#define mmCP_DMA_ME_SRC_ADDR 0xc080
+#define mmCP_DMA_ME_SRC_ADDR_HI 0xc081
+#define mmCP_DMA_ME_DST_ADDR 0xc082
+#define mmCP_DMA_ME_DST_ADDR_HI 0xc083
+#define mmCP_DMA_ME_CONTROL 0xc078
+#define mmCP_DMA_ME_COMMAND 0xc084
+#define mmCP_DMA_PFP_SRC_ADDR 0xc085
+#define mmCP_DMA_PFP_SRC_ADDR_HI 0xc086
+#define mmCP_DMA_PFP_DST_ADDR 0xc087
+#define mmCP_DMA_PFP_DST_ADDR_HI 0xc088
+#define mmCP_DMA_PFP_CONTROL 0xc077
+#define mmCP_DMA_PFP_COMMAND 0xc089
+#define mmCP_DMA_CNTL 0xc08a
+#define mmCP_DMA_READ_TAGS 0xc08b
+#define mmCP_PFP_IB_CONTROL 0xc08d
+#define mmCP_PFP_LOAD_CONTROL 0xc08e
+#define mmCP_SCRATCH_INDEX 0xc08f
+#define mmCP_SCRATCH_DATA 0xc090
+#define mmCP_RB_OFFSET 0xc091
+#define mmCP_IB1_OFFSET 0xc092
+#define mmCP_IB2_OFFSET 0xc093
+#define mmCP_IB1_PREAMBLE_BEGIN 0xc094
+#define mmCP_IB1_PREAMBLE_END 0xc095
+#define mmCP_IB2_PREAMBLE_BEGIN 0xc096
+#define mmCP_IB2_PREAMBLE_END 0xc097
+#define mmCP_CE_IB1_OFFSET 0xc098
+#define mmCP_CE_IB2_OFFSET 0xc099
+#define mmCP_CE_COUNTER 0xc09a
+#define mmCP_CE_RB_OFFSET 0xc09b
+#define mmCP_PFP_COMPLETION_STATUS 0xc0ec
+#define mmCP_CE_COMPLETION_STATUS 0xc0ed
+#define mmCP_PRED_NOT_VISIBLE 0xc0ee
+#define mmCP_PFP_METADATA_BASE_ADDR 0xc0f0
+#define mmCP_PFP_METADATA_BASE_ADDR_HI 0xc0f1
+#define mmCP_CE_METADATA_BASE_ADDR 0xc0f2
+#define mmCP_CE_METADATA_BASE_ADDR_HI 0xc0f3
+#define mmCP_DRAW_INDX_INDR_ADDR 0xc0f4
+#define mmCP_DRAW_INDX_INDR_ADDR_HI 0xc0f5
+#define mmCP_DISPATCH_INDR_ADDR 0xc0f6
+#define mmCP_DISPATCH_INDR_ADDR_HI 0xc0f7
+#define mmCP_INDEX_BASE_ADDR 0xc0f8
+#define mmCP_INDEX_BASE_ADDR_HI 0xc0f9
+#define mmCP_INDEX_TYPE 0xc0fa
+#define mmCP_GDS_BKUP_ADDR 0xc0fb
+#define mmCP_GDS_BKUP_ADDR_HI 0xc0fc
+#define mmCP_SAMPLE_STATUS 0xc0fd
+#define mmCP_STALLED_STAT1 0x219d
+#define mmCP_STALLED_STAT2 0x219e
+#define mmCP_STALLED_STAT3 0x219c
+#define mmCP_BUSY_STAT 0x219f
+#define mmCP_STAT 0x21a0
+#define mmCP_ME_HEADER_DUMP 0x21a1
+#define mmCP_PFP_HEADER_DUMP 0x21a2
+#define mmCP_GRBM_FREE_COUNT 0x21a3
+#define mmCP_CE_HEADER_DUMP 0x21a4
+#define mmCP_CSF_STAT 0x21b4
+#define mmCP_CSF_CNTL 0x21b5
+#define mmCP_ME_CNTL 0x21b6
+#define mmCP_CNTX_STAT 0x21b8
+#define mmCP_ME_PREEMPTION 0x21b9
+#define mmCP_RB0_RPTR 0x21c0
+#define mmCP_RB_RPTR 0x21c0
+#define mmCP_RB1_RPTR 0x21bf
+#define mmCP_RB2_RPTR 0x21be
+#define mmCP_RB_WPTR_DELAY 0x21c1
+#define mmCP_RB_WPTR_POLL_CNTL 0x21c2
+#define mmCP_CE_INIT_BASE_LO 0xc0c3
+#define mmCP_CE_INIT_BASE_HI 0xc0c4
+#define mmCP_CE_INIT_BUFSZ 0xc0c5
+#define mmCP_CE_IB1_BASE_LO 0xc0c6
+#define mmCP_CE_IB1_BASE_HI 0xc0c7
+#define mmCP_CE_IB1_BUFSZ 0xc0c8
+#define mmCP_CE_IB2_BASE_LO 0xc0c9
+#define mmCP_CE_IB2_BASE_HI 0xc0ca
+#define mmCP_CE_IB2_BUFSZ 0xc0cb
+#define mmCP_IB1_BASE_LO 0xc0cc
+#define mmCP_IB1_BASE_HI 0xc0cd
+#define mmCP_IB1_BUFSZ 0xc0ce
+#define mmCP_IB2_BASE_LO 0xc0cf
+#define mmCP_IB2_BASE_HI 0xc0d0
+#define mmCP_IB2_BUFSZ 0xc0d1
+#define mmCP_ST_BASE_LO 0xc0d2
+#define mmCP_ST_BASE_HI 0xc0d3
+#define mmCP_ST_BUFSZ 0xc0d4
+#define mmCP_ROQ_THRESHOLDS 0x21bc
+#define mmCP_MEQ_STQ_THRESHOLD 0x21bd
+#define mmCP_ROQ1_THRESHOLDS 0x21d5
+#define mmCP_ROQ2_THRESHOLDS 0x21d6
+#define mmCP_STQ_THRESHOLDS 0x21d7
+#define mmCP_QUEUE_THRESHOLDS 0x21d8
+#define mmCP_MEQ_THRESHOLDS 0x21d9
+#define mmCP_ROQ_AVAIL 0x21da
+#define mmCP_STQ_AVAIL 0x21db
+#define mmCP_ROQ2_AVAIL 0x21dc
+#define mmCP_MEQ_AVAIL 0x21dd
+#define mmCP_CMD_INDEX 0x21de
+#define mmCP_CMD_DATA 0x21df
+#define mmCP_ROQ_RB_STAT 0x21e0
+#define mmCP_ROQ_IB1_STAT 0x21e1
+#define mmCP_ROQ_IB2_STAT 0x21e2
+#define mmCP_STQ_STAT 0x21e3
+#define mmCP_STQ_WR_STAT 0x21e4
+#define mmCP_MEQ_STAT 0x21e5
+#define mmCP_CEQ1_AVAIL 0x21e6
+#define mmCP_CEQ2_AVAIL 0x21e7
+#define mmCP_CE_ROQ_RB_STAT 0x21e8
+#define mmCP_CE_ROQ_IB1_STAT 0x21e9
+#define mmCP_CE_ROQ_IB2_STAT 0x21ea
+#define mmCP_INT_STAT_DEBUG 0x21f7
+#define mmCP_PERFMON_CNTL 0xd808
+#define mmCP_PERFMON_CNTX_CNTL 0xa0d8
+#define mmCP_RINGID 0xa0d9
+#define mmCP_PIPEID 0xa0d9
+#define mmCP_VMID 0xa0da
+#define mmCP_HPD_ROQ_OFFSETS 0x3240
+#define mmCP_HPD_STATUS0 0x3241
+#define mmCP_MQD_BASE_ADDR 0x3245
+#define mmCP_MQD_BASE_ADDR_HI 0x3246
+#define mmCP_HQD_ACTIVE 0x3247
+#define mmCP_HQD_VMID 0x3248
+#define mmCP_HQD_PERSISTENT_STATE 0x3249
+#define mmCP_HQD_PIPE_PRIORITY 0x324a
+#define mmCP_HQD_QUEUE_PRIORITY 0x324b
+#define mmCP_HQD_QUANTUM 0x324c
+#define mmCP_HQD_PQ_BASE 0x324d
+#define mmCP_HQD_PQ_BASE_HI 0x324e
+#define mmCP_HQD_PQ_RPTR 0x324f
+#define mmCP_HQD_PQ_RPTR_REPORT_ADDR 0x3250
+#define mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI 0x3251
+#define mmCP_HQD_PQ_WPTR_POLL_ADDR 0x3252
+#define mmCP_HQD_PQ_WPTR_POLL_ADDR_HI 0x3253
+#define mmCP_HQD_PQ_DOORBELL_CONTROL 0x3254
+#define mmCP_HQD_PQ_WPTR 0x3255
+#define mmCP_HQD_PQ_CONTROL 0x3256
+#define mmCP_HQD_IB_BASE_ADDR 0x3257
+#define mmCP_HQD_IB_BASE_ADDR_HI 0x3258
+#define mmCP_HQD_IB_RPTR 0x3259
+#define mmCP_HQD_IB_CONTROL 0x325a
+#define mmCP_HQD_IQ_TIMER 0x325b
+#define mmCP_HQD_IQ_RPTR 0x325c
+#define mmCP_HQD_DEQUEUE_REQUEST 0x325d
+#define mmCP_HQD_DMA_OFFLOAD 0x325e
+#define mmCP_HQD_OFFLOAD 0x325e
+#define mmCP_HQD_SEMA_CMD 0x325f
+#define mmCP_HQD_MSG_TYPE 0x3260
+#define mmCP_HQD_ATOMIC0_PREOP_LO 0x3261
+#define mmCP_HQD_ATOMIC0_PREOP_HI 0x3262
+#define mmCP_HQD_ATOMIC1_PREOP_LO 0x3263
+#define mmCP_HQD_ATOMIC1_PREOP_HI 0x3264
+#define mmCP_HQD_HQ_SCHEDULER0 0x3265
+#define mmCP_HQD_HQ_STATUS0 0x3265
+#define mmCP_HQD_HQ_SCHEDULER1 0x3266
+#define mmCP_HQD_HQ_CONTROL0 0x3266
+#define mmCP_MQD_CONTROL 0x3267
+#define mmCP_HQD_HQ_STATUS1 0x3268
+#define mmCP_HQD_HQ_CONTROL1 0x3269
+#define mmCP_HQD_EOP_BASE_ADDR 0x326a
+#define mmCP_HQD_EOP_BASE_ADDR_HI 0x326b
+#define mmCP_HQD_EOP_CONTROL 0x326c
+#define mmCP_HQD_EOP_RPTR 0x326d
+#define mmCP_HQD_EOP_WPTR 0x326e
+#define mmCP_HQD_EOP_EVENTS 0x326f
+#define mmCP_HQD_CTX_SAVE_BASE_ADDR_LO 0x3270
+#define mmCP_HQD_CTX_SAVE_BASE_ADDR_HI 0x3271
+#define mmCP_HQD_CTX_SAVE_CONTROL 0x3272
+#define mmCP_HQD_CNTL_STACK_OFFSET 0x3273
+#define mmCP_HQD_CNTL_STACK_SIZE 0x3274
+#define mmCP_HQD_WG_STATE_OFFSET 0x3275
+#define mmCP_HQD_CTX_SAVE_SIZE 0x3276
+#define mmCP_HQD_GDS_RESOURCE_STATE 0x3277
+#define mmCP_HQD_ERROR 0x3278
+#define mmCP_HQD_EOP_WPTR_MEM 0x3279
+#define mmCP_HQD_EOP_DONES 0x327a
+#define mmDB_Z_READ_BASE 0xa012
+#define mmDB_STENCIL_READ_BASE 0xa013
+#define mmDB_Z_WRITE_BASE 0xa014
+#define mmDB_STENCIL_WRITE_BASE 0xa015
+#define mmDB_DEPTH_INFO 0xa00f
+#define mmDB_Z_INFO 0xa010
+#define mmDB_STENCIL_INFO 0xa011
+#define mmDB_DEPTH_SIZE 0xa016
+#define mmDB_DEPTH_SLICE 0xa017
+#define mmDB_DEPTH_VIEW 0xa002
+#define mmDB_RENDER_CONTROL 0xa000
+#define mmDB_COUNT_CONTROL 0xa001
+#define mmDB_RENDER_OVERRIDE 0xa003
+#define mmDB_RENDER_OVERRIDE2 0xa004
+#define mmDB_EQAA 0xa201
+#define mmDB_SHADER_CONTROL 0xa203
+#define mmDB_DEPTH_BOUNDS_MIN 0xa008
+#define mmDB_DEPTH_BOUNDS_MAX 0xa009
+#define mmDB_STENCIL_CLEAR 0xa00a
+#define mmDB_DEPTH_CLEAR 0xa00b
+#define mmDB_HTILE_DATA_BASE 0xa005
+#define mmDB_HTILE_SURFACE 0xa2af
+#define mmDB_PRELOAD_CONTROL 0xa2b2
+#define mmDB_STENCILREFMASK 0xa10c
+#define mmDB_STENCILREFMASK_BF 0xa10d
+#define mmDB_SRESULTS_COMPARE_STATE0 0xa2b0
+#define mmDB_SRESULTS_COMPARE_STATE1 0xa2b1
+#define mmDB_DEPTH_CONTROL 0xa200
+#define mmDB_STENCIL_CONTROL 0xa10b
+#define mmDB_ALPHA_TO_MASK 0xa2dc
+#define mmDB_PERFCOUNTER0_SELECT 0xdc40
+#define mmDB_PERFCOUNTER1_SELECT 0xdc42
+#define mmDB_PERFCOUNTER2_SELECT 0xdc44
+#define mmDB_PERFCOUNTER3_SELECT 0xdc46
+#define mmDB_PERFCOUNTER0_SELECT1 0xdc41
+#define mmDB_PERFCOUNTER1_SELECT1 0xdc43
+#define mmDB_PERFCOUNTER0_LO 0xd440
+#define mmDB_PERFCOUNTER1_LO 0xd442
+#define mmDB_PERFCOUNTER2_LO 0xd444
+#define mmDB_PERFCOUNTER3_LO 0xd446
+#define mmDB_PERFCOUNTER0_HI 0xd441
+#define mmDB_PERFCOUNTER1_HI 0xd443
+#define mmDB_PERFCOUNTER2_HI 0xd445
+#define mmDB_PERFCOUNTER3_HI 0xd447
+#define mmDB_DEBUG 0x260c
+#define mmDB_DEBUG2 0x260d
+#define mmDB_DEBUG3 0x260e
+#define mmDB_DEBUG4 0x260f
+#define mmDB_CREDIT_LIMIT 0x2614
+#define mmDB_WATERMARKS 0x2615
+#define mmDB_SUBTILE_CONTROL 0x2616
+#define mmDB_FREE_CACHELINES 0x2617
+#define mmDB_FIFO_DEPTH1 0x2618
+#define mmDB_FIFO_DEPTH2 0x2619
+#define mmDB_CGTT_CLK_CTRL_0 0xf0a4
+#define mmDB_ZPASS_COUNT_LOW 0xc3fe
+#define mmDB_ZPASS_COUNT_HI 0xc3ff
+#define mmDB_RING_CONTROL 0x261b
+#define mmDB_READ_DEBUG_0 0x2620
+#define mmDB_READ_DEBUG_1 0x2621
+#define mmDB_READ_DEBUG_2 0x2622
+#define mmDB_READ_DEBUG_3 0x2623
+#define mmDB_READ_DEBUG_4 0x2624
+#define mmDB_READ_DEBUG_5 0x2625
+#define mmDB_READ_DEBUG_6 0x2626
+#define mmDB_READ_DEBUG_7 0x2627
+#define mmDB_READ_DEBUG_8 0x2628
+#define mmDB_READ_DEBUG_9 0x2629
+#define mmDB_READ_DEBUG_A 0x262a
+#define mmDB_READ_DEBUG_B 0x262b
+#define mmDB_READ_DEBUG_C 0x262c
+#define mmDB_READ_DEBUG_D 0x262d
+#define mmDB_READ_DEBUG_E 0x262e
+#define mmDB_READ_DEBUG_F 0x262f
+#define mmDB_OCCLUSION_COUNT0_LOW 0xc3c0
+#define mmDB_OCCLUSION_COUNT0_HI 0xc3c1
+#define mmDB_OCCLUSION_COUNT1_LOW 0xc3c2
+#define mmDB_OCCLUSION_COUNT1_HI 0xc3c3
+#define mmDB_OCCLUSION_COUNT2_LOW 0xc3c4
+#define mmDB_OCCLUSION_COUNT2_HI 0xc3c5
+#define mmDB_OCCLUSION_COUNT3_LOW 0xc3c6
+#define mmDB_OCCLUSION_COUNT3_HI 0xc3c7
+#define mmCC_RB_REDUNDANCY 0x263c
+#define mmCC_RB_BACKEND_DISABLE 0x263d
+#define mmGC_USER_RB_REDUNDANCY 0x26de
+#define mmGC_USER_RB_BACKEND_DISABLE 0x26df
+#define mmGB_ADDR_CONFIG 0x263e
+#define mmGB_BACKEND_MAP 0x263f
+#define mmGB_GPU_ID 0x2640
+#define mmCC_RB_DAISY_CHAIN 0x2641
+#define mmGB_TILE_MODE0 0x2644
+#define mmGB_TILE_MODE1 0x2645
+#define mmGB_TILE_MODE2 0x2646
+#define mmGB_TILE_MODE3 0x2647
+#define mmGB_TILE_MODE4 0x2648
+#define mmGB_TILE_MODE5 0x2649
+#define mmGB_TILE_MODE6 0x264a
+#define mmGB_TILE_MODE7 0x264b
+#define mmGB_TILE_MODE8 0x264c
+#define mmGB_TILE_MODE9 0x264d
+#define mmGB_TILE_MODE10 0x264e
+#define mmGB_TILE_MODE11 0x264f
+#define mmGB_TILE_MODE12 0x2650
+#define mmGB_TILE_MODE13 0x2651
+#define mmGB_TILE_MODE14 0x2652
+#define mmGB_TILE_MODE15 0x2653
+#define mmGB_TILE_MODE16 0x2654
+#define mmGB_TILE_MODE17 0x2655
+#define mmGB_TILE_MODE18 0x2656
+#define mmGB_TILE_MODE19 0x2657
+#define mmGB_TILE_MODE20 0x2658
+#define mmGB_TILE_MODE21 0x2659
+#define mmGB_TILE_MODE22 0x265a
+#define mmGB_TILE_MODE23 0x265b
+#define mmGB_TILE_MODE24 0x265c
+#define mmGB_TILE_MODE25 0x265d
+#define mmGB_TILE_MODE26 0x265e
+#define mmGB_TILE_MODE27 0x265f
+#define mmGB_TILE_MODE28 0x2660
+#define mmGB_TILE_MODE29 0x2661
+#define mmGB_TILE_MODE30 0x2662
+#define mmGB_TILE_MODE31 0x2663
+#define mmGB_MACROTILE_MODE0 0x2664
+#define mmGB_MACROTILE_MODE1 0x2665
+#define mmGB_MACROTILE_MODE2 0x2666
+#define mmGB_MACROTILE_MODE3 0x2667
+#define mmGB_MACROTILE_MODE4 0x2668
+#define mmGB_MACROTILE_MODE5 0x2669
+#define mmGB_MACROTILE_MODE6 0x266a
+#define mmGB_MACROTILE_MODE7 0x266b
+#define mmGB_MACROTILE_MODE8 0x266c
+#define mmGB_MACROTILE_MODE9 0x266d
+#define mmGB_MACROTILE_MODE10 0x266e
+#define mmGB_MACROTILE_MODE11 0x266f
+#define mmGB_MACROTILE_MODE12 0x2670
+#define mmGB_MACROTILE_MODE13 0x2671
+#define mmGB_MACROTILE_MODE14 0x2672
+#define mmGB_MACROTILE_MODE15 0x2673
+#define mmGB_EDC_MODE 0x307e
+#define mmCC_GC_EDC_CONFIG 0x3098
+#define mmRAS_SIGNATURE_CONTROL 0x3380
+#define mmRAS_SIGNATURE_MASK 0x3381
+#define mmRAS_SX_SIGNATURE0 0x3382
+#define mmRAS_SX_SIGNATURE1 0x3383
+#define mmRAS_SX_SIGNATURE2 0x3384
+#define mmRAS_SX_SIGNATURE3 0x3385
+#define mmRAS_DB_SIGNATURE0 0x338b
+#define mmRAS_PA_SIGNATURE0 0x338c
+#define mmRAS_VGT_SIGNATURE0 0x338d
+#define mmRAS_SC_SIGNATURE0 0x338f
+#define mmRAS_SC_SIGNATURE1 0x3390
+#define mmRAS_SC_SIGNATURE2 0x3391
+#define mmRAS_SC_SIGNATURE3 0x3392
+#define mmRAS_SC_SIGNATURE4 0x3393
+#define mmRAS_SC_SIGNATURE5 0x3394
+#define mmRAS_SC_SIGNATURE6 0x3395
+#define mmRAS_SC_SIGNATURE7 0x3396
+#define mmRAS_IA_SIGNATURE0 0x3397
+#define mmRAS_IA_SIGNATURE1 0x3398
+#define mmRAS_SPI_SIGNATURE0 0x3399
+#define mmRAS_SPI_SIGNATURE1 0x339a
+#define mmRAS_TA_SIGNATURE0 0x339b
+#define mmRAS_TD_SIGNATURE0 0x339c
+#define mmRAS_CB_SIGNATURE0 0x339d
+#define mmRAS_BCI_SIGNATURE0 0x339e
+#define mmRAS_BCI_SIGNATURE1 0x339f
+#define mmRAS_TA_SIGNATURE1 0x33a0
+#define mmGRBM_HYP_CAM_INDEX 0xf83e
+#define mmGRBM_CAM_INDEX 0xf83e
+#define mmGRBM_HYP_CAM_DATA 0xf83f
+#define mmGRBM_CAM_DATA 0xf83f
+#define mmGRBM_CNTL 0x2000
+#define mmGRBM_SKEW_CNTL 0x2001
+#define mmGRBM_PWR_CNTL 0x2003
+#define mmGRBM_STATUS 0x2004
+#define mmGRBM_STATUS2 0x2002
+#define mmGRBM_STATUS_SE0 0x2005
+#define mmGRBM_STATUS_SE1 0x2006
+#define mmGRBM_STATUS_SE2 0x200e
+#define mmGRBM_STATUS_SE3 0x200f
+#define mmGRBM_SOFT_RESET 0x2008
+#define mmGRBM_DEBUG_CNTL 0x2009
+#define mmGRBM_DEBUG_DATA 0x200a
+#define mmGRBM_CGTT_CLK_CNTL 0x200b
+#define mmGRBM_GFX_INDEX 0xc200
+#define mmGRBM_GFX_CLKEN_CNTL 0x200c
+#define mmGRBM_WAIT_IDLE_CLOCKS 0x200d
+#define mmGRBM_DEBUG 0x2014
+#define mmGRBM_DEBUG_SNAPSHOT 0x2015
+#define mmGRBM_READ_ERROR 0x2016
+#define mmGRBM_READ_ERROR2 0x2017
+#define mmGRBM_INT_CNTL 0x2018
+#define mmGRBM_TRAP_OP 0x2019
+#define mmGRBM_TRAP_ADDR 0x201a
+#define mmGRBM_TRAP_ADDR_MSK 0x201b
+#define mmGRBM_TRAP_WD 0x201c
+#define mmGRBM_TRAP_WD_MSK 0x201d
+#define mmGRBM_DSM_BYPASS 0x201e
+#define mmGRBM_WRITE_ERROR 0x201f
+#define mmGRBM_PERFCOUNTER0_SELECT 0xd840
+#define mmGRBM_PERFCOUNTER1_SELECT 0xd841
+#define mmGRBM_SE0_PERFCOUNTER_SELECT 0xd842
+#define mmGRBM_SE1_PERFCOUNTER_SELECT 0xd843
+#define mmGRBM_SE2_PERFCOUNTER_SELECT 0xd844
+#define mmGRBM_SE3_PERFCOUNTER_SELECT 0xd845
+#define mmGRBM_PERFCOUNTER0_LO 0xd040
+#define mmGRBM_PERFCOUNTER0_HI 0xd041
+#define mmGRBM_PERFCOUNTER1_LO 0xd043
+#define mmGRBM_PERFCOUNTER1_HI 0xd044
+#define mmGRBM_SE0_PERFCOUNTER_LO 0xd045
+#define mmGRBM_SE0_PERFCOUNTER_HI 0xd046
+#define mmGRBM_SE1_PERFCOUNTER_LO 0xd047
+#define mmGRBM_SE1_PERFCOUNTER_HI 0xd048
+#define mmGRBM_SE2_PERFCOUNTER_LO 0xd049
+#define mmGRBM_SE2_PERFCOUNTER_HI 0xd04a
+#define mmGRBM_SE3_PERFCOUNTER_LO 0xd04b
+#define mmGRBM_SE3_PERFCOUNTER_HI 0xd04c
+#define mmGRBM_SCRATCH_REG0 0x2040
+#define mmGRBM_SCRATCH_REG1 0x2041
+#define mmGRBM_SCRATCH_REG2 0x2042
+#define mmGRBM_SCRATCH_REG3 0x2043
+#define mmGRBM_SCRATCH_REG4 0x2044
+#define mmGRBM_SCRATCH_REG5 0x2045
+#define mmGRBM_SCRATCH_REG6 0x2046
+#define mmGRBM_SCRATCH_REG7 0x2047
+#define mmDEBUG_INDEX 0x203c
+#define mmDEBUG_DATA 0x203d
+#define mmGRBM_NOWHERE 0x203f
+#define mmPA_CL_VPORT_XSCALE 0xa10f
+#define mmPA_CL_VPORT_XOFFSET 0xa110
+#define mmPA_CL_VPORT_YSCALE 0xa111
+#define mmPA_CL_VPORT_YOFFSET 0xa112
+#define mmPA_CL_VPORT_ZSCALE 0xa113
+#define mmPA_CL_VPORT_ZOFFSET 0xa114
+#define mmPA_CL_VPORT_XSCALE_1 0xa115
+#define mmPA_CL_VPORT_XSCALE_2 0xa11b
+#define mmPA_CL_VPORT_XSCALE_3 0xa121
+#define mmPA_CL_VPORT_XSCALE_4 0xa127
+#define mmPA_CL_VPORT_XSCALE_5 0xa12d
+#define mmPA_CL_VPORT_XSCALE_6 0xa133
+#define mmPA_CL_VPORT_XSCALE_7 0xa139
+#define mmPA_CL_VPORT_XSCALE_8 0xa13f
+#define mmPA_CL_VPORT_XSCALE_9 0xa145
+#define mmPA_CL_VPORT_XSCALE_10 0xa14b
+#define mmPA_CL_VPORT_XSCALE_11 0xa151
+#define mmPA_CL_VPORT_XSCALE_12 0xa157
+#define mmPA_CL_VPORT_XSCALE_13 0xa15d
+#define mmPA_CL_VPORT_XSCALE_14 0xa163
+#define mmPA_CL_VPORT_XSCALE_15 0xa169
+#define mmPA_CL_VPORT_XOFFSET_1 0xa116
+#define mmPA_CL_VPORT_XOFFSET_2 0xa11c
+#define mmPA_CL_VPORT_XOFFSET_3 0xa122
+#define mmPA_CL_VPORT_XOFFSET_4 0xa128
+#define mmPA_CL_VPORT_XOFFSET_5 0xa12e
+#define mmPA_CL_VPORT_XOFFSET_6 0xa134
+#define mmPA_CL_VPORT_XOFFSET_7 0xa13a
+#define mmPA_CL_VPORT_XOFFSET_8 0xa140
+#define mmPA_CL_VPORT_XOFFSET_9 0xa146
+#define mmPA_CL_VPORT_XOFFSET_10 0xa14c
+#define mmPA_CL_VPORT_XOFFSET_11 0xa152
+#define mmPA_CL_VPORT_XOFFSET_12 0xa158
+#define mmPA_CL_VPORT_XOFFSET_13 0xa15e
+#define mmPA_CL_VPORT_XOFFSET_14 0xa164
+#define mmPA_CL_VPORT_XOFFSET_15 0xa16a
+#define mmPA_CL_VPORT_YSCALE_1 0xa117
+#define mmPA_CL_VPORT_YSCALE_2 0xa11d
+#define mmPA_CL_VPORT_YSCALE_3 0xa123
+#define mmPA_CL_VPORT_YSCALE_4 0xa129
+#define mmPA_CL_VPORT_YSCALE_5 0xa12f
+#define mmPA_CL_VPORT_YSCALE_6 0xa135
+#define mmPA_CL_VPORT_YSCALE_7 0xa13b
+#define mmPA_CL_VPORT_YSCALE_8 0xa141
+#define mmPA_CL_VPORT_YSCALE_9 0xa147
+#define mmPA_CL_VPORT_YSCALE_10 0xa14d
+#define mmPA_CL_VPORT_YSCALE_11 0xa153
+#define mmPA_CL_VPORT_YSCALE_12 0xa159
+#define mmPA_CL_VPORT_YSCALE_13 0xa15f
+#define mmPA_CL_VPORT_YSCALE_14 0xa165
+#define mmPA_CL_VPORT_YSCALE_15 0xa16b
+#define mmPA_CL_VPORT_YOFFSET_1 0xa118
+#define mmPA_CL_VPORT_YOFFSET_2 0xa11e
+#define mmPA_CL_VPORT_YOFFSET_3 0xa124
+#define mmPA_CL_VPORT_YOFFSET_4 0xa12a
+#define mmPA_CL_VPORT_YOFFSET_5 0xa130
+#define mmPA_CL_VPORT_YOFFSET_6 0xa136
+#define mmPA_CL_VPORT_YOFFSET_7 0xa13c
+#define mmPA_CL_VPORT_YOFFSET_8 0xa142
+#define mmPA_CL_VPORT_YOFFSET_9 0xa148
+#define mmPA_CL_VPORT_YOFFSET_10 0xa14e
+#define mmPA_CL_VPORT_YOFFSET_11 0xa154
+#define mmPA_CL_VPORT_YOFFSET_12 0xa15a
+#define mmPA_CL_VPORT_YOFFSET_13 0xa160
+#define mmPA_CL_VPORT_YOFFSET_14 0xa166
+#define mmPA_CL_VPORT_YOFFSET_15 0xa16c
+#define mmPA_CL_VPORT_ZSCALE_1 0xa119
+#define mmPA_CL_VPORT_ZSCALE_2 0xa11f
+#define mmPA_CL_VPORT_ZSCALE_3 0xa125
+#define mmPA_CL_VPORT_ZSCALE_4 0xa12b
+#define mmPA_CL_VPORT_ZSCALE_5 0xa131
+#define mmPA_CL_VPORT_ZSCALE_6 0xa137
+#define mmPA_CL_VPORT_ZSCALE_7 0xa13d
+#define mmPA_CL_VPORT_ZSCALE_8 0xa143
+#define mmPA_CL_VPORT_ZSCALE_9 0xa149
+#define mmPA_CL_VPORT_ZSCALE_10 0xa14f
+#define mmPA_CL_VPORT_ZSCALE_11 0xa155
+#define mmPA_CL_VPORT_ZSCALE_12 0xa15b
+#define mmPA_CL_VPORT_ZSCALE_13 0xa161
+#define mmPA_CL_VPORT_ZSCALE_14 0xa167
+#define mmPA_CL_VPORT_ZSCALE_15 0xa16d
+#define mmPA_CL_VPORT_ZOFFSET_1 0xa11a
+#define mmPA_CL_VPORT_ZOFFSET_2 0xa120
+#define mmPA_CL_VPORT_ZOFFSET_3 0xa126
+#define mmPA_CL_VPORT_ZOFFSET_4 0xa12c
+#define mmPA_CL_VPORT_ZOFFSET_5 0xa132
+#define mmPA_CL_VPORT_ZOFFSET_6 0xa138
+#define mmPA_CL_VPORT_ZOFFSET_7 0xa13e
+#define mmPA_CL_VPORT_ZOFFSET_8 0xa144
+#define mmPA_CL_VPORT_ZOFFSET_9 0xa14a
+#define mmPA_CL_VPORT_ZOFFSET_10 0xa150
+#define mmPA_CL_VPORT_ZOFFSET_11 0xa156
+#define mmPA_CL_VPORT_ZOFFSET_12 0xa15c
+#define mmPA_CL_VPORT_ZOFFSET_13 0xa162
+#define mmPA_CL_VPORT_ZOFFSET_14 0xa168
+#define mmPA_CL_VPORT_ZOFFSET_15 0xa16e
+#define mmPA_CL_VTE_CNTL 0xa206
+#define mmPA_CL_VS_OUT_CNTL 0xa207
+#define mmPA_CL_NANINF_CNTL 0xa208
+#define mmPA_CL_CLIP_CNTL 0xa204
+#define mmPA_CL_GB_VERT_CLIP_ADJ 0xa2fa
+#define mmPA_CL_GB_VERT_DISC_ADJ 0xa2fb
+#define mmPA_CL_GB_HORZ_CLIP_ADJ 0xa2fc
+#define mmPA_CL_GB_HORZ_DISC_ADJ 0xa2fd
+#define mmPA_CL_UCP_0_X 0xa16f
+#define mmPA_CL_UCP_0_Y 0xa170
+#define mmPA_CL_UCP_0_Z 0xa171
+#define mmPA_CL_UCP_0_W 0xa172
+#define mmPA_CL_UCP_1_X 0xa173
+#define mmPA_CL_UCP_1_Y 0xa174
+#define mmPA_CL_UCP_1_Z 0xa175
+#define mmPA_CL_UCP_1_W 0xa176
+#define mmPA_CL_UCP_2_X 0xa177
+#define mmPA_CL_UCP_2_Y 0xa178
+#define mmPA_CL_UCP_2_Z 0xa179
+#define mmPA_CL_UCP_2_W 0xa17a
+#define mmPA_CL_UCP_3_X 0xa17b
+#define mmPA_CL_UCP_3_Y 0xa17c
+#define mmPA_CL_UCP_3_Z 0xa17d
+#define mmPA_CL_UCP_3_W 0xa17e
+#define mmPA_CL_UCP_4_X 0xa17f
+#define mmPA_CL_UCP_4_Y 0xa180
+#define mmPA_CL_UCP_4_Z 0xa181
+#define mmPA_CL_UCP_4_W 0xa182
+#define mmPA_CL_UCP_5_X 0xa183
+#define mmPA_CL_UCP_5_Y 0xa184
+#define mmPA_CL_UCP_5_Z 0xa185
+#define mmPA_CL_UCP_5_W 0xa186
+#define mmPA_CL_POINT_X_RAD 0xa1f5
+#define mmPA_CL_POINT_Y_RAD 0xa1f6
+#define mmPA_CL_POINT_SIZE 0xa1f7
+#define mmPA_CL_POINT_CULL_RAD 0xa1f8
+#define mmPA_CL_ENHANCE 0x2285
+#define mmPA_CL_RESET_DEBUG 0x2286
+#define mmPA_SU_VTX_CNTL 0xa2f9
+#define mmPA_SU_POINT_SIZE 0xa280
+#define mmPA_SU_POINT_MINMAX 0xa281
+#define mmPA_SU_LINE_CNTL 0xa282
+#define mmPA_SU_LINE_STIPPLE_CNTL 0xa209
+#define mmPA_SU_LINE_STIPPLE_SCALE 0xa20a
+#define mmPA_SU_PRIM_FILTER_CNTL 0xa20b
+#define mmPA_SU_SC_MODE_CNTL 0xa205
+#define mmPA_SU_POLY_OFFSET_DB_FMT_CNTL 0xa2de
+#define mmPA_SU_POLY_OFFSET_CLAMP 0xa2df
+#define mmPA_SU_POLY_OFFSET_FRONT_SCALE 0xa2e0
+#define mmPA_SU_POLY_OFFSET_FRONT_OFFSET 0xa2e1
+#define mmPA_SU_POLY_OFFSET_BACK_SCALE 0xa2e2
+#define mmPA_SU_POLY_OFFSET_BACK_OFFSET 0xa2e3
+#define mmPA_SU_HARDWARE_SCREEN_OFFSET 0xa08d
+#define mmPA_SU_LINE_STIPPLE_VALUE 0xc280
+#define mmPA_SU_PERFCOUNTER0_SELECT 0xd900
+#define mmPA_SU_PERFCOUNTER0_SELECT1 0xd901
+#define mmPA_SU_PERFCOUNTER1_SELECT 0xd902
+#define mmPA_SU_PERFCOUNTER1_SELECT1 0xd903
+#define mmPA_SU_PERFCOUNTER2_SELECT 0xd904
+#define mmPA_SU_PERFCOUNTER3_SELECT 0xd905
+#define mmPA_SU_PERFCOUNTER0_LO 0xd100
+#define mmPA_SU_PERFCOUNTER0_HI 0xd101
+#define mmPA_SU_PERFCOUNTER1_LO 0xd102
+#define mmPA_SU_PERFCOUNTER1_HI 0xd103
+#define mmPA_SU_PERFCOUNTER2_LO 0xd104
+#define mmPA_SU_PERFCOUNTER2_HI 0xd105
+#define mmPA_SU_PERFCOUNTER3_LO 0xd106
+#define mmPA_SU_PERFCOUNTER3_HI 0xd107
+#define mmPA_SC_AA_CONFIG 0xa2f8
+#define mmPA_SC_AA_MASK_X0Y0_X1Y0 0xa30e
+#define mmPA_SC_AA_MASK_X0Y1_X1Y1 0xa30f
+#define mmPA_SC_SHADER_CONTROL 0xa310
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 0xa2fe
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1 0xa2ff
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2 0xa300
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3 0xa301
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0 0xa302
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1 0xa303
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2 0xa304
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3 0xa305
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0 0xa306
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1 0xa307
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2 0xa308
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3 0xa309
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0 0xa30a
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1 0xa30b
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2 0xa30c
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3 0xa30d
+#define mmPA_SC_CENTROID_PRIORITY_0 0xa2f5
+#define mmPA_SC_CENTROID_PRIORITY_1 0xa2f6
+#define mmPA_SC_CLIPRECT_0_TL 0xa084
+#define mmPA_SC_CLIPRECT_0_BR 0xa085
+#define mmPA_SC_CLIPRECT_1_TL 0xa086
+#define mmPA_SC_CLIPRECT_1_BR 0xa087
+#define mmPA_SC_CLIPRECT_2_TL 0xa088
+#define mmPA_SC_CLIPRECT_2_BR 0xa089
+#define mmPA_SC_CLIPRECT_3_TL 0xa08a
+#define mmPA_SC_CLIPRECT_3_BR 0xa08b
+#define mmPA_SC_CLIPRECT_RULE 0xa083
+#define mmPA_SC_EDGERULE 0xa08c
+#define mmPA_SC_LINE_CNTL 0xa2f7
+#define mmPA_SC_LINE_STIPPLE 0xa283
+#define mmPA_SC_MODE_CNTL_0 0xa292
+#define mmPA_SC_MODE_CNTL_1 0xa293
+#define mmPA_SC_RASTER_CONFIG 0xa0d4
+#define mmPA_SC_RASTER_CONFIG_1 0xa0d5
+#define mmPA_SC_SCREEN_EXTENT_CONTROL 0xa0d6
+#define mmPA_SC_GENERIC_SCISSOR_TL 0xa090
+#define mmPA_SC_GENERIC_SCISSOR_BR 0xa091
+#define mmPA_SC_SCREEN_SCISSOR_TL 0xa00c
+#define mmPA_SC_SCREEN_SCISSOR_BR 0xa00d
+#define mmPA_SC_WINDOW_OFFSET 0xa080
+#define mmPA_SC_WINDOW_SCISSOR_TL 0xa081
+#define mmPA_SC_WINDOW_SCISSOR_BR 0xa082
+#define mmPA_SC_VPORT_SCISSOR_0_TL 0xa094
+#define mmPA_SC_VPORT_SCISSOR_1_TL 0xa096
+#define mmPA_SC_VPORT_SCISSOR_2_TL 0xa098
+#define mmPA_SC_VPORT_SCISSOR_3_TL 0xa09a
+#define mmPA_SC_VPORT_SCISSOR_4_TL 0xa09c
+#define mmPA_SC_VPORT_SCISSOR_5_TL 0xa09e
+#define mmPA_SC_VPORT_SCISSOR_6_TL 0xa0a0
+#define mmPA_SC_VPORT_SCISSOR_7_TL 0xa0a2
+#define mmPA_SC_VPORT_SCISSOR_8_TL 0xa0a4
+#define mmPA_SC_VPORT_SCISSOR_9_TL 0xa0a6
+#define mmPA_SC_VPORT_SCISSOR_10_TL 0xa0a8
+#define mmPA_SC_VPORT_SCISSOR_11_TL 0xa0aa
+#define mmPA_SC_VPORT_SCISSOR_12_TL 0xa0ac
+#define mmPA_SC_VPORT_SCISSOR_13_TL 0xa0ae
+#define mmPA_SC_VPORT_SCISSOR_14_TL 0xa0b0
+#define mmPA_SC_VPORT_SCISSOR_15_TL 0xa0b2
+#define mmPA_SC_VPORT_SCISSOR_0_BR 0xa095
+#define mmPA_SC_VPORT_SCISSOR_1_BR 0xa097
+#define mmPA_SC_VPORT_SCISSOR_2_BR 0xa099
+#define mmPA_SC_VPORT_SCISSOR_3_BR 0xa09b
+#define mmPA_SC_VPORT_SCISSOR_4_BR 0xa09d
+#define mmPA_SC_VPORT_SCISSOR_5_BR 0xa09f
+#define mmPA_SC_VPORT_SCISSOR_6_BR 0xa0a1
+#define mmPA_SC_VPORT_SCISSOR_7_BR 0xa0a3
+#define mmPA_SC_VPORT_SCISSOR_8_BR 0xa0a5
+#define mmPA_SC_VPORT_SCISSOR_9_BR 0xa0a7
+#define mmPA_SC_VPORT_SCISSOR_10_BR 0xa0a9
+#define mmPA_SC_VPORT_SCISSOR_11_BR 0xa0ab
+#define mmPA_SC_VPORT_SCISSOR_12_BR 0xa0ad
+#define mmPA_SC_VPORT_SCISSOR_13_BR 0xa0af
+#define mmPA_SC_VPORT_SCISSOR_14_BR 0xa0b1
+#define mmPA_SC_VPORT_SCISSOR_15_BR 0xa0b3
+#define mmPA_SC_VPORT_ZMIN_0 0xa0b4
+#define mmPA_SC_VPORT_ZMIN_1 0xa0b6
+#define mmPA_SC_VPORT_ZMIN_2 0xa0b8
+#define mmPA_SC_VPORT_ZMIN_3 0xa0ba
+#define mmPA_SC_VPORT_ZMIN_4 0xa0bc
+#define mmPA_SC_VPORT_ZMIN_5 0xa0be
+#define mmPA_SC_VPORT_ZMIN_6 0xa0c0
+#define mmPA_SC_VPORT_ZMIN_7 0xa0c2
+#define mmPA_SC_VPORT_ZMIN_8 0xa0c4
+#define mmPA_SC_VPORT_ZMIN_9 0xa0c6
+#define mmPA_SC_VPORT_ZMIN_10 0xa0c8
+#define mmPA_SC_VPORT_ZMIN_11 0xa0ca
+#define mmPA_SC_VPORT_ZMIN_12 0xa0cc
+#define mmPA_SC_VPORT_ZMIN_13 0xa0ce
+#define mmPA_SC_VPORT_ZMIN_14 0xa0d0
+#define mmPA_SC_VPORT_ZMIN_15 0xa0d2
+#define mmPA_SC_VPORT_ZMAX_0 0xa0b5
+#define mmPA_SC_VPORT_ZMAX_1 0xa0b7
+#define mmPA_SC_VPORT_ZMAX_2 0xa0b9
+#define mmPA_SC_VPORT_ZMAX_3 0xa0bb
+#define mmPA_SC_VPORT_ZMAX_4 0xa0bd
+#define mmPA_SC_VPORT_ZMAX_5 0xa0bf
+#define mmPA_SC_VPORT_ZMAX_6 0xa0c1
+#define mmPA_SC_VPORT_ZMAX_7 0xa0c3
+#define mmPA_SC_VPORT_ZMAX_8 0xa0c5
+#define mmPA_SC_VPORT_ZMAX_9 0xa0c7
+#define mmPA_SC_VPORT_ZMAX_10 0xa0c9
+#define mmPA_SC_VPORT_ZMAX_11 0xa0cb
+#define mmPA_SC_VPORT_ZMAX_12 0xa0cd
+#define mmPA_SC_VPORT_ZMAX_13 0xa0cf
+#define mmPA_SC_VPORT_ZMAX_14 0xa0d1
+#define mmPA_SC_VPORT_ZMAX_15 0xa0d3
+#define mmPA_SC_ENHANCE 0x22fc
+#define mmPA_SC_ENHANCE_1 0x22fd
+#define mmPA_SC_DSM_CNTL 0x22fe
+#define mmPA_SC_FIFO_SIZE 0x22f3
+#define mmPA_SC_IF_FIFO_SIZE 0x22f5
+#define mmPA_SC_FORCE_EOV_MAX_CNTS 0x22c9
+#define mmPA_SC_LINE_STIPPLE_STATE 0xc281
+#define mmPA_SC_SCREEN_EXTENT_MIN_0 0xc284
+#define mmPA_SC_SCREEN_EXTENT_MAX_0 0xc285
+#define mmPA_SC_SCREEN_EXTENT_MIN_1 0xc286
+#define mmPA_SC_SCREEN_EXTENT_MAX_1 0xc28b
+#define mmPA_SC_PERFCOUNTER0_SELECT 0xd940
+#define mmPA_SC_PERFCOUNTER0_SELECT1 0xd941
+#define mmPA_SC_PERFCOUNTER1_SELECT 0xd942
+#define mmPA_SC_PERFCOUNTER2_SELECT 0xd943
+#define mmPA_SC_PERFCOUNTER3_SELECT 0xd944
+#define mmPA_SC_PERFCOUNTER4_SELECT 0xd945
+#define mmPA_SC_PERFCOUNTER5_SELECT 0xd946
+#define mmPA_SC_PERFCOUNTER6_SELECT 0xd947
+#define mmPA_SC_PERFCOUNTER7_SELECT 0xd948
+#define mmPA_SC_PERFCOUNTER0_LO 0xd140
+#define mmPA_SC_PERFCOUNTER0_HI 0xd141
+#define mmPA_SC_PERFCOUNTER1_LO 0xd142
+#define mmPA_SC_PERFCOUNTER1_HI 0xd143
+#define mmPA_SC_PERFCOUNTER2_LO 0xd144
+#define mmPA_SC_PERFCOUNTER2_HI 0xd145
+#define mmPA_SC_PERFCOUNTER3_LO 0xd146
+#define mmPA_SC_PERFCOUNTER3_HI 0xd147
+#define mmPA_SC_PERFCOUNTER4_LO 0xd148
+#define mmPA_SC_PERFCOUNTER4_HI 0xd149
+#define mmPA_SC_PERFCOUNTER5_LO 0xd14a
+#define mmPA_SC_PERFCOUNTER5_HI 0xd14b
+#define mmPA_SC_PERFCOUNTER6_LO 0xd14c
+#define mmPA_SC_PERFCOUNTER6_HI 0xd14d
+#define mmPA_SC_PERFCOUNTER7_LO 0xd14e
+#define mmPA_SC_PERFCOUNTER7_HI 0xd14f
+#define mmPA_SC_P3D_TRAP_SCREEN_HV_EN 0xc2a0
+#define mmPA_SC_P3D_TRAP_SCREEN_H 0xc2a1
+#define mmPA_SC_P3D_TRAP_SCREEN_V 0xc2a2
+#define mmPA_SC_P3D_TRAP_SCREEN_OCCURRENCE 0xc2a3
+#define mmPA_SC_P3D_TRAP_SCREEN_COUNT 0xc2a4
+#define mmPA_SC_HP3D_TRAP_SCREEN_HV_EN 0xc2a8
+#define mmPA_SC_HP3D_TRAP_SCREEN_H 0xc2a9
+#define mmPA_SC_HP3D_TRAP_SCREEN_V 0xc2aa
+#define mmPA_SC_HP3D_TRAP_SCREEN_OCCURRENCE 0xc2ab
+#define mmPA_SC_HP3D_TRAP_SCREEN_COUNT 0xc2ac
+#define mmPA_SC_TRAP_SCREEN_HV_EN 0xc2b0
+#define mmPA_SC_TRAP_SCREEN_H 0xc2b1
+#define mmPA_SC_TRAP_SCREEN_V 0xc2b2
+#define mmPA_SC_TRAP_SCREEN_OCCURRENCE 0xc2b3
+#define mmPA_SC_TRAP_SCREEN_COUNT 0xc2b4
+#define mmPA_SC_P3D_TRAP_SCREEN_HV_LOCK 0x22c0
+#define mmPA_SC_HP3D_TRAP_SCREEN_HV_LOCK 0x22c1
+#define mmPA_SC_TRAP_SCREEN_HV_LOCK 0x22c2
+#define mmPA_CL_CNTL_STATUS 0x2284
+#define mmPA_SU_CNTL_STATUS 0x2294
+#define mmPA_SC_FIFO_DEPTH_CNTL 0x2295
+#define mmCGTT_PA_CLK_CTRL 0xf088
+#define mmCGTT_SC_CLK_CTRL 0xf089
+#define mmPA_SU_DEBUG_CNTL 0x2280
+#define mmPA_SU_DEBUG_DATA 0x2281
+#define mmPA_SC_DEBUG_CNTL 0x22f6
+#define mmPA_SC_DEBUG_DATA 0x22f7
+#define ixCLIPPER_DEBUG_REG00 0x0
+#define ixCLIPPER_DEBUG_REG01 0x1
+#define ixCLIPPER_DEBUG_REG02 0x2
+#define ixCLIPPER_DEBUG_REG03 0x3
+#define ixCLIPPER_DEBUG_REG04 0x4
+#define ixCLIPPER_DEBUG_REG05 0x5
+#define ixCLIPPER_DEBUG_REG06 0x6
+#define ixCLIPPER_DEBUG_REG07 0x7
+#define ixCLIPPER_DEBUG_REG08 0x8
+#define ixCLIPPER_DEBUG_REG09 0x9
+#define ixCLIPPER_DEBUG_REG10 0xa
+#define ixCLIPPER_DEBUG_REG11 0xb
+#define ixCLIPPER_DEBUG_REG12 0xc
+#define ixCLIPPER_DEBUG_REG13 0xd
+#define ixCLIPPER_DEBUG_REG14 0xe
+#define ixCLIPPER_DEBUG_REG15 0xf
+#define ixCLIPPER_DEBUG_REG16 0x10
+#define ixCLIPPER_DEBUG_REG17 0x11
+#define ixCLIPPER_DEBUG_REG18 0x12
+#define ixCLIPPER_DEBUG_REG19 0x13
+#define ixSXIFCCG_DEBUG_REG0 0x14
+#define ixSXIFCCG_DEBUG_REG1 0x15
+#define ixSXIFCCG_DEBUG_REG2 0x16
+#define ixSXIFCCG_DEBUG_REG3 0x17
+#define ixSETUP_DEBUG_REG0 0x18
+#define ixSETUP_DEBUG_REG1 0x19
+#define ixSETUP_DEBUG_REG2 0x1a
+#define ixSETUP_DEBUG_REG3 0x1b
+#define ixSETUP_DEBUG_REG4 0x1c
+#define ixSETUP_DEBUG_REG5 0x1d
+#define ixPA_SC_DEBUG_REG0 0x0
+#define ixPA_SC_DEBUG_REG1 0x1
+#define mmCOMPUTE_DISPATCH_INITIATOR 0x2e00
+#define mmCOMPUTE_DIM_X 0x2e01
+#define mmCOMPUTE_DIM_Y 0x2e02
+#define mmCOMPUTE_DIM_Z 0x2e03
+#define mmCOMPUTE_START_X 0x2e04
+#define mmCOMPUTE_START_Y 0x2e05
+#define mmCOMPUTE_START_Z 0x2e06
+#define mmCOMPUTE_NUM_THREAD_X 0x2e07
+#define mmCOMPUTE_NUM_THREAD_Y 0x2e08
+#define mmCOMPUTE_NUM_THREAD_Z 0x2e09
+#define mmCOMPUTE_PIPELINESTAT_ENABLE 0x2e0a
+#define mmCOMPUTE_PERFCOUNT_ENABLE 0x2e0b
+#define mmCOMPUTE_PGM_LO 0x2e0c
+#define mmCOMPUTE_PGM_HI 0x2e0d
+#define mmCOMPUTE_TBA_LO 0x2e0e
+#define mmCOMPUTE_TBA_HI 0x2e0f
+#define mmCOMPUTE_TMA_LO 0x2e10
+#define mmCOMPUTE_TMA_HI 0x2e11
+#define mmCOMPUTE_PGM_RSRC1 0x2e12
+#define mmCOMPUTE_PGM_RSRC2 0x2e13
+#define mmCOMPUTE_VMID 0x2e14
+#define mmCOMPUTE_RESOURCE_LIMITS 0x2e15
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE0 0x2e16
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE1 0x2e17
+#define mmCOMPUTE_TMPRING_SIZE 0x2e18
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE2 0x2e19
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE3 0x2e1a
+#define mmCOMPUTE_RESTART_X 0x2e1b
+#define mmCOMPUTE_RESTART_Y 0x2e1c
+#define mmCOMPUTE_RESTART_Z 0x2e1d
+#define mmCOMPUTE_THREAD_TRACE_ENABLE 0x2e1e
+#define mmCOMPUTE_MISC_RESERVED 0x2e1f
+#define mmCOMPUTE_DISPATCH_ID 0x2e20
+#define mmCOMPUTE_THREADGROUP_ID 0x2e21
+#define mmCOMPUTE_RELAUNCH 0x2e22
+#define mmCOMPUTE_WAVE_RESTORE_ADDR_LO 0x2e23
+#define mmCOMPUTE_WAVE_RESTORE_ADDR_HI 0x2e24
+#define mmCOMPUTE_WAVE_RESTORE_CONTROL 0x2e25
+#define mmCOMPUTE_USER_DATA_0 0x2e40
+#define mmCOMPUTE_USER_DATA_1 0x2e41
+#define mmCOMPUTE_USER_DATA_2 0x2e42
+#define mmCOMPUTE_USER_DATA_3 0x2e43
+#define mmCOMPUTE_USER_DATA_4 0x2e44
+#define mmCOMPUTE_USER_DATA_5 0x2e45
+#define mmCOMPUTE_USER_DATA_6 0x2e46
+#define mmCOMPUTE_USER_DATA_7 0x2e47
+#define mmCOMPUTE_USER_DATA_8 0x2e48
+#define mmCOMPUTE_USER_DATA_9 0x2e49
+#define mmCOMPUTE_USER_DATA_10 0x2e4a
+#define mmCOMPUTE_USER_DATA_11 0x2e4b
+#define mmCOMPUTE_USER_DATA_12 0x2e4c
+#define mmCOMPUTE_USER_DATA_13 0x2e4d
+#define mmCOMPUTE_USER_DATA_14 0x2e4e
+#define mmCOMPUTE_USER_DATA_15 0x2e4f
+#define mmCOMPUTE_NOWHERE 0x2e7f
+#define mmCSPRIV_CONNECT 0x0
+#define mmCSPRIV_THREAD_TRACE_TG0 0x1e
+#define mmCSPRIV_THREAD_TRACE_TG1 0x1e
+#define mmCSPRIV_THREAD_TRACE_TG2 0x1e
+#define mmCSPRIV_THREAD_TRACE_TG3 0x1e
+#define mmCSPRIV_THREAD_TRACE_EVENT 0x1f
+#define mmRLC_CNTL 0xec00
+#define mmRLC_DEBUG_SELECT 0xec01
+#define mmRLC_DEBUG 0xec02
+#define mmRLC_MC_CNTL 0xec03
+#define mmRLC_STAT 0xec04
+#define mmRLC_SAFE_MODE 0xec05
+#define mmRLC_MEM_SLP_CNTL 0xec06
+#define mmSMU_RLC_RESPONSE 0xec07
+#define mmRLC_RLCV_SAFE_MODE 0xec08
+#define mmRLC_SMU_SAFE_MODE 0xec09
+#define mmRLC_RLCV_COMMAND 0xec0a
+#define mmRLC_CLK_CNTL 0xec0b
+#define mmRLC_PERFMON_CLK_CNTL 0xdcbf
+#define mmRLC_PERFMON_CNTL 0xdcc0
+#define mmRLC_PERFCOUNTER0_SELECT 0xdcc1
+#define mmRLC_PERFCOUNTER1_SELECT 0xdcc2
+#define mmRLC_PERFCOUNTER0_LO 0xd480
+#define mmRLC_PERFCOUNTER1_LO 0xd482
+#define mmRLC_PERFCOUNTER0_HI 0xd481
+#define mmRLC_PERFCOUNTER1_HI 0xd483
+#define mmCGTT_RLC_CLK_CTRL 0xf0b8
+#define mmRLC_LB_CNTL 0xec19
+#define mmRLC_LB_CNTR_MAX 0xec12
+#define mmRLC_LB_CNTR_INIT 0xec1b
+#define mmRLC_LOAD_BALANCE_CNTR 0xec1c
+#define mmRLC_JUMP_TABLE_RESTORE 0xec1e
+#define mmRLC_PG_DELAY_2 0xec1f
+#define mmRLC_GPM_DEBUG_SELECT 0xec20
+#define mmRLC_GPM_DEBUG 0xec21
+#define mmRLC_GPM_DEBUG_INST_A 0xec22
+#define mmRLC_GPM_DEBUG_INST_B 0xec23
+#define mmRLC_GPM_DEBUG_INST_ADDR 0xec1d
+#define mmRLC_GPM_UCODE_ADDR 0xf83c
+#define mmRLC_GPM_UCODE_DATA 0xf83d
+#define mmGPU_BIST_CONTROL 0xf835
+#define mmRLC_ROM_CNTL 0xf836
+#define mmRLC_GPU_CLOCK_COUNT_LSB 0xec24
+#define mmRLC_GPU_CLOCK_COUNT_MSB 0xec25
+#define mmRLC_CAPTURE_GPU_CLOCK_COUNT 0xec26
+#define mmRLC_UCODE_CNTL 0xec27
+#define mmRLC_GPM_STAT 0xec40
+#define mmRLC_GPU_CLOCK_32_RES_SEL 0xec41
+#define mmRLC_GPU_CLOCK_32 0xec42
+#define mmRLC_PG_CNTL 0xec43
+#define mmRLC_GPM_THREAD_PRIORITY 0xec44
+#define mmRLC_GPM_THREAD_ENABLE 0xec45
+#define mmRLC_GPM_VMID_THREAD0 0xec46
+#define mmRLC_GPM_VMID_THREAD1 0xec47
+#define mmRLC_CGTT_MGCG_OVERRIDE 0xec48
+#define mmRLC_CGCG_CGLS_CTRL 0xec49
+#define mmRLC_CGCG_RAMP_CTRL 0xec4a
+#define mmRLC_DYN_PG_STATUS 0xec4b
+#define mmRLC_DYN_PG_REQUEST 0xec4c
+#define mmRLC_PG_DELAY 0xec4d
+#define mmRLC_CU_STATUS 0xec4e
+#define mmRLC_LB_INIT_CU_MASK 0xec4f
+#define mmRLC_LB_ALWAYS_ACTIVE_CU_MASK 0xec50
+#define mmRLC_LB_PARAMS 0xec51
+#define mmRLC_THREAD1_DELAY 0xec52
+#define mmRLC_PG_ALWAYS_ON_CU_MASK 0xec53
+#define mmRLC_MAX_PG_CU 0xec54
+#define mmRLC_AUTO_PG_CTRL 0xec55
+#define mmRLC_SMU_GRBM_REG_SAVE_CTRL 0xec56
+#define mmRLC_SERDES_RD_MASTER_INDEX 0xec59
+#define mmRLC_SERDES_RD_DATA_0 0xec5a
+#define mmRLC_SERDES_RD_DATA_1 0xec5b
+#define mmRLC_SERDES_RD_DATA_2 0xec5c
+#define mmRLC_SERDES_WR_CU_MASTER_MASK 0xec5d
+#define mmRLC_SERDES_WR_NONCU_MASTER_MASK 0xec5e
+#define mmRLC_SERDES_WR_CTRL 0xec5f
+#define mmRLC_SERDES_WR_DATA 0xec60
+#define mmRLC_SERDES_CU_MASTER_BUSY 0xec61
+#define mmRLC_SERDES_NONCU_MASTER_BUSY 0xec62
+#define mmRLC_GPM_GENERAL_0 0xec63
+#define mmRLC_GPM_GENERAL_1 0xec64
+#define mmRLC_GPM_GENERAL_2 0xec65
+#define mmRLC_GPM_GENERAL_3 0xec66
+#define mmRLC_GPM_GENERAL_4 0xec67
+#define mmRLC_GPM_GENERAL_5 0xec68
+#define mmRLC_GPM_GENERAL_6 0xec69
+#define mmRLC_GPM_GENERAL_7 0xec6a
+#define mmRLC_GPM_SCRATCH_ADDR 0xec6c
+#define mmRLC_GPM_SCRATCH_DATA 0xec6d
+#define mmRLC_STATIC_PG_STATUS 0xec6e
+#define mmRLC_GPM_PERF_COUNT_0 0xec6f
+#define mmRLC_GPM_PERF_COUNT_1 0xec70
+#define mmRLC_GPR_REG1 0xec79
+#define mmRLC_GPR_REG2 0xec7a
+#define mmRLC_MGCG_CTRL 0xec1a
+#define mmRLC_GPM_THREAD_RESET 0xec28
+#define mmRLC_SPM_VMID 0xec71
+#define mmRLC_SPM_INT_CNTL 0xec72
+#define mmRLC_SPM_INT_STATUS 0xec73
+#define mmRLC_SPM_DEBUG_SELECT 0xec74
+#define mmRLC_SPM_DEBUG 0xec75
+#define mmRLC_SMU_MESSAGE 0xec76
+#define mmRLC_GPM_LOG_SIZE 0xec77
+#define mmRLC_GPM_LOG_CONT 0xec7b
+#define mmRLC_PG_DELAY_3 0xec78
+#define mmRLC_GPM_INT_DISABLE_TH0 0xec7c
+#define mmRLC_GPM_INT_DISABLE_TH1 0xec7d
+#define mmRLC_GPM_INT_FORCE_TH0 0xec7e
+#define mmRLC_GPM_INT_FORCE_TH1 0xec7f
+#define mmRLC_SRM_CNTL 0xec80
+#define mmRLC_SRM_DEBUG_SELECT 0xec81
+#define mmRLC_SRM_DEBUG 0xec82
+#define mmRLC_SRM_ARAM_ADDR 0xec83
+#define mmRLC_SRM_ARAM_DATA 0xec84
+#define mmRLC_SRM_DRAM_ADDR 0xec85
+#define mmRLC_SRM_DRAM_DATA 0xec86
+#define mmRLC_SRM_GPM_COMMAND 0xec87
+#define mmRLC_SRM_GPM_COMMAND_STATUS 0xec88
+#define mmRLC_SRM_RLCV_COMMAND 0xec89
+#define mmRLC_SRM_RLCV_COMMAND_STATUS 0xec8a
+#define mmRLC_SRM_INDEX_CNTL_ADDR_0 0xec8b
+#define mmRLC_SRM_INDEX_CNTL_ADDR_1 0xec8c
+#define mmRLC_SRM_INDEX_CNTL_ADDR_2 0xec8d
+#define mmRLC_SRM_INDEX_CNTL_ADDR_3 0xec8e
+#define mmRLC_SRM_INDEX_CNTL_ADDR_4 0xec8f
+#define mmRLC_SRM_INDEX_CNTL_ADDR_5 0xec90
+#define mmRLC_SRM_INDEX_CNTL_ADDR_6 0xec91
+#define mmRLC_SRM_INDEX_CNTL_ADDR_7 0xec92
+#define mmRLC_SRM_INDEX_CNTL_DATA_0 0xec93
+#define mmRLC_SRM_INDEX_CNTL_DATA_1 0xec94
+#define mmRLC_SRM_INDEX_CNTL_DATA_2 0xec95
+#define mmRLC_SRM_INDEX_CNTL_DATA_3 0xec96
+#define mmRLC_SRM_INDEX_CNTL_DATA_4 0xec97
+#define mmRLC_SRM_INDEX_CNTL_DATA_5 0xec98
+#define mmRLC_SRM_INDEX_CNTL_DATA_6 0xec99
+#define mmRLC_SRM_INDEX_CNTL_DATA_7 0xec9a
+#define mmRLC_SRM_STAT 0xec9b
+#define mmRLC_SRM_GPM_ABORT 0xec9c
+#define mmRLC_CSIB_ADDR_LO 0xeca2
+#define mmRLC_CSIB_ADDR_HI 0xeca3
+#define mmRLC_CSIB_LENGTH 0xeca4
+#define mmRLC_CP_RESPONSE0 0xeca5
+#define mmRLC_CP_RESPONSE1 0xeca6
+#define mmRLC_CP_RESPONSE2 0xeca7
+#define mmRLC_CP_RESPONSE3 0xeca8
+#define mmRLC_SMU_COMMAND 0xeca9
+#define mmRLC_CP_SCHEDULERS 0xecaa
+#define mmRLC_SMU_ARGUMENT_1 0xecab
+#define mmRLC_SMU_ARGUMENT_2 0xecac
+#define mmRLC_GPM_GENERAL_8 0xecad
+#define mmRLC_GPM_GENERAL_9 0xecae
+#define mmRLC_GPM_GENERAL_10 0xecaf
+#define mmRLC_GPM_GENERAL_11 0xecb0
+#define mmRLC_GPM_GENERAL_12 0xecb1
+#define mmRLC_SPM_PERFMON_CNTL 0xdc80
+#define mmRLC_SPM_PERFMON_RING_BASE_LO 0xdc81
+#define mmRLC_SPM_PERFMON_RING_BASE_HI 0xdc82
+#define mmRLC_SPM_PERFMON_RING_SIZE 0xdc83
+#define mmRLC_SPM_PERFMON_SEGMENT_SIZE 0xdc84
+#define mmRLC_SPM_SE_MUXSEL_ADDR 0xdc85
+#define mmRLC_SPM_SE_MUXSEL_DATA 0xdc86
+#define mmRLC_SPM_CPG_PERFMON_SAMPLE_DELAY 0xdc87
+#define mmRLC_SPM_CPC_PERFMON_SAMPLE_DELAY 0xdc88
+#define mmRLC_SPM_CPF_PERFMON_SAMPLE_DELAY 0xdc89
+#define mmRLC_SPM_CB_PERFMON_SAMPLE_DELAY 0xdc8a
+#define mmRLC_SPM_DB_PERFMON_SAMPLE_DELAY 0xdc8b
+#define mmRLC_SPM_PA_PERFMON_SAMPLE_DELAY 0xdc8c
+#define mmRLC_SPM_GDS_PERFMON_SAMPLE_DELAY 0xdc8d
+#define mmRLC_SPM_IA_PERFMON_SAMPLE_DELAY 0xdc8e
+#define mmRLC_SPM_SC_PERFMON_SAMPLE_DELAY 0xdc90
+#define mmRLC_SPM_TCC_PERFMON_SAMPLE_DELAY 0xdc91
+#define mmRLC_SPM_TCA_PERFMON_SAMPLE_DELAY 0xdc92
+#define mmRLC_SPM_TCP_PERFMON_SAMPLE_DELAY 0xdc93
+#define mmRLC_SPM_TA_PERFMON_SAMPLE_DELAY 0xdc94
+#define mmRLC_SPM_TD_PERFMON_SAMPLE_DELAY 0xdc95
+#define mmRLC_SPM_VGT_PERFMON_SAMPLE_DELAY 0xdc96
+#define mmRLC_SPM_SPI_PERFMON_SAMPLE_DELAY 0xdc97
+#define mmRLC_SPM_SQG_PERFMON_SAMPLE_DELAY 0xdc98
+#define mmRLC_SPM_SX_PERFMON_SAMPLE_DELAY 0xdc9a
+#define mmRLC_SPM_GLOBAL_MUXSEL_ADDR 0xdc9b
+#define mmRLC_SPM_GLOBAL_MUXSEL_DATA 0xdc9c
+#define mmRLC_SPM_RING_RDPTR 0xdc9d
+#define mmRLC_SPM_SEGMENT_THRESHOLD 0xdc9e
+#define mmRLC_GPU_IOV_VF_ENABLE 0xfb00
+#define mmRLC_GPU_IOV_RLC_RESPONSE 0xfb4d
+#define mmRLC_GPU_IOV_ACTIVE_FCN_ID 0xfb40
+#define mmSPI_PS_INPUT_CNTL_0 0xa191
+#define mmSPI_PS_INPUT_CNTL_1 0xa192
+#define mmSPI_PS_INPUT_CNTL_2 0xa193
+#define mmSPI_PS_INPUT_CNTL_3 0xa194
+#define mmSPI_PS_INPUT_CNTL_4 0xa195
+#define mmSPI_PS_INPUT_CNTL_5 0xa196
+#define mmSPI_PS_INPUT_CNTL_6 0xa197
+#define mmSPI_PS_INPUT_CNTL_7 0xa198
+#define mmSPI_PS_INPUT_CNTL_8 0xa199
+#define mmSPI_PS_INPUT_CNTL_9 0xa19a
+#define mmSPI_PS_INPUT_CNTL_10 0xa19b
+#define mmSPI_PS_INPUT_CNTL_11 0xa19c
+#define mmSPI_PS_INPUT_CNTL_12 0xa19d
+#define mmSPI_PS_INPUT_CNTL_13 0xa19e
+#define mmSPI_PS_INPUT_CNTL_14 0xa19f
+#define mmSPI_PS_INPUT_CNTL_15 0xa1a0
+#define mmSPI_PS_INPUT_CNTL_16 0xa1a1
+#define mmSPI_PS_INPUT_CNTL_17 0xa1a2
+#define mmSPI_PS_INPUT_CNTL_18 0xa1a3
+#define mmSPI_PS_INPUT_CNTL_19 0xa1a4
+#define mmSPI_PS_INPUT_CNTL_20 0xa1a5
+#define mmSPI_PS_INPUT_CNTL_21 0xa1a6
+#define mmSPI_PS_INPUT_CNTL_22 0xa1a7
+#define mmSPI_PS_INPUT_CNTL_23 0xa1a8
+#define mmSPI_PS_INPUT_CNTL_24 0xa1a9
+#define mmSPI_PS_INPUT_CNTL_25 0xa1aa
+#define mmSPI_PS_INPUT_CNTL_26 0xa1ab
+#define mmSPI_PS_INPUT_CNTL_27 0xa1ac
+#define mmSPI_PS_INPUT_CNTL_28 0xa1ad
+#define mmSPI_PS_INPUT_CNTL_29 0xa1ae
+#define mmSPI_PS_INPUT_CNTL_30 0xa1af
+#define mmSPI_PS_INPUT_CNTL_31 0xa1b0
+#define mmSPI_VS_OUT_CONFIG 0xa1b1
+#define mmSPI_PS_INPUT_ENA 0xa1b3
+#define mmSPI_PS_INPUT_ADDR 0xa1b4
+#define mmSPI_INTERP_CONTROL_0 0xa1b5
+#define mmSPI_PS_IN_CONTROL 0xa1b6
+#define mmSPI_BARYC_CNTL 0xa1b8
+#define mmSPI_TMPRING_SIZE 0xa1ba
+#define mmSPI_SHADER_POS_FORMAT 0xa1c3
+#define mmSPI_SHADER_Z_FORMAT 0xa1c4
+#define mmSPI_SHADER_COL_FORMAT 0xa1c5
+#define mmSPI_ARB_PRIORITY 0x31c0
+#define mmSPI_ARB_CYCLES_0 0x31c1
+#define mmSPI_ARB_CYCLES_1 0x31c2
+#define mmSPI_CDBG_SYS_GFX 0x31c3
+#define mmSPI_CDBG_SYS_HP3D 0x31c4
+#define mmSPI_CDBG_SYS_CS0 0x31c5
+#define mmSPI_CDBG_SYS_CS1 0x31c6
+#define mmSPI_WCL_PIPE_PERCENT_GFX 0x31c7
+#define mmSPI_WCL_PIPE_PERCENT_HP3D 0x31c8
+#define mmSPI_WCL_PIPE_PERCENT_CS0 0x31c9
+#define mmSPI_WCL_PIPE_PERCENT_CS1 0x31ca
+#define mmSPI_WCL_PIPE_PERCENT_CS2 0x31cb
+#define mmSPI_WCL_PIPE_PERCENT_CS3 0x31cc
+#define mmSPI_WCL_PIPE_PERCENT_CS4 0x31cd
+#define mmSPI_WCL_PIPE_PERCENT_CS5 0x31ce
+#define mmSPI_WCL_PIPE_PERCENT_CS6 0x31cf
+#define mmSPI_WCL_PIPE_PERCENT_CS7 0x31d0
+#define mmSPI_GDBG_WAVE_CNTL 0x31d1
+#define mmSPI_GDBG_TRAP_CONFIG 0x31d2
+#define mmSPI_GDBG_TRAP_MASK 0x31d3
+#define mmSPI_GDBG_TBA_LO 0x31d4
+#define mmSPI_GDBG_TBA_HI 0x31d5
+#define mmSPI_GDBG_TMA_LO 0x31d6
+#define mmSPI_GDBG_TMA_HI 0x31d7
+#define mmSPI_GDBG_TRAP_DATA0 0x31d8
+#define mmSPI_GDBG_TRAP_DATA1 0x31d9
+#define mmSPI_RESET_DEBUG 0x31da
+#define mmSPI_COMPUTE_QUEUE_RESET 0x31db
+#define mmSPI_RESOURCE_RESERVE_CU_0 0x31dc
+#define mmSPI_RESOURCE_RESERVE_CU_1 0x31dd
+#define mmSPI_RESOURCE_RESERVE_CU_2 0x31de
+#define mmSPI_RESOURCE_RESERVE_CU_3 0x31df
+#define mmSPI_RESOURCE_RESERVE_CU_4 0x31e0
+#define mmSPI_RESOURCE_RESERVE_CU_5 0x31e1
+#define mmSPI_RESOURCE_RESERVE_CU_6 0x31e2
+#define mmSPI_RESOURCE_RESERVE_CU_7 0x31e3
+#define mmSPI_RESOURCE_RESERVE_CU_8 0x31e4
+#define mmSPI_RESOURCE_RESERVE_CU_9 0x31e5
+#define mmSPI_RESOURCE_RESERVE_CU_10 0x31f0
+#define mmSPI_RESOURCE_RESERVE_CU_11 0x31f1
+#define mmSPI_RESOURCE_RESERVE_CU_12 0x31f4
+#define mmSPI_RESOURCE_RESERVE_CU_13 0x31f5
+#define mmSPI_RESOURCE_RESERVE_CU_14 0x31f6
+#define mmSPI_RESOURCE_RESERVE_CU_15 0x31f7
+#define mmSPI_RESOURCE_RESERVE_EN_CU_0 0x31e6
+#define mmSPI_RESOURCE_RESERVE_EN_CU_1 0x31e7
+#define mmSPI_RESOURCE_RESERVE_EN_CU_2 0x31e8
+#define mmSPI_RESOURCE_RESERVE_EN_CU_3 0x31e9
+#define mmSPI_RESOURCE_RESERVE_EN_CU_4 0x31ea
+#define mmSPI_RESOURCE_RESERVE_EN_CU_5 0x31eb
+#define mmSPI_RESOURCE_RESERVE_EN_CU_6 0x31ec
+#define mmSPI_RESOURCE_RESERVE_EN_CU_7 0x31ed
+#define mmSPI_RESOURCE_RESERVE_EN_CU_8 0x31ee
+#define mmSPI_RESOURCE_RESERVE_EN_CU_9 0x31ef
+#define mmSPI_RESOURCE_RESERVE_EN_CU_10 0x31f2
+#define mmSPI_RESOURCE_RESERVE_EN_CU_11 0x31f3
+#define mmSPI_RESOURCE_RESERVE_EN_CU_12 0x31f8
+#define mmSPI_RESOURCE_RESERVE_EN_CU_13 0x31f9
+#define mmSPI_RESOURCE_RESERVE_EN_CU_14 0x31fa
+#define mmSPI_RESOURCE_RESERVE_EN_CU_15 0x31fb
+#define mmSPI_COMPUTE_WF_CTX_SAVE 0x31fc
+#define mmSPI_PS_MAX_WAVE_ID 0x243a
+#define mmSPI_START_PHASE 0x243b
+#define mmSPI_GFX_CNTL 0x243c
+#define mmSPI_CONFIG_CNTL 0x2440
+#define mmSPI_DEBUG_CNTL 0x2441
+#define mmSPI_DEBUG_READ 0x2442
+#define mmSPI_DSM_CNTL 0x2443
+#define mmSPI_EDC_CNT 0x2444
+#define mmSPI_PERFCOUNTER0_SELECT 0xd980
+#define mmSPI_PERFCOUNTER1_SELECT 0xd981
+#define mmSPI_PERFCOUNTER2_SELECT 0xd982
+#define mmSPI_PERFCOUNTER3_SELECT 0xd983
+#define mmSPI_PERFCOUNTER0_SELECT1 0xd984
+#define mmSPI_PERFCOUNTER1_SELECT1 0xd985
+#define mmSPI_PERFCOUNTER2_SELECT1 0xd986
+#define mmSPI_PERFCOUNTER3_SELECT1 0xd987
+#define mmSPI_PERFCOUNTER4_SELECT 0xd988
+#define mmSPI_PERFCOUNTER5_SELECT 0xd989
+#define mmSPI_PERFCOUNTER_BINS 0xd98a
+#define mmSPI_PERFCOUNTER0_HI 0xd180
+#define mmSPI_PERFCOUNTER0_LO 0xd181
+#define mmSPI_PERFCOUNTER1_HI 0xd182
+#define mmSPI_PERFCOUNTER1_LO 0xd183
+#define mmSPI_PERFCOUNTER2_HI 0xd184
+#define mmSPI_PERFCOUNTER2_LO 0xd185
+#define mmSPI_PERFCOUNTER3_HI 0xd186
+#define mmSPI_PERFCOUNTER3_LO 0xd187
+#define mmSPI_PERFCOUNTER4_HI 0xd188
+#define mmSPI_PERFCOUNTER4_LO 0xd189
+#define mmSPI_PERFCOUNTER5_HI 0xd18a
+#define mmSPI_PERFCOUNTER5_LO 0xd18b
+#define mmSPI_CONFIG_CNTL_1 0x244f
+#define mmSPI_DEBUG_BUSY 0x2450
+#define mmSPI_CONFIG_CNTL_2 0x2451
+#define mmCGTS_SM_CTRL_REG 0xf000
+#define mmCGTS_RD_CTRL_REG 0xf001
+#define mmCGTS_RD_REG 0xf002
+#define mmCGTS_TCC_DISABLE 0xf003
+#define mmCGTS_USER_TCC_DISABLE 0xf004
+#define mmCGTS_CU0_SP0_CTRL_REG 0xf008
+#define mmCGTS_CU0_LDS_SQ_CTRL_REG 0xf009
+#define mmCGTS_CU0_TA_SQC_CTRL_REG 0xf00a
+#define mmCGTS_CU0_SP1_CTRL_REG 0xf00b
+#define mmCGTS_CU0_TD_TCP_CTRL_REG 0xf00c
+#define mmCGTS_CU1_SP0_CTRL_REG 0xf00d
+#define mmCGTS_CU1_LDS_SQ_CTRL_REG 0xf00e
+#define mmCGTS_CU1_TA_CTRL_REG 0xf00f
+#define mmCGTS_CU1_SP1_CTRL_REG 0xf010
+#define mmCGTS_CU1_TD_TCP_CTRL_REG 0xf011
+#define mmCGTS_CU2_SP0_CTRL_REG 0xf012
+#define mmCGTS_CU2_LDS_SQ_CTRL_REG 0xf013
+#define mmCGTS_CU2_TA_CTRL_REG 0xf014
+#define mmCGTS_CU2_SP1_CTRL_REG 0xf015
+#define mmCGTS_CU2_TD_TCP_CTRL_REG 0xf016
+#define mmCGTS_CU3_SP0_CTRL_REG 0xf017
+#define mmCGTS_CU3_LDS_SQ_CTRL_REG 0xf018
+#define mmCGTS_CU3_TA_CTRL_REG 0xf019
+#define mmCGTS_CU3_SP1_CTRL_REG 0xf01a
+#define mmCGTS_CU3_TD_TCP_CTRL_REG 0xf01b
+#define mmCGTS_CU4_SP0_CTRL_REG 0xf01c
+#define mmCGTS_CU4_LDS_SQ_CTRL_REG 0xf01d
+#define mmCGTS_CU4_TA_SQC_CTRL_REG 0xf01e
+#define mmCGTS_CU4_SP1_CTRL_REG 0xf01f
+#define mmCGTS_CU4_TD_TCP_CTRL_REG 0xf020
+#define mmCGTS_CU5_SP0_CTRL_REG 0xf021
+#define mmCGTS_CU5_LDS_SQ_CTRL_REG 0xf022
+#define mmCGTS_CU5_TA_CTRL_REG 0xf023
+#define mmCGTS_CU5_SP1_CTRL_REG 0xf024
+#define mmCGTS_CU5_TD_TCP_CTRL_REG 0xf025
+#define mmCGTS_CU6_SP0_CTRL_REG 0xf026
+#define mmCGTS_CU6_LDS_SQ_CTRL_REG 0xf027
+#define mmCGTS_CU6_TA_CTRL_REG 0xf028
+#define mmCGTS_CU6_SP1_CTRL_REG 0xf029
+#define mmCGTS_CU6_TD_TCP_CTRL_REG 0xf02a
+#define mmCGTS_CU7_SP0_CTRL_REG 0xf02b
+#define mmCGTS_CU7_LDS_SQ_CTRL_REG 0xf02c
+#define mmCGTS_CU7_TA_CTRL_REG 0xf02d
+#define mmCGTS_CU7_SP1_CTRL_REG 0xf02e
+#define mmCGTS_CU7_TD_TCP_CTRL_REG 0xf02f
+#define mmCGTS_CU8_SP0_CTRL_REG 0xf030
+#define mmCGTS_CU8_LDS_SQ_CTRL_REG 0xf031
+#define mmCGTS_CU8_TA_SQC_CTRL_REG 0xf032
+#define mmCGTS_CU8_SP1_CTRL_REG 0xf033
+#define mmCGTS_CU8_TD_TCP_CTRL_REG 0xf034
+#define mmCGTS_CU9_SP0_CTRL_REG 0xf035
+#define mmCGTS_CU9_LDS_SQ_CTRL_REG 0xf036
+#define mmCGTS_CU9_TA_CTRL_REG 0xf037
+#define mmCGTS_CU9_SP1_CTRL_REG 0xf038
+#define mmCGTS_CU9_TD_TCP_CTRL_REG 0xf039
+#define mmCGTS_CU10_SP0_CTRL_REG 0xf03a
+#define mmCGTS_CU10_LDS_SQ_CTRL_REG 0xf03b
+#define mmCGTS_CU10_TA_CTRL_REG 0xf03c
+#define mmCGTS_CU10_SP1_CTRL_REG 0xf03d
+#define mmCGTS_CU10_TD_TCP_CTRL_REG 0xf03e
+#define mmCGTS_CU11_SP0_CTRL_REG 0xf03f
+#define mmCGTS_CU11_LDS_SQ_CTRL_REG 0xf040
+#define mmCGTS_CU11_TA_CTRL_REG 0xf041
+#define mmCGTS_CU11_SP1_CTRL_REG 0xf042
+#define mmCGTS_CU11_TD_TCP_CTRL_REG 0xf043
+#define mmCGTS_CU12_SP0_CTRL_REG 0xf044
+#define mmCGTS_CU12_LDS_SQ_CTRL_REG 0xf045
+#define mmCGTS_CU12_TA_SQC_CTRL_REG 0xf046
+#define mmCGTS_CU12_SP1_CTRL_REG 0xf047
+#define mmCGTS_CU12_TD_TCP_CTRL_REG 0xf048
+#define mmCGTS_CU13_SP0_CTRL_REG 0xf049
+#define mmCGTS_CU13_LDS_SQ_CTRL_REG 0xf04a
+#define mmCGTS_CU13_TA_CTRL_REG 0xf04b
+#define mmCGTS_CU13_SP1_CTRL_REG 0xf04c
+#define mmCGTS_CU13_TD_TCP_CTRL_REG 0xf04d
+#define mmCGTS_CU14_SP0_CTRL_REG 0xf04e
+#define mmCGTS_CU14_LDS_SQ_CTRL_REG 0xf04f
+#define mmCGTS_CU14_TA_CTRL_REG 0xf050
+#define mmCGTS_CU14_SP1_CTRL_REG 0xf051
+#define mmCGTS_CU14_TD_TCP_CTRL_REG 0xf052
+#define mmCGTS_CU15_SP0_CTRL_REG 0xf053
+#define mmCGTS_CU15_LDS_SQ_CTRL_REG 0xf054
+#define mmCGTS_CU15_TA_CTRL_REG 0xf055
+#define mmCGTS_CU15_SP1_CTRL_REG 0xf056
+#define mmCGTS_CU15_TD_TCP_CTRL_REG 0xf057
+#define mmCGTT_SPI_CLK_CTRL 0xf080
+#define mmCGTT_PC_CLK_CTRL 0xf081
+#define mmCGTT_BCI_CLK_CTRL 0xf082
+#define mmSPI_WF_LIFETIME_CNTL 0x24aa
+#define mmSPI_WF_LIFETIME_LIMIT_0 0x24ab
+#define mmSPI_WF_LIFETIME_LIMIT_1 0x24ac
+#define mmSPI_WF_LIFETIME_LIMIT_2 0x24ad
+#define mmSPI_WF_LIFETIME_LIMIT_3 0x24ae
+#define mmSPI_WF_LIFETIME_LIMIT_4 0x24af
+#define mmSPI_WF_LIFETIME_LIMIT_5 0x24b0
+#define mmSPI_WF_LIFETIME_LIMIT_6 0x24b1
+#define mmSPI_WF_LIFETIME_LIMIT_7 0x24b2
+#define mmSPI_WF_LIFETIME_LIMIT_8 0x24b3
+#define mmSPI_WF_LIFETIME_LIMIT_9 0x24b4
+#define mmSPI_WF_LIFETIME_STATUS_0 0x24b5
+#define mmSPI_WF_LIFETIME_STATUS_1 0x24b6
+#define mmSPI_WF_LIFETIME_STATUS_2 0x24b7
+#define mmSPI_WF_LIFETIME_STATUS_3 0x24b8
+#define mmSPI_WF_LIFETIME_STATUS_4 0x24b9
+#define mmSPI_WF_LIFETIME_STATUS_5 0x24ba
+#define mmSPI_WF_LIFETIME_STATUS_6 0x24bb
+#define mmSPI_WF_LIFETIME_STATUS_7 0x24bc
+#define mmSPI_WF_LIFETIME_STATUS_8 0x24bd
+#define mmSPI_WF_LIFETIME_STATUS_9 0x24be
+#define mmSPI_WF_LIFETIME_STATUS_10 0x24bf
+#define mmSPI_WF_LIFETIME_STATUS_11 0x24c0
+#define mmSPI_WF_LIFETIME_STATUS_12 0x24c1
+#define mmSPI_WF_LIFETIME_STATUS_13 0x24c2
+#define mmSPI_WF_LIFETIME_STATUS_14 0x24c3
+#define mmSPI_WF_LIFETIME_STATUS_15 0x24c4
+#define mmSPI_WF_LIFETIME_STATUS_16 0x24c5
+#define mmSPI_WF_LIFETIME_STATUS_17 0x24c6
+#define mmSPI_WF_LIFETIME_STATUS_18 0x24c7
+#define mmSPI_WF_LIFETIME_STATUS_19 0x24c8
+#define mmSPI_WF_LIFETIME_STATUS_20 0x24c9
+#define mmSPI_WF_LIFETIME_DEBUG 0x24ca
+#define mmSPI_SLAVE_DEBUG_BUSY 0x24d3
+#define mmSPI_LB_CTR_CTRL 0x24d4
+#define mmSPI_LB_CU_MASK 0x24d5
+#define mmSPI_LB_DATA_REG 0x24d6
+#define mmSPI_PG_ENABLE_STATIC_CU_MASK 0x24d7
+#define mmSPI_GDS_CREDITS 0x24d8
+#define mmSPI_SX_EXPORT_BUFFER_SIZES 0x24d9
+#define mmSPI_SX_SCOREBOARD_BUFFER_SIZES 0x24da
+#define mmSPI_CSQ_WF_ACTIVE_STATUS 0x24db
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_0 0x24dc
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_1 0x24dd
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_2 0x24de
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_3 0x24df
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_4 0x24e0
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_5 0x24e1
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_6 0x24e2
+#define mmSPI_CSQ_WF_ACTIVE_COUNT_7 0x24e3
+#define mmBCI_DEBUG_READ 0x24eb
+#define mmSPI_P0_TRAP_SCREEN_PSBA_LO 0x24ec
+#define mmSPI_P0_TRAP_SCREEN_PSBA_HI 0x24ed
+#define mmSPI_P0_TRAP_SCREEN_PSMA_LO 0x24ee
+#define mmSPI_P0_TRAP_SCREEN_PSMA_HI 0x24ef
+#define mmSPI_P0_TRAP_SCREEN_GPR_MIN 0x24f0
+#define mmSPI_P1_TRAP_SCREEN_PSBA_LO 0x24f1
+#define mmSPI_P1_TRAP_SCREEN_PSBA_HI 0x24f2
+#define mmSPI_P1_TRAP_SCREEN_PSMA_LO 0x24f3
+#define mmSPI_P1_TRAP_SCREEN_PSMA_HI 0x24f4
+#define mmSPI_P1_TRAP_SCREEN_GPR_MIN 0x24f5
+#define mmSPI_SHADER_TBA_LO_PS 0x2c00
+#define mmSPI_SHADER_TBA_HI_PS 0x2c01
+#define mmSPI_SHADER_TMA_LO_PS 0x2c02
+#define mmSPI_SHADER_TMA_HI_PS 0x2c03
+#define mmSPI_SHADER_PGM_LO_PS 0x2c08
+#define mmSPI_SHADER_PGM_HI_PS 0x2c09
+#define mmSPI_SHADER_PGM_RSRC1_PS 0x2c0a
+#define mmSPI_SHADER_PGM_RSRC2_PS 0x2c0b
+#define mmSPI_SHADER_PGM_RSRC3_PS 0x2c07
+#define mmSPI_SHADER_USER_DATA_PS_0 0x2c0c
+#define mmSPI_SHADER_USER_DATA_PS_1 0x2c0d
+#define mmSPI_SHADER_USER_DATA_PS_2 0x2c0e
+#define mmSPI_SHADER_USER_DATA_PS_3 0x2c0f
+#define mmSPI_SHADER_USER_DATA_PS_4 0x2c10
+#define mmSPI_SHADER_USER_DATA_PS_5 0x2c11
+#define mmSPI_SHADER_USER_DATA_PS_6 0x2c12
+#define mmSPI_SHADER_USER_DATA_PS_7 0x2c13
+#define mmSPI_SHADER_USER_DATA_PS_8 0x2c14
+#define mmSPI_SHADER_USER_DATA_PS_9 0x2c15
+#define mmSPI_SHADER_USER_DATA_PS_10 0x2c16
+#define mmSPI_SHADER_USER_DATA_PS_11 0x2c17
+#define mmSPI_SHADER_USER_DATA_PS_12 0x2c18
+#define mmSPI_SHADER_USER_DATA_PS_13 0x2c19
+#define mmSPI_SHADER_USER_DATA_PS_14 0x2c1a
+#define mmSPI_SHADER_USER_DATA_PS_15 0x2c1b
+#define mmSPI_SHADER_TBA_LO_VS 0x2c40
+#define mmSPI_SHADER_TBA_HI_VS 0x2c41
+#define mmSPI_SHADER_TMA_LO_VS 0x2c42
+#define mmSPI_SHADER_TMA_HI_VS 0x2c43
+#define mmSPI_SHADER_PGM_LO_VS 0x2c48
+#define mmSPI_SHADER_PGM_HI_VS 0x2c49
+#define mmSPI_SHADER_PGM_RSRC1_VS 0x2c4a
+#define mmSPI_SHADER_PGM_RSRC2_VS 0x2c4b
+#define mmSPI_SHADER_PGM_RSRC3_VS 0x2c46
+#define mmSPI_SHADER_LATE_ALLOC_VS 0x2c47
+#define mmSPI_SHADER_USER_DATA_VS_0 0x2c4c
+#define mmSPI_SHADER_USER_DATA_VS_1 0x2c4d
+#define mmSPI_SHADER_USER_DATA_VS_2 0x2c4e
+#define mmSPI_SHADER_USER_DATA_VS_3 0x2c4f
+#define mmSPI_SHADER_USER_DATA_VS_4 0x2c50
+#define mmSPI_SHADER_USER_DATA_VS_5 0x2c51
+#define mmSPI_SHADER_USER_DATA_VS_6 0x2c52
+#define mmSPI_SHADER_USER_DATA_VS_7 0x2c53
+#define mmSPI_SHADER_USER_DATA_VS_8 0x2c54
+#define mmSPI_SHADER_USER_DATA_VS_9 0x2c55
+#define mmSPI_SHADER_USER_DATA_VS_10 0x2c56
+#define mmSPI_SHADER_USER_DATA_VS_11 0x2c57
+#define mmSPI_SHADER_USER_DATA_VS_12 0x2c58
+#define mmSPI_SHADER_USER_DATA_VS_13 0x2c59
+#define mmSPI_SHADER_USER_DATA_VS_14 0x2c5a
+#define mmSPI_SHADER_USER_DATA_VS_15 0x2c5b
+#define mmSPI_SHADER_PGM_RSRC2_ES_VS 0x2c7c
+#define mmSPI_SHADER_PGM_RSRC2_LS_VS 0x2c7d
+#define mmSPI_SHADER_TBA_LO_GS 0x2c80
+#define mmSPI_SHADER_TBA_HI_GS 0x2c81
+#define mmSPI_SHADER_TMA_LO_GS 0x2c82
+#define mmSPI_SHADER_TMA_HI_GS 0x2c83
+#define mmSPI_SHADER_PGM_LO_GS 0x2c88
+#define mmSPI_SHADER_PGM_HI_GS 0x2c89
+#define mmSPI_SHADER_PGM_RSRC1_GS 0x2c8a
+#define mmSPI_SHADER_PGM_RSRC2_GS 0x2c8b
+#define mmSPI_SHADER_PGM_RSRC3_GS 0x2c87
+#define mmSPI_SHADER_USER_DATA_GS_0 0x2c8c
+#define mmSPI_SHADER_USER_DATA_GS_1 0x2c8d
+#define mmSPI_SHADER_USER_DATA_GS_2 0x2c8e
+#define mmSPI_SHADER_USER_DATA_GS_3 0x2c8f
+#define mmSPI_SHADER_USER_DATA_GS_4 0x2c90
+#define mmSPI_SHADER_USER_DATA_GS_5 0x2c91
+#define mmSPI_SHADER_USER_DATA_GS_6 0x2c92
+#define mmSPI_SHADER_USER_DATA_GS_7 0x2c93
+#define mmSPI_SHADER_USER_DATA_GS_8 0x2c94
+#define mmSPI_SHADER_USER_DATA_GS_9 0x2c95
+#define mmSPI_SHADER_USER_DATA_GS_10 0x2c96
+#define mmSPI_SHADER_USER_DATA_GS_11 0x2c97
+#define mmSPI_SHADER_USER_DATA_GS_12 0x2c98
+#define mmSPI_SHADER_USER_DATA_GS_13 0x2c99
+#define mmSPI_SHADER_USER_DATA_GS_14 0x2c9a
+#define mmSPI_SHADER_USER_DATA_GS_15 0x2c9b
+#define mmSPI_SHADER_PGM_RSRC2_ES_GS 0x2cbc
+#define mmSPI_SHADER_TBA_LO_ES 0x2cc0
+#define mmSPI_SHADER_TBA_HI_ES 0x2cc1
+#define mmSPI_SHADER_TMA_LO_ES 0x2cc2
+#define mmSPI_SHADER_TMA_HI_ES 0x2cc3
+#define mmSPI_SHADER_PGM_LO_ES 0x2cc8
+#define mmSPI_SHADER_PGM_HI_ES 0x2cc9
+#define mmSPI_SHADER_PGM_RSRC1_ES 0x2cca
+#define mmSPI_SHADER_PGM_RSRC2_ES 0x2ccb
+#define mmSPI_SHADER_PGM_RSRC3_ES 0x2cc7
+#define mmSPI_SHADER_USER_DATA_ES_0 0x2ccc
+#define mmSPI_SHADER_USER_DATA_ES_1 0x2ccd
+#define mmSPI_SHADER_USER_DATA_ES_2 0x2cce
+#define mmSPI_SHADER_USER_DATA_ES_3 0x2ccf
+#define mmSPI_SHADER_USER_DATA_ES_4 0x2cd0
+#define mmSPI_SHADER_USER_DATA_ES_5 0x2cd1
+#define mmSPI_SHADER_USER_DATA_ES_6 0x2cd2
+#define mmSPI_SHADER_USER_DATA_ES_7 0x2cd3
+#define mmSPI_SHADER_USER_DATA_ES_8 0x2cd4
+#define mmSPI_SHADER_USER_DATA_ES_9 0x2cd5
+#define mmSPI_SHADER_USER_DATA_ES_10 0x2cd6
+#define mmSPI_SHADER_USER_DATA_ES_11 0x2cd7
+#define mmSPI_SHADER_USER_DATA_ES_12 0x2cd8
+#define mmSPI_SHADER_USER_DATA_ES_13 0x2cd9
+#define mmSPI_SHADER_USER_DATA_ES_14 0x2cda
+#define mmSPI_SHADER_USER_DATA_ES_15 0x2cdb
+#define mmSPI_SHADER_PGM_RSRC2_LS_ES 0x2cfd
+#define mmSPI_SHADER_TBA_LO_HS 0x2d00
+#define mmSPI_SHADER_TBA_HI_HS 0x2d01
+#define mmSPI_SHADER_TMA_LO_HS 0x2d02
+#define mmSPI_SHADER_TMA_HI_HS 0x2d03
+#define mmSPI_SHADER_PGM_LO_HS 0x2d08
+#define mmSPI_SHADER_PGM_HI_HS 0x2d09
+#define mmSPI_SHADER_PGM_RSRC1_HS 0x2d0a
+#define mmSPI_SHADER_PGM_RSRC2_HS 0x2d0b
+#define mmSPI_SHADER_PGM_RSRC3_HS 0x2d07
+#define mmSPI_SHADER_USER_DATA_HS_0 0x2d0c
+#define mmSPI_SHADER_USER_DATA_HS_1 0x2d0d
+#define mmSPI_SHADER_USER_DATA_HS_2 0x2d0e
+#define mmSPI_SHADER_USER_DATA_HS_3 0x2d0f
+#define mmSPI_SHADER_USER_DATA_HS_4 0x2d10
+#define mmSPI_SHADER_USER_DATA_HS_5 0x2d11
+#define mmSPI_SHADER_USER_DATA_HS_6 0x2d12
+#define mmSPI_SHADER_USER_DATA_HS_7 0x2d13
+#define mmSPI_SHADER_USER_DATA_HS_8 0x2d14
+#define mmSPI_SHADER_USER_DATA_HS_9 0x2d15
+#define mmSPI_SHADER_USER_DATA_HS_10 0x2d16
+#define mmSPI_SHADER_USER_DATA_HS_11 0x2d17
+#define mmSPI_SHADER_USER_DATA_HS_12 0x2d18
+#define mmSPI_SHADER_USER_DATA_HS_13 0x2d19
+#define mmSPI_SHADER_USER_DATA_HS_14 0x2d1a
+#define mmSPI_SHADER_USER_DATA_HS_15 0x2d1b
+#define mmSPI_SHADER_PGM_RSRC2_LS_HS 0x2d3d
+#define mmSPI_SHADER_TBA_LO_LS 0x2d40
+#define mmSPI_SHADER_TBA_HI_LS 0x2d41
+#define mmSPI_SHADER_TMA_LO_LS 0x2d42
+#define mmSPI_SHADER_TMA_HI_LS 0x2d43
+#define mmSPI_SHADER_PGM_LO_LS 0x2d48
+#define mmSPI_SHADER_PGM_HI_LS 0x2d49
+#define mmSPI_SHADER_PGM_RSRC1_LS 0x2d4a
+#define mmSPI_SHADER_PGM_RSRC2_LS 0x2d4b
+#define mmSPI_SHADER_PGM_RSRC3_LS 0x2d47
+#define mmSPI_SHADER_USER_DATA_LS_0 0x2d4c
+#define mmSPI_SHADER_USER_DATA_LS_1 0x2d4d
+#define mmSPI_SHADER_USER_DATA_LS_2 0x2d4e
+#define mmSPI_SHADER_USER_DATA_LS_3 0x2d4f
+#define mmSPI_SHADER_USER_DATA_LS_4 0x2d50
+#define mmSPI_SHADER_USER_DATA_LS_5 0x2d51
+#define mmSPI_SHADER_USER_DATA_LS_6 0x2d52
+#define mmSPI_SHADER_USER_DATA_LS_7 0x2d53
+#define mmSPI_SHADER_USER_DATA_LS_8 0x2d54
+#define mmSPI_SHADER_USER_DATA_LS_9 0x2d55
+#define mmSPI_SHADER_USER_DATA_LS_10 0x2d56
+#define mmSPI_SHADER_USER_DATA_LS_11 0x2d57
+#define mmSPI_SHADER_USER_DATA_LS_12 0x2d58
+#define mmSPI_SHADER_USER_DATA_LS_13 0x2d59
+#define mmSPI_SHADER_USER_DATA_LS_14 0x2d5a
+#define mmSPI_SHADER_USER_DATA_LS_15 0x2d5b
+#define mmSQ_CONFIG 0x2300
+#define mmSQC_CONFIG 0x2301
+#define mmSQC_CACHES 0xc348
+#define mmSQC_WRITEBACK 0xc349
+#define mmSQC_DSM_CNTL 0x230f
+#define mmSQ_RANDOM_WAVE_PRI 0x2303
+#define mmSQ_REG_CREDITS 0x2304
+#define mmSQ_FIFO_SIZES 0x2305
+#define mmSQ_DSM_CNTL 0x2306
+#define mmCC_GC_SHADER_RATE_CONFIG 0x2312
+#define mmGC_USER_SHADER_RATE_CONFIG 0x2313
+#define mmSQ_INTERRUPT_AUTO_MASK 0x2314
+#define mmSQ_INTERRUPT_MSG_CTRL 0x2315
+#define mmSQ_PERFCOUNTER_CTRL 0xd9e0
+#define mmSQ_PERFCOUNTER_MASK 0xd9e1
+#define mmSQ_PERFCOUNTER_CTRL2 0xd9e2
+#define mmCC_SQC_BANK_DISABLE 0x2307
+#define mmUSER_SQC_BANK_DISABLE 0x2308
+#define mmSQ_PERFCOUNTER0_LO 0xd1c0
+#define mmSQ_PERFCOUNTER1_LO 0xd1c2
+#define mmSQ_PERFCOUNTER2_LO 0xd1c4
+#define mmSQ_PERFCOUNTER3_LO 0xd1c6
+#define mmSQ_PERFCOUNTER4_LO 0xd1c8
+#define mmSQ_PERFCOUNTER5_LO 0xd1ca
+#define mmSQ_PERFCOUNTER6_LO 0xd1cc
+#define mmSQ_PERFCOUNTER7_LO 0xd1ce
+#define mmSQ_PERFCOUNTER8_LO 0xd1d0
+#define mmSQ_PERFCOUNTER9_LO 0xd1d2
+#define mmSQ_PERFCOUNTER10_LO 0xd1d4
+#define mmSQ_PERFCOUNTER11_LO 0xd1d6
+#define mmSQ_PERFCOUNTER12_LO 0xd1d8
+#define mmSQ_PERFCOUNTER13_LO 0xd1da
+#define mmSQ_PERFCOUNTER14_LO 0xd1dc
+#define mmSQ_PERFCOUNTER15_LO 0xd1de
+#define mmSQ_PERFCOUNTER0_HI 0xd1c1
+#define mmSQ_PERFCOUNTER1_HI 0xd1c3
+#define mmSQ_PERFCOUNTER2_HI 0xd1c5
+#define mmSQ_PERFCOUNTER3_HI 0xd1c7
+#define mmSQ_PERFCOUNTER4_HI 0xd1c9
+#define mmSQ_PERFCOUNTER5_HI 0xd1cb
+#define mmSQ_PERFCOUNTER6_HI 0xd1cd
+#define mmSQ_PERFCOUNTER7_HI 0xd1cf
+#define mmSQ_PERFCOUNTER8_HI 0xd1d1
+#define mmSQ_PERFCOUNTER9_HI 0xd1d3
+#define mmSQ_PERFCOUNTER10_HI 0xd1d5
+#define mmSQ_PERFCOUNTER11_HI 0xd1d7
+#define mmSQ_PERFCOUNTER12_HI 0xd1d9
+#define mmSQ_PERFCOUNTER13_HI 0xd1db
+#define mmSQ_PERFCOUNTER14_HI 0xd1dd
+#define mmSQ_PERFCOUNTER15_HI 0xd1df
+#define mmSQ_PERFCOUNTER0_SELECT 0xd9c0
+#define mmSQ_PERFCOUNTER1_SELECT 0xd9c1
+#define mmSQ_PERFCOUNTER2_SELECT 0xd9c2
+#define mmSQ_PERFCOUNTER3_SELECT 0xd9c3
+#define mmSQ_PERFCOUNTER4_SELECT 0xd9c4
+#define mmSQ_PERFCOUNTER5_SELECT 0xd9c5
+#define mmSQ_PERFCOUNTER6_SELECT 0xd9c6
+#define mmSQ_PERFCOUNTER7_SELECT 0xd9c7
+#define mmSQ_PERFCOUNTER8_SELECT 0xd9c8
+#define mmSQ_PERFCOUNTER9_SELECT 0xd9c9
+#define mmSQ_PERFCOUNTER10_SELECT 0xd9ca
+#define mmSQ_PERFCOUNTER11_SELECT 0xd9cb
+#define mmSQ_PERFCOUNTER12_SELECT 0xd9cc
+#define mmSQ_PERFCOUNTER13_SELECT 0xd9cd
+#define mmSQ_PERFCOUNTER14_SELECT 0xd9ce
+#define mmSQ_PERFCOUNTER15_SELECT 0xd9cf
+#define mmCGTT_SQ_CLK_CTRL 0xf08c
+#define mmCGTT_SQG_CLK_CTRL 0xf08d
+#define mmSQ_ALU_CLK_CTRL 0xf08e
+#define mmSQ_TEX_CLK_CTRL 0xf08f
+#define mmSQ_LDS_CLK_CTRL 0xf090
+#define mmSQ_POWER_THROTTLE 0xf091
+#define mmSQ_POWER_THROTTLE2 0xf092
+#define mmSQ_TIME_HI 0x237c
+#define mmSQ_TIME_LO 0x237d
+#define mmSQ_THREAD_TRACE_BASE 0xc330
+#define mmSQ_THREAD_TRACE_BASE2 0xc337
+#define mmSQ_THREAD_TRACE_SIZE 0xc331
+#define mmSQ_THREAD_TRACE_MASK 0xc332
+#define mmSQ_THREAD_TRACE_USERDATA_0 0xc340
+#define mmSQ_THREAD_TRACE_USERDATA_1 0xc341
+#define mmSQ_THREAD_TRACE_USERDATA_2 0xc342
+#define mmSQ_THREAD_TRACE_USERDATA_3 0xc343
+#define mmSQ_THREAD_TRACE_MODE 0xc336
+#define mmSQ_THREAD_TRACE_CTRL 0xc335
+#define mmSQ_THREAD_TRACE_TOKEN_MASK 0xc333
+#define mmSQ_THREAD_TRACE_TOKEN_MASK2 0xc338
+#define mmSQ_THREAD_TRACE_PERF_MASK 0xc334
+#define mmSQ_THREAD_TRACE_WPTR 0xc339
+#define mmSQ_THREAD_TRACE_STATUS 0xc33a
+#define mmSQ_THREAD_TRACE_CNTR 0x2390
+#define mmSQ_THREAD_TRACE_HIWATER 0xc33b
+#define mmSQ_LB_CTR_CTRL 0x2398
+#define mmSQ_LB_DATA_ALU_CYCLES 0x2399
+#define mmSQ_LB_DATA_TEX_CYCLES 0x239a
+#define mmSQ_LB_DATA_ALU_STALLS 0x239b
+#define mmSQ_LB_DATA_TEX_STALLS 0x239c
+#define mmSQC_EDC_CNT 0x23a0
+#define mmSQ_EDC_SEC_CNT 0x23a1
+#define mmSQ_EDC_DED_CNT 0x23a2
+#define mmSQ_EDC_INFO 0x23a3
+#define mmSQ_BUF_RSRC_WORD0 0x23c0
+#define mmSQ_BUF_RSRC_WORD1 0x23c1
+#define mmSQ_BUF_RSRC_WORD2 0x23c2
+#define mmSQ_BUF_RSRC_WORD3 0x23c3
+#define mmSQ_IMG_RSRC_WORD0 0x23c4
+#define mmSQ_IMG_RSRC_WORD1 0x23c5
+#define mmSQ_IMG_RSRC_WORD2 0x23c6
+#define mmSQ_IMG_RSRC_WORD3 0x23c7
+#define mmSQ_IMG_RSRC_WORD4 0x23c8
+#define mmSQ_IMG_RSRC_WORD5 0x23c9
+#define mmSQ_IMG_RSRC_WORD6 0x23ca
+#define mmSQ_IMG_RSRC_WORD7 0x23cb
+#define mmSQ_IMG_SAMP_WORD0 0x23cc
+#define mmSQ_IMG_SAMP_WORD1 0x23cd
+#define mmSQ_IMG_SAMP_WORD2 0x23ce
+#define mmSQ_IMG_SAMP_WORD3 0x23cf
+#define mmSQ_FLAT_SCRATCH_WORD0 0x23d0
+#define mmSQ_FLAT_SCRATCH_WORD1 0x23d1
+#define mmSQ_M0_GPR_IDX_WORD 0x23d2
+#define mmSQ_IND_INDEX 0x2378
+#define mmSQ_CMD 0x237b
+#define mmSQ_IND_DATA 0x2379
+#define mmSQ_REG_TIMESTAMP 0x2374
+#define mmSQ_CMD_TIMESTAMP 0x2375
+#define mmSQ_HV_VMID_CTRL 0xf840
+#define ixSQ_WAVE_INST_DW0 0x1a
+#define ixSQ_WAVE_INST_DW1 0x1b
+#define ixSQ_WAVE_PC_LO 0x18
+#define ixSQ_WAVE_PC_HI 0x19
+#define ixSQ_WAVE_IB_DBG0 0x1c
+#define ixSQ_WAVE_IB_DBG1 0x1d
+#define ixSQ_WAVE_EXEC_LO 0x27e
+#define ixSQ_WAVE_EXEC_HI 0x27f
+#define ixSQ_WAVE_STATUS 0x12
+#define ixSQ_WAVE_MODE 0x11
+#define ixSQ_WAVE_TRAPSTS 0x13
+#define ixSQ_WAVE_HW_ID 0x14
+#define ixSQ_WAVE_GPR_ALLOC 0x15
+#define ixSQ_WAVE_LDS_ALLOC 0x16
+#define ixSQ_WAVE_IB_STS 0x17
+#define ixSQ_WAVE_M0 0x27c
+#define ixSQ_WAVE_TBA_LO 0x26c
+#define ixSQ_WAVE_TBA_HI 0x26d
+#define ixSQ_WAVE_TMA_LO 0x26e
+#define ixSQ_WAVE_TMA_HI 0x26f
+#define ixSQ_WAVE_TTMP0 0x270
+#define ixSQ_WAVE_TTMP1 0x271
+#define ixSQ_WAVE_TTMP2 0x272
+#define ixSQ_WAVE_TTMP3 0x273
+#define ixSQ_WAVE_TTMP4 0x274
+#define ixSQ_WAVE_TTMP5 0x275
+#define ixSQ_WAVE_TTMP6 0x276
+#define ixSQ_WAVE_TTMP7 0x277
+#define ixSQ_WAVE_TTMP8 0x278
+#define ixSQ_WAVE_TTMP9 0x279
+#define ixSQ_WAVE_TTMP10 0x27a
+#define ixSQ_WAVE_TTMP11 0x27b
+#define mmSQ_DEBUG_STS_GLOBAL 0x2309
+#define mmSQ_DEBUG_STS_GLOBAL2 0x2310
+#define mmSQ_DEBUG_STS_GLOBAL3 0x2311
+#define ixSQ_DEBUG_STS_LOCAL 0x8
+#define ixSQ_DEBUG_CTRL_LOCAL 0x9
+#define mmSH_MEM_BASES 0x230a
+#define mmSH_MEM_APE1_BASE 0x230b
+#define mmSH_MEM_APE1_LIMIT 0x230c
+#define mmSH_MEM_CONFIG 0x230d
+#define mmSQ_THREAD_TRACE_WORD_CMN 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_INST 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_INST_PC_1_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_INST_PC_2_OF_2 0x23b1
+#define mmSQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2 0x23b1
+#define mmSQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2 0x23b1
+#define mmSQ_THREAD_TRACE_WORD_WAVE 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_MISC 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_WAVE_START 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_REG_1_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_REG_2_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_REG_CS_1_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_REG_CS_2_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_EVENT 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_ISSUE 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_PERF_1_OF_2 0x23b0
+#define mmSQ_THREAD_TRACE_WORD_PERF_2_OF_2 0x23b1
+#define mmSQ_WREXEC_EXEC_LO 0x23b1
+#define mmSQ_WREXEC_EXEC_HI 0x23b1
+#define mmSQC_GATCL1_CNTL 0x23b2
+#define mmSQC_ATC_EDC_GATCL1_CNT 0x23b3
+#define ixSQ_INTERRUPT_WORD_CMN 0x20c0
+#define ixSQ_INTERRUPT_WORD_AUTO 0x20c0
+#define ixSQ_INTERRUPT_WORD_WAVE 0x20c0
+#define mmSQ_SOP2 0x237f
+#define mmSQ_VOP1 0x237f
+#define mmSQ_MTBUF_1 0x237f
+#define mmSQ_EXP_1 0x237f
+#define mmSQ_MUBUF_1 0x237f
+#define mmSQ_SMEM_1 0x237f
+#define mmSQ_INST 0x237f
+#define mmSQ_EXP_0 0x237f
+#define mmSQ_MUBUF_0 0x237f
+#define mmSQ_VOP_SDWA 0x237f
+#define mmSQ_VOP3_0 0x237f
+#define mmSQ_VOP2 0x237f
+#define mmSQ_MTBUF_0 0x237f
+#define mmSQ_SOPP 0x237f
+#define mmSQ_FLAT_0 0x237f
+#define mmSQ_VOP3_0_SDST_ENC 0x237f
+#define mmSQ_MIMG_1 0x237f
+#define mmSQ_SOP1 0x237f
+#define mmSQ_SOPC 0x237f
+#define mmSQ_FLAT_1 0x237f
+#define mmSQ_DS_1 0x237f
+#define mmSQ_VOP3_1 0x237f
+#define mmSQ_SMEM_0 0x237f
+#define mmSQ_MIMG_0 0x237f
+#define mmSQ_SOPK 0x237f
+#define mmSQ_DS_0 0x237f
+#define mmSQ_VOP_DPP 0x237f
+#define mmSQ_VOPC 0x237f
+#define mmSQ_VINTRP 0x237f
+#define mmCGTT_SX_CLK_CTRL0 0xf094
+#define mmCGTT_SX_CLK_CTRL1 0xf095
+#define mmCGTT_SX_CLK_CTRL2 0xf096
+#define mmCGTT_SX_CLK_CTRL3 0xf097
+#define mmCGTT_SX_CLK_CTRL4 0xf098
+#define mmSX_DEBUG_BUSY 0x2414
+#define mmSX_DEBUG_BUSY_2 0x2415
+#define mmSX_DEBUG_BUSY_3 0x2416
+#define mmSX_DEBUG_BUSY_4 0x2417
+#define mmSX_DEBUG_1 0x2418
+#define mmSX_PERFCOUNTER0_SELECT 0xda40
+#define mmSX_PERFCOUNTER1_SELECT 0xda41
+#define mmSX_PERFCOUNTER2_SELECT 0xda42
+#define mmSX_PERFCOUNTER3_SELECT 0xda43
+#define mmSX_PERFCOUNTER0_SELECT1 0xda44
+#define mmSX_PERFCOUNTER1_SELECT1 0xda45
+#define mmSX_PERFCOUNTER0_LO 0xd240
+#define mmSX_PERFCOUNTER0_HI 0xd241
+#define mmSX_PERFCOUNTER1_LO 0xd242
+#define mmSX_PERFCOUNTER1_HI 0xd243
+#define mmSX_PERFCOUNTER2_LO 0xd244
+#define mmSX_PERFCOUNTER2_HI 0xd245
+#define mmSX_PERFCOUNTER3_LO 0xd246
+#define mmSX_PERFCOUNTER3_HI 0xd247
+#define mmSX_PS_DOWNCONVERT 0xa1d5
+#define mmSX_BLEND_OPT_EPSILON 0xa1d6
+#define mmSX_BLEND_OPT_CONTROL 0xa1d7
+#define mmSX_MRT0_BLEND_OPT 0xa1d8
+#define mmSX_MRT1_BLEND_OPT 0xa1d9
+#define mmSX_MRT2_BLEND_OPT 0xa1da
+#define mmSX_MRT3_BLEND_OPT 0xa1db
+#define mmSX_MRT4_BLEND_OPT 0xa1dc
+#define mmSX_MRT5_BLEND_OPT 0xa1dd
+#define mmSX_MRT6_BLEND_OPT 0xa1de
+#define mmSX_MRT7_BLEND_OPT 0xa1df
+#define mmTCC_CTRL 0x2b80
+#define mmTCC_EDC_CNT 0x2b82
+#define mmTCC_REDUNDANCY 0x2b83
+#define mmTCC_EXE_DISABLE 0x2b84
+#define mmTCC_DSM_CNTL 0x2b85
+#define mmTCC_CGTT_SCLK_CTRL 0xf0ac
+#define mmTCA_CGTT_SCLK_CTRL 0xf0ad
+#define mmTCC_PERFCOUNTER0_SELECT 0xdb80
+#define mmTCC_PERFCOUNTER1_SELECT 0xdb82
+#define mmTCC_PERFCOUNTER0_SELECT1 0xdb81
+#define mmTCC_PERFCOUNTER1_SELECT1 0xdb83
+#define mmTCC_PERFCOUNTER2_SELECT 0xdb84
+#define mmTCC_PERFCOUNTER3_SELECT 0xdb85
+#define mmTCC_PERFCOUNTER0_LO 0xd380
+#define mmTCC_PERFCOUNTER1_LO 0xd382
+#define mmTCC_PERFCOUNTER2_LO 0xd384
+#define mmTCC_PERFCOUNTER3_LO 0xd386
+#define mmTCC_PERFCOUNTER0_HI 0xd381
+#define mmTCC_PERFCOUNTER1_HI 0xd383
+#define mmTCC_PERFCOUNTER2_HI 0xd385
+#define mmTCC_PERFCOUNTER3_HI 0xd387
+#define mmTCA_CTRL 0x2bc0
+#define mmTCA_PERFCOUNTER0_SELECT 0xdb90
+#define mmTCA_PERFCOUNTER1_SELECT 0xdb92
+#define mmTCA_PERFCOUNTER0_SELECT1 0xdb91
+#define mmTCA_PERFCOUNTER1_SELECT1 0xdb93
+#define mmTCA_PERFCOUNTER2_SELECT 0xdb94
+#define mmTCA_PERFCOUNTER3_SELECT 0xdb95
+#define mmTCA_PERFCOUNTER0_LO 0xd390
+#define mmTCA_PERFCOUNTER1_LO 0xd392
+#define mmTCA_PERFCOUNTER2_LO 0xd394
+#define mmTCA_PERFCOUNTER3_LO 0xd396
+#define mmTCA_PERFCOUNTER0_HI 0xd391
+#define mmTCA_PERFCOUNTER1_HI 0xd393
+#define mmTCA_PERFCOUNTER2_HI 0xd395
+#define mmTCA_PERFCOUNTER3_HI 0xd397
+#define mmTA_BC_BASE_ADDR 0xa020
+#define mmTA_BC_BASE_ADDR_HI 0xa021
+#define mmTD_CNTL 0x2525
+#define mmTD_STATUS 0x2526
+#define mmTD_DEBUG_INDEX 0x2528
+#define mmTD_DEBUG_DATA 0x2529
+#define mmTD_DSM_CNTL 0x252f
+#define mmTD_PERFCOUNTER0_SELECT 0xdb00
+#define mmTD_PERFCOUNTER1_SELECT 0xdb02
+#define mmTD_PERFCOUNTER0_SELECT1 0xdb01
+#define mmTD_PERFCOUNTER0_LO 0xd300
+#define mmTD_PERFCOUNTER1_LO 0xd302
+#define mmTD_PERFCOUNTER0_HI 0xd301
+#define mmTD_PERFCOUNTER1_HI 0xd303
+#define mmTD_SCRATCH 0x2533
+#define mmTA_CNTL 0x2541
+#define mmTA_CNTL_AUX 0x2542
+#define mmTA_RESERVED_010C 0x2543
+#define mmTA_CS_BC_BASE_ADDR 0xc380
+#define mmTA_CS_BC_BASE_ADDR_HI 0xc381
+#define mmTA_STATUS 0x2548
+#define mmTA_DEBUG_INDEX 0x254c
+#define mmTA_DEBUG_DATA 0x254d
+#define mmTA_PERFCOUNTER0_SELECT 0xdac0
+#define mmTA_PERFCOUNTER1_SELECT 0xdac2
+#define mmTA_PERFCOUNTER0_SELECT1 0xdac1
+#define mmTA_PERFCOUNTER0_LO 0xd2c0
+#define mmTA_PERFCOUNTER1_LO 0xd2c2
+#define mmTA_PERFCOUNTER0_HI 0xd2c1
+#define mmTA_PERFCOUNTER1_HI 0xd2c3
+#define mmTA_SCRATCH 0x2564
+#define mmSH_HIDDEN_PRIVATE_BASE_VMID 0x2580
+#define mmSH_STATIC_MEM_CONFIG 0x2581
+#define mmTCP_INVALIDATE 0x2b00
+#define mmTCP_STATUS 0x2b01
+#define mmTCP_CNTL 0x2b02
+#define mmTCP_CHAN_STEER_LO 0x2b03
+#define mmTCP_CHAN_STEER_HI 0x2b04
+#define mmTCP_ADDR_CONFIG 0x2b05
+#define mmTCP_CREDIT 0x2b06
+#define mmTCP_PERFCOUNTER0_SELECT 0xdb40
+#define mmTCP_PERFCOUNTER1_SELECT 0xdb42
+#define mmTCP_PERFCOUNTER0_SELECT1 0xdb41
+#define mmTCP_PERFCOUNTER1_SELECT1 0xdb43
+#define mmTCP_PERFCOUNTER2_SELECT 0xdb44
+#define mmTCP_PERFCOUNTER3_SELECT 0xdb45
+#define mmTCP_PERFCOUNTER0_LO 0xd340
+#define mmTCP_PERFCOUNTER1_LO 0xd342
+#define mmTCP_PERFCOUNTER2_LO 0xd344
+#define mmTCP_PERFCOUNTER3_LO 0xd346
+#define mmTCP_PERFCOUNTER0_HI 0xd341
+#define mmTCP_PERFCOUNTER1_HI 0xd343
+#define mmTCP_PERFCOUNTER2_HI 0xd345
+#define mmTCP_PERFCOUNTER3_HI 0xd347
+#define mmTCP_BUFFER_ADDR_HASH_CNTL 0x2b16
+#define mmTCP_EDC_CNT 0x2b17
+#define mmTC_CFG_L1_LOAD_POLICY0 0x2b1a
+#define mmTC_CFG_L1_LOAD_POLICY1 0x2b1b
+#define mmTC_CFG_L1_STORE_POLICY 0x2b1c
+#define mmTC_CFG_L2_LOAD_POLICY0 0x2b1d
+#define mmTC_CFG_L2_LOAD_POLICY1 0x2b1e
+#define mmTC_CFG_L2_STORE_POLICY0 0x2b1f
+#define mmTC_CFG_L2_STORE_POLICY1 0x2b20
+#define mmTC_CFG_L2_ATOMIC_POLICY 0x2b21
+#define mmTC_CFG_L1_VOLATILE 0x2b22
+#define mmTC_CFG_L2_VOLATILE 0x2b23
+#define mmTCP_WATCH0_ADDR_H 0x32a0
+#define mmTCP_WATCH1_ADDR_H 0x32a3
+#define mmTCP_WATCH2_ADDR_H 0x32a6
+#define mmTCP_WATCH3_ADDR_H 0x32a9
+#define mmTCP_WATCH0_ADDR_L 0x32a1
+#define mmTCP_WATCH1_ADDR_L 0x32a4
+#define mmTCP_WATCH2_ADDR_L 0x32a7
+#define mmTCP_WATCH3_ADDR_L 0x32aa
+#define mmTCP_WATCH0_CNTL 0x32a2
+#define mmTCP_WATCH1_CNTL 0x32a5
+#define mmTCP_WATCH2_CNTL 0x32a8
+#define mmTCP_WATCH3_CNTL 0x32ab
+#define mmTCP_GATCL1_CNTL 0x32b0
+#define mmTCP_ATC_EDC_GATCL1_CNT 0x32b1
+#define mmTCP_GATCL1_DSM_CNTL 0x32b2
+#define mmTCP_DSM_CNTL 0x32b3
+#define mmTCP_CNTL2 0x32b4
+#define mmTD_CGTT_CTRL 0xf09c
+#define mmTA_CGTT_CTRL 0xf09d
+#define mmCGTT_TCP_CLK_CTRL 0xf09e
+#define mmCGTT_TCI_CLK_CTRL 0xf09f
+#define mmTCI_STATUS 0x2b61
+#define mmTCI_CNTL_1 0x2b62
+#define mmTCI_CNTL_2 0x2b63
+#define mmGDS_CONFIG 0x25c0
+#define mmGDS_CNTL_STATUS 0x25c1
+#define mmGDS_ENHANCE2 0x25c2
+#define mmGDS_PROTECTION_FAULT 0x25c3
+#define mmGDS_VM_PROTECTION_FAULT 0x25c4
+#define mmGDS_EDC_CNT 0x25c5
+#define mmGDS_EDC_GRBM_CNT 0x25c6
+#define mmGDS_EDC_OA_DED 0x25c7
+#define mmGDS_DEBUG_CNTL 0x25c8
+#define mmGDS_DEBUG_DATA 0x25c9
+#define mmGDS_DSM_CNTL 0x25ca
+#define mmCGTT_GDS_CLK_CTRL 0xf0a0
+#define mmGDS_RD_ADDR 0xc400
+#define mmGDS_RD_DATA 0xc401
+#define mmGDS_RD_BURST_ADDR 0xc402
+#define mmGDS_RD_BURST_COUNT 0xc403
+#define mmGDS_RD_BURST_DATA 0xc404
+#define mmGDS_WR_ADDR 0xc405
+#define mmGDS_WR_DATA 0xc406
+#define mmGDS_WR_BURST_ADDR 0xc407
+#define mmGDS_WR_BURST_DATA 0xc408
+#define mmGDS_WRITE_COMPLETE 0xc409
+#define mmGDS_ATOM_CNTL 0xc40a
+#define mmGDS_ATOM_COMPLETE 0xc40b
+#define mmGDS_ATOM_BASE 0xc40c
+#define mmGDS_ATOM_SIZE 0xc40d
+#define mmGDS_ATOM_OFFSET0 0xc40e
+#define mmGDS_ATOM_OFFSET1 0xc40f
+#define mmGDS_ATOM_DST 0xc410
+#define mmGDS_ATOM_OP 0xc411
+#define mmGDS_ATOM_SRC0 0xc412
+#define mmGDS_ATOM_SRC0_U 0xc413
+#define mmGDS_ATOM_SRC1 0xc414
+#define mmGDS_ATOM_SRC1_U 0xc415
+#define mmGDS_ATOM_READ0 0xc416
+#define mmGDS_ATOM_READ0_U 0xc417
+#define mmGDS_ATOM_READ1 0xc418
+#define mmGDS_ATOM_READ1_U 0xc419
+#define mmGDS_GWS_RESOURCE_CNTL 0xc41a
+#define mmGDS_GWS_RESOURCE 0xc41b
+#define mmGDS_GWS_RESOURCE_CNT 0xc41c
+#define mmGDS_OA_CNTL 0xc41d
+#define mmGDS_OA_COUNTER 0xc41e
+#define mmGDS_OA_ADDRESS 0xc41f
+#define mmGDS_OA_INCDEC 0xc420
+#define mmGDS_OA_RING_SIZE 0xc421
+#define ixGDS_DEBUG_REG0 0x0
+#define ixGDS_DEBUG_REG1 0x1
+#define ixGDS_DEBUG_REG2 0x2
+#define ixGDS_DEBUG_REG3 0x3
+#define ixGDS_DEBUG_REG4 0x4
+#define ixGDS_DEBUG_REG5 0x5
+#define ixGDS_DEBUG_REG6 0x6
+#define mmGDS_PERFCOUNTER0_SELECT 0xda80
+#define mmGDS_PERFCOUNTER1_SELECT 0xda81
+#define mmGDS_PERFCOUNTER2_SELECT 0xda82
+#define mmGDS_PERFCOUNTER3_SELECT 0xda83
+#define mmGDS_PERFCOUNTER0_LO 0xd280
+#define mmGDS_PERFCOUNTER1_LO 0xd282
+#define mmGDS_PERFCOUNTER2_LO 0xd284
+#define mmGDS_PERFCOUNTER3_LO 0xd286
+#define mmGDS_PERFCOUNTER0_HI 0xd281
+#define mmGDS_PERFCOUNTER1_HI 0xd283
+#define mmGDS_PERFCOUNTER2_HI 0xd285
+#define mmGDS_PERFCOUNTER3_HI 0xd287
+#define mmGDS_PERFCOUNTER0_SELECT1 0xda84
+#define mmGDS_VMID0_BASE 0x3300
+#define mmGDS_VMID1_BASE 0x3302
+#define mmGDS_VMID2_BASE 0x3304
+#define mmGDS_VMID3_BASE 0x3306
+#define mmGDS_VMID4_BASE 0x3308
+#define mmGDS_VMID5_BASE 0x330a
+#define mmGDS_VMID6_BASE 0x330c
+#define mmGDS_VMID7_BASE 0x330e
+#define mmGDS_VMID8_BASE 0x3310
+#define mmGDS_VMID9_BASE 0x3312
+#define mmGDS_VMID10_BASE 0x3314
+#define mmGDS_VMID11_BASE 0x3316
+#define mmGDS_VMID12_BASE 0x3318
+#define mmGDS_VMID13_BASE 0x331a
+#define mmGDS_VMID14_BASE 0x331c
+#define mmGDS_VMID15_BASE 0x331e
+#define mmGDS_VMID0_SIZE 0x3301
+#define mmGDS_VMID1_SIZE 0x3303
+#define mmGDS_VMID2_SIZE 0x3305
+#define mmGDS_VMID3_SIZE 0x3307
+#define mmGDS_VMID4_SIZE 0x3309
+#define mmGDS_VMID5_SIZE 0x330b
+#define mmGDS_VMID6_SIZE 0x330d
+#define mmGDS_VMID7_SIZE 0x330f
+#define mmGDS_VMID8_SIZE 0x3311
+#define mmGDS_VMID9_SIZE 0x3313
+#define mmGDS_VMID10_SIZE 0x3315
+#define mmGDS_VMID11_SIZE 0x3317
+#define mmGDS_VMID12_SIZE 0x3319
+#define mmGDS_VMID13_SIZE 0x331b
+#define mmGDS_VMID14_SIZE 0x331d
+#define mmGDS_VMID15_SIZE 0x331f
+#define mmGDS_GWS_VMID0 0x3320
+#define mmGDS_GWS_VMID1 0x3321
+#define mmGDS_GWS_VMID2 0x3322
+#define mmGDS_GWS_VMID3 0x3323
+#define mmGDS_GWS_VMID4 0x3324
+#define mmGDS_GWS_VMID5 0x3325
+#define mmGDS_GWS_VMID6 0x3326
+#define mmGDS_GWS_VMID7 0x3327
+#define mmGDS_GWS_VMID8 0x3328
+#define mmGDS_GWS_VMID9 0x3329
+#define mmGDS_GWS_VMID10 0x332a
+#define mmGDS_GWS_VMID11 0x332b
+#define mmGDS_GWS_VMID12 0x332c
+#define mmGDS_GWS_VMID13 0x332d
+#define mmGDS_GWS_VMID14 0x332e
+#define mmGDS_GWS_VMID15 0x332f
+#define mmGDS_OA_VMID0 0x3330
+#define mmGDS_OA_VMID1 0x3331
+#define mmGDS_OA_VMID2 0x3332
+#define mmGDS_OA_VMID3 0x3333
+#define mmGDS_OA_VMID4 0x3334
+#define mmGDS_OA_VMID5 0x3335
+#define mmGDS_OA_VMID6 0x3336
+#define mmGDS_OA_VMID7 0x3337
+#define mmGDS_OA_VMID8 0x3338
+#define mmGDS_OA_VMID9 0x3339
+#define mmGDS_OA_VMID10 0x333a
+#define mmGDS_OA_VMID11 0x333b
+#define mmGDS_OA_VMID12 0x333c
+#define mmGDS_OA_VMID13 0x333d
+#define mmGDS_OA_VMID14 0x333e
+#define mmGDS_OA_VMID15 0x333f
+#define mmGDS_GWS_RESET0 0x3344
+#define mmGDS_GWS_RESET1 0x3345
+#define mmGDS_GWS_RESOURCE_RESET 0x3346
+#define mmGDS_COMPUTE_MAX_WAVE_ID 0x3348
+#define mmGDS_OA_RESET_MASK 0x3349
+#define mmGDS_OA_RESET 0x334a
+#define mmGDS_ENHANCE 0x334b
+#define mmGDS_OA_CGPG_RESTORE 0x334c
+#define mmGDS_CS_CTXSW_STATUS 0x334d
+#define mmGDS_CS_CTXSW_CNT0 0x334e
+#define mmGDS_CS_CTXSW_CNT1 0x334f
+#define mmGDS_CS_CTXSW_CNT2 0x3350
+#define mmGDS_CS_CTXSW_CNT3 0x3351
+#define mmGDS_GFX_CTXSW_STATUS 0x3352
+#define mmGDS_VS_CTXSW_CNT0 0x3353
+#define mmGDS_VS_CTXSW_CNT1 0x3354
+#define mmGDS_VS_CTXSW_CNT2 0x3355
+#define mmGDS_VS_CTXSW_CNT3 0x3356
+#define mmGDS_PS0_CTXSW_CNT0 0x3357
+#define mmGDS_PS1_CTXSW_CNT0 0x335b
+#define mmGDS_PS2_CTXSW_CNT0 0x335f
+#define mmGDS_PS3_CTXSW_CNT0 0x3363
+#define mmGDS_PS4_CTXSW_CNT0 0x3367
+#define mmGDS_PS5_CTXSW_CNT0 0x336b
+#define mmGDS_PS6_CTXSW_CNT0 0x336f
+#define mmGDS_PS7_CTXSW_CNT0 0x3373
+#define mmGDS_PS0_CTXSW_CNT1 0x3358
+#define mmGDS_PS1_CTXSW_CNT1 0x335c
+#define mmGDS_PS2_CTXSW_CNT1 0x3360
+#define mmGDS_PS3_CTXSW_CNT1 0x3364
+#define mmGDS_PS4_CTXSW_CNT1 0x3368
+#define mmGDS_PS5_CTXSW_CNT1 0x336c
+#define mmGDS_PS6_CTXSW_CNT1 0x3370
+#define mmGDS_PS7_CTXSW_CNT1 0x3374
+#define mmGDS_PS0_CTXSW_CNT2 0x3359
+#define mmGDS_PS1_CTXSW_CNT2 0x335d
+#define mmGDS_PS2_CTXSW_CNT2 0x3361
+#define mmGDS_PS3_CTXSW_CNT2 0x3365
+#define mmGDS_PS4_CTXSW_CNT2 0x3369
+#define mmGDS_PS5_CTXSW_CNT2 0x336d
+#define mmGDS_PS6_CTXSW_CNT2 0x3371
+#define mmGDS_PS7_CTXSW_CNT2 0x3375
+#define mmGDS_PS0_CTXSW_CNT3 0x335a
+#define mmGDS_PS1_CTXSW_CNT3 0x335e
+#define mmGDS_PS2_CTXSW_CNT3 0x3362
+#define mmGDS_PS3_CTXSW_CNT3 0x3366
+#define mmGDS_PS4_CTXSW_CNT3 0x336a
+#define mmGDS_PS5_CTXSW_CNT3 0x336e
+#define mmGDS_PS6_CTXSW_CNT3 0x3372
+#define mmGDS_PS7_CTXSW_CNT3 0x3376
+#define mmCS_COPY_STATE 0xa1f3
+#define mmGFX_COPY_STATE 0xa1f4
+#define mmVGT_DRAW_INITIATOR 0xa1fc
+#define mmVGT_EVENT_INITIATOR 0xa2a4
+#define mmVGT_EVENT_ADDRESS_REG 0xa1fe
+#define mmVGT_DMA_BASE_HI 0xa1f9
+#define mmVGT_DMA_BASE 0xa1fa
+#define mmVGT_DMA_INDEX_TYPE 0xa29f
+#define mmVGT_DMA_NUM_INSTANCES 0xa2a2
+#define mmIA_ENHANCE 0xa29c
+#define mmVGT_DMA_SIZE 0xa29d
+#define mmVGT_DMA_MAX_SIZE 0xa29e
+#define mmVGT_DMA_PRIMITIVE_TYPE 0x2271
+#define mmVGT_DMA_CONTROL 0x2272
+#define mmVGT_IMMED_DATA 0xa1fd
+#define mmVGT_INDEX_TYPE 0xc243
+#define mmVGT_NUM_INDICES 0xc24c
+#define mmVGT_NUM_INSTANCES 0xc24d
+#define mmVGT_PRIMITIVE_TYPE 0xc242
+#define mmVGT_PRIMITIVEID_EN 0xa2a1
+#define mmVGT_PRIMITIVEID_RESET 0xa2a3
+#define mmVGT_VTX_CNT_EN 0xa2ae
+#define mmVGT_REUSE_OFF 0xa2ad
+#define mmVGT_INSTANCE_STEP_RATE_0 0xa2a8
+#define mmVGT_INSTANCE_STEP_RATE_1 0xa2a9
+#define mmVGT_MAX_VTX_INDX 0xa100
+#define mmVGT_MIN_VTX_INDX 0xa101
+#define mmVGT_INDX_OFFSET 0xa102
+#define mmVGT_VERTEX_REUSE_BLOCK_CNTL 0xa316
+#define mmVGT_OUT_DEALLOC_CNTL 0xa317
+#define mmVGT_MULTI_PRIM_IB_RESET_INDX 0xa103
+#define mmVGT_MULTI_PRIM_IB_RESET_EN 0xa2a5
+#define mmVGT_ENHANCE 0xa294
+#define mmVGT_OUTPUT_PATH_CNTL 0xa284
+#define mmVGT_HOS_CNTL 0xa285
+#define mmVGT_HOS_MAX_TESS_LEVEL 0xa286
+#define mmVGT_HOS_MIN_TESS_LEVEL 0xa287
+#define mmVGT_HOS_REUSE_DEPTH 0xa288
+#define mmVGT_GROUP_PRIM_TYPE 0xa289
+#define mmVGT_GROUP_FIRST_DECR 0xa28a
+#define mmVGT_GROUP_DECR 0xa28b
+#define mmVGT_GROUP_VECT_0_CNTL 0xa28c
+#define mmVGT_GROUP_VECT_1_CNTL 0xa28d
+#define mmVGT_GROUP_VECT_0_FMT_CNTL 0xa28e
+#define mmVGT_GROUP_VECT_1_FMT_CNTL 0xa28f
+#define mmVGT_VTX_VECT_EJECT_REG 0x222c
+#define mmVGT_DMA_DATA_FIFO_DEPTH 0x222d
+#define mmVGT_DMA_REQ_FIFO_DEPTH 0x222e
+#define mmVGT_DRAW_INIT_FIFO_DEPTH 0x222f
+#define mmVGT_LAST_COPY_STATE 0x2230
+#define mmCC_GC_SHADER_ARRAY_CONFIG 0x226f
+#define mmGC_USER_SHADER_ARRAY_CONFIG 0x2270
+#define mmVGT_GS_MODE 0xa290
+#define mmVGT_GS_ONCHIP_CNTL 0xa291
+#define mmVGT_GS_OUT_PRIM_TYPE 0xa29b
+#define mmVGT_CACHE_INVALIDATION 0x2231
+#define mmVGT_RESET_DEBUG 0x2232
+#define mmVGT_STRMOUT_DELAY 0x2233
+#define mmVGT_FIFO_DEPTHS 0x2234
+#define mmVGT_GS_PER_ES 0xa295
+#define mmVGT_ES_PER_GS 0xa296
+#define mmVGT_GS_PER_VS 0xa297
+#define mmVGT_GS_VERTEX_REUSE 0x2235
+#define mmVGT_MC_LAT_CNTL 0x2236
+#define mmIA_CNTL_STATUS 0x2237
+#define mmVGT_STRMOUT_CONFIG 0xa2e5
+#define mmVGT_STRMOUT_BUFFER_SIZE_0 0xa2b4
+#define mmVGT_STRMOUT_BUFFER_SIZE_1 0xa2b8
+#define mmVGT_STRMOUT_BUFFER_SIZE_2 0xa2bc
+#define mmVGT_STRMOUT_BUFFER_SIZE_3 0xa2c0
+#define mmVGT_STRMOUT_BUFFER_OFFSET_0 0xa2b7
+#define mmVGT_STRMOUT_BUFFER_OFFSET_1 0xa2bb
+#define mmVGT_STRMOUT_BUFFER_OFFSET_2 0xa2bf
+#define mmVGT_STRMOUT_BUFFER_OFFSET_3 0xa2c3
+#define mmVGT_STRMOUT_VTX_STRIDE_0 0xa2b5
+#define mmVGT_STRMOUT_VTX_STRIDE_1 0xa2b9
+#define mmVGT_STRMOUT_VTX_STRIDE_2 0xa2bd
+#define mmVGT_STRMOUT_VTX_STRIDE_3 0xa2c1
+#define mmVGT_STRMOUT_BUFFER_CONFIG 0xa2e6
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_0 0xc244
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_1 0xc245
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_2 0xc246
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_3 0xc247
+#define mmVGT_STRMOUT_DRAW_OPAQUE_OFFSET 0xa2ca
+#define mmVGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE 0xa2cb
+#define mmVGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0xa2cc
+#define mmVGT_GS_MAX_VERT_OUT 0xa2ce
+#define mmVGT_SHADER_STAGES_EN 0xa2d5
+#define mmVGT_DISPATCH_DRAW_INDEX 0xa2dd
+#define mmVGT_LS_HS_CONFIG 0xa2d6
+#define mmVGT_DMA_LS_HS_CONFIG 0x2273
+#define mmVGT_TF_PARAM 0xa2db
+#define mmVGT_TESS_DISTRIBUTION 0xa2d4
+#define mmVGT_TF_RING_SIZE 0xc24e
+#define mmVGT_SYS_CONFIG 0x2263
+#define mmVGT_HS_OFFCHIP_PARAM 0xc24f
+#define mmVGT_TF_MEMORY_BASE 0xc250
+#define mmVGT_GS_INSTANCE_CNT 0xa2e4
+#define mmIA_MULTI_VGT_PARAM 0xa2aa
+#define mmVGT_VS_MAX_WAVE_ID 0x2268
+#define mmVGT_ESGS_RING_SIZE 0xc240
+#define mmVGT_GSVS_RING_SIZE 0xc241
+#define mmVGT_GSVS_RING_OFFSET_1 0xa298
+#define mmVGT_GSVS_RING_OFFSET_2 0xa299
+#define mmVGT_GSVS_RING_OFFSET_3 0xa29a
+#define mmVGT_ESGS_RING_ITEMSIZE 0xa2ab
+#define mmVGT_GSVS_RING_ITEMSIZE 0xa2ac
+#define mmVGT_GS_VERT_ITEMSIZE 0xa2d7
+#define mmVGT_GS_VERT_ITEMSIZE_1 0xa2d8
+#define mmVGT_GS_VERT_ITEMSIZE_2 0xa2d9
+#define mmVGT_GS_VERT_ITEMSIZE_3 0xa2da
+#define mmWD_CNTL_STATUS 0x223f
+#define mmWD_ENHANCE 0xa2a0
+#define mmGFX_PIPE_CONTROL 0x226d
+#define mmCGTT_VGT_CLK_CTRL 0xf084
+#define mmCGTT_IA_CLK_CTRL 0xf085
+#define mmCGTT_WD_CLK_CTRL 0xf086
+#define mmVGT_DEBUG_CNTL 0x2238
+#define mmVGT_DEBUG_DATA 0x2239
+#define mmIA_DEBUG_CNTL 0x223a
+#define mmIA_DEBUG_DATA 0x223b
+#define mmVGT_CNTL_STATUS 0x223c
+#define mmWD_DEBUG_CNTL 0x223d
+#define mmWD_DEBUG_DATA 0x223e
+#define mmWD_QOS 0x2242
+#define mmCC_GC_PRIM_CONFIG 0x2240
+#define mmGC_USER_PRIM_CONFIG 0x2241
+#define ixWD_DEBUG_REG0 0x0
+#define ixWD_DEBUG_REG1 0x1
+#define ixWD_DEBUG_REG2 0x2
+#define ixWD_DEBUG_REG3 0x3
+#define ixWD_DEBUG_REG4 0x4
+#define ixWD_DEBUG_REG5 0x5
+#define ixWD_DEBUG_REG6 0x6
+#define ixWD_DEBUG_REG7 0x7
+#define ixWD_DEBUG_REG8 0x8
+#define ixWD_DEBUG_REG9 0x9
+#define ixWD_DEBUG_REG10 0xa
+#define ixIA_DEBUG_REG0 0x0
+#define ixIA_DEBUG_REG1 0x1
+#define ixIA_DEBUG_REG2 0x2
+#define ixIA_DEBUG_REG3 0x3
+#define ixIA_DEBUG_REG4 0x4
+#define ixIA_DEBUG_REG5 0x5
+#define ixIA_DEBUG_REG6 0x6
+#define ixIA_DEBUG_REG7 0x7
+#define ixIA_DEBUG_REG8 0x8
+#define ixIA_DEBUG_REG9 0x9
+#define ixVGT_DEBUG_REG0 0x0
+#define ixVGT_DEBUG_REG1 0x1
+#define ixVGT_DEBUG_REG2 0x1e
+#define ixVGT_DEBUG_REG3 0x1f
+#define ixVGT_DEBUG_REG4 0x20
+#define ixVGT_DEBUG_REG5 0x21
+#define ixVGT_DEBUG_REG6 0x22
+#define ixVGT_DEBUG_REG7 0x23
+#define ixVGT_DEBUG_REG8 0x8
+#define ixVGT_DEBUG_REG9 0x9
+#define ixVGT_DEBUG_REG10 0xa
+#define ixVGT_DEBUG_REG11 0xb
+#define ixVGT_DEBUG_REG12 0xc
+#define ixVGT_DEBUG_REG13 0xd
+#define ixVGT_DEBUG_REG14 0xe
+#define ixVGT_DEBUG_REG15 0xf
+#define ixVGT_DEBUG_REG16 0x10
+#define ixVGT_DEBUG_REG17 0x11
+#define ixVGT_DEBUG_REG18 0x7
+#define ixVGT_DEBUG_REG19 0x13
+#define ixVGT_DEBUG_REG20 0x14
+#define ixVGT_DEBUG_REG21 0x15
+#define ixVGT_DEBUG_REG22 0x16
+#define ixVGT_DEBUG_REG23 0x17
+#define ixVGT_DEBUG_REG24 0x18
+#define ixVGT_DEBUG_REG25 0x19
+#define ixVGT_DEBUG_REG26 0x24
+#define ixVGT_DEBUG_REG27 0x1b
+#define ixVGT_DEBUG_REG28 0x1c
+#define ixVGT_DEBUG_REG29 0x1d
+#define ixVGT_DEBUG_REG31 0x26
+#define ixVGT_DEBUG_REG32 0x27
+#define ixVGT_DEBUG_REG33 0x28
+#define ixVGT_DEBUG_REG34 0x29
+#define ixVGT_DEBUG_REG36 0x2b
+#define mmVGT_PERFCOUNTER_SEID_MASK 0xd894
+#define mmVGT_PERFCOUNTER0_SELECT 0xd88c
+#define mmVGT_PERFCOUNTER1_SELECT 0xd88d
+#define mmVGT_PERFCOUNTER2_SELECT 0xd88e
+#define mmVGT_PERFCOUNTER3_SELECT 0xd88f
+#define mmVGT_PERFCOUNTER0_SELECT1 0xd890
+#define mmVGT_PERFCOUNTER1_SELECT1 0xd891
+#define mmVGT_PERFCOUNTER0_LO 0xd090
+#define mmVGT_PERFCOUNTER1_LO 0xd092
+#define mmVGT_PERFCOUNTER2_LO 0xd094
+#define mmVGT_PERFCOUNTER3_LO 0xd096
+#define mmVGT_PERFCOUNTER0_HI 0xd091
+#define mmVGT_PERFCOUNTER1_HI 0xd093
+#define mmVGT_PERFCOUNTER2_HI 0xd095
+#define mmVGT_PERFCOUNTER3_HI 0xd097
+#define mmIA_PERFCOUNTER0_SELECT 0xd884
+#define mmIA_PERFCOUNTER1_SELECT 0xd885
+#define mmIA_PERFCOUNTER2_SELECT 0xd886
+#define mmIA_PERFCOUNTER3_SELECT 0xd887
+#define mmIA_PERFCOUNTER0_SELECT1 0xd888
+#define mmIA_PERFCOUNTER0_LO 0xd088
+#define mmIA_PERFCOUNTER1_LO 0xd08a
+#define mmIA_PERFCOUNTER2_LO 0xd08c
+#define mmIA_PERFCOUNTER3_LO 0xd08e
+#define mmIA_PERFCOUNTER0_HI 0xd089
+#define mmIA_PERFCOUNTER1_HI 0xd08b
+#define mmIA_PERFCOUNTER2_HI 0xd08d
+#define mmIA_PERFCOUNTER3_HI 0xd08f
+#define mmWD_PERFCOUNTER0_SELECT 0xd880
+#define mmWD_PERFCOUNTER1_SELECT 0xd881
+#define mmWD_PERFCOUNTER2_SELECT 0xd882
+#define mmWD_PERFCOUNTER3_SELECT 0xd883
+#define mmWD_PERFCOUNTER0_LO 0xd080
+#define mmWD_PERFCOUNTER1_LO 0xd082
+#define mmWD_PERFCOUNTER2_LO 0xd084
+#define mmWD_PERFCOUNTER3_LO 0xd086
+#define mmWD_PERFCOUNTER0_HI 0xd081
+#define mmWD_PERFCOUNTER1_HI 0xd083
+#define mmWD_PERFCOUNTER2_HI 0xd085
+#define mmWD_PERFCOUNTER3_HI 0xd087
+#define mmDIDT_IND_INDEX 0x3280
+#define mmDIDT_IND_DATA 0x3281
+#define ixDIDT_SQ_CTRL0 0x0
+#define ixDIDT_SQ_CTRL1 0x1
+#define ixDIDT_SQ_CTRL2 0x2
+#define ixDIDT_SQ_CTRL_OCP 0x3
+#define ixDIDT_SQ_WEIGHT0_3 0x10
+#define ixDIDT_SQ_WEIGHT4_7 0x11
+#define ixDIDT_SQ_WEIGHT8_11 0x12
+#define ixDIDT_DB_CTRL0 0x20
+#define ixDIDT_DB_CTRL1 0x21
+#define ixDIDT_DB_CTRL2 0x22
+#define ixDIDT_DB_CTRL_OCP 0x23
+#define ixDIDT_DB_WEIGHT0_3 0x30
+#define ixDIDT_DB_WEIGHT4_7 0x31
+#define ixDIDT_DB_WEIGHT8_11 0x32
+#define ixDIDT_TD_CTRL0 0x40
+#define ixDIDT_TD_CTRL1 0x41
+#define ixDIDT_TD_CTRL2 0x42
+#define ixDIDT_TD_CTRL_OCP 0x43
+#define ixDIDT_TD_WEIGHT0_3 0x50
+#define ixDIDT_TD_WEIGHT4_7 0x51
+#define ixDIDT_TD_WEIGHT8_11 0x52
+#define ixDIDT_TCP_CTRL0 0x60
+#define ixDIDT_TCP_CTRL1 0x61
+#define ixDIDT_TCP_CTRL2 0x62
+#define ixDIDT_TCP_CTRL_OCP 0x63
+#define ixDIDT_TCP_WEIGHT0_3 0x70
+#define ixDIDT_TCP_WEIGHT4_7 0x71
+#define ixDIDT_TCP_WEIGHT8_11 0x72
+#define ixDIDT_DBR_CTRL0 0x80
+#define ixDIDT_DBR_CTRL1 0x81
+#define ixDIDT_DBR_CTRL2 0x82
+#define ixDIDT_DBR_CTRL_OCP 0x83
+#define ixDIDT_DBR_WEIGHT0_3 0x90
+#define ixDIDT_DBR_WEIGHT4_7 0x91
+#define ixDIDT_DBR_WEIGHT8_11 0x92
+
+#endif /* GFX_8_1_D_H */
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_enum.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_enum.h
new file mode 100644
index 000000000000..f9022097fbe9
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_enum.h
@@ -0,0 +1,6808 @@
+/*
+ * GFX_8_1 Register documentation
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) 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.
+ */
+
+#ifndef GFX_8_1_ENUM_H
+#define GFX_8_1_ENUM_H
+
+typedef enum SurfaceNumber {
+ NUMBER_UNORM = 0x0,
+ NUMBER_SNORM = 0x1,
+ NUMBER_USCALED = 0x2,
+ NUMBER_SSCALED = 0x3,
+ NUMBER_UINT = 0x4,
+ NUMBER_SINT = 0x5,
+ NUMBER_SRGB = 0x6,
+ NUMBER_FLOAT = 0x7,
+} SurfaceNumber;
+typedef enum SurfaceSwap {
+ SWAP_STD = 0x0,
+ SWAP_ALT = 0x1,
+ SWAP_STD_REV = 0x2,
+ SWAP_ALT_REV = 0x3,
+} SurfaceSwap;
+typedef enum CBMode {
+ CB_DISABLE = 0x0,
+ CB_NORMAL = 0x1,
+ CB_ELIMINATE_FAST_CLEAR = 0x2,
+ CB_RESOLVE = 0x3,
+ CB_DECOMPRESS = 0x4,
+ CB_FMASK_DECOMPRESS = 0x5,
+ CB_DCC_DECOMPRESS = 0x6,
+} CBMode;
+typedef enum RoundMode {
+ ROUND_BY_HALF = 0x0,
+ ROUND_TRUNCATE = 0x1,
+} RoundMode;
+typedef enum SourceFormat {
+ EXPORT_4C_32BPC = 0x0,
+ EXPORT_4C_16BPC = 0x1,
+ EXPORT_2C_32BPC_GR = 0x2,
+ EXPORT_2C_32BPC_AR = 0x3,
+} SourceFormat;
+typedef enum BlendOp {
+ BLEND_ZERO = 0x0,
+ BLEND_ONE = 0x1,
+ BLEND_SRC_COLOR = 0x2,
+ BLEND_ONE_MINUS_SRC_COLOR = 0x3,
+ BLEND_SRC_ALPHA = 0x4,
+ BLEND_ONE_MINUS_SRC_ALPHA = 0x5,
+ BLEND_DST_ALPHA = 0x6,
+ BLEND_ONE_MINUS_DST_ALPHA = 0x7,
+ BLEND_DST_COLOR = 0x8,
+ BLEND_ONE_MINUS_DST_COLOR = 0x9,
+ BLEND_SRC_ALPHA_SATURATE = 0xa,
+ BLEND_BOTH_SRC_ALPHA = 0xb,
+ BLEND_BOTH_INV_SRC_ALPHA = 0xc,
+ BLEND_CONSTANT_COLOR = 0xd,
+ BLEND_ONE_MINUS_CONSTANT_COLOR = 0xe,
+ BLEND_SRC1_COLOR = 0xf,
+ BLEND_INV_SRC1_COLOR = 0x10,
+ BLEND_SRC1_ALPHA = 0x11,
+ BLEND_INV_SRC1_ALPHA = 0x12,
+ BLEND_CONSTANT_ALPHA = 0x13,
+ BLEND_ONE_MINUS_CONSTANT_ALPHA = 0x14,
+} BlendOp;
+typedef enum CombFunc {
+ COMB_DST_PLUS_SRC = 0x0,
+ COMB_SRC_MINUS_DST = 0x1,
+ COMB_MIN_DST_SRC = 0x2,
+ COMB_MAX_DST_SRC = 0x3,
+ COMB_DST_MINUS_SRC = 0x4,
+} CombFunc;
+typedef enum BlendOpt {
+ FORCE_OPT_AUTO = 0x0,
+ FORCE_OPT_DISABLE = 0x1,
+ FORCE_OPT_ENABLE_IF_SRC_A_0 = 0x2,
+ FORCE_OPT_ENABLE_IF_SRC_RGB_0 = 0x3,
+ FORCE_OPT_ENABLE_IF_SRC_ARGB_0 = 0x4,
+ FORCE_OPT_ENABLE_IF_SRC_A_1 = 0x5,
+ FORCE_OPT_ENABLE_IF_SRC_RGB_1 = 0x6,
+ FORCE_OPT_ENABLE_IF_SRC_ARGB_1 = 0x7,
+} BlendOpt;
+typedef enum CmaskCode {
+ CMASK_CLR00_F0 = 0x0,
+ CMASK_CLR00_F1 = 0x1,
+ CMASK_CLR00_F2 = 0x2,
+ CMASK_CLR00_FX = 0x3,
+ CMASK_CLR01_F0 = 0x4,
+ CMASK_CLR01_F1 = 0x5,
+ CMASK_CLR01_F2 = 0x6,
+ CMASK_CLR01_FX = 0x7,
+ CMASK_CLR10_F0 = 0x8,
+ CMASK_CLR10_F1 = 0x9,
+ CMASK_CLR10_F2 = 0xa,
+ CMASK_CLR10_FX = 0xb,
+ CMASK_CLR11_F0 = 0xc,
+ CMASK_CLR11_F1 = 0xd,
+ CMASK_CLR11_F2 = 0xe,
+ CMASK_CLR11_FX = 0xf,
+} CmaskCode;
+typedef enum CmaskAddr {
+ CMASK_ADDR_TILED = 0x0,
+ CMASK_ADDR_LINEAR = 0x1,
+ CMASK_ADDR_COMPATIBLE = 0x2,
+} CmaskAddr;
+typedef enum CBPerfSel {
+ CB_PERF_SEL_NONE = 0x0,
+ CB_PERF_SEL_BUSY = 0x1,
+ CB_PERF_SEL_CORE_SCLK_VLD = 0x2,
+ CB_PERF_SEL_REG_SCLK0_VLD = 0x3,
+ CB_PERF_SEL_REG_SCLK1_VLD = 0x4,
+ CB_PERF_SEL_DRAWN_QUAD = 0x5,
+ CB_PERF_SEL_DRAWN_PIXEL = 0x6,
+ CB_PERF_SEL_DRAWN_QUAD_FRAGMENT = 0x7,
+ CB_PERF_SEL_DRAWN_TILE = 0x8,
+ CB_PERF_SEL_DB_CB_TILE_VALID_READY = 0x9,
+ CB_PERF_SEL_DB_CB_TILE_VALID_READYB = 0xa,
+ CB_PERF_SEL_DB_CB_TILE_VALIDB_READY = 0xb,
+ CB_PERF_SEL_DB_CB_TILE_VALIDB_READYB = 0xc,
+ CB_PERF_SEL_CM_FC_TILE_VALID_READY = 0xd,
+ CB_PERF_SEL_CM_FC_TILE_VALID_READYB = 0xe,
+ CB_PERF_SEL_CM_FC_TILE_VALIDB_READY = 0xf,
+ CB_PERF_SEL_CM_FC_TILE_VALIDB_READYB = 0x10,
+ CB_PERF_SEL_MERGE_TILE_ONLY_VALID_READY = 0x11,
+ CB_PERF_SEL_MERGE_TILE_ONLY_VALID_READYB = 0x12,
+ CB_PERF_SEL_DB_CB_LQUAD_VALID_READY = 0x13,
+ CB_PERF_SEL_DB_CB_LQUAD_VALID_READYB = 0x14,
+ CB_PERF_SEL_DB_CB_LQUAD_VALIDB_READY = 0x15,
+ CB_PERF_SEL_DB_CB_LQUAD_VALIDB_READYB = 0x16,
+ CB_PERF_SEL_LQUAD_NO_TILE = 0x17,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_32_R = 0x18,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_32_AR = 0x19,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_32_GR = 0x1a,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_32_ABGR = 0x1b,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_FP16_ABGR = 0x1c,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_SIGNED16_ABGR = 0x1d,
+ CB_PERF_SEL_LQUAD_FORMAT_IS_EXPORT_UNSIGNED16_ABGR= 0x1e,
+ CB_PERF_SEL_QUAD_KILLED_BY_EXTRA_PIXEL_EXPORT = 0x1f,
+ CB_PERF_SEL_QUAD_KILLED_BY_COLOR_INVALID = 0x20,
+ CB_PERF_SEL_QUAD_KILLED_BY_NULL_TARGET_SHADER_MASK= 0x21,
+ CB_PERF_SEL_QUAD_KILLED_BY_NULL_SAMPLE_MASK = 0x22,
+ CB_PERF_SEL_QUAD_KILLED_BY_DISCARD_PIXEL = 0x23,
+ CB_PERF_SEL_FC_CLEAR_QUAD_VALID_READY = 0x24,
+ CB_PERF_SEL_FC_CLEAR_QUAD_VALID_READYB = 0x25,
+ CB_PERF_SEL_FC_CLEAR_QUAD_VALIDB_READY = 0x26,
+ CB_PERF_SEL_FC_CLEAR_QUAD_VALIDB_READYB = 0x27,
+ CB_PERF_SEL_FOP_IN_VALID_READY = 0x28,
+ CB_PERF_SEL_FOP_IN_VALID_READYB = 0x29,
+ CB_PERF_SEL_FOP_IN_VALIDB_READY = 0x2a,
+ CB_PERF_SEL_FOP_IN_VALIDB_READYB = 0x2b,
+ CB_PERF_SEL_FC_CC_QUADFRAG_VALID_READY = 0x2c,
+ CB_PERF_SEL_FC_CC_QUADFRAG_VALID_READYB = 0x2d,
+ CB_PERF_SEL_FC_CC_QUADFRAG_VALIDB_READY = 0x2e,
+ CB_PERF_SEL_FC_CC_QUADFRAG_VALIDB_READYB = 0x2f,
+ CB_PERF_SEL_CC_IB_SR_FRAG_VALID_READY = 0x30,
+ CB_PERF_SEL_CC_IB_SR_FRAG_VALID_READYB = 0x31,
+ CB_PERF_SEL_CC_IB_SR_FRAG_VALIDB_READY = 0x32,
+ CB_PERF_SEL_CC_IB_SR_FRAG_VALIDB_READYB = 0x33,
+ CB_PERF_SEL_CC_IB_TB_FRAG_VALID_READY = 0x34,
+ CB_PERF_SEL_CC_IB_TB_FRAG_VALID_READYB = 0x35,
+ CB_PERF_SEL_CC_IB_TB_FRAG_VALIDB_READY = 0x36,
+ CB_PERF_SEL_CC_IB_TB_FRAG_VALIDB_READYB = 0x37,
+ CB_PERF_SEL_CC_RB_BC_EVENFRAG_VALID_READY = 0x38,
+ CB_PERF_SEL_CC_RB_BC_EVENFRAG_VALID_READYB = 0x39,
+ CB_PERF_SEL_CC_RB_BC_EVENFRAG_VALIDB_READY = 0x3a,
+ CB_PERF_SEL_CC_RB_BC_EVENFRAG_VALIDB_READYB = 0x3b,
+ CB_PERF_SEL_CC_RB_BC_ODDFRAG_VALID_READY = 0x3c,
+ CB_PERF_SEL_CC_RB_BC_ODDFRAG_VALID_READYB = 0x3d,
+ CB_PERF_SEL_CC_RB_BC_ODDFRAG_VALIDB_READY = 0x3e,
+ CB_PERF_SEL_CC_RB_BC_ODDFRAG_VALIDB_READYB = 0x3f,
+ CB_PERF_SEL_CC_BC_CS_FRAG_VALID = 0x40,
+ CB_PERF_SEL_CM_CACHE_HIT = 0x41,
+ CB_PERF_SEL_CM_CACHE_TAG_MISS = 0x42,
+ CB_PERF_SEL_CM_CACHE_SECTOR_MISS = 0x43,
+ CB_PERF_SEL_CM_CACHE_REEVICTION_STALL = 0x44,
+ CB_PERF_SEL_CM_CACHE_EVICT_NONZERO_INFLIGHT_STALL= 0x45,
+ CB_PERF_SEL_CM_CACHE_REPLACE_PENDING_EVICT_STALL = 0x46,
+ CB_PERF_SEL_CM_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL= 0x47,
+ CB_PERF_SEL_CM_CACHE_READ_OUTPUT_STALL = 0x48,
+ CB_PERF_SEL_CM_CACHE_WRITE_OUTPUT_STALL = 0x49,
+ CB_PERF_SEL_CM_CACHE_ACK_OUTPUT_STALL = 0x4a,
+ CB_PERF_SEL_CM_CACHE_STALL = 0x4b,
+ CB_PERF_SEL_CM_CACHE_FLUSH = 0x4c,
+ CB_PERF_SEL_CM_CACHE_TAGS_FLUSHED = 0x4d,
+ CB_PERF_SEL_CM_CACHE_SECTORS_FLUSHED = 0x4e,
+ CB_PERF_SEL_CM_CACHE_DIRTY_SECTORS_FLUSHED = 0x4f,
+ CB_PERF_SEL_FC_CACHE_HIT = 0x50,
+ CB_PERF_SEL_FC_CACHE_TAG_MISS = 0x51,
+ CB_PERF_SEL_FC_CACHE_SECTOR_MISS = 0x52,
+ CB_PERF_SEL_FC_CACHE_REEVICTION_STALL = 0x53,
+ CB_PERF_SEL_FC_CACHE_EVICT_NONZERO_INFLIGHT_STALL= 0x54,
+ CB_PERF_SEL_FC_CACHE_REPLACE_PENDING_EVICT_STALL = 0x55,
+ CB_PERF_SEL_FC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL= 0x56,
+ CB_PERF_SEL_FC_CACHE_READ_OUTPUT_STALL = 0x57,
+ CB_PERF_SEL_FC_CACHE_WRITE_OUTPUT_STALL = 0x58,
+ CB_PERF_SEL_FC_CACHE_ACK_OUTPUT_STALL = 0x59,
+ CB_PERF_SEL_FC_CACHE_STALL = 0x5a,
+ CB_PERF_SEL_FC_CACHE_FLUSH = 0x5b,
+ CB_PERF_SEL_FC_CACHE_TAGS_FLUSHED = 0x5c,
+ CB_PERF_SEL_FC_CACHE_SECTORS_FLUSHED = 0x5d,
+ CB_PERF_SEL_FC_CACHE_DIRTY_SECTORS_FLUSHED = 0x5e,
+ CB_PERF_SEL_CC_CACHE_HIT = 0x5f,
+ CB_PERF_SEL_CC_CACHE_TAG_MISS = 0x60,
+ CB_PERF_SEL_CC_CACHE_SECTOR_MISS = 0x61,
+ CB_PERF_SEL_CC_CACHE_REEVICTION_STALL = 0x62,
+ CB_PERF_SEL_CC_CACHE_EVICT_NONZERO_INFLIGHT_STALL= 0x63,
+ CB_PERF_SEL_CC_CACHE_REPLACE_PENDING_EVICT_STALL = 0x64,
+ CB_PERF_SEL_CC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL= 0x65,
+ CB_PERF_SEL_CC_CACHE_READ_OUTPUT_STALL = 0x66,
+ CB_PERF_SEL_CC_CACHE_WRITE_OUTPUT_STALL = 0x67,
+ CB_PERF_SEL_CC_CACHE_ACK_OUTPUT_STALL = 0x68,
+ CB_PERF_SEL_CC_CACHE_STALL = 0x69,
+ CB_PERF_SEL_CC_CACHE_FLUSH = 0x6a,
+ CB_PERF_SEL_CC_CACHE_TAGS_FLUSHED = 0x6b,
+ CB_PERF_SEL_CC_CACHE_SECTORS_FLUSHED = 0x6c,
+ CB_PERF_SEL_CC_CACHE_DIRTY_SECTORS_FLUSHED = 0x6d,
+ CB_PERF_SEL_CC_CACHE_WA_TO_RMW_CONVERSION = 0x6e,
+ CB_PERF_SEL_CC_CACHE_READS_SAVED_DUE_TO_DCC = 0x6f,
+ CB_PERF_SEL_CB_TAP_WRREQ_VALID_READY = 0x70,
+ CB_PERF_SEL_CB_TAP_WRREQ_VALID_READYB = 0x71,
+ CB_PERF_SEL_CB_TAP_WRREQ_VALIDB_READY = 0x72,
+ CB_PERF_SEL_CB_TAP_WRREQ_VALIDB_READYB = 0x73,
+ CB_PERF_SEL_CM_MC_WRITE_REQUEST = 0x74,
+ CB_PERF_SEL_FC_MC_WRITE_REQUEST = 0x75,
+ CB_PERF_SEL_CC_MC_WRITE_REQUEST = 0x76,
+ CB_PERF_SEL_CM_MC_WRITE_REQUESTS_IN_FLIGHT = 0x77,
+ CB_PERF_SEL_FC_MC_WRITE_REQUESTS_IN_FLIGHT = 0x78,
+ CB_PERF_SEL_CC_MC_WRITE_REQUESTS_IN_FLIGHT = 0x79,
+ CB_PERF_SEL_CB_TAP_RDREQ_VALID_READY = 0x7a,
+ CB_PERF_SEL_CB_TAP_RDREQ_VALID_READYB = 0x7b,
+ CB_PERF_SEL_CB_TAP_RDREQ_VALIDB_READY = 0x7c,
+ CB_PERF_SEL_CB_TAP_RDREQ_VALIDB_READYB = 0x7d,
+ CB_PERF_SEL_CM_MC_READ_REQUEST = 0x7e,
+ CB_PERF_SEL_FC_MC_READ_REQUEST = 0x7f,
+ CB_PERF_SEL_CC_MC_READ_REQUEST = 0x80,
+ CB_PERF_SEL_CM_MC_READ_REQUESTS_IN_FLIGHT = 0x81,
+ CB_PERF_SEL_FC_MC_READ_REQUESTS_IN_FLIGHT = 0x82,
+ CB_PERF_SEL_CC_MC_READ_REQUESTS_IN_FLIGHT = 0x83,
+ CB_PERF_SEL_CM_TQ_FULL = 0x84,
+ CB_PERF_SEL_CM_TQ_FIFO_TILE_RESIDENCY_STALL = 0x85,
+ CB_PERF_SEL_FC_QUAD_RDLAT_FIFO_FULL = 0x86,
+ CB_PERF_SEL_FC_TILE_RDLAT_FIFO_FULL = 0x87,
+ CB_PERF_SEL_FC_RDLAT_FIFO_QUAD_RESIDENCY_STALL = 0x88,
+ CB_PERF_SEL_FOP_FMASK_RAW_STALL = 0x89,
+ CB_PERF_SEL_FOP_FMASK_BYPASS_STALL = 0x8a,
+ CB_PERF_SEL_CC_SF_FULL = 0x8b,
+ CB_PERF_SEL_CC_RB_FULL = 0x8c,
+ CB_PERF_SEL_CC_EVENFIFO_QUAD_RESIDENCY_STALL = 0x8d,
+ CB_PERF_SEL_CC_ODDFIFO_QUAD_RESIDENCY_STALL = 0x8e,
+ CB_PERF_SEL_BLENDER_RAW_HAZARD_STALL = 0x8f,
+ CB_PERF_SEL_EVENT = 0x90,
+ CB_PERF_SEL_EVENT_CACHE_FLUSH_TS = 0x91,
+ CB_PERF_SEL_EVENT_CONTEXT_DONE = 0x92,
+ CB_PERF_SEL_EVENT_CACHE_FLUSH = 0x93,
+ CB_PERF_SEL_EVENT_CACHE_FLUSH_AND_INV_TS_EVENT = 0x94,
+ CB_PERF_SEL_EVENT_CACHE_FLUSH_AND_INV_EVENT = 0x95,
+ CB_PERF_SEL_EVENT_FLUSH_AND_INV_CB_DATA_TS = 0x96,
+ CB_PERF_SEL_EVENT_FLUSH_AND_INV_CB_META = 0x97,
+ CB_PERF_SEL_CC_SURFACE_SYNC = 0x98,
+ CB_PERF_SEL_CMASK_READ_DATA_0xC = 0x99,
+ CB_PERF_SEL_CMASK_READ_DATA_0xD = 0x9a,
+ CB_PERF_SEL_CMASK_READ_DATA_0xE = 0x9b,
+ CB_PERF_SEL_CMASK_READ_DATA_0xF = 0x9c,
+ CB_PERF_SEL_CMASK_WRITE_DATA_0xC = 0x9d,
+ CB_PERF_SEL_CMASK_WRITE_DATA_0xD = 0x9e,
+ CB_PERF_SEL_CMASK_WRITE_DATA_0xE = 0x9f,
+ CB_PERF_SEL_CMASK_WRITE_DATA_0xF = 0xa0,
+ CB_PERF_SEL_TWO_PROBE_QUAD_FRAGMENT = 0xa1,
+ CB_PERF_SEL_EXPORT_32_ABGR_QUAD_FRAGMENT = 0xa2,
+ CB_PERF_SEL_DUAL_SOURCE_COLOR_QUAD_FRAGMENT = 0xa3,
+ CB_PERF_SEL_QUAD_HAS_1_FRAGMENT_BEFORE_UPDATE = 0xa4,
+ CB_PERF_SEL_QUAD_HAS_2_FRAGMENTS_BEFORE_UPDATE = 0xa5,
+ CB_PERF_SEL_QUAD_HAS_3_FRAGMENTS_BEFORE_UPDATE = 0xa6,
+ CB_PERF_SEL_QUAD_HAS_4_FRAGMENTS_BEFORE_UPDATE = 0xa7,
+ CB_PERF_SEL_QUAD_HAS_5_FRAGMENTS_BEFORE_UPDATE = 0xa8,
+ CB_PERF_SEL_QUAD_HAS_6_FRAGMENTS_BEFORE_UPDATE = 0xa9,
+ CB_PERF_SEL_QUAD_HAS_7_FRAGMENTS_BEFORE_UPDATE = 0xaa,
+ CB_PERF_SEL_QUAD_HAS_8_FRAGMENTS_BEFORE_UPDATE = 0xab,
+ CB_PERF_SEL_QUAD_HAS_1_FRAGMENT_AFTER_UPDATE = 0xac,
+ CB_PERF_SEL_QUAD_HAS_2_FRAGMENTS_AFTER_UPDATE = 0xad,
+ CB_PERF_SEL_QUAD_HAS_3_FRAGMENTS_AFTER_UPDATE = 0xae,
+ CB_PERF_SEL_QUAD_HAS_4_FRAGMENTS_AFTER_UPDATE = 0xaf,
+ CB_PERF_SEL_QUAD_HAS_5_FRAGMENTS_AFTER_UPDATE = 0xb0,
+ CB_PERF_SEL_QUAD_HAS_6_FRAGMENTS_AFTER_UPDATE = 0xb1,
+ CB_PERF_SEL_QUAD_HAS_7_FRAGMENTS_AFTER_UPDATE = 0xb2,
+ CB_PERF_SEL_QUAD_HAS_8_FRAGMENTS_AFTER_UPDATE = 0xb3,
+ CB_PERF_SEL_QUAD_ADDED_1_FRAGMENT = 0xb4,
+ CB_PERF_SEL_QUAD_ADDED_2_FRAGMENTS = 0xb5,
+ CB_PERF_SEL_QUAD_ADDED_3_FRAGMENTS = 0xb6,
+ CB_PERF_SEL_QUAD_ADDED_4_FRAGMENTS = 0xb7,
+ CB_PERF_SEL_QUAD_ADDED_5_FRAGMENTS = 0xb8,
+ CB_PERF_SEL_QUAD_ADDED_6_FRAGMENTS = 0xb9,
+ CB_PERF_SEL_QUAD_ADDED_7_FRAGMENTS = 0xba,
+ CB_PERF_SEL_QUAD_REMOVED_1_FRAGMENT = 0xbb,
+ CB_PERF_SEL_QUAD_REMOVED_2_FRAGMENTS = 0xbc,
+ CB_PERF_SEL_QUAD_REMOVED_3_FRAGMENTS = 0xbd,
+ CB_PERF_SEL_QUAD_REMOVED_4_FRAGMENTS = 0xbe,
+ CB_PERF_SEL_QUAD_REMOVED_5_FRAGMENTS = 0xbf,
+ CB_PERF_SEL_QUAD_REMOVED_6_FRAGMENTS = 0xc0,
+ CB_PERF_SEL_QUAD_REMOVED_7_FRAGMENTS = 0xc1,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_0 = 0xc2,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_1 = 0xc3,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_2 = 0xc4,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_3 = 0xc5,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_4 = 0xc6,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_5 = 0xc7,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_6 = 0xc8,
+ CB_PERF_SEL_QUAD_READS_FRAGMENT_7 = 0xc9,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_0 = 0xca,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_1 = 0xcb,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_2 = 0xcc,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_3 = 0xcd,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_4 = 0xce,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_5 = 0xcf,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_6 = 0xd0,
+ CB_PERF_SEL_QUAD_WRITES_FRAGMENT_7 = 0xd1,
+ CB_PERF_SEL_QUAD_BLEND_OPT_DONT_READ_DST = 0xd2,
+ CB_PERF_SEL_QUAD_BLEND_OPT_BLEND_BYPASS = 0xd3,
+ CB_PERF_SEL_QUAD_BLEND_OPT_DISCARD_PIXELS = 0xd4,
+ CB_PERF_SEL_QUAD_DST_READ_COULD_HAVE_BEEN_OPTIMIZED= 0xd5,
+ CB_PERF_SEL_QUAD_BLENDING_COULD_HAVE_BEEN_BYPASSED= 0xd6,
+ CB_PERF_SEL_QUAD_COULD_HAVE_BEEN_DISCARDED = 0xd7,
+ CB_PERF_SEL_BLEND_OPT_PIXELS_RESULT_EQ_DEST = 0xd8,
+ CB_PERF_SEL_DRAWN_BUSY = 0xd9,
+ CB_PERF_SEL_TILE_TO_CMR_REGION_BUSY = 0xda,
+ CB_PERF_SEL_CMR_TO_FCR_REGION_BUSY = 0xdb,
+ CB_PERF_SEL_FCR_TO_CCR_REGION_BUSY = 0xdc,
+ CB_PERF_SEL_CCR_TO_CCW_REGION_BUSY = 0xdd,
+ CB_PERF_SEL_FC_PF_SLOW_MODE_QUAD_EMPTY_HALF_DROPPED= 0xde,
+ CB_PERF_SEL_FC_SEQUENCER_CLEAR = 0xdf,
+ CB_PERF_SEL_FC_SEQUENCER_ELIMINATE_FAST_CLEAR = 0xe0,
+ CB_PERF_SEL_FC_SEQUENCER_FMASK_DECOMPRESS = 0xe1,
+ CB_PERF_SEL_FC_SEQUENCER_FMASK_COMPRESSION_DISABLE= 0xe2,
+ CB_PERF_SEL_FC_KEYID_RDLAT_FIFO_FULL = 0xe3,
+ CB_PERF_SEL_FC_DOC_IS_STALLED = 0xe4,
+ CB_PERF_SEL_FC_DOC_MRTS_NOT_COMBINED = 0xe5,
+ CB_PERF_SEL_FC_DOC_MRTS_COMBINED = 0xe6,
+ CB_PERF_SEL_FC_DOC_QTILE_CAM_MISS = 0xe7,
+ CB_PERF_SEL_FC_DOC_QTILE_CAM_HIT = 0xe8,
+ CB_PERF_SEL_FC_DOC_CLINE_CAM_MISS = 0xe9,
+ CB_PERF_SEL_FC_DOC_CLINE_CAM_HIT = 0xea,
+ CB_PERF_SEL_FC_DOC_QUAD_PTR_FIFO_IS_FULL = 0xeb,
+ CB_PERF_SEL_FC_DOC_OVERWROTE_1_SECTOR = 0xec,
+ CB_PERF_SEL_FC_DOC_OVERWROTE_2_SECTORS = 0xed,
+ CB_PERF_SEL_FC_DOC_OVERWROTE_3_SECTORS = 0xee,
+ CB_PERF_SEL_FC_DOC_OVERWROTE_4_SECTORS = 0xef,
+ CB_PERF_SEL_FC_DOC_TOTAL_OVERWRITTEN_SECTORS = 0xf0,
+ CB_PERF_SEL_FC_DCC_CACHE_HIT = 0xf1,
+ CB_PERF_SEL_FC_DCC_CACHE_TAG_MISS = 0xf2,
+ CB_PERF_SEL_FC_DCC_CACHE_SECTOR_MISS = 0xf3,
+ CB_PERF_SEL_FC_DCC_CACHE_REEVICTION_STALL = 0xf4,
+ CB_PERF_SEL_FC_DCC_CACHE_EVICT_NONZERO_INFLIGHT_STALL= 0xf5,
+ CB_PERF_SEL_FC_DCC_CACHE_REPLACE_PENDING_EVICT_STALL= 0xf6,
+ CB_PERF_SEL_FC_DCC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL= 0xf7,
+ CB_PERF_SEL_FC_DCC_CACHE_READ_OUTPUT_STALL = 0xf8,
+ CB_PERF_SEL_FC_DCC_CACHE_WRITE_OUTPUT_STALL = 0xf9,
+ CB_PERF_SEL_FC_DCC_CACHE_ACK_OUTPUT_STALL = 0xfa,
+ CB_PERF_SEL_FC_DCC_CACHE_STALL = 0xfb,
+ CB_PERF_SEL_FC_DCC_CACHE_FLUSH = 0xfc,
+ CB_PERF_SEL_FC_DCC_CACHE_TAGS_FLUSHED = 0xfd,
+ CB_PERF_SEL_FC_DCC_CACHE_SECTORS_FLUSHED = 0xfe,
+ CB_PERF_SEL_FC_DCC_CACHE_DIRTY_SECTORS_FLUSHED = 0xff,
+ CB_PERF_SEL_CC_DCC_BEYOND_TILE_SPLIT = 0x100,
+ CB_PERF_SEL_FC_MC_DCC_WRITE_REQUEST = 0x101,
+ CB_PERF_SEL_FC_MC_DCC_WRITE_REQUESTS_IN_FLIGHT = 0x102,
+ CB_PERF_SEL_FC_MC_DCC_READ_REQUEST = 0x103,
+ CB_PERF_SEL_FC_MC_DCC_READ_REQUESTS_IN_FLIGHT = 0x104,
+ CB_PERF_SEL_CC_DCC_RDREQ_STALL = 0x105,
+ CB_PERF_SEL_CC_DCC_DECOMPRESS_TIDS_IN = 0x106,
+ CB_PERF_SEL_CC_DCC_DECOMPRESS_TIDS_OUT = 0x107,
+ CB_PERF_SEL_CC_DCC_COMPRESS_TIDS_IN = 0x108,
+ CB_PERF_SEL_CC_DCC_COMPRESS_TIDS_OUT = 0x109,
+ CB_PERF_SEL_FC_DCC_KEY_VALUE__CLEAR = 0x10a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__4_BLOCKS__2TO1 = 0x10b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__3BLOCKS_2TO1__1BLOCK_2TO2= 0x10c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO1__1BLOCK_2TO2__1BLOCK_2TO1= 0x10d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_2TO2__2BLOCKS_2TO1= 0x10e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__3BLOCKS_2TO1= 0x10f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO1__2BLOCKS_2TO2= 0x110,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__2BLOCKS_2TO2__1BLOCK_2TO1= 0x111,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_2TO2__1BLOCK_2TO1__1BLOCK_2TO2= 0x112,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_2TO1__1BLOCK_2TO2__1BLOCK_2TO1= 0x113,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO2__2BLOCKS_2TO1= 0x114,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__2BLOCKS_2TO1__1BLOCK_2TO2= 0x115,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__3BLOCKS_2TO2= 0x116,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_2TO1__2BLOCKS_2TO2= 0x117,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO2__1BLOCK_2TO1__1BLOCK_2TO2= 0x118,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__3BLOCKS_2TO2__1BLOCK_2TO1= 0x119,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_4TO1 = 0x11a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__1BLOCK_4TO2= 0x11b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__1BLOCK_4TO3= 0x11c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__1BLOCK_4TO4= 0x11d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__1BLOCK_4TO1= 0x11e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_4TO2 = 0x11f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__1BLOCK_4TO3= 0x120,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__1BLOCK_4TO4= 0x121,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__1BLOCK_4TO1= 0x122,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__1BLOCK_4TO2= 0x123,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_4TO3 = 0x124,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__1BLOCK_4TO4= 0x125,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO4__1BLOCK_4TO1= 0x126,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO4__1BLOCK_4TO2= 0x127,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO4__1BLOCK_4TO3= 0x128,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO1__1BLOCK_4TO1= 0x129,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO1__1BLOCK_4TO2= 0x12a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO1__1BLOCK_4TO3= 0x12b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO1__1BLOCK_4TO4= 0x12c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_2TO2__1BLOCK_4TO1= 0x12d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_2TO2__1BLOCK_4TO2= 0x12e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_2TO2__1BLOCK_4TO3= 0x12f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_2TO2__1BLOCK_4TO4= 0x130,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_2TO1__1BLOCK_4TO1= 0x131,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_2TO1__1BLOCK_4TO2= 0x132,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_2TO1__1BLOCK_4TO3= 0x133,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_2TO1__1BLOCK_4TO4= 0x134,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO2__1BLOCK_4TO1= 0x135,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO2__1BLOCK_4TO2= 0x136,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__2BLOCKS_2TO2__1BLOCK_4TO3= 0x137,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO1__1BLOCK_2TO1= 0x138,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO2__1BLOCK_2TO1= 0x139,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO3__1BLOCK_2TO1= 0x13a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO4__1BLOCK_2TO1= 0x13b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO1__1BLOCK_2TO1= 0x13c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO2__1BLOCK_2TO1= 0x13d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO3__1BLOCK_2TO1= 0x13e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO4__1BLOCK_2TO1= 0x13f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO1__1BLOCK_2TO2= 0x140,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO2__1BLOCK_2TO2= 0x141,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO3__1BLOCK_2TO2= 0x142,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_4TO4__1BLOCK_2TO2= 0x143,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO1__1BLOCK_2TO2= 0x144,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO2__1BLOCK_2TO2= 0x145,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_4TO3__1BLOCK_2TO2= 0x146,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__2BLOCKS_2TO1= 0x147,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__2BLOCKS_2TO1= 0x148,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__2BLOCKS_2TO1= 0x149,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO4__2BLOCKS_2TO1= 0x14a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__2BLOCKS_2TO2= 0x14b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__2BLOCKS_2TO2= 0x14c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__2BLOCKS_2TO2= 0x14d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__1BLOCK_2TO1__1BLOCK_2TO2= 0x14e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__1BLOCK_2TO1__1BLOCK_2TO2= 0x14f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__1BLOCK_2TO1__1BLOCK_2TO2= 0x150,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO4__1BLOCK_2TO1__1BLOCK_2TO2= 0x151,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO1__1BLOCK_2TO2__1BLOCK_2TO1= 0x152,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO2__1BLOCK_2TO2__1BLOCK_2TO1= 0x153,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO3__1BLOCK_2TO2__1BLOCK_2TO1= 0x154,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_4TO4__1BLOCK_2TO2__1BLOCK_2TO1= 0x155,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_6TO1= 0x156,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_6TO2= 0x157,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_6TO3= 0x158,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_6TO4= 0x159,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_6TO5= 0x15a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__1BLOCK_6TO6= 0x15b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__INV0 = 0x15c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO1__INV1 = 0x15d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_6TO1= 0x15e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_6TO2= 0x15f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_6TO3= 0x160,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_6TO4= 0x161,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__1BLOCK_6TO5= 0x162,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__INV0 = 0x163,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_2TO2__INV1 = 0x164,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO1__1BLOCK_2TO1= 0x165,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO2__1BLOCK_2TO1= 0x166,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO3__1BLOCK_2TO1= 0x167,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO4__1BLOCK_2TO1= 0x168,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO5__1BLOCK_2TO1= 0x169,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO6__1BLOCK_2TO1= 0x16a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__INV0__1BLOCK_2TO1 = 0x16b,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__INV1__1BLOCK_2TO1 = 0x16c,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO1__1BLOCK_2TO2= 0x16d,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO2__1BLOCK_2TO2= 0x16e,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO3__1BLOCK_2TO2= 0x16f,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO4__1BLOCK_2TO2= 0x170,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_6TO5__1BLOCK_2TO2= 0x171,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__INV0__1BLOCK_2TO2 = 0x172,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__INV1__1BLOCK_2TO2 = 0x173,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO1 = 0x174,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO2 = 0x175,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO3 = 0x176,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO4 = 0x177,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO5 = 0x178,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO6 = 0x179,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__1BLOCK_8TO7 = 0x17a,
+ CB_PERF_SEL_CC_DCC_KEY_VALUE__UNCOMPRESSED = 0x17b,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_2TO1 = 0x17c,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_4TO1 = 0x17d,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_4TO2 = 0x17e,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_4TO3 = 0x17f,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_6TO1 = 0x180,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_6TO2 = 0x181,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_6TO3 = 0x182,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_6TO4 = 0x183,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_6TO5 = 0x184,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO1 = 0x185,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO2 = 0x186,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO3 = 0x187,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO4 = 0x188,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO5 = 0x189,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO6 = 0x18a,
+ CB_PERF_SEL_CC_DCC_COMPRESS_RATIO_8TO7 = 0x18b,
+ CB_PERF_SEL_RBP_EXPORT_8PIX_LIT_BOTH = 0x18c,
+ CB_PERF_SEL_RBP_EXPORT_8PIX_LIT_LEFT = 0x18d,
+ CB_PERF_SEL_RBP_EXPORT_8PIX_LIT_RIGHT = 0x18e,
+ CB_PERF_SEL_RBP_SPLIT_MICROTILE = 0x18f,
+ CB_PERF_SEL_RBP_SPLIT_AA_SAMPLE_MASK = 0x190,
+ CB_PERF_SEL_RBP_SPLIT_PARTIAL_TARGET_MASK = 0x191,
+ CB_PERF_SEL_RBP_SPLIT_LINEAR_ADDRESSING = 0x192,
+ CB_PERF_SEL_RBP_SPLIT_AA_NO_FMASK_COMPRESS = 0x193,
+ CB_PERF_SEL_RBP_INSERT_MISSING_LAST_QUAD = 0x194,
+} CBPerfSel;
+typedef enum CBPerfOpFilterSel {
+ CB_PERF_OP_FILTER_SEL_WRITE_ONLY = 0x0,
+ CB_PERF_OP_FILTER_SEL_NEEDS_DESTINATION = 0x1,
+ CB_PERF_OP_FILTER_SEL_RESOLVE = 0x2,
+ CB_PERF_OP_FILTER_SEL_DECOMPRESS = 0x3,
+ CB_PERF_OP_FILTER_SEL_FMASK_DECOMPRESS = 0x4,
+ CB_PERF_OP_FILTER_SEL_ELIMINATE_FAST_CLEAR = 0x5,
+} CBPerfOpFilterSel;
+typedef enum CBPerfClearFilterSel {
+ CB_PERF_CLEAR_FILTER_SEL_NONCLEAR = 0x0,
+ CB_PERF_CLEAR_FILTER_SEL_CLEAR = 0x1,
+} CBPerfClearFilterSel;
+typedef enum CP_RING_ID {
+ RINGID0 = 0x0,
+ RINGID1 = 0x1,
+ RINGID2 = 0x2,
+ RINGID3 = 0x3,
+} CP_RING_ID;
+typedef enum CP_PIPE_ID {
+ PIPE_ID0 = 0x0,
+ PIPE_ID1 = 0x1,
+ PIPE_ID2 = 0x2,
+ PIPE_ID3 = 0x3,
+} CP_PIPE_ID;
+typedef enum CP_ME_ID {
+ ME_ID0 = 0x0,
+ ME_ID1 = 0x1,
+ ME_ID2 = 0x2,
+ ME_ID3 = 0x3,
+} CP_ME_ID;
+typedef enum SPM_PERFMON_STATE {
+ STRM_PERFMON_STATE_DISABLE_AND_RESET = 0x0,
+ STRM_PERFMON_STATE_START_COUNTING = 0x1,
+ STRM_PERFMON_STATE_STOP_COUNTING = 0x2,
+ STRM_PERFMON_STATE_RESERVED_3 = 0x3,
+ STRM_PERFMON_STATE_DISABLE_AND_RESET_PHANTOM = 0x4,
+ STRM_PERFMON_STATE_COUNT_AND_DUMP_PHANTOM = 0x5,
+} SPM_PERFMON_STATE;
+typedef enum CP_PERFMON_STATE {
+ CP_PERFMON_STATE_DISABLE_AND_RESET = 0x0,
+ CP_PERFMON_STATE_START_COUNTING = 0x1,
+ CP_PERFMON_STATE_STOP_COUNTING = 0x2,
+ CP_PERFMON_STATE_RESERVED_3 = 0x3,
+ CP_PERFMON_STATE_DISABLE_AND_RESET_PHANTOM = 0x4,
+ CP_PERFMON_STATE_COUNT_AND_DUMP_PHANTOM = 0x5,
+} CP_PERFMON_STATE;
+typedef enum CP_PERFMON_ENABLE_MODE {
+ CP_PERFMON_ENABLE_MODE_ALWAYS_COUNT = 0x0,
+ CP_PERFMON_ENABLE_MODE_RESERVED_1 = 0x1,
+ CP_PERFMON_ENABLE_MODE_COUNT_CONTEXT_TRUE = 0x2,
+ CP_PERFMON_ENABLE_MODE_COUNT_CONTEXT_FALSE = 0x3,
+} CP_PERFMON_ENABLE_MODE;
+typedef enum CPG_PERFCOUNT_SEL {
+ CPG_PERF_SEL_ALWAYS_COUNT = 0x0,
+ CPG_PERF_SEL_RBIU_FIFO_FULL = 0x1,
+ CPG_PERF_SEL_CSF_RTS_BUT_MIU_NOT_RTR = 0x2,
+ CPG_PERF_SEL_CSF_ST_BASE_SIZE_FIFO_FULL = 0x3,
+ CPG_PERF_SEL_CP_GRBM_DWORDS_SENT = 0x4,
+ CPG_PERF_SEL_ME_PARSER_BUSY = 0x5,
+ CPG_PERF_SEL_COUNT_TYPE0_PACKETS = 0x6,
+ CPG_PERF_SEL_COUNT_TYPE3_PACKETS = 0x7,
+ CPG_PERF_SEL_CSF_FETCHING_CMD_BUFFERS = 0x8,
+ CPG_PERF_SEL_CP_GRBM_OUT_OF_CREDITS = 0x9,
+ CPG_PERF_SEL_CP_PFP_GRBM_OUT_OF_CREDITS = 0xa,
+ CPG_PERF_SEL_CP_GDS_GRBM_OUT_OF_CREDITS = 0xb,
+ CPG_PERF_SEL_RCIU_STALLED_ON_ME_READ = 0xc,
+ CPG_PERF_SEL_RCIU_STALLED_ON_DMA_READ = 0xd,
+ CPG_PERF_SEL_SSU_STALLED_ON_ACTIVE_CNTX = 0xe,
+ CPG_PERF_SEL_SSU_STALLED_ON_CLEAN_SIGNALS = 0xf,
+ CPG_PERF_SEL_QU_STALLED_ON_EOP_DONE_PULSE = 0x10,
+ CPG_PERF_SEL_QU_STALLED_ON_EOP_DONE_WR_CONFIRM = 0x11,
+ CPG_PERF_SEL_PFP_STALLED_ON_CSF_READY = 0x12,
+ CPG_PERF_SEL_PFP_STALLED_ON_MEQ_READY = 0x13,
+ CPG_PERF_SEL_PFP_STALLED_ON_RCIU_READY = 0x14,
+ CPG_PERF_SEL_PFP_STALLED_FOR_DATA_FROM_ROQ = 0x15,
+ CPG_PERF_SEL_ME_STALLED_FOR_DATA_FROM_PFP = 0x16,
+ CPG_PERF_SEL_ME_STALLED_FOR_DATA_FROM_STQ = 0x17,
+ CPG_PERF_SEL_ME_STALLED_ON_NO_AVAIL_GFX_CNTX = 0x18,
+ CPG_PERF_SEL_ME_STALLED_WRITING_TO_RCIU = 0x19,
+ CPG_PERF_SEL_ME_STALLED_WRITING_CONSTANTS = 0x1a,
+ CPG_PERF_SEL_ME_STALLED_ON_PARTIAL_FLUSH = 0x1b,
+ CPG_PERF_SEL_ME_WAIT_ON_CE_COUNTER = 0x1c,
+ CPG_PERF_SEL_ME_WAIT_ON_AVAIL_BUFFER = 0x1d,
+ CPG_PERF_SEL_SEMAPHORE_BUSY_POLLING_FOR_PASS = 0x1e,
+ CPG_PERF_SEL_LOAD_STALLED_ON_SET_COHERENCY = 0x1f,
+ CPG_PERF_SEL_DYNAMIC_CLK_VALID = 0x20,
+ CPG_PERF_SEL_REGISTER_CLK_VALID = 0x21,
+ CPG_PERF_SEL_MIU_WRITE_REQUEST_SENT = 0x22,
+ CPG_PERF_SEL_MIU_READ_REQUEST_SENT = 0x23,
+ CPG_PERF_SEL_CE_STALL_RAM_DUMP = 0x24,
+ CPG_PERF_SEL_CE_STALL_RAM_WRITE = 0x25,
+ CPG_PERF_SEL_CE_STALL_ON_INC_FIFO = 0x26,
+ CPG_PERF_SEL_CE_STALL_ON_WR_RAM_FIFO = 0x27,
+ CPG_PERF_SEL_CE_STALL_ON_DATA_FROM_MIU = 0x28,
+ CPG_PERF_SEL_CE_STALL_ON_DATA_FROM_ROQ = 0x29,
+ CPG_PERF_SEL_CE_STALL_ON_CE_BUFFER_FLAG = 0x2a,
+ CPG_PERF_SEL_CE_STALL_ON_DE_COUNTER = 0x2b,
+ CPG_PERF_SEL_TCIU_STALL_WAIT_ON_FREE = 0x2c,
+ CPG_PERF_SEL_TCIU_STALL_WAIT_ON_TAGS = 0x2d,
+ CPG_PERF_SEL_ATCL2IU_STALL_WAIT_ON_FREE = 0x2e,
+ CPG_PERF_SEL_ATCL2IU_STALL_WAIT_ON_TAGS = 0x2f,
+ CPG_PERF_SEL_ATCL1_STALL_ON_TRANSLATION = 0x30,
+} CPG_PERFCOUNT_SEL;
+typedef enum CPF_PERFCOUNT_SEL {
+ CPF_PERF_SEL_ALWAYS_COUNT = 0x0,
+ CPF_PERF_SEL_MIU_STALLED_WAITING_RDREQ_FREE = 0x1,
+ CPF_PERF_SEL_TCIU_STALLED_WAITING_ON_FREE = 0x2,
+ CPF_PERF_SEL_TCIU_STALLED_WAITING_ON_TAGS = 0x3,
+ CPF_PERF_SEL_CSF_BUSY_FOR_FETCHING_RING = 0x4,
+ CPF_PERF_SEL_CSF_BUSY_FOR_FETCHING_IB1 = 0x5,
+ CPF_PERF_SEL_CSF_BUSY_FOR_FETCHING_IB2 = 0x6,
+ CPF_PERF_SEL_CSF_BUSY_FOR_FECTHINC_STATE = 0x7,
+ CPF_PERF_SEL_MIU_BUSY_FOR_OUTSTANDING_TAGS = 0x8,
+ CPF_PERF_SEL_CSF_RTS_MIU_NOT_RTR = 0x9,
+ CPF_PERF_SEL_CSF_STATE_FIFO_NOT_RTR = 0xa,
+ CPF_PERF_SEL_CSF_FETCHING_CMD_BUFFERS = 0xb,
+ CPF_PERF_SEL_GRBM_DWORDS_SENT = 0xc,
+ CPF_PERF_SEL_DYNAMIC_CLOCK_VALID = 0xd,
+ CPF_PERF_SEL_REGISTER_CLOCK_VALID = 0xe,
+ CPF_PERF_SEL_MIU_WRITE_REQUEST_SEND = 0xf,
+ CPF_PERF_SEL_MIU_READ_REQUEST_SEND = 0x10,
+ CPF_PERF_SEL_ATCL2IU_STALL_WAIT_ON_FREE = 0x11,
+ CPF_PERF_SEL_ATCL2IU_STALL_WAIT_ON_TAGS = 0x12,
+ CPF_PERF_SEL_ATCL1_STALL_ON_TRANSLATION = 0x13,
+} CPF_PERFCOUNT_SEL;
+typedef enum CPC_PERFCOUNT_SEL {
+ CPC_PERF_SEL_ALWAYS_COUNT = 0x0,
+ CPC_PERF_SEL_RCIU_STALL_WAIT_ON_FREE = 0x1,
+ CPC_PERF_SEL_RCIU_STALL_PRIV_VIOLATION = 0x2,
+ CPC_PERF_SEL_MIU_STALL_ON_RDREQ_FREE = 0x3,
+ CPC_PERF_SEL_MIU_STALL_ON_WRREQ_FREE = 0x4,
+ CPC_PERF_SEL_TCIU_STALL_WAIT_ON_FREE = 0x5,
+ CPC_PERF_SEL_ME1_STALL_WAIT_ON_RCIU_READY = 0x6,
+ CPC_PERF_SEL_ME1_STALL_WAIT_ON_RCIU_READY_PERF = 0x7,
+ CPC_PERF_SEL_ME1_STALL_WAIT_ON_RCIU_READ = 0x8,
+ CPC_PERF_SEL_ME1_STALL_WAIT_ON_MIU_READ = 0x9,
+ CPC_PERF_SEL_ME1_STALL_WAIT_ON_MIU_WRITE = 0xa,
+ CPC_PERF_SEL_ME1_STALL_ON_DATA_FROM_ROQ = 0xb,
+ CPC_PERF_SEL_ME1_STALL_ON_DATA_FROM_ROQ_PERF = 0xc,
+ CPC_PERF_SEL_ME1_BUSY_FOR_PACKET_DECODE = 0xd,
+ CPC_PERF_SEL_ME2_STALL_WAIT_ON_RCIU_READY = 0xe,
+ CPC_PERF_SEL_ME2_STALL_WAIT_ON_RCIU_READY_PERF = 0xf,
+ CPC_PERF_SEL_ME2_STALL_WAIT_ON_RCIU_READ = 0x10,
+ CPC_PERF_SEL_ME2_STALL_WAIT_ON_MIU_READ = 0x11,
+ CPC_PERF_SEL_ME2_STALL_WAIT_ON_MIU_WRITE = 0x12,
+ CPC_PERF_SEL_ME2_STALL_ON_DATA_FROM_ROQ = 0x13,
+ CPC_PERF_SEL_ME2_STALL_ON_DATA_FROM_ROQ_PERF = 0x14,
+ CPC_PERF_SEL_ME2_BUSY_FOR_PACKET_DECODE = 0x15,
+ CPC_PERF_SEL_ATCL2IU_STALL_WAIT_ON_FREE = 0x16,
+ CPC_PERF_SEL_ATCL2IU_STALL_WAIT_ON_TAGS = 0x17,
+ CPC_PERF_SEL_ATCL1_STALL_ON_TRANSLATION = 0x18,
+} CPC_PERFCOUNT_SEL;
+typedef enum CP_ALPHA_TAG_RAM_SEL {
+ CPG_TAG_RAM = 0x0,
+ CPC_TAG_RAM = 0x1,
+ CPF_TAG_RAM = 0x2,
+ RSV_TAG_RAM = 0x3,
+} CP_ALPHA_TAG_RAM_SEL;
+#define SEM_ECC_ERROR 0x0
+#define SEM_RESERVED 0x1
+#define SEM_FAILED 0x2
+#define SEM_PASSED 0x3
+#define IQ_QUEUE_SLEEP 0x0
+#define IQ_OFFLOAD_RETRY 0x1
+#define IQ_SCH_WAVE_MSG 0x2
+#define IQ_SEM_REARM 0x3
+#define IQ_DEQUEUE_RETRY 0x4
+#define IQ_INTR_TYPE_PQ 0x0
+#define IQ_INTR_TYPE_IB 0x1
+#define IQ_INTR_TYPE_MQD 0x2
+#define VMID_SZ 0x4
+#define CONFIG_SPACE_START 0x2000
+#define CONFIG_SPACE_END 0x9fff
+#define CONFIG_SPACE1_START 0x2000
+#define CONFIG_SPACE1_END 0x2bff
+#define CONFIG_SPACE2_START 0x3000
+#define CONFIG_SPACE2_END 0x9fff
+#define UCONFIG_SPACE_START 0xc000
+#define UCONFIG_SPACE_END 0xffff
+#define PERSISTENT_SPACE_START 0x2c00
+#define PERSISTENT_SPACE_END 0x2fff
+#define CONTEXT_SPACE_START 0xa000
+#define CONTEXT_SPACE_END 0xbfff
+typedef enum ForceControl {
+ FORCE_OFF = 0x0,
+ FORCE_ENABLE = 0x1,
+ FORCE_DISABLE = 0x2,
+ FORCE_RESERVED = 0x3,
+} ForceControl;
+typedef enum ZSamplePosition {
+ Z_SAMPLE_CENTER = 0x0,
+ Z_SAMPLE_CENTROID = 0x1,
+} ZSamplePosition;
+typedef enum ZOrder {
+ LATE_Z = 0x0,
+ EARLY_Z_THEN_LATE_Z = 0x1,
+ RE_Z = 0x2,
+ EARLY_Z_THEN_RE_Z = 0x3,
+} ZOrder;
+typedef enum ZpassControl {
+ ZPASS_DISABLE = 0x0,
+ ZPASS_SAMPLES = 0x1,
+ ZPASS_PIXELS = 0x2,
+} ZpassControl;
+typedef enum ZModeForce {
+ NO_FORCE = 0x0,
+ FORCE_EARLY_Z = 0x1,
+ FORCE_LATE_Z = 0x2,
+ FORCE_RE_Z = 0x3,
+} ZModeForce;
+typedef enum ZLimitSumm {
+ FORCE_SUMM_OFF = 0x0,
+ FORCE_SUMM_MINZ = 0x1,
+ FORCE_SUMM_MAXZ = 0x2,
+ FORCE_SUMM_BOTH = 0x3,
+} ZLimitSumm;
+typedef enum CompareFrag {
+ FRAG_NEVER = 0x0,
+ FRAG_LESS = 0x1,
+ FRAG_EQUAL = 0x2,
+ FRAG_LEQUAL = 0x3,
+ FRAG_GREATER = 0x4,
+ FRAG_NOTEQUAL = 0x5,
+ FRAG_GEQUAL = 0x6,
+ FRAG_ALWAYS = 0x7,
+} CompareFrag;
+typedef enum StencilOp {
+ STENCIL_KEEP = 0x0,
+ STENCIL_ZERO = 0x1,
+ STENCIL_ONES = 0x2,
+ STENCIL_REPLACE_TEST = 0x3,
+ STENCIL_REPLACE_OP = 0x4,
+ STENCIL_ADD_CLAMP = 0x5,
+ STENCIL_SUB_CLAMP = 0x6,
+ STENCIL_INVERT = 0x7,
+ STENCIL_ADD_WRAP = 0x8,
+ STENCIL_SUB_WRAP = 0x9,
+ STENCIL_AND = 0xa,
+ STENCIL_OR = 0xb,
+ STENCIL_XOR = 0xc,
+ STENCIL_NAND = 0xd,
+ STENCIL_NOR = 0xe,
+ STENCIL_XNOR = 0xf,
+} StencilOp;
+typedef enum ConservativeZExport {
+ EXPORT_ANY_Z = 0x0,
+ EXPORT_LESS_THAN_Z = 0x1,
+ EXPORT_GREATER_THAN_Z = 0x2,
+ EXPORT_RESERVED = 0x3,
+} ConservativeZExport;
+typedef enum DbPSLControl {
+ PSLC_AUTO = 0x0,
+ PSLC_ON_HANG_ONLY = 0x1,
+ PSLC_ASAP = 0x2,
+ PSLC_COUNTDOWN = 0x3,
+} DbPSLControl;
+typedef enum PerfCounter_Vals {
+ DB_PERF_SEL_SC_DB_tile_sends = 0x0,
+ DB_PERF_SEL_SC_DB_tile_busy = 0x1,
+ DB_PERF_SEL_SC_DB_tile_stalls = 0x2,
+ DB_PERF_SEL_SC_DB_tile_events = 0x3,
+ DB_PERF_SEL_SC_DB_tile_tiles = 0x4,
+ DB_PERF_SEL_SC_DB_tile_covered = 0x5,
+ DB_PERF_SEL_hiz_tc_read_starved = 0x6,
+ DB_PERF_SEL_hiz_tc_write_stall = 0x7,
+ DB_PERF_SEL_hiz_qtiles_culled = 0x8,
+ DB_PERF_SEL_his_qtiles_culled = 0x9,
+ DB_PERF_SEL_DB_SC_tile_sends = 0xa,
+ DB_PERF_SEL_DB_SC_tile_busy = 0xb,
+ DB_PERF_SEL_DB_SC_tile_stalls = 0xc,
+ DB_PERF_SEL_DB_SC_tile_df_stalls = 0xd,
+ DB_PERF_SEL_DB_SC_tile_tiles = 0xe,
+ DB_PERF_SEL_DB_SC_tile_culled = 0xf,
+ DB_PERF_SEL_DB_SC_tile_hier_kill = 0x10,
+ DB_PERF_SEL_DB_SC_tile_fast_ops = 0x11,
+ DB_PERF_SEL_DB_SC_tile_no_ops = 0x12,
+ DB_PERF_SEL_DB_SC_tile_tile_rate = 0x13,
+ DB_PERF_SEL_DB_SC_tile_ssaa_kill = 0x14,
+ DB_PERF_SEL_DB_SC_tile_fast_z_ops = 0x15,
+ DB_PERF_SEL_DB_SC_tile_fast_stencil_ops = 0x16,
+ DB_PERF_SEL_SC_DB_quad_sends = 0x17,
+ DB_PERF_SEL_SC_DB_quad_busy = 0x18,
+ DB_PERF_SEL_SC_DB_quad_squads = 0x19,
+ DB_PERF_SEL_SC_DB_quad_tiles = 0x1a,
+ DB_PERF_SEL_SC_DB_quad_pixels = 0x1b,
+ DB_PERF_SEL_SC_DB_quad_killed_tiles = 0x1c,
+ DB_PERF_SEL_DB_SC_quad_sends = 0x1d,
+ DB_PERF_SEL_DB_SC_quad_busy = 0x1e,
+ DB_PERF_SEL_DB_SC_quad_stalls = 0x1f,
+ DB_PERF_SEL_DB_SC_quad_tiles = 0x20,
+ DB_PERF_SEL_DB_SC_quad_lit_quad = 0x21,
+ DB_PERF_SEL_DB_CB_tile_sends = 0x22,
+ DB_PERF_SEL_DB_CB_tile_busy = 0x23,
+ DB_PERF_SEL_DB_CB_tile_stalls = 0x24,
+ DB_PERF_SEL_SX_DB_quad_sends = 0x25,
+ DB_PERF_SEL_SX_DB_quad_busy = 0x26,
+ DB_PERF_SEL_SX_DB_quad_stalls = 0x27,
+ DB_PERF_SEL_SX_DB_quad_quads = 0x28,
+ DB_PERF_SEL_SX_DB_quad_pixels = 0x29,
+ DB_PERF_SEL_SX_DB_quad_exports = 0x2a,
+ DB_PERF_SEL_SH_quads_outstanding_sum = 0x2b,
+ DB_PERF_SEL_DB_CB_lquad_sends = 0x2c,
+ DB_PERF_SEL_DB_CB_lquad_busy = 0x2d,
+ DB_PERF_SEL_DB_CB_lquad_stalls = 0x2e,
+ DB_PERF_SEL_DB_CB_lquad_quads = 0x2f,
+ DB_PERF_SEL_tile_rd_sends = 0x30,
+ DB_PERF_SEL_mi_tile_rd_outstanding_sum = 0x31,
+ DB_PERF_SEL_quad_rd_sends = 0x32,
+ DB_PERF_SEL_quad_rd_busy = 0x33,
+ DB_PERF_SEL_quad_rd_mi_stall = 0x34,
+ DB_PERF_SEL_quad_rd_rw_collision = 0x35,
+ DB_PERF_SEL_quad_rd_tag_stall = 0x36,
+ DB_PERF_SEL_quad_rd_32byte_reqs = 0x37,
+ DB_PERF_SEL_quad_rd_panic = 0x38,
+ DB_PERF_SEL_mi_quad_rd_outstanding_sum = 0x39,
+ DB_PERF_SEL_quad_rdret_sends = 0x3a,
+ DB_PERF_SEL_quad_rdret_busy = 0x3b,
+ DB_PERF_SEL_tile_wr_sends = 0x3c,
+ DB_PERF_SEL_tile_wr_acks = 0x3d,
+ DB_PERF_SEL_mi_tile_wr_outstanding_sum = 0x3e,
+ DB_PERF_SEL_quad_wr_sends = 0x3f,
+ DB_PERF_SEL_quad_wr_busy = 0x40,
+ DB_PERF_SEL_quad_wr_mi_stall = 0x41,
+ DB_PERF_SEL_quad_wr_coherency_stall = 0x42,
+ DB_PERF_SEL_quad_wr_acks = 0x43,
+ DB_PERF_SEL_mi_quad_wr_outstanding_sum = 0x44,
+ DB_PERF_SEL_Tile_Cache_misses = 0x45,
+ DB_PERF_SEL_Tile_Cache_hits = 0x46,
+ DB_PERF_SEL_Tile_Cache_flushes = 0x47,
+ DB_PERF_SEL_Tile_Cache_surface_stall = 0x48,
+ DB_PERF_SEL_Tile_Cache_starves = 0x49,
+ DB_PERF_SEL_Tile_Cache_mem_return_starve = 0x4a,
+ DB_PERF_SEL_tcp_dispatcher_reads = 0x4b,
+ DB_PERF_SEL_tcp_prefetcher_reads = 0x4c,
+ DB_PERF_SEL_tcp_preloader_reads = 0x4d,
+ DB_PERF_SEL_tcp_dispatcher_flushes = 0x4e,
+ DB_PERF_SEL_tcp_prefetcher_flushes = 0x4f,
+ DB_PERF_SEL_tcp_preloader_flushes = 0x50,
+ DB_PERF_SEL_Depth_Tile_Cache_sends = 0x51,
+ DB_PERF_SEL_Depth_Tile_Cache_busy = 0x52,
+ DB_PERF_SEL_Depth_Tile_Cache_starves = 0x53,
+ DB_PERF_SEL_Depth_Tile_Cache_dtile_locked = 0x54,
+ DB_PERF_SEL_Depth_Tile_Cache_alloc_stall = 0x55,
+ DB_PERF_SEL_Depth_Tile_Cache_misses = 0x56,
+ DB_PERF_SEL_Depth_Tile_Cache_hits = 0x57,
+ DB_PERF_SEL_Depth_Tile_Cache_flushes = 0x58,
+ DB_PERF_SEL_Depth_Tile_Cache_noop_tile = 0x59,
+ DB_PERF_SEL_Depth_Tile_Cache_detailed_noop = 0x5a,
+ DB_PERF_SEL_Depth_Tile_Cache_event = 0x5b,
+ DB_PERF_SEL_Depth_Tile_Cache_tile_frees = 0x5c,
+ DB_PERF_SEL_Depth_Tile_Cache_data_frees = 0x5d,
+ DB_PERF_SEL_Depth_Tile_Cache_mem_return_starve = 0x5e,
+ DB_PERF_SEL_Stencil_Cache_misses = 0x5f,
+ DB_PERF_SEL_Stencil_Cache_hits = 0x60,
+ DB_PERF_SEL_Stencil_Cache_flushes = 0x61,
+ DB_PERF_SEL_Stencil_Cache_starves = 0x62,
+ DB_PERF_SEL_Stencil_Cache_frees = 0x63,
+ DB_PERF_SEL_Z_Cache_separate_Z_misses = 0x64,
+ DB_PERF_SEL_Z_Cache_separate_Z_hits = 0x65,
+ DB_PERF_SEL_Z_Cache_separate_Z_flushes = 0x66,
+ DB_PERF_SEL_Z_Cache_separate_Z_starves = 0x67,
+ DB_PERF_SEL_Z_Cache_pmask_misses = 0x68,
+ DB_PERF_SEL_Z_Cache_pmask_hits = 0x69,
+ DB_PERF_SEL_Z_Cache_pmask_flushes = 0x6a,
+ DB_PERF_SEL_Z_Cache_pmask_starves = 0x6b,
+ DB_PERF_SEL_Z_Cache_frees = 0x6c,
+ DB_PERF_SEL_Plane_Cache_misses = 0x6d,
+ DB_PERF_SEL_Plane_Cache_hits = 0x6e,
+ DB_PERF_SEL_Plane_Cache_flushes = 0x6f,
+ DB_PERF_SEL_Plane_Cache_starves = 0x70,
+ DB_PERF_SEL_Plane_Cache_frees = 0x71,
+ DB_PERF_SEL_flush_expanded_stencil = 0x72,
+ DB_PERF_SEL_flush_compressed_stencil = 0x73,
+ DB_PERF_SEL_flush_single_stencil = 0x74,
+ DB_PERF_SEL_planes_flushed = 0x75,
+ DB_PERF_SEL_flush_1plane = 0x76,
+ DB_PERF_SEL_flush_2plane = 0x77,
+ DB_PERF_SEL_flush_3plane = 0x78,
+ DB_PERF_SEL_flush_4plane = 0x79,
+ DB_PERF_SEL_flush_5plane = 0x7a,
+ DB_PERF_SEL_flush_6plane = 0x7b,
+ DB_PERF_SEL_flush_7plane = 0x7c,
+ DB_PERF_SEL_flush_8plane = 0x7d,
+ DB_PERF_SEL_flush_9plane = 0x7e,
+ DB_PERF_SEL_flush_10plane = 0x7f,
+ DB_PERF_SEL_flush_11plane = 0x80,
+ DB_PERF_SEL_flush_12plane = 0x81,
+ DB_PERF_SEL_flush_13plane = 0x82,
+ DB_PERF_SEL_flush_14plane = 0x83,
+ DB_PERF_SEL_flush_15plane = 0x84,
+ DB_PERF_SEL_flush_16plane = 0x85,
+ DB_PERF_SEL_flush_expanded_z = 0x86,
+ DB_PERF_SEL_earlyZ_waiting_for_postZ_done = 0x87,
+ DB_PERF_SEL_reZ_waiting_for_postZ_done = 0x88,
+ DB_PERF_SEL_dk_tile_sends = 0x89,
+ DB_PERF_SEL_dk_tile_busy = 0x8a,
+ DB_PERF_SEL_dk_tile_quad_starves = 0x8b,
+ DB_PERF_SEL_dk_tile_stalls = 0x8c,
+ DB_PERF_SEL_dk_squad_sends = 0x8d,
+ DB_PERF_SEL_dk_squad_busy = 0x8e,
+ DB_PERF_SEL_dk_squad_stalls = 0x8f,
+ DB_PERF_SEL_Op_Pipe_Busy = 0x90,
+ DB_PERF_SEL_Op_Pipe_MC_Read_stall = 0x91,
+ DB_PERF_SEL_qc_busy = 0x92,
+ DB_PERF_SEL_qc_xfc = 0x93,
+ DB_PERF_SEL_qc_conflicts = 0x94,
+ DB_PERF_SEL_qc_full_stall = 0x95,
+ DB_PERF_SEL_qc_in_preZ_tile_stalls_postZ = 0x96,
+ DB_PERF_SEL_qc_in_postZ_tile_stalls_preZ = 0x97,
+ DB_PERF_SEL_tsc_insert_summarize_stall = 0x98,
+ DB_PERF_SEL_tl_busy = 0x99,
+ DB_PERF_SEL_tl_dtc_read_starved = 0x9a,
+ DB_PERF_SEL_tl_z_fetch_stall = 0x9b,
+ DB_PERF_SEL_tl_stencil_stall = 0x9c,
+ DB_PERF_SEL_tl_z_decompress_stall = 0x9d,
+ DB_PERF_SEL_tl_stencil_locked_stall = 0x9e,
+ DB_PERF_SEL_tl_events = 0x9f,
+ DB_PERF_SEL_tl_summarize_squads = 0xa0,
+ DB_PERF_SEL_tl_flush_expand_squads = 0xa1,
+ DB_PERF_SEL_tl_expand_squads = 0xa2,
+ DB_PERF_SEL_tl_preZ_squads = 0xa3,
+ DB_PERF_SEL_tl_postZ_squads = 0xa4,
+ DB_PERF_SEL_tl_preZ_noop_squads = 0xa5,
+ DB_PERF_SEL_tl_postZ_noop_squads = 0xa6,
+ DB_PERF_SEL_tl_tile_ops = 0xa7,
+ DB_PERF_SEL_tl_in_xfc = 0xa8,
+ DB_PERF_SEL_tl_in_single_stencil_expand_stall = 0xa9,
+ DB_PERF_SEL_tl_in_fast_z_stall = 0xaa,
+ DB_PERF_SEL_tl_out_xfc = 0xab,
+ DB_PERF_SEL_tl_out_squads = 0xac,
+ DB_PERF_SEL_zf_plane_multicycle = 0xad,
+ DB_PERF_SEL_PostZ_Samples_passing_Z = 0xae,
+ DB_PERF_SEL_PostZ_Samples_failing_Z = 0xaf,
+ DB_PERF_SEL_PostZ_Samples_failing_S = 0xb0,
+ DB_PERF_SEL_PreZ_Samples_passing_Z = 0xb1,
+ DB_PERF_SEL_PreZ_Samples_failing_Z = 0xb2,
+ DB_PERF_SEL_PreZ_Samples_failing_S = 0xb3,
+ DB_PERF_SEL_ts_tc_update_stall = 0xb4,
+ DB_PERF_SEL_sc_kick_start = 0xb5,
+ DB_PERF_SEL_sc_kick_end = 0xb6,
+ DB_PERF_SEL_clock_reg_active = 0xb7,
+ DB_PERF_SEL_clock_main_active = 0xb8,
+ DB_PERF_SEL_clock_mem_export_active = 0xb9,
+ DB_PERF_SEL_esr_ps_out_busy = 0xba,
+ DB_PERF_SEL_esr_ps_lqf_busy = 0xbb,
+ DB_PERF_SEL_esr_ps_lqf_stall = 0xbc,
+ DB_PERF_SEL_etr_out_send = 0xbd,
+ DB_PERF_SEL_etr_out_busy = 0xbe,
+ DB_PERF_SEL_etr_out_ltile_probe_fifo_full_stall = 0xbf,
+ DB_PERF_SEL_etr_out_cb_tile_stall = 0xc0,
+ DB_PERF_SEL_etr_out_esr_stall = 0xc1,
+ DB_PERF_SEL_esr_ps_sqq_busy = 0xc2,
+ DB_PERF_SEL_esr_ps_sqq_stall = 0xc3,
+ DB_PERF_SEL_esr_eot_fwd_busy = 0xc4,
+ DB_PERF_SEL_esr_eot_fwd_holding_squad = 0xc5,
+ DB_PERF_SEL_esr_eot_fwd_forward = 0xc6,
+ DB_PERF_SEL_esr_sqq_zi_busy = 0xc7,
+ DB_PERF_SEL_esr_sqq_zi_stall = 0xc8,
+ DB_PERF_SEL_postzl_sq_pt_busy = 0xc9,
+ DB_PERF_SEL_postzl_sq_pt_stall = 0xca,
+ DB_PERF_SEL_postzl_se_busy = 0xcb,
+ DB_PERF_SEL_postzl_se_stall = 0xcc,
+ DB_PERF_SEL_postzl_partial_launch = 0xcd,
+ DB_PERF_SEL_postzl_full_launch = 0xce,
+ DB_PERF_SEL_postzl_partial_waiting = 0xcf,
+ DB_PERF_SEL_postzl_tile_mem_stall = 0xd0,
+ DB_PERF_SEL_postzl_tile_init_stall = 0xd1,
+ DB_PEFF_SEL_prezl_tile_mem_stall = 0xd2,
+ DB_PERF_SEL_prezl_tile_init_stall = 0xd3,
+ DB_PERF_SEL_dtt_sm_clash_stall = 0xd4,
+ DB_PERF_SEL_dtt_sm_slot_stall = 0xd5,
+ DB_PERF_SEL_dtt_sm_miss_stall = 0xd6,
+ DB_PERF_SEL_mi_rdreq_busy = 0xd7,
+ DB_PERF_SEL_mi_rdreq_stall = 0xd8,
+ DB_PERF_SEL_mi_wrreq_busy = 0xd9,
+ DB_PERF_SEL_mi_wrreq_stall = 0xda,
+ DB_PERF_SEL_recomp_tile_to_1zplane_no_fastop = 0xdb,
+ DB_PERF_SEL_dkg_tile_rate_tile = 0xdc,
+ DB_PERF_SEL_prezl_src_in_sends = 0xdd,
+ DB_PERF_SEL_prezl_src_in_stall = 0xde,
+ DB_PERF_SEL_prezl_src_in_squads = 0xdf,
+ DB_PERF_SEL_prezl_src_in_squads_unrolled = 0xe0,
+ DB_PERF_SEL_prezl_src_in_tile_rate = 0xe1,
+ DB_PERF_SEL_prezl_src_in_tile_rate_unrolled = 0xe2,
+ DB_PERF_SEL_prezl_src_out_stall = 0xe3,
+ DB_PERF_SEL_postzl_src_in_sends = 0xe4,
+ DB_PERF_SEL_postzl_src_in_stall = 0xe5,
+ DB_PERF_SEL_postzl_src_in_squads = 0xe6,
+ DB_PERF_SEL_postzl_src_in_squads_unrolled = 0xe7,
+ DB_PERF_SEL_postzl_src_in_tile_rate = 0xe8,
+ DB_PERF_SEL_postzl_src_in_tile_rate_unrolled = 0xe9,
+ DB_PERF_SEL_postzl_src_out_stall = 0xea,
+ DB_PERF_SEL_esr_ps_src_in_sends = 0xeb,
+ DB_PERF_SEL_esr_ps_src_in_stall = 0xec,
+ DB_PERF_SEL_esr_ps_src_in_squads = 0xed,
+ DB_PERF_SEL_esr_ps_src_in_squads_unrolled = 0xee,
+ DB_PERF_SEL_esr_ps_src_in_tile_rate = 0xef,
+ DB_PERF_SEL_esr_ps_src_in_tile_rate_unrolled = 0xf0,
+ DB_PERF_SEL_esr_ps_src_in_tile_rate_unrolled_to_pixel_rate= 0xf1,
+ DB_PERF_SEL_esr_ps_src_out_stall = 0xf2,
+ DB_PERF_SEL_depth_bounds_qtiles_culled = 0xf3,
+ DB_PERF_SEL_PreZ_Samples_failing_DB = 0xf4,
+ DB_PERF_SEL_PostZ_Samples_failing_DB = 0xf5,
+ DB_PERF_SEL_flush_compressed = 0xf6,
+ DB_PERF_SEL_flush_plane_le4 = 0xf7,
+ DB_PERF_SEL_tiles_z_fully_summarized = 0xf8,
+ DB_PERF_SEL_tiles_stencil_fully_summarized = 0xf9,
+ DB_PERF_SEL_tiles_z_clear_on_expclear = 0xfa,
+ DB_PERF_SEL_tiles_s_clear_on_expclear = 0xfb,
+ DB_PERF_SEL_tiles_decomp_on_expclear = 0xfc,
+ DB_PERF_SEL_tiles_compressed_to_decompressed = 0xfd,
+ DB_PERF_SEL_Op_Pipe_Prez_Busy = 0xfe,
+ DB_PERF_SEL_Op_Pipe_Postz_Busy = 0xff,
+ DB_PERF_SEL_di_dt_stall = 0x100,
+ DB_PERF_SEL_DB_SC_quad_double_quad = 0x101,
+ DB_PERF_SEL_SX_DB_quad_export_quads = 0x102,
+ DB_PERF_SEL_SX_DB_quad_double_format = 0x103,
+ DB_PERF_SEL_SX_DB_quad_fast_format = 0x104,
+ DB_PERF_SEL_SX_DB_quad_slow_format = 0x105,
+ DB_PERF_SEL_DB_CB_lquad_export_quads = 0x106,
+ DB_PERF_SEL_DB_CB_lquad_double_format = 0x107,
+ DB_PERF_SEL_DB_CB_lquad_fast_format = 0x108,
+ DB_PERF_SEL_DB_CB_lquad_slow_format = 0x109,
+} PerfCounter_Vals;
+typedef enum RingCounterControl {
+ COUNTER_RING_SPLIT = 0x0,
+ COUNTER_RING_0 = 0x1,
+ COUNTER_RING_1 = 0x2,
+} RingCounterControl;
+typedef enum PixelPipeCounterId {
+ PIXEL_PIPE_OCCLUSION_COUNT_0 = 0x0,
+ PIXEL_PIPE_OCCLUSION_COUNT_1 = 0x1,
+ PIXEL_PIPE_OCCLUSION_COUNT_2 = 0x2,
+ PIXEL_PIPE_OCCLUSION_COUNT_3 = 0x3,
+ PIXEL_PIPE_SCREEN_MIN_EXTENTS_0 = 0x4,
+ PIXEL_PIPE_SCREEN_MAX_EXTENTS_0 = 0x5,
+ PIXEL_PIPE_SCREEN_MIN_EXTENTS_1 = 0x6,
+ PIXEL_PIPE_SCREEN_MAX_EXTENTS_1 = 0x7,
+} PixelPipeCounterId;
+typedef enum PixelPipeStride {
+ PIXEL_PIPE_STRIDE_32_BITS = 0x0,
+ PIXEL_PIPE_STRIDE_64_BITS = 0x1,
+ PIXEL_PIPE_STRIDE_128_BITS = 0x2,
+ PIXEL_PIPE_STRIDE_256_BITS = 0x3,
+} PixelPipeStride;
+typedef enum GB_EDC_DED_MODE {
+ GB_EDC_DED_MODE_LOG = 0x0,
+ GB_EDC_DED_MODE_HALT = 0x1,
+ GB_EDC_DED_MODE_INT_HALT = 0x2,
+} GB_EDC_DED_MODE;
+#define GB_TILING_CONFIG_TABLE_SIZE 0x20
+#define GB_TILING_CONFIG_MACROTABLE_SIZE 0x10
+typedef enum GRBM_PERF_SEL {
+ GRBM_PERF_SEL_COUNT = 0x0,
+ GRBM_PERF_SEL_USER_DEFINED = 0x1,
+ GRBM_PERF_SEL_GUI_ACTIVE = 0x2,
+ GRBM_PERF_SEL_CP_BUSY = 0x3,
+ GRBM_PERF_SEL_CP_COHER_BUSY = 0x4,
+ GRBM_PERF_SEL_CP_DMA_BUSY = 0x5,
+ GRBM_PERF_SEL_CB_BUSY = 0x6,
+ GRBM_PERF_SEL_DB_BUSY = 0x7,
+ GRBM_PERF_SEL_PA_BUSY = 0x8,
+ GRBM_PERF_SEL_SC_BUSY = 0x9,
+ GRBM_PERF_SEL_RESERVED_6 = 0xa,
+ GRBM_PERF_SEL_SPI_BUSY = 0xb,
+ GRBM_PERF_SEL_SX_BUSY = 0xc,
+ GRBM_PERF_SEL_TA_BUSY = 0xd,
+ GRBM_PERF_SEL_CB_CLEAN = 0xe,
+ GRBM_PERF_SEL_DB_CLEAN = 0xf,
+ GRBM_PERF_SEL_RESERVED_5 = 0x10,
+ GRBM_PERF_SEL_VGT_BUSY = 0x11,
+ GRBM_PERF_SEL_RESERVED_4 = 0x12,
+ GRBM_PERF_SEL_RESERVED_3 = 0x13,
+ GRBM_PERF_SEL_RESERVED_2 = 0x14,
+ GRBM_PERF_SEL_RESERVED_1 = 0x15,
+ GRBM_PERF_SEL_RESERVED_0 = 0x16,
+ GRBM_PERF_SEL_IA_BUSY = 0x17,
+ GRBM_PERF_SEL_IA_NO_DMA_BUSY = 0x18,
+ GRBM_PERF_SEL_GDS_BUSY = 0x19,
+ GRBM_PERF_SEL_BCI_BUSY = 0x1a,
+ GRBM_PERF_SEL_RLC_BUSY = 0x1b,
+ GRBM_PERF_SEL_TC_BUSY = 0x1c,
+ GRBM_PERF_SEL_CPG_BUSY = 0x1d,
+ GRBM_PERF_SEL_CPC_BUSY = 0x1e,
+ GRBM_PERF_SEL_CPF_BUSY = 0x1f,
+ GRBM_PERF_SEL_WD_BUSY = 0x20,
+ GRBM_PERF_SEL_WD_NO_DMA_BUSY = 0x21,
+} GRBM_PERF_SEL;
+typedef enum GRBM_SE0_PERF_SEL {
+ GRBM_SE0_PERF_SEL_COUNT = 0x0,
+ GRBM_SE0_PERF_SEL_USER_DEFINED = 0x1,
+ GRBM_SE0_PERF_SEL_CB_BUSY = 0x2,
+ GRBM_SE0_PERF_SEL_DB_BUSY = 0x3,
+ GRBM_SE0_PERF_SEL_SC_BUSY = 0x4,
+ GRBM_SE0_PERF_SEL_RESERVED_1 = 0x5,
+ GRBM_SE0_PERF_SEL_SPI_BUSY = 0x6,
+ GRBM_SE0_PERF_SEL_SX_BUSY = 0x7,
+ GRBM_SE0_PERF_SEL_TA_BUSY = 0x8,
+ GRBM_SE0_PERF_SEL_CB_CLEAN = 0x9,
+ GRBM_SE0_PERF_SEL_DB_CLEAN = 0xa,
+ GRBM_SE0_PERF_SEL_RESERVED_0 = 0xb,
+ GRBM_SE0_PERF_SEL_PA_BUSY = 0xc,
+ GRBM_SE0_PERF_SEL_VGT_BUSY = 0xd,
+ GRBM_SE0_PERF_SEL_BCI_BUSY = 0xe,
+} GRBM_SE0_PERF_SEL;
+typedef enum GRBM_SE1_PERF_SEL {
+ GRBM_SE1_PERF_SEL_COUNT = 0x0,
+ GRBM_SE1_PERF_SEL_USER_DEFINED = 0x1,
+ GRBM_SE1_PERF_SEL_CB_BUSY = 0x2,
+ GRBM_SE1_PERF_SEL_DB_BUSY = 0x3,
+ GRBM_SE1_PERF_SEL_SC_BUSY = 0x4,
+ GRBM_SE1_PERF_SEL_RESERVED_1 = 0x5,
+ GRBM_SE1_PERF_SEL_SPI_BUSY = 0x6,
+ GRBM_SE1_PERF_SEL_SX_BUSY = 0x7,
+ GRBM_SE1_PERF_SEL_TA_BUSY = 0x8,
+ GRBM_SE1_PERF_SEL_CB_CLEAN = 0x9,
+ GRBM_SE1_PERF_SEL_DB_CLEAN = 0xa,
+ GRBM_SE1_PERF_SEL_RESERVED_0 = 0xb,
+ GRBM_SE1_PERF_SEL_PA_BUSY = 0xc,
+ GRBM_SE1_PERF_SEL_VGT_BUSY = 0xd,
+ GRBM_SE1_PERF_SEL_BCI_BUSY = 0xe,
+} GRBM_SE1_PERF_SEL;
+typedef enum GRBM_SE2_PERF_SEL {
+ GRBM_SE2_PERF_SEL_COUNT = 0x0,
+ GRBM_SE2_PERF_SEL_USER_DEFINED = 0x1,
+ GRBM_SE2_PERF_SEL_CB_BUSY = 0x2,
+ GRBM_SE2_PERF_SEL_DB_BUSY = 0x3,
+ GRBM_SE2_PERF_SEL_SC_BUSY = 0x4,
+ GRBM_SE2_PERF_SEL_RESERVED_1 = 0x5,
+ GRBM_SE2_PERF_SEL_SPI_BUSY = 0x6,
+ GRBM_SE2_PERF_SEL_SX_BUSY = 0x7,
+ GRBM_SE2_PERF_SEL_TA_BUSY = 0x8,
+ GRBM_SE2_PERF_SEL_CB_CLEAN = 0x9,
+ GRBM_SE2_PERF_SEL_DB_CLEAN = 0xa,
+ GRBM_SE2_PERF_SEL_RESERVED_0 = 0xb,
+ GRBM_SE2_PERF_SEL_PA_BUSY = 0xc,
+ GRBM_SE2_PERF_SEL_VGT_BUSY = 0xd,
+ GRBM_SE2_PERF_SEL_BCI_BUSY = 0xe,
+} GRBM_SE2_PERF_SEL;
+typedef enum GRBM_SE3_PERF_SEL {
+ GRBM_SE3_PERF_SEL_COUNT = 0x0,
+ GRBM_SE3_PERF_SEL_USER_DEFINED = 0x1,
+ GRBM_SE3_PERF_SEL_CB_BUSY = 0x2,
+ GRBM_SE3_PERF_SEL_DB_BUSY = 0x3,
+ GRBM_SE3_PERF_SEL_SC_BUSY = 0x4,
+ GRBM_SE3_PERF_SEL_RESERVED_1 = 0x5,
+ GRBM_SE3_PERF_SEL_SPI_BUSY = 0x6,
+ GRBM_SE3_PERF_SEL_SX_BUSY = 0x7,
+ GRBM_SE3_PERF_SEL_TA_BUSY = 0x8,
+ GRBM_SE3_PERF_SEL_CB_CLEAN = 0x9,
+ GRBM_SE3_PERF_SEL_DB_CLEAN = 0xa,
+ GRBM_SE3_PERF_SEL_RESERVED_0 = 0xb,
+ GRBM_SE3_PERF_SEL_PA_BUSY = 0xc,
+ GRBM_SE3_PERF_SEL_VGT_BUSY = 0xd,
+ GRBM_SE3_PERF_SEL_BCI_BUSY = 0xe,
+} GRBM_SE3_PERF_SEL;
+typedef enum SU_PERFCNT_SEL {
+ PERF_PAPC_PASX_REQ = 0x0,
+ PERF_PAPC_PASX_DISABLE_PIPE = 0x1,
+ PERF_PAPC_PASX_FIRST_VECTOR = 0x2,
+ PERF_PAPC_PASX_SECOND_VECTOR = 0x3,
+ PERF_PAPC_PASX_FIRST_DEAD = 0x4,
+ PERF_PAPC_PASX_SECOND_DEAD = 0x5,
+ PERF_PAPC_PASX_VTX_KILL_DISCARD = 0x6,
+ PERF_PAPC_PASX_VTX_NAN_DISCARD = 0x7,
+ PERF_PAPC_PA_INPUT_PRIM = 0x8,
+ PERF_PAPC_PA_INPUT_NULL_PRIM = 0x9,
+ PERF_PAPC_PA_INPUT_EVENT_FLAG = 0xa,
+ PERF_PAPC_PA_INPUT_FIRST_PRIM_SLOT = 0xb,
+ PERF_PAPC_PA_INPUT_END_OF_PACKET = 0xc,
+ PERF_PAPC_PA_INPUT_EXTENDED_EVENT = 0xd,
+ PERF_PAPC_CLPR_CULL_PRIM = 0xe,
+ PERF_PAPC_CLPR_VVUCP_CULL_PRIM = 0xf,
+ PERF_PAPC_CLPR_VV_CULL_PRIM = 0x10,
+ PERF_PAPC_CLPR_UCP_CULL_PRIM = 0x11,
+ PERF_PAPC_CLPR_VTX_KILL_CULL_PRIM = 0x12,
+ PERF_PAPC_CLPR_VTX_NAN_CULL_PRIM = 0x13,
+ PERF_PAPC_CLPR_CULL_TO_NULL_PRIM = 0x14,
+ PERF_PAPC_CLPR_VVUCP_CLIP_PRIM = 0x15,
+ PERF_PAPC_CLPR_VV_CLIP_PRIM = 0x16,
+ PERF_PAPC_CLPR_UCP_CLIP_PRIM = 0x17,
+ PERF_PAPC_CLPR_POINT_CLIP_CANDIDATE = 0x18,
+ PERF_PAPC_CLPR_CLIP_PLANE_CNT_1 = 0x19,
+ PERF_PAPC_CLPR_CLIP_PLANE_CNT_2 = 0x1a,
+ PERF_PAPC_CLPR_CLIP_PLANE_CNT_3 = 0x1b,
+ PERF_PAPC_CLPR_CLIP_PLANE_CNT_4 = 0x1c,
+ PERF_PAPC_CLPR_CLIP_PLANE_CNT_5_8 = 0x1d,
+ PERF_PAPC_CLPR_CLIP_PLANE_CNT_9_12 = 0x1e,
+ PERF_PAPC_CLPR_CLIP_PLANE_NEAR = 0x1f,
+ PERF_PAPC_CLPR_CLIP_PLANE_FAR = 0x20,
+ PERF_PAPC_CLPR_CLIP_PLANE_LEFT = 0x21,
+ PERF_PAPC_CLPR_CLIP_PLANE_RIGHT = 0x22,
+ PERF_PAPC_CLPR_CLIP_PLANE_TOP = 0x23,
+ PERF_PAPC_CLPR_CLIP_PLANE_BOTTOM = 0x24,
+ PERF_PAPC_CLPR_GSC_KILL_CULL_PRIM = 0x25,
+ PERF_PAPC_CLPR_RASTER_KILL_CULL_PRIM = 0x26,
+ PERF_PAPC_CLSM_NULL_PRIM = 0x27,
+ PERF_PAPC_CLSM_TOTALLY_VISIBLE_PRIM = 0x28,
+ PERF_PAPC_CLSM_CULL_TO_NULL_PRIM = 0x29,
+ PERF_PAPC_CLSM_OUT_PRIM_CNT_1 = 0x2a,
+ PERF_PAPC_CLSM_OUT_PRIM_CNT_2 = 0x2b,
+ PERF_PAPC_CLSM_OUT_PRIM_CNT_3 = 0x2c,
+ PERF_PAPC_CLSM_OUT_PRIM_CNT_4 = 0x2d,
+ PERF_PAPC_CLSM_OUT_PRIM_CNT_5_8 = 0x2e,
+ PERF_PAPC_CLSM_OUT_PRIM_CNT_9_13 = 0x2f,
+ PERF_PAPC_CLIPGA_VTE_KILL_PRIM = 0x30,
+ PERF_PAPC_SU_INPUT_PRIM = 0x31,
+ PERF_PAPC_SU_INPUT_CLIP_PRIM = 0x32,
+ PERF_PAPC_SU_INPUT_NULL_PRIM = 0x33,
+ PERF_PAPC_SU_INPUT_PRIM_DUAL = 0x34,
+ PERF_PAPC_SU_INPUT_CLIP_PRIM_DUAL = 0x35,
+ PERF_PAPC_SU_ZERO_AREA_CULL_PRIM = 0x36,
+ PERF_PAPC_SU_BACK_FACE_CULL_PRIM = 0x37,
+ PERF_PAPC_SU_FRONT_FACE_CULL_PRIM = 0x38,
+ PERF_PAPC_SU_POLYMODE_FACE_CULL = 0x39,
+ PERF_PAPC_SU_POLYMODE_BACK_CULL = 0x3a,
+ PERF_PAPC_SU_POLYMODE_FRONT_CULL = 0x3b,
+ PERF_PAPC_SU_POLYMODE_INVALID_FILL = 0x3c,
+ PERF_PAPC_SU_OUTPUT_PRIM = 0x3d,
+ PERF_PAPC_SU_OUTPUT_CLIP_PRIM = 0x3e,
+ PERF_PAPC_SU_OUTPUT_NULL_PRIM = 0x3f,
+ PERF_PAPC_SU_OUTPUT_EVENT_FLAG = 0x40,
+ PERF_PAPC_SU_OUTPUT_FIRST_PRIM_SLOT = 0x41,
+ PERF_PAPC_SU_OUTPUT_END_OF_PACKET = 0x42,
+ PERF_PAPC_SU_OUTPUT_POLYMODE_FACE = 0x43,
+ PERF_PAPC_SU_OUTPUT_POLYMODE_BACK = 0x44,
+ PERF_PAPC_SU_OUTPUT_POLYMODE_FRONT = 0x45,
+ PERF_PAPC_SU_OUT_CLIP_POLYMODE_FACE = 0x46,
+ PERF_PAPC_SU_OUT_CLIP_POLYMODE_BACK = 0x47,
+ PERF_PAPC_SU_OUT_CLIP_POLYMODE_FRONT = 0x48,
+ PERF_PAPC_SU_OUTPUT_PRIM_DUAL = 0x49,
+ PERF_PAPC_SU_OUTPUT_CLIP_PRIM_DUAL = 0x4a,
+ PERF_PAPC_SU_OUTPUT_POLYMODE_DUAL = 0x4b,
+ PERF_PAPC_SU_OUTPUT_CLIP_POLYMODE_DUAL = 0x4c,
+ PERF_PAPC_PASX_REQ_IDLE = 0x4d,
+ PERF_PAPC_PASX_REQ_BUSY = 0x4e,
+ PERF_PAPC_PASX_REQ_STALLED = 0x4f,
+ PERF_PAPC_PASX_REC_IDLE = 0x50,
+ PERF_PAPC_PASX_REC_BUSY = 0x51,
+ PERF_PAPC_PASX_REC_STARVED_SX = 0x52,
+ PERF_PAPC_PASX_REC_STALLED = 0x53,
+ PERF_PAPC_PASX_REC_STALLED_POS_MEM = 0x54,
+ PERF_PAPC_PASX_REC_STALLED_CCGSM_IN = 0x55,
+ PERF_PAPC_CCGSM_IDLE = 0x56,
+ PERF_PAPC_CCGSM_BUSY = 0x57,
+ PERF_PAPC_CCGSM_STALLED = 0x58,
+ PERF_PAPC_CLPRIM_IDLE = 0x59,
+ PERF_PAPC_CLPRIM_BUSY = 0x5a,
+ PERF_PAPC_CLPRIM_STALLED = 0x5b,
+ PERF_PAPC_CLPRIM_STARVED_CCGSM = 0x5c,
+ PERF_PAPC_CLIPSM_IDLE = 0x5d,
+ PERF_PAPC_CLIPSM_BUSY = 0x5e,
+ PERF_PAPC_CLIPSM_WAIT_CLIP_VERT_ENGH = 0x5f,
+ PERF_PAPC_CLIPSM_WAIT_HIGH_PRI_SEQ = 0x60,
+ PERF_PAPC_CLIPSM_WAIT_CLIPGA = 0x61,
+ PERF_PAPC_CLIPSM_WAIT_AVAIL_VTE_CLIP = 0x62,
+ PERF_PAPC_CLIPSM_WAIT_CLIP_OUTSM = 0x63,
+ PERF_PAPC_CLIPGA_IDLE = 0x64,
+ PERF_PAPC_CLIPGA_BUSY = 0x65,
+ PERF_PAPC_CLIPGA_STARVED_VTE_CLIP = 0x66,
+ PERF_PAPC_CLIPGA_STALLED = 0x67,
+ PERF_PAPC_CLIP_IDLE = 0x68,
+ PERF_PAPC_CLIP_BUSY = 0x69,
+ PERF_PAPC_SU_IDLE = 0x6a,
+ PERF_PAPC_SU_BUSY = 0x6b,
+ PERF_PAPC_SU_STARVED_CLIP = 0x6c,
+ PERF_PAPC_SU_STALLED_SC = 0x6d,
+ PERF_PAPC_CL_DYN_SCLK_VLD = 0x6e,
+ PERF_PAPC_SU_DYN_SCLK_VLD = 0x6f,
+ PERF_PAPC_PA_REG_SCLK_VLD = 0x70,
+ PERF_PAPC_SU_MULTI_GPU_PRIM_FILTER_CULL = 0x71,
+ PERF_PAPC_PASX_SE0_REQ = 0x72,
+ PERF_PAPC_PASX_SE1_REQ = 0x73,
+ PERF_PAPC_PASX_SE0_FIRST_VECTOR = 0x74,
+ PERF_PAPC_PASX_SE0_SECOND_VECTOR = 0x75,
+ PERF_PAPC_PASX_SE1_FIRST_VECTOR = 0x76,
+ PERF_PAPC_PASX_SE1_SECOND_VECTOR = 0x77,
+ PERF_PAPC_SU_SE0_PRIM_FILTER_CULL = 0x78,
+ PERF_PAPC_SU_SE1_PRIM_FILTER_CULL = 0x79,
+ PERF_PAPC_SU_SE01_PRIM_FILTER_CULL = 0x7a,
+ PERF_PAPC_SU_SE0_OUTPUT_PRIM = 0x7b,
+ PERF_PAPC_SU_SE1_OUTPUT_PRIM = 0x7c,
+ PERF_PAPC_SU_SE01_OUTPUT_PRIM = 0x7d,
+ PERF_PAPC_SU_SE0_OUTPUT_NULL_PRIM = 0x7e,
+ PERF_PAPC_SU_SE1_OUTPUT_NULL_PRIM = 0x7f,
+ PERF_PAPC_SU_SE01_OUTPUT_NULL_PRIM = 0x80,
+ PERF_PAPC_SU_SE0_OUTPUT_FIRST_PRIM_SLOT = 0x81,
+ PERF_PAPC_SU_SE1_OUTPUT_FIRST_PRIM_SLOT = 0x82,
+ PERF_PAPC_SU_SE0_STALLED_SC = 0x83,
+ PERF_PAPC_SU_SE1_STALLED_SC = 0x84,
+ PERF_PAPC_SU_SE01_STALLED_SC = 0x85,
+ PERF_PAPC_CLSM_CLIPPING_PRIM = 0x86,
+ PERF_PAPC_SU_CULLED_PRIM = 0x87,
+ PERF_PAPC_SU_OUTPUT_EOPG = 0x88,
+ PERF_PAPC_SU_SE2_PRIM_FILTER_CULL = 0x89,
+ PERF_PAPC_SU_SE3_PRIM_FILTER_CULL = 0x8a,
+ PERF_PAPC_SU_SE2_OUTPUT_PRIM = 0x8b,
+ PERF_PAPC_SU_SE3_OUTPUT_PRIM = 0x8c,
+ PERF_PAPC_SU_SE2_OUTPUT_NULL_PRIM = 0x8d,
+ PERF_PAPC_SU_SE3_OUTPUT_NULL_PRIM = 0x8e,
+ PERF_PAPC_SU_SE0_OUTPUT_END_OF_PACKET = 0x8f,
+ PERF_PAPC_SU_SE1_OUTPUT_END_OF_PACKET = 0x90,
+ PERF_PAPC_SU_SE2_OUTPUT_END_OF_PACKET = 0x91,
+ PERF_PAPC_SU_SE3_OUTPUT_END_OF_PACKET = 0x92,
+ PERF_PAPC_SU_SE0_OUTPUT_EOPG = 0x93,
+ PERF_PAPC_SU_SE1_OUTPUT_EOPG = 0x94,
+ PERF_PAPC_SU_SE2_OUTPUT_EOPG = 0x95,
+ PERF_PAPC_SU_SE3_OUTPUT_EOPG = 0x96,
+ PERF_PAPC_SU_SE2_STALLED_SC = 0x97,
+ PERF_PAPC_SU_SE3_STALLED_SC = 0x98,
+} SU_PERFCNT_SEL;
+typedef enum SC_PERFCNT_SEL {
+ SC_SRPS_WINDOW_VALID = 0x0,
+ SC_PSSW_WINDOW_VALID = 0x1,
+ SC_TPQZ_WINDOW_VALID = 0x2,
+ SC_QZQP_WINDOW_VALID = 0x3,
+ SC_TRPK_WINDOW_VALID = 0x4,
+ SC_SRPS_WINDOW_VALID_BUSY = 0x5,
+ SC_PSSW_WINDOW_VALID_BUSY = 0x6,
+ SC_TPQZ_WINDOW_VALID_BUSY = 0x7,
+ SC_QZQP_WINDOW_VALID_BUSY = 0x8,
+ SC_TRPK_WINDOW_VALID_BUSY = 0x9,
+ SC_STARVED_BY_PA = 0xa,
+ SC_STALLED_BY_PRIMFIFO = 0xb,
+ SC_STALLED_BY_DB_TILE = 0xc,
+ SC_STARVED_BY_DB_TILE = 0xd,
+ SC_STALLED_BY_TILEORDERFIFO = 0xe,
+ SC_STALLED_BY_TILEFIFO = 0xf,
+ SC_STALLED_BY_DB_QUAD = 0x10,
+ SC_STARVED_BY_DB_QUAD = 0x11,
+ SC_STALLED_BY_QUADFIFO = 0x12,
+ SC_STALLED_BY_BCI = 0x13,
+ SC_STALLED_BY_SPI = 0x14,
+ SC_SCISSOR_DISCARD = 0x15,
+ SC_BB_DISCARD = 0x16,
+ SC_SUPERTILE_COUNT = 0x17,
+ SC_SUPERTILE_PER_PRIM_H0 = 0x18,
+ SC_SUPERTILE_PER_PRIM_H1 = 0x19,
+ SC_SUPERTILE_PER_PRIM_H2 = 0x1a,
+ SC_SUPERTILE_PER_PRIM_H3 = 0x1b,
+ SC_SUPERTILE_PER_PRIM_H4 = 0x1c,
+ SC_SUPERTILE_PER_PRIM_H5 = 0x1d,
+ SC_SUPERTILE_PER_PRIM_H6 = 0x1e,
+ SC_SUPERTILE_PER_PRIM_H7 = 0x1f,
+ SC_SUPERTILE_PER_PRIM_H8 = 0x20,
+ SC_SUPERTILE_PER_PRIM_H9 = 0x21,
+ SC_SUPERTILE_PER_PRIM_H10 = 0x22,
+ SC_SUPERTILE_PER_PRIM_H11 = 0x23,
+ SC_SUPERTILE_PER_PRIM_H12 = 0x24,
+ SC_SUPERTILE_PER_PRIM_H13 = 0x25,
+ SC_SUPERTILE_PER_PRIM_H14 = 0x26,
+ SC_SUPERTILE_PER_PRIM_H15 = 0x27,
+ SC_SUPERTILE_PER_PRIM_H16 = 0x28,
+ SC_TILE_PER_PRIM_H0 = 0x29,
+ SC_TILE_PER_PRIM_H1 = 0x2a,
+ SC_TILE_PER_PRIM_H2 = 0x2b,
+ SC_TILE_PER_PRIM_H3 = 0x2c,
+ SC_TILE_PER_PRIM_H4 = 0x2d,
+ SC_TILE_PER_PRIM_H5 = 0x2e,
+ SC_TILE_PER_PRIM_H6 = 0x2f,
+ SC_TILE_PER_PRIM_H7 = 0x30,
+ SC_TILE_PER_PRIM_H8 = 0x31,
+ SC_TILE_PER_PRIM_H9 = 0x32,
+ SC_TILE_PER_PRIM_H10 = 0x33,
+ SC_TILE_PER_PRIM_H11 = 0x34,
+ SC_TILE_PER_PRIM_H12 = 0x35,
+ SC_TILE_PER_PRIM_H13 = 0x36,
+ SC_TILE_PER_PRIM_H14 = 0x37,
+ SC_TILE_PER_PRIM_H15 = 0x38,
+ SC_TILE_PER_PRIM_H16 = 0x39,
+ SC_TILE_PER_SUPERTILE_H0 = 0x3a,
+ SC_TILE_PER_SUPERTILE_H1 = 0x3b,
+ SC_TILE_PER_SUPERTILE_H2 = 0x3c,
+ SC_TILE_PER_SUPERTILE_H3 = 0x3d,
+ SC_TILE_PER_SUPERTILE_H4 = 0x3e,
+ SC_TILE_PER_SUPERTILE_H5 = 0x3f,
+ SC_TILE_PER_SUPERTILE_H6 = 0x40,
+ SC_TILE_PER_SUPERTILE_H7 = 0x41,
+ SC_TILE_PER_SUPERTILE_H8 = 0x42,
+ SC_TILE_PER_SUPERTILE_H9 = 0x43,
+ SC_TILE_PER_SUPERTILE_H10 = 0x44,
+ SC_TILE_PER_SUPERTILE_H11 = 0x45,
+ SC_TILE_PER_SUPERTILE_H12 = 0x46,
+ SC_TILE_PER_SUPERTILE_H13 = 0x47,
+ SC_TILE_PER_SUPERTILE_H14 = 0x48,
+ SC_TILE_PER_SUPERTILE_H15 = 0x49,
+ SC_TILE_PER_SUPERTILE_H16 = 0x4a,
+ SC_TILE_PICKED_H1 = 0x4b,
+ SC_TILE_PICKED_H2 = 0x4c,
+ SC_TILE_PICKED_H3 = 0x4d,
+ SC_TILE_PICKED_H4 = 0x4e,
+ SC_QZ0_MULTI_GPU_TILE_DISCARD = 0x4f,
+ SC_QZ1_MULTI_GPU_TILE_DISCARD = 0x50,
+ SC_QZ2_MULTI_GPU_TILE_DISCARD = 0x51,
+ SC_QZ3_MULTI_GPU_TILE_DISCARD = 0x52,
+ SC_QZ0_TILE_COUNT = 0x53,
+ SC_QZ1_TILE_COUNT = 0x54,
+ SC_QZ2_TILE_COUNT = 0x55,
+ SC_QZ3_TILE_COUNT = 0x56,
+ SC_QZ0_TILE_COVERED_COUNT = 0x57,
+ SC_QZ1_TILE_COVERED_COUNT = 0x58,
+ SC_QZ2_TILE_COVERED_COUNT = 0x59,
+ SC_QZ3_TILE_COVERED_COUNT = 0x5a,
+ SC_QZ0_TILE_NOT_COVERED_COUNT = 0x5b,
+ SC_QZ1_TILE_NOT_COVERED_COUNT = 0x5c,
+ SC_QZ2_TILE_NOT_COVERED_COUNT = 0x5d,
+ SC_QZ3_TILE_NOT_COVERED_COUNT = 0x5e,
+ SC_QZ0_QUAD_PER_TILE_H0 = 0x5f,
+ SC_QZ0_QUAD_PER_TILE_H1 = 0x60,
+ SC_QZ0_QUAD_PER_TILE_H2 = 0x61,
+ SC_QZ0_QUAD_PER_TILE_H3 = 0x62,
+ SC_QZ0_QUAD_PER_TILE_H4 = 0x63,
+ SC_QZ0_QUAD_PER_TILE_H5 = 0x64,
+ SC_QZ0_QUAD_PER_TILE_H6 = 0x65,
+ SC_QZ0_QUAD_PER_TILE_H7 = 0x66,
+ SC_QZ0_QUAD_PER_TILE_H8 = 0x67,
+ SC_QZ0_QUAD_PER_TILE_H9 = 0x68,
+ SC_QZ0_QUAD_PER_TILE_H10 = 0x69,
+ SC_QZ0_QUAD_PER_TILE_H11 = 0x6a,
+ SC_QZ0_QUAD_PER_TILE_H12 = 0x6b,
+ SC_QZ0_QUAD_PER_TILE_H13 = 0x6c,
+ SC_QZ0_QUAD_PER_TILE_H14 = 0x6d,
+ SC_QZ0_QUAD_PER_TILE_H15 = 0x6e,
+ SC_QZ0_QUAD_PER_TILE_H16 = 0x6f,
+ SC_QZ1_QUAD_PER_TILE_H0 = 0x70,
+ SC_QZ1_QUAD_PER_TILE_H1 = 0x71,
+ SC_QZ1_QUAD_PER_TILE_H2 = 0x72,
+ SC_QZ1_QUAD_PER_TILE_H3 = 0x73,
+ SC_QZ1_QUAD_PER_TILE_H4 = 0x74,
+ SC_QZ1_QUAD_PER_TILE_H5 = 0x75,
+ SC_QZ1_QUAD_PER_TILE_H6 = 0x76,
+ SC_QZ1_QUAD_PER_TILE_H7 = 0x77,
+ SC_QZ1_QUAD_PER_TILE_H8 = 0x78,
+ SC_QZ1_QUAD_PER_TILE_H9 = 0x79,
+ SC_QZ1_QUAD_PER_TILE_H10 = 0x7a,
+ SC_QZ1_QUAD_PER_TILE_H11 = 0x7b,
+ SC_QZ1_QUAD_PER_TILE_H12 = 0x7c,
+ SC_QZ1_QUAD_PER_TILE_H13 = 0x7d,
+ SC_QZ1_QUAD_PER_TILE_H14 = 0x7e,
+ SC_QZ1_QUAD_PER_TILE_H15 = 0x7f,
+ SC_QZ1_QUAD_PER_TILE_H16 = 0x80,
+ SC_QZ2_QUAD_PER_TILE_H0 = 0x81,
+ SC_QZ2_QUAD_PER_TILE_H1 = 0x82,
+ SC_QZ2_QUAD_PER_TILE_H2 = 0x83,
+ SC_QZ2_QUAD_PER_TILE_H3 = 0x84,
+ SC_QZ2_QUAD_PER_TILE_H4 = 0x85,
+ SC_QZ2_QUAD_PER_TILE_H5 = 0x86,
+ SC_QZ2_QUAD_PER_TILE_H6 = 0x87,
+ SC_QZ2_QUAD_PER_TILE_H7 = 0x88,
+ SC_QZ2_QUAD_PER_TILE_H8 = 0x89,
+ SC_QZ2_QUAD_PER_TILE_H9 = 0x8a,
+ SC_QZ2_QUAD_PER_TILE_H10 = 0x8b,
+ SC_QZ2_QUAD_PER_TILE_H11 = 0x8c,
+ SC_QZ2_QUAD_PER_TILE_H12 = 0x8d,
+ SC_QZ2_QUAD_PER_TILE_H13 = 0x8e,
+ SC_QZ2_QUAD_PER_TILE_H14 = 0x8f,
+ SC_QZ2_QUAD_PER_TILE_H15 = 0x90,
+ SC_QZ2_QUAD_PER_TILE_H16 = 0x91,
+ SC_QZ3_QUAD_PER_TILE_H0 = 0x92,
+ SC_QZ3_QUAD_PER_TILE_H1 = 0x93,
+ SC_QZ3_QUAD_PER_TILE_H2 = 0x94,
+ SC_QZ3_QUAD_PER_TILE_H3 = 0x95,
+ SC_QZ3_QUAD_PER_TILE_H4 = 0x96,
+ SC_QZ3_QUAD_PER_TILE_H5 = 0x97,
+ SC_QZ3_QUAD_PER_TILE_H6 = 0x98,
+ SC_QZ3_QUAD_PER_TILE_H7 = 0x99,
+ SC_QZ3_QUAD_PER_TILE_H8 = 0x9a,
+ SC_QZ3_QUAD_PER_TILE_H9 = 0x9b,
+ SC_QZ3_QUAD_PER_TILE_H10 = 0x9c,
+ SC_QZ3_QUAD_PER_TILE_H11 = 0x9d,
+ SC_QZ3_QUAD_PER_TILE_H12 = 0x9e,
+ SC_QZ3_QUAD_PER_TILE_H13 = 0x9f,
+ SC_QZ3_QUAD_PER_TILE_H14 = 0xa0,
+ SC_QZ3_QUAD_PER_TILE_H15 = 0xa1,
+ SC_QZ3_QUAD_PER_TILE_H16 = 0xa2,
+ SC_QZ0_QUAD_COUNT = 0xa3,
+ SC_QZ1_QUAD_COUNT = 0xa4,
+ SC_QZ2_QUAD_COUNT = 0xa5,
+ SC_QZ3_QUAD_COUNT = 0xa6,
+ SC_P0_HIZ_TILE_COUNT = 0xa7,
+ SC_P1_HIZ_TILE_COUNT = 0xa8,
+ SC_P2_HIZ_TILE_COUNT = 0xa9,
+ SC_P3_HIZ_TILE_COUNT = 0xaa,
+ SC_P0_HIZ_QUAD_PER_TILE_H0 = 0xab,
+ SC_P0_HIZ_QUAD_PER_TILE_H1 = 0xac,
+ SC_P0_HIZ_QUAD_PER_TILE_H2 = 0xad,
+ SC_P0_HIZ_QUAD_PER_TILE_H3 = 0xae,
+ SC_P0_HIZ_QUAD_PER_TILE_H4 = 0xaf,
+ SC_P0_HIZ_QUAD_PER_TILE_H5 = 0xb0,
+ SC_P0_HIZ_QUAD_PER_TILE_H6 = 0xb1,
+ SC_P0_HIZ_QUAD_PER_TILE_H7 = 0xb2,
+ SC_P0_HIZ_QUAD_PER_TILE_H8 = 0xb3,
+ SC_P0_HIZ_QUAD_PER_TILE_H9 = 0xb4,
+ SC_P0_HIZ_QUAD_PER_TILE_H10 = 0xb5,
+ SC_P0_HIZ_QUAD_PER_TILE_H11 = 0xb6,
+ SC_P0_HIZ_QUAD_PER_TILE_H12 = 0xb7,
+ SC_P0_HIZ_QUAD_PER_TILE_H13 = 0xb8,
+ SC_P0_HIZ_QUAD_PER_TILE_H14 = 0xb9,
+ SC_P0_HIZ_QUAD_PER_TILE_H15 = 0xba,
+ SC_P0_HIZ_QUAD_PER_TILE_H16 = 0xbb,
+ SC_P1_HIZ_QUAD_PER_TILE_H0 = 0xbc,
+ SC_P1_HIZ_QUAD_PER_TILE_H1 = 0xbd,
+ SC_P1_HIZ_QUAD_PER_TILE_H2 = 0xbe,
+ SC_P1_HIZ_QUAD_PER_TILE_H3 = 0xbf,
+ SC_P1_HIZ_QUAD_PER_TILE_H4 = 0xc0,
+ SC_P1_HIZ_QUAD_PER_TILE_H5 = 0xc1,
+ SC_P1_HIZ_QUAD_PER_TILE_H6 = 0xc2,
+ SC_P1_HIZ_QUAD_PER_TILE_H7 = 0xc3,
+ SC_P1_HIZ_QUAD_PER_TILE_H8 = 0xc4,
+ SC_P1_HIZ_QUAD_PER_TILE_H9 = 0xc5,
+ SC_P1_HIZ_QUAD_PER_TILE_H10 = 0xc6,
+ SC_P1_HIZ_QUAD_PER_TILE_H11 = 0xc7,
+ SC_P1_HIZ_QUAD_PER_TILE_H12 = 0xc8,
+ SC_P1_HIZ_QUAD_PER_TILE_H13 = 0xc9,
+ SC_P1_HIZ_QUAD_PER_TILE_H14 = 0xca,
+ SC_P1_HIZ_QUAD_PER_TILE_H15 = 0xcb,
+ SC_P1_HIZ_QUAD_PER_TILE_H16 = 0xcc,
+ SC_P2_HIZ_QUAD_PER_TILE_H0 = 0xcd,
+ SC_P2_HIZ_QUAD_PER_TILE_H1 = 0xce,
+ SC_P2_HIZ_QUAD_PER_TILE_H2 = 0xcf,
+ SC_P2_HIZ_QUAD_PER_TILE_H3 = 0xd0,
+ SC_P2_HIZ_QUAD_PER_TILE_H4 = 0xd1,
+ SC_P2_HIZ_QUAD_PER_TILE_H5 = 0xd2,
+ SC_P2_HIZ_QUAD_PER_TILE_H6 = 0xd3,
+ SC_P2_HIZ_QUAD_PER_TILE_H7 = 0xd4,
+ SC_P2_HIZ_QUAD_PER_TILE_H8 = 0xd5,
+ SC_P2_HIZ_QUAD_PER_TILE_H9 = 0xd6,
+ SC_P2_HIZ_QUAD_PER_TILE_H10 = 0xd7,
+ SC_P2_HIZ_QUAD_PER_TILE_H11 = 0xd8,
+ SC_P2_HIZ_QUAD_PER_TILE_H12 = 0xd9,
+ SC_P2_HIZ_QUAD_PER_TILE_H13 = 0xda,
+ SC_P2_HIZ_QUAD_PER_TILE_H14 = 0xdb,
+ SC_P2_HIZ_QUAD_PER_TILE_H15 = 0xdc,
+ SC_P2_HIZ_QUAD_PER_TILE_H16 = 0xdd,
+ SC_P3_HIZ_QUAD_PER_TILE_H0 = 0xde,
+ SC_P3_HIZ_QUAD_PER_TILE_H1 = 0xdf,
+ SC_P3_HIZ_QUAD_PER_TILE_H2 = 0xe0,
+ SC_P3_HIZ_QUAD_PER_TILE_H3 = 0xe1,
+ SC_P3_HIZ_QUAD_PER_TILE_H4 = 0xe2,
+ SC_P3_HIZ_QUAD_PER_TILE_H5 = 0xe3,
+ SC_P3_HIZ_QUAD_PER_TILE_H6 = 0xe4,
+ SC_P3_HIZ_QUAD_PER_TILE_H7 = 0xe5,
+ SC_P3_HIZ_QUAD_PER_TILE_H8 = 0xe6,
+ SC_P3_HIZ_QUAD_PER_TILE_H9 = 0xe7,
+ SC_P3_HIZ_QUAD_PER_TILE_H10 = 0xe8,
+ SC_P3_HIZ_QUAD_PER_TILE_H11 = 0xe9,
+ SC_P3_HIZ_QUAD_PER_TILE_H12 = 0xea,
+ SC_P3_HIZ_QUAD_PER_TILE_H13 = 0xeb,
+ SC_P3_HIZ_QUAD_PER_TILE_H14 = 0xec,
+ SC_P3_HIZ_QUAD_PER_TILE_H15 = 0xed,
+ SC_P3_HIZ_QUAD_PER_TILE_H16 = 0xee,
+ SC_P0_HIZ_QUAD_COUNT = 0xef,
+ SC_P1_HIZ_QUAD_COUNT = 0xf0,
+ SC_P2_HIZ_QUAD_COUNT = 0xf1,
+ SC_P3_HIZ_QUAD_COUNT = 0xf2,
+ SC_P0_DETAIL_QUAD_COUNT = 0xf3,
+ SC_P1_DETAIL_QUAD_COUNT = 0xf4,
+ SC_P2_DETAIL_QUAD_COUNT = 0xf5,
+ SC_P3_DETAIL_QUAD_COUNT = 0xf6,
+ SC_P0_DETAIL_QUAD_WITH_1_PIX = 0xf7,
+ SC_P0_DETAIL_QUAD_WITH_2_PIX = 0xf8,
+ SC_P0_DETAIL_QUAD_WITH_3_PIX = 0xf9,
+ SC_P0_DETAIL_QUAD_WITH_4_PIX = 0xfa,
+ SC_P1_DETAIL_QUAD_WITH_1_PIX = 0xfb,
+ SC_P1_DETAIL_QUAD_WITH_2_PIX = 0xfc,
+ SC_P1_DETAIL_QUAD_WITH_3_PIX = 0xfd,
+ SC_P1_DETAIL_QUAD_WITH_4_PIX = 0xfe,
+ SC_P2_DETAIL_QUAD_WITH_1_PIX = 0xff,
+ SC_P2_DETAIL_QUAD_WITH_2_PIX = 0x100,
+ SC_P2_DETAIL_QUAD_WITH_3_PIX = 0x101,
+ SC_P2_DETAIL_QUAD_WITH_4_PIX = 0x102,
+ SC_P3_DETAIL_QUAD_WITH_1_PIX = 0x103,
+ SC_P3_DETAIL_QUAD_WITH_2_PIX = 0x104,
+ SC_P3_DETAIL_QUAD_WITH_3_PIX = 0x105,
+ SC_P3_DETAIL_QUAD_WITH_4_PIX = 0x106,
+ SC_EARLYZ_QUAD_COUNT = 0x107,
+ SC_EARLYZ_QUAD_WITH_1_PIX = 0x108,
+ SC_EARLYZ_QUAD_WITH_2_PIX = 0x109,
+ SC_EARLYZ_QUAD_WITH_3_PIX = 0x10a,
+ SC_EARLYZ_QUAD_WITH_4_PIX = 0x10b,
+ SC_PKR_QUAD_PER_ROW_H1 = 0x10c,
+ SC_PKR_QUAD_PER_ROW_H2 = 0x10d,
+ SC_PKR_4X2_QUAD_SPLIT = 0x10e,
+ SC_PKR_4X2_FILL_QUAD = 0x10f,
+ SC_PKR_END_OF_VECTOR = 0x110,
+ SC_PKR_CONTROL_XFER = 0x111,
+ SC_PKR_DBHANG_FORCE_EOV = 0x112,
+ SC_REG_SCLK_BUSY = 0x113,
+ SC_GRP0_DYN_SCLK_BUSY = 0x114,
+ SC_GRP1_DYN_SCLK_BUSY = 0x115,
+ SC_GRP2_DYN_SCLK_BUSY = 0x116,
+ SC_GRP3_DYN_SCLK_BUSY = 0x117,
+ SC_GRP4_DYN_SCLK_BUSY = 0x118,
+ SC_PA0_SC_DATA_FIFO_RD = 0x119,
+ SC_PA0_SC_DATA_FIFO_WE = 0x11a,
+ SC_PA1_SC_DATA_FIFO_RD = 0x11b,
+ SC_PA1_SC_DATA_FIFO_WE = 0x11c,
+ SC_PS_ARB_XFC_ALL_EVENT_OR_PRIM_CYCLES = 0x11d,
+ SC_PS_ARB_XFC_ONLY_PRIM_CYCLES = 0x11e,
+ SC_PS_ARB_XFC_ONLY_ONE_INC_PER_PRIM = 0x11f,
+ SC_PS_ARB_STALLED_FROM_BELOW = 0x120,
+ SC_PS_ARB_STARVED_FROM_ABOVE = 0x121,
+ SC_PS_ARB_SC_BUSY = 0x122,
+ SC_PS_ARB_PA_SC_BUSY = 0x123,
+ SC_PA2_SC_DATA_FIFO_RD = 0x124,
+ SC_PA2_SC_DATA_FIFO_WE = 0x125,
+ SC_PA3_SC_DATA_FIFO_RD = 0x126,
+ SC_PA3_SC_DATA_FIFO_WE = 0x127,
+ SC_PA_SC_DEALLOC_0_0_WE = 0x128,
+ SC_PA_SC_DEALLOC_0_1_WE = 0x129,
+ SC_PA_SC_DEALLOC_1_0_WE = 0x12a,
+ SC_PA_SC_DEALLOC_1_1_WE = 0x12b,
+ SC_PA_SC_DEALLOC_2_0_WE = 0x12c,
+ SC_PA_SC_DEALLOC_2_1_WE = 0x12d,
+ SC_PA_SC_DEALLOC_3_0_WE = 0x12e,
+ SC_PA_SC_DEALLOC_3_1_WE = 0x12f,
+ SC_PA0_SC_EOP_WE = 0x130,
+ SC_PA0_SC_EOPG_WE = 0x131,
+ SC_PA0_SC_EVENT_WE = 0x132,
+ SC_PA1_SC_EOP_WE = 0x133,
+ SC_PA1_SC_EOPG_WE = 0x134,
+ SC_PA1_SC_EVENT_WE = 0x135,
+ SC_PA2_SC_EOP_WE = 0x136,
+ SC_PA2_SC_EOPG_WE = 0x137,
+ SC_PA2_SC_EVENT_WE = 0x138,
+ SC_PA3_SC_EOP_WE = 0x139,
+ SC_PA3_SC_EOPG_WE = 0x13a,
+ SC_PA3_SC_EVENT_WE = 0x13b,
+ SC_PS_ARB_OOO_THRESHOLD_SWITCH_TO_DESIRED_FIFO = 0x13c,
+ SC_PS_ARB_OOO_FIFO_EMPTY_SWITCH = 0x13d,
+ SC_PS_ARB_NULL_PRIM_BUBBLE_POP = 0x13e,
+ SC_PS_ARB_EOP_POP_SYNC_POP = 0x13f,
+ SC_PS_ARB_EVENT_SYNC_POP = 0x140,
+ SC_SC_PS_ENG_MULTICYCLE_BUBBLE = 0x141,
+ SC_PA0_SC_FPOV_WE = 0x142,
+ SC_PA1_SC_FPOV_WE = 0x143,
+ SC_PA2_SC_FPOV_WE = 0x144,
+ SC_PA3_SC_FPOV_WE = 0x145,
+ SC_PA0_SC_LPOV_WE = 0x146,
+ SC_PA1_SC_LPOV_WE = 0x147,
+ SC_PA2_SC_LPOV_WE = 0x148,
+ SC_PA3_SC_LPOV_WE = 0x149,
+ SC_SC_SPI_DEALLOC_0_0 = 0x14a,
+ SC_SC_SPI_DEALLOC_0_1 = 0x14b,
+ SC_SC_SPI_DEALLOC_0_2 = 0x14c,
+ SC_SC_SPI_DEALLOC_1_0 = 0x14d,
+ SC_SC_SPI_DEALLOC_1_1 = 0x14e,
+ SC_SC_SPI_DEALLOC_1_2 = 0x14f,
+ SC_SC_SPI_DEALLOC_2_0 = 0x150,
+ SC_SC_SPI_DEALLOC_2_1 = 0x151,
+ SC_SC_SPI_DEALLOC_2_2 = 0x152,
+ SC_SC_SPI_DEALLOC_3_0 = 0x153,
+ SC_SC_SPI_DEALLOC_3_1 = 0x154,
+ SC_SC_SPI_DEALLOC_3_2 = 0x155,
+ SC_SC_SPI_FPOV_0 = 0x156,
+ SC_SC_SPI_FPOV_1 = 0x157,
+ SC_SC_SPI_FPOV_2 = 0x158,
+ SC_SC_SPI_FPOV_3 = 0x159,
+ SC_SC_SPI_EVENT = 0x15a,
+ SC_PS_TS_EVENT_FIFO_PUSH = 0x15b,
+ SC_PS_TS_EVENT_FIFO_POP = 0x15c,
+ SC_PS_CTX_DONE_FIFO_PUSH = 0x15d,
+ SC_PS_CTX_DONE_FIFO_POP = 0x15e,
+ SC_MULTICYCLE_BUBBLE_FREEZE = 0x15f,
+ SC_EOP_SYNC_WINDOW = 0x160,
+ SC_PA0_SC_NULL_WE = 0x161,
+ SC_PA0_SC_NULL_DEALLOC_WE = 0x162,
+ SC_PA0_SC_DATA_FIFO_EOPG_RD = 0x163,
+ SC_PA0_SC_DATA_FIFO_EOP_RD = 0x164,
+ SC_PA0_SC_DEALLOC_0_RD = 0x165,
+ SC_PA0_SC_DEALLOC_1_RD = 0x166,
+ SC_PA1_SC_DATA_FIFO_EOPG_RD = 0x167,
+ SC_PA1_SC_DATA_FIFO_EOP_RD = 0x168,
+ SC_PA1_SC_DEALLOC_0_RD = 0x169,
+ SC_PA1_SC_DEALLOC_1_RD = 0x16a,
+ SC_PA1_SC_NULL_WE = 0x16b,
+ SC_PA1_SC_NULL_DEALLOC_WE = 0x16c,
+ SC_PA2_SC_DATA_FIFO_EOPG_RD = 0x16d,
+ SC_PA2_SC_DATA_FIFO_EOP_RD = 0x16e,
+ SC_PA2_SC_DEALLOC_0_RD = 0x16f,
+ SC_PA2_SC_DEALLOC_1_RD = 0x170,
+ SC_PA2_SC_NULL_WE = 0x171,
+ SC_PA2_SC_NULL_DEALLOC_WE = 0x172,
+ SC_PA3_SC_DATA_FIFO_EOPG_RD = 0x173,
+ SC_PA3_SC_DATA_FIFO_EOP_RD = 0x174,
+ SC_PA3_SC_DEALLOC_0_RD = 0x175,
+ SC_PA3_SC_DEALLOC_1_RD = 0x176,
+ SC_PA3_SC_NULL_WE = 0x177,
+ SC_PA3_SC_NULL_DEALLOC_WE = 0x178,
+ SC_PS_PA0_SC_FIFO_EMPTY = 0x179,
+ SC_PS_PA0_SC_FIFO_FULL = 0x17a,
+ SC_PA0_PS_DATA_SEND = 0x17b,
+ SC_PS_PA1_SC_FIFO_EMPTY = 0x17c,
+ SC_PS_PA1_SC_FIFO_FULL = 0x17d,
+ SC_PA1_PS_DATA_SEND = 0x17e,
+ SC_PS_PA2_SC_FIFO_EMPTY = 0x17f,
+ SC_PS_PA2_SC_FIFO_FULL = 0x180,
+ SC_PA2_PS_DATA_SEND = 0x181,
+ SC_PS_PA3_SC_FIFO_EMPTY = 0x182,
+ SC_PS_PA3_SC_FIFO_FULL = 0x183,
+ SC_PA3_PS_DATA_SEND = 0x184,
+ SC_BUSY_PROCESSING_MULTICYCLE_PRIM = 0x185,
+ SC_BUSY_CNT_NOT_ZERO = 0x186,
+ SC_BM_BUSY = 0x187,
+ SC_BACKEND_BUSY = 0x188,
+ SC_SCF_SCB_INTERFACE_BUSY = 0x189,
+ SC_SCB_BUSY = 0x18a,
+ SC_STARVED_BY_PA_WITH_UNSELECTED_PA_NOT_EMPTY = 0x18b,
+ SC_STARVED_BY_PA_WITH_UNSELECTED_PA_FULL = 0x18c,
+} SC_PERFCNT_SEL;
+typedef enum SePairXsel {
+ RASTER_CONFIG_SE_PAIR_XSEL_8_WIDE_TILE = 0x0,
+ RASTER_CONFIG_SE_PAIR_XSEL_16_WIDE_TILE = 0x1,
+ RASTER_CONFIG_SE_PAIR_XSEL_32_WIDE_TILE = 0x2,
+ RASTER_CONFIG_SE_PAIR_XSEL_64_WIDE_TILE = 0x3,
+} SePairXsel;
+typedef enum SePairYsel {
+ RASTER_CONFIG_SE_PAIR_YSEL_8_WIDE_TILE = 0x0,
+ RASTER_CONFIG_SE_PAIR_YSEL_16_WIDE_TILE = 0x1,
+ RASTER_CONFIG_SE_PAIR_YSEL_32_WIDE_TILE = 0x2,
+ RASTER_CONFIG_SE_PAIR_YSEL_64_WIDE_TILE = 0x3,
+} SePairYsel;
+typedef enum SePairMap {
+ RASTER_CONFIG_SE_PAIR_MAP_0 = 0x0,
+ RASTER_CONFIG_SE_PAIR_MAP_1 = 0x1,
+ RASTER_CONFIG_SE_PAIR_MAP_2 = 0x2,
+ RASTER_CONFIG_SE_PAIR_MAP_3 = 0x3,
+} SePairMap;
+typedef enum SeXsel {
+ RASTER_CONFIG_SE_XSEL_8_WIDE_TILE = 0x0,
+ RASTER_CONFIG_SE_XSEL_16_WIDE_TILE = 0x1,
+ RASTER_CONFIG_SE_XSEL_32_WIDE_TILE = 0x2,
+ RASTER_CONFIG_SE_XSEL_64_WIDE_TILE = 0x3,
+} SeXsel;
+typedef enum SeYsel {
+ RASTER_CONFIG_SE_YSEL_8_WIDE_TILE = 0x0,
+ RASTER_CONFIG_SE_YSEL_16_WIDE_TILE = 0x1,
+ RASTER_CONFIG_SE_YSEL_32_WIDE_TILE = 0x2,
+ RASTER_CONFIG_SE_YSEL_64_WIDE_TILE = 0x3,
+} SeYsel;
+typedef enum SeMap {
+ RASTER_CONFIG_SE_MAP_0 = 0x0,
+ RASTER_CONFIG_SE_MAP_1 = 0x1,
+ RASTER_CONFIG_SE_MAP_2 = 0x2,
+ RASTER_CONFIG_SE_MAP_3 = 0x3,
+} SeMap;
+typedef enum ScXsel {
+ RASTER_CONFIG_SC_XSEL_8_WIDE_TILE = 0x0,
+ RASTER_CONFIG_SC_XSEL_16_WIDE_TILE = 0x1,
+ RASTER_CONFIG_SC_XSEL_32_WIDE_TILE = 0x2,
+ RASTER_CONFIG_SC_XSEL_64_WIDE_TILE = 0x3,
+} ScXsel;
+typedef enum ScYsel {
+ RASTER_CONFIG_SC_YSEL_8_WIDE_TILE = 0x0,
+ RASTER_CONFIG_SC_YSEL_16_WIDE_TILE = 0x1,
+ RASTER_CONFIG_SC_YSEL_32_WIDE_TILE = 0x2,
+ RASTER_CONFIG_SC_YSEL_64_WIDE_TILE = 0x3,
+} ScYsel;
+typedef enum ScMap {
+ RASTER_CONFIG_SC_MAP_0 = 0x0,
+ RASTER_CONFIG_SC_MAP_1 = 0x1,
+ RASTER_CONFIG_SC_MAP_2 = 0x2,
+ RASTER_CONFIG_SC_MAP_3 = 0x3,
+} ScMap;
+typedef enum PkrXsel2 {
+ RASTER_CONFIG_PKR_XSEL2_0 = 0x0,
+ RASTER_CONFIG_PKR_XSEL2_1 = 0x1,
+ RASTER_CONFIG_PKR_XSEL2_2 = 0x2,
+ RASTER_CONFIG_PKR_XSEL2_3 = 0x3,
+} PkrXsel2;
+typedef enum PkrXsel {
+ RASTER_CONFIG_PKR_XSEL_0 = 0x0,
+ RASTER_CONFIG_PKR_XSEL_1 = 0x1,
+ RASTER_CONFIG_PKR_XSEL_2 = 0x2,
+ RASTER_CONFIG_PKR_XSEL_3 = 0x3,
+} PkrXsel;
+typedef enum PkrYsel {
+ RASTER_CONFIG_PKR_YSEL_0 = 0x0,
+ RASTER_CONFIG_PKR_YSEL_1 = 0x1,
+ RASTER_CONFIG_PKR_YSEL_2 = 0x2,
+ RASTER_CONFIG_PKR_YSEL_3 = 0x3,
+} PkrYsel;
+typedef enum PkrMap {
+ RASTER_CONFIG_PKR_MAP_0 = 0x0,
+ RASTER_CONFIG_PKR_MAP_1 = 0x1,
+ RASTER_CONFIG_PKR_MAP_2 = 0x2,
+ RASTER_CONFIG_PKR_MAP_3 = 0x3,
+} PkrMap;
+typedef enum RbXsel {
+ RASTER_CONFIG_RB_XSEL_0 = 0x0,
+ RASTER_CONFIG_RB_XSEL_1 = 0x1,
+} RbXsel;
+typedef enum RbYsel {
+ RASTER_CONFIG_RB_YSEL_0 = 0x0,
+ RASTER_CONFIG_RB_YSEL_1 = 0x1,
+} RbYsel;
+typedef enum RbXsel2 {
+ RASTER_CONFIG_RB_XSEL2_0 = 0x0,
+ RASTER_CONFIG_RB_XSEL2_1 = 0x1,
+ RASTER_CONFIG_RB_XSEL2_2 = 0x2,
+ RASTER_CONFIG_RB_XSEL2_3 = 0x3,
+} RbXsel2;
+typedef enum RbMap {
+ RASTER_CONFIG_RB_MAP_0 = 0x0,
+ RASTER_CONFIG_RB_MAP_1 = 0x1,
+ RASTER_CONFIG_RB_MAP_2 = 0x2,
+ RASTER_CONFIG_RB_MAP_3 = 0x3,
+} RbMap;
+typedef enum CSDATA_TYPE {
+ CSDATA_TYPE_TG = 0x0,
+ CSDATA_TYPE_STATE = 0x1,
+ CSDATA_TYPE_EVENT = 0x2,
+ CSDATA_TYPE_PRIVATE = 0x3,
+} CSDATA_TYPE;
+#define CSDATA_TYPE_WIDTH 0x2
+#define CSDATA_ADDR_WIDTH 0x7
+#define CSDATA_DATA_WIDTH 0x20
+typedef enum SPI_SAMPLE_CNTL {
+ CENTROIDS_ONLY = 0x0,
+ CENTERS_ONLY = 0x1,
+ CENTROIDS_AND_CENTERS = 0x2,
+ UNDEF = 0x3,
+} SPI_SAMPLE_CNTL;
+typedef enum SPI_FOG_MODE {
+ SPI_FOG_NONE = 0x0,
+ SPI_FOG_EXP = 0x1,
+ SPI_FOG_EXP2 = 0x2,
+ SPI_FOG_LINEAR = 0x3,
+} SPI_FOG_MODE;
+typedef enum SPI_PNT_SPRITE_OVERRIDE {
+ SPI_PNT_SPRITE_SEL_0 = 0x0,
+ SPI_PNT_SPRITE_SEL_1 = 0x1,
+ SPI_PNT_SPRITE_SEL_S = 0x2,
+ SPI_PNT_SPRITE_SEL_T = 0x3,
+ SPI_PNT_SPRITE_SEL_NONE = 0x4,
+} SPI_PNT_SPRITE_OVERRIDE;
+typedef enum SPI_PERFCNT_SEL {
+ SPI_PERF_VS_WINDOW_VALID = 0x0,
+ SPI_PERF_VS_BUSY = 0x1,
+ SPI_PERF_VS_FIRST_WAVE = 0x2,
+ SPI_PERF_VS_LAST_WAVE = 0x3,
+ SPI_PERF_VS_LSHS_DEALLOC = 0x4,
+ SPI_PERF_VS_PC_STALL = 0x5,
+ SPI_PERF_VS_POS0_STALL = 0x6,
+ SPI_PERF_VS_POS1_STALL = 0x7,
+ SPI_PERF_VS_CRAWLER_STALL = 0x8,
+ SPI_PERF_VS_EVENT_WAVE = 0x9,
+ SPI_PERF_VS_WAVE = 0xa,
+ SPI_PERF_VS_PERS_UPD_FULL0 = 0xb,
+ SPI_PERF_VS_PERS_UPD_FULL1 = 0xc,
+ SPI_PERF_VS_LATE_ALLOC_FULL = 0xd,
+ SPI_PERF_VS_FIRST_SUBGRP = 0xe,
+ SPI_PERF_VS_LAST_SUBGRP = 0xf,
+ SPI_PERF_GS_WINDOW_VALID = 0x10,
+ SPI_PERF_GS_BUSY = 0x11,
+ SPI_PERF_GS_CRAWLER_STALL = 0x12,
+ SPI_PERF_GS_EVENT_WAVE = 0x13,
+ SPI_PERF_GS_WAVE = 0x14,
+ SPI_PERF_GS_PERS_UPD_FULL0 = 0x15,
+ SPI_PERF_GS_PERS_UPD_FULL1 = 0x16,
+ SPI_PERF_GS_FIRST_SUBGRP = 0x17,
+ SPI_PERF_GS_LAST_SUBGRP = 0x18,
+ SPI_PERF_ES_WINDOW_VALID = 0x19,
+ SPI_PERF_ES_BUSY = 0x1a,
+ SPI_PERF_ES_CRAWLER_STALL = 0x1b,
+ SPI_PERF_ES_FIRST_WAVE = 0x1c,
+ SPI_PERF_ES_LAST_WAVE = 0x1d,
+ SPI_PERF_ES_LSHS_DEALLOC = 0x1e,
+ SPI_PERF_ES_EVENT_WAVE = 0x1f,
+ SPI_PERF_ES_WAVE = 0x20,
+ SPI_PERF_ES_PERS_UPD_FULL0 = 0x21,
+ SPI_PERF_ES_PERS_UPD_FULL1 = 0x22,
+ SPI_PERF_ES_FIRST_SUBGRP = 0x23,
+ SPI_PERF_ES_LAST_SUBGRP = 0x24,
+ SPI_PERF_HS_WINDOW_VALID = 0x25,
+ SPI_PERF_HS_BUSY = 0x26,
+ SPI_PERF_HS_CRAWLER_STALL = 0x27,
+ SPI_PERF_HS_FIRST_WAVE = 0x28,
+ SPI_PERF_HS_LAST_WAVE = 0x29,
+ SPI_PERF_HS_LSHS_DEALLOC = 0x2a,
+ SPI_PERF_HS_EVENT_WAVE = 0x2b,
+ SPI_PERF_HS_WAVE = 0x2c,
+ SPI_PERF_HS_PERS_UPD_FULL0 = 0x2d,
+ SPI_PERF_HS_PERS_UPD_FULL1 = 0x2e,
+ SPI_PERF_LS_WINDOW_VALID = 0x2f,
+ SPI_PERF_LS_BUSY = 0x30,
+ SPI_PERF_LS_CRAWLER_STALL = 0x31,
+ SPI_PERF_LS_FIRST_WAVE = 0x32,
+ SPI_PERF_LS_LAST_WAVE = 0x33,
+ SPI_PERF_OFFCHIP_LDS_STALL_LS = 0x34,
+ SPI_PERF_LS_EVENT_WAVE = 0x35,
+ SPI_PERF_LS_WAVE = 0x36,
+ SPI_PERF_LS_PERS_UPD_FULL0 = 0x37,
+ SPI_PERF_LS_PERS_UPD_FULL1 = 0x38,
+ SPI_PERF_CSG_WINDOW_VALID = 0x39,
+ SPI_PERF_CSG_BUSY = 0x3a,
+ SPI_PERF_CSG_NUM_THREADGROUPS = 0x3b,
+ SPI_PERF_CSG_CRAWLER_STALL = 0x3c,
+ SPI_PERF_CSG_EVENT_WAVE = 0x3d,
+ SPI_PERF_CSG_WAVE = 0x3e,
+ SPI_PERF_CSN_WINDOW_VALID = 0x3f,
+ SPI_PERF_CSN_BUSY = 0x40,
+ SPI_PERF_CSN_NUM_THREADGROUPS = 0x41,
+ SPI_PERF_CSN_CRAWLER_STALL = 0x42,
+ SPI_PERF_CSN_EVENT_WAVE = 0x43,
+ SPI_PERF_CSN_WAVE = 0x44,
+ SPI_PERF_PS_CTL_WINDOW_VALID = 0x45,
+ SPI_PERF_PS_CTL_BUSY = 0x46,
+ SPI_PERF_PS_CTL_ACTIVE = 0x47,
+ SPI_PERF_PS_CTL_DEALLOC_BIN0 = 0x48,
+ SPI_PERF_PS_CTL_FPOS_BIN1_STALL = 0x49,
+ SPI_PERF_PS_CTL_EVENT_WAVE = 0x4a,
+ SPI_PERF_PS_CTL_WAVE = 0x4b,
+ SPI_PERF_PS_CTL_OPT_WAVE = 0x4c,
+ SPI_PERF_PS_CTL_PASS_BIN0 = 0x4d,
+ SPI_PERF_PS_CTL_PASS_BIN1 = 0x4e,
+ SPI_PERF_PS_CTL_FPOS_BIN2 = 0x4f,
+ SPI_PERF_PS_CTL_PRIM_BIN0 = 0x50,
+ SPI_PERF_PS_CTL_PRIM_BIN1 = 0x51,
+ SPI_PERF_PS_CTL_CNF_BIN2 = 0x52,
+ SPI_PERF_PS_CTL_CNF_BIN3 = 0x53,
+ SPI_PERF_PS_CTL_CRAWLER_STALL = 0x54,
+ SPI_PERF_PS_CTL_LDS_RES_FULL = 0x55,
+ SPI_PERF_PS_PERS_UPD_FULL0 = 0x56,
+ SPI_PERF_PS_PERS_UPD_FULL1 = 0x57,
+ SPI_PERF_PIX_ALLOC_PEND_CNT = 0x58,
+ SPI_PERF_PIX_ALLOC_SCB_STALL = 0x59,
+ SPI_PERF_PIX_ALLOC_DB0_STALL = 0x5a,
+ SPI_PERF_PIX_ALLOC_DB1_STALL = 0x5b,
+ SPI_PERF_PIX_ALLOC_DB2_STALL = 0x5c,
+ SPI_PERF_PIX_ALLOC_DB3_STALL = 0x5d,
+ SPI_PERF_LDS0_PC_VALID = 0x5e,
+ SPI_PERF_LDS1_PC_VALID = 0x5f,
+ SPI_PERF_RA_PIPE_REQ_BIN2 = 0x60,
+ SPI_PERF_RA_TASK_REQ_BIN3 = 0x61,
+ SPI_PERF_RA_WR_CTL_FULL = 0x62,
+ SPI_PERF_RA_REQ_NO_ALLOC = 0x63,
+ SPI_PERF_RA_REQ_NO_ALLOC_PS = 0x64,
+ SPI_PERF_RA_REQ_NO_ALLOC_VS = 0x65,
+ SPI_PERF_RA_REQ_NO_ALLOC_GS = 0x66,
+ SPI_PERF_RA_REQ_NO_ALLOC_ES = 0x67,
+ SPI_PERF_RA_REQ_NO_ALLOC_HS = 0x68,
+ SPI_PERF_RA_REQ_NO_ALLOC_LS = 0x69,
+ SPI_PERF_RA_REQ_NO_ALLOC_CSG = 0x6a,
+ SPI_PERF_RA_REQ_NO_ALLOC_CSN = 0x6b,
+ SPI_PERF_RA_RES_STALL_PS = 0x6c,
+ SPI_PERF_RA_RES_STALL_VS = 0x6d,
+ SPI_PERF_RA_RES_STALL_GS = 0x6e,
+ SPI_PERF_RA_RES_STALL_ES = 0x6f,
+ SPI_PERF_RA_RES_STALL_HS = 0x70,
+ SPI_PERF_RA_RES_STALL_LS = 0x71,
+ SPI_PERF_RA_RES_STALL_CSG = 0x72,
+ SPI_PERF_RA_RES_STALL_CSN = 0x73,
+ SPI_PERF_RA_TMP_STALL_PS = 0x74,
+ SPI_PERF_RA_TMP_STALL_VS = 0x75,
+ SPI_PERF_RA_TMP_STALL_GS = 0x76,
+ SPI_PERF_RA_TMP_STALL_ES = 0x77,
+ SPI_PERF_RA_TMP_STALL_HS = 0x78,
+ SPI_PERF_RA_TMP_STALL_LS = 0x79,
+ SPI_PERF_RA_TMP_STALL_CSG = 0x7a,
+ SPI_PERF_RA_TMP_STALL_CSN = 0x7b,
+ SPI_PERF_RA_WAVE_SIMD_FULL_PS = 0x7c,
+ SPI_PERF_RA_WAVE_SIMD_FULL_VS = 0x7d,
+ SPI_PERF_RA_WAVE_SIMD_FULL_GS = 0x7e,
+ SPI_PERF_RA_WAVE_SIMD_FULL_ES = 0x7f,
+ SPI_PERF_RA_WAVE_SIMD_FULL_HS = 0x80,
+ SPI_PERF_RA_WAVE_SIMD_FULL_LS = 0x81,
+ SPI_PERF_RA_WAVE_SIMD_FULL_CSG = 0x82,
+ SPI_PERF_RA_WAVE_SIMD_FULL_CSN = 0x83,
+ SPI_PERF_RA_VGPR_SIMD_FULL_PS = 0x84,
+ SPI_PERF_RA_VGPR_SIMD_FULL_VS = 0x85,
+ SPI_PERF_RA_VGPR_SIMD_FULL_GS = 0x86,
+ SPI_PERF_RA_VGPR_SIMD_FULL_ES = 0x87,
+ SPI_PERF_RA_VGPR_SIMD_FULL_HS = 0x88,
+ SPI_PERF_RA_VGPR_SIMD_FULL_LS = 0x89,
+ SPI_PERF_RA_VGPR_SIMD_FULL_CSG = 0x8a,
+ SPI_PERF_RA_VGPR_SIMD_FULL_CSN = 0x8b,
+ SPI_PERF_RA_SGPR_SIMD_FULL_PS = 0x8c,
+ SPI_PERF_RA_SGPR_SIMD_FULL_VS = 0x8d,
+ SPI_PERF_RA_SGPR_SIMD_FULL_GS = 0x8e,
+ SPI_PERF_RA_SGPR_SIMD_FULL_ES = 0x8f,
+ SPI_PERF_RA_SGPR_SIMD_FULL_HS = 0x90,
+ SPI_PERF_RA_SGPR_SIMD_FULL_LS = 0x91,
+ SPI_PERF_RA_SGPR_SIMD_FULL_CSG = 0x92,
+ SPI_PERF_RA_SGPR_SIMD_FULL_CSN = 0x93,
+ SPI_PERF_RA_LDS_CU_FULL_PS = 0x94,
+ SPI_PERF_RA_LDS_CU_FULL_LS = 0x95,
+ SPI_PERF_RA_LDS_CU_FULL_ES = 0x96,
+ SPI_PERF_RA_LDS_CU_FULL_CSG = 0x97,
+ SPI_PERF_RA_LDS_CU_FULL_CSN = 0x98,
+ SPI_PERF_RA_BAR_CU_FULL_HS = 0x99,
+ SPI_PERF_RA_BAR_CU_FULL_CSG = 0x9a,
+ SPI_PERF_RA_BAR_CU_FULL_CSN = 0x9b,
+ SPI_PERF_RA_BULKY_CU_FULL_CSG = 0x9c,
+ SPI_PERF_RA_BULKY_CU_FULL_CSN = 0x9d,
+ SPI_PERF_RA_TGLIM_CU_FULL_CSG = 0x9e,
+ SPI_PERF_RA_TGLIM_CU_FULL_CSN = 0x9f,
+ SPI_PERF_RA_WVLIM_STALL_PS = 0xa0,
+ SPI_PERF_RA_WVLIM_STALL_VS = 0xa1,
+ SPI_PERF_RA_WVLIM_STALL_GS = 0xa2,
+ SPI_PERF_RA_WVLIM_STALL_ES = 0xa3,
+ SPI_PERF_RA_WVLIM_STALL_HS = 0xa4,
+ SPI_PERF_RA_WVLIM_STALL_LS = 0xa5,
+ SPI_PERF_RA_WVLIM_STALL_CSG = 0xa6,
+ SPI_PERF_RA_WVLIM_STALL_CSN = 0xa7,
+ SPI_PERF_RA_PS_LOCK_NA = 0xa8,
+ SPI_PERF_RA_VS_LOCK = 0xa9,
+ SPI_PERF_RA_GS_LOCK = 0xaa,
+ SPI_PERF_RA_ES_LOCK = 0xab,
+ SPI_PERF_RA_HS_LOCK = 0xac,
+ SPI_PERF_RA_LS_LOCK = 0xad,
+ SPI_PERF_RA_CSG_LOCK = 0xae,
+ SPI_PERF_RA_CSN_LOCK = 0xaf,
+ SPI_PERF_RA_RSV_UPD = 0xb0,
+ SPI_PERF_EXP_ARB_COL_CNT = 0xb1,
+ SPI_PERF_EXP_ARB_PAR_CNT = 0xb2,
+ SPI_PERF_EXP_ARB_POS_CNT = 0xb3,
+ SPI_PERF_EXP_ARB_GDS_CNT = 0xb4,
+ SPI_PERF_CLKGATE_BUSY_STALL = 0xb5,
+ SPI_PERF_CLKGATE_ACTIVE_STALL = 0xb6,
+ SPI_PERF_CLKGATE_ALL_CLOCKS_ON = 0xb7,
+ SPI_PERF_CLKGATE_CGTT_DYN_ON = 0xb8,
+ SPI_PERF_CLKGATE_CGTT_REG_ON = 0xb9,
+ SPI_PERF_NUM_VS_POS_EXPORTS = 0xba,
+ SPI_PERF_NUM_VS_PARAM_EXPORTS = 0xbb,
+ SPI_PERF_NUM_PS_COL_EXPORTS = 0xbc,
+ SPI_PERF_ES_GRP_FIFO_FULL = 0xbd,
+ SPI_PERF_GS_GRP_FIFO_FULL = 0xbe,
+ SPI_PERF_HS_GRP_FIFO_FULL = 0xbf,
+ SPI_PERF_LS_GRP_FIFO_FULL = 0xc0,
+ SPI_PERF_VS_ALLOC_CNT = 0xc1,
+ SPI_PERF_VS_LATE_ALLOC_ACCUM = 0xc2,
+ SPI_PERF_PC_ALLOC_CNT = 0xc3,
+ SPI_PERF_PC_ALLOC_ACCUM = 0xc4,
+} SPI_PERFCNT_SEL;
+typedef enum SPI_SHADER_FORMAT {
+ SPI_SHADER_NONE = 0x0,
+ SPI_SHADER_1COMP = 0x1,
+ SPI_SHADER_2COMP = 0x2,
+ SPI_SHADER_4COMPRESS = 0x3,
+ SPI_SHADER_4COMP = 0x4,
+} SPI_SHADER_FORMAT;
+typedef enum SPI_SHADER_EX_FORMAT {
+ SPI_SHADER_ZERO = 0x0,
+ SPI_SHADER_32_R = 0x1,
+ SPI_SHADER_32_GR = 0x2,
+ SPI_SHADER_32_AR = 0x3,
+ SPI_SHADER_FP16_ABGR = 0x4,
+ SPI_SHADER_UNORM16_ABGR = 0x5,
+ SPI_SHADER_SNORM16_ABGR = 0x6,
+ SPI_SHADER_UINT16_ABGR = 0x7,
+ SPI_SHADER_SINT16_ABGR = 0x8,
+ SPI_SHADER_32_ABGR = 0x9,
+} SPI_SHADER_EX_FORMAT;
+typedef enum CLKGATE_SM_MODE {
+ ON_SEQ = 0x0,
+ OFF_SEQ = 0x1,
+ PROG_SEQ = 0x2,
+ READ_SEQ = 0x3,
+ SM_MODE_RESERVED = 0x4,
+} CLKGATE_SM_MODE;
+typedef enum CLKGATE_BASE_MODE {
+ MULT_8 = 0x0,
+ MULT_16 = 0x1,
+} CLKGATE_BASE_MODE;
+typedef enum SQ_TEX_CLAMP {
+ SQ_TEX_WRAP = 0x0,
+ SQ_TEX_MIRROR = 0x1,
+ SQ_TEX_CLAMP_LAST_TEXEL = 0x2,
+ SQ_TEX_MIRROR_ONCE_LAST_TEXEL = 0x3,
+ SQ_TEX_CLAMP_HALF_BORDER = 0x4,
+ SQ_TEX_MIRROR_ONCE_HALF_BORDER = 0x5,
+ SQ_TEX_CLAMP_BORDER = 0x6,
+ SQ_TEX_MIRROR_ONCE_BORDER = 0x7,
+} SQ_TEX_CLAMP;
+typedef enum SQ_TEX_XY_FILTER {
+ SQ_TEX_XY_FILTER_POINT = 0x0,
+ SQ_TEX_XY_FILTER_BILINEAR = 0x1,
+ SQ_TEX_XY_FILTER_ANISO_POINT = 0x2,
+ SQ_TEX_XY_FILTER_ANISO_BILINEAR = 0x3,
+} SQ_TEX_XY_FILTER;
+typedef enum SQ_TEX_Z_FILTER {
+ SQ_TEX_Z_FILTER_NONE = 0x0,
+ SQ_TEX_Z_FILTER_POINT = 0x1,
+ SQ_TEX_Z_FILTER_LINEAR = 0x2,
+} SQ_TEX_Z_FILTER;
+typedef enum SQ_TEX_MIP_FILTER {
+ SQ_TEX_MIP_FILTER_NONE = 0x0,
+ SQ_TEX_MIP_FILTER_POINT = 0x1,
+ SQ_TEX_MIP_FILTER_LINEAR = 0x2,
+ SQ_TEX_MIP_FILTER_POINT_ANISO_ADJ = 0x3,
+} SQ_TEX_MIP_FILTER;
+typedef enum SQ_TEX_ANISO_RATIO {
+ SQ_TEX_ANISO_RATIO_1 = 0x0,
+ SQ_TEX_ANISO_RATIO_2 = 0x1,
+ SQ_TEX_ANISO_RATIO_4 = 0x2,
+ SQ_TEX_ANISO_RATIO_8 = 0x3,
+ SQ_TEX_ANISO_RATIO_16 = 0x4,
+} SQ_TEX_ANISO_RATIO;
+typedef enum SQ_TEX_DEPTH_COMPARE {
+ SQ_TEX_DEPTH_COMPARE_NEVER = 0x0,
+ SQ_TEX_DEPTH_COMPARE_LESS = 0x1,
+ SQ_TEX_DEPTH_COMPARE_EQUAL = 0x2,
+ SQ_TEX_DEPTH_COMPARE_LESSEQUAL = 0x3,
+ SQ_TEX_DEPTH_COMPARE_GREATER = 0x4,
+ SQ_TEX_DEPTH_COMPARE_NOTEQUAL = 0x5,
+ SQ_TEX_DEPTH_COMPARE_GREATEREQUAL = 0x6,
+ SQ_TEX_DEPTH_COMPARE_ALWAYS = 0x7,
+} SQ_TEX_DEPTH_COMPARE;
+typedef enum SQ_TEX_BORDER_COLOR {
+ SQ_TEX_BORDER_COLOR_TRANS_BLACK = 0x0,
+ SQ_TEX_BORDER_COLOR_OPAQUE_BLACK = 0x1,
+ SQ_TEX_BORDER_COLOR_OPAQUE_WHITE = 0x2,
+ SQ_TEX_BORDER_COLOR_REGISTER = 0x3,
+} SQ_TEX_BORDER_COLOR;
+typedef enum SQ_RSRC_BUF_TYPE {
+ SQ_RSRC_BUF = 0x0,
+ SQ_RSRC_BUF_RSVD_1 = 0x1,
+ SQ_RSRC_BUF_RSVD_2 = 0x2,
+ SQ_RSRC_BUF_RSVD_3 = 0x3,
+} SQ_RSRC_BUF_TYPE;
+typedef enum SQ_RSRC_IMG_TYPE {
+ SQ_RSRC_IMG_RSVD_0 = 0x0,
+ SQ_RSRC_IMG_RSVD_1 = 0x1,
+ SQ_RSRC_IMG_RSVD_2 = 0x2,
+ SQ_RSRC_IMG_RSVD_3 = 0x3,
+ SQ_RSRC_IMG_RSVD_4 = 0x4,
+ SQ_RSRC_IMG_RSVD_5 = 0x5,
+ SQ_RSRC_IMG_RSVD_6 = 0x6,
+ SQ_RSRC_IMG_RSVD_7 = 0x7,
+ SQ_RSRC_IMG_1D = 0x8,
+ SQ_RSRC_IMG_2D = 0x9,
+ SQ_RSRC_IMG_3D = 0xa,
+ SQ_RSRC_IMG_CUBE = 0xb,
+ SQ_RSRC_IMG_1D_ARRAY = 0xc,
+ SQ_RSRC_IMG_2D_ARRAY = 0xd,
+ SQ_RSRC_IMG_2D_MSAA = 0xe,
+ SQ_RSRC_IMG_2D_MSAA_ARRAY = 0xf,
+} SQ_RSRC_IMG_TYPE;
+typedef enum SQ_RSRC_FLAT_TYPE {
+ SQ_RSRC_FLAT_RSVD_0 = 0x0,
+ SQ_RSRC_FLAT = 0x1,
+ SQ_RSRC_FLAT_RSVD_2 = 0x2,
+ SQ_RSRC_FLAT_RSVD_3 = 0x3,
+} SQ_RSRC_FLAT_TYPE;
+typedef enum SQ_IMG_FILTER_TYPE {
+ SQ_IMG_FILTER_MODE_BLEND = 0x0,
+ SQ_IMG_FILTER_MODE_MIN = 0x1,
+ SQ_IMG_FILTER_MODE_MAX = 0x2,
+} SQ_IMG_FILTER_TYPE;
+typedef enum SQ_SEL_XYZW01 {
+ SQ_SEL_0 = 0x0,
+ SQ_SEL_1 = 0x1,
+ SQ_SEL_RESERVED_0 = 0x2,
+ SQ_SEL_RESERVED_1 = 0x3,
+ SQ_SEL_X = 0x4,
+ SQ_SEL_Y = 0x5,
+ SQ_SEL_Z = 0x6,
+ SQ_SEL_W = 0x7,
+} SQ_SEL_XYZW01;
+typedef enum SQ_WAVE_TYPE {
+ SQ_WAVE_TYPE_PS = 0x0,
+ SQ_WAVE_TYPE_VS = 0x1,
+ SQ_WAVE_TYPE_GS = 0x2,
+ SQ_WAVE_TYPE_ES = 0x3,
+ SQ_WAVE_TYPE_HS = 0x4,
+ SQ_WAVE_TYPE_LS = 0x5,
+ SQ_WAVE_TYPE_CS = 0x6,
+ SQ_WAVE_TYPE_PS1 = 0x7,
+} SQ_WAVE_TYPE;
+typedef enum SQ_THREAD_TRACE_TOKEN_TYPE {
+ SQ_THREAD_TRACE_TOKEN_MISC = 0x0,
+ SQ_THREAD_TRACE_TOKEN_TIMESTAMP = 0x1,
+ SQ_THREAD_TRACE_TOKEN_REG = 0x2,
+ SQ_THREAD_TRACE_TOKEN_WAVE_START = 0x3,
+ SQ_THREAD_TRACE_TOKEN_WAVE_ALLOC = 0x4,
+ SQ_THREAD_TRACE_TOKEN_REG_CSPRIV = 0x5,
+ SQ_THREAD_TRACE_TOKEN_WAVE_END = 0x6,
+ SQ_THREAD_TRACE_TOKEN_EVENT = 0x7,
+ SQ_THREAD_TRACE_TOKEN_EVENT_CS = 0x8,
+ SQ_THREAD_TRACE_TOKEN_EVENT_GFX1 = 0x9,
+ SQ_THREAD_TRACE_TOKEN_INST = 0xa,
+ SQ_THREAD_TRACE_TOKEN_INST_PC = 0xb,
+ SQ_THREAD_TRACE_TOKEN_INST_USERDATA = 0xc,
+ SQ_THREAD_TRACE_TOKEN_ISSUE = 0xd,
+ SQ_THREAD_TRACE_TOKEN_PERF = 0xe,
+ SQ_THREAD_TRACE_TOKEN_REG_CS = 0xf,
+} SQ_THREAD_TRACE_TOKEN_TYPE;
+typedef enum SQ_THREAD_TRACE_MISC_TOKEN_TYPE {
+ SQ_THREAD_TRACE_MISC_TOKEN_TIME = 0x0,
+ SQ_THREAD_TRACE_MISC_TOKEN_TIME_RESET = 0x1,
+ SQ_THREAD_TRACE_MISC_TOKEN_PACKET_LOST = 0x2,
+ SQ_THREAD_TRACE_MISC_TOKEN_SURF_SYNC = 0x3,
+ SQ_THREAD_TRACE_MISC_TOKEN_TTRACE_STALL_BEGIN = 0x4,
+ SQ_THREAD_TRACE_MISC_TOKEN_TTRACE_STALL_END = 0x5,
+ SQ_THREAD_TRACE_MISC_TOKEN_SAVECTX = 0x6,
+ SQ_THREAD_TRACE_MISC_TOKEN_SHOOT_DOWN = 0x7,
+} SQ_THREAD_TRACE_MISC_TOKEN_TYPE;
+typedef enum SQ_THREAD_TRACE_INST_TYPE {
+ SQ_THREAD_TRACE_INST_TYPE_SMEM_RD = 0x0,
+ SQ_THREAD_TRACE_INST_TYPE_SALU_32 = 0x1,
+ SQ_THREAD_TRACE_INST_TYPE_VMEM_RD = 0x2,
+ SQ_THREAD_TRACE_INST_TYPE_VMEM_WR = 0x3,
+ SQ_THREAD_TRACE_INST_TYPE_FLAT_WR = 0x4,
+ SQ_THREAD_TRACE_INST_TYPE_VALU_32 = 0x5,
+ SQ_THREAD_TRACE_INST_TYPE_LDS = 0x6,
+ SQ_THREAD_TRACE_INST_TYPE_PC = 0x7,
+ SQ_THREAD_TRACE_INST_TYPE_EXPREQ_GDS = 0x8,
+ SQ_THREAD_TRACE_INST_TYPE_EXPREQ_GFX = 0x9,
+ SQ_THREAD_TRACE_INST_TYPE_EXPGNT_PAR_COL = 0xa,
+ SQ_THREAD_TRACE_INST_TYPE_EXPGNT_POS_GDS = 0xb,
+ SQ_THREAD_TRACE_INST_TYPE_JUMP = 0xc,
+ SQ_THREAD_TRACE_INST_TYPE_NEXT = 0xd,
+ SQ_THREAD_TRACE_INST_TYPE_FLAT_RD = 0xe,
+ SQ_THREAD_TRACE_INST_TYPE_OTHER_MSG = 0xf,
+ SQ_THREAD_TRACE_INST_TYPE_SMEM_WR = 0x10,
+ SQ_THREAD_TRACE_INST_TYPE_SALU_64 = 0x11,
+ SQ_THREAD_TRACE_INST_TYPE_VALU_64 = 0x12,
+ SQ_THREAD_TRACE_INST_TYPE_SMEM_RD_REPLAY = 0x13,
+ SQ_THREAD_TRACE_INST_TYPE_SMEM_WR_REPLAY = 0x14,
+ SQ_THREAD_TRACE_INST_TYPE_VMEM_RD_REPLAY = 0x15,
+ SQ_THREAD_TRACE_INST_TYPE_VMEM_WR_REPLAY = 0x16,
+ SQ_THREAD_TRACE_INST_TYPE_FLAT_RD_REPLAY = 0x17,
+ SQ_THREAD_TRACE_INST_TYPE_FLAT_WR_REPLAY = 0x18,
+} SQ_THREAD_TRACE_INST_TYPE;
+typedef enum SQ_THREAD_TRACE_REG_TYPE {
+ SQ_THREAD_TRACE_REG_TYPE_EVENT = 0x0,
+ SQ_THREAD_TRACE_REG_TYPE_DRAW = 0x1,
+ SQ_THREAD_TRACE_REG_TYPE_DISPATCH = 0x2,
+ SQ_THREAD_TRACE_REG_TYPE_USERDATA = 0x3,
+ SQ_THREAD_TRACE_REG_TYPE_MARKER = 0x4,
+ SQ_THREAD_TRACE_REG_TYPE_GFXDEC = 0x5,
+ SQ_THREAD_TRACE_REG_TYPE_SHDEC = 0x6,
+ SQ_THREAD_TRACE_REG_TYPE_OTHER = 0x7,
+} SQ_THREAD_TRACE_REG_TYPE;
+typedef enum SQ_THREAD_TRACE_REG_OP {
+ SQ_THREAD_TRACE_REG_OP_READ = 0x0,
+ SQ_THREAD_TRACE_REG_OP_WRITE = 0x1,
+} SQ_THREAD_TRACE_REG_OP;
+typedef enum SQ_THREAD_TRACE_MODE_SEL {
+ SQ_THREAD_TRACE_MODE_OFF = 0x0,
+ SQ_THREAD_TRACE_MODE_ON = 0x1,
+} SQ_THREAD_TRACE_MODE_SEL;
+typedef enum SQ_THREAD_TRACE_CAPTURE_MODE {
+ SQ_THREAD_TRACE_CAPTURE_MODE_ALL = 0x0,
+ SQ_THREAD_TRACE_CAPTURE_MODE_SELECT = 0x1,
+ SQ_THREAD_TRACE_CAPTURE_MODE_SELECT_DETAIL = 0x2,
+} SQ_THREAD_TRACE_CAPTURE_MODE;
+typedef enum SQ_THREAD_TRACE_VM_ID_MASK {
+ SQ_THREAD_TRACE_VM_ID_MASK_SINGLE = 0x0,
+ SQ_THREAD_TRACE_VM_ID_MASK_ALL = 0x1,
+ SQ_THREAD_TRACE_VM_ID_MASK_SINGLE_DETAIL = 0x2,
+} SQ_THREAD_TRACE_VM_ID_MASK;
+typedef enum SQ_THREAD_TRACE_WAVE_MASK {
+ SQ_THREAD_TRACE_WAVE_MASK_NONE = 0x0,
+ SQ_THREAD_TRACE_WAVE_MASK_ALL = 0x1,
+} SQ_THREAD_TRACE_WAVE_MASK;
+typedef enum SQ_THREAD_TRACE_ISSUE {
+ SQ_THREAD_TRACE_ISSUE_NULL = 0x0,
+ SQ_THREAD_TRACE_ISSUE_STALL = 0x1,
+ SQ_THREAD_TRACE_ISSUE_INST = 0x2,
+ SQ_THREAD_TRACE_ISSUE_IMMED = 0x3,
+} SQ_THREAD_TRACE_ISSUE;
+typedef enum SQ_THREAD_TRACE_ISSUE_MASK {
+ SQ_THREAD_TRACE_ISSUE_MASK_ALL = 0x0,
+ SQ_THREAD_TRACE_ISSUE_MASK_STALLED = 0x1,
+ SQ_THREAD_TRACE_ISSUE_MASK_STALLED_AND_IMMED = 0x2,
+ SQ_THREAD_TRACE_ISSUE_MASK_IMMED = 0x3,
+} SQ_THREAD_TRACE_ISSUE_MASK;
+typedef enum SQ_PERF_SEL {
+ SQ_PERF_SEL_NONE = 0x0,
+ SQ_PERF_SEL_ACCUM_PREV = 0x1,
+ SQ_PERF_SEL_CYCLES = 0x2,
+ SQ_PERF_SEL_BUSY_CYCLES = 0x3,
+ SQ_PERF_SEL_WAVES = 0x4,
+ SQ_PERF_SEL_LEVEL_WAVES = 0x5,
+ SQ_PERF_SEL_WAVES_EQ_64 = 0x6,
+ SQ_PERF_SEL_WAVES_LT_64 = 0x7,
+ SQ_PERF_SEL_WAVES_LT_48 = 0x8,
+ SQ_PERF_SEL_WAVES_LT_32 = 0x9,
+ SQ_PERF_SEL_WAVES_LT_16 = 0xa,
+ SQ_PERF_SEL_WAVES_CU = 0xb,
+ SQ_PERF_SEL_LEVEL_WAVES_CU = 0xc,
+ SQ_PERF_SEL_BUSY_CU_CYCLES = 0xd,
+ SQ_PERF_SEL_ITEMS = 0xe,
+ SQ_PERF_SEL_QUADS = 0xf,
+ SQ_PERF_SEL_EVENTS = 0x10,
+ SQ_PERF_SEL_SURF_SYNCS = 0x11,
+ SQ_PERF_SEL_TTRACE_REQS = 0x12,
+ SQ_PERF_SEL_TTRACE_INFLIGHT_REQS = 0x13,
+ SQ_PERF_SEL_TTRACE_STALL = 0x14,
+ SQ_PERF_SEL_MSG_CNTR = 0x15,
+ SQ_PERF_SEL_MSG_PERF = 0x16,
+ SQ_PERF_SEL_MSG_GSCNT = 0x17,
+ SQ_PERF_SEL_MSG_INTERRUPT = 0x18,
+ SQ_PERF_SEL_INSTS = 0x19,
+ SQ_PERF_SEL_INSTS_VALU = 0x1a,
+ SQ_PERF_SEL_INSTS_VMEM_WR = 0x1b,
+ SQ_PERF_SEL_INSTS_VMEM_RD = 0x1c,
+ SQ_PERF_SEL_INSTS_VMEM = 0x1d,
+ SQ_PERF_SEL_INSTS_SALU = 0x1e,
+ SQ_PERF_SEL_INSTS_SMEM = 0x1f,
+ SQ_PERF_SEL_INSTS_FLAT = 0x20,
+ SQ_PERF_SEL_INSTS_FLAT_LDS_ONLY = 0x21,
+ SQ_PERF_SEL_INSTS_LDS = 0x22,
+ SQ_PERF_SEL_INSTS_GDS = 0x23,
+ SQ_PERF_SEL_INSTS_EXP = 0x24,
+ SQ_PERF_SEL_INSTS_EXP_GDS = 0x25,
+ SQ_PERF_SEL_INSTS_BRANCH = 0x26,
+ SQ_PERF_SEL_INSTS_SENDMSG = 0x27,
+ SQ_PERF_SEL_INSTS_VSKIPPED = 0x28,
+ SQ_PERF_SEL_INST_LEVEL_VMEM = 0x29,
+ SQ_PERF_SEL_INST_LEVEL_SMEM = 0x2a,
+ SQ_PERF_SEL_INST_LEVEL_LDS = 0x2b,
+ SQ_PERF_SEL_INST_LEVEL_GDS = 0x2c,
+ SQ_PERF_SEL_INST_LEVEL_EXP = 0x2d,
+ SQ_PERF_SEL_WAVE_CYCLES = 0x2e,
+ SQ_PERF_SEL_WAVE_READY = 0x2f,
+ SQ_PERF_SEL_WAIT_CNT_VM = 0x30,
+ SQ_PERF_SEL_WAIT_CNT_LGKM = 0x31,
+ SQ_PERF_SEL_WAIT_CNT_EXP = 0x32,
+ SQ_PERF_SEL_WAIT_CNT_ANY = 0x33,
+ SQ_PERF_SEL_WAIT_BARRIER = 0x34,
+ SQ_PERF_SEL_WAIT_EXP_ALLOC = 0x35,
+ SQ_PERF_SEL_WAIT_SLEEP = 0x36,
+ SQ_PERF_SEL_WAIT_OTHER = 0x37,
+ SQ_PERF_SEL_WAIT_ANY = 0x38,
+ SQ_PERF_SEL_WAIT_TTRACE = 0x39,
+ SQ_PERF_SEL_WAIT_IFETCH = 0x3a,
+ SQ_PERF_SEL_WAIT_INST_VMEM = 0x3b,
+ SQ_PERF_SEL_WAIT_INST_SCA = 0x3c,
+ SQ_PERF_SEL_WAIT_INST_LDS = 0x3d,
+ SQ_PERF_SEL_WAIT_INST_VALU = 0x3e,
+ SQ_PERF_SEL_WAIT_INST_EXP_GDS = 0x3f,
+ SQ_PERF_SEL_WAIT_INST_MISC = 0x40,
+ SQ_PERF_SEL_WAIT_INST_FLAT = 0x41,
+ SQ_PERF_SEL_ACTIVE_INST_ANY = 0x42,
+ SQ_PERF_SEL_ACTIVE_INST_VMEM = 0x43,
+ SQ_PERF_SEL_ACTIVE_INST_LDS = 0x44,
+ SQ_PERF_SEL_ACTIVE_INST_VALU = 0x45,
+ SQ_PERF_SEL_ACTIVE_INST_SCA = 0x46,
+ SQ_PERF_SEL_ACTIVE_INST_EXP_GDS = 0x47,
+ SQ_PERF_SEL_ACTIVE_INST_MISC = 0x48,
+ SQ_PERF_SEL_ACTIVE_INST_FLAT = 0x49,
+ SQ_PERF_SEL_INST_CYCLES_VMEM_WR = 0x4a,
+ SQ_PERF_SEL_INST_CYCLES_VMEM_RD = 0x4b,
+ SQ_PERF_SEL_INST_CYCLES_VMEM_ADDR = 0x4c,
+ SQ_PERF_SEL_INST_CYCLES_VMEM_DATA = 0x4d,
+ SQ_PERF_SEL_INST_CYCLES_VMEM_CMD = 0x4e,
+ SQ_PERF_SEL_INST_CYCLES_VMEM = 0x4f,
+ SQ_PERF_SEL_INST_CYCLES_LDS = 0x50,
+ SQ_PERF_SEL_INST_CYCLES_VALU = 0x51,
+ SQ_PERF_SEL_INST_CYCLES_EXP = 0x52,
+ SQ_PERF_SEL_INST_CYCLES_GDS = 0x53,
+ SQ_PERF_SEL_INST_CYCLES_SCA = 0x54,
+ SQ_PERF_SEL_INST_CYCLES_SMEM = 0x55,
+ SQ_PERF_SEL_INST_CYCLES_SALU = 0x56,
+ SQ_PERF_SEL_INST_CYCLES_EXP_GDS = 0x57,
+ SQ_PERF_SEL_INST_CYCLES_MISC = 0x58,
+ SQ_PERF_SEL_THREAD_CYCLES_VALU = 0x59,
+ SQ_PERF_SEL_THREAD_CYCLES_VALU_MAX = 0x5a,
+ SQ_PERF_SEL_IFETCH = 0x5b,
+ SQ_PERF_SEL_IFETCH_LEVEL = 0x5c,
+ SQ_PERF_SEL_CBRANCH_FORK = 0x5d,
+ SQ_PERF_SEL_CBRANCH_FORK_SPLIT = 0x5e,
+ SQ_PERF_SEL_VALU_LDS_DIRECT_RD = 0x5f,
+ SQ_PERF_SEL_VALU_LDS_INTERP_OP = 0x60,
+ SQ_PERF_SEL_LDS_BANK_CONFLICT = 0x61,
+ SQ_PERF_SEL_LDS_ADDR_CONFLICT = 0x62,
+ SQ_PERF_SEL_LDS_UNALIGNED_STALL = 0x63,
+ SQ_PERF_SEL_LDS_MEM_VIOLATIONS = 0x64,
+ SQ_PERF_SEL_LDS_ATOMIC_RETURN = 0x65,
+ SQ_PERF_SEL_LDS_IDX_ACTIVE = 0x66,
+ SQ_PERF_SEL_VALU_DEP_STALL = 0x67,
+ SQ_PERF_SEL_VALU_STARVE = 0x68,
+ SQ_PERF_SEL_EXP_REQ_FIFO_FULL = 0x69,
+ SQ_PERF_SEL_LDS_BACK2BACK_STALL = 0x6a,
+ SQ_PERF_SEL_LDS_DATA_FIFO_FULL = 0x6b,
+ SQ_PERF_SEL_LDS_CMD_FIFO_FULL = 0x6c,
+ SQ_PERF_SEL_VMEM_BACK2BACK_STALL = 0x6d,
+ SQ_PERF_SEL_VMEM_TA_ADDR_FIFO_FULL = 0x6e,
+ SQ_PERF_SEL_VMEM_TA_CMD_FIFO_FULL = 0x6f,
+ SQ_PERF_SEL_VMEM_EX_DATA_REG_BUSY = 0x70,
+ SQ_PERF_SEL_VMEM_WR_BACK2BACK_STALL = 0x71,
+ SQ_PERF_SEL_VMEM_WR_TA_DATA_FIFO_FULL = 0x72,
+ SQ_PERF_SEL_VALU_SRC_C_CONFLICT = 0x73,
+ SQ_PERF_SEL_VMEM_RD_SRC_CD_CONFLICT = 0x74,
+ SQ_PERF_SEL_VMEM_WR_SRC_CD_CONFLICT = 0x75,
+ SQ_PERF_SEL_FLAT_SRC_CD_CONFLICT = 0x76,
+ SQ_PERF_SEL_LDS_SRC_CD_CONFLICT = 0x77,
+ SQ_PERF_SEL_SRC_CD_BUSY = 0x78,
+ SQ_PERF_SEL_PT_POWER_STALL = 0x79,
+ SQ_PERF_SEL_USER0 = 0x7a,
+ SQ_PERF_SEL_USER1 = 0x7b,
+ SQ_PERF_SEL_USER2 = 0x7c,
+ SQ_PERF_SEL_USER3 = 0x7d,
+ SQ_PERF_SEL_USER4 = 0x7e,
+ SQ_PERF_SEL_USER5 = 0x7f,
+ SQ_PERF_SEL_USER6 = 0x80,
+ SQ_PERF_SEL_USER7 = 0x81,
+ SQ_PERF_SEL_USER8 = 0x82,
+ SQ_PERF_SEL_USER9 = 0x83,
+ SQ_PERF_SEL_USER10 = 0x84,
+ SQ_PERF_SEL_USER11 = 0x85,
+ SQ_PERF_SEL_USER12 = 0x86,
+ SQ_PERF_SEL_USER13 = 0x87,
+ SQ_PERF_SEL_USER14 = 0x88,
+ SQ_PERF_SEL_USER15 = 0x89,
+ SQ_PERF_SEL_USER_LEVEL0 = 0x8a,
+ SQ_PERF_SEL_USER_LEVEL1 = 0x8b,
+ SQ_PERF_SEL_USER_LEVEL2 = 0x8c,
+ SQ_PERF_SEL_USER_LEVEL3 = 0x8d,
+ SQ_PERF_SEL_USER_LEVEL4 = 0x8e,
+ SQ_PERF_SEL_USER_LEVEL5 = 0x8f,
+ SQ_PERF_SEL_USER_LEVEL6 = 0x90,
+ SQ_PERF_SEL_USER_LEVEL7 = 0x91,
+ SQ_PERF_SEL_USER_LEVEL8 = 0x92,
+ SQ_PERF_SEL_USER_LEVEL9 = 0x93,
+ SQ_PERF_SEL_USER_LEVEL10 = 0x94,
+ SQ_PERF_SEL_USER_LEVEL11 = 0x95,
+ SQ_PERF_SEL_USER_LEVEL12 = 0x96,
+ SQ_PERF_SEL_USER_LEVEL13 = 0x97,
+ SQ_PERF_SEL_USER_LEVEL14 = 0x98,
+ SQ_PERF_SEL_USER_LEVEL15 = 0x99,
+ SQ_PERF_SEL_POWER_VALU = 0x9a,
+ SQ_PERF_SEL_POWER_VALU0 = 0x9b,
+ SQ_PERF_SEL_POWER_VALU1 = 0x9c,
+ SQ_PERF_SEL_POWER_VALU2 = 0x9d,
+ SQ_PERF_SEL_POWER_GPR_RD = 0x9e,
+ SQ_PERF_SEL_POWER_GPR_WR = 0x9f,
+ SQ_PERF_SEL_POWER_LDS_BUSY = 0xa0,
+ SQ_PERF_SEL_POWER_ALU_BUSY = 0xa1,
+ SQ_PERF_SEL_POWER_TEX_BUSY = 0xa2,
+ SQ_PERF_SEL_ACCUM_PREV_HIRES = 0xa3,
+ SQ_PERF_SEL_WAVES_RESTORED = 0xa4,
+ SQ_PERF_SEL_WAVES_SAVED = 0xa5,
+ SQ_PERF_SEL_DUMMY_LAST = 0xa7,
+ SQC_PERF_SEL_ICACHE_INPUT_VALID_READY = 0xa8,
+ SQC_PERF_SEL_ICACHE_INPUT_VALID_READYB = 0xa9,
+ SQC_PERF_SEL_ICACHE_INPUT_VALIDB = 0xaa,
+ SQC_PERF_SEL_DCACHE_INPUT_VALID_READY = 0xab,
+ SQC_PERF_SEL_DCACHE_INPUT_VALID_READYB = 0xac,
+ SQC_PERF_SEL_DCACHE_INPUT_VALIDB = 0xad,
+ SQC_PERF_SEL_TC_REQ = 0xae,
+ SQC_PERF_SEL_TC_INST_REQ = 0xaf,
+ SQC_PERF_SEL_TC_DATA_READ_REQ = 0xb0,
+ SQC_PERF_SEL_TC_DATA_WRITE_REQ = 0xb1,
+ SQC_PERF_SEL_TC_DATA_ATOMIC_REQ = 0xb2,
+ SQC_PERF_SEL_TC_STALL = 0xb3,
+ SQC_PERF_SEL_TC_STARVE = 0xb4,
+ SQC_PERF_SEL_ICACHE_BUSY_CYCLES = 0xb5,
+ SQC_PERF_SEL_ICACHE_REQ = 0xb6,
+ SQC_PERF_SEL_ICACHE_HITS = 0xb7,
+ SQC_PERF_SEL_ICACHE_MISSES = 0xb8,
+ SQC_PERF_SEL_ICACHE_MISSES_DUPLICATE = 0xb9,
+ SQC_PERF_SEL_ICACHE_INVAL_INST = 0xba,
+ SQC_PERF_SEL_ICACHE_INVAL_ASYNC = 0xbb,
+ SQC_PERF_SEL_ICACHE_INPUT_STALL_ARB_NO_GRANT = 0xbc,
+ SQC_PERF_SEL_ICACHE_INPUT_STALL_BANK_READYB = 0xbd,
+ SQC_PERF_SEL_ICACHE_CACHE_STALLED = 0xbe,
+ SQC_PERF_SEL_ICACHE_CACHE_STALL_INFLIGHT_NONZERO = 0xbf,
+ SQC_PERF_SEL_ICACHE_CACHE_STALL_INFLIGHT_MAX = 0xc0,
+ SQC_PERF_SEL_ICACHE_CACHE_STALL_OUTPUT = 0xc1,
+ SQC_PERF_SEL_ICACHE_CACHE_STALL_OUTPUT_MISS_FIFO = 0xc2,
+ SQC_PERF_SEL_ICACHE_CACHE_STALL_OUTPUT_HIT_FIFO = 0xc3,
+ SQC_PERF_SEL_ICACHE_CACHE_STALL_OUTPUT_TC_IF = 0xc4,
+ SQC_PERF_SEL_ICACHE_STALL_OUTXBAR_ARB_NO_GRANT = 0xc5,
+ SQC_PERF_SEL_DCACHE_BUSY_CYCLES = 0xc6,
+ SQC_PERF_SEL_DCACHE_REQ = 0xc7,
+ SQC_PERF_SEL_DCACHE_HITS = 0xc8,
+ SQC_PERF_SEL_DCACHE_MISSES = 0xc9,
+ SQC_PERF_SEL_DCACHE_MISSES_DUPLICATE = 0xca,
+ SQC_PERF_SEL_DCACHE_HIT_LRU_READ = 0xcb,
+ SQC_PERF_SEL_DCACHE_MISS_EVICT_READ = 0xcc,
+ SQC_PERF_SEL_DCACHE_WC_LRU_WRITE = 0xcd,
+ SQC_PERF_SEL_DCACHE_WT_EVICT_WRITE = 0xce,
+ SQC_PERF_SEL_DCACHE_ATOMIC = 0xcf,
+ SQC_PERF_SEL_DCACHE_VOLATILE = 0xd0,
+ SQC_PERF_SEL_DCACHE_INVAL_INST = 0xd1,
+ SQC_PERF_SEL_DCACHE_INVAL_ASYNC = 0xd2,
+ SQC_PERF_SEL_DCACHE_INVAL_VOLATILE_INST = 0xd3,
+ SQC_PERF_SEL_DCACHE_INVAL_VOLATILE_ASYNC = 0xd4,
+ SQC_PERF_SEL_DCACHE_WB_INST = 0xd5,
+ SQC_PERF_SEL_DCACHE_WB_ASYNC = 0xd6,
+ SQC_PERF_SEL_DCACHE_WB_VOLATILE_INST = 0xd7,
+ SQC_PERF_SEL_DCACHE_WB_VOLATILE_ASYNC = 0xd8,
+ SQC_PERF_SEL_DCACHE_INPUT_STALL_ARB_NO_GRANT = 0xd9,
+ SQC_PERF_SEL_DCACHE_INPUT_STALL_BANK_READYB = 0xda,
+ SQC_PERF_SEL_DCACHE_CACHE_STALLED = 0xdb,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_INFLIGHT_MAX = 0xdc,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_OUTPUT = 0xdd,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_EVICT = 0xde,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_UNORDERED = 0xdf,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_ALLOC_UNAVAILABLE= 0xe0,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_FORCE_EVICT = 0xe1,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_MULTI_FLUSH = 0xe2,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_FLUSH_DONE = 0xe3,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_OUTPUT_MISS_FIFO = 0xe4,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_OUTPUT_HIT_FIFO = 0xe5,
+ SQC_PERF_SEL_DCACHE_CACHE_STALL_OUTPUT_TC_IF = 0xe6,
+ SQC_PERF_SEL_DCACHE_STALL_OUTXBAR_ARB_NO_GRANT = 0xe7,
+ SQC_PERF_SEL_DCACHE_REQ_READ_1 = 0xe8,
+ SQC_PERF_SEL_DCACHE_REQ_READ_2 = 0xe9,
+ SQC_PERF_SEL_DCACHE_REQ_READ_4 = 0xea,
+ SQC_PERF_SEL_DCACHE_REQ_READ_8 = 0xeb,
+ SQC_PERF_SEL_DCACHE_REQ_READ_16 = 0xec,
+ SQC_PERF_SEL_DCACHE_REQ_TIME = 0xed,
+ SQC_PERF_SEL_DCACHE_REQ_WRITE_1 = 0xee,
+ SQC_PERF_SEL_DCACHE_REQ_WRITE_2 = 0xef,
+ SQC_PERF_SEL_DCACHE_REQ_WRITE_4 = 0xf0,
+ SQC_PERF_SEL_DCACHE_REQ_ATC_PROBE = 0xf1,
+ SQC_PERF_SEL_SQ_DCACHE_REQS = 0xf2,
+ SQC_PERF_SEL_DCACHE_FLAT_REQ = 0xf3,
+ SQC_PERF_SEL_DCACHE_NONFLAT_REQ = 0xf4,
+ SQC_PERF_SEL_ICACHE_INFLIGHT_LEVEL = 0xf5,
+ SQC_PERF_SEL_DCACHE_INFLIGHT_LEVEL = 0xf6,
+ SQC_PERF_SEL_TC_INFLIGHT_LEVEL = 0xf7,
+ SQC_PERF_SEL_ICACHE_TC_INFLIGHT_LEVEL = 0xf8,
+ SQC_PERF_SEL_DCACHE_TC_INFLIGHT_LEVEL = 0xf9,
+ SQC_PERF_SEL_ICACHE_GATCL1_TRANSLATION_MISS = 0xfa,
+ SQC_PERF_SEL_ICACHE_GATCL1_PERMISSION_MISS = 0xfb,
+ SQC_PERF_SEL_ICACHE_GATCL1_REQUEST = 0xfc,
+ SQC_PERF_SEL_ICACHE_GATCL1_STALL_INFLIGHT_MAX = 0xfd,
+ SQC_PERF_SEL_ICACHE_GATCL1_STALL_LRU_INFLIGHT = 0xfe,
+ SQC_PERF_SEL_ICACHE_GATCL1_LFIFO_FULL = 0xff,
+ SQC_PERF_SEL_ICACHE_GATCL1_STALL_LFIFO_NOT_RES = 0x100,
+ SQC_PERF_SEL_ICACHE_GATCL1_STALL_ATCL2_REQ_OUT_OF_CREDITS= 0x101,
+ SQC_PERF_SEL_ICACHE_GATCL1_ATCL2_INFLIGHT = 0x102,
+ SQC_PERF_SEL_ICACHE_GATCL1_STALL_MISSFIFO_FULL = 0x103,
+ SQC_PERF_SEL_DCACHE_GATCL1_TRANSLATION_MISS = 0x104,
+ SQC_PERF_SEL_DCACHE_GATCL1_PERMISSION_MISS = 0x105,
+ SQC_PERF_SEL_DCACHE_GATCL1_REQUEST = 0x106,
+ SQC_PERF_SEL_DCACHE_GATCL1_STALL_INFLIGHT_MAX = 0x107,
+ SQC_PERF_SEL_DCACHE_GATCL1_STALL_LRU_INFLIGHT = 0x108,
+ SQC_PERF_SEL_DCACHE_GATCL1_LFIFO_FULL = 0x109,
+ SQC_PERF_SEL_DCACHE_GATCL1_STALL_LFIFO_NOT_RES = 0x10a,
+ SQC_PERF_SEL_DCACHE_GATCL1_STALL_ATCL2_REQ_OUT_OF_CREDITS= 0x10b,
+ SQC_PERF_SEL_DCACHE_GATCL1_ATCL2_INFLIGHT = 0x10c,
+ SQC_PERF_SEL_DCACHE_GATCL1_STALL_MISSFIFO_FULL = 0x10d,
+ SQC_PERF_SEL_DCACHE_GATCL1_STALL_MULTI_MISS = 0x10e,
+ SQC_PERF_SEL_DCACHE_GATCL1_HIT_FIFO_FULL = 0x10f,
+ SQC_PERF_SEL_DUMMY_LAST = 0x110,
+ SQ_PERF_SEL_INSTS_SMEM_NORM = 0x111,
+ SQ_PERF_SEL_ATC_INSTS_VMEM = 0x112,
+ SQ_PERF_SEL_ATC_INST_LEVEL_VMEM = 0x113,
+ SQ_PERF_SEL_ATC_XNACK_FIRST = 0x114,
+ SQ_PERF_SEL_ATC_XNACK_ALL = 0x115,
+ SQ_PERF_SEL_ATC_XNACK_FIFO_FULL = 0x116,
+ SQ_PERF_SEL_ATC_INSTS_SMEM = 0x117,
+ SQ_PERF_SEL_ATC_INST_LEVEL_SMEM = 0x118,
+ SQ_PERF_SEL_IFETCH_XNACK = 0x119,
+ SQ_PERF_SEL_TLB_SHOOTDOWN = 0x11a,
+ SQ_PERF_SEL_TLB_SHOOTDOWN_CYCLES = 0x11b,
+ SQ_PERF_SEL_INSTS_VMEM_WR_REPLAY = 0x11c,
+ SQ_PERF_SEL_INSTS_VMEM_RD_REPLAY = 0x11d,
+ SQ_PERF_SEL_INSTS_VMEM_REPLAY = 0x11e,
+ SQ_PERF_SEL_INSTS_SMEM_REPLAY = 0x11f,
+ SQ_PERF_SEL_INSTS_SMEM_NORM_REPLAY = 0x120,
+ SQ_PERF_SEL_INSTS_FLAT_REPLAY = 0x121,
+ SQ_PERF_SEL_ATC_INSTS_VMEM_REPLAY = 0x122,
+ SQ_PERF_SEL_ATC_INSTS_SMEM_REPLAY = 0x123,
+ SQ_PERF_SEL_DUMMY_LAST1 = 0x12a,
+} SQ_PERF_SEL;
+typedef enum SQ_CAC_POWER_SEL {
+ SQ_CAC_POWER_VALU = 0x0,
+ SQ_CAC_POWER_VALU0 = 0x1,
+ SQ_CAC_POWER_VALU1 = 0x2,
+ SQ_CAC_POWER_VALU2 = 0x3,
+ SQ_CAC_POWER_GPR_RD = 0x4,
+ SQ_CAC_POWER_GPR_WR = 0x5,
+ SQ_CAC_POWER_LDS_BUSY = 0x6,
+ SQ_CAC_POWER_ALU_BUSY = 0x7,
+ SQ_CAC_POWER_TEX_BUSY = 0x8,
+} SQ_CAC_POWER_SEL;
+typedef enum SQ_IND_CMD_CMD {
+ SQ_IND_CMD_CMD_NULL = 0x0,
+ SQ_IND_CMD_CMD_SETHALT = 0x1,
+ SQ_IND_CMD_CMD_SAVECTX = 0x2,
+ SQ_IND_CMD_CMD_KILL = 0x3,
+ SQ_IND_CMD_CMD_DEBUG = 0x4,
+ SQ_IND_CMD_CMD_TRAP = 0x5,
+ SQ_IND_CMD_CMD_SET_SPI_PRIO = 0x6,
+} SQ_IND_CMD_CMD;
+typedef enum SQ_IND_CMD_MODE {
+ SQ_IND_CMD_MODE_SINGLE = 0x0,
+ SQ_IND_CMD_MODE_BROADCAST = 0x1,
+ SQ_IND_CMD_MODE_BROADCAST_QUEUE = 0x2,
+ SQ_IND_CMD_MODE_BROADCAST_PIPE = 0x3,
+ SQ_IND_CMD_MODE_BROADCAST_ME = 0x4,
+} SQ_IND_CMD_MODE;
+typedef enum SQ_EDC_INFO_SOURCE {
+ SQ_EDC_INFO_SOURCE_INVALID = 0x0,
+ SQ_EDC_INFO_SOURCE_INST = 0x1,
+ SQ_EDC_INFO_SOURCE_SGPR = 0x2,
+ SQ_EDC_INFO_SOURCE_VGPR = 0x3,
+ SQ_EDC_INFO_SOURCE_LDS = 0x4,
+ SQ_EDC_INFO_SOURCE_GDS = 0x5,
+ SQ_EDC_INFO_SOURCE_TA = 0x6,
+} SQ_EDC_INFO_SOURCE;
+typedef enum SQ_ROUND_MODE {
+ SQ_ROUND_NEAREST_EVEN = 0x0,
+ SQ_ROUND_PLUS_INFINITY = 0x1,
+ SQ_ROUND_MINUS_INFINITY = 0x2,
+ SQ_ROUND_TO_ZERO = 0x3,
+} SQ_ROUND_MODE;
+typedef enum SQ_INTERRUPT_WORD_ENCODING {
+ SQ_INTERRUPT_WORD_ENCODING_AUTO = 0x0,
+ SQ_INTERRUPT_WORD_ENCODING_INST = 0x1,
+ SQ_INTERRUPT_WORD_ENCODING_ERROR = 0x2,
+} SQ_INTERRUPT_WORD_ENCODING;
+typedef enum ENUM_SQ_EXPORT_RAT_INST {
+ SQ_EXPORT_RAT_INST_NOP = 0x0,
+ SQ_EXPORT_RAT_INST_STORE_TYPED = 0x1,
+ SQ_EXPORT_RAT_INST_STORE_RAW = 0x2,
+ SQ_EXPORT_RAT_INST_STORE_RAW_FDENORM = 0x3,
+ SQ_EXPORT_RAT_INST_CMPXCHG_INT = 0x4,
+ SQ_EXPORT_RAT_INST_CMPXCHG_FLT = 0x5,
+ SQ_EXPORT_RAT_INST_CMPXCHG_FDENORM = 0x6,
+ SQ_EXPORT_RAT_INST_ADD = 0x7,
+ SQ_EXPORT_RAT_INST_SUB = 0x8,
+ SQ_EXPORT_RAT_INST_RSUB = 0x9,
+ SQ_EXPORT_RAT_INST_MIN_INT = 0xa,
+ SQ_EXPORT_RAT_INST_MIN_UINT = 0xb,
+ SQ_EXPORT_RAT_INST_MAX_INT = 0xc,
+ SQ_EXPORT_RAT_INST_MAX_UINT = 0xd,
+ SQ_EXPORT_RAT_INST_AND = 0xe,
+ SQ_EXPORT_RAT_INST_OR = 0xf,
+ SQ_EXPORT_RAT_INST_XOR = 0x10,
+ SQ_EXPORT_RAT_INST_MSKOR = 0x11,
+ SQ_EXPORT_RAT_INST_INC_UINT = 0x12,
+ SQ_EXPORT_RAT_INST_DEC_UINT = 0x13,
+ SQ_EXPORT_RAT_INST_STORE_DWORD = 0x14,
+ SQ_EXPORT_RAT_INST_STORE_SHORT = 0x15,
+ SQ_EXPORT_RAT_INST_STORE_BYTE = 0x16,
+ SQ_EXPORT_RAT_INST_NOP_RTN = 0x20,
+ SQ_EXPORT_RAT_INST_XCHG_RTN = 0x22,
+ SQ_EXPORT_RAT_INST_XCHG_FDENORM_RTN = 0x23,
+ SQ_EXPORT_RAT_INST_CMPXCHG_INT_RTN = 0x24,
+ SQ_EXPORT_RAT_INST_CMPXCHG_FLT_RTN = 0x25,
+ SQ_EXPORT_RAT_INST_CMPXCHG_FDENORM_RTN = 0x26,
+ SQ_EXPORT_RAT_INST_ADD_RTN = 0x27,
+ SQ_EXPORT_RAT_INST_SUB_RTN = 0x28,
+ SQ_EXPORT_RAT_INST_RSUB_RTN = 0x29,
+ SQ_EXPORT_RAT_INST_MIN_INT_RTN = 0x2a,
+ SQ_EXPORT_RAT_INST_MIN_UINT_RTN = 0x2b,
+ SQ_EXPORT_RAT_INST_MAX_INT_RTN = 0x2c,
+ SQ_EXPORT_RAT_INST_MAX_UINT_RTN = 0x2d,
+ SQ_EXPORT_RAT_INST_AND_RTN = 0x2e,
+ SQ_EXPORT_RAT_INST_OR_RTN = 0x2f,
+ SQ_EXPORT_RAT_INST_XOR_RTN = 0x30,
+ SQ_EXPORT_RAT_INST_MSKOR_RTN = 0x31,
+ SQ_EXPORT_RAT_INST_INC_UINT_RTN = 0x32,
+ SQ_EXPORT_RAT_INST_DEC_UINT_RTN = 0x33,
+} ENUM_SQ_EXPORT_RAT_INST;
+typedef enum SQ_IBUF_ST {
+ SQ_IBUF_IB_IDLE = 0x0,
+ SQ_IBUF_IB_INI_WAIT_GNT = 0x1,
+ SQ_IBUF_IB_INI_WAIT_DRET = 0x2,
+ SQ_IBUF_IB_LE_4DW = 0x3,
+ SQ_IBUF_IB_WAIT_DRET = 0x4,
+ SQ_IBUF_IB_EMPTY_WAIT_DRET = 0x5,
+ SQ_IBUF_IB_DRET = 0x6,
+ SQ_IBUF_IB_EMPTY_WAIT_GNT = 0x7,
+} SQ_IBUF_ST;
+typedef enum SQ_INST_STR_ST {
+ SQ_INST_STR_IB_WAVE_NORML = 0x0,
+ SQ_INST_STR_IB_WAVE2ID_NORMAL_INST_AV = 0x1,
+ SQ_INST_STR_IB_WAVE_INTERNAL_INST_AV = 0x2,
+ SQ_INST_STR_IB_WAVE_INST_SKIP_AV = 0x3,
+ SQ_INST_STR_IB_WAVE_SETVSKIP_ST0 = 0x4,
+ SQ_INST_STR_IB_WAVE_SETVSKIP_ST1 = 0x5,
+ SQ_INST_STR_IB_WAVE_NOP_SLEEP_WAIT = 0x6,
+ SQ_INST_STR_IB_WAVE_PC_FROM_SGPR_MSG_WAIT = 0x7,
+} SQ_INST_STR_ST;
+typedef enum SQ_WAVE_IB_ECC_ST {
+ SQ_WAVE_IB_ECC_CLEAN = 0x0,
+ SQ_WAVE_IB_ECC_ERR_CONTINUE = 0x1,
+ SQ_WAVE_IB_ECC_ERR_HALT = 0x2,
+ SQ_WAVE_IB_ECC_WITH_ERR_MSG = 0x3,
+} SQ_WAVE_IB_ECC_ST;
+typedef enum SH_MEM_ADDRESS_MODE {
+ SH_MEM_ADDRESS_MODE_GPUVM64 = 0x0,
+ SH_MEM_ADDRESS_MODE_GPUVM32 = 0x1,
+ SH_MEM_ADDRESS_MODE_HSA64 = 0x2,
+ SH_MEM_ADDRESS_MODE_HSA32 = 0x3,
+} SH_MEM_ADDRESS_MODE;
+typedef enum SH_MEM_ALIGNMENT_MODE {
+ SH_MEM_ALIGNMENT_MODE_DWORD = 0x0,
+ SH_MEM_ALIGNMENT_MODE_DWORD_STRICT = 0x1,
+ SH_MEM_ALIGNMENT_MODE_STRICT = 0x2,
+ SH_MEM_ALIGNMENT_MODE_UNALIGNED = 0x3,
+} SH_MEM_ALIGNMENT_MODE;
+typedef enum SQ_THREAD_TRACE_WAVE_START_COUNT_PREFIX {
+ SQ_THREAD_TRACE_WAVE_START_COUNT_PREFIX_WREXEC = 0x18,
+ SQ_THREAD_TRACE_WAVE_START_COUNT_PREFIX_RESTORE = 0x19,
+} SQ_THREAD_TRACE_WAVE_START_COUNT_PREFIX;
+#define SQ_WAVE_TYPE_PS0 0x0
+#define SQIND_GLOBAL_REGS_OFFSET 0x0
+#define SQIND_GLOBAL_REGS_SIZE 0x8
+#define SQIND_LOCAL_REGS_OFFSET 0x8
+#define SQIND_LOCAL_REGS_SIZE 0x8
+#define SQIND_WAVE_HWREGS_OFFSET 0x10
+#define SQIND_WAVE_HWREGS_SIZE 0x1f0
+#define SQIND_WAVE_SGPRS_OFFSET 0x200
+#define SQIND_WAVE_SGPRS_SIZE 0x200
+#define SQ_GFXDEC_BEGIN 0xa000
+#define SQ_GFXDEC_END 0xc000
+#define SQ_GFXDEC_STATE_ID_SHIFT 0xa
+#define SQDEC_BEGIN 0x2300
+#define SQDEC_END 0x23ff
+#define SQPERFSDEC_BEGIN 0xd9c0
+#define SQPERFSDEC_END 0xda40
+#define SQPERFDDEC_BEGIN 0xd1c0
+#define SQPERFDDEC_END 0xd240
+#define SQGFXUDEC_BEGIN 0xc330
+#define SQGFXUDEC_END 0xc380
+#define SQPWRDEC_BEGIN 0xf08c
+#define SQPWRDEC_END 0xf094
+#define SQ_DISPATCHER_GFX_MIN 0x10
+#define SQ_DISPATCHER_GFX_CNT_PER_RING 0x8
+#define SQ_MAX_PGM_SGPRS 0x68
+#define SQ_MAX_PGM_VGPRS 0x100
+#define SQ_THREAD_TRACE_TIME_UNIT 0x4
+#define SQ_EX_MODE_EXCP_VALU_BASE 0x0
+#define SQ_EX_MODE_EXCP_VALU_SIZE 0x7
+#define SQ_EX_MODE_EXCP_INVALID 0x0
+#define SQ_EX_MODE_EXCP_INPUT_DENORM 0x1
+#define SQ_EX_MODE_EXCP_DIV0 0x2
+#define SQ_EX_MODE_EXCP_OVERFLOW 0x3
+#define SQ_EX_MODE_EXCP_UNDERFLOW 0x4
+#define SQ_EX_MODE_EXCP_INEXACT 0x5
+#define SQ_EX_MODE_EXCP_INT_DIV0 0x6
+#define SQ_EX_MODE_EXCP_ADDR_WATCH 0x7
+#define SQ_EX_MODE_EXCP_MEM_VIOL 0x8
+#define INST_ID_PRIV_START 0x80000000
+#define INST_ID_ECC_INTERRUPT_MSG 0xfffffff0
+#define INST_ID_TTRACE_NEW_PC_MSG 0xfffffff1
+#define INST_ID_HW_TRAP 0xfffffff2
+#define INST_ID_KILL_SEQ 0xfffffff3
+#define INST_ID_SPI_WREXEC 0xfffffff4
+#define INST_ID_HOST_REG_TRAP_MSG 0xfffffffe
+#define SQ_ENC_SOP1_BITS 0xbe800000
+#define SQ_ENC_SOP1_MASK 0xff800000
+#define SQ_ENC_SOP1_FIELD 0x17d
+#define SQ_ENC_SOPC_BITS 0xbf000000
+#define SQ_ENC_SOPC_MASK 0xff800000
+#define SQ_ENC_SOPC_FIELD 0x17e
+#define SQ_ENC_SOPP_BITS 0xbf800000
+#define SQ_ENC_SOPP_MASK 0xff800000
+#define SQ_ENC_SOPP_FIELD 0x17f
+#define SQ_ENC_SOPK_BITS 0xb0000000
+#define SQ_ENC_SOPK_MASK 0xf0000000
+#define SQ_ENC_SOPK_FIELD 0xb
+#define SQ_ENC_SOP2_BITS 0x80000000
+#define SQ_ENC_SOP2_MASK 0xc0000000
+#define SQ_ENC_SOP2_FIELD 0x2
+#define SQ_ENC_SMEM_BITS 0xc0000000
+#define SQ_ENC_SMEM_MASK 0xfc000000
+#define SQ_ENC_SMEM_FIELD 0x30
+#define SQ_ENC_VOP1_BITS 0x7e000000
+#define SQ_ENC_VOP1_MASK 0xfe000000
+#define SQ_ENC_VOP1_FIELD 0x3f
+#define SQ_ENC_VOPC_BITS 0x7c000000
+#define SQ_ENC_VOPC_MASK 0xfe000000
+#define SQ_ENC_VOPC_FIELD 0x3e
+#define SQ_ENC_VOP2_BITS 0x0
+#define SQ_ENC_VOP2_MASK 0x80000000
+#define SQ_ENC_VOP2_FIELD 0x0
+#define SQ_ENC_VINTRP_BITS 0xd4000000
+#define SQ_ENC_VINTRP_MASK 0xfc000000
+#define SQ_ENC_VINTRP_FIELD 0x35
+#define SQ_ENC_VOP3_BITS 0xd0000000
+#define SQ_ENC_VOP3_MASK 0xfc000000
+#define SQ_ENC_VOP3_FIELD 0x34
+#define SQ_ENC_DS_BITS 0xd8000000
+#define SQ_ENC_DS_MASK 0xfc000000
+#define SQ_ENC_DS_FIELD 0x36
+#define SQ_ENC_MUBUF_BITS 0xe0000000
+#define SQ_ENC_MUBUF_MASK 0xfc000000
+#define SQ_ENC_MUBUF_FIELD 0x38
+#define SQ_ENC_MTBUF_BITS 0xe8000000
+#define SQ_ENC_MTBUF_MASK 0xfc000000
+#define SQ_ENC_MTBUF_FIELD 0x3a
+#define SQ_ENC_MIMG_BITS 0xf0000000
+#define SQ_ENC_MIMG_MASK 0xfc000000
+#define SQ_ENC_MIMG_FIELD 0x3c
+#define SQ_ENC_EXP_BITS 0xc4000000
+#define SQ_ENC_EXP_MASK 0xfc000000
+#define SQ_ENC_EXP_FIELD 0x31
+#define SQ_ENC_FLAT_BITS 0xdc000000
+#define SQ_ENC_FLAT_MASK 0xfc000000
+#define SQ_ENC_FLAT_FIELD 0x37
+#define SQ_V_OP3_INTRP_OFFSET 0x274
+#define SQ_WAITCNT_VM_SHIFT 0x0
+#define SQ_SENDMSG_STREAMID_SIZE 0x2
+#define SQ_V_OPC_COUNT 0x100
+#define SQ_V_OP3_INTRP_COUNT 0xc
+#define SQ_XLATE_VOP3_TO_VOP2_OFFSET 0x100
+#define SQ_HWREG_OFFSET_SIZE 0x5
+#define SQ_HWREG_OFFSET_SHIFT 0x6
+#define SQ_V_OP3_3IN_OFFSET 0x1c0
+#define SQ_NUM_ATTR 0x21
+#define SQ_NUM_VGPR 0x100
+#define SQ_XLATE_VOP3_TO_VINTRP_COUNT 0x4
+#define SQ_SENDMSG_MSG_SIZE 0x4
+#define SQ_NUM_TTMP 0xc
+#define SQ_HWREG_ID_SIZE 0x6
+#define SQ_SENDMSG_GSOP_SIZE 0x2
+#define SQ_NUM_SGPR 0x66
+#define SQ_EXP_NUM_MRT 0x8
+#define SQ_SENDMSG_SYSTEM_SIZE 0x3
+#define SQ_WAITCNT_LGKM_SHIFT 0x8
+#define SQ_XLATE_VOP3_TO_VOP2_COUNT 0x40
+#define SQ_V_OP3_3IN_COUNT 0xb0
+#define SQ_V_INTRP_COUNT 0x4
+#define SQ_WAITCNT_EXP_SIZE 0x3
+#define SQ_SENDMSG_SYSTEM_SHIFT 0x4
+#define SQ_EXP_NUM_GDS 0x5
+#define SQ_HWREG_SIZE_SHIFT 0xb
+#define SQ_XLATE_VOP3_TO_VOPC_OFFSET 0x0
+#define SQ_V_OP3_2IN_COUNT 0x80
+#define SQ_XLATE_VOP3_TO_VINTRP_OFFSET 0x270
+#define SQ_SENDMSG_MSG_SHIFT 0x0
+#define SQ_WAITCNT_EXP_SHIFT 0x4
+#define SQ_WAITCNT_VM_SIZE 0x4
+#define SQ_XLATE_VOP3_TO_VOP1_OFFSET 0x140
+#define SQ_SENDMSG_GSOP_SHIFT 0x4
+#define SQ_XLATE_VOP3_TO_VOP1_COUNT 0x80
+#define SQ_SRC_VGPR_BIT 0x100
+#define SQ_V_OP2_COUNT 0x40
+#define SQ_EXP_NUM_PARAM 0x20
+#define SQ_V_OP1_COUNT 0x80
+#define SQ_SENDMSG_STREAMID_SHIFT 0x8
+#define SQ_V_OP3_2IN_OFFSET 0x280
+#define SQ_WAITCNT_LGKM_SIZE 0x4
+#define SQ_XLATE_VOP3_TO_VOPC_COUNT 0x100
+#define SQ_EXP_NUM_POS 0x4
+#define SQ_HWREG_SIZE_SIZE 0x5
+#define SQ_HWREG_ID_SHIFT 0x0
+#define SQ_S_MOV_B32 0x0
+#define SQ_S_MOV_B64 0x1
+#define SQ_S_CMOV_B32 0x2
+#define SQ_S_CMOV_B64 0x3
+#define SQ_S_NOT_B32 0x4
+#define SQ_S_NOT_B64 0x5
+#define SQ_S_WQM_B32 0x6
+#define SQ_S_WQM_B64 0x7
+#define SQ_S_BREV_B32 0x8
+#define SQ_S_BREV_B64 0x9
+#define SQ_S_BCNT0_I32_B32 0xa
+#define SQ_S_BCNT0_I32_B64 0xb
+#define SQ_S_BCNT1_I32_B32 0xc
+#define SQ_S_BCNT1_I32_B64 0xd
+#define SQ_S_FF0_I32_B32 0xe
+#define SQ_S_FF0_I32_B64 0xf
+#define SQ_S_FF1_I32_B32 0x10
+#define SQ_S_FF1_I32_B64 0x11
+#define SQ_S_FLBIT_I32_B32 0x12
+#define SQ_S_FLBIT_I32_B64 0x13
+#define SQ_S_FLBIT_I32 0x14
+#define SQ_S_FLBIT_I32_I64 0x15
+#define SQ_S_SEXT_I32_I8 0x16
+#define SQ_S_SEXT_I32_I16 0x17
+#define SQ_S_BITSET0_B32 0x18
+#define SQ_S_BITSET0_B64 0x19
+#define SQ_S_BITSET1_B32 0x1a
+#define SQ_S_BITSET1_B64 0x1b
+#define SQ_S_GETPC_B64 0x1c
+#define SQ_S_SETPC_B64 0x1d
+#define SQ_S_SWAPPC_B64 0x1e
+#define SQ_S_RFE_B64 0x1f
+#define SQ_S_AND_SAVEEXEC_B64 0x20
+#define SQ_S_OR_SAVEEXEC_B64 0x21
+#define SQ_S_XOR_SAVEEXEC_B64 0x22
+#define SQ_S_ANDN2_SAVEEXEC_B64 0x23
+#define SQ_S_ORN2_SAVEEXEC_B64 0x24
+#define SQ_S_NAND_SAVEEXEC_B64 0x25
+#define SQ_S_NOR_SAVEEXEC_B64 0x26
+#define SQ_S_XNOR_SAVEEXEC_B64 0x27
+#define SQ_S_QUADMASK_B32 0x28
+#define SQ_S_QUADMASK_B64 0x29
+#define SQ_S_MOVRELS_B32 0x2a
+#define SQ_S_MOVRELS_B64 0x2b
+#define SQ_S_MOVRELD_B32 0x2c
+#define SQ_S_MOVRELD_B64 0x2d
+#define SQ_S_CBRANCH_JOIN 0x2e
+#define SQ_S_MOV_REGRD_B32 0x2f
+#define SQ_S_ABS_I32 0x30
+#define SQ_S_MOV_FED_B32 0x31
+#define SQ_S_SET_GPR_IDX_IDX 0x32
+#define SQ_ATTR0 0x0
+#define SQ_S_MOVK_I32 0x0
+#define SQ_S_CMOVK_I32 0x1
+#define SQ_S_CMPK_EQ_I32 0x2
+#define SQ_S_CMPK_LG_I32 0x3
+#define SQ_S_CMPK_GT_I32 0x4
+#define SQ_S_CMPK_GE_I32 0x5
+#define SQ_S_CMPK_LT_I32 0x6
+#define SQ_S_CMPK_LE_I32 0x7
+#define SQ_S_CMPK_EQ_U32 0x8
+#define SQ_S_CMPK_LG_U32 0x9
+#define SQ_S_CMPK_GT_U32 0xa
+#define SQ_S_CMPK_GE_U32 0xb
+#define SQ_S_CMPK_LT_U32 0xc
+#define SQ_S_CMPK_LE_U32 0xd
+#define SQ_S_ADDK_I32 0xe
+#define SQ_S_MULK_I32 0xf
+#define SQ_S_CBRANCH_I_FORK 0x10
+#define SQ_S_GETREG_B32 0x11
+#define SQ_S_SETREG_B32 0x12
+#define SQ_S_GETREG_REGRD_B32 0x13
+#define SQ_S_SETREG_IMM32_B32 0x14
+#define SQ_TBA_LO 0x6c
+#define SQ_TBA_HI 0x6d
+#define SQ_TMA_LO 0x6e
+#define SQ_TMA_HI 0x6f
+#define SQ_TTMP0 0x70
+#define SQ_TTMP1 0x71
+#define SQ_TTMP2 0x72
+#define SQ_TTMP3 0x73
+#define SQ_TTMP4 0x74
+#define SQ_TTMP5 0x75
+#define SQ_TTMP6 0x76
+#define SQ_TTMP7 0x77
+#define SQ_TTMP8 0x78
+#define SQ_TTMP9 0x79
+#define SQ_TTMP10 0x7a
+#define SQ_TTMP11 0x7b
+#define SQ_VGPR0 0x0
+#define SQ_EXP 0x0
+#define SQ_EXP_MRT0 0x0
+#define SQ_EXP_MRTZ 0x8
+#define SQ_EXP_NULL 0x9
+#define SQ_EXP_POS0 0xc
+#define SQ_EXP_PARAM0 0x20
+#define SQ_CNT1 0x0
+#define SQ_CNT2 0x1
+#define SQ_CNT3 0x2
+#define SQ_CNT4 0x3
+#define SQ_S_LOAD_DWORD 0x0
+#define SQ_S_LOAD_DWORDX2 0x1
+#define SQ_S_LOAD_DWORDX4 0x2
+#define SQ_S_LOAD_DWORDX8 0x3
+#define SQ_S_LOAD_DWORDX16 0x4
+#define SQ_S_BUFFER_LOAD_DWORD 0x8
+#define SQ_S_BUFFER_LOAD_DWORDX2 0x9
+#define SQ_S_BUFFER_LOAD_DWORDX4 0xa
+#define SQ_S_BUFFER_LOAD_DWORDX8 0xb
+#define SQ_S_BUFFER_LOAD_DWORDX16 0xc
+#define SQ_S_STORE_DWORD 0x10
+#define SQ_S_STORE_DWORDX2 0x11
+#define SQ_S_STORE_DWORDX4 0x12
+#define SQ_S_BUFFER_STORE_DWORD 0x18
+#define SQ_S_BUFFER_STORE_DWORDX2 0x19
+#define SQ_S_BUFFER_STORE_DWORDX4 0x1a
+#define SQ_S_DCACHE_INV 0x20
+#define SQ_S_DCACHE_WB 0x21
+#define SQ_S_DCACHE_INV_VOL 0x22
+#define SQ_S_DCACHE_WB_VOL 0x23
+#define SQ_S_MEMTIME 0x24
+#define SQ_S_MEMREALTIME 0x25
+#define SQ_S_ATC_PROBE 0x26
+#define SQ_S_ATC_PROBE_BUFFER 0x27
+#define SQ_S_BUFFER_ATOMIC_SWAP 0x40
+#define SQ_S_BUFFER_ATOMIC_CMPSWAP 0x41
+#define SQ_S_BUFFER_ATOMIC_ADD 0x42
+#define SQ_S_BUFFER_ATOMIC_SUB 0x43
+#define SQ_S_BUFFER_ATOMIC_SMIN 0x44
+#define SQ_S_BUFFER_ATOMIC_UMIN 0x45
+#define SQ_S_BUFFER_ATOMIC_SMAX 0x46
+#define SQ_S_BUFFER_ATOMIC_UMAX 0x47
+#define SQ_S_BUFFER_ATOMIC_AND 0x48
+#define SQ_S_BUFFER_ATOMIC_OR 0x49
+#define SQ_S_BUFFER_ATOMIC_XOR 0x4a
+#define SQ_S_BUFFER_ATOMIC_INC 0x4b
+#define SQ_S_BUFFER_ATOMIC_DEC 0x4c
+#define SQ_S_BUFFER_ATOMIC_SWAP_X2 0x60
+#define SQ_S_BUFFER_ATOMIC_CMPSWAP_X2 0x61
+#define SQ_S_BUFFER_ATOMIC_ADD_X2 0x62
+#define SQ_S_BUFFER_ATOMIC_SUB_X2 0x63
+#define SQ_S_BUFFER_ATOMIC_SMIN_X2 0x64
+#define SQ_S_BUFFER_ATOMIC_UMIN_X2 0x65
+#define SQ_S_BUFFER_ATOMIC_SMAX_X2 0x66
+#define SQ_S_BUFFER_ATOMIC_UMAX_X2 0x67
+#define SQ_S_BUFFER_ATOMIC_AND_X2 0x68
+#define SQ_S_BUFFER_ATOMIC_OR_X2 0x69
+#define SQ_S_BUFFER_ATOMIC_XOR_X2 0x6a
+#define SQ_S_BUFFER_ATOMIC_INC_X2 0x6b
+#define SQ_S_BUFFER_ATOMIC_DEC_X2 0x6c
+#define SQ_F 0x0
+#define SQ_LT 0x1
+#define SQ_EQ 0x2
+#define SQ_LE 0x3
+#define SQ_GT 0x4
+#define SQ_LG 0x5
+#define SQ_GE 0x6
+#define SQ_O 0x7
+#define SQ_U 0x8
+#define SQ_NGE 0x9
+#define SQ_NLG 0xa
+#define SQ_NGT 0xb
+#define SQ_NLE 0xc
+#define SQ_NEQ 0xd
+#define SQ_NLT 0xe
+#define SQ_TRU 0xf
+#define SQ_V_CMP_CLASS_F32 0x10
+#define SQ_V_CMPX_CLASS_F32 0x11
+#define SQ_V_CMP_CLASS_F64 0x12
+#define SQ_V_CMPX_CLASS_F64 0x13
+#define SQ_V_CMP_CLASS_F16 0x14
+#define SQ_V_CMPX_CLASS_F16 0x15
+#define SQ_V_CMP_F_F16 0x20
+#define SQ_V_CMP_LT_F16 0x21
+#define SQ_V_CMP_EQ_F16 0x22
+#define SQ_V_CMP_LE_F16 0x23
+#define SQ_V_CMP_GT_F16 0x24
+#define SQ_V_CMP_LG_F16 0x25
+#define SQ_V_CMP_GE_F16 0x26
+#define SQ_V_CMP_O_F16 0x27
+#define SQ_V_CMP_U_F16 0x28
+#define SQ_V_CMP_NGE_F16 0x29
+#define SQ_V_CMP_NLG_F16 0x2a
+#define SQ_V_CMP_NGT_F16 0x2b
+#define SQ_V_CMP_NLE_F16 0x2c
+#define SQ_V_CMP_NEQ_F16 0x2d
+#define SQ_V_CMP_NLT_F16 0x2e
+#define SQ_V_CMP_TRU_F16 0x2f
+#define SQ_V_CMPX_F_F16 0x30
+#define SQ_V_CMPX_LT_F16 0x31
+#define SQ_V_CMPX_EQ_F16 0x32
+#define SQ_V_CMPX_LE_F16 0x33
+#define SQ_V_CMPX_GT_F16 0x34
+#define SQ_V_CMPX_LG_F16 0x35
+#define SQ_V_CMPX_GE_F16 0x36
+#define SQ_V_CMPX_O_F16 0x37
+#define SQ_V_CMPX_U_F16 0x38
+#define SQ_V_CMPX_NGE_F16 0x39
+#define SQ_V_CMPX_NLG_F16 0x3a
+#define SQ_V_CMPX_NGT_F16 0x3b
+#define SQ_V_CMPX_NLE_F16 0x3c
+#define SQ_V_CMPX_NEQ_F16 0x3d
+#define SQ_V_CMPX_NLT_F16 0x3e
+#define SQ_V_CMPX_TRU_F16 0x3f
+#define SQ_V_CMP_F_F32 0x40
+#define SQ_V_CMP_LT_F32 0x41
+#define SQ_V_CMP_EQ_F32 0x42
+#define SQ_V_CMP_LE_F32 0x43
+#define SQ_V_CMP_GT_F32 0x44
+#define SQ_V_CMP_LG_F32 0x45
+#define SQ_V_CMP_GE_F32 0x46
+#define SQ_V_CMP_O_F32 0x47
+#define SQ_V_CMP_U_F32 0x48
+#define SQ_V_CMP_NGE_F32 0x49
+#define SQ_V_CMP_NLG_F32 0x4a
+#define SQ_V_CMP_NGT_F32 0x4b
+#define SQ_V_CMP_NLE_F32 0x4c
+#define SQ_V_CMP_NEQ_F32 0x4d
+#define SQ_V_CMP_NLT_F32 0x4e
+#define SQ_V_CMP_TRU_F32 0x4f
+#define SQ_V_CMPX_F_F32 0x50
+#define SQ_V_CMPX_LT_F32 0x51
+#define SQ_V_CMPX_EQ_F32 0x52
+#define SQ_V_CMPX_LE_F32 0x53
+#define SQ_V_CMPX_GT_F32 0x54
+#define SQ_V_CMPX_LG_F32 0x55
+#define SQ_V_CMPX_GE_F32 0x56
+#define SQ_V_CMPX_O_F32 0x57
+#define SQ_V_CMPX_U_F32 0x58
+#define SQ_V_CMPX_NGE_F32 0x59
+#define SQ_V_CMPX_NLG_F32 0x5a
+#define SQ_V_CMPX_NGT_F32 0x5b
+#define SQ_V_CMPX_NLE_F32 0x5c
+#define SQ_V_CMPX_NEQ_F32 0x5d
+#define SQ_V_CMPX_NLT_F32 0x5e
+#define SQ_V_CMPX_TRU_F32 0x5f
+#define SQ_V_CMP_F_F64 0x60
+#define SQ_V_CMP_LT_F64 0x61
+#define SQ_V_CMP_EQ_F64 0x62
+#define SQ_V_CMP_LE_F64 0x63
+#define SQ_V_CMP_GT_F64 0x64
+#define SQ_V_CMP_LG_F64 0x65
+#define SQ_V_CMP_GE_F64 0x66
+#define SQ_V_CMP_O_F64 0x67
+#define SQ_V_CMP_U_F64 0x68
+#define SQ_V_CMP_NGE_F64 0x69
+#define SQ_V_CMP_NLG_F64 0x6a
+#define SQ_V_CMP_NGT_F64 0x6b
+#define SQ_V_CMP_NLE_F64 0x6c
+#define SQ_V_CMP_NEQ_F64 0x6d
+#define SQ_V_CMP_NLT_F64 0x6e
+#define SQ_V_CMP_TRU_F64 0x6f
+#define SQ_V_CMPX_F_F64 0x70
+#define SQ_V_CMPX_LT_F64 0x71
+#define SQ_V_CMPX_EQ_F64 0x72
+#define SQ_V_CMPX_LE_F64 0x73
+#define SQ_V_CMPX_GT_F64 0x74
+#define SQ_V_CMPX_LG_F64 0x75
+#define SQ_V_CMPX_GE_F64 0x76
+#define SQ_V_CMPX_O_F64 0x77
+#define SQ_V_CMPX_U_F64 0x78
+#define SQ_V_CMPX_NGE_F64 0x79
+#define SQ_V_CMPX_NLG_F64 0x7a
+#define SQ_V_CMPX_NGT_F64 0x7b
+#define SQ_V_CMPX_NLE_F64 0x7c
+#define SQ_V_CMPX_NEQ_F64 0x7d
+#define SQ_V_CMPX_NLT_F64 0x7e
+#define SQ_V_CMPX_TRU_F64 0x7f
+#define SQ_V_CMP_F_I16 0xa0
+#define SQ_V_CMP_LT_I16 0xa1
+#define SQ_V_CMP_EQ_I16 0xa2
+#define SQ_V_CMP_LE_I16 0xa3
+#define SQ_V_CMP_GT_I16 0xa4
+#define SQ_V_CMP_NE_I16 0xa5
+#define SQ_V_CMP_GE_I16 0xa6
+#define SQ_V_CMP_T_I16 0xa7
+#define SQ_V_CMP_F_U16 0xa8
+#define SQ_V_CMP_LT_U16 0xa9
+#define SQ_V_CMP_EQ_U16 0xaa
+#define SQ_V_CMP_LE_U16 0xab
+#define SQ_V_CMP_GT_U16 0xac
+#define SQ_V_CMP_NE_U16 0xad
+#define SQ_V_CMP_GE_U16 0xae
+#define SQ_V_CMP_T_U16 0xaf
+#define SQ_V_CMPX_F_I16 0xb0
+#define SQ_V_CMPX_LT_I16 0xb1
+#define SQ_V_CMPX_EQ_I16 0xb2
+#define SQ_V_CMPX_LE_I16 0xb3
+#define SQ_V_CMPX_GT_I16 0xb4
+#define SQ_V_CMPX_NE_I16 0xb5
+#define SQ_V_CMPX_GE_I16 0xb6
+#define SQ_V_CMPX_T_I16 0xb7
+#define SQ_V_CMPX_F_U16 0xb8
+#define SQ_V_CMPX_LT_U16 0xb9
+#define SQ_V_CMPX_EQ_U16 0xba
+#define SQ_V_CMPX_LE_U16 0xbb
+#define SQ_V_CMPX_GT_U16 0xbc
+#define SQ_V_CMPX_NE_U16 0xbd
+#define SQ_V_CMPX_GE_U16 0xbe
+#define SQ_V_CMPX_T_U16 0xbf
+#define SQ_V_CMP_F_I32 0xc0
+#define SQ_V_CMP_LT_I32 0xc1
+#define SQ_V_CMP_EQ_I32 0xc2
+#define SQ_V_CMP_LE_I32 0xc3
+#define SQ_V_CMP_GT_I32 0xc4
+#define SQ_V_CMP_NE_I32 0xc5
+#define SQ_V_CMP_GE_I32 0xc6
+#define SQ_V_CMP_T_I32 0xc7
+#define SQ_V_CMP_F_U32 0xc8
+#define SQ_V_CMP_LT_U32 0xc9
+#define SQ_V_CMP_EQ_U32 0xca
+#define SQ_V_CMP_LE_U32 0xcb
+#define SQ_V_CMP_GT_U32 0xcc
+#define SQ_V_CMP_NE_U32 0xcd
+#define SQ_V_CMP_GE_U32 0xce
+#define SQ_V_CMP_T_U32 0xcf
+#define SQ_V_CMPX_F_I32 0xd0
+#define SQ_V_CMPX_LT_I32 0xd1
+#define SQ_V_CMPX_EQ_I32 0xd2
+#define SQ_V_CMPX_LE_I32 0xd3
+#define SQ_V_CMPX_GT_I32 0xd4
+#define SQ_V_CMPX_NE_I32 0xd5
+#define SQ_V_CMPX_GE_I32 0xd6
+#define SQ_V_CMPX_T_I32 0xd7
+#define SQ_V_CMPX_F_U32 0xd8
+#define SQ_V_CMPX_LT_U32 0xd9
+#define SQ_V_CMPX_EQ_U32 0xda
+#define SQ_V_CMPX_LE_U32 0xdb
+#define SQ_V_CMPX_GT_U32 0xdc
+#define SQ_V_CMPX_NE_U32 0xdd
+#define SQ_V_CMPX_GE_U32 0xde
+#define SQ_V_CMPX_T_U32 0xdf
+#define SQ_V_CMP_F_I64 0xe0
+#define SQ_V_CMP_LT_I64 0xe1
+#define SQ_V_CMP_EQ_I64 0xe2
+#define SQ_V_CMP_LE_I64 0xe3
+#define SQ_V_CMP_GT_I64 0xe4
+#define SQ_V_CMP_NE_I64 0xe5
+#define SQ_V_CMP_GE_I64 0xe6
+#define SQ_V_CMP_T_I64 0xe7
+#define SQ_V_CMP_F_U64 0xe8
+#define SQ_V_CMP_LT_U64 0xe9
+#define SQ_V_CMP_EQ_U64 0xea
+#define SQ_V_CMP_LE_U64 0xeb
+#define SQ_V_CMP_GT_U64 0xec
+#define SQ_V_CMP_NE_U64 0xed
+#define SQ_V_CMP_GE_U64 0xee
+#define SQ_V_CMP_T_U64 0xef
+#define SQ_V_CMPX_F_I64 0xf0
+#define SQ_V_CMPX_LT_I64 0xf1
+#define SQ_V_CMPX_EQ_I64 0xf2
+#define SQ_V_CMPX_LE_I64 0xf3
+#define SQ_V_CMPX_GT_I64 0xf4
+#define SQ_V_CMPX_NE_I64 0xf5
+#define SQ_V_CMPX_GE_I64 0xf6
+#define SQ_V_CMPX_T_I64 0xf7
+#define SQ_V_CMPX_F_U64 0xf8
+#define SQ_V_CMPX_LT_U64 0xf9
+#define SQ_V_CMPX_EQ_U64 0xfa
+#define SQ_V_CMPX_LE_U64 0xfb
+#define SQ_V_CMPX_GT_U64 0xfc
+#define SQ_V_CMPX_NE_U64 0xfd
+#define SQ_V_CMPX_GE_U64 0xfe
+#define SQ_V_CMPX_T_U64 0xff
+#define SQ_L1 0x1
+#define SQ_L2 0x2
+#define SQ_L3 0x3
+#define SQ_L4 0x4
+#define SQ_L5 0x5
+#define SQ_L6 0x6
+#define SQ_L7 0x7
+#define SQ_L8 0x8
+#define SQ_L9 0x9
+#define SQ_L10 0xa
+#define SQ_L11 0xb
+#define SQ_L12 0xc
+#define SQ_L13 0xd
+#define SQ_L14 0xe
+#define SQ_L15 0xf
+#define SQ_SGPR0 0x0
+#define SQ_SDWA_UNUSED_PAD 0x0
+#define SQ_SDWA_UNUSED_SEXT 0x1
+#define SQ_SDWA_UNUSED_PRESERVE 0x2
+#define SQ_F 0x0
+#define SQ_LT 0x1
+#define SQ_EQ 0x2
+#define SQ_LE 0x3
+#define SQ_GT 0x4
+#define SQ_NE 0x5
+#define SQ_GE 0x6
+#define SQ_T 0x7
+#define SQ_SRC_64_INT 0xc0
+#define SQ_SRC_M_1_INT 0xc1
+#define SQ_SRC_M_2_INT 0xc2
+#define SQ_SRC_M_3_INT 0xc3
+#define SQ_SRC_M_4_INT 0xc4
+#define SQ_SRC_M_5_INT 0xc5
+#define SQ_SRC_M_6_INT 0xc6
+#define SQ_SRC_M_7_INT 0xc7
+#define SQ_SRC_M_8_INT 0xc8
+#define SQ_SRC_M_9_INT 0xc9
+#define SQ_SRC_M_10_INT 0xca
+#define SQ_SRC_M_11_INT 0xcb
+#define SQ_SRC_M_12_INT 0xcc
+#define SQ_SRC_M_13_INT 0xcd
+#define SQ_SRC_M_14_INT 0xce
+#define SQ_SRC_M_15_INT 0xcf
+#define SQ_SRC_M_16_INT 0xd0
+#define SQ_SRC_0_5 0xf0
+#define SQ_SRC_M_0_5 0xf1
+#define SQ_SRC_1 0xf2
+#define SQ_SRC_M_1 0xf3
+#define SQ_SRC_2 0xf4
+#define SQ_SRC_M_2 0xf5
+#define SQ_SRC_4 0xf6
+#define SQ_SRC_M_4 0xf7
+#define SQ_SRC_INV_2PI 0xf8
+#define SQ_SRC_0 0x80
+#define SQ_SRC_1_INT 0x81
+#define SQ_SRC_2_INT 0x82
+#define SQ_SRC_3_INT 0x83
+#define SQ_SRC_4_INT 0x84
+#define SQ_SRC_5_INT 0x85
+#define SQ_SRC_6_INT 0x86
+#define SQ_SRC_7_INT 0x87
+#define SQ_SRC_8_INT 0x88
+#define SQ_SRC_9_INT 0x89
+#define SQ_SRC_10_INT 0x8a
+#define SQ_SRC_11_INT 0x8b
+#define SQ_SRC_12_INT 0x8c
+#define SQ_SRC_13_INT 0x8d
+#define SQ_SRC_14_INT 0x8e
+#define SQ_SRC_15_INT 0x8f
+#define SQ_SRC_16_INT 0x90
+#define SQ_SRC_17_INT 0x91
+#define SQ_SRC_18_INT 0x92
+#define SQ_SRC_19_INT 0x93
+#define SQ_SRC_20_INT 0x94
+#define SQ_SRC_21_INT 0x95
+#define SQ_SRC_22_INT 0x96
+#define SQ_SRC_23_INT 0x97
+#define SQ_SRC_24_INT 0x98
+#define SQ_SRC_25_INT 0x99
+#define SQ_SRC_26_INT 0x9a
+#define SQ_SRC_27_INT 0x9b
+#define SQ_SRC_28_INT 0x9c
+#define SQ_SRC_29_INT 0x9d
+#define SQ_SRC_30_INT 0x9e
+#define SQ_SRC_31_INT 0x9f
+#define SQ_SRC_32_INT 0xa0
+#define SQ_SRC_33_INT 0xa1
+#define SQ_SRC_34_INT 0xa2
+#define SQ_SRC_35_INT 0xa3
+#define SQ_SRC_36_INT 0xa4
+#define SQ_SRC_37_INT 0xa5
+#define SQ_SRC_38_INT 0xa6
+#define SQ_SRC_39_INT 0xa7
+#define SQ_SRC_40_INT 0xa8
+#define SQ_SRC_41_INT 0xa9
+#define SQ_SRC_42_INT 0xaa
+#define SQ_SRC_43_INT 0xab
+#define SQ_SRC_44_INT 0xac
+#define SQ_SRC_45_INT 0xad
+#define SQ_SRC_46_INT 0xae
+#define SQ_SRC_47_INT 0xaf
+#define SQ_SRC_48_INT 0xb0
+#define SQ_SRC_49_INT 0xb1
+#define SQ_SRC_50_INT 0xb2
+#define SQ_SRC_51_INT 0xb3
+#define SQ_SRC_52_INT 0xb4
+#define SQ_SRC_53_INT 0xb5
+#define SQ_SRC_54_INT 0xb6
+#define SQ_SRC_55_INT 0xb7
+#define SQ_SRC_56_INT 0xb8
+#define SQ_SRC_57_INT 0xb9
+#define SQ_SRC_58_INT 0xba
+#define SQ_SRC_59_INT 0xbb
+#define SQ_SRC_60_INT 0xbc
+#define SQ_SRC_61_INT 0xbd
+#define SQ_SRC_62_INT 0xbe
+#define SQ_SRC_63_INT 0xbf
+#define SQ_DS_ADD_U32 0x0
+#define SQ_DS_SUB_U32 0x1
+#define SQ_DS_RSUB_U32 0x2
+#define SQ_DS_INC_U32 0x3
+#define SQ_DS_DEC_U32 0x4
+#define SQ_DS_MIN_I32 0x5
+#define SQ_DS_MAX_I32 0x6
+#define SQ_DS_MIN_U32 0x7
+#define SQ_DS_MAX_U32 0x8
+#define SQ_DS_AND_B32 0x9
+#define SQ_DS_OR_B32 0xa
+#define SQ_DS_XOR_B32 0xb
+#define SQ_DS_MSKOR_B32 0xc
+#define SQ_DS_WRITE_B32 0xd
+#define SQ_DS_WRITE2_B32 0xe
+#define SQ_DS_WRITE2ST64_B32 0xf
+#define SQ_DS_CMPST_B32 0x10
+#define SQ_DS_CMPST_F32 0x11
+#define SQ_DS_MIN_F32 0x12
+#define SQ_DS_MAX_F32 0x13
+#define SQ_DS_NOP 0x14
+#define SQ_DS_ADD_F32 0x15
+#define SQ_DS_WRITE_B8 0x1e
+#define SQ_DS_WRITE_B16 0x1f
+#define SQ_DS_ADD_RTN_U32 0x20
+#define SQ_DS_SUB_RTN_U32 0x21
+#define SQ_DS_RSUB_RTN_U32 0x22
+#define SQ_DS_INC_RTN_U32 0x23
+#define SQ_DS_DEC_RTN_U32 0x24
+#define SQ_DS_MIN_RTN_I32 0x25
+#define SQ_DS_MAX_RTN_I32 0x26
+#define SQ_DS_MIN_RTN_U32 0x27
+#define SQ_DS_MAX_RTN_U32 0x28
+#define SQ_DS_AND_RTN_B32 0x29
+#define SQ_DS_OR_RTN_B32 0x2a
+#define SQ_DS_XOR_RTN_B32 0x2b
+#define SQ_DS_MSKOR_RTN_B32 0x2c
+#define SQ_DS_WRXCHG_RTN_B32 0x2d
+#define SQ_DS_WRXCHG2_RTN_B32 0x2e
+#define SQ_DS_WRXCHG2ST64_RTN_B32 0x2f
+#define SQ_DS_CMPST_RTN_B32 0x30
+#define SQ_DS_CMPST_RTN_F32 0x31
+#define SQ_DS_MIN_RTN_F32 0x32
+#define SQ_DS_MAX_RTN_F32 0x33
+#define SQ_DS_WRAP_RTN_B32 0x34
+#define SQ_DS_ADD_RTN_F32 0x35
+#define SQ_DS_READ_B32 0x36
+#define SQ_DS_READ2_B32 0x37
+#define SQ_DS_READ2ST64_B32 0x38
+#define SQ_DS_READ_I8 0x39
+#define SQ_DS_READ_U8 0x3a
+#define SQ_DS_READ_I16 0x3b
+#define SQ_DS_READ_U16 0x3c
+#define SQ_DS_SWIZZLE_B32 0x3d
+#define SQ_DS_PERMUTE_B32 0x3e
+#define SQ_DS_BPERMUTE_B32 0x3f
+#define SQ_DS_ADD_U64 0x40
+#define SQ_DS_SUB_U64 0x41
+#define SQ_DS_RSUB_U64 0x42
+#define SQ_DS_INC_U64 0x43
+#define SQ_DS_DEC_U64 0x44
+#define SQ_DS_MIN_I64 0x45
+#define SQ_DS_MAX_I64 0x46
+#define SQ_DS_MIN_U64 0x47
+#define SQ_DS_MAX_U64 0x48
+#define SQ_DS_AND_B64 0x49
+#define SQ_DS_OR_B64 0x4a
+#define SQ_DS_XOR_B64 0x4b
+#define SQ_DS_MSKOR_B64 0x4c
+#define SQ_DS_WRITE_B64 0x4d
+#define SQ_DS_WRITE2_B64 0x4e
+#define SQ_DS_WRITE2ST64_B64 0x4f
+#define SQ_DS_CMPST_B64 0x50
+#define SQ_DS_CMPST_F64 0x51
+#define SQ_DS_MIN_F64 0x52
+#define SQ_DS_MAX_F64 0x53
+#define SQ_DS_ADD_RTN_U64 0x60
+#define SQ_DS_SUB_RTN_U64 0x61
+#define SQ_DS_RSUB_RTN_U64 0x62
+#define SQ_DS_INC_RTN_U64 0x63
+#define SQ_DS_DEC_RTN_U64 0x64
+#define SQ_DS_MIN_RTN_I64 0x65
+#define SQ_DS_MAX_RTN_I64 0x66
+#define SQ_DS_MIN_RTN_U64 0x67
+#define SQ_DS_MAX_RTN_U64 0x68
+#define SQ_DS_AND_RTN_B64 0x69
+#define SQ_DS_OR_RTN_B64 0x6a
+#define SQ_DS_XOR_RTN_B64 0x6b
+#define SQ_DS_MSKOR_RTN_B64 0x6c
+#define SQ_DS_WRXCHG_RTN_B64 0x6d
+#define SQ_DS_WRXCHG2_RTN_B64 0x6e
+#define SQ_DS_WRXCHG2ST64_RTN_B64 0x6f
+#define SQ_DS_CMPST_RTN_B64 0x70
+#define SQ_DS_CMPST_RTN_F64 0x71
+#define SQ_DS_MIN_RTN_F64 0x72
+#define SQ_DS_MAX_RTN_F64 0x73
+#define SQ_DS_READ_B64 0x76
+#define SQ_DS_READ2_B64 0x77
+#define SQ_DS_READ2ST64_B64 0x78
+#define SQ_DS_CONDXCHG32_RTN_B64 0x7e
+#define SQ_DS_ADD_SRC2_U32 0x80
+#define SQ_DS_SUB_SRC2_U32 0x81
+#define SQ_DS_RSUB_SRC2_U32 0x82
+#define SQ_DS_INC_SRC2_U32 0x83
+#define SQ_DS_DEC_SRC2_U32 0x84
+#define SQ_DS_MIN_SRC2_I32 0x85
+#define SQ_DS_MAX_SRC2_I32 0x86
+#define SQ_DS_MIN_SRC2_U32 0x87
+#define SQ_DS_MAX_SRC2_U32 0x88
+#define SQ_DS_AND_SRC2_B32 0x89
+#define SQ_DS_OR_SRC2_B32 0x8a
+#define SQ_DS_XOR_SRC2_B32 0x8b
+#define SQ_DS_WRITE_SRC2_B32 0x8d
+#define SQ_DS_MIN_SRC2_F32 0x92
+#define SQ_DS_MAX_SRC2_F32 0x93
+#define SQ_DS_ADD_SRC2_F32 0x95
+#define SQ_DS_GWS_SEMA_RELEASE_ALL 0x98
+#define SQ_DS_GWS_INIT 0x99
+#define SQ_DS_GWS_SEMA_V 0x9a
+#define SQ_DS_GWS_SEMA_BR 0x9b
+#define SQ_DS_GWS_SEMA_P 0x9c
+#define SQ_DS_GWS_BARRIER 0x9d
+#define SQ_DS_CONSUME 0xbd
+#define SQ_DS_APPEND 0xbe
+#define SQ_DS_ORDERED_COUNT 0xbf
+#define SQ_DS_ADD_SRC2_U64 0xc0
+#define SQ_DS_SUB_SRC2_U64 0xc1
+#define SQ_DS_RSUB_SRC2_U64 0xc2
+#define SQ_DS_INC_SRC2_U64 0xc3
+#define SQ_DS_DEC_SRC2_U64 0xc4
+#define SQ_DS_MIN_SRC2_I64 0xc5
+#define SQ_DS_MAX_SRC2_I64 0xc6
+#define SQ_DS_MIN_SRC2_U64 0xc7
+#define SQ_DS_MAX_SRC2_U64 0xc8
+#define SQ_DS_AND_SRC2_B64 0xc9
+#define SQ_DS_OR_SRC2_B64 0xca
+#define SQ_DS_XOR_SRC2_B64 0xcb
+#define SQ_DS_WRITE_SRC2_B64 0xcd
+#define SQ_DS_MIN_SRC2_F64 0xd2
+#define SQ_DS_MAX_SRC2_F64 0xd3
+#define SQ_DS_WRITE_B96 0xde
+#define SQ_DS_WRITE_B128 0xdf
+#define SQ_DS_CONDXCHG32_RTN_B128 0xfd
+#define SQ_DS_READ_B96 0xfe
+#define SQ_DS_READ_B128 0xff
+#define SQ_BUFFER_LOAD_FORMAT_X 0x0
+#define SQ_BUFFER_LOAD_FORMAT_XY 0x1
+#define SQ_BUFFER_LOAD_FORMAT_XYZ 0x2
+#define SQ_BUFFER_LOAD_FORMAT_XYZW 0x3
+#define SQ_BUFFER_STORE_FORMAT_X 0x4
+#define SQ_BUFFER_STORE_FORMAT_XY 0x5
+#define SQ_BUFFER_STORE_FORMAT_XYZ 0x6
+#define SQ_BUFFER_STORE_FORMAT_XYZW 0x7
+#define SQ_BUFFER_LOAD_FORMAT_D16_X 0x8
+#define SQ_BUFFER_LOAD_FORMAT_D16_XY 0x9
+#define SQ_BUFFER_LOAD_FORMAT_D16_XYZ 0xa
+#define SQ_BUFFER_LOAD_FORMAT_D16_XYZW 0xb
+#define SQ_BUFFER_STORE_FORMAT_D16_X 0xc
+#define SQ_BUFFER_STORE_FORMAT_D16_XY 0xd
+#define SQ_BUFFER_STORE_FORMAT_D16_XYZ 0xe
+#define SQ_BUFFER_STORE_FORMAT_D16_XYZW 0xf
+#define SQ_BUFFER_LOAD_UBYTE 0x10
+#define SQ_BUFFER_LOAD_SBYTE 0x11
+#define SQ_BUFFER_LOAD_USHORT 0x12
+#define SQ_BUFFER_LOAD_SSHORT 0x13
+#define SQ_BUFFER_LOAD_DWORD 0x14
+#define SQ_BUFFER_LOAD_DWORDX2 0x15
+#define SQ_BUFFER_LOAD_DWORDX3 0x16
+#define SQ_BUFFER_LOAD_DWORDX4 0x17
+#define SQ_BUFFER_STORE_BYTE 0x18
+#define SQ_BUFFER_STORE_SHORT 0x1a
+#define SQ_BUFFER_STORE_DWORD 0x1c
+#define SQ_BUFFER_STORE_DWORDX2 0x1d
+#define SQ_BUFFER_STORE_DWORDX3 0x1e
+#define SQ_BUFFER_STORE_DWORDX4 0x1f
+#define SQ_BUFFER_STORE_LDS_DWORD 0x3d
+#define SQ_BUFFER_WBINVL1 0x3e
+#define SQ_BUFFER_WBINVL1_VOL 0x3f
+#define SQ_BUFFER_ATOMIC_SWAP 0x40
+#define SQ_BUFFER_ATOMIC_CMPSWAP 0x41
+#define SQ_BUFFER_ATOMIC_ADD 0x42
+#define SQ_BUFFER_ATOMIC_SUB 0x43
+#define SQ_BUFFER_ATOMIC_SMIN 0x44
+#define SQ_BUFFER_ATOMIC_UMIN 0x45
+#define SQ_BUFFER_ATOMIC_SMAX 0x46
+#define SQ_BUFFER_ATOMIC_UMAX 0x47
+#define SQ_BUFFER_ATOMIC_AND 0x48
+#define SQ_BUFFER_ATOMIC_OR 0x49
+#define SQ_BUFFER_ATOMIC_XOR 0x4a
+#define SQ_BUFFER_ATOMIC_INC 0x4b
+#define SQ_BUFFER_ATOMIC_DEC 0x4c
+#define SQ_BUFFER_ATOMIC_SWAP_X2 0x60
+#define SQ_BUFFER_ATOMIC_CMPSWAP_X2 0x61
+#define SQ_BUFFER_ATOMIC_ADD_X2 0x62
+#define SQ_BUFFER_ATOMIC_SUB_X2 0x63
+#define SQ_BUFFER_ATOMIC_SMIN_X2 0x64
+#define SQ_BUFFER_ATOMIC_UMIN_X2 0x65
+#define SQ_BUFFER_ATOMIC_SMAX_X2 0x66
+#define SQ_BUFFER_ATOMIC_UMAX_X2 0x67
+#define SQ_BUFFER_ATOMIC_AND_X2 0x68
+#define SQ_BUFFER_ATOMIC_OR_X2 0x69
+#define SQ_BUFFER_ATOMIC_XOR_X2 0x6a
+#define SQ_BUFFER_ATOMIC_INC_X2 0x6b
+#define SQ_BUFFER_ATOMIC_DEC_X2 0x6c
+#define SQ_EXEC_LO 0x7e
+#define SQ_EXEC_HI 0x7f
+#define SQ_SRC_SCC 0xfd
+#define SQ_OMOD_OFF 0x0
+#define SQ_OMOD_M2 0x1
+#define SQ_OMOD_M4 0x2
+#define SQ_OMOD_D2 0x3
+#define SQ_DPP_QUAD_PERM 0x0
+#define SQ_DPP_ROW_SL1 0x101
+#define SQ_DPP_ROW_SL2 0x102
+#define SQ_DPP_ROW_SL3 0x103
+#define SQ_DPP_ROW_SL4 0x104
+#define SQ_DPP_ROW_SL5 0x105
+#define SQ_DPP_ROW_SL6 0x106
+#define SQ_DPP_ROW_SL7 0x107
+#define SQ_DPP_ROW_SL8 0x108
+#define SQ_DPP_ROW_SL9 0x109
+#define SQ_DPP_ROW_SL10 0x10a
+#define SQ_DPP_ROW_SL11 0x10b
+#define SQ_DPP_ROW_SL12 0x10c
+#define SQ_DPP_ROW_SL13 0x10d
+#define SQ_DPP_ROW_SL14 0x10e
+#define SQ_DPP_ROW_SL15 0x10f
+#define SQ_DPP_ROW_SR1 0x111
+#define SQ_DPP_ROW_SR2 0x112
+#define SQ_DPP_ROW_SR3 0x113
+#define SQ_DPP_ROW_SR4 0x114
+#define SQ_DPP_ROW_SR5 0x115
+#define SQ_DPP_ROW_SR6 0x116
+#define SQ_DPP_ROW_SR7 0x117
+#define SQ_DPP_ROW_SR8 0x118
+#define SQ_DPP_ROW_SR9 0x119
+#define SQ_DPP_ROW_SR10 0x11a
+#define SQ_DPP_ROW_SR11 0x11b
+#define SQ_DPP_ROW_SR12 0x11c
+#define SQ_DPP_ROW_SR13 0x11d
+#define SQ_DPP_ROW_SR14 0x11e
+#define SQ_DPP_ROW_SR15 0x11f
+#define SQ_DPP_ROW_RR1 0x121
+#define SQ_DPP_ROW_RR2 0x122
+#define SQ_DPP_ROW_RR3 0x123
+#define SQ_DPP_ROW_RR4 0x124
+#define SQ_DPP_ROW_RR5 0x125
+#define SQ_DPP_ROW_RR6 0x126
+#define SQ_DPP_ROW_RR7 0x127
+#define SQ_DPP_ROW_RR8 0x128
+#define SQ_DPP_ROW_RR9 0x129
+#define SQ_DPP_ROW_RR10 0x12a
+#define SQ_DPP_ROW_RR11 0x12b
+#define SQ_DPP_ROW_RR12 0x12c
+#define SQ_DPP_ROW_RR13 0x12d
+#define SQ_DPP_ROW_RR14 0x12e
+#define SQ_DPP_ROW_RR15 0x12f
+#define SQ_DPP_WF_SL1 0x130
+#define SQ_DPP_WF_RL1 0x134
+#define SQ_DPP_WF_SR1 0x138
+#define SQ_DPP_WF_RR1 0x13c
+#define SQ_DPP_ROW_MIRROR 0x140
+#define SQ_DPP_ROW_HALF_MIRROR 0x141
+#define SQ_DPP_ROW_BCAST15 0x142
+#define SQ_DPP_ROW_BCAST31 0x143
+#define SQ_EXP_GDS0 0x18
+#define SQ_GS_OP_NOP 0x0
+#define SQ_GS_OP_CUT 0x1
+#define SQ_GS_OP_EMIT 0x2
+#define SQ_GS_OP_EMIT_CUT 0x3
+#define SQ_IMAGE_LOAD 0x0
+#define SQ_IMAGE_LOAD_MIP 0x1
+#define SQ_IMAGE_LOAD_PCK 0x2
+#define SQ_IMAGE_LOAD_PCK_SGN 0x3
+#define SQ_IMAGE_LOAD_MIP_PCK 0x4
+#define SQ_IMAGE_LOAD_MIP_PCK_SGN 0x5
+#define SQ_IMAGE_STORE 0x8
+#define SQ_IMAGE_STORE_MIP 0x9
+#define SQ_IMAGE_STORE_PCK 0xa
+#define SQ_IMAGE_STORE_MIP_PCK 0xb
+#define SQ_IMAGE_GET_RESINFO 0xe
+#define SQ_IMAGE_ATOMIC_SWAP 0x10
+#define SQ_IMAGE_ATOMIC_CMPSWAP 0x11
+#define SQ_IMAGE_ATOMIC_ADD 0x12
+#define SQ_IMAGE_ATOMIC_SUB 0x13
+#define SQ_IMAGE_ATOMIC_SMIN 0x14
+#define SQ_IMAGE_ATOMIC_UMIN 0x15
+#define SQ_IMAGE_ATOMIC_SMAX 0x16
+#define SQ_IMAGE_ATOMIC_UMAX 0x17
+#define SQ_IMAGE_ATOMIC_AND 0x18
+#define SQ_IMAGE_ATOMIC_OR 0x19
+#define SQ_IMAGE_ATOMIC_XOR 0x1a
+#define SQ_IMAGE_ATOMIC_INC 0x1b
+#define SQ_IMAGE_ATOMIC_DEC 0x1c
+#define SQ_IMAGE_SAMPLE 0x20
+#define SQ_IMAGE_SAMPLE_CL 0x21
+#define SQ_IMAGE_SAMPLE_D 0x22
+#define SQ_IMAGE_SAMPLE_D_CL 0x23
+#define SQ_IMAGE_SAMPLE_L 0x24
+#define SQ_IMAGE_SAMPLE_B 0x25
+#define SQ_IMAGE_SAMPLE_B_CL 0x26
+#define SQ_IMAGE_SAMPLE_LZ 0x27
+#define SQ_IMAGE_SAMPLE_C 0x28
+#define SQ_IMAGE_SAMPLE_C_CL 0x29
+#define SQ_IMAGE_SAMPLE_C_D 0x2a
+#define SQ_IMAGE_SAMPLE_C_D_CL 0x2b
+#define SQ_IMAGE_SAMPLE_C_L 0x2c
+#define SQ_IMAGE_SAMPLE_C_B 0x2d
+#define SQ_IMAGE_SAMPLE_C_B_CL 0x2e
+#define SQ_IMAGE_SAMPLE_C_LZ 0x2f
+#define SQ_IMAGE_SAMPLE_O 0x30
+#define SQ_IMAGE_SAMPLE_CL_O 0x31
+#define SQ_IMAGE_SAMPLE_D_O 0x32
+#define SQ_IMAGE_SAMPLE_D_CL_O 0x33
+#define SQ_IMAGE_SAMPLE_L_O 0x34
+#define SQ_IMAGE_SAMPLE_B_O 0x35
+#define SQ_IMAGE_SAMPLE_B_CL_O 0x36
+#define SQ_IMAGE_SAMPLE_LZ_O 0x37
+#define SQ_IMAGE_SAMPLE_C_O 0x38
+#define SQ_IMAGE_SAMPLE_C_CL_O 0x39
+#define SQ_IMAGE_SAMPLE_C_D_O 0x3a
+#define SQ_IMAGE_SAMPLE_C_D_CL_O 0x3b
+#define SQ_IMAGE_SAMPLE_C_L_O 0x3c
+#define SQ_IMAGE_SAMPLE_C_B_O 0x3d
+#define SQ_IMAGE_SAMPLE_C_B_CL_O 0x3e
+#define SQ_IMAGE_SAMPLE_C_LZ_O 0x3f
+#define SQ_IMAGE_GATHER4 0x40
+#define SQ_IMAGE_GATHER4_CL 0x41
+#define SQ_IMAGE_GATHER4_L 0x44
+#define SQ_IMAGE_GATHER4_B 0x45
+#define SQ_IMAGE_GATHER4_B_CL 0x46
+#define SQ_IMAGE_GATHER4_LZ 0x47
+#define SQ_IMAGE_GATHER4_C 0x48
+#define SQ_IMAGE_GATHER4_C_CL 0x49
+#define SQ_IMAGE_GATHER4_C_L 0x4c
+#define SQ_IMAGE_GATHER4_C_B 0x4d
+#define SQ_IMAGE_GATHER4_C_B_CL 0x4e
+#define SQ_IMAGE_GATHER4_C_LZ 0x4f
+#define SQ_IMAGE_GATHER4_O 0x50
+#define SQ_IMAGE_GATHER4_CL_O 0x51
+#define SQ_IMAGE_GATHER4_L_O 0x54
+#define SQ_IMAGE_GATHER4_B_O 0x55
+#define SQ_IMAGE_GATHER4_B_CL_O 0x56
+#define SQ_IMAGE_GATHER4_LZ_O 0x57
+#define SQ_IMAGE_GATHER4_C_O 0x58
+#define SQ_IMAGE_GATHER4_C_CL_O 0x59
+#define SQ_IMAGE_GATHER4_C_L_O 0x5c
+#define SQ_IMAGE_GATHER4_C_B_O 0x5d
+#define SQ_IMAGE_GATHER4_C_B_CL_O 0x5e
+#define SQ_IMAGE_GATHER4_C_LZ_O 0x5f
+#define SQ_IMAGE_GET_LOD 0x60
+#define SQ_IMAGE_SAMPLE_CD 0x68
+#define SQ_IMAGE_SAMPLE_CD_CL 0x69
+#define SQ_IMAGE_SAMPLE_C_CD 0x6a
+#define SQ_IMAGE_SAMPLE_C_CD_CL 0x6b
+#define SQ_IMAGE_SAMPLE_CD_O 0x6c
+#define SQ_IMAGE_SAMPLE_CD_CL_O 0x6d
+#define SQ_IMAGE_SAMPLE_C_CD_O 0x6e
+#define SQ_IMAGE_SAMPLE_C_CD_CL_O 0x6f
+#define SQ_IMAGE_RSRC256 0x7e
+#define SQ_IMAGE_SAMPLER 0x7f
+#define SQ_SRC_VCCZ 0xfb
+#define SQ_SRC_VGPR0 0x100
+#define SQ_SDWA_BYTE_0 0x0
+#define SQ_SDWA_BYTE_1 0x1
+#define SQ_SDWA_BYTE_2 0x2
+#define SQ_SDWA_BYTE_3 0x3
+#define SQ_SDWA_WORD_0 0x4
+#define SQ_SDWA_WORD_1 0x5
+#define SQ_SDWA_DWORD 0x6
+#define SQ_XNACK_MASK_LO 0x68
+#define SQ_XNACK_MASK_HI 0x69
+#define SQ_TBUFFER_LOAD_FORMAT_X 0x0
+#define SQ_TBUFFER_LOAD_FORMAT_XY 0x1
+#define SQ_TBUFFER_LOAD_FORMAT_XYZ 0x2
+#define SQ_TBUFFER_LOAD_FORMAT_XYZW 0x3
+#define SQ_TBUFFER_STORE_FORMAT_X 0x4
+#define SQ_TBUFFER_STORE_FORMAT_XY 0x5
+#define SQ_TBUFFER_STORE_FORMAT_XYZ 0x6
+#define SQ_TBUFFER_STORE_FORMAT_XYZW 0x7
+#define SQ_TBUFFER_LOAD_FORMAT_D16_X 0x8
+#define SQ_TBUFFER_LOAD_FORMAT_D16_XY 0x9
+#define SQ_TBUFFER_LOAD_FORMAT_D16_XYZ 0xa
+#define SQ_TBUFFER_LOAD_FORMAT_D16_XYZW 0xb
+#define SQ_TBUFFER_STORE_FORMAT_D16_X 0xc
+#define SQ_TBUFFER_STORE_FORMAT_D16_XY 0xd
+#define SQ_TBUFFER_STORE_FORMAT_D16_XYZ 0xe
+#define SQ_TBUFFER_STORE_FORMAT_D16_XYZW 0xf
+#define SQ_CHAN_X 0x0
+#define SQ_CHAN_Y 0x1
+#define SQ_CHAN_Z 0x2
+#define SQ_CHAN_W 0x3
+#define SQ_V_NOP 0x0
+#define SQ_V_MOV_B32 0x1
+#define SQ_V_READFIRSTLANE_B32 0x2
+#define SQ_V_CVT_I32_F64 0x3
+#define SQ_V_CVT_F64_I32 0x4
+#define SQ_V_CVT_F32_I32 0x5
+#define SQ_V_CVT_F32_U32 0x6
+#define SQ_V_CVT_U32_F32 0x7
+#define SQ_V_CVT_I32_F32 0x8
+#define SQ_V_MOV_FED_B32 0x9
+#define SQ_V_CVT_F16_F32 0xa
+#define SQ_V_CVT_F32_F16 0xb
+#define SQ_V_CVT_RPI_I32_F32 0xc
+#define SQ_V_CVT_FLR_I32_F32 0xd
+#define SQ_V_CVT_OFF_F32_I4 0xe
+#define SQ_V_CVT_F32_F64 0xf
+#define SQ_V_CVT_F64_F32 0x10
+#define SQ_V_CVT_F32_UBYTE0 0x11
+#define SQ_V_CVT_F32_UBYTE1 0x12
+#define SQ_V_CVT_F32_UBYTE2 0x13
+#define SQ_V_CVT_F32_UBYTE3 0x14
+#define SQ_V_CVT_U32_F64 0x15
+#define SQ_V_CVT_F64_U32 0x16
+#define SQ_V_TRUNC_F64 0x17
+#define SQ_V_CEIL_F64 0x18
+#define SQ_V_RNDNE_F64 0x19
+#define SQ_V_FLOOR_F64 0x1a
+#define SQ_V_FRACT_F32 0x1b
+#define SQ_V_TRUNC_F32 0x1c
+#define SQ_V_CEIL_F32 0x1d
+#define SQ_V_RNDNE_F32 0x1e
+#define SQ_V_FLOOR_F32 0x1f
+#define SQ_V_EXP_F32 0x20
+#define SQ_V_LOG_F32 0x21
+#define SQ_V_RCP_F32 0x22
+#define SQ_V_RCP_IFLAG_F32 0x23
+#define SQ_V_RSQ_F32 0x24
+#define SQ_V_RCP_F64 0x25
+#define SQ_V_RSQ_F64 0x26
+#define SQ_V_SQRT_F32 0x27
+#define SQ_V_SQRT_F64 0x28
+#define SQ_V_SIN_F32 0x29
+#define SQ_V_COS_F32 0x2a
+#define SQ_V_NOT_B32 0x2b
+#define SQ_V_BFREV_B32 0x2c
+#define SQ_V_FFBH_U32 0x2d
+#define SQ_V_FFBL_B32 0x2e
+#define SQ_V_FFBH_I32 0x2f
+#define SQ_V_FREXP_EXP_I32_F64 0x30
+#define SQ_V_FREXP_MANT_F64 0x31
+#define SQ_V_FRACT_F64 0x32
+#define SQ_V_FREXP_EXP_I32_F32 0x33
+#define SQ_V_FREXP_MANT_F32 0x34
+#define SQ_V_CLREXCP 0x35
+#define SQ_V_MOVRELD_B32 0x36
+#define SQ_V_MOVRELS_B32 0x37
+#define SQ_V_MOVRELSD_B32 0x38
+#define SQ_V_CVT_F16_U16 0x39
+#define SQ_V_CVT_F16_I16 0x3a
+#define SQ_V_CVT_U16_F16 0x3b
+#define SQ_V_CVT_I16_F16 0x3c
+#define SQ_V_RCP_F16 0x3d
+#define SQ_V_SQRT_F16 0x3e
+#define SQ_V_RSQ_F16 0x3f
+#define SQ_V_LOG_F16 0x40
+#define SQ_V_EXP_F16 0x41
+#define SQ_V_FREXP_MANT_F16 0x42
+#define SQ_V_FREXP_EXP_I16_F16 0x43
+#define SQ_V_FLOOR_F16 0x44
+#define SQ_V_CEIL_F16 0x45
+#define SQ_V_TRUNC_F16 0x46
+#define SQ_V_RNDNE_F16 0x47
+#define SQ_V_FRACT_F16 0x48
+#define SQ_V_SIN_F16 0x49
+#define SQ_V_COS_F16 0x4a
+#define SQ_V_EXP_LEGACY_F32 0x4b
+#define SQ_V_LOG_LEGACY_F32 0x4c
+#define SQ_V_CVT_NORM_I16_F16 0x4d
+#define SQ_V_CVT_NORM_U16_F16 0x4e
+#define SQ_SRC_SDWA 0xf9
+#define SQ_V_OPC_OFFSET 0x0
+#define SQ_V_OP2_OFFSET 0x100
+#define SQ_V_OP1_OFFSET 0x140
+#define SQ_V_INTRP_OFFSET 0x270
+#define SQ_V_INTERP_P1_F32 0x0
+#define SQ_V_INTERP_P2_F32 0x1
+#define SQ_V_INTERP_MOV_F32 0x2
+#define SQ_S_NOP 0x0
+#define SQ_S_ENDPGM 0x1
+#define SQ_S_BRANCH 0x2
+#define SQ_S_WAKEUP 0x3
+#define SQ_S_CBRANCH_SCC0 0x4
+#define SQ_S_CBRANCH_SCC1 0x5
+#define SQ_S_CBRANCH_VCCZ 0x6
+#define SQ_S_CBRANCH_VCCNZ 0x7
+#define SQ_S_CBRANCH_EXECZ 0x8
+#define SQ_S_CBRANCH_EXECNZ 0x9
+#define SQ_S_BARRIER 0xa
+#define SQ_S_SETKILL 0xb
+#define SQ_S_WAITCNT 0xc
+#define SQ_S_SETHALT 0xd
+#define SQ_S_SLEEP 0xe
+#define SQ_S_SETPRIO 0xf
+#define SQ_S_SENDMSG 0x10
+#define SQ_S_SENDMSGHALT 0x11
+#define SQ_S_TRAP 0x12
+#define SQ_S_ICACHE_INV 0x13
+#define SQ_S_INCPERFLEVEL 0x14
+#define SQ_S_DECPERFLEVEL 0x15
+#define SQ_S_TTRACEDATA 0x16
+#define SQ_S_CBRANCH_CDBGSYS 0x17
+#define SQ_S_CBRANCH_CDBGUSER 0x18
+#define SQ_S_CBRANCH_CDBGSYS_OR_USER 0x19
+#define SQ_S_CBRANCH_CDBGSYS_AND_USER 0x1a
+#define SQ_S_ENDPGM_SAVED 0x1b
+#define SQ_S_SET_GPR_IDX_OFF 0x1c
+#define SQ_S_SET_GPR_IDX_MODE 0x1d
+#define SQ_SRC_DPP 0xfa
+#define SQ_SRC_LITERAL 0xff
+#define SQ_VCC_LO 0x6a
+#define SQ_VCC_HI 0x6b
+#define SQ_PARAM_P10 0x0
+#define SQ_PARAM_P20 0x1
+#define SQ_PARAM_P0 0x2
+#define SQ_SRC_LDS_DIRECT 0xfe
+#define SQ_V_CNDMASK_B32 0x0
+#define SQ_V_ADD_F32 0x1
+#define SQ_V_SUB_F32 0x2
+#define SQ_V_SUBREV_F32 0x3
+#define SQ_V_MUL_LEGACY_F32 0x4
+#define SQ_V_MUL_F32 0x5
+#define SQ_V_MUL_I32_I24 0x6
+#define SQ_V_MUL_HI_I32_I24 0x7
+#define SQ_V_MUL_U32_U24 0x8
+#define SQ_V_MUL_HI_U32_U24 0x9
+#define SQ_V_MIN_F32 0xa
+#define SQ_V_MAX_F32 0xb
+#define SQ_V_MIN_I32 0xc
+#define SQ_V_MAX_I32 0xd
+#define SQ_V_MIN_U32 0xe
+#define SQ_V_MAX_U32 0xf
+#define SQ_V_LSHRREV_B32 0x10
+#define SQ_V_ASHRREV_I32 0x11
+#define SQ_V_LSHLREV_B32 0x12
+#define SQ_V_AND_B32 0x13
+#define SQ_V_OR_B32 0x14
+#define SQ_V_XOR_B32 0x15
+#define SQ_V_MAC_F32 0x16
+#define SQ_V_MADMK_F32 0x17
+#define SQ_V_MADAK_F32 0x18
+#define SQ_V_ADD_U32 0x19
+#define SQ_V_SUB_U32 0x1a
+#define SQ_V_SUBREV_U32 0x1b
+#define SQ_V_ADDC_U32 0x1c
+#define SQ_V_SUBB_U32 0x1d
+#define SQ_V_SUBBREV_U32 0x1e
+#define SQ_V_ADD_F16 0x1f
+#define SQ_V_SUB_F16 0x20
+#define SQ_V_SUBREV_F16 0x21
+#define SQ_V_MUL_F16 0x22
+#define SQ_V_MAC_F16 0x23
+#define SQ_V_MADMK_F16 0x24
+#define SQ_V_MADAK_F16 0x25
+#define SQ_V_ADD_U16 0x26
+#define SQ_V_SUB_U16 0x27
+#define SQ_V_SUBREV_U16 0x28
+#define SQ_V_MUL_LO_U16 0x29
+#define SQ_V_LSHLREV_B16 0x2a
+#define SQ_V_LSHRREV_B16 0x2b
+#define SQ_V_ASHRREV_I16 0x2c
+#define SQ_V_MAX_F16 0x2d
+#define SQ_V_MIN_F16 0x2e
+#define SQ_V_MAX_U16 0x2f
+#define SQ_V_MAX_I16 0x30
+#define SQ_V_MIN_U16 0x31
+#define SQ_V_MIN_I16 0x32
+#define SQ_V_LDEXP_F16 0x33
+#define SQ_FLAT_LOAD_UBYTE 0x10
+#define SQ_FLAT_LOAD_SBYTE 0x11
+#define SQ_FLAT_LOAD_USHORT 0x12
+#define SQ_FLAT_LOAD_SSHORT 0x13
+#define SQ_FLAT_LOAD_DWORD 0x14
+#define SQ_FLAT_LOAD_DWORDX2 0x15
+#define SQ_FLAT_LOAD_DWORDX3 0x16
+#define SQ_FLAT_LOAD_DWORDX4 0x17
+#define SQ_FLAT_STORE_BYTE 0x18
+#define SQ_FLAT_STORE_SHORT 0x1a
+#define SQ_FLAT_STORE_DWORD 0x1c
+#define SQ_FLAT_STORE_DWORDX2 0x1d
+#define SQ_FLAT_STORE_DWORDX3 0x1e
+#define SQ_FLAT_STORE_DWORDX4 0x1f
+#define SQ_FLAT_ATOMIC_SWAP 0x40
+#define SQ_FLAT_ATOMIC_CMPSWAP 0x41
+#define SQ_FLAT_ATOMIC_ADD 0x42
+#define SQ_FLAT_ATOMIC_SUB 0x43
+#define SQ_FLAT_ATOMIC_SMIN 0x44
+#define SQ_FLAT_ATOMIC_UMIN 0x45
+#define SQ_FLAT_ATOMIC_SMAX 0x46
+#define SQ_FLAT_ATOMIC_UMAX 0x47
+#define SQ_FLAT_ATOMIC_AND 0x48
+#define SQ_FLAT_ATOMIC_OR 0x49
+#define SQ_FLAT_ATOMIC_XOR 0x4a
+#define SQ_FLAT_ATOMIC_INC 0x4b
+#define SQ_FLAT_ATOMIC_DEC 0x4c
+#define SQ_FLAT_ATOMIC_SWAP_X2 0x60
+#define SQ_FLAT_ATOMIC_CMPSWAP_X2 0x61
+#define SQ_FLAT_ATOMIC_ADD_X2 0x62
+#define SQ_FLAT_ATOMIC_SUB_X2 0x63
+#define SQ_FLAT_ATOMIC_SMIN_X2 0x64
+#define SQ_FLAT_ATOMIC_UMIN_X2 0x65
+#define SQ_FLAT_ATOMIC_SMAX_X2 0x66
+#define SQ_FLAT_ATOMIC_UMAX_X2 0x67
+#define SQ_FLAT_ATOMIC_AND_X2 0x68
+#define SQ_FLAT_ATOMIC_OR_X2 0x69
+#define SQ_FLAT_ATOMIC_XOR_X2 0x6a
+#define SQ_FLAT_ATOMIC_INC_X2 0x6b
+#define SQ_FLAT_ATOMIC_DEC_X2 0x6c
+#define SQ_S_CMP_EQ_I32 0x0
+#define SQ_S_CMP_LG_I32 0x1
+#define SQ_S_CMP_GT_I32 0x2
+#define SQ_S_CMP_GE_I32 0x3
+#define SQ_S_CMP_LT_I32 0x4
+#define SQ_S_CMP_LE_I32 0x5
+#define SQ_S_CMP_EQ_U32 0x6
+#define SQ_S_CMP_LG_U32 0x7
+#define SQ_S_CMP_GT_U32 0x8
+#define SQ_S_CMP_GE_U32 0x9
+#define SQ_S_CMP_LT_U32 0xa
+#define SQ_S_CMP_LE_U32 0xb
+#define SQ_S_BITCMP0_B32 0xc
+#define SQ_S_BITCMP1_B32 0xd
+#define SQ_S_BITCMP0_B64 0xe
+#define SQ_S_BITCMP1_B64 0xf
+#define SQ_S_SETVSKIP 0x10
+#define SQ_S_SET_GPR_IDX_ON 0x11
+#define SQ_S_CMP_EQ_U64 0x12
+#define SQ_S_CMP_LG_U64 0x13
+#define SQ_M0 0x7c
+#define SQ_V_MAD_LEGACY_F32 0x1c0
+#define SQ_V_MAD_F32 0x1c1
+#define SQ_V_MAD_I32_I24 0x1c2
+#define SQ_V_MAD_U32_U24 0x1c3
+#define SQ_V_CUBEID_F32 0x1c4
+#define SQ_V_CUBESC_F32 0x1c5
+#define SQ_V_CUBETC_F32 0x1c6
+#define SQ_V_CUBEMA_F32 0x1c7
+#define SQ_V_BFE_U32 0x1c8
+#define SQ_V_BFE_I32 0x1c9
+#define SQ_V_BFI_B32 0x1ca
+#define SQ_V_FMA_F32 0x1cb
+#define SQ_V_FMA_F64 0x1cc
+#define SQ_V_LERP_U8 0x1cd
+#define SQ_V_ALIGNBIT_B32 0x1ce
+#define SQ_V_ALIGNBYTE_B32 0x1cf
+#define SQ_V_MIN3_F32 0x1d0
+#define SQ_V_MIN3_I32 0x1d1
+#define SQ_V_MIN3_U32 0x1d2
+#define SQ_V_MAX3_F32 0x1d3
+#define SQ_V_MAX3_I32 0x1d4
+#define SQ_V_MAX3_U32 0x1d5
+#define SQ_V_MED3_F32 0x1d6
+#define SQ_V_MED3_I32 0x1d7
+#define SQ_V_MED3_U32 0x1d8
+#define SQ_V_SAD_U8 0x1d9
+#define SQ_V_SAD_HI_U8 0x1da
+#define SQ_V_SAD_U16 0x1db
+#define SQ_V_SAD_U32 0x1dc
+#define SQ_V_CVT_PK_U8_F32 0x1dd
+#define SQ_V_DIV_FIXUP_F32 0x1de
+#define SQ_V_DIV_FIXUP_F64 0x1df
+#define SQ_V_DIV_SCALE_F32 0x1e0
+#define SQ_V_DIV_SCALE_F64 0x1e1
+#define SQ_V_DIV_FMAS_F32 0x1e2
+#define SQ_V_DIV_FMAS_F64 0x1e3
+#define SQ_V_MSAD_U8 0x1e4
+#define SQ_V_QSAD_PK_U16_U8 0x1e5
+#define SQ_V_MQSAD_PK_U16_U8 0x1e6
+#define SQ_V_MQSAD_U32_U8 0x1e7
+#define SQ_V_MAD_U64_U32 0x1e8
+#define SQ_V_MAD_I64_I32 0x1e9
+#define SQ_V_MAD_F16 0x1ea
+#define SQ_V_MAD_U16 0x1eb
+#define SQ_V_MAD_I16 0x1ec
+#define SQ_V_PERM_B32 0x1ed
+#define SQ_V_FMA_F16 0x1ee
+#define SQ_V_DIV_FIXUP_F16 0x1ef
+#define SQ_V_CVT_PKACCUM_U8_F32 0x1f0
+#define SQ_V_INTERP_P1LL_F16 0x274
+#define SQ_V_INTERP_P1LV_F16 0x275
+#define SQ_V_INTERP_P2_F16 0x276
+#define SQ_V_ADD_F64 0x280
+#define SQ_V_MUL_F64 0x281
+#define SQ_V_MIN_F64 0x282
+#define SQ_V_MAX_F64 0x283
+#define SQ_V_LDEXP_F64 0x284
+#define SQ_V_MUL_LO_U32 0x285
+#define SQ_V_MUL_HI_U32 0x286
+#define SQ_V_MUL_HI_I32 0x287
+#define SQ_V_LDEXP_F32 0x288
+#define SQ_V_READLANE_B32 0x289
+#define SQ_V_WRITELANE_B32 0x28a
+#define SQ_V_BCNT_U32_B32 0x28b
+#define SQ_V_MBCNT_LO_U32_B32 0x28c
+#define SQ_V_MBCNT_HI_U32_B32 0x28d
+#define SQ_V_MAC_LEGACY_F32 0x28e
+#define SQ_V_LSHLREV_B64 0x28f
+#define SQ_V_LSHRREV_B64 0x290
+#define SQ_V_ASHRREV_I64 0x291
+#define SQ_V_TRIG_PREOP_F64 0x292
+#define SQ_V_BFM_B32 0x293
+#define SQ_V_CVT_PKNORM_I16_F32 0x294
+#define SQ_V_CVT_PKNORM_U16_F32 0x295
+#define SQ_V_CVT_PKRTZ_F16_F32 0x296
+#define SQ_V_CVT_PK_U16_U32 0x297
+#define SQ_V_CVT_PK_I16_I32 0x298
+#define SQ_V_CVT_PKNORM_I16_F16 0x299
+#define SQ_V_CVT_PKNORM_U16_F16 0x29a
+#define SQ_VCC_ALL 0x0
+#define SQ_SRC_EXECZ 0xfc
+#define SQ_FLAT_SCRATCH_LO 0x66
+#define SQ_FLAT_SCRATCH_HI 0x67
+#define SQ_SYSMSG_OP_ECC_ERR_INTERRUPT 0x1
+#define SQ_SYSMSG_OP_REG_RD 0x2
+#define SQ_SYSMSG_OP_HOST_TRAP_ACK 0x3
+#define SQ_SYSMSG_OP_TTRACE_PC 0x4
+#define SQ_HW_REG_MODE 0x1
+#define SQ_HW_REG_STATUS 0x2
+#define SQ_HW_REG_TRAPSTS 0x3
+#define SQ_HW_REG_HW_ID 0x4
+#define SQ_HW_REG_GPR_ALLOC 0x5
+#define SQ_HW_REG_LDS_ALLOC 0x6
+#define SQ_HW_REG_IB_STS 0x7
+#define SQ_HW_REG_PC_LO 0x8
+#define SQ_HW_REG_PC_HI 0x9
+#define SQ_HW_REG_INST_DW0 0xa
+#define SQ_HW_REG_INST_DW1 0xb
+#define SQ_HW_REG_IB_DBG0 0xc
+#define SQ_HW_REG_IB_DBG1 0xd
+#define SQ_DPP_BOUND_OFF 0x0
+#define SQ_DPP_BOUND_ZERO 0x1
+#define SQ_R1 0x1
+#define SQ_R2 0x2
+#define SQ_R3 0x3
+#define SQ_R4 0x4
+#define SQ_R5 0x5
+#define SQ_R6 0x6
+#define SQ_R7 0x7
+#define SQ_R8 0x8
+#define SQ_R9 0x9
+#define SQ_R10 0xa
+#define SQ_R11 0xb
+#define SQ_R12 0xc
+#define SQ_R13 0xd
+#define SQ_R14 0xe
+#define SQ_R15 0xf
+#define SQ_S_ADD_U32 0x0
+#define SQ_S_SUB_U32 0x1
+#define SQ_S_ADD_I32 0x2
+#define SQ_S_SUB_I32 0x3
+#define SQ_S_ADDC_U32 0x4
+#define SQ_S_SUBB_U32 0x5
+#define SQ_S_MIN_I32 0x6
+#define SQ_S_MIN_U32 0x7
+#define SQ_S_MAX_I32 0x8
+#define SQ_S_MAX_U32 0x9
+#define SQ_S_CSELECT_B32 0xa
+#define SQ_S_CSELECT_B64 0xb
+#define SQ_S_AND_B32 0xc
+#define SQ_S_AND_B64 0xd
+#define SQ_S_OR_B32 0xe
+#define SQ_S_OR_B64 0xf
+#define SQ_S_XOR_B32 0x10
+#define SQ_S_XOR_B64 0x11
+#define SQ_S_ANDN2_B32 0x12
+#define SQ_S_ANDN2_B64 0x13
+#define SQ_S_ORN2_B32 0x14
+#define SQ_S_ORN2_B64 0x15
+#define SQ_S_NAND_B32 0x16
+#define SQ_S_NAND_B64 0x17
+#define SQ_S_NOR_B32 0x18
+#define SQ_S_NOR_B64 0x19
+#define SQ_S_XNOR_B32 0x1a
+#define SQ_S_XNOR_B64 0x1b
+#define SQ_S_LSHL_B32 0x1c
+#define SQ_S_LSHL_B64 0x1d
+#define SQ_S_LSHR_B32 0x1e
+#define SQ_S_LSHR_B64 0x1f
+#define SQ_S_ASHR_I32 0x20
+#define SQ_S_ASHR_I64 0x21
+#define SQ_S_BFM_B32 0x22
+#define SQ_S_BFM_B64 0x23
+#define SQ_S_MUL_I32 0x24
+#define SQ_S_BFE_U32 0x25
+#define SQ_S_BFE_I32 0x26
+#define SQ_S_BFE_U64 0x27
+#define SQ_S_BFE_I64 0x28
+#define SQ_S_CBRANCH_G_FORK 0x29
+#define SQ_S_ABSDIFF_I32 0x2a
+#define SQ_S_RFE_RESTORE_B64 0x2b
+#define SQ_MSG_INTERRUPT 0x1
+#define SQ_MSG_GS 0x2
+#define SQ_MSG_GS_DONE 0x3
+#define SQ_MSG_SAVEWAVE 0x4
+#define SQ_MSG_SYSMSG 0xf
+typedef enum SX_BLEND_OPT {
+ BLEND_OPT_PRESERVE_NONE_IGNORE_ALL = 0x0,
+ BLEND_OPT_PRESERVE_ALL_IGNORE_NONE = 0x1,
+ BLEND_OPT_PRESERVE_C1_IGNORE_C0 = 0x2,
+ BLEND_OPT_PRESERVE_C0_IGNORE_C1 = 0x3,
+ BLEND_OPT_PRESERVE_A1_IGNORE_A0 = 0x4,
+ BLEND_OPT_PRESERVE_A0_IGNORE_A1 = 0x5,
+ BLEND_OPT_PRESERVE_NONE_IGNORE_A0 = 0x6,
+ BLEND_OPT_PRESERVE_NONE_IGNORE_NONE = 0x7,
+} SX_BLEND_OPT;
+typedef enum SX_OPT_COMB_FCN {
+ OPT_COMB_NONE = 0x0,
+ OPT_COMB_ADD = 0x1,
+ OPT_COMB_SUBTRACT = 0x2,
+ OPT_COMB_MIN = 0x3,
+ OPT_COMB_MAX = 0x4,
+ OPT_COMB_REVSUBTRACT = 0x5,
+ OPT_COMB_BLEND_DISABLED = 0x6,
+ OPT_COMB_SAFE_ADD = 0x7,
+} SX_OPT_COMB_FCN;
+typedef enum SX_DOWNCONVERT_FORMAT {
+ SX_RT_EXPORT_NO_CONVERSION = 0x0,
+ SX_RT_EXPORT_32_R = 0x1,
+ SX_RT_EXPORT_32_A = 0x2,
+ SX_RT_EXPORT_10_11_11 = 0x3,
+ SX_RT_EXPORT_2_10_10_10 = 0x4,
+ SX_RT_EXPORT_8_8_8_8 = 0x5,
+ SX_RT_EXPORT_5_6_5 = 0x6,
+ SX_RT_EXPORT_1_5_5_5 = 0x7,
+ SX_RT_EXPORT_4_4_4_4 = 0x8,
+ SX_RT_EXPORT_16_16_GR = 0x9,
+ SX_RT_EXPORT_16_16_AR = 0xa,
+} SX_DOWNCONVERT_FORMAT;
+typedef enum TEX_BORDER_COLOR_TYPE {
+ TEX_BorderColor_TransparentBlack = 0x0,
+ TEX_BorderColor_OpaqueBlack = 0x1,
+ TEX_BorderColor_OpaqueWhite = 0x2,
+ TEX_BorderColor_Register = 0x3,
+} TEX_BORDER_COLOR_TYPE;
+typedef enum TEX_CHROMA_KEY {
+ TEX_ChromaKey_Disabled = 0x0,
+ TEX_ChromaKey_Kill = 0x1,
+ TEX_ChromaKey_Blend = 0x2,
+ TEX_ChromaKey_RESERVED_3 = 0x3,
+} TEX_CHROMA_KEY;
+typedef enum TEX_CLAMP {
+ TEX_Clamp_Repeat = 0x0,
+ TEX_Clamp_Mirror = 0x1,
+ TEX_Clamp_ClampToLast = 0x2,
+ TEX_Clamp_MirrorOnceToLast = 0x3,
+ TEX_Clamp_ClampHalfToBorder = 0x4,
+ TEX_Clamp_MirrorOnceHalfToBorder = 0x5,
+ TEX_Clamp_ClampToBorder = 0x6,
+ TEX_Clamp_MirrorOnceToBorder = 0x7,
+} TEX_CLAMP;
+typedef enum TEX_COORD_TYPE {
+ TEX_CoordType_Unnormalized = 0x0,
+ TEX_CoordType_Normalized = 0x1,
+} TEX_COORD_TYPE;
+typedef enum TEX_DEPTH_COMPARE_FUNCTION {
+ TEX_DepthCompareFunction_Never = 0x0,
+ TEX_DepthCompareFunction_Less = 0x1,
+ TEX_DepthCompareFunction_Equal = 0x2,
+ TEX_DepthCompareFunction_LessEqual = 0x3,
+ TEX_DepthCompareFunction_Greater = 0x4,
+ TEX_DepthCompareFunction_NotEqual = 0x5,
+ TEX_DepthCompareFunction_GreaterEqual = 0x6,
+ TEX_DepthCompareFunction_Always = 0x7,
+} TEX_DEPTH_COMPARE_FUNCTION;
+typedef enum TEX_DIM {
+ TEX_Dim_1D = 0x0,
+ TEX_Dim_2D = 0x1,
+ TEX_Dim_3D = 0x2,
+ TEX_Dim_CubeMap = 0x3,
+ TEX_Dim_1DArray = 0x4,
+ TEX_Dim_2DArray = 0x5,
+ TEX_Dim_2D_MSAA = 0x6,
+ TEX_Dim_2DArray_MSAA = 0x7,
+} TEX_DIM;
+typedef enum TEX_FORMAT_COMP {
+ TEX_FormatComp_Unsigned = 0x0,
+ TEX_FormatComp_Signed = 0x1,
+ TEX_FormatComp_UnsignedBiased = 0x2,
+ TEX_FormatComp_RESERVED_3 = 0x3,
+} TEX_FORMAT_COMP;
+typedef enum TEX_MAX_ANISO_RATIO {
+ TEX_MaxAnisoRatio_1to1 = 0x0,
+ TEX_MaxAnisoRatio_2to1 = 0x1,
+ TEX_MaxAnisoRatio_4to1 = 0x2,
+ TEX_MaxAnisoRatio_8to1 = 0x3,
+ TEX_MaxAnisoRatio_16to1 = 0x4,
+ TEX_MaxAnisoRatio_RESERVED_5 = 0x5,
+ TEX_MaxAnisoRatio_RESERVED_6 = 0x6,
+ TEX_MaxAnisoRatio_RESERVED_7 = 0x7,
+} TEX_MAX_ANISO_RATIO;
+typedef enum TEX_MIP_FILTER {
+ TEX_MipFilter_None = 0x0,
+ TEX_MipFilter_Point = 0x1,
+ TEX_MipFilter_Linear = 0x2,
+ TEX_MipFilter_Point_Aniso_Adj = 0x3,
+} TEX_MIP_FILTER;
+typedef enum TEX_REQUEST_SIZE {
+ TEX_RequestSize_32B = 0x0,
+ TEX_RequestSize_64B = 0x1,
+ TEX_RequestSize_128B = 0x2,
+ TEX_RequestSize_2X64B = 0x3,
+} TEX_REQUEST_SIZE;
+typedef enum TEX_SAMPLER_TYPE {
+ TEX_SamplerType_Invalid = 0x0,
+ TEX_SamplerType_Valid = 0x1,
+} TEX_SAMPLER_TYPE;
+typedef enum TEX_XY_FILTER {
+ TEX_XYFilter_Point = 0x0,
+ TEX_XYFilter_Linear = 0x1,
+ TEX_XYFilter_AnisoPoint = 0x2,
+ TEX_XYFilter_AnisoLinear = 0x3,
+} TEX_XY_FILTER;
+typedef enum TEX_Z_FILTER {
+ TEX_ZFilter_None = 0x0,
+ TEX_ZFilter_Point = 0x1,
+ TEX_ZFilter_Linear = 0x2,
+ TEX_ZFilter_RESERVED_3 = 0x3,
+} TEX_Z_FILTER;
+typedef enum VTX_CLAMP {
+ VTX_Clamp_ClampToZero = 0x0,
+ VTX_Clamp_ClampToNAN = 0x1,
+} VTX_CLAMP;
+typedef enum VTX_FETCH_TYPE {
+ VTX_FetchType_VertexData = 0x0,
+ VTX_FetchType_InstanceData = 0x1,
+ VTX_FetchType_NoIndexOffset = 0x2,
+ VTX_FetchType_RESERVED_3 = 0x3,
+} VTX_FETCH_TYPE;
+typedef enum VTX_FORMAT_COMP_ALL {
+ VTX_FormatCompAll_Unsigned = 0x0,
+ VTX_FormatCompAll_Signed = 0x1,
+} VTX_FORMAT_COMP_ALL;
+typedef enum VTX_MEM_REQUEST_SIZE {
+ VTX_MemRequestSize_32B = 0x0,
+ VTX_MemRequestSize_64B = 0x1,
+} VTX_MEM_REQUEST_SIZE;
+typedef enum TVX_DATA_FORMAT {
+ TVX_FMT_INVALID = 0x0,
+ TVX_FMT_8 = 0x1,
+ TVX_FMT_4_4 = 0x2,
+ TVX_FMT_3_3_2 = 0x3,
+ TVX_FMT_RESERVED_4 = 0x4,
+ TVX_FMT_16 = 0x5,
+ TVX_FMT_16_FLOAT = 0x6,
+ TVX_FMT_8_8 = 0x7,
+ TVX_FMT_5_6_5 = 0x8,
+ TVX_FMT_6_5_5 = 0x9,
+ TVX_FMT_1_5_5_5 = 0xa,
+ TVX_FMT_4_4_4_4 = 0xb,
+ TVX_FMT_5_5_5_1 = 0xc,
+ TVX_FMT_32 = 0xd,
+ TVX_FMT_32_FLOAT = 0xe,
+ TVX_FMT_16_16 = 0xf,
+ TVX_FMT_16_16_FLOAT = 0x10,
+ TVX_FMT_8_24 = 0x11,
+ TVX_FMT_8_24_FLOAT = 0x12,
+ TVX_FMT_24_8 = 0x13,
+ TVX_FMT_24_8_FLOAT = 0x14,
+ TVX_FMT_10_11_11 = 0x15,
+ TVX_FMT_10_11_11_FLOAT = 0x16,
+ TVX_FMT_11_11_10 = 0x17,
+ TVX_FMT_11_11_10_FLOAT = 0x18,
+ TVX_FMT_2_10_10_10 = 0x19,
+ TVX_FMT_8_8_8_8 = 0x1a,
+ TVX_FMT_10_10_10_2 = 0x1b,
+ TVX_FMT_X24_8_32_FLOAT = 0x1c,
+ TVX_FMT_32_32 = 0x1d,
+ TVX_FMT_32_32_FLOAT = 0x1e,
+ TVX_FMT_16_16_16_16 = 0x1f,
+ TVX_FMT_16_16_16_16_FLOAT = 0x20,
+ TVX_FMT_RESERVED_33 = 0x21,
+ TVX_FMT_32_32_32_32 = 0x22,
+ TVX_FMT_32_32_32_32_FLOAT = 0x23,
+ TVX_FMT_RESERVED_36 = 0x24,
+ TVX_FMT_1 = 0x25,
+ TVX_FMT_1_REVERSED = 0x26,
+ TVX_FMT_GB_GR = 0x27,
+ TVX_FMT_BG_RG = 0x28,
+ TVX_FMT_32_AS_8 = 0x29,
+ TVX_FMT_32_AS_8_8 = 0x2a,
+ TVX_FMT_5_9_9_9_SHAREDEXP = 0x2b,
+ TVX_FMT_8_8_8 = 0x2c,
+ TVX_FMT_16_16_16 = 0x2d,
+ TVX_FMT_16_16_16_FLOAT = 0x2e,
+ TVX_FMT_32_32_32 = 0x2f,
+ TVX_FMT_32_32_32_FLOAT = 0x30,
+ TVX_FMT_BC1 = 0x31,
+ TVX_FMT_BC2 = 0x32,
+ TVX_FMT_BC3 = 0x33,
+ TVX_FMT_BC4 = 0x34,
+ TVX_FMT_BC5 = 0x35,
+ TVX_FMT_APC0 = 0x36,
+ TVX_FMT_APC1 = 0x37,
+ TVX_FMT_APC2 = 0x38,
+ TVX_FMT_APC3 = 0x39,
+ TVX_FMT_APC4 = 0x3a,
+ TVX_FMT_APC5 = 0x3b,
+ TVX_FMT_APC6 = 0x3c,
+ TVX_FMT_APC7 = 0x3d,
+ TVX_FMT_CTX1 = 0x3e,
+ TVX_FMT_RESERVED_63 = 0x3f,
+} TVX_DATA_FORMAT;
+typedef enum TVX_DST_SEL {
+ TVX_DstSel_X = 0x0,
+ TVX_DstSel_Y = 0x1,
+ TVX_DstSel_Z = 0x2,
+ TVX_DstSel_W = 0x3,
+ TVX_DstSel_0f = 0x4,
+ TVX_DstSel_1f = 0x5,
+ TVX_DstSel_RESERVED_6 = 0x6,
+ TVX_DstSel_Mask = 0x7,
+} TVX_DST_SEL;
+typedef enum TVX_ENDIAN_SWAP {
+ TVX_EndianSwap_None = 0x0,
+ TVX_EndianSwap_8in16 = 0x1,
+ TVX_EndianSwap_8in32 = 0x2,
+ TVX_EndianSwap_8in64 = 0x3,
+} TVX_ENDIAN_SWAP;
+typedef enum TVX_INST {
+ TVX_Inst_NormalVertexFetch = 0x0,
+ TVX_Inst_SemanticVertexFetch = 0x1,
+ TVX_Inst_RESERVED_2 = 0x2,
+ TVX_Inst_LD = 0x3,
+ TVX_Inst_GetTextureResInfo = 0x4,
+ TVX_Inst_GetNumberOfSamples = 0x5,
+ TVX_Inst_GetLOD = 0x6,
+ TVX_Inst_GetGradientsH = 0x7,
+ TVX_Inst_GetGradientsV = 0x8,
+ TVX_Inst_SetTextureOffsets = 0x9,
+ TVX_Inst_KeepGradients = 0xa,
+ TVX_Inst_SetGradientsH = 0xb,
+ TVX_Inst_SetGradientsV = 0xc,
+ TVX_Inst_Pass = 0xd,
+ TVX_Inst_GetBufferResInfo = 0xe,
+ TVX_Inst_RESERVED_15 = 0xf,
+ TVX_Inst_Sample = 0x10,
+ TVX_Inst_Sample_L = 0x11,
+ TVX_Inst_Sample_LB = 0x12,
+ TVX_Inst_Sample_LZ = 0x13,
+ TVX_Inst_Sample_G = 0x14,
+ TVX_Inst_Gather4 = 0x15,
+ TVX_Inst_Sample_G_LB = 0x16,
+ TVX_Inst_Gather4_O = 0x17,
+ TVX_Inst_Sample_C = 0x18,
+ TVX_Inst_Sample_C_L = 0x19,
+ TVX_Inst_Sample_C_LB = 0x1a,
+ TVX_Inst_Sample_C_LZ = 0x1b,
+ TVX_Inst_Sample_C_G = 0x1c,
+ TVX_Inst_Gather4_C = 0x1d,
+ TVX_Inst_Sample_C_G_LB = 0x1e,
+ TVX_Inst_Gather4_C_O = 0x1f,
+} TVX_INST;
+typedef enum TVX_NUM_FORMAT_ALL {
+ TVX_NumFormatAll_Norm = 0x0,
+ TVX_NumFormatAll_Int = 0x1,
+ TVX_NumFormatAll_Scaled = 0x2,
+ TVX_NumFormatAll_RESERVED_3 = 0x3,
+} TVX_NUM_FORMAT_ALL;
+typedef enum TVX_SRC_SEL {
+ TVX_SrcSel_X = 0x0,
+ TVX_SrcSel_Y = 0x1,
+ TVX_SrcSel_Z = 0x2,
+ TVX_SrcSel_W = 0x3,
+ TVX_SrcSel_0f = 0x4,
+ TVX_SrcSel_1f = 0x5,
+} TVX_SRC_SEL;
+typedef enum TVX_SRF_MODE_ALL {
+ TVX_SRFModeAll_ZCMO = 0x0,
+ TVX_SRFModeAll_NZ = 0x1,
+} TVX_SRF_MODE_ALL;
+typedef enum TVX_TYPE {
+ TVX_Type_InvalidTextureResource = 0x0,
+ TVX_Type_InvalidVertexBuffer = 0x1,
+ TVX_Type_ValidTextureResource = 0x2,
+ TVX_Type_ValidVertexBuffer = 0x3,
+} TVX_TYPE;
+typedef enum TC_OP_MASKS {
+ TC_OP_MASK_FLUSH_DENROM = 0x8,
+ TC_OP_MASK_64 = 0x20,
+ TC_OP_MASK_NO_RTN = 0x40,
+} TC_OP_MASKS;
+typedef enum TC_OP {
+ TC_OP_READ = 0x0,
+ TC_OP_ATOMIC_FCMPSWAP_RTN_32 = 0x1,
+ TC_OP_ATOMIC_FMIN_RTN_32 = 0x2,
+ TC_OP_ATOMIC_FMAX_RTN_32 = 0x3,
+ TC_OP_RESERVED_FOP_RTN_32_0 = 0x4,
+ TC_OP_RESERVED_FOP_RTN_32_1 = 0x5,
+ TC_OP_RESERVED_FOP_RTN_32_2 = 0x6,
+ TC_OP_ATOMIC_SWAP_RTN_32 = 0x7,
+ TC_OP_ATOMIC_CMPSWAP_RTN_32 = 0x8,
+ TC_OP_ATOMIC_FCMPSWAP_FLUSH_DENORM_RTN_32 = 0x9,
+ TC_OP_ATOMIC_FMIN_FLUSH_DENORM_RTN_32 = 0xa,
+ TC_OP_ATOMIC_FMAX_FLUSH_DENORM_RTN_32 = 0xb,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_RTN_32_0 = 0xc,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_RTN_32_1 = 0xd,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_RTN_32_2 = 0xe,
+ TC_OP_ATOMIC_ADD_RTN_32 = 0xf,
+ TC_OP_ATOMIC_SUB_RTN_32 = 0x10,
+ TC_OP_ATOMIC_SMIN_RTN_32 = 0x11,
+ TC_OP_ATOMIC_UMIN_RTN_32 = 0x12,
+ TC_OP_ATOMIC_SMAX_RTN_32 = 0x13,
+ TC_OP_ATOMIC_UMAX_RTN_32 = 0x14,
+ TC_OP_ATOMIC_AND_RTN_32 = 0x15,
+ TC_OP_ATOMIC_OR_RTN_32 = 0x16,
+ TC_OP_ATOMIC_XOR_RTN_32 = 0x17,
+ TC_OP_ATOMIC_INC_RTN_32 = 0x18,
+ TC_OP_ATOMIC_DEC_RTN_32 = 0x19,
+ TC_OP_WBINVL1_VOL = 0x1a,
+ TC_OP_WBINVL1_SD = 0x1b,
+ TC_OP_RESERVED_NON_FLOAT_RTN_32_0 = 0x1c,
+ TC_OP_RESERVED_NON_FLOAT_RTN_32_1 = 0x1d,
+ TC_OP_RESERVED_NON_FLOAT_RTN_32_2 = 0x1e,
+ TC_OP_RESERVED_NON_FLOAT_RTN_32_3 = 0x1f,
+ TC_OP_WRITE = 0x20,
+ TC_OP_ATOMIC_FCMPSWAP_RTN_64 = 0x21,
+ TC_OP_ATOMIC_FMIN_RTN_64 = 0x22,
+ TC_OP_ATOMIC_FMAX_RTN_64 = 0x23,
+ TC_OP_RESERVED_FOP_RTN_64_0 = 0x24,
+ TC_OP_RESERVED_FOP_RTN_64_1 = 0x25,
+ TC_OP_RESERVED_FOP_RTN_64_2 = 0x26,
+ TC_OP_ATOMIC_SWAP_RTN_64 = 0x27,
+ TC_OP_ATOMIC_CMPSWAP_RTN_64 = 0x28,
+ TC_OP_ATOMIC_FCMPSWAP_FLUSH_DENORM_RTN_64 = 0x29,
+ TC_OP_ATOMIC_FMIN_FLUSH_DENORM_RTN_64 = 0x2a,
+ TC_OP_ATOMIC_FMAX_FLUSH_DENORM_RTN_64 = 0x2b,
+ TC_OP_WBINVL2_SD = 0x2c,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_RTN_64_0 = 0x2d,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_RTN_64_1 = 0x2e,
+ TC_OP_ATOMIC_ADD_RTN_64 = 0x2f,
+ TC_OP_ATOMIC_SUB_RTN_64 = 0x30,
+ TC_OP_ATOMIC_SMIN_RTN_64 = 0x31,
+ TC_OP_ATOMIC_UMIN_RTN_64 = 0x32,
+ TC_OP_ATOMIC_SMAX_RTN_64 = 0x33,
+ TC_OP_ATOMIC_UMAX_RTN_64 = 0x34,
+ TC_OP_ATOMIC_AND_RTN_64 = 0x35,
+ TC_OP_ATOMIC_OR_RTN_64 = 0x36,
+ TC_OP_ATOMIC_XOR_RTN_64 = 0x37,
+ TC_OP_ATOMIC_INC_RTN_64 = 0x38,
+ TC_OP_ATOMIC_DEC_RTN_64 = 0x39,
+ TC_OP_WBL2_NC = 0x3a,
+ TC_OP_RESERVED_NON_FLOAT_RTN_64_0 = 0x3b,
+ TC_OP_RESERVED_NON_FLOAT_RTN_64_1 = 0x3c,
+ TC_OP_RESERVED_NON_FLOAT_RTN_64_2 = 0x3d,
+ TC_OP_RESERVED_NON_FLOAT_RTN_64_3 = 0x3e,
+ TC_OP_RESERVED_NON_FLOAT_RTN_64_4 = 0x3f,
+ TC_OP_WBINVL1 = 0x40,
+ TC_OP_ATOMIC_FCMPSWAP_32 = 0x41,
+ TC_OP_ATOMIC_FMIN_32 = 0x42,
+ TC_OP_ATOMIC_FMAX_32 = 0x43,
+ TC_OP_RESERVED_FOP_32_0 = 0x44,
+ TC_OP_RESERVED_FOP_32_1 = 0x45,
+ TC_OP_RESERVED_FOP_32_2 = 0x46,
+ TC_OP_ATOMIC_SWAP_32 = 0x47,
+ TC_OP_ATOMIC_CMPSWAP_32 = 0x48,
+ TC_OP_ATOMIC_FCMPSWAP_FLUSH_DENORM_32 = 0x49,
+ TC_OP_ATOMIC_FMIN_FLUSH_DENORM_32 = 0x4a,
+ TC_OP_ATOMIC_FMAX_FLUSH_DENORM_32 = 0x4b,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_32_0 = 0x4c,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_32_1 = 0x4d,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_32_2 = 0x4e,
+ TC_OP_ATOMIC_ADD_32 = 0x4f,
+ TC_OP_ATOMIC_SUB_32 = 0x50,
+ TC_OP_ATOMIC_SMIN_32 = 0x51,
+ TC_OP_ATOMIC_UMIN_32 = 0x52,
+ TC_OP_ATOMIC_SMAX_32 = 0x53,
+ TC_OP_ATOMIC_UMAX_32 = 0x54,
+ TC_OP_ATOMIC_AND_32 = 0x55,
+ TC_OP_ATOMIC_OR_32 = 0x56,
+ TC_OP_ATOMIC_XOR_32 = 0x57,
+ TC_OP_ATOMIC_INC_32 = 0x58,
+ TC_OP_ATOMIC_DEC_32 = 0x59,
+ TC_OP_INVL2_NC = 0x5a,
+ TC_OP_RESERVED_NON_FLOAT_32_0 = 0x5b,
+ TC_OP_RESERVED_NON_FLOAT_32_1 = 0x5c,
+ TC_OP_RESERVED_NON_FLOAT_32_2 = 0x5d,
+ TC_OP_RESERVED_NON_FLOAT_32_3 = 0x5e,
+ TC_OP_RESERVED_NON_FLOAT_32_4 = 0x5f,
+ TC_OP_WBINVL2 = 0x60,
+ TC_OP_ATOMIC_FCMPSWAP_64 = 0x61,
+ TC_OP_ATOMIC_FMIN_64 = 0x62,
+ TC_OP_ATOMIC_FMAX_64 = 0x63,
+ TC_OP_RESERVED_FOP_64_0 = 0x64,
+ TC_OP_RESERVED_FOP_64_1 = 0x65,
+ TC_OP_RESERVED_FOP_64_2 = 0x66,
+ TC_OP_ATOMIC_SWAP_64 = 0x67,
+ TC_OP_ATOMIC_CMPSWAP_64 = 0x68,
+ TC_OP_ATOMIC_FCMPSWAP_FLUSH_DENORM_64 = 0x69,
+ TC_OP_ATOMIC_FMIN_FLUSH_DENORM_64 = 0x6a,
+ TC_OP_ATOMIC_FMAX_FLUSH_DENORM_64 = 0x6b,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_64_0 = 0x6c,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_64_1 = 0x6d,
+ TC_OP_RESERVED_FOP_FLUSH_DENORM_64_2 = 0x6e,
+ TC_OP_ATOMIC_ADD_64 = 0x6f,
+ TC_OP_ATOMIC_SUB_64 = 0x70,
+ TC_OP_ATOMIC_SMIN_64 = 0x71,
+ TC_OP_ATOMIC_UMIN_64 = 0x72,
+ TC_OP_ATOMIC_SMAX_64 = 0x73,
+ TC_OP_ATOMIC_UMAX_64 = 0x74,
+ TC_OP_ATOMIC_AND_64 = 0x75,
+ TC_OP_ATOMIC_OR_64 = 0x76,
+ TC_OP_ATOMIC_XOR_64 = 0x77,
+ TC_OP_ATOMIC_INC_64 = 0x78,
+ TC_OP_ATOMIC_DEC_64 = 0x79,
+ TC_OP_WBINVL2_NC = 0x7a,
+ TC_OP_RESERVED_NON_FLOAT_64_0 = 0x7b,
+ TC_OP_RESERVED_NON_FLOAT_64_1 = 0x7c,
+ TC_OP_RESERVED_NON_FLOAT_64_2 = 0x7d,
+ TC_OP_RESERVED_NON_FLOAT_64_3 = 0x7e,
+ TC_OP_RESERVED_NON_FLOAT_64_4 = 0x7f,
+} TC_OP;
+typedef enum TC_CHUB_REQ_CREDITS_ENUM {
+ TC_CHUB_REQ_CREDITS = 0x10,
+} TC_CHUB_REQ_CREDITS_ENUM;
+typedef enum CHUB_TC_RET_CREDITS_ENUM {
+ CHUB_TC_RET_CREDITS = 0x20,
+} CHUB_TC_RET_CREDITS_ENUM;
+typedef enum TC_NACKS {
+ TC_NACK_NO_FAULT = 0x0,
+ TC_NACK_PAGE_FAULT = 0x1,
+ TC_NACK_PROTECTION_FAULT = 0x2,
+ TC_NACK_DATA_ERROR = 0x3,
+} TC_NACKS;
+typedef enum TCC_PERF_SEL {
+ TCC_PERF_SEL_NONE = 0x0,
+ TCC_PERF_SEL_CYCLE = 0x1,
+ TCC_PERF_SEL_BUSY = 0x2,
+ TCC_PERF_SEL_REQ = 0x3,
+ TCC_PERF_SEL_STREAMING_REQ = 0x4,
+ TCC_PERF_SEL_EXE_REQ = 0x5,
+ TCC_PERF_SEL_COMPRESSED_REQ = 0x6,
+ TCC_PERF_SEL_COMPRESSED_0_REQ = 0x7,
+ TCC_PERF_SEL_METADATA_REQ = 0x8,
+ TCC_PERF_SEL_NC_VIRTUAL_REQ = 0x9,
+ TCC_PERF_SEL_NC_PHYSICAL_REQ = 0xa,
+ TCC_PERF_SEL_UC_VIRTUAL_REQ = 0xb,
+ TCC_PERF_SEL_UC_PHYSICAL_REQ = 0xc,
+ TCC_PERF_SEL_CC_PHYSICAL_REQ = 0xd,
+ TCC_PERF_SEL_PROBE = 0xe,
+ TCC_PERF_SEL_READ = 0xf,
+ TCC_PERF_SEL_WRITE = 0x10,
+ TCC_PERF_SEL_ATOMIC = 0x11,
+ TCC_PERF_SEL_HIT = 0x12,
+ TCC_PERF_SEL_MISS = 0x13,
+ TCC_PERF_SEL_DEWRITE_ALLOCATE_HIT = 0x14,
+ TCC_PERF_SEL_FULLY_WRITTEN_HIT = 0x15,
+ TCC_PERF_SEL_WRITEBACK = 0x16,
+ TCC_PERF_SEL_LATENCY_FIFO_FULL = 0x17,
+ TCC_PERF_SEL_SRC_FIFO_FULL = 0x18,
+ TCC_PERF_SEL_HOLE_FIFO_FULL = 0x19,
+ TCC_PERF_SEL_MC_WRREQ = 0x1a,
+ TCC_PERF_SEL_MC_WRREQ_UNCACHED = 0x1b,
+ TCC_PERF_SEL_MC_WRREQ_STALL = 0x1c,
+ TCC_PERF_SEL_MC_WRREQ_CREDIT_STALL = 0x1d,
+ TCC_PERF_SEL_MC_WRREQ_MC_HALT_STALL = 0x1e,
+ TCC_PERF_SEL_TOO_MANY_MC_WRREQS_STALL = 0x1f,
+ TCC_PERF_SEL_MC_WRREQ_LEVEL = 0x20,
+ TCC_PERF_SEL_MC_ATOMIC = 0x21,
+ TCC_PERF_SEL_MC_ATOMIC_LEVEL = 0x22,
+ TCC_PERF_SEL_MC_RDREQ = 0x23,
+ TCC_PERF_SEL_MC_RDREQ_UNCACHED = 0x24,
+ TCC_PERF_SEL_MC_RDREQ_MDC = 0x25,
+ TCC_PERF_SEL_MC_RDREQ_COMPRESSED = 0x26,
+ TCC_PERF_SEL_MC_RDREQ_CREDIT_STALL = 0x27,
+ TCC_PERF_SEL_MC_RDREQ_MC_HALT_STALL = 0x28,
+ TCC_PERF_SEL_MC_RDREQ_LEVEL = 0x29,
+ TCC_PERF_SEL_TAG_STALL = 0x2a,
+ TCC_PERF_SEL_TAG_WRITEBACK_FIFO_FULL_STALL = 0x2b,
+ TCC_PERF_SEL_TAG_MISS_NOTHING_REPLACEABLE_STALL = 0x2c,
+ TCC_PERF_SEL_TAG_UNCACHED_WRITE_ATOMIC_FIFO_FULL_STALL= 0x2d,
+ TCC_PERF_SEL_TAG_NO_UNCACHED_WRITE_ATOMIC_ENTRIES_STALL= 0x2e,
+ TCC_PERF_SEL_TAG_PROBE_STALL = 0x2f,
+ TCC_PERF_SEL_TAG_PROBE_FILTER_STALL = 0x30,
+ TCC_PERF_SEL_READ_RETURN_TIMEOUT = 0x31,
+ TCC_PERF_SEL_WRITEBACK_READ_TIMEOUT = 0x32,
+ TCC_PERF_SEL_READ_RETURN_FULL_BUBBLE = 0x33,
+ TCC_PERF_SEL_BUBBLE = 0x34,
+ TCC_PERF_SEL_RETURN_ACK = 0x35,
+ TCC_PERF_SEL_RETURN_DATA = 0x36,
+ TCC_PERF_SEL_RETURN_HOLE = 0x37,
+ TCC_PERF_SEL_RETURN_ACK_HOLE = 0x38,
+ TCC_PERF_SEL_IB_REQ = 0x39,
+ TCC_PERF_SEL_IB_STALL = 0x3a,
+ TCC_PERF_SEL_IB_TAG_STALL = 0x3b,
+ TCC_PERF_SEL_IB_MDC_STALL = 0x3c,
+ TCC_PERF_SEL_TCA_LEVEL = 0x3d,
+ TCC_PERF_SEL_HOLE_LEVEL = 0x3e,
+ TCC_PERF_SEL_MC_RDRET_NACK = 0x3f,
+ TCC_PERF_SEL_MC_WRRET_NACK = 0x40,
+ TCC_PERF_SEL_NORMAL_WRITEBACK = 0x41,
+ TCC_PERF_SEL_TC_OP_WBL2_NC_WRITEBACK = 0x42,
+ TCC_PERF_SEL_TC_OP_WBINVL2_WRITEBACK = 0x43,
+ TCC_PERF_SEL_TC_OP_WBINVL2_NC_WRITEBACK = 0x44,
+ TCC_PERF_SEL_TC_OP_WBINVL2_SD_WRITEBACK = 0x45,
+ TCC_PERF_SEL_ALL_TC_OP_WB_WRITEBACK = 0x46,
+ TCC_PERF_SEL_NORMAL_EVICT = 0x47,
+ TCC_PERF_SEL_TC_OP_WBL2_NC_EVICT = 0x48,
+ TCC_PERF_SEL_TC_OP_INVL2_NC_EVICT = 0x49,
+ TCC_PERF_SEL_TC_OP_WBINVL2_EVICT = 0x4a,
+ TCC_PERF_SEL_TC_OP_WBINVL2_NC_EVICT = 0x4b,
+ TCC_PERF_SEL_TC_OP_WBINVL2_SD_EVICT = 0x4c,
+ TCC_PERF_SEL_ALL_TC_OP_INV_EVICT = 0x4d,
+ TCC_PERF_SEL_PROBE_EVICT = 0x4e,
+ TCC_PERF_SEL_TC_OP_WBL2_NC_CYCLE = 0x4f,
+ TCC_PERF_SEL_TC_OP_INVL2_NC_CYCLE = 0x50,
+ TCC_PERF_SEL_TC_OP_WBINVL2_CYCLE = 0x51,
+ TCC_PERF_SEL_TC_OP_WBINVL2_NC_CYCLE = 0x52,
+ TCC_PERF_SEL_TC_OP_WBINVL2_SD_CYCLE = 0x53,
+ TCC_PERF_SEL_ALL_TC_OP_WB_OR_INV_CYCLE = 0x54,
+ TCC_PERF_SEL_TC_OP_WBL2_NC_START = 0x55,
+ TCC_PERF_SEL_TC_OP_INVL2_NC_START = 0x56,
+ TCC_PERF_SEL_TC_OP_WBINVL2_START = 0x57,
+ TCC_PERF_SEL_TC_OP_WBINVL2_NC_START = 0x58,
+ TCC_PERF_SEL_TC_OP_WBINVL2_SD_START = 0x59,
+ TCC_PERF_SEL_ALL_TC_OP_WB_OR_INV_START = 0x5a,
+ TCC_PERF_SEL_TC_OP_WBL2_NC_FINISH = 0x5b,
+ TCC_PERF_SEL_TC_OP_INVL2_NC_FINISH = 0x5c,
+ TCC_PERF_SEL_TC_OP_WBINVL2_FINISH = 0x5d,
+ TCC_PERF_SEL_TC_OP_WBINVL2_NC_FINISH = 0x5e,
+ TCC_PERF_SEL_TC_OP_WBINVL2_SD_FINISH = 0x5f,
+ TCC_PERF_SEL_ALL_TC_OP_WB_OR_INV_FINISH = 0x60,
+ TCC_PERF_SEL_MDC_REQ = 0x61,
+ TCC_PERF_SEL_MDC_LEVEL = 0x62,
+ TCC_PERF_SEL_MDC_TAG_HIT = 0x63,
+ TCC_PERF_SEL_MDC_SECTOR_HIT = 0x64,
+ TCC_PERF_SEL_MDC_SECTOR_MISS = 0x65,
+ TCC_PERF_SEL_MDC_TAG_STALL = 0x66,
+ TCC_PERF_SEL_MDC_TAG_REPLACEMENT_LINE_IN_USE_STALL= 0x67,
+ TCC_PERF_SEL_MDC_TAG_DESECTORIZATION_FIFO_FULL_STALL= 0x68,
+ TCC_PERF_SEL_MDC_TAG_WAITING_FOR_INVALIDATE_COMPLETION_STALL= 0x69,
+ TCC_PERF_SEL_PROBE_FILTER_DISABLE_TRANSITION = 0x6a,
+ TCC_PERF_SEL_PROBE_FILTER_DISABLED = 0x6b,
+ TCC_PERF_SEL_CLIENT0_REQ = 0x80,
+ TCC_PERF_SEL_CLIENT1_REQ = 0x81,
+ TCC_PERF_SEL_CLIENT2_REQ = 0x82,
+ TCC_PERF_SEL_CLIENT3_REQ = 0x83,
+ TCC_PERF_SEL_CLIENT4_REQ = 0x84,
+ TCC_PERF_SEL_CLIENT5_REQ = 0x85,
+ TCC_PERF_SEL_CLIENT6_REQ = 0x86,
+ TCC_PERF_SEL_CLIENT7_REQ = 0x87,
+ TCC_PERF_SEL_CLIENT8_REQ = 0x88,
+ TCC_PERF_SEL_CLIENT9_REQ = 0x89,
+ TCC_PERF_SEL_CLIENT10_REQ = 0x8a,
+ TCC_PERF_SEL_CLIENT11_REQ = 0x8b,
+ TCC_PERF_SEL_CLIENT12_REQ = 0x8c,
+ TCC_PERF_SEL_CLIENT13_REQ = 0x8d,
+ TCC_PERF_SEL_CLIENT14_REQ = 0x8e,
+ TCC_PERF_SEL_CLIENT15_REQ = 0x8f,
+ TCC_PERF_SEL_CLIENT16_REQ = 0x90,
+ TCC_PERF_SEL_CLIENT17_REQ = 0x91,
+ TCC_PERF_SEL_CLIENT18_REQ = 0x92,
+ TCC_PERF_SEL_CLIENT19_REQ = 0x93,
+ TCC_PERF_SEL_CLIENT20_REQ = 0x94,
+ TCC_PERF_SEL_CLIENT21_REQ = 0x95,
+ TCC_PERF_SEL_CLIENT22_REQ = 0x96,
+ TCC_PERF_SEL_CLIENT23_REQ = 0x97,
+ TCC_PERF_SEL_CLIENT24_REQ = 0x98,
+ TCC_PERF_SEL_CLIENT25_REQ = 0x99,
+ TCC_PERF_SEL_CLIENT26_REQ = 0x9a,
+ TCC_PERF_SEL_CLIENT27_REQ = 0x9b,
+ TCC_PERF_SEL_CLIENT28_REQ = 0x9c,
+ TCC_PERF_SEL_CLIENT29_REQ = 0x9d,
+ TCC_PERF_SEL_CLIENT30_REQ = 0x9e,
+ TCC_PERF_SEL_CLIENT31_REQ = 0x9f,
+ TCC_PERF_SEL_CLIENT32_REQ = 0xa0,
+ TCC_PERF_SEL_CLIENT33_REQ = 0xa1,
+ TCC_PERF_SEL_CLIENT34_REQ = 0xa2,
+ TCC_PERF_SEL_CLIENT35_REQ = 0xa3,
+ TCC_PERF_SEL_CLIENT36_REQ = 0xa4,
+ TCC_PERF_SEL_CLIENT37_REQ = 0xa5,
+ TCC_PERF_SEL_CLIENT38_REQ = 0xa6,
+ TCC_PERF_SEL_CLIENT39_REQ = 0xa7,
+ TCC_PERF_SEL_CLIENT40_REQ = 0xa8,
+ TCC_PERF_SEL_CLIENT41_REQ = 0xa9,
+ TCC_PERF_SEL_CLIENT42_REQ = 0xaa,
+ TCC_PERF_SEL_CLIENT43_REQ = 0xab,
+ TCC_PERF_SEL_CLIENT44_REQ = 0xac,
+ TCC_PERF_SEL_CLIENT45_REQ = 0xad,
+ TCC_PERF_SEL_CLIENT46_REQ = 0xae,
+ TCC_PERF_SEL_CLIENT47_REQ = 0xaf,
+ TCC_PERF_SEL_CLIENT48_REQ = 0xb0,
+ TCC_PERF_SEL_CLIENT49_REQ = 0xb1,
+ TCC_PERF_SEL_CLIENT50_REQ = 0xb2,
+ TCC_PERF_SEL_CLIENT51_REQ = 0xb3,
+ TCC_PERF_SEL_CLIENT52_REQ = 0xb4,
+ TCC_PERF_SEL_CLIENT53_REQ = 0xb5,
+ TCC_PERF_SEL_CLIENT54_REQ = 0xb6,
+ TCC_PERF_SEL_CLIENT55_REQ = 0xb7,
+ TCC_PERF_SEL_CLIENT56_REQ = 0xb8,
+ TCC_PERF_SEL_CLIENT57_REQ = 0xb9,
+ TCC_PERF_SEL_CLIENT58_REQ = 0xba,
+ TCC_PERF_SEL_CLIENT59_REQ = 0xbb,
+ TCC_PERF_SEL_CLIENT60_REQ = 0xbc,
+ TCC_PERF_SEL_CLIENT61_REQ = 0xbd,
+ TCC_PERF_SEL_CLIENT62_REQ = 0xbe,
+ TCC_PERF_SEL_CLIENT63_REQ = 0xbf,
+ TCC_PERF_SEL_CLIENT64_REQ = 0xc0,
+ TCC_PERF_SEL_CLIENT65_REQ = 0xc1,
+ TCC_PERF_SEL_CLIENT66_REQ = 0xc2,
+ TCC_PERF_SEL_CLIENT67_REQ = 0xc3,
+ TCC_PERF_SEL_CLIENT68_REQ = 0xc4,
+ TCC_PERF_SEL_CLIENT69_REQ = 0xc5,
+ TCC_PERF_SEL_CLIENT70_REQ = 0xc6,
+ TCC_PERF_SEL_CLIENT71_REQ = 0xc7,
+ TCC_PERF_SEL_CLIENT72_REQ = 0xc8,
+ TCC_PERF_SEL_CLIENT73_REQ = 0xc9,
+ TCC_PERF_SEL_CLIENT74_REQ = 0xca,
+ TCC_PERF_SEL_CLIENT75_REQ = 0xcb,
+ TCC_PERF_SEL_CLIENT76_REQ = 0xcc,
+ TCC_PERF_SEL_CLIENT77_REQ = 0xcd,
+ TCC_PERF_SEL_CLIENT78_REQ = 0xce,
+ TCC_PERF_SEL_CLIENT79_REQ = 0xcf,
+ TCC_PERF_SEL_CLIENT80_REQ = 0xd0,
+ TCC_PERF_SEL_CLIENT81_REQ = 0xd1,
+ TCC_PERF_SEL_CLIENT82_REQ = 0xd2,
+ TCC_PERF_SEL_CLIENT83_REQ = 0xd3,
+ TCC_PERF_SEL_CLIENT84_REQ = 0xd4,
+ TCC_PERF_SEL_CLIENT85_REQ = 0xd5,
+ TCC_PERF_SEL_CLIENT86_REQ = 0xd6,
+ TCC_PERF_SEL_CLIENT87_REQ = 0xd7,
+ TCC_PERF_SEL_CLIENT88_REQ = 0xd8,
+ TCC_PERF_SEL_CLIENT89_REQ = 0xd9,
+ TCC_PERF_SEL_CLIENT90_REQ = 0xda,
+ TCC_PERF_SEL_CLIENT91_REQ = 0xdb,
+ TCC_PERF_SEL_CLIENT92_REQ = 0xdc,
+ TCC_PERF_SEL_CLIENT93_REQ = 0xdd,
+ TCC_PERF_SEL_CLIENT94_REQ = 0xde,
+ TCC_PERF_SEL_CLIENT95_REQ = 0xdf,
+ TCC_PERF_SEL_CLIENT96_REQ = 0xe0,
+ TCC_PERF_SEL_CLIENT97_REQ = 0xe1,
+ TCC_PERF_SEL_CLIENT98_REQ = 0xe2,
+ TCC_PERF_SEL_CLIENT99_REQ = 0xe3,
+ TCC_PERF_SEL_CLIENT100_REQ = 0xe4,
+ TCC_PERF_SEL_CLIENT101_REQ = 0xe5,
+ TCC_PERF_SEL_CLIENT102_REQ = 0xe6,
+ TCC_PERF_SEL_CLIENT103_REQ = 0xe7,
+ TCC_PERF_SEL_CLIENT104_REQ = 0xe8,
+ TCC_PERF_SEL_CLIENT105_REQ = 0xe9,
+ TCC_PERF_SEL_CLIENT106_REQ = 0xea,
+ TCC_PERF_SEL_CLIENT107_REQ = 0xeb,
+ TCC_PERF_SEL_CLIENT108_REQ = 0xec,
+ TCC_PERF_SEL_CLIENT109_REQ = 0xed,
+ TCC_PERF_SEL_CLIENT110_REQ = 0xee,
+ TCC_PERF_SEL_CLIENT111_REQ = 0xef,
+ TCC_PERF_SEL_CLIENT112_REQ = 0xf0,
+ TCC_PERF_SEL_CLIENT113_REQ = 0xf1,
+ TCC_PERF_SEL_CLIENT114_REQ = 0xf2,
+ TCC_PERF_SEL_CLIENT115_REQ = 0xf3,
+ TCC_PERF_SEL_CLIENT116_REQ = 0xf4,
+ TCC_PERF_SEL_CLIENT117_REQ = 0xf5,
+ TCC_PERF_SEL_CLIENT118_REQ = 0xf6,
+ TCC_PERF_SEL_CLIENT119_REQ = 0xf7,
+ TCC_PERF_SEL_CLIENT120_REQ = 0xf8,
+ TCC_PERF_SEL_CLIENT121_REQ = 0xf9,
+ TCC_PERF_SEL_CLIENT122_REQ = 0xfa,
+ TCC_PERF_SEL_CLIENT123_REQ = 0xfb,
+ TCC_PERF_SEL_CLIENT124_REQ = 0xfc,
+ TCC_PERF_SEL_CLIENT125_REQ = 0xfd,
+ TCC_PERF_SEL_CLIENT126_REQ = 0xfe,
+ TCC_PERF_SEL_CLIENT127_REQ = 0xff,
+} TCC_PERF_SEL;
+typedef enum TCA_PERF_SEL {
+ TCA_PERF_SEL_NONE = 0x0,
+ TCA_PERF_SEL_CYCLE = 0x1,
+ TCA_PERF_SEL_BUSY = 0x2,
+ TCA_PERF_SEL_FORCED_HOLE_TCC0 = 0x3,
+ TCA_PERF_SEL_FORCED_HOLE_TCC1 = 0x4,
+ TCA_PERF_SEL_FORCED_HOLE_TCC2 = 0x5,
+ TCA_PERF_SEL_FORCED_HOLE_TCC3 = 0x6,
+ TCA_PERF_SEL_FORCED_HOLE_TCC4 = 0x7,
+ TCA_PERF_SEL_FORCED_HOLE_TCC5 = 0x8,
+ TCA_PERF_SEL_FORCED_HOLE_TCC6 = 0x9,
+ TCA_PERF_SEL_FORCED_HOLE_TCC7 = 0xa,
+ TCA_PERF_SEL_REQ_TCC0 = 0xb,
+ TCA_PERF_SEL_REQ_TCC1 = 0xc,
+ TCA_PERF_SEL_REQ_TCC2 = 0xd,
+ TCA_PERF_SEL_REQ_TCC3 = 0xe,
+ TCA_PERF_SEL_REQ_TCC4 = 0xf,
+ TCA_PERF_SEL_REQ_TCC5 = 0x10,
+ TCA_PERF_SEL_REQ_TCC6 = 0x11,
+ TCA_PERF_SEL_REQ_TCC7 = 0x12,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC0 = 0x13,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC1 = 0x14,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC2 = 0x15,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC3 = 0x16,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC4 = 0x17,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC5 = 0x18,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC6 = 0x19,
+ TCA_PERF_SEL_CROSSBAR_DOUBLE_ARB_TCC7 = 0x1a,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC0 = 0x1b,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC1 = 0x1c,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC2 = 0x1d,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC3 = 0x1e,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC4 = 0x1f,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC5 = 0x20,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC6 = 0x21,
+ TCA_PERF_SEL_CROSSBAR_STALL_TCC7 = 0x22,
+} TCA_PERF_SEL;
+typedef enum TA_TC_ADDR_MODES {
+ TA_TC_ADDR_MODE_DEFAULT = 0x0,
+ TA_TC_ADDR_MODE_COMP0 = 0x1,
+ TA_TC_ADDR_MODE_COMP1 = 0x2,
+ TA_TC_ADDR_MODE_COMP2 = 0x3,
+ TA_TC_ADDR_MODE_COMP3 = 0x4,
+ TA_TC_ADDR_MODE_UNALIGNED = 0x5,
+ TA_TC_ADDR_MODE_BORDER_COLOR = 0x6,
+} TA_TC_ADDR_MODES;
+typedef enum TA_PERFCOUNT_SEL {
+ TA_PERF_SEL_NULL = 0x0,
+ TA_PERF_SEL_sh_fifo_busy = 0x1,
+ TA_PERF_SEL_sh_fifo_cmd_busy = 0x2,
+ TA_PERF_SEL_sh_fifo_addr_busy = 0x3,
+ TA_PERF_SEL_sh_fifo_data_busy = 0x4,
+ TA_PERF_SEL_sh_fifo_data_sfifo_busy = 0x5,
+ TA_PERF_SEL_sh_fifo_data_tfifo_busy = 0x6,
+ TA_PERF_SEL_gradient_busy = 0x7,
+ TA_PERF_SEL_gradient_fifo_busy = 0x8,
+ TA_PERF_SEL_lod_busy = 0x9,
+ TA_PERF_SEL_lod_fifo_busy = 0xa,
+ TA_PERF_SEL_addresser_busy = 0xb,
+ TA_PERF_SEL_addresser_fifo_busy = 0xc,
+ TA_PERF_SEL_aligner_busy = 0xd,
+ TA_PERF_SEL_write_path_busy = 0xe,
+ TA_PERF_SEL_ta_busy = 0xf,
+ TA_PERF_SEL_sq_ta_cmd_cycles = 0x10,
+ TA_PERF_SEL_sp_ta_addr_cycles = 0x11,
+ TA_PERF_SEL_sp_ta_data_cycles = 0x12,
+ TA_PERF_SEL_ta_fa_data_state_cycles = 0x13,
+ TA_PERF_SEL_sh_fifo_addr_waiting_on_cmd_cycles = 0x14,
+ TA_PERF_SEL_sh_fifo_cmd_waiting_on_addr_cycles = 0x15,
+ TA_PERF_SEL_sh_fifo_addr_starved_while_busy_cycles= 0x16,
+ TA_PERF_SEL_sh_fifo_cmd_starved_while_busy_cycles= 0x17,
+ TA_PERF_SEL_sh_fifo_data_waiting_on_data_state_cycles= 0x18,
+ TA_PERF_SEL_sh_fifo_data_state_waiting_on_data_cycles= 0x19,
+ TA_PERF_SEL_sh_fifo_data_starved_while_busy_cycles= 0x1a,
+ TA_PERF_SEL_sh_fifo_data_state_starved_while_busy_cycles= 0x1b,
+ TA_PERF_SEL_RESERVED_28 = 0x1c,
+ TA_PERF_SEL_RESERVED_29 = 0x1d,
+ TA_PERF_SEL_sh_fifo_addr_cycles = 0x1e,
+ TA_PERF_SEL_sh_fifo_data_cycles = 0x1f,
+ TA_PERF_SEL_total_wavefronts = 0x20,
+ TA_PERF_SEL_gradient_cycles = 0x21,
+ TA_PERF_SEL_walker_cycles = 0x22,
+ TA_PERF_SEL_aligner_cycles = 0x23,
+ TA_PERF_SEL_image_wavefronts = 0x24,
+ TA_PERF_SEL_image_read_wavefronts = 0x25,
+ TA_PERF_SEL_image_write_wavefronts = 0x26,
+ TA_PERF_SEL_image_atomic_wavefronts = 0x27,
+ TA_PERF_SEL_image_total_cycles = 0x28,
+ TA_PERF_SEL_RESERVED_41 = 0x29,
+ TA_PERF_SEL_RESERVED_42 = 0x2a,
+ TA_PERF_SEL_RESERVED_43 = 0x2b,
+ TA_PERF_SEL_buffer_wavefronts = 0x2c,
+ TA_PERF_SEL_buffer_read_wavefronts = 0x2d,
+ TA_PERF_SEL_buffer_write_wavefronts = 0x2e,
+ TA_PERF_SEL_buffer_atomic_wavefronts = 0x2f,
+ TA_PERF_SEL_buffer_coalescable_wavefronts = 0x30,
+ TA_PERF_SEL_buffer_total_cycles = 0x31,
+ TA_PERF_SEL_buffer_coalescable_addr_multicycled_cycles= 0x32,
+ TA_PERF_SEL_buffer_coalescable_clamp_16kdword_multicycled_cycles= 0x33,
+ TA_PERF_SEL_buffer_coalesced_read_cycles = 0x34,
+ TA_PERF_SEL_buffer_coalesced_write_cycles = 0x35,
+ TA_PERF_SEL_addr_stalled_by_tc_cycles = 0x36,
+ TA_PERF_SEL_addr_stalled_by_td_cycles = 0x37,
+ TA_PERF_SEL_data_stalled_by_tc_cycles = 0x38,
+ TA_PERF_SEL_addresser_stalled_by_aligner_only_cycles= 0x39,
+ TA_PERF_SEL_addresser_stalled_cycles = 0x3a,
+ TA_PERF_SEL_aniso_stalled_by_addresser_only_cycles= 0x3b,
+ TA_PERF_SEL_aniso_stalled_cycles = 0x3c,
+ TA_PERF_SEL_deriv_stalled_by_aniso_only_cycles = 0x3d,
+ TA_PERF_SEL_deriv_stalled_cycles = 0x3e,
+ TA_PERF_SEL_aniso_gt1_cycle_quads = 0x3f,
+ TA_PERF_SEL_color_1_cycle_pixels = 0x40,
+ TA_PERF_SEL_color_2_cycle_pixels = 0x41,
+ TA_PERF_SEL_color_3_cycle_pixels = 0x42,
+ TA_PERF_SEL_color_4_cycle_pixels = 0x43,
+ TA_PERF_SEL_mip_1_cycle_pixels = 0x44,
+ TA_PERF_SEL_mip_2_cycle_pixels = 0x45,
+ TA_PERF_SEL_vol_1_cycle_pixels = 0x46,
+ TA_PERF_SEL_vol_2_cycle_pixels = 0x47,
+ TA_PERF_SEL_bilin_point_1_cycle_pixels = 0x48,
+ TA_PERF_SEL_mipmap_lod_0_samples = 0x49,
+ TA_PERF_SEL_mipmap_lod_1_samples = 0x4a,
+ TA_PERF_SEL_mipmap_lod_2_samples = 0x4b,
+ TA_PERF_SEL_mipmap_lod_3_samples = 0x4c,
+ TA_PERF_SEL_mipmap_lod_4_samples = 0x4d,
+ TA_PERF_SEL_mipmap_lod_5_samples = 0x4e,
+ TA_PERF_SEL_mipmap_lod_6_samples = 0x4f,
+ TA_PERF_SEL_mipmap_lod_7_samples = 0x50,
+ TA_PERF_SEL_mipmap_lod_8_samples = 0x51,
+ TA_PERF_SEL_mipmap_lod_9_samples = 0x52,
+ TA_PERF_SEL_mipmap_lod_10_samples = 0x53,
+ TA_PERF_SEL_mipmap_lod_11_samples = 0x54,
+ TA_PERF_SEL_mipmap_lod_12_samples = 0x55,
+ TA_PERF_SEL_mipmap_lod_13_samples = 0x56,
+ TA_PERF_SEL_mipmap_lod_14_samples = 0x57,
+ TA_PERF_SEL_mipmap_invalid_samples = 0x58,
+ TA_PERF_SEL_aniso_1_cycle_quads = 0x59,
+ TA_PERF_SEL_aniso_2_cycle_quads = 0x5a,
+ TA_PERF_SEL_aniso_4_cycle_quads = 0x5b,
+ TA_PERF_SEL_aniso_6_cycle_quads = 0x5c,
+ TA_PERF_SEL_aniso_8_cycle_quads = 0x5d,
+ TA_PERF_SEL_aniso_10_cycle_quads = 0x5e,
+ TA_PERF_SEL_aniso_12_cycle_quads = 0x5f,
+ TA_PERF_SEL_aniso_14_cycle_quads = 0x60,
+ TA_PERF_SEL_aniso_16_cycle_quads = 0x61,
+ TA_PERF_SEL_write_path_input_cycles = 0x62,
+ TA_PERF_SEL_write_path_output_cycles = 0x63,
+ TA_PERF_SEL_flat_wavefronts = 0x64,
+ TA_PERF_SEL_flat_read_wavefronts = 0x65,
+ TA_PERF_SEL_flat_write_wavefronts = 0x66,
+ TA_PERF_SEL_flat_atomic_wavefronts = 0x67,
+ TA_PERF_SEL_flat_coalesceable_wavefronts = 0x68,
+ TA_PERF_SEL_reg_sclk_vld = 0x69,
+ TA_PERF_SEL_local_cg_dyn_sclk_grp0_en = 0x6a,
+ TA_PERF_SEL_local_cg_dyn_sclk_grp1_en = 0x6b,
+ TA_PERF_SEL_local_cg_dyn_sclk_grp1_mems_en = 0x6c,
+ TA_PERF_SEL_local_cg_dyn_sclk_grp4_en = 0x6d,
+ TA_PERF_SEL_local_cg_dyn_sclk_grp5_en = 0x6e,
+ TA_PERF_SEL_xnack_on_phase0 = 0x6f,
+ TA_PERF_SEL_xnack_on_phase1 = 0x70,
+ TA_PERF_SEL_xnack_on_phase2 = 0x71,
+ TA_PERF_SEL_xnack_on_phase3 = 0x72,
+ TA_PERF_SEL_first_xnack_on_phase0 = 0x73,
+ TA_PERF_SEL_first_xnack_on_phase1 = 0x74,
+ TA_PERF_SEL_first_xnack_on_phase2 = 0x75,
+ TA_PERF_SEL_first_xnack_on_phase3 = 0x76,
+} TA_PERFCOUNT_SEL;
+typedef enum TD_PERFCOUNT_SEL {
+ TD_PERF_SEL_none = 0x0,
+ TD_PERF_SEL_td_busy = 0x1,
+ TD_PERF_SEL_input_busy = 0x2,
+ TD_PERF_SEL_output_busy = 0x3,
+ TD_PERF_SEL_lerp_busy = 0x4,
+ TD_PERF_SEL_reg_sclk_vld = 0x5,
+ TD_PERF_SEL_local_cg_dyn_sclk_grp0_en = 0x6,
+ TD_PERF_SEL_local_cg_dyn_sclk_grp1_en = 0x7,
+ TD_PERF_SEL_local_cg_dyn_sclk_grp4_en = 0x8,
+ TD_PERF_SEL_local_cg_dyn_sclk_grp5_en = 0x9,
+ TD_PERF_SEL_tc_td_fifo_full = 0xa,
+ TD_PERF_SEL_constant_state_full = 0xb,
+ TD_PERF_SEL_sample_state_full = 0xc,
+ TD_PERF_SEL_output_fifo_full = 0xd,
+ TD_PERF_SEL_RESERVED_14 = 0xe,
+ TD_PERF_SEL_tc_stall = 0xf,
+ TD_PERF_SEL_pc_stall = 0x10,
+ TD_PERF_SEL_gds_stall = 0x11,
+ TD_PERF_SEL_RESERVED_18 = 0x12,
+ TD_PERF_SEL_RESERVED_19 = 0x13,
+ TD_PERF_SEL_gather4_wavefront = 0x14,
+ TD_PERF_SEL_sample_c_wavefront = 0x15,
+ TD_PERF_SEL_load_wavefront = 0x16,
+ TD_PERF_SEL_atomic_wavefront = 0x17,
+ TD_PERF_SEL_store_wavefront = 0x18,
+ TD_PERF_SEL_ldfptr_wavefront = 0x19,
+ TD_PERF_SEL_RESERVED_26 = 0x1a,
+ TD_PERF_SEL_RESERVED_27 = 0x1b,
+ TD_PERF_SEL_d16_en_wavefront = 0x1c,
+ TD_PERF_SEL_bicubic_filter_wavefront = 0x1d,
+ TD_PERF_SEL_bypass_filter_wavefront = 0x1e,
+ TD_PERF_SEL_min_max_filter_wavefront = 0x1f,
+ TD_PERF_SEL_coalescable_wavefront = 0x20,
+ TD_PERF_SEL_coalesced_phase = 0x21,
+ TD_PERF_SEL_four_phase_wavefront = 0x22,
+ TD_PERF_SEL_eight_phase_wavefront = 0x23,
+ TD_PERF_SEL_sixteen_phase_wavefront = 0x24,
+ TD_PERF_SEL_four_phase_forward_wavefront = 0x25,
+ TD_PERF_SEL_write_ack_wavefront = 0x26,
+ TD_PERF_SEL_RESERVED_39 = 0x27,
+ TD_PERF_SEL_user_defined_border = 0x28,
+ TD_PERF_SEL_white_border = 0x29,
+ TD_PERF_SEL_opaque_black_border = 0x2a,
+ TD_PERF_SEL_RESERVED_43 = 0x2b,
+ TD_PERF_SEL_RESERVED_44 = 0x2c,
+ TD_PERF_SEL_nack = 0x2d,
+ TD_PERF_SEL_td_sp_traffic = 0x2e,
+ TD_PERF_SEL_consume_gds_traffic = 0x2f,
+ TD_PERF_SEL_addresscmd_poison = 0x30,
+ TD_PERF_SEL_data_poison = 0x31,
+ TD_PERF_SEL_start_cycle_0 = 0x32,
+ TD_PERF_SEL_start_cycle_1 = 0x33,
+ TD_PERF_SEL_start_cycle_2 = 0x34,
+ TD_PERF_SEL_start_cycle_3 = 0x35,
+ TD_PERF_SEL_null_cycle_output = 0x36,
+ TD_PERF_SEL_d16_data_packed = 0x37,
+} TD_PERFCOUNT_SEL;
+typedef enum TCP_PERFCOUNT_SELECT {
+ TCP_PERF_SEL_TA_TCP_ADDR_STARVE_CYCLES = 0x0,
+ TCP_PERF_SEL_TA_TCP_DATA_STARVE_CYCLES = 0x1,
+ TCP_PERF_SEL_TCP_TA_ADDR_STALL_CYCLES = 0x2,
+ TCP_PERF_SEL_TCP_TA_DATA_STALL_CYCLES = 0x3,
+ TCP_PERF_SEL_TD_TCP_STALL_CYCLES = 0x4,
+ TCP_PERF_SEL_TCR_TCP_STALL_CYCLES = 0x5,
+ TCP_PERF_SEL_LOD_STALL_CYCLES = 0x6,
+ TCP_PERF_SEL_READ_TAGCONFLICT_STALL_CYCLES = 0x7,
+ TCP_PERF_SEL_WRITE_TAGCONFLICT_STALL_CYCLES = 0x8,
+ TCP_PERF_SEL_ATOMIC_TAGCONFLICT_STALL_CYCLES = 0x9,
+ TCP_PERF_SEL_ALLOC_STALL_CYCLES = 0xa,
+ TCP_PERF_SEL_LFIFO_STALL_CYCLES = 0xb,
+ TCP_PERF_SEL_RFIFO_STALL_CYCLES = 0xc,
+ TCP_PERF_SEL_TCR_RDRET_STALL = 0xd,
+ TCP_PERF_SEL_WRITE_CONFLICT_STALL = 0xe,
+ TCP_PERF_SEL_HOLE_READ_STALL = 0xf,
+ TCP_PERF_SEL_READCONFLICT_STALL_CYCLES = 0x10,
+ TCP_PERF_SEL_PENDING_STALL_CYCLES = 0x11,
+ TCP_PERF_SEL_READFIFO_STALL_CYCLES = 0x12,
+ TCP_PERF_SEL_TCP_LATENCY = 0x13,
+ TCP_PERF_SEL_TCC_READ_REQ_LATENCY = 0x14,
+ TCP_PERF_SEL_TCC_WRITE_REQ_LATENCY = 0x15,
+ TCP_PERF_SEL_TCC_WRITE_REQ_HOLE_LATENCY = 0x16,
+ TCP_PERF_SEL_TCC_READ_REQ = 0x17,
+ TCP_PERF_SEL_TCC_WRITE_REQ = 0x18,
+ TCP_PERF_SEL_TCC_ATOMIC_WITH_RET_REQ = 0x19,
+ TCP_PERF_SEL_TCC_ATOMIC_WITHOUT_RET_REQ = 0x1a,
+ TCP_PERF_SEL_TOTAL_LOCAL_READ = 0x1b,
+ TCP_PERF_SEL_TOTAL_GLOBAL_READ = 0x1c,
+ TCP_PERF_SEL_TOTAL_LOCAL_WRITE = 0x1d,
+ TCP_PERF_SEL_TOTAL_GLOBAL_WRITE = 0x1e,
+ TCP_PERF_SEL_TOTAL_ATOMIC_WITH_RET = 0x1f,
+ TCP_PERF_SEL_TOTAL_ATOMIC_WITHOUT_RET = 0x20,
+ TCP_PERF_SEL_TOTAL_WBINVL1 = 0x21,
+ TCP_PERF_SEL_IMG_READ_FMT_1 = 0x22,
+ TCP_PERF_SEL_IMG_READ_FMT_8 = 0x23,
+ TCP_PERF_SEL_IMG_READ_FMT_16 = 0x24,
+ TCP_PERF_SEL_IMG_READ_FMT_32 = 0x25,
+ TCP_PERF_SEL_IMG_READ_FMT_32_AS_8 = 0x26,
+ TCP_PERF_SEL_IMG_READ_FMT_32_AS_16 = 0x27,
+ TCP_PERF_SEL_IMG_READ_FMT_32_AS_128 = 0x28,
+ TCP_PERF_SEL_IMG_READ_FMT_64_2_CYCLE = 0x29,
+ TCP_PERF_SEL_IMG_READ_FMT_64_1_CYCLE = 0x2a,
+ TCP_PERF_SEL_IMG_READ_FMT_96 = 0x2b,
+ TCP_PERF_SEL_IMG_READ_FMT_128_4_CYCLE = 0x2c,
+ TCP_PERF_SEL_IMG_READ_FMT_128_1_CYCLE = 0x2d,
+ TCP_PERF_SEL_IMG_READ_FMT_BC1 = 0x2e,
+ TCP_PERF_SEL_IMG_READ_FMT_BC2 = 0x2f,
+ TCP_PERF_SEL_IMG_READ_FMT_BC3 = 0x30,
+ TCP_PERF_SEL_IMG_READ_FMT_BC4 = 0x31,
+ TCP_PERF_SEL_IMG_READ_FMT_BC5 = 0x32,
+ TCP_PERF_SEL_IMG_READ_FMT_BC6 = 0x33,
+ TCP_PERF_SEL_IMG_READ_FMT_BC7 = 0x34,
+ TCP_PERF_SEL_IMG_READ_FMT_I8 = 0x35,
+ TCP_PERF_SEL_IMG_READ_FMT_I16 = 0x36,
+ TCP_PERF_SEL_IMG_READ_FMT_I32 = 0x37,
+ TCP_PERF_SEL_IMG_READ_FMT_I32_AS_8 = 0x38,
+ TCP_PERF_SEL_IMG_READ_FMT_I32_AS_16 = 0x39,
+ TCP_PERF_SEL_IMG_READ_FMT_D8 = 0x3a,
+ TCP_PERF_SEL_IMG_READ_FMT_D16 = 0x3b,
+ TCP_PERF_SEL_IMG_READ_FMT_D32 = 0x3c,
+ TCP_PERF_SEL_IMG_WRITE_FMT_8 = 0x3d,
+ TCP_PERF_SEL_IMG_WRITE_FMT_16 = 0x3e,
+ TCP_PERF_SEL_IMG_WRITE_FMT_32 = 0x3f,
+ TCP_PERF_SEL_IMG_WRITE_FMT_64 = 0x40,
+ TCP_PERF_SEL_IMG_WRITE_FMT_128 = 0x41,
+ TCP_PERF_SEL_IMG_WRITE_FMT_D8 = 0x42,
+ TCP_PERF_SEL_IMG_WRITE_FMT_D16 = 0x43,
+ TCP_PERF_SEL_IMG_WRITE_FMT_D32 = 0x44,
+ TCP_PERF_SEL_IMG_ATOMIC_WITH_RET_FMT_32 = 0x45,
+ TCP_PERF_SEL_IMG_ATOMIC_WITHOUT_RET_FMT_32 = 0x46,
+ TCP_PERF_SEL_IMG_ATOMIC_WITH_RET_FMT_64 = 0x47,
+ TCP_PERF_SEL_IMG_ATOMIC_WITHOUT_RET_FMT_64 = 0x48,
+ TCP_PERF_SEL_BUF_READ_FMT_8 = 0x49,
+ TCP_PERF_SEL_BUF_READ_FMT_16 = 0x4a,
+ TCP_PERF_SEL_BUF_READ_FMT_32 = 0x4b,
+ TCP_PERF_SEL_BUF_WRITE_FMT_8 = 0x4c,
+ TCP_PERF_SEL_BUF_WRITE_FMT_16 = 0x4d,
+ TCP_PERF_SEL_BUF_WRITE_FMT_32 = 0x4e,
+ TCP_PERF_SEL_BUF_ATOMIC_WITH_RET_FMT_32 = 0x4f,
+ TCP_PERF_SEL_BUF_ATOMIC_WITHOUT_RET_FMT_32 = 0x50,
+ TCP_PERF_SEL_BUF_ATOMIC_WITH_RET_FMT_64 = 0x51,
+ TCP_PERF_SEL_BUF_ATOMIC_WITHOUT_RET_FMT_64 = 0x52,
+ TCP_PERF_SEL_ARR_LINEAR_GENERAL = 0x53,
+ TCP_PERF_SEL_ARR_LINEAR_ALIGNED = 0x54,
+ TCP_PERF_SEL_ARR_1D_THIN1 = 0x55,
+ TCP_PERF_SEL_ARR_1D_THICK = 0x56,
+ TCP_PERF_SEL_ARR_2D_THIN1 = 0x57,
+ TCP_PERF_SEL_ARR_2D_THICK = 0x58,
+ TCP_PERF_SEL_ARR_2D_XTHICK = 0x59,
+ TCP_PERF_SEL_ARR_3D_THIN1 = 0x5a,
+ TCP_PERF_SEL_ARR_3D_THICK = 0x5b,
+ TCP_PERF_SEL_ARR_3D_XTHICK = 0x5c,
+ TCP_PERF_SEL_DIM_1D = 0x5d,
+ TCP_PERF_SEL_DIM_2D = 0x5e,
+ TCP_PERF_SEL_DIM_3D = 0x5f,
+ TCP_PERF_SEL_DIM_1D_ARRAY = 0x60,
+ TCP_PERF_SEL_DIM_2D_ARRAY = 0x61,
+ TCP_PERF_SEL_DIM_2D_MSAA = 0x62,
+ TCP_PERF_SEL_DIM_2D_ARRAY_MSAA = 0x63,
+ TCP_PERF_SEL_DIM_CUBE_ARRAY = 0x64,
+ TCP_PERF_SEL_CP_TCP_INVALIDATE = 0x65,
+ TCP_PERF_SEL_TA_TCP_STATE_READ = 0x66,
+ TCP_PERF_SEL_TAGRAM0_REQ = 0x67,
+ TCP_PERF_SEL_TAGRAM1_REQ = 0x68,
+ TCP_PERF_SEL_TAGRAM2_REQ = 0x69,
+ TCP_PERF_SEL_TAGRAM3_REQ = 0x6a,
+ TCP_PERF_SEL_GATE_EN1 = 0x6b,
+ TCP_PERF_SEL_GATE_EN2 = 0x6c,
+ TCP_PERF_SEL_CORE_REG_SCLK_VLD = 0x6d,
+ TCP_PERF_SEL_TCC_REQ = 0x6e,
+ TCP_PERF_SEL_TCC_NON_READ_REQ = 0x6f,
+ TCP_PERF_SEL_TCC_BYPASS_READ_REQ = 0x70,
+ TCP_PERF_SEL_TCC_MISS_EVICT_READ_REQ = 0x71,
+ TCP_PERF_SEL_TCC_VOLATILE_READ_REQ = 0x72,
+ TCP_PERF_SEL_TCC_VOLATILE_BYPASS_READ_REQ = 0x73,
+ TCP_PERF_SEL_TCC_VOLATILE_MISS_EVICT_READ_REQ = 0x74,
+ TCP_PERF_SEL_TCC_BYPASS_WRITE_REQ = 0x75,
+ TCP_PERF_SEL_TCC_MISS_EVICT_WRITE_REQ = 0x76,
+ TCP_PERF_SEL_TCC_VOLATILE_BYPASS_WRITE_REQ = 0x77,
+ TCP_PERF_SEL_TCC_VOLATILE_WRITE_REQ = 0x78,
+ TCP_PERF_SEL_TCC_VOLATILE_MISS_EVICT_WRITE_REQ = 0x79,
+ TCP_PERF_SEL_TCC_BYPASS_ATOMIC_REQ = 0x7a,
+ TCP_PERF_SEL_TCC_ATOMIC_REQ = 0x7b,
+ TCP_PERF_SEL_TCC_VOLATILE_ATOMIC_REQ = 0x7c,
+ TCP_PERF_SEL_TCC_DATA_BUS_BUSY = 0x7d,
+ TCP_PERF_SEL_TOTAL_ACCESSES = 0x7e,
+ TCP_PERF_SEL_TOTAL_READ = 0x7f,
+ TCP_PERF_SEL_TOTAL_HIT_LRU_READ = 0x80,
+ TCP_PERF_SEL_TOTAL_HIT_EVICT_READ = 0x81,
+ TCP_PERF_SEL_TOTAL_MISS_LRU_READ = 0x82,
+ TCP_PERF_SEL_TOTAL_MISS_EVICT_READ = 0x83,
+ TCP_PERF_SEL_TOTAL_NON_READ = 0x84,
+ TCP_PERF_SEL_TOTAL_WRITE = 0x85,
+ TCP_PERF_SEL_TOTAL_MISS_LRU_WRITE = 0x86,
+ TCP_PERF_SEL_TOTAL_MISS_EVICT_WRITE = 0x87,
+ TCP_PERF_SEL_TOTAL_WBINVL1_VOL = 0x88,
+ TCP_PERF_SEL_TOTAL_WRITEBACK_INVALIDATES = 0x89,
+ TCP_PERF_SEL_DISPLAY_MICROTILING = 0x8a,
+ TCP_PERF_SEL_THIN_MICROTILING = 0x8b,
+ TCP_PERF_SEL_DEPTH_MICROTILING = 0x8c,
+ TCP_PERF_SEL_ARR_PRT_THIN1 = 0x8d,
+ TCP_PERF_SEL_ARR_PRT_2D_THIN1 = 0x8e,
+ TCP_PERF_SEL_ARR_PRT_3D_THIN1 = 0x8f,
+ TCP_PERF_SEL_ARR_PRT_THICK = 0x90,
+ TCP_PERF_SEL_ARR_PRT_2D_THICK = 0x91,
+ TCP_PERF_SEL_ARR_PRT_3D_THICK = 0x92,
+ TCP_PERF_SEL_CP_TCP_INVALIDATE_VOL = 0x93,
+ TCP_PERF_SEL_SQ_TCP_INVALIDATE_VOL = 0x94,
+ TCP_PERF_SEL_UNALIGNED = 0x95,
+ TCP_PERF_SEL_ROTATED_MICROTILING = 0x96,
+ TCP_PERF_SEL_THICK_MICROTILING = 0x97,
+ TCP_PERF_SEL_ATC = 0x98,
+ TCP_PERF_SEL_POWER_STALL = 0x99,
+ TCP_PERF_SEL_RESERVED_154 = 0x9a,
+ TCP_PERF_SEL_TCC_LRU_REQ = 0x9b,
+ TCP_PERF_SEL_TCC_STREAM_REQ = 0x9c,
+ TCP_PERF_SEL_TCC_NC_READ_REQ = 0x9d,
+ TCP_PERF_SEL_TCC_NC_WRITE_REQ = 0x9e,
+ TCP_PERF_SEL_TCC_NC_ATOMIC_REQ = 0x9f,
+ TCP_PERF_SEL_TCC_UC_READ_REQ = 0xa0,
+ TCP_PERF_SEL_TCC_UC_WRITE_REQ = 0xa1,
+ TCP_PERF_SEL_TCC_UC_ATOMIC_REQ = 0xa2,
+ TCP_PERF_SEL_TCC_CC_READ_REQ = 0xa3,
+ TCP_PERF_SEL_TCC_CC_WRITE_REQ = 0xa4,
+ TCP_PERF_SEL_TCC_CC_ATOMIC_REQ = 0xa5,
+ TCP_PERF_SEL_TCC_DCC_REQ = 0xa6,
+ TCP_PERF_SEL_TCC_PHYSICAL_REQ = 0xa7,
+ TCP_PERF_SEL_UNORDERED_MTYPE_STALL = 0xa8,
+ TCP_PERF_SEL_VOLATILE = 0xa9,
+ TCP_PERF_SEL_TC_TA_XNACK_STALL = 0xaa,
+ TCP_PERF_SEL_ATCL1_SERIALIZATION_STALL = 0xab,
+ TCP_PERF_SEL_SHOOTDOWN = 0xac,
+ TCP_PERF_SEL_GATCL1_TRANSLATION_MISS = 0xad,
+ TCP_PERF_SEL_GATCL1_PERMISSION_MISS = 0xae,
+ TCP_PERF_SEL_GATCL1_REQUEST = 0xaf,
+ TCP_PERF_SEL_GATCL1_STALL_INFLIGHT_MAX = 0xb0,
+ TCP_PERF_SEL_GATCL1_STALL_LRU_INFLIGHT = 0xb1,
+ TCP_PERF_SEL_GATCL1_LFIFO_FULL = 0xb2,
+ TCP_PERF_SEL_GATCL1_STALL_LFIFO_NOT_RES = 0xb3,
+ TCP_PERF_SEL_GATCL1_STALL_ATCL2_REQ_OUT_OF_CREDITS= 0xb4,
+ TCP_PERF_SEL_GATCL1_ATCL2_INFLIGHT = 0xb5,
+ TCP_PERF_SEL_GATCL1_STALL_MISSFIFO_FULL = 0xb6,
+ TCP_PERF_SEL_IMG_READ_FMT_ETC2_RGB = 0xb7,
+ TCP_PERF_SEL_IMG_READ_FMT_ETC2_RGBA = 0xb8,
+ TCP_PERF_SEL_IMG_READ_FMT_ETC2_RGBA1 = 0xb9,
+ TCP_PERF_SEL_IMG_READ_FMT_ETC2_R = 0xba,
+ TCP_PERF_SEL_IMG_READ_FMT_ETC2_RG = 0xbb,
+ TCP_PERF_SEL_IMG_READ_FMT_8_AS_32 = 0xbc,
+ TCP_PERF_SEL_IMG_READ_FMT_8_AS_64 = 0xbd,
+ TCP_PERF_SEL_IMG_READ_FMT_16_AS_64 = 0xbe,
+ TCP_PERF_SEL_IMG_READ_FMT_16_AS_128 = 0xbf,
+ TCP_PERF_SEL_IMG_WRITE_FMT_8_AS_32 = 0xc0,
+ TCP_PERF_SEL_IMG_WRITE_FMT_8_AS_64 = 0xc1,
+ TCP_PERF_SEL_IMG_WRITE_FMT_16_AS_64 = 0xc2,
+ TCP_PERF_SEL_IMG_WRITE_FMT_16_AS_128 = 0xc3,
+} TCP_PERFCOUNT_SELECT;
+typedef enum TCP_CACHE_POLICIES {
+ TCP_CACHE_POLICY_MISS_LRU = 0x0,
+ TCP_CACHE_POLICY_MISS_EVICT = 0x1,
+ TCP_CACHE_POLICY_HIT_LRU = 0x2,
+ TCP_CACHE_POLICY_HIT_EVICT = 0x3,
+} TCP_CACHE_POLICIES;
+typedef enum TCP_CACHE_STORE_POLICIES {
+ TCP_CACHE_STORE_POLICY_WT_LRU = 0x0,
+ TCP_CACHE_STORE_POLICY_WT_EVICT = 0x1,
+} TCP_CACHE_STORE_POLICIES;
+typedef enum TCP_WATCH_MODES {
+ TCP_WATCH_MODE_READ = 0x0,
+ TCP_WATCH_MODE_NONREAD = 0x1,
+ TCP_WATCH_MODE_ATOMIC = 0x2,
+ TCP_WATCH_MODE_ALL = 0x3,
+} TCP_WATCH_MODES;
+typedef enum TCP_DSM_DATA_SEL {
+ TCP_DSM_DISABLE = 0x0,
+ TCP_DSM_SEL0 = 0x1,
+ TCP_DSM_SEL1 = 0x2,
+ TCP_DSM_SEL_BOTH = 0x3,
+} TCP_DSM_DATA_SEL;
+typedef enum TCP_DSM_SINGLE_WRITE {
+ TCP_DSM_SINGLE_WRITE_EN = 0x1,
+} TCP_DSM_SINGLE_WRITE;
+typedef enum VGT_OUT_PRIM_TYPE {
+ VGT_OUT_POINT = 0x0,
+ VGT_OUT_LINE = 0x1,
+ VGT_OUT_TRI = 0x2,
+ VGT_OUT_RECT_V0 = 0x3,
+ VGT_OUT_RECT_V1 = 0x4,
+ VGT_OUT_RECT_V2 = 0x5,
+ VGT_OUT_RECT_V3 = 0x6,
+ VGT_OUT_RESERVED = 0x7,
+ VGT_TE_QUAD = 0x8,
+ VGT_TE_PRIM_INDEX_LINE = 0x9,
+ VGT_TE_PRIM_INDEX_TRI = 0xa,
+ VGT_TE_PRIM_INDEX_QUAD = 0xb,
+ VGT_OUT_LINE_ADJ = 0xc,
+ VGT_OUT_TRI_ADJ = 0xd,
+ VGT_OUT_PATCH = 0xe,
+} VGT_OUT_PRIM_TYPE;
+typedef enum VGT_DI_PRIM_TYPE {
+ DI_PT_NONE = 0x0,
+ DI_PT_POINTLIST = 0x1,
+ DI_PT_LINELIST = 0x2,
+ DI_PT_LINESTRIP = 0x3,
+ DI_PT_TRILIST = 0x4,
+ DI_PT_TRIFAN = 0x5,
+ DI_PT_TRISTRIP = 0x6,
+ DI_PT_UNUSED_0 = 0x7,
+ DI_PT_UNUSED_1 = 0x8,
+ DI_PT_PATCH = 0x9,
+ DI_PT_LINELIST_ADJ = 0xa,
+ DI_PT_LINESTRIP_ADJ = 0xb,
+ DI_PT_TRILIST_ADJ = 0xc,
+ DI_PT_TRISTRIP_ADJ = 0xd,
+ DI_PT_UNUSED_3 = 0xe,
+ DI_PT_UNUSED_4 = 0xf,
+ DI_PT_TRI_WITH_WFLAGS = 0x10,
+ DI_PT_RECTLIST = 0x11,
+ DI_PT_LINELOOP = 0x12,
+ DI_PT_QUADLIST = 0x13,
+ DI_PT_QUADSTRIP = 0x14,
+ DI_PT_POLYGON = 0x15,
+ DI_PT_2D_COPY_RECT_LIST_V0 = 0x16,
+ DI_PT_2D_COPY_RECT_LIST_V1 = 0x17,
+ DI_PT_2D_COPY_RECT_LIST_V2 = 0x18,
+ DI_PT_2D_COPY_RECT_LIST_V3 = 0x19,
+ DI_PT_2D_FILL_RECT_LIST = 0x1a,
+ DI_PT_2D_LINE_STRIP = 0x1b,
+ DI_PT_2D_TRI_STRIP = 0x1c,
+} VGT_DI_PRIM_TYPE;
+typedef enum VGT_DI_SOURCE_SELECT {
+ DI_SRC_SEL_DMA = 0x0,
+ DI_SRC_SEL_IMMEDIATE = 0x1,
+ DI_SRC_SEL_AUTO_INDEX = 0x2,
+ DI_SRC_SEL_RESERVED = 0x3,
+} VGT_DI_SOURCE_SELECT;
+typedef enum VGT_DI_MAJOR_MODE_SELECT {
+ DI_MAJOR_MODE_0 = 0x0,
+ DI_MAJOR_MODE_1 = 0x1,
+} VGT_DI_MAJOR_MODE_SELECT;
+typedef enum VGT_DI_INDEX_SIZE {
+ DI_INDEX_SIZE_16_BIT = 0x0,
+ DI_INDEX_SIZE_32_BIT = 0x1,
+ DI_INDEX_SIZE_8_BIT = 0x2,
+} VGT_DI_INDEX_SIZE;
+typedef enum VGT_EVENT_TYPE {
+ Reserved_0x00 = 0x0,
+ SAMPLE_STREAMOUTSTATS1 = 0x1,
+ SAMPLE_STREAMOUTSTATS2 = 0x2,
+ SAMPLE_STREAMOUTSTATS3 = 0x3,
+ CACHE_FLUSH_TS = 0x4,
+ CONTEXT_DONE = 0x5,
+ CACHE_FLUSH = 0x6,
+ CS_PARTIAL_FLUSH = 0x7,
+ VGT_STREAMOUT_SYNC = 0x8,
+ Reserved_0x09 = 0x9,
+ VGT_STREAMOUT_RESET = 0xa,
+ END_OF_PIPE_INCR_DE = 0xb,
+ END_OF_PIPE_IB_END = 0xc,
+ RST_PIX_CNT = 0xd,
+ Reserved_0x0E = 0xe,
+ VS_PARTIAL_FLUSH = 0xf,
+ PS_PARTIAL_FLUSH = 0x10,
+ FLUSH_HS_OUTPUT = 0x11,
+ FLUSH_LS_OUTPUT = 0x12,
+ Reserved_0x13 = 0x13,
+ CACHE_FLUSH_AND_INV_TS_EVENT = 0x14,
+ ZPASS_DONE = 0x15,
+ CACHE_FLUSH_AND_INV_EVENT = 0x16,
+ PERFCOUNTER_START = 0x17,
+ PERFCOUNTER_STOP = 0x18,
+ PIPELINESTAT_START = 0x19,
+ PIPELINESTAT_STOP = 0x1a,
+ PERFCOUNTER_SAMPLE = 0x1b,
+ FLUSH_ES_OUTPUT = 0x1c,
+ FLUSH_GS_OUTPUT = 0x1d,
+ SAMPLE_PIPELINESTAT = 0x1e,
+ SO_VGTSTREAMOUT_FLUSH = 0x1f,
+ SAMPLE_STREAMOUTSTATS = 0x20,
+ RESET_VTX_CNT = 0x21,
+ BLOCK_CONTEXT_DONE = 0x22,
+ CS_CONTEXT_DONE = 0x23,
+ VGT_FLUSH = 0x24,
+ TGID_ROLLOVER = 0x25,
+ SQ_NON_EVENT = 0x26,
+ SC_SEND_DB_VPZ = 0x27,
+ BOTTOM_OF_PIPE_TS = 0x28,
+ FLUSH_SX_TS = 0x29,
+ DB_CACHE_FLUSH_AND_INV = 0x2a,
+ FLUSH_AND_INV_DB_DATA_TS = 0x2b,
+ FLUSH_AND_INV_DB_META = 0x2c,
+ FLUSH_AND_INV_CB_DATA_TS = 0x2d,
+ FLUSH_AND_INV_CB_META = 0x2e,
+ CS_DONE = 0x2f,
+ PS_DONE = 0x30,
+ FLUSH_AND_INV_CB_PIXEL_DATA = 0x31,
+ SX_CB_RAT_ACK_REQUEST = 0x32,
+ THREAD_TRACE_START = 0x33,
+ THREAD_TRACE_STOP = 0x34,
+ THREAD_TRACE_MARKER = 0x35,
+ THREAD_TRACE_FLUSH = 0x36,
+ THREAD_TRACE_FINISH = 0x37,
+ PIXEL_PIPE_STAT_CONTROL = 0x38,
+ PIXEL_PIPE_STAT_DUMP = 0x39,
+ PIXEL_PIPE_STAT_RESET = 0x3a,
+ CONTEXT_SUSPEND = 0x3b,
+ OFFCHIP_HS_DEALLOC = 0x3c,
+} VGT_EVENT_TYPE;
+typedef enum VGT_DMA_SWAP_MODE {
+ VGT_DMA_SWAP_NONE = 0x0,
+ VGT_DMA_SWAP_16_BIT = 0x1,
+ VGT_DMA_SWAP_32_BIT = 0x2,
+ VGT_DMA_SWAP_WORD = 0x3,
+} VGT_DMA_SWAP_MODE;
+typedef enum VGT_INDEX_TYPE_MODE {
+ VGT_INDEX_16 = 0x0,
+ VGT_INDEX_32 = 0x1,
+ VGT_INDEX_8 = 0x2,
+} VGT_INDEX_TYPE_MODE;
+typedef enum VGT_DMA_BUF_TYPE {
+ VGT_DMA_BUF_MEM = 0x0,
+ VGT_DMA_BUF_RING = 0x1,
+ VGT_DMA_BUF_SETUP = 0x2,
+ VGT_DMA_PTR_UPDATE = 0x3,
+} VGT_DMA_BUF_TYPE;
+typedef enum VGT_OUTPATH_SELECT {
+ VGT_OUTPATH_VTX_REUSE = 0x0,
+ VGT_OUTPATH_TESS_EN = 0x1,
+ VGT_OUTPATH_PASSTHRU = 0x2,
+ VGT_OUTPATH_GS_BLOCK = 0x3,
+ VGT_OUTPATH_HS_BLOCK = 0x4,
+} VGT_OUTPATH_SELECT;
+typedef enum VGT_GRP_PRIM_TYPE {
+ VGT_GRP_3D_POINT = 0x0,
+ VGT_GRP_3D_LINE = 0x1,
+ VGT_GRP_3D_TRI = 0x2,
+ VGT_GRP_3D_RECT = 0x3,
+ VGT_GRP_3D_QUAD = 0x4,
+ VGT_GRP_2D_COPY_RECT_V0 = 0x5,
+ VGT_GRP_2D_COPY_RECT_V1 = 0x6,
+ VGT_GRP_2D_COPY_RECT_V2 = 0x7,
+ VGT_GRP_2D_COPY_RECT_V3 = 0x8,
+ VGT_GRP_2D_FILL_RECT = 0x9,
+ VGT_GRP_2D_LINE = 0xa,
+ VGT_GRP_2D_TRI = 0xb,
+ VGT_GRP_PRIM_INDEX_LINE = 0xc,
+ VGT_GRP_PRIM_INDEX_TRI = 0xd,
+ VGT_GRP_PRIM_INDEX_QUAD = 0xe,
+ VGT_GRP_3D_LINE_ADJ = 0xf,
+ VGT_GRP_3D_TRI_ADJ = 0x10,
+ VGT_GRP_3D_PATCH = 0x11,
+} VGT_GRP_PRIM_TYPE;
+typedef enum VGT_GRP_PRIM_ORDER {
+ VGT_GRP_LIST = 0x0,
+ VGT_GRP_STRIP = 0x1,
+ VGT_GRP_FAN = 0x2,
+ VGT_GRP_LOOP = 0x3,
+ VGT_GRP_POLYGON = 0x4,
+} VGT_GRP_PRIM_ORDER;
+typedef enum VGT_GROUP_CONV_SEL {
+ VGT_GRP_INDEX_16 = 0x0,
+ VGT_GRP_INDEX_32 = 0x1,
+ VGT_GRP_UINT_16 = 0x2,
+ VGT_GRP_UINT_32 = 0x3,
+ VGT_GRP_SINT_16 = 0x4,
+ VGT_GRP_SINT_32 = 0x5,
+ VGT_GRP_FLOAT_32 = 0x6,
+ VGT_GRP_AUTO_PRIM = 0x7,
+ VGT_GRP_FIX_1_23_TO_FLOAT = 0x8,
+} VGT_GROUP_CONV_SEL;
+typedef enum VGT_GS_MODE_TYPE {
+ GS_OFF = 0x0,
+ GS_SCENARIO_A = 0x1,
+ GS_SCENARIO_B = 0x2,
+ GS_SCENARIO_G = 0x3,
+ GS_SCENARIO_C = 0x4,
+ SPRITE_EN = 0x5,
+} VGT_GS_MODE_TYPE;
+typedef enum VGT_GS_CUT_MODE {
+ GS_CUT_1024 = 0x0,
+ GS_CUT_512 = 0x1,
+ GS_CUT_256 = 0x2,
+ GS_CUT_128 = 0x3,
+} VGT_GS_CUT_MODE;
+typedef enum VGT_GS_OUTPRIM_TYPE {
+ POINTLIST = 0x0,
+ LINESTRIP = 0x1,
+ TRISTRIP = 0x2,
+} VGT_GS_OUTPRIM_TYPE;
+typedef enum VGT_CACHE_INVALID_MODE {
+ VC_ONLY = 0x0,
+ TC_ONLY = 0x1,
+ VC_AND_TC = 0x2,
+} VGT_CACHE_INVALID_MODE;
+typedef enum VGT_TESS_TYPE {
+ TESS_ISOLINE = 0x0,
+ TESS_TRIANGLE = 0x1,
+ TESS_QUAD = 0x2,
+} VGT_TESS_TYPE;
+typedef enum VGT_TESS_PARTITION {
+ PART_INTEGER = 0x0,
+ PART_POW2 = 0x1,
+ PART_FRAC_ODD = 0x2,
+ PART_FRAC_EVEN = 0x3,
+} VGT_TESS_PARTITION;
+typedef enum VGT_TESS_TOPOLOGY {
+ OUTPUT_POINT = 0x0,
+ OUTPUT_LINE = 0x1,
+ OUTPUT_TRIANGLE_CW = 0x2,
+ OUTPUT_TRIANGLE_CCW = 0x3,
+} VGT_TESS_TOPOLOGY;
+typedef enum VGT_RDREQ_POLICY {
+ VGT_POLICY_LRU = 0x0,
+ VGT_POLICY_STREAM = 0x1,
+} VGT_RDREQ_POLICY;
+typedef enum VGT_DIST_MODE {
+ NO_DIST = 0x0,
+ PATCHES = 0x1,
+ DONUTS = 0x2,
+} VGT_DIST_MODE;
+typedef enum VGT_STAGES_LS_EN {
+ LS_STAGE_OFF = 0x0,
+ LS_STAGE_ON = 0x1,
+ CS_STAGE_ON = 0x2,
+ RESERVED_LS = 0x3,
+} VGT_STAGES_LS_EN;
+typedef enum VGT_STAGES_HS_EN {
+ HS_STAGE_OFF = 0x0,
+ HS_STAGE_ON = 0x1,
+} VGT_STAGES_HS_EN;
+typedef enum VGT_STAGES_ES_EN {
+ ES_STAGE_OFF = 0x0,
+ ES_STAGE_DS = 0x1,
+ ES_STAGE_REAL = 0x2,
+ RESERVED_ES = 0x3,
+} VGT_STAGES_ES_EN;
+typedef enum VGT_STAGES_GS_EN {
+ GS_STAGE_OFF = 0x0,
+ GS_STAGE_ON = 0x1,
+} VGT_STAGES_GS_EN;
+typedef enum VGT_STAGES_VS_EN {
+ VS_STAGE_REAL = 0x0,
+ VS_STAGE_DS = 0x1,
+ VS_STAGE_COPY_SHADER = 0x2,
+ RESERVED_VS = 0x3,
+} VGT_STAGES_VS_EN;
+typedef enum VGT_PERFCOUNT_SELECT {
+ vgt_perf_VGT_SPI_ESTHREAD_EVENT_WINDOW_ACTIVE = 0x0,
+ vgt_perf_VGT_SPI_ESVERT_VALID = 0x1,
+ vgt_perf_VGT_SPI_ESVERT_EOV = 0x2,
+ vgt_perf_VGT_SPI_ESVERT_STALLED = 0x3,
+ vgt_perf_VGT_SPI_ESVERT_STARVED_BUSY = 0x4,
+ vgt_perf_VGT_SPI_ESVERT_STARVED_IDLE = 0x5,
+ vgt_perf_VGT_SPI_ESVERT_STATIC = 0x6,
+ vgt_perf_VGT_SPI_ESTHREAD_IS_EVENT = 0x7,
+ vgt_perf_VGT_SPI_ESTHREAD_SEND = 0x8,
+ vgt_perf_VGT_SPI_GSPRIM_VALID = 0x9,
+ vgt_perf_VGT_SPI_GSPRIM_EOV = 0xa,
+ vgt_perf_VGT_SPI_GSPRIM_CONT = 0xb,
+ vgt_perf_VGT_SPI_GSPRIM_STALLED = 0xc,
+ vgt_perf_VGT_SPI_GSPRIM_STARVED_BUSY = 0xd,
+ vgt_perf_VGT_SPI_GSPRIM_STARVED_IDLE = 0xe,
+ vgt_perf_VGT_SPI_GSPRIM_STATIC = 0xf,
+ vgt_perf_VGT_SPI_GSTHREAD_EVENT_WINDOW_ACTIVE = 0x10,
+ vgt_perf_VGT_SPI_GSTHREAD_IS_EVENT = 0x11,
+ vgt_perf_VGT_SPI_GSTHREAD_SEND = 0x12,
+ vgt_perf_VGT_SPI_VSTHREAD_EVENT_WINDOW_ACTIVE = 0x13,
+ vgt_perf_VGT_SPI_VSVERT_SEND = 0x14,
+ vgt_perf_VGT_SPI_VSVERT_EOV = 0x15,
+ vgt_perf_VGT_SPI_VSVERT_STALLED = 0x16,
+ vgt_perf_VGT_SPI_VSVERT_STARVED_BUSY = 0x17,
+ vgt_perf_VGT_SPI_VSVERT_STARVED_IDLE = 0x18,
+ vgt_perf_VGT_SPI_VSVERT_STATIC = 0x19,
+ vgt_perf_VGT_SPI_VSTHREAD_IS_EVENT = 0x1a,
+ vgt_perf_VGT_SPI_VSTHREAD_SEND = 0x1b,
+ vgt_perf_VGT_PA_EVENT_WINDOW_ACTIVE = 0x1c,
+ vgt_perf_VGT_PA_CLIPV_SEND = 0x1d,
+ vgt_perf_VGT_PA_CLIPV_FIRSTVERT = 0x1e,
+ vgt_perf_VGT_PA_CLIPV_STALLED = 0x1f,
+ vgt_perf_VGT_PA_CLIPV_STARVED_BUSY = 0x20,
+ vgt_perf_VGT_PA_CLIPV_STARVED_IDLE = 0x21,
+ vgt_perf_VGT_PA_CLIPV_STATIC = 0x22,
+ vgt_perf_VGT_PA_CLIPP_SEND = 0x23,
+ vgt_perf_VGT_PA_CLIPP_EOP = 0x24,
+ vgt_perf_VGT_PA_CLIPP_IS_EVENT = 0x25,
+ vgt_perf_VGT_PA_CLIPP_NULL_PRIM = 0x26,
+ vgt_perf_VGT_PA_CLIPP_NEW_VTX_VECT = 0x27,
+ vgt_perf_VGT_PA_CLIPP_STALLED = 0x28,
+ vgt_perf_VGT_PA_CLIPP_STARVED_BUSY = 0x29,
+ vgt_perf_VGT_PA_CLIPP_STARVED_IDLE = 0x2a,
+ vgt_perf_VGT_PA_CLIPP_STATIC = 0x2b,
+ vgt_perf_VGT_PA_CLIPS_SEND = 0x2c,
+ vgt_perf_VGT_PA_CLIPS_STALLED = 0x2d,
+ vgt_perf_VGT_PA_CLIPS_STARVED_BUSY = 0x2e,
+ vgt_perf_VGT_PA_CLIPS_STARVED_IDLE = 0x2f,
+ vgt_perf_VGT_PA_CLIPS_STATIC = 0x30,
+ vgt_perf_vsvert_ds_send = 0x31,
+ vgt_perf_vsvert_api_send = 0x32,
+ vgt_perf_hs_tif_stall = 0x33,
+ vgt_perf_hs_input_stall = 0x34,
+ vgt_perf_hs_interface_stall = 0x35,
+ vgt_perf_hs_tfm_stall = 0x36,
+ vgt_perf_te11_starved = 0x37,
+ vgt_perf_gs_event_stall = 0x38,
+ vgt_perf_vgt_pa_clipp_send_not_event = 0x39,
+ vgt_perf_vgt_pa_clipp_valid_prim = 0x3a,
+ vgt_perf_reused_es_indices = 0x3b,
+ vgt_perf_vs_cache_hits = 0x3c,
+ vgt_perf_gs_cache_hits = 0x3d,
+ vgt_perf_ds_cache_hits = 0x3e,
+ vgt_perf_total_cache_hits = 0x3f,
+ vgt_perf_vgt_busy = 0x40,
+ vgt_perf_vgt_gs_busy = 0x41,
+ vgt_perf_esvert_stalled_es_tbl = 0x42,
+ vgt_perf_esvert_stalled_gs_tbl = 0x43,
+ vgt_perf_esvert_stalled_gs_event = 0x44,
+ vgt_perf_esvert_stalled_gsprim = 0x45,
+ vgt_perf_gsprim_stalled_es_tbl = 0x46,
+ vgt_perf_gsprim_stalled_gs_tbl = 0x47,
+ vgt_perf_gsprim_stalled_gs_event = 0x48,
+ vgt_perf_gsprim_stalled_esvert = 0x49,
+ vgt_perf_esthread_stalled_es_rb_full = 0x4a,
+ vgt_perf_esthread_stalled_spi_bp = 0x4b,
+ vgt_perf_counters_avail_stalled = 0x4c,
+ vgt_perf_gs_rb_space_avail_stalled = 0x4d,
+ vgt_perf_gs_issue_rtr_stalled = 0x4e,
+ vgt_perf_gsthread_stalled = 0x4f,
+ vgt_perf_strmout_stalled = 0x50,
+ vgt_perf_wait_for_es_done_stalled = 0x51,
+ vgt_perf_cm_stalled_by_gog = 0x52,
+ vgt_perf_cm_reading_stalled = 0x53,
+ vgt_perf_cm_stalled_by_gsfetch_done = 0x54,
+ vgt_perf_gog_vs_tbl_stalled = 0x55,
+ vgt_perf_gog_out_indx_stalled = 0x56,
+ vgt_perf_gog_out_prim_stalled = 0x57,
+ vgt_perf_waveid_stalled = 0x58,
+ vgt_perf_gog_busy = 0x59,
+ vgt_perf_reused_vs_indices = 0x5a,
+ vgt_perf_sclk_reg_vld_event = 0x5b,
+ vgt_perf_vs_conflicting_indices = 0x5c,
+ vgt_perf_sclk_core_vld_event = 0x5d,
+ vgt_perf_hswave_stalled = 0x5e,
+ vgt_perf_sclk_gs_vld_event = 0x5f,
+ vgt_perf_VGT_SPI_LSVERT_VALID = 0x60,
+ vgt_perf_VGT_SPI_LSVERT_EOV = 0x61,
+ vgt_perf_VGT_SPI_LSVERT_STALLED = 0x62,
+ vgt_perf_VGT_SPI_LSVERT_STARVED_BUSY = 0x63,
+ vgt_perf_VGT_SPI_LSVERT_STARVED_IDLE = 0x64,
+ vgt_perf_VGT_SPI_LSVERT_STATIC = 0x65,
+ vgt_perf_VGT_SPI_LSWAVE_EVENT_WINDOW_ACTIVE = 0x66,
+ vgt_perf_VGT_SPI_LSWAVE_IS_EVENT = 0x67,
+ vgt_perf_VGT_SPI_LSWAVE_SEND = 0x68,
+ vgt_perf_VGT_SPI_HSVERT_VALID = 0x69,
+ vgt_perf_VGT_SPI_HSVERT_EOV = 0x6a,
+ vgt_perf_VGT_SPI_HSVERT_STALLED = 0x6b,
+ vgt_perf_VGT_SPI_HSVERT_STARVED_BUSY = 0x6c,
+ vgt_perf_VGT_SPI_HSVERT_STARVED_IDLE = 0x6d,
+ vgt_perf_VGT_SPI_HSVERT_STATIC = 0x6e,
+ vgt_perf_VGT_SPI_HSWAVE_EVENT_WINDOW_ACTIVE = 0x6f,
+ vgt_perf_VGT_SPI_HSWAVE_IS_EVENT = 0x70,
+ vgt_perf_VGT_SPI_HSWAVE_SEND = 0x71,
+ vgt_perf_ds_prims = 0x72,
+ vgt_perf_ls_thread_groups = 0x73,
+ vgt_perf_hs_thread_groups = 0x74,
+ vgt_perf_es_thread_groups = 0x75,
+ vgt_perf_vs_thread_groups = 0x76,
+ vgt_perf_ls_done_latency = 0x77,
+ vgt_perf_hs_done_latency = 0x78,
+ vgt_perf_es_done_latency = 0x79,
+ vgt_perf_gs_done_latency = 0x7a,
+ vgt_perf_vgt_hs_busy = 0x7b,
+ vgt_perf_vgt_te11_busy = 0x7c,
+ vgt_perf_ls_flush = 0x7d,
+ vgt_perf_hs_flush = 0x7e,
+ vgt_perf_es_flush = 0x7f,
+ vgt_perf_vgt_pa_clipp_eopg = 0x80,
+ vgt_perf_ls_done = 0x81,
+ vgt_perf_hs_done = 0x82,
+ vgt_perf_es_done = 0x83,
+ vgt_perf_gs_done = 0x84,
+ vgt_perf_vsfetch_done = 0x85,
+ vgt_perf_gs_done_received = 0x86,
+ vgt_perf_es_ring_high_water_mark = 0x87,
+ vgt_perf_gs_ring_high_water_mark = 0x88,
+ vgt_perf_vs_table_high_water_mark = 0x89,
+ vgt_perf_hs_tgs_active_high_water_mark = 0x8a,
+ vgt_perf_pa_clipp_dealloc = 0x8b,
+ vgt_perf_cut_mem_flush_stalled = 0x8c,
+ vgt_perf_vsvert_work_received = 0x8d,
+ vgt_perf_vgt_pa_clipp_starved_after_work = 0x8e,
+ vgt_perf_te11_con_starved_after_work = 0x8f,
+ vgt_perf_hs_waiting_on_ls_done_stall = 0x90,
+ vgt_spi_vsvert_valid = 0x91,
+} VGT_PERFCOUNT_SELECT;
+typedef enum IA_PERFCOUNT_SELECT {
+ ia_perf_GRP_INPUT_EVENT_WINDOW_ACTIVE = 0x0,
+ ia_perf_dma_data_fifo_full = 0x1,
+ ia_perf_RESERVED1 = 0x2,
+ ia_perf_RESERVED2 = 0x3,
+ ia_perf_RESERVED3 = 0x4,
+ ia_perf_RESERVED4 = 0x5,
+ ia_perf_RESERVED5 = 0x6,
+ ia_perf_MC_LAT_BIN_0 = 0x7,
+ ia_perf_MC_LAT_BIN_1 = 0x8,
+ ia_perf_MC_LAT_BIN_2 = 0x9,
+ ia_perf_MC_LAT_BIN_3 = 0xa,
+ ia_perf_MC_LAT_BIN_4 = 0xb,
+ ia_perf_MC_LAT_BIN_5 = 0xc,
+ ia_perf_MC_LAT_BIN_6 = 0xd,
+ ia_perf_MC_LAT_BIN_7 = 0xe,
+ ia_perf_ia_busy = 0xf,
+ ia_perf_ia_sclk_reg_vld_event = 0x10,
+ ia_perf_RESERVED6 = 0x11,
+ ia_perf_ia_sclk_core_vld_event = 0x12,
+ ia_perf_RESERVED7 = 0x13,
+ ia_perf_ia_dma_return = 0x14,
+ ia_perf_ia_stalled = 0x15,
+ ia_perf_shift_starved_pipe0_event = 0x16,
+ ia_perf_shift_starved_pipe1_event = 0x17,
+} IA_PERFCOUNT_SELECT;
+typedef enum WD_PERFCOUNT_SELECT {
+ wd_perf_RBIU_FIFOS_EVENT_WINDOW_ACTIVE = 0x0,
+ wd_perf_RBIU_DR_FIFO_STARVED = 0x1,
+ wd_perf_RBIU_DR_FIFO_STALLED = 0x2,
+ wd_perf_RBIU_DI_FIFO_STARVED = 0x3,
+ wd_perf_RBIU_DI_FIFO_STALLED = 0x4,
+ wd_perf_wd_busy = 0x5,
+ wd_perf_wd_sclk_reg_vld_event = 0x6,
+ wd_perf_wd_sclk_input_vld_event = 0x7,
+ wd_perf_wd_sclk_core_vld_event = 0x8,
+ wd_perf_wd_stalled = 0x9,
+ wd_perf_inside_tf_bin_0 = 0xa,
+ wd_perf_inside_tf_bin_1 = 0xb,
+ wd_perf_inside_tf_bin_2 = 0xc,
+ wd_perf_inside_tf_bin_3 = 0xd,
+ wd_perf_inside_tf_bin_4 = 0xe,
+ wd_perf_inside_tf_bin_5 = 0xf,
+ wd_perf_inside_tf_bin_6 = 0x10,
+ wd_perf_inside_tf_bin_7 = 0x11,
+ wd_perf_inside_tf_bin_8 = 0x12,
+ wd_perf_tfreq_lat_bin_0 = 0x13,
+ wd_perf_tfreq_lat_bin_1 = 0x14,
+ wd_perf_tfreq_lat_bin_2 = 0x15,
+ wd_perf_tfreq_lat_bin_3 = 0x16,
+ wd_perf_tfreq_lat_bin_4 = 0x17,
+ wd_perf_tfreq_lat_bin_5 = 0x18,
+ wd_perf_tfreq_lat_bin_6 = 0x19,
+ wd_perf_tfreq_lat_bin_7 = 0x1a,
+ wd_starved_on_hs_done = 0x1b,
+ wd_perf_se0_hs_done_latency = 0x1c,
+ wd_perf_se1_hs_done_latency = 0x1d,
+ wd_perf_se2_hs_done_latency = 0x1e,
+ wd_perf_se3_hs_done_latency = 0x1f,
+ wd_perf_hs_done_se0 = 0x20,
+ wd_perf_hs_done_se1 = 0x21,
+ wd_perf_hs_done_se2 = 0x22,
+ wd_perf_hs_done_se3 = 0x23,
+ wd_perf_null_patches = 0x24,
+} WD_PERFCOUNT_SELECT;
+typedef enum WD_IA_DRAW_TYPE {
+ WD_IA_DRAW_TYPE_DI_MM0 = 0x0,
+ WD_IA_DRAW_TYPE_DI_MM1 = 0x1,
+ WD_IA_DRAW_TYPE_EVENT_INIT = 0x2,
+ WD_IA_DRAW_TYPE_EVENT_ADDR = 0x3,
+ WD_IA_DRAW_TYPE_MIN_INDX = 0x4,
+ WD_IA_DRAW_TYPE_MAX_INDX = 0x5,
+ WD_IA_DRAW_TYPE_INDX_OFF = 0x6,
+ WD_IA_DRAW_TYPE_IMM_DATA = 0x7,
+} WD_IA_DRAW_TYPE;
+typedef enum WD_IA_DRAW_SOURCE {
+ WD_IA_DRAW_SOURCE_DMA = 0x0,
+ WD_IA_DRAW_SOURCE_IMMD = 0x1,
+ WD_IA_DRAW_SOURCE_AUTO = 0x2,
+ WD_IA_DRAW_SOURCE_OPAQ = 0x3,
+} WD_IA_DRAW_SOURCE;
+#define GSTHREADID_SIZE 0x2
+typedef enum DebugBlockId {
+ DBG_BLOCK_ID_RESERVED = 0x0,
+ DBG_BLOCK_ID_DBG = 0x1,
+ DBG_BLOCK_ID_VMC = 0x2,
+ DBG_BLOCK_ID_PDMA = 0x3,
+ DBG_BLOCK_ID_CG = 0x4,
+ DBG_BLOCK_ID_SRBM = 0x5,
+ DBG_BLOCK_ID_GRBM = 0x6,
+ DBG_BLOCK_ID_RLC = 0x7,
+ DBG_BLOCK_ID_CSC = 0x8,
+ DBG_BLOCK_ID_SEM = 0x9,
+ DBG_BLOCK_ID_IH = 0xa,
+ DBG_BLOCK_ID_SC = 0xb,
+ DBG_BLOCK_ID_SQ = 0xc,
+ DBG_BLOCK_ID_UVDU = 0xd,
+ DBG_BLOCK_ID_SQA = 0xe,
+ DBG_BLOCK_ID_SDMA0 = 0xf,
+ DBG_BLOCK_ID_SDMA1 = 0x10,
+ DBG_BLOCK_ID_SPIM = 0x11,
+ DBG_BLOCK_ID_GDS = 0x12,
+ DBG_BLOCK_ID_VC0 = 0x13,
+ DBG_BLOCK_ID_VC1 = 0x14,
+ DBG_BLOCK_ID_PA0 = 0x15,
+ DBG_BLOCK_ID_PA1 = 0x16,
+ DBG_BLOCK_ID_CP0 = 0x17,
+ DBG_BLOCK_ID_CP1 = 0x18,
+ DBG_BLOCK_ID_CP2 = 0x19,
+ DBG_BLOCK_ID_XBR = 0x1a,
+ DBG_BLOCK_ID_UVDM = 0x1b,
+ DBG_BLOCK_ID_VGT0 = 0x1c,
+ DBG_BLOCK_ID_VGT1 = 0x1d,
+ DBG_BLOCK_ID_IA = 0x1e,
+ DBG_BLOCK_ID_SXM0 = 0x1f,
+ DBG_BLOCK_ID_SXM1 = 0x20,
+ DBG_BLOCK_ID_SCT0 = 0x21,
+ DBG_BLOCK_ID_SCT1 = 0x22,
+ DBG_BLOCK_ID_SPM0 = 0x23,
+ DBG_BLOCK_ID_SPM1 = 0x24,
+ DBG_BLOCK_ID_UNUSED0 = 0x25,
+ DBG_BLOCK_ID_UNUSED1 = 0x26,
+ DBG_BLOCK_ID_TCAA = 0x27,
+ DBG_BLOCK_ID_TCAB = 0x28,
+ DBG_BLOCK_ID_TCCA = 0x29,
+ DBG_BLOCK_ID_TCCB = 0x2a,
+ DBG_BLOCK_ID_MCC0 = 0x2b,
+ DBG_BLOCK_ID_MCC1 = 0x2c,
+ DBG_BLOCK_ID_MCC2 = 0x2d,
+ DBG_BLOCK_ID_MCC3 = 0x2e,
+ DBG_BLOCK_ID_SXS0 = 0x2f,
+ DBG_BLOCK_ID_SXS1 = 0x30,
+ DBG_BLOCK_ID_SXS2 = 0x31,
+ DBG_BLOCK_ID_SXS3 = 0x32,
+ DBG_BLOCK_ID_SXS4 = 0x33,
+ DBG_BLOCK_ID_SXS5 = 0x34,
+ DBG_BLOCK_ID_SXS6 = 0x35,
+ DBG_BLOCK_ID_SXS7 = 0x36,
+ DBG_BLOCK_ID_SXS8 = 0x37,
+ DBG_BLOCK_ID_SXS9 = 0x38,
+ DBG_BLOCK_ID_BCI0 = 0x39,
+ DBG_BLOCK_ID_BCI1 = 0x3a,
+ DBG_BLOCK_ID_BCI2 = 0x3b,
+ DBG_BLOCK_ID_BCI3 = 0x3c,
+ DBG_BLOCK_ID_MCB = 0x3d,
+ DBG_BLOCK_ID_UNUSED6 = 0x3e,
+ DBG_BLOCK_ID_SQA00 = 0x3f,
+ DBG_BLOCK_ID_SQA01 = 0x40,
+ DBG_BLOCK_ID_SQA02 = 0x41,
+ DBG_BLOCK_ID_SQA10 = 0x42,
+ DBG_BLOCK_ID_SQA11 = 0x43,
+ DBG_BLOCK_ID_SQA12 = 0x44,
+ DBG_BLOCK_ID_UNUSED7 = 0x45,
+ DBG_BLOCK_ID_UNUSED8 = 0x46,
+ DBG_BLOCK_ID_SQB00 = 0x47,
+ DBG_BLOCK_ID_SQB01 = 0x48,
+ DBG_BLOCK_ID_SQB10 = 0x49,
+ DBG_BLOCK_ID_SQB11 = 0x4a,
+ DBG_BLOCK_ID_SQ00 = 0x4b,
+ DBG_BLOCK_ID_SQ01 = 0x4c,
+ DBG_BLOCK_ID_SQ10 = 0x4d,
+ DBG_BLOCK_ID_SQ11 = 0x4e,
+ DBG_BLOCK_ID_CB00 = 0x4f,
+ DBG_BLOCK_ID_CB01 = 0x50,
+ DBG_BLOCK_ID_CB02 = 0x51,
+ DBG_BLOCK_ID_CB03 = 0x52,
+ DBG_BLOCK_ID_CB04 = 0x53,
+ DBG_BLOCK_ID_UNUSED9 = 0x54,
+ DBG_BLOCK_ID_UNUSED10 = 0x55,
+ DBG_BLOCK_ID_UNUSED11 = 0x56,
+ DBG_BLOCK_ID_CB10 = 0x57,
+ DBG_BLOCK_ID_CB11 = 0x58,
+ DBG_BLOCK_ID_CB12 = 0x59,
+ DBG_BLOCK_ID_CB13 = 0x5a,
+ DBG_BLOCK_ID_CB14 = 0x5b,
+ DBG_BLOCK_ID_UNUSED12 = 0x5c,
+ DBG_BLOCK_ID_UNUSED13 = 0x5d,
+ DBG_BLOCK_ID_UNUSED14 = 0x5e,
+ DBG_BLOCK_ID_TCP0 = 0x5f,
+ DBG_BLOCK_ID_TCP1 = 0x60,
+ DBG_BLOCK_ID_TCP2 = 0x61,
+ DBG_BLOCK_ID_TCP3 = 0x62,
+ DBG_BLOCK_ID_TCP4 = 0x63,
+ DBG_BLOCK_ID_TCP5 = 0x64,
+ DBG_BLOCK_ID_TCP6 = 0x65,
+ DBG_BLOCK_ID_TCP7 = 0x66,
+ DBG_BLOCK_ID_TCP8 = 0x67,
+ DBG_BLOCK_ID_TCP9 = 0x68,
+ DBG_BLOCK_ID_TCP10 = 0x69,
+ DBG_BLOCK_ID_TCP11 = 0x6a,
+ DBG_BLOCK_ID_TCP12 = 0x6b,
+ DBG_BLOCK_ID_TCP13 = 0x6c,
+ DBG_BLOCK_ID_TCP14 = 0x6d,
+ DBG_BLOCK_ID_TCP15 = 0x6e,
+ DBG_BLOCK_ID_TCP16 = 0x6f,
+ DBG_BLOCK_ID_TCP17 = 0x70,
+ DBG_BLOCK_ID_TCP18 = 0x71,
+ DBG_BLOCK_ID_TCP19 = 0x72,
+ DBG_BLOCK_ID_TCP20 = 0x73,
+ DBG_BLOCK_ID_TCP21 = 0x74,
+ DBG_BLOCK_ID_TCP22 = 0x75,
+ DBG_BLOCK_ID_TCP23 = 0x76,
+ DBG_BLOCK_ID_TCP_RESERVED0 = 0x77,
+ DBG_BLOCK_ID_TCP_RESERVED1 = 0x78,
+ DBG_BLOCK_ID_TCP_RESERVED2 = 0x79,
+ DBG_BLOCK_ID_TCP_RESERVED3 = 0x7a,
+ DBG_BLOCK_ID_TCP_RESERVED4 = 0x7b,
+ DBG_BLOCK_ID_TCP_RESERVED5 = 0x7c,
+ DBG_BLOCK_ID_TCP_RESERVED6 = 0x7d,
+ DBG_BLOCK_ID_TCP_RESERVED7 = 0x7e,
+ DBG_BLOCK_ID_DB00 = 0x7f,
+ DBG_BLOCK_ID_DB01 = 0x80,
+ DBG_BLOCK_ID_DB02 = 0x81,
+ DBG_BLOCK_ID_DB03 = 0x82,
+ DBG_BLOCK_ID_DB04 = 0x83,
+ DBG_BLOCK_ID_UNUSED15 = 0x84,
+ DBG_BLOCK_ID_UNUSED16 = 0x85,
+ DBG_BLOCK_ID_UNUSED17 = 0x86,
+ DBG_BLOCK_ID_DB10 = 0x87,
+ DBG_BLOCK_ID_DB11 = 0x88,
+ DBG_BLOCK_ID_DB12 = 0x89,
+ DBG_BLOCK_ID_DB13 = 0x8a,
+ DBG_BLOCK_ID_DB14 = 0x8b,
+ DBG_BLOCK_ID_UNUSED18 = 0x8c,
+ DBG_BLOCK_ID_UNUSED19 = 0x8d,
+ DBG_BLOCK_ID_UNUSED20 = 0x8e,
+ DBG_BLOCK_ID_TCC0 = 0x8f,
+ DBG_BLOCK_ID_TCC1 = 0x90,
+ DBG_BLOCK_ID_TCC2 = 0x91,
+ DBG_BLOCK_ID_TCC3 = 0x92,
+ DBG_BLOCK_ID_TCC4 = 0x93,
+ DBG_BLOCK_ID_TCC5 = 0x94,
+ DBG_BLOCK_ID_TCC6 = 0x95,
+ DBG_BLOCK_ID_TCC7 = 0x96,
+ DBG_BLOCK_ID_SPS00 = 0x97,
+ DBG_BLOCK_ID_SPS01 = 0x98,
+ DBG_BLOCK_ID_SPS02 = 0x99,
+ DBG_BLOCK_ID_SPS10 = 0x9a,
+ DBG_BLOCK_ID_SPS11 = 0x9b,
+ DBG_BLOCK_ID_SPS12 = 0x9c,
+ DBG_BLOCK_ID_UNUSED21 = 0x9d,
+ DBG_BLOCK_ID_UNUSED22 = 0x9e,
+ DBG_BLOCK_ID_TA00 = 0x9f,
+ DBG_BLOCK_ID_TA01 = 0xa0,
+ DBG_BLOCK_ID_TA02 = 0xa1,
+ DBG_BLOCK_ID_TA03 = 0xa2,
+ DBG_BLOCK_ID_TA04 = 0xa3,
+ DBG_BLOCK_ID_TA05 = 0xa4,
+ DBG_BLOCK_ID_TA06 = 0xa5,
+ DBG_BLOCK_ID_TA07 = 0xa6,
+ DBG_BLOCK_ID_TA08 = 0xa7,
+ DBG_BLOCK_ID_TA09 = 0xa8,
+ DBG_BLOCK_ID_TA0A = 0xa9,
+ DBG_BLOCK_ID_TA0B = 0xaa,
+ DBG_BLOCK_ID_UNUSED23 = 0xab,
+ DBG_BLOCK_ID_UNUSED24 = 0xac,
+ DBG_BLOCK_ID_UNUSED25 = 0xad,
+ DBG_BLOCK_ID_UNUSED26 = 0xae,
+ DBG_BLOCK_ID_TA10 = 0xaf,
+ DBG_BLOCK_ID_TA11 = 0xb0,
+ DBG_BLOCK_ID_TA12 = 0xb1,
+ DBG_BLOCK_ID_TA13 = 0xb2,
+ DBG_BLOCK_ID_TA14 = 0xb3,
+ DBG_BLOCK_ID_TA15 = 0xb4,
+ DBG_BLOCK_ID_TA16 = 0xb5,
+ DBG_BLOCK_ID_TA17 = 0xb6,
+ DBG_BLOCK_ID_TA18 = 0xb7,
+ DBG_BLOCK_ID_TA19 = 0xb8,
+ DBG_BLOCK_ID_TA1A = 0xb9,
+ DBG_BLOCK_ID_TA1B = 0xba,
+ DBG_BLOCK_ID_UNUSED27 = 0xbb,
+ DBG_BLOCK_ID_UNUSED28 = 0xbc,
+ DBG_BLOCK_ID_UNUSED29 = 0xbd,
+ DBG_BLOCK_ID_UNUSED30 = 0xbe,
+ DBG_BLOCK_ID_TD00 = 0xbf,
+ DBG_BLOCK_ID_TD01 = 0xc0,
+ DBG_BLOCK_ID_TD02 = 0xc1,
+ DBG_BLOCK_ID_TD03 = 0xc2,
+ DBG_BLOCK_ID_TD04 = 0xc3,
+ DBG_BLOCK_ID_TD05 = 0xc4,
+ DBG_BLOCK_ID_TD06 = 0xc5,
+ DBG_BLOCK_ID_TD07 = 0xc6,
+ DBG_BLOCK_ID_TD08 = 0xc7,
+ DBG_BLOCK_ID_TD09 = 0xc8,
+ DBG_BLOCK_ID_TD0A = 0xc9,
+ DBG_BLOCK_ID_TD0B = 0xca,
+ DBG_BLOCK_ID_UNUSED31 = 0xcb,
+ DBG_BLOCK_ID_UNUSED32 = 0xcc,
+ DBG_BLOCK_ID_UNUSED33 = 0xcd,
+ DBG_BLOCK_ID_UNUSED34 = 0xce,
+ DBG_BLOCK_ID_TD10 = 0xcf,
+ DBG_BLOCK_ID_TD11 = 0xd0,
+ DBG_BLOCK_ID_TD12 = 0xd1,
+ DBG_BLOCK_ID_TD13 = 0xd2,
+ DBG_BLOCK_ID_TD14 = 0xd3,
+ DBG_BLOCK_ID_TD15 = 0xd4,
+ DBG_BLOCK_ID_TD16 = 0xd5,
+ DBG_BLOCK_ID_TD17 = 0xd6,
+ DBG_BLOCK_ID_TD18 = 0xd7,
+ DBG_BLOCK_ID_TD19 = 0xd8,
+ DBG_BLOCK_ID_TD1A = 0xd9,
+ DBG_BLOCK_ID_TD1B = 0xda,
+ DBG_BLOCK_ID_UNUSED35 = 0xdb,
+ DBG_BLOCK_ID_UNUSED36 = 0xdc,
+ DBG_BLOCK_ID_UNUSED37 = 0xdd,
+ DBG_BLOCK_ID_UNUSED38 = 0xde,
+ DBG_BLOCK_ID_LDS00 = 0xdf,
+ DBG_BLOCK_ID_LDS01 = 0xe0,
+ DBG_BLOCK_ID_LDS02 = 0xe1,
+ DBG_BLOCK_ID_LDS03 = 0xe2,
+ DBG_BLOCK_ID_LDS04 = 0xe3,
+ DBG_BLOCK_ID_LDS05 = 0xe4,
+ DBG_BLOCK_ID_LDS06 = 0xe5,
+ DBG_BLOCK_ID_LDS07 = 0xe6,
+ DBG_BLOCK_ID_LDS08 = 0xe7,
+ DBG_BLOCK_ID_LDS09 = 0xe8,
+ DBG_BLOCK_ID_LDS0A = 0xe9,
+ DBG_BLOCK_ID_LDS0B = 0xea,
+ DBG_BLOCK_ID_UNUSED39 = 0xeb,
+ DBG_BLOCK_ID_UNUSED40 = 0xec,
+ DBG_BLOCK_ID_UNUSED41 = 0xed,
+ DBG_BLOCK_ID_UNUSED42 = 0xee,
+ DBG_BLOCK_ID_LDS10 = 0xef,
+ DBG_BLOCK_ID_LDS11 = 0xf0,
+ DBG_BLOCK_ID_LDS12 = 0xf1,
+ DBG_BLOCK_ID_LDS13 = 0xf2,
+ DBG_BLOCK_ID_LDS14 = 0xf3,
+ DBG_BLOCK_ID_LDS15 = 0xf4,
+ DBG_BLOCK_ID_LDS16 = 0xf5,
+ DBG_BLOCK_ID_LDS17 = 0xf6,
+ DBG_BLOCK_ID_LDS18 = 0xf7,
+ DBG_BLOCK_ID_LDS19 = 0xf8,
+ DBG_BLOCK_ID_LDS1A = 0xf9,
+ DBG_BLOCK_ID_LDS1B = 0xfa,
+ DBG_BLOCK_ID_UNUSED43 = 0xfb,
+ DBG_BLOCK_ID_UNUSED44 = 0xfc,
+ DBG_BLOCK_ID_UNUSED45 = 0xfd,
+ DBG_BLOCK_ID_UNUSED46 = 0xfe,
+} DebugBlockId;
+typedef enum DebugBlockId_BY2 {
+ DBG_BLOCK_ID_RESERVED_BY2 = 0x0,
+ DBG_BLOCK_ID_VMC_BY2 = 0x1,
+ DBG_BLOCK_ID_UNUSED0_BY2 = 0x2,
+ DBG_BLOCK_ID_GRBM_BY2 = 0x3,
+ DBG_BLOCK_ID_CSC_BY2 = 0x4,
+ DBG_BLOCK_ID_IH_BY2 = 0x5,
+ DBG_BLOCK_ID_SQ_BY2 = 0x6,
+ DBG_BLOCK_ID_UVD_BY2 = 0x7,
+ DBG_BLOCK_ID_SDMA0_BY2 = 0x8,
+ DBG_BLOCK_ID_SPIM_BY2 = 0x9,
+ DBG_BLOCK_ID_VC0_BY2 = 0xa,
+ DBG_BLOCK_ID_PA_BY2 = 0xb,
+ DBG_BLOCK_ID_CP0_BY2 = 0xc,
+ DBG_BLOCK_ID_CP2_BY2 = 0xd,
+ DBG_BLOCK_ID_PC0_BY2 = 0xe,
+ DBG_BLOCK_ID_BCI0_BY2 = 0xf,
+ DBG_BLOCK_ID_SXM0_BY2 = 0x10,
+ DBG_BLOCK_ID_SCT0_BY2 = 0x11,
+ DBG_BLOCK_ID_SPM0_BY2 = 0x12,
+ DBG_BLOCK_ID_BCI2_BY2 = 0x13,
+ DBG_BLOCK_ID_TCA_BY2 = 0x14,
+ DBG_BLOCK_ID_TCCA_BY2 = 0x15,
+ DBG_BLOCK_ID_MCC_BY2 = 0x16,
+ DBG_BLOCK_ID_MCC2_BY2 = 0x17,
+ DBG_BLOCK_ID_MCD_BY2 = 0x18,
+ DBG_BLOCK_ID_MCD2_BY2 = 0x19,
+ DBG_BLOCK_ID_MCD4_BY2 = 0x1a,
+ DBG_BLOCK_ID_MCB_BY2 = 0x1b,
+ DBG_BLOCK_ID_SQA_BY2 = 0x1c,
+ DBG_BLOCK_ID_SQA02_BY2 = 0x1d,
+ DBG_BLOCK_ID_SQA11_BY2 = 0x1e,
+ DBG_BLOCK_ID_UNUSED8_BY2 = 0x1f,
+ DBG_BLOCK_ID_SQB_BY2 = 0x20,
+ DBG_BLOCK_ID_SQB10_BY2 = 0x21,
+ DBG_BLOCK_ID_UNUSED10_BY2 = 0x22,
+ DBG_BLOCK_ID_UNUSED12_BY2 = 0x23,
+ DBG_BLOCK_ID_CB_BY2 = 0x24,
+ DBG_BLOCK_ID_CB02_BY2 = 0x25,
+ DBG_BLOCK_ID_CB10_BY2 = 0x26,
+ DBG_BLOCK_ID_CB12_BY2 = 0x27,
+ DBG_BLOCK_ID_SXS_BY2 = 0x28,
+ DBG_BLOCK_ID_SXS2_BY2 = 0x29,
+ DBG_BLOCK_ID_SXS4_BY2 = 0x2a,
+ DBG_BLOCK_ID_SXS6_BY2 = 0x2b,
+ DBG_BLOCK_ID_DB_BY2 = 0x2c,
+ DBG_BLOCK_ID_DB02_BY2 = 0x2d,
+ DBG_BLOCK_ID_DB10_BY2 = 0x2e,
+ DBG_BLOCK_ID_DB12_BY2 = 0x2f,
+ DBG_BLOCK_ID_TCP_BY2 = 0x30,
+ DBG_BLOCK_ID_TCP2_BY2 = 0x31,
+ DBG_BLOCK_ID_TCP4_BY2 = 0x32,
+ DBG_BLOCK_ID_TCP6_BY2 = 0x33,
+ DBG_BLOCK_ID_TCP8_BY2 = 0x34,
+ DBG_BLOCK_ID_TCP10_BY2 = 0x35,
+ DBG_BLOCK_ID_TCP12_BY2 = 0x36,
+ DBG_BLOCK_ID_TCP14_BY2 = 0x37,
+ DBG_BLOCK_ID_TCP16_BY2 = 0x38,
+ DBG_BLOCK_ID_TCP18_BY2 = 0x39,
+ DBG_BLOCK_ID_TCP20_BY2 = 0x3a,
+ DBG_BLOCK_ID_TCP22_BY2 = 0x3b,
+ DBG_BLOCK_ID_TCP_RESERVED0_BY2 = 0x3c,
+ DBG_BLOCK_ID_TCP_RESERVED2_BY2 = 0x3d,
+ DBG_BLOCK_ID_TCP_RESERVED4_BY2 = 0x3e,
+ DBG_BLOCK_ID_TCP_RESERVED6_BY2 = 0x3f,
+ DBG_BLOCK_ID_TCC_BY2 = 0x40,
+ DBG_BLOCK_ID_TCC2_BY2 = 0x41,
+ DBG_BLOCK_ID_TCC4_BY2 = 0x42,
+ DBG_BLOCK_ID_TCC6_BY2 = 0x43,
+ DBG_BLOCK_ID_SPS_BY2 = 0x44,
+ DBG_BLOCK_ID_SPS02_BY2 = 0x45,
+ DBG_BLOCK_ID_SPS11_BY2 = 0x46,
+ DBG_BLOCK_ID_UNUSED14_BY2 = 0x47,
+ DBG_BLOCK_ID_TA_BY2 = 0x48,
+ DBG_BLOCK_ID_TA02_BY2 = 0x49,
+ DBG_BLOCK_ID_TA04_BY2 = 0x4a,
+ DBG_BLOCK_ID_TA06_BY2 = 0x4b,
+ DBG_BLOCK_ID_TA08_BY2 = 0x4c,
+ DBG_BLOCK_ID_TA0A_BY2 = 0x4d,
+ DBG_BLOCK_ID_UNUSED20_BY2 = 0x4e,
+ DBG_BLOCK_ID_UNUSED22_BY2 = 0x4f,
+ DBG_BLOCK_ID_TA10_BY2 = 0x50,
+ DBG_BLOCK_ID_TA12_BY2 = 0x51,
+ DBG_BLOCK_ID_TA14_BY2 = 0x52,
+ DBG_BLOCK_ID_TA16_BY2 = 0x53,
+ DBG_BLOCK_ID_TA18_BY2 = 0x54,
+ DBG_BLOCK_ID_TA1A_BY2 = 0x55,
+ DBG_BLOCK_ID_UNUSED24_BY2 = 0x56,
+ DBG_BLOCK_ID_UNUSED26_BY2 = 0x57,
+ DBG_BLOCK_ID_TD_BY2 = 0x58,
+ DBG_BLOCK_ID_TD02_BY2 = 0x59,
+ DBG_BLOCK_ID_TD04_BY2 = 0x5a,
+ DBG_BLOCK_ID_TD06_BY2 = 0x5b,
+ DBG_BLOCK_ID_TD08_BY2 = 0x5c,
+ DBG_BLOCK_ID_TD0A_BY2 = 0x5d,
+ DBG_BLOCK_ID_UNUSED28_BY2 = 0x5e,
+ DBG_BLOCK_ID_UNUSED30_BY2 = 0x5f,
+ DBG_BLOCK_ID_TD10_BY2 = 0x60,
+ DBG_BLOCK_ID_TD12_BY2 = 0x61,
+ DBG_BLOCK_ID_TD14_BY2 = 0x62,
+ DBG_BLOCK_ID_TD16_BY2 = 0x63,
+ DBG_BLOCK_ID_TD18_BY2 = 0x64,
+ DBG_BLOCK_ID_TD1A_BY2 = 0x65,
+ DBG_BLOCK_ID_UNUSED32_BY2 = 0x66,
+ DBG_BLOCK_ID_UNUSED34_BY2 = 0x67,
+ DBG_BLOCK_ID_LDS_BY2 = 0x68,
+ DBG_BLOCK_ID_LDS02_BY2 = 0x69,
+ DBG_BLOCK_ID_LDS04_BY2 = 0x6a,
+ DBG_BLOCK_ID_LDS06_BY2 = 0x6b,
+ DBG_BLOCK_ID_LDS08_BY2 = 0x6c,
+ DBG_BLOCK_ID_LDS0A_BY2 = 0x6d,
+ DBG_BLOCK_ID_UNUSED36_BY2 = 0x6e,
+ DBG_BLOCK_ID_UNUSED38_BY2 = 0x6f,
+ DBG_BLOCK_ID_LDS10_BY2 = 0x70,
+ DBG_BLOCK_ID_LDS12_BY2 = 0x71,
+ DBG_BLOCK_ID_LDS14_BY2 = 0x72,
+ DBG_BLOCK_ID_LDS16_BY2 = 0x73,
+ DBG_BLOCK_ID_LDS18_BY2 = 0x74,
+ DBG_BLOCK_ID_LDS1A_BY2 = 0x75,
+ DBG_BLOCK_ID_UNUSED40_BY2 = 0x76,
+ DBG_BLOCK_ID_UNUSED42_BY2 = 0x77,
+} DebugBlockId_BY2;
+typedef enum DebugBlockId_BY4 {
+ DBG_BLOCK_ID_RESERVED_BY4 = 0x0,
+ DBG_BLOCK_ID_UNUSED0_BY4 = 0x1,
+ DBG_BLOCK_ID_CSC_BY4 = 0x2,
+ DBG_BLOCK_ID_SQ_BY4 = 0x3,
+ DBG_BLOCK_ID_SDMA0_BY4 = 0x4,
+ DBG_BLOCK_ID_VC0_BY4 = 0x5,
+ DBG_BLOCK_ID_CP0_BY4 = 0x6,
+ DBG_BLOCK_ID_UNUSED1_BY4 = 0x7,
+ DBG_BLOCK_ID_SXM0_BY4 = 0x8,
+ DBG_BLOCK_ID_SPM0_BY4 = 0x9,
+ DBG_BLOCK_ID_TCAA_BY4 = 0xa,
+ DBG_BLOCK_ID_MCC_BY4 = 0xb,
+ DBG_BLOCK_ID_MCD_BY4 = 0xc,
+ DBG_BLOCK_ID_MCD4_BY4 = 0xd,
+ DBG_BLOCK_ID_SQA_BY4 = 0xe,
+ DBG_BLOCK_ID_SQA11_BY4 = 0xf,
+ DBG_BLOCK_ID_SQB_BY4 = 0x10,
+ DBG_BLOCK_ID_UNUSED10_BY4 = 0x11,
+ DBG_BLOCK_ID_CB_BY4 = 0x12,
+ DBG_BLOCK_ID_CB10_BY4 = 0x13,
+ DBG_BLOCK_ID_SXS_BY4 = 0x14,
+ DBG_BLOCK_ID_SXS4_BY4 = 0x15,
+ DBG_BLOCK_ID_DB_BY4 = 0x16,
+ DBG_BLOCK_ID_DB10_BY4 = 0x17,
+ DBG_BLOCK_ID_TCP_BY4 = 0x18,
+ DBG_BLOCK_ID_TCP4_BY4 = 0x19,
+ DBG_BLOCK_ID_TCP8_BY4 = 0x1a,
+ DBG_BLOCK_ID_TCP12_BY4 = 0x1b,
+ DBG_BLOCK_ID_TCP16_BY4 = 0x1c,
+ DBG_BLOCK_ID_TCP20_BY4 = 0x1d,
+ DBG_BLOCK_ID_TCP_RESERVED0_BY4 = 0x1e,
+ DBG_BLOCK_ID_TCP_RESERVED4_BY4 = 0x1f,
+ DBG_BLOCK_ID_TCC_BY4 = 0x20,
+ DBG_BLOCK_ID_TCC4_BY4 = 0x21,
+ DBG_BLOCK_ID_SPS_BY4 = 0x22,
+ DBG_BLOCK_ID_SPS11_BY4 = 0x23,
+ DBG_BLOCK_ID_TA_BY4 = 0x24,
+ DBG_BLOCK_ID_TA04_BY4 = 0x25,
+ DBG_BLOCK_ID_TA08_BY4 = 0x26,
+ DBG_BLOCK_ID_UNUSED20_BY4 = 0x27,
+ DBG_BLOCK_ID_TA10_BY4 = 0x28,
+ DBG_BLOCK_ID_TA14_BY4 = 0x29,
+ DBG_BLOCK_ID_TA18_BY4 = 0x2a,
+ DBG_BLOCK_ID_UNUSED24_BY4 = 0x2b,
+ DBG_BLOCK_ID_TD_BY4 = 0x2c,
+ DBG_BLOCK_ID_TD04_BY4 = 0x2d,
+ DBG_BLOCK_ID_TD08_BY4 = 0x2e,
+ DBG_BLOCK_ID_UNUSED28_BY4 = 0x2f,
+ DBG_BLOCK_ID_TD10_BY4 = 0x30,
+ DBG_BLOCK_ID_TD14_BY4 = 0x31,
+ DBG_BLOCK_ID_TD18_BY4 = 0x32,
+ DBG_BLOCK_ID_UNUSED32_BY4 = 0x33,
+ DBG_BLOCK_ID_LDS_BY4 = 0x34,
+ DBG_BLOCK_ID_LDS04_BY4 = 0x35,
+ DBG_BLOCK_ID_LDS08_BY4 = 0x36,
+ DBG_BLOCK_ID_UNUSED36_BY4 = 0x37,
+ DBG_BLOCK_ID_LDS10_BY4 = 0x38,
+ DBG_BLOCK_ID_LDS14_BY4 = 0x39,
+ DBG_BLOCK_ID_LDS18_BY4 = 0x3a,
+ DBG_BLOCK_ID_UNUSED40_BY4 = 0x3b,
+} DebugBlockId_BY4;
+typedef enum DebugBlockId_BY8 {
+ DBG_BLOCK_ID_RESERVED_BY8 = 0x0,
+ DBG_BLOCK_ID_CSC_BY8 = 0x1,
+ DBG_BLOCK_ID_SDMA0_BY8 = 0x2,
+ DBG_BLOCK_ID_CP0_BY8 = 0x3,
+ DBG_BLOCK_ID_SXM0_BY8 = 0x4,
+ DBG_BLOCK_ID_TCA_BY8 = 0x5,
+ DBG_BLOCK_ID_MCD_BY8 = 0x6,
+ DBG_BLOCK_ID_SQA_BY8 = 0x7,
+ DBG_BLOCK_ID_SQB_BY8 = 0x8,
+ DBG_BLOCK_ID_CB_BY8 = 0x9,
+ DBG_BLOCK_ID_SXS_BY8 = 0xa,
+ DBG_BLOCK_ID_DB_BY8 = 0xb,
+ DBG_BLOCK_ID_TCP_BY8 = 0xc,
+ DBG_BLOCK_ID_TCP8_BY8 = 0xd,
+ DBG_BLOCK_ID_TCP16_BY8 = 0xe,
+ DBG_BLOCK_ID_TCP_RESERVED0_BY8 = 0xf,
+ DBG_BLOCK_ID_TCC_BY8 = 0x10,
+ DBG_BLOCK_ID_SPS_BY8 = 0x11,
+ DBG_BLOCK_ID_TA_BY8 = 0x12,
+ DBG_BLOCK_ID_TA08_BY8 = 0x13,
+ DBG_BLOCK_ID_TA10_BY8 = 0x14,
+ DBG_BLOCK_ID_TA18_BY8 = 0x15,
+ DBG_BLOCK_ID_TD_BY8 = 0x16,
+ DBG_BLOCK_ID_TD08_BY8 = 0x17,
+ DBG_BLOCK_ID_TD10_BY8 = 0x18,
+ DBG_BLOCK_ID_TD18_BY8 = 0x19,
+ DBG_BLOCK_ID_LDS_BY8 = 0x1a,
+ DBG_BLOCK_ID_LDS08_BY8 = 0x1b,
+ DBG_BLOCK_ID_LDS10_BY8 = 0x1c,
+ DBG_BLOCK_ID_LDS18_BY8 = 0x1d,
+} DebugBlockId_BY8;
+typedef enum DebugBlockId_BY16 {
+ DBG_BLOCK_ID_RESERVED_BY16 = 0x0,
+ DBG_BLOCK_ID_SDMA0_BY16 = 0x1,
+ DBG_BLOCK_ID_SXM_BY16 = 0x2,
+ DBG_BLOCK_ID_MCD_BY16 = 0x3,
+ DBG_BLOCK_ID_SQB_BY16 = 0x4,
+ DBG_BLOCK_ID_SXS_BY16 = 0x5,
+ DBG_BLOCK_ID_TCP_BY16 = 0x6,
+ DBG_BLOCK_ID_TCP16_BY16 = 0x7,
+ DBG_BLOCK_ID_TCC_BY16 = 0x8,
+ DBG_BLOCK_ID_TA_BY16 = 0x9,
+ DBG_BLOCK_ID_TA10_BY16 = 0xa,
+ DBG_BLOCK_ID_TD_BY16 = 0xb,
+ DBG_BLOCK_ID_TD10_BY16 = 0xc,
+ DBG_BLOCK_ID_LDS_BY16 = 0xd,
+ DBG_BLOCK_ID_LDS10_BY16 = 0xe,
+} DebugBlockId_BY16;
+typedef enum SurfaceEndian {
+ ENDIAN_NONE = 0x0,
+ ENDIAN_8IN16 = 0x1,
+ ENDIAN_8IN32 = 0x2,
+ ENDIAN_8IN64 = 0x3,
+} SurfaceEndian;
+typedef enum ArrayMode {
+ ARRAY_LINEAR_GENERAL = 0x0,
+ ARRAY_LINEAR_ALIGNED = 0x1,
+ ARRAY_1D_TILED_THIN1 = 0x2,
+ ARRAY_1D_TILED_THICK = 0x3,
+ ARRAY_2D_TILED_THIN1 = 0x4,
+ ARRAY_PRT_TILED_THIN1 = 0x5,
+ ARRAY_PRT_2D_TILED_THIN1 = 0x6,
+ ARRAY_2D_TILED_THICK = 0x7,
+ ARRAY_2D_TILED_XTHICK = 0x8,
+ ARRAY_PRT_TILED_THICK = 0x9,
+ ARRAY_PRT_2D_TILED_THICK = 0xa,
+ ARRAY_PRT_3D_TILED_THIN1 = 0xb,
+ ARRAY_3D_TILED_THIN1 = 0xc,
+ ARRAY_3D_TILED_THICK = 0xd,
+ ARRAY_3D_TILED_XTHICK = 0xe,
+ ARRAY_PRT_3D_TILED_THICK = 0xf,
+} ArrayMode;
+typedef enum PipeTiling {
+ CONFIG_1_PIPE = 0x0,
+ CONFIG_2_PIPE = 0x1,
+ CONFIG_4_PIPE = 0x2,
+ CONFIG_8_PIPE = 0x3,
+} PipeTiling;
+typedef enum BankTiling {
+ CONFIG_4_BANK = 0x0,
+ CONFIG_8_BANK = 0x1,
+} BankTiling;
+typedef enum GroupInterleave {
+ CONFIG_256B_GROUP = 0x0,
+ CONFIG_512B_GROUP = 0x1,
+} GroupInterleave;
+typedef enum RowTiling {
+ CONFIG_1KB_ROW = 0x0,
+ CONFIG_2KB_ROW = 0x1,
+ CONFIG_4KB_ROW = 0x2,
+ CONFIG_8KB_ROW = 0x3,
+ CONFIG_1KB_ROW_OPT = 0x4,
+ CONFIG_2KB_ROW_OPT = 0x5,
+ CONFIG_4KB_ROW_OPT = 0x6,
+ CONFIG_8KB_ROW_OPT = 0x7,
+} RowTiling;
+typedef enum BankSwapBytes {
+ CONFIG_128B_SWAPS = 0x0,
+ CONFIG_256B_SWAPS = 0x1,
+ CONFIG_512B_SWAPS = 0x2,
+ CONFIG_1KB_SWAPS = 0x3,
+} BankSwapBytes;
+typedef enum SampleSplitBytes {
+ CONFIG_1KB_SPLIT = 0x0,
+ CONFIG_2KB_SPLIT = 0x1,
+ CONFIG_4KB_SPLIT = 0x2,
+ CONFIG_8KB_SPLIT = 0x3,
+} SampleSplitBytes;
+typedef enum NumPipes {
+ ADDR_CONFIG_1_PIPE = 0x0,
+ ADDR_CONFIG_2_PIPE = 0x1,
+ ADDR_CONFIG_4_PIPE = 0x2,
+ ADDR_CONFIG_8_PIPE = 0x3,
+} NumPipes;
+typedef enum PipeInterleaveSize {
+ ADDR_CONFIG_PIPE_INTERLEAVE_256B = 0x0,
+ ADDR_CONFIG_PIPE_INTERLEAVE_512B = 0x1,
+} PipeInterleaveSize;
+typedef enum BankInterleaveSize {
+ ADDR_CONFIG_BANK_INTERLEAVE_1 = 0x0,
+ ADDR_CONFIG_BANK_INTERLEAVE_2 = 0x1,
+ ADDR_CONFIG_BANK_INTERLEAVE_4 = 0x2,
+ ADDR_CONFIG_BANK_INTERLEAVE_8 = 0x3,
+} BankInterleaveSize;
+typedef enum NumShaderEngines {
+ ADDR_CONFIG_1_SHADER_ENGINE = 0x0,
+ ADDR_CONFIG_2_SHADER_ENGINE = 0x1,
+} NumShaderEngines;
+typedef enum ShaderEngineTileSize {
+ ADDR_CONFIG_SE_TILE_16 = 0x0,
+ ADDR_CONFIG_SE_TILE_32 = 0x1,
+} ShaderEngineTileSize;
+typedef enum NumGPUs {
+ ADDR_CONFIG_1_GPU = 0x0,
+ ADDR_CONFIG_2_GPU = 0x1,
+ ADDR_CONFIG_4_GPU = 0x2,
+} NumGPUs;
+typedef enum MultiGPUTileSize {
+ ADDR_CONFIG_GPU_TILE_16 = 0x0,
+ ADDR_CONFIG_GPU_TILE_32 = 0x1,
+ ADDR_CONFIG_GPU_TILE_64 = 0x2,
+ ADDR_CONFIG_GPU_TILE_128 = 0x3,
+} MultiGPUTileSize;
+typedef enum RowSize {
+ ADDR_CONFIG_1KB_ROW = 0x0,
+ ADDR_CONFIG_2KB_ROW = 0x1,
+ ADDR_CONFIG_4KB_ROW = 0x2,
+} RowSize;
+typedef enum NumLowerPipes {
+ ADDR_CONFIG_1_LOWER_PIPES = 0x0,
+ ADDR_CONFIG_2_LOWER_PIPES = 0x1,
+} NumLowerPipes;
+typedef enum ColorTransform {
+ DCC_CT_AUTO = 0x0,
+ DCC_CT_NONE = 0x1,
+ ABGR_TO_A_BG_G_RB = 0x2,
+ BGRA_TO_BG_G_RB_A = 0x3,
+} ColorTransform;
+typedef enum CompareRef {
+ REF_NEVER = 0x0,
+ REF_LESS = 0x1,
+ REF_EQUAL = 0x2,
+ REF_LEQUAL = 0x3,
+ REF_GREATER = 0x4,
+ REF_NOTEQUAL = 0x5,
+ REF_GEQUAL = 0x6,
+ REF_ALWAYS = 0x7,
+} CompareRef;
+typedef enum ReadSize {
+ READ_256_BITS = 0x0,
+ READ_512_BITS = 0x1,
+} ReadSize;
+typedef enum DepthFormat {
+ DEPTH_INVALID = 0x0,
+ DEPTH_16 = 0x1,
+ DEPTH_X8_24 = 0x2,
+ DEPTH_8_24 = 0x3,
+ DEPTH_X8_24_FLOAT = 0x4,
+ DEPTH_8_24_FLOAT = 0x5,
+ DEPTH_32_FLOAT = 0x6,
+ DEPTH_X24_8_32_FLOAT = 0x7,
+} DepthFormat;
+typedef enum ZFormat {
+ Z_INVALID = 0x0,
+ Z_16 = 0x1,
+ Z_24 = 0x2,
+ Z_32_FLOAT = 0x3,
+} ZFormat;
+typedef enum StencilFormat {
+ STENCIL_INVALID = 0x0,
+ STENCIL_8 = 0x1,
+} StencilFormat;
+typedef enum CmaskMode {
+ CMASK_CLEAR_NONE = 0x0,
+ CMASK_CLEAR_ONE = 0x1,
+ CMASK_CLEAR_ALL = 0x2,
+ CMASK_ANY_EXPANDED = 0x3,
+ CMASK_ALPHA0_FRAG1 = 0x4,
+ CMASK_ALPHA0_FRAG2 = 0x5,
+ CMASK_ALPHA0_FRAG4 = 0x6,
+ CMASK_ALPHA0_FRAGS = 0x7,
+ CMASK_ALPHA1_FRAG1 = 0x8,
+ CMASK_ALPHA1_FRAG2 = 0x9,
+ CMASK_ALPHA1_FRAG4 = 0xa,
+ CMASK_ALPHA1_FRAGS = 0xb,
+ CMASK_ALPHAX_FRAG1 = 0xc,
+ CMASK_ALPHAX_FRAG2 = 0xd,
+ CMASK_ALPHAX_FRAG4 = 0xe,
+ CMASK_ALPHAX_FRAGS = 0xf,
+} CmaskMode;
+typedef enum QuadExportFormat {
+ EXPORT_UNUSED = 0x0,
+ EXPORT_32_R = 0x1,
+ EXPORT_32_GR = 0x2,
+ EXPORT_32_AR = 0x3,
+ EXPORT_FP16_ABGR = 0x4,
+ EXPORT_UNSIGNED16_ABGR = 0x5,
+ EXPORT_SIGNED16_ABGR = 0x6,
+ EXPORT_32_ABGR = 0x7,
+ EXPORT_32BPP_8PIX = 0x8,
+ EXPORT_16_16_UNSIGNED_8PIX = 0x9,
+ EXPORT_16_16_SIGNED_8PIX = 0xa,
+ EXPORT_16_16_FLOAT_8PIX = 0xb,
+} QuadExportFormat;
+typedef enum QuadExportFormatOld {
+ EXPORT_4P_32BPC_ABGR = 0x0,
+ EXPORT_4P_16BPC_ABGR = 0x1,
+ EXPORT_4P_32BPC_GR = 0x2,
+ EXPORT_4P_32BPC_AR = 0x3,
+ EXPORT_2P_32BPC_ABGR = 0x4,
+ EXPORT_8P_32BPC_R = 0x5,
+} QuadExportFormatOld;
+typedef enum ColorFormat {
+ COLOR_INVALID = 0x0,
+ COLOR_8 = 0x1,
+ COLOR_16 = 0x2,
+ COLOR_8_8 = 0x3,
+ COLOR_32 = 0x4,
+ COLOR_16_16 = 0x5,
+ COLOR_10_11_11 = 0x6,
+ COLOR_11_11_10 = 0x7,
+ COLOR_10_10_10_2 = 0x8,
+ COLOR_2_10_10_10 = 0x9,
+ COLOR_8_8_8_8 = 0xa,
+ COLOR_32_32 = 0xb,
+ COLOR_16_16_16_16 = 0xc,
+ COLOR_RESERVED_13 = 0xd,
+ COLOR_32_32_32_32 = 0xe,
+ COLOR_RESERVED_15 = 0xf,
+ COLOR_5_6_5 = 0x10,
+ COLOR_1_5_5_5 = 0x11,
+ COLOR_5_5_5_1 = 0x12,
+ COLOR_4_4_4_4 = 0x13,
+ COLOR_8_24 = 0x14,
+ COLOR_24_8 = 0x15,
+ COLOR_X24_8_32_FLOAT = 0x16,
+ COLOR_RESERVED_23 = 0x17,
+ COLOR_RESERVED_24 = 0x18,
+ COLOR_RESERVED_25 = 0x19,
+ COLOR_RESERVED_26 = 0x1a,
+ COLOR_RESERVED_27 = 0x1b,
+ COLOR_RESERVED_28 = 0x1c,
+ COLOR_RESERVED_29 = 0x1d,
+ COLOR_RESERVED_30 = 0x1e,
+} ColorFormat;
+typedef enum SurfaceFormat {
+ FMT_INVALID = 0x0,
+ FMT_8 = 0x1,
+ FMT_16 = 0x2,
+ FMT_8_8 = 0x3,
+ FMT_32 = 0x4,
+ FMT_16_16 = 0x5,
+ FMT_10_11_11 = 0x6,
+ FMT_11_11_10 = 0x7,
+ FMT_10_10_10_2 = 0x8,
+ FMT_2_10_10_10 = 0x9,
+ FMT_8_8_8_8 = 0xa,
+ FMT_32_32 = 0xb,
+ FMT_16_16_16_16 = 0xc,
+ FMT_32_32_32 = 0xd,
+ FMT_32_32_32_32 = 0xe,
+ FMT_RESERVED_4 = 0xf,
+ FMT_5_6_5 = 0x10,
+ FMT_1_5_5_5 = 0x11,
+ FMT_5_5_5_1 = 0x12,
+ FMT_4_4_4_4 = 0x13,
+ FMT_8_24 = 0x14,
+ FMT_24_8 = 0x15,
+ FMT_X24_8_32_FLOAT = 0x16,
+ FMT_RESERVED_33 = 0x17,
+ FMT_11_11_10_FLOAT = 0x18,
+ FMT_16_FLOAT = 0x19,
+ FMT_32_FLOAT = 0x1a,
+ FMT_16_16_FLOAT = 0x1b,
+ FMT_8_24_FLOAT = 0x1c,
+ FMT_24_8_FLOAT = 0x1d,
+ FMT_32_32_FLOAT = 0x1e,
+ FMT_10_11_11_FLOAT = 0x1f,
+ FMT_16_16_16_16_FLOAT = 0x20,
+ FMT_3_3_2 = 0x21,
+ FMT_6_5_5 = 0x22,
+ FMT_32_32_32_32_FLOAT = 0x23,
+ FMT_RESERVED_36 = 0x24,
+ FMT_1 = 0x25,
+ FMT_1_REVERSED = 0x26,
+ FMT_GB_GR = 0x27,
+ FMT_BG_RG = 0x28,
+ FMT_32_AS_8 = 0x29,
+ FMT_32_AS_8_8 = 0x2a,
+ FMT_5_9_9_9_SHAREDEXP = 0x2b,
+ FMT_8_8_8 = 0x2c,
+ FMT_16_16_16 = 0x2d,
+ FMT_16_16_16_FLOAT = 0x2e,
+ FMT_4_4 = 0x2f,
+ FMT_32_32_32_FLOAT = 0x30,
+ FMT_BC1 = 0x31,
+ FMT_BC2 = 0x32,
+ FMT_BC3 = 0x33,
+ FMT_BC4 = 0x34,
+ FMT_BC5 = 0x35,
+ FMT_BC6 = 0x36,
+ FMT_BC7 = 0x37,
+ FMT_32_AS_32_32_32_32 = 0x38,
+ FMT_APC3 = 0x39,
+ FMT_APC4 = 0x3a,
+ FMT_APC5 = 0x3b,
+ FMT_APC6 = 0x3c,
+ FMT_APC7 = 0x3d,
+ FMT_CTX1 = 0x3e,
+ FMT_RESERVED_63 = 0x3f,
+} SurfaceFormat;
+typedef enum BUF_DATA_FORMAT {
+ BUF_DATA_FORMAT_INVALID = 0x0,
+ BUF_DATA_FORMAT_8 = 0x1,
+ BUF_DATA_FORMAT_16 = 0x2,
+ BUF_DATA_FORMAT_8_8 = 0x3,
+ BUF_DATA_FORMAT_32 = 0x4,
+ BUF_DATA_FORMAT_16_16 = 0x5,
+ BUF_DATA_FORMAT_10_11_11 = 0x6,
+ BUF_DATA_FORMAT_11_11_10 = 0x7,
+ BUF_DATA_FORMAT_10_10_10_2 = 0x8,
+ BUF_DATA_FORMAT_2_10_10_10 = 0x9,
+ BUF_DATA_FORMAT_8_8_8_8 = 0xa,
+ BUF_DATA_FORMAT_32_32 = 0xb,
+ BUF_DATA_FORMAT_16_16_16_16 = 0xc,
+ BUF_DATA_FORMAT_32_32_32 = 0xd,
+ BUF_DATA_FORMAT_32_32_32_32 = 0xe,
+ BUF_DATA_FORMAT_RESERVED_15 = 0xf,
+} BUF_DATA_FORMAT;
+typedef enum IMG_DATA_FORMAT {
+ IMG_DATA_FORMAT_INVALID = 0x0,
+ IMG_DATA_FORMAT_8 = 0x1,
+ IMG_DATA_FORMAT_16 = 0x2,
+ IMG_DATA_FORMAT_8_8 = 0x3,
+ IMG_DATA_FORMAT_32 = 0x4,
+ IMG_DATA_FORMAT_16_16 = 0x5,
+ IMG_DATA_FORMAT_10_11_11 = 0x6,
+ IMG_DATA_FORMAT_11_11_10 = 0x7,
+ IMG_DATA_FORMAT_10_10_10_2 = 0x8,
+ IMG_DATA_FORMAT_2_10_10_10 = 0x9,
+ IMG_DATA_FORMAT_8_8_8_8 = 0xa,
+ IMG_DATA_FORMAT_32_32 = 0xb,
+ IMG_DATA_FORMAT_16_16_16_16 = 0xc,
+ IMG_DATA_FORMAT_32_32_32 = 0xd,
+ IMG_DATA_FORMAT_32_32_32_32 = 0xe,
+ IMG_DATA_FORMAT_16_AS_32_32 = 0xf,
+ IMG_DATA_FORMAT_5_6_5 = 0x10,
+ IMG_DATA_FORMAT_1_5_5_5 = 0x11,
+ IMG_DATA_FORMAT_5_5_5_1 = 0x12,
+ IMG_DATA_FORMAT_4_4_4_4 = 0x13,
+ IMG_DATA_FORMAT_8_24 = 0x14,
+ IMG_DATA_FORMAT_24_8 = 0x15,
+ IMG_DATA_FORMAT_X24_8_32 = 0x16,
+ IMG_DATA_FORMAT_8_AS_8_8_8_8 = 0x17,
+ IMG_DATA_FORMAT_ETC2_RGB = 0x18,
+ IMG_DATA_FORMAT_ETC2_RGBA = 0x19,
+ IMG_DATA_FORMAT_ETC2_R = 0x1a,
+ IMG_DATA_FORMAT_ETC2_RG = 0x1b,
+ IMG_DATA_FORMAT_ETC2_RGBA1 = 0x1c,
+ IMG_DATA_FORMAT_RESERVED_29 = 0x1d,
+ IMG_DATA_FORMAT_RESERVED_30 = 0x1e,
+ IMG_DATA_FORMAT_RESERVED_31 = 0x1f,
+ IMG_DATA_FORMAT_GB_GR = 0x20,
+ IMG_DATA_FORMAT_BG_RG = 0x21,
+ IMG_DATA_FORMAT_5_9_9_9 = 0x22,
+ IMG_DATA_FORMAT_BC1 = 0x23,
+ IMG_DATA_FORMAT_BC2 = 0x24,
+ IMG_DATA_FORMAT_BC3 = 0x25,
+ IMG_DATA_FORMAT_BC4 = 0x26,
+ IMG_DATA_FORMAT_BC5 = 0x27,
+ IMG_DATA_FORMAT_BC6 = 0x28,
+ IMG_DATA_FORMAT_BC7 = 0x29,
+ IMG_DATA_FORMAT_16_AS_16_16_16_16 = 0x2a,
+ IMG_DATA_FORMAT_16_AS_32_32_32_32 = 0x2b,
+ IMG_DATA_FORMAT_FMASK8_S2_F1 = 0x2c,
+ IMG_DATA_FORMAT_FMASK8_S4_F1 = 0x2d,
+ IMG_DATA_FORMAT_FMASK8_S8_F1 = 0x2e,
+ IMG_DATA_FORMAT_FMASK8_S2_F2 = 0x2f,
+ IMG_DATA_FORMAT_FMASK8_S4_F2 = 0x30,
+ IMG_DATA_FORMAT_FMASK8_S4_F4 = 0x31,
+ IMG_DATA_FORMAT_FMASK16_S16_F1 = 0x32,
+ IMG_DATA_FORMAT_FMASK16_S8_F2 = 0x33,
+ IMG_DATA_FORMAT_FMASK32_S16_F2 = 0x34,
+ IMG_DATA_FORMAT_FMASK32_S8_F4 = 0x35,
+ IMG_DATA_FORMAT_FMASK32_S8_F8 = 0x36,
+ IMG_DATA_FORMAT_FMASK64_S16_F4 = 0x37,
+ IMG_DATA_FORMAT_FMASK64_S16_F8 = 0x38,
+ IMG_DATA_FORMAT_4_4 = 0x39,
+ IMG_DATA_FORMAT_6_5_5 = 0x3a,
+ IMG_DATA_FORMAT_1 = 0x3b,
+ IMG_DATA_FORMAT_1_REVERSED = 0x3c,
+ IMG_DATA_FORMAT_8_AS_32 = 0x3d,
+ IMG_DATA_FORMAT_8_AS_32_32 = 0x3e,
+ IMG_DATA_FORMAT_32_AS_32_32_32_32 = 0x3f,
+} IMG_DATA_FORMAT;
+typedef enum BUF_NUM_FORMAT {
+ BUF_NUM_FORMAT_UNORM = 0x0,
+ BUF_NUM_FORMAT_SNORM = 0x1,
+ BUF_NUM_FORMAT_USCALED = 0x2,
+ BUF_NUM_FORMAT_SSCALED = 0x3,
+ BUF_NUM_FORMAT_UINT = 0x4,
+ BUF_NUM_FORMAT_SINT = 0x5,
+ BUF_NUM_FORMAT_RESERVED_6 = 0x6,
+ BUF_NUM_FORMAT_FLOAT = 0x7,
+} BUF_NUM_FORMAT;
+typedef enum IMG_NUM_FORMAT {
+ IMG_NUM_FORMAT_UNORM = 0x0,
+ IMG_NUM_FORMAT_SNORM = 0x1,
+ IMG_NUM_FORMAT_USCALED = 0x2,
+ IMG_NUM_FORMAT_SSCALED = 0x3,
+ IMG_NUM_FORMAT_UINT = 0x4,
+ IMG_NUM_FORMAT_SINT = 0x5,
+ IMG_NUM_FORMAT_RESERVED_6 = 0x6,
+ IMG_NUM_FORMAT_FLOAT = 0x7,
+ IMG_NUM_FORMAT_RESERVED_8 = 0x8,
+ IMG_NUM_FORMAT_SRGB = 0x9,
+ IMG_NUM_FORMAT_RESERVED_10 = 0xa,
+ IMG_NUM_FORMAT_RESERVED_11 = 0xb,
+ IMG_NUM_FORMAT_RESERVED_12 = 0xc,
+ IMG_NUM_FORMAT_RESERVED_13 = 0xd,
+ IMG_NUM_FORMAT_RESERVED_14 = 0xe,
+ IMG_NUM_FORMAT_RESERVED_15 = 0xf,
+} IMG_NUM_FORMAT;
+typedef enum TileType {
+ ARRAY_COLOR_TILE = 0x0,
+ ARRAY_DEPTH_TILE = 0x1,
+} TileType;
+typedef enum NonDispTilingOrder {
+ ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
+ ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
+} NonDispTilingOrder;
+typedef enum MicroTileMode {
+ ADDR_SURF_DISPLAY_MICRO_TILING = 0x0,
+ ADDR_SURF_THIN_MICRO_TILING = 0x1,
+ ADDR_SURF_DEPTH_MICRO_TILING = 0x2,
+ ADDR_SURF_ROTATED_MICRO_TILING = 0x3,
+ ADDR_SURF_THICK_MICRO_TILING = 0x4,
+} MicroTileMode;
+typedef enum TileSplit {
+ ADDR_SURF_TILE_SPLIT_64B = 0x0,
+ ADDR_SURF_TILE_SPLIT_128B = 0x1,
+ ADDR_SURF_TILE_SPLIT_256B = 0x2,
+ ADDR_SURF_TILE_SPLIT_512B = 0x3,
+ ADDR_SURF_TILE_SPLIT_1KB = 0x4,
+ ADDR_SURF_TILE_SPLIT_2KB = 0x5,
+ ADDR_SURF_TILE_SPLIT_4KB = 0x6,
+} TileSplit;
+typedef enum SampleSplit {
+ ADDR_SURF_SAMPLE_SPLIT_1 = 0x0,
+ ADDR_SURF_SAMPLE_SPLIT_2 = 0x1,
+ ADDR_SURF_SAMPLE_SPLIT_4 = 0x2,
+ ADDR_SURF_SAMPLE_SPLIT_8 = 0x3,
+} SampleSplit;
+typedef enum PipeConfig {
+ ADDR_SURF_P2 = 0x0,
+ ADDR_SURF_P2_RESERVED0 = 0x1,
+ ADDR_SURF_P2_RESERVED1 = 0x2,
+ ADDR_SURF_P2_RESERVED2 = 0x3,
+ ADDR_SURF_P4_8x16 = 0x4,
+ ADDR_SURF_P4_16x16 = 0x5,
+ ADDR_SURF_P4_16x32 = 0x6,
+ ADDR_SURF_P4_32x32 = 0x7,
+ ADDR_SURF_P8_16x16_8x16 = 0x8,
+ ADDR_SURF_P8_16x32_8x16 = 0x9,
+ ADDR_SURF_P8_32x32_8x16 = 0xa,
+ ADDR_SURF_P8_16x32_16x16 = 0xb,
+ ADDR_SURF_P8_32x32_16x16 = 0xc,
+ ADDR_SURF_P8_32x32_16x32 = 0xd,
+ ADDR_SURF_P8_32x64_32x32 = 0xe,
+ ADDR_SURF_P8_RESERVED0 = 0xf,
+ ADDR_SURF_P16_32x32_8x16 = 0x10,
+ ADDR_SURF_P16_32x32_16x16 = 0x11,
+} PipeConfig;
+typedef enum NumBanks {
+ ADDR_SURF_2_BANK = 0x0,
+ ADDR_SURF_4_BANK = 0x1,
+ ADDR_SURF_8_BANK = 0x2,
+ ADDR_SURF_16_BANK = 0x3,
+} NumBanks;
+typedef enum BankWidth {
+ ADDR_SURF_BANK_WIDTH_1 = 0x0,
+ ADDR_SURF_BANK_WIDTH_2 = 0x1,
+ ADDR_SURF_BANK_WIDTH_4 = 0x2,
+ ADDR_SURF_BANK_WIDTH_8 = 0x3,
+} BankWidth;
+typedef enum BankHeight {
+ ADDR_SURF_BANK_HEIGHT_1 = 0x0,
+ ADDR_SURF_BANK_HEIGHT_2 = 0x1,
+ ADDR_SURF_BANK_HEIGHT_4 = 0x2,
+ ADDR_SURF_BANK_HEIGHT_8 = 0x3,
+} BankHeight;
+typedef enum BankWidthHeight {
+ ADDR_SURF_BANK_WH_1 = 0x0,
+ ADDR_SURF_BANK_WH_2 = 0x1,
+ ADDR_SURF_BANK_WH_4 = 0x2,
+ ADDR_SURF_BANK_WH_8 = 0x3,
+} BankWidthHeight;
+typedef enum MacroTileAspect {
+ ADDR_SURF_MACRO_ASPECT_1 = 0x0,
+ ADDR_SURF_MACRO_ASPECT_2 = 0x1,
+ ADDR_SURF_MACRO_ASPECT_4 = 0x2,
+ ADDR_SURF_MACRO_ASPECT_8 = 0x3,
+} MacroTileAspect;
+typedef enum GATCL1RequestType {
+ GATCL1_TYPE_NORMAL = 0x0,
+ GATCL1_TYPE_SHOOTDOWN = 0x1,
+ GATCL1_TYPE_BYPASS = 0x2,
+} GATCL1RequestType;
+typedef enum TCC_CACHE_POLICIES {
+ TCC_CACHE_POLICY_LRU = 0x0,
+ TCC_CACHE_POLICY_STREAM = 0x1,
+} TCC_CACHE_POLICIES;
+typedef enum MTYPE {
+ MTYPE_NC_NV = 0x0,
+ MTYPE_NC = 0x1,
+ MTYPE_CC = 0x2,
+ MTYPE_UC = 0x3,
+} MTYPE;
+typedef enum PERFMON_COUNTER_MODE {
+ PERFMON_COUNTER_MODE_ACCUM = 0x0,
+ PERFMON_COUNTER_MODE_ACTIVE_CYCLES = 0x1,
+ PERFMON_COUNTER_MODE_MAX = 0x2,
+ PERFMON_COUNTER_MODE_DIRTY = 0x3,
+ PERFMON_COUNTER_MODE_SAMPLE = 0x4,
+ PERFMON_COUNTER_MODE_CYCLES_SINCE_FIRST_EVENT = 0x5,
+ PERFMON_COUNTER_MODE_CYCLES_SINCE_LAST_EVENT = 0x6,
+ PERFMON_COUNTER_MODE_CYCLES_GE_HI = 0x7,
+ PERFMON_COUNTER_MODE_CYCLES_EQ_HI = 0x8,
+ PERFMON_COUNTER_MODE_INACTIVE_CYCLES = 0x9,
+ PERFMON_COUNTER_MODE_RESERVED = 0xf,
+} PERFMON_COUNTER_MODE;
+typedef enum PERFMON_SPM_MODE {
+ PERFMON_SPM_MODE_OFF = 0x0,
+ PERFMON_SPM_MODE_16BIT_CLAMP = 0x1,
+ PERFMON_SPM_MODE_16BIT_NO_CLAMP = 0x2,
+ PERFMON_SPM_MODE_32BIT_CLAMP = 0x3,
+ PERFMON_SPM_MODE_32BIT_NO_CLAMP = 0x4,
+ PERFMON_SPM_MODE_RESERVED_5 = 0x5,
+ PERFMON_SPM_MODE_RESERVED_6 = 0x6,
+ PERFMON_SPM_MODE_RESERVED_7 = 0x7,
+ PERFMON_SPM_MODE_TEST_MODE_0 = 0x8,
+ PERFMON_SPM_MODE_TEST_MODE_1 = 0x9,
+ PERFMON_SPM_MODE_TEST_MODE_2 = 0xa,
+} PERFMON_SPM_MODE;
+typedef enum SurfaceTiling {
+ ARRAY_LINEAR = 0x0,
+ ARRAY_TILED = 0x1,
+} SurfaceTiling;
+typedef enum SurfaceArray {
+ ARRAY_1D = 0x0,
+ ARRAY_2D = 0x1,
+ ARRAY_3D = 0x2,
+ ARRAY_3D_SLICE = 0x3,
+} SurfaceArray;
+typedef enum ColorArray {
+ ARRAY_2D_ALT_COLOR = 0x0,
+ ARRAY_2D_COLOR = 0x1,
+ ARRAY_3D_SLICE_COLOR = 0x3,
+} ColorArray;
+typedef enum DepthArray {
+ ARRAY_2D_ALT_DEPTH = 0x0,
+ ARRAY_2D_DEPTH = 0x1,
+} DepthArray;
+typedef enum ENUM_NUM_SIMD_PER_CU {
+ NUM_SIMD_PER_CU = 0x4,
+} ENUM_NUM_SIMD_PER_CU;
+typedef enum MEM_PWR_FORCE_CTRL {
+ NO_FORCE_REQUEST = 0x0,
+ FORCE_LIGHT_SLEEP_REQUEST = 0x1,
+ FORCE_DEEP_SLEEP_REQUEST = 0x2,
+ FORCE_SHUT_DOWN_REQUEST = 0x3,
+} MEM_PWR_FORCE_CTRL;
+typedef enum MEM_PWR_FORCE_CTRL2 {
+ NO_FORCE_REQ = 0x0,
+ FORCE_LIGHT_SLEEP_REQ = 0x1,
+} MEM_PWR_FORCE_CTRL2;
+typedef enum MEM_PWR_DIS_CTRL {
+ ENABLE_MEM_PWR_CTRL = 0x0,
+ DISABLE_MEM_PWR_CTRL = 0x1,
+} MEM_PWR_DIS_CTRL;
+typedef enum MEM_PWR_SEL_CTRL {
+ DYNAMIC_SHUT_DOWN_ENABLE = 0x0,
+ DYNAMIC_DEEP_SLEEP_ENABLE = 0x1,
+ DYNAMIC_LIGHT_SLEEP_ENABLE = 0x2,
+} MEM_PWR_SEL_CTRL;
+typedef enum MEM_PWR_SEL_CTRL2 {
+ DYNAMIC_DEEP_SLEEP_EN = 0x0,
+ DYNAMIC_LIGHT_SLEEP_EN = 0x1,
+} MEM_PWR_SEL_CTRL2;
+
+#endif /* GFX_8_1_ENUM_H */
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_sh_mask.h
new file mode 100644
index 000000000000..397705a6b3a2
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_sh_mask.h
@@ -0,0 +1,21368 @@
+/*
+ * GFX_8_1 Register documentation
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) 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.
+ */
+
+#ifndef GFX_8_1_SH_MASK_H
+#define GFX_8_1_SH_MASK_H
+
+#define CB_BLEND_RED__BLEND_RED_MASK 0xffffffff
+#define CB_BLEND_RED__BLEND_RED__SHIFT 0x0
+#define CB_BLEND_GREEN__BLEND_GREEN_MASK 0xffffffff
+#define CB_BLEND_GREEN__BLEND_GREEN__SHIFT 0x0
+#define CB_BLEND_BLUE__BLEND_BLUE_MASK 0xffffffff
+#define CB_BLEND_BLUE__BLEND_BLUE__SHIFT 0x0
+#define CB_BLEND_ALPHA__BLEND_ALPHA_MASK 0xffffffff
+#define CB_BLEND_ALPHA__BLEND_ALPHA__SHIFT 0x0
+#define CB_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_DCC_CONTROL__OVERWRITE_COMBINER_MRT_SHARING_DISABLE_MASK 0x2
+#define CB_DCC_CONTROL__OVERWRITE_COMBINER_MRT_SHARING_DISABLE__SHIFT 0x1
+#define CB_DCC_CONTROL__OVERWRITE_COMBINER_WATERMARK_MASK 0x7c
+#define CB_DCC_CONTROL__OVERWRITE_COMBINER_WATERMARK__SHIFT 0x2
+#define CB_COLOR_CONTROL__DISABLE_DUAL_QUAD_MASK 0x1
+#define CB_COLOR_CONTROL__DISABLE_DUAL_QUAD__SHIFT 0x0
+#define CB_COLOR_CONTROL__DEGAMMA_ENABLE_MASK 0x8
+#define CB_COLOR_CONTROL__DEGAMMA_ENABLE__SHIFT 0x3
+#define CB_COLOR_CONTROL__MODE_MASK 0x70
+#define CB_COLOR_CONTROL__MODE__SHIFT 0x4
+#define CB_COLOR_CONTROL__ROP3_MASK 0xff0000
+#define CB_COLOR_CONTROL__ROP3__SHIFT 0x10
+#define CB_BLEND0_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND0_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND0_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND0_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND0_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND0_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND0_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND0_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND0_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND0_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND0_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND0_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND0_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND0_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND0_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND0_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND0_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND0_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND1_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND1_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND1_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND1_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND1_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND1_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND1_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND1_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND1_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND1_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND1_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND1_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND1_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND1_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND1_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND1_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND1_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND1_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND2_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND2_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND2_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND2_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND2_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND2_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND2_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND2_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND2_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND2_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND2_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND2_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND2_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND2_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND2_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND2_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND2_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND2_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND3_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND3_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND3_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND3_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND3_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND3_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND3_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND3_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND3_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND3_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND3_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND3_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND3_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND3_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND3_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND3_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND3_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND3_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND4_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND4_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND4_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND4_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND4_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND4_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND4_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND4_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND4_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND4_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND4_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND4_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND4_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND4_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND4_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND4_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND4_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND4_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND5_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND5_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND5_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND5_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND5_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND5_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND5_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND5_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND5_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND5_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND5_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND5_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND5_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND5_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND5_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND5_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND5_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND5_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND6_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND6_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND6_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND6_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND6_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND6_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND6_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND6_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND6_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND6_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND6_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND6_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND6_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND6_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND6_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND6_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND6_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND6_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_BLEND7_CONTROL__COLOR_SRCBLEND_MASK 0x1f
+#define CB_BLEND7_CONTROL__COLOR_SRCBLEND__SHIFT 0x0
+#define CB_BLEND7_CONTROL__COLOR_COMB_FCN_MASK 0xe0
+#define CB_BLEND7_CONTROL__COLOR_COMB_FCN__SHIFT 0x5
+#define CB_BLEND7_CONTROL__COLOR_DESTBLEND_MASK 0x1f00
+#define CB_BLEND7_CONTROL__COLOR_DESTBLEND__SHIFT 0x8
+#define CB_BLEND7_CONTROL__ALPHA_SRCBLEND_MASK 0x1f0000
+#define CB_BLEND7_CONTROL__ALPHA_SRCBLEND__SHIFT 0x10
+#define CB_BLEND7_CONTROL__ALPHA_COMB_FCN_MASK 0xe00000
+#define CB_BLEND7_CONTROL__ALPHA_COMB_FCN__SHIFT 0x15
+#define CB_BLEND7_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000
+#define CB_BLEND7_CONTROL__ALPHA_DESTBLEND__SHIFT 0x18
+#define CB_BLEND7_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000
+#define CB_BLEND7_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x1d
+#define CB_BLEND7_CONTROL__ENABLE_MASK 0x40000000
+#define CB_BLEND7_CONTROL__ENABLE__SHIFT 0x1e
+#define CB_BLEND7_CONTROL__DISABLE_ROP3_MASK 0x80000000
+#define CB_BLEND7_CONTROL__DISABLE_ROP3__SHIFT 0x1f
+#define CB_COLOR0_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR0_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR1_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR1_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR2_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR2_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR3_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR3_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR4_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR4_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR5_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR5_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR6_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR6_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR7_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR7_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR0_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR0_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR0_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR0_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR1_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR1_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR1_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR1_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR2_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR2_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR2_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR2_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR3_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR3_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR3_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR3_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR4_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR4_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR4_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR4_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR5_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR5_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR5_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR5_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR6_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR6_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR6_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR6_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR7_PITCH__TILE_MAX_MASK 0x7ff
+#define CB_COLOR7_PITCH__TILE_MAX__SHIFT 0x0
+#define CB_COLOR7_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000
+#define CB_COLOR7_PITCH__FMASK_TILE_MAX__SHIFT 0x14
+#define CB_COLOR0_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR0_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR1_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR1_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR2_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR2_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR3_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR3_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR4_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR4_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR5_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR5_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR6_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR6_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR7_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR7_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR0_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR0_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR0_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR0_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR1_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR1_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR1_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR1_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR2_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR2_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR2_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR2_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR3_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR3_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR3_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR3_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR4_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR4_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR4_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR4_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR5_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR5_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR5_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR5_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR6_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR6_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR6_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR6_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR7_VIEW__SLICE_START_MASK 0x7ff
+#define CB_COLOR7_VIEW__SLICE_START__SHIFT 0x0
+#define CB_COLOR7_VIEW__SLICE_MAX_MASK 0xffe000
+#define CB_COLOR7_VIEW__SLICE_MAX__SHIFT 0xd
+#define CB_COLOR0_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR0_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR0_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR0_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR0_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR0_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR0_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR0_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR0_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR0_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR0_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR0_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR0_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR0_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR0_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR0_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR0_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR0_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR0_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR0_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR0_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR0_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR0_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR0_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR0_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR0_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR0_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR0_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR0_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR0_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR0_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR0_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR0_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR0_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR0_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR0_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR1_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR1_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR1_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR1_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR1_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR1_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR1_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR1_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR1_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR1_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR1_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR1_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR1_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR1_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR1_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR1_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR1_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR1_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR1_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR1_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR1_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR1_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR1_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR1_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR1_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR1_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR1_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR1_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR1_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR1_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR1_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR1_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR1_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR1_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR1_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR1_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR2_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR2_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR2_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR2_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR2_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR2_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR2_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR2_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR2_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR2_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR2_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR2_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR2_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR2_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR2_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR2_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR2_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR2_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR2_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR2_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR2_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR2_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR2_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR2_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR2_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR2_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR2_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR2_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR2_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR2_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR2_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR2_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR2_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR2_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR2_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR2_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR3_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR3_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR3_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR3_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR3_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR3_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR3_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR3_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR3_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR3_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR3_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR3_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR3_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR3_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR3_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR3_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR3_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR3_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR3_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR3_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR3_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR3_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR3_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR3_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR3_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR3_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR3_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR3_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR3_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR3_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR3_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR3_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR3_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR3_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR3_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR3_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR4_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR4_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR4_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR4_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR4_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR4_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR4_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR4_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR4_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR4_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR4_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR4_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR4_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR4_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR4_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR4_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR4_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR4_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR4_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR4_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR4_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR4_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR4_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR4_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR4_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR4_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR4_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR4_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR4_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR4_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR4_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR4_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR4_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR4_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR4_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR4_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR5_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR5_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR5_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR5_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR5_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR5_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR5_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR5_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR5_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR5_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR5_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR5_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR5_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR5_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR5_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR5_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR5_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR5_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR5_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR5_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR5_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR5_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR5_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR5_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR5_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR5_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR5_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR5_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR5_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR5_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR5_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR5_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR5_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR5_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR5_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR5_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR6_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR6_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR6_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR6_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR6_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR6_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR6_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR6_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR6_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR6_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR6_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR6_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR6_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR6_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR6_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR6_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR6_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR6_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR6_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR6_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR6_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR6_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR6_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR6_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR6_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR6_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR6_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR6_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR6_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR6_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR6_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR6_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR6_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR6_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR6_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR6_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR7_INFO__ENDIAN_MASK 0x3
+#define CB_COLOR7_INFO__ENDIAN__SHIFT 0x0
+#define CB_COLOR7_INFO__FORMAT_MASK 0x7c
+#define CB_COLOR7_INFO__FORMAT__SHIFT 0x2
+#define CB_COLOR7_INFO__LINEAR_GENERAL_MASK 0x80
+#define CB_COLOR7_INFO__LINEAR_GENERAL__SHIFT 0x7
+#define CB_COLOR7_INFO__NUMBER_TYPE_MASK 0x700
+#define CB_COLOR7_INFO__NUMBER_TYPE__SHIFT 0x8
+#define CB_COLOR7_INFO__COMP_SWAP_MASK 0x1800
+#define CB_COLOR7_INFO__COMP_SWAP__SHIFT 0xb
+#define CB_COLOR7_INFO__FAST_CLEAR_MASK 0x2000
+#define CB_COLOR7_INFO__FAST_CLEAR__SHIFT 0xd
+#define CB_COLOR7_INFO__COMPRESSION_MASK 0x4000
+#define CB_COLOR7_INFO__COMPRESSION__SHIFT 0xe
+#define CB_COLOR7_INFO__BLEND_CLAMP_MASK 0x8000
+#define CB_COLOR7_INFO__BLEND_CLAMP__SHIFT 0xf
+#define CB_COLOR7_INFO__BLEND_BYPASS_MASK 0x10000
+#define CB_COLOR7_INFO__BLEND_BYPASS__SHIFT 0x10
+#define CB_COLOR7_INFO__SIMPLE_FLOAT_MASK 0x20000
+#define CB_COLOR7_INFO__SIMPLE_FLOAT__SHIFT 0x11
+#define CB_COLOR7_INFO__ROUND_MODE_MASK 0x40000
+#define CB_COLOR7_INFO__ROUND_MODE__SHIFT 0x12
+#define CB_COLOR7_INFO__CMASK_IS_LINEAR_MASK 0x80000
+#define CB_COLOR7_INFO__CMASK_IS_LINEAR__SHIFT 0x13
+#define CB_COLOR7_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x700000
+#define CB_COLOR7_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x14
+#define CB_COLOR7_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x3800000
+#define CB_COLOR7_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x17
+#define CB_COLOR7_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x4000000
+#define CB_COLOR7_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x1a
+#define CB_COLOR7_INFO__FMASK_COMPRESS_1FRAG_ONLY_MASK 0x8000000
+#define CB_COLOR7_INFO__FMASK_COMPRESS_1FRAG_ONLY__SHIFT 0x1b
+#define CB_COLOR7_INFO__DCC_ENABLE_MASK 0x10000000
+#define CB_COLOR7_INFO__DCC_ENABLE__SHIFT 0x1c
+#define CB_COLOR7_INFO__CMASK_ADDR_TYPE_MASK 0x60000000
+#define CB_COLOR7_INFO__CMASK_ADDR_TYPE__SHIFT 0x1d
+#define CB_COLOR0_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR0_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR0_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR0_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR0_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR0_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR0_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR0_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR0_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR0_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR0_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR0_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR1_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR1_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR1_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR1_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR1_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR1_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR1_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR1_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR1_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR1_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR1_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR1_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR2_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR2_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR2_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR2_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR2_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR2_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR2_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR2_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR2_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR2_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR2_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR2_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR3_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR3_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR3_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR3_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR3_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR3_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR3_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR3_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR3_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR3_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR3_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR3_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR4_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR4_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR4_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR4_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR4_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR4_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR4_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR4_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR4_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR4_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR4_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR4_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR5_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR5_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR5_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR5_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR5_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR5_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR5_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR5_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR5_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR5_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR5_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR5_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR6_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR6_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR6_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR6_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR6_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR6_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR6_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR6_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR6_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR6_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR6_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR6_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR7_ATTRIB__TILE_MODE_INDEX_MASK 0x1f
+#define CB_COLOR7_ATTRIB__TILE_MODE_INDEX__SHIFT 0x0
+#define CB_COLOR7_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x3e0
+#define CB_COLOR7_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x5
+#define CB_COLOR7_ATTRIB__FMASK_BANK_HEIGHT_MASK 0xc00
+#define CB_COLOR7_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0xa
+#define CB_COLOR7_ATTRIB__NUM_SAMPLES_MASK 0x7000
+#define CB_COLOR7_ATTRIB__NUM_SAMPLES__SHIFT 0xc
+#define CB_COLOR7_ATTRIB__NUM_FRAGMENTS_MASK 0x18000
+#define CB_COLOR7_ATTRIB__NUM_FRAGMENTS__SHIFT 0xf
+#define CB_COLOR7_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x20000
+#define CB_COLOR7_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x11
+#define CB_COLOR0_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR0_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR0_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR0_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR0_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR0_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR0_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR0_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR0_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR0_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR0_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR0_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR0_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR0_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR0_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR0_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR0_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR0_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR1_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR1_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR1_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR1_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR1_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR1_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR1_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR1_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR1_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR1_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR1_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR1_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR1_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR1_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR1_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR1_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR1_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR1_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR2_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR2_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR2_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR2_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR2_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR2_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR2_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR2_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR2_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR2_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR2_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR2_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR2_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR2_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR2_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR2_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR2_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR2_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR3_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR3_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR3_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR3_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR3_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR3_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR3_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR3_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR3_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR3_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR3_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR3_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR3_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR3_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR3_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR3_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR3_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR3_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR4_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR4_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR4_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR4_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR4_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR4_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR4_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR4_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR4_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR4_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR4_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR4_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR4_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR4_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR4_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR4_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR4_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR4_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR5_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR5_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR5_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR5_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR5_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR5_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR5_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR5_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR5_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR5_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR5_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR5_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR5_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR5_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR5_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR5_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR5_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR5_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR6_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR6_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR6_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR6_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR6_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR6_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR6_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR6_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR6_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR6_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR6_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR6_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR6_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR6_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR6_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR6_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR6_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR6_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR7_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE_MASK 0x1
+#define CB_COLOR7_DCC_CONTROL__OVERWRITE_COMBINER_DISABLE__SHIFT 0x0
+#define CB_COLOR7_DCC_CONTROL__KEY_CLEAR_ENABLE_MASK 0x2
+#define CB_COLOR7_DCC_CONTROL__KEY_CLEAR_ENABLE__SHIFT 0x1
+#define CB_COLOR7_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE_MASK 0xc
+#define CB_COLOR7_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE__SHIFT 0x2
+#define CB_COLOR7_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE_MASK 0x10
+#define CB_COLOR7_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE__SHIFT 0x4
+#define CB_COLOR7_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE_MASK 0x60
+#define CB_COLOR7_DCC_CONTROL__MAX_COMPRESSED_BLOCK_SIZE__SHIFT 0x5
+#define CB_COLOR7_DCC_CONTROL__COLOR_TRANSFORM_MASK 0x180
+#define CB_COLOR7_DCC_CONTROL__COLOR_TRANSFORM__SHIFT 0x7
+#define CB_COLOR7_DCC_CONTROL__INDEPENDENT_64B_BLOCKS_MASK 0x200
+#define CB_COLOR7_DCC_CONTROL__INDEPENDENT_64B_BLOCKS__SHIFT 0x9
+#define CB_COLOR7_DCC_CONTROL__LOSSY_RGB_PRECISION_MASK 0x3c00
+#define CB_COLOR7_DCC_CONTROL__LOSSY_RGB_PRECISION__SHIFT 0xa
+#define CB_COLOR7_DCC_CONTROL__LOSSY_ALPHA_PRECISION_MASK 0x3c000
+#define CB_COLOR7_DCC_CONTROL__LOSSY_ALPHA_PRECISION__SHIFT 0xe
+#define CB_COLOR0_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR0_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR1_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR1_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR2_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR2_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR3_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR3_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR4_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR4_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR5_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR5_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR6_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR6_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR7_CMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR7_CMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR0_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR0_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR1_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR1_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR2_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR2_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR3_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR3_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR4_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR4_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR5_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR5_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR6_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR6_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR7_CMASK_SLICE__TILE_MAX_MASK 0x3fff
+#define CB_COLOR7_CMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR0_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR0_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR1_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR1_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR2_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR2_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR3_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR3_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR4_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR4_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR5_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR5_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR6_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR6_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR7_FMASK__BASE_256B_MASK 0xffffffff
+#define CB_COLOR7_FMASK__BASE_256B__SHIFT 0x0
+#define CB_COLOR0_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR0_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR1_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR1_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR2_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR2_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR3_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR3_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR4_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR4_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR5_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR5_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR6_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR6_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR7_FMASK_SLICE__TILE_MAX_MASK 0x3fffff
+#define CB_COLOR7_FMASK_SLICE__TILE_MAX__SHIFT 0x0
+#define CB_COLOR0_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR0_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR1_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR1_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR2_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR2_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR3_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR3_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR4_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR4_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR5_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR5_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR6_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR6_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR7_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffff
+#define CB_COLOR7_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x0
+#define CB_COLOR0_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR0_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR1_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR1_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR2_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR2_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR3_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR3_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR4_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR4_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR5_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR5_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR6_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR6_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR7_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffff
+#define CB_COLOR7_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x0
+#define CB_COLOR0_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR0_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR1_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR1_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR2_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR2_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR3_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR3_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR4_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR4_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR5_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR5_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR6_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR6_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_COLOR7_DCC_BASE__BASE_256B_MASK 0xffffffff
+#define CB_COLOR7_DCC_BASE__BASE_256B__SHIFT 0x0
+#define CB_TARGET_MASK__TARGET0_ENABLE_MASK 0xf
+#define CB_TARGET_MASK__TARGET0_ENABLE__SHIFT 0x0
+#define CB_TARGET_MASK__TARGET1_ENABLE_MASK 0xf0
+#define CB_TARGET_MASK__TARGET1_ENABLE__SHIFT 0x4
+#define CB_TARGET_MASK__TARGET2_ENABLE_MASK 0xf00
+#define CB_TARGET_MASK__TARGET2_ENABLE__SHIFT 0x8
+#define CB_TARGET_MASK__TARGET3_ENABLE_MASK 0xf000
+#define CB_TARGET_MASK__TARGET3_ENABLE__SHIFT 0xc
+#define CB_TARGET_MASK__TARGET4_ENABLE_MASK 0xf0000
+#define CB_TARGET_MASK__TARGET4_ENABLE__SHIFT 0x10
+#define CB_TARGET_MASK__TARGET5_ENABLE_MASK 0xf00000
+#define CB_TARGET_MASK__TARGET5_ENABLE__SHIFT 0x14
+#define CB_TARGET_MASK__TARGET6_ENABLE_MASK 0xf000000
+#define CB_TARGET_MASK__TARGET6_ENABLE__SHIFT 0x18
+#define CB_TARGET_MASK__TARGET7_ENABLE_MASK 0xf0000000
+#define CB_TARGET_MASK__TARGET7_ENABLE__SHIFT 0x1c
+#define CB_SHADER_MASK__OUTPUT0_ENABLE_MASK 0xf
+#define CB_SHADER_MASK__OUTPUT0_ENABLE__SHIFT 0x0
+#define CB_SHADER_MASK__OUTPUT1_ENABLE_MASK 0xf0
+#define CB_SHADER_MASK__OUTPUT1_ENABLE__SHIFT 0x4
+#define CB_SHADER_MASK__OUTPUT2_ENABLE_MASK 0xf00
+#define CB_SHADER_MASK__OUTPUT2_ENABLE__SHIFT 0x8
+#define CB_SHADER_MASK__OUTPUT3_ENABLE_MASK 0xf000
+#define CB_SHADER_MASK__OUTPUT3_ENABLE__SHIFT 0xc
+#define CB_SHADER_MASK__OUTPUT4_ENABLE_MASK 0xf0000
+#define CB_SHADER_MASK__OUTPUT4_ENABLE__SHIFT 0x10
+#define CB_SHADER_MASK__OUTPUT5_ENABLE_MASK 0xf00000
+#define CB_SHADER_MASK__OUTPUT5_ENABLE__SHIFT 0x14
+#define CB_SHADER_MASK__OUTPUT6_ENABLE_MASK 0xf000000
+#define CB_SHADER_MASK__OUTPUT6_ENABLE__SHIFT 0x18
+#define CB_SHADER_MASK__OUTPUT7_ENABLE_MASK 0xf0000000
+#define CB_SHADER_MASK__OUTPUT7_ENABLE__SHIFT 0x1c
+#define CB_HW_CONTROL__CM_CACHE_EVICT_POINT_MASK 0xf
+#define CB_HW_CONTROL__CM_CACHE_EVICT_POINT__SHIFT 0x0
+#define CB_HW_CONTROL__FC_CACHE_EVICT_POINT_MASK 0x3c0
+#define CB_HW_CONTROL__FC_CACHE_EVICT_POINT__SHIFT 0x6
+#define CB_HW_CONTROL__CC_CACHE_EVICT_POINT_MASK 0xf000
+#define CB_HW_CONTROL__CC_CACHE_EVICT_POINT__SHIFT 0xc
+#define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE_MASK 0x10000
+#define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE__SHIFT 0x10
+#define CB_HW_CONTROL__DISABLE_INTNORM_LE11BPC_CLAMPING_MASK 0x40000
+#define CB_HW_CONTROL__DISABLE_INTNORM_LE11BPC_CLAMPING__SHIFT 0x12
+#define CB_HW_CONTROL__FORCE_NEEDS_DST_MASK 0x80000
+#define CB_HW_CONTROL__FORCE_NEEDS_DST__SHIFT 0x13
+#define CB_HW_CONTROL__FORCE_ALWAYS_TOGGLE_MASK 0x100000
+#define CB_HW_CONTROL__FORCE_ALWAYS_TOGGLE__SHIFT 0x14
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_RESULT_EQ_DEST_MASK 0x200000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_RESULT_EQ_DEST__SHIFT 0x15
+#define CB_HW_CONTROL__DISABLE_FULL_WRITE_MASK_MASK 0x400000
+#define CB_HW_CONTROL__DISABLE_FULL_WRITE_MASK__SHIFT 0x16
+#define CB_HW_CONTROL__DISABLE_RESOLVE_OPT_FOR_SINGLE_FRAG_MASK 0x800000
+#define CB_HW_CONTROL__DISABLE_RESOLVE_OPT_FOR_SINGLE_FRAG__SHIFT 0x17
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DONT_RD_DST_MASK 0x1000000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DONT_RD_DST__SHIFT 0x18
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_BYPASS_MASK 0x2000000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_BYPASS__SHIFT 0x19
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DISCARD_PIXEL_MASK 0x4000000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DISCARD_PIXEL__SHIFT 0x1a
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_WHEN_DISABLED_SRCALPHA_IS_USED_MASK 0x8000000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_WHEN_DISABLED_SRCALPHA_IS_USED__SHIFT 0x1b
+#define CB_HW_CONTROL__PRIORITIZE_FC_WR_OVER_FC_RD_ON_CMASK_CONFLICT_MASK 0x10000000
+#define CB_HW_CONTROL__PRIORITIZE_FC_WR_OVER_FC_RD_ON_CMASK_CONFLICT__SHIFT 0x1c
+#define CB_HW_CONTROL__PRIORITIZE_FC_EVICT_OVER_FOP_RD_ON_BANK_CONFLICT_MASK 0x20000000
+#define CB_HW_CONTROL__PRIORITIZE_FC_EVICT_OVER_FOP_RD_ON_BANK_CONFLICT__SHIFT 0x1d
+#define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT_MASK 0x40000000
+#define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT__SHIFT 0x1e
+#define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE_MASK 0x80000000
+#define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE__SHIFT 0x1f
+#define CB_HW_CONTROL_1__CM_CACHE_NUM_TAGS_MASK 0x1f
+#define CB_HW_CONTROL_1__CM_CACHE_NUM_TAGS__SHIFT 0x0
+#define CB_HW_CONTROL_1__FC_CACHE_NUM_TAGS_MASK 0x7e0
+#define CB_HW_CONTROL_1__FC_CACHE_NUM_TAGS__SHIFT 0x5
+#define CB_HW_CONTROL_1__CC_CACHE_NUM_TAGS_MASK 0x1f800
+#define CB_HW_CONTROL_1__CC_CACHE_NUM_TAGS__SHIFT 0xb
+#define CB_HW_CONTROL_1__CM_TILE_FIFO_DEPTH_MASK 0x3fe0000
+#define CB_HW_CONTROL_1__CM_TILE_FIFO_DEPTH__SHIFT 0x11
+#define CB_HW_CONTROL_1__CHICKEN_BITS_MASK 0xfc000000
+#define CB_HW_CONTROL_1__CHICKEN_BITS__SHIFT 0x1a
+#define CB_HW_CONTROL_2__CC_EVEN_ODD_FIFO_DEPTH_MASK 0xff
+#define CB_HW_CONTROL_2__CC_EVEN_ODD_FIFO_DEPTH__SHIFT 0x0
+#define CB_HW_CONTROL_2__FC_RDLAT_TILE_FIFO_DEPTH_MASK 0x7f00
+#define CB_HW_CONTROL_2__FC_RDLAT_TILE_FIFO_DEPTH__SHIFT 0x8
+#define CB_HW_CONTROL_2__FC_RDLAT_QUAD_FIFO_DEPTH_MASK 0x7f8000
+#define CB_HW_CONTROL_2__FC_RDLAT_QUAD_FIFO_DEPTH__SHIFT 0xf
+#define CB_HW_CONTROL_2__DRR_ASSUMED_FIFO_DEPTH_DIV8_MASK 0xf000000
+#define CB_HW_CONTROL_2__DRR_ASSUMED_FIFO_DEPTH_DIV8__SHIFT 0x18
+#define CB_HW_CONTROL_2__CHICKEN_BITS_MASK 0xf0000000
+#define CB_HW_CONTROL_2__CHICKEN_BITS__SHIFT 0x1c
+#define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL_MASK 0x1
+#define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL__SHIFT 0x0
+#define CB_HW_CONTROL_3__RAM_ADDRESS_CONFLICTS_DISALLOWED_MASK 0x2
+#define CB_HW_CONTROL_3__RAM_ADDRESS_CONFLICTS_DISALLOWED__SHIFT 0x1
+#define CB_HW_CONTROL_3__DISABLE_FAST_CLEAR_FETCH_OPT_MASK 0x4
+#define CB_HW_CONTROL_3__DISABLE_FAST_CLEAR_FETCH_OPT__SHIFT 0x2
+#define CB_HW_CONTROL_3__DISABLE_QUAD_MARKER_DROP_STOP_MASK 0x8
+#define CB_HW_CONTROL_3__DISABLE_QUAD_MARKER_DROP_STOP__SHIFT 0x3
+#define CB_HW_CONTROL_3__DISABLE_OVERWRITE_COMBINER_CAM_CLR_MASK 0x10
+#define CB_HW_CONTROL_3__DISABLE_OVERWRITE_COMBINER_CAM_CLR__SHIFT 0x4
+#define CB_HW_CONTROL_3__DISABLE_CC_CACHE_OVWR_STATUS_ACCUM_MASK 0x20
+#define CB_HW_CONTROL_3__DISABLE_CC_CACHE_OVWR_STATUS_ACCUM__SHIFT 0x5
+#define CB_HW_CONTROL_3__DISABLE_CC_CACHE_PANIC_GATING_MASK 0x80
+#define CB_HW_CONTROL_3__DISABLE_CC_CACHE_PANIC_GATING__SHIFT 0x7
+#define CB_HW_CONTROL_3__DISABLE_OVERWRITE_COMBINER_TARGET_MASK_VALIDATION_MASK 0x100
+#define CB_HW_CONTROL_3__DISABLE_OVERWRITE_COMBINER_TARGET_MASK_VALIDATION__SHIFT 0x8
+#define CB_HW_CONTROL_3__SPLIT_ALL_FAST_MODE_TRANSFERS_MASK 0x200
+#define CB_HW_CONTROL_3__SPLIT_ALL_FAST_MODE_TRANSFERS__SHIFT 0x9
+#define CB_HW_CONTROL_3__DISABLE_SHADER_BLEND_OPTS_MASK 0x400
+#define CB_HW_CONTROL_3__DISABLE_SHADER_BLEND_OPTS__SHIFT 0xa
+#define CB_HW_CONTROL_3__DISABLE_CMASK_LAST_QUAD_INSERTION_MASK 0x800
+#define CB_HW_CONTROL_3__DISABLE_CMASK_LAST_QUAD_INSERTION__SHIFT 0xb
+#define CB_HW_CONTROL_3__DISABLE_ROP3_FIXES_OF_BUG_511967_MASK 0x1000
+#define CB_HW_CONTROL_3__DISABLE_ROP3_FIXES_OF_BUG_511967__SHIFT 0xc
+#define CB_HW_CONTROL_3__DISABLE_ROP3_FIXES_OF_BUG_520657_MASK 0x2000
+#define CB_HW_CONTROL_3__DISABLE_ROP3_FIXES_OF_BUG_520657__SHIFT 0xd
+#define CB_DCC_CONFIG__OVERWRITE_COMBINER_DEPTH_MASK 0x1f
+#define CB_DCC_CONFIG__OVERWRITE_COMBINER_DEPTH__SHIFT 0x0
+#define CB_DCC_CONFIG__OVERWRITE_COMBINER_DISABLE_MASK 0x20
+#define CB_DCC_CONFIG__OVERWRITE_COMBINER_DISABLE__SHIFT 0x5
+#define CB_DCC_CONFIG__OVERWRITE_COMBINER_CC_POP_DISABLE_MASK 0x40
+#define CB_DCC_CONFIG__OVERWRITE_COMBINER_CC_POP_DISABLE__SHIFT 0x6
+#define CB_DCC_CONFIG__FC_RDLAT_KEYID_FIFO_DEPTH_MASK 0xff00
+#define CB_DCC_CONFIG__FC_RDLAT_KEYID_FIFO_DEPTH__SHIFT 0x8
+#define CB_DCC_CONFIG__READ_RETURN_SKID_FIFO_DEPTH_MASK 0x7f0000
+#define CB_DCC_CONFIG__READ_RETURN_SKID_FIFO_DEPTH__SHIFT 0x10
+#define CB_DCC_CONFIG__DCC_CACHE_EVICT_POINT_MASK 0xf000000
+#define CB_DCC_CONFIG__DCC_CACHE_EVICT_POINT__SHIFT 0x18
+#define CB_DCC_CONFIG__DCC_CACHE_NUM_TAGS_MASK 0xf0000000
+#define CB_DCC_CONFIG__DCC_CACHE_NUM_TAGS__SHIFT 0x1c
+#define CB_PERFCOUNTER_FILTER__OP_FILTER_ENABLE_MASK 0x1
+#define CB_PERFCOUNTER_FILTER__OP_FILTER_ENABLE__SHIFT 0x0
+#define CB_PERFCOUNTER_FILTER__OP_FILTER_SEL_MASK 0xe
+#define CB_PERFCOUNTER_FILTER__OP_FILTER_SEL__SHIFT 0x1
+#define CB_PERFCOUNTER_FILTER__FORMAT_FILTER_ENABLE_MASK 0x10
+#define CB_PERFCOUNTER_FILTER__FORMAT_FILTER_ENABLE__SHIFT 0x4
+#define CB_PERFCOUNTER_FILTER__FORMAT_FILTER_SEL_MASK 0x3e0
+#define CB_PERFCOUNTER_FILTER__FORMAT_FILTER_SEL__SHIFT 0x5
+#define CB_PERFCOUNTER_FILTER__CLEAR_FILTER_ENABLE_MASK 0x400
+#define CB_PERFCOUNTER_FILTER__CLEAR_FILTER_ENABLE__SHIFT 0xa
+#define CB_PERFCOUNTER_FILTER__CLEAR_FILTER_SEL_MASK 0x800
+#define CB_PERFCOUNTER_FILTER__CLEAR_FILTER_SEL__SHIFT 0xb
+#define CB_PERFCOUNTER_FILTER__MRT_FILTER_ENABLE_MASK 0x1000
+#define CB_PERFCOUNTER_FILTER__MRT_FILTER_ENABLE__SHIFT 0xc
+#define CB_PERFCOUNTER_FILTER__MRT_FILTER_SEL_MASK 0xe000
+#define CB_PERFCOUNTER_FILTER__MRT_FILTER_SEL__SHIFT 0xd
+#define CB_PERFCOUNTER_FILTER__NUM_SAMPLES_FILTER_ENABLE_MASK 0x20000
+#define CB_PERFCOUNTER_FILTER__NUM_SAMPLES_FILTER_ENABLE__SHIFT 0x11
+#define CB_PERFCOUNTER_FILTER__NUM_SAMPLES_FILTER_SEL_MASK 0x1c0000
+#define CB_PERFCOUNTER_FILTER__NUM_SAMPLES_FILTER_SEL__SHIFT 0x12
+#define CB_PERFCOUNTER_FILTER__NUM_FRAGMENTS_FILTER_ENABLE_MASK 0x200000
+#define CB_PERFCOUNTER_FILTER__NUM_FRAGMENTS_FILTER_ENABLE__SHIFT 0x15
+#define CB_PERFCOUNTER_FILTER__NUM_FRAGMENTS_FILTER_SEL_MASK 0xc00000
+#define CB_PERFCOUNTER_FILTER__NUM_FRAGMENTS_FILTER_SEL__SHIFT 0x16
+#define CB_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x1ff
+#define CB_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define CB_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x7fc00
+#define CB_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define CB_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define CB_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define CB_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define CB_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define CB_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define CB_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x1ff
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x7fc00
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define CB_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x1ff
+#define CB_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define CB_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define CB_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define CB_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x1ff
+#define CB_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define CB_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define CB_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define CB_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x1ff
+#define CB_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define CB_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define CB_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define CB_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CB_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CB_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CB_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CB_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CB_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CB_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CB_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CB_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CB_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CB_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CB_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CB_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CB_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CB_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CB_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CB_CGTT_SCLK_CTRL__ON_DELAY_MASK 0xf
+#define CB_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CB_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CB_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CB_DEBUG_BUS_1__CB_BUSY_MASK 0x1
+#define CB_DEBUG_BUS_1__CB_BUSY__SHIFT 0x0
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALID_READY_MASK 0x2
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALID_READY__SHIFT 0x1
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALID_READYB_MASK 0x4
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALID_READYB__SHIFT 0x2
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALIDB_READY_MASK 0x8
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALIDB_READY__SHIFT 0x3
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALIDB_READYB_MASK 0x10
+#define CB_DEBUG_BUS_1__DB_CB_TILE_VALIDB_READYB__SHIFT 0x4
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALID_READY_MASK 0x20
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALID_READY__SHIFT 0x5
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALID_READYB_MASK 0x40
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALID_READYB__SHIFT 0x6
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALIDB_READY_MASK 0x80
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALIDB_READY__SHIFT 0x7
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALIDB_READYB_MASK 0x100
+#define CB_DEBUG_BUS_1__DB_CB_LQUAD_VALIDB_READYB__SHIFT 0x8
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALID_READY_MASK 0x200
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALID_READY__SHIFT 0x9
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALID_READYB_MASK 0x400
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALID_READYB__SHIFT 0xa
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALIDB_READY_MASK 0x800
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALIDB_READY__SHIFT 0xb
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALIDB_READYB_MASK 0x1000
+#define CB_DEBUG_BUS_1__CB_TAP_WRREQ_VALIDB_READYB__SHIFT 0xc
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALID_READY_MASK 0x2000
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALID_READY__SHIFT 0xd
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALID_READYB_MASK 0x4000
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALID_READYB__SHIFT 0xe
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALIDB_READY_MASK 0x8000
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALIDB_READY__SHIFT 0xf
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALIDB_READYB_MASK 0x10000
+#define CB_DEBUG_BUS_1__CB_TAP_RDREQ_VALIDB_READYB__SHIFT 0x10
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALID_READY_MASK 0x20000
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALID_READY__SHIFT 0x11
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALID_READYB_MASK 0x40000
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALID_READYB__SHIFT 0x12
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALIDB_READY_MASK 0x80000
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALIDB_READY__SHIFT 0x13
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALIDB_READYB_MASK 0x100000
+#define CB_DEBUG_BUS_1__CM_FC_TILE_VALIDB_READYB__SHIFT 0x14
+#define CB_DEBUG_BUS_1__FC_CLEAR_QUAD_VALID_READY_MASK 0x200000
+#define CB_DEBUG_BUS_1__FC_CLEAR_QUAD_VALID_READY__SHIFT 0x15
+#define CB_DEBUG_BUS_1__FC_CLEAR_QUAD_VALID_READYB_MASK 0x400000
+#define CB_DEBUG_BUS_1__FC_CLEAR_QUAD_VALID_READYB__SHIFT 0x16
+#define CB_DEBUG_BUS_1__FC_CLEAR_QUAD_VALIDB_READY_MASK 0x800000
+#define CB_DEBUG_BUS_1__FC_CLEAR_QUAD_VALIDB_READY__SHIFT 0x17
+#define CB_DEBUG_BUS_2__FC_CLEAR_QUAD_VALIDB_READYB_MASK 0x1
+#define CB_DEBUG_BUS_2__FC_CLEAR_QUAD_VALIDB_READYB__SHIFT 0x0
+#define CB_DEBUG_BUS_2__FC_QUAD_RESIDENCY_STALL_MASK 0x2
+#define CB_DEBUG_BUS_2__FC_QUAD_RESIDENCY_STALL__SHIFT 0x1
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALID_READY_MASK 0x4
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALID_READY__SHIFT 0x2
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALID_READYB_MASK 0x8
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALID_READYB__SHIFT 0x3
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALIDB_READY_MASK 0x10
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALIDB_READY__SHIFT 0x4
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALIDB_READYB_MASK 0x20
+#define CB_DEBUG_BUS_2__FC_CC_QUADFRAG_VALIDB_READYB__SHIFT 0x5
+#define CB_DEBUG_BUS_2__FOP_IN_VALID_READY_MASK 0x40
+#define CB_DEBUG_BUS_2__FOP_IN_VALID_READY__SHIFT 0x6
+#define CB_DEBUG_BUS_2__FOP_IN_VALID_READYB_MASK 0x80
+#define CB_DEBUG_BUS_2__FOP_IN_VALID_READYB__SHIFT 0x7
+#define CB_DEBUG_BUS_2__FOP_IN_VALIDB_READY_MASK 0x100
+#define CB_DEBUG_BUS_2__FOP_IN_VALIDB_READY__SHIFT 0x8
+#define CB_DEBUG_BUS_2__FOP_IN_VALIDB_READYB_MASK 0x200
+#define CB_DEBUG_BUS_2__FOP_IN_VALIDB_READYB__SHIFT 0x9
+#define CB_DEBUG_BUS_2__FOP_FMASK_RAW_STALL_MASK 0x400
+#define CB_DEBUG_BUS_2__FOP_FMASK_RAW_STALL__SHIFT 0xa
+#define CB_DEBUG_BUS_2__FOP_FMASK_BYPASS_STALL_MASK 0x800
+#define CB_DEBUG_BUS_2__FOP_FMASK_BYPASS_STALL__SHIFT 0xb
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALID_READY_MASK 0x1000
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALID_READY__SHIFT 0xc
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALID_READYB_MASK 0x2000
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALID_READYB__SHIFT 0xd
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALIDB_READY_MASK 0x4000
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALIDB_READY__SHIFT 0xe
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALIDB_READYB_MASK 0x8000
+#define CB_DEBUG_BUS_2__CC_IB_TB_FRAG_VALIDB_READYB__SHIFT 0xf
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALID_READY_MASK 0x10000
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALID_READY__SHIFT 0x10
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALID_READYB_MASK 0x20000
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALID_READYB__SHIFT 0x11
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALIDB_READY_MASK 0x40000
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALIDB_READY__SHIFT 0x12
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALIDB_READYB_MASK 0x80000
+#define CB_DEBUG_BUS_2__CC_IB_SR_FRAG_VALIDB_READYB__SHIFT 0x13
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALID_READY_MASK 0x100000
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALID_READY__SHIFT 0x14
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALID_READYB_MASK 0x200000
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALID_READYB__SHIFT 0x15
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALIDB_READY_MASK 0x400000
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALIDB_READY__SHIFT 0x16
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALIDB_READYB_MASK 0x800000
+#define CB_DEBUG_BUS_2__CC_RB_BC_EVENFRAG_VALIDB_READYB__SHIFT 0x17
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALID_READY_MASK 0x1
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALID_READY__SHIFT 0x0
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALID_READYB_MASK 0x2
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALID_READYB__SHIFT 0x1
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALIDB_READY_MASK 0x4
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALIDB_READY__SHIFT 0x2
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALIDB_READYB_MASK 0x8
+#define CB_DEBUG_BUS_3__CC_RB_BC_ODDFRAG_VALIDB_READYB__SHIFT 0x3
+#define CB_DEBUG_BUS_3__CC_BC_CS_FRAG_VALID_MASK 0x10
+#define CB_DEBUG_BUS_3__CC_BC_CS_FRAG_VALID__SHIFT 0x4
+#define CB_DEBUG_BUS_3__CC_SF_FULL_MASK 0x20
+#define CB_DEBUG_BUS_3__CC_SF_FULL__SHIFT 0x5
+#define CB_DEBUG_BUS_3__CC_RB_FULL_MASK 0x40
+#define CB_DEBUG_BUS_3__CC_RB_FULL__SHIFT 0x6
+#define CB_DEBUG_BUS_3__CC_EVENFIFO_QUAD_RESIDENCY_STALL_MASK 0x80
+#define CB_DEBUG_BUS_3__CC_EVENFIFO_QUAD_RESIDENCY_STALL__SHIFT 0x7
+#define CB_DEBUG_BUS_3__CC_ODDFIFO_QUAD_RESIDENCY_STALL_MASK 0x100
+#define CB_DEBUG_BUS_3__CC_ODDFIFO_QUAD_RESIDENCY_STALL__SHIFT 0x8
+#define CB_DEBUG_BUS_3__CM_TQ_FULL_MASK 0x200
+#define CB_DEBUG_BUS_3__CM_TQ_FULL__SHIFT 0x9
+#define CB_DEBUG_BUS_3__CM_TILE_RESIDENCY_STALL_MASK 0x400
+#define CB_DEBUG_BUS_3__CM_TILE_RESIDENCY_STALL__SHIFT 0xa
+#define CB_DEBUG_BUS_3__LQUAD_NO_TILE_MASK 0x800
+#define CB_DEBUG_BUS_3__LQUAD_NO_TILE__SHIFT 0xb
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_R_MASK 0x1000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_R__SHIFT 0xc
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_AR_MASK 0x2000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_AR__SHIFT 0xd
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_GR_MASK 0x4000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_GR__SHIFT 0xe
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_ABGR_MASK 0x8000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_32_ABGR__SHIFT 0xf
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_FP16_ABGR_MASK 0x10000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_FP16_ABGR__SHIFT 0x10
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_SIGNED16_ABGR_MASK 0x20000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_SIGNED16_ABGR__SHIFT 0x11
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_UNSIGNED16_ABGR_MASK 0x40000
+#define CB_DEBUG_BUS_3__LQUAD_FORMAT_IS_EXPORT_UNSIGNED16_ABGR__SHIFT 0x12
+#define CB_DEBUG_BUS_3__CM_CACHE_HIT_MASK 0x80000
+#define CB_DEBUG_BUS_3__CM_CACHE_HIT__SHIFT 0x13
+#define CB_DEBUG_BUS_3__CM_CACHE_TAG_MISS_MASK 0x100000
+#define CB_DEBUG_BUS_3__CM_CACHE_TAG_MISS__SHIFT 0x14
+#define CB_DEBUG_BUS_3__CM_CACHE_SECTOR_MISS_MASK 0x200000
+#define CB_DEBUG_BUS_3__CM_CACHE_SECTOR_MISS__SHIFT 0x15
+#define CB_DEBUG_BUS_3__CM_CACHE_REEVICTION_STALL_MASK 0x400000
+#define CB_DEBUG_BUS_3__CM_CACHE_REEVICTION_STALL__SHIFT 0x16
+#define CB_DEBUG_BUS_3__CM_CACHE_EVICT_NONZERO_INFLIGHT_STALL_MASK 0x800000
+#define CB_DEBUG_BUS_3__CM_CACHE_EVICT_NONZERO_INFLIGHT_STALL__SHIFT 0x17
+#define CB_DEBUG_BUS_4__CM_CACHE_REPLACE_PENDING_EVICT_STALL_MASK 0x1
+#define CB_DEBUG_BUS_4__CM_CACHE_REPLACE_PENDING_EVICT_STALL__SHIFT 0x0
+#define CB_DEBUG_BUS_4__CM_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL_MASK 0x2
+#define CB_DEBUG_BUS_4__CM_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL__SHIFT 0x1
+#define CB_DEBUG_BUS_4__CM_CACHE_READ_OUTPUT_STALL_MASK 0x4
+#define CB_DEBUG_BUS_4__CM_CACHE_READ_OUTPUT_STALL__SHIFT 0x2
+#define CB_DEBUG_BUS_4__CM_CACHE_WRITE_OUTPUT_STALL_MASK 0x8
+#define CB_DEBUG_BUS_4__CM_CACHE_WRITE_OUTPUT_STALL__SHIFT 0x3
+#define CB_DEBUG_BUS_4__CM_CACHE_ACK_OUTPUT_STALL_MASK 0x10
+#define CB_DEBUG_BUS_4__CM_CACHE_ACK_OUTPUT_STALL__SHIFT 0x4
+#define CB_DEBUG_BUS_4__CM_CACHE_STALL_MASK 0x20
+#define CB_DEBUG_BUS_4__CM_CACHE_STALL__SHIFT 0x5
+#define CB_DEBUG_BUS_4__FC_CACHE_HIT_MASK 0x40
+#define CB_DEBUG_BUS_4__FC_CACHE_HIT__SHIFT 0x6
+#define CB_DEBUG_BUS_4__FC_CACHE_TAG_MISS_MASK 0x80
+#define CB_DEBUG_BUS_4__FC_CACHE_TAG_MISS__SHIFT 0x7
+#define CB_DEBUG_BUS_4__FC_CACHE_SECTOR_MISS_MASK 0x100
+#define CB_DEBUG_BUS_4__FC_CACHE_SECTOR_MISS__SHIFT 0x8
+#define CB_DEBUG_BUS_4__FC_CACHE_REEVICTION_STALL_MASK 0x200
+#define CB_DEBUG_BUS_4__FC_CACHE_REEVICTION_STALL__SHIFT 0x9
+#define CB_DEBUG_BUS_4__FC_CACHE_EVICT_NONZERO_INFLIGHT_STALL_MASK 0x400
+#define CB_DEBUG_BUS_4__FC_CACHE_EVICT_NONZERO_INFLIGHT_STALL__SHIFT 0xa
+#define CB_DEBUG_BUS_4__FC_CACHE_REPLACE_PENDING_EVICT_STALL_MASK 0x800
+#define CB_DEBUG_BUS_4__FC_CACHE_REPLACE_PENDING_EVICT_STALL__SHIFT 0xb
+#define CB_DEBUG_BUS_4__FC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL_MASK 0x1000
+#define CB_DEBUG_BUS_4__FC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL__SHIFT 0xc
+#define CB_DEBUG_BUS_4__FC_CACHE_READ_OUTPUT_STALL_MASK 0x2000
+#define CB_DEBUG_BUS_4__FC_CACHE_READ_OUTPUT_STALL__SHIFT 0xd
+#define CB_DEBUG_BUS_4__FC_CACHE_WRITE_OUTPUT_STALL_MASK 0x4000
+#define CB_DEBUG_BUS_4__FC_CACHE_WRITE_OUTPUT_STALL__SHIFT 0xe
+#define CB_DEBUG_BUS_4__FC_CACHE_ACK_OUTPUT_STALL_MASK 0x8000
+#define CB_DEBUG_BUS_4__FC_CACHE_ACK_OUTPUT_STALL__SHIFT 0xf
+#define CB_DEBUG_BUS_4__FC_CACHE_STALL_MASK 0x10000
+#define CB_DEBUG_BUS_4__FC_CACHE_STALL__SHIFT 0x10
+#define CB_DEBUG_BUS_4__CC_CACHE_HIT_MASK 0x20000
+#define CB_DEBUG_BUS_4__CC_CACHE_HIT__SHIFT 0x11
+#define CB_DEBUG_BUS_4__CC_CACHE_TAG_MISS_MASK 0x40000
+#define CB_DEBUG_BUS_4__CC_CACHE_TAG_MISS__SHIFT 0x12
+#define CB_DEBUG_BUS_4__CC_CACHE_SECTOR_MISS_MASK 0x80000
+#define CB_DEBUG_BUS_4__CC_CACHE_SECTOR_MISS__SHIFT 0x13
+#define CB_DEBUG_BUS_4__CC_CACHE_REEVICTION_STALL_MASK 0x100000
+#define CB_DEBUG_BUS_4__CC_CACHE_REEVICTION_STALL__SHIFT 0x14
+#define CB_DEBUG_BUS_4__CC_CACHE_EVICT_NONZERO_INFLIGHT_STALL_MASK 0x200000
+#define CB_DEBUG_BUS_4__CC_CACHE_EVICT_NONZERO_INFLIGHT_STALL__SHIFT 0x15
+#define CB_DEBUG_BUS_4__CC_CACHE_REPLACE_PENDING_EVICT_STALL_MASK 0x400000
+#define CB_DEBUG_BUS_4__CC_CACHE_REPLACE_PENDING_EVICT_STALL__SHIFT 0x16
+#define CB_DEBUG_BUS_4__CC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL_MASK 0x800000
+#define CB_DEBUG_BUS_4__CC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL__SHIFT 0x17
+#define CB_DEBUG_BUS_5__CC_CACHE_READ_OUTPUT_STALL_MASK 0x1
+#define CB_DEBUG_BUS_5__CC_CACHE_READ_OUTPUT_STALL__SHIFT 0x0
+#define CB_DEBUG_BUS_5__CC_CACHE_WRITE_OUTPUT_STALL_MASK 0x2
+#define CB_DEBUG_BUS_5__CC_CACHE_WRITE_OUTPUT_STALL__SHIFT 0x1
+#define CB_DEBUG_BUS_5__CC_CACHE_ACK_OUTPUT_STALL_MASK 0x4
+#define CB_DEBUG_BUS_5__CC_CACHE_ACK_OUTPUT_STALL__SHIFT 0x2
+#define CB_DEBUG_BUS_5__CC_CACHE_STALL_MASK 0x8
+#define CB_DEBUG_BUS_5__CC_CACHE_STALL__SHIFT 0x3
+#define CB_DEBUG_BUS_5__CC_CACHE_WA_TO_RMW_CONVERSION_MASK 0x10
+#define CB_DEBUG_BUS_5__CC_CACHE_WA_TO_RMW_CONVERSION__SHIFT 0x4
+#define CB_DEBUG_BUS_5__CM_CACHE_FLUSH_MASK 0x20
+#define CB_DEBUG_BUS_5__CM_CACHE_FLUSH__SHIFT 0x5
+#define CB_DEBUG_BUS_5__CM_CACHE_TAGS_FLUSHED_MASK 0x40
+#define CB_DEBUG_BUS_5__CM_CACHE_TAGS_FLUSHED__SHIFT 0x6
+#define CB_DEBUG_BUS_5__CM_CACHE_SECTORS_FLUSHED_MASK 0x80
+#define CB_DEBUG_BUS_5__CM_CACHE_SECTORS_FLUSHED__SHIFT 0x7
+#define CB_DEBUG_BUS_5__CM_CACHE_DIRTY_SECTORS_FLUSHED_MASK 0x100
+#define CB_DEBUG_BUS_5__CM_CACHE_DIRTY_SECTORS_FLUSHED__SHIFT 0x8
+#define CB_DEBUG_BUS_5__FC_CACHE_FLUSH_MASK 0x200
+#define CB_DEBUG_BUS_5__FC_CACHE_FLUSH__SHIFT 0x9
+#define CB_DEBUG_BUS_5__FC_CACHE_TAGS_FLUSHED_MASK 0x400
+#define CB_DEBUG_BUS_5__FC_CACHE_TAGS_FLUSHED__SHIFT 0xa
+#define CB_DEBUG_BUS_5__FC_CACHE_SECTORS_FLUSHED_MASK 0x3800
+#define CB_DEBUG_BUS_5__FC_CACHE_SECTORS_FLUSHED__SHIFT 0xb
+#define CB_DEBUG_BUS_5__FC_CACHE_DIRTY_SECTORS_FLUSHED_MASK 0x1c000
+#define CB_DEBUG_BUS_5__FC_CACHE_DIRTY_SECTORS_FLUSHED__SHIFT 0xe
+#define CB_DEBUG_BUS_5__CC_CACHE_FLUSH_MASK 0x20000
+#define CB_DEBUG_BUS_5__CC_CACHE_FLUSH__SHIFT 0x11
+#define CB_DEBUG_BUS_5__CC_CACHE_TAGS_FLUSHED_MASK 0x40000
+#define CB_DEBUG_BUS_5__CC_CACHE_TAGS_FLUSHED__SHIFT 0x12
+#define CB_DEBUG_BUS_5__CC_CACHE_SECTORS_FLUSHED_MASK 0x380000
+#define CB_DEBUG_BUS_5__CC_CACHE_SECTORS_FLUSHED__SHIFT 0x13
+#define CB_DEBUG_BUS_6__CC_CACHE_DIRTY_SECTORS_FLUSHED_MASK 0x7
+#define CB_DEBUG_BUS_6__CC_CACHE_DIRTY_SECTORS_FLUSHED__SHIFT 0x0
+#define CB_DEBUG_BUS_6__CM_MC_READ_REQUEST_MASK 0x8
+#define CB_DEBUG_BUS_6__CM_MC_READ_REQUEST__SHIFT 0x3
+#define CB_DEBUG_BUS_6__FC_MC_READ_REQUEST_MASK 0x10
+#define CB_DEBUG_BUS_6__FC_MC_READ_REQUEST__SHIFT 0x4
+#define CB_DEBUG_BUS_6__CC_MC_READ_REQUEST_MASK 0x20
+#define CB_DEBUG_BUS_6__CC_MC_READ_REQUEST__SHIFT 0x5
+#define CB_DEBUG_BUS_6__CM_MC_WRITE_REQUEST_MASK 0x40
+#define CB_DEBUG_BUS_6__CM_MC_WRITE_REQUEST__SHIFT 0x6
+#define CB_DEBUG_BUS_6__FC_MC_WRITE_REQUEST_MASK 0x80
+#define CB_DEBUG_BUS_6__FC_MC_WRITE_REQUEST__SHIFT 0x7
+#define CB_DEBUG_BUS_6__CC_MC_WRITE_REQUEST_MASK 0x100
+#define CB_DEBUG_BUS_6__CC_MC_WRITE_REQUEST__SHIFT 0x8
+#define CB_DEBUG_BUS_6__CM_MC_READ_REQUESTS_IN_FLIGHT_MASK 0x1fe00
+#define CB_DEBUG_BUS_6__CM_MC_READ_REQUESTS_IN_FLIGHT__SHIFT 0x9
+#define CB_DEBUG_BUS_7__FC_MC_READ_REQUESTS_IN_FLIGHT_MASK 0x7ff
+#define CB_DEBUG_BUS_7__FC_MC_READ_REQUESTS_IN_FLIGHT__SHIFT 0x0
+#define CB_DEBUG_BUS_7__CC_MC_READ_REQUESTS_IN_FLIGHT_MASK 0x1ff800
+#define CB_DEBUG_BUS_7__CC_MC_READ_REQUESTS_IN_FLIGHT__SHIFT 0xb
+#define CB_DEBUG_BUS_8__CM_MC_WRITE_REQUESTS_IN_FLIGHT_MASK 0xff
+#define CB_DEBUG_BUS_8__CM_MC_WRITE_REQUESTS_IN_FLIGHT__SHIFT 0x0
+#define CB_DEBUG_BUS_8__FC_MC_WRITE_REQUESTS_IN_FLIGHT_MASK 0x7ff00
+#define CB_DEBUG_BUS_8__FC_MC_WRITE_REQUESTS_IN_FLIGHT__SHIFT 0x8
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_FMASK_COMPRESSION_DISABLE_MASK 0x80000
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_FMASK_COMPRESSION_DISABLE__SHIFT 0x13
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_FMASK_DECOMPRESS_MASK 0x100000
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_FMASK_DECOMPRESS__SHIFT 0x14
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_ELIMINATE_FAST_CLEAR_MASK 0x200000
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_ELIMINATE_FAST_CLEAR__SHIFT 0x15
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_CLEAR_MASK 0x400000
+#define CB_DEBUG_BUS_8__FC_SEQUENCER_CLEAR__SHIFT 0x16
+#define CB_DEBUG_BUS_9__CC_MC_WRITE_REQUESTS_IN_FLIGHT_MASK 0x3ff
+#define CB_DEBUG_BUS_9__CC_MC_WRITE_REQUESTS_IN_FLIGHT__SHIFT 0x0
+#define CB_DEBUG_BUS_9__CC_SURFACE_SYNC_MASK 0x400
+#define CB_DEBUG_BUS_9__CC_SURFACE_SYNC__SHIFT 0xa
+#define CB_DEBUG_BUS_9__TWO_PROBE_QUAD_FRAGMENT_MASK 0x800
+#define CB_DEBUG_BUS_9__TWO_PROBE_QUAD_FRAGMENT__SHIFT 0xb
+#define CB_DEBUG_BUS_9__EXPORT_32_ABGR_QUAD_FRAGMENT_MASK 0x1000
+#define CB_DEBUG_BUS_9__EXPORT_32_ABGR_QUAD_FRAGMENT__SHIFT 0xc
+#define CB_DEBUG_BUS_9__DUAL_SOURCE_COLOR_QUAD_FRAGMENT_MASK 0x2000
+#define CB_DEBUG_BUS_9__DUAL_SOURCE_COLOR_QUAD_FRAGMENT__SHIFT 0xd
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_QUAD_MASK 0x4000
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_QUAD__SHIFT 0xe
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_PIXEL_MASK 0x78000
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_PIXEL__SHIFT 0xf
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_QUAD_FRAGMENT_MASK 0x80000
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_QUAD_FRAGMENT__SHIFT 0x13
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_TILE_MASK 0x100000
+#define CB_DEBUG_BUS_9__DEBUG_BUS_DRAWN_TILE__SHIFT 0x14
+#define CB_DEBUG_BUS_9__EVENT_ALL_MASK 0x200000
+#define CB_DEBUG_BUS_9__EVENT_ALL__SHIFT 0x15
+#define CB_DEBUG_BUS_9__EVENT_CACHE_FLUSH_TS_MASK 0x400000
+#define CB_DEBUG_BUS_9__EVENT_CACHE_FLUSH_TS__SHIFT 0x16
+#define CB_DEBUG_BUS_9__EVENT_CONTEXT_DONE_MASK 0x800000
+#define CB_DEBUG_BUS_9__EVENT_CONTEXT_DONE__SHIFT 0x17
+#define CB_DEBUG_BUS_10__EVENT_CACHE_FLUSH_MASK 0x1
+#define CB_DEBUG_BUS_10__EVENT_CACHE_FLUSH__SHIFT 0x0
+#define CB_DEBUG_BUS_10__EVENT_CACHE_FLUSH_AND_INV_TS_EVENT_MASK 0x2
+#define CB_DEBUG_BUS_10__EVENT_CACHE_FLUSH_AND_INV_TS_EVENT__SHIFT 0x1
+#define CB_DEBUG_BUS_10__EVENT_CACHE_FLUSH_AND_INV_EVENT_MASK 0x4
+#define CB_DEBUG_BUS_10__EVENT_CACHE_FLUSH_AND_INV_EVENT__SHIFT 0x2
+#define CB_DEBUG_BUS_10__EVENT_FLUSH_AND_INV_CB_DATA_TS_MASK 0x8
+#define CB_DEBUG_BUS_10__EVENT_FLUSH_AND_INV_CB_DATA_TS__SHIFT 0x3
+#define CB_DEBUG_BUS_10__EVENT_FLUSH_AND_INV_CB_META_MASK 0x10
+#define CB_DEBUG_BUS_10__EVENT_FLUSH_AND_INV_CB_META__SHIFT 0x4
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XC_MASK 0x20
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XC__SHIFT 0x5
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XD_MASK 0x40
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XD__SHIFT 0x6
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XE_MASK 0x80
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XE__SHIFT 0x7
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XF_MASK 0x100
+#define CB_DEBUG_BUS_10__CMASK_READ_DATA_0XF__SHIFT 0x8
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XC_MASK 0x200
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XC__SHIFT 0x9
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XD_MASK 0x400
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XD__SHIFT 0xa
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XE_MASK 0x800
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XE__SHIFT 0xb
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XF_MASK 0x1000
+#define CB_DEBUG_BUS_10__CMASK_WRITE_DATA_0XF__SHIFT 0xc
+#define CB_DEBUG_BUS_10__CORE_SCLK_VLD_MASK 0x2000
+#define CB_DEBUG_BUS_10__CORE_SCLK_VLD__SHIFT 0xd
+#define CB_DEBUG_BUS_10__REG_SCLK0_VLD_MASK 0x4000
+#define CB_DEBUG_BUS_10__REG_SCLK0_VLD__SHIFT 0xe
+#define CB_DEBUG_BUS_10__REG_SCLK1_VLD_MASK 0x8000
+#define CB_DEBUG_BUS_10__REG_SCLK1_VLD__SHIFT 0xf
+#define CB_DEBUG_BUS_10__MERGE_TILE_ONLY_VALID_READY_MASK 0x10000
+#define CB_DEBUG_BUS_10__MERGE_TILE_ONLY_VALID_READY__SHIFT 0x10
+#define CB_DEBUG_BUS_10__MERGE_TILE_ONLY_VALID_READYB_MASK 0x20000
+#define CB_DEBUG_BUS_10__MERGE_TILE_ONLY_VALID_READYB__SHIFT 0x11
+#define CB_DEBUG_BUS_10__FC_QUAD_RDLAT_FIFO_FULL_MASK 0x40000
+#define CB_DEBUG_BUS_10__FC_QUAD_RDLAT_FIFO_FULL__SHIFT 0x12
+#define CB_DEBUG_BUS_10__FC_TILE_RDLAT_FIFO_FULL_MASK 0x80000
+#define CB_DEBUG_BUS_10__FC_TILE_RDLAT_FIFO_FULL__SHIFT 0x13
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_1_FRAGMENT_BEFORE_UPDATE_MASK 0x100000
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_1_FRAGMENT_BEFORE_UPDATE__SHIFT 0x14
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_2_FRAGMENTS_BEFORE_UPDATE_MASK 0x200000
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_2_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x15
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_3_FRAGMENTS_BEFORE_UPDATE_MASK 0x400000
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_3_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x16
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_4_FRAGMENTS_BEFORE_UPDATE_MASK 0x800000
+#define CB_DEBUG_BUS_10__FOP_QUAD_HAS_4_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x17
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_5_FRAGMENTS_BEFORE_UPDATE_MASK 0x1
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_5_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x0
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_6_FRAGMENTS_BEFORE_UPDATE_MASK 0x2
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_6_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x1
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_7_FRAGMENTS_BEFORE_UPDATE_MASK 0x4
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_7_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x2
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_8_FRAGMENTS_BEFORE_UPDATE_MASK 0x8
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_8_FRAGMENTS_BEFORE_UPDATE__SHIFT 0x3
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_1_FRAGMENT_AFTER_UPDATE_MASK 0x10
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_1_FRAGMENT_AFTER_UPDATE__SHIFT 0x4
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_2_FRAGMENTS_AFTER_UPDATE_MASK 0x20
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_2_FRAGMENTS_AFTER_UPDATE__SHIFT 0x5
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_3_FRAGMENTS_AFTER_UPDATE_MASK 0x40
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_3_FRAGMENTS_AFTER_UPDATE__SHIFT 0x6
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_4_FRAGMENTS_AFTER_UPDATE_MASK 0x80
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_4_FRAGMENTS_AFTER_UPDATE__SHIFT 0x7
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_5_FRAGMENTS_AFTER_UPDATE_MASK 0x100
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_5_FRAGMENTS_AFTER_UPDATE__SHIFT 0x8
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_6_FRAGMENTS_AFTER_UPDATE_MASK 0x200
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_6_FRAGMENTS_AFTER_UPDATE__SHIFT 0x9
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_7_FRAGMENTS_AFTER_UPDATE_MASK 0x400
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_7_FRAGMENTS_AFTER_UPDATE__SHIFT 0xa
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_8_FRAGMENTS_AFTER_UPDATE_MASK 0x800
+#define CB_DEBUG_BUS_11__FOP_QUAD_HAS_8_FRAGMENTS_AFTER_UPDATE__SHIFT 0xb
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_1_FRAGMENT_MASK 0x1000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_1_FRAGMENT__SHIFT 0xc
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_2_FRAGMENTS_MASK 0x2000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_2_FRAGMENTS__SHIFT 0xd
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_3_FRAGMENTS_MASK 0x4000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_3_FRAGMENTS__SHIFT 0xe
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_4_FRAGMENTS_MASK 0x8000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_4_FRAGMENTS__SHIFT 0xf
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_5_FRAGMENTS_MASK 0x10000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_5_FRAGMENTS__SHIFT 0x10
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_6_FRAGMENTS_MASK 0x20000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_6_FRAGMENTS__SHIFT 0x11
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_7_FRAGMENTS_MASK 0x40000
+#define CB_DEBUG_BUS_11__FOP_QUAD_ADDED_7_FRAGMENTS__SHIFT 0x12
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_1_FRAGMENT_MASK 0x80000
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_1_FRAGMENT__SHIFT 0x13
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_2_FRAGMENTS_MASK 0x100000
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_2_FRAGMENTS__SHIFT 0x14
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_3_FRAGMENTS_MASK 0x200000
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_3_FRAGMENTS__SHIFT 0x15
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_4_FRAGMENTS_MASK 0x400000
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_4_FRAGMENTS__SHIFT 0x16
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_5_FRAGMENTS_MASK 0x800000
+#define CB_DEBUG_BUS_11__FOP_QUAD_REMOVED_5_FRAGMENTS__SHIFT 0x17
+#define CB_DEBUG_BUS_12__FOP_QUAD_REMOVED_6_FRAGMENTS_MASK 0x1
+#define CB_DEBUG_BUS_12__FOP_QUAD_REMOVED_6_FRAGMENTS__SHIFT 0x0
+#define CB_DEBUG_BUS_12__FOP_QUAD_REMOVED_7_FRAGMENTS_MASK 0x2
+#define CB_DEBUG_BUS_12__FOP_QUAD_REMOVED_7_FRAGMENTS__SHIFT 0x1
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_0_MASK 0x4
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_0__SHIFT 0x2
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_1_MASK 0x8
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_1__SHIFT 0x3
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_2_MASK 0x10
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_2__SHIFT 0x4
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_3_MASK 0x20
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_3__SHIFT 0x5
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_4_MASK 0x40
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_4__SHIFT 0x6
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_5_MASK 0x80
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_5__SHIFT 0x7
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_6_MASK 0x100
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_6__SHIFT 0x8
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_7_MASK 0x200
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_READS_FRAGMENT_7__SHIFT 0x9
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_0_MASK 0x400
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_0__SHIFT 0xa
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_1_MASK 0x800
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_1__SHIFT 0xb
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_2_MASK 0x1000
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_2__SHIFT 0xc
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_3_MASK 0x2000
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_3__SHIFT 0xd
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_4_MASK 0x4000
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_4__SHIFT 0xe
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_5_MASK 0x8000
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_5__SHIFT 0xf
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_6_MASK 0x10000
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_6__SHIFT 0x10
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_7_MASK 0x20000
+#define CB_DEBUG_BUS_12__FC_CC_QUADFRAG_WRITES_FRAGMENT_7__SHIFT 0x11
+#define CB_DEBUG_BUS_12__FC_QUAD_BLEND_OPT_DONT_READ_DST_MASK 0x40000
+#define CB_DEBUG_BUS_12__FC_QUAD_BLEND_OPT_DONT_READ_DST__SHIFT 0x12
+#define CB_DEBUG_BUS_12__FC_QUAD_BLEND_OPT_BLEND_BYPASS_MASK 0x80000
+#define CB_DEBUG_BUS_12__FC_QUAD_BLEND_OPT_BLEND_BYPASS__SHIFT 0x13
+#define CB_DEBUG_BUS_12__FC_QUAD_BLEND_OPT_DISCARD_PIXELS_MASK 0x100000
+#define CB_DEBUG_BUS_12__FC_QUAD_BLEND_OPT_DISCARD_PIXELS__SHIFT 0x14
+#define CB_DEBUG_BUS_12__FC_QUAD_KILLED_BY_EXTRA_PIXEL_EXPORT_MASK 0x200000
+#define CB_DEBUG_BUS_12__FC_QUAD_KILLED_BY_EXTRA_PIXEL_EXPORT__SHIFT 0x15
+#define CB_DEBUG_BUS_12__FC_QUAD_KILLED_BY_COLOR_INVALID_MASK 0x400000
+#define CB_DEBUG_BUS_12__FC_QUAD_KILLED_BY_COLOR_INVALID__SHIFT 0x16
+#define CB_DEBUG_BUS_12__FC_QUAD_KILLED_BY_NULL_TARGET_SHADER_MASK_MASK 0x800000
+#define CB_DEBUG_BUS_12__FC_QUAD_KILLED_BY_NULL_TARGET_SHADER_MASK__SHIFT 0x17
+#define CB_DEBUG_BUS_13__FC_PF_FC_KEYID_RDLAT_FIFO_FULL_MASK 0x1
+#define CB_DEBUG_BUS_13__FC_PF_FC_KEYID_RDLAT_FIFO_FULL__SHIFT 0x0
+#define CB_DEBUG_BUS_13__FC_DOC_QTILE_CAM_MISS_MASK 0x2
+#define CB_DEBUG_BUS_13__FC_DOC_QTILE_CAM_MISS__SHIFT 0x1
+#define CB_DEBUG_BUS_13__FC_DOC_QTILE_CAM_HIT_MASK 0x4
+#define CB_DEBUG_BUS_13__FC_DOC_QTILE_CAM_HIT__SHIFT 0x2
+#define CB_DEBUG_BUS_13__FC_DOC_CLINE_CAM_MISS_MASK 0x8
+#define CB_DEBUG_BUS_13__FC_DOC_CLINE_CAM_MISS__SHIFT 0x3
+#define CB_DEBUG_BUS_13__FC_DOC_CLINE_CAM_HIT_MASK 0x10
+#define CB_DEBUG_BUS_13__FC_DOC_CLINE_CAM_HIT__SHIFT 0x4
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_1_SECTOR_MASK 0x20
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_1_SECTOR__SHIFT 0x5
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_2_SECTORS_MASK 0x40
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_2_SECTORS__SHIFT 0x6
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_3_SECTORS_MASK 0x80
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_3_SECTORS__SHIFT 0x7
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_4_SECTORS_MASK 0x100
+#define CB_DEBUG_BUS_13__FC_DOC_OVERWROTE_4_SECTORS__SHIFT 0x8
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_HIT_MASK 0x200
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_HIT__SHIFT 0x9
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_TAG_MISS_MASK 0x400
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_TAG_MISS__SHIFT 0xa
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_SECTOR_MISS_MASK 0x800
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_SECTOR_MISS__SHIFT 0xb
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_REEVICTION_STALL_MASK 0x1000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_REEVICTION_STALL__SHIFT 0xc
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_EVICT_NONZERO_INFLIGHT_STALL_MASK 0x2000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_EVICT_NONZERO_INFLIGHT_STALL__SHIFT 0xd
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_REPLACE_PENDING_EVICT_STALL_MASK 0x4000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_REPLACE_PENDING_EVICT_STALL__SHIFT 0xe
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL_MASK 0x8000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_INFLIGHT_COUNTER_MAXIMUM_STALL__SHIFT 0xf
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_READ_OUTPUT_STALL_MASK 0x10000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_READ_OUTPUT_STALL__SHIFT 0x10
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_WRITE_OUTPUT_STALL_MASK 0x20000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_WRITE_OUTPUT_STALL__SHIFT 0x11
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_ACK_OUTPUT_STALL_MASK 0x40000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_ACK_OUTPUT_STALL__SHIFT 0x12
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_STALL_MASK 0x80000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_STALL__SHIFT 0x13
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_FLUSH_MASK 0x100000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_FLUSH__SHIFT 0x14
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_SECTORS_FLUSHED_MASK 0x200000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_SECTORS_FLUSHED__SHIFT 0x15
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_DIRTY_SECTORS_FLUSHED_MASK 0x400000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_DIRTY_SECTORS_FLUSHED__SHIFT 0x16
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_TAGS_FLUSHED_MASK 0x800000
+#define CB_DEBUG_BUS_13__FC_PF_DCC_CACHE_TAGS_FLUSHED__SHIFT 0x17
+#define CB_DEBUG_BUS_14__FC_MC_DCC_WRITE_REQUESTS_IN_FLIGHT_MASK 0x7ff
+#define CB_DEBUG_BUS_14__FC_MC_DCC_WRITE_REQUESTS_IN_FLIGHT__SHIFT 0x0
+#define CB_DEBUG_BUS_14__FC_MC_DCC_READ_REQUESTS_IN_FLIGHT_MASK 0x3ff800
+#define CB_DEBUG_BUS_14__FC_MC_DCC_READ_REQUESTS_IN_FLIGHT__SHIFT 0xb
+#define CB_DEBUG_BUS_14__CC_PF_DCC_BEYOND_TILE_SPLIT_MASK 0x400000
+#define CB_DEBUG_BUS_14__CC_PF_DCC_BEYOND_TILE_SPLIT__SHIFT 0x16
+#define CB_DEBUG_BUS_14__CC_PF_DCC_RDREQ_STALL_MASK 0x800000
+#define CB_DEBUG_BUS_14__CC_PF_DCC_RDREQ_STALL__SHIFT 0x17
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_2TO1_MASK 0x7
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_2TO1__SHIFT 0x0
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_4TO1_MASK 0x18
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_4TO1__SHIFT 0x3
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_4TO2_MASK 0x60
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_4TO2__SHIFT 0x5
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_4TO3_MASK 0x180
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_4TO3__SHIFT 0x7
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO1_MASK 0x600
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO1__SHIFT 0x9
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO2_MASK 0x1800
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO2__SHIFT 0xb
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO3_MASK 0x6000
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO3__SHIFT 0xd
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO4_MASK 0x18000
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO4__SHIFT 0xf
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO5_MASK 0x60000
+#define CB_DEBUG_BUS_15__CC_PF_DCC_COMPRESS_RATIO_6TO5__SHIFT 0x11
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO1_MASK 0x1
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO1__SHIFT 0x0
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO2_MASK 0x2
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO2__SHIFT 0x1
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO3_MASK 0x4
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO3__SHIFT 0x2
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO4_MASK 0x8
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO4__SHIFT 0x3
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO5_MASK 0x10
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO5__SHIFT 0x4
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO6_MASK 0x20
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO6__SHIFT 0x5
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO7_MASK 0x40
+#define CB_DEBUG_BUS_16__CC_PF_DCC_COMPRESS_RATIO_8TO7__SHIFT 0x6
+#define CB_DEBUG_BUS_17__TILE_INTFC_BUSY_MASK 0x1
+#define CB_DEBUG_BUS_17__TILE_INTFC_BUSY__SHIFT 0x0
+#define CB_DEBUG_BUS_17__MU_BUSY_MASK 0x2
+#define CB_DEBUG_BUS_17__MU_BUSY__SHIFT 0x1
+#define CB_DEBUG_BUS_17__TQ_BUSY_MASK 0x4
+#define CB_DEBUG_BUS_17__TQ_BUSY__SHIFT 0x2
+#define CB_DEBUG_BUS_17__AC_BUSY_MASK 0x8
+#define CB_DEBUG_BUS_17__AC_BUSY__SHIFT 0x3
+#define CB_DEBUG_BUS_17__CRW_BUSY_MASK 0x10
+#define CB_DEBUG_BUS_17__CRW_BUSY__SHIFT 0x4
+#define CB_DEBUG_BUS_17__CACHE_CTRL_BUSY_MASK 0x20
+#define CB_DEBUG_BUS_17__CACHE_CTRL_BUSY__SHIFT 0x5
+#define CB_DEBUG_BUS_17__MC_WR_PENDING_MASK 0x40
+#define CB_DEBUG_BUS_17__MC_WR_PENDING__SHIFT 0x6
+#define CB_DEBUG_BUS_17__FC_WR_PENDING_MASK 0x80
+#define CB_DEBUG_BUS_17__FC_WR_PENDING__SHIFT 0x7
+#define CB_DEBUG_BUS_17__FC_RD_PENDING_MASK 0x100
+#define CB_DEBUG_BUS_17__FC_RD_PENDING__SHIFT 0x8
+#define CB_DEBUG_BUS_17__EVICT_PENDING_MASK 0x200
+#define CB_DEBUG_BUS_17__EVICT_PENDING__SHIFT 0x9
+#define CB_DEBUG_BUS_17__LAST_RD_ARB_WINNER_MASK 0x400
+#define CB_DEBUG_BUS_17__LAST_RD_ARB_WINNER__SHIFT 0xa
+#define CB_DEBUG_BUS_17__MU_STATE_MASK 0x7f800
+#define CB_DEBUG_BUS_17__MU_STATE__SHIFT 0xb
+#define CB_DEBUG_BUS_18__TILE_RETIREMENT_BUSY_MASK 0x1
+#define CB_DEBUG_BUS_18__TILE_RETIREMENT_BUSY__SHIFT 0x0
+#define CB_DEBUG_BUS_18__FOP_BUSY_MASK 0x2
+#define CB_DEBUG_BUS_18__FOP_BUSY__SHIFT 0x1
+#define CB_DEBUG_BUS_18__CLEAR_BUSY_MASK 0x4
+#define CB_DEBUG_BUS_18__CLEAR_BUSY__SHIFT 0x2
+#define CB_DEBUG_BUS_18__LAT_BUSY_MASK 0x8
+#define CB_DEBUG_BUS_18__LAT_BUSY__SHIFT 0x3
+#define CB_DEBUG_BUS_18__CACHE_CTL_BUSY_MASK 0x10
+#define CB_DEBUG_BUS_18__CACHE_CTL_BUSY__SHIFT 0x4
+#define CB_DEBUG_BUS_18__ADDR_BUSY_MASK 0x20
+#define CB_DEBUG_BUS_18__ADDR_BUSY__SHIFT 0x5
+#define CB_DEBUG_BUS_18__MERGE_BUSY_MASK 0x40
+#define CB_DEBUG_BUS_18__MERGE_BUSY__SHIFT 0x6
+#define CB_DEBUG_BUS_18__QUAD_BUSY_MASK 0x80
+#define CB_DEBUG_BUS_18__QUAD_BUSY__SHIFT 0x7
+#define CB_DEBUG_BUS_18__TILE_BUSY_MASK 0x100
+#define CB_DEBUG_BUS_18__TILE_BUSY__SHIFT 0x8
+#define CB_DEBUG_BUS_18__DCC_BUSY_MASK 0x200
+#define CB_DEBUG_BUS_18__DCC_BUSY__SHIFT 0x9
+#define CB_DEBUG_BUS_18__DOC_BUSY_MASK 0x400
+#define CB_DEBUG_BUS_18__DOC_BUSY__SHIFT 0xa
+#define CB_DEBUG_BUS_18__DAG_BUSY_MASK 0x800
+#define CB_DEBUG_BUS_18__DAG_BUSY__SHIFT 0xb
+#define CB_DEBUG_BUS_18__DOC_STALL_MASK 0x1000
+#define CB_DEBUG_BUS_18__DOC_STALL__SHIFT 0xc
+#define CB_DEBUG_BUS_18__DOC_QT_CAM_FULL_MASK 0x2000
+#define CB_DEBUG_BUS_18__DOC_QT_CAM_FULL__SHIFT 0xd
+#define CB_DEBUG_BUS_18__DOC_CL_CAM_FULL_MASK 0x4000
+#define CB_DEBUG_BUS_18__DOC_CL_CAM_FULL__SHIFT 0xe
+#define CB_DEBUG_BUS_18__DOC_QUAD_PTR_FIFO_FULL_MASK 0x8000
+#define CB_DEBUG_BUS_18__DOC_QUAD_PTR_FIFO_FULL__SHIFT 0xf
+#define CB_DEBUG_BUS_18__DOC_SECTOR_MASK_FIFO_FULL_MASK 0x10000
+#define CB_DEBUG_BUS_18__DOC_SECTOR_MASK_FIFO_FULL__SHIFT 0x10
+#define CB_DEBUG_BUS_18__DCS_READ_WINNER_LAST_MASK 0x20000
+#define CB_DEBUG_BUS_18__DCS_READ_WINNER_LAST__SHIFT 0x11
+#define CB_DEBUG_BUS_18__DCS_READ_EV_PENDING_MASK 0x40000
+#define CB_DEBUG_BUS_18__DCS_READ_EV_PENDING__SHIFT 0x12
+#define CB_DEBUG_BUS_18__DCS_WRITE_CC_PENDING_MASK 0x80000
+#define CB_DEBUG_BUS_18__DCS_WRITE_CC_PENDING__SHIFT 0x13
+#define CB_DEBUG_BUS_18__DCS_READ_CC_PENDING_MASK 0x100000
+#define CB_DEBUG_BUS_18__DCS_READ_CC_PENDING__SHIFT 0x14
+#define CB_DEBUG_BUS_18__DCS_WRITE_MC_PENDING_MASK 0x200000
+#define CB_DEBUG_BUS_18__DCS_WRITE_MC_PENDING__SHIFT 0x15
+#define CB_DEBUG_BUS_19__SURF_SYNC_STATE_MASK 0x3
+#define CB_DEBUG_BUS_19__SURF_SYNC_STATE__SHIFT 0x0
+#define CB_DEBUG_BUS_19__SURF_SYNC_START_MASK 0x4
+#define CB_DEBUG_BUS_19__SURF_SYNC_START__SHIFT 0x2
+#define CB_DEBUG_BUS_19__SF_BUSY_MASK 0x8
+#define CB_DEBUG_BUS_19__SF_BUSY__SHIFT 0x3
+#define CB_DEBUG_BUS_19__CS_BUSY_MASK 0x10
+#define CB_DEBUG_BUS_19__CS_BUSY__SHIFT 0x4
+#define CB_DEBUG_BUS_19__RB_BUSY_MASK 0x20
+#define CB_DEBUG_BUS_19__RB_BUSY__SHIFT 0x5
+#define CB_DEBUG_BUS_19__DS_BUSY_MASK 0x40
+#define CB_DEBUG_BUS_19__DS_BUSY__SHIFT 0x6
+#define CB_DEBUG_BUS_19__TB_BUSY_MASK 0x80
+#define CB_DEBUG_BUS_19__TB_BUSY__SHIFT 0x7
+#define CB_DEBUG_BUS_19__IB_BUSY_MASK 0x100
+#define CB_DEBUG_BUS_19__IB_BUSY__SHIFT 0x8
+#define CB_DEBUG_BUS_19__DRR_BUSY_MASK 0x200
+#define CB_DEBUG_BUS_19__DRR_BUSY__SHIFT 0x9
+#define CB_DEBUG_BUS_19__DF_BUSY_MASK 0x400
+#define CB_DEBUG_BUS_19__DF_BUSY__SHIFT 0xa
+#define CB_DEBUG_BUS_19__DD_BUSY_MASK 0x800
+#define CB_DEBUG_BUS_19__DD_BUSY__SHIFT 0xb
+#define CB_DEBUG_BUS_19__DC_BUSY_MASK 0x1000
+#define CB_DEBUG_BUS_19__DC_BUSY__SHIFT 0xc
+#define CB_DEBUG_BUS_19__DK_BUSY_MASK 0x2000
+#define CB_DEBUG_BUS_19__DK_BUSY__SHIFT 0xd
+#define CB_DEBUG_BUS_19__DF_SKID_FIFO_EMPTY_MASK 0x4000
+#define CB_DEBUG_BUS_19__DF_SKID_FIFO_EMPTY__SHIFT 0xe
+#define CB_DEBUG_BUS_19__DF_CLEAR_FIFO_EMPTY_MASK 0x8000
+#define CB_DEBUG_BUS_19__DF_CLEAR_FIFO_EMPTY__SHIFT 0xf
+#define CB_DEBUG_BUS_19__DD_READY_MASK 0x10000
+#define CB_DEBUG_BUS_19__DD_READY__SHIFT 0x10
+#define CB_DEBUG_BUS_19__DC_FIFO_FULL_MASK 0x20000
+#define CB_DEBUG_BUS_19__DC_FIFO_FULL__SHIFT 0x11
+#define CB_DEBUG_BUS_19__DC_READY_MASK 0x40000
+#define CB_DEBUG_BUS_19__DC_READY__SHIFT 0x12
+#define CB_DEBUG_BUS_20__MC_RDREQ_CREDITS_MASK 0x3f
+#define CB_DEBUG_BUS_20__MC_RDREQ_CREDITS__SHIFT 0x0
+#define CB_DEBUG_BUS_20__MC_WRREQ_CREDITS_MASK 0xfc0
+#define CB_DEBUG_BUS_20__MC_WRREQ_CREDITS__SHIFT 0x6
+#define CB_DEBUG_BUS_20__CC_RDREQ_HAD_ITS_TURN_MASK 0x1000
+#define CB_DEBUG_BUS_20__CC_RDREQ_HAD_ITS_TURN__SHIFT 0xc
+#define CB_DEBUG_BUS_20__FC_RDREQ_HAD_ITS_TURN_MASK 0x2000
+#define CB_DEBUG_BUS_20__FC_RDREQ_HAD_ITS_TURN__SHIFT 0xd
+#define CB_DEBUG_BUS_20__CM_RDREQ_HAD_ITS_TURN_MASK 0x4000
+#define CB_DEBUG_BUS_20__CM_RDREQ_HAD_ITS_TURN__SHIFT 0xe
+#define CB_DEBUG_BUS_20__CC_WRREQ_HAD_ITS_TURN_MASK 0x10000
+#define CB_DEBUG_BUS_20__CC_WRREQ_HAD_ITS_TURN__SHIFT 0x10
+#define CB_DEBUG_BUS_20__FC_WRREQ_HAD_ITS_TURN_MASK 0x20000
+#define CB_DEBUG_BUS_20__FC_WRREQ_HAD_ITS_TURN__SHIFT 0x11
+#define CB_DEBUG_BUS_20__CM_WRREQ_HAD_ITS_TURN_MASK 0x40000
+#define CB_DEBUG_BUS_20__CM_WRREQ_HAD_ITS_TURN__SHIFT 0x12
+#define CB_DEBUG_BUS_20__CC_WRREQ_FIFO_EMPTY_MASK 0x100000
+#define CB_DEBUG_BUS_20__CC_WRREQ_FIFO_EMPTY__SHIFT 0x14
+#define CB_DEBUG_BUS_20__FC_WRREQ_FIFO_EMPTY_MASK 0x200000
+#define CB_DEBUG_BUS_20__FC_WRREQ_FIFO_EMPTY__SHIFT 0x15
+#define CB_DEBUG_BUS_20__CM_WRREQ_FIFO_EMPTY_MASK 0x400000
+#define CB_DEBUG_BUS_20__CM_WRREQ_FIFO_EMPTY__SHIFT 0x16
+#define CB_DEBUG_BUS_20__DCC_WRREQ_FIFO_EMPTY_MASK 0x800000
+#define CB_DEBUG_BUS_20__DCC_WRREQ_FIFO_EMPTY__SHIFT 0x17
+#define CB_DEBUG_BUS_21__CM_BUSY_MASK 0x1
+#define CB_DEBUG_BUS_21__CM_BUSY__SHIFT 0x0
+#define CB_DEBUG_BUS_21__FC_BUSY_MASK 0x2
+#define CB_DEBUG_BUS_21__FC_BUSY__SHIFT 0x1
+#define CB_DEBUG_BUS_21__CC_BUSY_MASK 0x4
+#define CB_DEBUG_BUS_21__CC_BUSY__SHIFT 0x2
+#define CB_DEBUG_BUS_21__BB_BUSY_MASK 0x8
+#define CB_DEBUG_BUS_21__BB_BUSY__SHIFT 0x3
+#define CB_DEBUG_BUS_21__MA_BUSY_MASK 0x10
+#define CB_DEBUG_BUS_21__MA_BUSY__SHIFT 0x4
+#define CB_DEBUG_BUS_21__CORE_SCLK_VLD_MASK 0x20
+#define CB_DEBUG_BUS_21__CORE_SCLK_VLD__SHIFT 0x5
+#define CB_DEBUG_BUS_21__REG_SCLK1_VLD_MASK 0x40
+#define CB_DEBUG_BUS_21__REG_SCLK1_VLD__SHIFT 0x6
+#define CB_DEBUG_BUS_21__REG_SCLK0_VLD_MASK 0x80
+#define CB_DEBUG_BUS_21__REG_SCLK0_VLD__SHIFT 0x7
+#define CB_DEBUG_BUS_22__OUTSTANDING_MC_READS_MASK 0xfff
+#define CB_DEBUG_BUS_22__OUTSTANDING_MC_READS__SHIFT 0x0
+#define CB_DEBUG_BUS_22__OUTSTANDING_MC_WRITES_MASK 0xfff000
+#define CB_DEBUG_BUS_22__OUTSTANDING_MC_WRITES__SHIFT 0xc
+#define CP_DFY_CNTL__POLICY_MASK 0x1
+#define CP_DFY_CNTL__POLICY__SHIFT 0x0
+#define CP_DFY_CNTL__MTYPE_MASK 0xc
+#define CP_DFY_CNTL__MTYPE__SHIFT 0x2
+#define CP_DFY_CNTL__LFSR_RESET_MASK 0x10000000
+#define CP_DFY_CNTL__LFSR_RESET__SHIFT 0x1c
+#define CP_DFY_CNTL__MODE_MASK 0x60000000
+#define CP_DFY_CNTL__MODE__SHIFT 0x1d
+#define CP_DFY_CNTL__ENABLE_MASK 0x80000000
+#define CP_DFY_CNTL__ENABLE__SHIFT 0x1f
+#define CP_DFY_STAT__BURST_COUNT_MASK 0xffff
+#define CP_DFY_STAT__BURST_COUNT__SHIFT 0x0
+#define CP_DFY_STAT__TAGS_PENDING_MASK 0x1ff0000
+#define CP_DFY_STAT__TAGS_PENDING__SHIFT 0x10
+#define CP_DFY_STAT__BUSY_MASK 0x80000000
+#define CP_DFY_STAT__BUSY__SHIFT 0x1f
+#define CP_DFY_ADDR_HI__ADDR_HI_MASK 0xffffffff
+#define CP_DFY_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_DFY_ADDR_LO__ADDR_LO_MASK 0xffffffe0
+#define CP_DFY_ADDR_LO__ADDR_LO__SHIFT 0x5
+#define CP_DFY_DATA_0__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_0__DATA__SHIFT 0x0
+#define CP_DFY_DATA_1__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_1__DATA__SHIFT 0x0
+#define CP_DFY_DATA_2__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_2__DATA__SHIFT 0x0
+#define CP_DFY_DATA_3__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_3__DATA__SHIFT 0x0
+#define CP_DFY_DATA_4__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_4__DATA__SHIFT 0x0
+#define CP_DFY_DATA_5__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_5__DATA__SHIFT 0x0
+#define CP_DFY_DATA_6__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_6__DATA__SHIFT 0x0
+#define CP_DFY_DATA_7__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_7__DATA__SHIFT 0x0
+#define CP_DFY_DATA_8__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_8__DATA__SHIFT 0x0
+#define CP_DFY_DATA_9__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_9__DATA__SHIFT 0x0
+#define CP_DFY_DATA_10__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_10__DATA__SHIFT 0x0
+#define CP_DFY_DATA_11__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_11__DATA__SHIFT 0x0
+#define CP_DFY_DATA_12__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_12__DATA__SHIFT 0x0
+#define CP_DFY_DATA_13__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_13__DATA__SHIFT 0x0
+#define CP_DFY_DATA_14__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_14__DATA__SHIFT 0x0
+#define CP_DFY_DATA_15__DATA_MASK 0xffffffff
+#define CP_DFY_DATA_15__DATA__SHIFT 0x0
+#define CP_DFY_CMD__OFFSET_MASK 0x1ff
+#define CP_DFY_CMD__OFFSET__SHIFT 0x0
+#define CP_DFY_CMD__SIZE_MASK 0xffff0000
+#define CP_DFY_CMD__SIZE__SHIFT 0x10
+#define CP_CPC_MGCG_SYNC_CNTL__COOLDOWN_PERIOD_MASK 0xff
+#define CP_CPC_MGCG_SYNC_CNTL__COOLDOWN_PERIOD__SHIFT 0x0
+#define CP_CPC_MGCG_SYNC_CNTL__WARMUP_PERIOD_MASK 0xff00
+#define CP_CPC_MGCG_SYNC_CNTL__WARMUP_PERIOD__SHIFT 0x8
+#define CP_ATCL1_CNTL__XNACK_REDO_TIMER_CNT_MASK 0x3ff
+#define CP_ATCL1_CNTL__XNACK_REDO_TIMER_CNT__SHIFT 0x0
+#define CP_RB0_BASE__RB_BASE_MASK 0xffffffff
+#define CP_RB0_BASE__RB_BASE__SHIFT 0x0
+#define CP_RB0_BASE_HI__RB_BASE_HI_MASK 0xff
+#define CP_RB0_BASE_HI__RB_BASE_HI__SHIFT 0x0
+#define CP_RB_BASE__RB_BASE_MASK 0xffffffff
+#define CP_RB_BASE__RB_BASE__SHIFT 0x0
+#define CP_RB1_BASE__RB_BASE_MASK 0xffffffff
+#define CP_RB1_BASE__RB_BASE__SHIFT 0x0
+#define CP_RB1_BASE_HI__RB_BASE_HI_MASK 0xff
+#define CP_RB1_BASE_HI__RB_BASE_HI__SHIFT 0x0
+#define CP_RB2_BASE__RB_BASE_MASK 0xffffffff
+#define CP_RB2_BASE__RB_BASE__SHIFT 0x0
+#define CP_RB0_CNTL__RB_BUFSZ_MASK 0x3f
+#define CP_RB0_CNTL__RB_BUFSZ__SHIFT 0x0
+#define CP_RB0_CNTL__RB_BLKSZ_MASK 0x3f00
+#define CP_RB0_CNTL__RB_BLKSZ__SHIFT 0x8
+#define CP_RB0_CNTL__MTYPE_MASK 0x18000
+#define CP_RB0_CNTL__MTYPE__SHIFT 0xf
+#define CP_RB0_CNTL__BUF_SWAP_MASK 0x60000
+#define CP_RB0_CNTL__BUF_SWAP__SHIFT 0x11
+#define CP_RB0_CNTL__MIN_AVAILSZ_MASK 0x300000
+#define CP_RB0_CNTL__MIN_AVAILSZ__SHIFT 0x14
+#define CP_RB0_CNTL__MIN_IB_AVAILSZ_MASK 0xc00000
+#define CP_RB0_CNTL__MIN_IB_AVAILSZ__SHIFT 0x16
+#define CP_RB0_CNTL__CACHE_POLICY_MASK 0x1000000
+#define CP_RB0_CNTL__CACHE_POLICY__SHIFT 0x18
+#define CP_RB0_CNTL__RB_NO_UPDATE_MASK 0x8000000
+#define CP_RB0_CNTL__RB_NO_UPDATE__SHIFT 0x1b
+#define CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000
+#define CP_RB0_CNTL__RB_RPTR_WR_ENA__SHIFT 0x1f
+#define CP_RB_CNTL__RB_BUFSZ_MASK 0x3f
+#define CP_RB_CNTL__RB_BUFSZ__SHIFT 0x0
+#define CP_RB_CNTL__RB_BLKSZ_MASK 0x3f00
+#define CP_RB_CNTL__RB_BLKSZ__SHIFT 0x8
+#define CP_RB_CNTL__MTYPE_MASK 0x18000
+#define CP_RB_CNTL__MTYPE__SHIFT 0xf
+#define CP_RB_CNTL__BUF_SWAP_MASK 0x60000
+#define CP_RB_CNTL__BUF_SWAP__SHIFT 0x11
+#define CP_RB_CNTL__MIN_AVAILSZ_MASK 0x300000
+#define CP_RB_CNTL__MIN_AVAILSZ__SHIFT 0x14
+#define CP_RB_CNTL__MIN_IB_AVAILSZ_MASK 0xc00000
+#define CP_RB_CNTL__MIN_IB_AVAILSZ__SHIFT 0x16
+#define CP_RB_CNTL__CACHE_POLICY_MASK 0x1000000
+#define CP_RB_CNTL__CACHE_POLICY__SHIFT 0x18
+#define CP_RB_CNTL__RB_NO_UPDATE_MASK 0x8000000
+#define CP_RB_CNTL__RB_NO_UPDATE__SHIFT 0x1b
+#define CP_RB_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000
+#define CP_RB_CNTL__RB_RPTR_WR_ENA__SHIFT 0x1f
+#define CP_RB1_CNTL__RB_BUFSZ_MASK 0x3f
+#define CP_RB1_CNTL__RB_BUFSZ__SHIFT 0x0
+#define CP_RB1_CNTL__RB_BLKSZ_MASK 0x3f00
+#define CP_RB1_CNTL__RB_BLKSZ__SHIFT 0x8
+#define CP_RB1_CNTL__MTYPE_MASK 0x18000
+#define CP_RB1_CNTL__MTYPE__SHIFT 0xf
+#define CP_RB1_CNTL__MIN_AVAILSZ_MASK 0x300000
+#define CP_RB1_CNTL__MIN_AVAILSZ__SHIFT 0x14
+#define CP_RB1_CNTL__MIN_IB_AVAILSZ_MASK 0xc00000
+#define CP_RB1_CNTL__MIN_IB_AVAILSZ__SHIFT 0x16
+#define CP_RB1_CNTL__CACHE_POLICY_MASK 0x1000000
+#define CP_RB1_CNTL__CACHE_POLICY__SHIFT 0x18
+#define CP_RB1_CNTL__RB_NO_UPDATE_MASK 0x8000000
+#define CP_RB1_CNTL__RB_NO_UPDATE__SHIFT 0x1b
+#define CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000
+#define CP_RB1_CNTL__RB_RPTR_WR_ENA__SHIFT 0x1f
+#define CP_RB2_CNTL__RB_BUFSZ_MASK 0x3f
+#define CP_RB2_CNTL__RB_BUFSZ__SHIFT 0x0
+#define CP_RB2_CNTL__RB_BLKSZ_MASK 0x3f00
+#define CP_RB2_CNTL__RB_BLKSZ__SHIFT 0x8
+#define CP_RB2_CNTL__MTYPE_MASK 0x18000
+#define CP_RB2_CNTL__MTYPE__SHIFT 0xf
+#define CP_RB2_CNTL__MIN_AVAILSZ_MASK 0x300000
+#define CP_RB2_CNTL__MIN_AVAILSZ__SHIFT 0x14
+#define CP_RB2_CNTL__MIN_IB_AVAILSZ_MASK 0xc00000
+#define CP_RB2_CNTL__MIN_IB_AVAILSZ__SHIFT 0x16
+#define CP_RB2_CNTL__CACHE_POLICY_MASK 0x1000000
+#define CP_RB2_CNTL__CACHE_POLICY__SHIFT 0x18
+#define CP_RB2_CNTL__RB_NO_UPDATE_MASK 0x8000000
+#define CP_RB2_CNTL__RB_NO_UPDATE__SHIFT 0x1b
+#define CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000
+#define CP_RB2_CNTL__RB_RPTR_WR_ENA__SHIFT 0x1f
+#define CP_RB_RPTR_WR__RB_RPTR_WR_MASK 0xfffff
+#define CP_RB_RPTR_WR__RB_RPTR_WR__SHIFT 0x0
+#define CP_RB0_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x3
+#define CP_RB0_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x0
+#define CP_RB0_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffc
+#define CP_RB0_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x2
+#define CP_RB_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x3
+#define CP_RB_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x0
+#define CP_RB_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffc
+#define CP_RB_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x2
+#define CP_RB1_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x3
+#define CP_RB1_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x0
+#define CP_RB1_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffc
+#define CP_RB1_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x2
+#define CP_RB2_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x3
+#define CP_RB2_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x0
+#define CP_RB2_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffc
+#define CP_RB2_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x2
+#define CP_RB0_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0xffff
+#define CP_RB0_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x0
+#define CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0xffff
+#define CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x0
+#define CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0xffff
+#define CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x0
+#define CP_RB2_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0xffff
+#define CP_RB2_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x0
+#define CP_RB0_WPTR__RB_WPTR_MASK 0xfffff
+#define CP_RB0_WPTR__RB_WPTR__SHIFT 0x0
+#define CP_RB_WPTR__RB_WPTR_MASK 0xfffff
+#define CP_RB_WPTR__RB_WPTR__SHIFT 0x0
+#define CP_RB1_WPTR__RB_WPTR_MASK 0xfffff
+#define CP_RB1_WPTR__RB_WPTR__SHIFT 0x0
+#define CP_RB2_WPTR__RB_WPTR_MASK 0xfffff
+#define CP_RB2_WPTR__RB_WPTR__SHIFT 0x0
+#define CP_RB_WPTR_POLL_ADDR_LO__RB_WPTR_POLL_ADDR_LO_MASK 0xfffffffc
+#define CP_RB_WPTR_POLL_ADDR_LO__RB_WPTR_POLL_ADDR_LO__SHIFT 0x2
+#define CP_RB_WPTR_POLL_ADDR_HI__RB_WPTR_POLL_ADDR_HI_MASK 0xff
+#define CP_RB_WPTR_POLL_ADDR_HI__RB_WPTR_POLL_ADDR_HI__SHIFT 0x0
+#define CP_INT_CNTL__CP_VM_DOORBELL_WR_INT_ENABLE_MASK 0x800
+#define CP_INT_CNTL__CP_VM_DOORBELL_WR_INT_ENABLE__SHIFT 0xb
+#define CP_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_INT_CNTL__CMP_BUSY_INT_ENABLE_MASK 0x40000
+#define CP_INT_CNTL__CMP_BUSY_INT_ENABLE__SHIFT 0x12
+#define CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK 0x80000
+#define CP_INT_CNTL__CNTX_BUSY_INT_ENABLE__SHIFT 0x13
+#define CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK 0x100000
+#define CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE__SHIFT 0x14
+#define CP_INT_CNTL__GFX_IDLE_INT_ENABLE_MASK 0x200000
+#define CP_INT_CNTL__GFX_IDLE_INT_ENABLE__SHIFT 0x15
+#define CP_INT_CNTL__PRIV_INSTR_INT_ENABLE_MASK 0x400000
+#define CP_INT_CNTL__PRIV_INSTR_INT_ENABLE__SHIFT 0x16
+#define CP_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_INT_CNTL_RING0__CP_VM_DOORBELL_WR_INT_ENABLE_MASK 0x800
+#define CP_INT_CNTL_RING0__CP_VM_DOORBELL_WR_INT_ENABLE__SHIFT 0xb
+#define CP_INT_CNTL_RING0__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_INT_CNTL_RING0__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_INT_CNTL_RING0__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_INT_CNTL_RING0__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_INT_CNTL_RING0__CMP_BUSY_INT_ENABLE_MASK 0x40000
+#define CP_INT_CNTL_RING0__CMP_BUSY_INT_ENABLE__SHIFT 0x12
+#define CP_INT_CNTL_RING0__CNTX_BUSY_INT_ENABLE_MASK 0x80000
+#define CP_INT_CNTL_RING0__CNTX_BUSY_INT_ENABLE__SHIFT 0x13
+#define CP_INT_CNTL_RING0__CNTX_EMPTY_INT_ENABLE_MASK 0x100000
+#define CP_INT_CNTL_RING0__CNTX_EMPTY_INT_ENABLE__SHIFT 0x14
+#define CP_INT_CNTL_RING0__GFX_IDLE_INT_ENABLE_MASK 0x200000
+#define CP_INT_CNTL_RING0__GFX_IDLE_INT_ENABLE__SHIFT 0x15
+#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK 0x400000
+#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE__SHIFT 0x16
+#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_INT_CNTL_RING0__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_INT_CNTL_RING0__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_INT_CNTL_RING0__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_INT_CNTL_RING0__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_INT_CNTL_RING0__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_INT_CNTL_RING0__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_INT_CNTL_RING0__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_INT_CNTL_RING0__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_INT_CNTL_RING1__CP_VM_DOORBELL_WR_INT_ENABLE_MASK 0x800
+#define CP_INT_CNTL_RING1__CP_VM_DOORBELL_WR_INT_ENABLE__SHIFT 0xb
+#define CP_INT_CNTL_RING1__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_INT_CNTL_RING1__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_INT_CNTL_RING1__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_INT_CNTL_RING1__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_INT_CNTL_RING1__CMP_BUSY_INT_ENABLE_MASK 0x40000
+#define CP_INT_CNTL_RING1__CMP_BUSY_INT_ENABLE__SHIFT 0x12
+#define CP_INT_CNTL_RING1__CNTX_BUSY_INT_ENABLE_MASK 0x80000
+#define CP_INT_CNTL_RING1__CNTX_BUSY_INT_ENABLE__SHIFT 0x13
+#define CP_INT_CNTL_RING1__CNTX_EMPTY_INT_ENABLE_MASK 0x100000
+#define CP_INT_CNTL_RING1__CNTX_EMPTY_INT_ENABLE__SHIFT 0x14
+#define CP_INT_CNTL_RING1__GFX_IDLE_INT_ENABLE_MASK 0x200000
+#define CP_INT_CNTL_RING1__GFX_IDLE_INT_ENABLE__SHIFT 0x15
+#define CP_INT_CNTL_RING1__PRIV_INSTR_INT_ENABLE_MASK 0x400000
+#define CP_INT_CNTL_RING1__PRIV_INSTR_INT_ENABLE__SHIFT 0x16
+#define CP_INT_CNTL_RING1__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_INT_CNTL_RING1__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_INT_CNTL_RING1__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_INT_CNTL_RING1__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_INT_CNTL_RING1__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_INT_CNTL_RING1__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_INT_CNTL_RING1__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_INT_CNTL_RING1__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_INT_CNTL_RING1__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_INT_CNTL_RING1__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_INT_CNTL_RING1__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_INT_CNTL_RING1__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_INT_CNTL_RING2__CP_VM_DOORBELL_WR_INT_ENABLE_MASK 0x800
+#define CP_INT_CNTL_RING2__CP_VM_DOORBELL_WR_INT_ENABLE__SHIFT 0xb
+#define CP_INT_CNTL_RING2__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_INT_CNTL_RING2__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_INT_CNTL_RING2__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_INT_CNTL_RING2__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_INT_CNTL_RING2__CMP_BUSY_INT_ENABLE_MASK 0x40000
+#define CP_INT_CNTL_RING2__CMP_BUSY_INT_ENABLE__SHIFT 0x12
+#define CP_INT_CNTL_RING2__CNTX_BUSY_INT_ENABLE_MASK 0x80000
+#define CP_INT_CNTL_RING2__CNTX_BUSY_INT_ENABLE__SHIFT 0x13
+#define CP_INT_CNTL_RING2__CNTX_EMPTY_INT_ENABLE_MASK 0x100000
+#define CP_INT_CNTL_RING2__CNTX_EMPTY_INT_ENABLE__SHIFT 0x14
+#define CP_INT_CNTL_RING2__GFX_IDLE_INT_ENABLE_MASK 0x200000
+#define CP_INT_CNTL_RING2__GFX_IDLE_INT_ENABLE__SHIFT 0x15
+#define CP_INT_CNTL_RING2__PRIV_INSTR_INT_ENABLE_MASK 0x400000
+#define CP_INT_CNTL_RING2__PRIV_INSTR_INT_ENABLE__SHIFT 0x16
+#define CP_INT_CNTL_RING2__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_INT_CNTL_RING2__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_INT_CNTL_RING2__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_INT_CNTL_RING2__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_INT_CNTL_RING2__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_INT_CNTL_RING2__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_INT_CNTL_RING2__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_INT_CNTL_RING2__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_INT_CNTL_RING2__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_INT_CNTL_RING2__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_INT_CNTL_RING2__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_INT_CNTL_RING2__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_INT_STATUS__CP_VM_DOORBELL_WR_INT_STAT_MASK 0x800
+#define CP_INT_STATUS__CP_VM_DOORBELL_WR_INT_STAT__SHIFT 0xb
+#define CP_INT_STATUS__CP_ECC_ERROR_INT_STAT_MASK 0x4000
+#define CP_INT_STATUS__CP_ECC_ERROR_INT_STAT__SHIFT 0xe
+#define CP_INT_STATUS__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x20000
+#define CP_INT_STATUS__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x11
+#define CP_INT_STATUS__CMP_BUSY_INT_STAT_MASK 0x40000
+#define CP_INT_STATUS__CMP_BUSY_INT_STAT__SHIFT 0x12
+#define CP_INT_STATUS__CNTX_BUSY_INT_STAT_MASK 0x80000
+#define CP_INT_STATUS__CNTX_BUSY_INT_STAT__SHIFT 0x13
+#define CP_INT_STATUS__CNTX_EMPTY_INT_STAT_MASK 0x100000
+#define CP_INT_STATUS__CNTX_EMPTY_INT_STAT__SHIFT 0x14
+#define CP_INT_STATUS__GFX_IDLE_INT_STAT_MASK 0x200000
+#define CP_INT_STATUS__GFX_IDLE_INT_STAT__SHIFT 0x15
+#define CP_INT_STATUS__PRIV_INSTR_INT_STAT_MASK 0x400000
+#define CP_INT_STATUS__PRIV_INSTR_INT_STAT__SHIFT 0x16
+#define CP_INT_STATUS__PRIV_REG_INT_STAT_MASK 0x800000
+#define CP_INT_STATUS__PRIV_REG_INT_STAT__SHIFT 0x17
+#define CP_INT_STATUS__OPCODE_ERROR_INT_STAT_MASK 0x1000000
+#define CP_INT_STATUS__OPCODE_ERROR_INT_STAT__SHIFT 0x18
+#define CP_INT_STATUS__TIME_STAMP_INT_STAT_MASK 0x4000000
+#define CP_INT_STATUS__TIME_STAMP_INT_STAT__SHIFT 0x1a
+#define CP_INT_STATUS__RESERVED_BIT_ERROR_INT_STAT_MASK 0x8000000
+#define CP_INT_STATUS__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x1b
+#define CP_INT_STATUS__GENERIC2_INT_STAT_MASK 0x20000000
+#define CP_INT_STATUS__GENERIC2_INT_STAT__SHIFT 0x1d
+#define CP_INT_STATUS__GENERIC1_INT_STAT_MASK 0x40000000
+#define CP_INT_STATUS__GENERIC1_INT_STAT__SHIFT 0x1e
+#define CP_INT_STATUS__GENERIC0_INT_STAT_MASK 0x80000000
+#define CP_INT_STATUS__GENERIC0_INT_STAT__SHIFT 0x1f
+#define CP_INT_STATUS_RING0__CP_VM_DOORBELL_WR_INT_STAT_MASK 0x800
+#define CP_INT_STATUS_RING0__CP_VM_DOORBELL_WR_INT_STAT__SHIFT 0xb
+#define CP_INT_STATUS_RING0__CP_ECC_ERROR_INT_STAT_MASK 0x4000
+#define CP_INT_STATUS_RING0__CP_ECC_ERROR_INT_STAT__SHIFT 0xe
+#define CP_INT_STATUS_RING0__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x20000
+#define CP_INT_STATUS_RING0__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x11
+#define CP_INT_STATUS_RING0__CMP_BUSY_INT_STAT_MASK 0x40000
+#define CP_INT_STATUS_RING0__CMP_BUSY_INT_STAT__SHIFT 0x12
+#define CP_INT_STATUS_RING0__GCNTX_BUSY_INT_STAT_MASK 0x80000
+#define CP_INT_STATUS_RING0__GCNTX_BUSY_INT_STAT__SHIFT 0x13
+#define CP_INT_STATUS_RING0__CNTX_EMPTY_INT_STAT_MASK 0x100000
+#define CP_INT_STATUS_RING0__CNTX_EMPTY_INT_STAT__SHIFT 0x14
+#define CP_INT_STATUS_RING0__GFX_IDLE_INT_STAT_MASK 0x200000
+#define CP_INT_STATUS_RING0__GFX_IDLE_INT_STAT__SHIFT 0x15
+#define CP_INT_STATUS_RING0__PRIV_INSTR_INT_STAT_MASK 0x400000
+#define CP_INT_STATUS_RING0__PRIV_INSTR_INT_STAT__SHIFT 0x16
+#define CP_INT_STATUS_RING0__PRIV_REG_INT_STAT_MASK 0x800000
+#define CP_INT_STATUS_RING0__PRIV_REG_INT_STAT__SHIFT 0x17
+#define CP_INT_STATUS_RING0__OPCODE_ERROR_INT_STAT_MASK 0x1000000
+#define CP_INT_STATUS_RING0__OPCODE_ERROR_INT_STAT__SHIFT 0x18
+#define CP_INT_STATUS_RING0__TIME_STAMP_INT_STAT_MASK 0x4000000
+#define CP_INT_STATUS_RING0__TIME_STAMP_INT_STAT__SHIFT 0x1a
+#define CP_INT_STATUS_RING0__RESERVED_BIT_ERROR_INT_STAT_MASK 0x8000000
+#define CP_INT_STATUS_RING0__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x1b
+#define CP_INT_STATUS_RING0__GENERIC2_INT_STAT_MASK 0x20000000
+#define CP_INT_STATUS_RING0__GENERIC2_INT_STAT__SHIFT 0x1d
+#define CP_INT_STATUS_RING0__GENERIC1_INT_STAT_MASK 0x40000000
+#define CP_INT_STATUS_RING0__GENERIC1_INT_STAT__SHIFT 0x1e
+#define CP_INT_STATUS_RING0__GENERIC0_INT_STAT_MASK 0x80000000
+#define CP_INT_STATUS_RING0__GENERIC0_INT_STAT__SHIFT 0x1f
+#define CP_INT_STATUS_RING1__CP_VM_DOORBELL_WR_INT_STAT_MASK 0x800
+#define CP_INT_STATUS_RING1__CP_VM_DOORBELL_WR_INT_STAT__SHIFT 0xb
+#define CP_INT_STATUS_RING1__CP_ECC_ERROR_INT_STAT_MASK 0x4000
+#define CP_INT_STATUS_RING1__CP_ECC_ERROR_INT_STAT__SHIFT 0xe
+#define CP_INT_STATUS_RING1__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x20000
+#define CP_INT_STATUS_RING1__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x11
+#define CP_INT_STATUS_RING1__CMP_BUSY_INT_STAT_MASK 0x40000
+#define CP_INT_STATUS_RING1__CMP_BUSY_INT_STAT__SHIFT 0x12
+#define CP_INT_STATUS_RING1__CNTX_BUSY_INT_STAT_MASK 0x80000
+#define CP_INT_STATUS_RING1__CNTX_BUSY_INT_STAT__SHIFT 0x13
+#define CP_INT_STATUS_RING1__CNTX_EMPTY_INT_STAT_MASK 0x100000
+#define CP_INT_STATUS_RING1__CNTX_EMPTY_INT_STAT__SHIFT 0x14
+#define CP_INT_STATUS_RING1__GFX_IDLE_INT_STAT_MASK 0x200000
+#define CP_INT_STATUS_RING1__GFX_IDLE_INT_STAT__SHIFT 0x15
+#define CP_INT_STATUS_RING1__PRIV_INSTR_INT_STAT_MASK 0x400000
+#define CP_INT_STATUS_RING1__PRIV_INSTR_INT_STAT__SHIFT 0x16
+#define CP_INT_STATUS_RING1__PRIV_REG_INT_STAT_MASK 0x800000
+#define CP_INT_STATUS_RING1__PRIV_REG_INT_STAT__SHIFT 0x17
+#define CP_INT_STATUS_RING1__OPCODE_ERROR_INT_STAT_MASK 0x1000000
+#define CP_INT_STATUS_RING1__OPCODE_ERROR_INT_STAT__SHIFT 0x18
+#define CP_INT_STATUS_RING1__TIME_STAMP_INT_STAT_MASK 0x4000000
+#define CP_INT_STATUS_RING1__TIME_STAMP_INT_STAT__SHIFT 0x1a
+#define CP_INT_STATUS_RING1__RESERVED_BIT_ERROR_INT_STAT_MASK 0x8000000
+#define CP_INT_STATUS_RING1__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x1b
+#define CP_INT_STATUS_RING1__GENERIC2_INT_STAT_MASK 0x20000000
+#define CP_INT_STATUS_RING1__GENERIC2_INT_STAT__SHIFT 0x1d
+#define CP_INT_STATUS_RING1__GENERIC1_INT_STAT_MASK 0x40000000
+#define CP_INT_STATUS_RING1__GENERIC1_INT_STAT__SHIFT 0x1e
+#define CP_INT_STATUS_RING1__GENERIC0_INT_STAT_MASK 0x80000000
+#define CP_INT_STATUS_RING1__GENERIC0_INT_STAT__SHIFT 0x1f
+#define CP_INT_STATUS_RING2__CP_VM_DOORBELL_WR_INT_STAT_MASK 0x800
+#define CP_INT_STATUS_RING2__CP_VM_DOORBELL_WR_INT_STAT__SHIFT 0xb
+#define CP_INT_STATUS_RING2__CP_ECC_ERROR_INT_STAT_MASK 0x4000
+#define CP_INT_STATUS_RING2__CP_ECC_ERROR_INT_STAT__SHIFT 0xe
+#define CP_INT_STATUS_RING2__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x20000
+#define CP_INT_STATUS_RING2__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x11
+#define CP_INT_STATUS_RING2__CMP_BUSY_INT_STAT_MASK 0x40000
+#define CP_INT_STATUS_RING2__CMP_BUSY_INT_STAT__SHIFT 0x12
+#define CP_INT_STATUS_RING2__CNTX_BUSY_INT_STAT_MASK 0x80000
+#define CP_INT_STATUS_RING2__CNTX_BUSY_INT_STAT__SHIFT 0x13
+#define CP_INT_STATUS_RING2__CNTX_EMPTY_INT_STAT_MASK 0x100000
+#define CP_INT_STATUS_RING2__CNTX_EMPTY_INT_STAT__SHIFT 0x14
+#define CP_INT_STATUS_RING2__GFX_IDLE_INT_STAT_MASK 0x200000
+#define CP_INT_STATUS_RING2__GFX_IDLE_INT_STAT__SHIFT 0x15
+#define CP_INT_STATUS_RING2__PRIV_INSTR_INT_STAT_MASK 0x400000
+#define CP_INT_STATUS_RING2__PRIV_INSTR_INT_STAT__SHIFT 0x16
+#define CP_INT_STATUS_RING2__PRIV_REG_INT_STAT_MASK 0x800000
+#define CP_INT_STATUS_RING2__PRIV_REG_INT_STAT__SHIFT 0x17
+#define CP_INT_STATUS_RING2__OPCODE_ERROR_INT_STAT_MASK 0x1000000
+#define CP_INT_STATUS_RING2__OPCODE_ERROR_INT_STAT__SHIFT 0x18
+#define CP_INT_STATUS_RING2__TIME_STAMP_INT_STAT_MASK 0x4000000
+#define CP_INT_STATUS_RING2__TIME_STAMP_INT_STAT__SHIFT 0x1a
+#define CP_INT_STATUS_RING2__RESERVED_BIT_ERROR_INT_STAT_MASK 0x8000000
+#define CP_INT_STATUS_RING2__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x1b
+#define CP_INT_STATUS_RING2__GENERIC2_INT_STAT_MASK 0x20000000
+#define CP_INT_STATUS_RING2__GENERIC2_INT_STAT__SHIFT 0x1d
+#define CP_INT_STATUS_RING2__GENERIC1_INT_STAT_MASK 0x40000000
+#define CP_INT_STATUS_RING2__GENERIC1_INT_STAT__SHIFT 0x1e
+#define CP_INT_STATUS_RING2__GENERIC0_INT_STAT_MASK 0x80000000
+#define CP_INT_STATUS_RING2__GENERIC0_INT_STAT__SHIFT 0x1f
+#define CP_DEVICE_ID__DEVICE_ID_MASK 0xff
+#define CP_DEVICE_ID__DEVICE_ID__SHIFT 0x0
+#define CP_RING_PRIORITY_CNTS__PRIORITY1_CNT_MASK 0xff
+#define CP_RING_PRIORITY_CNTS__PRIORITY1_CNT__SHIFT 0x0
+#define CP_RING_PRIORITY_CNTS__PRIORITY2A_CNT_MASK 0xff00
+#define CP_RING_PRIORITY_CNTS__PRIORITY2A_CNT__SHIFT 0x8
+#define CP_RING_PRIORITY_CNTS__PRIORITY2B_CNT_MASK 0xff0000
+#define CP_RING_PRIORITY_CNTS__PRIORITY2B_CNT__SHIFT 0x10
+#define CP_RING_PRIORITY_CNTS__PRIORITY3_CNT_MASK 0xff000000
+#define CP_RING_PRIORITY_CNTS__PRIORITY3_CNT__SHIFT 0x18
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY1_CNT_MASK 0xff
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY1_CNT__SHIFT 0x0
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY2A_CNT_MASK 0xff00
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY2A_CNT__SHIFT 0x8
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY2B_CNT_MASK 0xff0000
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY2B_CNT__SHIFT 0x10
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY3_CNT_MASK 0xff000000
+#define CP_ME0_PIPE_PRIORITY_CNTS__PRIORITY3_CNT__SHIFT 0x18
+#define CP_RING0_PRIORITY__PRIORITY_MASK 0x3
+#define CP_RING0_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME0_PIPE0_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME0_PIPE0_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_RING1_PRIORITY__PRIORITY_MASK 0x3
+#define CP_RING1_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME0_PIPE1_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME0_PIPE1_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_RING2_PRIORITY__PRIORITY_MASK 0x3
+#define CP_RING2_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME0_PIPE2_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME0_PIPE2_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ENDIAN_SWAP__ENDIAN_SWAP_MASK 0x3
+#define CP_ENDIAN_SWAP__ENDIAN_SWAP__SHIFT 0x0
+#define CP_RB_VMID__RB0_VMID_MASK 0xf
+#define CP_RB_VMID__RB0_VMID__SHIFT 0x0
+#define CP_RB_VMID__RB1_VMID_MASK 0xf00
+#define CP_RB_VMID__RB1_VMID__SHIFT 0x8
+#define CP_RB_VMID__RB2_VMID_MASK 0xf0000
+#define CP_RB_VMID__RB2_VMID__SHIFT 0x10
+#define CP_ME0_PIPE0_VMID__VMID_MASK 0xf
+#define CP_ME0_PIPE0_VMID__VMID__SHIFT 0x0
+#define CP_ME0_PIPE1_VMID__VMID_MASK 0xf
+#define CP_ME0_PIPE1_VMID__VMID__SHIFT 0x0
+#define CP_RB_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK 0x7ffffc
+#define CP_RB_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT 0x2
+#define CP_RB_DOORBELL_CONTROL__DOORBELL_EN_MASK 0x40000000
+#define CP_RB_DOORBELL_CONTROL__DOORBELL_EN__SHIFT 0x1e
+#define CP_RB_DOORBELL_CONTROL__DOORBELL_HIT_MASK 0x80000000
+#define CP_RB_DOORBELL_CONTROL__DOORBELL_HIT__SHIFT 0x1f
+#define CP_RB_DOORBELL_RANGE_LOWER__DOORBELL_RANGE_LOWER_MASK 0x7ffffc
+#define CP_RB_DOORBELL_RANGE_LOWER__DOORBELL_RANGE_LOWER__SHIFT 0x2
+#define CP_RB_DOORBELL_RANGE_UPPER__DOORBELL_RANGE_UPPER_MASK 0x7ffffc
+#define CP_RB_DOORBELL_RANGE_UPPER__DOORBELL_RANGE_UPPER__SHIFT 0x2
+#define CP_MEC_DOORBELL_RANGE_LOWER__DOORBELL_RANGE_LOWER_MASK 0x7ffffc
+#define CP_MEC_DOORBELL_RANGE_LOWER__DOORBELL_RANGE_LOWER__SHIFT 0x2
+#define CP_MEC_DOORBELL_RANGE_UPPER__DOORBELL_RANGE_UPPER_MASK 0x7ffffc
+#define CP_MEC_DOORBELL_RANGE_UPPER__DOORBELL_RANGE_UPPER__SHIFT 0x2
+#define CP_PFP_UCODE_ADDR__UCODE_ADDR_MASK 0x1fff
+#define CP_PFP_UCODE_ADDR__UCODE_ADDR__SHIFT 0x0
+#define CP_PFP_UCODE_DATA__UCODE_DATA_MASK 0xffffffff
+#define CP_PFP_UCODE_DATA__UCODE_DATA__SHIFT 0x0
+#define CP_ME_RAM_RADDR__ME_RAM_RADDR_MASK 0x1fff
+#define CP_ME_RAM_RADDR__ME_RAM_RADDR__SHIFT 0x0
+#define CP_ME_RAM_WADDR__ME_RAM_WADDR_MASK 0x1fff
+#define CP_ME_RAM_WADDR__ME_RAM_WADDR__SHIFT 0x0
+#define CP_ME_RAM_DATA__ME_RAM_DATA_MASK 0xffffffff
+#define CP_ME_RAM_DATA__ME_RAM_DATA__SHIFT 0x0
+#define CGTT_CPC_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_CPC_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_CPC_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_CPC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_CPC_CLK_CTRL__SOFT_OVERRIDE_PERFMON_MASK 0x20000000
+#define CGTT_CPC_CLK_CTRL__SOFT_OVERRIDE_PERFMON__SHIFT 0x1d
+#define CGTT_CPC_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000
+#define CGTT_CPC_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x1e
+#define CGTT_CPC_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000
+#define CGTT_CPC_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x1f
+#define CGTT_CPF_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_CPF_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_CPF_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_CPF_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_CPF_CLK_CTRL__SOFT_OVERRIDE_PERFMON_MASK 0x20000000
+#define CGTT_CPF_CLK_CTRL__SOFT_OVERRIDE_PERFMON__SHIFT 0x1d
+#define CGTT_CPF_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000
+#define CGTT_CPF_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x1e
+#define CGTT_CPF_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000
+#define CGTT_CPF_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x1f
+#define CGTT_CP_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_CP_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_CP_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_CP_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_PERFMON_MASK 0x20000000
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_PERFMON__SHIFT 0x1d
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x1e
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x1f
+#define CP_CE_UCODE_ADDR__UCODE_ADDR_MASK 0xfff
+#define CP_CE_UCODE_ADDR__UCODE_ADDR__SHIFT 0x0
+#define CP_CE_UCODE_DATA__UCODE_DATA_MASK 0xffffffff
+#define CP_CE_UCODE_DATA__UCODE_DATA__SHIFT 0x0
+#define CP_MEC_ME1_UCODE_ADDR__UCODE_ADDR_MASK 0x1ffff
+#define CP_MEC_ME1_UCODE_ADDR__UCODE_ADDR__SHIFT 0x0
+#define CP_MEC_ME1_UCODE_DATA__UCODE_DATA_MASK 0xffffffff
+#define CP_MEC_ME1_UCODE_DATA__UCODE_DATA__SHIFT 0x0
+#define CP_MEC_ME2_UCODE_ADDR__UCODE_ADDR_MASK 0x1ffff
+#define CP_MEC_ME2_UCODE_ADDR__UCODE_ADDR__SHIFT 0x0
+#define CP_MEC_ME2_UCODE_DATA__UCODE_DATA_MASK 0xffffffff
+#define CP_MEC_ME2_UCODE_DATA__UCODE_DATA__SHIFT 0x0
+#define CP_PFP_F32_INTERRUPT__PRIV_REG_INT_MASK 0x2
+#define CP_PFP_F32_INTERRUPT__PRIV_REG_INT__SHIFT 0x1
+#define CP_MEC1_F32_INTERRUPT__PRIV_REG_INT_MASK 0x2
+#define CP_MEC1_F32_INTERRUPT__PRIV_REG_INT__SHIFT 0x1
+#define CP_MEC2_F32_INTERRUPT__PRIV_REG_INT_MASK 0x2
+#define CP_MEC2_F32_INTERRUPT__PRIV_REG_INT__SHIFT 0x1
+#define CP_MEC1_F32_INT_DIS__EDC_ROQ_FED_INT_MASK 0x1
+#define CP_MEC1_F32_INT_DIS__EDC_ROQ_FED_INT__SHIFT 0x0
+#define CP_MEC1_F32_INT_DIS__PRIV_REG_INT_MASK 0x2
+#define CP_MEC1_F32_INT_DIS__PRIV_REG_INT__SHIFT 0x1
+#define CP_MEC1_F32_INT_DIS__RESERVED_BIT_ERR_INT_MASK 0x4
+#define CP_MEC1_F32_INT_DIS__RESERVED_BIT_ERR_INT__SHIFT 0x2
+#define CP_MEC1_F32_INT_DIS__EDC_TC_FED_INT_MASK 0x8
+#define CP_MEC1_F32_INT_DIS__EDC_TC_FED_INT__SHIFT 0x3
+#define CP_MEC1_F32_INT_DIS__EDC_GDS_FED_INT_MASK 0x10
+#define CP_MEC1_F32_INT_DIS__EDC_GDS_FED_INT__SHIFT 0x4
+#define CP_MEC1_F32_INT_DIS__EDC_SCRATCH_FED_INT_MASK 0x20
+#define CP_MEC1_F32_INT_DIS__EDC_SCRATCH_FED_INT__SHIFT 0x5
+#define CP_MEC1_F32_INT_DIS__WAVE_RESTORE_INT_MASK 0x40
+#define CP_MEC1_F32_INT_DIS__WAVE_RESTORE_INT__SHIFT 0x6
+#define CP_MEC1_F32_INT_DIS__SUA_VIOLATION_INT_MASK 0x80
+#define CP_MEC1_F32_INT_DIS__SUA_VIOLATION_INT__SHIFT 0x7
+#define CP_MEC1_F32_INT_DIS__EDC_DMA_FED_INT_MASK 0x100
+#define CP_MEC1_F32_INT_DIS__EDC_DMA_FED_INT__SHIFT 0x8
+#define CP_MEC1_F32_INT_DIS__IQ_TIMER_INT_MASK 0x200
+#define CP_MEC1_F32_INT_DIS__IQ_TIMER_INT__SHIFT 0x9
+#define CP_MEC2_F32_INT_DIS__EDC_ROQ_FED_INT_MASK 0x1
+#define CP_MEC2_F32_INT_DIS__EDC_ROQ_FED_INT__SHIFT 0x0
+#define CP_MEC2_F32_INT_DIS__PRIV_REG_INT_MASK 0x2
+#define CP_MEC2_F32_INT_DIS__PRIV_REG_INT__SHIFT 0x1
+#define CP_MEC2_F32_INT_DIS__RESERVED_BIT_ERR_INT_MASK 0x4
+#define CP_MEC2_F32_INT_DIS__RESERVED_BIT_ERR_INT__SHIFT 0x2
+#define CP_MEC2_F32_INT_DIS__EDC_TC_FED_INT_MASK 0x8
+#define CP_MEC2_F32_INT_DIS__EDC_TC_FED_INT__SHIFT 0x3
+#define CP_MEC2_F32_INT_DIS__EDC_GDS_FED_INT_MASK 0x10
+#define CP_MEC2_F32_INT_DIS__EDC_GDS_FED_INT__SHIFT 0x4
+#define CP_MEC2_F32_INT_DIS__EDC_SCRATCH_FED_INT_MASK 0x20
+#define CP_MEC2_F32_INT_DIS__EDC_SCRATCH_FED_INT__SHIFT 0x5
+#define CP_MEC2_F32_INT_DIS__WAVE_RESTORE_INT_MASK 0x40
+#define CP_MEC2_F32_INT_DIS__WAVE_RESTORE_INT__SHIFT 0x6
+#define CP_MEC2_F32_INT_DIS__SUA_VIOLATION_INT_MASK 0x80
+#define CP_MEC2_F32_INT_DIS__SUA_VIOLATION_INT__SHIFT 0x7
+#define CP_MEC2_F32_INT_DIS__EDC_DMA_FED_INT_MASK 0x100
+#define CP_MEC2_F32_INT_DIS__EDC_DMA_FED_INT__SHIFT 0x8
+#define CP_MEC2_F32_INT_DIS__IQ_TIMER_INT_MASK 0x200
+#define CP_MEC2_F32_INT_DIS__IQ_TIMER_INT__SHIFT 0x9
+#define CP_PWR_CNTL__GFX_CLK_HALT_ME0_PIPE0_MASK 0x1
+#define CP_PWR_CNTL__GFX_CLK_HALT_ME0_PIPE0__SHIFT 0x0
+#define CP_PWR_CNTL__GFX_CLK_HALT_ME0_PIPE1_MASK 0x2
+#define CP_PWR_CNTL__GFX_CLK_HALT_ME0_PIPE1__SHIFT 0x1
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE0_MASK 0x100
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE0__SHIFT 0x8
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE1_MASK 0x200
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE1__SHIFT 0x9
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE2_MASK 0x400
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE2__SHIFT 0xa
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE3_MASK 0x800
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME1_PIPE3__SHIFT 0xb
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE0_MASK 0x10000
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE0__SHIFT 0x10
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE1_MASK 0x20000
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE1__SHIFT 0x11
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE2_MASK 0x40000
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE2__SHIFT 0x12
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE3_MASK 0x80000
+#define CP_PWR_CNTL__CMP_CLK_HALT_ME2_PIPE3__SHIFT 0x13
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK 0x1
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_EN__SHIFT 0x0
+#define CP_MEM_SLP_CNTL__CP_MEM_DS_EN_MASK 0x2
+#define CP_MEM_SLP_CNTL__CP_MEM_DS_EN__SHIFT 0x1
+#define CP_MEM_SLP_CNTL__RESERVED_MASK 0x7c
+#define CP_MEM_SLP_CNTL__RESERVED__SHIFT 0x2
+#define CP_MEM_SLP_CNTL__CP_LS_DS_BUSY_OVERRIDE_MASK 0x80
+#define CP_MEM_SLP_CNTL__CP_LS_DS_BUSY_OVERRIDE__SHIFT 0x7
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_ON_DELAY_MASK 0xff00
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_ON_DELAY__SHIFT 0x8
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_OFF_DELAY_MASK 0xff0000
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_OFF_DELAY__SHIFT 0x10
+#define CP_MEM_SLP_CNTL__RESERVED1_MASK 0xff000000
+#define CP_MEM_SLP_CNTL__RESERVED1__SHIFT 0x18
+#define CP_ECC_FIRSTOCCURRENCE__INTERFACE_MASK 0x3
+#define CP_ECC_FIRSTOCCURRENCE__INTERFACE__SHIFT 0x0
+#define CP_ECC_FIRSTOCCURRENCE__CLIENT_MASK 0xf0
+#define CP_ECC_FIRSTOCCURRENCE__CLIENT__SHIFT 0x4
+#define CP_ECC_FIRSTOCCURRENCE__ME_MASK 0x300
+#define CP_ECC_FIRSTOCCURRENCE__ME__SHIFT 0x8
+#define CP_ECC_FIRSTOCCURRENCE__PIPE_MASK 0xc00
+#define CP_ECC_FIRSTOCCURRENCE__PIPE__SHIFT 0xa
+#define CP_ECC_FIRSTOCCURRENCE__QUEUE_MASK 0x7000
+#define CP_ECC_FIRSTOCCURRENCE__QUEUE__SHIFT 0xc
+#define CP_ECC_FIRSTOCCURRENCE__VMID_MASK 0xf0000
+#define CP_ECC_FIRSTOCCURRENCE__VMID__SHIFT 0x10
+#define CP_ECC_FIRSTOCCURRENCE_RING0__OBSOLETE_MASK 0xffffffff
+#define CP_ECC_FIRSTOCCURRENCE_RING0__OBSOLETE__SHIFT 0x0
+#define CP_ECC_FIRSTOCCURRENCE_RING1__OBSOLETE_MASK 0xffffffff
+#define CP_ECC_FIRSTOCCURRENCE_RING1__OBSOLETE__SHIFT 0x0
+#define CP_ECC_FIRSTOCCURRENCE_RING2__OBSOLETE_MASK 0xffffffff
+#define CP_ECC_FIRSTOCCURRENCE_RING2__OBSOLETE__SHIFT 0x0
+#define CP_PQ_WPTR_POLL_CNTL__PERIOD_MASK 0xff
+#define CP_PQ_WPTR_POLL_CNTL__PERIOD__SHIFT 0x0
+#define CP_PQ_WPTR_POLL_CNTL__POLL_ACTIVE_MASK 0x40000000
+#define CP_PQ_WPTR_POLL_CNTL__POLL_ACTIVE__SHIFT 0x1e
+#define CP_PQ_WPTR_POLL_CNTL__EN_MASK 0x80000000
+#define CP_PQ_WPTR_POLL_CNTL__EN__SHIFT 0x1f
+#define CP_PQ_WPTR_POLL_CNTL1__QUEUE_MASK_MASK 0xffffffff
+#define CP_PQ_WPTR_POLL_CNTL1__QUEUE_MASK__SHIFT 0x0
+#define CPC_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CPC_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CPC_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CPC_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CPC_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CPC_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CPC_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CPC_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CPC_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CPC_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CPC_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CPC_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CPC_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CPC_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CPC_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CPC_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CPC_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CPC_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CPC_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CPC_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CPC_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CPC_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CPC_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CPC_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME1_PIPE0_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME1_PIPE0_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME1_PIPE0_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME1_PIPE0_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME1_PIPE0_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME1_PIPE0_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME1_PIPE0_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME1_PIPE0_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME1_PIPE0_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME1_PIPE0_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME1_PIPE0_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME1_PIPE0_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME1_PIPE0_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME1_PIPE0_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME1_PIPE0_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME1_PIPE0_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME1_PIPE0_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME1_PIPE0_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME1_PIPE0_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME1_PIPE0_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME1_PIPE0_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME1_PIPE0_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME1_PIPE0_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME1_PIPE0_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME1_PIPE1_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME1_PIPE1_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME1_PIPE1_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME1_PIPE1_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME1_PIPE1_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME1_PIPE1_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME1_PIPE1_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME1_PIPE1_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME1_PIPE1_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME1_PIPE1_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME1_PIPE1_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME1_PIPE1_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME1_PIPE1_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME1_PIPE1_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME1_PIPE1_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME1_PIPE1_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME1_PIPE1_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME1_PIPE1_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME1_PIPE1_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME1_PIPE1_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME1_PIPE1_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME1_PIPE1_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME1_PIPE1_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME1_PIPE1_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME1_PIPE2_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME1_PIPE2_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME1_PIPE2_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME1_PIPE2_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME1_PIPE2_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME1_PIPE2_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME1_PIPE2_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME1_PIPE2_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME1_PIPE2_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME1_PIPE2_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME1_PIPE2_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME1_PIPE2_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME1_PIPE2_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME1_PIPE2_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME1_PIPE2_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME1_PIPE2_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME1_PIPE2_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME1_PIPE2_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME1_PIPE2_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME1_PIPE2_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME1_PIPE2_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME1_PIPE2_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME1_PIPE2_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME1_PIPE2_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME1_PIPE3_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME1_PIPE3_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME1_PIPE3_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME1_PIPE3_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME1_PIPE3_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME1_PIPE3_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME1_PIPE3_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME1_PIPE3_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME1_PIPE3_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME1_PIPE3_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME1_PIPE3_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME1_PIPE3_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME1_PIPE3_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME1_PIPE3_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME1_PIPE3_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME1_PIPE3_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME1_PIPE3_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME1_PIPE3_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME1_PIPE3_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME1_PIPE3_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME1_PIPE3_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME1_PIPE3_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME1_PIPE3_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME1_PIPE3_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME2_PIPE0_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME2_PIPE0_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME2_PIPE0_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME2_PIPE0_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME2_PIPE0_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME2_PIPE0_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME2_PIPE0_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME2_PIPE0_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME2_PIPE0_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME2_PIPE0_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME2_PIPE0_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME2_PIPE0_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME2_PIPE0_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME2_PIPE0_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME2_PIPE0_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME2_PIPE0_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME2_PIPE0_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME2_PIPE0_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME2_PIPE0_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME2_PIPE0_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME2_PIPE0_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME2_PIPE0_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME2_PIPE0_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME2_PIPE0_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME2_PIPE1_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME2_PIPE1_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME2_PIPE1_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME2_PIPE1_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME2_PIPE1_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME2_PIPE1_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME2_PIPE1_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME2_PIPE1_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME2_PIPE1_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME2_PIPE1_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME2_PIPE1_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME2_PIPE1_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME2_PIPE1_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME2_PIPE1_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME2_PIPE1_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME2_PIPE1_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME2_PIPE1_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME2_PIPE1_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME2_PIPE1_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME2_PIPE1_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME2_PIPE1_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME2_PIPE1_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME2_PIPE1_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME2_PIPE1_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME2_PIPE2_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME2_PIPE2_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME2_PIPE2_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME2_PIPE2_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME2_PIPE2_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME2_PIPE2_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME2_PIPE2_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME2_PIPE2_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME2_PIPE2_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME2_PIPE2_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME2_PIPE2_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME2_PIPE2_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME2_PIPE2_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME2_PIPE2_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME2_PIPE2_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME2_PIPE2_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME2_PIPE2_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME2_PIPE2_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME2_PIPE2_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME2_PIPE2_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME2_PIPE2_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME2_PIPE2_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME2_PIPE2_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME2_PIPE2_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CP_ME2_PIPE3_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE_MASK 0x1000
+#define CP_ME2_PIPE3_INT_CNTL__CMP_QUERY_STATUS_INT_ENABLE__SHIFT 0xc
+#define CP_ME2_PIPE3_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE_MASK 0x2000
+#define CP_ME2_PIPE3_INT_CNTL__DEQUEUE_REQUEST_INT_ENABLE__SHIFT 0xd
+#define CP_ME2_PIPE3_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x4000
+#define CP_ME2_PIPE3_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0xe
+#define CP_ME2_PIPE3_INT_CNTL__SUA_VIOLATION_INT_ENABLE_MASK 0x8000
+#define CP_ME2_PIPE3_INT_CNTL__SUA_VIOLATION_INT_ENABLE__SHIFT 0xf
+#define CP_ME2_PIPE3_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x20000
+#define CP_ME2_PIPE3_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x11
+#define CP_ME2_PIPE3_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x800000
+#define CP_ME2_PIPE3_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x17
+#define CP_ME2_PIPE3_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x1000000
+#define CP_ME2_PIPE3_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x18
+#define CP_ME2_PIPE3_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x4000000
+#define CP_ME2_PIPE3_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x1a
+#define CP_ME2_PIPE3_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x8000000
+#define CP_ME2_PIPE3_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x1b
+#define CP_ME2_PIPE3_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000
+#define CP_ME2_PIPE3_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x1d
+#define CP_ME2_PIPE3_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000
+#define CP_ME2_PIPE3_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x1e
+#define CP_ME2_PIPE3_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000
+#define CP_ME2_PIPE3_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x1f
+#define CPC_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CPC_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CPC_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CPC_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CPC_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CPC_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CPC_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CPC_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CPC_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CPC_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CPC_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CPC_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CPC_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CPC_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CPC_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CPC_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CPC_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CPC_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CPC_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CPC_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CPC_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CPC_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CPC_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CPC_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME1_PIPE0_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME1_PIPE0_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME1_PIPE0_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME1_PIPE0_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME1_PIPE0_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME1_PIPE0_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME1_PIPE0_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME1_PIPE0_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME1_PIPE0_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME1_PIPE0_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME1_PIPE0_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME1_PIPE0_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME1_PIPE0_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME1_PIPE0_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME1_PIPE0_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME1_PIPE0_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME1_PIPE0_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME1_PIPE0_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME1_PIPE0_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME1_PIPE0_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME1_PIPE0_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME1_PIPE0_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME1_PIPE0_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME1_PIPE0_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME1_PIPE1_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME1_PIPE1_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME1_PIPE1_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME1_PIPE1_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME1_PIPE1_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME1_PIPE1_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME1_PIPE1_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME1_PIPE1_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME1_PIPE1_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME1_PIPE1_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME1_PIPE1_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME1_PIPE1_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME1_PIPE1_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME1_PIPE1_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME1_PIPE1_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME1_PIPE1_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME1_PIPE1_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME1_PIPE1_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME1_PIPE1_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME1_PIPE1_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME1_PIPE1_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME1_PIPE1_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME1_PIPE1_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME1_PIPE1_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME1_PIPE2_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME1_PIPE2_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME1_PIPE2_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME1_PIPE2_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME1_PIPE2_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME1_PIPE2_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME1_PIPE2_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME1_PIPE2_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME1_PIPE2_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME1_PIPE2_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME1_PIPE2_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME1_PIPE2_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME1_PIPE2_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME1_PIPE2_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME1_PIPE2_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME1_PIPE2_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME1_PIPE2_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME1_PIPE2_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME1_PIPE2_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME1_PIPE2_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME1_PIPE2_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME1_PIPE2_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME1_PIPE2_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME1_PIPE2_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME1_PIPE3_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME1_PIPE3_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME1_PIPE3_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME1_PIPE3_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME1_PIPE3_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME1_PIPE3_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME1_PIPE3_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME1_PIPE3_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME1_PIPE3_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME1_PIPE3_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME1_PIPE3_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME1_PIPE3_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME1_PIPE3_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME1_PIPE3_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME1_PIPE3_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME1_PIPE3_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME1_PIPE3_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME1_PIPE3_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME1_PIPE3_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME1_PIPE3_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME1_PIPE3_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME1_PIPE3_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME1_PIPE3_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME1_PIPE3_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME2_PIPE0_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME2_PIPE0_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME2_PIPE0_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME2_PIPE0_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME2_PIPE0_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME2_PIPE0_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME2_PIPE0_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME2_PIPE0_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME2_PIPE0_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME2_PIPE0_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME2_PIPE0_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME2_PIPE0_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME2_PIPE0_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME2_PIPE0_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME2_PIPE0_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME2_PIPE0_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME2_PIPE0_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME2_PIPE0_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME2_PIPE0_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME2_PIPE0_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME2_PIPE0_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME2_PIPE0_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME2_PIPE0_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME2_PIPE0_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME2_PIPE1_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME2_PIPE1_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME2_PIPE1_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME2_PIPE1_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME2_PIPE1_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME2_PIPE1_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME2_PIPE1_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME2_PIPE1_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME2_PIPE1_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME2_PIPE1_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME2_PIPE1_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME2_PIPE1_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME2_PIPE1_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME2_PIPE1_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME2_PIPE1_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME2_PIPE1_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME2_PIPE1_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME2_PIPE1_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME2_PIPE1_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME2_PIPE1_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME2_PIPE1_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME2_PIPE1_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME2_PIPE1_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME2_PIPE1_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME2_PIPE2_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME2_PIPE2_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME2_PIPE2_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME2_PIPE2_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME2_PIPE2_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME2_PIPE2_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME2_PIPE2_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME2_PIPE2_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME2_PIPE2_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME2_PIPE2_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME2_PIPE2_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME2_PIPE2_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME2_PIPE2_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME2_PIPE2_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME2_PIPE2_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME2_PIPE2_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME2_PIPE2_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME2_PIPE2_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME2_PIPE2_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME2_PIPE2_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME2_PIPE2_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME2_PIPE2_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME2_PIPE2_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME2_PIPE2_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME2_PIPE3_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS_MASK 0x1000
+#define CP_ME2_PIPE3_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
+#define CP_ME2_PIPE3_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS_MASK 0x2000
+#define CP_ME2_PIPE3_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
+#define CP_ME2_PIPE3_INT_STATUS__CP_ECC_ERROR_INT_STATUS_MASK 0x4000
+#define CP_ME2_PIPE3_INT_STATUS__CP_ECC_ERROR_INT_STATUS__SHIFT 0xe
+#define CP_ME2_PIPE3_INT_STATUS__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME2_PIPE3_INT_STATUS__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME2_PIPE3_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS_MASK 0x20000
+#define CP_ME2_PIPE3_INT_STATUS__WRM_POLL_TIMEOUT_INT_STATUS__SHIFT 0x11
+#define CP_ME2_PIPE3_INT_STATUS__PRIV_REG_INT_STATUS_MASK 0x800000
+#define CP_ME2_PIPE3_INT_STATUS__PRIV_REG_INT_STATUS__SHIFT 0x17
+#define CP_ME2_PIPE3_INT_STATUS__OPCODE_ERROR_INT_STATUS_MASK 0x1000000
+#define CP_ME2_PIPE3_INT_STATUS__OPCODE_ERROR_INT_STATUS__SHIFT 0x18
+#define CP_ME2_PIPE3_INT_STATUS__TIME_STAMP_INT_STATUS_MASK 0x4000000
+#define CP_ME2_PIPE3_INT_STATUS__TIME_STAMP_INT_STATUS__SHIFT 0x1a
+#define CP_ME2_PIPE3_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS_MASK 0x8000000
+#define CP_ME2_PIPE3_INT_STATUS__RESERVED_BIT_ERROR_INT_STATUS__SHIFT 0x1b
+#define CP_ME2_PIPE3_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000
+#define CP_ME2_PIPE3_INT_STATUS__GENERIC2_INT_STATUS__SHIFT 0x1d
+#define CP_ME2_PIPE3_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000
+#define CP_ME2_PIPE3_INT_STATUS__GENERIC1_INT_STATUS__SHIFT 0x1e
+#define CP_ME2_PIPE3_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000
+#define CP_ME2_PIPE3_INT_STATUS__GENERIC0_INT_STATUS__SHIFT 0x1f
+#define CP_ME1_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED_MASK 0x1000
+#define CP_ME1_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED__SHIFT 0xc
+#define CP_ME1_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED_MASK 0x2000
+#define CP_ME1_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED__SHIFT 0xd
+#define CP_ME1_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x4000
+#define CP_ME1_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
+#define CP_ME1_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME1_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME1_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x20000
+#define CP_ME1_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
+#define CP_ME1_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x800000
+#define CP_ME1_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
+#define CP_ME1_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x1000000
+#define CP_ME1_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
+#define CP_ME1_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x4000000
+#define CP_ME1_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
+#define CP_ME1_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x8000000
+#define CP_ME1_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
+#define CP_ME1_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000
+#define CP_ME1_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
+#define CP_ME1_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000
+#define CP_ME1_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
+#define CP_ME1_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000
+#define CP_ME1_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
+#define CP_ME2_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED_MASK 0x1000
+#define CP_ME2_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED__SHIFT 0xc
+#define CP_ME2_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED_MASK 0x2000
+#define CP_ME2_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED__SHIFT 0xd
+#define CP_ME2_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x4000
+#define CP_ME2_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
+#define CP_ME2_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS_MASK 0x8000
+#define CP_ME2_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME2_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x20000
+#define CP_ME2_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
+#define CP_ME2_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x800000
+#define CP_ME2_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
+#define CP_ME2_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x1000000
+#define CP_ME2_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
+#define CP_ME2_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x4000000
+#define CP_ME2_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
+#define CP_ME2_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x8000000
+#define CP_ME2_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
+#define CP_ME2_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000
+#define CP_ME2_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
+#define CP_ME2_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000
+#define CP_ME2_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
+#define CP_ME2_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000
+#define CP_ME2_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY1_CNT_MASK 0xff
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY1_CNT__SHIFT 0x0
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY2A_CNT_MASK 0xff00
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY2A_CNT__SHIFT 0x8
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY2B_CNT_MASK 0xff0000
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY2B_CNT__SHIFT 0x10
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY3_CNT_MASK 0xff000000
+#define CP_ME1_PIPE_PRIORITY_CNTS__PRIORITY3_CNT__SHIFT 0x18
+#define CP_ME1_PIPE0_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME1_PIPE0_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME1_PIPE1_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME1_PIPE1_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME1_PIPE2_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME1_PIPE2_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME1_PIPE3_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME1_PIPE3_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY1_CNT_MASK 0xff
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY1_CNT__SHIFT 0x0
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY2A_CNT_MASK 0xff00
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY2A_CNT__SHIFT 0x8
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY2B_CNT_MASK 0xff0000
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY2B_CNT__SHIFT 0x10
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY3_CNT_MASK 0xff000000
+#define CP_ME2_PIPE_PRIORITY_CNTS__PRIORITY3_CNT__SHIFT 0x18
+#define CP_ME2_PIPE0_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME2_PIPE0_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME2_PIPE1_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME2_PIPE1_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME2_PIPE2_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME2_PIPE2_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_ME2_PIPE3_PRIORITY__PRIORITY_MASK 0x3
+#define CP_ME2_PIPE3_PRIORITY__PRIORITY__SHIFT 0x0
+#define CP_CE_PRGRM_CNTR_START__IP_START_MASK 0x7ff
+#define CP_CE_PRGRM_CNTR_START__IP_START__SHIFT 0x0
+#define CP_PFP_PRGRM_CNTR_START__IP_START_MASK 0xfff
+#define CP_PFP_PRGRM_CNTR_START__IP_START__SHIFT 0x0
+#define CP_ME_PRGRM_CNTR_START__IP_START_MASK 0xfff
+#define CP_ME_PRGRM_CNTR_START__IP_START__SHIFT 0x0
+#define CP_MEC1_PRGRM_CNTR_START__IP_START_MASK 0xffff
+#define CP_MEC1_PRGRM_CNTR_START__IP_START__SHIFT 0x0
+#define CP_MEC2_PRGRM_CNTR_START__IP_START_MASK 0xffff
+#define CP_MEC2_PRGRM_CNTR_START__IP_START__SHIFT 0x0
+#define CP_CE_INTR_ROUTINE_START__IR_START_MASK 0x7ff
+#define CP_CE_INTR_ROUTINE_START__IR_START__SHIFT 0x0
+#define CP_PFP_INTR_ROUTINE_START__IR_START_MASK 0xfff
+#define CP_PFP_INTR_ROUTINE_START__IR_START__SHIFT 0x0
+#define CP_ME_INTR_ROUTINE_START__IR_START_MASK 0xfff
+#define CP_ME_INTR_ROUTINE_START__IR_START__SHIFT 0x0
+#define CP_MEC1_INTR_ROUTINE_START__IR_START_MASK 0xffff
+#define CP_MEC1_INTR_ROUTINE_START__IR_START__SHIFT 0x0
+#define CP_MEC2_INTR_ROUTINE_START__IR_START_MASK 0xffff
+#define CP_MEC2_INTR_ROUTINE_START__IR_START__SHIFT 0x0
+#define CP_CONTEXT_CNTL__ME0PIPE0_MAX_WD_CNTX_MASK 0x7
+#define CP_CONTEXT_CNTL__ME0PIPE0_MAX_WD_CNTX__SHIFT 0x0
+#define CP_CONTEXT_CNTL__ME0PIPE0_MAX_PIPE_CNTX_MASK 0x70
+#define CP_CONTEXT_CNTL__ME0PIPE0_MAX_PIPE_CNTX__SHIFT 0x4
+#define CP_CONTEXT_CNTL__ME0PIPE1_MAX_WD_CNTX_MASK 0x70000
+#define CP_CONTEXT_CNTL__ME0PIPE1_MAX_WD_CNTX__SHIFT 0x10
+#define CP_CONTEXT_CNTL__ME0PIPE1_MAX_PIPE_CNTX_MASK 0x700000
+#define CP_CONTEXT_CNTL__ME0PIPE1_MAX_PIPE_CNTX__SHIFT 0x14
+#define CP_MAX_CONTEXT__MAX_CONTEXT_MASK 0x7
+#define CP_MAX_CONTEXT__MAX_CONTEXT__SHIFT 0x0
+#define CP_IQ_WAIT_TIME1__IB_OFFLOAD_MASK 0xff
+#define CP_IQ_WAIT_TIME1__IB_OFFLOAD__SHIFT 0x0
+#define CP_IQ_WAIT_TIME1__ATOMIC_OFFLOAD_MASK 0xff00
+#define CP_IQ_WAIT_TIME1__ATOMIC_OFFLOAD__SHIFT 0x8
+#define CP_IQ_WAIT_TIME1__WRM_OFFLOAD_MASK 0xff0000
+#define CP_IQ_WAIT_TIME1__WRM_OFFLOAD__SHIFT 0x10
+#define CP_IQ_WAIT_TIME1__GWS_MASK 0xff000000
+#define CP_IQ_WAIT_TIME1__GWS__SHIFT 0x18
+#define CP_IQ_WAIT_TIME2__QUE_SLEEP_MASK 0xff
+#define CP_IQ_WAIT_TIME2__QUE_SLEEP__SHIFT 0x0
+#define CP_IQ_WAIT_TIME2__SCH_WAVE_MASK 0xff00
+#define CP_IQ_WAIT_TIME2__SCH_WAVE__SHIFT 0x8
+#define CP_IQ_WAIT_TIME2__SEM_REARM_MASK 0xff0000
+#define CP_IQ_WAIT_TIME2__SEM_REARM__SHIFT 0x10
+#define CP_IQ_WAIT_TIME2__DEQ_RETRY_MASK 0xff000000
+#define CP_IQ_WAIT_TIME2__DEQ_RETRY__SHIFT 0x18
+#define CP_VMID_RESET__RESET_REQUEST_MASK 0xffff
+#define CP_VMID_RESET__RESET_REQUEST__SHIFT 0x0
+#define CP_VMID_RESET__RESET_STATUS_MASK 0xffff0000
+#define CP_VMID_RESET__RESET_STATUS__SHIFT 0x10
+#define CP_VMID_PREEMPT__PREEMPT_REQUEST_MASK 0xffff
+#define CP_VMID_PREEMPT__PREEMPT_REQUEST__SHIFT 0x0
+#define CP_VMID_PREEMPT__VIRT_COMMAND_MASK 0xf0000
+#define CP_VMID_PREEMPT__VIRT_COMMAND__SHIFT 0x10
+#define CP_VMID_STATUS__PREEMPT_DE_STATUS_MASK 0xffff
+#define CP_VMID_STATUS__PREEMPT_DE_STATUS__SHIFT 0x0
+#define CP_VMID_STATUS__PREEMPT_CE_STATUS_MASK 0xffff0000
+#define CP_VMID_STATUS__PREEMPT_CE_STATUS__SHIFT 0x10
+#define CPC_INT_CNTX_ID__CNTX_ID_MASK 0xfffffff
+#define CPC_INT_CNTX_ID__CNTX_ID__SHIFT 0x0
+#define CPC_INT_CNTX_ID__QUEUE_ID_MASK 0x70000000
+#define CPC_INT_CNTX_ID__QUEUE_ID__SHIFT 0x1c
+#define CP_PQ_STATUS__DOORBELL_UPDATED_MASK 0x1
+#define CP_PQ_STATUS__DOORBELL_UPDATED__SHIFT 0x0
+#define CP_PQ_STATUS__DOORBELL_ENABLE_MASK 0x2
+#define CP_PQ_STATUS__DOORBELL_ENABLE__SHIFT 0x1
+#define CP_CPC_IC_BASE_LO__IC_BASE_LO_MASK 0xfffff000
+#define CP_CPC_IC_BASE_LO__IC_BASE_LO__SHIFT 0xc
+#define CP_CPC_IC_BASE_HI__IC_BASE_HI_MASK 0xffff
+#define CP_CPC_IC_BASE_HI__IC_BASE_HI__SHIFT 0x0
+#define CP_CPC_IC_BASE_CNTL__VMID_MASK 0xf
+#define CP_CPC_IC_BASE_CNTL__VMID__SHIFT 0x0
+#define CP_CPC_IC_BASE_CNTL__ATC_MASK 0x800000
+#define CP_CPC_IC_BASE_CNTL__ATC__SHIFT 0x17
+#define CP_CPC_IC_BASE_CNTL__CACHE_POLICY_MASK 0x1000000
+#define CP_CPC_IC_BASE_CNTL__CACHE_POLICY__SHIFT 0x18
+#define CP_CPC_IC_BASE_CNTL__MTYPE_MASK 0x18000000
+#define CP_CPC_IC_BASE_CNTL__MTYPE__SHIFT 0x1b
+#define CP_CPC_IC_OP_CNTL__INVALIDATE_CACHE_MASK 0x1
+#define CP_CPC_IC_OP_CNTL__INVALIDATE_CACHE__SHIFT 0x0
+#define CP_CPC_IC_OP_CNTL__PRIME_ICACHE_MASK 0x10
+#define CP_CPC_IC_OP_CNTL__PRIME_ICACHE__SHIFT 0x4
+#define CP_CPC_IC_OP_CNTL__ICACHE_PRIMED_MASK 0x20
+#define CP_CPC_IC_OP_CNTL__ICACHE_PRIMED__SHIFT 0x5
+#define CP_CPC_STATUS__MEC1_BUSY_MASK 0x1
+#define CP_CPC_STATUS__MEC1_BUSY__SHIFT 0x0
+#define CP_CPC_STATUS__MEC2_BUSY_MASK 0x2
+#define CP_CPC_STATUS__MEC2_BUSY__SHIFT 0x1
+#define CP_CPC_STATUS__DC0_BUSY_MASK 0x4
+#define CP_CPC_STATUS__DC0_BUSY__SHIFT 0x2
+#define CP_CPC_STATUS__DC1_BUSY_MASK 0x8
+#define CP_CPC_STATUS__DC1_BUSY__SHIFT 0x3
+#define CP_CPC_STATUS__RCIU1_BUSY_MASK 0x10
+#define CP_CPC_STATUS__RCIU1_BUSY__SHIFT 0x4
+#define CP_CPC_STATUS__RCIU2_BUSY_MASK 0x20
+#define CP_CPC_STATUS__RCIU2_BUSY__SHIFT 0x5
+#define CP_CPC_STATUS__ROQ1_BUSY_MASK 0x40
+#define CP_CPC_STATUS__ROQ1_BUSY__SHIFT 0x6
+#define CP_CPC_STATUS__ROQ2_BUSY_MASK 0x80
+#define CP_CPC_STATUS__ROQ2_BUSY__SHIFT 0x7
+#define CP_CPC_STATUS__TCIU_BUSY_MASK 0x400
+#define CP_CPC_STATUS__TCIU_BUSY__SHIFT 0xa
+#define CP_CPC_STATUS__SCRATCH_RAM_BUSY_MASK 0x800
+#define CP_CPC_STATUS__SCRATCH_RAM_BUSY__SHIFT 0xb
+#define CP_CPC_STATUS__QU_BUSY_MASK 0x1000
+#define CP_CPC_STATUS__QU_BUSY__SHIFT 0xc
+#define CP_CPC_STATUS__ATCL2IU_BUSY_MASK 0x2000
+#define CP_CPC_STATUS__ATCL2IU_BUSY__SHIFT 0xd
+#define CP_CPC_STATUS__CPG_CPC_BUSY_MASK 0x20000000
+#define CP_CPC_STATUS__CPG_CPC_BUSY__SHIFT 0x1d
+#define CP_CPC_STATUS__CPF_CPC_BUSY_MASK 0x40000000
+#define CP_CPC_STATUS__CPF_CPC_BUSY__SHIFT 0x1e
+#define CP_CPC_STATUS__CPC_BUSY_MASK 0x80000000
+#define CP_CPC_STATUS__CPC_BUSY__SHIFT 0x1f
+#define CP_CPC_BUSY_STAT__MEC1_LOAD_BUSY_MASK 0x1
+#define CP_CPC_BUSY_STAT__MEC1_LOAD_BUSY__SHIFT 0x0
+#define CP_CPC_BUSY_STAT__MEC1_SEMAPOHRE_BUSY_MASK 0x2
+#define CP_CPC_BUSY_STAT__MEC1_SEMAPOHRE_BUSY__SHIFT 0x1
+#define CP_CPC_BUSY_STAT__MEC1_MUTEX_BUSY_MASK 0x4
+#define CP_CPC_BUSY_STAT__MEC1_MUTEX_BUSY__SHIFT 0x2
+#define CP_CPC_BUSY_STAT__MEC1_MESSAGE_BUSY_MASK 0x8
+#define CP_CPC_BUSY_STAT__MEC1_MESSAGE_BUSY__SHIFT 0x3
+#define CP_CPC_BUSY_STAT__MEC1_EOP_QUEUE_BUSY_MASK 0x10
+#define CP_CPC_BUSY_STAT__MEC1_EOP_QUEUE_BUSY__SHIFT 0x4
+#define CP_CPC_BUSY_STAT__MEC1_IQ_QUEUE_BUSY_MASK 0x20
+#define CP_CPC_BUSY_STAT__MEC1_IQ_QUEUE_BUSY__SHIFT 0x5
+#define CP_CPC_BUSY_STAT__MEC1_IB_QUEUE_BUSY_MASK 0x40
+#define CP_CPC_BUSY_STAT__MEC1_IB_QUEUE_BUSY__SHIFT 0x6
+#define CP_CPC_BUSY_STAT__MEC1_TC_BUSY_MASK 0x80
+#define CP_CPC_BUSY_STAT__MEC1_TC_BUSY__SHIFT 0x7
+#define CP_CPC_BUSY_STAT__MEC1_DMA_BUSY_MASK 0x100
+#define CP_CPC_BUSY_STAT__MEC1_DMA_BUSY__SHIFT 0x8
+#define CP_CPC_BUSY_STAT__MEC1_PARTIAL_FLUSH_BUSY_MASK 0x200
+#define CP_CPC_BUSY_STAT__MEC1_PARTIAL_FLUSH_BUSY__SHIFT 0x9
+#define CP_CPC_BUSY_STAT__MEC1_PIPE0_BUSY_MASK 0x400
+#define CP_CPC_BUSY_STAT__MEC1_PIPE0_BUSY__SHIFT 0xa
+#define CP_CPC_BUSY_STAT__MEC1_PIPE1_BUSY_MASK 0x800
+#define CP_CPC_BUSY_STAT__MEC1_PIPE1_BUSY__SHIFT 0xb
+#define CP_CPC_BUSY_STAT__MEC1_PIPE2_BUSY_MASK 0x1000
+#define CP_CPC_BUSY_STAT__MEC1_PIPE2_BUSY__SHIFT 0xc
+#define CP_CPC_BUSY_STAT__MEC1_PIPE3_BUSY_MASK 0x2000
+#define CP_CPC_BUSY_STAT__MEC1_PIPE3_BUSY__SHIFT 0xd
+#define CP_CPC_BUSY_STAT__MEC2_LOAD_BUSY_MASK 0x10000
+#define CP_CPC_BUSY_STAT__MEC2_LOAD_BUSY__SHIFT 0x10
+#define CP_CPC_BUSY_STAT__MEC2_SEMAPOHRE_BUSY_MASK 0x20000
+#define CP_CPC_BUSY_STAT__MEC2_SEMAPOHRE_BUSY__SHIFT 0x11
+#define CP_CPC_BUSY_STAT__MEC2_MUTEX_BUSY_MASK 0x40000
+#define CP_CPC_BUSY_STAT__MEC2_MUTEX_BUSY__SHIFT 0x12
+#define CP_CPC_BUSY_STAT__MEC2_MESSAGE_BUSY_MASK 0x80000
+#define CP_CPC_BUSY_STAT__MEC2_MESSAGE_BUSY__SHIFT 0x13
+#define CP_CPC_BUSY_STAT__MEC2_EOP_QUEUE_BUSY_MASK 0x100000
+#define CP_CPC_BUSY_STAT__MEC2_EOP_QUEUE_BUSY__SHIFT 0x14
+#define CP_CPC_BUSY_STAT__MEC2_IQ_QUEUE_BUSY_MASK 0x200000
+#define CP_CPC_BUSY_STAT__MEC2_IQ_QUEUE_BUSY__SHIFT 0x15
+#define CP_CPC_BUSY_STAT__MEC2_IB_QUEUE_BUSY_MASK 0x400000
+#define CP_CPC_BUSY_STAT__MEC2_IB_QUEUE_BUSY__SHIFT 0x16
+#define CP_CPC_BUSY_STAT__MEC2_TC_BUSY_MASK 0x800000
+#define CP_CPC_BUSY_STAT__MEC2_TC_BUSY__SHIFT 0x17
+#define CP_CPC_BUSY_STAT__MEC2_DMA_BUSY_MASK 0x1000000
+#define CP_CPC_BUSY_STAT__MEC2_DMA_BUSY__SHIFT 0x18
+#define CP_CPC_BUSY_STAT__MEC2_PARTIAL_FLUSH_BUSY_MASK 0x2000000
+#define CP_CPC_BUSY_STAT__MEC2_PARTIAL_FLUSH_BUSY__SHIFT 0x19
+#define CP_CPC_BUSY_STAT__MEC2_PIPE0_BUSY_MASK 0x4000000
+#define CP_CPC_BUSY_STAT__MEC2_PIPE0_BUSY__SHIFT 0x1a
+#define CP_CPC_BUSY_STAT__MEC2_PIPE1_BUSY_MASK 0x8000000
+#define CP_CPC_BUSY_STAT__MEC2_PIPE1_BUSY__SHIFT 0x1b
+#define CP_CPC_BUSY_STAT__MEC2_PIPE2_BUSY_MASK 0x10000000
+#define CP_CPC_BUSY_STAT__MEC2_PIPE2_BUSY__SHIFT 0x1c
+#define CP_CPC_BUSY_STAT__MEC2_PIPE3_BUSY_MASK 0x20000000
+#define CP_CPC_BUSY_STAT__MEC2_PIPE3_BUSY__SHIFT 0x1d
+#define CP_CPC_STALLED_STAT1__RCIU_TX_FREE_STALL_MASK 0x8
+#define CP_CPC_STALLED_STAT1__RCIU_TX_FREE_STALL__SHIFT 0x3
+#define CP_CPC_STALLED_STAT1__RCIU_PRIV_VIOLATION_MASK 0x10
+#define CP_CPC_STALLED_STAT1__RCIU_PRIV_VIOLATION__SHIFT 0x4
+#define CP_CPC_STALLED_STAT1__TCIU_TX_FREE_STALL_MASK 0x40
+#define CP_CPC_STALLED_STAT1__TCIU_TX_FREE_STALL__SHIFT 0x6
+#define CP_CPC_STALLED_STAT1__MEC1_DECODING_PACKET_MASK 0x100
+#define CP_CPC_STALLED_STAT1__MEC1_DECODING_PACKET__SHIFT 0x8
+#define CP_CPC_STALLED_STAT1__MEC1_WAIT_ON_RCIU_MASK 0x200
+#define CP_CPC_STALLED_STAT1__MEC1_WAIT_ON_RCIU__SHIFT 0x9
+#define CP_CPC_STALLED_STAT1__MEC1_WAIT_ON_RCIU_READ_MASK 0x400
+#define CP_CPC_STALLED_STAT1__MEC1_WAIT_ON_RCIU_READ__SHIFT 0xa
+#define CP_CPC_STALLED_STAT1__MEC1_WAIT_ON_ROQ_DATA_MASK 0x2000
+#define CP_CPC_STALLED_STAT1__MEC1_WAIT_ON_ROQ_DATA__SHIFT 0xd
+#define CP_CPC_STALLED_STAT1__MEC2_DECODING_PACKET_MASK 0x10000
+#define CP_CPC_STALLED_STAT1__MEC2_DECODING_PACKET__SHIFT 0x10
+#define CP_CPC_STALLED_STAT1__MEC2_WAIT_ON_RCIU_MASK 0x20000
+#define CP_CPC_STALLED_STAT1__MEC2_WAIT_ON_RCIU__SHIFT 0x11
+#define CP_CPC_STALLED_STAT1__MEC2_WAIT_ON_RCIU_READ_MASK 0x40000
+#define CP_CPC_STALLED_STAT1__MEC2_WAIT_ON_RCIU_READ__SHIFT 0x12
+#define CP_CPC_STALLED_STAT1__MEC2_WAIT_ON_ROQ_DATA_MASK 0x200000
+#define CP_CPC_STALLED_STAT1__MEC2_WAIT_ON_ROQ_DATA__SHIFT 0x15
+#define CP_CPC_STALLED_STAT1__ATCL2IU_WAITING_ON_FREE_MASK 0x400000
+#define CP_CPC_STALLED_STAT1__ATCL2IU_WAITING_ON_FREE__SHIFT 0x16
+#define CP_CPC_STALLED_STAT1__ATCL2IU_WAITING_ON_TAGS_MASK 0x800000
+#define CP_CPC_STALLED_STAT1__ATCL2IU_WAITING_ON_TAGS__SHIFT 0x17
+#define CP_CPC_STALLED_STAT1__ATCL1_WAITING_ON_TRANS_MASK 0x1000000
+#define CP_CPC_STALLED_STAT1__ATCL1_WAITING_ON_TRANS__SHIFT 0x18
+#define CP_CPF_STATUS__POST_WPTR_GFX_BUSY_MASK 0x1
+#define CP_CPF_STATUS__POST_WPTR_GFX_BUSY__SHIFT 0x0
+#define CP_CPF_STATUS__CSF_BUSY_MASK 0x2
+#define CP_CPF_STATUS__CSF_BUSY__SHIFT 0x1
+#define CP_CPF_STATUS__ROQ_ALIGN_BUSY_MASK 0x10
+#define CP_CPF_STATUS__ROQ_ALIGN_BUSY__SHIFT 0x4
+#define CP_CPF_STATUS__ROQ_RING_BUSY_MASK 0x20
+#define CP_CPF_STATUS__ROQ_RING_BUSY__SHIFT 0x5
+#define CP_CPF_STATUS__ROQ_INDIRECT1_BUSY_MASK 0x40
+#define CP_CPF_STATUS__ROQ_INDIRECT1_BUSY__SHIFT 0x6
+#define CP_CPF_STATUS__ROQ_INDIRECT2_BUSY_MASK 0x80
+#define CP_CPF_STATUS__ROQ_INDIRECT2_BUSY__SHIFT 0x7
+#define CP_CPF_STATUS__ROQ_STATE_BUSY_MASK 0x100
+#define CP_CPF_STATUS__ROQ_STATE_BUSY__SHIFT 0x8
+#define CP_CPF_STATUS__ROQ_CE_RING_BUSY_MASK 0x200
+#define CP_CPF_STATUS__ROQ_CE_RING_BUSY__SHIFT 0x9
+#define CP_CPF_STATUS__ROQ_CE_INDIRECT1_BUSY_MASK 0x400
+#define CP_CPF_STATUS__ROQ_CE_INDIRECT1_BUSY__SHIFT 0xa
+#define CP_CPF_STATUS__ROQ_CE_INDIRECT2_BUSY_MASK 0x800
+#define CP_CPF_STATUS__ROQ_CE_INDIRECT2_BUSY__SHIFT 0xb
+#define CP_CPF_STATUS__SEMAPHORE_BUSY_MASK 0x1000
+#define CP_CPF_STATUS__SEMAPHORE_BUSY__SHIFT 0xc
+#define CP_CPF_STATUS__INTERRUPT_BUSY_MASK 0x2000
+#define CP_CPF_STATUS__INTERRUPT_BUSY__SHIFT 0xd
+#define CP_CPF_STATUS__TCIU_BUSY_MASK 0x4000
+#define CP_CPF_STATUS__TCIU_BUSY__SHIFT 0xe
+#define CP_CPF_STATUS__HQD_BUSY_MASK 0x8000
+#define CP_CPF_STATUS__HQD_BUSY__SHIFT 0xf
+#define CP_CPF_STATUS__PRT_BUSY_MASK 0x10000
+#define CP_CPF_STATUS__PRT_BUSY__SHIFT 0x10
+#define CP_CPF_STATUS__ATCL2IU_BUSY_MASK 0x20000
+#define CP_CPF_STATUS__ATCL2IU_BUSY__SHIFT 0x11
+#define CP_CPF_STATUS__CPF_GFX_BUSY_MASK 0x4000000
+#define CP_CPF_STATUS__CPF_GFX_BUSY__SHIFT 0x1a
+#define CP_CPF_STATUS__CPF_CMP_BUSY_MASK 0x8000000
+#define CP_CPF_STATUS__CPF_CMP_BUSY__SHIFT 0x1b
+#define CP_CPF_STATUS__GRBM_CPF_STAT_BUSY_MASK 0x30000000
+#define CP_CPF_STATUS__GRBM_CPF_STAT_BUSY__SHIFT 0x1c
+#define CP_CPF_STATUS__CPC_CPF_BUSY_MASK 0x40000000
+#define CP_CPF_STATUS__CPC_CPF_BUSY__SHIFT 0x1e
+#define CP_CPF_STATUS__CPF_BUSY_MASK 0x80000000
+#define CP_CPF_STATUS__CPF_BUSY__SHIFT 0x1f
+#define CP_CPF_BUSY_STAT__REG_BUS_FIFO_BUSY_MASK 0x1
+#define CP_CPF_BUSY_STAT__REG_BUS_FIFO_BUSY__SHIFT 0x0
+#define CP_CPF_BUSY_STAT__CSF_RING_BUSY_MASK 0x2
+#define CP_CPF_BUSY_STAT__CSF_RING_BUSY__SHIFT 0x1
+#define CP_CPF_BUSY_STAT__CSF_INDIRECT1_BUSY_MASK 0x4
+#define CP_CPF_BUSY_STAT__CSF_INDIRECT1_BUSY__SHIFT 0x2
+#define CP_CPF_BUSY_STAT__CSF_INDIRECT2_BUSY_MASK 0x8
+#define CP_CPF_BUSY_STAT__CSF_INDIRECT2_BUSY__SHIFT 0x3
+#define CP_CPF_BUSY_STAT__CSF_STATE_BUSY_MASK 0x10
+#define CP_CPF_BUSY_STAT__CSF_STATE_BUSY__SHIFT 0x4
+#define CP_CPF_BUSY_STAT__CSF_CE_INDR1_BUSY_MASK 0x20
+#define CP_CPF_BUSY_STAT__CSF_CE_INDR1_BUSY__SHIFT 0x5
+#define CP_CPF_BUSY_STAT__CSF_CE_INDR2_BUSY_MASK 0x40
+#define CP_CPF_BUSY_STAT__CSF_CE_INDR2_BUSY__SHIFT 0x6
+#define CP_CPF_BUSY_STAT__CSF_ARBITER_BUSY_MASK 0x80
+#define CP_CPF_BUSY_STAT__CSF_ARBITER_BUSY__SHIFT 0x7
+#define CP_CPF_BUSY_STAT__CSF_INPUT_BUSY_MASK 0x100
+#define CP_CPF_BUSY_STAT__CSF_INPUT_BUSY__SHIFT 0x8
+#define CP_CPF_BUSY_STAT__OUTSTANDING_READ_TAGS_MASK 0x200
+#define CP_CPF_BUSY_STAT__OUTSTANDING_READ_TAGS__SHIFT 0x9
+#define CP_CPF_BUSY_STAT__HPD_PROCESSING_EOP_BUSY_MASK 0x800
+#define CP_CPF_BUSY_STAT__HPD_PROCESSING_EOP_BUSY__SHIFT 0xb
+#define CP_CPF_BUSY_STAT__HQD_DISPATCH_BUSY_MASK 0x1000
+#define CP_CPF_BUSY_STAT__HQD_DISPATCH_BUSY__SHIFT 0xc
+#define CP_CPF_BUSY_STAT__HQD_IQ_TIMER_BUSY_MASK 0x2000
+#define CP_CPF_BUSY_STAT__HQD_IQ_TIMER_BUSY__SHIFT 0xd
+#define CP_CPF_BUSY_STAT__HQD_DMA_OFFLOAD_BUSY_MASK 0x4000
+#define CP_CPF_BUSY_STAT__HQD_DMA_OFFLOAD_BUSY__SHIFT 0xe
+#define CP_CPF_BUSY_STAT__HQD_WAIT_SEMAPHORE_BUSY_MASK 0x8000
+#define CP_CPF_BUSY_STAT__HQD_WAIT_SEMAPHORE_BUSY__SHIFT 0xf
+#define CP_CPF_BUSY_STAT__HQD_SIGNAL_SEMAPHORE_BUSY_MASK 0x10000
+#define CP_CPF_BUSY_STAT__HQD_SIGNAL_SEMAPHORE_BUSY__SHIFT 0x10
+#define CP_CPF_BUSY_STAT__HQD_MESSAGE_BUSY_MASK 0x20000
+#define CP_CPF_BUSY_STAT__HQD_MESSAGE_BUSY__SHIFT 0x11
+#define CP_CPF_BUSY_STAT__HQD_PQ_FETCHER_BUSY_MASK 0x40000
+#define CP_CPF_BUSY_STAT__HQD_PQ_FETCHER_BUSY__SHIFT 0x12
+#define CP_CPF_BUSY_STAT__HQD_IB_FETCHER_BUSY_MASK 0x80000
+#define CP_CPF_BUSY_STAT__HQD_IB_FETCHER_BUSY__SHIFT 0x13
+#define CP_CPF_BUSY_STAT__HQD_IQ_FETCHER_BUSY_MASK 0x100000
+#define CP_CPF_BUSY_STAT__HQD_IQ_FETCHER_BUSY__SHIFT 0x14
+#define CP_CPF_BUSY_STAT__HQD_EOP_FETCHER_BUSY_MASK 0x200000
+#define CP_CPF_BUSY_STAT__HQD_EOP_FETCHER_BUSY__SHIFT 0x15
+#define CP_CPF_BUSY_STAT__HQD_CONSUMED_RPTR_BUSY_MASK 0x400000
+#define CP_CPF_BUSY_STAT__HQD_CONSUMED_RPTR_BUSY__SHIFT 0x16
+#define CP_CPF_BUSY_STAT__HQD_FETCHER_ARB_BUSY_MASK 0x800000
+#define CP_CPF_BUSY_STAT__HQD_FETCHER_ARB_BUSY__SHIFT 0x17
+#define CP_CPF_BUSY_STAT__HQD_ROQ_ALIGN_BUSY_MASK 0x1000000
+#define CP_CPF_BUSY_STAT__HQD_ROQ_ALIGN_BUSY__SHIFT 0x18
+#define CP_CPF_BUSY_STAT__HQD_ROQ_EOP_BUSY_MASK 0x2000000
+#define CP_CPF_BUSY_STAT__HQD_ROQ_EOP_BUSY__SHIFT 0x19
+#define CP_CPF_BUSY_STAT__HQD_ROQ_IQ_BUSY_MASK 0x4000000
+#define CP_CPF_BUSY_STAT__HQD_ROQ_IQ_BUSY__SHIFT 0x1a
+#define CP_CPF_BUSY_STAT__HQD_ROQ_PQ_BUSY_MASK 0x8000000
+#define CP_CPF_BUSY_STAT__HQD_ROQ_PQ_BUSY__SHIFT 0x1b
+#define CP_CPF_BUSY_STAT__HQD_ROQ_IB_BUSY_MASK 0x10000000
+#define CP_CPF_BUSY_STAT__HQD_ROQ_IB_BUSY__SHIFT 0x1c
+#define CP_CPF_BUSY_STAT__HQD_WPTR_POLL_BUSY_MASK 0x20000000
+#define CP_CPF_BUSY_STAT__HQD_WPTR_POLL_BUSY__SHIFT 0x1d
+#define CP_CPF_BUSY_STAT__HQD_PQ_BUSY_MASK 0x40000000
+#define CP_CPF_BUSY_STAT__HQD_PQ_BUSY__SHIFT 0x1e
+#define CP_CPF_BUSY_STAT__HQD_IB_BUSY_MASK 0x80000000
+#define CP_CPF_BUSY_STAT__HQD_IB_BUSY__SHIFT 0x1f
+#define CP_CPF_STALLED_STAT1__RING_FETCHING_DATA_MASK 0x1
+#define CP_CPF_STALLED_STAT1__RING_FETCHING_DATA__SHIFT 0x0
+#define CP_CPF_STALLED_STAT1__INDR1_FETCHING_DATA_MASK 0x2
+#define CP_CPF_STALLED_STAT1__INDR1_FETCHING_DATA__SHIFT 0x1
+#define CP_CPF_STALLED_STAT1__INDR2_FETCHING_DATA_MASK 0x4
+#define CP_CPF_STALLED_STAT1__INDR2_FETCHING_DATA__SHIFT 0x2
+#define CP_CPF_STALLED_STAT1__STATE_FETCHING_DATA_MASK 0x8
+#define CP_CPF_STALLED_STAT1__STATE_FETCHING_DATA__SHIFT 0x3
+#define CP_CPF_STALLED_STAT1__TCIU_WAITING_ON_FREE_MASK 0x20
+#define CP_CPF_STALLED_STAT1__TCIU_WAITING_ON_FREE__SHIFT 0x5
+#define CP_CPF_STALLED_STAT1__TCIU_WAITING_ON_TAGS_MASK 0x40
+#define CP_CPF_STALLED_STAT1__TCIU_WAITING_ON_TAGS__SHIFT 0x6
+#define CP_CPF_STALLED_STAT1__ATCL2IU_WAITING_ON_FREE_MASK 0x80
+#define CP_CPF_STALLED_STAT1__ATCL2IU_WAITING_ON_FREE__SHIFT 0x7
+#define CP_CPF_STALLED_STAT1__ATCL2IU_WAITING_ON_TAGS_MASK 0x100
+#define CP_CPF_STALLED_STAT1__ATCL2IU_WAITING_ON_TAGS__SHIFT 0x8
+#define CP_CPF_STALLED_STAT1__ATCL1_WAITING_ON_TRANS_MASK 0x200
+#define CP_CPF_STALLED_STAT1__ATCL1_WAITING_ON_TRANS__SHIFT 0x9
+#define CP_CPC_GRBM_FREE_COUNT__FREE_COUNT_MASK 0x3f
+#define CP_CPC_GRBM_FREE_COUNT__FREE_COUNT__SHIFT 0x0
+#define CP_MEC_CNTL__MEC_INVALIDATE_ICACHE_MASK 0x10
+#define CP_MEC_CNTL__MEC_INVALIDATE_ICACHE__SHIFT 0x4
+#define CP_MEC_CNTL__MEC_ME1_PIPE0_RESET_MASK 0x10000
+#define CP_MEC_CNTL__MEC_ME1_PIPE0_RESET__SHIFT 0x10
+#define CP_MEC_CNTL__MEC_ME1_PIPE1_RESET_MASK 0x20000
+#define CP_MEC_CNTL__MEC_ME1_PIPE1_RESET__SHIFT 0x11
+#define CP_MEC_CNTL__MEC_ME1_PIPE2_RESET_MASK 0x40000
+#define CP_MEC_CNTL__MEC_ME1_PIPE2_RESET__SHIFT 0x12
+#define CP_MEC_CNTL__MEC_ME1_PIPE3_RESET_MASK 0x80000
+#define CP_MEC_CNTL__MEC_ME1_PIPE3_RESET__SHIFT 0x13
+#define CP_MEC_CNTL__MEC_ME2_PIPE0_RESET_MASK 0x100000
+#define CP_MEC_CNTL__MEC_ME2_PIPE0_RESET__SHIFT 0x14
+#define CP_MEC_CNTL__MEC_ME2_PIPE1_RESET_MASK 0x200000
+#define CP_MEC_CNTL__MEC_ME2_PIPE1_RESET__SHIFT 0x15
+#define CP_MEC_CNTL__MEC_ME2_HALT_MASK 0x10000000
+#define CP_MEC_CNTL__MEC_ME2_HALT__SHIFT 0x1c
+#define CP_MEC_CNTL__MEC_ME2_STEP_MASK 0x20000000
+#define CP_MEC_CNTL__MEC_ME2_STEP__SHIFT 0x1d
+#define CP_MEC_CNTL__MEC_ME1_HALT_MASK 0x40000000
+#define CP_MEC_CNTL__MEC_ME1_HALT__SHIFT 0x1e
+#define CP_MEC_CNTL__MEC_ME1_STEP_MASK 0x80000000
+#define CP_MEC_CNTL__MEC_ME1_STEP__SHIFT 0x1f
+#define CP_MEC_ME1_HEADER_DUMP__HEADER_DUMP_MASK 0xffffffff
+#define CP_MEC_ME1_HEADER_DUMP__HEADER_DUMP__SHIFT 0x0
+#define CP_MEC_ME2_HEADER_DUMP__HEADER_DUMP_MASK 0xffffffff
+#define CP_MEC_ME2_HEADER_DUMP__HEADER_DUMP__SHIFT 0x0
+#define CP_CPC_SCRATCH_INDEX__SCRATCH_INDEX_MASK 0x1ff
+#define CP_CPC_SCRATCH_INDEX__SCRATCH_INDEX__SHIFT 0x0
+#define CP_CPC_SCRATCH_DATA__SCRATCH_DATA_MASK 0xffffffff
+#define CP_CPC_SCRATCH_DATA__SCRATCH_DATA__SHIFT 0x0
+#define CPG_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3f
+#define CPG_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define CPG_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CPG_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CPG_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CPG_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CPG_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3f
+#define CPG_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define CPG_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xfc00
+#define CPG_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define CPG_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3f
+#define CPG_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define CPG_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xfc00
+#define CPG_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define CPG_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define CPG_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define CPG_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CPG_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CPG_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CPG_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CPC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3f
+#define CPC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define CPC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CPC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CPC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CPC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CPC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3f
+#define CPC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define CPC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xfc00
+#define CPC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define CPC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3f
+#define CPC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define CPC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xfc00
+#define CPC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define CPC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define CPC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define CPC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CPC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CPC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CPC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CPF_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3f
+#define CPF_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define CPF_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CPF_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CPF_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CPF_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CPF_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3f
+#define CPF_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define CPF_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xfc00
+#define CPF_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define CPF_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3f
+#define CPF_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define CPF_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xfc00
+#define CPF_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define CPF_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define CPF_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define CPF_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define CPF_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define CPF_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define CPF_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CP_CPC_HALT_HYST_COUNT__COUNT_MASK 0xf
+#define CP_CPC_HALT_HYST_COUNT__COUNT__SHIFT 0x0
+#define CP_DRAW_OBJECT__OBJECT_MASK 0xffffffff
+#define CP_DRAW_OBJECT__OBJECT__SHIFT 0x0
+#define CP_DRAW_OBJECT_COUNTER__COUNT_MASK 0xffff
+#define CP_DRAW_OBJECT_COUNTER__COUNT__SHIFT 0x0
+#define CP_DRAW_WINDOW_MASK_HI__WINDOW_MASK_HI_MASK 0xffffffff
+#define CP_DRAW_WINDOW_MASK_HI__WINDOW_MASK_HI__SHIFT 0x0
+#define CP_DRAW_WINDOW_HI__WINDOW_HI_MASK 0xffffffff
+#define CP_DRAW_WINDOW_HI__WINDOW_HI__SHIFT 0x0
+#define CP_DRAW_WINDOW_LO__MIN_MASK 0xffff
+#define CP_DRAW_WINDOW_LO__MIN__SHIFT 0x0
+#define CP_DRAW_WINDOW_LO__MAX_MASK 0xffff0000
+#define CP_DRAW_WINDOW_LO__MAX__SHIFT 0x10
+#define CP_DRAW_WINDOW_CNTL__DISABLE_DRAW_WINDOW_LO_MAX_MASK 0x1
+#define CP_DRAW_WINDOW_CNTL__DISABLE_DRAW_WINDOW_LO_MAX__SHIFT 0x0
+#define CP_DRAW_WINDOW_CNTL__DISABLE_DRAW_WINDOW_LO_MIN_MASK 0x2
+#define CP_DRAW_WINDOW_CNTL__DISABLE_DRAW_WINDOW_LO_MIN__SHIFT 0x1
+#define CP_DRAW_WINDOW_CNTL__DISABLE_DRAW_WINDOW_HI_MASK 0x4
+#define CP_DRAW_WINDOW_CNTL__DISABLE_DRAW_WINDOW_HI__SHIFT 0x2
+#define CP_DRAW_WINDOW_CNTL__MODE_MASK 0x100
+#define CP_DRAW_WINDOW_CNTL__MODE__SHIFT 0x8
+#define CP_PRT_LOD_STATS_CNTL0__BU_SIZE_MASK 0xffffffff
+#define CP_PRT_LOD_STATS_CNTL0__BU_SIZE__SHIFT 0x0
+#define CP_PRT_LOD_STATS_CNTL1__BASE_LO_MASK 0xffffffff
+#define CP_PRT_LOD_STATS_CNTL1__BASE_LO__SHIFT 0x0
+#define CP_PRT_LOD_STATS_CNTL2__BASE_HI_MASK 0x3
+#define CP_PRT_LOD_STATS_CNTL2__BASE_HI__SHIFT 0x0
+#define CP_PRT_LOD_STATS_CNTL2__INTERVAL_MASK 0x3fc
+#define CP_PRT_LOD_STATS_CNTL2__INTERVAL__SHIFT 0x2
+#define CP_PRT_LOD_STATS_CNTL2__RESET_CNT_MASK 0x3fc00
+#define CP_PRT_LOD_STATS_CNTL2__RESET_CNT__SHIFT 0xa
+#define CP_PRT_LOD_STATS_CNTL2__RESET_FORCE_MASK 0x40000
+#define CP_PRT_LOD_STATS_CNTL2__RESET_FORCE__SHIFT 0x12
+#define CP_PRT_LOD_STATS_CNTL2__REPORT_AND_RESET_MASK 0x80000
+#define CP_PRT_LOD_STATS_CNTL2__REPORT_AND_RESET__SHIFT 0x13
+#define CP_PRT_LOD_STATS_CNTL2__MC_VMID_MASK 0x7800000
+#define CP_PRT_LOD_STATS_CNTL2__MC_VMID__SHIFT 0x17
+#define CP_PRT_LOD_STATS_CNTL2__CACHE_POLICY_MASK 0x10000000
+#define CP_PRT_LOD_STATS_CNTL2__CACHE_POLICY__SHIFT 0x1c
+#define CP_PRT_LOD_STATS_CNTL2__MTYPE_MASK 0xc0000000
+#define CP_PRT_LOD_STATS_CNTL2__MTYPE__SHIFT 0x1e
+#define CP_CE_COMPARE_COUNT__COMPARE_COUNT_MASK 0xffffffff
+#define CP_CE_COMPARE_COUNT__COMPARE_COUNT__SHIFT 0x0
+#define CP_CE_DE_COUNT__DRAW_ENGINE_COUNT_MASK 0xffffffff
+#define CP_CE_DE_COUNT__DRAW_ENGINE_COUNT__SHIFT 0x0
+#define CP_DE_CE_COUNT__CONST_ENGINE_COUNT_MASK 0xffffffff
+#define CP_DE_CE_COUNT__CONST_ENGINE_COUNT__SHIFT 0x0
+#define CP_DE_LAST_INVAL_COUNT__LAST_INVAL_COUNT_MASK 0xffffffff
+#define CP_DE_LAST_INVAL_COUNT__LAST_INVAL_COUNT__SHIFT 0x0
+#define CP_DE_DE_COUNT__DRAW_ENGINE_COUNT_MASK 0xffffffff
+#define CP_DE_DE_COUNT__DRAW_ENGINE_COUNT__SHIFT 0x0
+#define CP_EOP_DONE_EVENT_CNTL__WBINV_TC_OP_MASK 0x7f
+#define CP_EOP_DONE_EVENT_CNTL__WBINV_TC_OP__SHIFT 0x0
+#define CP_EOP_DONE_EVENT_CNTL__WBINV_ACTION_ENA_MASK 0x3f000
+#define CP_EOP_DONE_EVENT_CNTL__WBINV_ACTION_ENA__SHIFT 0xc
+#define CP_EOP_DONE_EVENT_CNTL__CACHE_CONTROL_MASK 0x2000000
+#define CP_EOP_DONE_EVENT_CNTL__CACHE_CONTROL__SHIFT 0x19
+#define CP_EOP_DONE_EVENT_CNTL__MTYPE_MASK 0x18000000
+#define CP_EOP_DONE_EVENT_CNTL__MTYPE__SHIFT 0x1b
+#define CP_EOP_DONE_DATA_CNTL__CNTX_ID_MASK 0xffff
+#define CP_EOP_DONE_DATA_CNTL__CNTX_ID__SHIFT 0x0
+#define CP_EOP_DONE_DATA_CNTL__DST_SEL_MASK 0x30000
+#define CP_EOP_DONE_DATA_CNTL__DST_SEL__SHIFT 0x10
+#define CP_EOP_DONE_DATA_CNTL__INT_SEL_MASK 0x7000000
+#define CP_EOP_DONE_DATA_CNTL__INT_SEL__SHIFT 0x18
+#define CP_EOP_DONE_DATA_CNTL__DATA_SEL_MASK 0xe0000000
+#define CP_EOP_DONE_DATA_CNTL__DATA_SEL__SHIFT 0x1d
+#define CP_EOP_DONE_CNTX_ID__CNTX_ID_MASK 0xfffffff
+#define CP_EOP_DONE_CNTX_ID__CNTX_ID__SHIFT 0x0
+#define CP_EOP_DONE_ADDR_LO__ADDR_LO_MASK 0xfffffffc
+#define CP_EOP_DONE_ADDR_LO__ADDR_LO__SHIFT 0x2
+#define CP_EOP_DONE_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_EOP_DONE_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_EOP_DONE_DATA_LO__DATA_LO_MASK 0xffffffff
+#define CP_EOP_DONE_DATA_LO__DATA_LO__SHIFT 0x0
+#define CP_EOP_DONE_DATA_HI__DATA_HI_MASK 0xffffffff
+#define CP_EOP_DONE_DATA_HI__DATA_HI__SHIFT 0x0
+#define CP_EOP_LAST_FENCE_LO__LAST_FENCE_LO_MASK 0xffffffff
+#define CP_EOP_LAST_FENCE_LO__LAST_FENCE_LO__SHIFT 0x0
+#define CP_EOP_LAST_FENCE_HI__LAST_FENCE_HI_MASK 0xffffffff
+#define CP_EOP_LAST_FENCE_HI__LAST_FENCE_HI__SHIFT 0x0
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_LO_MASK 0xfffffffc
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_LO__SHIFT 0x2
+#define CP_STREAM_OUT_ADDR_HI__STREAM_OUT_ADDR_HI_MASK 0xffff
+#define CP_STREAM_OUT_ADDR_HI__STREAM_OUT_ADDR_HI__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT0_LO__NUM_PRIM_WRITTEN_CNT0_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT0_LO__NUM_PRIM_WRITTEN_CNT0_LO__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT0_HI__NUM_PRIM_WRITTEN_CNT0_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT0_HI__NUM_PRIM_WRITTEN_CNT0_HI__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT0_LO__NUM_PRIM_NEEDED_CNT0_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT0_LO__NUM_PRIM_NEEDED_CNT0_LO__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT0_HI__NUM_PRIM_NEEDED_CNT0_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT0_HI__NUM_PRIM_NEEDED_CNT0_HI__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT1_LO__NUM_PRIM_WRITTEN_CNT1_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT1_LO__NUM_PRIM_WRITTEN_CNT1_LO__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT1_HI__NUM_PRIM_WRITTEN_CNT1_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT1_HI__NUM_PRIM_WRITTEN_CNT1_HI__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT1_LO__NUM_PRIM_NEEDED_CNT1_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT1_LO__NUM_PRIM_NEEDED_CNT1_LO__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT1_HI__NUM_PRIM_NEEDED_CNT1_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT1_HI__NUM_PRIM_NEEDED_CNT1_HI__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT2_LO__NUM_PRIM_WRITTEN_CNT2_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT2_LO__NUM_PRIM_WRITTEN_CNT2_LO__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT2_HI__NUM_PRIM_WRITTEN_CNT2_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT2_HI__NUM_PRIM_WRITTEN_CNT2_HI__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT2_LO__NUM_PRIM_NEEDED_CNT2_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT2_LO__NUM_PRIM_NEEDED_CNT2_LO__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT2_HI__NUM_PRIM_NEEDED_CNT2_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT2_HI__NUM_PRIM_NEEDED_CNT2_HI__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT3_LO__NUM_PRIM_WRITTEN_CNT3_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT3_LO__NUM_PRIM_WRITTEN_CNT3_LO__SHIFT 0x0
+#define CP_NUM_PRIM_WRITTEN_COUNT3_HI__NUM_PRIM_WRITTEN_CNT3_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_WRITTEN_COUNT3_HI__NUM_PRIM_WRITTEN_CNT3_HI__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT3_LO__NUM_PRIM_NEEDED_CNT3_LO_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT3_LO__NUM_PRIM_NEEDED_CNT3_LO__SHIFT 0x0
+#define CP_NUM_PRIM_NEEDED_COUNT3_HI__NUM_PRIM_NEEDED_CNT3_HI_MASK 0xffffffff
+#define CP_NUM_PRIM_NEEDED_COUNT3_HI__NUM_PRIM_NEEDED_CNT3_HI__SHIFT 0x0
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_LO_MASK 0xfffffffc
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_LO__SHIFT 0x2
+#define CP_PIPE_STATS_ADDR_HI__PIPE_STATS_ADDR_HI_MASK 0xffff
+#define CP_PIPE_STATS_ADDR_HI__PIPE_STATS_ADDR_HI__SHIFT 0x0
+#define CP_VGT_IAVERT_COUNT_LO__IAVERT_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_IAVERT_COUNT_LO__IAVERT_COUNT_LO__SHIFT 0x0
+#define CP_VGT_IAVERT_COUNT_HI__IAVERT_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_IAVERT_COUNT_HI__IAVERT_COUNT_HI__SHIFT 0x0
+#define CP_VGT_IAPRIM_COUNT_LO__IAPRIM_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_IAPRIM_COUNT_LO__IAPRIM_COUNT_LO__SHIFT 0x0
+#define CP_VGT_IAPRIM_COUNT_HI__IAPRIM_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_IAPRIM_COUNT_HI__IAPRIM_COUNT_HI__SHIFT 0x0
+#define CP_VGT_GSPRIM_COUNT_LO__GSPRIM_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_GSPRIM_COUNT_LO__GSPRIM_COUNT_LO__SHIFT 0x0
+#define CP_VGT_GSPRIM_COUNT_HI__GSPRIM_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_GSPRIM_COUNT_HI__GSPRIM_COUNT_HI__SHIFT 0x0
+#define CP_VGT_VSINVOC_COUNT_LO__VSINVOC_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_VSINVOC_COUNT_LO__VSINVOC_COUNT_LO__SHIFT 0x0
+#define CP_VGT_VSINVOC_COUNT_HI__VSINVOC_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_VSINVOC_COUNT_HI__VSINVOC_COUNT_HI__SHIFT 0x0
+#define CP_VGT_GSINVOC_COUNT_LO__GSINVOC_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_GSINVOC_COUNT_LO__GSINVOC_COUNT_LO__SHIFT 0x0
+#define CP_VGT_GSINVOC_COUNT_HI__GSINVOC_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_GSINVOC_COUNT_HI__GSINVOC_COUNT_HI__SHIFT 0x0
+#define CP_VGT_HSINVOC_COUNT_LO__HSINVOC_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_HSINVOC_COUNT_LO__HSINVOC_COUNT_LO__SHIFT 0x0
+#define CP_VGT_HSINVOC_COUNT_HI__HSINVOC_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_HSINVOC_COUNT_HI__HSINVOC_COUNT_HI__SHIFT 0x0
+#define CP_VGT_DSINVOC_COUNT_LO__DSINVOC_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_DSINVOC_COUNT_LO__DSINVOC_COUNT_LO__SHIFT 0x0
+#define CP_VGT_DSINVOC_COUNT_HI__DSINVOC_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_DSINVOC_COUNT_HI__DSINVOC_COUNT_HI__SHIFT 0x0
+#define CP_PA_CINVOC_COUNT_LO__CINVOC_COUNT_LO_MASK 0xffffffff
+#define CP_PA_CINVOC_COUNT_LO__CINVOC_COUNT_LO__SHIFT 0x0
+#define CP_PA_CINVOC_COUNT_HI__CINVOC_COUNT_HI_MASK 0xffffffff
+#define CP_PA_CINVOC_COUNT_HI__CINVOC_COUNT_HI__SHIFT 0x0
+#define CP_PA_CPRIM_COUNT_LO__CPRIM_COUNT_LO_MASK 0xffffffff
+#define CP_PA_CPRIM_COUNT_LO__CPRIM_COUNT_LO__SHIFT 0x0
+#define CP_PA_CPRIM_COUNT_HI__CPRIM_COUNT_HI_MASK 0xffffffff
+#define CP_PA_CPRIM_COUNT_HI__CPRIM_COUNT_HI__SHIFT 0x0
+#define CP_SC_PSINVOC_COUNT0_LO__PSINVOC_COUNT0_LO_MASK 0xffffffff
+#define CP_SC_PSINVOC_COUNT0_LO__PSINVOC_COUNT0_LO__SHIFT 0x0
+#define CP_SC_PSINVOC_COUNT0_HI__PSINVOC_COUNT0_HI_MASK 0xffffffff
+#define CP_SC_PSINVOC_COUNT0_HI__PSINVOC_COUNT0_HI__SHIFT 0x0
+#define CP_SC_PSINVOC_COUNT1_LO__OBSOLETE_MASK 0xffffffff
+#define CP_SC_PSINVOC_COUNT1_LO__OBSOLETE__SHIFT 0x0
+#define CP_SC_PSINVOC_COUNT1_HI__OBSOLETE_MASK 0xffffffff
+#define CP_SC_PSINVOC_COUNT1_HI__OBSOLETE__SHIFT 0x0
+#define CP_VGT_CSINVOC_COUNT_LO__CSINVOC_COUNT_LO_MASK 0xffffffff
+#define CP_VGT_CSINVOC_COUNT_LO__CSINVOC_COUNT_LO__SHIFT 0x0
+#define CP_VGT_CSINVOC_COUNT_HI__CSINVOC_COUNT_HI_MASK 0xffffffff
+#define CP_VGT_CSINVOC_COUNT_HI__CSINVOC_COUNT_HI__SHIFT 0x0
+#define CP_PIPE_STATS_CONTROL__CACHE_CONTROL_MASK 0x2000000
+#define CP_PIPE_STATS_CONTROL__CACHE_CONTROL__SHIFT 0x19
+#define CP_PIPE_STATS_CONTROL__MTYPE_MASK 0x18000000
+#define CP_PIPE_STATS_CONTROL__MTYPE__SHIFT 0x1b
+#define CP_STREAM_OUT_CONTROL__CACHE_CONTROL_MASK 0x2000000
+#define CP_STREAM_OUT_CONTROL__CACHE_CONTROL__SHIFT 0x19
+#define CP_STREAM_OUT_CONTROL__MTYPE_MASK 0x18000000
+#define CP_STREAM_OUT_CONTROL__MTYPE__SHIFT 0x1b
+#define CP_STRMOUT_CNTL__OFFSET_UPDATE_DONE_MASK 0x1
+#define CP_STRMOUT_CNTL__OFFSET_UPDATE_DONE__SHIFT 0x0
+#define SCRATCH_REG0__SCRATCH_REG0_MASK 0xffffffff
+#define SCRATCH_REG0__SCRATCH_REG0__SHIFT 0x0
+#define SCRATCH_REG1__SCRATCH_REG1_MASK 0xffffffff
+#define SCRATCH_REG1__SCRATCH_REG1__SHIFT 0x0
+#define SCRATCH_REG2__SCRATCH_REG2_MASK 0xffffffff
+#define SCRATCH_REG2__SCRATCH_REG2__SHIFT 0x0
+#define SCRATCH_REG3__SCRATCH_REG3_MASK 0xffffffff
+#define SCRATCH_REG3__SCRATCH_REG3__SHIFT 0x0
+#define SCRATCH_REG4__SCRATCH_REG4_MASK 0xffffffff
+#define SCRATCH_REG4__SCRATCH_REG4__SHIFT 0x0
+#define SCRATCH_REG5__SCRATCH_REG5_MASK 0xffffffff
+#define SCRATCH_REG5__SCRATCH_REG5__SHIFT 0x0
+#define SCRATCH_REG6__SCRATCH_REG6_MASK 0xffffffff
+#define SCRATCH_REG6__SCRATCH_REG6__SHIFT 0x0
+#define SCRATCH_REG7__SCRATCH_REG7_MASK 0xffffffff
+#define SCRATCH_REG7__SCRATCH_REG7__SHIFT 0x0
+#define SCRATCH_UMSK__OBSOLETE_UMSK_MASK 0xff
+#define SCRATCH_UMSK__OBSOLETE_UMSK__SHIFT 0x0
+#define SCRATCH_UMSK__OBSOLETE_SWAP_MASK 0x30000
+#define SCRATCH_UMSK__OBSOLETE_SWAP__SHIFT 0x10
+#define SCRATCH_ADDR__OBSOLETE_ADDR_MASK 0xffffffff
+#define SCRATCH_ADDR__OBSOLETE_ADDR__SHIFT 0x0
+#define CP_PFP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO_MASK 0xffffffff
+#define CP_PFP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO__SHIFT 0x0
+#define CP_PFP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI_MASK 0xffffffff
+#define CP_PFP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI__SHIFT 0x0
+#define CP_PFP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO_MASK 0xffffffff
+#define CP_PFP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO__SHIFT 0x0
+#define CP_PFP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI_MASK 0xffffffff
+#define CP_PFP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI__SHIFT 0x0
+#define CP_PFP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO_MASK 0xffffffff
+#define CP_PFP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO__SHIFT 0x0
+#define CP_PFP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI_MASK 0xffffffff
+#define CP_PFP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI__SHIFT 0x0
+#define CP_APPEND_ADDR_LO__MEM_ADDR_LO_MASK 0xfffffffc
+#define CP_APPEND_ADDR_LO__MEM_ADDR_LO__SHIFT 0x2
+#define CP_APPEND_ADDR_HI__MEM_ADDR_HI_MASK 0xffff
+#define CP_APPEND_ADDR_HI__MEM_ADDR_HI__SHIFT 0x0
+#define CP_APPEND_ADDR_HI__CS_PS_SEL_MASK 0x10000
+#define CP_APPEND_ADDR_HI__CS_PS_SEL__SHIFT 0x10
+#define CP_APPEND_ADDR_HI__CACHE_POLICY_MASK 0x2000000
+#define CP_APPEND_ADDR_HI__CACHE_POLICY__SHIFT 0x19
+#define CP_APPEND_ADDR_HI__MTYPE_MASK 0x18000000
+#define CP_APPEND_ADDR_HI__MTYPE__SHIFT 0x1b
+#define CP_APPEND_ADDR_HI__COMMAND_MASK 0xe0000000
+#define CP_APPEND_ADDR_HI__COMMAND__SHIFT 0x1d
+#define CP_APPEND_DATA__DATA_MASK 0xffffffff
+#define CP_APPEND_DATA__DATA__SHIFT 0x0
+#define CP_APPEND_LAST_CS_FENCE__LAST_FENCE_MASK 0xffffffff
+#define CP_APPEND_LAST_CS_FENCE__LAST_FENCE__SHIFT 0x0
+#define CP_APPEND_LAST_PS_FENCE__LAST_FENCE_MASK 0xffffffff
+#define CP_APPEND_LAST_PS_FENCE__LAST_FENCE__SHIFT 0x0
+#define CP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO_MASK 0xffffffff
+#define CP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO__SHIFT 0x0
+#define CP_ME_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO_MASK 0xffffffff
+#define CP_ME_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO__SHIFT 0x0
+#define CP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI_MASK 0xffffffff
+#define CP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI__SHIFT 0x0
+#define CP_ME_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI_MASK 0xffffffff
+#define CP_ME_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI__SHIFT 0x0
+#define CP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO_MASK 0xffffffff
+#define CP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO__SHIFT 0x0
+#define CP_ME_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO_MASK 0xffffffff
+#define CP_ME_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO__SHIFT 0x0
+#define CP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI_MASK 0xffffffff
+#define CP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI__SHIFT 0x0
+#define CP_ME_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI_MASK 0xffffffff
+#define CP_ME_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI__SHIFT 0x0
+#define CP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO_MASK 0xffffffff
+#define CP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO__SHIFT 0x0
+#define CP_ME_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO_MASK 0xffffffff
+#define CP_ME_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO__SHIFT 0x0
+#define CP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI_MASK 0xffffffff
+#define CP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI__SHIFT 0x0
+#define CP_ME_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI_MASK 0xffffffff
+#define CP_ME_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI__SHIFT 0x0
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_SWAP_MASK 0x3
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_SWAP__SHIFT 0x0
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_LO_MASK 0xfffffffc
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_LO__SHIFT 0x2
+#define CP_ME_MC_WADDR_HI__ME_MC_WADDR_HI_MASK 0xffff
+#define CP_ME_MC_WADDR_HI__ME_MC_WADDR_HI__SHIFT 0x0
+#define CP_ME_MC_WADDR_HI__MTYPE_MASK 0x300000
+#define CP_ME_MC_WADDR_HI__MTYPE__SHIFT 0x14
+#define CP_ME_MC_WADDR_HI__CACHE_POLICY_MASK 0x400000
+#define CP_ME_MC_WADDR_HI__CACHE_POLICY__SHIFT 0x16
+#define CP_ME_MC_WDATA_LO__ME_MC_WDATA_LO_MASK 0xffffffff
+#define CP_ME_MC_WDATA_LO__ME_MC_WDATA_LO__SHIFT 0x0
+#define CP_ME_MC_WDATA_HI__ME_MC_WDATA_HI_MASK 0xffffffff
+#define CP_ME_MC_WDATA_HI__ME_MC_WDATA_HI__SHIFT 0x0
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_SWAP_MASK 0x3
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_SWAP__SHIFT 0x0
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_LO_MASK 0xfffffffc
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_LO__SHIFT 0x2
+#define CP_ME_MC_RADDR_HI__ME_MC_RADDR_HI_MASK 0xffff
+#define CP_ME_MC_RADDR_HI__ME_MC_RADDR_HI__SHIFT 0x0
+#define CP_ME_MC_RADDR_HI__MTYPE_MASK 0x300000
+#define CP_ME_MC_RADDR_HI__MTYPE__SHIFT 0x14
+#define CP_ME_MC_RADDR_HI__CACHE_POLICY_MASK 0x400000
+#define CP_ME_MC_RADDR_HI__CACHE_POLICY__SHIFT 0x16
+#define CP_SEM_WAIT_TIMER__SEM_WAIT_TIMER_MASK 0xffffffff
+#define CP_SEM_WAIT_TIMER__SEM_WAIT_TIMER__SHIFT 0x0
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_SWAP_MASK 0x3
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_SWAP__SHIFT 0x0
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_LO_MASK 0xfffffff8
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_LO__SHIFT 0x3
+#define CP_SIG_SEM_ADDR_HI__SEM_ADDR_HI_MASK 0xffff
+#define CP_SIG_SEM_ADDR_HI__SEM_ADDR_HI__SHIFT 0x0
+#define CP_SIG_SEM_ADDR_HI__SEM_USE_MAILBOX_MASK 0x10000
+#define CP_SIG_SEM_ADDR_HI__SEM_USE_MAILBOX__SHIFT 0x10
+#define CP_SIG_SEM_ADDR_HI__SEM_SIGNAL_TYPE_MASK 0x100000
+#define CP_SIG_SEM_ADDR_HI__SEM_SIGNAL_TYPE__SHIFT 0x14
+#define CP_SIG_SEM_ADDR_HI__SEM_CLIENT_CODE_MASK 0x3000000
+#define CP_SIG_SEM_ADDR_HI__SEM_CLIENT_CODE__SHIFT 0x18
+#define CP_SIG_SEM_ADDR_HI__SEM_SELECT_MASK 0xe0000000
+#define CP_SIG_SEM_ADDR_HI__SEM_SELECT__SHIFT 0x1d
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_SWAP_MASK 0x3
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_SWAP__SHIFT 0x0
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_LO_MASK 0xfffffff8
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_LO__SHIFT 0x3
+#define CP_WAIT_SEM_ADDR_HI__SEM_ADDR_HI_MASK 0xffff
+#define CP_WAIT_SEM_ADDR_HI__SEM_ADDR_HI__SHIFT 0x0
+#define CP_WAIT_SEM_ADDR_HI__SEM_USE_MAILBOX_MASK 0x10000
+#define CP_WAIT_SEM_ADDR_HI__SEM_USE_MAILBOX__SHIFT 0x10
+#define CP_WAIT_SEM_ADDR_HI__SEM_SIGNAL_TYPE_MASK 0x100000
+#define CP_WAIT_SEM_ADDR_HI__SEM_SIGNAL_TYPE__SHIFT 0x14
+#define CP_WAIT_SEM_ADDR_HI__SEM_CLIENT_CODE_MASK 0x3000000
+#define CP_WAIT_SEM_ADDR_HI__SEM_CLIENT_CODE__SHIFT 0x18
+#define CP_WAIT_SEM_ADDR_HI__SEM_SELECT_MASK 0xe0000000
+#define CP_WAIT_SEM_ADDR_HI__SEM_SELECT__SHIFT 0x1d
+#define CP_WAIT_REG_MEM_TIMEOUT__WAIT_REG_MEM_TIMEOUT_MASK 0xffffffff
+#define CP_WAIT_REG_MEM_TIMEOUT__WAIT_REG_MEM_TIMEOUT__SHIFT 0x0
+#define CP_COHER_START_DELAY__START_DELAY_COUNT_MASK 0x3f
+#define CP_COHER_START_DELAY__START_DELAY_COUNT__SHIFT 0x0
+#define CP_COHER_CNTL__DEST_BASE_0_ENA_MASK 0x1
+#define CP_COHER_CNTL__DEST_BASE_0_ENA__SHIFT 0x0
+#define CP_COHER_CNTL__DEST_BASE_1_ENA_MASK 0x2
+#define CP_COHER_CNTL__DEST_BASE_1_ENA__SHIFT 0x1
+#define CP_COHER_CNTL__TC_SD_ACTION_ENA_MASK 0x4
+#define CP_COHER_CNTL__TC_SD_ACTION_ENA__SHIFT 0x2
+#define CP_COHER_CNTL__TC_NC_ACTION_ENA_MASK 0x8
+#define CP_COHER_CNTL__TC_NC_ACTION_ENA__SHIFT 0x3
+#define CP_COHER_CNTL__CB0_DEST_BASE_ENA_MASK 0x40
+#define CP_COHER_CNTL__CB0_DEST_BASE_ENA__SHIFT 0x6
+#define CP_COHER_CNTL__CB1_DEST_BASE_ENA_MASK 0x80
+#define CP_COHER_CNTL__CB1_DEST_BASE_ENA__SHIFT 0x7
+#define CP_COHER_CNTL__CB2_DEST_BASE_ENA_MASK 0x100
+#define CP_COHER_CNTL__CB2_DEST_BASE_ENA__SHIFT 0x8
+#define CP_COHER_CNTL__CB3_DEST_BASE_ENA_MASK 0x200
+#define CP_COHER_CNTL__CB3_DEST_BASE_ENA__SHIFT 0x9
+#define CP_COHER_CNTL__CB4_DEST_BASE_ENA_MASK 0x400
+#define CP_COHER_CNTL__CB4_DEST_BASE_ENA__SHIFT 0xa
+#define CP_COHER_CNTL__CB5_DEST_BASE_ENA_MASK 0x800
+#define CP_COHER_CNTL__CB5_DEST_BASE_ENA__SHIFT 0xb
+#define CP_COHER_CNTL__CB6_DEST_BASE_ENA_MASK 0x1000
+#define CP_COHER_CNTL__CB6_DEST_BASE_ENA__SHIFT 0xc
+#define CP_COHER_CNTL__CB7_DEST_BASE_ENA_MASK 0x2000
+#define CP_COHER_CNTL__CB7_DEST_BASE_ENA__SHIFT 0xd
+#define CP_COHER_CNTL__DB_DEST_BASE_ENA_MASK 0x4000
+#define CP_COHER_CNTL__DB_DEST_BASE_ENA__SHIFT 0xe
+#define CP_COHER_CNTL__TCL1_VOL_ACTION_ENA_MASK 0x8000
+#define CP_COHER_CNTL__TCL1_VOL_ACTION_ENA__SHIFT 0xf
+#define CP_COHER_CNTL__TC_WB_ACTION_ENA_MASK 0x40000
+#define CP_COHER_CNTL__TC_WB_ACTION_ENA__SHIFT 0x12
+#define CP_COHER_CNTL__DEST_BASE_2_ENA_MASK 0x80000
+#define CP_COHER_CNTL__DEST_BASE_2_ENA__SHIFT 0x13
+#define CP_COHER_CNTL__DEST_BASE_3_ENA_MASK 0x200000
+#define CP_COHER_CNTL__DEST_BASE_3_ENA__SHIFT 0x15
+#define CP_COHER_CNTL__TCL1_ACTION_ENA_MASK 0x400000
+#define CP_COHER_CNTL__TCL1_ACTION_ENA__SHIFT 0x16
+#define CP_COHER_CNTL__TC_ACTION_ENA_MASK 0x800000
+#define CP_COHER_CNTL__TC_ACTION_ENA__SHIFT 0x17
+#define CP_COHER_CNTL__CB_ACTION_ENA_MASK 0x2000000
+#define CP_COHER_CNTL__CB_ACTION_ENA__SHIFT 0x19
+#define CP_COHER_CNTL__DB_ACTION_ENA_MASK 0x4000000
+#define CP_COHER_CNTL__DB_ACTION_ENA__SHIFT 0x1a
+#define CP_COHER_CNTL__SH_KCACHE_ACTION_ENA_MASK 0x8000000
+#define CP_COHER_CNTL__SH_KCACHE_ACTION_ENA__SHIFT 0x1b
+#define CP_COHER_CNTL__SH_KCACHE_VOL_ACTION_ENA_MASK 0x10000000
+#define CP_COHER_CNTL__SH_KCACHE_VOL_ACTION_ENA__SHIFT 0x1c
+#define CP_COHER_CNTL__SH_ICACHE_ACTION_ENA_MASK 0x20000000
+#define CP_COHER_CNTL__SH_ICACHE_ACTION_ENA__SHIFT 0x1d
+#define CP_COHER_CNTL__SH_KCACHE_WB_ACTION_ENA_MASK 0x40000000
+#define CP_COHER_CNTL__SH_KCACHE_WB_ACTION_ENA__SHIFT 0x1e
+#define CP_COHER_CNTL__SH_SD_ACTION_ENA_MASK 0x80000000
+#define CP_COHER_CNTL__SH_SD_ACTION_ENA__SHIFT 0x1f
+#define CP_COHER_SIZE__COHER_SIZE_256B_MASK 0xffffffff
+#define CP_COHER_SIZE__COHER_SIZE_256B__SHIFT 0x0
+#define CP_COHER_SIZE_HI__COHER_SIZE_HI_256B_MASK 0xff
+#define CP_COHER_SIZE_HI__COHER_SIZE_HI_256B__SHIFT 0x0
+#define CP_COHER_BASE__COHER_BASE_256B_MASK 0xffffffff
+#define CP_COHER_BASE__COHER_BASE_256B__SHIFT 0x0
+#define CP_COHER_BASE_HI__COHER_BASE_HI_256B_MASK 0xff
+#define CP_COHER_BASE_HI__COHER_BASE_HI_256B__SHIFT 0x0
+#define CP_COHER_STATUS__MATCHING_GFX_CNTX_MASK 0xff
+#define CP_COHER_STATUS__MATCHING_GFX_CNTX__SHIFT 0x0
+#define CP_COHER_STATUS__MEID_MASK 0x3000000
+#define CP_COHER_STATUS__MEID__SHIFT 0x18
+#define CP_COHER_STATUS__PHASE1_STATUS_MASK 0x40000000
+#define CP_COHER_STATUS__PHASE1_STATUS__SHIFT 0x1e
+#define CP_COHER_STATUS__STATUS_MASK 0x80000000
+#define CP_COHER_STATUS__STATUS__SHIFT 0x1f
+#define COHER_DEST_BASE_0__DEST_BASE_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_0__DEST_BASE_256B__SHIFT 0x0
+#define COHER_DEST_BASE_1__DEST_BASE_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_1__DEST_BASE_256B__SHIFT 0x0
+#define COHER_DEST_BASE_2__DEST_BASE_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_2__DEST_BASE_256B__SHIFT 0x0
+#define COHER_DEST_BASE_3__DEST_BASE_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_3__DEST_BASE_256B__SHIFT 0x0
+#define COHER_DEST_BASE_HI_0__DEST_BASE_HI_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_HI_0__DEST_BASE_HI_256B__SHIFT 0x0
+#define COHER_DEST_BASE_HI_1__DEST_BASE_HI_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_HI_1__DEST_BASE_HI_256B__SHIFT 0x0
+#define COHER_DEST_BASE_HI_2__DEST_BASE_HI_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_HI_2__DEST_BASE_HI_256B__SHIFT 0x0
+#define COHER_DEST_BASE_HI_3__DEST_BASE_HI_256B_MASK 0xffffffff
+#define COHER_DEST_BASE_HI_3__DEST_BASE_HI_256B__SHIFT 0x0
+#define CP_DMA_ME_SRC_ADDR__SRC_ADDR_MASK 0xffffffff
+#define CP_DMA_ME_SRC_ADDR__SRC_ADDR__SHIFT 0x0
+#define CP_DMA_ME_SRC_ADDR_HI__SRC_ADDR_HI_MASK 0xffff
+#define CP_DMA_ME_SRC_ADDR_HI__SRC_ADDR_HI__SHIFT 0x0
+#define CP_DMA_ME_DST_ADDR__DST_ADDR_MASK 0xffffffff
+#define CP_DMA_ME_DST_ADDR__DST_ADDR__SHIFT 0x0
+#define CP_DMA_ME_DST_ADDR_HI__DST_ADDR_HI_MASK 0xffff
+#define CP_DMA_ME_DST_ADDR_HI__DST_ADDR_HI__SHIFT 0x0
+#define CP_DMA_ME_CONTROL__SRC_MTYPE_MASK 0xc00
+#define CP_DMA_ME_CONTROL__SRC_MTYPE__SHIFT 0xa
+#define CP_DMA_ME_CONTROL__SRC_ATC_MASK 0x1000
+#define CP_DMA_ME_CONTROL__SRC_ATC__SHIFT 0xc
+#define CP_DMA_ME_CONTROL__SRC_CACHE_POLICY_MASK 0x2000
+#define CP_DMA_ME_CONTROL__SRC_CACHE_POLICY__SHIFT 0xd
+#define CP_DMA_ME_CONTROL__DST_SELECT_MASK 0x300000
+#define CP_DMA_ME_CONTROL__DST_SELECT__SHIFT 0x14
+#define CP_DMA_ME_CONTROL__DST_MTYPE_MASK 0xc00000
+#define CP_DMA_ME_CONTROL__DST_MTYPE__SHIFT 0x16
+#define CP_DMA_ME_CONTROL__DST_ATC_MASK 0x1000000
+#define CP_DMA_ME_CONTROL__DST_ATC__SHIFT 0x18
+#define CP_DMA_ME_CONTROL__DST_CACHE_POLICY_MASK 0x2000000
+#define CP_DMA_ME_CONTROL__DST_CACHE_POLICY__SHIFT 0x19
+#define CP_DMA_ME_CONTROL__SRC_SELECT_MASK 0x60000000
+#define CP_DMA_ME_CONTROL__SRC_SELECT__SHIFT 0x1d
+#define CP_DMA_ME_COMMAND__BYTE_COUNT_MASK 0x1fffff
+#define CP_DMA_ME_COMMAND__BYTE_COUNT__SHIFT 0x0
+#define CP_DMA_ME_COMMAND__DIS_WC_MASK 0x200000
+#define CP_DMA_ME_COMMAND__DIS_WC__SHIFT 0x15
+#define CP_DMA_ME_COMMAND__SRC_SWAP_MASK 0xc00000
+#define CP_DMA_ME_COMMAND__SRC_SWAP__SHIFT 0x16
+#define CP_DMA_ME_COMMAND__DST_SWAP_MASK 0x3000000
+#define CP_DMA_ME_COMMAND__DST_SWAP__SHIFT 0x18
+#define CP_DMA_ME_COMMAND__SAS_MASK 0x4000000
+#define CP_DMA_ME_COMMAND__SAS__SHIFT 0x1a
+#define CP_DMA_ME_COMMAND__DAS_MASK 0x8000000
+#define CP_DMA_ME_COMMAND__DAS__SHIFT 0x1b
+#define CP_DMA_ME_COMMAND__SAIC_MASK 0x10000000
+#define CP_DMA_ME_COMMAND__SAIC__SHIFT 0x1c
+#define CP_DMA_ME_COMMAND__DAIC_MASK 0x20000000
+#define CP_DMA_ME_COMMAND__DAIC__SHIFT 0x1d
+#define CP_DMA_ME_COMMAND__RAW_WAIT_MASK 0x40000000
+#define CP_DMA_ME_COMMAND__RAW_WAIT__SHIFT 0x1e
+#define CP_DMA_PFP_SRC_ADDR__SRC_ADDR_MASK 0xffffffff
+#define CP_DMA_PFP_SRC_ADDR__SRC_ADDR__SHIFT 0x0
+#define CP_DMA_PFP_SRC_ADDR_HI__SRC_ADDR_HI_MASK 0xffff
+#define CP_DMA_PFP_SRC_ADDR_HI__SRC_ADDR_HI__SHIFT 0x0
+#define CP_DMA_PFP_DST_ADDR__DST_ADDR_MASK 0xffffffff
+#define CP_DMA_PFP_DST_ADDR__DST_ADDR__SHIFT 0x0
+#define CP_DMA_PFP_DST_ADDR_HI__DST_ADDR_HI_MASK 0xffff
+#define CP_DMA_PFP_DST_ADDR_HI__DST_ADDR_HI__SHIFT 0x0
+#define CP_DMA_PFP_CONTROL__SRC_MTYPE_MASK 0xc00
+#define CP_DMA_PFP_CONTROL__SRC_MTYPE__SHIFT 0xa
+#define CP_DMA_PFP_CONTROL__SRC_ATC_MASK 0x1000
+#define CP_DMA_PFP_CONTROL__SRC_ATC__SHIFT 0xc
+#define CP_DMA_PFP_CONTROL__SRC_CACHE_POLICY_MASK 0x2000
+#define CP_DMA_PFP_CONTROL__SRC_CACHE_POLICY__SHIFT 0xd
+#define CP_DMA_PFP_CONTROL__DST_SELECT_MASK 0x300000
+#define CP_DMA_PFP_CONTROL__DST_SELECT__SHIFT 0x14
+#define CP_DMA_PFP_CONTROL__DST_MTYPE_MASK 0xc00000
+#define CP_DMA_PFP_CONTROL__DST_MTYPE__SHIFT 0x16
+#define CP_DMA_PFP_CONTROL__DST_ATC_MASK 0x1000000
+#define CP_DMA_PFP_CONTROL__DST_ATC__SHIFT 0x18
+#define CP_DMA_PFP_CONTROL__DST_CACHE_POLICY_MASK 0x2000000
+#define CP_DMA_PFP_CONTROL__DST_CACHE_POLICY__SHIFT 0x19
+#define CP_DMA_PFP_CONTROL__SRC_SELECT_MASK 0x60000000
+#define CP_DMA_PFP_CONTROL__SRC_SELECT__SHIFT 0x1d
+#define CP_DMA_PFP_COMMAND__BYTE_COUNT_MASK 0x1fffff
+#define CP_DMA_PFP_COMMAND__BYTE_COUNT__SHIFT 0x0
+#define CP_DMA_PFP_COMMAND__DIS_WC_MASK 0x200000
+#define CP_DMA_PFP_COMMAND__DIS_WC__SHIFT 0x15
+#define CP_DMA_PFP_COMMAND__SRC_SWAP_MASK 0xc00000
+#define CP_DMA_PFP_COMMAND__SRC_SWAP__SHIFT 0x16
+#define CP_DMA_PFP_COMMAND__DST_SWAP_MASK 0x3000000
+#define CP_DMA_PFP_COMMAND__DST_SWAP__SHIFT 0x18
+#define CP_DMA_PFP_COMMAND__SAS_MASK 0x4000000
+#define CP_DMA_PFP_COMMAND__SAS__SHIFT 0x1a
+#define CP_DMA_PFP_COMMAND__DAS_MASK 0x8000000
+#define CP_DMA_PFP_COMMAND__DAS__SHIFT 0x1b
+#define CP_DMA_PFP_COMMAND__SAIC_MASK 0x10000000
+#define CP_DMA_PFP_COMMAND__SAIC__SHIFT 0x1c
+#define CP_DMA_PFP_COMMAND__DAIC_MASK 0x20000000
+#define CP_DMA_PFP_COMMAND__DAIC__SHIFT 0x1d
+#define CP_DMA_PFP_COMMAND__RAW_WAIT_MASK 0x40000000
+#define CP_DMA_PFP_COMMAND__RAW_WAIT__SHIFT 0x1e
+#define CP_DMA_CNTL__MIN_AVAILSZ_MASK 0x30
+#define CP_DMA_CNTL__MIN_AVAILSZ__SHIFT 0x4
+#define CP_DMA_CNTL__BUFFER_DEPTH_MASK 0xf0000
+#define CP_DMA_CNTL__BUFFER_DEPTH__SHIFT 0x10
+#define CP_DMA_CNTL__PIO_FIFO_EMPTY_MASK 0x10000000
+#define CP_DMA_CNTL__PIO_FIFO_EMPTY__SHIFT 0x1c
+#define CP_DMA_CNTL__PIO_FIFO_FULL_MASK 0x20000000
+#define CP_DMA_CNTL__PIO_FIFO_FULL__SHIFT 0x1d
+#define CP_DMA_CNTL__PIO_COUNT_MASK 0xc0000000
+#define CP_DMA_CNTL__PIO_COUNT__SHIFT 0x1e
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_MASK 0x3ffffff
+#define CP_DMA_READ_TAGS__DMA_READ_TAG__SHIFT 0x0
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_VALID_MASK 0x10000000
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_VALID__SHIFT 0x1c
+#define CP_PFP_IB_CONTROL__IB_EN_MASK 0xff
+#define CP_PFP_IB_CONTROL__IB_EN__SHIFT 0x0
+#define CP_PFP_LOAD_CONTROL__CONFIG_REG_EN_MASK 0x1
+#define CP_PFP_LOAD_CONTROL__CONFIG_REG_EN__SHIFT 0x0
+#define CP_PFP_LOAD_CONTROL__CNTX_REG_EN_MASK 0x2
+#define CP_PFP_LOAD_CONTROL__CNTX_REG_EN__SHIFT 0x1
+#define CP_PFP_LOAD_CONTROL__SH_GFX_REG_EN_MASK 0x10000
+#define CP_PFP_LOAD_CONTROL__SH_GFX_REG_EN__SHIFT 0x10
+#define CP_PFP_LOAD_CONTROL__SH_CS_REG_EN_MASK 0x1000000
+#define CP_PFP_LOAD_CONTROL__SH_CS_REG_EN__SHIFT 0x18
+#define CP_SCRATCH_INDEX__SCRATCH_INDEX_MASK 0xff
+#define CP_SCRATCH_INDEX__SCRATCH_INDEX__SHIFT 0x0
+#define CP_SCRATCH_DATA__SCRATCH_DATA_MASK 0xffffffff
+#define CP_SCRATCH_DATA__SCRATCH_DATA__SHIFT 0x0
+#define CP_RB_OFFSET__RB_OFFSET_MASK 0xfffff
+#define CP_RB_OFFSET__RB_OFFSET__SHIFT 0x0
+#define CP_IB1_OFFSET__IB1_OFFSET_MASK 0xfffff
+#define CP_IB1_OFFSET__IB1_OFFSET__SHIFT 0x0
+#define CP_IB2_OFFSET__IB2_OFFSET_MASK 0xfffff
+#define CP_IB2_OFFSET__IB2_OFFSET__SHIFT 0x0
+#define CP_IB1_PREAMBLE_BEGIN__IB1_PREAMBLE_BEGIN_MASK 0xfffff
+#define CP_IB1_PREAMBLE_BEGIN__IB1_PREAMBLE_BEGIN__SHIFT 0x0
+#define CP_IB1_PREAMBLE_END__IB1_PREAMBLE_END_MASK 0xfffff
+#define CP_IB1_PREAMBLE_END__IB1_PREAMBLE_END__SHIFT 0x0
+#define CP_IB2_PREAMBLE_BEGIN__IB2_PREAMBLE_BEGIN_MASK 0xfffff
+#define CP_IB2_PREAMBLE_BEGIN__IB2_PREAMBLE_BEGIN__SHIFT 0x0
+#define CP_IB2_PREAMBLE_END__IB2_PREAMBLE_END_MASK 0xfffff
+#define CP_IB2_PREAMBLE_END__IB2_PREAMBLE_END__SHIFT 0x0
+#define CP_CE_IB1_OFFSET__IB1_OFFSET_MASK 0xfffff
+#define CP_CE_IB1_OFFSET__IB1_OFFSET__SHIFT 0x0
+#define CP_CE_IB2_OFFSET__IB2_OFFSET_MASK 0xfffff
+#define CP_CE_IB2_OFFSET__IB2_OFFSET__SHIFT 0x0
+#define CP_CE_COUNTER__CONST_ENGINE_COUNT_MASK 0xffffffff
+#define CP_CE_COUNTER__CONST_ENGINE_COUNT__SHIFT 0x0
+#define CP_CE_RB_OFFSET__RB_OFFSET_MASK 0xfffff
+#define CP_CE_RB_OFFSET__RB_OFFSET__SHIFT 0x0
+#define CP_PFP_COMPLETION_STATUS__STATUS_MASK 0x3
+#define CP_PFP_COMPLETION_STATUS__STATUS__SHIFT 0x0
+#define CP_CE_COMPLETION_STATUS__STATUS_MASK 0x3
+#define CP_CE_COMPLETION_STATUS__STATUS__SHIFT 0x0
+#define CP_PRED_NOT_VISIBLE__NOT_VISIBLE_MASK 0x1
+#define CP_PRED_NOT_VISIBLE__NOT_VISIBLE__SHIFT 0x0
+#define CP_PFP_METADATA_BASE_ADDR__ADDR_LO_MASK 0xffffffff
+#define CP_PFP_METADATA_BASE_ADDR__ADDR_LO__SHIFT 0x0
+#define CP_PFP_METADATA_BASE_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_PFP_METADATA_BASE_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_CE_METADATA_BASE_ADDR__ADDR_LO_MASK 0xffffffff
+#define CP_CE_METADATA_BASE_ADDR__ADDR_LO__SHIFT 0x0
+#define CP_CE_METADATA_BASE_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_CE_METADATA_BASE_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_DRAW_INDX_INDR_ADDR__ADDR_LO_MASK 0xffffffff
+#define CP_DRAW_INDX_INDR_ADDR__ADDR_LO__SHIFT 0x0
+#define CP_DRAW_INDX_INDR_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_DRAW_INDX_INDR_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_DISPATCH_INDR_ADDR__ADDR_LO_MASK 0xffffffff
+#define CP_DISPATCH_INDR_ADDR__ADDR_LO__SHIFT 0x0
+#define CP_DISPATCH_INDR_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_DISPATCH_INDR_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_INDEX_BASE_ADDR__ADDR_LO_MASK 0xffffffff
+#define CP_INDEX_BASE_ADDR__ADDR_LO__SHIFT 0x0
+#define CP_INDEX_BASE_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_INDEX_BASE_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_INDEX_TYPE__INDEX_TYPE_MASK 0x3
+#define CP_INDEX_TYPE__INDEX_TYPE__SHIFT 0x0
+#define CP_GDS_BKUP_ADDR__ADDR_LO_MASK 0xffffffff
+#define CP_GDS_BKUP_ADDR__ADDR_LO__SHIFT 0x0
+#define CP_GDS_BKUP_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_GDS_BKUP_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_SAMPLE_STATUS__Z_PASS_ACITVE_MASK 0x1
+#define CP_SAMPLE_STATUS__Z_PASS_ACITVE__SHIFT 0x0
+#define CP_SAMPLE_STATUS__STREAMOUT_ACTIVE_MASK 0x2
+#define CP_SAMPLE_STATUS__STREAMOUT_ACTIVE__SHIFT 0x1
+#define CP_SAMPLE_STATUS__PIPELINE_ACTIVE_MASK 0x4
+#define CP_SAMPLE_STATUS__PIPELINE_ACTIVE__SHIFT 0x2
+#define CP_SAMPLE_STATUS__STIPPLE_ACTIVE_MASK 0x8
+#define CP_SAMPLE_STATUS__STIPPLE_ACTIVE__SHIFT 0x3
+#define CP_SAMPLE_STATUS__VGT_BUFFERS_ACTIVE_MASK 0x10
+#define CP_SAMPLE_STATUS__VGT_BUFFERS_ACTIVE__SHIFT 0x4
+#define CP_SAMPLE_STATUS__SCREEN_EXT_ACTIVE_MASK 0x20
+#define CP_SAMPLE_STATUS__SCREEN_EXT_ACTIVE__SHIFT 0x5
+#define CP_SAMPLE_STATUS__DRAW_INDIRECT_ACTIVE_MASK 0x40
+#define CP_SAMPLE_STATUS__DRAW_INDIRECT_ACTIVE__SHIFT 0x6
+#define CP_SAMPLE_STATUS__DISP_INDIRECT_ACTIVE_MASK 0x80
+#define CP_SAMPLE_STATUS__DISP_INDIRECT_ACTIVE__SHIFT 0x7
+#define CP_STALLED_STAT1__RBIU_TO_DMA_NOT_RDY_TO_RCV_MASK 0x1
+#define CP_STALLED_STAT1__RBIU_TO_DMA_NOT_RDY_TO_RCV__SHIFT 0x0
+#define CP_STALLED_STAT1__RBIU_TO_SEM_NOT_RDY_TO_RCV_MASK 0x4
+#define CP_STALLED_STAT1__RBIU_TO_SEM_NOT_RDY_TO_RCV__SHIFT 0x2
+#define CP_STALLED_STAT1__RBIU_TO_MEMWR_NOT_RDY_TO_RCV_MASK 0x10
+#define CP_STALLED_STAT1__RBIU_TO_MEMWR_NOT_RDY_TO_RCV__SHIFT 0x4
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_CE_BUFFER_FLAG_MASK 0x400
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_CE_BUFFER_FLAG__SHIFT 0xa
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_DE_BUFFER_FLAG_MASK 0x800
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_DE_BUFFER_FLAG__SHIFT 0xb
+#define CP_STALLED_STAT1__ME_STALLED_ON_TC_WR_CONFIRM_MASK 0x1000
+#define CP_STALLED_STAT1__ME_STALLED_ON_TC_WR_CONFIRM__SHIFT 0xc
+#define CP_STALLED_STAT1__ME_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x2000
+#define CP_STALLED_STAT1__ME_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0xd
+#define CP_STALLED_STAT1__ME_WAITING_ON_TC_READ_DATA_MASK 0x4000
+#define CP_STALLED_STAT1__ME_WAITING_ON_TC_READ_DATA__SHIFT 0xe
+#define CP_STALLED_STAT1__ME_WAITING_ON_REG_READ_DATA_MASK 0x8000
+#define CP_STALLED_STAT1__ME_WAITING_ON_REG_READ_DATA__SHIFT 0xf
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GDS_FREE_MASK 0x800000
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GDS_FREE__SHIFT 0x17
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GRBM_FREE_MASK 0x1000000
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GRBM_FREE__SHIFT 0x18
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_VGT_FREE_MASK 0x2000000
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_VGT_FREE__SHIFT 0x19
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_ME_READ_MASK 0x4000000
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_ME_READ__SHIFT 0x1a
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_DMA_READ_MASK 0x8000000
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_DMA_READ__SHIFT 0x1b
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_APPEND_READ_MASK 0x10000000
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_APPEND_READ__SHIFT 0x1c
+#define CP_STALLED_STAT1__RCIU_HALTED_BY_REG_VIOLATION_MASK 0x20000000
+#define CP_STALLED_STAT1__RCIU_HALTED_BY_REG_VIOLATION__SHIFT 0x1d
+#define CP_STALLED_STAT2__PFP_TO_CSF_NOT_RDY_TO_RCV_MASK 0x1
+#define CP_STALLED_STAT2__PFP_TO_CSF_NOT_RDY_TO_RCV__SHIFT 0x0
+#define CP_STALLED_STAT2__PFP_TO_MEQ_NOT_RDY_TO_RCV_MASK 0x2
+#define CP_STALLED_STAT2__PFP_TO_MEQ_NOT_RDY_TO_RCV__SHIFT 0x1
+#define CP_STALLED_STAT2__PFP_TO_RCIU_NOT_RDY_TO_RCV_MASK 0x4
+#define CP_STALLED_STAT2__PFP_TO_RCIU_NOT_RDY_TO_RCV__SHIFT 0x2
+#define CP_STALLED_STAT2__PFP_TO_VGT_WRITES_PENDING_MASK 0x10
+#define CP_STALLED_STAT2__PFP_TO_VGT_WRITES_PENDING__SHIFT 0x4
+#define CP_STALLED_STAT2__PFP_RCIU_READ_PENDING_MASK 0x20
+#define CP_STALLED_STAT2__PFP_RCIU_READ_PENDING__SHIFT 0x5
+#define CP_STALLED_STAT2__PFP_WAITING_ON_BUFFER_DATA_MASK 0x100
+#define CP_STALLED_STAT2__PFP_WAITING_ON_BUFFER_DATA__SHIFT 0x8
+#define CP_STALLED_STAT2__ME_WAIT_ON_CE_COUNTER_MASK 0x200
+#define CP_STALLED_STAT2__ME_WAIT_ON_CE_COUNTER__SHIFT 0x9
+#define CP_STALLED_STAT2__ME_WAIT_ON_AVAIL_BUFFER_MASK 0x400
+#define CP_STALLED_STAT2__ME_WAIT_ON_AVAIL_BUFFER__SHIFT 0xa
+#define CP_STALLED_STAT2__GFX_CNTX_NOT_AVAIL_TO_ME_MASK 0x800
+#define CP_STALLED_STAT2__GFX_CNTX_NOT_AVAIL_TO_ME__SHIFT 0xb
+#define CP_STALLED_STAT2__ME_RCIU_NOT_RDY_TO_RCV_MASK 0x1000
+#define CP_STALLED_STAT2__ME_RCIU_NOT_RDY_TO_RCV__SHIFT 0xc
+#define CP_STALLED_STAT2__ME_TO_CONST_NOT_RDY_TO_RCV_MASK 0x2000
+#define CP_STALLED_STAT2__ME_TO_CONST_NOT_RDY_TO_RCV__SHIFT 0xd
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_PFP_MASK 0x4000
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_PFP__SHIFT 0xe
+#define CP_STALLED_STAT2__ME_WAITING_ON_PARTIAL_FLUSH_MASK 0x8000
+#define CP_STALLED_STAT2__ME_WAITING_ON_PARTIAL_FLUSH__SHIFT 0xf
+#define CP_STALLED_STAT2__MEQ_TO_ME_NOT_RDY_TO_RCV_MASK 0x10000
+#define CP_STALLED_STAT2__MEQ_TO_ME_NOT_RDY_TO_RCV__SHIFT 0x10
+#define CP_STALLED_STAT2__STQ_TO_ME_NOT_RDY_TO_RCV_MASK 0x20000
+#define CP_STALLED_STAT2__STQ_TO_ME_NOT_RDY_TO_RCV__SHIFT 0x11
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_STQ_MASK 0x40000
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_STQ__SHIFT 0x12
+#define CP_STALLED_STAT2__PFP_STALLED_ON_TC_WR_CONFIRM_MASK 0x80000
+#define CP_STALLED_STAT2__PFP_STALLED_ON_TC_WR_CONFIRM__SHIFT 0x13
+#define CP_STALLED_STAT2__PFP_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x100000
+#define CP_STALLED_STAT2__PFP_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0x14
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_SC_EOP_DONE_MASK 0x200000
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_SC_EOP_DONE__SHIFT 0x15
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_WR_CONFIRM_MASK 0x400000
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_WR_CONFIRM__SHIFT 0x16
+#define CP_STALLED_STAT2__STRMO_WR_OF_PRIM_DATA_PENDING_MASK 0x800000
+#define CP_STALLED_STAT2__STRMO_WR_OF_PRIM_DATA_PENDING__SHIFT 0x17
+#define CP_STALLED_STAT2__PIPE_STATS_WR_DATA_PENDING_MASK 0x1000000
+#define CP_STALLED_STAT2__PIPE_STATS_WR_DATA_PENDING__SHIFT 0x18
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_CS_DONE_MASK 0x2000000
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_CS_DONE__SHIFT 0x19
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_PS_DONE_MASK 0x4000000
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_PS_DONE__SHIFT 0x1a
+#define CP_STALLED_STAT2__APPEND_WAIT_ON_WR_CONFIRM_MASK 0x8000000
+#define CP_STALLED_STAT2__APPEND_WAIT_ON_WR_CONFIRM__SHIFT 0x1b
+#define CP_STALLED_STAT2__APPEND_ACTIVE_PARTITION_MASK 0x10000000
+#define CP_STALLED_STAT2__APPEND_ACTIVE_PARTITION__SHIFT 0x1c
+#define CP_STALLED_STAT2__APPEND_WAITING_TO_SEND_MEMWRITE_MASK 0x20000000
+#define CP_STALLED_STAT2__APPEND_WAITING_TO_SEND_MEMWRITE__SHIFT 0x1d
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_IDLE_CNTXS_MASK 0x40000000
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_IDLE_CNTXS__SHIFT 0x1e
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_ALL_CLEAN_MASK 0x80000000
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_ALL_CLEAN__SHIFT 0x1f
+#define CP_STALLED_STAT3__CE_TO_CSF_NOT_RDY_TO_RCV_MASK 0x1
+#define CP_STALLED_STAT3__CE_TO_CSF_NOT_RDY_TO_RCV__SHIFT 0x0
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_FETCHER_NOT_RDY_TO_RCV_MASK 0x2
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_FETCHER_NOT_RDY_TO_RCV__SHIFT 0x1
+#define CP_STALLED_STAT3__CE_WAITING_ON_DATA_FROM_RAM_INIT_FETCHER_MASK 0x4
+#define CP_STALLED_STAT3__CE_WAITING_ON_DATA_FROM_RAM_INIT_FETCHER__SHIFT 0x2
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_NOT_RDY_MASK 0x8
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_NOT_RDY__SHIFT 0x3
+#define CP_STALLED_STAT3__CE_TO_RAM_DUMP_NOT_RDY_MASK 0x10
+#define CP_STALLED_STAT3__CE_TO_RAM_DUMP_NOT_RDY__SHIFT 0x4
+#define CP_STALLED_STAT3__CE_TO_RAM_WRITE_NOT_RDY_MASK 0x20
+#define CP_STALLED_STAT3__CE_TO_RAM_WRITE_NOT_RDY__SHIFT 0x5
+#define CP_STALLED_STAT3__CE_TO_INC_FIFO_NOT_RDY_TO_RCV_MASK 0x40
+#define CP_STALLED_STAT3__CE_TO_INC_FIFO_NOT_RDY_TO_RCV__SHIFT 0x6
+#define CP_STALLED_STAT3__CE_TO_WR_FIFO_NOT_RDY_TO_RCV_MASK 0x80
+#define CP_STALLED_STAT3__CE_TO_WR_FIFO_NOT_RDY_TO_RCV__SHIFT 0x7
+#define CP_STALLED_STAT3__CE_WAITING_ON_BUFFER_DATA_MASK 0x400
+#define CP_STALLED_STAT3__CE_WAITING_ON_BUFFER_DATA__SHIFT 0xa
+#define CP_STALLED_STAT3__CE_WAITING_ON_CE_BUFFER_FLAG_MASK 0x800
+#define CP_STALLED_STAT3__CE_WAITING_ON_CE_BUFFER_FLAG__SHIFT 0xb
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_MASK 0x1000
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER__SHIFT 0xc
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_UNDERFLOW_MASK 0x2000
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_UNDERFLOW__SHIFT 0xd
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_FREE_MASK 0x4000
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_FREE__SHIFT 0xe
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_TAGS_MASK 0x8000
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_TAGS__SHIFT 0xf
+#define CP_STALLED_STAT3__CE_STALLED_ON_TC_WR_CONFIRM_MASK 0x10000
+#define CP_STALLED_STAT3__CE_STALLED_ON_TC_WR_CONFIRM__SHIFT 0x10
+#define CP_STALLED_STAT3__CE_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x20000
+#define CP_STALLED_STAT3__CE_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0x11
+#define CP_STALLED_STAT3__ATCL2IU_WAITING_ON_FREE_MASK 0x40000
+#define CP_STALLED_STAT3__ATCL2IU_WAITING_ON_FREE__SHIFT 0x12
+#define CP_STALLED_STAT3__ATCL2IU_WAITING_ON_TAGS_MASK 0x80000
+#define CP_STALLED_STAT3__ATCL2IU_WAITING_ON_TAGS__SHIFT 0x13
+#define CP_STALLED_STAT3__ATCL1_WAITING_ON_TRANS_MASK 0x100000
+#define CP_STALLED_STAT3__ATCL1_WAITING_ON_TRANS__SHIFT 0x14
+#define CP_BUSY_STAT__REG_BUS_FIFO_BUSY_MASK 0x1
+#define CP_BUSY_STAT__REG_BUS_FIFO_BUSY__SHIFT 0x0
+#define CP_BUSY_STAT__COHER_CNT_NEQ_ZERO_MASK 0x40
+#define CP_BUSY_STAT__COHER_CNT_NEQ_ZERO__SHIFT 0x6
+#define CP_BUSY_STAT__PFP_PARSING_PACKETS_MASK 0x80
+#define CP_BUSY_STAT__PFP_PARSING_PACKETS__SHIFT 0x7
+#define CP_BUSY_STAT__ME_PARSING_PACKETS_MASK 0x100
+#define CP_BUSY_STAT__ME_PARSING_PACKETS__SHIFT 0x8
+#define CP_BUSY_STAT__RCIU_PFP_BUSY_MASK 0x200
+#define CP_BUSY_STAT__RCIU_PFP_BUSY__SHIFT 0x9
+#define CP_BUSY_STAT__RCIU_ME_BUSY_MASK 0x400
+#define CP_BUSY_STAT__RCIU_ME_BUSY__SHIFT 0xa
+#define CP_BUSY_STAT__SEM_CMDFIFO_NOT_EMPTY_MASK 0x1000
+#define CP_BUSY_STAT__SEM_CMDFIFO_NOT_EMPTY__SHIFT 0xc
+#define CP_BUSY_STAT__SEM_FAILED_AND_HOLDING_MASK 0x2000
+#define CP_BUSY_STAT__SEM_FAILED_AND_HOLDING__SHIFT 0xd
+#define CP_BUSY_STAT__SEM_POLLING_FOR_PASS_MASK 0x4000
+#define CP_BUSY_STAT__SEM_POLLING_FOR_PASS__SHIFT 0xe
+#define CP_BUSY_STAT__GFX_CONTEXT_BUSY_MASK 0x8000
+#define CP_BUSY_STAT__GFX_CONTEXT_BUSY__SHIFT 0xf
+#define CP_BUSY_STAT__ME_PARSER_BUSY_MASK 0x20000
+#define CP_BUSY_STAT__ME_PARSER_BUSY__SHIFT 0x11
+#define CP_BUSY_STAT__EOP_DONE_BUSY_MASK 0x40000
+#define CP_BUSY_STAT__EOP_DONE_BUSY__SHIFT 0x12
+#define CP_BUSY_STAT__STRM_OUT_BUSY_MASK 0x80000
+#define CP_BUSY_STAT__STRM_OUT_BUSY__SHIFT 0x13
+#define CP_BUSY_STAT__PIPE_STATS_BUSY_MASK 0x100000
+#define CP_BUSY_STAT__PIPE_STATS_BUSY__SHIFT 0x14
+#define CP_BUSY_STAT__RCIU_CE_BUSY_MASK 0x200000
+#define CP_BUSY_STAT__RCIU_CE_BUSY__SHIFT 0x15
+#define CP_BUSY_STAT__CE_PARSING_PACKETS_MASK 0x400000
+#define CP_BUSY_STAT__CE_PARSING_PACKETS__SHIFT 0x16
+#define CP_STAT__ROQ_RING_BUSY_MASK 0x200
+#define CP_STAT__ROQ_RING_BUSY__SHIFT 0x9
+#define CP_STAT__ROQ_INDIRECT1_BUSY_MASK 0x400
+#define CP_STAT__ROQ_INDIRECT1_BUSY__SHIFT 0xa
+#define CP_STAT__ROQ_INDIRECT2_BUSY_MASK 0x800
+#define CP_STAT__ROQ_INDIRECT2_BUSY__SHIFT 0xb
+#define CP_STAT__ROQ_STATE_BUSY_MASK 0x1000
+#define CP_STAT__ROQ_STATE_BUSY__SHIFT 0xc
+#define CP_STAT__DC_BUSY_MASK 0x2000
+#define CP_STAT__DC_BUSY__SHIFT 0xd
+#define CP_STAT__ATCL2IU_BUSY_MASK 0x4000
+#define CP_STAT__ATCL2IU_BUSY__SHIFT 0xe
+#define CP_STAT__PFP_BUSY_MASK 0x8000
+#define CP_STAT__PFP_BUSY__SHIFT 0xf
+#define CP_STAT__MEQ_BUSY_MASK 0x10000
+#define CP_STAT__MEQ_BUSY__SHIFT 0x10
+#define CP_STAT__ME_BUSY_MASK 0x20000
+#define CP_STAT__ME_BUSY__SHIFT 0x11
+#define CP_STAT__QUERY_BUSY_MASK 0x40000
+#define CP_STAT__QUERY_BUSY__SHIFT 0x12
+#define CP_STAT__SEMAPHORE_BUSY_MASK 0x80000
+#define CP_STAT__SEMAPHORE_BUSY__SHIFT 0x13
+#define CP_STAT__INTERRUPT_BUSY_MASK 0x100000
+#define CP_STAT__INTERRUPT_BUSY__SHIFT 0x14
+#define CP_STAT__SURFACE_SYNC_BUSY_MASK 0x200000
+#define CP_STAT__SURFACE_SYNC_BUSY__SHIFT 0x15
+#define CP_STAT__DMA_BUSY_MASK 0x400000
+#define CP_STAT__DMA_BUSY__SHIFT 0x16
+#define CP_STAT__RCIU_BUSY_MASK 0x800000
+#define CP_STAT__RCIU_BUSY__SHIFT 0x17
+#define CP_STAT__SCRATCH_RAM_BUSY_MASK 0x1000000
+#define CP_STAT__SCRATCH_RAM_BUSY__SHIFT 0x18
+#define CP_STAT__CPC_CPG_BUSY_MASK 0x2000000
+#define CP_STAT__CPC_CPG_BUSY__SHIFT 0x19
+#define CP_STAT__CE_BUSY_MASK 0x4000000
+#define CP_STAT__CE_BUSY__SHIFT 0x1a
+#define CP_STAT__TCIU_BUSY_MASK 0x8000000
+#define CP_STAT__TCIU_BUSY__SHIFT 0x1b
+#define CP_STAT__ROQ_CE_RING_BUSY_MASK 0x10000000
+#define CP_STAT__ROQ_CE_RING_BUSY__SHIFT 0x1c
+#define CP_STAT__ROQ_CE_INDIRECT1_BUSY_MASK 0x20000000
+#define CP_STAT__ROQ_CE_INDIRECT1_BUSY__SHIFT 0x1d
+#define CP_STAT__ROQ_CE_INDIRECT2_BUSY_MASK 0x40000000
+#define CP_STAT__ROQ_CE_INDIRECT2_BUSY__SHIFT 0x1e
+#define CP_STAT__CP_BUSY_MASK 0x80000000
+#define CP_STAT__CP_BUSY__SHIFT 0x1f
+#define CP_ME_HEADER_DUMP__ME_HEADER_DUMP_MASK 0xffffffff
+#define CP_ME_HEADER_DUMP__ME_HEADER_DUMP__SHIFT 0x0
+#define CP_PFP_HEADER_DUMP__PFP_HEADER_DUMP_MASK 0xffffffff
+#define CP_PFP_HEADER_DUMP__PFP_HEADER_DUMP__SHIFT 0x0
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_MASK 0x3f
+#define CP_GRBM_FREE_COUNT__FREE_COUNT__SHIFT 0x0
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_GDS_MASK 0x3f00
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_GDS__SHIFT 0x8
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_PFP_MASK 0x3f0000
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_PFP__SHIFT 0x10
+#define CP_CE_HEADER_DUMP__CE_HEADER_DUMP_MASK 0xffffffff
+#define CP_CE_HEADER_DUMP__CE_HEADER_DUMP__SHIFT 0x0
+#define CP_CSF_STAT__BUFFER_SLOTS_ALLOCATED_MASK 0xf
+#define CP_CSF_STAT__BUFFER_SLOTS_ALLOCATED__SHIFT 0x0
+#define CP_CSF_STAT__BUFFER_REQUEST_COUNT_MASK 0x1ff00
+#define CP_CSF_STAT__BUFFER_REQUEST_COUNT__SHIFT 0x8
+#define CP_CSF_CNTL__FETCH_BUFFER_DEPTH_MASK 0xf
+#define CP_CSF_CNTL__FETCH_BUFFER_DEPTH__SHIFT 0x0
+#define CP_ME_CNTL__CE_INVALIDATE_ICACHE_MASK 0x10
+#define CP_ME_CNTL__CE_INVALIDATE_ICACHE__SHIFT 0x4
+#define CP_ME_CNTL__PFP_INVALIDATE_ICACHE_MASK 0x40
+#define CP_ME_CNTL__PFP_INVALIDATE_ICACHE__SHIFT 0x6
+#define CP_ME_CNTL__ME_INVALIDATE_ICACHE_MASK 0x100
+#define CP_ME_CNTL__ME_INVALIDATE_ICACHE__SHIFT 0x8
+#define CP_ME_CNTL__CE_PIPE0_RESET_MASK 0x10000
+#define CP_ME_CNTL__CE_PIPE0_RESET__SHIFT 0x10
+#define CP_ME_CNTL__PFP_PIPE0_RESET_MASK 0x40000
+#define CP_ME_CNTL__PFP_PIPE0_RESET__SHIFT 0x12
+#define CP_ME_CNTL__ME_PIPE0_RESET_MASK 0x100000
+#define CP_ME_CNTL__ME_PIPE0_RESET__SHIFT 0x14
+#define CP_ME_CNTL__CE_HALT_MASK 0x1000000
+#define CP_ME_CNTL__CE_HALT__SHIFT 0x18
+#define CP_ME_CNTL__CE_STEP_MASK 0x2000000
+#define CP_ME_CNTL__CE_STEP__SHIFT 0x19
+#define CP_ME_CNTL__PFP_HALT_MASK 0x4000000
+#define CP_ME_CNTL__PFP_HALT__SHIFT 0x1a
+#define CP_ME_CNTL__PFP_STEP_MASK 0x8000000
+#define CP_ME_CNTL__PFP_STEP__SHIFT 0x1b
+#define CP_ME_CNTL__ME_HALT_MASK 0x10000000
+#define CP_ME_CNTL__ME_HALT__SHIFT 0x1c
+#define CP_ME_CNTL__ME_STEP_MASK 0x20000000
+#define CP_ME_CNTL__ME_STEP__SHIFT 0x1d
+#define CP_CNTX_STAT__ACTIVE_HP3D_CONTEXTS_MASK 0xff
+#define CP_CNTX_STAT__ACTIVE_HP3D_CONTEXTS__SHIFT 0x0
+#define CP_CNTX_STAT__CURRENT_HP3D_CONTEXT_MASK 0x700
+#define CP_CNTX_STAT__CURRENT_HP3D_CONTEXT__SHIFT 0x8
+#define CP_CNTX_STAT__ACTIVE_GFX_CONTEXTS_MASK 0xff00000
+#define CP_CNTX_STAT__ACTIVE_GFX_CONTEXTS__SHIFT 0x14
+#define CP_CNTX_STAT__CURRENT_GFX_CONTEXT_MASK 0x70000000
+#define CP_CNTX_STAT__CURRENT_GFX_CONTEXT__SHIFT 0x1c
+#define CP_ME_PREEMPTION__OBSOLETE_MASK 0x1
+#define CP_ME_PREEMPTION__OBSOLETE__SHIFT 0x0
+#define CP_RB0_RPTR__RB_RPTR_MASK 0xfffff
+#define CP_RB0_RPTR__RB_RPTR__SHIFT 0x0
+#define CP_RB_RPTR__RB_RPTR_MASK 0xfffff
+#define CP_RB_RPTR__RB_RPTR__SHIFT 0x0
+#define CP_RB1_RPTR__RB_RPTR_MASK 0xfffff
+#define CP_RB1_RPTR__RB_RPTR__SHIFT 0x0
+#define CP_RB2_RPTR__RB_RPTR_MASK 0xfffff
+#define CP_RB2_RPTR__RB_RPTR__SHIFT 0x0
+#define CP_RB_WPTR_DELAY__PRE_WRITE_TIMER_MASK 0xfffffff
+#define CP_RB_WPTR_DELAY__PRE_WRITE_TIMER__SHIFT 0x0
+#define CP_RB_WPTR_DELAY__PRE_WRITE_LIMIT_MASK 0xf0000000
+#define CP_RB_WPTR_DELAY__PRE_WRITE_LIMIT__SHIFT 0x1c
+#define CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY_MASK 0xffff
+#define CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT 0x0
+#define CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT_MASK 0xffff0000
+#define CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT 0x10
+#define CP_CE_INIT_BASE_LO__INIT_BASE_LO_MASK 0xffffffe0
+#define CP_CE_INIT_BASE_LO__INIT_BASE_LO__SHIFT 0x5
+#define CP_CE_INIT_BASE_HI__INIT_BASE_HI_MASK 0xffff
+#define CP_CE_INIT_BASE_HI__INIT_BASE_HI__SHIFT 0x0
+#define CP_CE_INIT_BUFSZ__INIT_BUFSZ_MASK 0xfff
+#define CP_CE_INIT_BUFSZ__INIT_BUFSZ__SHIFT 0x0
+#define CP_CE_IB1_BASE_LO__IB1_BASE_LO_MASK 0xfffffffc
+#define CP_CE_IB1_BASE_LO__IB1_BASE_LO__SHIFT 0x2
+#define CP_CE_IB1_BASE_HI__IB1_BASE_HI_MASK 0xffff
+#define CP_CE_IB1_BASE_HI__IB1_BASE_HI__SHIFT 0x0
+#define CP_CE_IB1_BUFSZ__IB1_BUFSZ_MASK 0xfffff
+#define CP_CE_IB1_BUFSZ__IB1_BUFSZ__SHIFT 0x0
+#define CP_CE_IB2_BASE_LO__IB2_BASE_LO_MASK 0xfffffffc
+#define CP_CE_IB2_BASE_LO__IB2_BASE_LO__SHIFT 0x2
+#define CP_CE_IB2_BASE_HI__IB2_BASE_HI_MASK 0xffff
+#define CP_CE_IB2_BASE_HI__IB2_BASE_HI__SHIFT 0x0
+#define CP_CE_IB2_BUFSZ__IB2_BUFSZ_MASK 0xfffff
+#define CP_CE_IB2_BUFSZ__IB2_BUFSZ__SHIFT 0x0
+#define CP_IB1_BASE_LO__IB1_BASE_LO_MASK 0xfffffffc
+#define CP_IB1_BASE_LO__IB1_BASE_LO__SHIFT 0x2
+#define CP_IB1_BASE_HI__IB1_BASE_HI_MASK 0xffff
+#define CP_IB1_BASE_HI__IB1_BASE_HI__SHIFT 0x0
+#define CP_IB1_BUFSZ__IB1_BUFSZ_MASK 0xfffff
+#define CP_IB1_BUFSZ__IB1_BUFSZ__SHIFT 0x0
+#define CP_IB2_BASE_LO__IB2_BASE_LO_MASK 0xfffffffc
+#define CP_IB2_BASE_LO__IB2_BASE_LO__SHIFT 0x2
+#define CP_IB2_BASE_HI__IB2_BASE_HI_MASK 0xffff
+#define CP_IB2_BASE_HI__IB2_BASE_HI__SHIFT 0x0
+#define CP_IB2_BUFSZ__IB2_BUFSZ_MASK 0xfffff
+#define CP_IB2_BUFSZ__IB2_BUFSZ__SHIFT 0x0
+#define CP_ST_BASE_LO__ST_BASE_LO_MASK 0xfffffffc
+#define CP_ST_BASE_LO__ST_BASE_LO__SHIFT 0x2
+#define CP_ST_BASE_HI__ST_BASE_HI_MASK 0xffff
+#define CP_ST_BASE_HI__ST_BASE_HI__SHIFT 0x0
+#define CP_ST_BUFSZ__ST_BUFSZ_MASK 0xfffff
+#define CP_ST_BUFSZ__ST_BUFSZ__SHIFT 0x0
+#define CP_ROQ_THRESHOLDS__IB1_START_MASK 0xff
+#define CP_ROQ_THRESHOLDS__IB1_START__SHIFT 0x0
+#define CP_ROQ_THRESHOLDS__IB2_START_MASK 0xff00
+#define CP_ROQ_THRESHOLDS__IB2_START__SHIFT 0x8
+#define CP_MEQ_STQ_THRESHOLD__STQ_START_MASK 0xff
+#define CP_MEQ_STQ_THRESHOLD__STQ_START__SHIFT 0x0
+#define CP_ROQ1_THRESHOLDS__RB1_START_MASK 0xff
+#define CP_ROQ1_THRESHOLDS__RB1_START__SHIFT 0x0
+#define CP_ROQ1_THRESHOLDS__RB2_START_MASK 0xff00
+#define CP_ROQ1_THRESHOLDS__RB2_START__SHIFT 0x8
+#define CP_ROQ1_THRESHOLDS__R0_IB1_START_MASK 0xff0000
+#define CP_ROQ1_THRESHOLDS__R0_IB1_START__SHIFT 0x10
+#define CP_ROQ1_THRESHOLDS__R1_IB1_START_MASK 0xff000000
+#define CP_ROQ1_THRESHOLDS__R1_IB1_START__SHIFT 0x18
+#define CP_ROQ2_THRESHOLDS__R2_IB1_START_MASK 0xff
+#define CP_ROQ2_THRESHOLDS__R2_IB1_START__SHIFT 0x0
+#define CP_ROQ2_THRESHOLDS__R0_IB2_START_MASK 0xff00
+#define CP_ROQ2_THRESHOLDS__R0_IB2_START__SHIFT 0x8
+#define CP_ROQ2_THRESHOLDS__R1_IB2_START_MASK 0xff0000
+#define CP_ROQ2_THRESHOLDS__R1_IB2_START__SHIFT 0x10
+#define CP_ROQ2_THRESHOLDS__R2_IB2_START_MASK 0xff000000
+#define CP_ROQ2_THRESHOLDS__R2_IB2_START__SHIFT 0x18
+#define CP_STQ_THRESHOLDS__STQ0_START_MASK 0xff
+#define CP_STQ_THRESHOLDS__STQ0_START__SHIFT 0x0
+#define CP_STQ_THRESHOLDS__STQ1_START_MASK 0xff00
+#define CP_STQ_THRESHOLDS__STQ1_START__SHIFT 0x8
+#define CP_STQ_THRESHOLDS__STQ2_START_MASK 0xff0000
+#define CP_STQ_THRESHOLDS__STQ2_START__SHIFT 0x10
+#define CP_QUEUE_THRESHOLDS__ROQ_IB1_START_MASK 0x3f
+#define CP_QUEUE_THRESHOLDS__ROQ_IB1_START__SHIFT 0x0
+#define CP_QUEUE_THRESHOLDS__ROQ_IB2_START_MASK 0x3f00
+#define CP_QUEUE_THRESHOLDS__ROQ_IB2_START__SHIFT 0x8
+#define CP_MEQ_THRESHOLDS__MEQ1_START_MASK 0xff
+#define CP_MEQ_THRESHOLDS__MEQ1_START__SHIFT 0x0
+#define CP_MEQ_THRESHOLDS__MEQ2_START_MASK 0xff00
+#define CP_MEQ_THRESHOLDS__MEQ2_START__SHIFT 0x8
+#define CP_ROQ_AVAIL__ROQ_CNT_RING_MASK 0x7ff
+#define CP_ROQ_AVAIL__ROQ_CNT_RING__SHIFT 0x0
+#define CP_ROQ_AVAIL__ROQ_CNT_IB1_MASK 0x7ff0000
+#define CP_ROQ_AVAIL__ROQ_CNT_IB1__SHIFT 0x10
+#define CP_STQ_AVAIL__STQ_CNT_MASK 0x1ff
+#define CP_STQ_AVAIL__STQ_CNT__SHIFT 0x0
+#define CP_ROQ2_AVAIL__ROQ_CNT_IB2_MASK 0x7ff
+#define CP_ROQ2_AVAIL__ROQ_CNT_IB2__SHIFT 0x0
+#define CP_MEQ_AVAIL__MEQ_CNT_MASK 0x3ff
+#define CP_MEQ_AVAIL__MEQ_CNT__SHIFT 0x0
+#define CP_CMD_INDEX__CMD_INDEX_MASK 0x7ff
+#define CP_CMD_INDEX__CMD_INDEX__SHIFT 0x0
+#define CP_CMD_INDEX__CMD_ME_SEL_MASK 0x3000
+#define CP_CMD_INDEX__CMD_ME_SEL__SHIFT 0xc
+#define CP_CMD_INDEX__CMD_QUEUE_SEL_MASK 0x70000
+#define CP_CMD_INDEX__CMD_QUEUE_SEL__SHIFT 0x10
+#define CP_CMD_DATA__CMD_DATA_MASK 0xffffffff
+#define CP_CMD_DATA__CMD_DATA__SHIFT 0x0
+#define CP_ROQ_RB_STAT__ROQ_RPTR_PRIMARY_MASK 0x3ff
+#define CP_ROQ_RB_STAT__ROQ_RPTR_PRIMARY__SHIFT 0x0
+#define CP_ROQ_RB_STAT__ROQ_WPTR_PRIMARY_MASK 0x3ff0000
+#define CP_ROQ_RB_STAT__ROQ_WPTR_PRIMARY__SHIFT 0x10
+#define CP_ROQ_IB1_STAT__ROQ_RPTR_INDIRECT1_MASK 0x3ff
+#define CP_ROQ_IB1_STAT__ROQ_RPTR_INDIRECT1__SHIFT 0x0
+#define CP_ROQ_IB1_STAT__ROQ_WPTR_INDIRECT1_MASK 0x3ff0000
+#define CP_ROQ_IB1_STAT__ROQ_WPTR_INDIRECT1__SHIFT 0x10
+#define CP_ROQ_IB2_STAT__ROQ_RPTR_INDIRECT2_MASK 0x3ff
+#define CP_ROQ_IB2_STAT__ROQ_RPTR_INDIRECT2__SHIFT 0x0
+#define CP_ROQ_IB2_STAT__ROQ_WPTR_INDIRECT2_MASK 0x3ff0000
+#define CP_ROQ_IB2_STAT__ROQ_WPTR_INDIRECT2__SHIFT 0x10
+#define CP_STQ_STAT__STQ_RPTR_MASK 0x3ff
+#define CP_STQ_STAT__STQ_RPTR__SHIFT 0x0
+#define CP_STQ_WR_STAT__STQ_WPTR_MASK 0x3ff
+#define CP_STQ_WR_STAT__STQ_WPTR__SHIFT 0x0
+#define CP_MEQ_STAT__MEQ_RPTR_MASK 0x3ff
+#define CP_MEQ_STAT__MEQ_RPTR__SHIFT 0x0
+#define CP_MEQ_STAT__MEQ_WPTR_MASK 0x3ff0000
+#define CP_MEQ_STAT__MEQ_WPTR__SHIFT 0x10
+#define CP_CEQ1_AVAIL__CEQ_CNT_RING_MASK 0x7ff
+#define CP_CEQ1_AVAIL__CEQ_CNT_RING__SHIFT 0x0
+#define CP_CEQ1_AVAIL__CEQ_CNT_IB1_MASK 0x7ff0000
+#define CP_CEQ1_AVAIL__CEQ_CNT_IB1__SHIFT 0x10
+#define CP_CEQ2_AVAIL__CEQ_CNT_IB2_MASK 0x7ff
+#define CP_CEQ2_AVAIL__CEQ_CNT_IB2__SHIFT 0x0
+#define CP_CE_ROQ_RB_STAT__CEQ_RPTR_PRIMARY_MASK 0x3ff
+#define CP_CE_ROQ_RB_STAT__CEQ_RPTR_PRIMARY__SHIFT 0x0
+#define CP_CE_ROQ_RB_STAT__CEQ_WPTR_PRIMARY_MASK 0x3ff0000
+#define CP_CE_ROQ_RB_STAT__CEQ_WPTR_PRIMARY__SHIFT 0x10
+#define CP_CE_ROQ_IB1_STAT__CEQ_RPTR_INDIRECT1_MASK 0x3ff
+#define CP_CE_ROQ_IB1_STAT__CEQ_RPTR_INDIRECT1__SHIFT 0x0
+#define CP_CE_ROQ_IB1_STAT__CEQ_WPTR_INDIRECT1_MASK 0x3ff0000
+#define CP_CE_ROQ_IB1_STAT__CEQ_WPTR_INDIRECT1__SHIFT 0x10
+#define CP_CE_ROQ_IB2_STAT__CEQ_RPTR_INDIRECT2_MASK 0x3ff
+#define CP_CE_ROQ_IB2_STAT__CEQ_RPTR_INDIRECT2__SHIFT 0x0
+#define CP_CE_ROQ_IB2_STAT__CEQ_WPTR_INDIRECT2_MASK 0x3ff0000
+#define CP_CE_ROQ_IB2_STAT__CEQ_WPTR_INDIRECT2__SHIFT 0x10
+#define CP_INT_STAT_DEBUG__CP_VM_DOORBELL_WR_INT_ASSERTED_MASK 0x800
+#define CP_INT_STAT_DEBUG__CP_VM_DOORBELL_WR_INT_ASSERTED__SHIFT 0xb
+#define CP_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x4000
+#define CP_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
+#define CP_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x20000
+#define CP_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
+#define CP_INT_STAT_DEBUG__CMP_BUSY_INT_ASSERTED_MASK 0x40000
+#define CP_INT_STAT_DEBUG__CMP_BUSY_INT_ASSERTED__SHIFT 0x12
+#define CP_INT_STAT_DEBUG__CNTX_BUSY_INT_ASSERTED_MASK 0x80000
+#define CP_INT_STAT_DEBUG__CNTX_BUSY_INT_ASSERTED__SHIFT 0x13
+#define CP_INT_STAT_DEBUG__CNTX_EMPTY_INT_ASSERTED_MASK 0x100000
+#define CP_INT_STAT_DEBUG__CNTX_EMPTY_INT_ASSERTED__SHIFT 0x14
+#define CP_INT_STAT_DEBUG__GFX_IDLE_INT_ASSERTED_MASK 0x200000
+#define CP_INT_STAT_DEBUG__GFX_IDLE_INT_ASSERTED__SHIFT 0x15
+#define CP_INT_STAT_DEBUG__PRIV_INSTR_INT_ASSERTED_MASK 0x400000
+#define CP_INT_STAT_DEBUG__PRIV_INSTR_INT_ASSERTED__SHIFT 0x16
+#define CP_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x800000
+#define CP_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
+#define CP_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x1000000
+#define CP_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
+#define CP_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x4000000
+#define CP_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
+#define CP_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x8000000
+#define CP_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
+#define CP_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000
+#define CP_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
+#define CP_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000
+#define CP_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
+#define CP_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000
+#define CP_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
+#define CP_PERFMON_CNTL__PERFMON_STATE_MASK 0xf
+#define CP_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x0
+#define CP_PERFMON_CNTL__SPM_PERFMON_STATE_MASK 0xf0
+#define CP_PERFMON_CNTL__SPM_PERFMON_STATE__SHIFT 0x4
+#define CP_PERFMON_CNTL__PERFMON_ENABLE_MODE_MASK 0x300
+#define CP_PERFMON_CNTL__PERFMON_ENABLE_MODE__SHIFT 0x8
+#define CP_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x400
+#define CP_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0xa
+#define CP_PERFMON_CNTX_CNTL__PERFMON_ENABLE_MASK 0x80000000
+#define CP_PERFMON_CNTX_CNTL__PERFMON_ENABLE__SHIFT 0x1f
+#define CP_RINGID__RINGID_MASK 0x3
+#define CP_RINGID__RINGID__SHIFT 0x0
+#define CP_PIPEID__PIPE_ID_MASK 0x3
+#define CP_PIPEID__PIPE_ID__SHIFT 0x0
+#define CP_VMID__VMID_MASK 0xf
+#define CP_VMID__VMID__SHIFT 0x0
+#define CP_HPD_ROQ_OFFSETS__IQ_OFFSET_MASK 0x7
+#define CP_HPD_ROQ_OFFSETS__IQ_OFFSET__SHIFT 0x0
+#define CP_HPD_ROQ_OFFSETS__PQ_OFFSET_MASK 0x3f00
+#define CP_HPD_ROQ_OFFSETS__PQ_OFFSET__SHIFT 0x8
+#define CP_HPD_ROQ_OFFSETS__IB_OFFSET_MASK 0x3f0000
+#define CP_HPD_ROQ_OFFSETS__IB_OFFSET__SHIFT 0x10
+#define CP_HPD_STATUS0__QUEUE_STATE_MASK 0x1f
+#define CP_HPD_STATUS0__QUEUE_STATE__SHIFT 0x0
+#define CP_HPD_STATUS0__MAPPED_QUEUE_MASK 0xe0
+#define CP_HPD_STATUS0__MAPPED_QUEUE__SHIFT 0x5
+#define CP_HPD_STATUS0__QUEUE_AVAILABLE_MASK 0xff00
+#define CP_HPD_STATUS0__QUEUE_AVAILABLE__SHIFT 0x8
+#define CP_MQD_BASE_ADDR__BASE_ADDR_MASK 0xfffffffc
+#define CP_MQD_BASE_ADDR__BASE_ADDR__SHIFT 0x2
+#define CP_MQD_BASE_ADDR_HI__BASE_ADDR_HI_MASK 0xffff
+#define CP_MQD_BASE_ADDR_HI__BASE_ADDR_HI__SHIFT 0x0
+#define CP_HQD_ACTIVE__ACTIVE_MASK 0x1
+#define CP_HQD_ACTIVE__ACTIVE__SHIFT 0x0
+#define CP_HQD_ACTIVE__BUSY_GATE_MASK 0x2
+#define CP_HQD_ACTIVE__BUSY_GATE__SHIFT 0x1
+#define CP_HQD_VMID__VMID_MASK 0xf
+#define CP_HQD_VMID__VMID__SHIFT 0x0
+#define CP_HQD_VMID__IB_VMID_MASK 0xf00
+#define CP_HQD_VMID__IB_VMID__SHIFT 0x8
+#define CP_HQD_VMID__VQID_MASK 0x3ff0000
+#define CP_HQD_VMID__VQID__SHIFT 0x10
+#define CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK 0x1
+#define CP_HQD_PERSISTENT_STATE__PRELOAD_REQ__SHIFT 0x0
+#define CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE_MASK 0x3ff00
+#define CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT 0x8
+#define CP_HQD_PERSISTENT_STATE__RESTORE_ACTIVE_MASK 0x10000000
+#define CP_HQD_PERSISTENT_STATE__RESTORE_ACTIVE__SHIFT 0x1c
+#define CP_HQD_PERSISTENT_STATE__RELAUNCH_WAVES_MASK 0x20000000
+#define CP_HQD_PERSISTENT_STATE__RELAUNCH_WAVES__SHIFT 0x1d
+#define CP_HQD_PERSISTENT_STATE__QSWITCH_MODE_MASK 0x40000000
+#define CP_HQD_PERSISTENT_STATE__QSWITCH_MODE__SHIFT 0x1e
+#define CP_HQD_PERSISTENT_STATE__DISP_ACTIVE_MASK 0x80000000
+#define CP_HQD_PERSISTENT_STATE__DISP_ACTIVE__SHIFT 0x1f
+#define CP_HQD_PIPE_PRIORITY__PIPE_PRIORITY_MASK 0x3
+#define CP_HQD_PIPE_PRIORITY__PIPE_PRIORITY__SHIFT 0x0
+#define CP_HQD_QUEUE_PRIORITY__PRIORITY_LEVEL_MASK 0xf
+#define CP_HQD_QUEUE_PRIORITY__PRIORITY_LEVEL__SHIFT 0x0
+#define CP_HQD_QUANTUM__QUANTUM_EN_MASK 0x1
+#define CP_HQD_QUANTUM__QUANTUM_EN__SHIFT 0x0
+#define CP_HQD_QUANTUM__QUANTUM_SCALE_MASK 0x10
+#define CP_HQD_QUANTUM__QUANTUM_SCALE__SHIFT 0x4
+#define CP_HQD_QUANTUM__QUANTUM_DURATION_MASK 0x3f00
+#define CP_HQD_QUANTUM__QUANTUM_DURATION__SHIFT 0x8
+#define CP_HQD_QUANTUM__QUANTUM_ACTIVE_MASK 0x80000000
+#define CP_HQD_QUANTUM__QUANTUM_ACTIVE__SHIFT 0x1f
+#define CP_HQD_PQ_BASE__ADDR_MASK 0xffffffff
+#define CP_HQD_PQ_BASE__ADDR__SHIFT 0x0
+#define CP_HQD_PQ_BASE_HI__ADDR_HI_MASK 0xff
+#define CP_HQD_PQ_BASE_HI__ADDR_HI__SHIFT 0x0
+#define CP_HQD_PQ_RPTR__CONSUMED_OFFSET_MASK 0xffffffff
+#define CP_HQD_PQ_RPTR__CONSUMED_OFFSET__SHIFT 0x0
+#define CP_HQD_PQ_RPTR_REPORT_ADDR__RPTR_REPORT_ADDR_MASK 0xfffffffc
+#define CP_HQD_PQ_RPTR_REPORT_ADDR__RPTR_REPORT_ADDR__SHIFT 0x2
+#define CP_HQD_PQ_RPTR_REPORT_ADDR_HI__RPTR_REPORT_ADDR_HI_MASK 0xffff
+#define CP_HQD_PQ_RPTR_REPORT_ADDR_HI__RPTR_REPORT_ADDR_HI__SHIFT 0x0
+#define CP_HQD_PQ_WPTR_POLL_ADDR__WPTR_ADDR_MASK 0xfffffffc
+#define CP_HQD_PQ_WPTR_POLL_ADDR__WPTR_ADDR__SHIFT 0x2
+#define CP_HQD_PQ_WPTR_POLL_ADDR_HI__WPTR_ADDR_HI_MASK 0xffff
+#define CP_HQD_PQ_WPTR_POLL_ADDR_HI__WPTR_ADDR_HI__SHIFT 0x0
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_MODE_MASK 0x1
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_MODE__SHIFT 0x0
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_BIF_DROP_MASK 0x2
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_BIF_DROP__SHIFT 0x1
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK 0x7ffffc
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT 0x2
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_CARRY_BITS_MASK 0x3800000
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_CARRY_BITS__SHIFT 0x17
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE_MASK 0x10000000
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE__SHIFT 0x1c
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SCHD_HIT_MASK 0x20000000
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SCHD_HIT__SHIFT 0x1d
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK 0x40000000
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN__SHIFT 0x1e
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT_MASK 0x80000000
+#define CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT__SHIFT 0x1f
+#define CP_HQD_PQ_WPTR__OFFSET_MASK 0xffffffff
+#define CP_HQD_PQ_WPTR__OFFSET__SHIFT 0x0
+#define CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK 0x3f
+#define CP_HQD_PQ_CONTROL__QUEUE_SIZE__SHIFT 0x0
+#define CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE_MASK 0x3f00
+#define CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT 0x8
+#define CP_HQD_PQ_CONTROL__MTYPE_MASK 0x18000
+#define CP_HQD_PQ_CONTROL__MTYPE__SHIFT 0xf
+#define CP_HQD_PQ_CONTROL__ENDIAN_SWAP_MASK 0x60000
+#define CP_HQD_PQ_CONTROL__ENDIAN_SWAP__SHIFT 0x11
+#define CP_HQD_PQ_CONTROL__MIN_AVAIL_SIZE_MASK 0x300000
+#define CP_HQD_PQ_CONTROL__MIN_AVAIL_SIZE__SHIFT 0x14
+#define CP_HQD_PQ_CONTROL__PQ_ATC_MASK 0x800000
+#define CP_HQD_PQ_CONTROL__PQ_ATC__SHIFT 0x17
+#define CP_HQD_PQ_CONTROL__CACHE_POLICY_MASK 0x1000000
+#define CP_HQD_PQ_CONTROL__CACHE_POLICY__SHIFT 0x18
+#define CP_HQD_PQ_CONTROL__SLOT_BASED_WPTR_MASK 0x6000000
+#define CP_HQD_PQ_CONTROL__SLOT_BASED_WPTR__SHIFT 0x19
+#define CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK 0x8000000
+#define CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR__SHIFT 0x1b
+#define CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK 0x10000000
+#define CP_HQD_PQ_CONTROL__UNORD_DISPATCH__SHIFT 0x1c
+#define CP_HQD_PQ_CONTROL__ROQ_PQ_IB_FLIP_MASK 0x20000000
+#define CP_HQD_PQ_CONTROL__ROQ_PQ_IB_FLIP__SHIFT 0x1d
+#define CP_HQD_PQ_CONTROL__PRIV_STATE_MASK 0x40000000
+#define CP_HQD_PQ_CONTROL__PRIV_STATE__SHIFT 0x1e
+#define CP_HQD_PQ_CONTROL__KMD_QUEUE_MASK 0x80000000
+#define CP_HQD_PQ_CONTROL__KMD_QUEUE__SHIFT 0x1f
+#define CP_HQD_IB_BASE_ADDR__IB_BASE_ADDR_MASK 0xfffffffc
+#define CP_HQD_IB_BASE_ADDR__IB_BASE_ADDR__SHIFT 0x2
+#define CP_HQD_IB_BASE_ADDR_HI__IB_BASE_ADDR_HI_MASK 0xffff
+#define CP_HQD_IB_BASE_ADDR_HI__IB_BASE_ADDR_HI__SHIFT 0x0
+#define CP_HQD_IB_RPTR__CONSUMED_OFFSET_MASK 0xfffff
+#define CP_HQD_IB_RPTR__CONSUMED_OFFSET__SHIFT 0x0
+#define CP_HQD_IB_CONTROL__IB_SIZE_MASK 0xfffff
+#define CP_HQD_IB_CONTROL__IB_SIZE__SHIFT 0x0
+#define CP_HQD_IB_CONTROL__MIN_IB_AVAIL_SIZE_MASK 0x300000
+#define CP_HQD_IB_CONTROL__MIN_IB_AVAIL_SIZE__SHIFT 0x14
+#define CP_HQD_IB_CONTROL__IB_ATC_MASK 0x800000
+#define CP_HQD_IB_CONTROL__IB_ATC__SHIFT 0x17
+#define CP_HQD_IB_CONTROL__IB_CACHE_POLICY_MASK 0x1000000
+#define CP_HQD_IB_CONTROL__IB_CACHE_POLICY__SHIFT 0x18
+#define CP_HQD_IB_CONTROL__MTYPE_MASK 0x18000000
+#define CP_HQD_IB_CONTROL__MTYPE__SHIFT 0x1b
+#define CP_HQD_IB_CONTROL__PROCESSING_IB_MASK 0x80000000
+#define CP_HQD_IB_CONTROL__PROCESSING_IB__SHIFT 0x1f
+#define CP_HQD_IQ_TIMER__WAIT_TIME_MASK 0xff
+#define CP_HQD_IQ_TIMER__WAIT_TIME__SHIFT 0x0
+#define CP_HQD_IQ_TIMER__RETRY_TYPE_MASK 0x700
+#define CP_HQD_IQ_TIMER__RETRY_TYPE__SHIFT 0x8
+#define CP_HQD_IQ_TIMER__IMMEDIATE_EXPIRE_MASK 0x800
+#define CP_HQD_IQ_TIMER__IMMEDIATE_EXPIRE__SHIFT 0xb
+#define CP_HQD_IQ_TIMER__INTERRUPT_TYPE_MASK 0x3000
+#define CP_HQD_IQ_TIMER__INTERRUPT_TYPE__SHIFT 0xc
+#define CP_HQD_IQ_TIMER__CLOCK_COUNT_MASK 0xc000
+#define CP_HQD_IQ_TIMER__CLOCK_COUNT__SHIFT 0xe
+#define CP_HQD_IQ_TIMER__INTERRUPT_SIZE_MASK 0x3f0000
+#define CP_HQD_IQ_TIMER__INTERRUPT_SIZE__SHIFT 0x10
+#define CP_HQD_IQ_TIMER__QUANTUM_TIMER_MASK 0x400000
+#define CP_HQD_IQ_TIMER__QUANTUM_TIMER__SHIFT 0x16
+#define CP_HQD_IQ_TIMER__IQ_ATC_MASK 0x800000
+#define CP_HQD_IQ_TIMER__IQ_ATC__SHIFT 0x17
+#define CP_HQD_IQ_TIMER__CACHE_POLICY_MASK 0x1000000
+#define CP_HQD_IQ_TIMER__CACHE_POLICY__SHIFT 0x18
+#define CP_HQD_IQ_TIMER__MTYPE_MASK 0x18000000
+#define CP_HQD_IQ_TIMER__MTYPE__SHIFT 0x1b
+#define CP_HQD_IQ_TIMER__PROCESS_IQ_EN_MASK 0x20000000
+#define CP_HQD_IQ_TIMER__PROCESS_IQ_EN__SHIFT 0x1d
+#define CP_HQD_IQ_TIMER__PROCESSING_IQ_MASK 0x40000000
+#define CP_HQD_IQ_TIMER__PROCESSING_IQ__SHIFT 0x1e
+#define CP_HQD_IQ_TIMER__ACTIVE_MASK 0x80000000
+#define CP_HQD_IQ_TIMER__ACTIVE__SHIFT 0x1f
+#define CP_HQD_IQ_RPTR__OFFSET_MASK 0x3f
+#define CP_HQD_IQ_RPTR__OFFSET__SHIFT 0x0
+#define CP_HQD_DEQUEUE_REQUEST__DEQUEUE_REQ_MASK 0x7
+#define CP_HQD_DEQUEUE_REQUEST__DEQUEUE_REQ__SHIFT 0x0
+#define CP_HQD_DEQUEUE_REQUEST__IQ_REQ_PEND_MASK 0x10
+#define CP_HQD_DEQUEUE_REQUEST__IQ_REQ_PEND__SHIFT 0x4
+#define CP_HQD_DEQUEUE_REQUEST__DEQUEUE_INT_MASK 0x100
+#define CP_HQD_DEQUEUE_REQUEST__DEQUEUE_INT__SHIFT 0x8
+#define CP_HQD_DEQUEUE_REQUEST__IQ_REQ_PEND_EN_MASK 0x200
+#define CP_HQD_DEQUEUE_REQUEST__IQ_REQ_PEND_EN__SHIFT 0x9
+#define CP_HQD_DEQUEUE_REQUEST__DEQUEUE_REQ_EN_MASK 0x400
+#define CP_HQD_DEQUEUE_REQUEST__DEQUEUE_REQ_EN__SHIFT 0xa
+#define CP_HQD_DMA_OFFLOAD__DMA_OFFLOAD_MASK 0x1
+#define CP_HQD_DMA_OFFLOAD__DMA_OFFLOAD__SHIFT 0x0
+#define CP_HQD_OFFLOAD__DMA_OFFLOAD_MASK 0x1
+#define CP_HQD_OFFLOAD__DMA_OFFLOAD__SHIFT 0x0
+#define CP_HQD_OFFLOAD__DMA_OFFLOAD_EN_MASK 0x2
+#define CP_HQD_OFFLOAD__DMA_OFFLOAD_EN__SHIFT 0x1
+#define CP_HQD_OFFLOAD__EOP_OFFLOAD_MASK 0x10
+#define CP_HQD_OFFLOAD__EOP_OFFLOAD__SHIFT 0x4
+#define CP_HQD_OFFLOAD__EOP_OFFLOAD_EN_MASK 0x20
+#define CP_HQD_OFFLOAD__EOP_OFFLOAD_EN__SHIFT 0x5
+#define CP_HQD_SEMA_CMD__RETRY_MASK 0x1
+#define CP_HQD_SEMA_CMD__RETRY__SHIFT 0x0
+#define CP_HQD_SEMA_CMD__RESULT_MASK 0x6
+#define CP_HQD_SEMA_CMD__RESULT__SHIFT 0x1
+#define CP_HQD_MSG_TYPE__ACTION_MASK 0x7
+#define CP_HQD_MSG_TYPE__ACTION__SHIFT 0x0
+#define CP_HQD_MSG_TYPE__SAVE_STATE_MASK 0x70
+#define CP_HQD_MSG_TYPE__SAVE_STATE__SHIFT 0x4
+#define CP_HQD_ATOMIC0_PREOP_LO__ATOMIC0_PREOP_LO_MASK 0xffffffff
+#define CP_HQD_ATOMIC0_PREOP_LO__ATOMIC0_PREOP_LO__SHIFT 0x0
+#define CP_HQD_ATOMIC0_PREOP_HI__ATOMIC0_PREOP_HI_MASK 0xffffffff
+#define CP_HQD_ATOMIC0_PREOP_HI__ATOMIC0_PREOP_HI__SHIFT 0x0
+#define CP_HQD_ATOMIC1_PREOP_LO__ATOMIC1_PREOP_LO_MASK 0xffffffff
+#define CP_HQD_ATOMIC1_PREOP_LO__ATOMIC1_PREOP_LO__SHIFT 0x0
+#define CP_HQD_ATOMIC1_PREOP_HI__ATOMIC1_PREOP_HI_MASK 0xffffffff
+#define CP_HQD_ATOMIC1_PREOP_HI__ATOMIC1_PREOP_HI__SHIFT 0x0
+#define CP_HQD_HQ_SCHEDULER0__SCHEDULER_MASK 0xffffffff
+#define CP_HQD_HQ_SCHEDULER0__SCHEDULER__SHIFT 0x0
+#define CP_HQD_HQ_STATUS0__DEQUEUE_STATUS_MASK 0x3
+#define CP_HQD_HQ_STATUS0__DEQUEUE_STATUS__SHIFT 0x0
+#define CP_HQD_HQ_STATUS0__DEQUEUE_RETRY_CNT_MASK 0xc
+#define CP_HQD_HQ_STATUS0__DEQUEUE_RETRY_CNT__SHIFT 0x2
+#define CP_HQD_HQ_STATUS0__RSV_6_4_MASK 0x70
+#define CP_HQD_HQ_STATUS0__RSV_6_4__SHIFT 0x4
+#define CP_HQD_HQ_STATUS0__SCRATCH_RAM_INIT_MASK 0x80
+#define CP_HQD_HQ_STATUS0__SCRATCH_RAM_INIT__SHIFT 0x7
+#define CP_HQD_HQ_STATUS0__TCL2_DIRTY_MASK 0x100
+#define CP_HQD_HQ_STATUS0__TCL2_DIRTY__SHIFT 0x8
+#define CP_HQD_HQ_STATUS0__PG_ACTIVATED_MASK 0x200
+#define CP_HQD_HQ_STATUS0__PG_ACTIVATED__SHIFT 0x9
+#define CP_HQD_HQ_STATUS0__RSVR_31_10_MASK 0xfffffc00
+#define CP_HQD_HQ_STATUS0__RSVR_31_10__SHIFT 0xa
+#define CP_HQD_HQ_SCHEDULER1__SCHEDULER_MASK 0xffffffff
+#define CP_HQD_HQ_SCHEDULER1__SCHEDULER__SHIFT 0x0
+#define CP_HQD_HQ_CONTROL0__CONTROL_MASK 0xffffffff
+#define CP_HQD_HQ_CONTROL0__CONTROL__SHIFT 0x0
+#define CP_MQD_CONTROL__VMID_MASK 0xf
+#define CP_MQD_CONTROL__VMID__SHIFT 0x0
+#define CP_MQD_CONTROL__PROCESSING_MQD_MASK 0x1000
+#define CP_MQD_CONTROL__PROCESSING_MQD__SHIFT 0xc
+#define CP_MQD_CONTROL__PROCESSING_MQD_EN_MASK 0x2000
+#define CP_MQD_CONTROL__PROCESSING_MQD_EN__SHIFT 0xd
+#define CP_MQD_CONTROL__MQD_ATC_MASK 0x800000
+#define CP_MQD_CONTROL__MQD_ATC__SHIFT 0x17
+#define CP_MQD_CONTROL__CACHE_POLICY_MASK 0x1000000
+#define CP_MQD_CONTROL__CACHE_POLICY__SHIFT 0x18
+#define CP_MQD_CONTROL__MTYPE_MASK 0x18000000
+#define CP_MQD_CONTROL__MTYPE__SHIFT 0x1b
+#define CP_HQD_HQ_STATUS1__STATUS_MASK 0xffffffff
+#define CP_HQD_HQ_STATUS1__STATUS__SHIFT 0x0
+#define CP_HQD_HQ_CONTROL1__CONTROL_MASK 0xffffffff
+#define CP_HQD_HQ_CONTROL1__CONTROL__SHIFT 0x0
+#define CP_HQD_EOP_BASE_ADDR__BASE_ADDR_MASK 0xffffffff
+#define CP_HQD_EOP_BASE_ADDR__BASE_ADDR__SHIFT 0x0
+#define CP_HQD_EOP_BASE_ADDR_HI__BASE_ADDR_HI_MASK 0xff
+#define CP_HQD_EOP_BASE_ADDR_HI__BASE_ADDR_HI__SHIFT 0x0
+#define CP_HQD_EOP_CONTROL__EOP_SIZE_MASK 0x3f
+#define CP_HQD_EOP_CONTROL__EOP_SIZE__SHIFT 0x0
+#define CP_HQD_EOP_CONTROL__PROCESSING_EOP_MASK 0x100
+#define CP_HQD_EOP_CONTROL__PROCESSING_EOP__SHIFT 0x8
+#define CP_HQD_EOP_CONTROL__PROCESS_EOP_EN_MASK 0x1000
+#define CP_HQD_EOP_CONTROL__PROCESS_EOP_EN__SHIFT 0xc
+#define CP_HQD_EOP_CONTROL__PROCESSING_EOPIB_MASK 0x2000
+#define CP_HQD_EOP_CONTROL__PROCESSING_EOPIB__SHIFT 0xd
+#define CP_HQD_EOP_CONTROL__PROCESS_EOPIB_EN_MASK 0x4000
+#define CP_HQD_EOP_CONTROL__PROCESS_EOPIB_EN__SHIFT 0xe
+#define CP_HQD_EOP_CONTROL__MTYPE_MASK 0x18000
+#define CP_HQD_EOP_CONTROL__MTYPE__SHIFT 0xf
+#define CP_HQD_EOP_CONTROL__EOP_ATC_MASK 0x800000
+#define CP_HQD_EOP_CONTROL__EOP_ATC__SHIFT 0x17
+#define CP_HQD_EOP_CONTROL__CACHE_POLICY_MASK 0x1000000
+#define CP_HQD_EOP_CONTROL__CACHE_POLICY__SHIFT 0x18
+#define CP_HQD_EOP_CONTROL__SIG_SEM_RESULT_MASK 0x60000000
+#define CP_HQD_EOP_CONTROL__SIG_SEM_RESULT__SHIFT 0x1d
+#define CP_HQD_EOP_CONTROL__PEND_SIG_SEM_MASK 0x80000000
+#define CP_HQD_EOP_CONTROL__PEND_SIG_SEM__SHIFT 0x1f
+#define CP_HQD_EOP_RPTR__RPTR_MASK 0x1fff
+#define CP_HQD_EOP_RPTR__RPTR__SHIFT 0x0
+#define CP_HQD_EOP_RPTR__RPTR_EQ_CSMD_WPTR_MASK 0x40000000
+#define CP_HQD_EOP_RPTR__RPTR_EQ_CSMD_WPTR__SHIFT 0x1e
+#define CP_HQD_EOP_RPTR__INIT_FETCHER_MASK 0x80000000
+#define CP_HQD_EOP_RPTR__INIT_FETCHER__SHIFT 0x1f
+#define CP_HQD_EOP_WPTR__WPTR_MASK 0x1fff
+#define CP_HQD_EOP_WPTR__WPTR__SHIFT 0x0
+#define CP_HQD_EOP_WPTR__EOP_AVAIL_MASK 0x1fff0000
+#define CP_HQD_EOP_WPTR__EOP_AVAIL__SHIFT 0x10
+#define CP_HQD_EOP_EVENTS__EVENT_COUNT_MASK 0xfff
+#define CP_HQD_EOP_EVENTS__EVENT_COUNT__SHIFT 0x0
+#define CP_HQD_EOP_EVENTS__CS_PARTIAL_FLUSH_PEND_MASK 0x10000
+#define CP_HQD_EOP_EVENTS__CS_PARTIAL_FLUSH_PEND__SHIFT 0x10
+#define CP_HQD_CTX_SAVE_BASE_ADDR_LO__ADDR_MASK 0xfffff000
+#define CP_HQD_CTX_SAVE_BASE_ADDR_LO__ADDR__SHIFT 0xc
+#define CP_HQD_CTX_SAVE_BASE_ADDR_HI__ADDR_HI_MASK 0xffff
+#define CP_HQD_CTX_SAVE_BASE_ADDR_HI__ADDR_HI__SHIFT 0x0
+#define CP_HQD_CTX_SAVE_CONTROL__ATC_MASK 0x1
+#define CP_HQD_CTX_SAVE_CONTROL__ATC__SHIFT 0x0
+#define CP_HQD_CTX_SAVE_CONTROL__MTYPE_MASK 0x6
+#define CP_HQD_CTX_SAVE_CONTROL__MTYPE__SHIFT 0x1
+#define CP_HQD_CTX_SAVE_CONTROL__POLICY_MASK 0x8
+#define CP_HQD_CTX_SAVE_CONTROL__POLICY__SHIFT 0x3
+#define CP_HQD_CNTL_STACK_OFFSET__OFFSET_MASK 0x7ffc
+#define CP_HQD_CNTL_STACK_OFFSET__OFFSET__SHIFT 0x2
+#define CP_HQD_CNTL_STACK_SIZE__SIZE_MASK 0x7000
+#define CP_HQD_CNTL_STACK_SIZE__SIZE__SHIFT 0xc
+#define CP_HQD_WG_STATE_OFFSET__OFFSET_MASK 0x1fffffc
+#define CP_HQD_WG_STATE_OFFSET__OFFSET__SHIFT 0x2
+#define CP_HQD_CTX_SAVE_SIZE__SIZE_MASK 0x1fff000
+#define CP_HQD_CTX_SAVE_SIZE__SIZE__SHIFT 0xc
+#define CP_HQD_GDS_RESOURCE_STATE__OA_REQUIRED_MASK 0x1
+#define CP_HQD_GDS_RESOURCE_STATE__OA_REQUIRED__SHIFT 0x0
+#define CP_HQD_GDS_RESOURCE_STATE__OA_ACQUIRED_MASK 0x2
+#define CP_HQD_GDS_RESOURCE_STATE__OA_ACQUIRED__SHIFT 0x1
+#define CP_HQD_GDS_RESOURCE_STATE__GWS_SIZE_MASK 0x3f0
+#define CP_HQD_GDS_RESOURCE_STATE__GWS_SIZE__SHIFT 0x4
+#define CP_HQD_GDS_RESOURCE_STATE__GWS_PNTR_MASK 0x3f000
+#define CP_HQD_GDS_RESOURCE_STATE__GWS_PNTR__SHIFT 0xc
+#define CP_HQD_ERROR__EDC_ERROR_ID_MASK 0xf
+#define CP_HQD_ERROR__EDC_ERROR_ID__SHIFT 0x0
+#define CP_HQD_ERROR__SUA_ERROR_MASK 0x10
+#define CP_HQD_ERROR__SUA_ERROR__SHIFT 0x4
+#define CP_HQD_EOP_WPTR_MEM__WPTR_MASK 0x1fff
+#define CP_HQD_EOP_WPTR_MEM__WPTR__SHIFT 0x0
+#define CP_HQD_EOP_DONES__DONE_COUNT_MASK 0xffffffff
+#define CP_HQD_EOP_DONES__DONE_COUNT__SHIFT 0x0
+#define DB_Z_READ_BASE__BASE_256B_MASK 0xffffffff
+#define DB_Z_READ_BASE__BASE_256B__SHIFT 0x0
+#define DB_STENCIL_READ_BASE__BASE_256B_MASK 0xffffffff
+#define DB_STENCIL_READ_BASE__BASE_256B__SHIFT 0x0
+#define DB_Z_WRITE_BASE__BASE_256B_MASK 0xffffffff
+#define DB_Z_WRITE_BASE__BASE_256B__SHIFT 0x0
+#define DB_STENCIL_WRITE_BASE__BASE_256B_MASK 0xffffffff
+#define DB_STENCIL_WRITE_BASE__BASE_256B__SHIFT 0x0
+#define DB_DEPTH_INFO__ADDR5_SWIZZLE_MASK_MASK 0xf
+#define DB_DEPTH_INFO__ADDR5_SWIZZLE_MASK__SHIFT 0x0
+#define DB_DEPTH_INFO__ARRAY_MODE_MASK 0xf0
+#define DB_DEPTH_INFO__ARRAY_MODE__SHIFT 0x4
+#define DB_DEPTH_INFO__PIPE_CONFIG_MASK 0x1f00
+#define DB_DEPTH_INFO__PIPE_CONFIG__SHIFT 0x8
+#define DB_DEPTH_INFO__BANK_WIDTH_MASK 0x6000
+#define DB_DEPTH_INFO__BANK_WIDTH__SHIFT 0xd
+#define DB_DEPTH_INFO__BANK_HEIGHT_MASK 0x18000
+#define DB_DEPTH_INFO__BANK_HEIGHT__SHIFT 0xf
+#define DB_DEPTH_INFO__MACRO_TILE_ASPECT_MASK 0x60000
+#define DB_DEPTH_INFO__MACRO_TILE_ASPECT__SHIFT 0x11
+#define DB_DEPTH_INFO__NUM_BANKS_MASK 0x180000
+#define DB_DEPTH_INFO__NUM_BANKS__SHIFT 0x13
+#define DB_Z_INFO__FORMAT_MASK 0x3
+#define DB_Z_INFO__FORMAT__SHIFT 0x0
+#define DB_Z_INFO__NUM_SAMPLES_MASK 0xc
+#define DB_Z_INFO__NUM_SAMPLES__SHIFT 0x2
+#define DB_Z_INFO__TILE_SPLIT_MASK 0xe000
+#define DB_Z_INFO__TILE_SPLIT__SHIFT 0xd
+#define DB_Z_INFO__TILE_MODE_INDEX_MASK 0x700000
+#define DB_Z_INFO__TILE_MODE_INDEX__SHIFT 0x14
+#define DB_Z_INFO__DECOMPRESS_ON_N_ZPLANES_MASK 0x7800000
+#define DB_Z_INFO__DECOMPRESS_ON_N_ZPLANES__SHIFT 0x17
+#define DB_Z_INFO__ALLOW_EXPCLEAR_MASK 0x8000000
+#define DB_Z_INFO__ALLOW_EXPCLEAR__SHIFT 0x1b
+#define DB_Z_INFO__READ_SIZE_MASK 0x10000000
+#define DB_Z_INFO__READ_SIZE__SHIFT 0x1c
+#define DB_Z_INFO__TILE_SURFACE_ENABLE_MASK 0x20000000
+#define DB_Z_INFO__TILE_SURFACE_ENABLE__SHIFT 0x1d
+#define DB_Z_INFO__CLEAR_DISALLOWED_MASK 0x40000000
+#define DB_Z_INFO__CLEAR_DISALLOWED__SHIFT 0x1e
+#define DB_Z_INFO__ZRANGE_PRECISION_MASK 0x80000000
+#define DB_Z_INFO__ZRANGE_PRECISION__SHIFT 0x1f
+#define DB_STENCIL_INFO__FORMAT_MASK 0x1
+#define DB_STENCIL_INFO__FORMAT__SHIFT 0x0
+#define DB_STENCIL_INFO__TILE_SPLIT_MASK 0xe000
+#define DB_STENCIL_INFO__TILE_SPLIT__SHIFT 0xd
+#define DB_STENCIL_INFO__TILE_MODE_INDEX_MASK 0x700000
+#define DB_STENCIL_INFO__TILE_MODE_INDEX__SHIFT 0x14
+#define DB_STENCIL_INFO__ALLOW_EXPCLEAR_MASK 0x8000000
+#define DB_STENCIL_INFO__ALLOW_EXPCLEAR__SHIFT 0x1b
+#define DB_STENCIL_INFO__TILE_STENCIL_DISABLE_MASK 0x20000000
+#define DB_STENCIL_INFO__TILE_STENCIL_DISABLE__SHIFT 0x1d
+#define DB_STENCIL_INFO__CLEAR_DISALLOWED_MASK 0x40000000
+#define DB_STENCIL_INFO__CLEAR_DISALLOWED__SHIFT 0x1e
+#define DB_DEPTH_SIZE__PITCH_TILE_MAX_MASK 0x7ff
+#define DB_DEPTH_SIZE__PITCH_TILE_MAX__SHIFT 0x0
+#define DB_DEPTH_SIZE__HEIGHT_TILE_MAX_MASK 0x3ff800
+#define DB_DEPTH_SIZE__HEIGHT_TILE_MAX__SHIFT 0xb
+#define DB_DEPTH_SLICE__SLICE_TILE_MAX_MASK 0x3fffff
+#define DB_DEPTH_SLICE__SLICE_TILE_MAX__SHIFT 0x0
+#define DB_DEPTH_VIEW__SLICE_START_MASK 0x7ff
+#define DB_DEPTH_VIEW__SLICE_START__SHIFT 0x0
+#define DB_DEPTH_VIEW__SLICE_MAX_MASK 0xffe000
+#define DB_DEPTH_VIEW__SLICE_MAX__SHIFT 0xd
+#define DB_DEPTH_VIEW__Z_READ_ONLY_MASK 0x1000000
+#define DB_DEPTH_VIEW__Z_READ_ONLY__SHIFT 0x18
+#define DB_DEPTH_VIEW__STENCIL_READ_ONLY_MASK 0x2000000
+#define DB_DEPTH_VIEW__STENCIL_READ_ONLY__SHIFT 0x19
+#define DB_RENDER_CONTROL__DEPTH_CLEAR_ENABLE_MASK 0x1
+#define DB_RENDER_CONTROL__DEPTH_CLEAR_ENABLE__SHIFT 0x0
+#define DB_RENDER_CONTROL__STENCIL_CLEAR_ENABLE_MASK 0x2
+#define DB_RENDER_CONTROL__STENCIL_CLEAR_ENABLE__SHIFT 0x1
+#define DB_RENDER_CONTROL__DEPTH_COPY_MASK 0x4
+#define DB_RENDER_CONTROL__DEPTH_COPY__SHIFT 0x2
+#define DB_RENDER_CONTROL__STENCIL_COPY_MASK 0x8
+#define DB_RENDER_CONTROL__STENCIL_COPY__SHIFT 0x3
+#define DB_RENDER_CONTROL__RESUMMARIZE_ENABLE_MASK 0x10
+#define DB_RENDER_CONTROL__RESUMMARIZE_ENABLE__SHIFT 0x4
+#define DB_RENDER_CONTROL__STENCIL_COMPRESS_DISABLE_MASK 0x20
+#define DB_RENDER_CONTROL__STENCIL_COMPRESS_DISABLE__SHIFT 0x5
+#define DB_RENDER_CONTROL__DEPTH_COMPRESS_DISABLE_MASK 0x40
+#define DB_RENDER_CONTROL__DEPTH_COMPRESS_DISABLE__SHIFT 0x6
+#define DB_RENDER_CONTROL__COPY_CENTROID_MASK 0x80
+#define DB_RENDER_CONTROL__COPY_CENTROID__SHIFT 0x7
+#define DB_RENDER_CONTROL__COPY_SAMPLE_MASK 0xf00
+#define DB_RENDER_CONTROL__COPY_SAMPLE__SHIFT 0x8
+#define DB_RENDER_CONTROL__DECOMPRESS_ENABLE_MASK 0x1000
+#define DB_RENDER_CONTROL__DECOMPRESS_ENABLE__SHIFT 0xc
+#define DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE_MASK 0x1
+#define DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE__SHIFT 0x0
+#define DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_MASK 0x2
+#define DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS__SHIFT 0x1
+#define DB_COUNT_CONTROL__SAMPLE_RATE_MASK 0x70
+#define DB_COUNT_CONTROL__SAMPLE_RATE__SHIFT 0x4
+#define DB_COUNT_CONTROL__ZPASS_ENABLE_MASK 0xf00
+#define DB_COUNT_CONTROL__ZPASS_ENABLE__SHIFT 0x8
+#define DB_COUNT_CONTROL__ZFAIL_ENABLE_MASK 0xf000
+#define DB_COUNT_CONTROL__ZFAIL_ENABLE__SHIFT 0xc
+#define DB_COUNT_CONTROL__SFAIL_ENABLE_MASK 0xf0000
+#define DB_COUNT_CONTROL__SFAIL_ENABLE__SHIFT 0x10
+#define DB_COUNT_CONTROL__DBFAIL_ENABLE_MASK 0xf00000
+#define DB_COUNT_CONTROL__DBFAIL_ENABLE__SHIFT 0x14
+#define DB_COUNT_CONTROL__SLICE_EVEN_ENABLE_MASK 0xf000000
+#define DB_COUNT_CONTROL__SLICE_EVEN_ENABLE__SHIFT 0x18
+#define DB_COUNT_CONTROL__SLICE_ODD_ENABLE_MASK 0xf0000000
+#define DB_COUNT_CONTROL__SLICE_ODD_ENABLE__SHIFT 0x1c
+#define DB_RENDER_OVERRIDE__FORCE_HIZ_ENABLE_MASK 0x3
+#define DB_RENDER_OVERRIDE__FORCE_HIZ_ENABLE__SHIFT 0x0
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE0_MASK 0xc
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE0__SHIFT 0x2
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE1_MASK 0x30
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE1__SHIFT 0x4
+#define DB_RENDER_OVERRIDE__FORCE_SHADER_Z_ORDER_MASK 0x40
+#define DB_RENDER_OVERRIDE__FORCE_SHADER_Z_ORDER__SHIFT 0x6
+#define DB_RENDER_OVERRIDE__FAST_Z_DISABLE_MASK 0x80
+#define DB_RENDER_OVERRIDE__FAST_Z_DISABLE__SHIFT 0x7
+#define DB_RENDER_OVERRIDE__FAST_STENCIL_DISABLE_MASK 0x100
+#define DB_RENDER_OVERRIDE__FAST_STENCIL_DISABLE__SHIFT 0x8
+#define DB_RENDER_OVERRIDE__NOOP_CULL_DISABLE_MASK 0x200
+#define DB_RENDER_OVERRIDE__NOOP_CULL_DISABLE__SHIFT 0x9
+#define DB_RENDER_OVERRIDE__FORCE_COLOR_KILL_MASK 0x400
+#define DB_RENDER_OVERRIDE__FORCE_COLOR_KILL__SHIFT 0xa
+#define DB_RENDER_OVERRIDE__FORCE_Z_READ_MASK 0x800
+#define DB_RENDER_OVERRIDE__FORCE_Z_READ__SHIFT 0xb
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_READ_MASK 0x1000
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_READ__SHIFT 0xc
+#define DB_RENDER_OVERRIDE__FORCE_FULL_Z_RANGE_MASK 0x6000
+#define DB_RENDER_OVERRIDE__FORCE_FULL_Z_RANGE__SHIFT 0xd
+#define DB_RENDER_OVERRIDE__FORCE_QC_SMASK_CONFLICT_MASK 0x8000
+#define DB_RENDER_OVERRIDE__FORCE_QC_SMASK_CONFLICT__SHIFT 0xf
+#define DB_RENDER_OVERRIDE__DISABLE_VIEWPORT_CLAMP_MASK 0x10000
+#define DB_RENDER_OVERRIDE__DISABLE_VIEWPORT_CLAMP__SHIFT 0x10
+#define DB_RENDER_OVERRIDE__IGNORE_SC_ZRANGE_MASK 0x20000
+#define DB_RENDER_OVERRIDE__IGNORE_SC_ZRANGE__SHIFT 0x11
+#define DB_RENDER_OVERRIDE__DISABLE_FULLY_COVERED_MASK 0x40000
+#define DB_RENDER_OVERRIDE__DISABLE_FULLY_COVERED__SHIFT 0x12
+#define DB_RENDER_OVERRIDE__FORCE_Z_LIMIT_SUMM_MASK 0x180000
+#define DB_RENDER_OVERRIDE__FORCE_Z_LIMIT_SUMM__SHIFT 0x13
+#define DB_RENDER_OVERRIDE__MAX_TILES_IN_DTT_MASK 0x3e00000
+#define DB_RENDER_OVERRIDE__MAX_TILES_IN_DTT__SHIFT 0x15
+#define DB_RENDER_OVERRIDE__DISABLE_TILE_RATE_TILES_MASK 0x4000000
+#define DB_RENDER_OVERRIDE__DISABLE_TILE_RATE_TILES__SHIFT 0x1a
+#define DB_RENDER_OVERRIDE__FORCE_Z_DIRTY_MASK 0x8000000
+#define DB_RENDER_OVERRIDE__FORCE_Z_DIRTY__SHIFT 0x1b
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_DIRTY_MASK 0x10000000
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_DIRTY__SHIFT 0x1c
+#define DB_RENDER_OVERRIDE__FORCE_Z_VALID_MASK 0x20000000
+#define DB_RENDER_OVERRIDE__FORCE_Z_VALID__SHIFT 0x1d
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_VALID_MASK 0x40000000
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_VALID__SHIFT 0x1e
+#define DB_RENDER_OVERRIDE__PRESERVE_COMPRESSION_MASK 0x80000000
+#define DB_RENDER_OVERRIDE__PRESERVE_COMPRESSION__SHIFT 0x1f
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL_MASK 0x3
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL__SHIFT 0x0
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN_MASK 0x1c
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN__SHIFT 0x2
+#define DB_RENDER_OVERRIDE2__DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION_MASK 0x20
+#define DB_RENDER_OVERRIDE2__DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION__SHIFT 0x5
+#define DB_RENDER_OVERRIDE2__DISABLE_SMEM_EXPCLEAR_OPTIMIZATION_MASK 0x40
+#define DB_RENDER_OVERRIDE2__DISABLE_SMEM_EXPCLEAR_OPTIMIZATION__SHIFT 0x6
+#define DB_RENDER_OVERRIDE2__DISABLE_COLOR_ON_VALIDATION_MASK 0x80
+#define DB_RENDER_OVERRIDE2__DISABLE_COLOR_ON_VALIDATION__SHIFT 0x7
+#define DB_RENDER_OVERRIDE2__DECOMPRESS_Z_ON_FLUSH_MASK 0x100
+#define DB_RENDER_OVERRIDE2__DECOMPRESS_Z_ON_FLUSH__SHIFT 0x8
+#define DB_RENDER_OVERRIDE2__DISABLE_REG_SNOOP_MASK 0x200
+#define DB_RENDER_OVERRIDE2__DISABLE_REG_SNOOP__SHIFT 0x9
+#define DB_RENDER_OVERRIDE2__DEPTH_BOUNDS_HIER_DEPTH_DISABLE_MASK 0x400
+#define DB_RENDER_OVERRIDE2__DEPTH_BOUNDS_HIER_DEPTH_DISABLE__SHIFT 0xa
+#define DB_RENDER_OVERRIDE2__SEPARATE_HIZS_FUNC_ENABLE_MASK 0x800
+#define DB_RENDER_OVERRIDE2__SEPARATE_HIZS_FUNC_ENABLE__SHIFT 0xb
+#define DB_RENDER_OVERRIDE2__HIZ_ZFUNC_MASK 0x7000
+#define DB_RENDER_OVERRIDE2__HIZ_ZFUNC__SHIFT 0xc
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_FF_MASK 0x38000
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_FF__SHIFT 0xf
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_BF_MASK 0x1c0000
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_BF__SHIFT 0x12
+#define DB_RENDER_OVERRIDE2__PRESERVE_ZRANGE_MASK 0x200000
+#define DB_RENDER_OVERRIDE2__PRESERVE_ZRANGE__SHIFT 0x15
+#define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS_MASK 0x400000
+#define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS__SHIFT 0x16
+#define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS_MASK 0x800000
+#define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS__SHIFT 0x17
+#define DB_EQAA__MAX_ANCHOR_SAMPLES_MASK 0x7
+#define DB_EQAA__MAX_ANCHOR_SAMPLES__SHIFT 0x0
+#define DB_EQAA__PS_ITER_SAMPLES_MASK 0x70
+#define DB_EQAA__PS_ITER_SAMPLES__SHIFT 0x4
+#define DB_EQAA__MASK_EXPORT_NUM_SAMPLES_MASK 0x700
+#define DB_EQAA__MASK_EXPORT_NUM_SAMPLES__SHIFT 0x8
+#define DB_EQAA__ALPHA_TO_MASK_NUM_SAMPLES_MASK 0x7000
+#define DB_EQAA__ALPHA_TO_MASK_NUM_SAMPLES__SHIFT 0xc
+#define DB_EQAA__HIGH_QUALITY_INTERSECTIONS_MASK 0x10000
+#define DB_EQAA__HIGH_QUALITY_INTERSECTIONS__SHIFT 0x10
+#define DB_EQAA__INCOHERENT_EQAA_READS_MASK 0x20000
+#define DB_EQAA__INCOHERENT_EQAA_READS__SHIFT 0x11
+#define DB_EQAA__INTERPOLATE_COMP_Z_MASK 0x40000
+#define DB_EQAA__INTERPOLATE_COMP_Z__SHIFT 0x12
+#define DB_EQAA__INTERPOLATE_SRC_Z_MASK 0x80000
+#define DB_EQAA__INTERPOLATE_SRC_Z__SHIFT 0x13
+#define DB_EQAA__STATIC_ANCHOR_ASSOCIATIONS_MASK 0x100000
+#define DB_EQAA__STATIC_ANCHOR_ASSOCIATIONS__SHIFT 0x14
+#define DB_EQAA__ALPHA_TO_MASK_EQAA_DISABLE_MASK 0x200000
+#define DB_EQAA__ALPHA_TO_MASK_EQAA_DISABLE__SHIFT 0x15
+#define DB_EQAA__OVERRASTERIZATION_AMOUNT_MASK 0x7000000
+#define DB_EQAA__OVERRASTERIZATION_AMOUNT__SHIFT 0x18
+#define DB_EQAA__ENABLE_POSTZ_OVERRASTERIZATION_MASK 0x8000000
+#define DB_EQAA__ENABLE_POSTZ_OVERRASTERIZATION__SHIFT 0x1b
+#define DB_SHADER_CONTROL__Z_EXPORT_ENABLE_MASK 0x1
+#define DB_SHADER_CONTROL__Z_EXPORT_ENABLE__SHIFT 0x0
+#define DB_SHADER_CONTROL__STENCIL_TEST_VAL_EXPORT_ENABLE_MASK 0x2
+#define DB_SHADER_CONTROL__STENCIL_TEST_VAL_EXPORT_ENABLE__SHIFT 0x1
+#define DB_SHADER_CONTROL__STENCIL_OP_VAL_EXPORT_ENABLE_MASK 0x4
+#define DB_SHADER_CONTROL__STENCIL_OP_VAL_EXPORT_ENABLE__SHIFT 0x2
+#define DB_SHADER_CONTROL__Z_ORDER_MASK 0x30
+#define DB_SHADER_CONTROL__Z_ORDER__SHIFT 0x4
+#define DB_SHADER_CONTROL__KILL_ENABLE_MASK 0x40
+#define DB_SHADER_CONTROL__KILL_ENABLE__SHIFT 0x6
+#define DB_SHADER_CONTROL__COVERAGE_TO_MASK_ENABLE_MASK 0x80
+#define DB_SHADER_CONTROL__COVERAGE_TO_MASK_ENABLE__SHIFT 0x7
+#define DB_SHADER_CONTROL__MASK_EXPORT_ENABLE_MASK 0x100
+#define DB_SHADER_CONTROL__MASK_EXPORT_ENABLE__SHIFT 0x8
+#define DB_SHADER_CONTROL__EXEC_ON_HIER_FAIL_MASK 0x200
+#define DB_SHADER_CONTROL__EXEC_ON_HIER_FAIL__SHIFT 0x9
+#define DB_SHADER_CONTROL__EXEC_ON_NOOP_MASK 0x400
+#define DB_SHADER_CONTROL__EXEC_ON_NOOP__SHIFT 0xa
+#define DB_SHADER_CONTROL__ALPHA_TO_MASK_DISABLE_MASK 0x800
+#define DB_SHADER_CONTROL__ALPHA_TO_MASK_DISABLE__SHIFT 0xb
+#define DB_SHADER_CONTROL__DEPTH_BEFORE_SHADER_MASK 0x1000
+#define DB_SHADER_CONTROL__DEPTH_BEFORE_SHADER__SHIFT 0xc
+#define DB_SHADER_CONTROL__CONSERVATIVE_Z_EXPORT_MASK 0x6000
+#define DB_SHADER_CONTROL__CONSERVATIVE_Z_EXPORT__SHIFT 0xd
+#define DB_SHADER_CONTROL__DUAL_QUAD_DISABLE_MASK 0x8000
+#define DB_SHADER_CONTROL__DUAL_QUAD_DISABLE__SHIFT 0xf
+#define DB_DEPTH_BOUNDS_MIN__MIN_MASK 0xffffffff
+#define DB_DEPTH_BOUNDS_MIN__MIN__SHIFT 0x0
+#define DB_DEPTH_BOUNDS_MAX__MAX_MASK 0xffffffff
+#define DB_DEPTH_BOUNDS_MAX__MAX__SHIFT 0x0
+#define DB_STENCIL_CLEAR__CLEAR_MASK 0xff
+#define DB_STENCIL_CLEAR__CLEAR__SHIFT 0x0
+#define DB_DEPTH_CLEAR__DEPTH_CLEAR_MASK 0xffffffff
+#define DB_DEPTH_CLEAR__DEPTH_CLEAR__SHIFT 0x0
+#define DB_HTILE_DATA_BASE__BASE_256B_MASK 0xffffffff
+#define DB_HTILE_DATA_BASE__BASE_256B__SHIFT 0x0
+#define DB_HTILE_SURFACE__LINEAR_MASK 0x1
+#define DB_HTILE_SURFACE__LINEAR__SHIFT 0x0
+#define DB_HTILE_SURFACE__FULL_CACHE_MASK 0x2
+#define DB_HTILE_SURFACE__FULL_CACHE__SHIFT 0x1
+#define DB_HTILE_SURFACE__HTILE_USES_PRELOAD_WIN_MASK 0x4
+#define DB_HTILE_SURFACE__HTILE_USES_PRELOAD_WIN__SHIFT 0x2
+#define DB_HTILE_SURFACE__PRELOAD_MASK 0x8
+#define DB_HTILE_SURFACE__PRELOAD__SHIFT 0x3
+#define DB_HTILE_SURFACE__PREFETCH_WIDTH_MASK 0x3f0
+#define DB_HTILE_SURFACE__PREFETCH_WIDTH__SHIFT 0x4
+#define DB_HTILE_SURFACE__PREFETCH_HEIGHT_MASK 0xfc00
+#define DB_HTILE_SURFACE__PREFETCH_HEIGHT__SHIFT 0xa
+#define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE_MASK 0x10000
+#define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE__SHIFT 0x10
+#define DB_HTILE_SURFACE__TC_COMPATIBLE_MASK 0x20000
+#define DB_HTILE_SURFACE__TC_COMPATIBLE__SHIFT 0x11
+#define DB_PRELOAD_CONTROL__START_X_MASK 0xff
+#define DB_PRELOAD_CONTROL__START_X__SHIFT 0x0
+#define DB_PRELOAD_CONTROL__START_Y_MASK 0xff00
+#define DB_PRELOAD_CONTROL__START_Y__SHIFT 0x8
+#define DB_PRELOAD_CONTROL__MAX_X_MASK 0xff0000
+#define DB_PRELOAD_CONTROL__MAX_X__SHIFT 0x10
+#define DB_PRELOAD_CONTROL__MAX_Y_MASK 0xff000000
+#define DB_PRELOAD_CONTROL__MAX_Y__SHIFT 0x18
+#define DB_STENCILREFMASK__STENCILTESTVAL_MASK 0xff
+#define DB_STENCILREFMASK__STENCILTESTVAL__SHIFT 0x0
+#define DB_STENCILREFMASK__STENCILMASK_MASK 0xff00
+#define DB_STENCILREFMASK__STENCILMASK__SHIFT 0x8
+#define DB_STENCILREFMASK__STENCILWRITEMASK_MASK 0xff0000
+#define DB_STENCILREFMASK__STENCILWRITEMASK__SHIFT 0x10
+#define DB_STENCILREFMASK__STENCILOPVAL_MASK 0xff000000
+#define DB_STENCILREFMASK__STENCILOPVAL__SHIFT 0x18
+#define DB_STENCILREFMASK_BF__STENCILTESTVAL_BF_MASK 0xff
+#define DB_STENCILREFMASK_BF__STENCILTESTVAL_BF__SHIFT 0x0
+#define DB_STENCILREFMASK_BF__STENCILMASK_BF_MASK 0xff00
+#define DB_STENCILREFMASK_BF__STENCILMASK_BF__SHIFT 0x8
+#define DB_STENCILREFMASK_BF__STENCILWRITEMASK_BF_MASK 0xff0000
+#define DB_STENCILREFMASK_BF__STENCILWRITEMASK_BF__SHIFT 0x10
+#define DB_STENCILREFMASK_BF__STENCILOPVAL_BF_MASK 0xff000000
+#define DB_STENCILREFMASK_BF__STENCILOPVAL_BF__SHIFT 0x18
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0_MASK 0x7
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0__SHIFT 0x0
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0_MASK 0xff0
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0__SHIFT 0x4
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREMASK0_MASK 0xff000
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREMASK0__SHIFT 0xc
+#define DB_SRESULTS_COMPARE_STATE0__ENABLE0_MASK 0x1000000
+#define DB_SRESULTS_COMPARE_STATE0__ENABLE0__SHIFT 0x18
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREFUNC1_MASK 0x7
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREFUNC1__SHIFT 0x0
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREVALUE1_MASK 0xff0
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREVALUE1__SHIFT 0x4
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREMASK1_MASK 0xff000
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREMASK1__SHIFT 0xc
+#define DB_SRESULTS_COMPARE_STATE1__ENABLE1_MASK 0x1000000
+#define DB_SRESULTS_COMPARE_STATE1__ENABLE1__SHIFT 0x18
+#define DB_DEPTH_CONTROL__STENCIL_ENABLE_MASK 0x1
+#define DB_DEPTH_CONTROL__STENCIL_ENABLE__SHIFT 0x0
+#define DB_DEPTH_CONTROL__Z_ENABLE_MASK 0x2
+#define DB_DEPTH_CONTROL__Z_ENABLE__SHIFT 0x1
+#define DB_DEPTH_CONTROL__Z_WRITE_ENABLE_MASK 0x4
+#define DB_DEPTH_CONTROL__Z_WRITE_ENABLE__SHIFT 0x2
+#define DB_DEPTH_CONTROL__DEPTH_BOUNDS_ENABLE_MASK 0x8
+#define DB_DEPTH_CONTROL__DEPTH_BOUNDS_ENABLE__SHIFT 0x3
+#define DB_DEPTH_CONTROL__ZFUNC_MASK 0x70
+#define DB_DEPTH_CONTROL__ZFUNC__SHIFT 0x4
+#define DB_DEPTH_CONTROL__BACKFACE_ENABLE_MASK 0x80
+#define DB_DEPTH_CONTROL__BACKFACE_ENABLE__SHIFT 0x7
+#define DB_DEPTH_CONTROL__STENCILFUNC_MASK 0x700
+#define DB_DEPTH_CONTROL__STENCILFUNC__SHIFT 0x8
+#define DB_DEPTH_CONTROL__STENCILFUNC_BF_MASK 0x700000
+#define DB_DEPTH_CONTROL__STENCILFUNC_BF__SHIFT 0x14
+#define DB_DEPTH_CONTROL__ENABLE_COLOR_WRITES_ON_DEPTH_FAIL_MASK 0x40000000
+#define DB_DEPTH_CONTROL__ENABLE_COLOR_WRITES_ON_DEPTH_FAIL__SHIFT 0x1e
+#define DB_DEPTH_CONTROL__DISABLE_COLOR_WRITES_ON_DEPTH_PASS_MASK 0x80000000
+#define DB_DEPTH_CONTROL__DISABLE_COLOR_WRITES_ON_DEPTH_PASS__SHIFT 0x1f
+#define DB_STENCIL_CONTROL__STENCILFAIL_MASK 0xf
+#define DB_STENCIL_CONTROL__STENCILFAIL__SHIFT 0x0
+#define DB_STENCIL_CONTROL__STENCILZPASS_MASK 0xf0
+#define DB_STENCIL_CONTROL__STENCILZPASS__SHIFT 0x4
+#define DB_STENCIL_CONTROL__STENCILZFAIL_MASK 0xf00
+#define DB_STENCIL_CONTROL__STENCILZFAIL__SHIFT 0x8
+#define DB_STENCIL_CONTROL__STENCILFAIL_BF_MASK 0xf000
+#define DB_STENCIL_CONTROL__STENCILFAIL_BF__SHIFT 0xc
+#define DB_STENCIL_CONTROL__STENCILZPASS_BF_MASK 0xf0000
+#define DB_STENCIL_CONTROL__STENCILZPASS_BF__SHIFT 0x10
+#define DB_STENCIL_CONTROL__STENCILZFAIL_BF_MASK 0xf00000
+#define DB_STENCIL_CONTROL__STENCILZFAIL_BF__SHIFT 0x14
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_ENABLE_MASK 0x1
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_ENABLE__SHIFT 0x0
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET0_MASK 0x300
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET0__SHIFT 0x8
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET1_MASK 0xc00
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET1__SHIFT 0xa
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET2_MASK 0x3000
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET2__SHIFT 0xc
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET3_MASK 0xc000
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET3__SHIFT 0xe
+#define DB_ALPHA_TO_MASK__OFFSET_ROUND_MASK 0x10000
+#define DB_ALPHA_TO_MASK__OFFSET_ROUND__SHIFT 0x10
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define DB_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define DB_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define DB_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define DB_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL1_MASK 0xffc00
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL1__SHIFT 0xa
+#define DB_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define DB_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE1_MASK 0xf000000
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE1__SHIFT 0x18
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL1_MASK 0xffc00
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL1__SHIFT 0xa
+#define DB_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define DB_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE1_MASK 0xf000000
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE1__SHIFT 0x18
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf000000
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x18
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define DB_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define DB_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define DB_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define DB_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define DB_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define DB_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define DB_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define DB_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define DB_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define DB_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define DB_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define DB_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define DB_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define DB_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define DB_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define DB_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define DB_DEBUG__DEBUG_STENCIL_COMPRESS_DISABLE_MASK 0x1
+#define DB_DEBUG__DEBUG_STENCIL_COMPRESS_DISABLE__SHIFT 0x0
+#define DB_DEBUG__DEBUG_DEPTH_COMPRESS_DISABLE_MASK 0x2
+#define DB_DEBUG__DEBUG_DEPTH_COMPRESS_DISABLE__SHIFT 0x1
+#define DB_DEBUG__FETCH_FULL_Z_TILE_MASK 0x4
+#define DB_DEBUG__FETCH_FULL_Z_TILE__SHIFT 0x2
+#define DB_DEBUG__FETCH_FULL_STENCIL_TILE_MASK 0x8
+#define DB_DEBUG__FETCH_FULL_STENCIL_TILE__SHIFT 0x3
+#define DB_DEBUG__FORCE_Z_MODE_MASK 0x30
+#define DB_DEBUG__FORCE_Z_MODE__SHIFT 0x4
+#define DB_DEBUG__DEBUG_FORCE_DEPTH_READ_MASK 0x40
+#define DB_DEBUG__DEBUG_FORCE_DEPTH_READ__SHIFT 0x6
+#define DB_DEBUG__DEBUG_FORCE_STENCIL_READ_MASK 0x80
+#define DB_DEBUG__DEBUG_FORCE_STENCIL_READ__SHIFT 0x7
+#define DB_DEBUG__DEBUG_FORCE_HIZ_ENABLE_MASK 0x300
+#define DB_DEBUG__DEBUG_FORCE_HIZ_ENABLE__SHIFT 0x8
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE0_MASK 0xc00
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE0__SHIFT 0xa
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE1_MASK 0x3000
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE1__SHIFT 0xc
+#define DB_DEBUG__DEBUG_FAST_Z_DISABLE_MASK 0x4000
+#define DB_DEBUG__DEBUG_FAST_Z_DISABLE__SHIFT 0xe
+#define DB_DEBUG__DEBUG_FAST_STENCIL_DISABLE_MASK 0x8000
+#define DB_DEBUG__DEBUG_FAST_STENCIL_DISABLE__SHIFT 0xf
+#define DB_DEBUG__DEBUG_NOOP_CULL_DISABLE_MASK 0x10000
+#define DB_DEBUG__DEBUG_NOOP_CULL_DISABLE__SHIFT 0x10
+#define DB_DEBUG__DISABLE_SUMM_SQUADS_MASK 0x20000
+#define DB_DEBUG__DISABLE_SUMM_SQUADS__SHIFT 0x11
+#define DB_DEBUG__DEPTH_CACHE_FORCE_MISS_MASK 0x40000
+#define DB_DEBUG__DEPTH_CACHE_FORCE_MISS__SHIFT 0x12
+#define DB_DEBUG__DEBUG_FORCE_FULL_Z_RANGE_MASK 0x180000
+#define DB_DEBUG__DEBUG_FORCE_FULL_Z_RANGE__SHIFT 0x13
+#define DB_DEBUG__NEVER_FREE_Z_ONLY_MASK 0x200000
+#define DB_DEBUG__NEVER_FREE_Z_ONLY__SHIFT 0x15
+#define DB_DEBUG__ZPASS_COUNTS_LOOK_AT_PIPE_STAT_EVENTS_MASK 0x400000
+#define DB_DEBUG__ZPASS_COUNTS_LOOK_AT_PIPE_STAT_EVENTS__SHIFT 0x16
+#define DB_DEBUG__DISABLE_VPORT_ZPLANE_OPTIMIZATION_MASK 0x800000
+#define DB_DEBUG__DISABLE_VPORT_ZPLANE_OPTIMIZATION__SHIFT 0x17
+#define DB_DEBUG__DECOMPRESS_AFTER_N_ZPLANES_MASK 0xf000000
+#define DB_DEBUG__DECOMPRESS_AFTER_N_ZPLANES__SHIFT 0x18
+#define DB_DEBUG__ONE_FREE_IN_FLIGHT_MASK 0x10000000
+#define DB_DEBUG__ONE_FREE_IN_FLIGHT__SHIFT 0x1c
+#define DB_DEBUG__FORCE_MISS_IF_NOT_INFLIGHT_MASK 0x20000000
+#define DB_DEBUG__FORCE_MISS_IF_NOT_INFLIGHT__SHIFT 0x1d
+#define DB_DEBUG__DISABLE_DEPTH_SURFACE_SYNC_MASK 0x40000000
+#define DB_DEBUG__DISABLE_DEPTH_SURFACE_SYNC__SHIFT 0x1e
+#define DB_DEBUG__DISABLE_HTILE_SURFACE_SYNC_MASK 0x80000000
+#define DB_DEBUG__DISABLE_HTILE_SURFACE_SYNC__SHIFT 0x1f
+#define DB_DEBUG2__ALLOW_COMPZ_BYTE_MASKING_MASK 0x1
+#define DB_DEBUG2__ALLOW_COMPZ_BYTE_MASKING__SHIFT 0x0
+#define DB_DEBUG2__DISABLE_TC_ZRANGE_L0_CACHE_MASK 0x2
+#define DB_DEBUG2__DISABLE_TC_ZRANGE_L0_CACHE__SHIFT 0x1
+#define DB_DEBUG2__DISABLE_TC_MASK_L0_CACHE_MASK 0x4
+#define DB_DEBUG2__DISABLE_TC_MASK_L0_CACHE__SHIFT 0x2
+#define DB_DEBUG2__DTR_ROUND_ROBIN_ARB_MASK 0x8
+#define DB_DEBUG2__DTR_ROUND_ROBIN_ARB__SHIFT 0x3
+#define DB_DEBUG2__DTR_PREZ_STALLS_FOR_ETF_ROOM_MASK 0x10
+#define DB_DEBUG2__DTR_PREZ_STALLS_FOR_ETF_ROOM__SHIFT 0x4
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_MASK 0x20
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL__SHIFT 0x5
+#define DB_DEBUG2__ENABLE_PREZL_CB_STALL_MASK 0x40
+#define DB_DEBUG2__ENABLE_PREZL_CB_STALL__SHIFT 0x6
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_REZ_MASK 0x80
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_REZ__SHIFT 0x7
+#define DB_DEBUG2__DISABLE_PREZL_CB_STALL_REZ_MASK 0x100
+#define DB_DEBUG2__DISABLE_PREZL_CB_STALL_REZ__SHIFT 0x8
+#define DB_DEBUG2__CLK_OFF_DELAY_MASK 0x3e00
+#define DB_DEBUG2__CLK_OFF_DELAY__SHIFT 0x9
+#define DB_DEBUG2__DISABLE_TILE_COVERED_FOR_PS_ITER_MASK 0x4000
+#define DB_DEBUG2__DISABLE_TILE_COVERED_FOR_PS_ITER__SHIFT 0xe
+#define DB_DEBUG2__ENABLE_SUBTILE_GROUPING_MASK 0x8000
+#define DB_DEBUG2__ENABLE_SUBTILE_GROUPING__SHIFT 0xf
+#define DB_DEBUG2__DISABLE_HTILE_PAIRED_PIPES_MASK 0x10000
+#define DB_DEBUG2__DISABLE_HTILE_PAIRED_PIPES__SHIFT 0x10
+#define DB_DEBUG2__DISABLE_NULL_EOT_FORWARDING_MASK 0x20000
+#define DB_DEBUG2__DISABLE_NULL_EOT_FORWARDING__SHIFT 0x11
+#define DB_DEBUG2__DISABLE_DTT_DATA_FORWARDING_MASK 0x40000
+#define DB_DEBUG2__DISABLE_DTT_DATA_FORWARDING__SHIFT 0x12
+#define DB_DEBUG2__DISABLE_QUAD_COHERENCY_STALL_MASK 0x80000
+#define DB_DEBUG2__DISABLE_QUAD_COHERENCY_STALL__SHIFT 0x13
+#define DB_DEBUG2__ENABLE_PREZ_OF_REZ_SUMM_MASK 0x10000000
+#define DB_DEBUG2__ENABLE_PREZ_OF_REZ_SUMM__SHIFT 0x1c
+#define DB_DEBUG2__DISABLE_PREZL_VIEWPORT_STALL_MASK 0x20000000
+#define DB_DEBUG2__DISABLE_PREZL_VIEWPORT_STALL__SHIFT 0x1d
+#define DB_DEBUG2__DISABLE_SINGLE_STENCIL_QUAD_SUMM_MASK 0x40000000
+#define DB_DEBUG2__DISABLE_SINGLE_STENCIL_QUAD_SUMM__SHIFT 0x1e
+#define DB_DEBUG2__DISABLE_WRITE_STALL_ON_RDWR_CONFLICT_MASK 0x80000000
+#define DB_DEBUG2__DISABLE_WRITE_STALL_ON_RDWR_CONFLICT__SHIFT 0x1f
+#define DB_DEBUG3__FORCE_DB_IS_GOOD_MASK 0x4
+#define DB_DEBUG3__FORCE_DB_IS_GOOD__SHIFT 0x2
+#define DB_DEBUG3__DISABLE_TL_SSO_NULL_SUPPRESSION_MASK 0x8
+#define DB_DEBUG3__DISABLE_TL_SSO_NULL_SUPPRESSION__SHIFT 0x3
+#define DB_DEBUG3__DISABLE_HIZ_ON_VPORT_CLAMP_MASK 0x10
+#define DB_DEBUG3__DISABLE_HIZ_ON_VPORT_CLAMP__SHIFT 0x4
+#define DB_DEBUG3__EQAA_INTERPOLATE_COMP_Z_MASK 0x20
+#define DB_DEBUG3__EQAA_INTERPOLATE_COMP_Z__SHIFT 0x5
+#define DB_DEBUG3__EQAA_INTERPOLATE_SRC_Z_MASK 0x40
+#define DB_DEBUG3__EQAA_INTERPOLATE_SRC_Z__SHIFT 0x6
+#define DB_DEBUG3__DISABLE_TCP_CAM_BYPASS_MASK 0x80
+#define DB_DEBUG3__DISABLE_TCP_CAM_BYPASS__SHIFT 0x7
+#define DB_DEBUG3__DISABLE_ZCMP_DIRTY_SUPPRESSION_MASK 0x100
+#define DB_DEBUG3__DISABLE_ZCMP_DIRTY_SUPPRESSION__SHIFT 0x8
+#define DB_DEBUG3__DISABLE_REDUNDANT_PLANE_FLUSHES_OPT_MASK 0x200
+#define DB_DEBUG3__DISABLE_REDUNDANT_PLANE_FLUSHES_OPT__SHIFT 0x9
+#define DB_DEBUG3__DISABLE_RECOMP_TO_1ZPLANE_WITHOUT_FASTOP_MASK 0x400
+#define DB_DEBUG3__DISABLE_RECOMP_TO_1ZPLANE_WITHOUT_FASTOP__SHIFT 0xa
+#define DB_DEBUG3__ENABLE_INCOHERENT_EQAA_READS_MASK 0x800
+#define DB_DEBUG3__ENABLE_INCOHERENT_EQAA_READS__SHIFT 0xb
+#define DB_DEBUG3__DISABLE_OP_Z_DATA_FORWARDING_MASK 0x1000
+#define DB_DEBUG3__DISABLE_OP_Z_DATA_FORWARDING__SHIFT 0xc
+#define DB_DEBUG3__DISABLE_OP_DF_BYPASS_MASK 0x2000
+#define DB_DEBUG3__DISABLE_OP_DF_BYPASS__SHIFT 0xd
+#define DB_DEBUG3__DISABLE_OP_DF_WRITE_COMBINE_MASK 0x4000
+#define DB_DEBUG3__DISABLE_OP_DF_WRITE_COMBINE__SHIFT 0xe
+#define DB_DEBUG3__DISABLE_OP_DF_DIRECT_FEEDBACK_MASK 0x8000
+#define DB_DEBUG3__DISABLE_OP_DF_DIRECT_FEEDBACK__SHIFT 0xf
+#define DB_DEBUG3__ALLOW_RF2P_RW_COLLISION_MASK 0x10000
+#define DB_DEBUG3__ALLOW_RF2P_RW_COLLISION__SHIFT 0x10
+#define DB_DEBUG3__SLOW_PREZ_TO_A2M_OMASK_RATE_MASK 0x20000
+#define DB_DEBUG3__SLOW_PREZ_TO_A2M_OMASK_RATE__SHIFT 0x11
+#define DB_DEBUG3__DISABLE_OP_S_DATA_FORWARDING_MASK 0x40000
+#define DB_DEBUG3__DISABLE_OP_S_DATA_FORWARDING__SHIFT 0x12
+#define DB_DEBUG3__DISABLE_TC_UPDATE_WRITE_COMBINE_MASK 0x80000
+#define DB_DEBUG3__DISABLE_TC_UPDATE_WRITE_COMBINE__SHIFT 0x13
+#define DB_DEBUG3__DISABLE_HZ_TC_WRITE_COMBINE_MASK 0x100000
+#define DB_DEBUG3__DISABLE_HZ_TC_WRITE_COMBINE__SHIFT 0x14
+#define DB_DEBUG3__ENABLE_RECOMP_ZDIRTY_SUPPRESSION_OPT_MASK 0x200000
+#define DB_DEBUG3__ENABLE_RECOMP_ZDIRTY_SUPPRESSION_OPT__SHIFT 0x15
+#define DB_DEBUG3__ENABLE_TC_MA_ROUND_ROBIN_ARB_MASK 0x400000
+#define DB_DEBUG3__ENABLE_TC_MA_ROUND_ROBIN_ARB__SHIFT 0x16
+#define DB_DEBUG3__DISABLE_RAM_READ_SUPPRESION_ON_FWD_MASK 0x800000
+#define DB_DEBUG3__DISABLE_RAM_READ_SUPPRESION_ON_FWD__SHIFT 0x17
+#define DB_DEBUG3__DISABLE_EQAA_A2M_PERF_OPT_MASK 0x1000000
+#define DB_DEBUG3__DISABLE_EQAA_A2M_PERF_OPT__SHIFT 0x18
+#define DB_DEBUG3__DISABLE_DI_DT_STALL_MASK 0x2000000
+#define DB_DEBUG3__DISABLE_DI_DT_STALL__SHIFT 0x19
+#define DB_DEBUG3__ENABLE_DB_PROCESS_RESET_MASK 0x4000000
+#define DB_DEBUG3__ENABLE_DB_PROCESS_RESET__SHIFT 0x1a
+#define DB_DEBUG3__DISABLE_OVERRASTERIZATION_FIX_MASK 0x8000000
+#define DB_DEBUG3__DISABLE_OVERRASTERIZATION_FIX__SHIFT 0x1b
+#define DB_DEBUG3__DONT_INSERT_CONTEXT_SUSPEND_MASK 0x10000000
+#define DB_DEBUG3__DONT_INSERT_CONTEXT_SUSPEND__SHIFT 0x1c
+#define DB_DEBUG3__DONT_DELETE_CONTEXT_SUSPEND_MASK 0x20000000
+#define DB_DEBUG3__DONT_DELETE_CONTEXT_SUSPEND__SHIFT 0x1d
+#define DB_DEBUG3__DISABLE_4XAA_2P_DELAYED_WRITE_MASK 0x40000000
+#define DB_DEBUG3__DISABLE_4XAA_2P_DELAYED_WRITE__SHIFT 0x1e
+#define DB_DEBUG3__DISABLE_4XAA_2P_INTERLEAVED_PMASK_MASK 0x80000000
+#define DB_DEBUG3__DISABLE_4XAA_2P_INTERLEAVED_PMASK__SHIFT 0x1f
+#define DB_DEBUG4__DISABLE_QC_Z_MASK_SUMMATION_MASK 0x1
+#define DB_DEBUG4__DISABLE_QC_Z_MASK_SUMMATION__SHIFT 0x0
+#define DB_DEBUG4__DISABLE_QC_STENCIL_MASK_SUMMATION_MASK 0x2
+#define DB_DEBUG4__DISABLE_QC_STENCIL_MASK_SUMMATION__SHIFT 0x1
+#define DB_DEBUG4__DISABLE_RESUMM_TO_SINGLE_STENCIL_MASK 0x4
+#define DB_DEBUG4__DISABLE_RESUMM_TO_SINGLE_STENCIL__SHIFT 0x2
+#define DB_DEBUG4__DISABLE_PREZ_POSTZ_DTILE_CONFLICT_STALL_MASK 0x8
+#define DB_DEBUG4__DISABLE_PREZ_POSTZ_DTILE_CONFLICT_STALL__SHIFT 0x3
+#define DB_DEBUG4__DISABLE_4XAA_2P_ZD_HOLDOFF_MASK 0x10
+#define DB_DEBUG4__DISABLE_4XAA_2P_ZD_HOLDOFF__SHIFT 0x4
+#define DB_DEBUG4__ENABLE_A2M_DQUAD_OPTIMIZATION_MASK 0x20
+#define DB_DEBUG4__ENABLE_A2M_DQUAD_OPTIMIZATION__SHIFT 0x5
+#define DB_DEBUG4__ENABLE_DBCB_SLOW_FORMAT_COLLAPSE_MASK 0x40
+#define DB_DEBUG4__ENABLE_DBCB_SLOW_FORMAT_COLLAPSE__SHIFT 0x6
+#define DB_DEBUG4__DB_EXTRA_DEBUG4_MASK 0xffffff80
+#define DB_DEBUG4__DB_EXTRA_DEBUG4__SHIFT 0x7
+#define DB_CREDIT_LIMIT__DB_SC_TILE_CREDITS_MASK 0x1f
+#define DB_CREDIT_LIMIT__DB_SC_TILE_CREDITS__SHIFT 0x0
+#define DB_CREDIT_LIMIT__DB_SC_QUAD_CREDITS_MASK 0x3e0
+#define DB_CREDIT_LIMIT__DB_SC_QUAD_CREDITS__SHIFT 0x5
+#define DB_CREDIT_LIMIT__DB_CB_LQUAD_CREDITS_MASK 0x1c00
+#define DB_CREDIT_LIMIT__DB_CB_LQUAD_CREDITS__SHIFT 0xa
+#define DB_CREDIT_LIMIT__DB_CB_TILE_CREDITS_MASK 0x7f000000
+#define DB_CREDIT_LIMIT__DB_CB_TILE_CREDITS__SHIFT 0x18
+#define DB_WATERMARKS__DEPTH_FREE_MASK 0x1f
+#define DB_WATERMARKS__DEPTH_FREE__SHIFT 0x0
+#define DB_WATERMARKS__DEPTH_FLUSH_MASK 0x7e0
+#define DB_WATERMARKS__DEPTH_FLUSH__SHIFT 0x5
+#define DB_WATERMARKS__FORCE_SUMMARIZE_MASK 0x7800
+#define DB_WATERMARKS__FORCE_SUMMARIZE__SHIFT 0xb
+#define DB_WATERMARKS__DEPTH_PENDING_FREE_MASK 0xf8000
+#define DB_WATERMARKS__DEPTH_PENDING_FREE__SHIFT 0xf
+#define DB_WATERMARKS__DEPTH_CACHELINE_FREE_MASK 0x7f00000
+#define DB_WATERMARKS__DEPTH_CACHELINE_FREE__SHIFT 0x14
+#define DB_WATERMARKS__EARLY_Z_PANIC_DISABLE_MASK 0x8000000
+#define DB_WATERMARKS__EARLY_Z_PANIC_DISABLE__SHIFT 0x1b
+#define DB_WATERMARKS__LATE_Z_PANIC_DISABLE_MASK 0x10000000
+#define DB_WATERMARKS__LATE_Z_PANIC_DISABLE__SHIFT 0x1c
+#define DB_WATERMARKS__RE_Z_PANIC_DISABLE_MASK 0x20000000
+#define DB_WATERMARKS__RE_Z_PANIC_DISABLE__SHIFT 0x1d
+#define DB_WATERMARKS__AUTO_FLUSH_HTILE_MASK 0x40000000
+#define DB_WATERMARKS__AUTO_FLUSH_HTILE__SHIFT 0x1e
+#define DB_WATERMARKS__AUTO_FLUSH_QUAD_MASK 0x80000000
+#define DB_WATERMARKS__AUTO_FLUSH_QUAD__SHIFT 0x1f
+#define DB_SUBTILE_CONTROL__MSAA1_X_MASK 0x3
+#define DB_SUBTILE_CONTROL__MSAA1_X__SHIFT 0x0
+#define DB_SUBTILE_CONTROL__MSAA1_Y_MASK 0xc
+#define DB_SUBTILE_CONTROL__MSAA1_Y__SHIFT 0x2
+#define DB_SUBTILE_CONTROL__MSAA2_X_MASK 0x30
+#define DB_SUBTILE_CONTROL__MSAA2_X__SHIFT 0x4
+#define DB_SUBTILE_CONTROL__MSAA2_Y_MASK 0xc0
+#define DB_SUBTILE_CONTROL__MSAA2_Y__SHIFT 0x6
+#define DB_SUBTILE_CONTROL__MSAA4_X_MASK 0x300
+#define DB_SUBTILE_CONTROL__MSAA4_X__SHIFT 0x8
+#define DB_SUBTILE_CONTROL__MSAA4_Y_MASK 0xc00
+#define DB_SUBTILE_CONTROL__MSAA4_Y__SHIFT 0xa
+#define DB_SUBTILE_CONTROL__MSAA8_X_MASK 0x3000
+#define DB_SUBTILE_CONTROL__MSAA8_X__SHIFT 0xc
+#define DB_SUBTILE_CONTROL__MSAA8_Y_MASK 0xc000
+#define DB_SUBTILE_CONTROL__MSAA8_Y__SHIFT 0xe
+#define DB_SUBTILE_CONTROL__MSAA16_X_MASK 0x30000
+#define DB_SUBTILE_CONTROL__MSAA16_X__SHIFT 0x10
+#define DB_SUBTILE_CONTROL__MSAA16_Y_MASK 0xc0000
+#define DB_SUBTILE_CONTROL__MSAA16_Y__SHIFT 0x12
+#define DB_FREE_CACHELINES__FREE_DTILE_DEPTH_MASK 0x7f
+#define DB_FREE_CACHELINES__FREE_DTILE_DEPTH__SHIFT 0x0
+#define DB_FREE_CACHELINES__FREE_PLANE_DEPTH_MASK 0x3f80
+#define DB_FREE_CACHELINES__FREE_PLANE_DEPTH__SHIFT 0x7
+#define DB_FREE_CACHELINES__FREE_Z_DEPTH_MASK 0x1fc000
+#define DB_FREE_CACHELINES__FREE_Z_DEPTH__SHIFT 0xe
+#define DB_FREE_CACHELINES__FREE_HTILE_DEPTH_MASK 0x1e00000
+#define DB_FREE_CACHELINES__FREE_HTILE_DEPTH__SHIFT 0x15
+#define DB_FREE_CACHELINES__QUAD_READ_REQS_MASK 0xfe000000
+#define DB_FREE_CACHELINES__QUAD_READ_REQS__SHIFT 0x19
+#define DB_FIFO_DEPTH1__MI_RDREQ_FIFO_DEPTH_MASK 0x1f
+#define DB_FIFO_DEPTH1__MI_RDREQ_FIFO_DEPTH__SHIFT 0x0
+#define DB_FIFO_DEPTH1__MI_WRREQ_FIFO_DEPTH_MASK 0x3e0
+#define DB_FIFO_DEPTH1__MI_WRREQ_FIFO_DEPTH__SHIFT 0x5
+#define DB_FIFO_DEPTH1__MCC_DEPTH_MASK 0xfc00
+#define DB_FIFO_DEPTH1__MCC_DEPTH__SHIFT 0xa
+#define DB_FIFO_DEPTH1__QC_DEPTH_MASK 0x1f0000
+#define DB_FIFO_DEPTH1__QC_DEPTH__SHIFT 0x10
+#define DB_FIFO_DEPTH1__LTILE_PROBE_FIFO_DEPTH_MASK 0x1fe00000
+#define DB_FIFO_DEPTH1__LTILE_PROBE_FIFO_DEPTH__SHIFT 0x15
+#define DB_FIFO_DEPTH2__EQUAD_FIFO_DEPTH_MASK 0xff
+#define DB_FIFO_DEPTH2__EQUAD_FIFO_DEPTH__SHIFT 0x0
+#define DB_FIFO_DEPTH2__ETILE_OP_FIFO_DEPTH_MASK 0x7f00
+#define DB_FIFO_DEPTH2__ETILE_OP_FIFO_DEPTH__SHIFT 0x8
+#define DB_FIFO_DEPTH2__LQUAD_FIFO_DEPTH_MASK 0x1ff8000
+#define DB_FIFO_DEPTH2__LQUAD_FIFO_DEPTH__SHIFT 0xf
+#define DB_FIFO_DEPTH2__LTILE_OP_FIFO_DEPTH_MASK 0xfe000000
+#define DB_FIFO_DEPTH2__LTILE_OP_FIFO_DEPTH__SHIFT 0x19
+#define DB_CGTT_CLK_CTRL_0__ON_DELAY_MASK 0xf
+#define DB_CGTT_CLK_CTRL_0__ON_DELAY__SHIFT 0x0
+#define DB_CGTT_CLK_CTRL_0__OFF_HYSTERESIS_MASK 0xff0
+#define DB_CGTT_CLK_CTRL_0__OFF_HYSTERESIS__SHIFT 0x4
+#define DB_CGTT_CLK_CTRL_0__RESERVED_MASK 0xfff000
+#define DB_CGTT_CLK_CTRL_0__RESERVED__SHIFT 0xc
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE7_MASK 0x1000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE7__SHIFT 0x18
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE6_MASK 0x2000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE6__SHIFT 0x19
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE5_MASK 0x4000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE5__SHIFT 0x1a
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE4_MASK 0x8000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE4__SHIFT 0x1b
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE3_MASK 0x10000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE3__SHIFT 0x1c
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE2_MASK 0x20000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE2__SHIFT 0x1d
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE1_MASK 0x40000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE1__SHIFT 0x1e
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE0_MASK 0x80000000
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE0__SHIFT 0x1f
+#define DB_ZPASS_COUNT_LOW__COUNT_LOW_MASK 0xffffffff
+#define DB_ZPASS_COUNT_LOW__COUNT_LOW__SHIFT 0x0
+#define DB_ZPASS_COUNT_HI__COUNT_HI_MASK 0x7fffffff
+#define DB_ZPASS_COUNT_HI__COUNT_HI__SHIFT 0x0
+#define DB_RING_CONTROL__COUNTER_CONTROL_MASK 0x3
+#define DB_RING_CONTROL__COUNTER_CONTROL__SHIFT 0x0
+#define DB_READ_DEBUG_0__BUSY_DATA0_MASK 0xffffffff
+#define DB_READ_DEBUG_0__BUSY_DATA0__SHIFT 0x0
+#define DB_READ_DEBUG_1__BUSY_DATA1_MASK 0xffffffff
+#define DB_READ_DEBUG_1__BUSY_DATA1__SHIFT 0x0
+#define DB_READ_DEBUG_2__BUSY_DATA2_MASK 0xffffffff
+#define DB_READ_DEBUG_2__BUSY_DATA2__SHIFT 0x0
+#define DB_READ_DEBUG_3__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_3__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_4__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_4__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_5__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_5__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_6__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_6__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_7__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_7__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_8__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_8__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_9__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_9__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_A__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_A__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_B__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_B__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_C__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_C__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_D__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_D__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_E__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_E__DEBUG_DATA__SHIFT 0x0
+#define DB_READ_DEBUG_F__DEBUG_DATA_MASK 0xffffffff
+#define DB_READ_DEBUG_F__DEBUG_DATA__SHIFT 0x0
+#define DB_OCCLUSION_COUNT0_LOW__COUNT_LOW_MASK 0xffffffff
+#define DB_OCCLUSION_COUNT0_LOW__COUNT_LOW__SHIFT 0x0
+#define DB_OCCLUSION_COUNT0_HI__COUNT_HI_MASK 0x7fffffff
+#define DB_OCCLUSION_COUNT0_HI__COUNT_HI__SHIFT 0x0
+#define DB_OCCLUSION_COUNT1_LOW__COUNT_LOW_MASK 0xffffffff
+#define DB_OCCLUSION_COUNT1_LOW__COUNT_LOW__SHIFT 0x0
+#define DB_OCCLUSION_COUNT1_HI__COUNT_HI_MASK 0x7fffffff
+#define DB_OCCLUSION_COUNT1_HI__COUNT_HI__SHIFT 0x0
+#define DB_OCCLUSION_COUNT2_LOW__COUNT_LOW_MASK 0xffffffff
+#define DB_OCCLUSION_COUNT2_LOW__COUNT_LOW__SHIFT 0x0
+#define DB_OCCLUSION_COUNT2_HI__COUNT_HI_MASK 0x7fffffff
+#define DB_OCCLUSION_COUNT2_HI__COUNT_HI__SHIFT 0x0
+#define DB_OCCLUSION_COUNT3_LOW__COUNT_LOW_MASK 0xffffffff
+#define DB_OCCLUSION_COUNT3_LOW__COUNT_LOW__SHIFT 0x0
+#define DB_OCCLUSION_COUNT3_HI__COUNT_HI_MASK 0x7fffffff
+#define DB_OCCLUSION_COUNT3_HI__COUNT_HI__SHIFT 0x0
+#define CC_RB_REDUNDANCY__FAILED_RB0_MASK 0xf00
+#define CC_RB_REDUNDANCY__FAILED_RB0__SHIFT 0x8
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY0_MASK 0x1000
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY0__SHIFT 0xc
+#define CC_RB_REDUNDANCY__FAILED_RB1_MASK 0xf0000
+#define CC_RB_REDUNDANCY__FAILED_RB1__SHIFT 0x10
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY1_MASK 0x100000
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY1__SHIFT 0x14
+#define CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0xff0000
+#define CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x10
+#define GC_USER_RB_REDUNDANCY__FAILED_RB0_MASK 0xf00
+#define GC_USER_RB_REDUNDANCY__FAILED_RB0__SHIFT 0x8
+#define GC_USER_RB_REDUNDANCY__EN_REDUNDANCY0_MASK 0x1000
+#define GC_USER_RB_REDUNDANCY__EN_REDUNDANCY0__SHIFT 0xc
+#define GC_USER_RB_REDUNDANCY__FAILED_RB1_MASK 0xf0000
+#define GC_USER_RB_REDUNDANCY__FAILED_RB1__SHIFT 0x10
+#define GC_USER_RB_REDUNDANCY__EN_REDUNDANCY1_MASK 0x100000
+#define GC_USER_RB_REDUNDANCY__EN_REDUNDANCY1__SHIFT 0x14
+#define GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0xff0000
+#define GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x10
+#define GB_ADDR_CONFIG__NUM_PIPES_MASK 0x7
+#define GB_ADDR_CONFIG__NUM_PIPES__SHIFT 0x0
+#define GB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x70
+#define GB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x4
+#define GB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x700
+#define GB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x8
+#define GB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x3000
+#define GB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0xc
+#define GB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x70000
+#define GB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x10
+#define GB_ADDR_CONFIG__NUM_GPUS_MASK 0x700000
+#define GB_ADDR_CONFIG__NUM_GPUS__SHIFT 0x14
+#define GB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x3000000
+#define GB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x18
+#define GB_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000
+#define GB_ADDR_CONFIG__ROW_SIZE__SHIFT 0x1c
+#define GB_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000
+#define GB_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x1e
+#define GB_BACKEND_MAP__BACKEND_MAP_MASK 0xffffffff
+#define GB_BACKEND_MAP__BACKEND_MAP__SHIFT 0x0
+#define GB_GPU_ID__GPU_ID_MASK 0xf
+#define GB_GPU_ID__GPU_ID__SHIFT 0x0
+#define CC_RB_DAISY_CHAIN__RB_0_MASK 0xf
+#define CC_RB_DAISY_CHAIN__RB_0__SHIFT 0x0
+#define CC_RB_DAISY_CHAIN__RB_1_MASK 0xf0
+#define CC_RB_DAISY_CHAIN__RB_1__SHIFT 0x4
+#define CC_RB_DAISY_CHAIN__RB_2_MASK 0xf00
+#define CC_RB_DAISY_CHAIN__RB_2__SHIFT 0x8
+#define CC_RB_DAISY_CHAIN__RB_3_MASK 0xf000
+#define CC_RB_DAISY_CHAIN__RB_3__SHIFT 0xc
+#define CC_RB_DAISY_CHAIN__RB_4_MASK 0xf0000
+#define CC_RB_DAISY_CHAIN__RB_4__SHIFT 0x10
+#define CC_RB_DAISY_CHAIN__RB_5_MASK 0xf00000
+#define CC_RB_DAISY_CHAIN__RB_5__SHIFT 0x14
+#define CC_RB_DAISY_CHAIN__RB_6_MASK 0xf000000
+#define CC_RB_DAISY_CHAIN__RB_6__SHIFT 0x18
+#define CC_RB_DAISY_CHAIN__RB_7_MASK 0xf0000000
+#define CC_RB_DAISY_CHAIN__RB_7__SHIFT 0x1c
+#define GB_TILE_MODE0__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE0__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE0__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE0__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE0__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE0__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE0__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE0__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE0__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE0__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE1__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE1__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE1__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE1__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE1__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE1__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE1__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE1__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE1__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE1__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE2__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE2__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE2__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE2__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE2__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE2__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE2__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE2__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE2__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE2__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE3__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE3__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE3__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE3__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE3__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE3__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE3__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE3__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE3__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE3__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE4__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE4__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE4__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE4__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE4__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE4__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE4__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE4__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE4__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE4__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE5__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE5__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE5__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE5__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE5__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE5__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE5__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE5__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE5__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE5__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE6__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE6__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE6__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE6__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE6__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE6__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE6__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE6__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE6__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE6__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE7__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE7__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE7__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE7__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE7__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE7__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE7__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE7__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE7__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE7__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE8__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE8__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE8__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE8__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE8__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE8__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE8__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE8__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE8__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE8__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE9__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE9__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE9__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE9__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE9__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE9__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE9__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE9__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE9__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE9__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE10__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE10__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE10__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE10__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE10__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE10__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE10__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE10__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE10__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE10__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE11__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE11__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE11__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE11__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE11__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE11__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE11__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE11__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE11__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE11__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE12__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE12__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE12__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE12__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE12__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE12__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE12__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE12__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE12__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE12__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE13__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE13__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE13__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE13__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE13__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE13__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE13__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE13__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE13__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE13__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE14__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE14__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE14__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE14__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE14__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE14__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE14__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE14__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE14__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE14__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE15__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE15__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE15__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE15__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE15__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE15__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE15__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE15__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE15__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE15__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE16__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE16__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE16__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE16__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE16__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE16__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE16__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE16__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE16__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE16__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE17__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE17__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE17__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE17__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE17__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE17__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE17__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE17__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE17__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE17__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE18__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE18__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE18__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE18__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE18__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE18__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE18__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE18__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE18__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE18__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE19__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE19__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE19__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE19__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE19__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE19__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE19__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE19__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE19__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE19__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE20__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE20__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE20__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE20__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE20__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE20__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE20__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE20__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE20__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE20__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE21__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE21__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE21__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE21__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE21__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE21__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE21__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE21__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE21__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE21__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE22__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE22__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE22__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE22__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE22__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE22__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE22__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE22__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE22__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE22__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE23__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE23__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE23__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE23__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE23__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE23__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE23__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE23__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE23__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE23__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE24__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE24__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE24__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE24__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE24__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE24__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE24__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE24__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE24__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE24__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE25__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE25__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE25__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE25__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE25__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE25__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE25__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE25__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE25__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE25__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE26__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE26__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE26__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE26__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE26__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE26__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE26__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE26__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE26__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE26__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE27__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE27__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE27__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE27__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE27__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE27__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE27__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE27__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE27__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE27__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE28__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE28__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE28__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE28__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE28__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE28__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE28__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE28__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE28__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE28__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE29__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE29__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE29__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE29__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE29__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE29__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE29__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE29__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE29__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE29__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE30__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE30__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE30__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE30__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE30__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE30__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE30__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE30__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE30__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE30__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_TILE_MODE31__ARRAY_MODE_MASK 0x3c
+#define GB_TILE_MODE31__ARRAY_MODE__SHIFT 0x2
+#define GB_TILE_MODE31__PIPE_CONFIG_MASK 0x7c0
+#define GB_TILE_MODE31__PIPE_CONFIG__SHIFT 0x6
+#define GB_TILE_MODE31__TILE_SPLIT_MASK 0x3800
+#define GB_TILE_MODE31__TILE_SPLIT__SHIFT 0xb
+#define GB_TILE_MODE31__MICRO_TILE_MODE_NEW_MASK 0x1c00000
+#define GB_TILE_MODE31__MICRO_TILE_MODE_NEW__SHIFT 0x16
+#define GB_TILE_MODE31__SAMPLE_SPLIT_MASK 0x6000000
+#define GB_TILE_MODE31__SAMPLE_SPLIT__SHIFT 0x19
+#define GB_MACROTILE_MODE0__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE0__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE0__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE0__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE0__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE0__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE0__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE0__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE1__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE1__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE1__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE1__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE1__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE1__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE1__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE1__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE2__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE2__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE2__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE2__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE2__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE2__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE2__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE2__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE3__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE3__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE3__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE3__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE3__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE3__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE3__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE3__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE4__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE4__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE4__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE4__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE4__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE4__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE4__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE4__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE5__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE5__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE5__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE5__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE5__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE5__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE5__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE5__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE6__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE6__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE6__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE6__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE6__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE6__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE6__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE6__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE7__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE7__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE7__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE7__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE7__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE7__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE7__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE7__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE8__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE8__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE8__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE8__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE8__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE8__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE8__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE8__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE9__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE9__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE9__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE9__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE9__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE9__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE9__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE9__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE10__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE10__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE10__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE10__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE10__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE10__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE10__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE10__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE11__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE11__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE11__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE11__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE11__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE11__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE11__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE11__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE12__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE12__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE12__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE12__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE12__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE12__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE12__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE12__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE13__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE13__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE13__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE13__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE13__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE13__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE13__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE13__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE14__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE14__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE14__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE14__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE14__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE14__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE14__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE14__NUM_BANKS__SHIFT 0x6
+#define GB_MACROTILE_MODE15__BANK_WIDTH_MASK 0x3
+#define GB_MACROTILE_MODE15__BANK_WIDTH__SHIFT 0x0
+#define GB_MACROTILE_MODE15__BANK_HEIGHT_MASK 0xc
+#define GB_MACROTILE_MODE15__BANK_HEIGHT__SHIFT 0x2
+#define GB_MACROTILE_MODE15__MACRO_TILE_ASPECT_MASK 0x30
+#define GB_MACROTILE_MODE15__MACRO_TILE_ASPECT__SHIFT 0x4
+#define GB_MACROTILE_MODE15__NUM_BANKS_MASK 0xc0
+#define GB_MACROTILE_MODE15__NUM_BANKS__SHIFT 0x6
+#define GB_EDC_MODE__FORCE_SEC_ON_DED_MASK 0x10000
+#define GB_EDC_MODE__FORCE_SEC_ON_DED__SHIFT 0x10
+#define GB_EDC_MODE__DED_MODE_MASK 0x300000
+#define GB_EDC_MODE__DED_MODE__SHIFT 0x14
+#define GB_EDC_MODE__PROP_FED_MASK 0x20000000
+#define GB_EDC_MODE__PROP_FED__SHIFT 0x1d
+#define GB_EDC_MODE__BYPASS_MASK 0x80000000
+#define GB_EDC_MODE__BYPASS__SHIFT 0x1f
+#define CC_GC_EDC_CONFIG__DIS_EDC_MASK 0x2
+#define CC_GC_EDC_CONFIG__DIS_EDC__SHIFT 0x1
+#define RAS_SIGNATURE_CONTROL__ENABLE_MASK 0x1
+#define RAS_SIGNATURE_CONTROL__ENABLE__SHIFT 0x0
+#define RAS_SIGNATURE_MASK__INPUT_BUS_MASK_MASK 0xffffffff
+#define RAS_SIGNATURE_MASK__INPUT_BUS_MASK__SHIFT 0x0
+#define RAS_SX_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_SX_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_SX_SIGNATURE1__SIGNATURE_MASK 0xffffffff
+#define RAS_SX_SIGNATURE1__SIGNATURE__SHIFT 0x0
+#define RAS_SX_SIGNATURE2__SIGNATURE_MASK 0xffffffff
+#define RAS_SX_SIGNATURE2__SIGNATURE__SHIFT 0x0
+#define RAS_SX_SIGNATURE3__SIGNATURE_MASK 0xffffffff
+#define RAS_SX_SIGNATURE3__SIGNATURE__SHIFT 0x0
+#define RAS_DB_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_DB_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_PA_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_PA_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_VGT_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_VGT_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE1__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE1__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE2__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE2__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE3__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE3__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE4__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE4__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE5__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE5__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE6__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE6__SIGNATURE__SHIFT 0x0
+#define RAS_SC_SIGNATURE7__SIGNATURE_MASK 0xffffffff
+#define RAS_SC_SIGNATURE7__SIGNATURE__SHIFT 0x0
+#define RAS_IA_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_IA_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_IA_SIGNATURE1__SIGNATURE_MASK 0xffffffff
+#define RAS_IA_SIGNATURE1__SIGNATURE__SHIFT 0x0
+#define RAS_SPI_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_SPI_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_SPI_SIGNATURE1__SIGNATURE_MASK 0xffffffff
+#define RAS_SPI_SIGNATURE1__SIGNATURE__SHIFT 0x0
+#define RAS_TA_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_TA_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_TD_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_TD_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_CB_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_CB_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_BCI_SIGNATURE0__SIGNATURE_MASK 0xffffffff
+#define RAS_BCI_SIGNATURE0__SIGNATURE__SHIFT 0x0
+#define RAS_BCI_SIGNATURE1__SIGNATURE_MASK 0xffffffff
+#define RAS_BCI_SIGNATURE1__SIGNATURE__SHIFT 0x0
+#define RAS_TA_SIGNATURE1__SIGNATURE_MASK 0xffffffff
+#define RAS_TA_SIGNATURE1__SIGNATURE__SHIFT 0x0
+#define GRBM_HYP_CAM_INDEX__CAM_INDEX_MASK 0x7
+#define GRBM_HYP_CAM_INDEX__CAM_INDEX__SHIFT 0x0
+#define GRBM_CAM_INDEX__CAM_INDEX_MASK 0x7
+#define GRBM_CAM_INDEX__CAM_INDEX__SHIFT 0x0
+#define GRBM_HYP_CAM_DATA__CAM_ADDR_MASK 0xffff
+#define GRBM_HYP_CAM_DATA__CAM_ADDR__SHIFT 0x0
+#define GRBM_HYP_CAM_DATA__CAM_REMAPADDR_MASK 0xffff0000
+#define GRBM_HYP_CAM_DATA__CAM_REMAPADDR__SHIFT 0x10
+#define GRBM_CAM_DATA__CAM_ADDR_MASK 0xffff
+#define GRBM_CAM_DATA__CAM_ADDR__SHIFT 0x0
+#define GRBM_CAM_DATA__CAM_REMAPADDR_MASK 0xffff0000
+#define GRBM_CAM_DATA__CAM_REMAPADDR__SHIFT 0x10
+#define GRBM_CNTL__READ_TIMEOUT_MASK 0xff
+#define GRBM_CNTL__READ_TIMEOUT__SHIFT 0x0
+#define GRBM_CNTL__REPORT_LAST_RDERR_MASK 0x80000000
+#define GRBM_CNTL__REPORT_LAST_RDERR__SHIFT 0x1f
+#define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD_MASK 0x3f
+#define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD__SHIFT 0x0
+#define GRBM_SKEW_CNTL__SKEW_COUNT_MASK 0xfc0
+#define GRBM_SKEW_CNTL__SKEW_COUNT__SHIFT 0x6
+#define GRBM_PWR_CNTL__ALL_REQ_TYPE_MASK 0x3
+#define GRBM_PWR_CNTL__ALL_REQ_TYPE__SHIFT 0x0
+#define GRBM_PWR_CNTL__GFX_REQ_TYPE_MASK 0xc
+#define GRBM_PWR_CNTL__GFX_REQ_TYPE__SHIFT 0x2
+#define GRBM_PWR_CNTL__ALL_RSP_TYPE_MASK 0x30
+#define GRBM_PWR_CNTL__ALL_RSP_TYPE__SHIFT 0x4
+#define GRBM_PWR_CNTL__GFX_RSP_TYPE_MASK 0xc0
+#define GRBM_PWR_CNTL__GFX_RSP_TYPE__SHIFT 0x6
+#define GRBM_PWR_CNTL__GFX_REQ_EN_MASK 0x4000
+#define GRBM_PWR_CNTL__GFX_REQ_EN__SHIFT 0xe
+#define GRBM_PWR_CNTL__ALL_REQ_EN_MASK 0x8000
+#define GRBM_PWR_CNTL__ALL_REQ_EN__SHIFT 0xf
+#define GRBM_STATUS__ME0PIPE0_CMDFIFO_AVAIL_MASK 0xf
+#define GRBM_STATUS__ME0PIPE0_CMDFIFO_AVAIL__SHIFT 0x0
+#define GRBM_STATUS__SRBM_RQ_PENDING_MASK 0x20
+#define GRBM_STATUS__SRBM_RQ_PENDING__SHIFT 0x5
+#define GRBM_STATUS__ME0PIPE0_CF_RQ_PENDING_MASK 0x80
+#define GRBM_STATUS__ME0PIPE0_CF_RQ_PENDING__SHIFT 0x7
+#define GRBM_STATUS__ME0PIPE0_PF_RQ_PENDING_MASK 0x100
+#define GRBM_STATUS__ME0PIPE0_PF_RQ_PENDING__SHIFT 0x8
+#define GRBM_STATUS__GDS_DMA_RQ_PENDING_MASK 0x200
+#define GRBM_STATUS__GDS_DMA_RQ_PENDING__SHIFT 0x9
+#define GRBM_STATUS__DB_CLEAN_MASK 0x1000
+#define GRBM_STATUS__DB_CLEAN__SHIFT 0xc
+#define GRBM_STATUS__CB_CLEAN_MASK 0x2000
+#define GRBM_STATUS__CB_CLEAN__SHIFT 0xd
+#define GRBM_STATUS__TA_BUSY_MASK 0x4000
+#define GRBM_STATUS__TA_BUSY__SHIFT 0xe
+#define GRBM_STATUS__GDS_BUSY_MASK 0x8000
+#define GRBM_STATUS__GDS_BUSY__SHIFT 0xf
+#define GRBM_STATUS__WD_BUSY_NO_DMA_MASK 0x10000
+#define GRBM_STATUS__WD_BUSY_NO_DMA__SHIFT 0x10
+#define GRBM_STATUS__VGT_BUSY_MASK 0x20000
+#define GRBM_STATUS__VGT_BUSY__SHIFT 0x11
+#define GRBM_STATUS__IA_BUSY_NO_DMA_MASK 0x40000
+#define GRBM_STATUS__IA_BUSY_NO_DMA__SHIFT 0x12
+#define GRBM_STATUS__IA_BUSY_MASK 0x80000
+#define GRBM_STATUS__IA_BUSY__SHIFT 0x13
+#define GRBM_STATUS__SX_BUSY_MASK 0x100000
+#define GRBM_STATUS__SX_BUSY__SHIFT 0x14
+#define GRBM_STATUS__WD_BUSY_MASK 0x200000
+#define GRBM_STATUS__WD_BUSY__SHIFT 0x15
+#define GRBM_STATUS__SPI_BUSY_MASK 0x400000
+#define GRBM_STATUS__SPI_BUSY__SHIFT 0x16
+#define GRBM_STATUS__BCI_BUSY_MASK 0x800000
+#define GRBM_STATUS__BCI_BUSY__SHIFT 0x17
+#define GRBM_STATUS__SC_BUSY_MASK 0x1000000
+#define GRBM_STATUS__SC_BUSY__SHIFT 0x18
+#define GRBM_STATUS__PA_BUSY_MASK 0x2000000
+#define GRBM_STATUS__PA_BUSY__SHIFT 0x19
+#define GRBM_STATUS__DB_BUSY_MASK 0x4000000
+#define GRBM_STATUS__DB_BUSY__SHIFT 0x1a
+#define GRBM_STATUS__CP_COHERENCY_BUSY_MASK 0x10000000
+#define GRBM_STATUS__CP_COHERENCY_BUSY__SHIFT 0x1c
+#define GRBM_STATUS__CP_BUSY_MASK 0x20000000
+#define GRBM_STATUS__CP_BUSY__SHIFT 0x1d
+#define GRBM_STATUS__CB_BUSY_MASK 0x40000000
+#define GRBM_STATUS__CB_BUSY__SHIFT 0x1e
+#define GRBM_STATUS__GUI_ACTIVE_MASK 0x80000000
+#define GRBM_STATUS__GUI_ACTIVE__SHIFT 0x1f
+#define GRBM_STATUS2__ME0PIPE1_CMDFIFO_AVAIL_MASK 0xf
+#define GRBM_STATUS2__ME0PIPE1_CMDFIFO_AVAIL__SHIFT 0x0
+#define GRBM_STATUS2__ME0PIPE1_CF_RQ_PENDING_MASK 0x10
+#define GRBM_STATUS2__ME0PIPE1_CF_RQ_PENDING__SHIFT 0x4
+#define GRBM_STATUS2__ME0PIPE1_PF_RQ_PENDING_MASK 0x20
+#define GRBM_STATUS2__ME0PIPE1_PF_RQ_PENDING__SHIFT 0x5
+#define GRBM_STATUS2__ME1PIPE0_RQ_PENDING_MASK 0x40
+#define GRBM_STATUS2__ME1PIPE0_RQ_PENDING__SHIFT 0x6
+#define GRBM_STATUS2__ME1PIPE1_RQ_PENDING_MASK 0x80
+#define GRBM_STATUS2__ME1PIPE1_RQ_PENDING__SHIFT 0x7
+#define GRBM_STATUS2__ME1PIPE2_RQ_PENDING_MASK 0x100
+#define GRBM_STATUS2__ME1PIPE2_RQ_PENDING__SHIFT 0x8
+#define GRBM_STATUS2__ME1PIPE3_RQ_PENDING_MASK 0x200
+#define GRBM_STATUS2__ME1PIPE3_RQ_PENDING__SHIFT 0x9
+#define GRBM_STATUS2__ME2PIPE0_RQ_PENDING_MASK 0x400
+#define GRBM_STATUS2__ME2PIPE0_RQ_PENDING__SHIFT 0xa
+#define GRBM_STATUS2__ME2PIPE1_RQ_PENDING_MASK 0x800
+#define GRBM_STATUS2__ME2PIPE1_RQ_PENDING__SHIFT 0xb
+#define GRBM_STATUS2__ME2PIPE2_RQ_PENDING_MASK 0x1000
+#define GRBM_STATUS2__ME2PIPE2_RQ_PENDING__SHIFT 0xc
+#define GRBM_STATUS2__ME2PIPE3_RQ_PENDING_MASK 0x2000
+#define GRBM_STATUS2__ME2PIPE3_RQ_PENDING__SHIFT 0xd
+#define GRBM_STATUS2__RLC_RQ_PENDING_MASK 0x4000
+#define GRBM_STATUS2__RLC_RQ_PENDING__SHIFT 0xe
+#define GRBM_STATUS2__RLC_BUSY_MASK 0x1000000
+#define GRBM_STATUS2__RLC_BUSY__SHIFT 0x18
+#define GRBM_STATUS2__TC_BUSY_MASK 0x2000000
+#define GRBM_STATUS2__TC_BUSY__SHIFT 0x19
+#define GRBM_STATUS2__TCC_CC_RESIDENT_MASK 0x4000000
+#define GRBM_STATUS2__TCC_CC_RESIDENT__SHIFT 0x1a
+#define GRBM_STATUS2__CPF_BUSY_MASK 0x10000000
+#define GRBM_STATUS2__CPF_BUSY__SHIFT 0x1c
+#define GRBM_STATUS2__CPC_BUSY_MASK 0x20000000
+#define GRBM_STATUS2__CPC_BUSY__SHIFT 0x1d
+#define GRBM_STATUS2__CPG_BUSY_MASK 0x40000000
+#define GRBM_STATUS2__CPG_BUSY__SHIFT 0x1e
+#define GRBM_STATUS_SE0__DB_CLEAN_MASK 0x2
+#define GRBM_STATUS_SE0__DB_CLEAN__SHIFT 0x1
+#define GRBM_STATUS_SE0__CB_CLEAN_MASK 0x4
+#define GRBM_STATUS_SE0__CB_CLEAN__SHIFT 0x2
+#define GRBM_STATUS_SE0__BCI_BUSY_MASK 0x400000
+#define GRBM_STATUS_SE0__BCI_BUSY__SHIFT 0x16
+#define GRBM_STATUS_SE0__VGT_BUSY_MASK 0x800000
+#define GRBM_STATUS_SE0__VGT_BUSY__SHIFT 0x17
+#define GRBM_STATUS_SE0__PA_BUSY_MASK 0x1000000
+#define GRBM_STATUS_SE0__PA_BUSY__SHIFT 0x18
+#define GRBM_STATUS_SE0__TA_BUSY_MASK 0x2000000
+#define GRBM_STATUS_SE0__TA_BUSY__SHIFT 0x19
+#define GRBM_STATUS_SE0__SX_BUSY_MASK 0x4000000
+#define GRBM_STATUS_SE0__SX_BUSY__SHIFT 0x1a
+#define GRBM_STATUS_SE0__SPI_BUSY_MASK 0x8000000
+#define GRBM_STATUS_SE0__SPI_BUSY__SHIFT 0x1b
+#define GRBM_STATUS_SE0__SC_BUSY_MASK 0x20000000
+#define GRBM_STATUS_SE0__SC_BUSY__SHIFT 0x1d
+#define GRBM_STATUS_SE0__DB_BUSY_MASK 0x40000000
+#define GRBM_STATUS_SE0__DB_BUSY__SHIFT 0x1e
+#define GRBM_STATUS_SE0__CB_BUSY_MASK 0x80000000
+#define GRBM_STATUS_SE0__CB_BUSY__SHIFT 0x1f
+#define GRBM_STATUS_SE1__DB_CLEAN_MASK 0x2
+#define GRBM_STATUS_SE1__DB_CLEAN__SHIFT 0x1
+#define GRBM_STATUS_SE1__CB_CLEAN_MASK 0x4
+#define GRBM_STATUS_SE1__CB_CLEAN__SHIFT 0x2
+#define GRBM_STATUS_SE1__BCI_BUSY_MASK 0x400000
+#define GRBM_STATUS_SE1__BCI_BUSY__SHIFT 0x16
+#define GRBM_STATUS_SE1__VGT_BUSY_MASK 0x800000
+#define GRBM_STATUS_SE1__VGT_BUSY__SHIFT 0x17
+#define GRBM_STATUS_SE1__PA_BUSY_MASK 0x1000000
+#define GRBM_STATUS_SE1__PA_BUSY__SHIFT 0x18
+#define GRBM_STATUS_SE1__TA_BUSY_MASK 0x2000000
+#define GRBM_STATUS_SE1__TA_BUSY__SHIFT 0x19
+#define GRBM_STATUS_SE1__SX_BUSY_MASK 0x4000000
+#define GRBM_STATUS_SE1__SX_BUSY__SHIFT 0x1a
+#define GRBM_STATUS_SE1__SPI_BUSY_MASK 0x8000000
+#define GRBM_STATUS_SE1__SPI_BUSY__SHIFT 0x1b
+#define GRBM_STATUS_SE1__SC_BUSY_MASK 0x20000000
+#define GRBM_STATUS_SE1__SC_BUSY__SHIFT 0x1d
+#define GRBM_STATUS_SE1__DB_BUSY_MASK 0x40000000
+#define GRBM_STATUS_SE1__DB_BUSY__SHIFT 0x1e
+#define GRBM_STATUS_SE1__CB_BUSY_MASK 0x80000000
+#define GRBM_STATUS_SE1__CB_BUSY__SHIFT 0x1f
+#define GRBM_STATUS_SE2__DB_CLEAN_MASK 0x2
+#define GRBM_STATUS_SE2__DB_CLEAN__SHIFT 0x1
+#define GRBM_STATUS_SE2__CB_CLEAN_MASK 0x4
+#define GRBM_STATUS_SE2__CB_CLEAN__SHIFT 0x2
+#define GRBM_STATUS_SE2__BCI_BUSY_MASK 0x400000
+#define GRBM_STATUS_SE2__BCI_BUSY__SHIFT 0x16
+#define GRBM_STATUS_SE2__VGT_BUSY_MASK 0x800000
+#define GRBM_STATUS_SE2__VGT_BUSY__SHIFT 0x17
+#define GRBM_STATUS_SE2__PA_BUSY_MASK 0x1000000
+#define GRBM_STATUS_SE2__PA_BUSY__SHIFT 0x18
+#define GRBM_STATUS_SE2__TA_BUSY_MASK 0x2000000
+#define GRBM_STATUS_SE2__TA_BUSY__SHIFT 0x19
+#define GRBM_STATUS_SE2__SX_BUSY_MASK 0x4000000
+#define GRBM_STATUS_SE2__SX_BUSY__SHIFT 0x1a
+#define GRBM_STATUS_SE2__SPI_BUSY_MASK 0x8000000
+#define GRBM_STATUS_SE2__SPI_BUSY__SHIFT 0x1b
+#define GRBM_STATUS_SE2__SC_BUSY_MASK 0x20000000
+#define GRBM_STATUS_SE2__SC_BUSY__SHIFT 0x1d
+#define GRBM_STATUS_SE2__DB_BUSY_MASK 0x40000000
+#define GRBM_STATUS_SE2__DB_BUSY__SHIFT 0x1e
+#define GRBM_STATUS_SE2__CB_BUSY_MASK 0x80000000
+#define GRBM_STATUS_SE2__CB_BUSY__SHIFT 0x1f
+#define GRBM_STATUS_SE3__DB_CLEAN_MASK 0x2
+#define GRBM_STATUS_SE3__DB_CLEAN__SHIFT 0x1
+#define GRBM_STATUS_SE3__CB_CLEAN_MASK 0x4
+#define GRBM_STATUS_SE3__CB_CLEAN__SHIFT 0x2
+#define GRBM_STATUS_SE3__BCI_BUSY_MASK 0x400000
+#define GRBM_STATUS_SE3__BCI_BUSY__SHIFT 0x16
+#define GRBM_STATUS_SE3__VGT_BUSY_MASK 0x800000
+#define GRBM_STATUS_SE3__VGT_BUSY__SHIFT 0x17
+#define GRBM_STATUS_SE3__PA_BUSY_MASK 0x1000000
+#define GRBM_STATUS_SE3__PA_BUSY__SHIFT 0x18
+#define GRBM_STATUS_SE3__TA_BUSY_MASK 0x2000000
+#define GRBM_STATUS_SE3__TA_BUSY__SHIFT 0x19
+#define GRBM_STATUS_SE3__SX_BUSY_MASK 0x4000000
+#define GRBM_STATUS_SE3__SX_BUSY__SHIFT 0x1a
+#define GRBM_STATUS_SE3__SPI_BUSY_MASK 0x8000000
+#define GRBM_STATUS_SE3__SPI_BUSY__SHIFT 0x1b
+#define GRBM_STATUS_SE3__SC_BUSY_MASK 0x20000000
+#define GRBM_STATUS_SE3__SC_BUSY__SHIFT 0x1d
+#define GRBM_STATUS_SE3__DB_BUSY_MASK 0x40000000
+#define GRBM_STATUS_SE3__DB_BUSY__SHIFT 0x1e
+#define GRBM_STATUS_SE3__CB_BUSY_MASK 0x80000000
+#define GRBM_STATUS_SE3__CB_BUSY__SHIFT 0x1f
+#define GRBM_SOFT_RESET__SOFT_RESET_CP_MASK 0x1
+#define GRBM_SOFT_RESET__SOFT_RESET_CP__SHIFT 0x0
+#define GRBM_SOFT_RESET__SOFT_RESET_RLC_MASK 0x4
+#define GRBM_SOFT_RESET__SOFT_RESET_RLC__SHIFT 0x2
+#define GRBM_SOFT_RESET__SOFT_RESET_GFX_MASK 0x10000
+#define GRBM_SOFT_RESET__SOFT_RESET_GFX__SHIFT 0x10
+#define GRBM_SOFT_RESET__SOFT_RESET_CPF_MASK 0x20000
+#define GRBM_SOFT_RESET__SOFT_RESET_CPF__SHIFT 0x11
+#define GRBM_SOFT_RESET__SOFT_RESET_CPC_MASK 0x40000
+#define GRBM_SOFT_RESET__SOFT_RESET_CPC__SHIFT 0x12
+#define GRBM_SOFT_RESET__SOFT_RESET_CPG_MASK 0x80000
+#define GRBM_SOFT_RESET__SOFT_RESET_CPG__SHIFT 0x13
+#define GRBM_SOFT_RESET__SOFT_RESET_CAC_MASK 0x100000
+#define GRBM_SOFT_RESET__SOFT_RESET_CAC__SHIFT 0x14
+#define GRBM_DEBUG_CNTL__GRBM_DEBUG_INDEX_MASK 0x3f
+#define GRBM_DEBUG_CNTL__GRBM_DEBUG_INDEX__SHIFT 0x0
+#define GRBM_DEBUG_DATA__DATA_MASK 0xffffffff
+#define GRBM_DEBUG_DATA__DATA__SHIFT 0x0
+#define GRBM_CGTT_CLK_CNTL__ON_DELAY_MASK 0xf
+#define GRBM_CGTT_CLK_CNTL__ON_DELAY__SHIFT 0x0
+#define GRBM_CGTT_CLK_CNTL__OFF_HYSTERESIS_MASK 0xff0
+#define GRBM_CGTT_CLK_CNTL__OFF_HYSTERESIS__SHIFT 0x4
+#define GRBM_CGTT_CLK_CNTL__SOFT_OVERRIDE_DYN_MASK 0x40000000
+#define GRBM_CGTT_CLK_CNTL__SOFT_OVERRIDE_DYN__SHIFT 0x1e
+#define GRBM_GFX_INDEX__INSTANCE_INDEX_MASK 0xff
+#define GRBM_GFX_INDEX__INSTANCE_INDEX__SHIFT 0x0
+#define GRBM_GFX_INDEX__SH_INDEX_MASK 0xff00
+#define GRBM_GFX_INDEX__SH_INDEX__SHIFT 0x8
+#define GRBM_GFX_INDEX__SE_INDEX_MASK 0xff0000
+#define GRBM_GFX_INDEX__SE_INDEX__SHIFT 0x10
+#define GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK 0x20000000
+#define GRBM_GFX_INDEX__SH_BROADCAST_WRITES__SHIFT 0x1d
+#define GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK 0x40000000
+#define GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES__SHIFT 0x1e
+#define GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK 0x80000000
+#define GRBM_GFX_INDEX__SE_BROADCAST_WRITES__SHIFT 0x1f
+#define GRBM_GFX_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0xf
+#define GRBM_GFX_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x0
+#define GRBM_GFX_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x1f00
+#define GRBM_GFX_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x8
+#define GRBM_WAIT_IDLE_CLOCKS__WAIT_IDLE_CLOCKS_MASK 0xff
+#define GRBM_WAIT_IDLE_CLOCKS__WAIT_IDLE_CLOCKS__SHIFT 0x0
+#define GRBM_DEBUG__IGNORE_RDY_MASK 0x2
+#define GRBM_DEBUG__IGNORE_RDY__SHIFT 0x1
+#define GRBM_DEBUG__IGNORE_FAO_MASK 0x20
+#define GRBM_DEBUG__IGNORE_FAO__SHIFT 0x5
+#define GRBM_DEBUG__DISABLE_READ_TIMEOUT_MASK 0x40
+#define GRBM_DEBUG__DISABLE_READ_TIMEOUT__SHIFT 0x6
+#define GRBM_DEBUG__SNAPSHOT_FREE_CNTRS_MASK 0x80
+#define GRBM_DEBUG__SNAPSHOT_FREE_CNTRS__SHIFT 0x7
+#define GRBM_DEBUG__HYSTERESIS_GUI_ACTIVE_MASK 0xf00
+#define GRBM_DEBUG__HYSTERESIS_GUI_ACTIVE__SHIFT 0x8
+#define GRBM_DEBUG__GFX_CLOCK_DOMAIN_OVERRIDE_MASK 0x1000
+#define GRBM_DEBUG__GFX_CLOCK_DOMAIN_OVERRIDE__SHIFT 0xc
+#define GRBM_DEBUG__GRBM_TRAP_ENABLE_MASK 0x2000
+#define GRBM_DEBUG__GRBM_TRAP_ENABLE__SHIFT 0xd
+#define GRBM_DEBUG__DEBUG_BUS_FGCG_EN_MASK 0x80000000
+#define GRBM_DEBUG__DEBUG_BUS_FGCG_EN__SHIFT 0x1f
+#define GRBM_DEBUG_SNAPSHOT__CPF_RDY_MASK 0x1
+#define GRBM_DEBUG_SNAPSHOT__CPF_RDY__SHIFT 0x0
+#define GRBM_DEBUG_SNAPSHOT__CPG_RDY_MASK 0x2
+#define GRBM_DEBUG_SNAPSHOT__CPG_RDY__SHIFT 0x1
+#define GRBM_DEBUG_SNAPSHOT__SRBM_RDY_MASK 0x4
+#define GRBM_DEBUG_SNAPSHOT__SRBM_RDY__SHIFT 0x2
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE0_RDY_MASK 0x8
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE0_RDY__SHIFT 0x3
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE1_RDY_MASK 0x10
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE1_RDY__SHIFT 0x4
+#define GRBM_DEBUG_SNAPSHOT__GDS_RDY_MASK 0x20
+#define GRBM_DEBUG_SNAPSHOT__GDS_RDY__SHIFT 0x5
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY0_MASK 0x40
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY0__SHIFT 0x6
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY0_MASK 0x80
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY0__SHIFT 0x7
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY0_MASK 0x100
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY0__SHIFT 0x8
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY0_MASK 0x200
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY0__SHIFT 0x9
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY0_MASK 0x400
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY0__SHIFT 0xa
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY0_MASK 0x800
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY0__SHIFT 0xb
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY0_MASK 0x1000
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY0__SHIFT 0xc
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY0_MASK 0x2000
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY0__SHIFT 0xd
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY1_MASK 0x4000
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY1__SHIFT 0xe
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY1_MASK 0x8000
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY1__SHIFT 0xf
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY1_MASK 0x10000
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY1__SHIFT 0x10
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY1_MASK 0x20000
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY1__SHIFT 0x11
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY1_MASK 0x40000
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY1__SHIFT 0x12
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY1_MASK 0x80000
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY1__SHIFT 0x13
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY1_MASK 0x100000
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY1__SHIFT 0x14
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY1_MASK 0x200000
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY1__SHIFT 0x15
+#define GRBM_READ_ERROR__READ_ADDRESS_MASK 0x3fffc
+#define GRBM_READ_ERROR__READ_ADDRESS__SHIFT 0x2
+#define GRBM_READ_ERROR__READ_PIPEID_MASK 0x300000
+#define GRBM_READ_ERROR__READ_PIPEID__SHIFT 0x14
+#define GRBM_READ_ERROR__READ_MEID_MASK 0xc00000
+#define GRBM_READ_ERROR__READ_MEID__SHIFT 0x16
+#define GRBM_READ_ERROR__READ_ERROR_MASK 0x80000000
+#define GRBM_READ_ERROR__READ_ERROR__SHIFT 0x1f
+#define GRBM_READ_ERROR2__READ_REQUESTER_SRBM_MASK 0x20000
+#define GRBM_READ_ERROR2__READ_REQUESTER_SRBM__SHIFT 0x11
+#define GRBM_READ_ERROR2__READ_REQUESTER_RLC_MASK 0x40000
+#define GRBM_READ_ERROR2__READ_REQUESTER_RLC__SHIFT 0x12
+#define GRBM_READ_ERROR2__READ_REQUESTER_GDS_DMA_MASK 0x80000
+#define GRBM_READ_ERROR2__READ_REQUESTER_GDS_DMA__SHIFT 0x13
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_CF_MASK 0x100000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_CF__SHIFT 0x14
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_PF_MASK 0x200000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_PF__SHIFT 0x15
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_CF_MASK 0x400000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_CF__SHIFT 0x16
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_PF_MASK 0x800000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_PF__SHIFT 0x17
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE0_MASK 0x1000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE0__SHIFT 0x18
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE1_MASK 0x2000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE1__SHIFT 0x19
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE2_MASK 0x4000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE2__SHIFT 0x1a
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE3_MASK 0x8000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE3__SHIFT 0x1b
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE0_MASK 0x10000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE0__SHIFT 0x1c
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE1_MASK 0x20000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE1__SHIFT 0x1d
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE2_MASK 0x40000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE2__SHIFT 0x1e
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE3_MASK 0x80000000
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE3__SHIFT 0x1f
+#define GRBM_INT_CNTL__RDERR_INT_ENABLE_MASK 0x1
+#define GRBM_INT_CNTL__RDERR_INT_ENABLE__SHIFT 0x0
+#define GRBM_INT_CNTL__GUI_IDLE_INT_ENABLE_MASK 0x80000
+#define GRBM_INT_CNTL__GUI_IDLE_INT_ENABLE__SHIFT 0x13
+#define GRBM_TRAP_OP__RW_MASK 0x1
+#define GRBM_TRAP_OP__RW__SHIFT 0x0
+#define GRBM_TRAP_ADDR__DATA_MASK 0xffff
+#define GRBM_TRAP_ADDR__DATA__SHIFT 0x0
+#define GRBM_TRAP_ADDR_MSK__DATA_MASK 0xffff
+#define GRBM_TRAP_ADDR_MSK__DATA__SHIFT 0x0
+#define GRBM_TRAP_WD__DATA_MASK 0xffffffff
+#define GRBM_TRAP_WD__DATA__SHIFT 0x0
+#define GRBM_TRAP_WD_MSK__DATA_MASK 0xffffffff
+#define GRBM_TRAP_WD_MSK__DATA__SHIFT 0x0
+#define GRBM_DSM_BYPASS__BYPASS_BITS_MASK 0x3
+#define GRBM_DSM_BYPASS__BYPASS_BITS__SHIFT 0x0
+#define GRBM_DSM_BYPASS__BYPASS_EN_MASK 0x4
+#define GRBM_DSM_BYPASS__BYPASS_EN__SHIFT 0x2
+#define GRBM_WRITE_ERROR__WRITE_REQUESTER_RLC_MASK 0x1
+#define GRBM_WRITE_ERROR__WRITE_REQUESTER_RLC__SHIFT 0x0
+#define GRBM_WRITE_ERROR__WRITE_REQUESTER_SRBM_MASK 0x2
+#define GRBM_WRITE_ERROR__WRITE_REQUESTER_SRBM__SHIFT 0x1
+#define GRBM_WRITE_ERROR__WRITE_SSRCID_MASK 0x1c
+#define GRBM_WRITE_ERROR__WRITE_SSRCID__SHIFT 0x2
+#define GRBM_WRITE_ERROR__WRITE_VFID_MASK 0x1e0
+#define GRBM_WRITE_ERROR__WRITE_VFID__SHIFT 0x5
+#define GRBM_WRITE_ERROR__WRITE_VF_MASK 0x1000
+#define GRBM_WRITE_ERROR__WRITE_VF__SHIFT 0xc
+#define GRBM_WRITE_ERROR__WRITE_VMID_MASK 0x1e000
+#define GRBM_WRITE_ERROR__WRITE_VMID__SHIFT 0xd
+#define GRBM_WRITE_ERROR__WRITE_PIPEID_MASK 0x300000
+#define GRBM_WRITE_ERROR__WRITE_PIPEID__SHIFT 0x14
+#define GRBM_WRITE_ERROR__WRITE_MEID_MASK 0xc00000
+#define GRBM_WRITE_ERROR__WRITE_MEID__SHIFT 0x16
+#define GRBM_WRITE_ERROR__WRITE_ERROR_MASK 0x80000000
+#define GRBM_WRITE_ERROR__WRITE_ERROR__SHIFT 0x1f
+#define GRBM_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3f
+#define GRBM_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define GRBM_PERFCOUNTER0_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x400
+#define GRBM_PERFCOUNTER0_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0xa
+#define GRBM_PERFCOUNTER0_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x800
+#define GRBM_PERFCOUNTER0_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0xb
+#define GRBM_PERFCOUNTER0_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x1000
+#define GRBM_PERFCOUNTER0_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0xc
+#define GRBM_PERFCOUNTER0_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x2000
+#define GRBM_PERFCOUNTER0_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0xd
+#define GRBM_PERFCOUNTER0_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x4000
+#define GRBM_PERFCOUNTER0_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0xe
+#define GRBM_PERFCOUNTER0_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x10000
+#define GRBM_PERFCOUNTER0_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x10
+#define GRBM_PERFCOUNTER0_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x20000
+#define GRBM_PERFCOUNTER0_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x11
+#define GRBM_PERFCOUNTER0_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x40000
+#define GRBM_PERFCOUNTER0_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x12
+#define GRBM_PERFCOUNTER0_SELECT__GRBM_BUSY_USER_DEFINED_MASK_MASK 0x80000
+#define GRBM_PERFCOUNTER0_SELECT__GRBM_BUSY_USER_DEFINED_MASK__SHIFT 0x13
+#define GRBM_PERFCOUNTER0_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x100000
+#define GRBM_PERFCOUNTER0_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x14
+#define GRBM_PERFCOUNTER0_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x200000
+#define GRBM_PERFCOUNTER0_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x15
+#define GRBM_PERFCOUNTER0_SELECT__CP_BUSY_USER_DEFINED_MASK_MASK 0x400000
+#define GRBM_PERFCOUNTER0_SELECT__CP_BUSY_USER_DEFINED_MASK__SHIFT 0x16
+#define GRBM_PERFCOUNTER0_SELECT__IA_BUSY_USER_DEFINED_MASK_MASK 0x800000
+#define GRBM_PERFCOUNTER0_SELECT__IA_BUSY_USER_DEFINED_MASK__SHIFT 0x17
+#define GRBM_PERFCOUNTER0_SELECT__GDS_BUSY_USER_DEFINED_MASK_MASK 0x1000000
+#define GRBM_PERFCOUNTER0_SELECT__GDS_BUSY_USER_DEFINED_MASK__SHIFT 0x18
+#define GRBM_PERFCOUNTER0_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x2000000
+#define GRBM_PERFCOUNTER0_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x19
+#define GRBM_PERFCOUNTER0_SELECT__RLC_BUSY_USER_DEFINED_MASK_MASK 0x4000000
+#define GRBM_PERFCOUNTER0_SELECT__RLC_BUSY_USER_DEFINED_MASK__SHIFT 0x1a
+#define GRBM_PERFCOUNTER0_SELECT__TC_BUSY_USER_DEFINED_MASK_MASK 0x8000000
+#define GRBM_PERFCOUNTER0_SELECT__TC_BUSY_USER_DEFINED_MASK__SHIFT 0x1b
+#define GRBM_PERFCOUNTER0_SELECT__WD_BUSY_USER_DEFINED_MASK_MASK 0x10000000
+#define GRBM_PERFCOUNTER0_SELECT__WD_BUSY_USER_DEFINED_MASK__SHIFT 0x1c
+#define GRBM_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3f
+#define GRBM_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define GRBM_PERFCOUNTER1_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x400
+#define GRBM_PERFCOUNTER1_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0xa
+#define GRBM_PERFCOUNTER1_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x800
+#define GRBM_PERFCOUNTER1_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0xb
+#define GRBM_PERFCOUNTER1_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x1000
+#define GRBM_PERFCOUNTER1_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0xc
+#define GRBM_PERFCOUNTER1_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x2000
+#define GRBM_PERFCOUNTER1_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0xd
+#define GRBM_PERFCOUNTER1_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x4000
+#define GRBM_PERFCOUNTER1_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0xe
+#define GRBM_PERFCOUNTER1_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x10000
+#define GRBM_PERFCOUNTER1_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x10
+#define GRBM_PERFCOUNTER1_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x20000
+#define GRBM_PERFCOUNTER1_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x11
+#define GRBM_PERFCOUNTER1_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x40000
+#define GRBM_PERFCOUNTER1_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x12
+#define GRBM_PERFCOUNTER1_SELECT__GRBM_BUSY_USER_DEFINED_MASK_MASK 0x80000
+#define GRBM_PERFCOUNTER1_SELECT__GRBM_BUSY_USER_DEFINED_MASK__SHIFT 0x13
+#define GRBM_PERFCOUNTER1_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x100000
+#define GRBM_PERFCOUNTER1_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x14
+#define GRBM_PERFCOUNTER1_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x200000
+#define GRBM_PERFCOUNTER1_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x15
+#define GRBM_PERFCOUNTER1_SELECT__CP_BUSY_USER_DEFINED_MASK_MASK 0x400000
+#define GRBM_PERFCOUNTER1_SELECT__CP_BUSY_USER_DEFINED_MASK__SHIFT 0x16
+#define GRBM_PERFCOUNTER1_SELECT__IA_BUSY_USER_DEFINED_MASK_MASK 0x800000
+#define GRBM_PERFCOUNTER1_SELECT__IA_BUSY_USER_DEFINED_MASK__SHIFT 0x17
+#define GRBM_PERFCOUNTER1_SELECT__GDS_BUSY_USER_DEFINED_MASK_MASK 0x1000000
+#define GRBM_PERFCOUNTER1_SELECT__GDS_BUSY_USER_DEFINED_MASK__SHIFT 0x18
+#define GRBM_PERFCOUNTER1_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x2000000
+#define GRBM_PERFCOUNTER1_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x19
+#define GRBM_PERFCOUNTER1_SELECT__RLC_BUSY_USER_DEFINED_MASK_MASK 0x4000000
+#define GRBM_PERFCOUNTER1_SELECT__RLC_BUSY_USER_DEFINED_MASK__SHIFT 0x1a
+#define GRBM_PERFCOUNTER1_SELECT__TC_BUSY_USER_DEFINED_MASK_MASK 0x8000000
+#define GRBM_PERFCOUNTER1_SELECT__TC_BUSY_USER_DEFINED_MASK__SHIFT 0x1b
+#define GRBM_PERFCOUNTER1_SELECT__WD_BUSY_USER_DEFINED_MASK_MASK 0x10000000
+#define GRBM_PERFCOUNTER1_SELECT__WD_BUSY_USER_DEFINED_MASK__SHIFT 0x1c
+#define GRBM_SE0_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x3f
+#define GRBM_SE0_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x0
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x400
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0xa
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x800
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0xb
+#define GRBM_SE0_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x1000
+#define GRBM_SE0_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0xc
+#define GRBM_SE0_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x2000
+#define GRBM_SE0_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0xd
+#define GRBM_SE0_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x8000
+#define GRBM_SE0_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0xf
+#define GRBM_SE0_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x10000
+#define GRBM_SE0_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x10
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x20000
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x11
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x40000
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x12
+#define GRBM_SE0_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x80000
+#define GRBM_SE0_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x13
+#define GRBM_SE0_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x100000
+#define GRBM_SE0_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x14
+#define GRBM_SE0_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x200000
+#define GRBM_SE0_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x15
+#define GRBM_SE1_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x3f
+#define GRBM_SE1_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x0
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x400
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0xa
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x800
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0xb
+#define GRBM_SE1_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x1000
+#define GRBM_SE1_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0xc
+#define GRBM_SE1_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x2000
+#define GRBM_SE1_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0xd
+#define GRBM_SE1_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x8000
+#define GRBM_SE1_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0xf
+#define GRBM_SE1_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x10000
+#define GRBM_SE1_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x10
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x20000
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x11
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x40000
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x12
+#define GRBM_SE1_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x80000
+#define GRBM_SE1_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x13
+#define GRBM_SE1_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x100000
+#define GRBM_SE1_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x14
+#define GRBM_SE1_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x200000
+#define GRBM_SE1_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x15
+#define GRBM_SE2_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x3f
+#define GRBM_SE2_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x0
+#define GRBM_SE2_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x400
+#define GRBM_SE2_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0xa
+#define GRBM_SE2_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x800
+#define GRBM_SE2_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0xb
+#define GRBM_SE2_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x1000
+#define GRBM_SE2_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0xc
+#define GRBM_SE2_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x2000
+#define GRBM_SE2_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0xd
+#define GRBM_SE2_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x8000
+#define GRBM_SE2_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0xf
+#define GRBM_SE2_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x10000
+#define GRBM_SE2_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x10
+#define GRBM_SE2_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x20000
+#define GRBM_SE2_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x11
+#define GRBM_SE2_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x40000
+#define GRBM_SE2_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x12
+#define GRBM_SE2_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x80000
+#define GRBM_SE2_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x13
+#define GRBM_SE2_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x100000
+#define GRBM_SE2_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x14
+#define GRBM_SE2_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x200000
+#define GRBM_SE2_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x15
+#define GRBM_SE3_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x3f
+#define GRBM_SE3_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x0
+#define GRBM_SE3_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x400
+#define GRBM_SE3_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0xa
+#define GRBM_SE3_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x800
+#define GRBM_SE3_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0xb
+#define GRBM_SE3_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x1000
+#define GRBM_SE3_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0xc
+#define GRBM_SE3_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x2000
+#define GRBM_SE3_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0xd
+#define GRBM_SE3_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x8000
+#define GRBM_SE3_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0xf
+#define GRBM_SE3_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x10000
+#define GRBM_SE3_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x10
+#define GRBM_SE3_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x20000
+#define GRBM_SE3_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x11
+#define GRBM_SE3_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x40000
+#define GRBM_SE3_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x12
+#define GRBM_SE3_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x80000
+#define GRBM_SE3_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x13
+#define GRBM_SE3_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x100000
+#define GRBM_SE3_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x14
+#define GRBM_SE3_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x200000
+#define GRBM_SE3_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x15
+#define GRBM_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GRBM_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GRBM_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GRBM_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GRBM_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GRBM_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GRBM_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GRBM_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GRBM_SE0_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GRBM_SE0_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GRBM_SE0_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GRBM_SE0_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GRBM_SE1_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GRBM_SE1_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GRBM_SE1_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GRBM_SE1_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GRBM_SE2_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GRBM_SE2_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GRBM_SE2_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GRBM_SE2_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GRBM_SE3_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GRBM_SE3_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GRBM_SE3_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GRBM_SE3_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GRBM_SCRATCH_REG0__SCRATCH_REG0_MASK 0xffffffff
+#define GRBM_SCRATCH_REG0__SCRATCH_REG0__SHIFT 0x0
+#define GRBM_SCRATCH_REG1__SCRATCH_REG1_MASK 0xffffffff
+#define GRBM_SCRATCH_REG1__SCRATCH_REG1__SHIFT 0x0
+#define GRBM_SCRATCH_REG2__SCRATCH_REG2_MASK 0xffffffff
+#define GRBM_SCRATCH_REG2__SCRATCH_REG2__SHIFT 0x0
+#define GRBM_SCRATCH_REG3__SCRATCH_REG3_MASK 0xffffffff
+#define GRBM_SCRATCH_REG3__SCRATCH_REG3__SHIFT 0x0
+#define GRBM_SCRATCH_REG4__SCRATCH_REG4_MASK 0xffffffff
+#define GRBM_SCRATCH_REG4__SCRATCH_REG4__SHIFT 0x0
+#define GRBM_SCRATCH_REG5__SCRATCH_REG5_MASK 0xffffffff
+#define GRBM_SCRATCH_REG5__SCRATCH_REG5__SHIFT 0x0
+#define GRBM_SCRATCH_REG6__SCRATCH_REG6_MASK 0xffffffff
+#define GRBM_SCRATCH_REG6__SCRATCH_REG6__SHIFT 0x0
+#define GRBM_SCRATCH_REG7__SCRATCH_REG7_MASK 0xffffffff
+#define GRBM_SCRATCH_REG7__SCRATCH_REG7__SHIFT 0x0
+#define DEBUG_INDEX__DEBUG_INDEX_MASK 0x3ffff
+#define DEBUG_INDEX__DEBUG_INDEX__SHIFT 0x0
+#define DEBUG_DATA__DEBUG_DATA_MASK 0xffffffff
+#define DEBUG_DATA__DEBUG_DATA__SHIFT 0x0
+#define GRBM_NOWHERE__DATA_MASK 0xffffffff
+#define GRBM_NOWHERE__DATA__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_1__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_1__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_2__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_2__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_3__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_3__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_4__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_4__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_5__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_5__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_6__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_6__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_7__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_7__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_8__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_8__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_9__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_9__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_10__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_10__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_11__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_11__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_12__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_12__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_13__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_13__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_14__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_14__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XSCALE_15__VPORT_XSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_XSCALE_15__VPORT_XSCALE__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_1__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_1__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_2__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_2__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_3__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_3__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_4__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_4__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_5__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_5__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_6__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_6__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_7__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_7__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_8__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_8__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_9__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_9__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_10__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_10__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_11__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_11__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_12__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_12__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_13__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_13__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_14__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_14__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_XOFFSET_15__VPORT_XOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_XOFFSET_15__VPORT_XOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_1__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_1__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_2__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_2__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_3__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_3__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_4__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_4__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_5__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_5__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_6__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_6__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_7__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_7__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_8__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_8__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_9__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_9__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_10__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_10__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_11__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_11__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_12__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_12__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_13__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_13__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_14__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_14__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YSCALE_15__VPORT_YSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_YSCALE_15__VPORT_YSCALE__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_1__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_1__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_2__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_2__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_3__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_3__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_4__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_4__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_5__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_5__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_6__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_6__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_7__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_7__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_8__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_8__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_9__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_9__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_10__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_10__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_11__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_11__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_12__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_12__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_13__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_13__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_14__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_14__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_YOFFSET_15__VPORT_YOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_YOFFSET_15__VPORT_YOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_1__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_1__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_2__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_2__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_3__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_3__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_4__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_4__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_5__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_5__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_6__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_6__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_7__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_7__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_8__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_8__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_9__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_9__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_10__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_10__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_11__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_11__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_12__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_12__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_13__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_13__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_14__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_14__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZSCALE_15__VPORT_ZSCALE_MASK 0xffffffff
+#define PA_CL_VPORT_ZSCALE_15__VPORT_ZSCALE__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_1__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_1__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_2__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_2__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_3__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_3__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_4__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_4__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_5__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_5__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_6__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_6__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_7__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_7__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_8__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_8__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_9__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_9__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_10__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_10__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_11__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_11__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_12__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_12__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_13__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_13__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_14__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_14__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VPORT_ZOFFSET_15__VPORT_ZOFFSET_MASK 0xffffffff
+#define PA_CL_VPORT_ZOFFSET_15__VPORT_ZOFFSET__SHIFT 0x0
+#define PA_CL_VTE_CNTL__VPORT_X_SCALE_ENA_MASK 0x1
+#define PA_CL_VTE_CNTL__VPORT_X_SCALE_ENA__SHIFT 0x0
+#define PA_CL_VTE_CNTL__VPORT_X_OFFSET_ENA_MASK 0x2
+#define PA_CL_VTE_CNTL__VPORT_X_OFFSET_ENA__SHIFT 0x1
+#define PA_CL_VTE_CNTL__VPORT_Y_SCALE_ENA_MASK 0x4
+#define PA_CL_VTE_CNTL__VPORT_Y_SCALE_ENA__SHIFT 0x2
+#define PA_CL_VTE_CNTL__VPORT_Y_OFFSET_ENA_MASK 0x8
+#define PA_CL_VTE_CNTL__VPORT_Y_OFFSET_ENA__SHIFT 0x3
+#define PA_CL_VTE_CNTL__VPORT_Z_SCALE_ENA_MASK 0x10
+#define PA_CL_VTE_CNTL__VPORT_Z_SCALE_ENA__SHIFT 0x4
+#define PA_CL_VTE_CNTL__VPORT_Z_OFFSET_ENA_MASK 0x20
+#define PA_CL_VTE_CNTL__VPORT_Z_OFFSET_ENA__SHIFT 0x5
+#define PA_CL_VTE_CNTL__VTX_XY_FMT_MASK 0x100
+#define PA_CL_VTE_CNTL__VTX_XY_FMT__SHIFT 0x8
+#define PA_CL_VTE_CNTL__VTX_Z_FMT_MASK 0x200
+#define PA_CL_VTE_CNTL__VTX_Z_FMT__SHIFT 0x9
+#define PA_CL_VTE_CNTL__VTX_W0_FMT_MASK 0x400
+#define PA_CL_VTE_CNTL__VTX_W0_FMT__SHIFT 0xa
+#define PA_CL_VTE_CNTL__PERFCOUNTER_REF_MASK 0x800
+#define PA_CL_VTE_CNTL__PERFCOUNTER_REF__SHIFT 0xb
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0_MASK 0x1
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0__SHIFT 0x0
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_1_MASK 0x2
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_1__SHIFT 0x1
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_2_MASK 0x4
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_2__SHIFT 0x2
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_3_MASK 0x8
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_3__SHIFT 0x3
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_4_MASK 0x10
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_4__SHIFT 0x4
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_5_MASK 0x20
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_5__SHIFT 0x5
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_6_MASK 0x40
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_6__SHIFT 0x6
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_7_MASK 0x80
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_7__SHIFT 0x7
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_0_MASK 0x100
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_0__SHIFT 0x8
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_1_MASK 0x200
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_1__SHIFT 0x9
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_2_MASK 0x400
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_2__SHIFT 0xa
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_3_MASK 0x800
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_3__SHIFT 0xb
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_4_MASK 0x1000
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_4__SHIFT 0xc
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_5_MASK 0x2000
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_5__SHIFT 0xd
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_6_MASK 0x4000
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_6__SHIFT 0xe
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_7_MASK 0x8000
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_7__SHIFT 0xf
+#define PA_CL_VS_OUT_CNTL__USE_VTX_POINT_SIZE_MASK 0x10000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_POINT_SIZE__SHIFT 0x10
+#define PA_CL_VS_OUT_CNTL__USE_VTX_EDGE_FLAG_MASK 0x20000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_EDGE_FLAG__SHIFT 0x11
+#define PA_CL_VS_OUT_CNTL__USE_VTX_RENDER_TARGET_INDX_MASK 0x40000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_RENDER_TARGET_INDX__SHIFT 0x12
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VIEWPORT_INDX_MASK 0x80000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VIEWPORT_INDX__SHIFT 0x13
+#define PA_CL_VS_OUT_CNTL__USE_VTX_KILL_FLAG_MASK 0x100000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_KILL_FLAG__SHIFT 0x14
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_VEC_ENA_MASK 0x200000
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_VEC_ENA__SHIFT 0x15
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST0_VEC_ENA_MASK 0x400000
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST0_VEC_ENA__SHIFT 0x16
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST1_VEC_ENA_MASK 0x800000
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST1_VEC_ENA__SHIFT 0x17
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA_MASK 0x1000000
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA__SHIFT 0x18
+#define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG_MASK 0x2000000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG__SHIFT 0x19
+#define PA_CL_VS_OUT_CNTL__USE_VTX_LINE_WIDTH_MASK 0x4000000
+#define PA_CL_VS_OUT_CNTL__USE_VTX_LINE_WIDTH__SHIFT 0x1a
+#define PA_CL_NANINF_CNTL__VTE_XY_INF_DISCARD_MASK 0x1
+#define PA_CL_NANINF_CNTL__VTE_XY_INF_DISCARD__SHIFT 0x0
+#define PA_CL_NANINF_CNTL__VTE_Z_INF_DISCARD_MASK 0x2
+#define PA_CL_NANINF_CNTL__VTE_Z_INF_DISCARD__SHIFT 0x1
+#define PA_CL_NANINF_CNTL__VTE_W_INF_DISCARD_MASK 0x4
+#define PA_CL_NANINF_CNTL__VTE_W_INF_DISCARD__SHIFT 0x2
+#define PA_CL_NANINF_CNTL__VTE_0XNANINF_IS_0_MASK 0x8
+#define PA_CL_NANINF_CNTL__VTE_0XNANINF_IS_0__SHIFT 0x3
+#define PA_CL_NANINF_CNTL__VTE_XY_NAN_RETAIN_MASK 0x10
+#define PA_CL_NANINF_CNTL__VTE_XY_NAN_RETAIN__SHIFT 0x4
+#define PA_CL_NANINF_CNTL__VTE_Z_NAN_RETAIN_MASK 0x20
+#define PA_CL_NANINF_CNTL__VTE_Z_NAN_RETAIN__SHIFT 0x5
+#define PA_CL_NANINF_CNTL__VTE_W_NAN_RETAIN_MASK 0x40
+#define PA_CL_NANINF_CNTL__VTE_W_NAN_RETAIN__SHIFT 0x6
+#define PA_CL_NANINF_CNTL__VTE_W_RECIP_NAN_IS_0_MASK 0x80
+#define PA_CL_NANINF_CNTL__VTE_W_RECIP_NAN_IS_0__SHIFT 0x7
+#define PA_CL_NANINF_CNTL__VS_XY_NAN_TO_INF_MASK 0x100
+#define PA_CL_NANINF_CNTL__VS_XY_NAN_TO_INF__SHIFT 0x8
+#define PA_CL_NANINF_CNTL__VS_XY_INF_RETAIN_MASK 0x200
+#define PA_CL_NANINF_CNTL__VS_XY_INF_RETAIN__SHIFT 0x9
+#define PA_CL_NANINF_CNTL__VS_Z_NAN_TO_INF_MASK 0x400
+#define PA_CL_NANINF_CNTL__VS_Z_NAN_TO_INF__SHIFT 0xa
+#define PA_CL_NANINF_CNTL__VS_Z_INF_RETAIN_MASK 0x800
+#define PA_CL_NANINF_CNTL__VS_Z_INF_RETAIN__SHIFT 0xb
+#define PA_CL_NANINF_CNTL__VS_W_NAN_TO_INF_MASK 0x1000
+#define PA_CL_NANINF_CNTL__VS_W_NAN_TO_INF__SHIFT 0xc
+#define PA_CL_NANINF_CNTL__VS_W_INF_RETAIN_MASK 0x2000
+#define PA_CL_NANINF_CNTL__VS_W_INF_RETAIN__SHIFT 0xd
+#define PA_CL_NANINF_CNTL__VS_CLIP_DIST_INF_DISCARD_MASK 0x4000
+#define PA_CL_NANINF_CNTL__VS_CLIP_DIST_INF_DISCARD__SHIFT 0xe
+#define PA_CL_NANINF_CNTL__VTE_NO_OUTPUT_NEG_0_MASK 0x100000
+#define PA_CL_NANINF_CNTL__VTE_NO_OUTPUT_NEG_0__SHIFT 0x14
+#define PA_CL_CLIP_CNTL__UCP_ENA_0_MASK 0x1
+#define PA_CL_CLIP_CNTL__UCP_ENA_0__SHIFT 0x0
+#define PA_CL_CLIP_CNTL__UCP_ENA_1_MASK 0x2
+#define PA_CL_CLIP_CNTL__UCP_ENA_1__SHIFT 0x1
+#define PA_CL_CLIP_CNTL__UCP_ENA_2_MASK 0x4
+#define PA_CL_CLIP_CNTL__UCP_ENA_2__SHIFT 0x2
+#define PA_CL_CLIP_CNTL__UCP_ENA_3_MASK 0x8
+#define PA_CL_CLIP_CNTL__UCP_ENA_3__SHIFT 0x3
+#define PA_CL_CLIP_CNTL__UCP_ENA_4_MASK 0x10
+#define PA_CL_CLIP_CNTL__UCP_ENA_4__SHIFT 0x4
+#define PA_CL_CLIP_CNTL__UCP_ENA_5_MASK 0x20
+#define PA_CL_CLIP_CNTL__UCP_ENA_5__SHIFT 0x5
+#define PA_CL_CLIP_CNTL__PS_UCP_Y_SCALE_NEG_MASK 0x2000
+#define PA_CL_CLIP_CNTL__PS_UCP_Y_SCALE_NEG__SHIFT 0xd
+#define PA_CL_CLIP_CNTL__PS_UCP_MODE_MASK 0xc000
+#define PA_CL_CLIP_CNTL__PS_UCP_MODE__SHIFT 0xe
+#define PA_CL_CLIP_CNTL__CLIP_DISABLE_MASK 0x10000
+#define PA_CL_CLIP_CNTL__CLIP_DISABLE__SHIFT 0x10
+#define PA_CL_CLIP_CNTL__UCP_CULL_ONLY_ENA_MASK 0x20000
+#define PA_CL_CLIP_CNTL__UCP_CULL_ONLY_ENA__SHIFT 0x11
+#define PA_CL_CLIP_CNTL__BOUNDARY_EDGE_FLAG_ENA_MASK 0x40000
+#define PA_CL_CLIP_CNTL__BOUNDARY_EDGE_FLAG_ENA__SHIFT 0x12
+#define PA_CL_CLIP_CNTL__DX_CLIP_SPACE_DEF_MASK 0x80000
+#define PA_CL_CLIP_CNTL__DX_CLIP_SPACE_DEF__SHIFT 0x13
+#define PA_CL_CLIP_CNTL__DIS_CLIP_ERR_DETECT_MASK 0x100000
+#define PA_CL_CLIP_CNTL__DIS_CLIP_ERR_DETECT__SHIFT 0x14
+#define PA_CL_CLIP_CNTL__VTX_KILL_OR_MASK 0x200000
+#define PA_CL_CLIP_CNTL__VTX_KILL_OR__SHIFT 0x15
+#define PA_CL_CLIP_CNTL__DX_RASTERIZATION_KILL_MASK 0x400000
+#define PA_CL_CLIP_CNTL__DX_RASTERIZATION_KILL__SHIFT 0x16
+#define PA_CL_CLIP_CNTL__DX_LINEAR_ATTR_CLIP_ENA_MASK 0x1000000
+#define PA_CL_CLIP_CNTL__DX_LINEAR_ATTR_CLIP_ENA__SHIFT 0x18
+#define PA_CL_CLIP_CNTL__VTE_VPORT_PROVOKE_DISABLE_MASK 0x2000000
+#define PA_CL_CLIP_CNTL__VTE_VPORT_PROVOKE_DISABLE__SHIFT 0x19
+#define PA_CL_CLIP_CNTL__ZCLIP_NEAR_DISABLE_MASK 0x4000000
+#define PA_CL_CLIP_CNTL__ZCLIP_NEAR_DISABLE__SHIFT 0x1a
+#define PA_CL_CLIP_CNTL__ZCLIP_FAR_DISABLE_MASK 0x8000000
+#define PA_CL_CLIP_CNTL__ZCLIP_FAR_DISABLE__SHIFT 0x1b
+#define PA_CL_GB_VERT_CLIP_ADJ__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_GB_VERT_CLIP_ADJ__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_GB_VERT_DISC_ADJ__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_GB_VERT_DISC_ADJ__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_GB_HORZ_CLIP_ADJ__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_GB_HORZ_CLIP_ADJ__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_GB_HORZ_DISC_ADJ__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_GB_HORZ_DISC_ADJ__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_0_X__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_0_X__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_0_Y__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_0_Y__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_0_Z__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_0_Z__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_0_W__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_0_W__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_1_X__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_1_X__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_1_Y__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_1_Y__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_1_Z__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_1_Z__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_1_W__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_1_W__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_2_X__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_2_X__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_2_Y__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_2_Y__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_2_Z__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_2_Z__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_2_W__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_2_W__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_3_X__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_3_X__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_3_Y__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_3_Y__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_3_Z__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_3_Z__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_3_W__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_3_W__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_4_X__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_4_X__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_4_Y__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_4_Y__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_4_Z__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_4_Z__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_4_W__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_4_W__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_5_X__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_5_X__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_5_Y__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_5_Y__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_5_Z__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_5_Z__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_UCP_5_W__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_UCP_5_W__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_POINT_X_RAD__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_POINT_X_RAD__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_POINT_Y_RAD__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_POINT_Y_RAD__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_POINT_SIZE__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_POINT_SIZE__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_POINT_CULL_RAD__DATA_REGISTER_MASK 0xffffffff
+#define PA_CL_POINT_CULL_RAD__DATA_REGISTER__SHIFT 0x0
+#define PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA_MASK 0x1
+#define PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA__SHIFT 0x0
+#define PA_CL_ENHANCE__NUM_CLIP_SEQ_MASK 0x6
+#define PA_CL_ENHANCE__NUM_CLIP_SEQ__SHIFT 0x1
+#define PA_CL_ENHANCE__CLIPPED_PRIM_SEQ_STALL_MASK 0x8
+#define PA_CL_ENHANCE__CLIPPED_PRIM_SEQ_STALL__SHIFT 0x3
+#define PA_CL_ENHANCE__VE_NAN_PROC_DISABLE_MASK 0x10
+#define PA_CL_ENHANCE__VE_NAN_PROC_DISABLE__SHIFT 0x4
+#define PA_CL_ENHANCE__XTRA_DEBUG_REG_SEL_MASK 0x20
+#define PA_CL_ENHANCE__XTRA_DEBUG_REG_SEL__SHIFT 0x5
+#define PA_CL_ENHANCE__ECO_SPARE3_MASK 0x10000000
+#define PA_CL_ENHANCE__ECO_SPARE3__SHIFT 0x1c
+#define PA_CL_ENHANCE__ECO_SPARE2_MASK 0x20000000
+#define PA_CL_ENHANCE__ECO_SPARE2__SHIFT 0x1d
+#define PA_CL_ENHANCE__ECO_SPARE1_MASK 0x40000000
+#define PA_CL_ENHANCE__ECO_SPARE1__SHIFT 0x1e
+#define PA_CL_ENHANCE__ECO_SPARE0_MASK 0x80000000
+#define PA_CL_ENHANCE__ECO_SPARE0__SHIFT 0x1f
+#define PA_CL_RESET_DEBUG__CL_TRIV_DISC_DISABLE_MASK 0x1
+#define PA_CL_RESET_DEBUG__CL_TRIV_DISC_DISABLE__SHIFT 0x0
+#define PA_SU_VTX_CNTL__PIX_CENTER_MASK 0x1
+#define PA_SU_VTX_CNTL__PIX_CENTER__SHIFT 0x0
+#define PA_SU_VTX_CNTL__ROUND_MODE_MASK 0x6
+#define PA_SU_VTX_CNTL__ROUND_MODE__SHIFT 0x1
+#define PA_SU_VTX_CNTL__QUANT_MODE_MASK 0x38
+#define PA_SU_VTX_CNTL__QUANT_MODE__SHIFT 0x3
+#define PA_SU_POINT_SIZE__HEIGHT_MASK 0xffff
+#define PA_SU_POINT_SIZE__HEIGHT__SHIFT 0x0
+#define PA_SU_POINT_SIZE__WIDTH_MASK 0xffff0000
+#define PA_SU_POINT_SIZE__WIDTH__SHIFT 0x10
+#define PA_SU_POINT_MINMAX__MIN_SIZE_MASK 0xffff
+#define PA_SU_POINT_MINMAX__MIN_SIZE__SHIFT 0x0
+#define PA_SU_POINT_MINMAX__MAX_SIZE_MASK 0xffff0000
+#define PA_SU_POINT_MINMAX__MAX_SIZE__SHIFT 0x10
+#define PA_SU_LINE_CNTL__WIDTH_MASK 0xffff
+#define PA_SU_LINE_CNTL__WIDTH__SHIFT 0x0
+#define PA_SU_LINE_STIPPLE_CNTL__LINE_STIPPLE_RESET_MASK 0x3
+#define PA_SU_LINE_STIPPLE_CNTL__LINE_STIPPLE_RESET__SHIFT 0x0
+#define PA_SU_LINE_STIPPLE_CNTL__EXPAND_FULL_LENGTH_MASK 0x4
+#define PA_SU_LINE_STIPPLE_CNTL__EXPAND_FULL_LENGTH__SHIFT 0x2
+#define PA_SU_LINE_STIPPLE_CNTL__FRACTIONAL_ACCUM_MASK 0x8
+#define PA_SU_LINE_STIPPLE_CNTL__FRACTIONAL_ACCUM__SHIFT 0x3
+#define PA_SU_LINE_STIPPLE_CNTL__DIAMOND_ADJUST_MASK 0x10
+#define PA_SU_LINE_STIPPLE_CNTL__DIAMOND_ADJUST__SHIFT 0x4
+#define PA_SU_LINE_STIPPLE_SCALE__LINE_STIPPLE_SCALE_MASK 0xffffffff
+#define PA_SU_LINE_STIPPLE_SCALE__LINE_STIPPLE_SCALE__SHIFT 0x0
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_FILTER_DISABLE_MASK 0x1
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_FILTER_DISABLE__SHIFT 0x0
+#define PA_SU_PRIM_FILTER_CNTL__LINE_FILTER_DISABLE_MASK 0x2
+#define PA_SU_PRIM_FILTER_CNTL__LINE_FILTER_DISABLE__SHIFT 0x1
+#define PA_SU_PRIM_FILTER_CNTL__POINT_FILTER_DISABLE_MASK 0x4
+#define PA_SU_PRIM_FILTER_CNTL__POINT_FILTER_DISABLE__SHIFT 0x2
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_FILTER_DISABLE_MASK 0x8
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_FILTER_DISABLE__SHIFT 0x3
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_EXPAND_ENA_MASK 0x10
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_EXPAND_ENA__SHIFT 0x4
+#define PA_SU_PRIM_FILTER_CNTL__LINE_EXPAND_ENA_MASK 0x20
+#define PA_SU_PRIM_FILTER_CNTL__LINE_EXPAND_ENA__SHIFT 0x5
+#define PA_SU_PRIM_FILTER_CNTL__POINT_EXPAND_ENA_MASK 0x40
+#define PA_SU_PRIM_FILTER_CNTL__POINT_EXPAND_ENA__SHIFT 0x6
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_EXPAND_ENA_MASK 0x80
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_EXPAND_ENA__SHIFT 0x7
+#define PA_SU_PRIM_FILTER_CNTL__PRIM_EXPAND_CONSTANT_MASK 0xff00
+#define PA_SU_PRIM_FILTER_CNTL__PRIM_EXPAND_CONSTANT__SHIFT 0x8
+#define PA_SU_PRIM_FILTER_CNTL__XMAX_RIGHT_EXCLUSION_MASK 0x40000000
+#define PA_SU_PRIM_FILTER_CNTL__XMAX_RIGHT_EXCLUSION__SHIFT 0x1e
+#define PA_SU_PRIM_FILTER_CNTL__YMAX_BOTTOM_EXCLUSION_MASK 0x80000000
+#define PA_SU_PRIM_FILTER_CNTL__YMAX_BOTTOM_EXCLUSION__SHIFT 0x1f
+#define PA_SU_SC_MODE_CNTL__CULL_FRONT_MASK 0x1
+#define PA_SU_SC_MODE_CNTL__CULL_FRONT__SHIFT 0x0
+#define PA_SU_SC_MODE_CNTL__CULL_BACK_MASK 0x2
+#define PA_SU_SC_MODE_CNTL__CULL_BACK__SHIFT 0x1
+#define PA_SU_SC_MODE_CNTL__FACE_MASK 0x4
+#define PA_SU_SC_MODE_CNTL__FACE__SHIFT 0x2
+#define PA_SU_SC_MODE_CNTL__POLY_MODE_MASK 0x18
+#define PA_SU_SC_MODE_CNTL__POLY_MODE__SHIFT 0x3
+#define PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE_MASK 0xe0
+#define PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE__SHIFT 0x5
+#define PA_SU_SC_MODE_CNTL__POLYMODE_BACK_PTYPE_MASK 0x700
+#define PA_SU_SC_MODE_CNTL__POLYMODE_BACK_PTYPE__SHIFT 0x8
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_FRONT_ENABLE_MASK 0x800
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_FRONT_ENABLE__SHIFT 0xb
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_BACK_ENABLE_MASK 0x1000
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_BACK_ENABLE__SHIFT 0xc
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_PARA_ENABLE_MASK 0x2000
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_PARA_ENABLE__SHIFT 0xd
+#define PA_SU_SC_MODE_CNTL__VTX_WINDOW_OFFSET_ENABLE_MASK 0x10000
+#define PA_SU_SC_MODE_CNTL__VTX_WINDOW_OFFSET_ENABLE__SHIFT 0x10
+#define PA_SU_SC_MODE_CNTL__PROVOKING_VTX_LAST_MASK 0x80000
+#define PA_SU_SC_MODE_CNTL__PROVOKING_VTX_LAST__SHIFT 0x13
+#define PA_SU_SC_MODE_CNTL__PERSP_CORR_DIS_MASK 0x100000
+#define PA_SU_SC_MODE_CNTL__PERSP_CORR_DIS__SHIFT 0x14
+#define PA_SU_SC_MODE_CNTL__MULTI_PRIM_IB_ENA_MASK 0x200000
+#define PA_SU_SC_MODE_CNTL__MULTI_PRIM_IB_ENA__SHIFT 0x15
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_NEG_NUM_DB_BITS_MASK 0xff
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_NEG_NUM_DB_BITS__SHIFT 0x0
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_DB_IS_FLOAT_FMT_MASK 0x100
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_DB_IS_FLOAT_FMT__SHIFT 0x8
+#define PA_SU_POLY_OFFSET_CLAMP__CLAMP_MASK 0xffffffff
+#define PA_SU_POLY_OFFSET_CLAMP__CLAMP__SHIFT 0x0
+#define PA_SU_POLY_OFFSET_FRONT_SCALE__SCALE_MASK 0xffffffff
+#define PA_SU_POLY_OFFSET_FRONT_SCALE__SCALE__SHIFT 0x0
+#define PA_SU_POLY_OFFSET_FRONT_OFFSET__OFFSET_MASK 0xffffffff
+#define PA_SU_POLY_OFFSET_FRONT_OFFSET__OFFSET__SHIFT 0x0
+#define PA_SU_POLY_OFFSET_BACK_SCALE__SCALE_MASK 0xffffffff
+#define PA_SU_POLY_OFFSET_BACK_SCALE__SCALE__SHIFT 0x0
+#define PA_SU_POLY_OFFSET_BACK_OFFSET__OFFSET_MASK 0xffffffff
+#define PA_SU_POLY_OFFSET_BACK_OFFSET__OFFSET__SHIFT 0x0
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_X_MASK 0x1ff
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_X__SHIFT 0x0
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_Y_MASK 0x1ff0000
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_Y__SHIFT 0x10
+#define PA_SU_LINE_STIPPLE_VALUE__LINE_STIPPLE_VALUE_MASK 0xffffff
+#define PA_SU_LINE_STIPPLE_VALUE__LINE_STIPPLE_VALUE__SHIFT 0x0
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define PA_SU_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define PA_SU_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define PA_SU_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define PA_SU_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define PA_SU_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SU_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SU_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define PA_SU_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define PA_SU_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SU_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SU_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define PA_SU_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define PA_SU_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SU_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SU_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffff
+#define PA_SU_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SU_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SU_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SU_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffff
+#define PA_SU_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SU_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SU_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SU_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffff
+#define PA_SU_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SU_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SU_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SU_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffff
+#define PA_SU_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_AA_CONFIG__MSAA_NUM_SAMPLES_MASK 0x7
+#define PA_SC_AA_CONFIG__MSAA_NUM_SAMPLES__SHIFT 0x0
+#define PA_SC_AA_CONFIG__AA_MASK_CENTROID_DTMN_MASK 0x10
+#define PA_SC_AA_CONFIG__AA_MASK_CENTROID_DTMN__SHIFT 0x4
+#define PA_SC_AA_CONFIG__MAX_SAMPLE_DIST_MASK 0x1e000
+#define PA_SC_AA_CONFIG__MAX_SAMPLE_DIST__SHIFT 0xd
+#define PA_SC_AA_CONFIG__MSAA_EXPOSED_SAMPLES_MASK 0x700000
+#define PA_SC_AA_CONFIG__MSAA_EXPOSED_SAMPLES__SHIFT 0x14
+#define PA_SC_AA_CONFIG__DETAIL_TO_EXPOSED_MODE_MASK 0x3000000
+#define PA_SC_AA_CONFIG__DETAIL_TO_EXPOSED_MODE__SHIFT 0x18
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X0Y0_MASK 0xffff
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X0Y0__SHIFT 0x0
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X1Y0_MASK 0xffff0000
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X1Y0__SHIFT 0x10
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X0Y1_MASK 0xffff
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X0Y1__SHIFT 0x0
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X1Y1_MASK 0xffff0000
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X1Y1__SHIFT 0x10
+#define PA_SC_SHADER_CONTROL__REALIGN_DQUADS_AFTER_N_WAVES_MASK 0x3
+#define PA_SC_SHADER_CONTROL__REALIGN_DQUADS_AFTER_N_WAVES__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_Y__SHIFT 0x1c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_X_MASK 0xf
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_X__SHIFT 0x0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_Y_MASK 0xf0
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_Y__SHIFT 0x4
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_X_MASK 0xf00
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_X__SHIFT 0x8
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_Y_MASK 0xf000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_Y__SHIFT 0xc
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_X_MASK 0xf0000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_X__SHIFT 0x10
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_Y_MASK 0xf00000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_Y__SHIFT 0x14
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_X_MASK 0xf000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_X__SHIFT 0x18
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_Y_MASK 0xf0000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_Y__SHIFT 0x1c
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_0_MASK 0xf
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_0__SHIFT 0x0
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_1_MASK 0xf0
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_1__SHIFT 0x4
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_2_MASK 0xf00
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_2__SHIFT 0x8
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_3_MASK 0xf000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_3__SHIFT 0xc
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_4_MASK 0xf0000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_4__SHIFT 0x10
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_5_MASK 0xf00000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_5__SHIFT 0x14
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_6_MASK 0xf000000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_6__SHIFT 0x18
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_7_MASK 0xf0000000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_7__SHIFT 0x1c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_8_MASK 0xf
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_8__SHIFT 0x0
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_9_MASK 0xf0
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_9__SHIFT 0x4
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_10_MASK 0xf00
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_10__SHIFT 0x8
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_11_MASK 0xf000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_11__SHIFT 0xc
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_12_MASK 0xf0000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_12__SHIFT 0x10
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_13_MASK 0xf00000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_13__SHIFT 0x14
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_14_MASK 0xf000000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_14__SHIFT 0x18
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_15_MASK 0xf0000000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_15__SHIFT 0x1c
+#define PA_SC_CLIPRECT_0_TL__TL_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_0_TL__TL_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_0_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_0_TL__TL_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_0_BR__BR_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_0_BR__BR_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_0_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_0_BR__BR_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_1_TL__TL_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_1_TL__TL_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_1_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_1_TL__TL_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_1_BR__BR_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_1_BR__BR_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_1_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_1_BR__BR_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_2_TL__TL_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_2_TL__TL_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_2_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_2_TL__TL_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_2_BR__BR_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_2_BR__BR_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_2_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_2_BR__BR_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_3_TL__TL_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_3_TL__TL_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_3_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_3_TL__TL_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_3_BR__BR_X_MASK 0x7fff
+#define PA_SC_CLIPRECT_3_BR__BR_X__SHIFT 0x0
+#define PA_SC_CLIPRECT_3_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_CLIPRECT_3_BR__BR_Y__SHIFT 0x10
+#define PA_SC_CLIPRECT_RULE__CLIP_RULE_MASK 0xffff
+#define PA_SC_CLIPRECT_RULE__CLIP_RULE__SHIFT 0x0
+#define PA_SC_EDGERULE__ER_TRI_MASK 0xf
+#define PA_SC_EDGERULE__ER_TRI__SHIFT 0x0
+#define PA_SC_EDGERULE__ER_POINT_MASK 0xf0
+#define PA_SC_EDGERULE__ER_POINT__SHIFT 0x4
+#define PA_SC_EDGERULE__ER_RECT_MASK 0xf00
+#define PA_SC_EDGERULE__ER_RECT__SHIFT 0x8
+#define PA_SC_EDGERULE__ER_LINE_LR_MASK 0x3f000
+#define PA_SC_EDGERULE__ER_LINE_LR__SHIFT 0xc
+#define PA_SC_EDGERULE__ER_LINE_RL_MASK 0xfc0000
+#define PA_SC_EDGERULE__ER_LINE_RL__SHIFT 0x12
+#define PA_SC_EDGERULE__ER_LINE_TB_MASK 0xf000000
+#define PA_SC_EDGERULE__ER_LINE_TB__SHIFT 0x18
+#define PA_SC_EDGERULE__ER_LINE_BT_MASK 0xf0000000
+#define PA_SC_EDGERULE__ER_LINE_BT__SHIFT 0x1c
+#define PA_SC_LINE_CNTL__EXPAND_LINE_WIDTH_MASK 0x200
+#define PA_SC_LINE_CNTL__EXPAND_LINE_WIDTH__SHIFT 0x9
+#define PA_SC_LINE_CNTL__LAST_PIXEL_MASK 0x400
+#define PA_SC_LINE_CNTL__LAST_PIXEL__SHIFT 0xa
+#define PA_SC_LINE_CNTL__PERPENDICULAR_ENDCAP_ENA_MASK 0x800
+#define PA_SC_LINE_CNTL__PERPENDICULAR_ENDCAP_ENA__SHIFT 0xb
+#define PA_SC_LINE_CNTL__DX10_DIAMOND_TEST_ENA_MASK 0x1000
+#define PA_SC_LINE_CNTL__DX10_DIAMOND_TEST_ENA__SHIFT 0xc
+#define PA_SC_LINE_STIPPLE__LINE_PATTERN_MASK 0xffff
+#define PA_SC_LINE_STIPPLE__LINE_PATTERN__SHIFT 0x0
+#define PA_SC_LINE_STIPPLE__REPEAT_COUNT_MASK 0xff0000
+#define PA_SC_LINE_STIPPLE__REPEAT_COUNT__SHIFT 0x10
+#define PA_SC_LINE_STIPPLE__PATTERN_BIT_ORDER_MASK 0x10000000
+#define PA_SC_LINE_STIPPLE__PATTERN_BIT_ORDER__SHIFT 0x1c
+#define PA_SC_LINE_STIPPLE__AUTO_RESET_CNTL_MASK 0x60000000
+#define PA_SC_LINE_STIPPLE__AUTO_RESET_CNTL__SHIFT 0x1d
+#define PA_SC_MODE_CNTL_0__MSAA_ENABLE_MASK 0x1
+#define PA_SC_MODE_CNTL_0__MSAA_ENABLE__SHIFT 0x0
+#define PA_SC_MODE_CNTL_0__VPORT_SCISSOR_ENABLE_MASK 0x2
+#define PA_SC_MODE_CNTL_0__VPORT_SCISSOR_ENABLE__SHIFT 0x1
+#define PA_SC_MODE_CNTL_0__LINE_STIPPLE_ENABLE_MASK 0x4
+#define PA_SC_MODE_CNTL_0__LINE_STIPPLE_ENABLE__SHIFT 0x2
+#define PA_SC_MODE_CNTL_0__SEND_UNLIT_STILES_TO_PKR_MASK 0x8
+#define PA_SC_MODE_CNTL_0__SEND_UNLIT_STILES_TO_PKR__SHIFT 0x3
+#define PA_SC_MODE_CNTL_1__WALK_SIZE_MASK 0x1
+#define PA_SC_MODE_CNTL_1__WALK_SIZE__SHIFT 0x0
+#define PA_SC_MODE_CNTL_1__WALK_ALIGNMENT_MASK 0x2
+#define PA_SC_MODE_CNTL_1__WALK_ALIGNMENT__SHIFT 0x1
+#define PA_SC_MODE_CNTL_1__WALK_ALIGN8_PRIM_FITS_ST_MASK 0x4
+#define PA_SC_MODE_CNTL_1__WALK_ALIGN8_PRIM_FITS_ST__SHIFT 0x2
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_ENABLE_MASK 0x8
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_ENABLE__SHIFT 0x3
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_SIZE_MASK 0x70
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_SIZE__SHIFT 0x4
+#define PA_SC_MODE_CNTL_1__SUPERTILE_WALK_ORDER_ENABLE_MASK 0x80
+#define PA_SC_MODE_CNTL_1__SUPERTILE_WALK_ORDER_ENABLE__SHIFT 0x7
+#define PA_SC_MODE_CNTL_1__TILE_WALK_ORDER_ENABLE_MASK 0x100
+#define PA_SC_MODE_CNTL_1__TILE_WALK_ORDER_ENABLE__SHIFT 0x8
+#define PA_SC_MODE_CNTL_1__TILE_COVER_DISABLE_MASK 0x200
+#define PA_SC_MODE_CNTL_1__TILE_COVER_DISABLE__SHIFT 0x9
+#define PA_SC_MODE_CNTL_1__TILE_COVER_NO_SCISSOR_MASK 0x400
+#define PA_SC_MODE_CNTL_1__TILE_COVER_NO_SCISSOR__SHIFT 0xa
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_EXTENT_MASK 0x800
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_EXTENT__SHIFT 0xb
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_OFFSET_MASK 0x1000
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_OFFSET__SHIFT 0xc
+#define PA_SC_MODE_CNTL_1__ZMM_RECT_EXTENT_MASK 0x2000
+#define PA_SC_MODE_CNTL_1__ZMM_RECT_EXTENT__SHIFT 0xd
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_HI_Z_MASK 0x4000
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_HI_Z__SHIFT 0xe
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_DETAIL_MASK_MASK 0x8000
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_DETAIL_MASK__SHIFT 0xf
+#define PA_SC_MODE_CNTL_1__PS_ITER_SAMPLE_MASK 0x10000
+#define PA_SC_MODE_CNTL_1__PS_ITER_SAMPLE__SHIFT 0x10
+#define PA_SC_MODE_CNTL_1__MULTI_SHADER_ENGINE_PRIM_DISCARD_ENABLE_MASK 0x20000
+#define PA_SC_MODE_CNTL_1__MULTI_SHADER_ENGINE_PRIM_DISCARD_ENABLE__SHIFT 0x11
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_SUPERTILE_ENABLE_MASK 0x40000
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_SUPERTILE_ENABLE__SHIFT 0x12
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_ENABLE_MASK 0x80000
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_ENABLE__SHIFT 0x13
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_MASK 0xf00000
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE__SHIFT 0x14
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_PRIM_DISCARD_ENABLE_MASK 0x1000000
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_PRIM_DISCARD_ENABLE__SHIFT 0x18
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_CNTDWN_ENABLE_MASK 0x2000000
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_CNTDWN_ENABLE__SHIFT 0x19
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_REZ_ENABLE_MASK 0x4000000
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_REZ_ENABLE__SHIFT 0x1a
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_PRIMITIVE_ENABLE_MASK 0x8000000
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_PRIMITIVE_ENABLE__SHIFT 0x1b
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_WATER_MARK_MASK 0x70000000
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_WATER_MARK__SHIFT 0x1c
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR0_MASK 0x3
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT 0x0
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR1_MASK 0xc
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT 0x2
+#define PA_SC_RASTER_CONFIG__RB_XSEL2_MASK 0x30
+#define PA_SC_RASTER_CONFIG__RB_XSEL2__SHIFT 0x4
+#define PA_SC_RASTER_CONFIG__RB_XSEL_MASK 0x40
+#define PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT 0x6
+#define PA_SC_RASTER_CONFIG__RB_YSEL_MASK 0x80
+#define PA_SC_RASTER_CONFIG__RB_YSEL__SHIFT 0x7
+#define PA_SC_RASTER_CONFIG__PKR_MAP_MASK 0x300
+#define PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT 0x8
+#define PA_SC_RASTER_CONFIG__PKR_XSEL_MASK 0xc00
+#define PA_SC_RASTER_CONFIG__PKR_XSEL__SHIFT 0xa
+#define PA_SC_RASTER_CONFIG__PKR_YSEL_MASK 0x3000
+#define PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT 0xc
+#define PA_SC_RASTER_CONFIG__PKR_XSEL2_MASK 0xc000
+#define PA_SC_RASTER_CONFIG__PKR_XSEL2__SHIFT 0xe
+#define PA_SC_RASTER_CONFIG__SC_MAP_MASK 0x30000
+#define PA_SC_RASTER_CONFIG__SC_MAP__SHIFT 0x10
+#define PA_SC_RASTER_CONFIG__SC_XSEL_MASK 0xc0000
+#define PA_SC_RASTER_CONFIG__SC_XSEL__SHIFT 0x12
+#define PA_SC_RASTER_CONFIG__SC_YSEL_MASK 0x300000
+#define PA_SC_RASTER_CONFIG__SC_YSEL__SHIFT 0x14
+#define PA_SC_RASTER_CONFIG__SE_MAP_MASK 0x3000000
+#define PA_SC_RASTER_CONFIG__SE_MAP__SHIFT 0x18
+#define PA_SC_RASTER_CONFIG__SE_XSEL_MASK 0xc000000
+#define PA_SC_RASTER_CONFIG__SE_XSEL__SHIFT 0x1a
+#define PA_SC_RASTER_CONFIG__SE_YSEL_MASK 0x30000000
+#define PA_SC_RASTER_CONFIG__SE_YSEL__SHIFT 0x1c
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_MAP_MASK 0x3
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_MAP__SHIFT 0x0
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_XSEL_MASK 0xc
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_XSEL__SHIFT 0x2
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_YSEL_MASK 0x30
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_YSEL__SHIFT 0x4
+#define PA_SC_SCREEN_EXTENT_CONTROL__SLICE_EVEN_ENABLE_MASK 0x3
+#define PA_SC_SCREEN_EXTENT_CONTROL__SLICE_EVEN_ENABLE__SHIFT 0x0
+#define PA_SC_SCREEN_EXTENT_CONTROL__SLICE_ODD_ENABLE_MASK 0xc
+#define PA_SC_SCREEN_EXTENT_CONTROL__SLICE_ODD_ENABLE__SHIFT 0x2
+#define PA_SC_GENERIC_SCISSOR_TL__TL_X_MASK 0x7fff
+#define PA_SC_GENERIC_SCISSOR_TL__TL_X__SHIFT 0x0
+#define PA_SC_GENERIC_SCISSOR_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_GENERIC_SCISSOR_TL__TL_Y__SHIFT 0x10
+#define PA_SC_GENERIC_SCISSOR_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_GENERIC_SCISSOR_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_GENERIC_SCISSOR_BR__BR_X_MASK 0x7fff
+#define PA_SC_GENERIC_SCISSOR_BR__BR_X__SHIFT 0x0
+#define PA_SC_GENERIC_SCISSOR_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_GENERIC_SCISSOR_BR__BR_Y__SHIFT 0x10
+#define PA_SC_SCREEN_SCISSOR_TL__TL_X_MASK 0xffff
+#define PA_SC_SCREEN_SCISSOR_TL__TL_X__SHIFT 0x0
+#define PA_SC_SCREEN_SCISSOR_TL__TL_Y_MASK 0xffff0000
+#define PA_SC_SCREEN_SCISSOR_TL__TL_Y__SHIFT 0x10
+#define PA_SC_SCREEN_SCISSOR_BR__BR_X_MASK 0xffff
+#define PA_SC_SCREEN_SCISSOR_BR__BR_X__SHIFT 0x0
+#define PA_SC_SCREEN_SCISSOR_BR__BR_Y_MASK 0xffff0000
+#define PA_SC_SCREEN_SCISSOR_BR__BR_Y__SHIFT 0x10
+#define PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_MASK 0xffff
+#define PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET__SHIFT 0x0
+#define PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_MASK 0xffff0000
+#define PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET__SHIFT 0x10
+#define PA_SC_WINDOW_SCISSOR_TL__TL_X_MASK 0x7fff
+#define PA_SC_WINDOW_SCISSOR_TL__TL_X__SHIFT 0x0
+#define PA_SC_WINDOW_SCISSOR_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_WINDOW_SCISSOR_TL__TL_Y__SHIFT 0x10
+#define PA_SC_WINDOW_SCISSOR_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_WINDOW_SCISSOR_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_WINDOW_SCISSOR_BR__BR_X_MASK 0x7fff
+#define PA_SC_WINDOW_SCISSOR_BR__BR_X__SHIFT 0x0
+#define PA_SC_WINDOW_SCISSOR_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_WINDOW_SCISSOR_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_0_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_0_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_1_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_1_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_2_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_2_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_3_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_3_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_4_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_4_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_5_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_5_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_6_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_6_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_7_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_7_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_8_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_8_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_9_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_9_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_10_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_10_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_11_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_11_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_12_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_12_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_13_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_13_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_14_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_14_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_15_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000
+#define PA_SC_VPORT_SCISSOR_15_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x1f
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_X_MASK 0x7fff
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_X__SHIFT 0x0
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_Y_MASK 0x7fff0000
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_Y__SHIFT 0x10
+#define PA_SC_VPORT_ZMIN_0__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_0__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_1__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_1__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_2__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_2__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_3__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_3__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_4__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_4__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_5__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_5__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_6__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_6__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_7__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_7__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_8__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_8__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_9__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_9__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_10__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_10__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_11__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_11__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_12__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_12__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_13__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_13__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_14__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_14__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMIN_15__VPORT_ZMIN_MASK 0xffffffff
+#define PA_SC_VPORT_ZMIN_15__VPORT_ZMIN__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_0__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_0__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_1__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_1__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_2__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_2__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_3__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_3__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_4__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_4__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_5__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_5__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_6__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_6__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_7__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_7__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_8__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_8__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_9__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_9__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_10__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_10__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_11__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_11__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_12__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_12__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_13__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_13__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_14__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_14__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_VPORT_ZMAX_15__VPORT_ZMAX_MASK 0xffffffff
+#define PA_SC_VPORT_ZMAX_15__VPORT_ZMAX__SHIFT 0x0
+#define PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER_MASK 0x1
+#define PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER__SHIFT 0x0
+#define PA_SC_ENHANCE__DISABLE_SC_DB_TILE_FIX_MASK 0x2
+#define PA_SC_ENHANCE__DISABLE_SC_DB_TILE_FIX__SHIFT 0x1
+#define PA_SC_ENHANCE__DISABLE_AA_MASK_FULL_FIX_MASK 0x4
+#define PA_SC_ENHANCE__DISABLE_AA_MASK_FULL_FIX__SHIFT 0x2
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOCATIONS_MASK 0x8
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOCATIONS__SHIFT 0x3
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOC_CENTROID_MASK 0x10
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOC_CENTROID__SHIFT 0x4
+#define PA_SC_ENHANCE__DISABLE_SCISSOR_FIX_MASK 0x20
+#define PA_SC_ENHANCE__DISABLE_SCISSOR_FIX__SHIFT 0x5
+#define PA_SC_ENHANCE__DISABLE_PW_BUBBLE_COLLAPSE_MASK 0xc0
+#define PA_SC_ENHANCE__DISABLE_PW_BUBBLE_COLLAPSE__SHIFT 0x6
+#define PA_SC_ENHANCE__SEND_UNLIT_STILES_TO_PACKER_MASK 0x100
+#define PA_SC_ENHANCE__SEND_UNLIT_STILES_TO_PACKER__SHIFT 0x8
+#define PA_SC_ENHANCE__DISABLE_DUALGRAD_PERF_OPTIMIZATION_MASK 0x200
+#define PA_SC_ENHANCE__DISABLE_DUALGRAD_PERF_OPTIMIZATION__SHIFT 0x9
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_PRIM_MASK 0x400
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_PRIM__SHIFT 0xa
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_SUPERTILE_MASK 0x800
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_SUPERTILE__SHIFT 0xb
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_TILE_MASK 0x1000
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_TILE__SHIFT 0xc
+#define PA_SC_ENHANCE__DISABLE_PA_SC_GUIDANCE_MASK 0x2000
+#define PA_SC_ENHANCE__DISABLE_PA_SC_GUIDANCE__SHIFT 0xd
+#define PA_SC_ENHANCE__DISABLE_EOV_ALL_CTRL_ONLY_COMBINATIONS_MASK 0x4000
+#define PA_SC_ENHANCE__DISABLE_EOV_ALL_CTRL_ONLY_COMBINATIONS__SHIFT 0xe
+#define PA_SC_ENHANCE__ENABLE_MULTICYCLE_BUBBLE_FREEZE_MASK 0x8000
+#define PA_SC_ENHANCE__ENABLE_MULTICYCLE_BUBBLE_FREEZE__SHIFT 0xf
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_PA_SC_GUIDANCE_MASK 0x10000
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_PA_SC_GUIDANCE__SHIFT 0x10
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_POLY_MODE_MASK 0x20000
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_POLY_MODE__SHIFT 0x11
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EOP_SYNC_NULL_PRIMS_LAST_MASK 0x40000
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EOP_SYNC_NULL_PRIMS_LAST__SHIFT 0x12
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_THRESHOLD_SWITCHING_MASK 0x80000
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_THRESHOLD_SWITCHING__SHIFT 0x13
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_THRESHOLD_SWITCH_AT_EOPG_ONLY_MASK 0x100000
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_THRESHOLD_SWITCH_AT_EOPG_ONLY__SHIFT 0x14
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_DESIRED_FIFO_EMPTY_SWITCHING_MASK 0x200000
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_DESIRED_FIFO_EMPTY_SWITCHING__SHIFT 0x15
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_SELECTED_FIFO_EMPTY_SWITCHING_MASK 0x400000
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_SELECTED_FIFO_EMPTY_SWITCHING__SHIFT 0x16
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EMPTY_SWITCHING_HYSTERYSIS_MASK 0x800000
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EMPTY_SWITCHING_HYSTERYSIS__SHIFT 0x17
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_DESIRED_FIFO_IS_NEXT_FEID_MASK 0x1000000
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_DESIRED_FIFO_IS_NEXT_FEID__SHIFT 0x18
+#define PA_SC_ENHANCE__DISABLE_OOO_NO_EOPG_SKEW_DESIRED_FIFO_IS_CURRENT_FIFO_MASK 0x2000000
+#define PA_SC_ENHANCE__DISABLE_OOO_NO_EOPG_SKEW_DESIRED_FIFO_IS_CURRENT_FIFO__SHIFT 0x19
+#define PA_SC_ENHANCE__OOO_DISABLE_EOP_ON_FIRST_LIVE_PRIM_HIT_MASK 0x4000000
+#define PA_SC_ENHANCE__OOO_DISABLE_EOP_ON_FIRST_LIVE_PRIM_HIT__SHIFT 0x1a
+#define PA_SC_ENHANCE__OOO_DISABLE_EOPG_SKEW_THRESHOLD_SWITCHING_MASK 0x8000000
+#define PA_SC_ENHANCE__OOO_DISABLE_EOPG_SKEW_THRESHOLD_SWITCHING__SHIFT 0x1b
+#define PA_SC_ENHANCE__DISABLE_EOP_LINE_STIPPLE_RESET_MASK 0x10000000
+#define PA_SC_ENHANCE__DISABLE_EOP_LINE_STIPPLE_RESET__SHIFT 0x1c
+#define PA_SC_ENHANCE__DISABLE_VPZ_EOP_LINE_STIPPLE_RESET_MASK 0x20000000
+#define PA_SC_ENHANCE__DISABLE_VPZ_EOP_LINE_STIPPLE_RESET__SHIFT 0x1d
+#define PA_SC_ENHANCE__ECO_SPARE1_MASK 0x40000000
+#define PA_SC_ENHANCE__ECO_SPARE1__SHIFT 0x1e
+#define PA_SC_ENHANCE__ECO_SPARE0_MASK 0x80000000
+#define PA_SC_ENHANCE__ECO_SPARE0__SHIFT 0x1f
+#define PA_SC_ENHANCE_1__REALIGN_DQUADS_OVERRIDE_ENABLE_MASK 0x1
+#define PA_SC_ENHANCE_1__REALIGN_DQUADS_OVERRIDE_ENABLE__SHIFT 0x0
+#define PA_SC_ENHANCE_1__REALIGN_DQUADS_OVERRIDE_MASK 0x6
+#define PA_SC_ENHANCE_1__REALIGN_DQUADS_OVERRIDE__SHIFT 0x1
+#define PA_SC_ENHANCE_1__ENABLE_SC_BINNING_MASK 0x8
+#define PA_SC_ENHANCE_1__ENABLE_SC_BINNING__SHIFT 0x3
+#define PA_SC_ENHANCE_1__ECO_SPARE0_MASK 0x10
+#define PA_SC_ENHANCE_1__ECO_SPARE0__SHIFT 0x4
+#define PA_SC_ENHANCE_1__ECO_SPARE1_MASK 0x20
+#define PA_SC_ENHANCE_1__ECO_SPARE1__SHIFT 0x5
+#define PA_SC_ENHANCE_1__ECO_SPARE2_MASK 0x40
+#define PA_SC_ENHANCE_1__ECO_SPARE2__SHIFT 0x6
+#define PA_SC_ENHANCE_1__ECO_SPARE3_MASK 0x80
+#define PA_SC_ENHANCE_1__ECO_SPARE3__SHIFT 0x7
+#define PA_SC_DSM_CNTL__FORCE_EOV_REZ_0_MASK 0x1
+#define PA_SC_DSM_CNTL__FORCE_EOV_REZ_0__SHIFT 0x0
+#define PA_SC_DSM_CNTL__FORCE_EOV_REZ_1_MASK 0x2
+#define PA_SC_DSM_CNTL__FORCE_EOV_REZ_1__SHIFT 0x1
+#define PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE_MASK 0x3f
+#define PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT 0x0
+#define PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE_MASK 0x7fc0
+#define PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE__SHIFT 0x6
+#define PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE_MASK 0x1f8000
+#define PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT 0xf
+#define PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE_MASK 0xff800000
+#define PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT 0x17
+#define PA_SC_IF_FIFO_SIZE__SC_DB_TILE_IF_FIFO_SIZE_MASK 0x3f
+#define PA_SC_IF_FIFO_SIZE__SC_DB_TILE_IF_FIFO_SIZE__SHIFT 0x0
+#define PA_SC_IF_FIFO_SIZE__SC_DB_QUAD_IF_FIFO_SIZE_MASK 0xfc0
+#define PA_SC_IF_FIFO_SIZE__SC_DB_QUAD_IF_FIFO_SIZE__SHIFT 0x6
+#define PA_SC_IF_FIFO_SIZE__SC_SPI_IF_FIFO_SIZE_MASK 0x3f000
+#define PA_SC_IF_FIFO_SIZE__SC_SPI_IF_FIFO_SIZE__SHIFT 0xc
+#define PA_SC_IF_FIFO_SIZE__SC_BCI_IF_FIFO_SIZE_MASK 0xfc0000
+#define PA_SC_IF_FIFO_SIZE__SC_BCI_IF_FIFO_SIZE__SHIFT 0x12
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_MASK 0xffff
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT__SHIFT 0x0
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_MASK 0xffff0000
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT__SHIFT 0x10
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_PTR_MASK 0xf
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_PTR__SHIFT 0x0
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_COUNT_MASK 0xff00
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_COUNT__SHIFT 0x8
+#define PA_SC_SCREEN_EXTENT_MIN_0__X_MASK 0xffff
+#define PA_SC_SCREEN_EXTENT_MIN_0__X__SHIFT 0x0
+#define PA_SC_SCREEN_EXTENT_MIN_0__Y_MASK 0xffff0000
+#define PA_SC_SCREEN_EXTENT_MIN_0__Y__SHIFT 0x10
+#define PA_SC_SCREEN_EXTENT_MAX_0__X_MASK 0xffff
+#define PA_SC_SCREEN_EXTENT_MAX_0__X__SHIFT 0x0
+#define PA_SC_SCREEN_EXTENT_MAX_0__Y_MASK 0xffff0000
+#define PA_SC_SCREEN_EXTENT_MAX_0__Y__SHIFT 0x10
+#define PA_SC_SCREEN_EXTENT_MIN_1__X_MASK 0xffff
+#define PA_SC_SCREEN_EXTENT_MIN_1__X__SHIFT 0x0
+#define PA_SC_SCREEN_EXTENT_MIN_1__Y_MASK 0xffff0000
+#define PA_SC_SCREEN_EXTENT_MIN_1__Y__SHIFT 0x10
+#define PA_SC_SCREEN_EXTENT_MAX_1__X_MASK 0xffff
+#define PA_SC_SCREEN_EXTENT_MAX_1__X__SHIFT 0x0
+#define PA_SC_SCREEN_EXTENT_MAX_1__Y_MASK 0xffff0000
+#define PA_SC_SCREEN_EXTENT_MAX_1__Y__SHIFT 0x10
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define PA_SC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define PA_SC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define PA_SC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER6_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER6_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER7_SELECT__PERF_SEL_MASK 0x3ff
+#define PA_SC_PERFCOUNTER7_SELECT__PERF_SEL__SHIFT 0x0
+#define PA_SC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER6_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER6_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER6_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER6_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_PERFCOUNTER7_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER7_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define PA_SC_PERFCOUNTER7_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define PA_SC_PERFCOUNTER7_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define PA_SC_P3D_TRAP_SCREEN_HV_EN__ENABLE_HV_PRE_SHADER_MASK 0x1
+#define PA_SC_P3D_TRAP_SCREEN_HV_EN__ENABLE_HV_PRE_SHADER__SHIFT 0x0
+#define PA_SC_P3D_TRAP_SCREEN_HV_EN__FORCE_PRE_SHADER_ALL_PIXELS_MASK 0x2
+#define PA_SC_P3D_TRAP_SCREEN_HV_EN__FORCE_PRE_SHADER_ALL_PIXELS__SHIFT 0x1
+#define PA_SC_P3D_TRAP_SCREEN_H__X_COORD_MASK 0x3fff
+#define PA_SC_P3D_TRAP_SCREEN_H__X_COORD__SHIFT 0x0
+#define PA_SC_P3D_TRAP_SCREEN_V__Y_COORD_MASK 0x3fff
+#define PA_SC_P3D_TRAP_SCREEN_V__Y_COORD__SHIFT 0x0
+#define PA_SC_P3D_TRAP_SCREEN_OCCURRENCE__COUNT_MASK 0xffff
+#define PA_SC_P3D_TRAP_SCREEN_OCCURRENCE__COUNT__SHIFT 0x0
+#define PA_SC_P3D_TRAP_SCREEN_COUNT__COUNT_MASK 0xffff
+#define PA_SC_P3D_TRAP_SCREEN_COUNT__COUNT__SHIFT 0x0
+#define PA_SC_HP3D_TRAP_SCREEN_HV_EN__ENABLE_HV_PRE_SHADER_MASK 0x1
+#define PA_SC_HP3D_TRAP_SCREEN_HV_EN__ENABLE_HV_PRE_SHADER__SHIFT 0x0
+#define PA_SC_HP3D_TRAP_SCREEN_HV_EN__FORCE_PRE_SHADER_ALL_PIXELS_MASK 0x2
+#define PA_SC_HP3D_TRAP_SCREEN_HV_EN__FORCE_PRE_SHADER_ALL_PIXELS__SHIFT 0x1
+#define PA_SC_HP3D_TRAP_SCREEN_H__X_COORD_MASK 0x3fff
+#define PA_SC_HP3D_TRAP_SCREEN_H__X_COORD__SHIFT 0x0
+#define PA_SC_HP3D_TRAP_SCREEN_V__Y_COORD_MASK 0x3fff
+#define PA_SC_HP3D_TRAP_SCREEN_V__Y_COORD__SHIFT 0x0
+#define PA_SC_HP3D_TRAP_SCREEN_OCCURRENCE__COUNT_MASK 0xffff
+#define PA_SC_HP3D_TRAP_SCREEN_OCCURRENCE__COUNT__SHIFT 0x0
+#define PA_SC_HP3D_TRAP_SCREEN_COUNT__COUNT_MASK 0xffff
+#define PA_SC_HP3D_TRAP_SCREEN_COUNT__COUNT__SHIFT 0x0
+#define PA_SC_TRAP_SCREEN_HV_EN__ENABLE_HV_PRE_SHADER_MASK 0x1
+#define PA_SC_TRAP_SCREEN_HV_EN__ENABLE_HV_PRE_SHADER__SHIFT 0x0
+#define PA_SC_TRAP_SCREEN_HV_EN__FORCE_PRE_SHADER_ALL_PIXELS_MASK 0x2
+#define PA_SC_TRAP_SCREEN_HV_EN__FORCE_PRE_SHADER_ALL_PIXELS__SHIFT 0x1
+#define PA_SC_TRAP_SCREEN_H__X_COORD_MASK 0x3fff
+#define PA_SC_TRAP_SCREEN_H__X_COORD__SHIFT 0x0
+#define PA_SC_TRAP_SCREEN_V__Y_COORD_MASK 0x3fff
+#define PA_SC_TRAP_SCREEN_V__Y_COORD__SHIFT 0x0
+#define PA_SC_TRAP_SCREEN_OCCURRENCE__COUNT_MASK 0xffff
+#define PA_SC_TRAP_SCREEN_OCCURRENCE__COUNT__SHIFT 0x0
+#define PA_SC_TRAP_SCREEN_COUNT__COUNT_MASK 0xffff
+#define PA_SC_TRAP_SCREEN_COUNT__COUNT__SHIFT 0x0
+#define PA_SC_P3D_TRAP_SCREEN_HV_LOCK__DISABLE_NON_PRIV_WRITES_MASK 0x1
+#define PA_SC_P3D_TRAP_SCREEN_HV_LOCK__DISABLE_NON_PRIV_WRITES__SHIFT 0x0
+#define PA_SC_HP3D_TRAP_SCREEN_HV_LOCK__DISABLE_NON_PRIV_WRITES_MASK 0x1
+#define PA_SC_HP3D_TRAP_SCREEN_HV_LOCK__DISABLE_NON_PRIV_WRITES__SHIFT 0x0
+#define PA_SC_TRAP_SCREEN_HV_LOCK__DISABLE_NON_PRIV_WRITES_MASK 0x1
+#define PA_SC_TRAP_SCREEN_HV_LOCK__DISABLE_NON_PRIV_WRITES__SHIFT 0x0
+#define PA_CL_CNTL_STATUS__CL_BUSY_MASK 0x80000000
+#define PA_CL_CNTL_STATUS__CL_BUSY__SHIFT 0x1f
+#define PA_SU_CNTL_STATUS__SU_BUSY_MASK 0x80000000
+#define PA_SU_CNTL_STATUS__SU_BUSY__SHIFT 0x1f
+#define PA_SC_FIFO_DEPTH_CNTL__DEPTH_MASK 0x3ff
+#define PA_SC_FIFO_DEPTH_CNTL__DEPTH__SHIFT 0x0
+#define CGTT_PA_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_PA_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_PA_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_PA_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_PA_CLK_CTRL__SU_CLK_OVERRIDE_MASK 0x20000000
+#define CGTT_PA_CLK_CTRL__SU_CLK_OVERRIDE__SHIFT 0x1d
+#define CGTT_PA_CLK_CTRL__CL_CLK_OVERRIDE_MASK 0x40000000
+#define CGTT_PA_CLK_CTRL__CL_CLK_OVERRIDE__SHIFT 0x1e
+#define CGTT_PA_CLK_CTRL__REG_CLK_OVERRIDE_MASK 0x80000000
+#define CGTT_PA_CLK_CTRL__REG_CLK_OVERRIDE__SHIFT 0x1f
+#define CGTT_SC_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_SC_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_SC_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define PA_SU_DEBUG_CNTL__SU_DEBUG_INDX_MASK 0x1f
+#define PA_SU_DEBUG_CNTL__SU_DEBUG_INDX__SHIFT 0x0
+#define PA_SU_DEBUG_DATA__DATA_MASK 0xffffffff
+#define PA_SU_DEBUG_DATA__DATA__SHIFT 0x0
+#define PA_SC_DEBUG_CNTL__SC_DEBUG_INDX_MASK 0x3f
+#define PA_SC_DEBUG_CNTL__SC_DEBUG_INDX__SHIFT 0x0
+#define PA_SC_DEBUG_DATA__DATA_MASK 0xffffffff
+#define PA_SC_DEBUG_DATA__DATA__SHIFT 0x0
+#define CLIPPER_DEBUG_REG00__ALWAYS_ZERO_MASK 0xff
+#define CLIPPER_DEBUG_REG00__ALWAYS_ZERO__SHIFT 0x0
+#define CLIPPER_DEBUG_REG00__clip_ga_bc_fifo_write_MASK 0x100
+#define CLIPPER_DEBUG_REG00__clip_ga_bc_fifo_write__SHIFT 0x8
+#define CLIPPER_DEBUG_REG00__su_clip_baryc_free_MASK 0x600
+#define CLIPPER_DEBUG_REG00__su_clip_baryc_free__SHIFT 0x9
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_write_MASK 0x800
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_write__SHIFT 0xb
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_full_MASK 0x1000
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_full__SHIFT 0xc
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_empty_MASK 0x2000
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_empty__SHIFT 0xd
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_full_MASK 0x4000
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_full__SHIFT 0xe
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_empty_MASK 0x8000
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_empty__SHIFT 0xf
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_full_MASK 0x10000
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_full__SHIFT 0x10
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_empty_MASK 0x20000
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_empty__SHIFT 0x11
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_full_MASK 0x40000
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_full__SHIFT 0x12
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_empty_MASK 0x80000
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_empty__SHIFT 0x13
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_full_MASK 0x100000
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_full__SHIFT 0x14
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_fifo_empty_MASK 0x200000
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_fifo_empty__SHIFT 0x15
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_full_MASK 0x400000
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_full__SHIFT 0x16
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_empty_MASK 0x800000
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_empty__SHIFT 0x17
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_full_MASK 0x1000000
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_full__SHIFT 0x18
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_empty_MASK 0x2000000
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_empty__SHIFT 0x19
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_full_MASK 0x4000000
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_full__SHIFT 0x1a
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_empty_MASK 0x8000000
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_empty__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_full_MASK 0x10000000
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_full__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_write_MASK 0x20000000
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_write__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_write_MASK 0x40000000
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_write__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_write_MASK 0x80000000
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_write__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG01__ALWAYS_ZERO_MASK 0xff
+#define CLIPPER_DEBUG_REG01__ALWAYS_ZERO__SHIFT 0x0
+#define CLIPPER_DEBUG_REG01__clip_extra_bc_valid_MASK 0x700
+#define CLIPPER_DEBUG_REG01__clip_extra_bc_valid__SHIFT 0x8
+#define CLIPPER_DEBUG_REG01__clip_vert_vte_valid_MASK 0x3800
+#define CLIPPER_DEBUG_REG01__clip_vert_vte_valid__SHIFT 0xb
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_vertex_deallocate_MASK 0x1c000
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_vertex_deallocate__SHIFT 0xe
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_deallocate_slot_MASK 0xe0000
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_deallocate_slot__SHIFT 0x11
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_null_primitive_MASK 0x100000
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_null_primitive__SHIFT 0x14
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_2_MASK 0x200000
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_2__SHIFT 0x15
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_1_MASK 0x400000
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_1__SHIFT 0x16
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_0_MASK 0x800000
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_0__SHIFT 0x17
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_extra_bc_valid_MASK 0x1000000
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_extra_bc_valid__SHIFT 0x18
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vte_naninf_kill_MASK 0x2000000
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vte_naninf_kill__SHIFT 0x19
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vertex_store_indx_MASK 0xc000000
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vertex_store_indx__SHIFT 0x1a
+#define CLIPPER_DEBUG_REG01__clip_ga_bc_fifo_write_MASK 0x10000000
+#define CLIPPER_DEBUG_REG01__clip_ga_bc_fifo_write__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG01__clip_to_ga_fifo_write_MASK 0x20000000
+#define CLIPPER_DEBUG_REG01__clip_to_ga_fifo_write__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_advanceread_MASK 0x40000000
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_advanceread__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_empty_MASK 0x80000000
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_empty__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG02__clip_extra_bc_valid_MASK 0x7
+#define CLIPPER_DEBUG_REG02__clip_extra_bc_valid__SHIFT 0x0
+#define CLIPPER_DEBUG_REG02__clip_vert_vte_valid_MASK 0x38
+#define CLIPPER_DEBUG_REG02__clip_vert_vte_valid__SHIFT 0x3
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clip_seq_indx_MASK 0xc0
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clip_seq_indx__SHIFT 0x6
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_2_MASK 0xf00
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_2__SHIFT 0x8
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_1_MASK 0xf000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_1__SHIFT 0xc
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_0_MASK 0xf0000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_0__SHIFT 0x10
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_extra_bc_coords_MASK 0x100000
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_extra_bc_coords__SHIFT 0x14
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_vte_naninf_kill_MASK 0x200000
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_vte_naninf_kill__SHIFT 0x15
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_end_of_packet_MASK 0x400000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_end_of_packet__SHIFT 0x16
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_first_prim_of_slot_MASK 0x800000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_first_prim_of_slot__SHIFT 0x17
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clipped_prim_MASK 0x1000000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clipped_prim__SHIFT 0x18
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_null_primitive_MASK 0x2000000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_null_primitive__SHIFT 0x19
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_full_MASK 0x4000000
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_full__SHIFT 0x1a
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_full_MASK 0x8000000
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_full__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_write_MASK 0x10000000
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_write__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_write_MASK 0x20000000
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_write__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_advanceread_MASK 0x40000000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_advanceread__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_empty_MASK 0x80000000
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_empty__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_code_or_MASK 0x3fff
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_code_or__SHIFT 0x0
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_id_MASK 0xfc000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_id__SHIFT 0xe
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_state_var_indx_MASK 0x700000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_state_var_indx__SHIFT 0x14
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_primitive_MASK 0x800000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_primitive__SHIFT 0x17
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_deallocate_slot_MASK 0x7000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_deallocate_slot__SHIFT 0x18
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_first_prim_of_slot_MASK 0x8000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_first_prim_of_slot__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_end_of_packet_MASK 0x10000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_end_of_packet__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_param_cache_indx_0_MASK 0x7fe
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_param_cache_indx_0__SHIFT 0x1
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_2_MASK 0x1f800
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_2__SHIFT 0xb
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_1_MASK 0x7e0000
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_1__SHIFT 0x11
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_0__SHIFT 0x17
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_code_or_MASK 0x3fff
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_code_or__SHIFT 0x0
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_id_MASK 0xfc000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_id__SHIFT 0xe
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_state_var_indx_MASK 0x700000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_state_var_indx__SHIFT 0x14
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_primitive_MASK 0x800000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_primitive__SHIFT 0x17
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_deallocate_slot_MASK 0x7000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_deallocate_slot__SHIFT 0x18
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_first_prim_of_slot_MASK 0x8000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_first_prim_of_slot__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_end_of_packet_MASK 0x10000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_end_of_packet__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_param_cache_indx_0_MASK 0x7fe
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_param_cache_indx_0__SHIFT 0x1
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_2_MASK 0x1f800
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_2__SHIFT 0xb
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_1_MASK 0x7e0000
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_1__SHIFT 0x11
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_0__SHIFT 0x17
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_code_or_MASK 0x3fff
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_code_or__SHIFT 0x0
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_id_MASK 0xfc000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_id__SHIFT 0xe
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_state_var_indx_MASK 0x700000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_state_var_indx__SHIFT 0x14
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_primitive_MASK 0x800000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_primitive__SHIFT 0x17
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_deallocate_slot_MASK 0x7000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_deallocate_slot__SHIFT 0x18
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_first_prim_of_slot_MASK 0x8000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_first_prim_of_slot__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_end_of_packet_MASK 0x10000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_end_of_packet__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_param_cache_indx_0_MASK 0x7fe
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_param_cache_indx_0__SHIFT 0x1
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_2_MASK 0x1f800
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_2__SHIFT 0xb
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_1_MASK 0x7e0000
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_1__SHIFT 0x11
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_0__SHIFT 0x17
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_code_or_MASK 0x3fff
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_code_or__SHIFT 0x0
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_id_MASK 0xfc000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_id__SHIFT 0xe
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_state_var_indx_MASK 0x700000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_state_var_indx__SHIFT 0x14
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_primitive_MASK 0x800000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_primitive__SHIFT 0x17
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_deallocate_slot_MASK 0x7000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_deallocate_slot__SHIFT 0x18
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_first_prim_of_slot_MASK 0x8000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_first_prim_of_slot__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_end_of_packet_MASK 0x10000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_end_of_packet__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_param_cache_indx_0_MASK 0x7fe
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_param_cache_indx_0__SHIFT 0x1
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_2_MASK 0x1f800
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_2__SHIFT 0xb
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_1_MASK 0x7e0000
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_1__SHIFT 0x11
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_0__SHIFT 0x17
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_event_MASK 0x20000000
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_event__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_null_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_null_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_event_MASK 0x1
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_event__SHIFT 0x0
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_event_MASK 0x2
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_event__SHIFT 0x1
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_event_MASK 0x4
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_event__SHIFT 0x2
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_event_MASK 0x8
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_event__SHIFT 0x3
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_primitive_MASK 0x10
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_primitive__SHIFT 0x4
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_primitive_MASK 0x20
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_primitive__SHIFT 0x5
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_primitive_MASK 0x40
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_primitive__SHIFT 0x6
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_primitive_MASK 0x80
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_primitive__SHIFT 0x7
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_to_outsm_cnt_MASK 0xf00
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x8
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_to_outsm_cnt_MASK 0xf000
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0xc
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_to_outsm_cnt_MASK 0xf0000
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x10
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_to_outsm_cnt_MASK 0xf00000
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x14
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_prim_valid_MASK 0x1000000
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_prim_valid__SHIFT 0x18
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_prim_valid_MASK 0x2000000
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_prim_valid__SHIFT 0x19
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_prim_valid_MASK 0x4000000
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_prim_valid__SHIFT 0x1a
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_prim_valid_MASK 0x8000000
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_prim_valid__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG11__clipsm3_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x10000000
+#define CLIPPER_DEBUG_REG11__clipsm3_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG11__clipsm2_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x20000000
+#define CLIPPER_DEBUG_REG11__clipsm2_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG11__clipsm1_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x40000000
+#define CLIPPER_DEBUG_REG11__clipsm1_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG11__clipsm0_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x80000000
+#define CLIPPER_DEBUG_REG11__clipsm0_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG12__ALWAYS_ZERO_MASK 0xff
+#define CLIPPER_DEBUG_REG12__ALWAYS_ZERO__SHIFT 0x0
+#define CLIPPER_DEBUG_REG12__clip_priority_available_vte_out_clip_MASK 0x1f00
+#define CLIPPER_DEBUG_REG12__clip_priority_available_vte_out_clip__SHIFT 0x8
+#define CLIPPER_DEBUG_REG12__clip_priority_available_clip_verts_MASK 0x3e000
+#define CLIPPER_DEBUG_REG12__clip_priority_available_clip_verts__SHIFT 0xd
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_out_MASK 0xc0000
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_out__SHIFT 0x12
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_vert_MASK 0x300000
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_vert__SHIFT 0x14
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_load_MASK 0xc00000
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_load__SHIFT 0x16
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_clip_primitive_MASK 0x1000000
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_clip_primitive__SHIFT 0x18
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_prim_valid_MASK 0x2000000
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x19
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_clip_primitive_MASK 0x4000000
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_clip_primitive__SHIFT 0x1a
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_prim_valid_MASK 0x8000000
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_clip_primitive_MASK 0x10000000
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_clip_primitive__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_prim_valid_MASK 0x20000000
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_clip_primitive_MASK 0x40000000
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_clip_primitive__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG13__clprim_in_back_state_var_indx_MASK 0x7
+#define CLIPPER_DEBUG_REG13__clprim_in_back_state_var_indx__SHIFT 0x0
+#define CLIPPER_DEBUG_REG13__point_clip_candidate_MASK 0x8
+#define CLIPPER_DEBUG_REG13__point_clip_candidate__SHIFT 0x3
+#define CLIPPER_DEBUG_REG13__prim_nan_kill_MASK 0x10
+#define CLIPPER_DEBUG_REG13__prim_nan_kill__SHIFT 0x4
+#define CLIPPER_DEBUG_REG13__clprim_clip_primitive_MASK 0x20
+#define CLIPPER_DEBUG_REG13__clprim_clip_primitive__SHIFT 0x5
+#define CLIPPER_DEBUG_REG13__clprim_cull_primitive_MASK 0x40
+#define CLIPPER_DEBUG_REG13__clprim_cull_primitive__SHIFT 0x6
+#define CLIPPER_DEBUG_REG13__prim_back_valid_MASK 0x80
+#define CLIPPER_DEBUG_REG13__prim_back_valid__SHIFT 0x7
+#define CLIPPER_DEBUG_REG13__vertval_bits_vertex_cc_next_valid_MASK 0xf00
+#define CLIPPER_DEBUG_REG13__vertval_bits_vertex_cc_next_valid__SHIFT 0x8
+#define CLIPPER_DEBUG_REG13__clipcc_vertex_store_indx_MASK 0x3000
+#define CLIPPER_DEBUG_REG13__clipcc_vertex_store_indx__SHIFT 0xc
+#define CLIPPER_DEBUG_REG13__vte_out_orig_fifo_fifo_empty_MASK 0x4000
+#define CLIPPER_DEBUG_REG13__vte_out_orig_fifo_fifo_empty__SHIFT 0xe
+#define CLIPPER_DEBUG_REG13__clipcode_fifo_fifo_empty_MASK 0x8000
+#define CLIPPER_DEBUG_REG13__clipcode_fifo_fifo_empty__SHIFT 0xf
+#define CLIPPER_DEBUG_REG13__ccgen_to_clipcc_fifo_empty_MASK 0x10000
+#define CLIPPER_DEBUG_REG13__ccgen_to_clipcc_fifo_empty__SHIFT 0x10
+#define CLIPPER_DEBUG_REG13__clip_priority_seq_indx_out_cnt_MASK 0x1e0000
+#define CLIPPER_DEBUG_REG13__clip_priority_seq_indx_out_cnt__SHIFT 0x11
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_orig_vertices_MASK 0x600000
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_orig_vertices__SHIFT 0x15
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_clipsm_wait_MASK 0x800000
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_clipsm_wait__SHIFT 0x17
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_contents_MASK 0x1f000000
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_contents__SHIFT 0x18
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_full_MASK 0x20000000
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_full__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_advanceread_MASK 0x40000000
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_advanceread__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_write_MASK 0x80000000
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_write__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_2_MASK 0x3f
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_2__SHIFT 0x0
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_1_MASK 0xfc0
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_1__SHIFT 0x6
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_0_MASK 0x3f000
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_0__SHIFT 0xc
+#define CLIPPER_DEBUG_REG14__outputclprimtoclip_null_primitive_MASK 0x40000
+#define CLIPPER_DEBUG_REG14__outputclprimtoclip_null_primitive__SHIFT 0x12
+#define CLIPPER_DEBUG_REG14__clprim_in_back_end_of_packet_MASK 0x80000
+#define CLIPPER_DEBUG_REG14__clprim_in_back_end_of_packet__SHIFT 0x13
+#define CLIPPER_DEBUG_REG14__clprim_in_back_first_prim_of_slot_MASK 0x100000
+#define CLIPPER_DEBUG_REG14__clprim_in_back_first_prim_of_slot__SHIFT 0x14
+#define CLIPPER_DEBUG_REG14__clprim_in_back_deallocate_slot_MASK 0xe00000
+#define CLIPPER_DEBUG_REG14__clprim_in_back_deallocate_slot__SHIFT 0x15
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_id_MASK 0x3f000000
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_id__SHIFT 0x18
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_MASK 0x40000000
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG14__prim_back_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG14__prim_back_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG15__vertval_bits_vertex_vertex_store_msb_MASK 0xffff
+#define CLIPPER_DEBUG_REG15__vertval_bits_vertex_vertex_store_msb__SHIFT 0x0
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_2_MASK 0x1f0000
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_2__SHIFT 0x10
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_1_MASK 0x3e00000
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_1__SHIFT 0x15
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_0_MASK 0x7c000000
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_0__SHIFT 0x1a
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG16__sm0_prim_end_state_MASK 0x7f
+#define CLIPPER_DEBUG_REG16__sm0_prim_end_state__SHIFT 0x0
+#define CLIPPER_DEBUG_REG16__sm0_ps_expand_MASK 0x80
+#define CLIPPER_DEBUG_REG16__sm0_ps_expand__SHIFT 0x7
+#define CLIPPER_DEBUG_REG16__sm0_clip_vert_cnt_MASK 0x1f00
+#define CLIPPER_DEBUG_REG16__sm0_clip_vert_cnt__SHIFT 0x8
+#define CLIPPER_DEBUG_REG16__sm0_vertex_clip_cnt_MASK 0x3e000
+#define CLIPPER_DEBUG_REG16__sm0_vertex_clip_cnt__SHIFT 0xd
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_1_MASK 0x40000
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_1__SHIFT 0x12
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_0_MASK 0x80000
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_0__SHIFT 0x13
+#define CLIPPER_DEBUG_REG16__sm0_current_state_MASK 0x7f00000
+#define CLIPPER_DEBUG_REG16__sm0_current_state__SHIFT 0x14
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x8000000
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_outsm_fifo_full_MASK 0x10000000
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_outsm_fifo_full__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG16__sm0_highest_priority_seq_MASK 0x20000000
+#define CLIPPER_DEBUG_REG16__sm0_highest_priority_seq__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG16__sm0_outputcliptoclipga_0_MASK 0x40000000
+#define CLIPPER_DEBUG_REG16__sm0_outputcliptoclipga_0__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG16__sm0_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG16__sm0_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG17__sm1_prim_end_state_MASK 0x7f
+#define CLIPPER_DEBUG_REG17__sm1_prim_end_state__SHIFT 0x0
+#define CLIPPER_DEBUG_REG17__sm1_ps_expand_MASK 0x80
+#define CLIPPER_DEBUG_REG17__sm1_ps_expand__SHIFT 0x7
+#define CLIPPER_DEBUG_REG17__sm1_clip_vert_cnt_MASK 0x1f00
+#define CLIPPER_DEBUG_REG17__sm1_clip_vert_cnt__SHIFT 0x8
+#define CLIPPER_DEBUG_REG17__sm1_vertex_clip_cnt_MASK 0x3e000
+#define CLIPPER_DEBUG_REG17__sm1_vertex_clip_cnt__SHIFT 0xd
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_1_MASK 0x40000
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_1__SHIFT 0x12
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_0_MASK 0x80000
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_0__SHIFT 0x13
+#define CLIPPER_DEBUG_REG17__sm1_current_state_MASK 0x7f00000
+#define CLIPPER_DEBUG_REG17__sm1_current_state__SHIFT 0x14
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x8000000
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_outsm_fifo_full_MASK 0x10000000
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_outsm_fifo_full__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG17__sm1_highest_priority_seq_MASK 0x20000000
+#define CLIPPER_DEBUG_REG17__sm1_highest_priority_seq__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG17__sm1_outputcliptoclipga_0_MASK 0x40000000
+#define CLIPPER_DEBUG_REG17__sm1_outputcliptoclipga_0__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG17__sm1_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG17__sm1_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG18__sm2_prim_end_state_MASK 0x7f
+#define CLIPPER_DEBUG_REG18__sm2_prim_end_state__SHIFT 0x0
+#define CLIPPER_DEBUG_REG18__sm2_ps_expand_MASK 0x80
+#define CLIPPER_DEBUG_REG18__sm2_ps_expand__SHIFT 0x7
+#define CLIPPER_DEBUG_REG18__sm2_clip_vert_cnt_MASK 0x1f00
+#define CLIPPER_DEBUG_REG18__sm2_clip_vert_cnt__SHIFT 0x8
+#define CLIPPER_DEBUG_REG18__sm2_vertex_clip_cnt_MASK 0x3e000
+#define CLIPPER_DEBUG_REG18__sm2_vertex_clip_cnt__SHIFT 0xd
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_1_MASK 0x40000
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_1__SHIFT 0x12
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_0_MASK 0x80000
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_0__SHIFT 0x13
+#define CLIPPER_DEBUG_REG18__sm2_current_state_MASK 0x7f00000
+#define CLIPPER_DEBUG_REG18__sm2_current_state__SHIFT 0x14
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x8000000
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_outsm_fifo_full_MASK 0x10000000
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_outsm_fifo_full__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG18__sm2_highest_priority_seq_MASK 0x20000000
+#define CLIPPER_DEBUG_REG18__sm2_highest_priority_seq__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG18__sm2_outputcliptoclipga_0_MASK 0x40000000
+#define CLIPPER_DEBUG_REG18__sm2_outputcliptoclipga_0__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG18__sm2_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG18__sm2_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define CLIPPER_DEBUG_REG19__sm3_prim_end_state_MASK 0x7f
+#define CLIPPER_DEBUG_REG19__sm3_prim_end_state__SHIFT 0x0
+#define CLIPPER_DEBUG_REG19__sm3_ps_expand_MASK 0x80
+#define CLIPPER_DEBUG_REG19__sm3_ps_expand__SHIFT 0x7
+#define CLIPPER_DEBUG_REG19__sm3_clip_vert_cnt_MASK 0x1f00
+#define CLIPPER_DEBUG_REG19__sm3_clip_vert_cnt__SHIFT 0x8
+#define CLIPPER_DEBUG_REG19__sm3_vertex_clip_cnt_MASK 0x3e000
+#define CLIPPER_DEBUG_REG19__sm3_vertex_clip_cnt__SHIFT 0xd
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_1_MASK 0x40000
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_1__SHIFT 0x12
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_0_MASK 0x80000
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_0__SHIFT 0x13
+#define CLIPPER_DEBUG_REG19__sm3_current_state_MASK 0x7f00000
+#define CLIPPER_DEBUG_REG19__sm3_current_state__SHIFT 0x14
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x8000000
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x1b
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_outsm_fifo_full_MASK 0x10000000
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_outsm_fifo_full__SHIFT 0x1c
+#define CLIPPER_DEBUG_REG19__sm3_highest_priority_seq_MASK 0x20000000
+#define CLIPPER_DEBUG_REG19__sm3_highest_priority_seq__SHIFT 0x1d
+#define CLIPPER_DEBUG_REG19__sm3_outputcliptoclipga_0_MASK 0x40000000
+#define CLIPPER_DEBUG_REG19__sm3_outputcliptoclipga_0__SHIFT 0x1e
+#define CLIPPER_DEBUG_REG19__sm3_clprim_to_clip_prim_valid_MASK 0x80000000
+#define CLIPPER_DEBUG_REG19__sm3_clprim_to_clip_prim_valid__SHIFT 0x1f
+#define SXIFCCG_DEBUG_REG0__position_address_MASK 0x3f
+#define SXIFCCG_DEBUG_REG0__position_address__SHIFT 0x0
+#define SXIFCCG_DEBUG_REG0__point_address_MASK 0x1c0
+#define SXIFCCG_DEBUG_REG0__point_address__SHIFT 0x6
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_state_var_indx_MASK 0xe00
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_state_var_indx__SHIFT 0x9
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_req_mask_MASK 0xf000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_req_mask__SHIFT 0xc
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_pci_MASK 0x3ff0000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_pci__SHIFT 0x10
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_sel_MASK 0xc000000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_sel__SHIFT 0x1a
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_sp_id_MASK 0x30000000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_sp_id__SHIFT 0x1c
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_inc_MASK 0x40000000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_inc__SHIFT 0x1e
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_advance_MASK 0x80000000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_advance__SHIFT 0x1f
+#define SXIFCCG_DEBUG_REG1__available_positions_MASK 0x7f
+#define SXIFCCG_DEBUG_REG1__available_positions__SHIFT 0x0
+#define SXIFCCG_DEBUG_REG1__sx_receive_indx_MASK 0x380
+#define SXIFCCG_DEBUG_REG1__sx_receive_indx__SHIFT 0x7
+#define SXIFCCG_DEBUG_REG1__sx_pending_fifo_contents_MASK 0x7c00
+#define SXIFCCG_DEBUG_REG1__sx_pending_fifo_contents__SHIFT 0xa
+#define SXIFCCG_DEBUG_REG1__statevar_bits_vs_out_misc_vec_ena_MASK 0x8000
+#define SXIFCCG_DEBUG_REG1__statevar_bits_vs_out_misc_vec_ena__SHIFT 0xf
+#define SXIFCCG_DEBUG_REG1__statevar_bits_disable_sp_MASK 0xf0000
+#define SXIFCCG_DEBUG_REG1__statevar_bits_disable_sp__SHIFT 0x10
+#define SXIFCCG_DEBUG_REG1__aux_sel_MASK 0x300000
+#define SXIFCCG_DEBUG_REG1__aux_sel__SHIFT 0x14
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_1_MASK 0x400000
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_1__SHIFT 0x16
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_0_MASK 0x800000
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_0__SHIFT 0x17
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_1_MASK 0xf000000
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_1__SHIFT 0x18
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_0_MASK 0xf0000000
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_0__SHIFT 0x1c
+#define SXIFCCG_DEBUG_REG2__param_cache_base_MASK 0x7f
+#define SXIFCCG_DEBUG_REG2__param_cache_base__SHIFT 0x0
+#define SXIFCCG_DEBUG_REG2__sx_aux_MASK 0x180
+#define SXIFCCG_DEBUG_REG2__sx_aux__SHIFT 0x7
+#define SXIFCCG_DEBUG_REG2__sx_request_indx_MASK 0x7e00
+#define SXIFCCG_DEBUG_REG2__sx_request_indx__SHIFT 0x9
+#define SXIFCCG_DEBUG_REG2__req_active_verts_loaded_MASK 0x8000
+#define SXIFCCG_DEBUG_REG2__req_active_verts_loaded__SHIFT 0xf
+#define SXIFCCG_DEBUG_REG2__req_active_verts_MASK 0x7f0000
+#define SXIFCCG_DEBUG_REG2__req_active_verts__SHIFT 0x10
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_state_var_indx_MASK 0x3800000
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_state_var_indx__SHIFT 0x17
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_active_verts_MASK 0xfc000000
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_active_verts__SHIFT 0x1a
+#define SXIFCCG_DEBUG_REG3__ALWAYS_ZERO_MASK 0xff
+#define SXIFCCG_DEBUG_REG3__ALWAYS_ZERO__SHIFT 0x0
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_entriesavailable_MASK 0xf00
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_entriesavailable__SHIFT 0x8
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist1_vec_ena_MASK 0x1000
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist1_vec_ena__SHIFT 0xc
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist0_vec_ena_MASK 0x2000
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist0_vec_ena__SHIFT 0xd
+#define SXIFCCG_DEBUG_REG3__available_positions_MASK 0x1fc000
+#define SXIFCCG_DEBUG_REG3__available_positions__SHIFT 0xe
+#define SXIFCCG_DEBUG_REG3__current_state_MASK 0x600000
+#define SXIFCCG_DEBUG_REG3__current_state__SHIFT 0x15
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_empty_MASK 0x800000
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_empty__SHIFT 0x17
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_full_MASK 0x1000000
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_full__SHIFT 0x18
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_empty_MASK 0x2000000
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_empty__SHIFT 0x19
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_full_MASK 0x4000000
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_full__SHIFT 0x1a
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_empty_MASK 0x8000000
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_empty__SHIFT 0x1b
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_full_MASK 0x10000000
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_full__SHIFT 0x1c
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_fifo_full_MASK 0x20000000
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_fifo_full__SHIFT 0x1d
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_write_MASK 0x40000000
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_write__SHIFT 0x1e
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_write_MASK 0x80000000
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_write__SHIFT 0x1f
+#define SETUP_DEBUG_REG0__su_baryc_cntl_state_MASK 0x3
+#define SETUP_DEBUG_REG0__su_baryc_cntl_state__SHIFT 0x0
+#define SETUP_DEBUG_REG0__su_cntl_state_MASK 0x3c
+#define SETUP_DEBUG_REG0__su_cntl_state__SHIFT 0x2
+#define SETUP_DEBUG_REG0__pmode_state_MASK 0x3f00
+#define SETUP_DEBUG_REG0__pmode_state__SHIFT 0x8
+#define SETUP_DEBUG_REG0__ge_stallb_MASK 0x4000
+#define SETUP_DEBUG_REG0__ge_stallb__SHIFT 0xe
+#define SETUP_DEBUG_REG0__geom_enable_MASK 0x8000
+#define SETUP_DEBUG_REG0__geom_enable__SHIFT 0xf
+#define SETUP_DEBUG_REG0__su_clip_baryc_free_MASK 0x30000
+#define SETUP_DEBUG_REG0__su_clip_baryc_free__SHIFT 0x10
+#define SETUP_DEBUG_REG0__su_clip_rtr_MASK 0x40000
+#define SETUP_DEBUG_REG0__su_clip_rtr__SHIFT 0x12
+#define SETUP_DEBUG_REG0__pfifo_busy_MASK 0x80000
+#define SETUP_DEBUG_REG0__pfifo_busy__SHIFT 0x13
+#define SETUP_DEBUG_REG0__su_cntl_busy_MASK 0x100000
+#define SETUP_DEBUG_REG0__su_cntl_busy__SHIFT 0x14
+#define SETUP_DEBUG_REG0__geom_busy_MASK 0x200000
+#define SETUP_DEBUG_REG0__geom_busy__SHIFT 0x15
+#define SETUP_DEBUG_REG0__event_id_gated_MASK 0xfc00000
+#define SETUP_DEBUG_REG0__event_id_gated__SHIFT 0x16
+#define SETUP_DEBUG_REG0__event_gated_MASK 0x10000000
+#define SETUP_DEBUG_REG0__event_gated__SHIFT 0x1c
+#define SETUP_DEBUG_REG0__pmode_prim_gated_MASK 0x20000000
+#define SETUP_DEBUG_REG0__pmode_prim_gated__SHIFT 0x1d
+#define SETUP_DEBUG_REG0__su_dyn_sclk_vld_MASK 0x40000000
+#define SETUP_DEBUG_REG0__su_dyn_sclk_vld__SHIFT 0x1e
+#define SETUP_DEBUG_REG0__cl_dyn_sclk_vld_MASK 0x80000000
+#define SETUP_DEBUG_REG0__cl_dyn_sclk_vld__SHIFT 0x1f
+#define SETUP_DEBUG_REG1__y_sort0_gated_23_8_MASK 0xffff
+#define SETUP_DEBUG_REG1__y_sort0_gated_23_8__SHIFT 0x0
+#define SETUP_DEBUG_REG1__x_sort0_gated_23_8_MASK 0xffff0000
+#define SETUP_DEBUG_REG1__x_sort0_gated_23_8__SHIFT 0x10
+#define SETUP_DEBUG_REG2__y_sort1_gated_23_8_MASK 0xffff
+#define SETUP_DEBUG_REG2__y_sort1_gated_23_8__SHIFT 0x0
+#define SETUP_DEBUG_REG2__x_sort1_gated_23_8_MASK 0xffff0000
+#define SETUP_DEBUG_REG2__x_sort1_gated_23_8__SHIFT 0x10
+#define SETUP_DEBUG_REG3__y_sort2_gated_23_8_MASK 0xffff
+#define SETUP_DEBUG_REG3__y_sort2_gated_23_8__SHIFT 0x0
+#define SETUP_DEBUG_REG3__x_sort2_gated_23_8_MASK 0xffff0000
+#define SETUP_DEBUG_REG3__x_sort2_gated_23_8__SHIFT 0x10
+#define SETUP_DEBUG_REG4__attr_indx_sort0_gated_MASK 0x3fff
+#define SETUP_DEBUG_REG4__attr_indx_sort0_gated__SHIFT 0x0
+#define SETUP_DEBUG_REG4__null_prim_gated_MASK 0x4000
+#define SETUP_DEBUG_REG4__null_prim_gated__SHIFT 0xe
+#define SETUP_DEBUG_REG4__backfacing_gated_MASK 0x8000
+#define SETUP_DEBUG_REG4__backfacing_gated__SHIFT 0xf
+#define SETUP_DEBUG_REG4__st_indx_gated_MASK 0x70000
+#define SETUP_DEBUG_REG4__st_indx_gated__SHIFT 0x10
+#define SETUP_DEBUG_REG4__clipped_gated_MASK 0x80000
+#define SETUP_DEBUG_REG4__clipped_gated__SHIFT 0x13
+#define SETUP_DEBUG_REG4__dealloc_slot_gated_MASK 0x700000
+#define SETUP_DEBUG_REG4__dealloc_slot_gated__SHIFT 0x14
+#define SETUP_DEBUG_REG4__xmajor_gated_MASK 0x800000
+#define SETUP_DEBUG_REG4__xmajor_gated__SHIFT 0x17
+#define SETUP_DEBUG_REG4__diamond_rule_gated_MASK 0x3000000
+#define SETUP_DEBUG_REG4__diamond_rule_gated__SHIFT 0x18
+#define SETUP_DEBUG_REG4__type_gated_MASK 0x1c000000
+#define SETUP_DEBUG_REG4__type_gated__SHIFT 0x1a
+#define SETUP_DEBUG_REG4__fpov_gated_MASK 0x60000000
+#define SETUP_DEBUG_REG4__fpov_gated__SHIFT 0x1d
+#define SETUP_DEBUG_REG4__eop_gated_MASK 0x80000000
+#define SETUP_DEBUG_REG4__eop_gated__SHIFT 0x1f
+#define SETUP_DEBUG_REG5__attr_indx_sort2_gated_MASK 0x3fff
+#define SETUP_DEBUG_REG5__attr_indx_sort2_gated__SHIFT 0x0
+#define SETUP_DEBUG_REG5__attr_indx_sort1_gated_MASK 0xfffc000
+#define SETUP_DEBUG_REG5__attr_indx_sort1_gated__SHIFT 0xe
+#define SETUP_DEBUG_REG5__provoking_vtx_gated_MASK 0x30000000
+#define SETUP_DEBUG_REG5__provoking_vtx_gated__SHIFT 0x1c
+#define SETUP_DEBUG_REG5__valid_prim_gated_MASK 0x40000000
+#define SETUP_DEBUG_REG5__valid_prim_gated__SHIFT 0x1e
+#define SETUP_DEBUG_REG5__pa_reg_sclk_vld_MASK 0x80000000
+#define SETUP_DEBUG_REG5__pa_reg_sclk_vld__SHIFT 0x1f
+#define PA_SC_DEBUG_REG0__REG0_FIELD0_MASK 0x3
+#define PA_SC_DEBUG_REG0__REG0_FIELD0__SHIFT 0x0
+#define PA_SC_DEBUG_REG0__REG0_FIELD1_MASK 0xc
+#define PA_SC_DEBUG_REG0__REG0_FIELD1__SHIFT 0x2
+#define PA_SC_DEBUG_REG1__REG1_FIELD0_MASK 0x3
+#define PA_SC_DEBUG_REG1__REG1_FIELD0__SHIFT 0x0
+#define PA_SC_DEBUG_REG1__REG1_FIELD1_MASK 0xc
+#define PA_SC_DEBUG_REG1__REG1_FIELD1__SHIFT 0x2
+#define COMPUTE_DISPATCH_INITIATOR__COMPUTE_SHADER_EN_MASK 0x1
+#define COMPUTE_DISPATCH_INITIATOR__COMPUTE_SHADER_EN__SHIFT 0x0
+#define COMPUTE_DISPATCH_INITIATOR__PARTIAL_TG_EN_MASK 0x2
+#define COMPUTE_DISPATCH_INITIATOR__PARTIAL_TG_EN__SHIFT 0x1
+#define COMPUTE_DISPATCH_INITIATOR__FORCE_START_AT_000_MASK 0x4
+#define COMPUTE_DISPATCH_INITIATOR__FORCE_START_AT_000__SHIFT 0x2
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_ENBL_MASK 0x8
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_ENBL__SHIFT 0x3
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_MODE_MASK 0x10
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_MODE__SHIFT 0x4
+#define COMPUTE_DISPATCH_INITIATOR__USE_THREAD_DIMENSIONS_MASK 0x20
+#define COMPUTE_DISPATCH_INITIATOR__USE_THREAD_DIMENSIONS__SHIFT 0x5
+#define COMPUTE_DISPATCH_INITIATOR__ORDER_MODE_MASK 0x40
+#define COMPUTE_DISPATCH_INITIATOR__ORDER_MODE__SHIFT 0x6
+#define COMPUTE_DISPATCH_INITIATOR__DISPATCH_CACHE_CNTL_MASK 0x380
+#define COMPUTE_DISPATCH_INITIATOR__DISPATCH_CACHE_CNTL__SHIFT 0x7
+#define COMPUTE_DISPATCH_INITIATOR__SCALAR_L1_INV_VOL_MASK 0x400
+#define COMPUTE_DISPATCH_INITIATOR__SCALAR_L1_INV_VOL__SHIFT 0xa
+#define COMPUTE_DISPATCH_INITIATOR__VECTOR_L1_INV_VOL_MASK 0x800
+#define COMPUTE_DISPATCH_INITIATOR__VECTOR_L1_INV_VOL__SHIFT 0xb
+#define COMPUTE_DISPATCH_INITIATOR__DATA_ATC_MASK 0x1000
+#define COMPUTE_DISPATCH_INITIATOR__DATA_ATC__SHIFT 0xc
+#define COMPUTE_DISPATCH_INITIATOR__RESTORE_MASK 0x4000
+#define COMPUTE_DISPATCH_INITIATOR__RESTORE__SHIFT 0xe
+#define COMPUTE_DIM_X__SIZE_MASK 0xffffffff
+#define COMPUTE_DIM_X__SIZE__SHIFT 0x0
+#define COMPUTE_DIM_Y__SIZE_MASK 0xffffffff
+#define COMPUTE_DIM_Y__SIZE__SHIFT 0x0
+#define COMPUTE_DIM_Z__SIZE_MASK 0xffffffff
+#define COMPUTE_DIM_Z__SIZE__SHIFT 0x0
+#define COMPUTE_START_X__START_MASK 0xffffffff
+#define COMPUTE_START_X__START__SHIFT 0x0
+#define COMPUTE_START_Y__START_MASK 0xffffffff
+#define COMPUTE_START_Y__START__SHIFT 0x0
+#define COMPUTE_START_Z__START_MASK 0xffffffff
+#define COMPUTE_START_Z__START__SHIFT 0x0
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_FULL_MASK 0xffff
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_FULL__SHIFT 0x0
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_PARTIAL_MASK 0xffff0000
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_PARTIAL__SHIFT 0x10
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_FULL_MASK 0xffff
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_FULL__SHIFT 0x0
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_PARTIAL_MASK 0xffff0000
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_PARTIAL__SHIFT 0x10
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_FULL_MASK 0xffff
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_FULL__SHIFT 0x0
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_PARTIAL_MASK 0xffff0000
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_PARTIAL__SHIFT 0x10
+#define COMPUTE_PIPELINESTAT_ENABLE__PIPELINESTAT_ENABLE_MASK 0x1
+#define COMPUTE_PIPELINESTAT_ENABLE__PIPELINESTAT_ENABLE__SHIFT 0x0
+#define COMPUTE_PERFCOUNT_ENABLE__PERFCOUNT_ENABLE_MASK 0x1
+#define COMPUTE_PERFCOUNT_ENABLE__PERFCOUNT_ENABLE__SHIFT 0x0
+#define COMPUTE_PGM_LO__DATA_MASK 0xffffffff
+#define COMPUTE_PGM_LO__DATA__SHIFT 0x0
+#define COMPUTE_PGM_HI__DATA_MASK 0xff
+#define COMPUTE_PGM_HI__DATA__SHIFT 0x0
+#define COMPUTE_PGM_HI__INST_ATC_MASK 0x100
+#define COMPUTE_PGM_HI__INST_ATC__SHIFT 0x8
+#define COMPUTE_TBA_LO__DATA_MASK 0xffffffff
+#define COMPUTE_TBA_LO__DATA__SHIFT 0x0
+#define COMPUTE_TBA_HI__DATA_MASK 0xff
+#define COMPUTE_TBA_HI__DATA__SHIFT 0x0
+#define COMPUTE_TMA_LO__DATA_MASK 0xffffffff
+#define COMPUTE_TMA_LO__DATA__SHIFT 0x0
+#define COMPUTE_TMA_HI__DATA_MASK 0xff
+#define COMPUTE_TMA_HI__DATA__SHIFT 0x0
+#define COMPUTE_PGM_RSRC1__VGPRS_MASK 0x3f
+#define COMPUTE_PGM_RSRC1__VGPRS__SHIFT 0x0
+#define COMPUTE_PGM_RSRC1__SGPRS_MASK 0x3c0
+#define COMPUTE_PGM_RSRC1__SGPRS__SHIFT 0x6
+#define COMPUTE_PGM_RSRC1__PRIORITY_MASK 0xc00
+#define COMPUTE_PGM_RSRC1__PRIORITY__SHIFT 0xa
+#define COMPUTE_PGM_RSRC1__FLOAT_MODE_MASK 0xff000
+#define COMPUTE_PGM_RSRC1__FLOAT_MODE__SHIFT 0xc
+#define COMPUTE_PGM_RSRC1__PRIV_MASK 0x100000
+#define COMPUTE_PGM_RSRC1__PRIV__SHIFT 0x14
+#define COMPUTE_PGM_RSRC1__DX10_CLAMP_MASK 0x200000
+#define COMPUTE_PGM_RSRC1__DX10_CLAMP__SHIFT 0x15
+#define COMPUTE_PGM_RSRC1__DEBUG_MODE_MASK 0x400000
+#define COMPUTE_PGM_RSRC1__DEBUG_MODE__SHIFT 0x16
+#define COMPUTE_PGM_RSRC1__IEEE_MODE_MASK 0x800000
+#define COMPUTE_PGM_RSRC1__IEEE_MODE__SHIFT 0x17
+#define COMPUTE_PGM_RSRC1__BULKY_MASK 0x1000000
+#define COMPUTE_PGM_RSRC1__BULKY__SHIFT 0x18
+#define COMPUTE_PGM_RSRC1__CDBG_USER_MASK 0x2000000
+#define COMPUTE_PGM_RSRC1__CDBG_USER__SHIFT 0x19
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN_MASK 0x1
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN__SHIFT 0x0
+#define COMPUTE_PGM_RSRC2__USER_SGPR_MASK 0x3e
+#define COMPUTE_PGM_RSRC2__USER_SGPR__SHIFT 0x1
+#define COMPUTE_PGM_RSRC2__TRAP_PRESENT_MASK 0x40
+#define COMPUTE_PGM_RSRC2__TRAP_PRESENT__SHIFT 0x6
+#define COMPUTE_PGM_RSRC2__TGID_X_EN_MASK 0x80
+#define COMPUTE_PGM_RSRC2__TGID_X_EN__SHIFT 0x7
+#define COMPUTE_PGM_RSRC2__TGID_Y_EN_MASK 0x100
+#define COMPUTE_PGM_RSRC2__TGID_Y_EN__SHIFT 0x8
+#define COMPUTE_PGM_RSRC2__TGID_Z_EN_MASK 0x200
+#define COMPUTE_PGM_RSRC2__TGID_Z_EN__SHIFT 0x9
+#define COMPUTE_PGM_RSRC2__TG_SIZE_EN_MASK 0x400
+#define COMPUTE_PGM_RSRC2__TG_SIZE_EN__SHIFT 0xa
+#define COMPUTE_PGM_RSRC2__TIDIG_COMP_CNT_MASK 0x1800
+#define COMPUTE_PGM_RSRC2__TIDIG_COMP_CNT__SHIFT 0xb
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MSB_MASK 0x6000
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MSB__SHIFT 0xd
+#define COMPUTE_PGM_RSRC2__LDS_SIZE_MASK 0xff8000
+#define COMPUTE_PGM_RSRC2__LDS_SIZE__SHIFT 0xf
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MASK 0x7f000000
+#define COMPUTE_PGM_RSRC2__EXCP_EN__SHIFT 0x18
+#define COMPUTE_VMID__DATA_MASK 0xf
+#define COMPUTE_VMID__DATA__SHIFT 0x0
+#define COMPUTE_RESOURCE_LIMITS__WAVES_PER_SH_MASK 0x3ff
+#define COMPUTE_RESOURCE_LIMITS__WAVES_PER_SH__SHIFT 0x0
+#define COMPUTE_RESOURCE_LIMITS__TG_PER_CU_MASK 0xf000
+#define COMPUTE_RESOURCE_LIMITS__TG_PER_CU__SHIFT 0xc
+#define COMPUTE_RESOURCE_LIMITS__LOCK_THRESHOLD_MASK 0x3f0000
+#define COMPUTE_RESOURCE_LIMITS__LOCK_THRESHOLD__SHIFT 0x10
+#define COMPUTE_RESOURCE_LIMITS__SIMD_DEST_CNTL_MASK 0x400000
+#define COMPUTE_RESOURCE_LIMITS__SIMD_DEST_CNTL__SHIFT 0x16
+#define COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST_MASK 0x800000
+#define COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST__SHIFT 0x17
+#define COMPUTE_RESOURCE_LIMITS__CU_GROUP_COUNT_MASK 0x7000000
+#define COMPUTE_RESOURCE_LIMITS__CU_GROUP_COUNT__SHIFT 0x18
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH0_CU_EN_MASK 0xffff
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH0_CU_EN__SHIFT 0x0
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH1_CU_EN_MASK 0xffff0000
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH1_CU_EN__SHIFT 0x10
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH0_CU_EN_MASK 0xffff
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH0_CU_EN__SHIFT 0x0
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH1_CU_EN_MASK 0xffff0000
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH1_CU_EN__SHIFT 0x10
+#define COMPUTE_TMPRING_SIZE__WAVES_MASK 0xfff
+#define COMPUTE_TMPRING_SIZE__WAVES__SHIFT 0x0
+#define COMPUTE_TMPRING_SIZE__WAVESIZE_MASK 0x1fff000
+#define COMPUTE_TMPRING_SIZE__WAVESIZE__SHIFT 0xc
+#define COMPUTE_STATIC_THREAD_MGMT_SE2__SH0_CU_EN_MASK 0xffff
+#define COMPUTE_STATIC_THREAD_MGMT_SE2__SH0_CU_EN__SHIFT 0x0
+#define COMPUTE_STATIC_THREAD_MGMT_SE2__SH1_CU_EN_MASK 0xffff0000
+#define COMPUTE_STATIC_THREAD_MGMT_SE2__SH1_CU_EN__SHIFT 0x10
+#define COMPUTE_STATIC_THREAD_MGMT_SE3__SH0_CU_EN_MASK 0xffff
+#define COMPUTE_STATIC_THREAD_MGMT_SE3__SH0_CU_EN__SHIFT 0x0
+#define COMPUTE_STATIC_THREAD_MGMT_SE3__SH1_CU_EN_MASK 0xffff0000
+#define COMPUTE_STATIC_THREAD_MGMT_SE3__SH1_CU_EN__SHIFT 0x10
+#define COMPUTE_RESTART_X__RESTART_MASK 0xffffffff
+#define COMPUTE_RESTART_X__RESTART__SHIFT 0x0
+#define COMPUTE_RESTART_Y__RESTART_MASK 0xffffffff
+#define COMPUTE_RESTART_Y__RESTART__SHIFT 0x0
+#define COMPUTE_RESTART_Z__RESTART_MASK 0xffffffff
+#define COMPUTE_RESTART_Z__RESTART__SHIFT 0x0
+#define COMPUTE_THREAD_TRACE_ENABLE__THREAD_TRACE_ENABLE_MASK 0x1
+#define COMPUTE_THREAD_TRACE_ENABLE__THREAD_TRACE_ENABLE__SHIFT 0x0
+#define COMPUTE_MISC_RESERVED__SEND_SEID_MASK 0x3
+#define COMPUTE_MISC_RESERVED__SEND_SEID__SHIFT 0x0
+#define COMPUTE_MISC_RESERVED__RESERVED2_MASK 0x4
+#define COMPUTE_MISC_RESERVED__RESERVED2__SHIFT 0x2
+#define COMPUTE_MISC_RESERVED__RESERVED3_MASK 0x8
+#define COMPUTE_MISC_RESERVED__RESERVED3__SHIFT 0x3
+#define COMPUTE_MISC_RESERVED__RESERVED4_MASK 0x10
+#define COMPUTE_MISC_RESERVED__RESERVED4__SHIFT 0x4
+#define COMPUTE_MISC_RESERVED__WAVE_ID_BASE_MASK 0x1ffe0
+#define COMPUTE_MISC_RESERVED__WAVE_ID_BASE__SHIFT 0x5
+#define COMPUTE_DISPATCH_ID__DISPATCH_ID_MASK 0xffffffff
+#define COMPUTE_DISPATCH_ID__DISPATCH_ID__SHIFT 0x0
+#define COMPUTE_THREADGROUP_ID__THREADGROUP_ID_MASK 0xffffffff
+#define COMPUTE_THREADGROUP_ID__THREADGROUP_ID__SHIFT 0x0
+#define COMPUTE_RELAUNCH__PAYLOAD_MASK 0x3fffffff
+#define COMPUTE_RELAUNCH__PAYLOAD__SHIFT 0x0
+#define COMPUTE_RELAUNCH__IS_EVENT_MASK 0x40000000
+#define COMPUTE_RELAUNCH__IS_EVENT__SHIFT 0x1e
+#define COMPUTE_RELAUNCH__IS_STATE_MASK 0x80000000
+#define COMPUTE_RELAUNCH__IS_STATE__SHIFT 0x1f
+#define COMPUTE_WAVE_RESTORE_ADDR_LO__ADDR_MASK 0xffffffff
+#define COMPUTE_WAVE_RESTORE_ADDR_LO__ADDR__SHIFT 0x0
+#define COMPUTE_WAVE_RESTORE_ADDR_HI__ADDR_MASK 0xffff
+#define COMPUTE_WAVE_RESTORE_ADDR_HI__ADDR__SHIFT 0x0
+#define COMPUTE_WAVE_RESTORE_CONTROL__ATC_MASK 0x1
+#define COMPUTE_WAVE_RESTORE_CONTROL__ATC__SHIFT 0x0
+#define COMPUTE_WAVE_RESTORE_CONTROL__MTYPE_MASK 0x6
+#define COMPUTE_WAVE_RESTORE_CONTROL__MTYPE__SHIFT 0x1
+#define COMPUTE_USER_DATA_0__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_0__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_1__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_1__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_2__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_2__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_3__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_3__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_4__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_4__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_5__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_5__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_6__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_6__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_7__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_7__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_8__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_8__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_9__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_9__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_10__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_10__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_11__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_11__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_12__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_12__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_13__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_13__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_14__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_14__DATA__SHIFT 0x0
+#define COMPUTE_USER_DATA_15__DATA_MASK 0xffffffff
+#define COMPUTE_USER_DATA_15__DATA__SHIFT 0x0
+#define COMPUTE_NOWHERE__DATA_MASK 0xffffffff
+#define COMPUTE_NOWHERE__DATA__SHIFT 0x0
+#define CSPRIV_CONNECT__DOORBELL_OFFSET_MASK 0x1fffff
+#define CSPRIV_CONNECT__DOORBELL_OFFSET__SHIFT 0x0
+#define CSPRIV_CONNECT__QUEUE_ID_MASK 0xe00000
+#define CSPRIV_CONNECT__QUEUE_ID__SHIFT 0x15
+#define CSPRIV_CONNECT__VMID_MASK 0x3c000000
+#define CSPRIV_CONNECT__VMID__SHIFT 0x1a
+#define CSPRIV_CONNECT__UNORD_DISP_MASK 0x80000000
+#define CSPRIV_CONNECT__UNORD_DISP__SHIFT 0x1f
+#define CSPRIV_THREAD_TRACE_TG0__TGID_X_MASK 0xffffffff
+#define CSPRIV_THREAD_TRACE_TG0__TGID_X__SHIFT 0x0
+#define CSPRIV_THREAD_TRACE_TG1__TGID_Y_MASK 0xffffffff
+#define CSPRIV_THREAD_TRACE_TG1__TGID_Y__SHIFT 0x0
+#define CSPRIV_THREAD_TRACE_TG2__TGID_Z_MASK 0xffffffff
+#define CSPRIV_THREAD_TRACE_TG2__TGID_Z__SHIFT 0x0
+#define CSPRIV_THREAD_TRACE_TG3__WAVE_ID_BASE_MASK 0xfff
+#define CSPRIV_THREAD_TRACE_TG3__WAVE_ID_BASE__SHIFT 0x0
+#define CSPRIV_THREAD_TRACE_TG3__THREADS_IN_GROUP_MASK 0xfff000
+#define CSPRIV_THREAD_TRACE_TG3__THREADS_IN_GROUP__SHIFT 0xc
+#define CSPRIV_THREAD_TRACE_TG3__PARTIAL_X_FLAG_MASK 0x1000000
+#define CSPRIV_THREAD_TRACE_TG3__PARTIAL_X_FLAG__SHIFT 0x18
+#define CSPRIV_THREAD_TRACE_TG3__PARTIAL_Y_FLAG_MASK 0x2000000
+#define CSPRIV_THREAD_TRACE_TG3__PARTIAL_Y_FLAG__SHIFT 0x19
+#define CSPRIV_THREAD_TRACE_TG3__PARTIAL_Z_FLAG_MASK 0x4000000
+#define CSPRIV_THREAD_TRACE_TG3__PARTIAL_Z_FLAG__SHIFT 0x1a
+#define CSPRIV_THREAD_TRACE_TG3__LAST_TG_MASK 0x8000000
+#define CSPRIV_THREAD_TRACE_TG3__LAST_TG__SHIFT 0x1b
+#define CSPRIV_THREAD_TRACE_TG3__FIRST_TG_MASK 0x10000000
+#define CSPRIV_THREAD_TRACE_TG3__FIRST_TG__SHIFT 0x1c
+#define CSPRIV_THREAD_TRACE_EVENT__EVENT_ID_MASK 0x1f
+#define CSPRIV_THREAD_TRACE_EVENT__EVENT_ID__SHIFT 0x0
+#define RLC_CNTL__RLC_ENABLE_F32_MASK 0x1
+#define RLC_CNTL__RLC_ENABLE_F32__SHIFT 0x0
+#define RLC_CNTL__FORCE_RETRY_MASK 0x2
+#define RLC_CNTL__FORCE_RETRY__SHIFT 0x1
+#define RLC_CNTL__READ_CACHE_DISABLE_MASK 0x4
+#define RLC_CNTL__READ_CACHE_DISABLE__SHIFT 0x2
+#define RLC_CNTL__RLC_STEP_F32_MASK 0x8
+#define RLC_CNTL__RLC_STEP_F32__SHIFT 0x3
+#define RLC_CNTL__SOFT_RESET_DEBUG_MODE_MASK 0x10
+#define RLC_CNTL__SOFT_RESET_DEBUG_MODE__SHIFT 0x4
+#define RLC_CNTL__RESERVED_MASK 0xffffff00
+#define RLC_CNTL__RESERVED__SHIFT 0x8
+#define RLC_DEBUG_SELECT__SELECT_MASK 0xff
+#define RLC_DEBUG_SELECT__SELECT__SHIFT 0x0
+#define RLC_DEBUG_SELECT__RESERVED_MASK 0xffffff00
+#define RLC_DEBUG_SELECT__RESERVED__SHIFT 0x8
+#define RLC_DEBUG__DATA_MASK 0xffffffff
+#define RLC_DEBUG__DATA__SHIFT 0x0
+#define RLC_MC_CNTL__WRREQ_SWAP_MASK 0x3
+#define RLC_MC_CNTL__WRREQ_SWAP__SHIFT 0x0
+#define RLC_MC_CNTL__WRREQ_TRAN_MASK 0x4
+#define RLC_MC_CNTL__WRREQ_TRAN__SHIFT 0x2
+#define RLC_MC_CNTL__WRREQ_PRIV_MASK 0x8
+#define RLC_MC_CNTL__WRREQ_PRIV__SHIFT 0x3
+#define RLC_MC_CNTL__WRNFO_STALL_MASK 0x10
+#define RLC_MC_CNTL__WRNFO_STALL__SHIFT 0x4
+#define RLC_MC_CNTL__WRNFO_URG_MASK 0x1e0
+#define RLC_MC_CNTL__WRNFO_URG__SHIFT 0x5
+#define RLC_MC_CNTL__WRREQ_DW_IMASK_MASK 0x1e00
+#define RLC_MC_CNTL__WRREQ_DW_IMASK__SHIFT 0x9
+#define RLC_MC_CNTL__RESERVED_B_MASK 0xfe000
+#define RLC_MC_CNTL__RESERVED_B__SHIFT 0xd
+#define RLC_MC_CNTL__RDNFO_URG_MASK 0xf00000
+#define RLC_MC_CNTL__RDNFO_URG__SHIFT 0x14
+#define RLC_MC_CNTL__RDREQ_SWAP_MASK 0x3000000
+#define RLC_MC_CNTL__RDREQ_SWAP__SHIFT 0x18
+#define RLC_MC_CNTL__RDREQ_TRAN_MASK 0x4000000
+#define RLC_MC_CNTL__RDREQ_TRAN__SHIFT 0x1a
+#define RLC_MC_CNTL__RDREQ_PRIV_MASK 0x8000000
+#define RLC_MC_CNTL__RDREQ_PRIV__SHIFT 0x1b
+#define RLC_MC_CNTL__RDNFO_STALL_MASK 0x10000000
+#define RLC_MC_CNTL__RDNFO_STALL__SHIFT 0x1c
+#define RLC_MC_CNTL__RESERVED_MASK 0xe0000000
+#define RLC_MC_CNTL__RESERVED__SHIFT 0x1d
+#define RLC_STAT__RLC_BUSY_MASK 0x1
+#define RLC_STAT__RLC_BUSY__SHIFT 0x0
+#define RLC_STAT__RLC_GPM_BUSY_MASK 0x2
+#define RLC_STAT__RLC_GPM_BUSY__SHIFT 0x1
+#define RLC_STAT__RLC_SPM_BUSY_MASK 0x4
+#define RLC_STAT__RLC_SPM_BUSY__SHIFT 0x2
+#define RLC_STAT__RLC_SRM_BUSY_MASK 0x8
+#define RLC_STAT__RLC_SRM_BUSY__SHIFT 0x3
+#define RLC_STAT__RESERVED_MASK 0xfffffff0
+#define RLC_STAT__RESERVED__SHIFT 0x4
+#define RLC_SAFE_MODE__CMD_MASK 0x1
+#define RLC_SAFE_MODE__CMD__SHIFT 0x0
+#define RLC_SAFE_MODE__MESSAGE_MASK 0x1e
+#define RLC_SAFE_MODE__MESSAGE__SHIFT 0x1
+#define RLC_SAFE_MODE__RESERVED1_MASK 0xe0
+#define RLC_SAFE_MODE__RESERVED1__SHIFT 0x5
+#define RLC_SAFE_MODE__RESPONSE_MASK 0xf00
+#define RLC_SAFE_MODE__RESPONSE__SHIFT 0x8
+#define RLC_SAFE_MODE__RESERVED_MASK 0xfffff000
+#define RLC_SAFE_MODE__RESERVED__SHIFT 0xc
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK 0x1
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN__SHIFT 0x0
+#define RLC_MEM_SLP_CNTL__RLC_MEM_DS_EN_MASK 0x2
+#define RLC_MEM_SLP_CNTL__RLC_MEM_DS_EN__SHIFT 0x1
+#define RLC_MEM_SLP_CNTL__RESERVED_MASK 0x7c
+#define RLC_MEM_SLP_CNTL__RESERVED__SHIFT 0x2
+#define RLC_MEM_SLP_CNTL__RLC_LS_DS_BUSY_OVERRIDE_MASK 0x80
+#define RLC_MEM_SLP_CNTL__RLC_LS_DS_BUSY_OVERRIDE__SHIFT 0x7
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_ON_DELAY_MASK 0xff00
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_ON_DELAY__SHIFT 0x8
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_OFF_DELAY_MASK 0xff0000
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_OFF_DELAY__SHIFT 0x10
+#define RLC_MEM_SLP_CNTL__RESERVED1_MASK 0xff000000
+#define RLC_MEM_SLP_CNTL__RESERVED1__SHIFT 0x18
+#define SMU_RLC_RESPONSE__RESP_MASK 0xffffffff
+#define SMU_RLC_RESPONSE__RESP__SHIFT 0x0
+#define RLC_RLCV_SAFE_MODE__CMD_MASK 0x1
+#define RLC_RLCV_SAFE_MODE__CMD__SHIFT 0x0
+#define RLC_RLCV_SAFE_MODE__MESSAGE_MASK 0x1e
+#define RLC_RLCV_SAFE_MODE__MESSAGE__SHIFT 0x1
+#define RLC_RLCV_SAFE_MODE__RESERVED1_MASK 0xe0
+#define RLC_RLCV_SAFE_MODE__RESERVED1__SHIFT 0x5
+#define RLC_RLCV_SAFE_MODE__RESPONSE_MASK 0xf00
+#define RLC_RLCV_SAFE_MODE__RESPONSE__SHIFT 0x8
+#define RLC_RLCV_SAFE_MODE__RESERVED_MASK 0xfffff000
+#define RLC_RLCV_SAFE_MODE__RESERVED__SHIFT 0xc
+#define RLC_SMU_SAFE_MODE__CMD_MASK 0x1
+#define RLC_SMU_SAFE_MODE__CMD__SHIFT 0x0
+#define RLC_SMU_SAFE_MODE__MESSAGE_MASK 0x1e
+#define RLC_SMU_SAFE_MODE__MESSAGE__SHIFT 0x1
+#define RLC_SMU_SAFE_MODE__RESERVED1_MASK 0xe0
+#define RLC_SMU_SAFE_MODE__RESERVED1__SHIFT 0x5
+#define RLC_SMU_SAFE_MODE__RESPONSE_MASK 0xf00
+#define RLC_SMU_SAFE_MODE__RESPONSE__SHIFT 0x8
+#define RLC_SMU_SAFE_MODE__RESERVED_MASK 0xfffff000
+#define RLC_SMU_SAFE_MODE__RESERVED__SHIFT 0xc
+#define RLC_RLCV_COMMAND__CMD_MASK 0xf
+#define RLC_RLCV_COMMAND__CMD__SHIFT 0x0
+#define RLC_RLCV_COMMAND__RESERVED_MASK 0xfffffff0
+#define RLC_RLCV_COMMAND__RESERVED__SHIFT 0x4
+#define RLC_CLK_CNTL__RLC_SRM_CLK_CNTL_MASK 0x1
+#define RLC_CLK_CNTL__RLC_SRM_CLK_CNTL__SHIFT 0x0
+#define RLC_CLK_CNTL__RLC_SPM_CLK_CNTL_MASK 0x2
+#define RLC_CLK_CNTL__RLC_SPM_CLK_CNTL__SHIFT 0x1
+#define RLC_CLK_CNTL__RESERVED_MASK 0xfffffffc
+#define RLC_CLK_CNTL__RESERVED__SHIFT 0x2
+#define RLC_PERFMON_CLK_CNTL__PERFMON_CLOCK_STATE_MASK 0x1
+#define RLC_PERFMON_CLK_CNTL__PERFMON_CLOCK_STATE__SHIFT 0x0
+#define RLC_PERFMON_CNTL__PERFMON_STATE_MASK 0x7
+#define RLC_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x0
+#define RLC_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x400
+#define RLC_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0xa
+#define RLC_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0xff
+#define RLC_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define RLC_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0xff
+#define RLC_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define RLC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define RLC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define RLC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define RLC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define RLC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define RLC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define RLC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define RLC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define CGTT_RLC_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_RLC_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_RLC_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_RLC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x1e
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x1f
+#define RLC_LB_CNTL__LOAD_BALANCE_ENABLE_MASK 0x1
+#define RLC_LB_CNTL__LOAD_BALANCE_ENABLE__SHIFT 0x0
+#define RLC_LB_CNTL__LB_CNT_CP_BUSY_MASK 0x2
+#define RLC_LB_CNTL__LB_CNT_CP_BUSY__SHIFT 0x1
+#define RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE_MASK 0x4
+#define RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE__SHIFT 0x2
+#define RLC_LB_CNTL__LB_CNT_REG_INC_MASK 0x8
+#define RLC_LB_CNTL__LB_CNT_REG_INC__SHIFT 0x3
+#define RLC_LB_CNTL__CU_MASK_USED_OFF_HYST_MASK 0xff0
+#define RLC_LB_CNTL__CU_MASK_USED_OFF_HYST__SHIFT 0x4
+#define RLC_LB_CNTL__RESERVED_MASK 0xfffff000
+#define RLC_LB_CNTL__RESERVED__SHIFT 0xc
+#define RLC_LB_CNTR_MAX__LB_CNTR_MAX_MASK 0xffffffff
+#define RLC_LB_CNTR_MAX__LB_CNTR_MAX__SHIFT 0x0
+#define RLC_LB_CNTR_INIT__LB_CNTR_INIT_MASK 0xffffffff
+#define RLC_LB_CNTR_INIT__LB_CNTR_INIT__SHIFT 0x0
+#define RLC_LOAD_BALANCE_CNTR__RLC_LOAD_BALANCE_CNTR_MASK 0xffffffff
+#define RLC_LOAD_BALANCE_CNTR__RLC_LOAD_BALANCE_CNTR__SHIFT 0x0
+#define RLC_JUMP_TABLE_RESTORE__ADDR_MASK 0xffffffff
+#define RLC_JUMP_TABLE_RESTORE__ADDR__SHIFT 0x0
+#define RLC_PG_DELAY_2__SERDES_TIMEOUT_VALUE_MASK 0xff
+#define RLC_PG_DELAY_2__SERDES_TIMEOUT_VALUE__SHIFT 0x0
+#define RLC_PG_DELAY_2__SERDES_CMD_DELAY_MASK 0xff00
+#define RLC_PG_DELAY_2__SERDES_CMD_DELAY__SHIFT 0x8
+#define RLC_PG_DELAY_2__PERCU_TIMEOUT_VALUE_MASK 0xffff0000
+#define RLC_PG_DELAY_2__PERCU_TIMEOUT_VALUE__SHIFT 0x10
+#define RLC_GPM_DEBUG_SELECT__SELECT_MASK 0xff
+#define RLC_GPM_DEBUG_SELECT__SELECT__SHIFT 0x0
+#define RLC_GPM_DEBUG_SELECT__F32_DEBUG_SELECT_MASK 0x300
+#define RLC_GPM_DEBUG_SELECT__F32_DEBUG_SELECT__SHIFT 0x8
+#define RLC_GPM_DEBUG_SELECT__RESERVED_MASK 0xfffffc00
+#define RLC_GPM_DEBUG_SELECT__RESERVED__SHIFT 0xa
+#define RLC_GPM_DEBUG__DATA_MASK 0xffffffff
+#define RLC_GPM_DEBUG__DATA__SHIFT 0x0
+#define RLC_GPM_DEBUG_INST_A__INST_A_MASK 0xffffffff
+#define RLC_GPM_DEBUG_INST_A__INST_A__SHIFT 0x0
+#define RLC_GPM_DEBUG_INST_B__INST_B_MASK 0xffffffff
+#define RLC_GPM_DEBUG_INST_B__INST_B__SHIFT 0x0
+#define RLC_GPM_DEBUG_INST_ADDR__ADRR_A_MASK 0xffff
+#define RLC_GPM_DEBUG_INST_ADDR__ADRR_A__SHIFT 0x0
+#define RLC_GPM_DEBUG_INST_ADDR__ADDR_B_MASK 0xffff0000
+#define RLC_GPM_DEBUG_INST_ADDR__ADDR_B__SHIFT 0x10
+#define RLC_GPM_UCODE_ADDR__UCODE_ADDR_MASK 0xfff
+#define RLC_GPM_UCODE_ADDR__UCODE_ADDR__SHIFT 0x0
+#define RLC_GPM_UCODE_ADDR__RESERVED_MASK 0xfffff000
+#define RLC_GPM_UCODE_ADDR__RESERVED__SHIFT 0xc
+#define RLC_GPM_UCODE_DATA__UCODE_DATA_MASK 0xffffffff
+#define RLC_GPM_UCODE_DATA__UCODE_DATA__SHIFT 0x0
+#define GPU_BIST_CONTROL__STOP_ON_FAIL_HW_MASK 0x1
+#define GPU_BIST_CONTROL__STOP_ON_FAIL_HW__SHIFT 0x0
+#define GPU_BIST_CONTROL__STOP_ON_FAIL_CU_HARV_MASK 0x2
+#define GPU_BIST_CONTROL__STOP_ON_FAIL_CU_HARV__SHIFT 0x1
+#define GPU_BIST_CONTROL__CU_HARV_LOOP_COUNT_MASK 0x3c
+#define GPU_BIST_CONTROL__CU_HARV_LOOP_COUNT__SHIFT 0x2
+#define GPU_BIST_CONTROL__RESERVED_MASK 0xffff80
+#define GPU_BIST_CONTROL__RESERVED__SHIFT 0x7
+#define GPU_BIST_CONTROL__GLOBAL_LOOP_COUNT_MASK 0xff000000
+#define GPU_BIST_CONTROL__GLOBAL_LOOP_COUNT__SHIFT 0x18
+#define RLC_ROM_CNTL__USE_ROM_MASK 0x1
+#define RLC_ROM_CNTL__USE_ROM__SHIFT 0x0
+#define RLC_ROM_CNTL__SLP_MODE_EN_MASK 0x2
+#define RLC_ROM_CNTL__SLP_MODE_EN__SHIFT 0x1
+#define RLC_ROM_CNTL__EFUSE_DISTRIB_EN_MASK 0x4
+#define RLC_ROM_CNTL__EFUSE_DISTRIB_EN__SHIFT 0x2
+#define RLC_ROM_CNTL__HELLOWORLD_EN_MASK 0x8
+#define RLC_ROM_CNTL__HELLOWORLD_EN__SHIFT 0x3
+#define RLC_ROM_CNTL__CU_HARVEST_EN_MASK 0x10
+#define RLC_ROM_CNTL__CU_HARVEST_EN__SHIFT 0x4
+#define RLC_ROM_CNTL__RESERVED_MASK 0xffffffe0
+#define RLC_ROM_CNTL__RESERVED__SHIFT 0x5
+#define RLC_GPU_CLOCK_COUNT_LSB__GPU_CLOCKS_LSB_MASK 0xffffffff
+#define RLC_GPU_CLOCK_COUNT_LSB__GPU_CLOCKS_LSB__SHIFT 0x0
+#define RLC_GPU_CLOCK_COUNT_MSB__GPU_CLOCKS_MSB_MASK 0xffffffff
+#define RLC_GPU_CLOCK_COUNT_MSB__GPU_CLOCKS_MSB__SHIFT 0x0
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__CAPTURE_MASK 0x1
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__CAPTURE__SHIFT 0x0
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__RESERVED_MASK 0xfffffffe
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__RESERVED__SHIFT 0x1
+#define RLC_UCODE_CNTL__RLC_UCODE_FLAGS_MASK 0xffffffff
+#define RLC_UCODE_CNTL__RLC_UCODE_FLAGS__SHIFT 0x0
+#define RLC_GPM_STAT__RLC_BUSY_MASK 0x1
+#define RLC_GPM_STAT__RLC_BUSY__SHIFT 0x0
+#define RLC_GPM_STAT__GFX_POWER_STATUS_MASK 0x2
+#define RLC_GPM_STAT__GFX_POWER_STATUS__SHIFT 0x1
+#define RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK 0x4
+#define RLC_GPM_STAT__GFX_CLOCK_STATUS__SHIFT 0x2
+#define RLC_GPM_STAT__GFX_LS_STATUS_MASK 0x8
+#define RLC_GPM_STAT__GFX_LS_STATUS__SHIFT 0x3
+#define RLC_GPM_STAT__GFX_PIPELINE_POWER_STATUS_MASK 0x10
+#define RLC_GPM_STAT__GFX_PIPELINE_POWER_STATUS__SHIFT 0x4
+#define RLC_GPM_STAT__CNTX_IDLE_BEING_PROCESSED_MASK 0x20
+#define RLC_GPM_STAT__CNTX_IDLE_BEING_PROCESSED__SHIFT 0x5
+#define RLC_GPM_STAT__CNTX_BUSY_BEING_PROCESSED_MASK 0x40
+#define RLC_GPM_STAT__CNTX_BUSY_BEING_PROCESSED__SHIFT 0x6
+#define RLC_GPM_STAT__GFX_IDLE_BEING_PROCESSED_MASK 0x80
+#define RLC_GPM_STAT__GFX_IDLE_BEING_PROCESSED__SHIFT 0x7
+#define RLC_GPM_STAT__CMP_BUSY_BEING_PROCESSED_MASK 0x100
+#define RLC_GPM_STAT__CMP_BUSY_BEING_PROCESSED__SHIFT 0x8
+#define RLC_GPM_STAT__SAVING_REGISTERS_MASK 0x200
+#define RLC_GPM_STAT__SAVING_REGISTERS__SHIFT 0x9
+#define RLC_GPM_STAT__RESTORING_REGISTERS_MASK 0x400
+#define RLC_GPM_STAT__RESTORING_REGISTERS__SHIFT 0xa
+#define RLC_GPM_STAT__GFX3D_BLOCKS_CHANGING_POWER_STATE_MASK 0x800
+#define RLC_GPM_STAT__GFX3D_BLOCKS_CHANGING_POWER_STATE__SHIFT 0xb
+#define RLC_GPM_STAT__CMP_BLOCKS_CHANGING_POWER_STATE_MASK 0x1000
+#define RLC_GPM_STAT__CMP_BLOCKS_CHANGING_POWER_STATE__SHIFT 0xc
+#define RLC_GPM_STAT__STATIC_CU_POWERING_UP_MASK 0x2000
+#define RLC_GPM_STAT__STATIC_CU_POWERING_UP__SHIFT 0xd
+#define RLC_GPM_STAT__STATIC_CU_POWERING_DOWN_MASK 0x4000
+#define RLC_GPM_STAT__STATIC_CU_POWERING_DOWN__SHIFT 0xe
+#define RLC_GPM_STAT__DYN_CU_POWERING_UP_MASK 0x8000
+#define RLC_GPM_STAT__DYN_CU_POWERING_UP__SHIFT 0xf
+#define RLC_GPM_STAT__DYN_CU_POWERING_DOWN_MASK 0x10000
+#define RLC_GPM_STAT__DYN_CU_POWERING_DOWN__SHIFT 0x10
+#define RLC_GPM_STAT__ABORTED_PD_SEQUENCE_MASK 0x20000
+#define RLC_GPM_STAT__ABORTED_PD_SEQUENCE__SHIFT 0x11
+#define RLC_GPM_STAT__RESERVED_MASK 0xfc0000
+#define RLC_GPM_STAT__RESERVED__SHIFT 0x12
+#define RLC_GPM_STAT__PG_ERROR_STATUS_MASK 0xff000000
+#define RLC_GPM_STAT__PG_ERROR_STATUS__SHIFT 0x18
+#define RLC_GPU_CLOCK_32_RES_SEL__RES_SEL_MASK 0x3f
+#define RLC_GPU_CLOCK_32_RES_SEL__RES_SEL__SHIFT 0x0
+#define RLC_GPU_CLOCK_32_RES_SEL__RESERVED_MASK 0xffffffc0
+#define RLC_GPU_CLOCK_32_RES_SEL__RESERVED__SHIFT 0x6
+#define RLC_GPU_CLOCK_32__GPU_CLOCK_32_MASK 0xffffffff
+#define RLC_GPU_CLOCK_32__GPU_CLOCK_32__SHIFT 0x0
+#define RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK 0x1
+#define RLC_PG_CNTL__GFX_POWER_GATING_ENABLE__SHIFT 0x0
+#define RLC_PG_CNTL__GFX_POWER_GATING_SRC_MASK 0x2
+#define RLC_PG_CNTL__GFX_POWER_GATING_SRC__SHIFT 0x1
+#define RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK 0x4
+#define RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE__SHIFT 0x2
+#define RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK 0x8
+#define RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE__SHIFT 0x3
+#define RLC_PG_CNTL__GFX_PIPELINE_PG_ENABLE_MASK 0x10
+#define RLC_PG_CNTL__GFX_PIPELINE_PG_ENABLE__SHIFT 0x4
+#define RLC_PG_CNTL__RESERVED_MASK 0x3fe0
+#define RLC_PG_CNTL__RESERVED__SHIFT 0x5
+#define RLC_PG_CNTL__PG_OVERRIDE_MASK 0x4000
+#define RLC_PG_CNTL__PG_OVERRIDE__SHIFT 0xe
+#define RLC_PG_CNTL__CP_PG_DISABLE_MASK 0x8000
+#define RLC_PG_CNTL__CP_PG_DISABLE__SHIFT 0xf
+#define RLC_PG_CNTL__CHUB_HANDSHAKE_ENABLE_MASK 0x10000
+#define RLC_PG_CNTL__CHUB_HANDSHAKE_ENABLE__SHIFT 0x10
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK 0x20000
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE__SHIFT 0x11
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK 0x40000
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE__SHIFT 0x12
+#define RLC_PG_CNTL__SMU_HANDSHAKE_ENABLE_MASK 0x80000
+#define RLC_PG_CNTL__SMU_HANDSHAKE_ENABLE__SHIFT 0x13
+#define RLC_PG_CNTL__RESERVED1_MASK 0xf00000
+#define RLC_PG_CNTL__RESERVED1__SHIFT 0x14
+#define RLC_GPM_THREAD_PRIORITY__THREAD0_PRIORITY_MASK 0xff
+#define RLC_GPM_THREAD_PRIORITY__THREAD0_PRIORITY__SHIFT 0x0
+#define RLC_GPM_THREAD_PRIORITY__THREAD1_PRIORITY_MASK 0xff00
+#define RLC_GPM_THREAD_PRIORITY__THREAD1_PRIORITY__SHIFT 0x8
+#define RLC_GPM_THREAD_PRIORITY__THREAD2_PRIORITY_MASK 0xff0000
+#define RLC_GPM_THREAD_PRIORITY__THREAD2_PRIORITY__SHIFT 0x10
+#define RLC_GPM_THREAD_PRIORITY__THREAD3_PRIORITY_MASK 0xff000000
+#define RLC_GPM_THREAD_PRIORITY__THREAD3_PRIORITY__SHIFT 0x18
+#define RLC_GPM_THREAD_ENABLE__THREAD0_ENABLE_MASK 0x1
+#define RLC_GPM_THREAD_ENABLE__THREAD0_ENABLE__SHIFT 0x0
+#define RLC_GPM_THREAD_ENABLE__THREAD1_ENABLE_MASK 0x2
+#define RLC_GPM_THREAD_ENABLE__THREAD1_ENABLE__SHIFT 0x1
+#define RLC_GPM_THREAD_ENABLE__THREAD2_ENABLE_MASK 0x4
+#define RLC_GPM_THREAD_ENABLE__THREAD2_ENABLE__SHIFT 0x2
+#define RLC_GPM_THREAD_ENABLE__THREAD3_ENABLE_MASK 0x8
+#define RLC_GPM_THREAD_ENABLE__THREAD3_ENABLE__SHIFT 0x3
+#define RLC_GPM_THREAD_ENABLE__RESERVED_MASK 0xfffffff0
+#define RLC_GPM_THREAD_ENABLE__RESERVED__SHIFT 0x4
+#define RLC_GPM_VMID_THREAD0__RLC_VMID_MASK 0xf
+#define RLC_GPM_VMID_THREAD0__RLC_VMID__SHIFT 0x0
+#define RLC_GPM_VMID_THREAD0__RESERVED0_MASK 0xf0
+#define RLC_GPM_VMID_THREAD0__RESERVED0__SHIFT 0x4
+#define RLC_GPM_VMID_THREAD0__RLC_QUEUEID_MASK 0x700
+#define RLC_GPM_VMID_THREAD0__RLC_QUEUEID__SHIFT 0x8
+#define RLC_GPM_VMID_THREAD0__RESERVED1_MASK 0xfffff800
+#define RLC_GPM_VMID_THREAD0__RESERVED1__SHIFT 0xb
+#define RLC_GPM_VMID_THREAD1__RLC_VMID_MASK 0xf
+#define RLC_GPM_VMID_THREAD1__RLC_VMID__SHIFT 0x0
+#define RLC_GPM_VMID_THREAD1__RESERVED0_MASK 0xf0
+#define RLC_GPM_VMID_THREAD1__RESERVED0__SHIFT 0x4
+#define RLC_GPM_VMID_THREAD1__RLC_QUEUEID_MASK 0x700
+#define RLC_GPM_VMID_THREAD1__RLC_QUEUEID__SHIFT 0x8
+#define RLC_GPM_VMID_THREAD1__RESERVED1_MASK 0xfffff800
+#define RLC_GPM_VMID_THREAD1__RESERVED1__SHIFT 0xb
+#define RLC_CGTT_MGCG_OVERRIDE__OVERRIDE_MASK 0xffffffff
+#define RLC_CGTT_MGCG_OVERRIDE__OVERRIDE__SHIFT 0x0
+#define RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK 0x1
+#define RLC_CGCG_CGLS_CTRL__CGCG_EN__SHIFT 0x0
+#define RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK 0x2
+#define RLC_CGCG_CGLS_CTRL__CGLS_EN__SHIFT 0x1
+#define RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY_MASK 0xfc
+#define RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT 0x2
+#define RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD_MASK 0x7ffff00
+#define RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT 0x8
+#define RLC_CGCG_CGLS_CTRL__CGCG_CONTROLLER_MASK 0x8000000
+#define RLC_CGCG_CGLS_CTRL__CGCG_CONTROLLER__SHIFT 0x1b
+#define RLC_CGCG_CGLS_CTRL__CGCG_REG_CTRL_MASK 0x10000000
+#define RLC_CGCG_CGLS_CTRL__CGCG_REG_CTRL__SHIFT 0x1c
+#define RLC_CGCG_CGLS_CTRL__SLEEP_MODE_MASK 0x60000000
+#define RLC_CGCG_CGLS_CTRL__SLEEP_MODE__SHIFT 0x1d
+#define RLC_CGCG_CGLS_CTRL__SIM_SILICON_EN_MASK 0x80000000
+#define RLC_CGCG_CGLS_CTRL__SIM_SILICON_EN__SHIFT 0x1f
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_START_UNIT_MASK 0xf
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_START_UNIT__SHIFT 0x0
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_STEP_UNIT_MASK 0xf0
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_STEP_UNIT__SHIFT 0x4
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_START_UNIT_MASK 0xf00
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_START_UNIT__SHIFT 0x8
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_STEP_UNIT_MASK 0xf000
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_STEP_UNIT__SHIFT 0xc
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_CNT_MASK 0xfff0000
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_CNT__SHIFT 0x10
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_UNIT_MASK 0xf0000000
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_UNIT__SHIFT 0x1c
+#define RLC_DYN_PG_STATUS__PG_STATUS_CU_MASK_MASK 0xffffffff
+#define RLC_DYN_PG_STATUS__PG_STATUS_CU_MASK__SHIFT 0x0
+#define RLC_DYN_PG_REQUEST__PG_REQUEST_CU_MASK_MASK 0xffffffff
+#define RLC_DYN_PG_REQUEST__PG_REQUEST_CU_MASK__SHIFT 0x0
+#define RLC_PG_DELAY__POWER_UP_DELAY_MASK 0xff
+#define RLC_PG_DELAY__POWER_UP_DELAY__SHIFT 0x0
+#define RLC_PG_DELAY__POWER_DOWN_DELAY_MASK 0xff00
+#define RLC_PG_DELAY__POWER_DOWN_DELAY__SHIFT 0x8
+#define RLC_PG_DELAY__CMD_PROPAGATE_DELAY_MASK 0xff0000
+#define RLC_PG_DELAY__CMD_PROPAGATE_DELAY__SHIFT 0x10
+#define RLC_PG_DELAY__MEM_SLEEP_DELAY_MASK 0xff000000
+#define RLC_PG_DELAY__MEM_SLEEP_DELAY__SHIFT 0x18
+#define RLC_CU_STATUS__WORK_PENDING_MASK 0xffffffff
+#define RLC_CU_STATUS__WORK_PENDING__SHIFT 0x0
+#define RLC_LB_INIT_CU_MASK__INIT_CU_MASK_MASK 0xffffffff
+#define RLC_LB_INIT_CU_MASK__INIT_CU_MASK__SHIFT 0x0
+#define RLC_LB_ALWAYS_ACTIVE_CU_MASK__ALWAYS_ACTIVE_CU_MASK_MASK 0xffffffff
+#define RLC_LB_ALWAYS_ACTIVE_CU_MASK__ALWAYS_ACTIVE_CU_MASK__SHIFT 0x0
+#define RLC_LB_PARAMS__SKIP_L2_CHECK_MASK 0x1
+#define RLC_LB_PARAMS__SKIP_L2_CHECK__SHIFT 0x0
+#define RLC_LB_PARAMS__FIFO_SAMPLES_MASK 0xfe
+#define RLC_LB_PARAMS__FIFO_SAMPLES__SHIFT 0x1
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLES_MASK 0xff00
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLES__SHIFT 0x8
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLE_INTERVAL_MASK 0xffff0000
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLE_INTERVAL__SHIFT 0x10
+#define RLC_THREAD1_DELAY__CU_IDEL_DELAY_MASK 0xff
+#define RLC_THREAD1_DELAY__CU_IDEL_DELAY__SHIFT 0x0
+#define RLC_THREAD1_DELAY__LBPW_INNER_LOOP_DELAY_MASK 0xff00
+#define RLC_THREAD1_DELAY__LBPW_INNER_LOOP_DELAY__SHIFT 0x8
+#define RLC_THREAD1_DELAY__LBPW_OUTER_LOOP_DELAY_MASK 0xff0000
+#define RLC_THREAD1_DELAY__LBPW_OUTER_LOOP_DELAY__SHIFT 0x10
+#define RLC_THREAD1_DELAY__SPARE_MASK 0xff000000
+#define RLC_THREAD1_DELAY__SPARE__SHIFT 0x18
+#define RLC_PG_ALWAYS_ON_CU_MASK__AON_CU_MASK_MASK 0xffffffff
+#define RLC_PG_ALWAYS_ON_CU_MASK__AON_CU_MASK__SHIFT 0x0
+#define RLC_MAX_PG_CU__MAX_POWERED_UP_CU_MASK 0xff
+#define RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT 0x0
+#define RLC_MAX_PG_CU__SPARE_MASK 0xffffff00
+#define RLC_MAX_PG_CU__SPARE__SHIFT 0x8
+#define RLC_AUTO_PG_CTRL__AUTO_PG_EN_MASK 0x1
+#define RLC_AUTO_PG_CTRL__AUTO_PG_EN__SHIFT 0x0
+#define RLC_AUTO_PG_CTRL__AUTO_GRBM_REG_SAVE_ON_IDLE_EN_MASK 0x2
+#define RLC_AUTO_PG_CTRL__AUTO_GRBM_REG_SAVE_ON_IDLE_EN__SHIFT 0x1
+#define RLC_AUTO_PG_CTRL__AUTO_WAKE_UP_EN_MASK 0x4
+#define RLC_AUTO_PG_CTRL__AUTO_WAKE_UP_EN__SHIFT 0x2
+#define RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD_MASK 0x7fff8
+#define RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT 0x3
+#define RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD_MASK 0xfff80000
+#define RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD__SHIFT 0x13
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__START_GRBM_REG_SAVE_MASK 0x1
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__START_GRBM_REG_SAVE__SHIFT 0x0
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__SPARE_MASK 0xfffffffe
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__SPARE__SHIFT 0x1
+#define RLC_SERDES_RD_MASTER_INDEX__CU_ID_MASK 0xf
+#define RLC_SERDES_RD_MASTER_INDEX__CU_ID__SHIFT 0x0
+#define RLC_SERDES_RD_MASTER_INDEX__SH_ID_MASK 0x30
+#define RLC_SERDES_RD_MASTER_INDEX__SH_ID__SHIFT 0x4
+#define RLC_SERDES_RD_MASTER_INDEX__SE_ID_MASK 0x1c0
+#define RLC_SERDES_RD_MASTER_INDEX__SE_ID__SHIFT 0x6
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_ID_MASK 0x200
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_ID__SHIFT 0x9
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_MASK 0x400
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU__SHIFT 0xa
+#define RLC_SERDES_RD_MASTER_INDEX__NON_SE_MASK 0x7800
+#define RLC_SERDES_RD_MASTER_INDEX__NON_SE__SHIFT 0xb
+#define RLC_SERDES_RD_MASTER_INDEX__DATA_REG_ID_MASK 0x18000
+#define RLC_SERDES_RD_MASTER_INDEX__DATA_REG_ID__SHIFT 0xf
+#define RLC_SERDES_RD_MASTER_INDEX__SPARE_MASK 0xfffe0000
+#define RLC_SERDES_RD_MASTER_INDEX__SPARE__SHIFT 0x11
+#define RLC_SERDES_RD_DATA_0__DATA_MASK 0xffffffff
+#define RLC_SERDES_RD_DATA_0__DATA__SHIFT 0x0
+#define RLC_SERDES_RD_DATA_1__DATA_MASK 0xffffffff
+#define RLC_SERDES_RD_DATA_1__DATA__SHIFT 0x0
+#define RLC_SERDES_RD_DATA_2__DATA_MASK 0xffffffff
+#define RLC_SERDES_RD_DATA_2__DATA__SHIFT 0x0
+#define RLC_SERDES_WR_CU_MASTER_MASK__MASTER_MASK_MASK 0xffffffff
+#define RLC_SERDES_WR_CU_MASTER_MASK__MASTER_MASK__SHIFT 0x0
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SE_MASTER_MASK_MASK 0xffff
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SE_MASTER_MASK__SHIFT 0x0
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__GC_MASTER_MASK_MASK 0x10000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__GC_MASTER_MASK__SHIFT 0x10
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__GC_GFX_MASTER_MASK_MASK 0x20000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__GC_GFX_MASTER_MASK__SHIFT 0x11
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__TC0_MASTER_MASK_MASK 0x40000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__TC0_MASTER_MASK__SHIFT 0x12
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__TC1_MASTER_MASK_MASK 0x80000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__TC1_MASTER_MASK__SHIFT 0x13
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE0_MASTER_MASK_MASK 0x100000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE0_MASTER_MASK__SHIFT 0x14
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE1_MASTER_MASK_MASK 0x200000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE1_MASTER_MASK__SHIFT 0x15
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE2_MASTER_MASK_MASK 0x400000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE2_MASTER_MASK__SHIFT 0x16
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE3_MASTER_MASK_MASK 0x800000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__SPARE3_MASTER_MASK__SHIFT 0x17
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__RESERVED_MASK 0xff000000
+#define RLC_SERDES_WR_NONCU_MASTER_MASK__RESERVED__SHIFT 0x18
+#define RLC_SERDES_WR_CTRL__BPM_ADDR_MASK 0xff
+#define RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT 0x0
+#define RLC_SERDES_WR_CTRL__POWER_DOWN_MASK 0x100
+#define RLC_SERDES_WR_CTRL__POWER_DOWN__SHIFT 0x8
+#define RLC_SERDES_WR_CTRL__POWER_UP_MASK 0x200
+#define RLC_SERDES_WR_CTRL__POWER_UP__SHIFT 0x9
+#define RLC_SERDES_WR_CTRL__P1_SELECT_MASK 0x400
+#define RLC_SERDES_WR_CTRL__P1_SELECT__SHIFT 0xa
+#define RLC_SERDES_WR_CTRL__P2_SELECT_MASK 0x800
+#define RLC_SERDES_WR_CTRL__P2_SELECT__SHIFT 0xb
+#define RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK 0x1000
+#define RLC_SERDES_WR_CTRL__WRITE_COMMAND__SHIFT 0xc
+#define RLC_SERDES_WR_CTRL__READ_COMMAND_MASK 0x2000
+#define RLC_SERDES_WR_CTRL__READ_COMMAND__SHIFT 0xd
+#define RLC_SERDES_WR_CTRL__RDDATA_RESET_MASK 0x4000
+#define RLC_SERDES_WR_CTRL__RDDATA_RESET__SHIFT 0xe
+#define RLC_SERDES_WR_CTRL__SHORT_FORMAT_MASK 0x8000
+#define RLC_SERDES_WR_CTRL__SHORT_FORMAT__SHIFT 0xf
+#define RLC_SERDES_WR_CTRL__BPM_DATA_MASK 0x3ff0000
+#define RLC_SERDES_WR_CTRL__BPM_DATA__SHIFT 0x10
+#define RLC_SERDES_WR_CTRL__SRBM_OVERRIDE_MASK 0x4000000
+#define RLC_SERDES_WR_CTRL__SRBM_OVERRIDE__SHIFT 0x1a
+#define RLC_SERDES_WR_CTRL__RSVD_BPM_ADDR_MASK 0x8000000
+#define RLC_SERDES_WR_CTRL__RSVD_BPM_ADDR__SHIFT 0x1b
+#define RLC_SERDES_WR_CTRL__REG_ADDR_MASK 0xf0000000
+#define RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT 0x1c
+#define RLC_SERDES_WR_DATA__DATA_MASK 0xffffffff
+#define RLC_SERDES_WR_DATA__DATA__SHIFT 0x0
+#define RLC_SERDES_CU_MASTER_BUSY__BUSY_BUSY_MASK 0xffffffff
+#define RLC_SERDES_CU_MASTER_BUSY__BUSY_BUSY__SHIFT 0x0
+#define RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK 0xffff
+#define RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY__SHIFT 0x0
+#define RLC_SERDES_NONCU_MASTER_BUSY__GC_MASTER_BUSY_MASK 0x10000
+#define RLC_SERDES_NONCU_MASTER_BUSY__GC_MASTER_BUSY__SHIFT 0x10
+#define RLC_SERDES_NONCU_MASTER_BUSY__GC_GFX_MASTER_BUSY_MASK 0x20000
+#define RLC_SERDES_NONCU_MASTER_BUSY__GC_GFX_MASTER_BUSY__SHIFT 0x11
+#define RLC_SERDES_NONCU_MASTER_BUSY__TC0_MASTER_BUSY_MASK 0x40000
+#define RLC_SERDES_NONCU_MASTER_BUSY__TC0_MASTER_BUSY__SHIFT 0x12
+#define RLC_SERDES_NONCU_MASTER_BUSY__TC1_MASTER_BUSY_MASK 0x80000
+#define RLC_SERDES_NONCU_MASTER_BUSY__TC1_MASTER_BUSY__SHIFT 0x13
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE0_MASTER_BUSY_MASK 0x100000
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE0_MASTER_BUSY__SHIFT 0x14
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE1_MASTER_BUSY_MASK 0x200000
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE1_MASTER_BUSY__SHIFT 0x15
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE2_MASTER_BUSY_MASK 0x400000
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE2_MASTER_BUSY__SHIFT 0x16
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE3_MASTER_BUSY_MASK 0x800000
+#define RLC_SERDES_NONCU_MASTER_BUSY__SPARE3_MASTER_BUSY__SHIFT 0x17
+#define RLC_SERDES_NONCU_MASTER_BUSY__RESERVED_MASK 0xff000000
+#define RLC_SERDES_NONCU_MASTER_BUSY__RESERVED__SHIFT 0x18
+#define RLC_GPM_GENERAL_0__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_0__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_1__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_1__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_2__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_2__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_3__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_3__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_4__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_4__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_5__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_5__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_6__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_6__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_7__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_7__DATA__SHIFT 0x0
+#define RLC_GPM_SCRATCH_ADDR__ADDR_MASK 0x1ff
+#define RLC_GPM_SCRATCH_ADDR__ADDR__SHIFT 0x0
+#define RLC_GPM_SCRATCH_ADDR__RESERVED_MASK 0xfffffe00
+#define RLC_GPM_SCRATCH_ADDR__RESERVED__SHIFT 0x9
+#define RLC_GPM_SCRATCH_DATA__DATA_MASK 0xffffffff
+#define RLC_GPM_SCRATCH_DATA__DATA__SHIFT 0x0
+#define RLC_STATIC_PG_STATUS__PG_STATUS_CU_MASK_MASK 0xffffffff
+#define RLC_STATIC_PG_STATUS__PG_STATUS_CU_MASK__SHIFT 0x0
+#define RLC_GPM_PERF_COUNT_0__FEATURE_SEL_MASK 0xf
+#define RLC_GPM_PERF_COUNT_0__FEATURE_SEL__SHIFT 0x0
+#define RLC_GPM_PERF_COUNT_0__SE_INDEX_MASK 0xf0
+#define RLC_GPM_PERF_COUNT_0__SE_INDEX__SHIFT 0x4
+#define RLC_GPM_PERF_COUNT_0__SH_INDEX_MASK 0xf00
+#define RLC_GPM_PERF_COUNT_0__SH_INDEX__SHIFT 0x8
+#define RLC_GPM_PERF_COUNT_0__CU_INDEX_MASK 0xf000
+#define RLC_GPM_PERF_COUNT_0__CU_INDEX__SHIFT 0xc
+#define RLC_GPM_PERF_COUNT_0__EVENT_SEL_MASK 0x30000
+#define RLC_GPM_PERF_COUNT_0__EVENT_SEL__SHIFT 0x10
+#define RLC_GPM_PERF_COUNT_0__UNUSED_MASK 0xc0000
+#define RLC_GPM_PERF_COUNT_0__UNUSED__SHIFT 0x12
+#define RLC_GPM_PERF_COUNT_0__ENABLE_MASK 0x100000
+#define RLC_GPM_PERF_COUNT_0__ENABLE__SHIFT 0x14
+#define RLC_GPM_PERF_COUNT_0__RESERVED_MASK 0xffe00000
+#define RLC_GPM_PERF_COUNT_0__RESERVED__SHIFT 0x15
+#define RLC_GPM_PERF_COUNT_1__FEATURE_SEL_MASK 0xf
+#define RLC_GPM_PERF_COUNT_1__FEATURE_SEL__SHIFT 0x0
+#define RLC_GPM_PERF_COUNT_1__SE_INDEX_MASK 0xf0
+#define RLC_GPM_PERF_COUNT_1__SE_INDEX__SHIFT 0x4
+#define RLC_GPM_PERF_COUNT_1__SH_INDEX_MASK 0xf00
+#define RLC_GPM_PERF_COUNT_1__SH_INDEX__SHIFT 0x8
+#define RLC_GPM_PERF_COUNT_1__CU_INDEX_MASK 0xf000
+#define RLC_GPM_PERF_COUNT_1__CU_INDEX__SHIFT 0xc
+#define RLC_GPM_PERF_COUNT_1__EVENT_SEL_MASK 0x30000
+#define RLC_GPM_PERF_COUNT_1__EVENT_SEL__SHIFT 0x10
+#define RLC_GPM_PERF_COUNT_1__UNUSED_MASK 0xc0000
+#define RLC_GPM_PERF_COUNT_1__UNUSED__SHIFT 0x12
+#define RLC_GPM_PERF_COUNT_1__ENABLE_MASK 0x100000
+#define RLC_GPM_PERF_COUNT_1__ENABLE__SHIFT 0x14
+#define RLC_GPM_PERF_COUNT_1__RESERVED_MASK 0xffe00000
+#define RLC_GPM_PERF_COUNT_1__RESERVED__SHIFT 0x15
+#define RLC_GPR_REG1__DATA_MASK 0xffffffff
+#define RLC_GPR_REG1__DATA__SHIFT 0x0
+#define RLC_GPR_REG2__DATA_MASK 0xffffffff
+#define RLC_GPR_REG2__DATA__SHIFT 0x0
+#define RLC_MGCG_CTRL__MGCG_EN_MASK 0x1
+#define RLC_MGCG_CTRL__MGCG_EN__SHIFT 0x0
+#define RLC_MGCG_CTRL__SILICON_EN_MASK 0x2
+#define RLC_MGCG_CTRL__SILICON_EN__SHIFT 0x1
+#define RLC_MGCG_CTRL__SIMULATION_EN_MASK 0x4
+#define RLC_MGCG_CTRL__SIMULATION_EN__SHIFT 0x2
+#define RLC_MGCG_CTRL__ON_DELAY_MASK 0x78
+#define RLC_MGCG_CTRL__ON_DELAY__SHIFT 0x3
+#define RLC_MGCG_CTRL__OFF_HYSTERESIS_MASK 0x7f80
+#define RLC_MGCG_CTRL__OFF_HYSTERESIS__SHIFT 0x7
+#define RLC_MGCG_CTRL__GC_CAC_MGCG_CLK_CNTL_MASK 0x8000
+#define RLC_MGCG_CTRL__GC_CAC_MGCG_CLK_CNTL__SHIFT 0xf
+#define RLC_MGCG_CTRL__SE_CAC_MGCG_CLK_CNTL_MASK 0x10000
+#define RLC_MGCG_CTRL__SE_CAC_MGCG_CLK_CNTL__SHIFT 0x10
+#define RLC_MGCG_CTRL__SPARE_MASK 0xfffe0000
+#define RLC_MGCG_CTRL__SPARE__SHIFT 0x11
+#define RLC_GPM_THREAD_RESET__THREAD0_RESET_MASK 0x1
+#define RLC_GPM_THREAD_RESET__THREAD0_RESET__SHIFT 0x0
+#define RLC_GPM_THREAD_RESET__THREAD1_RESET_MASK 0x2
+#define RLC_GPM_THREAD_RESET__THREAD1_RESET__SHIFT 0x1
+#define RLC_GPM_THREAD_RESET__THREAD2_RESET_MASK 0x4
+#define RLC_GPM_THREAD_RESET__THREAD2_RESET__SHIFT 0x2
+#define RLC_GPM_THREAD_RESET__THREAD3_RESET_MASK 0x8
+#define RLC_GPM_THREAD_RESET__THREAD3_RESET__SHIFT 0x3
+#define RLC_GPM_THREAD_RESET__RESERVED_MASK 0xfffffff0
+#define RLC_GPM_THREAD_RESET__RESERVED__SHIFT 0x4
+#define RLC_SPM_VMID__RLC_SPM_VMID_MASK 0xf
+#define RLC_SPM_VMID__RLC_SPM_VMID__SHIFT 0x0
+#define RLC_SPM_VMID__RESERVED_MASK 0xfffffff0
+#define RLC_SPM_VMID__RESERVED__SHIFT 0x4
+#define RLC_SPM_INT_CNTL__RLC_SPM_INT_CNTL_MASK 0x1
+#define RLC_SPM_INT_CNTL__RLC_SPM_INT_CNTL__SHIFT 0x0
+#define RLC_SPM_INT_CNTL__RESERVED_MASK 0xfffffffe
+#define RLC_SPM_INT_CNTL__RESERVED__SHIFT 0x1
+#define RLC_SPM_INT_STATUS__RLC_SPM_INT_STATUS_MASK 0x1
+#define RLC_SPM_INT_STATUS__RLC_SPM_INT_STATUS__SHIFT 0x0
+#define RLC_SPM_INT_STATUS__RESERVED_MASK 0xfffffffe
+#define RLC_SPM_INT_STATUS__RESERVED__SHIFT 0x1
+#define RLC_SPM_DEBUG_SELECT__SELECT_MASK 0xff
+#define RLC_SPM_DEBUG_SELECT__SELECT__SHIFT 0x0
+#define RLC_SPM_DEBUG_SELECT__RESERVED_MASK 0x7f00
+#define RLC_SPM_DEBUG_SELECT__RESERVED__SHIFT 0x8
+#define RLC_SPM_DEBUG_SELECT__RLC_SPM_DEBUG_MODE_MASK 0x8000
+#define RLC_SPM_DEBUG_SELECT__RLC_SPM_DEBUG_MODE__SHIFT 0xf
+#define RLC_SPM_DEBUG_SELECT__RLC_SPM_NUM_SAMPLE_MASK 0xffff0000
+#define RLC_SPM_DEBUG_SELECT__RLC_SPM_NUM_SAMPLE__SHIFT 0x10
+#define RLC_SPM_DEBUG__DATA_MASK 0xffffffff
+#define RLC_SPM_DEBUG__DATA__SHIFT 0x0
+#define RLC_SMU_MESSAGE__CMD_MASK 0xffffffff
+#define RLC_SMU_MESSAGE__CMD__SHIFT 0x0
+#define RLC_GPM_LOG_SIZE__SIZE_MASK 0xffffffff
+#define RLC_GPM_LOG_SIZE__SIZE__SHIFT 0x0
+#define RLC_GPM_LOG_CONT__CONT_MASK 0xffffffff
+#define RLC_GPM_LOG_CONT__CONT__SHIFT 0x0
+#define RLC_PG_DELAY_3__CGCG_ACTIVE_BEFORE_CGPG_MASK 0xff
+#define RLC_PG_DELAY_3__CGCG_ACTIVE_BEFORE_CGPG__SHIFT 0x0
+#define RLC_PG_DELAY_3__RESERVED_MASK 0xffffff00
+#define RLC_PG_DELAY_3__RESERVED__SHIFT 0x8
+#define RLC_GPM_INT_DISABLE_TH0__DISABLE_MASK 0xffffffff
+#define RLC_GPM_INT_DISABLE_TH0__DISABLE__SHIFT 0x0
+#define RLC_GPM_INT_DISABLE_TH1__DISABLE_MASK 0xffffffff
+#define RLC_GPM_INT_DISABLE_TH1__DISABLE__SHIFT 0x0
+#define RLC_GPM_INT_FORCE_TH0__FORCE_MASK 0xffffffff
+#define RLC_GPM_INT_FORCE_TH0__FORCE__SHIFT 0x0
+#define RLC_GPM_INT_FORCE_TH1__FORCE_MASK 0xffffffff
+#define RLC_GPM_INT_FORCE_TH1__FORCE__SHIFT 0x0
+#define RLC_SRM_CNTL__SRM_ENABLE_MASK 0x1
+#define RLC_SRM_CNTL__SRM_ENABLE__SHIFT 0x0
+#define RLC_SRM_CNTL__AUTO_INCR_ADDR_MASK 0x2
+#define RLC_SRM_CNTL__AUTO_INCR_ADDR__SHIFT 0x1
+#define RLC_SRM_CNTL__RESERVED_MASK 0xfffffffc
+#define RLC_SRM_CNTL__RESERVED__SHIFT 0x2
+#define RLC_SRM_DEBUG_SELECT__SELECT_MASK 0xff
+#define RLC_SRM_DEBUG_SELECT__SELECT__SHIFT 0x0
+#define RLC_SRM_DEBUG_SELECT__RESERVED_MASK 0xffffff00
+#define RLC_SRM_DEBUG_SELECT__RESERVED__SHIFT 0x8
+#define RLC_SRM_DEBUG__DATA_MASK 0xffffffff
+#define RLC_SRM_DEBUG__DATA__SHIFT 0x0
+#define RLC_SRM_ARAM_ADDR__ADDR_MASK 0x3ff
+#define RLC_SRM_ARAM_ADDR__ADDR__SHIFT 0x0
+#define RLC_SRM_ARAM_ADDR__RESERVED_MASK 0xfffffc00
+#define RLC_SRM_ARAM_ADDR__RESERVED__SHIFT 0xa
+#define RLC_SRM_ARAM_DATA__DATA_MASK 0xffffffff
+#define RLC_SRM_ARAM_DATA__DATA__SHIFT 0x0
+#define RLC_SRM_DRAM_ADDR__ADDR_MASK 0x3ff
+#define RLC_SRM_DRAM_ADDR__ADDR__SHIFT 0x0
+#define RLC_SRM_DRAM_ADDR__RESERVED_MASK 0xfffffc00
+#define RLC_SRM_DRAM_ADDR__RESERVED__SHIFT 0xa
+#define RLC_SRM_DRAM_DATA__DATA_MASK 0xffffffff
+#define RLC_SRM_DRAM_DATA__DATA__SHIFT 0x0
+#define RLC_SRM_GPM_COMMAND__OP_MASK 0x1
+#define RLC_SRM_GPM_COMMAND__OP__SHIFT 0x0
+#define RLC_SRM_GPM_COMMAND__INDEX_CNTL_MASK 0x2
+#define RLC_SRM_GPM_COMMAND__INDEX_CNTL__SHIFT 0x1
+#define RLC_SRM_GPM_COMMAND__INDEX_CNTL_NUM_MASK 0x1c
+#define RLC_SRM_GPM_COMMAND__INDEX_CNTL_NUM__SHIFT 0x2
+#define RLC_SRM_GPM_COMMAND__SIZE_MASK 0x1ffe0
+#define RLC_SRM_GPM_COMMAND__SIZE__SHIFT 0x5
+#define RLC_SRM_GPM_COMMAND__START_OFFSET_MASK 0x1ffe0000
+#define RLC_SRM_GPM_COMMAND__START_OFFSET__SHIFT 0x11
+#define RLC_SRM_GPM_COMMAND__RESERVED1_MASK 0x60000000
+#define RLC_SRM_GPM_COMMAND__RESERVED1__SHIFT 0x1d
+#define RLC_SRM_GPM_COMMAND__DEST_MEMORY_MASK 0x80000000
+#define RLC_SRM_GPM_COMMAND__DEST_MEMORY__SHIFT 0x1f
+#define RLC_SRM_GPM_COMMAND_STATUS__FIFO_EMPTY_MASK 0x1
+#define RLC_SRM_GPM_COMMAND_STATUS__FIFO_EMPTY__SHIFT 0x0
+#define RLC_SRM_GPM_COMMAND_STATUS__FIFO_FULL_MASK 0x2
+#define RLC_SRM_GPM_COMMAND_STATUS__FIFO_FULL__SHIFT 0x1
+#define RLC_SRM_GPM_COMMAND_STATUS__RESERVED_MASK 0xfffffffc
+#define RLC_SRM_GPM_COMMAND_STATUS__RESERVED__SHIFT 0x2
+#define RLC_SRM_RLCV_COMMAND__OP_MASK 0x1
+#define RLC_SRM_RLCV_COMMAND__OP__SHIFT 0x0
+#define RLC_SRM_RLCV_COMMAND__RESERVED_MASK 0xe
+#define RLC_SRM_RLCV_COMMAND__RESERVED__SHIFT 0x1
+#define RLC_SRM_RLCV_COMMAND__SIZE_MASK 0xfff0
+#define RLC_SRM_RLCV_COMMAND__SIZE__SHIFT 0x4
+#define RLC_SRM_RLCV_COMMAND__START_OFFSET_MASK 0xfff0000
+#define RLC_SRM_RLCV_COMMAND__START_OFFSET__SHIFT 0x10
+#define RLC_SRM_RLCV_COMMAND__RESERVED1_MASK 0x70000000
+#define RLC_SRM_RLCV_COMMAND__RESERVED1__SHIFT 0x1c
+#define RLC_SRM_RLCV_COMMAND__DEST_MEMORY_MASK 0x80000000
+#define RLC_SRM_RLCV_COMMAND__DEST_MEMORY__SHIFT 0x1f
+#define RLC_SRM_RLCV_COMMAND_STATUS__FIFO_EMPTY_MASK 0x1
+#define RLC_SRM_RLCV_COMMAND_STATUS__FIFO_EMPTY__SHIFT 0x0
+#define RLC_SRM_RLCV_COMMAND_STATUS__FIFO_FULL_MASK 0x2
+#define RLC_SRM_RLCV_COMMAND_STATUS__FIFO_FULL__SHIFT 0x1
+#define RLC_SRM_RLCV_COMMAND_STATUS__RESERVED_MASK 0xfffffffc
+#define RLC_SRM_RLCV_COMMAND_STATUS__RESERVED__SHIFT 0x2
+#define RLC_SRM_INDEX_CNTL_ADDR_0__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_0__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_0__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_0__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_1__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_1__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_1__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_1__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_2__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_2__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_2__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_2__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_3__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_3__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_3__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_3__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_4__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_4__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_4__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_4__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_5__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_5__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_5__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_5__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_6__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_6__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_6__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_6__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_ADDR_7__ADDRESS_MASK 0xffff
+#define RLC_SRM_INDEX_CNTL_ADDR_7__ADDRESS__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_ADDR_7__RESERVED_MASK 0xffff0000
+#define RLC_SRM_INDEX_CNTL_ADDR_7__RESERVED__SHIFT 0x10
+#define RLC_SRM_INDEX_CNTL_DATA_0__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_0__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_1__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_1__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_2__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_2__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_3__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_3__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_4__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_4__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_5__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_5__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_6__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_6__DATA__SHIFT 0x0
+#define RLC_SRM_INDEX_CNTL_DATA_7__DATA_MASK 0xffffffff
+#define RLC_SRM_INDEX_CNTL_DATA_7__DATA__SHIFT 0x0
+#define RLC_SRM_STAT__SRM_STATUS_MASK 0x1
+#define RLC_SRM_STAT__SRM_STATUS__SHIFT 0x0
+#define RLC_SRM_STAT__RESERVED_MASK 0xfffffffe
+#define RLC_SRM_STAT__RESERVED__SHIFT 0x1
+#define RLC_SRM_GPM_ABORT__ABORT_MASK 0x1
+#define RLC_SRM_GPM_ABORT__ABORT__SHIFT 0x0
+#define RLC_SRM_GPM_ABORT__RESERVED_MASK 0xfffffffe
+#define RLC_SRM_GPM_ABORT__RESERVED__SHIFT 0x1
+#define RLC_CSIB_ADDR_LO__ADDRESS_MASK 0xffffffff
+#define RLC_CSIB_ADDR_LO__ADDRESS__SHIFT 0x0
+#define RLC_CSIB_ADDR_HI__ADDRESS_MASK 0xffff
+#define RLC_CSIB_ADDR_HI__ADDRESS__SHIFT 0x0
+#define RLC_CSIB_LENGTH__LENGTH_MASK 0xffffffff
+#define RLC_CSIB_LENGTH__LENGTH__SHIFT 0x0
+#define RLC_CP_RESPONSE0__RESPONSE_MASK 0xffffffff
+#define RLC_CP_RESPONSE0__RESPONSE__SHIFT 0x0
+#define RLC_CP_RESPONSE1__RESPONSE_MASK 0xffffffff
+#define RLC_CP_RESPONSE1__RESPONSE__SHIFT 0x0
+#define RLC_CP_RESPONSE2__RESPONSE_MASK 0xffffffff
+#define RLC_CP_RESPONSE2__RESPONSE__SHIFT 0x0
+#define RLC_CP_RESPONSE3__RESPONSE_MASK 0xffffffff
+#define RLC_CP_RESPONSE3__RESPONSE__SHIFT 0x0
+#define RLC_SMU_COMMAND__CMD_MASK 0xffffffff
+#define RLC_SMU_COMMAND__CMD__SHIFT 0x0
+#define RLC_CP_SCHEDULERS__scheduler0_MASK 0xff
+#define RLC_CP_SCHEDULERS__scheduler0__SHIFT 0x0
+#define RLC_CP_SCHEDULERS__scheduler1_MASK 0xff00
+#define RLC_CP_SCHEDULERS__scheduler1__SHIFT 0x8
+#define RLC_CP_SCHEDULERS__scheduler2_MASK 0xff0000
+#define RLC_CP_SCHEDULERS__scheduler2__SHIFT 0x10
+#define RLC_CP_SCHEDULERS__scheduler3_MASK 0xff000000
+#define RLC_CP_SCHEDULERS__scheduler3__SHIFT 0x18
+#define RLC_SMU_ARGUMENT_1__ARG_MASK 0xffffffff
+#define RLC_SMU_ARGUMENT_1__ARG__SHIFT 0x0
+#define RLC_SMU_ARGUMENT_2__ARG_MASK 0xffffffff
+#define RLC_SMU_ARGUMENT_2__ARG__SHIFT 0x0
+#define RLC_GPM_GENERAL_8__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_8__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_9__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_9__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_10__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_10__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_11__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_11__DATA__SHIFT 0x0
+#define RLC_GPM_GENERAL_12__DATA_MASK 0xffffffff
+#define RLC_GPM_GENERAL_12__DATA__SHIFT 0x0
+#define RLC_SPM_PERFMON_CNTL__RESERVED1_MASK 0xfff
+#define RLC_SPM_PERFMON_CNTL__RESERVED1__SHIFT 0x0
+#define RLC_SPM_PERFMON_CNTL__PERFMON_RING_MODE_MASK 0x3000
+#define RLC_SPM_PERFMON_CNTL__PERFMON_RING_MODE__SHIFT 0xc
+#define RLC_SPM_PERFMON_CNTL__RESERVED_MASK 0xc000
+#define RLC_SPM_PERFMON_CNTL__RESERVED__SHIFT 0xe
+#define RLC_SPM_PERFMON_CNTL__PERFMON_SAMPLE_INTERVAL_MASK 0xffff0000
+#define RLC_SPM_PERFMON_CNTL__PERFMON_SAMPLE_INTERVAL__SHIFT 0x10
+#define RLC_SPM_PERFMON_RING_BASE_LO__RING_BASE_LO_MASK 0xffffffff
+#define RLC_SPM_PERFMON_RING_BASE_LO__RING_BASE_LO__SHIFT 0x0
+#define RLC_SPM_PERFMON_RING_BASE_HI__RING_BASE_HI_MASK 0xffff
+#define RLC_SPM_PERFMON_RING_BASE_HI__RING_BASE_HI__SHIFT 0x0
+#define RLC_SPM_PERFMON_RING_BASE_HI__RESERVED_MASK 0xffff0000
+#define RLC_SPM_PERFMON_RING_BASE_HI__RESERVED__SHIFT 0x10
+#define RLC_SPM_PERFMON_RING_SIZE__RING_BASE_SIZE_MASK 0xffffffff
+#define RLC_SPM_PERFMON_RING_SIZE__RING_BASE_SIZE__SHIFT 0x0
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__PERFMON_SEGMENT_SIZE_MASK 0xff
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__PERFMON_SEGMENT_SIZE__SHIFT 0x0
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__RESERVED1_MASK 0x700
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__RESERVED1__SHIFT 0x8
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__GLOBAL_NUM_LINE_MASK 0xf800
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__GLOBAL_NUM_LINE__SHIFT 0xb
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__SE0_NUM_LINE_MASK 0x1f0000
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__SE0_NUM_LINE__SHIFT 0x10
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__SE1_NUM_LINE_MASK 0x3e00000
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__SE1_NUM_LINE__SHIFT 0x15
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__SE2_NUM_LINE_MASK 0x7c000000
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__SE2_NUM_LINE__SHIFT 0x1a
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__RESERVED_MASK 0x80000000
+#define RLC_SPM_PERFMON_SEGMENT_SIZE__RESERVED__SHIFT 0x1f
+#define RLC_SPM_SE_MUXSEL_ADDR__PERFMON_SEL_ADDR_MASK 0xffffffff
+#define RLC_SPM_SE_MUXSEL_ADDR__PERFMON_SEL_ADDR__SHIFT 0x0
+#define RLC_SPM_SE_MUXSEL_DATA__PERFMON_SEL_DATA_MASK 0xffffffff
+#define RLC_SPM_SE_MUXSEL_DATA__PERFMON_SEL_DATA__SHIFT 0x0
+#define RLC_SPM_CPG_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_CPG_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_CPG_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_CPG_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_CPC_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_CPC_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_CPC_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_CPC_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_CPF_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_CPF_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_CPF_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_CPF_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_CB_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_CB_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_CB_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_CB_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_DB_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_DB_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_DB_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_DB_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_PA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_PA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_PA_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_PA_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_GDS_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_GDS_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_GDS_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_GDS_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_IA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_IA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_IA_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_IA_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_SC_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_SC_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_SC_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_SC_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_TCC_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_TCC_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_TCC_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_TCC_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_TCA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_TCA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_TCA_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_TCA_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_TCP_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_TCP_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_TCP_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_TCP_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_TA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_TA_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_TA_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_TA_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_TD_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_TD_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_TD_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_TD_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_VGT_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_VGT_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_VGT_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_VGT_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_SPI_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_SPI_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_SPI_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_SPI_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_SQG_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_SQG_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_SQG_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_SQG_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_SX_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY_MASK 0xff
+#define RLC_SPM_SX_PERFMON_SAMPLE_DELAY__PERFMON_SAMPLE_DELAY__SHIFT 0x0
+#define RLC_SPM_SX_PERFMON_SAMPLE_DELAY__RESERVED_MASK 0xffffff00
+#define RLC_SPM_SX_PERFMON_SAMPLE_DELAY__RESERVED__SHIFT 0x8
+#define RLC_SPM_GLOBAL_MUXSEL_ADDR__PERFMON_SEL_ADDR_MASK 0xffffffff
+#define RLC_SPM_GLOBAL_MUXSEL_ADDR__PERFMON_SEL_ADDR__SHIFT 0x0
+#define RLC_SPM_GLOBAL_MUXSEL_DATA__PERFMON_SEL_DATA_MASK 0xffffffff
+#define RLC_SPM_GLOBAL_MUXSEL_DATA__PERFMON_SEL_DATA__SHIFT 0x0
+#define RLC_SPM_RING_RDPTR__PERFMON_RING_RDPTR_MASK 0xffffffff
+#define RLC_SPM_RING_RDPTR__PERFMON_RING_RDPTR__SHIFT 0x0
+#define RLC_SPM_SEGMENT_THRESHOLD__NUM_SEGMENT_THRESHOLD_MASK 0xffffffff
+#define RLC_SPM_SEGMENT_THRESHOLD__NUM_SEGMENT_THRESHOLD__SHIFT 0x0
+#define RLC_GPU_IOV_VF_ENABLE__VF_ENABLE_MASK 0x1
+#define RLC_GPU_IOV_VF_ENABLE__VF_ENABLE__SHIFT 0x0
+#define RLC_GPU_IOV_VF_ENABLE__RESERVED_MASK 0xfffe
+#define RLC_GPU_IOV_VF_ENABLE__RESERVED__SHIFT 0x1
+#define RLC_GPU_IOV_VF_ENABLE__VF_NUM_MASK 0xffff0000
+#define RLC_GPU_IOV_VF_ENABLE__VF_NUM__SHIFT 0x10
+#define RLC_GPU_IOV_RLC_RESPONSE__RESP_MASK 0xffffffff
+#define RLC_GPU_IOV_RLC_RESPONSE__RESP__SHIFT 0x0
+#define RLC_GPU_IOV_ACTIVE_FCN_ID__VF_ID_MASK 0xf
+#define RLC_GPU_IOV_ACTIVE_FCN_ID__VF_ID__SHIFT 0x0
+#define RLC_GPU_IOV_ACTIVE_FCN_ID__RESERVED_MASK 0x7ffffff0
+#define RLC_GPU_IOV_ACTIVE_FCN_ID__RESERVED__SHIFT 0x4
+#define RLC_GPU_IOV_ACTIVE_FCN_ID__PF_VF_MASK 0x80000000
+#define RLC_GPU_IOV_ACTIVE_FCN_ID__PF_VF__SHIFT 0x1f
+#define SPI_PS_INPUT_CNTL_0__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_0__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_0__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_0__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_0__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_0__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_0__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_0__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_0__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_0__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_0__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_0__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_0__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_0__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_0__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_0__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_1__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_1__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_1__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_1__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_1__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_1__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_1__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_1__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_1__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_1__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_1__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_1__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_1__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_1__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_1__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_1__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_2__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_2__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_2__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_2__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_2__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_2__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_2__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_2__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_2__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_2__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_2__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_2__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_2__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_2__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_2__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_2__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_3__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_3__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_3__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_3__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_3__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_3__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_3__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_3__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_3__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_3__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_3__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_3__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_3__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_3__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_3__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_3__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_4__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_4__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_4__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_4__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_4__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_4__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_4__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_4__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_4__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_4__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_4__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_4__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_4__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_4__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_4__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_4__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_5__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_5__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_5__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_5__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_5__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_5__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_5__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_5__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_5__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_5__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_5__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_5__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_5__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_5__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_5__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_5__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_6__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_6__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_6__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_6__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_6__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_6__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_6__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_6__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_6__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_6__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_6__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_6__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_6__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_6__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_6__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_6__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_7__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_7__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_7__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_7__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_7__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_7__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_7__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_7__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_7__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_7__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_7__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_7__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_7__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_7__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_7__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_7__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_8__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_8__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_8__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_8__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_8__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_8__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_8__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_8__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_8__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_8__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_8__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_8__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_8__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_8__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_8__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_8__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_9__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_9__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_9__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_9__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_9__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_9__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_9__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_9__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_9__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_9__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_9__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_9__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_9__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_9__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_9__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_9__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_10__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_10__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_10__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_10__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_10__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_10__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_10__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_10__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_10__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_10__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_10__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_10__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_10__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_10__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_10__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_10__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_11__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_11__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_11__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_11__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_11__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_11__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_11__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_11__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_11__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_11__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_11__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_11__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_11__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_11__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_11__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_11__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_12__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_12__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_12__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_12__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_12__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_12__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_12__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_12__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_12__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_12__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_12__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_12__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_12__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_12__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_12__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_12__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_13__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_13__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_13__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_13__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_13__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_13__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_13__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_13__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_13__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_13__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_13__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_13__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_13__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_13__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_13__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_13__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_14__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_14__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_14__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_14__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_14__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_14__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_14__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_14__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_14__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_14__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_14__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_14__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_14__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_14__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_14__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_14__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_15__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_15__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_15__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_15__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_15__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_15__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_15__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_15__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_15__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_15__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_15__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_15__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_15__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_15__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_15__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_15__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_16__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_16__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_16__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_16__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_16__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_16__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_16__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_16__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_16__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_16__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_16__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_16__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_16__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_16__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_16__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_16__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_17__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_17__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_17__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_17__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_17__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_17__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_17__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_17__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_17__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_17__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_17__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_17__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_17__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_17__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_17__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_17__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_18__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_18__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_18__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_18__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_18__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_18__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_18__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_18__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_18__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_18__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_18__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_18__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_18__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_18__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_18__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_18__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_19__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_19__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_19__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_19__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_19__CYL_WRAP_MASK 0x1e000
+#define SPI_PS_INPUT_CNTL_19__CYL_WRAP__SHIFT 0xd
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX_MASK 0x20000
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX__SHIFT 0x11
+#define SPI_PS_INPUT_CNTL_19__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_19__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_19__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_19__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_19__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_19__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX_ATTR1_MASK 0x800000
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX_ATTR1__SHIFT 0x17
+#define SPI_PS_INPUT_CNTL_19__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_19__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_19__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_19__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_20__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_20__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_20__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_20__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_20__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_20__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_20__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_20__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_20__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_20__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_20__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_20__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_20__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_20__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_21__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_21__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_21__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_21__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_21__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_21__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_21__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_21__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_21__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_21__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_21__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_21__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_21__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_21__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_22__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_22__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_22__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_22__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_22__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_22__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_22__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_22__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_22__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_22__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_22__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_22__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_22__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_22__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_23__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_23__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_23__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_23__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_23__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_23__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_23__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_23__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_23__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_23__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_23__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_23__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_23__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_23__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_24__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_24__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_24__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_24__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_24__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_24__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_24__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_24__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_24__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_24__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_24__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_24__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_24__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_24__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_25__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_25__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_25__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_25__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_25__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_25__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_25__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_25__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_25__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_25__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_25__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_25__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_25__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_25__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_26__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_26__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_26__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_26__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_26__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_26__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_26__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_26__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_26__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_26__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_26__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_26__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_26__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_26__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_27__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_27__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_27__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_27__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_27__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_27__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_27__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_27__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_27__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_27__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_27__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_27__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_27__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_27__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_28__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_28__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_28__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_28__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_28__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_28__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_28__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_28__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_28__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_28__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_28__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_28__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_28__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_28__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_29__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_29__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_29__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_29__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_29__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_29__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_29__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_29__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_29__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_29__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_29__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_29__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_29__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_29__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_30__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_30__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_30__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_30__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_30__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_30__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_30__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_30__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_30__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_30__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_30__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_30__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_30__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_30__ATTR1_VALID__SHIFT 0x19
+#define SPI_PS_INPUT_CNTL_31__OFFSET_MASK 0x3f
+#define SPI_PS_INPUT_CNTL_31__OFFSET__SHIFT 0x0
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL_MASK 0x300
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL__SHIFT 0x8
+#define SPI_PS_INPUT_CNTL_31__FLAT_SHADE_MASK 0x400
+#define SPI_PS_INPUT_CNTL_31__FLAT_SHADE__SHIFT 0xa
+#define SPI_PS_INPUT_CNTL_31__DUP_MASK 0x40000
+#define SPI_PS_INPUT_CNTL_31__DUP__SHIFT 0x12
+#define SPI_PS_INPUT_CNTL_31__FP16_INTERP_MODE_MASK 0x80000
+#define SPI_PS_INPUT_CNTL_31__FP16_INTERP_MODE__SHIFT 0x13
+#define SPI_PS_INPUT_CNTL_31__USE_DEFAULT_ATTR1_MASK 0x100000
+#define SPI_PS_INPUT_CNTL_31__USE_DEFAULT_ATTR1__SHIFT 0x14
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL_ATTR1_MASK 0x600000
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL_ATTR1__SHIFT 0x15
+#define SPI_PS_INPUT_CNTL_31__ATTR0_VALID_MASK 0x1000000
+#define SPI_PS_INPUT_CNTL_31__ATTR0_VALID__SHIFT 0x18
+#define SPI_PS_INPUT_CNTL_31__ATTR1_VALID_MASK 0x2000000
+#define SPI_PS_INPUT_CNTL_31__ATTR1_VALID__SHIFT 0x19
+#define SPI_VS_OUT_CONFIG__VS_EXPORT_COUNT_MASK 0x3e
+#define SPI_VS_OUT_CONFIG__VS_EXPORT_COUNT__SHIFT 0x1
+#define SPI_VS_OUT_CONFIG__VS_HALF_PACK_MASK 0x40
+#define SPI_VS_OUT_CONFIG__VS_HALF_PACK__SHIFT 0x6
+#define SPI_PS_INPUT_ENA__PERSP_SAMPLE_ENA_MASK 0x1
+#define SPI_PS_INPUT_ENA__PERSP_SAMPLE_ENA__SHIFT 0x0
+#define SPI_PS_INPUT_ENA__PERSP_CENTER_ENA_MASK 0x2
+#define SPI_PS_INPUT_ENA__PERSP_CENTER_ENA__SHIFT 0x1
+#define SPI_PS_INPUT_ENA__PERSP_CENTROID_ENA_MASK 0x4
+#define SPI_PS_INPUT_ENA__PERSP_CENTROID_ENA__SHIFT 0x2
+#define SPI_PS_INPUT_ENA__PERSP_PULL_MODEL_ENA_MASK 0x8
+#define SPI_PS_INPUT_ENA__PERSP_PULL_MODEL_ENA__SHIFT 0x3
+#define SPI_PS_INPUT_ENA__LINEAR_SAMPLE_ENA_MASK 0x10
+#define SPI_PS_INPUT_ENA__LINEAR_SAMPLE_ENA__SHIFT 0x4
+#define SPI_PS_INPUT_ENA__LINEAR_CENTER_ENA_MASK 0x20
+#define SPI_PS_INPUT_ENA__LINEAR_CENTER_ENA__SHIFT 0x5
+#define SPI_PS_INPUT_ENA__LINEAR_CENTROID_ENA_MASK 0x40
+#define SPI_PS_INPUT_ENA__LINEAR_CENTROID_ENA__SHIFT 0x6
+#define SPI_PS_INPUT_ENA__LINE_STIPPLE_TEX_ENA_MASK 0x80
+#define SPI_PS_INPUT_ENA__LINE_STIPPLE_TEX_ENA__SHIFT 0x7
+#define SPI_PS_INPUT_ENA__POS_X_FLOAT_ENA_MASK 0x100
+#define SPI_PS_INPUT_ENA__POS_X_FLOAT_ENA__SHIFT 0x8
+#define SPI_PS_INPUT_ENA__POS_Y_FLOAT_ENA_MASK 0x200
+#define SPI_PS_INPUT_ENA__POS_Y_FLOAT_ENA__SHIFT 0x9
+#define SPI_PS_INPUT_ENA__POS_Z_FLOAT_ENA_MASK 0x400
+#define SPI_PS_INPUT_ENA__POS_Z_FLOAT_ENA__SHIFT 0xa
+#define SPI_PS_INPUT_ENA__POS_W_FLOAT_ENA_MASK 0x800
+#define SPI_PS_INPUT_ENA__POS_W_FLOAT_ENA__SHIFT 0xb
+#define SPI_PS_INPUT_ENA__FRONT_FACE_ENA_MASK 0x1000
+#define SPI_PS_INPUT_ENA__FRONT_FACE_ENA__SHIFT 0xc
+#define SPI_PS_INPUT_ENA__ANCILLARY_ENA_MASK 0x2000
+#define SPI_PS_INPUT_ENA__ANCILLARY_ENA__SHIFT 0xd
+#define SPI_PS_INPUT_ENA__SAMPLE_COVERAGE_ENA_MASK 0x4000
+#define SPI_PS_INPUT_ENA__SAMPLE_COVERAGE_ENA__SHIFT 0xe
+#define SPI_PS_INPUT_ENA__POS_FIXED_PT_ENA_MASK 0x8000
+#define SPI_PS_INPUT_ENA__POS_FIXED_PT_ENA__SHIFT 0xf
+#define SPI_PS_INPUT_ADDR__PERSP_SAMPLE_ENA_MASK 0x1
+#define SPI_PS_INPUT_ADDR__PERSP_SAMPLE_ENA__SHIFT 0x0
+#define SPI_PS_INPUT_ADDR__PERSP_CENTER_ENA_MASK 0x2
+#define SPI_PS_INPUT_ADDR__PERSP_CENTER_ENA__SHIFT 0x1
+#define SPI_PS_INPUT_ADDR__PERSP_CENTROID_ENA_MASK 0x4
+#define SPI_PS_INPUT_ADDR__PERSP_CENTROID_ENA__SHIFT 0x2
+#define SPI_PS_INPUT_ADDR__PERSP_PULL_MODEL_ENA_MASK 0x8
+#define SPI_PS_INPUT_ADDR__PERSP_PULL_MODEL_ENA__SHIFT 0x3
+#define SPI_PS_INPUT_ADDR__LINEAR_SAMPLE_ENA_MASK 0x10
+#define SPI_PS_INPUT_ADDR__LINEAR_SAMPLE_ENA__SHIFT 0x4
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTER_ENA_MASK 0x20
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTER_ENA__SHIFT 0x5
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTROID_ENA_MASK 0x40
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTROID_ENA__SHIFT 0x6
+#define SPI_PS_INPUT_ADDR__LINE_STIPPLE_TEX_ENA_MASK 0x80
+#define SPI_PS_INPUT_ADDR__LINE_STIPPLE_TEX_ENA__SHIFT 0x7
+#define SPI_PS_INPUT_ADDR__POS_X_FLOAT_ENA_MASK 0x100
+#define SPI_PS_INPUT_ADDR__POS_X_FLOAT_ENA__SHIFT 0x8
+#define SPI_PS_INPUT_ADDR__POS_Y_FLOAT_ENA_MASK 0x200
+#define SPI_PS_INPUT_ADDR__POS_Y_FLOAT_ENA__SHIFT 0x9
+#define SPI_PS_INPUT_ADDR__POS_Z_FLOAT_ENA_MASK 0x400
+#define SPI_PS_INPUT_ADDR__POS_Z_FLOAT_ENA__SHIFT 0xa
+#define SPI_PS_INPUT_ADDR__POS_W_FLOAT_ENA_MASK 0x800
+#define SPI_PS_INPUT_ADDR__POS_W_FLOAT_ENA__SHIFT 0xb
+#define SPI_PS_INPUT_ADDR__FRONT_FACE_ENA_MASK 0x1000
+#define SPI_PS_INPUT_ADDR__FRONT_FACE_ENA__SHIFT 0xc
+#define SPI_PS_INPUT_ADDR__ANCILLARY_ENA_MASK 0x2000
+#define SPI_PS_INPUT_ADDR__ANCILLARY_ENA__SHIFT 0xd
+#define SPI_PS_INPUT_ADDR__SAMPLE_COVERAGE_ENA_MASK 0x4000
+#define SPI_PS_INPUT_ADDR__SAMPLE_COVERAGE_ENA__SHIFT 0xe
+#define SPI_PS_INPUT_ADDR__POS_FIXED_PT_ENA_MASK 0x8000
+#define SPI_PS_INPUT_ADDR__POS_FIXED_PT_ENA__SHIFT 0xf
+#define SPI_INTERP_CONTROL_0__FLAT_SHADE_ENA_MASK 0x1
+#define SPI_INTERP_CONTROL_0__FLAT_SHADE_ENA__SHIFT 0x0
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_ENA_MASK 0x2
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_ENA__SHIFT 0x1
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_X_MASK 0x1c
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_X__SHIFT 0x2
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Y_MASK 0xe0
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Y__SHIFT 0x5
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Z_MASK 0x700
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Z__SHIFT 0x8
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_W_MASK 0x3800
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_W__SHIFT 0xb
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_TOP_1_MASK 0x4000
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_TOP_1__SHIFT 0xe
+#define SPI_PS_IN_CONTROL__NUM_INTERP_MASK 0x3f
+#define SPI_PS_IN_CONTROL__NUM_INTERP__SHIFT 0x0
+#define SPI_PS_IN_CONTROL__PARAM_GEN_MASK 0x40
+#define SPI_PS_IN_CONTROL__PARAM_GEN__SHIFT 0x6
+#define SPI_PS_IN_CONTROL__BC_OPTIMIZE_DISABLE_MASK 0x4000
+#define SPI_PS_IN_CONTROL__BC_OPTIMIZE_DISABLE__SHIFT 0xe
+#define SPI_BARYC_CNTL__PERSP_CENTER_CNTL_MASK 0x1
+#define SPI_BARYC_CNTL__PERSP_CENTER_CNTL__SHIFT 0x0
+#define SPI_BARYC_CNTL__PERSP_CENTROID_CNTL_MASK 0x10
+#define SPI_BARYC_CNTL__PERSP_CENTROID_CNTL__SHIFT 0x4
+#define SPI_BARYC_CNTL__LINEAR_CENTER_CNTL_MASK 0x100
+#define SPI_BARYC_CNTL__LINEAR_CENTER_CNTL__SHIFT 0x8
+#define SPI_BARYC_CNTL__LINEAR_CENTROID_CNTL_MASK 0x1000
+#define SPI_BARYC_CNTL__LINEAR_CENTROID_CNTL__SHIFT 0xc
+#define SPI_BARYC_CNTL__POS_FLOAT_LOCATION_MASK 0x30000
+#define SPI_BARYC_CNTL__POS_FLOAT_LOCATION__SHIFT 0x10
+#define SPI_BARYC_CNTL__POS_FLOAT_ULC_MASK 0x100000
+#define SPI_BARYC_CNTL__POS_FLOAT_ULC__SHIFT 0x14
+#define SPI_BARYC_CNTL__FRONT_FACE_ALL_BITS_MASK 0x1000000
+#define SPI_BARYC_CNTL__FRONT_FACE_ALL_BITS__SHIFT 0x18
+#define SPI_TMPRING_SIZE__WAVES_MASK 0xfff
+#define SPI_TMPRING_SIZE__WAVES__SHIFT 0x0
+#define SPI_TMPRING_SIZE__WAVESIZE_MASK 0x1fff000
+#define SPI_TMPRING_SIZE__WAVESIZE__SHIFT 0xc
+#define SPI_SHADER_POS_FORMAT__POS0_EXPORT_FORMAT_MASK 0xf
+#define SPI_SHADER_POS_FORMAT__POS0_EXPORT_FORMAT__SHIFT 0x0
+#define SPI_SHADER_POS_FORMAT__POS1_EXPORT_FORMAT_MASK 0xf0
+#define SPI_SHADER_POS_FORMAT__POS1_EXPORT_FORMAT__SHIFT 0x4
+#define SPI_SHADER_POS_FORMAT__POS2_EXPORT_FORMAT_MASK 0xf00
+#define SPI_SHADER_POS_FORMAT__POS2_EXPORT_FORMAT__SHIFT 0x8
+#define SPI_SHADER_POS_FORMAT__POS3_EXPORT_FORMAT_MASK 0xf000
+#define SPI_SHADER_POS_FORMAT__POS3_EXPORT_FORMAT__SHIFT 0xc
+#define SPI_SHADER_Z_FORMAT__Z_EXPORT_FORMAT_MASK 0xf
+#define SPI_SHADER_Z_FORMAT__Z_EXPORT_FORMAT__SHIFT 0x0
+#define SPI_SHADER_COL_FORMAT__COL0_EXPORT_FORMAT_MASK 0xf
+#define SPI_SHADER_COL_FORMAT__COL0_EXPORT_FORMAT__SHIFT 0x0
+#define SPI_SHADER_COL_FORMAT__COL1_EXPORT_FORMAT_MASK 0xf0
+#define SPI_SHADER_COL_FORMAT__COL1_EXPORT_FORMAT__SHIFT 0x4
+#define SPI_SHADER_COL_FORMAT__COL2_EXPORT_FORMAT_MASK 0xf00
+#define SPI_SHADER_COL_FORMAT__COL2_EXPORT_FORMAT__SHIFT 0x8
+#define SPI_SHADER_COL_FORMAT__COL3_EXPORT_FORMAT_MASK 0xf000
+#define SPI_SHADER_COL_FORMAT__COL3_EXPORT_FORMAT__SHIFT 0xc
+#define SPI_SHADER_COL_FORMAT__COL4_EXPORT_FORMAT_MASK 0xf0000
+#define SPI_SHADER_COL_FORMAT__COL4_EXPORT_FORMAT__SHIFT 0x10
+#define SPI_SHADER_COL_FORMAT__COL5_EXPORT_FORMAT_MASK 0xf00000
+#define SPI_SHADER_COL_FORMAT__COL5_EXPORT_FORMAT__SHIFT 0x14
+#define SPI_SHADER_COL_FORMAT__COL6_EXPORT_FORMAT_MASK 0xf000000
+#define SPI_SHADER_COL_FORMAT__COL6_EXPORT_FORMAT__SHIFT 0x18
+#define SPI_SHADER_COL_FORMAT__COL7_EXPORT_FORMAT_MASK 0xf0000000
+#define SPI_SHADER_COL_FORMAT__COL7_EXPORT_FORMAT__SHIFT 0x1c
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS0_MASK 0x7
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS0__SHIFT 0x0
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS1_MASK 0x38
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS1__SHIFT 0x3
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS2_MASK 0x1c0
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS2__SHIFT 0x6
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS3_MASK 0xe00
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS3__SHIFT 0x9
+#define SPI_ARB_PRIORITY__TS0_DUR_MULT_MASK 0x3000
+#define SPI_ARB_PRIORITY__TS0_DUR_MULT__SHIFT 0xc
+#define SPI_ARB_PRIORITY__TS1_DUR_MULT_MASK 0xc000
+#define SPI_ARB_PRIORITY__TS1_DUR_MULT__SHIFT 0xe
+#define SPI_ARB_PRIORITY__TS2_DUR_MULT_MASK 0x30000
+#define SPI_ARB_PRIORITY__TS2_DUR_MULT__SHIFT 0x10
+#define SPI_ARB_PRIORITY__TS3_DUR_MULT_MASK 0xc0000
+#define SPI_ARB_PRIORITY__TS3_DUR_MULT__SHIFT 0x12
+#define SPI_ARB_CYCLES_0__TS0_DURATION_MASK 0xffff
+#define SPI_ARB_CYCLES_0__TS0_DURATION__SHIFT 0x0
+#define SPI_ARB_CYCLES_0__TS1_DURATION_MASK 0xffff0000
+#define SPI_ARB_CYCLES_0__TS1_DURATION__SHIFT 0x10
+#define SPI_ARB_CYCLES_1__TS2_DURATION_MASK 0xffff
+#define SPI_ARB_CYCLES_1__TS2_DURATION__SHIFT 0x0
+#define SPI_ARB_CYCLES_1__TS3_DURATION_MASK 0xffff0000
+#define SPI_ARB_CYCLES_1__TS3_DURATION__SHIFT 0x10
+#define SPI_CDBG_SYS_GFX__PS_EN_MASK 0x1
+#define SPI_CDBG_SYS_GFX__PS_EN__SHIFT 0x0
+#define SPI_CDBG_SYS_GFX__VS_EN_MASK 0x2
+#define SPI_CDBG_SYS_GFX__VS_EN__SHIFT 0x1
+#define SPI_CDBG_SYS_GFX__GS_EN_MASK 0x4
+#define SPI_CDBG_SYS_GFX__GS_EN__SHIFT 0x2
+#define SPI_CDBG_SYS_GFX__ES_EN_MASK 0x8
+#define SPI_CDBG_SYS_GFX__ES_EN__SHIFT 0x3
+#define SPI_CDBG_SYS_GFX__HS_EN_MASK 0x10
+#define SPI_CDBG_SYS_GFX__HS_EN__SHIFT 0x4
+#define SPI_CDBG_SYS_GFX__LS_EN_MASK 0x20
+#define SPI_CDBG_SYS_GFX__LS_EN__SHIFT 0x5
+#define SPI_CDBG_SYS_GFX__CS_EN_MASK 0x40
+#define SPI_CDBG_SYS_GFX__CS_EN__SHIFT 0x6
+#define SPI_CDBG_SYS_HP3D__PS_EN_MASK 0x1
+#define SPI_CDBG_SYS_HP3D__PS_EN__SHIFT 0x0
+#define SPI_CDBG_SYS_HP3D__VS_EN_MASK 0x2
+#define SPI_CDBG_SYS_HP3D__VS_EN__SHIFT 0x1
+#define SPI_CDBG_SYS_HP3D__GS_EN_MASK 0x4
+#define SPI_CDBG_SYS_HP3D__GS_EN__SHIFT 0x2
+#define SPI_CDBG_SYS_HP3D__ES_EN_MASK 0x8
+#define SPI_CDBG_SYS_HP3D__ES_EN__SHIFT 0x3
+#define SPI_CDBG_SYS_HP3D__HS_EN_MASK 0x10
+#define SPI_CDBG_SYS_HP3D__HS_EN__SHIFT 0x4
+#define SPI_CDBG_SYS_HP3D__LS_EN_MASK 0x20
+#define SPI_CDBG_SYS_HP3D__LS_EN__SHIFT 0x5
+#define SPI_CDBG_SYS_CS0__PIPE0_MASK 0xff
+#define SPI_CDBG_SYS_CS0__PIPE0__SHIFT 0x0
+#define SPI_CDBG_SYS_CS0__PIPE1_MASK 0xff00
+#define SPI_CDBG_SYS_CS0__PIPE1__SHIFT 0x8
+#define SPI_CDBG_SYS_CS0__PIPE2_MASK 0xff0000
+#define SPI_CDBG_SYS_CS0__PIPE2__SHIFT 0x10
+#define SPI_CDBG_SYS_CS0__PIPE3_MASK 0xff000000
+#define SPI_CDBG_SYS_CS0__PIPE3__SHIFT 0x18
+#define SPI_CDBG_SYS_CS1__PIPE0_MASK 0xff
+#define SPI_CDBG_SYS_CS1__PIPE0__SHIFT 0x0
+#define SPI_CDBG_SYS_CS1__PIPE1_MASK 0xff00
+#define SPI_CDBG_SYS_CS1__PIPE1__SHIFT 0x8
+#define SPI_CDBG_SYS_CS1__PIPE2_MASK 0xff0000
+#define SPI_CDBG_SYS_CS1__PIPE2__SHIFT 0x10
+#define SPI_CDBG_SYS_CS1__PIPE3_MASK 0xff000000
+#define SPI_CDBG_SYS_CS1__PIPE3__SHIFT 0x18
+#define SPI_WCL_PIPE_PERCENT_GFX__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_GFX__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_GFX__LS_GRP_VALUE_MASK 0xf80
+#define SPI_WCL_PIPE_PERCENT_GFX__LS_GRP_VALUE__SHIFT 0x7
+#define SPI_WCL_PIPE_PERCENT_GFX__HS_GRP_VALUE_MASK 0x1f000
+#define SPI_WCL_PIPE_PERCENT_GFX__HS_GRP_VALUE__SHIFT 0xc
+#define SPI_WCL_PIPE_PERCENT_GFX__ES_GRP_VALUE_MASK 0x3e0000
+#define SPI_WCL_PIPE_PERCENT_GFX__ES_GRP_VALUE__SHIFT 0x11
+#define SPI_WCL_PIPE_PERCENT_GFX__GS_GRP_VALUE_MASK 0x7c00000
+#define SPI_WCL_PIPE_PERCENT_GFX__GS_GRP_VALUE__SHIFT 0x16
+#define SPI_WCL_PIPE_PERCENT_HP3D__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_HP3D__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_HP3D__LS_GRP_VALUE_MASK 0xf80
+#define SPI_WCL_PIPE_PERCENT_HP3D__LS_GRP_VALUE__SHIFT 0x7
+#define SPI_WCL_PIPE_PERCENT_HP3D__HS_GRP_VALUE_MASK 0x1f000
+#define SPI_WCL_PIPE_PERCENT_HP3D__HS_GRP_VALUE__SHIFT 0xc
+#define SPI_WCL_PIPE_PERCENT_HP3D__ES_GRP_VALUE_MASK 0x3e0000
+#define SPI_WCL_PIPE_PERCENT_HP3D__ES_GRP_VALUE__SHIFT 0x11
+#define SPI_WCL_PIPE_PERCENT_HP3D__GS_GRP_VALUE_MASK 0x7c00000
+#define SPI_WCL_PIPE_PERCENT_HP3D__GS_GRP_VALUE__SHIFT 0x16
+#define SPI_WCL_PIPE_PERCENT_CS0__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS0__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS1__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS1__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS2__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS2__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS3__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS3__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS4__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS4__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS5__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS5__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS6__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS6__VALUE__SHIFT 0x0
+#define SPI_WCL_PIPE_PERCENT_CS7__VALUE_MASK 0x7f
+#define SPI_WCL_PIPE_PERCENT_CS7__VALUE__SHIFT 0x0
+#define SPI_GDBG_WAVE_CNTL__STALL_RA_MASK 0x1
+#define SPI_GDBG_WAVE_CNTL__STALL_RA__SHIFT 0x0
+#define SPI_GDBG_WAVE_CNTL__STALL_VMID_MASK 0x1fffe
+#define SPI_GDBG_WAVE_CNTL__STALL_VMID__SHIFT 0x1
+#define SPI_GDBG_TRAP_CONFIG__ME_SEL_MASK 0x3
+#define SPI_GDBG_TRAP_CONFIG__ME_SEL__SHIFT 0x0
+#define SPI_GDBG_TRAP_CONFIG__PIPE_SEL_MASK 0xc
+#define SPI_GDBG_TRAP_CONFIG__PIPE_SEL__SHIFT 0x2
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_SEL_MASK 0x70
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_SEL__SHIFT 0x4
+#define SPI_GDBG_TRAP_CONFIG__ME_MATCH_MASK 0x80
+#define SPI_GDBG_TRAP_CONFIG__ME_MATCH__SHIFT 0x7
+#define SPI_GDBG_TRAP_CONFIG__PIPE_MATCH_MASK 0x100
+#define SPI_GDBG_TRAP_CONFIG__PIPE_MATCH__SHIFT 0x8
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_MATCH_MASK 0x200
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_MATCH__SHIFT 0x9
+#define SPI_GDBG_TRAP_CONFIG__TRAP_EN_MASK 0x8000
+#define SPI_GDBG_TRAP_CONFIG__TRAP_EN__SHIFT 0xf
+#define SPI_GDBG_TRAP_CONFIG__VMID_SEL_MASK 0xffff0000
+#define SPI_GDBG_TRAP_CONFIG__VMID_SEL__SHIFT 0x10
+#define SPI_GDBG_TRAP_MASK__EXCP_EN_MASK 0x1ff
+#define SPI_GDBG_TRAP_MASK__EXCP_EN__SHIFT 0x0
+#define SPI_GDBG_TRAP_MASK__REPLACE_MASK 0x200
+#define SPI_GDBG_TRAP_MASK__REPLACE__SHIFT 0x9
+#define SPI_GDBG_TBA_LO__MEM_BASE_MASK 0xffffffff
+#define SPI_GDBG_TBA_LO__MEM_BASE__SHIFT 0x0
+#define SPI_GDBG_TBA_HI__MEM_BASE_MASK 0xff
+#define SPI_GDBG_TBA_HI__MEM_BASE__SHIFT 0x0
+#define SPI_GDBG_TMA_LO__MEM_BASE_MASK 0xffffffff
+#define SPI_GDBG_TMA_LO__MEM_BASE__SHIFT 0x0
+#define SPI_GDBG_TMA_HI__MEM_BASE_MASK 0xff
+#define SPI_GDBG_TMA_HI__MEM_BASE__SHIFT 0x0
+#define SPI_GDBG_TRAP_DATA0__DATA_MASK 0xffffffff
+#define SPI_GDBG_TRAP_DATA0__DATA__SHIFT 0x0
+#define SPI_GDBG_TRAP_DATA1__DATA_MASK 0xffffffff
+#define SPI_GDBG_TRAP_DATA1__DATA__SHIFT 0x0
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_MASK 0x1
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET__SHIFT 0x0
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_PER_VMID_MASK 0x2
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_PER_VMID__SHIFT 0x1
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_ALL_VMID_MASK 0x4
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_ALL_VMID__SHIFT 0x2
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_RESOURCE_MASK 0x8
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_RESOURCE__SHIFT 0x3
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_PRIORITY_MASK 0x10
+#define SPI_RESET_DEBUG__DISABLE_GFX_RESET_PRIORITY__SHIFT 0x4
+#define SPI_COMPUTE_QUEUE_RESET__RESET_MASK 0x1
+#define SPI_COMPUTE_QUEUE_RESET__RESET__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_0__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_0__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_0__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_0__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_0__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_0__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_0__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_0__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_0__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_0__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_1__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_1__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_1__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_1__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_1__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_1__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_1__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_1__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_1__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_1__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_2__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_2__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_2__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_2__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_2__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_2__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_2__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_2__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_2__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_2__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_3__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_3__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_3__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_3__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_3__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_3__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_3__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_3__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_3__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_3__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_4__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_4__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_4__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_4__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_4__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_4__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_4__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_4__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_4__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_4__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_5__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_5__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_5__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_5__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_5__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_5__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_5__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_5__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_5__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_5__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_6__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_6__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_6__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_6__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_6__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_6__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_6__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_6__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_6__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_6__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_7__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_7__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_7__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_7__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_7__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_7__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_7__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_7__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_7__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_7__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_8__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_8__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_8__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_8__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_8__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_8__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_8__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_8__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_8__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_8__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_9__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_9__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_9__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_9__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_9__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_9__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_9__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_9__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_9__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_9__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_10__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_10__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_10__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_10__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_10__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_10__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_10__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_10__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_10__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_10__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_11__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_11__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_11__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_11__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_11__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_11__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_11__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_11__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_11__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_11__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_12__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_12__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_12__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_12__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_12__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_12__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_12__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_12__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_12__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_12__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_13__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_13__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_13__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_13__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_13__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_13__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_13__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_13__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_13__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_13__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_14__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_14__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_14__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_14__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_14__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_14__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_14__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_14__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_14__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_14__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_CU_15__VGPR_MASK 0xf
+#define SPI_RESOURCE_RESERVE_CU_15__VGPR__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_CU_15__SGPR_MASK 0xf0
+#define SPI_RESOURCE_RESERVE_CU_15__SGPR__SHIFT 0x4
+#define SPI_RESOURCE_RESERVE_CU_15__LDS_MASK 0xf00
+#define SPI_RESOURCE_RESERVE_CU_15__LDS__SHIFT 0x8
+#define SPI_RESOURCE_RESERVE_CU_15__WAVES_MASK 0x7000
+#define SPI_RESOURCE_RESERVE_CU_15__WAVES__SHIFT 0xc
+#define SPI_RESOURCE_RESERVE_CU_15__BARRIERS_MASK 0x78000
+#define SPI_RESOURCE_RESERVE_CU_15__BARRIERS__SHIFT 0xf
+#define SPI_RESOURCE_RESERVE_EN_CU_0__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_0__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_0__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_0__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_0__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_0__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_0__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_0__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_1__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_1__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_1__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_1__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_1__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_1__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_1__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_1__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_2__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_2__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_2__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_2__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_2__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_2__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_2__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_2__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_3__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_3__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_3__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_3__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_3__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_3__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_3__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_3__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_4__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_4__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_4__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_4__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_4__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_4__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_4__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_4__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_5__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_5__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_5__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_5__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_5__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_5__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_5__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_5__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_6__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_6__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_6__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_6__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_6__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_6__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_6__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_6__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_7__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_7__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_7__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_7__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_7__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_7__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_7__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_7__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_8__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_8__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_8__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_8__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_8__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_8__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_8__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_8__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_9__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_9__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_9__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_9__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_9__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_9__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_9__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_9__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_10__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_10__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_10__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_10__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_10__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_10__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_10__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_10__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_11__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_11__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_11__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_11__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_11__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_11__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_11__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_11__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_12__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_12__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_12__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_12__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_12__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_12__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_12__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_12__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_13__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_13__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_13__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_13__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_13__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_13__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_13__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_13__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_14__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_14__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_14__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_14__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_14__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_14__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_14__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_14__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_RESOURCE_RESERVE_EN_CU_15__EN_MASK 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_15__EN__SHIFT 0x0
+#define SPI_RESOURCE_RESERVE_EN_CU_15__TYPE_MASK_MASK 0xfffe
+#define SPI_RESOURCE_RESERVE_EN_CU_15__TYPE_MASK__SHIFT 0x1
+#define SPI_RESOURCE_RESERVE_EN_CU_15__QUEUE_MASK_MASK 0xff0000
+#define SPI_RESOURCE_RESERVE_EN_CU_15__QUEUE_MASK__SHIFT 0x10
+#define SPI_RESOURCE_RESERVE_EN_CU_15__RESERVE_SPACE_ONLY_MASK 0x1000000
+#define SPI_RESOURCE_RESERVE_EN_CU_15__RESERVE_SPACE_ONLY__SHIFT 0x18
+#define SPI_COMPUTE_WF_CTX_SAVE__INITIATE_MASK 0x1
+#define SPI_COMPUTE_WF_CTX_SAVE__INITIATE__SHIFT 0x0
+#define SPI_COMPUTE_WF_CTX_SAVE__GDS_INTERRUPT_EN_MASK 0x2
+#define SPI_COMPUTE_WF_CTX_SAVE__GDS_INTERRUPT_EN__SHIFT 0x1
+#define SPI_COMPUTE_WF_CTX_SAVE__DONE_INTERRUPT_EN_MASK 0x4
+#define SPI_COMPUTE_WF_CTX_SAVE__DONE_INTERRUPT_EN__SHIFT 0x2
+#define SPI_COMPUTE_WF_CTX_SAVE__GDS_REQ_BUSY_MASK 0x40000000
+#define SPI_COMPUTE_WF_CTX_SAVE__GDS_REQ_BUSY__SHIFT 0x1e
+#define SPI_COMPUTE_WF_CTX_SAVE__SAVE_BUSY_MASK 0x80000000
+#define SPI_COMPUTE_WF_CTX_SAVE__SAVE_BUSY__SHIFT 0x1f
+#define SPI_PS_MAX_WAVE_ID__MAX_WAVE_ID_MASK 0xfff
+#define SPI_PS_MAX_WAVE_ID__MAX_WAVE_ID__SHIFT 0x0
+#define SPI_START_PHASE__VGPR_START_PHASE_MASK 0x3
+#define SPI_START_PHASE__VGPR_START_PHASE__SHIFT 0x0
+#define SPI_START_PHASE__SGPR_START_PHASE_MASK 0xc
+#define SPI_START_PHASE__SGPR_START_PHASE__SHIFT 0x2
+#define SPI_START_PHASE__WAVE_START_PHASE_MASK 0x30
+#define SPI_START_PHASE__WAVE_START_PHASE__SHIFT 0x4
+#define SPI_GFX_CNTL__RESET_COUNTS_MASK 0x1
+#define SPI_GFX_CNTL__RESET_COUNTS__SHIFT 0x0
+#define SPI_CONFIG_CNTL__GPR_WRITE_PRIORITY_MASK 0x1fffff
+#define SPI_CONFIG_CNTL__GPR_WRITE_PRIORITY__SHIFT 0x0
+#define SPI_CONFIG_CNTL__EXP_PRIORITY_ORDER_MASK 0xe00000
+#define SPI_CONFIG_CNTL__EXP_PRIORITY_ORDER__SHIFT 0x15
+#define SPI_CONFIG_CNTL__ENABLE_SQG_TOP_EVENTS_MASK 0x1000000
+#define SPI_CONFIG_CNTL__ENABLE_SQG_TOP_EVENTS__SHIFT 0x18
+#define SPI_CONFIG_CNTL__ENABLE_SQG_BOP_EVENTS_MASK 0x2000000
+#define SPI_CONFIG_CNTL__ENABLE_SQG_BOP_EVENTS__SHIFT 0x19
+#define SPI_CONFIG_CNTL__RSRC_MGMT_RESET_MASK 0x4000000
+#define SPI_CONFIG_CNTL__RSRC_MGMT_RESET__SHIFT 0x1a
+#define SPI_CONFIG_CNTL__TTRACE_STALL_ALL_MASK 0x8000000
+#define SPI_CONFIG_CNTL__TTRACE_STALL_ALL__SHIFT 0x1b
+#define SPI_DEBUG_CNTL__DEBUG_GRBM_OVERRIDE_MASK 0x1
+#define SPI_DEBUG_CNTL__DEBUG_GRBM_OVERRIDE__SHIFT 0x0
+#define SPI_DEBUG_CNTL__DEBUG_THREAD_TYPE_SEL_MASK 0xe
+#define SPI_DEBUG_CNTL__DEBUG_THREAD_TYPE_SEL__SHIFT 0x1
+#define SPI_DEBUG_CNTL__DEBUG_GROUP_SEL_MASK 0x3f0
+#define SPI_DEBUG_CNTL__DEBUG_GROUP_SEL__SHIFT 0x4
+#define SPI_DEBUG_CNTL__DEBUG_SIMD_SEL_MASK 0xfc00
+#define SPI_DEBUG_CNTL__DEBUG_SIMD_SEL__SHIFT 0xa
+#define SPI_DEBUG_CNTL__DEBUG_SH_SEL_MASK 0x10000
+#define SPI_DEBUG_CNTL__DEBUG_SH_SEL__SHIFT 0x10
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_0_MASK 0x20000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_0__SHIFT 0x11
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_1_MASK 0x40000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_1__SHIFT 0x12
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_2_MASK 0x80000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_2__SHIFT 0x13
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_3_MASK 0x100000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_3__SHIFT 0x14
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_4_MASK 0x200000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_4__SHIFT 0x15
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_5_MASK 0x400000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_5__SHIFT 0x16
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_6_MASK 0x800000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_6__SHIFT 0x17
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_7_MASK 0x1000000
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_7__SHIFT 0x18
+#define SPI_DEBUG_CNTL__DEBUG_PIPE_SEL_MASK 0xe000000
+#define SPI_DEBUG_CNTL__DEBUG_PIPE_SEL__SHIFT 0x19
+#define SPI_DEBUG_CNTL__DEBUG_REG_EN_MASK 0x80000000
+#define SPI_DEBUG_CNTL__DEBUG_REG_EN__SHIFT 0x1f
+#define SPI_DEBUG_READ__DATA_MASK 0xffffff
+#define SPI_DEBUG_READ__DATA__SHIFT 0x0
+#define SPI_DSM_CNTL__Sel_DSM_SPI_Irritator_data0_MASK 0x1
+#define SPI_DSM_CNTL__Sel_DSM_SPI_Irritator_data0__SHIFT 0x0
+#define SPI_DSM_CNTL__Sel_DSM_SPI_Irritator_data1_MASK 0x2
+#define SPI_DSM_CNTL__Sel_DSM_SPI_Irritator_data1__SHIFT 0x1
+#define SPI_DSM_CNTL__SPI_Enable_Single_Write_MASK 0x4
+#define SPI_DSM_CNTL__SPI_Enable_Single_Write__SHIFT 0x2
+#define SPI_DSM_CNTL__UNUSED_MASK 0xfffffff8
+#define SPI_DSM_CNTL__UNUSED__SHIFT 0x3
+#define SPI_EDC_CNT__SED_MASK 0xff
+#define SPI_EDC_CNT__SED__SHIFT 0x0
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define SPI_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define SPI_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define SPI_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define SPI_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL1_MASK 0xffc00
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL1__SHIFT 0xa
+#define SPI_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define SPI_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL1_MASK 0xffc00
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL1__SHIFT 0xa
+#define SPI_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define SPI_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL2_MASK 0x3ff
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL2__SHIFT 0x0
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL3_MASK 0xffc00
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL3__SHIFT 0xa
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL2_MASK 0x3ff
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL2__SHIFT 0x0
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL3_MASK 0xffc00
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL3__SHIFT 0xa
+#define SPI_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0xff
+#define SPI_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x0
+#define SPI_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0xff
+#define SPI_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x0
+#define SPI_PERFCOUNTER_BINS__BIN0_MIN_MASK 0xf
+#define SPI_PERFCOUNTER_BINS__BIN0_MIN__SHIFT 0x0
+#define SPI_PERFCOUNTER_BINS__BIN0_MAX_MASK 0xf0
+#define SPI_PERFCOUNTER_BINS__BIN0_MAX__SHIFT 0x4
+#define SPI_PERFCOUNTER_BINS__BIN1_MIN_MASK 0xf00
+#define SPI_PERFCOUNTER_BINS__BIN1_MIN__SHIFT 0x8
+#define SPI_PERFCOUNTER_BINS__BIN1_MAX_MASK 0xf000
+#define SPI_PERFCOUNTER_BINS__BIN1_MAX__SHIFT 0xc
+#define SPI_PERFCOUNTER_BINS__BIN2_MIN_MASK 0xf0000
+#define SPI_PERFCOUNTER_BINS__BIN2_MIN__SHIFT 0x10
+#define SPI_PERFCOUNTER_BINS__BIN2_MAX_MASK 0xf00000
+#define SPI_PERFCOUNTER_BINS__BIN2_MAX__SHIFT 0x14
+#define SPI_PERFCOUNTER_BINS__BIN3_MIN_MASK 0xf000000
+#define SPI_PERFCOUNTER_BINS__BIN3_MIN__SHIFT 0x18
+#define SPI_PERFCOUNTER_BINS__BIN3_MAX_MASK 0xf0000000
+#define SPI_PERFCOUNTER_BINS__BIN3_MAX__SHIFT 0x1c
+#define SPI_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SPI_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SPI_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SPI_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SPI_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SPI_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SPI_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SPI_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SPI_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SPI_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SPI_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SPI_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SPI_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SPI_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SPI_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SPI_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SPI_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SPI_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SPI_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SPI_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SPI_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SPI_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SPI_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SPI_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_MASK 0xf
+#define SPI_CONFIG_CNTL_1__VTX_DONE_DELAY__SHIFT 0x0
+#define SPI_CONFIG_CNTL_1__INTERP_ONE_PRIM_PER_ROW_MASK 0x10
+#define SPI_CONFIG_CNTL_1__INTERP_ONE_PRIM_PER_ROW__SHIFT 0x4
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_ENABLE_MASK 0x40
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_ENABLE__SHIFT 0x6
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_STRICT_MASK 0x80
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_STRICT__SHIFT 0x7
+#define SPI_CONFIG_CNTL_1__CRC_SIMD_ID_WADDR_DISABLE_MASK 0x100
+#define SPI_CONFIG_CNTL_1__CRC_SIMD_ID_WADDR_DISABLE__SHIFT 0x8
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_MODE_MASK 0x200
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_MODE__SHIFT 0x9
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_CNT_MASK 0x3c00
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_CNT__SHIFT 0xa
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_SIZE_MASK 0xffff0000
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_SIZE__SHIFT 0x10
+#define SPI_DEBUG_BUSY__LS_BUSY_MASK 0x1
+#define SPI_DEBUG_BUSY__LS_BUSY__SHIFT 0x0
+#define SPI_DEBUG_BUSY__HS_BUSY_MASK 0x2
+#define SPI_DEBUG_BUSY__HS_BUSY__SHIFT 0x1
+#define SPI_DEBUG_BUSY__ES_BUSY_MASK 0x4
+#define SPI_DEBUG_BUSY__ES_BUSY__SHIFT 0x2
+#define SPI_DEBUG_BUSY__GS_BUSY_MASK 0x8
+#define SPI_DEBUG_BUSY__GS_BUSY__SHIFT 0x3
+#define SPI_DEBUG_BUSY__VS_BUSY_MASK 0x10
+#define SPI_DEBUG_BUSY__VS_BUSY__SHIFT 0x4
+#define SPI_DEBUG_BUSY__PS0_BUSY_MASK 0x20
+#define SPI_DEBUG_BUSY__PS0_BUSY__SHIFT 0x5
+#define SPI_DEBUG_BUSY__PS1_BUSY_MASK 0x40
+#define SPI_DEBUG_BUSY__PS1_BUSY__SHIFT 0x6
+#define SPI_DEBUG_BUSY__CSG_BUSY_MASK 0x80
+#define SPI_DEBUG_BUSY__CSG_BUSY__SHIFT 0x7
+#define SPI_DEBUG_BUSY__CS0_BUSY_MASK 0x100
+#define SPI_DEBUG_BUSY__CS0_BUSY__SHIFT 0x8
+#define SPI_DEBUG_BUSY__CS1_BUSY_MASK 0x200
+#define SPI_DEBUG_BUSY__CS1_BUSY__SHIFT 0x9
+#define SPI_DEBUG_BUSY__CS2_BUSY_MASK 0x400
+#define SPI_DEBUG_BUSY__CS2_BUSY__SHIFT 0xa
+#define SPI_DEBUG_BUSY__CS3_BUSY_MASK 0x800
+#define SPI_DEBUG_BUSY__CS3_BUSY__SHIFT 0xb
+#define SPI_DEBUG_BUSY__CS4_BUSY_MASK 0x1000
+#define SPI_DEBUG_BUSY__CS4_BUSY__SHIFT 0xc
+#define SPI_DEBUG_BUSY__CS5_BUSY_MASK 0x2000
+#define SPI_DEBUG_BUSY__CS5_BUSY__SHIFT 0xd
+#define SPI_DEBUG_BUSY__CS6_BUSY_MASK 0x4000
+#define SPI_DEBUG_BUSY__CS6_BUSY__SHIFT 0xe
+#define SPI_DEBUG_BUSY__CS7_BUSY_MASK 0x8000
+#define SPI_DEBUG_BUSY__CS7_BUSY__SHIFT 0xf
+#define SPI_DEBUG_BUSY__LDS_WR_CTL0_BUSY_MASK 0x10000
+#define SPI_DEBUG_BUSY__LDS_WR_CTL0_BUSY__SHIFT 0x10
+#define SPI_DEBUG_BUSY__LDS_WR_CTL1_BUSY_MASK 0x20000
+#define SPI_DEBUG_BUSY__LDS_WR_CTL1_BUSY__SHIFT 0x11
+#define SPI_DEBUG_BUSY__RSRC_ALLOC0_BUSY_MASK 0x40000
+#define SPI_DEBUG_BUSY__RSRC_ALLOC0_BUSY__SHIFT 0x12
+#define SPI_DEBUG_BUSY__RSRC_ALLOC1_BUSY_MASK 0x80000
+#define SPI_DEBUG_BUSY__RSRC_ALLOC1_BUSY__SHIFT 0x13
+#define SPI_DEBUG_BUSY__PC_DEALLOC_BUSY_MASK 0x100000
+#define SPI_DEBUG_BUSY__PC_DEALLOC_BUSY__SHIFT 0x14
+#define SPI_DEBUG_BUSY__EVENT_CLCTR_BUSY_MASK 0x200000
+#define SPI_DEBUG_BUSY__EVENT_CLCTR_BUSY__SHIFT 0x15
+#define SPI_DEBUG_BUSY__GRBM_BUSY_MASK 0x400000
+#define SPI_DEBUG_BUSY__GRBM_BUSY__SHIFT 0x16
+#define SPI_DEBUG_BUSY__SPIS_BUSY_MASK 0x800000
+#define SPI_DEBUG_BUSY__SPIS_BUSY__SHIFT 0x17
+#define SPI_CONFIG_CNTL_2__CONTEXT_SAVE_WAIT_GDS_REQUEST_CYCLE_OVHD_MASK 0xf
+#define SPI_CONFIG_CNTL_2__CONTEXT_SAVE_WAIT_GDS_REQUEST_CYCLE_OVHD__SHIFT 0x0
+#define SPI_CONFIG_CNTL_2__CONTEXT_SAVE_WAIT_GDS_GRANT_CYCLE_OVHD_MASK 0xf0
+#define SPI_CONFIG_CNTL_2__CONTEXT_SAVE_WAIT_GDS_GRANT_CYCLE_OVHD__SHIFT 0x4
+#define CGTS_SM_CTRL_REG__ON_SEQ_DELAY_MASK 0xf
+#define CGTS_SM_CTRL_REG__ON_SEQ_DELAY__SHIFT 0x0
+#define CGTS_SM_CTRL_REG__OFF_SEQ_DELAY_MASK 0xff0
+#define CGTS_SM_CTRL_REG__OFF_SEQ_DELAY__SHIFT 0x4
+#define CGTS_SM_CTRL_REG__MGCG_ENABLED_MASK 0x1000
+#define CGTS_SM_CTRL_REG__MGCG_ENABLED__SHIFT 0xc
+#define CGTS_SM_CTRL_REG__BASE_MODE_MASK 0x10000
+#define CGTS_SM_CTRL_REG__BASE_MODE__SHIFT 0x10
+#define CGTS_SM_CTRL_REG__SM_MODE_MASK 0xe0000
+#define CGTS_SM_CTRL_REG__SM_MODE__SHIFT 0x11
+#define CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK 0x100000
+#define CGTS_SM_CTRL_REG__SM_MODE_ENABLE__SHIFT 0x14
+#define CGTS_SM_CTRL_REG__OVERRIDE_MASK 0x200000
+#define CGTS_SM_CTRL_REG__OVERRIDE__SHIFT 0x15
+#define CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK 0x400000
+#define CGTS_SM_CTRL_REG__LS_OVERRIDE__SHIFT 0x16
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK 0x800000
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN__SHIFT 0x17
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_MASK 0xff000000
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT 0x18
+#define CGTS_RD_CTRL_REG__ROW_MUX_SEL_MASK 0x1f
+#define CGTS_RD_CTRL_REG__ROW_MUX_SEL__SHIFT 0x0
+#define CGTS_RD_CTRL_REG__REG_MUX_SEL_MASK 0x1f00
+#define CGTS_RD_CTRL_REG__REG_MUX_SEL__SHIFT 0x8
+#define CGTS_RD_REG__READ_DATA_MASK 0x3fff
+#define CGTS_RD_REG__READ_DATA__SHIFT 0x0
+#define CGTS_TCC_DISABLE__TCC_DISABLE_MASK 0xffff0000
+#define CGTS_TCC_DISABLE__TCC_DISABLE__SHIFT 0x10
+#define CGTS_USER_TCC_DISABLE__TCC_DISABLE_MASK 0xffff0000
+#define CGTS_USER_TCC_DISABLE__TCC_DISABLE__SHIFT 0x10
+#define CGTS_CU0_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU0_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU0_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU0_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU0_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU0_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU0_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU0_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU0_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU0_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU0_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU0_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU0_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU0_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU0_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU0_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU0_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU0_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU0_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU0_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU0_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU0_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU0_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_MASK 0x7f0000
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC__SHIFT 0x10
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_OVERRIDE_MASK 0x800000
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_OVERRIDE__SHIFT 0x17
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU0_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU0_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU0_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU0_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU0_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU0_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU0_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU0_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU0_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU0_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU0_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU0_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU0_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU0_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU0_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU0_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU0_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU0_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU0_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU0_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU0_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU0_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU0_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU1_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU1_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU1_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU1_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU1_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU1_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU1_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU1_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU1_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU1_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU1_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU1_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU1_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU1_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU1_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU1_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU1_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU1_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU1_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU1_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU1_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU1_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU1_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU1_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU1_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU1_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU1_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU1_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU1_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU1_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU1_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU1_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU1_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU1_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU1_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU1_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU1_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU1_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU1_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU1_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU1_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU1_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU1_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU1_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU1_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU1_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU1_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU1_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU1_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU1_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU1_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU1_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU1_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU1_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU2_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU2_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU2_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU2_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU2_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU2_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU2_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU2_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU2_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU2_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU2_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU2_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU2_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU2_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU2_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU2_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU2_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU2_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU2_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU2_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU2_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU2_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU2_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU2_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU2_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU2_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU2_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU2_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU2_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU2_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU2_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU2_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU2_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU2_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU2_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU2_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU2_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU2_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU2_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU2_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU2_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU2_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU2_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU2_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU2_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU2_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU2_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU2_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU2_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU2_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU2_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU2_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU2_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU2_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU3_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU3_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU3_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU3_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU3_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU3_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU3_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU3_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU3_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU3_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU3_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU3_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU3_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU3_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU3_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU3_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU3_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU3_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU3_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU3_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU3_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU3_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU3_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU3_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU3_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU3_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU3_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU3_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU3_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU3_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU3_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU3_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU3_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU3_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU3_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU3_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU3_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU3_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU3_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU3_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU3_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU3_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU3_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU3_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU3_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU3_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU3_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU3_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU3_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU3_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU3_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU3_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU3_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU3_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU4_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU4_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU4_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU4_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU4_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU4_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU4_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU4_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU4_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU4_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU4_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU4_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU4_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU4_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU4_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU4_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU4_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU4_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU4_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU4_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU4_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU4_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU4_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_MASK 0x7f0000
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC__SHIFT 0x10
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_OVERRIDE_MASK 0x800000
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_OVERRIDE__SHIFT 0x17
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU4_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU4_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU4_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU4_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU4_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU4_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU4_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU4_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU4_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU4_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU4_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU4_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU4_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU4_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU4_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU4_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU4_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU4_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU4_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU4_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU4_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU4_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU4_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU5_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU5_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU5_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU5_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU5_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU5_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU5_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU5_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU5_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU5_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU5_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU5_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU5_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU5_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU5_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU5_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU5_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU5_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU5_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU5_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU5_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU5_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU5_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU5_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU5_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU5_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU5_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU5_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU5_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU5_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU5_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU5_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU5_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU5_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU5_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU5_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU5_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU5_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU5_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU5_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU5_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU5_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU5_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU5_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU5_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU5_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU5_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU5_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU5_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU5_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU5_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU5_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU5_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU5_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU6_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU6_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU6_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU6_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU6_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU6_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU6_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU6_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU6_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU6_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU6_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU6_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU6_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU6_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU6_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU6_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU6_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU6_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU6_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU6_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU6_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU6_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU6_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU6_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU6_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU6_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU6_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU6_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU6_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU6_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU6_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU6_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU6_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU6_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU6_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU6_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU6_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU6_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU6_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU6_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU6_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU6_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU6_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU6_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU6_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU6_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU6_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU6_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU6_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU6_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU6_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU6_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU6_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU6_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU7_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU7_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU7_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU7_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU7_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU7_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU7_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU7_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU7_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU7_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU7_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU7_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU7_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU7_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU7_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU7_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU7_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU7_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU7_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU7_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU7_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU7_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU7_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU7_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU7_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU7_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU7_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU7_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU7_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU7_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU7_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU7_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU7_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU7_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU7_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU7_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU7_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU7_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU7_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU7_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU7_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU7_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU7_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU7_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU7_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU7_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU7_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU7_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU7_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU7_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU7_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU7_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU7_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU7_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU8_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU8_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU8_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU8_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU8_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU8_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU8_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU8_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU8_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU8_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU8_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU8_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU8_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU8_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU8_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU8_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU8_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU8_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU8_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU8_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU8_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU8_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU8_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_MASK 0x7f0000
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC__SHIFT 0x10
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_OVERRIDE_MASK 0x800000
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_OVERRIDE__SHIFT 0x17
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU8_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU8_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU8_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU8_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU8_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU8_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU8_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU8_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU8_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU8_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU8_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU8_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU8_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU8_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU8_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU8_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU8_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU8_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU8_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU8_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU8_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU8_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU8_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU9_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU9_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU9_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU9_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU9_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU9_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU9_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU9_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU9_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU9_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU9_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU9_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU9_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU9_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU9_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU9_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU9_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU9_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU9_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU9_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU9_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU9_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU9_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU9_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU9_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU9_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU9_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU9_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU9_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU9_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU9_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU9_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU9_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU9_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU9_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU9_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU9_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU9_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU9_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU9_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU9_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU9_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU9_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU9_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU9_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU9_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU9_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU9_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU9_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU9_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU9_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU9_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU9_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU9_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU10_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU10_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU10_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU10_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU10_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU10_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU10_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU10_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU10_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU10_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU10_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU10_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU10_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU10_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU10_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU10_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU10_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU10_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU10_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU10_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU10_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU10_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU10_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU10_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU10_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU10_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU10_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU10_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU10_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU10_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU10_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU10_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU10_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU10_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU10_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU10_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU10_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU10_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU10_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU10_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU10_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU10_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU10_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU10_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU10_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU10_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU10_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU10_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU10_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU10_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU10_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU10_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU10_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU10_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU11_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU11_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU11_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU11_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU11_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU11_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU11_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU11_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU11_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU11_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU11_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU11_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU11_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU11_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU11_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU11_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU11_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU11_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU11_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU11_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU11_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU11_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU11_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU11_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU11_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU11_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU11_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU11_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU11_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU11_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU11_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU11_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU11_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU11_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU11_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU11_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU11_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU11_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU11_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU11_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU11_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU11_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU11_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU11_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU11_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU11_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU11_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU11_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU11_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU11_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU11_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU11_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU11_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU11_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU12_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU12_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU12_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU12_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU12_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU12_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU12_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU12_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU12_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU12_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU12_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU12_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU12_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU12_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU12_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU12_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU12_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU12_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU12_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU12_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU12_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU12_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU12_TA_SQC_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_MASK 0x7f0000
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC__SHIFT 0x10
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_OVERRIDE_MASK 0x800000
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_OVERRIDE__SHIFT 0x17
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU12_TA_SQC_CTRL_REG__SQC_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU12_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU12_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU12_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU12_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU12_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU12_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU12_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU12_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU12_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU12_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU12_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU12_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU12_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU12_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU12_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU12_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU12_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU12_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU12_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU12_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU12_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU12_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU13_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU13_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU13_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU13_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU13_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU13_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU13_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU13_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU13_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU13_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU13_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU13_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU13_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU13_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU13_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU13_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU13_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU13_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU13_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU13_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU13_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU13_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU13_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU13_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU13_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU13_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU13_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU13_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU13_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU13_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU13_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU13_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU13_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU13_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU13_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU13_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU13_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU13_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU13_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU13_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU13_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU13_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU13_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU13_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU13_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU13_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU13_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU13_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU13_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU13_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU13_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU13_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU13_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU13_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU14_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU14_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU14_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU14_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU14_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU14_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU14_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU14_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU14_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU14_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU14_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU14_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU14_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU14_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU14_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU14_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU14_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU14_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU14_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU14_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU14_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU14_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU14_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU14_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU14_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU14_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU14_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU14_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU14_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU14_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU14_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU14_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU14_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU14_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU14_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU14_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU14_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU14_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU14_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU14_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU14_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU14_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU14_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU14_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU14_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU14_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU14_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU14_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU14_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU14_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU14_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU14_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU14_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU14_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU15_SP0_CTRL_REG__SP00_MASK 0x7f
+#define CGTS_CU15_SP0_CTRL_REG__SP00__SHIFT 0x0
+#define CGTS_CU15_SP0_CTRL_REG__SP00_OVERRIDE_MASK 0x80
+#define CGTS_CU15_SP0_CTRL_REG__SP00_OVERRIDE__SHIFT 0x7
+#define CGTS_CU15_SP0_CTRL_REG__SP00_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU15_SP0_CTRL_REG__SP00_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU15_SP0_CTRL_REG__SP00_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU15_SP0_CTRL_REG__SP00_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU15_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU15_SP0_CTRL_REG__SP00_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU15_SP0_CTRL_REG__SP01_MASK 0x7f0000
+#define CGTS_CU15_SP0_CTRL_REG__SP01__SHIFT 0x10
+#define CGTS_CU15_SP0_CTRL_REG__SP01_OVERRIDE_MASK 0x800000
+#define CGTS_CU15_SP0_CTRL_REG__SP01_OVERRIDE__SHIFT 0x17
+#define CGTS_CU15_SP0_CTRL_REG__SP01_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU15_SP0_CTRL_REG__SP01_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU15_SP0_CTRL_REG__SP01_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU15_SP0_CTRL_REG__SP01_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU15_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU15_SP0_CTRL_REG__SP01_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_MASK 0x7f
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS__SHIFT 0x0
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_OVERRIDE_MASK 0x80
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_OVERRIDE__SHIFT 0x7
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU15_LDS_SQ_CTRL_REG__LDS_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_MASK 0x7f0000
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ__SHIFT 0x10
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_OVERRIDE_MASK 0x800000
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_OVERRIDE__SHIFT 0x17
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU15_LDS_SQ_CTRL_REG__SQ_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU15_TA_CTRL_REG__TA_MASK 0x7f
+#define CGTS_CU15_TA_CTRL_REG__TA__SHIFT 0x0
+#define CGTS_CU15_TA_CTRL_REG__TA_OVERRIDE_MASK 0x80
+#define CGTS_CU15_TA_CTRL_REG__TA_OVERRIDE__SHIFT 0x7
+#define CGTS_CU15_TA_CTRL_REG__TA_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU15_TA_CTRL_REG__TA_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU15_TA_CTRL_REG__TA_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU15_TA_CTRL_REG__TA_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU15_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU15_TA_CTRL_REG__TA_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU15_SP1_CTRL_REG__SP10_MASK 0x7f
+#define CGTS_CU15_SP1_CTRL_REG__SP10__SHIFT 0x0
+#define CGTS_CU15_SP1_CTRL_REG__SP10_OVERRIDE_MASK 0x80
+#define CGTS_CU15_SP1_CTRL_REG__SP10_OVERRIDE__SHIFT 0x7
+#define CGTS_CU15_SP1_CTRL_REG__SP10_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU15_SP1_CTRL_REG__SP10_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU15_SP1_CTRL_REG__SP10_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU15_SP1_CTRL_REG__SP10_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU15_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU15_SP1_CTRL_REG__SP10_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU15_SP1_CTRL_REG__SP11_MASK 0x7f0000
+#define CGTS_CU15_SP1_CTRL_REG__SP11__SHIFT 0x10
+#define CGTS_CU15_SP1_CTRL_REG__SP11_OVERRIDE_MASK 0x800000
+#define CGTS_CU15_SP1_CTRL_REG__SP11_OVERRIDE__SHIFT 0x17
+#define CGTS_CU15_SP1_CTRL_REG__SP11_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU15_SP1_CTRL_REG__SP11_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU15_SP1_CTRL_REG__SP11_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU15_SP1_CTRL_REG__SP11_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU15_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU15_SP1_CTRL_REG__SP11_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_MASK 0x7f
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD__SHIFT 0x0
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_OVERRIDE_MASK 0x80
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_OVERRIDE__SHIFT 0x7
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE_MASK 0x300
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_BUSY_OVERRIDE__SHIFT 0x8
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_LS_OVERRIDE_MASK 0x400
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_LS_OVERRIDE__SHIFT 0xa
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE_MASK 0x800
+#define CGTS_CU15_TD_TCP_CTRL_REG__TD_SIMDBUSY_OVERRIDE__SHIFT 0xb
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_MASK 0x7f0000
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP__SHIFT 0x10
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_OVERRIDE_MASK 0x800000
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_OVERRIDE__SHIFT 0x17
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE_MASK 0x3000000
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_BUSY_OVERRIDE__SHIFT 0x18
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE_MASK 0x4000000
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_LS_OVERRIDE__SHIFT 0x1a
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE_MASK 0x8000000
+#define CGTS_CU15_TD_TCP_CTRL_REG__TCP_SIMDBUSY_OVERRIDE__SHIFT 0x1b
+#define CGTT_SPI_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_SPI_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_SPI_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SPI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OFF_HYST_MASK 0xfc0000
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OFF_HYST__SHIFT 0x12
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OVERRIDE_MASK 0x1000000
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OVERRIDE__SHIFT 0x18
+#define CGTT_SPI_CLK_CTRL__ALL_CLK_ON_OVERRIDE_MASK 0x4000000
+#define CGTT_SPI_CLK_CTRL__ALL_CLK_ON_OVERRIDE__SHIFT 0x1a
+#define CGTT_SPI_CLK_CTRL__GRP3_OVERRIDE_MASK 0x8000000
+#define CGTT_SPI_CLK_CTRL__GRP3_OVERRIDE__SHIFT 0x1b
+#define CGTT_SPI_CLK_CTRL__GRP2_OVERRIDE_MASK 0x10000000
+#define CGTT_SPI_CLK_CTRL__GRP2_OVERRIDE__SHIFT 0x1c
+#define CGTT_SPI_CLK_CTRL__GRP1_OVERRIDE_MASK 0x20000000
+#define CGTT_SPI_CLK_CTRL__GRP1_OVERRIDE__SHIFT 0x1d
+#define CGTT_SPI_CLK_CTRL__GRP0_OVERRIDE_MASK 0x40000000
+#define CGTT_SPI_CLK_CTRL__GRP0_OVERRIDE__SHIFT 0x1e
+#define CGTT_SPI_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_SPI_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define CGTT_PC_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_PC_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_PC_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_PC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OFF_HYST_MASK 0xfc0000
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OFF_HYST__SHIFT 0x12
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OVERRIDE_MASK 0x1000000
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OVERRIDE__SHIFT 0x18
+#define CGTT_PC_CLK_CTRL__BACK_CLK_ON_OVERRIDE_MASK 0x2000000
+#define CGTT_PC_CLK_CTRL__BACK_CLK_ON_OVERRIDE__SHIFT 0x19
+#define CGTT_PC_CLK_CTRL__FRONT_CLK_ON_OVERRIDE_MASK 0x4000000
+#define CGTT_PC_CLK_CTRL__FRONT_CLK_ON_OVERRIDE__SHIFT 0x1a
+#define CGTT_PC_CLK_CTRL__CORE3_OVERRIDE_MASK 0x8000000
+#define CGTT_PC_CLK_CTRL__CORE3_OVERRIDE__SHIFT 0x1b
+#define CGTT_PC_CLK_CTRL__CORE2_OVERRIDE_MASK 0x10000000
+#define CGTT_PC_CLK_CTRL__CORE2_OVERRIDE__SHIFT 0x1c
+#define CGTT_PC_CLK_CTRL__CORE1_OVERRIDE_MASK 0x20000000
+#define CGTT_PC_CLK_CTRL__CORE1_OVERRIDE__SHIFT 0x1d
+#define CGTT_PC_CLK_CTRL__CORE0_OVERRIDE_MASK 0x40000000
+#define CGTT_PC_CLK_CTRL__CORE0_OVERRIDE__SHIFT 0x1e
+#define CGTT_PC_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_PC_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define CGTT_BCI_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_BCI_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_BCI_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_BCI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_BCI_CLK_CTRL__RESERVED_MASK 0xfff000
+#define CGTT_BCI_CLK_CTRL__RESERVED__SHIFT 0xc
+#define CGTT_BCI_CLK_CTRL__CORE6_OVERRIDE_MASK 0x1000000
+#define CGTT_BCI_CLK_CTRL__CORE6_OVERRIDE__SHIFT 0x18
+#define CGTT_BCI_CLK_CTRL__CORE5_OVERRIDE_MASK 0x2000000
+#define CGTT_BCI_CLK_CTRL__CORE5_OVERRIDE__SHIFT 0x19
+#define CGTT_BCI_CLK_CTRL__CORE4_OVERRIDE_MASK 0x4000000
+#define CGTT_BCI_CLK_CTRL__CORE4_OVERRIDE__SHIFT 0x1a
+#define CGTT_BCI_CLK_CTRL__CORE3_OVERRIDE_MASK 0x8000000
+#define CGTT_BCI_CLK_CTRL__CORE3_OVERRIDE__SHIFT 0x1b
+#define CGTT_BCI_CLK_CTRL__CORE2_OVERRIDE_MASK 0x10000000
+#define CGTT_BCI_CLK_CTRL__CORE2_OVERRIDE__SHIFT 0x1c
+#define CGTT_BCI_CLK_CTRL__CORE1_OVERRIDE_MASK 0x20000000
+#define CGTT_BCI_CLK_CTRL__CORE1_OVERRIDE__SHIFT 0x1d
+#define CGTT_BCI_CLK_CTRL__CORE0_OVERRIDE_MASK 0x40000000
+#define CGTT_BCI_CLK_CTRL__CORE0_OVERRIDE__SHIFT 0x1e
+#define CGTT_BCI_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_BCI_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define SPI_WF_LIFETIME_CNTL__SAMPLE_PERIOD_MASK 0xf
+#define SPI_WF_LIFETIME_CNTL__SAMPLE_PERIOD__SHIFT 0x0
+#define SPI_WF_LIFETIME_CNTL__EN_MASK 0x10
+#define SPI_WF_LIFETIME_CNTL__EN__SHIFT 0x4
+#define SPI_WF_LIFETIME_LIMIT_0__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_0__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_0__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_0__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_1__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_1__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_1__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_1__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_2__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_2__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_2__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_2__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_3__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_3__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_3__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_3__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_4__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_4__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_4__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_4__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_5__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_5__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_5__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_5__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_6__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_6__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_6__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_6__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_7__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_7__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_7__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_7__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_8__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_8__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_8__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_8__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_LIMIT_9__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_LIMIT_9__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_LIMIT_9__EN_WARN_MASK 0x80000000
+#define SPI_WF_LIFETIME_LIMIT_9__EN_WARN__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_0__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_0__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_0__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_0__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_1__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_1__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_1__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_1__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_2__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_2__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_2__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_2__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_3__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_3__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_3__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_3__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_4__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_4__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_4__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_4__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_5__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_5__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_5__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_5__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_6__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_6__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_6__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_6__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_7__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_7__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_7__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_7__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_8__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_8__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_8__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_8__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_9__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_9__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_9__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_9__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_10__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_10__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_10__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_10__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_11__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_11__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_11__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_11__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_12__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_12__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_12__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_12__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_13__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_13__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_13__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_13__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_14__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_14__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_14__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_14__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_15__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_15__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_15__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_15__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_16__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_16__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_16__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_16__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_17__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_17__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_17__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_17__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_18__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_18__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_18__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_18__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_19__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_19__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_19__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_19__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_STATUS_20__MAX_CNT_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_STATUS_20__MAX_CNT__SHIFT 0x0
+#define SPI_WF_LIFETIME_STATUS_20__INT_SENT_MASK 0x80000000
+#define SPI_WF_LIFETIME_STATUS_20__INT_SENT__SHIFT 0x1f
+#define SPI_WF_LIFETIME_DEBUG__START_VALUE_MASK 0x7fffffff
+#define SPI_WF_LIFETIME_DEBUG__START_VALUE__SHIFT 0x0
+#define SPI_WF_LIFETIME_DEBUG__OVERRIDE_EN_MASK 0x80000000
+#define SPI_WF_LIFETIME_DEBUG__OVERRIDE_EN__SHIFT 0x1f
+#define SPI_SLAVE_DEBUG_BUSY__LS_VTX_BUSY_MASK 0x1
+#define SPI_SLAVE_DEBUG_BUSY__LS_VTX_BUSY__SHIFT 0x0
+#define SPI_SLAVE_DEBUG_BUSY__HS_VTX_BUSY_MASK 0x2
+#define SPI_SLAVE_DEBUG_BUSY__HS_VTX_BUSY__SHIFT 0x1
+#define SPI_SLAVE_DEBUG_BUSY__ES_VTX_BUSY_MASK 0x4
+#define SPI_SLAVE_DEBUG_BUSY__ES_VTX_BUSY__SHIFT 0x2
+#define SPI_SLAVE_DEBUG_BUSY__GS_VTX_BUSY_MASK 0x8
+#define SPI_SLAVE_DEBUG_BUSY__GS_VTX_BUSY__SHIFT 0x3
+#define SPI_SLAVE_DEBUG_BUSY__VS_VTX_BUSY_MASK 0x10
+#define SPI_SLAVE_DEBUG_BUSY__VS_VTX_BUSY__SHIFT 0x4
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC00_BUSY_MASK 0x20
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC00_BUSY__SHIFT 0x5
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC01_BUSY_MASK 0x40
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC01_BUSY__SHIFT 0x6
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC10_BUSY_MASK 0x80
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC10_BUSY__SHIFT 0x7
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC11_BUSY_MASK 0x100
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC11_BUSY__SHIFT 0x8
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC00_BUSY_MASK 0x200
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC00_BUSY__SHIFT 0x9
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC01_BUSY_MASK 0x400
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC01_BUSY__SHIFT 0xa
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC02_BUSY_MASK 0x800
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC02_BUSY__SHIFT 0xb
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC03_BUSY_MASK 0x1000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC03_BUSY__SHIFT 0xc
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC10_BUSY_MASK 0x2000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC10_BUSY__SHIFT 0xd
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC11_BUSY_MASK 0x4000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC11_BUSY__SHIFT 0xe
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC12_BUSY_MASK 0x8000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC12_BUSY__SHIFT 0xf
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC13_BUSY_MASK 0x10000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC13_BUSY__SHIFT 0x10
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER0_BUSY_MASK 0x20000
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER0_BUSY__SHIFT 0x11
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER1_BUSY_MASK 0x40000
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER1_BUSY__SHIFT 0x12
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC0_BUSY_MASK 0x80000
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC0_BUSY__SHIFT 0x13
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC1_BUSY_MASK 0x100000
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC1_BUSY__SHIFT 0x14
+#define SPI_SLAVE_DEBUG_BUSY__EVENT_CNTL_BUSY_MASK 0x200000
+#define SPI_SLAVE_DEBUG_BUSY__EVENT_CNTL_BUSY__SHIFT 0x15
+#define SPI_SLAVE_DEBUG_BUSY__SAVE_CTX_BUSY_MASK 0x400000
+#define SPI_SLAVE_DEBUG_BUSY__SAVE_CTX_BUSY__SHIFT 0x16
+#define SPI_LB_CTR_CTRL__LOAD_MASK 0x1
+#define SPI_LB_CTR_CTRL__LOAD__SHIFT 0x0
+#define SPI_LB_CU_MASK__CU_MASK_MASK 0xffff
+#define SPI_LB_CU_MASK__CU_MASK__SHIFT 0x0
+#define SPI_LB_DATA_REG__CNT_DATA_MASK 0xffffffff
+#define SPI_LB_DATA_REG__CNT_DATA__SHIFT 0x0
+#define SPI_PG_ENABLE_STATIC_CU_MASK__CU_MASK_MASK 0xffff
+#define SPI_PG_ENABLE_STATIC_CU_MASK__CU_MASK__SHIFT 0x0
+#define SPI_GDS_CREDITS__DS_DATA_CREDITS_MASK 0xff
+#define SPI_GDS_CREDITS__DS_DATA_CREDITS__SHIFT 0x0
+#define SPI_GDS_CREDITS__DS_CMD_CREDITS_MASK 0xff00
+#define SPI_GDS_CREDITS__DS_CMD_CREDITS__SHIFT 0x8
+#define SPI_GDS_CREDITS__UNUSED_MASK 0xffff0000
+#define SPI_GDS_CREDITS__UNUSED__SHIFT 0x10
+#define SPI_SX_EXPORT_BUFFER_SIZES__COLOR_BUFFER_SIZE_MASK 0xffff
+#define SPI_SX_EXPORT_BUFFER_SIZES__COLOR_BUFFER_SIZE__SHIFT 0x0
+#define SPI_SX_EXPORT_BUFFER_SIZES__POSITION_BUFFER_SIZE_MASK 0xffff0000
+#define SPI_SX_EXPORT_BUFFER_SIZES__POSITION_BUFFER_SIZE__SHIFT 0x10
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__COLOR_SCOREBOARD_SIZE_MASK 0xffff
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__COLOR_SCOREBOARD_SIZE__SHIFT 0x0
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__POSITION_SCOREBOARD_SIZE_MASK 0xffff0000
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__POSITION_SCOREBOARD_SIZE__SHIFT 0x10
+#define SPI_CSQ_WF_ACTIVE_STATUS__ACTIVE_MASK 0xffffffff
+#define SPI_CSQ_WF_ACTIVE_STATUS__ACTIVE__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_1__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_1__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_2__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_2__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_3__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_3__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_4__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_4__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_5__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_5__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_6__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_6__COUNT__SHIFT 0x0
+#define SPI_CSQ_WF_ACTIVE_COUNT_7__COUNT_MASK 0x7ff
+#define SPI_CSQ_WF_ACTIVE_COUNT_7__COUNT__SHIFT 0x0
+#define BCI_DEBUG_READ__DATA_MASK 0xffffff
+#define BCI_DEBUG_READ__DATA__SHIFT 0x0
+#define SPI_P0_TRAP_SCREEN_PSBA_LO__MEM_BASE_MASK 0xffffffff
+#define SPI_P0_TRAP_SCREEN_PSBA_LO__MEM_BASE__SHIFT 0x0
+#define SPI_P0_TRAP_SCREEN_PSBA_HI__MEM_BASE_MASK 0xff
+#define SPI_P0_TRAP_SCREEN_PSBA_HI__MEM_BASE__SHIFT 0x0
+#define SPI_P0_TRAP_SCREEN_PSMA_LO__MEM_BASE_MASK 0xffffffff
+#define SPI_P0_TRAP_SCREEN_PSMA_LO__MEM_BASE__SHIFT 0x0
+#define SPI_P0_TRAP_SCREEN_PSMA_HI__MEM_BASE_MASK 0xff
+#define SPI_P0_TRAP_SCREEN_PSMA_HI__MEM_BASE__SHIFT 0x0
+#define SPI_P0_TRAP_SCREEN_GPR_MIN__VGPR_MIN_MASK 0x3f
+#define SPI_P0_TRAP_SCREEN_GPR_MIN__VGPR_MIN__SHIFT 0x0
+#define SPI_P0_TRAP_SCREEN_GPR_MIN__SGPR_MIN_MASK 0x3c0
+#define SPI_P0_TRAP_SCREEN_GPR_MIN__SGPR_MIN__SHIFT 0x6
+#define SPI_P1_TRAP_SCREEN_PSBA_LO__MEM_BASE_MASK 0xffffffff
+#define SPI_P1_TRAP_SCREEN_PSBA_LO__MEM_BASE__SHIFT 0x0
+#define SPI_P1_TRAP_SCREEN_PSBA_HI__MEM_BASE_MASK 0xff
+#define SPI_P1_TRAP_SCREEN_PSBA_HI__MEM_BASE__SHIFT 0x0
+#define SPI_P1_TRAP_SCREEN_PSMA_LO__MEM_BASE_MASK 0xffffffff
+#define SPI_P1_TRAP_SCREEN_PSMA_LO__MEM_BASE__SHIFT 0x0
+#define SPI_P1_TRAP_SCREEN_PSMA_HI__MEM_BASE_MASK 0xff
+#define SPI_P1_TRAP_SCREEN_PSMA_HI__MEM_BASE__SHIFT 0x0
+#define SPI_P1_TRAP_SCREEN_GPR_MIN__VGPR_MIN_MASK 0x3f
+#define SPI_P1_TRAP_SCREEN_GPR_MIN__VGPR_MIN__SHIFT 0x0
+#define SPI_P1_TRAP_SCREEN_GPR_MIN__SGPR_MIN_MASK 0x3c0
+#define SPI_P1_TRAP_SCREEN_GPR_MIN__SGPR_MIN__SHIFT 0x6
+#define SPI_SHADER_TBA_LO_PS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TBA_LO_PS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TBA_HI_PS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TBA_HI_PS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_LO_PS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TMA_LO_PS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_HI_PS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TMA_HI_PS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_LO_PS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_PGM_LO_PS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_HI_PS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_PGM_HI_PS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_PS__VGPRS_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC1_PS__VGPRS__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_PS__SGPRS_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC1_PS__SGPRS__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC1_PS__PRIORITY_MASK 0xc00
+#define SPI_SHADER_PGM_RSRC1_PS__PRIORITY__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC1_PS__FLOAT_MODE_MASK 0xff000
+#define SPI_SHADER_PGM_RSRC1_PS__FLOAT_MODE__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC1_PS__PRIV_MASK 0x100000
+#define SPI_SHADER_PGM_RSRC1_PS__PRIV__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC1_PS__DX10_CLAMP_MASK 0x200000
+#define SPI_SHADER_PGM_RSRC1_PS__DX10_CLAMP__SHIFT 0x15
+#define SPI_SHADER_PGM_RSRC1_PS__DEBUG_MODE_MASK 0x400000
+#define SPI_SHADER_PGM_RSRC1_PS__DEBUG_MODE__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC1_PS__IEEE_MODE_MASK 0x800000
+#define SPI_SHADER_PGM_RSRC1_PS__IEEE_MODE__SHIFT 0x17
+#define SPI_SHADER_PGM_RSRC1_PS__CU_GROUP_DISABLE_MASK 0x1000000
+#define SPI_SHADER_PGM_RSRC1_PS__CU_GROUP_DISABLE__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC1_PS__CACHE_CTL_MASK 0xe000000
+#define SPI_SHADER_PGM_RSRC1_PS__CACHE_CTL__SHIFT 0x19
+#define SPI_SHADER_PGM_RSRC1_PS__CDBG_USER_MASK 0x10000000
+#define SPI_SHADER_PGM_RSRC1_PS__CDBG_USER__SHIFT 0x1c
+#define SPI_SHADER_PGM_RSRC2_PS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_PS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_PS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_PS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_PS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_PS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_PS__WAVE_CNT_EN_MASK 0x80
+#define SPI_SHADER_PGM_RSRC2_PS__WAVE_CNT_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_PS__EXTRA_LDS_SIZE_MASK 0xff00
+#define SPI_SHADER_PGM_RSRC2_PS__EXTRA_LDS_SIZE__SHIFT 0x8
+#define SPI_SHADER_PGM_RSRC2_PS__EXCP_EN_MASK 0x1ff0000
+#define SPI_SHADER_PGM_RSRC2_PS__EXCP_EN__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_PS__CU_EN_MASK 0xffff
+#define SPI_SHADER_PGM_RSRC3_PS__CU_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC3_PS__WAVE_LIMIT_MASK 0x3f0000
+#define SPI_SHADER_PGM_RSRC3_PS__WAVE_LIMIT__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_PS__LOCK_LOW_THRESHOLD_MASK 0x3c00000
+#define SPI_SHADER_PGM_RSRC3_PS__LOCK_LOW_THRESHOLD__SHIFT 0x16
+#define SPI_SHADER_USER_DATA_PS_0__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_0__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_1__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_1__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_2__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_2__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_3__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_3__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_4__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_4__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_5__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_5__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_6__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_6__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_7__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_7__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_8__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_8__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_9__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_9__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_10__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_10__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_11__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_11__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_12__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_12__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_13__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_13__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_14__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_14__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_PS_15__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_PS_15__DATA__SHIFT 0x0
+#define SPI_SHADER_TBA_LO_VS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TBA_LO_VS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TBA_HI_VS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TBA_HI_VS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_LO_VS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TMA_LO_VS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_HI_VS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TMA_HI_VS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_LO_VS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_PGM_LO_VS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_HI_VS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_PGM_HI_VS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_VS__VGPRS_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC1_VS__VGPRS__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_VS__SGPRS_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC1_VS__SGPRS__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC1_VS__PRIORITY_MASK 0xc00
+#define SPI_SHADER_PGM_RSRC1_VS__PRIORITY__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC1_VS__FLOAT_MODE_MASK 0xff000
+#define SPI_SHADER_PGM_RSRC1_VS__FLOAT_MODE__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC1_VS__PRIV_MASK 0x100000
+#define SPI_SHADER_PGM_RSRC1_VS__PRIV__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC1_VS__DX10_CLAMP_MASK 0x200000
+#define SPI_SHADER_PGM_RSRC1_VS__DX10_CLAMP__SHIFT 0x15
+#define SPI_SHADER_PGM_RSRC1_VS__DEBUG_MODE_MASK 0x400000
+#define SPI_SHADER_PGM_RSRC1_VS__DEBUG_MODE__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC1_VS__IEEE_MODE_MASK 0x800000
+#define SPI_SHADER_PGM_RSRC1_VS__IEEE_MODE__SHIFT 0x17
+#define SPI_SHADER_PGM_RSRC1_VS__VGPR_COMP_CNT_MASK 0x3000000
+#define SPI_SHADER_PGM_RSRC1_VS__VGPR_COMP_CNT__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC1_VS__CU_GROUP_ENABLE_MASK 0x4000000
+#define SPI_SHADER_PGM_RSRC1_VS__CU_GROUP_ENABLE__SHIFT 0x1a
+#define SPI_SHADER_PGM_RSRC1_VS__CACHE_CTL_MASK 0x38000000
+#define SPI_SHADER_PGM_RSRC1_VS__CACHE_CTL__SHIFT 0x1b
+#define SPI_SHADER_PGM_RSRC1_VS__CDBG_USER_MASK 0x40000000
+#define SPI_SHADER_PGM_RSRC1_VS__CDBG_USER__SHIFT 0x1e
+#define SPI_SHADER_PGM_RSRC2_VS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_VS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_VS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_VS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_VS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_VS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_VS__OC_LDS_EN_MASK 0x80
+#define SPI_SHADER_PGM_RSRC2_VS__OC_LDS_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE0_EN_MASK 0x100
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE0_EN__SHIFT 0x8
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE1_EN_MASK 0x200
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE1_EN__SHIFT 0x9
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE2_EN_MASK 0x400
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE2_EN__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE3_EN_MASK 0x800
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE3_EN__SHIFT 0xb
+#define SPI_SHADER_PGM_RSRC2_VS__SO_EN_MASK 0x1000
+#define SPI_SHADER_PGM_RSRC2_VS__SO_EN__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC2_VS__EXCP_EN_MASK 0x3fe000
+#define SPI_SHADER_PGM_RSRC2_VS__EXCP_EN__SHIFT 0xd
+#define SPI_SHADER_PGM_RSRC2_VS__DISPATCH_DRAW_EN_MASK 0x1000000
+#define SPI_SHADER_PGM_RSRC2_VS__DISPATCH_DRAW_EN__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC3_VS__CU_EN_MASK 0xffff
+#define SPI_SHADER_PGM_RSRC3_VS__CU_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC3_VS__WAVE_LIMIT_MASK 0x3f0000
+#define SPI_SHADER_PGM_RSRC3_VS__WAVE_LIMIT__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_VS__LOCK_LOW_THRESHOLD_MASK 0x3c00000
+#define SPI_SHADER_PGM_RSRC3_VS__LOCK_LOW_THRESHOLD__SHIFT 0x16
+#define SPI_SHADER_LATE_ALLOC_VS__LIMIT_MASK 0x3f
+#define SPI_SHADER_LATE_ALLOC_VS__LIMIT__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_0__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_0__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_1__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_1__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_2__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_2__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_3__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_3__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_4__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_4__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_5__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_5__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_6__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_6__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_7__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_7__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_8__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_8__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_9__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_9__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_10__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_10__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_11__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_11__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_12__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_12__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_13__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_13__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_14__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_14__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_VS_15__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_VS_15__DATA__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_ES_VS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_ES_VS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_ES_VS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_ES_VS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_ES_VS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_ES_VS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_ES_VS__OC_LDS_EN_MASK 0x80
+#define SPI_SHADER_PGM_RSRC2_ES_VS__OC_LDS_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_ES_VS__EXCP_EN_MASK 0x1ff00
+#define SPI_SHADER_PGM_RSRC2_ES_VS__EXCP_EN__SHIFT 0x8
+#define SPI_SHADER_PGM_RSRC2_ES_VS__LDS_SIZE_MASK 0x1ff00000
+#define SPI_SHADER_PGM_RSRC2_ES_VS__LDS_SIZE__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC2_LS_VS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_LS_VS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_LS_VS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_LS_VS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_LS_VS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_LS_VS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_LS_VS__LDS_SIZE_MASK 0xff80
+#define SPI_SHADER_PGM_RSRC2_LS_VS__LDS_SIZE__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_LS_VS__EXCP_EN_MASK 0x1ff0000
+#define SPI_SHADER_PGM_RSRC2_LS_VS__EXCP_EN__SHIFT 0x10
+#define SPI_SHADER_TBA_LO_GS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TBA_LO_GS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TBA_HI_GS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TBA_HI_GS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_LO_GS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TMA_LO_GS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_HI_GS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TMA_HI_GS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_LO_GS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_PGM_LO_GS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_HI_GS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_PGM_HI_GS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_GS__VGPRS_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC1_GS__VGPRS__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_GS__SGPRS_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC1_GS__SGPRS__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC1_GS__PRIORITY_MASK 0xc00
+#define SPI_SHADER_PGM_RSRC1_GS__PRIORITY__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC1_GS__FLOAT_MODE_MASK 0xff000
+#define SPI_SHADER_PGM_RSRC1_GS__FLOAT_MODE__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC1_GS__PRIV_MASK 0x100000
+#define SPI_SHADER_PGM_RSRC1_GS__PRIV__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC1_GS__DX10_CLAMP_MASK 0x200000
+#define SPI_SHADER_PGM_RSRC1_GS__DX10_CLAMP__SHIFT 0x15
+#define SPI_SHADER_PGM_RSRC1_GS__DEBUG_MODE_MASK 0x400000
+#define SPI_SHADER_PGM_RSRC1_GS__DEBUG_MODE__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC1_GS__IEEE_MODE_MASK 0x800000
+#define SPI_SHADER_PGM_RSRC1_GS__IEEE_MODE__SHIFT 0x17
+#define SPI_SHADER_PGM_RSRC1_GS__CU_GROUP_ENABLE_MASK 0x1000000
+#define SPI_SHADER_PGM_RSRC1_GS__CU_GROUP_ENABLE__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC1_GS__CACHE_CTL_MASK 0xe000000
+#define SPI_SHADER_PGM_RSRC1_GS__CACHE_CTL__SHIFT 0x19
+#define SPI_SHADER_PGM_RSRC1_GS__CDBG_USER_MASK 0x10000000
+#define SPI_SHADER_PGM_RSRC1_GS__CDBG_USER__SHIFT 0x1c
+#define SPI_SHADER_PGM_RSRC2_GS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_GS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_GS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_GS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_GS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_GS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_GS__EXCP_EN_MASK 0xff80
+#define SPI_SHADER_PGM_RSRC2_GS__EXCP_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC3_GS__CU_EN_MASK 0xffff
+#define SPI_SHADER_PGM_RSRC3_GS__CU_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC3_GS__WAVE_LIMIT_MASK 0x3f0000
+#define SPI_SHADER_PGM_RSRC3_GS__WAVE_LIMIT__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_GS__LOCK_LOW_THRESHOLD_MASK 0x3c00000
+#define SPI_SHADER_PGM_RSRC3_GS__LOCK_LOW_THRESHOLD__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC3_GS__GROUP_FIFO_DEPTH_MASK 0xfc000000
+#define SPI_SHADER_PGM_RSRC3_GS__GROUP_FIFO_DEPTH__SHIFT 0x1a
+#define SPI_SHADER_USER_DATA_GS_0__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_0__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_1__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_1__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_2__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_2__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_3__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_3__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_4__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_4__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_5__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_5__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_6__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_6__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_7__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_7__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_8__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_8__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_9__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_9__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_10__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_10__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_11__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_11__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_12__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_12__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_13__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_13__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_14__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_14__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_GS_15__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_GS_15__DATA__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_ES_GS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_ES_GS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_ES_GS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_ES_GS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_ES_GS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_ES_GS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_ES_GS__OC_LDS_EN_MASK 0x80
+#define SPI_SHADER_PGM_RSRC2_ES_GS__OC_LDS_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_ES_GS__EXCP_EN_MASK 0x1ff00
+#define SPI_SHADER_PGM_RSRC2_ES_GS__EXCP_EN__SHIFT 0x8
+#define SPI_SHADER_PGM_RSRC2_ES_GS__LDS_SIZE_MASK 0x1ff00000
+#define SPI_SHADER_PGM_RSRC2_ES_GS__LDS_SIZE__SHIFT 0x14
+#define SPI_SHADER_TBA_LO_ES__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TBA_LO_ES__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TBA_HI_ES__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TBA_HI_ES__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_LO_ES__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TMA_LO_ES__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_HI_ES__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TMA_HI_ES__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_LO_ES__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_PGM_LO_ES__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_HI_ES__MEM_BASE_MASK 0xff
+#define SPI_SHADER_PGM_HI_ES__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_ES__VGPRS_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC1_ES__VGPRS__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_ES__SGPRS_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC1_ES__SGPRS__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC1_ES__PRIORITY_MASK 0xc00
+#define SPI_SHADER_PGM_RSRC1_ES__PRIORITY__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC1_ES__FLOAT_MODE_MASK 0xff000
+#define SPI_SHADER_PGM_RSRC1_ES__FLOAT_MODE__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC1_ES__PRIV_MASK 0x100000
+#define SPI_SHADER_PGM_RSRC1_ES__PRIV__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC1_ES__DX10_CLAMP_MASK 0x200000
+#define SPI_SHADER_PGM_RSRC1_ES__DX10_CLAMP__SHIFT 0x15
+#define SPI_SHADER_PGM_RSRC1_ES__DEBUG_MODE_MASK 0x400000
+#define SPI_SHADER_PGM_RSRC1_ES__DEBUG_MODE__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC1_ES__IEEE_MODE_MASK 0x800000
+#define SPI_SHADER_PGM_RSRC1_ES__IEEE_MODE__SHIFT 0x17
+#define SPI_SHADER_PGM_RSRC1_ES__VGPR_COMP_CNT_MASK 0x3000000
+#define SPI_SHADER_PGM_RSRC1_ES__VGPR_COMP_CNT__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC1_ES__CU_GROUP_ENABLE_MASK 0x4000000
+#define SPI_SHADER_PGM_RSRC1_ES__CU_GROUP_ENABLE__SHIFT 0x1a
+#define SPI_SHADER_PGM_RSRC1_ES__CACHE_CTL_MASK 0x38000000
+#define SPI_SHADER_PGM_RSRC1_ES__CACHE_CTL__SHIFT 0x1b
+#define SPI_SHADER_PGM_RSRC1_ES__CDBG_USER_MASK 0x40000000
+#define SPI_SHADER_PGM_RSRC1_ES__CDBG_USER__SHIFT 0x1e
+#define SPI_SHADER_PGM_RSRC2_ES__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_ES__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_ES__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_ES__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_ES__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_ES__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_ES__OC_LDS_EN_MASK 0x80
+#define SPI_SHADER_PGM_RSRC2_ES__OC_LDS_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_ES__EXCP_EN_MASK 0x1ff00
+#define SPI_SHADER_PGM_RSRC2_ES__EXCP_EN__SHIFT 0x8
+#define SPI_SHADER_PGM_RSRC2_ES__LDS_SIZE_MASK 0x1ff00000
+#define SPI_SHADER_PGM_RSRC2_ES__LDS_SIZE__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC3_ES__CU_EN_MASK 0xffff
+#define SPI_SHADER_PGM_RSRC3_ES__CU_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC3_ES__WAVE_LIMIT_MASK 0x3f0000
+#define SPI_SHADER_PGM_RSRC3_ES__WAVE_LIMIT__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_ES__LOCK_LOW_THRESHOLD_MASK 0x3c00000
+#define SPI_SHADER_PGM_RSRC3_ES__LOCK_LOW_THRESHOLD__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC3_ES__GROUP_FIFO_DEPTH_MASK 0xfc000000
+#define SPI_SHADER_PGM_RSRC3_ES__GROUP_FIFO_DEPTH__SHIFT 0x1a
+#define SPI_SHADER_USER_DATA_ES_0__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_0__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_1__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_1__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_2__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_2__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_3__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_3__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_4__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_4__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_5__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_5__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_6__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_6__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_7__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_7__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_8__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_8__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_9__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_9__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_10__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_10__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_11__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_11__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_12__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_12__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_13__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_13__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_14__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_14__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_ES_15__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_ES_15__DATA__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_LS_ES__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_LS_ES__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_LS_ES__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_LS_ES__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_LS_ES__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_LS_ES__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_LS_ES__LDS_SIZE_MASK 0xff80
+#define SPI_SHADER_PGM_RSRC2_LS_ES__LDS_SIZE__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_LS_ES__EXCP_EN_MASK 0x1ff0000
+#define SPI_SHADER_PGM_RSRC2_LS_ES__EXCP_EN__SHIFT 0x10
+#define SPI_SHADER_TBA_LO_HS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TBA_LO_HS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TBA_HI_HS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TBA_HI_HS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_LO_HS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TMA_LO_HS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_HI_HS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TMA_HI_HS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_LO_HS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_PGM_LO_HS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_HI_HS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_PGM_HI_HS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_HS__VGPRS_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC1_HS__VGPRS__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_HS__SGPRS_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC1_HS__SGPRS__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC1_HS__PRIORITY_MASK 0xc00
+#define SPI_SHADER_PGM_RSRC1_HS__PRIORITY__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC1_HS__FLOAT_MODE_MASK 0xff000
+#define SPI_SHADER_PGM_RSRC1_HS__FLOAT_MODE__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC1_HS__PRIV_MASK 0x100000
+#define SPI_SHADER_PGM_RSRC1_HS__PRIV__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC1_HS__DX10_CLAMP_MASK 0x200000
+#define SPI_SHADER_PGM_RSRC1_HS__DX10_CLAMP__SHIFT 0x15
+#define SPI_SHADER_PGM_RSRC1_HS__DEBUG_MODE_MASK 0x400000
+#define SPI_SHADER_PGM_RSRC1_HS__DEBUG_MODE__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC1_HS__IEEE_MODE_MASK 0x800000
+#define SPI_SHADER_PGM_RSRC1_HS__IEEE_MODE__SHIFT 0x17
+#define SPI_SHADER_PGM_RSRC1_HS__CACHE_CTL_MASK 0x7000000
+#define SPI_SHADER_PGM_RSRC1_HS__CACHE_CTL__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC1_HS__CDBG_USER_MASK 0x8000000
+#define SPI_SHADER_PGM_RSRC1_HS__CDBG_USER__SHIFT 0x1b
+#define SPI_SHADER_PGM_RSRC2_HS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_HS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_HS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_HS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_HS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_HS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_HS__OC_LDS_EN_MASK 0x80
+#define SPI_SHADER_PGM_RSRC2_HS__OC_LDS_EN__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_HS__TG_SIZE_EN_MASK 0x100
+#define SPI_SHADER_PGM_RSRC2_HS__TG_SIZE_EN__SHIFT 0x8
+#define SPI_SHADER_PGM_RSRC2_HS__EXCP_EN_MASK 0x3fe00
+#define SPI_SHADER_PGM_RSRC2_HS__EXCP_EN__SHIFT 0x9
+#define SPI_SHADER_PGM_RSRC3_HS__WAVE_LIMIT_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC3_HS__WAVE_LIMIT__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC3_HS__LOCK_LOW_THRESHOLD_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC3_HS__LOCK_LOW_THRESHOLD__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC3_HS__GROUP_FIFO_DEPTH_MASK 0xfc00
+#define SPI_SHADER_PGM_RSRC3_HS__GROUP_FIFO_DEPTH__SHIFT 0xa
+#define SPI_SHADER_USER_DATA_HS_0__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_0__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_1__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_1__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_2__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_2__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_3__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_3__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_4__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_4__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_5__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_5__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_6__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_6__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_7__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_7__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_8__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_8__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_9__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_9__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_10__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_10__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_11__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_11__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_12__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_12__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_13__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_13__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_14__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_14__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_HS_15__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_HS_15__DATA__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_LS_HS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_LS_HS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_LS_HS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_LS_HS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_LS_HS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_LS_HS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_LS_HS__LDS_SIZE_MASK 0xff80
+#define SPI_SHADER_PGM_RSRC2_LS_HS__LDS_SIZE__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_LS_HS__EXCP_EN_MASK 0x1ff0000
+#define SPI_SHADER_PGM_RSRC2_LS_HS__EXCP_EN__SHIFT 0x10
+#define SPI_SHADER_TBA_LO_LS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TBA_LO_LS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TBA_HI_LS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TBA_HI_LS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_LO_LS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_TMA_LO_LS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_TMA_HI_LS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_TMA_HI_LS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_LO_LS__MEM_BASE_MASK 0xffffffff
+#define SPI_SHADER_PGM_LO_LS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_HI_LS__MEM_BASE_MASK 0xff
+#define SPI_SHADER_PGM_HI_LS__MEM_BASE__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_LS__VGPRS_MASK 0x3f
+#define SPI_SHADER_PGM_RSRC1_LS__VGPRS__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC1_LS__SGPRS_MASK 0x3c0
+#define SPI_SHADER_PGM_RSRC1_LS__SGPRS__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC1_LS__PRIORITY_MASK 0xc00
+#define SPI_SHADER_PGM_RSRC1_LS__PRIORITY__SHIFT 0xa
+#define SPI_SHADER_PGM_RSRC1_LS__FLOAT_MODE_MASK 0xff000
+#define SPI_SHADER_PGM_RSRC1_LS__FLOAT_MODE__SHIFT 0xc
+#define SPI_SHADER_PGM_RSRC1_LS__PRIV_MASK 0x100000
+#define SPI_SHADER_PGM_RSRC1_LS__PRIV__SHIFT 0x14
+#define SPI_SHADER_PGM_RSRC1_LS__DX10_CLAMP_MASK 0x200000
+#define SPI_SHADER_PGM_RSRC1_LS__DX10_CLAMP__SHIFT 0x15
+#define SPI_SHADER_PGM_RSRC1_LS__DEBUG_MODE_MASK 0x400000
+#define SPI_SHADER_PGM_RSRC1_LS__DEBUG_MODE__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC1_LS__IEEE_MODE_MASK 0x800000
+#define SPI_SHADER_PGM_RSRC1_LS__IEEE_MODE__SHIFT 0x17
+#define SPI_SHADER_PGM_RSRC1_LS__VGPR_COMP_CNT_MASK 0x3000000
+#define SPI_SHADER_PGM_RSRC1_LS__VGPR_COMP_CNT__SHIFT 0x18
+#define SPI_SHADER_PGM_RSRC1_LS__CACHE_CTL_MASK 0x1c000000
+#define SPI_SHADER_PGM_RSRC1_LS__CACHE_CTL__SHIFT 0x1a
+#define SPI_SHADER_PGM_RSRC1_LS__CDBG_USER_MASK 0x20000000
+#define SPI_SHADER_PGM_RSRC1_LS__CDBG_USER__SHIFT 0x1d
+#define SPI_SHADER_PGM_RSRC2_LS__SCRATCH_EN_MASK 0x1
+#define SPI_SHADER_PGM_RSRC2_LS__SCRATCH_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC2_LS__USER_SGPR_MASK 0x3e
+#define SPI_SHADER_PGM_RSRC2_LS__USER_SGPR__SHIFT 0x1
+#define SPI_SHADER_PGM_RSRC2_LS__TRAP_PRESENT_MASK 0x40
+#define SPI_SHADER_PGM_RSRC2_LS__TRAP_PRESENT__SHIFT 0x6
+#define SPI_SHADER_PGM_RSRC2_LS__LDS_SIZE_MASK 0xff80
+#define SPI_SHADER_PGM_RSRC2_LS__LDS_SIZE__SHIFT 0x7
+#define SPI_SHADER_PGM_RSRC2_LS__EXCP_EN_MASK 0x1ff0000
+#define SPI_SHADER_PGM_RSRC2_LS__EXCP_EN__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_LS__CU_EN_MASK 0xffff
+#define SPI_SHADER_PGM_RSRC3_LS__CU_EN__SHIFT 0x0
+#define SPI_SHADER_PGM_RSRC3_LS__WAVE_LIMIT_MASK 0x3f0000
+#define SPI_SHADER_PGM_RSRC3_LS__WAVE_LIMIT__SHIFT 0x10
+#define SPI_SHADER_PGM_RSRC3_LS__LOCK_LOW_THRESHOLD_MASK 0x3c00000
+#define SPI_SHADER_PGM_RSRC3_LS__LOCK_LOW_THRESHOLD__SHIFT 0x16
+#define SPI_SHADER_PGM_RSRC3_LS__GROUP_FIFO_DEPTH_MASK 0xfc000000
+#define SPI_SHADER_PGM_RSRC3_LS__GROUP_FIFO_DEPTH__SHIFT 0x1a
+#define SPI_SHADER_USER_DATA_LS_0__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_0__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_1__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_1__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_2__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_2__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_3__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_3__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_4__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_4__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_5__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_5__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_6__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_6__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_7__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_7__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_8__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_8__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_9__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_9__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_10__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_10__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_11__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_11__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_12__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_12__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_13__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_13__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_14__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_14__DATA__SHIFT 0x0
+#define SPI_SHADER_USER_DATA_LS_15__DATA_MASK 0xffffffff
+#define SPI_SHADER_USER_DATA_LS_15__DATA__SHIFT 0x0
+#define SQ_CONFIG__UNUSED_MASK 0xff
+#define SQ_CONFIG__UNUSED__SHIFT 0x0
+#define SQ_CONFIG__DEBUG_EN_MASK 0x100
+#define SQ_CONFIG__DEBUG_EN__SHIFT 0x8
+#define SQ_CONFIG__DEBUG_SINGLE_MEMOP_MASK 0x200
+#define SQ_CONFIG__DEBUG_SINGLE_MEMOP__SHIFT 0x9
+#define SQ_CONFIG__DEBUG_ONE_INST_CLAUSE_MASK 0x400
+#define SQ_CONFIG__DEBUG_ONE_INST_CLAUSE__SHIFT 0xa
+#define SQ_CONFIG__EARLY_TA_DONE_DISABLE_MASK 0x1000
+#define SQ_CONFIG__EARLY_TA_DONE_DISABLE__SHIFT 0xc
+#define SQ_CONFIG__DUA_FLAT_LOCK_ENABLE_MASK 0x2000
+#define SQ_CONFIG__DUA_FLAT_LOCK_ENABLE__SHIFT 0xd
+#define SQ_CONFIG__DUA_LDS_BYPASS_DISABLE_MASK 0x4000
+#define SQ_CONFIG__DUA_LDS_BYPASS_DISABLE__SHIFT 0xe
+#define SQ_CONFIG__DUA_FLAT_LDS_PINGPONG_DISABLE_MASK 0x8000
+#define SQ_CONFIG__DUA_FLAT_LDS_PINGPONG_DISABLE__SHIFT 0xf
+#define SQ_CONFIG__DISABLE_VMEM_SOFT_CLAUSE_MASK 0x10000
+#define SQ_CONFIG__DISABLE_VMEM_SOFT_CLAUSE__SHIFT 0x10
+#define SQ_CONFIG__DISABLE_SMEM_SOFT_CLAUSE_MASK 0x20000
+#define SQ_CONFIG__DISABLE_SMEM_SOFT_CLAUSE__SHIFT 0x11
+#define SQ_CONFIG__ENABLE_HIPRIO_ON_EXP_RDY_VS_MASK 0x40000
+#define SQ_CONFIG__ENABLE_HIPRIO_ON_EXP_RDY_VS__SHIFT 0x12
+#define SQ_CONFIG__PRIO_VAL_ON_EXP_RDY_VS_MASK 0x180000
+#define SQ_CONFIG__PRIO_VAL_ON_EXP_RDY_VS__SHIFT 0x13
+#define SQ_CONFIG__REPLAY_SLEEP_CNT_MASK 0x1e00000
+#define SQ_CONFIG__REPLAY_SLEEP_CNT__SHIFT 0x15
+#define SQC_CONFIG__INST_CACHE_SIZE_MASK 0x3
+#define SQC_CONFIG__INST_CACHE_SIZE__SHIFT 0x0
+#define SQC_CONFIG__DATA_CACHE_SIZE_MASK 0xc
+#define SQC_CONFIG__DATA_CACHE_SIZE__SHIFT 0x2
+#define SQC_CONFIG__MISS_FIFO_DEPTH_MASK 0x30
+#define SQC_CONFIG__MISS_FIFO_DEPTH__SHIFT 0x4
+#define SQC_CONFIG__HIT_FIFO_DEPTH_MASK 0x40
+#define SQC_CONFIG__HIT_FIFO_DEPTH__SHIFT 0x6
+#define SQC_CONFIG__FORCE_ALWAYS_MISS_MASK 0x80
+#define SQC_CONFIG__FORCE_ALWAYS_MISS__SHIFT 0x7
+#define SQC_CONFIG__FORCE_IN_ORDER_MASK 0x100
+#define SQC_CONFIG__FORCE_IN_ORDER__SHIFT 0x8
+#define SQC_CONFIG__IDENTITY_HASH_BANK_MASK 0x200
+#define SQC_CONFIG__IDENTITY_HASH_BANK__SHIFT 0x9
+#define SQC_CONFIG__IDENTITY_HASH_SET_MASK 0x400
+#define SQC_CONFIG__IDENTITY_HASH_SET__SHIFT 0xa
+#define SQC_CONFIG__PER_VMID_INV_DISABLE_MASK 0x800
+#define SQC_CONFIG__PER_VMID_INV_DISABLE__SHIFT 0xb
+#define SQC_CONFIG__EVICT_LRU_MASK 0x3000
+#define SQC_CONFIG__EVICT_LRU__SHIFT 0xc
+#define SQC_CONFIG__FORCE_2_BANK_MASK 0x4000
+#define SQC_CONFIG__FORCE_2_BANK__SHIFT 0xe
+#define SQC_CONFIG__FORCE_1_BANK_MASK 0x8000
+#define SQC_CONFIG__FORCE_1_BANK__SHIFT 0xf
+#define SQC_CONFIG__LS_DISABLE_CLOCKS_MASK 0xff0000
+#define SQC_CONFIG__LS_DISABLE_CLOCKS__SHIFT 0x10
+#define SQC_CACHES__TARGET_INST_MASK 0x1
+#define SQC_CACHES__TARGET_INST__SHIFT 0x0
+#define SQC_CACHES__TARGET_DATA_MASK 0x2
+#define SQC_CACHES__TARGET_DATA__SHIFT 0x1
+#define SQC_CACHES__INVALIDATE_MASK 0x4
+#define SQC_CACHES__INVALIDATE__SHIFT 0x2
+#define SQC_CACHES__WRITEBACK_MASK 0x8
+#define SQC_CACHES__WRITEBACK__SHIFT 0x3
+#define SQC_CACHES__VOL_MASK 0x10
+#define SQC_CACHES__VOL__SHIFT 0x4
+#define SQC_CACHES__COMPLETE_MASK 0x10000
+#define SQC_CACHES__COMPLETE__SHIFT 0x10
+#define SQC_WRITEBACK__DWB_MASK 0x1
+#define SQC_WRITEBACK__DWB__SHIFT 0x0
+#define SQC_WRITEBACK__DIRTY_MASK 0x2
+#define SQC_WRITEBACK__DIRTY__SHIFT 0x1
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKA_MASK 0x3
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKA__SHIFT 0x0
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKA_MASK 0x4
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKA__SHIFT 0x2
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKB_MASK 0x18
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKB__SHIFT 0x3
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKB_MASK 0x20
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKB__SHIFT 0x5
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKC_MASK 0xc0
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKC__SHIFT 0x6
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKC_MASK 0x100
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKC__SHIFT 0x8
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKD_MASK 0x600
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_BANKD__SHIFT 0x9
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKD_MASK 0x800
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_BANKD__SHIFT 0xb
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_GATCL1_MASK 0x3000
+#define SQC_DSM_CNTL__SEL_DATA_ICACHE_GATCL1__SHIFT 0xc
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_GATCL1_MASK 0x4000
+#define SQC_DSM_CNTL__EN_SINGLE_WR_ICACHE_GATCL1__SHIFT 0xe
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKA_MASK 0x18000
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKA__SHIFT 0xf
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKA_MASK 0x20000
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKA__SHIFT 0x11
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKB_MASK 0xc0000
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKB__SHIFT 0x12
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKB_MASK 0x100000
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKB__SHIFT 0x14
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKC_MASK 0x600000
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKC__SHIFT 0x15
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKC_MASK 0x800000
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKC__SHIFT 0x17
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKD_MASK 0x3000000
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_BANKD__SHIFT 0x18
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKD_MASK 0x4000000
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_BANKD__SHIFT 0x1a
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_GATCL1_MASK 0x18000000
+#define SQC_DSM_CNTL__SEL_DATA_DCACHE_GATCL1__SHIFT 0x1b
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_GATCL1_MASK 0x20000000
+#define SQC_DSM_CNTL__EN_SINGLE_WR_DCACHE_GATCL1__SHIFT 0x1d
+#define SQ_RANDOM_WAVE_PRI__RET_MASK 0x7f
+#define SQ_RANDOM_WAVE_PRI__RET__SHIFT 0x0
+#define SQ_RANDOM_WAVE_PRI__RUI_MASK 0x380
+#define SQ_RANDOM_WAVE_PRI__RUI__SHIFT 0x7
+#define SQ_RANDOM_WAVE_PRI__RNG_MASK 0x1ffc00
+#define SQ_RANDOM_WAVE_PRI__RNG__SHIFT 0xa
+#define SQ_REG_CREDITS__SRBM_CREDITS_MASK 0x3f
+#define SQ_REG_CREDITS__SRBM_CREDITS__SHIFT 0x0
+#define SQ_REG_CREDITS__CMD_CREDITS_MASK 0xf00
+#define SQ_REG_CREDITS__CMD_CREDITS__SHIFT 0x8
+#define SQ_REG_CREDITS__REG_BUSY_MASK 0x10000000
+#define SQ_REG_CREDITS__REG_BUSY__SHIFT 0x1c
+#define SQ_REG_CREDITS__SRBM_OVERFLOW_MASK 0x20000000
+#define SQ_REG_CREDITS__SRBM_OVERFLOW__SHIFT 0x1d
+#define SQ_REG_CREDITS__IMMED_OVERFLOW_MASK 0x40000000
+#define SQ_REG_CREDITS__IMMED_OVERFLOW__SHIFT 0x1e
+#define SQ_REG_CREDITS__CMD_OVERFLOW_MASK 0x80000000
+#define SQ_REG_CREDITS__CMD_OVERFLOW__SHIFT 0x1f
+#define SQ_FIFO_SIZES__INTERRUPT_FIFO_SIZE_MASK 0xf
+#define SQ_FIFO_SIZES__INTERRUPT_FIFO_SIZE__SHIFT 0x0
+#define SQ_FIFO_SIZES__TTRACE_FIFO_SIZE_MASK 0xf00
+#define SQ_FIFO_SIZES__TTRACE_FIFO_SIZE__SHIFT 0x8
+#define SQ_FIFO_SIZES__EXPORT_BUF_SIZE_MASK 0x30000
+#define SQ_FIFO_SIZES__EXPORT_BUF_SIZE__SHIFT 0x10
+#define SQ_FIFO_SIZES__VMEM_DATA_FIFO_SIZE_MASK 0xc0000
+#define SQ_FIFO_SIZES__VMEM_DATA_FIFO_SIZE__SHIFT 0x12
+#define SQ_DSM_CNTL__WAVEFRONT_STALL_0_MASK 0x1
+#define SQ_DSM_CNTL__WAVEFRONT_STALL_0__SHIFT 0x0
+#define SQ_DSM_CNTL__WAVEFRONT_STALL_1_MASK 0x2
+#define SQ_DSM_CNTL__WAVEFRONT_STALL_1__SHIFT 0x1
+#define SQ_DSM_CNTL__SPI_BACKPRESSURE_0_MASK 0x4
+#define SQ_DSM_CNTL__SPI_BACKPRESSURE_0__SHIFT 0x2
+#define SQ_DSM_CNTL__SPI_BACKPRESSURE_1_MASK 0x8
+#define SQ_DSM_CNTL__SPI_BACKPRESSURE_1__SHIFT 0x3
+#define SQ_DSM_CNTL__SEL_DSM_SGPR_IRRITATOR_DATA0_MASK 0x100
+#define SQ_DSM_CNTL__SEL_DSM_SGPR_IRRITATOR_DATA0__SHIFT 0x8
+#define SQ_DSM_CNTL__SEL_DSM_SGPR_IRRITATOR_DATA1_MASK 0x200
+#define SQ_DSM_CNTL__SEL_DSM_SGPR_IRRITATOR_DATA1__SHIFT 0x9
+#define SQ_DSM_CNTL__SGPR_ENABLE_SINGLE_WRITE_MASK 0x400
+#define SQ_DSM_CNTL__SGPR_ENABLE_SINGLE_WRITE__SHIFT 0xa
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA0_MASK 0x10000
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA0__SHIFT 0x10
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA1_MASK 0x20000
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA1__SHIFT 0x11
+#define SQ_DSM_CNTL__LDS_ENABLE_SINGLE_WRITE01_MASK 0x40000
+#define SQ_DSM_CNTL__LDS_ENABLE_SINGLE_WRITE01__SHIFT 0x12
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA2_MASK 0x80000
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA2__SHIFT 0x13
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA3_MASK 0x100000
+#define SQ_DSM_CNTL__SEL_DSM_LDS_IRRITATOR_DATA3__SHIFT 0x14
+#define SQ_DSM_CNTL__LDS_ENABLE_SINGLE_WRITE23_MASK 0x200000
+#define SQ_DSM_CNTL__LDS_ENABLE_SINGLE_WRITE23__SHIFT 0x15
+#define SQ_DSM_CNTL__SEL_DSM_SP_IRRITATOR_DATA0_MASK 0x1000000
+#define SQ_DSM_CNTL__SEL_DSM_SP_IRRITATOR_DATA0__SHIFT 0x18
+#define SQ_DSM_CNTL__SEL_DSM_SP_IRRITATOR_DATA1_MASK 0x2000000
+#define SQ_DSM_CNTL__SEL_DSM_SP_IRRITATOR_DATA1__SHIFT 0x19
+#define SQ_DSM_CNTL__SP_ENABLE_SINGLE_WRITE_MASK 0x4000000
+#define SQ_DSM_CNTL__SP_ENABLE_SINGLE_WRITE__SHIFT 0x1a
+#define CC_GC_SHADER_RATE_CONFIG__DPFP_RATE_MASK 0x6
+#define CC_GC_SHADER_RATE_CONFIG__DPFP_RATE__SHIFT 0x1
+#define CC_GC_SHADER_RATE_CONFIG__SQC_BALANCE_DISABLE_MASK 0x8
+#define CC_GC_SHADER_RATE_CONFIG__SQC_BALANCE_DISABLE__SHIFT 0x3
+#define CC_GC_SHADER_RATE_CONFIG__HALF_LDS_MASK 0x10
+#define CC_GC_SHADER_RATE_CONFIG__HALF_LDS__SHIFT 0x4
+#define GC_USER_SHADER_RATE_CONFIG__DPFP_RATE_MASK 0x6
+#define GC_USER_SHADER_RATE_CONFIG__DPFP_RATE__SHIFT 0x1
+#define GC_USER_SHADER_RATE_CONFIG__SQC_BALANCE_DISABLE_MASK 0x8
+#define GC_USER_SHADER_RATE_CONFIG__SQC_BALANCE_DISABLE__SHIFT 0x3
+#define GC_USER_SHADER_RATE_CONFIG__HALF_LDS_MASK 0x10
+#define GC_USER_SHADER_RATE_CONFIG__HALF_LDS__SHIFT 0x4
+#define SQ_INTERRUPT_AUTO_MASK__MASK_MASK 0xffffff
+#define SQ_INTERRUPT_AUTO_MASK__MASK__SHIFT 0x0
+#define SQ_INTERRUPT_MSG_CTRL__STALL_MASK 0x1
+#define SQ_INTERRUPT_MSG_CTRL__STALL__SHIFT 0x0
+#define SQ_PERFCOUNTER_CTRL__PS_EN_MASK 0x1
+#define SQ_PERFCOUNTER_CTRL__PS_EN__SHIFT 0x0
+#define SQ_PERFCOUNTER_CTRL__VS_EN_MASK 0x2
+#define SQ_PERFCOUNTER_CTRL__VS_EN__SHIFT 0x1
+#define SQ_PERFCOUNTER_CTRL__GS_EN_MASK 0x4
+#define SQ_PERFCOUNTER_CTRL__GS_EN__SHIFT 0x2
+#define SQ_PERFCOUNTER_CTRL__ES_EN_MASK 0x8
+#define SQ_PERFCOUNTER_CTRL__ES_EN__SHIFT 0x3
+#define SQ_PERFCOUNTER_CTRL__HS_EN_MASK 0x10
+#define SQ_PERFCOUNTER_CTRL__HS_EN__SHIFT 0x4
+#define SQ_PERFCOUNTER_CTRL__LS_EN_MASK 0x20
+#define SQ_PERFCOUNTER_CTRL__LS_EN__SHIFT 0x5
+#define SQ_PERFCOUNTER_CTRL__CS_EN_MASK 0x40
+#define SQ_PERFCOUNTER_CTRL__CS_EN__SHIFT 0x6
+#define SQ_PERFCOUNTER_CTRL__CNTR_RATE_MASK 0x1f00
+#define SQ_PERFCOUNTER_CTRL__CNTR_RATE__SHIFT 0x8
+#define SQ_PERFCOUNTER_CTRL__DISABLE_FLUSH_MASK 0x2000
+#define SQ_PERFCOUNTER_CTRL__DISABLE_FLUSH__SHIFT 0xd
+#define SQ_PERFCOUNTER_MASK__SH0_MASK_MASK 0xffff
+#define SQ_PERFCOUNTER_MASK__SH0_MASK__SHIFT 0x0
+#define SQ_PERFCOUNTER_MASK__SH1_MASK_MASK 0xffff0000
+#define SQ_PERFCOUNTER_MASK__SH1_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER_CTRL2__FORCE_EN_MASK 0x1
+#define SQ_PERFCOUNTER_CTRL2__FORCE_EN__SHIFT 0x0
+#define CC_SQC_BANK_DISABLE__SQC0_BANK_DISABLE_MASK 0xf0000
+#define CC_SQC_BANK_DISABLE__SQC0_BANK_DISABLE__SHIFT 0x10
+#define CC_SQC_BANK_DISABLE__SQC1_BANK_DISABLE_MASK 0xf00000
+#define CC_SQC_BANK_DISABLE__SQC1_BANK_DISABLE__SHIFT 0x14
+#define CC_SQC_BANK_DISABLE__SQC2_BANK_DISABLE_MASK 0xf000000
+#define CC_SQC_BANK_DISABLE__SQC2_BANK_DISABLE__SHIFT 0x18
+#define CC_SQC_BANK_DISABLE__SQC3_BANK_DISABLE_MASK 0xf0000000
+#define CC_SQC_BANK_DISABLE__SQC3_BANK_DISABLE__SHIFT 0x1c
+#define USER_SQC_BANK_DISABLE__SQC0_BANK_DISABLE_MASK 0xf0000
+#define USER_SQC_BANK_DISABLE__SQC0_BANK_DISABLE__SHIFT 0x10
+#define USER_SQC_BANK_DISABLE__SQC1_BANK_DISABLE_MASK 0xf00000
+#define USER_SQC_BANK_DISABLE__SQC1_BANK_DISABLE__SHIFT 0x14
+#define USER_SQC_BANK_DISABLE__SQC2_BANK_DISABLE_MASK 0xf000000
+#define USER_SQC_BANK_DISABLE__SQC2_BANK_DISABLE__SHIFT 0x18
+#define USER_SQC_BANK_DISABLE__SQC3_BANK_DISABLE_MASK 0xf0000000
+#define USER_SQC_BANK_DISABLE__SQC3_BANK_DISABLE__SHIFT 0x1c
+#define SQ_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER6_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER6_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER7_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER7_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER8_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER8_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER9_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER9_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER10_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER10_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER11_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER11_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER12_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER12_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER13_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER13_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER14_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER14_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER15_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SQ_PERFCOUNTER15_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SQ_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER6_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER6_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER7_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER7_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER8_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER8_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER9_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER9_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER10_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER10_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER11_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER11_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER12_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER12_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER13_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER13_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER14_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER14_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER15_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SQ_PERFCOUNTER15_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SQ_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER0_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER0_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER0_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER0_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER0_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER0_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER0_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER0_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER1_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER1_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER1_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER1_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER1_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER1_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER1_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER1_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER2_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER2_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER2_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER2_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER2_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER2_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER2_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER2_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER3_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER3_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER3_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER3_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER3_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER3_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER3_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER3_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER4_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER4_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER4_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER4_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER4_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER4_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER4_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER4_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER4_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER4_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER5_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER5_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER5_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER5_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER5_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER5_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER5_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER5_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER5_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER5_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER6_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER6_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER6_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER6_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER6_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER6_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER6_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER6_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER6_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER6_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER6_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER6_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER7_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER7_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER7_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER7_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER7_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER7_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER7_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER7_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER7_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER7_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER7_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER7_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER8_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER8_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER8_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER8_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER8_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER8_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER8_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER8_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER8_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER8_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER8_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER8_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER9_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER9_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER9_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER9_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER9_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER9_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER9_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER9_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER9_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER9_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER9_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER9_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER10_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER10_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER10_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER10_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER10_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER10_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER10_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER10_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER10_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER10_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER10_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER10_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER11_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER11_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER11_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER11_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER11_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER11_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER11_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER11_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER11_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER11_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER11_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER11_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER12_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER12_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER12_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER12_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER12_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER12_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER12_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER12_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER12_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER12_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER12_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER12_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER13_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER13_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER13_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER13_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER13_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER13_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER13_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER13_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER13_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER13_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER13_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER13_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER14_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER14_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER14_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER14_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER14_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER14_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER14_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER14_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER14_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER14_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER14_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER14_SELECT__PERF_MODE__SHIFT 0x1c
+#define SQ_PERFCOUNTER15_SELECT__PERF_SEL_MASK 0x1ff
+#define SQ_PERFCOUNTER15_SELECT__PERF_SEL__SHIFT 0x0
+#define SQ_PERFCOUNTER15_SELECT__SQC_BANK_MASK_MASK 0xf000
+#define SQ_PERFCOUNTER15_SELECT__SQC_BANK_MASK__SHIFT 0xc
+#define SQ_PERFCOUNTER15_SELECT__SQC_CLIENT_MASK_MASK 0xf0000
+#define SQ_PERFCOUNTER15_SELECT__SQC_CLIENT_MASK__SHIFT 0x10
+#define SQ_PERFCOUNTER15_SELECT__SPM_MODE_MASK 0xf00000
+#define SQ_PERFCOUNTER15_SELECT__SPM_MODE__SHIFT 0x14
+#define SQ_PERFCOUNTER15_SELECT__SIMD_MASK_MASK 0xf000000
+#define SQ_PERFCOUNTER15_SELECT__SIMD_MASK__SHIFT 0x18
+#define SQ_PERFCOUNTER15_SELECT__PERF_MODE_MASK 0xf0000000
+#define SQ_PERFCOUNTER15_SELECT__PERF_MODE__SHIFT 0x1c
+#define CGTT_SQ_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_SQ_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_SQ_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SQ_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SQ_CLK_CTRL__PERFMON_OVERRIDE_MASK 0x20000000
+#define CGTT_SQ_CLK_CTRL__PERFMON_OVERRIDE__SHIFT 0x1d
+#define CGTT_SQ_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000
+#define CGTT_SQ_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x1e
+#define CGTT_SQ_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_SQ_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define CGTT_SQG_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_SQG_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_SQG_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SQG_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SQG_CLK_CTRL__TTRACE_OVERRIDE_MASK 0x10000000
+#define CGTT_SQG_CLK_CTRL__TTRACE_OVERRIDE__SHIFT 0x1c
+#define CGTT_SQG_CLK_CTRL__PERFMON_OVERRIDE_MASK 0x20000000
+#define CGTT_SQG_CLK_CTRL__PERFMON_OVERRIDE__SHIFT 0x1d
+#define CGTT_SQG_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000
+#define CGTT_SQG_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x1e
+#define CGTT_SQG_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_SQG_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0xffff
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x0
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x10
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0xffff
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x0
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x10
+#define SQ_LDS_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0xffff
+#define SQ_LDS_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x0
+#define SQ_LDS_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000
+#define SQ_LDS_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x10
+#define SQ_POWER_THROTTLE__MIN_POWER_MASK 0x3fff
+#define SQ_POWER_THROTTLE__MIN_POWER__SHIFT 0x0
+#define SQ_POWER_THROTTLE__MAX_POWER_MASK 0x3fff0000
+#define SQ_POWER_THROTTLE__MAX_POWER__SHIFT 0x10
+#define SQ_POWER_THROTTLE__PHASE_OFFSET_MASK 0xc0000000
+#define SQ_POWER_THROTTLE__PHASE_OFFSET__SHIFT 0x1e
+#define SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK 0x3fff
+#define SQ_POWER_THROTTLE2__MAX_POWER_DELTA__SHIFT 0x0
+#define SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK 0x3ff0000
+#define SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x10
+#define SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000
+#define SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x1b
+#define SQ_POWER_THROTTLE2__USE_REF_CLOCK_MASK 0x80000000
+#define SQ_POWER_THROTTLE2__USE_REF_CLOCK__SHIFT 0x1f
+#define SQ_TIME_HI__TIME_MASK 0xffffffff
+#define SQ_TIME_HI__TIME__SHIFT 0x0
+#define SQ_TIME_LO__TIME_MASK 0xffffffff
+#define SQ_TIME_LO__TIME__SHIFT 0x0
+#define SQ_THREAD_TRACE_BASE__ADDR_MASK 0xffffffff
+#define SQ_THREAD_TRACE_BASE__ADDR__SHIFT 0x0
+#define SQ_THREAD_TRACE_BASE2__ADDR_HI_MASK 0xf
+#define SQ_THREAD_TRACE_BASE2__ADDR_HI__SHIFT 0x0
+#define SQ_THREAD_TRACE_SIZE__SIZE_MASK 0x3fffff
+#define SQ_THREAD_TRACE_SIZE__SIZE__SHIFT 0x0
+#define SQ_THREAD_TRACE_MASK__CU_SEL_MASK 0x1f
+#define SQ_THREAD_TRACE_MASK__CU_SEL__SHIFT 0x0
+#define SQ_THREAD_TRACE_MASK__SH_SEL_MASK 0x20
+#define SQ_THREAD_TRACE_MASK__SH_SEL__SHIFT 0x5
+#define SQ_THREAD_TRACE_MASK__REG_STALL_EN_MASK 0x80
+#define SQ_THREAD_TRACE_MASK__REG_STALL_EN__SHIFT 0x7
+#define SQ_THREAD_TRACE_MASK__SIMD_EN_MASK 0xf00
+#define SQ_THREAD_TRACE_MASK__SIMD_EN__SHIFT 0x8
+#define SQ_THREAD_TRACE_MASK__VM_ID_MASK_MASK 0x3000
+#define SQ_THREAD_TRACE_MASK__VM_ID_MASK__SHIFT 0xc
+#define SQ_THREAD_TRACE_MASK__SPI_STALL_EN_MASK 0x4000
+#define SQ_THREAD_TRACE_MASK__SPI_STALL_EN__SHIFT 0xe
+#define SQ_THREAD_TRACE_MASK__SQ_STALL_EN_MASK 0x8000
+#define SQ_THREAD_TRACE_MASK__SQ_STALL_EN__SHIFT 0xf
+#define SQ_THREAD_TRACE_USERDATA_0__DATA_MASK 0xffffffff
+#define SQ_THREAD_TRACE_USERDATA_0__DATA__SHIFT 0x0
+#define SQ_THREAD_TRACE_USERDATA_1__DATA_MASK 0xffffffff
+#define SQ_THREAD_TRACE_USERDATA_1__DATA__SHIFT 0x0
+#define SQ_THREAD_TRACE_USERDATA_2__DATA_MASK 0xffffffff
+#define SQ_THREAD_TRACE_USERDATA_2__DATA__SHIFT 0x0
+#define SQ_THREAD_TRACE_USERDATA_3__DATA_MASK 0xffffffff
+#define SQ_THREAD_TRACE_USERDATA_3__DATA__SHIFT 0x0
+#define SQ_THREAD_TRACE_MODE__MASK_PS_MASK 0x7
+#define SQ_THREAD_TRACE_MODE__MASK_PS__SHIFT 0x0
+#define SQ_THREAD_TRACE_MODE__MASK_VS_MASK 0x38
+#define SQ_THREAD_TRACE_MODE__MASK_VS__SHIFT 0x3
+#define SQ_THREAD_TRACE_MODE__MASK_GS_MASK 0x1c0
+#define SQ_THREAD_TRACE_MODE__MASK_GS__SHIFT 0x6
+#define SQ_THREAD_TRACE_MODE__MASK_ES_MASK 0xe00
+#define SQ_THREAD_TRACE_MODE__MASK_ES__SHIFT 0x9
+#define SQ_THREAD_TRACE_MODE__MASK_HS_MASK 0x7000
+#define SQ_THREAD_TRACE_MODE__MASK_HS__SHIFT 0xc
+#define SQ_THREAD_TRACE_MODE__MASK_LS_MASK 0x38000
+#define SQ_THREAD_TRACE_MODE__MASK_LS__SHIFT 0xf
+#define SQ_THREAD_TRACE_MODE__MASK_CS_MASK 0x1c0000
+#define SQ_THREAD_TRACE_MODE__MASK_CS__SHIFT 0x12
+#define SQ_THREAD_TRACE_MODE__MODE_MASK 0x600000
+#define SQ_THREAD_TRACE_MODE__MODE__SHIFT 0x15
+#define SQ_THREAD_TRACE_MODE__CAPTURE_MODE_MASK 0x1800000
+#define SQ_THREAD_TRACE_MODE__CAPTURE_MODE__SHIFT 0x17
+#define SQ_THREAD_TRACE_MODE__AUTOFLUSH_EN_MASK 0x2000000
+#define SQ_THREAD_TRACE_MODE__AUTOFLUSH_EN__SHIFT 0x19
+#define SQ_THREAD_TRACE_MODE__PRIV_MASK 0x4000000
+#define SQ_THREAD_TRACE_MODE__PRIV__SHIFT 0x1a
+#define SQ_THREAD_TRACE_MODE__ISSUE_MASK_MASK 0x18000000
+#define SQ_THREAD_TRACE_MODE__ISSUE_MASK__SHIFT 0x1b
+#define SQ_THREAD_TRACE_MODE__TEST_MODE_MASK 0x20000000
+#define SQ_THREAD_TRACE_MODE__TEST_MODE__SHIFT 0x1d
+#define SQ_THREAD_TRACE_MODE__INTERRUPT_EN_MASK 0x40000000
+#define SQ_THREAD_TRACE_MODE__INTERRUPT_EN__SHIFT 0x1e
+#define SQ_THREAD_TRACE_MODE__WRAP_MASK 0x80000000
+#define SQ_THREAD_TRACE_MODE__WRAP__SHIFT 0x1f
+#define SQ_THREAD_TRACE_CTRL__RESET_BUFFER_MASK 0x80000000
+#define SQ_THREAD_TRACE_CTRL__RESET_BUFFER__SHIFT 0x1f
+#define SQ_THREAD_TRACE_TOKEN_MASK__TOKEN_MASK_MASK 0xffff
+#define SQ_THREAD_TRACE_TOKEN_MASK__TOKEN_MASK__SHIFT 0x0
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_MASK_MASK 0xff0000
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_MASK__SHIFT 0x10
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_DROP_ON_STALL_MASK 0x1000000
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_DROP_ON_STALL__SHIFT 0x18
+#define SQ_THREAD_TRACE_TOKEN_MASK2__INST_MASK_MASK 0xffffffff
+#define SQ_THREAD_TRACE_TOKEN_MASK2__INST_MASK__SHIFT 0x0
+#define SQ_THREAD_TRACE_PERF_MASK__SH0_MASK_MASK 0xffff
+#define SQ_THREAD_TRACE_PERF_MASK__SH0_MASK__SHIFT 0x0
+#define SQ_THREAD_TRACE_PERF_MASK__SH1_MASK_MASK 0xffff0000
+#define SQ_THREAD_TRACE_PERF_MASK__SH1_MASK__SHIFT 0x10
+#define SQ_THREAD_TRACE_WPTR__WPTR_MASK 0x3fffffff
+#define SQ_THREAD_TRACE_WPTR__WPTR__SHIFT 0x0
+#define SQ_THREAD_TRACE_WPTR__READ_OFFSET_MASK 0xc0000000
+#define SQ_THREAD_TRACE_WPTR__READ_OFFSET__SHIFT 0x1e
+#define SQ_THREAD_TRACE_STATUS__FINISH_PENDING_MASK 0x3ff
+#define SQ_THREAD_TRACE_STATUS__FINISH_PENDING__SHIFT 0x0
+#define SQ_THREAD_TRACE_STATUS__FINISH_DONE_MASK 0x3ff0000
+#define SQ_THREAD_TRACE_STATUS__FINISH_DONE__SHIFT 0x10
+#define SQ_THREAD_TRACE_STATUS__NEW_BUF_MASK 0x20000000
+#define SQ_THREAD_TRACE_STATUS__NEW_BUF__SHIFT 0x1d
+#define SQ_THREAD_TRACE_STATUS__BUSY_MASK 0x40000000
+#define SQ_THREAD_TRACE_STATUS__BUSY__SHIFT 0x1e
+#define SQ_THREAD_TRACE_STATUS__FULL_MASK 0x80000000
+#define SQ_THREAD_TRACE_STATUS__FULL__SHIFT 0x1f
+#define SQ_THREAD_TRACE_CNTR__CNTR_MASK 0xffffffff
+#define SQ_THREAD_TRACE_CNTR__CNTR__SHIFT 0x0
+#define SQ_THREAD_TRACE_HIWATER__HIWATER_MASK 0x7
+#define SQ_THREAD_TRACE_HIWATER__HIWATER__SHIFT 0x0
+#define SQ_LB_CTR_CTRL__START_MASK 0x1
+#define SQ_LB_CTR_CTRL__START__SHIFT 0x0
+#define SQ_LB_CTR_CTRL__LOAD_MASK 0x2
+#define SQ_LB_CTR_CTRL__LOAD__SHIFT 0x1
+#define SQ_LB_CTR_CTRL__CLEAR_MASK 0x4
+#define SQ_LB_CTR_CTRL__CLEAR__SHIFT 0x2
+#define SQ_LB_DATA_ALU_CYCLES__DATA_MASK 0xffffffff
+#define SQ_LB_DATA_ALU_CYCLES__DATA__SHIFT 0x0
+#define SQ_LB_DATA_TEX_CYCLES__DATA_MASK 0xffffffff
+#define SQ_LB_DATA_TEX_CYCLES__DATA__SHIFT 0x0
+#define SQ_LB_DATA_ALU_STALLS__DATA_MASK 0xffffffff
+#define SQ_LB_DATA_ALU_STALLS__DATA__SHIFT 0x0
+#define SQ_LB_DATA_TEX_STALLS__DATA_MASK 0xffffffff
+#define SQ_LB_DATA_TEX_STALLS__DATA__SHIFT 0x0
+#define SQC_EDC_CNT__INST_SEC_MASK 0xff
+#define SQC_EDC_CNT__INST_SEC__SHIFT 0x0
+#define SQC_EDC_CNT__INST_DED_MASK 0xff00
+#define SQC_EDC_CNT__INST_DED__SHIFT 0x8
+#define SQC_EDC_CNT__DATA_SEC_MASK 0xff0000
+#define SQC_EDC_CNT__DATA_SEC__SHIFT 0x10
+#define SQC_EDC_CNT__DATA_DED_MASK 0xff000000
+#define SQC_EDC_CNT__DATA_DED__SHIFT 0x18
+#define SQ_EDC_SEC_CNT__LDS_SEC_MASK 0xff
+#define SQ_EDC_SEC_CNT__LDS_SEC__SHIFT 0x0
+#define SQ_EDC_SEC_CNT__SGPR_SEC_MASK 0xff00
+#define SQ_EDC_SEC_CNT__SGPR_SEC__SHIFT 0x8
+#define SQ_EDC_SEC_CNT__VGPR_SEC_MASK 0xff0000
+#define SQ_EDC_SEC_CNT__VGPR_SEC__SHIFT 0x10
+#define SQ_EDC_DED_CNT__LDS_DED_MASK 0xff
+#define SQ_EDC_DED_CNT__LDS_DED__SHIFT 0x0
+#define SQ_EDC_DED_CNT__SGPR_DED_MASK 0xff00
+#define SQ_EDC_DED_CNT__SGPR_DED__SHIFT 0x8
+#define SQ_EDC_DED_CNT__VGPR_DED_MASK 0xff0000
+#define SQ_EDC_DED_CNT__VGPR_DED__SHIFT 0x10
+#define SQ_EDC_INFO__WAVE_ID_MASK 0xf
+#define SQ_EDC_INFO__WAVE_ID__SHIFT 0x0
+#define SQ_EDC_INFO__SIMD_ID_MASK 0x30
+#define SQ_EDC_INFO__SIMD_ID__SHIFT 0x4
+#define SQ_EDC_INFO__SOURCE_MASK 0x1c0
+#define SQ_EDC_INFO__SOURCE__SHIFT 0x6
+#define SQ_EDC_INFO__VM_ID_MASK 0x1e00
+#define SQ_EDC_INFO__VM_ID__SHIFT 0x9
+#define SQ_BUF_RSRC_WORD0__BASE_ADDRESS_MASK 0xffffffff
+#define SQ_BUF_RSRC_WORD0__BASE_ADDRESS__SHIFT 0x0
+#define SQ_BUF_RSRC_WORD1__BASE_ADDRESS_HI_MASK 0xffff
+#define SQ_BUF_RSRC_WORD1__BASE_ADDRESS_HI__SHIFT 0x0
+#define SQ_BUF_RSRC_WORD1__STRIDE_MASK 0x3fff0000
+#define SQ_BUF_RSRC_WORD1__STRIDE__SHIFT 0x10
+#define SQ_BUF_RSRC_WORD1__CACHE_SWIZZLE_MASK 0x40000000
+#define SQ_BUF_RSRC_WORD1__CACHE_SWIZZLE__SHIFT 0x1e
+#define SQ_BUF_RSRC_WORD1__SWIZZLE_ENABLE_MASK 0x80000000
+#define SQ_BUF_RSRC_WORD1__SWIZZLE_ENABLE__SHIFT 0x1f
+#define SQ_BUF_RSRC_WORD2__NUM_RECORDS_MASK 0xffffffff
+#define SQ_BUF_RSRC_WORD2__NUM_RECORDS__SHIFT 0x0
+#define SQ_BUF_RSRC_WORD3__DST_SEL_X_MASK 0x7
+#define SQ_BUF_RSRC_WORD3__DST_SEL_X__SHIFT 0x0
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Y_MASK 0x38
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Y__SHIFT 0x3
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Z_MASK 0x1c0
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Z__SHIFT 0x6
+#define SQ_BUF_RSRC_WORD3__DST_SEL_W_MASK 0xe00
+#define SQ_BUF_RSRC_WORD3__DST_SEL_W__SHIFT 0x9
+#define SQ_BUF_RSRC_WORD3__NUM_FORMAT_MASK 0x7000
+#define SQ_BUF_RSRC_WORD3__NUM_FORMAT__SHIFT 0xc
+#define SQ_BUF_RSRC_WORD3__DATA_FORMAT_MASK 0x78000
+#define SQ_BUF_RSRC_WORD3__DATA_FORMAT__SHIFT 0xf
+#define SQ_BUF_RSRC_WORD3__ELEMENT_SIZE_MASK 0x180000
+#define SQ_BUF_RSRC_WORD3__ELEMENT_SIZE__SHIFT 0x13
+#define SQ_BUF_RSRC_WORD3__INDEX_STRIDE_MASK 0x600000
+#define SQ_BUF_RSRC_WORD3__INDEX_STRIDE__SHIFT 0x15
+#define SQ_BUF_RSRC_WORD3__ADD_TID_ENABLE_MASK 0x800000
+#define SQ_BUF_RSRC_WORD3__ADD_TID_ENABLE__SHIFT 0x17
+#define SQ_BUF_RSRC_WORD3__ATC_MASK 0x1000000
+#define SQ_BUF_RSRC_WORD3__ATC__SHIFT 0x18
+#define SQ_BUF_RSRC_WORD3__HASH_ENABLE_MASK 0x2000000
+#define SQ_BUF_RSRC_WORD3__HASH_ENABLE__SHIFT 0x19
+#define SQ_BUF_RSRC_WORD3__HEAP_MASK 0x4000000
+#define SQ_BUF_RSRC_WORD3__HEAP__SHIFT 0x1a
+#define SQ_BUF_RSRC_WORD3__MTYPE_MASK 0x38000000
+#define SQ_BUF_RSRC_WORD3__MTYPE__SHIFT 0x1b
+#define SQ_BUF_RSRC_WORD3__TYPE_MASK 0xc0000000
+#define SQ_BUF_RSRC_WORD3__TYPE__SHIFT 0x1e
+#define SQ_IMG_RSRC_WORD0__BASE_ADDRESS_MASK 0xffffffff
+#define SQ_IMG_RSRC_WORD0__BASE_ADDRESS__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD1__BASE_ADDRESS_HI_MASK 0xff
+#define SQ_IMG_RSRC_WORD1__BASE_ADDRESS_HI__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD1__MIN_LOD_MASK 0xfff00
+#define SQ_IMG_RSRC_WORD1__MIN_LOD__SHIFT 0x8
+#define SQ_IMG_RSRC_WORD1__DATA_FORMAT_MASK 0x3f00000
+#define SQ_IMG_RSRC_WORD1__DATA_FORMAT__SHIFT 0x14
+#define SQ_IMG_RSRC_WORD1__NUM_FORMAT_MASK 0x3c000000
+#define SQ_IMG_RSRC_WORD1__NUM_FORMAT__SHIFT 0x1a
+#define SQ_IMG_RSRC_WORD1__MTYPE_MASK 0xc0000000
+#define SQ_IMG_RSRC_WORD1__MTYPE__SHIFT 0x1e
+#define SQ_IMG_RSRC_WORD2__WIDTH_MASK 0x3fff
+#define SQ_IMG_RSRC_WORD2__WIDTH__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD2__HEIGHT_MASK 0xfffc000
+#define SQ_IMG_RSRC_WORD2__HEIGHT__SHIFT 0xe
+#define SQ_IMG_RSRC_WORD2__PERF_MOD_MASK 0x70000000
+#define SQ_IMG_RSRC_WORD2__PERF_MOD__SHIFT 0x1c
+#define SQ_IMG_RSRC_WORD2__INTERLACED_MASK 0x80000000
+#define SQ_IMG_RSRC_WORD2__INTERLACED__SHIFT 0x1f
+#define SQ_IMG_RSRC_WORD3__DST_SEL_X_MASK 0x7
+#define SQ_IMG_RSRC_WORD3__DST_SEL_X__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Y_MASK 0x38
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Y__SHIFT 0x3
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Z_MASK 0x1c0
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Z__SHIFT 0x6
+#define SQ_IMG_RSRC_WORD3__DST_SEL_W_MASK 0xe00
+#define SQ_IMG_RSRC_WORD3__DST_SEL_W__SHIFT 0x9
+#define SQ_IMG_RSRC_WORD3__BASE_LEVEL_MASK 0xf000
+#define SQ_IMG_RSRC_WORD3__BASE_LEVEL__SHIFT 0xc
+#define SQ_IMG_RSRC_WORD3__LAST_LEVEL_MASK 0xf0000
+#define SQ_IMG_RSRC_WORD3__LAST_LEVEL__SHIFT 0x10
+#define SQ_IMG_RSRC_WORD3__TILING_INDEX_MASK 0x1f00000
+#define SQ_IMG_RSRC_WORD3__TILING_INDEX__SHIFT 0x14
+#define SQ_IMG_RSRC_WORD3__POW2_PAD_MASK 0x2000000
+#define SQ_IMG_RSRC_WORD3__POW2_PAD__SHIFT 0x19
+#define SQ_IMG_RSRC_WORD3__MTYPE_MASK 0x4000000
+#define SQ_IMG_RSRC_WORD3__MTYPE__SHIFT 0x1a
+#define SQ_IMG_RSRC_WORD3__ATC_MASK 0x8000000
+#define SQ_IMG_RSRC_WORD3__ATC__SHIFT 0x1b
+#define SQ_IMG_RSRC_WORD3__TYPE_MASK 0xf0000000
+#define SQ_IMG_RSRC_WORD3__TYPE__SHIFT 0x1c
+#define SQ_IMG_RSRC_WORD4__DEPTH_MASK 0x1fff
+#define SQ_IMG_RSRC_WORD4__DEPTH__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD4__PITCH_MASK 0x7ffe000
+#define SQ_IMG_RSRC_WORD4__PITCH__SHIFT 0xd
+#define SQ_IMG_RSRC_WORD5__BASE_ARRAY_MASK 0x1fff
+#define SQ_IMG_RSRC_WORD5__BASE_ARRAY__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD5__LAST_ARRAY_MASK 0x3ffe000
+#define SQ_IMG_RSRC_WORD5__LAST_ARRAY__SHIFT 0xd
+#define SQ_IMG_RSRC_WORD6__MIN_LOD_WARN_MASK 0xfff
+#define SQ_IMG_RSRC_WORD6__MIN_LOD_WARN__SHIFT 0x0
+#define SQ_IMG_RSRC_WORD6__COUNTER_BANK_ID_MASK 0xff000
+#define SQ_IMG_RSRC_WORD6__COUNTER_BANK_ID__SHIFT 0xc
+#define SQ_IMG_RSRC_WORD6__LOD_HDW_CNT_EN_MASK 0x100000
+#define SQ_IMG_RSRC_WORD6__LOD_HDW_CNT_EN__SHIFT 0x14
+#define SQ_IMG_RSRC_WORD6__COMPRESSION_EN_MASK 0x200000
+#define SQ_IMG_RSRC_WORD6__COMPRESSION_EN__SHIFT 0x15
+#define SQ_IMG_RSRC_WORD6__ALPHA_IS_ON_MSB_MASK 0x400000
+#define SQ_IMG_RSRC_WORD6__ALPHA_IS_ON_MSB__SHIFT 0x16
+#define SQ_IMG_RSRC_WORD6__COLOR_TRANSFORM_MASK 0x800000
+#define SQ_IMG_RSRC_WORD6__COLOR_TRANSFORM__SHIFT 0x17
+#define SQ_IMG_RSRC_WORD6__LOST_ALPHA_BITS_MASK 0xf000000
+#define SQ_IMG_RSRC_WORD6__LOST_ALPHA_BITS__SHIFT 0x18
+#define SQ_IMG_RSRC_WORD6__LOST_COLOR_BITS_MASK 0xf0000000
+#define SQ_IMG_RSRC_WORD6__LOST_COLOR_BITS__SHIFT 0x1c
+#define SQ_IMG_RSRC_WORD7__META_DATA_ADDRESS_MASK 0xffffffff
+#define SQ_IMG_RSRC_WORD7__META_DATA_ADDRESS__SHIFT 0x0
+#define SQ_IMG_SAMP_WORD0__CLAMP_X_MASK 0x7
+#define SQ_IMG_SAMP_WORD0__CLAMP_X__SHIFT 0x0
+#define SQ_IMG_SAMP_WORD0__CLAMP_Y_MASK 0x38
+#define SQ_IMG_SAMP_WORD0__CLAMP_Y__SHIFT 0x3
+#define SQ_IMG_SAMP_WORD0__CLAMP_Z_MASK 0x1c0
+#define SQ_IMG_SAMP_WORD0__CLAMP_Z__SHIFT 0x6
+#define SQ_IMG_SAMP_WORD0__MAX_ANISO_RATIO_MASK 0xe00
+#define SQ_IMG_SAMP_WORD0__MAX_ANISO_RATIO__SHIFT 0x9
+#define SQ_IMG_SAMP_WORD0__DEPTH_COMPARE_FUNC_MASK 0x7000
+#define SQ_IMG_SAMP_WORD0__DEPTH_COMPARE_FUNC__SHIFT 0xc
+#define SQ_IMG_SAMP_WORD0__FORCE_UNNORMALIZED_MASK 0x8000
+#define SQ_IMG_SAMP_WORD0__FORCE_UNNORMALIZED__SHIFT 0xf
+#define SQ_IMG_SAMP_WORD0__ANISO_THRESHOLD_MASK 0x70000
+#define SQ_IMG_SAMP_WORD0__ANISO_THRESHOLD__SHIFT 0x10
+#define SQ_IMG_SAMP_WORD0__MC_COORD_TRUNC_MASK 0x80000
+#define SQ_IMG_SAMP_WORD0__MC_COORD_TRUNC__SHIFT 0x13
+#define SQ_IMG_SAMP_WORD0__FORCE_DEGAMMA_MASK 0x100000
+#define SQ_IMG_SAMP_WORD0__FORCE_DEGAMMA__SHIFT 0x14
+#define SQ_IMG_SAMP_WORD0__ANISO_BIAS_MASK 0x7e00000
+#define SQ_IMG_SAMP_WORD0__ANISO_BIAS__SHIFT 0x15
+#define SQ_IMG_SAMP_WORD0__TRUNC_COORD_MASK 0x8000000
+#define SQ_IMG_SAMP_WORD0__TRUNC_COORD__SHIFT 0x1b
+#define SQ_IMG_SAMP_WORD0__DISABLE_CUBE_WRAP_MASK 0x10000000
+#define SQ_IMG_SAMP_WORD0__DISABLE_CUBE_WRAP__SHIFT 0x1c
+#define SQ_IMG_SAMP_WORD0__FILTER_MODE_MASK 0x60000000
+#define SQ_IMG_SAMP_WORD0__FILTER_MODE__SHIFT 0x1d
+#define SQ_IMG_SAMP_WORD0__COMPAT_MODE_MASK 0x80000000
+#define SQ_IMG_SAMP_WORD0__COMPAT_MODE__SHIFT 0x1f
+#define SQ_IMG_SAMP_WORD1__MIN_LOD_MASK 0xfff
+#define SQ_IMG_SAMP_WORD1__MIN_LOD__SHIFT 0x0
+#define SQ_IMG_SAMP_WORD1__MAX_LOD_MASK 0xfff000
+#define SQ_IMG_SAMP_WORD1__MAX_LOD__SHIFT 0xc
+#define SQ_IMG_SAMP_WORD1__PERF_MIP_MASK 0xf000000
+#define SQ_IMG_SAMP_WORD1__PERF_MIP__SHIFT 0x18
+#define SQ_IMG_SAMP_WORD1__PERF_Z_MASK 0xf0000000
+#define SQ_IMG_SAMP_WORD1__PERF_Z__SHIFT 0x1c
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_MASK 0x3fff
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS__SHIFT 0x0
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_SEC_MASK 0xfc000
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_SEC__SHIFT 0xe
+#define SQ_IMG_SAMP_WORD2__XY_MAG_FILTER_MASK 0x300000
+#define SQ_IMG_SAMP_WORD2__XY_MAG_FILTER__SHIFT 0x14
+#define SQ_IMG_SAMP_WORD2__XY_MIN_FILTER_MASK 0xc00000
+#define SQ_IMG_SAMP_WORD2__XY_MIN_FILTER__SHIFT 0x16
+#define SQ_IMG_SAMP_WORD2__Z_FILTER_MASK 0x3000000
+#define SQ_IMG_SAMP_WORD2__Z_FILTER__SHIFT 0x18
+#define SQ_IMG_SAMP_WORD2__MIP_FILTER_MASK 0xc000000
+#define SQ_IMG_SAMP_WORD2__MIP_FILTER__SHIFT 0x1a
+#define SQ_IMG_SAMP_WORD2__MIP_POINT_PRECLAMP_MASK 0x10000000
+#define SQ_IMG_SAMP_WORD2__MIP_POINT_PRECLAMP__SHIFT 0x1c
+#define SQ_IMG_SAMP_WORD2__DISABLE_LSB_CEIL_MASK 0x20000000
+#define SQ_IMG_SAMP_WORD2__DISABLE_LSB_CEIL__SHIFT 0x1d
+#define SQ_IMG_SAMP_WORD2__FILTER_PREC_FIX_MASK 0x40000000
+#define SQ_IMG_SAMP_WORD2__FILTER_PREC_FIX__SHIFT 0x1e
+#define SQ_IMG_SAMP_WORD2__ANISO_OVERRIDE_MASK 0x80000000
+#define SQ_IMG_SAMP_WORD2__ANISO_OVERRIDE__SHIFT 0x1f
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_PTR_MASK 0xfff
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_PTR__SHIFT 0x0
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_TYPE_MASK 0xc0000000
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_TYPE__SHIFT 0x1e
+#define SQ_FLAT_SCRATCH_WORD0__SIZE_MASK 0x7ffff
+#define SQ_FLAT_SCRATCH_WORD0__SIZE__SHIFT 0x0
+#define SQ_FLAT_SCRATCH_WORD1__OFFSET_MASK 0xffffff
+#define SQ_FLAT_SCRATCH_WORD1__OFFSET__SHIFT 0x0
+#define SQ_M0_GPR_IDX_WORD__INDEX_MASK 0xff
+#define SQ_M0_GPR_IDX_WORD__INDEX__SHIFT 0x0
+#define SQ_M0_GPR_IDX_WORD__VSRC0_REL_MASK 0x1000
+#define SQ_M0_GPR_IDX_WORD__VSRC0_REL__SHIFT 0xc
+#define SQ_M0_GPR_IDX_WORD__VSRC1_REL_MASK 0x2000
+#define SQ_M0_GPR_IDX_WORD__VSRC1_REL__SHIFT 0xd
+#define SQ_M0_GPR_IDX_WORD__VSRC2_REL_MASK 0x4000
+#define SQ_M0_GPR_IDX_WORD__VSRC2_REL__SHIFT 0xe
+#define SQ_M0_GPR_IDX_WORD__VDST_REL_MASK 0x8000
+#define SQ_M0_GPR_IDX_WORD__VDST_REL__SHIFT 0xf
+#define SQ_IND_INDEX__WAVE_ID_MASK 0xf
+#define SQ_IND_INDEX__WAVE_ID__SHIFT 0x0
+#define SQ_IND_INDEX__SIMD_ID_MASK 0x30
+#define SQ_IND_INDEX__SIMD_ID__SHIFT 0x4
+#define SQ_IND_INDEX__THREAD_ID_MASK 0xfc0
+#define SQ_IND_INDEX__THREAD_ID__SHIFT 0x6
+#define SQ_IND_INDEX__AUTO_INCR_MASK 0x1000
+#define SQ_IND_INDEX__AUTO_INCR__SHIFT 0xc
+#define SQ_IND_INDEX__FORCE_READ_MASK 0x2000
+#define SQ_IND_INDEX__FORCE_READ__SHIFT 0xd
+#define SQ_IND_INDEX__READ_TIMEOUT_MASK 0x4000
+#define SQ_IND_INDEX__READ_TIMEOUT__SHIFT 0xe
+#define SQ_IND_INDEX__UNINDEXED_MASK 0x8000
+#define SQ_IND_INDEX__UNINDEXED__SHIFT 0xf
+#define SQ_IND_INDEX__INDEX_MASK 0xffff0000
+#define SQ_IND_INDEX__INDEX__SHIFT 0x10
+#define SQ_CMD__CMD_MASK 0x7
+#define SQ_CMD__CMD__SHIFT 0x0
+#define SQ_CMD__MODE_MASK 0x70
+#define SQ_CMD__MODE__SHIFT 0x4
+#define SQ_CMD__CHECK_VMID_MASK 0x80
+#define SQ_CMD__CHECK_VMID__SHIFT 0x7
+#define SQ_CMD__DATA_MASK 0x700
+#define SQ_CMD__DATA__SHIFT 0x8
+#define SQ_CMD__WAVE_ID_MASK 0xf0000
+#define SQ_CMD__WAVE_ID__SHIFT 0x10
+#define SQ_CMD__SIMD_ID_MASK 0x300000
+#define SQ_CMD__SIMD_ID__SHIFT 0x14
+#define SQ_CMD__QUEUE_ID_MASK 0x7000000
+#define SQ_CMD__QUEUE_ID__SHIFT 0x18
+#define SQ_CMD__VM_ID_MASK 0xf0000000
+#define SQ_CMD__VM_ID__SHIFT 0x1c
+#define SQ_IND_DATA__DATA_MASK 0xffffffff
+#define SQ_IND_DATA__DATA__SHIFT 0x0
+#define SQ_REG_TIMESTAMP__TIMESTAMP_MASK 0xff
+#define SQ_REG_TIMESTAMP__TIMESTAMP__SHIFT 0x0
+#define SQ_CMD_TIMESTAMP__TIMESTAMP_MASK 0xff
+#define SQ_CMD_TIMESTAMP__TIMESTAMP__SHIFT 0x0
+#define SQ_HV_VMID_CTRL__DEFAULT_VMID_MASK 0xf
+#define SQ_HV_VMID_CTRL__DEFAULT_VMID__SHIFT 0x0
+#define SQ_HV_VMID_CTRL__ALLOWED_VMID_MASK_MASK 0xffff0
+#define SQ_HV_VMID_CTRL__ALLOWED_VMID_MASK__SHIFT 0x4
+#define SQ_WAVE_INST_DW0__INST_DW0_MASK 0xffffffff
+#define SQ_WAVE_INST_DW0__INST_DW0__SHIFT 0x0
+#define SQ_WAVE_INST_DW1__INST_DW1_MASK 0xffffffff
+#define SQ_WAVE_INST_DW1__INST_DW1__SHIFT 0x0
+#define SQ_WAVE_PC_LO__PC_LO_MASK 0xffffffff
+#define SQ_WAVE_PC_LO__PC_LO__SHIFT 0x0
+#define SQ_WAVE_PC_HI__PC_HI_MASK 0xffff
+#define SQ_WAVE_PC_HI__PC_HI__SHIFT 0x0
+#define SQ_WAVE_IB_DBG0__IBUF_ST_MASK 0x7
+#define SQ_WAVE_IB_DBG0__IBUF_ST__SHIFT 0x0
+#define SQ_WAVE_IB_DBG0__PC_INVALID_MASK 0x8
+#define SQ_WAVE_IB_DBG0__PC_INVALID__SHIFT 0x3
+#define SQ_WAVE_IB_DBG0__NEED_NEXT_DW_MASK 0x10
+#define SQ_WAVE_IB_DBG0__NEED_NEXT_DW__SHIFT 0x4
+#define SQ_WAVE_IB_DBG0__NO_PREFETCH_CNT_MASK 0xe0
+#define SQ_WAVE_IB_DBG0__NO_PREFETCH_CNT__SHIFT 0x5
+#define SQ_WAVE_IB_DBG0__IBUF_RPTR_MASK 0x300
+#define SQ_WAVE_IB_DBG0__IBUF_RPTR__SHIFT 0x8
+#define SQ_WAVE_IB_DBG0__IBUF_WPTR_MASK 0xc00
+#define SQ_WAVE_IB_DBG0__IBUF_WPTR__SHIFT 0xa
+#define SQ_WAVE_IB_DBG0__INST_STR_ST_MASK 0xf0000
+#define SQ_WAVE_IB_DBG0__INST_STR_ST__SHIFT 0x10
+#define SQ_WAVE_IB_DBG0__MISC_CNT_MASK 0xf00000
+#define SQ_WAVE_IB_DBG0__MISC_CNT__SHIFT 0x14
+#define SQ_WAVE_IB_DBG0__ECC_ST_MASK 0x3000000
+#define SQ_WAVE_IB_DBG0__ECC_ST__SHIFT 0x18
+#define SQ_WAVE_IB_DBG0__IS_HYB_MASK 0x4000000
+#define SQ_WAVE_IB_DBG0__IS_HYB__SHIFT 0x1a
+#define SQ_WAVE_IB_DBG0__HYB_CNT_MASK 0x18000000
+#define SQ_WAVE_IB_DBG0__HYB_CNT__SHIFT 0x1b
+#define SQ_WAVE_IB_DBG0__KILL_MASK 0x20000000
+#define SQ_WAVE_IB_DBG0__KILL__SHIFT 0x1d
+#define SQ_WAVE_IB_DBG0__NEED_KILL_IFETCH_MASK 0x40000000
+#define SQ_WAVE_IB_DBG0__NEED_KILL_IFETCH__SHIFT 0x1e
+#define SQ_WAVE_IB_DBG1__IXNACK_MASK 0x1
+#define SQ_WAVE_IB_DBG1__IXNACK__SHIFT 0x0
+#define SQ_WAVE_IB_DBG1__XNACK_MASK 0x2
+#define SQ_WAVE_IB_DBG1__XNACK__SHIFT 0x1
+#define SQ_WAVE_IB_DBG1__TA_NEED_RESET_MASK 0x4
+#define SQ_WAVE_IB_DBG1__TA_NEED_RESET__SHIFT 0x2
+#define SQ_WAVE_IB_DBG1__XCNT_MASK 0xf0
+#define SQ_WAVE_IB_DBG1__XCNT__SHIFT 0x4
+#define SQ_WAVE_IB_DBG1__QCNT_MASK 0xf00
+#define SQ_WAVE_IB_DBG1__QCNT__SHIFT 0x8
+#define SQ_WAVE_EXEC_LO__EXEC_LO_MASK 0xffffffff
+#define SQ_WAVE_EXEC_LO__EXEC_LO__SHIFT 0x0
+#define SQ_WAVE_EXEC_HI__EXEC_HI_MASK 0xffffffff
+#define SQ_WAVE_EXEC_HI__EXEC_HI__SHIFT 0x0
+#define SQ_WAVE_STATUS__SCC_MASK 0x1
+#define SQ_WAVE_STATUS__SCC__SHIFT 0x0
+#define SQ_WAVE_STATUS__SPI_PRIO_MASK 0x6
+#define SQ_WAVE_STATUS__SPI_PRIO__SHIFT 0x1
+#define SQ_WAVE_STATUS__USER_PRIO_MASK 0x18
+#define SQ_WAVE_STATUS__USER_PRIO__SHIFT 0x3
+#define SQ_WAVE_STATUS__PRIV_MASK 0x20
+#define SQ_WAVE_STATUS__PRIV__SHIFT 0x5
+#define SQ_WAVE_STATUS__TRAP_EN_MASK 0x40
+#define SQ_WAVE_STATUS__TRAP_EN__SHIFT 0x6
+#define SQ_WAVE_STATUS__TTRACE_EN_MASK 0x80
+#define SQ_WAVE_STATUS__TTRACE_EN__SHIFT 0x7
+#define SQ_WAVE_STATUS__EXPORT_RDY_MASK 0x100
+#define SQ_WAVE_STATUS__EXPORT_RDY__SHIFT 0x8
+#define SQ_WAVE_STATUS__EXECZ_MASK 0x200
+#define SQ_WAVE_STATUS__EXECZ__SHIFT 0x9
+#define SQ_WAVE_STATUS__VCCZ_MASK 0x400
+#define SQ_WAVE_STATUS__VCCZ__SHIFT 0xa
+#define SQ_WAVE_STATUS__IN_TG_MASK 0x800
+#define SQ_WAVE_STATUS__IN_TG__SHIFT 0xb
+#define SQ_WAVE_STATUS__IN_BARRIER_MASK 0x1000
+#define SQ_WAVE_STATUS__IN_BARRIER__SHIFT 0xc
+#define SQ_WAVE_STATUS__HALT_MASK 0x2000
+#define SQ_WAVE_STATUS__HALT__SHIFT 0xd
+#define SQ_WAVE_STATUS__TRAP_MASK 0x4000
+#define SQ_WAVE_STATUS__TRAP__SHIFT 0xe
+#define SQ_WAVE_STATUS__TTRACE_CU_EN_MASK 0x8000
+#define SQ_WAVE_STATUS__TTRACE_CU_EN__SHIFT 0xf
+#define SQ_WAVE_STATUS__VALID_MASK 0x10000
+#define SQ_WAVE_STATUS__VALID__SHIFT 0x10
+#define SQ_WAVE_STATUS__ECC_ERR_MASK 0x20000
+#define SQ_WAVE_STATUS__ECC_ERR__SHIFT 0x11
+#define SQ_WAVE_STATUS__SKIP_EXPORT_MASK 0x40000
+#define SQ_WAVE_STATUS__SKIP_EXPORT__SHIFT 0x12
+#define SQ_WAVE_STATUS__PERF_EN_MASK 0x80000
+#define SQ_WAVE_STATUS__PERF_EN__SHIFT 0x13
+#define SQ_WAVE_STATUS__COND_DBG_USER_MASK 0x100000
+#define SQ_WAVE_STATUS__COND_DBG_USER__SHIFT 0x14
+#define SQ_WAVE_STATUS__COND_DBG_SYS_MASK 0x200000
+#define SQ_WAVE_STATUS__COND_DBG_SYS__SHIFT 0x15
+#define SQ_WAVE_STATUS__ALLOW_REPLAY_MASK 0x400000
+#define SQ_WAVE_STATUS__ALLOW_REPLAY__SHIFT 0x16
+#define SQ_WAVE_STATUS__INST_ATC_MASK 0x800000
+#define SQ_WAVE_STATUS__INST_ATC__SHIFT 0x17
+#define SQ_WAVE_STATUS__MUST_EXPORT_MASK 0x8000000
+#define SQ_WAVE_STATUS__MUST_EXPORT__SHIFT 0x1b
+#define SQ_WAVE_MODE__FP_ROUND_MASK 0xf
+#define SQ_WAVE_MODE__FP_ROUND__SHIFT 0x0
+#define SQ_WAVE_MODE__FP_DENORM_MASK 0xf0
+#define SQ_WAVE_MODE__FP_DENORM__SHIFT 0x4
+#define SQ_WAVE_MODE__DX10_CLAMP_MASK 0x100
+#define SQ_WAVE_MODE__DX10_CLAMP__SHIFT 0x8
+#define SQ_WAVE_MODE__IEEE_MASK 0x200
+#define SQ_WAVE_MODE__IEEE__SHIFT 0x9
+#define SQ_WAVE_MODE__LOD_CLAMPED_MASK 0x400
+#define SQ_WAVE_MODE__LOD_CLAMPED__SHIFT 0xa
+#define SQ_WAVE_MODE__DEBUG_EN_MASK 0x800
+#define SQ_WAVE_MODE__DEBUG_EN__SHIFT 0xb
+#define SQ_WAVE_MODE__EXCP_EN_MASK 0x1ff000
+#define SQ_WAVE_MODE__EXCP_EN__SHIFT 0xc
+#define SQ_WAVE_MODE__GPR_IDX_EN_MASK 0x8000000
+#define SQ_WAVE_MODE__GPR_IDX_EN__SHIFT 0x1b
+#define SQ_WAVE_MODE__VSKIP_MASK 0x10000000
+#define SQ_WAVE_MODE__VSKIP__SHIFT 0x1c
+#define SQ_WAVE_MODE__CSP_MASK 0xe0000000
+#define SQ_WAVE_MODE__CSP__SHIFT 0x1d
+#define SQ_WAVE_TRAPSTS__EXCP_MASK 0x1ff
+#define SQ_WAVE_TRAPSTS__EXCP__SHIFT 0x0
+#define SQ_WAVE_TRAPSTS__SAVECTX_MASK 0x400
+#define SQ_WAVE_TRAPSTS__SAVECTX__SHIFT 0xa
+#define SQ_WAVE_TRAPSTS__EXCP_CYCLE_MASK 0x3f0000
+#define SQ_WAVE_TRAPSTS__EXCP_CYCLE__SHIFT 0x10
+#define SQ_WAVE_TRAPSTS__DP_RATE_MASK 0xe0000000
+#define SQ_WAVE_TRAPSTS__DP_RATE__SHIFT 0x1d
+#define SQ_WAVE_HW_ID__WAVE_ID_MASK 0xf
+#define SQ_WAVE_HW_ID__WAVE_ID__SHIFT 0x0
+#define SQ_WAVE_HW_ID__SIMD_ID_MASK 0x30
+#define SQ_WAVE_HW_ID__SIMD_ID__SHIFT 0x4
+#define SQ_WAVE_HW_ID__PIPE_ID_MASK 0xc0
+#define SQ_WAVE_HW_ID__PIPE_ID__SHIFT 0x6
+#define SQ_WAVE_HW_ID__CU_ID_MASK 0xf00
+#define SQ_WAVE_HW_ID__CU_ID__SHIFT 0x8
+#define SQ_WAVE_HW_ID__SH_ID_MASK 0x1000
+#define SQ_WAVE_HW_ID__SH_ID__SHIFT 0xc
+#define SQ_WAVE_HW_ID__SE_ID_MASK 0x6000
+#define SQ_WAVE_HW_ID__SE_ID__SHIFT 0xd
+#define SQ_WAVE_HW_ID__TG_ID_MASK 0xf0000
+#define SQ_WAVE_HW_ID__TG_ID__SHIFT 0x10
+#define SQ_WAVE_HW_ID__VM_ID_MASK 0xf00000
+#define SQ_WAVE_HW_ID__VM_ID__SHIFT 0x14
+#define SQ_WAVE_HW_ID__QUEUE_ID_MASK 0x7000000
+#define SQ_WAVE_HW_ID__QUEUE_ID__SHIFT 0x18
+#define SQ_WAVE_HW_ID__STATE_ID_MASK 0x38000000
+#define SQ_WAVE_HW_ID__STATE_ID__SHIFT 0x1b
+#define SQ_WAVE_HW_ID__ME_ID_MASK 0xc0000000
+#define SQ_WAVE_HW_ID__ME_ID__SHIFT 0x1e
+#define SQ_WAVE_GPR_ALLOC__VGPR_BASE_MASK 0x3f
+#define SQ_WAVE_GPR_ALLOC__VGPR_BASE__SHIFT 0x0
+#define SQ_WAVE_GPR_ALLOC__VGPR_SIZE_MASK 0x3f00
+#define SQ_WAVE_GPR_ALLOC__VGPR_SIZE__SHIFT 0x8
+#define SQ_WAVE_GPR_ALLOC__SGPR_BASE_MASK 0x3f0000
+#define SQ_WAVE_GPR_ALLOC__SGPR_BASE__SHIFT 0x10
+#define SQ_WAVE_GPR_ALLOC__SGPR_SIZE_MASK 0xf000000
+#define SQ_WAVE_GPR_ALLOC__SGPR_SIZE__SHIFT 0x18
+#define SQ_WAVE_LDS_ALLOC__LDS_BASE_MASK 0xff
+#define SQ_WAVE_LDS_ALLOC__LDS_BASE__SHIFT 0x0
+#define SQ_WAVE_LDS_ALLOC__LDS_SIZE_MASK 0x1ff000
+#define SQ_WAVE_LDS_ALLOC__LDS_SIZE__SHIFT 0xc
+#define SQ_WAVE_IB_STS__VM_CNT_MASK 0xf
+#define SQ_WAVE_IB_STS__VM_CNT__SHIFT 0x0
+#define SQ_WAVE_IB_STS__EXP_CNT_MASK 0x70
+#define SQ_WAVE_IB_STS__EXP_CNT__SHIFT 0x4
+#define SQ_WAVE_IB_STS__LGKM_CNT_MASK 0xf00
+#define SQ_WAVE_IB_STS__LGKM_CNT__SHIFT 0x8
+#define SQ_WAVE_IB_STS__VALU_CNT_MASK 0x7000
+#define SQ_WAVE_IB_STS__VALU_CNT__SHIFT 0xc
+#define SQ_WAVE_IB_STS__FIRST_REPLAY_MASK 0x8000
+#define SQ_WAVE_IB_STS__FIRST_REPLAY__SHIFT 0xf
+#define SQ_WAVE_IB_STS__RCNT_MASK 0xf0000
+#define SQ_WAVE_IB_STS__RCNT__SHIFT 0x10
+#define SQ_WAVE_M0__M0_MASK 0xffffffff
+#define SQ_WAVE_M0__M0__SHIFT 0x0
+#define SQ_WAVE_TBA_LO__ADDR_LO_MASK 0xffffffff
+#define SQ_WAVE_TBA_LO__ADDR_LO__SHIFT 0x0
+#define SQ_WAVE_TBA_HI__ADDR_HI_MASK 0xff
+#define SQ_WAVE_TBA_HI__ADDR_HI__SHIFT 0x0
+#define SQ_WAVE_TMA_LO__ADDR_LO_MASK 0xffffffff
+#define SQ_WAVE_TMA_LO__ADDR_LO__SHIFT 0x0
+#define SQ_WAVE_TMA_HI__ADDR_HI_MASK 0xff
+#define SQ_WAVE_TMA_HI__ADDR_HI__SHIFT 0x0
+#define SQ_WAVE_TTMP0__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP0__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP1__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP1__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP2__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP2__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP3__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP3__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP4__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP4__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP5__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP5__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP6__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP6__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP7__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP7__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP8__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP8__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP9__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP9__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP10__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP10__DATA__SHIFT 0x0
+#define SQ_WAVE_TTMP11__DATA_MASK 0xffffffff
+#define SQ_WAVE_TTMP11__DATA__SHIFT 0x0
+#define SQ_DEBUG_STS_GLOBAL__BUSY_MASK 0x1
+#define SQ_DEBUG_STS_GLOBAL__BUSY__SHIFT 0x0
+#define SQ_DEBUG_STS_GLOBAL__INTERRUPT_MSG_BUSY_MASK 0x2
+#define SQ_DEBUG_STS_GLOBAL__INTERRUPT_MSG_BUSY__SHIFT 0x1
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH0_MASK 0xfff0
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH0__SHIFT 0x4
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH1_MASK 0xfff0000
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH1__SHIFT 0x10
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0_MASK 0xff
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0__SHIFT 0x0
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX1_MASK 0xff00
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX1__SHIFT 0x8
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_IMMED_MASK 0xff0000
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_IMMED__SHIFT 0x10
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_HOST_MASK 0xff000000
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_HOST__SHIFT 0x18
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_CMD_MASK 0xf
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_CMD__SHIFT 0x0
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_REG_MASK 0x3f0
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_REG__SHIFT 0x4
+#define SQ_DEBUG_STS_LOCAL__BUSY_MASK 0x1
+#define SQ_DEBUG_STS_LOCAL__BUSY__SHIFT 0x0
+#define SQ_DEBUG_STS_LOCAL__WAVE_LEVEL_MASK 0x3f0
+#define SQ_DEBUG_STS_LOCAL__WAVE_LEVEL__SHIFT 0x4
+#define SQ_DEBUG_CTRL_LOCAL__UNUSED_MASK 0xff
+#define SQ_DEBUG_CTRL_LOCAL__UNUSED__SHIFT 0x0
+#define SH_MEM_BASES__PRIVATE_BASE_MASK 0xffff
+#define SH_MEM_BASES__PRIVATE_BASE__SHIFT 0x0
+#define SH_MEM_BASES__SHARED_BASE_MASK 0xffff0000
+#define SH_MEM_BASES__SHARED_BASE__SHIFT 0x10
+#define SH_MEM_APE1_BASE__BASE_MASK 0xffffffff
+#define SH_MEM_APE1_BASE__BASE__SHIFT 0x0
+#define SH_MEM_APE1_LIMIT__LIMIT_MASK 0xffffffff
+#define SH_MEM_APE1_LIMIT__LIMIT__SHIFT 0x0
+#define SH_MEM_CONFIG__ADDRESS_MODE_MASK 0x3
+#define SH_MEM_CONFIG__ADDRESS_MODE__SHIFT 0x0
+#define SH_MEM_CONFIG__PRIVATE_ATC_MASK 0x4
+#define SH_MEM_CONFIG__PRIVATE_ATC__SHIFT 0x2
+#define SH_MEM_CONFIG__ALIGNMENT_MODE_MASK 0x18
+#define SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT 0x3
+#define SH_MEM_CONFIG__DEFAULT_MTYPE_MASK 0xe0
+#define SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT 0x5
+#define SH_MEM_CONFIG__APE1_MTYPE_MASK 0x700
+#define SH_MEM_CONFIG__APE1_MTYPE__SHIFT 0x8
+#define SH_MEM_CONFIG__APE1_ATC_MASK 0x800
+#define SH_MEM_CONFIG__APE1_ATC__SHIFT 0xb
+#define SQ_THREAD_TRACE_WORD_CMN__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_CMN__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_CMN__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_CMN__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_INST__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_INST__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_INST__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_INST__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_INST__WAVE_ID_MASK 0x1e0
+#define SQ_THREAD_TRACE_WORD_INST__WAVE_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_INST__SIMD_ID_MASK 0x600
+#define SQ_THREAD_TRACE_WORD_INST__SIMD_ID__SHIFT 0x9
+#define SQ_THREAD_TRACE_WORD_INST__INST_TYPE_MASK 0xf800
+#define SQ_THREAD_TRACE_WORD_INST__INST_TYPE__SHIFT 0xb
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__WAVE_ID_MASK 0x1e0
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__WAVE_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__SIMD_ID_MASK 0x600
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__SIMD_ID__SHIFT 0x9
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__PC_LO_MASK 0xffff0000
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__PC_LO__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_INST_PC_2_OF_2__PC_HI_MASK 0xffffff
+#define SQ_THREAD_TRACE_WORD_INST_PC_2_OF_2__PC_HI__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SH_ID_MASK 0x20
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SH_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__CU_ID_MASK 0x3c0
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__CU_ID__SHIFT 0x6
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__WAVE_ID_MASK 0x3c00
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__WAVE_ID__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SIMD_ID_MASK 0xc000
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SIMD_ID__SHIFT 0xe
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__DATA_LO_MASK 0xffff0000
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__DATA_LO__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2__DATA_HI_MASK 0xffff
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2__DATA_HI__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TIME_LO_MASK 0xffff0000
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TIME_LO__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2__TIME_HI_MASK 0xffffffff
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2__TIME_HI__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_WAVE__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_WAVE__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_WAVE__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_WAVE__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_WAVE__SH_ID_MASK 0x20
+#define SQ_THREAD_TRACE_WORD_WAVE__SH_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_WAVE__CU_ID_MASK 0x3c0
+#define SQ_THREAD_TRACE_WORD_WAVE__CU_ID__SHIFT 0x6
+#define SQ_THREAD_TRACE_WORD_WAVE__WAVE_ID_MASK 0x3c00
+#define SQ_THREAD_TRACE_WORD_WAVE__WAVE_ID__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_WAVE__SIMD_ID_MASK 0xc000
+#define SQ_THREAD_TRACE_WORD_WAVE__SIMD_ID__SHIFT 0xe
+#define SQ_THREAD_TRACE_WORD_MISC__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_MISC__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_MISC__TIME_DELTA_MASK 0xff0
+#define SQ_THREAD_TRACE_WORD_MISC__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_MISC__SH_ID_MASK 0x1000
+#define SQ_THREAD_TRACE_WORD_MISC__SH_ID__SHIFT 0xc
+#define SQ_THREAD_TRACE_WORD_MISC__MISC_TOKEN_TYPE_MASK 0xe000
+#define SQ_THREAD_TRACE_WORD_MISC__MISC_TOKEN_TYPE__SHIFT 0xd
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SH_ID_MASK 0x20
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SH_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_WAVE_START__CU_ID_MASK 0x3c0
+#define SQ_THREAD_TRACE_WORD_WAVE_START__CU_ID__SHIFT 0x6
+#define SQ_THREAD_TRACE_WORD_WAVE_START__WAVE_ID_MASK 0x3c00
+#define SQ_THREAD_TRACE_WORD_WAVE_START__WAVE_ID__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SIMD_ID_MASK 0xc000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SIMD_ID__SHIFT 0xe
+#define SQ_THREAD_TRACE_WORD_WAVE_START__DISPATCHER_MASK 0x1f0000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__DISPATCHER__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_WAVE_START__VS_NO_ALLOC_OR_GROUPED_MASK 0x200000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__VS_NO_ALLOC_OR_GROUPED__SHIFT 0x15
+#define SQ_THREAD_TRACE_WORD_WAVE_START__COUNT_MASK 0x1fc00000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__COUNT__SHIFT 0x16
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TG_ID_MASK 0xe0000000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TG_ID__SHIFT 0x1d
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__PIPE_ID_MASK 0x60
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__PIPE_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__ME_ID_MASK 0x180
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__ME_ID__SHIFT 0x7
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_DROPPED_PREV_MASK 0x200
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_DROPPED_PREV__SHIFT 0x9
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_TYPE_MASK 0x1c00
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_TYPE__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_PRIV_MASK 0x4000
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_PRIV__SHIFT 0xe
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_OP_MASK 0x8000
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_OP__SHIFT 0xf
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_ADDR_MASK 0xffff0000
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_ADDR__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_REG_2_OF_2__DATA_MASK 0xffffffff
+#define SQ_THREAD_TRACE_WORD_REG_2_OF_2__DATA__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__PIPE_ID_MASK 0x60
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__PIPE_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__ME_ID_MASK 0x180
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__ME_ID__SHIFT 0x7
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__REG_ADDR_MASK 0xfe00
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__REG_ADDR__SHIFT 0x9
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__DATA_LO_MASK 0xffff0000
+#define SQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__DATA_LO__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_REG_CS_2_OF_2__DATA_HI_MASK 0xffff
+#define SQ_THREAD_TRACE_WORD_REG_CS_2_OF_2__DATA_HI__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_EVENT__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_EVENT__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_EVENT__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_EVENT__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_EVENT__SH_ID_MASK 0x20
+#define SQ_THREAD_TRACE_WORD_EVENT__SH_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_EVENT__STAGE_MASK 0x1c0
+#define SQ_THREAD_TRACE_WORD_EVENT__STAGE__SHIFT 0x6
+#define SQ_THREAD_TRACE_WORD_EVENT__EVENT_TYPE_MASK 0xfc00
+#define SQ_THREAD_TRACE_WORD_EVENT__EVENT_TYPE__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_ISSUE__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_ISSUE__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_ISSUE__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_ISSUE__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_ISSUE__SIMD_ID_MASK 0x60
+#define SQ_THREAD_TRACE_WORD_ISSUE__SIMD_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST0_MASK 0x300
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST0__SHIFT 0x8
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST1_MASK 0xc00
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST1__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST2_MASK 0x3000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST2__SHIFT 0xc
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST3_MASK 0xc000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST3__SHIFT 0xe
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST4_MASK 0x30000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST4__SHIFT 0x10
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST5_MASK 0xc0000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST5__SHIFT 0x12
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST6_MASK 0x300000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST6__SHIFT 0x14
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST7_MASK 0xc00000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST7__SHIFT 0x16
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST8_MASK 0x3000000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST8__SHIFT 0x18
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST9_MASK 0xc000000
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST9__SHIFT 0x1a
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TOKEN_TYPE_MASK 0xf
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TOKEN_TYPE__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TIME_DELTA_MASK 0x10
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TIME_DELTA__SHIFT 0x4
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__SH_ID_MASK 0x20
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__SH_ID__SHIFT 0x5
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CU_ID_MASK 0x3c0
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CU_ID__SHIFT 0x6
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR_BANK_MASK 0xc00
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR_BANK__SHIFT 0xa
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR0_MASK 0x1fff000
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR0__SHIFT 0xc
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR1_LO_MASK 0xfe000000
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR1_LO__SHIFT 0x19
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR1_HI_MASK 0x3f
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR1_HI__SHIFT 0x0
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR2_MASK 0x7ffc0
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR2__SHIFT 0x6
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR3_MASK 0xfff80000
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR3__SHIFT 0x13
+#define SQ_WREXEC_EXEC_LO__ADDR_LO_MASK 0xffffffff
+#define SQ_WREXEC_EXEC_LO__ADDR_LO__SHIFT 0x0
+#define SQ_WREXEC_EXEC_HI__ADDR_HI_MASK 0xffff
+#define SQ_WREXEC_EXEC_HI__ADDR_HI__SHIFT 0x0
+#define SQ_WREXEC_EXEC_HI__FIRST_WAVE_MASK 0x4000000
+#define SQ_WREXEC_EXEC_HI__FIRST_WAVE__SHIFT 0x1a
+#define SQ_WREXEC_EXEC_HI__ATC_MASK 0x8000000
+#define SQ_WREXEC_EXEC_HI__ATC__SHIFT 0x1b
+#define SQ_WREXEC_EXEC_HI__MTYPE_MASK 0x70000000
+#define SQ_WREXEC_EXEC_HI__MTYPE__SHIFT 0x1c
+#define SQ_WREXEC_EXEC_HI__MSB_MASK 0x80000000
+#define SQ_WREXEC_EXEC_HI__MSB__SHIFT 0x1f
+#define SQC_GATCL1_CNTL__RESERVED_MASK 0x3ffff
+#define SQC_GATCL1_CNTL__RESERVED__SHIFT 0x0
+#define SQC_GATCL1_CNTL__DCACHE_INVALIDATE_ALL_VMID_MASK 0x40000
+#define SQC_GATCL1_CNTL__DCACHE_INVALIDATE_ALL_VMID__SHIFT 0x12
+#define SQC_GATCL1_CNTL__DCACHE_FORCE_MISS_MASK 0x80000
+#define SQC_GATCL1_CNTL__DCACHE_FORCE_MISS__SHIFT 0x13
+#define SQC_GATCL1_CNTL__DCACHE_FORCE_IN_ORDER_MASK 0x100000
+#define SQC_GATCL1_CNTL__DCACHE_FORCE_IN_ORDER__SHIFT 0x14
+#define SQC_GATCL1_CNTL__DCACHE_REDUCE_FIFO_DEPTH_BY_2_MASK 0x600000
+#define SQC_GATCL1_CNTL__DCACHE_REDUCE_FIFO_DEPTH_BY_2__SHIFT 0x15
+#define SQC_GATCL1_CNTL__DCACHE_REDUCE_CACHE_SIZE_BY_2_MASK 0x1800000
+#define SQC_GATCL1_CNTL__DCACHE_REDUCE_CACHE_SIZE_BY_2__SHIFT 0x17
+#define SQC_GATCL1_CNTL__ICACHE_INVALIDATE_ALL_VMID_MASK 0x2000000
+#define SQC_GATCL1_CNTL__ICACHE_INVALIDATE_ALL_VMID__SHIFT 0x19
+#define SQC_GATCL1_CNTL__ICACHE_FORCE_MISS_MASK 0x4000000
+#define SQC_GATCL1_CNTL__ICACHE_FORCE_MISS__SHIFT 0x1a
+#define SQC_GATCL1_CNTL__ICACHE_FORCE_IN_ORDER_MASK 0x8000000
+#define SQC_GATCL1_CNTL__ICACHE_FORCE_IN_ORDER__SHIFT 0x1b
+#define SQC_GATCL1_CNTL__ICACHE_REDUCE_FIFO_DEPTH_BY_2_MASK 0x30000000
+#define SQC_GATCL1_CNTL__ICACHE_REDUCE_FIFO_DEPTH_BY_2__SHIFT 0x1c
+#define SQC_GATCL1_CNTL__ICACHE_REDUCE_CACHE_SIZE_BY_2_MASK 0xc0000000
+#define SQC_GATCL1_CNTL__ICACHE_REDUCE_CACHE_SIZE_BY_2__SHIFT 0x1e
+#define SQC_ATC_EDC_GATCL1_CNT__ICACHE_DATA_SEC_MASK 0xff
+#define SQC_ATC_EDC_GATCL1_CNT__ICACHE_DATA_SEC__SHIFT 0x0
+#define SQC_ATC_EDC_GATCL1_CNT__DCACHE_DATA_SEC_MASK 0xff0000
+#define SQC_ATC_EDC_GATCL1_CNT__DCACHE_DATA_SEC__SHIFT 0x10
+#define SQ_INTERRUPT_WORD_CMN__SE_ID_MASK 0x3000000
+#define SQ_INTERRUPT_WORD_CMN__SE_ID__SHIFT 0x18
+#define SQ_INTERRUPT_WORD_CMN__ENCODING_MASK 0xc000000
+#define SQ_INTERRUPT_WORD_CMN__ENCODING__SHIFT 0x1a
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_MASK 0x1
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE__SHIFT 0x0
+#define SQ_INTERRUPT_WORD_AUTO__WLT_MASK 0x2
+#define SQ_INTERRUPT_WORD_AUTO__WLT__SHIFT 0x1
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_BUF_FULL_MASK 0x4
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_BUF_FULL__SHIFT 0x2
+#define SQ_INTERRUPT_WORD_AUTO__REG_TIMESTAMP_MASK 0x8
+#define SQ_INTERRUPT_WORD_AUTO__REG_TIMESTAMP__SHIFT 0x3
+#define SQ_INTERRUPT_WORD_AUTO__CMD_TIMESTAMP_MASK 0x10
+#define SQ_INTERRUPT_WORD_AUTO__CMD_TIMESTAMP__SHIFT 0x4
+#define SQ_INTERRUPT_WORD_AUTO__HOST_CMD_OVERFLOW_MASK 0x20
+#define SQ_INTERRUPT_WORD_AUTO__HOST_CMD_OVERFLOW__SHIFT 0x5
+#define SQ_INTERRUPT_WORD_AUTO__HOST_REG_OVERFLOW_MASK 0x40
+#define SQ_INTERRUPT_WORD_AUTO__HOST_REG_OVERFLOW__SHIFT 0x6
+#define SQ_INTERRUPT_WORD_AUTO__IMMED_OVERFLOW_MASK 0x80
+#define SQ_INTERRUPT_WORD_AUTO__IMMED_OVERFLOW__SHIFT 0x7
+#define SQ_INTERRUPT_WORD_AUTO__SE_ID_MASK 0x3000000
+#define SQ_INTERRUPT_WORD_AUTO__SE_ID__SHIFT 0x18
+#define SQ_INTERRUPT_WORD_AUTO__ENCODING_MASK 0xc000000
+#define SQ_INTERRUPT_WORD_AUTO__ENCODING__SHIFT 0x1a
+#define SQ_INTERRUPT_WORD_WAVE__DATA_MASK 0xff
+#define SQ_INTERRUPT_WORD_WAVE__DATA__SHIFT 0x0
+#define SQ_INTERRUPT_WORD_WAVE__SH_ID_MASK 0x100
+#define SQ_INTERRUPT_WORD_WAVE__SH_ID__SHIFT 0x8
+#define SQ_INTERRUPT_WORD_WAVE__PRIV_MASK 0x200
+#define SQ_INTERRUPT_WORD_WAVE__PRIV__SHIFT 0x9
+#define SQ_INTERRUPT_WORD_WAVE__VM_ID_MASK 0x3c00
+#define SQ_INTERRUPT_WORD_WAVE__VM_ID__SHIFT 0xa
+#define SQ_INTERRUPT_WORD_WAVE__WAVE_ID_MASK 0x3c000
+#define SQ_INTERRUPT_WORD_WAVE__WAVE_ID__SHIFT 0xe
+#define SQ_INTERRUPT_WORD_WAVE__SIMD_ID_MASK 0xc0000
+#define SQ_INTERRUPT_WORD_WAVE__SIMD_ID__SHIFT 0x12
+#define SQ_INTERRUPT_WORD_WAVE__CU_ID_MASK 0xf00000
+#define SQ_INTERRUPT_WORD_WAVE__CU_ID__SHIFT 0x14
+#define SQ_INTERRUPT_WORD_WAVE__SE_ID_MASK 0x3000000
+#define SQ_INTERRUPT_WORD_WAVE__SE_ID__SHIFT 0x18
+#define SQ_INTERRUPT_WORD_WAVE__ENCODING_MASK 0xc000000
+#define SQ_INTERRUPT_WORD_WAVE__ENCODING__SHIFT 0x1a
+#define SQ_SOP2__SSRC0_MASK 0xff
+#define SQ_SOP2__SSRC0__SHIFT 0x0
+#define SQ_SOP2__SSRC1_MASK 0xff00
+#define SQ_SOP2__SSRC1__SHIFT 0x8
+#define SQ_SOP2__SDST_MASK 0x7f0000
+#define SQ_SOP2__SDST__SHIFT 0x10
+#define SQ_SOP2__OP_MASK 0x3f800000
+#define SQ_SOP2__OP__SHIFT 0x17
+#define SQ_SOP2__ENCODING_MASK 0xc0000000
+#define SQ_SOP2__ENCODING__SHIFT 0x1e
+#define SQ_VOP1__SRC0_MASK 0x1ff
+#define SQ_VOP1__SRC0__SHIFT 0x0
+#define SQ_VOP1__OP_MASK 0x1fe00
+#define SQ_VOP1__OP__SHIFT 0x9
+#define SQ_VOP1__VDST_MASK 0x1fe0000
+#define SQ_VOP1__VDST__SHIFT 0x11
+#define SQ_VOP1__ENCODING_MASK 0xfe000000
+#define SQ_VOP1__ENCODING__SHIFT 0x19
+#define SQ_MTBUF_1__VADDR_MASK 0xff
+#define SQ_MTBUF_1__VADDR__SHIFT 0x0
+#define SQ_MTBUF_1__VDATA_MASK 0xff00
+#define SQ_MTBUF_1__VDATA__SHIFT 0x8
+#define SQ_MTBUF_1__SRSRC_MASK 0x1f0000
+#define SQ_MTBUF_1__SRSRC__SHIFT 0x10
+#define SQ_MTBUF_1__SLC_MASK 0x400000
+#define SQ_MTBUF_1__SLC__SHIFT 0x16
+#define SQ_MTBUF_1__TFE_MASK 0x800000
+#define SQ_MTBUF_1__TFE__SHIFT 0x17
+#define SQ_MTBUF_1__SOFFSET_MASK 0xff000000
+#define SQ_MTBUF_1__SOFFSET__SHIFT 0x18
+#define SQ_EXP_1__VSRC0_MASK 0xff
+#define SQ_EXP_1__VSRC0__SHIFT 0x0
+#define SQ_EXP_1__VSRC1_MASK 0xff00
+#define SQ_EXP_1__VSRC1__SHIFT 0x8
+#define SQ_EXP_1__VSRC2_MASK 0xff0000
+#define SQ_EXP_1__VSRC2__SHIFT 0x10
+#define SQ_EXP_1__VSRC3_MASK 0xff000000
+#define SQ_EXP_1__VSRC3__SHIFT 0x18
+#define SQ_MUBUF_1__VADDR_MASK 0xff
+#define SQ_MUBUF_1__VADDR__SHIFT 0x0
+#define SQ_MUBUF_1__VDATA_MASK 0xff00
+#define SQ_MUBUF_1__VDATA__SHIFT 0x8
+#define SQ_MUBUF_1__SRSRC_MASK 0x1f0000
+#define SQ_MUBUF_1__SRSRC__SHIFT 0x10
+#define SQ_MUBUF_1__TFE_MASK 0x800000
+#define SQ_MUBUF_1__TFE__SHIFT 0x17
+#define SQ_MUBUF_1__SOFFSET_MASK 0xff000000
+#define SQ_MUBUF_1__SOFFSET__SHIFT 0x18
+#define SQ_SMEM_1__OFFSET_MASK 0xfffff
+#define SQ_SMEM_1__OFFSET__SHIFT 0x0
+#define SQ_INST__ENCODING_MASK 0xffffffff
+#define SQ_INST__ENCODING__SHIFT 0x0
+#define SQ_EXP_0__EN_MASK 0xf
+#define SQ_EXP_0__EN__SHIFT 0x0
+#define SQ_EXP_0__TGT_MASK 0x3f0
+#define SQ_EXP_0__TGT__SHIFT 0x4
+#define SQ_EXP_0__COMPR_MASK 0x400
+#define SQ_EXP_0__COMPR__SHIFT 0xa
+#define SQ_EXP_0__DONE_MASK 0x800
+#define SQ_EXP_0__DONE__SHIFT 0xb
+#define SQ_EXP_0__VM_MASK 0x1000
+#define SQ_EXP_0__VM__SHIFT 0xc
+#define SQ_EXP_0__ENCODING_MASK 0xfc000000
+#define SQ_EXP_0__ENCODING__SHIFT 0x1a
+#define SQ_MUBUF_0__OFFSET_MASK 0xfff
+#define SQ_MUBUF_0__OFFSET__SHIFT 0x0
+#define SQ_MUBUF_0__OFFEN_MASK 0x1000
+#define SQ_MUBUF_0__OFFEN__SHIFT 0xc
+#define SQ_MUBUF_0__IDXEN_MASK 0x2000
+#define SQ_MUBUF_0__IDXEN__SHIFT 0xd
+#define SQ_MUBUF_0__GLC_MASK 0x4000
+#define SQ_MUBUF_0__GLC__SHIFT 0xe
+#define SQ_MUBUF_0__LDS_MASK 0x10000
+#define SQ_MUBUF_0__LDS__SHIFT 0x10
+#define SQ_MUBUF_0__SLC_MASK 0x20000
+#define SQ_MUBUF_0__SLC__SHIFT 0x11
+#define SQ_MUBUF_0__OP_MASK 0x1fc0000
+#define SQ_MUBUF_0__OP__SHIFT 0x12
+#define SQ_MUBUF_0__ENCODING_MASK 0xfc000000
+#define SQ_MUBUF_0__ENCODING__SHIFT 0x1a
+#define SQ_VOP_SDWA__SRC0_MASK 0xff
+#define SQ_VOP_SDWA__SRC0__SHIFT 0x0
+#define SQ_VOP_SDWA__DST_SEL_MASK 0x700
+#define SQ_VOP_SDWA__DST_SEL__SHIFT 0x8
+#define SQ_VOP_SDWA__DST_UNUSED_MASK 0x1800
+#define SQ_VOP_SDWA__DST_UNUSED__SHIFT 0xb
+#define SQ_VOP_SDWA__CLAMP_MASK 0x2000
+#define SQ_VOP_SDWA__CLAMP__SHIFT 0xd
+#define SQ_VOP_SDWA__SRC0_SEL_MASK 0x70000
+#define SQ_VOP_SDWA__SRC0_SEL__SHIFT 0x10
+#define SQ_VOP_SDWA__SRC0_SEXT_MASK 0x80000
+#define SQ_VOP_SDWA__SRC0_SEXT__SHIFT 0x13
+#define SQ_VOP_SDWA__SRC0_NEG_MASK 0x100000
+#define SQ_VOP_SDWA__SRC0_NEG__SHIFT 0x14
+#define SQ_VOP_SDWA__SRC0_ABS_MASK 0x200000
+#define SQ_VOP_SDWA__SRC0_ABS__SHIFT 0x15
+#define SQ_VOP_SDWA__SRC1_SEL_MASK 0x7000000
+#define SQ_VOP_SDWA__SRC1_SEL__SHIFT 0x18
+#define SQ_VOP_SDWA__SRC1_SEXT_MASK 0x8000000
+#define SQ_VOP_SDWA__SRC1_SEXT__SHIFT 0x1b
+#define SQ_VOP_SDWA__SRC1_NEG_MASK 0x10000000
+#define SQ_VOP_SDWA__SRC1_NEG__SHIFT 0x1c
+#define SQ_VOP_SDWA__SRC1_ABS_MASK 0x20000000
+#define SQ_VOP_SDWA__SRC1_ABS__SHIFT 0x1d
+#define SQ_VOP3_0__VDST_MASK 0xff
+#define SQ_VOP3_0__VDST__SHIFT 0x0
+#define SQ_VOP3_0__ABS_MASK 0x700
+#define SQ_VOP3_0__ABS__SHIFT 0x8
+#define SQ_VOP3_0__CLAMP_MASK 0x8000
+#define SQ_VOP3_0__CLAMP__SHIFT 0xf
+#define SQ_VOP3_0__OP_MASK 0x3ff0000
+#define SQ_VOP3_0__OP__SHIFT 0x10
+#define SQ_VOP3_0__ENCODING_MASK 0xfc000000
+#define SQ_VOP3_0__ENCODING__SHIFT 0x1a
+#define SQ_VOP2__SRC0_MASK 0x1ff
+#define SQ_VOP2__SRC0__SHIFT 0x0
+#define SQ_VOP2__VSRC1_MASK 0x1fe00
+#define SQ_VOP2__VSRC1__SHIFT 0x9
+#define SQ_VOP2__VDST_MASK 0x1fe0000
+#define SQ_VOP2__VDST__SHIFT 0x11
+#define SQ_VOP2__OP_MASK 0x7e000000
+#define SQ_VOP2__OP__SHIFT 0x19
+#define SQ_VOP2__ENCODING_MASK 0x80000000
+#define SQ_VOP2__ENCODING__SHIFT 0x1f
+#define SQ_MTBUF_0__OFFSET_MASK 0xfff
+#define SQ_MTBUF_0__OFFSET__SHIFT 0x0
+#define SQ_MTBUF_0__OFFEN_MASK 0x1000
+#define SQ_MTBUF_0__OFFEN__SHIFT 0xc
+#define SQ_MTBUF_0__IDXEN_MASK 0x2000
+#define SQ_MTBUF_0__IDXEN__SHIFT 0xd
+#define SQ_MTBUF_0__GLC_MASK 0x4000
+#define SQ_MTBUF_0__GLC__SHIFT 0xe
+#define SQ_MTBUF_0__OP_MASK 0x78000
+#define SQ_MTBUF_0__OP__SHIFT 0xf
+#define SQ_MTBUF_0__DFMT_MASK 0x780000
+#define SQ_MTBUF_0__DFMT__SHIFT 0x13
+#define SQ_MTBUF_0__NFMT_MASK 0x3800000
+#define SQ_MTBUF_0__NFMT__SHIFT 0x17
+#define SQ_MTBUF_0__ENCODING_MASK 0xfc000000
+#define SQ_MTBUF_0__ENCODING__SHIFT 0x1a
+#define SQ_SOPP__SIMM16_MASK 0xffff
+#define SQ_SOPP__SIMM16__SHIFT 0x0
+#define SQ_SOPP__OP_MASK 0x7f0000
+#define SQ_SOPP__OP__SHIFT 0x10
+#define SQ_SOPP__ENCODING_MASK 0xff800000
+#define SQ_SOPP__ENCODING__SHIFT 0x17
+#define SQ_FLAT_0__GLC_MASK 0x10000
+#define SQ_FLAT_0__GLC__SHIFT 0x10
+#define SQ_FLAT_0__SLC_MASK 0x20000
+#define SQ_FLAT_0__SLC__SHIFT 0x11
+#define SQ_FLAT_0__OP_MASK 0x1fc0000
+#define SQ_FLAT_0__OP__SHIFT 0x12
+#define SQ_FLAT_0__ENCODING_MASK 0xfc000000
+#define SQ_FLAT_0__ENCODING__SHIFT 0x1a
+#define SQ_VOP3_0_SDST_ENC__VDST_MASK 0xff
+#define SQ_VOP3_0_SDST_ENC__VDST__SHIFT 0x0
+#define SQ_VOP3_0_SDST_ENC__SDST_MASK 0x7f00
+#define SQ_VOP3_0_SDST_ENC__SDST__SHIFT 0x8
+#define SQ_VOP3_0_SDST_ENC__CLAMP_MASK 0x8000
+#define SQ_VOP3_0_SDST_ENC__CLAMP__SHIFT 0xf
+#define SQ_VOP3_0_SDST_ENC__OP_MASK 0x3ff0000
+#define SQ_VOP3_0_SDST_ENC__OP__SHIFT 0x10
+#define SQ_VOP3_0_SDST_ENC__ENCODING_MASK 0xfc000000
+#define SQ_VOP3_0_SDST_ENC__ENCODING__SHIFT 0x1a
+#define SQ_MIMG_1__VADDR_MASK 0xff
+#define SQ_MIMG_1__VADDR__SHIFT 0x0
+#define SQ_MIMG_1__VDATA_MASK 0xff00
+#define SQ_MIMG_1__VDATA__SHIFT 0x8
+#define SQ_MIMG_1__SRSRC_MASK 0x1f0000
+#define SQ_MIMG_1__SRSRC__SHIFT 0x10
+#define SQ_MIMG_1__SSAMP_MASK 0x3e00000
+#define SQ_MIMG_1__SSAMP__SHIFT 0x15
+#define SQ_MIMG_1__D16_MASK 0x80000000
+#define SQ_MIMG_1__D16__SHIFT 0x1f
+#define SQ_SOP1__SSRC0_MASK 0xff
+#define SQ_SOP1__SSRC0__SHIFT 0x0
+#define SQ_SOP1__OP_MASK 0xff00
+#define SQ_SOP1__OP__SHIFT 0x8
+#define SQ_SOP1__SDST_MASK 0x7f0000
+#define SQ_SOP1__SDST__SHIFT 0x10
+#define SQ_SOP1__ENCODING_MASK 0xff800000
+#define SQ_SOP1__ENCODING__SHIFT 0x17
+#define SQ_SOPC__SSRC0_MASK 0xff
+#define SQ_SOPC__SSRC0__SHIFT 0x0
+#define SQ_SOPC__SSRC1_MASK 0xff00
+#define SQ_SOPC__SSRC1__SHIFT 0x8
+#define SQ_SOPC__OP_MASK 0x7f0000
+#define SQ_SOPC__OP__SHIFT 0x10
+#define SQ_SOPC__ENCODING_MASK 0xff800000
+#define SQ_SOPC__ENCODING__SHIFT 0x17
+#define SQ_FLAT_1__ADDR_MASK 0xff
+#define SQ_FLAT_1__ADDR__SHIFT 0x0
+#define SQ_FLAT_1__DATA_MASK 0xff00
+#define SQ_FLAT_1__DATA__SHIFT 0x8
+#define SQ_FLAT_1__TFE_MASK 0x800000
+#define SQ_FLAT_1__TFE__SHIFT 0x17
+#define SQ_FLAT_1__VDST_MASK 0xff000000
+#define SQ_FLAT_1__VDST__SHIFT 0x18
+#define SQ_DS_1__ADDR_MASK 0xff
+#define SQ_DS_1__ADDR__SHIFT 0x0
+#define SQ_DS_1__DATA0_MASK 0xff00
+#define SQ_DS_1__DATA0__SHIFT 0x8
+#define SQ_DS_1__DATA1_MASK 0xff0000
+#define SQ_DS_1__DATA1__SHIFT 0x10
+#define SQ_DS_1__VDST_MASK 0xff000000
+#define SQ_DS_1__VDST__SHIFT 0x18
+#define SQ_VOP3_1__SRC0_MASK 0x1ff
+#define SQ_VOP3_1__SRC0__SHIFT 0x0
+#define SQ_VOP3_1__SRC1_MASK 0x3fe00
+#define SQ_VOP3_1__SRC1__SHIFT 0x9
+#define SQ_VOP3_1__SRC2_MASK 0x7fc0000
+#define SQ_VOP3_1__SRC2__SHIFT 0x12
+#define SQ_VOP3_1__OMOD_MASK 0x18000000
+#define SQ_VOP3_1__OMOD__SHIFT 0x1b
+#define SQ_VOP3_1__NEG_MASK 0xe0000000
+#define SQ_VOP3_1__NEG__SHIFT 0x1d
+#define SQ_SMEM_0__SBASE_MASK 0x3f
+#define SQ_SMEM_0__SBASE__SHIFT 0x0
+#define SQ_SMEM_0__SDATA_MASK 0x1fc0
+#define SQ_SMEM_0__SDATA__SHIFT 0x6
+#define SQ_SMEM_0__GLC_MASK 0x10000
+#define SQ_SMEM_0__GLC__SHIFT 0x10
+#define SQ_SMEM_0__IMM_MASK 0x20000
+#define SQ_SMEM_0__IMM__SHIFT 0x11
+#define SQ_SMEM_0__OP_MASK 0x3fc0000
+#define SQ_SMEM_0__OP__SHIFT 0x12
+#define SQ_SMEM_0__ENCODING_MASK 0xfc000000
+#define SQ_SMEM_0__ENCODING__SHIFT 0x1a
+#define SQ_MIMG_0__DMASK_MASK 0xf00
+#define SQ_MIMG_0__DMASK__SHIFT 0x8
+#define SQ_MIMG_0__UNORM_MASK 0x1000
+#define SQ_MIMG_0__UNORM__SHIFT 0xc
+#define SQ_MIMG_0__GLC_MASK 0x2000
+#define SQ_MIMG_0__GLC__SHIFT 0xd
+#define SQ_MIMG_0__DA_MASK 0x4000
+#define SQ_MIMG_0__DA__SHIFT 0xe
+#define SQ_MIMG_0__R128_MASK 0x8000
+#define SQ_MIMG_0__R128__SHIFT 0xf
+#define SQ_MIMG_0__TFE_MASK 0x10000
+#define SQ_MIMG_0__TFE__SHIFT 0x10
+#define SQ_MIMG_0__LWE_MASK 0x20000
+#define SQ_MIMG_0__LWE__SHIFT 0x11
+#define SQ_MIMG_0__OP_MASK 0x1fc0000
+#define SQ_MIMG_0__OP__SHIFT 0x12
+#define SQ_MIMG_0__SLC_MASK 0x2000000
+#define SQ_MIMG_0__SLC__SHIFT 0x19
+#define SQ_MIMG_0__ENCODING_MASK 0xfc000000
+#define SQ_MIMG_0__ENCODING__SHIFT 0x1a
+#define SQ_SOPK__SIMM16_MASK 0xffff
+#define SQ_SOPK__SIMM16__SHIFT 0x0
+#define SQ_SOPK__SDST_MASK 0x7f0000
+#define SQ_SOPK__SDST__SHIFT 0x10
+#define SQ_SOPK__OP_MASK 0xf800000
+#define SQ_SOPK__OP__SHIFT 0x17
+#define SQ_SOPK__ENCODING_MASK 0xf0000000
+#define SQ_SOPK__ENCODING__SHIFT 0x1c
+#define SQ_DS_0__OFFSET0_MASK 0xff
+#define SQ_DS_0__OFFSET0__SHIFT 0x0
+#define SQ_DS_0__OFFSET1_MASK 0xff00
+#define SQ_DS_0__OFFSET1__SHIFT 0x8
+#define SQ_DS_0__GDS_MASK 0x10000
+#define SQ_DS_0__GDS__SHIFT 0x10
+#define SQ_DS_0__OP_MASK 0x1fe0000
+#define SQ_DS_0__OP__SHIFT 0x11
+#define SQ_DS_0__ENCODING_MASK 0xfc000000
+#define SQ_DS_0__ENCODING__SHIFT 0x1a
+#define SQ_VOP_DPP__SRC0_MASK 0xff
+#define SQ_VOP_DPP__SRC0__SHIFT 0x0
+#define SQ_VOP_DPP__DPP_CTRL_MASK 0x1ff00
+#define SQ_VOP_DPP__DPP_CTRL__SHIFT 0x8
+#define SQ_VOP_DPP__BOUND_CTRL_MASK 0x80000
+#define SQ_VOP_DPP__BOUND_CTRL__SHIFT 0x13
+#define SQ_VOP_DPP__SRC0_NEG_MASK 0x100000
+#define SQ_VOP_DPP__SRC0_NEG__SHIFT 0x14
+#define SQ_VOP_DPP__SRC0_ABS_MASK 0x200000
+#define SQ_VOP_DPP__SRC0_ABS__SHIFT 0x15
+#define SQ_VOP_DPP__SRC1_NEG_MASK 0x400000
+#define SQ_VOP_DPP__SRC1_NEG__SHIFT 0x16
+#define SQ_VOP_DPP__SRC1_ABS_MASK 0x800000
+#define SQ_VOP_DPP__SRC1_ABS__SHIFT 0x17
+#define SQ_VOP_DPP__BANK_MASK_MASK 0xf000000
+#define SQ_VOP_DPP__BANK_MASK__SHIFT 0x18
+#define SQ_VOP_DPP__ROW_MASK_MASK 0xf0000000
+#define SQ_VOP_DPP__ROW_MASK__SHIFT 0x1c
+#define SQ_VOPC__SRC0_MASK 0x1ff
+#define SQ_VOPC__SRC0__SHIFT 0x0
+#define SQ_VOPC__VSRC1_MASK 0x1fe00
+#define SQ_VOPC__VSRC1__SHIFT 0x9
+#define SQ_VOPC__OP_MASK 0x1fe0000
+#define SQ_VOPC__OP__SHIFT 0x11
+#define SQ_VOPC__ENCODING_MASK 0xfe000000
+#define SQ_VOPC__ENCODING__SHIFT 0x19
+#define SQ_VINTRP__VSRC_MASK 0xff
+#define SQ_VINTRP__VSRC__SHIFT 0x0
+#define SQ_VINTRP__ATTRCHAN_MASK 0x300
+#define SQ_VINTRP__ATTRCHAN__SHIFT 0x8
+#define SQ_VINTRP__ATTR_MASK 0xfc00
+#define SQ_VINTRP__ATTR__SHIFT 0xa
+#define SQ_VINTRP__OP_MASK 0x30000
+#define SQ_VINTRP__OP__SHIFT 0x10
+#define SQ_VINTRP__VDST_MASK 0x3fc0000
+#define SQ_VINTRP__VDST__SHIFT 0x12
+#define SQ_VINTRP__ENCODING_MASK 0xfc000000
+#define SQ_VINTRP__ENCODING__SHIFT 0x1a
+#define CGTT_SX_CLK_CTRL0__ON_DELAY_MASK 0xf
+#define CGTT_SX_CLK_CTRL0__ON_DELAY__SHIFT 0x0
+#define CGTT_SX_CLK_CTRL0__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SX_CLK_CTRL0__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SX_CLK_CTRL0__RESERVED_MASK 0xfff000
+#define CGTT_SX_CLK_CTRL0__RESERVED__SHIFT 0xc
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CGTT_SX_CLK_CTRL1__ON_DELAY_MASK 0xf
+#define CGTT_SX_CLK_CTRL1__ON_DELAY__SHIFT 0x0
+#define CGTT_SX_CLK_CTRL1__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SX_CLK_CTRL1__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SX_CLK_CTRL1__RESERVED_MASK 0xfff000
+#define CGTT_SX_CLK_CTRL1__RESERVED__SHIFT 0xc
+#define CGTT_SX_CLK_CTRL1__DBG_EN_MASK 0x1000000
+#define CGTT_SX_CLK_CTRL1__DBG_EN__SHIFT 0x18
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CGTT_SX_CLK_CTRL2__ON_DELAY_MASK 0xf
+#define CGTT_SX_CLK_CTRL2__ON_DELAY__SHIFT 0x0
+#define CGTT_SX_CLK_CTRL2__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SX_CLK_CTRL2__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SX_CLK_CTRL2__RESERVED_MASK 0xfff000
+#define CGTT_SX_CLK_CTRL2__RESERVED__SHIFT 0xc
+#define CGTT_SX_CLK_CTRL2__DBG_EN_MASK 0x1000000
+#define CGTT_SX_CLK_CTRL2__DBG_EN__SHIFT 0x18
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CGTT_SX_CLK_CTRL3__ON_DELAY_MASK 0xf
+#define CGTT_SX_CLK_CTRL3__ON_DELAY__SHIFT 0x0
+#define CGTT_SX_CLK_CTRL3__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SX_CLK_CTRL3__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SX_CLK_CTRL3__RESERVED_MASK 0xfff000
+#define CGTT_SX_CLK_CTRL3__RESERVED__SHIFT 0xc
+#define CGTT_SX_CLK_CTRL3__DBG_EN_MASK 0x1000000
+#define CGTT_SX_CLK_CTRL3__DBG_EN__SHIFT 0x18
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CGTT_SX_CLK_CTRL4__ON_DELAY_MASK 0xf
+#define CGTT_SX_CLK_CTRL4__ON_DELAY__SHIFT 0x0
+#define CGTT_SX_CLK_CTRL4__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_SX_CLK_CTRL4__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_SX_CLK_CTRL4__RESERVED_MASK 0xfff000
+#define CGTT_SX_CLK_CTRL4__RESERVED__SHIFT 0xc
+#define CGTT_SX_CLK_CTRL4__DBG_EN_MASK 0x1000000
+#define CGTT_SX_CLK_CTRL4__DBG_EN__SHIFT 0x18
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE0__SHIFT 0x1f
+#define SX_DEBUG_BUSY__POS_FREE_OR_VALIDS_MASK 0x1
+#define SX_DEBUG_BUSY__POS_FREE_OR_VALIDS__SHIFT 0x0
+#define SX_DEBUG_BUSY__POS_REQUESTER_BUSY_MASK 0x2
+#define SX_DEBUG_BUSY__POS_REQUESTER_BUSY__SHIFT 0x1
+#define SX_DEBUG_BUSY__PA_SX_BUSY_MASK 0x4
+#define SX_DEBUG_BUSY__PA_SX_BUSY__SHIFT 0x2
+#define SX_DEBUG_BUSY__POS_SCBD_BUSY_MASK 0x8
+#define SX_DEBUG_BUSY__POS_SCBD_BUSY__SHIFT 0x3
+#define SX_DEBUG_BUSY__POS_BANK3VAL3_BUSY_MASK 0x10
+#define SX_DEBUG_BUSY__POS_BANK3VAL3_BUSY__SHIFT 0x4
+#define SX_DEBUG_BUSY__POS_BANK3VAL2_BUSY_MASK 0x20
+#define SX_DEBUG_BUSY__POS_BANK3VAL2_BUSY__SHIFT 0x5
+#define SX_DEBUG_BUSY__POS_BANK3VAL1_BUSY_MASK 0x40
+#define SX_DEBUG_BUSY__POS_BANK3VAL1_BUSY__SHIFT 0x6
+#define SX_DEBUG_BUSY__POS_BANK3VAL0_BUSY_MASK 0x80
+#define SX_DEBUG_BUSY__POS_BANK3VAL0_BUSY__SHIFT 0x7
+#define SX_DEBUG_BUSY__POS_BANK2VAL3_BUSY_MASK 0x100
+#define SX_DEBUG_BUSY__POS_BANK2VAL3_BUSY__SHIFT 0x8
+#define SX_DEBUG_BUSY__POS_BANK2VAL2_BUSY_MASK 0x200
+#define SX_DEBUG_BUSY__POS_BANK2VAL2_BUSY__SHIFT 0x9
+#define SX_DEBUG_BUSY__POS_BANK2VAL1_BUSY_MASK 0x400
+#define SX_DEBUG_BUSY__POS_BANK2VAL1_BUSY__SHIFT 0xa
+#define SX_DEBUG_BUSY__POS_BANK2VAL0_BUSY_MASK 0x800
+#define SX_DEBUG_BUSY__POS_BANK2VAL0_BUSY__SHIFT 0xb
+#define SX_DEBUG_BUSY__POS_BANK1VAL3_BUSY_MASK 0x1000
+#define SX_DEBUG_BUSY__POS_BANK1VAL3_BUSY__SHIFT 0xc
+#define SX_DEBUG_BUSY__POS_BANK1VAL2_BUSY_MASK 0x2000
+#define SX_DEBUG_BUSY__POS_BANK1VAL2_BUSY__SHIFT 0xd
+#define SX_DEBUG_BUSY__POS_BANK1VAL1_BUSY_MASK 0x4000
+#define SX_DEBUG_BUSY__POS_BANK1VAL1_BUSY__SHIFT 0xe
+#define SX_DEBUG_BUSY__POS_BANK1VAL0_BUSY_MASK 0x8000
+#define SX_DEBUG_BUSY__POS_BANK1VAL0_BUSY__SHIFT 0xf
+#define SX_DEBUG_BUSY__POS_BANK0VAL3_BUSY_MASK 0x10000
+#define SX_DEBUG_BUSY__POS_BANK0VAL3_BUSY__SHIFT 0x10
+#define SX_DEBUG_BUSY__POS_BANK0VAL2_BUSY_MASK 0x20000
+#define SX_DEBUG_BUSY__POS_BANK0VAL2_BUSY__SHIFT 0x11
+#define SX_DEBUG_BUSY__POS_BANK0VAL1_BUSY_MASK 0x40000
+#define SX_DEBUG_BUSY__POS_BANK0VAL1_BUSY__SHIFT 0x12
+#define SX_DEBUG_BUSY__POS_BANK0VAL0_BUSY_MASK 0x80000
+#define SX_DEBUG_BUSY__POS_BANK0VAL0_BUSY__SHIFT 0x13
+#define SX_DEBUG_BUSY__POS_INMUX_VALID_MASK 0x100000
+#define SX_DEBUG_BUSY__POS_INMUX_VALID__SHIFT 0x14
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ3_MASK 0x200000
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ3__SHIFT 0x15
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ2_MASK 0x400000
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ2__SHIFT 0x16
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ1_MASK 0x800000
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ1__SHIFT 0x17
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ3_MASK 0x1000000
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ3__SHIFT 0x18
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ2_MASK 0x2000000
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ2__SHIFT 0x19
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ1_MASK 0x4000000
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ1__SHIFT 0x1a
+#define SX_DEBUG_BUSY__PCCMD_VALID_MASK 0x8000000
+#define SX_DEBUG_BUSY__PCCMD_VALID__SHIFT 0x1b
+#define SX_DEBUG_BUSY__VDATA1_VALID_MASK 0x10000000
+#define SX_DEBUG_BUSY__VDATA1_VALID__SHIFT 0x1c
+#define SX_DEBUG_BUSY__VDATA0_VALID_MASK 0x20000000
+#define SX_DEBUG_BUSY__VDATA0_VALID__SHIFT 0x1d
+#define SX_DEBUG_BUSY__CMD_BUSYORVAL_MASK 0x40000000
+#define SX_DEBUG_BUSY__CMD_BUSYORVAL__SHIFT 0x1e
+#define SX_DEBUG_BUSY__ADDR_BUSYORVAL_MASK 0x80000000
+#define SX_DEBUG_BUSY__ADDR_BUSYORVAL__SHIFT 0x1f
+#define SX_DEBUG_BUSY_2__COL_SCBD_BUSY_MASK 0x1
+#define SX_DEBUG_BUSY_2__COL_SCBD_BUSY__SHIFT 0x0
+#define SX_DEBUG_BUSY_2__COL_REQ3_FREECNT_NE0_MASK 0x2
+#define SX_DEBUG_BUSY_2__COL_REQ3_FREECNT_NE0__SHIFT 0x1
+#define SX_DEBUG_BUSY_2__COL_REQ3_IDLE_MASK 0x4
+#define SX_DEBUG_BUSY_2__COL_REQ3_IDLE__SHIFT 0x2
+#define SX_DEBUG_BUSY_2__COL_REQ3_BUSY_MASK 0x8
+#define SX_DEBUG_BUSY_2__COL_REQ3_BUSY__SHIFT 0x3
+#define SX_DEBUG_BUSY_2__COL_REQ2_FREECNT_NE0_MASK 0x10
+#define SX_DEBUG_BUSY_2__COL_REQ2_FREECNT_NE0__SHIFT 0x4
+#define SX_DEBUG_BUSY_2__COL_REQ2_IDLE_MASK 0x20
+#define SX_DEBUG_BUSY_2__COL_REQ2_IDLE__SHIFT 0x5
+#define SX_DEBUG_BUSY_2__COL_REQ2_BUSY_MASK 0x40
+#define SX_DEBUG_BUSY_2__COL_REQ2_BUSY__SHIFT 0x6
+#define SX_DEBUG_BUSY_2__COL_REQ1_FREECNT_NE0_MASK 0x80
+#define SX_DEBUG_BUSY_2__COL_REQ1_FREECNT_NE0__SHIFT 0x7
+#define SX_DEBUG_BUSY_2__COL_REQ1_IDLE_MASK 0x100
+#define SX_DEBUG_BUSY_2__COL_REQ1_IDLE__SHIFT 0x8
+#define SX_DEBUG_BUSY_2__COL_REQ1_BUSY_MASK 0x200
+#define SX_DEBUG_BUSY_2__COL_REQ1_BUSY__SHIFT 0x9
+#define SX_DEBUG_BUSY_2__COL_REQ0_FREECNT_NE0_MASK 0x400
+#define SX_DEBUG_BUSY_2__COL_REQ0_FREECNT_NE0__SHIFT 0xa
+#define SX_DEBUG_BUSY_2__COL_REQ0_IDLE_MASK 0x800
+#define SX_DEBUG_BUSY_2__COL_REQ0_IDLE__SHIFT 0xb
+#define SX_DEBUG_BUSY_2__COL_REQ0_BUSY_MASK 0x1000
+#define SX_DEBUG_BUSY_2__COL_REQ0_BUSY__SHIFT 0xc
+#define SX_DEBUG_BUSY_2__COL_DBIF3_SENDFREE_BUSY_MASK 0x2000
+#define SX_DEBUG_BUSY_2__COL_DBIF3_SENDFREE_BUSY__SHIFT 0xd
+#define SX_DEBUG_BUSY_2__COL_DBIF3_FIFO_BUSY_MASK 0x4000
+#define SX_DEBUG_BUSY_2__COL_DBIF3_FIFO_BUSY__SHIFT 0xe
+#define SX_DEBUG_BUSY_2__COL_DBIF3_READ_VALID_MASK 0x8000
+#define SX_DEBUG_BUSY_2__COL_DBIF3_READ_VALID__SHIFT 0xf
+#define SX_DEBUG_BUSY_2__COL_DBIF2_SENDFREE_BUSY_MASK 0x10000
+#define SX_DEBUG_BUSY_2__COL_DBIF2_SENDFREE_BUSY__SHIFT 0x10
+#define SX_DEBUG_BUSY_2__COL_DBIF2_FIFO_BUSY_MASK 0x20000
+#define SX_DEBUG_BUSY_2__COL_DBIF2_FIFO_BUSY__SHIFT 0x11
+#define SX_DEBUG_BUSY_2__COL_DBIF2_READ_VALID_MASK 0x40000
+#define SX_DEBUG_BUSY_2__COL_DBIF2_READ_VALID__SHIFT 0x12
+#define SX_DEBUG_BUSY_2__COL_DBIF1_SENDFREE_BUSY_MASK 0x80000
+#define SX_DEBUG_BUSY_2__COL_DBIF1_SENDFREE_BUSY__SHIFT 0x13
+#define SX_DEBUG_BUSY_2__COL_DBIF1_FIFO_BUSY_MASK 0x100000
+#define SX_DEBUG_BUSY_2__COL_DBIF1_FIFO_BUSY__SHIFT 0x14
+#define SX_DEBUG_BUSY_2__COL_DBIF1_READ_VALID_MASK 0x200000
+#define SX_DEBUG_BUSY_2__COL_DBIF1_READ_VALID__SHIFT 0x15
+#define SX_DEBUG_BUSY_2__COL_DBIF0_SENDFREE_BUSY_MASK 0x400000
+#define SX_DEBUG_BUSY_2__COL_DBIF0_SENDFREE_BUSY__SHIFT 0x16
+#define SX_DEBUG_BUSY_2__COL_DBIF0_FIFO_BUSY_MASK 0x800000
+#define SX_DEBUG_BUSY_2__COL_DBIF0_FIFO_BUSY__SHIFT 0x17
+#define SX_DEBUG_BUSY_2__COL_DBIF0_READ_VALID_MASK 0x1000000
+#define SX_DEBUG_BUSY_2__COL_DBIF0_READ_VALID__SHIFT 0x18
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL3_BUSY_MASK 0x2000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL3_BUSY__SHIFT 0x19
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL2_BUSY_MASK 0x4000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL2_BUSY__SHIFT 0x1a
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL1_BUSY_MASK 0x8000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL1_BUSY__SHIFT 0x1b
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL0_BUSY_MASK 0x10000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL0_BUSY__SHIFT 0x1c
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL3_BUSY_MASK 0x20000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL3_BUSY__SHIFT 0x1d
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL2_BUSY_MASK 0x40000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL2_BUSY__SHIFT 0x1e
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL1_BUSY_MASK 0x80000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL1_BUSY__SHIFT 0x1f
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK2_VAL0_BUSY_MASK 0x1
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK2_VAL0_BUSY__SHIFT 0x0
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL3_BUSY_MASK 0x2
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL3_BUSY__SHIFT 0x1
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL2_BUSY_MASK 0x4
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL2_BUSY__SHIFT 0x2
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL1_BUSY_MASK 0x8
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL1_BUSY__SHIFT 0x3
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL0_BUSY_MASK 0x10
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL0_BUSY__SHIFT 0x4
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL3_BUSY_MASK 0x20
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL3_BUSY__SHIFT 0x5
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL2_BUSY_MASK 0x40
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL2_BUSY__SHIFT 0x6
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL1_BUSY_MASK 0x80
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL1_BUSY__SHIFT 0x7
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL0_BUSY_MASK 0x100
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL0_BUSY__SHIFT 0x8
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL3_BUSY_MASK 0x200
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL3_BUSY__SHIFT 0x9
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL2_BUSY_MASK 0x400
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL2_BUSY__SHIFT 0xa
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL1_BUSY_MASK 0x800
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL1_BUSY__SHIFT 0xb
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL0_BUSY_MASK 0x1000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL0_BUSY__SHIFT 0xc
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL3_BUSY_MASK 0x2000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL3_BUSY__SHIFT 0xd
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL2_BUSY_MASK 0x4000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL2_BUSY__SHIFT 0xe
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL1_BUSY_MASK 0x8000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL1_BUSY__SHIFT 0xf
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL0_BUSY_MASK 0x10000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL0_BUSY__SHIFT 0x10
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL3_BUSY_MASK 0x20000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL3_BUSY__SHIFT 0x11
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL2_BUSY_MASK 0x40000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL2_BUSY__SHIFT 0x12
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL1_BUSY_MASK 0x80000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL1_BUSY__SHIFT 0x13
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL0_BUSY_MASK 0x100000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL0_BUSY__SHIFT 0x14
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL3_BUSY_MASK 0x200000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL3_BUSY__SHIFT 0x15
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL2_BUSY_MASK 0x400000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL2_BUSY__SHIFT 0x16
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL1_BUSY_MASK 0x800000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL1_BUSY__SHIFT 0x17
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL0_BUSY_MASK 0x1000000
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL0_BUSY__SHIFT 0x18
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL3_BUSY_MASK 0x2000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL3_BUSY__SHIFT 0x19
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL2_BUSY_MASK 0x4000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL2_BUSY__SHIFT 0x1a
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL1_BUSY_MASK 0x8000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL1_BUSY__SHIFT 0x1b
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL0_BUSY_MASK 0x10000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL0_BUSY__SHIFT 0x1c
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL3_BUSY_MASK 0x20000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL3_BUSY__SHIFT 0x1d
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL2_BUSY_MASK 0x40000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL2_BUSY__SHIFT 0x1e
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL1_BUSY_MASK 0x80000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL1_BUSY__SHIFT 0x1f
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK2_VAL0_BUSY_MASK 0x1
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK2_VAL0_BUSY__SHIFT 0x0
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL3_BUSY_MASK 0x2
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL3_BUSY__SHIFT 0x1
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL2_BUSY_MASK 0x4
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL2_BUSY__SHIFT 0x2
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL1_BUSY_MASK 0x8
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL1_BUSY__SHIFT 0x3
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL0_BUSY_MASK 0x10
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL0_BUSY__SHIFT 0x4
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL3_BUSY_MASK 0x20
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL3_BUSY__SHIFT 0x5
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL2_BUSY_MASK 0x40
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL2_BUSY__SHIFT 0x6
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL1_BUSY_MASK 0x80
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL1_BUSY__SHIFT 0x7
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL0_BUSY_MASK 0x100
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL0_BUSY__SHIFT 0x8
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL3_BUSY_MASK 0x200
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL3_BUSY__SHIFT 0x9
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL2_BUSY_MASK 0x400
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL2_BUSY__SHIFT 0xa
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL1_BUSY_MASK 0x800
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL1_BUSY__SHIFT 0xb
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL0_BUSY_MASK 0x1000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL0_BUSY__SHIFT 0xc
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL3_BUSY_MASK 0x2000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL3_BUSY__SHIFT 0xd
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL2_BUSY_MASK 0x4000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL2_BUSY__SHIFT 0xe
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL1_BUSY_MASK 0x8000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL1_BUSY__SHIFT 0xf
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL0_BUSY_MASK 0x10000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL0_BUSY__SHIFT 0x10
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL3_BUSY_MASK 0x20000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL3_BUSY__SHIFT 0x11
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL2_BUSY_MASK 0x40000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL2_BUSY__SHIFT 0x12
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL1_BUSY_MASK 0x80000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL1_BUSY__SHIFT 0x13
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL0_BUSY_MASK 0x100000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL0_BUSY__SHIFT 0x14
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL3_BUSY_MASK 0x200000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL3_BUSY__SHIFT 0x15
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL2_BUSY_MASK 0x400000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL2_BUSY__SHIFT 0x16
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL1_BUSY_MASK 0x800000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL1_BUSY__SHIFT 0x17
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL0_BUSY_MASK 0x1000000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL0_BUSY__SHIFT 0x18
+#define SX_DEBUG_BUSY_4__RESERVED_MASK 0xfe000000
+#define SX_DEBUG_BUSY_4__RESERVED__SHIFT 0x19
+#define SX_DEBUG_1__SX_DB_QUAD_CREDIT_MASK 0x7f
+#define SX_DEBUG_1__SX_DB_QUAD_CREDIT__SHIFT 0x0
+#define SX_DEBUG_1__DISABLE_BLEND_OPT_DONT_RD_DST_MASK 0x100
+#define SX_DEBUG_1__DISABLE_BLEND_OPT_DONT_RD_DST__SHIFT 0x8
+#define SX_DEBUG_1__DISABLE_BLEND_OPT_BYPASS_MASK 0x200
+#define SX_DEBUG_1__DISABLE_BLEND_OPT_BYPASS__SHIFT 0x9
+#define SX_DEBUG_1__DISABLE_BLEND_OPT_DISCARD_PIXEL_MASK 0x400
+#define SX_DEBUG_1__DISABLE_BLEND_OPT_DISCARD_PIXEL__SHIFT 0xa
+#define SX_DEBUG_1__DISABLE_QUAD_PAIR_OPT_MASK 0x800
+#define SX_DEBUG_1__DISABLE_QUAD_PAIR_OPT__SHIFT 0xb
+#define SX_DEBUG_1__DISABLE_PIX_EN_ZERO_OPT_MASK 0x1000
+#define SX_DEBUG_1__DISABLE_PIX_EN_ZERO_OPT__SHIFT 0xc
+#define SX_DEBUG_1__DEBUG_DATA_MASK 0xffffe000
+#define SX_DEBUG_1__DEBUG_DATA__SHIFT 0xd
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define SX_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define SX_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define SX_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define SX_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define SX_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define SX_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define SX_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define SX_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2_MASK 0x3ff
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x0
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3_MASK 0xffc00
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0xa
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT2_MASK 0x3ff
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x0
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT3_MASK 0xffc00
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0xa
+#define SX_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SX_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SX_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SX_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SX_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SX_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SX_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SX_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SX_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SX_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SX_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SX_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SX_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define SX_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define SX_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define SX_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define SX_PS_DOWNCONVERT__MRT0_MASK 0xf
+#define SX_PS_DOWNCONVERT__MRT0__SHIFT 0x0
+#define SX_PS_DOWNCONVERT__MRT1_MASK 0xf0
+#define SX_PS_DOWNCONVERT__MRT1__SHIFT 0x4
+#define SX_PS_DOWNCONVERT__MRT2_MASK 0xf00
+#define SX_PS_DOWNCONVERT__MRT2__SHIFT 0x8
+#define SX_PS_DOWNCONVERT__MRT3_MASK 0xf000
+#define SX_PS_DOWNCONVERT__MRT3__SHIFT 0xc
+#define SX_PS_DOWNCONVERT__MRT4_MASK 0xf0000
+#define SX_PS_DOWNCONVERT__MRT4__SHIFT 0x10
+#define SX_PS_DOWNCONVERT__MRT5_MASK 0xf00000
+#define SX_PS_DOWNCONVERT__MRT5__SHIFT 0x14
+#define SX_PS_DOWNCONVERT__MRT6_MASK 0xf000000
+#define SX_PS_DOWNCONVERT__MRT6__SHIFT 0x18
+#define SX_PS_DOWNCONVERT__MRT7_MASK 0xf0000000
+#define SX_PS_DOWNCONVERT__MRT7__SHIFT 0x1c
+#define SX_BLEND_OPT_EPSILON__MRT0_EPSILON_MASK 0xf
+#define SX_BLEND_OPT_EPSILON__MRT0_EPSILON__SHIFT 0x0
+#define SX_BLEND_OPT_EPSILON__MRT1_EPSILON_MASK 0xf0
+#define SX_BLEND_OPT_EPSILON__MRT1_EPSILON__SHIFT 0x4
+#define SX_BLEND_OPT_EPSILON__MRT2_EPSILON_MASK 0xf00
+#define SX_BLEND_OPT_EPSILON__MRT2_EPSILON__SHIFT 0x8
+#define SX_BLEND_OPT_EPSILON__MRT3_EPSILON_MASK 0xf000
+#define SX_BLEND_OPT_EPSILON__MRT3_EPSILON__SHIFT 0xc
+#define SX_BLEND_OPT_EPSILON__MRT4_EPSILON_MASK 0xf0000
+#define SX_BLEND_OPT_EPSILON__MRT4_EPSILON__SHIFT 0x10
+#define SX_BLEND_OPT_EPSILON__MRT5_EPSILON_MASK 0xf00000
+#define SX_BLEND_OPT_EPSILON__MRT5_EPSILON__SHIFT 0x14
+#define SX_BLEND_OPT_EPSILON__MRT6_EPSILON_MASK 0xf000000
+#define SX_BLEND_OPT_EPSILON__MRT6_EPSILON__SHIFT 0x18
+#define SX_BLEND_OPT_EPSILON__MRT7_EPSILON_MASK 0xf0000000
+#define SX_BLEND_OPT_EPSILON__MRT7_EPSILON__SHIFT 0x1c
+#define SX_BLEND_OPT_CONTROL__MRT0_COLOR_OPT_DISABLE_MASK 0x1
+#define SX_BLEND_OPT_CONTROL__MRT0_COLOR_OPT_DISABLE__SHIFT 0x0
+#define SX_BLEND_OPT_CONTROL__MRT0_ALPHA_OPT_DISABLE_MASK 0x2
+#define SX_BLEND_OPT_CONTROL__MRT0_ALPHA_OPT_DISABLE__SHIFT 0x1
+#define SX_BLEND_OPT_CONTROL__MRT1_COLOR_OPT_DISABLE_MASK 0x10
+#define SX_BLEND_OPT_CONTROL__MRT1_COLOR_OPT_DISABLE__SHIFT 0x4
+#define SX_BLEND_OPT_CONTROL__MRT1_ALPHA_OPT_DISABLE_MASK 0x20
+#define SX_BLEND_OPT_CONTROL__MRT1_ALPHA_OPT_DISABLE__SHIFT 0x5
+#define SX_BLEND_OPT_CONTROL__MRT2_COLOR_OPT_DISABLE_MASK 0x100
+#define SX_BLEND_OPT_CONTROL__MRT2_COLOR_OPT_DISABLE__SHIFT 0x8
+#define SX_BLEND_OPT_CONTROL__MRT2_ALPHA_OPT_DISABLE_MASK 0x200
+#define SX_BLEND_OPT_CONTROL__MRT2_ALPHA_OPT_DISABLE__SHIFT 0x9
+#define SX_BLEND_OPT_CONTROL__MRT3_COLOR_OPT_DISABLE_MASK 0x1000
+#define SX_BLEND_OPT_CONTROL__MRT3_COLOR_OPT_DISABLE__SHIFT 0xc
+#define SX_BLEND_OPT_CONTROL__MRT3_ALPHA_OPT_DISABLE_MASK 0x2000
+#define SX_BLEND_OPT_CONTROL__MRT3_ALPHA_OPT_DISABLE__SHIFT 0xd
+#define SX_BLEND_OPT_CONTROL__MRT4_COLOR_OPT_DISABLE_MASK 0x10000
+#define SX_BLEND_OPT_CONTROL__MRT4_COLOR_OPT_DISABLE__SHIFT 0x10
+#define SX_BLEND_OPT_CONTROL__MRT4_ALPHA_OPT_DISABLE_MASK 0x20000
+#define SX_BLEND_OPT_CONTROL__MRT4_ALPHA_OPT_DISABLE__SHIFT 0x11
+#define SX_BLEND_OPT_CONTROL__MRT5_COLOR_OPT_DISABLE_MASK 0x100000
+#define SX_BLEND_OPT_CONTROL__MRT5_COLOR_OPT_DISABLE__SHIFT 0x14
+#define SX_BLEND_OPT_CONTROL__MRT5_ALPHA_OPT_DISABLE_MASK 0x200000
+#define SX_BLEND_OPT_CONTROL__MRT5_ALPHA_OPT_DISABLE__SHIFT 0x15
+#define SX_BLEND_OPT_CONTROL__MRT6_COLOR_OPT_DISABLE_MASK 0x1000000
+#define SX_BLEND_OPT_CONTROL__MRT6_COLOR_OPT_DISABLE__SHIFT 0x18
+#define SX_BLEND_OPT_CONTROL__MRT6_ALPHA_OPT_DISABLE_MASK 0x2000000
+#define SX_BLEND_OPT_CONTROL__MRT6_ALPHA_OPT_DISABLE__SHIFT 0x19
+#define SX_BLEND_OPT_CONTROL__MRT7_COLOR_OPT_DISABLE_MASK 0x10000000
+#define SX_BLEND_OPT_CONTROL__MRT7_COLOR_OPT_DISABLE__SHIFT 0x1c
+#define SX_BLEND_OPT_CONTROL__MRT7_ALPHA_OPT_DISABLE_MASK 0x20000000
+#define SX_BLEND_OPT_CONTROL__MRT7_ALPHA_OPT_DISABLE__SHIFT 0x1d
+#define SX_BLEND_OPT_CONTROL__PIXEN_ZERO_OPT_DISABLE_MASK 0x80000000
+#define SX_BLEND_OPT_CONTROL__PIXEN_ZERO_OPT_DISABLE__SHIFT 0x1f
+#define SX_MRT0_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT0_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT0_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT0_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT0_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT0_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT0_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT0_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT0_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT0_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT0_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT0_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT1_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT1_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT1_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT1_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT1_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT1_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT1_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT1_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT1_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT1_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT1_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT1_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT2_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT2_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT2_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT2_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT2_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT2_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT2_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT2_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT2_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT2_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT2_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT2_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT3_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT3_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT3_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT3_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT3_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT3_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT3_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT3_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT3_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT3_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT3_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT3_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT4_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT4_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT4_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT4_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT4_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT4_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT4_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT4_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT4_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT4_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT4_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT4_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT5_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT5_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT5_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT5_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT5_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT5_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT5_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT5_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT5_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT5_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT5_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT5_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT6_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT6_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT6_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT6_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT6_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT6_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT6_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT6_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT6_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT6_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT6_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT6_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define SX_MRT7_BLEND_OPT__COLOR_SRC_OPT_MASK 0x7
+#define SX_MRT7_BLEND_OPT__COLOR_SRC_OPT__SHIFT 0x0
+#define SX_MRT7_BLEND_OPT__COLOR_DST_OPT_MASK 0x70
+#define SX_MRT7_BLEND_OPT__COLOR_DST_OPT__SHIFT 0x4
+#define SX_MRT7_BLEND_OPT__COLOR_COMB_FCN_MASK 0x700
+#define SX_MRT7_BLEND_OPT__COLOR_COMB_FCN__SHIFT 0x8
+#define SX_MRT7_BLEND_OPT__ALPHA_SRC_OPT_MASK 0x70000
+#define SX_MRT7_BLEND_OPT__ALPHA_SRC_OPT__SHIFT 0x10
+#define SX_MRT7_BLEND_OPT__ALPHA_DST_OPT_MASK 0x700000
+#define SX_MRT7_BLEND_OPT__ALPHA_DST_OPT__SHIFT 0x14
+#define SX_MRT7_BLEND_OPT__ALPHA_COMB_FCN_MASK 0x7000000
+#define SX_MRT7_BLEND_OPT__ALPHA_COMB_FCN__SHIFT 0x18
+#define TCC_CTRL__CACHE_SIZE_MASK 0x3
+#define TCC_CTRL__CACHE_SIZE__SHIFT 0x0
+#define TCC_CTRL__RATE_MASK 0xc
+#define TCC_CTRL__RATE__SHIFT 0x2
+#define TCC_CTRL__WRITEBACK_MARGIN_MASK 0xf0
+#define TCC_CTRL__WRITEBACK_MARGIN__SHIFT 0x4
+#define TCC_CTRL__METADATA_LATENCY_FIFO_SIZE_MASK 0xf00
+#define TCC_CTRL__METADATA_LATENCY_FIFO_SIZE__SHIFT 0x8
+#define TCC_CTRL__SRC_FIFO_SIZE_MASK 0xf000
+#define TCC_CTRL__SRC_FIFO_SIZE__SHIFT 0xc
+#define TCC_CTRL__LATENCY_FIFO_SIZE_MASK 0xf0000
+#define TCC_CTRL__LATENCY_FIFO_SIZE__SHIFT 0x10
+#define TCC_CTRL__WB_OR_INV_ALL_VMIDS_MASK 0x100000
+#define TCC_CTRL__WB_OR_INV_ALL_VMIDS__SHIFT 0x14
+#define TCC_CTRL__MDC_SIZE_MASK 0x3000000
+#define TCC_CTRL__MDC_SIZE__SHIFT 0x18
+#define TCC_CTRL__MDC_SECTOR_SIZE_MASK 0xc000000
+#define TCC_CTRL__MDC_SECTOR_SIZE__SHIFT 0x1a
+#define TCC_CTRL__MDC_SIDEBAND_FIFO_SIZE_MASK 0xf0000000
+#define TCC_CTRL__MDC_SIDEBAND_FIFO_SIZE__SHIFT 0x1c
+#define TCC_EDC_CNT__SEC_COUNT_MASK 0xff
+#define TCC_EDC_CNT__SEC_COUNT__SHIFT 0x0
+#define TCC_EDC_CNT__DED_COUNT_MASK 0xff0000
+#define TCC_EDC_CNT__DED_COUNT__SHIFT 0x10
+#define TCC_REDUNDANCY__MC_SEL0_MASK 0x1
+#define TCC_REDUNDANCY__MC_SEL0__SHIFT 0x0
+#define TCC_REDUNDANCY__MC_SEL1_MASK 0x2
+#define TCC_REDUNDANCY__MC_SEL1__SHIFT 0x1
+#define TCC_EXE_DISABLE__EXE_DISABLE_MASK 0x2
+#define TCC_EXE_DISABLE__EXE_DISABLE__SHIFT 0x1
+#define TCC_DSM_CNTL__CACHE_RAM_IRRITATOR_DATA_SEL_MASK 0x3
+#define TCC_DSM_CNTL__CACHE_RAM_IRRITATOR_DATA_SEL__SHIFT 0x0
+#define TCC_DSM_CNTL__CACHE_RAM_IRRITATOR_SINGLE_WRITE_MASK 0x4
+#define TCC_DSM_CNTL__CACHE_RAM_IRRITATOR_SINGLE_WRITE__SHIFT 0x2
+#define TCC_CGTT_SCLK_CTRL__ON_DELAY_MASK 0xf
+#define TCC_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x0
+#define TCC_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define TCC_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define TCA_CGTT_SCLK_CTRL__ON_DELAY_MASK 0xf
+#define TCA_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x0
+#define TCA_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define TCA_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define TCC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define TCC_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCC_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf000000
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x18
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf0000000
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x1c
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf000000
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x18
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf0000000
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x1c
+#define TCC_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define TCC_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define TCC_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCC_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCC_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCC_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCC_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define TCC_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define TCC_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCC_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCC_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCC_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCC_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCC_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCC_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCC_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCC_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCC_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCC_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCC_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCA_CTRL__HOLE_TIMEOUT_MASK 0xf
+#define TCA_CTRL__HOLE_TIMEOUT__SHIFT 0x0
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define TCA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define TCA_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCA_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf000000
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x18
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf0000000
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x1c
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf000000
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x18
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf0000000
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x1c
+#define TCA_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define TCA_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define TCA_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCA_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCA_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCA_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCA_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define TCA_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define TCA_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCA_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCA_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCA_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCA_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCA_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCA_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCA_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCA_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCA_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCA_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCA_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TA_BC_BASE_ADDR__ADDRESS_MASK 0xffffffff
+#define TA_BC_BASE_ADDR__ADDRESS__SHIFT 0x0
+#define TA_BC_BASE_ADDR_HI__ADDRESS_MASK 0xff
+#define TA_BC_BASE_ADDR_HI__ADDRESS__SHIFT 0x0
+#define TD_CNTL__SYNC_PHASE_SH_MASK 0x3
+#define TD_CNTL__SYNC_PHASE_SH__SHIFT 0x0
+#define TD_CNTL__SYNC_PHASE_VC_SMX_MASK 0x30
+#define TD_CNTL__SYNC_PHASE_VC_SMX__SHIFT 0x4
+#define TD_CNTL__PAD_STALL_EN_MASK 0x100
+#define TD_CNTL__PAD_STALL_EN__SHIFT 0x8
+#define TD_CNTL__EXTEND_LDS_STALL_MASK 0x600
+#define TD_CNTL__EXTEND_LDS_STALL__SHIFT 0x9
+#define TD_CNTL__LDS_STALL_PHASE_ADJUST_MASK 0x1800
+#define TD_CNTL__LDS_STALL_PHASE_ADJUST__SHIFT 0xb
+#define TD_CNTL__PRECISION_COMPATIBILITY_MASK 0x8000
+#define TD_CNTL__PRECISION_COMPATIBILITY__SHIFT 0xf
+#define TD_CNTL__GATHER4_FLOAT_MODE_MASK 0x10000
+#define TD_CNTL__GATHER4_FLOAT_MODE__SHIFT 0x10
+#define TD_CNTL__LD_FLOAT_MODE_MASK 0x40000
+#define TD_CNTL__LD_FLOAT_MODE__SHIFT 0x12
+#define TD_CNTL__GATHER4_DX9_MODE_MASK 0x80000
+#define TD_CNTL__GATHER4_DX9_MODE__SHIFT 0x13
+#define TD_CNTL__DISABLE_POWER_THROTTLE_MASK 0x100000
+#define TD_CNTL__DISABLE_POWER_THROTTLE__SHIFT 0x14
+#define TD_CNTL__ENABLE_ROUND_TO_ZERO_MASK 0x200000
+#define TD_CNTL__ENABLE_ROUND_TO_ZERO__SHIFT 0x15
+#define TD_CNTL__DISABLE_D16_PACKING_MASK 0x400000
+#define TD_CNTL__DISABLE_D16_PACKING__SHIFT 0x16
+#define TD_CNTL__DISABLE_2BIT_SIGNED_FORMAT_MASK 0x800000
+#define TD_CNTL__DISABLE_2BIT_SIGNED_FORMAT__SHIFT 0x17
+#define TD_STATUS__BUSY_MASK 0x80000000
+#define TD_STATUS__BUSY__SHIFT 0x1f
+#define TD_DEBUG_INDEX__INDEX_MASK 0x1f
+#define TD_DEBUG_INDEX__INDEX__SHIFT 0x0
+#define TD_DEBUG_DATA__DATA_MASK 0xffffffff
+#define TD_DEBUG_DATA__DATA__SHIFT 0x0
+#define TD_DSM_CNTL__FORCE_SEDB_0_MASK 0x1
+#define TD_DSM_CNTL__FORCE_SEDB_0__SHIFT 0x0
+#define TD_DSM_CNTL__FORCE_SEDB_1_MASK 0x2
+#define TD_DSM_CNTL__FORCE_SEDB_1__SHIFT 0x1
+#define TD_DSM_CNTL__EN_SINGLE_WR_SEDB_MASK 0x4
+#define TD_DSM_CNTL__EN_SINGLE_WR_SEDB__SHIFT 0x2
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0xff
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x3fc00
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define TD_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define TD_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define TD_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0xff
+#define TD_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define TD_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x3fc00
+#define TD_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define TD_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define TD_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define TD_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define TD_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define TD_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define TD_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0xff
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x3fc00
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define TD_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TD_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TD_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TD_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TD_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TD_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TD_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TD_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TD_SCRATCH__SCRATCH_MASK 0xffffffff
+#define TD_SCRATCH__SCRATCH__SHIFT 0x0
+#define TA_CNTL__FX_XNACK_CREDIT_MASK 0x7f
+#define TA_CNTL__FX_XNACK_CREDIT__SHIFT 0x0
+#define TA_CNTL__SQ_XNACK_CREDIT_MASK 0x1e00
+#define TA_CNTL__SQ_XNACK_CREDIT__SHIFT 0x9
+#define TA_CNTL__TC_DATA_CREDIT_MASK 0xe000
+#define TA_CNTL__TC_DATA_CREDIT__SHIFT 0xd
+#define TA_CNTL__ALIGNER_CREDIT_MASK 0x1f0000
+#define TA_CNTL__ALIGNER_CREDIT__SHIFT 0x10
+#define TA_CNTL__TD_FIFO_CREDIT_MASK 0xffc00000
+#define TA_CNTL__TD_FIFO_CREDIT__SHIFT 0x16
+#define TA_CNTL_AUX__SCOAL_DSWIZZLE_N_MASK 0x1
+#define TA_CNTL_AUX__SCOAL_DSWIZZLE_N__SHIFT 0x0
+#define TA_CNTL_AUX__RESERVED_MASK 0xe
+#define TA_CNTL_AUX__RESERVED__SHIFT 0x1
+#define TA_CNTL_AUX__D16_PACK_DISABLE_MASK 0x10
+#define TA_CNTL_AUX__D16_PACK_DISABLE__SHIFT 0x4
+#define TA_CNTL_AUX__ANISO_WEIGHT_MODE_MASK 0x10000
+#define TA_CNTL_AUX__ANISO_WEIGHT_MODE__SHIFT 0x10
+#define TA_CNTL_AUX__ANISO_RATIO_LUT_MASK 0x20000
+#define TA_CNTL_AUX__ANISO_RATIO_LUT__SHIFT 0x11
+#define TA_CNTL_AUX__ANISO_TAP_MASK 0x40000
+#define TA_CNTL_AUX__ANISO_TAP__SHIFT 0x12
+#define TA_CNTL_AUX__ANISO_MIP_ADJ_MODE_MASK 0x80000
+#define TA_CNTL_AUX__ANISO_MIP_ADJ_MODE__SHIFT 0x13
+#define TA_RESERVED_010C__Unused_MASK 0xffffffff
+#define TA_RESERVED_010C__Unused__SHIFT 0x0
+#define TA_CS_BC_BASE_ADDR__ADDRESS_MASK 0xffffffff
+#define TA_CS_BC_BASE_ADDR__ADDRESS__SHIFT 0x0
+#define TA_CS_BC_BASE_ADDR_HI__ADDRESS_MASK 0xff
+#define TA_CS_BC_BASE_ADDR_HI__ADDRESS__SHIFT 0x0
+#define TA_STATUS__FG_PFIFO_EMPTYB_MASK 0x1000
+#define TA_STATUS__FG_PFIFO_EMPTYB__SHIFT 0xc
+#define TA_STATUS__FG_LFIFO_EMPTYB_MASK 0x2000
+#define TA_STATUS__FG_LFIFO_EMPTYB__SHIFT 0xd
+#define TA_STATUS__FG_SFIFO_EMPTYB_MASK 0x4000
+#define TA_STATUS__FG_SFIFO_EMPTYB__SHIFT 0xe
+#define TA_STATUS__FL_PFIFO_EMPTYB_MASK 0x10000
+#define TA_STATUS__FL_PFIFO_EMPTYB__SHIFT 0x10
+#define TA_STATUS__FL_LFIFO_EMPTYB_MASK 0x20000
+#define TA_STATUS__FL_LFIFO_EMPTYB__SHIFT 0x11
+#define TA_STATUS__FL_SFIFO_EMPTYB_MASK 0x40000
+#define TA_STATUS__FL_SFIFO_EMPTYB__SHIFT 0x12
+#define TA_STATUS__FA_PFIFO_EMPTYB_MASK 0x100000
+#define TA_STATUS__FA_PFIFO_EMPTYB__SHIFT 0x14
+#define TA_STATUS__FA_LFIFO_EMPTYB_MASK 0x200000
+#define TA_STATUS__FA_LFIFO_EMPTYB__SHIFT 0x15
+#define TA_STATUS__FA_SFIFO_EMPTYB_MASK 0x400000
+#define TA_STATUS__FA_SFIFO_EMPTYB__SHIFT 0x16
+#define TA_STATUS__IN_BUSY_MASK 0x1000000
+#define TA_STATUS__IN_BUSY__SHIFT 0x18
+#define TA_STATUS__FG_BUSY_MASK 0x2000000
+#define TA_STATUS__FG_BUSY__SHIFT 0x19
+#define TA_STATUS__LA_BUSY_MASK 0x4000000
+#define TA_STATUS__LA_BUSY__SHIFT 0x1a
+#define TA_STATUS__FL_BUSY_MASK 0x8000000
+#define TA_STATUS__FL_BUSY__SHIFT 0x1b
+#define TA_STATUS__TA_BUSY_MASK 0x10000000
+#define TA_STATUS__TA_BUSY__SHIFT 0x1c
+#define TA_STATUS__FA_BUSY_MASK 0x20000000
+#define TA_STATUS__FA_BUSY__SHIFT 0x1d
+#define TA_STATUS__AL_BUSY_MASK 0x40000000
+#define TA_STATUS__AL_BUSY__SHIFT 0x1e
+#define TA_STATUS__BUSY_MASK 0x80000000
+#define TA_STATUS__BUSY__SHIFT 0x1f
+#define TA_DEBUG_INDEX__INDEX_MASK 0x1f
+#define TA_DEBUG_INDEX__INDEX__SHIFT 0x0
+#define TA_DEBUG_DATA__DATA_MASK 0xffffffff
+#define TA_DEBUG_DATA__DATA__SHIFT 0x0
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0xff
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x3fc00
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define TA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define TA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0xff
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x3fc00
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define TA_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define TA_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0xff
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x3fc00
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define TA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TA_SCRATCH__SCRATCH_MASK 0xffffffff
+#define TA_SCRATCH__SCRATCH__SHIFT 0x0
+#define SH_HIDDEN_PRIVATE_BASE_VMID__ADDRESS_MASK 0xffffffff
+#define SH_HIDDEN_PRIVATE_BASE_VMID__ADDRESS__SHIFT 0x0
+#define SH_STATIC_MEM_CONFIG__SWIZZLE_ENABLE_MASK 0x1
+#define SH_STATIC_MEM_CONFIG__SWIZZLE_ENABLE__SHIFT 0x0
+#define SH_STATIC_MEM_CONFIG__ELEMENT_SIZE_MASK 0x6
+#define SH_STATIC_MEM_CONFIG__ELEMENT_SIZE__SHIFT 0x1
+#define SH_STATIC_MEM_CONFIG__INDEX_STRIDE_MASK 0x18
+#define SH_STATIC_MEM_CONFIG__INDEX_STRIDE__SHIFT 0x3
+#define SH_STATIC_MEM_CONFIG__PRIVATE_MTYPE_MASK 0xe0
+#define SH_STATIC_MEM_CONFIG__PRIVATE_MTYPE__SHIFT 0x5
+#define SH_STATIC_MEM_CONFIG__READ_ONLY_CNTL_MASK 0xff00
+#define SH_STATIC_MEM_CONFIG__READ_ONLY_CNTL__SHIFT 0x8
+#define TCP_INVALIDATE__START_MASK 0x1
+#define TCP_INVALIDATE__START__SHIFT 0x0
+#define TCP_STATUS__TCP_BUSY_MASK 0x1
+#define TCP_STATUS__TCP_BUSY__SHIFT 0x0
+#define TCP_STATUS__INPUT_BUSY_MASK 0x2
+#define TCP_STATUS__INPUT_BUSY__SHIFT 0x1
+#define TCP_STATUS__ADRS_BUSY_MASK 0x4
+#define TCP_STATUS__ADRS_BUSY__SHIFT 0x2
+#define TCP_STATUS__TAGRAMS_BUSY_MASK 0x8
+#define TCP_STATUS__TAGRAMS_BUSY__SHIFT 0x3
+#define TCP_STATUS__CNTRL_BUSY_MASK 0x10
+#define TCP_STATUS__CNTRL_BUSY__SHIFT 0x4
+#define TCP_STATUS__LFIFO_BUSY_MASK 0x20
+#define TCP_STATUS__LFIFO_BUSY__SHIFT 0x5
+#define TCP_STATUS__READ_BUSY_MASK 0x40
+#define TCP_STATUS__READ_BUSY__SHIFT 0x6
+#define TCP_STATUS__FORMAT_BUSY_MASK 0x80
+#define TCP_STATUS__FORMAT_BUSY__SHIFT 0x7
+#define TCP_CNTL__FORCE_HIT_MASK 0x1
+#define TCP_CNTL__FORCE_HIT__SHIFT 0x0
+#define TCP_CNTL__FORCE_MISS_MASK 0x2
+#define TCP_CNTL__FORCE_MISS__SHIFT 0x1
+#define TCP_CNTL__L1_SIZE_MASK 0xc
+#define TCP_CNTL__L1_SIZE__SHIFT 0x2
+#define TCP_CNTL__FLAT_BUF_HASH_ENABLE_MASK 0x10
+#define TCP_CNTL__FLAT_BUF_HASH_ENABLE__SHIFT 0x4
+#define TCP_CNTL__FLAT_BUF_CACHE_SWIZZLE_MASK 0x20
+#define TCP_CNTL__FLAT_BUF_CACHE_SWIZZLE__SHIFT 0x5
+#define TCP_CNTL__FORCE_EOW_TOTAL_CNT_MASK 0x1f8000
+#define TCP_CNTL__FORCE_EOW_TOTAL_CNT__SHIFT 0xf
+#define TCP_CNTL__FORCE_EOW_TAGRAM_CNT_MASK 0xfc00000
+#define TCP_CNTL__FORCE_EOW_TAGRAM_CNT__SHIFT 0x16
+#define TCP_CNTL__DISABLE_Z_MAP_MASK 0x10000000
+#define TCP_CNTL__DISABLE_Z_MAP__SHIFT 0x1c
+#define TCP_CNTL__INV_ALL_VMIDS_MASK 0x20000000
+#define TCP_CNTL__INV_ALL_VMIDS__SHIFT 0x1d
+#define TCP_CHAN_STEER_LO__CHAN0_MASK 0xf
+#define TCP_CHAN_STEER_LO__CHAN0__SHIFT 0x0
+#define TCP_CHAN_STEER_LO__CHAN1_MASK 0xf0
+#define TCP_CHAN_STEER_LO__CHAN1__SHIFT 0x4
+#define TCP_CHAN_STEER_LO__CHAN2_MASK 0xf00
+#define TCP_CHAN_STEER_LO__CHAN2__SHIFT 0x8
+#define TCP_CHAN_STEER_LO__CHAN3_MASK 0xf000
+#define TCP_CHAN_STEER_LO__CHAN3__SHIFT 0xc
+#define TCP_CHAN_STEER_LO__CHAN4_MASK 0xf0000
+#define TCP_CHAN_STEER_LO__CHAN4__SHIFT 0x10
+#define TCP_CHAN_STEER_LO__CHAN5_MASK 0xf00000
+#define TCP_CHAN_STEER_LO__CHAN5__SHIFT 0x14
+#define TCP_CHAN_STEER_LO__CHAN6_MASK 0xf000000
+#define TCP_CHAN_STEER_LO__CHAN6__SHIFT 0x18
+#define TCP_CHAN_STEER_LO__CHAN7_MASK 0xf0000000
+#define TCP_CHAN_STEER_LO__CHAN7__SHIFT 0x1c
+#define TCP_CHAN_STEER_HI__CHAN8_MASK 0xf
+#define TCP_CHAN_STEER_HI__CHAN8__SHIFT 0x0
+#define TCP_CHAN_STEER_HI__CHAN9_MASK 0xf0
+#define TCP_CHAN_STEER_HI__CHAN9__SHIFT 0x4
+#define TCP_CHAN_STEER_HI__CHANA_MASK 0xf00
+#define TCP_CHAN_STEER_HI__CHANA__SHIFT 0x8
+#define TCP_CHAN_STEER_HI__CHANB_MASK 0xf000
+#define TCP_CHAN_STEER_HI__CHANB__SHIFT 0xc
+#define TCP_CHAN_STEER_HI__CHANC_MASK 0xf0000
+#define TCP_CHAN_STEER_HI__CHANC__SHIFT 0x10
+#define TCP_CHAN_STEER_HI__CHAND_MASK 0xf00000
+#define TCP_CHAN_STEER_HI__CHAND__SHIFT 0x14
+#define TCP_CHAN_STEER_HI__CHANE_MASK 0xf000000
+#define TCP_CHAN_STEER_HI__CHANE__SHIFT 0x18
+#define TCP_CHAN_STEER_HI__CHANF_MASK 0xf0000000
+#define TCP_CHAN_STEER_HI__CHANF__SHIFT 0x1c
+#define TCP_ADDR_CONFIG__NUM_TCC_BANKS_MASK 0xf
+#define TCP_ADDR_CONFIG__NUM_TCC_BANKS__SHIFT 0x0
+#define TCP_ADDR_CONFIG__NUM_BANKS_MASK 0x30
+#define TCP_ADDR_CONFIG__NUM_BANKS__SHIFT 0x4
+#define TCP_ADDR_CONFIG__COLHI_WIDTH_MASK 0x1c0
+#define TCP_ADDR_CONFIG__COLHI_WIDTH__SHIFT 0x6
+#define TCP_ADDR_CONFIG__RB_SPLIT_COLHI_MASK 0x200
+#define TCP_ADDR_CONFIG__RB_SPLIT_COLHI__SHIFT 0x9
+#define TCP_CREDIT__LFIFO_CREDIT_MASK 0x3ff
+#define TCP_CREDIT__LFIFO_CREDIT__SHIFT 0x0
+#define TCP_CREDIT__REQ_FIFO_CREDIT_MASK 0x7f0000
+#define TCP_CREDIT__REQ_FIFO_CREDIT__SHIFT 0x10
+#define TCP_CREDIT__TD_CREDIT_MASK 0xe0000000
+#define TCP_CREDIT__TD_CREDIT__SHIFT 0x1d
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define TCP_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCP_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define TCP_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCP_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf000000
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x18
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define TCP_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x3ff
+#define TCP_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define TCP_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCP_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCP_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCP_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCP_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x3ff
+#define TCP_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define TCP_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define TCP_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define TCP_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define TCP_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define TCP_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCP_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCP_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCP_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCP_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCP_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCP_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define TCP_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define TCP_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCP_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCP_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCP_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCP_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCP_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCP_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define TCP_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_BITS_MASK 0x7
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_BITS__SHIFT 0x0
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_BITS_MASK 0x700
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_BITS__SHIFT 0x8
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_XOR_COUNT_MASK 0x70000
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_XOR_COUNT__SHIFT 0x10
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_XOR_COUNT_MASK 0x7000000
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_XOR_COUNT__SHIFT 0x18
+#define TCP_EDC_CNT__SEC_COUNT_MASK 0xff
+#define TCP_EDC_CNT__SEC_COUNT__SHIFT 0x0
+#define TCP_EDC_CNT__LFIFO_SED_COUNT_MASK 0xff00
+#define TCP_EDC_CNT__LFIFO_SED_COUNT__SHIFT 0x8
+#define TCP_EDC_CNT__DED_COUNT_MASK 0xff0000
+#define TCP_EDC_CNT__DED_COUNT__SHIFT 0x10
+#define TCP_EDC_CNT__UNUSED_MASK 0xff000000
+#define TCP_EDC_CNT__UNUSED__SHIFT 0x18
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_0_MASK 0x3
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_0__SHIFT 0x0
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_1_MASK 0xc
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_1__SHIFT 0x2
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_2_MASK 0x30
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_2__SHIFT 0x4
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_3_MASK 0xc0
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_3__SHIFT 0x6
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_4_MASK 0x300
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_4__SHIFT 0x8
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_5_MASK 0xc00
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_5__SHIFT 0xa
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_6_MASK 0x3000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_6__SHIFT 0xc
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_7_MASK 0xc000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_7__SHIFT 0xe
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_8_MASK 0x30000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_8__SHIFT 0x10
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_9_MASK 0xc0000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_9__SHIFT 0x12
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_10_MASK 0x300000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_10__SHIFT 0x14
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_11_MASK 0xc00000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_11__SHIFT 0x16
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_12_MASK 0x3000000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_12__SHIFT 0x18
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_13_MASK 0xc000000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_13__SHIFT 0x1a
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_14_MASK 0x30000000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_14__SHIFT 0x1c
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_15_MASK 0xc0000000
+#define TC_CFG_L1_LOAD_POLICY0__POLICY_15__SHIFT 0x1e
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_16_MASK 0x3
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_16__SHIFT 0x0
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_17_MASK 0xc
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_17__SHIFT 0x2
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_18_MASK 0x30
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_18__SHIFT 0x4
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_19_MASK 0xc0
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_19__SHIFT 0x6
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_20_MASK 0x300
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_20__SHIFT 0x8
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_21_MASK 0xc00
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_21__SHIFT 0xa
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_22_MASK 0x3000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_22__SHIFT 0xc
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_23_MASK 0xc000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_23__SHIFT 0xe
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_24_MASK 0x30000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_24__SHIFT 0x10
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_25_MASK 0xc0000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_25__SHIFT 0x12
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_26_MASK 0x300000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_26__SHIFT 0x14
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_27_MASK 0xc00000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_27__SHIFT 0x16
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_28_MASK 0x3000000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_28__SHIFT 0x18
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_29_MASK 0xc000000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_29__SHIFT 0x1a
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_30_MASK 0x30000000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_30__SHIFT 0x1c
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_31_MASK 0xc0000000
+#define TC_CFG_L1_LOAD_POLICY1__POLICY_31__SHIFT 0x1e
+#define TC_CFG_L1_STORE_POLICY__POLICY_0_MASK 0x1
+#define TC_CFG_L1_STORE_POLICY__POLICY_0__SHIFT 0x0
+#define TC_CFG_L1_STORE_POLICY__POLICY_1_MASK 0x2
+#define TC_CFG_L1_STORE_POLICY__POLICY_1__SHIFT 0x1
+#define TC_CFG_L1_STORE_POLICY__POLICY_2_MASK 0x4
+#define TC_CFG_L1_STORE_POLICY__POLICY_2__SHIFT 0x2
+#define TC_CFG_L1_STORE_POLICY__POLICY_3_MASK 0x8
+#define TC_CFG_L1_STORE_POLICY__POLICY_3__SHIFT 0x3
+#define TC_CFG_L1_STORE_POLICY__POLICY_4_MASK 0x10
+#define TC_CFG_L1_STORE_POLICY__POLICY_4__SHIFT 0x4
+#define TC_CFG_L1_STORE_POLICY__POLICY_5_MASK 0x20
+#define TC_CFG_L1_STORE_POLICY__POLICY_5__SHIFT 0x5
+#define TC_CFG_L1_STORE_POLICY__POLICY_6_MASK 0x40
+#define TC_CFG_L1_STORE_POLICY__POLICY_6__SHIFT 0x6
+#define TC_CFG_L1_STORE_POLICY__POLICY_7_MASK 0x80
+#define TC_CFG_L1_STORE_POLICY__POLICY_7__SHIFT 0x7
+#define TC_CFG_L1_STORE_POLICY__POLICY_8_MASK 0x100
+#define TC_CFG_L1_STORE_POLICY__POLICY_8__SHIFT 0x8
+#define TC_CFG_L1_STORE_POLICY__POLICY_9_MASK 0x200
+#define TC_CFG_L1_STORE_POLICY__POLICY_9__SHIFT 0x9
+#define TC_CFG_L1_STORE_POLICY__POLICY_10_MASK 0x400
+#define TC_CFG_L1_STORE_POLICY__POLICY_10__SHIFT 0xa
+#define TC_CFG_L1_STORE_POLICY__POLICY_11_MASK 0x800
+#define TC_CFG_L1_STORE_POLICY__POLICY_11__SHIFT 0xb
+#define TC_CFG_L1_STORE_POLICY__POLICY_12_MASK 0x1000
+#define TC_CFG_L1_STORE_POLICY__POLICY_12__SHIFT 0xc
+#define TC_CFG_L1_STORE_POLICY__POLICY_13_MASK 0x2000
+#define TC_CFG_L1_STORE_POLICY__POLICY_13__SHIFT 0xd
+#define TC_CFG_L1_STORE_POLICY__POLICY_14_MASK 0x4000
+#define TC_CFG_L1_STORE_POLICY__POLICY_14__SHIFT 0xe
+#define TC_CFG_L1_STORE_POLICY__POLICY_15_MASK 0x8000
+#define TC_CFG_L1_STORE_POLICY__POLICY_15__SHIFT 0xf
+#define TC_CFG_L1_STORE_POLICY__POLICY_16_MASK 0x10000
+#define TC_CFG_L1_STORE_POLICY__POLICY_16__SHIFT 0x10
+#define TC_CFG_L1_STORE_POLICY__POLICY_17_MASK 0x20000
+#define TC_CFG_L1_STORE_POLICY__POLICY_17__SHIFT 0x11
+#define TC_CFG_L1_STORE_POLICY__POLICY_18_MASK 0x40000
+#define TC_CFG_L1_STORE_POLICY__POLICY_18__SHIFT 0x12
+#define TC_CFG_L1_STORE_POLICY__POLICY_19_MASK 0x80000
+#define TC_CFG_L1_STORE_POLICY__POLICY_19__SHIFT 0x13
+#define TC_CFG_L1_STORE_POLICY__POLICY_20_MASK 0x100000
+#define TC_CFG_L1_STORE_POLICY__POLICY_20__SHIFT 0x14
+#define TC_CFG_L1_STORE_POLICY__POLICY_21_MASK 0x200000
+#define TC_CFG_L1_STORE_POLICY__POLICY_21__SHIFT 0x15
+#define TC_CFG_L1_STORE_POLICY__POLICY_22_MASK 0x400000
+#define TC_CFG_L1_STORE_POLICY__POLICY_22__SHIFT 0x16
+#define TC_CFG_L1_STORE_POLICY__POLICY_23_MASK 0x800000
+#define TC_CFG_L1_STORE_POLICY__POLICY_23__SHIFT 0x17
+#define TC_CFG_L1_STORE_POLICY__POLICY_24_MASK 0x1000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_24__SHIFT 0x18
+#define TC_CFG_L1_STORE_POLICY__POLICY_25_MASK 0x2000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_25__SHIFT 0x19
+#define TC_CFG_L1_STORE_POLICY__POLICY_26_MASK 0x4000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_26__SHIFT 0x1a
+#define TC_CFG_L1_STORE_POLICY__POLICY_27_MASK 0x8000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_27__SHIFT 0x1b
+#define TC_CFG_L1_STORE_POLICY__POLICY_28_MASK 0x10000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_28__SHIFT 0x1c
+#define TC_CFG_L1_STORE_POLICY__POLICY_29_MASK 0x20000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_29__SHIFT 0x1d
+#define TC_CFG_L1_STORE_POLICY__POLICY_30_MASK 0x40000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_30__SHIFT 0x1e
+#define TC_CFG_L1_STORE_POLICY__POLICY_31_MASK 0x80000000
+#define TC_CFG_L1_STORE_POLICY__POLICY_31__SHIFT 0x1f
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_0_MASK 0x3
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_0__SHIFT 0x0
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_1_MASK 0xc
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_1__SHIFT 0x2
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_2_MASK 0x30
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_2__SHIFT 0x4
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_3_MASK 0xc0
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_3__SHIFT 0x6
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_4_MASK 0x300
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_4__SHIFT 0x8
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_5_MASK 0xc00
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_5__SHIFT 0xa
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_6_MASK 0x3000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_6__SHIFT 0xc
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_7_MASK 0xc000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_7__SHIFT 0xe
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_8_MASK 0x30000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_8__SHIFT 0x10
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_9_MASK 0xc0000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_9__SHIFT 0x12
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_10_MASK 0x300000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_10__SHIFT 0x14
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_11_MASK 0xc00000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_11__SHIFT 0x16
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_12_MASK 0x3000000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_12__SHIFT 0x18
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_13_MASK 0xc000000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_13__SHIFT 0x1a
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_14_MASK 0x30000000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_14__SHIFT 0x1c
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_15_MASK 0xc0000000
+#define TC_CFG_L2_LOAD_POLICY0__POLICY_15__SHIFT 0x1e
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_16_MASK 0x3
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_16__SHIFT 0x0
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_17_MASK 0xc
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_17__SHIFT 0x2
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_18_MASK 0x30
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_18__SHIFT 0x4
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_19_MASK 0xc0
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_19__SHIFT 0x6
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_20_MASK 0x300
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_20__SHIFT 0x8
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_21_MASK 0xc00
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_21__SHIFT 0xa
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_22_MASK 0x3000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_22__SHIFT 0xc
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_23_MASK 0xc000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_23__SHIFT 0xe
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_24_MASK 0x30000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_24__SHIFT 0x10
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_25_MASK 0xc0000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_25__SHIFT 0x12
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_26_MASK 0x300000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_26__SHIFT 0x14
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_27_MASK 0xc00000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_27__SHIFT 0x16
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_28_MASK 0x3000000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_28__SHIFT 0x18
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_29_MASK 0xc000000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_29__SHIFT 0x1a
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_30_MASK 0x30000000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_30__SHIFT 0x1c
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_31_MASK 0xc0000000
+#define TC_CFG_L2_LOAD_POLICY1__POLICY_31__SHIFT 0x1e
+#define TC_CFG_L2_STORE_POLICY0__POLICY_0_MASK 0x3
+#define TC_CFG_L2_STORE_POLICY0__POLICY_0__SHIFT 0x0
+#define TC_CFG_L2_STORE_POLICY0__POLICY_1_MASK 0xc
+#define TC_CFG_L2_STORE_POLICY0__POLICY_1__SHIFT 0x2
+#define TC_CFG_L2_STORE_POLICY0__POLICY_2_MASK 0x30
+#define TC_CFG_L2_STORE_POLICY0__POLICY_2__SHIFT 0x4
+#define TC_CFG_L2_STORE_POLICY0__POLICY_3_MASK 0xc0
+#define TC_CFG_L2_STORE_POLICY0__POLICY_3__SHIFT 0x6
+#define TC_CFG_L2_STORE_POLICY0__POLICY_4_MASK 0x300
+#define TC_CFG_L2_STORE_POLICY0__POLICY_4__SHIFT 0x8
+#define TC_CFG_L2_STORE_POLICY0__POLICY_5_MASK 0xc00
+#define TC_CFG_L2_STORE_POLICY0__POLICY_5__SHIFT 0xa
+#define TC_CFG_L2_STORE_POLICY0__POLICY_6_MASK 0x3000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_6__SHIFT 0xc
+#define TC_CFG_L2_STORE_POLICY0__POLICY_7_MASK 0xc000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_7__SHIFT 0xe
+#define TC_CFG_L2_STORE_POLICY0__POLICY_8_MASK 0x30000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_8__SHIFT 0x10
+#define TC_CFG_L2_STORE_POLICY0__POLICY_9_MASK 0xc0000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_9__SHIFT 0x12
+#define TC_CFG_L2_STORE_POLICY0__POLICY_10_MASK 0x300000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_10__SHIFT 0x14
+#define TC_CFG_L2_STORE_POLICY0__POLICY_11_MASK 0xc00000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_11__SHIFT 0x16
+#define TC_CFG_L2_STORE_POLICY0__POLICY_12_MASK 0x3000000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_12__SHIFT 0x18
+#define TC_CFG_L2_STORE_POLICY0__POLICY_13_MASK 0xc000000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_13__SHIFT 0x1a
+#define TC_CFG_L2_STORE_POLICY0__POLICY_14_MASK 0x30000000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_14__SHIFT 0x1c
+#define TC_CFG_L2_STORE_POLICY0__POLICY_15_MASK 0xc0000000
+#define TC_CFG_L2_STORE_POLICY0__POLICY_15__SHIFT 0x1e
+#define TC_CFG_L2_STORE_POLICY1__POLICY_16_MASK 0x3
+#define TC_CFG_L2_STORE_POLICY1__POLICY_16__SHIFT 0x0
+#define TC_CFG_L2_STORE_POLICY1__POLICY_17_MASK 0xc
+#define TC_CFG_L2_STORE_POLICY1__POLICY_17__SHIFT 0x2
+#define TC_CFG_L2_STORE_POLICY1__POLICY_18_MASK 0x30
+#define TC_CFG_L2_STORE_POLICY1__POLICY_18__SHIFT 0x4
+#define TC_CFG_L2_STORE_POLICY1__POLICY_19_MASK 0xc0
+#define TC_CFG_L2_STORE_POLICY1__POLICY_19__SHIFT 0x6
+#define TC_CFG_L2_STORE_POLICY1__POLICY_20_MASK 0x300
+#define TC_CFG_L2_STORE_POLICY1__POLICY_20__SHIFT 0x8
+#define TC_CFG_L2_STORE_POLICY1__POLICY_21_MASK 0xc00
+#define TC_CFG_L2_STORE_POLICY1__POLICY_21__SHIFT 0xa
+#define TC_CFG_L2_STORE_POLICY1__POLICY_22_MASK 0x3000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_22__SHIFT 0xc
+#define TC_CFG_L2_STORE_POLICY1__POLICY_23_MASK 0xc000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_23__SHIFT 0xe
+#define TC_CFG_L2_STORE_POLICY1__POLICY_24_MASK 0x30000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_24__SHIFT 0x10
+#define TC_CFG_L2_STORE_POLICY1__POLICY_25_MASK 0xc0000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_25__SHIFT 0x12
+#define TC_CFG_L2_STORE_POLICY1__POLICY_26_MASK 0x300000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_26__SHIFT 0x14
+#define TC_CFG_L2_STORE_POLICY1__POLICY_27_MASK 0xc00000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_27__SHIFT 0x16
+#define TC_CFG_L2_STORE_POLICY1__POLICY_28_MASK 0x3000000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_28__SHIFT 0x18
+#define TC_CFG_L2_STORE_POLICY1__POLICY_29_MASK 0xc000000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_29__SHIFT 0x1a
+#define TC_CFG_L2_STORE_POLICY1__POLICY_30_MASK 0x30000000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_30__SHIFT 0x1c
+#define TC_CFG_L2_STORE_POLICY1__POLICY_31_MASK 0xc0000000
+#define TC_CFG_L2_STORE_POLICY1__POLICY_31__SHIFT 0x1e
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_0_MASK 0x3
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_0__SHIFT 0x0
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_1_MASK 0xc
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_1__SHIFT 0x2
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_2_MASK 0x30
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_2__SHIFT 0x4
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_3_MASK 0xc0
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_3__SHIFT 0x6
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_4_MASK 0x300
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_4__SHIFT 0x8
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_5_MASK 0xc00
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_5__SHIFT 0xa
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_6_MASK 0x3000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_6__SHIFT 0xc
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_7_MASK 0xc000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_7__SHIFT 0xe
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_8_MASK 0x30000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_8__SHIFT 0x10
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_9_MASK 0xc0000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_9__SHIFT 0x12
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_10_MASK 0x300000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_10__SHIFT 0x14
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_11_MASK 0xc00000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_11__SHIFT 0x16
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_12_MASK 0x3000000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_12__SHIFT 0x18
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_13_MASK 0xc000000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_13__SHIFT 0x1a
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_14_MASK 0x30000000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_14__SHIFT 0x1c
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_15_MASK 0xc0000000
+#define TC_CFG_L2_ATOMIC_POLICY__POLICY_15__SHIFT 0x1e
+#define TC_CFG_L1_VOLATILE__VOL_MASK 0xf
+#define TC_CFG_L1_VOLATILE__VOL__SHIFT 0x0
+#define TC_CFG_L2_VOLATILE__VOL_MASK 0xf
+#define TC_CFG_L2_VOLATILE__VOL__SHIFT 0x0
+#define TCP_WATCH0_ADDR_H__ADDR_MASK 0xffff
+#define TCP_WATCH0_ADDR_H__ADDR__SHIFT 0x0
+#define TCP_WATCH1_ADDR_H__ADDR_MASK 0xffff
+#define TCP_WATCH1_ADDR_H__ADDR__SHIFT 0x0
+#define TCP_WATCH2_ADDR_H__ADDR_MASK 0xffff
+#define TCP_WATCH2_ADDR_H__ADDR__SHIFT 0x0
+#define TCP_WATCH3_ADDR_H__ADDR_MASK 0xffff
+#define TCP_WATCH3_ADDR_H__ADDR__SHIFT 0x0
+#define TCP_WATCH0_ADDR_L__ADDR_MASK 0xffffffc0
+#define TCP_WATCH0_ADDR_L__ADDR__SHIFT 0x6
+#define TCP_WATCH1_ADDR_L__ADDR_MASK 0xffffffc0
+#define TCP_WATCH1_ADDR_L__ADDR__SHIFT 0x6
+#define TCP_WATCH2_ADDR_L__ADDR_MASK 0xffffffc0
+#define TCP_WATCH2_ADDR_L__ADDR__SHIFT 0x6
+#define TCP_WATCH3_ADDR_L__ADDR_MASK 0xffffffc0
+#define TCP_WATCH3_ADDR_L__ADDR__SHIFT 0x6
+#define TCP_WATCH0_CNTL__MASK_MASK 0xffffff
+#define TCP_WATCH0_CNTL__MASK__SHIFT 0x0
+#define TCP_WATCH0_CNTL__VMID_MASK 0xf000000
+#define TCP_WATCH0_CNTL__VMID__SHIFT 0x18
+#define TCP_WATCH0_CNTL__ATC_MASK 0x10000000
+#define TCP_WATCH0_CNTL__ATC__SHIFT 0x1c
+#define TCP_WATCH0_CNTL__MODE_MASK 0x60000000
+#define TCP_WATCH0_CNTL__MODE__SHIFT 0x1d
+#define TCP_WATCH0_CNTL__VALID_MASK 0x80000000
+#define TCP_WATCH0_CNTL__VALID__SHIFT 0x1f
+#define TCP_WATCH1_CNTL__MASK_MASK 0xffffff
+#define TCP_WATCH1_CNTL__MASK__SHIFT 0x0
+#define TCP_WATCH1_CNTL__VMID_MASK 0xf000000
+#define TCP_WATCH1_CNTL__VMID__SHIFT 0x18
+#define TCP_WATCH1_CNTL__ATC_MASK 0x10000000
+#define TCP_WATCH1_CNTL__ATC__SHIFT 0x1c
+#define TCP_WATCH1_CNTL__MODE_MASK 0x60000000
+#define TCP_WATCH1_CNTL__MODE__SHIFT 0x1d
+#define TCP_WATCH1_CNTL__VALID_MASK 0x80000000
+#define TCP_WATCH1_CNTL__VALID__SHIFT 0x1f
+#define TCP_WATCH2_CNTL__MASK_MASK 0xffffff
+#define TCP_WATCH2_CNTL__MASK__SHIFT 0x0
+#define TCP_WATCH2_CNTL__VMID_MASK 0xf000000
+#define TCP_WATCH2_CNTL__VMID__SHIFT 0x18
+#define TCP_WATCH2_CNTL__ATC_MASK 0x10000000
+#define TCP_WATCH2_CNTL__ATC__SHIFT 0x1c
+#define TCP_WATCH2_CNTL__MODE_MASK 0x60000000
+#define TCP_WATCH2_CNTL__MODE__SHIFT 0x1d
+#define TCP_WATCH2_CNTL__VALID_MASK 0x80000000
+#define TCP_WATCH2_CNTL__VALID__SHIFT 0x1f
+#define TCP_WATCH3_CNTL__MASK_MASK 0xffffff
+#define TCP_WATCH3_CNTL__MASK__SHIFT 0x0
+#define TCP_WATCH3_CNTL__VMID_MASK 0xf000000
+#define TCP_WATCH3_CNTL__VMID__SHIFT 0x18
+#define TCP_WATCH3_CNTL__ATC_MASK 0x10000000
+#define TCP_WATCH3_CNTL__ATC__SHIFT 0x1c
+#define TCP_WATCH3_CNTL__MODE_MASK 0x60000000
+#define TCP_WATCH3_CNTL__MODE__SHIFT 0x1d
+#define TCP_WATCH3_CNTL__VALID_MASK 0x80000000
+#define TCP_WATCH3_CNTL__VALID__SHIFT 0x1f
+#define TCP_GATCL1_CNTL__INVALIDATE_ALL_VMID_MASK 0x2000000
+#define TCP_GATCL1_CNTL__INVALIDATE_ALL_VMID__SHIFT 0x19
+#define TCP_GATCL1_CNTL__FORCE_MISS_MASK 0x4000000
+#define TCP_GATCL1_CNTL__FORCE_MISS__SHIFT 0x1a
+#define TCP_GATCL1_CNTL__FORCE_IN_ORDER_MASK 0x8000000
+#define TCP_GATCL1_CNTL__FORCE_IN_ORDER__SHIFT 0x1b
+#define TCP_GATCL1_CNTL__REDUCE_FIFO_DEPTH_BY_2_MASK 0x30000000
+#define TCP_GATCL1_CNTL__REDUCE_FIFO_DEPTH_BY_2__SHIFT 0x1c
+#define TCP_GATCL1_CNTL__REDUCE_CACHE_SIZE_BY_2_MASK 0xc0000000
+#define TCP_GATCL1_CNTL__REDUCE_CACHE_SIZE_BY_2__SHIFT 0x1e
+#define TCP_ATC_EDC_GATCL1_CNT__DATA_SEC_MASK 0xff
+#define TCP_ATC_EDC_GATCL1_CNT__DATA_SEC__SHIFT 0x0
+#define TCP_GATCL1_DSM_CNTL__SEL_DSM_TCP_GATCL1_IRRITATOR_DATA_A0_MASK 0x1
+#define TCP_GATCL1_DSM_CNTL__SEL_DSM_TCP_GATCL1_IRRITATOR_DATA_A0__SHIFT 0x0
+#define TCP_GATCL1_DSM_CNTL__SEL_DSM_TCP_GATCL1_IRRITATOR_DATA_A1_MASK 0x2
+#define TCP_GATCL1_DSM_CNTL__SEL_DSM_TCP_GATCL1_IRRITATOR_DATA_A1__SHIFT 0x1
+#define TCP_GATCL1_DSM_CNTL__TCP_GATCL1_ENABLE_SINGLE_WRITE_A_MASK 0x4
+#define TCP_GATCL1_DSM_CNTL__TCP_GATCL1_ENABLE_SINGLE_WRITE_A__SHIFT 0x2
+#define TCP_DSM_CNTL__CACHE_RAM_IRRITATOR_DATA_SEL_MASK 0x3
+#define TCP_DSM_CNTL__CACHE_RAM_IRRITATOR_DATA_SEL__SHIFT 0x0
+#define TCP_DSM_CNTL__CACHE_RAM_IRRITATOR_SINGLE_WRITE_MASK 0x4
+#define TCP_DSM_CNTL__CACHE_RAM_IRRITATOR_SINGLE_WRITE__SHIFT 0x2
+#define TCP_DSM_CNTL__LFIFO_RAM_IRRITATOR_DATA_SEL_MASK 0x18
+#define TCP_DSM_CNTL__LFIFO_RAM_IRRITATOR_DATA_SEL__SHIFT 0x3
+#define TCP_DSM_CNTL__LFIFO_RAM_IRRITATOR_SINGLE_WRITE_MASK 0x20
+#define TCP_DSM_CNTL__LFIFO_RAM_IRRITATOR_SINGLE_WRITE__SHIFT 0x5
+#define TCP_CNTL2__LS_DISABLE_CLOCKS_MASK 0xff
+#define TCP_CNTL2__LS_DISABLE_CLOCKS__SHIFT 0x0
+#define TD_CGTT_CTRL__ON_DELAY_MASK 0xf
+#define TD_CGTT_CTRL__ON_DELAY__SHIFT 0x0
+#define TD_CGTT_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define TD_CGTT_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define TD_CGTT_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define TD_CGTT_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define TD_CGTT_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define TD_CGTT_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define TD_CGTT_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define TD_CGTT_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define TD_CGTT_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define TD_CGTT_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define TA_CGTT_CTRL__ON_DELAY_MASK 0xf
+#define TA_CGTT_CTRL__ON_DELAY__SHIFT 0x0
+#define TA_CGTT_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define TA_CGTT_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define TA_CGTT_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define TA_CGTT_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define TA_CGTT_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define TA_CGTT_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define TA_CGTT_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define TA_CGTT_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define TA_CGTT_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define TA_CGTT_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CGTT_TCP_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_TCP_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_TCP_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_TCP_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define CGTT_TCI_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_TCI_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_TCI_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_TCI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define TCI_STATUS__TCI_BUSY_MASK 0x1
+#define TCI_STATUS__TCI_BUSY__SHIFT 0x0
+#define TCI_CNTL_1__WBINVL1_NUM_CYCLES_MASK 0xffff
+#define TCI_CNTL_1__WBINVL1_NUM_CYCLES__SHIFT 0x0
+#define TCI_CNTL_1__REQ_FIFO_DEPTH_MASK 0xff0000
+#define TCI_CNTL_1__REQ_FIFO_DEPTH__SHIFT 0x10
+#define TCI_CNTL_1__WDATA_RAM_DEPTH_MASK 0xff000000
+#define TCI_CNTL_1__WDATA_RAM_DEPTH__SHIFT 0x18
+#define TCI_CNTL_2__L1_INVAL_ON_WBINVL2_MASK 0x1
+#define TCI_CNTL_2__L1_INVAL_ON_WBINVL2__SHIFT 0x0
+#define TCI_CNTL_2__TCA_MAX_CREDIT_MASK 0x1fe
+#define TCI_CNTL_2__TCA_MAX_CREDIT__SHIFT 0x1
+#define GDS_CONFIG__SH0_GPR_PHASE_SEL_MASK 0x6
+#define GDS_CONFIG__SH0_GPR_PHASE_SEL__SHIFT 0x1
+#define GDS_CONFIG__SH1_GPR_PHASE_SEL_MASK 0x18
+#define GDS_CONFIG__SH1_GPR_PHASE_SEL__SHIFT 0x3
+#define GDS_CONFIG__SH2_GPR_PHASE_SEL_MASK 0x60
+#define GDS_CONFIG__SH2_GPR_PHASE_SEL__SHIFT 0x5
+#define GDS_CONFIG__SH3_GPR_PHASE_SEL_MASK 0x180
+#define GDS_CONFIG__SH3_GPR_PHASE_SEL__SHIFT 0x7
+#define GDS_CNTL_STATUS__GDS_BUSY_MASK 0x1
+#define GDS_CNTL_STATUS__GDS_BUSY__SHIFT 0x0
+#define GDS_CNTL_STATUS__GRBM_WBUF_BUSY_MASK 0x2
+#define GDS_CNTL_STATUS__GRBM_WBUF_BUSY__SHIFT 0x1
+#define GDS_CNTL_STATUS__ORD_APP_BUSY_MASK 0x4
+#define GDS_CNTL_STATUS__ORD_APP_BUSY__SHIFT 0x2
+#define GDS_CNTL_STATUS__DS_BANK_CONFLICT_MASK 0x8
+#define GDS_CNTL_STATUS__DS_BANK_CONFLICT__SHIFT 0x3
+#define GDS_CNTL_STATUS__DS_ADDR_CONFLICT_MASK 0x10
+#define GDS_CNTL_STATUS__DS_ADDR_CONFLICT__SHIFT 0x4
+#define GDS_CNTL_STATUS__DS_WR_CLAMP_MASK 0x20
+#define GDS_CNTL_STATUS__DS_WR_CLAMP__SHIFT 0x5
+#define GDS_CNTL_STATUS__DS_RD_CLAMP_MASK 0x40
+#define GDS_CNTL_STATUS__DS_RD_CLAMP__SHIFT 0x6
+#define GDS_CNTL_STATUS__GRBM_RBUF_BUSY_MASK 0x80
+#define GDS_CNTL_STATUS__GRBM_RBUF_BUSY__SHIFT 0x7
+#define GDS_CNTL_STATUS__DS_BUSY_MASK 0x100
+#define GDS_CNTL_STATUS__DS_BUSY__SHIFT 0x8
+#define GDS_CNTL_STATUS__GWS_BUSY_MASK 0x200
+#define GDS_CNTL_STATUS__GWS_BUSY__SHIFT 0x9
+#define GDS_CNTL_STATUS__ORD_FIFO_BUSY_MASK 0x400
+#define GDS_CNTL_STATUS__ORD_FIFO_BUSY__SHIFT 0xa
+#define GDS_CNTL_STATUS__CREDIT_BUSY0_MASK 0x800
+#define GDS_CNTL_STATUS__CREDIT_BUSY0__SHIFT 0xb
+#define GDS_CNTL_STATUS__CREDIT_BUSY1_MASK 0x1000
+#define GDS_CNTL_STATUS__CREDIT_BUSY1__SHIFT 0xc
+#define GDS_CNTL_STATUS__CREDIT_BUSY2_MASK 0x2000
+#define GDS_CNTL_STATUS__CREDIT_BUSY2__SHIFT 0xd
+#define GDS_CNTL_STATUS__CREDIT_BUSY3_MASK 0x4000
+#define GDS_CNTL_STATUS__CREDIT_BUSY3__SHIFT 0xe
+#define GDS_ENHANCE2__MISC_MASK 0xffff
+#define GDS_ENHANCE2__MISC__SHIFT 0x0
+#define GDS_ENHANCE2__UNUSED_MASK 0xffff0000
+#define GDS_ENHANCE2__UNUSED__SHIFT 0x10
+#define GDS_PROTECTION_FAULT__WRITE_DIS_MASK 0x1
+#define GDS_PROTECTION_FAULT__WRITE_DIS__SHIFT 0x0
+#define GDS_PROTECTION_FAULT__FAULT_DETECTED_MASK 0x2
+#define GDS_PROTECTION_FAULT__FAULT_DETECTED__SHIFT 0x1
+#define GDS_PROTECTION_FAULT__GRBM_MASK 0x4
+#define GDS_PROTECTION_FAULT__GRBM__SHIFT 0x2
+#define GDS_PROTECTION_FAULT__SH_ID_MASK 0x38
+#define GDS_PROTECTION_FAULT__SH_ID__SHIFT 0x3
+#define GDS_PROTECTION_FAULT__CU_ID_MASK 0x3c0
+#define GDS_PROTECTION_FAULT__CU_ID__SHIFT 0x6
+#define GDS_PROTECTION_FAULT__SIMD_ID_MASK 0xc00
+#define GDS_PROTECTION_FAULT__SIMD_ID__SHIFT 0xa
+#define GDS_PROTECTION_FAULT__WAVE_ID_MASK 0xf000
+#define GDS_PROTECTION_FAULT__WAVE_ID__SHIFT 0xc
+#define GDS_PROTECTION_FAULT__ADDRESS_MASK 0xffff0000
+#define GDS_PROTECTION_FAULT__ADDRESS__SHIFT 0x10
+#define GDS_VM_PROTECTION_FAULT__WRITE_DIS_MASK 0x1
+#define GDS_VM_PROTECTION_FAULT__WRITE_DIS__SHIFT 0x0
+#define GDS_VM_PROTECTION_FAULT__FAULT_DETECTED_MASK 0x2
+#define GDS_VM_PROTECTION_FAULT__FAULT_DETECTED__SHIFT 0x1
+#define GDS_VM_PROTECTION_FAULT__GWS_MASK 0x4
+#define GDS_VM_PROTECTION_FAULT__GWS__SHIFT 0x2
+#define GDS_VM_PROTECTION_FAULT__OA_MASK 0x8
+#define GDS_VM_PROTECTION_FAULT__OA__SHIFT 0x3
+#define GDS_VM_PROTECTION_FAULT__GRBM_MASK 0x10
+#define GDS_VM_PROTECTION_FAULT__GRBM__SHIFT 0x4
+#define GDS_VM_PROTECTION_FAULT__VMID_MASK 0xf00
+#define GDS_VM_PROTECTION_FAULT__VMID__SHIFT 0x8
+#define GDS_VM_PROTECTION_FAULT__ADDRESS_MASK 0xffff0000
+#define GDS_VM_PROTECTION_FAULT__ADDRESS__SHIFT 0x10
+#define GDS_EDC_CNT__DED_MASK 0xff
+#define GDS_EDC_CNT__DED__SHIFT 0x0
+#define GDS_EDC_CNT__SED_MASK 0xff00
+#define GDS_EDC_CNT__SED__SHIFT 0x8
+#define GDS_EDC_CNT__SEC_MASK 0xff0000
+#define GDS_EDC_CNT__SEC__SHIFT 0x10
+#define GDS_EDC_GRBM_CNT__DED_MASK 0xff
+#define GDS_EDC_GRBM_CNT__DED__SHIFT 0x0
+#define GDS_EDC_GRBM_CNT__SEC_MASK 0xff0000
+#define GDS_EDC_GRBM_CNT__SEC__SHIFT 0x10
+#define GDS_EDC_OA_DED__ME0_GFXHP3D_PIX_DED_MASK 0x1
+#define GDS_EDC_OA_DED__ME0_GFXHP3D_PIX_DED__SHIFT 0x0
+#define GDS_EDC_OA_DED__ME0_GFXHP3D_VTX_DED_MASK 0x2
+#define GDS_EDC_OA_DED__ME0_GFXHP3D_VTX_DED__SHIFT 0x1
+#define GDS_EDC_OA_DED__ME0_CS_DED_MASK 0x4
+#define GDS_EDC_OA_DED__ME0_CS_DED__SHIFT 0x2
+#define GDS_EDC_OA_DED__UNUSED0_MASK 0x8
+#define GDS_EDC_OA_DED__UNUSED0__SHIFT 0x3
+#define GDS_EDC_OA_DED__ME1_PIPE0_DED_MASK 0x10
+#define GDS_EDC_OA_DED__ME1_PIPE0_DED__SHIFT 0x4
+#define GDS_EDC_OA_DED__ME1_PIPE1_DED_MASK 0x20
+#define GDS_EDC_OA_DED__ME1_PIPE1_DED__SHIFT 0x5
+#define GDS_EDC_OA_DED__ME1_PIPE2_DED_MASK 0x40
+#define GDS_EDC_OA_DED__ME1_PIPE2_DED__SHIFT 0x6
+#define GDS_EDC_OA_DED__ME1_PIPE3_DED_MASK 0x80
+#define GDS_EDC_OA_DED__ME1_PIPE3_DED__SHIFT 0x7
+#define GDS_EDC_OA_DED__ME2_PIPE0_DED_MASK 0x100
+#define GDS_EDC_OA_DED__ME2_PIPE0_DED__SHIFT 0x8
+#define GDS_EDC_OA_DED__ME2_PIPE1_DED_MASK 0x200
+#define GDS_EDC_OA_DED__ME2_PIPE1_DED__SHIFT 0x9
+#define GDS_EDC_OA_DED__ME2_PIPE2_DED_MASK 0x400
+#define GDS_EDC_OA_DED__ME2_PIPE2_DED__SHIFT 0xa
+#define GDS_EDC_OA_DED__ME2_PIPE3_DED_MASK 0x800
+#define GDS_EDC_OA_DED__ME2_PIPE3_DED__SHIFT 0xb
+#define GDS_EDC_OA_DED__UNUSED1_MASK 0xfffff000
+#define GDS_EDC_OA_DED__UNUSED1__SHIFT 0xc
+#define GDS_DEBUG_CNTL__GDS_DEBUG_INDX_MASK 0x1f
+#define GDS_DEBUG_CNTL__GDS_DEBUG_INDX__SHIFT 0x0
+#define GDS_DEBUG_CNTL__UNUSED_MASK 0xffffffe0
+#define GDS_DEBUG_CNTL__UNUSED__SHIFT 0x5
+#define GDS_DEBUG_DATA__DATA_MASK 0xffffffff
+#define GDS_DEBUG_DATA__DATA__SHIFT 0x0
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_A_0_MASK 0x1
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_A_0__SHIFT 0x0
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_A_1_MASK 0x2
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_A_1__SHIFT 0x1
+#define GDS_DSM_CNTL__GDS_ENABLE_SINGLE_WRITE_A_MASK 0x4
+#define GDS_DSM_CNTL__GDS_ENABLE_SINGLE_WRITE_A__SHIFT 0x2
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_B_0_MASK 0x8
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_B_0__SHIFT 0x3
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_B_1_MASK 0x10
+#define GDS_DSM_CNTL__SEL_DSM_GDS_IRRITATOR_DATA_B_1__SHIFT 0x4
+#define GDS_DSM_CNTL__GDS_ENABLE_SINGLE_WRITE_B_MASK 0x20
+#define GDS_DSM_CNTL__GDS_ENABLE_SINGLE_WRITE_B__SHIFT 0x5
+#define GDS_DSM_CNTL__UNUSED_MASK 0xffffffc0
+#define GDS_DSM_CNTL__UNUSED__SHIFT 0x6
+#define CGTT_GDS_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_GDS_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_GDS_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_GDS_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x2000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x19
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x4000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x1a
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x1e
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x1f
+#define GDS_RD_ADDR__READ_ADDR_MASK 0xffffffff
+#define GDS_RD_ADDR__READ_ADDR__SHIFT 0x0
+#define GDS_RD_DATA__READ_DATA_MASK 0xffffffff
+#define GDS_RD_DATA__READ_DATA__SHIFT 0x0
+#define GDS_RD_BURST_ADDR__BURST_ADDR_MASK 0xffffffff
+#define GDS_RD_BURST_ADDR__BURST_ADDR__SHIFT 0x0
+#define GDS_RD_BURST_COUNT__BURST_COUNT_MASK 0xffffffff
+#define GDS_RD_BURST_COUNT__BURST_COUNT__SHIFT 0x0
+#define GDS_RD_BURST_DATA__BURST_DATA_MASK 0xffffffff
+#define GDS_RD_BURST_DATA__BURST_DATA__SHIFT 0x0
+#define GDS_WR_ADDR__WRITE_ADDR_MASK 0xffffffff
+#define GDS_WR_ADDR__WRITE_ADDR__SHIFT 0x0
+#define GDS_WR_DATA__WRITE_DATA_MASK 0xffffffff
+#define GDS_WR_DATA__WRITE_DATA__SHIFT 0x0
+#define GDS_WR_BURST_ADDR__WRITE_ADDR_MASK 0xffffffff
+#define GDS_WR_BURST_ADDR__WRITE_ADDR__SHIFT 0x0
+#define GDS_WR_BURST_DATA__WRITE_DATA_MASK 0xffffffff
+#define GDS_WR_BURST_DATA__WRITE_DATA__SHIFT 0x0
+#define GDS_WRITE_COMPLETE__WRITE_COMPLETE_MASK 0xffffffff
+#define GDS_WRITE_COMPLETE__WRITE_COMPLETE__SHIFT 0x0
+#define GDS_ATOM_CNTL__AINC_MASK 0x3f
+#define GDS_ATOM_CNTL__AINC__SHIFT 0x0
+#define GDS_ATOM_CNTL__UNUSED1_MASK 0xc0
+#define GDS_ATOM_CNTL__UNUSED1__SHIFT 0x6
+#define GDS_ATOM_CNTL__DMODE_MASK 0x300
+#define GDS_ATOM_CNTL__DMODE__SHIFT 0x8
+#define GDS_ATOM_CNTL__UNUSED2_MASK 0xfffffc00
+#define GDS_ATOM_CNTL__UNUSED2__SHIFT 0xa
+#define GDS_ATOM_COMPLETE__COMPLETE_MASK 0x1
+#define GDS_ATOM_COMPLETE__COMPLETE__SHIFT 0x0
+#define GDS_ATOM_COMPLETE__UNUSED_MASK 0xfffffffe
+#define GDS_ATOM_COMPLETE__UNUSED__SHIFT 0x1
+#define GDS_ATOM_BASE__BASE_MASK 0xffff
+#define GDS_ATOM_BASE__BASE__SHIFT 0x0
+#define GDS_ATOM_BASE__UNUSED_MASK 0xffff0000
+#define GDS_ATOM_BASE__UNUSED__SHIFT 0x10
+#define GDS_ATOM_SIZE__SIZE_MASK 0xffff
+#define GDS_ATOM_SIZE__SIZE__SHIFT 0x0
+#define GDS_ATOM_SIZE__UNUSED_MASK 0xffff0000
+#define GDS_ATOM_SIZE__UNUSED__SHIFT 0x10
+#define GDS_ATOM_OFFSET0__OFFSET0_MASK 0xff
+#define GDS_ATOM_OFFSET0__OFFSET0__SHIFT 0x0
+#define GDS_ATOM_OFFSET0__UNUSED_MASK 0xffffff00
+#define GDS_ATOM_OFFSET0__UNUSED__SHIFT 0x8
+#define GDS_ATOM_OFFSET1__OFFSET1_MASK 0xff
+#define GDS_ATOM_OFFSET1__OFFSET1__SHIFT 0x0
+#define GDS_ATOM_OFFSET1__UNUSED_MASK 0xffffff00
+#define GDS_ATOM_OFFSET1__UNUSED__SHIFT 0x8
+#define GDS_ATOM_DST__DST_MASK 0xffffffff
+#define GDS_ATOM_DST__DST__SHIFT 0x0
+#define GDS_ATOM_OP__OP_MASK 0xff
+#define GDS_ATOM_OP__OP__SHIFT 0x0
+#define GDS_ATOM_OP__UNUSED_MASK 0xffffff00
+#define GDS_ATOM_OP__UNUSED__SHIFT 0x8
+#define GDS_ATOM_SRC0__DATA_MASK 0xffffffff
+#define GDS_ATOM_SRC0__DATA__SHIFT 0x0
+#define GDS_ATOM_SRC0_U__DATA_MASK 0xffffffff
+#define GDS_ATOM_SRC0_U__DATA__SHIFT 0x0
+#define GDS_ATOM_SRC1__DATA_MASK 0xffffffff
+#define GDS_ATOM_SRC1__DATA__SHIFT 0x0
+#define GDS_ATOM_SRC1_U__DATA_MASK 0xffffffff
+#define GDS_ATOM_SRC1_U__DATA__SHIFT 0x0
+#define GDS_ATOM_READ0__DATA_MASK 0xffffffff
+#define GDS_ATOM_READ0__DATA__SHIFT 0x0
+#define GDS_ATOM_READ0_U__DATA_MASK 0xffffffff
+#define GDS_ATOM_READ0_U__DATA__SHIFT 0x0
+#define GDS_ATOM_READ1__DATA_MASK 0xffffffff
+#define GDS_ATOM_READ1__DATA__SHIFT 0x0
+#define GDS_ATOM_READ1_U__DATA_MASK 0xffffffff
+#define GDS_ATOM_READ1_U__DATA__SHIFT 0x0
+#define GDS_GWS_RESOURCE_CNTL__INDEX_MASK 0x3f
+#define GDS_GWS_RESOURCE_CNTL__INDEX__SHIFT 0x0
+#define GDS_GWS_RESOURCE_CNTL__UNUSED_MASK 0xffffffc0
+#define GDS_GWS_RESOURCE_CNTL__UNUSED__SHIFT 0x6
+#define GDS_GWS_RESOURCE__FLAG_MASK 0x1
+#define GDS_GWS_RESOURCE__FLAG__SHIFT 0x0
+#define GDS_GWS_RESOURCE__COUNTER_MASK 0x1ffe
+#define GDS_GWS_RESOURCE__COUNTER__SHIFT 0x1
+#define GDS_GWS_RESOURCE__TYPE_MASK 0x2000
+#define GDS_GWS_RESOURCE__TYPE__SHIFT 0xd
+#define GDS_GWS_RESOURCE__DED_MASK 0x4000
+#define GDS_GWS_RESOURCE__DED__SHIFT 0xe
+#define GDS_GWS_RESOURCE__RELEASE_ALL_MASK 0x8000
+#define GDS_GWS_RESOURCE__RELEASE_ALL__SHIFT 0xf
+#define GDS_GWS_RESOURCE__HEAD_QUEUE_MASK 0xfff0000
+#define GDS_GWS_RESOURCE__HEAD_QUEUE__SHIFT 0x10
+#define GDS_GWS_RESOURCE__HEAD_VALID_MASK 0x10000000
+#define GDS_GWS_RESOURCE__HEAD_VALID__SHIFT 0x1c
+#define GDS_GWS_RESOURCE__HEAD_FLAG_MASK 0x20000000
+#define GDS_GWS_RESOURCE__HEAD_FLAG__SHIFT 0x1d
+#define GDS_GWS_RESOURCE__UNUSED1_MASK 0xc0000000
+#define GDS_GWS_RESOURCE__UNUSED1__SHIFT 0x1e
+#define GDS_GWS_RESOURCE_CNT__RESOURCE_CNT_MASK 0xffff
+#define GDS_GWS_RESOURCE_CNT__RESOURCE_CNT__SHIFT 0x0
+#define GDS_GWS_RESOURCE_CNT__UNUSED_MASK 0xffff0000
+#define GDS_GWS_RESOURCE_CNT__UNUSED__SHIFT 0x10
+#define GDS_OA_CNTL__INDEX_MASK 0xf
+#define GDS_OA_CNTL__INDEX__SHIFT 0x0
+#define GDS_OA_CNTL__UNUSED_MASK 0xfffffff0
+#define GDS_OA_CNTL__UNUSED__SHIFT 0x4
+#define GDS_OA_COUNTER__SPACE_AVAILABLE_MASK 0xffffffff
+#define GDS_OA_COUNTER__SPACE_AVAILABLE__SHIFT 0x0
+#define GDS_OA_ADDRESS__DS_ADDRESS_MASK 0xffff
+#define GDS_OA_ADDRESS__DS_ADDRESS__SHIFT 0x0
+#define GDS_OA_ADDRESS__CRAWLER_MASK 0xf0000
+#define GDS_OA_ADDRESS__CRAWLER__SHIFT 0x10
+#define GDS_OA_ADDRESS__CRAWLER_TYPE_MASK 0x300000
+#define GDS_OA_ADDRESS__CRAWLER_TYPE__SHIFT 0x14
+#define GDS_OA_ADDRESS__UNUSED_MASK 0x3fc00000
+#define GDS_OA_ADDRESS__UNUSED__SHIFT 0x16
+#define GDS_OA_ADDRESS__NO_ALLOC_MASK 0x40000000
+#define GDS_OA_ADDRESS__NO_ALLOC__SHIFT 0x1e
+#define GDS_OA_ADDRESS__ENABLE_MASK 0x80000000
+#define GDS_OA_ADDRESS__ENABLE__SHIFT 0x1f
+#define GDS_OA_INCDEC__VALUE_MASK 0x7fffffff
+#define GDS_OA_INCDEC__VALUE__SHIFT 0x0
+#define GDS_OA_INCDEC__INCDEC_MASK 0x80000000
+#define GDS_OA_INCDEC__INCDEC__SHIFT 0x1f
+#define GDS_OA_RING_SIZE__RING_SIZE_MASK 0xffffffff
+#define GDS_OA_RING_SIZE__RING_SIZE__SHIFT 0x0
+#define GDS_DEBUG_REG0__spare1_MASK 0x3f
+#define GDS_DEBUG_REG0__spare1__SHIFT 0x0
+#define GDS_DEBUG_REG0__write_buff_valid_MASK 0x40
+#define GDS_DEBUG_REG0__write_buff_valid__SHIFT 0x6
+#define GDS_DEBUG_REG0__wr_pixel_nxt_ptr_MASK 0xf80
+#define GDS_DEBUG_REG0__wr_pixel_nxt_ptr__SHIFT 0x7
+#define GDS_DEBUG_REG0__last_pixel_ptr_MASK 0x1000
+#define GDS_DEBUG_REG0__last_pixel_ptr__SHIFT 0xc
+#define GDS_DEBUG_REG0__cstate_MASK 0x1e000
+#define GDS_DEBUG_REG0__cstate__SHIFT 0xd
+#define GDS_DEBUG_REG0__buff_write_MASK 0x20000
+#define GDS_DEBUG_REG0__buff_write__SHIFT 0x11
+#define GDS_DEBUG_REG0__flush_request_MASK 0x40000
+#define GDS_DEBUG_REG0__flush_request__SHIFT 0x12
+#define GDS_DEBUG_REG0__wr_buffer_wr_complete_MASK 0x80000
+#define GDS_DEBUG_REG0__wr_buffer_wr_complete__SHIFT 0x13
+#define GDS_DEBUG_REG0__wbuf_fifo_empty_MASK 0x100000
+#define GDS_DEBUG_REG0__wbuf_fifo_empty__SHIFT 0x14
+#define GDS_DEBUG_REG0__wbuf_fifo_full_MASK 0x200000
+#define GDS_DEBUG_REG0__wbuf_fifo_full__SHIFT 0x15
+#define GDS_DEBUG_REG0__spare_MASK 0xffc00000
+#define GDS_DEBUG_REG0__spare__SHIFT 0x16
+#define GDS_DEBUG_REG1__tag_hit_MASK 0x1
+#define GDS_DEBUG_REG1__tag_hit__SHIFT 0x0
+#define GDS_DEBUG_REG1__tag_miss_MASK 0x2
+#define GDS_DEBUG_REG1__tag_miss__SHIFT 0x1
+#define GDS_DEBUG_REG1__pixel_addr_MASK 0x1fffc
+#define GDS_DEBUG_REG1__pixel_addr__SHIFT 0x2
+#define GDS_DEBUG_REG1__pixel_vld_MASK 0x20000
+#define GDS_DEBUG_REG1__pixel_vld__SHIFT 0x11
+#define GDS_DEBUG_REG1__data_ready_MASK 0x40000
+#define GDS_DEBUG_REG1__data_ready__SHIFT 0x12
+#define GDS_DEBUG_REG1__awaiting_data_MASK 0x80000
+#define GDS_DEBUG_REG1__awaiting_data__SHIFT 0x13
+#define GDS_DEBUG_REG1__addr_fifo_full_MASK 0x100000
+#define GDS_DEBUG_REG1__addr_fifo_full__SHIFT 0x14
+#define GDS_DEBUG_REG1__addr_fifo_empty_MASK 0x200000
+#define GDS_DEBUG_REG1__addr_fifo_empty__SHIFT 0x15
+#define GDS_DEBUG_REG1__buffer_loaded_MASK 0x400000
+#define GDS_DEBUG_REG1__buffer_loaded__SHIFT 0x16
+#define GDS_DEBUG_REG1__buffer_invalid_MASK 0x800000
+#define GDS_DEBUG_REG1__buffer_invalid__SHIFT 0x17
+#define GDS_DEBUG_REG1__spare_MASK 0xff000000
+#define GDS_DEBUG_REG1__spare__SHIFT 0x18
+#define GDS_DEBUG_REG2__ds_full_MASK 0x1
+#define GDS_DEBUG_REG2__ds_full__SHIFT 0x0
+#define GDS_DEBUG_REG2__ds_credit_avail_MASK 0x2
+#define GDS_DEBUG_REG2__ds_credit_avail__SHIFT 0x1
+#define GDS_DEBUG_REG2__ord_idx_free_MASK 0x4
+#define GDS_DEBUG_REG2__ord_idx_free__SHIFT 0x2
+#define GDS_DEBUG_REG2__cmd_write_MASK 0x8
+#define GDS_DEBUG_REG2__cmd_write__SHIFT 0x3
+#define GDS_DEBUG_REG2__app_sel_MASK 0xf0
+#define GDS_DEBUG_REG2__app_sel__SHIFT 0x4
+#define GDS_DEBUG_REG2__req_MASK 0x7fff00
+#define GDS_DEBUG_REG2__req__SHIFT 0x8
+#define GDS_DEBUG_REG2__spare_MASK 0xff800000
+#define GDS_DEBUG_REG2__spare__SHIFT 0x17
+#define GDS_DEBUG_REG3__pipe_num_busy_MASK 0x7ff
+#define GDS_DEBUG_REG3__pipe_num_busy__SHIFT 0x0
+#define GDS_DEBUG_REG3__pipe0_busy_num_MASK 0x7800
+#define GDS_DEBUG_REG3__pipe0_busy_num__SHIFT 0xb
+#define GDS_DEBUG_REG3__spare_MASK 0xffff8000
+#define GDS_DEBUG_REG3__spare__SHIFT 0xf
+#define GDS_DEBUG_REG4__gws_busy_MASK 0x1
+#define GDS_DEBUG_REG4__gws_busy__SHIFT 0x0
+#define GDS_DEBUG_REG4__gws_req_MASK 0x2
+#define GDS_DEBUG_REG4__gws_req__SHIFT 0x1
+#define GDS_DEBUG_REG4__gws_out_stall_MASK 0x4
+#define GDS_DEBUG_REG4__gws_out_stall__SHIFT 0x2
+#define GDS_DEBUG_REG4__cur_reso_MASK 0x1f8
+#define GDS_DEBUG_REG4__cur_reso__SHIFT 0x3
+#define GDS_DEBUG_REG4__cur_reso_head_valid_MASK 0x200
+#define GDS_DEBUG_REG4__cur_reso_head_valid__SHIFT 0x9
+#define GDS_DEBUG_REG4__cur_reso_head_dirty_MASK 0x400
+#define GDS_DEBUG_REG4__cur_reso_head_dirty__SHIFT 0xa
+#define GDS_DEBUG_REG4__cur_reso_head_flag_MASK 0x800
+#define GDS_DEBUG_REG4__cur_reso_head_flag__SHIFT 0xb
+#define GDS_DEBUG_REG4__cur_reso_fed_MASK 0x1000
+#define GDS_DEBUG_REG4__cur_reso_fed__SHIFT 0xc
+#define GDS_DEBUG_REG4__cur_reso_barrier_MASK 0x2000
+#define GDS_DEBUG_REG4__cur_reso_barrier__SHIFT 0xd
+#define GDS_DEBUG_REG4__cur_reso_flag_MASK 0x4000
+#define GDS_DEBUG_REG4__cur_reso_flag__SHIFT 0xe
+#define GDS_DEBUG_REG4__cur_reso_cnt_gt0_MASK 0x8000
+#define GDS_DEBUG_REG4__cur_reso_cnt_gt0__SHIFT 0xf
+#define GDS_DEBUG_REG4__credit_cnt_gt0_MASK 0x10000
+#define GDS_DEBUG_REG4__credit_cnt_gt0__SHIFT 0x10
+#define GDS_DEBUG_REG4__cmd_write_MASK 0x20000
+#define GDS_DEBUG_REG4__cmd_write__SHIFT 0x11
+#define GDS_DEBUG_REG4__grbm_gws_reso_wr_MASK 0x40000
+#define GDS_DEBUG_REG4__grbm_gws_reso_wr__SHIFT 0x12
+#define GDS_DEBUG_REG4__grbm_gws_reso_rd_MASK 0x80000
+#define GDS_DEBUG_REG4__grbm_gws_reso_rd__SHIFT 0x13
+#define GDS_DEBUG_REG4__ram_read_busy_MASK 0x100000
+#define GDS_DEBUG_REG4__ram_read_busy__SHIFT 0x14
+#define GDS_DEBUG_REG4__gws_bulkfree_MASK 0x200000
+#define GDS_DEBUG_REG4__gws_bulkfree__SHIFT 0x15
+#define GDS_DEBUG_REG4__ram_gws_re_MASK 0x400000
+#define GDS_DEBUG_REG4__ram_gws_re__SHIFT 0x16
+#define GDS_DEBUG_REG4__ram_gws_we_MASK 0x800000
+#define GDS_DEBUG_REG4__ram_gws_we__SHIFT 0x17
+#define GDS_DEBUG_REG4__spare_MASK 0xff000000
+#define GDS_DEBUG_REG4__spare__SHIFT 0x18
+#define GDS_DEBUG_REG5__write_dis_MASK 0x1
+#define GDS_DEBUG_REG5__write_dis__SHIFT 0x0
+#define GDS_DEBUG_REG5__dec_error_MASK 0x2
+#define GDS_DEBUG_REG5__dec_error__SHIFT 0x1
+#define GDS_DEBUG_REG5__alloc_opco_error_MASK 0x4
+#define GDS_DEBUG_REG5__alloc_opco_error__SHIFT 0x2
+#define GDS_DEBUG_REG5__dealloc_opco_error_MASK 0x8
+#define GDS_DEBUG_REG5__dealloc_opco_error__SHIFT 0x3
+#define GDS_DEBUG_REG5__wrap_opco_error_MASK 0x10
+#define GDS_DEBUG_REG5__wrap_opco_error__SHIFT 0x4
+#define GDS_DEBUG_REG5__spare_MASK 0xe0
+#define GDS_DEBUG_REG5__spare__SHIFT 0x5
+#define GDS_DEBUG_REG5__error_ds_address_MASK 0x3fff00
+#define GDS_DEBUG_REG5__error_ds_address__SHIFT 0x8
+#define GDS_DEBUG_REG5__spare1_MASK 0xffc00000
+#define GDS_DEBUG_REG5__spare1__SHIFT 0x16
+#define GDS_DEBUG_REG6__oa_busy_MASK 0x1
+#define GDS_DEBUG_REG6__oa_busy__SHIFT 0x0
+#define GDS_DEBUG_REG6__counters_enabled_MASK 0x1e
+#define GDS_DEBUG_REG6__counters_enabled__SHIFT 0x1
+#define GDS_DEBUG_REG6__counters_busy_MASK 0x1fffe0
+#define GDS_DEBUG_REG6__counters_busy__SHIFT 0x5
+#define GDS_DEBUG_REG6__spare_MASK 0xffe00000
+#define GDS_DEBUG_REG6__spare__SHIFT 0x15
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define GDS_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define GDS_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define GDS_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define GDS_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define GDS_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0xf00000
+#define GDS_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x14
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT_MASK 0x3ff
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT__SHIFT 0x0
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1_MASK 0xffc00
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1__SHIFT 0xa
+#define GDS_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0xf00000
+#define GDS_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x14
+#define GDS_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GDS_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GDS_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GDS_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GDS_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GDS_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GDS_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define GDS_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define GDS_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GDS_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GDS_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GDS_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GDS_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GDS_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GDS_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define GDS_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2_MASK 0x3ff
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x0
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3_MASK 0xffc00
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0xa
+#define GDS_VMID0_BASE__BASE_MASK 0xffff
+#define GDS_VMID0_BASE__BASE__SHIFT 0x0
+#define GDS_VMID1_BASE__BASE_MASK 0xffff
+#define GDS_VMID1_BASE__BASE__SHIFT 0x0
+#define GDS_VMID2_BASE__BASE_MASK 0xffff
+#define GDS_VMID2_BASE__BASE__SHIFT 0x0
+#define GDS_VMID3_BASE__BASE_MASK 0xffff
+#define GDS_VMID3_BASE__BASE__SHIFT 0x0
+#define GDS_VMID4_BASE__BASE_MASK 0xffff
+#define GDS_VMID4_BASE__BASE__SHIFT 0x0
+#define GDS_VMID5_BASE__BASE_MASK 0xffff
+#define GDS_VMID5_BASE__BASE__SHIFT 0x0
+#define GDS_VMID6_BASE__BASE_MASK 0xffff
+#define GDS_VMID6_BASE__BASE__SHIFT 0x0
+#define GDS_VMID7_BASE__BASE_MASK 0xffff
+#define GDS_VMID7_BASE__BASE__SHIFT 0x0
+#define GDS_VMID8_BASE__BASE_MASK 0xffff
+#define GDS_VMID8_BASE__BASE__SHIFT 0x0
+#define GDS_VMID9_BASE__BASE_MASK 0xffff
+#define GDS_VMID9_BASE__BASE__SHIFT 0x0
+#define GDS_VMID10_BASE__BASE_MASK 0xffff
+#define GDS_VMID10_BASE__BASE__SHIFT 0x0
+#define GDS_VMID11_BASE__BASE_MASK 0xffff
+#define GDS_VMID11_BASE__BASE__SHIFT 0x0
+#define GDS_VMID12_BASE__BASE_MASK 0xffff
+#define GDS_VMID12_BASE__BASE__SHIFT 0x0
+#define GDS_VMID13_BASE__BASE_MASK 0xffff
+#define GDS_VMID13_BASE__BASE__SHIFT 0x0
+#define GDS_VMID14_BASE__BASE_MASK 0xffff
+#define GDS_VMID14_BASE__BASE__SHIFT 0x0
+#define GDS_VMID15_BASE__BASE_MASK 0xffff
+#define GDS_VMID15_BASE__BASE__SHIFT 0x0
+#define GDS_VMID0_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID0_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID1_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID1_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID2_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID2_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID3_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID3_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID4_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID4_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID5_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID5_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID6_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID6_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID7_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID7_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID8_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID8_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID9_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID9_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID10_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID10_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID11_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID11_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID12_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID12_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID13_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID13_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID14_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID14_SIZE__SIZE__SHIFT 0x0
+#define GDS_VMID15_SIZE__SIZE_MASK 0x1ffff
+#define GDS_VMID15_SIZE__SIZE__SHIFT 0x0
+#define GDS_GWS_VMID0__BASE_MASK 0x3f
+#define GDS_GWS_VMID0__BASE__SHIFT 0x0
+#define GDS_GWS_VMID0__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID0__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID1__BASE_MASK 0x3f
+#define GDS_GWS_VMID1__BASE__SHIFT 0x0
+#define GDS_GWS_VMID1__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID1__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID2__BASE_MASK 0x3f
+#define GDS_GWS_VMID2__BASE__SHIFT 0x0
+#define GDS_GWS_VMID2__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID2__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID3__BASE_MASK 0x3f
+#define GDS_GWS_VMID3__BASE__SHIFT 0x0
+#define GDS_GWS_VMID3__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID3__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID4__BASE_MASK 0x3f
+#define GDS_GWS_VMID4__BASE__SHIFT 0x0
+#define GDS_GWS_VMID4__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID4__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID5__BASE_MASK 0x3f
+#define GDS_GWS_VMID5__BASE__SHIFT 0x0
+#define GDS_GWS_VMID5__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID5__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID6__BASE_MASK 0x3f
+#define GDS_GWS_VMID6__BASE__SHIFT 0x0
+#define GDS_GWS_VMID6__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID6__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID7__BASE_MASK 0x3f
+#define GDS_GWS_VMID7__BASE__SHIFT 0x0
+#define GDS_GWS_VMID7__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID7__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID8__BASE_MASK 0x3f
+#define GDS_GWS_VMID8__BASE__SHIFT 0x0
+#define GDS_GWS_VMID8__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID8__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID9__BASE_MASK 0x3f
+#define GDS_GWS_VMID9__BASE__SHIFT 0x0
+#define GDS_GWS_VMID9__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID9__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID10__BASE_MASK 0x3f
+#define GDS_GWS_VMID10__BASE__SHIFT 0x0
+#define GDS_GWS_VMID10__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID10__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID11__BASE_MASK 0x3f
+#define GDS_GWS_VMID11__BASE__SHIFT 0x0
+#define GDS_GWS_VMID11__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID11__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID12__BASE_MASK 0x3f
+#define GDS_GWS_VMID12__BASE__SHIFT 0x0
+#define GDS_GWS_VMID12__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID12__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID13__BASE_MASK 0x3f
+#define GDS_GWS_VMID13__BASE__SHIFT 0x0
+#define GDS_GWS_VMID13__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID13__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID14__BASE_MASK 0x3f
+#define GDS_GWS_VMID14__BASE__SHIFT 0x0
+#define GDS_GWS_VMID14__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID14__SIZE__SHIFT 0x10
+#define GDS_GWS_VMID15__BASE_MASK 0x3f
+#define GDS_GWS_VMID15__BASE__SHIFT 0x0
+#define GDS_GWS_VMID15__SIZE_MASK 0x7f0000
+#define GDS_GWS_VMID15__SIZE__SHIFT 0x10
+#define GDS_OA_VMID0__MASK_MASK 0xffff
+#define GDS_OA_VMID0__MASK__SHIFT 0x0
+#define GDS_OA_VMID0__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID0__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID1__MASK_MASK 0xffff
+#define GDS_OA_VMID1__MASK__SHIFT 0x0
+#define GDS_OA_VMID1__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID1__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID2__MASK_MASK 0xffff
+#define GDS_OA_VMID2__MASK__SHIFT 0x0
+#define GDS_OA_VMID2__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID2__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID3__MASK_MASK 0xffff
+#define GDS_OA_VMID3__MASK__SHIFT 0x0
+#define GDS_OA_VMID3__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID3__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID4__MASK_MASK 0xffff
+#define GDS_OA_VMID4__MASK__SHIFT 0x0
+#define GDS_OA_VMID4__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID4__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID5__MASK_MASK 0xffff
+#define GDS_OA_VMID5__MASK__SHIFT 0x0
+#define GDS_OA_VMID5__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID5__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID6__MASK_MASK 0xffff
+#define GDS_OA_VMID6__MASK__SHIFT 0x0
+#define GDS_OA_VMID6__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID6__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID7__MASK_MASK 0xffff
+#define GDS_OA_VMID7__MASK__SHIFT 0x0
+#define GDS_OA_VMID7__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID7__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID8__MASK_MASK 0xffff
+#define GDS_OA_VMID8__MASK__SHIFT 0x0
+#define GDS_OA_VMID8__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID8__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID9__MASK_MASK 0xffff
+#define GDS_OA_VMID9__MASK__SHIFT 0x0
+#define GDS_OA_VMID9__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID9__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID10__MASK_MASK 0xffff
+#define GDS_OA_VMID10__MASK__SHIFT 0x0
+#define GDS_OA_VMID10__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID10__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID11__MASK_MASK 0xffff
+#define GDS_OA_VMID11__MASK__SHIFT 0x0
+#define GDS_OA_VMID11__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID11__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID12__MASK_MASK 0xffff
+#define GDS_OA_VMID12__MASK__SHIFT 0x0
+#define GDS_OA_VMID12__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID12__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID13__MASK_MASK 0xffff
+#define GDS_OA_VMID13__MASK__SHIFT 0x0
+#define GDS_OA_VMID13__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID13__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID14__MASK_MASK 0xffff
+#define GDS_OA_VMID14__MASK__SHIFT 0x0
+#define GDS_OA_VMID14__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID14__UNUSED__SHIFT 0x10
+#define GDS_OA_VMID15__MASK_MASK 0xffff
+#define GDS_OA_VMID15__MASK__SHIFT 0x0
+#define GDS_OA_VMID15__UNUSED_MASK 0xffff0000
+#define GDS_OA_VMID15__UNUSED__SHIFT 0x10
+#define GDS_GWS_RESET0__RESOURCE0_RESET_MASK 0x1
+#define GDS_GWS_RESET0__RESOURCE0_RESET__SHIFT 0x0
+#define GDS_GWS_RESET0__RESOURCE1_RESET_MASK 0x2
+#define GDS_GWS_RESET0__RESOURCE1_RESET__SHIFT 0x1
+#define GDS_GWS_RESET0__RESOURCE2_RESET_MASK 0x4
+#define GDS_GWS_RESET0__RESOURCE2_RESET__SHIFT 0x2
+#define GDS_GWS_RESET0__RESOURCE3_RESET_MASK 0x8
+#define GDS_GWS_RESET0__RESOURCE3_RESET__SHIFT 0x3
+#define GDS_GWS_RESET0__RESOURCE4_RESET_MASK 0x10
+#define GDS_GWS_RESET0__RESOURCE4_RESET__SHIFT 0x4
+#define GDS_GWS_RESET0__RESOURCE5_RESET_MASK 0x20
+#define GDS_GWS_RESET0__RESOURCE5_RESET__SHIFT 0x5
+#define GDS_GWS_RESET0__RESOURCE6_RESET_MASK 0x40
+#define GDS_GWS_RESET0__RESOURCE6_RESET__SHIFT 0x6
+#define GDS_GWS_RESET0__RESOURCE7_RESET_MASK 0x80
+#define GDS_GWS_RESET0__RESOURCE7_RESET__SHIFT 0x7
+#define GDS_GWS_RESET0__RESOURCE8_RESET_MASK 0x100
+#define GDS_GWS_RESET0__RESOURCE8_RESET__SHIFT 0x8
+#define GDS_GWS_RESET0__RESOURCE9_RESET_MASK 0x200
+#define GDS_GWS_RESET0__RESOURCE9_RESET__SHIFT 0x9
+#define GDS_GWS_RESET0__RESOURCE10_RESET_MASK 0x400
+#define GDS_GWS_RESET0__RESOURCE10_RESET__SHIFT 0xa
+#define GDS_GWS_RESET0__RESOURCE11_RESET_MASK 0x800
+#define GDS_GWS_RESET0__RESOURCE11_RESET__SHIFT 0xb
+#define GDS_GWS_RESET0__RESOURCE12_RESET_MASK 0x1000
+#define GDS_GWS_RESET0__RESOURCE12_RESET__SHIFT 0xc
+#define GDS_GWS_RESET0__RESOURCE13_RESET_MASK 0x2000
+#define GDS_GWS_RESET0__RESOURCE13_RESET__SHIFT 0xd
+#define GDS_GWS_RESET0__RESOURCE14_RESET_MASK 0x4000
+#define GDS_GWS_RESET0__RESOURCE14_RESET__SHIFT 0xe
+#define GDS_GWS_RESET0__RESOURCE15_RESET_MASK 0x8000
+#define GDS_GWS_RESET0__RESOURCE15_RESET__SHIFT 0xf
+#define GDS_GWS_RESET0__RESOURCE16_RESET_MASK 0x10000
+#define GDS_GWS_RESET0__RESOURCE16_RESET__SHIFT 0x10
+#define GDS_GWS_RESET0__RESOURCE17_RESET_MASK 0x20000
+#define GDS_GWS_RESET0__RESOURCE17_RESET__SHIFT 0x11
+#define GDS_GWS_RESET0__RESOURCE18_RESET_MASK 0x40000
+#define GDS_GWS_RESET0__RESOURCE18_RESET__SHIFT 0x12
+#define GDS_GWS_RESET0__RESOURCE19_RESET_MASK 0x80000
+#define GDS_GWS_RESET0__RESOURCE19_RESET__SHIFT 0x13
+#define GDS_GWS_RESET0__RESOURCE20_RESET_MASK 0x100000
+#define GDS_GWS_RESET0__RESOURCE20_RESET__SHIFT 0x14
+#define GDS_GWS_RESET0__RESOURCE21_RESET_MASK 0x200000
+#define GDS_GWS_RESET0__RESOURCE21_RESET__SHIFT 0x15
+#define GDS_GWS_RESET0__RESOURCE22_RESET_MASK 0x400000
+#define GDS_GWS_RESET0__RESOURCE22_RESET__SHIFT 0x16
+#define GDS_GWS_RESET0__RESOURCE23_RESET_MASK 0x800000
+#define GDS_GWS_RESET0__RESOURCE23_RESET__SHIFT 0x17
+#define GDS_GWS_RESET0__RESOURCE24_RESET_MASK 0x1000000
+#define GDS_GWS_RESET0__RESOURCE24_RESET__SHIFT 0x18
+#define GDS_GWS_RESET0__RESOURCE25_RESET_MASK 0x2000000
+#define GDS_GWS_RESET0__RESOURCE25_RESET__SHIFT 0x19
+#define GDS_GWS_RESET0__RESOURCE26_RESET_MASK 0x4000000
+#define GDS_GWS_RESET0__RESOURCE26_RESET__SHIFT 0x1a
+#define GDS_GWS_RESET0__RESOURCE27_RESET_MASK 0x8000000
+#define GDS_GWS_RESET0__RESOURCE27_RESET__SHIFT 0x1b
+#define GDS_GWS_RESET0__RESOURCE28_RESET_MASK 0x10000000
+#define GDS_GWS_RESET0__RESOURCE28_RESET__SHIFT 0x1c
+#define GDS_GWS_RESET0__RESOURCE29_RESET_MASK 0x20000000
+#define GDS_GWS_RESET0__RESOURCE29_RESET__SHIFT 0x1d
+#define GDS_GWS_RESET0__RESOURCE30_RESET_MASK 0x40000000
+#define GDS_GWS_RESET0__RESOURCE30_RESET__SHIFT 0x1e
+#define GDS_GWS_RESET0__RESOURCE31_RESET_MASK 0x80000000
+#define GDS_GWS_RESET0__RESOURCE31_RESET__SHIFT 0x1f
+#define GDS_GWS_RESET1__RESOURCE32_RESET_MASK 0x1
+#define GDS_GWS_RESET1__RESOURCE32_RESET__SHIFT 0x0
+#define GDS_GWS_RESET1__RESOURCE33_RESET_MASK 0x2
+#define GDS_GWS_RESET1__RESOURCE33_RESET__SHIFT 0x1
+#define GDS_GWS_RESET1__RESOURCE34_RESET_MASK 0x4
+#define GDS_GWS_RESET1__RESOURCE34_RESET__SHIFT 0x2
+#define GDS_GWS_RESET1__RESOURCE35_RESET_MASK 0x8
+#define GDS_GWS_RESET1__RESOURCE35_RESET__SHIFT 0x3
+#define GDS_GWS_RESET1__RESOURCE36_RESET_MASK 0x10
+#define GDS_GWS_RESET1__RESOURCE36_RESET__SHIFT 0x4
+#define GDS_GWS_RESET1__RESOURCE37_RESET_MASK 0x20
+#define GDS_GWS_RESET1__RESOURCE37_RESET__SHIFT 0x5
+#define GDS_GWS_RESET1__RESOURCE38_RESET_MASK 0x40
+#define GDS_GWS_RESET1__RESOURCE38_RESET__SHIFT 0x6
+#define GDS_GWS_RESET1__RESOURCE39_RESET_MASK 0x80
+#define GDS_GWS_RESET1__RESOURCE39_RESET__SHIFT 0x7
+#define GDS_GWS_RESET1__RESOURCE40_RESET_MASK 0x100
+#define GDS_GWS_RESET1__RESOURCE40_RESET__SHIFT 0x8
+#define GDS_GWS_RESET1__RESOURCE41_RESET_MASK 0x200
+#define GDS_GWS_RESET1__RESOURCE41_RESET__SHIFT 0x9
+#define GDS_GWS_RESET1__RESOURCE42_RESET_MASK 0x400
+#define GDS_GWS_RESET1__RESOURCE42_RESET__SHIFT 0xa
+#define GDS_GWS_RESET1__RESOURCE43_RESET_MASK 0x800
+#define GDS_GWS_RESET1__RESOURCE43_RESET__SHIFT 0xb
+#define GDS_GWS_RESET1__RESOURCE44_RESET_MASK 0x1000
+#define GDS_GWS_RESET1__RESOURCE44_RESET__SHIFT 0xc
+#define GDS_GWS_RESET1__RESOURCE45_RESET_MASK 0x2000
+#define GDS_GWS_RESET1__RESOURCE45_RESET__SHIFT 0xd
+#define GDS_GWS_RESET1__RESOURCE46_RESET_MASK 0x4000
+#define GDS_GWS_RESET1__RESOURCE46_RESET__SHIFT 0xe
+#define GDS_GWS_RESET1__RESOURCE47_RESET_MASK 0x8000
+#define GDS_GWS_RESET1__RESOURCE47_RESET__SHIFT 0xf
+#define GDS_GWS_RESET1__RESOURCE48_RESET_MASK 0x10000
+#define GDS_GWS_RESET1__RESOURCE48_RESET__SHIFT 0x10
+#define GDS_GWS_RESET1__RESOURCE49_RESET_MASK 0x20000
+#define GDS_GWS_RESET1__RESOURCE49_RESET__SHIFT 0x11
+#define GDS_GWS_RESET1__RESOURCE50_RESET_MASK 0x40000
+#define GDS_GWS_RESET1__RESOURCE50_RESET__SHIFT 0x12
+#define GDS_GWS_RESET1__RESOURCE51_RESET_MASK 0x80000
+#define GDS_GWS_RESET1__RESOURCE51_RESET__SHIFT 0x13
+#define GDS_GWS_RESET1__RESOURCE52_RESET_MASK 0x100000
+#define GDS_GWS_RESET1__RESOURCE52_RESET__SHIFT 0x14
+#define GDS_GWS_RESET1__RESOURCE53_RESET_MASK 0x200000
+#define GDS_GWS_RESET1__RESOURCE53_RESET__SHIFT 0x15
+#define GDS_GWS_RESET1__RESOURCE54_RESET_MASK 0x400000
+#define GDS_GWS_RESET1__RESOURCE54_RESET__SHIFT 0x16
+#define GDS_GWS_RESET1__RESOURCE55_RESET_MASK 0x800000
+#define GDS_GWS_RESET1__RESOURCE55_RESET__SHIFT 0x17
+#define GDS_GWS_RESET1__RESOURCE56_RESET_MASK 0x1000000
+#define GDS_GWS_RESET1__RESOURCE56_RESET__SHIFT 0x18
+#define GDS_GWS_RESET1__RESOURCE57_RESET_MASK 0x2000000
+#define GDS_GWS_RESET1__RESOURCE57_RESET__SHIFT 0x19
+#define GDS_GWS_RESET1__RESOURCE58_RESET_MASK 0x4000000
+#define GDS_GWS_RESET1__RESOURCE58_RESET__SHIFT 0x1a
+#define GDS_GWS_RESET1__RESOURCE59_RESET_MASK 0x8000000
+#define GDS_GWS_RESET1__RESOURCE59_RESET__SHIFT 0x1b
+#define GDS_GWS_RESET1__RESOURCE60_RESET_MASK 0x10000000
+#define GDS_GWS_RESET1__RESOURCE60_RESET__SHIFT 0x1c
+#define GDS_GWS_RESET1__RESOURCE61_RESET_MASK 0x20000000
+#define GDS_GWS_RESET1__RESOURCE61_RESET__SHIFT 0x1d
+#define GDS_GWS_RESET1__RESOURCE62_RESET_MASK 0x40000000
+#define GDS_GWS_RESET1__RESOURCE62_RESET__SHIFT 0x1e
+#define GDS_GWS_RESET1__RESOURCE63_RESET_MASK 0x80000000
+#define GDS_GWS_RESET1__RESOURCE63_RESET__SHIFT 0x1f
+#define GDS_GWS_RESOURCE_RESET__RESET_MASK 0x1
+#define GDS_GWS_RESOURCE_RESET__RESET__SHIFT 0x0
+#define GDS_GWS_RESOURCE_RESET__RESOURCE_ID_MASK 0xff00
+#define GDS_GWS_RESOURCE_RESET__RESOURCE_ID__SHIFT 0x8
+#define GDS_COMPUTE_MAX_WAVE_ID__MAX_WAVE_ID_MASK 0xfff
+#define GDS_COMPUTE_MAX_WAVE_ID__MAX_WAVE_ID__SHIFT 0x0
+#define GDS_OA_RESET_MASK__ME0_GFXHP3D_PIX_RESET_MASK 0x1
+#define GDS_OA_RESET_MASK__ME0_GFXHP3D_PIX_RESET__SHIFT 0x0
+#define GDS_OA_RESET_MASK__ME0_GFXHP3D_VTX_RESET_MASK 0x2
+#define GDS_OA_RESET_MASK__ME0_GFXHP3D_VTX_RESET__SHIFT 0x1
+#define GDS_OA_RESET_MASK__ME0_CS_RESET_MASK 0x4
+#define GDS_OA_RESET_MASK__ME0_CS_RESET__SHIFT 0x2
+#define GDS_OA_RESET_MASK__UNUSED0_MASK 0x8
+#define GDS_OA_RESET_MASK__UNUSED0__SHIFT 0x3
+#define GDS_OA_RESET_MASK__ME1_PIPE0_RESET_MASK 0x10
+#define GDS_OA_RESET_MASK__ME1_PIPE0_RESET__SHIFT 0x4
+#define GDS_OA_RESET_MASK__ME1_PIPE1_RESET_MASK 0x20
+#define GDS_OA_RESET_MASK__ME1_PIPE1_RESET__SHIFT 0x5
+#define GDS_OA_RESET_MASK__ME1_PIPE2_RESET_MASK 0x40
+#define GDS_OA_RESET_MASK__ME1_PIPE2_RESET__SHIFT 0x6
+#define GDS_OA_RESET_MASK__ME1_PIPE3_RESET_MASK 0x80
+#define GDS_OA_RESET_MASK__ME1_PIPE3_RESET__SHIFT 0x7
+#define GDS_OA_RESET_MASK__ME2_PIPE0_RESET_MASK 0x100
+#define GDS_OA_RESET_MASK__ME2_PIPE0_RESET__SHIFT 0x8
+#define GDS_OA_RESET_MASK__ME2_PIPE1_RESET_MASK 0x200
+#define GDS_OA_RESET_MASK__ME2_PIPE1_RESET__SHIFT 0x9
+#define GDS_OA_RESET_MASK__ME2_PIPE2_RESET_MASK 0x400
+#define GDS_OA_RESET_MASK__ME2_PIPE2_RESET__SHIFT 0xa
+#define GDS_OA_RESET_MASK__ME2_PIPE3_RESET_MASK 0x800
+#define GDS_OA_RESET_MASK__ME2_PIPE3_RESET__SHIFT 0xb
+#define GDS_OA_RESET_MASK__UNUSED1_MASK 0xfffff000
+#define GDS_OA_RESET_MASK__UNUSED1__SHIFT 0xc
+#define GDS_OA_RESET__RESET_MASK 0x1
+#define GDS_OA_RESET__RESET__SHIFT 0x0
+#define GDS_OA_RESET__PIPE_ID_MASK 0xff00
+#define GDS_OA_RESET__PIPE_ID__SHIFT 0x8
+#define GDS_ENHANCE__MISC_MASK 0xffff
+#define GDS_ENHANCE__MISC__SHIFT 0x0
+#define GDS_ENHANCE__AUTO_INC_INDEX_MASK 0x10000
+#define GDS_ENHANCE__AUTO_INC_INDEX__SHIFT 0x10
+#define GDS_ENHANCE__CGPG_RESTORE_MASK 0x20000
+#define GDS_ENHANCE__CGPG_RESTORE__SHIFT 0x11
+#define GDS_ENHANCE__UNUSED_MASK 0xfffc0000
+#define GDS_ENHANCE__UNUSED__SHIFT 0x12
+#define GDS_OA_CGPG_RESTORE__VMID_MASK 0xff
+#define GDS_OA_CGPG_RESTORE__VMID__SHIFT 0x0
+#define GDS_OA_CGPG_RESTORE__MEID_MASK 0xf00
+#define GDS_OA_CGPG_RESTORE__MEID__SHIFT 0x8
+#define GDS_OA_CGPG_RESTORE__PIPEID_MASK 0xf000
+#define GDS_OA_CGPG_RESTORE__PIPEID__SHIFT 0xc
+#define GDS_OA_CGPG_RESTORE__QUEUEID_MASK 0xf0000
+#define GDS_OA_CGPG_RESTORE__QUEUEID__SHIFT 0x10
+#define GDS_OA_CGPG_RESTORE__UNUSED_MASK 0xfff00000
+#define GDS_OA_CGPG_RESTORE__UNUSED__SHIFT 0x14
+#define GDS_CS_CTXSW_STATUS__R_MASK 0x1
+#define GDS_CS_CTXSW_STATUS__R__SHIFT 0x0
+#define GDS_CS_CTXSW_STATUS__W_MASK 0x2
+#define GDS_CS_CTXSW_STATUS__W__SHIFT 0x1
+#define GDS_CS_CTXSW_STATUS__UNUSED_MASK 0xfffffffc
+#define GDS_CS_CTXSW_STATUS__UNUSED__SHIFT 0x2
+#define GDS_CS_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_CS_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_CS_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_CS_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_CS_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_CS_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_CS_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_CS_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_CS_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_CS_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_CS_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_CS_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_CS_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_CS_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_CS_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_CS_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_GFX_CTXSW_STATUS__R_MASK 0x1
+#define GDS_GFX_CTXSW_STATUS__R__SHIFT 0x0
+#define GDS_GFX_CTXSW_STATUS__W_MASK 0x2
+#define GDS_GFX_CTXSW_STATUS__W__SHIFT 0x1
+#define GDS_GFX_CTXSW_STATUS__UNUSED_MASK 0xfffffffc
+#define GDS_GFX_CTXSW_STATUS__UNUSED__SHIFT 0x2
+#define GDS_VS_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_VS_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_VS_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_VS_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_VS_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_VS_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_VS_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_VS_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_VS_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_VS_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_VS_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_VS_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_VS_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_VS_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_VS_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_VS_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS0_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS0_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS0_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS0_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS1_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS1_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS1_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS1_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS2_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS2_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS2_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS2_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS3_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS3_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS3_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS3_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS4_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS4_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS4_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS4_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS5_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS5_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS5_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS5_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS6_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS6_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS6_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS6_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS7_CTXSW_CNT0__UPDN_MASK 0xffff
+#define GDS_PS7_CTXSW_CNT0__UPDN__SHIFT 0x0
+#define GDS_PS7_CTXSW_CNT0__PTR_MASK 0xffff0000
+#define GDS_PS7_CTXSW_CNT0__PTR__SHIFT 0x10
+#define GDS_PS0_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS0_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS0_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS0_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS1_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS1_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS1_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS1_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS2_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS2_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS2_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS2_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS3_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS3_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS3_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS3_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS4_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS4_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS4_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS4_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS5_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS5_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS5_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS5_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS6_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS6_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS6_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS6_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS7_CTXSW_CNT1__UPDN_MASK 0xffff
+#define GDS_PS7_CTXSW_CNT1__UPDN__SHIFT 0x0
+#define GDS_PS7_CTXSW_CNT1__PTR_MASK 0xffff0000
+#define GDS_PS7_CTXSW_CNT1__PTR__SHIFT 0x10
+#define GDS_PS0_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS0_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS0_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS0_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS1_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS1_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS1_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS1_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS2_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS2_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS2_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS2_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS3_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS3_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS3_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS3_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS4_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS4_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS4_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS4_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS5_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS5_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS5_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS5_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS6_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS6_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS6_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS6_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS7_CTXSW_CNT2__UPDN_MASK 0xffff
+#define GDS_PS7_CTXSW_CNT2__UPDN__SHIFT 0x0
+#define GDS_PS7_CTXSW_CNT2__PTR_MASK 0xffff0000
+#define GDS_PS7_CTXSW_CNT2__PTR__SHIFT 0x10
+#define GDS_PS0_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS0_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS0_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS0_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS1_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS1_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS1_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS1_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS2_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS2_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS2_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS2_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS3_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS3_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS3_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS3_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS4_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS4_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS4_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS4_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS5_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS5_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS5_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS5_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS6_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS6_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS6_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS6_CTXSW_CNT3__PTR__SHIFT 0x10
+#define GDS_PS7_CTXSW_CNT3__UPDN_MASK 0xffff
+#define GDS_PS7_CTXSW_CNT3__UPDN__SHIFT 0x0
+#define GDS_PS7_CTXSW_CNT3__PTR_MASK 0xffff0000
+#define GDS_PS7_CTXSW_CNT3__PTR__SHIFT 0x10
+#define CS_COPY_STATE__SRC_STATE_ID_MASK 0x7
+#define CS_COPY_STATE__SRC_STATE_ID__SHIFT 0x0
+#define GFX_COPY_STATE__SRC_STATE_ID_MASK 0x7
+#define GFX_COPY_STATE__SRC_STATE_ID__SHIFT 0x0
+#define VGT_DRAW_INITIATOR__SOURCE_SELECT_MASK 0x3
+#define VGT_DRAW_INITIATOR__SOURCE_SELECT__SHIFT 0x0
+#define VGT_DRAW_INITIATOR__MAJOR_MODE_MASK 0xc
+#define VGT_DRAW_INITIATOR__MAJOR_MODE__SHIFT 0x2
+#define VGT_DRAW_INITIATOR__SPRITE_EN_R6XX_MASK 0x10
+#define VGT_DRAW_INITIATOR__SPRITE_EN_R6XX__SHIFT 0x4
+#define VGT_DRAW_INITIATOR__NOT_EOP_MASK 0x20
+#define VGT_DRAW_INITIATOR__NOT_EOP__SHIFT 0x5
+#define VGT_DRAW_INITIATOR__USE_OPAQUE_MASK 0x40
+#define VGT_DRAW_INITIATOR__USE_OPAQUE__SHIFT 0x6
+#define VGT_EVENT_INITIATOR__EVENT_TYPE_MASK 0x3f
+#define VGT_EVENT_INITIATOR__EVENT_TYPE__SHIFT 0x0
+#define VGT_EVENT_INITIATOR__ADDRESS_HI_MASK 0x7fc0000
+#define VGT_EVENT_INITIATOR__ADDRESS_HI__SHIFT 0x12
+#define VGT_EVENT_INITIATOR__EXTENDED_EVENT_MASK 0x8000000
+#define VGT_EVENT_INITIATOR__EXTENDED_EVENT__SHIFT 0x1b
+#define VGT_EVENT_ADDRESS_REG__ADDRESS_LOW_MASK 0xfffffff
+#define VGT_EVENT_ADDRESS_REG__ADDRESS_LOW__SHIFT 0x0
+#define VGT_DMA_BASE_HI__BASE_ADDR_MASK 0xff
+#define VGT_DMA_BASE_HI__BASE_ADDR__SHIFT 0x0
+#define VGT_DMA_BASE__BASE_ADDR_MASK 0xffffffff
+#define VGT_DMA_BASE__BASE_ADDR__SHIFT 0x0
+#define VGT_DMA_INDEX_TYPE__INDEX_TYPE_MASK 0x3
+#define VGT_DMA_INDEX_TYPE__INDEX_TYPE__SHIFT 0x0
+#define VGT_DMA_INDEX_TYPE__SWAP_MODE_MASK 0xc
+#define VGT_DMA_INDEX_TYPE__SWAP_MODE__SHIFT 0x2
+#define VGT_DMA_INDEX_TYPE__BUF_TYPE_MASK 0x30
+#define VGT_DMA_INDEX_TYPE__BUF_TYPE__SHIFT 0x4
+#define VGT_DMA_INDEX_TYPE__RDREQ_POLICY_MASK 0x40
+#define VGT_DMA_INDEX_TYPE__RDREQ_POLICY__SHIFT 0x6
+#define VGT_DMA_INDEX_TYPE__NOT_EOP_MASK 0x200
+#define VGT_DMA_INDEX_TYPE__NOT_EOP__SHIFT 0x9
+#define VGT_DMA_INDEX_TYPE__REQ_PATH_MASK 0x400
+#define VGT_DMA_INDEX_TYPE__REQ_PATH__SHIFT 0xa
+#define VGT_DMA_INDEX_TYPE__MTYPE_MASK 0x1800
+#define VGT_DMA_INDEX_TYPE__MTYPE__SHIFT 0xb
+#define VGT_DMA_NUM_INSTANCES__NUM_INSTANCES_MASK 0xffffffff
+#define VGT_DMA_NUM_INSTANCES__NUM_INSTANCES__SHIFT 0x0
+#define IA_ENHANCE__MISC_MASK 0xffffffff
+#define IA_ENHANCE__MISC__SHIFT 0x0
+#define VGT_DMA_SIZE__NUM_INDICES_MASK 0xffffffff
+#define VGT_DMA_SIZE__NUM_INDICES__SHIFT 0x0
+#define VGT_DMA_MAX_SIZE__MAX_SIZE_MASK 0xffffffff
+#define VGT_DMA_MAX_SIZE__MAX_SIZE__SHIFT 0x0
+#define VGT_DMA_PRIMITIVE_TYPE__PRIM_TYPE_MASK 0x3f
+#define VGT_DMA_PRIMITIVE_TYPE__PRIM_TYPE__SHIFT 0x0
+#define VGT_DMA_CONTROL__PRIMGROUP_SIZE_MASK 0xffff
+#define VGT_DMA_CONTROL__PRIMGROUP_SIZE__SHIFT 0x0
+#define VGT_DMA_CONTROL__IA_SWITCH_ON_EOP_MASK 0x20000
+#define VGT_DMA_CONTROL__IA_SWITCH_ON_EOP__SHIFT 0x11
+#define VGT_DMA_CONTROL__WD_SWITCH_ON_EOP_MASK 0x100000
+#define VGT_DMA_CONTROL__WD_SWITCH_ON_EOP__SHIFT 0x14
+#define VGT_IMMED_DATA__DATA_MASK 0xffffffff
+#define VGT_IMMED_DATA__DATA__SHIFT 0x0
+#define VGT_INDEX_TYPE__INDEX_TYPE_MASK 0x3
+#define VGT_INDEX_TYPE__INDEX_TYPE__SHIFT 0x0
+#define VGT_NUM_INDICES__NUM_INDICES_MASK 0xffffffff
+#define VGT_NUM_INDICES__NUM_INDICES__SHIFT 0x0
+#define VGT_NUM_INSTANCES__NUM_INSTANCES_MASK 0xffffffff
+#define VGT_NUM_INSTANCES__NUM_INSTANCES__SHIFT 0x0
+#define VGT_PRIMITIVE_TYPE__PRIM_TYPE_MASK 0x3f
+#define VGT_PRIMITIVE_TYPE__PRIM_TYPE__SHIFT 0x0
+#define VGT_PRIMITIVEID_EN__PRIMITIVEID_EN_MASK 0x1
+#define VGT_PRIMITIVEID_EN__PRIMITIVEID_EN__SHIFT 0x0
+#define VGT_PRIMITIVEID_EN__DISABLE_RESET_ON_EOI_MASK 0x2
+#define VGT_PRIMITIVEID_EN__DISABLE_RESET_ON_EOI__SHIFT 0x1
+#define VGT_PRIMITIVEID_RESET__VALUE_MASK 0xffffffff
+#define VGT_PRIMITIVEID_RESET__VALUE__SHIFT 0x0
+#define VGT_VTX_CNT_EN__VTX_CNT_EN_MASK 0x1
+#define VGT_VTX_CNT_EN__VTX_CNT_EN__SHIFT 0x0
+#define VGT_REUSE_OFF__REUSE_OFF_MASK 0x1
+#define VGT_REUSE_OFF__REUSE_OFF__SHIFT 0x0
+#define VGT_INSTANCE_STEP_RATE_0__STEP_RATE_MASK 0xffffffff
+#define VGT_INSTANCE_STEP_RATE_0__STEP_RATE__SHIFT 0x0
+#define VGT_INSTANCE_STEP_RATE_1__STEP_RATE_MASK 0xffffffff
+#define VGT_INSTANCE_STEP_RATE_1__STEP_RATE__SHIFT 0x0
+#define VGT_MAX_VTX_INDX__MAX_INDX_MASK 0xffffffff
+#define VGT_MAX_VTX_INDX__MAX_INDX__SHIFT 0x0
+#define VGT_MIN_VTX_INDX__MIN_INDX_MASK 0xffffffff
+#define VGT_MIN_VTX_INDX__MIN_INDX__SHIFT 0x0
+#define VGT_INDX_OFFSET__INDX_OFFSET_MASK 0xffffffff
+#define VGT_INDX_OFFSET__INDX_OFFSET__SHIFT 0x0
+#define VGT_VERTEX_REUSE_BLOCK_CNTL__VTX_REUSE_DEPTH_MASK 0xff
+#define VGT_VERTEX_REUSE_BLOCK_CNTL__VTX_REUSE_DEPTH__SHIFT 0x0
+#define VGT_OUT_DEALLOC_CNTL__DEALLOC_DIST_MASK 0x7f
+#define VGT_OUT_DEALLOC_CNTL__DEALLOC_DIST__SHIFT 0x0
+#define VGT_MULTI_PRIM_IB_RESET_INDX__RESET_INDX_MASK 0xffffffff
+#define VGT_MULTI_PRIM_IB_RESET_INDX__RESET_INDX__SHIFT 0x0
+#define VGT_MULTI_PRIM_IB_RESET_EN__RESET_EN_MASK 0x1
+#define VGT_MULTI_PRIM_IB_RESET_EN__RESET_EN__SHIFT 0x0
+#define VGT_ENHANCE__MISC_MASK 0xffffffff
+#define VGT_ENHANCE__MISC__SHIFT 0x0
+#define VGT_OUTPUT_PATH_CNTL__PATH_SELECT_MASK 0x7
+#define VGT_OUTPUT_PATH_CNTL__PATH_SELECT__SHIFT 0x0
+#define VGT_HOS_CNTL__TESS_MODE_MASK 0x3
+#define VGT_HOS_CNTL__TESS_MODE__SHIFT 0x0
+#define VGT_HOS_MAX_TESS_LEVEL__MAX_TESS_MASK 0xffffffff
+#define VGT_HOS_MAX_TESS_LEVEL__MAX_TESS__SHIFT 0x0
+#define VGT_HOS_MIN_TESS_LEVEL__MIN_TESS_MASK 0xffffffff
+#define VGT_HOS_MIN_TESS_LEVEL__MIN_TESS__SHIFT 0x0
+#define VGT_HOS_REUSE_DEPTH__REUSE_DEPTH_MASK 0xff
+#define VGT_HOS_REUSE_DEPTH__REUSE_DEPTH__SHIFT 0x0
+#define VGT_GROUP_PRIM_TYPE__PRIM_TYPE_MASK 0x1f
+#define VGT_GROUP_PRIM_TYPE__PRIM_TYPE__SHIFT 0x0
+#define VGT_GROUP_PRIM_TYPE__RETAIN_ORDER_MASK 0x4000
+#define VGT_GROUP_PRIM_TYPE__RETAIN_ORDER__SHIFT 0xe
+#define VGT_GROUP_PRIM_TYPE__RETAIN_QUADS_MASK 0x8000
+#define VGT_GROUP_PRIM_TYPE__RETAIN_QUADS__SHIFT 0xf
+#define VGT_GROUP_PRIM_TYPE__PRIM_ORDER_MASK 0x70000
+#define VGT_GROUP_PRIM_TYPE__PRIM_ORDER__SHIFT 0x10
+#define VGT_GROUP_FIRST_DECR__FIRST_DECR_MASK 0xf
+#define VGT_GROUP_FIRST_DECR__FIRST_DECR__SHIFT 0x0
+#define VGT_GROUP_DECR__DECR_MASK 0xf
+#define VGT_GROUP_DECR__DECR__SHIFT 0x0
+#define VGT_GROUP_VECT_0_CNTL__COMP_X_EN_MASK 0x1
+#define VGT_GROUP_VECT_0_CNTL__COMP_X_EN__SHIFT 0x0
+#define VGT_GROUP_VECT_0_CNTL__COMP_Y_EN_MASK 0x2
+#define VGT_GROUP_VECT_0_CNTL__COMP_Y_EN__SHIFT 0x1
+#define VGT_GROUP_VECT_0_CNTL__COMP_Z_EN_MASK 0x4
+#define VGT_GROUP_VECT_0_CNTL__COMP_Z_EN__SHIFT 0x2
+#define VGT_GROUP_VECT_0_CNTL__COMP_W_EN_MASK 0x8
+#define VGT_GROUP_VECT_0_CNTL__COMP_W_EN__SHIFT 0x3
+#define VGT_GROUP_VECT_0_CNTL__STRIDE_MASK 0xff00
+#define VGT_GROUP_VECT_0_CNTL__STRIDE__SHIFT 0x8
+#define VGT_GROUP_VECT_0_CNTL__SHIFT_MASK 0xff0000
+#define VGT_GROUP_VECT_0_CNTL__SHIFT__SHIFT 0x10
+#define VGT_GROUP_VECT_1_CNTL__COMP_X_EN_MASK 0x1
+#define VGT_GROUP_VECT_1_CNTL__COMP_X_EN__SHIFT 0x0
+#define VGT_GROUP_VECT_1_CNTL__COMP_Y_EN_MASK 0x2
+#define VGT_GROUP_VECT_1_CNTL__COMP_Y_EN__SHIFT 0x1
+#define VGT_GROUP_VECT_1_CNTL__COMP_Z_EN_MASK 0x4
+#define VGT_GROUP_VECT_1_CNTL__COMP_Z_EN__SHIFT 0x2
+#define VGT_GROUP_VECT_1_CNTL__COMP_W_EN_MASK 0x8
+#define VGT_GROUP_VECT_1_CNTL__COMP_W_EN__SHIFT 0x3
+#define VGT_GROUP_VECT_1_CNTL__STRIDE_MASK 0xff00
+#define VGT_GROUP_VECT_1_CNTL__STRIDE__SHIFT 0x8
+#define VGT_GROUP_VECT_1_CNTL__SHIFT_MASK 0xff0000
+#define VGT_GROUP_VECT_1_CNTL__SHIFT__SHIFT 0x10
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_CONV_MASK 0xf
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_CONV__SHIFT 0x0
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_OFFSET_MASK 0xf0
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_OFFSET__SHIFT 0x4
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_CONV_MASK 0xf00
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_CONV__SHIFT 0x8
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_OFFSET_MASK 0xf000
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_OFFSET__SHIFT 0xc
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_CONV_MASK 0xf0000
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_CONV__SHIFT 0x10
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_OFFSET_MASK 0xf00000
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_OFFSET__SHIFT 0x14
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_CONV_MASK 0xf000000
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_CONV__SHIFT 0x18
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_OFFSET_MASK 0xf0000000
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_OFFSET__SHIFT 0x1c
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_CONV_MASK 0xf
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_CONV__SHIFT 0x0
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_OFFSET_MASK 0xf0
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_OFFSET__SHIFT 0x4
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_CONV_MASK 0xf00
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_CONV__SHIFT 0x8
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_OFFSET_MASK 0xf000
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_OFFSET__SHIFT 0xc
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_CONV_MASK 0xf0000
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_CONV__SHIFT 0x10
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_OFFSET_MASK 0xf00000
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_OFFSET__SHIFT 0x14
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_CONV_MASK 0xf000000
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_CONV__SHIFT 0x18
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_OFFSET_MASK 0xf0000000
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_OFFSET__SHIFT 0x1c
+#define VGT_VTX_VECT_EJECT_REG__PRIM_COUNT_MASK 0x3ff
+#define VGT_VTX_VECT_EJECT_REG__PRIM_COUNT__SHIFT 0x0
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA_DATA_FIFO_DEPTH_MASK 0x1ff
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA_DATA_FIFO_DEPTH__SHIFT 0x0
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA2DRAW_FIFO_DEPTH_MASK 0x7fe00
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA2DRAW_FIFO_DEPTH__SHIFT 0x9
+#define VGT_DMA_REQ_FIFO_DEPTH__DMA_REQ_FIFO_DEPTH_MASK 0x3f
+#define VGT_DMA_REQ_FIFO_DEPTH__DMA_REQ_FIFO_DEPTH__SHIFT 0x0
+#define VGT_DRAW_INIT_FIFO_DEPTH__DRAW_INIT_FIFO_DEPTH_MASK 0x3f
+#define VGT_DRAW_INIT_FIFO_DEPTH__DRAW_INIT_FIFO_DEPTH__SHIFT 0x0
+#define VGT_LAST_COPY_STATE__SRC_STATE_ID_MASK 0x7
+#define VGT_LAST_COPY_STATE__SRC_STATE_ID__SHIFT 0x0
+#define VGT_LAST_COPY_STATE__DST_STATE_ID_MASK 0x70000
+#define VGT_LAST_COPY_STATE__DST_STATE_ID__SHIFT 0x10
+#define CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK 0xffff0000
+#define CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT 0x10
+#define GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK 0xffff0000
+#define GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT 0x10
+#define VGT_GS_MODE__MODE_MASK 0x7
+#define VGT_GS_MODE__MODE__SHIFT 0x0
+#define VGT_GS_MODE__RESERVED_0_MASK 0x8
+#define VGT_GS_MODE__RESERVED_0__SHIFT 0x3
+#define VGT_GS_MODE__CUT_MODE_MASK 0x30
+#define VGT_GS_MODE__CUT_MODE__SHIFT 0x4
+#define VGT_GS_MODE__RESERVED_1_MASK 0x7c0
+#define VGT_GS_MODE__RESERVED_1__SHIFT 0x6
+#define VGT_GS_MODE__GS_C_PACK_EN_MASK 0x800
+#define VGT_GS_MODE__GS_C_PACK_EN__SHIFT 0xb
+#define VGT_GS_MODE__RESERVED_2_MASK 0x1000
+#define VGT_GS_MODE__RESERVED_2__SHIFT 0xc
+#define VGT_GS_MODE__ES_PASSTHRU_MASK 0x2000
+#define VGT_GS_MODE__ES_PASSTHRU__SHIFT 0xd
+#define VGT_GS_MODE__RESERVED_3_MASK 0x4000
+#define VGT_GS_MODE__RESERVED_3__SHIFT 0xe
+#define VGT_GS_MODE__RESERVED_4_MASK 0x8000
+#define VGT_GS_MODE__RESERVED_4__SHIFT 0xf
+#define VGT_GS_MODE__RESERVED_5_MASK 0x10000
+#define VGT_GS_MODE__RESERVED_5__SHIFT 0x10
+#define VGT_GS_MODE__PARTIAL_THD_AT_EOI_MASK 0x20000
+#define VGT_GS_MODE__PARTIAL_THD_AT_EOI__SHIFT 0x11
+#define VGT_GS_MODE__SUPPRESS_CUTS_MASK 0x40000
+#define VGT_GS_MODE__SUPPRESS_CUTS__SHIFT 0x12
+#define VGT_GS_MODE__ES_WRITE_OPTIMIZE_MASK 0x80000
+#define VGT_GS_MODE__ES_WRITE_OPTIMIZE__SHIFT 0x13
+#define VGT_GS_MODE__GS_WRITE_OPTIMIZE_MASK 0x100000
+#define VGT_GS_MODE__GS_WRITE_OPTIMIZE__SHIFT 0x14
+#define VGT_GS_MODE__ONCHIP_MASK 0x600000
+#define VGT_GS_MODE__ONCHIP__SHIFT 0x15
+#define VGT_GS_ONCHIP_CNTL__ES_VERTS_PER_SUBGRP_MASK 0x7ff
+#define VGT_GS_ONCHIP_CNTL__ES_VERTS_PER_SUBGRP__SHIFT 0x0
+#define VGT_GS_ONCHIP_CNTL__GS_PRIMS_PER_SUBGRP_MASK 0x3ff800
+#define VGT_GS_ONCHIP_CNTL__GS_PRIMS_PER_SUBGRP__SHIFT 0xb
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_MASK 0x3f
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE__SHIFT 0x0
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_1_MASK 0x3f00
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_1__SHIFT 0x8
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_2_MASK 0x3f0000
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_2__SHIFT 0x10
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_3_MASK 0xfc00000
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_3__SHIFT 0x16
+#define VGT_GS_OUT_PRIM_TYPE__UNIQUE_TYPE_PER_STREAM_MASK 0x80000000
+#define VGT_GS_OUT_PRIM_TYPE__UNIQUE_TYPE_PER_STREAM__SHIFT 0x1f
+#define VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_MASK 0x3
+#define VGT_CACHE_INVALIDATION__CACHE_INVALIDATION__SHIFT 0x0
+#define VGT_CACHE_INVALIDATION__DIS_INSTANCING_OPT_MASK 0x10
+#define VGT_CACHE_INVALIDATION__DIS_INSTANCING_OPT__SHIFT 0x4
+#define VGT_CACHE_INVALIDATION__VS_NO_EXTRA_BUFFER_MASK 0x20
+#define VGT_CACHE_INVALIDATION__VS_NO_EXTRA_BUFFER__SHIFT 0x5
+#define VGT_CACHE_INVALIDATION__AUTO_INVLD_EN_MASK 0xc0
+#define VGT_CACHE_INVALIDATION__AUTO_INVLD_EN__SHIFT 0x6
+#define VGT_CACHE_INVALIDATION__USE_GS_DONE_MASK 0x200
+#define VGT_CACHE_INVALIDATION__USE_GS_DONE__SHIFT 0x9
+#define VGT_CACHE_INVALIDATION__DIS_RANGE_FULL_INVLD_MASK 0x800
+#define VGT_CACHE_INVALIDATION__DIS_RANGE_FULL_INVLD__SHIFT 0xb
+#define VGT_CACHE_INVALIDATION__GS_LATE_ALLOC_EN_MASK 0x1000
+#define VGT_CACHE_INVALIDATION__GS_LATE_ALLOC_EN__SHIFT 0xc
+#define VGT_CACHE_INVALIDATION__STREAMOUT_FULL_FLUSH_MASK 0x2000
+#define VGT_CACHE_INVALIDATION__STREAMOUT_FULL_FLUSH__SHIFT 0xd
+#define VGT_CACHE_INVALIDATION__ES_LIMIT_MASK 0x1f0000
+#define VGT_CACHE_INVALIDATION__ES_LIMIT__SHIFT 0x10
+#define VGT_RESET_DEBUG__GS_DISABLE_MASK 0x1
+#define VGT_RESET_DEBUG__GS_DISABLE__SHIFT 0x0
+#define VGT_RESET_DEBUG__TESS_DISABLE_MASK 0x2
+#define VGT_RESET_DEBUG__TESS_DISABLE__SHIFT 0x1
+#define VGT_RESET_DEBUG__WD_DISABLE_MASK 0x4
+#define VGT_RESET_DEBUG__WD_DISABLE__SHIFT 0x2
+#define VGT_STRMOUT_DELAY__SKIP_DELAY_MASK 0xff
+#define VGT_STRMOUT_DELAY__SKIP_DELAY__SHIFT 0x0
+#define VGT_STRMOUT_DELAY__SE0_WD_DELAY_MASK 0x700
+#define VGT_STRMOUT_DELAY__SE0_WD_DELAY__SHIFT 0x8
+#define VGT_STRMOUT_DELAY__SE1_WD_DELAY_MASK 0x3800
+#define VGT_STRMOUT_DELAY__SE1_WD_DELAY__SHIFT 0xb
+#define VGT_STRMOUT_DELAY__SE2_WD_DELAY_MASK 0x1c000
+#define VGT_STRMOUT_DELAY__SE2_WD_DELAY__SHIFT 0xe
+#define VGT_STRMOUT_DELAY__SE3_WD_DELAY_MASK 0xe0000
+#define VGT_STRMOUT_DELAY__SE3_WD_DELAY__SHIFT 0x11
+#define VGT_FIFO_DEPTHS__VS_DEALLOC_TBL_DEPTH_MASK 0x7f
+#define VGT_FIFO_DEPTHS__VS_DEALLOC_TBL_DEPTH__SHIFT 0x0
+#define VGT_FIFO_DEPTHS__RESERVED_0_MASK 0x80
+#define VGT_FIFO_DEPTHS__RESERVED_0__SHIFT 0x7
+#define VGT_FIFO_DEPTHS__CLIPP_FIFO_DEPTH_MASK 0x3fff00
+#define VGT_FIFO_DEPTHS__CLIPP_FIFO_DEPTH__SHIFT 0x8
+#define VGT_FIFO_DEPTHS__HSINPUT_FIFO_DEPTH_MASK 0xfc00000
+#define VGT_FIFO_DEPTHS__HSINPUT_FIFO_DEPTH__SHIFT 0x16
+#define VGT_GS_PER_ES__GS_PER_ES_MASK 0x7ff
+#define VGT_GS_PER_ES__GS_PER_ES__SHIFT 0x0
+#define VGT_ES_PER_GS__ES_PER_GS_MASK 0x7ff
+#define VGT_ES_PER_GS__ES_PER_GS__SHIFT 0x0
+#define VGT_GS_PER_VS__GS_PER_VS_MASK 0xf
+#define VGT_GS_PER_VS__GS_PER_VS__SHIFT 0x0
+#define VGT_GS_VERTEX_REUSE__VERT_REUSE_MASK 0x1f
+#define VGT_GS_VERTEX_REUSE__VERT_REUSE__SHIFT 0x0
+#define VGT_MC_LAT_CNTL__MC_TIME_STAMP_RES_MASK 0x3
+#define VGT_MC_LAT_CNTL__MC_TIME_STAMP_RES__SHIFT 0x0
+#define IA_CNTL_STATUS__IA_BUSY_MASK 0x1
+#define IA_CNTL_STATUS__IA_BUSY__SHIFT 0x0
+#define IA_CNTL_STATUS__IA_DMA_BUSY_MASK 0x2
+#define IA_CNTL_STATUS__IA_DMA_BUSY__SHIFT 0x1
+#define IA_CNTL_STATUS__IA_DMA_REQ_BUSY_MASK 0x4
+#define IA_CNTL_STATUS__IA_DMA_REQ_BUSY__SHIFT 0x2
+#define IA_CNTL_STATUS__IA_GRP_BUSY_MASK 0x8
+#define IA_CNTL_STATUS__IA_GRP_BUSY__SHIFT 0x3
+#define IA_CNTL_STATUS__IA_ADC_BUSY_MASK 0x10
+#define IA_CNTL_STATUS__IA_ADC_BUSY__SHIFT 0x4
+#define VGT_STRMOUT_CONFIG__STREAMOUT_0_EN_MASK 0x1
+#define VGT_STRMOUT_CONFIG__STREAMOUT_0_EN__SHIFT 0x0
+#define VGT_STRMOUT_CONFIG__STREAMOUT_1_EN_MASK 0x2
+#define VGT_STRMOUT_CONFIG__STREAMOUT_1_EN__SHIFT 0x1
+#define VGT_STRMOUT_CONFIG__STREAMOUT_2_EN_MASK 0x4
+#define VGT_STRMOUT_CONFIG__STREAMOUT_2_EN__SHIFT 0x2
+#define VGT_STRMOUT_CONFIG__STREAMOUT_3_EN_MASK 0x8
+#define VGT_STRMOUT_CONFIG__STREAMOUT_3_EN__SHIFT 0x3
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK 0x70
+#define VGT_STRMOUT_CONFIG__RAST_STREAM__SHIFT 0x4
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK_MASK 0xf00
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK__SHIFT 0x8
+#define VGT_STRMOUT_CONFIG__USE_RAST_STREAM_MASK_MASK 0x80000000
+#define VGT_STRMOUT_CONFIG__USE_RAST_STREAM_MASK__SHIFT 0x1f
+#define VGT_STRMOUT_BUFFER_SIZE_0__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_SIZE_0__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_SIZE_1__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_SIZE_1__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_SIZE_2__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_SIZE_2__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_SIZE_3__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_SIZE_3__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_OFFSET_0__OFFSET_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_OFFSET_0__OFFSET__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_OFFSET_1__OFFSET_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_OFFSET_1__OFFSET__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_OFFSET_2__OFFSET_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_OFFSET_2__OFFSET__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_OFFSET_3__OFFSET_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_OFFSET_3__OFFSET__SHIFT 0x0
+#define VGT_STRMOUT_VTX_STRIDE_0__STRIDE_MASK 0x3ff
+#define VGT_STRMOUT_VTX_STRIDE_0__STRIDE__SHIFT 0x0
+#define VGT_STRMOUT_VTX_STRIDE_1__STRIDE_MASK 0x3ff
+#define VGT_STRMOUT_VTX_STRIDE_1__STRIDE__SHIFT 0x0
+#define VGT_STRMOUT_VTX_STRIDE_2__STRIDE_MASK 0x3ff
+#define VGT_STRMOUT_VTX_STRIDE_2__STRIDE__SHIFT 0x0
+#define VGT_STRMOUT_VTX_STRIDE_3__STRIDE_MASK 0x3ff
+#define VGT_STRMOUT_VTX_STRIDE_3__STRIDE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_0_BUFFER_EN_MASK 0xf
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_0_BUFFER_EN__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_1_BUFFER_EN_MASK 0xf0
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_1_BUFFER_EN__SHIFT 0x4
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_2_BUFFER_EN_MASK 0xf00
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_2_BUFFER_EN__SHIFT 0x8
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_3_BUFFER_EN_MASK 0xf000
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_3_BUFFER_EN__SHIFT 0xc
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_0__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_0__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_1__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_1__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_2__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_2__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_3__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_3__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_DRAW_OPAQUE_OFFSET__OFFSET_MASK 0xffffffff
+#define VGT_STRMOUT_DRAW_OPAQUE_OFFSET__OFFSET__SHIFT 0x0
+#define VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE__SIZE_MASK 0xffffffff
+#define VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE__SIZE__SHIFT 0x0
+#define VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE__VERTEX_STRIDE_MASK 0x1ff
+#define VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE__VERTEX_STRIDE__SHIFT 0x0
+#define VGT_GS_MAX_VERT_OUT__MAX_VERT_OUT_MASK 0x7ff
+#define VGT_GS_MAX_VERT_OUT__MAX_VERT_OUT__SHIFT 0x0
+#define VGT_SHADER_STAGES_EN__LS_EN_MASK 0x3
+#define VGT_SHADER_STAGES_EN__LS_EN__SHIFT 0x0
+#define VGT_SHADER_STAGES_EN__HS_EN_MASK 0x4
+#define VGT_SHADER_STAGES_EN__HS_EN__SHIFT 0x2
+#define VGT_SHADER_STAGES_EN__ES_EN_MASK 0x18
+#define VGT_SHADER_STAGES_EN__ES_EN__SHIFT 0x3
+#define VGT_SHADER_STAGES_EN__GS_EN_MASK 0x20
+#define VGT_SHADER_STAGES_EN__GS_EN__SHIFT 0x5
+#define VGT_SHADER_STAGES_EN__VS_EN_MASK 0xc0
+#define VGT_SHADER_STAGES_EN__VS_EN__SHIFT 0x6
+#define VGT_SHADER_STAGES_EN__DYNAMIC_HS_MASK 0x100
+#define VGT_SHADER_STAGES_EN__DYNAMIC_HS__SHIFT 0x8
+#define VGT_SHADER_STAGES_EN__DISPATCH_DRAW_EN_MASK 0x200
+#define VGT_SHADER_STAGES_EN__DISPATCH_DRAW_EN__SHIFT 0x9
+#define VGT_SHADER_STAGES_EN__DIS_DEALLOC_ACCUM_0_MASK 0x400
+#define VGT_SHADER_STAGES_EN__DIS_DEALLOC_ACCUM_0__SHIFT 0xa
+#define VGT_SHADER_STAGES_EN__DIS_DEALLOC_ACCUM_1_MASK 0x800
+#define VGT_SHADER_STAGES_EN__DIS_DEALLOC_ACCUM_1__SHIFT 0xb
+#define VGT_SHADER_STAGES_EN__VS_WAVE_ID_EN_MASK 0x1000
+#define VGT_SHADER_STAGES_EN__VS_WAVE_ID_EN__SHIFT 0xc
+#define VGT_DISPATCH_DRAW_INDEX__MATCH_INDEX_MASK 0xffffffff
+#define VGT_DISPATCH_DRAW_INDEX__MATCH_INDEX__SHIFT 0x0
+#define VGT_LS_HS_CONFIG__NUM_PATCHES_MASK 0xff
+#define VGT_LS_HS_CONFIG__NUM_PATCHES__SHIFT 0x0
+#define VGT_LS_HS_CONFIG__HS_NUM_INPUT_CP_MASK 0x3f00
+#define VGT_LS_HS_CONFIG__HS_NUM_INPUT_CP__SHIFT 0x8
+#define VGT_LS_HS_CONFIG__HS_NUM_OUTPUT_CP_MASK 0xfc000
+#define VGT_LS_HS_CONFIG__HS_NUM_OUTPUT_CP__SHIFT 0xe
+#define VGT_DMA_LS_HS_CONFIG__HS_NUM_INPUT_CP_MASK 0x3f00
+#define VGT_DMA_LS_HS_CONFIG__HS_NUM_INPUT_CP__SHIFT 0x8
+#define VGT_TF_PARAM__TYPE_MASK 0x3
+#define VGT_TF_PARAM__TYPE__SHIFT 0x0
+#define VGT_TF_PARAM__PARTITIONING_MASK 0x1c
+#define VGT_TF_PARAM__PARTITIONING__SHIFT 0x2
+#define VGT_TF_PARAM__TOPOLOGY_MASK 0xe0
+#define VGT_TF_PARAM__TOPOLOGY__SHIFT 0x5
+#define VGT_TF_PARAM__RESERVED_REDUC_AXIS_MASK 0x100
+#define VGT_TF_PARAM__RESERVED_REDUC_AXIS__SHIFT 0x8
+#define VGT_TF_PARAM__DEPRECATED_MASK 0x200
+#define VGT_TF_PARAM__DEPRECATED__SHIFT 0x9
+#define VGT_TF_PARAM__NUM_DS_WAVES_PER_SIMD_MASK 0x3c00
+#define VGT_TF_PARAM__NUM_DS_WAVES_PER_SIMD__SHIFT 0xa
+#define VGT_TF_PARAM__DISABLE_DONUTS_MASK 0x4000
+#define VGT_TF_PARAM__DISABLE_DONUTS__SHIFT 0xe
+#define VGT_TF_PARAM__RDREQ_POLICY_MASK 0x8000
+#define VGT_TF_PARAM__RDREQ_POLICY__SHIFT 0xf
+#define VGT_TF_PARAM__DISTRIBUTION_MODE_MASK 0x60000
+#define VGT_TF_PARAM__DISTRIBUTION_MODE__SHIFT 0x11
+#define VGT_TF_PARAM__MTYPE_MASK 0x180000
+#define VGT_TF_PARAM__MTYPE__SHIFT 0x13
+#define VGT_TESS_DISTRIBUTION__ACCUM_ISOLINE_MASK 0xff
+#define VGT_TESS_DISTRIBUTION__ACCUM_ISOLINE__SHIFT 0x0
+#define VGT_TESS_DISTRIBUTION__ACCUM_TRI_MASK 0xff00
+#define VGT_TESS_DISTRIBUTION__ACCUM_TRI__SHIFT 0x8
+#define VGT_TESS_DISTRIBUTION__ACCUM_QUAD_MASK 0xff0000
+#define VGT_TESS_DISTRIBUTION__ACCUM_QUAD__SHIFT 0x10
+#define VGT_TESS_DISTRIBUTION__DONUT_SPLIT_MASK 0xff000000
+#define VGT_TESS_DISTRIBUTION__DONUT_SPLIT__SHIFT 0x18
+#define VGT_TF_RING_SIZE__SIZE_MASK 0xffff
+#define VGT_TF_RING_SIZE__SIZE__SHIFT 0x0
+#define VGT_SYS_CONFIG__DUAL_CORE_EN_MASK 0x1
+#define VGT_SYS_CONFIG__DUAL_CORE_EN__SHIFT 0x0
+#define VGT_SYS_CONFIG__MAX_LS_HS_THDGRP_MASK 0x7e
+#define VGT_SYS_CONFIG__MAX_LS_HS_THDGRP__SHIFT 0x1
+#define VGT_SYS_CONFIG__ADC_EVENT_FILTER_DISABLE_MASK 0x80
+#define VGT_SYS_CONFIG__ADC_EVENT_FILTER_DISABLE__SHIFT 0x7
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_BUFFERING_MASK 0x1ff
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_BUFFERING__SHIFT 0x0
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY_MASK 0x600
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY__SHIFT 0x9
+#define VGT_TF_MEMORY_BASE__BASE_MASK 0xffffffff
+#define VGT_TF_MEMORY_BASE__BASE__SHIFT 0x0
+#define VGT_GS_INSTANCE_CNT__ENABLE_MASK 0x1
+#define VGT_GS_INSTANCE_CNT__ENABLE__SHIFT 0x0
+#define VGT_GS_INSTANCE_CNT__CNT_MASK 0x1fc
+#define VGT_GS_INSTANCE_CNT__CNT__SHIFT 0x2
+#define IA_MULTI_VGT_PARAM__PRIMGROUP_SIZE_MASK 0xffff
+#define IA_MULTI_VGT_PARAM__PRIMGROUP_SIZE__SHIFT 0x0
+#define IA_MULTI_VGT_PARAM__PARTIAL_VS_WAVE_ON_MASK 0x10000
+#define IA_MULTI_VGT_PARAM__PARTIAL_VS_WAVE_ON__SHIFT 0x10
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOP_MASK 0x20000
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOP__SHIFT 0x11
+#define IA_MULTI_VGT_PARAM__PARTIAL_ES_WAVE_ON_MASK 0x40000
+#define IA_MULTI_VGT_PARAM__PARTIAL_ES_WAVE_ON__SHIFT 0x12
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOI_MASK 0x80000
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOI__SHIFT 0x13
+#define IA_MULTI_VGT_PARAM__WD_SWITCH_ON_EOP_MASK 0x100000
+#define IA_MULTI_VGT_PARAM__WD_SWITCH_ON_EOP__SHIFT 0x14
+#define IA_MULTI_VGT_PARAM__MAX_PRIMGRP_IN_WAVE_MASK 0xf0000000
+#define IA_MULTI_VGT_PARAM__MAX_PRIMGRP_IN_WAVE__SHIFT 0x1c
+#define VGT_VS_MAX_WAVE_ID__MAX_WAVE_ID_MASK 0xfff
+#define VGT_VS_MAX_WAVE_ID__MAX_WAVE_ID__SHIFT 0x0
+#define VGT_ESGS_RING_SIZE__MEM_SIZE_MASK 0xffffffff
+#define VGT_ESGS_RING_SIZE__MEM_SIZE__SHIFT 0x0
+#define VGT_GSVS_RING_SIZE__MEM_SIZE_MASK 0xffffffff
+#define VGT_GSVS_RING_SIZE__MEM_SIZE__SHIFT 0x0
+#define VGT_GSVS_RING_OFFSET_1__OFFSET_MASK 0x7fff
+#define VGT_GSVS_RING_OFFSET_1__OFFSET__SHIFT 0x0
+#define VGT_GSVS_RING_OFFSET_2__OFFSET_MASK 0x7fff
+#define VGT_GSVS_RING_OFFSET_2__OFFSET__SHIFT 0x0
+#define VGT_GSVS_RING_OFFSET_3__OFFSET_MASK 0x7fff
+#define VGT_GSVS_RING_OFFSET_3__OFFSET__SHIFT 0x0
+#define VGT_ESGS_RING_ITEMSIZE__ITEMSIZE_MASK 0x7fff
+#define VGT_ESGS_RING_ITEMSIZE__ITEMSIZE__SHIFT 0x0
+#define VGT_GSVS_RING_ITEMSIZE__ITEMSIZE_MASK 0x7fff
+#define VGT_GSVS_RING_ITEMSIZE__ITEMSIZE__SHIFT 0x0
+#define VGT_GS_VERT_ITEMSIZE__ITEMSIZE_MASK 0x7fff
+#define VGT_GS_VERT_ITEMSIZE__ITEMSIZE__SHIFT 0x0
+#define VGT_GS_VERT_ITEMSIZE_1__ITEMSIZE_MASK 0x7fff
+#define VGT_GS_VERT_ITEMSIZE_1__ITEMSIZE__SHIFT 0x0
+#define VGT_GS_VERT_ITEMSIZE_2__ITEMSIZE_MASK 0x7fff
+#define VGT_GS_VERT_ITEMSIZE_2__ITEMSIZE__SHIFT 0x0
+#define VGT_GS_VERT_ITEMSIZE_3__ITEMSIZE_MASK 0x7fff
+#define VGT_GS_VERT_ITEMSIZE_3__ITEMSIZE__SHIFT 0x0
+#define WD_CNTL_STATUS__WD_BUSY_MASK 0x1
+#define WD_CNTL_STATUS__WD_BUSY__SHIFT 0x0
+#define WD_CNTL_STATUS__WD_SPL_DMA_BUSY_MASK 0x2
+#define WD_CNTL_STATUS__WD_SPL_DMA_BUSY__SHIFT 0x1
+#define WD_CNTL_STATUS__WD_SPL_DI_BUSY_MASK 0x4
+#define WD_CNTL_STATUS__WD_SPL_DI_BUSY__SHIFT 0x2
+#define WD_CNTL_STATUS__WD_ADC_BUSY_MASK 0x8
+#define WD_CNTL_STATUS__WD_ADC_BUSY__SHIFT 0x3
+#define WD_ENHANCE__MISC_MASK 0xffffffff
+#define WD_ENHANCE__MISC__SHIFT 0x0
+#define GFX_PIPE_CONTROL__HYSTERESIS_CNT_MASK 0x1fff
+#define GFX_PIPE_CONTROL__HYSTERESIS_CNT__SHIFT 0x0
+#define GFX_PIPE_CONTROL__RESERVED_MASK 0xe000
+#define GFX_PIPE_CONTROL__RESERVED__SHIFT 0xd
+#define GFX_PIPE_CONTROL__CONTEXT_SUSPEND_EN_MASK 0x10000
+#define GFX_PIPE_CONTROL__CONTEXT_SUSPEND_EN__SHIFT 0x10
+#define CGTT_VGT_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_VGT_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_VGT_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_VGT_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_VGT_CLK_CTRL__PERF_ENABLE_MASK 0x2000000
+#define CGTT_VGT_CLK_CTRL__PERF_ENABLE__SHIFT 0x19
+#define CGTT_VGT_CLK_CTRL__DBG_ENABLE_MASK 0x4000000
+#define CGTT_VGT_CLK_CTRL__DBG_ENABLE__SHIFT 0x1a
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_VGT_CLK_CTRL__TESS_OVERRIDE_MASK 0x10000000
+#define CGTT_VGT_CLK_CTRL__TESS_OVERRIDE__SHIFT 0x1c
+#define CGTT_VGT_CLK_CTRL__GS_OVERRIDE_MASK 0x20000000
+#define CGTT_VGT_CLK_CTRL__GS_OVERRIDE__SHIFT 0x1d
+#define CGTT_VGT_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000
+#define CGTT_VGT_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x1e
+#define CGTT_VGT_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_VGT_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define CGTT_IA_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_IA_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_IA_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_IA_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_IA_CLK_CTRL__PERF_ENABLE_MASK 0x2000000
+#define CGTT_IA_CLK_CTRL__PERF_ENABLE__SHIFT 0x19
+#define CGTT_IA_CLK_CTRL__DBG_ENABLE_MASK 0x4000000
+#define CGTT_IA_CLK_CTRL__DBG_ENABLE__SHIFT 0x1a
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x1c
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x1d
+#define CGTT_IA_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000
+#define CGTT_IA_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x1e
+#define CGTT_IA_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_IA_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define CGTT_WD_CLK_CTRL__ON_DELAY_MASK 0xf
+#define CGTT_WD_CLK_CTRL__ON_DELAY__SHIFT 0x0
+#define CGTT_WD_CLK_CTRL__OFF_HYSTERESIS_MASK 0xff0
+#define CGTT_WD_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x4
+#define CGTT_WD_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x1000000
+#define CGTT_WD_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x18
+#define CGTT_WD_CLK_CTRL__PERF_ENABLE_MASK 0x2000000
+#define CGTT_WD_CLK_CTRL__PERF_ENABLE__SHIFT 0x19
+#define CGTT_WD_CLK_CTRL__DBG_ENABLE_MASK 0x4000000
+#define CGTT_WD_CLK_CTRL__DBG_ENABLE__SHIFT 0x1a
+#define CGTT_WD_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x8000000
+#define CGTT_WD_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x1b
+#define CGTT_WD_CLK_CTRL__TESS_OVERRIDE_MASK 0x10000000
+#define CGTT_WD_CLK_CTRL__TESS_OVERRIDE__SHIFT 0x1c
+#define CGTT_WD_CLK_CTRL__CORE_OVERRIDE_MASK 0x20000000
+#define CGTT_WD_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x1d
+#define CGTT_WD_CLK_CTRL__RBIU_INPUT_OVERRIDE_MASK 0x40000000
+#define CGTT_WD_CLK_CTRL__RBIU_INPUT_OVERRIDE__SHIFT 0x1e
+#define CGTT_WD_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000
+#define CGTT_WD_CLK_CTRL__REG_OVERRIDE__SHIFT 0x1f
+#define VGT_DEBUG_CNTL__VGT_DEBUG_INDX_MASK 0x3f
+#define VGT_DEBUG_CNTL__VGT_DEBUG_INDX__SHIFT 0x0
+#define VGT_DEBUG_CNTL__VGT_DEBUG_SEL_BUS_B_MASK 0x40
+#define VGT_DEBUG_CNTL__VGT_DEBUG_SEL_BUS_B__SHIFT 0x6
+#define VGT_DEBUG_DATA__DATA_MASK 0xffffffff
+#define VGT_DEBUG_DATA__DATA__SHIFT 0x0
+#define IA_DEBUG_CNTL__IA_DEBUG_INDX_MASK 0x3f
+#define IA_DEBUG_CNTL__IA_DEBUG_INDX__SHIFT 0x0
+#define IA_DEBUG_CNTL__IA_DEBUG_SEL_BUS_B_MASK 0x40
+#define IA_DEBUG_CNTL__IA_DEBUG_SEL_BUS_B__SHIFT 0x6
+#define IA_DEBUG_DATA__DATA_MASK 0xffffffff
+#define IA_DEBUG_DATA__DATA__SHIFT 0x0
+#define VGT_CNTL_STATUS__VGT_BUSY_MASK 0x1
+#define VGT_CNTL_STATUS__VGT_BUSY__SHIFT 0x0
+#define VGT_CNTL_STATUS__VGT_OUT_INDX_BUSY_MASK 0x2
+#define VGT_CNTL_STATUS__VGT_OUT_INDX_BUSY__SHIFT 0x1
+#define VGT_CNTL_STATUS__VGT_OUT_BUSY_MASK 0x4
+#define VGT_CNTL_STATUS__VGT_OUT_BUSY__SHIFT 0x2
+#define VGT_CNTL_STATUS__VGT_PT_BUSY_MASK 0x8
+#define VGT_CNTL_STATUS__VGT_PT_BUSY__SHIFT 0x3
+#define VGT_CNTL_STATUS__VGT_TE_BUSY_MASK 0x10
+#define VGT_CNTL_STATUS__VGT_TE_BUSY__SHIFT 0x4
+#define VGT_CNTL_STATUS__VGT_VR_BUSY_MASK 0x20
+#define VGT_CNTL_STATUS__VGT_VR_BUSY__SHIFT 0x5
+#define VGT_CNTL_STATUS__VGT_PI_BUSY_MASK 0x40
+#define VGT_CNTL_STATUS__VGT_PI_BUSY__SHIFT 0x6
+#define VGT_CNTL_STATUS__VGT_GS_BUSY_MASK 0x80
+#define VGT_CNTL_STATUS__VGT_GS_BUSY__SHIFT 0x7
+#define VGT_CNTL_STATUS__VGT_HS_BUSY_MASK 0x100
+#define VGT_CNTL_STATUS__VGT_HS_BUSY__SHIFT 0x8
+#define VGT_CNTL_STATUS__VGT_TE11_BUSY_MASK 0x200
+#define VGT_CNTL_STATUS__VGT_TE11_BUSY__SHIFT 0x9
+#define WD_DEBUG_CNTL__WD_DEBUG_INDX_MASK 0x3f
+#define WD_DEBUG_CNTL__WD_DEBUG_INDX__SHIFT 0x0
+#define WD_DEBUG_CNTL__WD_DEBUG_SEL_BUS_B_MASK 0x40
+#define WD_DEBUG_CNTL__WD_DEBUG_SEL_BUS_B__SHIFT 0x6
+#define WD_DEBUG_DATA__DATA_MASK 0xffffffff
+#define WD_DEBUG_DATA__DATA__SHIFT 0x0
+#define WD_QOS__DRAW_STALL_MASK 0x1
+#define WD_QOS__DRAW_STALL__SHIFT 0x0
+#define CC_GC_PRIM_CONFIG__INACTIVE_IA_MASK 0x30000
+#define CC_GC_PRIM_CONFIG__INACTIVE_IA__SHIFT 0x10
+#define CC_GC_PRIM_CONFIG__INACTIVE_VGT_PA_MASK 0xf000000
+#define CC_GC_PRIM_CONFIG__INACTIVE_VGT_PA__SHIFT 0x18
+#define GC_USER_PRIM_CONFIG__INACTIVE_IA_MASK 0x30000
+#define GC_USER_PRIM_CONFIG__INACTIVE_IA__SHIFT 0x10
+#define GC_USER_PRIM_CONFIG__INACTIVE_VGT_PA_MASK 0xf000000
+#define GC_USER_PRIM_CONFIG__INACTIVE_VGT_PA__SHIFT 0x18
+#define WD_DEBUG_REG0__wd_busy_extended_MASK 0x1
+#define WD_DEBUG_REG0__wd_busy_extended__SHIFT 0x0
+#define WD_DEBUG_REG0__wd_nodma_busy_extended_MASK 0x2
+#define WD_DEBUG_REG0__wd_nodma_busy_extended__SHIFT 0x1
+#define WD_DEBUG_REG0__wd_busy_MASK 0x4
+#define WD_DEBUG_REG0__wd_busy__SHIFT 0x2
+#define WD_DEBUG_REG0__wd_nodma_busy_MASK 0x8
+#define WD_DEBUG_REG0__wd_nodma_busy__SHIFT 0x3
+#define WD_DEBUG_REG0__rbiu_busy_MASK 0x10
+#define WD_DEBUG_REG0__rbiu_busy__SHIFT 0x4
+#define WD_DEBUG_REG0__spl_dma_busy_MASK 0x20
+#define WD_DEBUG_REG0__spl_dma_busy__SHIFT 0x5
+#define WD_DEBUG_REG0__spl_di_busy_MASK 0x40
+#define WD_DEBUG_REG0__spl_di_busy__SHIFT 0x6
+#define WD_DEBUG_REG0__vgt0_active_q_MASK 0x80
+#define WD_DEBUG_REG0__vgt0_active_q__SHIFT 0x7
+#define WD_DEBUG_REG0__vgt1_active_q_MASK 0x100
+#define WD_DEBUG_REG0__vgt1_active_q__SHIFT 0x8
+#define WD_DEBUG_REG0__spl_dma_p1_busy_MASK 0x200
+#define WD_DEBUG_REG0__spl_dma_p1_busy__SHIFT 0x9
+#define WD_DEBUG_REG0__rbiu_dr_p1_fifo_busy_MASK 0x400
+#define WD_DEBUG_REG0__rbiu_dr_p1_fifo_busy__SHIFT 0xa
+#define WD_DEBUG_REG0__rbiu_di_p1_fifo_busy_MASK 0x800
+#define WD_DEBUG_REG0__rbiu_di_p1_fifo_busy__SHIFT 0xb
+#define WD_DEBUG_REG0__SPARE2_MASK 0x1000
+#define WD_DEBUG_REG0__SPARE2__SHIFT 0xc
+#define WD_DEBUG_REG0__rbiu_dr_fifo_busy_MASK 0x2000
+#define WD_DEBUG_REG0__rbiu_dr_fifo_busy__SHIFT 0xd
+#define WD_DEBUG_REG0__rbiu_spl_dr_valid_MASK 0x4000
+#define WD_DEBUG_REG0__rbiu_spl_dr_valid__SHIFT 0xe
+#define WD_DEBUG_REG0__spl_rbiu_dr_read_MASK 0x8000
+#define WD_DEBUG_REG0__spl_rbiu_dr_read__SHIFT 0xf
+#define WD_DEBUG_REG0__SPARE3_MASK 0x10000
+#define WD_DEBUG_REG0__SPARE3__SHIFT 0x10
+#define WD_DEBUG_REG0__rbiu_di_fifo_busy_MASK 0x20000
+#define WD_DEBUG_REG0__rbiu_di_fifo_busy__SHIFT 0x11
+#define WD_DEBUG_REG0__rbiu_spl_di_valid_MASK 0x40000
+#define WD_DEBUG_REG0__rbiu_spl_di_valid__SHIFT 0x12
+#define WD_DEBUG_REG0__spl_rbiu_di_read_MASK 0x80000
+#define WD_DEBUG_REG0__spl_rbiu_di_read__SHIFT 0x13
+#define WD_DEBUG_REG0__se0_synced_q_MASK 0x100000
+#define WD_DEBUG_REG0__se0_synced_q__SHIFT 0x14
+#define WD_DEBUG_REG0__se1_synced_q_MASK 0x200000
+#define WD_DEBUG_REG0__se1_synced_q__SHIFT 0x15
+#define WD_DEBUG_REG0__se2_synced_q_MASK 0x400000
+#define WD_DEBUG_REG0__se2_synced_q__SHIFT 0x16
+#define WD_DEBUG_REG0__se3_synced_q_MASK 0x800000
+#define WD_DEBUG_REG0__se3_synced_q__SHIFT 0x17
+#define WD_DEBUG_REG0__reg_clk_busy_MASK 0x1000000
+#define WD_DEBUG_REG0__reg_clk_busy__SHIFT 0x18
+#define WD_DEBUG_REG0__input_clk_busy_MASK 0x2000000
+#define WD_DEBUG_REG0__input_clk_busy__SHIFT 0x19
+#define WD_DEBUG_REG0__core_clk_busy_MASK 0x4000000
+#define WD_DEBUG_REG0__core_clk_busy__SHIFT 0x1a
+#define WD_DEBUG_REG0__vgt2_active_q_MASK 0x8000000
+#define WD_DEBUG_REG0__vgt2_active_q__SHIFT 0x1b
+#define WD_DEBUG_REG0__sclk_reg_vld_MASK 0x10000000
+#define WD_DEBUG_REG0__sclk_reg_vld__SHIFT 0x1c
+#define WD_DEBUG_REG0__sclk_input_vld_MASK 0x20000000
+#define WD_DEBUG_REG0__sclk_input_vld__SHIFT 0x1d
+#define WD_DEBUG_REG0__sclk_core_vld_MASK 0x40000000
+#define WD_DEBUG_REG0__sclk_core_vld__SHIFT 0x1e
+#define WD_DEBUG_REG0__vgt3_active_q_MASK 0x80000000
+#define WD_DEBUG_REG0__vgt3_active_q__SHIFT 0x1f
+#define WD_DEBUG_REG1__grbm_fifo_empty_MASK 0x1
+#define WD_DEBUG_REG1__grbm_fifo_empty__SHIFT 0x0
+#define WD_DEBUG_REG1__grbm_fifo_full_MASK 0x2
+#define WD_DEBUG_REG1__grbm_fifo_full__SHIFT 0x1
+#define WD_DEBUG_REG1__grbm_fifo_we_MASK 0x4
+#define WD_DEBUG_REG1__grbm_fifo_we__SHIFT 0x2
+#define WD_DEBUG_REG1__grbm_fifo_re_MASK 0x8
+#define WD_DEBUG_REG1__grbm_fifo_re__SHIFT 0x3
+#define WD_DEBUG_REG1__draw_initiator_valid_q_MASK 0x10
+#define WD_DEBUG_REG1__draw_initiator_valid_q__SHIFT 0x4
+#define WD_DEBUG_REG1__event_initiator_valid_q_MASK 0x20
+#define WD_DEBUG_REG1__event_initiator_valid_q__SHIFT 0x5
+#define WD_DEBUG_REG1__event_addr_valid_q_MASK 0x40
+#define WD_DEBUG_REG1__event_addr_valid_q__SHIFT 0x6
+#define WD_DEBUG_REG1__dma_request_valid_q_MASK 0x80
+#define WD_DEBUG_REG1__dma_request_valid_q__SHIFT 0x7
+#define WD_DEBUG_REG1__SPARE0_MASK 0x100
+#define WD_DEBUG_REG1__SPARE0__SHIFT 0x8
+#define WD_DEBUG_REG1__min_indx_valid_q_MASK 0x200
+#define WD_DEBUG_REG1__min_indx_valid_q__SHIFT 0x9
+#define WD_DEBUG_REG1__max_indx_valid_q_MASK 0x400
+#define WD_DEBUG_REG1__max_indx_valid_q__SHIFT 0xa
+#define WD_DEBUG_REG1__indx_offset_valid_q_MASK 0x800
+#define WD_DEBUG_REG1__indx_offset_valid_q__SHIFT 0xb
+#define WD_DEBUG_REG1__grbm_fifo_rdata_reg_id_MASK 0x1f000
+#define WD_DEBUG_REG1__grbm_fifo_rdata_reg_id__SHIFT 0xc
+#define WD_DEBUG_REG1__grbm_fifo_rdata_state_MASK 0xe0000
+#define WD_DEBUG_REG1__grbm_fifo_rdata_state__SHIFT 0x11
+#define WD_DEBUG_REG1__free_cnt_q_MASK 0x3f00000
+#define WD_DEBUG_REG1__free_cnt_q__SHIFT 0x14
+#define WD_DEBUG_REG1__rbiu_di_fifo_we_MASK 0x4000000
+#define WD_DEBUG_REG1__rbiu_di_fifo_we__SHIFT 0x1a
+#define WD_DEBUG_REG1__rbiu_dr_fifo_we_MASK 0x8000000
+#define WD_DEBUG_REG1__rbiu_dr_fifo_we__SHIFT 0x1b
+#define WD_DEBUG_REG1__rbiu_di_fifo_empty_MASK 0x10000000
+#define WD_DEBUG_REG1__rbiu_di_fifo_empty__SHIFT 0x1c
+#define WD_DEBUG_REG1__rbiu_di_fifo_full_MASK 0x20000000
+#define WD_DEBUG_REG1__rbiu_di_fifo_full__SHIFT 0x1d
+#define WD_DEBUG_REG1__rbiu_dr_fifo_empty_MASK 0x40000000
+#define WD_DEBUG_REG1__rbiu_dr_fifo_empty__SHIFT 0x1e
+#define WD_DEBUG_REG1__rbiu_dr_fifo_full_MASK 0x80000000
+#define WD_DEBUG_REG1__rbiu_dr_fifo_full__SHIFT 0x1f
+#define WD_DEBUG_REG2__p1_grbm_fifo_empty_MASK 0x1
+#define WD_DEBUG_REG2__p1_grbm_fifo_empty__SHIFT 0x0
+#define WD_DEBUG_REG2__p1_grbm_fifo_full_MASK 0x2
+#define WD_DEBUG_REG2__p1_grbm_fifo_full__SHIFT 0x1
+#define WD_DEBUG_REG2__p1_grbm_fifo_we_MASK 0x4
+#define WD_DEBUG_REG2__p1_grbm_fifo_we__SHIFT 0x2
+#define WD_DEBUG_REG2__p1_grbm_fifo_re_MASK 0x8
+#define WD_DEBUG_REG2__p1_grbm_fifo_re__SHIFT 0x3
+#define WD_DEBUG_REG2__p1_draw_initiator_valid_q_MASK 0x10
+#define WD_DEBUG_REG2__p1_draw_initiator_valid_q__SHIFT 0x4
+#define WD_DEBUG_REG2__p1_event_initiator_valid_q_MASK 0x20
+#define WD_DEBUG_REG2__p1_event_initiator_valid_q__SHIFT 0x5
+#define WD_DEBUG_REG2__p1_event_addr_valid_q_MASK 0x40
+#define WD_DEBUG_REG2__p1_event_addr_valid_q__SHIFT 0x6
+#define WD_DEBUG_REG2__p1_dma_request_valid_q_MASK 0x80
+#define WD_DEBUG_REG2__p1_dma_request_valid_q__SHIFT 0x7
+#define WD_DEBUG_REG2__SPARE0_MASK 0x100
+#define WD_DEBUG_REG2__SPARE0__SHIFT 0x8
+#define WD_DEBUG_REG2__p1_min_indx_valid_q_MASK 0x200
+#define WD_DEBUG_REG2__p1_min_indx_valid_q__SHIFT 0x9
+#define WD_DEBUG_REG2__p1_max_indx_valid_q_MASK 0x400
+#define WD_DEBUG_REG2__p1_max_indx_valid_q__SHIFT 0xa
+#define WD_DEBUG_REG2__p1_indx_offset_valid_q_MASK 0x800
+#define WD_DEBUG_REG2__p1_indx_offset_valid_q__SHIFT 0xb
+#define WD_DEBUG_REG2__p1_grbm_fifo_rdata_reg_id_MASK 0x1f000
+#define WD_DEBUG_REG2__p1_grbm_fifo_rdata_reg_id__SHIFT 0xc
+#define WD_DEBUG_REG2__p1_grbm_fifo_rdata_state_MASK 0xe0000
+#define WD_DEBUG_REG2__p1_grbm_fifo_rdata_state__SHIFT 0x11
+#define WD_DEBUG_REG2__p1_free_cnt_q_MASK 0x3f00000
+#define WD_DEBUG_REG2__p1_free_cnt_q__SHIFT 0x14
+#define WD_DEBUG_REG2__p1_rbiu_di_fifo_we_MASK 0x4000000
+#define WD_DEBUG_REG2__p1_rbiu_di_fifo_we__SHIFT 0x1a
+#define WD_DEBUG_REG2__p1_rbiu_dr_fifo_we_MASK 0x8000000
+#define WD_DEBUG_REG2__p1_rbiu_dr_fifo_we__SHIFT 0x1b
+#define WD_DEBUG_REG2__p1_rbiu_di_fifo_empty_MASK 0x10000000
+#define WD_DEBUG_REG2__p1_rbiu_di_fifo_empty__SHIFT 0x1c
+#define WD_DEBUG_REG2__p1_rbiu_di_fifo_full_MASK 0x20000000
+#define WD_DEBUG_REG2__p1_rbiu_di_fifo_full__SHIFT 0x1d
+#define WD_DEBUG_REG2__p1_rbiu_dr_fifo_empty_MASK 0x40000000
+#define WD_DEBUG_REG2__p1_rbiu_dr_fifo_empty__SHIFT 0x1e
+#define WD_DEBUG_REG2__p1_rbiu_dr_fifo_full_MASK 0x80000000
+#define WD_DEBUG_REG2__p1_rbiu_dr_fifo_full__SHIFT 0x1f
+#define WD_DEBUG_REG3__rbiu_spl_dr_valid_MASK 0x1
+#define WD_DEBUG_REG3__rbiu_spl_dr_valid__SHIFT 0x0
+#define WD_DEBUG_REG3__SPARE0_MASK 0x2
+#define WD_DEBUG_REG3__SPARE0__SHIFT 0x1
+#define WD_DEBUG_REG3__pipe0_dr_MASK 0x4
+#define WD_DEBUG_REG3__pipe0_dr__SHIFT 0x2
+#define WD_DEBUG_REG3__pipe0_rtr_MASK 0x8
+#define WD_DEBUG_REG3__pipe0_rtr__SHIFT 0x3
+#define WD_DEBUG_REG3__pipe1_dr_MASK 0x10
+#define WD_DEBUG_REG3__pipe1_dr__SHIFT 0x4
+#define WD_DEBUG_REG3__pipe1_rtr_MASK 0x20
+#define WD_DEBUG_REG3__pipe1_rtr__SHIFT 0x5
+#define WD_DEBUG_REG3__wd_subdma_fifo_empty_MASK 0x40
+#define WD_DEBUG_REG3__wd_subdma_fifo_empty__SHIFT 0x6
+#define WD_DEBUG_REG3__wd_subdma_fifo_full_MASK 0x80
+#define WD_DEBUG_REG3__wd_subdma_fifo_full__SHIFT 0x7
+#define WD_DEBUG_REG3__dma_buf_type_p0_q_MASK 0x300
+#define WD_DEBUG_REG3__dma_buf_type_p0_q__SHIFT 0x8
+#define WD_DEBUG_REG3__dma_zero_indices_p0_q_MASK 0x400
+#define WD_DEBUG_REG3__dma_zero_indices_p0_q__SHIFT 0xa
+#define WD_DEBUG_REG3__dma_req_path_p3_q_MASK 0x800
+#define WD_DEBUG_REG3__dma_req_path_p3_q__SHIFT 0xb
+#define WD_DEBUG_REG3__dma_not_eop_p1_q_MASK 0x1000
+#define WD_DEBUG_REG3__dma_not_eop_p1_q__SHIFT 0xc
+#define WD_DEBUG_REG3__out_of_range_p4_MASK 0x2000
+#define WD_DEBUG_REG3__out_of_range_p4__SHIFT 0xd
+#define WD_DEBUG_REG3__last_sub_dma_p3_q_MASK 0x4000
+#define WD_DEBUG_REG3__last_sub_dma_p3_q__SHIFT 0xe
+#define WD_DEBUG_REG3__last_rdreq_of_sub_dma_p4_MASK 0x8000
+#define WD_DEBUG_REG3__last_rdreq_of_sub_dma_p4__SHIFT 0xf
+#define WD_DEBUG_REG3__WD_IA_dma_send_d_MASK 0x10000
+#define WD_DEBUG_REG3__WD_IA_dma_send_d__SHIFT 0x10
+#define WD_DEBUG_REG3__WD_IA_dma_rtr_MASK 0x20000
+#define WD_DEBUG_REG3__WD_IA_dma_rtr__SHIFT 0x11
+#define WD_DEBUG_REG3__WD_IA1_dma_send_d_MASK 0x40000
+#define WD_DEBUG_REG3__WD_IA1_dma_send_d__SHIFT 0x12
+#define WD_DEBUG_REG3__WD_IA1_dma_rtr_MASK 0x80000
+#define WD_DEBUG_REG3__WD_IA1_dma_rtr__SHIFT 0x13
+#define WD_DEBUG_REG3__last_inst_of_dma_p2_MASK 0x100000
+#define WD_DEBUG_REG3__last_inst_of_dma_p2__SHIFT 0x14
+#define WD_DEBUG_REG3__last_sd_of_inst_p2_MASK 0x200000
+#define WD_DEBUG_REG3__last_sd_of_inst_p2__SHIFT 0x15
+#define WD_DEBUG_REG3__last_sd_of_dma_p2_MASK 0x400000
+#define WD_DEBUG_REG3__last_sd_of_dma_p2__SHIFT 0x16
+#define WD_DEBUG_REG3__SPARE1_MASK 0x800000
+#define WD_DEBUG_REG3__SPARE1__SHIFT 0x17
+#define WD_DEBUG_REG3__WD_IA_dma_busy_MASK 0x1000000
+#define WD_DEBUG_REG3__WD_IA_dma_busy__SHIFT 0x18
+#define WD_DEBUG_REG3__WD_IA1_dma_busy_MASK 0x2000000
+#define WD_DEBUG_REG3__WD_IA1_dma_busy__SHIFT 0x19
+#define WD_DEBUG_REG3__send_to_ia1_p3_q_MASK 0x4000000
+#define WD_DEBUG_REG3__send_to_ia1_p3_q__SHIFT 0x1a
+#define WD_DEBUG_REG3__dma_wd_switch_on_eop_p3_q_MASK 0x8000000
+#define WD_DEBUG_REG3__dma_wd_switch_on_eop_p3_q__SHIFT 0x1b
+#define WD_DEBUG_REG3__pipe3_dr_MASK 0x10000000
+#define WD_DEBUG_REG3__pipe3_dr__SHIFT 0x1c
+#define WD_DEBUG_REG3__pipe3_rtr_MASK 0x20000000
+#define WD_DEBUG_REG3__pipe3_rtr__SHIFT 0x1d
+#define WD_DEBUG_REG3__wd_dma2draw_fifo_empty_MASK 0x40000000
+#define WD_DEBUG_REG3__wd_dma2draw_fifo_empty__SHIFT 0x1e
+#define WD_DEBUG_REG3__wd_dma2draw_fifo_full_MASK 0x80000000
+#define WD_DEBUG_REG3__wd_dma2draw_fifo_full__SHIFT 0x1f
+#define WD_DEBUG_REG4__rbiu_spl_di_valid_MASK 0x1
+#define WD_DEBUG_REG4__rbiu_spl_di_valid__SHIFT 0x0
+#define WD_DEBUG_REG4__spl_rbiu_di_read_MASK 0x2
+#define WD_DEBUG_REG4__spl_rbiu_di_read__SHIFT 0x1
+#define WD_DEBUG_REG4__rbiu_spl_p1_di_valid_MASK 0x4
+#define WD_DEBUG_REG4__rbiu_spl_p1_di_valid__SHIFT 0x2
+#define WD_DEBUG_REG4__spl_rbiu_p1_di_read_MASK 0x8
+#define WD_DEBUG_REG4__spl_rbiu_p1_di_read__SHIFT 0x3
+#define WD_DEBUG_REG4__pipe0_dr_MASK 0x10
+#define WD_DEBUG_REG4__pipe0_dr__SHIFT 0x4
+#define WD_DEBUG_REG4__pipe0_rtr_MASK 0x20
+#define WD_DEBUG_REG4__pipe0_rtr__SHIFT 0x5
+#define WD_DEBUG_REG4__pipe1_dr_MASK 0x40
+#define WD_DEBUG_REG4__pipe1_dr__SHIFT 0x6
+#define WD_DEBUG_REG4__pipe1_rtr_MASK 0x80
+#define WD_DEBUG_REG4__pipe1_rtr__SHIFT 0x7
+#define WD_DEBUG_REG4__pipe2_dr_MASK 0x100
+#define WD_DEBUG_REG4__pipe2_dr__SHIFT 0x8
+#define WD_DEBUG_REG4__pipe2_rtr_MASK 0x200
+#define WD_DEBUG_REG4__pipe2_rtr__SHIFT 0x9
+#define WD_DEBUG_REG4__pipe3_ld_MASK 0x400
+#define WD_DEBUG_REG4__pipe3_ld__SHIFT 0xa
+#define WD_DEBUG_REG4__pipe3_rtr_MASK 0x800
+#define WD_DEBUG_REG4__pipe3_rtr__SHIFT 0xb
+#define WD_DEBUG_REG4__WD_IA_draw_send_d_MASK 0x1000
+#define WD_DEBUG_REG4__WD_IA_draw_send_d__SHIFT 0xc
+#define WD_DEBUG_REG4__WD_IA_draw_rtr_MASK 0x2000
+#define WD_DEBUG_REG4__WD_IA_draw_rtr__SHIFT 0xd
+#define WD_DEBUG_REG4__di_type_p0_MASK 0xc000
+#define WD_DEBUG_REG4__di_type_p0__SHIFT 0xe
+#define WD_DEBUG_REG4__di_state_sel_p1_q_MASK 0x70000
+#define WD_DEBUG_REG4__di_state_sel_p1_q__SHIFT 0x10
+#define WD_DEBUG_REG4__di_wd_switch_on_eop_p1_q_MASK 0x80000
+#define WD_DEBUG_REG4__di_wd_switch_on_eop_p1_q__SHIFT 0x13
+#define WD_DEBUG_REG4__rbiu_spl_pipe0_lockout_MASK 0x100000
+#define WD_DEBUG_REG4__rbiu_spl_pipe0_lockout__SHIFT 0x14
+#define WD_DEBUG_REG4__last_inst_of_di_p2_MASK 0x200000
+#define WD_DEBUG_REG4__last_inst_of_di_p2__SHIFT 0x15
+#define WD_DEBUG_REG4__last_sd_of_inst_p2_MASK 0x400000
+#define WD_DEBUG_REG4__last_sd_of_inst_p2__SHIFT 0x16
+#define WD_DEBUG_REG4__last_sd_of_di_p2_MASK 0x800000
+#define WD_DEBUG_REG4__last_sd_of_di_p2__SHIFT 0x17
+#define WD_DEBUG_REG4__not_eop_wait_p1_q_MASK 0x1000000
+#define WD_DEBUG_REG4__not_eop_wait_p1_q__SHIFT 0x18
+#define WD_DEBUG_REG4__not_eop_wait_q_MASK 0x2000000
+#define WD_DEBUG_REG4__not_eop_wait_q__SHIFT 0x19
+#define WD_DEBUG_REG4__ext_event_wait_p1_q_MASK 0x4000000
+#define WD_DEBUG_REG4__ext_event_wait_p1_q__SHIFT 0x1a
+#define WD_DEBUG_REG4__ext_event_wait_q_MASK 0x8000000
+#define WD_DEBUG_REG4__ext_event_wait_q__SHIFT 0x1b
+#define WD_DEBUG_REG4__WD_IA1_draw_send_d_MASK 0x10000000
+#define WD_DEBUG_REG4__WD_IA1_draw_send_d__SHIFT 0x1c
+#define WD_DEBUG_REG4__WD_IA1_draw_rtr_MASK 0x20000000
+#define WD_DEBUG_REG4__WD_IA1_draw_rtr__SHIFT 0x1d
+#define WD_DEBUG_REG4__send_to_ia1_q_MASK 0x40000000
+#define WD_DEBUG_REG4__send_to_ia1_q__SHIFT 0x1e
+#define WD_DEBUG_REG4__dual_ia_mode_MASK 0x80000000
+#define WD_DEBUG_REG4__dual_ia_mode__SHIFT 0x1f
+#define WD_DEBUG_REG5__p1_rbiu_spl_dr_valid_MASK 0x1
+#define WD_DEBUG_REG5__p1_rbiu_spl_dr_valid__SHIFT 0x0
+#define WD_DEBUG_REG5__SPARE0_MASK 0x2
+#define WD_DEBUG_REG5__SPARE0__SHIFT 0x1
+#define WD_DEBUG_REG5__p1_pipe0_dr_MASK 0x4
+#define WD_DEBUG_REG5__p1_pipe0_dr__SHIFT 0x2
+#define WD_DEBUG_REG5__p1_pipe0_rtr_MASK 0x8
+#define WD_DEBUG_REG5__p1_pipe0_rtr__SHIFT 0x3
+#define WD_DEBUG_REG5__p1_pipe1_dr_MASK 0x10
+#define WD_DEBUG_REG5__p1_pipe1_dr__SHIFT 0x4
+#define WD_DEBUG_REG5__p1_pipe1_rtr_MASK 0x20
+#define WD_DEBUG_REG5__p1_pipe1_rtr__SHIFT 0x5
+#define WD_DEBUG_REG5__p1_wd_subdma_fifo_empty_MASK 0x40
+#define WD_DEBUG_REG5__p1_wd_subdma_fifo_empty__SHIFT 0x6
+#define WD_DEBUG_REG5__p1_wd_subdma_fifo_full_MASK 0x80
+#define WD_DEBUG_REG5__p1_wd_subdma_fifo_full__SHIFT 0x7
+#define WD_DEBUG_REG5__p1_dma_buf_type_p0_q_MASK 0x300
+#define WD_DEBUG_REG5__p1_dma_buf_type_p0_q__SHIFT 0x8
+#define WD_DEBUG_REG5__p1_dma_zero_indices_p0_q_MASK 0x400
+#define WD_DEBUG_REG5__p1_dma_zero_indices_p0_q__SHIFT 0xa
+#define WD_DEBUG_REG5__p1_dma_req_path_p3_q_MASK 0x800
+#define WD_DEBUG_REG5__p1_dma_req_path_p3_q__SHIFT 0xb
+#define WD_DEBUG_REG5__p1_dma_not_eop_p1_q_MASK 0x1000
+#define WD_DEBUG_REG5__p1_dma_not_eop_p1_q__SHIFT 0xc
+#define WD_DEBUG_REG5__p1_out_of_range_p4_MASK 0x2000
+#define WD_DEBUG_REG5__p1_out_of_range_p4__SHIFT 0xd
+#define WD_DEBUG_REG5__p1_last_sub_dma_p3_q_MASK 0x4000
+#define WD_DEBUG_REG5__p1_last_sub_dma_p3_q__SHIFT 0xe
+#define WD_DEBUG_REG5__p1_last_rdreq_of_sub_dma_p4_MASK 0x8000
+#define WD_DEBUG_REG5__p1_last_rdreq_of_sub_dma_p4__SHIFT 0xf
+#define WD_DEBUG_REG5__p1_WD_IA_dma_send_d_MASK 0x10000
+#define WD_DEBUG_REG5__p1_WD_IA_dma_send_d__SHIFT 0x10
+#define WD_DEBUG_REG5__p1_WD_IA_dma_rtr_MASK 0x20000
+#define WD_DEBUG_REG5__p1_WD_IA_dma_rtr__SHIFT 0x11
+#define WD_DEBUG_REG5__p1_WD_IA1_dma_send_d_MASK 0x40000
+#define WD_DEBUG_REG5__p1_WD_IA1_dma_send_d__SHIFT 0x12
+#define WD_DEBUG_REG5__p1_WD_IA1_dma_rtr_MASK 0x80000
+#define WD_DEBUG_REG5__p1_WD_IA1_dma_rtr__SHIFT 0x13
+#define WD_DEBUG_REG5__p1_last_inst_of_dma_p2_MASK 0x100000
+#define WD_DEBUG_REG5__p1_last_inst_of_dma_p2__SHIFT 0x14
+#define WD_DEBUG_REG5__p1_last_sd_of_inst_p2_MASK 0x200000
+#define WD_DEBUG_REG5__p1_last_sd_of_inst_p2__SHIFT 0x15
+#define WD_DEBUG_REG5__p1_last_sd_of_dma_p2_MASK 0x400000
+#define WD_DEBUG_REG5__p1_last_sd_of_dma_p2__SHIFT 0x16
+#define WD_DEBUG_REG5__SPARE1_MASK 0x800000
+#define WD_DEBUG_REG5__SPARE1__SHIFT 0x17
+#define WD_DEBUG_REG5__p1_WD_IA_dma_busy_MASK 0x1000000
+#define WD_DEBUG_REG5__p1_WD_IA_dma_busy__SHIFT 0x18
+#define WD_DEBUG_REG5__p1_WD_IA1_dma_busy_MASK 0x2000000
+#define WD_DEBUG_REG5__p1_WD_IA1_dma_busy__SHIFT 0x19
+#define WD_DEBUG_REG5__p1_send_to_ia1_p3_q_MASK 0x4000000
+#define WD_DEBUG_REG5__p1_send_to_ia1_p3_q__SHIFT 0x1a
+#define WD_DEBUG_REG5__p1_dma_wd_switch_on_eop_p3_q_MASK 0x8000000
+#define WD_DEBUG_REG5__p1_dma_wd_switch_on_eop_p3_q__SHIFT 0x1b
+#define WD_DEBUG_REG5__p1_pipe3_dr_MASK 0x10000000
+#define WD_DEBUG_REG5__p1_pipe3_dr__SHIFT 0x1c
+#define WD_DEBUG_REG5__p1_pipe3_rtr_MASK 0x20000000
+#define WD_DEBUG_REG5__p1_pipe3_rtr__SHIFT 0x1d
+#define WD_DEBUG_REG5__p1_wd_dma2draw_fifo_empty_MASK 0x40000000
+#define WD_DEBUG_REG5__p1_wd_dma2draw_fifo_empty__SHIFT 0x1e
+#define WD_DEBUG_REG5__p1_wd_dma2draw_fifo_full_MASK 0x80000000
+#define WD_DEBUG_REG5__p1_wd_dma2draw_fifo_full__SHIFT 0x1f
+#define WD_DEBUG_REG6__WD_IA_draw_eop_MASK 0xffffffff
+#define WD_DEBUG_REG6__WD_IA_draw_eop__SHIFT 0x0
+#define WD_DEBUG_REG7__SE0VGT_WD_thdgrp_send_in_MASK 0x1
+#define WD_DEBUG_REG7__SE0VGT_WD_thdgrp_send_in__SHIFT 0x0
+#define WD_DEBUG_REG7__wd_arb_se0_input_fifo_re_MASK 0x2
+#define WD_DEBUG_REG7__wd_arb_se0_input_fifo_re__SHIFT 0x1
+#define WD_DEBUG_REG7__wd_arb_se0_input_fifo_empty_MASK 0x4
+#define WD_DEBUG_REG7__wd_arb_se0_input_fifo_empty__SHIFT 0x2
+#define WD_DEBUG_REG7__wd_arb_se0_input_fifo_full_MASK 0x8
+#define WD_DEBUG_REG7__wd_arb_se0_input_fifo_full__SHIFT 0x3
+#define WD_DEBUG_REG7__SE1VGT_WD_thdgrp_send_in_MASK 0x10
+#define WD_DEBUG_REG7__SE1VGT_WD_thdgrp_send_in__SHIFT 0x4
+#define WD_DEBUG_REG7__wd_arb_se1_input_fifo_re_MASK 0x20
+#define WD_DEBUG_REG7__wd_arb_se1_input_fifo_re__SHIFT 0x5
+#define WD_DEBUG_REG7__wd_arb_se1_input_fifo_empty_MASK 0x40
+#define WD_DEBUG_REG7__wd_arb_se1_input_fifo_empty__SHIFT 0x6
+#define WD_DEBUG_REG7__wd_arb_se1_input_fifo_full_MASK 0x80
+#define WD_DEBUG_REG7__wd_arb_se1_input_fifo_full__SHIFT 0x7
+#define WD_DEBUG_REG7__SPARE1_MASK 0xf00
+#define WD_DEBUG_REG7__SPARE1__SHIFT 0x8
+#define WD_DEBUG_REG7__SPARE2_MASK 0xf000
+#define WD_DEBUG_REG7__SPARE2__SHIFT 0xc
+#define WD_DEBUG_REG7__te11_arb_state_q_MASK 0x70000
+#define WD_DEBUG_REG7__te11_arb_state_q__SHIFT 0x10
+#define WD_DEBUG_REG7__SPARE5_MASK 0x80000
+#define WD_DEBUG_REG7__SPARE5__SHIFT 0x13
+#define WD_DEBUG_REG7__se0_thdgrp_is_event_MASK 0x100000
+#define WD_DEBUG_REG7__se0_thdgrp_is_event__SHIFT 0x14
+#define WD_DEBUG_REG7__se0_thdgrp_eop_MASK 0x200000
+#define WD_DEBUG_REG7__se0_thdgrp_eop__SHIFT 0x15
+#define WD_DEBUG_REG7__se1_thdgrp_is_event_MASK 0x400000
+#define WD_DEBUG_REG7__se1_thdgrp_is_event__SHIFT 0x16
+#define WD_DEBUG_REG7__se1_thdgrp_eop_MASK 0x800000
+#define WD_DEBUG_REG7__se1_thdgrp_eop__SHIFT 0x17
+#define WD_DEBUG_REG7__SPARE6_MASK 0xf000000
+#define WD_DEBUG_REG7__SPARE6__SHIFT 0x18
+#define WD_DEBUG_REG7__tfreq_arb_tgroup_rtr_MASK 0x10000000
+#define WD_DEBUG_REG7__tfreq_arb_tgroup_rtr__SHIFT 0x1c
+#define WD_DEBUG_REG7__arb_tfreq_tgroup_rts_MASK 0x20000000
+#define WD_DEBUG_REG7__arb_tfreq_tgroup_rts__SHIFT 0x1d
+#define WD_DEBUG_REG7__arb_tfreq_tgroup_event_MASK 0x40000000
+#define WD_DEBUG_REG7__arb_tfreq_tgroup_event__SHIFT 0x1e
+#define WD_DEBUG_REG7__te11_arb_busy_MASK 0x80000000
+#define WD_DEBUG_REG7__te11_arb_busy__SHIFT 0x1f
+#define WD_DEBUG_REG8__pipe0_dr_MASK 0x1
+#define WD_DEBUG_REG8__pipe0_dr__SHIFT 0x0
+#define WD_DEBUG_REG8__pipe1_dr_MASK 0x2
+#define WD_DEBUG_REG8__pipe1_dr__SHIFT 0x1
+#define WD_DEBUG_REG8__pipe0_rtr_MASK 0x4
+#define WD_DEBUG_REG8__pipe0_rtr__SHIFT 0x2
+#define WD_DEBUG_REG8__pipe1_rtr_MASK 0x8
+#define WD_DEBUG_REG8__pipe1_rtr__SHIFT 0x3
+#define WD_DEBUG_REG8__tfreq_tg_fifo_empty_MASK 0x10
+#define WD_DEBUG_REG8__tfreq_tg_fifo_empty__SHIFT 0x4
+#define WD_DEBUG_REG8__tfreq_tg_fifo_full_MASK 0x20
+#define WD_DEBUG_REG8__tfreq_tg_fifo_full__SHIFT 0x5
+#define WD_DEBUG_REG8__tf_data_fifo_busy_q_MASK 0x40
+#define WD_DEBUG_REG8__tf_data_fifo_busy_q__SHIFT 0x6
+#define WD_DEBUG_REG8__tf_data_fifo_rtr_q_MASK 0x80
+#define WD_DEBUG_REG8__tf_data_fifo_rtr_q__SHIFT 0x7
+#define WD_DEBUG_REG8__tf_skid_fifo_empty_MASK 0x100
+#define WD_DEBUG_REG8__tf_skid_fifo_empty__SHIFT 0x8
+#define WD_DEBUG_REG8__tf_skid_fifo_full_MASK 0x200
+#define WD_DEBUG_REG8__tf_skid_fifo_full__SHIFT 0x9
+#define WD_DEBUG_REG8__wd_tc_rdreq_rtr_q_MASK 0x400
+#define WD_DEBUG_REG8__wd_tc_rdreq_rtr_q__SHIFT 0xa
+#define WD_DEBUG_REG8__last_req_of_tg_p2_MASK 0x800
+#define WD_DEBUG_REG8__last_req_of_tg_p2__SHIFT 0xb
+#define WD_DEBUG_REG8__se0spi_wd_hs_done_cnt_q_MASK 0x3f000
+#define WD_DEBUG_REG8__se0spi_wd_hs_done_cnt_q__SHIFT 0xc
+#define WD_DEBUG_REG8__event_flag_p1_q_MASK 0x40000
+#define WD_DEBUG_REG8__event_flag_p1_q__SHIFT 0x12
+#define WD_DEBUG_REG8__null_flag_p1_q_MASK 0x80000
+#define WD_DEBUG_REG8__null_flag_p1_q__SHIFT 0x13
+#define WD_DEBUG_REG8__tf_data_fifo_cnt_q_MASK 0x7f00000
+#define WD_DEBUG_REG8__tf_data_fifo_cnt_q__SHIFT 0x14
+#define WD_DEBUG_REG8__second_tf_ret_data_q_MASK 0x8000000
+#define WD_DEBUG_REG8__second_tf_ret_data_q__SHIFT 0x1b
+#define WD_DEBUG_REG8__first_req_of_tg_p1_q_MASK 0x10000000
+#define WD_DEBUG_REG8__first_req_of_tg_p1_q__SHIFT 0x1c
+#define WD_DEBUG_REG8__WD_TC_rdreq_send_out_MASK 0x20000000
+#define WD_DEBUG_REG8__WD_TC_rdreq_send_out__SHIFT 0x1d
+#define WD_DEBUG_REG8__WD_TC_rdnfo_stall_out_MASK 0x40000000
+#define WD_DEBUG_REG8__WD_TC_rdnfo_stall_out__SHIFT 0x1e
+#define WD_DEBUG_REG8__TC_WD_rdret_valid_in_MASK 0x80000000
+#define WD_DEBUG_REG8__TC_WD_rdret_valid_in__SHIFT 0x1f
+#define WD_DEBUG_REG9__pipe0_dr_MASK 0x1
+#define WD_DEBUG_REG9__pipe0_dr__SHIFT 0x0
+#define WD_DEBUG_REG9__pipec_tf_dr_MASK 0x2
+#define WD_DEBUG_REG9__pipec_tf_dr__SHIFT 0x1
+#define WD_DEBUG_REG9__pipe2_dr_MASK 0x4
+#define WD_DEBUG_REG9__pipe2_dr__SHIFT 0x2
+#define WD_DEBUG_REG9__event_or_null_flags_p0_q_MASK 0x8
+#define WD_DEBUG_REG9__event_or_null_flags_p0_q__SHIFT 0x3
+#define WD_DEBUG_REG9__pipe0_rtr_MASK 0x10
+#define WD_DEBUG_REG9__pipe0_rtr__SHIFT 0x4
+#define WD_DEBUG_REG9__pipe1_rtr_MASK 0x20
+#define WD_DEBUG_REG9__pipe1_rtr__SHIFT 0x5
+#define WD_DEBUG_REG9__pipec_tf_rtr_MASK 0x40
+#define WD_DEBUG_REG9__pipec_tf_rtr__SHIFT 0x6
+#define WD_DEBUG_REG9__pipe2_rtr_MASK 0x80
+#define WD_DEBUG_REG9__pipe2_rtr__SHIFT 0x7
+#define WD_DEBUG_REG9__ttp_patch_fifo_full_MASK 0x100
+#define WD_DEBUG_REG9__ttp_patch_fifo_full__SHIFT 0x8
+#define WD_DEBUG_REG9__ttp_patch_fifo_empty_MASK 0x200
+#define WD_DEBUG_REG9__ttp_patch_fifo_empty__SHIFT 0x9
+#define WD_DEBUG_REG9__ttp_tf_fifo_empty_MASK 0x400
+#define WD_DEBUG_REG9__ttp_tf_fifo_empty__SHIFT 0xa
+#define WD_DEBUG_REG9__SPARE0_MASK 0xf800
+#define WD_DEBUG_REG9__SPARE0__SHIFT 0xb
+#define WD_DEBUG_REG9__tf_fetch_state_q_MASK 0x70000
+#define WD_DEBUG_REG9__tf_fetch_state_q__SHIFT 0x10
+#define WD_DEBUG_REG9__last_patch_of_tg_MASK 0x80000
+#define WD_DEBUG_REG9__last_patch_of_tg__SHIFT 0x13
+#define WD_DEBUG_REG9__tf_pointer_p0_q_MASK 0xf00000
+#define WD_DEBUG_REG9__tf_pointer_p0_q__SHIFT 0x14
+#define WD_DEBUG_REG9__dynamic_hs_p0_q_MASK 0x1000000
+#define WD_DEBUG_REG9__dynamic_hs_p0_q__SHIFT 0x18
+#define WD_DEBUG_REG9__first_fetch_of_tg_p0_q_MASK 0x2000000
+#define WD_DEBUG_REG9__first_fetch_of_tg_p0_q__SHIFT 0x19
+#define WD_DEBUG_REG9__mem_is_even_MASK 0x4000000
+#define WD_DEBUG_REG9__mem_is_even__SHIFT 0x1a
+#define WD_DEBUG_REG9__SPARE1_MASK 0x8000000
+#define WD_DEBUG_REG9__SPARE1__SHIFT 0x1b
+#define WD_DEBUG_REG9__SPARE2_MASK 0x30000000
+#define WD_DEBUG_REG9__SPARE2__SHIFT 0x1c
+#define WD_DEBUG_REG9__pipe4_dr_MASK 0x40000000
+#define WD_DEBUG_REG9__pipe4_dr__SHIFT 0x1e
+#define WD_DEBUG_REG9__pipe4_rtr_MASK 0x80000000
+#define WD_DEBUG_REG9__pipe4_rtr__SHIFT 0x1f
+#define WD_DEBUG_REG10__ttp_pd_patch_rts_MASK 0x1
+#define WD_DEBUG_REG10__ttp_pd_patch_rts__SHIFT 0x0
+#define WD_DEBUG_REG10__ttp_pd_is_event_MASK 0x2
+#define WD_DEBUG_REG10__ttp_pd_is_event__SHIFT 0x1
+#define WD_DEBUG_REG10__ttp_pd_eopg_MASK 0x4
+#define WD_DEBUG_REG10__ttp_pd_eopg__SHIFT 0x2
+#define WD_DEBUG_REG10__ttp_pd_eop_MASK 0x8
+#define WD_DEBUG_REG10__ttp_pd_eop__SHIFT 0x3
+#define WD_DEBUG_REG10__pipe0_dr_MASK 0x10
+#define WD_DEBUG_REG10__pipe0_dr__SHIFT 0x4
+#define WD_DEBUG_REG10__pipe1_dr_MASK 0x20
+#define WD_DEBUG_REG10__pipe1_dr__SHIFT 0x5
+#define WD_DEBUG_REG10__pipe0_rtr_MASK 0x40
+#define WD_DEBUG_REG10__pipe0_rtr__SHIFT 0x6
+#define WD_DEBUG_REG10__pipe1_rtr_MASK 0x80
+#define WD_DEBUG_REG10__pipe1_rtr__SHIFT 0x7
+#define WD_DEBUG_REG10__donut_en_p1_q_MASK 0x100
+#define WD_DEBUG_REG10__donut_en_p1_q__SHIFT 0x8
+#define WD_DEBUG_REG10__donut_se_switch_p2_MASK 0x200
+#define WD_DEBUG_REG10__donut_se_switch_p2__SHIFT 0x9
+#define WD_DEBUG_REG10__patch_se_switch_p2_MASK 0x400
+#define WD_DEBUG_REG10__patch_se_switch_p2__SHIFT 0xa
+#define WD_DEBUG_REG10__last_donut_switch_p2_MASK 0x800
+#define WD_DEBUG_REG10__last_donut_switch_p2__SHIFT 0xb
+#define WD_DEBUG_REG10__last_donut_of_patch_p2_MASK 0x1000
+#define WD_DEBUG_REG10__last_donut_of_patch_p2__SHIFT 0xc
+#define WD_DEBUG_REG10__is_event_p1_q_MASK 0x2000
+#define WD_DEBUG_REG10__is_event_p1_q__SHIFT 0xd
+#define WD_DEBUG_REG10__eopg_p1_q_MASK 0x4000
+#define WD_DEBUG_REG10__eopg_p1_q__SHIFT 0xe
+#define WD_DEBUG_REG10__eop_p1_q_MASK 0x8000
+#define WD_DEBUG_REG10__eop_p1_q__SHIFT 0xf
+#define WD_DEBUG_REG10__patch_accum_q_MASK 0xff0000
+#define WD_DEBUG_REG10__patch_accum_q__SHIFT 0x10
+#define WD_DEBUG_REG10__wd_te11_out_se0_fifo_full_MASK 0x1000000
+#define WD_DEBUG_REG10__wd_te11_out_se0_fifo_full__SHIFT 0x18
+#define WD_DEBUG_REG10__wd_te11_out_se0_fifo_empty_MASK 0x2000000
+#define WD_DEBUG_REG10__wd_te11_out_se0_fifo_empty__SHIFT 0x19
+#define WD_DEBUG_REG10__wd_te11_out_se1_fifo_full_MASK 0x4000000
+#define WD_DEBUG_REG10__wd_te11_out_se1_fifo_full__SHIFT 0x1a
+#define WD_DEBUG_REG10__wd_te11_out_se1_fifo_empty_MASK 0x8000000
+#define WD_DEBUG_REG10__wd_te11_out_se1_fifo_empty__SHIFT 0x1b
+#define WD_DEBUG_REG10__wd_te11_out_se2_fifo_full_MASK 0x10000000
+#define WD_DEBUG_REG10__wd_te11_out_se2_fifo_full__SHIFT 0x1c
+#define WD_DEBUG_REG10__wd_te11_out_se2_fifo_empty_MASK 0x20000000
+#define WD_DEBUG_REG10__wd_te11_out_se2_fifo_empty__SHIFT 0x1d
+#define WD_DEBUG_REG10__wd_te11_out_se3_fifo_full_MASK 0x40000000
+#define WD_DEBUG_REG10__wd_te11_out_se3_fifo_full__SHIFT 0x1e
+#define WD_DEBUG_REG10__wd_te11_out_se3_fifo_empty_MASK 0x80000000
+#define WD_DEBUG_REG10__wd_te11_out_se3_fifo_empty__SHIFT 0x1f
+#define IA_DEBUG_REG0__ia_busy_extended_MASK 0x1
+#define IA_DEBUG_REG0__ia_busy_extended__SHIFT 0x0
+#define IA_DEBUG_REG0__ia_nodma_busy_extended_MASK 0x2
+#define IA_DEBUG_REG0__ia_nodma_busy_extended__SHIFT 0x1
+#define IA_DEBUG_REG0__ia_busy_MASK 0x4
+#define IA_DEBUG_REG0__ia_busy__SHIFT 0x2
+#define IA_DEBUG_REG0__ia_nodma_busy_MASK 0x8
+#define IA_DEBUG_REG0__ia_nodma_busy__SHIFT 0x3
+#define IA_DEBUG_REG0__SPARE0_MASK 0x10
+#define IA_DEBUG_REG0__SPARE0__SHIFT 0x4
+#define IA_DEBUG_REG0__dma_req_busy_MASK 0x20
+#define IA_DEBUG_REG0__dma_req_busy__SHIFT 0x5
+#define IA_DEBUG_REG0__dma_busy_MASK 0x40
+#define IA_DEBUG_REG0__dma_busy__SHIFT 0x6
+#define IA_DEBUG_REG0__mc_xl8r_busy_MASK 0x80
+#define IA_DEBUG_REG0__mc_xl8r_busy__SHIFT 0x7
+#define IA_DEBUG_REG0__grp_busy_MASK 0x100
+#define IA_DEBUG_REG0__grp_busy__SHIFT 0x8
+#define IA_DEBUG_REG0__SPARE1_MASK 0x200
+#define IA_DEBUG_REG0__SPARE1__SHIFT 0x9
+#define IA_DEBUG_REG0__dma_grp_valid_MASK 0x400
+#define IA_DEBUG_REG0__dma_grp_valid__SHIFT 0xa
+#define IA_DEBUG_REG0__grp_dma_read_MASK 0x800
+#define IA_DEBUG_REG0__grp_dma_read__SHIFT 0xb
+#define IA_DEBUG_REG0__dma_grp_hp_valid_MASK 0x1000
+#define IA_DEBUG_REG0__dma_grp_hp_valid__SHIFT 0xc
+#define IA_DEBUG_REG0__grp_dma_hp_read_MASK 0x2000
+#define IA_DEBUG_REG0__grp_dma_hp_read__SHIFT 0xd
+#define IA_DEBUG_REG0__SPARE2_MASK 0xffc000
+#define IA_DEBUG_REG0__SPARE2__SHIFT 0xe
+#define IA_DEBUG_REG0__reg_clk_busy_MASK 0x1000000
+#define IA_DEBUG_REG0__reg_clk_busy__SHIFT 0x18
+#define IA_DEBUG_REG0__core_clk_busy_MASK 0x2000000
+#define IA_DEBUG_REG0__core_clk_busy__SHIFT 0x19
+#define IA_DEBUG_REG0__SPARE3_MASK 0x4000000
+#define IA_DEBUG_REG0__SPARE3__SHIFT 0x1a
+#define IA_DEBUG_REG0__SPARE4_MASK 0x8000000
+#define IA_DEBUG_REG0__SPARE4__SHIFT 0x1b
+#define IA_DEBUG_REG0__sclk_reg_vld_MASK 0x10000000
+#define IA_DEBUG_REG0__sclk_reg_vld__SHIFT 0x1c
+#define IA_DEBUG_REG0__sclk_core_vld_MASK 0x20000000
+#define IA_DEBUG_REG0__sclk_core_vld__SHIFT 0x1d
+#define IA_DEBUG_REG0__SPARE5_MASK 0x40000000
+#define IA_DEBUG_REG0__SPARE5__SHIFT 0x1e
+#define IA_DEBUG_REG0__SPARE6_MASK 0x80000000
+#define IA_DEBUG_REG0__SPARE6__SHIFT 0x1f
+#define IA_DEBUG_REG1__dma_input_fifo_empty_MASK 0x1
+#define IA_DEBUG_REG1__dma_input_fifo_empty__SHIFT 0x0
+#define IA_DEBUG_REG1__dma_input_fifo_full_MASK 0x2
+#define IA_DEBUG_REG1__dma_input_fifo_full__SHIFT 0x1
+#define IA_DEBUG_REG1__start_new_packet_MASK 0x4
+#define IA_DEBUG_REG1__start_new_packet__SHIFT 0x2
+#define IA_DEBUG_REG1__dma_rdreq_dr_q_MASK 0x8
+#define IA_DEBUG_REG1__dma_rdreq_dr_q__SHIFT 0x3
+#define IA_DEBUG_REG1__dma_zero_indices_q_MASK 0x10
+#define IA_DEBUG_REG1__dma_zero_indices_q__SHIFT 0x4
+#define IA_DEBUG_REG1__dma_buf_type_q_MASK 0x60
+#define IA_DEBUG_REG1__dma_buf_type_q__SHIFT 0x5
+#define IA_DEBUG_REG1__dma_req_path_q_MASK 0x80
+#define IA_DEBUG_REG1__dma_req_path_q__SHIFT 0x7
+#define IA_DEBUG_REG1__discard_1st_chunk_MASK 0x100
+#define IA_DEBUG_REG1__discard_1st_chunk__SHIFT 0x8
+#define IA_DEBUG_REG1__discard_2nd_chunk_MASK 0x200
+#define IA_DEBUG_REG1__discard_2nd_chunk__SHIFT 0x9
+#define IA_DEBUG_REG1__second_tc_ret_data_q_MASK 0x400
+#define IA_DEBUG_REG1__second_tc_ret_data_q__SHIFT 0xa
+#define IA_DEBUG_REG1__dma_tc_ret_sel_q_MASK 0x800
+#define IA_DEBUG_REG1__dma_tc_ret_sel_q__SHIFT 0xb
+#define IA_DEBUG_REG1__last_rdreq_in_dma_op_MASK 0x1000
+#define IA_DEBUG_REG1__last_rdreq_in_dma_op__SHIFT 0xc
+#define IA_DEBUG_REG1__dma_mask_fifo_empty_MASK 0x2000
+#define IA_DEBUG_REG1__dma_mask_fifo_empty__SHIFT 0xd
+#define IA_DEBUG_REG1__dma_data_fifo_empty_q_MASK 0x4000
+#define IA_DEBUG_REG1__dma_data_fifo_empty_q__SHIFT 0xe
+#define IA_DEBUG_REG1__dma_data_fifo_full_MASK 0x8000
+#define IA_DEBUG_REG1__dma_data_fifo_full__SHIFT 0xf
+#define IA_DEBUG_REG1__dma_req_fifo_empty_MASK 0x10000
+#define IA_DEBUG_REG1__dma_req_fifo_empty__SHIFT 0x10
+#define IA_DEBUG_REG1__dma_req_fifo_full_MASK 0x20000
+#define IA_DEBUG_REG1__dma_req_fifo_full__SHIFT 0x11
+#define IA_DEBUG_REG1__stage2_dr_MASK 0x40000
+#define IA_DEBUG_REG1__stage2_dr__SHIFT 0x12
+#define IA_DEBUG_REG1__stage2_rtr_MASK 0x80000
+#define IA_DEBUG_REG1__stage2_rtr__SHIFT 0x13
+#define IA_DEBUG_REG1__stage3_dr_MASK 0x100000
+#define IA_DEBUG_REG1__stage3_dr__SHIFT 0x14
+#define IA_DEBUG_REG1__stage3_rtr_MASK 0x200000
+#define IA_DEBUG_REG1__stage3_rtr__SHIFT 0x15
+#define IA_DEBUG_REG1__stage4_dr_MASK 0x400000
+#define IA_DEBUG_REG1__stage4_dr__SHIFT 0x16
+#define IA_DEBUG_REG1__stage4_rtr_MASK 0x800000
+#define IA_DEBUG_REG1__stage4_rtr__SHIFT 0x17
+#define IA_DEBUG_REG1__dma_skid_fifo_empty_MASK 0x1000000
+#define IA_DEBUG_REG1__dma_skid_fifo_empty__SHIFT 0x18
+#define IA_DEBUG_REG1__dma_skid_fifo_full_MASK 0x2000000
+#define IA_DEBUG_REG1__dma_skid_fifo_full__SHIFT 0x19
+#define IA_DEBUG_REG1__dma_grp_valid_MASK 0x4000000
+#define IA_DEBUG_REG1__dma_grp_valid__SHIFT 0x1a
+#define IA_DEBUG_REG1__grp_dma_read_MASK 0x8000000
+#define IA_DEBUG_REG1__grp_dma_read__SHIFT 0x1b
+#define IA_DEBUG_REG1__current_data_valid_MASK 0x10000000
+#define IA_DEBUG_REG1__current_data_valid__SHIFT 0x1c
+#define IA_DEBUG_REG1__out_of_range_r2_q_MASK 0x20000000
+#define IA_DEBUG_REG1__out_of_range_r2_q__SHIFT 0x1d
+#define IA_DEBUG_REG1__dma_mask_fifo_we_MASK 0x40000000
+#define IA_DEBUG_REG1__dma_mask_fifo_we__SHIFT 0x1e
+#define IA_DEBUG_REG1__dma_ret_data_we_q_MASK 0x80000000
+#define IA_DEBUG_REG1__dma_ret_data_we_q__SHIFT 0x1f
+#define IA_DEBUG_REG2__hp_dma_input_fifo_empty_MASK 0x1
+#define IA_DEBUG_REG2__hp_dma_input_fifo_empty__SHIFT 0x0
+#define IA_DEBUG_REG2__hp_dma_input_fifo_full_MASK 0x2
+#define IA_DEBUG_REG2__hp_dma_input_fifo_full__SHIFT 0x1
+#define IA_DEBUG_REG2__hp_start_new_packet_MASK 0x4
+#define IA_DEBUG_REG2__hp_start_new_packet__SHIFT 0x2
+#define IA_DEBUG_REG2__hp_dma_rdreq_dr_q_MASK 0x8
+#define IA_DEBUG_REG2__hp_dma_rdreq_dr_q__SHIFT 0x3
+#define IA_DEBUG_REG2__hp_dma_zero_indices_q_MASK 0x10
+#define IA_DEBUG_REG2__hp_dma_zero_indices_q__SHIFT 0x4
+#define IA_DEBUG_REG2__hp_dma_buf_type_q_MASK 0x60
+#define IA_DEBUG_REG2__hp_dma_buf_type_q__SHIFT 0x5
+#define IA_DEBUG_REG2__hp_dma_req_path_q_MASK 0x80
+#define IA_DEBUG_REG2__hp_dma_req_path_q__SHIFT 0x7
+#define IA_DEBUG_REG2__hp_discard_1st_chunk_MASK 0x100
+#define IA_DEBUG_REG2__hp_discard_1st_chunk__SHIFT 0x8
+#define IA_DEBUG_REG2__hp_discard_2nd_chunk_MASK 0x200
+#define IA_DEBUG_REG2__hp_discard_2nd_chunk__SHIFT 0x9
+#define IA_DEBUG_REG2__hp_second_tc_ret_data_q_MASK 0x400
+#define IA_DEBUG_REG2__hp_second_tc_ret_data_q__SHIFT 0xa
+#define IA_DEBUG_REG2__hp_dma_tc_ret_sel_q_MASK 0x800
+#define IA_DEBUG_REG2__hp_dma_tc_ret_sel_q__SHIFT 0xb
+#define IA_DEBUG_REG2__hp_last_rdreq_in_dma_op_MASK 0x1000
+#define IA_DEBUG_REG2__hp_last_rdreq_in_dma_op__SHIFT 0xc
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_empty_MASK 0x2000
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_empty__SHIFT 0xd
+#define IA_DEBUG_REG2__hp_dma_data_fifo_empty_q_MASK 0x4000
+#define IA_DEBUG_REG2__hp_dma_data_fifo_empty_q__SHIFT 0xe
+#define IA_DEBUG_REG2__hp_dma_data_fifo_full_MASK 0x8000
+#define IA_DEBUG_REG2__hp_dma_data_fifo_full__SHIFT 0xf
+#define IA_DEBUG_REG2__hp_dma_req_fifo_empty_MASK 0x10000
+#define IA_DEBUG_REG2__hp_dma_req_fifo_empty__SHIFT 0x10
+#define IA_DEBUG_REG2__hp_dma_req_fifo_full_MASK 0x20000
+#define IA_DEBUG_REG2__hp_dma_req_fifo_full__SHIFT 0x11
+#define IA_DEBUG_REG2__hp_stage2_dr_MASK 0x40000
+#define IA_DEBUG_REG2__hp_stage2_dr__SHIFT 0x12
+#define IA_DEBUG_REG2__hp_stage2_rtr_MASK 0x80000
+#define IA_DEBUG_REG2__hp_stage2_rtr__SHIFT 0x13
+#define IA_DEBUG_REG2__hp_stage3_dr_MASK 0x100000
+#define IA_DEBUG_REG2__hp_stage3_dr__SHIFT 0x14
+#define IA_DEBUG_REG2__hp_stage3_rtr_MASK 0x200000
+#define IA_DEBUG_REG2__hp_stage3_rtr__SHIFT 0x15
+#define IA_DEBUG_REG2__hp_stage4_dr_MASK 0x400000
+#define IA_DEBUG_REG2__hp_stage4_dr__SHIFT 0x16
+#define IA_DEBUG_REG2__hp_stage4_rtr_MASK 0x800000
+#define IA_DEBUG_REG2__hp_stage4_rtr__SHIFT 0x17
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_empty_MASK 0x1000000
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_empty__SHIFT 0x18
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_full_MASK 0x2000000
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_full__SHIFT 0x19
+#define IA_DEBUG_REG2__hp_dma_grp_valid_MASK 0x4000000
+#define IA_DEBUG_REG2__hp_dma_grp_valid__SHIFT 0x1a
+#define IA_DEBUG_REG2__hp_grp_dma_read_MASK 0x8000000
+#define IA_DEBUG_REG2__hp_grp_dma_read__SHIFT 0x1b
+#define IA_DEBUG_REG2__hp_current_data_valid_MASK 0x10000000
+#define IA_DEBUG_REG2__hp_current_data_valid__SHIFT 0x1c
+#define IA_DEBUG_REG2__hp_out_of_range_r2_q_MASK 0x20000000
+#define IA_DEBUG_REG2__hp_out_of_range_r2_q__SHIFT 0x1d
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_we_MASK 0x40000000
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_we__SHIFT 0x1e
+#define IA_DEBUG_REG2__hp_dma_ret_data_we_q_MASK 0x80000000
+#define IA_DEBUG_REG2__hp_dma_ret_data_we_q__SHIFT 0x1f
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_valid_MASK 0x1
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_valid__SHIFT 0x0
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_read_MASK 0x2
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_read__SHIFT 0x1
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_null_out_MASK 0x4
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_null_out__SHIFT 0x2
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_eop_out_MASK 0x8
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_eop_out__SHIFT 0x3
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_use_tc_out_MASK 0x10
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_use_tc_out__SHIFT 0x4
+#define IA_DEBUG_REG3__grp_dma_draw_is_pipe0_MASK 0x20
+#define IA_DEBUG_REG3__grp_dma_draw_is_pipe0__SHIFT 0x5
+#define IA_DEBUG_REG3__must_service_pipe0_req_MASK 0x40
+#define IA_DEBUG_REG3__must_service_pipe0_req__SHIFT 0x6
+#define IA_DEBUG_REG3__send_pipe1_req_MASK 0x80
+#define IA_DEBUG_REG3__send_pipe1_req__SHIFT 0x7
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_valid_MASK 0x100
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_valid__SHIFT 0x8
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_read_MASK 0x200
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_read__SHIFT 0x9
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_null_out_MASK 0x400
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_null_out__SHIFT 0xa
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_eop_out_MASK 0x800
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_eop_out__SHIFT 0xb
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_use_tc_out_MASK 0x1000
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_use_tc_out__SHIFT 0xc
+#define IA_DEBUG_REG3__ia_mc_rdreq_rtr_q_MASK 0x2000
+#define IA_DEBUG_REG3__ia_mc_rdreq_rtr_q__SHIFT 0xd
+#define IA_DEBUG_REG3__mc_out_rtr_MASK 0x4000
+#define IA_DEBUG_REG3__mc_out_rtr__SHIFT 0xe
+#define IA_DEBUG_REG3__dma_rdreq_send_out_MASK 0x8000
+#define IA_DEBUG_REG3__dma_rdreq_send_out__SHIFT 0xf
+#define IA_DEBUG_REG3__pipe0_dr_MASK 0x10000
+#define IA_DEBUG_REG3__pipe0_dr__SHIFT 0x10
+#define IA_DEBUG_REG3__pipe0_rtr_MASK 0x20000
+#define IA_DEBUG_REG3__pipe0_rtr__SHIFT 0x11
+#define IA_DEBUG_REG3__ia_tc_rdreq_rtr_q_MASK 0x40000
+#define IA_DEBUG_REG3__ia_tc_rdreq_rtr_q__SHIFT 0x12
+#define IA_DEBUG_REG3__tc_out_rtr_MASK 0x80000
+#define IA_DEBUG_REG3__tc_out_rtr__SHIFT 0x13
+#define IA_DEBUG_REG3__pair0_valid_p1_MASK 0x100000
+#define IA_DEBUG_REG3__pair0_valid_p1__SHIFT 0x14
+#define IA_DEBUG_REG3__pair1_valid_p1_MASK 0x200000
+#define IA_DEBUG_REG3__pair1_valid_p1__SHIFT 0x15
+#define IA_DEBUG_REG3__pair2_valid_p1_MASK 0x400000
+#define IA_DEBUG_REG3__pair2_valid_p1__SHIFT 0x16
+#define IA_DEBUG_REG3__pair3_valid_p1_MASK 0x800000
+#define IA_DEBUG_REG3__pair3_valid_p1__SHIFT 0x17
+#define IA_DEBUG_REG3__tc_req_count_q_MASK 0x3000000
+#define IA_DEBUG_REG3__tc_req_count_q__SHIFT 0x18
+#define IA_DEBUG_REG3__discard_1st_chunk_MASK 0x4000000
+#define IA_DEBUG_REG3__discard_1st_chunk__SHIFT 0x1a
+#define IA_DEBUG_REG3__discard_2nd_chunk_MASK 0x8000000
+#define IA_DEBUG_REG3__discard_2nd_chunk__SHIFT 0x1b
+#define IA_DEBUG_REG3__last_tc_req_p1_MASK 0x10000000
+#define IA_DEBUG_REG3__last_tc_req_p1__SHIFT 0x1c
+#define IA_DEBUG_REG3__IA_TC_rdreq_send_out_MASK 0x20000000
+#define IA_DEBUG_REG3__IA_TC_rdreq_send_out__SHIFT 0x1d
+#define IA_DEBUG_REG3__TC_IA_rdret_valid_in_MASK 0x40000000
+#define IA_DEBUG_REG3__TC_IA_rdret_valid_in__SHIFT 0x1e
+#define IA_DEBUG_REG3__TAP_IA_rdret_vld_in_MASK 0x80000000
+#define IA_DEBUG_REG3__TAP_IA_rdret_vld_in__SHIFT 0x1f
+#define IA_DEBUG_REG4__pipe0_dr_MASK 0x1
+#define IA_DEBUG_REG4__pipe0_dr__SHIFT 0x0
+#define IA_DEBUG_REG4__pipe1_dr_MASK 0x2
+#define IA_DEBUG_REG4__pipe1_dr__SHIFT 0x1
+#define IA_DEBUG_REG4__pipe2_dr_MASK 0x4
+#define IA_DEBUG_REG4__pipe2_dr__SHIFT 0x2
+#define IA_DEBUG_REG4__pipe3_dr_MASK 0x8
+#define IA_DEBUG_REG4__pipe3_dr__SHIFT 0x3
+#define IA_DEBUG_REG4__pipe4_dr_MASK 0x10
+#define IA_DEBUG_REG4__pipe4_dr__SHIFT 0x4
+#define IA_DEBUG_REG4__pipe5_dr_MASK 0x20
+#define IA_DEBUG_REG4__pipe5_dr__SHIFT 0x5
+#define IA_DEBUG_REG4__grp_se0_fifo_empty_MASK 0x40
+#define IA_DEBUG_REG4__grp_se0_fifo_empty__SHIFT 0x6
+#define IA_DEBUG_REG4__grp_se0_fifo_full_MASK 0x80
+#define IA_DEBUG_REG4__grp_se0_fifo_full__SHIFT 0x7
+#define IA_DEBUG_REG4__pipe0_rtr_MASK 0x100
+#define IA_DEBUG_REG4__pipe0_rtr__SHIFT 0x8
+#define IA_DEBUG_REG4__pipe1_rtr_MASK 0x200
+#define IA_DEBUG_REG4__pipe1_rtr__SHIFT 0x9
+#define IA_DEBUG_REG4__pipe2_rtr_MASK 0x400
+#define IA_DEBUG_REG4__pipe2_rtr__SHIFT 0xa
+#define IA_DEBUG_REG4__pipe3_rtr_MASK 0x800
+#define IA_DEBUG_REG4__pipe3_rtr__SHIFT 0xb
+#define IA_DEBUG_REG4__pipe4_rtr_MASK 0x1000
+#define IA_DEBUG_REG4__pipe4_rtr__SHIFT 0xc
+#define IA_DEBUG_REG4__pipe5_rtr_MASK 0x2000
+#define IA_DEBUG_REG4__pipe5_rtr__SHIFT 0xd
+#define IA_DEBUG_REG4__ia_vgt_prim_rtr_q_MASK 0x4000
+#define IA_DEBUG_REG4__ia_vgt_prim_rtr_q__SHIFT 0xe
+#define IA_DEBUG_REG4__ia_se1vgt_prim_rtr_q_MASK 0x8000
+#define IA_DEBUG_REG4__ia_se1vgt_prim_rtr_q__SHIFT 0xf
+#define IA_DEBUG_REG4__di_major_mode_p1_q_MASK 0x10000
+#define IA_DEBUG_REG4__di_major_mode_p1_q__SHIFT 0x10
+#define IA_DEBUG_REG4__gs_mode_p1_q_MASK 0xe0000
+#define IA_DEBUG_REG4__gs_mode_p1_q__SHIFT 0x11
+#define IA_DEBUG_REG4__di_event_flag_p1_q_MASK 0x100000
+#define IA_DEBUG_REG4__di_event_flag_p1_q__SHIFT 0x14
+#define IA_DEBUG_REG4__di_state_sel_p1_q_MASK 0xe00000
+#define IA_DEBUG_REG4__di_state_sel_p1_q__SHIFT 0x15
+#define IA_DEBUG_REG4__draw_opaq_en_p1_q_MASK 0x1000000
+#define IA_DEBUG_REG4__draw_opaq_en_p1_q__SHIFT 0x18
+#define IA_DEBUG_REG4__draw_opaq_active_q_MASK 0x2000000
+#define IA_DEBUG_REG4__draw_opaq_active_q__SHIFT 0x19
+#define IA_DEBUG_REG4__di_source_select_p1_q_MASK 0xc000000
+#define IA_DEBUG_REG4__di_source_select_p1_q__SHIFT 0x1a
+#define IA_DEBUG_REG4__ready_to_read_di_MASK 0x10000000
+#define IA_DEBUG_REG4__ready_to_read_di__SHIFT 0x1c
+#define IA_DEBUG_REG4__di_first_group_of_draw_q_MASK 0x20000000
+#define IA_DEBUG_REG4__di_first_group_of_draw_q__SHIFT 0x1d
+#define IA_DEBUG_REG4__last_shift_of_draw_MASK 0x40000000
+#define IA_DEBUG_REG4__last_shift_of_draw__SHIFT 0x1e
+#define IA_DEBUG_REG4__current_shift_is_vect1_q_MASK 0x80000000
+#define IA_DEBUG_REG4__current_shift_is_vect1_q__SHIFT 0x1f
+#define IA_DEBUG_REG5__di_index_counter_q_15_0_MASK 0xffff
+#define IA_DEBUG_REG5__di_index_counter_q_15_0__SHIFT 0x0
+#define IA_DEBUG_REG5__instanceid_13_0_MASK 0x3fff0000
+#define IA_DEBUG_REG5__instanceid_13_0__SHIFT 0x10
+#define IA_DEBUG_REG5__draw_input_fifo_full_MASK 0x40000000
+#define IA_DEBUG_REG5__draw_input_fifo_full__SHIFT 0x1e
+#define IA_DEBUG_REG5__draw_input_fifo_empty_MASK 0x80000000
+#define IA_DEBUG_REG5__draw_input_fifo_empty__SHIFT 0x1f
+#define IA_DEBUG_REG6__current_shift_q_MASK 0xf
+#define IA_DEBUG_REG6__current_shift_q__SHIFT 0x0
+#define IA_DEBUG_REG6__current_stride_pre_MASK 0xf0
+#define IA_DEBUG_REG6__current_stride_pre__SHIFT 0x4
+#define IA_DEBUG_REG6__current_stride_q_MASK 0x1f00
+#define IA_DEBUG_REG6__current_stride_q__SHIFT 0x8
+#define IA_DEBUG_REG6__first_group_partial_MASK 0x2000
+#define IA_DEBUG_REG6__first_group_partial__SHIFT 0xd
+#define IA_DEBUG_REG6__second_group_partial_MASK 0x4000
+#define IA_DEBUG_REG6__second_group_partial__SHIFT 0xe
+#define IA_DEBUG_REG6__curr_prim_partial_MASK 0x8000
+#define IA_DEBUG_REG6__curr_prim_partial__SHIFT 0xf
+#define IA_DEBUG_REG6__next_stride_q_MASK 0x1f0000
+#define IA_DEBUG_REG6__next_stride_q__SHIFT 0x10
+#define IA_DEBUG_REG6__next_group_partial_MASK 0x200000
+#define IA_DEBUG_REG6__next_group_partial__SHIFT 0x15
+#define IA_DEBUG_REG6__after_group_partial_MASK 0x400000
+#define IA_DEBUG_REG6__after_group_partial__SHIFT 0x16
+#define IA_DEBUG_REG6__extract_group_MASK 0x800000
+#define IA_DEBUG_REG6__extract_group__SHIFT 0x17
+#define IA_DEBUG_REG6__grp_shift_debug_data_MASK 0xff000000
+#define IA_DEBUG_REG6__grp_shift_debug_data__SHIFT 0x18
+#define IA_DEBUG_REG7__reset_indx_state_q_MASK 0xf
+#define IA_DEBUG_REG7__reset_indx_state_q__SHIFT 0x0
+#define IA_DEBUG_REG7__shift_vect_valid_p2_q_MASK 0xf0
+#define IA_DEBUG_REG7__shift_vect_valid_p2_q__SHIFT 0x4
+#define IA_DEBUG_REG7__shift_vect1_valid_p2_q_MASK 0xf00
+#define IA_DEBUG_REG7__shift_vect1_valid_p2_q__SHIFT 0x8
+#define IA_DEBUG_REG7__shift_vect0_reset_match_p2_q_MASK 0xf000
+#define IA_DEBUG_REG7__shift_vect0_reset_match_p2_q__SHIFT 0xc
+#define IA_DEBUG_REG7__shift_vect1_reset_match_p2_q_MASK 0xf0000
+#define IA_DEBUG_REG7__shift_vect1_reset_match_p2_q__SHIFT 0x10
+#define IA_DEBUG_REG7__num_indx_in_group_p2_q_MASK 0x700000
+#define IA_DEBUG_REG7__num_indx_in_group_p2_q__SHIFT 0x14
+#define IA_DEBUG_REG7__last_group_of_draw_p2_q_MASK 0x800000
+#define IA_DEBUG_REG7__last_group_of_draw_p2_q__SHIFT 0x17
+#define IA_DEBUG_REG7__shift_event_flag_p2_q_MASK 0x1000000
+#define IA_DEBUG_REG7__shift_event_flag_p2_q__SHIFT 0x18
+#define IA_DEBUG_REG7__indx_shift_is_one_p2_q_MASK 0x2000000
+#define IA_DEBUG_REG7__indx_shift_is_one_p2_q__SHIFT 0x19
+#define IA_DEBUG_REG7__indx_shift_is_two_p2_q_MASK 0x4000000
+#define IA_DEBUG_REG7__indx_shift_is_two_p2_q__SHIFT 0x1a
+#define IA_DEBUG_REG7__indx_stride_is_four_p2_q_MASK 0x8000000
+#define IA_DEBUG_REG7__indx_stride_is_four_p2_q__SHIFT 0x1b
+#define IA_DEBUG_REG7__shift_prim1_reset_p3_q_MASK 0x10000000
+#define IA_DEBUG_REG7__shift_prim1_reset_p3_q__SHIFT 0x1c
+#define IA_DEBUG_REG7__shift_prim1_partial_p3_q_MASK 0x20000000
+#define IA_DEBUG_REG7__shift_prim1_partial_p3_q__SHIFT 0x1d
+#define IA_DEBUG_REG7__shift_prim0_reset_p3_q_MASK 0x40000000
+#define IA_DEBUG_REG7__shift_prim0_reset_p3_q__SHIFT 0x1e
+#define IA_DEBUG_REG7__shift_prim0_partial_p3_q_MASK 0x80000000
+#define IA_DEBUG_REG7__shift_prim0_partial_p3_q__SHIFT 0x1f
+#define IA_DEBUG_REG8__di_prim_type_p1_q_MASK 0x1f
+#define IA_DEBUG_REG8__di_prim_type_p1_q__SHIFT 0x0
+#define IA_DEBUG_REG8__two_cycle_xfer_p1_q_MASK 0x20
+#define IA_DEBUG_REG8__two_cycle_xfer_p1_q__SHIFT 0x5
+#define IA_DEBUG_REG8__two_prim_input_p1_q_MASK 0x40
+#define IA_DEBUG_REG8__two_prim_input_p1_q__SHIFT 0x6
+#define IA_DEBUG_REG8__shift_vect_end_of_packet_p5_q_MASK 0x80
+#define IA_DEBUG_REG8__shift_vect_end_of_packet_p5_q__SHIFT 0x7
+#define IA_DEBUG_REG8__last_group_of_inst_p5_q_MASK 0x100
+#define IA_DEBUG_REG8__last_group_of_inst_p5_q__SHIFT 0x8
+#define IA_DEBUG_REG8__shift_prim1_null_flag_p5_q_MASK 0x200
+#define IA_DEBUG_REG8__shift_prim1_null_flag_p5_q__SHIFT 0x9
+#define IA_DEBUG_REG8__shift_prim0_null_flag_p5_q_MASK 0x400
+#define IA_DEBUG_REG8__shift_prim0_null_flag_p5_q__SHIFT 0xa
+#define IA_DEBUG_REG8__grp_continued_MASK 0x800
+#define IA_DEBUG_REG8__grp_continued__SHIFT 0xb
+#define IA_DEBUG_REG8__grp_state_sel_MASK 0x7000
+#define IA_DEBUG_REG8__grp_state_sel__SHIFT 0xc
+#define IA_DEBUG_REG8__grp_sub_prim_type_MASK 0x1f8000
+#define IA_DEBUG_REG8__grp_sub_prim_type__SHIFT 0xf
+#define IA_DEBUG_REG8__grp_output_path_MASK 0xe00000
+#define IA_DEBUG_REG8__grp_output_path__SHIFT 0x15
+#define IA_DEBUG_REG8__grp_null_primitive_MASK 0x1000000
+#define IA_DEBUG_REG8__grp_null_primitive__SHIFT 0x18
+#define IA_DEBUG_REG8__grp_eop_MASK 0x2000000
+#define IA_DEBUG_REG8__grp_eop__SHIFT 0x19
+#define IA_DEBUG_REG8__grp_eopg_MASK 0x4000000
+#define IA_DEBUG_REG8__grp_eopg__SHIFT 0x1a
+#define IA_DEBUG_REG8__grp_event_flag_MASK 0x8000000
+#define IA_DEBUG_REG8__grp_event_flag__SHIFT 0x1b
+#define IA_DEBUG_REG8__grp_components_valid_MASK 0xf0000000
+#define IA_DEBUG_REG8__grp_components_valid__SHIFT 0x1c
+#define IA_DEBUG_REG9__send_to_se1_p6_MASK 0x1
+#define IA_DEBUG_REG9__send_to_se1_p6__SHIFT 0x0
+#define IA_DEBUG_REG9__gfx_se_switch_p6_MASK 0x2
+#define IA_DEBUG_REG9__gfx_se_switch_p6__SHIFT 0x1
+#define IA_DEBUG_REG9__null_eoi_xfer_prim1_p6_MASK 0x4
+#define IA_DEBUG_REG9__null_eoi_xfer_prim1_p6__SHIFT 0x2
+#define IA_DEBUG_REG9__null_eoi_xfer_prim0_p6_MASK 0x8
+#define IA_DEBUG_REG9__null_eoi_xfer_prim0_p6__SHIFT 0x3
+#define IA_DEBUG_REG9__prim1_eoi_p6_MASK 0x10
+#define IA_DEBUG_REG9__prim1_eoi_p6__SHIFT 0x4
+#define IA_DEBUG_REG9__prim0_eoi_p6_MASK 0x20
+#define IA_DEBUG_REG9__prim0_eoi_p6__SHIFT 0x5
+#define IA_DEBUG_REG9__prim1_valid_eopg_p6_MASK 0x40
+#define IA_DEBUG_REG9__prim1_valid_eopg_p6__SHIFT 0x6
+#define IA_DEBUG_REG9__prim0_valid_eopg_p6_MASK 0x80
+#define IA_DEBUG_REG9__prim0_valid_eopg_p6__SHIFT 0x7
+#define IA_DEBUG_REG9__prim1_to_other_se_p6_MASK 0x100
+#define IA_DEBUG_REG9__prim1_to_other_se_p6__SHIFT 0x8
+#define IA_DEBUG_REG9__eopg_on_last_prim_p6_MASK 0x200
+#define IA_DEBUG_REG9__eopg_on_last_prim_p6__SHIFT 0x9
+#define IA_DEBUG_REG9__eopg_between_prims_p6_MASK 0x400
+#define IA_DEBUG_REG9__eopg_between_prims_p6__SHIFT 0xa
+#define IA_DEBUG_REG9__prim_count_eq_group_size_p6_MASK 0x800
+#define IA_DEBUG_REG9__prim_count_eq_group_size_p6__SHIFT 0xb
+#define IA_DEBUG_REG9__prim_count_gt_group_size_p6_MASK 0x1000
+#define IA_DEBUG_REG9__prim_count_gt_group_size_p6__SHIFT 0xc
+#define IA_DEBUG_REG9__two_prim_output_p5_q_MASK 0x2000
+#define IA_DEBUG_REG9__two_prim_output_p5_q__SHIFT 0xd
+#define IA_DEBUG_REG9__SPARE0_MASK 0x4000
+#define IA_DEBUG_REG9__SPARE0__SHIFT 0xe
+#define IA_DEBUG_REG9__SPARE1_MASK 0x8000
+#define IA_DEBUG_REG9__SPARE1__SHIFT 0xf
+#define IA_DEBUG_REG9__shift_vect_end_of_packet_p5_q_MASK 0x10000
+#define IA_DEBUG_REG9__shift_vect_end_of_packet_p5_q__SHIFT 0x10
+#define IA_DEBUG_REG9__prim1_xfer_p6_MASK 0x20000
+#define IA_DEBUG_REG9__prim1_xfer_p6__SHIFT 0x11
+#define IA_DEBUG_REG9__grp_se1_fifo_empty_MASK 0x40000
+#define IA_DEBUG_REG9__grp_se1_fifo_empty__SHIFT 0x12
+#define IA_DEBUG_REG9__grp_se1_fifo_full_MASK 0x80000
+#define IA_DEBUG_REG9__grp_se1_fifo_full__SHIFT 0x13
+#define IA_DEBUG_REG9__prim_counter_q_MASK 0xfff00000
+#define IA_DEBUG_REG9__prim_counter_q__SHIFT 0x14
+#define VGT_DEBUG_REG0__vgt_busy_extended_MASK 0x1
+#define VGT_DEBUG_REG0__vgt_busy_extended__SHIFT 0x0
+#define VGT_DEBUG_REG0__SPARE9_MASK 0x2
+#define VGT_DEBUG_REG0__SPARE9__SHIFT 0x1
+#define VGT_DEBUG_REG0__vgt_busy_MASK 0x4
+#define VGT_DEBUG_REG0__vgt_busy__SHIFT 0x2
+#define VGT_DEBUG_REG0__SPARE8_MASK 0x8
+#define VGT_DEBUG_REG0__SPARE8__SHIFT 0x3
+#define VGT_DEBUG_REG0__SPARE7_MASK 0x10
+#define VGT_DEBUG_REG0__SPARE7__SHIFT 0x4
+#define VGT_DEBUG_REG0__SPARE6_MASK 0x20
+#define VGT_DEBUG_REG0__SPARE6__SHIFT 0x5
+#define VGT_DEBUG_REG0__SPARE5_MASK 0x40
+#define VGT_DEBUG_REG0__SPARE5__SHIFT 0x6
+#define VGT_DEBUG_REG0__SPARE4_MASK 0x80
+#define VGT_DEBUG_REG0__SPARE4__SHIFT 0x7
+#define VGT_DEBUG_REG0__pi_busy_MASK 0x100
+#define VGT_DEBUG_REG0__pi_busy__SHIFT 0x8
+#define VGT_DEBUG_REG0__vr_pi_busy_MASK 0x200
+#define VGT_DEBUG_REG0__vr_pi_busy__SHIFT 0x9
+#define VGT_DEBUG_REG0__pt_pi_busy_MASK 0x400
+#define VGT_DEBUG_REG0__pt_pi_busy__SHIFT 0xa
+#define VGT_DEBUG_REG0__te_pi_busy_MASK 0x800
+#define VGT_DEBUG_REG0__te_pi_busy__SHIFT 0xb
+#define VGT_DEBUG_REG0__gs_busy_MASK 0x1000
+#define VGT_DEBUG_REG0__gs_busy__SHIFT 0xc
+#define VGT_DEBUG_REG0__rcm_busy_MASK 0x2000
+#define VGT_DEBUG_REG0__rcm_busy__SHIFT 0xd
+#define VGT_DEBUG_REG0__tm_busy_MASK 0x4000
+#define VGT_DEBUG_REG0__tm_busy__SHIFT 0xe
+#define VGT_DEBUG_REG0__cm_busy_MASK 0x8000
+#define VGT_DEBUG_REG0__cm_busy__SHIFT 0xf
+#define VGT_DEBUG_REG0__gog_busy_MASK 0x10000
+#define VGT_DEBUG_REG0__gog_busy__SHIFT 0x10
+#define VGT_DEBUG_REG0__frmt_busy_MASK 0x20000
+#define VGT_DEBUG_REG0__frmt_busy__SHIFT 0x11
+#define VGT_DEBUG_REG0__SPARE10_MASK 0x40000
+#define VGT_DEBUG_REG0__SPARE10__SHIFT 0x12
+#define VGT_DEBUG_REG0__te11_pi_busy_MASK 0x80000
+#define VGT_DEBUG_REG0__te11_pi_busy__SHIFT 0x13
+#define VGT_DEBUG_REG0__SPARE3_MASK 0x100000
+#define VGT_DEBUG_REG0__SPARE3__SHIFT 0x14
+#define VGT_DEBUG_REG0__combined_out_busy_MASK 0x200000
+#define VGT_DEBUG_REG0__combined_out_busy__SHIFT 0x15
+#define VGT_DEBUG_REG0__spi_vs_interfaces_busy_MASK 0x400000
+#define VGT_DEBUG_REG0__spi_vs_interfaces_busy__SHIFT 0x16
+#define VGT_DEBUG_REG0__pa_interfaces_busy_MASK 0x800000
+#define VGT_DEBUG_REG0__pa_interfaces_busy__SHIFT 0x17
+#define VGT_DEBUG_REG0__reg_clk_busy_MASK 0x1000000
+#define VGT_DEBUG_REG0__reg_clk_busy__SHIFT 0x18
+#define VGT_DEBUG_REG0__SPARE2_MASK 0x2000000
+#define VGT_DEBUG_REG0__SPARE2__SHIFT 0x19
+#define VGT_DEBUG_REG0__core_clk_busy_MASK 0x4000000
+#define VGT_DEBUG_REG0__core_clk_busy__SHIFT 0x1a
+#define VGT_DEBUG_REG0__gs_clk_busy_MASK 0x8000000
+#define VGT_DEBUG_REG0__gs_clk_busy__SHIFT 0x1b
+#define VGT_DEBUG_REG0__SPARE1_MASK 0x10000000
+#define VGT_DEBUG_REG0__SPARE1__SHIFT 0x1c
+#define VGT_DEBUG_REG0__sclk_core_vld_MASK 0x20000000
+#define VGT_DEBUG_REG0__sclk_core_vld__SHIFT 0x1d
+#define VGT_DEBUG_REG0__sclk_gs_vld_MASK 0x40000000
+#define VGT_DEBUG_REG0__sclk_gs_vld__SHIFT 0x1e
+#define VGT_DEBUG_REG0__SPARE0_MASK 0x80000000
+#define VGT_DEBUG_REG0__SPARE0__SHIFT 0x1f
+#define VGT_DEBUG_REG1__SPARE9_MASK 0x1
+#define VGT_DEBUG_REG1__SPARE9__SHIFT 0x0
+#define VGT_DEBUG_REG1__SPARE8_MASK 0x2
+#define VGT_DEBUG_REG1__SPARE8__SHIFT 0x1
+#define VGT_DEBUG_REG1__SPARE7_MASK 0x4
+#define VGT_DEBUG_REG1__SPARE7__SHIFT 0x2
+#define VGT_DEBUG_REG1__SPARE6_MASK 0x8
+#define VGT_DEBUG_REG1__SPARE6__SHIFT 0x3
+#define VGT_DEBUG_REG1__SPARE5_MASK 0x10
+#define VGT_DEBUG_REG1__SPARE5__SHIFT 0x4
+#define VGT_DEBUG_REG1__SPARE4_MASK 0x20
+#define VGT_DEBUG_REG1__SPARE4__SHIFT 0x5
+#define VGT_DEBUG_REG1__SPARE3_MASK 0x40
+#define VGT_DEBUG_REG1__SPARE3__SHIFT 0x6
+#define VGT_DEBUG_REG1__SPARE2_MASK 0x80
+#define VGT_DEBUG_REG1__SPARE2__SHIFT 0x7
+#define VGT_DEBUG_REG1__SPARE1_MASK 0x100
+#define VGT_DEBUG_REG1__SPARE1__SHIFT 0x8
+#define VGT_DEBUG_REG1__SPARE0_MASK 0x200
+#define VGT_DEBUG_REG1__SPARE0__SHIFT 0x9
+#define VGT_DEBUG_REG1__pi_vr_valid_MASK 0x400
+#define VGT_DEBUG_REG1__pi_vr_valid__SHIFT 0xa
+#define VGT_DEBUG_REG1__vr_pi_read_MASK 0x800
+#define VGT_DEBUG_REG1__vr_pi_read__SHIFT 0xb
+#define VGT_DEBUG_REG1__pi_pt_valid_MASK 0x1000
+#define VGT_DEBUG_REG1__pi_pt_valid__SHIFT 0xc
+#define VGT_DEBUG_REG1__pt_pi_read_MASK 0x2000
+#define VGT_DEBUG_REG1__pt_pi_read__SHIFT 0xd
+#define VGT_DEBUG_REG1__pi_te_valid_MASK 0x4000
+#define VGT_DEBUG_REG1__pi_te_valid__SHIFT 0xe
+#define VGT_DEBUG_REG1__te_grp_read_MASK 0x8000
+#define VGT_DEBUG_REG1__te_grp_read__SHIFT 0xf
+#define VGT_DEBUG_REG1__vr_out_indx_valid_MASK 0x10000
+#define VGT_DEBUG_REG1__vr_out_indx_valid__SHIFT 0x10
+#define VGT_DEBUG_REG1__SPARE12_MASK 0x20000
+#define VGT_DEBUG_REG1__SPARE12__SHIFT 0x11
+#define VGT_DEBUG_REG1__vr_out_prim_valid_MASK 0x40000
+#define VGT_DEBUG_REG1__vr_out_prim_valid__SHIFT 0x12
+#define VGT_DEBUG_REG1__SPARE11_MASK 0x80000
+#define VGT_DEBUG_REG1__SPARE11__SHIFT 0x13
+#define VGT_DEBUG_REG1__pt_out_indx_valid_MASK 0x100000
+#define VGT_DEBUG_REG1__pt_out_indx_valid__SHIFT 0x14
+#define VGT_DEBUG_REG1__SPARE10_MASK 0x200000
+#define VGT_DEBUG_REG1__SPARE10__SHIFT 0x15
+#define VGT_DEBUG_REG1__pt_out_prim_valid_MASK 0x400000
+#define VGT_DEBUG_REG1__pt_out_prim_valid__SHIFT 0x16
+#define VGT_DEBUG_REG1__SPARE23_MASK 0x800000
+#define VGT_DEBUG_REG1__SPARE23__SHIFT 0x17
+#define VGT_DEBUG_REG1__te_out_data_valid_MASK 0x1000000
+#define VGT_DEBUG_REG1__te_out_data_valid__SHIFT 0x18
+#define VGT_DEBUG_REG1__SPARE25_MASK 0x2000000
+#define VGT_DEBUG_REG1__SPARE25__SHIFT 0x19
+#define VGT_DEBUG_REG1__pi_gs_valid_MASK 0x4000000
+#define VGT_DEBUG_REG1__pi_gs_valid__SHIFT 0x1a
+#define VGT_DEBUG_REG1__gs_pi_read_MASK 0x8000000
+#define VGT_DEBUG_REG1__gs_pi_read__SHIFT 0x1b
+#define VGT_DEBUG_REG1__gog_out_indx_valid_MASK 0x10000000
+#define VGT_DEBUG_REG1__gog_out_indx_valid__SHIFT 0x1c
+#define VGT_DEBUG_REG1__out_indx_read_MASK 0x20000000
+#define VGT_DEBUG_REG1__out_indx_read__SHIFT 0x1d
+#define VGT_DEBUG_REG1__gog_out_prim_valid_MASK 0x40000000
+#define VGT_DEBUG_REG1__gog_out_prim_valid__SHIFT 0x1e
+#define VGT_DEBUG_REG1__out_prim_read_MASK 0x80000000
+#define VGT_DEBUG_REG1__out_prim_read__SHIFT 0x1f
+#define VGT_DEBUG_REG2__hs_grp_busy_MASK 0x1
+#define VGT_DEBUG_REG2__hs_grp_busy__SHIFT 0x0
+#define VGT_DEBUG_REG2__hs_noif_busy_MASK 0x2
+#define VGT_DEBUG_REG2__hs_noif_busy__SHIFT 0x1
+#define VGT_DEBUG_REG2__tfmmIsBusy_MASK 0x4
+#define VGT_DEBUG_REG2__tfmmIsBusy__SHIFT 0x2
+#define VGT_DEBUG_REG2__lsVertIfBusy_0_MASK 0x8
+#define VGT_DEBUG_REG2__lsVertIfBusy_0__SHIFT 0x3
+#define VGT_DEBUG_REG2__te11_hs_tess_input_rtr_MASK 0x10
+#define VGT_DEBUG_REG2__te11_hs_tess_input_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG2__lsWaveIfBusy_0_MASK 0x20
+#define VGT_DEBUG_REG2__lsWaveIfBusy_0__SHIFT 0x5
+#define VGT_DEBUG_REG2__hs_te11_tess_input_rts_MASK 0x40
+#define VGT_DEBUG_REG2__hs_te11_tess_input_rts__SHIFT 0x6
+#define VGT_DEBUG_REG2__grpModBusy_MASK 0x80
+#define VGT_DEBUG_REG2__grpModBusy__SHIFT 0x7
+#define VGT_DEBUG_REG2__lsVertFifoEmpty_MASK 0x100
+#define VGT_DEBUG_REG2__lsVertFifoEmpty__SHIFT 0x8
+#define VGT_DEBUG_REG2__lsWaveFifoEmpty_MASK 0x200
+#define VGT_DEBUG_REG2__lsWaveFifoEmpty__SHIFT 0x9
+#define VGT_DEBUG_REG2__hsVertFifoEmpty_MASK 0x400
+#define VGT_DEBUG_REG2__hsVertFifoEmpty__SHIFT 0xa
+#define VGT_DEBUG_REG2__hsWaveFifoEmpty_MASK 0x800
+#define VGT_DEBUG_REG2__hsWaveFifoEmpty__SHIFT 0xb
+#define VGT_DEBUG_REG2__hsInputFifoEmpty_MASK 0x1000
+#define VGT_DEBUG_REG2__hsInputFifoEmpty__SHIFT 0xc
+#define VGT_DEBUG_REG2__hsTifFifoEmpty_MASK 0x2000
+#define VGT_DEBUG_REG2__hsTifFifoEmpty__SHIFT 0xd
+#define VGT_DEBUG_REG2__lsVertFifoFull_MASK 0x4000
+#define VGT_DEBUG_REG2__lsVertFifoFull__SHIFT 0xe
+#define VGT_DEBUG_REG2__lsWaveFifoFull_MASK 0x8000
+#define VGT_DEBUG_REG2__lsWaveFifoFull__SHIFT 0xf
+#define VGT_DEBUG_REG2__hsVertFifoFull_MASK 0x10000
+#define VGT_DEBUG_REG2__hsVertFifoFull__SHIFT 0x10
+#define VGT_DEBUG_REG2__hsWaveFifoFull_MASK 0x20000
+#define VGT_DEBUG_REG2__hsWaveFifoFull__SHIFT 0x11
+#define VGT_DEBUG_REG2__hsInputFifoFull_MASK 0x40000
+#define VGT_DEBUG_REG2__hsInputFifoFull__SHIFT 0x12
+#define VGT_DEBUG_REG2__hsTifFifoFull_MASK 0x80000
+#define VGT_DEBUG_REG2__hsTifFifoFull__SHIFT 0x13
+#define VGT_DEBUG_REG2__p0_rtr_MASK 0x100000
+#define VGT_DEBUG_REG2__p0_rtr__SHIFT 0x14
+#define VGT_DEBUG_REG2__p1_rtr_MASK 0x200000
+#define VGT_DEBUG_REG2__p1_rtr__SHIFT 0x15
+#define VGT_DEBUG_REG2__p0_dr_MASK 0x400000
+#define VGT_DEBUG_REG2__p0_dr__SHIFT 0x16
+#define VGT_DEBUG_REG2__p1_dr_MASK 0x800000
+#define VGT_DEBUG_REG2__p1_dr__SHIFT 0x17
+#define VGT_DEBUG_REG2__p0_rts_MASK 0x1000000
+#define VGT_DEBUG_REG2__p0_rts__SHIFT 0x18
+#define VGT_DEBUG_REG2__p1_rts_MASK 0x2000000
+#define VGT_DEBUG_REG2__p1_rts__SHIFT 0x19
+#define VGT_DEBUG_REG2__ls_sh_id_MASK 0x4000000
+#define VGT_DEBUG_REG2__ls_sh_id__SHIFT 0x1a
+#define VGT_DEBUG_REG2__lsFwaveFlag_MASK 0x8000000
+#define VGT_DEBUG_REG2__lsFwaveFlag__SHIFT 0x1b
+#define VGT_DEBUG_REG2__lsWaveSendFlush_MASK 0x10000000
+#define VGT_DEBUG_REG2__lsWaveSendFlush__SHIFT 0x1c
+#define VGT_DEBUG_REG2__SPARE_MASK 0xe0000000
+#define VGT_DEBUG_REG2__SPARE__SHIFT 0x1d
+#define VGT_DEBUG_REG3__lsTgRelInd_MASK 0xfff
+#define VGT_DEBUG_REG3__lsTgRelInd__SHIFT 0x0
+#define VGT_DEBUG_REG3__lsWaveRelInd_MASK 0x3f000
+#define VGT_DEBUG_REG3__lsWaveRelInd__SHIFT 0xc
+#define VGT_DEBUG_REG3__lsPatchCnt_MASK 0x3fc0000
+#define VGT_DEBUG_REG3__lsPatchCnt__SHIFT 0x12
+#define VGT_DEBUG_REG3__hsWaveRelInd_MASK 0xfc000000
+#define VGT_DEBUG_REG3__hsWaveRelInd__SHIFT 0x1a
+#define VGT_DEBUG_REG4__hsPatchCnt_MASK 0xff
+#define VGT_DEBUG_REG4__hsPatchCnt__SHIFT 0x0
+#define VGT_DEBUG_REG4__hsPrimId_15_0_MASK 0xffff00
+#define VGT_DEBUG_REG4__hsPrimId_15_0__SHIFT 0x8
+#define VGT_DEBUG_REG4__hsCpCnt_MASK 0x1f000000
+#define VGT_DEBUG_REG4__hsCpCnt__SHIFT 0x18
+#define VGT_DEBUG_REG4__hsWaveSendFlush_MASK 0x20000000
+#define VGT_DEBUG_REG4__hsWaveSendFlush__SHIFT 0x1d
+#define VGT_DEBUG_REG4__hsFwaveFlag_MASK 0x40000000
+#define VGT_DEBUG_REG4__hsFwaveFlag__SHIFT 0x1e
+#define VGT_DEBUG_REG4__SPARE_MASK 0x80000000
+#define VGT_DEBUG_REG4__SPARE__SHIFT 0x1f
+#define VGT_DEBUG_REG5__SPARE4_MASK 0x7
+#define VGT_DEBUG_REG5__SPARE4__SHIFT 0x0
+#define VGT_DEBUG_REG5__hsWaveCreditCnt_0_MASK 0xf8
+#define VGT_DEBUG_REG5__hsWaveCreditCnt_0__SHIFT 0x3
+#define VGT_DEBUG_REG5__SPARE3_MASK 0x700
+#define VGT_DEBUG_REG5__SPARE3__SHIFT 0x8
+#define VGT_DEBUG_REG5__hsVertCreditCnt_0_MASK 0xf800
+#define VGT_DEBUG_REG5__hsVertCreditCnt_0__SHIFT 0xb
+#define VGT_DEBUG_REG5__SPARE2_MASK 0x70000
+#define VGT_DEBUG_REG5__SPARE2__SHIFT 0x10
+#define VGT_DEBUG_REG5__lsWaveCreditCnt_0_MASK 0xf80000
+#define VGT_DEBUG_REG5__lsWaveCreditCnt_0__SHIFT 0x13
+#define VGT_DEBUG_REG5__SPARE1_MASK 0x7000000
+#define VGT_DEBUG_REG5__SPARE1__SHIFT 0x18
+#define VGT_DEBUG_REG5__lsVertCreditCnt_0_MASK 0xf8000000
+#define VGT_DEBUG_REG5__lsVertCreditCnt_0__SHIFT 0x1b
+#define VGT_DEBUG_REG6__debug_BASE_MASK 0xffff
+#define VGT_DEBUG_REG6__debug_BASE__SHIFT 0x0
+#define VGT_DEBUG_REG6__debug_SIZE_MASK 0xffff0000
+#define VGT_DEBUG_REG6__debug_SIZE__SHIFT 0x10
+#define VGT_DEBUG_REG7__debug_tfmmFifoEmpty_MASK 0x1
+#define VGT_DEBUG_REG7__debug_tfmmFifoEmpty__SHIFT 0x0
+#define VGT_DEBUG_REG7__debug_tfmmFifoFull_MASK 0x2
+#define VGT_DEBUG_REG7__debug_tfmmFifoFull__SHIFT 0x1
+#define VGT_DEBUG_REG7__hs_pipe0_dr_MASK 0x4
+#define VGT_DEBUG_REG7__hs_pipe0_dr__SHIFT 0x2
+#define VGT_DEBUG_REG7__hs_pipe0_rtr_MASK 0x8
+#define VGT_DEBUG_REG7__hs_pipe0_rtr__SHIFT 0x3
+#define VGT_DEBUG_REG7__hs_pipe1_rtr_MASK 0x10
+#define VGT_DEBUG_REG7__hs_pipe1_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG7__SPARE_MASK 0xffe0
+#define VGT_DEBUG_REG7__SPARE__SHIFT 0x5
+#define VGT_DEBUG_REG7__TF_addr_MASK 0xffff0000
+#define VGT_DEBUG_REG7__TF_addr__SHIFT 0x10
+#define VGT_DEBUG_REG8__rcm_busy_q_MASK 0x1
+#define VGT_DEBUG_REG8__rcm_busy_q__SHIFT 0x0
+#define VGT_DEBUG_REG8__rcm_noif_busy_q_MASK 0x2
+#define VGT_DEBUG_REG8__rcm_noif_busy_q__SHIFT 0x1
+#define VGT_DEBUG_REG8__r1_inst_rtr_MASK 0x4
+#define VGT_DEBUG_REG8__r1_inst_rtr__SHIFT 0x2
+#define VGT_DEBUG_REG8__spi_gsprim_fifo_busy_q_MASK 0x8
+#define VGT_DEBUG_REG8__spi_gsprim_fifo_busy_q__SHIFT 0x3
+#define VGT_DEBUG_REG8__spi_esvert_fifo_busy_q_MASK 0x10
+#define VGT_DEBUG_REG8__spi_esvert_fifo_busy_q__SHIFT 0x4
+#define VGT_DEBUG_REG8__gs_tbl_valid_r3_q_MASK 0x20
+#define VGT_DEBUG_REG8__gs_tbl_valid_r3_q__SHIFT 0x5
+#define VGT_DEBUG_REG8__valid_r0_q_MASK 0x40
+#define VGT_DEBUG_REG8__valid_r0_q__SHIFT 0x6
+#define VGT_DEBUG_REG8__valid_r1_q_MASK 0x80
+#define VGT_DEBUG_REG8__valid_r1_q__SHIFT 0x7
+#define VGT_DEBUG_REG8__valid_r2_MASK 0x100
+#define VGT_DEBUG_REG8__valid_r2__SHIFT 0x8
+#define VGT_DEBUG_REG8__valid_r2_q_MASK 0x200
+#define VGT_DEBUG_REG8__valid_r2_q__SHIFT 0x9
+#define VGT_DEBUG_REG8__r0_rtr_MASK 0x400
+#define VGT_DEBUG_REG8__r0_rtr__SHIFT 0xa
+#define VGT_DEBUG_REG8__r1_rtr_MASK 0x800
+#define VGT_DEBUG_REG8__r1_rtr__SHIFT 0xb
+#define VGT_DEBUG_REG8__r2_indx_rtr_MASK 0x1000
+#define VGT_DEBUG_REG8__r2_indx_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG8__r2_rtr_MASK 0x2000
+#define VGT_DEBUG_REG8__r2_rtr__SHIFT 0xd
+#define VGT_DEBUG_REG8__es_gs_rtr_MASK 0x4000
+#define VGT_DEBUG_REG8__es_gs_rtr__SHIFT 0xe
+#define VGT_DEBUG_REG8__gs_event_fifo_rtr_MASK 0x8000
+#define VGT_DEBUG_REG8__gs_event_fifo_rtr__SHIFT 0xf
+#define VGT_DEBUG_REG8__tm_rcm_gs_event_rtr_MASK 0x10000
+#define VGT_DEBUG_REG8__tm_rcm_gs_event_rtr__SHIFT 0x10
+#define VGT_DEBUG_REG8__gs_tbl_r3_rtr_MASK 0x20000
+#define VGT_DEBUG_REG8__gs_tbl_r3_rtr__SHIFT 0x11
+#define VGT_DEBUG_REG8__prim_skid_fifo_empty_MASK 0x40000
+#define VGT_DEBUG_REG8__prim_skid_fifo_empty__SHIFT 0x12
+#define VGT_DEBUG_REG8__VGT_SPI_gsprim_rtr_q_MASK 0x80000
+#define VGT_DEBUG_REG8__VGT_SPI_gsprim_rtr_q__SHIFT 0x13
+#define VGT_DEBUG_REG8__tm_rcm_gs_tbl_rtr_MASK 0x100000
+#define VGT_DEBUG_REG8__tm_rcm_gs_tbl_rtr__SHIFT 0x14
+#define VGT_DEBUG_REG8__tm_rcm_es_tbl_rtr_MASK 0x200000
+#define VGT_DEBUG_REG8__tm_rcm_es_tbl_rtr__SHIFT 0x15
+#define VGT_DEBUG_REG8__VGT_SPI_esvert_rtr_q_MASK 0x400000
+#define VGT_DEBUG_REG8__VGT_SPI_esvert_rtr_q__SHIFT 0x16
+#define VGT_DEBUG_REG8__r2_no_bp_rtr_MASK 0x800000
+#define VGT_DEBUG_REG8__r2_no_bp_rtr__SHIFT 0x17
+#define VGT_DEBUG_REG8__hold_for_es_flush_MASK 0x1000000
+#define VGT_DEBUG_REG8__hold_for_es_flush__SHIFT 0x18
+#define VGT_DEBUG_REG8__gs_event_fifo_empty_MASK 0x2000000
+#define VGT_DEBUG_REG8__gs_event_fifo_empty__SHIFT 0x19
+#define VGT_DEBUG_REG8__gsprim_buff_empty_q_MASK 0x4000000
+#define VGT_DEBUG_REG8__gsprim_buff_empty_q__SHIFT 0x1a
+#define VGT_DEBUG_REG8__gsprim_buff_full_q_MASK 0x8000000
+#define VGT_DEBUG_REG8__gsprim_buff_full_q__SHIFT 0x1b
+#define VGT_DEBUG_REG8__te_prim_fifo_empty_MASK 0x10000000
+#define VGT_DEBUG_REG8__te_prim_fifo_empty__SHIFT 0x1c
+#define VGT_DEBUG_REG8__te_prim_fifo_full_MASK 0x20000000
+#define VGT_DEBUG_REG8__te_prim_fifo_full__SHIFT 0x1d
+#define VGT_DEBUG_REG8__te_vert_fifo_empty_MASK 0x40000000
+#define VGT_DEBUG_REG8__te_vert_fifo_empty__SHIFT 0x1e
+#define VGT_DEBUG_REG8__te_vert_fifo_full_MASK 0x80000000
+#define VGT_DEBUG_REG8__te_vert_fifo_full__SHIFT 0x1f
+#define VGT_DEBUG_REG9__indices_to_send_r2_q_MASK 0x3
+#define VGT_DEBUG_REG9__indices_to_send_r2_q__SHIFT 0x0
+#define VGT_DEBUG_REG9__valid_indices_r3_MASK 0x4
+#define VGT_DEBUG_REG9__valid_indices_r3__SHIFT 0x2
+#define VGT_DEBUG_REG9__gs_eov_r3_MASK 0x8
+#define VGT_DEBUG_REG9__gs_eov_r3__SHIFT 0x3
+#define VGT_DEBUG_REG9__eop_indx_r3_MASK 0x10
+#define VGT_DEBUG_REG9__eop_indx_r3__SHIFT 0x4
+#define VGT_DEBUG_REG9__eop_prim_r3_MASK 0x20
+#define VGT_DEBUG_REG9__eop_prim_r3__SHIFT 0x5
+#define VGT_DEBUG_REG9__es_eov_r3_MASK 0x40
+#define VGT_DEBUG_REG9__es_eov_r3__SHIFT 0x6
+#define VGT_DEBUG_REG9__es_tbl_state_r3_q_0_MASK 0x80
+#define VGT_DEBUG_REG9__es_tbl_state_r3_q_0__SHIFT 0x7
+#define VGT_DEBUG_REG9__pending_es_send_r3_q_MASK 0x100
+#define VGT_DEBUG_REG9__pending_es_send_r3_q__SHIFT 0x8
+#define VGT_DEBUG_REG9__pending_es_flush_r3_MASK 0x200
+#define VGT_DEBUG_REG9__pending_es_flush_r3__SHIFT 0x9
+#define VGT_DEBUG_REG9__gs_tbl_num_es_per_gs_r3_q_not_0_MASK 0x400
+#define VGT_DEBUG_REG9__gs_tbl_num_es_per_gs_r3_q_not_0__SHIFT 0xa
+#define VGT_DEBUG_REG9__gs_tbl_prim_cnt_r3_q_MASK 0x3f800
+#define VGT_DEBUG_REG9__gs_tbl_prim_cnt_r3_q__SHIFT 0xb
+#define VGT_DEBUG_REG9__gs_tbl_eop_r3_q_MASK 0x40000
+#define VGT_DEBUG_REG9__gs_tbl_eop_r3_q__SHIFT 0x12
+#define VGT_DEBUG_REG9__gs_tbl_state_r3_q_MASK 0x380000
+#define VGT_DEBUG_REG9__gs_tbl_state_r3_q__SHIFT 0x13
+#define VGT_DEBUG_REG9__gs_pending_state_r3_q_MASK 0x400000
+#define VGT_DEBUG_REG9__gs_pending_state_r3_q__SHIFT 0x16
+#define VGT_DEBUG_REG9__invalidate_rb_roll_over_q_MASK 0x800000
+#define VGT_DEBUG_REG9__invalidate_rb_roll_over_q__SHIFT 0x17
+#define VGT_DEBUG_REG9__gs_instancing_state_q_MASK 0x1000000
+#define VGT_DEBUG_REG9__gs_instancing_state_q__SHIFT 0x18
+#define VGT_DEBUG_REG9__es_per_gs_vert_cnt_r3_q_not_0_MASK 0x2000000
+#define VGT_DEBUG_REG9__es_per_gs_vert_cnt_r3_q_not_0__SHIFT 0x19
+#define VGT_DEBUG_REG9__gs_prim_per_es_ctr_r3_q_not_0_MASK 0x4000000
+#define VGT_DEBUG_REG9__gs_prim_per_es_ctr_r3_q_not_0__SHIFT 0x1a
+#define VGT_DEBUG_REG9__pre_r0_rtr_MASK 0x8000000
+#define VGT_DEBUG_REG9__pre_r0_rtr__SHIFT 0x1b
+#define VGT_DEBUG_REG9__valid_r3_q_MASK 0x10000000
+#define VGT_DEBUG_REG9__valid_r3_q__SHIFT 0x1c
+#define VGT_DEBUG_REG9__valid_pre_r0_q_MASK 0x20000000
+#define VGT_DEBUG_REG9__valid_pre_r0_q__SHIFT 0x1d
+#define VGT_DEBUG_REG9__SPARE0_MASK 0x40000000
+#define VGT_DEBUG_REG9__SPARE0__SHIFT 0x1e
+#define VGT_DEBUG_REG9__off_chip_hs_r2_q_MASK 0x80000000
+#define VGT_DEBUG_REG9__off_chip_hs_r2_q__SHIFT 0x1f
+#define VGT_DEBUG_REG10__index_buffer_depth_r1_q_MASK 0x1f
+#define VGT_DEBUG_REG10__index_buffer_depth_r1_q__SHIFT 0x0
+#define VGT_DEBUG_REG10__eopg_r2_q_MASK 0x20
+#define VGT_DEBUG_REG10__eopg_r2_q__SHIFT 0x5
+#define VGT_DEBUG_REG10__eotg_r2_q_MASK 0x40
+#define VGT_DEBUG_REG10__eotg_r2_q__SHIFT 0x6
+#define VGT_DEBUG_REG10__onchip_gs_en_r0_q_MASK 0x180
+#define VGT_DEBUG_REG10__onchip_gs_en_r0_q__SHIFT 0x7
+#define VGT_DEBUG_REG10__SPARE2_MASK 0x600
+#define VGT_DEBUG_REG10__SPARE2__SHIFT 0x9
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_qq_MASK 0x800
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_qq__SHIFT 0xb
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_q_MASK 0x1000
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_q__SHIFT 0xc
+#define VGT_DEBUG_REG10__gs_rb_space_avail_r3_q_9_0_MASK 0x7fe000
+#define VGT_DEBUG_REG10__gs_rb_space_avail_r3_q_9_0__SHIFT 0xd
+#define VGT_DEBUG_REG10__es_rb_space_avail_r2_q_8_0_MASK 0xff800000
+#define VGT_DEBUG_REG10__es_rb_space_avail_r2_q_8_0__SHIFT 0x17
+#define VGT_DEBUG_REG11__tm_busy_q_MASK 0x1
+#define VGT_DEBUG_REG11__tm_busy_q__SHIFT 0x0
+#define VGT_DEBUG_REG11__tm_noif_busy_q_MASK 0x2
+#define VGT_DEBUG_REG11__tm_noif_busy_q__SHIFT 0x1
+#define VGT_DEBUG_REG11__tm_out_busy_q_MASK 0x4
+#define VGT_DEBUG_REG11__tm_out_busy_q__SHIFT 0x2
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_busy_MASK 0x8
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_busy__SHIFT 0x3
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_busy_MASK 0x10
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_busy__SHIFT 0x4
+#define VGT_DEBUG_REG11__SPARE1_MASK 0x20
+#define VGT_DEBUG_REG11__SPARE1__SHIFT 0x5
+#define VGT_DEBUG_REG11__spi_gsthread_fifo_busy_MASK 0x40
+#define VGT_DEBUG_REG11__spi_gsthread_fifo_busy__SHIFT 0x6
+#define VGT_DEBUG_REG11__spi_esthread_fifo_busy_MASK 0x80
+#define VGT_DEBUG_REG11__spi_esthread_fifo_busy__SHIFT 0x7
+#define VGT_DEBUG_REG11__hold_eswave_MASK 0x100
+#define VGT_DEBUG_REG11__hold_eswave__SHIFT 0x8
+#define VGT_DEBUG_REG11__es_rb_roll_over_r3_MASK 0x200
+#define VGT_DEBUG_REG11__es_rb_roll_over_r3__SHIFT 0x9
+#define VGT_DEBUG_REG11__counters_busy_r0_MASK 0x400
+#define VGT_DEBUG_REG11__counters_busy_r0__SHIFT 0xa
+#define VGT_DEBUG_REG11__counters_avail_r0_MASK 0x800
+#define VGT_DEBUG_REG11__counters_avail_r0__SHIFT 0xb
+#define VGT_DEBUG_REG11__counters_available_r0_MASK 0x1000
+#define VGT_DEBUG_REG11__counters_available_r0__SHIFT 0xc
+#define VGT_DEBUG_REG11__vs_event_fifo_rtr_MASK 0x2000
+#define VGT_DEBUG_REG11__vs_event_fifo_rtr__SHIFT 0xd
+#define VGT_DEBUG_REG11__VGT_SPI_gsthread_rtr_q_MASK 0x4000
+#define VGT_DEBUG_REG11__VGT_SPI_gsthread_rtr_q__SHIFT 0xe
+#define VGT_DEBUG_REG11__VGT_SPI_esthread_rtr_q_MASK 0x8000
+#define VGT_DEBUG_REG11__VGT_SPI_esthread_rtr_q__SHIFT 0xf
+#define VGT_DEBUG_REG11__gs_issue_rtr_MASK 0x10000
+#define VGT_DEBUG_REG11__gs_issue_rtr__SHIFT 0x10
+#define VGT_DEBUG_REG11__tm_pt_event_rtr_MASK 0x20000
+#define VGT_DEBUG_REG11__tm_pt_event_rtr__SHIFT 0x11
+#define VGT_DEBUG_REG11__SPARE0_MASK 0x40000
+#define VGT_DEBUG_REG11__SPARE0__SHIFT 0x12
+#define VGT_DEBUG_REG11__gs_r0_rtr_MASK 0x80000
+#define VGT_DEBUG_REG11__gs_r0_rtr__SHIFT 0x13
+#define VGT_DEBUG_REG11__es_r0_rtr_MASK 0x100000
+#define VGT_DEBUG_REG11__es_r0_rtr__SHIFT 0x14
+#define VGT_DEBUG_REG11__gog_tm_vs_event_rtr_MASK 0x200000
+#define VGT_DEBUG_REG11__gog_tm_vs_event_rtr__SHIFT 0x15
+#define VGT_DEBUG_REG11__tm_rcm_gs_event_rtr_MASK 0x400000
+#define VGT_DEBUG_REG11__tm_rcm_gs_event_rtr__SHIFT 0x16
+#define VGT_DEBUG_REG11__tm_rcm_gs_tbl_rtr_MASK 0x800000
+#define VGT_DEBUG_REG11__tm_rcm_gs_tbl_rtr__SHIFT 0x17
+#define VGT_DEBUG_REG11__tm_rcm_es_tbl_rtr_MASK 0x1000000
+#define VGT_DEBUG_REG11__tm_rcm_es_tbl_rtr__SHIFT 0x18
+#define VGT_DEBUG_REG11__vs_event_fifo_empty_MASK 0x2000000
+#define VGT_DEBUG_REG11__vs_event_fifo_empty__SHIFT 0x19
+#define VGT_DEBUG_REG11__vs_event_fifo_full_MASK 0x4000000
+#define VGT_DEBUG_REG11__vs_event_fifo_full__SHIFT 0x1a
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_full_MASK 0x8000000
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_full__SHIFT 0x1b
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_full_MASK 0x10000000
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_full__SHIFT 0x1c
+#define VGT_DEBUG_REG11__send_event_q_MASK 0x20000000
+#define VGT_DEBUG_REG11__send_event_q__SHIFT 0x1d
+#define VGT_DEBUG_REG11__es_tbl_empty_MASK 0x40000000
+#define VGT_DEBUG_REG11__es_tbl_empty__SHIFT 0x1e
+#define VGT_DEBUG_REG11__no_active_states_r0_MASK 0x80000000
+#define VGT_DEBUG_REG11__no_active_states_r0__SHIFT 0x1f
+#define VGT_DEBUG_REG12__gs_state0_r0_q_MASK 0x7
+#define VGT_DEBUG_REG12__gs_state0_r0_q__SHIFT 0x0
+#define VGT_DEBUG_REG12__gs_state1_r0_q_MASK 0x38
+#define VGT_DEBUG_REG12__gs_state1_r0_q__SHIFT 0x3
+#define VGT_DEBUG_REG12__gs_state2_r0_q_MASK 0x1c0
+#define VGT_DEBUG_REG12__gs_state2_r0_q__SHIFT 0x6
+#define VGT_DEBUG_REG12__gs_state3_r0_q_MASK 0xe00
+#define VGT_DEBUG_REG12__gs_state3_r0_q__SHIFT 0x9
+#define VGT_DEBUG_REG12__gs_state4_r0_q_MASK 0x7000
+#define VGT_DEBUG_REG12__gs_state4_r0_q__SHIFT 0xc
+#define VGT_DEBUG_REG12__gs_state5_r0_q_MASK 0x38000
+#define VGT_DEBUG_REG12__gs_state5_r0_q__SHIFT 0xf
+#define VGT_DEBUG_REG12__gs_state6_r0_q_MASK 0x1c0000
+#define VGT_DEBUG_REG12__gs_state6_r0_q__SHIFT 0x12
+#define VGT_DEBUG_REG12__gs_state7_r0_q_MASK 0xe00000
+#define VGT_DEBUG_REG12__gs_state7_r0_q__SHIFT 0x15
+#define VGT_DEBUG_REG12__gs_state8_r0_q_MASK 0x7000000
+#define VGT_DEBUG_REG12__gs_state8_r0_q__SHIFT 0x18
+#define VGT_DEBUG_REG12__gs_state9_r0_q_MASK 0x38000000
+#define VGT_DEBUG_REG12__gs_state9_r0_q__SHIFT 0x1b
+#define VGT_DEBUG_REG12__hold_eswave_eop_MASK 0x40000000
+#define VGT_DEBUG_REG12__hold_eswave_eop__SHIFT 0x1e
+#define VGT_DEBUG_REG12__SPARE0_MASK 0x80000000
+#define VGT_DEBUG_REG12__SPARE0__SHIFT 0x1f
+#define VGT_DEBUG_REG13__gs_state10_r0_q_MASK 0x7
+#define VGT_DEBUG_REG13__gs_state10_r0_q__SHIFT 0x0
+#define VGT_DEBUG_REG13__gs_state11_r0_q_MASK 0x38
+#define VGT_DEBUG_REG13__gs_state11_r0_q__SHIFT 0x3
+#define VGT_DEBUG_REG13__gs_state12_r0_q_MASK 0x1c0
+#define VGT_DEBUG_REG13__gs_state12_r0_q__SHIFT 0x6
+#define VGT_DEBUG_REG13__gs_state13_r0_q_MASK 0xe00
+#define VGT_DEBUG_REG13__gs_state13_r0_q__SHIFT 0x9
+#define VGT_DEBUG_REG13__gs_state14_r0_q_MASK 0x7000
+#define VGT_DEBUG_REG13__gs_state14_r0_q__SHIFT 0xc
+#define VGT_DEBUG_REG13__gs_state15_r0_q_MASK 0x38000
+#define VGT_DEBUG_REG13__gs_state15_r0_q__SHIFT 0xf
+#define VGT_DEBUG_REG13__gs_tbl_wrptr_r0_q_3_0_MASK 0x3c0000
+#define VGT_DEBUG_REG13__gs_tbl_wrptr_r0_q_3_0__SHIFT 0x12
+#define VGT_DEBUG_REG13__gsfetch_done_fifo_cnt_q_not_0_MASK 0x400000
+#define VGT_DEBUG_REG13__gsfetch_done_fifo_cnt_q_not_0__SHIFT 0x16
+#define VGT_DEBUG_REG13__gsfetch_done_cnt_q_not_0_MASK 0x800000
+#define VGT_DEBUG_REG13__gsfetch_done_cnt_q_not_0__SHIFT 0x17
+#define VGT_DEBUG_REG13__es_tbl_full_MASK 0x1000000
+#define VGT_DEBUG_REG13__es_tbl_full__SHIFT 0x18
+#define VGT_DEBUG_REG13__SPARE1_MASK 0x2000000
+#define VGT_DEBUG_REG13__SPARE1__SHIFT 0x19
+#define VGT_DEBUG_REG13__SPARE0_MASK 0x4000000
+#define VGT_DEBUG_REG13__SPARE0__SHIFT 0x1a
+#define VGT_DEBUG_REG13__active_cm_sm_r0_q_MASK 0xf8000000
+#define VGT_DEBUG_REG13__active_cm_sm_r0_q__SHIFT 0x1b
+#define VGT_DEBUG_REG14__SPARE3_MASK 0xf
+#define VGT_DEBUG_REG14__SPARE3__SHIFT 0x0
+#define VGT_DEBUG_REG14__gsfetch_done_fifo_full_MASK 0x10
+#define VGT_DEBUG_REG14__gsfetch_done_fifo_full__SHIFT 0x4
+#define VGT_DEBUG_REG14__gs_rb_space_avail_r0_MASK 0x20
+#define VGT_DEBUG_REG14__gs_rb_space_avail_r0__SHIFT 0x5
+#define VGT_DEBUG_REG14__smx_es_done_cnt_r0_q_not_0_MASK 0x40
+#define VGT_DEBUG_REG14__smx_es_done_cnt_r0_q_not_0__SHIFT 0x6
+#define VGT_DEBUG_REG14__SPARE8_MASK 0x180
+#define VGT_DEBUG_REG14__SPARE8__SHIFT 0x7
+#define VGT_DEBUG_REG14__vs_done_cnt_q_not_0_MASK 0x200
+#define VGT_DEBUG_REG14__vs_done_cnt_q_not_0__SHIFT 0x9
+#define VGT_DEBUG_REG14__es_flush_cnt_busy_q_MASK 0x400
+#define VGT_DEBUG_REG14__es_flush_cnt_busy_q__SHIFT 0xa
+#define VGT_DEBUG_REG14__gs_tbl_full_r0_MASK 0x800
+#define VGT_DEBUG_REG14__gs_tbl_full_r0__SHIFT 0xb
+#define VGT_DEBUG_REG14__SPARE2_MASK 0x1ff000
+#define VGT_DEBUG_REG14__SPARE2__SHIFT 0xc
+#define VGT_DEBUG_REG14__se1spi_gsthread_fifo_busy_MASK 0x200000
+#define VGT_DEBUG_REG14__se1spi_gsthread_fifo_busy__SHIFT 0x15
+#define VGT_DEBUG_REG14__SPARE_MASK 0x1c00000
+#define VGT_DEBUG_REG14__SPARE__SHIFT 0x16
+#define VGT_DEBUG_REG14__VGT_SE1SPI_gsthread_rtr_q_MASK 0x2000000
+#define VGT_DEBUG_REG14__VGT_SE1SPI_gsthread_rtr_q__SHIFT 0x19
+#define VGT_DEBUG_REG14__smx1_es_done_cnt_r0_q_not_0_MASK 0x4000000
+#define VGT_DEBUG_REG14__smx1_es_done_cnt_r0_q_not_0__SHIFT 0x1a
+#define VGT_DEBUG_REG14__se1spi_esthread_fifo_busy_MASK 0x8000000
+#define VGT_DEBUG_REG14__se1spi_esthread_fifo_busy__SHIFT 0x1b
+#define VGT_DEBUG_REG14__SPARE1_MASK 0x10000000
+#define VGT_DEBUG_REG14__SPARE1__SHIFT 0x1c
+#define VGT_DEBUG_REG14__gsfetch_done_se1_cnt_q_not_0_MASK 0x20000000
+#define VGT_DEBUG_REG14__gsfetch_done_se1_cnt_q_not_0__SHIFT 0x1d
+#define VGT_DEBUG_REG14__SPARE0_MASK 0x40000000
+#define VGT_DEBUG_REG14__SPARE0__SHIFT 0x1e
+#define VGT_DEBUG_REG14__VGT_SE1SPI_esthread_rtr_q_MASK 0x80000000
+#define VGT_DEBUG_REG14__VGT_SE1SPI_esthread_rtr_q__SHIFT 0x1f
+#define VGT_DEBUG_REG15__cm_busy_q_MASK 0x1
+#define VGT_DEBUG_REG15__cm_busy_q__SHIFT 0x0
+#define VGT_DEBUG_REG15__counters_busy_q_MASK 0x2
+#define VGT_DEBUG_REG15__counters_busy_q__SHIFT 0x1
+#define VGT_DEBUG_REG15__output_fifo_empty_MASK 0x4
+#define VGT_DEBUG_REG15__output_fifo_empty__SHIFT 0x2
+#define VGT_DEBUG_REG15__output_fifo_full_MASK 0x8
+#define VGT_DEBUG_REG15__output_fifo_full__SHIFT 0x3
+#define VGT_DEBUG_REG15__counters_full_MASK 0x10
+#define VGT_DEBUG_REG15__counters_full__SHIFT 0x4
+#define VGT_DEBUG_REG15__active_sm_q_MASK 0x3e0
+#define VGT_DEBUG_REG15__active_sm_q__SHIFT 0x5
+#define VGT_DEBUG_REG15__entry_rdptr_q_MASK 0x7c00
+#define VGT_DEBUG_REG15__entry_rdptr_q__SHIFT 0xa
+#define VGT_DEBUG_REG15__cntr_tbl_wrptr_q_MASK 0xf8000
+#define VGT_DEBUG_REG15__cntr_tbl_wrptr_q__SHIFT 0xf
+#define VGT_DEBUG_REG15__SPARE25_MASK 0x3f00000
+#define VGT_DEBUG_REG15__SPARE25__SHIFT 0x14
+#define VGT_DEBUG_REG15__st_cut_mode_q_MASK 0xc000000
+#define VGT_DEBUG_REG15__st_cut_mode_q__SHIFT 0x1a
+#define VGT_DEBUG_REG15__gs_done_array_q_not_0_MASK 0x10000000
+#define VGT_DEBUG_REG15__gs_done_array_q_not_0__SHIFT 0x1c
+#define VGT_DEBUG_REG15__SPARE31_MASK 0xe0000000
+#define VGT_DEBUG_REG15__SPARE31__SHIFT 0x1d
+#define VGT_DEBUG_REG16__gog_busy_MASK 0x1
+#define VGT_DEBUG_REG16__gog_busy__SHIFT 0x0
+#define VGT_DEBUG_REG16__gog_state_q_MASK 0xe
+#define VGT_DEBUG_REG16__gog_state_q__SHIFT 0x1
+#define VGT_DEBUG_REG16__r0_rtr_MASK 0x10
+#define VGT_DEBUG_REG16__r0_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG16__r1_rtr_MASK 0x20
+#define VGT_DEBUG_REG16__r1_rtr__SHIFT 0x5
+#define VGT_DEBUG_REG16__r1_upstream_rtr_MASK 0x40
+#define VGT_DEBUG_REG16__r1_upstream_rtr__SHIFT 0x6
+#define VGT_DEBUG_REG16__r2_vs_tbl_rtr_MASK 0x80
+#define VGT_DEBUG_REG16__r2_vs_tbl_rtr__SHIFT 0x7
+#define VGT_DEBUG_REG16__r2_prim_rtr_MASK 0x100
+#define VGT_DEBUG_REG16__r2_prim_rtr__SHIFT 0x8
+#define VGT_DEBUG_REG16__r2_indx_rtr_MASK 0x200
+#define VGT_DEBUG_REG16__r2_indx_rtr__SHIFT 0x9
+#define VGT_DEBUG_REG16__r2_rtr_MASK 0x400
+#define VGT_DEBUG_REG16__r2_rtr__SHIFT 0xa
+#define VGT_DEBUG_REG16__gog_tm_vs_event_rtr_MASK 0x800
+#define VGT_DEBUG_REG16__gog_tm_vs_event_rtr__SHIFT 0xb
+#define VGT_DEBUG_REG16__r3_force_vs_tbl_we_rtr_MASK 0x1000
+#define VGT_DEBUG_REG16__r3_force_vs_tbl_we_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG16__indx_valid_r2_q_MASK 0x2000
+#define VGT_DEBUG_REG16__indx_valid_r2_q__SHIFT 0xd
+#define VGT_DEBUG_REG16__prim_valid_r2_q_MASK 0x4000
+#define VGT_DEBUG_REG16__prim_valid_r2_q__SHIFT 0xe
+#define VGT_DEBUG_REG16__valid_r2_q_MASK 0x8000
+#define VGT_DEBUG_REG16__valid_r2_q__SHIFT 0xf
+#define VGT_DEBUG_REG16__prim_valid_r1_q_MASK 0x10000
+#define VGT_DEBUG_REG16__prim_valid_r1_q__SHIFT 0x10
+#define VGT_DEBUG_REG16__indx_valid_r1_q_MASK 0x20000
+#define VGT_DEBUG_REG16__indx_valid_r1_q__SHIFT 0x11
+#define VGT_DEBUG_REG16__valid_r1_q_MASK 0x40000
+#define VGT_DEBUG_REG16__valid_r1_q__SHIFT 0x12
+#define VGT_DEBUG_REG16__indx_valid_r0_q_MASK 0x80000
+#define VGT_DEBUG_REG16__indx_valid_r0_q__SHIFT 0x13
+#define VGT_DEBUG_REG16__prim_valid_r0_q_MASK 0x100000
+#define VGT_DEBUG_REG16__prim_valid_r0_q__SHIFT 0x14
+#define VGT_DEBUG_REG16__valid_r0_q_MASK 0x200000
+#define VGT_DEBUG_REG16__valid_r0_q__SHIFT 0x15
+#define VGT_DEBUG_REG16__send_event_q_MASK 0x400000
+#define VGT_DEBUG_REG16__send_event_q__SHIFT 0x16
+#define VGT_DEBUG_REG16__SPARE24_MASK 0x800000
+#define VGT_DEBUG_REG16__SPARE24__SHIFT 0x17
+#define VGT_DEBUG_REG16__vert_seen_since_sopg_r2_q_MASK 0x1000000
+#define VGT_DEBUG_REG16__vert_seen_since_sopg_r2_q__SHIFT 0x18
+#define VGT_DEBUG_REG16__gog_out_prim_state_sel_MASK 0xe000000
+#define VGT_DEBUG_REG16__gog_out_prim_state_sel__SHIFT 0x19
+#define VGT_DEBUG_REG16__multiple_streams_en_r1_q_MASK 0x10000000
+#define VGT_DEBUG_REG16__multiple_streams_en_r1_q__SHIFT 0x1c
+#define VGT_DEBUG_REG16__vs_vert_count_r2_q_not_0_MASK 0x20000000
+#define VGT_DEBUG_REG16__vs_vert_count_r2_q_not_0__SHIFT 0x1d
+#define VGT_DEBUG_REG16__num_gs_r2_q_not_0_MASK 0x40000000
+#define VGT_DEBUG_REG16__num_gs_r2_q_not_0__SHIFT 0x1e
+#define VGT_DEBUG_REG16__new_vs_thread_r2_MASK 0x80000000
+#define VGT_DEBUG_REG16__new_vs_thread_r2__SHIFT 0x1f
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx2_5_0_MASK 0x3f
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx2_5_0__SHIFT 0x0
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx1_5_0_MASK 0xfc0
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx1_5_0__SHIFT 0x6
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx0_5_0_MASK 0x3f000
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx0_5_0__SHIFT 0xc
+#define VGT_DEBUG_REG17__gog_out_indx_13_0_MASK 0xfffc0000
+#define VGT_DEBUG_REG17__gog_out_indx_13_0__SHIFT 0x12
+#define VGT_DEBUG_REG18__grp_vr_valid_MASK 0x1
+#define VGT_DEBUG_REG18__grp_vr_valid__SHIFT 0x0
+#define VGT_DEBUG_REG18__pipe0_dr_MASK 0x2
+#define VGT_DEBUG_REG18__pipe0_dr__SHIFT 0x1
+#define VGT_DEBUG_REG18__pipe1_dr_MASK 0x4
+#define VGT_DEBUG_REG18__pipe1_dr__SHIFT 0x2
+#define VGT_DEBUG_REG18__vr_grp_read_MASK 0x8
+#define VGT_DEBUG_REG18__vr_grp_read__SHIFT 0x3
+#define VGT_DEBUG_REG18__pipe0_rtr_MASK 0x10
+#define VGT_DEBUG_REG18__pipe0_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG18__pipe1_rtr_MASK 0x20
+#define VGT_DEBUG_REG18__pipe1_rtr__SHIFT 0x5
+#define VGT_DEBUG_REG18__out_vr_indx_read_MASK 0x40
+#define VGT_DEBUG_REG18__out_vr_indx_read__SHIFT 0x6
+#define VGT_DEBUG_REG18__out_vr_prim_read_MASK 0x80
+#define VGT_DEBUG_REG18__out_vr_prim_read__SHIFT 0x7
+#define VGT_DEBUG_REG18__indices_to_send_q_MASK 0x700
+#define VGT_DEBUG_REG18__indices_to_send_q__SHIFT 0x8
+#define VGT_DEBUG_REG18__valid_indices_MASK 0x800
+#define VGT_DEBUG_REG18__valid_indices__SHIFT 0xb
+#define VGT_DEBUG_REG18__last_indx_of_prim_MASK 0x1000
+#define VGT_DEBUG_REG18__last_indx_of_prim__SHIFT 0xc
+#define VGT_DEBUG_REG18__indx0_new_d_MASK 0x2000
+#define VGT_DEBUG_REG18__indx0_new_d__SHIFT 0xd
+#define VGT_DEBUG_REG18__indx1_new_d_MASK 0x4000
+#define VGT_DEBUG_REG18__indx1_new_d__SHIFT 0xe
+#define VGT_DEBUG_REG18__indx2_new_d_MASK 0x8000
+#define VGT_DEBUG_REG18__indx2_new_d__SHIFT 0xf
+#define VGT_DEBUG_REG18__indx2_hit_d_MASK 0x10000
+#define VGT_DEBUG_REG18__indx2_hit_d__SHIFT 0x10
+#define VGT_DEBUG_REG18__indx1_hit_d_MASK 0x20000
+#define VGT_DEBUG_REG18__indx1_hit_d__SHIFT 0x11
+#define VGT_DEBUG_REG18__indx0_hit_d_MASK 0x40000
+#define VGT_DEBUG_REG18__indx0_hit_d__SHIFT 0x12
+#define VGT_DEBUG_REG18__st_vertex_reuse_off_r0_q_MASK 0x80000
+#define VGT_DEBUG_REG18__st_vertex_reuse_off_r0_q__SHIFT 0x13
+#define VGT_DEBUG_REG18__last_group_of_instance_r0_q_MASK 0x100000
+#define VGT_DEBUG_REG18__last_group_of_instance_r0_q__SHIFT 0x14
+#define VGT_DEBUG_REG18__null_primitive_r0_q_MASK 0x200000
+#define VGT_DEBUG_REG18__null_primitive_r0_q__SHIFT 0x15
+#define VGT_DEBUG_REG18__eop_r0_q_MASK 0x400000
+#define VGT_DEBUG_REG18__eop_r0_q__SHIFT 0x16
+#define VGT_DEBUG_REG18__eject_vtx_vect_r1_d_MASK 0x800000
+#define VGT_DEBUG_REG18__eject_vtx_vect_r1_d__SHIFT 0x17
+#define VGT_DEBUG_REG18__sub_prim_type_r0_q_MASK 0x7000000
+#define VGT_DEBUG_REG18__sub_prim_type_r0_q__SHIFT 0x18
+#define VGT_DEBUG_REG18__gs_scenario_a_r0_q_MASK 0x8000000
+#define VGT_DEBUG_REG18__gs_scenario_a_r0_q__SHIFT 0x1b
+#define VGT_DEBUG_REG18__gs_scenario_b_r0_q_MASK 0x10000000
+#define VGT_DEBUG_REG18__gs_scenario_b_r0_q__SHIFT 0x1c
+#define VGT_DEBUG_REG18__components_valid_r0_q_MASK 0xe0000000
+#define VGT_DEBUG_REG18__components_valid_r0_q__SHIFT 0x1d
+#define VGT_DEBUG_REG19__separate_out_busy_q_MASK 0x1
+#define VGT_DEBUG_REG19__separate_out_busy_q__SHIFT 0x0
+#define VGT_DEBUG_REG19__separate_out_indx_busy_q_MASK 0x2
+#define VGT_DEBUG_REG19__separate_out_indx_busy_q__SHIFT 0x1
+#define VGT_DEBUG_REG19__prim_buffer_empty_MASK 0x4
+#define VGT_DEBUG_REG19__prim_buffer_empty__SHIFT 0x2
+#define VGT_DEBUG_REG19__prim_buffer_full_MASK 0x8
+#define VGT_DEBUG_REG19__prim_buffer_full__SHIFT 0x3
+#define VGT_DEBUG_REG19__pa_clips_fifo_busy_q_MASK 0x10
+#define VGT_DEBUG_REG19__pa_clips_fifo_busy_q__SHIFT 0x4
+#define VGT_DEBUG_REG19__pa_clipp_fifo_busy_q_MASK 0x20
+#define VGT_DEBUG_REG19__pa_clipp_fifo_busy_q__SHIFT 0x5
+#define VGT_DEBUG_REG19__VGT_PA_clips_rtr_q_MASK 0x40
+#define VGT_DEBUG_REG19__VGT_PA_clips_rtr_q__SHIFT 0x6
+#define VGT_DEBUG_REG19__VGT_PA_clipp_rtr_q_MASK 0x80
+#define VGT_DEBUG_REG19__VGT_PA_clipp_rtr_q__SHIFT 0x7
+#define VGT_DEBUG_REG19__spi_vsthread_fifo_busy_q_MASK 0x100
+#define VGT_DEBUG_REG19__spi_vsthread_fifo_busy_q__SHIFT 0x8
+#define VGT_DEBUG_REG19__spi_vsvert_fifo_busy_q_MASK 0x200
+#define VGT_DEBUG_REG19__spi_vsvert_fifo_busy_q__SHIFT 0x9
+#define VGT_DEBUG_REG19__pa_clipv_fifo_busy_q_MASK 0x400
+#define VGT_DEBUG_REG19__pa_clipv_fifo_busy_q__SHIFT 0xa
+#define VGT_DEBUG_REG19__hold_prim_MASK 0x800
+#define VGT_DEBUG_REG19__hold_prim__SHIFT 0xb
+#define VGT_DEBUG_REG19__VGT_SPI_vsthread_rtr_q_MASK 0x1000
+#define VGT_DEBUG_REG19__VGT_SPI_vsthread_rtr_q__SHIFT 0xc
+#define VGT_DEBUG_REG19__VGT_SPI_vsvert_rtr_q_MASK 0x2000
+#define VGT_DEBUG_REG19__VGT_SPI_vsvert_rtr_q__SHIFT 0xd
+#define VGT_DEBUG_REG19__VGT_PA_clipv_rtr_q_MASK 0x4000
+#define VGT_DEBUG_REG19__VGT_PA_clipv_rtr_q__SHIFT 0xe
+#define VGT_DEBUG_REG19__new_packet_q_MASK 0x8000
+#define VGT_DEBUG_REG19__new_packet_q__SHIFT 0xf
+#define VGT_DEBUG_REG19__buffered_prim_event_MASK 0x10000
+#define VGT_DEBUG_REG19__buffered_prim_event__SHIFT 0x10
+#define VGT_DEBUG_REG19__buffered_prim_null_primitive_MASK 0x20000
+#define VGT_DEBUG_REG19__buffered_prim_null_primitive__SHIFT 0x11
+#define VGT_DEBUG_REG19__buffered_prim_eop_MASK 0x40000
+#define VGT_DEBUG_REG19__buffered_prim_eop__SHIFT 0x12
+#define VGT_DEBUG_REG19__buffered_prim_eject_vtx_vect_MASK 0x80000
+#define VGT_DEBUG_REG19__buffered_prim_eject_vtx_vect__SHIFT 0x13
+#define VGT_DEBUG_REG19__buffered_prim_type_event_MASK 0x3f00000
+#define VGT_DEBUG_REG19__buffered_prim_type_event__SHIFT 0x14
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vswave_rtr_q_MASK 0x4000000
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vswave_rtr_q__SHIFT 0x1a
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vsvert_rtr_q_MASK 0x8000000
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vsvert_rtr_q__SHIFT 0x1b
+#define VGT_DEBUG_REG19__num_new_unique_rel_indx_MASK 0x30000000
+#define VGT_DEBUG_REG19__num_new_unique_rel_indx__SHIFT 0x1c
+#define VGT_DEBUG_REG19__null_terminate_vtx_vector_MASK 0x40000000
+#define VGT_DEBUG_REG19__null_terminate_vtx_vector__SHIFT 0x1e
+#define VGT_DEBUG_REG19__filter_event_MASK 0x80000000
+#define VGT_DEBUG_REG19__filter_event__SHIFT 0x1f
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexindex_MASK 0xffff
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexindex__SHIFT 0x0
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexcount_not_0_MASK 0x10000
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexcount_not_0__SHIFT 0x10
+#define VGT_DEBUG_REG20__SPARE17_MASK 0x20000
+#define VGT_DEBUG_REG20__SPARE17__SHIFT 0x11
+#define VGT_DEBUG_REG20__alloc_counter_q_MASK 0x3c0000
+#define VGT_DEBUG_REG20__alloc_counter_q__SHIFT 0x12
+#define VGT_DEBUG_REG20__curr_dealloc_distance_q_MASK 0x1fc00000
+#define VGT_DEBUG_REG20__curr_dealloc_distance_q__SHIFT 0x16
+#define VGT_DEBUG_REG20__new_allocate_q_MASK 0x20000000
+#define VGT_DEBUG_REG20__new_allocate_q__SHIFT 0x1d
+#define VGT_DEBUG_REG20__curr_slot_in_vtx_vect_q_not_0_MASK 0x40000000
+#define VGT_DEBUG_REG20__curr_slot_in_vtx_vect_q_not_0__SHIFT 0x1e
+#define VGT_DEBUG_REG20__int_vtx_counter_q_not_0_MASK 0x80000000
+#define VGT_DEBUG_REG20__int_vtx_counter_q_not_0__SHIFT 0x1f
+#define VGT_DEBUG_REG21__out_indx_fifo_empty_MASK 0x1
+#define VGT_DEBUG_REG21__out_indx_fifo_empty__SHIFT 0x0
+#define VGT_DEBUG_REG21__indx_side_fifo_empty_MASK 0x2
+#define VGT_DEBUG_REG21__indx_side_fifo_empty__SHIFT 0x1
+#define VGT_DEBUG_REG21__pipe0_dr_MASK 0x4
+#define VGT_DEBUG_REG21__pipe0_dr__SHIFT 0x2
+#define VGT_DEBUG_REG21__pipe1_dr_MASK 0x8
+#define VGT_DEBUG_REG21__pipe1_dr__SHIFT 0x3
+#define VGT_DEBUG_REG21__pipe2_dr_MASK 0x10
+#define VGT_DEBUG_REG21__pipe2_dr__SHIFT 0x4
+#define VGT_DEBUG_REG21__vsthread_buff_empty_MASK 0x20
+#define VGT_DEBUG_REG21__vsthread_buff_empty__SHIFT 0x5
+#define VGT_DEBUG_REG21__out_indx_fifo_full_MASK 0x40
+#define VGT_DEBUG_REG21__out_indx_fifo_full__SHIFT 0x6
+#define VGT_DEBUG_REG21__indx_side_fifo_full_MASK 0x80
+#define VGT_DEBUG_REG21__indx_side_fifo_full__SHIFT 0x7
+#define VGT_DEBUG_REG21__pipe0_rtr_MASK 0x100
+#define VGT_DEBUG_REG21__pipe0_rtr__SHIFT 0x8
+#define VGT_DEBUG_REG21__pipe1_rtr_MASK 0x200
+#define VGT_DEBUG_REG21__pipe1_rtr__SHIFT 0x9
+#define VGT_DEBUG_REG21__pipe2_rtr_MASK 0x400
+#define VGT_DEBUG_REG21__pipe2_rtr__SHIFT 0xa
+#define VGT_DEBUG_REG21__vsthread_buff_full_MASK 0x800
+#define VGT_DEBUG_REG21__vsthread_buff_full__SHIFT 0xb
+#define VGT_DEBUG_REG21__interfaces_rtr_MASK 0x1000
+#define VGT_DEBUG_REG21__interfaces_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG21__indx_count_q_not_0_MASK 0x2000
+#define VGT_DEBUG_REG21__indx_count_q_not_0__SHIFT 0xd
+#define VGT_DEBUG_REG21__wait_for_external_eopg_q_MASK 0x4000
+#define VGT_DEBUG_REG21__wait_for_external_eopg_q__SHIFT 0xe
+#define VGT_DEBUG_REG21__full_state_p1_q_MASK 0x8000
+#define VGT_DEBUG_REG21__full_state_p1_q__SHIFT 0xf
+#define VGT_DEBUG_REG21__indx_side_indx_valid_MASK 0x10000
+#define VGT_DEBUG_REG21__indx_side_indx_valid__SHIFT 0x10
+#define VGT_DEBUG_REG21__stateid_p0_q_MASK 0xe0000
+#define VGT_DEBUG_REG21__stateid_p0_q__SHIFT 0x11
+#define VGT_DEBUG_REG21__is_event_p0_q_MASK 0x100000
+#define VGT_DEBUG_REG21__is_event_p0_q__SHIFT 0x14
+#define VGT_DEBUG_REG21__lshs_dealloc_p1_MASK 0x200000
+#define VGT_DEBUG_REG21__lshs_dealloc_p1__SHIFT 0x15
+#define VGT_DEBUG_REG21__stream_id_r2_q_MASK 0x400000
+#define VGT_DEBUG_REG21__stream_id_r2_q__SHIFT 0x16
+#define VGT_DEBUG_REG21__vtx_vect_counter_q_not_0_MASK 0x800000
+#define VGT_DEBUG_REG21__vtx_vect_counter_q_not_0__SHIFT 0x17
+#define VGT_DEBUG_REG21__buff_full_p1_MASK 0x1000000
+#define VGT_DEBUG_REG21__buff_full_p1__SHIFT 0x18
+#define VGT_DEBUG_REG21__strmout_valid_p1_MASK 0x2000000
+#define VGT_DEBUG_REG21__strmout_valid_p1__SHIFT 0x19
+#define VGT_DEBUG_REG21__eotg_r2_q_MASK 0x4000000
+#define VGT_DEBUG_REG21__eotg_r2_q__SHIFT 0x1a
+#define VGT_DEBUG_REG21__null_r2_q_MASK 0x8000000
+#define VGT_DEBUG_REG21__null_r2_q__SHIFT 0x1b
+#define VGT_DEBUG_REG21__p0_dr_MASK 0x10000000
+#define VGT_DEBUG_REG21__p0_dr__SHIFT 0x1c
+#define VGT_DEBUG_REG21__p0_rtr_MASK 0x20000000
+#define VGT_DEBUG_REG21__p0_rtr__SHIFT 0x1d
+#define VGT_DEBUG_REG21__eopg_p0_q_MASK 0x40000000
+#define VGT_DEBUG_REG21__eopg_p0_q__SHIFT 0x1e
+#define VGT_DEBUG_REG21__p0_nobp_MASK 0x80000000
+#define VGT_DEBUG_REG21__p0_nobp__SHIFT 0x1f
+#define VGT_DEBUG_REG22__cm_state16_MASK 0x3
+#define VGT_DEBUG_REG22__cm_state16__SHIFT 0x0
+#define VGT_DEBUG_REG22__cm_state17_MASK 0xc
+#define VGT_DEBUG_REG22__cm_state17__SHIFT 0x2
+#define VGT_DEBUG_REG22__cm_state18_MASK 0x30
+#define VGT_DEBUG_REG22__cm_state18__SHIFT 0x4
+#define VGT_DEBUG_REG22__cm_state19_MASK 0xc0
+#define VGT_DEBUG_REG22__cm_state19__SHIFT 0x6
+#define VGT_DEBUG_REG22__cm_state20_MASK 0x300
+#define VGT_DEBUG_REG22__cm_state20__SHIFT 0x8
+#define VGT_DEBUG_REG22__cm_state21_MASK 0xc00
+#define VGT_DEBUG_REG22__cm_state21__SHIFT 0xa
+#define VGT_DEBUG_REG22__cm_state22_MASK 0x3000
+#define VGT_DEBUG_REG22__cm_state22__SHIFT 0xc
+#define VGT_DEBUG_REG22__cm_state23_MASK 0xc000
+#define VGT_DEBUG_REG22__cm_state23__SHIFT 0xe
+#define VGT_DEBUG_REG22__cm_state24_MASK 0x30000
+#define VGT_DEBUG_REG22__cm_state24__SHIFT 0x10
+#define VGT_DEBUG_REG22__cm_state25_MASK 0xc0000
+#define VGT_DEBUG_REG22__cm_state25__SHIFT 0x12
+#define VGT_DEBUG_REG22__cm_state26_MASK 0x300000
+#define VGT_DEBUG_REG22__cm_state26__SHIFT 0x14
+#define VGT_DEBUG_REG22__cm_state27_MASK 0xc00000
+#define VGT_DEBUG_REG22__cm_state27__SHIFT 0x16
+#define VGT_DEBUG_REG22__cm_state28_MASK 0x3000000
+#define VGT_DEBUG_REG22__cm_state28__SHIFT 0x18
+#define VGT_DEBUG_REG22__cm_state29_MASK 0xc000000
+#define VGT_DEBUG_REG22__cm_state29__SHIFT 0x1a
+#define VGT_DEBUG_REG22__cm_state30_MASK 0x30000000
+#define VGT_DEBUG_REG22__cm_state30__SHIFT 0x1c
+#define VGT_DEBUG_REG22__cm_state31_MASK 0xc0000000
+#define VGT_DEBUG_REG22__cm_state31__SHIFT 0x1e
+#define VGT_DEBUG_REG23__frmt_busy_MASK 0x1
+#define VGT_DEBUG_REG23__frmt_busy__SHIFT 0x0
+#define VGT_DEBUG_REG23__rcm_frmt_vert_rtr_MASK 0x2
+#define VGT_DEBUG_REG23__rcm_frmt_vert_rtr__SHIFT 0x1
+#define VGT_DEBUG_REG23__rcm_frmt_prim_rtr_MASK 0x4
+#define VGT_DEBUG_REG23__rcm_frmt_prim_rtr__SHIFT 0x2
+#define VGT_DEBUG_REG23__prim_r3_rtr_MASK 0x8
+#define VGT_DEBUG_REG23__prim_r3_rtr__SHIFT 0x3
+#define VGT_DEBUG_REG23__prim_r2_rtr_MASK 0x10
+#define VGT_DEBUG_REG23__prim_r2_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG23__vert_r3_rtr_MASK 0x20
+#define VGT_DEBUG_REG23__vert_r3_rtr__SHIFT 0x5
+#define VGT_DEBUG_REG23__vert_r2_rtr_MASK 0x40
+#define VGT_DEBUG_REG23__vert_r2_rtr__SHIFT 0x6
+#define VGT_DEBUG_REG23__vert_r1_rtr_MASK 0x80
+#define VGT_DEBUG_REG23__vert_r1_rtr__SHIFT 0x7
+#define VGT_DEBUG_REG23__vert_r0_rtr_MASK 0x100
+#define VGT_DEBUG_REG23__vert_r0_rtr__SHIFT 0x8
+#define VGT_DEBUG_REG23__prim_fifo_empty_MASK 0x200
+#define VGT_DEBUG_REG23__prim_fifo_empty__SHIFT 0x9
+#define VGT_DEBUG_REG23__prim_fifo_full_MASK 0x400
+#define VGT_DEBUG_REG23__prim_fifo_full__SHIFT 0xa
+#define VGT_DEBUG_REG23__vert_dr_r2_q_MASK 0x800
+#define VGT_DEBUG_REG23__vert_dr_r2_q__SHIFT 0xb
+#define VGT_DEBUG_REG23__prim_dr_r2_q_MASK 0x1000
+#define VGT_DEBUG_REG23__prim_dr_r2_q__SHIFT 0xc
+#define VGT_DEBUG_REG23__vert_dr_r1_q_MASK 0x2000
+#define VGT_DEBUG_REG23__vert_dr_r1_q__SHIFT 0xd
+#define VGT_DEBUG_REG23__vert_dr_r0_q_MASK 0x4000
+#define VGT_DEBUG_REG23__vert_dr_r0_q__SHIFT 0xe
+#define VGT_DEBUG_REG23__new_verts_r2_q_MASK 0x18000
+#define VGT_DEBUG_REG23__new_verts_r2_q__SHIFT 0xf
+#define VGT_DEBUG_REG23__verts_sent_r2_q_MASK 0x1e0000
+#define VGT_DEBUG_REG23__verts_sent_r2_q__SHIFT 0x11
+#define VGT_DEBUG_REG23__prim_state_sel_r2_q_MASK 0xe00000
+#define VGT_DEBUG_REG23__prim_state_sel_r2_q__SHIFT 0x15
+#define VGT_DEBUG_REG23__SPARE_MASK 0xff000000
+#define VGT_DEBUG_REG23__SPARE__SHIFT 0x18
+#define VGT_DEBUG_REG24__avail_es_rb_space_r0_q_23_0_MASK 0xffffff
+#define VGT_DEBUG_REG24__avail_es_rb_space_r0_q_23_0__SHIFT 0x0
+#define VGT_DEBUG_REG24__dependent_st_cut_mode_q_MASK 0x3000000
+#define VGT_DEBUG_REG24__dependent_st_cut_mode_q__SHIFT 0x18
+#define VGT_DEBUG_REG24__SPARE31_MASK 0xfc000000
+#define VGT_DEBUG_REG24__SPARE31__SHIFT 0x1a
+#define VGT_DEBUG_REG25__avail_gs_rb_space_r0_q_25_0_MASK 0x3ffffff
+#define VGT_DEBUG_REG25__avail_gs_rb_space_r0_q_25_0__SHIFT 0x0
+#define VGT_DEBUG_REG25__active_sm_r0_q_MASK 0x3c000000
+#define VGT_DEBUG_REG25__active_sm_r0_q__SHIFT 0x1a
+#define VGT_DEBUG_REG25__add_gs_rb_space_r1_q_MASK 0x40000000
+#define VGT_DEBUG_REG25__add_gs_rb_space_r1_q__SHIFT 0x1e
+#define VGT_DEBUG_REG25__add_gs_rb_space_r0_q_MASK 0x80000000
+#define VGT_DEBUG_REG25__add_gs_rb_space_r0_q__SHIFT 0x1f
+#define VGT_DEBUG_REG26__cm_state0_MASK 0x3
+#define VGT_DEBUG_REG26__cm_state0__SHIFT 0x0
+#define VGT_DEBUG_REG26__cm_state1_MASK 0xc
+#define VGT_DEBUG_REG26__cm_state1__SHIFT 0x2
+#define VGT_DEBUG_REG26__cm_state2_MASK 0x30
+#define VGT_DEBUG_REG26__cm_state2__SHIFT 0x4
+#define VGT_DEBUG_REG26__cm_state3_MASK 0xc0
+#define VGT_DEBUG_REG26__cm_state3__SHIFT 0x6
+#define VGT_DEBUG_REG26__cm_state4_MASK 0x300
+#define VGT_DEBUG_REG26__cm_state4__SHIFT 0x8
+#define VGT_DEBUG_REG26__cm_state5_MASK 0xc00
+#define VGT_DEBUG_REG26__cm_state5__SHIFT 0xa
+#define VGT_DEBUG_REG26__cm_state6_MASK 0x3000
+#define VGT_DEBUG_REG26__cm_state6__SHIFT 0xc
+#define VGT_DEBUG_REG26__cm_state7_MASK 0xc000
+#define VGT_DEBUG_REG26__cm_state7__SHIFT 0xe
+#define VGT_DEBUG_REG26__cm_state8_MASK 0x30000
+#define VGT_DEBUG_REG26__cm_state8__SHIFT 0x10
+#define VGT_DEBUG_REG26__cm_state9_MASK 0xc0000
+#define VGT_DEBUG_REG26__cm_state9__SHIFT 0x12
+#define VGT_DEBUG_REG26__cm_state10_MASK 0x300000
+#define VGT_DEBUG_REG26__cm_state10__SHIFT 0x14
+#define VGT_DEBUG_REG26__cm_state11_MASK 0xc00000
+#define VGT_DEBUG_REG26__cm_state11__SHIFT 0x16
+#define VGT_DEBUG_REG26__cm_state12_MASK 0x3000000
+#define VGT_DEBUG_REG26__cm_state12__SHIFT 0x18
+#define VGT_DEBUG_REG26__cm_state13_MASK 0xc000000
+#define VGT_DEBUG_REG26__cm_state13__SHIFT 0x1a
+#define VGT_DEBUG_REG26__cm_state14_MASK 0x30000000
+#define VGT_DEBUG_REG26__cm_state14__SHIFT 0x1c
+#define VGT_DEBUG_REG26__cm_state15_MASK 0xc0000000
+#define VGT_DEBUG_REG26__cm_state15__SHIFT 0x1e
+#define VGT_DEBUG_REG27__pipe0_dr_MASK 0x1
+#define VGT_DEBUG_REG27__pipe0_dr__SHIFT 0x0
+#define VGT_DEBUG_REG27__gsc0_dr_MASK 0x2
+#define VGT_DEBUG_REG27__gsc0_dr__SHIFT 0x1
+#define VGT_DEBUG_REG27__pipe1_dr_MASK 0x4
+#define VGT_DEBUG_REG27__pipe1_dr__SHIFT 0x2
+#define VGT_DEBUG_REG27__tm_pt_event_rtr_MASK 0x8
+#define VGT_DEBUG_REG27__tm_pt_event_rtr__SHIFT 0x3
+#define VGT_DEBUG_REG27__pipe0_rtr_MASK 0x10
+#define VGT_DEBUG_REG27__pipe0_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG27__gsc0_rtr_MASK 0x20
+#define VGT_DEBUG_REG27__gsc0_rtr__SHIFT 0x5
+#define VGT_DEBUG_REG27__pipe1_rtr_MASK 0x40
+#define VGT_DEBUG_REG27__pipe1_rtr__SHIFT 0x6
+#define VGT_DEBUG_REG27__last_indx_of_prim_p1_q_MASK 0x80
+#define VGT_DEBUG_REG27__last_indx_of_prim_p1_q__SHIFT 0x7
+#define VGT_DEBUG_REG27__indices_to_send_p0_q_MASK 0x300
+#define VGT_DEBUG_REG27__indices_to_send_p0_q__SHIFT 0x8
+#define VGT_DEBUG_REG27__event_flag_p1_q_MASK 0x400
+#define VGT_DEBUG_REG27__event_flag_p1_q__SHIFT 0xa
+#define VGT_DEBUG_REG27__eop_p1_q_MASK 0x800
+#define VGT_DEBUG_REG27__eop_p1_q__SHIFT 0xb
+#define VGT_DEBUG_REG27__gs_out_prim_type_p0_q_MASK 0x3000
+#define VGT_DEBUG_REG27__gs_out_prim_type_p0_q__SHIFT 0xc
+#define VGT_DEBUG_REG27__gsc_null_primitive_p0_q_MASK 0x4000
+#define VGT_DEBUG_REG27__gsc_null_primitive_p0_q__SHIFT 0xe
+#define VGT_DEBUG_REG27__gsc_eop_p0_q_MASK 0x8000
+#define VGT_DEBUG_REG27__gsc_eop_p0_q__SHIFT 0xf
+#define VGT_DEBUG_REG27__gsc_2cycle_output_MASK 0x10000
+#define VGT_DEBUG_REG27__gsc_2cycle_output__SHIFT 0x10
+#define VGT_DEBUG_REG27__gsc_2nd_cycle_p0_q_MASK 0x20000
+#define VGT_DEBUG_REG27__gsc_2nd_cycle_p0_q__SHIFT 0x11
+#define VGT_DEBUG_REG27__last_indx_of_vsprim_MASK 0x40000
+#define VGT_DEBUG_REG27__last_indx_of_vsprim__SHIFT 0x12
+#define VGT_DEBUG_REG27__first_vsprim_of_gsprim_p0_q_MASK 0x80000
+#define VGT_DEBUG_REG27__first_vsprim_of_gsprim_p0_q__SHIFT 0x13
+#define VGT_DEBUG_REG27__gsc_indx_count_p0_q_MASK 0x7ff00000
+#define VGT_DEBUG_REG27__gsc_indx_count_p0_q__SHIFT 0x14
+#define VGT_DEBUG_REG27__last_vsprim_of_gsprim_MASK 0x80000000
+#define VGT_DEBUG_REG27__last_vsprim_of_gsprim__SHIFT 0x1f
+#define VGT_DEBUG_REG28__con_state_q_MASK 0xf
+#define VGT_DEBUG_REG28__con_state_q__SHIFT 0x0
+#define VGT_DEBUG_REG28__second_cycle_q_MASK 0x10
+#define VGT_DEBUG_REG28__second_cycle_q__SHIFT 0x4
+#define VGT_DEBUG_REG28__process_tri_middle_p0_q_MASK 0x20
+#define VGT_DEBUG_REG28__process_tri_middle_p0_q__SHIFT 0x5
+#define VGT_DEBUG_REG28__process_tri_1st_2nd_half_p0_q_MASK 0x40
+#define VGT_DEBUG_REG28__process_tri_1st_2nd_half_p0_q__SHIFT 0x6
+#define VGT_DEBUG_REG28__process_tri_center_poly_p0_q_MASK 0x80
+#define VGT_DEBUG_REG28__process_tri_center_poly_p0_q__SHIFT 0x7
+#define VGT_DEBUG_REG28__pipe0_patch_dr_MASK 0x100
+#define VGT_DEBUG_REG28__pipe0_patch_dr__SHIFT 0x8
+#define VGT_DEBUG_REG28__pipe0_edge_dr_MASK 0x200
+#define VGT_DEBUG_REG28__pipe0_edge_dr__SHIFT 0x9
+#define VGT_DEBUG_REG28__pipe1_dr_MASK 0x400
+#define VGT_DEBUG_REG28__pipe1_dr__SHIFT 0xa
+#define VGT_DEBUG_REG28__pipe0_patch_rtr_MASK 0x800
+#define VGT_DEBUG_REG28__pipe0_patch_rtr__SHIFT 0xb
+#define VGT_DEBUG_REG28__pipe0_edge_rtr_MASK 0x1000
+#define VGT_DEBUG_REG28__pipe0_edge_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG28__pipe1_rtr_MASK 0x2000
+#define VGT_DEBUG_REG28__pipe1_rtr__SHIFT 0xd
+#define VGT_DEBUG_REG28__outer_parity_p0_q_MASK 0x4000
+#define VGT_DEBUG_REG28__outer_parity_p0_q__SHIFT 0xe
+#define VGT_DEBUG_REG28__parallel_parity_p0_q_MASK 0x8000
+#define VGT_DEBUG_REG28__parallel_parity_p0_q__SHIFT 0xf
+#define VGT_DEBUG_REG28__first_ring_of_patch_p0_q_MASK 0x10000
+#define VGT_DEBUG_REG28__first_ring_of_patch_p0_q__SHIFT 0x10
+#define VGT_DEBUG_REG28__last_ring_of_patch_p0_q_MASK 0x20000
+#define VGT_DEBUG_REG28__last_ring_of_patch_p0_q__SHIFT 0x11
+#define VGT_DEBUG_REG28__last_edge_of_outer_ring_p0_q_MASK 0x40000
+#define VGT_DEBUG_REG28__last_edge_of_outer_ring_p0_q__SHIFT 0x12
+#define VGT_DEBUG_REG28__last_point_of_outer_ring_p1_MASK 0x80000
+#define VGT_DEBUG_REG28__last_point_of_outer_ring_p1__SHIFT 0x13
+#define VGT_DEBUG_REG28__last_point_of_inner_ring_p1_MASK 0x100000
+#define VGT_DEBUG_REG28__last_point_of_inner_ring_p1__SHIFT 0x14
+#define VGT_DEBUG_REG28__outer_edge_tf_eq_one_p0_q_MASK 0x200000
+#define VGT_DEBUG_REG28__outer_edge_tf_eq_one_p0_q__SHIFT 0x15
+#define VGT_DEBUG_REG28__advance_outer_point_p1_MASK 0x400000
+#define VGT_DEBUG_REG28__advance_outer_point_p1__SHIFT 0x16
+#define VGT_DEBUG_REG28__advance_inner_point_p1_MASK 0x800000
+#define VGT_DEBUG_REG28__advance_inner_point_p1__SHIFT 0x17
+#define VGT_DEBUG_REG28__next_ring_is_rect_p0_q_MASK 0x1000000
+#define VGT_DEBUG_REG28__next_ring_is_rect_p0_q__SHIFT 0x18
+#define VGT_DEBUG_REG28__pipe1_outer1_rtr_MASK 0x2000000
+#define VGT_DEBUG_REG28__pipe1_outer1_rtr__SHIFT 0x19
+#define VGT_DEBUG_REG28__pipe1_outer2_rtr_MASK 0x4000000
+#define VGT_DEBUG_REG28__pipe1_outer2_rtr__SHIFT 0x1a
+#define VGT_DEBUG_REG28__pipe1_inner1_rtr_MASK 0x8000000
+#define VGT_DEBUG_REG28__pipe1_inner1_rtr__SHIFT 0x1b
+#define VGT_DEBUG_REG28__pipe1_inner2_rtr_MASK 0x10000000
+#define VGT_DEBUG_REG28__pipe1_inner2_rtr__SHIFT 0x1c
+#define VGT_DEBUG_REG28__pipe1_patch_rtr_MASK 0x20000000
+#define VGT_DEBUG_REG28__pipe1_patch_rtr__SHIFT 0x1d
+#define VGT_DEBUG_REG28__pipe1_edge_rtr_MASK 0x40000000
+#define VGT_DEBUG_REG28__pipe1_edge_rtr__SHIFT 0x1e
+#define VGT_DEBUG_REG28__use_stored_inner_q_ring2_MASK 0x80000000
+#define VGT_DEBUG_REG28__use_stored_inner_q_ring2__SHIFT 0x1f
+#define VGT_DEBUG_REG29__con_state_q_MASK 0xf
+#define VGT_DEBUG_REG29__con_state_q__SHIFT 0x0
+#define VGT_DEBUG_REG29__second_cycle_q_MASK 0x10
+#define VGT_DEBUG_REG29__second_cycle_q__SHIFT 0x4
+#define VGT_DEBUG_REG29__process_tri_middle_p0_q_MASK 0x20
+#define VGT_DEBUG_REG29__process_tri_middle_p0_q__SHIFT 0x5
+#define VGT_DEBUG_REG29__process_tri_1st_2nd_half_p0_q_MASK 0x40
+#define VGT_DEBUG_REG29__process_tri_1st_2nd_half_p0_q__SHIFT 0x6
+#define VGT_DEBUG_REG29__process_tri_center_poly_p0_q_MASK 0x80
+#define VGT_DEBUG_REG29__process_tri_center_poly_p0_q__SHIFT 0x7
+#define VGT_DEBUG_REG29__pipe0_patch_dr_MASK 0x100
+#define VGT_DEBUG_REG29__pipe0_patch_dr__SHIFT 0x8
+#define VGT_DEBUG_REG29__pipe0_edge_dr_MASK 0x200
+#define VGT_DEBUG_REG29__pipe0_edge_dr__SHIFT 0x9
+#define VGT_DEBUG_REG29__pipe1_dr_MASK 0x400
+#define VGT_DEBUG_REG29__pipe1_dr__SHIFT 0xa
+#define VGT_DEBUG_REG29__pipe0_patch_rtr_MASK 0x800
+#define VGT_DEBUG_REG29__pipe0_patch_rtr__SHIFT 0xb
+#define VGT_DEBUG_REG29__pipe0_edge_rtr_MASK 0x1000
+#define VGT_DEBUG_REG29__pipe0_edge_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG29__pipe1_rtr_MASK 0x2000
+#define VGT_DEBUG_REG29__pipe1_rtr__SHIFT 0xd
+#define VGT_DEBUG_REG29__outer_parity_p0_q_MASK 0x4000
+#define VGT_DEBUG_REG29__outer_parity_p0_q__SHIFT 0xe
+#define VGT_DEBUG_REG29__parallel_parity_p0_q_MASK 0x8000
+#define VGT_DEBUG_REG29__parallel_parity_p0_q__SHIFT 0xf
+#define VGT_DEBUG_REG29__first_ring_of_patch_p0_q_MASK 0x10000
+#define VGT_DEBUG_REG29__first_ring_of_patch_p0_q__SHIFT 0x10
+#define VGT_DEBUG_REG29__last_ring_of_patch_p0_q_MASK 0x20000
+#define VGT_DEBUG_REG29__last_ring_of_patch_p0_q__SHIFT 0x11
+#define VGT_DEBUG_REG29__last_edge_of_outer_ring_p0_q_MASK 0x40000
+#define VGT_DEBUG_REG29__last_edge_of_outer_ring_p0_q__SHIFT 0x12
+#define VGT_DEBUG_REG29__last_point_of_outer_ring_p1_MASK 0x80000
+#define VGT_DEBUG_REG29__last_point_of_outer_ring_p1__SHIFT 0x13
+#define VGT_DEBUG_REG29__last_point_of_inner_ring_p1_MASK 0x100000
+#define VGT_DEBUG_REG29__last_point_of_inner_ring_p1__SHIFT 0x14
+#define VGT_DEBUG_REG29__outer_edge_tf_eq_one_p0_q_MASK 0x200000
+#define VGT_DEBUG_REG29__outer_edge_tf_eq_one_p0_q__SHIFT 0x15
+#define VGT_DEBUG_REG29__advance_outer_point_p1_MASK 0x400000
+#define VGT_DEBUG_REG29__advance_outer_point_p1__SHIFT 0x16
+#define VGT_DEBUG_REG29__advance_inner_point_p1_MASK 0x800000
+#define VGT_DEBUG_REG29__advance_inner_point_p1__SHIFT 0x17
+#define VGT_DEBUG_REG29__next_ring_is_rect_p0_q_MASK 0x1000000
+#define VGT_DEBUG_REG29__next_ring_is_rect_p0_q__SHIFT 0x18
+#define VGT_DEBUG_REG29__pipe1_outer1_rtr_MASK 0x2000000
+#define VGT_DEBUG_REG29__pipe1_outer1_rtr__SHIFT 0x19
+#define VGT_DEBUG_REG29__pipe1_outer2_rtr_MASK 0x4000000
+#define VGT_DEBUG_REG29__pipe1_outer2_rtr__SHIFT 0x1a
+#define VGT_DEBUG_REG29__pipe1_inner1_rtr_MASK 0x8000000
+#define VGT_DEBUG_REG29__pipe1_inner1_rtr__SHIFT 0x1b
+#define VGT_DEBUG_REG29__pipe1_inner2_rtr_MASK 0x10000000
+#define VGT_DEBUG_REG29__pipe1_inner2_rtr__SHIFT 0x1c
+#define VGT_DEBUG_REG29__pipe1_patch_rtr_MASK 0x20000000
+#define VGT_DEBUG_REG29__pipe1_patch_rtr__SHIFT 0x1d
+#define VGT_DEBUG_REG29__pipe1_edge_rtr_MASK 0x40000000
+#define VGT_DEBUG_REG29__pipe1_edge_rtr__SHIFT 0x1e
+#define VGT_DEBUG_REG29__use_stored_inner_q_ring3_MASK 0x80000000
+#define VGT_DEBUG_REG29__use_stored_inner_q_ring3__SHIFT 0x1f
+#define VGT_DEBUG_REG31__pipe0_dr_MASK 0x1
+#define VGT_DEBUG_REG31__pipe0_dr__SHIFT 0x0
+#define VGT_DEBUG_REG31__pipe0_rtr_MASK 0x2
+#define VGT_DEBUG_REG31__pipe0_rtr__SHIFT 0x1
+#define VGT_DEBUG_REG31__pipe1_outer_dr_MASK 0x4
+#define VGT_DEBUG_REG31__pipe1_outer_dr__SHIFT 0x2
+#define VGT_DEBUG_REG31__pipe1_inner_dr_MASK 0x8
+#define VGT_DEBUG_REG31__pipe1_inner_dr__SHIFT 0x3
+#define VGT_DEBUG_REG31__pipe2_outer_dr_MASK 0x10
+#define VGT_DEBUG_REG31__pipe2_outer_dr__SHIFT 0x4
+#define VGT_DEBUG_REG31__pipe2_inner_dr_MASK 0x20
+#define VGT_DEBUG_REG31__pipe2_inner_dr__SHIFT 0x5
+#define VGT_DEBUG_REG31__pipe3_outer_dr_MASK 0x40
+#define VGT_DEBUG_REG31__pipe3_outer_dr__SHIFT 0x6
+#define VGT_DEBUG_REG31__pipe3_inner_dr_MASK 0x80
+#define VGT_DEBUG_REG31__pipe3_inner_dr__SHIFT 0x7
+#define VGT_DEBUG_REG31__pipe4_outer_dr_MASK 0x100
+#define VGT_DEBUG_REG31__pipe4_outer_dr__SHIFT 0x8
+#define VGT_DEBUG_REG31__pipe4_inner_dr_MASK 0x200
+#define VGT_DEBUG_REG31__pipe4_inner_dr__SHIFT 0x9
+#define VGT_DEBUG_REG31__pipe5_outer_dr_MASK 0x400
+#define VGT_DEBUG_REG31__pipe5_outer_dr__SHIFT 0xa
+#define VGT_DEBUG_REG31__pipe5_inner_dr_MASK 0x800
+#define VGT_DEBUG_REG31__pipe5_inner_dr__SHIFT 0xb
+#define VGT_DEBUG_REG31__pipe2_outer_rtr_MASK 0x1000
+#define VGT_DEBUG_REG31__pipe2_outer_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG31__pipe2_inner_rtr_MASK 0x2000
+#define VGT_DEBUG_REG31__pipe2_inner_rtr__SHIFT 0xd
+#define VGT_DEBUG_REG31__pipe3_outer_rtr_MASK 0x4000
+#define VGT_DEBUG_REG31__pipe3_outer_rtr__SHIFT 0xe
+#define VGT_DEBUG_REG31__pipe3_inner_rtr_MASK 0x8000
+#define VGT_DEBUG_REG31__pipe3_inner_rtr__SHIFT 0xf
+#define VGT_DEBUG_REG31__pipe4_outer_rtr_MASK 0x10000
+#define VGT_DEBUG_REG31__pipe4_outer_rtr__SHIFT 0x10
+#define VGT_DEBUG_REG31__pipe4_inner_rtr_MASK 0x20000
+#define VGT_DEBUG_REG31__pipe4_inner_rtr__SHIFT 0x11
+#define VGT_DEBUG_REG31__pipe5_outer_rtr_MASK 0x40000
+#define VGT_DEBUG_REG31__pipe5_outer_rtr__SHIFT 0x12
+#define VGT_DEBUG_REG31__pipe5_inner_rtr_MASK 0x80000
+#define VGT_DEBUG_REG31__pipe5_inner_rtr__SHIFT 0x13
+#define VGT_DEBUG_REG31__pg_con_outer_point1_rts_MASK 0x100000
+#define VGT_DEBUG_REG31__pg_con_outer_point1_rts__SHIFT 0x14
+#define VGT_DEBUG_REG31__pg_con_outer_point2_rts_MASK 0x200000
+#define VGT_DEBUG_REG31__pg_con_outer_point2_rts__SHIFT 0x15
+#define VGT_DEBUG_REG31__pg_con_inner_point1_rts_MASK 0x400000
+#define VGT_DEBUG_REG31__pg_con_inner_point1_rts__SHIFT 0x16
+#define VGT_DEBUG_REG31__pg_con_inner_point2_rts_MASK 0x800000
+#define VGT_DEBUG_REG31__pg_con_inner_point2_rts__SHIFT 0x17
+#define VGT_DEBUG_REG31__pg_patch_fifo_empty_MASK 0x1000000
+#define VGT_DEBUG_REG31__pg_patch_fifo_empty__SHIFT 0x18
+#define VGT_DEBUG_REG31__pg_edge_fifo_empty_MASK 0x2000000
+#define VGT_DEBUG_REG31__pg_edge_fifo_empty__SHIFT 0x19
+#define VGT_DEBUG_REG31__pg_inner3_perp_fifo_empty_MASK 0x4000000
+#define VGT_DEBUG_REG31__pg_inner3_perp_fifo_empty__SHIFT 0x1a
+#define VGT_DEBUG_REG31__pg_patch_fifo_full_MASK 0x8000000
+#define VGT_DEBUG_REG31__pg_patch_fifo_full__SHIFT 0x1b
+#define VGT_DEBUG_REG31__pg_edge_fifo_full_MASK 0x10000000
+#define VGT_DEBUG_REG31__pg_edge_fifo_full__SHIFT 0x1c
+#define VGT_DEBUG_REG31__pg_inner_perp_fifo_full_MASK 0x20000000
+#define VGT_DEBUG_REG31__pg_inner_perp_fifo_full__SHIFT 0x1d
+#define VGT_DEBUG_REG31__outer_ring_done_q_MASK 0x40000000
+#define VGT_DEBUG_REG31__outer_ring_done_q__SHIFT 0x1e
+#define VGT_DEBUG_REG31__inner_ring_done_q_MASK 0x80000000
+#define VGT_DEBUG_REG31__inner_ring_done_q__SHIFT 0x1f
+#define VGT_DEBUG_REG32__first_ring_of_patch_MASK 0x1
+#define VGT_DEBUG_REG32__first_ring_of_patch__SHIFT 0x0
+#define VGT_DEBUG_REG32__last_ring_of_patch_MASK 0x2
+#define VGT_DEBUG_REG32__last_ring_of_patch__SHIFT 0x1
+#define VGT_DEBUG_REG32__last_edge_of_outer_ring_MASK 0x4
+#define VGT_DEBUG_REG32__last_edge_of_outer_ring__SHIFT 0x2
+#define VGT_DEBUG_REG32__last_point_of_outer_edge_MASK 0x8
+#define VGT_DEBUG_REG32__last_point_of_outer_edge__SHIFT 0x3
+#define VGT_DEBUG_REG32__last_edge_of_inner_ring_MASK 0x10
+#define VGT_DEBUG_REG32__last_edge_of_inner_ring__SHIFT 0x4
+#define VGT_DEBUG_REG32__last_point_of_inner_edge_MASK 0x20
+#define VGT_DEBUG_REG32__last_point_of_inner_edge__SHIFT 0x5
+#define VGT_DEBUG_REG32__last_patch_of_tg_p0_q_MASK 0x40
+#define VGT_DEBUG_REG32__last_patch_of_tg_p0_q__SHIFT 0x6
+#define VGT_DEBUG_REG32__event_null_special_p0_q_MASK 0x80
+#define VGT_DEBUG_REG32__event_null_special_p0_q__SHIFT 0x7
+#define VGT_DEBUG_REG32__event_flag_p5_q_MASK 0x100
+#define VGT_DEBUG_REG32__event_flag_p5_q__SHIFT 0x8
+#define VGT_DEBUG_REG32__first_point_of_patch_p5_q_MASK 0x200
+#define VGT_DEBUG_REG32__first_point_of_patch_p5_q__SHIFT 0x9
+#define VGT_DEBUG_REG32__first_point_of_edge_p5_q_MASK 0x400
+#define VGT_DEBUG_REG32__first_point_of_edge_p5_q__SHIFT 0xa
+#define VGT_DEBUG_REG32__last_patch_of_tg_p5_q_MASK 0x800
+#define VGT_DEBUG_REG32__last_patch_of_tg_p5_q__SHIFT 0xb
+#define VGT_DEBUG_REG32__tess_topology_p5_q_MASK 0x3000
+#define VGT_DEBUG_REG32__tess_topology_p5_q__SHIFT 0xc
+#define VGT_DEBUG_REG32__pipe5_inner3_rtr_MASK 0x4000
+#define VGT_DEBUG_REG32__pipe5_inner3_rtr__SHIFT 0xe
+#define VGT_DEBUG_REG32__pipe5_inner2_rtr_MASK 0x8000
+#define VGT_DEBUG_REG32__pipe5_inner2_rtr__SHIFT 0xf
+#define VGT_DEBUG_REG32__pg_edge_fifo3_full_MASK 0x10000
+#define VGT_DEBUG_REG32__pg_edge_fifo3_full__SHIFT 0x10
+#define VGT_DEBUG_REG32__pg_edge_fifo2_full_MASK 0x20000
+#define VGT_DEBUG_REG32__pg_edge_fifo2_full__SHIFT 0x11
+#define VGT_DEBUG_REG32__pg_inner3_point_fifo_full_MASK 0x40000
+#define VGT_DEBUG_REG32__pg_inner3_point_fifo_full__SHIFT 0x12
+#define VGT_DEBUG_REG32__pg_outer3_point_fifo_full_MASK 0x80000
+#define VGT_DEBUG_REG32__pg_outer3_point_fifo_full__SHIFT 0x13
+#define VGT_DEBUG_REG32__pg_inner2_point_fifo_full_MASK 0x100000
+#define VGT_DEBUG_REG32__pg_inner2_point_fifo_full__SHIFT 0x14
+#define VGT_DEBUG_REG32__pg_outer2_point_fifo_full_MASK 0x200000
+#define VGT_DEBUG_REG32__pg_outer2_point_fifo_full__SHIFT 0x15
+#define VGT_DEBUG_REG32__pg_inner_point_fifo_full_MASK 0x400000
+#define VGT_DEBUG_REG32__pg_inner_point_fifo_full__SHIFT 0x16
+#define VGT_DEBUG_REG32__pg_outer_point_fifo_full_MASK 0x800000
+#define VGT_DEBUG_REG32__pg_outer_point_fifo_full__SHIFT 0x17
+#define VGT_DEBUG_REG32__inner2_fifos_rtr_MASK 0x1000000
+#define VGT_DEBUG_REG32__inner2_fifos_rtr__SHIFT 0x18
+#define VGT_DEBUG_REG32__inner_fifos_rtr_MASK 0x2000000
+#define VGT_DEBUG_REG32__inner_fifos_rtr__SHIFT 0x19
+#define VGT_DEBUG_REG32__outer_fifos_rtr_MASK 0x4000000
+#define VGT_DEBUG_REG32__outer_fifos_rtr__SHIFT 0x1a
+#define VGT_DEBUG_REG32__fifos_rtr_MASK 0x8000000
+#define VGT_DEBUG_REG32__fifos_rtr__SHIFT 0x1b
+#define VGT_DEBUG_REG32__SPARE_MASK 0xf0000000
+#define VGT_DEBUG_REG32__SPARE__SHIFT 0x1c
+#define VGT_DEBUG_REG33__pipe0_patch_dr_MASK 0x1
+#define VGT_DEBUG_REG33__pipe0_patch_dr__SHIFT 0x0
+#define VGT_DEBUG_REG33__ring3_pipe1_dr_MASK 0x2
+#define VGT_DEBUG_REG33__ring3_pipe1_dr__SHIFT 0x1
+#define VGT_DEBUG_REG33__pipe1_dr_MASK 0x4
+#define VGT_DEBUG_REG33__pipe1_dr__SHIFT 0x2
+#define VGT_DEBUG_REG33__pipe2_dr_MASK 0x8
+#define VGT_DEBUG_REG33__pipe2_dr__SHIFT 0x3
+#define VGT_DEBUG_REG33__pipe0_patch_rtr_MASK 0x10
+#define VGT_DEBUG_REG33__pipe0_patch_rtr__SHIFT 0x4
+#define VGT_DEBUG_REG33__ring2_pipe1_dr_MASK 0x20
+#define VGT_DEBUG_REG33__ring2_pipe1_dr__SHIFT 0x5
+#define VGT_DEBUG_REG33__ring1_pipe1_dr_MASK 0x40
+#define VGT_DEBUG_REG33__ring1_pipe1_dr__SHIFT 0x6
+#define VGT_DEBUG_REG33__pipe2_rtr_MASK 0x80
+#define VGT_DEBUG_REG33__pipe2_rtr__SHIFT 0x7
+#define VGT_DEBUG_REG33__pipe3_dr_MASK 0x100
+#define VGT_DEBUG_REG33__pipe3_dr__SHIFT 0x8
+#define VGT_DEBUG_REG33__pipe3_rtr_MASK 0x200
+#define VGT_DEBUG_REG33__pipe3_rtr__SHIFT 0x9
+#define VGT_DEBUG_REG33__ring2_in_sync_q_MASK 0x400
+#define VGT_DEBUG_REG33__ring2_in_sync_q__SHIFT 0xa
+#define VGT_DEBUG_REG33__ring1_in_sync_q_MASK 0x800
+#define VGT_DEBUG_REG33__ring1_in_sync_q__SHIFT 0xb
+#define VGT_DEBUG_REG33__pipe1_patch_rtr_MASK 0x1000
+#define VGT_DEBUG_REG33__pipe1_patch_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG33__ring3_in_sync_q_MASK 0x2000
+#define VGT_DEBUG_REG33__ring3_in_sync_q__SHIFT 0xd
+#define VGT_DEBUG_REG33__tm_te11_event_rtr_MASK 0x4000
+#define VGT_DEBUG_REG33__tm_te11_event_rtr__SHIFT 0xe
+#define VGT_DEBUG_REG33__first_prim_of_patch_q_MASK 0x8000
+#define VGT_DEBUG_REG33__first_prim_of_patch_q__SHIFT 0xf
+#define VGT_DEBUG_REG33__con_prim_fifo_full_MASK 0x10000
+#define VGT_DEBUG_REG33__con_prim_fifo_full__SHIFT 0x10
+#define VGT_DEBUG_REG33__con_vert_fifo_full_MASK 0x20000
+#define VGT_DEBUG_REG33__con_vert_fifo_full__SHIFT 0x11
+#define VGT_DEBUG_REG33__con_prim_fifo_empty_MASK 0x40000
+#define VGT_DEBUG_REG33__con_prim_fifo_empty__SHIFT 0x12
+#define VGT_DEBUG_REG33__con_vert_fifo_empty_MASK 0x80000
+#define VGT_DEBUG_REG33__con_vert_fifo_empty__SHIFT 0x13
+#define VGT_DEBUG_REG33__last_patch_of_tg_p0_q_MASK 0x100000
+#define VGT_DEBUG_REG33__last_patch_of_tg_p0_q__SHIFT 0x14
+#define VGT_DEBUG_REG33__ring3_valid_p2_MASK 0x200000
+#define VGT_DEBUG_REG33__ring3_valid_p2__SHIFT 0x15
+#define VGT_DEBUG_REG33__ring2_valid_p2_MASK 0x400000
+#define VGT_DEBUG_REG33__ring2_valid_p2__SHIFT 0x16
+#define VGT_DEBUG_REG33__ring1_valid_p2_MASK 0x800000
+#define VGT_DEBUG_REG33__ring1_valid_p2__SHIFT 0x17
+#define VGT_DEBUG_REG33__tess_type_p0_q_MASK 0x3000000
+#define VGT_DEBUG_REG33__tess_type_p0_q__SHIFT 0x18
+#define VGT_DEBUG_REG33__tess_topology_p0_q_MASK 0xc000000
+#define VGT_DEBUG_REG33__tess_topology_p0_q__SHIFT 0x1a
+#define VGT_DEBUG_REG33__te11_out_vert_gs_en_MASK 0x10000000
+#define VGT_DEBUG_REG33__te11_out_vert_gs_en__SHIFT 0x1c
+#define VGT_DEBUG_REG33__con_ring3_busy_MASK 0x20000000
+#define VGT_DEBUG_REG33__con_ring3_busy__SHIFT 0x1d
+#define VGT_DEBUG_REG33__con_ring2_busy_MASK 0x40000000
+#define VGT_DEBUG_REG33__con_ring2_busy__SHIFT 0x1e
+#define VGT_DEBUG_REG33__con_ring1_busy_MASK 0x80000000
+#define VGT_DEBUG_REG33__con_ring1_busy__SHIFT 0x1f
+#define VGT_DEBUG_REG34__con_state_q_MASK 0xf
+#define VGT_DEBUG_REG34__con_state_q__SHIFT 0x0
+#define VGT_DEBUG_REG34__second_cycle_q_MASK 0x10
+#define VGT_DEBUG_REG34__second_cycle_q__SHIFT 0x4
+#define VGT_DEBUG_REG34__process_tri_middle_p0_q_MASK 0x20
+#define VGT_DEBUG_REG34__process_tri_middle_p0_q__SHIFT 0x5
+#define VGT_DEBUG_REG34__process_tri_1st_2nd_half_p0_q_MASK 0x40
+#define VGT_DEBUG_REG34__process_tri_1st_2nd_half_p0_q__SHIFT 0x6
+#define VGT_DEBUG_REG34__process_tri_center_poly_p0_q_MASK 0x80
+#define VGT_DEBUG_REG34__process_tri_center_poly_p0_q__SHIFT 0x7
+#define VGT_DEBUG_REG34__pipe0_patch_dr_MASK 0x100
+#define VGT_DEBUG_REG34__pipe0_patch_dr__SHIFT 0x8
+#define VGT_DEBUG_REG34__pipe0_edge_dr_MASK 0x200
+#define VGT_DEBUG_REG34__pipe0_edge_dr__SHIFT 0x9
+#define VGT_DEBUG_REG34__pipe1_dr_MASK 0x400
+#define VGT_DEBUG_REG34__pipe1_dr__SHIFT 0xa
+#define VGT_DEBUG_REG34__pipe0_patch_rtr_MASK 0x800
+#define VGT_DEBUG_REG34__pipe0_patch_rtr__SHIFT 0xb
+#define VGT_DEBUG_REG34__pipe0_edge_rtr_MASK 0x1000
+#define VGT_DEBUG_REG34__pipe0_edge_rtr__SHIFT 0xc
+#define VGT_DEBUG_REG34__pipe1_rtr_MASK 0x2000
+#define VGT_DEBUG_REG34__pipe1_rtr__SHIFT 0xd
+#define VGT_DEBUG_REG34__outer_parity_p0_q_MASK 0x4000
+#define VGT_DEBUG_REG34__outer_parity_p0_q__SHIFT 0xe
+#define VGT_DEBUG_REG34__parallel_parity_p0_q_MASK 0x8000
+#define VGT_DEBUG_REG34__parallel_parity_p0_q__SHIFT 0xf
+#define VGT_DEBUG_REG34__first_ring_of_patch_p0_q_MASK 0x10000
+#define VGT_DEBUG_REG34__first_ring_of_patch_p0_q__SHIFT 0x10
+#define VGT_DEBUG_REG34__last_ring_of_patch_p0_q_MASK 0x20000
+#define VGT_DEBUG_REG34__last_ring_of_patch_p0_q__SHIFT 0x11
+#define VGT_DEBUG_REG34__last_edge_of_outer_ring_p0_q_MASK 0x40000
+#define VGT_DEBUG_REG34__last_edge_of_outer_ring_p0_q__SHIFT 0x12
+#define VGT_DEBUG_REG34__last_point_of_outer_ring_p1_MASK 0x80000
+#define VGT_DEBUG_REG34__last_point_of_outer_ring_p1__SHIFT 0x13
+#define VGT_DEBUG_REG34__last_point_of_inner_ring_p1_MASK 0x100000
+#define VGT_DEBUG_REG34__last_point_of_inner_ring_p1__SHIFT 0x14
+#define VGT_DEBUG_REG34__outer_edge_tf_eq_one_p0_q_MASK 0x200000
+#define VGT_DEBUG_REG34__outer_edge_tf_eq_one_p0_q__SHIFT 0x15
+#define VGT_DEBUG_REG34__advance_outer_point_p1_MASK 0x400000
+#define VGT_DEBUG_REG34__advance_outer_point_p1__SHIFT 0x16
+#define VGT_DEBUG_REG34__advance_inner_point_p1_MASK 0x800000
+#define VGT_DEBUG_REG34__advance_inner_point_p1__SHIFT 0x17
+#define VGT_DEBUG_REG34__next_ring_is_rect_p0_q_MASK 0x1000000
+#define VGT_DEBUG_REG34__next_ring_is_rect_p0_q__SHIFT 0x18
+#define VGT_DEBUG_REG34__pipe1_outer1_rtr_MASK 0x2000000
+#define VGT_DEBUG_REG34__pipe1_outer1_rtr__SHIFT 0x19
+#define VGT_DEBUG_REG34__pipe1_outer2_rtr_MASK 0x4000000
+#define VGT_DEBUG_REG34__pipe1_outer2_rtr__SHIFT 0x1a
+#define VGT_DEBUG_REG34__pipe1_inner1_rtr_MASK 0x8000000
+#define VGT_DEBUG_REG34__pipe1_inner1_rtr__SHIFT 0x1b
+#define VGT_DEBUG_REG34__pipe1_inner2_rtr_MASK 0x10000000
+#define VGT_DEBUG_REG34__pipe1_inner2_rtr__SHIFT 0x1c
+#define VGT_DEBUG_REG34__pipe1_patch_rtr_MASK 0x20000000
+#define VGT_DEBUG_REG34__pipe1_patch_rtr__SHIFT 0x1d
+#define VGT_DEBUG_REG34__pipe1_edge_rtr_MASK 0x40000000
+#define VGT_DEBUG_REG34__pipe1_edge_rtr__SHIFT 0x1e
+#define VGT_DEBUG_REG34__use_stored_inner_q_ring1_MASK 0x80000000
+#define VGT_DEBUG_REG34__use_stored_inner_q_ring1__SHIFT 0x1f
+#define VGT_DEBUG_REG36__VGT_PA_clipp_eop_MASK 0xffffffff
+#define VGT_DEBUG_REG36__VGT_PA_clipp_eop__SHIFT 0x0
+#define VGT_PERFCOUNTER_SEID_MASK__PERF_SEID_IGNORE_MASK_MASK 0xff
+#define VGT_PERFCOUNTER_SEID_MASK__PERF_SEID_IGNORE_MASK__SHIFT 0x0
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define VGT_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define VGT_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x3ff
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0xffc00
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0xa
+#define VGT_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0xf00000
+#define VGT_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x14
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0xf000000
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x18
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define VGT_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0xff
+#define VGT_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define VGT_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define VGT_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define VGT_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0xff
+#define VGT_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define VGT_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define VGT_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x3ff
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x0
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0xffc00
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0xa
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf000000
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x18
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define VGT_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define VGT_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define VGT_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define VGT_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define VGT_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define VGT_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define VGT_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define VGT_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define VGT_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define VGT_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define VGT_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define VGT_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define VGT_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define VGT_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define VGT_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define VGT_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x3ff
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0xffc00
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0xa
+#define IA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0xf00000
+#define IA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x14
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0xf000000
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x18
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define IA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0xff
+#define IA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define IA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define IA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define IA_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0xff
+#define IA_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define IA_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define IA_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define IA_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0xff
+#define IA_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define IA_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define IA_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x3ff
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x0
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0xffc00
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0xa
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf000000
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x18
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x1c
+#define IA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define IA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define IA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define IA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define IA_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define IA_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define IA_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define IA_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define IA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define IA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define IA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define IA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define IA_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define IA_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define IA_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define IA_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define WD_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0xff
+#define WD_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x0
+#define WD_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000
+#define WD_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x1c
+#define WD_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0xff
+#define WD_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x0
+#define WD_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000
+#define WD_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x1c
+#define WD_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0xff
+#define WD_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x0
+#define WD_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000
+#define WD_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x1c
+#define WD_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0xff
+#define WD_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x0
+#define WD_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000
+#define WD_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x1c
+#define WD_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define WD_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define WD_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define WD_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define WD_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define WD_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define WD_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffff
+#define WD_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x0
+#define WD_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define WD_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define WD_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define WD_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define WD_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define WD_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define WD_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffff
+#define WD_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x0
+#define DIDT_IND_INDEX__DIDT_IND_INDEX_MASK 0xffffffff
+#define DIDT_IND_INDEX__DIDT_IND_INDEX__SHIFT 0x0
+#define DIDT_IND_DATA__DIDT_IND_DATA_MASK 0xffffffff
+#define DIDT_IND_DATA__DIDT_IND_DATA__SHIFT 0x0
+#define DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK 0x1
+#define DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT 0x0
+#define DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK 0x2
+#define DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT 0x1
+#define DIDT_SQ_CTRL0__PHASE_OFFSET_MASK 0xc
+#define DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT 0x2
+#define DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK 0x10
+#define DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT 0x4
+#define DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK 0x20
+#define DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT 0x5
+#define DIDT_SQ_CTRL0__UNUSED_0_MASK 0xffffffc0
+#define DIDT_SQ_CTRL0__UNUSED_0__SHIFT 0x6
+#define DIDT_SQ_CTRL1__MIN_POWER_MASK 0xffff
+#define DIDT_SQ_CTRL1__MIN_POWER__SHIFT 0x0
+#define DIDT_SQ_CTRL1__MAX_POWER_MASK 0xffff0000
+#define DIDT_SQ_CTRL1__MAX_POWER__SHIFT 0x10
+#define DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK 0x3fff
+#define DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT 0x0
+#define DIDT_SQ_CTRL2__UNUSED_0_MASK 0xc000
+#define DIDT_SQ_CTRL2__UNUSED_0__SHIFT 0xe
+#define DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK 0x3ff0000
+#define DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x10
+#define DIDT_SQ_CTRL2__UNUSED_1_MASK 0x4000000
+#define DIDT_SQ_CTRL2__UNUSED_1__SHIFT 0x1a
+#define DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000
+#define DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x1b
+#define DIDT_SQ_CTRL2__UNUSED_2_MASK 0x80000000
+#define DIDT_SQ_CTRL2__UNUSED_2__SHIFT 0x1f
+#define DIDT_SQ_CTRL_OCP__UNUSED_0_MASK 0xffff
+#define DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT 0x0
+#define DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK 0xffff0000
+#define DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT 0x10
+#define DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK 0xff
+#define DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT 0x0
+#define DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK 0xff00
+#define DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT 0x8
+#define DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK 0xff0000
+#define DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT 0x10
+#define DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK 0xff000000
+#define DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT 0x18
+#define DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK 0xff
+#define DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT 0x0
+#define DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK 0xff00
+#define DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT 0x8
+#define DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK 0xff0000
+#define DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT 0x10
+#define DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK 0xff000000
+#define DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT 0x18
+#define DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK 0xff
+#define DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT 0x0
+#define DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK 0xff00
+#define DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT 0x8
+#define DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK 0xff0000
+#define DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT 0x10
+#define DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK 0xff000000
+#define DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT 0x18
+#define DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK 0x1
+#define DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT 0x0
+#define DIDT_DB_CTRL0__USE_REF_CLOCK_MASK 0x2
+#define DIDT_DB_CTRL0__USE_REF_CLOCK__SHIFT 0x1
+#define DIDT_DB_CTRL0__PHASE_OFFSET_MASK 0xc
+#define DIDT_DB_CTRL0__PHASE_OFFSET__SHIFT 0x2
+#define DIDT_DB_CTRL0__DIDT_CTRL_RST_MASK 0x10
+#define DIDT_DB_CTRL0__DIDT_CTRL_RST__SHIFT 0x4
+#define DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK 0x20
+#define DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT 0x5
+#define DIDT_DB_CTRL0__UNUSED_0_MASK 0xffffffc0
+#define DIDT_DB_CTRL0__UNUSED_0__SHIFT 0x6
+#define DIDT_DB_CTRL1__MIN_POWER_MASK 0xffff
+#define DIDT_DB_CTRL1__MIN_POWER__SHIFT 0x0
+#define DIDT_DB_CTRL1__MAX_POWER_MASK 0xffff0000
+#define DIDT_DB_CTRL1__MAX_POWER__SHIFT 0x10
+#define DIDT_DB_CTRL2__MAX_POWER_DELTA_MASK 0x3fff
+#define DIDT_DB_CTRL2__MAX_POWER_DELTA__SHIFT 0x0
+#define DIDT_DB_CTRL2__UNUSED_0_MASK 0xc000
+#define DIDT_DB_CTRL2__UNUSED_0__SHIFT 0xe
+#define DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK 0x3ff0000
+#define DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x10
+#define DIDT_DB_CTRL2__UNUSED_1_MASK 0x4000000
+#define DIDT_DB_CTRL2__UNUSED_1__SHIFT 0x1a
+#define DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000
+#define DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x1b
+#define DIDT_DB_CTRL2__UNUSED_2_MASK 0x80000000
+#define DIDT_DB_CTRL2__UNUSED_2__SHIFT 0x1f
+#define DIDT_DB_CTRL_OCP__UNUSED_0_MASK 0xffff
+#define DIDT_DB_CTRL_OCP__UNUSED_0__SHIFT 0x0
+#define DIDT_DB_CTRL_OCP__OCP_MAX_POWER_MASK 0xffff0000
+#define DIDT_DB_CTRL_OCP__OCP_MAX_POWER__SHIFT 0x10
+#define DIDT_DB_WEIGHT0_3__WEIGHT0_MASK 0xff
+#define DIDT_DB_WEIGHT0_3__WEIGHT0__SHIFT 0x0
+#define DIDT_DB_WEIGHT0_3__WEIGHT1_MASK 0xff00
+#define DIDT_DB_WEIGHT0_3__WEIGHT1__SHIFT 0x8
+#define DIDT_DB_WEIGHT0_3__WEIGHT2_MASK 0xff0000
+#define DIDT_DB_WEIGHT0_3__WEIGHT2__SHIFT 0x10
+#define DIDT_DB_WEIGHT0_3__WEIGHT3_MASK 0xff000000
+#define DIDT_DB_WEIGHT0_3__WEIGHT3__SHIFT 0x18
+#define DIDT_DB_WEIGHT4_7__WEIGHT4_MASK 0xff
+#define DIDT_DB_WEIGHT4_7__WEIGHT4__SHIFT 0x0
+#define DIDT_DB_WEIGHT4_7__WEIGHT5_MASK 0xff00
+#define DIDT_DB_WEIGHT4_7__WEIGHT5__SHIFT 0x8
+#define DIDT_DB_WEIGHT4_7__WEIGHT6_MASK 0xff0000
+#define DIDT_DB_WEIGHT4_7__WEIGHT6__SHIFT 0x10
+#define DIDT_DB_WEIGHT4_7__WEIGHT7_MASK 0xff000000
+#define DIDT_DB_WEIGHT4_7__WEIGHT7__SHIFT 0x18
+#define DIDT_DB_WEIGHT8_11__WEIGHT8_MASK 0xff
+#define DIDT_DB_WEIGHT8_11__WEIGHT8__SHIFT 0x0
+#define DIDT_DB_WEIGHT8_11__WEIGHT9_MASK 0xff00
+#define DIDT_DB_WEIGHT8_11__WEIGHT9__SHIFT 0x8
+#define DIDT_DB_WEIGHT8_11__WEIGHT10_MASK 0xff0000
+#define DIDT_DB_WEIGHT8_11__WEIGHT10__SHIFT 0x10
+#define DIDT_DB_WEIGHT8_11__WEIGHT11_MASK 0xff000000
+#define DIDT_DB_WEIGHT8_11__WEIGHT11__SHIFT 0x18
+#define DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK 0x1
+#define DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT 0x0
+#define DIDT_TD_CTRL0__USE_REF_CLOCK_MASK 0x2
+#define DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT 0x1
+#define DIDT_TD_CTRL0__PHASE_OFFSET_MASK 0xc
+#define DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT 0x2
+#define DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK 0x10
+#define DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT 0x4
+#define DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK 0x20
+#define DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT 0x5
+#define DIDT_TD_CTRL0__UNUSED_0_MASK 0xffffffc0
+#define DIDT_TD_CTRL0__UNUSED_0__SHIFT 0x6
+#define DIDT_TD_CTRL1__MIN_POWER_MASK 0xffff
+#define DIDT_TD_CTRL1__MIN_POWER__SHIFT 0x0
+#define DIDT_TD_CTRL1__MAX_POWER_MASK 0xffff0000
+#define DIDT_TD_CTRL1__MAX_POWER__SHIFT 0x10
+#define DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK 0x3fff
+#define DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT 0x0
+#define DIDT_TD_CTRL2__UNUSED_0_MASK 0xc000
+#define DIDT_TD_CTRL2__UNUSED_0__SHIFT 0xe
+#define DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK 0x3ff0000
+#define DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x10
+#define DIDT_TD_CTRL2__UNUSED_1_MASK 0x4000000
+#define DIDT_TD_CTRL2__UNUSED_1__SHIFT 0x1a
+#define DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000
+#define DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x1b
+#define DIDT_TD_CTRL2__UNUSED_2_MASK 0x80000000
+#define DIDT_TD_CTRL2__UNUSED_2__SHIFT 0x1f
+#define DIDT_TD_CTRL_OCP__UNUSED_0_MASK 0xffff
+#define DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT 0x0
+#define DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK 0xffff0000
+#define DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT 0x10
+#define DIDT_TD_WEIGHT0_3__WEIGHT0_MASK 0xff
+#define DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT 0x0
+#define DIDT_TD_WEIGHT0_3__WEIGHT1_MASK 0xff00
+#define DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT 0x8
+#define DIDT_TD_WEIGHT0_3__WEIGHT2_MASK 0xff0000
+#define DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT 0x10
+#define DIDT_TD_WEIGHT0_3__WEIGHT3_MASK 0xff000000
+#define DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT 0x18
+#define DIDT_TD_WEIGHT4_7__WEIGHT4_MASK 0xff
+#define DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT 0x0
+#define DIDT_TD_WEIGHT4_7__WEIGHT5_MASK 0xff00
+#define DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT 0x8
+#define DIDT_TD_WEIGHT4_7__WEIGHT6_MASK 0xff0000
+#define DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT 0x10
+#define DIDT_TD_WEIGHT4_7__WEIGHT7_MASK 0xff000000
+#define DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT 0x18
+#define DIDT_TD_WEIGHT8_11__WEIGHT8_MASK 0xff
+#define DIDT_TD_WEIGHT8_11__WEIGHT8__SHIFT 0x0
+#define DIDT_TD_WEIGHT8_11__WEIGHT9_MASK 0xff00
+#define DIDT_TD_WEIGHT8_11__WEIGHT9__SHIFT 0x8
+#define DIDT_TD_WEIGHT8_11__WEIGHT10_MASK 0xff0000
+#define DIDT_TD_WEIGHT8_11__WEIGHT10__SHIFT 0x10
+#define DIDT_TD_WEIGHT8_11__WEIGHT11_MASK 0xff000000
+#define DIDT_TD_WEIGHT8_11__WEIGHT11__SHIFT 0x18
+#define DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK 0x1
+#define DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT 0x0
+#define DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK 0x2
+#define DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT 0x1
+#define DIDT_TCP_CTRL0__PHASE_OFFSET_MASK 0xc
+#define DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT 0x2
+#define DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK 0x10
+#define DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT 0x4
+#define DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK 0x20
+#define DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT 0x5
+#define DIDT_TCP_CTRL0__UNUSED_0_MASK 0xffffffc0
+#define DIDT_TCP_CTRL0__UNUSED_0__SHIFT 0x6
+#define DIDT_TCP_CTRL1__MIN_POWER_MASK 0xffff
+#define DIDT_TCP_CTRL1__MIN_POWER__SHIFT 0x0
+#define DIDT_TCP_CTRL1__MAX_POWER_MASK 0xffff0000
+#define DIDT_TCP_CTRL1__MAX_POWER__SHIFT 0x10
+#define DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK 0x3fff
+#define DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT 0x0
+#define DIDT_TCP_CTRL2__UNUSED_0_MASK 0xc000
+#define DIDT_TCP_CTRL2__UNUSED_0__SHIFT 0xe
+#define DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK 0x3ff0000
+#define DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x10
+#define DIDT_TCP_CTRL2__UNUSED_1_MASK 0x4000000
+#define DIDT_TCP_CTRL2__UNUSED_1__SHIFT 0x1a
+#define DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000
+#define DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x1b
+#define DIDT_TCP_CTRL2__UNUSED_2_MASK 0x80000000
+#define DIDT_TCP_CTRL2__UNUSED_2__SHIFT 0x1f
+#define DIDT_TCP_CTRL_OCP__UNUSED_0_MASK 0xffff
+#define DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT 0x0
+#define DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK 0xffff0000
+#define DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT 0x10
+#define DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK 0xff
+#define DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT 0x0
+#define DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK 0xff00
+#define DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT 0x8
+#define DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK 0xff0000
+#define DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT 0x10
+#define DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK 0xff000000
+#define DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT 0x18
+#define DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK 0xff
+#define DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT 0x0
+#define DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK 0xff00
+#define DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT 0x8
+#define DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK 0xff0000
+#define DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT 0x10
+#define DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK 0xff000000
+#define DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT 0x18
+#define DIDT_TCP_WEIGHT8_11__WEIGHT8_MASK 0xff
+#define DIDT_TCP_WEIGHT8_11__WEIGHT8__SHIFT 0x0
+#define DIDT_TCP_WEIGHT8_11__WEIGHT9_MASK 0xff00
+#define DIDT_TCP_WEIGHT8_11__WEIGHT9__SHIFT 0x8
+#define DIDT_TCP_WEIGHT8_11__WEIGHT10_MASK 0xff0000
+#define DIDT_TCP_WEIGHT8_11__WEIGHT10__SHIFT 0x10
+#define DIDT_TCP_WEIGHT8_11__WEIGHT11_MASK 0xff000000
+#define DIDT_TCP_WEIGHT8_11__WEIGHT11__SHIFT 0x18
+#define DIDT_DBR_CTRL0__DIDT_CTRL_EN_MASK 0x1
+#define DIDT_DBR_CTRL0__DIDT_CTRL_EN__SHIFT 0x0
+#define DIDT_DBR_CTRL0__USE_REF_CLOCK_MASK 0x2
+#define DIDT_DBR_CTRL0__USE_REF_CLOCK__SHIFT 0x1
+#define DIDT_DBR_CTRL0__PHASE_OFFSET_MASK 0xc
+#define DIDT_DBR_CTRL0__PHASE_OFFSET__SHIFT 0x2
+#define DIDT_DBR_CTRL0__DIDT_CTRL_RST_MASK 0x10
+#define DIDT_DBR_CTRL0__DIDT_CTRL_RST__SHIFT 0x4
+#define DIDT_DBR_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK 0x20
+#define DIDT_DBR_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT 0x5
+#define DIDT_DBR_CTRL0__UNUSED_0_MASK 0xffffffc0
+#define DIDT_DBR_CTRL0__UNUSED_0__SHIFT 0x6
+#define DIDT_DBR_CTRL1__MIN_POWER_MASK 0xffff
+#define DIDT_DBR_CTRL1__MIN_POWER__SHIFT 0x0
+#define DIDT_DBR_CTRL1__MAX_POWER_MASK 0xffff0000
+#define DIDT_DBR_CTRL1__MAX_POWER__SHIFT 0x10
+#define DIDT_DBR_CTRL2__MAX_POWER_DELTA_MASK 0x3fff
+#define DIDT_DBR_CTRL2__MAX_POWER_DELTA__SHIFT 0x0
+#define DIDT_DBR_CTRL2__UNUSED_0_MASK 0xc000
+#define DIDT_DBR_CTRL2__UNUSED_0__SHIFT 0xe
+#define DIDT_DBR_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK 0x3ff0000
+#define DIDT_DBR_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x10
+#define DIDT_DBR_CTRL2__UNUSED_1_MASK 0x4000000
+#define DIDT_DBR_CTRL2__UNUSED_1__SHIFT 0x1a
+#define DIDT_DBR_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000
+#define DIDT_DBR_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x1b
+#define DIDT_DBR_CTRL2__UNUSED_2_MASK 0x80000000
+#define DIDT_DBR_CTRL2__UNUSED_2__SHIFT 0x1f
+#define DIDT_DBR_CTRL_OCP__UNUSED_0_MASK 0xffff
+#define DIDT_DBR_CTRL_OCP__UNUSED_0__SHIFT 0x0
+#define DIDT_DBR_CTRL_OCP__OCP_MAX_POWER_MASK 0xffff0000
+#define DIDT_DBR_CTRL_OCP__OCP_MAX_POWER__SHIFT 0x10
+#define DIDT_DBR_WEIGHT0_3__WEIGHT0_MASK 0xff
+#define DIDT_DBR_WEIGHT0_3__WEIGHT0__SHIFT 0x0
+#define DIDT_DBR_WEIGHT0_3__WEIGHT1_MASK 0xff00
+#define DIDT_DBR_WEIGHT0_3__WEIGHT1__SHIFT 0x8
+#define DIDT_DBR_WEIGHT0_3__WEIGHT2_MASK 0xff0000
+#define DIDT_DBR_WEIGHT0_3__WEIGHT2__SHIFT 0x10
+#define DIDT_DBR_WEIGHT0_3__WEIGHT3_MASK 0xff000000
+#define DIDT_DBR_WEIGHT0_3__WEIGHT3__SHIFT 0x18
+#define DIDT_DBR_WEIGHT4_7__WEIGHT4_MASK 0xff
+#define DIDT_DBR_WEIGHT4_7__WEIGHT4__SHIFT 0x0
+#define DIDT_DBR_WEIGHT4_7__WEIGHT5_MASK 0xff00
+#define DIDT_DBR_WEIGHT4_7__WEIGHT5__SHIFT 0x8
+#define DIDT_DBR_WEIGHT4_7__WEIGHT6_MASK 0xff0000
+#define DIDT_DBR_WEIGHT4_7__WEIGHT6__SHIFT 0x10
+#define DIDT_DBR_WEIGHT4_7__WEIGHT7_MASK 0xff000000
+#define DIDT_DBR_WEIGHT4_7__WEIGHT7__SHIFT 0x18
+#define DIDT_DBR_WEIGHT8_11__WEIGHT8_MASK 0xff
+#define DIDT_DBR_WEIGHT8_11__WEIGHT8__SHIFT 0x0
+#define DIDT_DBR_WEIGHT8_11__WEIGHT9_MASK 0xff00
+#define DIDT_DBR_WEIGHT8_11__WEIGHT9__SHIFT 0x8
+#define DIDT_DBR_WEIGHT8_11__WEIGHT10_MASK 0xff0000
+#define DIDT_DBR_WEIGHT8_11__WEIGHT10__SHIFT 0x10
+#define DIDT_DBR_WEIGHT8_11__WEIGHT11_MASK 0xff000000
+#define DIDT_DBR_WEIGHT8_11__WEIGHT11__SHIFT 0x18
+
+#endif /* GFX_8_1_SH_MASK_H */
diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h
index 44c5d4a4d1bf..552622675ace 100644
--- a/drivers/gpu/drm/amd/include/atombios.h
+++ b/drivers/gpu/drm/amd/include/atombios.h
@@ -6784,7 +6784,7 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE_V2_1
ULONG ulMCUcodeRomStartAddr;
ULONG ulMCUcodeLength;
USHORT usMcRegInitTableOffset; // offset of ATOM_REG_INIT_SETTING array for MC core register settings.
- USHORT usReserved; // offset of ATOM_INIT_REG_BLOCK for MC SEQ/PHY regsiter setting
+ USHORT usReserved; // offset of ATOM_INIT_REG_BLOCK for MC SEQ/PHY register setting
}ATOM_MC_INIT_PARAM_TABLE_V2_1;
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
index 144f50acc971..c89dc777768f 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
@@ -16,6 +16,8 @@ TRACE_EVENT(amd_sched_job,
TP_ARGS(sched_job),
TP_STRUCT__entry(
__field(struct amd_sched_entity *, entity)
+ __field(struct amd_sched_job *, sched_job)
+ __field(struct fence *, fence)
__field(const char *, name)
__field(u32, job_count)
__field(int, hw_job_count)
@@ -23,16 +25,32 @@ TRACE_EVENT(amd_sched_job,
TP_fast_assign(
__entry->entity = sched_job->s_entity;
+ __entry->sched_job = sched_job;
+ __entry->fence = &sched_job->s_fence->base;
__entry->name = sched_job->sched->name;
__entry->job_count = kfifo_len(
&sched_job->s_entity->job_queue) / sizeof(sched_job);
__entry->hw_job_count = atomic_read(
&sched_job->sched->hw_rq_count);
),
- TP_printk("entity=%p, ring=%s, job count:%u, hw job count:%d",
- __entry->entity, __entry->name, __entry->job_count,
- __entry->hw_job_count)
+ TP_printk("entity=%p, sched job=%p, fence=%p, ring=%s, job count:%u, hw job count:%d",
+ __entry->entity, __entry->sched_job, __entry->fence, __entry->name,
+ __entry->job_count, __entry->hw_job_count)
);
+
+TRACE_EVENT(amd_sched_process_job,
+ TP_PROTO(struct amd_sched_fence *fence),
+ TP_ARGS(fence),
+ TP_STRUCT__entry(
+ __field(struct fence *, fence)
+ ),
+
+ TP_fast_assign(
+ __entry->fence = &fence->base;
+ ),
+ TP_printk("fence=%p signaled", __entry->fence)
+);
+
#endif
/* This part must be outside protection */
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 3697eeeecf82..ea30d6ad4c13 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -34,6 +34,9 @@ static struct amd_sched_job *
amd_sched_entity_pop_job(struct amd_sched_entity *entity);
static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
+struct kmem_cache *sched_fence_slab;
+atomic_t sched_fence_slab_ref = ATOMIC_INIT(0);
+
/* Initialize a given run queue struct */
static void amd_sched_rq_init(struct amd_sched_rq *rq)
{
@@ -222,6 +225,12 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity)
while ((entity->dependency = sched->ops->dependency(sched_job))) {
+ if (entity->dependency->context == entity->fence_context) {
+ /* We can ignore fences from ourself */
+ fence_put(entity->dependency);
+ continue;
+ }
+
if (fence_add_callback(entity->dependency, &entity->cb,
amd_sched_entity_wakeup))
fence_put(entity->dependency);
@@ -267,22 +276,13 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
*
* Returns 0 for success, negative error code otherwise.
*/
-int amd_sched_entity_push_job(struct amd_sched_job *sched_job)
+void amd_sched_entity_push_job(struct amd_sched_job *sched_job)
{
struct amd_sched_entity *entity = sched_job->s_entity;
- struct amd_sched_fence *fence = amd_sched_fence_create(
- entity, sched_job->owner);
-
- if (!fence)
- return -ENOMEM;
-
- fence_get(&fence->base);
- sched_job->s_fence = fence;
wait_event(entity->sched->job_scheduled,
amd_sched_entity_in(sched_job));
trace_amd_sched_job(sched_job);
- return 0;
}
/**
@@ -327,19 +327,50 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
struct amd_sched_fence *s_fence =
container_of(cb, struct amd_sched_fence, cb);
struct amd_gpu_scheduler *sched = s_fence->sched;
+ unsigned long flags;
atomic_dec(&sched->hw_rq_count);
amd_sched_fence_signal(s_fence);
+ if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
+ cancel_delayed_work(&s_fence->dwork);
+ spin_lock_irqsave(&sched->fence_list_lock, flags);
+ list_del_init(&s_fence->list);
+ spin_unlock_irqrestore(&sched->fence_list_lock, flags);
+ }
+ trace_amd_sched_process_job(s_fence);
fence_put(&s_fence->base);
wake_up_interruptible(&sched->wake_up_worker);
}
+static void amd_sched_fence_work_func(struct work_struct *work)
+{
+ struct amd_sched_fence *s_fence =
+ container_of(work, struct amd_sched_fence, dwork.work);
+ struct amd_gpu_scheduler *sched = s_fence->sched;
+ struct amd_sched_fence *entity, *tmp;
+ unsigned long flags;
+
+ DRM_ERROR("[%s] scheduler is timeout!\n", sched->name);
+
+ /* Clean all pending fences */
+ spin_lock_irqsave(&sched->fence_list_lock, flags);
+ list_for_each_entry_safe(entity, tmp, &sched->fence_list, list) {
+ DRM_ERROR(" fence no %d\n", entity->base.seqno);
+ cancel_delayed_work(&entity->dwork);
+ list_del_init(&entity->list);
+ fence_put(&entity->base);
+ }
+ spin_unlock_irqrestore(&sched->fence_list_lock, flags);
+}
+
static int amd_sched_main(void *param)
{
struct sched_param sparam = {.sched_priority = 1};
struct amd_gpu_scheduler *sched = (struct amd_gpu_scheduler *)param;
int r, count;
+ spin_lock_init(&sched->fence_list_lock);
+ INIT_LIST_HEAD(&sched->fence_list);
sched_setscheduler(current, SCHED_FIFO, &sparam);
while (!kthread_should_stop()) {
@@ -347,6 +378,7 @@ static int amd_sched_main(void *param)
struct amd_sched_fence *s_fence;
struct amd_sched_job *sched_job;
struct fence *fence;
+ unsigned long flags;
wait_event_interruptible(sched->wake_up_worker,
kthread_should_stop() ||
@@ -357,6 +389,15 @@ static int amd_sched_main(void *param)
entity = sched_job->s_entity;
s_fence = sched_job->s_fence;
+
+ if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
+ INIT_DELAYED_WORK(&s_fence->dwork, amd_sched_fence_work_func);
+ schedule_delayed_work(&s_fence->dwork, sched->timeout);
+ spin_lock_irqsave(&sched->fence_list_lock, flags);
+ list_add_tail(&s_fence->list, &sched->fence_list);
+ spin_unlock_irqrestore(&sched->fence_list_lock, flags);
+ }
+
atomic_inc(&sched->hw_rq_count);
fence = sched->ops->run_job(sched_job);
if (fence) {
@@ -392,17 +433,25 @@ static int amd_sched_main(void *param)
*/
int amd_sched_init(struct amd_gpu_scheduler *sched,
struct amd_sched_backend_ops *ops,
- unsigned hw_submission, const char *name)
+ unsigned hw_submission, long timeout, const char *name)
{
sched->ops = ops;
sched->hw_submission_limit = hw_submission;
sched->name = name;
+ sched->timeout = timeout;
amd_sched_rq_init(&sched->sched_rq);
amd_sched_rq_init(&sched->kernel_rq);
init_waitqueue_head(&sched->wake_up_worker);
init_waitqueue_head(&sched->job_scheduled);
atomic_set(&sched->hw_rq_count, 0);
+ if (atomic_inc_return(&sched_fence_slab_ref) == 1) {
+ sched_fence_slab = kmem_cache_create(
+ "amd_sched_fence", sizeof(struct amd_sched_fence), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!sched_fence_slab)
+ return -ENOMEM;
+ }
/* Each scheduler will run on a seperate kernel thread */
sched->thread = kthread_run(amd_sched_main, sched, sched->name);
@@ -421,5 +470,8 @@ int amd_sched_init(struct amd_gpu_scheduler *sched,
*/
void amd_sched_fini(struct amd_gpu_scheduler *sched)
{
- kthread_stop(sched->thread);
+ if (sched->thread)
+ kthread_stop(sched->thread);
+ if (atomic_dec_and_test(&sched_fence_slab_ref))
+ kmem_cache_destroy(sched_fence_slab);
}
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
index 80b64dc22214..939692b14f4b 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -30,6 +30,9 @@
struct amd_gpu_scheduler;
struct amd_sched_rq;
+extern struct kmem_cache *sched_fence_slab;
+extern atomic_t sched_fence_slab_ref;
+
/**
* A scheduler entity is a wrapper around a job queue or a group
* of other entities. Entities take turns emitting jobs from their
@@ -68,13 +71,14 @@ struct amd_sched_fence {
struct amd_gpu_scheduler *sched;
spinlock_t lock;
void *owner;
+ struct delayed_work dwork;
+ struct list_head list;
};
struct amd_sched_job {
struct amd_gpu_scheduler *sched;
struct amd_sched_entity *s_entity;
struct amd_sched_fence *s_fence;
- void *owner;
};
extern const struct fence_ops amd_sched_fence_ops;
@@ -103,18 +107,21 @@ struct amd_sched_backend_ops {
struct amd_gpu_scheduler {
struct amd_sched_backend_ops *ops;
uint32_t hw_submission_limit;
+ long timeout;
const char *name;
struct amd_sched_rq sched_rq;
struct amd_sched_rq kernel_rq;
wait_queue_head_t wake_up_worker;
wait_queue_head_t job_scheduled;
atomic_t hw_rq_count;
+ struct list_head fence_list;
+ spinlock_t fence_list_lock;
struct task_struct *thread;
};
int amd_sched_init(struct amd_gpu_scheduler *sched,
struct amd_sched_backend_ops *ops,
- uint32_t hw_submission, const char *name);
+ uint32_t hw_submission, long timeout, const char *name);
void amd_sched_fini(struct amd_gpu_scheduler *sched);
int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
@@ -123,7 +130,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
uint32_t jobs);
void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
struct amd_sched_entity *entity);
-int amd_sched_entity_push_job(struct amd_sched_job *sched_job);
+void amd_sched_entity_push_job(struct amd_sched_job *sched_job);
struct amd_sched_fence *amd_sched_fence_create(
struct amd_sched_entity *s_entity, void *owner);
diff --git a/drivers/gpu/drm/amd/scheduler/sched_fence.c b/drivers/gpu/drm/amd/scheduler/sched_fence.c
index d802638094f4..8d2130b9ff05 100644
--- a/drivers/gpu/drm/amd/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/amd/scheduler/sched_fence.c
@@ -32,7 +32,7 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *s_entity
struct amd_sched_fence *fence = NULL;
unsigned seq;
- fence = kzalloc(sizeof(struct amd_sched_fence), GFP_KERNEL);
+ fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);
if (fence == NULL)
return NULL;
fence->owner = owner;
@@ -71,11 +71,17 @@ static bool amd_sched_fence_enable_signaling(struct fence *f)
return true;
}
+static void amd_sched_fence_release(struct fence *f)
+{
+ struct amd_sched_fence *fence = to_amd_sched_fence(f);
+ kmem_cache_free(sched_fence_slab, fence);
+}
+
const struct fence_ops amd_sched_fence_ops = {
.get_driver_name = amd_sched_fence_get_driver_name,
.get_timeline_name = amd_sched_fence_get_timeline_name,
.enable_signaling = amd_sched_fence_enable_signaling,
.signaled = NULL,
.wait = fence_default_wait,
- .release = NULL,
+ .release = amd_sched_fence_release,
};
diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index 50ae88ad4d76..eb773e9af313 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -14,12 +14,3 @@ config DRM_ARMADA
This driver provides no built-in acceleration; acceleration is
performed by other IP found on the SoC. This driver provides
kernel mode setting and buffer management to userspace.
-
-config DRM_ARMADA_TDA1998X
- bool "Support TDA1998X HDMI output"
- depends on DRM_ARMADA != n
- depends on I2C && DRM_I2C_NXP_TDA998X = y
- default y
- help
- Support the TDA1998x HDMI output device found on the Solid-Run
- CuBox.
diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
index d6f43e06150a..ffd673615772 100644
--- a/drivers/gpu/drm/armada/Makefile
+++ b/drivers/gpu/drm/armada/Makefile
@@ -1,6 +1,5 @@
armada-y := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
- armada_gem.o armada_output.o armada_overlay.o \
- armada_slave.o
+ armada_gem.o armada_overlay.o
armada-y += armada_510.o
armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 01ffe9bffe38..cebcab560626 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -20,6 +20,7 @@
#include "armada_hw.h"
struct armada_frame_work {
+ struct armada_plane_work work;
struct drm_pending_vblank_event *event;
struct armada_regs regs[4];
struct drm_framebuffer *old_fb;
@@ -33,6 +34,23 @@ enum csc_mode {
CSC_RGB_STUDIO = 2,
};
+static const uint32_t armada_primary_formats[] = {
+ DRM_FORMAT_UYVY,
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_VYUY,
+ DRM_FORMAT_YVYU,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_ABGR1555,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_BGR565,
+};
+
/*
* A note about interlacing. Let's consider HDMI 1920x1080i.
* The timing parameters we have from X are:
@@ -173,49 +191,82 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
return i;
}
-static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc,
- struct armada_frame_work *work)
+static void armada_drm_plane_work_run(struct armada_crtc *dcrtc,
+ struct armada_plane *plane)
+{
+ struct armada_plane_work *work = xchg(&plane->work, NULL);
+
+ /* Handle any pending frame work. */
+ if (work) {
+ work->fn(dcrtc, plane, work);
+ drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+ }
+
+ wake_up(&plane->frame_wait);
+}
+
+int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
+ struct armada_plane *plane, struct armada_plane_work *work)
{
- struct drm_device *dev = dcrtc->crtc.dev;
- unsigned long flags;
int ret;
- ret = drm_vblank_get(dev, dcrtc->num);
+ ret = drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
if (ret) {
DRM_ERROR("failed to acquire vblank counter\n");
return ret;
}
- spin_lock_irqsave(&dev->event_lock, flags);
- if (!dcrtc->frame_work)
- dcrtc->frame_work = work;
- else
- ret = -EBUSY;
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
+ ret = cmpxchg(&plane->work, NULL, work) ? -EBUSY : 0;
if (ret)
- drm_vblank_put(dev, dcrtc->num);
+ drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
return ret;
}
-static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc)
+int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout)
{
- struct drm_device *dev = dcrtc->crtc.dev;
- struct armada_frame_work *work = dcrtc->frame_work;
+ return wait_event_timeout(plane->frame_wait, !plane->work, timeout);
+}
- dcrtc->frame_work = NULL;
+struct armada_plane_work *armada_drm_plane_work_cancel(
+ struct armada_crtc *dcrtc, struct armada_plane *plane)
+{
+ struct armada_plane_work *work = xchg(&plane->work, NULL);
- armada_drm_crtc_update_regs(dcrtc, work->regs);
+ if (work)
+ drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
- if (work->event)
- drm_send_vblank_event(dev, dcrtc->num, work->event);
+ return work;
+}
- drm_vblank_put(dev, dcrtc->num);
+static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc,
+ struct armada_frame_work *work)
+{
+ struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary);
+
+ return armada_drm_plane_work_queue(dcrtc, plane, &work->work);
+}
+
+static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc,
+ struct armada_plane *plane, struct armada_plane_work *work)
+{
+ struct armada_frame_work *fwork = container_of(work, struct armada_frame_work, work);
+ struct drm_device *dev = dcrtc->crtc.dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dcrtc->irq_lock, flags);
+ armada_drm_crtc_update_regs(dcrtc, fwork->regs);
+ spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+
+ if (fwork->event) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+ drm_send_vblank_event(dev, dcrtc->num, fwork->event);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
/* Finally, queue the process-half of the cleanup. */
- __armada_drm_queue_unref_work(dcrtc->crtc.dev, work->old_fb);
- kfree(work);
+ __armada_drm_queue_unref_work(dcrtc->crtc.dev, fwork->old_fb);
+ kfree(fwork);
}
static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc,
@@ -235,6 +286,7 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc,
work = kmalloc(sizeof(*work), GFP_KERNEL);
if (work) {
int i = 0;
+ work->work.fn = armada_drm_crtc_complete_frame_work;
work->event = NULL;
work->old_fb = fb;
armada_reg_queue_end(work->regs, i);
@@ -255,19 +307,14 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc,
static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
{
- struct drm_device *dev = dcrtc->crtc.dev;
+ struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary);
/*
* Tell the DRM core that vblank IRQs aren't going to happen for
* a while. This cleans up any pending vblank events for us.
*/
drm_crtc_vblank_off(&dcrtc->crtc);
-
- /* Handle any pending flip event. */
- spin_lock_irq(&dev->event_lock);
- if (dcrtc->frame_work)
- armada_drm_crtc_complete_frame_work(dcrtc);
- spin_unlock_irq(&dev->event_lock);
+ armada_drm_plane_work_run(dcrtc, plane);
}
void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
@@ -287,7 +334,11 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)
if (dcrtc->dpms != dpms) {
dcrtc->dpms = dpms;
+ if (!IS_ERR(dcrtc->clk) && !dpms_blanked(dpms))
+ WARN_ON(clk_prepare_enable(dcrtc->clk));
armada_drm_crtc_update(dcrtc);
+ if (!IS_ERR(dcrtc->clk) && dpms_blanked(dpms))
+ clk_disable_unprepare(dcrtc->clk);
if (dpms_blanked(dpms))
armada_drm_vblank_off(dcrtc);
else
@@ -310,17 +361,11 @@ static void armada_drm_crtc_prepare(struct drm_crtc *crtc)
/*
* If we have an overlay plane associated with this CRTC, disable
* it before the modeset to avoid its coordinates being outside
- * the new mode parameters. DRM doesn't provide help with this.
+ * the new mode parameters.
*/
plane = dcrtc->plane;
- if (plane) {
- struct drm_framebuffer *fb = plane->fb;
-
- plane->funcs->disable_plane(plane);
- plane->fb = NULL;
- plane->crtc = NULL;
- drm_framebuffer_unreference(fb);
- }
+ if (plane)
+ drm_plane_force_disable(plane);
}
/* The mode_config.mutex will be held for this call */
@@ -356,8 +401,8 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
{
- struct armada_vbl_event *e, *n;
void __iomem *base = dcrtc->base;
+ struct drm_plane *ovl_plane;
if (stat & DMA_FF_UNDERFLOW)
DRM_ERROR("video underflow on crtc %u\n", dcrtc->num);
@@ -368,11 +413,10 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num);
spin_lock(&dcrtc->irq_lock);
-
- list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) {
- list_del_init(&e->node);
- drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
- e->fn(dcrtc, e->data);
+ ovl_plane = dcrtc->plane;
+ if (ovl_plane) {
+ struct armada_plane *plane = drm_to_armada_plane(ovl_plane);
+ armada_drm_plane_work_run(dcrtc, plane);
}
if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
@@ -404,14 +448,8 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
spin_unlock(&dcrtc->irq_lock);
if (stat & GRA_FRAME_IRQ) {
- struct drm_device *dev = dcrtc->crtc.dev;
-
- spin_lock(&dev->event_lock);
- if (dcrtc->frame_work)
- armada_drm_crtc_complete_frame_work(dcrtc);
- spin_unlock(&dev->event_lock);
-
- wake_up(&dcrtc->frame_wait);
+ struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary);
+ armada_drm_plane_work_run(dcrtc, plane);
}
}
@@ -527,7 +565,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
adj->crtc_vtotal, tm, bm);
/* Wait for pending flips to complete */
- wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
+ armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary),
+ MAX_SCHEDULE_TIMEOUT);
drm_crtc_vblank_off(crtc);
@@ -537,6 +576,13 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
writel_relaxed(val, dcrtc->base + LCD_SPU_DUMB_CTRL);
}
+ /*
+ * If we are blanked, we would have disabled the clock. Re-enable
+ * it so that compute_clock() does the right thing.
+ */
+ if (!IS_ERR(dcrtc->clk) && dpms_blanked(dcrtc->dpms))
+ WARN_ON(clk_prepare_enable(dcrtc->clk));
+
/* Now compute the divider for real */
dcrtc->variant->compute_clock(dcrtc, adj, &sclk);
@@ -637,7 +683,8 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
armada_reg_queue_end(regs, i);
/* Wait for pending flips to complete */
- wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
+ armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary),
+ MAX_SCHEDULE_TIMEOUT);
/* Take a reference to the new fb as we're using it */
drm_framebuffer_reference(crtc->primary->fb);
@@ -651,18 +698,47 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
return 0;
}
+void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc,
+ struct drm_plane *plane)
+{
+ u32 sram_para1, dma_ctrl0_mask;
+
+ /*
+ * Drop our reference on any framebuffer attached to this plane.
+ * We don't need to NULL this out as drm_plane_force_disable(),
+ * and __setplane_internal() will do so for an overlay plane, and
+ * __drm_helper_disable_unused_functions() will do so for the
+ * primary plane.
+ */
+ if (plane->fb)
+ drm_framebuffer_unreference(plane->fb);
+
+ /* Power down the Y/U/V FIFOs */
+ sram_para1 = CFG_PDWN16x66 | CFG_PDWN32x66;
+
+ /* Power down most RAMs and FIFOs if this is the primary plane */
+ if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+ sram_para1 |= CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
+ CFG_PDWN32x32 | CFG_PDWN64x66;
+ dma_ctrl0_mask = CFG_GRA_ENA;
+ } else {
+ dma_ctrl0_mask = CFG_DMA_ENA;
+ }
+
+ spin_lock_irq(&dcrtc->irq_lock);
+ armada_updatel(0, dma_ctrl0_mask, dcrtc->base + LCD_SPU_DMA_CTRL0);
+ spin_unlock_irq(&dcrtc->irq_lock);
+
+ armada_updatel(sram_para1, 0, dcrtc->base + LCD_SPU_SRAM_PARA1);
+}
+
/* The mode_config.mutex will be held for this call */
static void armada_drm_crtc_disable(struct drm_crtc *crtc)
{
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
- armada_drm_crtc_finish_fb(dcrtc, crtc->primary->fb, true);
-
- /* Power down most RAMs and FIFOs */
- writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
- CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
- CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
+ armada_drm_crtc_plane_disable(dcrtc, crtc->primary);
}
static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
@@ -920,8 +996,6 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
{
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct armada_frame_work *work;
- struct drm_device *dev = crtc->dev;
- unsigned long flags;
unsigned i;
int ret;
@@ -933,6 +1007,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
if (!work)
return -ENOMEM;
+ work->work.fn = armada_drm_crtc_complete_frame_work;
work->event = event;
work->old_fb = dcrtc->crtc.primary->fb;
@@ -966,12 +1041,8 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
* Finally, if the display is blanked, we won't receive an
* interrupt, so complete it now.
*/
- if (dpms_blanked(dcrtc->dpms)) {
- spin_lock_irqsave(&dev->event_lock, flags);
- if (dcrtc->frame_work)
- armada_drm_crtc_complete_frame_work(dcrtc);
- spin_unlock_irqrestore(&dev->event_lock, flags);
- }
+ if (dpms_blanked(dcrtc->dpms))
+ armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary));
return 0;
}
@@ -1012,6 +1083,19 @@ static struct drm_crtc_funcs armada_crtc_funcs = {
.set_property = armada_drm_crtc_set_property,
};
+static const struct drm_plane_funcs armada_primary_plane_funcs = {
+ .update_plane = drm_primary_helper_update,
+ .disable_plane = drm_primary_helper_disable,
+ .destroy = drm_primary_helper_destroy,
+};
+
+int armada_drm_plane_init(struct armada_plane *plane)
+{
+ init_waitqueue_head(&plane->frame_wait);
+
+ return 0;
+}
+
static struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = {
{ CSC_AUTO, "Auto" },
{ CSC_YUV_CCIR601, "CCIR601" },
@@ -1044,12 +1128,13 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev)
return 0;
}
-int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
+static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
struct resource *res, int irq, const struct armada_variant *variant,
struct device_node *port)
{
struct armada_private *priv = drm->dev_private;
struct armada_crtc *dcrtc;
+ struct armada_plane *primary;
void __iomem *base;
int ret;
@@ -1080,8 +1165,6 @@ int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
spin_lock_init(&dcrtc->irq_lock);
dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR;
- INIT_LIST_HEAD(&dcrtc->vbl_list);
- init_waitqueue_head(&dcrtc->frame_wait);
/* Initialize some registers which we don't otherwise set */
writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV);
@@ -1118,7 +1201,32 @@ int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
priv->dcrtc[dcrtc->num] = dcrtc;
dcrtc->crtc.port = port;
- drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs);
+
+ primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+ if (!primary)
+ return -ENOMEM;
+
+ ret = armada_drm_plane_init(primary);
+ if (ret) {
+ kfree(primary);
+ return ret;
+ }
+
+ ret = drm_universal_plane_init(drm, &primary->base, 0,
+ &armada_primary_plane_funcs,
+ armada_primary_formats,
+ ARRAY_SIZE(armada_primary_formats),
+ DRM_PLANE_TYPE_PRIMARY);
+ if (ret) {
+ kfree(primary);
+ return ret;
+ }
+
+ ret = drm_crtc_init_with_planes(drm, &dcrtc->crtc, &primary->base, NULL,
+ &armada_crtc_funcs);
+ if (ret)
+ goto err_crtc_init;
+
drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
@@ -1127,6 +1235,10 @@ int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
dcrtc->csc_rgb_mode);
return armada_overlay_plane_create(drm, 1 << dcrtc->num);
+
+err_crtc_init:
+ primary->base.funcs->destroy(&primary->base);
+ return ret;
}
static int
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 98102a5a9af5..04fdd22d483b 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -31,9 +31,30 @@ struct armada_regs {
#define armada_reg_queue_end(_r, _i) \
armada_reg_queue_mod(_r, _i, 0, 0, ~0)
-struct armada_frame_work;
+struct armada_crtc;
+struct armada_plane;
struct armada_variant;
+struct armada_plane_work {
+ void (*fn)(struct armada_crtc *,
+ struct armada_plane *,
+ struct armada_plane_work *);
+};
+
+struct armada_plane {
+ struct drm_plane base;
+ wait_queue_head_t frame_wait;
+ struct armada_plane_work *work;
+};
+#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
+
+int armada_drm_plane_init(struct armada_plane *plane);
+int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
+ struct armada_plane *plane, struct armada_plane_work *work);
+int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
+struct armada_plane_work *armada_drm_plane_work_cancel(
+ struct armada_crtc *dcrtc, struct armada_plane *plane);
+
struct armada_crtc {
struct drm_crtc crtc;
const struct armada_variant *variant;
@@ -66,25 +87,20 @@ struct armada_crtc {
uint32_t dumb_ctrl;
uint32_t spu_iopad_ctrl;
- wait_queue_head_t frame_wait;
- struct armada_frame_work *frame_work;
-
spinlock_t irq_lock;
uint32_t irq_ena;
- struct list_head vbl_list;
};
#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
-struct device_node;
-int armada_drm_crtc_create(struct drm_device *, struct device *,
- struct resource *, int, const struct armada_variant *,
- struct device_node *);
void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
+void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc,
+ struct drm_plane *plane);
+
extern struct platform_driver armada_lcd_platform_driver;
#endif
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index 5f6aef0dca59..4df6f2af2b21 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -37,22 +37,6 @@ static inline uint32_t armada_pitch(uint32_t width, uint32_t bpp)
return ALIGN(pitch, 128);
}
-struct armada_vbl_event {
- struct list_head node;
- void *data;
- void (*fn)(struct armada_crtc *, void *);
-};
-void armada_drm_vbl_event_add(struct armada_crtc *,
- struct armada_vbl_event *);
-void armada_drm_vbl_event_remove(struct armada_crtc *,
- struct armada_vbl_event *);
-#define armada_drm_vbl_event_init(_e, _f, _d) do { \
- struct armada_vbl_event *__e = _e; \
- INIT_LIST_HEAD(&__e->node); \
- __e->data = _d; \
- __e->fn = _f; \
-} while (0)
-
struct armada_private;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 225034b74cda..77ab93d60125 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -11,6 +11,7 @@
#include <linux/of_graph.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
#include "armada_crtc.h"
#include "armada_drm.h"
#include "armada_gem.h"
@@ -18,47 +19,6 @@
#include <drm/armada_drm.h>
#include "armada_ioctlP.h"
-#ifdef CONFIG_DRM_ARMADA_TDA1998X
-#include <drm/i2c/tda998x.h>
-#include "armada_slave.h"
-
-static struct tda998x_encoder_params params = {
- /* With 0x24, there is no translation between vp_out and int_vp
- FB LCD out Pins VIP Int Vp
- R:23:16 R:7:0 VPC7:0 7:0 7:0[R]
- G:15:8 G:15:8 VPB7:0 23:16 23:16[G]
- B:7:0 B:23:16 VPA7:0 15:8 15:8[B]
- */
- .swap_a = 2,
- .swap_b = 3,
- .swap_c = 4,
- .swap_d = 5,
- .swap_e = 0,
- .swap_f = 1,
- .audio_cfg = BIT(2),
- .audio_frame[1] = 1,
- .audio_format = AFMT_SPDIF,
- .audio_sample_rate = 44100,
-};
-
-static const struct armada_drm_slave_config tda19988_config = {
- .i2c_adapter_id = 0,
- .crtcs = 1 << 0, /* Only LCD0 at the moment */
- .polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT,
- .interlace_allowed = true,
- .info = {
- .type = "tda998x",
- .addr = 0x70,
- .platform_data = &params,
- },
-};
-#endif
-
-static bool is_componentized(struct device *dev)
-{
- return dev->of_node || dev->platform_data;
-}
-
static void armada_drm_unref_work(struct work_struct *work)
{
struct armada_private *priv =
@@ -91,16 +51,11 @@ void armada_drm_queue_unref_work(struct drm_device *dev,
static int armada_drm_load(struct drm_device *dev, unsigned long flags)
{
- const struct platform_device_id *id;
- const struct armada_variant *variant;
struct armada_private *priv;
- struct resource *res[ARRAY_SIZE(priv->dcrtc)];
struct resource *mem = NULL;
- int ret, n, i;
-
- memset(res, 0, sizeof(res));
+ int ret, n;
- for (n = i = 0; ; n++) {
+ for (n = 0; ; n++) {
struct resource *r = platform_get_resource(dev->platformdev,
IORESOURCE_MEM, n);
if (!r)
@@ -109,8 +64,6 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
/* Resources above 64K are graphics memory */
if (resource_size(r) > SZ_64K)
mem = r;
- else if (i < ARRAY_SIZE(priv->dcrtc))
- res[i++] = r;
else
return -EINVAL;
}
@@ -131,13 +84,6 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
platform_set_drvdata(dev->platformdev, dev);
dev->dev_private = priv;
- /* Get the implementation specific driver data. */
- id = platform_get_device_id(dev->platformdev);
- if (!id)
- return -ENXIO;
-
- variant = (const struct armada_variant *)id->driver_data;
-
INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
INIT_KFIFO(priv->fb_unref);
@@ -157,34 +103,9 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
dev->mode_config.funcs = &armada_drm_mode_config_funcs;
drm_mm_init(&priv->linear, mem->start, resource_size(mem));
- /* Create all LCD controllers */
- for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
- int irq;
-
- if (!res[n])
- break;
-
- irq = platform_get_irq(dev->platformdev, n);
- if (irq < 0)
- goto err_kms;
-
- ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq,
- variant, NULL);
- if (ret)
- goto err_kms;
- }
-
- if (is_componentized(dev->dev)) {
- ret = component_bind_all(dev->dev, dev);
- if (ret)
- goto err_kms;
- } else {
-#ifdef CONFIG_DRM_ARMADA_TDA1998X
- ret = armada_drm_connector_slave_create(dev, &tda19988_config);
- if (ret)
- goto err_kms;
-#endif
- }
+ ret = component_bind_all(dev->dev, dev);
+ if (ret)
+ goto err_kms;
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
@@ -202,8 +123,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
return 0;
err_comp:
- if (is_componentized(dev->dev))
- component_unbind_all(dev->dev, dev);
+ component_unbind_all(dev->dev, dev);
err_kms:
drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear);
@@ -219,8 +139,7 @@ static int armada_drm_unload(struct drm_device *dev)
drm_kms_helper_poll_fini(dev);
armada_fbdev_fini(dev);
- if (is_componentized(dev->dev))
- component_unbind_all(dev->dev, dev);
+ component_unbind_all(dev->dev, dev);
drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear);
@@ -230,50 +149,24 @@ static int armada_drm_unload(struct drm_device *dev)
return 0;
}
-void armada_drm_vbl_event_add(struct armada_crtc *dcrtc,
- struct armada_vbl_event *evt)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dcrtc->irq_lock, flags);
- if (list_empty(&evt->node)) {
- list_add_tail(&evt->node, &dcrtc->vbl_list);
-
- drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
- }
- spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
-}
-
-void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc,
- struct armada_vbl_event *evt)
-{
- if (!list_empty(&evt->node)) {
- list_del_init(&evt->node);
- drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
- }
-}
-
/* These are called under the vbl_lock. */
-static int armada_drm_enable_vblank(struct drm_device *dev, int crtc)
+static int armada_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct armada_private *priv = dev->dev_private;
- armada_drm_crtc_enable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
+ armada_drm_crtc_enable_irq(priv->dcrtc[pipe], VSYNC_IRQ_ENA);
return 0;
}
-static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
+static void armada_drm_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct armada_private *priv = dev->dev_private;
- armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
+ armada_drm_crtc_disable_irq(priv->dcrtc[pipe], VSYNC_IRQ_ENA);
}
static struct drm_ioctl_desc armada_ioctls[] = {
- DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
- DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP, armada_gem_mmap_ioctl,
- DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl,
- DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,0),
+ DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP, armada_gem_mmap_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl, 0),
};
static void armada_drm_lastclose(struct drm_device *dev)
@@ -300,7 +193,7 @@ static struct drm_driver armada_drm_driver = {
.lastclose = armada_drm_lastclose,
.unload = armada_drm_unload,
.set_busid = drm_platform_set_busid,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = armada_drm_enable_vblank,
.disable_vblank = armada_drm_disable_vblank,
#ifdef CONFIG_DEBUG_FS
@@ -370,43 +263,29 @@ static void armada_add_endpoints(struct device *dev,
}
}
-static int armada_drm_find_components(struct device *dev,
- struct component_match **match)
-{
- struct device_node *port;
- int i;
-
- if (dev->of_node) {
- struct device_node *np = dev->of_node;
-
- for (i = 0; ; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
-
- component_match_add(dev, match, compare_of, port);
- of_node_put(port);
- }
+static const struct component_master_ops armada_master_ops = {
+ .bind = armada_drm_bind,
+ .unbind = armada_drm_unbind,
+};
- if (i == 0) {
- dev_err(dev, "missing 'ports' property\n");
- return -ENODEV;
- }
+static int armada_drm_probe(struct platform_device *pdev)
+{
+ struct component_match *match = NULL;
+ struct device *dev = &pdev->dev;
+ int ret;
- for (i = 0; ; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
+ ret = drm_of_component_probe(dev, compare_dev_name, &armada_master_ops);
+ if (ret != -EINVAL)
+ return ret;
- armada_add_endpoints(dev, match, port);
- of_node_put(port);
- }
- } else if (dev->platform_data) {
+ if (dev->platform_data) {
char **devices = dev->platform_data;
+ struct device_node *port;
struct device *d;
+ int i;
for (i = 0; devices[i]; i++)
- component_match_add(dev, match, compare_dev_name,
+ component_match_add(dev, &match, compare_dev_name,
devices[i]);
if (i == 0) {
@@ -416,56 +295,30 @@ static int armada_drm_find_components(struct device *dev,
for (i = 0; devices[i]; i++) {
d = bus_find_device_by_name(&platform_bus_type, NULL,
- devices[i]);
+ devices[i]);
if (d && d->of_node) {
for_each_child_of_node(d->of_node, port)
- armada_add_endpoints(dev, match, port);
+ armada_add_endpoints(dev, &match, port);
}
put_device(d);
}
}
- return 0;
-}
-
-static const struct component_master_ops armada_master_ops = {
- .bind = armada_drm_bind,
- .unbind = armada_drm_unbind,
-};
-
-static int armada_drm_probe(struct platform_device *pdev)
-{
- if (is_componentized(&pdev->dev)) {
- struct component_match *match = NULL;
- int ret;
-
- ret = armada_drm_find_components(&pdev->dev, &match);
- if (ret < 0)
- return ret;
-
- return component_master_add_with_match(&pdev->dev,
- &armada_master_ops, match);
- } else {
- return drm_platform_init(&armada_drm_driver, pdev);
- }
+ return component_master_add_with_match(&pdev->dev, &armada_master_ops,
+ match);
}
static int armada_drm_remove(struct platform_device *pdev)
{
- if (is_componentized(&pdev->dev))
- component_master_del(&pdev->dev, &armada_master_ops);
- else
- drm_put_dev(platform_get_drvdata(pdev));
+ component_master_del(&pdev->dev, &armada_master_ops);
return 0;
}
static const struct platform_device_id armada_drm_platform_ids[] = {
{
.name = "armada-drm",
- .driver_data = (unsigned long)&armada510_ops,
}, {
.name = "armada-510-drm",
- .driver_data = (unsigned long)&armada510_ops,
},
{ },
};
diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c
deleted file mode 100644
index 5a9823178291..000000000000
--- a/drivers/gpu/drm/armada/armada_output.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2012 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 <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_encoder_slave.h>
-#include "armada_output.h"
-#include "armada_drm.h"
-
-struct armada_connector {
- struct drm_connector conn;
- const struct armada_output_type *type;
-};
-
-#define drm_to_armada_conn(c) container_of(c, struct armada_connector, conn)
-
-struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn)
-{
- struct drm_encoder *enc = conn->encoder;
-
- return enc ? enc : drm_encoder_find(conn->dev, conn->encoder_ids[0]);
-}
-
-static enum drm_connector_status armada_drm_connector_detect(
- struct drm_connector *conn, bool force)
-{
- struct armada_connector *dconn = drm_to_armada_conn(conn);
- enum drm_connector_status status = connector_status_disconnected;
-
- if (dconn->type->detect) {
- status = dconn->type->detect(conn, force);
- } else {
- struct drm_encoder *enc = armada_drm_connector_encoder(conn);
-
- if (enc)
- status = encoder_helper_funcs(enc)->detect(enc, conn);
- }
-
- return status;
-}
-
-static void armada_drm_connector_destroy(struct drm_connector *conn)
-{
- struct armada_connector *dconn = drm_to_armada_conn(conn);
-
- drm_connector_unregister(conn);
- drm_connector_cleanup(conn);
- kfree(dconn);
-}
-
-static int armada_drm_connector_set_property(struct drm_connector *conn,
- struct drm_property *property, uint64_t value)
-{
- struct armada_connector *dconn = drm_to_armada_conn(conn);
-
- if (!dconn->type->set_property)
- return -EINVAL;
-
- return dconn->type->set_property(conn, property, value);
-}
-
-static const struct drm_connector_funcs armada_drm_conn_funcs = {
- .dpms = drm_helper_connector_dpms,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .detect = armada_drm_connector_detect,
- .destroy = armada_drm_connector_destroy,
- .set_property = armada_drm_connector_set_property,
-};
-
-/* Shouldn't this be a generic helper function? */
-int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn,
- struct drm_display_mode *mode)
-{
- struct drm_encoder *encoder = armada_drm_connector_encoder(conn);
- int valid = MODE_BAD;
-
- if (encoder) {
- struct drm_encoder_slave *slave = to_encoder_slave(encoder);
-
- valid = slave->slave_funcs->mode_valid(encoder, mode);
- }
- return valid;
-}
-
-int armada_drm_slave_encoder_set_property(struct drm_connector *conn,
- struct drm_property *property, uint64_t value)
-{
- struct drm_encoder *encoder = armada_drm_connector_encoder(conn);
- int rc = -EINVAL;
-
- if (encoder) {
- struct drm_encoder_slave *slave = to_encoder_slave(encoder);
-
- rc = slave->slave_funcs->set_property(encoder, conn, property,
- value);
- }
- return rc;
-}
-
-int armada_output_create(struct drm_device *dev,
- const struct armada_output_type *type, const void *data)
-{
- struct armada_connector *dconn;
- int ret;
-
- dconn = kzalloc(sizeof(*dconn), GFP_KERNEL);
- if (!dconn)
- return -ENOMEM;
-
- dconn->type = type;
-
- ret = drm_connector_init(dev, &dconn->conn, &armada_drm_conn_funcs,
- type->connector_type);
- if (ret) {
- DRM_ERROR("unable to init connector\n");
- goto err_destroy_dconn;
- }
-
- ret = type->create(&dconn->conn, data);
- if (ret)
- goto err_conn;
-
- ret = drm_connector_register(&dconn->conn);
- if (ret)
- goto err_sysfs;
-
- return 0;
-
- err_sysfs:
- if (dconn->conn.encoder)
- dconn->conn.encoder->funcs->destroy(dconn->conn.encoder);
- err_conn:
- drm_connector_cleanup(&dconn->conn);
- err_destroy_dconn:
- kfree(dconn);
- return ret;
-}
diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h
deleted file mode 100644
index f448785753e8..000000000000
--- a/drivers/gpu/drm/armada/armada_output.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2012 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 ARMADA_CONNETOR_H
-#define ARMADA_CONNETOR_H
-
-#define encoder_helper_funcs(encoder) \
- ((const struct drm_encoder_helper_funcs *)encoder->helper_private)
-
-struct armada_output_type {
- int connector_type;
- enum drm_connector_status (*detect)(struct drm_connector *, bool);
- int (*create)(struct drm_connector *, const void *);
- int (*set_property)(struct drm_connector *, struct drm_property *,
- uint64_t);
-};
-
-struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn);
-
-int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn,
- struct drm_display_mode *mode);
-
-int armada_drm_slave_encoder_set_property(struct drm_connector *conn,
- struct drm_property *property, uint64_t value);
-
-int armada_output_create(struct drm_device *dev,
- const struct armada_output_type *type, const void *data);
-
-#endif
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index e939faba7fcc..5c22b380f8f3 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -16,7 +16,7 @@
#include <drm/armada_drm.h>
#include "armada_ioctlP.h"
-struct armada_plane_properties {
+struct armada_ovl_plane_properties {
uint32_t colorkey_yr;
uint32_t colorkey_ug;
uint32_t colorkey_vb;
@@ -29,26 +29,25 @@ struct armada_plane_properties {
uint32_t colorkey_mode;
};
-struct armada_plane {
- struct drm_plane base;
- spinlock_t lock;
+struct armada_ovl_plane {
+ struct armada_plane base;
struct drm_framebuffer *old_fb;
uint32_t src_hw;
uint32_t dst_hw;
uint32_t dst_yx;
uint32_t ctrl0;
struct {
- struct armada_vbl_event update;
+ struct armada_plane_work work;
struct armada_regs regs[13];
- wait_queue_head_t wait;
} vbl;
- struct armada_plane_properties prop;
+ struct armada_ovl_plane_properties prop;
};
-#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
+#define drm_to_armada_ovl_plane(p) \
+ container_of(p, struct armada_ovl_plane, base.base)
static void
-armada_ovl_update_attr(struct armada_plane_properties *prop,
+armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
struct armada_crtc *dcrtc)
{
writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y);
@@ -71,32 +70,34 @@ armada_ovl_update_attr(struct armada_plane_properties *prop,
spin_unlock_irq(&dcrtc->irq_lock);
}
-/* === Plane support === */
-static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data)
+static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane,
+ struct drm_framebuffer *fb)
{
- struct armada_plane *dplane = data;
- struct drm_framebuffer *fb;
+ struct drm_framebuffer *old_fb;
- armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
+ old_fb = xchg(&dplane->old_fb, fb);
- spin_lock(&dplane->lock);
- fb = dplane->old_fb;
- dplane->old_fb = NULL;
- spin_unlock(&dplane->lock);
+ if (old_fb)
+ armada_drm_queue_unref_work(dplane->base.base.dev, old_fb);
+}
- if (fb)
- armada_drm_queue_unref_work(dcrtc->crtc.dev, fb);
+/* === Plane support === */
+static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
+ struct armada_plane *plane, struct armada_plane_work *work)
+{
+ struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base);
- wake_up(&dplane->vbl.wait);
+ armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
+ armada_ovl_retire_fb(dplane, NULL);
}
static int
-armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
{
- struct armada_plane *dplane = drm_to_armada_plane(plane);
+ struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct drm_rect src = {
.x1 = src_x,
@@ -160,9 +161,8 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
dcrtc->base + LCD_SPU_SRAM_PARA1);
}
- wait_event_timeout(dplane->vbl.wait,
- list_empty(&dplane->vbl.update.node),
- HZ/25);
+ if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0)
+ armada_drm_plane_work_cancel(dcrtc, &dplane->base);
if (plane->fb != fb) {
struct armada_gem_object *obj = drm_fb_obj(fb);
@@ -175,17 +175,8 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
*/
drm_framebuffer_reference(fb);
- if (plane->fb) {
- struct drm_framebuffer *older_fb;
-
- spin_lock_irq(&dplane->lock);
- older_fb = dplane->old_fb;
- dplane->old_fb = plane->fb;
- spin_unlock_irq(&dplane->lock);
- if (older_fb)
- armada_drm_queue_unref_work(dcrtc->crtc.dev,
- older_fb);
- }
+ if (plane->fb)
+ armada_ovl_retire_fb(dplane, plane->fb);
src_y = src.y1 >> 16;
src_x = src.x1 >> 16;
@@ -262,60 +253,50 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
}
if (idx) {
armada_reg_queue_end(dplane->vbl.regs, idx);
- armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update);
+ armada_drm_plane_work_queue(dcrtc, &dplane->base,
+ &dplane->vbl.work);
}
return 0;
}
-static int armada_plane_disable(struct drm_plane *plane)
+static int armada_ovl_plane_disable(struct drm_plane *plane)
{
- struct armada_plane *dplane = drm_to_armada_plane(plane);
+ struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
struct drm_framebuffer *fb;
struct armada_crtc *dcrtc;
- if (!dplane->base.crtc)
+ if (!dplane->base.base.crtc)
return 0;
- dcrtc = drm_to_armada_crtc(dplane->base.crtc);
- dcrtc->plane = NULL;
-
- spin_lock_irq(&dcrtc->irq_lock);
- armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update);
- armada_updatel(0, CFG_DMA_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
- dplane->ctrl0 = 0;
- spin_unlock_irq(&dcrtc->irq_lock);
+ dcrtc = drm_to_armada_crtc(dplane->base.base.crtc);
- /* Power down the Y/U/V FIFOs */
- armada_updatel(CFG_PDWN16x66 | CFG_PDWN32x66, 0,
- dcrtc->base + LCD_SPU_SRAM_PARA1);
+ armada_drm_plane_work_cancel(dcrtc, &dplane->base);
+ armada_drm_crtc_plane_disable(dcrtc, plane);
- if (plane->fb)
- drm_framebuffer_unreference(plane->fb);
+ dcrtc->plane = NULL;
+ dplane->ctrl0 = 0;
- spin_lock_irq(&dplane->lock);
- fb = dplane->old_fb;
- dplane->old_fb = NULL;
- spin_unlock_irq(&dplane->lock);
+ fb = xchg(&dplane->old_fb, NULL);
if (fb)
drm_framebuffer_unreference(fb);
return 0;
}
-static void armada_plane_destroy(struct drm_plane *plane)
+static void armada_ovl_plane_destroy(struct drm_plane *plane)
{
- struct armada_plane *dplane = drm_to_armada_plane(plane);
+ struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
drm_plane_cleanup(plane);
kfree(dplane);
}
-static int armada_plane_set_property(struct drm_plane *plane,
+static int armada_ovl_plane_set_property(struct drm_plane *plane,
struct drm_property *property, uint64_t val)
{
struct armada_private *priv = plane->dev->dev_private;
- struct armada_plane *dplane = drm_to_armada_plane(plane);
+ struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
bool update_attr = false;
if (property == priv->colorkey_prop) {
@@ -372,21 +353,21 @@ static int armada_plane_set_property(struct drm_plane *plane,
update_attr = true;
}
- if (update_attr && dplane->base.crtc)
+ if (update_attr && dplane->base.base.crtc)
armada_ovl_update_attr(&dplane->prop,
- drm_to_armada_crtc(dplane->base.crtc));
+ drm_to_armada_crtc(dplane->base.base.crtc));
return 0;
}
-static const struct drm_plane_funcs armada_plane_funcs = {
- .update_plane = armada_plane_update,
- .disable_plane = armada_plane_disable,
- .destroy = armada_plane_destroy,
- .set_property = armada_plane_set_property,
+static const struct drm_plane_funcs armada_ovl_plane_funcs = {
+ .update_plane = armada_ovl_plane_update,
+ .disable_plane = armada_ovl_plane_disable,
+ .destroy = armada_ovl_plane_destroy,
+ .set_property = armada_ovl_plane_set_property,
};
-static const uint32_t armada_formats[] = {
+static const uint32_t armada_ovl_formats[] = {
DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV,
DRM_FORMAT_YUV420,
@@ -456,7 +437,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
{
struct armada_private *priv = dev->dev_private;
struct drm_mode_object *mobj;
- struct armada_plane *dplane;
+ struct armada_ovl_plane *dplane;
int ret;
ret = armada_overlay_create_properties(dev);
@@ -467,13 +448,23 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
if (!dplane)
return -ENOMEM;
- spin_lock_init(&dplane->lock);
- init_waitqueue_head(&dplane->vbl.wait);
- armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl,
- dplane);
+ ret = armada_drm_plane_init(&dplane->base);
+ if (ret) {
+ kfree(dplane);
+ return ret;
+ }
+
+ dplane->vbl.work.fn = armada_ovl_plane_work;
- drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs,
- armada_formats, ARRAY_SIZE(armada_formats), false);
+ ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs,
+ &armada_ovl_plane_funcs,
+ armada_ovl_formats,
+ ARRAY_SIZE(armada_ovl_formats),
+ DRM_PLANE_TYPE_OVERLAY);
+ if (ret) {
+ kfree(dplane);
+ return ret;
+ }
dplane->prop.colorkey_yr = 0xfefefe00;
dplane->prop.colorkey_ug = 0x01010100;
@@ -483,7 +474,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
dplane->prop.contrast = 0x4000;
dplane->prop.saturation = 0x4000;
- mobj = &dplane->base.base;
+ mobj = &dplane->base.base.base;
drm_object_attach_property(mobj, priv->colorkey_prop,
0x0101fe);
drm_object_attach_property(mobj, priv->colorkey_min_prop,
diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c
deleted file mode 100644
index 00d0facb42f3..000000000000
--- a/drivers/gpu/drm/armada/armada_slave.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2012 Russell King
- * Rewritten from the dovefb driver, and Armada510 manuals.
- *
- * 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 <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_encoder_slave.h>
-#include "armada_drm.h"
-#include "armada_output.h"
-#include "armada_slave.h"
-
-static int armada_drm_slave_get_modes(struct drm_connector *conn)
-{
- struct drm_encoder *enc = armada_drm_connector_encoder(conn);
- int count = 0;
-
- if (enc) {
- struct drm_encoder_slave *slave = to_encoder_slave(enc);
-
- count = slave->slave_funcs->get_modes(enc, conn);
- }
-
- return count;
-}
-
-static void armada_drm_slave_destroy(struct drm_encoder *enc)
-{
- struct drm_encoder_slave *slave = to_encoder_slave(enc);
- struct i2c_client *client = drm_i2c_encoder_get_client(enc);
-
- if (slave->slave_funcs)
- slave->slave_funcs->destroy(enc);
- if (client)
- i2c_put_adapter(client->adapter);
-
- drm_encoder_cleanup(&slave->base);
- kfree(slave);
-}
-
-static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = {
- .destroy = armada_drm_slave_destroy,
-};
-
-static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = {
- .get_modes = armada_drm_slave_get_modes,
- .mode_valid = armada_drm_slave_encoder_mode_valid,
- .best_encoder = armada_drm_connector_encoder,
-};
-
-static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = {
- .dpms = drm_i2c_encoder_dpms,
- .save = drm_i2c_encoder_save,
- .restore = drm_i2c_encoder_restore,
- .mode_fixup = drm_i2c_encoder_mode_fixup,
- .prepare = drm_i2c_encoder_prepare,
- .commit = drm_i2c_encoder_commit,
- .mode_set = drm_i2c_encoder_mode_set,
- .detect = drm_i2c_encoder_detect,
-};
-
-static int
-armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
-{
- const struct armada_drm_slave_config *config = data;
- struct drm_encoder_slave *slave;
- struct i2c_adapter *adap;
- int ret;
-
- conn->interlace_allowed = config->interlace_allowed;
- conn->doublescan_allowed = config->doublescan_allowed;
- conn->polled = config->polled;
-
- drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);
-
- slave = kzalloc(sizeof(*slave), GFP_KERNEL);
- if (!slave)
- return -ENOMEM;
-
- slave->base.possible_crtcs = config->crtcs;
-
- adap = i2c_get_adapter(config->i2c_adapter_id);
- if (!adap) {
- kfree(slave);
- return -EPROBE_DEFER;
- }
-
- ret = drm_encoder_init(conn->dev, &slave->base,
- &armada_drm_slave_encoder_funcs,
- DRM_MODE_ENCODER_TMDS);
- if (ret) {
- DRM_ERROR("unable to init encoder\n");
- i2c_put_adapter(adap);
- kfree(slave);
- return ret;
- }
-
- ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
- i2c_put_adapter(adap);
- if (ret) {
- DRM_ERROR("unable to init encoder slave\n");
- armada_drm_slave_destroy(&slave->base);
- return ret;
- }
-
- drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);
-
- ret = slave->slave_funcs->create_resources(&slave->base, conn);
- if (ret) {
- armada_drm_slave_destroy(&slave->base);
- return ret;
- }
-
- ret = drm_mode_connector_attach_encoder(conn, &slave->base);
- if (ret) {
- armada_drm_slave_destroy(&slave->base);
- return ret;
- }
-
- conn->encoder = &slave->base;
-
- return ret;
-}
-
-static const struct armada_output_type armada_drm_conn_slave = {
- .connector_type = DRM_MODE_CONNECTOR_HDMIA,
- .create = armada_drm_conn_slave_create,
- .set_property = armada_drm_slave_encoder_set_property,
-};
-
-int armada_drm_connector_slave_create(struct drm_device *dev,
- const struct armada_drm_slave_config *config)
-{
- return armada_output_create(dev, &armada_drm_conn_slave, config);
-}
diff --git a/drivers/gpu/drm/armada/armada_slave.h b/drivers/gpu/drm/armada/armada_slave.h
deleted file mode 100644
index bf2374c96fc1..000000000000
--- a/drivers/gpu/drm/armada/armada_slave.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2012 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 ARMADA_SLAVE_H
-#define ARMADA_SLAVE_H
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-
-struct armada_drm_slave_config {
- int i2c_adapter_id;
- uint32_t crtcs;
- uint8_t polled;
- bool interlace_allowed;
- bool doublescan_allowed;
- struct i2c_board_info info;
-};
-
-int armada_drm_connector_slave_create(struct drm_device *dev,
- const struct armada_drm_slave_config *);
-
-#endif
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 86205a28e56b..05f6522c0457 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -315,6 +315,7 @@ int ast_framebuffer_init(struct drm_device *dev,
int ast_fbdev_init(struct drm_device *dev);
void ast_fbdev_fini(struct drm_device *dev);
void ast_fbdev_set_suspend(struct drm_device *dev, int state);
+void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr);
struct ast_bo {
struct ttm_buffer_object bo;
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index f31db28a684b..a37e7ea4a00c 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -365,3 +365,10 @@ void ast_fbdev_set_suspend(struct drm_device *dev, int state)
drm_fb_helper_set_suspend(&ast->fbdev->helper, state);
}
+
+void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr)
+{
+ ast->fbdev->helper.fbdev->fix.smem_start =
+ ast->fbdev->helper.fbdev->apertures->ranges[0].base + gpu_addr;
+ ast->fbdev->helper.fbdev->fix.smem_len = ast->vram_size - gpu_addr;
+}
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 838217f8ce7d..541a610667ad 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -448,6 +448,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
dev->mode_config.min_height = 0;
dev->mode_config.preferred_depth = 24;
dev->mode_config.prefer_shadow = 1;
+ dev->mode_config.fb_base = pci_resource_start(ast->dev->pdev, 0);
if (ast->chip == AST2100 ||
ast->chip == AST2200 ||
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index b7ee2634e47c..69d19f3304a5 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -547,6 +547,8 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
if (ret)
DRM_ERROR("failed to kmap fbcon\n");
+ else
+ ast_fbdev_set_base(ast, gpu_addr);
}
ast_bo_unreserve(bo);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 8bc62ec407f9..244df0a440b7 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -656,7 +656,8 @@ static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
}
-static int atmel_hlcdc_dc_enable_vblank(struct drm_device *dev, int crtc)
+static int atmel_hlcdc_dc_enable_vblank(struct drm_device *dev,
+ unsigned int pipe)
{
struct atmel_hlcdc_dc *dc = dev->dev_private;
@@ -666,7 +667,8 @@ static int atmel_hlcdc_dc_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-static void atmel_hlcdc_dc_disable_vblank(struct drm_device *dev, int crtc)
+static void atmel_hlcdc_dc_disable_vblank(struct drm_device *dev,
+ unsigned int pipe)
{
struct atmel_hlcdc_dc *dc = dev->dev_private;
@@ -697,7 +699,7 @@ static struct drm_driver atmel_hlcdc_dc_driver = {
.irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
.irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
.irq_uninstall = atmel_hlcdc_dc_irq_uninstall,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = atmel_hlcdc_dc_enable_vblank,
.disable_vblank = atmel_hlcdc_dc_disable_vblank,
.gem_free_object = drm_gem_cma_free_object,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index be9fa8220499..d0299aed517e 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -633,7 +633,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
if (!state->bpp[i])
return -EINVAL;
- switch (state->base.rotation & 0xf) {
+ switch (state->base.rotation & DRM_ROTATE_MASK) {
case BIT(DRM_ROTATE_90):
offset = ((y_offset + state->src_y + patched_src_w - 1) /
ydiv) * fb->pitches[i];
@@ -712,11 +712,13 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
}
static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
+ if (!new_state->fb)
+ return 0;
+
return atmel_hlcdc_layer_update_start(&plane->layer);
}
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 2de52a53a803..6dddd392aa42 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -11,6 +11,18 @@ config DRM_DW_HDMI
tristate
select DRM_KMS_HELPER
+config DRM_DW_HDMI_AHB_AUDIO
+ tristate "Synopsis Designware AHB Audio interface"
+ depends on DRM_DW_HDMI && SND
+ select SND_PCM
+ select SND_PCM_ELD
+ select SND_PCM_IEC958
+ help
+ Support the AHB Audio interface which is part of the Synopsis
+ Designware HDMI block. This is used in conjunction with
+ the i.MX6 HDMI driver.
+
+
config DRM_NXP_PTN3460
tristate "NXP PTN3460 DP/LVDS bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index e2eef1c2f4c3..d4e28beec30e 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,5 +1,6 @@
ccflags-y := -Iinclude/drm
obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw_hdmi-ahb-audio.o
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
new file mode 100644
index 000000000000..59f630f1c61a
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
@@ -0,0 +1,653 @@
+/*
+ * DesignWare HDMI audio driver
+ *
+ * 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.
+ *
+ * Written and tested against the Designware HDMI Tx found in iMX6.
+ */
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_edid.h>
+
+#include <sound/asoundef.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
+#include <sound/pcm_iec958.h>
+
+#include "dw_hdmi-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-ahb-audio"
+
+/* Provide some bits rather than bit offsets */
+enum {
+ HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7),
+ HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3),
+ HDMI_AHB_DMA_START_START = BIT(0),
+ HDMI_AHB_DMA_STOP_STOP = BIT(0),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL =
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR |
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST |
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY |
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE |
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL |
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY,
+ HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5),
+ HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4),
+ HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3),
+ HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2),
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
+ HDMI_IH_AHBDMAAUD_STAT0_ALL =
+ HDMI_IH_AHBDMAAUD_STAT0_ERROR |
+ HDMI_IH_AHBDMAAUD_STAT0_LOST |
+ HDMI_IH_AHBDMAAUD_STAT0_RETRY |
+ HDMI_IH_AHBDMAAUD_STAT0_DONE |
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL |
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY,
+ HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1,
+ HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1,
+ HDMI_AHB_DMA_CONF0_INCR4 = 0,
+ HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0),
+ HDMI_AHB_DMA_MASK_DONE = BIT(7),
+
+ HDMI_REVISION_ID = 0x0001,
+ HDMI_IH_AHBDMAAUD_STAT0 = 0x0109,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189,
+ HDMI_FC_AUDICONF2 = 0x1027,
+ HDMI_FC_AUDSCONF = 0x1063,
+ HDMI_FC_AUDSCONF_LAYOUT1 = 1 << 0,
+ HDMI_FC_AUDSCONF_LAYOUT0 = 0 << 0,
+ HDMI_AHB_DMA_CONF0 = 0x3600,
+ HDMI_AHB_DMA_START = 0x3601,
+ HDMI_AHB_DMA_STOP = 0x3602,
+ HDMI_AHB_DMA_THRSLD = 0x3603,
+ HDMI_AHB_DMA_STRADDR0 = 0x3604,
+ HDMI_AHB_DMA_STPADDR0 = 0x3608,
+ HDMI_AHB_DMA_MASK = 0x3614,
+ HDMI_AHB_DMA_POL = 0x3615,
+ HDMI_AHB_DMA_CONF1 = 0x3616,
+ HDMI_AHB_DMA_BUFFPOL = 0x361a,
+};
+
+struct dw_hdmi_channel_conf {
+ u8 conf1;
+ u8 ca;
+};
+
+/*
+ * The default mapping of ALSA channels to HDMI channels and speaker
+ * allocation bits. Note that we can't do channel remapping here -
+ * channels must be in the same order.
+ *
+ * Mappings for alsa-lib pcm/surround*.conf files:
+ *
+ * Front Sur4.0 Sur4.1 Sur5.0 Sur5.1 Sur7.1
+ * Channels 2 4 6 6 6 8
+ *
+ * Our mapping from ALSA channel to CEA686D speaker name and HDMI channel:
+ *
+ * Number of ALSA channels
+ * ALSA Channel 2 3 4 5 6 7 8
+ * 0 FL:0 = = = = = =
+ * 1 FR:1 = = = = = =
+ * 2 FC:3 RL:4 LFE:2 = = =
+ * 3 RR:5 RL:4 FC:3 = =
+ * 4 RR:5 RL:4 = =
+ * 5 RR:5 = =
+ * 6 RC:6 =
+ * 7 RLC/FRC RLC/FRC
+ */
+static struct dw_hdmi_channel_conf default_hdmi_channel_config[7] = {
+ { 0x03, 0x00 }, /* FL,FR */
+ { 0x0b, 0x02 }, /* FL,FR,FC */
+ { 0x33, 0x08 }, /* FL,FR,RL,RR */
+ { 0x37, 0x09 }, /* FL,FR,LFE,RL,RR */
+ { 0x3f, 0x0b }, /* FL,FR,LFE,FC,RL,RR */
+ { 0x7f, 0x0f }, /* FL,FR,LFE,FC,RL,RR,RC */
+ { 0xff, 0x13 }, /* FL,FR,LFE,FC,RL,RR,[FR]RC,[FR]LC */
+};
+
+struct snd_dw_hdmi {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ spinlock_t lock;
+ struct dw_hdmi_audio_data data;
+ struct snd_pcm_substream *substream;
+ void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
+ void *buf_src;
+ void *buf_dst;
+ dma_addr_t buf_addr;
+ unsigned buf_offset;
+ unsigned buf_period;
+ unsigned buf_size;
+ unsigned channels;
+ u8 revision;
+ u8 iec_offset;
+ u8 cs[192][8];
+};
+
+static void dw_hdmi_writel(u32 val, void __iomem *ptr)
+{
+ writeb_relaxed(val, ptr);
+ writeb_relaxed(val >> 8, ptr + 1);
+ writeb_relaxed(val >> 16, ptr + 2);
+ writeb_relaxed(val >> 24, ptr + 3);
+}
+
+/*
+ * Convert to hardware format: The userspace buffer contains IEC958 samples,
+ * with the PCUV bits in bits 31..28 and audio samples in bits 27..4. We
+ * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
+ * samples in 23..0.
+ *
+ * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
+ *
+ * Ideally, we could do with having the data properly formatted in userspace.
+ */
+static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
+ size_t offset, size_t bytes)
+{
+ u32 *src = dw->buf_src + offset;
+ u32 *dst = dw->buf_dst + offset;
+ u32 *end = dw->buf_src + offset + bytes;
+
+ do {
+ u32 b, sample = *src++;
+
+ b = (sample & 8) << (28 - 3);
+
+ sample >>= 4;
+
+ *dst++ = sample | b;
+ } while (src < end);
+}
+
+static u32 parity(u32 sample)
+{
+ sample ^= sample >> 16;
+ sample ^= sample >> 8;
+ sample ^= sample >> 4;
+ sample ^= sample >> 2;
+ sample ^= sample >> 1;
+ return (sample & 1) << 27;
+}
+
+static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw,
+ size_t offset, size_t bytes)
+{
+ u32 *src = dw->buf_src + offset;
+ u32 *dst = dw->buf_dst + offset;
+ u32 *end = dw->buf_src + offset + bytes;
+
+ do {
+ unsigned i;
+ u8 *cs;
+
+ cs = dw->cs[dw->iec_offset++];
+ if (dw->iec_offset >= 192)
+ dw->iec_offset = 0;
+
+ i = dw->channels;
+ do {
+ u32 sample = *src++;
+
+ sample &= ~0xff000000;
+ sample |= *cs++ << 24;
+ sample |= parity(sample & ~0xf8000000);
+
+ *dst++ = sample;
+ } while (--i);
+ } while (src < end);
+}
+
+static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
+ struct snd_pcm_runtime *runtime)
+{
+ u8 cs[4];
+ unsigned ch, i, j;
+
+ snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs));
+
+ memset(dw->cs, 0, sizeof(dw->cs));
+
+ for (ch = 0; ch < 8; ch++) {
+ cs[2] &= ~IEC958_AES2_CON_CHANNEL;
+ cs[2] |= (ch + 1) << 4;
+
+ for (i = 0; i < ARRAY_SIZE(cs); i++) {
+ unsigned c = cs[i];
+
+ for (j = 0; j < 8; j++, c >>= 1)
+ dw->cs[i * 8 + j][ch] = (c & 1) << 2;
+ }
+ }
+ dw->cs[0][0] |= BIT(4);
+}
+
+static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw)
+{
+ void __iomem *base = dw->data.base;
+ unsigned offset = dw->buf_offset;
+ unsigned period = dw->buf_period;
+ u32 start, stop;
+
+ dw->reformat(dw, offset, period);
+
+ /* Clear all irqs before enabling irqs and starting DMA */
+ writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL,
+ base + HDMI_IH_AHBDMAAUD_STAT0);
+
+ start = dw->buf_addr + offset;
+ stop = start + period - 1;
+
+ /* Setup the hardware start/stop addresses */
+ dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0);
+ dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0);
+
+ writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK);
+ writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START);
+
+ offset += period;
+ if (offset >= dw->buf_size)
+ offset = 0;
+ dw->buf_offset = offset;
+}
+
+static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw)
+{
+ /* Disable interrupts before disabling DMA */
+ writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK);
+ writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP);
+}
+
+static irqreturn_t snd_dw_hdmi_irq(int irq, void *data)
+{
+ struct snd_dw_hdmi *dw = data;
+ struct snd_pcm_substream *substream;
+ unsigned stat;
+
+ stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
+ if (!stat)
+ return IRQ_NONE;
+
+ writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
+
+ substream = dw->substream;
+ if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) {
+ snd_pcm_period_elapsed(substream);
+
+ spin_lock(&dw->lock);
+ if (dw->substream)
+ dw_hdmi_start_dma(dw);
+ spin_unlock(&dw->lock);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct snd_pcm_hardware dw_hdmi_hw = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_176400 |
+ SNDRV_PCM_RATE_192000,
+ .channels_min = 2,
+ .channels_max = 8,
+ .buffer_bytes_max = 1024 * 1024,
+ .period_bytes_min = 256,
+ .period_bytes_max = 8192, /* ERR004323: must limit to 8k */
+ .periods_min = 2,
+ .periods_max = 16,
+ .fifo_size = 0,
+};
+
+static int dw_hdmi_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dw_hdmi *dw = substream->private_data;
+ void __iomem *base = dw->data.base;
+ int ret;
+
+ runtime->hw = dw_hdmi_hw;
+
+ ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_pcm_limit_hw_rates(runtime);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ /* Limit the buffer size to the size of the preallocated buffer */
+ ret = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ 0, substream->dma_buffer.bytes);
+ if (ret < 0)
+ return ret;
+
+ /* Clear FIFO */
+ writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST,
+ base + HDMI_AHB_DMA_CONF0);
+
+ /* Configure interrupt polarities */
+ writeb_relaxed(~0, base + HDMI_AHB_DMA_POL);
+ writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL);
+
+ /* Keep interrupts masked, and clear any pending */
+ writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK);
+ writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0);
+
+ ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
+ "dw-hdmi-audio", dw);
+ if (ret)
+ return ret;
+
+ /* Un-mute done interrupt */
+ writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL &
+ ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE,
+ base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+ return 0;
+}
+
+static int dw_hdmi_close(struct snd_pcm_substream *substream)
+{
+ struct snd_dw_hdmi *dw = substream->private_data;
+
+ /* Mute all interrupts */
+ writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
+ dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+ free_irq(dw->data.irq, dw);
+
+ return 0;
+}
+
+static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ /* Allocate the PCM runtime buffer, which is exposed to userspace. */
+ return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(params));
+}
+
+static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dw_hdmi *dw = substream->private_data;
+ u8 threshold, conf0, conf1, layout, ca;
+
+ /* Setup as per 3.0.5 FSL 4.1.0 BSP */
+ switch (dw->revision) {
+ case 0x0a:
+ conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
+ HDMI_AHB_DMA_CONF0_INCR4;
+ if (runtime->channels == 2)
+ threshold = 126;
+ else
+ threshold = 124;
+ break;
+ case 0x1a:
+ conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
+ HDMI_AHB_DMA_CONF0_INCR8;
+ threshold = 128;
+ break;
+ default:
+ /* NOTREACHED */
+ return -EINVAL;
+ }
+
+ dw_hdmi_set_sample_rate(dw->data.hdmi, runtime->rate);
+
+ /* Minimum number of bytes in the fifo. */
+ runtime->hw.fifo_size = threshold * 32;
+
+ conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK;
+ conf1 = default_hdmi_channel_config[runtime->channels - 2].conf1;
+ ca = default_hdmi_channel_config[runtime->channels - 2].ca;
+
+ /*
+ * For >2 channel PCM audio, we need to select layout 1
+ * and set an appropriate channel map.
+ */
+ if (runtime->channels > 2)
+ layout = HDMI_FC_AUDSCONF_LAYOUT1;
+ else
+ layout = HDMI_FC_AUDSCONF_LAYOUT0;
+
+ writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD);
+ writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0);
+ writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1);
+ writeb_relaxed(layout, dw->data.base + HDMI_FC_AUDSCONF);
+ writeb_relaxed(ca, dw->data.base + HDMI_FC_AUDICONF2);
+
+ switch (runtime->format) {
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+ dw->reformat = dw_hdmi_reformat_iec958;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ dw_hdmi_create_cs(dw, runtime);
+ dw->reformat = dw_hdmi_reformat_s24;
+ break;
+ }
+ dw->iec_offset = 0;
+ dw->channels = runtime->channels;
+ dw->buf_src = runtime->dma_area;
+ dw->buf_dst = substream->dma_buffer.area;
+ dw->buf_addr = substream->dma_buffer.addr;
+ dw->buf_period = snd_pcm_lib_period_bytes(substream);
+ dw->buf_size = snd_pcm_lib_buffer_bytes(substream);
+
+ return 0;
+}
+
+static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_dw_hdmi *dw = substream->private_data;
+ unsigned long flags;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ spin_lock_irqsave(&dw->lock, flags);
+ dw->buf_offset = 0;
+ dw->substream = substream;
+ dw_hdmi_start_dma(dw);
+ dw_hdmi_audio_enable(dw->data.hdmi);
+ spin_unlock_irqrestore(&dw->lock, flags);
+ substream->runtime->delay = substream->runtime->period_size;
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ spin_lock_irqsave(&dw->lock, flags);
+ dw->substream = NULL;
+ dw_hdmi_stop_dma(dw);
+ dw_hdmi_audio_disable(dw->data.hdmi);
+ spin_unlock_irqrestore(&dw->lock, flags);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dw_hdmi *dw = substream->private_data;
+
+ /*
+ * We are unable to report the exact hardware position as
+ * reading the 32-bit DMA position using 8-bit reads is racy.
+ */
+ return bytes_to_frames(runtime, dw->buf_offset);
+}
+
+static struct snd_pcm_ops snd_dw_hdmi_ops = {
+ .open = dw_hdmi_open,
+ .close = dw_hdmi_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = dw_hdmi_hw_params,
+ .hw_free = dw_hdmi_hw_free,
+ .prepare = dw_hdmi_prepare,
+ .trigger = dw_hdmi_trigger,
+ .pointer = dw_hdmi_pointer,
+ .page = snd_pcm_lib_get_vmalloc_page,
+};
+
+static int snd_dw_hdmi_probe(struct platform_device *pdev)
+{
+ const struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
+ struct device *dev = pdev->dev.parent;
+ struct snd_dw_hdmi *dw;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ unsigned revision;
+ int ret;
+
+ writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
+ data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+ revision = readb_relaxed(data->base + HDMI_REVISION_ID);
+ if (revision != 0x0a && revision != 0x1a) {
+ dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n",
+ revision);
+ return -ENXIO;
+ }
+
+ ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, sizeof(struct snd_dw_hdmi), &card);
+ if (ret < 0)
+ return ret;
+
+ strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+ strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname));
+ snprintf(card->longname, sizeof(card->longname),
+ "%s rev 0x%02x, irq %d", card->shortname, revision,
+ data->irq);
+
+ dw = card->private_data;
+ dw->card = card;
+ dw->data = *data;
+ dw->revision = revision;
+
+ spin_lock_init(&dw->lock);
+
+ ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm);
+ if (ret < 0)
+ goto err;
+
+ dw->pcm = pcm;
+ pcm->private_data = dw;
+ strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops);
+
+ /*
+ * To support 8-channel 96kHz audio reliably, we need 512k
+ * to satisfy alsa with our restricted period (ERR004323).
+ */
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ dev, 128 * 1024, 1024 * 1024);
+
+ ret = snd_card_register(card);
+ if (ret < 0)
+ goto err;
+
+ platform_set_drvdata(pdev, dw);
+
+ return 0;
+
+err:
+ snd_card_free(card);
+ return ret;
+}
+
+static int snd_dw_hdmi_remove(struct platform_device *pdev)
+{
+ struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
+
+ snd_card_free(dw->card);
+
+ return 0;
+}
+
+#if defined(CONFIG_PM_SLEEP) && defined(IS_NOT_BROKEN)
+/*
+ * This code is fine, but requires implementation in the dw_hdmi_trigger()
+ * method which is currently missing as I have no way to test this.
+ */
+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;
+}
+
+static int snd_dw_hdmi_resume(struct device *dev)
+{
+ struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
+
+ snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
+ snd_dw_hdmi_resume);
+#define PM_OPS &snd_dw_hdmi_pm
+#else
+#define PM_OPS NULL
+#endif
+
+static struct platform_driver snd_dw_hdmi_driver = {
+ .probe = snd_dw_hdmi_probe,
+ .remove = snd_dw_hdmi_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = PM_OPS,
+ },
+};
+
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Synopsis Designware HDMI AHB ALSA interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-audio.h
new file mode 100644
index 000000000000..91f631beecc7
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-audio.h
@@ -0,0 +1,14 @@
+#ifndef DW_HDMI_AUDIO_H
+#define DW_HDMI_AUDIO_H
+
+struct dw_hdmi;
+
+struct dw_hdmi_audio_data {
+ phys_addr_t phys;
+ void __iomem *base;
+ int irq;
+ struct dw_hdmi *hdmi;
+ u8 *eld;
+};
+
+#endif
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0083d4e7e7e2..56de9f1c95fc 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -28,6 +28,7 @@
#include <drm/bridge/dw_hdmi.h>
#include "dw_hdmi.h"
+#include "dw_hdmi-audio.h"
#define HDMI_EDID_LEN 512
@@ -104,6 +105,7 @@ struct dw_hdmi {
struct drm_encoder *encoder;
struct drm_bridge *bridge;
+ struct platform_device *audio;
enum dw_hdmi_devtype dev_type;
struct device *dev;
struct clk *isfr_clk;
@@ -126,7 +128,11 @@ struct dw_hdmi {
bool sink_has_audio;
struct mutex mutex; /* for state below and previous_mode */
+ enum drm_connector_force force; /* mutex-protected force state */
bool disabled; /* DRM has disabled our bridge */
+ bool bridge_is_on; /* indicates the bridge is on */
+ bool rxsense; /* rxsense state */
+ u8 phy_mask; /* desired phy int mask settings */
spinlock_t audio_lock;
struct mutex audio_mutex;
@@ -134,12 +140,19 @@ struct dw_hdmi {
unsigned int audio_cts;
unsigned int audio_n;
bool audio_enable;
- int ratio;
void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read)(struct dw_hdmi *hdmi, int offset);
};
+#define HDMI_IH_PHY_STAT0_RX_SENSE \
+ (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \
+ HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3)
+
+#define HDMI_PHY_RX_SENSE \
+ (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
+ HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
+
static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
{
writel(val, hdmi->regs + (offset << 2));
@@ -203,61 +216,53 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
}
-static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
- unsigned int ratio)
+static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
{
unsigned int n = (128 * freq) / 1000;
+ unsigned int mult = 1;
+
+ while (freq > 48000) {
+ mult *= 2;
+ freq /= 2;
+ }
switch (freq) {
case 32000:
- if (pixel_clk == 25170000)
- n = (ratio == 150) ? 9152 : 4576;
- else if (pixel_clk == 27020000)
- n = (ratio == 150) ? 8192 : 4096;
- else if (pixel_clk == 74170000 || pixel_clk == 148350000)
+ if (pixel_clk == 25175000)
+ n = 4576;
+ else if (pixel_clk == 27027000)
+ n = 4096;
+ else if (pixel_clk == 74176000 || pixel_clk == 148352000)
n = 11648;
else
n = 4096;
+ n *= mult;
break;
case 44100:
- if (pixel_clk == 25170000)
+ if (pixel_clk == 25175000)
n = 7007;
- else if (pixel_clk == 74170000)
+ else if (pixel_clk == 74176000)
n = 17836;
- else if (pixel_clk == 148350000)
- n = (ratio == 150) ? 17836 : 8918;
+ else if (pixel_clk == 148352000)
+ n = 8918;
else
n = 6272;
+ n *= mult;
break;
case 48000:
- if (pixel_clk == 25170000)
- n = (ratio == 150) ? 9152 : 6864;
- else if (pixel_clk == 27020000)
- n = (ratio == 150) ? 8192 : 6144;
- else if (pixel_clk == 74170000)
+ if (pixel_clk == 25175000)
+ n = 6864;
+ else if (pixel_clk == 27027000)
+ n = 6144;
+ else if (pixel_clk == 74176000)
n = 11648;
- else if (pixel_clk == 148350000)
- n = (ratio == 150) ? 11648 : 5824;
+ else if (pixel_clk == 148352000)
+ n = 5824;
else
n = 6144;
- break;
-
- case 88200:
- n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
- break;
-
- case 96000:
- n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
- break;
-
- case 176400:
- n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
- break;
-
- case 192000:
- n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
+ n *= mult;
break;
default:
@@ -267,93 +272,29 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
return n;
}
-static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
- unsigned int ratio)
-{
- unsigned int cts = 0;
-
- pr_debug("%s: freq: %d pixel_clk: %ld ratio: %d\n", __func__, freq,
- pixel_clk, ratio);
-
- switch (freq) {
- case 32000:
- if (pixel_clk == 297000000) {
- cts = 222750;
- break;
- }
- case 48000:
- case 96000:
- case 192000:
- switch (pixel_clk) {
- case 25200000:
- case 27000000:
- case 54000000:
- case 74250000:
- case 148500000:
- cts = pixel_clk / 1000;
- break;
- case 297000000:
- cts = 247500;
- break;
- /*
- * All other TMDS clocks are not supported by
- * DWC_hdmi_tx. The TMDS clocks divided or
- * multiplied by 1,001 coefficients are not
- * supported.
- */
- default:
- break;
- }
- break;
- case 44100:
- case 88200:
- case 176400:
- switch (pixel_clk) {
- case 25200000:
- cts = 28000;
- break;
- case 27000000:
- cts = 30000;
- break;
- case 54000000:
- cts = 60000;
- break;
- case 74250000:
- cts = 82500;
- break;
- case 148500000:
- cts = 165000;
- break;
- case 297000000:
- cts = 247500;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- if (ratio == 100)
- return cts;
- return (cts * ratio) / 100;
-}
-
static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
- unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
+ unsigned long pixel_clk, unsigned int sample_rate)
{
+ unsigned long ftdms = pixel_clk;
unsigned int n, cts;
+ u64 tmp;
- n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
- cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
- if (!cts) {
- dev_err(hdmi->dev,
- "%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
- __func__, pixel_clk, sample_rate);
- }
+ n = hdmi_compute_n(sample_rate, pixel_clk);
+
+ /*
+ * Compute the CTS value from the N value. Note that CTS and N
+ * can be up to 20 bits in total, so we need 64-bit math. Also
+ * note that our TDMS clock is not fully accurate; it is accurate
+ * to kHz. This can introduce an unnecessary remainder in the
+ * calculation below, so we don't try to warn about that.
+ */
+ tmp = (u64)ftdms * n;
+ do_div(tmp, 128 * sample_rate);
+ cts = tmp;
- dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
- __func__, sample_rate, ratio, pixel_clk, n, cts);
+ dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
+ __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
+ n, cts);
spin_lock_irq(&hdmi->audio_lock);
hdmi->audio_n = n;
@@ -365,8 +306,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
{
mutex_lock(&hdmi->audio_mutex);
- hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
- hdmi->ratio);
+ hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate);
mutex_unlock(&hdmi->audio_mutex);
}
@@ -374,7 +314,7 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
{
mutex_lock(&hdmi->audio_mutex);
hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
- hdmi->sample_rate, hdmi->ratio);
+ hdmi->sample_rate);
mutex_unlock(&hdmi->audio_mutex);
}
@@ -383,7 +323,7 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
mutex_lock(&hdmi->audio_mutex);
hdmi->sample_rate = rate;
hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
- hdmi->sample_rate, hdmi->ratio);
+ hdmi->sample_rate);
mutex_unlock(&hdmi->audio_mutex);
}
EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
@@ -1063,6 +1003,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
u8 inv_val;
struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
+ unsigned int vdisplay;
vmode->mpixelclock = mode->clock * 1000;
@@ -1102,13 +1043,29 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
+ vdisplay = mode->vdisplay;
+ vblank = mode->vtotal - mode->vdisplay;
+ v_de_vs = mode->vsync_start - mode->vdisplay;
+ vsync_len = mode->vsync_end - mode->vsync_start;
+
+ /*
+ * When we're setting an interlaced mode, we need
+ * to adjust the vertical timing to suit.
+ */
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+ vdisplay /= 2;
+ vblank /= 2;
+ v_de_vs /= 2;
+ vsync_len /= 2;
+ }
+
/* Set up horizontal active pixel width */
hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
/* Set up vertical active lines */
- hdmi_writeb(hdmi, mode->vdisplay >> 8, HDMI_FC_INVACTV1);
- hdmi_writeb(hdmi, mode->vdisplay, HDMI_FC_INVACTV0);
+ hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1);
+ hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
/* Set up horizontal blanking pixel region width */
hblank = mode->htotal - mode->hdisplay;
@@ -1116,7 +1073,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
/* Set up vertical blanking pixel region width */
- vblank = mode->vtotal - mode->vdisplay;
hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
/* Set up HSYNC active edge delay width (in pixel clks) */
@@ -1125,7 +1081,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
/* Set up VSYNC active edge delay (in lines) */
- v_de_vs = mode->vsync_start - mode->vdisplay;
hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
/* Set up HSYNC active pulse width (in pixel clks) */
@@ -1134,7 +1089,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
/* Set up VSYNC active edge delay (in lines) */
- vsync_len = mode->vsync_end - mode->vsync_start;
hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
}
@@ -1302,10 +1256,11 @@ static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
HDMI_PHY_I2CM_CTLINT_ADDR);
/* enable cable hot plug irq */
- hdmi_writeb(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
/* Clear Hotplug interrupts */
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+ HDMI_IH_PHY_STAT0);
return 0;
}
@@ -1364,12 +1319,61 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
{
+ hdmi->bridge_is_on = true;
dw_hdmi_setup(hdmi, &hdmi->previous_mode);
}
static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
{
dw_hdmi_phy_disable(hdmi);
+ hdmi->bridge_is_on = false;
+}
+
+static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
+{
+ int force = hdmi->force;
+
+ if (hdmi->disabled) {
+ force = DRM_FORCE_OFF;
+ } else if (force == DRM_FORCE_UNSPECIFIED) {
+ if (hdmi->rxsense)
+ force = DRM_FORCE_ON;
+ else
+ force = DRM_FORCE_OFF;
+ }
+
+ if (force == DRM_FORCE_OFF) {
+ if (hdmi->bridge_is_on)
+ dw_hdmi_poweroff(hdmi);
+ } else {
+ if (!hdmi->bridge_is_on)
+ dw_hdmi_poweron(hdmi);
+ }
+}
+
+/*
+ * Adjust the detection of RXSENSE according to whether we have a forced
+ * connection mode enabled, or whether we have been disabled. There is
+ * no point processing RXSENSE interrupts if we have a forced connection
+ * state, or DRM has us disabled.
+ *
+ * We also disable rxsense interrupts when we think we're disconnected
+ * to avoid floating TDMS signals giving false rxsense interrupts.
+ *
+ * Note: we still need to listen for HPD interrupts even when DRM has us
+ * disabled so that we can detect a connect event.
+ */
+static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
+{
+ u8 old_mask = hdmi->phy_mask;
+
+ if (hdmi->force || hdmi->disabled || !hdmi->rxsense)
+ hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
+ else
+ hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
+
+ if (old_mask != hdmi->phy_mask)
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
}
static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
@@ -1399,7 +1403,8 @@ static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
mutex_lock(&hdmi->mutex);
hdmi->disabled = true;
- dw_hdmi_poweroff(hdmi);
+ dw_hdmi_update_power(hdmi);
+ dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
}
@@ -1408,8 +1413,9 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
struct dw_hdmi *hdmi = bridge->driver_private;
mutex_lock(&hdmi->mutex);
- dw_hdmi_poweron(hdmi);
hdmi->disabled = false;
+ dw_hdmi_update_power(hdmi);
+ dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
}
@@ -1424,6 +1430,12 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
connector);
+ mutex_lock(&hdmi->mutex);
+ hdmi->force = DRM_FORCE_UNSPECIFIED;
+ dw_hdmi_update_power(hdmi);
+ dw_hdmi_update_phy_mask(hdmi);
+ mutex_unlock(&hdmi->mutex);
+
return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
connector_status_connected : connector_status_disconnected;
}
@@ -1447,6 +1459,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
+ /* Store the ELD */
+ drm_edid_to_eld(connector, edid);
kfree(edid);
} else {
dev_dbg(hdmi->dev, "failed to get edid\n");
@@ -1488,11 +1502,24 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
}
+static void dw_hdmi_connector_force(struct drm_connector *connector)
+{
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
+ connector);
+
+ mutex_lock(&hdmi->mutex);
+ hdmi->force = connector->force;
+ dw_hdmi_update_power(hdmi);
+ dw_hdmi_update_phy_mask(hdmi);
+ mutex_unlock(&hdmi->mutex);
+}
+
static struct drm_connector_funcs dw_hdmi_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = dw_hdmi_connector_detect,
.destroy = dw_hdmi_connector_destroy,
+ .force = dw_hdmi_connector_force,
};
static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
@@ -1525,33 +1552,69 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
{
struct dw_hdmi *hdmi = dev_id;
- u8 intr_stat;
- u8 phy_int_pol;
+ u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat;
intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
-
phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
+ phy_stat = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+
+ phy_pol_mask = 0;
+ if (intr_stat & HDMI_IH_PHY_STAT0_HPD)
+ phy_pol_mask |= HDMI_PHY_HPD;
+ if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0)
+ phy_pol_mask |= HDMI_PHY_RX_SENSE0;
+ if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE1)
+ phy_pol_mask |= HDMI_PHY_RX_SENSE1;
+ if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE2)
+ phy_pol_mask |= HDMI_PHY_RX_SENSE2;
+ if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE3)
+ phy_pol_mask |= HDMI_PHY_RX_SENSE3;
+
+ if (phy_pol_mask)
+ hdmi_modb(hdmi, ~phy_int_pol, phy_pol_mask, HDMI_PHY_POL0);
- if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
- hdmi_modb(hdmi, ~phy_int_pol, HDMI_PHY_HPD, HDMI_PHY_POL0);
+ /*
+ * RX sense tells us whether the TDMS transmitters are detecting
+ * load - in other words, there's something listening on the
+ * other end of the link. Use this to decide whether we should
+ * power on the phy as HPD may be toggled by the sink to merely
+ * ask the source to re-read the EDID.
+ */
+ if (intr_stat &
+ (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
mutex_lock(&hdmi->mutex);
- if (phy_int_pol & HDMI_PHY_HPD) {
- dev_dbg(hdmi->dev, "EVENT=plugin\n");
-
- if (!hdmi->disabled)
- dw_hdmi_poweron(hdmi);
- } else {
- dev_dbg(hdmi->dev, "EVENT=plugout\n");
-
- if (!hdmi->disabled)
- dw_hdmi_poweroff(hdmi);
+ if (!hdmi->disabled && !hdmi->force) {
+ /*
+ * If the RX sense status indicates we're disconnected,
+ * clear the software rxsense status.
+ */
+ if (!(phy_stat & HDMI_PHY_RX_SENSE))
+ hdmi->rxsense = false;
+
+ /*
+ * Only set the software rxsense status when both
+ * rxsense and hpd indicates we're connected.
+ * This avoids what seems to be bad behaviour in
+ * at least iMX6S versions of the phy.
+ */
+ if (phy_stat & HDMI_PHY_HPD)
+ hdmi->rxsense = true;
+
+ dw_hdmi_update_power(hdmi);
+ dw_hdmi_update_phy_mask(hdmi);
}
mutex_unlock(&hdmi->mutex);
+ }
+
+ if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
+ dev_dbg(hdmi->dev, "EVENT=%s\n",
+ phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
drm_helper_hpd_irq_event(hdmi->bridge->dev);
}
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
- hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
+ HDMI_IH_MUTE_PHY_STAT0);
return IRQ_HANDLED;
}
@@ -1599,7 +1662,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
{
struct drm_device *drm = data;
struct device_node *np = dev->of_node;
+ struct platform_device_info pdevinfo;
struct device_node *ddc_node;
+ struct dw_hdmi_audio_data audio;
struct dw_hdmi *hdmi;
int ret;
u32 val = 1;
@@ -1608,13 +1673,16 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
if (!hdmi)
return -ENOMEM;
+ hdmi->connector.interlace_allowed = 1;
+
hdmi->plat_data = plat_data;
hdmi->dev = dev;
hdmi->dev_type = plat_data->dev_type;
hdmi->sample_rate = 48000;
- hdmi->ratio = 100;
hdmi->encoder = encoder;
hdmi->disabled = true;
+ hdmi->rxsense = true;
+ hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
mutex_init(&hdmi->mutex);
mutex_init(&hdmi->audio_mutex);
@@ -1705,10 +1773,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
* Configure registers related to HDMI interrupt
* generation before registering IRQ.
*/
- hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
+ hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
/* Clear Hotplug interrupts */
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+ HDMI_IH_PHY_STAT0);
ret = dw_hdmi_fb_registered(hdmi);
if (ret)
@@ -1719,7 +1788,26 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
goto err_iahb;
/* Unmute interrupts */
- hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
+ HDMI_IH_MUTE_PHY_STAT0);
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ pdevinfo.parent = dev;
+ pdevinfo.id = PLATFORM_DEVID_AUTO;
+
+ if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
+ audio.phys = iores->start;
+ audio.base = hdmi->regs;
+ audio.irq = irq;
+ audio.hdmi = hdmi;
+ audio.eld = hdmi->connector.eld;
+
+ pdevinfo.name = "dw-hdmi-ahb-audio";
+ pdevinfo.data = &audio;
+ pdevinfo.size_data = sizeof(audio);
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+ hdmi->audio = platform_device_register_full(&pdevinfo);
+ }
dev_set_drvdata(dev, hdmi);
@@ -1738,6 +1826,9 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
{
struct dw_hdmi *hdmi = dev_get_drvdata(dev);
+ if (hdmi->audio && !IS_ERR(hdmi->audio))
+ platform_device_unregister(hdmi->audio);
+
/* Disable all interrupts */
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index ee7f7ed2ab12..fc9a560429d6 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -545,6 +545,9 @@
#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
enum {
+/* CONFIG1_ID field values */
+ HDMI_CONFIG1_AHB = 0x01,
+
/* IH_FC_INT2 field values */
HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index 1b1bf2384815..0ffa3a6a206a 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -400,7 +400,6 @@ static struct i2c_driver ptn3460_driver = {
.remove = ptn3460_remove,
.driver = {
.name = "nxp,ptn3460",
- .owner = THIS_MODULE,
.of_match_table = ptn3460_match,
},
};
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 1a6607beb29f..be881e9fef8f 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -668,7 +668,6 @@ static struct i2c_driver ps8622_driver = {
.remove = ps8622_remove,
.driver = {
.name = "ps8622",
- .owner = THIS_MODULE,
.of_match_table = ps8622_devices,
},
};
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index 4b2b4aa5033b..a10ea6aec629 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -36,8 +36,6 @@
#include <linux/slab.h>
#include "drm_legacy.h"
-#if __OS_HAS_AGP
-
#include <asm/agp.h>
/**
@@ -502,5 +500,3 @@ drm_agp_bind_pages(struct drm_device *dev,
return mem;
}
EXPORT_SYMBOL(drm_agp_bind_pages);
-
-#endif /* __OS_HAS_AGP */
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f7d5166f89b2..aeee083c7f95 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -438,7 +438,8 @@ EXPORT_SYMBOL(drm_atomic_crtc_set_property);
* consistent behavior you must call this function rather than the
* driver hook directly.
*/
-int drm_atomic_crtc_get_property(struct drm_crtc *crtc,
+static int
+drm_atomic_crtc_get_property(struct drm_crtc *crtc,
const struct drm_crtc_state *state,
struct drm_property *property, uint64_t *val)
{
@@ -663,6 +664,25 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
return 0;
}
+static bool
+plane_switching_crtc(struct drm_atomic_state *state,
+ struct drm_plane *plane,
+ struct drm_plane_state *plane_state)
+{
+ if (!plane->state->crtc || !plane_state->crtc)
+ return false;
+
+ if (plane->state->crtc == plane_state->crtc)
+ return false;
+
+ /* This could be refined, but currently there's no helper or driver code
+ * to implement direct switching of active planes nor userspace to take
+ * advantage of more direct plane switching without the intermediate
+ * full OFF state.
+ */
+ return true;
+}
+
/**
* drm_atomic_plane_check - check plane state
* @plane: plane to check
@@ -734,6 +754,12 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
return -ENOSPC;
}
+ if (plane_switching_crtc(state->state, plane, state)) {
+ DRM_DEBUG_ATOMIC("[PLANE:%d] switching CRTC directly\n",
+ plane->base.id);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -1406,6 +1432,45 @@ static int atomic_set_prop(struct drm_atomic_state *state,
return ret;
}
+/**
+ * drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
+ *
+ * @dev: drm device to check.
+ * @plane_mask: plane mask for planes that were updated.
+ * @ret: return value, can be -EDEADLK for a retry.
+ *
+ * Before doing an update plane->old_fb is set to plane->fb,
+ * but before dropping the locks old_fb needs to be set to NULL
+ * and plane->fb updated. This is a common operation for each
+ * atomic update, so this call is split off as a helper.
+ */
+void drm_atomic_clean_old_fb(struct drm_device *dev,
+ unsigned plane_mask,
+ int ret)
+{
+ struct drm_plane *plane;
+
+ /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
+ * locks (ie. while it is still safe to deref plane->state). We
+ * need to do this here because the driver entry points cannot
+ * distinguish between legacy and atomic ioctls.
+ */
+ drm_for_each_plane_mask(plane, dev, plane_mask) {
+ if (ret == 0) {
+ struct drm_framebuffer *new_fb = plane->state->fb;
+ if (new_fb)
+ drm_framebuffer_reference(new_fb);
+ plane->fb = new_fb;
+ plane->crtc = plane->state->crtc;
+
+ if (plane->old_fb)
+ drm_framebuffer_unreference(plane->old_fb);
+ }
+ plane->old_fb = NULL;
+ }
+}
+EXPORT_SYMBOL(drm_atomic_clean_old_fb);
+
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
@@ -1420,7 +1485,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
struct drm_plane *plane;
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
- unsigned plane_mask = 0;
+ unsigned plane_mask;
int ret = 0;
unsigned int i, j;
@@ -1460,6 +1525,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
retry:
+ plane_mask = 0;
copied_objs = 0;
copied_props = 0;
@@ -1550,24 +1616,7 @@ retry:
}
out:
- /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
- * locks (ie. while it is still safe to deref plane->state). We
- * need to do this here because the driver entry points cannot
- * distinguish between legacy and atomic ioctls.
- */
- drm_for_each_plane_mask(plane, dev, plane_mask) {
- if (ret == 0) {
- struct drm_framebuffer *new_fb = plane->state->fb;
- if (new_fb)
- drm_framebuffer_reference(new_fb);
- plane->fb = new_fb;
- plane->crtc = plane->state->crtc;
-
- if (plane->old_fb)
- drm_framebuffer_unreference(plane->old_fb);
- }
- plane->old_fb = NULL;
- }
+ drm_atomic_clean_old_fb(dev, plane_mask, ret);
if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
/*
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index aecb5d69bc2d..e5aec45bf985 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -42,14 +42,14 @@
* add their own additional internal state.
*
* This library also provides default implementations for the check callback in
- * drm_atomic_helper_check and for the commit callback with
- * drm_atomic_helper_commit. But the individual stages and callbacks are expose
- * to allow drivers to mix and match and e.g. use the plane helpers only
+ * drm_atomic_helper_check() and for the commit callback with
+ * drm_atomic_helper_commit(). But the individual stages and callbacks are
+ * exposed to allow drivers to mix and match and e.g. use the plane helpers only
* together with a driver private modeset implementation.
*
* This library also provides implementations for all the legacy driver
- * interfaces on top of the atomic interface. See drm_atomic_helper_set_config,
- * drm_atomic_helper_disable_plane, drm_atomic_helper_disable_plane and the
+ * interfaces on top of the atomic interface. See drm_atomic_helper_set_config(),
+ * drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the
* various functions to implement set_property callbacks. New drivers must not
* implement these functions themselves but must use the provided helpers.
*/
@@ -210,6 +210,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
return -EINVAL;
}
+ if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
+ DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
+ new_encoder->base.id,
+ new_encoder->name,
+ connector_state->crtc->base.id);
+ return -EINVAL;
+ }
+
if (new_encoder == connector_state->best_encoder) {
DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
connector->base.id,
@@ -993,6 +1001,22 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
* object. This can still fail when e.g. the framebuffer reservation fails. For
* now this doesn't implement asynchronous commits.
*
+ * Note that right now this function does not support async commits, and hence
+ * driver writers must implement their own version for now. Also note that the
+ * default ordering of how the various stages are called is to match the legacy
+ * modeset helper library closest. One peculiarity of that is that it doesn't
+ * mesh well with runtime PM at all.
+ *
+ * For drivers supporting runtime PM the recommended sequence is
+ *
+ * drm_atomic_helper_commit_modeset_disables(dev, state);
+ *
+ * drm_atomic_helper_commit_modeset_enables(dev, state);
+ *
+ * drm_atomic_helper_commit_planes(dev, state, true);
+ *
+ * See the kerneldoc entries for these three functions for more details.
+ *
* RETURNS
* Zero for success or -errno.
*/
@@ -1037,7 +1061,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
drm_atomic_helper_commit_modeset_disables(dev, state);
- drm_atomic_helper_commit_planes(dev, state);
+ drm_atomic_helper_commit_planes(dev, state, false);
drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -1077,7 +1101,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit);
* work item, which allows nice concurrent updates on disjoint sets of crtcs.
*
* 3. The software state is updated synchronously with
- * drm_atomic_helper_swap_state. Doing this under the protection of all modeset
+ * drm_atomic_helper_swap_state(). Doing this under the protection of all modeset
* locks means concurrent callers never see inconsistent state. And doing this
* while it's guaranteed that no relevant async worker runs means that async
* workers do not need grab any locks. Actually they must not grab locks, for
@@ -1111,17 +1135,14 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
const struct drm_plane_helper_funcs *funcs;
struct drm_plane *plane = state->planes[i];
struct drm_plane_state *plane_state = state->plane_states[i];
- struct drm_framebuffer *fb;
if (!plane)
continue;
funcs = plane->helper_private;
- fb = plane_state->fb;
-
- if (fb && funcs->prepare_fb) {
- ret = funcs->prepare_fb(plane, fb, plane_state);
+ if (funcs->prepare_fb) {
+ ret = funcs->prepare_fb(plane, plane_state);
if (ret)
goto fail;
}
@@ -1134,17 +1155,14 @@ fail:
const struct drm_plane_helper_funcs *funcs;
struct drm_plane *plane = state->planes[i];
struct drm_plane_state *plane_state = state->plane_states[i];
- struct drm_framebuffer *fb;
if (!plane)
continue;
funcs = plane->helper_private;
- fb = state->plane_states[i]->fb;
-
- if (fb && funcs->cleanup_fb)
- funcs->cleanup_fb(plane, fb, plane_state);
+ if (funcs->cleanup_fb)
+ funcs->cleanup_fb(plane, plane_state);
}
@@ -1152,10 +1170,16 @@ fail:
}
EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
+bool plane_crtc_active(struct drm_plane_state *state)
+{
+ return state->crtc && state->crtc->state->active;
+}
+
/**
* drm_atomic_helper_commit_planes - commit plane state
* @dev: DRM device
* @old_state: atomic state object with old state structures
+ * @active_only: Only commit on active CRTC if set
*
* This function commits the new plane state using the plane and atomic helper
* functions for planes and crtcs. It assumes that the atomic state has already
@@ -1168,9 +1192,26 @@ EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
* Note that this function does all plane updates across all CRTCs in one step.
* If the hardware can't support this approach look at
* drm_atomic_helper_commit_planes_on_crtc() instead.
+ *
+ * Plane parameters can be updated by applications while the associated CRTC is
+ * disabled. The DRM/KMS core will store the parameters in the plane state,
+ * which will be available to the driver when the CRTC is turned on. As a result
+ * most drivers don't need to be immediately notified of plane updates for a
+ * disabled CRTC.
+ *
+ * Unless otherwise needed, drivers are advised to set the @active_only
+ * parameters to true in order not to receive plane update notifications related
+ * to a disabled CRTC. This avoids the need to manually ignore plane updates in
+ * driver code when the driver and/or hardware can't or just don't need to deal
+ * with updates on disabled CRTCs, for example when supporting runtime PM.
+ *
+ * The drm_atomic_helper_commit() default implementation only sets @active_only
+ * to false to most closely match the behaviour of the legacy helpers. This should
+ * not be copied blindly by drivers.
*/
void drm_atomic_helper_commit_planes(struct drm_device *dev,
- struct drm_atomic_state *old_state)
+ struct drm_atomic_state *old_state,
+ bool active_only)
{
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
@@ -1186,25 +1227,43 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
if (!funcs || !funcs->atomic_begin)
continue;
+ if (active_only && !crtc->state->active)
+ continue;
+
funcs->atomic_begin(crtc, old_crtc_state);
}
for_each_plane_in_state(old_state, plane, old_plane_state, i) {
const struct drm_plane_helper_funcs *funcs;
+ bool disabling;
funcs = plane->helper_private;
if (!funcs)
continue;
+ disabling = drm_atomic_plane_disabling(plane, old_plane_state);
+
+ if (active_only) {
+ /*
+ * Skip planes related to inactive CRTCs. If the plane
+ * is enabled use the state of the current CRTC. If the
+ * plane is being disabled use the state of the old
+ * CRTC to avoid skipping planes being disabled on an
+ * active CRTC.
+ */
+ if (!disabling && !plane_crtc_active(plane->state))
+ continue;
+ if (disabling && !plane_crtc_active(old_plane_state))
+ continue;
+ }
+
/*
* Special-case disabling the plane if drivers support it.
*/
- if (drm_atomic_plane_disabling(plane, old_plane_state) &&
- funcs->atomic_disable)
+ if (disabling && funcs->atomic_disable)
funcs->atomic_disable(plane, old_plane_state);
- else if (plane->state->crtc ||
- drm_atomic_plane_disabling(plane, old_plane_state))
+ else if (plane->state->crtc || disabling)
funcs->atomic_update(plane, old_plane_state);
}
@@ -1216,6 +1275,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
if (!funcs || !funcs->atomic_flush)
continue;
+ if (active_only && !crtc->state->active)
+ continue;
+
funcs->atomic_flush(crtc, old_crtc_state);
}
}
@@ -1300,14 +1362,11 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
for_each_plane_in_state(old_state, plane, plane_state, i) {
const struct drm_plane_helper_funcs *funcs;
- struct drm_framebuffer *old_fb;
funcs = plane->helper_private;
- old_fb = plane_state->fb;
-
- if (old_fb && funcs->cleanup_fb)
- funcs->cleanup_fb(plane, old_fb, plane_state);
+ if (funcs->cleanup_fb)
+ funcs->cleanup_fb(plane, plane_state);
}
}
EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
@@ -1334,7 +1393,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
*
* 4. Actually commit the hardware state.
*
- * 5. Call drm_atomic_helper_cleanup_planes with @state, which since step 3
+ * 5. Call drm_atomic_helper_cleanup_planes() with @state, which since step 3
* contains the old state. Also do any other cleanup required with that state.
*/
void drm_atomic_helper_swap_state(struct drm_device *dev,
@@ -1502,21 +1561,12 @@ retry:
goto fail;
}
- ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+ if (plane_state->crtc && (plane == plane->crtc->cursor))
+ plane_state->state->legacy_cursor_update = true;
+
+ ret = __drm_atomic_helper_disable_plane(plane, plane_state);
if (ret != 0)
goto fail;
- drm_atomic_set_fb_for_plane(plane_state, NULL);
- plane_state->crtc_x = 0;
- plane_state->crtc_y = 0;
- plane_state->crtc_h = 0;
- plane_state->crtc_w = 0;
- plane_state->src_x = 0;
- plane_state->src_y = 0;
- plane_state->src_h = 0;
- plane_state->src_w = 0;
-
- if (plane == plane->crtc->cursor)
- state->legacy_cursor_update = true;
ret = drm_atomic_commit(state);
if (ret != 0)
@@ -1546,6 +1596,29 @@ backoff:
}
EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
+/* just used from fb-helper and atomic-helper: */
+int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
+ struct drm_plane_state *plane_state)
+{
+ int ret;
+
+ ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+ if (ret != 0)
+ return ret;
+
+ drm_atomic_set_fb_for_plane(plane_state, NULL);
+ plane_state->crtc_x = 0;
+ plane_state->crtc_y = 0;
+ plane_state->crtc_h = 0;
+ plane_state->crtc_w = 0;
+ plane_state->src_x = 0;
+ plane_state->src_y = 0;
+ plane_state->src_h = 0;
+ plane_state->src_w = 0;
+
+ return 0;
+}
+
static int update_output_state(struct drm_atomic_state *state,
struct drm_mode_set *set)
{
@@ -1629,8 +1702,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
{
struct drm_atomic_state *state;
struct drm_crtc *crtc = set->crtc;
- struct drm_crtc_state *crtc_state;
- struct drm_plane_state *primary_state;
int ret = 0;
state = drm_atomic_state_alloc(crtc->dev);
@@ -1639,17 +1710,55 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
retry:
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state)) {
- ret = PTR_ERR(crtc_state);
+ ret = __drm_atomic_helper_set_config(set, state);
+ if (ret != 0)
goto fail;
- }
- primary_state = drm_atomic_get_plane_state(state, crtc->primary);
- if (IS_ERR(primary_state)) {
- ret = PTR_ERR(primary_state);
+ ret = drm_atomic_commit(state);
+ if (ret != 0)
goto fail;
- }
+
+ /* Driver takes ownership of state on successful commit. */
+ return 0;
+fail:
+ if (ret == -EDEADLK)
+ goto backoff;
+
+ drm_atomic_state_free(state);
+
+ return ret;
+backoff:
+ drm_atomic_state_clear(state);
+ drm_atomic_legacy_backoff(state);
+
+ /*
+ * Someone might have exchanged the framebuffer while we dropped locks
+ * in the backoff code. We need to fix up the fb refcount tracking the
+ * core does for us.
+ */
+ crtc->primary->old_fb = crtc->primary->fb;
+
+ goto retry;
+}
+EXPORT_SYMBOL(drm_atomic_helper_set_config);
+
+/* just used from fb-helper and atomic-helper: */
+int __drm_atomic_helper_set_config(struct drm_mode_set *set,
+ struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_plane_state *primary_state;
+ struct drm_crtc *crtc = set->crtc;
+ int hdisplay, vdisplay;
+ int ret;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ primary_state = drm_atomic_get_plane_state(state, crtc->primary);
+ if (IS_ERR(primary_state))
+ return PTR_ERR(primary_state);
if (!set->mode) {
WARN_ON(set->fb);
@@ -1657,13 +1766,13 @@ retry:
ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
if (ret != 0)
- goto fail;
+ return ret;
crtc_state->active = false;
ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
if (ret != 0)
- goto fail;
+ return ret;
drm_atomic_set_fb_for_plane(primary_state, NULL);
@@ -1675,55 +1784,38 @@ retry:
ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
if (ret != 0)
- goto fail;
+ return ret;
crtc_state->active = true;
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
if (ret != 0)
- goto fail;
+ return ret;
+
+ drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
+
drm_atomic_set_fb_for_plane(primary_state, set->fb);
primary_state->crtc_x = 0;
primary_state->crtc_y = 0;
- primary_state->crtc_h = set->mode->vdisplay;
- primary_state->crtc_w = set->mode->hdisplay;
+ primary_state->crtc_h = vdisplay;
+ primary_state->crtc_w = hdisplay;
primary_state->src_x = set->x << 16;
primary_state->src_y = set->y << 16;
- primary_state->src_h = set->mode->vdisplay << 16;
- primary_state->src_w = set->mode->hdisplay << 16;
+ if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
+ primary_state->src_h = hdisplay << 16;
+ primary_state->src_w = vdisplay << 16;
+ } else {
+ primary_state->src_h = vdisplay << 16;
+ primary_state->src_w = hdisplay << 16;
+ }
commit:
ret = update_output_state(state, set);
if (ret)
- goto fail;
-
- ret = drm_atomic_commit(state);
- if (ret != 0)
- goto fail;
+ return ret;
- /* Driver takes ownership of state on successful commit. */
return 0;
-fail:
- if (ret == -EDEADLK)
- goto backoff;
-
- drm_atomic_state_free(state);
-
- return ret;
-backoff:
- drm_atomic_state_clear(state);
- drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- crtc->primary->old_fb = crtc->primary->fb;
-
- goto retry;
}
-EXPORT_SYMBOL(drm_atomic_helper_set_config);
/**
* drm_atomic_helper_crtc_set_property - helper for crtc properties
@@ -2333,6 +2425,84 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
/**
+ * drm_atomic_helper_duplicate_state - duplicate an atomic state object
+ * @dev: DRM device
+ * @ctx: lock acquisition context
+ *
+ * Makes a copy of the current atomic state by looping over all objects and
+ * duplicating their respective states.
+ *
+ * Note that this treats atomic state as persistent between save and restore.
+ * Drivers must make sure that this is possible and won't result in confusion
+ * or erroneous behaviour.
+ *
+ * Note that if callers haven't already acquired all modeset locks this might
+ * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
+ *
+ * Returns:
+ * A pointer to the copy of the atomic state object on success or an
+ * ERR_PTR()-encoded error code on failure.
+ */
+struct drm_atomic_state *
+drm_atomic_helper_duplicate_state(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_atomic_state *state;
+ struct drm_connector *conn;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ int err = 0;
+
+ state = drm_atomic_state_alloc(dev);
+ if (!state)
+ return ERR_PTR(-ENOMEM);
+
+ state->acquire_ctx = ctx;
+
+ drm_for_each_crtc(crtc, dev) {
+ struct drm_crtc_state *crtc_state;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state)) {
+ err = PTR_ERR(crtc_state);
+ goto free;
+ }
+ }
+
+ drm_for_each_plane(plane, dev) {
+ struct drm_plane_state *plane_state;
+
+ plane_state = drm_atomic_get_plane_state(state, plane);
+ if (IS_ERR(plane_state)) {
+ err = PTR_ERR(plane_state);
+ goto free;
+ }
+ }
+
+ drm_for_each_connector(conn, dev) {
+ struct drm_connector_state *conn_state;
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ if (IS_ERR(conn_state)) {
+ err = PTR_ERR(conn_state);
+ goto free;
+ }
+ }
+
+ /* clear the acquire context so that it isn't accidentally reused */
+ state->acquire_ctx = NULL;
+
+free:
+ if (err < 0) {
+ drm_atomic_state_free(state);
+ state = ERR_PTR(err);
+ }
+
+ return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
+
+/**
* __drm_atomic_helper_connector_destroy_state - release connector state
* @connector: connector object
* @state: connector state object to release
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 569064a00693..f1a204d253cc 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -582,7 +582,7 @@ static void drm_cleanup_buf_error(struct drm_device * dev,
}
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
/**
* Add AGP buffers for DMA transfers.
*
@@ -756,7 +756,7 @@ int drm_legacy_addbufs_agp(struct drm_device *dev,
return 0;
}
EXPORT_SYMBOL(drm_legacy_addbufs_agp);
-#endif /* __OS_HAS_AGP */
+#endif /* CONFIG_AGP */
int drm_legacy_addbufs_pci(struct drm_device *dev,
struct drm_buf_desc *request)
@@ -1145,7 +1145,7 @@ int drm_legacy_addbufs(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (request->flags & _DRM_AGP_BUFFER)
ret = drm_legacy_addbufs_agp(dev, request);
else
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 33d877c65ced..24c5434abd1c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -306,8 +306,7 @@ static int drm_mode_object_get_reg(struct drm_device *dev,
* reference counted modeset objects like framebuffers.
*
* Returns:
- * New unique (relative to other objects in @dev) integer identifier for the
- * object.
+ * Zero on success, error code on failure.
*/
int drm_mode_object_get(struct drm_device *dev,
struct drm_mode_object *obj, uint32_t obj_type)
@@ -423,7 +422,7 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
out:
mutex_unlock(&dev->mode_config.fb_lock);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(drm_framebuffer_init);
@@ -538,7 +537,12 @@ EXPORT_SYMBOL(drm_framebuffer_reference);
*/
void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
{
- struct drm_device *dev = fb->dev;
+ struct drm_device *dev;
+
+ if (!fb)
+ return;
+
+ dev = fb->dev;
mutex_lock(&dev->mode_config.fb_lock);
/* Mark fb as reaped and drop idr ref. */
@@ -589,12 +593,17 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
*/
void drm_framebuffer_remove(struct drm_framebuffer *fb)
{
- struct drm_device *dev = fb->dev;
+ struct drm_device *dev;
struct drm_crtc *crtc;
struct drm_plane *plane;
struct drm_mode_set set;
int ret;
+ if (!fb)
+ return;
+
+ dev = fb->dev;
+
WARN_ON(!list_empty(&fb->filp_head));
/*
@@ -667,7 +676,6 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
crtc->dev = dev;
crtc->funcs = funcs;
- crtc->invert_dimensions = false;
drm_modeset_lock_init(&crtc->mutex);
ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
@@ -1509,7 +1517,7 @@ EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
*/
int drm_mode_create_tv_properties(struct drm_device *dev,
unsigned int num_modes,
- char *modes[])
+ const char * const modes[])
{
struct drm_property *tv_selector;
struct drm_property *tv_subconnector;
@@ -1525,6 +1533,9 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
"select subconnector",
drm_tv_select_enum_list,
ARRAY_SIZE(drm_tv_select_enum_list));
+ if (!tv_selector)
+ goto nomem;
+
dev->mode_config.tv_select_subconnector_property = tv_selector;
tv_subconnector =
@@ -1532,6 +1543,8 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
"subconnector",
drm_tv_subconnector_enum_list,
ARRAY_SIZE(drm_tv_subconnector_enum_list));
+ if (!tv_subconnector)
+ goto nomem;
dev->mode_config.tv_subconnector_property = tv_subconnector;
/*
@@ -1539,42 +1552,67 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
*/
dev->mode_config.tv_left_margin_property =
drm_property_create_range(dev, 0, "left margin", 0, 100);
+ if (!dev->mode_config.tv_left_margin_property)
+ goto nomem;
dev->mode_config.tv_right_margin_property =
drm_property_create_range(dev, 0, "right margin", 0, 100);
+ if (!dev->mode_config.tv_right_margin_property)
+ goto nomem;
dev->mode_config.tv_top_margin_property =
drm_property_create_range(dev, 0, "top margin", 0, 100);
+ if (!dev->mode_config.tv_top_margin_property)
+ goto nomem;
dev->mode_config.tv_bottom_margin_property =
drm_property_create_range(dev, 0, "bottom margin", 0, 100);
+ if (!dev->mode_config.tv_bottom_margin_property)
+ goto nomem;
dev->mode_config.tv_mode_property =
drm_property_create(dev, DRM_MODE_PROP_ENUM,
"mode", num_modes);
+ if (!dev->mode_config.tv_mode_property)
+ goto nomem;
+
for (i = 0; i < num_modes; i++)
drm_property_add_enum(dev->mode_config.tv_mode_property, i,
i, modes[i]);
dev->mode_config.tv_brightness_property =
drm_property_create_range(dev, 0, "brightness", 0, 100);
+ if (!dev->mode_config.tv_brightness_property)
+ goto nomem;
dev->mode_config.tv_contrast_property =
drm_property_create_range(dev, 0, "contrast", 0, 100);
+ if (!dev->mode_config.tv_contrast_property)
+ goto nomem;
dev->mode_config.tv_flicker_reduction_property =
drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
+ if (!dev->mode_config.tv_flicker_reduction_property)
+ goto nomem;
dev->mode_config.tv_overscan_property =
drm_property_create_range(dev, 0, "overscan", 0, 100);
+ if (!dev->mode_config.tv_overscan_property)
+ goto nomem;
dev->mode_config.tv_saturation_property =
drm_property_create_range(dev, 0, "saturation", 0, 100);
+ if (!dev->mode_config.tv_saturation_property)
+ goto nomem;
dev->mode_config.tv_hue_property =
drm_property_create_range(dev, 0, "hue", 0, 100);
+ if (!dev->mode_config.tv_hue_property)
+ goto nomem;
return 0;
+nomem:
+ return -ENOMEM;
}
EXPORT_SYMBOL(drm_mode_create_tv_properties);
@@ -2276,6 +2314,32 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
return -EINVAL;
}
+static int check_src_coords(uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h,
+ const struct drm_framebuffer *fb)
+{
+ unsigned int fb_width, fb_height;
+
+ fb_width = fb->width << 16;
+ fb_height = fb->height << 16;
+
+ /* Make sure source coordinates are inside the fb. */
+ if (src_w > fb_width ||
+ src_x > fb_width - src_w ||
+ src_h > fb_height ||
+ src_y > fb_height - src_h) {
+ DRM_DEBUG_KMS("Invalid source coordinates "
+ "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
+ src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
+ src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
+ src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
+ src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
/*
* setplane_internal - setplane handler for internal callers
*
@@ -2295,7 +2359,6 @@ static int __setplane_internal(struct drm_plane *plane,
uint32_t src_w, uint32_t src_h)
{
int ret = 0;
- unsigned int fb_width, fb_height;
/* No fb means shut it down */
if (!fb) {
@@ -2332,27 +2395,13 @@ static int __setplane_internal(struct drm_plane *plane,
crtc_y > INT_MAX - (int32_t) crtc_h) {
DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
crtc_w, crtc_h, crtc_x, crtc_y);
- return -ERANGE;
+ ret = -ERANGE;
+ goto out;
}
-
- fb_width = fb->width << 16;
- fb_height = fb->height << 16;
-
- /* Make sure source coordinates are inside the fb. */
- if (src_w > fb_width ||
- src_x > fb_width - src_w ||
- src_h > fb_height ||
- src_y > fb_height - src_h) {
- DRM_DEBUG_KMS("Invalid source coordinates "
- "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
- src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
- src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
- src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
- src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
- ret = -ENOSPC;
+ ret = check_src_coords(src_x, src_y, src_w, src_h, fb);
+ if (ret)
goto out;
- }
plane->old_fb = plane->fb;
ret = plane->funcs->update_plane(plane, crtc, fb,
@@ -2543,20 +2592,13 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
- if (crtc->invert_dimensions)
+ if (crtc->state &&
+ crtc->primary->state->rotation & (BIT(DRM_ROTATE_90) |
+ BIT(DRM_ROTATE_270)))
swap(hdisplay, vdisplay);
- if (hdisplay > fb->width ||
- vdisplay > fb->height ||
- x > fb->width - hdisplay ||
- y > fb->height - vdisplay) {
- DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
- fb->width, fb->height, hdisplay, vdisplay, x, y,
- crtc->invert_dimensions ? " (inverted)" : "");
- return -ENOSPC;
- }
-
- return 0;
+ return check_src_coords(x << 16, y << 16,
+ hdisplay << 16, vdisplay << 16, fb);
}
EXPORT_SYMBOL(drm_crtc_check_viewport);
@@ -3310,14 +3352,11 @@ int drm_mode_rmfb(struct drm_device *dev,
if (!found)
goto fail_lookup;
- /* Mark fb as reaped, we still have a ref from fpriv->fbs. */
- __drm_framebuffer_unregister(dev, fb);
-
list_del_init(&fb->filp_head);
mutex_unlock(&dev->mode_config.fb_lock);
mutex_unlock(&file_priv->fbs_lock);
- drm_framebuffer_remove(fb);
+ drm_framebuffer_unreference(fb);
return 0;
@@ -3484,7 +3523,6 @@ out_err1:
*/
void drm_fb_release(struct drm_file *priv)
{
- struct drm_device *dev = priv->minor->dev;
struct drm_framebuffer *fb, *tfb;
/*
@@ -3498,16 +3536,10 @@ void drm_fb_release(struct drm_file *priv)
* at it any more.
*/
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
-
- mutex_lock(&dev->mode_config.fb_lock);
- /* Mark fb as reaped, we still have a ref from fpriv->fbs. */
- __drm_framebuffer_unregister(dev, fb);
- mutex_unlock(&dev->mode_config.fb_lock);
-
list_del_init(&fb->filp_head);
- /* This will also drop the fpriv->fbs reference. */
- drm_framebuffer_remove(fb);
+ /* This drops the fpriv->fbs reference. */
+ drm_framebuffer_unreference(fb);
}
}
@@ -4105,7 +4137,7 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
struct drm_property_blob *blob;
int ret;
- if (!length)
+ if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
return ERR_PTR(-EINVAL);
blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
@@ -4454,7 +4486,7 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
* not associated with any file_priv. */
mutex_lock(&dev->mode_config.blob_lock);
out_resp->blob_id = blob->base.id;
- list_add_tail(&file_priv->blobs, &blob->head_file);
+ list_add_tail(&blob->head_file, &file_priv->blobs);
mutex_unlock(&dev->mode_config.blob_lock);
return 0;
@@ -5181,7 +5213,14 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
goto out;
}
- ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
+ if (crtc->state) {
+ const struct drm_plane_state *state = crtc->primary->state;
+
+ ret = check_src_coords(state->src_x, state->src_y,
+ state->src_w, state->src_h, fb);
+ } else {
+ ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
+ }
if (ret)
goto out;
@@ -5629,7 +5668,8 @@ unsigned int drm_rotation_simplify(unsigned int rotation,
{
if (rotation & ~supported_rotations) {
rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y);
- rotation = (rotation & ~0xf) | BIT((ffs(rotation & 0xf) + 1) % 4);
+ rotation = (rotation & DRM_REFLECT_MASK) |
+ BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4);
}
return rotation;
@@ -5732,7 +5772,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
*/
WARN_ON(!list_empty(&dev->mode_config.fb_list));
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
- drm_framebuffer_remove(fb);
+ drm_framebuffer_free(&fb->refcount);
}
list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 291734e87fca..9535c5b60387 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -424,6 +424,19 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
I2C_FUNC_10BIT_ADDR;
}
+static void drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg)
+{
+ /*
+ * In case of i2c defer or short i2c ack reply to a write,
+ * we need to switch to WRITE_STATUS_UPDATE to drain the
+ * rest of the message
+ */
+ if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) {
+ msg->request &= DP_AUX_I2C_MOT;
+ msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE;
+ }
+}
+
#define AUX_PRECHARGE_LEN 10 /* 10 to 16 */
#define AUX_SYNC_LEN (16 + 4) /* preamble + AUX_SYNC_END */
#define AUX_STOP_LEN 4
@@ -579,6 +592,8 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
* Both native ACK and I2C ACK replies received. We
* can assume the transfer was successful.
*/
+ if (ret != msg->size)
+ drm_dp_i2c_msg_write_status_update(msg);
return ret;
case DP_AUX_I2C_REPLY_NACK:
@@ -596,6 +611,8 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
if (defer_i2c < 7)
defer_i2c++;
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
+ drm_dp_i2c_msg_write_status_update(msg);
+
continue;
default:
@@ -608,6 +625,14 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
return -EREMOTEIO;
}
+static void drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg *msg,
+ const struct i2c_msg *i2c_msg)
+{
+ msg->request = (i2c_msg->flags & I2C_M_RD) ?
+ DP_AUX_I2C_READ : DP_AUX_I2C_WRITE;
+ msg->request |= DP_AUX_I2C_MOT;
+}
+
/*
* Keep retrying drm_dp_i2c_do_msg until all data has been transferred.
*
@@ -661,10 +686,7 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
for (i = 0; i < num; i++) {
msg.address = msgs[i].addr;
- msg.request = (msgs[i].flags & I2C_M_RD) ?
- DP_AUX_I2C_READ :
- DP_AUX_I2C_WRITE;
- msg.request |= DP_AUX_I2C_MOT;
+ drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
/* Send a bare address packet to start the transaction.
* Zero sized messages specify an address only (bare
* address) transaction.
@@ -672,6 +694,13 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
msg.buffer = NULL;
msg.size = 0;
err = drm_dp_i2c_do_msg(aux, &msg);
+
+ /*
+ * Reset msg.request in case in case it got
+ * changed into a WRITE_STATUS_UPDATE.
+ */
+ drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
+
if (err < 0)
break;
/* We want each transaction to be as large as possible, but
@@ -684,6 +713,13 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
msg.size = min(transfer_size, msgs[i].len - j);
err = drm_dp_i2c_drain_msg(aux, &msg);
+
+ /*
+ * Reset msg.request in case in case it got
+ * changed into a WRITE_STATUS_UPDATE.
+ */
+ drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
+
if (err < 0)
break;
transfer_size = err;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index bf27a07dbce3..809959d56d78 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1194,17 +1194,18 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
list_for_each_entry(port, &mstb->ports, next) {
if (port->port_num == port_num) {
- if (!port->mstb) {
+ mstb = port->mstb;
+ if (!mstb) {
DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
- return NULL;
+ goto out;
}
- mstb = port->mstb;
break;
}
}
}
kref_get(&mstb->kref);
+out:
mutex_unlock(&mgr->lock);
return mstb;
}
@@ -2801,12 +2802,13 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs
if (msgs[num - 1].flags & I2C_M_RD)
reading = true;
- if (!reading) {
+ if (!reading || (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) {
DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
ret = -EIO;
goto out;
}
+ memset(&msg, 0, sizeof(msg));
msg.req_type = DP_REMOTE_I2C_READ;
msg.u.i2c_read.num_transactions = num - 1;
msg.u.i2c_read.port_number = port->port_num;
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 53d09a19f7e1..9362609df38a 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -37,11 +37,9 @@
#include "drm_legacy.h"
#include "drm_internal.h"
-unsigned int drm_debug = 0; /* 1 to enable debug output */
+unsigned int drm_debug = 0; /* bitmask of DRM_UT_x */
EXPORT_SYMBOL(drm_debug);
-bool drm_atomic = 0;
-
MODULE_AUTHOR(CORE_AUTHOR);
MODULE_DESCRIPTION(CORE_DESC);
MODULE_LICENSE("GPL and additional rights");
@@ -55,7 +53,6 @@ module_param_named(debug, drm_debug, int, 0600);
static DEFINE_SPINLOCK(drm_minor_lock);
static struct idr drm_minors_idr;
-struct class *drm_class;
static struct dentry *drm_debugfs_root;
void drm_err(const char *format, ...)
@@ -398,15 +395,51 @@ void drm_minor_release(struct drm_minor *minor)
}
/**
+ * DOC: driver instance overview
+ *
+ * A device instance for a drm driver is represented by struct &drm_device. This
+ * is allocated with drm_dev_alloc(), usually from bus-specific ->probe()
+ * callbacks implemented by the driver. The driver then needs to initialize all
+ * the various subsystems for the drm device like memory management, vblank
+ * handling, modesetting support and intial output configuration plus obviously
+ * initialize all the corresponding hardware bits. An important part of this is
+ * also calling drm_dev_set_unique() to set the userspace-visible unique name of
+ * this device instance. Finally when everything is up and running and ready for
+ * userspace the device instance can be published using drm_dev_register().
+ *
+ * There is also deprecated support for initalizing device instances using
+ * bus-specific helpers and the ->load() callback. But due to
+ * backwards-compatibility needs the device instance have to be published too
+ * early, which requires unpretty global locking to make safe and is therefore
+ * only support for existing drivers not yet converted to the new scheme.
+ *
+ * When cleaning up a device instance everything needs to be done in reverse:
+ * First unpublish the device instance with drm_dev_unregister(). Then clean up
+ * any other resources allocated at device initialization and drop the driver's
+ * reference to &drm_device using drm_dev_unref().
+ *
+ * Note that the lifetime rules for &drm_device instance has still a lot of
+ * historical baggage. Hence use the reference counting provided by
+ * drm_dev_ref() and drm_dev_unref() only carefully.
+ *
+ * Also note that embedding of &drm_device is currently not (yet) supported (but
+ * it would be easy to add). Drivers can store driver-private data in the
+ * dev_priv field of &drm_device.
+ */
+
+/**
* drm_put_dev - Unregister and release a DRM device
* @dev: DRM device
*
* Called at module unload time or when a PCI device is unplugged.
*
- * Use of this function is discouraged. It will eventually go away completely.
- * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
- *
* Cleans up all DRM device, calling drm_lastclose().
+ *
+ * Note: Use of this function is deprecated. It will eventually go away
+ * completely. Please use drm_dev_unregister() and drm_dev_unref() explicitly
+ * instead to make sure that the device isn't userspace accessible any more
+ * while teardown is in progress, ensuring that userspace can't access an
+ * inconsistent state.
*/
void drm_put_dev(struct drm_device *dev)
{
@@ -519,7 +552,9 @@ static void drm_fs_inode_free(struct inode *inode)
*
* Allocate and initialize a new DRM device. No device registration is done.
* Call drm_dev_register() to advertice the device to user space and register it
- * with other core subsystems.
+ * with other core subsystems. This should be done last in the device
+ * initialization sequence to make sure userspace can't access an inconsistent
+ * state.
*
* The initial ref-count of the object is 1. Use drm_dev_ref() and
* drm_dev_unref() to take and drop further ref-counts.
@@ -566,6 +601,8 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
if (ret)
goto err_minors;
+
+ WARN_ON(driver->suspend || driver->resume);
}
if (drm_core_check_feature(dev, DRIVER_RENDER)) {
@@ -672,6 +709,12 @@ EXPORT_SYMBOL(drm_dev_unref);
*
* Never call this twice on any device!
*
+ * NOTE: To ensure backward compatibility with existing drivers method this
+ * function calls the ->load() method after registering the device nodes,
+ * creating race conditions. Usage of the ->load() methods is therefore
+ * deprecated, drivers must perform all initialization before calling
+ * drm_dev_register().
+ *
* RETURNS:
* 0 on success, negative error code on failure.
*/
@@ -719,6 +762,9 @@ EXPORT_SYMBOL(drm_dev_register);
* Unregister the DRM device from the system. This does the reverse of
* drm_dev_register() but does not deallocate the device. The caller must call
* drm_dev_unref() to drop their final reference.
+ *
+ * This should be called first in the device teardown code to make sure
+ * userspace can't access the device instance any more.
*/
void drm_dev_unregister(struct drm_device *dev)
{
@@ -839,10 +885,9 @@ static int __init drm_core_init(void)
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
goto err_p1;
- drm_class = drm_sysfs_create(THIS_MODULE, "drm");
- if (IS_ERR(drm_class)) {
+ ret = drm_sysfs_init();
+ if (ret < 0) {
printk(KERN_ERR "DRM: Error creating drm class.\n");
- ret = PTR_ERR(drm_class);
goto err_p2;
}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 05bb7311ac5d..d5d2c03fd136 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2044,7 +2044,7 @@ mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
static bool valid_inferred_mode(const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- struct drm_display_mode *m;
+ const struct drm_display_mode *m;
bool ok = false;
list_for_each_entry(m, &connector->probed_modes, head) {
@@ -2418,6 +2418,8 @@ add_cvt_modes(struct drm_connector *connector, struct edid *edid)
return closure.modes;
}
+static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode);
+
static void
do_detailed_mode(struct detailed_timing *timing, void *c)
{
@@ -2434,6 +2436,13 @@ do_detailed_mode(struct detailed_timing *timing, void *c)
if (closure->preferred)
newmode->type |= DRM_MODE_TYPE_PREFERRED;
+ /*
+ * Detailed modes are limited to 10kHz pixel clock resolution,
+ * so fix up anything that looks like CEA/HDMI mode, but the clock
+ * is just slightly off.
+ */
+ fixup_detailed_cea_mode_clock(newmode);
+
drm_mode_probed_add(closure->connector, newmode);
closure->modes++;
closure->preferred = 0;
@@ -2529,9 +2538,9 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
* and the 60Hz variant otherwise.
*/
if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
- clock = clock * 1001 / 1000;
+ clock = DIV_ROUND_CLOSEST(clock * 1001, 1000);
else
- clock = DIV_ROUND_UP(clock * 1000, 1001);
+ clock = DIV_ROUND_CLOSEST(clock * 1000, 1001);
return clock;
}
@@ -3103,6 +3112,45 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
return modes;
}
+static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
+{
+ const struct drm_display_mode *cea_mode;
+ int clock1, clock2, clock;
+ u8 mode_idx;
+ const char *type;
+
+ mode_idx = drm_match_cea_mode(mode) - 1;
+ if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
+ type = "CEA";
+ cea_mode = &edid_cea_modes[mode_idx];
+ clock1 = cea_mode->clock;
+ clock2 = cea_mode_alternate_clock(cea_mode);
+ } else {
+ mode_idx = drm_match_hdmi_mode(mode) - 1;
+ if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
+ type = "HDMI";
+ cea_mode = &edid_4k_modes[mode_idx];
+ clock1 = cea_mode->clock;
+ clock2 = hdmi_mode_alternate_clock(cea_mode);
+ } else {
+ return;
+ }
+ }
+
+ /* pick whichever is closest */
+ if (abs(mode->clock - clock1) < abs(mode->clock - clock2))
+ clock = clock1;
+ else
+ clock = clock2;
+
+ if (mode->clock == clock)
+ return;
+
+ DRM_DEBUG("detailed mode matches %s VIC %d, adjusting clock %d -> %d\n",
+ type, mode_idx + 1, mode->clock, clock);
+ mode->clock = clock;
+}
+
static void
parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
{
@@ -3361,7 +3409,7 @@ EXPORT_SYMBOL(drm_edid_to_speaker_allocation);
* the sink doesn't support audio or video.
*/
int drm_av_sync_delay(struct drm_connector *connector,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *mode)
{
int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
int a, v;
@@ -3396,7 +3444,6 @@ EXPORT_SYMBOL(drm_av_sync_delay);
/**
* drm_select_eld - select one ELD from multiple HDMI/DP sinks
* @encoder: the encoder just changed display mode
- * @mode: the adjusted display mode
*
* It's possible for one encoder to be associated with multiple HDMI/DP sinks.
* The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
@@ -3404,8 +3451,7 @@ EXPORT_SYMBOL(drm_av_sync_delay);
* Return: The connector associated with the first HDMI/DP sink that has ELD
* attached to it.
*/
-struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
+struct drm_connector *drm_select_eld(struct drm_encoder *encoder)
{
struct drm_connector *connector;
struct drm_device *dev = encoder->dev;
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index c5605fe4907e..698b8c3b09d9 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -32,7 +32,7 @@ MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob "
"from built-in data or /lib/firmware instead. ");
#define GENERIC_EDIDS 6
-static const char *generic_edid_name[GENERIC_EDIDS] = {
+static const char * const generic_edid_name[GENERIC_EDIDS] = {
"edid/800x600.bin",
"edid/1024x768.bin",
"edid/1280x1024.bin",
@@ -264,20 +264,43 @@ out:
int drm_load_edid_firmware(struct drm_connector *connector)
{
const char *connector_name = connector->name;
- char *edidname = edid_firmware, *last, *colon;
+ char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
int ret;
struct edid *edid;
- if (*edidname == '\0')
+ if (edid_firmware[0] == '\0')
return 0;
- colon = strchr(edidname, ':');
- if (colon != NULL) {
- if (strncmp(connector_name, edidname, colon - edidname))
- return 0;
- edidname = colon + 1;
- if (*edidname == '\0')
+ /*
+ * If there are multiple edid files specified and separated
+ * by commas, search through the list looking for one that
+ * matches the connector.
+ *
+ * If there's one or more that don't't specify a connector, keep
+ * the last one found one as a fallback.
+ */
+ fwstr = kstrdup(edid_firmware, GFP_KERNEL);
+ edidstr = fwstr;
+
+ while ((edidname = strsep(&edidstr, ","))) {
+ colon = strchr(edidname, ':');
+ if (colon != NULL) {
+ if (strncmp(connector_name, edidname, colon - edidname))
+ continue;
+ edidname = colon + 1;
+ break;
+ }
+
+ if (*edidname != '\0') /* corner case: multiple ',' */
+ fallback = edidname;
+ }
+
+ if (!edidname) {
+ if (!fallback) {
+ kfree(fwstr);
return 0;
+ }
+ edidname = fallback;
}
last = edidname + strlen(edidname) - 1;
@@ -285,6 +308,8 @@ int drm_load_edid_firmware(struct drm_connector *connector)
*last = '\0';
edid = edid_load(connector, edidname, connector_name);
+ kfree(fwstr);
+
if (IS_ERR_OR_NULL(edid))
return 0;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index ca08c472311b..69cbab5e5c81 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -38,6 +38,13 @@
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+
+static bool drm_fbdev_emulation = true;
+module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
+MODULE_PARM_DESC(fbdev_emulation,
+ "Enable legacy fbdev emulation [default=true]");
static LIST_HEAD(kernel_fb_helper_list);
@@ -99,6 +106,9 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
struct drm_connector *connector;
int i;
+ if (!drm_fbdev_emulation)
+ return 0;
+
mutex_lock(&dev->mode_config.mutex);
drm_for_each_connector(connector, dev) {
struct drm_fb_helper_connector *fb_helper_connector;
@@ -129,6 +139,9 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
struct drm_fb_helper_connector **temp;
struct drm_fb_helper_connector *fb_helper_connector;
+ if (!drm_fbdev_emulation)
+ return 0;
+
WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
@@ -184,6 +197,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_connector *fb_helper_connector;
int i, j;
+ if (!drm_fbdev_emulation)
+ return 0;
+
WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
for (i = 0; i < fb_helper->connector_count; i++) {
@@ -320,15 +336,83 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
}
EXPORT_SYMBOL(drm_fb_helper_debug_leave);
-static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
+{
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_plane *plane;
+ struct drm_atomic_state *state;
+ int i, ret;
+ unsigned plane_mask;
+
+ state = drm_atomic_state_alloc(dev);
+ if (!state)
+ return -ENOMEM;
+
+ state->acquire_ctx = dev->mode_config.acquire_ctx;
+retry:
+ plane_mask = 0;
+ drm_for_each_plane(plane, dev) {
+ struct drm_plane_state *plane_state;
+
+ plane_state = drm_atomic_get_plane_state(state, plane);
+ if (IS_ERR(plane_state)) {
+ ret = PTR_ERR(plane_state);
+ goto fail;
+ }
+
+ plane_state->rotation = BIT(DRM_ROTATE_0);
+
+ plane->old_fb = plane->fb;
+ plane_mask |= 1 << drm_plane_index(plane);
+
+ /* disable non-primary: */
+ if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+ continue;
+
+ ret = __drm_atomic_helper_disable_plane(plane, plane_state);
+ if (ret != 0)
+ goto fail;
+ }
+
+ for(i = 0; i < fb_helper->crtc_count; i++) {
+ struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+
+ ret = __drm_atomic_helper_set_config(mode_set, state);
+ if (ret != 0)
+ goto fail;
+ }
+
+ ret = drm_atomic_commit(state);
+
+fail:
+ drm_atomic_clean_old_fb(dev, plane_mask, ret);
+
+ if (ret == -EDEADLK)
+ goto backoff;
+
+ if (ret != 0)
+ drm_atomic_state_free(state);
+
+ return ret;
+
+backoff:
+ drm_atomic_state_clear(state);
+ drm_atomic_legacy_backoff(state);
+
+ goto retry;
+}
+
+static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev = fb_helper->dev;
struct drm_plane *plane;
- bool error = false;
int i;
drm_warn_on_modeset_not_all_locked(dev);
+ if (fb_helper->atomic)
+ return restore_fbdev_mode_atomic(fb_helper);
+
drm_for_each_plane(plane, dev) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
@@ -348,18 +432,19 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
if (crtc->funcs->cursor_set2) {
ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
if (ret)
- error = true;
+ return ret;
} else if (crtc->funcs->cursor_set) {
ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
if (ret)
- error = true;
+ return ret;
}
ret = drm_mode_set_config_internal(mode_set);
if (ret)
- error = true;
+ return ret;
}
- return error;
+
+ return 0;
}
/**
@@ -369,12 +454,18 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
* This should be called from driver's drm ->lastclose callback
* when implementing an fbcon on top of kms using this helper. This ensures that
* the user isn't greeted with a black screen when e.g. X dies.
+ *
+ * RETURNS:
+ * Zero if everything went ok, negative error code otherwise.
*/
-bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
+int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev = fb_helper->dev;
- bool ret;
- bool do_delayed = false;
+ bool do_delayed;
+ int ret;
+
+ if (!drm_fbdev_emulation)
+ return -ENODEV;
drm_modeset_lock_all(dev);
ret = restore_fbdev_mode(fb_helper);
@@ -592,6 +683,9 @@ int drm_fb_helper_init(struct drm_device *dev,
struct drm_crtc *crtc;
int i;
+ if (!drm_fbdev_emulation)
+ return 0;
+
if (!max_conn_count)
return -EINVAL;
@@ -625,6 +719,8 @@ int drm_fb_helper_init(struct drm_device *dev,
i++;
}
+ fb_helper->atomic = !!drm_core_check_feature(dev, DRIVER_ATOMIC);
+
return 0;
out_free:
drm_fb_helper_crtc_free(fb_helper);
@@ -714,6 +810,9 @@ EXPORT_SYMBOL(drm_fb_helper_release_fbi);
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{
+ if (!drm_fbdev_emulation)
+ return;
+
if (!list_empty(&fb_helper->kernel_fb_list)) {
list_del(&fb_helper->kernel_fb_list);
if (list_empty(&kernel_fb_helper_list)) {
@@ -1122,6 +1221,66 @@ int drm_fb_helper_set_par(struct fb_info *info)
}
EXPORT_SYMBOL(drm_fb_helper_set_par);
+static int pan_display_atomic(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_atomic_state *state;
+ struct drm_plane *plane;
+ int i, ret;
+ unsigned plane_mask;
+
+ state = drm_atomic_state_alloc(dev);
+ if (!state)
+ return -ENOMEM;
+
+ state->acquire_ctx = dev->mode_config.acquire_ctx;
+retry:
+ plane_mask = 0;
+ for(i = 0; i < fb_helper->crtc_count; i++) {
+ struct drm_mode_set *mode_set;
+
+ mode_set = &fb_helper->crtc_info[i].mode_set;
+
+ mode_set->x = var->xoffset;
+ mode_set->y = var->yoffset;
+
+ ret = __drm_atomic_helper_set_config(mode_set, state);
+ if (ret != 0)
+ goto fail;
+
+ plane = mode_set->crtc->primary;
+ plane_mask |= drm_plane_index(plane);
+ plane->old_fb = plane->fb;
+ }
+
+ ret = drm_atomic_commit(state);
+ if (ret != 0)
+ goto fail;
+
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+
+
+fail:
+ drm_atomic_clean_old_fb(dev, plane_mask, ret);
+
+ if (ret == -EDEADLK)
+ goto backoff;
+
+ if (ret != 0)
+ drm_atomic_state_free(state);
+
+ return ret;
+
+backoff:
+ drm_atomic_state_clear(state);
+ drm_atomic_legacy_backoff(state);
+
+ goto retry;
+}
+
/**
* drm_fb_helper_pan_display - implementation for ->fb_pan_display
* @var: updated screen information
@@ -1145,6 +1304,11 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
return -EBUSY;
}
+ if (fb_helper->atomic) {
+ ret = pan_display_atomic(var, info);
+ goto unlock;
+ }
+
for (i = 0; i < fb_helper->crtc_count; i++) {
modeset = &fb_helper->crtc_info[i].mode_set;
@@ -1159,6 +1323,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
}
}
}
+unlock:
drm_modeset_unlock_all(dev);
return ret;
}
@@ -1934,6 +2099,9 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
struct drm_device *dev = fb_helper->dev;
int count = 0;
+ if (!drm_fbdev_emulation)
+ return 0;
+
mutex_lock(&dev->mode_config.mutex);
count = drm_fb_helper_probe_connector_modes(fb_helper,
dev->mode_config.max_width,
@@ -1977,6 +2145,9 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
struct drm_device *dev = fb_helper->dev;
u32 max_width, max_height;
+ if (!drm_fbdev_emulation)
+ return 0;
+
mutex_lock(&fb_helper->dev->mode_config.mutex);
if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
fb_helper->delayed_hotplug = true;
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 3c2d4abd71c5..c7de454e8e88 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -491,7 +491,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
* __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping)
* so shmem can relocate pages during swapin if required.
*/
- BUG_ON((mapping_gfp_mask(mapping) & __GFP_DMA32) &&
+ BUG_ON(mapping_gfp_constraint(mapping, __GFP_DMA32) &&
(page_to_pfn(p) >= 0x00100000UL));
}
@@ -763,7 +763,8 @@ EXPORT_SYMBOL(drm_gem_object_release);
void
drm_gem_object_free(struct kref *kref)
{
- struct drm_gem_object *obj = (struct drm_gem_object *) kref;
+ struct drm_gem_object *obj =
+ container_of(kref, struct drm_gem_object, refcount);
struct drm_device *dev = obj->dev;
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -810,8 +811,6 @@ EXPORT_SYMBOL(drm_gem_vm_close);
* drm_gem_mmap() prevents unprivileged users from mapping random objects. So
* callers must verify access restrictions before calling this helper.
*
- * NOTE: This function has to be protected with dev->struct_mutex
- *
* Return 0 or success or -EINVAL if the object size is smaller than the VMA
* size, or if no gem_vm_ops are provided.
*/
@@ -820,8 +819,6 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
{
struct drm_device *dev = obj->dev;
- lockdep_assert_held(&dev->struct_mutex);
-
/* Check for valid size. */
if (obj_size < vma->vm_end - vma->vm_start)
return -EINVAL;
@@ -865,30 +862,46 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev;
- struct drm_gem_object *obj;
+ struct drm_gem_object *obj = NULL;
struct drm_vma_offset_node *node;
int ret;
if (drm_device_is_unplugged(dev))
return -ENODEV;
- mutex_lock(&dev->struct_mutex);
+ drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+ node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+ vma->vm_pgoff,
+ vma_pages(vma));
+ if (likely(node)) {
+ obj = container_of(node, struct drm_gem_object, vma_node);
+ /*
+ * When the object is being freed, after it hits 0-refcnt it
+ * proceeds to tear down the object. In the process it will
+ * attempt to remove the VMA offset and so acquire this
+ * mgr->vm_lock. Therefore if we find an object with a 0-refcnt
+ * that matches our range, we know it is in the process of being
+ * destroyed and will be freed as soon as we release the lock -
+ * so we have to check for the 0-refcnted object and treat it as
+ * invalid.
+ */
+ if (!kref_get_unless_zero(&obj->refcount))
+ obj = NULL;
+ }
+ drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
- node = drm_vma_offset_exact_lookup(dev->vma_offset_manager,
- vma->vm_pgoff,
- vma_pages(vma));
- if (!node) {
- mutex_unlock(&dev->struct_mutex);
+ if (!obj)
return -EINVAL;
- } else if (!drm_vma_node_is_allowed(node, filp)) {
- mutex_unlock(&dev->struct_mutex);
+
+ if (!drm_vma_node_is_allowed(node, filp)) {
+ drm_gem_object_unreference_unlocked(obj);
return -EACCES;
}
- obj = container_of(node, struct drm_gem_object, vma_node);
- ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, vma);
+ ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
+ vma);
- mutex_unlock(&dev->struct_mutex);
+ drm_gem_object_unreference_unlocked(obj);
return ret;
}
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 86cc793cdf79..e109b49cd25d 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -481,12 +481,9 @@ int drm_gem_cma_prime_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
struct drm_gem_cma_object *cma_obj;
- struct drm_device *dev = obj->dev;
int ret;
- mutex_lock(&dev->struct_mutex);
ret = drm_gem_mmap_obj(obj, obj->size, vma);
- mutex_unlock(&dev->struct_mutex);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 059af01bd07a..43cbda3306ac 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -73,7 +73,7 @@ int drm_authmagic(struct drm_device *dev, void *data,
/* drm_sysfs.c */
extern struct class *drm_class;
-struct class *drm_sysfs_create(struct module *owner, char *name);
+int drm_sysfs_init(void);
void drm_sysfs_destroy(void);
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
int drm_sysfs_connector_add(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index ddfa6014c2c2..57676f8d7ecf 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -720,7 +720,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
return 0;
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
typedef struct drm_agp_mode32 {
u32 mode; /**< AGP mode */
} drm_agp_mode32_t;
@@ -882,7 +882,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
}
-#endif /* __OS_HAS_AGP */
+#endif /* CONFIG_AGP */
typedef struct drm_scatter_gather32 {
u32 size; /**< In bytes -- will round to page boundary */
@@ -1090,7 +1090,7 @@ static drm_ioctl_compat_t *drm_compat_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
[DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index d93e7378c077..8ce2a0c59116 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -40,7 +40,7 @@
static int drm_version(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-/**
+/*
* Get the bus id.
*
* \param inode device inode.
@@ -75,7 +75,7 @@ drm_unset_busid(struct drm_device *dev,
master->unique_len = 0;
}
-/**
+/*
* Set the bus id.
*
* \param inode device inode.
@@ -149,7 +149,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
return 0;
}
-/**
+/*
* Get a mapping information.
*
* \param inode device inode.
@@ -201,7 +201,7 @@ static int drm_getmap(struct drm_device *dev, void *data,
return 0;
}
-/**
+/*
* Get client information.
*
* \param inode device inode.
@@ -244,7 +244,7 @@ static int drm_getclient(struct drm_device *dev, void *data,
}
}
-/**
+/*
* Get statistics information.
*
* \param inode device inode.
@@ -265,7 +265,7 @@ static int drm_getstats(struct drm_device *dev, void *data,
return 0;
}
-/**
+/*
* Get device/driver capabilities
*/
static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
@@ -318,7 +318,7 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
return 0;
}
-/**
+/*
* Set device/driver capabilities
*/
static int
@@ -352,7 +352,7 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
return 0;
}
-/**
+/*
* Setversion ioctl.
*
* \param inode device inode.
@@ -406,7 +406,18 @@ done:
return retcode;
}
-/** No-op ioctl. */
+/**
+ * drm_noop - DRM no-op ioctl implemntation
+ * @dev: DRM device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: DRM file for the ioctl call
+ *
+ * This no-op implementation for drm ioctls is useful for deprecated
+ * functionality where we can't return a failure code because existing userspace
+ * checks the result of the ioctl, but doesn't care about the action.
+ *
+ * Always returns successfully with 0.
+ */
int drm_noop(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -416,6 +427,28 @@ int drm_noop(struct drm_device *dev, void *data,
EXPORT_SYMBOL(drm_noop);
/**
+ * drm_invalid_op - DRM invalid ioctl implemntation
+ * @dev: DRM device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: DRM file for the ioctl call
+ *
+ * This no-op implementation for drm ioctls is useful for deprecated
+ * functionality where we really don't want to allow userspace to call the ioctl
+ * any more. This is the case for old ums interfaces for drivers that
+ * transitioned to kms gradually and so kept the old legacy tables around. This
+ * only applies to radeon and i915 kms drivers, other drivers shouldn't need to
+ * use this function.
+ *
+ * Always fails with a return value of -EINVAL.
+ */
+int drm_invalid_op(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL(drm_invalid_op);
+
+/*
* Copy and IOCTL return string to user space
*/
static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
@@ -438,7 +471,7 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
return 0;
}
-/**
+/*
* Get version information
*
* \param inode device inode.
@@ -470,7 +503,7 @@ static int drm_version(struct drm_device *dev, void *data,
return err;
}
-/**
+/*
* drm_ioctl_permit - Check ioctl permissions against caller
*
* @flags: ioctl permission flags.
@@ -518,7 +551,7 @@ EXPORT_SYMBOL(drm_ioctl_permit);
.name = #ioctl \
}
-/** Ioctl table */
+/* Ioctl table */
static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version,
DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW),
@@ -571,7 +604,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -635,16 +668,16 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
/**
- * Called whenever a process performs an ioctl on /dev/drm.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
+ * drm_ioctl - ioctl callback implementation for DRM drivers
+ * @filp: file this ioctl is called on
+ * @cmd: ioctl cmd number
+ * @arg: user argument
*
* Looks up the ioctl function in the ::ioctls table, checking for root
* previleges if so required, and dispatches to the respective function.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
*/
long drm_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
@@ -658,13 +691,16 @@ long drm_ioctl(struct file *filp,
char stack_kdata[128];
char *kdata = NULL;
unsigned int usize, asize, drv_size;
+ bool is_driver_ioctl;
dev = file_priv->minor->dev;
if (drm_device_is_unplugged(dev))
return -ENODEV;
- if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END) {
+ is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
+
+ if (is_driver_ioctl) {
/* driver ioctl */
if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
goto err_i1;
@@ -723,7 +759,10 @@ long drm_ioctl(struct file *filp,
memset(kdata, 0, usize);
}
- if (ioctl->flags & DRM_UNLOCKED)
+ /* Enforce sane locking for kms driver ioctls. Core ioctls are
+ * too messy still. */
+ if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
+ (ioctl->flags & DRM_UNLOCKED))
retcode = func(dev, kdata, file_priv);
else {
mutex_lock(&drm_global_mutex);
@@ -754,9 +793,15 @@ EXPORT_SYMBOL(drm_ioctl);
/**
* drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ * @nr: ioctl number
+ * @flags: where to return the ioctl permission flags
+ *
+ * This ioctl is only used by the vmwgfx driver to augment the access checks
+ * done by the drm core and insofar a pretty decent layering violation. This
+ * shouldn't be used by any drivers.
*
- * @nr: Ioctl number.
- * @flags: Where to return the ioctl permission flags
+ * Returns:
+ * True if the @nr corresponds to a DRM core ioctl numer, false otherwise.
*/
bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
{
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 22d207e211e7..2151ea551d3b 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -74,22 +74,22 @@ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
-static void store_vblank(struct drm_device *dev, int crtc,
+static void store_vblank(struct drm_device *dev, unsigned int pipe,
u32 vblank_count_inc,
- struct timeval *t_vblank)
+ struct timeval *t_vblank, u32 last)
{
- struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+ struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
u32 tslot;
assert_spin_locked(&dev->vblank_time_lock);
- if (t_vblank) {
- /* All writers hold the spinlock, but readers are serialized by
- * the latching of vblank->count below.
- */
- tslot = vblank->count + vblank_count_inc;
- vblanktimestamp(dev, crtc, tslot) = *t_vblank;
- }
+ vblank->last = last;
+
+ /* All writers hold the spinlock, but readers are serialized by
+ * the latching of vblank->count below.
+ */
+ tslot = vblank->count + vblank_count_inc;
+ vblanktimestamp(dev, pipe, tslot) = *t_vblank;
/*
* vblank timestamp updates are protected on the write side with
@@ -105,12 +105,60 @@ static void store_vblank(struct drm_device *dev, int crtc,
}
/**
+ * drm_reset_vblank_timestamp - reset the last timestamp to the last vblank
+ * @dev: DRM device
+ * @pipe: index of CRTC for which to reset the timestamp
+ *
+ * Reset the stored timestamp for the current vblank count to correspond
+ * to the last vblank occurred.
+ *
+ * Only to be called from drm_vblank_on().
+ *
+ * Note: caller must hold dev->vbl_lock since this reads & writes
+ * device vblank fields.
+ */
+static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe)
+{
+ u32 cur_vblank;
+ bool rc;
+ struct timeval t_vblank;
+ int count = DRM_TIMESTAMP_MAXRETRIES;
+
+ spin_lock(&dev->vblank_time_lock);
+
+ /*
+ * sample the current counter to avoid random jumps
+ * when drm_vblank_enable() applies the diff
+ */
+ do {
+ cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
+ rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
+ } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0);
+
+ /*
+ * Only reinitialize corresponding vblank timestamp if high-precision query
+ * available and didn't fail. Otherwise reinitialize delayed at next vblank
+ * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid.
+ */
+ if (!rc)
+ t_vblank = (struct timeval) {0, 0};
+
+ /*
+ * +1 to make sure user will never see the same
+ * vblank counter value before and after a modeset
+ */
+ store_vblank(dev, pipe, 1, &t_vblank, cur_vblank);
+
+ spin_unlock(&dev->vblank_time_lock);
+}
+
+/**
* drm_update_vblank_count - update the master vblank counter
* @dev: DRM device
* @pipe: counter to update
*
* Call back into the driver to update the appropriate vblank counter
- * (specified by @crtc). Deal with wraparound, if it occurred, and
+ * (specified by @pipe). Deal with wraparound, if it occurred, and
* update the last read value so we can deal with wraparound on the next
* call if necessary.
*
@@ -120,12 +168,15 @@ static void store_vblank(struct drm_device *dev, int crtc,
* Note: caller must hold dev->vbl_lock since this reads & writes
* device vblank fields.
*/
-static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe)
+static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
+ unsigned long flags)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
u32 cur_vblank, diff;
bool rc;
struct timeval t_vblank;
+ int count = DRM_TIMESTAMP_MAXRETRIES;
+ int framedur_ns = vblank->framedur_ns;
/*
* Interrupts were disabled prior to this call, so deal with counter
@@ -141,33 +192,54 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe)
*/
do {
cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
- rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
- } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe));
+ rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags);
+ } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0);
+
+ if (dev->max_vblank_count != 0) {
+ /* trust the hw counter when it's around */
+ diff = (cur_vblank - vblank->last) & dev->max_vblank_count;
+ } else if (rc && framedur_ns) {
+ const struct timeval *t_old;
+ u64 diff_ns;
- /* Deal with counter wrap */
- diff = cur_vblank - vblank->last;
- if (cur_vblank < vblank->last) {
- diff += dev->max_vblank_count + 1;
+ t_old = &vblanktimestamp(dev, pipe, vblank->count);
+ diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old);
+
+ /*
+ * Figure out how many vblanks we've missed based
+ * on the difference in the timestamps and the
+ * frame/field duration.
+ */
+ diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
- DRM_DEBUG("last_vblank[%u]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
- pipe, vblank->last, cur_vblank, diff);
+ if (diff == 0 && flags & DRM_CALLED_FROM_VBLIRQ)
+ DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored."
+ " diff_ns = %lld, framedur_ns = %d)\n",
+ pipe, (long long) diff_ns, framedur_ns);
+ } else {
+ /* some kind of default for drivers w/o accurate vbl timestamping */
+ diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0;
}
- DRM_DEBUG("updating vblank count on crtc %u, missed %d\n",
- pipe, diff);
+ DRM_DEBUG_VBL("updating vblank count on crtc %u:"
+ " current=%u, diff=%u, hw=%u hw_last=%u\n",
+ pipe, vblank->count, diff, cur_vblank, vblank->last);
- if (diff == 0)
+ if (diff == 0) {
+ WARN_ON_ONCE(cur_vblank != vblank->last);
return;
+ }
/*
* Only reinitialize corresponding vblank timestamp if high-precision query
- * available and didn't fail. Otherwise reinitialize delayed at next vblank
- * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid.
+ * available and didn't fail, or we were called from the vblank interrupt.
+ * Otherwise reinitialize delayed at next vblank interrupt and assign 0
+ * for now, to mark the vblanktimestamp as invalid.
*/
- if (!rc)
+ if (!rc && (flags & DRM_CALLED_FROM_VBLIRQ) == 0)
t_vblank = (struct timeval) {0, 0};
- store_vblank(dev, pipe, diff, &t_vblank);
+ store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
}
/*
@@ -180,11 +252,6 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
unsigned long irqflags;
- u32 vblcount;
- s64 diff_ns;
- bool vblrc;
- struct timeval tvblank;
- int count = DRM_TIMESTAMP_MAXRETRIES;
/* Prevent vblank irq processing while disabling vblank irqs,
* so no updates of timestamps or count can happen after we've
@@ -193,26 +260,6 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
/*
- * If the vblank interrupt was already disabled update the count
- * and timestamp to maintain the appearance that the counter
- * has been ticking all along until this time. This makes the
- * count account for the entire time between drm_vblank_on() and
- * drm_vblank_off().
- *
- * But only do this if precise vblank timestamps are available.
- * Otherwise we might read a totally bogus timestamp since drivers
- * lacking precise timestamp support rely upon sampling the system clock
- * at vblank interrupt time. Which obviously won't work out well if the
- * vblank interrupt is disabled.
- */
- if (!vblank->enabled &&
- drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) {
- drm_update_vblank_count(dev, pipe);
- spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
- return;
- }
-
- /*
* Only disable vblank interrupts if they're enabled. This avoids
* calling the ->disable_vblank() operation in atomic context with the
* hardware potentially runtime suspended.
@@ -222,47 +269,13 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
vblank->enabled = false;
}
- /* No further vblank irq's will be processed after
- * this point. Get current hardware vblank count and
- * vblank timestamp, repeat until they are consistent.
- *
- * FIXME: There is still a race condition here and in
- * drm_update_vblank_count() which can cause off-by-one
- * reinitialization of software vblank counter. If gpu
- * vblank counter doesn't increment exactly at the leading
- * edge of a vblank interval, then we can lose 1 count if
- * we happen to execute between start of vblank and the
- * delayed gpu counter increment.
- */
- do {
- vblank->last = dev->driver->get_vblank_counter(dev, pipe);
- vblrc = drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0);
- } while (vblank->last != dev->driver->get_vblank_counter(dev, pipe) && (--count) && vblrc);
-
- if (!count)
- vblrc = 0;
-
- /* Compute time difference to stored timestamp of last vblank
- * as updated by last invocation of drm_handle_vblank() in vblank irq.
- */
- vblcount = vblank->count;
- diff_ns = timeval_to_ns(&tvblank) -
- timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount));
-
- /* If there is at least 1 msec difference between the last stored
- * timestamp and tvblank, then we are currently executing our
- * disable inside a new vblank interval, the tvblank timestamp
- * corresponds to this new vblank interval and the irq handler
- * for this vblank didn't run yet and won't run due to our disable.
- * Therefore we need to do the job of drm_handle_vblank() and
- * increment the vblank counter by one to account for this vblank.
- *
- * Skip this step if there isn't any high precision timestamp
- * available. In that case we can't account for this and just
- * hope for the best.
+ /*
+ * Always update the count and timestamp to maintain the
+ * appearance that the counter has been ticking all along until
+ * this time. This makes the count account for the entire time
+ * between drm_vblank_on() and drm_vblank_off().
*/
- if (vblrc && (abs64(diff_ns) > 1000000))
- store_vblank(dev, pipe, 1, &tvblank);
+ drm_update_vblank_count(dev, pipe, 0);
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
}
@@ -603,19 +616,27 @@ int drm_control(struct drm_device *dev, void *data,
void drm_calc_timestamping_constants(struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{
- int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = drm_crtc_index(crtc);
+ struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ int linedur_ns = 0, framedur_ns = 0;
int dotclock = mode->crtc_clock;
+ if (!dev->num_crtcs)
+ return;
+
+ if (WARN_ON(pipe >= dev->num_crtcs))
+ return;
+
/* Valid dotclock? */
if (dotclock > 0) {
int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
/*
* Convert scanline length in pixels and video
- * dot clock to line duration, frame duration
- * and pixel duration in nanoseconds:
+ * dot clock to line duration and frame duration
+ * in nanoseconds:
*/
- pixeldur_ns = 1000000 / dotclock;
linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
@@ -628,16 +649,14 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n",
crtc->base.id);
- crtc->pixeldur_ns = pixeldur_ns;
- crtc->linedur_ns = linedur_ns;
- crtc->framedur_ns = framedur_ns;
+ vblank->linedur_ns = linedur_ns;
+ vblank->framedur_ns = framedur_ns;
DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
crtc->base.id, mode->crtc_htotal,
mode->crtc_vtotal, mode->crtc_vdisplay);
- DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
- crtc->base.id, dotclock, framedur_ns,
- linedur_ns, pixeldur_ns);
+ DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d\n",
+ crtc->base.id, dotclock, framedur_ns, linedur_ns);
}
EXPORT_SYMBOL(drm_calc_timestamping_constants);
@@ -651,7 +670,6 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
* @flags: Flags to pass to driver:
* 0 = Default,
* DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler
- * @refcrtc: CRTC which defines scanout timing
* @mode: mode which defines the scanout timings
*
* Implements calculation of exact vblank timestamps from given drm_display_mode
@@ -692,15 +710,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
int *max_error,
struct timeval *vblank_time,
unsigned flags,
- const struct drm_crtc *refcrtc,
const struct drm_display_mode *mode)
{
struct timeval tv_etime;
ktime_t stime, etime;
- int vbl_status;
+ unsigned int vbl_status;
+ int ret = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
int vpos, hpos, i;
- int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
- bool invbl;
+ int delta_ns, duration_ns;
if (pipe >= dev->num_crtcs) {
DRM_ERROR("Invalid crtc %u\n", pipe);
@@ -713,15 +730,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
return -EIO;
}
- /* Durations of frames, lines, pixels in nanoseconds. */
- framedur_ns = refcrtc->framedur_ns;
- linedur_ns = refcrtc->linedur_ns;
- pixeldur_ns = refcrtc->pixeldur_ns;
-
/* If mode timing undefined, just return as no-op:
* Happens during initial modesetting of a crtc.
*/
- if (framedur_ns == 0) {
+ if (mode->crtc_clock == 0) {
DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
return -EAGAIN;
}
@@ -738,12 +750,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
* Get vertical and horizontal scanout position vpos, hpos,
* and bounding timestamps stime, etime, pre/post query.
*/
- vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos,
- &hpos, &stime, &etime);
+ vbl_status = dev->driver->get_scanout_position(dev, pipe, flags,
+ &vpos, &hpos,
+ &stime, &etime,
+ mode);
/* Return as no-op if scanout query unsupported or failed. */
if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
- DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n",
+ DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n",
pipe, vbl_status);
return -EIO;
}
@@ -770,13 +784,15 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
* within vblank area, counting down the number of lines until
* start of scanout.
*/
- invbl = vbl_status & DRM_SCANOUTPOS_IN_VBLANK;
+ if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK)
+ ret |= DRM_VBLANKTIME_IN_VBLANK;
/* Convert scanout position into elapsed time at raw_time query
* since start of scanout at first display scanline. delta_ns
* can be negative if start of scanout hasn't happened yet.
*/
- delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
+ delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
+ mode->crtc_clock);
if (!drm_timestamp_monotonic)
etime = ktime_mono_to_real(etime);
@@ -792,17 +808,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
etime = ktime_sub_ns(etime, delta_ns);
*vblank_time = ktime_to_timeval(etime);
- DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
- pipe, (int)vbl_status, hpos, vpos,
- (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
- (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
- duration_ns/1000, i);
-
- vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
- if (invbl)
- vbl_status |= DRM_VBLANKTIME_IN_VBLANK;
+ DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
+ pipe, vbl_status, hpos, vpos,
+ (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
+ (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
+ duration_ns/1000, i);
- return vbl_status;
+ return ret;
}
EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
@@ -873,7 +885,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
* Returns:
* The software vblank counter.
*/
-u32 drm_vblank_count(struct drm_device *dev, int pipe)
+u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
@@ -914,11 +926,14 @@ EXPORT_SYMBOL(drm_crtc_vblank_count);
* vblank events since the system was booted, including lost events due to
* modesetting activity. Returns corresponding system timestamp of the time
* of the vblank interval that corresponds to the current vblank counter value.
+ *
+ * This is the legacy version of drm_crtc_vblank_count_and_time().
*/
u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
struct timeval *vblanktime)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ int count = DRM_TIMESTAMP_MAXRETRIES;
u32 cur_vblank;
if (WARN_ON(pipe >= dev->num_crtcs))
@@ -934,12 +949,33 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
smp_rmb();
*vblanktime = vblanktimestamp(dev, pipe, cur_vblank);
smp_rmb();
- } while (cur_vblank != vblank->count);
+ } while (cur_vblank != vblank->count && --count > 0);
return cur_vblank;
}
EXPORT_SYMBOL(drm_vblank_count_and_time);
+/**
+ * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value
+ * and the system timestamp corresponding to that vblank counter value
+ * @crtc: which counter to retrieve
+ * @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
+ *
+ * Fetches the "cooked" vblank count value that represents the number of
+ * vblank events since the system was booted, including lost events due to
+ * modesetting activity. Returns corresponding system timestamp of the time
+ * of the vblank interval that corresponds to the current vblank counter value.
+ *
+ * This is the native KMS version of drm_vblank_count_and_time().
+ */
+u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
+ struct timeval *vblanktime)
+{
+ return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc),
+ vblanktime);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
+
static void send_vblank_event(struct drm_device *dev,
struct drm_pending_vblank_event *e,
unsigned long seq, struct timeval *now)
@@ -1033,7 +1069,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
atomic_dec(&vblank->refcount);
else {
vblank->enabled = true;
- drm_update_vblank_count(dev, pipe);
+ drm_update_vblank_count(dev, pipe, 0);
}
}
@@ -1154,8 +1190,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_put);
* @dev: DRM device
* @pipe: CRTC index
*
- * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
- * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
+ * This waits for one vblank to pass on @pipe, using the irq driver interfaces.
+ * It is a failure to call this when the vblank irq for @pipe is disabled, e.g.
* due to lack of driver support or because the crtc is off.
*/
void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
@@ -1244,8 +1280,8 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
if (e->pipe != pipe)
continue;
- DRM_DEBUG("Sending premature vblank event on disable: \
- wanted %d, current %d\n",
+ DRM_DEBUG("Sending premature vblank event on disable: "
+ "wanted %d, current %d\n",
e->event.sequence, seq);
list_del(&e->base.link);
drm_vblank_put(dev, pipe);
@@ -1276,7 +1312,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off);
/**
* drm_crtc_vblank_reset - reset vblank state to off on a CRTC
- * @drm_crtc: CRTC in question
+ * @crtc: CRTC in question
*
* Drivers can use this function to reset the vblank state to off at load time.
* Drivers should use this together with the drm_crtc_vblank_off() and
@@ -1284,12 +1320,12 @@ EXPORT_SYMBOL(drm_crtc_vblank_off);
* drm_crtc_vblank_off() is that this function doesn't save the vblank counter
* and hence doesn't need to call any driver hooks.
*/
-void drm_crtc_vblank_reset(struct drm_crtc *drm_crtc)
+void drm_crtc_vblank_reset(struct drm_crtc *crtc)
{
- struct drm_device *dev = drm_crtc->dev;
+ struct drm_device *dev = crtc->dev;
unsigned long irqflags;
- int crtc = drm_crtc_index(drm_crtc);
- struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+ unsigned int pipe = drm_crtc_index(crtc);
+ struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
spin_lock_irqsave(&dev->vbl_lock, irqflags);
/*
@@ -1333,16 +1369,8 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
vblank->inmodeset = 0;
}
- /*
- * sample the current counter to avoid random jumps
- * when drm_vblank_enable() applies the diff
- *
- * -1 to make sure user will never see the same
- * vblank counter value before and after a modeset
- */
- vblank->last =
- (dev->driver->get_vblank_counter(dev, pipe) - 1) &
- dev->max_vblank_count;
+ drm_reset_vblank_timestamp(dev, pipe);
+
/*
* re-enable interrupts if there are users left, or the
* user wishes vblank interrupts to be enabled all the time.
@@ -1725,9 +1753,6 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
- u32 vblcount;
- s64 diff_ns;
- struct timeval tvblank;
unsigned long irqflags;
if (WARN_ON_ONCE(!dev->num_crtcs))
@@ -1751,32 +1776,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
return false;
}
- /* Fetch corresponding timestamp for this vblank interval from
- * driver and store it in proper slot of timestamp ringbuffer.
- */
-
- /* Get current timestamp and count. */
- vblcount = vblank->count;
- drm_get_last_vbltimestamp(dev, pipe, &tvblank, DRM_CALLED_FROM_VBLIRQ);
-
- /* Compute time difference to timestamp of last vblank */
- diff_ns = timeval_to_ns(&tvblank) -
- timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount));
-
- /* Update vblank timestamp and count if at least
- * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds
- * difference between last stored timestamp and current
- * timestamp. A smaller difference means basically
- * identical timestamps. Happens if this vblank has
- * been already processed and this is a redundant call,
- * e.g., due to spurious vblank interrupts. We need to
- * ignore those for accounting.
- */
- if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS)
- store_vblank(dev, pipe, 1, &tvblank);
- else
- DRM_DEBUG("crtc %u: Redundant vblirq ignored. diff_ns = %d\n",
- pipe, (int) diff_ns);
+ drm_update_vblank_count(dev, pipe, DRM_CALLED_FROM_VBLIRQ);
spin_unlock(&dev->vblank_time_lock);
@@ -1806,3 +1806,20 @@ bool drm_crtc_handle_vblank(struct drm_crtc *crtc)
return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc));
}
EXPORT_SYMBOL(drm_crtc_handle_vblank);
+
+/**
+ * drm_vblank_no_hw_counter - "No hw counter" implementation of .get_vblank_counter()
+ * @dev: DRM device
+ * @pipe: CRTC for which to read the counter
+ *
+ * Drivers can plug this into the .get_vblank_counter() function if
+ * there is no useable hardware frame counter available.
+ *
+ * Returns:
+ * 0
+ */
+u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
+{
+ return 0;
+}
+EXPORT_SYMBOL(drm_vblank_no_hw_counter);
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index 4924d381b664..daa2ff12101b 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -38,8 +38,6 @@
#include "drm_legacy.h"
#include "drm_internal.h"
-static int drm_notifier(void *priv);
-
static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
/**
@@ -118,14 +116,8 @@ int drm_legacy_lock(struct drm_device *dev, void *data,
* really probably not the correct answer but lets us debug xkb
* xserver for now */
if (!file_priv->is_master) {
- sigemptyset(&dev->sigmask);
- sigaddset(&dev->sigmask, SIGSTOP);
- sigaddset(&dev->sigmask, SIGTSTP);
- sigaddset(&dev->sigmask, SIGTTIN);
- sigaddset(&dev->sigmask, SIGTTOU);
dev->sigdata.context = lock->context;
dev->sigdata.lock = master->lock.hw_lock;
- block_all_signals(drm_notifier, dev, &dev->sigmask);
}
if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
@@ -169,7 +161,6 @@ int drm_legacy_unlock(struct drm_device *dev, void *data, struct drm_file *file_
/* FIXME: Should really bail out here. */
}
- unblock_all_signals();
return 0;
}
@@ -288,38 +279,6 @@ int drm_legacy_lock_free(struct drm_lock_data *lock_data, unsigned int context)
}
/**
- * If we get here, it means that the process has called DRM_IOCTL_LOCK
- * without calling DRM_IOCTL_UNLOCK.
- *
- * If the lock is not held, then let the signal proceed as usual. If the lock
- * is held, then set the contended flag and keep the signal blocked.
- *
- * \param priv pointer to a drm_device structure.
- * \return one if the signal should be delivered normally, or zero if the
- * signal should be blocked.
- */
-static int drm_notifier(void *priv)
-{
- struct drm_device *dev = priv;
- struct drm_hw_lock *lock = dev->sigdata.lock;
- unsigned int old, new, prev;
-
- /* Allow signal delivery if lock isn't held */
- if (!lock || !_DRM_LOCK_IS_HELD(lock->lock)
- || _DRM_LOCKING_CONTEXT(lock->lock) != dev->sigdata.context)
- return 1;
-
- /* Otherwise, set flag to force call to
- drmUnlock */
- do {
- old = lock->lock;
- new = old | _DRM_LOCK_CONT;
- prev = cmpxchg(&lock->lock, old, new);
- } while (prev != old);
- return 0;
-}
-
-/**
* This function returns immediately and takes the hw lock
* with the kernel context if it is free, otherwise it gets the highest priority when and if
* it is eventually released.
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index a521ef6ff807..87a8cb73366f 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -38,7 +38,7 @@
#include <drm/drmP.h>
#include "drm_legacy.h"
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
#ifdef HAVE_PAGE_AGP
# include <asm/agp.h>
@@ -111,14 +111,14 @@ int drm_unbind_agp(struct agp_memory * handle)
return agp_unbind_memory(handle);
}
-#else /* __OS_HAS_AGP */
+#else /* CONFIG_AGP */
static inline void *agp_remap(unsigned long offset, unsigned long size,
struct drm_device * dev)
{
return NULL;
}
-#endif /* agp */
+#endif /* CONFIG_AGP */
void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev)
{
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 3427b115e2bb..04de6fd88f8c 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -267,12 +267,12 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
if (adj_end > end)
adj_end = end;
- if (flags & DRM_MM_CREATE_TOP)
- adj_start = adj_end - size;
-
if (mm->color_adjust)
mm->color_adjust(hole_node, color, &adj_start, &adj_end);
+ if (flags & DRM_MM_CREATE_TOP)
+ adj_start = adj_end - size;
+
if (alignment) {
u64 tmp = adj_start;
unsigned rem;
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index fba321ca4344..6675b1428410 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -307,6 +307,8 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
WARN_ON(ctx->contended);
if (ctx->trylock_only) {
+ lockdep_assert_held(&ctx->ww_ctx);
+
if (!ww_mutex_trylock(&lock->mutex))
return -EBUSY;
else
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index be3884073ea4..493c05c9ce4f 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -1,3 +1,4 @@
+#include <linux/component.h>
#include <linux/export.h>
#include <linux/list.h>
#include <linux/of_graph.h>
@@ -61,3 +62,90 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
return possible_crtcs;
}
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
+
+/**
+ * drm_of_component_probe - Generic probe function for a component based master
+ * @dev: master device containing the OF node
+ * @compare_of: compare function used for matching components
+ * @master_ops: component master ops to be used
+ *
+ * Parse the platform device OF node and bind all the components associated
+ * with the master. Interface ports are added before the encoders in order to
+ * satisfy their .bind requirements
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+int drm_of_component_probe(struct device *dev,
+ int (*compare_of)(struct device *, void *),
+ const struct component_master_ops *m_ops)
+{
+ struct device_node *ep, *port, *remote;
+ struct component_match *match = NULL;
+ int i;
+
+ if (!dev->of_node)
+ return -EINVAL;
+
+ /*
+ * Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
+ * called from encoder's .bind callbacks works as expected
+ */
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(dev->of_node, "ports", i);
+ if (!port)
+ break;
+
+ if (!of_device_is_available(port->parent)) {
+ of_node_put(port);
+ continue;
+ }
+
+ component_match_add(dev, &match, compare_of, port);
+ of_node_put(port);
+ }
+
+ if (i == 0) {
+ dev_err(dev, "missing 'ports' property\n");
+ return -ENODEV;
+ }
+
+ if (!match) {
+ dev_err(dev, "no available port\n");
+ return -ENODEV;
+ }
+
+ /*
+ * For bound crtcs, bind the encoders attached to their remote endpoint
+ */
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(dev->of_node, "ports", i);
+ if (!port)
+ break;
+
+ if (!of_device_is_available(port->parent)) {
+ of_node_put(port);
+ continue;
+ }
+
+ for_each_child_of_node(port, ep) {
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!remote || !of_device_is_available(remote)) {
+ of_node_put(remote);
+ continue;
+ } else if (!of_device_is_available(remote->parent)) {
+ dev_warn(dev, "parent device of %s is not available\n",
+ remote->full_name);
+ of_node_put(remote);
+ continue;
+ }
+
+ component_match_add(dev, &match, compare_of, remote);
+ of_node_put(remote);
+ }
+ of_node_put(port);
+ }
+
+ return component_master_add_with_match(dev, m_ops, match);
+}
+EXPORT_SYMBOL(drm_of_component_probe);
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index 1b1bd42b0368..fcd2a86acd2c 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -266,6 +266,9 @@ void drm_pci_agp_destroy(struct drm_device *dev)
* then register the character device and inter module information.
* Try and register, if we fail to register, backout previous work.
*
+ * NOTE: This function is deprecated, please use drm_dev_alloc() and
+ * drm_dev_register() instead and remove your ->load() callback.
+ *
* Return: 0 on success or a negative error code on failure.
*/
int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
@@ -326,6 +329,10 @@ EXPORT_SYMBOL(drm_get_pci_dev);
* Initializes a drm_device structures, registering the stubs and initializing
* the AGP device.
*
+ * NOTE: This function is deprecated. Modern modesetting drm drivers should use
+ * pci_register_driver() directly, this function only provides shadow-binding
+ * support for old legacy drivers on top of that core pci function.
+ *
* Return: 0 on success or a negative error code on failure.
*/
int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
@@ -435,6 +442,10 @@ EXPORT_SYMBOL(drm_pci_init);
*
* Unregisters one or more devices matched by a PCI driver from the DRM
* subsystem.
+ *
+ * NOTE: This function is deprecated. Modern modesetting drm drivers should use
+ * pci_unregister_driver() directly, this function only provides shadow-binding
+ * support for old legacy drivers on top of that core pci function.
*/
void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
{
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 5e5a07af02c8..d384ebcf0aaf 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -426,7 +426,7 @@ int drm_plane_helper_commit(struct drm_plane *plane,
if (plane_funcs->prepare_fb && plane_state->fb &&
plane_state->fb != old_fb) {
- ret = plane_funcs->prepare_fb(plane, plane_state->fb,
+ ret = plane_funcs->prepare_fb(plane,
plane_state);
if (ret)
goto out;
@@ -479,8 +479,8 @@ int drm_plane_helper_commit(struct drm_plane *plane,
ret = 0;
}
- if (plane_funcs->cleanup_fb && old_fb)
- plane_funcs->cleanup_fb(plane, old_fb, plane_state);
+ if (plane_funcs->cleanup_fb)
+ plane_funcs->cleanup_fb(plane, plane_state);
out:
if (plane_state) {
if (plane->funcs->atomic_destroy_state)
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 5314c9d5fef4..644169e1a029 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -95,6 +95,9 @@ EXPORT_SYMBOL(drm_platform_set_busid);
* subsystem, initializing a drm_device structure and calling the driver's
* .load() function.
*
+ * NOTE: This function is deprecated, please use drm_dev_alloc() and
+ * drm_dev_register() instead and remove your ->load() callback.
+ *
* Return: 0 on success or a negative error code on failure.
*/
int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device)
diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c
index 631f5afd451c..531ac4cc9756 100644
--- a/drivers/gpu/drm/drm_rect.c
+++ b/drivers/gpu/drm/drm_rect.c
@@ -330,7 +330,7 @@ void drm_rect_rotate(struct drm_rect *r,
}
}
- switch (rotation & 0xf) {
+ switch (rotation & DRM_ROTATE_MASK) {
case BIT(DRM_ROTATE_0):
break;
case BIT(DRM_ROTATE_90):
@@ -390,7 +390,7 @@ void drm_rect_rotate_inv(struct drm_rect *r,
{
struct drm_rect tmp;
- switch (rotation & 0xf) {
+ switch (rotation & DRM_ROTATE_MASK) {
case BIT(DRM_ROTATE_0):
break;
case BIT(DRM_ROTATE_90):
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 0f6cd33b531f..615b7e667320 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -30,6 +30,8 @@ static struct device_type drm_sysfs_device_minor = {
.name = "drm_minor"
};
+struct class *drm_class;
+
/**
* __drm_class_suspend - internal DRM class suspend routine
* @dev: Linux device to suspend
@@ -112,41 +114,34 @@ static CLASS_ATTR_STRING(version, S_IRUGO,
CORE_DATE);
/**
- * drm_sysfs_create - create a struct drm_sysfs_class structure
- * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
- * @name: pointer to a string for the name of this class.
+ * drm_sysfs_init - initialize sysfs helpers
+ *
+ * This is used to create the DRM class, which is the implicit parent of any
+ * other top-level DRM sysfs objects.
*
- * This is used to create DRM class pointer that can then be used
- * in calls to drm_sysfs_device_add().
+ * You must call drm_sysfs_destroy() to release the allocated resources.
*
- * Note, the pointer created here is to be destroyed when finished by making a
- * call to drm_sysfs_destroy().
+ * Return: 0 on success, negative error code on failure.
*/
-struct class *drm_sysfs_create(struct module *owner, char *name)
+int drm_sysfs_init(void)
{
- struct class *class;
int err;
- class = class_create(owner, name);
- if (IS_ERR(class)) {
- err = PTR_ERR(class);
- goto err_out;
- }
-
- class->pm = &drm_class_dev_pm_ops;
-
- err = class_create_file(class, &class_attr_version.attr);
- if (err)
- goto err_out_class;
+ drm_class = class_create(THIS_MODULE, "drm");
+ if (IS_ERR(drm_class))
+ return PTR_ERR(drm_class);
- class->devnode = drm_devnode;
+ drm_class->pm = &drm_class_dev_pm_ops;
- return class;
+ err = class_create_file(drm_class, &class_attr_version.attr);
+ if (err) {
+ class_destroy(drm_class);
+ drm_class = NULL;
+ return err;
+ }
-err_out_class:
- class_destroy(class);
-err_out:
- return ERR_PTR(err);
+ drm_class->devnode = drm_devnode;
+ return 0;
}
/**
@@ -156,7 +151,7 @@ err_out:
*/
void drm_sysfs_destroy(void)
{
- if ((drm_class == NULL) || (IS_ERR(drm_class)))
+ if (IS_ERR_OR_NULL(drm_class))
return;
class_remove_file(drm_class, &class_attr_version.attr);
class_destroy(drm_class);
@@ -235,18 +230,12 @@ static ssize_t dpms_show(struct device *device,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
- struct drm_device *dev = connector->dev;
- uint64_t dpms_status;
- int ret;
+ int dpms;
- ret = drm_object_property_get_value(&connector->base,
- dev->mode_config.dpms_property,
- &dpms_status);
- if (ret)
- return 0;
+ dpms = READ_ONCE(connector->dpms);
return snprintf(buf, PAGE_SIZE, "%s\n",
- drm_get_dpms_name((int)dpms_status));
+ drm_get_dpms_name(dpms));
}
static ssize_t enabled_show(struct device *device,
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index aab49ee4ed40..f90bd5fe35ba 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -95,7 +95,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
* Find the right map and if it's AGP memory find the real physical page to
* map, get the page, increment the use count and return it.
*/
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct drm_file *priv = vma->vm_file->private_data;
@@ -168,12 +168,12 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
vm_fault_error:
return VM_FAULT_SIGBUS; /* Disallow mremap */
}
-#else /* __OS_HAS_AGP */
+#else
static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
}
-#endif /* __OS_HAS_AGP */
+#endif
/**
* \c nopage method for shared virtual memory.
@@ -556,7 +556,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
* --BenH.
*/
if (!vma->vm_pgoff
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
&& (!dev->agp
|| dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
#endif
diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c
index 68c1f32fb086..2f2ecde8285b 100644
--- a/drivers/gpu/drm/drm_vma_manager.c
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -112,7 +112,7 @@ void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager *mgr)
EXPORT_SYMBOL(drm_vma_offset_manager_destroy);
/**
- * drm_vma_offset_lookup() - Find node in offset space
+ * drm_vma_offset_lookup_locked() - Find node in offset space
* @mgr: Manager object
* @start: Start address for object (page-based)
* @pages: Size of object (page-based)
@@ -122,37 +122,21 @@ EXPORT_SYMBOL(drm_vma_offset_manager_destroy);
* region and the given node will be returned, as long as the node spans the
* whole requested area (given the size in number of pages as @pages).
*
- * RETURNS:
- * Returns NULL if no suitable node can be found. Otherwise, the best match
- * is returned. It's the caller's responsibility to make sure the node doesn't
- * get destroyed before the caller can access it.
- */
-struct drm_vma_offset_node *drm_vma_offset_lookup(struct drm_vma_offset_manager *mgr,
- unsigned long start,
- unsigned long pages)
-{
- struct drm_vma_offset_node *node;
-
- read_lock(&mgr->vm_lock);
- node = drm_vma_offset_lookup_locked(mgr, start, pages);
- read_unlock(&mgr->vm_lock);
-
- return node;
-}
-EXPORT_SYMBOL(drm_vma_offset_lookup);
-
-/**
- * drm_vma_offset_lookup_locked() - Find node in offset space
- * @mgr: Manager object
- * @start: Start address for object (page-based)
- * @pages: Size of object (page-based)
+ * Note that before lookup the vma offset manager lookup lock must be acquired
+ * with drm_vma_offset_lock_lookup(). See there for an example. This can then be
+ * used to implement weakly referenced lookups using kref_get_unless_zero().
*
- * Same as drm_vma_offset_lookup() but requires the caller to lock offset lookup
- * manually. See drm_vma_offset_lock_lookup() for an example.
+ * Example:
+ * drm_vma_offset_lock_lookup(mgr);
+ * node = drm_vma_offset_lookup_locked(mgr);
+ * if (node)
+ * kref_get_unless_zero(container_of(node, sth, entr));
+ * drm_vma_offset_unlock_lookup(mgr);
*
* RETURNS:
* Returns NULL if no suitable node can be found. Otherwise, the best match
- * is returned.
+ * is returned. It's the caller's responsibility to make sure the node doesn't
+ * get destroyed before the caller can access it.
*/
struct drm_vma_offset_node *drm_vma_offset_lookup_locked(struct drm_vma_offset_manager *mgr,
unsigned long start,
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index bd1a4156f647..96e86cf4455b 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -11,43 +11,59 @@ config DRM_EXYNOS
Choose this option if you have a Samsung SoC EXYNOS chipset.
If M is selected the module will be called exynosdrm.
+if DRM_EXYNOS
+
config DRM_EXYNOS_IOMMU
bool
- depends on DRM_EXYNOS && EXYNOS_IOMMU && ARM_DMA_USE_IOMMU
+ depends on EXYNOS_IOMMU && ARM_DMA_USE_IOMMU
default y
+comment "CRTCs"
+
config DRM_EXYNOS_FIMD
- bool "Exynos DRM FIMD"
- depends on DRM_EXYNOS && !FB_S3C
+ bool "FIMD"
+ depends on !FB_S3C
select FB_MODE_HELPERS
select MFD_SYSCON
help
Choose this option if you want to use Exynos FIMD for DRM.
config DRM_EXYNOS5433_DECON
- bool "Exynos5433 DRM DECON"
- depends on DRM_EXYNOS
+ bool "DECON on Exynos5433"
help
Choose this option if you want to use Exynos5433 DECON for DRM.
config DRM_EXYNOS7_DECON
- bool "Exynos7 DRM DECON"
- depends on DRM_EXYNOS && !FB_S3C
+ bool "DECON on Exynos7"
+ depends on !FB_S3C
select FB_MODE_HELPERS
help
Choose this option if you want to use Exynos DECON for DRM.
+config DRM_EXYNOS_MIXER
+ bool "Mixer"
+ depends on !VIDEO_SAMSUNG_S5P_TV
+ help
+ Choose this option if you want to use Exynos Mixer for DRM.
+
+config DRM_EXYNOS_VIDI
+ bool "Virtual Display"
+ help
+ Choose this option if you want to use Exynos VIDI for DRM.
+
+comment "Encoders and Bridges"
+
config DRM_EXYNOS_DPI
- bool "EXYNOS DRM parallel output support"
- depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+ bool "Parallel output"
+ depends on DRM_EXYNOS_FIMD
select DRM_PANEL
default n
help
This enables support for Exynos parallel output.
config DRM_EXYNOS_DSI
- bool "EXYNOS DRM MIPI-DSI driver support"
- depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON)
+ bool "MIPI-DSI host"
+ depends on DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON
select DRM_MIPI_DSI
select DRM_PANEL
default n
@@ -55,58 +71,55 @@ config DRM_EXYNOS_DSI
This enables support for Exynos MIPI-DSI device.
config DRM_EXYNOS_DP
- bool "EXYNOS DRM DP driver support"
- depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+ bool "Display Port"
+ depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
default DRM_EXYNOS
select DRM_PANEL
help
This enables support for DP device.
config DRM_EXYNOS_HDMI
- bool "Exynos DRM HDMI"
- depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
+ bool "HDMI"
+ depends on !VIDEO_SAMSUNG_S5P_TV && (DRM_EXYNOS_MIXER || DRM_EXYNOS5433_DECON)
help
Choose this option if you want to use Exynos HDMI for DRM.
-config DRM_EXYNOS_VIDI
- bool "Exynos DRM Virtual Display"
- depends on DRM_EXYNOS
+config DRM_EXYNOS_MIC
+ bool "Mobile Image Compressor"
+ depends on DRM_EXYNOS5433_DECON
help
- Choose this option if you want to use Exynos VIDI for DRM.
+ Choose this option if you want to use Exynos MIC for DRM.
+
+comment "Sub-drivers"
config DRM_EXYNOS_G2D
- bool "Exynos DRM G2D"
- depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D
+ bool "G2D"
+ depends on !VIDEO_SAMSUNG_S5P_G2D
select FRAME_VECTOR
help
Choose this option if you want to use Exynos G2D for DRM.
config DRM_EXYNOS_IPP
- bool "Exynos DRM IPP"
- depends on DRM_EXYNOS
+ bool "Image Post Processor"
help
Choose this option if you want to use IPP feature for DRM.
config DRM_EXYNOS_FIMC
- bool "Exynos DRM FIMC"
+ bool "FIMC"
depends on DRM_EXYNOS_IPP && MFD_SYSCON
help
Choose this option if you want to use Exynos FIMC for DRM.
config DRM_EXYNOS_ROTATOR
- bool "Exynos DRM Rotator"
+ bool "Rotator"
depends on DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos Rotator for DRM.
config DRM_EXYNOS_GSC
- bool "Exynos DRM GSC"
+ bool "GScaler"
depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
help
Choose this option if you want to use Exynos GSC for DRM.
-config DRM_EXYNOS_MIC
- bool "Exynos DRM MIC"
- depends on (DRM_EXYNOS && DRM_EXYNOS5433_DECON)
- help
- Choose this option if you want to use Exynos MIC for DRM.
+endif
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 02aecfed6354..6496532aaa91 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -14,7 +14,8 @@ exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o
exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER) += exynos_mixer.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index b3c730770b0f..fbe1b3174f75 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
@@ -24,28 +25,11 @@
#include "exynos_drm_iommu.h"
#define WINDOWS_NR 3
+#define CURSOR_WIN 2
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
-struct decon_context {
- struct device *dev;
- struct drm_device *drm_dev;
- struct exynos_drm_crtc *crtc;
- struct exynos_drm_plane planes[WINDOWS_NR];
- void __iomem *addr;
- struct clk *clks[6];
- unsigned int default_win;
- unsigned long irq_flags;
- int pipe;
- bool suspended;
-
-#define BIT_CLKS_ENABLED 0
-#define BIT_IRQS_ENABLED 1
- unsigned long enabled;
- bool i80_if;
- atomic_t win_updated;
-};
-
static const char * const decon_clks_name[] = {
+ "pclk",
"aclk_decon",
"aclk_smmu_decon0x",
"aclk_xiu_decon0x",
@@ -54,6 +38,32 @@ static const char * const decon_clks_name[] = {
"sclk_decon_eclk",
};
+enum decon_iftype {
+ IFTYPE_RGB,
+ IFTYPE_I80,
+ IFTYPE_HDMI
+};
+
+enum decon_flag_bits {
+ BIT_CLKS_ENABLED,
+ BIT_IRQS_ENABLED,
+ BIT_WIN_UPDATED,
+ BIT_SUSPENDED
+};
+
+struct decon_context {
+ struct device *dev;
+ struct drm_device *drm_dev;
+ struct exynos_drm_crtc *crtc;
+ struct exynos_drm_plane planes[WINDOWS_NR];
+ void __iomem *addr;
+ struct clk *clks[ARRAY_SIZE(decon_clks_name)];
+ int pipe;
+ unsigned long flags;
+ enum decon_iftype out_type;
+ int first_win;
+};
+
static const uint32_t decon_formats[] = {
DRM_FORMAT_XRGB1555,
DRM_FORMAT_RGB565,
@@ -61,17 +71,24 @@ static const uint32_t decon_formats[] = {
DRM_FORMAT_ARGB8888,
};
+static inline void decon_set_bits(struct decon_context *ctx, u32 reg, u32 mask,
+ u32 val)
+{
+ val = (val & mask) | (readl(ctx->addr + reg) & ~mask);
+ writel(val, ctx->addr + reg);
+}
+
static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
u32 val;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return -EPERM;
- if (test_and_set_bit(0, &ctx->irq_flags)) {
+ if (test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
val = VIDINTCON0_INTEN;
- if (ctx->i80_if)
+ if (ctx->out_type == IFTYPE_I80)
val |= VIDINTCON0_FRAMEDONE;
else
val |= VIDINTCON0_INTFRMEN;
@@ -86,79 +103,85 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
- if (test_and_clear_bit(0, &ctx->irq_flags))
+ if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags))
writel(0, ctx->addr + DECON_VIDINTCON0);
}
static void decon_setup_trigger(struct decon_context *ctx)
{
- u32 val = TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
- TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN;
+ u32 val = (ctx->out_type != IFTYPE_HDMI)
+ ? TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
+ TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN
+ : TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
+ TRIGCON_HWTRIGMASK_I80_RGB | TRIGCON_HWTRIGEN_I80_RGB;
writel(val, ctx->addr + DECON_TRIGCON);
}
static void decon_commit(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
- struct drm_display_mode *mode = &crtc->base.mode;
+ struct drm_display_mode *m = &crtc->base.mode;
u32 val;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
+ if (ctx->out_type == IFTYPE_HDMI) {
+ m->crtc_hsync_start = m->crtc_hdisplay + 10;
+ m->crtc_hsync_end = m->crtc_htotal - 92;
+ m->crtc_vsync_start = m->crtc_vdisplay + 1;
+ m->crtc_vsync_end = m->crtc_vsync_start + 1;
+ }
+
+ decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID, 0);
+
/* enable clock gate */
val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F;
writel(val, ctx->addr + DECON_CMU);
/* lcd on and use command if */
val = VIDOUT_LCD_ON;
- if (ctx->i80_if)
+ if (ctx->out_type == IFTYPE_I80)
val |= VIDOUT_COMMAND_IF;
else
val |= VIDOUT_RGB_IF;
writel(val, ctx->addr + DECON_VIDOUTCON0);
- val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
- VIDTCON2_HOZVAL(mode->hdisplay - 1);
+ val = VIDTCON2_LINEVAL(m->vdisplay - 1) |
+ VIDTCON2_HOZVAL(m->hdisplay - 1);
writel(val, ctx->addr + DECON_VIDTCON2);
- if (!ctx->i80_if) {
+ if (ctx->out_type != IFTYPE_I80) {
val = VIDTCON00_VBPD_F(
- mode->crtc_vtotal - mode->crtc_vsync_end) |
+ m->crtc_vtotal - m->crtc_vsync_end - 1) |
VIDTCON00_VFPD_F(
- mode->crtc_vsync_start - mode->crtc_vdisplay);
+ m->crtc_vsync_start - m->crtc_vdisplay - 1);
writel(val, ctx->addr + DECON_VIDTCON00);
val = VIDTCON01_VSPW_F(
- mode->crtc_vsync_end - mode->crtc_vsync_start);
+ m->crtc_vsync_end - m->crtc_vsync_start - 1);
writel(val, ctx->addr + DECON_VIDTCON01);
val = VIDTCON10_HBPD_F(
- mode->crtc_htotal - mode->crtc_hsync_end) |
+ m->crtc_htotal - m->crtc_hsync_end - 1) |
VIDTCON10_HFPD_F(
- mode->crtc_hsync_start - mode->crtc_hdisplay);
+ m->crtc_hsync_start - m->crtc_hdisplay - 1);
writel(val, ctx->addr + DECON_VIDTCON10);
val = VIDTCON11_HSPW_F(
- mode->crtc_hsync_end - mode->crtc_hsync_start);
+ m->crtc_hsync_end - m->crtc_hsync_start - 1);
writel(val, ctx->addr + DECON_VIDTCON11);
}
decon_setup_trigger(ctx);
/* enable output and display signal */
- val = VIDCON0_ENVID | VIDCON0_ENVID_F;
- writel(val, ctx->addr + DECON_VIDCON0);
+ decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0);
}
-#define COORDINATE_X(x) (((x) & 0xfff) << 12)
-#define COORDINATE_Y(x) ((x) & 0xfff)
-#define OFFSIZE(x) (((x) & 0x3fff) << 14)
-#define PAGEWIDTH(x) ((x) & 0x3fff)
-
static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
struct drm_framebuffer *fb)
{
@@ -214,16 +237,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
static void decon_shadow_protect_win(struct decon_context *ctx, int win,
bool protect)
{
- u32 val;
-
- val = readl(ctx->addr + DECON_SHADOWCON);
-
- if (protect)
- val |= SHADOWCON_Wx_PROTECT(win);
- else
- val &= ~SHADOWCON_Wx_PROTECT(win);
-
- writel(val, ctx->addr + DECON_SHADOWCON);
+ decon_set_bits(ctx, DECON_SHADOWCON, SHADOWCON_Wx_PROTECT(win),
+ protect ? ~0 : 0);
}
static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
@@ -231,12 +246,16 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
{
struct decon_context *ctx = crtc->ctx;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
decon_shadow_protect_win(ctx, plane->zpos, true);
}
+#define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s))
+#define COORDINATE_X(x) BIT_VAL((x), 23, 12)
+#define COORDINATE_Y(x) BIT_VAL((x), 11, 0)
+
static void decon_update_plane(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane)
{
@@ -247,7 +266,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
unsigned int pitch = state->fb->pitches[0];
u32 val;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
@@ -270,21 +289,21 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
val = plane->dma_addr[0] + pitch * plane->crtc_h;
writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
- val = OFFSIZE(pitch - plane->crtc_w * bpp)
- | PAGEWIDTH(plane->crtc_w * bpp);
+ if (ctx->out_type != IFTYPE_HDMI)
+ val = BIT_VAL(pitch - plane->crtc_w * bpp, 27, 14)
+ | BIT_VAL(plane->crtc_w * bpp, 13, 0);
+ else
+ val = BIT_VAL(pitch - plane->crtc_w * bpp, 29, 15)
+ | BIT_VAL(plane->crtc_w * bpp, 14, 0);
writel(val, ctx->addr + DECON_VIDW0xADD2(win));
decon_win_set_pixfmt(ctx, win, state->fb);
/* window enable */
- val = readl(ctx->addr + DECON_WINCONx(win));
- val |= WINCONx_ENWIN_F;
- writel(val, ctx->addr + DECON_WINCONx(win));
+ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
/* standalone update */
- val = readl(ctx->addr + DECON_UPDATE);
- val |= STANDALONE_UPDATE_F;
- writel(val, ctx->addr + DECON_UPDATE);
+ decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
}
static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -292,24 +311,19 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
{
struct decon_context *ctx = crtc->ctx;
unsigned int win = plane->zpos;
- u32 val;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
decon_shadow_protect_win(ctx, win, true);
/* window disable */
- val = readl(ctx->addr + DECON_WINCONx(win));
- val &= ~WINCONx_ENWIN_F;
- writel(val, ctx->addr + DECON_WINCONx(win));
+ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
decon_shadow_protect_win(ctx, win, false);
/* standalone update */
- val = readl(ctx->addr + DECON_UPDATE);
- val |= STANDALONE_UPDATE_F;
- writel(val, ctx->addr + DECON_UPDATE);
+ decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
}
static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
@@ -317,13 +331,13 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
{
struct decon_context *ctx = crtc->ctx;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
decon_shadow_protect_win(ctx, plane->zpos, false);
- if (ctx->i80_if)
- atomic_set(&ctx->win_updated, 1);
+ if (ctx->out_type == IFTYPE_I80)
+ set_bit(BIT_WIN_UPDATED, &ctx->flags);
}
static void decon_swreset(struct decon_context *ctx)
@@ -347,6 +361,17 @@ static void decon_swreset(struct decon_context *ctx)
}
WARN(tries == 0, "failed to software reset DECON\n");
+
+ if (ctx->out_type != IFTYPE_HDMI)
+ return;
+
+ writel(VIDCON0_CLKVALUP | VIDCON0_VLCKFREE, ctx->addr + DECON_VIDCON0);
+ decon_set_bits(ctx, DECON_CMU,
+ CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F, ~0);
+ writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1);
+ writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN,
+ ctx->addr + DECON_CRCCTRL);
+ decon_setup_trigger(ctx);
}
static void decon_enable(struct exynos_drm_crtc *crtc)
@@ -355,11 +380,9 @@ static void decon_enable(struct exynos_drm_crtc *crtc)
int ret;
int i;
- if (!ctx->suspended)
+ if (!test_and_clear_bit(BIT_SUSPENDED, &ctx->flags))
return;
- ctx->suspended = false;
-
pm_runtime_get_sync(ctx->dev);
for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
@@ -368,10 +391,10 @@ static void decon_enable(struct exynos_drm_crtc *crtc)
goto err;
}
- set_bit(BIT_CLKS_ENABLED, &ctx->enabled);
+ set_bit(BIT_CLKS_ENABLED, &ctx->flags);
/* if vblank was enabled status, enable it again. */
- if (test_and_clear_bit(0, &ctx->irq_flags))
+ if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags))
decon_enable_vblank(ctx->crtc);
decon_commit(ctx->crtc);
@@ -381,7 +404,7 @@ err:
while (--i >= 0)
clk_disable_unprepare(ctx->clks[i]);
- ctx->suspended = true;
+ set_bit(BIT_SUSPENDED, &ctx->flags);
}
static void decon_disable(struct exynos_drm_crtc *crtc)
@@ -389,7 +412,7 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
struct decon_context *ctx = crtc->ctx;
int i;
- if (ctx->suspended)
+ if (test_bit(BIT_SUSPENDED, &ctx->flags))
return;
/*
@@ -397,7 +420,7 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
* suspend that connector. Otherwise we might try to scan from
* a destroyed buffer later.
*/
- for (i = 0; i < WINDOWS_NR; i++)
+ for (i = ctx->first_win; i < WINDOWS_NR; i++)
decon_disable_plane(crtc, &ctx->planes[i]);
decon_swreset(ctx);
@@ -405,27 +428,22 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
clk_disable_unprepare(ctx->clks[i]);
- clear_bit(BIT_CLKS_ENABLED, &ctx->enabled);
+ clear_bit(BIT_CLKS_ENABLED, &ctx->flags);
pm_runtime_put_sync(ctx->dev);
- ctx->suspended = true;
+ set_bit(BIT_SUSPENDED, &ctx->flags);
}
void decon_te_irq_handler(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
- u32 val;
- if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
+ if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags))
return;
- if (atomic_add_unless(&ctx->win_updated, -1, 0)) {
- /* trigger */
- val = readl(ctx->addr + DECON_TRIGCON);
- val |= TRIGCON_SWTRIGCMD;
- writel(val, ctx->addr + DECON_TRIGCON);
- }
+ if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags))
+ decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0);
drm_crtc_handle_vblank(&ctx->crtc->base);
}
@@ -434,7 +452,6 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
int win, i, ret;
- u32 val;
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -445,25 +462,10 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc)
}
for (win = 0; win < WINDOWS_NR; win++) {
- /* shadow update disable */
- val = readl(ctx->addr + DECON_SHADOWCON);
- val |= SHADOWCON_Wx_PROTECT(win);
- writel(val, ctx->addr + DECON_SHADOWCON);
-
- /* window disable */
- val = readl(ctx->addr + DECON_WINCONx(win));
- val &= ~WINCONx_ENWIN_F;
- writel(val, ctx->addr + DECON_WINCONx(win));
-
- /* shadow update enable */
- val = readl(ctx->addr + DECON_SHADOWCON);
- val &= ~SHADOWCON_Wx_PROTECT(win);
- writel(val, ctx->addr + DECON_SHADOWCON);
-
- /* standalone update */
- val = readl(ctx->addr + DECON_UPDATE);
- val |= STANDALONE_UPDATE_F;
- writel(val, ctx->addr + DECON_UPDATE);
+ decon_shadow_protect_win(ctx, win, true);
+ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
+ decon_shadow_protect_win(ctx, win, false);
+ decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
}
/* TODO: wait for possible vsync */
msleep(50);
@@ -479,7 +481,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
.commit = decon_commit,
.enable_vblank = decon_enable_vblank,
.disable_vblank = decon_disable_vblank,
- .commit = decon_commit,
.atomic_begin = decon_atomic_begin,
.update_plane = decon_update_plane,
.disable_plane = decon_disable_plane,
@@ -493,26 +494,30 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
struct drm_device *drm_dev = data;
struct exynos_drm_private *priv = drm_dev->dev_private;
struct exynos_drm_plane *exynos_plane;
+ enum exynos_drm_output_type out_type;
enum drm_plane_type type;
- unsigned int zpos;
+ unsigned int win;
int ret;
ctx->drm_dev = drm_dev;
ctx->pipe = priv->pipe++;
- for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
- type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
- DRM_PLANE_TYPE_OVERLAY;
- ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
+ for (win = ctx->first_win; win < WINDOWS_NR; win++) {
+ int tmp = (win == ctx->first_win) ? 0 : win;
+
+ type = exynos_plane_get_type(tmp, CURSOR_WIN);
+ ret = exynos_plane_init(drm_dev, &ctx->planes[win],
1 << ctx->pipe, type, decon_formats,
- ARRAY_SIZE(decon_formats), zpos);
+ ARRAY_SIZE(decon_formats), win);
if (ret)
return ret;
}
- exynos_plane = &ctx->planes[ctx->default_win];
+ exynos_plane = &ctx->planes[ctx->first_win];
+ out_type = (ctx->out_type == IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI
+ : EXYNOS_DISPLAY_TYPE_LCD;
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
- ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
+ ctx->pipe, out_type,
&decon_crtc_ops, ctx);
if (IS_ERR(ctx->crtc)) {
ret = PTR_ERR(ctx->crtc);
@@ -546,38 +551,20 @@ static const struct component_ops decon_component_ops = {
.unbind = decon_unbind,
};
-static irqreturn_t decon_vsync_irq_handler(int irq, void *dev_id)
-{
- struct decon_context *ctx = dev_id;
- u32 val;
-
- if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
- goto out;
-
- val = readl(ctx->addr + DECON_VIDINTCON1);
- if (val & VIDINTCON1_INTFRMPEND) {
- drm_crtc_handle_vblank(&ctx->crtc->base);
-
- /* clear */
- writel(VIDINTCON1_INTFRMPEND, ctx->addr + DECON_VIDINTCON1);
- }
-
-out:
- return IRQ_HANDLED;
-}
-
-static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
+static irqreturn_t decon_irq_handler(int irq, void *dev_id)
{
struct decon_context *ctx = dev_id;
u32 val;
int win;
- if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
+ if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags))
goto out;
val = readl(ctx->addr + DECON_VIDINTCON1);
- if (val & VIDINTCON1_INTFRMDONEPEND) {
- for (win = 0 ; win < WINDOWS_NR ; win++) {
+ val &= VIDINTCON1_INTFRMDONEPEND | VIDINTCON1_INTFRMPEND;
+
+ if (val) {
+ for (win = ctx->first_win; win < WINDOWS_NR ; win++) {
struct exynos_drm_plane *plane = &ctx->planes[win];
if (!plane->pending_fb)
@@ -587,16 +574,29 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
}
/* clear */
- writel(VIDINTCON1_INTFRMDONEPEND,
- ctx->addr + DECON_VIDINTCON1);
+ writel(val, ctx->addr + DECON_VIDINTCON1);
}
out:
return IRQ_HANDLED;
}
+static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
+ {
+ .compatible = "samsung,exynos5433-decon",
+ .data = (void *)IFTYPE_RGB
+ },
+ {
+ .compatible = "samsung,exynos5433-decon-tv",
+ .data = (void *)IFTYPE_HDMI
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
+
static int exynos5433_decon_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id;
struct device *dev = &pdev->dev;
struct decon_context *ctx;
struct resource *res;
@@ -607,11 +607,16 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
- ctx->default_win = 0;
- ctx->suspended = true;
+ __set_bit(BIT_SUSPENDED, &ctx->flags);
ctx->dev = dev;
- if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
- ctx->i80_if = true;
+
+ of_id = of_match_device(exynos5433_decon_driver_dt_match, &pdev->dev);
+ ctx->out_type = (enum decon_iftype)of_id->data;
+
+ if (ctx->out_type == IFTYPE_HDMI)
+ ctx->first_win = 1;
+ else if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
+ ctx->out_type = IFTYPE_I80;
for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
struct clk *clk;
@@ -636,15 +641,14 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
}
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
- ctx->i80_if ? "lcd_sys" : "vsync");
+ (ctx->out_type == IFTYPE_I80) ? "lcd_sys" : "vsync");
if (!res) {
dev_err(dev, "cannot find IRQ resource\n");
return -ENXIO;
}
- ret = devm_request_irq(dev, res->start, ctx->i80_if ?
- decon_lcd_sys_irq_handler : decon_vsync_irq_handler, 0,
- "drm_decon", ctx);
+ ret = devm_request_irq(dev, res->start, decon_irq_handler, 0,
+ "drm_decon", ctx);
if (ret < 0) {
dev_err(dev, "lcd_sys irq request failed\n");
return ret;
@@ -675,12 +679,6 @@ static int exynos5433_decon_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
- { .compatible = "samsung,exynos5433-decon" },
- {},
-};
-MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
-
struct platform_driver exynos5433_decon_driver = {
.probe = exynos5433_decon_probe,
.remove = exynos5433_decon_remove,
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index e6cbaca821a4..ead2b16e237d 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -40,6 +40,7 @@
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
#define WINDOWS_NR 2
+#define CURSOR_WIN 1
struct decon_context {
struct device *dev;
@@ -51,7 +52,6 @@ struct decon_context {
struct clk *eclk;
struct clk *vclk;
void __iomem *regs;
- unsigned int default_win;
unsigned long irq_flags;
bool i80_if;
bool suspended;
@@ -690,8 +690,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
}
for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
- type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
- DRM_PLANE_TYPE_OVERLAY;
+ type = exynos_plane_get_type(zpos, CURSOR_WIN);
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type, decon_formats,
ARRAY_SIZE(decon_formats), zpos);
@@ -699,7 +698,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
return ret;
}
- exynos_plane = &ctx->planes[ctx->default_win];
+ exynos_plane = &ctx->planes[DEFAULT_WIN];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
&decon_crtc_ops, ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index ed28823d3b35..b3ba27fd9a6b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -50,6 +50,17 @@ exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
exynos_crtc->ops->commit(exynos_crtc);
}
+static int exynos_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+ if (exynos_crtc->ops->atomic_check)
+ return exynos_crtc->ops->atomic_check(exynos_crtc, state);
+
+ return 0;
+}
+
static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -86,6 +97,7 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
.enable = exynos_drm_crtc_enable,
.disable = exynos_drm_crtc_disable,
.mode_set_nofb = exynos_drm_crtc_mode_set_nofb,
+ .atomic_check = exynos_crtc_atomic_check,
.atomic_begin = exynos_crtc_atomic_begin,
.atomic_flush = exynos_crtc_atomic_flush,
};
@@ -152,7 +164,7 @@ err_crtc:
return ERR_PTR(ret);
}
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc =
@@ -164,7 +176,7 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
return 0;
}
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc =
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index f87d4abda6f7..f9f365bd0257 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -23,8 +23,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
enum exynos_drm_output_type type,
const struct exynos_drm_crtc_ops *ops,
void *context);
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe);
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe);
void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
struct exynos_drm_plane *exynos_plane);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index ae9e6b2d3758..2c6019d6a205 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -105,7 +105,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
atomic_inc(&exynos_crtc->pending_update);
}
- drm_atomic_helper_commit_planes(dev, state);
+ drm_atomic_helper_commit_planes(dev, state, false);
exynos_atomic_wait_for_commit(state);
@@ -405,25 +405,25 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
static const struct drm_ioctl_desc exynos_ioctls[] = {
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl,
- DRM_UNLOCKED | DRM_AUTH),
+ DRM_AUTH),
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, exynos_g2d_get_ver_ioctl,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, exynos_g2d_set_cmdlist_ioctl,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, exynos_drm_ipp_get_property,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, exynos_drm_ipp_set_property,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF, exynos_drm_ipp_queue_buf,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL, exynos_drm_ipp_cmd_ctrl,
- DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
};
static const struct file_operations exynos_drm_driver_fops = {
@@ -449,7 +449,7 @@ static struct drm_driver exynos_drm_driver = {
.lastclose = exynos_drm_lastclose,
.postclose = exynos_drm_postclose,
.set_busid = drm_platform_set_busid,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = exynos_drm_crtc_enable_vblank,
.disable_vblank = exynos_drm_crtc_disable_vblank,
.gem_free_object = exynos_drm_gem_free_object,
@@ -529,8 +529,10 @@ static struct platform_driver *const exynos_drm_kms_drivers[] = {
#ifdef CONFIG_DRM_EXYNOS_DSI
&dsi_driver,
#endif
-#ifdef CONFIG_DRM_EXYNOS_HDMI
+#ifdef CONFIG_DRM_EXYNOS_MIXER
&mixer_driver,
+#endif
+#ifdef CONFIG_DRM_EXYNOS_HDMI
&hdmi_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_VIDI
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 6c717ba672db..f1eda7fa4e3c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -22,6 +22,8 @@
#define MAX_PLANE 5
#define MAX_FB_BUFFER 4
+#define DEFAULT_WIN 0
+
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base)
#define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
@@ -87,6 +89,7 @@ struct exynos_drm_plane {
* @disable_vblank: specific driver callback for disabling vblank interrupt.
* @wait_for_vblank: wait for vblank interrupt to make sure that
* hardware overlay is updated.
+ * @atomic_check: validate state
* @atomic_begin: prepare a window to receive a update
* @atomic_flush: mark the end of a window update
* @update_plane: apply hardware specific overlay data to registers.
@@ -106,6 +109,8 @@ struct exynos_drm_crtc_ops {
int (*enable_vblank)(struct exynos_drm_crtc *crtc);
void (*disable_vblank)(struct exynos_drm_crtc *crtc);
void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
+ int (*atomic_check)(struct exynos_drm_crtc *crtc,
+ struct drm_crtc_state *state);
void (*atomic_begin)(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane);
void (*update_plane)(struct exynos_drm_crtc *crtc,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 084280859589..fcea28bdbc42 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -32,15 +32,15 @@
* exynos specific framebuffer structure.
*
* @fb: drm framebuffer obejct.
- * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
+ * @exynos_gem: array of exynos specific gem object containing a gem object.
*/
struct exynos_drm_fb {
- struct drm_framebuffer fb;
- struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
+ struct drm_framebuffer fb;
+ struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
};
static int check_fb_gem_memory_type(struct drm_device *drm_dev,
- struct exynos_drm_gem_obj *exynos_gem_obj)
+ struct exynos_drm_gem *exynos_gem)
{
unsigned int flags;
@@ -51,7 +51,7 @@ static int check_fb_gem_memory_type(struct drm_device *drm_dev,
if (is_drm_iommu_supported(drm_dev))
return 0;
- flags = exynos_gem_obj->flags;
+ flags = exynos_gem->flags;
/*
* without iommu support, not support physically non-continuous memory
@@ -75,13 +75,13 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
drm_framebuffer_cleanup(fb);
- for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) {
+ for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem); i++) {
struct drm_gem_object *obj;
- if (exynos_fb->exynos_gem_obj[i] == NULL)
+ if (exynos_fb->exynos_gem[i] == NULL)
continue;
- obj = &exynos_fb->exynos_gem_obj[i]->base;
+ obj = &exynos_fb->exynos_gem[i]->base;
drm_gem_object_unreference_unlocked(obj);
}
@@ -96,7 +96,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
return drm_gem_handle_create(file_priv,
- &exynos_fb->exynos_gem_obj[0]->base, handle);
+ &exynos_fb->exynos_gem[0]->base, handle);
}
static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
@@ -118,7 +118,7 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
- struct exynos_drm_gem_obj **gem_obj,
+ struct exynos_drm_gem **exynos_gem,
int count)
{
struct exynos_drm_fb *exynos_fb;
@@ -130,11 +130,11 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
return ERR_PTR(-ENOMEM);
for (i = 0; i < count; i++) {
- ret = check_fb_gem_memory_type(dev, gem_obj[i]);
+ ret = check_fb_gem_memory_type(dev, exynos_gem[i]);
if (ret < 0)
goto err;
- exynos_fb->exynos_gem_obj[i] = gem_obj[i];
+ exynos_fb->exynos_gem[i] = exynos_gem[i];
}
drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
@@ -156,7 +156,7 @@ static struct drm_framebuffer *
exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
struct drm_mode_fb_cmd2 *mode_cmd)
{
- struct exynos_drm_gem_obj *gem_objs[MAX_FB_BUFFER];
+ struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
struct drm_gem_object *obj;
struct drm_framebuffer *fb;
int i;
@@ -171,10 +171,10 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
goto err;
}
- gem_objs[i] = to_exynos_gem_obj(obj);
+ exynos_gem[i] = to_exynos_gem(obj);
}
- fb = exynos_drm_framebuffer_init(dev, mode_cmd, gem_objs, i);
+ fb = exynos_drm_framebuffer_init(dev, mode_cmd, exynos_gem, i);
if (IS_ERR(fb)) {
ret = PTR_ERR(fb);
goto err;
@@ -184,27 +184,26 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
err:
while (i--)
- drm_gem_object_unreference_unlocked(&gem_objs[i]->base);
+ drm_gem_object_unreference_unlocked(&exynos_gem[i]->base);
return ERR_PTR(ret);
}
-struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
- int index)
+struct exynos_drm_gem *exynos_drm_fb_gem(struct drm_framebuffer *fb, int index)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
- struct exynos_drm_gem_obj *obj;
+ struct exynos_drm_gem *exynos_gem;
if (index >= MAX_FB_BUFFER)
return NULL;
- obj = exynos_fb->exynos_gem_obj[index];
- if (!obj)
+ exynos_gem = exynos_fb->exynos_gem[index];
+ if (!exynos_gem)
return NULL;
- DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)obj->dma_addr);
+ DRM_DEBUG_KMS("dma_addr: 0x%lx\n", (unsigned long)exynos_gem->dma_addr);
- return obj;
+ return exynos_gem;
}
static void exynos_drm_output_poll_changed(struct drm_device *dev)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
index 85e4445b920e..726a2d44371f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -19,12 +19,11 @@
struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
- struct exynos_drm_gem_obj **gem_obj,
+ struct exynos_drm_gem **exynos_gem,
int count);
/* get gem object of a drm framebuffer */
-struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
- int index);
+struct exynos_drm_gem *exynos_drm_fb_gem(struct drm_framebuffer *fb, int index);
void exynos_drm_mode_config_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index a221f753ad9c..f6118baa8e3e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -30,8 +30,8 @@
drm_fb_helper)
struct exynos_drm_fbdev {
- struct drm_fb_helper drm_fb_helper;
- struct exynos_drm_gem_obj *obj;
+ struct drm_fb_helper drm_fb_helper;
+ struct exynos_drm_gem *exynos_gem;
};
static int exynos_drm_fb_mmap(struct fb_info *info,
@@ -39,7 +39,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
{
struct drm_fb_helper *helper = info->par;
struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper);
- struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
+ struct exynos_drm_gem *exynos_gem = exynos_fbd->exynos_gem;
unsigned long vm_size;
int ret;
@@ -47,11 +47,12 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
vm_size = vma->vm_end - vma->vm_start;
- if (vm_size > obj->size)
+ if (vm_size > exynos_gem->size)
return -EINVAL;
- ret = dma_mmap_attrs(helper->dev->dev, vma, obj->pages, obj->dma_addr,
- obj->size, &obj->dma_attrs);
+ ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->pages,
+ exynos_gem->dma_addr, exynos_gem->size,
+ &exynos_gem->dma_attrs);
if (ret < 0) {
DRM_ERROR("failed to mmap.\n");
return ret;
@@ -75,7 +76,7 @@ static struct fb_ops exynos_drm_fb_ops = {
static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes,
- struct exynos_drm_gem_obj *obj)
+ struct exynos_drm_gem *exynos_gem)
{
struct fb_info *fbi;
struct drm_framebuffer *fb = helper->fb;
@@ -96,11 +97,11 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
- nr_pages = obj->size >> PAGE_SHIFT;
+ nr_pages = exynos_gem->size >> PAGE_SHIFT;
- obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP,
- pgprot_writecombine(PAGE_KERNEL));
- if (!obj->kvaddr) {
+ exynos_gem->kvaddr = (void __iomem *) vmap(exynos_gem->pages, nr_pages,
+ VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+ if (!exynos_gem->kvaddr) {
DRM_ERROR("failed to map pages to kernel space.\n");
drm_fb_helper_release_fbi(helper);
return -EIO;
@@ -109,7 +110,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
offset += fbi->var.yoffset * fb->pitches[0];
- fbi->screen_base = obj->kvaddr + offset;
+ fbi->screen_base = exynos_gem->kvaddr + offset;
fbi->screen_size = size;
fbi->fix.smem_len = size;
@@ -120,7 +121,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
- struct exynos_drm_gem_obj *obj;
+ struct exynos_drm_gem *exynos_gem;
struct drm_device *dev = helper->dev;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct platform_device *pdev = dev->platformdev;
@@ -141,32 +142,34 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
size = mode_cmd.pitches[0] * mode_cmd.height;
- obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
+ exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
/*
* If physically contiguous memory allocation fails and if IOMMU is
* supported then try to get buffer from non physically contiguous
* memory area.
*/
- if (IS_ERR(obj) && is_drm_iommu_supported(dev)) {
+ if (IS_ERR(exynos_gem) && is_drm_iommu_supported(dev)) {
dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
- obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, size);
+ exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG,
+ size);
}
- if (IS_ERR(obj)) {
- ret = PTR_ERR(obj);
+ if (IS_ERR(exynos_gem)) {
+ ret = PTR_ERR(exynos_gem);
goto out;
}
- exynos_fbdev->obj = obj;
+ exynos_fbdev->exynos_gem = exynos_gem;
- helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj, 1);
+ helper->fb =
+ exynos_drm_framebuffer_init(dev, &mode_cmd, &exynos_gem, 1);
if (IS_ERR(helper->fb)) {
DRM_ERROR("failed to create drm framebuffer.\n");
ret = PTR_ERR(helper->fb);
goto err_destroy_gem;
}
- ret = exynos_drm_fbdev_update(helper, sizes, obj);
+ ret = exynos_drm_fbdev_update(helper, sizes, exynos_gem);
if (ret < 0)
goto err_destroy_framebuffer;
@@ -176,7 +179,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
err_destroy_framebuffer:
drm_framebuffer_cleanup(helper->fb);
err_destroy_gem:
- exynos_drm_gem_destroy(obj);
+ exynos_drm_gem_destroy(exynos_gem);
/*
* if failed, all resources allocated above would be released by
@@ -269,11 +272,11 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
struct drm_fb_helper *fb_helper)
{
struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
- struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
+ struct exynos_drm_gem *exynos_gem = exynos_fbd->exynos_gem;
struct drm_framebuffer *fb;
- if (obj->kvaddr)
- vunmap(obj->kvaddr);
+ if (exynos_gem->kvaddr)
+ vunmap(exynos_gem->kvaddr);
/* release drm framebuffer and real buffer */
if (fb_helper->fb && fb_helper->fb->funcs) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index dd3a5e6d58c8..c747824f3c98 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -466,7 +466,7 @@ static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
EXYNOS_MSCTRL_C_INT_IN_2PLANE);
break;
default:
- dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt);
+ dev_err(ippdrv->dev, "invalid source yuv order 0x%x.\n", fmt);
return -EINVAL;
}
@@ -513,7 +513,7 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt)
cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
break;
default:
- dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt);
+ dev_err(ippdrv->dev, "invalid source format 0x%x.\n", fmt);
return -EINVAL;
}
@@ -578,7 +578,7 @@ static int fimc_src_set_transf(struct device *dev,
cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
break;
default:
- dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
return -EINVAL;
}
@@ -701,7 +701,7 @@ static int fimc_src_set_addr(struct device *dev,
property->prop_id, buf_id, buf_type);
if (buf_id > FIMC_MAX_SRC) {
- dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
return -ENOMEM;
}
@@ -812,7 +812,7 @@ static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
break;
default:
- dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
+ dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
return -EINVAL;
}
@@ -865,7 +865,7 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
break;
default:
- dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
+ dev_err(ippdrv->dev, "invalid target format 0x%x.\n",
fmt);
return -EINVAL;
}
@@ -929,7 +929,7 @@ static int fimc_dst_set_transf(struct device *dev,
cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
break;
default:
- dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
return -EINVAL;
}
@@ -1160,7 +1160,7 @@ static int fimc_dst_set_addr(struct device *dev,
property->prop_id, buf_id, buf_type);
if (buf_id > FIMC_MAX_DST) {
- dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 3d1aba67758b..bd75c1531cac 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -87,6 +87,7 @@
/* FIMD has totally five hardware windows. */
#define WINDOWS_NR 5
+#define CURSOR_WIN 4
struct fimd_driver_data {
unsigned int timing_base;
@@ -153,7 +154,6 @@ struct fimd_context {
struct clk *lcd_clk;
void __iomem *regs;
struct regmap *sysreg;
- unsigned int default_win;
unsigned long irq_flags;
u32 vidcon0;
u32 vidcon1;
@@ -949,8 +949,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
ctx->pipe = priv->pipe++;
for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
- type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
- DRM_PLANE_TYPE_OVERLAY;
+ type = exynos_plane_get_type(zpos, CURSOR_WIN);
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type, fimd_formats,
ARRAY_SIZE(fimd_formats), zpos);
@@ -958,7 +957,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
return ret;
}
- exynos_plane = &ctx->planes[ctx->default_win];
+ exynos_plane = &ctx->planes[DEFAULT_WIN];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
&fimd_crtc_ops, ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 407afedb6003..252eb301470c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -20,97 +20,108 @@
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"
-static int exynos_drm_alloc_buf(struct exynos_drm_gem_obj *obj)
+static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
{
- struct drm_device *dev = obj->base.dev;
+ struct drm_device *dev = exynos_gem->base.dev;
enum dma_attr attr;
unsigned int nr_pages;
+ struct sg_table sgt;
+ int ret = -ENOMEM;
- if (obj->dma_addr) {
+ if (exynos_gem->dma_addr) {
DRM_DEBUG_KMS("already allocated.\n");
return 0;
}
- init_dma_attrs(&obj->dma_attrs);
+ init_dma_attrs(&exynos_gem->dma_attrs);
/*
* if EXYNOS_BO_CONTIG, fully physically contiguous memory
* region will be allocated else physically contiguous
* as possible.
*/
- if (!(obj->flags & EXYNOS_BO_NONCONTIG))
- dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &obj->dma_attrs);
+ if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
+ dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &exynos_gem->dma_attrs);
/*
* if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
* else cachable mapping.
*/
- if (obj->flags & EXYNOS_BO_WC || !(obj->flags & EXYNOS_BO_CACHABLE))
+ if (exynos_gem->flags & EXYNOS_BO_WC ||
+ !(exynos_gem->flags & EXYNOS_BO_CACHABLE))
attr = DMA_ATTR_WRITE_COMBINE;
else
attr = DMA_ATTR_NON_CONSISTENT;
- dma_set_attr(attr, &obj->dma_attrs);
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &obj->dma_attrs);
+ dma_set_attr(attr, &exynos_gem->dma_attrs);
+ dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &exynos_gem->dma_attrs);
- nr_pages = obj->size >> PAGE_SHIFT;
+ nr_pages = exynos_gem->size >> PAGE_SHIFT;
- if (!is_drm_iommu_supported(dev)) {
- obj->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
- if (!obj->pages) {
- DRM_ERROR("failed to allocate pages.\n");
- return -ENOMEM;
- }
+ exynos_gem->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
+ if (!exynos_gem->pages) {
+ DRM_ERROR("failed to allocate pages.\n");
+ return -ENOMEM;
}
- obj->cookie = dma_alloc_attrs(dev->dev, obj->size, &obj->dma_addr,
- GFP_KERNEL, &obj->dma_attrs);
- if (!obj->cookie) {
+ exynos_gem->cookie = dma_alloc_attrs(dev->dev, exynos_gem->size,
+ &exynos_gem->dma_addr, GFP_KERNEL,
+ &exynos_gem->dma_attrs);
+ if (!exynos_gem->cookie) {
DRM_ERROR("failed to allocate buffer.\n");
- if (obj->pages)
- drm_free_large(obj->pages);
- return -ENOMEM;
+ goto err_free;
}
- if (obj->pages) {
- dma_addr_t start_addr;
- unsigned int i = 0;
-
- start_addr = obj->dma_addr;
- while (i < nr_pages) {
- obj->pages[i] = pfn_to_page(dma_to_pfn(dev->dev,
- start_addr));
- start_addr += PAGE_SIZE;
- i++;
- }
- } else {
- obj->pages = obj->cookie;
+ ret = dma_get_sgtable_attrs(dev->dev, &sgt, exynos_gem->cookie,
+ exynos_gem->dma_addr, exynos_gem->size,
+ &exynos_gem->dma_attrs);
+ if (ret < 0) {
+ DRM_ERROR("failed to get sgtable.\n");
+ goto err_dma_free;
}
+ if (drm_prime_sg_to_page_addr_arrays(&sgt, exynos_gem->pages, NULL,
+ nr_pages)) {
+ DRM_ERROR("invalid sgtable.\n");
+ ret = -EINVAL;
+ goto err_sgt_free;
+ }
+
+ sg_free_table(&sgt);
+
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
- (unsigned long)obj->dma_addr,
- obj->size);
+ (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
return 0;
+
+err_sgt_free:
+ sg_free_table(&sgt);
+err_dma_free:
+ dma_free_attrs(dev->dev, exynos_gem->size, exynos_gem->cookie,
+ exynos_gem->dma_addr, &exynos_gem->dma_attrs);
+err_free:
+ drm_free_large(exynos_gem->pages);
+
+ return ret;
}
-static void exynos_drm_free_buf(struct exynos_drm_gem_obj *obj)
+static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
{
- struct drm_device *dev = obj->base.dev;
+ struct drm_device *dev = exynos_gem->base.dev;
- if (!obj->dma_addr) {
+ if (!exynos_gem->dma_addr) {
DRM_DEBUG_KMS("dma_addr is invalid.\n");
return;
}
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
- (unsigned long)obj->dma_addr, obj->size);
+ (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
- dma_free_attrs(dev->dev, obj->size, obj->cookie,
- (dma_addr_t)obj->dma_addr, &obj->dma_attrs);
+ dma_free_attrs(dev->dev, exynos_gem->size, exynos_gem->cookie,
+ (dma_addr_t)exynos_gem->dma_addr,
+ &exynos_gem->dma_attrs);
- if (!is_drm_iommu_supported(dev))
- drm_free_large(obj->pages);
+ drm_free_large(exynos_gem->pages);
}
static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
@@ -135,9 +146,9 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
return 0;
}
-void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
+void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
{
- struct drm_gem_object *obj = &exynos_gem_obj->base;
+ struct drm_gem_object *obj = &exynos_gem->base;
DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count);
@@ -148,21 +159,21 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
* once dmabuf's refcount becomes 0.
*/
if (obj->import_attach)
- drm_prime_gem_destroy(obj, exynos_gem_obj->sgt);
+ drm_prime_gem_destroy(obj, exynos_gem->sgt);
else
- exynos_drm_free_buf(exynos_gem_obj);
+ exynos_drm_free_buf(exynos_gem);
/* release file pointer to gem object. */
drm_gem_object_release(obj);
- kfree(exynos_gem_obj);
+ kfree(exynos_gem);
}
unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
unsigned int gem_handle,
struct drm_file *file_priv)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
struct drm_gem_object *obj;
obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
@@ -171,51 +182,51 @@ unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
return 0;
}
- exynos_gem_obj = to_exynos_gem_obj(obj);
+ exynos_gem = to_exynos_gem(obj);
drm_gem_object_unreference_unlocked(obj);
- return exynos_gem_obj->size;
+ return exynos_gem->size;
}
-static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
- unsigned long size)
+static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
+ unsigned long size)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
struct drm_gem_object *obj;
int ret;
- exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
- if (!exynos_gem_obj)
+ exynos_gem = kzalloc(sizeof(*exynos_gem), GFP_KERNEL);
+ if (!exynos_gem)
return ERR_PTR(-ENOMEM);
- exynos_gem_obj->size = size;
- obj = &exynos_gem_obj->base;
+ exynos_gem->size = size;
+ obj = &exynos_gem->base;
ret = drm_gem_object_init(dev, obj, size);
if (ret < 0) {
DRM_ERROR("failed to initialize gem object\n");
- kfree(exynos_gem_obj);
+ kfree(exynos_gem);
return ERR_PTR(ret);
}
ret = drm_gem_create_mmap_offset(obj);
if (ret < 0) {
drm_gem_object_release(obj);
- kfree(exynos_gem_obj);
+ kfree(exynos_gem);
return ERR_PTR(ret);
}
DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
- return exynos_gem_obj;
+ return exynos_gem;
}
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
- unsigned int flags,
- unsigned long size)
+struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev,
+ unsigned int flags,
+ unsigned long size)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
int ret;
if (flags & ~(EXYNOS_BO_MASK)) {
@@ -230,38 +241,38 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
size = roundup(size, PAGE_SIZE);
- exynos_gem_obj = exynos_drm_gem_init(dev, size);
- if (IS_ERR(exynos_gem_obj))
- return exynos_gem_obj;
+ exynos_gem = exynos_drm_gem_init(dev, size);
+ if (IS_ERR(exynos_gem))
+ return exynos_gem;
/* set memory type and cache attribute from user side. */
- exynos_gem_obj->flags = flags;
+ exynos_gem->flags = flags;
- ret = exynos_drm_alloc_buf(exynos_gem_obj);
+ ret = exynos_drm_alloc_buf(exynos_gem);
if (ret < 0) {
- drm_gem_object_release(&exynos_gem_obj->base);
- kfree(exynos_gem_obj);
+ drm_gem_object_release(&exynos_gem->base);
+ kfree(exynos_gem);
return ERR_PTR(ret);
}
- return exynos_gem_obj;
+ return exynos_gem;
}
int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_exynos_gem_create *args = data;
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
int ret;
- exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
- if (IS_ERR(exynos_gem_obj))
- return PTR_ERR(exynos_gem_obj);
+ exynos_gem = exynos_drm_gem_create(dev, args->flags, args->size);
+ if (IS_ERR(exynos_gem))
+ return PTR_ERR(exynos_gem);
- ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
- &args->handle);
+ ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
+ &args->handle);
if (ret) {
- exynos_drm_gem_destroy(exynos_gem_obj);
+ exynos_drm_gem_destroy(exynos_gem);
return ret;
}
@@ -272,7 +283,7 @@ dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
unsigned int gem_handle,
struct drm_file *filp)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
struct drm_gem_object *obj;
obj = drm_gem_object_lookup(dev, filp, gem_handle);
@@ -281,9 +292,9 @@ dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
return ERR_PTR(-EINVAL);
}
- exynos_gem_obj = to_exynos_gem_obj(obj);
+ exynos_gem = to_exynos_gem(obj);
- return &exynos_gem_obj->dma_addr;
+ return &exynos_gem->dma_addr;
}
void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
@@ -307,10 +318,10 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
drm_gem_object_unreference_unlocked(obj);
}
-static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
+static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
struct vm_area_struct *vma)
{
- struct drm_device *drm_dev = exynos_gem_obj->base.dev;
+ struct drm_device *drm_dev = exynos_gem->base.dev;
unsigned long vm_size;
int ret;
@@ -320,12 +331,12 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
vm_size = vma->vm_end - vma->vm_start;
/* check if user-requested size is valid. */
- if (vm_size > exynos_gem_obj->size)
+ if (vm_size > exynos_gem->size)
return -EINVAL;
- ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem_obj->pages,
- exynos_gem_obj->dma_addr, exynos_gem_obj->size,
- &exynos_gem_obj->dma_attrs);
+ ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->pages,
+ exynos_gem->dma_addr, exynos_gem->size,
+ &exynos_gem->dma_attrs);
if (ret < 0) {
DRM_ERROR("failed to mmap.\n");
return ret;
@@ -337,7 +348,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
struct drm_exynos_gem_info *args = data;
struct drm_gem_object *obj;
@@ -350,10 +361,10 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- exynos_gem_obj = to_exynos_gem_obj(obj);
+ exynos_gem = to_exynos_gem(obj);
- args->flags = exynos_gem_obj->flags;
- args->size = exynos_gem_obj->size;
+ args->flags = exynos_gem->flags;
+ args->size = exynos_gem->size;
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
@@ -389,14 +400,14 @@ void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
void exynos_drm_gem_free_object(struct drm_gem_object *obj)
{
- exynos_drm_gem_destroy(to_exynos_gem_obj(obj));
+ exynos_drm_gem_destroy(to_exynos_gem(obj));
}
int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
struct drm_mode_create_dumb *args)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
unsigned int flags;
int ret;
@@ -414,16 +425,16 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
else
flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
- exynos_gem_obj = exynos_drm_gem_create(dev, flags, args->size);
- if (IS_ERR(exynos_gem_obj)) {
+ exynos_gem = exynos_drm_gem_create(dev, flags, args->size);
+ if (IS_ERR(exynos_gem)) {
dev_warn(dev->dev, "FB allocation failed.\n");
- return PTR_ERR(exynos_gem_obj);
+ return PTR_ERR(exynos_gem);
}
- ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
- &args->handle);
+ ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
+ &args->handle);
if (ret) {
- exynos_drm_gem_destroy(exynos_gem_obj);
+ exynos_drm_gem_destroy(exynos_gem);
return ret;
}
@@ -464,7 +475,7 @@ unlock:
int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct drm_gem_object *obj = vma->vm_private_data;
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+ struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
unsigned long pfn;
pgoff_t page_offset;
int ret;
@@ -472,13 +483,13 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
page_offset = ((unsigned long)vmf->virtual_address -
vma->vm_start) >> PAGE_SHIFT;
- if (page_offset >= (exynos_gem_obj->size >> PAGE_SHIFT)) {
+ if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) {
DRM_ERROR("invalid page offset\n");
ret = -EINVAL;
goto out;
}
- pfn = page_to_pfn(exynos_gem_obj->pages[page_offset]);
+ pfn = page_to_pfn(exynos_gem->pages[page_offset]);
ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
out:
@@ -496,7 +507,7 @@ out:
int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
struct drm_gem_object *obj;
int ret;
@@ -508,21 +519,21 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
}
obj = vma->vm_private_data;
- exynos_gem_obj = to_exynos_gem_obj(obj);
+ exynos_gem = to_exynos_gem(obj);
- DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem_obj->flags);
+ DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags);
/* non-cachable as default. */
- if (exynos_gem_obj->flags & EXYNOS_BO_CACHABLE)
+ if (exynos_gem->flags & EXYNOS_BO_CACHABLE)
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- else if (exynos_gem_obj->flags & EXYNOS_BO_WC)
+ else if (exynos_gem->flags & EXYNOS_BO_WC)
vma->vm_page_prot =
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
else
vma->vm_page_prot =
pgprot_noncached(vm_get_page_prot(vma->vm_flags));
- ret = exynos_drm_gem_mmap_buffer(exynos_gem_obj, vma);
+ ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma);
if (ret)
goto err_close_vm;
@@ -537,12 +548,12 @@ err_close_vm:
/* low-level interface prime helpers */
struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+ struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
int npages;
- npages = exynos_gem_obj->size >> PAGE_SHIFT;
+ npages = exynos_gem->size >> PAGE_SHIFT;
- return drm_prime_pages_to_sg(exynos_gem_obj->pages, npages);
+ return drm_prime_pages_to_sg(exynos_gem->pages, npages);
}
struct drm_gem_object *
@@ -550,35 +561,35 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach,
struct sg_table *sgt)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_gem *exynos_gem;
int npages;
int ret;
- exynos_gem_obj = exynos_drm_gem_init(dev, attach->dmabuf->size);
- if (IS_ERR(exynos_gem_obj)) {
- ret = PTR_ERR(exynos_gem_obj);
+ exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size);
+ if (IS_ERR(exynos_gem)) {
+ ret = PTR_ERR(exynos_gem);
return ERR_PTR(ret);
}
- exynos_gem_obj->dma_addr = sg_dma_address(sgt->sgl);
+ exynos_gem->dma_addr = sg_dma_address(sgt->sgl);
- npages = exynos_gem_obj->size >> PAGE_SHIFT;
- exynos_gem_obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
- if (!exynos_gem_obj->pages) {
+ npages = exynos_gem->size >> PAGE_SHIFT;
+ exynos_gem->pages = drm_malloc_ab(npages, sizeof(struct page *));
+ if (!exynos_gem->pages) {
ret = -ENOMEM;
goto err;
}
- ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem_obj->pages, NULL,
- npages);
+ ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem->pages, NULL,
+ npages);
if (ret < 0)
goto err_free_large;
- exynos_gem_obj->sgt = sgt;
+ exynos_gem->sgt = sgt;
if (sgt->nents == 1) {
/* always physically continuous memory if sgt->nents is 1. */
- exynos_gem_obj->flags |= EXYNOS_BO_CONTIG;
+ exynos_gem->flags |= EXYNOS_BO_CONTIG;
} else {
/*
* this case could be CONTIG or NONCONTIG type but for now
@@ -586,16 +597,16 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
* TODO. we have to find a way that exporter can notify
* the type of its own buffer to importer.
*/
- exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG;
+ exynos_gem->flags |= EXYNOS_BO_NONCONTIG;
}
- return &exynos_gem_obj->base;
+ return &exynos_gem->base;
err_free_large:
- drm_free_large(exynos_gem_obj->pages);
+ drm_free_large(exynos_gem->pages);
err:
- drm_gem_object_release(&exynos_gem_obj->base);
- kfree(exynos_gem_obj);
+ drm_gem_object_release(&exynos_gem->base);
+ kfree(exynos_gem);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index b62d1007c0e0..37ab8b282db6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -14,8 +14,7 @@
#include <drm/drm_gem.h>
-#define to_exynos_gem_obj(x) container_of(x,\
- struct exynos_drm_gem_obj, base)
+#define to_exynos_gem(x) container_of(x, struct exynos_drm_gem, base)
#define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG)
@@ -44,7 +43,7 @@
* P.S. this object would be transferred to user as kms_bo.handle so
* user can access the buffer through kms_bo.handle.
*/
-struct exynos_drm_gem_obj {
+struct exynos_drm_gem {
struct drm_gem_object base;
unsigned int flags;
unsigned long size;
@@ -59,12 +58,12 @@ struct exynos_drm_gem_obj {
struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
/* destroy a buffer with gem object */
-void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
+void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem);
/* create a new buffer with gem object */
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
- unsigned int flags,
- unsigned long size);
+struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev,
+ unsigned int flags,
+ unsigned long size);
/*
* request gem object creation and buffer allocation as the size
@@ -106,7 +105,7 @@ unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
struct drm_file *file_priv);
/* free gem object. */
-void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj);
+void exynos_drm_gem_free_object(struct drm_gem_object *obj);
/* create memory region for drm framebuffer. */
int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 808a0a013780..11b87d2a7913 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -543,7 +543,7 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt)
GSC_IN_YUV420_2P);
break;
default:
- dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
+ dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
return -EINVAL;
}
@@ -595,7 +595,7 @@ static int gsc_src_set_transf(struct device *dev,
cfg &= ~GSC_IN_ROT_YFLIP;
break;
default:
- dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
return -EINVAL;
}
@@ -721,7 +721,7 @@ static int gsc_src_set_addr(struct device *dev,
property->prop_id, buf_id, buf_type);
if (buf_id > GSC_MAX_SRC) {
- dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
return -EINVAL;
}
@@ -814,7 +814,7 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt)
GSC_OUT_YUV420_2P);
break;
default:
- dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
+ dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
return -EINVAL;
}
@@ -866,7 +866,7 @@ static int gsc_dst_set_transf(struct device *dev,
cfg &= ~GSC_IN_ROT_YFLIP;
break;
default:
- dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
+ dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
return -EINVAL;
}
@@ -1176,7 +1176,7 @@ static int gsc_dst_set_addr(struct device *dev,
property->prop_id, buf_id, buf_type);
if (buf_id > GSC_MAX_DST) {
- dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
+ dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index 055e8ec2ef21..d73b9ad35b7a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -139,6 +139,5 @@ void drm_iommu_detach_device(struct drm_device *drm_dev,
if (!mapping || !mapping->domain)
return;
- iommu_detach_device(mapping->domain, subdrv_dev);
- drm_release_iommu_mapping(drm_dev);
+ arm_iommu_detach_device(subdrv_dev);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 714822441467..179311760bb7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -128,15 +128,14 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
nr = drm_format_num_planes(state->fb->pixel_format);
for (i = 0; i < nr; i++) {
- struct exynos_drm_gem_obj *obj =
- exynos_drm_fb_gem_obj(state->fb, i);
-
- if (!obj) {
+ struct exynos_drm_gem *exynos_gem =
+ exynos_drm_fb_gem(state->fb, i);
+ if (!exynos_gem) {
DRM_DEBUG_KMS("gem object is null\n");
return -EFAULT;
}
- exynos_plane->dma_addr[i] = obj->dma_addr +
+ exynos_plane->dma_addr[i] = exynos_gem->dma_addr +
state->fb->offsets[i];
DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
@@ -208,6 +207,17 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
drm_object_attach_property(&plane->base, prop, zpos);
}
+enum drm_plane_type exynos_plane_get_type(unsigned int zpos,
+ unsigned int cursor_win)
+{
+ if (zpos == DEFAULT_WIN)
+ return DRM_PLANE_TYPE_PRIMARY;
+ else if (zpos == cursor_win)
+ return DRM_PLANE_TYPE_CURSOR;
+ else
+ return DRM_PLANE_TYPE_OVERLAY;
+}
+
int exynos_plane_init(struct drm_device *dev,
struct exynos_drm_plane *exynos_plane,
unsigned long possible_crtcs, enum drm_plane_type type,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 476c9340b591..abb641e64c23 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -9,6 +9,8 @@
*
*/
+enum drm_plane_type exynos_plane_get_type(unsigned int zpos,
+ unsigned int cursor_win);
int exynos_plane_init(struct drm_device *dev,
struct exynos_drm_plane *exynos_plane,
unsigned long possible_crtcs, enum drm_plane_type type,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 75718e1bc3dd..669362c53f49 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -29,6 +29,7 @@
/* vidi has totally three virtual windows. */
#define WINDOWS_NR 3
+#define CURSOR_WIN 2
#define ctx_from_connector(c) container_of(c, struct vidi_context, \
connector)
@@ -42,7 +43,6 @@ struct vidi_context {
struct exynos_drm_plane planes[WINDOWS_NR];
struct edid *raw_edid;
unsigned int clkdiv;
- unsigned int default_win;
unsigned long irq_flags;
unsigned int connected;
bool vblank_on;
@@ -446,8 +446,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
vidi_ctx_initialize(ctx, drm_dev);
for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
- type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
- DRM_PLANE_TYPE_OVERLAY;
+ type = exynos_plane_get_type(zpos, CURSOR_WIN);
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type, formats,
ARRAY_SIZE(formats), zpos);
@@ -455,7 +454,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
return ret;
}
- exynos_plane = &ctx->planes[ctx->default_win];
+ exynos_plane = &ctx->planes[DEFAULT_WIN];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
&vidi_crtc_ops, ctx);
@@ -507,7 +506,6 @@ static int vidi_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
- ctx->default_win = 0;
ctx->pdev = pdev;
INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 932f7fa240f8..57b675563e94 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -30,11 +30,11 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/hdmi.h>
#include <linux/component.h>
#include <linux/mfd/syscon.h>
@@ -44,11 +44,6 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
-#include "exynos_mixer.h"
-
-#include <linux/gpio.h>
-
-#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
#define HOTPLUG_DEBOUNCE_MS 1100
@@ -66,6 +61,33 @@
enum hdmi_type {
HDMI_TYPE13,
HDMI_TYPE14,
+ HDMI_TYPE_COUNT
+};
+
+#define HDMI_MAPPED_BASE 0xffff0000
+
+enum hdmi_mapped_regs {
+ HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
+ HDMI_PHY_RSTOUT,
+ HDMI_ACR_CON,
+ HDMI_ACR_MCTS0,
+ HDMI_ACR_CTS0,
+ HDMI_ACR_N0
+};
+
+static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
+ { HDMI_V13_PHY_STATUS, HDMI_PHY_STATUS_0 },
+ { HDMI_V13_PHY_RSTOUT, HDMI_V14_PHY_RSTOUT },
+ { HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
+ { HDMI_V13_ACR_MCTS0, HDMI_V14_ACR_MCTS0 },
+ { HDMI_V13_ACR_CTS0, HDMI_V14_ACR_CTS0 },
+ { HDMI_V13_ACR_N0, HDMI_V14_ACR_N0 },
+};
+
+static const char * const supply[] = {
+ "vdd",
+ "vdd_osc",
+ "vdd_pll",
};
struct hdmi_driver_data {
@@ -75,44 +97,32 @@ struct hdmi_driver_data {
unsigned int is_apb_phy:1;
};
-struct hdmi_resources {
- struct clk *hdmi;
- struct clk *sclk_hdmi;
- struct clk *sclk_pixel;
- struct clk *sclk_hdmiphy;
- struct clk *mout_hdmi;
- struct regulator_bulk_data *regul_bulk;
- struct regulator *reg_hdmi_en;
- int regul_count;
-};
-
struct hdmi_context {
struct drm_encoder encoder;
struct device *dev;
struct drm_device *drm_dev;
struct drm_connector connector;
- bool hpd;
bool powered;
bool dvi_mode;
-
- void __iomem *regs;
- int irq;
struct delayed_work hotplug_work;
-
- struct i2c_adapter *ddc_adpt;
- struct i2c_client *hdmiphy_port;
-
- /* current hdmiphy conf regs */
struct drm_display_mode current_mode;
u8 cea_video_id;
-
- struct hdmi_resources res;
const struct hdmi_driver_data *drv_data;
- int hpd_gpio;
+ void __iomem *regs;
void __iomem *regs_hdmiphy;
-
+ struct i2c_client *hdmiphy_port;
+ struct i2c_adapter *ddc_adpt;
+ struct gpio_desc *hpd_gpio;
+ int irq;
struct regmap *pmureg;
+ struct clk *hdmi;
+ struct clk *sclk_hdmi;
+ struct clk *sclk_pixel;
+ struct clk *sclk_hdmiphy;
+ struct clk *mout_hdmi;
+ struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)];
+ struct regulator *reg_hdmi_en;
};
static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
@@ -120,6 +130,11 @@ static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
return container_of(e, struct hdmi_context, encoder);
}
+static inline struct hdmi_context *connector_to_hdmi(struct drm_connector *c)
+{
+ return container_of(c, struct hdmi_context, connector);
+}
+
struct hdmiphy_config {
int pixel_clock;
u8 conf[32];
@@ -133,7 +148,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
},
},
{
@@ -142,7 +157,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
},
},
{
@@ -151,7 +166,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
+ 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80,
},
},
{
@@ -160,7 +175,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
- 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
+ 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80,
},
},
{
@@ -169,7 +184,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
- 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
+ 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80,
},
},
};
@@ -199,7 +214,7 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
},
},
{
@@ -262,7 +277,7 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
+ 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
},
},
{
@@ -325,7 +340,7 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
- 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
+ 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
},
},
};
@@ -507,29 +522,31 @@ static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
.is_apb_phy = 0,
};
-static struct hdmi_driver_data exynos5_hdmi_driver_data = {
- .type = HDMI_TYPE14,
- .phy_confs = hdmiphy_v13_configs,
- .phy_conf_count = ARRAY_SIZE(hdmiphy_v13_configs),
- .is_apb_phy = 0,
-};
+static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
+{
+ if ((reg_id & 0xffff0000) == HDMI_MAPPED_BASE)
+ return hdmi_reg_map[reg_id & 0xffff][hdata->drv_data->type];
+ return reg_id;
+}
static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
{
- return readl(hdata->regs + reg_id);
+ return readl(hdata->regs + hdmi_map_reg(hdata, reg_id));
}
static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
u32 reg_id, u8 value)
{
- writeb(value, hdata->regs + reg_id);
+ writel(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
}
static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
int bytes, u32 val)
{
+ reg_id = hdmi_map_reg(hdata, reg_id);
+
while (--bytes >= 0) {
- writeb(val & 0xff, hdata->regs + reg_id);
+ writel(val & 0xff, hdata->regs + reg_id);
val >>= 8;
reg_id += 4;
}
@@ -538,31 +555,14 @@ static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
u32 reg_id, u32 value, u32 mask)
{
- u32 old = readl(hdata->regs + reg_id);
+ u32 old;
+
+ reg_id = hdmi_map_reg(hdata, reg_id);
+ old = readl(hdata->regs + reg_id);
value = (value & mask) | (old & ~mask);
writel(value, hdata->regs + reg_id);
}
-static int hdmiphy_reg_writeb(struct hdmi_context *hdata,
- u32 reg_offset, u8 value)
-{
- if (hdata->hdmiphy_port) {
- u8 buffer[2];
- int ret;
-
- buffer[0] = reg_offset;
- buffer[1] = value;
-
- ret = i2c_master_send(hdata->hdmiphy_port, buffer, 2);
- if (ret == 2)
- return 0;
- return ret;
- } else {
- writeb(value, hdata->regs_hdmiphy + (reg_offset<<2));
- return 0;
- }
-}
-
static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
u32 reg_offset, const u8 *buf, u32 len)
{
@@ -579,7 +579,7 @@ static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
} else {
int i;
for (i = 0; i < len; i++)
- writeb(buf[i], hdata->regs_hdmiphy +
+ writel(buf[i], hdata->regs_hdmiphy +
((reg_offset + i)<<2));
return 0;
}
@@ -689,7 +689,7 @@ static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
DUMPREG(HDMI_PHY_STATUS_0);
DUMPREG(HDMI_PHY_STATUS_PLL);
DUMPREG(HDMI_PHY_CON_0);
- DUMPREG(HDMI_PHY_RSTOUT);
+ DUMPREG(HDMI_V14_PHY_RSTOUT);
DUMPREG(HDMI_PHY_VPLL);
DUMPREG(HDMI_PHY_CMU);
DUMPREG(HDMI_CORE_RSTOUT);
@@ -942,9 +942,9 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
bool force)
{
- struct hdmi_context *hdata = ctx_from_connector(connector);
+ struct hdmi_context *hdata = connector_to_hdmi(connector);
- if (gpio_get_value(hdata->hpd_gpio))
+ if (gpiod_get_value(hdata->hpd_gpio))
return connector_status_connected;
return connector_status_disconnected;
@@ -968,7 +968,7 @@ static struct drm_connector_funcs hdmi_connector_funcs = {
static int hdmi_get_modes(struct drm_connector *connector)
{
- struct hdmi_context *hdata = ctx_from_connector(connector);
+ struct hdmi_context *hdata = connector_to_hdmi(connector);
struct edid *edid;
int ret;
@@ -1008,7 +1008,7 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
static int hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
- struct hdmi_context *hdata = ctx_from_connector(connector);
+ struct hdmi_context *hdata = connector_to_hdmi(connector);
int ret;
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
@@ -1016,10 +1016,6 @@ static int hdmi_mode_valid(struct drm_connector *connector,
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
false, mode->clock * 1000);
- ret = mixer_check_mode(mode);
- if (ret)
- return MODE_BAD;
-
ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
if (ret < 0)
return MODE_BAD;
@@ -1029,7 +1025,7 @@ static int hdmi_mode_valid(struct drm_connector *connector,
static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
{
- struct hdmi_context *hdata = ctx_from_connector(connector);
+ struct hdmi_context *hdata = connector_to_hdmi(connector);
return &hdata->encoder;
}
@@ -1110,70 +1106,17 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
return true;
}
-static void hdmi_set_acr(u32 freq, u8 *acr)
+static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
{
u32 n, cts;
- switch (freq) {
- case 32000:
- n = 4096;
- cts = 27000;
- break;
- case 44100:
- n = 6272;
- cts = 30000;
- break;
- case 88200:
- n = 12544;
- cts = 30000;
- break;
- case 176400:
- n = 25088;
- cts = 30000;
- break;
- case 48000:
- n = 6144;
- cts = 27000;
- break;
- case 96000:
- n = 12288;
- cts = 27000;
- break;
- case 192000:
- n = 24576;
- cts = 27000;
- break;
- default:
- n = 0;
- cts = 0;
- break;
- }
-
- acr[1] = cts >> 16;
- acr[2] = cts >> 8 & 0xff;
- acr[3] = cts & 0xff;
+ cts = (freq % 9) ? 27000 : 30000;
+ n = 128 * freq / (27000000 / cts);
- acr[4] = n >> 16;
- acr[5] = n >> 8 & 0xff;
- acr[6] = n & 0xff;
-}
-
-static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
-{
- hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
- hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
- hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
- hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
- hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
- hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
- hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
- hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
- hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
-
- if (hdata->drv_data->type == HDMI_TYPE13)
- hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
- else
- hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
+ hdmi_reg_writev(hdata, HDMI_ACR_N0, 3, n);
+ hdmi_reg_writev(hdata, HDMI_ACR_MCTS0, 3, cts);
+ hdmi_reg_writev(hdata, HDMI_ACR_CTS0, 3, cts);
+ hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
}
static void hdmi_audio_init(struct hdmi_context *hdata)
@@ -1181,7 +1124,6 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
u32 sample_rate, bits_per_sample;
u32 data_num, bit_ch, sample_frq;
u32 val;
- u8 acr[7];
sample_rate = 44100;
bits_per_sample = 16;
@@ -1201,8 +1143,7 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
break;
}
- hdmi_set_acr(sample_rate, acr);
- hdmi_reg_acr(hdata, acr);
+ hdmi_reg_acr(hdata, sample_rate);
hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
| HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
@@ -1335,11 +1276,27 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
}
}
+static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
+{
+ int tries;
+
+ for (tries = 0; tries < 10; ++tries) {
+ u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
+
+ if (val & HDMI_PHY_STATUS_READY) {
+ DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
+ return;
+ }
+ usleep_range(10, 20);
+ }
+
+ DRM_ERROR("PLL could not reach steady state\n");
+}
+
static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
{
struct drm_display_mode *m = &hdata->current_mode;
unsigned int val;
- int tries;
hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
@@ -1425,32 +1382,11 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
-
- /* waiting for HDMIPHY's PLL to get to steady state */
- for (tries = 100; tries; --tries) {
- u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
- if (val & HDMI_PHY_STATUS_READY)
- break;
- usleep_range(1000, 2000);
- }
- /* steady state not achieved */
- if (tries == 0) {
- DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
- hdmi_regs_dump(hdata, "timing apply");
- }
-
- clk_disable_unprepare(hdata->res.sclk_hdmi);
- clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
- clk_prepare_enable(hdata->res.sclk_hdmi);
-
- /* enable HDMI and timing generator */
- hdmi_start(hdata, true);
}
static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
{
struct drm_display_mode *m = &hdata->current_mode;
- int tries;
hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
@@ -1562,26 +1498,6 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
hdmi_reg_writev(hdata, HDMI_TG_3D, 1, 0x0);
-
- /* waiting for HDMIPHY's PLL to get to steady state */
- for (tries = 100; tries; --tries) {
- u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
- if (val & HDMI_PHY_STATUS_READY)
- break;
- usleep_range(1000, 2000);
- }
- /* steady state not achieved */
- if (tries == 0) {
- DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
- hdmi_regs_dump(hdata, "timing apply");
- }
-
- clk_disable_unprepare(hdata->res.sclk_hdmi);
- clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
- clk_prepare_enable(hdata->res.sclk_hdmi);
-
- /* enable HDMI and timing generator */
- hdmi_start(hdata, true);
}
static void hdmi_mode_apply(struct hdmi_context *hdata)
@@ -1590,74 +1506,26 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)
hdmi_v13_mode_apply(hdata);
else
hdmi_v14_mode_apply(hdata);
-}
-static void hdmiphy_conf_reset(struct hdmi_context *hdata)
-{
- u32 reg;
+ hdmiphy_wait_for_pll(hdata);
- clk_disable_unprepare(hdata->res.sclk_hdmi);
- clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
- clk_prepare_enable(hdata->res.sclk_hdmi);
+ clk_set_parent(hdata->mout_hdmi, hdata->sclk_hdmiphy);
- /* operation mode */
- hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
- HDMI_PHY_ENABLE_MODE_SET);
+ /* enable HDMI and timing generator */
+ hdmi_start(hdata, true);
+}
- if (hdata->drv_data->type == HDMI_TYPE13)
- reg = HDMI_V13_PHY_RSTOUT;
- else
- reg = HDMI_PHY_RSTOUT;
+static void hdmiphy_conf_reset(struct hdmi_context *hdata)
+{
+ clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel);
/* reset hdmiphy */
- hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
+ hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
usleep_range(10000, 12000);
- hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
+ hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
usleep_range(10000, 12000);
}
-static void hdmiphy_poweron(struct hdmi_context *hdata)
-{
- if (hdata->drv_data->type != HDMI_TYPE14)
- return;
-
- DRM_DEBUG_KMS("\n");
-
- /* For PHY Mode Setting */
- hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
- HDMI_PHY_ENABLE_MODE_SET);
- /* Phy Power On */
- hdmiphy_reg_writeb(hdata, HDMIPHY_POWER,
- HDMI_PHY_POWER_ON);
- /* For PHY Mode Setting */
- hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
- HDMI_PHY_DISABLE_MODE_SET);
- /* PHY SW Reset */
- hdmiphy_conf_reset(hdata);
-}
-
-static void hdmiphy_poweroff(struct hdmi_context *hdata)
-{
- if (hdata->drv_data->type != HDMI_TYPE14)
- return;
-
- DRM_DEBUG_KMS("\n");
-
- /* PHY SW Reset */
- hdmiphy_conf_reset(hdata);
- /* For PHY Mode Setting */
- hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
- HDMI_PHY_ENABLE_MODE_SET);
-
- /* PHY Power Off */
- hdmiphy_reg_writeb(hdata, HDMIPHY_POWER,
- HDMI_PHY_POWER_OFF);
-
- /* For PHY Mode Setting */
- hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
- HDMI_PHY_DISABLE_MODE_SET);
-}
-
static void hdmiphy_conf_apply(struct hdmi_context *hdata)
{
int ret;
@@ -1678,14 +1546,6 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
}
usleep_range(10000, 12000);
-
- ret = hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
- HDMI_PHY_DISABLE_MODE_SET);
- if (ret) {
- DRM_ERROR("failed to enable hdmiphy\n");
- return;
- }
-
}
static void hdmi_conf_apply(struct hdmi_context *hdata)
@@ -1724,7 +1584,6 @@ static void hdmi_mode_set(struct drm_encoder *encoder,
static void hdmi_enable(struct drm_encoder *encoder)
{
struct hdmi_context *hdata = encoder_to_hdmi(encoder);
- struct hdmi_resources *res = &hdata->res;
if (hdata->powered)
return;
@@ -1733,24 +1592,22 @@ static void hdmi_enable(struct drm_encoder *encoder)
pm_runtime_get_sync(hdata->dev);
- if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
+ if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
DRM_DEBUG_KMS("failed to enable regulator bulk\n");
/* set pmu hdmiphy control bit to enable hdmiphy */
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
PMU_HDMI_PHY_ENABLE_BIT, 1);
- clk_prepare_enable(res->hdmi);
- clk_prepare_enable(res->sclk_hdmi);
+ clk_prepare_enable(hdata->hdmi);
+ clk_prepare_enable(hdata->sclk_hdmi);
- hdmiphy_poweron(hdata);
hdmi_conf_apply(hdata);
}
static void hdmi_disable(struct drm_encoder *encoder)
{
struct hdmi_context *hdata = encoder_to_hdmi(encoder);
- struct hdmi_resources *res = &hdata->res;
struct drm_crtc *crtc = encoder->crtc;
const struct drm_crtc_helper_funcs *funcs = NULL;
@@ -1774,18 +1631,16 @@ static void hdmi_disable(struct drm_encoder *encoder)
/* HDMI System Disable */
hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
- hdmiphy_poweroff(hdata);
-
cancel_delayed_work(&hdata->hotplug_work);
- clk_disable_unprepare(res->sclk_hdmi);
- clk_disable_unprepare(res->hdmi);
+ clk_disable_unprepare(hdata->sclk_hdmi);
+ clk_disable_unprepare(hdata->hdmi);
/* reset pmu hdmiphy control bit to disable hdmiphy */
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
PMU_HDMI_PHY_ENABLE_BIT, 0);
- regulator_bulk_disable(res->regul_count, res->regul_bulk);
+ regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
pm_runtime_put_sync(hdata->dev);
@@ -1826,80 +1681,76 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
static int hdmi_resources_init(struct hdmi_context *hdata)
{
struct device *dev = hdata->dev;
- struct hdmi_resources *res = &hdata->res;
- static char *supply[] = {
- "vdd",
- "vdd_osc",
- "vdd_pll",
- };
int i, ret;
DRM_DEBUG_KMS("HDMI resource init\n");
+ hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
+ if (IS_ERR(hdata->hpd_gpio)) {
+ DRM_ERROR("cannot get hpd gpio property\n");
+ return PTR_ERR(hdata->hpd_gpio);
+ }
+
+ hdata->irq = gpiod_to_irq(hdata->hpd_gpio);
+ if (hdata->irq < 0) {
+ DRM_ERROR("failed to get GPIO irq\n");
+ return hdata->irq;
+ }
/* get clocks, power */
- res->hdmi = devm_clk_get(dev, "hdmi");
- if (IS_ERR(res->hdmi)) {
+ hdata->hdmi = devm_clk_get(dev, "hdmi");
+ if (IS_ERR(hdata->hdmi)) {
DRM_ERROR("failed to get clock 'hdmi'\n");
- ret = PTR_ERR(res->hdmi);
+ ret = PTR_ERR(hdata->hdmi);
goto fail;
}
- res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
- if (IS_ERR(res->sclk_hdmi)) {
+ hdata->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
+ if (IS_ERR(hdata->sclk_hdmi)) {
DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
- ret = PTR_ERR(res->sclk_hdmi);
+ ret = PTR_ERR(hdata->sclk_hdmi);
goto fail;
}
- res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
- if (IS_ERR(res->sclk_pixel)) {
+ hdata->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
+ if (IS_ERR(hdata->sclk_pixel)) {
DRM_ERROR("failed to get clock 'sclk_pixel'\n");
- ret = PTR_ERR(res->sclk_pixel);
+ ret = PTR_ERR(hdata->sclk_pixel);
goto fail;
}
- res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
- if (IS_ERR(res->sclk_hdmiphy)) {
+ hdata->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
+ if (IS_ERR(hdata->sclk_hdmiphy)) {
DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
- ret = PTR_ERR(res->sclk_hdmiphy);
+ ret = PTR_ERR(hdata->sclk_hdmiphy);
goto fail;
}
- res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
- if (IS_ERR(res->mout_hdmi)) {
+ hdata->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
+ if (IS_ERR(hdata->mout_hdmi)) {
DRM_ERROR("failed to get clock 'mout_hdmi'\n");
- ret = PTR_ERR(res->mout_hdmi);
+ ret = PTR_ERR(hdata->mout_hdmi);
goto fail;
}
- clk_set_parent(res->mout_hdmi, res->sclk_pixel);
+ clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel);
- res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
- sizeof(res->regul_bulk[0]), GFP_KERNEL);
- if (!res->regul_bulk) {
- ret = -ENOMEM;
- goto fail;
- }
for (i = 0; i < ARRAY_SIZE(supply); ++i) {
- res->regul_bulk[i].supply = supply[i];
- res->regul_bulk[i].consumer = NULL;
+ hdata->regul_bulk[i].supply = supply[i];
+ hdata->regul_bulk[i].consumer = NULL;
}
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk);
if (ret) {
DRM_ERROR("failed to get regulators\n");
return ret;
}
- res->regul_count = ARRAY_SIZE(supply);
- res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
- if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
- DRM_ERROR("failed to get hdmi-en regulator\n");
- return PTR_ERR(res->reg_hdmi_en);
- }
- if (!IS_ERR(res->reg_hdmi_en)) {
- ret = regulator_enable(res->reg_hdmi_en);
- if (ret) {
- DRM_ERROR("failed to enable hdmi-en regulator\n");
- return ret;
- }
- } else
- res->reg_hdmi_en = NULL;
+ hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
+
+ if (PTR_ERR(hdata->reg_hdmi_en) == -ENODEV)
+ return 0;
+
+ if (IS_ERR(hdata->reg_hdmi_en))
+ return PTR_ERR(hdata->reg_hdmi_en);
+
+ ret = regulator_enable(hdata->reg_hdmi_en);
+ if (ret)
+ DRM_ERROR("failed to enable hdmi-en regulator\n");
return ret;
fail:
@@ -1909,9 +1760,6 @@ fail:
static struct of_device_id hdmi_match_types[] = {
{
- .compatible = "samsung,exynos5-hdmi",
- .data = &exynos5_hdmi_driver_data,
- }, {
.compatible = "samsung,exynos4210-hdmi",
.data = &exynos4210_hdmi_driver_data,
}, {
@@ -2009,11 +1857,6 @@ static int hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdata);
hdata->dev = dev;
- hdata->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpio", 0);
- if (hdata->hpd_gpio < 0) {
- DRM_ERROR("cannot get hpd gpio property\n");
- return hdata->hpd_gpio;
- }
ret = hdmi_resources_init(hdata);
if (ret) {
@@ -2028,12 +1871,6 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}
- ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
- if (ret) {
- DRM_ERROR("failed to request HPD gpio\n");
- return ret;
- }
-
ddc_node = hdmi_legacy_ddc_dt_binding(dev);
if (ddc_node)
goto out_get_ddc_adpt;
@@ -2081,13 +1918,6 @@ out_get_phy_port:
}
}
- hdata->irq = gpio_to_irq(hdata->hpd_gpio);
- if (hdata->irq < 0) {
- DRM_ERROR("failed to get GPIO irq\n");
- ret = hdata->irq;
- goto err_hdmiphy;
- }
-
INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
@@ -2133,15 +1963,17 @@ static int hdmi_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&hdata->hotplug_work);
- if (hdata->res.reg_hdmi_en)
- regulator_disable(hdata->res.reg_hdmi_en);
+ component_del(&pdev->dev, &hdmi_component_ops);
+
+ pm_runtime_disable(&pdev->dev);
+
+ if (!IS_ERR(hdata->reg_hdmi_en))
+ regulator_disable(hdata->reg_hdmi_en);
if (hdata->hdmiphy_port)
put_device(&hdata->hdmiphy_port->dev);
- put_device(&hdata->ddc_adpt->dev);
- pm_runtime_disable(&pdev->dev);
- component_del(&pdev->dev, &hdmi_component_ops);
+ put_device(&hdata->ddc_adpt->dev);
return 0;
}
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7f81cce966d4..d09f8f9a8939 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -39,11 +39,10 @@
#include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_iommu.h"
-#include "exynos_mixer.h"
#define MIXER_WIN_NR 3
-#define MIXER_DEFAULT_WIN 0
#define VP_DEFAULT_WIN 2
+#define CURSOR_WIN 1
/* The pixelformats that are natively supported by the mixer. */
#define MXR_FORMAT_RGB565 4
@@ -600,7 +599,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
/* setup display size */
if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
- win == MIXER_DEFAULT_WIN) {
+ win == DEFAULT_WIN) {
val = MXR_MXR_RES_HEIGHT(mode->vdisplay);
val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
mixer_reg_write(res, MXR_RESOLUTION, val);
@@ -652,7 +651,7 @@ static void vp_win_reset(struct mixer_context *ctx)
/* waiting until VP_SRESET_PROCESSING is 0 */
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
break;
- usleep_range(10000, 12000);
+ mdelay(10);
}
WARN(tries == 0, "failed to reset Video Processor\n");
}
@@ -1096,8 +1095,10 @@ static void mixer_disable(struct exynos_drm_crtc *crtc)
}
/* Only valid for Mixer version 16.0.33.0 */
-int mixer_check_mode(struct drm_display_mode *mode)
+static int mixer_atomic_check(struct exynos_drm_crtc *crtc,
+ struct drm_crtc_state *state)
{
+ struct drm_display_mode *mode = &state->adjusted_mode;
u32 w, h;
w = mode->hdisplay;
@@ -1123,6 +1124,7 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
.wait_for_vblank = mixer_wait_for_vblank,
.update_plane = mixer_update_plane,
.disable_plane = mixer_disable_plane,
+ .atomic_check = mixer_atomic_check,
};
static struct mixer_drv_data exynos5420_mxr_drv_data = {
@@ -1197,8 +1199,6 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
const uint32_t *formats;
unsigned int fcount;
- type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
- DRM_PLANE_TYPE_OVERLAY;
if (zpos < VP_DEFAULT_WIN) {
formats = mixer_formats;
fcount = ARRAY_SIZE(mixer_formats);
@@ -1207,6 +1207,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
fcount = ARRAY_SIZE(vp_formats);
}
+ type = exynos_plane_get_type(zpos, CURSOR_WIN);
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type, formats, fcount,
zpos);
@@ -1214,7 +1215,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
return ret;
}
- exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
+ exynos_plane = &ctx->planes[DEFAULT_WIN];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
&mixer_crtc_ops, ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.h b/drivers/gpu/drm/exynos/exynos_mixer.h
deleted file mode 100644
index 3811e417f0e9..000000000000
--- a/drivers/gpu/drm/exynos/exynos_mixer.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 Google, 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.
- */
-
-#ifndef _EXYNOS_MIXER_H_
-#define _EXYNOS_MIXER_H_
-
-/* This function returns 0 if the given timing is valid for the mixer */
-int mixer_check_mode(struct drm_display_mode *mode);
-
-#endif
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h
index 3f35ac6d8a47..8c891e59be21 100644
--- a/drivers/gpu/drm/exynos/regs-hdmi.h
+++ b/drivers/gpu/drm/exynos/regs-hdmi.h
@@ -72,7 +72,6 @@
#define HDMI_V13_V_SYNC_GEN_3_0 HDMI_CORE_BASE(0x0150)
#define HDMI_V13_V_SYNC_GEN_3_1 HDMI_CORE_BASE(0x0154)
#define HDMI_V13_V_SYNC_GEN_3_2 HDMI_CORE_BASE(0x0158)
-#define HDMI_V13_ACR_CON HDMI_CORE_BASE(0x0180)
#define HDMI_V13_AVI_CON HDMI_CORE_BASE(0x0300)
#define HDMI_V13_AVI_BYTE(n) HDMI_CORE_BASE(0x0320 + 4 * (n))
#define HDMI_V13_DC_CONTROL HDMI_CORE_BASE(0x05C0)
@@ -171,7 +170,7 @@
#define HDMI_HPD_ST HDMI_CTRL_BASE(0x0044)
#define HDMI_HPD_TH_X HDMI_CTRL_BASE(0x0050)
#define HDMI_AUDIO_CLKSEL HDMI_CTRL_BASE(0x0070)
-#define HDMI_PHY_RSTOUT HDMI_CTRL_BASE(0x0074)
+#define HDMI_V14_PHY_RSTOUT HDMI_CTRL_BASE(0x0074)
#define HDMI_PHY_VPLL HDMI_CTRL_BASE(0x0078)
#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x007C)
#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0080)
@@ -277,16 +276,26 @@
#define HDMI_ASP_CHCFG2 HDMI_CORE_BASE(0x0318)
#define HDMI_ASP_CHCFG3 HDMI_CORE_BASE(0x031C)
-#define HDMI_ACR_CON HDMI_CORE_BASE(0x0400)
-#define HDMI_ACR_MCTS0 HDMI_CORE_BASE(0x0410)
-#define HDMI_ACR_MCTS1 HDMI_CORE_BASE(0x0414)
-#define HDMI_ACR_MCTS2 HDMI_CORE_BASE(0x0418)
-#define HDMI_ACR_CTS0 HDMI_CORE_BASE(0x0420)
-#define HDMI_ACR_CTS1 HDMI_CORE_BASE(0x0424)
-#define HDMI_ACR_CTS2 HDMI_CORE_BASE(0x0428)
-#define HDMI_ACR_N0 HDMI_CORE_BASE(0x0430)
-#define HDMI_ACR_N1 HDMI_CORE_BASE(0x0434)
-#define HDMI_ACR_N2 HDMI_CORE_BASE(0x0438)
+#define HDMI_V13_ACR_CON HDMI_CORE_BASE(0x0180)
+#define HDMI_V13_ACR_MCTS0 HDMI_CORE_BASE(0x0184)
+#define HDMI_V13_ACR_MCTS1 HDMI_CORE_BASE(0x0188)
+#define HDMI_V13_ACR_MCTS2 HDMI_CORE_BASE(0x018C)
+#define HDMI_V13_ACR_CTS0 HDMI_CORE_BASE(0x0190)
+#define HDMI_V13_ACR_CTS1 HDMI_CORE_BASE(0x0194)
+#define HDMI_V13_ACR_CTS2 HDMI_CORE_BASE(0x0198)
+#define HDMI_V13_ACR_N0 HDMI_CORE_BASE(0x01A0)
+#define HDMI_V13_ACR_N1 HDMI_CORE_BASE(0x01A4)
+#define HDMI_V13_ACR_N2 HDMI_CORE_BASE(0x01A8)
+#define HDMI_V14_ACR_CON HDMI_CORE_BASE(0x0400)
+#define HDMI_V14_ACR_MCTS0 HDMI_CORE_BASE(0x0410)
+#define HDMI_V14_ACR_MCTS1 HDMI_CORE_BASE(0x0414)
+#define HDMI_V14_ACR_MCTS2 HDMI_CORE_BASE(0x0418)
+#define HDMI_V14_ACR_CTS0 HDMI_CORE_BASE(0x0420)
+#define HDMI_V14_ACR_CTS1 HDMI_CORE_BASE(0x0424)
+#define HDMI_V14_ACR_CTS2 HDMI_CORE_BASE(0x0428)
+#define HDMI_V14_ACR_N0 HDMI_CORE_BASE(0x0430)
+#define HDMI_V14_ACR_N1 HDMI_CORE_BASE(0x0434)
+#define HDMI_V14_ACR_N2 HDMI_CORE_BASE(0x0438)
/* Packet related registers */
#define HDMI_ACP_CON HDMI_CORE_BASE(0x0500)
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index 9a8e2da47158..1930234ba5f1 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -140,7 +140,7 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
return IRQ_HANDLED;
}
-static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
+static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
unsigned int value;
@@ -156,7 +156,8 @@ static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
+static void fsl_dcu_drm_disable_vblank(struct drm_device *dev,
+ unsigned int pipe)
{
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
unsigned int value;
@@ -192,7 +193,7 @@ static struct drm_driver fsl_dcu_drm_driver = {
.unload = fsl_dcu_unload,
.preclose = fsl_dcu_drm_preclose,
.irq_handler = fsl_dcu_drm_irq,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = fsl_dcu_drm_enable_vblank,
.disable_vblank = fsl_dcu_drm_disable_vblank,
.gem_free_object = drm_gem_cma_free_object,
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index d1e300dcd544..51daaea40b4d 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -191,14 +191,12 @@ set_failed:
static void
fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
}
static int
fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
return 0;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 0fafb8e2483a..17cea400ae32 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -247,7 +247,6 @@ i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
#define wait_for(COND, MS) _wait_for(COND, MS, 1)
-#define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000)
#define DP_LINK_CONFIGURATION_SIZE 9
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index e38057b91865..e21726ecac32 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -687,15 +687,15 @@ extern void psb_irq_turn_off_dpst(struct drm_device *dev);
extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int psb_enable_vblank(struct drm_device *dev, int crtc);
-extern void psb_disable_vblank(struct drm_device *dev, int crtc);
+extern int psb_enable_vblank(struct drm_device *dev, unsigned int pipe);
+extern void psb_disable_vblank(struct drm_device *dev, unsigned int pipe);
void
psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
void
psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
+extern u32 psb_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
/* framebuffer.c */
extern int psbfb_probed(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 624eb36511c5..78eb10902809 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -510,7 +510,7 @@ int psb_irq_disable_dpst(struct drm_device *dev)
/*
* It is used to enable VBLANK interrupt
*/
-int psb_enable_vblank(struct drm_device *dev, int pipe)
+int psb_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_psb_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -549,7 +549,7 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
/*
* It is used to disable VBLANK interrupt
*/
-void psb_disable_vblank(struct drm_device *dev, int pipe)
+void psb_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_psb_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -622,7 +622,7 @@ void mdfld_disable_te(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed a 'crtc', which
* we use as a pipe index
*/
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
+u32 psb_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
uint32_t high_frame = PIPEAFRAMEHIGH;
uint32_t low_frame = PIPEAFRAMEPIXEL;
@@ -654,7 +654,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
reg_val = REG_READ(pipeconf_reg);
if (!(reg_val & PIPEACONF_ENABLE)) {
- dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
+ dev_err(dev->dev, "trying to get vblank count for disabled pipe %u\n",
pipe);
goto psb_get_vblank_counter_exit;
}
diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h
index d0b45ffa1126..e6a81a8c9f35 100644
--- a/drivers/gpu/drm/gma500/psb_irq.h
+++ b/drivers/gpu/drm/gma500/psb_irq.h
@@ -38,9 +38,9 @@ int psb_irq_enable_dpst(struct drm_device *dev);
int psb_irq_disable_dpst(struct drm_device *dev);
void psb_irq_turn_on_dpst(struct drm_device *dev);
void psb_irq_turn_off_dpst(struct drm_device *dev);
-int psb_enable_vblank(struct drm_device *dev, int pipe);
-void psb_disable_vblank(struct drm_device *dev, int pipe);
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
+int psb_enable_vblank(struct drm_device *dev, unsigned int pipe);
+void psb_disable_vblank(struct drm_device *dev, unsigned int pipe);
+u32 psb_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
int mdfld_enable_te(struct drm_device *dev, int pipe);
void mdfld_disable_te(struct drm_device *dev, int pipe);
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index 51fa32392029..d9a72c96e56c 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -119,8 +119,8 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
struct ch7006_encoder_params *params = &priv->params;
struct ch7006_state *state = &priv->state;
uint8_t *regs = state->regs;
- struct ch7006_mode *mode = priv->mode;
- struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+ const struct ch7006_mode *mode = priv->mode;
+ const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
int start_active;
ch7006_dbg(client, "\n");
@@ -226,7 +226,7 @@ static int ch7006_encoder_get_modes(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct ch7006_priv *priv = to_ch7006_priv(encoder);
- struct ch7006_mode *mode;
+ const struct ch7006_mode *mode;
int n = 0;
for (mode = ch7006_modes; mode->mode.clock; mode++) {
diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c
index 9b83574141a6..bb5f67f10edb 100644
--- a/drivers/gpu/drm/i2c/ch7006_mode.c
+++ b/drivers/gpu/drm/i2c/ch7006_mode.c
@@ -26,7 +26,7 @@
#include "ch7006_priv.h"
-char *ch7006_tv_norm_names[] = {
+const char * const ch7006_tv_norm_names[] = {
[TV_NORM_PAL] = "PAL",
[TV_NORM_PAL_M] = "PAL-M",
[TV_NORM_PAL_N] = "PAL-N",
@@ -46,7 +46,7 @@ char *ch7006_tv_norm_names[] = {
.vtotal = 625, \
.hvirtual = 810
-struct ch7006_tv_norm_info ch7006_tv_norms[] = {
+const struct ch7006_tv_norm_info ch7006_tv_norms[] = {
[TV_NORM_NTSC_M] = {
NTSC_LIKE_TIMINGS,
.black_level = 0.339 * fixed1,
@@ -142,7 +142,7 @@ struct ch7006_tv_norm_info ch7006_tv_norms[] = {
#define PAL_LIKE (1 << TV_NORM_PAL | 1 << TV_NORM_PAL_N | 1 << TV_NORM_PAL_NC)
-struct ch7006_mode ch7006_modes[] = {
+const struct ch7006_mode ch7006_modes[] = {
MODE(21000, 512, 384, 840, 500, N, N, 181.797557582, 5_4, 0x6, PAL_LIKE),
MODE(26250, 512, 384, 840, 625, N, N, 145.438046066, 1_1, 0x1, PAL_LIKE),
MODE(20140, 512, 384, 800, 420, N, N, 213.257083791, 5_4, 0x4, NTSC_LIKE),
@@ -171,11 +171,11 @@ struct ch7006_mode ch7006_modes[] = {
{}
};
-struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
- const struct drm_display_mode *drm_mode)
+const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
+ const struct drm_display_mode *drm_mode)
{
struct ch7006_priv *priv = to_ch7006_priv(encoder);
- struct ch7006_mode *mode;
+ const struct ch7006_mode *mode;
for (mode = ch7006_modes; mode->mode.clock; mode++) {
@@ -202,7 +202,7 @@ void ch7006_setup_levels(struct drm_encoder *encoder)
struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
uint8_t *regs = priv->state.regs;
- struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+ const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
int gain;
int black_level;
@@ -233,8 +233,8 @@ void ch7006_setup_subcarrier(struct drm_encoder *encoder)
struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
- struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
- struct ch7006_mode *mode = priv->mode;
+ const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+ const struct ch7006_mode *mode = priv->mode;
uint32_t subc_inc;
subc_inc = round_fixed((mode->subc_coeff >> 8)
@@ -257,7 +257,7 @@ void ch7006_setup_pll(struct drm_encoder *encoder)
struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
uint8_t *regs = priv->state.regs;
- struct ch7006_mode *mode = priv->mode;
+ const struct ch7006_mode *mode = priv->mode;
int n, best_n = 0;
int m, best_m = 0;
int freq, best_freq = 0;
@@ -328,9 +328,9 @@ void ch7006_setup_properties(struct drm_encoder *encoder)
struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
- struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
- struct ch7006_mode *ch_mode = priv->mode;
- struct drm_display_mode *mode = &ch_mode->mode;
+ const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+ const struct ch7006_mode *ch_mode = priv->mode;
+ const struct drm_display_mode *mode = &ch_mode->mode;
uint8_t *regs = state->regs;
int flicker, contrast, hpos, vpos;
uint64_t scale, aspect;
diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h
index ce577841f931..dc6414af5d79 100644
--- a/drivers/gpu/drm/i2c/ch7006_priv.h
+++ b/drivers/gpu/drm/i2c/ch7006_priv.h
@@ -78,7 +78,7 @@ struct ch7006_state {
struct ch7006_priv {
struct ch7006_encoder_params params;
- struct ch7006_mode *mode;
+ const struct ch7006_mode *mode;
struct ch7006_state state;
struct ch7006_state saved_state;
@@ -106,12 +106,12 @@ extern int ch7006_debug;
extern char *ch7006_tv_norm;
extern int ch7006_scale;
-extern char *ch7006_tv_norm_names[];
-extern struct ch7006_tv_norm_info ch7006_tv_norms[];
-extern struct ch7006_mode ch7006_modes[];
+extern const char * const ch7006_tv_norm_names[];
+extern const struct ch7006_tv_norm_info ch7006_tv_norms[];
+extern const struct ch7006_mode ch7006_modes[];
-struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
- const struct drm_display_mode *drm_mode);
+const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
+ const struct drm_display_mode *drm_mode);
void ch7006_setup_levels(struct drm_encoder *encoder);
void ch7006_setup_subcarrier(struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 424228be79ae..896b6aaf8c4d 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -23,7 +23,6 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
-#include <drm/drm_encoder_slave.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/i2c/tda998x.h>
@@ -34,9 +33,8 @@ struct tda998x_priv {
struct i2c_client *cec;
struct i2c_client *hdmi;
struct mutex mutex;
- struct delayed_work dwork;
- uint16_t rev;
- uint8_t current_page;
+ u16 rev;
+ u8 current_page;
int dpms;
bool is_hdmi_sink;
u8 vip_cntrl_0;
@@ -46,10 +44,21 @@ struct tda998x_priv {
wait_queue_head_t wq_edid;
volatile int wq_edid_wait;
- struct drm_encoder *encoder;
+
+ struct work_struct detect_work;
+ struct timer_list edid_delay_timer;
+ wait_queue_head_t edid_delay_waitq;
+ bool edid_delay_active;
+
+ struct drm_encoder encoder;
+ struct drm_connector connector;
};
-#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
+#define conn_to_tda998x_priv(x) \
+ container_of(x, struct tda998x_priv, connector)
+
+#define enc_to_tda998x_priv(x) \
+ container_of(x, struct tda998x_priv, encoder)
/* The TDA9988 series of devices use a paged register scheme.. to simplify
* things we encode the page # in upper bits of the register #. To read/
@@ -326,6 +335,8 @@ struct tda998x_priv {
# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0)
#define REG_CEC_RXSHPDINTENA 0xfc /* read/write */
#define REG_CEC_RXSHPDINT 0xfd /* read */
+# define CEC_RXSHPDINT_RXSENS BIT(0)
+# define CEC_RXSHPDINT_HPD BIT(1)
#define REG_CEC_RXSHPDLEV 0xfe /* read */
# define CEC_RXSHPDLEV_RXSENS (1 << 0)
# define CEC_RXSHPDLEV_HPD (1 << 1)
@@ -345,10 +356,10 @@ struct tda998x_priv {
#define TDA19988 0x0301
static void
-cec_write(struct tda998x_priv *priv, uint16_t addr, uint8_t val)
+cec_write(struct tda998x_priv *priv, u16 addr, u8 val)
{
struct i2c_client *client = priv->cec;
- uint8_t buf[] = {addr, val};
+ u8 buf[] = {addr, val};
int ret;
ret = i2c_master_send(client, buf, sizeof(buf));
@@ -356,11 +367,11 @@ cec_write(struct tda998x_priv *priv, uint16_t addr, uint8_t val)
dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
}
-static uint8_t
-cec_read(struct tda998x_priv *priv, uint8_t addr)
+static u8
+cec_read(struct tda998x_priv *priv, u8 addr)
{
struct i2c_client *client = priv->cec;
- uint8_t val;
+ u8 val;
int ret;
ret = i2c_master_send(client, &addr, sizeof(addr));
@@ -379,11 +390,11 @@ fail:
}
static int
-set_page(struct tda998x_priv *priv, uint16_t reg)
+set_page(struct tda998x_priv *priv, u16 reg)
{
if (REG2PAGE(reg) != priv->current_page) {
struct i2c_client *client = priv->hdmi;
- uint8_t buf[] = {
+ u8 buf[] = {
REG_CURPAGE, REG2PAGE(reg)
};
int ret = i2c_master_send(client, buf, sizeof(buf));
@@ -399,10 +410,10 @@ set_page(struct tda998x_priv *priv, uint16_t reg)
}
static int
-reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt)
+reg_read_range(struct tda998x_priv *priv, u16 reg, char *buf, int cnt)
{
struct i2c_client *client = priv->hdmi;
- uint8_t addr = REG2ADDR(reg);
+ u8 addr = REG2ADDR(reg);
int ret;
mutex_lock(&priv->mutex);
@@ -428,10 +439,10 @@ out:
}
static void
-reg_write_range(struct tda998x_priv *priv, uint16_t reg, uint8_t *p, int cnt)
+reg_write_range(struct tda998x_priv *priv, u16 reg, u8 *p, int cnt)
{
struct i2c_client *client = priv->hdmi;
- uint8_t buf[cnt+1];
+ u8 buf[cnt+1];
int ret;
buf[0] = REG2ADDR(reg);
@@ -450,9 +461,9 @@ out:
}
static int
-reg_read(struct tda998x_priv *priv, uint16_t reg)
+reg_read(struct tda998x_priv *priv, u16 reg)
{
- uint8_t val = 0;
+ u8 val = 0;
int ret;
ret = reg_read_range(priv, reg, &val, sizeof(val));
@@ -462,10 +473,10 @@ reg_read(struct tda998x_priv *priv, uint16_t reg)
}
static void
-reg_write(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
+reg_write(struct tda998x_priv *priv, u16 reg, u8 val)
{
struct i2c_client *client = priv->hdmi;
- uint8_t buf[] = {REG2ADDR(reg), val};
+ u8 buf[] = {REG2ADDR(reg), val};
int ret;
mutex_lock(&priv->mutex);
@@ -481,10 +492,10 @@ out:
}
static void
-reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val)
+reg_write16(struct tda998x_priv *priv, u16 reg, u16 val)
{
struct i2c_client *client = priv->hdmi;
- uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
+ u8 buf[] = {REG2ADDR(reg), val >> 8, val};
int ret;
mutex_lock(&priv->mutex);
@@ -500,7 +511,7 @@ out:
}
static void
-reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
+reg_set(struct tda998x_priv *priv, u16 reg, u8 val)
{
int old_val;
@@ -510,7 +521,7 @@ reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
}
static void
-reg_clear(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
+reg_clear(struct tda998x_priv *priv, u16 reg, u8 val)
{
int old_val;
@@ -551,15 +562,50 @@ tda998x_reset(struct tda998x_priv *priv)
reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
}
-/* handle HDMI connect/disconnect */
-static void tda998x_hpd(struct work_struct *work)
+/*
+ * The TDA998x has a problem when trying to read the EDID close to a
+ * HPD assertion: it needs a delay of 100ms to avoid timing out while
+ * trying to read EDID data.
+ *
+ * However, tda998x_encoder_get_modes() may be called at any moment
+ * after tda998x_connector_detect() indicates that we are connected, so
+ * we need to delay probing modes in tda998x_encoder_get_modes() after
+ * we have seen a HPD inactive->active transition. This code implements
+ * that delay.
+ */
+static void tda998x_edid_delay_done(unsigned long data)
+{
+ struct tda998x_priv *priv = (struct tda998x_priv *)data;
+
+ priv->edid_delay_active = false;
+ wake_up(&priv->edid_delay_waitq);
+ schedule_work(&priv->detect_work);
+}
+
+static void tda998x_edid_delay_start(struct tda998x_priv *priv)
+{
+ priv->edid_delay_active = true;
+ mod_timer(&priv->edid_delay_timer, jiffies + HZ/10);
+}
+
+static int tda998x_edid_delay_wait(struct tda998x_priv *priv)
+{
+ return wait_event_killable(priv->edid_delay_waitq, !priv->edid_delay_active);
+}
+
+/*
+ * We need to run the KMS hotplug event helper outside of our threaded
+ * interrupt routine as this can call back into our get_modes method,
+ * which will want to make use of interrupts.
+ */
+static void tda998x_detect_work(struct work_struct *work)
{
- struct delayed_work *dwork = to_delayed_work(work);
struct tda998x_priv *priv =
- container_of(dwork, struct tda998x_priv, dwork);
+ container_of(work, struct tda998x_priv, detect_work);
+ struct drm_device *dev = priv->encoder.dev;
- if (priv->encoder && priv->encoder->dev)
- drm_kms_helper_hotplug_event(priv->encoder->dev);
+ if (dev)
+ drm_kms_helper_hotplug_event(dev);
}
/*
@@ -569,9 +615,8 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data)
{
struct tda998x_priv *priv = data;
u8 sta, cec, lvl, flag0, flag1, flag2;
+ bool handled = false;
- if (!priv)
- return IRQ_HANDLED;
sta = cec_read(priv, REG_CEC_INTSTATUS);
cec = cec_read(priv, REG_CEC_RXSHPDINT);
lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
@@ -581,75 +626,76 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data)
DRM_DEBUG_DRIVER(
"tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
sta, cec, lvl, flag0, flag1, flag2);
+
+ if (cec & CEC_RXSHPDINT_HPD) {
+ if (lvl & CEC_RXSHPDLEV_HPD)
+ tda998x_edid_delay_start(priv);
+ else
+ schedule_work(&priv->detect_work);
+
+ handled = true;
+ }
+
if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
priv->wq_edid_wait = 0;
wake_up(&priv->wq_edid);
- } else if (cec != 0) { /* HPD change */
- schedule_delayed_work(&priv->dwork, HZ/10);
+ handled = true;
}
- return IRQ_HANDLED;
-}
-static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
-{
- int sum = 0;
-
- while (bytes--)
- sum -= *buf++;
- return sum;
+ return IRQ_RETVAL(handled);
}
-#define HB(x) (x)
-#define PB(x) (HB(2) + 1 + (x))
-
static void
-tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr,
- uint8_t *buf, size_t size)
+tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
+ union hdmi_infoframe *frame)
{
+ u8 buf[32];
+ ssize_t len;
+
+ len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
+ if (len < 0) {
+ dev_err(&priv->hdmi->dev,
+ "hdmi_infoframe_pack() type=0x%02x failed: %zd\n",
+ frame->any.type, len);
+ return;
+ }
+
reg_clear(priv, REG_DIP_IF_FLAGS, bit);
- reg_write_range(priv, addr, buf, size);
+ reg_write_range(priv, addr, buf, len);
reg_set(priv, REG_DIP_IF_FLAGS, bit);
}
static void
tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p)
{
- u8 buf[PB(HDMI_AUDIO_INFOFRAME_SIZE) + 1];
+ union hdmi_infoframe frame;
+
+ hdmi_audio_infoframe_init(&frame.audio);
- memset(buf, 0, sizeof(buf));
- buf[HB(0)] = HDMI_INFOFRAME_TYPE_AUDIO;
- buf[HB(1)] = 0x01;
- buf[HB(2)] = HDMI_AUDIO_INFOFRAME_SIZE;
- buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */
- buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */
- buf[PB(4)] = p->audio_frame[4];
- buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */
+ frame.audio.channels = p->audio_frame[1] & 0x07;
+ frame.audio.channel_allocation = p->audio_frame[4];
+ frame.audio.level_shift_value = (p->audio_frame[5] & 0x78) >> 3;
+ frame.audio.downmix_inhibit = (p->audio_frame[5] & 0x80) >> 7;
- buf[PB(0)] = tda998x_cksum(buf, sizeof(buf));
+ /*
+ * L-PCM and IEC61937 compressed audio shall always set sample
+ * frequency to "refer to stream". For others, see the HDMI
+ * specification.
+ */
+ frame.audio.sample_frequency = (p->audio_frame[2] & 0x1c) >> 2;
- tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
- sizeof(buf));
+ tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame);
}
static void
tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
{
- struct hdmi_avi_infoframe frame;
- u8 buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
- ssize_t len;
+ union hdmi_infoframe frame;
- drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+ drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+ frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
- frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
-
- len = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf));
- if (len < 0) {
- dev_err(&priv->hdmi->dev,
- "hdmi_avi_infoframe_pack() failed: %zd\n", len);
- return;
- }
-
- tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf, len);
+ tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
}
static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
@@ -667,8 +713,8 @@ static void
tda998x_configure_audio(struct tda998x_priv *priv,
struct drm_display_mode *mode, struct tda998x_encoder_params *p)
{
- uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv;
- uint32_t n;
+ u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
+ u32 n;
/* Enable audio ports */
reg_write(priv, REG_ENA_AP, p->audio_cfg);
@@ -776,8 +822,10 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv,
priv->params = *p;
}
-static void tda998x_encoder_dpms(struct tda998x_priv *priv, int mode)
+static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
{
+ struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
+
/* we only care about on or off: */
if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
@@ -827,8 +875,8 @@ tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
return true;
}
-static int tda998x_encoder_mode_valid(struct tda998x_priv *priv,
- struct drm_display_mode *mode)
+static int tda998x_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
{
if (mode->clock > 150000)
return MODE_CLOCK_HIGH;
@@ -840,18 +888,19 @@ static int tda998x_encoder_mode_valid(struct tda998x_priv *priv,
}
static void
-tda998x_encoder_mode_set(struct tda998x_priv *priv,
+tda998x_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- uint16_t ref_pix, ref_line, n_pix, n_line;
- uint16_t hs_pix_s, hs_pix_e;
- uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
- uint16_t vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e;
- uint16_t vwin1_line_s, vwin1_line_e;
- uint16_t vwin2_line_s, vwin2_line_e;
- uint16_t de_pix_s, de_pix_e;
- uint8_t reg, div, rep;
+ struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
+ u16 ref_pix, ref_line, n_pix, n_line;
+ u16 hs_pix_s, hs_pix_e;
+ u16 vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
+ u16 vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e;
+ u16 vwin1_line_s, vwin1_line_e;
+ u16 vwin2_line_s, vwin2_line_e;
+ u16 de_pix_s, de_pix_e;
+ u8 reg, div, rep;
/*
* Internally TDA998x is using ITU-R BT.656 style sync but
@@ -1031,9 +1080,10 @@ tda998x_encoder_mode_set(struct tda998x_priv *priv,
}
static enum drm_connector_status
-tda998x_encoder_detect(struct tda998x_priv *priv)
+tda998x_connector_detect(struct drm_connector *connector, bool force)
{
- uint8_t val = cec_read(priv, REG_CEC_RXSHPDLEV);
+ struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+ u8 val = cec_read(priv, REG_CEC_RXSHPDLEV);
return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
connector_status_disconnected;
@@ -1042,7 +1092,7 @@ tda998x_encoder_detect(struct tda998x_priv *priv)
static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
{
struct tda998x_priv *priv = data;
- uint8_t offset, segptr;
+ u8 offset, segptr;
int ret, i;
offset = (blk & 1) ? 128 : 0;
@@ -1095,13 +1145,20 @@ static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
return 0;
}
-static int
-tda998x_encoder_get_modes(struct tda998x_priv *priv,
- struct drm_connector *connector)
+static int tda998x_connector_get_modes(struct drm_connector *connector)
{
+ struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
struct edid *edid;
int n;
+ /*
+ * If we get killed while waiting for the HPD timeout, return
+ * no modes found: we are not in a restartable path, so we
+ * can't handle signals gracefully.
+ */
+ if (tda998x_edid_delay_wait(priv))
+ return 0;
+
if (priv->rev == TDA19988)
reg_clear(priv, REG_TX4, TX4_PD_RAM);
@@ -1133,101 +1190,21 @@ static void tda998x_encoder_set_polling(struct tda998x_priv *priv,
DRM_CONNECTOR_POLL_DISCONNECT;
}
-static int
-tda998x_encoder_set_property(struct drm_encoder *encoder,
- struct drm_connector *connector,
- struct drm_property *property,
- uint64_t val)
-{
- DBG("");
- return 0;
-}
-
static void tda998x_destroy(struct tda998x_priv *priv)
{
/* disable all IRQs and free the IRQ handler */
cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
- if (priv->hdmi->irq) {
- free_irq(priv->hdmi->irq, priv);
- cancel_delayed_work_sync(&priv->dwork);
- }
-
- i2c_unregister_device(priv->cec);
-}
-
-/* Slave encoder support */
-
-static void
-tda998x_encoder_slave_set_config(struct drm_encoder *encoder, void *params)
-{
- tda998x_encoder_set_config(to_tda998x_priv(encoder), params);
-}
-static void tda998x_encoder_slave_destroy(struct drm_encoder *encoder)
-{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
- tda998x_destroy(priv);
- drm_i2c_encoder_destroy(encoder);
- kfree(priv);
-}
-
-static void tda998x_encoder_slave_dpms(struct drm_encoder *encoder, int mode)
-{
- tda998x_encoder_dpms(to_tda998x_priv(encoder), mode);
-}
-
-static int tda998x_encoder_slave_mode_valid(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
-{
- return tda998x_encoder_mode_valid(to_tda998x_priv(encoder), mode);
-}
+ if (priv->hdmi->irq)
+ free_irq(priv->hdmi->irq, priv);
-static void
-tda998x_encoder_slave_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- tda998x_encoder_mode_set(to_tda998x_priv(encoder), mode, adjusted_mode);
-}
+ del_timer_sync(&priv->edid_delay_timer);
+ cancel_work_sync(&priv->detect_work);
-static enum drm_connector_status
-tda998x_encoder_slave_detect(struct drm_encoder *encoder,
- struct drm_connector *connector)
-{
- return tda998x_encoder_detect(to_tda998x_priv(encoder));
-}
-
-static int tda998x_encoder_slave_get_modes(struct drm_encoder *encoder,
- struct drm_connector *connector)
-{
- return tda998x_encoder_get_modes(to_tda998x_priv(encoder), connector);
-}
-
-static int
-tda998x_encoder_slave_create_resources(struct drm_encoder *encoder,
- struct drm_connector *connector)
-{
- tda998x_encoder_set_polling(to_tda998x_priv(encoder), connector);
- return 0;
+ i2c_unregister_device(priv->cec);
}
-static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = {
- .set_config = tda998x_encoder_slave_set_config,
- .destroy = tda998x_encoder_slave_destroy,
- .dpms = tda998x_encoder_slave_dpms,
- .save = tda998x_encoder_save,
- .restore = tda998x_encoder_restore,
- .mode_fixup = tda998x_encoder_mode_fixup,
- .mode_valid = tda998x_encoder_slave_mode_valid,
- .mode_set = tda998x_encoder_slave_mode_set,
- .detect = tda998x_encoder_slave_detect,
- .get_modes = tda998x_encoder_slave_get_modes,
- .create_resources = tda998x_encoder_slave_create_resources,
- .set_property = tda998x_encoder_set_property,
-};
-
/* I2C driver functions */
static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
@@ -1252,6 +1229,10 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
priv->dpms = DRM_MODE_DPMS_OFF;
mutex_init(&priv->mutex); /* protect the page access */
+ init_waitqueue_head(&priv->edid_delay_waitq);
+ setup_timer(&priv->edid_delay_timer, tda998x_edid_delay_done,
+ (unsigned long)priv);
+ INIT_WORK(&priv->detect_work, tda998x_detect_work);
/* wake up the device: */
cec_write(priv, REG_CEC_ENAMODS,
@@ -1310,7 +1291,6 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
/* init read EDID waitqueue and HDP work */
init_waitqueue_head(&priv->wq_edid);
- INIT_DELAYED_WORK(&priv->dwork, tda998x_hpd);
/* clear pending interrupts */
reg_read(priv, REG_INT_FLAGS_0);
@@ -1359,84 +1339,31 @@ fail:
return -ENXIO;
}
-static int tda998x_encoder_init(struct i2c_client *client,
- struct drm_device *dev,
- struct drm_encoder_slave *encoder_slave)
-{
- struct tda998x_priv *priv;
- int ret;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->encoder = &encoder_slave->base;
-
- ret = tda998x_create(client, priv);
- if (ret) {
- kfree(priv);
- return ret;
- }
-
- encoder_slave->slave_priv = priv;
- encoder_slave->slave_funcs = &tda998x_encoder_slave_funcs;
-
- return 0;
-}
-
-struct tda998x_priv2 {
- struct tda998x_priv base;
- struct drm_encoder encoder;
- struct drm_connector connector;
-};
-
-#define conn_to_tda998x_priv2(x) \
- container_of(x, struct tda998x_priv2, connector);
-
-#define enc_to_tda998x_priv2(x) \
- container_of(x, struct tda998x_priv2, encoder);
-
-static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode)
-{
- struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
-
- tda998x_encoder_dpms(&priv->base, mode);
-}
-
static void tda998x_encoder_prepare(struct drm_encoder *encoder)
{
- tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_OFF);
+ tda998x_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void tda998x_encoder_commit(struct drm_encoder *encoder)
{
- tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static void tda998x_encoder2_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
-
- tda998x_encoder_mode_set(&priv->base, mode, adjusted_mode);
+ tda998x_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
}
static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = {
- .dpms = tda998x_encoder2_dpms,
+ .dpms = tda998x_encoder_dpms,
.save = tda998x_encoder_save,
.restore = tda998x_encoder_restore,
.mode_fixup = tda998x_encoder_mode_fixup,
.prepare = tda998x_encoder_prepare,
.commit = tda998x_encoder_commit,
- .mode_set = tda998x_encoder2_mode_set,
+ .mode_set = tda998x_encoder_mode_set,
};
static void tda998x_encoder_destroy(struct drm_encoder *encoder)
{
- struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+ struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
- tda998x_destroy(&priv->base);
+ tda998x_destroy(priv);
drm_encoder_cleanup(encoder);
}
@@ -1444,25 +1371,10 @@ static const struct drm_encoder_funcs tda998x_encoder_funcs = {
.destroy = tda998x_encoder_destroy,
};
-static int tda998x_connector_get_modes(struct drm_connector *connector)
-{
- struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
-
- return tda998x_encoder_get_modes(&priv->base, connector);
-}
-
-static int tda998x_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
-
- return tda998x_encoder_mode_valid(&priv->base, mode);
-}
-
static struct drm_encoder *
tda998x_connector_best_encoder(struct drm_connector *connector)
{
- struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+ struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
return &priv->encoder;
}
@@ -1474,14 +1386,6 @@ const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
.best_encoder = tda998x_connector_best_encoder,
};
-static enum drm_connector_status
-tda998x_connector_detect(struct drm_connector *connector, bool force)
-{
- struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
-
- return tda998x_encoder_detect(&priv->base);
-}
-
static void tda998x_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
@@ -1500,8 +1404,8 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data)
struct tda998x_encoder_params *params = dev->platform_data;
struct i2c_client *client = to_i2c_client(dev);
struct drm_device *drm = data;
- struct tda998x_priv2 *priv;
- uint32_t crtcs = 0;
+ struct tda998x_priv *priv;
+ u32 crtcs = 0;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -1519,18 +1423,17 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data)
crtcs = 1 << 0;
}
- priv->base.encoder = &priv->encoder;
priv->connector.interlace_allowed = 1;
priv->encoder.possible_crtcs = crtcs;
- ret = tda998x_create(client, &priv->base);
+ ret = tda998x_create(client, priv);
if (ret)
return ret;
if (!dev->of_node && params)
- tda998x_encoder_set_config(&priv->base, params);
+ tda998x_encoder_set_config(priv, params);
- tda998x_encoder_set_polling(&priv->base, &priv->connector);
+ tda998x_encoder_set_polling(priv, &priv->connector);
drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs);
ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
@@ -1560,18 +1463,18 @@ err_sysfs:
err_connector:
drm_encoder_cleanup(&priv->encoder);
err_encoder:
- tda998x_destroy(&priv->base);
+ tda998x_destroy(priv);
return ret;
}
static void tda998x_unbind(struct device *dev, struct device *master,
void *data)
{
- struct tda998x_priv2 *priv = dev_get_drvdata(dev);
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
drm_connector_cleanup(&priv->connector);
drm_encoder_cleanup(&priv->encoder);
- tda998x_destroy(&priv->base);
+ tda998x_destroy(priv);
}
static const struct component_ops tda998x_ops = {
@@ -1605,38 +1508,18 @@ static struct i2c_device_id tda998x_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, tda998x_ids);
-static struct drm_i2c_encoder_driver tda998x_driver = {
- .i2c_driver = {
- .probe = tda998x_probe,
- .remove = tda998x_remove,
- .driver = {
- .name = "tda998x",
- .of_match_table = of_match_ptr(tda998x_dt_ids),
- },
- .id_table = tda998x_ids,
+static struct i2c_driver tda998x_driver = {
+ .probe = tda998x_probe,
+ .remove = tda998x_remove,
+ .driver = {
+ .name = "tda998x",
+ .of_match_table = of_match_ptr(tda998x_dt_ids),
},
- .encoder_init = tda998x_encoder_init,
+ .id_table = tda998x_ids,
};
-/* Module initialization */
-
-static int __init
-tda998x_init(void)
-{
- DBG("");
- return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver);
-}
-
-static void __exit
-tda998x_exit(void)
-{
- DBG("");
- drm_i2c_encoder_unregister(&tda998x_driver);
-}
+module_i2c_driver(tda998x_driver);
MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
MODULE_LICENSE("GPL");
-
-module_init(tda998x_init);
-module_exit(tda998x_exit);
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 998b4643109f..44d290ae1999 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -40,6 +40,10 @@ i915-y += i915_cmd_parser.o \
intel_ringbuffer.o \
intel_uncore.o
+# general-purpose microcontroller (GuC) support
+i915-y += intel_guc_loader.o \
+ i915_guc_submission.o
+
# autogenerated null render state
i915-y += intel_renderstate_gen6.o \
intel_renderstate_gen7.o \
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 312163379db9..0e2c1b9648a7 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -94,8 +94,8 @@ struct intel_dvo_dev_ops {
* after this function is called.
*/
void (*mode_set)(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode);
/*
* Probe for a connected output, and return detect_status.
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index 86b27d1d90c2..cbb22027a3ce 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -255,8 +255,8 @@ static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
}
static void ch7017_mode_set(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
uint8_t lvds_pll_feedback_div, lvds_pll_vco_control;
uint8_t outputs_enable, lvds_control_2, lvds_power_down;
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index 80449f475960..4b4acc1a06fe 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -275,8 +275,8 @@ static enum drm_mode_status ch7xxx_mode_valid(struct intel_dvo_device *dvo,
}
static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
uint8_t tvco, tpcp, tpd, tlpf, idf;
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index 732ce8785945..ff9f1b077d83 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -394,8 +394,8 @@ static bool ivch_get_hw_state(struct intel_dvo_device *dvo)
}
static void ivch_mode_set(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
struct ivch_priv *priv = dvo->dev_priv;
uint16_t vr40 = 0;
@@ -414,16 +414,16 @@ static void ivch_mode_set(struct intel_dvo_device *dvo,
vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE |
VR40_HORIZONTAL_INTERP_ENABLE);
- if (mode->hdisplay != adjusted_mode->hdisplay ||
- mode->vdisplay != adjusted_mode->vdisplay) {
+ if (mode->hdisplay != adjusted_mode->crtc_hdisplay ||
+ mode->vdisplay != adjusted_mode->crtc_vdisplay) {
uint16_t x_ratio, y_ratio;
vr01 |= VR01_PANEL_FIT_ENABLE;
vr40 |= VR40_CLOCK_GATING_ENABLE;
x_ratio = (((mode->hdisplay - 1) << 16) /
- (adjusted_mode->hdisplay - 1)) >> 2;
+ (adjusted_mode->crtc_hdisplay - 1)) >> 2;
y_ratio = (((mode->vdisplay - 1) << 16) /
- (adjusted_mode->vdisplay - 1)) >> 2;
+ (adjusted_mode->crtc_vdisplay - 1)) >> 2;
ivch_write(dvo, VR42, x_ratio);
ivch_write(dvo, VR41, y_ratio);
} else {
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
index 97ae8aa157e9..063859fff0f0 100644
--- a/drivers/gpu/drm/i915/dvo_ns2501.c
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -546,8 +546,8 @@ static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
}
static void ns2501_mode_set(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
const struct ns2501_configuration *conf;
struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index fa0114967076..26f13eb634f9 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -190,8 +190,8 @@ static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,
}
static void sil164_mode_set(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
/* As long as the basics are set up, since we don't have clock
* dependencies in the mode setup, we can just leave the
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 7853719a0e81..6f1a0a6d4e22 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -222,8 +222,8 @@ static enum drm_mode_status tfp410_mode_valid(struct intel_dvo_device *dvo,
}
static void tfp410_mode_set(struct intel_dvo_device *dvo,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
{
/* As long as the basics are set up, since we don't have clock dependencies
* in the mode setup, we can just leave the registers alone and everything
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 237ff6884a22..db58c8d664c2 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -94,7 +94,7 @@
#define CMD(op, opm, f, lm, fl, ...) \
{ \
.flags = (fl) | ((f) ? CMD_DESC_FIXED : 0), \
- .cmd = { (op), (opm) }, \
+ .cmd = { (op), (opm) }, \
.length = { (lm) }, \
__VA_ARGS__ \
}
@@ -124,14 +124,14 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ),
CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W,
.reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ),
- CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B,
+ CMD( MI_STORE_REGISTER_MEM, SMI, F, 3, W | B,
.reg = { .offset = 1, .mask = 0x007FFFFC },
.bits = {{
.offset = 0,
.mask = MI_GLOBAL_GTT,
.expected = 0,
}}, ),
- CMD( MI_LOAD_REGISTER_MEM(1), SMI, !F, 0xFF, W | B,
+ CMD( MI_LOAD_REGISTER_MEM, SMI, F, 3, W | B,
.reg = { .offset = 1, .mask = 0x007FFFFC },
.bits = {{
.offset = 0,
@@ -448,6 +448,9 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
REG32(GEN7_3DPRIM_INSTANCE_COUNT),
REG32(GEN7_3DPRIM_START_INSTANCE),
REG32(GEN7_3DPRIM_BASE_VERTEX),
+ REG32(GEN7_GPGPU_DISPATCHDIMX),
+ REG32(GEN7_GPGPU_DISPATCHDIMY),
+ REG32(GEN7_GPGPU_DISPATCHDIMZ),
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)),
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)),
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)),
@@ -1021,7 +1024,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
* only MI_LOAD_REGISTER_IMM commands.
*/
if (reg_addr == OACONTROL) {
- if (desc->cmd.value == MI_LOAD_REGISTER_MEM(1)) {
+ if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
return false;
}
@@ -1035,7 +1038,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
* allowed mask/value pair given in the whitelist entry.
*/
if (reg->mask) {
- if (desc->cmd.value == MI_LOAD_REGISTER_MEM(1)) {
+ if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n",
reg_addr);
return false;
@@ -1213,6 +1216,8 @@ int i915_cmd_parser_get_version(void)
* 2. Allow access to the MI_PREDICATE_SRC0 and
* MI_PREDICATE_SRC1 registers.
* 3. Allow access to the GPGPU_THREADS_DISPATCHED register.
+ * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3.
+ * 5. GPGPU dispatch compute indirect registers.
*/
- return 3;
+ return 5;
}
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index e3ec9049081f..a3b22bdacd44 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -46,11 +46,6 @@ enum {
PINNED_LIST,
};
-static const char *yesno(int v)
-{
- return v ? "yes" : "no";
-}
-
/* As the drm_debugfs_init() routines are called before dev->dev_private is
* allocated we need to hook into the minor for release. */
static int
@@ -258,7 +253,11 @@ static int obj_rank_by_stolen(void *priv,
struct drm_i915_gem_object *b =
container_of(B, struct drm_i915_gem_object, obj_exec_link);
- return a->stolen->start - b->stolen->start;
+ if (a->stolen->start < b->stolen->start)
+ return -1;
+ if (a->stolen->start > b->stolen->start)
+ return 1;
+ return 0;
}
static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
@@ -957,7 +956,6 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
if (ret)
return ret;
- seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start);
seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
for (i = 0; i < dev_priv->num_fence_regs; i++) {
struct drm_i915_gem_object *obj = dev_priv->fence_regs[i].obj;
@@ -1314,6 +1312,10 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
seq_puts(m, "no P-state info available\n");
}
+ seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq);
+ seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
+ seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
+
out:
intel_runtime_pm_put(dev_priv);
return ret;
@@ -1387,17 +1389,16 @@ static int ironlake_drpc_info(struct seq_file *m)
intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex);
- seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
- "yes" : "no");
+ seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
seq_printf(m, "Boost freq: %d\n",
(rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >>
MEMMODE_BOOST_FREQ_SHIFT);
seq_printf(m, "HW control enabled: %s\n",
- rgvmodectl & MEMMODE_HWIDLE_EN ? "yes" : "no");
+ yesno(rgvmodectl & MEMMODE_HWIDLE_EN));
seq_printf(m, "SW control enabled: %s\n",
- rgvmodectl & MEMMODE_SWMODE_EN ? "yes" : "no");
+ yesno(rgvmodectl & MEMMODE_SWMODE_EN));
seq_printf(m, "Gated voltage change: %s\n",
- rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
+ yesno(rgvmodectl & MEMMODE_RCLK_GATE));
seq_printf(m, "Starting frequency: P%d\n",
(rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
seq_printf(m, "Max P-state: P%d\n",
@@ -1406,7 +1407,7 @@ static int ironlake_drpc_info(struct seq_file *m)
seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
seq_printf(m, "Render standby enabled: %s\n",
- (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
+ yesno(!(rstdbyctl & RCX_SW_EXIT)));
seq_puts(m, "Current RS state: ");
switch (rstdbyctl & RSX_STATUS_MASK) {
case RSX_STATUS_ON:
@@ -1849,7 +1850,7 @@ static int i915_opregion(struct seq_file *m, void *unused)
goto out;
if (opregion->header) {
- memcpy_fromio(data, opregion->header, OPREGION_SIZE);
+ memcpy(data, opregion->header, OPREGION_SIZE);
seq_write(m, data, OPREGION_SIZE);
}
@@ -1995,7 +1996,7 @@ static void i915_dump_lrc_obj(struct seq_file *m,
return;
}
- page = i915_gem_object_get_page(ctx_obj, 1);
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
if (!WARN_ON(page == NULL)) {
reg_state = kmap_atomic(page);
@@ -2075,8 +2076,8 @@ static int i915_execlists(struct seq_file *m, void *data)
seq_printf(m, "%s\n", ring->name);
- status = I915_READ(RING_EXECLIST_STATUS(ring));
- ctx_id = I915_READ(RING_EXECLIST_STATUS(ring) + 4);
+ status = I915_READ(RING_EXECLIST_STATUS_LO(ring));
+ ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring));
seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n",
status, ctx_id);
@@ -2091,8 +2092,8 @@ static int i915_execlists(struct seq_file *m, void *data)
read_pointer, write_pointer);
for (i = 0; i < 6; i++) {
- status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i);
- ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i + 4);
+ status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i));
+ ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i));
seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n",
i, status, ctx_id);
@@ -2237,10 +2238,9 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
for_each_ring(ring, dev_priv, unused) {
seq_printf(m, "%s\n", ring->name);
for (i = 0; i < 4; i++) {
- u32 offset = 0x270 + i * 8;
- u64 pdp = I915_READ(ring->mmio_base + offset + 4);
+ u64 pdp = I915_READ(GEN8_RING_PDP_UDW(ring, i));
pdp <<= 32;
- pdp |= I915_READ(ring->mmio_base + offset);
+ pdp |= I915_READ(GEN8_RING_PDP_LDW(ring, i));
seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp);
}
}
@@ -2250,7 +2250,6 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring;
- struct drm_file *file;
int i;
if (INTEL_INFO(dev)->gen == 6)
@@ -2273,13 +2272,6 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
ppgtt->debug_dump(ppgtt, m);
}
- list_for_each_entry_reverse(file, &dev->filelist, lhead) {
- struct drm_i915_file_private *file_priv = file->driver_priv;
-
- seq_printf(m, "proc: %s\n",
- get_pid_task(file->pid, PIDTYPE_PID)->comm);
- idr_for_each(&file_priv->context_idr, per_file_ctx, m);
- }
seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
}
@@ -2288,6 +2280,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_file *file;
int ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
@@ -2299,10 +2292,26 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
else if (INTEL_INFO(dev)->gen >= 6)
gen6_ppgtt_info(m, dev);
+ list_for_each_entry_reverse(file, &dev->filelist, lhead) {
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct task_struct *task;
+
+ task = get_pid_task(file->pid, PIDTYPE_PID);
+ if (!task) {
+ ret = -ESRCH;
+ goto out_put;
+ }
+ seq_printf(m, "\nproc: %s\n", task->comm);
+ put_task_struct(task);
+ idr_for_each(&file_priv->context_idr, per_file_ctx,
+ (void *)(unsigned long)m);
+ }
+
+out_put:
intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex);
- return 0;
+ return ret;
}
static int count_irq_waiters(struct drm_i915_private *i915)
@@ -2372,6 +2381,147 @@ static int i915_llc(struct seq_file *m, void *data)
return 0;
}
+static int i915_guc_load_status_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_i915_private *dev_priv = node->minor->dev->dev_private;
+ struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+ u32 tmp, i;
+
+ if (!HAS_GUC_UCODE(dev_priv->dev))
+ return 0;
+
+ seq_printf(m, "GuC firmware status:\n");
+ seq_printf(m, "\tpath: %s\n",
+ guc_fw->guc_fw_path);
+ seq_printf(m, "\tfetch: %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+ seq_printf(m, "\tload: %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+ seq_printf(m, "\tversion wanted: %d.%d\n",
+ guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+ seq_printf(m, "\tversion found: %d.%d\n",
+ guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
+
+ tmp = I915_READ(GUC_STATUS);
+
+ seq_printf(m, "\nGuC status 0x%08x:\n", tmp);
+ seq_printf(m, "\tBootrom status = 0x%x\n",
+ (tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT);
+ seq_printf(m, "\tuKernel status = 0x%x\n",
+ (tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT);
+ seq_printf(m, "\tMIA Core status = 0x%x\n",
+ (tmp & GS_MIA_MASK) >> GS_MIA_SHIFT);
+ seq_puts(m, "\nScratch registers:\n");
+ for (i = 0; i < 16; i++)
+ seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i)));
+
+ return 0;
+}
+
+static void i915_guc_client_info(struct seq_file *m,
+ struct drm_i915_private *dev_priv,
+ struct i915_guc_client *client)
+{
+ struct intel_engine_cs *ring;
+ uint64_t tot = 0;
+ uint32_t i;
+
+ seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
+ client->priority, client->ctx_index, client->proc_desc_offset);
+ seq_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n",
+ client->doorbell_id, client->doorbell_offset, client->cookie);
+ seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
+ client->wq_size, client->wq_offset, client->wq_tail);
+
+ seq_printf(m, "\tFailed to queue: %u\n", client->q_fail);
+ seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
+ seq_printf(m, "\tLast submission result: %d\n", client->retcode);
+
+ for_each_ring(ring, dev_priv, i) {
+ seq_printf(m, "\tSubmissions: %llu %s\n",
+ client->submissions[i],
+ ring->name);
+ tot += client->submissions[i];
+ }
+ seq_printf(m, "\tTotal: %llu\n", tot);
+}
+
+static int i915_guc_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc guc;
+ struct i915_guc_client client = {};
+ struct intel_engine_cs *ring;
+ enum intel_ring_id i;
+ u64 total = 0;
+
+ if (!HAS_GUC_SCHED(dev_priv->dev))
+ return 0;
+
+ /* Take a local copy of the GuC data, so we can dump it at leisure */
+ spin_lock(&dev_priv->guc.host2guc_lock);
+ guc = dev_priv->guc;
+ if (guc.execbuf_client) {
+ spin_lock(&guc.execbuf_client->wq_lock);
+ client = *guc.execbuf_client;
+ spin_unlock(&guc.execbuf_client->wq_lock);
+ }
+ spin_unlock(&dev_priv->guc.host2guc_lock);
+
+ seq_printf(m, "GuC total action count: %llu\n", guc.action_count);
+ seq_printf(m, "GuC action failure count: %u\n", guc.action_fail);
+ seq_printf(m, "GuC last action command: 0x%x\n", guc.action_cmd);
+ seq_printf(m, "GuC last action status: 0x%x\n", guc.action_status);
+ seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
+
+ seq_printf(m, "\nGuC submissions:\n");
+ for_each_ring(ring, dev_priv, i) {
+ seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x %9d\n",
+ ring->name, guc.submissions[i],
+ guc.last_seqno[i], guc.last_seqno[i]);
+ total += guc.submissions[i];
+ }
+ seq_printf(m, "\t%s: %llu\n", "Total", total);
+
+ seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
+ i915_guc_client_info(m, dev_priv, &client);
+
+ /* Add more as required ... */
+
+ return 0;
+}
+
+static int i915_guc_log_dump(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *log_obj = dev_priv->guc.log_obj;
+ u32 *log;
+ int i = 0, pg;
+
+ if (!log_obj)
+ return 0;
+
+ for (pg = 0; pg < log_obj->base.size / PAGE_SIZE; pg++) {
+ log = kmap_atomic(i915_gem_object_get_page(log_obj, pg));
+
+ for (i = 0; i < PAGE_SIZE / sizeof(u32); i += 4)
+ seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ *(log + i), *(log + i + 1),
+ *(log + i + 2), *(log + i + 3));
+
+ kunmap_atomic(log);
+ }
+
+ seq_putc(m, '\n');
+
+ return 0;
+}
+
static int i915_edp_psr_status(struct seq_file *m, void *data)
{
struct drm_info_node *node = m->private;
@@ -2680,11 +2830,13 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
struct drm_device *dev = node->minor->dev;
struct drm_crtc *crtc = &intel_crtc->base;
struct intel_encoder *intel_encoder;
+ struct drm_plane_state *plane_state = crtc->primary->state;
+ struct drm_framebuffer *fb = plane_state->fb;
- if (crtc->primary->fb)
+ if (fb)
seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
- crtc->primary->fb->base.id, crtc->x, crtc->y,
- crtc->primary->fb->width, crtc->primary->fb->height);
+ fb->base.id, plane_state->src_x >> 16,
+ plane_state->src_y >> 16, fb->width, fb->height);
else
seq_puts(m, "\tprimary plane disabled\n");
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
@@ -2706,8 +2858,7 @@ static void intel_dp_info(struct seq_file *m,
struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
- seq_printf(m, "\taudio support: %s\n", intel_dp->has_audio ? "yes" :
- "no");
+ seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
if (intel_encoder->type == INTEL_OUTPUT_EDP)
intel_panel_info(m, &intel_connector->panel);
}
@@ -2718,8 +2869,7 @@ static void intel_hdmi_info(struct seq_file *m,
struct intel_encoder *intel_encoder = intel_connector->encoder;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
- seq_printf(m, "\taudio support: %s\n", intel_hdmi->has_audio ? "yes" :
- "no");
+ seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio));
}
static void intel_lvds_info(struct seq_file *m,
@@ -2769,7 +2919,7 @@ static bool cursor_active(struct drm_device *dev, int pipe)
u32 state;
if (IS_845G(dev) || IS_I865G(dev))
- state = I915_READ(_CURACNTR) & CURSOR_ENABLE;
+ state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
else
state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
@@ -3007,7 +3157,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
skl_ddb_entry_size(entry));
}
- entry = &ddb->cursor[pipe];
+ entry = &ddb->plane[pipe][PLANE_CURSOR];
seq_printf(m, " %-13s%8u%8u%8u\n", "Cursor", entry->start,
entry->end, skl_ddb_entry_size(entry));
}
@@ -4807,7 +4957,7 @@ static void cherryview_sseu_device_status(struct drm_device *dev,
struct sseu_dev_status *stat)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- const int ss_max = 2;
+ int ss_max = 2;
int ss;
u32 sig1[ss_max], sig2[ss_max];
@@ -4900,13 +5050,38 @@ static void gen9_sseu_device_status(struct drm_device *dev,
}
}
+static void broadwell_sseu_device_status(struct drm_device *dev,
+ struct sseu_dev_status *stat)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int s;
+ u32 slice_info = I915_READ(GEN8_GT_SLICE_INFO);
+
+ stat->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK);
+
+ if (stat->slice_total) {
+ stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
+ stat->subslice_total = stat->slice_total *
+ stat->subslice_per_slice;
+ stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
+ stat->eu_total = stat->eu_per_subslice * stat->subslice_total;
+
+ /* subtract fused off EU(s) from enabled slice(s) */
+ for (s = 0; s < stat->slice_total; s++) {
+ u8 subslice_7eu = INTEL_INFO(dev)->subslice_7eu[s];
+
+ stat->eu_total -= hweight8(subslice_7eu);
+ }
+ }
+}
+
static int i915_sseu_status(struct seq_file *m, void *unused)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct sseu_dev_status stat;
- if ((INTEL_INFO(dev)->gen < 8) || IS_BROADWELL(dev))
+ if (INTEL_INFO(dev)->gen < 8)
return -ENODEV;
seq_puts(m, "SSEU Device Info\n");
@@ -4931,6 +5106,8 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
memset(&stat, 0, sizeof(stat));
if (IS_CHERRYVIEW(dev)) {
cherryview_sseu_device_status(dev, &stat);
+ } else if (IS_BROADWELL(dev)) {
+ broadwell_sseu_device_status(dev, &stat);
} else if (INTEL_INFO(dev)->gen >= 9) {
gen9_sseu_device_status(dev, &stat);
}
@@ -5033,6 +5210,9 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
{"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS},
{"i915_gem_batch_pool", i915_gem_batch_pool_info, 0},
+ {"i915_guc_info", i915_guc_info, 0},
+ {"i915_guc_load_status", i915_guc_load_status_info, 0},
+ {"i915_guc_log_dump", i915_guc_log_dump, 0},
{"i915_frequency_info", i915_frequency_info, 0},
{"i915_hangcheck_info", i915_hangcheck_info, 0},
{"i915_drpc_info", i915_drpc_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ab37d1121be8..b4741d121a74 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -75,7 +75,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
value = 1;
break;
case I915_PARAM_NUM_FENCES_AVAIL:
- value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
+ value = dev_priv->num_fence_regs;
break;
case I915_PARAM_HAS_OVERLAY:
value = dev_priv->overlay ? 1 : 0;
@@ -183,35 +183,6 @@ static int i915_getparam(struct drm_device *dev, void *data,
return 0;
}
-static int i915_setparam(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- drm_i915_setparam_t *param = data;
-
- switch (param->param) {
- case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
- case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
- case I915_SETPARAM_ALLOW_BATCHBUFFER:
- /* Reject all old ums/dri params. */
- return -ENODEV;
-
- case I915_SETPARAM_NUM_USED_FENCES:
- if (param->value > dev_priv->num_fence_regs ||
- param->value < 0)
- return -EINVAL;
- /* Userspace can use first N regs */
- dev_priv->fence_reg_start = param->value;
- break;
- default:
- DRM_DEBUG_DRIVER("unknown parameter %d\n",
- param->param);
- return -EINVAL;
- }
-
- return 0;
-}
-
static int i915_get_bridge_dev(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -364,12 +335,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
/* i915 resume handler doesn't set to D0 */
pci_set_power_state(dev->pdev, PCI_D0);
- i915_resume_legacy(dev);
+ i915_resume_switcheroo(dev);
dev->switch_power_state = DRM_SWITCH_POWER_ON;
} else {
pr_err("switched off\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- i915_suspend_legacy(dev, pmm);
+ i915_suspend_switcheroo(dev, pmm);
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
}
}
@@ -435,6 +406,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
* working irqs for e.g. gmbus and dp aux transfers. */
intel_modeset_init(dev);
+ intel_guc_ucode_init(dev);
+
ret = i915_gem_init(dev);
if (ret)
goto cleanup_irq;
@@ -476,6 +449,7 @@ cleanup_gem:
i915_gem_context_fini(dev);
mutex_unlock(&dev->struct_mutex);
cleanup_irq:
+ intel_guc_ucode_fini(dev);
drm_irq_uninstall(dev);
cleanup_gem_stolen:
i915_gem_cleanup_stolen(dev);
@@ -623,17 +597,6 @@ static void gen9_sseu_info_init(struct drm_device *dev)
u32 fuse2, s_enable, ss_disable, eu_disable;
u8 eu_mask = 0xff;
- /*
- * BXT has a single slice. BXT also has at most 6 EU per subslice,
- * and therefore only the lowest 6 bits of the 8-bit EU disable
- * fields are valid.
- */
- if (IS_BROXTON(dev)) {
- s_max = 1;
- eu_max = 6;
- eu_mask = 0x3f;
- }
-
info = (struct intel_device_info *)&dev_priv->info;
fuse2 = I915_READ(GEN8_FUSE2);
s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >>
@@ -705,6 +668,82 @@ static void gen9_sseu_info_init(struct drm_device *dev)
info->has_eu_pg = (info->eu_per_subslice > 2);
}
+static void broadwell_sseu_info_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_device_info *info;
+ const int s_max = 3, ss_max = 3, eu_max = 8;
+ int s, ss;
+ u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
+
+ fuse2 = I915_READ(GEN8_FUSE2);
+ s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
+ ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
+
+ eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
+ eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
+ ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
+ (32 - GEN8_EU_DIS0_S1_SHIFT));
+ eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
+ ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
+ (32 - GEN8_EU_DIS1_S2_SHIFT));
+
+
+ info = (struct intel_device_info *)&dev_priv->info;
+ info->slice_total = hweight32(s_enable);
+
+ /*
+ * The subslice disable field is global, i.e. it applies
+ * to each of the enabled slices.
+ */
+ info->subslice_per_slice = ss_max - hweight32(ss_disable);
+ info->subslice_total = info->slice_total * info->subslice_per_slice;
+
+ /*
+ * Iterate through enabled slices and subslices to
+ * count the total enabled EU.
+ */
+ for (s = 0; s < s_max; s++) {
+ if (!(s_enable & (0x1 << s)))
+ /* skip disabled slice */
+ continue;
+
+ for (ss = 0; ss < ss_max; ss++) {
+ u32 n_disabled;
+
+ if (ss_disable & (0x1 << ss))
+ /* skip disabled subslice */
+ continue;
+
+ n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
+
+ /*
+ * Record which subslices have 7 EUs.
+ */
+ if (eu_max - n_disabled == 7)
+ info->subslice_7eu[s] |= 1 << ss;
+
+ info->eu_total += eu_max - n_disabled;
+ }
+ }
+
+ /*
+ * BDW is expected to always have a uniform distribution of EU across
+ * subslices with the exception that any one EU in any one subslice may
+ * be fused off for die recovery.
+ */
+ info->eu_per_subslice = info->subslice_total ?
+ DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
+
+ /*
+ * BDW supports slice power gating on devices with more than
+ * one slice.
+ */
+ info->has_slice_pg = (info->slice_total > 1);
+ info->has_subslice_pg = 0;
+ info->has_eu_pg = 0;
+}
+
/*
* Determine various intel_device_info fields at runtime.
*
@@ -775,6 +814,8 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
/* Initialize slice/subslice/EU info */
if (IS_CHERRYVIEW(dev))
cherryview_sseu_info_init(dev);
+ else if (IS_BROADWELL(dev))
+ broadwell_sseu_info_init(dev);
else if (INTEL_INFO(dev)->gen >= 9)
gen9_sseu_info_init(dev);
@@ -791,6 +832,24 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
info->has_eu_pg ? "y" : "n");
}
+static void intel_init_dpio(struct drm_i915_private *dev_priv)
+{
+ if (!IS_VALLEYVIEW(dev_priv))
+ return;
+
+ /*
+ * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
+ * CHV x1 PHY (DP/HDMI D)
+ * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
+ */
+ if (IS_CHERRYVIEW(dev_priv)) {
+ DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
+ DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
+ } else {
+ DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
+ }
+}
+
/**
* i915_driver_load - setup chip and create an initial config
* @dev: DRM device
@@ -832,6 +891,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
mutex_init(&dev_priv->sb_lock);
mutex_init(&dev_priv->modeset_restore_lock);
mutex_init(&dev_priv->csr_lock);
+ mutex_init(&dev_priv->av_mutex);
intel_pm_setup(dev);
@@ -971,8 +1031,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_setup_gmbus(dev);
intel_opregion_setup(dev);
- intel_setup_bios(dev);
-
i915_gem_load(dev);
/* On the 945G/GM, the chipset reports the MSI capability on the
@@ -991,6 +1049,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_device_info_runtime_init(dev);
+ intel_init_dpio(dev_priv);
+
if (INTEL_INFO(dev)->num_pipes) {
ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
if (ret)
@@ -1059,12 +1119,9 @@ out_freecsr:
put_bridge:
pci_dev_put(dev_priv->bridge_dev);
free_priv:
- if (dev_priv->requests)
- kmem_cache_destroy(dev_priv->requests);
- if (dev_priv->vmas)
- kmem_cache_destroy(dev_priv->vmas);
- if (dev_priv->objects)
- kmem_cache_destroy(dev_priv->objects);
+ kmem_cache_destroy(dev_priv->requests);
+ kmem_cache_destroy(dev_priv->vmas);
+ kmem_cache_destroy(dev_priv->objects);
kfree(dev_priv);
return ret;
}
@@ -1111,6 +1168,10 @@ int i915_driver_unload(struct drm_device *dev)
dev_priv->vbt.child_dev = NULL;
dev_priv->vbt.child_dev_num = 0;
}
+ kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
+ dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
+ kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
+ dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
vga_switcheroo_unregister_client(dev->pdev);
vga_client_register(dev->pdev, NULL, NULL, NULL);
@@ -1127,6 +1188,7 @@ int i915_driver_unload(struct drm_device *dev)
/* Flush any outstanding unpin_work. */
flush_workqueue(dev_priv->wq);
+ intel_guc_ucode_fini(dev);
mutex_lock(&dev->struct_mutex);
i915_gem_cleanup_ringbuffer(dev);
i915_gem_context_fini(dev);
@@ -1150,13 +1212,9 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->regs != NULL)
pci_iounmap(dev->pdev, dev_priv->regs);
- if (dev_priv->requests)
- kmem_cache_destroy(dev_priv->requests);
- if (dev_priv->vmas)
- kmem_cache_destroy(dev_priv->vmas);
- if (dev_priv->objects)
- kmem_cache_destroy(dev_priv->objects);
-
+ kmem_cache_destroy(dev_priv->requests);
+ kmem_cache_destroy(dev_priv->vmas);
+ kmem_cache_destroy(dev_priv->objects);
pci_dev_put(dev_priv->bridge_dev);
kfree(dev_priv);
@@ -1226,7 +1284,7 @@ const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(I915_SETPARAM, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -1236,41 +1294,41 @@ const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
+ DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
};
int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index ab64d68388f2..760e0ce4aa26 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -362,6 +362,7 @@ static const struct intel_device_info intel_skylake_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.has_llc = 1,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -374,6 +375,7 @@ static const struct intel_device_info intel_skylake_gt3_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
.has_llc = 1,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -386,6 +388,7 @@ static const struct intel_device_info intel_broxton_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.num_pipes = 3,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -440,6 +443,34 @@ static const struct pci_device_id pciidlist[] = { /* aka */
MODULE_DEVICE_TABLE(pci, pciidlist);
+static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
+{
+ enum intel_pch ret = PCH_NOP;
+
+ /*
+ * In a virtualized passthrough environment we can be in a
+ * setup where the ISA bridge is not able to be passed through.
+ * In this case, a south bridge can be emulated and we have to
+ * make an educated guess as to which PCH is really there.
+ */
+
+ if (IS_GEN5(dev)) {
+ ret = PCH_IBX;
+ DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n");
+ } else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
+ ret = PCH_CPT;
+ DRM_DEBUG_KMS("Assuming CouarPoint PCH\n");
+ } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ ret = PCH_LPT;
+ DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
+ } else if (IS_SKYLAKE(dev)) {
+ ret = PCH_SPT;
+ DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
+ }
+
+ return ret;
+}
+
void intel_detect_pch(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -500,6 +531,8 @@ void intel_detect_pch(struct drm_device *dev)
dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
WARN_ON(!IS_SKYLAKE(dev));
+ } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE) {
+ dev_priv->pch_type = intel_virt_detect_pch(dev);
} else
continue;
@@ -605,6 +638,8 @@ static int i915_drm_suspend(struct drm_device *dev)
return error;
}
+ intel_guc_suspend(dev);
+
intel_suspend_gt_powersave(dev);
/*
@@ -679,7 +714,7 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
return 0;
}
-int i915_suspend_legacy(struct drm_device *dev, pm_message_t state)
+int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state)
{
int error;
@@ -734,6 +769,8 @@ static int i915_drm_resume(struct drm_device *dev)
}
mutex_unlock(&dev->struct_mutex);
+ intel_guc_resume(dev);
+
intel_modeset_init_hw(dev);
spin_lock_irq(&dev_priv->irq_lock);
@@ -812,7 +849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
return ret;
}
-int i915_resume_legacy(struct drm_device *dev)
+int i915_resume_switcheroo(struct drm_device *dev)
{
int ret;
@@ -1018,12 +1055,6 @@ static int skl_suspend_complete(struct drm_i915_private *dev_priv)
{
/* Enabling DC6 is not a hard requirement to enter runtime D3 */
- /*
- * This is to ensure that CSR isn't identified as loaded before
- * CSR-loading program is called during runtime-resume.
- */
- intel_csr_load_status_set(dev_priv, FW_UNINITIALIZED);
-
skl_uninit_cdclk(dev_priv);
return 0;
@@ -1117,7 +1148,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
s->gfx_pend_tlb1 = I915_READ(GEN7_GFX_PEND_TLB1);
for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
- s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
+ s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS(i));
s->media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
s->gfx_max_req_count = I915_READ(GEN7_GFX_MAX_REQ_COUNT);
@@ -1161,7 +1192,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
s->pm_ier = I915_READ(GEN6_PMIER);
for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
- s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
+ s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH(i));
/* GT SA CZ domain, 0x100000-0x138124 */
s->tilectl = I915_READ(TILECTL);
@@ -1199,7 +1230,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
I915_WRITE(GEN7_GFX_PEND_TLB1, s->gfx_pend_tlb1);
for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
- I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
+ I915_WRITE(GEN7_LRA_LIMITS(i), s->lra_limits[i]);
I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count);
@@ -1243,7 +1274,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_PMIER, s->pm_ier);
for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
- I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
+ I915_WRITE(GEN7_GT_SCRATCH(i), s->gt_scratch[i]);
/* GT SA CZ domain, 0x100000-0x138124 */
I915_WRITE(TILECTL, s->tilectl);
@@ -1473,6 +1504,8 @@ static int intel_runtime_suspend(struct device *device)
i915_gem_release_all_mmaps(dev_priv);
mutex_unlock(&dev->struct_mutex);
+ intel_guc_suspend(dev);
+
intel_suspend_gt_powersave(dev);
intel_runtime_pm_disable_interrupts(dev_priv);
@@ -1532,6 +1565,8 @@ static int intel_runtime_resume(struct device *device)
intel_opregion_notify_adapter(dev, PCI_D0);
dev_priv->pm.suspended = false;
+ intel_guc_resume(dev);
+
if (IS_GEN6(dev_priv))
intel_init_pch_refclk(dev);
@@ -1552,6 +1587,15 @@ static int intel_runtime_resume(struct device *device)
gen6_update_ring_freq(dev);
intel_runtime_pm_enable_interrupts(dev_priv);
+
+ /*
+ * On VLV/CHV display interrupts are part of the display
+ * power well, so hpd is reinitialized from there. For
+ * everyone else do it here.
+ */
+ if (!IS_VALLEYVIEW(dev_priv))
+ intel_hpd_init(dev_priv);
+
intel_enable_gt_powersave(dev);
if (ret)
@@ -1649,7 +1693,7 @@ static struct drm_driver driver = {
*/
.driver_features =
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
- DRIVER_RENDER,
+ DRIVER_RENDER | DRIVER_MODESET,
.load = i915_driver_load,
.unload = i915_driver_unload,
.open = i915_driver_open,
@@ -1658,10 +1702,6 @@ static struct drm_driver driver = {
.postclose = i915_driver_postclose,
.set_busid = drm_pci_set_busid,
- /* Used in place of i915_pm_ops for non-DRIVER_MODESET */
- .suspend = i915_suspend_legacy,
- .resume = i915_resume_legacy,
-
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = i915_debugfs_init,
.debugfs_cleanup = i915_debugfs_cleanup,
@@ -1704,7 +1744,6 @@ static int __init i915_init(void)
* either the i915.modeset prarameter or by the
* vga_text_mode_force boot option.
*/
- driver.driver_features |= DRIVER_MODESET;
if (i915.modeset == 0)
driver.driver_features &= ~DRIVER_MODESET;
@@ -1715,18 +1754,12 @@ static int __init i915_init(void)
#endif
if (!(driver.driver_features & DRIVER_MODESET)) {
- driver.get_vblank_timestamp = NULL;
/* Silently fail loading to not upset userspace. */
DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
return 0;
}
- /*
- * FIXME: Note that we're lying to the DRM core here so that we can get access
- * to the atomic ioctl and the atomic properties. Only plane operations on
- * a single CRTC will actually work.
- */
- if (driver.driver_features & DRIVER_MODESET)
+ if (i915.nuclear_pageflip)
driver.driver_features |= DRIVER_ATOMIC;
return drm_pci_init(&driver, &i915_pci_driver);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e1db8de52851..95bb27de774f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -50,13 +50,14 @@
#include <linux/intel-iommu.h>
#include <linux/kref.h>
#include <linux/pm_qos.h>
+#include "intel_guc.h"
/* General customization:
*/
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20150731"
+#define DRIVER_DATE "20151010"
#undef WARN_ON
/* Many gcc seem to no see through this and fall over :( */
@@ -67,11 +68,11 @@
BUILD_BUG_ON(__i915_warn_cond); \
WARN(__i915_warn_cond, "WARN_ON(" #x ")"); })
#else
-#define WARN_ON(x) WARN((x), "WARN_ON(" #x ")")
+#define WARN_ON(x) WARN((x), "WARN_ON(%s)", #x )
#endif
#undef WARN_ON_ONCE
-#define WARN_ON_ONCE(x) WARN_ONCE((x), "WARN_ON_ONCE(" #x ")")
+#define WARN_ON_ONCE(x) WARN_ONCE((x), "WARN_ON_ONCE(%s)", #x )
#define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \
(long) (x), __func__);
@@ -105,6 +106,11 @@
unlikely(__ret_warn_on); \
})
+static inline const char *yesno(bool v)
+{
+ return v ? "yes" : "no";
+}
+
enum pipe {
INVALID_PIPE = -1,
PIPE_A = 0,
@@ -125,17 +131,17 @@ enum transcoder {
#define transcoder_name(t) ((t) + 'A')
/*
- * This is the maximum (across all platforms) number of planes (primary +
- * sprites) that can be active at the same time on one pipe.
- *
- * This value doesn't count the cursor plane.
+ * I915_MAX_PLANES in the enum below is the maximum (across all platforms)
+ * number of planes per CRTC. Not all platforms really have this many planes,
+ * which means some arrays of size I915_MAX_PLANES may have unused entries
+ * between the topmost sprite plane and the cursor plane.
*/
-#define I915_MAX_PLANES 4
-
enum plane {
PLANE_A = 0,
PLANE_B,
PLANE_C,
+ PLANE_CURSOR,
+ I915_MAX_PLANES,
};
#define plane_name(p) ((p) + 'A')
@@ -345,6 +351,8 @@ enum intel_dpll_id {
/* hsw/bdw */
DPLL_ID_WRPLL1 = 0,
DPLL_ID_WRPLL2 = 1,
+ DPLL_ID_SPLL = 2,
+
/* skl */
DPLL_ID_SKL_DPLL1 = 0,
DPLL_ID_SKL_DPLL2 = 1,
@@ -361,6 +369,7 @@ struct intel_dpll_hw_state {
/* hsw, bdw */
uint32_t wrpll;
+ uint32_t spll;
/* skl */
/*
@@ -444,14 +453,14 @@ struct opregion_swsci;
struct opregion_asle;
struct intel_opregion {
- struct opregion_header __iomem *header;
- struct opregion_acpi __iomem *acpi;
- struct opregion_swsci __iomem *swsci;
+ struct opregion_header *header;
+ struct opregion_acpi *acpi;
+ struct opregion_swsci *swsci;
u32 swsci_gbda_sub_functions;
u32 swsci_sbcb_sub_functions;
- struct opregion_asle __iomem *asle;
- void __iomem *vbt;
- u32 __iomem *lid_state;
+ struct opregion_asle *asle;
+ void *vbt;
+ u32 *lid_state;
struct work_struct asle_work;
};
#define OPREGION_SIZE (8*1024)
@@ -549,7 +558,7 @@ struct drm_i915_error_state {
struct drm_i915_error_object {
int page_count;
- u32 gtt_offset;
+ u64 gtt_offset;
u32 *pages[0];
} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
@@ -575,7 +584,7 @@ struct drm_i915_error_state {
u32 size;
u32 name;
u32 rseqno[I915_NUM_RINGS], wseqno;
- u32 gtt_offset;
+ u64 gtt_offset;
u32 read_domains;
u32 write_domain;
s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
@@ -640,7 +649,7 @@ struct drm_i915_display_funcs {
void (*crtc_disable)(struct drm_crtc *crtc);
void (*audio_codec_enable)(struct drm_connector *connector,
struct intel_encoder *encoder,
- struct drm_display_mode *mode);
+ const struct drm_display_mode *adjusted_mode);
void (*audio_codec_disable)(struct intel_encoder *encoder);
void (*fdi_link_train)(struct drm_crtc *crtc);
void (*init_clock_gating)(struct drm_device *dev);
@@ -658,13 +667,6 @@ struct drm_i915_display_funcs {
/* render clock increase/decrease */
/* display clock increase/decrease */
/* pll clock increase/decrease */
-
- int (*setup_backlight)(struct intel_connector *connector, enum pipe pipe);
- uint32_t (*get_backlight)(struct intel_connector *connector);
- void (*set_backlight)(struct intel_connector *connector,
- uint32_t level);
- void (*disable_backlight)(struct intel_connector *connector);
- void (*enable_backlight)(struct intel_connector *connector);
};
enum forcewake_domain_id {
@@ -882,7 +884,6 @@ struct intel_context {
} legacy_hw_ctx;
/* Execlists */
- bool rcs_initialized;
struct {
struct drm_i915_gem_object *state;
struct intel_ringbuffer *ringbuf;
@@ -941,6 +942,9 @@ struct i915_fbc {
FBC_CHIP_DEFAULT, /* disabled by default on this chip */
FBC_ROTATION, /* rotation is not supported */
FBC_IN_DBG_MASTER, /* kernel debugger is active */
+ FBC_BAD_STRIDE, /* stride is not supported */
+ FBC_PIXEL_RATE, /* pixel rate is too big */
+ FBC_PIXEL_FORMAT /* pixel format is invalid */
} no_fbc_reason;
bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
@@ -1034,7 +1038,7 @@ struct i915_suspend_saved_registers {
u32 saveMI_ARB_STATE;
u32 saveSWF0[16];
u32 saveSWF1[16];
- u32 saveSWF2[3];
+ u32 saveSWF3[3];
uint64_t saveFENCE[I915_MAX_NUM_FENCES];
u32 savePCH_PORT_HOTPLUG;
u16 saveGCDGMBUS;
@@ -1136,7 +1140,6 @@ struct intel_gen6_power_mgmt {
u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */
u8 rp1_freq; /* "less than" RP0 power/freqency */
u8 rp0_freq; /* Non-overclocked max frequency. */
- u32 cz_freq;
u8 up_threshold; /* Current %busy required to uplock */
u8 down_threshold; /* Current %busy required to downclock */
@@ -1578,8 +1581,7 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
struct skl_ddb_allocation {
struct skl_ddb_entry pipe[I915_MAX_PIPES];
struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */
- struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* y-plane */
- struct skl_ddb_entry cursor[I915_MAX_PIPES];
+ struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES];
};
struct skl_wm_values {
@@ -1587,18 +1589,13 @@ struct skl_wm_values {
struct skl_ddb_allocation ddb;
uint32_t wm_linetime[I915_MAX_PIPES];
uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8];
- uint32_t cursor[I915_MAX_PIPES][8];
uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES];
- uint32_t cursor_trans[I915_MAX_PIPES];
};
struct skl_wm_level {
bool plane_en[I915_MAX_PLANES];
- bool cursor_en;
uint16_t plane_res_b[I915_MAX_PLANES];
uint8_t plane_res_l[I915_MAX_PLANES];
- uint16_t cursor_res_b;
- uint8_t cursor_res_l;
};
/*
@@ -1693,7 +1690,7 @@ struct i915_execbuffer_params {
struct drm_file *file;
uint32_t dispatch_flags;
uint32_t args_batch_start_offset;
- uint32_t batch_obj_vm_offset;
+ uint64_t batch_obj_vm_offset;
struct intel_engine_cs *ring;
struct drm_i915_gem_object *batch_obj;
struct intel_context *ctx;
@@ -1716,6 +1713,8 @@ struct drm_i915_private {
struct i915_virtual_gpu vgpu;
+ struct intel_guc guc;
+
struct intel_csr csr;
/* Display CSR-related protection */
@@ -1790,13 +1789,14 @@ struct drm_i915_private {
struct mutex pps_mutex;
struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
- int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
unsigned int fsb_freq, mem_freq, is_ddr3;
unsigned int skl_boot_cdclk;
unsigned int cdclk_freq, max_cdclk_freq;
+ unsigned int max_dotclk_freq;
unsigned int hpll_freq;
+ unsigned int czclk_freq;
/**
* wq - Driver workqueue for GEM.
@@ -1885,6 +1885,11 @@ struct drm_i915_private {
/* hda/i915 audio component */
struct i915_audio_component *audio_component;
bool audio_component_registered;
+ /**
+ * av_mutex - mutex for audio/video sync
+ *
+ */
+ struct mutex av_mutex;
uint32_t hw_context_size;
struct list_head context_list;
@@ -1947,6 +1952,9 @@ struct drm_i915_private {
bool edp_low_vswing;
+ /* perform PHY state sanity checks? */
+ bool chv_phy_assert[2];
+
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
@@ -1963,6 +1971,11 @@ static inline struct drm_i915_private *dev_to_i915(struct device *dev)
return to_i915(dev_get_drvdata(dev));
}
+static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
+{
+ return container_of(guc, struct drm_i915_private, guc);
+}
+
/* Iterate over initialised rings */
#define for_each_ring(ring__, dev_priv__, i__) \
for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
@@ -1999,25 +2012,26 @@ struct drm_i915_gem_object_ops {
/*
* Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is
- * considered to be the frontbuffer for the given plane interface-vise. This
+ * considered to be the frontbuffer for the given plane interface-wise. This
* doesn't mean that the hw necessarily already scans it out, but that any
* rendering (by the cpu or gpu) will land in the frontbuffer eventually.
*
* We have one bit per pipe and per scanout plane type.
*/
-#define INTEL_FRONTBUFFER_BITS_PER_PIPE 4
+#define INTEL_MAX_SPRITE_BITS_PER_PIPE 5
+#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8
#define INTEL_FRONTBUFFER_BITS \
(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES)
#define INTEL_FRONTBUFFER_PRIMARY(pipe) \
(1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
#define INTEL_FRONTBUFFER_CURSOR(pipe) \
- (1 << (1 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
-#define INTEL_FRONTBUFFER_SPRITE(pipe) \
- (1 << (2 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+ (1 << (1 + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_SPRITE(pipe, plane) \
+ (1 << (2 + plane + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
#define INTEL_FRONTBUFFER_OVERLAY(pipe) \
- (1 << (3 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+ (1 << (2 + INTEL_MAX_SPRITE_BITS_PER_PIPE + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \
- (0xf << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
+ (0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
struct drm_i915_gem_object {
struct drm_gem_object base;
@@ -2475,6 +2489,11 @@ struct drm_i915_cmd_table {
#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \
INTEL_DEVID(dev) == 0x1915 || \
INTEL_DEVID(dev) == 0x191E)
+#define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \
+ (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
+#define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \
+ (INTEL_DEVID(dev) & 0x00F0) == 0x0030)
+
#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
#define SKL_REVID_A0 (0x0)
@@ -2486,7 +2505,7 @@ struct drm_i915_cmd_table {
#define BXT_REVID_A0 (0x0)
#define BXT_REVID_B0 (0x3)
-#define BXT_REVID_C0 (0x6)
+#define BXT_REVID_C0 (0x9)
/*
* The genX designation typically refers to the render engine, so render
@@ -2520,7 +2539,8 @@ struct drm_i915_cmd_table {
#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 8)
#define USES_PPGTT(dev) (i915.enable_ppgtt)
-#define USES_FULL_PPGTT(dev) (i915.enable_ppgtt == 2)
+#define USES_FULL_PPGTT(dev) (i915.enable_ppgtt >= 2)
+#define USES_FULL_48BIT_PPGTT(dev) (i915.enable_ppgtt == 3)
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
@@ -2564,7 +2584,10 @@ struct drm_i915_cmd_table {
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
-#define HAS_CSR(dev) (IS_SKYLAKE(dev))
+#define HAS_CSR(dev) (IS_GEN9(dev))
+
+#define HAS_GUC_UCODE(dev) (IS_GEN9(dev))
+#define HAS_GUC_SCHED(dev) (IS_GEN9(dev))
#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
INTEL_INFO(dev)->gen >= 8)
@@ -2580,10 +2603,12 @@ struct drm_i915_cmd_table {
#define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE 0x9c00
#define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100
#define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00
+#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
#define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
#define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT)
#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
+#define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
@@ -2603,8 +2628,8 @@ struct drm_i915_cmd_table {
extern const struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl;
-extern int i915_suspend_legacy(struct drm_device *dev, pm_message_t state);
-extern int i915_resume_legacy(struct drm_device *dev);
+extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state);
+extern int i915_resume_switcheroo(struct drm_device *dev);
/* i915_params.c */
struct i915_params {
@@ -2637,6 +2662,7 @@ struct i915_params {
int use_mmio_flip;
int mmio_debug;
bool verbose_state_checks;
+ bool nuclear_pageflip;
int edp_vswing;
};
extern struct i915_params i915 __read_mostly;
@@ -2716,6 +2742,9 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
+void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
+ uint32_t mask,
+ uint32_t bits);
void
ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask);
void
@@ -2783,8 +2812,6 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
size_t size);
struct drm_i915_gem_object *i915_gem_object_create_from_data(
struct drm_device *dev, const void *data, size_t size);
-void i915_init_vm(struct drm_i915_private *dev_priv,
- struct i915_address_space *vm);
void i915_gem_free_object(struct drm_gem_object *obj);
void i915_gem_vma_destroy(struct i915_vma *vma);
@@ -2795,6 +2822,8 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
#define PIN_OFFSET_BIAS (1<<3)
#define PIN_USER (1<<4)
#define PIN_UPDATE (1<<5)
+#define PIN_ZONE_4G (1<<6)
+#define PIN_HIGH (1<<7)
#define PIN_OFFSET_MASK (~4095)
int __must_check
i915_gem_object_pin(struct drm_i915_gem_object *obj,
@@ -2810,6 +2839,11 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
u32 flags);
int __must_check i915_vma_unbind(struct i915_vma *vma);
+/*
+ * BEWARE: Do not use the function below unless you can _absolutely_
+ * _guarantee_ VMA in question is _not in use_ anywhere.
+ */
+int __must_check __i915_vma_unbind_no_wait(struct i915_vma *vma);
int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
@@ -2986,13 +3020,11 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gem_obj, int flags);
-unsigned long
-i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
- const struct i915_ggtt_view *view);
-unsigned long
-i915_gem_obj_offset(struct drm_i915_gem_object *o,
- struct i915_address_space *vm);
-static inline unsigned long
+u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
+ const struct i915_ggtt_view *view);
+u64 i915_gem_obj_offset(struct drm_i915_gem_object *o,
+ struct i915_address_space *vm);
+static inline u64
i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *o)
{
return i915_gem_obj_ggtt_offset_view(o, &i915_ggtt_view_normal);
@@ -3140,7 +3172,6 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
unsigned long end,
unsigned flags);
int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
-int i915_gem_evict_everything(struct drm_device *dev);
/* belongs in i915_gem_gtt.h */
static inline void i915_gem_chipset_flush(struct drm_device *dev)
@@ -3153,6 +3184,10 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev)
int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node, u64 size,
unsigned alignment);
+int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
+ struct drm_mm_node *node, u64 size,
+ unsigned alignment, u64 start,
+ u64 end);
void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node);
int i915_gem_init_stolen(struct drm_device *dev);
@@ -3167,11 +3202,12 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
/* i915_gem_shrinker.c */
unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
- long target,
+ unsigned long target,
unsigned flags);
#define I915_SHRINK_PURGEABLE 0x1
#define I915_SHRINK_UNBOUND 0x2
#define I915_SHRINK_BOUND 0x4
+#define I915_SHRINK_ACTIVE 0x8
unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
void i915_gem_shrinker_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4d631a946481..91bb1fc27420 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1005,12 +1005,14 @@ out:
if (!needs_clflush_after &&
obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
if (i915_gem_clflush_object(obj, obj->pin_display))
- i915_gem_chipset_flush(dev);
+ needs_clflush_after = true;
}
}
if (needs_clflush_after)
i915_gem_chipset_flush(dev);
+ else
+ obj->cache_dirty = true;
intel_fb_obj_flush(obj, false, ORIGIN_CPU);
return ret;
@@ -1711,8 +1713,8 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
/**
* i915_gem_fault - fault a page into the GTT
- * vma: VMA in question
- * vmf: fault info
+ * @vma: VMA in question
+ * @vmf: fault info
*
* The fault handler is set up by drm_gem_mmap() when a object is GTT mapped
* from userspace. The fault handler takes care of binding the object to
@@ -2214,9 +2216,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
* Fail silently without starting the shrinker
*/
mapping = file_inode(obj->base.filp)->i_mapping;
- gfp = mapping_gfp_mask(mapping);
- gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
- gfp &= ~(__GFP_IO | __GFP_WAIT);
+ gfp = mapping_gfp_constraint(mapping, ~(__GFP_IO | __GFP_RECLAIM));
+ gfp |= __GFP_NORETRY | __GFP_NOWARN;
sg = st->sgl;
st->nents = 0;
for (i = 0; i < page_count; i++) {
@@ -3206,7 +3207,7 @@ static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
old_write_domain);
}
-int i915_vma_unbind(struct i915_vma *vma)
+static int __i915_vma_unbind(struct i915_vma *vma, bool wait)
{
struct drm_i915_gem_object *obj = vma->obj;
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
@@ -3225,13 +3226,11 @@ int i915_vma_unbind(struct i915_vma *vma)
BUG_ON(obj->pages == NULL);
- ret = i915_gem_object_wait_rendering(obj, false);
- if (ret)
- return ret;
- /* Continue on if we fail due to EIO, the GPU is hung so we
- * should be safe and we need to cleanup or else we might
- * cause memory corruption through use-after-free.
- */
+ if (wait) {
+ ret = i915_gem_object_wait_rendering(obj, false);
+ if (ret)
+ return ret;
+ }
if (i915_is_ggtt(vma->vm) &&
vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
@@ -3276,6 +3275,16 @@ int i915_vma_unbind(struct i915_vma *vma)
return 0;
}
+int i915_vma_unbind(struct i915_vma *vma)
+{
+ return __i915_vma_unbind(vma, true);
+}
+
+int __i915_vma_unbind_no_wait(struct i915_vma *vma)
+{
+ return __i915_vma_unbind(vma, false);
+}
+
int i915_gpu_idle(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3355,11 +3364,10 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
{
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 size, fence_size, fence_alignment, unfenced_alignment;
- u64 start =
- flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
- u64 end =
- flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total;
+ u32 fence_alignment, unfenced_alignment;
+ u32 search_flag, alloc_flag;
+ u64 start, end;
+ u64 size, fence_size;
struct i915_vma *vma;
int ret;
@@ -3399,6 +3407,13 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
size = flags & PIN_MAPPABLE ? fence_size : obj->base.size;
}
+ start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
+ end = vm->total;
+ if (flags & PIN_MAPPABLE)
+ end = min_t(u64, end, dev_priv->gtt.mappable_end);
+ if (flags & PIN_ZONE_4G)
+ end = min_t(u64, end, (1ULL << 32));
+
if (alignment == 0)
alignment = flags & PIN_MAPPABLE ? fence_alignment :
unfenced_alignment;
@@ -3414,7 +3429,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
* attempt to find space.
*/
if (size > end) {
- DRM_DEBUG("Attempting to bind an object (view type=%u) larger than the aperture: size=%u > %s aperture=%llu\n",
+ DRM_DEBUG("Attempting to bind an object (view type=%u) larger than the aperture: size=%llu > %s aperture=%llu\n",
ggtt_view ? ggtt_view->type : 0,
size,
flags & PIN_MAPPABLE ? "mappable" : "total",
@@ -3434,13 +3449,21 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
if (IS_ERR(vma))
goto err_unpin;
+ if (flags & PIN_HIGH) {
+ search_flag = DRM_MM_SEARCH_BELOW;
+ alloc_flag = DRM_MM_CREATE_TOP;
+ } else {
+ search_flag = DRM_MM_SEARCH_DEFAULT;
+ alloc_flag = DRM_MM_CREATE_DEFAULT;
+ }
+
search_free:
ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
size, alignment,
obj->cache_level,
start, end,
- DRM_MM_SEARCH_DEFAULT,
- DRM_MM_CREATE_DEFAULT);
+ search_flag,
+ alloc_flag);
if (ret) {
ret = i915_gem_evict_something(dev, vm, size, alignment,
obj->cache_level,
@@ -3633,59 +3656,117 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
return 0;
}
+/**
+ * Changes the cache-level of an object across all VMA.
+ *
+ * After this function returns, the object will be in the new cache-level
+ * across all GTT and the contents of the backing storage will be coherent,
+ * with respect to the new cache-level. In order to keep the backing storage
+ * coherent for all users, we only allow a single cache level to be set
+ * globally on the object and prevent it from being changed whilst the
+ * hardware is reading from the object. That is if the object is currently
+ * on the scanout it will be set to uncached (or equivalent display
+ * cache coherency) and all non-MOCS GPU access will also be uncached so
+ * that all direct access to the scanout remains coherent.
+ */
int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level)
{
struct drm_device *dev = obj->base.dev;
struct i915_vma *vma, *next;
- int ret;
+ bool bound = false;
+ int ret = 0;
if (obj->cache_level == cache_level)
- return 0;
-
- if (i915_gem_obj_is_pinned(obj)) {
- DRM_DEBUG("can not change the cache level of pinned objects\n");
- return -EBUSY;
- }
+ goto out;
+ /* Inspect the list of currently bound VMA and unbind any that would
+ * be invalid given the new cache-level. This is principally to
+ * catch the issue of the CS prefetch crossing page boundaries and
+ * reading an invalid PTE on older architectures.
+ */
list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) {
+ if (!drm_mm_node_allocated(&vma->node))
+ continue;
+
+ if (vma->pin_count) {
+ DRM_DEBUG("can not change the cache level of pinned objects\n");
+ return -EBUSY;
+ }
+
if (!i915_gem_valid_gtt_space(vma, cache_level)) {
ret = i915_vma_unbind(vma);
if (ret)
return ret;
- }
+ } else
+ bound = true;
}
- if (i915_gem_obj_bound_any(obj)) {
+ /* We can reuse the existing drm_mm nodes but need to change the
+ * cache-level on the PTE. We could simply unbind them all and
+ * rebind with the correct cache-level on next use. However since
+ * we already have a valid slot, dma mapping, pages etc, we may as
+ * rewrite the PTE in the belief that doing so tramples upon less
+ * state and so involves less work.
+ */
+ if (bound) {
+ /* Before we change the PTE, the GPU must not be accessing it.
+ * If we wait upon the object, we know that all the bound
+ * VMA are no longer active.
+ */
ret = i915_gem_object_wait_rendering(obj, false);
if (ret)
return ret;
- i915_gem_object_finish_gtt(obj);
-
- /* Before SandyBridge, you could not use tiling or fence
- * registers with snooped memory, so relinquish any fences
- * currently pointing to our region in the aperture.
- */
- if (INTEL_INFO(dev)->gen < 6) {
+ if (!HAS_LLC(dev) && cache_level != I915_CACHE_NONE) {
+ /* Access to snoopable pages through the GTT is
+ * incoherent and on some machines causes a hard
+ * lockup. Relinquish the CPU mmaping to force
+ * userspace to refault in the pages and we can
+ * then double check if the GTT mapping is still
+ * valid for that pointer access.
+ */
+ i915_gem_release_mmap(obj);
+
+ /* As we no longer need a fence for GTT access,
+ * we can relinquish it now (and so prevent having
+ * to steal a fence from someone else on the next
+ * fence request). Note GPU activity would have
+ * dropped the fence as all snoopable access is
+ * supposed to be linear.
+ */
ret = i915_gem_object_put_fence(obj);
if (ret)
return ret;
+ } else {
+ /* We either have incoherent backing store and
+ * so no GTT access or the architecture is fully
+ * coherent. In such cases, existing GTT mmaps
+ * ignore the cache bit in the PTE and we can
+ * rewrite it without confusing the GPU or having
+ * to force userspace to fault back in its mmaps.
+ */
}
- list_for_each_entry(vma, &obj->vma_list, vma_link)
- if (drm_mm_node_allocated(&vma->node)) {
- ret = i915_vma_bind(vma, cache_level,
- PIN_UPDATE);
- if (ret)
- return ret;
- }
+ list_for_each_entry(vma, &obj->vma_list, vma_link) {
+ if (!drm_mm_node_allocated(&vma->node))
+ continue;
+
+ ret = i915_vma_bind(vma, cache_level, PIN_UPDATE);
+ if (ret)
+ return ret;
+ }
}
list_for_each_entry(vma, &obj->vma_list, vma_link)
vma->node.color = cache_level;
obj->cache_level = cache_level;
+out:
+ /* Flush the dirty CPU caches to the backing storage so that the
+ * object is now coherent at its new cache level (with respect
+ * to the access domain).
+ */
if (obj->cache_dirty &&
obj->base.write_domain != I915_GEM_DOMAIN_CPU &&
cpu_write_needs_clflush(obj)) {
@@ -3728,6 +3809,7 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_caching *args = data;
struct drm_i915_gem_object *obj;
enum i915_cache_level level;
@@ -3738,6 +3820,15 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
level = I915_CACHE_NONE;
break;
case I915_CACHING_CACHED:
+ /*
+ * Due to a HW issue on BXT A stepping, GPU stores via a
+ * snooped mapping may leave stale data in a corresponding CPU
+ * cacheline, whereas normally such cachelines would get
+ * invalidated.
+ */
+ if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)
+ return -ENODEV;
+
level = I915_CACHE_LLC;
break;
case I915_CACHING_DISPLAY:
@@ -3747,9 +3838,11 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
+ intel_runtime_pm_get(dev_priv);
+
ret = i915_mutex_lock_interruptible(dev);
if (ret)
- return ret;
+ goto rpm_put;
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
if (&obj->base == NULL) {
@@ -3762,6 +3855,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
drm_gem_object_unreference(&obj->base);
unlock:
mutex_unlock(&dev->struct_mutex);
+rpm_put:
+ intel_runtime_pm_put(dev_priv);
+
return ret;
}
@@ -4011,15 +4107,13 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
return -EBUSY;
if (i915_vma_misplaced(vma, alignment, flags)) {
- unsigned long offset;
- offset = ggtt_view ? i915_gem_obj_ggtt_offset_view(obj, ggtt_view) :
- i915_gem_obj_offset(obj, vm);
WARN(vma->pin_count,
"bo is already pinned in %s with incorrect alignment:"
- " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
+ " offset=%08x %08x, req.alignment=%x, req.map_and_fenceable=%d,"
" obj->map_and_fenceable=%d\n",
ggtt_view ? "ggtt" : "ppgtt",
- offset,
+ upper_32_bits(vma->node.start),
+ lower_32_bits(vma->node.start),
alignment,
!!(flags & PIN_MAPPABLE),
obj->map_and_fenceable);
@@ -4526,22 +4620,6 @@ void i915_gem_init_swizzling(struct drm_device *dev)
BUG();
}
-static bool
-intel_enable_blt(struct drm_device *dev)
-{
- if (!HAS_BLT(dev))
- return false;
-
- /* The blitter was dysfunctional on early prototypes */
- if (IS_GEN6(dev) && dev->pdev->revision < 8) {
- DRM_INFO("BLT not supported on this pre-production hardware;"
- " graphics performance will be degraded.\n");
- return false;
- }
-
- return true;
-}
-
static void init_unused_ring(struct drm_device *dev, u32 base)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4584,7 +4662,7 @@ int i915_gem_init_rings(struct drm_device *dev)
goto cleanup_render_ring;
}
- if (intel_enable_blt(dev)) {
+ if (HAS_BLT(dev)) {
ret = intel_init_blt_ring_buffer(dev);
if (ret)
goto cleanup_bsd_ring;
@@ -4602,14 +4680,8 @@ int i915_gem_init_rings(struct drm_device *dev)
goto cleanup_vebox_ring;
}
- ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000));
- if (ret)
- goto cleanup_bsd2_ring;
-
return 0;
-cleanup_bsd2_ring:
- intel_cleanup_ring_buffer(&dev_priv->ring[VCS2]);
cleanup_vebox_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[VECS]);
cleanup_blt_ring:
@@ -4679,6 +4751,33 @@ i915_gem_init_hw(struct drm_device *dev)
goto out;
}
+ /* We can't enable contexts until all firmware is loaded */
+ if (HAS_GUC_UCODE(dev)) {
+ ret = intel_guc_ucode_load(dev);
+ if (ret) {
+ /*
+ * If we got an error and GuC submission is enabled, map
+ * the error to -EIO so the GPU will be declared wedged.
+ * OTOH, if we didn't intend to use the GuC anyway, just
+ * discard the error and carry on.
+ */
+ DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret,
+ i915.enable_guc_submission ? "" :
+ " (ignored)");
+ ret = i915.enable_guc_submission ? -EIO : 0;
+ if (ret)
+ goto out;
+ }
+ }
+
+ /*
+ * Increment the next seqno by 0x100 so we have a visible break
+ * on re-initialisation
+ */
+ ret = i915_gem_set_seqno(dev, dev_priv->next_seqno+0x100);
+ if (ret)
+ goto out;
+
/* Now it is safe to go back round and do everything else: */
for_each_ring(ring, dev_priv, i) {
struct drm_i915_gem_request *req;
@@ -4816,18 +4915,6 @@ init_ring_lists(struct intel_engine_cs *ring)
INIT_LIST_HEAD(&ring->request_list);
}
-void i915_init_vm(struct drm_i915_private *dev_priv,
- struct i915_address_space *vm)
-{
- if (!i915_is_ggtt(vm))
- drm_mm_init(&vm->mm, vm->start, vm->total);
- vm->dev = dev_priv->dev;
- INIT_LIST_HEAD(&vm->active_list);
- INIT_LIST_HEAD(&vm->inactive_list);
- INIT_LIST_HEAD(&vm->global_link);
- list_add_tail(&vm->global_link, &dev_priv->vm_list);
-}
-
void
i915_gem_load(struct drm_device *dev)
{
@@ -4851,8 +4938,6 @@ i915_gem_load(struct drm_device *dev)
NULL);
INIT_LIST_HEAD(&dev_priv->vm_list);
- i915_init_vm(dev_priv, &dev_priv->gtt.base);
-
INIT_LIST_HEAD(&dev_priv->context_list);
INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
INIT_LIST_HEAD(&dev_priv->mm.bound_list);
@@ -4880,6 +4965,14 @@ i915_gem_load(struct drm_device *dev)
dev_priv->num_fence_regs =
I915_READ(vgtif_reg(avail_rs.fence_num));
+ /*
+ * Set initial sequence number for requests.
+ * Using this number allows the wraparound to happen early,
+ * catching any obvious problems.
+ */
+ dev_priv->next_seqno = ((u32)~0 - 0x1100);
+ dev_priv->last_seqno = ((u32)~0 - 0x1101);
+
/* Initialize fence registers to zero */
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
i915_gem_restore_fences(dev);
@@ -4949,9 +5042,9 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file)
/**
* i915_gem_track_fb - update frontbuffer tracking
- * old: current GEM buffer for the frontbuffer slots
- * new: new GEM buffer for the frontbuffer slots
- * frontbuffer_bits: bitmask of frontbuffer slots
+ * @old: current GEM buffer for the frontbuffer slots
+ * @new: new GEM buffer for the frontbuffer slots
+ * @frontbuffer_bits: bitmask of frontbuffer slots
*
* This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them
* from @old and setting them in @new. Both @old and @new can be NULL.
@@ -4974,9 +5067,8 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
}
/* All the new VM stuff */
-unsigned long
-i915_gem_obj_offset(struct drm_i915_gem_object *o,
- struct i915_address_space *vm)
+u64 i915_gem_obj_offset(struct drm_i915_gem_object *o,
+ struct i915_address_space *vm)
{
struct drm_i915_private *dev_priv = o->base.dev->dev_private;
struct i915_vma *vma;
@@ -4996,9 +5088,8 @@ i915_gem_obj_offset(struct drm_i915_gem_object *o,
return -1;
}
-unsigned long
-i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
- const struct i915_ggtt_view *view)
+u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
+ const struct i915_ggtt_view *view)
{
struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
struct i915_vma *vma;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 8e893b354bcc..8c688a5f1589 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -133,6 +133,23 @@ static int get_context_size(struct drm_device *dev)
return ret;
}
+static void i915_gem_context_clean(struct intel_context *ctx)
+{
+ struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
+ struct i915_vma *vma, *next;
+
+ if (!ppgtt)
+ return;
+
+ WARN_ON(!list_empty(&ppgtt->base.active_list));
+
+ list_for_each_entry_safe(vma, next, &ppgtt->base.inactive_list,
+ mm_list) {
+ if (WARN_ON(__i915_vma_unbind_no_wait(vma)))
+ break;
+ }
+}
+
void i915_gem_context_free(struct kref *ctx_ref)
{
struct intel_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
@@ -142,6 +159,13 @@ void i915_gem_context_free(struct kref *ctx_ref)
if (i915.enable_execlists)
intel_lr_context_free(ctx);
+ /*
+ * This context is going away and we need to remove all VMAs still
+ * around. This is to handle imported shared objects for which
+ * destructor did not run when their handles were closed.
+ */
+ i915_gem_context_clean(ctx);
+
i915_ppgtt_put(ctx->ppgtt);
if (ctx->legacy_hw_ctx.rcs_state)
@@ -332,6 +356,13 @@ int i915_gem_context_init(struct drm_device *dev)
if (WARN_ON(dev_priv->ring[RCS].default_context))
return 0;
+ if (intel_vgpu_active(dev) && HAS_LOGICAL_RING_CONTEXTS(dev)) {
+ if (!i915.enable_execlists) {
+ DRM_INFO("Only EXECLIST mode is supported in vgpu.\n");
+ return -EINVAL;
+ }
+ }
+
if (i915.enable_execlists) {
/* NB: intentionally left blank. We will allocate our own
* backing objects as we need them, thank you very much */
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index d09e35ed9c9a..d71a133ceff5 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -237,48 +237,3 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
return 0;
}
-
-/**
- * i915_gem_evict_everything - Try to evict all objects
- * @dev: Device to evict objects for
- *
- * This functions tries to evict all gem objects from all address spaces. Used
- * by the shrinker as a last-ditch effort and for suspend, before releasing the
- * backing storage of all unbound objects.
- */
-int
-i915_gem_evict_everything(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct i915_address_space *vm, *v;
- bool lists_empty = true;
- int ret;
-
- list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
- lists_empty = (list_empty(&vm->inactive_list) &&
- list_empty(&vm->active_list));
- if (!lists_empty)
- lists_empty = false;
- }
-
- if (lists_empty)
- return -ENOSPC;
-
- trace_i915_gem_evict_everything(dev);
-
- /* The gpu_idle will flush everything in the write domain to the
- * active list. Then we must move everything off the active list
- * with retire requests.
- */
- ret = i915_gpu_idle(dev);
- if (ret)
- return ret;
-
- i915_gem_retire_requests(dev);
-
- /* Having flushed everything, unbind() should never raise an error */
- list_for_each_entry_safe(vm, v, &dev_priv->vm_list, global_link)
- WARN_ON(i915_gem_evict_vm(vm, false));
-
- return 0;
-}
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a953d4975b8c..6ed7d63a0688 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -590,10 +590,17 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
flags |= PIN_GLOBAL;
if (!drm_mm_node_allocated(&vma->node)) {
+ /* Wa32bitGeneralStateOffset & Wa32bitInstructionBaseOffset,
+ * limit address to the first 4GBs for unflagged objects.
+ */
+ if ((entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) == 0)
+ flags |= PIN_ZONE_4G;
if (entry->flags & __EXEC_OBJECT_NEEDS_MAP)
flags |= PIN_GLOBAL | PIN_MAPPABLE;
if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS)
flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
+ if ((flags & PIN_MAPPABLE) == 0)
+ flags |= PIN_HIGH;
}
ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags);
@@ -671,6 +678,10 @@ eb_vma_misplaced(struct i915_vma *vma)
if (entry->flags & __EXEC_OBJECT_NEEDS_MAP && !obj->map_and_fenceable)
return !only_mappable_for_reloc(entry->flags);
+ if ((entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) == 0 &&
+ (vma->node.start + vma->node.size - 1) >> 32)
+ return true;
+
return false;
}
@@ -934,7 +945,21 @@ i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec)
if (exec->flags & __I915_EXEC_UNKNOWN_FLAGS)
return false;
- return ((exec->batch_start_offset | exec->batch_len) & 0x7) == 0;
+ /* Kernel clipping was a DRI1 misfeature */
+ if (exec->num_cliprects || exec->cliprects_ptr)
+ return false;
+
+ if (exec->DR4 == 0xffffffff) {
+ DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
+ exec->DR4 = 0;
+ }
+ if (exec->DR1 || exec->DR4)
+ return false;
+
+ if ((exec->batch_start_offset | exec->batch_len) & 0x7)
+ return false;
+
+ return true;
}
static int
@@ -1009,7 +1034,7 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
}
if (i915.enable_execlists && !ctx->engine[ring->id].state) {
- int ret = intel_lr_context_deferred_create(ctx, ring);
+ int ret = intel_lr_context_deferred_alloc(ctx, ring);
if (ret) {
DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret);
return ERR_PTR(ret);
@@ -1098,47 +1123,6 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
return 0;
}
-static int
-i915_emit_box(struct drm_i915_gem_request *req,
- struct drm_clip_rect *box,
- int DR1, int DR4)
-{
- struct intel_engine_cs *ring = req->ring;
- int ret;
-
- if (box->y2 <= box->y1 || box->x2 <= box->x1 ||
- box->y2 <= 0 || box->x2 <= 0) {
- DRM_ERROR("Bad box %d,%d..%d,%d\n",
- box->x1, box->y1, box->x2, box->y2);
- return -EINVAL;
- }
-
- if (INTEL_INFO(ring->dev)->gen >= 4) {
- ret = intel_ring_begin(req, 4);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, GFX_OP_DRAWRECT_INFO_I965);
- intel_ring_emit(ring, (box->x1 & 0xffff) | box->y1 << 16);
- intel_ring_emit(ring, ((box->x2 - 1) & 0xffff) | (box->y2 - 1) << 16);
- intel_ring_emit(ring, DR4);
- } else {
- ret = intel_ring_begin(req, 6);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, GFX_OP_DRAWRECT_INFO);
- intel_ring_emit(ring, DR1);
- intel_ring_emit(ring, (box->x1 & 0xffff) | box->y1 << 16);
- intel_ring_emit(ring, ((box->x2 - 1) & 0xffff) | (box->y2 - 1) << 16);
- intel_ring_emit(ring, DR4);
- intel_ring_emit(ring, 0);
- }
- intel_ring_advance(ring);
-
- return 0;
-}
-
static struct drm_i915_gem_object*
i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
struct drm_i915_gem_exec_object2 *shadow_exec_entry,
@@ -1197,65 +1181,21 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas)
{
- struct drm_clip_rect *cliprects = NULL;
struct drm_device *dev = params->dev;
struct intel_engine_cs *ring = params->ring;
struct drm_i915_private *dev_priv = dev->dev_private;
u64 exec_start, exec_len;
int instp_mode;
u32 instp_mask;
- int i, ret = 0;
-
- if (args->num_cliprects != 0) {
- if (ring != &dev_priv->ring[RCS]) {
- DRM_DEBUG("clip rectangles are only valid with the render ring\n");
- return -EINVAL;
- }
-
- if (INTEL_INFO(dev)->gen >= 5) {
- DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
- return -EINVAL;
- }
-
- if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
- DRM_DEBUG("execbuf with %u cliprects\n",
- args->num_cliprects);
- return -EINVAL;
- }
-
- cliprects = kcalloc(args->num_cliprects,
- sizeof(*cliprects),
- GFP_KERNEL);
- if (cliprects == NULL) {
- ret = -ENOMEM;
- goto error;
- }
-
- if (copy_from_user(cliprects,
- to_user_ptr(args->cliprects_ptr),
- sizeof(*cliprects)*args->num_cliprects)) {
- ret = -EFAULT;
- goto error;
- }
- } else {
- if (args->DR4 == 0xffffffff) {
- DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
- args->DR4 = 0;
- }
-
- if (args->DR1 || args->DR4 || args->cliprects_ptr) {
- DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
- return -EINVAL;
- }
- }
+ int ret;
ret = i915_gem_execbuffer_move_to_gpu(params->request, vmas);
if (ret)
- goto error;
+ return ret;
ret = i915_switch_context(params->request);
if (ret)
- goto error;
+ return ret;
WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<<ring->id),
"%s didn't clear reload\n", ring->name);
@@ -1268,22 +1208,19 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
case I915_EXEC_CONSTANTS_REL_SURFACE:
if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
- ret = -EINVAL;
- goto error;
+ return -EINVAL;
}
if (instp_mode != dev_priv->relative_constants_mode) {
if (INTEL_INFO(dev)->gen < 4) {
DRM_DEBUG("no rel constants on pre-gen4\n");
- ret = -EINVAL;
- goto error;
+ return -EINVAL;
}
if (INTEL_INFO(dev)->gen > 5 &&
instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
- ret = -EINVAL;
- goto error;
+ return -EINVAL;
}
/* The HW changed the meaning on this bit on gen6 */
@@ -1293,15 +1230,14 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
break;
default:
DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
- ret = -EINVAL;
- goto error;
+ return -EINVAL;
}
if (ring == &dev_priv->ring[RCS] &&
- instp_mode != dev_priv->relative_constants_mode) {
+ instp_mode != dev_priv->relative_constants_mode) {
ret = intel_ring_begin(params->request, 4);
if (ret)
- goto error;
+ return ret;
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
@@ -1315,42 +1251,25 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
ret = i915_reset_gen7_sol_offsets(dev, params->request);
if (ret)
- goto error;
+ return ret;
}
exec_len = args->batch_len;
exec_start = params->batch_obj_vm_offset +
params->args_batch_start_offset;
- if (cliprects) {
- for (i = 0; i < args->num_cliprects; i++) {
- ret = i915_emit_box(params->request, &cliprects[i],
- args->DR1, args->DR4);
- if (ret)
- goto error;
-
- ret = ring->dispatch_execbuffer(params->request,
- exec_start, exec_len,
- params->dispatch_flags);
- if (ret)
- goto error;
- }
- } else {
- ret = ring->dispatch_execbuffer(params->request,
- exec_start, exec_len,
- params->dispatch_flags);
- if (ret)
- return ret;
- }
+ ret = ring->dispatch_execbuffer(params->request,
+ exec_start, exec_len,
+ params->dispatch_flags);
+ if (ret)
+ return ret;
trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
i915_gem_execbuffer_move_to_active(vmas, params->request);
i915_gem_execbuffer_retire_commands(params);
-error:
- kfree(cliprects);
- return ret;
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c
index af1f8c461060..40a10b25956c 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence.c
@@ -59,19 +59,19 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int fence_reg;
+ int fence_reg_lo, fence_reg_hi;
int fence_pitch_shift;
if (INTEL_INFO(dev)->gen >= 6) {
- fence_reg = FENCE_REG_SANDYBRIDGE_0;
- fence_pitch_shift = SANDYBRIDGE_FENCE_PITCH_SHIFT;
+ fence_reg_lo = FENCE_REG_GEN6_LO(reg);
+ fence_reg_hi = FENCE_REG_GEN6_HI(reg);
+ fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT;
} else {
- fence_reg = FENCE_REG_965_0;
+ fence_reg_lo = FENCE_REG_965_LO(reg);
+ fence_reg_hi = FENCE_REG_965_HI(reg);
fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
}
- fence_reg += reg * 8;
-
/* To w/a incoherency with non-atomic 64-bit register updates,
* we split the 64-bit update into two 32-bit writes. In order
* for a partial fence not to be evaluated between writes, we
@@ -81,8 +81,8 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
* For extra levels of paranoia, we make sure each step lands
* before applying the next step.
*/
- I915_WRITE(fence_reg, 0);
- POSTING_READ(fence_reg);
+ I915_WRITE(fence_reg_lo, 0);
+ POSTING_READ(fence_reg_lo);
if (obj) {
u32 size = i915_gem_obj_ggtt_size(obj);
@@ -103,14 +103,14 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
val |= I965_FENCE_REG_VALID;
- I915_WRITE(fence_reg + 4, val >> 32);
- POSTING_READ(fence_reg + 4);
+ I915_WRITE(fence_reg_hi, val >> 32);
+ POSTING_READ(fence_reg_hi);
- I915_WRITE(fence_reg + 0, val);
- POSTING_READ(fence_reg);
+ I915_WRITE(fence_reg_lo, val);
+ POSTING_READ(fence_reg_lo);
} else {
- I915_WRITE(fence_reg + 4, 0);
- POSTING_READ(fence_reg + 4);
+ I915_WRITE(fence_reg_hi, 0);
+ POSTING_READ(fence_reg_hi);
}
}
@@ -128,7 +128,7 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
WARN((i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK) ||
(size & -size) != size ||
(i915_gem_obj_ggtt_offset(obj) & (size - 1)),
- "object 0x%08lx [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
+ "object 0x%08llx [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
i915_gem_obj_ggtt_offset(obj), obj->map_and_fenceable, size);
if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
@@ -149,13 +149,8 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
} else
val = 0;
- if (reg < 8)
- reg = FENCE_REG_830_0 + reg * 4;
- else
- reg = FENCE_REG_945_8 + (reg - 8) * 4;
-
- I915_WRITE(reg, val);
- POSTING_READ(reg);
+ I915_WRITE(FENCE_REG(reg), val);
+ POSTING_READ(FENCE_REG(reg));
}
static void i830_write_fence_reg(struct drm_device *dev, int reg,
@@ -171,7 +166,7 @@ static void i830_write_fence_reg(struct drm_device *dev, int reg,
WARN((i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK) ||
(size & -size) != size ||
(i915_gem_obj_ggtt_offset(obj) & (size - 1)),
- "object 0x%08lx not 512K or pot-size 0x%08x aligned\n",
+ "object 0x%08llx not 512K or pot-size 0x%08x aligned\n",
i915_gem_obj_ggtt_offset(obj), size);
pitch_val = obj->stride / 128;
@@ -186,8 +181,8 @@ static void i830_write_fence_reg(struct drm_device *dev, int reg,
} else
val = 0;
- I915_WRITE(FENCE_REG_830_0 + reg * 4, val);
- POSTING_READ(FENCE_REG_830_0 + reg * 4);
+ I915_WRITE(FENCE_REG(reg), val);
+ POSTING_READ(FENCE_REG(reg));
}
inline static bool i915_gem_object_needs_mb(struct drm_i915_gem_object *obj)
@@ -322,7 +317,7 @@ i915_find_fence_reg(struct drm_device *dev)
/* First try to find a free reg */
avail = NULL;
- for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
+ for (i = 0; i < dev_priv->num_fence_regs; i++) {
reg = &dev_priv->fence_regs[i];
if (!reg->obj)
return reg;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 96054a560f4f..43f35d12b677 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -204,6 +204,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr,
return pde;
}
+#define gen8_pdpe_encode gen8_pde_encode
+#define gen8_pml4e_encode gen8_pde_encode
+
static gen6_pte_t snb_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
bool valid, u32 unused)
@@ -522,6 +525,127 @@ static void gen8_initialize_pd(struct i915_address_space *vm,
fill_px(vm->dev, pd, scratch_pde);
}
+static int __pdp_init(struct drm_device *dev,
+ struct i915_page_directory_pointer *pdp)
+{
+ size_t pdpes = I915_PDPES_PER_PDP(dev);
+
+ pdp->used_pdpes = kcalloc(BITS_TO_LONGS(pdpes),
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!pdp->used_pdpes)
+ return -ENOMEM;
+
+ pdp->page_directory = kcalloc(pdpes, sizeof(*pdp->page_directory),
+ GFP_KERNEL);
+ if (!pdp->page_directory) {
+ kfree(pdp->used_pdpes);
+ /* the PDP might be the statically allocated top level. Keep it
+ * as clean as possible */
+ pdp->used_pdpes = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void __pdp_fini(struct i915_page_directory_pointer *pdp)
+{
+ kfree(pdp->used_pdpes);
+ kfree(pdp->page_directory);
+ pdp->page_directory = NULL;
+}
+
+static struct
+i915_page_directory_pointer *alloc_pdp(struct drm_device *dev)
+{
+ struct i915_page_directory_pointer *pdp;
+ int ret = -ENOMEM;
+
+ WARN_ON(!USES_FULL_48BIT_PPGTT(dev));
+
+ pdp = kzalloc(sizeof(*pdp), GFP_KERNEL);
+ if (!pdp)
+ return ERR_PTR(-ENOMEM);
+
+ ret = __pdp_init(dev, pdp);
+ if (ret)
+ goto fail_bitmap;
+
+ ret = setup_px(dev, pdp);
+ if (ret)
+ goto fail_page_m;
+
+ return pdp;
+
+fail_page_m:
+ __pdp_fini(pdp);
+fail_bitmap:
+ kfree(pdp);
+
+ return ERR_PTR(ret);
+}
+
+static void free_pdp(struct drm_device *dev,
+ struct i915_page_directory_pointer *pdp)
+{
+ __pdp_fini(pdp);
+ if (USES_FULL_48BIT_PPGTT(dev)) {
+ cleanup_px(dev, pdp);
+ kfree(pdp);
+ }
+}
+
+static void gen8_initialize_pdp(struct i915_address_space *vm,
+ struct i915_page_directory_pointer *pdp)
+{
+ gen8_ppgtt_pdpe_t scratch_pdpe;
+
+ scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
+
+ fill_px(vm->dev, pdp, scratch_pdpe);
+}
+
+static void gen8_initialize_pml4(struct i915_address_space *vm,
+ struct i915_pml4 *pml4)
+{
+ gen8_ppgtt_pml4e_t scratch_pml4e;
+
+ scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp),
+ I915_CACHE_LLC);
+
+ fill_px(vm->dev, pml4, scratch_pml4e);
+}
+
+static void
+gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt,
+ struct i915_page_directory_pointer *pdp,
+ struct i915_page_directory *pd,
+ int index)
+{
+ gen8_ppgtt_pdpe_t *page_directorypo;
+
+ if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
+ return;
+
+ page_directorypo = kmap_px(pdp);
+ page_directorypo[index] = gen8_pdpe_encode(px_dma(pd), I915_CACHE_LLC);
+ kunmap_px(ppgtt, page_directorypo);
+}
+
+static void
+gen8_setup_page_directory_pointer(struct i915_hw_ppgtt *ppgtt,
+ struct i915_pml4 *pml4,
+ struct i915_page_directory_pointer *pdp,
+ int index)
+{
+ gen8_ppgtt_pml4e_t *pagemap = kmap_px(pml4);
+
+ WARN_ON(!USES_FULL_48BIT_PPGTT(ppgtt->base.dev));
+ pagemap[index] = gen8_pml4e_encode(px_dma(pdp), I915_CACHE_LLC);
+ kunmap_px(ppgtt, pagemap);
+}
+
/* Broadwell Page Directory Pointer Descriptors */
static int gen8_write_pdp(struct drm_i915_gem_request *req,
unsigned entry,
@@ -547,8 +671,8 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req,
return 0;
}
-static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt,
- struct drm_i915_gem_request *req)
+static int gen8_legacy_mm_switch(struct i915_hw_ppgtt *ppgtt,
+ struct drm_i915_gem_request *req)
{
int i, ret;
@@ -563,31 +687,38 @@ static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt,
return 0;
}
-static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
- uint64_t start,
- uint64_t length,
- bool use_scratch)
+static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt,
+ struct drm_i915_gem_request *req)
+{
+ return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4));
+}
+
+static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm,
+ struct i915_page_directory_pointer *pdp,
+ uint64_t start,
+ uint64_t length,
+ gen8_pte_t scratch_pte)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
- gen8_pte_t *pt_vaddr, scratch_pte;
- unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK;
- unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK;
- unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK;
+ gen8_pte_t *pt_vaddr;
+ unsigned pdpe = gen8_pdpe_index(start);
+ unsigned pde = gen8_pde_index(start);
+ unsigned pte = gen8_pte_index(start);
unsigned num_entries = length >> PAGE_SHIFT;
unsigned last_pte, i;
- scratch_pte = gen8_pte_encode(px_dma(ppgtt->base.scratch_page),
- I915_CACHE_LLC, use_scratch);
+ if (WARN_ON(!pdp))
+ return;
while (num_entries) {
struct i915_page_directory *pd;
struct i915_page_table *pt;
- if (WARN_ON(!ppgtt->pdp.page_directory[pdpe]))
+ if (WARN_ON(!pdp->page_directory[pdpe]))
break;
- pd = ppgtt->pdp.page_directory[pdpe];
+ pd = pdp->page_directory[pdpe];
if (WARN_ON(!pd->page_table[pde]))
break;
@@ -612,45 +743,69 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
pte = 0;
if (++pde == I915_PDES) {
- pdpe++;
+ if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
+ break;
pde = 0;
}
}
}
-static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
- struct sg_table *pages,
- uint64_t start,
- enum i915_cache_level cache_level, u32 unused)
+static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
+ uint64_t start,
+ uint64_t length,
+ bool use_scratch)
+{
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+ gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
+ I915_CACHE_LLC, use_scratch);
+
+ if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+ gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
+ scratch_pte);
+ } else {
+ uint64_t templ4, pml4e;
+ struct i915_page_directory_pointer *pdp;
+
+ gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
+ gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
+ scratch_pte);
+ }
+ }
+}
+
+static void
+gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
+ struct i915_page_directory_pointer *pdp,
+ struct sg_page_iter *sg_iter,
+ uint64_t start,
+ enum i915_cache_level cache_level)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
gen8_pte_t *pt_vaddr;
- unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK;
- unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK;
- unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK;
- struct sg_page_iter sg_iter;
+ unsigned pdpe = gen8_pdpe_index(start);
+ unsigned pde = gen8_pde_index(start);
+ unsigned pte = gen8_pte_index(start);
pt_vaddr = NULL;
- for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
- if (WARN_ON(pdpe >= GEN8_LEGACY_PDPES))
- break;
-
+ while (__sg_page_iter_next(sg_iter)) {
if (pt_vaddr == NULL) {
- struct i915_page_directory *pd = ppgtt->pdp.page_directory[pdpe];
+ struct i915_page_directory *pd = pdp->page_directory[pdpe];
struct i915_page_table *pt = pd->page_table[pde];
pt_vaddr = kmap_px(pt);
}
pt_vaddr[pte] =
- gen8_pte_encode(sg_page_iter_dma_address(&sg_iter),
+ gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
cache_level, true);
if (++pte == GEN8_PTES) {
kunmap_px(ppgtt, pt_vaddr);
pt_vaddr = NULL;
if (++pde == I915_PDES) {
- pdpe++;
+ if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
+ break;
pde = 0;
}
pte = 0;
@@ -661,6 +816,33 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
kunmap_px(ppgtt, pt_vaddr);
}
+static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
+ struct sg_table *pages,
+ uint64_t start,
+ enum i915_cache_level cache_level,
+ u32 unused)
+{
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+ struct sg_page_iter sg_iter;
+
+ __sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
+
+ if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+ gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start,
+ cache_level);
+ } else {
+ struct i915_page_directory_pointer *pdp;
+ uint64_t templ4, pml4e;
+ uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT;
+
+ gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
+ gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter,
+ start, cache_level);
+ }
+ }
+}
+
static void gen8_free_page_tables(struct drm_device *dev,
struct i915_page_directory *pd)
{
@@ -699,8 +881,55 @@ static int gen8_init_scratch(struct i915_address_space *vm)
return PTR_ERR(vm->scratch_pd);
}
+ if (USES_FULL_48BIT_PPGTT(dev)) {
+ vm->scratch_pdp = alloc_pdp(dev);
+ if (IS_ERR(vm->scratch_pdp)) {
+ free_pd(dev, vm->scratch_pd);
+ free_pt(dev, vm->scratch_pt);
+ free_scratch_page(dev, vm->scratch_page);
+ return PTR_ERR(vm->scratch_pdp);
+ }
+ }
+
gen8_initialize_pt(vm, vm->scratch_pt);
gen8_initialize_pd(vm, vm->scratch_pd);
+ if (USES_FULL_48BIT_PPGTT(dev))
+ gen8_initialize_pdp(vm, vm->scratch_pdp);
+
+ return 0;
+}
+
+static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
+{
+ enum vgt_g2v_type msg;
+ struct drm_device *dev = ppgtt->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned int offset = vgtif_reg(pdp0_lo);
+ int i;
+
+ if (USES_FULL_48BIT_PPGTT(dev)) {
+ u64 daddr = px_dma(&ppgtt->pml4);
+
+ I915_WRITE(offset, lower_32_bits(daddr));
+ I915_WRITE(offset + 4, upper_32_bits(daddr));
+
+ msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE :
+ VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY);
+ } else {
+ for (i = 0; i < GEN8_LEGACY_PDPES; i++) {
+ u64 daddr = i915_page_dir_dma_addr(ppgtt, i);
+
+ I915_WRITE(offset, lower_32_bits(daddr));
+ I915_WRITE(offset + 4, upper_32_bits(daddr));
+
+ offset += 8;
+ }
+
+ msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE :
+ VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY);
+ }
+
+ I915_WRITE(vgtif_reg(g2v_notify), msg);
return 0;
}
@@ -709,35 +938,65 @@ static void gen8_free_scratch(struct i915_address_space *vm)
{
struct drm_device *dev = vm->dev;
+ if (USES_FULL_48BIT_PPGTT(dev))
+ free_pdp(dev, vm->scratch_pdp);
free_pd(dev, vm->scratch_pd);
free_pt(dev, vm->scratch_pt);
free_scratch_page(dev, vm->scratch_page);
}
-static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev,
+ struct i915_page_directory_pointer *pdp)
{
- struct i915_hw_ppgtt *ppgtt =
- container_of(vm, struct i915_hw_ppgtt, base);
int i;
- for_each_set_bit(i, ppgtt->pdp.used_pdpes, GEN8_LEGACY_PDPES) {
- if (WARN_ON(!ppgtt->pdp.page_directory[i]))
+ for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) {
+ if (WARN_ON(!pdp->page_directory[i]))
continue;
- gen8_free_page_tables(ppgtt->base.dev,
- ppgtt->pdp.page_directory[i]);
- free_pd(ppgtt->base.dev, ppgtt->pdp.page_directory[i]);
+ gen8_free_page_tables(dev, pdp->page_directory[i]);
+ free_pd(dev, pdp->page_directory[i]);
}
+ free_pdp(dev, pdp);
+}
+
+static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt)
+{
+ int i;
+
+ for_each_set_bit(i, ppgtt->pml4.used_pml4es, GEN8_PML4ES_PER_PML4) {
+ if (WARN_ON(!ppgtt->pml4.pdps[i]))
+ continue;
+
+ gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, ppgtt->pml4.pdps[i]);
+ }
+
+ cleanup_px(ppgtt->base.dev, &ppgtt->pml4);
+}
+
+static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+{
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+
+ if (intel_vgpu_active(vm->dev))
+ gen8_ppgtt_notify_vgt(ppgtt, false);
+
+ if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
+ gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp);
+ else
+ gen8_ppgtt_cleanup_4lvl(ppgtt);
+
gen8_free_scratch(vm);
}
/**
* gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range.
- * @ppgtt: Master ppgtt structure.
- * @pd: Page directory for this address range.
+ * @vm: Master vm structure.
+ * @pd: Page directory for this address range.
* @start: Starting virtual address to begin allocations.
- * @length Size of the allocations.
+ * @length: Size of the allocations.
* @new_pts: Bitmap set by function with new allocations. Likely used by the
* caller to free on error.
*
@@ -750,22 +1009,22 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
*
* Return: 0 if success; negative error code otherwise.
*/
-static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt,
+static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
struct i915_page_directory *pd,
uint64_t start,
uint64_t length,
unsigned long *new_pts)
{
- struct drm_device *dev = ppgtt->base.dev;
+ struct drm_device *dev = vm->dev;
struct i915_page_table *pt;
uint64_t temp;
uint32_t pde;
gen8_for_each_pde(pt, pd, start, length, temp, pde) {
/* Don't reallocate page tables */
- if (pt) {
+ if (test_bit(pde, pd->used_pdes)) {
/* Scratch is never allocated this way */
- WARN_ON(pt == ppgtt->base.scratch_pt);
+ WARN_ON(pt == vm->scratch_pt);
continue;
}
@@ -773,9 +1032,10 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt,
if (IS_ERR(pt))
goto unwind_out;
- gen8_initialize_pt(&ppgtt->base, pt);
+ gen8_initialize_pt(vm, pt);
pd->page_table[pde] = pt;
__set_bit(pde, new_pts);
+ trace_i915_page_table_entry_alloc(vm, pde, start, GEN8_PDE_SHIFT);
}
return 0;
@@ -789,11 +1049,11 @@ unwind_out:
/**
* gen8_ppgtt_alloc_page_directories() - Allocate page directories for VA range.
- * @ppgtt: Master ppgtt structure.
+ * @vm: Master vm structure.
* @pdp: Page directory pointer for this address range.
* @start: Starting virtual address to begin allocations.
- * @length Size of the allocations.
- * @new_pds Bitmap set by function with new allocations. Likely used by the
+ * @length: Size of the allocations.
+ * @new_pds: Bitmap set by function with new allocations. Likely used by the
* caller to free on error.
*
* Allocate the required number of page directories starting at the pde index of
@@ -810,48 +1070,102 @@ unwind_out:
*
* Return: 0 if success; negative error code otherwise.
*/
-static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt,
- struct i915_page_directory_pointer *pdp,
- uint64_t start,
- uint64_t length,
- unsigned long *new_pds)
+static int
+gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
+ struct i915_page_directory_pointer *pdp,
+ uint64_t start,
+ uint64_t length,
+ unsigned long *new_pds)
{
- struct drm_device *dev = ppgtt->base.dev;
+ struct drm_device *dev = vm->dev;
struct i915_page_directory *pd;
uint64_t temp;
uint32_t pdpe;
+ uint32_t pdpes = I915_PDPES_PER_PDP(dev);
- WARN_ON(!bitmap_empty(new_pds, GEN8_LEGACY_PDPES));
+ WARN_ON(!bitmap_empty(new_pds, pdpes));
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
- if (pd)
+ if (test_bit(pdpe, pdp->used_pdpes))
continue;
pd = alloc_pd(dev);
if (IS_ERR(pd))
goto unwind_out;
- gen8_initialize_pd(&ppgtt->base, pd);
+ gen8_initialize_pd(vm, pd);
pdp->page_directory[pdpe] = pd;
__set_bit(pdpe, new_pds);
+ trace_i915_page_directory_entry_alloc(vm, pdpe, start, GEN8_PDPE_SHIFT);
}
return 0;
unwind_out:
- for_each_set_bit(pdpe, new_pds, GEN8_LEGACY_PDPES)
+ for_each_set_bit(pdpe, new_pds, pdpes)
free_pd(dev, pdp->page_directory[pdpe]);
return -ENOMEM;
}
-static void
-free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts)
+/**
+ * gen8_ppgtt_alloc_page_dirpointers() - Allocate pdps for VA range.
+ * @vm: Master vm structure.
+ * @pml4: Page map level 4 for this address range.
+ * @start: Starting virtual address to begin allocations.
+ * @length: Size of the allocations.
+ * @new_pdps: Bitmap set by function with new allocations. Likely used by the
+ * caller to free on error.
+ *
+ * Allocate the required number of page directory pointers. Extremely similar to
+ * gen8_ppgtt_alloc_page_directories() and gen8_ppgtt_alloc_pagetabs().
+ * The main difference is here we are limited by the pml4 boundary (instead of
+ * the page directory pointer).
+ *
+ * Return: 0 if success; negative error code otherwise.
+ */
+static int
+gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
+ struct i915_pml4 *pml4,
+ uint64_t start,
+ uint64_t length,
+ unsigned long *new_pdps)
{
- int i;
+ struct drm_device *dev = vm->dev;
+ struct i915_page_directory_pointer *pdp;
+ uint64_t temp;
+ uint32_t pml4e;
+
+ WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4));
+
+ gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
+ if (!test_bit(pml4e, pml4->used_pml4es)) {
+ pdp = alloc_pdp(dev);
+ if (IS_ERR(pdp))
+ goto unwind_out;
+
+ gen8_initialize_pdp(vm, pdp);
+ pml4->pdps[pml4e] = pdp;
+ __set_bit(pml4e, new_pdps);
+ trace_i915_page_directory_pointer_entry_alloc(vm,
+ pml4e,
+ start,
+ GEN8_PML4E_SHIFT);
+ }
+ }
- for (i = 0; i < GEN8_LEGACY_PDPES; i++)
- kfree(new_pts[i]);
+ return 0;
+
+unwind_out:
+ for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
+ free_pdp(dev, pml4->pdps[pml4e]);
+
+ return -ENOMEM;
+}
+
+static void
+free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long *new_pts)
+{
kfree(new_pts);
kfree(new_pds);
}
@@ -861,28 +1175,20 @@ free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts)
*/
static
int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds,
- unsigned long ***new_pts)
+ unsigned long **new_pts,
+ uint32_t pdpes)
{
- int i;
unsigned long *pds;
- unsigned long **pts;
+ unsigned long *pts;
- pds = kcalloc(BITS_TO_LONGS(GEN8_LEGACY_PDPES), sizeof(unsigned long), GFP_KERNEL);
+ pds = kcalloc(BITS_TO_LONGS(pdpes), sizeof(unsigned long), GFP_TEMPORARY);
if (!pds)
return -ENOMEM;
- pts = kcalloc(GEN8_LEGACY_PDPES, sizeof(unsigned long *), GFP_KERNEL);
- if (!pts) {
- kfree(pds);
- return -ENOMEM;
- }
-
- for (i = 0; i < GEN8_LEGACY_PDPES; i++) {
- pts[i] = kcalloc(BITS_TO_LONGS(I915_PDES),
- sizeof(unsigned long), GFP_KERNEL);
- if (!pts[i])
- goto err_out;
- }
+ pts = kcalloc(pdpes, BITS_TO_LONGS(I915_PDES) * sizeof(unsigned long),
+ GFP_TEMPORARY);
+ if (!pts)
+ goto err_out;
*new_pds = pds;
*new_pts = pts;
@@ -904,18 +1210,21 @@ static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
}
-static int gen8_alloc_va_range(struct i915_address_space *vm,
- uint64_t start,
- uint64_t length)
+static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
+ struct i915_page_directory_pointer *pdp,
+ uint64_t start,
+ uint64_t length)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
- unsigned long *new_page_dirs, **new_page_tables;
+ unsigned long *new_page_dirs, *new_page_tables;
+ struct drm_device *dev = vm->dev;
struct i915_page_directory *pd;
const uint64_t orig_start = start;
const uint64_t orig_length = length;
uint64_t temp;
uint32_t pdpe;
+ uint32_t pdpes = I915_PDPES_PER_PDP(dev);
int ret;
/* Wrap is never okay since we can only represent 48b, and we don't
@@ -924,25 +1233,25 @@ static int gen8_alloc_va_range(struct i915_address_space *vm,
if (WARN_ON(start + length < start))
return -ENODEV;
- if (WARN_ON(start + length > ppgtt->base.total))
+ if (WARN_ON(start + length > vm->total))
return -ENODEV;
- ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables);
+ ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes);
if (ret)
return ret;
/* Do the allocations first so we can easily bail out */
- ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length,
- new_page_dirs);
+ ret = gen8_ppgtt_alloc_page_directories(vm, pdp, start, length,
+ new_page_dirs);
if (ret) {
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
return ret;
}
/* For every page directory referenced, allocate page tables */
- gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) {
- ret = gen8_ppgtt_alloc_pagetabs(ppgtt, pd, start, length,
- new_page_tables[pdpe]);
+ gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
+ ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length,
+ new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES));
if (ret)
goto err_out;
}
@@ -952,10 +1261,10 @@ static int gen8_alloc_va_range(struct i915_address_space *vm,
/* Allocations have completed successfully, so set the bitmaps, and do
* the mappings. */
- gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) {
+ gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
gen8_pde_t *const page_directory = kmap_px(pd);
struct i915_page_table *pt;
- uint64_t pd_len = gen8_clamp_pd(start, length);
+ uint64_t pd_len = length;
uint64_t pd_start = start;
uint32_t pde;
@@ -979,14 +1288,18 @@ static int gen8_alloc_va_range(struct i915_address_space *vm,
/* Map the PDE to the page table */
page_directory[pde] = gen8_pde_encode(px_dma(pt),
I915_CACHE_LLC);
+ trace_i915_page_table_entry_map(&ppgtt->base, pde, pt,
+ gen8_pte_index(start),
+ gen8_pte_count(start, length),
+ GEN8_PTES);
/* NB: We haven't yet mapped ptes to pages. At this
* point we're still relying on insert_entries() */
}
kunmap_px(ppgtt, page_directory);
-
- __set_bit(pdpe, ppgtt->pdp.used_pdpes);
+ __set_bit(pdpe, pdp->used_pdpes);
+ gen8_setup_page_directory(ppgtt, pdp, pd, pdpe);
}
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
@@ -995,18 +1308,191 @@ static int gen8_alloc_va_range(struct i915_address_space *vm,
err_out:
while (pdpe--) {
- for_each_set_bit(temp, new_page_tables[pdpe], I915_PDES)
- free_pt(vm->dev, ppgtt->pdp.page_directory[pdpe]->page_table[temp]);
+ for_each_set_bit(temp, new_page_tables + pdpe *
+ BITS_TO_LONGS(I915_PDES), I915_PDES)
+ free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
}
- for_each_set_bit(pdpe, new_page_dirs, GEN8_LEGACY_PDPES)
- free_pd(vm->dev, ppgtt->pdp.page_directory[pdpe]);
+ for_each_set_bit(pdpe, new_page_dirs, pdpes)
+ free_pd(dev, pdp->page_directory[pdpe]);
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
mark_tlbs_dirty(ppgtt);
return ret;
}
+static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
+ struct i915_pml4 *pml4,
+ uint64_t start,
+ uint64_t length)
+{
+ DECLARE_BITMAP(new_pdps, GEN8_PML4ES_PER_PML4);
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+ struct i915_page_directory_pointer *pdp;
+ uint64_t temp, pml4e;
+ int ret = 0;
+
+ /* Do the pml4 allocations first, so we don't need to track the newly
+ * allocated tables below the pdp */
+ bitmap_zero(new_pdps, GEN8_PML4ES_PER_PML4);
+
+ /* The pagedirectory and pagetable allocations are done in the shared 3
+ * and 4 level code. Just allocate the pdps.
+ */
+ ret = gen8_ppgtt_alloc_page_dirpointers(vm, pml4, start, length,
+ new_pdps);
+ if (ret)
+ return ret;
+
+ WARN(bitmap_weight(new_pdps, GEN8_PML4ES_PER_PML4) > 2,
+ "The allocation has spanned more than 512GB. "
+ "It is highly likely this is incorrect.");
+
+ gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
+ WARN_ON(!pdp);
+
+ ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length);
+ if (ret)
+ goto err_out;
+
+ gen8_setup_page_directory_pointer(ppgtt, pml4, pdp, pml4e);
+ }
+
+ bitmap_or(pml4->used_pml4es, new_pdps, pml4->used_pml4es,
+ GEN8_PML4ES_PER_PML4);
+
+ return 0;
+
+err_out:
+ for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
+ gen8_ppgtt_cleanup_3lvl(vm->dev, pml4->pdps[pml4e]);
+
+ return ret;
+}
+
+static int gen8_alloc_va_range(struct i915_address_space *vm,
+ uint64_t start, uint64_t length)
+{
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+
+ if (USES_FULL_48BIT_PPGTT(vm->dev))
+ return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length);
+ else
+ return gen8_alloc_va_range_3lvl(vm, &ppgtt->pdp, start, length);
+}
+
+static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
+ uint64_t start, uint64_t length,
+ gen8_pte_t scratch_pte,
+ struct seq_file *m)
+{
+ struct i915_page_directory *pd;
+ uint64_t temp;
+ uint32_t pdpe;
+
+ gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
+ struct i915_page_table *pt;
+ uint64_t pd_len = length;
+ uint64_t pd_start = start;
+ uint32_t pde;
+
+ if (!test_bit(pdpe, pdp->used_pdpes))
+ continue;
+
+ seq_printf(m, "\tPDPE #%d\n", pdpe);
+ gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
+ uint32_t pte;
+ gen8_pte_t *pt_vaddr;
+
+ if (!test_bit(pde, pd->used_pdes))
+ continue;
+
+ pt_vaddr = kmap_px(pt);
+ for (pte = 0; pte < GEN8_PTES; pte += 4) {
+ uint64_t va =
+ (pdpe << GEN8_PDPE_SHIFT) |
+ (pde << GEN8_PDE_SHIFT) |
+ (pte << GEN8_PTE_SHIFT);
+ int i;
+ bool found = false;
+
+ for (i = 0; i < 4; i++)
+ if (pt_vaddr[pte + i] != scratch_pte)
+ found = true;
+ if (!found)
+ continue;
+
+ seq_printf(m, "\t\t0x%llx [%03d,%03d,%04d]: =", va, pdpe, pde, pte);
+ for (i = 0; i < 4; i++) {
+ if (pt_vaddr[pte + i] != scratch_pte)
+ seq_printf(m, " %llx", pt_vaddr[pte + i]);
+ else
+ seq_puts(m, " SCRATCH ");
+ }
+ seq_puts(m, "\n");
+ }
+ /* don't use kunmap_px, it could trigger
+ * an unnecessary flush.
+ */
+ kunmap_atomic(pt_vaddr);
+ }
+ }
+}
+
+static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
+{
+ struct i915_address_space *vm = &ppgtt->base;
+ uint64_t start = ppgtt->base.start;
+ uint64_t length = ppgtt->base.total;
+ gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
+ I915_CACHE_LLC, true);
+
+ if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+ gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
+ } else {
+ uint64_t templ4, pml4e;
+ struct i915_pml4 *pml4 = &ppgtt->pml4;
+ struct i915_page_directory_pointer *pdp;
+
+ gen8_for_each_pml4e(pdp, pml4, start, length, templ4, pml4e) {
+ if (!test_bit(pml4e, pml4->used_pml4es))
+ continue;
+
+ seq_printf(m, " PML4E #%llu\n", pml4e);
+ gen8_dump_pdp(pdp, start, length, scratch_pte, m);
+ }
+ }
+}
+
+static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt)
+{
+ unsigned long *new_page_dirs, *new_page_tables;
+ uint32_t pdpes = I915_PDPES_PER_PDP(dev);
+ int ret;
+
+ /* We allocate temp bitmap for page tables for no gain
+ * but as this is for init only, lets keep the things simple
+ */
+ ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes);
+ if (ret)
+ return ret;
+
+ /* Allocate for all pdps regardless of how the ppgtt
+ * was defined.
+ */
+ ret = gen8_ppgtt_alloc_page_directories(&ppgtt->base, &ppgtt->pdp,
+ 0, 1ULL << 32,
+ new_page_dirs);
+ if (!ret)
+ *ppgtt->pdp.used_pdpes = *new_page_dirs;
+
+ free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
+
+ return ret;
+}
+
/*
* GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
* with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1023,24 +1509,49 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
return ret;
ppgtt->base.start = 0;
- ppgtt->base.total = 1ULL << 32;
- if (IS_ENABLED(CONFIG_X86_32))
- /* While we have a proliferation of size_t variables
- * we cannot represent the full ppgtt size on 32bit,
- * so limit it to the same size as the GGTT (currently
- * 2GiB).
- */
- ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total;
ppgtt->base.cleanup = gen8_ppgtt_cleanup;
ppgtt->base.allocate_va_range = gen8_alloc_va_range;
ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
ppgtt->base.clear_range = gen8_ppgtt_clear_range;
ppgtt->base.unbind_vma = ppgtt_unbind_vma;
ppgtt->base.bind_vma = ppgtt_bind_vma;
+ ppgtt->debug_dump = gen8_dump_ppgtt;
- ppgtt->switch_mm = gen8_mm_switch;
+ if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
+ ret = setup_px(ppgtt->base.dev, &ppgtt->pml4);
+ if (ret)
+ goto free_scratch;
+
+ gen8_initialize_pml4(&ppgtt->base, &ppgtt->pml4);
+
+ ppgtt->base.total = 1ULL << 48;
+ ppgtt->switch_mm = gen8_48b_mm_switch;
+ } else {
+ ret = __pdp_init(ppgtt->base.dev, &ppgtt->pdp);
+ if (ret)
+ goto free_scratch;
+
+ ppgtt->base.total = 1ULL << 32;
+ ppgtt->switch_mm = gen8_legacy_mm_switch;
+ trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base,
+ 0, 0,
+ GEN8_PML4E_SHIFT);
+
+ if (intel_vgpu_active(ppgtt->base.dev)) {
+ ret = gen8_preallocate_top_level_pdps(ppgtt);
+ if (ret)
+ goto free_scratch;
+ }
+ }
+
+ if (intel_vgpu_active(ppgtt->base.dev))
+ gen8_ppgtt_notify_vgt(ppgtt, true);
return 0;
+
+free_scratch:
+ gen8_free_scratch(&ppgtt->base);
+ return ret;
}
static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
@@ -1228,8 +1739,9 @@ static void gen8_ppgtt_enable(struct drm_device *dev)
int j;
for_each_ring(ring, dev_priv, j) {
+ u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
I915_WRITE(RING_MODE_GEN7(ring),
- _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+ _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
}
}
@@ -1609,6 +2121,16 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
return gen8_ppgtt_init(ppgtt);
}
+static void i915_address_space_init(struct i915_address_space *vm,
+ struct drm_i915_private *dev_priv)
+{
+ drm_mm_init(&vm->mm, vm->start, vm->total);
+ vm->dev = dev_priv->dev;
+ INIT_LIST_HEAD(&vm->active_list);
+ INIT_LIST_HEAD(&vm->inactive_list);
+ list_add_tail(&vm->global_link, &dev_priv->vm_list);
+}
+
int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1617,9 +2139,7 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
ret = __hw_ppgtt_init(dev, ppgtt);
if (ret == 0) {
kref_init(&ppgtt->ref);
- drm_mm_init(&ppgtt->base.mm, ppgtt->base.start,
- ppgtt->base.total);
- i915_init_vm(dev_priv, &ppgtt->base);
+ i915_address_space_init(&ppgtt->base, dev_priv);
}
return ret;
@@ -1982,6 +2502,36 @@ static int ggtt_bind_vma(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags)
{
+ struct drm_i915_gem_object *obj = vma->obj;
+ u32 pte_flags = 0;
+ int ret;
+
+ ret = i915_get_ggtt_vma_pages(vma);
+ if (ret)
+ return ret;
+
+ /* Currently applicable only to VLV */
+ if (obj->gt_ro)
+ pte_flags |= PTE_READ_ONLY;
+
+ vma->vm->insert_entries(vma->vm, vma->ggtt_view.pages,
+ vma->node.start,
+ cache_level, pte_flags);
+
+ /*
+ * Without aliasing PPGTT there's no difference between
+ * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
+ * upgrade to both bound if we bind either to avoid double-binding.
+ */
+ vma->bound |= GLOBAL_BIND | LOCAL_BIND;
+
+ return 0;
+}
+
+static int aliasing_gtt_bind_vma(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags)
+{
struct drm_device *dev = vma->vm->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = vma->obj;
@@ -1999,24 +2549,13 @@ static int ggtt_bind_vma(struct i915_vma *vma,
pte_flags |= PTE_READ_ONLY;
- if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
+ if (flags & GLOBAL_BIND) {
vma->vm->insert_entries(vma->vm, pages,
vma->node.start,
cache_level, pte_flags);
-
- /* Note the inconsistency here is due to absence of the
- * aliasing ppgtt on gen4 and earlier. Though we always
- * request PIN_USER for execbuffer (translated to LOCAL_BIND),
- * without the appgtt, we cannot honour that request and so
- * must substitute it with a global binding. Since we do this
- * behind the upper layers back, we need to explicitly set
- * the bound flag ourselves.
- */
- vma->bound |= GLOBAL_BIND;
-
}
- if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
+ if (flags & LOCAL_BIND) {
struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
appgtt->base.insert_entries(&appgtt->base, pages,
vma->node.start,
@@ -2084,9 +2623,9 @@ static void i915_gtt_color_adjust(struct drm_mm_node *node,
}
static int i915_gem_setup_global_gtt(struct drm_device *dev,
- unsigned long start,
- unsigned long mappable_end,
- unsigned long end)
+ u64 start,
+ u64 mappable_end,
+ u64 end)
{
/* Let GEM Manage all of the aperture.
*
@@ -2106,11 +2645,13 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
BUG_ON(mappable_end > end);
- /* Subtract the guard page ... */
- drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE);
+ ggtt_vm->start = start;
- dev_priv->gtt.base.start = start;
- dev_priv->gtt.base.total = end - start;
+ /* Subtract the guard page before address space initialization to
+ * shrink the range used by drm_mm */
+ ggtt_vm->total = end - start - PAGE_SIZE;
+ i915_address_space_init(ggtt_vm, dev_priv);
+ ggtt_vm->total += PAGE_SIZE;
if (intel_vgpu_active(dev)) {
ret = intel_vgt_balloon(dev);
@@ -2119,13 +2660,13 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
}
if (!HAS_LLC(dev))
- dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust;
+ ggtt_vm->mm.color_adjust = i915_gtt_color_adjust;
/* Mark any preallocated objects as occupied */
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm);
- DRM_DEBUG_KMS("reserving preallocated space: %lx + %zx\n",
+ DRM_DEBUG_KMS("reserving preallocated space: %llx + %zx\n",
i915_gem_obj_ggtt_offset(obj), obj->base.size);
WARN_ON(i915_gem_obj_ggtt_bound(obj));
@@ -2135,6 +2676,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
return ret;
}
vma->bound |= GLOBAL_BIND;
+ list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list);
}
/* Clear any non-preallocated blocks */
@@ -2177,6 +2719,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
true);
dev_priv->mm.aliasing_ppgtt = ppgtt;
+ WARN_ON(dev_priv->gtt.base.bind_vma != ggtt_bind_vma);
+ dev_priv->gtt.base.bind_vma = aliasing_gtt_bind_vma;
}
return 0;
@@ -2367,8 +2911,8 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
/* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b
* write would work. */
- I915_WRITE(GEN8_PRIVATE_PAT, pat);
- I915_WRITE(GEN8_PRIVATE_PAT + 4, pat >> 32);
+ I915_WRITE(GEN8_PRIVATE_PAT_LO, pat);
+ I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
}
static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
@@ -2402,8 +2946,8 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
GEN8_PPAT(6, CHV_PPAT_SNOOP) |
GEN8_PPAT(7, CHV_PPAT_SNOOP);
- I915_WRITE(GEN8_PRIVATE_PAT, pat);
- I915_WRITE(GEN8_PRIVATE_PAT + 4, pat >> 32);
+ I915_WRITE(GEN8_PRIVATE_PAT_LO, pat);
+ I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
}
static int gen8_gmch_probe(struct drm_device *dev,
@@ -2722,15 +3266,18 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
}
-static void
-rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height,
- struct sg_table *st)
+static struct scatterlist *
+rotate_pages(dma_addr_t *in, unsigned int offset,
+ unsigned int width, unsigned int height,
+ struct sg_table *st, struct scatterlist *sg)
{
unsigned int column, row;
unsigned int src_idx;
- struct scatterlist *sg = st->sgl;
- st->nents = 0;
+ if (!sg) {
+ st->nents = 0;
+ sg = st->sgl;
+ }
for (column = 0; column < width; column++) {
src_idx = width * (height - 1) + column;
@@ -2741,12 +3288,14 @@ rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height,
* The only thing we need are DMA addresses.
*/
sg_set_page(sg, NULL, PAGE_SIZE, 0);
- sg_dma_address(sg) = in[src_idx];
+ sg_dma_address(sg) = in[offset + src_idx];
sg_dma_len(sg) = PAGE_SIZE;
sg = sg_next(sg);
src_idx -= width;
}
}
+
+ return sg;
}
static struct sg_table *
@@ -2755,10 +3304,13 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
{
struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
+ unsigned int size_pages_uv;
struct sg_page_iter sg_iter;
unsigned long i;
dma_addr_t *page_addr_list;
struct sg_table *st;
+ unsigned int uv_start_page;
+ struct scatterlist *sg;
int ret = -ENOMEM;
/* Allocate a temporary list of source pages for random access. */
@@ -2767,12 +3319,18 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
if (!page_addr_list)
return ERR_PTR(ret);
+ /* Account for UV plane with NV12. */
+ if (rot_info->pixel_format == DRM_FORMAT_NV12)
+ size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
+ else
+ size_pages_uv = 0;
+
/* Allocate target SG list. */
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (!st)
goto err_st_alloc;
- ret = sg_alloc_table(st, size_pages, GFP_KERNEL);
+ ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
if (ret)
goto err_sg_alloc;
@@ -2784,15 +3342,32 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
}
/* Rotate the pages. */
- rotate_pages(page_addr_list,
+ sg = rotate_pages(page_addr_list, 0,
rot_info->width_pages, rot_info->height_pages,
- st);
+ st, NULL);
+
+ /* Append the UV plane if NV12. */
+ if (rot_info->pixel_format == DRM_FORMAT_NV12) {
+ uv_start_page = size_pages;
+
+ /* Check for tile-row un-alignment. */
+ if (offset_in_page(rot_info->uv_offset))
+ uv_start_page--;
+
+ rot_info->uv_start_page = uv_start_page;
+
+ rotate_pages(page_addr_list, uv_start_page,
+ rot_info->width_pages_uv,
+ rot_info->height_pages_uv,
+ st, sg);
+ }
DRM_DEBUG_KMS(
- "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n",
+ "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
obj->base.size, rot_info->pitch, rot_info->height,
rot_info->pixel_format, rot_info->width_pages,
- rot_info->height_pages, size_pages);
+ rot_info->height_pages, size_pages + size_pages_uv,
+ size_pages);
drm_free_large(page_addr_list);
@@ -2804,10 +3379,11 @@ err_st_alloc:
drm_free_large(page_addr_list);
DRM_DEBUG_KMS(
- "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages)\n",
+ "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
obj->base.size, ret, rot_info->pitch, rot_info->height,
rot_info->pixel_format, rot_info->width_pages,
- rot_info->height_pages, size_pages);
+ rot_info->height_pages, size_pages + size_pages_uv,
+ size_pages);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index e1cfa292f9ad..a216397ead52 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -39,6 +39,8 @@ struct drm_i915_file_private;
typedef uint32_t gen6_pte_t;
typedef uint64_t gen8_pte_t;
typedef uint64_t gen8_pde_t;
+typedef uint64_t gen8_ppgtt_pdpe_t;
+typedef uint64_t gen8_ppgtt_pml4e_t;
#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
@@ -88,9 +90,18 @@ typedef uint64_t gen8_pde_t;
* PDPE | PDE | PTE | offset
* The difference as compared to normal x86 3 level page table is the PDPEs are
* programmed via register.
+ *
+ * GEN8 48b legacy style address is defined as a 4 level page table:
+ * 47:39 | 38:30 | 29:21 | 20:12 | 11:0
+ * PML4E | PDPE | PDE | PTE | offset
*/
+#define GEN8_PML4ES_PER_PML4 512
+#define GEN8_PML4E_SHIFT 39
+#define GEN8_PML4E_MASK (GEN8_PML4ES_PER_PML4 - 1)
#define GEN8_PDPE_SHIFT 30
-#define GEN8_PDPE_MASK 0x3
+/* NB: GEN8_PDPE_MASK is untrue for 32b platforms, but it has no impact on 32b page
+ * tables */
+#define GEN8_PDPE_MASK 0x1ff
#define GEN8_PDE_SHIFT 21
#define GEN8_PDE_MASK 0x1ff
#define GEN8_PTE_SHIFT 12
@@ -98,6 +109,9 @@ typedef uint64_t gen8_pde_t;
#define GEN8_LEGACY_PDPES 4
#define GEN8_PTES I915_PTES(sizeof(gen8_pte_t))
+#define I915_PDPES_PER_PDP(dev) (USES_FULL_48BIT_PPGTT(dev) ?\
+ GEN8_PML4ES_PER_PML4 : GEN8_LEGACY_PDPES)
+
#define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD)
#define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */
#define PPAT_CACHED_INDEX _PAGE_PAT /* WB LLCeLLC */
@@ -124,10 +138,14 @@ enum i915_ggtt_view_type {
struct intel_rotation_info {
unsigned int height;
unsigned int pitch;
+ unsigned int uv_offset;
uint32_t pixel_format;
uint64_t fb_modifier;
unsigned int width_pages, height_pages;
uint64_t size;
+ unsigned int width_pages_uv, height_pages_uv;
+ uint64_t size_uv;
+ unsigned int uv_start_page;
};
struct i915_ggtt_view {
@@ -135,7 +153,7 @@ struct i915_ggtt_view {
union {
struct {
- unsigned long offset;
+ u64 offset;
unsigned int size;
} partial;
} params;
@@ -241,9 +259,17 @@ struct i915_page_directory {
};
struct i915_page_directory_pointer {
- /* struct page *page; */
- DECLARE_BITMAP(used_pdpes, GEN8_LEGACY_PDPES);
- struct i915_page_directory *page_directory[GEN8_LEGACY_PDPES];
+ struct i915_page_dma base;
+
+ unsigned long *used_pdpes;
+ struct i915_page_directory **page_directory;
+};
+
+struct i915_pml4 {
+ struct i915_page_dma base;
+
+ DECLARE_BITMAP(used_pml4es, GEN8_PML4ES_PER_PML4);
+ struct i915_page_directory_pointer *pdps[GEN8_PML4ES_PER_PML4];
};
struct i915_address_space {
@@ -256,6 +282,7 @@ struct i915_address_space {
struct i915_page_scratch *scratch_page;
struct i915_page_table *scratch_pt;
struct i915_page_directory *scratch_pd;
+ struct i915_page_directory_pointer *scratch_pdp; /* GEN8+ & 48b PPGTT */
/**
* List of objects currently involved in rendering.
@@ -318,6 +345,7 @@ struct i915_gtt {
struct i915_address_space base;
size_t stolen_size; /* Total size of stolen memory */
+ size_t stolen_usable_size; /* Total size minus BIOS reserved */
u64 mappable_end; /* End offset that we can CPU map */
struct io_mapping *mappable; /* Mapping to our CPU mappable region */
phys_addr_t mappable_base; /* PA of our GMADR */
@@ -341,8 +369,9 @@ struct i915_hw_ppgtt {
struct drm_mm_node node;
unsigned long pd_dirty_rings;
union {
- struct i915_page_directory_pointer pdp;
- struct i915_page_directory pd;
+ struct i915_pml4 pml4; /* GEN8+ & 48b PPGTT */
+ struct i915_page_directory_pointer pdp; /* GEN8+ */
+ struct i915_page_directory pd; /* GEN6-7 */
};
struct drm_i915_file_private *file_priv;
@@ -365,7 +394,8 @@ struct i915_hw_ppgtt {
*/
#define gen6_for_each_pde(pt, pd, start, length, temp, iter) \
for (iter = gen6_pde_index(start); \
- pt = (pd)->page_table[iter], length > 0 && iter < I915_PDES; \
+ length > 0 && iter < I915_PDES ? \
+ (pt = (pd)->page_table[iter]), 1 : 0; \
iter++, \
temp = ALIGN(start+1, 1 << GEN6_PDE_SHIFT) - start, \
temp = min_t(unsigned, temp, length), \
@@ -430,30 +460,30 @@ static inline uint32_t gen6_pde_index(uint32_t addr)
*/
#define gen8_for_each_pde(pt, pd, start, length, temp, iter) \
for (iter = gen8_pde_index(start); \
- pt = (pd)->page_table[iter], length > 0 && iter < I915_PDES; \
+ length > 0 && iter < I915_PDES ? \
+ (pt = (pd)->page_table[iter]), 1 : 0; \
iter++, \
temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start, \
temp = min(temp, length), \
start += temp, length -= temp)
-#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \
- for (iter = gen8_pdpe_index(start); \
- pd = (pdp)->page_directory[iter], length > 0 && iter < GEN8_LEGACY_PDPES; \
+#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \
+ for (iter = gen8_pdpe_index(start); \
+ length > 0 && (iter < I915_PDPES_PER_PDP(dev)) ? \
+ (pd = (pdp)->page_directory[iter]), 1 : 0; \
iter++, \
temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \
temp = min(temp, length), \
start += temp, length -= temp)
-/* Clamp length to the next page_directory boundary */
-static inline uint64_t gen8_clamp_pd(uint64_t start, uint64_t length)
-{
- uint64_t next_pd = ALIGN(start + 1, 1 << GEN8_PDPE_SHIFT);
-
- if (next_pd > (start + length))
- return length;
-
- return next_pd - start;
-}
+#define gen8_for_each_pml4e(pdp, pml4, start, length, temp, iter) \
+ for (iter = gen8_pml4e_index(start); \
+ length > 0 && iter < GEN8_PML4ES_PER_PML4 ? \
+ (pdp = (pml4)->pdps[iter]), 1 : 0; \
+ iter++, \
+ temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT) - start, \
+ temp = min(temp, length), \
+ start += temp, length -= temp)
static inline uint32_t gen8_pte_index(uint64_t address)
{
@@ -472,8 +502,7 @@ static inline uint32_t gen8_pdpe_index(uint64_t address)
static inline uint32_t gen8_pml4e_index(uint64_t address)
{
- WARN_ON(1); /* For 64B */
- return 0;
+ return (address >> GEN8_PML4E_SHIFT) & GEN8_PML4E_MASK;
}
static inline size_t gen8_pte_count(uint64_t address, uint64_t length)
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index f6ecbda2c604..f7df54a8ee2b 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -73,7 +73,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
*/
unsigned long
i915_gem_shrink(struct drm_i915_private *dev_priv,
- long target, unsigned flags)
+ unsigned long target, unsigned flags)
{
const struct {
struct list_head *list;
@@ -85,6 +85,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
}, *phase;
unsigned long count = 0;
+ trace_i915_gem_shrink(dev_priv, target, flags);
+ i915_gem_retire_requests(dev_priv->dev);
+
/*
* As we may completely rewrite the (un)bound list whilst unbinding
* (due to retiring requests) we have to strictly process only
@@ -123,6 +126,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
obj->madv != I915_MADV_DONTNEED)
continue;
+ if ((flags & I915_SHRINK_ACTIVE) == 0 && obj->active)
+ continue;
+
drm_gem_object_reference(&obj->base);
/* For the unbound phase, this should be a no-op! */
@@ -139,11 +145,13 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
list_splice(&still_in_list, phase->list);
}
+ i915_gem_retire_requests(dev_priv->dev);
+
return count;
}
/**
- * i915_gem_shrink - Shrink buffer object caches completely
+ * i915_gem_shrink_all - Shrink buffer object caches completely
* @dev_priv: i915 device
*
* This is a simple wraper around i915_gem_shrink() to aggressively shrink all
@@ -158,9 +166,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
*/
unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)
{
- i915_gem_evict_everything(dev_priv->dev);
- return i915_gem_shrink(dev_priv, LONG_MAX,
- I915_SHRINK_BOUND | I915_SHRINK_UNBOUND);
+ return i915_gem_shrink(dev_priv, -1UL,
+ I915_SHRINK_BOUND |
+ I915_SHRINK_UNBOUND |
+ I915_SHRINK_ACTIVE);
}
static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
@@ -213,7 +222,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
count += obj->base.size >> PAGE_SHIFT;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
- if (obj->pages_pin_count == num_vma_bound(obj))
+ if (!obj->active && obj->pages_pin_count == num_vma_bound(obj))
count += obj->base.size >> PAGE_SHIFT;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index f361c4a56995..cdacf3f5b77a 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -30,6 +30,9 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
+#define KB(x) ((x) * 1024)
+#define MB(x) (KB(x) * 1024)
+
/*
* The BIOS typically reserves some of the system's memory for the exclusive
* use of the integrated graphics. This memory is no longer available for
@@ -42,23 +45,38 @@
* for is a boon.
*/
-int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
- struct drm_mm_node *node, u64 size,
- unsigned alignment)
+int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
+ struct drm_mm_node *node, u64 size,
+ unsigned alignment, u64 start, u64 end)
{
int ret;
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return -ENODEV;
+ /* See the comment at the drm_mm_init() call for more about this check.
+ * WaSkipStolenMemoryFirstPage:bdw,chv (incomplete) */
+ if (INTEL_INFO(dev_priv)->gen == 8 && start < 4096)
+ start = 4096;
+
mutex_lock(&dev_priv->mm.stolen_lock);
- ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size, alignment,
- DRM_MM_SEARCH_DEFAULT);
+ ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, size,
+ alignment, start, end,
+ DRM_MM_SEARCH_DEFAULT);
mutex_unlock(&dev_priv->mm.stolen_lock);
return ret;
}
+int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
+ struct drm_mm_node *node, u64 size,
+ unsigned alignment)
+{
+ return i915_gem_stolen_insert_node_in_range(dev_priv, node, size,
+ alignment, 0,
+ dev_priv->gtt.stolen_usable_size);
+}
+
void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node)
{
@@ -76,24 +94,91 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
/* Almost universally we can find the Graphics Base of Stolen Memory
* at offset 0x5c in the igfx configuration space. On a few (desktop)
* machines this is also mirrored in the bridge device at different
- * locations, or in the MCHBAR. On gen2, the layout is again slightly
- * different with the Graphics Segment immediately following Top of
- * Memory (or Top of Usable DRAM). Note it appears that TOUD is only
- * reported by 865g, so we just use the top of memory as determined
- * by the e820 probe.
+ * locations, or in the MCHBAR.
+ *
+ * On 865 we just check the TOUD register.
+ *
+ * On 830/845/85x the stolen memory base isn't available in any
+ * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size.
*
- * XXX However gen2 requires an unavailable symbol.
*/
base = 0;
if (INTEL_INFO(dev)->gen >= 3) {
/* Read Graphics Base of Stolen Memory directly */
pci_read_config_dword(dev->pdev, 0x5c, &base);
base &= ~((1<<20) - 1);
- } else { /* GEN2 */
-#if 0
- /* Stolen is immediately above Top of Memory */
- base = max_low_pfn_mapped << PAGE_SHIFT;
-#endif
+ } else if (IS_I865G(dev)) {
+ u16 toud = 0;
+
+ /*
+ * FIXME is the graphics stolen memory region
+ * always at TOUD? Ie. is it always the last
+ * one to be allocated by the BIOS?
+ */
+ pci_bus_read_config_word(dev->pdev->bus, PCI_DEVFN(0, 0),
+ I865_TOUD, &toud);
+
+ base = toud << 16;
+ } else if (IS_I85X(dev)) {
+ u32 tseg_size = 0;
+ u32 tom;
+ u8 tmp;
+
+ pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
+ I85X_ESMRAMC, &tmp);
+
+ if (tmp & TSEG_ENABLE)
+ tseg_size = MB(1);
+
+ pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 1),
+ I85X_DRB3, &tmp);
+ tom = tmp * MB(32);
+
+ base = tom - tseg_size - dev_priv->gtt.stolen_size;
+ } else if (IS_845G(dev)) {
+ u32 tseg_size = 0;
+ u32 tom;
+ u8 tmp;
+
+ pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
+ I845_ESMRAMC, &tmp);
+
+ if (tmp & TSEG_ENABLE) {
+ switch (tmp & I845_TSEG_SIZE_MASK) {
+ case I845_TSEG_SIZE_512K:
+ tseg_size = KB(512);
+ break;
+ case I845_TSEG_SIZE_1M:
+ tseg_size = MB(1);
+ break;
+ }
+ }
+
+ pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
+ I830_DRB3, &tmp);
+ tom = tmp * MB(32);
+
+ base = tom - tseg_size - dev_priv->gtt.stolen_size;
+ } else if (IS_I830(dev)) {
+ u32 tseg_size = 0;
+ u32 tom;
+ u8 tmp;
+
+ pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
+ I830_ESMRAMC, &tmp);
+
+ if (tmp & TSEG_ENABLE) {
+ if (tmp & I830_TSEG_SIZE_1M)
+ tseg_size = MB(1);
+ else
+ tseg_size = KB(512);
+ }
+
+ pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
+ I830_DRB3, &tmp);
+ tom = tmp * MB(32);
+
+ base = tom - tseg_size - dev_priv->gtt.stolen_size;
}
if (base == 0)
@@ -186,6 +271,29 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
drm_mm_takedown(&dev_priv->mm.stolen);
}
+static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
+ unsigned long *base, unsigned long *size)
+{
+ uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ?
+ CTG_STOLEN_RESERVED :
+ ELK_STOLEN_RESERVED);
+ unsigned long stolen_top = dev_priv->mm.stolen_base +
+ dev_priv->gtt.stolen_size;
+
+ *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
+
+ WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base);
+
+ /* On these platforms, the register doesn't have a size field, so the
+ * size is the distance between the base and the top of the stolen
+ * memory. We also have the genuine case where base is zero and there's
+ * nothing reserved. */
+ if (*base == 0)
+ *size = 0;
+ else
+ *size = stolen_top - *base;
+}
+
static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv,
unsigned long *base, unsigned long *size)
{
@@ -281,7 +389,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
int i915_gem_init_stolen(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long reserved_total, reserved_base, reserved_size;
+ unsigned long reserved_total, reserved_base = 0, reserved_size;
unsigned long stolen_top;
mutex_init(&dev_priv->mm.stolen_lock);
@@ -305,7 +413,12 @@ int i915_gem_init_stolen(struct drm_device *dev)
switch (INTEL_INFO(dev_priv)->gen) {
case 2:
case 3:
+ break;
case 4:
+ if (IS_G4X(dev))
+ g4x_get_stolen_reserved(dev_priv, &reserved_base,
+ &reserved_size);
+ break;
case 5:
/* Assume the gen6 maximum for the older platforms. */
reserved_size = 1024 * 1024;
@@ -352,9 +465,21 @@ int i915_gem_init_stolen(struct drm_device *dev)
dev_priv->gtt.stolen_size >> 10,
(dev_priv->gtt.stolen_size - reserved_total) >> 10);
- /* Basic memrange allocator for stolen space */
- drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
- reserved_total);
+ dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size -
+ reserved_total;
+
+ /*
+ * Basic memrange allocator for stolen space.
+ *
+ * TODO: Notice that some platforms require us to not use the first page
+ * of the stolen memory but their BIOSes may still put the framebuffer
+ * on the first page. So we don't reserve this page for now because of
+ * that. Our current solution is to just prevent new nodes from being
+ * inserted on the first page - see the check we have at
+ * i915_gem_stolen_insert_node_in_range(). We may want to fix the fbcon
+ * problem later.
+ */
+ drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
return 0;
}
@@ -544,7 +669,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
- goto err_out;
+ goto err;
}
/* To simplify the initialisation sequence between KMS and GTT,
@@ -558,23 +683,19 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
ret = drm_mm_reserve_node(&ggtt->mm, &vma->node);
if (ret) {
DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
- goto err_vma;
+ goto err;
}
- }
- vma->bound |= GLOBAL_BIND;
+ vma->bound |= GLOBAL_BIND;
+ list_add_tail(&vma->mm_list, &ggtt->inactive_list);
+ }
list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
- list_add_tail(&vma->mm_list, &ggtt->inactive_list);
i915_gem_object_pin_pages(obj);
return obj;
-err_vma:
- i915_gem_vma_destroy(vma);
-err_out:
- i915_gem_stolen_remove_node(dev_priv, stolen);
- kfree(stolen);
+err:
drm_gem_object_unreference(&obj->base);
return NULL;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index 8fd431bcdfd3..19fb0bddc1cd 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -50,7 +50,6 @@ struct i915_mmu_notifier {
struct mmu_notifier mn;
struct rb_root objects;
struct list_head linear;
- unsigned long serial;
bool has_linear;
};
@@ -59,13 +58,16 @@ struct i915_mmu_object {
struct interval_tree_node it;
struct list_head link;
struct drm_i915_gem_object *obj;
+ struct work_struct work;
+ bool active;
bool is_linear;
};
-static unsigned long cancel_userptr(struct drm_i915_gem_object *obj)
+static void __cancel_userptr__worker(struct work_struct *work)
{
+ struct i915_mmu_object *mo = container_of(work, typeof(*mo), work);
+ struct drm_i915_gem_object *obj = mo->obj;
struct drm_device *dev = obj->base.dev;
- unsigned long end;
mutex_lock(&dev->struct_mutex);
/* Cancel any active worker and force us to re-evaluate gup */
@@ -88,45 +90,28 @@ static unsigned long cancel_userptr(struct drm_i915_gem_object *obj)
dev_priv->mm.interruptible = was_interruptible;
}
- end = obj->userptr.ptr + obj->base.size;
-
drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex);
-
- return end;
}
-static void *invalidate_range__linear(struct i915_mmu_notifier *mn,
- struct mm_struct *mm,
- unsigned long start,
- unsigned long end)
+static unsigned long cancel_userptr(struct i915_mmu_object *mo)
{
- struct i915_mmu_object *mo;
- unsigned long serial;
-
-restart:
- serial = mn->serial;
- list_for_each_entry(mo, &mn->linear, link) {
- struct drm_i915_gem_object *obj;
-
- if (mo->it.last < start || mo->it.start > end)
- continue;
-
- obj = mo->obj;
-
- if (!kref_get_unless_zero(&obj->base.refcount))
- continue;
-
- spin_unlock(&mn->lock);
-
- cancel_userptr(obj);
-
- spin_lock(&mn->lock);
- if (serial != mn->serial)
- goto restart;
+ unsigned long end = mo->obj->userptr.ptr + mo->obj->base.size;
+
+ /* The mmu_object is released late when destroying the
+ * GEM object so it is entirely possible to gain a
+ * reference on an object in the process of being freed
+ * since our serialisation is via the spinlock and not
+ * the struct_mutex - and consequently use it after it
+ * is freed and then double free it.
+ */
+ if (mo->active && kref_get_unless_zero(&mo->obj->base.refcount)) {
+ schedule_work(&mo->work);
+ /* only schedule one work packet to avoid the refleak */
+ mo->active = false;
}
- return NULL;
+ return end;
}
static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
@@ -134,46 +119,32 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
unsigned long start,
unsigned long end)
{
- struct i915_mmu_notifier *mn = container_of(_mn, struct i915_mmu_notifier, mn);
- struct interval_tree_node *it = NULL;
- unsigned long next = start;
- unsigned long serial = 0;
-
- end--; /* interval ranges are inclusive, but invalidate range is exclusive */
- while (next < end) {
- struct drm_i915_gem_object *obj = NULL;
-
- spin_lock(&mn->lock);
- if (mn->has_linear)
- it = invalidate_range__linear(mn, mm, start, end);
- else if (serial == mn->serial)
- it = interval_tree_iter_next(it, next, end);
- else
- it = interval_tree_iter_first(&mn->objects, start, end);
- if (it != NULL) {
- obj = container_of(it, struct i915_mmu_object, it)->obj;
-
- /* The mmu_object is released late when destroying the
- * GEM object so it is entirely possible to gain a
- * reference on an object in the process of being freed
- * since our serialisation is via the spinlock and not
- * the struct_mutex - and consequently use it after it
- * is freed and then double free it.
- */
- if (!kref_get_unless_zero(&obj->base.refcount)) {
- spin_unlock(&mn->lock);
- serial = 0;
+ struct i915_mmu_notifier *mn =
+ container_of(_mn, struct i915_mmu_notifier, mn);
+ struct i915_mmu_object *mo;
+
+ /* interval ranges are inclusive, but invalidate range is exclusive */
+ end--;
+
+ spin_lock(&mn->lock);
+ if (mn->has_linear) {
+ list_for_each_entry(mo, &mn->linear, link) {
+ if (mo->it.last < start || mo->it.start > end)
continue;
- }
- serial = mn->serial;
+ cancel_userptr(mo);
}
- spin_unlock(&mn->lock);
- if (obj == NULL)
- return;
+ } else {
+ struct interval_tree_node *it;
- next = cancel_userptr(obj);
+ it = interval_tree_iter_first(&mn->objects, start, end);
+ while (it) {
+ mo = container_of(it, struct i915_mmu_object, it);
+ start = cancel_userptr(mo);
+ it = interval_tree_iter_next(it, start, end);
+ }
}
+ spin_unlock(&mn->lock);
}
static const struct mmu_notifier_ops i915_gem_userptr_notifier = {
@@ -193,7 +164,6 @@ i915_mmu_notifier_create(struct mm_struct *mm)
spin_lock_init(&mn->lock);
mn->mn.ops = &i915_gem_userptr_notifier;
mn->objects = RB_ROOT;
- mn->serial = 1;
INIT_LIST_HEAD(&mn->linear);
mn->has_linear = false;
@@ -207,12 +177,6 @@ i915_mmu_notifier_create(struct mm_struct *mm)
return mn;
}
-static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mn)
-{
- if (++mn->serial == 0)
- mn->serial = 1;
-}
-
static int
i915_mmu_notifier_add(struct drm_device *dev,
struct i915_mmu_notifier *mn,
@@ -259,10 +223,9 @@ i915_mmu_notifier_add(struct drm_device *dev,
} else
interval_tree_insert(&mo->it, &mn->objects);
- if (ret == 0) {
+ if (ret == 0)
list_add(&mo->link, &mn->linear);
- __i915_mmu_notifier_update_serial(mn);
- }
+
spin_unlock(&mn->lock);
mutex_unlock(&dev->struct_mutex);
@@ -290,7 +253,6 @@ i915_mmu_notifier_del(struct i915_mmu_notifier *mn,
mn->has_linear = i915_mmu_notifier_has_linear(mn);
else
interval_tree_remove(&mo->it, &mn->objects);
- __i915_mmu_notifier_update_serial(mn);
spin_unlock(&mn->lock);
}
@@ -357,6 +319,7 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj,
mo->it.start = obj->userptr.ptr;
mo->it.last = mo->it.start + obj->base.size - 1;
mo->obj = obj;
+ INIT_WORK(&mo->work, __cancel_userptr__worker);
ret = i915_mmu_notifier_add(obj->base.dev, mn, mo);
if (ret) {
@@ -565,31 +528,65 @@ __i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj,
return ret;
}
+static int
+__i915_gem_userptr_set_active(struct drm_i915_gem_object *obj,
+ bool value)
+{
+ int ret = 0;
+
+ /* During mm_invalidate_range we need to cancel any userptr that
+ * overlaps the range being invalidated. Doing so requires the
+ * struct_mutex, and that risks recursion. In order to cause
+ * recursion, the user must alias the userptr address space with
+ * a GTT mmapping (possible with a MAP_FIXED) - then when we have
+ * to invalidate that mmaping, mm_invalidate_range is called with
+ * the userptr address *and* the struct_mutex held. To prevent that
+ * we set a flag under the i915_mmu_notifier spinlock to indicate
+ * whether this object is valid.
+ */
+#if defined(CONFIG_MMU_NOTIFIER)
+ if (obj->userptr.mmu_object == NULL)
+ return 0;
+
+ spin_lock(&obj->userptr.mmu_object->mn->lock);
+ /* In order to serialise get_pages with an outstanding
+ * cancel_userptr, we must drop the struct_mutex and try again.
+ */
+ if (!value || !work_pending(&obj->userptr.mmu_object->work))
+ obj->userptr.mmu_object->active = value;
+ else
+ ret = -EAGAIN;
+ spin_unlock(&obj->userptr.mmu_object->mn->lock);
+#endif
+
+ return ret;
+}
+
static void
__i915_gem_userptr_get_pages_worker(struct work_struct *_work)
{
struct get_pages_work *work = container_of(_work, typeof(*work), work);
struct drm_i915_gem_object *obj = work->obj;
struct drm_device *dev = obj->base.dev;
- const int num_pages = obj->base.size >> PAGE_SHIFT;
+ const int npages = obj->base.size >> PAGE_SHIFT;
struct page **pvec;
int pinned, ret;
ret = -ENOMEM;
pinned = 0;
- pvec = kmalloc(num_pages*sizeof(struct page *),
+ pvec = kmalloc(npages*sizeof(struct page *),
GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
if (pvec == NULL)
- pvec = drm_malloc_ab(num_pages, sizeof(struct page *));
+ pvec = drm_malloc_ab(npages, sizeof(struct page *));
if (pvec != NULL) {
struct mm_struct *mm = obj->userptr.mm->mm;
down_read(&mm->mmap_sem);
- while (pinned < num_pages) {
+ while (pinned < npages) {
ret = get_user_pages(work->task, mm,
obj->userptr.ptr + pinned * PAGE_SIZE,
- num_pages - pinned,
+ npages - pinned,
!obj->userptr.read_only, 0,
pvec + pinned, NULL);
if (ret < 0)
@@ -601,20 +598,22 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
}
mutex_lock(&dev->struct_mutex);
- if (obj->userptr.work != &work->work) {
- ret = 0;
- } else if (pinned == num_pages) {
- ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages);
- if (ret == 0) {
- list_add_tail(&obj->global_list, &to_i915(dev)->mm.unbound_list);
- obj->get_page.sg = obj->pages->sgl;
- obj->get_page.last = 0;
-
- pinned = 0;
+ if (obj->userptr.work == &work->work) {
+ if (pinned == npages) {
+ ret = __i915_gem_userptr_set_pages(obj, pvec, npages);
+ if (ret == 0) {
+ list_add_tail(&obj->global_list,
+ &to_i915(dev)->mm.unbound_list);
+ obj->get_page.sg = obj->pages->sgl;
+ obj->get_page.last = 0;
+ pinned = 0;
+ }
}
+ obj->userptr.work = ERR_PTR(ret);
+ if (ret)
+ __i915_gem_userptr_set_active(obj, false);
}
- obj->userptr.work = ERR_PTR(ret);
obj->userptr.workers--;
drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex);
@@ -627,11 +626,60 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
}
static int
+__i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj,
+ bool *active)
+{
+ struct get_pages_work *work;
+
+ /* Spawn a worker so that we can acquire the
+ * user pages without holding our mutex. Access
+ * to the user pages requires mmap_sem, and we have
+ * a strict lock ordering of mmap_sem, struct_mutex -
+ * we already hold struct_mutex here and so cannot
+ * call gup without encountering a lock inversion.
+ *
+ * Userspace will keep on repeating the operation
+ * (thanks to EAGAIN) until either we hit the fast
+ * path or the worker completes. If the worker is
+ * cancelled or superseded, the task is still run
+ * but the results ignored. (This leads to
+ * complications that we may have a stray object
+ * refcount that we need to be wary of when
+ * checking for existing objects during creation.)
+ * If the worker encounters an error, it reports
+ * that error back to this function through
+ * obj->userptr.work = ERR_PTR.
+ */
+ if (obj->userptr.workers >= I915_GEM_USERPTR_MAX_WORKERS)
+ return -EAGAIN;
+
+ work = kmalloc(sizeof(*work), GFP_KERNEL);
+ if (work == NULL)
+ return -ENOMEM;
+
+ obj->userptr.work = &work->work;
+ obj->userptr.workers++;
+
+ work->obj = obj;
+ drm_gem_object_reference(&obj->base);
+
+ work->task = current;
+ get_task_struct(work->task);
+
+ INIT_WORK(&work->work, __i915_gem_userptr_get_pages_worker);
+ schedule_work(&work->work);
+
+ *active = true;
+ return -EAGAIN;
+}
+
+static int
i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
{
const int num_pages = obj->base.size >> PAGE_SHIFT;
struct page **pvec;
int pinned, ret;
+ bool active;
/* If userspace should engineer that these pages are replaced in
* the vma between us binding this page into the GTT and completion
@@ -649,6 +697,20 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
* to the vma (discard or cloning) which should prevent the more
* egregious cases from causing harm.
*/
+ if (IS_ERR(obj->userptr.work)) {
+ /* active flag will have been dropped already by the worker */
+ ret = PTR_ERR(obj->userptr.work);
+ obj->userptr.work = NULL;
+ return ret;
+ }
+ if (obj->userptr.work)
+ /* active flag should still be held for the pending work */
+ return -EAGAIN;
+
+ /* Let the mmu-notifier know that we have begun and need cancellation */
+ ret = __i915_gem_userptr_set_active(obj, true);
+ if (ret)
+ return ret;
pvec = NULL;
pinned = 0;
@@ -657,73 +719,27 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
if (pvec == NULL) {
pvec = drm_malloc_ab(num_pages, sizeof(struct page *));
- if (pvec == NULL)
+ if (pvec == NULL) {
+ __i915_gem_userptr_set_active(obj, false);
return -ENOMEM;
+ }
}
pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages,
!obj->userptr.read_only, pvec);
}
- if (pinned < num_pages) {
- if (pinned < 0) {
- ret = pinned;
- pinned = 0;
- } else {
- /* Spawn a worker so that we can acquire the
- * user pages without holding our mutex. Access
- * to the user pages requires mmap_sem, and we have
- * a strict lock ordering of mmap_sem, struct_mutex -
- * we already hold struct_mutex here and so cannot
- * call gup without encountering a lock inversion.
- *
- * Userspace will keep on repeating the operation
- * (thanks to EAGAIN) until either we hit the fast
- * path or the worker completes. If the worker is
- * cancelled or superseded, the task is still run
- * but the results ignored. (This leads to
- * complications that we may have a stray object
- * refcount that we need to be wary of when
- * checking for existing objects during creation.)
- * If the worker encounters an error, it reports
- * that error back to this function through
- * obj->userptr.work = ERR_PTR.
- */
- ret = -EAGAIN;
- if (obj->userptr.work == NULL &&
- obj->userptr.workers < I915_GEM_USERPTR_MAX_WORKERS) {
- struct get_pages_work *work;
-
- work = kmalloc(sizeof(*work), GFP_KERNEL);
- if (work != NULL) {
- obj->userptr.work = &work->work;
- obj->userptr.workers++;
-
- work->obj = obj;
- drm_gem_object_reference(&obj->base);
-
- work->task = current;
- get_task_struct(work->task);
-
- INIT_WORK(&work->work, __i915_gem_userptr_get_pages_worker);
- schedule_work(&work->work);
- } else
- ret = -ENOMEM;
- } else {
- if (IS_ERR(obj->userptr.work)) {
- ret = PTR_ERR(obj->userptr.work);
- obj->userptr.work = NULL;
- }
- }
- }
- } else {
+
+ active = false;
+ if (pinned < 0)
+ ret = pinned, pinned = 0;
+ else if (pinned < num_pages)
+ ret = __i915_gem_userptr_get_pages_schedule(obj, &active);
+ else
ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages);
- if (ret == 0) {
- obj->userptr.work = NULL;
- pinned = 0;
- }
+ if (ret) {
+ __i915_gem_userptr_set_active(obj, active);
+ release_pages(pvec, pinned, 0);
}
-
- release_pages(pvec, pinned, 0);
drm_free_large(pvec);
return ret;
}
@@ -734,6 +750,7 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj)
struct sg_page_iter sg_iter;
BUG_ON(obj->userptr.work != NULL);
+ __i915_gem_userptr_set_active(obj, false);
if (obj->madv != I915_MADV_WILLNEED)
obj->dirty = 0;
@@ -804,7 +821,10 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
* Also note, that the object created here is not currently a "first class"
* object, in that several ioctls are banned. These are the CPU access
* ioctls: mmap(), pwrite and pread. In practice, you are expected to use
- * direct access via your pointer rather than use those ioctls.
+ * direct access via your pointer rather than use those ioctls. Another
+ * restriction is that we do not allow userptr surfaces to be pinned to the
+ * hardware and so we reject any attempt to create a framebuffer out of a
+ * userptr.
*
* If you think this is a good interface to use to pass GPU memory between
* drivers, please use dma-buf instead. In fact, wherever possible use
@@ -813,7 +833,6 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
int
i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_userptr *args = data;
struct drm_i915_gem_object *obj;
int ret;
@@ -826,9 +845,6 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file
if (offset_in_page(args->user_ptr | args->user_size))
return -EINVAL;
- if (args->user_size > dev_priv->gtt.base.total)
- return -E2BIG;
-
if (!access_ok(args->flags & I915_USERPTR_READ_ONLY ? VERIFY_READ : VERIFY_WRITE,
(char __user *)(unsigned long)args->user_ptr, args->user_size))
return -EFAULT;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 41d0739e6fdf..2f04e4f2ff35 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -30,11 +30,6 @@
#include <generated/utsrelease.h>
#include "i915_drv.h"
-static const char *yesno(int v)
-{
- return v ? "yes" : "no";
-}
-
static const char *ring_str(int ring)
{
switch (ring) {
@@ -197,8 +192,9 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m,
err_printf(m, " %s [%d]:\n", name, count);
while (count--) {
- err_printf(m, " %08x %8u %02x %02x [ ",
- err->gtt_offset,
+ err_printf(m, " %08x_%08x %8u %02x %02x [ ",
+ upper_32_bits(err->gtt_offset),
+ lower_32_bits(err->gtt_offset),
err->size,
err->read_domains,
err->write_domain);
@@ -427,15 +423,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, " (submitted by %s [%d])",
error->ring[i].comm,
error->ring[i].pid);
- err_printf(m, " --- gtt_offset = 0x%08x\n",
- obj->gtt_offset);
+ err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+ upper_32_bits(obj->gtt_offset),
+ lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
obj = error->ring[i].wa_batchbuffer;
if (obj) {
err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
- dev_priv->ring[i].name, obj->gtt_offset);
+ dev_priv->ring[i].name,
+ lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
@@ -454,22 +452,28 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
if ((obj = error->ring[i].ringbuffer)) {
err_printf(m, "%s --- ringbuffer = 0x%08x\n",
dev_priv->ring[i].name,
- obj->gtt_offset);
+ lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
if ((obj = error->ring[i].hws_page)) {
- err_printf(m, "%s --- HW Status = 0x%08x\n",
- dev_priv->ring[i].name,
- obj->gtt_offset);
+ u64 hws_offset = obj->gtt_offset;
+ u32 *hws_page = &obj->pages[0][0];
+
+ if (i915.enable_execlists) {
+ hws_offset += LRC_PPHWSP_PN * PAGE_SIZE;
+ hws_page = &obj->pages[LRC_PPHWSP_PN][0];
+ }
+ err_printf(m, "%s --- HW Status = 0x%08llx\n",
+ dev_priv->ring[i].name, hws_offset);
offset = 0;
for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
err_printf(m, "[%04x] %08x %08x %08x %08x\n",
offset,
- obj->pages[0][elt],
- obj->pages[0][elt+1],
- obj->pages[0][elt+2],
- obj->pages[0][elt+3]);
+ hws_page[elt],
+ hws_page[elt+1],
+ hws_page[elt+2],
+ hws_page[elt+3]);
offset += 16;
}
}
@@ -477,13 +481,14 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
if ((obj = error->ring[i].ctx)) {
err_printf(m, "%s --- HW Context = 0x%08x\n",
dev_priv->ring[i].name,
- obj->gtt_offset);
+ lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
}
if ((obj = error->semaphore_obj)) {
- err_printf(m, "Semaphore page = 0x%08x\n", obj->gtt_offset);
+ err_printf(m, "Semaphore page = 0x%08x\n",
+ lower_32_bits(obj->gtt_offset));
for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
err_printf(m, "[%04x] %08x %08x %08x %08x\n",
elt * 4,
@@ -591,7 +596,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
int num_pages;
bool use_ggtt;
int i = 0;
- u32 reloc_offset;
+ u64 reloc_offset;
if (src == NULL || src->pages == NULL)
return NULL;
@@ -787,20 +792,15 @@ static void i915_gem_record_fences(struct drm_device *dev,
int i;
if (IS_GEN3(dev) || IS_GEN2(dev)) {
- for (i = 0; i < 8; i++)
- error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
- if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
- for (i = 0; i < 8; i++)
- error->fence[i+8] = I915_READ(FENCE_REG_945_8 +
- (i * 4));
- } else if (IS_GEN5(dev) || IS_GEN4(dev))
- for (i = 0; i < 16; i++)
- error->fence[i] = I915_READ64(FENCE_REG_965_0 +
- (i * 8));
- else if (INTEL_INFO(dev)->gen >= 6)
for (i = 0; i < dev_priv->num_fence_regs; i++)
- error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 +
- (i * 8));
+ error->fence[i] = I915_READ(FENCE_REG(i));
+ } else if (IS_GEN5(dev) || IS_GEN4(dev)) {
+ for (i = 0; i < dev_priv->num_fence_regs; i++)
+ error->fence[i] = I915_READ64(FENCE_REG_965_LO(i));
+ } else if (INTEL_INFO(dev)->gen >= 6) {
+ for (i = 0; i < dev_priv->num_fence_regs; i++)
+ error->fence[i] = I915_READ64(FENCE_REG_GEN6_LO(i));
+ }
}
@@ -886,7 +886,7 @@ static void i915_record_ring_state(struct drm_device *dev,
ering->faddr = I915_READ(DMA_FADD_I8XX);
ering->ipeir = I915_READ(IPEIR);
ering->ipehr = I915_READ(IPEHR);
- ering->instdone = I915_READ(INSTDONE);
+ ering->instdone = I915_READ(GEN2_INSTDONE);
}
ering->waiting = waitqueue_active(&ring->irq_queue);
@@ -1388,12 +1388,12 @@ void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone)
memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
if (IS_GEN2(dev) || IS_GEN3(dev))
- instdone[0] = I915_READ(INSTDONE);
+ instdone[0] = I915_READ(GEN2_INSTDONE);
else if (IS_GEN4(dev) || IS_GEN5(dev) || IS_GEN6(dev)) {
- instdone[0] = I915_READ(INSTDONE_I965);
- instdone[1] = I915_READ(INSTDONE1);
+ instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
+ instdone[1] = I915_READ(GEN4_INSTDONE1);
} else if (INTEL_INFO(dev)->gen >= 7) {
- instdone[0] = I915_READ(GEN7_INSTDONE_1);
+ instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
instdone[1] = I915_READ(GEN7_SC_INSTDONE);
instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
index ccdc6c8ac20b..c4cb1c0c4d0d 100644
--- a/drivers/gpu/drm/i915/i915_guc_reg.h
+++ b/drivers/gpu/drm/i915/i915_guc_reg.h
@@ -37,14 +37,11 @@
#define GS_UKERNEL_READY (0xF0 << GS_UKERNEL_SHIFT)
#define GS_MIA_SHIFT 16
#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT)
-
-#define GUC_WOPCM_SIZE 0xc050
-#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */
-#define GUC_WOPCM_OFFSET 0x80000 /* 512KB */
+#define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT)
#define SOFT_SCRATCH(n) (0xc180 + ((n) * 4))
-#define UOS_RSA_SCRATCH_0 0xc200
+#define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4)
#define DMA_ADDR_0_LOW 0xc300
#define DMA_ADDR_0_HIGH 0xc304
#define DMA_ADDR_1_LOW 0xc308
@@ -56,10 +53,19 @@
#define UOS_MOVE (1<<4)
#define START_DMA (1<<0)
#define DMA_GUC_WOPCM_OFFSET 0xc340
+#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */
+#define GUC_MAX_IDLE_COUNT 0xC3E4
+
+#define GUC_WOPCM_SIZE 0xc050
+#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */
+
+/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
+#define GUC_WOPCM_TOP (GUC_WOPCM_SIZE_VALUE)
#define GEN8_GT_PM_CONFIG 0x138140
+#define GEN9LP_GT_PM_CONFIG 0x138140
#define GEN9_GT_PM_CONFIG 0x13816c
-#define GEN8_GT_DOORBELL_ENABLE (1<<0)
+#define GT_DOORBELL_ENABLE (1<<0)
#define GEN8_GTCR 0x4274
#define GEN8_GTCR_INVALIDATE (1<<0)
@@ -80,7 +86,8 @@
GUC_ENABLE_READ_CACHE_LOGIC | \
GUC_ENABLE_MIA_CACHING | \
GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA | \
- GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA)
+ GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \
+ GUC_ENABLE_MIA_CLOCK_GATING)
#define HOST2GUC_INTERRUPT 0xc4c8
#define HOST2GUC_TRIGGER (1<<0)
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
new file mode 100644
index 000000000000..036b42bae827
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -0,0 +1,975 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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/firmware.h>
+#include <linux/circ_buf.h>
+#include "i915_drv.h"
+#include "intel_guc.h"
+
+/**
+ * DOC: GuC Client
+ *
+ * i915_guc_client:
+ * We use the term client to avoid confusion with contexts. A i915_guc_client is
+ * equivalent to GuC object guc_context_desc. This context descriptor is
+ * allocated from a pool of 1024 entries. Kernel driver will allocate doorbell
+ * and workqueue for it. Also the process descriptor (guc_process_desc), which
+ * is mapped to client space. So the client can write Work Item then ring the
+ * doorbell.
+ *
+ * To simplify the implementation, we allocate one gem object that contains all
+ * pages for doorbell, process descriptor and workqueue.
+ *
+ * The Scratch registers:
+ * There are 16 MMIO-based registers start from 0xC180. The kernel driver writes
+ * a value to the action register (SOFT_SCRATCH_0) along with any data. It then
+ * triggers an interrupt on the GuC via another register write (0xC4C8).
+ * Firmware writes a success/fail code back to the action register after
+ * processes the request. The kernel driver polls waiting for this update and
+ * then proceeds.
+ * See host2guc_action()
+ *
+ * Doorbells:
+ * Doorbells are interrupts to uKernel. A doorbell is a single cache line (QW)
+ * mapped into process space.
+ *
+ * Work Items:
+ * There are several types of work items that the host may place into a
+ * workqueue, each with its own requirements and limitations. Currently only
+ * WQ_TYPE_INORDER is needed to support legacy submission via GuC, which
+ * represents in-order queue. The kernel driver packs ring tail pointer and an
+ * ELSP context descriptor dword into Work Item.
+ * See guc_add_workqueue_item()
+ *
+ */
+
+/*
+ * Read GuC command/status register (SOFT_SCRATCH_0)
+ * Return true if it contains a response rather than a command
+ */
+static inline bool host2guc_action_response(struct drm_i915_private *dev_priv,
+ u32 *status)
+{
+ u32 val = I915_READ(SOFT_SCRATCH(0));
+ *status = val;
+ return GUC2HOST_IS_RESPONSE(val);
+}
+
+static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ u32 status;
+ int i;
+ int ret;
+
+ if (WARN_ON(len < 1 || len > 15))
+ return -EINVAL;
+
+ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+ spin_lock(&dev_priv->guc.host2guc_lock);
+
+ dev_priv->guc.action_count += 1;
+ dev_priv->guc.action_cmd = data[0];
+
+ for (i = 0; i < len; i++)
+ I915_WRITE(SOFT_SCRATCH(i), data[i]);
+
+ POSTING_READ(SOFT_SCRATCH(i - 1));
+
+ I915_WRITE(HOST2GUC_INTERRUPT, HOST2GUC_TRIGGER);
+
+ /* No HOST2GUC command should take longer than 10ms */
+ ret = wait_for_atomic(host2guc_action_response(dev_priv, &status), 10);
+ if (status != GUC2HOST_STATUS_SUCCESS) {
+ /*
+ * Either the GuC explicitly returned an error (which
+ * we convert to -EIO here) or no response at all was
+ * received within the timeout limit (-ETIMEDOUT)
+ */
+ if (ret != -ETIMEDOUT)
+ ret = -EIO;
+
+ DRM_ERROR("GUC: host2guc action 0x%X failed. ret=%d "
+ "status=0x%08X response=0x%08X\n",
+ data[0], ret, status,
+ I915_READ(SOFT_SCRATCH(15)));
+
+ dev_priv->guc.action_fail += 1;
+ dev_priv->guc.action_err = ret;
+ }
+ dev_priv->guc.action_status = status;
+
+ spin_unlock(&dev_priv->guc.host2guc_lock);
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+ return ret;
+}
+
+/*
+ * Tell the GuC to allocate or deallocate a specific doorbell
+ */
+
+static int host2guc_allocate_doorbell(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ u32 data[2];
+
+ data[0] = HOST2GUC_ACTION_ALLOCATE_DOORBELL;
+ data[1] = client->ctx_index;
+
+ return host2guc_action(guc, data, 2);
+}
+
+static int host2guc_release_doorbell(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ u32 data[2];
+
+ data[0] = HOST2GUC_ACTION_DEALLOCATE_DOORBELL;
+ data[1] = client->ctx_index;
+
+ return host2guc_action(guc, data, 2);
+}
+
+static int host2guc_sample_forcewake(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct drm_device *dev = dev_priv->dev;
+ u32 data[2];
+
+ data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
+ /* WaRsDisableCoarsePowerGating:skl,bxt */
+ if (!intel_enable_rc6(dev_priv->dev) ||
+ (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
+ (IS_SKL_GT3(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)) ||
+ (IS_SKL_GT4(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)))
+ data[1] = 0;
+ else
+ /* bit 0 and 1 are for Render and Media domain separately */
+ data[1] = GUC_FORCEWAKE_RENDER | GUC_FORCEWAKE_MEDIA;
+
+ return host2guc_action(guc, data, ARRAY_SIZE(data));
+}
+
+/*
+ * Initialise, update, or clear doorbell data shared with the GuC
+ *
+ * These functions modify shared data and so need access to the mapped
+ * client object which contains the page being used for the doorbell
+ */
+
+static void guc_init_doorbell(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ struct guc_doorbell_info *doorbell;
+ void *base;
+
+ base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
+ doorbell = base + client->doorbell_offset;
+
+ doorbell->db_status = 1;
+ doorbell->cookie = 0;
+
+ kunmap_atomic(base);
+}
+
+static int guc_ring_doorbell(struct i915_guc_client *gc)
+{
+ struct guc_process_desc *desc;
+ union guc_doorbell_qw db_cmp, db_exc, db_ret;
+ union guc_doorbell_qw *db;
+ void *base;
+ int attempt = 2, ret = -EAGAIN;
+
+ base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
+ desc = base + gc->proc_desc_offset;
+
+ /* Update the tail so it is visible to GuC */
+ desc->tail = gc->wq_tail;
+
+ /* current cookie */
+ db_cmp.db_status = GUC_DOORBELL_ENABLED;
+ db_cmp.cookie = gc->cookie;
+
+ /* cookie to be updated */
+ db_exc.db_status = GUC_DOORBELL_ENABLED;
+ db_exc.cookie = gc->cookie + 1;
+ if (db_exc.cookie == 0)
+ db_exc.cookie = 1;
+
+ /* pointer of current doorbell cacheline */
+ db = base + gc->doorbell_offset;
+
+ while (attempt--) {
+ /* lets ring the doorbell */
+ db_ret.value_qw = atomic64_cmpxchg((atomic64_t *)db,
+ db_cmp.value_qw, db_exc.value_qw);
+
+ /* if the exchange was successfully executed */
+ if (db_ret.value_qw == db_cmp.value_qw) {
+ /* db was successfully rung */
+ gc->cookie = db_exc.cookie;
+ ret = 0;
+ break;
+ }
+
+ /* XXX: doorbell was lost and need to acquire it again */
+ if (db_ret.db_status == GUC_DOORBELL_DISABLED)
+ break;
+
+ DRM_ERROR("Cookie mismatch. Expected %d, returned %d\n",
+ db_cmp.cookie, db_ret.cookie);
+
+ /* update the cookie to newly read cookie from GuC */
+ db_cmp.cookie = db_ret.cookie;
+ db_exc.cookie = db_ret.cookie + 1;
+ if (db_exc.cookie == 0)
+ db_exc.cookie = 1;
+ }
+
+ kunmap_atomic(base);
+ return ret;
+}
+
+static void guc_disable_doorbell(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct guc_doorbell_info *doorbell;
+ void *base;
+ int drbreg = GEN8_DRBREGL(client->doorbell_id);
+ int value;
+
+ base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
+ doorbell = base + client->doorbell_offset;
+
+ doorbell->db_status = 0;
+
+ kunmap_atomic(base);
+
+ I915_WRITE(drbreg, I915_READ(drbreg) & ~GEN8_DRB_VALID);
+
+ value = I915_READ(drbreg);
+ WARN_ON((value & GEN8_DRB_VALID) != 0);
+
+ I915_WRITE(GEN8_DRBREGU(client->doorbell_id), 0);
+ I915_WRITE(drbreg, 0);
+
+ /* XXX: wait for any interrupts */
+ /* XXX: wait for workqueue to drain */
+}
+
+/*
+ * Select, assign and relase doorbell cachelines
+ *
+ * These functions track which doorbell cachelines are in use.
+ * The data they manipulate is protected by the host2guc lock.
+ */
+
+static uint32_t select_doorbell_cacheline(struct intel_guc *guc)
+{
+ const uint32_t cacheline_size = cache_line_size();
+ uint32_t offset;
+
+ spin_lock(&guc->host2guc_lock);
+
+ /* Doorbell uses a single cache line within a page */
+ offset = offset_in_page(guc->db_cacheline);
+
+ /* Moving to next cache line to reduce contention */
+ guc->db_cacheline += cacheline_size;
+
+ spin_unlock(&guc->host2guc_lock);
+
+ DRM_DEBUG_DRIVER("selected doorbell cacheline 0x%x, next 0x%x, linesize %u\n",
+ offset, guc->db_cacheline, cacheline_size);
+
+ return offset;
+}
+
+static uint16_t assign_doorbell(struct intel_guc *guc, uint32_t priority)
+{
+ /*
+ * The bitmap is split into two halves; the first half is used for
+ * normal priority contexts, the second half for high-priority ones.
+ * Note that logically higher priorities are numerically less than
+ * normal ones, so the test below means "is it high-priority?"
+ */
+ const bool hi_pri = (priority <= GUC_CTX_PRIORITY_HIGH);
+ const uint16_t half = GUC_MAX_DOORBELLS / 2;
+ const uint16_t start = hi_pri ? half : 0;
+ const uint16_t end = start + half;
+ uint16_t id;
+
+ spin_lock(&guc->host2guc_lock);
+ id = find_next_zero_bit(guc->doorbell_bitmap, end, start);
+ if (id == end)
+ id = GUC_INVALID_DOORBELL_ID;
+ else
+ bitmap_set(guc->doorbell_bitmap, id, 1);
+ spin_unlock(&guc->host2guc_lock);
+
+ DRM_DEBUG_DRIVER("assigned %s priority doorbell id 0x%x\n",
+ hi_pri ? "high" : "normal", id);
+
+ return id;
+}
+
+static void release_doorbell(struct intel_guc *guc, uint16_t id)
+{
+ spin_lock(&guc->host2guc_lock);
+ bitmap_clear(guc->doorbell_bitmap, id, 1);
+ spin_unlock(&guc->host2guc_lock);
+}
+
+/*
+ * Initialise the process descriptor shared with the GuC firmware.
+ */
+static void guc_init_proc_desc(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ struct guc_process_desc *desc;
+ void *base;
+
+ base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
+ desc = base + client->proc_desc_offset;
+
+ memset(desc, 0, sizeof(*desc));
+
+ /*
+ * XXX: pDoorbell and WQVBaseAddress are pointers in process address
+ * space for ring3 clients (set them as in mmap_ioctl) or kernel
+ * space for kernel clients (map on demand instead? May make debug
+ * easier to have it mapped).
+ */
+ desc->wq_base_addr = 0;
+ desc->db_base_addr = 0;
+
+ desc->context_id = client->ctx_index;
+ desc->wq_size_bytes = client->wq_size;
+ desc->wq_status = WQ_STATUS_ACTIVE;
+ desc->priority = client->priority;
+
+ kunmap_atomic(base);
+}
+
+/*
+ * Initialise/clear the context descriptor shared with the GuC firmware.
+ *
+ * This descriptor tells the GuC where (in GGTT space) to find the important
+ * data structures relating to this client (doorbell, process descriptor,
+ * write queue, etc).
+ */
+
+static void guc_init_ctx_desc(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ struct intel_context *ctx = client->owner;
+ struct guc_context_desc desc;
+ struct sg_table *sg;
+ int i;
+
+ memset(&desc, 0, sizeof(desc));
+
+ desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL;
+ desc.context_id = client->ctx_index;
+ desc.priority = client->priority;
+ desc.db_id = client->doorbell_id;
+
+ for (i = 0; i < I915_NUM_RINGS; i++) {
+ struct guc_execlist_context *lrc = &desc.lrc[i];
+ struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
+ struct intel_engine_cs *ring;
+ struct drm_i915_gem_object *obj;
+ uint64_t ctx_desc;
+
+ /* TODO: We have a design issue to be solved here. Only when we
+ * receive the first batch, we know which engine is used by the
+ * user. But here GuC expects the lrc and ring to be pinned. It
+ * is not an issue for default context, which is the only one
+ * for now who owns a GuC client. But for future owner of GuC
+ * client, need to make sure lrc is pinned prior to enter here.
+ */
+ obj = ctx->engine[i].state;
+ if (!obj)
+ break; /* XXX: continue? */
+
+ ring = ringbuf->ring;
+ ctx_desc = intel_lr_context_descriptor(ctx, ring);
+ lrc->context_desc = (u32)ctx_desc;
+
+ /* The state page is after PPHWSP */
+ lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) +
+ LRC_STATE_PN * PAGE_SIZE;
+ lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
+ (ring->id << GUC_ELC_ENGINE_OFFSET);
+
+ obj = ringbuf->obj;
+
+ lrc->ring_begin = i915_gem_obj_ggtt_offset(obj);
+ lrc->ring_end = lrc->ring_begin + obj->base.size - 1;
+ lrc->ring_next_free_location = lrc->ring_begin;
+ lrc->ring_current_tail_pointer_value = 0;
+
+ desc.engines_used |= (1 << ring->id);
+ }
+
+ WARN_ON(desc.engines_used == 0);
+
+ /*
+ * The CPU address is only needed at certain points, so kmap_atomic on
+ * demand instead of storing it in the ctx descriptor.
+ * XXX: May make debug easier to have it mapped
+ */
+ desc.db_trigger_cpu = 0;
+ desc.db_trigger_uk = client->doorbell_offset +
+ i915_gem_obj_ggtt_offset(client->client_obj);
+ desc.db_trigger_phy = client->doorbell_offset +
+ sg_dma_address(client->client_obj->pages->sgl);
+
+ desc.process_desc = client->proc_desc_offset +
+ i915_gem_obj_ggtt_offset(client->client_obj);
+
+ desc.wq_addr = client->wq_offset +
+ i915_gem_obj_ggtt_offset(client->client_obj);
+
+ desc.wq_size = client->wq_size;
+
+ /*
+ * XXX: Take LRCs from an existing intel_context if this is not an
+ * IsKMDCreatedContext client
+ */
+ desc.desc_private = (uintptr_t)client;
+
+ /* Pool context is pinned already */
+ sg = guc->ctx_pool_obj->pages;
+ sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc),
+ sizeof(desc) * client->ctx_index);
+}
+
+static void guc_fini_ctx_desc(struct intel_guc *guc,
+ struct i915_guc_client *client)
+{
+ struct guc_context_desc desc;
+ struct sg_table *sg;
+
+ memset(&desc, 0, sizeof(desc));
+
+ sg = guc->ctx_pool_obj->pages;
+ sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc),
+ sizeof(desc) * client->ctx_index);
+}
+
+/* Get valid workqueue item and return it back to offset */
+static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset)
+{
+ struct guc_process_desc *desc;
+ void *base;
+ u32 size = sizeof(struct guc_wq_item);
+ int ret = 0, timeout_counter = 200;
+
+ base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
+ desc = base + gc->proc_desc_offset;
+
+ while (timeout_counter-- > 0) {
+ ret = wait_for_atomic(CIRC_SPACE(gc->wq_tail, desc->head,
+ gc->wq_size) >= size, 1);
+
+ if (!ret) {
+ *offset = gc->wq_tail;
+
+ /* advance the tail for next workqueue item */
+ gc->wq_tail += size;
+ gc->wq_tail &= gc->wq_size - 1;
+
+ /* this will break the loop */
+ timeout_counter = 0;
+ }
+ };
+
+ kunmap_atomic(base);
+
+ return ret;
+}
+
+static int guc_add_workqueue_item(struct i915_guc_client *gc,
+ struct drm_i915_gem_request *rq)
+{
+ enum intel_ring_id ring_id = rq->ring->id;
+ struct guc_wq_item *wqi;
+ void *base;
+ u32 tail, wq_len, wq_off = 0;
+ int ret;
+
+ ret = guc_get_workqueue_space(gc, &wq_off);
+ if (ret)
+ return ret;
+
+ /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
+ * should not have the case where structure wqi is across page, neither
+ * wrapped to the beginning. This simplifies the implementation below.
+ *
+ * XXX: if not the case, we need save data to a temp wqi and copy it to
+ * workqueue buffer dw by dw.
+ */
+ WARN_ON(sizeof(struct guc_wq_item) != 16);
+ WARN_ON(wq_off & 3);
+
+ /* wq starts from the page after doorbell / process_desc */
+ base = kmap_atomic(i915_gem_object_get_page(gc->client_obj,
+ (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT));
+ wq_off &= PAGE_SIZE - 1;
+ wqi = (struct guc_wq_item *)((char *)base + wq_off);
+
+ /* len does not include the header */
+ wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1;
+ wqi->header = WQ_TYPE_INORDER |
+ (wq_len << WQ_LEN_SHIFT) |
+ (ring_id << WQ_TARGET_SHIFT) |
+ WQ_NO_WCFLUSH_WAIT;
+
+ /* The GuC wants only the low-order word of the context descriptor */
+ wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring);
+
+ /* The GuC firmware wants the tail index in QWords, not bytes */
+ tail = rq->ringbuf->tail >> 3;
+ wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
+ wqi->fence_id = 0; /*XXX: what fence to be here */
+
+ kunmap_atomic(base);
+
+ return 0;
+}
+
+#define CTX_RING_BUFFER_START 0x08
+
+/* Update the ringbuffer pointer in a saved context image */
+static void lr_context_update(struct drm_i915_gem_request *rq)
+{
+ enum intel_ring_id ring_id = rq->ring->id;
+ struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring_id].state;
+ struct drm_i915_gem_object *rb_obj = rq->ringbuf->obj;
+ struct page *page;
+ uint32_t *reg_state;
+
+ BUG_ON(!ctx_obj);
+ WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
+ WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+ reg_state = kmap_atomic(page);
+
+ reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj);
+
+ kunmap_atomic(reg_state);
+}
+
+/**
+ * i915_guc_submit() - Submit commands through GuC
+ * @client: the guc client where commands will go through
+ * @ctx: LRC where commands come from
+ * @ring: HW engine that will excute the commands
+ *
+ * Return: 0 if succeed
+ */
+int i915_guc_submit(struct i915_guc_client *client,
+ struct drm_i915_gem_request *rq)
+{
+ struct intel_guc *guc = client->guc;
+ enum intel_ring_id ring_id = rq->ring->id;
+ unsigned long flags;
+ int q_ret, b_ret;
+
+ /* Need this because of the deferred pin ctx and ring */
+ /* Shall we move this right after ring is pinned? */
+ lr_context_update(rq);
+
+ spin_lock_irqsave(&client->wq_lock, flags);
+
+ q_ret = guc_add_workqueue_item(client, rq);
+ if (q_ret == 0)
+ b_ret = guc_ring_doorbell(client);
+
+ client->submissions[ring_id] += 1;
+ if (q_ret) {
+ client->q_fail += 1;
+ client->retcode = q_ret;
+ } else if (b_ret) {
+ client->b_fail += 1;
+ client->retcode = q_ret = b_ret;
+ } else {
+ client->retcode = 0;
+ }
+ spin_unlock_irqrestore(&client->wq_lock, flags);
+
+ spin_lock(&guc->host2guc_lock);
+ guc->submissions[ring_id] += 1;
+ guc->last_seqno[ring_id] = rq->seqno;
+ spin_unlock(&guc->host2guc_lock);
+
+ return q_ret;
+}
+
+/*
+ * Everything below here is concerned with setup & teardown, and is
+ * therefore not part of the somewhat time-critical batch-submission
+ * path of i915_guc_submit() above.
+ */
+
+/**
+ * gem_allocate_guc_obj() - Allocate gem object for GuC usage
+ * @dev: drm device
+ * @size: size of object
+ *
+ * This is a wrapper to create a gem obj. In order to use it inside GuC, the
+ * object needs to be pinned lifetime. Also we must pin it to gtt space other
+ * than [0, GUC_WOPCM_TOP) because this range is reserved inside GuC.
+ *
+ * Return: A drm_i915_gem_object if successful, otherwise NULL.
+ */
+static struct drm_i915_gem_object *gem_allocate_guc_obj(struct drm_device *dev,
+ u32 size)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj;
+
+ obj = i915_gem_alloc_object(dev, size);
+ if (!obj)
+ return NULL;
+
+ if (i915_gem_object_get_pages(obj)) {
+ drm_gem_object_unreference(&obj->base);
+ return NULL;
+ }
+
+ if (i915_gem_obj_ggtt_pin(obj, PAGE_SIZE,
+ PIN_OFFSET_BIAS | GUC_WOPCM_TOP)) {
+ drm_gem_object_unreference(&obj->base);
+ return NULL;
+ }
+
+ /* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
+ I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
+
+ return obj;
+}
+
+/**
+ * gem_release_guc_obj() - Release gem object allocated for GuC usage
+ * @obj: gem obj to be released
+ */
+static void gem_release_guc_obj(struct drm_i915_gem_object *obj)
+{
+ if (!obj)
+ return;
+
+ if (i915_gem_obj_is_pinned(obj))
+ i915_gem_object_ggtt_unpin(obj);
+
+ drm_gem_object_unreference(&obj->base);
+}
+
+static void guc_client_free(struct drm_device *dev,
+ struct i915_guc_client *client)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+
+ if (!client)
+ return;
+
+ if (client->doorbell_id != GUC_INVALID_DOORBELL_ID) {
+ /*
+ * First disable the doorbell, then tell the GuC we've
+ * finished with it, finally deallocate it in our bitmap
+ */
+ guc_disable_doorbell(guc, client);
+ host2guc_release_doorbell(guc, client);
+ release_doorbell(guc, client->doorbell_id);
+ }
+
+ /*
+ * XXX: wait for any outstanding submissions before freeing memory.
+ * Be sure to drop any locks
+ */
+
+ gem_release_guc_obj(client->client_obj);
+
+ if (client->ctx_index != GUC_INVALID_CTX_ID) {
+ guc_fini_ctx_desc(guc, client);
+ ida_simple_remove(&guc->ctx_ids, client->ctx_index);
+ }
+
+ kfree(client);
+}
+
+/**
+ * guc_client_alloc() - Allocate an i915_guc_client
+ * @dev: drm device
+ * @priority: four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW
+ * The kernel client to replace ExecList submission is created with
+ * NORMAL priority. Priority of a client for scheduler can be HIGH,
+ * while a preemption context can use CRITICAL.
+ * @ctx the context to own the client (we use the default render context)
+ *
+ * Return: An i915_guc_client object if success.
+ */
+static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
+ uint32_t priority,
+ struct intel_context *ctx)
+{
+ struct i915_guc_client *client;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+ struct drm_i915_gem_object *obj;
+
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return NULL;
+
+ client->doorbell_id = GUC_INVALID_DOORBELL_ID;
+ client->priority = priority;
+ client->owner = ctx;
+ client->guc = guc;
+
+ client->ctx_index = (uint32_t)ida_simple_get(&guc->ctx_ids, 0,
+ GUC_MAX_GPU_CONTEXTS, GFP_KERNEL);
+ if (client->ctx_index >= GUC_MAX_GPU_CONTEXTS) {
+ client->ctx_index = GUC_INVALID_CTX_ID;
+ goto err;
+ }
+
+ /* The first page is doorbell/proc_desc. Two followed pages are wq. */
+ obj = gem_allocate_guc_obj(dev, GUC_DB_SIZE + GUC_WQ_SIZE);
+ if (!obj)
+ goto err;
+
+ client->client_obj = obj;
+ client->wq_offset = GUC_DB_SIZE;
+ client->wq_size = GUC_WQ_SIZE;
+ spin_lock_init(&client->wq_lock);
+
+ client->doorbell_offset = select_doorbell_cacheline(guc);
+
+ /*
+ * Since the doorbell only requires a single cacheline, we can save
+ * space by putting the application process descriptor in the same
+ * page. Use the half of the page that doesn't include the doorbell.
+ */
+ if (client->doorbell_offset >= (GUC_DB_SIZE / 2))
+ client->proc_desc_offset = 0;
+ else
+ client->proc_desc_offset = (GUC_DB_SIZE / 2);
+
+ client->doorbell_id = assign_doorbell(guc, client->priority);
+ if (client->doorbell_id == GUC_INVALID_DOORBELL_ID)
+ /* XXX: evict a doorbell instead */
+ goto err;
+
+ guc_init_proc_desc(guc, client);
+ guc_init_ctx_desc(guc, client);
+ guc_init_doorbell(guc, client);
+
+ /* XXX: Any cache flushes needed? General domain mgmt calls? */
+
+ if (host2guc_allocate_doorbell(guc, client))
+ goto err;
+
+ DRM_DEBUG_DRIVER("new priority %u client %p: ctx_index %u db_id %u\n",
+ priority, client, client->ctx_index, client->doorbell_id);
+
+ return client;
+
+err:
+ DRM_ERROR("FAILED to create priority %u GuC client!\n", priority);
+
+ guc_client_free(dev, client);
+ return NULL;
+}
+
+static void guc_create_log(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct drm_i915_gem_object *obj;
+ unsigned long offset;
+ uint32_t size, flags;
+
+ if (i915.guc_log_level < GUC_LOG_VERBOSITY_MIN)
+ return;
+
+ if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX)
+ i915.guc_log_level = GUC_LOG_VERBOSITY_MAX;
+
+ /* The first page is to save log buffer state. Allocate one
+ * extra page for others in case for overlap */
+ size = (1 + GUC_LOG_DPC_PAGES + 1 +
+ GUC_LOG_ISR_PAGES + 1 +
+ GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT;
+
+ obj = guc->log_obj;
+ if (!obj) {
+ obj = gem_allocate_guc_obj(dev_priv->dev, size);
+ if (!obj) {
+ /* logging will be off */
+ i915.guc_log_level = -1;
+ return;
+ }
+
+ guc->log_obj = obj;
+ }
+
+ /* each allocated unit is a page */
+ flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL |
+ (GUC_LOG_DPC_PAGES << GUC_LOG_DPC_SHIFT) |
+ (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) |
+ (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT);
+
+ offset = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; /* in pages */
+ guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
+}
+
+/*
+ * Set up the memory resources to be shared with the GuC. At this point,
+ * we require just one object that can be mapped through the GGTT.
+ */
+int i915_guc_submission_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ const size_t ctxsize = sizeof(struct guc_context_desc);
+ const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize;
+ const size_t gemsize = round_up(poolsize, PAGE_SIZE);
+ struct intel_guc *guc = &dev_priv->guc;
+
+ if (!i915.enable_guc_submission)
+ return 0; /* not enabled */
+
+ if (guc->ctx_pool_obj)
+ return 0; /* already allocated */
+
+ guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv->dev, gemsize);
+ if (!guc->ctx_pool_obj)
+ return -ENOMEM;
+
+ spin_lock_init(&dev_priv->guc.host2guc_lock);
+
+ ida_init(&guc->ctx_ids);
+
+ guc_create_log(guc);
+
+ return 0;
+}
+
+int i915_guc_submission_enable(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+ struct intel_context *ctx = dev_priv->ring[RCS].default_context;
+ struct i915_guc_client *client;
+
+ /* client for execbuf submission */
+ client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_NORMAL, ctx);
+ if (!client) {
+ DRM_ERROR("Failed to create execbuf guc_client\n");
+ return -ENOMEM;
+ }
+
+ guc->execbuf_client = client;
+
+ host2guc_sample_forcewake(guc, client);
+
+ return 0;
+}
+
+void i915_guc_submission_disable(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+
+ guc_client_free(dev, guc->execbuf_client);
+ guc->execbuf_client = NULL;
+}
+
+void i915_guc_submission_fini(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+
+ gem_release_guc_obj(dev_priv->guc.log_obj);
+ guc->log_obj = NULL;
+
+ if (guc->ctx_pool_obj)
+ ida_destroy(&guc->ctx_ids);
+ gem_release_guc_obj(guc->ctx_pool_obj);
+ guc->ctx_pool_obj = NULL;
+}
+
+/**
+ * intel_guc_suspend() - notify GuC entering suspend state
+ * @dev: drm device
+ */
+int intel_guc_suspend(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+ struct intel_context *ctx;
+ u32 data[3];
+
+ if (!i915.enable_guc_submission)
+ return 0;
+
+ ctx = dev_priv->ring[RCS].default_context;
+
+ data[0] = HOST2GUC_ACTION_ENTER_S_STATE;
+ /* any value greater than GUC_POWER_D0 */
+ data[1] = GUC_POWER_D1;
+ /* first page is shared data with GuC */
+ data[2] = i915_gem_obj_ggtt_offset(ctx->engine[RCS].state);
+
+ return host2guc_action(guc, data, ARRAY_SIZE(data));
+}
+
+
+/**
+ * intel_guc_resume() - notify GuC resuming from suspend state
+ * @dev: drm device
+ */
+int intel_guc_resume(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+ struct intel_context *ctx;
+ u32 data[3];
+
+ if (!i915.enable_guc_submission)
+ return 0;
+
+ ctx = dev_priv->ring[RCS].default_context;
+
+ data[0] = HOST2GUC_ACTION_EXIT_S_STATE;
+ data[1] = GUC_POWER_D0;
+ /* first page is shared data with GuC */
+ data[2] = i915_gem_obj_ggtt_offset(ctx->engine[RCS].state);
+
+ return host2guc_action(guc, data, ARRAY_SIZE(data));
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 39d73dbc1c47..0d228f909dcb 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -45,6 +45,18 @@
* and related files, but that will be described in separate chapters.
*/
+static const u32 hpd_ilk[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = DE_DP_A_HOTPLUG,
+};
+
+static const u32 hpd_ivb[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
+};
+
+static const u32 hpd_bdw[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG,
+};
+
static const u32 hpd_ibx[HPD_NUM_PINS] = {
[HPD_CRT] = SDE_CRT_HOTPLUG,
[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
@@ -62,6 +74,7 @@ static const u32 hpd_cpt[HPD_NUM_PINS] = {
};
static const u32 hpd_spt[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
@@ -97,6 +110,7 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = {
/* BXT hpd list */
static const u32 hpd_bxt[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA,
[HPD_PORT_B] = BXT_DE_PORT_HP_DDIB,
[HPD_PORT_C] = BXT_DE_PORT_HP_DDIC
};
@@ -125,27 +139,30 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = {
/*
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
*/
-#define GEN5_ASSERT_IIR_IS_ZERO(reg) do { \
- u32 val = I915_READ(reg); \
- if (val) { \
- WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", \
- (reg), val); \
- I915_WRITE((reg), 0xffffffff); \
- POSTING_READ(reg); \
- I915_WRITE((reg), 0xffffffff); \
- POSTING_READ(reg); \
- } \
-} while (0)
+static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
+{
+ u32 val = I915_READ(reg);
+
+ if (val == 0)
+ return;
+
+ WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n",
+ reg, val);
+ I915_WRITE(reg, 0xffffffff);
+ POSTING_READ(reg);
+ I915_WRITE(reg, 0xffffffff);
+ POSTING_READ(reg);
+}
#define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
- GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
+ gen5_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \
I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
POSTING_READ(GEN8_##type##_IMR(which)); \
} while (0)
#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \
- GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \
+ gen5_assert_iir_is_zero(dev_priv, type##IIR); \
I915_WRITE(type##IER, (ier_val)); \
I915_WRITE(type##IMR, (imr_val)); \
POSTING_READ(type##IMR); \
@@ -154,36 +171,85 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = {
static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
/* For display hotplug interrupt */
-void
-ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+static inline void
+i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
+ uint32_t mask,
+ uint32_t bits)
{
+ uint32_t val;
+
assert_spin_locked(&dev_priv->irq_lock);
+ WARN_ON(bits & ~mask);
- if (WARN_ON(!intel_irqs_enabled(dev_priv)))
- return;
+ val = I915_READ(PORT_HOTPLUG_EN);
+ val &= ~mask;
+ val |= bits;
+ I915_WRITE(PORT_HOTPLUG_EN, val);
+}
- if ((dev_priv->irq_mask & mask) != 0) {
- dev_priv->irq_mask &= ~mask;
- I915_WRITE(DEIMR, dev_priv->irq_mask);
- POSTING_READ(DEIMR);
- }
+/**
+ * i915_hotplug_interrupt_update - update hotplug interrupt enable
+ * @dev_priv: driver private
+ * @mask: bits to update
+ * @bits: bits to enable
+ * NOTE: the HPD enable bits are modified both inside and outside
+ * of an interrupt context. To avoid that read-modify-write cycles
+ * interfer, these bits are protected by a spinlock. Since this
+ * function is usually not called from a context where the lock is
+ * held already, this function acquires the lock itself. A non-locking
+ * version is also available.
+ */
+void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
+ uint32_t mask,
+ uint32_t bits)
+{
+ spin_lock_irq(&dev_priv->irq_lock);
+ i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
+ spin_unlock_irq(&dev_priv->irq_lock);
}
-void
-ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+/**
+ * ilk_update_display_irq - update DEIMR
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+static void ilk_update_display_irq(struct drm_i915_private *dev_priv,
+ uint32_t interrupt_mask,
+ uint32_t enabled_irq_mask)
{
+ uint32_t new_val;
+
assert_spin_locked(&dev_priv->irq_lock);
+ WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
- if ((dev_priv->irq_mask & mask) != mask) {
- dev_priv->irq_mask |= mask;
+ new_val = dev_priv->irq_mask;
+ new_val &= ~interrupt_mask;
+ new_val |= (~enabled_irq_mask & interrupt_mask);
+
+ if (new_val != dev_priv->irq_mask) {
+ dev_priv->irq_mask = new_val;
I915_WRITE(DEIMR, dev_priv->irq_mask);
POSTING_READ(DEIMR);
}
}
+void
+ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+{
+ ilk_update_display_irq(dev_priv, mask, mask);
+}
+
+void
+ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+{
+ ilk_update_display_irq(dev_priv, mask, 0);
+}
+
/**
* ilk_update_gt_irq - update GTIMR
* @dev_priv: driver private
@@ -351,6 +417,38 @@ void gen6_disable_rps_interrupts(struct drm_device *dev)
}
/**
+ * bdw_update_port_irq - update DE port interrupt
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
+ uint32_t interrupt_mask,
+ uint32_t enabled_irq_mask)
+{
+ uint32_t new_val;
+ uint32_t old_val;
+
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
+ if (WARN_ON(!intel_irqs_enabled(dev_priv)))
+ return;
+
+ old_val = I915_READ(GEN8_DE_PORT_IMR);
+
+ new_val = old_val;
+ new_val &= ~interrupt_mask;
+ new_val |= (~enabled_irq_mask & interrupt_mask);
+
+ if (new_val != old_val) {
+ I915_WRITE(GEN8_DE_PORT_IMR, new_val);
+ POSTING_READ(GEN8_DE_PORT_IMR);
+ }
+}
+
+/**
* ibx_display_interrupt_update - update SDEIMR
* @dev_priv: driver private
* @interrupt_mask: mask of interrupt bits to update
@@ -486,6 +584,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
/**
* i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
+ * @dev: drm device
*/
static void i915_enable_asle_pipestat(struct drm_device *dev)
{
@@ -554,7 +653,7 @@ static void i915_enable_asle_pipestat(struct drm_device *dev)
* of horizontal active on the first line of vertical active
*/
-static u32 i8xx_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 i8xx_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
/* Gen2 doesn't have a hardware frame counter */
return 0;
@@ -563,7 +662,7 @@ static u32 i8xx_get_vblank_counter(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed a 'crtc', which
* we use as a pipe index
*/
-static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long high_frame;
@@ -611,12 +710,11 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
}
-static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = PIPE_FRMCOUNT_GM45(pipe);
- return I915_READ(reg);
+ return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
}
/* raw reads, only for fast reads of display block, no need for forcewake etc. */
@@ -651,7 +749,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
* problem. We may need to extend this to include other platforms,
* but so far testing only shows the problem on HSW.
*/
- if (IS_HASWELL(dev) && !position) {
+ if (HAS_DDI(dev) && !position) {
int i, temp;
for (i = 0; i < 100; i++) {
@@ -672,14 +770,14 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
return (position + crtc->scanline_offset) % vtotal;
}
-static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
+static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
unsigned int flags, int *vpos, int *hpos,
- ktime_t *stime, ktime_t *etime)
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- const struct drm_display_mode *mode = &intel_crtc->base.hwmode;
int position;
int vbl_start, vbl_end, hsync_start, htotal, vtotal;
bool in_vbl = true;
@@ -809,34 +907,33 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc)
return position;
}
-static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
+static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
int *max_error,
struct timeval *vblank_time,
unsigned flags)
{
struct drm_crtc *crtc;
- if (pipe < 0 || pipe >= INTEL_INFO(dev)->num_pipes) {
- DRM_ERROR("Invalid crtc %d\n", pipe);
+ if (pipe >= INTEL_INFO(dev)->num_pipes) {
+ DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
/* Get drm_crtc to timestamp: */
crtc = intel_get_crtc_for_pipe(dev, pipe);
if (crtc == NULL) {
- DRM_ERROR("Invalid crtc %d\n", pipe);
+ DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
if (!crtc->hwmode.crtc_clock) {
- DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
+ DRM_DEBUG_KMS("crtc %u is disabled\n", pipe);
return -EBUSY;
}
/* Helper routine in DRM core does all the work: */
return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
vblank_time, flags,
- crtc,
&crtc->hwmode);
}
@@ -903,12 +1000,16 @@ static bool vlv_c0_above(struct drm_i915_private *dev_priv,
int threshold)
{
u64 time, c0;
+ unsigned int mul = 100;
if (old->cz_clock == 0)
return false;
+ if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
+ mul <<= 8;
+
time = now->cz_clock - old->cz_clock;
- time *= threshold * dev_priv->mem_freq;
+ time *= threshold * dev_priv->czclk_freq;
/* Workload can be split between render + media, e.g. SwapBuffers
* being blitted in X after being rendered in mesa. To account for
@@ -916,7 +1017,7 @@ static bool vlv_c0_above(struct drm_i915_private *dev_priv,
*/
c0 = now->render_c0 - old->render_c0;
c0 += now->media_c0 - old->media_c0;
- c0 *= 100 * VLV_CZ_CLOCK_TO_MILLI_SEC * 4 / 1000;
+ c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
return c0 >= time;
}
@@ -1264,7 +1365,31 @@ static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
{
switch (port) {
case PORT_A:
- return val & BXT_PORTA_HOTPLUG_LONG_DETECT;
+ return val & PORTA_HOTPLUG_LONG_DETECT;
+ case PORT_B:
+ return val & PORTB_HOTPLUG_LONG_DETECT;
+ case PORT_C:
+ return val & PORTC_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool spt_port_hotplug2_long_detect(enum port port, u32 val)
+{
+ switch (port) {
+ case PORT_E:
+ return val & PORTE_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool spt_port_hotplug_long_detect(enum port port, u32 val)
+{
+ switch (port) {
+ case PORT_A:
+ return val & PORTA_HOTPLUG_LONG_DETECT;
case PORT_B:
return val & PORTB_HOTPLUG_LONG_DETECT;
case PORT_C:
@@ -1276,6 +1401,16 @@ static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
}
}
+static bool ilk_port_hotplug_long_detect(enum port port, u32 val)
+{
+ switch (port) {
+ case PORT_A:
+ return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
static bool pch_port_hotplug_long_detect(enum port port, u32 val)
{
switch (port) {
@@ -1285,8 +1420,6 @@ static bool pch_port_hotplug_long_detect(enum port port, u32 val)
return val & PORTC_HOTPLUG_LONG_DETECT;
case PORT_D:
return val & PORTD_HOTPLUG_LONG_DETECT;
- case PORT_E:
- return val & PORTE_HOTPLUG_LONG_DETECT;
default:
return false;
}
@@ -1306,7 +1439,13 @@ static bool i9xx_port_hotplug_long_detect(enum port port, u32 val)
}
}
-/* Get a bit mask of pins that have triggered, and which ones may be long. */
+/*
+ * Get a bit mask of pins that have triggered, and which ones may be long.
+ * This can be called multiple times with the same masks to accumulate
+ * hotplug detection results from several registers.
+ *
+ * Note that the caller is expected to zero out the masks initially.
+ */
static void intel_get_hpd_pins(u32 *pin_mask, u32 *long_mask,
u32 hotplug_trigger, u32 dig_hotplug_reg,
const u32 hpd[HPD_NUM_PINS],
@@ -1315,9 +1454,6 @@ static void intel_get_hpd_pins(u32 *pin_mask, u32 *long_mask,
enum port port;
int i;
- *pin_mask = 0;
- *long_mask = 0;
-
for_each_hpd_pin(i) {
if ((hpd[i] & hotplug_trigger) == 0)
continue;
@@ -1558,7 +1694,7 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
- u32 pin_mask, long_mask;
+ u32 pin_mask = 0, long_mask = 0;
if (!hotplug_status)
return;
@@ -1573,20 +1709,25 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
- intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
- hotplug_trigger, hpd_status_g4x,
- i9xx_port_hotplug_long_detect);
- intel_hpd_irq_handler(dev, pin_mask, long_mask);
+ if (hotplug_trigger) {
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+ hotplug_trigger, hpd_status_g4x,
+ i9xx_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev, pin_mask, long_mask);
+ }
if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
dp_aux_irq_handler(dev);
} else {
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
- intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
- hotplug_trigger, hpd_status_i915,
- i9xx_port_hotplug_long_detect);
- intel_hpd_irq_handler(dev, pin_mask, long_mask);
+ if (hotplug_trigger) {
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+ hotplug_trigger, hpd_status_i915,
+ i9xx_port_hotplug_long_detect);
+ intel_hpd_irq_handler(dev, pin_mask, long_mask);
+ }
}
}
@@ -1680,23 +1821,30 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
return ret;
}
+static void ibx_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger,
+ const u32 hpd[HPD_NUM_PINS])
+{
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+ I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+ dig_hotplug_reg, hpd,
+ pch_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev, pin_mask, long_mask);
+}
+
static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
- if (hotplug_trigger) {
- u32 dig_hotplug_reg, pin_mask, long_mask;
-
- dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
- I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
-
- intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
- dig_hotplug_reg, hpd_ibx,
- pch_port_hotplug_long_detect);
- intel_hpd_irq_handler(dev, pin_mask, long_mask);
- }
+ if (hotplug_trigger)
+ ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
if (pch_iir & SDE_AUDIO_POWER_MASK) {
int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -1787,38 +1935,10 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe;
- u32 hotplug_trigger;
+ u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
- if (HAS_PCH_SPT(dev))
- hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT;
- else
- hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
-
- if (hotplug_trigger) {
- u32 dig_hotplug_reg, pin_mask, long_mask;
-
- dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
- I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
-
- if (HAS_PCH_SPT(dev)) {
- intel_get_hpd_pins(&pin_mask, &long_mask,
- hotplug_trigger,
- dig_hotplug_reg, hpd_spt,
- pch_port_hotplug_long_detect);
-
- /* detect PORTE HP event */
- dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2);
- if (pch_port_hotplug_long_detect(PORT_E,
- dig_hotplug_reg))
- long_mask |= 1 << HPD_PORT_E;
- } else
- intel_get_hpd_pins(&pin_mask, &long_mask,
- hotplug_trigger,
- dig_hotplug_reg, hpd_cpt,
- pch_port_hotplug_long_detect);
-
- intel_hpd_irq_handler(dev, pin_mask, long_mask);
- }
+ if (hotplug_trigger)
+ ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
@@ -1849,10 +1969,67 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
cpt_serr_int_handler(dev);
}
+static void spt_irq_handler(struct drm_device *dev, u32 pch_iir)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
+ ~SDE_PORTE_HOTPLUG_SPT;
+ u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
+ u32 pin_mask = 0, long_mask = 0;
+
+ if (hotplug_trigger) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+ I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+ dig_hotplug_reg, hpd_spt,
+ spt_port_hotplug_long_detect);
+ }
+
+ if (hotplug2_trigger) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2);
+ I915_WRITE(PCH_PORT_HOTPLUG2, dig_hotplug_reg);
+
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug2_trigger,
+ dig_hotplug_reg, hpd_spt,
+ spt_port_hotplug2_long_detect);
+ }
+
+ if (pin_mask)
+ intel_hpd_irq_handler(dev, pin_mask, long_mask);
+
+ if (pch_iir & SDE_GMBUS_CPT)
+ gmbus_irq_handler(dev);
+}
+
+static void ilk_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger,
+ const u32 hpd[HPD_NUM_PINS])
+{
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+ dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
+ I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg);
+
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+ dig_hotplug_reg, hpd,
+ ilk_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev, pin_mask, long_mask);
+}
+
static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
{
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe;
+ u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
+
+ if (hotplug_trigger)
+ ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_ilk);
if (de_iir & DE_AUX_CHANNEL_A)
dp_aux_irq_handler(dev);
@@ -1902,6 +2079,10 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
{
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe;
+ u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
+
+ if (hotplug_trigger)
+ ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_ivb);
if (de_iir & DE_ERR_INT_IVB)
ivb_err_int_handler(dev);
@@ -2014,27 +2195,19 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
return ret;
}
-static void bxt_hpd_handler(struct drm_device *dev, uint32_t iir_status)
+static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger,
+ const u32 hpd[HPD_NUM_PINS])
{
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 hp_control, hp_trigger;
- u32 pin_mask, long_mask;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
- /* Get the status */
- hp_trigger = iir_status & BXT_DE_PORT_HOTPLUG_MASK;
- hp_control = I915_READ(BXT_HOTPLUG_CTL);
+ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+ I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
- /* Hotplug not enabled ? */
- if (!(hp_control & BXT_HOTPLUG_CTL_MASK)) {
- DRM_ERROR("Interrupt when HPD disabled\n");
- return;
- }
+ intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+ dig_hotplug_reg, hpd,
+ bxt_port_hotplug_long_detect);
- /* Clear sticky bits in hpd status */
- I915_WRITE(BXT_HOTPLUG_CTL, hp_control);
-
- intel_get_hpd_pins(&pin_mask, &long_mask, hp_trigger, hp_control,
- hpd_bxt, bxt_port_hotplug_long_detect);
intel_hpd_irq_handler(dev, pin_mask, long_mask);
}
@@ -2051,7 +2224,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
if (!intel_irqs_enabled(dev_priv))
return IRQ_NONE;
- if (IS_GEN9(dev))
+ if (INTEL_INFO(dev_priv)->gen >= 9)
aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
GEN9_AUX_CHANNEL_D;
@@ -2084,6 +2257,12 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
tmp = I915_READ(GEN8_DE_PORT_IIR);
if (tmp) {
bool found = false;
+ u32 hotplug_trigger = 0;
+
+ if (IS_BROXTON(dev_priv))
+ hotplug_trigger = tmp & BXT_DE_PORT_HOTPLUG_MASK;
+ else if (IS_BROADWELL(dev_priv))
+ hotplug_trigger = tmp & GEN8_PORT_DP_A_HOTPLUG;
I915_WRITE(GEN8_DE_PORT_IIR, tmp);
ret = IRQ_HANDLED;
@@ -2093,8 +2272,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
found = true;
}
- if (IS_BROXTON(dev) && tmp & BXT_DE_PORT_HOTPLUG_MASK) {
- bxt_hpd_handler(dev, tmp);
+ if (hotplug_trigger) {
+ if (IS_BROXTON(dev))
+ bxt_hpd_irq_handler(dev, hotplug_trigger, hpd_bxt);
+ else
+ ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_bdw);
found = true;
}
@@ -2125,7 +2307,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
intel_pipe_handle_vblank(dev, pipe))
intel_check_page_flip(dev, pipe);
- if (IS_GEN9(dev))
+ if (INTEL_INFO(dev_priv)->gen >= 9)
flip_done = pipe_iir & GEN9_PIPE_PLANE1_FLIP_DONE;
else
flip_done = pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE;
@@ -2143,7 +2325,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
pipe);
- if (IS_GEN9(dev))
+ if (INTEL_INFO(dev_priv)->gen >= 9)
fault_errors = pipe_iir & GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
else
fault_errors = pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
@@ -2167,7 +2349,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
if (pch_iir) {
I915_WRITE(SDEIIR, pch_iir);
ret = IRQ_HANDLED;
- cpt_irq_handler(dev, pch_iir);
+
+ if (HAS_PCH_SPT(dev_priv))
+ spt_irq_handler(dev, pch_iir);
+ else
+ cpt_irq_handler(dev, pch_iir);
} else
DRM_ERROR("The master control interrupt lied (SDE)!\n");
@@ -2209,6 +2395,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv,
/**
* i915_reset_and_wakeup - do process context error handling work
+ * @dev: drm device
*
* Fire an error uevent so userspace can see that a hang or error
* was detected.
@@ -2386,7 +2573,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
* i915_handle_error - handle a gpu error
* @dev: drm device
*
- * Do some basic checking of regsiter state at error time and
+ * Do some basic checking of register state at error time and
* dump it to the syslog. Also call i915_capture_error_state() to make
* sure we get a record and make it available in debugfs. Fire a uevent
* so userspace knows something bad happened (should trigger collection
@@ -2432,7 +2619,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
-static int i915_enable_vblank(struct drm_device *dev, int pipe)
+static int i915_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2449,7 +2636,7 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe)
return 0;
}
-static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
+static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2463,7 +2650,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
return 0;
}
-static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
+static int valleyview_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2476,7 +2663,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
return 0;
}
-static int gen8_enable_vblank(struct drm_device *dev, int pipe)
+static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2492,7 +2679,7 @@ static int gen8_enable_vblank(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
-static void i915_disable_vblank(struct drm_device *dev, int pipe)
+static void i915_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2504,7 +2691,7 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
+static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2516,7 +2703,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
+static void valleyview_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2527,7 +2714,7 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-static void gen8_disable_vblank(struct drm_device *dev, int pipe)
+static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -2599,6 +2786,26 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
u64 offset = 0;
int i, backwards;
+ /*
+ * This function does not support execlist mode - any attempt to
+ * proceed further into this function will result in a kernel panic
+ * when dereferencing ring->buffer, which is not set up in execlist
+ * mode.
+ *
+ * The correct way of doing it would be to derive the currently
+ * executing ring buffer from the current context, which is derived
+ * from the currently running request. Unfortunately, to get the
+ * current request we would have to grab the struct_mutex before doing
+ * anything else, which would be ill-advised since some other thread
+ * might have grabbed it already and managed to hang itself, causing
+ * the hang checker to deadlock.
+ *
+ * Therefore, this function does not support execlist mode in its
+ * current form. Just return NULL and move on.
+ */
+ if (ring->buffer == NULL)
+ return NULL;
+
ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
return NULL;
@@ -2933,7 +3140,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
{
enum pipe pipe;
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xFFFFFFFF, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
for_each_pipe(dev_priv, pipe)
@@ -3027,86 +3234,124 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
vlv_display_irq_reset(dev_priv);
}
+static u32 intel_hpd_enabled_irqs(struct drm_device *dev,
+ const u32 hpd[HPD_NUM_PINS])
+{
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_encoder *encoder;
+ u32 enabled_irqs = 0;
+
+ for_each_intel_encoder(dev, encoder)
+ if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
+ enabled_irqs |= hpd[encoder->hpd_pin];
+
+ return enabled_irqs;
+}
+
static void ibx_hpd_irq_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_encoder *intel_encoder;
- u32 hotplug_irqs, hotplug, enabled_irqs = 0;
+ u32 hotplug_irqs, hotplug, enabled_irqs;
if (HAS_PCH_IBX(dev)) {
hotplug_irqs = SDE_HOTPLUG_MASK;
- for_each_intel_encoder(dev, intel_encoder)
- if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED)
- enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
- } else if (HAS_PCH_SPT(dev)) {
- hotplug_irqs = SDE_HOTPLUG_MASK_SPT;
- for_each_intel_encoder(dev, intel_encoder)
- if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED)
- enabled_irqs |= hpd_spt[intel_encoder->hpd_pin];
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ibx);
} else {
hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
- for_each_intel_encoder(dev, intel_encoder)
- if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED)
- enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin];
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_cpt);
}
ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
/*
* Enable digital hotplug on the PCH, and configure the DP short pulse
- * duration to 2ms (which is the minimum in the Display Port spec)
- *
- * This register is the same on all known PCH chips.
+ * duration to 2ms (which is the minimum in the Display Port spec).
+ * The pulse duration bits are reserved on LPT+.
*/
hotplug = I915_READ(PCH_PORT_HOTPLUG);
hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
+ /*
+ * When CPU and PCH are on the same package, port A
+ * HPD must be enabled in both north and south.
+ */
+ if (HAS_PCH_LPT_LP(dev))
+ hotplug |= PORTA_HOTPLUG_ENABLE;
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+}
- /* enable SPT PORTE hot plug */
- if (HAS_PCH_SPT(dev)) {
- hotplug = I915_READ(PCH_PORT_HOTPLUG2);
- hotplug |= PORTE_HOTPLUG_ENABLE;
- I915_WRITE(PCH_PORT_HOTPLUG2, hotplug);
- }
+static void spt_hpd_irq_setup(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 hotplug_irqs, hotplug, enabled_irqs;
+
+ hotplug_irqs = SDE_HOTPLUG_MASK_SPT;
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_spt);
+
+ ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+ /* Enable digital hotplug on the PCH */
+ hotplug = I915_READ(PCH_PORT_HOTPLUG);
+ hotplug |= PORTD_HOTPLUG_ENABLE | PORTC_HOTPLUG_ENABLE |
+ PORTB_HOTPLUG_ENABLE | PORTA_HOTPLUG_ENABLE;
+ I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+
+ hotplug = I915_READ(PCH_PORT_HOTPLUG2);
+ hotplug |= PORTE_HOTPLUG_ENABLE;
+ I915_WRITE(PCH_PORT_HOTPLUG2, hotplug);
}
-static void bxt_hpd_irq_setup(struct drm_device *dev)
+static void ilk_hpd_irq_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_encoder *intel_encoder;
- u32 hotplug_port = 0;
- u32 hotplug_ctrl;
-
- /* Now, enable HPD */
- for_each_intel_encoder(dev, intel_encoder) {
- if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state
- == HPD_ENABLED)
- hotplug_port |= hpd_bxt[intel_encoder->hpd_pin];
+ u32 hotplug_irqs, hotplug, enabled_irqs;
+
+ if (INTEL_INFO(dev)->gen >= 8) {
+ hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG;
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_bdw);
+
+ bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+ } else if (INTEL_INFO(dev)->gen >= 7) {
+ hotplug_irqs = DE_DP_A_HOTPLUG_IVB;
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ivb);
+
+ ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
+ } else {
+ hotplug_irqs = DE_DP_A_HOTPLUG;
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ilk);
+
+ ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
}
- /* Mask all HPD control bits */
- hotplug_ctrl = I915_READ(BXT_HOTPLUG_CTL) & ~BXT_HOTPLUG_CTL_MASK;
+ /*
+ * Enable digital hotplug on the CPU, and configure the DP short pulse
+ * duration to 2ms (which is the minimum in the Display Port spec)
+ * The pulse duration bits are reserved on HSW+.
+ */
+ hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
+ hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK;
+ hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_2ms;
+ I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug);
+
+ ibx_hpd_irq_setup(dev);
+}
+
+static void bxt_hpd_irq_setup(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 hotplug_irqs, hotplug, enabled_irqs;
- /* Enable requested port in hotplug control */
- /* TODO: implement (short) HPD support on port A */
- WARN_ON_ONCE(hotplug_port & BXT_DE_PORT_HP_DDIA);
- if (hotplug_port & BXT_DE_PORT_HP_DDIB)
- hotplug_ctrl |= BXT_DDIB_HPD_ENABLE;
- if (hotplug_port & BXT_DE_PORT_HP_DDIC)
- hotplug_ctrl |= BXT_DDIC_HPD_ENABLE;
- I915_WRITE(BXT_HOTPLUG_CTL, hotplug_ctrl);
+ enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_bxt);
+ hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK;
- /* Unmask DDI hotplug in IMR */
- hotplug_ctrl = I915_READ(GEN8_DE_PORT_IMR) & ~hotplug_port;
- I915_WRITE(GEN8_DE_PORT_IMR, hotplug_ctrl);
+ bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
- /* Enable DDI hotplug in IER */
- hotplug_ctrl = I915_READ(GEN8_DE_PORT_IER) | hotplug_port;
- I915_WRITE(GEN8_DE_PORT_IER, hotplug_ctrl);
- POSTING_READ(GEN8_DE_PORT_IER);
+ hotplug = I915_READ(PCH_PORT_HOTPLUG);
+ hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE |
+ PORTA_HOTPLUG_ENABLE;
+ I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
}
static void ibx_irq_postinstall(struct drm_device *dev)
@@ -3122,7 +3367,7 @@ static void ibx_irq_postinstall(struct drm_device *dev)
else
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
- GEN5_ASSERT_IIR_IS_ZERO(SDEIIR);
+ gen5_assert_iir_is_zero(dev_priv, SDEIIR);
I915_WRITE(SDEIMR, ~mask);
}
@@ -3174,15 +3419,17 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
DE_PLANEB_FLIP_DONE_IVB |
DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB);
extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
- DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB);
+ DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
+ DE_DP_A_HOTPLUG_IVB);
} else {
display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
DE_AUX_CHANNEL_A |
DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE |
DE_POISON);
- extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT |
- DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN;
+ extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT |
+ DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
+ DE_DP_A_HOTPLUG);
}
dev_priv->irq_mask = ~display_mask;
@@ -3309,7 +3556,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
{
dev_priv->irq_mask = ~0;
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
POSTING_READ(PORT_HOTPLUG_EN);
I915_WRITE(VLV_IIR, 0xffffffff);
@@ -3378,24 +3625,31 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
{
uint32_t de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE;
uint32_t de_pipe_enables;
- int pipe;
- u32 de_port_en = GEN8_AUX_CHANNEL_A;
+ u32 de_port_masked = GEN8_AUX_CHANNEL_A;
+ u32 de_port_enables;
+ enum pipe pipe;
- if (IS_GEN9(dev_priv)) {
+ if (INTEL_INFO(dev_priv)->gen >= 9) {
de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE |
GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
- de_port_en |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
- GEN9_AUX_CHANNEL_D;
-
+ de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
+ GEN9_AUX_CHANNEL_D;
if (IS_BROXTON(dev_priv))
- de_port_en |= BXT_DE_PORT_GMBUS;
- } else
+ de_port_masked |= BXT_DE_PORT_GMBUS;
+ } else {
de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE |
GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
+ }
de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
GEN8_PIPE_FIFO_UNDERRUN;
+ de_port_enables = de_port_masked;
+ if (IS_BROXTON(dev_priv))
+ de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
+ else if (IS_BROADWELL(dev_priv))
+ de_port_enables |= GEN8_PORT_DP_A_HOTPLUG;
+
dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked;
dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
@@ -3407,7 +3661,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
dev_priv->de_irq_mask[pipe],
de_pipe_enables);
- GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_en, de_port_en);
+ GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
}
static int gen8_irq_postinstall(struct drm_device *dev)
@@ -3676,7 +3930,7 @@ static void i915_irq_preinstall(struct drm_device * dev)
int pipe;
if (I915_HAS_HOTPLUG(dev)) {
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
@@ -3710,7 +3964,7 @@ static int i915_irq_postinstall(struct drm_device *dev)
I915_USER_INTERRUPT;
if (I915_HAS_HOTPLUG(dev)) {
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
POSTING_READ(PORT_HOTPLUG_EN);
/* Enable in IER... */
@@ -3872,7 +4126,7 @@ static void i915_irq_uninstall(struct drm_device * dev)
int pipe;
if (I915_HAS_HOTPLUG(dev)) {
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
@@ -3893,7 +4147,7 @@ static void i965_irq_preinstall(struct drm_device * dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe;
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
I915_WRITE(HWSTAM, 0xeffe);
@@ -3954,7 +4208,7 @@ static int i965_irq_postinstall(struct drm_device *dev)
I915_WRITE(IER, enable_mask);
POSTING_READ(IER);
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
POSTING_READ(PORT_HOTPLUG_EN);
i915_enable_asle_pipestat(dev);
@@ -3965,29 +4219,27 @@ static int i965_irq_postinstall(struct drm_device *dev)
static void i915_hpd_irq_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_encoder *intel_encoder;
u32 hotplug_en;
assert_spin_locked(&dev_priv->irq_lock);
- hotplug_en = I915_READ(PORT_HOTPLUG_EN);
- hotplug_en &= ~HOTPLUG_INT_EN_MASK;
/* Note HDMI and DP share hotplug bits */
/* enable bits are the same for all generations */
- for_each_intel_encoder(dev, intel_encoder)
- if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED)
- hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
+ hotplug_en = intel_hpd_enabled_irqs(dev, hpd_mask_i915);
/* Programming the CRT detection parameters tends
to generate a spurious hotplug event about three
seconds later. So just do it once.
*/
if (IS_G4X(dev))
hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
- hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
/* Ignore TV since it's buggy */
- I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+ i915_hotplug_interrupt_update_locked(dev_priv,
+ HOTPLUG_INT_EN_MASK |
+ CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
+ CRT_HOTPLUG_ACTIVATION_PERIOD_64,
+ hotplug_en);
}
static irqreturn_t i965_irq_handler(int irq, void *arg)
@@ -4100,7 +4352,7 @@ static void i965_irq_uninstall(struct drm_device * dev)
if (!dev_priv)
return;
- I915_WRITE(PORT_HOTPLUG_EN, 0);
+ i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
I915_WRITE(HWSTAM, 0xffffffff);
@@ -4148,7 +4400,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
- dev->driver->get_vblank_counter = gm45_get_vblank_counter;
+ dev->driver->get_vblank_counter = g4x_get_vblank_counter;
} else {
dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
@@ -4188,10 +4440,12 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->irq_uninstall = gen8_irq_uninstall;
dev->driver->enable_vblank = gen8_enable_vblank;
dev->driver->disable_vblank = gen8_disable_vblank;
- if (HAS_PCH_SPLIT(dev))
- dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
- else
+ if (IS_BROXTON(dev))
dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
+ else if (HAS_PCH_SPT(dev))
+ dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup;
+ else
+ dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
} else if (HAS_PCH_SPLIT(dev)) {
dev->driver->irq_handler = ironlake_irq_handler;
dev->driver->irq_preinstall = ironlake_irq_reset;
@@ -4199,7 +4453,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->irq_uninstall = ironlake_irq_uninstall;
dev->driver->enable_vblank = ironlake_enable_vblank;
dev->driver->disable_vblank = ironlake_disable_vblank;
- dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
+ dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
} else {
if (INTEL_INFO(dev_priv)->gen == 2) {
dev->driver->irq_preinstall = i8xx_irq_preinstall;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 5ae4b0aba564..4be13a5eb932 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -38,7 +38,7 @@ struct i915_params i915 __read_mostly = {
.enable_ppgtt = -1,
.enable_psr = 0,
.preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
- .disable_power_well = 1,
+ .disable_power_well = -1,
.enable_ips = 1,
.fastboot = 0,
.prefault_disable = 0,
@@ -51,6 +51,7 @@ struct i915_params i915 __read_mostly = {
.use_mmio_flip = 0,
.mmio_debug = 0,
.verbose_state_checks = 1,
+ .nuclear_pageflip = 0,
.edp_vswing = 0,
.enable_guc_submission = false,
.guc_log_level = -1,
@@ -61,7 +62,7 @@ MODULE_PARM_DESC(modeset,
"Use kernel modesetting [KMS] (0=disable, "
"1=on, -1=force vga console preference [default])");
-module_param_named(panel_ignore_lid, i915.panel_ignore_lid, int, 0600);
+module_param_named_unsafe(panel_ignore_lid, i915.panel_ignore_lid, int, 0600);
MODULE_PARM_DESC(panel_ignore_lid,
"Override lid status (0=autodetect, 1=autodetect disabled [default], "
"-1=force lid closed, -2=force lid open)");
@@ -84,17 +85,17 @@ MODULE_PARM_DESC(enable_fbc,
"Enable frame buffer compression for power savings "
"(default: -1 (use per-chip default))");
-module_param_named(lvds_channel_mode, i915.lvds_channel_mode, int, 0600);
+module_param_named_unsafe(lvds_channel_mode, i915.lvds_channel_mode, int, 0600);
MODULE_PARM_DESC(lvds_channel_mode,
"Specify LVDS channel mode "
"(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");
-module_param_named(lvds_use_ssc, i915.panel_use_ssc, int, 0600);
+module_param_named_unsafe(lvds_use_ssc, i915.panel_use_ssc, int, 0600);
MODULE_PARM_DESC(lvds_use_ssc,
"Use Spread Spectrum Clock with panels [LVDS/eDP] "
"(default: auto from VBT)");
-module_param_named(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600);
+module_param_named_unsafe(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600);
MODULE_PARM_DESC(vbt_sdvo_panel_type,
"Override/Ignore selection of SDVO panel mode in the VBT "
"(-2=ignore, -1=auto [default], index in VBT BIOS table)");
@@ -102,7 +103,7 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type,
module_param_named_unsafe(reset, i915.reset, bool, 0600);
MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
-module_param_named(enable_hangcheck, i915.enable_hangcheck, bool, 0644);
+module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644);
MODULE_PARM_DESC(enable_hangcheck,
"Periodically check GPU activity for detecting hangs. "
"WARNING: Disabling this can cause system wide hangs. "
@@ -113,23 +114,24 @@ MODULE_PARM_DESC(enable_ppgtt,
"Override PPGTT usage. "
"(-1=auto [default], 0=disabled, 1=aliasing, 2=full)");
-module_param_named(enable_execlists, i915.enable_execlists, int, 0400);
+module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400);
MODULE_PARM_DESC(enable_execlists,
"Override execlists usage. "
"(-1=auto [default], 0=disabled, 1=enabled)");
-module_param_named(enable_psr, i915.enable_psr, int, 0600);
+module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600);
MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)");
-module_param_named(preliminary_hw_support, i915.preliminary_hw_support, int, 0600);
+module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, int, 0600);
MODULE_PARM_DESC(preliminary_hw_support,
"Enable preliminary hardware support.");
-module_param_named(disable_power_well, i915.disable_power_well, int, 0600);
+module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0600);
MODULE_PARM_DESC(disable_power_well,
- "Disable the power well when possible (default: true)");
+ "Disable display power wells when possible "
+ "(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)");
-module_param_named(enable_ips, i915.enable_ips, int, 0600);
+module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600);
MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
module_param_named(fastboot, i915.fastboot, bool, 0600);
@@ -146,7 +148,7 @@ MODULE_PARM_DESC(load_detect_test,
"Force-enable the VGA load detect code for testing (default:false). "
"For developers only.");
-module_param_named(invert_brightness, i915.invert_brightness, int, 0600);
+module_param_named_unsafe(invert_brightness, i915.invert_brightness, int, 0600);
MODULE_PARM_DESC(invert_brightness,
"Invert backlight brightness "
"(-1 force normal, 0 machine defaults, 1 force inversion), please "
@@ -157,14 +159,14 @@ MODULE_PARM_DESC(invert_brightness,
module_param_named(disable_display, i915.disable_display, bool, 0600);
MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
-module_param_named(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600);
+module_param_named_unsafe(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600);
MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)");
-module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
+module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled [default], 0=disabled)");
-module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600);
+module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600);
MODULE_PARM_DESC(use_mmio_flip,
"use MMIO flips (-1=never, 0=driver discretion [default], 1=always)");
@@ -177,6 +179,10 @@ module_param_named(verbose_state_checks, i915.verbose_state_checks, bool, 0600);
MODULE_PARM_DESC(verbose_state_checks,
"Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions.");
+module_param_named_unsafe(nuclear_pageflip, i915.nuclear_pageflip, bool, 0600);
+MODULE_PARM_DESC(nuclear_pageflip,
+ "Force atomic modeset functionality; asynchronous mode is not yet supported. (default: false).");
+
/* WA to get away with the default setting in VBT for early platforms.Will be removed */
module_param_named_unsafe(edp_vswing, i915.edp_vswing, int, 0400);
MODULE_PARM_DESC(edp_vswing,
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 83a0888756d6..bc7b8faba84d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -105,7 +105,7 @@
#define GRDOM_RESET_STATUS (1<<1)
#define GRDOM_RESET_ENABLE (1<<0)
-#define ILK_GDSR 0x2ca4 /* MCHBAR offset */
+#define ILK_GDSR (MCHBAR_MIRROR_BASE + 0x2ca4)
#define ILK_GRDOM_FULL (0<<1)
#define ILK_GRDOM_RENDER (1<<1)
#define ILK_GRDOM_MEDIA (3<<1)
@@ -352,8 +352,8 @@
*/
#define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*(x)-1)
#define MI_LRI_FORCE_POSTED (1<<12)
-#define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*(x)-1)
-#define MI_STORE_REGISTER_MEM_GEN8(x) MI_INSTR(0x24, 3*(x)-1)
+#define MI_STORE_REGISTER_MEM MI_INSTR(0x24, 1)
+#define MI_STORE_REGISTER_MEM_GEN8 MI_INSTR(0x24, 2)
#define MI_SRM_LRM_GLOBAL_GTT (1<<22)
#define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */
#define MI_FLUSH_DW_STORE_INDEX (1<<21)
@@ -364,8 +364,8 @@
#define MI_INVALIDATE_BSD (1<<7)
#define MI_FLUSH_DW_USE_GTT (1<<2)
#define MI_FLUSH_DW_USE_PPGTT (0<<2)
-#define MI_LOAD_REGISTER_MEM(x) MI_INSTR(0x29, 2*(x)-1)
-#define MI_LOAD_REGISTER_MEM_GEN8(x) MI_INSTR(0x29, 3*(x)-1)
+#define MI_LOAD_REGISTER_MEM MI_INSTR(0x29, 1)
+#define MI_LOAD_REGISTER_MEM_GEN8 MI_INSTR(0x29, 2)
#define MI_BATCH_BUFFER MI_INSTR(0x30, 1)
#define MI_BATCH_NON_SECURE (1)
/* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */
@@ -429,7 +429,7 @@
#define ASYNC_FLIP (1<<22)
#define DISPLAY_PLANE_A (0<<20)
#define DISPLAY_PLANE_B (1<<20)
-#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
+#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
#define PIPE_CONTROL_FLUSH_L3 (1<<27)
#define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */
#define PIPE_CONTROL_MMIO_WRITE (1<<23)
@@ -536,6 +536,10 @@
#define GEN7_3DPRIM_START_INSTANCE 0x243C
#define GEN7_3DPRIM_BASE_VERTEX 0x2440
+#define GEN7_GPGPU_DISPATCHDIMX 0x2500
+#define GEN7_GPGPU_DISPATCHDIMY 0x2504
+#define GEN7_GPGPU_DISPATCHDIMZ 0x2508
+
#define OACONTROL 0x2360
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
@@ -728,12 +732,13 @@ enum skl_disp_power_wells {
#define DSI_PLL_N1_DIV_MASK (3 << 16)
#define DSI_PLL_M1_DIV_SHIFT 0
#define DSI_PLL_M1_DIV_MASK (0x1ff << 0)
+#define CCK_CZ_CLOCK_CONTROL 0x62
#define CCK_DISPLAY_CLOCK_CONTROL 0x6b
-#define DISPLAY_TRUNK_FORCE_ON (1 << 17)
-#define DISPLAY_TRUNK_FORCE_OFF (1 << 16)
-#define DISPLAY_FREQUENCY_STATUS (0x1f << 8)
-#define DISPLAY_FREQUENCY_STATUS_SHIFT 8
-#define DISPLAY_FREQUENCY_VALUES (0x1f << 0)
+#define CCK_TRUNK_FORCE_ON (1 << 17)
+#define CCK_TRUNK_FORCE_OFF (1 << 16)
+#define CCK_FREQUENCY_STATUS (0x1f << 8)
+#define CCK_FREQUENCY_STATUS_SHIFT 8
+#define CCK_FREQUENCY_VALUES (0x1f << 0)
/**
* DOC: DPIO
@@ -1099,6 +1104,12 @@ enum skl_disp_power_wells {
#define DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE 1 /* 1: coarse & 0 : fine */
#define CHV_PLL_DW9(ch) _PIPE(ch, _CHV_PLL_DW9_CH0, _CHV_PLL_DW9_CH1)
+#define _CHV_CMN_DW0_CH0 0x8100
+#define DPIO_ALLDL_POWERDOWN_SHIFT_CH0 19
+#define DPIO_ANYDL_POWERDOWN_SHIFT_CH0 18
+#define DPIO_ALLDL_POWERDOWN (1 << 1)
+#define DPIO_ANYDL_POWERDOWN (1 << 0)
+
#define _CHV_CMN_DW5_CH0 0x8114
#define CHV_BUFRIGHTENA1_DISABLE (0 << 20)
#define CHV_BUFRIGHTENA1_NORMAL (1 << 20)
@@ -1135,10 +1146,23 @@ enum skl_disp_power_wells {
#define _CHV_CMN_DW19_CH0 0x814c
#define _CHV_CMN_DW6_CH1 0x8098
+#define DPIO_ALLDL_POWERDOWN_SHIFT_CH1 30 /* CL2 DW6 only */
+#define DPIO_ANYDL_POWERDOWN_SHIFT_CH1 29 /* CL2 DW6 only */
+#define DPIO_DYNPWRDOWNEN_CH1 (1 << 28) /* CL2 DW6 only */
#define CHV_CMN_USEDCLKCHANNEL (1 << 13)
+
#define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1)
+#define CHV_CMN_DW28 0x8170
+#define DPIO_CL1POWERDOWNEN (1 << 23)
+#define DPIO_DYNPWRDOWNEN_CH0 (1 << 22)
+#define DPIO_SUS_CLK_CONFIG_ON (0 << 0)
+#define DPIO_SUS_CLK_CONFIG_CLKREQ (1 << 0)
+#define DPIO_SUS_CLK_CONFIG_GATE (2 << 0)
+#define DPIO_SUS_CLK_CONFIG_GATE_CLKREQ (3 << 0)
+
#define CHV_CMN_DW30 0x8178
+#define DPIO_CL2_LDOFUSE_PWRENB (1 << 6)
#define DPIO_LRC_BYPASS (1 << 3)
#define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \
@@ -1231,7 +1255,7 @@ enum skl_disp_power_wells {
#define PORT_PLL_DCO_AMP_OVR_EN_H (1<<27)
#define PORT_PLL_DCO_AMP_DEFAULT 15
#define PORT_PLL_DCO_AMP_MASK 0x3c00
-#define PORT_PLL_DCO_AMP(x) (x<<10)
+#define PORT_PLL_DCO_AMP(x) ((x)<<10)
#define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \
_PORT_PLL_0_B, \
_PORT_PLL_0_C)
@@ -1376,7 +1400,8 @@ enum skl_disp_power_wells {
#define BXT_PORT_TX_DW3_LN0(port) _PORT3(port, _PORT_TX_DW3_LN0_A, \
_PORT_TX_DW3_LN0_B, \
_PORT_TX_DW3_LN0_C)
-#define UNIQE_TRANGE_EN_METHOD (1 << 27)
+#define SCALE_DCOMP_METHOD (1 << 26)
+#define UNIQUE_TRANGE_EN_METHOD (1 << 27)
#define _PORT_TX_DW4_LN0_A 0x162510
#define _PORT_TX_DW4_LN0_B 0x6C510
@@ -1417,9 +1442,15 @@ enum skl_disp_power_wells {
/*
* Fence registers
+ * [0-7] @ 0x2000 gen2,gen3
+ * [8-15] @ 0x3000 945,g33,pnv
+ *
+ * [0-15] @ 0x3000 gen4,gen5
+ *
+ * [0-15] @ 0x100000 gen6,vlv,chv
+ * [0-31] @ 0x100000 gen7+
*/
-#define FENCE_REG_830_0 0x2000
-#define FENCE_REG_945_8 0x3000
+#define FENCE_REG(i) (0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4)
#define I830_FENCE_START_MASK 0x07f80000
#define I830_FENCE_TILING_Y_SHIFT 12
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
@@ -1432,14 +1463,16 @@ enum skl_disp_power_wells {
#define I915_FENCE_START_MASK 0x0ff00000
#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8)
-#define FENCE_REG_965_0 0x03000
+#define FENCE_REG_965_LO(i) (0x03000 + (i) * 8)
+#define FENCE_REG_965_HI(i) (0x03000 + (i) * 8 + 4)
#define I965_FENCE_PITCH_SHIFT 2
#define I965_FENCE_TILING_Y_SHIFT 1
#define I965_FENCE_REG_VALID (1<<0)
#define I965_FENCE_MAX_PITCH_VAL 0x0400
-#define FENCE_REG_SANDYBRIDGE_0 0x100000
-#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32
+#define FENCE_REG_GEN6_LO(i) (0x100000 + (i) * 8)
+#define FENCE_REG_GEN6_HI(i) (0x100000 + (i) * 8 + 4)
+#define GEN6_FENCE_PITCH_SHIFT 32
#define GEN7_FENCE_MAX_PITCH_VAL 0x0800
@@ -1508,7 +1541,7 @@ enum skl_disp_power_wells {
#define GEN7_GFX_PEND_TLB0 0x4034
#define GEN7_GFX_PEND_TLB1 0x4038
/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
-#define GEN7_LRA_LIMITS_BASE 0x403C
+#define GEN7_LRA_LIMITS(i) (0x403C + (i) * 4)
#define GEN7_LRA_LIMITS_REG_NUM 13
#define GEN7_MEDIA_MAX_REQ_COUNT 0x4070
#define GEN7_GFX_MAX_REQ_COUNT 0x4074
@@ -1519,11 +1552,12 @@ enum skl_disp_power_wells {
#define RENDER_HWS_PGA_GEN7 (0x04080)
#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id)
#define RING_FAULT_GTTSEL_MASK (1<<11)
-#define RING_FAULT_SRCID(x) ((x >> 3) & 0xff)
-#define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3)
+#define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff)
+#define RING_FAULT_FAULT_TYPE(x) (((x) >> 1) & 0x3)
#define RING_FAULT_VALID (1<<0)
#define DONE_REG 0x40b0
-#define GEN8_PRIVATE_PAT 0x40e0
+#define GEN8_PRIVATE_PAT_LO 0x40e0
+#define GEN8_PRIVATE_PAT_HI (0x40e0 + 4)
#define BSD_HWS_PGA_GEN7 (0x04180)
#define BLT_HWS_PGA_GEN7 (0x04280)
#define VEBOX_HWS_PGA_GEN7 (0x04380)
@@ -1563,14 +1597,17 @@ enum skl_disp_power_wells {
#endif
#define IPEIR_I965 0x02064
#define IPEHR_I965 0x02068
-#define INSTDONE_I965 0x0206c
-#define GEN7_INSTDONE_1 0x0206c
#define GEN7_SC_INSTDONE 0x07100
#define GEN7_SAMPLER_INSTDONE 0x0e160
#define GEN7_ROW_INSTDONE 0x0e164
#define I915_NUM_INSTDONE_REG 4
#define RING_IPEIR(base) ((base)+0x64)
#define RING_IPEHR(base) ((base)+0x68)
+/*
+ * On GEN4, only the render ring INSTDONE exists and has a different
+ * layout than the GEN7+ version.
+ * The GEN2 counterpart of this register is GEN2_INSTDONE.
+ */
#define RING_INSTDONE(base) ((base)+0x6c)
#define RING_INSTPS(base) ((base)+0x70)
#define RING_DMA_FADD(base) ((base)+0x78)
@@ -1578,7 +1615,7 @@ enum skl_disp_power_wells {
#define RING_INSTPM(base) ((base)+0xc0)
#define RING_MI_MODE(base) ((base)+0x9c)
#define INSTPS 0x02070 /* 965+ only */
-#define INSTDONE1 0x0207c /* 965+ only */
+#define GEN4_INSTDONE1 0x0207c /* 965+ only, aka INSTDONE_2 on SNB */
#define ACTHD_I965 0x02074
#define HWS_PGA 0x02080
#define HWS_ADDRESS_MASK 0xfffff000
@@ -1587,7 +1624,7 @@ enum skl_disp_power_wells {
#define PWRCTX_EN (1<<0)
#define IPEIR 0x02088
#define IPEHR 0x0208c
-#define INSTDONE 0x02090
+#define GEN2_INSTDONE 0x02090
#define NOPID 0x02094
#define HWSTAM 0x02098
#define DMA_FADD_I8XX 0x020d0
@@ -1604,9 +1641,9 @@ enum skl_disp_power_wells {
#define ERR_INT_PIPE_CRC_DONE_B (1<<5)
#define ERR_INT_FIFO_UNDERRUN_B (1<<3)
#define ERR_INT_PIPE_CRC_DONE_A (1<<2)
-#define ERR_INT_PIPE_CRC_DONE(pipe) (1<<(2 + pipe*3))
+#define ERR_INT_PIPE_CRC_DONE(pipe) (1<<(2 + (pipe)*3))
#define ERR_INT_FIFO_UNDERRUN_A (1<<0)
-#define ERR_INT_FIFO_UNDERRUN(pipe) (1<<(pipe*3))
+#define ERR_INT_FIFO_UNDERRUN(pipe) (1<<((pipe)*3))
#define GEN8_FAULT_TLB_DATA0 0x04b10
#define GEN8_FAULT_TLB_DATA1 0x04b14
@@ -1667,18 +1704,25 @@ enum skl_disp_power_wells {
#define GEN6_WIZ_HASHING_16x4 GEN6_WIZ_HASHING(1, 0)
#define GEN6_WIZ_HASHING_MASK GEN6_WIZ_HASHING(1, 1)
#define GEN6_TD_FOUR_ROW_DISPATCH_DISABLE (1 << 5)
-#define GEN9_IZ_HASHING_MASK(slice) (0x3 << (slice * 2))
-#define GEN9_IZ_HASHING(slice, val) ((val) << (slice * 2))
+#define GEN9_IZ_HASHING_MASK(slice) (0x3 << ((slice) * 2))
+#define GEN9_IZ_HASHING(slice, val) ((val) << ((slice) * 2))
#define GFX_MODE 0x02520
#define GFX_MODE_GEN7 0x0229c
#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c)
#define GFX_RUN_LIST_ENABLE (1<<15)
+#define GFX_INTERRUPT_STEERING (1<<14)
#define GFX_TLB_INVALIDATE_EXPLICIT (1<<13)
#define GFX_SURFACE_FAULT_ENABLE (1<<12)
#define GFX_REPLAY_MODE (1<<11)
#define GFX_PSMI_GRANULARITY (1<<10)
#define GFX_PPGTT_ENABLE (1<<9)
+#define GEN8_GFX_PPGTT_48B (1<<7)
+
+#define GFX_FORWARD_VBLANK_MASK (3<<5)
+#define GFX_FORWARD_VBLANK_NEVER (0<<5)
+#define GFX_FORWARD_VBLANK_ALWAYS (1<<5)
+#define GFX_FORWARD_VBLANK_COND (2<<5)
#define VLV_DISPLAY_BASE 0x180000
#define VLV_MIPI_BASE VLV_DISPLAY_BASE
@@ -1850,12 +1894,27 @@ enum skl_disp_power_wells {
#define CHV_FGT_EU_DIS_SS1_R1_MASK (0xf << CHV_FGT_EU_DIS_SS1_R1_SHIFT)
#define GEN8_FUSE2 0x9120
+#define GEN8_F2_SS_DIS_SHIFT 21
+#define GEN8_F2_SS_DIS_MASK (0x7 << GEN8_F2_SS_DIS_SHIFT)
#define GEN8_F2_S_ENA_SHIFT 25
#define GEN8_F2_S_ENA_MASK (0x7 << GEN8_F2_S_ENA_SHIFT)
#define GEN9_F2_SS_DIS_SHIFT 20
#define GEN9_F2_SS_DIS_MASK (0xf << GEN9_F2_SS_DIS_SHIFT)
+#define GEN8_EU_DISABLE0 0x9134
+#define GEN8_EU_DIS0_S0_MASK 0xffffff
+#define GEN8_EU_DIS0_S1_SHIFT 24
+#define GEN8_EU_DIS0_S1_MASK (0xff << GEN8_EU_DIS0_S1_SHIFT)
+
+#define GEN8_EU_DISABLE1 0x9138
+#define GEN8_EU_DIS1_S1_MASK 0xffff
+#define GEN8_EU_DIS1_S2_SHIFT 16
+#define GEN8_EU_DIS1_S2_MASK (0xffff << GEN8_EU_DIS1_S2_SHIFT)
+
+#define GEN8_EU_DISABLE2 0x913c
+#define GEN8_EU_DIS2_S2_MASK 0xff
+
#define GEN9_EU_DISABLE(slice) (0x9134 + (slice)*0x4)
#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
@@ -1985,7 +2044,7 @@ enum skl_disp_power_wells {
#define FBC_CTL_CPU_FENCE (1<<1)
#define FBC_CTL_PLANE(plane) ((plane)<<0)
#define FBC_FENCE_OFF 0x03218 /* BSpec typo has 321Bh */
-#define FBC_TAG 0x03300
+#define FBC_TAG(i) (0x03300 + (i) * 4)
#define FBC_STATUS2 0x43214
#define FBC_COMPRESSION_MASK 0x7ff
@@ -2085,7 +2144,7 @@ enum skl_disp_power_wells {
# define GPIO_DATA_VAL_IN (1 << 12)
# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
-#define GMBUS0 0x5100 /* clock/port select */
+#define GMBUS0 (dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
#define GMBUS_RATE_100KHZ (0<<8)
#define GMBUS_RATE_50KHZ (1<<8)
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
@@ -2104,7 +2163,7 @@ enum skl_disp_power_wells {
#define GMBUS_PIN_2_BXT 2
#define GMBUS_PIN_3_BXT 3
#define GMBUS_NUM_PINS 7 /* including 0 */
-#define GMBUS1 0x5104 /* command/status */
+#define GMBUS1 (dev_priv->gpio_mmio_base + 0x5104) /* command/status */
#define GMBUS_SW_CLR_INT (1<<31)
#define GMBUS_SW_RDY (1<<30)
#define GMBUS_ENT (1<<29) /* enable timeout */
@@ -2118,7 +2177,7 @@ enum skl_disp_power_wells {
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
#define GMBUS_SLAVE_WRITE (0<<0)
-#define GMBUS2 0x5108 /* status */
+#define GMBUS2 (dev_priv->gpio_mmio_base + 0x5108) /* status */
#define GMBUS_INUSE (1<<15)
#define GMBUS_HW_WAIT_PHASE (1<<14)
#define GMBUS_STALL_TIMEOUT (1<<13)
@@ -2126,14 +2185,14 @@ enum skl_disp_power_wells {
#define GMBUS_HW_RDY (1<<11)
#define GMBUS_SATOER (1<<10)
#define GMBUS_ACTIVE (1<<9)
-#define GMBUS3 0x510c /* data buffer bytes 3-0 */
-#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */
+#define GMBUS3 (dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */
+#define GMBUS4 (dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */
#define GMBUS_SLAVE_TIMEOUT_EN (1<<4)
#define GMBUS_NAK_EN (1<<3)
#define GMBUS_IDLE_EN (1<<2)
#define GMBUS_HW_WAIT_EN (1<<1)
#define GMBUS_HW_RDY_EN (1<<0)
-#define GMBUS5 0x5120 /* byte index */
+#define GMBUS5 (dev_priv->gpio_mmio_base + 0x5120) /* byte index */
#define GMBUS_2BYTE_INDEX_EN (1<<31)
/*
@@ -2185,16 +2244,20 @@ enum skl_disp_power_wells {
#define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240)
#define DPLL_PORTD_READY_MASK (0xf)
#define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
+#define PHY_CH_POWER_DOWN_OVRD_EN(phy, ch) (1 << (2*(phy)+(ch)+27))
#define PHY_LDO_DELAY_0NS 0x0
#define PHY_LDO_DELAY_200NS 0x1
#define PHY_LDO_DELAY_600NS 0x2
#define PHY_LDO_SEQ_DELAY(delay, phy) ((delay) << (2*(phy)+23))
+#define PHY_CH_POWER_DOWN_OVRD(mask, phy, ch) ((mask) << (8*(phy)+4*(ch)+11))
#define PHY_CH_SU_PSR 0x1
#define PHY_CH_DEEP_PSR 0x7
#define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6*(phy)+3*(ch)+2))
#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy))
#define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
#define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
+#define PHY_STATUS_CMN_LDO(phy, ch) (1 << (6-(6*(phy)+3*(ch))))
+#define PHY_STATUS_SPLINE_LDO(phy, ch, spline) (1 << (8-(6*(phy)+3*(ch)+(spline))))
/*
* The i830 generation, in LVDS mode, defines P1 as the bit number set within
@@ -2445,8 +2508,8 @@ enum skl_disp_power_wells {
#define PALETTE_A_OFFSET 0xa000
#define PALETTE_B_OFFSET 0xa800
#define CHV_PALETTE_C_OFFSET 0xc000
-#define PALETTE(pipe) (dev_priv->info.palette_offsets[pipe] + \
- dev_priv->info.display_mmio_offset)
+#define PALETTE(pipe, i) (dev_priv->info.palette_offsets[pipe] + \
+ dev_priv->info.display_mmio_offset + (i) * 4)
/* MCH MMIO space */
@@ -2464,6 +2527,11 @@ enum skl_disp_power_wells {
#define MCHBAR_MIRROR_BASE_SNB 0x140000
+#define CTG_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x34)
+#define ELK_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x48)
+#define G4X_STOLEN_RESERVED_ADDR1_MASK (0xFFFF << 16)
+#define G4X_STOLEN_RESERVED_ADDR2_MASK (0xFFF << 4)
+
/* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */
#define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04)
@@ -2544,7 +2612,7 @@ enum skl_disp_power_wells {
#define TSFS_INTR_MASK 0x000000ff
#define CRSTANDVID 0x11100
-#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
+#define PXVFREQ(i) (0x11110 + (i) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
#define PXVFREQ_PX_MASK 0x7f000000
#define PXVFREQ_PX_SHIFT 24
#define VIDFREQ_BASE 0x11110
@@ -2728,8 +2796,8 @@ enum skl_disp_power_wells {
#define CSIEW0 0x11250
#define CSIEW1 0x11254
#define CSIEW2 0x11258
-#define PEW 0x1125c
-#define DEW 0x11270
+#define PEW(i) (0x1125c + (i) * 4) /* 5 registers */
+#define DEW(i) (0x11270 + (i) * 4) /* 3 registers */
#define MCHAFE 0x112c0
#define CSIEC 0x112e0
#define DMIEC 0x112e4
@@ -2753,8 +2821,8 @@ enum skl_disp_power_wells {
#define EG5 0x11624
#define EG6 0x11628
#define EG7 0x1162c
-#define PXW 0x11664
-#define PXWL 0x11680
+#define PXW(i) (0x11664 + (i) * 4) /* 4 registers */
+#define PXWL(i) (0x11680 + (i) * 4) /* 8 registers */
#define LCFUSE02 0x116c0
#define LCFUSE_HIV_MASK 0x000000ff
#define CSIPLL0 0x12c10
@@ -2772,8 +2840,11 @@ enum skl_disp_power_wells {
#define INTERVAL_1_28_US(us) (((us) * 100) >> 7)
#define INTERVAL_1_33_US(us) (((us) * 3) >> 2)
+#define INTERVAL_0_833_US(us) (((us) * 6) / 5)
#define GT_INTERVAL_FROM_US(dev_priv, us) (IS_GEN9(dev_priv) ? \
- INTERVAL_1_33_US(us) : \
+ (IS_BROXTON(dev_priv) ? \
+ INTERVAL_0_833_US(us) : \
+ INTERVAL_1_33_US(us)) : \
INTERVAL_1_28_US(us))
/*
@@ -2795,21 +2866,21 @@ enum skl_disp_power_wells {
* doesn't need saving on GT1
*/
#define CXT_SIZE 0x21a0
-#define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f)
-#define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f)
-#define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f)
-#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f)
-#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f)
+#define GEN6_CXT_POWER_SIZE(cxt_reg) (((cxt_reg) >> 24) & 0x3f)
+#define GEN6_CXT_RING_SIZE(cxt_reg) (((cxt_reg) >> 18) & 0x3f)
+#define GEN6_CXT_RENDER_SIZE(cxt_reg) (((cxt_reg) >> 12) & 0x3f)
+#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) (((cxt_reg) >> 6) & 0x3f)
+#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) (((cxt_reg) >> 0) & 0x3f)
#define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_RING_SIZE(cxt_reg) + \
GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \
GEN6_CXT_PIPELINE_SIZE(cxt_reg))
#define GEN7_CXT_SIZE 0x21a8
-#define GEN7_CXT_POWER_SIZE(ctx_reg) ((ctx_reg >> 25) & 0x7f)
-#define GEN7_CXT_RING_SIZE(ctx_reg) ((ctx_reg >> 22) & 0x7)
-#define GEN7_CXT_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f)
-#define GEN7_CXT_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f)
-#define GEN7_CXT_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7)
-#define GEN7_CXT_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f)
+#define GEN7_CXT_POWER_SIZE(ctx_reg) (((ctx_reg) >> 25) & 0x7f)
+#define GEN7_CXT_RING_SIZE(ctx_reg) (((ctx_reg) >> 22) & 0x7)
+#define GEN7_CXT_RENDER_SIZE(ctx_reg) (((ctx_reg) >> 16) & 0x3f)
+#define GEN7_CXT_EXTENDED_SIZE(ctx_reg) (((ctx_reg) >> 9) & 0x7f)
+#define GEN7_CXT_GT1_SIZE(ctx_reg) (((ctx_reg) >> 6) & 0x7)
+#define GEN7_CXT_VFSTATE_SIZE(ctx_reg) (((ctx_reg) >> 0) & 0x3f)
#define GEN7_CXT_TOTAL_SIZE(ctx_reg) (GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \
GEN7_CXT_VFSTATE_SIZE(ctx_reg))
/* Haswell does have the CXT_SIZE register however it does not appear to be
@@ -3229,7 +3300,9 @@ enum skl_disp_power_wells {
#define GEN3_SDVOC 0x61160
#define GEN4_HDMIB GEN3_SDVOB
#define GEN4_HDMIC GEN3_SDVOC
-#define CHV_HDMID 0x6116C
+#define VLV_HDMIB (VLV_DISPLAY_BASE + GEN4_HDMIB)
+#define VLV_HDMIC (VLV_DISPLAY_BASE + GEN4_HDMIC)
+#define CHV_HDMID (VLV_DISPLAY_BASE + 0x6116C)
#define PCH_SDVOB 0xe1140
#define PCH_HDMIB PCH_SDVOB
#define PCH_HDMIC 0xe1150
@@ -3561,17 +3634,29 @@ enum skl_disp_power_wells {
#define UTIL_PIN_CTL 0x48400
#define UTIL_PIN_ENABLE (1 << 31)
+#define UTIL_PIN_PIPE(x) ((x) << 29)
+#define UTIL_PIN_PIPE_MASK (3 << 29)
+#define UTIL_PIN_MODE_PWM (1 << 24)
+#define UTIL_PIN_MODE_MASK (0xf << 24)
+#define UTIL_PIN_POLARITY (1 << 22)
+
/* BXT backlight register definition. */
-#define BXT_BLC_PWM_CTL1 0xC8250
+#define _BXT_BLC_PWM_CTL1 0xC8250
#define BXT_BLC_PWM_ENABLE (1 << 31)
#define BXT_BLC_PWM_POLARITY (1 << 29)
-#define BXT_BLC_PWM_FREQ1 0xC8254
-#define BXT_BLC_PWM_DUTY1 0xC8258
+#define _BXT_BLC_PWM_FREQ1 0xC8254
+#define _BXT_BLC_PWM_DUTY1 0xC8258
-#define BXT_BLC_PWM_CTL2 0xC8350
-#define BXT_BLC_PWM_FREQ2 0xC8354
-#define BXT_BLC_PWM_DUTY2 0xC8358
+#define _BXT_BLC_PWM_CTL2 0xC8350
+#define _BXT_BLC_PWM_FREQ2 0xC8354
+#define _BXT_BLC_PWM_DUTY2 0xC8358
+#define BXT_BLC_PWM_CTL(controller) _PIPE(controller, \
+ _BXT_BLC_PWM_CTL1, _BXT_BLC_PWM_CTL2)
+#define BXT_BLC_PWM_FREQ(controller) _PIPE(controller, \
+ _BXT_BLC_PWM_FREQ1, _BXT_BLC_PWM_FREQ2)
+#define BXT_BLC_PWM_DUTY(controller) _PIPE(controller, \
+ _BXT_BLC_PWM_DUTY1, _BXT_BLC_PWM_DUTY2)
#define PCH_GTC_CTL 0xe7000
#define PCH_GTC_ENABLE (1 << 31)
@@ -4047,14 +4132,10 @@ enum skl_disp_power_wells {
# define TV_CC_DATA_1_MASK 0x0000007f
# define TV_CC_DATA_1_SHIFT 0
-#define TV_H_LUMA_0 0x68100
-#define TV_H_LUMA_59 0x681ec
-#define TV_H_CHROMA_0 0x68200
-#define TV_H_CHROMA_59 0x682ec
-#define TV_V_LUMA_0 0x68300
-#define TV_V_LUMA_42 0x683a8
-#define TV_V_CHROMA_0 0x68400
-#define TV_V_CHROMA_42 0x684a8
+#define TV_H_LUMA(i) (0x68100 + (i) * 4) /* 60 registers */
+#define TV_H_CHROMA(i) (0x68200 + (i) * 4) /* 60 registers */
+#define TV_V_LUMA(i) (0x68300 + (i) * 4) /* 43 registers */
+#define TV_V_CHROMA(i) (0x68400 + (i) * 4) /* 43 registers */
/* Display Port */
#define DP_A 0x64000 /* eDP */
@@ -4062,6 +4143,10 @@ enum skl_disp_power_wells {
#define DP_C 0x64200
#define DP_D 0x64300
+#define VLV_DP_B (VLV_DISPLAY_BASE + DP_B)
+#define VLV_DP_C (VLV_DISPLAY_BASE + DP_C)
+#define CHV_DP_D (VLV_DISPLAY_BASE + DP_D)
+
#define DP_PORT_EN (1 << 31)
#define DP_PIPEB_SELECT (1 << 30)
#define DP_PIPE_MASK (1 << 30)
@@ -4107,6 +4192,7 @@ enum skl_disp_power_wells {
/* How many wires to use. I guess 3 was too hard */
#define DP_PORT_WIDTH(width) (((width) - 1) << 19)
#define DP_PORT_WIDTH_MASK (7 << 19)
+#define DP_PORT_WIDTH_SHIFT 19
/* Mystic DPCD version 1.1 special mode */
#define DP_ENHANCED_FRAMING (1 << 18)
@@ -4198,7 +4284,7 @@ enum skl_disp_power_wells {
#define DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL (1 << 14)
#define DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL (1 << 13)
#define DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL (1 << 12)
-#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (1f << 5)
+#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (0x1f << 5)
#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) (((c) - 1) << 5)
#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) ((c) - 1)
@@ -4617,6 +4703,7 @@ enum skl_disp_power_wells {
#define CBR1_VLV (VLV_DISPLAY_BASE + 0x70400)
#define CBR_PND_DEADLINE_DISABLE (1<<31)
+#define CBR_PWM_CLOCK_MUX_SELECT (1<<30)
/* FIFO watermark sizes etc */
#define G4X_FIFO_LINE_SIZE 64
@@ -4759,10 +4846,10 @@ enum skl_disp_power_wells {
#define PIPE_PIXEL_MASK 0x00ffffff
#define PIPE_PIXEL_SHIFT 0
/* GM45+ just has to be different */
-#define _PIPEA_FRMCOUNT_GM45 0x70040
-#define _PIPEA_FLIPCOUNT_GM45 0x70044
-#define PIPE_FRMCOUNT_GM45(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_GM45)
-#define PIPE_FLIPCOUNT_GM45(pipe) _PIPE2(pipe, _PIPEA_FLIPCOUNT_GM45)
+#define _PIPEA_FRMCOUNT_G4X 0x70040
+#define _PIPEA_FLIPCOUNT_G4X 0x70044
+#define PIPE_FRMCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_G4X)
+#define PIPE_FLIPCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FLIPCOUNT_G4X)
/* Cursor A & B regs */
#define _CURACNTR 0x70080
@@ -4904,20 +4991,20 @@ enum skl_disp_power_wells {
#define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK)
#define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK)
-/* VBIOS flags */
-#define SWF00 (dev_priv->info.display_mmio_offset + 0x71410)
-#define SWF01 (dev_priv->info.display_mmio_offset + 0x71414)
-#define SWF02 (dev_priv->info.display_mmio_offset + 0x71418)
-#define SWF03 (dev_priv->info.display_mmio_offset + 0x7141c)
-#define SWF04 (dev_priv->info.display_mmio_offset + 0x71420)
-#define SWF05 (dev_priv->info.display_mmio_offset + 0x71424)
-#define SWF06 (dev_priv->info.display_mmio_offset + 0x71428)
-#define SWF10 (dev_priv->info.display_mmio_offset + 0x70410)
-#define SWF11 (dev_priv->info.display_mmio_offset + 0x70414)
-#define SWF14 (dev_priv->info.display_mmio_offset + 0x71420)
-#define SWF30 (dev_priv->info.display_mmio_offset + 0x72414)
-#define SWF31 (dev_priv->info.display_mmio_offset + 0x72418)
-#define SWF32 (dev_priv->info.display_mmio_offset + 0x7241c)
+/*
+ * VBIOS flags
+ * gen2:
+ * [00:06] alm,mgm
+ * [10:16] all
+ * [30:32] alm,mgm
+ * gen3+:
+ * [00:0f] all
+ * [10:1f] all
+ * [30:32] all
+ */
+#define SWF0(i) (dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4)
+#define SWF1(i) (dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4)
+#define SWF3(i) (dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4)
/* Pipe B */
#define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000)
@@ -4925,8 +5012,8 @@ enum skl_disp_power_wells {
#define _PIPEBSTAT (dev_priv->info.display_mmio_offset + 0x71024)
#define _PIPEBFRAMEHIGH 0x71040
#define _PIPEBFRAMEPIXEL 0x71044
-#define _PIPEB_FRMCOUNT_GM45 (dev_priv->info.display_mmio_offset + 0x71040)
-#define _PIPEB_FLIPCOUNT_GM45 (dev_priv->info.display_mmio_offset + 0x71044)
+#define _PIPEB_FRMCOUNT_G4X (dev_priv->info.display_mmio_offset + 0x71040)
+#define _PIPEB_FLIPCOUNT_G4X (dev_priv->info.display_mmio_offset + 0x71044)
/* Display B control */
@@ -5136,18 +5223,18 @@ enum skl_disp_power_wells {
#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8)
#define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4)
-#define SPCNTR(pipe, plane) _PIPE(pipe * 2 + plane, _SPACNTR, _SPBCNTR)
-#define SPLINOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPALINOFF, _SPBLINOFF)
-#define SPSTRIDE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASTRIDE, _SPBSTRIDE)
-#define SPPOS(pipe, plane) _PIPE(pipe * 2 + plane, _SPAPOS, _SPBPOS)
-#define SPSIZE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASIZE, _SPBSIZE)
-#define SPKEYMINVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMINVAL, _SPBKEYMINVAL)
-#define SPKEYMSK(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMSK, _SPBKEYMSK)
-#define SPSURF(pipe, plane) _PIPE(pipe * 2 + plane, _SPASURF, _SPBSURF)
-#define SPKEYMAXVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMAXVAL, _SPBKEYMAXVAL)
-#define SPTILEOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPATILEOFF, _SPBTILEOFF)
-#define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA)
-#define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC)
+#define SPCNTR(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR)
+#define SPLINOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPALINOFF, _SPBLINOFF)
+#define SPSTRIDE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASTRIDE, _SPBSTRIDE)
+#define SPPOS(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAPOS, _SPBPOS)
+#define SPSIZE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASIZE, _SPBSIZE)
+#define SPKEYMINVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMINVAL, _SPBKEYMINVAL)
+#define SPKEYMSK(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMSK, _SPBKEYMSK)
+#define SPSURF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASURF, _SPBSURF)
+#define SPKEYMAXVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
+#define SPTILEOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF)
+#define SPCONSTALPHA(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA)
+#define SPGAMC(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC)
/*
* CHV pipe B sprite CSC
@@ -5363,15 +5450,17 @@ enum skl_disp_power_wells {
#define CPU_VGACNTRL 0x41000
-#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030
-#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
-#define DIGITAL_PORTA_SHORT_PULSE_2MS (0 << 2)
-#define DIGITAL_PORTA_SHORT_PULSE_4_5MS (1 << 2)
-#define DIGITAL_PORTA_SHORT_PULSE_6MS (2 << 2)
-#define DIGITAL_PORTA_SHORT_PULSE_100MS (3 << 2)
-#define DIGITAL_PORTA_NO_DETECT (0 << 0)
-#define DIGITAL_PORTA_LONG_PULSE_DETECT_MASK (1 << 1)
-#define DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK (1 << 0)
+#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030
+#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
+#define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */
+#define DIGITAL_PORTA_PULSE_DURATION_4_5ms (1 << 2) /* pre-HSW */
+#define DIGITAL_PORTA_PULSE_DURATION_6ms (2 << 2) /* pre-HSW */
+#define DIGITAL_PORTA_PULSE_DURATION_100ms (3 << 2) /* pre-HSW */
+#define DIGITAL_PORTA_PULSE_DURATION_MASK (3 << 2) /* pre-HSW */
+#define DIGITAL_PORTA_HOTPLUG_STATUS_MASK (3 << 0)
+#define DIGITAL_PORTA_HOTPLUG_NO_DETECT (0 << 0)
+#define DIGITAL_PORTA_HOTPLUG_SHORT_DETECT (1 << 0)
+#define DIGITAL_PORTA_HOTPLUG_LONG_DETECT (2 << 0)
/* refresh rate hardware control */
#define RR_HW_CTL 0x45300
@@ -5491,7 +5580,7 @@ enum skl_disp_power_wells {
#define PS_SCALER_MODE_DYN (0 << 28)
#define PS_SCALER_MODE_HQ (1 << 28)
#define PS_PLANE_SEL_MASK (7 << 25)
-#define PS_PLANE_SEL(plane) ((plane + 1) << 25)
+#define PS_PLANE_SEL(plane) (((plane) + 1) << 25)
#define PS_FILTER_MASK (3 << 23)
#define PS_FILTER_MEDIUM (0 << 23)
#define PS_FILTER_EDGE_ENHANCE (2 << 23)
@@ -5596,7 +5685,7 @@ enum skl_disp_power_wells {
/* legacy palette */
#define _LGC_PALETTE_A 0x4a000
#define _LGC_PALETTE_B 0x4a800
-#define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
+#define LGC_PALETTE(pipe, i) (_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4)
#define _GAMMA_MODE_A 0x4a480
#define _GAMMA_MODE_B 0x4ac80
@@ -5656,7 +5745,7 @@ enum skl_disp_power_wells {
#define DE_PLANEA_FLIP_DONE_IVB (1<<3)
#define DE_PLANE_FLIP_DONE_IVB(plane) (1<< (3 + 5*(plane)))
#define DE_PIPEA_VBLANK_IVB (1<<0)
-#define DE_PIPE_VBLANK_IVB(pipe) (1 << (pipe * 5))
+#define DE_PIPE_VBLANK_IVB(pipe) (1 << ((pipe) * 5))
#define VLV_MASTER_IER 0x4400c /* Gunit master IER */
#define MASTER_INTERRUPT_ENABLE (1<<31)
@@ -5680,7 +5769,7 @@ enum skl_disp_power_wells {
#define GEN8_DE_PIPE_C_IRQ (1<<18)
#define GEN8_DE_PIPE_B_IRQ (1<<17)
#define GEN8_DE_PIPE_A_IRQ (1<<16)
-#define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+pipe))
+#define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+(pipe)))
#define GEN8_GT_VECS_IRQ (1<<6)
#define GEN8_GT_PM_IRQ (1<<4)
#define GEN8_GT_VCS2_IRQ (1<<3)
@@ -5693,11 +5782,12 @@ enum skl_disp_power_wells {
#define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which)))
#define GEN8_GT_IER(which) (0x4430c + (0x10 * (which)))
-#define GEN8_BCS_IRQ_SHIFT 16
#define GEN8_RCS_IRQ_SHIFT 0
-#define GEN8_VCS2_IRQ_SHIFT 16
+#define GEN8_BCS_IRQ_SHIFT 16
#define GEN8_VCS1_IRQ_SHIFT 0
+#define GEN8_VCS2_IRQ_SHIFT 16
#define GEN8_VECS_IRQ_SHIFT 0
+#define GEN8_WD_IRQ_SHIFT 16
#define GEN8_DE_PIPE_ISR(pipe) (0x44400 + (0x10 * (pipe)))
#define GEN8_DE_PIPE_IMR(pipe) (0x44404 + (0x10 * (pipe)))
@@ -5723,7 +5813,7 @@ enum skl_disp_power_wells {
#define GEN9_PIPE_PLANE3_FLIP_DONE (1 << 5)
#define GEN9_PIPE_PLANE2_FLIP_DONE (1 << 4)
#define GEN9_PIPE_PLANE1_FLIP_DONE (1 << 3)
-#define GEN9_PIPE_PLANE_FLIP_DONE(p) (1 << (3 + p))
+#define GEN9_PIPE_PLANE_FLIP_DONE(p) (1 << (3 + (p)))
#define GEN8_DE_PIPE_IRQ_FAULT_ERRORS \
(GEN8_PIPE_CURSOR_FAULT | \
GEN8_PIPE_SPRITE_FAULT | \
@@ -5763,21 +5853,6 @@ enum skl_disp_power_wells {
#define GEN8_PCU_IIR 0x444e8
#define GEN8_PCU_IER 0x444ec
-/* BXT hotplug control */
-#define BXT_HOTPLUG_CTL 0xC4030
-#define BXT_DDIA_HPD_ENABLE (1 << 28)
-#define BXT_DDIA_HPD_STATUS (3 << 24)
-#define BXT_DDIC_HPD_ENABLE (1 << 12)
-#define BXT_DDIC_HPD_STATUS (3 << 8)
-#define BXT_DDIB_HPD_ENABLE (1 << 4)
-#define BXT_DDIB_HPD_STATUS (3 << 0)
-#define BXT_HOTPLUG_CTL_MASK (BXT_DDIA_HPD_ENABLE | \
- BXT_DDIB_HPD_ENABLE | \
- BXT_DDIC_HPD_ENABLE)
-#define BXT_HPD_STATUS_MASK (BXT_DDIA_HPD_STATUS | \
- BXT_DDIB_HPD_STATUS | \
- BXT_DDIC_HPD_STATUS)
-
#define ILK_DISPLAY_CHICKEN2 0x42004
/* Required on all Ironlake and Sandybridge according to the B-Spec. */
#define ILK_ELPIN_409_SELECT (1 << 25)
@@ -5950,6 +6025,7 @@ enum skl_disp_power_wells {
#define SDE_AUXB_CPT (1 << 25)
#define SDE_AUX_MASK_CPT (7 << 25)
#define SDE_PORTE_HOTPLUG_SPT (1 << 25)
+#define SDE_PORTA_HOTPLUG_SPT (1 << 24)
#define SDE_PORTD_HOTPLUG_CPT (1 << 23)
#define SDE_PORTC_HOTPLUG_CPT (1 << 22)
#define SDE_PORTB_HOTPLUG_CPT (1 << 21)
@@ -5963,7 +6039,8 @@ enum skl_disp_power_wells {
#define SDE_HOTPLUG_MASK_SPT (SDE_PORTE_HOTPLUG_SPT | \
SDE_PORTD_HOTPLUG_CPT | \
SDE_PORTC_HOTPLUG_CPT | \
- SDE_PORTB_HOTPLUG_CPT)
+ SDE_PORTB_HOTPLUG_CPT | \
+ SDE_PORTA_HOTPLUG_SPT)
#define SDE_GMBUS_CPT (1 << 17)
#define SDE_ERROR_CPT (1 << 16)
#define SDE_AUDIO_CP_REQ_C_CPT (1 << 10)
@@ -5995,49 +6072,49 @@ enum skl_disp_power_wells {
#define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6)
#define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3)
#define SERR_INT_TRANS_A_FIFO_UNDERRUN (1<<0)
-#define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<(pipe*3))
+#define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<((pipe)*3))
/* digital port hotplug */
-#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
-#define BXT_PORTA_HOTPLUG_ENABLE (1 << 28)
-#define BXT_PORTA_HOTPLUG_STATUS_MASK (0x3 << 24)
-#define BXT_PORTA_HOTPLUG_NO_DETECT (0 << 24)
-#define BXT_PORTA_HOTPLUG_SHORT_DETECT (1 << 24)
-#define BXT_PORTA_HOTPLUG_LONG_DETECT (2 << 24)
-#define PORTD_HOTPLUG_ENABLE (1 << 20)
-#define PORTD_PULSE_DURATION_2ms (0)
-#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
-#define PORTD_PULSE_DURATION_6ms (2 << 18)
-#define PORTD_PULSE_DURATION_100ms (3 << 18)
-#define PORTD_PULSE_DURATION_MASK (3 << 18)
-#define PORTD_HOTPLUG_STATUS_MASK (0x3 << 16)
+#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
+#define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */
+#define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */
+#define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */
+#define PORTA_HOTPLUG_SHORT_DETECT (1 << 24) /* SPT+ & BXT */
+#define PORTA_HOTPLUG_LONG_DETECT (2 << 24) /* SPT+ & BXT */
+#define PORTD_HOTPLUG_ENABLE (1 << 20)
+#define PORTD_PULSE_DURATION_2ms (0 << 18) /* pre-LPT */
+#define PORTD_PULSE_DURATION_4_5ms (1 << 18) /* pre-LPT */
+#define PORTD_PULSE_DURATION_6ms (2 << 18) /* pre-LPT */
+#define PORTD_PULSE_DURATION_100ms (3 << 18) /* pre-LPT */
+#define PORTD_PULSE_DURATION_MASK (3 << 18) /* pre-LPT */
+#define PORTD_HOTPLUG_STATUS_MASK (3 << 16)
#define PORTD_HOTPLUG_NO_DETECT (0 << 16)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (2 << 16)
-#define PORTC_HOTPLUG_ENABLE (1 << 12)
-#define PORTC_PULSE_DURATION_2ms (0)
-#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
-#define PORTC_PULSE_DURATION_6ms (2 << 10)
-#define PORTC_PULSE_DURATION_100ms (3 << 10)
-#define PORTC_PULSE_DURATION_MASK (3 << 10)
-#define PORTC_HOTPLUG_STATUS_MASK (0x3 << 8)
+#define PORTC_HOTPLUG_ENABLE (1 << 12)
+#define PORTC_PULSE_DURATION_2ms (0 << 10) /* pre-LPT */
+#define PORTC_PULSE_DURATION_4_5ms (1 << 10) /* pre-LPT */
+#define PORTC_PULSE_DURATION_6ms (2 << 10) /* pre-LPT */
+#define PORTC_PULSE_DURATION_100ms (3 << 10) /* pre-LPT */
+#define PORTC_PULSE_DURATION_MASK (3 << 10) /* pre-LPT */
+#define PORTC_HOTPLUG_STATUS_MASK (3 << 8)
#define PORTC_HOTPLUG_NO_DETECT (0 << 8)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (2 << 8)
-#define PORTB_HOTPLUG_ENABLE (1 << 4)
-#define PORTB_PULSE_DURATION_2ms (0)
-#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
-#define PORTB_PULSE_DURATION_6ms (2 << 2)
-#define PORTB_PULSE_DURATION_100ms (3 << 2)
-#define PORTB_PULSE_DURATION_MASK (3 << 2)
-#define PORTB_HOTPLUG_STATUS_MASK (0x3 << 0)
+#define PORTB_HOTPLUG_ENABLE (1 << 4)
+#define PORTB_PULSE_DURATION_2ms (0 << 2) /* pre-LPT */
+#define PORTB_PULSE_DURATION_4_5ms (1 << 2) /* pre-LPT */
+#define PORTB_PULSE_DURATION_6ms (2 << 2) /* pre-LPT */
+#define PORTB_PULSE_DURATION_100ms (3 << 2) /* pre-LPT */
+#define PORTB_PULSE_DURATION_MASK (3 << 2) /* pre-LPT */
+#define PORTB_HOTPLUG_STATUS_MASK (3 << 0)
#define PORTB_HOTPLUG_NO_DETECT (0 << 0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (2 << 0)
-#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 */
-#define PORTE_HOTPLUG_ENABLE (1 << 4)
-#define PORTE_HOTPLUG_STATUS_MASK (0x3 << 0)
+#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 SPT+ */
+#define PORTE_HOTPLUG_ENABLE (1 << 4)
+#define PORTE_HOTPLUG_STATUS_MASK (3 << 0)
#define PORTE_HOTPLUG_NO_DETECT (0 << 0)
#define PORTE_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTE_HOTPLUG_LONG_DETECT (2 << 0)
@@ -6106,9 +6183,9 @@ enum skl_disp_power_wells {
#define PCH_SSC4_AUX_PARMS 0xc6214
#define PCH_DPLL_SEL 0xc7000
-#define TRANS_DPLLB_SEL(pipe) (1 << (pipe * 4))
+#define TRANS_DPLLB_SEL(pipe) (1 << ((pipe) * 4))
#define TRANS_DPLLA_SEL(pipe) 0
-#define TRANS_DPLL_ENABLE(pipe) (1 << (pipe * 4 + 3))
+#define TRANS_DPLL_ENABLE(pipe) (1 << ((pipe) * 4 + 3))
/* transcoder */
@@ -6209,16 +6286,16 @@ enum skl_disp_power_wells {
#define HSW_TVIDEO_DIP_CTL(trans) \
_TRANSCODER2(trans, HSW_VIDEO_DIP_CTL_A)
-#define HSW_TVIDEO_DIP_AVI_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A)
-#define HSW_TVIDEO_DIP_VS_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A)
-#define HSW_TVIDEO_DIP_SPD_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A)
+#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A) + (i) * 4)
+#define HSW_TVIDEO_DIP_VS_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A) + (i) * 4)
+#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A) + (i) * 4)
#define HSW_TVIDEO_DIP_GCP(trans) \
_TRANSCODER2(trans, HSW_VIDEO_DIP_GCP_A)
-#define HSW_TVIDEO_DIP_VSC_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A)
+#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A) + (i) * 4)
#define HSW_STEREO_3D_CTL_A 0x70020
#define S3D_ENABLE (1<<31)
@@ -6304,9 +6381,11 @@ enum skl_disp_power_wells {
#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
#define FDI_BC_BIFURCATION_SELECT (1 << 12)
+#define SPT_PWM_GRANULARITY (1<<0)
#define SOUTH_CHICKEN2 0xc2004
#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13)
#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12)
+#define LPT_PWM_GRANULARITY (1<<5)
#define DPLS_EDP_PPS_FIX_DIS (1<<0)
#define _FDI_RXA_CHICKEN 0xc200c
@@ -6508,10 +6587,10 @@ enum skl_disp_power_wells {
#define _BXT_PP_ON_DELAYS2 0xc7308
#define _BXT_PP_OFF_DELAYS2 0xc730c
-#define BXT_PP_STATUS(n) ((!n) ? PCH_PP_STATUS : _BXT_PP_STATUS2)
-#define BXT_PP_CONTROL(n) ((!n) ? PCH_PP_CONTROL : _BXT_PP_CONTROL2)
-#define BXT_PP_ON_DELAYS(n) ((!n) ? PCH_PP_ON_DELAYS : _BXT_PP_ON_DELAYS2)
-#define BXT_PP_OFF_DELAYS(n) ((!n) ? PCH_PP_OFF_DELAYS : _BXT_PP_OFF_DELAYS2)
+#define BXT_PP_STATUS(n) _PIPE(n, PCH_PP_STATUS, _BXT_PP_STATUS2)
+#define BXT_PP_CONTROL(n) _PIPE(n, PCH_PP_CONTROL, _BXT_PP_CONTROL2)
+#define BXT_PP_ON_DELAYS(n) _PIPE(n, PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
+#define BXT_PP_OFF_DELAYS(n) _PIPE(n, PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
#define PCH_DP_B 0xe4100
#define PCH_DPB_AUX_CH_CTL 0xe4110
@@ -6784,7 +6863,7 @@ enum skl_disp_power_wells {
GEN6_PM_RP_DOWN_THRESHOLD | \
GEN6_PM_RP_DOWN_TIMEOUT)
-#define GEN7_GT_SCRATCH_BASE 0x4F100
+#define GEN7_GT_SCRATCH(i) (0x4F100 + (i) * 4)
#define GEN7_GT_SCRATCH_REG_NUM 8
#define VLV_GTLC_SURVIVABILITY_REG 0x130098
@@ -6843,6 +6922,9 @@ enum skl_disp_power_wells {
#define GEN6_RC6 3
#define GEN6_RC7 4
+#define GEN8_GT_SLICE_INFO 0x138064
+#define GEN8_LSLICESTAT_MASK 0x7
+
#define CHV_POWER_SS0_SIG1 0xa720
#define CHV_POWER_SS1_SIG1 0xa728
#define CHV_SS_PG_ENABLE (1<<1)
@@ -6870,7 +6952,10 @@ enum skl_disp_power_wells {
#define GEN9_PGCTL_SSB_EU311_ACK (1 << 14)
#define GEN7_MISCCPCTL (0x9424)
-#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0)
+#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0)
+#define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1<<2)
+#define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4)
+#define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6)
#define GEN8_GARBCNTL 0xB004
#define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7)
@@ -6916,6 +7001,9 @@ enum skl_disp_power_wells {
#define HSW_ROW_CHICKEN3 0xe49c
#define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6)
+#define HALF_SLICE_CHICKEN2 0xe180
+#define GEN8_ST_PO_DISABLE (1<<13)
+
#define HALF_SLICE_CHICKEN3 0xe184
#define HSW_SAMPLE_C_PERFORMANCE (1<<9)
#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8)
@@ -7159,12 +7247,15 @@ enum skl_disp_power_wells {
#define DDI_BUF_IS_IDLE (1<<7)
#define DDI_A_4_LANES (1<<4)
#define DDI_PORT_WIDTH(width) (((width) - 1) << 1)
+#define DDI_PORT_WIDTH_MASK (7 << 1)
+#define DDI_PORT_WIDTH_SHIFT 1
#define DDI_INIT_DISPLAY_DETECTED (1<<0)
/* DDI Buffer Translations */
#define DDI_BUF_TRANS_A 0x64E00
#define DDI_BUF_TRANS_B 0x64E60
-#define DDI_BUF_TRANS(port) _PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B)
+#define DDI_BUF_TRANS_LO(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8)
+#define DDI_BUF_TRANS_HI(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8 + 4)
/* Sideband Interface (SBI) is programmed indirectly, via
* SBI_ADDR, which contains the register offset; and SBI_DATA,
@@ -7257,7 +7348,7 @@ enum skl_disp_power_wells {
#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B)
/* For each transcoder, we need to select the corresponding port clock */
#define TRANS_CLK_SEL_DISABLED (0x0<<29)
-#define TRANS_CLK_SEL_PORT(x) ((x+1)<<29)
+#define TRANS_CLK_SEL_PORT(x) (((x)+1)<<29)
#define TRANSA_MSA_MISC 0x60410
#define TRANSB_MSA_MISC 0x61410
@@ -7330,10 +7421,10 @@ enum skl_disp_power_wells {
/* DPLL control2 */
#define DPLL_CTRL2 0x6C05C
-#define DPLL_CTRL2_DDI_CLK_OFF(port) (1<<(port+15))
+#define DPLL_CTRL2_DDI_CLK_OFF(port) (1<<((port)+15))
#define DPLL_CTRL2_DDI_CLK_SEL_MASK(port) (3<<((port)*3+1))
#define DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port) ((port)*3+1)
-#define DPLL_CTRL2_DDI_CLK_SEL(clk, port) (clk<<((port)*3+1))
+#define DPLL_CTRL2_DDI_CLK_SEL(clk, port) ((clk)<<((port)*3+1))
#define DPLL_CTRL2_DDI_SEL_OVERRIDE(port) (1<<((port)*3))
/* DPLL Status */
@@ -7346,31 +7437,31 @@ enum skl_disp_power_wells {
#define DPLL3_CFGCR1 0x6C050
#define DPLL_CFGCR1_FREQ_ENABLE (1<<31)
#define DPLL_CFGCR1_DCO_FRACTION_MASK (0x7fff<<9)
-#define DPLL_CFGCR1_DCO_FRACTION(x) (x<<9)
+#define DPLL_CFGCR1_DCO_FRACTION(x) ((x)<<9)
#define DPLL_CFGCR1_DCO_INTEGER_MASK (0x1ff)
#define DPLL1_CFGCR2 0x6C044
#define DPLL2_CFGCR2 0x6C04C
#define DPLL3_CFGCR2 0x6C054
#define DPLL_CFGCR2_QDIV_RATIO_MASK (0xff<<8)
-#define DPLL_CFGCR2_QDIV_RATIO(x) (x<<8)
-#define DPLL_CFGCR2_QDIV_MODE(x) (x<<7)
+#define DPLL_CFGCR2_QDIV_RATIO(x) ((x)<<8)
+#define DPLL_CFGCR2_QDIV_MODE(x) ((x)<<7)
#define DPLL_CFGCR2_KDIV_MASK (3<<5)
-#define DPLL_CFGCR2_KDIV(x) (x<<5)
+#define DPLL_CFGCR2_KDIV(x) ((x)<<5)
#define DPLL_CFGCR2_KDIV_5 (0<<5)
#define DPLL_CFGCR2_KDIV_2 (1<<5)
#define DPLL_CFGCR2_KDIV_3 (2<<5)
#define DPLL_CFGCR2_KDIV_1 (3<<5)
#define DPLL_CFGCR2_PDIV_MASK (7<<2)
-#define DPLL_CFGCR2_PDIV(x) (x<<2)
+#define DPLL_CFGCR2_PDIV(x) ((x)<<2)
#define DPLL_CFGCR2_PDIV_1 (0<<2)
#define DPLL_CFGCR2_PDIV_2 (1<<2)
#define DPLL_CFGCR2_PDIV_3 (2<<2)
#define DPLL_CFGCR2_PDIV_7 (4<<2)
#define DPLL_CFGCR2_CENTRAL_FREQ_MASK (3)
-#define GET_CFG_CR1_REG(id) (DPLL1_CFGCR1 + (id - SKL_DPLL1) * 8)
-#define GET_CFG_CR2_REG(id) (DPLL1_CFGCR2 + (id - SKL_DPLL1) * 8)
+#define DPLL_CFGCR1(id) (DPLL1_CFGCR1 + ((id) - SKL_DPLL1) * 8)
+#define DPLL_CFGCR2(id) (DPLL1_CFGCR2 + ((id) - SKL_DPLL1) * 8)
/* BXT display engine PLL */
#define BXT_DE_PLL_CTL 0x6d000
@@ -7475,9 +7566,116 @@ enum skl_disp_power_wells {
#define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */
+/* BXT MIPI clock controls */
+#define BXT_MAX_VAR_OUTPUT_KHZ 39500
+
+#define BXT_MIPI_CLOCK_CTL 0x46090
+#define BXT_MIPI1_DIV_SHIFT 26
+#define BXT_MIPI2_DIV_SHIFT 10
+#define BXT_MIPI_DIV_SHIFT(port) \
+ _MIPI_PORT(port, BXT_MIPI1_DIV_SHIFT, \
+ BXT_MIPI2_DIV_SHIFT)
+/* Var clock divider to generate TX source. Result must be < 39.5 M */
+#define BXT_MIPI1_ESCLK_VAR_DIV_MASK (0x3F << 26)
+#define BXT_MIPI2_ESCLK_VAR_DIV_MASK (0x3F << 10)
+#define BXT_MIPI_ESCLK_VAR_DIV_MASK(port) \
+ _MIPI_PORT(port, BXT_MIPI1_ESCLK_VAR_DIV_MASK, \
+ BXT_MIPI2_ESCLK_VAR_DIV_MASK)
+
+#define BXT_MIPI_ESCLK_VAR_DIV(port, val) \
+ (val << BXT_MIPI_DIV_SHIFT(port))
+/* TX control divider to select actual TX clock output from (8x/var) */
+#define BXT_MIPI1_TX_ESCLK_SHIFT 21
+#define BXT_MIPI2_TX_ESCLK_SHIFT 5
+#define BXT_MIPI_TX_ESCLK_SHIFT(port) \
+ _MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_SHIFT, \
+ BXT_MIPI2_TX_ESCLK_SHIFT)
+#define BXT_MIPI1_TX_ESCLK_FIXDIV_MASK (3 << 21)
+#define BXT_MIPI2_TX_ESCLK_FIXDIV_MASK (3 << 5)
+#define BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port) \
+ _MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_FIXDIV_MASK, \
+ BXT_MIPI2_TX_ESCLK_FIXDIV_MASK)
+#define BXT_MIPI_TX_ESCLK_8XDIV_BY2(port) \
+ (0x0 << BXT_MIPI_TX_ESCLK_SHIFT(port))
+#define BXT_MIPI_TX_ESCLK_8XDIV_BY4(port) \
+ (0x1 << BXT_MIPI_TX_ESCLK_SHIFT(port))
+#define BXT_MIPI_TX_ESCLK_8XDIV_BY8(port) \
+ (0x2 << BXT_MIPI_TX_ESCLK_SHIFT(port))
+/* RX control divider to select actual RX clock output from 8x*/
+#define BXT_MIPI1_RX_ESCLK_SHIFT 19
+#define BXT_MIPI2_RX_ESCLK_SHIFT 3
+#define BXT_MIPI_RX_ESCLK_SHIFT(port) \
+ _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_SHIFT, \
+ BXT_MIPI2_RX_ESCLK_SHIFT)
+#define BXT_MIPI1_RX_ESCLK_FIXDIV_MASK (3 << 19)
+#define BXT_MIPI2_RX_ESCLK_FIXDIV_MASK (3 << 3)
+#define BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port) \
+ (3 << BXT_MIPI_RX_ESCLK_SHIFT(port))
+#define BXT_MIPI_RX_ESCLK_8X_BY2(port) \
+ (1 << BXT_MIPI_RX_ESCLK_SHIFT(port))
+#define BXT_MIPI_RX_ESCLK_8X_BY3(port) \
+ (2 << BXT_MIPI_RX_ESCLK_SHIFT(port))
+#define BXT_MIPI_RX_ESCLK_8X_BY4(port) \
+ (3 << BXT_MIPI_RX_ESCLK_SHIFT(port))
+/* BXT-A WA: Always prog DPHY dividers to 00 */
+#define BXT_MIPI1_DPHY_DIV_SHIFT 16
+#define BXT_MIPI2_DPHY_DIV_SHIFT 0
+#define BXT_MIPI_DPHY_DIV_SHIFT(port) \
+ _MIPI_PORT(port, BXT_MIPI1_DPHY_DIV_SHIFT, \
+ BXT_MIPI2_DPHY_DIV_SHIFT)
+#define BXT_MIPI_1_DPHY_DIVIDER_MASK (3 << 16)
+#define BXT_MIPI_2_DPHY_DIVIDER_MASK (3 << 0)
+#define BXT_MIPI_DPHY_DIVIDER_MASK(port) \
+ (3 << BXT_MIPI_DPHY_DIV_SHIFT(port))
+
+/* BXT MIPI mode configure */
+#define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8
+#define _BXT_MIPIC_TRANS_HACTIVE 0x6B8F8
+#define BXT_MIPI_TRANS_HACTIVE(tc) _MIPI_PORT(tc, \
+ _BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE)
+
+#define _BXT_MIPIA_TRANS_VACTIVE 0x6B0FC
+#define _BXT_MIPIC_TRANS_VACTIVE 0x6B8FC
+#define BXT_MIPI_TRANS_VACTIVE(tc) _MIPI_PORT(tc, \
+ _BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE)
+
+#define _BXT_MIPIA_TRANS_VTOTAL 0x6B100
+#define _BXT_MIPIC_TRANS_VTOTAL 0x6B900
+#define BXT_MIPI_TRANS_VTOTAL(tc) _MIPI_PORT(tc, \
+ _BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL)
+
+#define BXT_DSI_PLL_CTL 0x161000
+#define BXT_DSI_PLL_PVD_RATIO_SHIFT 16
+#define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT)
+#define BXT_DSI_PLL_PVD_RATIO_1 (1 << BXT_DSI_PLL_PVD_RATIO_SHIFT)
+#define BXT_DSIC_16X_BY2 (1 << 10)
+#define BXT_DSIC_16X_BY3 (2 << 10)
+#define BXT_DSIC_16X_BY4 (3 << 10)
+#define BXT_DSIA_16X_BY2 (1 << 8)
+#define BXT_DSIA_16X_BY3 (2 << 8)
+#define BXT_DSIA_16X_BY4 (3 << 8)
+#define BXT_DSI_FREQ_SEL_SHIFT 8
+#define BXT_DSI_FREQ_SEL_MASK (0xF << BXT_DSI_FREQ_SEL_SHIFT)
+
+#define BXT_DSI_PLL_RATIO_MAX 0x7D
+#define BXT_DSI_PLL_RATIO_MIN 0x22
+#define BXT_DSI_PLL_RATIO_MASK 0xFF
+#define BXT_REF_CLOCK_KHZ 19500
+
+#define BXT_DSI_PLL_ENABLE 0x46080
+#define BXT_DSI_PLL_DO_ENABLE (1 << 31)
+#define BXT_DSI_PLL_LOCKED (1 << 30)
+
#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190)
#define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700)
#define MIPI_PORT_CTRL(port) _MIPI_PORT(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL)
+
+ /* BXT port control */
+#define _BXT_MIPIA_PORT_CTRL 0x6B0C0
+#define _BXT_MIPIC_PORT_CTRL 0x6B8C0
+#define BXT_MIPI_PORT_CTRL(tc) _MIPI_PORT(tc, _BXT_MIPIA_PORT_CTRL, \
+ _BXT_MIPIC_PORT_CTRL)
+
#define DPI_ENABLE (1 << 31) /* A + C */
#define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27
#define MIPIA_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 27)
@@ -7781,7 +7979,7 @@ enum skl_disp_power_wells {
#define VIRTUAL_CHANNEL_SHIFT 6
#define VIRTUAL_CHANNEL_MASK (3 << 6)
#define DATA_TYPE_SHIFT 0
-#define DATA_TYPE_MASK (3f << 0)
+#define DATA_TYPE_MASK (0x3f << 0)
/* data type values, see include/video/mipi_display.h */
#define _MIPIA_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb074)
@@ -7888,6 +8086,11 @@ enum skl_disp_power_wells {
#define READ_REQUEST_PRIORITY_HIGH (3 << 3)
#define RGB_FLIP_TO_BGR (1 << 2)
+#define BXT_PIPE_SELECT_MASK (7 << 7)
+#define BXT_PIPE_SELECT_C (2 << 7)
+#define BXT_PIPE_SELECT_B (1 << 7)
+#define BXT_PIPE_SELECT_A (0 << 7)
+
#define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108)
#define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908)
#define MIPI_DATA_ADDRESS(port) _MIPI_PORT(port, _MIPIA_DATA_ADDRESS, \
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 1ccac618468e..2d9182189422 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -122,12 +122,24 @@ int i915_save_state(struct drm_device *dev)
dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
/* Scratch space */
- for (i = 0; i < 16; i++) {
- dev_priv->regfile.saveSWF0[i] = I915_READ(SWF00 + (i << 2));
- dev_priv->regfile.saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+ if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
+ for (i = 0; i < 7; i++) {
+ dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
+ dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
+ }
+ for (i = 0; i < 3; i++)
+ dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
+ } else if (IS_GEN2(dev_priv)) {
+ for (i = 0; i < 7; i++)
+ dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
+ } else if (HAS_GMCH_DISPLAY(dev_priv)) {
+ for (i = 0; i < 16; i++) {
+ dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
+ dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
+ }
+ for (i = 0; i < 3; i++)
+ dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
}
- for (i = 0; i < 3; i++)
- dev_priv->regfile.saveSWF2[i] = I915_READ(SWF30 + (i << 2));
mutex_unlock(&dev->struct_mutex);
@@ -156,12 +168,25 @@ int i915_restore_state(struct drm_device *dev)
/* Memory arbitration state */
I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
- for (i = 0; i < 16; i++) {
- I915_WRITE(SWF00 + (i << 2), dev_priv->regfile.saveSWF0[i]);
- I915_WRITE(SWF10 + (i << 2), dev_priv->regfile.saveSWF1[i]);
+ /* Scratch space */
+ if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
+ for (i = 0; i < 7; i++) {
+ I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
+ I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
+ }
+ for (i = 0; i < 3; i++)
+ I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
+ } else if (IS_GEN2(dev_priv)) {
+ for (i = 0; i < 7; i++)
+ I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
+ } else if (HAS_GMCH_DISPLAY(dev_priv)) {
+ for (i = 0; i < 16; i++) {
+ I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
+ I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
+ }
+ for (i = 0; i < 3; i++)
+ I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
}
- for (i = 0; i < 3; i++)
- I915_WRITE(SWF30 + (i << 2), dev_priv->regfile.saveSWF2[i]);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 55bd04c6b939..50ce9ce2b269 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -39,7 +39,7 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u64 raw_time; /* 32b value may overflow during fixed point math */
- u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
+ u64 units = 128ULL, div = 100000ULL;
u32 ret;
if (!intel_enable_rc6(dev))
@@ -49,41 +49,19 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
/* On VLV and CHV, residency time is in CZ units rather than 1.28us */
if (IS_VALLEYVIEW(dev)) {
- u32 clk_reg, czcount_30ns;
-
- if (IS_CHERRYVIEW(dev))
- clk_reg = CHV_CLK_CTL1;
- else
- clk_reg = VLV_CLK_CTL2;
-
- czcount_30ns = I915_READ(clk_reg) >> CLK_CTL2_CZCOUNT_30NS_SHIFT;
-
- if (!czcount_30ns) {
- WARN(!czcount_30ns, "bogus CZ count value");
- ret = 0;
- goto out;
- }
-
- if (IS_CHERRYVIEW(dev) && czcount_30ns == 1) {
- /* Special case for 320Mhz */
- div = 10000000ULL;
- units = 3125ULL;
- } else {
- czcount_30ns += 1;
- div = 1000000ULL;
- units = DIV_ROUND_UP_ULL(30ULL * bias, czcount_30ns);
- }
+ units = 1;
+ div = dev_priv->czclk_freq;
if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
units <<= 8;
-
- div = div * bias;
+ } else if (IS_BROXTON(dev)) {
+ units = 1;
+ div = 1200; /* 833.33ns */
}
raw_time = I915_READ(reg) * units;
ret = DIV_ROUND_UP_ULL(raw_time, div);
-out:
intel_runtime_pm_put(dev_priv);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 2f34c47bd4bf..04fe8491c8b6 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -17,8 +17,8 @@
/* pipe updates */
TRACE_EVENT(i915_pipe_update_start,
- TP_PROTO(struct intel_crtc *crtc, u32 min, u32 max),
- TP_ARGS(crtc, min, max),
+ TP_PROTO(struct intel_crtc *crtc),
+ TP_ARGS(crtc),
TP_STRUCT__entry(
__field(enum pipe, pipe)
@@ -33,8 +33,8 @@ TRACE_EVENT(i915_pipe_update_start,
__entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
crtc->pipe);
__entry->scanline = intel_get_crtc_scanline(crtc);
- __entry->min = min;
- __entry->max = max;
+ __entry->min = crtc->debug.min_vbl;
+ __entry->max = crtc->debug.max_vbl;
),
TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
@@ -43,8 +43,8 @@ TRACE_EVENT(i915_pipe_update_start,
);
TRACE_EVENT(i915_pipe_update_vblank_evaded,
- TP_PROTO(struct intel_crtc *crtc, u32 min, u32 max, u32 frame),
- TP_ARGS(crtc, min, max, frame),
+ TP_PROTO(struct intel_crtc *crtc),
+ TP_ARGS(crtc),
TP_STRUCT__entry(
__field(enum pipe, pipe)
@@ -56,10 +56,10 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded,
TP_fast_assign(
__entry->pipe = crtc->pipe;
- __entry->frame = frame;
- __entry->scanline = intel_get_crtc_scanline(crtc);
- __entry->min = min;
- __entry->max = max;
+ __entry->frame = crtc->debug.start_vbl_count;
+ __entry->scanline = crtc->debug.scanline_start;
+ __entry->min = crtc->debug.min_vbl;
+ __entry->max = crtc->debug.max_vbl;
),
TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
@@ -68,8 +68,8 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded,
);
TRACE_EVENT(i915_pipe_update_end,
- TP_PROTO(struct intel_crtc *crtc, u32 frame),
- TP_ARGS(crtc, frame),
+ TP_PROTO(struct intel_crtc *crtc, u32 frame, int scanline_end),
+ TP_ARGS(crtc, frame, scanline_end),
TP_STRUCT__entry(
__field(enum pipe, pipe)
@@ -80,7 +80,7 @@ TRACE_EVENT(i915_pipe_update_end,
TP_fast_assign(
__entry->pipe = crtc->pipe;
__entry->frame = frame;
- __entry->scanline = intel_get_crtc_scanline(crtc);
+ __entry->scanline = scanline_end;
),
TP_printk("pipe %c, frame=%u, scanline=%u",
@@ -107,6 +107,26 @@ TRACE_EVENT(i915_gem_object_create,
TP_printk("obj=%p, size=%u", __entry->obj, __entry->size)
);
+TRACE_EVENT(i915_gem_shrink,
+ TP_PROTO(struct drm_i915_private *i915, unsigned long target, unsigned flags),
+ TP_ARGS(i915, target, flags),
+
+ TP_STRUCT__entry(
+ __field(int, dev)
+ __field(unsigned long, target)
+ __field(unsigned, flags)
+ ),
+
+ TP_fast_assign(
+ __entry->dev = i915->dev->primary->index;
+ __entry->target = target;
+ __entry->flags = flags;
+ ),
+
+ TP_printk("dev=%d, target=%lu, flags=%x",
+ __entry->dev, __entry->target, __entry->flags)
+);
+
TRACE_EVENT(i915_vma_bind,
TP_PROTO(struct i915_vma *vma, unsigned flags),
TP_ARGS(vma, flags),
@@ -186,33 +206,49 @@ DEFINE_EVENT(i915_va, i915_va_alloc,
TP_ARGS(vm, start, length, name)
);
-DECLARE_EVENT_CLASS(i915_page_table_entry,
- TP_PROTO(struct i915_address_space *vm, u32 pde, u64 start, u64 pde_shift),
- TP_ARGS(vm, pde, start, pde_shift),
+DECLARE_EVENT_CLASS(i915_px_entry,
+ TP_PROTO(struct i915_address_space *vm, u32 px, u64 start, u64 px_shift),
+ TP_ARGS(vm, px, start, px_shift),
TP_STRUCT__entry(
__field(struct i915_address_space *, vm)
- __field(u32, pde)
+ __field(u32, px)
__field(u64, start)
__field(u64, end)
),
TP_fast_assign(
__entry->vm = vm;
- __entry->pde = pde;
+ __entry->px = px;
__entry->start = start;
- __entry->end = ((start + (1ULL << pde_shift)) & ~((1ULL << pde_shift)-1)) - 1;
+ __entry->end = ((start + (1ULL << px_shift)) & ~((1ULL << px_shift)-1)) - 1;
),
TP_printk("vm=%p, pde=%d (0x%llx-0x%llx)",
- __entry->vm, __entry->pde, __entry->start, __entry->end)
+ __entry->vm, __entry->px, __entry->start, __entry->end)
);
-DEFINE_EVENT(i915_page_table_entry, i915_page_table_entry_alloc,
+DEFINE_EVENT(i915_px_entry, i915_page_table_entry_alloc,
TP_PROTO(struct i915_address_space *vm, u32 pde, u64 start, u64 pde_shift),
TP_ARGS(vm, pde, start, pde_shift)
);
+DEFINE_EVENT_PRINT(i915_px_entry, i915_page_directory_entry_alloc,
+ TP_PROTO(struct i915_address_space *vm, u32 pdpe, u64 start, u64 pdpe_shift),
+ TP_ARGS(vm, pdpe, start, pdpe_shift),
+
+ TP_printk("vm=%p, pdpe=%d (0x%llx-0x%llx)",
+ __entry->vm, __entry->px, __entry->start, __entry->end)
+);
+
+DEFINE_EVENT_PRINT(i915_px_entry, i915_page_directory_pointer_entry_alloc,
+ TP_PROTO(struct i915_address_space *vm, u32 pml4e, u64 start, u64 pml4e_shift),
+ TP_ARGS(vm, pml4e, start, pml4e_shift),
+
+ TP_printk("vm=%p, pml4e=%d (0x%llx-0x%llx)",
+ __entry->vm, __entry->px, __entry->start, __entry->end)
+);
+
/* Avoid extra math because we only support two sizes. The format is defined by
* bitmap_scnprintf. Each 32 bits is 8 HEX digits followed by comma */
#define TRACE_PT_SIZE(bits) \
diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h
index 97a88b5f6a26..21c97f44d637 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.h
+++ b/drivers/gpu/drm/i915/i915_vgpu.h
@@ -40,6 +40,19 @@
#define INTEL_VGT_IF_VERSION \
INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR)
+/*
+ * notifications from guest to vgpu device model
+ */
+enum vgt_g2v_type {
+ VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE = 2,
+ VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY,
+ VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE,
+ VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY,
+ VGT_G2V_EXECLIST_CONTEXT_CREATE,
+ VGT_G2V_EXECLIST_CONTEXT_DESTROY,
+ VGT_G2V_MAX,
+};
+
struct vgt_if {
uint64_t magic; /* VGT_MAGIC */
uint16_t version_major;
@@ -70,11 +83,28 @@ struct vgt_if {
uint32_t rsv3[0x200 - 24]; /* pad to half page */
/*
* The bottom half page is for response from Gfx driver to hypervisor.
- * Set to reserved fields temporarily by now.
*/
uint32_t rsv4;
uint32_t display_ready; /* ready for display owner switch */
- uint32_t rsv5[0x200 - 2]; /* pad to one page */
+
+ uint32_t rsv5[4];
+
+ uint32_t g2v_notify;
+ uint32_t rsv6[7];
+
+ uint32_t pdp0_lo;
+ uint32_t pdp0_hi;
+ uint32_t pdp1_lo;
+ uint32_t pdp1_hi;
+ uint32_t pdp2_lo;
+ uint32_t pdp2_hi;
+ uint32_t pdp3_lo;
+ uint32_t pdp3_hi;
+
+ uint32_t execlist_context_descriptor_lo;
+ uint32_t execlist_context_descriptor_hi;
+
+ uint32_t rsv7[0x200 - 24]; /* pad to one page */
} __packed;
#define vgtif_reg(x) \
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index d96eee1ae9c5..eb638a1e69d2 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -5,7 +5,6 @@
*/
#include <linux/pci.h>
#include <linux/acpi.h>
-#include <linux/vga_switcheroo.h>
#include <drm/drmP.h>
#include "i915_drv.h"
@@ -146,7 +145,7 @@ static bool intel_dsm_detect(void)
if (vga_count == 2 && has_dsm) {
acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
- DRM_DEBUG_DRIVER("VGA switcheroo: detected DSM switching method %s handle\n",
+ DRM_DEBUG_DRIVER("vga_switcheroo: detected DSM switching method %s handle\n",
acpi_method_name);
return true;
}
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index e2531cf59266..f1975f267710 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -85,21 +85,15 @@ intel_connector_atomic_get_property(struct drm_connector *connector,
struct drm_crtc_state *
intel_crtc_duplicate_state(struct drm_crtc *crtc)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *crtc_state;
- if (WARN_ON(!intel_crtc->config))
- crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
- else
- crtc_state = kmemdup(intel_crtc->config,
- sizeof(*intel_crtc->config), GFP_KERNEL);
-
+ crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL);
if (!crtc_state)
return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
- crtc_state->base.crtc = crtc;
+ crtc_state->update_pipe = false;
return &crtc_state->base;
}
@@ -149,9 +143,6 @@ int intel_atomic_setup_scalers(struct drm_device *dev,
int i, j;
num_scalers_need = hweight32(scaler_state->scaler_users);
- DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n",
- crtc_state, num_scalers_need, intel_crtc->num_scalers,
- scaler_state->scaler_users);
/*
* High level flow:
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index f1ab8e4b9c11..a11980696595 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -76,11 +76,7 @@ intel_plane_duplicate_state(struct drm_plane *plane)
struct drm_plane_state *state;
struct intel_plane_state *intel_state;
- if (WARN_ON(!plane->state))
- intel_state = intel_create_plane_state(plane);
- else
- intel_state = kmemdup(plane->state, sizeof(*intel_state),
- GFP_KERNEL);
+ intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL);
if (!intel_state)
return NULL;
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 2a5c76faf9f8..4dccd9b003a1 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -50,36 +50,67 @@
* co-operation between the graphics and audio drivers is handled via audio
* related registers. (The notable exception is the power management, not
* covered here.)
+ *
+ * The struct i915_audio_component is used to interact between the graphics
+ * and audio drivers. The struct i915_audio_component_ops *ops in it is
+ * defined in graphics driver and called in audio driver. The
+ * struct i915_audio_component_audio_ops *audio_ops is called from i915 driver.
*/
static const struct {
int clock;
u32 config;
} hdmi_audio_clock[] = {
- { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 },
+ { 25175, AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 },
{ 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */
{ 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 },
- { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 },
+ { 27027, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 },
{ 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 },
- { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 },
- { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 },
+ { 54054, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 },
+ { 74176, AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 },
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 },
- { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
+ { 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 },
};
+/* HDMI N/CTS table */
+#define TMDS_297M 297000
+#define TMDS_296M 296703
+static const struct {
+ int sample_rate;
+ int clock;
+ int n;
+ int cts;
+} aud_ncts[] = {
+ { 44100, TMDS_296M, 4459, 234375 },
+ { 44100, TMDS_297M, 4704, 247500 },
+ { 48000, TMDS_296M, 5824, 281250 },
+ { 48000, TMDS_297M, 5120, 247500 },
+ { 32000, TMDS_296M, 5824, 421875 },
+ { 32000, TMDS_297M, 3072, 222750 },
+ { 88200, TMDS_296M, 8918, 234375 },
+ { 88200, TMDS_297M, 9408, 247500 },
+ { 96000, TMDS_296M, 11648, 281250 },
+ { 96000, TMDS_297M, 10240, 247500 },
+ { 176400, TMDS_296M, 17836, 234375 },
+ { 176400, TMDS_297M, 18816, 247500 },
+ { 192000, TMDS_296M, 23296, 281250 },
+ { 192000, TMDS_297M, 20480, 247500 },
+};
+
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
-static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode)
+static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode)
{
int i;
for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) {
- if (mode->clock == hdmi_audio_clock[i].clock)
+ if (adjusted_mode->crtc_clock == hdmi_audio_clock[i].clock)
break;
}
if (i == ARRAY_SIZE(hdmi_audio_clock)) {
- DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock);
+ DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n",
+ adjusted_mode->crtc_clock);
i = 1;
}
@@ -90,6 +121,45 @@ static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode)
return hdmi_audio_clock[i].config;
}
+static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
+ if ((rate == aud_ncts[i].sample_rate) &&
+ (mode->clock == aud_ncts[i].clock)) {
+ return aud_ncts[i].n;
+ }
+ }
+ return 0;
+}
+
+static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
+{
+ int n_low, n_up;
+ uint32_t tmp = val;
+
+ n_low = n & 0xfff;
+ n_up = (n >> 12) & 0xff;
+ tmp &= ~(AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK);
+ tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
+ (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
+ AUD_CONFIG_N_PROG_ENABLE);
+ return tmp;
+}
+
+/* check whether N/CTS/M need be set manually */
+static bool audio_rate_need_prog(struct intel_crtc *crtc,
+ const struct drm_display_mode *mode)
+{
+ if (((mode->clock == TMDS_297M) ||
+ (mode->clock == TMDS_296M)) &&
+ intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
+ return true;
+ else
+ return false;
+}
+
static bool intel_eld_uptodate(struct drm_connector *connector,
int reg_eldv, uint32_t bits_eldv,
int reg_elda, uint32_t bits_elda,
@@ -138,7 +208,7 @@ static void g4x_audio_codec_disable(struct intel_encoder *encoder)
static void g4x_audio_codec_enable(struct drm_connector *connector,
struct intel_encoder *encoder,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = connector->dev->dev_private;
uint8_t *eld = connector->eld;
@@ -184,6 +254,8 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder)
DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe));
+ mutex_lock(&dev_priv->av_mutex);
+
/* Disable timestamps */
tmp = I915_READ(HSW_AUD_CFG(pipe));
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
@@ -199,22 +271,31 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder)
tmp &= ~AUDIO_ELD_VALID(pipe);
tmp &= ~AUDIO_OUTPUT_ENABLE(pipe);
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+
+ mutex_unlock(&dev_priv->av_mutex);
}
static void hsw_audio_codec_enable(struct drm_connector *connector,
struct intel_encoder *encoder,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
enum pipe pipe = intel_crtc->pipe;
+ struct i915_audio_component *acomp = dev_priv->audio_component;
const uint8_t *eld = connector->eld;
+ struct intel_digital_port *intel_dig_port =
+ enc_to_dig_port(&encoder->base);
+ enum port port = intel_dig_port->port;
uint32_t tmp;
int len, i;
+ int n, rate;
DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n",
pipe_name(pipe), drm_eld_size(eld));
+ mutex_lock(&dev_priv->av_mutex);
+
/* Enable audio presence detect, invalidate ELD */
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
tmp |= AUDIO_OUTPUT_ENABLE(pipe);
@@ -246,13 +327,32 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
/* Enable timestamps */
tmp = I915_READ(HSW_AUD_CFG(pipe));
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
- tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
tmp |= AUD_CONFIG_N_VALUE_INDEX;
else
- tmp |= audio_config_hdmi_pixel_clock(mode);
+ tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
+
+ tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+ if (audio_rate_need_prog(intel_crtc, adjusted_mode)) {
+ if (!acomp)
+ rate = 0;
+ else if (port >= PORT_A && port <= PORT_E)
+ rate = acomp->aud_sample_rate[port];
+ else {
+ DRM_ERROR("invalid port: %d\n", port);
+ rate = 0;
+ }
+ n = audio_config_get_n(adjusted_mode, rate);
+ if (n != 0)
+ tmp = audio_config_setup_n_reg(n, tmp);
+ else
+ DRM_DEBUG_KMS("no suitable N value is found\n");
+ }
+
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+
+ mutex_unlock(&dev_priv->av_mutex);
}
static void ilk_audio_codec_disable(struct intel_encoder *encoder)
@@ -304,7 +404,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder)
static void ilk_audio_codec_enable(struct drm_connector *connector,
struct intel_encoder *encoder,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
@@ -381,7 +481,7 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
tmp |= AUD_CONFIG_N_VALUE_INDEX;
else
- tmp |= audio_config_hdmi_pixel_clock(mode);
+ tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
I915_WRITE(aud_config, tmp);
}
@@ -396,7 +496,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
{
struct drm_encoder *encoder = &intel_encoder->base;
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
- struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
struct drm_connector *connector;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -404,7 +504,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
enum port port = intel_dig_port->port;
- connector = drm_select_eld(encoder, mode);
+ connector = drm_select_eld(encoder);
if (!connector)
return;
@@ -419,10 +519,11 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
connector->eld[5] |= (1 << 2);
- connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
+ connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
if (dev_priv->display.audio_codec_enable)
- dev_priv->display.audio_codec_enable(connector, intel_encoder, mode);
+ dev_priv->display.audio_codec_enable(connector, intel_encoder,
+ adjusted_mode);
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
@@ -527,12 +628,91 @@ static int i915_audio_component_get_cdclk_freq(struct device *dev)
return ret;
}
+static int i915_audio_component_sync_audio_rate(struct device *dev,
+ int port, int rate)
+{
+ struct drm_i915_private *dev_priv = dev_to_i915(dev);
+ struct drm_device *drm_dev = dev_priv->dev;
+ struct intel_encoder *intel_encoder;
+ struct intel_digital_port *intel_dig_port;
+ struct intel_crtc *crtc;
+ struct drm_display_mode *mode;
+ struct i915_audio_component *acomp = dev_priv->audio_component;
+ enum pipe pipe = -1;
+ u32 tmp;
+ int n;
+
+ /* HSW, BDW SKL need this fix */
+ if (!IS_SKYLAKE(dev_priv) &&
+ !IS_BROADWELL(dev_priv) &&
+ !IS_HASWELL(dev_priv))
+ return 0;
+
+ mutex_lock(&dev_priv->av_mutex);
+ /* 1. get the pipe */
+ for_each_intel_encoder(drm_dev, intel_encoder) {
+ if (intel_encoder->type != INTEL_OUTPUT_HDMI)
+ continue;
+ intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+ if (port == intel_dig_port->port) {
+ crtc = to_intel_crtc(intel_encoder->base.crtc);
+ if (!crtc) {
+ DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__);
+ continue;
+ }
+ pipe = crtc->pipe;
+ break;
+ }
+ }
+
+ if (pipe == INVALID_PIPE) {
+ DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
+ mutex_unlock(&dev_priv->av_mutex);
+ return -ENODEV;
+ }
+ DRM_DEBUG_KMS("pipe %c connects port %c\n",
+ pipe_name(pipe), port_name(port));
+ mode = &crtc->config->base.adjusted_mode;
+
+ /* port must be valid now, otherwise the pipe will be invalid */
+ acomp->aud_sample_rate[port] = rate;
+
+ /* 2. check whether to set the N/CTS/M manually or not */
+ if (!audio_rate_need_prog(crtc, mode)) {
+ tmp = I915_READ(HSW_AUD_CFG(pipe));
+ tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+ I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ mutex_unlock(&dev_priv->av_mutex);
+ return 0;
+ }
+
+ n = audio_config_get_n(mode, rate);
+ if (n == 0) {
+ DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n",
+ port_name(port));
+ tmp = I915_READ(HSW_AUD_CFG(pipe));
+ tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+ I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ mutex_unlock(&dev_priv->av_mutex);
+ return 0;
+ }
+
+ /* 3. set the N/CTS/M */
+ tmp = I915_READ(HSW_AUD_CFG(pipe));
+ tmp = audio_config_setup_n_reg(n, tmp);
+ I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+
+ mutex_unlock(&dev_priv->av_mutex);
+ return 0;
+}
+
static const struct i915_audio_component_ops i915_audio_component_ops = {
.owner = THIS_MODULE,
.get_power = i915_audio_component_get_power,
.put_power = i915_audio_component_put_power,
.codec_wake_override = i915_audio_component_codec_wake_override,
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
+ .sync_audio_rate = i915_audio_component_sync_audio_rate,
};
static int i915_audio_component_bind(struct device *i915_dev,
@@ -540,6 +720,7 @@ static int i915_audio_component_bind(struct device *i915_dev,
{
struct i915_audio_component *acomp = data;
struct drm_i915_private *dev_priv = dev_to_i915(i915_dev);
+ int i;
if (WARN_ON(acomp->ops || acomp->dev))
return -EEXIST;
@@ -547,6 +728,9 @@ static int i915_audio_component_bind(struct device *i915_dev,
drm_modeset_lock_all(dev_priv->dev);
acomp->ops = &i915_audio_component_ops;
acomp->dev = i915_dev;
+ BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS);
+ for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++)
+ acomp->aud_sample_rate[i] = 0;
dev_priv->audio_component = acomp;
drm_modeset_unlock_all(dev_priv->dev);
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index c19e669ffe50..ce82f9c7df24 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1231,20 +1231,13 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = {
{ }
};
-static const struct bdb_header *validate_vbt(const void __iomem *_base,
+static const struct bdb_header *validate_vbt(const void *base,
size_t size,
- const void __iomem *_vbt,
+ const void *_vbt,
const char *source)
{
- /*
- * This is the one place where we explicitly discard the address space
- * (__iomem) of the BIOS/VBT. (And this will cause a sparse complaint.)
- * From now on everything is based on 'base', and treated as regular
- * memory.
- */
- const void *base = (const void *) _base;
- size_t offset = _vbt - _base;
- const struct vbt_header *vbt = base + offset;
+ size_t offset = _vbt - base;
+ const struct vbt_header *vbt = _vbt;
const struct bdb_header *bdb;
if (offset + sizeof(struct vbt_header) > size) {
@@ -1282,7 +1275,15 @@ static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
/* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i++) {
if (ioread32(bios + i) == *((const u32 *) "$VBT")) {
- bdb = validate_vbt(bios, size, bios + i, "PCI ROM");
+ /*
+ * This is the one place where we explicitly discard the
+ * address space (__iomem) of the BIOS/VBT. From now on
+ * everything is based on 'base', and treated as regular
+ * memory.
+ */
+ void *_bios = (void __force *) bios;
+
+ bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM");
break;
}
}
@@ -1350,21 +1351,3 @@ intel_parse_bios(struct drm_device *dev)
return 0;
}
-
-/* Ensure that vital registers have been initialised, even if the BIOS
- * is absent or just failing to do its job.
- */
-void intel_setup_bios(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- /* Set the Panel Power On/Off timings if uninitialized. */
- if (!HAS_PCH_SPLIT(dev) &&
- I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
- /* Set T2 to 40ms and T5 to 200ms */
- I915_WRITE(PP_ON_DELAYS, 0x019007d0);
-
- /* Set T3 to 35ms and Tx to 200ms */
- I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
- }
-}
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 46cd5c7ebacd..7ec8c9aefb84 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -588,7 +588,6 @@ struct bdb_psr {
struct psr_table psr_table[16];
} __packed;
-void intel_setup_bios(struct drm_device *dev);
int intel_parse_bios(struct drm_device *dev);
/*
@@ -742,7 +741,6 @@ int intel_parse_bios(struct drm_device *dev);
*/
#define DEVICE_TYPE_eDP_BITS \
(DEVICE_TYPE_INTERNAL_CONNECTOR | \
- DEVICE_TYPE_NOT_HDMI_OUTPUT | \
DEVICE_TYPE_MIPI_OUTPUT | \
DEVICE_TYPE_COMPOSITE_OUTPUT | \
DEVICE_TYPE_DUAL_CHANNEL | \
@@ -750,7 +748,6 @@ int intel_parse_bios(struct drm_device *dev);
DEVICE_TYPE_TMDS_DVI_SIGNALING | \
DEVICE_TYPE_VIDEO_SIGNALING | \
DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
- DEVICE_TYPE_DIGITAL_OUTPUT | \
DEVICE_TYPE_ANALOG_OUTPUT)
/* define the DVO port for HDMI output type */
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index af5e43bef4a4..6a2c76e367a5 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -138,18 +138,6 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
-static void hsw_crt_pre_enable(struct intel_encoder *encoder)
-{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n");
- I915_WRITE(SPLL_CTL,
- SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC);
- POSTING_READ(SPLL_CTL);
- udelay(20);
-}
-
/* Note: The caller is required to filter out dpms modes not supported by the
* platform. */
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -158,7 +146,7 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crt *crt = intel_encoder_to_crt(encoder);
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
- struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
u32 adpa;
if (INTEL_INFO(dev)->gen >= 5)
@@ -216,19 +204,6 @@ static void pch_post_disable_crt(struct intel_encoder *encoder)
intel_disable_crt(encoder);
}
-static void hsw_crt_post_disable(struct intel_encoder *encoder)
-{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t val;
-
- DRM_DEBUG_KMS("Disabling SPLL\n");
- val = I915_READ(SPLL_CTL);
- WARN_ON(!(val & SPLL_PLL_ENABLE));
- I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
- POSTING_READ(SPLL_CTL);
-}
-
static void intel_enable_crt(struct intel_encoder *encoder)
{
struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -280,6 +255,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
if (HAS_DDI(dev)) {
pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
pipe_config->port_clock = 135000 * 2;
+
+ pipe_config->dpll_hw_state.wrpll = 0;
+ pipe_config->dpll_hw_state.spll =
+ SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
}
return true;
@@ -376,7 +355,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 hotplug_en, orig, stat;
+ u32 stat;
bool ret = false;
int i, tries = 0;
@@ -395,12 +374,12 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
tries = 2;
else
tries = 1;
- hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
- hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
for (i = 0; i < tries ; i++) {
/* turn on the FORCE_DETECT */
- I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+ i915_hotplug_interrupt_update(dev_priv,
+ CRT_HOTPLUG_FORCE_DETECT,
+ CRT_HOTPLUG_FORCE_DETECT);
/* wait for FORCE_DETECT to go off */
if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
CRT_HOTPLUG_FORCE_DETECT) == 0,
@@ -415,8 +394,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
/* clear the interrupt we just generated, if any */
I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
- /* and put the bits back */
- I915_WRITE(PORT_HOTPLUG_EN, orig);
+ i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0);
return ret;
}
@@ -861,8 +839,6 @@ void intel_crt_init(struct drm_device *dev)
if (HAS_DDI(dev)) {
crt->base.get_config = hsw_crt_get_config;
crt->base.get_hw_state = intel_ddi_get_hw_state;
- crt->base.pre_enable = hsw_crt_pre_enable;
- crt->base.post_disable = hsw_crt_post_disable;
} else {
crt->base.get_config = intel_crt_get_config;
crt->base.get_hw_state = intel_crt_get_hw_state;
@@ -891,7 +867,7 @@ void intel_crt_init(struct drm_device *dev)
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
FDI_RX_LINK_REVERSAL_OVERRIDE;
- dev_priv->fdi_rx_config = I915_READ(_FDI_RXA_CTL) & fdi_config;
+ dev_priv->fdi_rx_config = I915_READ(FDI_RX_CTL(PIPE_A)) & fdi_config;
}
intel_crt_reset(connector);
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index d0f1b8d833cd..9e530a739354 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -42,13 +42,15 @@
*/
#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
+#define I915_CSR_BXT "i915/bxt_dmc_ver1.bin"
MODULE_FIRMWARE(I915_CSR_SKL);
+MODULE_FIRMWARE(I915_CSR_BXT);
/*
* SKL CSR registers for DC5 and DC6
*/
-#define CSR_PROGRAM_BASE 0x80000
+#define CSR_PROGRAM(i) (0x80000 + (i) * 4)
#define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0
#define CSR_HTP_ADDR_SKL 0x00500034
#define CSR_SSP_BASE 0x8F074
@@ -181,11 +183,19 @@ static const struct stepping_info skl_stepping_info[] = {
{'G', '0'}, {'H', '0'}, {'I', '0'}
};
+static struct stepping_info bxt_stepping_info[] = {
+ {'A', '0'}, {'A', '1'}, {'A', '2'},
+ {'B', '0'}, {'B', '1'}, {'B', '2'}
+};
+
static char intel_get_stepping(struct drm_device *dev)
{
if (IS_SKYLAKE(dev) && (dev->pdev->revision <
ARRAY_SIZE(skl_stepping_info)))
return skl_stepping_info[dev->pdev->revision].stepping;
+ else if (IS_BROXTON(dev) && (dev->pdev->revision <
+ ARRAY_SIZE(bxt_stepping_info)))
+ return bxt_stepping_info[dev->pdev->revision].stepping;
else
return -ENODATA;
}
@@ -195,6 +205,9 @@ static char intel_get_substepping(struct drm_device *dev)
if (IS_SKYLAKE(dev) && (dev->pdev->revision <
ARRAY_SIZE(skl_stepping_info)))
return skl_stepping_info[dev->pdev->revision].substepping;
+ else if (IS_BROXTON(dev) && (dev->pdev->revision <
+ ARRAY_SIZE(bxt_stepping_info)))
+ return bxt_stepping_info[dev->pdev->revision].substepping;
else
return -ENODATA;
}
@@ -252,11 +265,19 @@ void intel_csr_load_program(struct drm_device *dev)
return;
}
+ /*
+ * FIXME: Firmware gets lost on S3/S4, but not when entering system
+ * standby or suspend-to-idle (which is just like forced runtime pm).
+ * Unfortunately the ACPI subsystem doesn't yet give us a way to
+ * differentiate this, hence figure it out with this hack.
+ */
+ if (I915_READ(CSR_PROGRAM(0)))
+ return;
+
mutex_lock(&dev_priv->csr_lock);
fw_size = dev_priv->csr.dmc_fw_size;
for (i = 0; i < fw_size; i++)
- I915_WRITE(CSR_PROGRAM_BASE + i * 4,
- payload[i]);
+ I915_WRITE(CSR_PROGRAM(i), payload[i]);
for (i = 0; i < dev_priv->csr.mmio_count; i++) {
I915_WRITE(dev_priv->csr.mmioaddr[i],
@@ -409,6 +430,8 @@ void intel_csr_ucode_init(struct drm_device *dev)
if (IS_SKYLAKE(dev))
csr->fw_path = I915_CSR_SKL;
+ else if (IS_BROXTON(dev_priv))
+ csr->fw_path = I915_CSR_BXT;
else {
DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
intel_csr_load_status_set(dev_priv, FW_FAILED);
@@ -454,10 +477,10 @@ void intel_csr_ucode_fini(struct drm_device *dev)
void assert_csr_loaded(struct drm_i915_private *dev_priv)
{
- WARN(intel_csr_load_status_get(dev_priv) != FW_LOADED,
- "CSR is not loaded.\n");
- WARN(!I915_READ(CSR_PROGRAM_BASE),
- "CSR program storage start is NULL\n");
- WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
- WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
+ WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED,
+ "CSR is not loaded.\n");
+ WARN_ONCE(!I915_READ(CSR_PROGRAM(0)),
+ "CSR program storage start is NULL\n");
+ WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
+ WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
}
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 61575f67a626..a6752a61d99f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -256,9 +256,6 @@ struct bxt_ddi_buf_trans {
bool default_index; /* true if the entry represents default value */
};
-/* BSpec does not define separate vswing/pre-emphasis values for eDP.
- * Using DP values for eDP as well.
- */
static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = {
/* Idx NT mV diff db */
{ 52, 0x9A, 0, 128, true }, /* 0: 400 0 */
@@ -273,6 +270,20 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = {
{ 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */
};
+static const struct bxt_ddi_buf_trans bxt_ddi_translations_edp[] = {
+ /* Idx NT mV diff db */
+ { 26, 0, 0, 128, false }, /* 0: 200 0 */
+ { 38, 0, 0, 112, false }, /* 1: 200 1.5 */
+ { 48, 0, 0, 96, false }, /* 2: 200 4 */
+ { 54, 0, 0, 69, false }, /* 3: 200 6 */
+ { 32, 0, 0, 128, false }, /* 4: 250 0 */
+ { 48, 0, 0, 104, false }, /* 5: 250 1.5 */
+ { 54, 0, 0, 85, false }, /* 6: 250 4 */
+ { 43, 0, 0, 128, false }, /* 7: 300 0 */
+ { 54, 0, 0, 101, false }, /* 8: 300 1.5 */
+ { 48, 0, 0, 128, false }, /* 9: 300 0 */
+};
+
/* BSpec has 2 recommended values - entries 0 and 8.
* Using the entry with higher vswing.
*/
@@ -298,21 +309,26 @@ static void ddi_get_encoder_port(struct intel_encoder *intel_encoder,
enum port *port)
{
struct drm_encoder *encoder = &intel_encoder->base;
- int type = intel_encoder->type;
- if (type == INTEL_OUTPUT_DP_MST) {
+ switch (intel_encoder->type) {
+ case INTEL_OUTPUT_DP_MST:
*dig_port = enc_to_mst(encoder)->primary;
*port = (*dig_port)->port;
- } else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
- type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
+ break;
+ case INTEL_OUTPUT_DISPLAYPORT:
+ case INTEL_OUTPUT_EDP:
+ case INTEL_OUTPUT_HDMI:
+ case INTEL_OUTPUT_UNKNOWN:
*dig_port = enc_to_dig_port(encoder);
*port = (*dig_port)->port;
- } else if (type == INTEL_OUTPUT_ANALOG) {
+ break;
+ case INTEL_OUTPUT_ANALOG:
*dig_port = NULL;
*port = PORT_E;
- } else {
- DRM_ERROR("Invalid DDI encoder type %d\n", type);
- BUG();
+ break;
+ default:
+ WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type);
+ break;
}
}
@@ -414,7 +430,6 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
bool supports_hdmi)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg;
u32 iboost_bit = 0;
int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry,
size;
@@ -505,11 +520,11 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
BUG();
}
- for (i = 0, reg = DDI_BUF_TRANS(port); i < size; i++) {
- I915_WRITE(reg, ddi_translations[i].trans1 | iboost_bit);
- reg += 4;
- I915_WRITE(reg, ddi_translations[i].trans2);
- reg += 4;
+ for (i = 0; i < size; i++) {
+ I915_WRITE(DDI_BUF_TRANS_LO(port, i),
+ ddi_translations[i].trans1 | iboost_bit);
+ I915_WRITE(DDI_BUF_TRANS_HI(port, i),
+ ddi_translations[i].trans2);
}
if (!supports_hdmi)
@@ -521,10 +536,10 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
hdmi_level = hdmi_default_entry;
/* Entry 9 is for HDMI: */
- I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit);
- reg += 4;
- I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2);
- reg += 4;
+ I915_WRITE(DDI_BUF_TRANS_LO(port, i),
+ ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit);
+ I915_WRITE(DDI_BUF_TRANS_HI(port, i),
+ ddi_translations_hdmi[hdmi_level].trans2);
}
/* Program DDI buffers translations for DP. By default, program ports A-D in DP
@@ -543,8 +558,10 @@ void intel_prepare_ddi(struct drm_device *dev)
enum port port;
bool supports_hdmi;
- ddi_get_encoder_port(intel_encoder, &intel_dig_port, &port);
+ if (intel_encoder->type == INTEL_OUTPUT_DSI)
+ continue;
+ ddi_get_encoder_port(intel_encoder, &intel_dig_port, &port);
if (visited[port])
continue;
@@ -593,7 +610,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
*
* WaFDIAutoLinkSetTimingOverrride:hsw
*/
- I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) |
+ I915_WRITE(FDI_RX_MISC(PIPE_A), FDI_RX_PWRDN_LANE1_VAL(2) |
FDI_RX_PWRDN_LANE0_VAL(2) |
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
@@ -601,13 +618,13 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
FDI_RX_PLL_ENABLE |
FDI_DP_PORT_WIDTH(intel_crtc->config->fdi_lanes);
- I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
- POSTING_READ(_FDI_RXA_CTL);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
+ POSTING_READ(FDI_RX_CTL(PIPE_A));
udelay(220);
/* Switch from Rawclk to PCDclk */
rx_ctl_val |= FDI_PCDCLK;
- I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
/* Configure Port Clock Select */
I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->config->ddi_pll_sel);
@@ -636,21 +653,21 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
udelay(600);
/* Program PCH FDI Receiver TU */
- I915_WRITE(_FDI_RXA_TUSIZE1, TU_SIZE(64));
+ I915_WRITE(FDI_RX_TUSIZE1(PIPE_A), TU_SIZE(64));
/* Enable PCH FDI Receiver with auto-training */
rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO;
- I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
- POSTING_READ(_FDI_RXA_CTL);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
+ POSTING_READ(FDI_RX_CTL(PIPE_A));
/* Wait for FDI receiver lane calibration */
udelay(30);
/* Unset FDI_RX_MISC pwrdn lanes */
- temp = I915_READ(_FDI_RXA_MISC);
+ temp = I915_READ(FDI_RX_MISC(PIPE_A));
temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
- I915_WRITE(_FDI_RXA_MISC, temp);
- POSTING_READ(_FDI_RXA_MISC);
+ I915_WRITE(FDI_RX_MISC(PIPE_A), temp);
+ POSTING_READ(FDI_RX_MISC(PIPE_A));
/* Wait for FDI auto training time */
udelay(5);
@@ -684,15 +701,15 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
intel_wait_ddi_buf_idle(dev_priv, PORT_E);
rx_ctl_val &= ~FDI_RX_ENABLE;
- I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
- POSTING_READ(_FDI_RXA_CTL);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
+ POSTING_READ(FDI_RX_CTL(PIPE_A));
/* Reset FDI_RX_MISC pwrdn lanes */
- temp = I915_READ(_FDI_RXA_MISC);
+ temp = I915_READ(FDI_RX_MISC(PIPE_A));
temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
- I915_WRITE(_FDI_RXA_MISC, temp);
- POSTING_READ(_FDI_RXA_MISC);
+ I915_WRITE(FDI_RX_MISC(PIPE_A), temp);
+ POSTING_READ(FDI_RX_MISC(PIPE_A));
}
DRM_ERROR("FDI link training failed!\n");
@@ -707,7 +724,6 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder)
intel_dp->DP = intel_dig_port->saved_port_bits |
DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0);
intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
-
}
static struct intel_encoder *
@@ -955,8 +971,8 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
uint32_t cfgcr1_val, cfgcr2_val;
uint32_t p0, p1, p2, dco_freq;
- cfgcr1_reg = GET_CFG_CR1_REG(dpll);
- cfgcr2_reg = GET_CFG_CR2_REG(dpll);
+ cfgcr1_reg = DPLL_CFGCR1(dpll);
+ cfgcr2_reg = DPLL_CFGCR2(dpll);
cfgcr1_val = I915_READ(cfgcr1_reg);
cfgcr2_val = I915_READ(cfgcr2_reg);
@@ -1242,9 +1258,10 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */,
static bool
hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state,
- struct intel_encoder *intel_encoder,
- int clock)
+ struct intel_encoder *intel_encoder)
{
+ int clock = crtc_state->port_clock;
+
if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
struct intel_shared_dpll *pll;
uint32_t val;
@@ -1269,6 +1286,18 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
}
crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
+ } else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) {
+ struct drm_atomic_state *state = crtc_state->base.state;
+ struct intel_shared_dpll_config *spll =
+ &intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL];
+
+ if (spll->crtc_mask &&
+ WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll))
+ return false;
+
+ crtc_state->shared_dpll = DPLL_ID_SPLL;
+ spll->hw_state.spll = crtc_state->dpll_hw_state.spll;
+ spll->crtc_mask |= 1 << intel_crtc->pipe;
}
return true;
@@ -1523,11 +1552,11 @@ skip_remaining_dividers:
static bool
skl_ddi_pll_select(struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state,
- struct intel_encoder *intel_encoder,
- int clock)
+ struct intel_encoder *intel_encoder)
{
struct intel_shared_dpll *pll;
uint32_t ctrl1, cfgcr1, cfgcr2;
+ int clock = crtc_state->port_clock;
/*
* See comment in intel_dpll_hw_state to understand why we always use 0
@@ -1615,14 +1644,14 @@ static const struct bxt_clk_div bxt_dp_clk_val[] = {
static bool
bxt_ddi_pll_select(struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state,
- struct intel_encoder *intel_encoder,
- int clock)
+ struct intel_encoder *intel_encoder)
{
struct intel_shared_dpll *pll;
struct bxt_clk_div clk_div = {0};
int vco = 0;
uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
uint32_t lanestagger;
+ int clock = crtc_state->port_clock;
if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
intel_clock_t best_clock;
@@ -1750,17 +1779,16 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
struct drm_device *dev = intel_crtc->base.dev;
struct intel_encoder *intel_encoder =
intel_ddi_get_crtc_new_encoder(crtc_state);
- int clock = crtc_state->port_clock;
if (IS_SKYLAKE(dev))
return skl_ddi_pll_select(intel_crtc, crtc_state,
- intel_encoder, clock);
+ intel_encoder);
else if (IS_BROXTON(dev))
return bxt_ddi_pll_select(intel_crtc, crtc_state,
- intel_encoder, clock);
+ intel_encoder);
else
return hsw_ddi_pll_select(intel_crtc, crtc_state,
- intel_encoder, clock);
+ intel_encoder);
}
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
@@ -1893,7 +1921,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
} else
temp |= TRANS_DDI_MODE_SELECT_DP_SST;
- temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
+ temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
} else if (type == INTEL_OUTPUT_DP_MST) {
struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
@@ -1902,7 +1930,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
} else
temp |= TRANS_DDI_MODE_SELECT_DP_SST;
- temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
+ temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
} else {
WARN(1, "Invalid encoder type %d for pipe %c\n",
intel_encoder->type, pipe_name(pipe));
@@ -2029,7 +2057,8 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
{
struct drm_crtc *crtc = &intel_crtc->base;
- struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
enum port port = intel_ddi_get_encoder_port(intel_encoder);
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
@@ -2114,7 +2143,11 @@ static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level,
u32 n_entries, i;
uint32_t val;
- if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+ if (type == INTEL_OUTPUT_EDP && dev_priv->edp_low_vswing) {
+ n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
+ ddi_translations = bxt_ddi_translations_edp;
+ } else if (type == INTEL_OUTPUT_DISPLAYPORT
+ || type == INTEL_OUTPUT_EDP) {
n_entries = ARRAY_SIZE(bxt_ddi_translations_dp);
ddi_translations = bxt_ddi_translations_dp;
} else if (type == INTEL_OUTPUT_HDMI) {
@@ -2152,9 +2185,13 @@ static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level,
I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val);
val = I915_READ(BXT_PORT_TX_DW3_LN0(port));
- val &= ~UNIQE_TRANGE_EN_METHOD;
+ val &= ~SCALE_DCOMP_METHOD;
if (ddi_translations[level].enable)
- val |= UNIQE_TRANGE_EN_METHOD;
+ val |= SCALE_DCOMP_METHOD;
+
+ if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD))
+ DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set");
+
I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val);
val = I915_READ(BXT_PORT_TX_DW4_LN0(port));
@@ -2289,11 +2326,12 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ intel_dp_set_link_params(intel_dp, crtc->config);
+
intel_ddi_init_dp_buf_reg(intel_encoder);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp);
- intel_dp_complete_link_train(intel_dp);
if (port != PORT_A || INTEL_INFO(dev)->gen >= 9)
intel_dp_stop_link_train(intel_dp);
} else if (type == INTEL_OUTPUT_HDMI) {
@@ -2411,7 +2449,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
}
}
-static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
@@ -2419,9 +2457,17 @@ static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
udelay(20);
}
-static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
+ I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
+ POSTING_READ(SPLL_CTL);
+ udelay(20);
+}
+
+static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
uint32_t val;
val = I915_READ(WRPLL_CTL(pll->id));
@@ -2429,9 +2475,19 @@ static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
POSTING_READ(WRPLL_CTL(pll->id));
}
-static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll,
- struct intel_dpll_hw_state *hw_state)
+static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
+ uint32_t val;
+
+ val = I915_READ(SPLL_CTL);
+ I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+ POSTING_READ(SPLL_CTL);
+}
+
+static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
{
uint32_t val;
@@ -2444,25 +2500,50 @@ static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
return val & WRPLL_PLL_ENABLE;
}
+static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
+{
+ uint32_t val;
+
+ if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+ return false;
+
+ val = I915_READ(SPLL_CTL);
+ hw_state->spll = val;
+
+ return val & SPLL_PLL_ENABLE;
+}
+
+
static const char * const hsw_ddi_pll_names[] = {
"WRPLL 1",
"WRPLL 2",
+ "SPLL"
};
static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
{
int i;
- dev_priv->num_shared_dpll = 2;
+ dev_priv->num_shared_dpll = 3;
- for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+ for (i = 0; i < 2; i++) {
dev_priv->shared_dplls[i].id = i;
dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
- dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable;
- dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable;
+ dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
+ dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
dev_priv->shared_dplls[i].get_hw_state =
- hsw_ddi_pll_get_hw_state;
+ hsw_ddi_wrpll_get_hw_state;
}
+
+ /* SPLL is special, but needs to be initialized anyway.. */
+ dev_priv->shared_dplls[i].id = i;
+ dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
+ dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
+ dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
+ dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;
+
}
static const char * const skl_ddi_pll_names[] = {
@@ -2480,20 +2561,20 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = {
{
/* DPLL 1 */
.ctl = LCPLL2_CTL,
- .cfgcr1 = DPLL1_CFGCR1,
- .cfgcr2 = DPLL1_CFGCR2,
+ .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
+ .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
},
{
/* DPLL 2 */
.ctl = WRPLL_CTL1,
- .cfgcr1 = DPLL2_CFGCR1,
- .cfgcr2 = DPLL2_CFGCR2,
+ .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
+ .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
},
{
/* DPLL 3 */
.ctl = WRPLL_CTL2,
- .cfgcr1 = DPLL3_CFGCR1,
- .cfgcr2 = DPLL3_CFGCR2,
+ .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
+ .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
},
};
@@ -2881,7 +2962,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
* here just read out lanes 0/1 and output a note if lanes 2/3 differ.
*/
hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
- if (I915_READ(BXT_PORT_PCS_DW12_LN23(port) != hw_state->pcsdw12))
+ if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
hw_state->pcsdw12,
I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
@@ -2999,22 +3080,22 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc)
intel_ddi_post_disable(intel_encoder);
- val = I915_READ(_FDI_RXA_CTL);
+ val = I915_READ(FDI_RX_CTL(PIPE_A));
val &= ~FDI_RX_ENABLE;
- I915_WRITE(_FDI_RXA_CTL, val);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), val);
- val = I915_READ(_FDI_RXA_MISC);
+ val = I915_READ(FDI_RX_MISC(PIPE_A));
val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
- I915_WRITE(_FDI_RXA_MISC, val);
+ I915_WRITE(FDI_RX_MISC(PIPE_A), val);
- val = I915_READ(_FDI_RXA_CTL);
+ val = I915_READ(FDI_RX_CTL(PIPE_A));
val &= ~FDI_PCDCLK;
- I915_WRITE(_FDI_RXA_CTL, val);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), val);
- val = I915_READ(_FDI_RXA_CTL);
+ val = I915_READ(FDI_RX_CTL(PIPE_A));
val &= ~FDI_RX_PLL_ENABLE;
- I915_WRITE(_FDI_RXA_CTL, val);
+ I915_WRITE(FDI_RX_CTL(PIPE_A), val);
}
void intel_ddi_get_config(struct intel_encoder *encoder,
@@ -3069,6 +3150,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
case TRANS_DDI_MODE_SELECT_DP_SST:
case TRANS_DDI_MODE_SELECT_DP_MST:
pipe_config->has_dp_encoder = true;
+ pipe_config->lane_count =
+ ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
intel_dp_get_m_n(intel_crtc, pipe_config);
break;
default:
@@ -3215,7 +3298,15 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
goto err;
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
- dev_priv->hotplug.irq_port[port] = intel_dig_port;
+ /*
+ * On BXT A0/A1, sw needs to activate DDIA HPD logic and
+ * interrupts to check the external panel connection.
+ */
+ if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)
+ && port == PORT_B)
+ dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port;
+ else
+ dev_priv->hotplug.irq_port[port] = intel_dig_port;
}
/* In theory we don't need the encoder->type check, but leave it just in
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cf418be7d30a..71860f8680f9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -72,6 +72,10 @@ static const uint32_t skl_primary_formats[] = {
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_YVYU,
+ DRM_FORMAT_UYVY,
+ DRM_FORMAT_VYUY,
};
/* Cursor formats */
@@ -108,6 +112,9 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr
struct intel_crtc_state *crtc_state);
static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
int num_connectors);
+static void skylake_pfit_enable(struct intel_crtc *crtc);
+static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
+static void ironlake_pfit_enable(struct intel_crtc *crtc);
static void intel_modeset_setup_hw_state(struct drm_device *dev);
typedef struct {
@@ -125,6 +132,42 @@ struct intel_limit {
intel_p2_t p2;
};
+/* returns HPLL frequency in kHz */
+static int valleyview_get_vco(struct drm_i915_private *dev_priv)
+{
+ int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
+
+ /* Obtain SKU information */
+ mutex_lock(&dev_priv->sb_lock);
+ hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
+ CCK_FUSE_HPLL_FREQ_MASK;
+ mutex_unlock(&dev_priv->sb_lock);
+
+ return vco_freq[hpll_freq] * 1000;
+}
+
+static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
+ const char *name, u32 reg)
+{
+ u32 val;
+ int divider;
+
+ if (dev_priv->hpll_freq == 0)
+ dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
+
+ mutex_lock(&dev_priv->sb_lock);
+ val = vlv_cck_read(dev_priv, reg);
+ mutex_unlock(&dev_priv->sb_lock);
+
+ divider = val & CCK_FREQUENCY_VALUES;
+
+ WARN((val & CCK_FREQUENCY_STATUS) !=
+ (divider << CCK_FREQUENCY_STATUS_SHIFT),
+ "%s change in progress\n", name);
+
+ return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1);
+}
+
int
intel_pch_rawclk(struct drm_device *dev)
{
@@ -135,6 +178,50 @@ intel_pch_rawclk(struct drm_device *dev)
return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
}
+/* hrawclock is 1/4 the FSB frequency */
+int intel_hrawclk(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t clkcfg;
+
+ /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
+ if (IS_VALLEYVIEW(dev))
+ return 200;
+
+ clkcfg = I915_READ(CLKCFG);
+ switch (clkcfg & CLKCFG_FSB_MASK) {
+ case CLKCFG_FSB_400:
+ return 100;
+ case CLKCFG_FSB_533:
+ return 133;
+ case CLKCFG_FSB_667:
+ return 166;
+ case CLKCFG_FSB_800:
+ return 200;
+ case CLKCFG_FSB_1067:
+ return 266;
+ case CLKCFG_FSB_1333:
+ return 333;
+ /* these two are just a guess; one of them might be right */
+ case CLKCFG_FSB_1600:
+ case CLKCFG_FSB_1600_ALT:
+ return 400;
+ default:
+ return 133;
+ }
+}
+
+static void intel_update_czclk(struct drm_i915_private *dev_priv)
+{
+ if (!IS_VALLEYVIEW(dev_priv))
+ return;
+
+ dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
+ CCK_CZ_CLOCK_CONTROL);
+
+ DRM_DEBUG_DRIVER("CZ clock rate: %d kHz\n", dev_priv->czclk_freq);
+}
+
static inline u32 /* units of 100MHz */
intel_fdi_link_freq(struct drm_device *dev)
{
@@ -1061,54 +1148,6 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
}
}
-/*
- * ibx_digital_port_connected - is the specified port connected?
- * @dev_priv: i915 private structure
- * @port: the port to test
- *
- * Returns true if @port is connected, false otherwise.
- */
-bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
- struct intel_digital_port *port)
-{
- u32 bit;
-
- if (HAS_PCH_IBX(dev_priv->dev)) {
- switch (port->port) {
- case PORT_B:
- bit = SDE_PORTB_HOTPLUG;
- break;
- case PORT_C:
- bit = SDE_PORTC_HOTPLUG;
- break;
- case PORT_D:
- bit = SDE_PORTD_HOTPLUG;
- break;
- default:
- return true;
- }
- } else {
- switch (port->port) {
- case PORT_B:
- bit = SDE_PORTB_HOTPLUG_CPT;
- break;
- case PORT_C:
- bit = SDE_PORTC_HOTPLUG_CPT;
- break;
- case PORT_D:
- bit = SDE_PORTD_HOTPLUG_CPT;
- break;
- case PORT_E:
- bit = SDE_PORTE_HOTPLUG_SPT;
- break;
- default:
- return true;
- }
- }
-
- return I915_READ(SDEISR) & bit;
-}
-
static const char *state_string(bool enabled)
{
return enabled ? "on" : "off";
@@ -1118,12 +1157,10 @@ static const char *state_string(bool enabled)
void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = DPLL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(DPLL(pipe));
cur_state = !!(val & DPLL_VCO_ENABLE);
I915_STATE_WARN(cur_state != state,
"PLL state assertion failure (expected %s, current %s)\n",
@@ -1180,20 +1217,16 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
- u32 val;
bool cur_state;
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
pipe);
if (HAS_DDI(dev_priv->dev)) {
/* DDI does not have a specific FDI_TX register */
- reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
- val = I915_READ(reg);
+ u32 val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
} else {
- reg = FDI_TX_CTL(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(FDI_TX_CTL(pipe));
cur_state = !!(val & FDI_TX_ENABLE);
}
I915_STATE_WARN(cur_state != state,
@@ -1206,12 +1239,10 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
static void assert_fdi_rx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = FDI_RX_CTL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(FDI_RX_CTL(pipe));
cur_state = !!(val & FDI_RX_ENABLE);
I915_STATE_WARN(cur_state != state,
"FDI RX state assertion failure (expected %s, current %s)\n",
@@ -1223,7 +1254,6 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- int reg;
u32 val;
/* ILK FDI PLL is always enabled */
@@ -1234,20 +1264,17 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
if (HAS_DDI(dev_priv->dev))
return;
- reg = FDI_TX_CTL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(FDI_TX_CTL(pipe));
I915_STATE_WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
}
void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = FDI_RX_CTL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(FDI_RX_CTL(pipe));
cur_state = !!(val & FDI_RX_PLL_ENABLE);
I915_STATE_WARN(cur_state != state,
"FDI RX PLL assertion failure (expected %s, current %s)\n",
@@ -1303,7 +1330,7 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
bool cur_state;
if (IS_845G(dev) || IS_I865G(dev))
- cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE;
+ cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
else
cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
@@ -1317,8 +1344,6 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
void assert_pipe(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
- u32 val;
bool cur_state;
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
pipe);
@@ -1332,8 +1357,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
cur_state = false;
} else {
- reg = PIPECONF(cpu_transcoder);
- val = I915_READ(reg);
+ u32 val = I915_READ(PIPECONF(cpu_transcoder));
cur_state = !!(val & PIPECONF_ENABLE);
}
@@ -1345,12 +1369,10 @@ void assert_pipe(struct drm_i915_private *dev_priv,
static void assert_plane(struct drm_i915_private *dev_priv,
enum plane plane, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = DSPCNTR(plane);
- val = I915_READ(reg);
+ val = I915_READ(DSPCNTR(plane));
cur_state = !!(val & DISPLAY_PLANE_ENABLE);
I915_STATE_WARN(cur_state != state,
"plane %c assertion failure (expected %s, current %s)\n",
@@ -1364,14 +1386,11 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- int reg, i;
- u32 val;
- int cur_pipe;
+ int i;
/* Primary planes are fixed to pipes on gen4+ */
if (INTEL_INFO(dev)->gen >= 4) {
- reg = DSPCNTR(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(DSPCNTR(pipe));
I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
"plane %c assertion failure, should be disabled but not\n",
plane_name(pipe));
@@ -1380,9 +1399,8 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
/* Need to check both planes against the pipe */
for_each_pipe(dev_priv, i) {
- reg = DSPCNTR(i);
- val = I915_READ(reg);
- cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
+ u32 val = I915_READ(DSPCNTR(i));
+ enum pipe cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
DISPPLANE_SEL_PIPE_SHIFT;
I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
"plane %c assertion failure, should be off on pipe %c but is still active\n",
@@ -1394,33 +1412,29 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- int reg, sprite;
- u32 val;
+ int sprite;
if (INTEL_INFO(dev)->gen >= 9) {
for_each_sprite(dev_priv, pipe, sprite) {
- val = I915_READ(PLANE_CTL(pipe, sprite));
+ u32 val = I915_READ(PLANE_CTL(pipe, sprite));
I915_STATE_WARN(val & PLANE_CTL_ENABLE,
"plane %d assertion failure, should be off on pipe %c but is still active\n",
sprite, pipe_name(pipe));
}
} else if (IS_VALLEYVIEW(dev)) {
for_each_sprite(dev_priv, pipe, sprite) {
- reg = SPCNTR(pipe, sprite);
- val = I915_READ(reg);
+ u32 val = I915_READ(SPCNTR(pipe, sprite));
I915_STATE_WARN(val & SP_ENABLE,
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
sprite_name(pipe, sprite), pipe_name(pipe));
}
} else if (INTEL_INFO(dev)->gen >= 7) {
- reg = SPRCTL(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(SPRCTL(pipe));
I915_STATE_WARN(val & SPRITE_ENABLE,
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
plane_name(pipe), pipe_name(pipe));
} else if (INTEL_INFO(dev)->gen >= 5) {
- reg = DVSCNTR(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(DVSCNTR(pipe));
I915_STATE_WARN(val & DVS_ENABLE,
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
plane_name(pipe), pipe_name(pipe));
@@ -1449,12 +1463,10 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- int reg;
u32 val;
bool enabled;
- reg = PCH_TRANSCONF(pipe);
- val = I915_READ(reg);
+ val = I915_READ(PCH_TRANSCONF(pipe));
enabled = !!(val & TRANS_ENABLE);
I915_STATE_WARN(enabled,
"transcoder assertion failed, should be off on pipe %c but is still active\n",
@@ -1561,21 +1573,18 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- int reg;
u32 val;
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B);
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C);
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D);
- reg = PCH_ADPA;
- val = I915_READ(reg);
+ val = I915_READ(PCH_ADPA);
I915_STATE_WARN(adpa_pipe_enabled(dev_priv, pipe, val),
"PCH VGA enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
- reg = PCH_LVDS;
- val = I915_READ(reg);
+ val = I915_READ(PCH_LVDS);
I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val),
"PCH LVDS enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
@@ -1585,26 +1594,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
}
-static void intel_init_dpio(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- if (!IS_VALLEYVIEW(dev))
- return;
-
- /*
- * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
- * CHV x1 PHY (DP/HDMI D)
- * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
- */
- if (IS_CHERRYVIEW(dev)) {
- DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
- DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
- } else {
- DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
- }
-}
-
static void vlv_enable_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config)
{
@@ -1724,6 +1713,15 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
}
+ /*
+ * Apparently we need to have VGA mode enabled prior to changing
+ * the P1/P2 dividers. Otherwise the DPLL will keep using the old
+ * dividers, even though the register value does change.
+ */
+ I915_WRITE(reg, 0);
+
+ I915_WRITE(reg, dpll);
+
/* Wait for the clocks to stabilize. */
POSTING_READ(reg);
udelay(150);
@@ -1831,17 +1829,6 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
val &= ~DPIO_DCLKP_EN;
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
- /* disable left/right clock distribution */
- if (pipe != PIPE_B) {
- val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
- val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
- vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
- } else {
- val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
- val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
- vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
- }
-
mutex_unlock(&dev_priv->sb_lock);
}
@@ -2042,9 +2029,9 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
/* Workaround: set timing override bit. */
- val = I915_READ(_TRANSA_CHICKEN2);
+ val = I915_READ(TRANS_CHICKEN2(PIPE_A));
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
- I915_WRITE(_TRANSA_CHICKEN2, val);
+ I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
val = TRANS_ENABLE;
pipeconf_val = I915_READ(PIPECONF(cpu_transcoder));
@@ -2102,9 +2089,9 @@ static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
DRM_ERROR("Failed to disable PCH transcoder\n");
/* Workaround: clear timing override bit. */
- val = I915_READ(_TRANSA_CHICKEN2);
+ val = I915_READ(TRANS_CHICKEN2(PIPE_A));
val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
- I915_WRITE(_TRANSA_CHICKEN2, val);
+ I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
}
/**
@@ -2229,7 +2216,7 @@ static bool need_vtd_wa(struct drm_device *dev)
unsigned int
intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
- uint64_t fb_format_modifier)
+ uint64_t fb_format_modifier, unsigned int plane)
{
unsigned int tile_height;
uint32_t pixel_bytes;
@@ -2245,7 +2232,7 @@ intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
tile_height = 32;
break;
case I915_FORMAT_MOD_Yf_TILED:
- pixel_bytes = drm_format_plane_cpp(pixel_format, 0);
+ pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
switch (pixel_bytes) {
default:
case 1:
@@ -2279,7 +2266,7 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
uint32_t pixel_format, uint64_t fb_format_modifier)
{
return ALIGN(height, intel_tile_height(dev, pixel_format,
- fb_format_modifier));
+ fb_format_modifier, 0));
}
static int
@@ -2302,15 +2289,27 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
info->height = fb->height;
info->pixel_format = fb->pixel_format;
info->pitch = fb->pitches[0];
+ info->uv_offset = fb->offsets[1];
info->fb_modifier = fb->modifier[0];
tile_height = intel_tile_height(fb->dev, fb->pixel_format,
- fb->modifier[0]);
+ fb->modifier[0], 0);
tile_pitch = PAGE_SIZE / tile_height;
info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
info->size = info->width_pages * info->height_pages * PAGE_SIZE;
+ if (info->pixel_format == DRM_FORMAT_NV12) {
+ tile_height = intel_tile_height(fb->dev, fb->pixel_format,
+ fb->modifier[0], 1);
+ tile_pitch = PAGE_SIZE / tile_height;
+ info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
+ info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
+ tile_height);
+ info->size_uv = info->width_pages_uv * info->height_pages_uv *
+ PAGE_SIZE;
+ }
+
return 0;
}
@@ -2399,22 +2398,24 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
* framebuffer compression. For simplicity, we always install
* a fence as the cost is not that onerous.
*/
- ret = i915_gem_object_get_fence(obj);
- if (ret == -EDEADLK) {
- /*
- * -EDEADLK means there are no free fences
- * no pending flips.
- *
- * This is propagated to atomic, but it uses
- * -EDEADLK to force a locking recovery, so
- * change the returned error to -EBUSY.
- */
- ret = -EBUSY;
- goto err_unpin;
- } else if (ret)
- goto err_unpin;
+ if (view.type == I915_GGTT_VIEW_NORMAL) {
+ ret = i915_gem_object_get_fence(obj);
+ if (ret == -EDEADLK) {
+ /*
+ * -EDEADLK means there are no free fences
+ * no pending flips.
+ *
+ * This is propagated to atomic, but it uses
+ * -EDEADLK to force a locking recovery, so
+ * change the returned error to -EBUSY.
+ */
+ ret = -EBUSY;
+ goto err_unpin;
+ } else if (ret)
+ goto err_unpin;
- i915_gem_object_pin_fence(obj);
+ i915_gem_object_pin_fence(obj);
+ }
dev_priv->mm.interruptible = true;
intel_runtime_pm_put(dev_priv);
@@ -2440,7 +2441,9 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
WARN_ONCE(ret, "Couldn't get view from plane state!");
- i915_gem_object_unpin_fence(obj);
+ if (view.type == I915_GGTT_VIEW_NORMAL)
+ i915_gem_object_unpin_fence(obj);
+
i915_gem_object_unpin_from_display_plane(obj, &view);
}
@@ -2525,6 +2528,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config)
{
struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = NULL;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct drm_framebuffer *fb = &plane_config->fb->base;
@@ -2537,6 +2541,12 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
if (plane_config->size == 0)
return false;
+ /* If the FB is too big, just don't use it since fbdev is not very
+ * important and we should probably use that space with FBC or other
+ * features. */
+ if (size_aligned * 2 > dev_priv->gtt.stolen_usable_size)
+ return false;
+
obj = i915_gem_object_create_stolen_for_preallocated(dev,
base_aligned,
base_aligned,
@@ -2636,11 +2646,13 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
return;
valid_fb:
- plane_state->src_x = plane_state->src_y = 0;
+ plane_state->src_x = 0;
+ plane_state->src_y = 0;
plane_state->src_w = fb->width << 16;
plane_state->src_h = fb->height << 16;
- plane_state->crtc_x = plane_state->src_y = 0;
+ plane_state->crtc_x = 0;
+ plane_state->crtc_y = 0;
plane_state->crtc_w = fb->width;
plane_state->crtc_h = fb->height;
@@ -2769,6 +2781,9 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
(intel_crtc->config->pipe_src_w - 1) * pixel_size;
}
+ intel_crtc->adjusted_x = x;
+ intel_crtc->adjusted_y = y;
+
I915_WRITE(reg, dspcntr);
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
@@ -2869,6 +2884,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
}
}
+ intel_crtc->adjusted_x = x;
+ intel_crtc->adjusted_y = y;
+
I915_WRITE(reg, dspcntr);
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
@@ -2918,14 +2936,29 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
}
unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj)
+ struct drm_i915_gem_object *obj,
+ unsigned int plane)
{
const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
+ struct i915_vma *vma;
+ unsigned char *offset;
if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
view = &i915_ggtt_view_rotated;
- return i915_gem_obj_ggtt_offset_view(obj, view);
+ vma = i915_gem_obj_to_ggtt_view(obj, view);
+ if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
+ view->type))
+ return -1;
+
+ offset = (unsigned char *)vma->node.start;
+
+ if (plane == 1) {
+ offset += vma->ggtt_view.rotation_info.uv_start_page *
+ PAGE_SIZE;
+ }
+
+ return (unsigned long)offset;
}
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -2936,8 +2969,6 @@ static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, id), 0);
I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, id), 0);
I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, id), 0);
- DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n",
- intel_crtc->base.base.id, intel_crtc->pipe, id);
}
/*
@@ -3083,34 +3114,26 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
obj = intel_fb_obj(fb);
stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
fb->pixel_format);
- surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj);
+ surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
- /*
- * FIXME: intel_plane_state->src, dst aren't set when transitional
- * update_plane helpers are called from legacy paths.
- * Once full atomic crtc is available, below check can be avoided.
- */
- if (drm_rect_width(&plane_state->src)) {
- scaler_id = plane_state->scaler_id;
- src_x = plane_state->src.x1 >> 16;
- src_y = plane_state->src.y1 >> 16;
- src_w = drm_rect_width(&plane_state->src) >> 16;
- src_h = drm_rect_height(&plane_state->src) >> 16;
- dst_x = plane_state->dst.x1;
- dst_y = plane_state->dst.y1;
- dst_w = drm_rect_width(&plane_state->dst);
- dst_h = drm_rect_height(&plane_state->dst);
-
- WARN_ON(x != src_x || y != src_y);
- } else {
- src_w = intel_crtc->config->pipe_src_w;
- src_h = intel_crtc->config->pipe_src_h;
- }
+ WARN_ON(drm_rect_width(&plane_state->src) == 0);
+
+ scaler_id = plane_state->scaler_id;
+ src_x = plane_state->src.x1 >> 16;
+ src_y = plane_state->src.y1 >> 16;
+ src_w = drm_rect_width(&plane_state->src) >> 16;
+ src_h = drm_rect_height(&plane_state->src) >> 16;
+ dst_x = plane_state->dst.x1;
+ dst_y = plane_state->dst.y1;
+ dst_w = drm_rect_width(&plane_state->dst);
+ dst_h = drm_rect_height(&plane_state->dst);
+
+ WARN_ON(x != src_x || y != src_y);
if (intel_rotation_90_or_270(rotation)) {
/* stride = Surface height in tiles */
tile_height = intel_tile_height(dev, fb->pixel_format,
- fb->modifier[0]);
+ fb->modifier[0], 0);
stride = DIV_ROUND_UP(fb->height, tile_height);
x_offset = stride * tile_height - y - src_h;
y_offset = x;
@@ -3123,6 +3146,9 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
}
plane_offset = y_offset << 16 | x_offset;
+ intel_crtc->adjusted_x = x_offset;
+ intel_crtc->adjusted_y = y_offset;
+
I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
@@ -3179,24 +3205,20 @@ static void intel_complete_page_flips(struct drm_device *dev)
static void intel_update_primary_planes(struct drm_device *dev)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
for_each_crtc(dev, crtc) {
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_plane *plane = to_intel_plane(crtc->primary);
+ struct intel_plane_state *plane_state;
- drm_modeset_lock(&crtc->mutex, NULL);
- /*
- * FIXME: Once we have proper support for primary planes (and
- * disabling them without disabling the entire crtc) allow again
- * a NULL crtc->primary->fb.
- */
- if (intel_crtc->active && crtc->primary->fb)
- dev_priv->display.update_primary_plane(crtc,
- crtc->primary->fb,
- crtc->x,
- crtc->y);
- drm_modeset_unlock(&crtc->mutex);
+ drm_modeset_lock_crtc(crtc, &plane->base);
+
+ plane_state = to_intel_plane_state(plane->base.state);
+
+ if (plane_state->base.fb)
+ plane->commit_plane(&plane->base, plane_state);
+
+ drm_modeset_unlock_crtc(crtc);
}
}
@@ -3240,6 +3262,9 @@ void intel_finish_reset(struct drm_device *dev)
* so update the base address of all primary
* planes to the the last fb to make sure we're
* showing the correct fb after a reset.
+ *
+ * FIXME: Atomic will make this obsolete since we won't schedule
+ * CS-based flips (which might get lost in gpu resets) any more.
*/
intel_update_primary_planes(dev);
return;
@@ -3310,14 +3335,23 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
return pending;
}
-static void intel_update_pipe_size(struct intel_crtc *crtc)
+static void intel_update_pipe_config(struct intel_crtc *crtc,
+ struct intel_crtc_state *old_crtc_state)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- const struct drm_display_mode *adjusted_mode;
+ struct intel_crtc_state *pipe_config =
+ to_intel_crtc_state(crtc->base.state);
- if (!i915.fastboot)
- return;
+ /* drm_atomic_helper_update_legacy_modeset_state might not be called. */
+ crtc->base.mode = crtc->base.state->mode;
+
+ DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n",
+ old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h,
+ pipe_config->pipe_src_w, pipe_config->pipe_src_h);
+
+ if (HAS_DDI(dev))
+ intel_set_pipe_csc(&crtc->base);
/*
* Update pipe size and adjust fitter if needed: the reason for this is
@@ -3326,27 +3360,24 @@ static void intel_update_pipe_size(struct intel_crtc *crtc)
* fastboot case, we'll flip, but if we don't update the pipesrc and
* pfit state, we'll end up with a big fb scanned out into the wrong
* sized surface.
- *
- * To fix this properly, we need to hoist the checks up into
- * compute_mode_changes (or above), check the actual pfit state and
- * whether the platform allows pfit disable with pipe active, and only
- * then update the pipesrc and pfit state, even on the flip path.
*/
- adjusted_mode = &crtc->config->base.adjusted_mode;
-
I915_WRITE(PIPESRC(crtc->pipe),
- ((adjusted_mode->crtc_hdisplay - 1) << 16) |
- (adjusted_mode->crtc_vdisplay - 1));
- if (!crtc->config->pch_pfit.enabled &&
- (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
- intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
- I915_WRITE(PF_CTL(crtc->pipe), 0);
- I915_WRITE(PF_WIN_POS(crtc->pipe), 0);
- I915_WRITE(PF_WIN_SZ(crtc->pipe), 0);
+ ((pipe_config->pipe_src_w - 1) << 16) |
+ (pipe_config->pipe_src_h - 1));
+
+ /* on skylake this is done by detaching scalers */
+ if (INTEL_INFO(dev)->gen >= 9) {
+ skl_detach_scalers(crtc);
+
+ if (pipe_config->pch_pfit.enabled)
+ skylake_pfit_enable(crtc);
+ } else if (HAS_PCH_SPLIT(dev)) {
+ if (pipe_config->pch_pfit.enabled)
+ ironlake_pfit_enable(crtc);
+ else if (old_crtc_state->pch_pfit.enabled)
+ ironlake_pfit_disable(crtc, true);
}
- crtc->config->pipe_src_w = adjusted_mode->crtc_hdisplay;
- crtc->config->pipe_src_h = adjusted_mode->crtc_vdisplay;
}
static void intel_fdi_normal_train(struct drm_crtc *crtc)
@@ -4208,6 +4239,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
struct intel_shared_dpll *pll;
struct intel_shared_dpll_config *shared_dpll;
enum intel_dpll_id i;
+ int max = dev_priv->num_shared_dpll;
shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
@@ -4242,9 +4274,11 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
WARN_ON(shared_dpll[i].crtc_mask);
goto found;
- }
+ } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
+ /* Do not consider SPLL */
+ max = 2;
- for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+ for (i = 0; i < max; i++) {
pll = &dev_priv->shared_dplls[i];
/* Only want to check enabled timings first */
@@ -4392,8 +4426,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
int skl_update_scaler_crtc(struct intel_crtc_state *state)
{
struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
- struct drm_display_mode *adjusted_mode =
- &state->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
DRM_DEBUG_KMS("Updating scaler for [CRTC:%i] scaler_user index %u.%u\n",
intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);
@@ -4401,7 +4434,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
&state->scaler_state.scaler_id, DRM_ROTATE_0,
state->pipe_src_w, state->pipe_src_h,
- adjusted_mode->hdisplay, adjusted_mode->vdisplay);
+ adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
}
/**
@@ -4594,7 +4627,6 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
- int palreg = PALETTE(pipe);
int i;
bool reenable_ips = false;
@@ -4609,10 +4641,6 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
assert_pll_enabled(dev_priv, pipe);
}
- /* use legacy palette for Ironlake */
- if (!HAS_GMCH_DISPLAY(dev))
- palreg = LGC_PALETTE(pipe);
-
/* Workaround : Do not read or write the pipe palette/gamma data while
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
*/
@@ -4624,7 +4652,14 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
}
for (i = 0; i < 256; i++) {
- I915_WRITE(palreg + 4 * i,
+ u32 palreg;
+
+ if (HAS_GMCH_DISPLAY(dev))
+ palreg = PALETTE(pipe, i);
+ else
+ palreg = LGC_PALETTE(pipe, i);
+
+ I915_WRITE(palreg,
(intel_crtc->lut_r[i] << 16) |
(intel_crtc->lut_g[i] << 8) |
intel_crtc->lut_b[i]);
@@ -4922,6 +4957,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe, hsw_workaround_pipe;
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc->state);
+ bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
if (WARN_ON(intel_crtc->active))
return;
@@ -4951,9 +4987,12 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
- for_each_encoder_on_crtc(dev, crtc, encoder)
+ for_each_encoder_on_crtc(dev, crtc, encoder) {
+ if (encoder->pre_pll_enable)
+ encoder->pre_pll_enable(encoder);
if (encoder->pre_enable)
encoder->pre_enable(encoder);
+ }
if (intel_crtc->config->has_pch_encoder) {
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
@@ -4961,14 +5000,13 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
dev_priv->display.fdi_link_train(crtc);
}
- intel_ddi_enable_pipe_clock(intel_crtc);
+ if (!is_dsi)
+ intel_ddi_enable_pipe_clock(intel_crtc);
- if (INTEL_INFO(dev)->gen == 9)
+ if (INTEL_INFO(dev)->gen >= 9)
skylake_pfit_enable(intel_crtc);
- else if (INTEL_INFO(dev)->gen < 9)
- ironlake_pfit_enable(intel_crtc);
else
- MISSING_CASE(INTEL_INFO(dev)->gen);
+ ironlake_pfit_enable(intel_crtc);
/*
* On ILK+ LUT must be loaded before the pipe is running but with
@@ -4977,7 +5015,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc_load_lut(crtc);
intel_ddi_set_pipe_settings(crtc);
- intel_ddi_enable_transcoder_func(crtc);
+ if (!is_dsi)
+ intel_ddi_enable_transcoder_func(crtc);
intel_update_watermarks(crtc);
intel_enable_pipe(intel_crtc);
@@ -4985,7 +5024,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config->has_pch_encoder)
lpt_pch_enable(crtc);
- if (intel_crtc->config->dp_encoder_is_mst)
+ if (intel_crtc->config->dp_encoder_is_mst && !is_dsi)
intel_ddi_set_vc_payload_alloc(crtc, true);
assert_vblank_disabled(crtc);
@@ -5005,7 +5044,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
}
}
-static void ironlake_pfit_disable(struct intel_crtc *crtc)
+static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5013,7 +5052,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc)
/* To avoid upsetting the power well on haswell only disable the pfit if
* it's in use. The hw state code will make sure we get this right. */
- if (crtc->config->pch_pfit.enabled) {
+ if (force || crtc->config->pch_pfit.enabled) {
I915_WRITE(PF_CTL(pipe), 0);
I915_WRITE(PF_WIN_POS(pipe), 0);
I915_WRITE(PF_WIN_SZ(pipe), 0);
@@ -5040,7 +5079,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
intel_disable_pipe(intel_crtc);
- ironlake_pfit_disable(intel_crtc);
+ ironlake_pfit_disable(intel_crtc, false);
if (intel_crtc->config->has_pch_encoder)
ironlake_fdi_disable(crtc);
@@ -5069,9 +5108,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_fdi_pll_disable(intel_crtc);
}
-
- intel_crtc->active = false;
- intel_update_watermarks(crtc);
}
static void haswell_crtc_disable(struct drm_crtc *crtc)
@@ -5081,6 +5117,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder;
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+ bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
for_each_encoder_on_crtc(dev, crtc, encoder) {
intel_opregion_notify_encoder(encoder, false);
@@ -5098,16 +5135,16 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
if (intel_crtc->config->dp_encoder_is_mst)
intel_ddi_set_vc_payload_alloc(crtc, false);
- intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
+ if (!is_dsi)
+ intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
- if (INTEL_INFO(dev)->gen == 9)
+ if (INTEL_INFO(dev)->gen >= 9)
skylake_scaler_disable(intel_crtc);
- else if (INTEL_INFO(dev)->gen < 9)
- ironlake_pfit_disable(intel_crtc);
else
- MISSING_CASE(INTEL_INFO(dev)->gen);
+ ironlake_pfit_disable(intel_crtc, false);
- intel_ddi_disable_pipe_clock(intel_crtc);
+ if (!is_dsi)
+ intel_ddi_disable_pipe_clock(intel_crtc);
if (intel_crtc->config->has_pch_encoder) {
lpt_disable_pch_transcoder(dev_priv);
@@ -5117,9 +5154,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->post_disable)
encoder->post_disable(encoder);
-
- intel_crtc->active = false;
- intel_update_watermarks(crtc);
}
static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -5277,6 +5311,21 @@ static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
modeset_put_power_domains(dev_priv, put_domains[i]);
}
+static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
+{
+ int max_cdclk_freq = dev_priv->max_cdclk_freq;
+
+ if (INTEL_INFO(dev_priv)->gen >= 9 ||
+ IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+ return max_cdclk_freq;
+ else if (IS_CHERRYVIEW(dev_priv))
+ return max_cdclk_freq*95/100;
+ else if (INTEL_INFO(dev_priv)->gen < 4)
+ return 2*max_cdclk_freq*90/100;
+ else
+ return max_cdclk_freq*90/100;
+}
+
static void intel_update_max_cdclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5316,8 +5365,13 @@ static void intel_update_max_cdclk(struct drm_device *dev)
dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
}
+ dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
+
DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
dev_priv->max_cdclk_freq);
+
+ DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
+ dev_priv->max_dotclk_freq);
}
static void intel_update_cdclk(struct drm_device *dev)
@@ -5693,10 +5747,16 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
DRM_ERROR("DBuf power disable timeout\n");
- /* disable DPLL0 */
- I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
- if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
- DRM_ERROR("Couldn't disable DPLL0\n");
+ /*
+ * DMC assumes ownership of LCPLL and will get confused if we touch it.
+ */
+ if (dev_priv->csr.dmc_payload) {
+ /* disable DPLL0 */
+ I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) &
+ ~LCPLL_PLL_ENABLE);
+ if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
+ DRM_ERROR("Couldn't disable DPLL0\n");
+ }
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
}
@@ -5733,20 +5793,6 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
DRM_ERROR("DBuf power enable timeout\n");
}
-/* returns HPLL frequency in kHz */
-static int valleyview_get_vco(struct drm_i915_private *dev_priv)
-{
- int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
-
- /* Obtain SKU information */
- mutex_lock(&dev_priv->sb_lock);
- hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
- CCK_FUSE_HPLL_FREQ_MASK;
- mutex_unlock(&dev_priv->sb_lock);
-
- return vco_freq[hpll_freq] * 1000;
-}
-
/* Adjust CDclk dividers to allow high res or save power if possible */
static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
{
@@ -5784,12 +5830,12 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
/* adjust cdclk divider */
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
- val &= ~DISPLAY_FREQUENCY_VALUES;
+ val &= ~CCK_FREQUENCY_VALUES;
val |= divider;
vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
- DISPLAY_FREQUENCY_STATUS) == (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
+ CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
50))
DRM_ERROR("timed out waiting for CDclk change\n");
}
@@ -5967,7 +6013,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
else
default_credits = PFI_CREDIT(8);
- if (DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 1000) >= dev_priv->rps.cz_freq) {
+ if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
/* CHV suggested value is 31 or 63 */
if (IS_CHERRYVIEW(dev_priv))
credits = PFI_CREDIT_63;
@@ -6035,13 +6081,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
- if (!is_dsi) {
- if (IS_CHERRYVIEW(dev))
- chv_prepare_pll(intel_crtc, intel_crtc->config);
- else
- vlv_prepare_pll(intel_crtc, intel_crtc->config);
- }
-
if (intel_crtc->config->has_dp_encoder)
intel_dp_set_m_n(intel_crtc, M1_N1);
@@ -6065,10 +6104,13 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
encoder->pre_pll_enable(encoder);
if (!is_dsi) {
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev)) {
+ chv_prepare_pll(intel_crtc, intel_crtc->config);
chv_enable_pll(intel_crtc, intel_crtc->config);
- else
+ } else {
+ vlv_prepare_pll(intel_crtc, intel_crtc->config);
vlv_enable_pll(intel_crtc, intel_crtc->config);
+ }
}
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -6196,11 +6238,12 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
i9xx_disable_pll(intel_crtc);
}
+ for_each_encoder_on_crtc(dev, crtc, encoder)
+ if (encoder->post_pll_disable)
+ encoder->post_pll_disable(encoder);
+
if (!IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-
- intel_crtc->active = false;
- intel_update_watermarks(crtc);
}
static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
@@ -6220,6 +6263,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
dev_priv->display.crtc_disable(crtc);
+ intel_crtc->active = false;
+ intel_update_watermarks(crtc);
intel_disable_shared_dpll(intel_crtc);
domains = intel_crtc->enabled_power_domains;
@@ -6456,7 +6501,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
struct intel_crtc_state *pipe_config)
{
struct drm_device *dev = intel_crtc->base.dev;
- struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int lane, link_bw, fdi_dotclock, ret;
bool needs_recompute = false;
@@ -6535,7 +6580,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
/* FIXME should check pixel clock limits on all platforms */
if (INTEL_INFO(dev)->gen < 4) {
@@ -6572,7 +6617,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
*/
if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
- adjusted_mode->hsync_start == adjusted_mode->hdisplay)
+ adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
return -EINVAL;
if (HAS_IPS(dev))
@@ -6699,24 +6744,8 @@ static int haswell_get_display_clock_speed(struct drm_device *dev)
static int valleyview_get_display_clock_speed(struct drm_device *dev)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 val;
- int divider;
-
- if (dev_priv->hpll_freq == 0)
- dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
-
- mutex_lock(&dev_priv->sb_lock);
- val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
- mutex_unlock(&dev_priv->sb_lock);
-
- divider = val & DISPLAY_FREQUENCY_VALUES;
-
- WARN((val & DISPLAY_FREQUENCY_STATUS) !=
- (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
- "cdclk change in progress\n");
-
- return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1);
+ return vlv_get_cck_clock_hpll(to_i915(dev), "cdclk",
+ CCK_DISPLAY_CLOCK_CONTROL);
}
static int ilk_get_display_clock_speed(struct drm_device *dev)
@@ -7377,8 +7406,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
1 << DPIO_CHV_N_DIV_SHIFT);
/* M2 fraction division */
- if (bestm2_frac)
- vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
+ vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
/* M2 fraction division enable */
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
@@ -7604,8 +7632,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe = intel_crtc->pipe;
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
- struct drm_display_mode *adjusted_mode =
- &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
uint32_t crtc_vtotal, crtc_vblank_end;
int vsyncshift = 0;
@@ -8119,6 +8146,14 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
else
i9xx_crtc_clock_get(crtc, pipe_config);
+ /*
+ * Normally the dotclock is filled in by the encoder .get_config()
+ * but in case the pipe is enabled w/o any ports we need a sane
+ * default.
+ */
+ pipe_config->base.adjusted_mode.crtc_clock =
+ pipe_config->port_clock / pipe_config->pixel_multiplier;
+
return true;
}
@@ -8380,8 +8415,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread,
if (WARN(with_fdi && !with_spread, "FDI requires downspread\n"))
with_spread = true;
- if (WARN(dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE &&
- with_fdi, "LP PCH doesn't have FDI\n"))
+ if (WARN(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n"))
with_fdi = false;
mutex_lock(&dev_priv->sb_lock);
@@ -8404,8 +8438,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread,
}
}
- reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ?
- SBI_GEN0 : SBI_DBUFF0;
+ reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
@@ -8421,8 +8454,7 @@ static void lpt_disable_clkout_dp(struct drm_device *dev)
mutex_lock(&dev_priv->sb_lock);
- reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ?
- SBI_GEN0 : SBI_DBUFF0;
+ reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
@@ -9434,7 +9466,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
DRM_DEBUG_KMS("Enabling package C8+\n");
- if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
+ if (HAS_PCH_LPT_LP(dev)) {
val = I915_READ(SOUTH_DSPCLK_GATE_D);
val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -9454,7 +9486,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
hsw_restore_lcpll(dev_priv);
lpt_init_pch_refclk(dev);
- if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
+ if (HAS_PCH_LPT_LP(dev)) {
val = I915_READ(SOUTH_DSPCLK_GATE_D);
val |= PCH_LP_PARTITION_LEVEL_DISABLE;
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -9696,6 +9728,8 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
case PORT_CLK_SEL_WRPLL2:
pipe_config->shared_dpll = DPLL_ID_WRPLL2;
break;
+ case PORT_CLK_SEL_SPLL:
+ pipe_config->shared_dpll = DPLL_ID_SPLL;
}
}
@@ -9804,12 +9838,10 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
}
if (intel_display_power_is_enabled(dev_priv, pfit_domain)) {
- if (INTEL_INFO(dev)->gen == 9)
+ if (INTEL_INFO(dev)->gen >= 9)
skylake_get_pfit_config(crtc, pipe_config);
- else if (INTEL_INFO(dev)->gen < 9)
- ironlake_get_pfit_config(crtc, pipe_config);
else
- MISSING_CASE(INTEL_INFO(dev)->gen);
+ ironlake_get_pfit_config(crtc, pipe_config);
}
if (IS_HASWELL(dev))
@@ -9866,13 +9898,13 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
/* On these chipsets we can only modify the base/size/stride
* whilst the cursor is disabled.
*/
- I915_WRITE(_CURACNTR, 0);
- POSTING_READ(_CURACNTR);
+ I915_WRITE(CURCNTR(PIPE_A), 0);
+ POSTING_READ(CURCNTR(PIPE_A));
intel_crtc->cursor_cntl = 0;
}
if (intel_crtc->cursor_base != base) {
- I915_WRITE(_CURABASE, base);
+ I915_WRITE(CURBASE(PIPE_A), base);
intel_crtc->cursor_base = base;
}
@@ -9882,8 +9914,8 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
}
if (intel_crtc->cursor_cntl != cntl) {
- I915_WRITE(_CURACNTR, cntl);
- POSTING_READ(_CURACNTR);
+ I915_WRITE(CURCNTR(PIPE_A), cntl);
+ POSTING_READ(CURCNTR(PIPE_A));
intel_crtc->cursor_cntl = cntl;
}
}
@@ -9915,7 +9947,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
}
cntl |= pipe << 28; /* Connect to correct pipe */
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (HAS_DDI(dev))
cntl |= CURSOR_PIPE_CSC_ENABLE;
}
@@ -9943,8 +9975,9 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- int x = crtc->cursor_x;
- int y = crtc->cursor_y;
+ struct drm_plane_state *cursor_state = crtc->cursor->state;
+ int x = cursor_state->crtc_x;
+ int y = cursor_state->crtc_y;
u32 base = 0, pos = 0;
if (on)
@@ -9957,7 +9990,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
base = 0;
if (x < 0) {
- if (x + intel_crtc->base.cursor->state->crtc_w <= 0)
+ if (x + cursor_state->crtc_w <= 0)
base = 0;
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
@@ -9966,7 +9999,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
pos |= x << CURSOR_X_SHIFT;
if (y < 0) {
- if (y + intel_crtc->base.cursor->state->crtc_h <= 0)
+ if (y + cursor_state->crtc_h <= 0)
base = 0;
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
@@ -9982,8 +10015,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
/* ILK+ do this automagically */
if (HAS_GMCH_DISPLAY(dev) &&
crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) {
- base += (intel_crtc->base.cursor->state->crtc_h *
- intel_crtc->base.cursor->state->crtc_w - 1) * 4;
+ base += (cursor_state->crtc_h *
+ cursor_state->crtc_w - 1) * 4;
}
if (IS_845G(dev) || IS_I865G(dev))
@@ -10784,7 +10817,7 @@ static bool page_flip_finished(struct intel_crtc *crtc)
*/
return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) ==
crtc->unpin_work->gtt_offset &&
- g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_GM45(crtc->pipe)),
+ g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_G4X(crtc->pipe)),
crtc->unpin_work->flip_count);
}
@@ -10810,11 +10843,11 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
-static inline void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
+static inline void intel_mark_page_flip_active(struct intel_unpin_work *work)
{
/* Ensure that the work item is consistent when activating it ... */
smp_wmb();
- atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
+ atomic_set(&work->pending, INTEL_FLIP_PENDING);
/* and that it is marked active as soon as the irq could fire. */
smp_wmb();
}
@@ -10850,7 +10883,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, 0); /* aux display base address, unused */
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -10882,7 +10915,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, MI_NOOP);
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -10921,7 +10954,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
intel_ring_emit(ring, pf | pipesrc);
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -10957,7 +10990,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
intel_ring_emit(ring, pf | pipesrc);
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -11034,10 +11067,10 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
DERRMR_PIPEB_PRI_FLIP_DONE |
DERRMR_PIPEC_PRI_FLIP_DONE));
if (IS_GEN8(dev))
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) |
+ intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT);
else
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
+ intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
MI_SRM_LRM_GLOBAL_GTT);
intel_ring_emit(ring, DERRMR);
intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
@@ -11052,7 +11085,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, (MI_NOOP));
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -11083,7 +11116,8 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
return ring != i915_gem_request_get_ring(obj->last_write_req);
}
-static void skl_do_mmio_flip(struct intel_crtc *intel_crtc)
+static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
+ struct intel_unpin_work *work)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -11124,11 +11158,12 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc)
I915_WRITE(PLANE_CTL(pipe, 0), ctl);
I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
- I915_WRITE(PLANE_SURF(pipe, 0), intel_crtc->unpin_work->gtt_offset);
+ I915_WRITE(PLANE_SURF(pipe, 0), work->gtt_offset);
POSTING_READ(PLANE_SURF(pipe, 0));
}
-static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc)
+static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
+ struct intel_unpin_work *work)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -11148,32 +11183,36 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc)
I915_WRITE(reg, dspcntr);
- I915_WRITE(DSPSURF(intel_crtc->plane),
- intel_crtc->unpin_work->gtt_offset);
+ I915_WRITE(DSPSURF(intel_crtc->plane), work->gtt_offset);
POSTING_READ(DSPSURF(intel_crtc->plane));
-
}
/*
* XXX: This is the temporary way to update the plane registers until we get
* around to using the usual plane update functions for MMIO flips
*/
-static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
+static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip)
{
- struct drm_device *dev = intel_crtc->base.dev;
- u32 start_vbl_count;
+ struct intel_crtc *crtc = mmio_flip->crtc;
+ struct intel_unpin_work *work;
+
+ spin_lock_irq(&crtc->base.dev->event_lock);
+ work = crtc->unpin_work;
+ spin_unlock_irq(&crtc->base.dev->event_lock);
+ if (work == NULL)
+ return;
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(work);
- intel_pipe_update_start(intel_crtc, &start_vbl_count);
+ intel_pipe_update_start(crtc);
- if (INTEL_INFO(dev)->gen >= 9)
- skl_do_mmio_flip(intel_crtc);
+ if (INTEL_INFO(mmio_flip->i915)->gen >= 9)
+ skl_do_mmio_flip(crtc, work);
else
/* use_mmio_flip() retricts MMIO flips to ilk+ */
- ilk_do_mmio_flip(intel_crtc);
+ ilk_do_mmio_flip(crtc, work);
- intel_pipe_update_end(intel_crtc, start_vbl_count);
+ intel_pipe_update_end(crtc);
}
static void intel_mmio_flip_work_func(struct work_struct *work)
@@ -11181,15 +11220,15 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
struct intel_mmio_flip *mmio_flip =
container_of(work, struct intel_mmio_flip, work);
- if (mmio_flip->req)
+ if (mmio_flip->req) {
WARN_ON(__i915_wait_request(mmio_flip->req,
mmio_flip->crtc->reset_counter,
false, NULL,
&mmio_flip->i915->rps.mmioflips));
+ i915_gem_request_unreference__unlocked(mmio_flip->req);
+ }
- intel_do_mmio_flip(mmio_flip->crtc);
-
- i915_gem_request_unreference__unlocked(mmio_flip->req);
+ intel_do_mmio_flip(mmio_flip);
kfree(mmio_flip);
}
@@ -11237,6 +11276,9 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev,
if (atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE)
return true;
+ if (atomic_read(&work->pending) < INTEL_FLIP_PENDING)
+ return false;
+
if (!work->enable_stall_check)
return false;
@@ -11387,7 +11429,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
- work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(pipe)) + 1;
+ work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
if (IS_VALLEYVIEW(dev)) {
ring = &dev_priv->ring[BCS];
@@ -11417,8 +11459,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
if (ret)
goto cleanup_pending;
- work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), obj)
- + intel_crtc->dspaddr_offset;
+ work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
+ obj, 0);
+ work->gtt_offset += intel_crtc->dspaddr_offset;
if (mmio_flip) {
ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
@@ -11627,7 +11670,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
intel_crtc->atomic.update_wm_pre = true;
}
- if (visible)
+ if (visible || was_visible)
intel_crtc->atomic.fb_bits |=
to_intel_plane(plane)->frontbuffer_bit;
@@ -11900,14 +11943,16 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n,
pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n,
pipe_config->fdi_m_n.tu);
- DRM_DEBUG_KMS("dp: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
+ DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
pipe_config->has_dp_encoder,
+ pipe_config->lane_count,
pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n,
pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n,
pipe_config->dp_m_n.tu);
- DRM_DEBUG_KMS("dp: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n",
+ DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n",
pipe_config->has_dp_encoder,
+ pipe_config->lane_count,
pipe_config->dp_m2_n2.gmch_m,
pipe_config->dp_m2_n2.gmch_n,
pipe_config->dp_m2_n2.link_m,
@@ -11965,9 +12010,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->dpll_hw_state.cfgcr1,
pipe_config->dpll_hw_state.cfgcr2);
} else if (HAS_DDI(dev)) {
- DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x\n",
+ DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
pipe_config->ddi_pll_sel,
- pipe_config->dpll_hw_state.wrpll);
+ pipe_config->dpll_hw_state.wrpll,
+ pipe_config->dpll_hw_state.spll);
} else {
DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
"fp0: 0x%x, fp1: 0x%x\n",
@@ -12119,10 +12165,6 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
(DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)))
pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC;
- /* Compute a starting value for pipe_config->pipe_bpp taking the source
- * plane pixel format and any sink constraints into account. Returns the
- * source plane bpp so that dithering can be selected on mismatches
- * after encoders and crtc also have had their say. */
base_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc),
pipe_config);
if (base_bpp < 0)
@@ -12191,7 +12233,7 @@ encoder_retry:
/* Dithering seems to not pass-through bits correctly when it should, so
* only enable it on 6bpc panels. */
pipe_config->dither = pipe_config->pipe_bpp == 6*3;
- DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
+ DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
fail:
@@ -12241,7 +12283,6 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
base.head) \
if (mask & (1 <<(intel_crtc)->pipe))
-
static bool
intel_compare_m_n(unsigned int m, unsigned int n,
unsigned int m2, unsigned int n2,
@@ -12414,6 +12455,7 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_M_N(fdi_m_n);
PIPE_CONF_CHECK_I(has_dp_encoder);
+ PIPE_CONF_CHECK_I(lane_count);
if (INTEL_INFO(dev)->gen < 8) {
PIPE_CONF_CHECK_M_N(dp_m_n);
@@ -12461,22 +12503,24 @@ intel_pipe_config_compare(struct drm_device *dev,
DRM_MODE_FLAG_NVSYNC);
}
- PIPE_CONF_CHECK_I(pipe_src_w);
- PIPE_CONF_CHECK_I(pipe_src_h);
-
- PIPE_CONF_CHECK_I(gmch_pfit.control);
+ PIPE_CONF_CHECK_X(gmch_pfit.control);
/* pfit ratios are autocomputed by the hw on gen4+ */
if (INTEL_INFO(dev)->gen < 4)
PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
- PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
+ PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
- PIPE_CONF_CHECK_I(pch_pfit.enabled);
- if (current_config->pch_pfit.enabled) {
- PIPE_CONF_CHECK_I(pch_pfit.pos);
- PIPE_CONF_CHECK_I(pch_pfit.size);
- }
+ if (!adjust) {
+ PIPE_CONF_CHECK_I(pipe_src_w);
+ PIPE_CONF_CHECK_I(pipe_src_h);
+
+ PIPE_CONF_CHECK_I(pch_pfit.enabled);
+ if (current_config->pch_pfit.enabled) {
+ PIPE_CONF_CHECK_X(pch_pfit.pos);
+ PIPE_CONF_CHECK_X(pch_pfit.size);
+ }
- PIPE_CONF_CHECK_I(scaler_state.scaler_id);
+ PIPE_CONF_CHECK_I(scaler_state.scaler_id);
+ }
/* BDW+ don't expose a synchronous way to read the state */
if (IS_HASWELL(dev))
@@ -12492,6 +12536,7 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
+ PIPE_CONF_CHECK_X(dpll_hw_state.spll);
PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
@@ -12549,8 +12594,8 @@ static void check_wm_state(struct drm_device *dev)
}
/* cursor */
- hw_entry = &hw_ddb.cursor[pipe];
- sw_entry = &sw_ddb->cursor[pipe];
+ hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
+ sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
if (skl_ddb_entry_equal(hw_entry, sw_entry))
continue;
@@ -12638,7 +12683,8 @@ check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state)
struct intel_crtc_state *pipe_config, *sw_config;
bool active;
- if (!needs_modeset(crtc->state))
+ if (!needs_modeset(crtc->state) &&
+ !to_intel_crtc_state(crtc->state)->update_pipe)
continue;
__drm_atomic_helper_crtc_destroy_state(crtc, old_crtc_state);
@@ -12792,11 +12838,11 @@ static void update_scanline_offset(struct intel_crtc *crtc)
* one to the value.
*/
if (IS_GEN2(dev)) {
- const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
int vtotal;
- vtotal = mode->crtc_vtotal;
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ vtotal = adjusted_mode->crtc_vtotal;
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
vtotal /= 2;
crtc->scanline_offset = vtotal - 1;
@@ -12934,7 +12980,6 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state)
return ret;
}
-
static int intel_modeset_checks(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
@@ -12996,6 +13041,9 @@ static int intel_atomic_check(struct drm_device *dev,
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc_state);
+ memset(&to_intel_crtc(crtc)->atomic, 0,
+ sizeof(struct intel_crtc_atomic_commit));
+
/* Catch I915_MODE_FLAG_INHERITED */
if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
crtc_state->mode_changed = true;
@@ -13025,6 +13073,7 @@ static int intel_atomic_check(struct drm_device *dev,
to_intel_crtc_state(crtc->state),
pipe_config, true)) {
crtc_state->mode_changed = false;
+ to_intel_crtc_state(crtc_state)->update_pipe = true;
}
if (needs_modeset(crtc_state)) {
@@ -13122,16 +13171,30 @@ static int intel_atomic_commit(struct drm_device *dev,
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
bool modeset = needs_modeset(crtc->state);
+ bool update_pipe = !modeset &&
+ to_intel_crtc_state(crtc->state)->update_pipe;
+ unsigned long put_domains = 0;
if (modeset && crtc->state->active) {
update_scanline_offset(to_intel_crtc(crtc));
dev_priv->display.crtc_enable(crtc);
}
+ if (update_pipe) {
+ put_domains = modeset_get_crtc_power_domains(crtc);
+
+ /* make sure intel_modeset_check_state runs */
+ any_ms = true;
+ }
+
if (!modeset)
intel_pre_plane_update(intel_crtc);
drm_atomic_helper_commit_planes_on_crtc(crtc_state);
+
+ if (put_domains)
+ modeset_put_power_domains(dev_priv, put_domains);
+
intel_post_plane_update(intel_crtc);
}
@@ -13287,8 +13350,6 @@ static void intel_shared_dpll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- intel_update_cdclk(dev);
-
if (HAS_DDI(dev))
intel_ddi_pll_init(dev);
else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
@@ -13313,10 +13374,10 @@ static void intel_shared_dpll_init(struct drm_device *dev)
*/
int
intel_prepare_plane_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
struct drm_device *dev = plane->dev;
+ struct drm_framebuffer *fb = new_state->fb;
struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
@@ -13354,19 +13415,18 @@ intel_prepare_plane_fb(struct drm_plane *plane,
*/
void
intel_cleanup_plane_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *old_state)
{
struct drm_device *dev = plane->dev;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb);
- if (WARN_ON(!obj))
+ if (!obj)
return;
if (plane->type != DRM_PLANE_TYPE_CURSOR ||
!INTEL_INFO(dev)->cursor_needs_physical) {
mutex_lock(&dev->struct_mutex);
- intel_unpin_fb_obj(fb, old_state);
+ intel_unpin_fb_obj(old_state->fb, old_state);
mutex_unlock(&dev->struct_mutex);
}
}
@@ -13448,11 +13508,9 @@ intel_commit_primary_plane(struct drm_plane *plane,
if (!crtc->state->active)
return;
- if (state->visible)
- /* FIXME: kill this fastboot hack */
- intel_update_pipe_size(intel_crtc);
-
- dev_priv->display.update_primary_plane(crtc, fb, crtc->x, crtc->y);
+ dev_priv->display.update_primary_plane(crtc, fb,
+ state->src.x1 >> 16,
+ state->src.y1 >> 16);
}
static void
@@ -13470,15 +13528,23 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
{
struct drm_device *dev = crtc->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *old_intel_state =
+ to_intel_crtc_state(old_crtc_state);
+ bool modeset = needs_modeset(crtc->state);
if (intel_crtc->atomic.update_wm_pre)
intel_update_watermarks(crtc);
/* Perform vblank evasion around commit operation */
if (crtc->state->active)
- intel_pipe_update_start(intel_crtc, &intel_crtc->start_vbl_count);
+ intel_pipe_update_start(intel_crtc);
+
+ if (modeset)
+ return;
- if (!needs_modeset(crtc->state) && INTEL_INFO(dev)->gen >= 9)
+ if (to_intel_crtc_state(crtc->state)->update_pipe)
+ intel_update_pipe_config(intel_crtc, old_intel_state);
+ else if (INTEL_INFO(dev)->gen >= 9)
skl_detach_scalers(intel_crtc);
}
@@ -13488,7 +13554,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
if (crtc->state->active)
- intel_pipe_update_end(intel_crtc, intel_crtc->start_vbl_count);
+ intel_pipe_update_end(intel_crtc);
}
/**
@@ -13657,10 +13723,6 @@ intel_commit_cursor_plane(struct drm_plane *plane,
crtc = crtc ? crtc : plane->crtc;
intel_crtc = to_intel_crtc(crtc);
- plane->fb = state->base.fb;
- crtc->cursor_x = state->base.crtc_x;
- crtc->cursor_y = state->base.crtc_y;
-
if (intel_crtc->cursor_bo == obj)
goto update;
@@ -13946,7 +14008,7 @@ static void intel_setup_outputs(struct drm_device *dev)
* On SKL pre-D0 the strap isn't connected, so we assume
* it's there.
*/
- found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED;
+ found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
/* WaIgnoreDDIAStrap: skl */
if (found || IS_SKYLAKE(dev))
intel_ddi_init(dev, PORT_A);
@@ -14007,29 +14069,26 @@ static void intel_setup_outputs(struct drm_device *dev)
* eDP ports. Consult the VBT as well as DP_DETECTED to
* detect eDP ports.
*/
- if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED &&
+ if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
!intel_dp_is_edp(dev, PORT_B))
- intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
- PORT_B);
- if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED ||
+ intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
+ if (I915_READ(VLV_DP_B) & DP_DETECTED ||
intel_dp_is_edp(dev, PORT_B))
- intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
+ intel_dp_init(dev, VLV_DP_B, PORT_B);
- if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED &&
+ if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
!intel_dp_is_edp(dev, PORT_C))
- intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
- PORT_C);
- if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED ||
+ intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
+ if (I915_READ(VLV_DP_C) & DP_DETECTED ||
intel_dp_is_edp(dev, PORT_C))
- intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
+ intel_dp_init(dev, VLV_DP_C, PORT_C);
if (IS_CHERRYVIEW(dev)) {
- if (I915_READ(VLV_DISPLAY_BASE + CHV_HDMID) & SDVO_DETECTED)
- intel_hdmi_init(dev, VLV_DISPLAY_BASE + CHV_HDMID,
- PORT_D);
/* eDP not supported on port D, so don't check VBT */
- if (I915_READ(VLV_DISPLAY_BASE + DP_D) & DP_DETECTED)
- intel_dp_init(dev, VLV_DISPLAY_BASE + DP_D, PORT_D);
+ if (I915_READ(CHV_HDMID) & SDVO_DETECTED)
+ intel_hdmi_init(dev, CHV_HDMID, PORT_D);
+ if (I915_READ(CHV_DP_D) & DP_DETECTED)
+ intel_dp_init(dev, CHV_DP_D, PORT_D);
}
intel_dsi_init(dev);
@@ -14107,6 +14166,11 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
+ if (obj->userptr.mm) {
+ DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n");
+ return -EINVAL;
+ }
+
return drm_gem_handle_create(file, &obj->base, handle);
}
@@ -14313,16 +14377,17 @@ static int intel_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
intel_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ struct drm_mode_fb_cmd2 *user_mode_cmd)
{
struct drm_i915_gem_object *obj;
+ struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
- mode_cmd->handles[0]));
+ mode_cmd.handles[0]));
if (&obj->base == NULL)
return ERR_PTR(-ENOENT);
- return intel_framebuffer_create(dev, mode_cmd, obj);
+ return intel_framebuffer_create(dev, &mode_cmd, obj);
}
#ifndef CONFIG_DRM_FBDEV_EMULATION
@@ -14520,8 +14585,6 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.queue_flip = intel_default_queue_flip;
}
- intel_panel_init_backlight_funcs(dev);
-
mutex_init(&dev_priv->pps_mutex);
}
@@ -14656,6 +14719,9 @@ static struct intel_quirk intel_quirks[] = {
/* Apple Macbook 2,1 (Core 2 T7400) */
{ 0x27a2, 0x8086, 0x7270, quirk_backlight_present },
+ /* Apple Macbook 4,1 */
+ { 0x2a02, 0x106b, 0x00a1, quirk_backlight_present },
+
/* Toshiba CB35 Chromebook (Celeron 2955U) */
{ 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
@@ -14664,6 +14730,9 @@ static struct intel_quirk intel_quirks[] = {
/* Dell Chromebook 11 */
{ 0x0a06, 0x1028, 0x0a35, quirk_backlight_present },
+
+ /* Dell Chromebook 11 (2015 version) */
+ { 0x0a16, 0x1028, 0x0a35, quirk_backlight_present },
};
static void intel_init_quirks(struct drm_device *dev)
@@ -14799,7 +14868,8 @@ void intel_modeset_init(struct drm_device *dev)
}
}
- intel_init_dpio(dev);
+ intel_update_czclk(dev_priv);
+ intel_update_cdclk(dev);
intel_shared_dpll_init(dev);
@@ -14867,13 +14937,12 @@ intel_check_plane_mapping(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg, val;
+ u32 val;
if (INTEL_INFO(dev)->num_pipes == 1)
return true;
- reg = DSPCNTR(!crtc->plane);
- val = I915_READ(reg);
+ val = I915_READ(DSPCNTR(!crtc->plane));
if ((val & DISPLAY_PLANE_ENABLE) &&
(!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
@@ -14882,13 +14951,22 @@ intel_check_plane_mapping(struct intel_crtc *crtc)
return true;
}
+static bool intel_crtc_has_encoders(struct intel_crtc *crtc)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct intel_encoder *encoder;
+
+ for_each_encoder_on_crtc(dev, &crtc->base, encoder)
+ return true;
+
+ return false;
+}
+
static void intel_sanitize_crtc(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_encoder *encoder;
u32 reg;
- bool enable;
/* Clear any frame start delays used for debugging left by the BIOS */
reg = PIPECONF(crtc->config->cpu_transcoder);
@@ -14897,9 +14975,17 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
/* restore vblank interrupts to correct state */
drm_crtc_vblank_reset(&crtc->base);
if (crtc->active) {
- drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
- update_scanline_offset(crtc);
+ struct intel_plane *plane;
+
drm_crtc_vblank_on(&crtc->base);
+
+ /* Disable everything but the primary plane */
+ for_each_intel_plane_on_crtc(dev, crtc, plane) {
+ if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+ continue;
+
+ plane->disable_plane(&plane->base, &crtc->base);
+ }
}
/* We need to sanitize the plane -> pipe mapping first because this will
@@ -14932,16 +15018,11 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
/* Adjust the state of the output pipe according to whether we
* have active connectors/encoders. */
- enable = false;
- for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
- enable = true;
- break;
- }
-
- if (!enable)
+ if (!intel_crtc_has_encoders(crtc))
intel_crtc_disable_noatomic(&crtc->base);
if (crtc->active != crtc->base.state->active) {
+ struct intel_encoder *encoder;
/* This can happen either due to bugs in the get_hw_state
* functions or because of calls to intel_crtc_disable_noatomic,
@@ -15067,38 +15148,25 @@ void i915_redisable_vga(struct drm_device *dev)
i915_redisable_vga_power_on(dev);
}
-static bool primary_get_hw_state(struct intel_crtc *crtc)
+static bool primary_get_hw_state(struct intel_plane *plane)
{
- struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+ struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
- return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
+ return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
}
-static void readout_plane_state(struct intel_crtc *crtc,
- struct intel_crtc_state *crtc_state)
+/* FIXME read out full plane state for all planes */
+static void readout_plane_state(struct intel_crtc *crtc)
{
- struct intel_plane *p;
- struct intel_plane_state *plane_state;
- bool active = crtc_state->base.active;
-
- for_each_intel_plane(crtc->base.dev, p) {
- if (crtc->pipe != p->pipe)
- continue;
+ struct drm_plane *primary = crtc->base.primary;
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(primary->state);
- plane_state = to_intel_plane_state(p->base.state);
+ plane_state->visible =
+ primary_get_hw_state(to_intel_plane(primary));
- if (p->base.type == DRM_PLANE_TYPE_PRIMARY) {
- plane_state->visible = primary_get_hw_state(crtc);
- if (plane_state->visible)
- crtc->base.state->plane_mask |=
- 1 << drm_plane_index(&p->base);
- } else {
- if (active)
- p->disable_plane(&p->base, &crtc->base);
-
- plane_state->visible = false;
- }
- }
+ if (plane_state->visible)
+ crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
}
static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -15121,34 +15189,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
crtc->base.state->active = crtc->active;
crtc->base.enabled = crtc->active;
- memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
- if (crtc->base.state->active) {
- intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
- intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
- WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
-
- /*
- * The initial mode needs to be set in order to keep
- * the atomic core happy. It wants a valid mode if the
- * crtc's enabled, so we do the above call.
- *
- * At this point some state updated by the connectors
- * in their ->detect() callback has not run yet, so
- * no recalculation can be done yet.
- *
- * Even if we could do a recalculation and modeset
- * right now it would cause a double modeset if
- * fbdev or userspace chooses a different initial mode.
- *
- * If that happens, someone indicated they wanted a
- * mode change, which means it's safe to do a full
- * recalculation.
- */
- crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
- }
-
- crtc->base.hwmode = crtc->config->base.adjusted_mode;
- readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
+ readout_plane_state(crtc);
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
crtc->base.base.id,
@@ -15207,6 +15248,39 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
connector->base.name,
connector->base.encoder ? "enabled" : "disabled");
}
+
+ for_each_intel_crtc(dev, crtc) {
+ crtc->base.hwmode = crtc->config->base.adjusted_mode;
+
+ memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
+ if (crtc->base.state->active) {
+ intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
+ intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
+ WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
+
+ /*
+ * The initial mode needs to be set in order to keep
+ * the atomic core happy. It wants a valid mode if the
+ * crtc's enabled, so we do the above call.
+ *
+ * At this point some state updated by the connectors
+ * in their ->detect() callback has not run yet, so
+ * no recalculation can be done yet.
+ *
+ * Even if we could do a recalculation and modeset
+ * right now it would cause a double modeset if
+ * fbdev or userspace chooses a different initial mode.
+ *
+ * If that happens, someone indicated they wanted a
+ * mode change, which means it's safe to do a full
+ * recalculation.
+ */
+ crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
+
+ drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
+ update_scanline_offset(crtc);
+ }
+ }
}
/* Scan out the current hw modeset state,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0a2e33fbf20d..09bdd94ca3ba 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -130,6 +130,11 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp);
static void vlv_steal_power_sequencer(struct drm_device *dev,
enum pipe pipe);
+static unsigned int intel_dp_unused_lane_mask(int lane_count)
+{
+ return ~((1 << lane_count) - 1) & 0xf;
+}
+
static int
intel_dp_max_link_bw(struct intel_dp *intel_dp)
{
@@ -253,40 +258,6 @@ static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
dst[i] = src >> ((3-i) * 8);
}
-/* hrawclock is 1/4 the FSB frequency */
-static int
-intel_hrawclk(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t clkcfg;
-
- /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
- if (IS_VALLEYVIEW(dev))
- return 200;
-
- clkcfg = I915_READ(CLKCFG);
- switch (clkcfg & CLKCFG_FSB_MASK) {
- case CLKCFG_FSB_400:
- return 100;
- case CLKCFG_FSB_533:
- return 133;
- case CLKCFG_FSB_667:
- return 166;
- case CLKCFG_FSB_800:
- return 200;
- case CLKCFG_FSB_1067:
- return 266;
- case CLKCFG_FSB_1333:
- return 333;
- /* these two are just a guess; one of them might be right */
- case CLKCFG_FSB_1600:
- case CLKCFG_FSB_1600_ALT:
- return 400;
- default:
- return 133;
- }
-}
-
static void
intel_dp_init_panel_power_sequencer(struct drm_device *dev,
struct intel_dp *intel_dp);
@@ -333,7 +304,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe = intel_dp->pps_pipe;
- bool pll_enabled;
+ bool pll_enabled, release_cl_override = false;
+ enum dpio_phy phy = DPIO_PHY(pipe);
+ enum dpio_channel ch = vlv_pipe_to_channel(pipe);
uint32_t DP;
if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
@@ -363,9 +336,13 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
* The DPLL for the pipe must be enabled for this to work.
* So enable temporarily it if it's not already enabled.
*/
- if (!pll_enabled)
+ if (!pll_enabled) {
+ release_cl_override = IS_CHERRYVIEW(dev) &&
+ !chv_phy_powergate_ch(dev_priv, phy, ch, true);
+
vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
&chv_dpll[0].dpll : &vlv_dpll[0].dpll);
+ }
/*
* Similar magic as in intel_dp_enable_port().
@@ -382,8 +359,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg);
- if (!pll_enabled)
+ if (!pll_enabled) {
vlv_force_pll_off(dev, pipe);
+
+ if (release_cl_override)
+ chv_phy_powergate_ch(dev_priv, phy, ch, false);
+ }
}
static enum pipe
@@ -593,8 +574,6 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
edp_notifier);
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_div;
- u32 pp_ctrl_reg, pp_div_reg;
if (!is_edp(intel_dp) || code != SYS_RESTART)
return 0;
@@ -603,6 +582,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
if (IS_VALLEYVIEW(dev)) {
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+ u32 pp_ctrl_reg, pp_div_reg;
+ u32 pp_div;
pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
@@ -974,6 +955,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_NATIVE_WRITE:
case DP_AUX_I2C_WRITE:
+ case DP_AUX_I2C_WRITE_STATUS_UPDATE:
txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE;
rxsize = 2; /* 0 or 1 data bytes */
@@ -1383,6 +1365,19 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
return rate_to_index(rate, intel_dp->sink_rates);
}
+static void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
+ uint8_t *link_bw, uint8_t *rate_select)
+{
+ if (intel_dp->num_sink_rates) {
+ *link_bw = 0;
+ *rate_select =
+ intel_dp_rate_select(intel_dp, port_clock);
+ } else {
+ *link_bw = drm_dp_link_rate_to_bw_code(port_clock);
+ *rate_select = 0;
+ }
+}
+
bool
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
@@ -1404,6 +1399,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
int link_avail, link_clock;
int common_rates[DP_MAX_SUPPORTED_RATES] = {};
int common_len;
+ uint8_t link_bw, rate_select;
common_len = intel_dp_common_rates(intel_dp, common_rates);
@@ -1499,32 +1495,23 @@ found:
* CEA-861-E - 5.1 Default Encoding Parameters
* VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry
*/
- if (bpp != 18 && drm_match_cea_mode(adjusted_mode) > 1)
- intel_dp->color_range = DP_COLOR_RANGE_16_235;
- else
- intel_dp->color_range = 0;
- }
-
- if (intel_dp->color_range)
- pipe_config->limited_color_range = true;
-
- intel_dp->lane_count = lane_count;
-
- if (intel_dp->num_sink_rates) {
- intel_dp->link_bw = 0;
- intel_dp->rate_select =
- intel_dp_rate_select(intel_dp, common_rates[clock]);
+ pipe_config->limited_color_range =
+ bpp != 18 && drm_match_cea_mode(adjusted_mode) > 1;
} else {
- intel_dp->link_bw =
- drm_dp_link_rate_to_bw_code(common_rates[clock]);
- intel_dp->rate_select = 0;
+ pipe_config->limited_color_range =
+ intel_dp->limited_color_range;
}
+ pipe_config->lane_count = lane_count;
+
pipe_config->pipe_bpp = bpp;
pipe_config->port_clock = common_rates[clock];
- DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
- intel_dp->link_bw, intel_dp->lane_count,
+ intel_dp_compute_rate(intel_dp, pipe_config->port_clock,
+ &link_bw, &rate_select);
+
+ DRM_DEBUG_KMS("DP link bw %02x rate select %02x lane count %d clock %d bpp %d\n",
+ link_bw, rate_select, pipe_config->lane_count,
pipe_config->port_clock, bpp);
DRM_DEBUG_KMS("DP link bw required %i available %i\n",
mode_rate, link_avail);
@@ -1586,6 +1573,13 @@ static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp)
udelay(500);
}
+void intel_dp_set_link_params(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *pipe_config)
+{
+ intel_dp->link_rate = pipe_config->port_clock;
+ intel_dp->lane_count = pipe_config->lane_count;
+}
+
static void intel_dp_prepare(struct intel_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
@@ -1593,7 +1587,9 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
enum port port = dp_to_dig_port(intel_dp)->port;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
- struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+
+ intel_dp_set_link_params(intel_dp, crtc->config);
/*
* There are four kinds of DP registers:
@@ -1619,7 +1615,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
/* Handle DP bits in common between all three register formats */
intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
- intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count);
+ intel_dp->DP |= DP_PORT_WIDTH(crtc->config->lane_count);
if (crtc->config->has_audio)
intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
@@ -1649,8 +1645,9 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
trans_dp &= ~TRANS_DP_ENH_FRAMING;
I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp);
} else {
- if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
- intel_dp->DP |= intel_dp->color_range;
+ if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
+ crtc->config->limited_color_range)
+ intel_dp->DP |= DP_COLOR_RANGE_16_235;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
intel_dp->DP |= DP_SYNC_HS_HIGH;
@@ -2290,13 +2287,14 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A;
if (HAS_PCH_CPT(dev) && port != PORT_A) {
- tmp = I915_READ(TRANS_DP_CTL(crtc->pipe));
- if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH)
+ u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe));
+
+ if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
- if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH)
+ if (trans_dp & TRANS_DP_VSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
@@ -2320,6 +2318,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
pipe_config->has_dp_encoder = true;
+ pipe_config->lane_count =
+ ((tmp & DP_PORT_WIDTH_MASK) >> DP_PORT_WIDTH_SHIFT) + 1;
+
intel_dp_get_m_n(crtc, pipe_config);
if (port == PORT_A) {
@@ -2399,38 +2400,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder)
intel_dp_link_down(intel_dp);
}
-static void chv_post_disable_dp(struct intel_encoder *encoder)
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+ bool reset)
{
- struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
- struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc =
- to_intel_crtc(encoder->base.crtc);
- enum dpio_channel ch = vlv_dport_to_channel(dport);
- enum pipe pipe = intel_crtc->pipe;
- u32 val;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ enum pipe pipe = crtc->pipe;
+ uint32_t val;
- intel_dp_link_down(intel_dp);
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+ if (reset)
+ val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+ else
+ val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
- mutex_lock(&dev_priv->sb_lock);
+ if (crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+ if (reset)
+ val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+ else
+ val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+ }
- /* Propagate soft reset to data lane reset */
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
val |= CHV_PCS_REQ_SOFTRESET_EN;
+ if (reset)
+ val &= ~DPIO_PCS_CLK_SOFT_RESET;
+ else
+ val |= DPIO_PCS_CLK_SOFT_RESET;
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+ if (crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+ val |= CHV_PCS_REQ_SOFTRESET_EN;
+ if (reset)
+ val &= ~DPIO_PCS_CLK_SOFT_RESET;
+ else
+ val |= DPIO_PCS_CLK_SOFT_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+ }
+}
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
- val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+static void chv_post_disable_dp(struct intel_encoder *encoder)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ intel_dp_link_down(intel_dp);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
- val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+ mutex_lock(&dev_priv->sb_lock);
+
+ /* Assert data lane reset */
+ chv_data_lane_soft_reset(encoder, true);
mutex_unlock(&dev_priv->sb_lock);
}
@@ -2550,7 +2575,6 @@ static void intel_enable_dp(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
- unsigned int lane_mask = 0x0;
if (WARN_ON(dp_reg & DP_PORT_EN))
return;
@@ -2568,13 +2592,18 @@ static void intel_enable_dp(struct intel_encoder *encoder)
pps_unlock(intel_dp);
- if (IS_VALLEYVIEW(dev))
+ if (IS_VALLEYVIEW(dev)) {
+ unsigned int lane_mask = 0x0;
+
+ if (IS_CHERRYVIEW(dev))
+ lane_mask = intel_dp_unused_lane_mask(crtc->config->lane_count);
+
vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp),
lane_mask);
+ }
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp);
- intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
if (crtc->config->has_audio) {
@@ -2797,31 +2826,19 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
- val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
-
- /* Deassert soft data lane reset*/
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
- val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
- val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+ if (intel_crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+ val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+ }
/* Program Tx lane latency optimal setting*/
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < intel_crtc->config->lane_count; i++) {
/* Set the upar bit */
- data = (i == 1) ? 0x0 : 0x1;
+ if (intel_crtc->config->lane_count == 1)
+ data = 0x0;
+ else
+ data = (i == 1) ? 0x0 : 0x1;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW14(ch, i),
data << DPIO_UPAR_SHIFT);
}
@@ -2842,9 +2859,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
val |= DPIO_TX2_STAGGER_MASK(0x1f);
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
- val |= DPIO_TX2_STAGGER_MASK(0x1f);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+ if (intel_crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+ val |= DPIO_TX2_STAGGER_MASK(0x1f);
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+ }
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch),
DPIO_LANESTAGGER_STRAP(stagger) |
@@ -2853,16 +2872,27 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
DPIO_TX1_STAGGER_MULT(6) |
DPIO_TX2_STAGGER_MULT(0));
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
- DPIO_LANESTAGGER_STRAP(stagger) |
- DPIO_LANESTAGGER_STRAP_OVRD |
- DPIO_TX1_STAGGER_MASK(0x1f) |
- DPIO_TX1_STAGGER_MULT(7) |
- DPIO_TX2_STAGGER_MULT(5));
+ if (intel_crtc->config->lane_count > 2) {
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
+ DPIO_LANESTAGGER_STRAP(stagger) |
+ DPIO_LANESTAGGER_STRAP_OVRD |
+ DPIO_TX1_STAGGER_MASK(0x1f) |
+ DPIO_TX1_STAGGER_MULT(7) |
+ DPIO_TX2_STAGGER_MULT(5));
+ }
+
+ /* Deassert data lane reset */
+ chv_data_lane_soft_reset(encoder, false);
mutex_unlock(&dev_priv->sb_lock);
intel_enable_dp(encoder);
+
+ /* Second common lane will stay alive on its own now */
+ if (dport->release_cl2_override) {
+ chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
+ dport->release_cl2_override = false;
+ }
}
static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
@@ -2874,12 +2904,27 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
to_intel_crtc(encoder->base.crtc);
enum dpio_channel ch = vlv_dport_to_channel(dport);
enum pipe pipe = intel_crtc->pipe;
+ unsigned int lane_mask =
+ intel_dp_unused_lane_mask(intel_crtc->config->lane_count);
u32 val;
intel_dp_prepare(encoder);
+ /*
+ * Must trick the second common lane into life.
+ * Otherwise we can't even access the PLL.
+ */
+ if (ch == DPIO_CH0 && pipe == PIPE_B)
+ dport->release_cl2_override =
+ !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
+
+ chv_phy_powergate_lanes(encoder, true, lane_mask);
+
mutex_lock(&dev_priv->sb_lock);
+ /* Assert data lane reset */
+ chv_data_lane_soft_reset(encoder, true);
+
/* program left/right clock distribution */
if (pipe != PIPE_B) {
val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
@@ -2908,13 +2953,15 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
val |= CHV_PCS_USEDCLKCHANNEL;
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
- val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
- if (pipe != PIPE_B)
- val &= ~CHV_PCS_USEDCLKCHANNEL;
- else
- val |= CHV_PCS_USEDCLKCHANNEL;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+ if (intel_crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
+ val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+ if (pipe != PIPE_B)
+ val &= ~CHV_PCS_USEDCLKCHANNEL;
+ else
+ val |= CHV_PCS_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+ }
/*
* This a a bit weird since generally CL
@@ -2931,6 +2978,39 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->sb_lock);
}
+static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
+ u32 val;
+
+ mutex_lock(&dev_priv->sb_lock);
+
+ /* disable left/right clock distribution */
+ if (pipe != PIPE_B) {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+ val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+ } else {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+ val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+ }
+
+ mutex_unlock(&dev_priv->sb_lock);
+
+ /*
+ * Leave the power down bit cleared for at least one
+ * lane so that chv_powergate_phy_ch() will power
+ * on something when the channel is otherwise unused.
+ * When the port is off and the override is removed
+ * the lanes power down anyway, so otherwise it doesn't
+ * really matter what the state of power down bits is
+ * after this.
+ */
+ chv_phy_powergate_lanes(encoder, false, 0x0);
+}
+
/*
* Native read with retry for link status and receiver capability reads for
* cases where the sink may still be asleep.
@@ -3167,6 +3247,12 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
return 0;
}
+static bool chv_need_uniq_trans_scale(uint8_t train_set)
+{
+ return (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) == DP_TRAIN_PRE_EMPH_LEVEL_0 &&
+ (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) == DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+}
+
static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -3258,24 +3344,28 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
- val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
- val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
- val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+ if (intel_crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
+ val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
+ val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
+ val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+ }
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch));
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
- val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
- val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
+ if (intel_crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
+ val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
+ val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
+ }
/* Program swing deemph */
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < intel_crtc->config->lane_count; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i));
val &= ~DPIO_SWING_DEEMPH9P5_MASK;
val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT;
@@ -3283,43 +3373,36 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
}
/* Program swing margin */
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < intel_crtc->config->lane_count; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
+
val &= ~DPIO_SWING_MARGIN000_MASK;
val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT;
+
+ /*
+ * Supposedly this value shouldn't matter when unique transition
+ * scale is disabled, but in fact it does matter. Let's just
+ * always program the same value and hope it's OK.
+ */
+ val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
+ val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT;
+
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
}
- /* Disable unique transition scale */
- for (i = 0; i < 4; i++) {
+ /*
+ * The document said it needs to set bit 27 for ch0 and bit 26
+ * for ch1. Might be a typo in the doc.
+ * For now, for this unique transition scale selection, set bit
+ * 27 for ch0 and ch1.
+ */
+ for (i = 0; i < intel_crtc->config->lane_count; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
- val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
- vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
- }
-
- if (((train_set & DP_TRAIN_PRE_EMPHASIS_MASK)
- == DP_TRAIN_PRE_EMPH_LEVEL_0) &&
- ((train_set & DP_TRAIN_VOLTAGE_SWING_MASK)
- == DP_TRAIN_VOLTAGE_SWING_LEVEL_3)) {
-
- /*
- * The document said it needs to set bit 27 for ch0 and bit 26
- * for ch1. Might be a typo in the doc.
- * For now, for this unique transition scale selection, set bit
- * 27 for ch0 and ch1.
- */
- for (i = 0; i < 4; i++) {
- val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
+ if (chv_need_uniq_trans_scale(train_set))
val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
- vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
- }
-
- for (i = 0; i < 4; i++) {
- val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
- val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
- val |= (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT);
- vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
- }
+ else
+ val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
+ vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
}
/* Start swing calculation */
@@ -3327,14 +3410,11 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
- val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
-
- /* LRC Bypass */
- val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
- val |= DPIO_LRC_BYPASS;
- vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, val);
+ if (intel_crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
+ val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+ }
mutex_unlock(&dev_priv->sb_lock);
@@ -3520,8 +3600,8 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
uint8_t dp_train_pat)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_device *dev = intel_dig_port->base.base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_private *dev_priv =
+ to_i915(intel_dig_port->base.base.dev);
uint8_t buf[sizeof(intel_dp->train_set) + 1];
int ret, len;
@@ -3562,8 +3642,8 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP,
const uint8_t link_status[DP_LINK_STATUS_SIZE])
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_device *dev = intel_dig_port->base.base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_private *dev_priv =
+ to_i915(intel_dig_port->base.base.dev);
int ret;
intel_get_adjust_train(intel_dp, link_status);
@@ -3610,8 +3690,8 @@ static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
}
/* Enable corresponding port and start training pattern 1 */
-void
-intel_dp_start_link_train(struct intel_dp *intel_dp)
+static void
+intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
{
struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base;
struct drm_device *dev = encoder->dev;
@@ -3620,19 +3700,23 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
int voltage_tries, loop_tries;
uint32_t DP = intel_dp->DP;
uint8_t link_config[2];
+ uint8_t link_bw, rate_select;
if (HAS_DDI(dev))
intel_ddi_prepare_link_retrain(encoder);
+ intel_dp_compute_rate(intel_dp, intel_dp->link_rate,
+ &link_bw, &rate_select);
+
/* Write the link configuration data */
- link_config[0] = intel_dp->link_bw;
+ link_config[0] = link_bw;
link_config[1] = intel_dp->lane_count;
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
if (intel_dp->num_sink_rates)
drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
- &intel_dp->rate_select, 1);
+ &rate_select, 1);
link_config[0] = 0;
link_config[1] = DP_SET_ANSI_8B10B;
@@ -3720,17 +3804,30 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
intel_dp->DP = DP;
}
-void
-intel_dp_complete_link_train(struct intel_dp *intel_dp)
+static void
+intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
bool channel_eq = false;
int tries, cr_tries;
uint32_t DP = intel_dp->DP;
uint32_t training_pattern = DP_TRAINING_PATTERN_2;
- /* Training Pattern 3 for HBR2 ot 1.2 devices that support it*/
- if (intel_dp->link_bw == DP_LINK_BW_5_4 || intel_dp->use_tps3)
+ /*
+ * Training Pattern 3 for HBR2 or 1.2 devices that support it.
+ *
+ * Intel platforms that support HBR2 also support TPS3. TPS3 support is
+ * also mandatory for downstream devices that support HBR2.
+ *
+ * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
+ * supported but still not enabled.
+ */
+ if (intel_dp_source_supports_hbr2(dev) &&
+ drm_dp_tps3_supported(intel_dp->dpcd))
training_pattern = DP_TRAINING_PATTERN_3;
+ else if (intel_dp->link_rate == 540000)
+ DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n");
/* channel equalization */
if (!intel_dp_set_link_train(intel_dp, &DP,
@@ -3758,9 +3855,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
}
/* Make sure clock is still ok */
- if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+ if (!drm_dp_clock_recovery_ok(link_status,
+ intel_dp->lane_count)) {
intel_dp->train_set_valid = false;
- intel_dp_start_link_train(intel_dp);
+ intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp, &DP,
training_pattern |
DP_LINK_SCRAMBLING_DISABLE);
@@ -3768,7 +3866,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
continue;
}
- if (drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) {
+ if (drm_dp_channel_eq_ok(link_status,
+ intel_dp->lane_count)) {
channel_eq = true;
break;
}
@@ -3776,7 +3875,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
/* Try 5 times, then try clock recovery if that fails */
if (tries > 5) {
intel_dp->train_set_valid = false;
- intel_dp_start_link_train(intel_dp);
+ intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp, &DP,
training_pattern |
DP_LINK_SCRAMBLING_DISABLE);
@@ -3809,6 +3908,13 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
DP_TRAINING_PATTERN_DISABLE);
}
+void
+intel_dp_start_link_train(struct intel_dp *intel_dp)
+{
+ intel_dp_link_training_clock_recovery(intel_dp);
+ intel_dp_link_training_channel_equalization(intel_dp);
+}
+
static void
intel_dp_link_down(struct intel_dp *intel_dp)
{
@@ -3909,19 +4015,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
}
}
- /* Training Pattern 3 support, Intel platforms that support HBR2 alone
- * have support for TP3 hence that check is used along with dpcd check
- * to ensure TP3 can be enabled.
- * SKL < B0: due it's WaDisableHBR2 is the only exception where TP3 is
- * supported but still not enabled.
- */
- if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 &&
- intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED &&
- intel_dp_source_supports_hbr2(dev)) {
- intel_dp->use_tps3 = true;
- DRM_DEBUG_KMS("Displayport TPS3 supported\n");
- } else
- intel_dp->use_tps3 = false;
+ DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
+ yesno(intel_dp_source_supports_hbr2(dev)),
+ yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
/* Intermediate frequency support */
if (is_edp(intel_dp) &&
@@ -4007,22 +4103,30 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
return intel_dp->is_mst;
}
-static void intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
+static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
+ int ret = 0;
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) {
DRM_DEBUG_KMS("Sink CRC couldn't be stopped properly\n");
- return;
+ ret = -EIO;
+ goto out;
}
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK,
- buf & ~DP_TEST_SINK_START) < 0)
+ buf & ~DP_TEST_SINK_START) < 0) {
DRM_DEBUG_KMS("Sink CRC couldn't be stopped properly\n");
+ ret = -EIO;
+ goto out;
+ }
+ intel_dp->sink_crc.started = false;
+ out:
hsw_enable_ips(intel_crtc);
+ return ret;
}
static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
@@ -4030,6 +4134,13 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
+ int ret;
+
+ if (intel_dp->sink_crc.started) {
+ ret = intel_dp_sink_crc_stop(intel_dp);
+ if (ret)
+ return ret;
+ }
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0)
return -EIO;
@@ -4037,6 +4148,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
if (!(buf & DP_TEST_CRC_SUPPORTED))
return -ENOTTY;
+ intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK;
+
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
return -EIO;
@@ -4048,6 +4161,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
return -EIO;
}
+ intel_dp->sink_crc.started = true;
return 0;
}
@@ -4057,38 +4171,55 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
struct drm_device *dev = dig_port->base.base.dev;
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
- int test_crc_count;
+ int count, ret;
int attempts = 6;
- int ret;
+ bool old_equal_new;
ret = intel_dp_sink_crc_start(intel_dp);
if (ret)
return ret;
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) {
- ret = -EIO;
- goto stop;
- }
-
- test_crc_count = buf & DP_TEST_COUNT_MASK;
-
do {
+ intel_wait_for_vblank(dev, intel_crtc->pipe);
+
if (drm_dp_dpcd_readb(&intel_dp->aux,
DP_TEST_SINK_MISC, &buf) < 0) {
ret = -EIO;
goto stop;
}
- intel_wait_for_vblank(dev, intel_crtc->pipe);
- } while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count);
+ count = buf & DP_TEST_COUNT_MASK;
+
+ /*
+ * Count might be reset during the loop. In this case
+ * last known count needs to be reset as well.
+ */
+ if (count == 0)
+ intel_dp->sink_crc.last_count = 0;
+
+ if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
+ ret = -EIO;
+ goto stop;
+ }
+
+ old_equal_new = (count == intel_dp->sink_crc.last_count &&
+ !memcmp(intel_dp->sink_crc.last_crc, crc,
+ 6 * sizeof(u8)));
+
+ } while (--attempts && (count == 0 || old_equal_new));
+
+ intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK;
+ memcpy(intel_dp->sink_crc.last_crc, crc, 6 * sizeof(u8));
if (attempts == 0) {
- DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n");
- ret = -ETIMEDOUT;
- goto stop;
+ if (old_equal_new) {
+ DRM_DEBUG_KMS("Unreliable Sink CRC counter: Current returned CRC is identical to the previous one\n");
+ } else {
+ DRM_ERROR("Panel is unable to calculate any CRC after 6 vblanks\n");
+ ret = -ETIMEDOUT;
+ goto stop;
+ }
}
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0)
- ret = -EIO;
stop:
intel_dp_sink_crc_stop(intel_dp);
return ret;
@@ -4248,10 +4379,10 @@ go_again:
if (bret == true) {
/* check link status - esi[10] = 0x200c */
- if (intel_dp->active_mst_links && !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
+ if (intel_dp->active_mst_links &&
+ !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
intel_dp_start_link_train(intel_dp);
- intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
}
@@ -4342,7 +4473,6 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
intel_encoder->base.name);
intel_dp_start_link_train(intel_dp);
- intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
}
}
@@ -4410,58 +4540,164 @@ edp_detect(struct intel_dp *intel_dp)
return status;
}
-static enum drm_connector_status
-ironlake_dp_detect(struct intel_dp *intel_dp)
+static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
+ struct intel_digital_port *port)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ u32 bit;
- if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
- return connector_status_disconnected;
+ switch (port->port) {
+ case PORT_A:
+ return true;
+ case PORT_B:
+ bit = SDE_PORTB_HOTPLUG;
+ break;
+ case PORT_C:
+ bit = SDE_PORTC_HOTPLUG;
+ break;
+ case PORT_D:
+ bit = SDE_PORTD_HOTPLUG;
+ break;
+ default:
+ MISSING_CASE(port->port);
+ return false;
+ }
- return intel_dp_detect_dpcd(intel_dp);
+ return I915_READ(SDEISR) & bit;
+}
+
+static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv,
+ struct intel_digital_port *port)
+{
+ u32 bit;
+
+ switch (port->port) {
+ case PORT_A:
+ return true;
+ case PORT_B:
+ bit = SDE_PORTB_HOTPLUG_CPT;
+ break;
+ case PORT_C:
+ bit = SDE_PORTC_HOTPLUG_CPT;
+ break;
+ case PORT_D:
+ bit = SDE_PORTD_HOTPLUG_CPT;
+ break;
+ case PORT_E:
+ bit = SDE_PORTE_HOTPLUG_SPT;
+ break;
+ default:
+ MISSING_CASE(port->port);
+ return false;
+ }
+
+ return I915_READ(SDEISR) & bit;
+}
+
+static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv,
+ struct intel_digital_port *port)
+{
+ u32 bit;
+
+ switch (port->port) {
+ case PORT_B:
+ bit = PORTB_HOTPLUG_LIVE_STATUS_G4X;
+ break;
+ case PORT_C:
+ bit = PORTC_HOTPLUG_LIVE_STATUS_G4X;
+ break;
+ case PORT_D:
+ bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
+ break;
+ default:
+ MISSING_CASE(port->port);
+ return false;
+ }
+
+ return I915_READ(PORT_HOTPLUG_STAT) & bit;
}
-static int g4x_digital_port_connected(struct drm_device *dev,
+static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv,
+ struct intel_digital_port *port)
+{
+ u32 bit;
+
+ switch (port->port) {
+ case PORT_B:
+ bit = PORTB_HOTPLUG_LIVE_STATUS_VLV;
+ break;
+ case PORT_C:
+ bit = PORTC_HOTPLUG_LIVE_STATUS_VLV;
+ break;
+ case PORT_D:
+ bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
+ break;
+ default:
+ MISSING_CASE(port->port);
+ return false;
+ }
+
+ return I915_READ(PORT_HOTPLUG_STAT) & bit;
+}
+
+static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv,
struct intel_digital_port *intel_dig_port)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t bit;
+ struct intel_encoder *intel_encoder = &intel_dig_port->base;
+ enum port port;
+ u32 bit;
- if (IS_VALLEYVIEW(dev)) {
- switch (intel_dig_port->port) {
- case PORT_B:
- bit = PORTB_HOTPLUG_LIVE_STATUS_VLV;
- break;
- case PORT_C:
- bit = PORTC_HOTPLUG_LIVE_STATUS_VLV;
- break;
- case PORT_D:
- bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
- break;
- default:
- return -EINVAL;
- }
- } else {
- switch (intel_dig_port->port) {
- case PORT_B:
- bit = PORTB_HOTPLUG_LIVE_STATUS_G4X;
- break;
- case PORT_C:
- bit = PORTC_HOTPLUG_LIVE_STATUS_G4X;
- break;
- case PORT_D:
- bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
- break;
- default:
- return -EINVAL;
- }
+ intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port);
+ switch (port) {
+ case PORT_A:
+ bit = BXT_DE_PORT_HP_DDIA;
+ break;
+ case PORT_B:
+ bit = BXT_DE_PORT_HP_DDIB;
+ break;
+ case PORT_C:
+ bit = BXT_DE_PORT_HP_DDIC;
+ break;
+ default:
+ MISSING_CASE(port);
+ return false;
}
- if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
- return 0;
- return 1;
+ return I915_READ(GEN8_DE_PORT_ISR) & bit;
+}
+
+/*
+ * intel_digital_port_connected - is the specified port connected?
+ * @dev_priv: i915 private structure
+ * @port: the port to test
+ *
+ * Return %true if @port is connected, %false otherwise.
+ */
+bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
+ struct intel_digital_port *port)
+{
+ if (HAS_PCH_IBX(dev_priv))
+ return ibx_digital_port_connected(dev_priv, port);
+ if (HAS_PCH_SPLIT(dev_priv))
+ return cpt_digital_port_connected(dev_priv, port);
+ else if (IS_BROXTON(dev_priv))
+ return bxt_digital_port_connected(dev_priv, port);
+ else if (IS_VALLEYVIEW(dev_priv))
+ return vlv_digital_port_connected(dev_priv, port);
+ else
+ return g4x_digital_port_connected(dev_priv, port);
+}
+
+static enum drm_connector_status
+ironlake_dp_detect(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+
+ if (!intel_digital_port_connected(dev_priv, intel_dig_port))
+ return connector_status_disconnected;
+
+ return intel_dp_detect_dpcd(intel_dp);
}
static enum drm_connector_status
@@ -4469,7 +4705,6 @@ g4x_dp_detect(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- int ret;
/* Can't disconnect eDP, but you can close the lid... */
if (is_edp(intel_dp)) {
@@ -4481,10 +4716,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)
return status;
}
- ret = g4x_digital_port_connected(dev, intel_dig_port);
- if (ret == -EINVAL)
- return connector_status_unknown;
- else if (ret == 0)
+ if (!intel_digital_port_connected(dev->dev_private, intel_dig_port))
return connector_status_disconnected;
return intel_dp_detect_dpcd(intel_dp);
@@ -4728,7 +4960,7 @@ intel_dp_set_property(struct drm_connector *connector,
if (property == dev_priv->broadcast_rgb_property) {
bool old_auto = intel_dp->color_range_auto;
- uint32_t old_range = intel_dp->color_range;
+ bool old_range = intel_dp->limited_color_range;
switch (val) {
case INTEL_BROADCAST_RGB_AUTO:
@@ -4736,18 +4968,18 @@ intel_dp_set_property(struct drm_connector *connector,
break;
case INTEL_BROADCAST_RGB_FULL:
intel_dp->color_range_auto = false;
- intel_dp->color_range = 0;
+ intel_dp->limited_color_range = false;
break;
case INTEL_BROADCAST_RGB_LIMITED:
intel_dp->color_range_auto = false;
- intel_dp->color_range = DP_COLOR_RANGE_16_235;
+ intel_dp->limited_color_range = true;
break;
default:
return -EINVAL;
}
if (old_auto == intel_dp->color_range_auto &&
- old_range == intel_dp->color_range)
+ old_range == intel_dp->limited_color_range)
return 0;
goto done;
@@ -4947,13 +5179,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
/* indicate that we need to restart link training */
intel_dp->train_set_valid = false;
- if (HAS_PCH_SPLIT(dev)) {
- if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
- goto mst_fail;
- } else {
- if (g4x_digital_port_connected(dev, intel_dig_port) != 1)
- goto mst_fail;
- }
+ if (!intel_digital_port_connected(dev_priv, intel_dig_port))
+ goto mst_fail;
if (!intel_dp_get_dpcd(intel_dp)) {
goto mst_fail;
@@ -5028,6 +5255,13 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port)
[PORT_E] = DVO_PORT_DPE,
};
+ /*
+ * eDP not supported on g4x. so bail out early just
+ * for a bit extra safety in case the VBT is bonkers.
+ */
+ if (INTEL_INFO(dev)->gen < 5)
+ return false;
+
if (port == PORT_A)
return true;
@@ -5302,7 +5536,6 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
struct intel_dp *intel_dp = dev_priv->drrs.dp;
struct intel_crtc_state *config = NULL;
struct intel_crtc *intel_crtc = NULL;
- u32 reg, val;
enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
if (refresh_rate <= 0) {
@@ -5364,9 +5597,10 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
DRM_ERROR("Unsupported refreshrate type\n");
}
} else if (INTEL_INFO(dev)->gen > 6) {
- reg = PIPECONF(intel_crtc->config->cpu_transcoder);
- val = I915_READ(reg);
+ u32 reg = PIPECONF(intel_crtc->config->cpu_transcoder);
+ u32 val;
+ val = I915_READ(reg);
if (index > DRRS_HIGH_RR) {
if (IS_VALLEYVIEW(dev))
val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
@@ -5765,7 +5999,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
- intel_connector->panel.backlight_power = intel_edp_backlight_power;
+ intel_connector->panel.backlight.power = intel_edp_backlight_power;
intel_panel_setup_backlight(connector, pipe);
return true;
@@ -5853,6 +6087,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
break;
case PORT_B:
intel_encoder->hpd_pin = HPD_PORT_B;
+ if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0))
+ intel_encoder->hpd_pin = HPD_PORT_A;
break;
case PORT_C:
intel_encoder->hpd_pin = HPD_PORT_C;
@@ -5932,10 +6168,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
return;
intel_connector = intel_connector_alloc();
- if (!intel_connector) {
- kfree(intel_dig_port);
- return;
- }
+ if (!intel_connector)
+ goto err_connector_alloc;
intel_encoder = &intel_dig_port->base;
encoder = &intel_encoder->base;
@@ -5953,6 +6187,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->pre_enable = chv_pre_enable_dp;
intel_encoder->enable = vlv_enable_dp;
intel_encoder->post_disable = chv_post_disable_dp;
+ intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
} else if (IS_VALLEYVIEW(dev)) {
intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
intel_encoder->pre_enable = vlv_pre_enable_dp;
@@ -5982,11 +6217,18 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
dev_priv->hotplug.irq_port[port] = intel_dig_port;
- if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
- drm_encoder_cleanup(encoder);
- kfree(intel_dig_port);
- kfree(intel_connector);
- }
+ if (!intel_dp_init_connector(intel_dig_port, intel_connector))
+ goto err_init_connector;
+
+ return;
+
+err_init_connector:
+ drm_encoder_cleanup(encoder);
+ kfree(intel_connector);
+err_connector_alloc:
+ kfree(intel_dig_port);
+
+ return;
}
void intel_dp_mst_suspend(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 6ade06888432..0639275fc471 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -39,8 +39,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_atomic_state *state;
int bpp, i;
- int lane_count, slots, rate;
- struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+ int lane_count, slots;
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
struct drm_connector *drm_connector;
struct intel_connector *connector, *found = NULL;
struct drm_connector_state *connector_state;
@@ -56,20 +56,11 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
*/
lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
- rate = intel_dp_max_link_rate(intel_dp);
- if (intel_dp->num_sink_rates) {
- intel_dp->link_bw = 0;
- intel_dp->rate_select = intel_dp_rate_select(intel_dp, rate);
- } else {
- intel_dp->link_bw = drm_dp_link_rate_to_bw_code(rate);
- intel_dp->rate_select = 0;
- }
-
- intel_dp->lane_count = lane_count;
+ pipe_config->lane_count = lane_count;
pipe_config->pipe_bpp = 24;
- pipe_config->port_clock = rate;
+ pipe_config->port_clock = intel_dp_max_link_rate(intel_dp);
state = pipe_config->base.state;
@@ -87,7 +78,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
return false;
}
- mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
+ mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp);
pipe_config->pbn = mst_pbn;
slots = drm_dp_find_vcpi_slots(&intel_dp->mst_mgr, mst_pbn);
@@ -184,6 +175,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
if (intel_dp->active_mst_links == 0) {
enum port port = intel_ddi_get_encoder_port(encoder);
+ intel_dp_set_link_params(intel_dp, intel_crtc->config);
+
/* FIXME: add support for SKL */
if (INTEL_INFO(dev)->gen < 9)
I915_WRITE(PORT_CLK_SEL(port),
@@ -195,7 +188,6 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
intel_dp_start_link_train(intel_dp);
- intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
}
@@ -286,6 +278,10 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
break;
}
pipe_config->base.adjusted_mode.flags |= flags;
+
+ pipe_config->lane_count =
+ ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
+
intel_dp_get_m_n(crtc, pipe_config);
intel_ddi_clock_get(&intel_dig_port->base, pipe_config);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2b9e6f9775c5..0598932ce623 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -142,6 +142,7 @@ struct intel_encoder {
void (*mode_set)(struct intel_encoder *intel_encoder);
void (*disable)(struct intel_encoder *);
void (*post_disable)(struct intel_encoder *);
+ void (*post_pll_disable)(struct intel_encoder *);
/* Read out the current hw state of this connector, returning true if
* the encoder is active. If the encoder is enabled it also set the pipe
* it is connected to in the pipe parameter. */
@@ -178,12 +179,22 @@ struct intel_panel {
bool active_low_pwm;
/* PWM chip */
+ bool util_pin_active_low; /* bxt+ */
+ u8 controller; /* bxt+ only */
struct pwm_device *pwm;
struct backlight_device *device;
- } backlight;
- void (*backlight_power)(struct intel_connector *, bool enable);
+ /* Connector and platform specific backlight functions */
+ int (*setup)(struct intel_connector *connector, enum pipe pipe);
+ uint32_t (*get)(struct intel_connector *connector);
+ void (*set)(struct intel_connector *connector, uint32_t level);
+ void (*disable)(struct intel_connector *connector);
+ void (*enable)(struct intel_connector *connector);
+ uint32_t (*hz_to_pwm)(struct intel_connector *connector,
+ uint32_t hz);
+ void (*power)(struct intel_connector *, bool enable);
+ } backlight;
};
struct intel_connector {
@@ -337,6 +348,8 @@ struct intel_crtc_state {
#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
unsigned long quirks;
+ bool update_pipe;
+
/* Pipe source size (ie. panel fitter input size)
* All planes will be positioned inside this space,
* and get clipped at the edges. */
@@ -423,6 +436,8 @@ struct intel_crtc_state {
/* Used by SDVO (and if we ever fix it, HDMI). */
unsigned pixel_multiplier;
+ uint8_t lane_count;
+
/* Panel fitter controls for gen2-gen4 + VLV */
struct {
u32 control;
@@ -532,6 +547,8 @@ struct intel_crtc {
* gen4+ this only adjusts up to a tile, offsets within a tile are
* handled in the hw itself (with the TILEOFF register). */
unsigned long dspaddr_offset;
+ int adjusted_x;
+ int adjusted_y;
struct drm_i915_gem_object *cursor_bo;
uint32_t cursor_addr;
@@ -560,7 +577,13 @@ struct intel_crtc {
int scanline_offset;
- unsigned start_vbl_count;
+ struct {
+ unsigned start_vbl_count;
+ ktime_t start_vbl_time;
+ int min_vbl, max_vbl;
+ int scanline_start;
+ } debug;
+
struct intel_crtc_atomic_commit atomic;
/* scalers available on this crtc */
@@ -657,19 +680,20 @@ struct cxsr_latency {
struct intel_hdmi {
u32 hdmi_reg;
int ddc_bus;
- uint32_t color_range;
+ bool limited_color_range;
bool color_range_auto;
bool has_hdmi_sink;
bool has_audio;
enum hdmi_force_audio force_audio;
bool rgb_quant_range_selectable;
enum hdmi_picture_aspect aspect_ratio;
+ struct intel_connector *attached_connector;
void (*write_infoframe)(struct drm_encoder *encoder,
enum hdmi_infoframe_type type,
const void *frame, ssize_t len);
void (*set_infoframes)(struct drm_encoder *encoder,
bool enable,
- struct drm_display_mode *adjusted_mode);
+ const struct drm_display_mode *adjusted_mode);
bool (*infoframe_enabled)(struct drm_encoder *encoder);
};
@@ -696,23 +720,29 @@ enum link_m_n_set {
M2_N2
};
+struct sink_crc {
+ bool started;
+ u8 last_crc[6];
+ int last_count;
+};
+
struct intel_dp {
uint32_t output_reg;
uint32_t aux_ch_ctl_reg;
uint32_t DP;
+ int link_rate;
+ uint8_t lane_count;
bool has_audio;
enum hdmi_force_audio force_audio;
- uint32_t color_range;
+ bool limited_color_range;
bool color_range_auto;
- uint8_t link_bw;
- uint8_t rate_select;
- uint8_t lane_count;
uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
uint8_t num_sink_rates;
int sink_rates[DP_MAX_SUPPORTED_RATES];
+ struct sink_crc sink_crc;
struct drm_dp_aux aux;
uint8_t train_set[4];
int panel_power_up_delay;
@@ -735,7 +765,6 @@ struct intel_dp {
enum pipe pps_pipe;
struct edp_power_seq pps_delays;
- bool use_tps3;
bool can_mst; /* this port supports mst */
bool is_mst;
int active_mst_links;
@@ -770,6 +799,7 @@ struct intel_digital_port {
struct intel_dp dp;
struct intel_hdmi hdmi;
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
+ bool release_cl2_override;
};
struct intel_dp_mst_encoder {
@@ -779,7 +809,7 @@ struct intel_dp_mst_encoder {
void *port; /* store this opaque as its illegal to dereference it */
};
-static inline int
+static inline enum dpio_channel
vlv_dport_to_channel(struct intel_digital_port *dport)
{
switch (dport->port) {
@@ -793,7 +823,21 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
}
}
-static inline int
+static inline enum dpio_phy
+vlv_dport_to_phy(struct intel_digital_port *dport)
+{
+ switch (dport->port) {
+ case PORT_B:
+ case PORT_C:
+ return DPIO_PHY0;
+ case PORT_D:
+ return DPIO_PHY1;
+ default:
+ BUG();
+ }
+}
+
+static inline enum dpio_channel
vlv_pipe_to_channel(enum pipe pipe)
{
switch (pipe) {
@@ -834,8 +878,8 @@ struct intel_unpin_work {
u32 flip_count;
u32 gtt_offset;
struct drm_i915_gem_request *flip_queued_req;
- int flip_queued_vblank;
- int flip_ready_vblank;
+ u32 flip_queued_vblank;
+ u32 flip_ready_vblank;
bool enable_stall_check;
};
@@ -987,6 +1031,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
extern const struct drm_plane_funcs intel_plane_funcs;
bool intel_has_pending_fb_unpin(struct drm_device *dev);
int intel_pch_rawclk(struct drm_device *dev);
+int intel_hrawclk(struct drm_device *dev);
void intel_mark_busy(struct drm_device *dev);
void intel_mark_idle(struct drm_device *dev);
void intel_crtc_restore_mode(struct drm_crtc *crtc);
@@ -995,8 +1040,6 @@ void intel_encoder_destroy(struct drm_encoder *encoder);
int intel_connector_init(struct intel_connector *);
struct intel_connector *intel_connector_alloc(void);
bool intel_connector_get_hw_state(struct intel_connector *connector);
-bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
- struct intel_digital_port *port);
void intel_connector_attach_encoder(struct intel_connector *connector,
struct intel_encoder *encoder);
struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
@@ -1038,10 +1081,8 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe);
void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
void intel_check_page_flip(struct drm_device *dev, int pipe);
int intel_prepare_plane_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state);
void intel_cleanup_plane_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *old_state);
int intel_plane_atomic_get_property(struct drm_plane *plane,
const struct drm_plane_state *state,
@@ -1056,7 +1097,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
unsigned int
intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
- uint64_t fb_format_modifier);
+ uint64_t fb_format_modifier, unsigned int plane);
static inline bool
intel_rotation_90_or_270(unsigned int rotation)
@@ -1137,7 +1178,9 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj);
+ struct drm_i915_gem_object *obj,
+ unsigned int plane);
+
u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
u32 skl_plane_ctl_rotation(unsigned int rotation);
@@ -1155,8 +1198,9 @@ void assert_csr_loaded(struct drm_i915_private *dev_priv);
void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector);
+void intel_dp_set_link_params(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *pipe_config);
void intel_dp_start_link_train(struct intel_dp *intel_dp);
-void intel_dp_complete_link_train(struct intel_dp *intel_dp);
void intel_dp_stop_link_train(struct intel_dp *intel_dp);
void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
void intel_dp_encoder_destroy(struct drm_encoder *encoder);
@@ -1185,6 +1229,8 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp);
void intel_edp_drrs_invalidate(struct drm_device *dev,
unsigned frontbuffer_bits);
void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
+bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
+ struct intel_digital_port *port);
void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
/* intel_dp_mst.c */
@@ -1263,6 +1309,7 @@ int intel_connector_update_modes(struct drm_connector *connector,
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
void intel_attach_force_audio_property(struct drm_connector *connector);
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
+void intel_attach_aspect_ratio_property(struct drm_connector *connector);
/* intel_overlay.c */
@@ -1295,7 +1342,6 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
void intel_panel_enable_backlight(struct intel_connector *connector);
void intel_panel_disable_backlight(struct intel_connector *connector);
void intel_panel_destroy_backlight(struct drm_connector *connector);
-void intel_panel_init_backlight_funcs(struct drm_device *dev);
enum drm_connector_status intel_panel_detect(struct drm_device *dev);
extern struct drm_display_mode *intel_find_panel_downclock(
struct drm_device *dev,
@@ -1339,6 +1385,12 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
+void chv_phy_powergate_lanes(struct intel_encoder *encoder,
+ bool override, unsigned int mask);
+bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+ enum dpio_channel ch, bool override);
+
+
/* intel_pm.c */
void intel_init_clock_gating(struct drm_device *dev);
void intel_suspend_hw(struct drm_device *dev);
@@ -1384,9 +1436,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-void intel_pipe_update_start(struct intel_crtc *crtc,
- uint32_t *start_vbl_count);
-void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
+void intel_pipe_update_start(struct intel_crtc *crtc);
+void intel_pipe_update_end(struct intel_crtc *crtc);
/* intel_tv.c */
void intel_tv_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 32a6c7184ca4..170ae6f4866e 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -282,58 +282,46 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
return true;
}
-static void intel_dsi_port_enable(struct intel_encoder *encoder)
+static void bxt_dsi_device_ready(struct intel_encoder *encoder)
{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
enum port port;
- u32 temp;
+ u32 val;
- if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
- temp = I915_READ(VLV_CHICKEN_3);
- temp &= ~PIXEL_OVERLAP_CNT_MASK |
- intel_dsi->pixel_overlap <<
- PIXEL_OVERLAP_CNT_SHIFT;
- I915_WRITE(VLV_CHICKEN_3, temp);
- }
+ DRM_DEBUG_KMS("\n");
+ /* Exit Low power state in 4 steps*/
for_each_dsi_port(port, intel_dsi->ports) {
- temp = I915_READ(MIPI_PORT_CTRL(port));
- temp &= ~LANE_CONFIGURATION_MASK;
- temp &= ~DUAL_LINK_MODE_MASK;
- if (intel_dsi->ports == ((1 << PORT_A) | (1 << PORT_C))) {
- temp |= (intel_dsi->dual_link - 1)
- << DUAL_LINK_MODE_SHIFT;
- temp |= intel_crtc->pipe ?
- LANE_CONFIGURATION_DUAL_LINK_B :
- LANE_CONFIGURATION_DUAL_LINK_A;
- }
- /* assert ip_tg_enable signal */
- I915_WRITE(MIPI_PORT_CTRL(port), temp | DPI_ENABLE);
- POSTING_READ(MIPI_PORT_CTRL(port));
- }
-}
+ /* 1. Enable MIPI PHY transparent latch */
+ val = I915_READ(BXT_MIPI_PORT_CTRL(port));
+ I915_WRITE(BXT_MIPI_PORT_CTRL(port), val | LP_OUTPUT_HOLD);
+ usleep_range(2000, 2500);
-static void intel_dsi_port_disable(struct intel_encoder *encoder)
-{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
- enum port port;
- u32 temp;
+ /* 2. Enter ULPS */
+ val = I915_READ(MIPI_DEVICE_READY(port));
+ val &= ~ULPS_STATE_MASK;
+ val |= (ULPS_STATE_ENTER | DEVICE_READY);
+ I915_WRITE(MIPI_DEVICE_READY(port), val);
+ usleep_range(2, 3);
+
+ /* 3. Exit ULPS */
+ val = I915_READ(MIPI_DEVICE_READY(port));
+ val &= ~ULPS_STATE_MASK;
+ val |= (ULPS_STATE_EXIT | DEVICE_READY);
+ I915_WRITE(MIPI_DEVICE_READY(port), val);
+ usleep_range(1000, 1500);
- for_each_dsi_port(port, intel_dsi->ports) {
- /* de-assert ip_tg_enable signal */
- temp = I915_READ(MIPI_PORT_CTRL(port));
- I915_WRITE(MIPI_PORT_CTRL(port), temp & ~DPI_ENABLE);
- POSTING_READ(MIPI_PORT_CTRL(port));
+ /* Clear ULPS and set device ready */
+ val = I915_READ(MIPI_DEVICE_READY(port));
+ val &= ~ULPS_STATE_MASK;
+ val |= DEVICE_READY;
+ I915_WRITE(MIPI_DEVICE_READY(port), val);
}
}
-static void intel_dsi_device_ready(struct intel_encoder *encoder)
+static void vlv_dsi_device_ready(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
@@ -372,6 +360,75 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
}
}
+static void intel_dsi_device_ready(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+
+ if (IS_VALLEYVIEW(dev))
+ vlv_dsi_device_ready(encoder);
+ else if (IS_BROXTON(dev))
+ bxt_dsi_device_ready(encoder);
+}
+
+static void intel_dsi_port_enable(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ enum port port;
+ u32 temp;
+ u32 port_ctrl;
+
+ if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
+ temp = I915_READ(VLV_CHICKEN_3);
+ temp &= ~PIXEL_OVERLAP_CNT_MASK |
+ intel_dsi->pixel_overlap <<
+ PIXEL_OVERLAP_CNT_SHIFT;
+ I915_WRITE(VLV_CHICKEN_3, temp);
+ }
+
+ for_each_dsi_port(port, intel_dsi->ports) {
+ port_ctrl = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) :
+ MIPI_PORT_CTRL(port);
+
+ temp = I915_READ(port_ctrl);
+
+ temp &= ~LANE_CONFIGURATION_MASK;
+ temp &= ~DUAL_LINK_MODE_MASK;
+
+ if (intel_dsi->ports == ((1 << PORT_A) | (1 << PORT_C))) {
+ temp |= (intel_dsi->dual_link - 1)
+ << DUAL_LINK_MODE_SHIFT;
+ temp |= intel_crtc->pipe ?
+ LANE_CONFIGURATION_DUAL_LINK_B :
+ LANE_CONFIGURATION_DUAL_LINK_A;
+ }
+ /* assert ip_tg_enable signal */
+ I915_WRITE(port_ctrl, temp | DPI_ENABLE);
+ POSTING_READ(port_ctrl);
+ }
+}
+
+static void intel_dsi_port_disable(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ enum port port;
+ u32 temp;
+ u32 port_ctrl;
+
+ for_each_dsi_port(port, intel_dsi->ports) {
+ /* de-assert ip_tg_enable signal */
+ port_ctrl = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) :
+ MIPI_PORT_CTRL(port);
+ temp = I915_READ(port_ctrl);
+ I915_WRITE(port_ctrl, temp & ~DPI_ENABLE);
+ POSTING_READ(port_ctrl);
+ }
+}
+
static void intel_dsi_enable(struct intel_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
@@ -419,19 +476,24 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
msleep(intel_dsi->panel_on_delay);
- /* Disable DPOunit clock gating, can stall pipe
- * and we need DPLL REFA always enabled */
- tmp = I915_READ(DPLL(pipe));
- tmp |= DPLL_REF_CLK_ENABLE_VLV;
- I915_WRITE(DPLL(pipe), tmp);
-
- /* update the hw state for DPLL */
- intel_crtc->config->dpll_hw_state.dpll = DPLL_INTEGRATED_REF_CLK_VLV |
- DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
-
- tmp = I915_READ(DSPCLK_GATE_D);
- tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
- I915_WRITE(DSPCLK_GATE_D, tmp);
+ if (IS_VALLEYVIEW(dev)) {
+ /*
+ * Disable DPOunit clock gating, can stall pipe
+ * and we need DPLL REFA always enabled
+ */
+ tmp = I915_READ(DPLL(pipe));
+ tmp |= DPLL_REF_CLK_ENABLE_VLV;
+ I915_WRITE(DPLL(pipe), tmp);
+
+ /* update the hw state for DPLL */
+ intel_crtc->config->dpll_hw_state.dpll =
+ DPLL_INTEGRATED_REF_CLK_VLV |
+ DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+
+ tmp = I915_READ(DSPCLK_GATE_D);
+ tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
+ I915_WRITE(DSPCLK_GATE_D, tmp);
+ }
/* put device in ready state */
intel_dsi_device_ready(encoder);
@@ -495,12 +557,7 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
/* Panel commands can be sent when clock is in LP11 */
I915_WRITE(MIPI_DEVICE_READY(port), 0x0);
- temp = I915_READ(MIPI_CTRL(port));
- temp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
- I915_WRITE(MIPI_CTRL(port), temp |
- intel_dsi->escape_clk_div <<
- ESCAPE_CLOCK_DIVIDER_SHIFT);
-
+ intel_dsi_reset_clocks(encoder, port);
I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
temp = I915_READ(MIPI_DSI_FUNC_PRG(port));
@@ -519,10 +576,12 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
{
+ struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
enum port port;
u32 val;
+ u32 port_ctrl = 0;
DRM_DEBUG_KMS("\n");
for_each_dsi_port(port, intel_dsi->ports) {
@@ -539,25 +598,29 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
ULPS_STATE_ENTER);
usleep_range(2000, 2500);
+ if (IS_BROXTON(dev))
+ port_ctrl = BXT_MIPI_PORT_CTRL(port);
+ else if (IS_VALLEYVIEW(dev))
+ /* Common bit for both MIPI Port A & MIPI Port C */
+ port_ctrl = MIPI_PORT_CTRL(PORT_A);
+
/* Wait till Clock lanes are in LP-00 state for MIPI Port A
* only. MIPI Port C has no similar bit for checking
*/
- if (wait_for(((I915_READ(MIPI_PORT_CTRL(PORT_A)) & AFE_LATCHOUT)
- == 0x00000), 30))
+ if (wait_for(((I915_READ(port_ctrl) & AFE_LATCHOUT)
+ == 0x00000), 30))
DRM_ERROR("DSI LP not going Low\n");
- /* Disable MIPI PHY transparent latch
- * Common bit for both MIPI Port A & MIPI Port C
- */
- val = I915_READ(MIPI_PORT_CTRL(PORT_A));
- I915_WRITE(MIPI_PORT_CTRL(PORT_A), val & ~LP_OUTPUT_HOLD);
+ /* Disable MIPI PHY transparent latch */
+ val = I915_READ(port_ctrl);
+ I915_WRITE(port_ctrl, val & ~LP_OUTPUT_HOLD);
usleep_range(1000, 1500);
I915_WRITE(MIPI_DEVICE_READY(port), 0x00);
usleep_range(2000, 2500);
}
- vlv_disable_dsi_pll(encoder);
+ intel_disable_dsi_pll(encoder);
}
static void intel_dsi_post_disable(struct intel_encoder *encoder)
@@ -593,7 +656,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
struct drm_device *dev = encoder->base.dev;
enum intel_display_power_domain power_domain;
- u32 dpi_enabled, func;
+ u32 dpi_enabled, func, ctrl_reg;
enum port port;
DRM_DEBUG_KMS("\n");
@@ -605,8 +668,9 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
/* XXX: this only works for one DSI output */
for_each_dsi_port(port, intel_dsi->ports) {
func = I915_READ(MIPI_DSI_FUNC_PRG(port));
- dpi_enabled = I915_READ(MIPI_PORT_CTRL(port)) &
- DPI_ENABLE;
+ ctrl_reg = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) :
+ MIPI_PORT_CTRL(port);
+ dpi_enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
/* Due to some hardware limitations on BYT, MIPI Port C DPI
* Enable bit does not get set. To check whether DSI Port C
@@ -631,7 +695,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
static void intel_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
- u32 pclk;
+ u32 pclk = 0;
DRM_DEBUG_KMS("\n");
/*
@@ -640,7 +704,11 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
*/
pipe_config->dpll_hw_state.dpll_md = 0;
- pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
+ if (IS_BROXTON(encoder->base.dev))
+ pclk = bxt_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
+ else if (IS_VALLEYVIEW(encoder->base.dev))
+ pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
+
if (!pclk)
return;
@@ -654,6 +722,7 @@ intel_dsi_mode_valid(struct drm_connector *connector,
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+ int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
DRM_DEBUG_KMS("\n");
@@ -667,6 +736,8 @@ intel_dsi_mode_valid(struct drm_connector *connector,
return MODE_PANEL;
if (mode->vdisplay > fixed_mode->vdisplay)
return MODE_PANEL;
+ if (fixed_mode->clock > max_dotclk)
+ return MODE_CLOCK_HIGH;
}
return MODE_OK;
@@ -695,7 +766,7 @@ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
}
static void set_dsi_timings(struct drm_encoder *encoder,
- const struct drm_display_mode *mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -707,10 +778,10 @@ static void set_dsi_timings(struct drm_encoder *encoder,
u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
- hactive = mode->hdisplay;
- hfp = mode->hsync_start - mode->hdisplay;
- hsync = mode->hsync_end - mode->hsync_start;
- hbp = mode->htotal - mode->hsync_end;
+ hactive = adjusted_mode->crtc_hdisplay;
+ hfp = adjusted_mode->crtc_hsync_start - adjusted_mode->crtc_hdisplay;
+ hsync = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+ hbp = adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_end;
if (intel_dsi->dual_link) {
hactive /= 2;
@@ -721,9 +792,9 @@ static void set_dsi_timings(struct drm_encoder *encoder,
hbp /= 2;
}
- vfp = mode->vsync_start - mode->vdisplay;
- vsync = mode->vsync_end - mode->vsync_start;
- vbp = mode->vtotal - mode->vsync_end;
+ vfp = adjusted_mode->crtc_vsync_start - adjusted_mode->crtc_vdisplay;
+ vsync = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
+ vbp = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_end;
/* horizontal values are in terms of high speed byte clock */
hactive = txbyteclkhs(hactive, bpp, lane_count,
@@ -734,6 +805,21 @@ static void set_dsi_timings(struct drm_encoder *encoder,
hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio);
for_each_dsi_port(port, intel_dsi->ports) {
+ if (IS_BROXTON(dev)) {
+ /*
+ * Program hdisplay and vdisplay on MIPI transcoder.
+ * This is different from calculated hactive and
+ * vactive, as they are calculated per channel basis,
+ * whereas these values should be based on resolution.
+ */
+ I915_WRITE(BXT_MIPI_TRANS_HACTIVE(port),
+ adjusted_mode->crtc_hdisplay);
+ I915_WRITE(BXT_MIPI_TRANS_VACTIVE(port),
+ adjusted_mode->crtc_vdisplay);
+ I915_WRITE(BXT_MIPI_TRANS_VTOTAL(port),
+ adjusted_mode->crtc_vtotal);
+ }
+
I915_WRITE(MIPI_HACTIVE_AREA_COUNT(port), hactive);
I915_WRITE(MIPI_HFP_COUNT(port), hfp);
@@ -756,8 +842,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
- struct drm_display_mode *adjusted_mode =
- &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
enum port port;
unsigned int bpp = intel_crtc->config->pipe_bpp;
u32 val, tmp;
@@ -765,7 +850,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
DRM_DEBUG_KMS("pipe %c\n", pipe_name(intel_crtc->pipe));
- mode_hdisplay = adjusted_mode->hdisplay;
+ mode_hdisplay = adjusted_mode->crtc_hdisplay;
if (intel_dsi->dual_link) {
mode_hdisplay /= 2;
@@ -774,16 +859,39 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
}
for_each_dsi_port(port, intel_dsi->ports) {
- /* escape clock divider, 20MHz, shared for A and C.
- * device ready must be off when doing this! txclkesc? */
- tmp = I915_READ(MIPI_CTRL(PORT_A));
- tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
- I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1);
-
- /* read request priority is per pipe */
- tmp = I915_READ(MIPI_CTRL(port));
- tmp &= ~READ_REQUEST_PRIORITY_MASK;
- I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH);
+ if (IS_VALLEYVIEW(dev)) {
+ /*
+ * escape clock divider, 20MHz, shared for A and C.
+ * device ready must be off when doing this! txclkesc?
+ */
+ tmp = I915_READ(MIPI_CTRL(PORT_A));
+ tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
+ I915_WRITE(MIPI_CTRL(PORT_A), tmp |
+ ESCAPE_CLOCK_DIVIDER_1);
+
+ /* read request priority is per pipe */
+ tmp = I915_READ(MIPI_CTRL(port));
+ tmp &= ~READ_REQUEST_PRIORITY_MASK;
+ I915_WRITE(MIPI_CTRL(port), tmp |
+ READ_REQUEST_PRIORITY_HIGH);
+ } else if (IS_BROXTON(dev)) {
+ /*
+ * FIXME:
+ * BXT can connect any PIPE to any MIPI port.
+ * Select the pipe based on the MIPI port read from
+ * VBT for now. Pick PIPE A for MIPI port A and C
+ * for port C.
+ */
+ tmp = I915_READ(MIPI_CTRL(port));
+ tmp &= ~BXT_PIPE_SELECT_MASK;
+
+ if (port == PORT_A)
+ tmp |= BXT_PIPE_SELECT_A;
+ else if (port == PORT_C)
+ tmp |= BXT_PIPE_SELECT_C;
+
+ I915_WRITE(MIPI_CTRL(port), tmp);
+ }
/* XXX: why here, why like this? handling in irq handler?! */
I915_WRITE(MIPI_INTR_STAT(port), 0xffffffff);
@@ -792,7 +900,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
I915_WRITE(MIPI_DPHY_PARAM(port), intel_dsi->dphy_reg);
I915_WRITE(MIPI_DPI_RESOLUTION(port),
- adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
+ adjusted_mode->crtc_vdisplay << VERTICAL_ADDRESS_SHIFT |
mode_hdisplay << HORIZONTAL_ADDRESS_SHIFT);
}
@@ -838,15 +946,15 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
if (is_vid_mode(intel_dsi) &&
intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
I915_WRITE(MIPI_HS_TX_TIMEOUT(port),
- txbyteclkhs(adjusted_mode->htotal, bpp,
- intel_dsi->lane_count,
- intel_dsi->burst_mode_ratio) + 1);
+ txbyteclkhs(adjusted_mode->crtc_htotal, bpp,
+ intel_dsi->lane_count,
+ intel_dsi->burst_mode_ratio) + 1);
} else {
I915_WRITE(MIPI_HS_TX_TIMEOUT(port),
- txbyteclkhs(adjusted_mode->vtotal *
- adjusted_mode->htotal,
- bpp, intel_dsi->lane_count,
- intel_dsi->burst_mode_ratio) + 1);
+ txbyteclkhs(adjusted_mode->crtc_vtotal *
+ adjusted_mode->crtc_htotal,
+ bpp, intel_dsi->lane_count,
+ intel_dsi->burst_mode_ratio) + 1);
}
I915_WRITE(MIPI_LP_RX_TIMEOUT(port), intel_dsi->lp_rx_timeout);
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(port),
@@ -860,6 +968,17 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
I915_WRITE(MIPI_INIT_COUNT(port),
txclkesc(intel_dsi->escape_clk_div, 100));
+ if (IS_BROXTON(dev) && (!intel_dsi->dual_link)) {
+ /*
+ * BXT spec says write MIPI_INIT_COUNT for
+ * both the ports, even if only one is
+ * getting used. So write the other port
+ * if not in dual link mode.
+ */
+ I915_WRITE(MIPI_INIT_COUNT(port ==
+ PORT_A ? PORT_C : PORT_A),
+ intel_dsi->init_count);
+ }
/* recovery disables */
I915_WRITE(MIPI_EOT_DISABLE(port), tmp);
@@ -911,8 +1030,8 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
DRM_DEBUG_KMS("\n");
intel_dsi_prepare(encoder);
+ intel_enable_dsi_pll(encoder);
- vlv_enable_dsi_pll(encoder);
}
static enum drm_connector_status
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index 42a68593e32a..e6cb25239941 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -124,9 +124,12 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
return container_of(encoder, struct intel_dsi, base.base);
}
-extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
-extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
+extern void intel_enable_dsi_pll(struct intel_encoder *encoder);
+extern void intel_disable_dsi_pll(struct intel_encoder *encoder);
extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp);
+extern u32 bxt_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp);
+extern void intel_dsi_reset_clocks(struct intel_encoder *encoder,
+ enum port port);
struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id);
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index c6a8975b128f..cb3cf3986212 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -246,7 +246,7 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl);
}
-void vlv_enable_dsi_pll(struct intel_encoder *encoder)
+static void vlv_enable_dsi_pll(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
u32 tmp;
@@ -276,7 +276,7 @@ void vlv_enable_dsi_pll(struct intel_encoder *encoder)
DRM_DEBUG_KMS("DSI PLL locked\n");
}
-void vlv_disable_dsi_pll(struct intel_encoder *encoder)
+static void vlv_disable_dsi_pll(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
u32 tmp;
@@ -293,6 +293,26 @@ void vlv_disable_dsi_pll(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->sb_lock);
}
+static void bxt_disable_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ u32 val;
+
+ DRM_DEBUG_KMS("\n");
+
+ val = I915_READ(BXT_DSI_PLL_ENABLE);
+ val &= ~BXT_DSI_PLL_DO_ENABLE;
+ I915_WRITE(BXT_DSI_PLL_ENABLE, val);
+
+ /*
+ * PLL lock should deassert within 200us.
+ * Wait up to 1ms before timing out.
+ */
+ if (wait_for((I915_READ(BXT_DSI_PLL_ENABLE)
+ & BXT_DSI_PLL_LOCKED) == 0, 1))
+ DRM_ERROR("Timeout waiting for PLL lock deassertion\n");
+}
+
static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
{
int bpp = dsi_pixel_format_bpp(pixel_format);
@@ -363,3 +383,222 @@ u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp)
return pclk;
}
+
+u32 bxt_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp)
+{
+ u32 pclk;
+ u32 dsi_clk;
+ u32 dsi_ratio;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+
+ /* Divide by zero */
+ if (!pipe_bpp) {
+ DRM_ERROR("Invalid BPP(0)\n");
+ return 0;
+ }
+
+ dsi_ratio = I915_READ(BXT_DSI_PLL_CTL) &
+ BXT_DSI_PLL_RATIO_MASK;
+
+ /* Invalid DSI ratio ? */
+ if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN ||
+ dsi_ratio > BXT_DSI_PLL_RATIO_MAX) {
+ DRM_ERROR("Invalid DSI pll ratio(%u) programmed\n", dsi_ratio);
+ return 0;
+ }
+
+ dsi_clk = (dsi_ratio * BXT_REF_CLOCK_KHZ) / 2;
+
+ /* pixel_format and pipe_bpp should agree */
+ assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp);
+
+ pclk = DIV_ROUND_CLOSEST(dsi_clk * intel_dsi->lane_count, pipe_bpp);
+
+ DRM_DEBUG_DRIVER("Calculated pclk=%u\n", pclk);
+ return pclk;
+}
+
+static void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
+{
+ u32 temp;
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
+ temp = I915_READ(MIPI_CTRL(port));
+ temp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
+ I915_WRITE(MIPI_CTRL(port), temp |
+ intel_dsi->escape_clk_div <<
+ ESCAPE_CLOCK_DIVIDER_SHIFT);
+}
+
+/* Program BXT Mipi clocks and dividers */
+static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port)
+{
+ u32 tmp;
+ u32 divider;
+ u32 dsi_rate;
+ u32 pll_ratio;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Clear old configurations */
+ tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
+ tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
+ tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port));
+ tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port));
+ tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port));
+
+ /* Get the current DSI rate(actual) */
+ pll_ratio = I915_READ(BXT_DSI_PLL_CTL) &
+ BXT_DSI_PLL_RATIO_MASK;
+ dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2;
+
+ /* Max possible output of clock is 39.5 MHz, program value -1 */
+ divider = (dsi_rate / BXT_MAX_VAR_OUTPUT_KHZ) - 1;
+ tmp |= BXT_MIPI_ESCLK_VAR_DIV(port, divider);
+
+ /*
+ * Tx escape clock must be as close to 20MHz possible, but should
+ * not exceed it. Hence select divide by 2
+ */
+ tmp |= BXT_MIPI_TX_ESCLK_8XDIV_BY2(port);
+
+ tmp |= BXT_MIPI_RX_ESCLK_8X_BY3(port);
+
+ I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
+}
+
+static bool bxt_configure_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ u8 dsi_ratio;
+ u32 dsi_clk;
+ u32 val;
+
+ dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
+ intel_dsi->lane_count);
+
+ /*
+ * From clock diagram, to get PLL ratio divider, divide double of DSI
+ * link rate (i.e., 2*8x=16x frequency value) by ref clock. Make sure to
+ * round 'up' the result
+ */
+ dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ);
+ if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN ||
+ dsi_ratio > BXT_DSI_PLL_RATIO_MAX) {
+ DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n");
+ return false;
+ }
+
+ /*
+ * Program DSI ratio and Select MIPIC and MIPIA PLL output as 8x
+ * Spec says both have to be programmed, even if one is not getting
+ * used. Configure MIPI_CLOCK_CTL dividers in modeset
+ */
+ val = I915_READ(BXT_DSI_PLL_CTL);
+ val &= ~BXT_DSI_PLL_PVD_RATIO_MASK;
+ val &= ~BXT_DSI_FREQ_SEL_MASK;
+ val &= ~BXT_DSI_PLL_RATIO_MASK;
+ val |= (dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2);
+
+ /* As per recommendation from hardware team,
+ * Prog PVD ratio =1 if dsi ratio <= 50
+ */
+ if (dsi_ratio <= 50) {
+ val &= ~BXT_DSI_PLL_PVD_RATIO_MASK;
+ val |= BXT_DSI_PLL_PVD_RATIO_1;
+ }
+
+ I915_WRITE(BXT_DSI_PLL_CTL, val);
+ POSTING_READ(BXT_DSI_PLL_CTL);
+
+ return true;
+}
+
+static void bxt_enable_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ enum port port;
+ u32 val;
+
+ DRM_DEBUG_KMS("\n");
+
+ val = I915_READ(BXT_DSI_PLL_ENABLE);
+
+ if (val & BXT_DSI_PLL_DO_ENABLE) {
+ WARN(1, "DSI PLL already enabled. Disabling it.\n");
+ val &= ~BXT_DSI_PLL_DO_ENABLE;
+ I915_WRITE(BXT_DSI_PLL_ENABLE, val);
+ }
+
+ /* Configure PLL vales */
+ if (!bxt_configure_dsi_pll(encoder)) {
+ DRM_ERROR("Configure DSI PLL failed, abort PLL enable\n");
+ return;
+ }
+
+ /* Program TX, RX, Dphy clocks */
+ for_each_dsi_port(port, intel_dsi->ports)
+ bxt_dsi_program_clocks(encoder->base.dev, port);
+
+ /* Enable DSI PLL */
+ val = I915_READ(BXT_DSI_PLL_ENABLE);
+ val |= BXT_DSI_PLL_DO_ENABLE;
+ I915_WRITE(BXT_DSI_PLL_ENABLE, val);
+
+ /* Timeout and fail if PLL not locked */
+ if (wait_for(I915_READ(BXT_DSI_PLL_ENABLE) & BXT_DSI_PLL_LOCKED, 1)) {
+ DRM_ERROR("Timed out waiting for DSI PLL to lock\n");
+ return;
+ }
+
+ DRM_DEBUG_KMS("DSI PLL locked\n");
+}
+
+void intel_enable_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+
+ if (IS_VALLEYVIEW(dev))
+ vlv_enable_dsi_pll(encoder);
+ else if (IS_BROXTON(dev))
+ bxt_enable_dsi_pll(encoder);
+}
+
+void intel_disable_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+
+ if (IS_VALLEYVIEW(dev))
+ vlv_disable_dsi_pll(encoder);
+ else if (IS_BROXTON(dev))
+ bxt_disable_dsi_pll(encoder);
+}
+
+static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
+{
+ u32 tmp;
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Clear old configurations */
+ tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
+ tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
+ tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port));
+ tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port));
+ tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port));
+ I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
+ I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
+}
+
+void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
+{
+ struct drm_device *dev = encoder->base.dev;
+
+ if (IS_BROXTON(dev))
+ bxt_dsi_reset_clocks(encoder, port);
+ else if (IS_VALLEYVIEW(dev))
+ vlv_dsi_reset_clocks(encoder, port);
+}
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index dc532bb61d22..8492053e0ff0 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -97,7 +97,8 @@ struct intel_dvo {
struct intel_dvo_device dev;
- struct drm_display_mode *panel_fixed_mode;
+ struct intel_connector *attached_connector;
+
bool panel_wants_dither;
};
@@ -201,19 +202,28 @@ intel_dvo_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+ const struct drm_display_mode *fixed_mode =
+ to_intel_connector(connector)->panel.fixed_mode;
+ int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ int target_clock = mode->clock;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
/* XXX: Validate clock range */
- if (intel_dvo->panel_fixed_mode) {
- if (mode->hdisplay > intel_dvo->panel_fixed_mode->hdisplay)
+ if (fixed_mode) {
+ if (mode->hdisplay > fixed_mode->hdisplay)
return MODE_PANEL;
- if (mode->vdisplay > intel_dvo->panel_fixed_mode->vdisplay)
+ if (mode->vdisplay > fixed_mode->vdisplay)
return MODE_PANEL;
+
+ target_clock = fixed_mode->clock;
}
+ if (target_clock > max_dotclk)
+ return MODE_CLOCK_HIGH;
+
return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
}
@@ -221,6 +231,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
+ const struct drm_display_mode *fixed_mode =
+ intel_dvo->attached_connector->panel.fixed_mode;
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
/* If we have timings from the BIOS for the panel, put them in
@@ -228,21 +240,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
* with the panel scaling set up to source from the H/VDisplay
* of the original mode.
*/
- if (intel_dvo->panel_fixed_mode != NULL) {
-#define C(x) adjusted_mode->x = intel_dvo->panel_fixed_mode->x
- C(hdisplay);
- C(hsync_start);
- C(hsync_end);
- C(htotal);
- C(vdisplay);
- C(vsync_start);
- C(vsync_end);
- C(vtotal);
- C(clock);
-#undef C
-
- drm_mode_set_crtcinfo(adjusted_mode, 0);
- }
+ if (fixed_mode)
+ intel_fixed_panel_mode(fixed_mode, adjusted_mode);
return true;
}
@@ -252,7 +251,7 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder)
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
- struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
int pipe = crtc->pipe;
u32 dvo_val;
@@ -286,11 +285,11 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder)
dvo_val |= DVO_VSYNC_ACTIVE_HIGH;
/*I915_WRITE(DVOB_SRCDIM,
- (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
- (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
+ (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+ (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
I915_WRITE(dvo_srcdim_reg,
- (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
- (adjusted_mode->vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));
+ (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+ (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));
/*I915_WRITE(DVOB, dvo_val);*/
I915_WRITE(dvo_reg, dvo_val);
}
@@ -311,8 +310,9 @@ intel_dvo_detect(struct drm_connector *connector, bool force)
static int intel_dvo_get_modes(struct drm_connector *connector)
{
- struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct drm_i915_private *dev_priv = connector->dev->dev_private;
+ const struct drm_display_mode *fixed_mode =
+ to_intel_connector(connector)->panel.fixed_mode;
/* We should probably have an i2c driver get_modes function for those
* devices which will have a fixed set of modes determined by the chip
@@ -324,9 +324,9 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
if (!list_empty(&connector->probed_modes))
return 1;
- if (intel_dvo->panel_fixed_mode != NULL) {
+ if (fixed_mode) {
struct drm_display_mode *mode;
- mode = drm_mode_duplicate(connector->dev, intel_dvo->panel_fixed_mode);
+ mode = drm_mode_duplicate(connector->dev, fixed_mode);
if (mode) {
drm_mode_probed_add(connector, mode);
return 1;
@@ -339,6 +339,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
static void intel_dvo_destroy(struct drm_connector *connector)
{
drm_connector_cleanup(connector);
+ intel_panel_fini(&to_intel_connector(connector)->panel);
kfree(connector);
}
@@ -365,8 +366,6 @@ static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
if (intel_dvo->dev.dev_ops->destroy)
intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev);
- kfree(intel_dvo->panel_fixed_mode);
-
intel_encoder_destroy(encoder);
}
@@ -431,6 +430,8 @@ void intel_dvo_init(struct drm_device *dev)
return;
}
+ intel_dvo->attached_connector = intel_connector;
+
intel_encoder = &intel_dvo->base;
drm_encoder_init(dev, &intel_encoder->base,
&intel_dvo_enc_funcs, encoder_type);
@@ -535,8 +536,9 @@ void intel_dvo_init(struct drm_device *dev)
* headers, likely), so for now, just get the current
* mode being output through DVO.
*/
- intel_dvo->panel_fixed_mode =
- intel_dvo_get_current_mode(connector);
+ intel_panel_init(&intel_connector->panel,
+ intel_dvo_get_current_mode(connector),
+ NULL);
intel_dvo->panel_wants_dither = true;
}
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 1f97fb548c2a..cf47352b7b8e 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -41,6 +41,24 @@
#include "intel_drv.h"
#include "i915_drv.h"
+static inline bool fbc_supported(struct drm_i915_private *dev_priv)
+{
+ return dev_priv->fbc.enable_fbc != NULL;
+}
+
+/*
+ * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
+ * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
+ * origin so the x and y offsets can actually fit the registers. As a
+ * consequence, the fence doesn't really start exactly at the display plane
+ * address we program because it starts at the real start of the buffer, so we
+ * have to take this into consideration here.
+ */
+static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
+{
+ return crtc->base.y - crtc->adjusted_y;
+}
+
static void i8xx_fbc_disable(struct drm_i915_private *dev_priv)
{
u32 fbc_ctl;
@@ -88,7 +106,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc)
/* Clear old tags */
for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
- I915_WRITE(FBC_TAG + (i * 4), 0);
+ I915_WRITE(FBC_TAG(i), 0);
if (IS_GEN4(dev_priv)) {
u32 fbc_ctl2;
@@ -97,7 +115,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc)
fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
fbc_ctl2 |= FBC_CTL_PLANE(crtc->plane);
I915_WRITE(FBC_CONTROL2, fbc_ctl2);
- I915_WRITE(FBC_FENCE_OFF, crtc->base.y);
+ I915_WRITE(FBC_FENCE_OFF, get_crtc_fence_y_offset(crtc));
}
/* enable it... */
@@ -135,7 +153,7 @@ static void g4x_fbc_enable(struct intel_crtc *crtc)
dpfc_ctl |= DPFC_CTL_LIMIT_1X;
dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
- I915_WRITE(DPFC_FENCE_YOFF, crtc->base.y);
+ I915_WRITE(DPFC_FENCE_YOFF, get_crtc_fence_y_offset(crtc));
/* enable it... */
I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
@@ -177,6 +195,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
u32 dpfc_ctl;
int threshold = dev_priv->fbc.threshold;
+ unsigned int y_offset;
dev_priv->fbc.enabled = true;
@@ -200,7 +219,8 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
if (IS_GEN5(dev_priv))
dpfc_ctl |= obj->fence_reg;
- I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->base.y);
+ y_offset = get_crtc_fence_y_offset(crtc);
+ I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset);
I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
/* enable it... */
I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
@@ -208,7 +228,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
if (IS_GEN6(dev_priv)) {
I915_WRITE(SNB_DPFC_CTL_SA,
SNB_CPU_FENCE_ENABLE | obj->fence_reg);
- I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y);
+ I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset);
}
intel_fbc_nuke(dev_priv);
@@ -272,23 +292,23 @@ static void gen7_fbc_enable(struct intel_crtc *crtc)
if (dev_priv->fbc.false_color)
dpfc_ctl |= FBC_CTL_FALSE_COLOR;
- I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
-
if (IS_IVYBRIDGE(dev_priv)) {
/* WaFbcAsynchFlipDisableFbcQueue:ivb */
I915_WRITE(ILK_DISPLAY_CHICKEN1,
I915_READ(ILK_DISPLAY_CHICKEN1) |
ILK_FBCQ_DIS);
- } else {
+ } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
I915_WRITE(CHICKEN_PIPESL_1(crtc->pipe),
I915_READ(CHICKEN_PIPESL_1(crtc->pipe)) |
HSW_FBCQ_DIS);
}
+ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
+
I915_WRITE(SNB_DPFC_CTL_SA,
SNB_CPU_FENCE_ENABLE | obj->fence_reg);
- I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y);
+ I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc));
intel_fbc_nuke(dev_priv);
@@ -308,6 +328,18 @@ bool intel_fbc_enabled(struct drm_i915_private *dev_priv)
return dev_priv->fbc.enabled;
}
+static void intel_fbc_enable(struct intel_crtc *crtc,
+ const struct drm_framebuffer *fb)
+{
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+ dev_priv->fbc.enable_fbc(crtc);
+
+ dev_priv->fbc.crtc = crtc;
+ dev_priv->fbc.fb_id = fb->base.id;
+ dev_priv->fbc.y = crtc->base.y;
+}
+
static void intel_fbc_work_fn(struct work_struct *__work)
{
struct intel_fbc_work *work =
@@ -321,13 +353,8 @@ static void intel_fbc_work_fn(struct work_struct *__work)
/* Double check that we haven't switched fb without cancelling
* the prior work.
*/
- if (crtc_fb == work->fb) {
- dev_priv->fbc.enable_fbc(work->crtc);
-
- dev_priv->fbc.crtc = work->crtc;
- dev_priv->fbc.fb_id = crtc_fb->base.id;
- dev_priv->fbc.y = work->crtc->base.y;
- }
+ if (crtc_fb == work->fb)
+ intel_fbc_enable(work->crtc, work->fb);
dev_priv->fbc.fbc_work = NULL;
}
@@ -361,7 +388,7 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
dev_priv->fbc.fbc_work = NULL;
}
-static void intel_fbc_enable(struct intel_crtc *crtc)
+static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
{
struct intel_fbc_work *work;
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -373,7 +400,7 @@ static void intel_fbc_enable(struct intel_crtc *crtc)
work = kzalloc(sizeof(*work), GFP_KERNEL);
if (work == NULL) {
DRM_ERROR("Failed to allocate FBC work structure\n");
- dev_priv->fbc.enable_fbc(crtc);
+ intel_fbc_enable(crtc, crtc->base.primary->fb);
return;
}
@@ -417,7 +444,7 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
*/
void intel_fbc_disable(struct drm_i915_private *dev_priv)
{
- if (!dev_priv->fbc.enable_fbc)
+ if (!fbc_supported(dev_priv))
return;
mutex_lock(&dev_priv->fbc.lock);
@@ -435,7 +462,7 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
- if (!dev_priv->fbc.enable_fbc)
+ if (!fbc_supported(dev_priv))
return;
mutex_lock(&dev_priv->fbc.lock);
@@ -473,6 +500,12 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason)
return "rotation unsupported";
case FBC_IN_DBG_MASTER:
return "Kernel debugger is active";
+ case FBC_BAD_STRIDE:
+ return "framebuffer stride not supported";
+ case FBC_PIXEL_RATE:
+ return "pixel rate is too big";
+ case FBC_PIXEL_FORMAT:
+ return "pixel format is invalid";
default:
MISSING_CASE(reason);
return "unknown reason";
@@ -542,6 +575,16 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
{
int compression_threshold = 1;
int ret;
+ u64 end;
+
+ /* The FBC hardware for BDW/SKL doesn't have access to the stolen
+ * reserved range size, so it always assumes the maximum (8mb) is used.
+ * If we enable FBC using a CFB on that memory range we'll get FIFO
+ * underruns, even if that range is not reserved by the BIOS. */
+ if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+ end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
+ else
+ end = dev_priv->gtt.stolen_usable_size;
/* HACK: This code depends on what we will do in *_enable_fbc. If that
* code changes, this code needs to change as well.
@@ -551,7 +594,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
*/
/* Try to over-allocate to reduce reallocations and fragmentation. */
- ret = i915_gem_stolen_insert_node(dev_priv, node, size <<= 1, 4096);
+ ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1,
+ 4096, 0, end);
if (ret == 0)
return compression_threshold;
@@ -561,7 +605,8 @@ again:
(fb_cpp == 2 && compression_threshold == 2))
return 0;
- ret = i915_gem_stolen_insert_node(dev_priv, node, size >>= 1, 4096);
+ ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
+ 4096, 0, end);
if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
return 0;
} else if (ret) {
@@ -613,8 +658,9 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size,
dev_priv->fbc.uncompressed_size = size;
- DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
- size);
+ DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
+ dev_priv->fbc.compressed_fb.size,
+ dev_priv->fbc.threshold);
return 0;
@@ -644,7 +690,7 @@ static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
{
- if (!dev_priv->fbc.enable_fbc)
+ if (!fbc_supported(dev_priv))
return;
mutex_lock(&dev_priv->fbc.lock);
@@ -652,16 +698,134 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
mutex_unlock(&dev_priv->fbc.lock);
}
-static int intel_fbc_setup_cfb(struct drm_i915_private *dev_priv, int size,
- int fb_cpp)
+/*
+ * For SKL+, the plane source size used by the hardware is based on the value we
+ * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value
+ * we wrote to PIPESRC.
+ */
+static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc,
+ int *width, int *height)
{
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(crtc->base.primary->state);
+ int w, h;
+
+ if (intel_rotation_90_or_270(plane_state->base.rotation)) {
+ w = drm_rect_height(&plane_state->src) >> 16;
+ h = drm_rect_width(&plane_state->src) >> 16;
+ } else {
+ w = drm_rect_width(&plane_state->src) >> 16;
+ h = drm_rect_height(&plane_state->src) >> 16;
+ }
+
+ if (width)
+ *width = w;
+ if (height)
+ *height = h;
+}
+
+static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+ struct drm_framebuffer *fb = crtc->base.primary->fb;
+ int lines;
+
+ intel_fbc_get_plane_source_size(crtc, NULL, &lines);
+ if (INTEL_INFO(dev_priv)->gen >= 7)
+ lines = min(lines, 2048);
+
+ return lines * fb->pitches[0];
+}
+
+static int intel_fbc_setup_cfb(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+ struct drm_framebuffer *fb = crtc->base.primary->fb;
+ int size, cpp;
+
+ size = intel_fbc_calculate_cfb_size(crtc);
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+
if (size <= dev_priv->fbc.uncompressed_size)
return 0;
/* Release any current block */
__intel_fbc_cleanup_cfb(dev_priv);
- return intel_fbc_alloc_cfb(dev_priv, size, fb_cpp);
+ return intel_fbc_alloc_cfb(dev_priv, size, cpp);
+}
+
+static bool stride_is_valid(struct drm_i915_private *dev_priv,
+ unsigned int stride)
+{
+ /* These should have been caught earlier. */
+ WARN_ON(stride < 512);
+ WARN_ON((stride & (64 - 1)) != 0);
+
+ /* Below are the additional FBC restrictions. */
+
+ if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
+ return stride == 4096 || stride == 8192;
+
+ if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048)
+ return false;
+
+ if (stride > 16384)
+ return false;
+
+ return true;
+}
+
+static bool pixel_format_is_valid(struct drm_framebuffer *fb)
+{
+ struct drm_device *dev = fb->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ switch (fb->pixel_format) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ return true;
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_RGB565:
+ /* 16bpp not supported on gen2 */
+ if (IS_GEN2(dev))
+ return false;
+ /* WaFbcOnly1to1Ratio:ctg */
+ if (IS_G4X(dev_priv))
+ return false;
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*
+ * For some reason, the hardware tracking starts looking at whatever we
+ * programmed as the display plane base address register. It does not look at
+ * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y}
+ * variables instead of just looking at the pipe/plane size.
+ */
+static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+ unsigned int effective_w, effective_h, max_w, max_h;
+
+ if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
+ max_w = 4096;
+ max_h = 4096;
+ } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
+ max_w = 4096;
+ max_h = 2048;
+ } else {
+ max_w = 2048;
+ max_h = 1536;
+ }
+
+ intel_fbc_get_plane_source_size(crtc, &effective_w, &effective_h);
+ effective_w += crtc->adjusted_x;
+ effective_h += crtc->adjusted_y;
+
+ return effective_w <= max_w && effective_h <= max_h;
}
/**
@@ -690,7 +854,6 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
const struct drm_display_mode *adjusted_mode;
- unsigned int max_width, max_height;
WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
@@ -739,21 +902,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
goto out_disable;
}
- if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
- max_width = 4096;
- max_height = 4096;
- } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
- max_width = 4096;
- max_height = 2048;
- } else {
- max_width = 2048;
- max_height = 1536;
- }
- if (intel_crtc->config->pipe_src_w > max_width ||
- intel_crtc->config->pipe_src_h > max_height) {
+ if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) {
set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE);
goto out_disable;
}
+
if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) &&
intel_crtc->plane != PLANE_A) {
set_no_fbc_reason(dev_priv, FBC_BAD_PLANE);
@@ -774,14 +927,31 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
goto out_disable;
}
+ if (!stride_is_valid(dev_priv, fb->pitches[0])) {
+ set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE);
+ goto out_disable;
+ }
+
+ if (!pixel_format_is_valid(fb)) {
+ set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT);
+ goto out_disable;
+ }
+
/* If the kernel debugger is active, always disable compression */
if (in_dbg_master()) {
set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER);
goto out_disable;
}
- if (intel_fbc_setup_cfb(dev_priv, obj->base.size,
- drm_format_plane_cpp(fb->pixel_format, 0))) {
+ /* WaFbcExceedCdClockThreshold:hsw,bdw */
+ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
+ ilk_pipe_pixel_rate(intel_crtc->config) >=
+ dev_priv->cdclk_freq * 95 / 100) {
+ set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE);
+ goto out_disable;
+ }
+
+ if (intel_fbc_setup_cfb(intel_crtc)) {
set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL);
goto out_disable;
}
@@ -824,7 +994,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
__intel_fbc_disable(dev_priv);
}
- intel_fbc_enable(intel_crtc);
+ intel_fbc_schedule_enable(intel_crtc);
dev_priv->fbc.no_fbc_reason = FBC_OK;
return;
@@ -845,7 +1015,7 @@ out_disable:
*/
void intel_fbc_update(struct drm_i915_private *dev_priv)
{
- if (!dev_priv->fbc.enable_fbc)
+ if (!fbc_supported(dev_priv))
return;
mutex_lock(&dev_priv->fbc.lock);
@@ -859,7 +1029,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
{
unsigned int fbc_bits;
- if (!dev_priv->fbc.enable_fbc)
+ if (!fbc_supported(dev_priv))
return;
if (origin == ORIGIN_GTT)
@@ -886,7 +1056,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
void intel_fbc_flush(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits, enum fb_op_origin origin)
{
- if (!dev_priv->fbc.enable_fbc)
+ if (!fbc_supported(dev_priv))
return;
if (origin == ORIGIN_GTT)
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 8c6a6fa46005..4fd5fdfef6bd 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -121,8 +121,9 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
container_of(helper, struct intel_fbdev, helper);
struct drm_framebuffer *fb;
struct drm_device *dev = helper->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_mode_fb_cmd2 mode_cmd = {};
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj = NULL;
int size, ret;
/* we don't do packed 24bpp */
@@ -139,7 +140,12 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
size = mode_cmd.pitches[0] * mode_cmd.height;
size = PAGE_ALIGN(size);
- obj = i915_gem_object_create_stolen(dev, size);
+
+ /* If the FB is too big, just don't use it since fbdev is not very
+ * important and we should probably use that space with FBC or other
+ * features. */
+ if (size * 2 < dev_priv->gtt.stolen_usable_size)
+ obj = i915_gem_object_create_stolen(dev, size);
if (obj == NULL)
obj = i915_gem_alloc_object(dev, size);
if (!obj) {
@@ -263,7 +269,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
- DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n",
+ DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n",
fb->width, fb->height,
i915_gem_obj_ggtt_offset(obj), obj);
@@ -541,16 +547,13 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
struct intel_crtc *intel_crtc;
unsigned int max_size = 0;
- if (!i915.fastboot)
- return false;
-
/* Find the largest fb */
for_each_crtc(dev, crtc) {
struct drm_i915_gem_object *obj =
intel_fb_obj(crtc->primary->state->fb);
intel_crtc = to_intel_crtc(crtc);
- if (!intel_crtc->active || !obj) {
+ if (!crtc->state->active || !obj) {
DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
pipe_name(intel_crtc->pipe));
continue;
@@ -575,7 +578,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
intel_crtc = to_intel_crtc(crtc);
- if (!intel_crtc->active) {
+ if (!crtc->state->active) {
DRM_DEBUG_KMS("pipe %c not active, skipping\n",
pipe_name(intel_crtc->pipe));
continue;
@@ -638,7 +641,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
for_each_crtc(dev, crtc) {
intel_crtc = to_intel_crtc(crtc);
- if (!intel_crtc->active)
+ if (!crtc->state->active)
continue;
WARN(!crtc->primary->fb,
@@ -689,6 +692,8 @@ int intel_fbdev_init(struct drm_device *dev)
return ret;
}
+ ifbdev->helper.atomic = true;
+
dev_priv->fbdev = ifbdev;
INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
new file mode 100644
index 000000000000..081d5f648d26
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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.
+ *
+ */
+#ifndef _INTEL_GUC_H_
+#define _INTEL_GUC_H_
+
+#include "intel_guc_fwif.h"
+#include "i915_guc_reg.h"
+
+struct i915_guc_client {
+ struct drm_i915_gem_object *client_obj;
+ struct intel_context *owner;
+ struct intel_guc *guc;
+ uint32_t priority;
+ uint32_t ctx_index;
+
+ uint32_t proc_desc_offset;
+ uint32_t doorbell_offset;
+ uint32_t cookie;
+ uint16_t doorbell_id;
+ uint16_t padding; /* Maintain alignment */
+
+ uint32_t wq_offset;
+ uint32_t wq_size;
+
+ spinlock_t wq_lock; /* Protects all data below */
+ uint32_t wq_tail;
+
+ /* GuC submission statistics & status */
+ uint64_t submissions[I915_NUM_RINGS];
+ uint32_t q_fail;
+ uint32_t b_fail;
+ int retcode;
+};
+
+enum intel_guc_fw_status {
+ GUC_FIRMWARE_FAIL = -1,
+ GUC_FIRMWARE_NONE = 0,
+ GUC_FIRMWARE_PENDING,
+ GUC_FIRMWARE_SUCCESS
+};
+
+/*
+ * This structure encapsulates all the data needed during the process
+ * of fetching, caching, and loading the firmware image into the GuC.
+ */
+struct intel_guc_fw {
+ struct drm_device * guc_dev;
+ const char * guc_fw_path;
+ size_t guc_fw_size;
+ struct drm_i915_gem_object * guc_fw_obj;
+ enum intel_guc_fw_status guc_fw_fetch_status;
+ enum intel_guc_fw_status guc_fw_load_status;
+
+ uint16_t guc_fw_major_wanted;
+ uint16_t guc_fw_minor_wanted;
+ uint16_t guc_fw_major_found;
+ uint16_t guc_fw_minor_found;
+};
+
+struct intel_guc {
+ struct intel_guc_fw guc_fw;
+
+ uint32_t log_flags;
+ struct drm_i915_gem_object *log_obj;
+
+ struct drm_i915_gem_object *ctx_pool_obj;
+ struct ida ctx_ids;
+
+ struct i915_guc_client *execbuf_client;
+
+ spinlock_t host2guc_lock; /* Protects all data below */
+
+ DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS);
+ uint32_t db_cacheline; /* Cyclic counter mod pagesize */
+
+ /* Action status & statistics */
+ uint64_t action_count; /* Total commands issued */
+ uint32_t action_cmd; /* Last command word */
+ uint32_t action_status; /* Last return status */
+ uint32_t action_fail; /* Total number of failures */
+ int32_t action_err; /* Last error code */
+
+ uint64_t submissions[I915_NUM_RINGS];
+ uint32_t last_seqno[I915_NUM_RINGS];
+};
+
+/* intel_guc_loader.c */
+extern void intel_guc_ucode_init(struct drm_device *dev);
+extern int intel_guc_ucode_load(struct drm_device *dev);
+extern void intel_guc_ucode_fini(struct drm_device *dev);
+extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status);
+extern int intel_guc_suspend(struct drm_device *dev);
+extern int intel_guc_resume(struct drm_device *dev);
+
+/* i915_guc_submission.c */
+int i915_guc_submission_init(struct drm_device *dev);
+int i915_guc_submission_enable(struct drm_device *dev);
+int i915_guc_submit(struct i915_guc_client *client,
+ struct drm_i915_gem_request *rq);
+void i915_guc_submission_disable(struct drm_device *dev);
+void i915_guc_submission_fini(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 18d7f20936c8..593d2f585978 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -32,17 +32,16 @@
* EDITING THIS FILE IS THEREFORE NOT RECOMMENDED - YOUR CHANGES MAY BE LOST.
*/
-#define GFXCORE_FAMILY_GEN8 11
#define GFXCORE_FAMILY_GEN9 12
-#define GFXCORE_FAMILY_FORCE_ULONG 0x7fffffff
+#define GFXCORE_FAMILY_UNKNOWN 0x7fffffff
-#define GUC_CTX_PRIORITY_CRITICAL 0
+#define GUC_CTX_PRIORITY_KMD_HIGH 0
#define GUC_CTX_PRIORITY_HIGH 1
-#define GUC_CTX_PRIORITY_NORMAL 2
-#define GUC_CTX_PRIORITY_LOW 3
+#define GUC_CTX_PRIORITY_KMD_NORMAL 2
+#define GUC_CTX_PRIORITY_NORMAL 3
#define GUC_MAX_GPU_CONTEXTS 1024
-#define GUC_INVALID_CTX_ID (GUC_MAX_GPU_CONTEXTS + 1)
+#define GUC_INVALID_CTX_ID GUC_MAX_GPU_CONTEXTS
/* Work queue item header definitions */
#define WQ_STATUS_ACTIVE 1
@@ -76,6 +75,7 @@
#define GUC_CTX_DESC_ATTR_RESET (1 << 4)
#define GUC_CTX_DESC_ATTR_WQLOCKED (1 << 5)
#define GUC_CTX_DESC_ATTR_PCH (1 << 6)
+#define GUC_CTX_DESC_ATTR_TERMINATED (1 << 7)
/* The guc control data is 10 DWORDs */
#define GUC_CTL_CTXINFO 0
@@ -108,6 +108,7 @@
#define GUC_CTL_DISABLE_SCHEDULER (1 << 4)
#define GUC_CTL_PREEMPTION_LOG (1 << 5)
#define GUC_CTL_ENABLE_SLPC (1 << 7)
+#define GUC_CTL_RESET_ON_PREMPT_FAILURE (1 << 8)
#define GUC_CTL_DEBUG 8
#define GUC_LOG_VERBOSITY_SHIFT 0
#define GUC_LOG_VERBOSITY_LOW (0 << GUC_LOG_VERBOSITY_SHIFT)
@@ -117,8 +118,9 @@
/* Verbosity range-check limits, without the shift */
#define GUC_LOG_VERBOSITY_MIN 0
#define GUC_LOG_VERBOSITY_MAX 3
+#define GUC_CTL_RSRVD 9
-#define GUC_CTL_MAX_DWORDS (GUC_CTL_DEBUG + 1)
+#define GUC_CTL_MAX_DWORDS (GUC_CTL_RSRVD + 1)
struct guc_doorbell_info {
u32 db_status;
@@ -208,18 +210,31 @@ struct guc_context_desc {
u32 engine_presence;
- u32 reserved0[1];
+ u8 engine_suspended;
+
+ u8 reserved0[3];
u64 reserved1[1];
u64 desc_private;
} __packed;
+#define GUC_FORCEWAKE_RENDER (1 << 0)
+#define GUC_FORCEWAKE_MEDIA (1 << 1)
+
+#define GUC_POWER_UNSPECIFIED 0
+#define GUC_POWER_D0 1
+#define GUC_POWER_D1 2
+#define GUC_POWER_D2 3
+#define GUC_POWER_D3 4
+
/* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
enum host2guc_action {
HOST2GUC_ACTION_DEFAULT = 0x0,
HOST2GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
HOST2GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
HOST2GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
+ HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
+ HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
HOST2GUC_ACTION_LIMIT
};
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
new file mode 100644
index 000000000000..3541f76c65a7
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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.
+ *
+ * Authors:
+ * Vinit Azad <vinit.azad@intel.com>
+ * Ben Widawsky <ben@bwidawsk.net>
+ * Dave Gordon <david.s.gordon@intel.com>
+ * Alex Dai <yu.dai@intel.com>
+ */
+#include <linux/firmware.h>
+#include "i915_drv.h"
+#include "intel_guc.h"
+
+/**
+ * DOC: GuC
+ *
+ * intel_guc:
+ * Top level structure of guc. It handles firmware loading and manages client
+ * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy
+ * ExecList submission.
+ *
+ * Firmware versioning:
+ * The firmware build process will generate a version header file with major and
+ * minor version defined. The versions are built into CSS header of firmware.
+ * i915 kernel driver set the minimal firmware version required per platform.
+ * The firmware installation package will install (symbolic link) proper version
+ * of firmware.
+ *
+ * GuC address space:
+ * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP),
+ * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is
+ * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects
+ * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.
+ *
+ * Firmware log:
+ * Firmware log is enabled by setting i915.guc_log_level to non-negative level.
+ * Log data is printed out via reading debugfs i915_guc_log_dump. Reading from
+ * i915_guc_load_status will print out firmware loading status and scratch
+ * registers value.
+ *
+ */
+
+#define I915_SKL_GUC_UCODE "i915/skl_guc_ver4.bin"
+MODULE_FIRMWARE(I915_SKL_GUC_UCODE);
+
+/* User-friendly representation of an enum */
+const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status)
+{
+ switch (status) {
+ case GUC_FIRMWARE_FAIL:
+ return "FAIL";
+ case GUC_FIRMWARE_NONE:
+ return "NONE";
+ case GUC_FIRMWARE_PENDING:
+ return "PENDING";
+ case GUC_FIRMWARE_SUCCESS:
+ return "SUCCESS";
+ default:
+ return "UNKNOWN!";
+ }
+};
+
+static void direct_interrupts_to_host(struct drm_i915_private *dev_priv)
+{
+ struct intel_engine_cs *ring;
+ int i, irqs;
+
+ /* tell all command streamers NOT to forward interrupts and vblank to GuC */
+ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER);
+ irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING);
+ for_each_ring(ring, dev_priv, i)
+ I915_WRITE(RING_MODE_GEN7(ring), irqs);
+
+ /* route all GT interrupts to the host */
+ I915_WRITE(GUC_BCS_RCS_IER, 0);
+ I915_WRITE(GUC_VCS2_VCS1_IER, 0);
+ I915_WRITE(GUC_WD_VECS_IER, 0);
+}
+
+static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
+{
+ struct intel_engine_cs *ring;
+ int i, irqs;
+
+ /* tell all command streamers to forward interrupts and vblank to GuC */
+ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS);
+ irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING);
+ for_each_ring(ring, dev_priv, i)
+ I915_WRITE(RING_MODE_GEN7(ring), irqs);
+
+ /* route USER_INTERRUPT to Host, all others are sent to GuC. */
+ irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
+ GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
+ /* These three registers have the same bit definitions */
+ I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
+ I915_WRITE(GUC_VCS2_VCS1_IER, ~irqs);
+ I915_WRITE(GUC_WD_VECS_IER, ~irqs);
+}
+
+static u32 get_gttype(struct drm_i915_private *dev_priv)
+{
+ /* XXX: GT type based on PCI device ID? field seems unused by fw */
+ return 0;
+}
+
+static u32 get_core_family(struct drm_i915_private *dev_priv)
+{
+ switch (INTEL_INFO(dev_priv)->gen) {
+ case 9:
+ return GFXCORE_FAMILY_GEN9;
+
+ default:
+ DRM_ERROR("GUC: unsupported core family\n");
+ return GFXCORE_FAMILY_UNKNOWN;
+ }
+}
+
+static void set_guc_init_params(struct drm_i915_private *dev_priv)
+{
+ struct intel_guc *guc = &dev_priv->guc;
+ u32 params[GUC_CTL_MAX_DWORDS];
+ int i;
+
+ memset(&params, 0, sizeof(params));
+
+ params[GUC_CTL_DEVICE_INFO] |=
+ (get_gttype(dev_priv) << GUC_CTL_GTTYPE_SHIFT) |
+ (get_core_family(dev_priv) << GUC_CTL_COREFAMILY_SHIFT);
+
+ /*
+ * GuC ARAT increment is 10 ns. GuC default scheduler quantum is one
+ * second. This ARAR is calculated by:
+ * Scheduler-Quantum-in-ns / ARAT-increment-in-ns = 1000000000 / 10
+ */
+ params[GUC_CTL_ARAT_HIGH] = 0;
+ params[GUC_CTL_ARAT_LOW] = 100000000;
+
+ params[GUC_CTL_WA] |= GUC_CTL_WA_UK_BY_DRIVER;
+
+ params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER |
+ GUC_CTL_VCS2_ENABLED;
+
+ if (i915.guc_log_level >= 0) {
+ params[GUC_CTL_LOG_PARAMS] = guc->log_flags;
+ params[GUC_CTL_DEBUG] =
+ i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT;
+ }
+
+ /* If GuC submission is enabled, set up additional parameters here */
+ if (i915.enable_guc_submission) {
+ u32 pgs = i915_gem_obj_ggtt_offset(dev_priv->guc.ctx_pool_obj);
+ u32 ctx_in_16 = GUC_MAX_GPU_CONTEXTS / 16;
+
+ pgs >>= PAGE_SHIFT;
+ params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) |
+ (ctx_in_16 << GUC_CTL_CTXNUM_IN16_SHIFT);
+
+ params[GUC_CTL_FEATURE] |= GUC_CTL_KERNEL_SUBMISSIONS;
+
+ /* Unmask this bit to enable the GuC's internal scheduler */
+ params[GUC_CTL_FEATURE] &= ~GUC_CTL_DISABLE_SCHEDULER;
+ }
+
+ I915_WRITE(SOFT_SCRATCH(0), 0);
+
+ for (i = 0; i < GUC_CTL_MAX_DWORDS; i++)
+ I915_WRITE(SOFT_SCRATCH(1 + i), params[i]);
+}
+
+/*
+ * Read the GuC status register (GUC_STATUS) and store it in the
+ * specified location; then return a boolean indicating whether
+ * the value matches either of two values representing completion
+ * of the GuC boot process.
+ *
+ * This is used for polling the GuC status in a wait_for_atomic()
+ * loop below.
+ */
+static inline bool guc_ucode_response(struct drm_i915_private *dev_priv,
+ u32 *status)
+{
+ u32 val = I915_READ(GUC_STATUS);
+ u32 uk_val = val & GS_UKERNEL_MASK;
+ *status = val;
+ return (uk_val == GS_UKERNEL_READY ||
+ ((val & GS_MIA_CORE_STATE) && uk_val == GS_UKERNEL_LAPIC_DONE));
+}
+
+/*
+ * Transfer the firmware image to RAM for execution by the microcontroller.
+ *
+ * GuC Firmware layout:
+ * +-------------------------------+ ----
+ * | CSS header | 128B
+ * | contains major/minor version |
+ * +-------------------------------+ ----
+ * | uCode |
+ * +-------------------------------+ ----
+ * | RSA signature | 256B
+ * +-------------------------------+ ----
+ *
+ * Architecturally, the DMA engine is bidirectional, and can potentially even
+ * transfer between GTT locations. This functionality is left out of the API
+ * for now as there is no need for it.
+ *
+ * Note that GuC needs the CSS header plus uKernel code to be copied by the
+ * DMA engine in one operation, whereas the RSA signature is loaded via MMIO.
+ */
+
+#define UOS_CSS_HEADER_OFFSET 0
+#define UOS_VER_MINOR_OFFSET 0x44
+#define UOS_VER_MAJOR_OFFSET 0x46
+#define UOS_CSS_HEADER_SIZE 0x80
+#define UOS_RSA_SIG_SIZE 0x100
+
+static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
+{
+ struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+ struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
+ unsigned long offset;
+ struct sg_table *sg = fw_obj->pages;
+ u32 status, ucode_size, rsa[UOS_RSA_SIG_SIZE / sizeof(u32)];
+ int i, ret = 0;
+
+ /* uCode size, also is where RSA signature starts */
+ offset = ucode_size = guc_fw->guc_fw_size - UOS_RSA_SIG_SIZE;
+ I915_WRITE(DMA_COPY_SIZE, ucode_size);
+
+ /* Copy RSA signature from the fw image to HW for verification */
+ sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, UOS_RSA_SIG_SIZE, offset);
+ for (i = 0; i < UOS_RSA_SIG_SIZE / sizeof(u32); i++)
+ I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]);
+
+ /* Set the source address for the new blob */
+ offset = i915_gem_obj_ggtt_offset(fw_obj);
+ I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
+ I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
+
+ /*
+ * Set the DMA destination. Current uCode expects the code to be
+ * loaded at 8k; locations below this are used for the stack.
+ */
+ I915_WRITE(DMA_ADDR_1_LOW, 0x2000);
+ I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
+
+ /* Finally start the DMA */
+ I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
+
+ /*
+ * Spin-wait for the DMA to complete & the GuC to start up.
+ * NB: Docs recommend not using the interrupt for completion.
+ * Measurements indicate this should take no more than 20ms, so a
+ * timeout here indicates that the GuC has failed and is unusable.
+ * (Higher levels of the driver will attempt to fall back to
+ * execlist mode if this happens.)
+ */
+ ret = wait_for_atomic(guc_ucode_response(dev_priv, &status), 100);
+
+ DRM_DEBUG_DRIVER("DMA status 0x%x, GuC status 0x%x\n",
+ I915_READ(DMA_CTRL), status);
+
+ if ((status & GS_BOOTROM_MASK) == GS_BOOTROM_RSA_FAILED) {
+ DRM_ERROR("GuC firmware signature verification failed\n");
+ ret = -ENOEXEC;
+ }
+
+ DRM_DEBUG_DRIVER("returning %d\n", ret);
+
+ return ret;
+}
+
+/*
+ * Load the GuC firmware blob into the MinuteIA.
+ */
+static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
+{
+ struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+ struct drm_device *dev = dev_priv->dev;
+ int ret;
+
+ ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false);
+ if (ret) {
+ DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
+ return ret;
+ }
+
+ ret = i915_gem_obj_ggtt_pin(guc_fw->guc_fw_obj, 0, 0);
+ if (ret) {
+ DRM_DEBUG_DRIVER("pin failed %d\n", ret);
+ return ret;
+ }
+
+ /* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
+ I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
+
+ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+
+ /* init WOPCM */
+ I915_WRITE(GUC_WOPCM_SIZE, GUC_WOPCM_SIZE_VALUE);
+ I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
+
+ /* Enable MIA caching. GuC clock gating is disabled. */
+ I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
+
+ /* WaDisableMinuteIaClockGating:skl,bxt */
+ if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
+ (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) {
+ I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
+ ~GUC_ENABLE_MIA_CLOCK_GATING));
+ }
+
+ /* WaC6DisallowByGfxPause*/
+ I915_WRITE(GEN6_GFXPAUSE, 0x30FFF);
+
+ if (IS_BROXTON(dev))
+ I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
+ else
+ I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
+
+ if (IS_GEN9(dev)) {
+ /* DOP Clock Gating Enable for GuC clocks */
+ I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE |
+ I915_READ(GEN7_MISCCPCTL)));
+
+ /* allows for 5us before GT can go to RC6 */
+ I915_WRITE(GUC_ARAT_C6DIS, 0x1FF);
+ }
+
+ set_guc_init_params(dev_priv);
+
+ ret = guc_ucode_xfer_dma(dev_priv);
+
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+ /*
+ * We keep the object pages for reuse during resume. But we can unpin it
+ * now that DMA has completed, so it doesn't continue to take up space.
+ */
+ i915_gem_object_ggtt_unpin(guc_fw->guc_fw_obj);
+
+ return ret;
+}
+
+/**
+ * intel_guc_ucode_load() - load GuC uCode into the device
+ * @dev: drm device
+ *
+ * Called from gem_init_hw() during driver loading and also after a GPU reset.
+ *
+ * The firmware image should have already been fetched into memory by the
+ * earlier call to intel_guc_ucode_init(), so here we need only check that
+ * is succeeded, and then transfer the image to the h/w.
+ *
+ * Return: non-zero code on error
+ */
+int intel_guc_ucode_load(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+ int err = 0;
+
+ DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
+ intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+
+ direct_interrupts_to_host(dev_priv);
+
+ if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE)
+ return 0;
+
+ if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_SUCCESS &&
+ guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL)
+ return -ENOEXEC;
+
+ guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
+
+ DRM_DEBUG_DRIVER("GuC fw fetch status %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+
+ switch (guc_fw->guc_fw_fetch_status) {
+ case GUC_FIRMWARE_FAIL:
+ /* something went wrong :( */
+ err = -EIO;
+ goto fail;
+
+ case GUC_FIRMWARE_NONE:
+ case GUC_FIRMWARE_PENDING:
+ default:
+ /* "can't happen" */
+ WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n",
+ guc_fw->guc_fw_path,
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
+ guc_fw->guc_fw_fetch_status);
+ err = -ENXIO;
+ goto fail;
+
+ case GUC_FIRMWARE_SUCCESS:
+ break;
+ }
+
+ err = i915_guc_submission_init(dev);
+ if (err)
+ goto fail;
+
+ err = guc_ucode_xfer(dev_priv);
+ if (err)
+ goto fail;
+
+ guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
+
+ DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
+ intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+
+ if (i915.enable_guc_submission) {
+ /* The execbuf_client will be recreated. Release it first. */
+ i915_guc_submission_disable(dev);
+
+ err = i915_guc_submission_enable(dev);
+ if (err)
+ goto fail;
+ direct_interrupts_to_guc(dev_priv);
+ }
+
+ return 0;
+
+fail:
+ if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
+ guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;
+
+ direct_interrupts_to_host(dev_priv);
+ i915_guc_submission_disable(dev);
+
+ return err;
+}
+
+static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
+{
+ struct drm_i915_gem_object *obj;
+ const struct firmware *fw;
+ const u8 *css_header;
+ const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_RSA_SIG_SIZE;
+ const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_RSA_SIG_SIZE
+ - 0x8000; /* 32k reserved (8K stack + 24k context) */
+ int err;
+
+ DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+
+ err = request_firmware(&fw, guc_fw->guc_fw_path, &dev->pdev->dev);
+ if (err)
+ goto fail;
+ if (!fw)
+ goto fail;
+
+ DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n",
+ guc_fw->guc_fw_path, fw);
+ DRM_DEBUG_DRIVER("firmware file size %zu (minimum %zu, maximum %zu)\n",
+ fw->size, minsize, maxsize);
+
+ /* Check the size of the blob befoe examining buffer contents */
+ if (fw->size < minsize || fw->size > maxsize)
+ goto fail;
+
+ /*
+ * The GuC firmware image has the version number embedded at a well-known
+ * offset within the firmware blob; note that major / minor version are
+ * TWO bytes each (i.e. u16), although all pointers and offsets are defined
+ * in terms of bytes (u8).
+ */
+ css_header = fw->data + UOS_CSS_HEADER_OFFSET;
+ guc_fw->guc_fw_major_found = *(u16 *)(css_header + UOS_VER_MAJOR_OFFSET);
+ guc_fw->guc_fw_minor_found = *(u16 *)(css_header + UOS_VER_MINOR_OFFSET);
+
+ if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted ||
+ guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) {
+ DRM_ERROR("GuC firmware version %d.%d, required %d.%d\n",
+ guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found,
+ guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+ err = -ENOEXEC;
+ goto fail;
+ }
+
+ DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n",
+ guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found,
+ guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+
+ mutex_lock(&dev->struct_mutex);
+ obj = i915_gem_object_create_from_data(dev, fw->data, fw->size);
+ mutex_unlock(&dev->struct_mutex);
+ if (IS_ERR_OR_NULL(obj)) {
+ err = obj ? PTR_ERR(obj) : -ENOMEM;
+ goto fail;
+ }
+
+ guc_fw->guc_fw_obj = obj;
+ guc_fw->guc_fw_size = fw->size;
+
+ DRM_DEBUG_DRIVER("GuC fw fetch status SUCCESS, obj %p\n",
+ guc_fw->guc_fw_obj);
+
+ release_firmware(fw);
+ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_SUCCESS;
+ return;
+
+fail:
+ DRM_DEBUG_DRIVER("GuC fw fetch status FAIL; err %d, fw %p, obj %p\n",
+ err, fw, guc_fw->guc_fw_obj);
+ DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n",
+ guc_fw->guc_fw_path, err);
+
+ obj = guc_fw->guc_fw_obj;
+ if (obj)
+ drm_gem_object_unreference(&obj->base);
+ guc_fw->guc_fw_obj = NULL;
+
+ release_firmware(fw); /* OK even if fw is NULL */
+ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
+}
+
+/**
+ * intel_guc_ucode_init() - define parameters and fetch firmware
+ * @dev: drm device
+ *
+ * Called early during driver load, but after GEM is initialised.
+ *
+ * The firmware will be transferred to the GuC's memory later,
+ * when intel_guc_ucode_load() is called.
+ */
+void intel_guc_ucode_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+ const char *fw_path;
+
+ if (!HAS_GUC_SCHED(dev))
+ i915.enable_guc_submission = false;
+
+ if (!HAS_GUC_UCODE(dev)) {
+ fw_path = NULL;
+ } else if (IS_SKYLAKE(dev)) {
+ fw_path = I915_SKL_GUC_UCODE;
+ guc_fw->guc_fw_major_wanted = 4;
+ guc_fw->guc_fw_minor_wanted = 3;
+ } else {
+ i915.enable_guc_submission = false;
+ fw_path = ""; /* unknown device */
+ }
+
+ guc_fw->guc_dev = dev;
+ guc_fw->guc_fw_path = fw_path;
+ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
+ guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE;
+
+ if (fw_path == NULL)
+ return;
+
+ if (*fw_path == '\0') {
+ DRM_ERROR("No GuC firmware known for this platform\n");
+ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
+ return;
+ }
+
+ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING;
+ DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path);
+ guc_fw_fetch(dev, guc_fw);
+ /* status must now be FAIL or SUCCESS */
+}
+
+/**
+ * intel_guc_ucode_fini() - clean up all allocated resources
+ * @dev: drm device
+ */
+void intel_guc_ucode_fini(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+
+ direct_interrupts_to_host(dev_priv);
+ i915_guc_submission_fini(dev);
+
+ mutex_lock(&dev->struct_mutex);
+ if (guc_fw->guc_fw_obj)
+ drm_gem_object_unreference(&guc_fw->guc_fw_obj->base);
+ guc_fw->guc_fw_obj = NULL;
+ mutex_unlock(&dev->struct_mutex);
+
+ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
+}
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index dcd336bcdfe7..9eafa191cee2 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -113,17 +113,18 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
}
}
-static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
- enum transcoder cpu_transcoder,
- struct drm_i915_private *dev_priv)
+static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum hdmi_infoframe_type type,
+ int i)
{
switch (type) {
case HDMI_INFOFRAME_TYPE_AVI:
- return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder);
+ return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i);
case HDMI_INFOFRAME_TYPE_SPD:
- return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder);
+ return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i);
case HDMI_INFOFRAME_TYPE_VENDOR:
- return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder);
+ return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i);
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
return 0;
@@ -365,14 +366,13 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder);
+ enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+ u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
u32 data_reg;
int i;
u32 val = I915_READ(ctl_reg);
- data_reg = hsw_infoframe_data_reg(type,
- intel_crtc->config->cpu_transcoder,
- dev_priv);
+ data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0);
if (data_reg == 0)
return;
@@ -381,12 +381,14 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
mmiowb();
for (i = 0; i < len; i += 4) {
- I915_WRITE(data_reg + i, *data);
+ I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
+ type, i >> 2), *data);
data++;
}
/* Write every possible data byte to force correct ECC calculation. */
for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
- I915_WRITE(data_reg + i, 0);
+ I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
+ type, i >> 2), 0);
mmiowb();
val |= hsw_infoframe_enable(type);
@@ -447,16 +449,13 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
}
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
union hdmi_infoframe frame;
int ret;
- /* Set user selected PAR to incoming mode's member */
- adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio;
-
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
adjusted_mode);
if (ret < 0) {
@@ -494,7 +493,7 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
static void
intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
union hdmi_infoframe frame;
int ret;
@@ -509,7 +508,7 @@ intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
static void g4x_set_infoframes(struct drm_encoder *encoder,
bool enable,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
@@ -661,7 +660,7 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder)
static void ibx_set_infoframes(struct drm_encoder *encoder,
bool enable,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -713,7 +712,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
static void cpt_set_infoframes(struct drm_encoder *encoder,
bool enable,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -755,7 +754,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
static void vlv_set_infoframes(struct drm_encoder *encoder,
bool enable,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
@@ -807,7 +806,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
static void hsw_set_infoframes(struct drm_encoder *encoder,
bool enable,
- struct drm_display_mode *adjusted_mode)
+ const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -844,12 +843,12 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
- struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
u32 hdmi_val;
hdmi_val = SDVO_ENCODING_HDMI;
- if (!HAS_PCH_SPLIT(dev))
- hdmi_val |= intel_hdmi->color_range;
+ if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range)
+ hdmi_val |= HDMI_COLOR_RANGE_16_235;
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -1260,11 +1259,12 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
if (intel_hdmi->color_range_auto) {
/* See CEA-861-E - 5.1 Default Encoding Parameters */
- if (pipe_config->has_hdmi_sink &&
- drm_match_cea_mode(adjusted_mode) > 1)
- intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235;
- else
- intel_hdmi->color_range = 0;
+ pipe_config->limited_color_range =
+ pipe_config->has_hdmi_sink &&
+ drm_match_cea_mode(adjusted_mode) > 1;
+ } else {
+ pipe_config->limited_color_range =
+ intel_hdmi->limited_color_range;
}
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) {
@@ -1273,9 +1273,6 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
clock_12bpc *= 2;
}
- if (intel_hdmi->color_range)
- pipe_config->limited_color_range = true;
-
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
pipe_config->has_pch_encoder = true;
@@ -1314,6 +1311,9 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
return false;
}
+ /* Set user selected PAR to incoming mode's member */
+ adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio;
+
return true;
}
@@ -1331,22 +1331,23 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
}
static bool
-intel_hdmi_set_edid(struct drm_connector *connector)
+intel_hdmi_set_edid(struct drm_connector *connector, bool force)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct intel_encoder *intel_encoder =
&hdmi_to_dig_port(intel_hdmi)->base;
enum intel_display_power_domain power_domain;
- struct edid *edid;
+ struct edid *edid = NULL;
bool connected = false;
power_domain = intel_display_port_power_domain(intel_encoder);
intel_display_power_get(dev_priv, power_domain);
- edid = drm_get_edid(connector,
- intel_gmbus_get_adapter(dev_priv,
- intel_hdmi->ddc_bus));
+ if (force)
+ edid = drm_get_edid(connector,
+ intel_gmbus_get_adapter(dev_priv,
+ intel_hdmi->ddc_bus));
intel_display_power_put(dev_priv, power_domain);
@@ -1374,13 +1375,26 @@ static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector, bool force)
{
enum drm_connector_status status;
+ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+ struct drm_i915_private *dev_priv = to_i915(connector->dev);
+ bool live_status = false;
+ unsigned int retry = 3;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
+ while (!live_status && --retry) {
+ live_status = intel_digital_port_connected(dev_priv,
+ hdmi_to_dig_port(intel_hdmi));
+ mdelay(10);
+ }
+
+ if (!live_status)
+ DRM_DEBUG_KMS("Live status not up!");
+
intel_hdmi_unset_edid(connector);
- if (intel_hdmi_set_edid(connector)) {
+ if (intel_hdmi_set_edid(connector, live_status)) {
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
@@ -1404,7 +1418,7 @@ intel_hdmi_force(struct drm_connector *connector)
if (connector->status != connector_status_connected)
return;
- intel_hdmi_set_edid(connector);
+ intel_hdmi_set_edid(connector, true);
hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
}
@@ -1470,7 +1484,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
if (property == dev_priv->broadcast_rgb_property) {
bool old_auto = intel_hdmi->color_range_auto;
- uint32_t old_range = intel_hdmi->color_range;
+ bool old_range = intel_hdmi->limited_color_range;
switch (val) {
case INTEL_BROADCAST_RGB_AUTO:
@@ -1478,18 +1492,18 @@ intel_hdmi_set_property(struct drm_connector *connector,
break;
case INTEL_BROADCAST_RGB_FULL:
intel_hdmi->color_range_auto = false;
- intel_hdmi->color_range = 0;
+ intel_hdmi->limited_color_range = false;
break;
case INTEL_BROADCAST_RGB_LIMITED:
intel_hdmi->color_range_auto = false;
- intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235;
+ intel_hdmi->limited_color_range = true;
break;
default:
return -EINVAL;
}
if (old_auto == intel_hdmi->color_range_auto &&
- old_range == intel_hdmi->color_range)
+ old_range == intel_hdmi->limited_color_range)
return 0;
goto done;
@@ -1525,8 +1539,7 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
- struct drm_display_mode *adjusted_mode =
- &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
intel_hdmi_prepare(encoder);
@@ -1543,8 +1556,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc =
to_intel_crtc(encoder->base.crtc);
- struct drm_display_mode *adjusted_mode =
- &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
enum dpio_channel port = vlv_dport_to_channel(dport);
int pipe = intel_crtc->pipe;
u32 val;
@@ -1617,6 +1629,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->sb_lock);
}
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+ bool reset)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ enum pipe pipe = crtc->pipe;
+ uint32_t val;
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+ if (reset)
+ val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+ else
+ val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+
+ if (crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+ if (reset)
+ val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+ else
+ val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+ }
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
+ val |= CHV_PCS_REQ_SOFTRESET_EN;
+ if (reset)
+ val &= ~DPIO_PCS_CLK_SOFT_RESET;
+ else
+ val |= DPIO_PCS_CLK_SOFT_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
+
+ if (crtc->config->lane_count > 2) {
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+ val |= CHV_PCS_REQ_SOFTRESET_EN;
+ if (reset)
+ val &= ~DPIO_PCS_CLK_SOFT_RESET;
+ else
+ val |= DPIO_PCS_CLK_SOFT_RESET;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+ }
+}
+
static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1630,8 +1686,21 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
intel_hdmi_prepare(encoder);
+ /*
+ * Must trick the second common lane into life.
+ * Otherwise we can't even access the PLL.
+ */
+ if (ch == DPIO_CH0 && pipe == PIPE_B)
+ dport->release_cl2_override =
+ !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
+
+ chv_phy_powergate_lanes(encoder, true, 0x0);
+
mutex_lock(&dev_priv->sb_lock);
+ /* Assert data lane reset */
+ chv_data_lane_soft_reset(encoder, true);
+
/* program left/right clock distribution */
if (pipe != PIPE_B) {
val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
@@ -1683,6 +1752,39 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->sb_lock);
}
+static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
+ u32 val;
+
+ mutex_lock(&dev_priv->sb_lock);
+
+ /* disable left/right clock distribution */
+ if (pipe != PIPE_B) {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+ val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+ } else {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+ val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+ }
+
+ mutex_unlock(&dev_priv->sb_lock);
+
+ /*
+ * Leave the power down bit cleared for at least one
+ * lane so that chv_powergate_phy_ch() will power
+ * on something when the channel is otherwise unused.
+ * When the port is off and the override is removed
+ * the lanes power down anyway, so otherwise it doesn't
+ * really matter what the state of power down bits is
+ * after this.
+ */
+ chv_phy_powergate_lanes(encoder, false, 0x0);
+}
+
static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1701,33 +1803,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
static void chv_hdmi_post_disable(struct intel_encoder *encoder)
{
- struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc =
- to_intel_crtc(encoder->base.crtc);
- enum dpio_channel ch = vlv_dport_to_channel(dport);
- enum pipe pipe = intel_crtc->pipe;
- u32 val;
mutex_lock(&dev_priv->sb_lock);
- /* Propagate soft reset to data lane reset */
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
- val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
- val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+ /* Assert data lane reset */
+ chv_data_lane_soft_reset(encoder, true);
mutex_unlock(&dev_priv->sb_lock);
}
@@ -1740,8 +1822,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc =
to_intel_crtc(encoder->base.crtc);
- struct drm_display_mode *adjusted_mode =
- &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
enum dpio_channel ch = vlv_dport_to_channel(dport);
int pipe = intel_crtc->pipe;
int data, i, stagger;
@@ -1758,23 +1839,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
- /* Deassert soft data lane reset*/
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
- val |= CHV_PCS_REQ_SOFTRESET_EN;
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
- val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
- val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
- val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-
/* Program Tx latency optimal setting */
for (i = 0; i < 4; i++) {
/* Set the upar bit */
@@ -1817,6 +1881,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
DPIO_TX1_STAGGER_MULT(7) |
DPIO_TX2_STAGGER_MULT(5));
+ /* Deassert data lane reset */
+ chv_data_lane_soft_reset(encoder, false);
+
/* Clear calc init */
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
@@ -1851,31 +1918,33 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
+
val &= ~DPIO_SWING_MARGIN000_MASK;
val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
+
+ /*
+ * Supposedly this value shouldn't matter when unique transition
+ * scale is disabled, but in fact it does matter. Let's just
+ * always program the same value and hope it's OK.
+ */
+ val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
+ val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT;
+
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
}
- /* Disable unique transition scale */
+ /*
+ * The document said it needs to set bit 27 for ch0 and bit 26
+ * for ch1. Might be a typo in the doc.
+ * For now, for this unique transition scale selection, set bit
+ * 27 for ch0 and ch1.
+ */
for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
}
- /* Additional steps for 1200mV-0dB */
-#if 0
- val = vlv_dpio_read(dev_priv, pipe, VLV_TX_DW3(ch));
- if (ch)
- val |= DPIO_TX_UNIQ_TRANS_SCALE_CH1;
- else
- val |= DPIO_TX_UNIQ_TRANS_SCALE_CH0;
- vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(ch), val);
-
- vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(ch),
- vlv_dpio_read(dev_priv, pipe, VLV_TX_DW2(ch)) |
- (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT));
-#endif
/* Start swing calculation */
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
@@ -1885,11 +1954,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
- /* LRC Bypass */
- val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
- val |= DPIO_LRC_BYPASS;
- vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, val);
-
mutex_unlock(&dev_priv->sb_lock);
intel_hdmi->set_infoframes(&encoder->base,
@@ -1899,6 +1963,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
g4x_enable_hdmi(encoder);
vlv_wait_port_ready(dev_priv, dport, 0x0);
+
+ /* Second common lane will stay alive on its own now */
+ if (dport->release_cl2_override) {
+ chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
+ dport->release_cl2_override = false;
+ }
}
static void intel_hdmi_destroy(struct drm_connector *connector)
@@ -1931,15 +2001,6 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
};
static void
-intel_attach_aspect_ratio_property(struct drm_connector *connector)
-{
- if (!drm_mode_create_aspect_ratio_property(connector->dev))
- drm_object_attach_property(&connector->base,
- connector->dev->mode_config.aspect_ratio_property,
- DRM_MODE_PICTURE_ASPECT_NONE);
-}
-
-static void
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
{
intel_attach_force_audio_property(connector);
@@ -1974,7 +2035,14 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT;
else
intel_hdmi->ddc_bus = GMBUS_PIN_DPB;
- intel_encoder->hpd_pin = HPD_PORT_B;
+ /*
+ * On BXT A0/A1, sw needs to activate DDIA HPD logic and
+ * interrupts to check the external panel connection.
+ */
+ if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0))
+ intel_encoder->hpd_pin = HPD_PORT_A;
+ else
+ intel_encoder->hpd_pin = HPD_PORT_B;
break;
case PORT_C:
if (IS_BROXTON(dev_priv))
@@ -2051,6 +2119,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
intel_connector_attach_encoder(intel_connector, intel_encoder);
drm_connector_register(connector);
+ intel_hdmi->attached_connector = intel_connector;
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
* 0xd. Failure to do so will result in spurious interrupts being
@@ -2097,6 +2166,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
intel_encoder->pre_enable = chv_hdmi_pre_enable;
intel_encoder->enable = vlv_enable_hdmi;
intel_encoder->post_disable = chv_hdmi_post_disable;
+ intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
} else if (IS_VALLEYVIEW(dev)) {
intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
intel_encoder->pre_enable = vlv_hdmi_pre_enable;
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index a64f26c670af..1369fc41d039 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -114,8 +114,8 @@ intel_i2c_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
- I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
+ I915_WRITE(GMBUS0, 0);
+ I915_WRITE(GMBUS4, 0);
}
static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
@@ -261,7 +261,6 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus4_irq_en)
{
int i;
- int reg_offset = dev_priv->gpio_mmio_base;
u32 gmbus2 = 0;
DEFINE_WAIT(wait);
@@ -271,13 +270,13 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
/* Important: The hw handles only the first bit, so set only one! Since
* we also need to check for NAKs besides the hw ready/idle signal, we
* need to wake up periodically and check that ourselves. */
- I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en);
+ I915_WRITE(GMBUS4, gmbus4_irq_en);
for (i = 0; i < msecs_to_jiffies_timeout(50); i++) {
prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait,
TASK_UNINTERRUPTIBLE);
- gmbus2 = I915_READ_NOTRACE(GMBUS2 + reg_offset);
+ gmbus2 = I915_READ_NOTRACE(GMBUS2);
if (gmbus2 & (GMBUS_SATOER | gmbus2_status))
break;
@@ -285,7 +284,7 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
}
finish_wait(&dev_priv->gmbus_wait_queue, &wait);
- I915_WRITE(GMBUS4 + reg_offset, 0);
+ I915_WRITE(GMBUS4, 0);
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
@@ -298,20 +297,19 @@ static int
gmbus_wait_idle(struct drm_i915_private *dev_priv)
{
int ret;
- int reg_offset = dev_priv->gpio_mmio_base;
-#define C ((I915_READ_NOTRACE(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0)
+#define C ((I915_READ_NOTRACE(GMBUS2) & GMBUS_ACTIVE) == 0)
if (!HAS_GMBUS_IRQ(dev_priv->dev))
return wait_for(C, 10);
/* Important: The hw handles only the first bit, so set only one! */
- I915_WRITE(GMBUS4 + reg_offset, GMBUS_IDLE_EN);
+ I915_WRITE(GMBUS4, GMBUS_IDLE_EN);
ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
msecs_to_jiffies_timeout(10));
- I915_WRITE(GMBUS4 + reg_offset, 0);
+ I915_WRITE(GMBUS4, 0);
if (ret)
return 0;
@@ -325,9 +323,7 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len,
u32 gmbus1_index)
{
- int reg_offset = dev_priv->gpio_mmio_base;
-
- I915_WRITE(GMBUS1 + reg_offset,
+ I915_WRITE(GMBUS1,
gmbus1_index |
GMBUS_CYCLE_WAIT |
(len << GMBUS_BYTE_COUNT_SHIFT) |
@@ -342,7 +338,7 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
if (ret)
return ret;
- val = I915_READ(GMBUS3 + reg_offset);
+ val = I915_READ(GMBUS3);
do {
*buf++ = val & 0xff;
val >>= 8;
@@ -380,7 +376,6 @@ static int
gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len)
{
- int reg_offset = dev_priv->gpio_mmio_base;
unsigned int chunk_size = len;
u32 val, loop;
@@ -390,8 +385,8 @@ gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
len -= 1;
}
- I915_WRITE(GMBUS3 + reg_offset, val);
- I915_WRITE(GMBUS1 + reg_offset,
+ I915_WRITE(GMBUS3, val);
+ I915_WRITE(GMBUS1,
GMBUS_CYCLE_WAIT |
(chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
@@ -404,7 +399,7 @@ gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
val |= *buf++ << (8 * loop);
} while (--len && ++loop < 4);
- I915_WRITE(GMBUS3 + reg_offset, val);
+ I915_WRITE(GMBUS3, val);
ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
GMBUS_HW_RDY_EN);
@@ -452,7 +447,6 @@ gmbus_is_index_read(struct i2c_msg *msgs, int i, int num)
static int
gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
{
- int reg_offset = dev_priv->gpio_mmio_base;
u32 gmbus1_index = 0;
u32 gmbus5 = 0;
int ret;
@@ -466,13 +460,13 @@ gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
/* GMBUS5 holds 16-bit index */
if (gmbus5)
- I915_WRITE(GMBUS5 + reg_offset, gmbus5);
+ I915_WRITE(GMBUS5, gmbus5);
ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
/* Clear GMBUS5 after each index transfer */
if (gmbus5)
- I915_WRITE(GMBUS5 + reg_offset, 0);
+ I915_WRITE(GMBUS5, 0);
return ret;
}
@@ -486,7 +480,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
struct intel_gmbus,
adapter);
struct drm_i915_private *dev_priv = bus->dev_priv;
- int i = 0, inc, try = 0, reg_offset;
+ int i = 0, inc, try = 0;
int ret = 0;
intel_aux_display_runtime_get(dev_priv);
@@ -497,10 +491,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
goto out;
}
- reg_offset = dev_priv->gpio_mmio_base;
-
retry:
- I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
+ I915_WRITE(GMBUS0, bus->reg0);
for (; i < num; i += inc) {
inc = 1;
@@ -530,7 +522,7 @@ retry:
* a STOP on the very first cycle. To simplify the code we
* unconditionally generate the STOP condition with an additional gmbus
* cycle. */
- I915_WRITE(GMBUS1 + reg_offset, GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
+ I915_WRITE(GMBUS1, GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
/* Mark the GMBUS interface as disabled after waiting for idle.
* We will re-enable it at the start of the next xfer,
@@ -541,7 +533,7 @@ retry:
adapter->name);
ret = -ETIMEDOUT;
}
- I915_WRITE(GMBUS0 + reg_offset, 0);
+ I915_WRITE(GMBUS0, 0);
ret = ret ?: i;
goto out;
@@ -570,9 +562,9 @@ clear_err:
* of resetting the GMBUS controller and so clearing the
* BUS_ERROR raised by the slave's NAK.
*/
- I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
- I915_WRITE(GMBUS1 + reg_offset, 0);
- I915_WRITE(GMBUS0 + reg_offset, 0);
+ I915_WRITE(GMBUS1, GMBUS_SW_CLR_INT);
+ I915_WRITE(GMBUS1, 0);
+ I915_WRITE(GMBUS0, 0);
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr,
@@ -595,7 +587,7 @@ clear_err:
timeout:
DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
bus->adapter.name, bus->reg0 & 0xff);
- I915_WRITE(GMBUS0 + reg_offset, 0);
+ I915_WRITE(GMBUS0, 0);
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
bus->force_bit = 1;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7412caedcf7f..88e12bdf79e2 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -196,13 +196,21 @@
reg_state[CTX_PDP ## n ## _LDW+1] = lower_32_bits(_addr); \
}
+#define ASSIGN_CTX_PML4(ppgtt, reg_state) { \
+ reg_state[CTX_PDP0_UDW + 1] = upper_32_bits(px_dma(&ppgtt->pml4)); \
+ reg_state[CTX_PDP0_LDW + 1] = lower_32_bits(px_dma(&ppgtt->pml4)); \
+}
+
enum {
ADVANCED_CONTEXT = 0,
- LEGACY_CONTEXT,
+ LEGACY_32B_CONTEXT,
ADVANCED_AD_CONTEXT,
LEGACY_64B_CONTEXT
};
-#define GEN8_CTX_MODE_SHIFT 3
+#define GEN8_CTX_ADDRESSING_MODE_SHIFT 3
+#define GEN8_CTX_ADDRESSING_MODE(dev) (USES_FULL_48BIT_PPGTT(dev) ?\
+ LEGACY_64B_CONTEXT :\
+ LEGACY_32B_CONTEXT)
enum {
FAULT_AND_HANG = 0,
FAULT_AND_HALT, /* Debug only */
@@ -213,6 +221,9 @@ enum {
#define CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT 0x17
static int intel_lr_context_pin(struct drm_i915_gem_request *rq);
+static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
+ struct drm_i915_gem_object *default_ctx_obj);
+
/**
* intel_sanitize_enable_execlists() - sanitize i915.enable_execlists
@@ -228,6 +239,12 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists
{
WARN_ON(i915.enable_ppgtt == -1);
+ /* On platforms with execlist available, vGPU will only
+ * support execlist mode, no ring buffer mode.
+ */
+ if (HAS_LOGICAL_RING_CONTEXTS(dev) && intel_vgpu_active(dev))
+ return 1;
+
if (INTEL_INFO(dev)->gen >= 9)
return 1;
@@ -255,25 +272,35 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists
*/
u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj)
{
- u32 lrca = i915_gem_obj_ggtt_offset(ctx_obj);
+ u32 lrca = i915_gem_obj_ggtt_offset(ctx_obj) +
+ LRC_PPHWSP_PN * PAGE_SIZE;
/* LRCA is required to be 4K aligned so the more significant 20 bits
* are globally unique */
return lrca >> 12;
}
-static uint64_t execlists_ctx_descriptor(struct drm_i915_gem_request *rq)
+static bool disable_lite_restore_wa(struct intel_engine_cs *ring)
{
- struct intel_engine_cs *ring = rq->ring;
struct drm_device *dev = ring->dev;
- struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state;
+
+ return ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
+ (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) &&
+ (ring->id == VCS || ring->id == VCS2);
+}
+
+uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
+ struct intel_engine_cs *ring)
+{
+ struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state;
uint64_t desc;
- uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj);
+ uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj) +
+ LRC_PPHWSP_PN * PAGE_SIZE;
WARN_ON(lrca & 0xFFFFFFFF00000FFFULL);
desc = GEN8_CTX_VALID;
- desc |= LEGACY_CONTEXT << GEN8_CTX_MODE_SHIFT;
+ desc |= GEN8_CTX_ADDRESSING_MODE(dev) << GEN8_CTX_ADDRESSING_MODE_SHIFT;
if (IS_GEN8(ctx_obj->base.dev))
desc |= GEN8_CTX_L3LLC_COHERENT;
desc |= GEN8_CTX_PRIVILEGE;
@@ -285,10 +312,8 @@ static uint64_t execlists_ctx_descriptor(struct drm_i915_gem_request *rq)
/* desc |= GEN8_CTX_FORCE_RESTORE; */
/* WaEnableForceRestoreInCtxtDescForVCS:skl */
- if (IS_GEN9(dev) &&
- INTEL_REVID(dev) <= SKL_REVID_B0 &&
- (ring->id == BCS || ring->id == VCS ||
- ring->id == VECS || ring->id == VCS2))
+ /* WaEnableForceRestoreInCtxtDescForVCS:bxt */
+ if (disable_lite_restore_wa(ring))
desc |= GEN8_CTX_FORCE_RESTORE;
return desc;
@@ -304,13 +329,13 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0,
uint64_t desc[2];
if (rq1) {
- desc[1] = execlists_ctx_descriptor(rq1);
+ desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->ring);
rq1->elsp_submitted++;
} else {
desc[1] = 0;
}
- desc[0] = execlists_ctx_descriptor(rq0);
+ desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->ring);
rq0->elsp_submitted++;
/* You must always write both descriptors in the order below. */
@@ -324,7 +349,7 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0,
I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[0]));
/* ELSP is a wo register, use another nearby reg for posting */
- POSTING_READ_FW(RING_EXECLIST_STATUS(ring));
+ POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring));
intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
spin_unlock(&dev_priv->uncore.lock);
}
@@ -342,16 +367,18 @@ static int execlists_update_context(struct drm_i915_gem_request *rq)
WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
- page = i915_gem_object_get_page(ctx_obj, 1);
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
reg_state = kmap_atomic(page);
reg_state[CTX_RING_TAIL+1] = rq->tail;
reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj);
- /* True PPGTT with dynamic page allocation: update PDP registers and
- * point the unallocated PDPs to the scratch page
- */
- if (ppgtt) {
+ if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
+ /* True 32b PPGTT with dynamic page allocation: update PDP
+ * registers and point the unallocated PDPs to scratch page.
+ * PML4 is allocated during ppgtt init, so this is not needed
+ * in 48-bit mode.
+ */
ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
@@ -477,7 +504,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
u32 status_pointer;
u8 read_pointer;
u8 write_pointer;
- u32 status;
+ u32 status = 0;
u32 status_id;
u32 submit_contexts = 0;
@@ -492,10 +519,8 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
while (read_pointer < write_pointer) {
read_pointer++;
- status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
- (read_pointer % GEN8_CSB_ENTRIES) * 8);
- status_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
- (read_pointer % GEN8_CSB_ENTRIES) * 8 + 4);
+ status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer % GEN8_CSB_ENTRIES));
+ status_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer % GEN8_CSB_ENTRIES));
if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
continue;
@@ -515,8 +540,14 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
}
}
- if (submit_contexts != 0)
+ if (disable_lite_restore_wa(ring)) {
+ /* Prevent a ctx to preempt itself */
+ if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) &&
+ (submit_contexts != 0))
+ execlists_context_unqueue(ring);
+ } else if (submit_contexts != 0) {
execlists_context_unqueue(ring);
+ }
spin_unlock(&ring->execlist_lock);
@@ -540,8 +571,6 @@ static int execlists_context_queue(struct drm_i915_gem_request *request)
i915_gem_request_reference(request);
- request->tail = request->ringbuf->tail;
-
spin_lock_irq(&ring->execlist_lock);
list_for_each_entry(cursor, &ring->execlist_queue, execlist_link)
@@ -694,13 +723,19 @@ static void
intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
{
struct intel_engine_cs *ring = request->ring;
+ struct drm_i915_private *dev_priv = request->i915;
intel_logical_ring_advance(request->ringbuf);
+ request->tail = request->ringbuf->tail;
+
if (intel_ring_stopped(ring))
return;
- execlists_context_queue(request);
+ if (dev_priv->guc.execbuf_client)
+ i915_guc_submit(dev_priv->guc.execbuf_client, request);
+ else
+ execlists_context_queue(request);
}
static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf)
@@ -767,8 +802,7 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes)
/**
* intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands
*
- * @request: The request to start some new work for
- * @ctx: Logical ring context whose ringbuffer is being prepared.
+ * @req: The request to start some new work for
* @num_dwords: number of DWORDs that we plan to write to the ringbuffer.
*
* The ringbuffer might not be ready to accept the commands right away (maybe it needs to
@@ -870,21 +904,6 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
return -EINVAL;
}
- if (args->num_cliprects != 0) {
- DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
- return -EINVAL;
- } else {
- if (args->DR4 == 0xffffffff) {
- DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
- args->DR4 = 0;
- }
-
- if (args->DR1 || args->DR4 || args->cliprects_ptr) {
- DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
- return -EINVAL;
- }
- }
-
if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
DRM_DEBUG("sol reset is gen7 only\n");
return -EINVAL;
@@ -988,34 +1007,54 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
return 0;
}
+static int intel_lr_context_do_pin(struct intel_engine_cs *ring,
+ struct drm_i915_gem_object *ctx_obj,
+ struct intel_ringbuffer *ringbuf)
+{
+ struct drm_device *dev = ring->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret = 0;
+
+ WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex));
+ ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN,
+ PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+ if (ret)
+ return ret;
+
+ ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
+ if (ret)
+ goto unpin_ctx_obj;
+
+ ctx_obj->dirty = true;
+
+ /* Invalidate GuC TLB. */
+ if (i915.enable_guc_submission)
+ I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
+
+ return ret;
+
+unpin_ctx_obj:
+ i915_gem_object_ggtt_unpin(ctx_obj);
+
+ return ret;
+}
+
static int intel_lr_context_pin(struct drm_i915_gem_request *rq)
{
+ int ret = 0;
struct intel_engine_cs *ring = rq->ring;
struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state;
struct intel_ringbuffer *ringbuf = rq->ringbuf;
- int ret = 0;
- WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex));
if (rq->ctx->engine[ring->id].pin_count++ == 0) {
- ret = i915_gem_obj_ggtt_pin(ctx_obj,
- GEN8_LR_CONTEXT_ALIGN, 0);
+ ret = intel_lr_context_do_pin(ring, ctx_obj, ringbuf);
if (ret)
goto reset_pin_count;
-
- ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
- if (ret)
- goto unpin_ctx_obj;
-
- ctx_obj->dirty = true;
}
-
return ret;
-unpin_ctx_obj:
- i915_gem_object_ggtt_unpin(ctx_obj);
reset_pin_count:
rq->ctx->engine[ring->id].pin_count = 0;
-
return ret;
}
@@ -1113,7 +1152,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
if (IS_SKYLAKE(ring->dev) && INTEL_REVID(ring->dev) <= SKL_REVID_E0)
l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
- wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8(1) |
+ wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
wa_ctx_emit(batch, index, GEN8_L3SQCREG4);
wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
@@ -1131,7 +1170,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
wa_ctx_emit(batch, index, 0);
wa_ctx_emit(batch, index, 0);
- wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8(1) |
+ wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
wa_ctx_emit(batch, index, GEN8_L3SQCREG4);
wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
@@ -1200,9 +1239,10 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
/* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */
if (IS_BROADWELL(ring->dev)) {
- index = gen8_emit_flush_coherentl3_wa(ring, batch, index);
- if (index < 0)
- return index;
+ int rc = gen8_emit_flush_coherentl3_wa(ring, batch, index);
+ if (rc < 0)
+ return rc;
+ index = rc;
}
/* WaClearSlmSpaceAtContextSwitch:bdw,chv */
@@ -1426,6 +1466,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
struct drm_i915_private *dev_priv = dev->dev_private;
u8 next_context_status_buffer_hw;
+ lrc_setup_hardware_status_page(ring,
+ ring->default_context->engine[ring->id].state);
+
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
@@ -1542,12 +1585,16 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req,
* Ideally, we should set Force PD Restore in ctx descriptor,
* but we can't. Force Restore would be a second option, but
* it is unsafe in case of lite-restore (because the ctx is
- * not idle). */
+ * not idle). PML4 is allocated during ppgtt init so this is
+ * not needed in 48-bit.*/
if (req->ctx->ppgtt &&
(intel_ring_flag(req->ring) & req->ctx->ppgtt->pd_dirty_rings)) {
- ret = intel_logical_ring_emit_pdps(req);
- if (ret)
- return ret;
+ if (!USES_FULL_48BIT_PPGTT(req->i915) &&
+ !intel_vgpu_active(req->i915->dev)) {
+ ret = intel_logical_ring_emit_pdps(req);
+ if (ret)
+ return ret;
+ }
req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->ring);
}
@@ -1659,6 +1706,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
}
if (invalidate_domains) {
@@ -1713,6 +1761,34 @@ static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno)
intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
}
+static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+{
+
+ /*
+ * On BXT A steppings there is a HW coherency issue whereby the
+ * MI_STORE_DATA_IMM storing the completed request's seqno
+ * occasionally doesn't invalidate the CPU cache. Work around this by
+ * clflushing the corresponding cacheline whenever the caller wants
+ * the coherency to be guaranteed. Note that this cacheline is known
+ * to be clean at this point, since we only write it in
+ * bxt_a_set_seqno(), where we also do a clflush after the write. So
+ * this clflush in practice becomes an invalidate operation.
+ */
+
+ if (!lazy_coherency)
+ intel_flush_status_page(ring, I915_GEM_HWS_INDEX);
+
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+{
+ intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+
+ /* See bxt_a_get_seqno() explaining the reason for the clflush. */
+ intel_flush_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
static int gen8_emit_request(struct drm_i915_gem_request *request)
{
struct intel_ringbuffer *ringbuf = request->ringbuf;
@@ -1855,7 +1931,21 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
if (ret)
return ret;
- ret = intel_lr_context_deferred_create(ring->default_context, ring);
+ ret = intel_lr_context_deferred_alloc(ring->default_context, ring);
+ if (ret)
+ return ret;
+
+ /* As this is the default context, always pin it */
+ ret = intel_lr_context_do_pin(
+ ring,
+ ring->default_context->engine[ring->id].state,
+ ring->default_context->engine[ring->id].ringbuf);
+ if (ret) {
+ DRM_ERROR(
+ "Failed to pin and map ringbuffer %s: %d\n",
+ ring->name, ret);
+ return ret;
+ }
return ret;
}
@@ -1882,8 +1972,13 @@ static int logical_render_ring_init(struct drm_device *dev)
ring->init_hw = gen8_init_render_ring;
ring->init_context = gen8_init_rcs_context;
ring->cleanup = intel_fini_pipe_control;
- ring->get_seqno = gen8_get_seqno;
- ring->set_seqno = gen8_set_seqno;
+ if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ ring->get_seqno = bxt_a_get_seqno;
+ ring->set_seqno = bxt_a_set_seqno;
+ } else {
+ ring->get_seqno = gen8_get_seqno;
+ ring->set_seqno = gen8_set_seqno;
+ }
ring->emit_request = gen8_emit_request;
ring->emit_flush = gen8_emit_flush_render;
ring->irq_get = gen8_logical_ring_get_irq;
@@ -1929,8 +2024,13 @@ static int logical_bsd_ring_init(struct drm_device *dev)
GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
ring->init_hw = gen8_init_common_ring;
- ring->get_seqno = gen8_get_seqno;
- ring->set_seqno = gen8_set_seqno;
+ if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ ring->get_seqno = bxt_a_get_seqno;
+ ring->set_seqno = bxt_a_set_seqno;
+ } else {
+ ring->get_seqno = gen8_get_seqno;
+ ring->set_seqno = gen8_set_seqno;
+ }
ring->emit_request = gen8_emit_request;
ring->emit_flush = gen8_emit_flush;
ring->irq_get = gen8_logical_ring_get_irq;
@@ -1979,8 +2079,13 @@ static int logical_blt_ring_init(struct drm_device *dev)
GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
ring->init_hw = gen8_init_common_ring;
- ring->get_seqno = gen8_get_seqno;
- ring->set_seqno = gen8_set_seqno;
+ if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ ring->get_seqno = bxt_a_get_seqno;
+ ring->set_seqno = bxt_a_set_seqno;
+ } else {
+ ring->get_seqno = gen8_get_seqno;
+ ring->set_seqno = gen8_set_seqno;
+ }
ring->emit_request = gen8_emit_request;
ring->emit_flush = gen8_emit_flush;
ring->irq_get = gen8_logical_ring_get_irq;
@@ -2004,8 +2109,13 @@ static int logical_vebox_ring_init(struct drm_device *dev)
GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT;
ring->init_hw = gen8_init_common_ring;
- ring->get_seqno = gen8_get_seqno;
- ring->set_seqno = gen8_set_seqno;
+ if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ ring->get_seqno = bxt_a_get_seqno;
+ ring->set_seqno = bxt_a_set_seqno;
+ } else {
+ ring->get_seqno = gen8_get_seqno;
+ ring->set_seqno = gen8_set_seqno;
+ }
ring->emit_request = gen8_emit_request;
ring->emit_flush = gen8_emit_flush;
ring->irq_get = gen8_logical_ring_get_irq;
@@ -2058,14 +2168,8 @@ int intel_logical_rings_init(struct drm_device *dev)
goto cleanup_vebox_ring;
}
- ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000));
- if (ret)
- goto cleanup_bsd2_ring;
-
return 0;
-cleanup_bsd2_ring:
- intel_logical_ring_cleanup(&dev_priv->ring[VCS2]);
cleanup_vebox_ring:
intel_logical_ring_cleanup(&dev_priv->ring[VECS]);
cleanup_blt_ring:
@@ -2151,7 +2255,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
/* The second page of the context object contains some fields which must
* be set up prior to the first execution. */
- page = i915_gem_object_get_page(ctx_obj, 1);
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
reg_state = kmap_atomic(page);
/* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM
@@ -2228,13 +2332,24 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
reg_state[CTX_PDP0_UDW] = GEN8_RING_PDP_UDW(ring, 0);
reg_state[CTX_PDP0_LDW] = GEN8_RING_PDP_LDW(ring, 0);
- /* With dynamic page allocation, PDPs may not be allocated at this point,
- * Point the unallocated PDPs to the scratch page
- */
- ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
- ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
- ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
- ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
+ if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
+ /* 64b PPGTT (48bit canonical)
+ * PDP0_DESCRIPTOR contains the base address to PML4 and
+ * other PDP Descriptors are ignored.
+ */
+ ASSIGN_CTX_PML4(ppgtt, reg_state);
+ } else {
+ /* 32b PPGTT
+ * PDP*_DESCRIPTOR contains the base address of space supported.
+ * With dynamic page allocation, PDPs may not be allocated at
+ * this point. Point the unallocated PDPs to the scratch page
+ */
+ ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
+ ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
+ ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
+ ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
+ }
+
if (ring->id == RCS) {
reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1);
reg_state[CTX_R_PWR_CLK_STATE] = GEN8_R_PWR_CLK_STATE;
@@ -2275,8 +2390,7 @@ void intel_lr_context_free(struct intel_context *ctx)
i915_gem_object_ggtt_unpin(ctx_obj);
}
WARN_ON(ctx->engine[ring->id].pin_count);
- intel_destroy_ringbuffer_obj(ringbuf);
- kfree(ringbuf);
+ intel_ringbuffer_free(ringbuf);
drm_gem_object_unreference(&ctx_obj->base);
}
}
@@ -2310,12 +2424,13 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
struct drm_i915_gem_object *default_ctx_obj)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct page *page;
- /* The status page is offset 0 from the default context object
- * in LRC mode. */
- ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj);
- ring->status_page.page_addr =
- kmap(sg_page(default_ctx_obj->pages->sgl));
+ /* The HWSP is part of the default context object in LRC mode. */
+ ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj)
+ + LRC_PPHWSP_PN * PAGE_SIZE;
+ page = i915_gem_object_get_page(default_ctx_obj, LRC_PPHWSP_PN);
+ ring->status_page.page_addr = kmap(page);
ring->status_page.obj = default_ctx_obj;
I915_WRITE(RING_HWS_PGA(ring->mmio_base),
@@ -2324,7 +2439,7 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
}
/**
- * intel_lr_context_deferred_create() - create the LRC specific bits of a context
+ * intel_lr_context_deferred_alloc() - create the LRC specific bits of a context
* @ctx: LR context to create.
* @ring: engine to be used with the context.
*
@@ -2336,10 +2451,10 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
*
* Return: non-zero on error.
*/
-int intel_lr_context_deferred_create(struct intel_context *ctx,
+
+int intel_lr_context_deferred_alloc(struct intel_context *ctx,
struct intel_engine_cs *ring)
{
- const bool is_global_default_ctx = (ctx == ring->default_context);
struct drm_device *dev = ring->dev;
struct drm_i915_gem_object *ctx_obj;
uint32_t context_size;
@@ -2351,107 +2466,58 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
context_size = round_up(get_lr_context_size(ring), 4096);
+ /* One extra page as the sharing data between driver and GuC */
+ context_size += PAGE_SIZE * LRC_PPHWSP_PN;
+
ctx_obj = i915_gem_alloc_object(dev, context_size);
if (!ctx_obj) {
DRM_DEBUG_DRIVER("Alloc LRC backing obj failed.\n");
return -ENOMEM;
}
- if (is_global_default_ctx) {
- ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, 0);
- if (ret) {
- DRM_DEBUG_DRIVER("Pin LRC backing obj failed: %d\n",
- ret);
- drm_gem_object_unreference(&ctx_obj->base);
- return ret;
- }
- }
-
- ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
- if (!ringbuf) {
- DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
- ring->name);
- ret = -ENOMEM;
- goto error_unpin_ctx;
- }
-
- ringbuf->ring = ring;
-
- ringbuf->size = 32 * PAGE_SIZE;
- ringbuf->effective_size = ringbuf->size;
- ringbuf->head = 0;
- ringbuf->tail = 0;
- ringbuf->last_retired_head = -1;
- intel_ring_update_space(ringbuf);
-
- if (ringbuf->obj == NULL) {
- ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
- if (ret) {
- DRM_DEBUG_DRIVER(
- "Failed to allocate ringbuffer obj %s: %d\n",
- ring->name, ret);
- goto error_free_rbuf;
- }
-
- if (is_global_default_ctx) {
- ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf);
- if (ret) {
- DRM_ERROR(
- "Failed to pin and map ringbuffer %s: %d\n",
- ring->name, ret);
- goto error_destroy_rbuf;
- }
- }
-
+ ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE);
+ if (IS_ERR(ringbuf)) {
+ ret = PTR_ERR(ringbuf);
+ goto error_deref_obj;
}
ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf);
if (ret) {
DRM_DEBUG_DRIVER("Failed to populate LRC: %d\n", ret);
- goto error;
+ goto error_ringbuf;
}
ctx->engine[ring->id].ringbuf = ringbuf;
ctx->engine[ring->id].state = ctx_obj;
- if (ctx == ring->default_context)
- lrc_setup_hardware_status_page(ring, ctx_obj);
- else if (ring->id == RCS && !ctx->rcs_initialized) {
- if (ring->init_context) {
- struct drm_i915_gem_request *req;
+ if (ctx != ring->default_context && ring->init_context) {
+ struct drm_i915_gem_request *req;
- ret = i915_gem_request_alloc(ring, ctx, &req);
- if (ret)
- return ret;
-
- ret = ring->init_context(req);
- if (ret) {
- DRM_ERROR("ring init context: %d\n", ret);
- i915_gem_request_cancel(req);
- ctx->engine[ring->id].ringbuf = NULL;
- ctx->engine[ring->id].state = NULL;
- goto error;
- }
-
- i915_add_request_no_flush(req);
+ ret = i915_gem_request_alloc(ring,
+ ctx, &req);
+ if (ret) {
+ DRM_ERROR("ring create req: %d\n",
+ ret);
+ goto error_ringbuf;
}
- ctx->rcs_initialized = true;
+ ret = ring->init_context(req);
+ if (ret) {
+ DRM_ERROR("ring init context: %d\n",
+ ret);
+ i915_gem_request_cancel(req);
+ goto error_ringbuf;
+ }
+ i915_add_request_no_flush(req);
}
-
return 0;
-error:
- if (is_global_default_ctx)
- intel_unpin_ringbuffer_obj(ringbuf);
-error_destroy_rbuf:
- intel_destroy_ringbuffer_obj(ringbuf);
-error_free_rbuf:
- kfree(ringbuf);
-error_unpin_ctx:
- if (is_global_default_ctx)
- i915_gem_object_ggtt_unpin(ctx_obj);
+error_ringbuf:
+ intel_ringbuffer_free(ringbuf);
+error_deref_obj:
drm_gem_object_unreference(&ctx_obj->base);
+ ctx->engine[ring->id].ringbuf = NULL;
+ ctx->engine[ring->id].state = NULL;
return ret;
}
@@ -2477,7 +2543,7 @@ void intel_lr_context_reset(struct drm_device *dev,
WARN(1, "Failed get_pages for context obj\n");
continue;
}
- page = i915_gem_object_get_page(ctx_obj, 1);
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
reg_state = kmap_atomic(page);
reg_state[CTX_RING_HEAD+1] = 0;
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 3c63bb32ad81..4e60d54ba66d 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -30,12 +30,14 @@
/* Execlists regs */
#define RING_ELSP(ring) ((ring)->mmio_base+0x230)
-#define RING_EXECLIST_STATUS(ring) ((ring)->mmio_base+0x234)
+#define RING_EXECLIST_STATUS_LO(ring) ((ring)->mmio_base+0x234)
+#define RING_EXECLIST_STATUS_HI(ring) ((ring)->mmio_base+0x234 + 4)
#define RING_CONTEXT_CONTROL(ring) ((ring)->mmio_base+0x244)
#define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH (1 << 3)
#define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0)
#define CTX_CTRL_RS_CTX_ENABLE (1 << 1)
-#define RING_CONTEXT_STATUS_BUF(ring) ((ring)->mmio_base+0x370)
+#define RING_CONTEXT_STATUS_BUF_LO(ring, i) ((ring)->mmio_base+0x370 + (i) * 8)
+#define RING_CONTEXT_STATUS_BUF_HI(ring, i) ((ring)->mmio_base+0x370 + (i) * 8 + 4)
#define RING_CONTEXT_STATUS_PTR(ring) ((ring)->mmio_base+0x3a0)
/* Logical Rings */
@@ -70,12 +72,20 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf,
}
/* Logical Ring Contexts */
+
+/* One extra page is added before LRC for GuC as shared data */
+#define LRC_GUCSHR_PN (0)
+#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + 1)
+#define LRC_STATE_PN (LRC_PPHWSP_PN + 1)
+
void intel_lr_context_free(struct intel_context *ctx);
-int intel_lr_context_deferred_create(struct intel_context *ctx,
- struct intel_engine_cs *ring);
+int intel_lr_context_deferred_alloc(struct intel_context *ctx,
+ struct intel_engine_cs *ring);
void intel_lr_context_unpin(struct drm_i915_gem_request *req);
void intel_lr_context_reset(struct drm_device *dev,
struct intel_context *ctx);
+uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
+ struct intel_engine_cs *ring);
/* Execlists */
int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 881b5d13592e..7f39b8ad88ae 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -98,15 +98,11 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 lvds_reg, tmp, flags = 0;
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ u32 tmp, flags = 0;
int dotclock;
- if (HAS_PCH_SPLIT(dev))
- lvds_reg = PCH_LVDS;
- else
- lvds_reg = LVDS;
-
- tmp = I915_READ(lvds_reg);
+ tmp = I915_READ(lvds_encoder->reg);
if (tmp & LVDS_HSYNC_POLARITY)
flags |= DRM_MODE_FLAG_NHSYNC;
else
@@ -139,8 +135,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
- const struct drm_display_mode *adjusted_mode =
- &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
int pipe = crtc->pipe;
u32 temp;
@@ -289,11 +284,14 @@ intel_lvds_mode_valid(struct drm_connector *connector,
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+ int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
if (mode->hdisplay > fixed_mode->hdisplay)
return MODE_PANEL;
if (mode->vdisplay > fixed_mode->vdisplay)
return MODE_PANEL;
+ if (fixed_mode->clock > max_pixclk)
+ return MODE_CLOCK_HIGH;
return MODE_OK;
}
@@ -941,6 +939,7 @@ void intel_lvds_init(struct drm_device *dev)
struct drm_display_mode *downclock_mode = NULL;
struct edid *edid;
struct drm_crtc *crtc;
+ u32 lvds_reg;
u32 lvds;
int pipe;
u8 pin;
@@ -952,7 +951,7 @@ void intel_lvds_init(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(PCH_PP_CONTROL,
I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
- } else {
+ } else if (INTEL_INFO(dev_priv)->gen < 5) {
I915_WRITE(PP_CONTROL,
I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
}
@@ -963,8 +962,15 @@ void intel_lvds_init(struct drm_device *dev)
if (dmi_check_system(intel_no_lvds))
return;
+ if (HAS_PCH_SPLIT(dev))
+ lvds_reg = PCH_LVDS;
+ else
+ lvds_reg = LVDS;
+
+ lvds = I915_READ(lvds_reg);
+
if (HAS_PCH_SPLIT(dev)) {
- if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
+ if ((lvds & LVDS_DETECTED) == 0)
return;
if (dev_priv->vbt.edp_support) {
DRM_DEBUG_KMS("disable LVDS for eDP support\n");
@@ -974,14 +980,25 @@ void intel_lvds_init(struct drm_device *dev)
pin = GMBUS_PIN_PANEL;
if (!lvds_is_present_in_vbt(dev, &pin)) {
- u32 reg = HAS_PCH_SPLIT(dev) ? PCH_LVDS : LVDS;
- if ((I915_READ(reg) & LVDS_PORT_EN) == 0) {
+ if ((lvds & LVDS_PORT_EN) == 0) {
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
return;
}
DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
}
+ /* Set the Panel Power On/Off timings if uninitialized. */
+ if (INTEL_INFO(dev_priv)->gen < 5 &&
+ I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
+ /* Set T2 to 40ms and T5 to 200ms */
+ I915_WRITE(PP_ON_DELAYS, 0x019007d0);
+
+ /* Set T3 to 35ms and Tx to 200ms */
+ I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
+
+ DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
+ }
+
lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
if (!lvds_encoder)
return;
@@ -1040,11 +1057,7 @@ void intel_lvds_init(struct drm_device *dev)
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- if (HAS_PCH_SPLIT(dev)) {
- lvds_encoder->reg = PCH_LVDS;
- } else {
- lvds_encoder->reg = LVDS;
- }
+ lvds_encoder->reg = lvds_reg;
/* create the scaling mode property */
drm_mode_create_scaling_mode_property(dev);
@@ -1125,7 +1138,6 @@ void intel_lvds_init(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev))
goto failed;
- lvds = I915_READ(LVDS);
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
crtc = intel_get_crtc_for_pipe(dev, pipe);
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 0e860f39933d..38a4c8ce7e63 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -126,3 +126,12 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector)
drm_object_attach_property(&connector->base, prop, 0);
}
+
+void
+intel_attach_aspect_ratio_property(struct drm_connector *connector)
+{
+ if (!drm_mode_create_aspect_ratio_property(connector->dev))
+ drm_object_attach_property(&connector->base,
+ connector->dev->mode_config.aspect_ratio_property,
+ DRM_MODE_PICTURE_ASPECT_NONE);
+}
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index cb1c65739425..6dc13c02c28e 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -239,7 +239,7 @@ struct opregion_asle {
static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct opregion_swsci __iomem *swsci = dev_priv->opregion.swsci;
+ struct opregion_swsci *swsci = dev_priv->opregion.swsci;
u32 main_function, sub_function, scic;
u16 pci_swsci;
u32 dslp;
@@ -264,7 +264,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
}
/* Driver sleep timeout in ms. */
- dslp = ioread32(&swsci->dslp);
+ dslp = swsci->dslp;
if (!dslp) {
/* The spec says 2ms should be the default, but it's too small
* for some machines. */
@@ -277,7 +277,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
}
/* The spec tells us to do this, but we are the only user... */
- scic = ioread32(&swsci->scic);
+ scic = swsci->scic;
if (scic & SWSCI_SCIC_INDICATOR) {
DRM_DEBUG_DRIVER("SWSCI request already in progress\n");
return -EBUSY;
@@ -285,8 +285,8 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
scic = function | SWSCI_SCIC_INDICATOR;
- iowrite32(parm, &swsci->parm);
- iowrite32(scic, &swsci->scic);
+ swsci->parm = parm;
+ swsci->scic = scic;
/* Ensure SCI event is selected and event trigger is cleared. */
pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci);
@@ -301,7 +301,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
/* Poll for the result. */
-#define C (((scic = ioread32(&swsci->scic)) & SWSCI_SCIC_INDICATOR) == 0)
+#define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
if (wait_for(C, dslp)) {
DRM_DEBUG_DRIVER("SWSCI request timed out\n");
return -ETIMEDOUT;
@@ -317,7 +317,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
}
if (parm_out)
- *parm_out = ioread32(&swsci->parm);
+ *parm_out = swsci->parm;
return 0;
@@ -341,8 +341,12 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
if (!HAS_DDI(dev))
return 0;
- port = intel_ddi_get_encoder_port(intel_encoder);
- if (port == PORT_E) {
+ if (intel_encoder->type == INTEL_OUTPUT_DSI)
+ port = 0;
+ else
+ port = intel_ddi_get_encoder_port(intel_encoder);
+
+ if (port == PORT_E) {
port = 0;
} else {
parm |= 1 << port;
@@ -363,6 +367,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
break;
case INTEL_OUTPUT_EDP:
+ case INTEL_OUTPUT_DSI:
type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
break;
default:
@@ -407,7 +412,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_connector *intel_connector;
- struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
@@ -432,7 +437,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
- iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
+ asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -519,14 +524,14 @@ static void asle_work(struct work_struct *work)
struct drm_i915_private *dev_priv =
container_of(opregion, struct drm_i915_private, opregion);
struct drm_device *dev = dev_priv->dev;
- struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
u32 aslc_stat = 0;
u32 aslc_req;
if (!asle)
return;
- aslc_req = ioread32(&asle->aslc);
+ aslc_req = asle->aslc;
if (!(aslc_req & ASLC_REQ_MSK)) {
DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n",
@@ -535,34 +540,34 @@ static void asle_work(struct work_struct *work)
}
if (aslc_req & ASLC_SET_ALS_ILLUM)
- aslc_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi));
+ aslc_stat |= asle_set_als_illum(dev, asle->alsi);
if (aslc_req & ASLC_SET_BACKLIGHT)
- aslc_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
+ aslc_stat |= asle_set_backlight(dev, asle->bclp);
if (aslc_req & ASLC_SET_PFIT)
- aslc_stat |= asle_set_pfit(dev, ioread32(&asle->pfit));
+ aslc_stat |= asle_set_pfit(dev, asle->pfit);
if (aslc_req & ASLC_SET_PWM_FREQ)
- aslc_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb));
+ aslc_stat |= asle_set_pwm_freq(dev, asle->pfmb);
if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
aslc_stat |= asle_set_supported_rotation_angles(dev,
- ioread32(&asle->srot));
+ asle->srot);
if (aslc_req & ASLC_BUTTON_ARRAY)
- aslc_stat |= asle_set_button_array(dev, ioread32(&asle->iuer));
+ aslc_stat |= asle_set_button_array(dev, asle->iuer);
if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
- aslc_stat |= asle_set_convertible(dev, ioread32(&asle->iuer));
+ aslc_stat |= asle_set_convertible(dev, asle->iuer);
if (aslc_req & ASLC_DOCKING_INDICATOR)
- aslc_stat |= asle_set_docking(dev, ioread32(&asle->iuer));
+ aslc_stat |= asle_set_docking(dev, asle->iuer);
if (aslc_req & ASLC_ISCT_STATE_CHANGE)
aslc_stat |= asle_isct_state(dev);
- iowrite32(aslc_stat, &asle->aslc);
+ asle->aslc = aslc_stat;
}
void intel_opregion_asle_intr(struct drm_device *dev)
@@ -587,8 +592,8 @@ static int intel_opregion_video_event(struct notifier_block *nb,
Linux, these are handled by the dock, button and video drivers.
*/
- struct opregion_acpi __iomem *acpi;
struct acpi_bus_event *event = data;
+ struct opregion_acpi *acpi;
int ret = NOTIFY_OK;
if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
@@ -599,11 +604,10 @@ static int intel_opregion_video_event(struct notifier_block *nb,
acpi = system_opregion->acpi;
- if (event->type == 0x80 &&
- (ioread32(&acpi->cevt) & 1) == 0)
+ if (event->type == 0x80 && ((acpi->cevt & 1) == 0))
ret = NOTIFY_BAD;
- iowrite32(0, &acpi->csts);
+ acpi->csts = 0;
return ret;
}
@@ -623,14 +627,14 @@ static u32 get_did(struct intel_opregion *opregion, int i)
u32 did;
if (i < ARRAY_SIZE(opregion->acpi->didl)) {
- did = ioread32(&opregion->acpi->didl[i]);
+ did = opregion->acpi->didl[i];
} else {
i -= ARRAY_SIZE(opregion->acpi->didl);
if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
return 0;
- did = ioread32(&opregion->acpi->did2[i]);
+ did = opregion->acpi->did2[i];
}
return did;
@@ -639,14 +643,14 @@ static u32 get_did(struct intel_opregion *opregion, int i)
static void set_did(struct intel_opregion *opregion, int i, u32 val)
{
if (i < ARRAY_SIZE(opregion->acpi->didl)) {
- iowrite32(val, &opregion->acpi->didl[i]);
+ opregion->acpi->didl[i] = val;
} else {
i -= ARRAY_SIZE(opregion->acpi->didl);
if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
return;
- iowrite32(val, &opregion->acpi->did2[i]);
+ opregion->acpi->did2[i] = val;
}
}
@@ -768,7 +772,7 @@ static void intel_setup_cadls(struct drm_device *dev)
* there are less than eight devices. */
do {
disp_id = get_did(opregion, i);
- iowrite32(disp_id, &opregion->acpi->cadl[i]);
+ opregion->acpi->cadl[i] = disp_id;
} while (++i < 8 && disp_id != 0);
}
@@ -787,16 +791,16 @@ void intel_opregion_init(struct drm_device *dev)
/* Notify BIOS we are ready to handle ACPI video ext notifs.
* Right now, all the events are handled by the ACPI video module.
* We don't actually need to do anything with them. */
- iowrite32(0, &opregion->acpi->csts);
- iowrite32(1, &opregion->acpi->drdy);
+ opregion->acpi->csts = 0;
+ opregion->acpi->drdy = 1;
system_opregion = opregion;
register_acpi_notifier(&intel_opregion_notifier);
}
if (opregion->asle) {
- iowrite32(ASLE_TCHE_BLC_EN, &opregion->asle->tche);
- iowrite32(ASLE_ARDY_READY, &opregion->asle->ardy);
+ opregion->asle->tche = ASLE_TCHE_BLC_EN;
+ opregion->asle->ardy = ASLE_ARDY_READY;
}
}
@@ -809,19 +813,19 @@ void intel_opregion_fini(struct drm_device *dev)
return;
if (opregion->asle)
- iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy);
+ opregion->asle->ardy = ASLE_ARDY_NOT_READY;
cancel_work_sync(&dev_priv->opregion.asle_work);
if (opregion->acpi) {
- iowrite32(0, &opregion->acpi->drdy);
+ opregion->acpi->drdy = 0;
system_opregion = NULL;
unregister_acpi_notifier(&intel_opregion_notifier);
}
/* just clear all opregion memory pointers now */
- iounmap(opregion->header);
+ memunmap(opregion->header);
opregion->header = NULL;
opregion->acpi = NULL;
opregion->swsci = NULL;
@@ -894,10 +898,10 @@ int intel_opregion_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
- void __iomem *base;
u32 asls, mboxes;
char buf[sizeof(OPREGION_SIGNATURE)];
int err = 0;
+ void *base;
BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100);
BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
@@ -915,11 +919,11 @@ int intel_opregion_setup(struct drm_device *dev)
INIT_WORK(&opregion->asle_work, asle_work);
#endif
- base = acpi_os_ioremap(asls, OPREGION_SIZE);
+ base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
if (!base)
return -ENOMEM;
- memcpy_fromio(buf, base, sizeof(buf));
+ memcpy(buf, base, sizeof(buf));
if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
DRM_DEBUG_DRIVER("opregion signature mismatch\n");
@@ -931,7 +935,7 @@ int intel_opregion_setup(struct drm_device *dev)
opregion->lid_state = base + ACPI_CLID;
- mboxes = ioread32(&opregion->header->mboxes);
+ mboxes = opregion->header->mboxes;
if (mboxes & MBOX_ACPI) {
DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
opregion->acpi = base + OPREGION_ACPI_OFFSET;
@@ -946,12 +950,12 @@ int intel_opregion_setup(struct drm_device *dev)
DRM_DEBUG_DRIVER("ASLE supported\n");
opregion->asle = base + OPREGION_ASLE_OFFSET;
- iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy);
+ opregion->asle->ardy = ASLE_ARDY_NOT_READY;
}
return 0;
err_out:
- iounmap(base);
+ memunmap(base);
return err;
}
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e2ab3f6ed022..a24df35e11e7 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -105,59 +105,55 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
struct intel_crtc_state *pipe_config,
int fitting_mode)
{
- struct drm_display_mode *adjusted_mode;
- int x, y, width, height;
-
- adjusted_mode = &pipe_config->base.adjusted_mode;
-
- x = y = width = height = 0;
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+ int x = 0, y = 0, width = 0, height = 0;
/* Native modes don't need fitting */
- if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
- adjusted_mode->vdisplay == pipe_config->pipe_src_h)
+ if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
+ adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
goto done;
switch (fitting_mode) {
case DRM_MODE_SCALE_CENTER:
width = pipe_config->pipe_src_w;
height = pipe_config->pipe_src_h;
- x = (adjusted_mode->hdisplay - width + 1)/2;
- y = (adjusted_mode->vdisplay - height + 1)/2;
+ x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
+ y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
break;
case DRM_MODE_SCALE_ASPECT:
/* Scale but preserve the aspect ratio */
{
- u32 scaled_width = adjusted_mode->hdisplay
+ u32 scaled_width = adjusted_mode->crtc_hdisplay
* pipe_config->pipe_src_h;
u32 scaled_height = pipe_config->pipe_src_w
- * adjusted_mode->vdisplay;
+ * adjusted_mode->crtc_vdisplay;
if (scaled_width > scaled_height) { /* pillar */
width = scaled_height / pipe_config->pipe_src_h;
if (width & 1)
width++;
- x = (adjusted_mode->hdisplay - width + 1) / 2;
+ x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
y = 0;
- height = adjusted_mode->vdisplay;
+ height = adjusted_mode->crtc_vdisplay;
} else if (scaled_width < scaled_height) { /* letter */
height = scaled_width / pipe_config->pipe_src_w;
if (height & 1)
height++;
- y = (adjusted_mode->vdisplay - height + 1) / 2;
+ y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
x = 0;
- width = adjusted_mode->hdisplay;
+ width = adjusted_mode->crtc_hdisplay;
} else {
x = y = 0;
- width = adjusted_mode->hdisplay;
- height = adjusted_mode->vdisplay;
+ width = adjusted_mode->crtc_hdisplay;
+ height = adjusted_mode->crtc_vdisplay;
}
}
break;
case DRM_MODE_SCALE_FULLSCREEN:
x = y = 0;
- width = adjusted_mode->hdisplay;
- height = adjusted_mode->vdisplay;
+ width = adjusted_mode->crtc_hdisplay;
+ height = adjusted_mode->crtc_vdisplay;
break;
default:
@@ -172,46 +168,46 @@ done:
}
static void
-centre_horizontally(struct drm_display_mode *mode,
+centre_horizontally(struct drm_display_mode *adjusted_mode,
int width)
{
u32 border, sync_pos, blank_width, sync_width;
/* keep the hsync and hblank widths constant */
- sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
- blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
+ sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+ blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
sync_pos = (blank_width - sync_width + 1) / 2;
- border = (mode->hdisplay - width + 1) / 2;
+ border = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
border += border & 1; /* make the border even */
- mode->crtc_hdisplay = width;
- mode->crtc_hblank_start = width + border;
- mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
+ adjusted_mode->crtc_hdisplay = width;
+ adjusted_mode->crtc_hblank_start = width + border;
+ adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width;
- mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
- mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
+ adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos;
+ adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width;
}
static void
-centre_vertically(struct drm_display_mode *mode,
+centre_vertically(struct drm_display_mode *adjusted_mode,
int height)
{
u32 border, sync_pos, blank_width, sync_width;
/* keep the vsync and vblank widths constant */
- sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
- blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
+ sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
+ blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start;
sync_pos = (blank_width - sync_width + 1) / 2;
- border = (mode->vdisplay - height + 1) / 2;
+ border = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
- mode->crtc_vdisplay = height;
- mode->crtc_vblank_start = height + border;
- mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
+ adjusted_mode->crtc_vdisplay = height;
+ adjusted_mode->crtc_vblank_start = height + border;
+ adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width;
- mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
- mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
+ adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos;
+ adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width;
}
static inline u32 panel_fitter_scaling(u32 source, u32 target)
@@ -230,11 +226,11 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target)
static void i965_scale_aspect(struct intel_crtc_state *pipe_config,
u32 *pfit_control)
{
- struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
- u32 scaled_width = adjusted_mode->hdisplay *
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+ u32 scaled_width = adjusted_mode->crtc_hdisplay *
pipe_config->pipe_src_h;
u32 scaled_height = pipe_config->pipe_src_w *
- adjusted_mode->vdisplay;
+ adjusted_mode->crtc_vdisplay;
/* 965+ is easy, it does everything in hw */
if (scaled_width > scaled_height)
@@ -243,7 +239,7 @@ static void i965_scale_aspect(struct intel_crtc_state *pipe_config,
else if (scaled_width < scaled_height)
*pfit_control |= PFIT_ENABLE |
PFIT_SCALING_LETTER;
- else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
+ else if (adjusted_mode->crtc_hdisplay != pipe_config->pipe_src_w)
*pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
}
@@ -252,10 +248,10 @@ static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config,
u32 *border)
{
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
- u32 scaled_width = adjusted_mode->hdisplay *
+ u32 scaled_width = adjusted_mode->crtc_hdisplay *
pipe_config->pipe_src_h;
u32 scaled_height = pipe_config->pipe_src_w *
- adjusted_mode->vdisplay;
+ adjusted_mode->crtc_vdisplay;
u32 bits;
/*
@@ -269,9 +265,9 @@ static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config,
pipe_config->pipe_src_h);
*border = LVDS_BORDER_ENABLE;
- if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
+ if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay) {
bits = panel_fitter_scaling(pipe_config->pipe_src_h,
- adjusted_mode->vdisplay);
+ adjusted_mode->crtc_vdisplay);
*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
bits << PFIT_VERT_SCALE_SHIFT);
@@ -285,9 +281,9 @@ static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config,
pipe_config->pipe_src_w);
*border = LVDS_BORDER_ENABLE;
- if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
+ if (pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
bits = panel_fitter_scaling(pipe_config->pipe_src_w,
- adjusted_mode->hdisplay);
+ adjusted_mode->crtc_hdisplay);
*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
bits << PFIT_VERT_SCALE_SHIFT);
@@ -310,13 +306,11 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
{
struct drm_device *dev = intel_crtc->base.dev;
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
- struct drm_display_mode *adjusted_mode;
-
- adjusted_mode = &pipe_config->base.adjusted_mode;
+ struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
/* Native modes don't need fitting */
- if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
- adjusted_mode->vdisplay == pipe_config->pipe_src_h)
+ if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
+ adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
goto out;
switch (fitting_mode) {
@@ -342,8 +336,8 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
* Full scaling, even if it changes the aspect ratio.
* Fortunately this is all done for us in hw.
*/
- if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
- pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
+ if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay ||
+ pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
pfit_control |= PFIT_ENABLE;
if (INTEL_INFO(dev)->gen >= 4)
pfit_control |= PFIT_SCALING_AUTO;
@@ -387,7 +381,7 @@ intel_panel_detect(struct drm_device *dev)
/* Assume that the BIOS does not lie through the OpRegion... */
if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
- return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
+ return *dev_priv->opregion.lid_state & 0x1 ?
connector_status_connected :
connector_status_disconnected;
}
@@ -484,7 +478,7 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector,
return val;
}
-static u32 bdw_get_backlight(struct intel_connector *connector)
+static u32 lpt_get_backlight(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -542,9 +536,10 @@ static u32 vlv_get_backlight(struct intel_connector *connector)
static u32 bxt_get_backlight(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
+ struct intel_panel *panel = &connector->panel;
struct drm_i915_private *dev_priv = dev->dev_private;
- return I915_READ(BXT_BLC_PWM_DUTY1);
+ return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller));
}
static u32 pwm_get_backlight(struct intel_connector *connector)
@@ -566,7 +561,7 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector)
mutex_lock(&dev_priv->backlight_lock);
if (panel->backlight.enabled) {
- val = dev_priv->display.get_backlight(connector);
+ val = panel->backlight.get(connector);
val = intel_panel_compute_brightness(connector, val);
}
@@ -576,7 +571,7 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector)
return val;
}
-static void bdw_set_backlight(struct intel_connector *connector, u32 level)
+static void lpt_set_backlight(struct intel_connector *connector, u32 level)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -640,8 +635,9 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_panel *panel = &connector->panel;
- I915_WRITE(BXT_BLC_PWM_DUTY1, level);
+ I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
}
static void pwm_set_backlight(struct intel_connector *connector, u32 level)
@@ -655,13 +651,12 @@ static void pwm_set_backlight(struct intel_connector *connector, u32 level)
static void
intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
{
- struct drm_device *dev = connector->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_panel *panel = &connector->panel;
DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
level = intel_panel_compute_brightness(connector, level);
- dev_priv->display.set_backlight(connector, level);
+ panel->backlight.set(connector, level);
}
/* set backlight brightness to level in range [0..max], scaling wrt hw min */
@@ -729,6 +724,32 @@ void intel_panel_set_backlight_acpi(struct intel_connector *connector,
mutex_unlock(&dev_priv->backlight_lock);
}
+static void lpt_disable_backlight(struct intel_connector *connector)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 tmp;
+
+ intel_panel_actually_set_backlight(connector, 0);
+
+ /*
+ * Although we don't support or enable CPU PWM with LPT/SPT based
+ * systems, it may have been enabled prior to loading the
+ * driver. Disable to avoid warnings on LCPLL disable.
+ *
+ * This needs rework if we need to add support for CPU PWM on PCH split
+ * platforms.
+ */
+ tmp = I915_READ(BLC_PWM_CPU_CTL2);
+ if (tmp & BLM_PWM_ENABLE) {
+ DRM_DEBUG_KMS("cpu backlight was enabled, disabling\n");
+ I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
+ }
+
+ tmp = I915_READ(BLC_PWM_PCH_CTL1);
+ I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
+}
+
static void pch_disable_backlight(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
@@ -781,12 +802,20 @@ static void bxt_disable_backlight(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 tmp;
+ struct intel_panel *panel = &connector->panel;
+ u32 tmp, val;
intel_panel_actually_set_backlight(connector, 0);
- tmp = I915_READ(BXT_BLC_PWM_CTL1);
- I915_WRITE(BXT_BLC_PWM_CTL1, tmp & ~BXT_BLC_PWM_ENABLE);
+ tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
+ I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
+ tmp & ~BXT_BLC_PWM_ENABLE);
+
+ if (panel->backlight.controller == 1) {
+ val = I915_READ(UTIL_PIN_CTL);
+ val &= ~UTIL_PIN_ENABLE;
+ I915_WRITE(UTIL_PIN_CTL, val);
+ }
}
static void pwm_disable_backlight(struct intel_connector *connector)
@@ -809,7 +838,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
return;
/*
- * Do not disable backlight on the vgaswitcheroo path. When switching
+ * Do not disable backlight on the vga_switcheroo path. When switching
* away from i915, the other client may depend on i915 to handle the
* backlight. This will leave the backlight on unnecessarily when
* another client is not activated.
@@ -824,12 +853,12 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
if (panel->backlight.device)
panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
panel->backlight.enabled = false;
- dev_priv->display.disable_backlight(connector);
+ panel->backlight.disable(connector);
mutex_unlock(&dev_priv->backlight_lock);
}
-static void bdw_enable_backlight(struct intel_connector *connector)
+static void lpt_enable_backlight(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1018,16 +1047,38 @@ static void bxt_enable_backlight(struct intel_connector *connector)
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_panel *panel = &connector->panel;
- u32 pwm_ctl;
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
+ u32 pwm_ctl, val;
+
+ /* To use 2nd set of backlight registers, utility pin has to be
+ * enabled with PWM mode.
+ * The field should only be changed when the utility pin is disabled
+ */
+ if (panel->backlight.controller == 1) {
+ val = I915_READ(UTIL_PIN_CTL);
+ if (val & UTIL_PIN_ENABLE) {
+ DRM_DEBUG_KMS("util pin already enabled\n");
+ val &= ~UTIL_PIN_ENABLE;
+ I915_WRITE(UTIL_PIN_CTL, val);
+ }
- pwm_ctl = I915_READ(BXT_BLC_PWM_CTL1);
+ val = 0;
+ if (panel->backlight.util_pin_active_low)
+ val |= UTIL_PIN_POLARITY;
+ I915_WRITE(UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) |
+ UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE);
+ }
+
+ pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
if (pwm_ctl & BXT_BLC_PWM_ENABLE) {
DRM_DEBUG_KMS("backlight already enabled\n");
pwm_ctl &= ~BXT_BLC_PWM_ENABLE;
- I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl);
+ I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
+ pwm_ctl);
}
- I915_WRITE(BXT_BLC_PWM_FREQ1, panel->backlight.max);
+ I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller),
+ panel->backlight.max);
intel_panel_actually_set_backlight(connector, panel->backlight.level);
@@ -1035,9 +1086,10 @@ static void bxt_enable_backlight(struct intel_connector *connector)
if (panel->backlight.active_low_pwm)
pwm_ctl |= BXT_BLC_PWM_POLARITY;
- I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl);
- POSTING_READ(BXT_BLC_PWM_CTL1);
- I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE);
+ I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl);
+ POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
+ I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
+ pwm_ctl | BXT_BLC_PWM_ENABLE);
}
static void pwm_enable_backlight(struct intel_connector *connector)
@@ -1073,7 +1125,7 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
panel->backlight.device->props.max_brightness);
}
- dev_priv->display.enable_backlight(connector);
+ panel->backlight.enable(connector);
panel->backlight.enabled = true;
if (panel->backlight.device)
panel->backlight.device->props.power = FB_BLANK_UNBLANK;
@@ -1101,10 +1153,10 @@ static int intel_backlight_device_update_status(struct backlight_device *bd)
* callback needs to take this into account.
*/
if (panel->backlight.enabled) {
- if (panel->backlight_power) {
+ if (panel->backlight.power) {
bool enable = bd->props.power == FB_BLANK_UNBLANK &&
bd->props.brightness != 0;
- panel->backlight_power(connector, enable);
+ panel->backlight.power(connector, enable);
}
} else {
bd->props.power = FB_BLANK_POWERDOWN;
@@ -1212,10 +1264,150 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
/*
- * Note: The setup hooks can't assume pipe is set!
+ * SPT: This value represents the period of the PWM stream in clock periods
+ * multiplied by 16 (default increment) or 128 (alternate increment selected in
+ * SCHICKEN_1 bit 0). PWM clock is 24 MHz.
+ */
+static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 mul, clock;
+
+ if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
+ mul = 128;
+ else
+ mul = 16;
+
+ clock = MHz(24);
+
+ return clock / (pwm_freq_hz * mul);
+}
+
+/*
+ * LPT: This value represents the period of the PWM stream in clock periods
+ * multiplied by 128 (default increment) or 16 (alternate increment, selected in
+ * LPT SOUTH_CHICKEN2 register bit 5).
+ */
+static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 mul, clock;
+
+ if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY)
+ mul = 16;
+ else
+ mul = 128;
+
+ if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
+ clock = MHz(135); /* LPT:H */
+ else
+ clock = MHz(24); /* LPT:LP */
+
+ return clock / (pwm_freq_hz * mul);
+}
+
+/*
+ * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH
+ * display raw clocks multiplied by 128.
+ */
+static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
+{
+ struct drm_device *dev = connector->base.dev;
+ int clock = MHz(intel_pch_rawclk(dev));
+
+ return clock / (pwm_freq_hz * 128);
+}
+
+/*
+ * Gen2: This field determines the number of time base events (display core
+ * clock frequency/32) in total for a complete cycle of modulated backlight
+ * control.
*
- * XXX: Query mode clock or hardware clock and program PWM modulation frequency
- * appropriately when it's 0. Use VBT and/or sane defaults.
+ * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock)
+ * divided by 32.
+ */
+static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int clock;
+
+ if (IS_PINEVIEW(dev))
+ clock = intel_hrawclk(dev);
+ else
+ clock = 1000 * dev_priv->display.get_display_clock_speed(dev);
+
+ return clock / (pwm_freq_hz * 32);
+}
+
+/*
+ * Gen4: This value represents the period of the PWM stream in display core
+ * clocks multiplied by 128.
+ */
+static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int clock = 1000 * dev_priv->display.get_display_clock_speed(dev);
+
+ return clock / (pwm_freq_hz * 128);
+}
+
+/*
+ * VLV: This value represents the period of the PWM stream in display core
+ * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks
+ * multiplied by 16. CHV uses a 19.2MHz S0IX clock.
+ */
+static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int clock;
+
+ if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
+ if (IS_CHERRYVIEW(dev))
+ return KHz(19200) / (pwm_freq_hz * 16);
+ else
+ return MHz(25) / (pwm_freq_hz * 16);
+ } else {
+ clock = intel_hrawclk(dev);
+ return MHz(clock) / (pwm_freq_hz * 128);
+ }
+}
+
+static u32 get_backlight_max_vbt(struct intel_connector *connector)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_panel *panel = &connector->panel;
+ u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz;
+ u32 pwm;
+
+ if (!pwm_freq_hz) {
+ DRM_DEBUG_KMS("backlight frequency not specified in VBT\n");
+ return 0;
+ }
+
+ if (!panel->backlight.hz_to_pwm) {
+ DRM_DEBUG_KMS("backlight frequency setting from VBT currently not supported on this platform\n");
+ return 0;
+ }
+
+ pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz);
+ if (!pwm) {
+ DRM_DEBUG_KMS("backlight frequency conversion failed\n");
+ return 0;
+ }
+
+ DRM_DEBUG_KMS("backlight frequency %u Hz from VBT\n", pwm_freq_hz);
+
+ return pwm;
+}
+
+/*
+ * Note: The setup hooks can't assume pipe is set!
*/
static u32 get_backlight_min_vbt(struct intel_connector *connector)
{
@@ -1243,7 +1435,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector)
return scale(min, 0, 255, 0, panel->backlight.max);
}
-static int bdw_setup_backlight(struct intel_connector *connector, enum pipe unused)
+static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1255,12 +1447,16 @@ static int bdw_setup_backlight(struct intel_connector *connector, enum pipe unus
pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
panel->backlight.max = pch_ctl2 >> 16;
+
+ if (!panel->backlight.max)
+ panel->backlight.max = get_backlight_max_vbt(connector);
+
if (!panel->backlight.max)
return -ENODEV;
panel->backlight.min = get_backlight_min_vbt(connector);
- val = bdw_get_backlight(connector);
+ val = lpt_get_backlight(connector);
panel->backlight.level = intel_panel_compute_brightness(connector, val);
panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
@@ -1281,6 +1477,10 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus
pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
panel->backlight.max = pch_ctl2 >> 16;
+
+ if (!panel->backlight.max)
+ panel->backlight.max = get_backlight_max_vbt(connector);
+
if (!panel->backlight.max)
return -ENODEV;
@@ -1312,12 +1512,18 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu
panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
panel->backlight.max = ctl >> 17;
- if (panel->backlight.combination_mode)
- panel->backlight.max *= 0xff;
+
+ if (!panel->backlight.max) {
+ panel->backlight.max = get_backlight_max_vbt(connector);
+ panel->backlight.max >>= 1;
+ }
if (!panel->backlight.max)
return -ENODEV;
+ if (panel->backlight.combination_mode)
+ panel->backlight.max *= 0xff;
+
panel->backlight.min = get_backlight_min_vbt(connector);
val = i9xx_get_backlight(connector);
@@ -1341,12 +1547,16 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu
ctl = I915_READ(BLC_PWM_CTL);
panel->backlight.max = ctl >> 16;
- if (panel->backlight.combination_mode)
- panel->backlight.max *= 0xff;
+
+ if (!panel->backlight.max)
+ panel->backlight.max = get_backlight_max_vbt(connector);
if (!panel->backlight.max)
return -ENODEV;
+ if (panel->backlight.combination_mode)
+ panel->backlight.max *= 0xff;
+
panel->backlight.min = get_backlight_min_vbt(connector);
val = i9xx_get_backlight(connector);
@@ -1363,21 +1573,8 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_panel *panel = &connector->panel;
- enum pipe p;
u32 ctl, ctl2, val;
- for_each_pipe(dev_priv, p) {
- u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(p));
-
- /* Skip if the modulation freq is already set */
- if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
- continue;
-
- cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
- I915_WRITE(VLV_BLC_PWM_CTL(p), (0xf42 << 16) |
- cur_val);
- }
-
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
return -ENODEV;
@@ -1386,6 +1583,10 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe
ctl = I915_READ(VLV_BLC_PWM_CTL(pipe));
panel->backlight.max = ctl >> 16;
+
+ if (!panel->backlight.max)
+ panel->backlight.max = get_backlight_max_vbt(connector);
+
if (!panel->backlight.max)
return -ENODEV;
@@ -1408,10 +1609,32 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
struct intel_panel *panel = &connector->panel;
u32 pwm_ctl, val;
- pwm_ctl = I915_READ(BXT_BLC_PWM_CTL1);
+ /*
+ * For BXT hard coding the Backlight controller to 0.
+ * TODO : Read the controller value from VBT and generalize
+ */
+ panel->backlight.controller = 0;
+
+ pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
+
+ /* Keeping the check if controller 1 is to be programmed.
+ * This will come into affect once the VBT parsing
+ * is fixed for controller selection, and controller 1 is used
+ * for a prticular display configuration.
+ */
+ if (panel->backlight.controller == 1) {
+ val = I915_READ(UTIL_PIN_CTL);
+ panel->backlight.util_pin_active_low =
+ val & UTIL_PIN_POLARITY;
+ }
+
panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
+ panel->backlight.max =
+ I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller));
+
+ if (!panel->backlight.max)
+ panel->backlight.max = get_backlight_max_vbt(connector);
- panel->backlight.max = I915_READ(BXT_BLC_PWM_FREQ1);
if (!panel->backlight.max)
return -ENODEV;
@@ -1475,9 +1698,13 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
}
}
+ /* ensure intel_panel has been initialized first */
+ if (WARN_ON(!panel->backlight.setup))
+ return -ENODEV;
+
/* set level and max in panel struct */
mutex_lock(&dev_priv->backlight_lock);
- ret = dev_priv->display.setup_backlight(intel_connector, pipe);
+ ret = panel->backlight.setup(intel_connector, pipe);
mutex_unlock(&dev_priv->backlight_lock);
if (ret) {
@@ -1509,54 +1736,66 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
}
/* Set up chip specific backlight functions */
-void intel_panel_init_backlight_funcs(struct drm_device *dev)
+static void
+intel_panel_init_backlight_funcs(struct intel_panel *panel)
{
+ struct intel_connector *intel_connector =
+ container_of(panel, struct intel_connector, panel);
+ struct drm_device *dev = intel_connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (IS_BROXTON(dev)) {
- dev_priv->display.setup_backlight = bxt_setup_backlight;
- dev_priv->display.enable_backlight = bxt_enable_backlight;
- dev_priv->display.disable_backlight = bxt_disable_backlight;
- dev_priv->display.set_backlight = bxt_set_backlight;
- dev_priv->display.get_backlight = bxt_get_backlight;
- } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev)) {
- dev_priv->display.setup_backlight = bdw_setup_backlight;
- dev_priv->display.enable_backlight = bdw_enable_backlight;
- dev_priv->display.disable_backlight = pch_disable_backlight;
- dev_priv->display.set_backlight = bdw_set_backlight;
- dev_priv->display.get_backlight = bdw_get_backlight;
+ panel->backlight.setup = bxt_setup_backlight;
+ panel->backlight.enable = bxt_enable_backlight;
+ panel->backlight.disable = bxt_disable_backlight;
+ panel->backlight.set = bxt_set_backlight;
+ panel->backlight.get = bxt_get_backlight;
+ } else if (HAS_PCH_LPT(dev) || HAS_PCH_SPT(dev)) {
+ panel->backlight.setup = lpt_setup_backlight;
+ panel->backlight.enable = lpt_enable_backlight;
+ panel->backlight.disable = lpt_disable_backlight;
+ panel->backlight.set = lpt_set_backlight;
+ panel->backlight.get = lpt_get_backlight;
+ if (HAS_PCH_LPT(dev))
+ panel->backlight.hz_to_pwm = lpt_hz_to_pwm;
+ else
+ panel->backlight.hz_to_pwm = spt_hz_to_pwm;
} else if (HAS_PCH_SPLIT(dev)) {
- dev_priv->display.setup_backlight = pch_setup_backlight;
- dev_priv->display.enable_backlight = pch_enable_backlight;
- dev_priv->display.disable_backlight = pch_disable_backlight;
- dev_priv->display.set_backlight = pch_set_backlight;
- dev_priv->display.get_backlight = pch_get_backlight;
+ panel->backlight.setup = pch_setup_backlight;
+ panel->backlight.enable = pch_enable_backlight;
+ panel->backlight.disable = pch_disable_backlight;
+ panel->backlight.set = pch_set_backlight;
+ panel->backlight.get = pch_get_backlight;
+ panel->backlight.hz_to_pwm = pch_hz_to_pwm;
} else if (IS_VALLEYVIEW(dev)) {
if (dev_priv->vbt.has_mipi) {
- dev_priv->display.setup_backlight = pwm_setup_backlight;
- dev_priv->display.enable_backlight = pwm_enable_backlight;
- dev_priv->display.disable_backlight = pwm_disable_backlight;
- dev_priv->display.set_backlight = pwm_set_backlight;
- dev_priv->display.get_backlight = pwm_get_backlight;
+ panel->backlight.setup = pwm_setup_backlight;
+ panel->backlight.enable = pwm_enable_backlight;
+ panel->backlight.disable = pwm_disable_backlight;
+ panel->backlight.set = pwm_set_backlight;
+ panel->backlight.get = pwm_get_backlight;
} else {
- dev_priv->display.setup_backlight = vlv_setup_backlight;
- dev_priv->display.enable_backlight = vlv_enable_backlight;
- dev_priv->display.disable_backlight = vlv_disable_backlight;
- dev_priv->display.set_backlight = vlv_set_backlight;
- dev_priv->display.get_backlight = vlv_get_backlight;
+ panel->backlight.setup = vlv_setup_backlight;
+ panel->backlight.enable = vlv_enable_backlight;
+ panel->backlight.disable = vlv_disable_backlight;
+ panel->backlight.set = vlv_set_backlight;
+ panel->backlight.get = vlv_get_backlight;
+ panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
}
} else if (IS_GEN4(dev)) {
- dev_priv->display.setup_backlight = i965_setup_backlight;
- dev_priv->display.enable_backlight = i965_enable_backlight;
- dev_priv->display.disable_backlight = i965_disable_backlight;
- dev_priv->display.set_backlight = i9xx_set_backlight;
- dev_priv->display.get_backlight = i9xx_get_backlight;
+ panel->backlight.setup = i965_setup_backlight;
+ panel->backlight.enable = i965_enable_backlight;
+ panel->backlight.disable = i965_disable_backlight;
+ panel->backlight.set = i9xx_set_backlight;
+ panel->backlight.get = i9xx_get_backlight;
+ panel->backlight.hz_to_pwm = i965_hz_to_pwm;
} else {
- dev_priv->display.setup_backlight = i9xx_setup_backlight;
- dev_priv->display.enable_backlight = i9xx_enable_backlight;
- dev_priv->display.disable_backlight = i9xx_disable_backlight;
- dev_priv->display.set_backlight = i9xx_set_backlight;
- dev_priv->display.get_backlight = i9xx_get_backlight;
+ panel->backlight.setup = i9xx_setup_backlight;
+ panel->backlight.enable = i9xx_enable_backlight;
+ panel->backlight.disable = i9xx_disable_backlight;
+ panel->backlight.set = i9xx_set_backlight;
+ panel->backlight.get = i9xx_get_backlight;
+ panel->backlight.hz_to_pwm = i9xx_hz_to_pwm;
}
}
@@ -1564,6 +1803,8 @@ int intel_panel_init(struct intel_panel *panel,
struct drm_display_mode *fixed_mode,
struct drm_display_mode *downclock_mode)
{
+ intel_panel_init_backlight_funcs(panel);
+
panel->fixed_mode = fixed_mode;
panel->downclock_mode = downclock_mode;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ddbb7ed0a193..071a76b9ac52 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -52,82 +52,20 @@
#define INTEL_RC6p_ENABLE (1<<1)
#define INTEL_RC6pp_ENABLE (1<<2)
-static void gen9_init_clock_gating(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- /* WaEnableLbsSlaRetryTimerDecrement:skl */
- I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
- GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
-
- /* WaDisableKillLogic:bxt,skl */
- I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
- ECOCHK_DIS_TLB);
-}
-
-static void skl_init_clock_gating(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- gen9_init_clock_gating(dev);
-
- if (INTEL_REVID(dev) <= SKL_REVID_B0) {
- /*
- * WaDisableSDEUnitClockGating:skl
- * WaSetGAPSunitClckGateDisable:skl
- */
- I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
- GEN8_GAPSUNIT_CLOCK_GATE_DISABLE |
- GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
-
- /* WaDisableVFUnitClockGating:skl */
- I915_WRITE(GEN6_UCGCTL2, I915_READ(GEN6_UCGCTL2) |
- GEN6_VFUNIT_CLOCK_GATE_DISABLE);
- }
-
- if (INTEL_REVID(dev) <= SKL_REVID_D0) {
- /* WaDisableHDCInvalidation:skl */
- I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
- BDW_DISABLE_HDC_INVALIDATION);
-
- /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
- I915_WRITE(FF_SLICE_CS_CHICKEN2,
- _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
- }
-
- /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
- * involving this register should also be added to WA batch as required.
- */
- if (INTEL_REVID(dev) <= SKL_REVID_E0)
- /* WaDisableLSQCROPERFforOCL:skl */
- I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
- GEN8_LQSC_RO_PERF_DIS);
-
- /* WaEnableGapsTsvCreditFix:skl */
- if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) {
- I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
- GEN9_GAPS_TSV_CREDIT_DISABLE));
- }
-}
-
static void bxt_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- gen9_init_clock_gating(dev);
+ /* WaDisableSDEUnitClockGating:bxt */
+ I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
+ GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
/*
* FIXME:
- * GEN8_SDEUNIT_CLOCK_GATE_DISABLE applies on A0 only.
* GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ applies on 3x6 GT SKUs only.
*/
- /* WaDisableSDEUnitClockGating:bxt */
I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
- GEN8_SDEUNIT_CLOCK_GATE_DISABLE |
GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ);
-
- /* FIXME: apply on A0 only */
- I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
}
static void i915_pineview_get_mem_freq(struct drm_device *dev)
@@ -691,12 +629,9 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
crtc = single_enabled_crtc(dev);
if (crtc) {
- const struct drm_display_mode *adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
- int clock;
-
- adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
- clock = adjusted_mode->crtc_clock;
+ int clock = adjusted_mode->crtc_clock;
/* Display SR */
wm = intel_calculate_wm(clock, &pineview_display_wm,
@@ -1200,7 +1135,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
case DRM_PLANE_TYPE_CURSOR:
for (level = 0; level < wm_state->num_levels; level++)
wm_state->sr[level].cursor =
- wm_state->sr[level].cursor;
+ wm_state->wm[level].cursor;
break;
case DRM_PLANE_TYPE_PRIMARY:
for (level = 0; level < wm_state->num_levels; level++)
@@ -1490,8 +1425,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
if (crtc) {
/* self-refresh has much higher latency */
static const int sr_latency_ns = 12000;
- const struct drm_display_mode *adjusted_mode =
- &to_intel_crtc(crtc)->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
int clock = adjusted_mode->crtc_clock;
int htotal = adjusted_mode->crtc_htotal;
int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
@@ -1638,8 +1572,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
if (HAS_FW_BLC(dev) && enabled) {
/* self-refresh has much higher latency */
static const int sr_latency_ns = 6000;
- const struct drm_display_mode *adjusted_mode =
- &to_intel_crtc(enabled)->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &to_intel_crtc(enabled)->config->base.adjusted_mode;
int clock = adjusted_mode->crtc_clock;
int htotal = adjusted_mode->crtc_htotal;
int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w;
@@ -1780,16 +1713,6 @@ struct skl_pipe_wm_parameters {
uint32_t pipe_htotal;
uint32_t pixel_rate; /* in KHz */
struct intel_plane_wm_parameters plane[I915_MAX_PLANES];
- struct intel_plane_wm_parameters cursor;
-};
-
-struct ilk_pipe_wm_parameters {
- bool active;
- uint32_t pipe_htotal;
- uint32_t pixel_rate;
- struct intel_plane_wm_parameters pri;
- struct intel_plane_wm_parameters spr;
- struct intel_plane_wm_parameters cur;
};
struct ilk_wm_maximums {
@@ -1810,26 +1733,26 @@ struct intel_wm_config {
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
*/
-static uint32_t ilk_compute_pri_wm(const struct ilk_pipe_wm_parameters *params,
+static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
+ const struct intel_plane_state *pstate,
uint32_t mem_value,
bool is_lp)
{
+ int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
uint32_t method1, method2;
- if (!params->active || !params->pri.enabled)
+ if (!cstate->base.active || !pstate->visible)
return 0;
- method1 = ilk_wm_method1(params->pixel_rate,
- params->pri.bytes_per_pixel,
- mem_value);
+ method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value);
if (!is_lp)
return method1;
- method2 = ilk_wm_method2(params->pixel_rate,
- params->pipe_htotal,
- params->pri.horiz_pixels,
- params->pri.bytes_per_pixel,
+ method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
+ cstate->base.adjusted_mode.crtc_htotal,
+ drm_rect_width(&pstate->dst),
+ bpp,
mem_value);
return min(method1, method2);
@@ -1839,21 +1762,21 @@ static uint32_t ilk_compute_pri_wm(const struct ilk_pipe_wm_parameters *params,
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
*/
-static uint32_t ilk_compute_spr_wm(const struct ilk_pipe_wm_parameters *params,
+static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
+ const struct intel_plane_state *pstate,
uint32_t mem_value)
{
+ int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
uint32_t method1, method2;
- if (!params->active || !params->spr.enabled)
+ if (!cstate->base.active || !pstate->visible)
return 0;
- method1 = ilk_wm_method1(params->pixel_rate,
- params->spr.bytes_per_pixel,
- mem_value);
- method2 = ilk_wm_method2(params->pixel_rate,
- params->pipe_htotal,
- params->spr.horiz_pixels,
- params->spr.bytes_per_pixel,
+ method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value);
+ method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
+ cstate->base.adjusted_mode.crtc_htotal,
+ drm_rect_width(&pstate->dst),
+ bpp,
mem_value);
return min(method1, method2);
}
@@ -1862,29 +1785,33 @@ static uint32_t ilk_compute_spr_wm(const struct ilk_pipe_wm_parameters *params,
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
*/
-static uint32_t ilk_compute_cur_wm(const struct ilk_pipe_wm_parameters *params,
+static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
+ const struct intel_plane_state *pstate,
uint32_t mem_value)
{
- if (!params->active || !params->cur.enabled)
+ int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+
+ if (!cstate->base.active || !pstate->visible)
return 0;
- return ilk_wm_method2(params->pixel_rate,
- params->pipe_htotal,
- params->cur.horiz_pixels,
- params->cur.bytes_per_pixel,
+ return ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
+ cstate->base.adjusted_mode.crtc_htotal,
+ drm_rect_width(&pstate->dst),
+ bpp,
mem_value);
}
/* Only for WM_LP. */
-static uint32_t ilk_compute_fbc_wm(const struct ilk_pipe_wm_parameters *params,
+static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
+ const struct intel_plane_state *pstate,
uint32_t pri_val)
{
- if (!params->active || !params->pri.enabled)
+ int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+
+ if (!cstate->base.active || !pstate->visible)
return 0;
- return ilk_wm_fbc(pri_val,
- params->pri.horiz_pixels,
- params->pri.bytes_per_pixel);
+ return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), bpp);
}
static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
@@ -2049,10 +1976,12 @@ static bool ilk_validate_wm_level(int level,
}
static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
+ const struct intel_crtc *intel_crtc,
int level,
- const struct ilk_pipe_wm_parameters *p,
+ struct intel_crtc_state *cstate,
struct intel_wm_level *result)
{
+ struct intel_plane *intel_plane;
uint16_t pri_latency = dev_priv->wm.pri_latency[level];
uint16_t spr_latency = dev_priv->wm.spr_latency[level];
uint16_t cur_latency = dev_priv->wm.cur_latency[level];
@@ -2064,10 +1993,29 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
cur_latency *= 5;
}
- result->pri_val = ilk_compute_pri_wm(p, pri_latency, level);
- result->spr_val = ilk_compute_spr_wm(p, spr_latency);
- result->cur_val = ilk_compute_cur_wm(p, cur_latency);
- result->fbc_val = ilk_compute_fbc_wm(p, result->pri_val);
+ for_each_intel_plane_on_crtc(dev_priv->dev, intel_crtc, intel_plane) {
+ struct intel_plane_state *pstate =
+ to_intel_plane_state(intel_plane->base.state);
+
+ switch (intel_plane->base.type) {
+ case DRM_PLANE_TYPE_PRIMARY:
+ result->pri_val = ilk_compute_pri_wm(cstate, pstate,
+ pri_latency,
+ level);
+ result->fbc_val = ilk_compute_fbc_wm(cstate, pstate,
+ result->pri_val);
+ break;
+ case DRM_PLANE_TYPE_OVERLAY:
+ result->spr_val = ilk_compute_spr_wm(cstate, pstate,
+ spr_latency);
+ break;
+ case DRM_PLANE_TYPE_CURSOR:
+ result->cur_val = ilk_compute_cur_wm(cstate, pstate,
+ cur_latency);
+ break;
+ }
+ }
+
result->enable = true;
}
@@ -2076,7 +2024,7 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_display_mode *mode = &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
u32 linetime, ips_linetime;
if (!intel_crtc->active)
@@ -2085,9 +2033,9 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
/* The WM are computed with base on how long it takes to fill a single
* row at the given clock rate, multiplied by 8.
* */
- linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
- mode->crtc_clock);
- ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
+ linetime = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8,
+ adjusted_mode->crtc_clock);
+ ips_linetime = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8,
dev_priv->cdclk_freq);
return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
@@ -2326,48 +2274,6 @@ static void skl_setup_wm_latency(struct drm_device *dev)
intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
}
-static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
- struct ilk_pipe_wm_parameters *p)
-{
- struct drm_device *dev = crtc->dev;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
- struct drm_plane *plane;
-
- if (!intel_crtc->active)
- return;
-
- p->active = true;
- p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal;
- p->pixel_rate = ilk_pipe_pixel_rate(intel_crtc->config);
-
- if (crtc->primary->state->fb)
- p->pri.bytes_per_pixel =
- crtc->primary->state->fb->bits_per_pixel / 8;
- else
- p->pri.bytes_per_pixel = 4;
-
- p->cur.bytes_per_pixel = 4;
- /*
- * TODO: for now, assume primary and cursor planes are always enabled.
- * Setting them to false makes the screen flicker.
- */
- p->pri.enabled = true;
- p->cur.enabled = true;
-
- p->pri.horiz_pixels = intel_crtc->config->pipe_src_w;
- p->cur.horiz_pixels = intel_crtc->base.cursor->state->crtc_w;
-
- drm_for_each_legacy_plane(plane, dev) {
- struct intel_plane *intel_plane = to_intel_plane(plane);
-
- if (intel_plane->pipe == pipe) {
- p->spr = intel_plane->wm;
- break;
- }
- }
-}
-
static void ilk_compute_wm_config(struct drm_device *dev,
struct intel_wm_config *config)
{
@@ -2387,34 +2293,47 @@ static void ilk_compute_wm_config(struct drm_device *dev,
}
/* Compute new watermarks for the pipe */
-static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
- const struct ilk_pipe_wm_parameters *params,
+static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
struct intel_pipe_wm *pipe_wm)
{
+ struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_plane *intel_plane;
+ struct intel_plane_state *sprstate = NULL;
int level, max_level = ilk_wm_max_level(dev);
/* LP0 watermark maximums depend on this pipe alone */
struct intel_wm_config config = {
.num_pipes_active = 1,
- .sprites_enabled = params->spr.enabled,
- .sprites_scaled = params->spr.scaled,
};
struct ilk_wm_maximums max;
- pipe_wm->pipe_enabled = params->active;
- pipe_wm->sprites_enabled = params->spr.enabled;
- pipe_wm->sprites_scaled = params->spr.scaled;
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) {
+ sprstate = to_intel_plane_state(intel_plane->base.state);
+ break;
+ }
+ }
+
+ config.sprites_enabled = sprstate->visible;
+ config.sprites_scaled = sprstate->visible &&
+ (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
+ drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
+
+ pipe_wm->pipe_enabled = cstate->base.active;
+ pipe_wm->sprites_enabled = sprstate->visible;
+ pipe_wm->sprites_scaled = config.sprites_scaled;
/* ILK/SNB: LP2+ watermarks only w/o sprites */
- if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
+ if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible)
max_level = 1;
/* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
- if (params->spr.scaled)
+ if (config.sprites_scaled)
max_level = 0;
- ilk_compute_wm_level(dev_priv, 0, params, &pipe_wm->wm[0]);
+ ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, &pipe_wm->wm[0]);
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
@@ -2431,7 +2350,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
for (level = 1; level <= max_level; level++) {
struct intel_wm_level wm = {};
- ilk_compute_wm_level(dev_priv, level, params, &wm);
+ ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, &wm);
/*
* Disable any watermark level that exceeds the
@@ -2899,7 +2818,12 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
int plane;
u32 val;
+ memset(ddb, 0, sizeof(*ddb));
+
for_each_pipe(dev_priv, pipe) {
+ if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe)))
+ continue;
+
for_each_plane(dev_priv, pipe, plane) {
val = I915_READ(PLANE_BUF_CFG(pipe, plane));
skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane],
@@ -2907,7 +2831,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
}
val = I915_READ(CUR_BUF_CFG(pipe));
- skl_ddb_entry_init_from_hw(&ddb->cursor[pipe], val);
+ skl_ddb_entry_init_from_hw(&ddb->plane[pipe][PLANE_CURSOR],
+ val);
}
}
@@ -2976,13 +2901,14 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc,
alloc_size = skl_ddb_entry_size(alloc);
if (alloc_size == 0) {
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
- memset(&ddb->cursor[pipe], 0, sizeof(ddb->cursor[pipe]));
+ memset(&ddb->plane[pipe][PLANE_CURSOR], 0,
+ sizeof(ddb->plane[pipe][PLANE_CURSOR]));
return;
}
cursor_blocks = skl_cursor_allocation(config);
- ddb->cursor[pipe].start = alloc->end - cursor_blocks;
- ddb->cursor[pipe].end = alloc->end;
+ ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - cursor_blocks;
+ ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
alloc_size -= cursor_blocks;
alloc->end -= cursor_blocks;
@@ -3121,8 +3047,8 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
sizeof(new_ddb->plane[pipe])))
return true;
- if (memcmp(&new_ddb->cursor[pipe], &cur_ddb->cursor[pipe],
- sizeof(new_ddb->cursor[pipe])))
+ if (memcmp(&new_ddb->plane[pipe][PLANE_CURSOR], &cur_ddb->plane[pipe][PLANE_CURSOR],
+ sizeof(new_ddb->plane[pipe][PLANE_CURSOR])))
return true;
return false;
@@ -3166,7 +3092,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc,
if (fb) {
p->plane[0].enabled = true;
p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
- drm_format_plane_cpp(fb->pixel_format, 1) : fb->bits_per_pixel / 8;
+ drm_format_plane_cpp(fb->pixel_format, 1) :
+ drm_format_plane_cpp(fb->pixel_format, 0);
p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
drm_format_plane_cpp(fb->pixel_format, 0) : 0;
p->plane[0].tiling = fb->modifier[0];
@@ -3181,17 +3108,17 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc,
p->plane[0].rotation = crtc->primary->state->rotation;
fb = crtc->cursor->state->fb;
- p->cursor.y_bytes_per_pixel = 0;
+ p->plane[PLANE_CURSOR].y_bytes_per_pixel = 0;
if (fb) {
- p->cursor.enabled = true;
- p->cursor.bytes_per_pixel = fb->bits_per_pixel / 8;
- p->cursor.horiz_pixels = crtc->cursor->state->crtc_w;
- p->cursor.vert_pixels = crtc->cursor->state->crtc_h;
+ p->plane[PLANE_CURSOR].enabled = true;
+ p->plane[PLANE_CURSOR].bytes_per_pixel = fb->bits_per_pixel / 8;
+ p->plane[PLANE_CURSOR].horiz_pixels = crtc->cursor->state->crtc_w;
+ p->plane[PLANE_CURSOR].vert_pixels = crtc->cursor->state->crtc_h;
} else {
- p->cursor.enabled = false;
- p->cursor.bytes_per_pixel = 0;
- p->cursor.horiz_pixels = 64;
- p->cursor.vert_pixels = 64;
+ p->plane[PLANE_CURSOR].enabled = false;
+ p->plane[PLANE_CURSOR].bytes_per_pixel = 0;
+ p->plane[PLANE_CURSOR].horiz_pixels = 64;
+ p->plane[PLANE_CURSOR].vert_pixels = 64;
}
}
@@ -3305,11 +3232,12 @@ static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
&result->plane_res_l[i]);
}
- ddb_blocks = skl_ddb_entry_size(&ddb->cursor[pipe]);
- result->cursor_en = skl_compute_plane_wm(dev_priv, p, &p->cursor,
+ ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][PLANE_CURSOR]);
+ result->plane_en[PLANE_CURSOR] = skl_compute_plane_wm(dev_priv, p,
+ &p->plane[PLANE_CURSOR],
ddb_blocks, level,
- &result->cursor_res_b,
- &result->cursor_res_l);
+ &result->plane_res_b[PLANE_CURSOR],
+ &result->plane_res_l[PLANE_CURSOR]);
}
static uint32_t
@@ -3337,7 +3265,7 @@ static void skl_compute_transition_wm(struct drm_crtc *crtc,
/* Until we know more, just disable transition WMs */
for (i = 0; i < intel_num_planes(intel_crtc); i++)
trans_wm->plane_en[i] = false;
- trans_wm->cursor_en = false;
+ trans_wm->plane_en[PLANE_CURSOR] = false;
}
static void skl_compute_pipe_wm(struct drm_crtc *crtc,
@@ -3386,13 +3314,13 @@ static void skl_compute_wm_results(struct drm_device *dev,
temp = 0;
- temp |= p_wm->wm[level].cursor_res_l << PLANE_WM_LINES_SHIFT;
- temp |= p_wm->wm[level].cursor_res_b;
+ temp |= p_wm->wm[level].plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT;
+ temp |= p_wm->wm[level].plane_res_b[PLANE_CURSOR];
- if (p_wm->wm[level].cursor_en)
+ if (p_wm->wm[level].plane_en[PLANE_CURSOR])
temp |= PLANE_WM_EN;
- r->cursor[pipe][level] = temp;
+ r->plane[pipe][PLANE_CURSOR][level] = temp;
}
@@ -3408,12 +3336,12 @@ static void skl_compute_wm_results(struct drm_device *dev,
}
temp = 0;
- temp |= p_wm->trans_wm.cursor_res_l << PLANE_WM_LINES_SHIFT;
- temp |= p_wm->trans_wm.cursor_res_b;
- if (p_wm->trans_wm.cursor_en)
+ temp |= p_wm->trans_wm.plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT;
+ temp |= p_wm->trans_wm.plane_res_b[PLANE_CURSOR];
+ if (p_wm->trans_wm.plane_en[PLANE_CURSOR])
temp |= PLANE_WM_EN;
- r->cursor_trans[pipe] = temp;
+ r->plane_trans[pipe][PLANE_CURSOR] = temp;
r->wm_linetime[pipe] = p_wm->linetime;
}
@@ -3447,12 +3375,13 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv,
I915_WRITE(PLANE_WM(pipe, i, level),
new->plane[pipe][i][level]);
I915_WRITE(CUR_WM(pipe, level),
- new->cursor[pipe][level]);
+ new->plane[pipe][PLANE_CURSOR][level]);
}
for (i = 0; i < intel_num_planes(crtc); i++)
I915_WRITE(PLANE_WM_TRANS(pipe, i),
new->plane_trans[pipe][i]);
- I915_WRITE(CUR_WM_TRANS(pipe), new->cursor_trans[pipe]);
+ I915_WRITE(CUR_WM_TRANS(pipe),
+ new->plane_trans[pipe][PLANE_CURSOR]);
for (i = 0; i < intel_num_planes(crtc); i++) {
skl_ddb_entry_write(dev_priv,
@@ -3464,7 +3393,7 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv,
}
skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe),
- &new->ddb.cursor[pipe]);
+ &new->ddb.plane[pipe][PLANE_CURSOR]);
}
}
@@ -3672,6 +3601,26 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
}
}
+static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
+{
+ watermarks->wm_linetime[pipe] = 0;
+ memset(watermarks->plane[pipe], 0,
+ sizeof(uint32_t) * 8 * I915_MAX_PLANES);
+ memset(watermarks->plane_trans[pipe],
+ 0, sizeof(uint32_t) * I915_MAX_PLANES);
+ watermarks->plane_trans[pipe][PLANE_CURSOR] = 0;
+
+ /* Clear ddb entries for pipe */
+ memset(&watermarks->ddb.pipe[pipe], 0, sizeof(struct skl_ddb_entry));
+ memset(&watermarks->ddb.plane[pipe], 0,
+ sizeof(struct skl_ddb_entry) * I915_MAX_PLANES);
+ memset(&watermarks->ddb.y_plane[pipe], 0,
+ sizeof(struct skl_ddb_entry) * I915_MAX_PLANES);
+ memset(&watermarks->ddb.plane[pipe][PLANE_CURSOR], 0,
+ sizeof(struct skl_ddb_entry));
+
+}
+
static void skl_update_wm(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -3682,7 +3631,11 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct skl_pipe_wm pipe_wm = {};
struct intel_wm_config config = {};
- memset(results, 0, sizeof(*results));
+
+ /* Clear all dirty flags */
+ memset(results->dirty, 0, sizeof(bool) * I915_MAX_PIPES);
+
+ skl_clear_wm(results, intel_crtc->pipe);
skl_compute_wm_global_parameters(dev, &config);
@@ -3737,19 +3690,19 @@ skl_update_sprite_wm(struct drm_plane *plane, struct drm_crtc *crtc,
static void ilk_update_wm(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct ilk_wm_maximums max;
- struct ilk_pipe_wm_parameters params = {};
struct ilk_wm_values results = {};
enum intel_ddb_partitioning partitioning;
struct intel_pipe_wm pipe_wm = {};
struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
struct intel_wm_config config = {};
- ilk_compute_wm_parameters(crtc, &params);
+ WARN_ON(cstate->base.active != intel_crtc->active);
- intel_compute_pipe_wm(crtc, &params, &pipe_wm);
+ intel_compute_pipe_wm(cstate, &pipe_wm);
if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
return;
@@ -3789,12 +3742,6 @@ ilk_update_sprite_wm(struct drm_plane *plane,
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
- intel_plane->wm.enabled = enabled;
- intel_plane->wm.scaled = scaled;
- intel_plane->wm.horiz_pixels = sprite_width;
- intel_plane->wm.vert_pixels = sprite_width;
- intel_plane->wm.bytes_per_pixel = pixel_size;
-
/*
* IVB workaround: must disable low power watermarks for at least
* one frame before enabling scaling. LP watermarks can be re-enabled
@@ -3826,10 +3773,10 @@ static void skl_pipe_wm_active_state(uint32_t val,
(val >> PLANE_WM_LINES_SHIFT) &
PLANE_WM_LINES_MASK;
} else {
- active->wm[level].cursor_en = is_enabled;
- active->wm[level].cursor_res_b =
+ active->wm[level].plane_en[PLANE_CURSOR] = is_enabled;
+ active->wm[level].plane_res_b[PLANE_CURSOR] =
val & PLANE_WM_BLOCKS_MASK;
- active->wm[level].cursor_res_l =
+ active->wm[level].plane_res_l[PLANE_CURSOR] =
(val >> PLANE_WM_LINES_SHIFT) &
PLANE_WM_LINES_MASK;
}
@@ -3842,10 +3789,10 @@ static void skl_pipe_wm_active_state(uint32_t val,
(val >> PLANE_WM_LINES_SHIFT) &
PLANE_WM_LINES_MASK;
} else {
- active->trans_wm.cursor_en = is_enabled;
- active->trans_wm.cursor_res_b =
+ active->trans_wm.plane_en[PLANE_CURSOR] = is_enabled;
+ active->trans_wm.plane_res_b[PLANE_CURSOR] =
val & PLANE_WM_BLOCKS_MASK;
- active->trans_wm.cursor_res_l =
+ active->trans_wm.plane_res_l[PLANE_CURSOR] =
(val >> PLANE_WM_LINES_SHIFT) &
PLANE_WM_LINES_MASK;
}
@@ -3871,12 +3818,12 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
for (i = 0; i < intel_num_planes(intel_crtc); i++)
hw->plane[pipe][i][level] =
I915_READ(PLANE_WM(pipe, i, level));
- hw->cursor[pipe][level] = I915_READ(CUR_WM(pipe, level));
+ hw->plane[pipe][PLANE_CURSOR][level] = I915_READ(CUR_WM(pipe, level));
}
for (i = 0; i < intel_num_planes(intel_crtc); i++)
hw->plane_trans[pipe][i] = I915_READ(PLANE_WM_TRANS(pipe, i));
- hw->cursor_trans[pipe] = I915_READ(CUR_WM_TRANS(pipe));
+ hw->plane_trans[pipe][PLANE_CURSOR] = I915_READ(CUR_WM_TRANS(pipe));
if (!intel_crtc->active)
return;
@@ -3891,7 +3838,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
skl_pipe_wm_active_state(temp, active, false,
false, i, level);
}
- temp = hw->cursor[pipe][level];
+ temp = hw->plane[pipe][PLANE_CURSOR][level];
skl_pipe_wm_active_state(temp, active, false, true, i, level);
}
@@ -3900,7 +3847,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
skl_pipe_wm_active_state(temp, active, true, false, i, 0);
}
- temp = hw->cursor_trans[pipe];
+ temp = hw->plane_trans[pipe][PLANE_CURSOR];
skl_pipe_wm_active_state(temp, active, true, true, i, 0);
}
@@ -4261,7 +4208,7 @@ static void ironlake_enable_drps(struct drm_device *dev)
fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
MEMMODE_FSTART_SHIFT;
- vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
+ vstart = (I915_READ(PXVFREQ(fstart)) & PXVFREQ_PX_MASK) >>
PXVFREQ_PX_SHIFT;
dev_priv->ips.fmax = fmax; /* IPS callback will increase this */
@@ -4292,10 +4239,10 @@ static void ironlake_enable_drps(struct drm_device *dev)
ironlake_set_drps(dev, fstart);
- dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
- I915_READ(0x112e0);
+ dev_priv->ips.last_count1 = I915_READ(DMIEC) +
+ I915_READ(DDREC) + I915_READ(CSIEC);
dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies);
- dev_priv->ips.last_count2 = I915_READ(0x112f4);
+ dev_priv->ips.last_count2 = I915_READ(GFXEC);
dev_priv->ips.last_time2 = ktime_get_raw_ns();
spin_unlock_irq(&mchdev_lock);
@@ -4466,6 +4413,10 @@ static void gen6_set_rps(struct drm_device *dev, u8 val)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */
+ if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0))
+ return;
+
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
WARN_ON(val > dev_priv->rps.max_freq);
WARN_ON(val < dev_priv->rps.min_freq);
@@ -4498,7 +4449,7 @@ static void gen6_set_rps(struct drm_device *dev, u8 val)
POSTING_READ(GEN6_RPNSWREQ);
dev_priv->rps.cur_freq = val;
- trace_intel_gpu_freq_change(val * 50);
+ trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val));
}
static void valleyview_set_rps(struct drm_device *dev, u8 val)
@@ -4786,6 +4737,12 @@ static void gen9_enable_rps(struct drm_device *dev)
gen6_init_rps_frequencies(dev);
+ /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */
+ if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) {
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+ return;
+ }
+
/* Program defaults and thresholds for RPS*/
I915_WRITE(GEN6_RC_VIDEO_FREQ,
GEN9_FREQUENCY(dev_priv->rps.rp1_freq));
@@ -4823,13 +4780,22 @@ static void gen9_enable_rc6(struct drm_device *dev)
I915_WRITE(GEN6_RC_CONTROL, 0);
/* 2b: Program RC6 thresholds.*/
- I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
+
+ /* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */
+ if (IS_SKYLAKE(dev) && !((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) &&
+ (INTEL_REVID(dev) <= SKL_REVID_E0)))
+ I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16);
+ else
+ I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
for_each_ring(ring, dev_priv, unused)
I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+
+ if (HAS_GUC_UCODE(dev))
+ I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
+
I915_WRITE(GEN6_RC_SLEEP, 0);
- I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */
/* 2c: Program Coarse Power Gating Policies. */
I915_WRITE(GEN9_MEDIA_PG_IDLE_HYSTERESIS, 25);
@@ -4840,17 +4806,30 @@ static void gen9_enable_rc6(struct drm_device *dev)
rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
"on" : "off");
- I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
- GEN6_RC_CTL_EI_MODE(1) |
- rc6_mask);
+ /* WaRsUseTimeoutMode */
+ if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_D0) ||
+ (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0)) {
+ I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */
+ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
+ GEN7_RC_CTL_TO_MODE |
+ rc6_mask);
+ } else {
+ I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */
+ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
+ GEN6_RC_CTL_EI_MODE(1) |
+ rc6_mask);
+ }
/*
* 3b: Enable Coarse Power Gating only when RC6 is enabled.
- * WaDisableRenderPowerGating:skl,bxt - Render PG need to be disabled with RC6.
+ * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6.
*/
- I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
- GEN9_MEDIA_PG_ENABLE : 0);
-
+ if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
+ ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_E0)))
+ I915_WRITE(GEN9_PG_ENABLE, 0);
+ else
+ I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
+ (GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE) : 0);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -5148,32 +5127,27 @@ static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv)
struct drm_device *dev = dev_priv->dev;
u32 val, rp0;
- if (dev->pdev->revision >= 0x20) {
- val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
+ val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
- switch (INTEL_INFO(dev)->eu_total) {
- case 8:
- /* (2 * 4) config */
- rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT);
- break;
- case 12:
- /* (2 * 6) config */
- rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS6EU_FUSE_SHIFT);
- break;
- case 16:
- /* (2 * 8) config */
- default:
- /* Setting (2 * 8) Min RP0 for any other combination */
- rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS8EU_FUSE_SHIFT);
- break;
- }
- rp0 = (rp0 & FB_GFX_FREQ_FUSE_MASK);
- } else {
- /* For pre-production hardware */
- val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG);
- rp0 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) &
- PUNIT_GPU_STATUS_MAX_FREQ_MASK;
+ switch (INTEL_INFO(dev)->eu_total) {
+ case 8:
+ /* (2 * 4) config */
+ rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT);
+ break;
+ case 12:
+ /* (2 * 6) config */
+ rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS6EU_FUSE_SHIFT);
+ break;
+ case 16:
+ /* (2 * 8) config */
+ default:
+ /* Setting (2 * 8) Min RP0 for any other combination */
+ rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS8EU_FUSE_SHIFT);
+ break;
}
+
+ rp0 = (rp0 & FB_GFX_FREQ_FUSE_MASK);
+
return rp0;
}
@@ -5189,18 +5163,11 @@ static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv)
static int cherryview_rps_guar_freq(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = dev_priv->dev;
u32 val, rp1;
- if (dev->pdev->revision >= 0x20) {
- val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
- rp1 = (val & FB_GFX_FREQ_FUSE_MASK);
- } else {
- /* For pre-production hardware */
- val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
- rp1 = ((val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) &
- PUNIT_GPU_STATUS_MAX_FREQ_MASK);
- }
+ val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
+ rp1 = (val & FB_GFX_FREQ_FUSE_MASK);
+
return rp1;
}
@@ -5415,25 +5382,10 @@ static void cherryview_init_gt_powersave(struct drm_device *dev)
mutex_unlock(&dev_priv->sb_lock);
switch ((val >> 2) & 0x7) {
- case 0:
- case 1:
- dev_priv->rps.cz_freq = 200;
- dev_priv->mem_freq = 1600;
- break;
- case 2:
- dev_priv->rps.cz_freq = 267;
- dev_priv->mem_freq = 1600;
- break;
case 3:
- dev_priv->rps.cz_freq = 333;
dev_priv->mem_freq = 2000;
break;
- case 4:
- dev_priv->rps.cz_freq = 320;
- dev_priv->mem_freq = 1600;
- break;
- case 5:
- dev_priv->rps.cz_freq = 400;
+ default:
dev_priv->mem_freq = 1600;
break;
}
@@ -5565,7 +5517,7 @@ static void cherryview_enable_rps(struct drm_device *dev)
/* RPS code assumes GPLL is used */
WARN_ONCE((val & GPLLENABLE) == 0, "GPLL not enabled\n");
- DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & GPLLENABLE ? "yes" : "no");
+ DRM_DEBUG_DRIVER("GPLL enabled? %s\n", yesno(val & GPLLENABLE));
DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
dev_priv->rps.cur_freq = (val >> 8) & 0xff;
@@ -5655,7 +5607,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
/* RPS code assumes GPLL is used */
WARN_ONCE((val & GPLLENABLE) == 0, "GPLL not enabled\n");
- DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & GPLLENABLE ? "yes" : "no");
+ DRM_DEBUG_DRIVER("GPLL enabled? %s\n", yesno(val & GPLLENABLE));
DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
dev_priv->rps.cur_freq = (val >> 8) & 0xff;
@@ -5864,7 +5816,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
assert_spin_locked(&mchdev_lock);
- pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_freq * 4));
+ pxvid = I915_READ(PXVFREQ(dev_priv->rps.cur_freq));
pxvid = (pxvid >> 24) & 0x7f;
ext_v = pvid_to_extvid(dev_priv, pxvid);
@@ -6107,13 +6059,13 @@ static void intel_init_emon(struct drm_device *dev)
I915_WRITE(CSIEW2, 0x04000004);
for (i = 0; i < 5; i++)
- I915_WRITE(PEW + (i * 4), 0);
+ I915_WRITE(PEW(i), 0);
for (i = 0; i < 3; i++)
- I915_WRITE(DEW + (i * 4), 0);
+ I915_WRITE(DEW(i), 0);
/* Program P-state weights to account for frequency power adjustment */
for (i = 0; i < 16; i++) {
- u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
+ u32 pxvidfreq = I915_READ(PXVFREQ(i));
unsigned long freq = intel_pxfreq(pxvidfreq);
unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
PXVFREQ_PX_SHIFT;
@@ -6134,7 +6086,7 @@ static void intel_init_emon(struct drm_device *dev)
for (i = 0; i < 4; i++) {
u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
(pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
- I915_WRITE(PXW + (i * 4), val);
+ I915_WRITE(PXW(i), val);
}
/* Adjust magic regs to magic values (more experimental results) */
@@ -6150,7 +6102,7 @@ static void intel_init_emon(struct drm_device *dev)
I915_WRITE(EG7, 0);
for (i = 0; i < 8; i++)
- I915_WRITE(PXWL + (i * 4), 0);
+ I915_WRITE(PXWL(i), 0);
/* Enable PMON + select events */
I915_WRITE(ECR, 0x80000019);
@@ -6604,14 +6556,14 @@ static void lpt_init_clock_gating(struct drm_device *dev)
* TODO: this bit should only be enabled when really needed, then
* disabled when not needed anymore in order to save power.
*/
- if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
+ if (HAS_PCH_LPT_LP(dev))
I915_WRITE(SOUTH_DSPCLK_GATE_D,
I915_READ(SOUTH_DSPCLK_GATE_D) |
PCH_LP_PARTITION_LEVEL_DISABLE);
/* WADPOClockGatingDisable:hsw */
- I915_WRITE(_TRANSA_CHICKEN1,
- I915_READ(_TRANSA_CHICKEN1) |
+ I915_WRITE(TRANS_CHICKEN1(PIPE_A),
+ I915_READ(TRANS_CHICKEN1(PIPE_A)) |
TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
}
@@ -6619,7 +6571,7 @@ static void lpt_suspend_hw(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
+ if (HAS_PCH_LPT_LP(dev)) {
uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D);
val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
@@ -7105,9 +7057,6 @@ void intel_init_pm(struct drm_device *dev)
if (IS_BROXTON(dev))
dev_priv->display.init_clock_gating =
bxt_init_clock_gating;
- else if (IS_SKYLAKE(dev))
- dev_priv->display.init_clock_gating =
- skl_init_clock_gating;
dev_priv->display.update_wm = skl_update_wm;
dev_priv->display.update_sprite_wm = skl_update_sprite_wm;
} else if (HAS_PCH_SPLIT(dev)) {
@@ -7260,7 +7209,7 @@ static int vlv_gpu_freq_div(unsigned int czclk_freq)
static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
- int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->mem_freq, 4);
+ int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
div = vlv_gpu_freq_div(czclk_freq);
if (div < 0)
@@ -7271,7 +7220,7 @@ static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
- int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->mem_freq, 4);
+ int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
mul = vlv_gpu_freq_div(czclk_freq);
if (mul < 0)
@@ -7282,7 +7231,7 @@ static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val)
static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
- int div, czclk_freq = dev_priv->rps.cz_freq;
+ int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
div = vlv_gpu_freq_div(czclk_freq) / 2;
if (div < 0)
@@ -7293,7 +7242,7 @@ static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
- int mul, czclk_freq = dev_priv->rps.cz_freq;
+ int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
mul = vlv_gpu_freq_div(czclk_freq) / 2;
if (mul < 0)
@@ -7306,7 +7255,8 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
if (IS_GEN9(dev_priv->dev))
- return (val * GT_FREQUENCY_MULTIPLIER) / GEN9_FREQ_SCALER;
+ return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER,
+ GEN9_FREQ_SCALER);
else if (IS_CHERRYVIEW(dev_priv->dev))
return chv_gpu_freq(dev_priv, val);
else if (IS_VALLEYVIEW(dev_priv->dev))
@@ -7318,13 +7268,14 @@ int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
int intel_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
if (IS_GEN9(dev_priv->dev))
- return (val * GEN9_FREQ_SCALER) / GT_FREQUENCY_MULTIPLIER;
+ return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER,
+ GT_FREQUENCY_MULTIPLIER);
else if (IS_CHERRYVIEW(dev_priv->dev))
return chv_freq_opcode(dev_priv, val);
else if (IS_VALLEYVIEW(dev_priv->dev))
return byt_freq_opcode(dev_priv, val);
else
- return val / GT_FREQUENCY_MULTIPLIER;
+ return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);
}
struct request_boost {
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index a04b4dc5ed9b..213581c215b3 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -73,14 +73,14 @@ static bool vlv_is_psr_active_on_pipe(struct drm_device *dev, int pipe)
}
static void intel_psr_write_vsc(struct intel_dp *intel_dp,
- struct edp_vsc_psr *vsc_psr)
+ const struct edp_vsc_psr *vsc_psr)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc->config->cpu_transcoder);
- u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc->config->cpu_transcoder);
+ enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
+ u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
uint32_t *data = (uint32_t *) vsc_psr;
unsigned int i;
@@ -90,12 +90,14 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp,
I915_WRITE(ctl_reg, 0);
POSTING_READ(ctl_reg);
- for (i = 0; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) {
- if (i < sizeof(struct edp_vsc_psr))
- I915_WRITE(data_reg + i, *data++);
- else
- I915_WRITE(data_reg + i, 0);
+ for (i = 0; i < sizeof(*vsc_psr); i += 4) {
+ I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder,
+ i >> 2), *data);
+ data++;
}
+ for (; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4)
+ I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder,
+ i >> 2), 0);
I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW);
POSTING_READ(ctl_reg);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6e6b8db996ef..9461a238f5d5 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -347,6 +347,7 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req,
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
}
if (invalidate_domains) {
flags |= PIPE_CONTROL_TLB_INVALIDATE;
@@ -418,6 +419,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req,
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
}
if (invalidate_domains) {
flags |= PIPE_CONTROL_TLB_INVALIDATE;
@@ -717,7 +719,7 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_workarounds *w = &dev_priv->workarounds;
- if (WARN_ON_ONCE(w->count == 0))
+ if (w->count == 0)
return 0;
ring->gpu_caches_dirty = true;
@@ -800,42 +802,29 @@ static int wa_add(struct drm_i915_private *dev_priv,
#define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
-static int bdw_init_workarounds(struct intel_engine_cs *ring)
+static int gen8_init_workarounds(struct intel_engine_cs *ring)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
- /* WaDisableAsyncFlipPerfMode:bdw */
+ /* WaDisableAsyncFlipPerfMode:bdw,chv */
WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
- /* WaDisablePartialInstShootdown:bdw */
- /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
+ /* WaDisablePartialInstShootdown:bdw,chv */
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
- PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE |
- STALL_DOP_GATING_DISABLE);
-
- /* WaDisableDopClockGating:bdw */
- WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
- DOP_CLOCK_GATING_DISABLE);
-
- WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
- GEN8_SAMPLER_POWER_BYPASS_DIS);
+ PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
/* Use Force Non-Coherent whenever executing a 3D context. This is a
* workaround for for a possible hang in the unlikely event a TLB
* invalidation occurs during a PSD flush.
*/
+ /* WaForceEnableNonCoherent:bdw,chv */
+ /* WaHdcDisableFetchWhenMasked:bdw,chv */
WA_SET_BIT_MASKED(HDC_CHICKEN0,
- /* WaForceEnableNonCoherent:bdw */
- HDC_FORCE_NON_COHERENT |
- /* WaForceContextSaveRestoreNonCoherent:bdw */
- HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
- /* WaHdcDisableFetchWhenMasked:bdw */
HDC_DONOT_FETCH_MEM_WHEN_MASKED |
- /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
- (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
+ HDC_FORCE_NON_COHERENT);
/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
* "The Hierarchical Z RAW Stall Optimization allows non-overlapping
@@ -843,13 +832,12 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
* stalling waiting for the earlier ones to write to Hierarchical Z
* buffer."
*
- * This optimization is off by default for Broadwell; turn it on.
+ * This optimization is off by default for BDW and CHV; turn it on.
*/
WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
- /* Wa4x4STCOptimizationDisable:bdw */
- WA_SET_BIT_MASKED(CACHE_MODE_1,
- GEN8_4x4_STC_OPTIMIZATION_DISABLE);
+ /* Wa4x4STCOptimizationDisable:bdw,chv */
+ WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
/*
* BSpec recommends 8x4 when MSAA is used,
@@ -866,56 +854,51 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
return 0;
}
-static int chv_init_workarounds(struct intel_engine_cs *ring)
+static int bdw_init_workarounds(struct intel_engine_cs *ring)
{
+ int ret;
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
+ ret = gen8_init_workarounds(ring);
+ if (ret)
+ return ret;
- /* WaDisableAsyncFlipPerfMode:chv */
- WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
+ /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
+ WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
- /* WaDisablePartialInstShootdown:chv */
- /* WaDisableThreadStallDopClockGating:chv */
- WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
- PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE |
- STALL_DOP_GATING_DISABLE);
+ /* WaDisableDopClockGating:bdw */
+ WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
+ DOP_CLOCK_GATING_DISABLE);
+
+ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
+ GEN8_SAMPLER_POWER_BYPASS_DIS);
- /* Use Force Non-Coherent whenever executing a 3D context. This is a
- * workaround for a possible hang in the unlikely event a TLB
- * invalidation occurs during a PSD flush.
- */
- /* WaForceEnableNonCoherent:chv */
- /* WaHdcDisableFetchWhenMasked:chv */
WA_SET_BIT_MASKED(HDC_CHICKEN0,
- HDC_FORCE_NON_COHERENT |
- HDC_DONOT_FETCH_MEM_WHEN_MASKED);
+ /* WaForceContextSaveRestoreNonCoherent:bdw */
+ HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
+ /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
+ (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
- /* According to the CACHE_MODE_0 default value documentation, some
- * CHV platforms disable this optimization by default. Turn it on.
- */
- WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
+ return 0;
+}
- /* Wa4x4STCOptimizationDisable:chv */
- WA_SET_BIT_MASKED(CACHE_MODE_1,
- GEN8_4x4_STC_OPTIMIZATION_DISABLE);
+static int chv_init_workarounds(struct intel_engine_cs *ring)
+{
+ int ret;
+ struct drm_device *dev = ring->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ ret = gen8_init_workarounds(ring);
+ if (ret)
+ return ret;
+
+ /* WaDisableThreadStallDopClockGating:chv */
+ WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
/* Improve HiZ throughput on CHV. */
WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
- /*
- * BSpec recommends 8x4 when MSAA is used,
- * however in practice 16x4 seems fastest.
- *
- * Note that PS/WM thread counts depend on the WIZ hashing
- * disable bit, which we don't touch here, but it's good
- * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
- */
- WA_SET_FIELD_MASKED(GEN7_GT_MODE,
- GEN6_WIZ_HASHING_MASK,
- GEN6_WIZ_HASHING_16x4);
-
return 0;
}
@@ -925,6 +908,14 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ /* WaEnableLbsSlaRetryTimerDecrement:skl */
+ I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
+ GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
+
+ /* WaDisableKillLogic:bxt,skl */
+ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+ ECOCHK_DIS_TLB);
+
/* WaDisablePartialInstShootdown:skl,bxt */
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
@@ -961,10 +952,9 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
}
/* Wa4x4STCOptimizationDisable:skl,bxt */
- WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
-
/* WaDisablePartialResolveInVc:skl,bxt */
- WA_SET_BIT_MASKED(CACHE_MODE_1, GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE);
+ WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
+ GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
/* WaCcsTlbPrefetchDisable:skl,bxt */
WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
@@ -983,6 +973,16 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE;
WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp);
+ /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */
+ if (IS_SKYLAKE(dev) ||
+ (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_B0)) {
+ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
+ GEN8_SAMPLER_POWER_BYPASS_DIS);
+ }
+
+ /* WaDisableSTUnitPowerOptimization:skl,bxt */
+ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
+
return 0;
}
@@ -1028,13 +1028,39 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
return 0;
}
-
static int skl_init_workarounds(struct intel_engine_cs *ring)
{
+ int ret;
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- gen9_init_workarounds(ring);
+ ret = gen9_init_workarounds(ring);
+ if (ret)
+ return ret;
+
+ if (INTEL_REVID(dev) <= SKL_REVID_D0) {
+ /* WaDisableHDCInvalidation:skl */
+ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+ BDW_DISABLE_HDC_INVALIDATION);
+
+ /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
+ I915_WRITE(FF_SLICE_CS_CHICKEN2,
+ _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
+ }
+
+ /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
+ * involving this register should also be added to WA batch as required.
+ */
+ if (INTEL_REVID(dev) <= SKL_REVID_E0)
+ /* WaDisableLSQCROPERFforOCL:skl */
+ I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
+ GEN8_LQSC_RO_PERF_DIS);
+
+ /* WaEnableGapsTsvCreditFix:skl */
+ if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) {
+ I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+ GEN9_GAPS_TSV_CREDIT_DISABLE));
+ }
/* WaDisablePowerCompilerClockGating:skl */
if (INTEL_REVID(dev) == SKL_REVID_B0)
@@ -1071,10 +1097,24 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
static int bxt_init_workarounds(struct intel_engine_cs *ring)
{
+ int ret;
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- gen9_init_workarounds(ring);
+ ret = gen9_init_workarounds(ring);
+ if (ret)
+ return ret;
+
+ /* WaStoreMultiplePTEenable:bxt */
+ /* This is a requirement according to Hardware specification */
+ if (INTEL_REVID(dev) == BXT_REVID_A0)
+ I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
+
+ /* WaSetClckGatingDisableMedia:bxt */
+ if (INTEL_REVID(dev) == BXT_REVID_A0) {
+ I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
+ ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
+ }
/* WaDisableThreadStallDopClockGating:bxt */
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
@@ -1996,14 +2036,14 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
return 0;
}
-void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
+static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
{
drm_gem_object_unreference(&ringbuf->obj->base);
ringbuf->obj = NULL;
}
-int intel_alloc_ringbuffer_obj(struct drm_device *dev,
- struct intel_ringbuffer *ringbuf)
+static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
+ struct intel_ringbuffer *ringbuf)
{
struct drm_i915_gem_object *obj;
@@ -2023,6 +2063,48 @@ int intel_alloc_ringbuffer_obj(struct drm_device *dev,
return 0;
}
+struct intel_ringbuffer *
+intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
+{
+ struct intel_ringbuffer *ring;
+ int ret;
+
+ ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+ if (ring == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ ring->ring = engine;
+
+ ring->size = size;
+ /* Workaround an erratum on the i830 which causes a hang if
+ * the TAIL pointer points to within the last 2 cachelines
+ * of the buffer.
+ */
+ ring->effective_size = size;
+ if (IS_I830(engine->dev) || IS_845G(engine->dev))
+ ring->effective_size -= 2 * CACHELINE_BYTES;
+
+ ring->last_retired_head = -1;
+ intel_ring_update_space(ring);
+
+ ret = intel_alloc_ringbuffer_obj(engine->dev, ring);
+ if (ret) {
+ DRM_ERROR("Failed to allocate ringbuffer %s: %d\n",
+ engine->name, ret);
+ kfree(ring);
+ return ERR_PTR(ret);
+ }
+
+ return ring;
+}
+
+void
+intel_ringbuffer_free(struct intel_ringbuffer *ring)
+{
+ intel_destroy_ringbuffer_obj(ring);
+ kfree(ring);
+}
+
static int intel_init_ring_buffer(struct drm_device *dev,
struct intel_engine_cs *ring)
{
@@ -2031,22 +2113,20 @@ static int intel_init_ring_buffer(struct drm_device *dev,
WARN_ON(ring->buffer);
- ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
- if (!ringbuf)
- return -ENOMEM;
- ring->buffer = ringbuf;
-
ring->dev = dev;
INIT_LIST_HEAD(&ring->active_list);
INIT_LIST_HEAD(&ring->request_list);
INIT_LIST_HEAD(&ring->execlist_queue);
i915_gem_batch_pool_init(dev, &ring->batch_pool);
- ringbuf->size = 32 * PAGE_SIZE;
- ringbuf->ring = ring;
memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
init_waitqueue_head(&ring->irq_queue);
+ ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE);
+ if (IS_ERR(ringbuf))
+ return PTR_ERR(ringbuf);
+ ring->buffer = ringbuf;
+
if (I915_NEED_GFX_HWS(dev)) {
ret = init_status_page(ring);
if (ret)
@@ -2058,15 +2138,6 @@ static int intel_init_ring_buffer(struct drm_device *dev,
goto error;
}
- WARN_ON(ringbuf->obj);
-
- ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
- if (ret) {
- DRM_ERROR("Failed to allocate ringbuffer %s: %d\n",
- ring->name, ret);
- goto error;
- }
-
ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf);
if (ret) {
DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
@@ -2075,14 +2146,6 @@ static int intel_init_ring_buffer(struct drm_device *dev,
goto error;
}
- /* Workaround an erratum on the i830 which causes a hang if
- * the TAIL pointer points to within the last 2 cachelines
- * of the buffer.
- */
- ringbuf->effective_size = ringbuf->size;
- if (IS_I830(dev) || IS_845G(dev))
- ringbuf->effective_size -= 2 * CACHELINE_BYTES;
-
ret = i915_cmd_parser_init_ring(ring);
if (ret)
goto error;
@@ -2090,7 +2153,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
return 0;
error:
- kfree(ringbuf);
+ intel_ringbuffer_free(ringbuf);
ring->buffer = NULL;
return ret;
}
@@ -2098,19 +2161,18 @@ error:
void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
{
struct drm_i915_private *dev_priv;
- struct intel_ringbuffer *ringbuf;
if (!intel_ring_initialized(ring))
return;
dev_priv = to_i915(ring->dev);
- ringbuf = ring->buffer;
intel_stop_ring_buffer(ring);
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
- intel_unpin_ringbuffer_obj(ringbuf);
- intel_destroy_ringbuffer_obj(ringbuf);
+ intel_unpin_ringbuffer_obj(ring->buffer);
+ intel_ringbuffer_free(ring->buffer);
+ ring->buffer = NULL;
if (ring->cleanup)
ring->cleanup(ring);
@@ -2119,9 +2181,6 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
i915_cmd_parser_fini_ring(ring);
i915_gem_batch_pool_fini(&ring->batch_pool);
-
- kfree(ringbuf);
- ring->buffer = NULL;
}
static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
@@ -2608,6 +2667,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
GEN8_RING_SEMAPHORE_INIT;
}
} else if (INTEL_INFO(dev)->gen >= 6) {
+ ring->init_context = intel_rcs_ctx_init;
ring->add_request = gen6_add_request;
ring->flush = gen7_render_ring_flush;
if (INTEL_INFO(dev)->gen == 6)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 2e85fda94963..49fa41dc0eb6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -377,6 +377,13 @@ intel_ring_sync_index(struct intel_engine_cs *ring,
return idx;
}
+static inline void
+intel_flush_status_page(struct intel_engine_cs *ring, int reg)
+{
+ drm_clflush_virt_range(&ring->status_page.page_addr[reg],
+ sizeof(uint32_t));
+}
+
static inline u32
intel_read_status_page(struct intel_engine_cs *ring,
int reg)
@@ -413,12 +420,12 @@ intel_write_status_page(struct intel_engine_cs *ring,
#define I915_GEM_HWS_SCRATCH_INDEX 0x40
#define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
-void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
+struct intel_ringbuffer *
+intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size);
int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
struct intel_ringbuffer *ringbuf);
-void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
-int intel_alloc_ringbuffer_obj(struct drm_device *dev,
- struct intel_ringbuffer *ringbuf);
+void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
+void intel_ringbuffer_free(struct intel_ringbuffer *ring);
void intel_stop_ring_buffer(struct intel_engine_cs *ring);
void intel_cleanup_ring_buffer(struct intel_engine_cs *ring);
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 7401cf90b0db..d89c1d0aa1b7 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -464,14 +464,14 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
SKL_DISP_PW_2);
- WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n");
- WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
- WARN(pg2_enabled, "PG2 not disabled to enable DC5.\n");
+ WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n");
+ WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
+ WARN_ONCE(pg2_enabled, "PG2 not disabled to enable DC5.\n");
- WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
- "DC5 already programmed to be enabled.\n");
- WARN(dev_priv->pm.suspended,
- "DC5 cannot be enabled, if platform is runtime-suspended.\n");
+ WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
+ "DC5 already programmed to be enabled.\n");
+ WARN_ONCE(dev_priv->pm.suspended,
+ "DC5 cannot be enabled, if platform is runtime-suspended.\n");
assert_csr_loaded(dev_priv);
}
@@ -487,8 +487,8 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
if (dev_priv->power_domains.initializing)
return;
- WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
- WARN(dev_priv->pm.suspended,
+ WARN_ONCE(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
+ WARN_ONCE(dev_priv->pm.suspended,
"Disabling of DC5 while platform is runtime-suspended should never happen.\n");
}
@@ -527,12 +527,12 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
- WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n");
- WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
- WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
- "Backlight is not disabled.\n");
- WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
- "DC6 already programmed to be enabled.\n");
+ WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n");
+ WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
+ WARN_ONCE(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
+ "Backlight is not disabled.\n");
+ WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
+ "DC6 already programmed to be enabled.\n");
assert_csr_loaded(dev_priv);
}
@@ -547,8 +547,8 @@ static void assert_can_disable_dc6(struct drm_i915_private *dev_priv)
return;
assert_csr_loaded(dev_priv);
- WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
- "DC6 already programmed to be disabled.\n");
+ WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
+ "DC6 already programmed to be disabled.\n");
}
static void skl_enable_dc6(struct drm_i915_private *dev_priv)
@@ -657,9 +657,15 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
}
} else {
if (enable_requested) {
- I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask);
- POSTING_READ(HSW_PWR_WELL_DRIVER);
- DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
+ if (IS_SKYLAKE(dev) &&
+ (power_well->data == SKL_DISP_PW_1) &&
+ (intel_csr_load_status_get(dev_priv) == FW_LOADED))
+ DRM_DEBUG_KMS("Not Disabling PW1, dmc will handle\n");
+ else {
+ I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask);
+ POSTING_READ(HSW_PWR_WELL_DRIVER);
+ DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
+ }
if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
power_well->data == SKL_DISP_PW_2) {
@@ -671,7 +677,7 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
wait_for((state = intel_csr_load_status_get(dev_priv)) !=
FW_UNINITIALIZED, 1000);
if (state != FW_LOADED)
- DRM_ERROR("CSR firmware not ready (%d)\n",
+ DRM_DEBUG("CSR firmware not ready (%d)\n",
state);
else
if (SKL_ENABLE_DC6(dev))
@@ -856,6 +862,25 @@ static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
{
+ enum pipe pipe;
+
+ /*
+ * Enable the CRI clock source so we can get at the
+ * display and the reference clock for VGA
+ * hotplug / manual detection. Supposedly DSI also
+ * needs the ref clock up and running.
+ *
+ * CHV DPLL B/C have some issues if VGA mode is enabled.
+ */
+ for_each_pipe(dev_priv->dev, pipe) {
+ u32 val = I915_READ(DPLL(pipe));
+
+ val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+ if (pipe != PIPE_A)
+ val |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
+ I915_WRITE(DPLL(pipe), val);
+ }
spin_lock_irq(&dev_priv->irq_lock);
valleyview_enable_display_irqs(dev_priv);
@@ -907,13 +932,7 @@ static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
{
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
- /*
- * Enable the CRI clock source so we can get at the
- * display and the reference clock for VGA
- * hotplug / manual detection.
- */
- I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | DPLL_VGA_MODE_DIS |
- DPLL_REF_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
+ /* since ref/cri clock was enabled */
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
vlv_set_power_well(dev_priv, power_well, true);
@@ -948,30 +967,149 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
vlv_set_power_well(dev_priv, power_well, false);
}
+#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
+
+static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
+ int power_well_id)
+{
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ struct i915_power_well *power_well;
+ int i;
+
+ for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+ if (power_well->data == power_well_id)
+ return power_well;
+ }
+
+ return NULL;
+}
+
+#define BITS_SET(val, bits) (((val) & (bits)) == (bits))
+
+static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
+{
+ struct i915_power_well *cmn_bc =
+ lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
+ struct i915_power_well *cmn_d =
+ lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
+ u32 phy_control = dev_priv->chv_phy_control;
+ u32 phy_status = 0;
+ u32 phy_status_mask = 0xffffffff;
+ u32 tmp;
+
+ /*
+ * The BIOS can leave the PHY is some weird state
+ * where it doesn't fully power down some parts.
+ * Disable the asserts until the PHY has been fully
+ * reset (ie. the power well has been disabled at
+ * least once).
+ */
+ if (!dev_priv->chv_phy_assert[DPIO_PHY0])
+ phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0) |
+ PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0) |
+ PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1) |
+ PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1) |
+ PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0) |
+ PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1));
+
+ if (!dev_priv->chv_phy_assert[DPIO_PHY1])
+ phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0) |
+ PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) |
+ PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1));
+
+ if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
+ phy_status |= PHY_POWERGOOD(DPIO_PHY0);
+
+ /* this assumes override is only used to enable lanes */
+ if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0)) == 0)
+ phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0);
+
+ if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1)) == 0)
+ phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1);
+
+ /* CL1 is on whenever anything is on in either channel */
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0) |
+ PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)))
+ phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0);
+
+ /*
+ * The DPLLB check accounts for the pipe B + port A usage
+ * with CL2 powered up but all the lanes in the second channel
+ * powered down.
+ */
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) &&
+ (I915_READ(DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0)
+ phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1);
+
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH0)))
+ phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0);
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH0)))
+ phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1);
+
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH1)))
+ phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0);
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH1)))
+ phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
+ }
+
+ if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
+ phy_status |= PHY_POWERGOOD(DPIO_PHY1);
+
+ /* this assumes override is only used to enable lanes */
+ if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0)) == 0)
+ phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0);
+
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0)))
+ phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0);
+
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY1, DPIO_CH0)))
+ phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0);
+ if (BITS_SET(phy_control,
+ PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY1, DPIO_CH0)))
+ phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1);
+ }
+
+ phy_status &= phy_status_mask;
+
+ /*
+ * The PHY may be busy with some initial calibration and whatnot,
+ * so the power state can take a while to actually change.
+ */
+ if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS) & phy_status_mask) == phy_status, 10))
+ WARN(phy_status != tmp,
+ "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
+ tmp, phy_status, dev_priv->chv_phy_control);
+}
+
+#undef BITS_SET
+
static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum dpio_phy phy;
+ enum pipe pipe;
+ uint32_t tmp;
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
- /*
- * Enable the CRI clock source so we can get at the
- * display and the reference clock for VGA
- * hotplug / manual detection.
- */
if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+ pipe = PIPE_A;
phy = DPIO_PHY0;
- I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | DPLL_VGA_MODE_DIS |
- DPLL_REF_CLK_ENABLE_VLV);
- I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | DPLL_VGA_MODE_DIS |
- DPLL_REF_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
} else {
+ pipe = PIPE_C;
phy = DPIO_PHY1;
- I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) | DPLL_VGA_MODE_DIS |
- DPLL_REF_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
}
+
+ /* since ref/cri clock was enabled */
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
vlv_set_power_well(dev_priv, power_well, true);
@@ -979,8 +1117,38 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
DRM_ERROR("Display PHY %d is not power up\n", phy);
+ mutex_lock(&dev_priv->sb_lock);
+
+ /* Enable dynamic power down */
+ tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
+ tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN |
+ DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
+
+ if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+ tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
+ tmp |= DPIO_DYNPWRDOWNEN_CH1;
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
+ } else {
+ /*
+ * Force the non-existing CL2 off. BXT does this
+ * too, so maybe it saves some power even though
+ * CL2 doesn't exist?
+ */
+ tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
+ tmp |= DPIO_CL2_LDOFUSE_PWRENB;
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp);
+ }
+
+ mutex_unlock(&dev_priv->sb_lock);
+
dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+ DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
+ phy, dev_priv->chv_phy_control);
+
+ assert_chv_phy_status(dev_priv);
}
static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
@@ -1004,6 +1172,137 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
vlv_set_power_well(dev_priv, power_well, false);
+
+ DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
+ phy, dev_priv->chv_phy_control);
+
+ /* PHY is fully reset now, so we can enable the PHY state asserts */
+ dev_priv->chv_phy_assert[phy] = true;
+
+ assert_chv_phy_status(dev_priv);
+}
+
+static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+ enum dpio_channel ch, bool override, unsigned int mask)
+{
+ enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
+ u32 reg, val, expected, actual;
+
+ /*
+ * The BIOS can leave the PHY is some weird state
+ * where it doesn't fully power down some parts.
+ * Disable the asserts until the PHY has been fully
+ * reset (ie. the power well has been disabled at
+ * least once).
+ */
+ if (!dev_priv->chv_phy_assert[phy])
+ return;
+
+ if (ch == DPIO_CH0)
+ reg = _CHV_CMN_DW0_CH0;
+ else
+ reg = _CHV_CMN_DW6_CH1;
+
+ mutex_lock(&dev_priv->sb_lock);
+ val = vlv_dpio_read(dev_priv, pipe, reg);
+ mutex_unlock(&dev_priv->sb_lock);
+
+ /*
+ * This assumes !override is only used when the port is disabled.
+ * All lanes should power down even without the override when
+ * the port is disabled.
+ */
+ if (!override || mask == 0xf) {
+ expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
+ /*
+ * If CH1 common lane is not active anymore
+ * (eg. for pipe B DPLL) the entire channel will
+ * shut down, which causes the common lane registers
+ * to read as 0. That means we can't actually check
+ * the lane power down status bits, but as the entire
+ * register reads as 0 it's a good indication that the
+ * channel is indeed entirely powered down.
+ */
+ if (ch == DPIO_CH1 && val == 0)
+ expected = 0;
+ } else if (mask != 0x0) {
+ expected = DPIO_ANYDL_POWERDOWN;
+ } else {
+ expected = 0;
+ }
+
+ if (ch == DPIO_CH0)
+ actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
+ else
+ actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
+ actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
+
+ WARN(actual != expected,
+ "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
+ !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
+ !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
+ reg, val);
+}
+
+bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+ enum dpio_channel ch, bool override)
+{
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ bool was_override;
+
+ mutex_lock(&power_domains->lock);
+
+ was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+
+ if (override == was_override)
+ goto out;
+
+ if (override)
+ dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ else
+ dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+
+ I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+ DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
+ phy, ch, dev_priv->chv_phy_control);
+
+ assert_chv_phy_status(dev_priv);
+
+out:
+ mutex_unlock(&power_domains->lock);
+
+ return was_override;
+}
+
+void chv_phy_powergate_lanes(struct intel_encoder *encoder,
+ bool override, unsigned int mask)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(&encoder->base));
+ enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+
+ mutex_lock(&power_domains->lock);
+
+ dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
+ dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
+
+ if (override)
+ dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ else
+ dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+
+ I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+ DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
+ phy, ch, mask, dev_priv->chv_phy_control);
+
+ assert_chv_phy_status(dev_priv);
+
+ assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
+
+ mutex_unlock(&power_domains->lock);
}
static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
@@ -1167,8 +1466,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
intel_runtime_pm_put(dev_priv);
}
-#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
-
#define HSW_ALWAYS_ON_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PIPE_A) | \
BIT(POWER_DOMAIN_TRANSCODER_EDP) | \
@@ -1430,21 +1727,6 @@ static struct i915_power_well chv_power_wells[] = {
},
};
-static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
- int power_well_id)
-{
- struct i915_power_domains *power_domains = &dev_priv->power_domains;
- struct i915_power_well *power_well;
- int i;
-
- for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
- if (power_well->data == power_well_id)
- return power_well;
- }
-
- return NULL;
-}
-
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
int power_well_id)
{
@@ -1529,6 +1811,21 @@ static struct i915_power_well bxt_power_wells[] = {
}
};
+static int
+sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
+ int disable_power_well)
+{
+ if (disable_power_well >= 0)
+ return !!disable_power_well;
+
+ if (IS_SKYLAKE(dev_priv)) {
+ DRM_DEBUG_KMS("Disabling display power well support\n");
+ return 0;
+ }
+
+ return 1;
+}
+
#define set_power_wells(power_domains, __power_wells) ({ \
(power_domains)->power_wells = (__power_wells); \
(power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \
@@ -1545,6 +1842,9 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
{
struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ i915.disable_power_well = sanitize_disable_power_well_option(dev_priv,
+ i915.disable_power_well);
+
mutex_init(&power_domains->lock);
/*
@@ -1583,7 +1883,6 @@ static void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
/* Make sure we're not suspended first. */
pm_runtime_get_sync(device);
- pm_runtime_disable(device);
}
/**
@@ -1630,19 +1929,80 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
* DISPLAY_PHY_CONTROL can get corrupted if read. As a
* workaround never ever read DISPLAY_PHY_CONTROL, and
* instead maintain a shadow copy ourselves. Use the actual
- * power well state to reconstruct the expected initial
- * value.
+ * power well state and lane status to reconstruct the
+ * expected initial value.
*/
dev_priv->chv_phy_control =
PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) |
PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) |
- PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH0) |
- PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH1) |
- PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY1, DPIO_CH0);
- if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc))
+ PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) |
+ PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) |
+ PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0);
+
+ /*
+ * If all lanes are disabled we leave the override disabled
+ * with all power down bits cleared to match the state we
+ * would use after disabling the port. Otherwise enable the
+ * override and set the lane powerdown bits accding to the
+ * current lane status.
+ */
+ if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
+ uint32_t status = I915_READ(DPLL(PIPE_A));
+ unsigned int mask;
+
+ mask = status & DPLL_PORTB_READY_MASK;
+ if (mask == 0xf)
+ mask = 0x0;
+ else
+ dev_priv->chv_phy_control |=
+ PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0);
+
+ dev_priv->chv_phy_control |=
+ PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0);
+
+ mask = (status & DPLL_PORTC_READY_MASK) >> 4;
+ if (mask == 0xf)
+ mask = 0x0;
+ else
+ dev_priv->chv_phy_control |=
+ PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1);
+
+ dev_priv->chv_phy_control |=
+ PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);
+
dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
- if (cmn_d->ops->is_enabled(dev_priv, cmn_d))
+
+ dev_priv->chv_phy_assert[DPIO_PHY0] = false;
+ } else {
+ dev_priv->chv_phy_assert[DPIO_PHY0] = true;
+ }
+
+ if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
+ uint32_t status = I915_READ(DPIO_PHY_STATUS);
+ unsigned int mask;
+
+ mask = status & DPLL_PORTD_READY_MASK;
+
+ if (mask == 0xf)
+ mask = 0x0;
+ else
+ dev_priv->chv_phy_control |=
+ PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0);
+
+ dev_priv->chv_phy_control |=
+ PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);
+
dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
+
+ dev_priv->chv_phy_assert[DPIO_PHY1] = false;
+ } else {
+ dev_priv->chv_phy_assert[DPIO_PHY1] = true;
+ }
+
+ I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+ DRM_DEBUG_KMS("Initial PHY_CONTROL=0x%08x\n",
+ dev_priv->chv_phy_control);
}
static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
@@ -1688,7 +2048,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
power_domains->initializing = true;
if (IS_CHERRYVIEW(dev)) {
+ mutex_lock(&power_domains->lock);
chv_phy_control_init(dev_priv);
+ mutex_unlock(&power_domains->lock);
} else if (IS_VALLEYVIEW(dev)) {
mutex_lock(&power_domains->lock);
vlv_cmnlane_wa(dev_priv);
@@ -1820,8 +2182,6 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
if (!HAS_RUNTIME_PM(dev))
return;
- pm_runtime_set_active(device);
-
/*
* RPM depends on RC6 to save restore the GT HW context, so make RC6 a
* requirement.
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c98098e884cc..c42b636c2087 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -53,7 +53,7 @@
#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
-static const char *tv_format_names[] = {
+static const char * const tv_format_names[] = {
"NTSC_M" , "NTSC_J" , "NTSC_443",
"PAL_B" , "PAL_D" , "PAL_G" ,
"PAL_H" , "PAL_I" , "PAL_M" ,
@@ -63,7 +63,7 @@ static const char *tv_format_names[] = {
"SECAM_60"
};
-#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
+#define TV_FORMAT_NUM ARRAY_SIZE(tv_format_names)
struct intel_sdvo {
struct intel_encoder base;
@@ -107,6 +107,11 @@ struct intel_sdvo {
bool color_range_auto;
/**
+ * HDMI user specified aspect ratio
+ */
+ enum hdmi_picture_aspect aspect_ratio;
+
+ /**
* This is set if we're going to treat the device as TV-out.
*
* While we have these nice friendly flags for output types that ought
@@ -452,7 +457,7 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer);
}
-static const char *cmd_status_names[] = {
+static const char * const cmd_status_names[] = {
"Power on",
"Success",
"Not supported",
@@ -603,11 +608,11 @@ log_fail:
return false;
}
-static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
+static int intel_sdvo_get_pixel_multiplier(const struct drm_display_mode *adjusted_mode)
{
- if (mode->clock >= 100000)
+ if (adjusted_mode->crtc_clock >= 100000)
return 1;
- else if (mode->clock >= 50000)
+ else if (adjusted_mode->crtc_clock >= 50000)
return 2;
else
return 4;
@@ -1181,6 +1186,10 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
if (intel_sdvo->is_tv)
i9xx_adjust_sdvo_tv_clock(pipe_config);
+ /* Set user selected PAR to incoming mode's member */
+ if (intel_sdvo->is_hdmi)
+ adjusted_mode->picture_aspect_ratio = intel_sdvo->aspect_ratio;
+
return true;
}
@@ -1189,8 +1198,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder)
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(intel_encoder->base.crtc);
- struct drm_display_mode *adjusted_mode =
- &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
struct drm_display_mode *mode = &crtc->config->base.mode;
struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder);
u32 sdvox;
@@ -2044,6 +2052,23 @@ intel_sdvo_set_property(struct drm_connector *connector,
goto done;
}
+ if (property == connector->dev->mode_config.aspect_ratio_property) {
+ switch (val) {
+ case DRM_MODE_PICTURE_ASPECT_NONE:
+ intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
+ break;
+ case DRM_MODE_PICTURE_ASPECT_4_3:
+ intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
+ break;
+ case DRM_MODE_PICTURE_ASPECT_16_9:
+ intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
+ break;
+ default:
+ return -EINVAL;
+ }
+ goto done;
+ }
+
#define CHECK_PROPERTY(name, NAME) \
if (intel_sdvo_connector->name == property) { \
if (intel_sdvo_connector->cur_##name == temp_value) return 0; \
@@ -2222,7 +2247,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
*/
static void
intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
- struct intel_sdvo *sdvo, u32 reg)
+ struct intel_sdvo *sdvo)
{
struct sdvo_device_mapping *mapping;
@@ -2239,7 +2264,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
static void
intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
- struct intel_sdvo *sdvo, u32 reg)
+ struct intel_sdvo *sdvo)
{
struct sdvo_device_mapping *mapping;
u8 pin;
@@ -2383,6 +2408,8 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
intel_attach_broadcast_rgb_property(&connector->base.base);
intel_sdvo->color_range_auto = true;
}
+ intel_attach_aspect_ratio_property(&connector->base.base);
+ intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
}
static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
@@ -2925,7 +2952,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
intel_sdvo->sdvo_reg = sdvo_reg;
intel_sdvo->is_sdvob = is_sdvob;
intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1;
- intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg);
+ intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo);
if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev))
goto err_i2c_bus;
@@ -2987,7 +3014,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
*/
intel_sdvo->base.cloneable = 0;
- intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
+ intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo);
/* Set the input timing to the screen. Assume always input 0. */
if (!intel_sdvo_set_target_input(intel_sdvo))
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 9d8af2f8a875..56dc132e8e20 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -53,13 +53,15 @@ format_is_yuv(uint32_t format)
}
}
-static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
+static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
+ int usecs)
{
/* paranoia */
- if (!mode->crtc_htotal)
+ if (!adjusted_mode->crtc_htotal)
return 1;
- return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
+ return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
+ 1000 * adjusted_mode->crtc_htotal);
}
/**
@@ -76,26 +78,25 @@ static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
* avoid random delays. The value written to @start_vbl_count should be
* supplied to intel_pipe_update_end() for error checking.
*/
-void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
+void intel_pipe_update_start(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
- const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
enum pipe pipe = crtc->pipe;
long timeout = msecs_to_jiffies_timeout(1);
int scanline, min, max, vblank_start;
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
DEFINE_WAIT(wait);
- vblank_start = mode->crtc_vblank_start;
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ vblank_start = adjusted_mode->crtc_vblank_start;
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
vblank_start = DIV_ROUND_UP(vblank_start, 2);
/* FIXME needs to be calibrated sensibly */
- min = vblank_start - usecs_to_scanlines(mode, 100);
+ min = vblank_start - usecs_to_scanlines(adjusted_mode, 100);
max = vblank_start - 1;
local_irq_disable();
- *start_vbl_count = 0;
if (min <= 0 || max <= 0)
return;
@@ -103,7 +104,9 @@ void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
return;
- trace_i915_pipe_update_start(crtc, min, max);
+ crtc->debug.min_vbl = min;
+ crtc->debug.max_vbl = max;
+ trace_i915_pipe_update_start(crtc);
for (;;) {
/*
@@ -134,9 +137,12 @@ void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
drm_crtc_vblank_put(&crtc->base);
- *start_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
+ crtc->debug.scanline_start = scanline;
+ crtc->debug.start_vbl_time = ktime_get();
+ crtc->debug.start_vbl_count =
+ dev->driver->get_vblank_counter(dev, pipe);
- trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count);
+ trace_i915_pipe_update_vblank_evaded(crtc);
}
/**
@@ -148,19 +154,27 @@ void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
* re-enables interrupts and verifies the update was actually completed
* before a vblank using the value of @start_vbl_count.
*/
-void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
+void intel_pipe_update_end(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
enum pipe pipe = crtc->pipe;
+ int scanline_end = intel_get_crtc_scanline(crtc);
u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
+ ktime_t end_vbl_time = ktime_get();
- trace_i915_pipe_update_end(crtc, end_vbl_count);
+ trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
local_irq_enable();
- if (start_vbl_count && start_vbl_count != end_vbl_count)
- DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n",
- pipe_name(pipe), start_vbl_count, end_vbl_count);
+ if (crtc->debug.start_vbl_count &&
+ crtc->debug.start_vbl_count != end_vbl_count) {
+ DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
+ pipe_name(pipe), crtc->debug.start_vbl_count,
+ end_vbl_count,
+ ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
+ crtc->debug.min_vbl, crtc->debug.max_vbl,
+ crtc->debug.scanline_start, scanline_end);
+ }
}
static void
@@ -189,6 +203,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
int scaler_id;
plane_ctl = PLANE_CTL_ENABLE |
+ PLANE_CTL_PIPE_GAMMA_ENABLE |
PLANE_CTL_PIPE_CSC_ENABLE;
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
@@ -223,12 +238,12 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
else if (key->flags & I915_SET_COLORKEY_SOURCE)
plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
- surf_addr = intel_plane_obj_offset(intel_plane, obj);
+ surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
if (intel_rotation_90_or_270(rotation)) {
/* stride: Surface height in tiles */
tile_height = intel_tile_height(dev, fb->pixel_format,
- fb->modifier[0]);
+ fb->modifier[0], 0);
stride = DIV_ROUND_UP(fb->height, tile_height);
plane_size = (src_w << 16) | src_h;
x_offset = stride * tile_height - y - (src_h + 1);
@@ -598,7 +613,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
- I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
+ I915_WRITE(SPRCTL(pipe), 0);
/* Can't leave the scaler enabled... */
if (intel_plane->can_scale)
I915_WRITE(SPRSCALE(pipe), 0);
@@ -923,8 +938,6 @@ intel_commit_sprite_plane(struct drm_plane *plane,
crtc = crtc ? crtc : plane->crtc;
- plane->fb = fb;
-
if (!crtc->state->active)
return;
@@ -1121,7 +1134,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
intel_plane->pipe = pipe;
intel_plane->plane = plane;
- intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe);
+ intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
intel_plane->check_plane = intel_check_sprite_plane;
intel_plane->commit_plane = intel_commit_sprite_plane;
possible_crtcs = (1 << pipe);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 0568ae6ec9dd..6bea78944cd6 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1138,13 +1138,13 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder)
j = 0;
for (i = 0; i < 60; i++)
- I915_WRITE(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ I915_WRITE(TV_H_LUMA(i), tv_mode->filter_table[j++]);
for (i = 0; i < 60; i++)
- I915_WRITE(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ I915_WRITE(TV_H_CHROMA(i), tv_mode->filter_table[j++]);
for (i = 0; i < 43; i++)
- I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ I915_WRITE(TV_V_LUMA(i), tv_mode->filter_table[j++]);
for (i = 0; i < 43; i++)
- I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ I915_WRITE(TV_V_CHROMA(i), tv_mode->filter_table[j++]);
I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
I915_WRITE(TV_CTL, tv_ctl);
}
@@ -1291,7 +1291,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
return;
- for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
+ for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
tv_mode = tv_modes + i;
if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
@@ -1579,7 +1579,7 @@ intel_tv_init(struct drm_device *dev)
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
u32 tv_dac_on, tv_dac_off, save_tv_dac;
- char *tv_format_names[ARRAY_SIZE(tv_modes)];
+ const char *tv_format_names[ARRAY_SIZE(tv_modes)];
int i, initial_mode = 0;
if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
@@ -1677,7 +1677,7 @@ intel_tv_init(struct drm_device *dev)
/* Create TV properties then attach current values */
for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
- tv_format_names[i] = (char *)tv_modes[i].name;
+ tv_format_names[i] = tv_modes[i].name;
drm_mode_create_tv_properties(dev,
ARRAY_SIZE(tv_modes),
tv_format_names);
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 9d3c2e420d2b..43cba129a0c0 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -27,7 +27,7 @@
#include <linux/pm_runtime.h>
-#define FORCEWAKE_ACK_TIMEOUT_MS 2
+#define FORCEWAKE_ACK_TIMEOUT_MS 50
#define __raw_i915_read8(dev_priv__, reg__) readb((dev_priv__)->regs + (reg__))
#define __raw_i915_write8(dev_priv__, reg__, val__) writeb(val__, (dev_priv__)->regs + (reg__))
@@ -52,8 +52,7 @@ static const char * const forcewake_domain_names[] = {
const char *
intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id)
{
- BUILD_BUG_ON((sizeof(forcewake_domain_names)/sizeof(const char *)) !=
- FW_DOMAIN_ID_COUNT);
+ BUILD_BUG_ON(ARRAY_SIZE(forcewake_domain_names) != FW_DOMAIN_ID_COUNT);
if (id >= 0 && id < FW_DOMAIN_ID_COUNT)
return forcewake_domain_names[id];
@@ -526,7 +525,7 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
}
/* We give fast paths for the really cool registers */
-#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+#define NEEDS_FORCE_WAKE(reg) \
((reg) < 0x40000 && (reg) != FORCEWAKE)
#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
@@ -728,7 +727,7 @@ static u##x \
gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
GEN6_READ_HEADER(x); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) \
+ if (NEEDS_FORCE_WAKE(reg)) \
__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
val = __raw_i915_read##x(dev_priv, reg); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
@@ -762,7 +761,7 @@ chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
GEN6_READ_FOOTER; \
}
-#define SKL_NEEDS_FORCE_WAKE(dev_priv, reg) \
+#define SKL_NEEDS_FORCE_WAKE(reg) \
((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
#define __gen9_read(x) \
@@ -770,9 +769,10 @@ static u##x \
gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_READ_HEADER(x); \
- if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg))) \
+ hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
+ if (!SKL_NEEDS_FORCE_WAKE(reg)) \
fw_engine = 0; \
- else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
fw_engine = FORCEWAKE_RENDER; \
else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \
fw_engine = FORCEWAKE_MEDIA; \
@@ -783,6 +783,7 @@ gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
+ hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
GEN6_READ_FOOTER; \
}
@@ -867,7 +868,7 @@ static void \
gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
u32 __fifo_ret = 0; \
GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+ if (NEEDS_FORCE_WAKE(reg)) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
__raw_i915_write##x(dev_priv, reg, val); \
@@ -882,7 +883,7 @@ static void \
hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
u32 __fifo_ret = 0; \
GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+ if (NEEDS_FORCE_WAKE(reg)) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
@@ -983,7 +984,8 @@ gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \
bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_WRITE_HEADER; \
- if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg)) || \
+ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
+ if (!SKL_NEEDS_FORCE_WAKE(reg) || \
is_gen9_shadowed(dev_priv, reg)) \
fw_engine = 0; \
else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
@@ -997,6 +999,8 @@ gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
__raw_i915_write##x(dev_priv, reg, val); \
+ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
+ hsw_unclaimed_reg_detect(dev_priv); \
GEN6_WRITE_FOOTER; \
}
@@ -1198,8 +1202,6 @@ void intel_uncore_init(struct drm_device *dev)
switch (INTEL_INFO(dev)->gen) {
default:
- MISSING_CASE(INTEL_INFO(dev)->gen);
- return;
case 9:
ASSIGN_WRITE_MMIO_VFUNCS(gen9);
ASSIGN_READ_MMIO_VFUNCS(gen9);
@@ -1427,21 +1429,21 @@ static int ironlake_do_reset(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
+ I915_WRITE(ILK_GDSR,
ILK_GRDOM_RENDER | ILK_GRDOM_RESET_ENABLE);
- ret = wait_for((I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) &
+ ret = wait_for((I915_READ(ILK_GDSR) &
ILK_GRDOM_RESET_ENABLE) == 0, 500);
if (ret)
return ret;
- I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
+ I915_WRITE(ILK_GDSR,
ILK_GRDOM_MEDIA | ILK_GRDOM_RESET_ENABLE);
- ret = wait_for((I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) &
+ ret = wait_for((I915_READ(ILK_GDSR) &
ILK_GRDOM_RESET_ENABLE) == 0, 500);
if (ret)
return ret;
- I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, 0);
+ I915_WRITE(ILK_GDSR, 0);
return 0;
}
@@ -1529,13 +1531,22 @@ static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)
int intel_gpu_reset(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
int (*reset)(struct drm_device *);
+ int ret;
reset = intel_get_gpu_reset(dev);
if (reset == NULL)
return -ENODEV;
- return reset(dev);
+ /* If the power well sleeps during the reset, the reset
+ * request may be dropped and never completes (causing -EIO).
+ */
+ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+ ret = reset(dev);
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+ return ret;
}
bool intel_has_gpu_reset(struct drm_device *dev)
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 644edf65dbe0..98605ea2ad9d 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -48,11 +48,17 @@ static const struct dw_hdmi_mpll_config imx_mpll_cfg[] = {
{ 0x40a2, 0x000a },
},
}, {
- ~0UL, {
+ 216000000, {
{ 0x00a0, 0x000a },
{ 0x2001, 0x000f },
{ 0x4002, 0x000f },
},
+ }, {
+ ~0UL, {
+ { 0x0000, 0x0000 },
+ { 0x0000, 0x0000 },
+ { 0x0000, 0x0000 },
+ },
}
};
@@ -82,7 +88,7 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
*/
static const struct dw_hdmi_phy_config imx_phy_config[] = {
/*pixelclk symbol term vlev */
- { 148500000, 0x800d, 0x0005, 0x01ad},
+ { 216000000, 0x800d, 0x0005, 0x01ad},
{ ~0UL, 0x0000, 0x0000, 0x0000}
};
@@ -148,7 +154,8 @@ static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con,
{
if (mode->clock < 13500)
return MODE_CLOCK_LOW;
- if (mode->clock > 266000)
+ /* FIXME: Hardware is capable of 266MHz, but setup data is missing. */
+ if (mode->clock > 216000)
return MODE_CLOCK_HIGH;
return MODE_OK;
@@ -159,7 +166,8 @@ static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
{
if (mode->clock < 13500)
return MODE_CLOCK_LOW;
- if (mode->clock > 270000)
+ /* FIXME: Hardware is capable of 270MHz, but setup data is missing. */
+ if (mode->clock > 216000)
return MODE_CLOCK_HIGH;
return MODE_OK;
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 74f505b0dd02..64f16ea779ef 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -145,10 +145,10 @@ void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
}
EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
-static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
+static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe)
{
struct imx_drm_device *imxdrm = drm->dev_private;
- struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
+ struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe];
int ret;
if (!imx_drm_crtc)
@@ -163,10 +163,10 @@ static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
return ret;
}
-static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
+static void imx_drm_disable_vblank(struct drm_device *drm, unsigned int pipe)
{
struct imx_drm_device *imxdrm = drm->dev_private;
- struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
+ struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe];
if (!imx_drm_crtc)
return;
@@ -487,7 +487,7 @@ static struct drm_driver imx_drm_driver = {
.gem_prime_vmap = drm_gem_cma_prime_vmap,
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
.gem_prime_mmap = drm_gem_cma_prime_mmap,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = imx_drm_enable_vblank,
.disable_vblank = imx_drm_disable_vblank,
.ioctls = imx_drm_ioctls,
@@ -531,59 +531,12 @@ static const struct component_master_ops imx_drm_ops = {
static int imx_drm_platform_probe(struct platform_device *pdev)
{
- struct device_node *ep, *port, *remote;
- struct component_match *match = NULL;
- int ret;
- int i;
-
- /*
- * Bind the IPU display interface ports first, so that
- * imx_drm_encoder_parse_of called from encoder .bind callbacks
- * works as expected.
- */
- for (i = 0; ; i++) {
- port = of_parse_phandle(pdev->dev.of_node, "ports", i);
- if (!port)
- break;
-
- component_match_add(&pdev->dev, &match, compare_of, port);
- }
+ int ret = drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops);
- if (i == 0) {
- dev_err(&pdev->dev, "missing 'ports' property\n");
- return -ENODEV;
- }
+ if (!ret)
+ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- /* Then bind all encoders */
- for (i = 0; ; i++) {
- port = of_parse_phandle(pdev->dev.of_node, "ports", i);
- if (!port)
- break;
-
- for_each_child_of_node(port, ep) {
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote || !of_device_is_available(remote)) {
- of_node_put(remote);
- continue;
- } else if (!of_device_is_available(remote->parent)) {
- dev_warn(&pdev->dev, "parent device of %s is not available\n",
- remote->full_name);
- of_node_put(remote);
- continue;
- }
-
- component_match_add(&pdev->dev, &match, compare_of,
- remote);
- of_node_put(remote);
- }
- of_node_put(port);
- }
-
- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- return component_master_add_with_match(&pdev->dev, &imx_drm_ops, match);
+ return ret;
}
static int imx_drm_platform_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 878a643d72e4..575f4c84388f 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -23,12 +23,21 @@
#define to_ipu_plane(x) container_of(x, struct ipu_plane, base)
static const uint32_t ipu_plane_formats[] = {
+ DRM_FORMAT_ARGB1555,
DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_ABGR1555,
DRM_FORMAT_XBGR1555,
+ DRM_FORMAT_RGBA5551,
+ DRM_FORMAT_BGRA5551,
+ DRM_FORMAT_ARGB4444,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_RGBX8888,
+ DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_BGRA8888,
DRM_FORMAT_YUYV,
DRM_FORMAT_YVYU,
DRM_FORMAT_YUV420,
@@ -175,8 +184,15 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
/* Enable local alpha on partial plane */
switch (fb->pixel_format) {
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_ARGB4444:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_BGRA8888:
ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
break;
default:
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
index 8cfa9cb74c86..1f2f9ca25901 100644
--- a/drivers/gpu/drm/mga/mga_dma.c
+++ b/drivers/gpu/drm/mga/mga_dma.c
@@ -416,7 +416,7 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags)
return 0;
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
/**
* Bootstrap the driver for AGP DMA.
*
@@ -947,7 +947,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
drm_legacy_ioremapfree(dev->agp_buffer_map, dev);
if (dev_priv->used_new_dma_init) {
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->agp_handle != 0) {
struct drm_agp_binding unbind_req;
struct drm_agp_buffer free_req;
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
index b4a2014917e5..bb312339e0b0 100644
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -183,9 +183,9 @@ extern int mga_warp_install_microcode(drm_mga_private_t *dev_priv);
extern int mga_warp_init(drm_mga_private_t *dev_priv);
/* mga_irq.c */
-extern int mga_enable_vblank(struct drm_device *dev, int crtc);
-extern void mga_disable_vblank(struct drm_device *dev, int crtc);
-extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int mga_enable_vblank(struct drm_device *dev, unsigned int pipe);
+extern void mga_disable_vblank(struct drm_device *dev, unsigned int pipe);
+extern u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
extern irqreturn_t mga_driver_irq_handler(int irq, void *arg);
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c
index 1b071b8ff9dc..693ba708cfed 100644
--- a/drivers/gpu/drm/mga/mga_irq.c
+++ b/drivers/gpu/drm/mga/mga_irq.c
@@ -35,12 +35,12 @@
#include <drm/mga_drm.h>
#include "mga_drv.h"
-u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
+u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
const drm_mga_private_t *const dev_priv =
(drm_mga_private_t *) dev->dev_private;
- if (crtc != 0)
+ if (pipe != 0)
return 0;
return atomic_read(&dev_priv->vbl_received);
@@ -88,13 +88,13 @@ irqreturn_t mga_driver_irq_handler(int irq, void *arg)
return IRQ_NONE;
}
-int mga_enable_vblank(struct drm_device *dev, int crtc)
+int mga_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- if (crtc != 0) {
- DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
- crtc);
+ if (pipe != 0) {
+ DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
+ pipe);
return 0;
}
@@ -103,11 +103,11 @@ int mga_enable_vblank(struct drm_device *dev, int crtc)
}
-void mga_disable_vblank(struct drm_device *dev, int crtc)
+void mga_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
- if (crtc != 0) {
- DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
- crtc);
+ if (pipe != 0) {
+ DRM_ERROR("tried to disable vblank on non-existent crtc %u\n",
+ pipe);
}
/* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c
index 4f2068fe5d88..a7bf6a90eae5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_cursor.c
+++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c
@@ -70,6 +70,11 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
BUG_ON(pixels_current == pixels_prev);
+ if (!handle || !file_priv) {
+ mga_hide_cursor(mdev);
+ return 0;
+ }
+
obj = drm_gem_object_lookup(dev, file_priv, handle);
if (!obj)
return -ENOENT;
@@ -88,12 +93,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
goto out_unreserve1;
}
- if (!handle) {
- mga_hide_cursor(mdev);
- ret = 0;
- goto out1;
- }
-
/* Move cursor buffers into VRAM if they aren't already */
if (!pixels_1->pin_count) {
ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM,
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 8e6c7c638e24..84d3ec98e6b9 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -14,20 +14,6 @@ config DRM_MSM
help
DRM/KMS driver for MSM/snapdragon.
-config DRM_MSM_FBDEV
- bool "Enable legacy fbdev support for MSM modesetting driver"
- depends on DRM_MSM
- select DRM_KMS_FB_HELPER
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- default y
- help
- Choose this option if you have a need for the legacy fbdev
- support. Note that this support also provide the linux console
- support on top of the MSM modesetting driver.
-
config DRM_MSM_REGISTER_LOGGING
bool "MSM DRM register logging"
depends on DRM_MSM
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 0a543eb5e5d7..1c90290be716 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -50,7 +50,7 @@ msm-y := \
msm_rd.o \
msm_ringbuffer.o
-msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
+msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index 0261f0d31612..9e2aceb4ffe6 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index 48d133711487..97dc1c6ec107 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
@@ -280,6 +281,8 @@ enum a3xx_rb_blend_opcode {
enum a3xx_intp_mode {
SMOOTH = 0,
FLAT = 1,
+ ZERO = 2,
+ ONE = 3,
};
enum a3xx_repl_mode {
@@ -680,9 +683,16 @@ static inline uint32_t REG_A3XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000460
#define A3XX_GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE 0x00080000
#define A3XX_GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE 0x00100000
#define A3XX_GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE 0x00200000
+#define A3XX_GRAS_CL_CLIP_CNTL_ZERO_GB_SCALE_Z 0x00400000
#define A3XX_GRAS_CL_CLIP_CNTL_ZCOORD 0x00800000
#define A3XX_GRAS_CL_CLIP_CNTL_WCOORD 0x01000000
#define A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE 0x02000000
+#define A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__MASK 0x1c000000
+#define A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__SHIFT 26
+static inline uint32_t A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES(uint32_t val)
+{
+ return ((val) << A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__SHIFT) & A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__MASK;
+}
#define REG_A3XX_GRAS_CL_GB_CLIP_ADJ 0x00002044
#define A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK 0x000003ff
@@ -773,7 +783,7 @@ static inline uint32_t A3XX_GRAS_SU_POINT_SIZE(float val)
#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
{
- return ((((int32_t)(val * 16384.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK;
+ return ((((int32_t)(val * 1048576.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK;
}
#define REG_A3XX_GRAS_SU_POLY_OFFSET_OFFSET 0x0000206d
@@ -894,6 +904,9 @@ static inline uint32_t A3XX_RB_MODE_CONTROL_MRT(uint32_t val)
#define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE 0x00010000
#define REG_A3XX_RB_RENDER_CONTROL 0x000020c1
+#define A3XX_RB_RENDER_CONTROL_DUAL_COLOR_IN_ENABLE 0x00000001
+#define A3XX_RB_RENDER_CONTROL_YUV_IN_ENABLE 0x00000002
+#define A3XX_RB_RENDER_CONTROL_COV_VALUE_INPUT_ENABLE 0x00000004
#define A3XX_RB_RENDER_CONTROL_FACENESS 0x00000008
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK 0x00000ff0
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__SHIFT 4
@@ -907,6 +920,8 @@ static inline uint32_t A3XX_RB_RENDER_CONTROL_BIN_WIDTH(uint32_t val)
#define A3XX_RB_RENDER_CONTROL_YCOORD 0x00008000
#define A3XX_RB_RENDER_CONTROL_ZCOORD 0x00010000
#define A3XX_RB_RENDER_CONTROL_WCOORD 0x00020000
+#define A3XX_RB_RENDER_CONTROL_I_CLAMP_ENABLE 0x00080000
+#define A3XX_RB_RENDER_CONTROL_COV_VALUE_OUTPUT_ENABLE 0x00100000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST 0x00400000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK 0x07000000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT 24
@@ -914,6 +929,8 @@ static inline uint32_t A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(enum adreno_compar
{
return ((val) << A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT) & A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK;
}
+#define A3XX_RB_RENDER_CONTROL_ALPHA_TO_COVERAGE 0x40000000
+#define A3XX_RB_RENDER_CONTROL_ALPHA_TO_ONE 0x80000000
#define REG_A3XX_RB_MSAA_CONTROL 0x000020c2
#define A3XX_RB_MSAA_CONTROL_DISABLE 0x00000400
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index ac55066db3b0..99de8271dba8 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
@@ -162,10 +163,13 @@ enum a4xx_tex_fmt {
TFMT4_8_UNORM = 4,
TFMT4_8_8_UNORM = 14,
TFMT4_8_8_8_8_UNORM = 28,
+ TFMT4_8_SNORM = 5,
TFMT4_8_8_SNORM = 15,
TFMT4_8_8_8_8_SNORM = 29,
+ TFMT4_8_UINT = 6,
TFMT4_8_8_UINT = 16,
TFMT4_8_8_8_8_UINT = 30,
+ TFMT4_8_SINT = 7,
TFMT4_8_8_SINT = 17,
TFMT4_8_8_8_8_SINT = 31,
TFMT4_16_UINT = 21,
@@ -246,7 +250,8 @@ enum a4xx_tex_clamp {
A4XX_TEX_REPEAT = 0,
A4XX_TEX_CLAMP_TO_EDGE = 1,
A4XX_TEX_MIRROR_REPEAT = 2,
- A4XX_TEX_CLAMP_NONE = 3,
+ A4XX_TEX_CLAMP_TO_BORDER = 3,
+ A4XX_TEX_MIRROR_CLAMP = 4,
};
enum a4xx_tex_aniso {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index 399a9e528139..c304468cf2bd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
@@ -85,6 +86,10 @@ enum adreno_rb_blend_factor {
FACTOR_CONSTANT_ALPHA = 14,
FACTOR_ONE_MINUS_CONSTANT_ALPHA = 15,
FACTOR_SRC_ALPHA_SATURATE = 16,
+ FACTOR_SRC1_COLOR = 20,
+ FACTOR_ONE_MINUS_SRC1_COLOR = 21,
+ FACTOR_SRC1_ALPHA = 22,
+ FACTOR_ONE_MINUS_SRC1_ALPHA = 23,
};
enum adreno_rb_surface_endian {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 41904fed1350..a22fef569499 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 1d2e32f0817b..b2b5f3dd1b4c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -567,114 +567,234 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
#define REG_DSI_8x60_PHY_CAL_STATUS 0x000000fc
#define DSI_8x60_PHY_CAL_STATUS_CAL_BUSY 0x10000000
-static inline uint32_t REG_DSI_8960_LN(uint32_t i0) { return 0x00000300 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN(uint32_t i0) { return 0x00000000 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_CFG_0(uint32_t i0) { return 0x00000300 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_0(uint32_t i0) { return 0x00000000 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_CFG_1(uint32_t i0) { return 0x00000304 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_1(uint32_t i0) { return 0x00000004 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_CFG_2(uint32_t i0) { return 0x00000308 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_2(uint32_t i0) { return 0x00000008 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000030c + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000000c + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_TEST_STR_0(uint32_t i0) { return 0x00000314 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(uint32_t i0) { return 0x00000014 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_TEST_STR_1(uint32_t i0) { return 0x00000318 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(uint32_t i0) { return 0x00000018 + 0x40*i0; }
-#define REG_DSI_8960_PHY_LNCK_CFG_0 0x00000400
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_0 0x00000100
-#define REG_DSI_8960_PHY_LNCK_CFG_1 0x00000404
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_1 0x00000104
-#define REG_DSI_8960_PHY_LNCK_CFG_2 0x00000408
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_2 0x00000108
-#define REG_DSI_8960_PHY_LNCK_TEST_DATAPATH 0x0000040c
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH 0x0000010c
-#define REG_DSI_8960_PHY_LNCK_TEST_STR0 0x00000414
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0 0x00000114
-#define REG_DSI_8960_PHY_LNCK_TEST_STR1 0x00000418
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1 0x00000118
-#define REG_DSI_8960_PHY_TIMING_CTRL_0 0x00000440
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_0 0x00000140
+#define DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_1 0x00000144
+#define DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_2 0x00000148
+#define DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_3 0x0000014c
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_4 0x00000150
+#define DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_5 0x00000154
+#define DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_6 0x00000158
+#define DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_7 0x0000015c
+#define DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_8 0x00000160
+#define DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_9 0x00000164
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__MASK 0x00000007
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__MASK;
+}
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__MASK 0x00000070
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__SHIFT 4
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_10 0x00000168
+#define DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__MASK 0x00000007
+#define DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_11 0x0000016c
+#define DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_CTRL_0 0x00000170
+
+#define REG_DSI_28nm_8960_PHY_CTRL_1 0x00000174
+
+#define REG_DSI_28nm_8960_PHY_CTRL_2 0x00000178
+
+#define REG_DSI_28nm_8960_PHY_CTRL_3 0x0000017c
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_0 0x00000180
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_1 0x00000184
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_2 0x00000188
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_0 0x0000018c
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_1 0x00000190
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_2 0x00000194
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_3 0x00000198
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_4 0x0000019c
-#define REG_DSI_8960_PHY_TIMING_CTRL_1 0x00000444
+#define REG_DSI_28nm_8960_PHY_LDO_CTRL 0x000001b0
-#define REG_DSI_8960_PHY_TIMING_CTRL_2 0x00000448
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0 0x00000000
-#define REG_DSI_8960_PHY_TIMING_CTRL_3 0x0000044c
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1 0x00000004
-#define REG_DSI_8960_PHY_TIMING_CTRL_4 0x00000450
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2 0x00000008
-#define REG_DSI_8960_PHY_TIMING_CTRL_5 0x00000454
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3 0x0000000c
-#define REG_DSI_8960_PHY_TIMING_CTRL_6 0x00000458
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4 0x00000010
-#define REG_DSI_8960_PHY_TIMING_CTRL_7 0x0000045c
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_5 0x00000014
-#define REG_DSI_8960_PHY_TIMING_CTRL_8 0x00000460
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG 0x00000018
-#define REG_DSI_8960_PHY_TIMING_CTRL_9 0x00000464
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER 0x00000028
-#define REG_DSI_8960_PHY_TIMING_CTRL_10 0x00000468
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_0 0x0000002c
-#define REG_DSI_8960_PHY_TIMING_CTRL_11 0x0000046c
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_1 0x00000030
-#define REG_DSI_8960_PHY_CTRL_0 0x00000470
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2 0x00000034
-#define REG_DSI_8960_PHY_CTRL_1 0x00000474
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0 0x00000038
-#define REG_DSI_8960_PHY_CTRL_2 0x00000478
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1 0x0000003c
-#define REG_DSI_8960_PHY_CTRL_3 0x0000047c
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_2 0x00000040
-#define REG_DSI_8960_PHY_STRENGTH_0 0x00000480
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3 0x00000044
-#define REG_DSI_8960_PHY_STRENGTH_1 0x00000484
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4 0x00000048
-#define REG_DSI_8960_PHY_STRENGTH_2 0x00000488
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS 0x00000050
+#define DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY 0x00000010
-#define REG_DSI_8960_PHY_BIST_CTRL_0 0x0000048c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_0 0x00000000
+#define DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE 0x00000001
-#define REG_DSI_8960_PHY_BIST_CTRL_1 0x00000490
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_1 0x00000004
-#define REG_DSI_8960_PHY_BIST_CTRL_2 0x00000494
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_2 0x00000008
-#define REG_DSI_8960_PHY_BIST_CTRL_3 0x00000498
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_3 0x0000000c
-#define REG_DSI_8960_PHY_BIST_CTRL_4 0x0000049c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_4 0x00000010
-#define REG_DSI_8960_PHY_LDO_CTRL 0x000004b0
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_5 0x00000014
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_0 0x00000500
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_6 0x00000018
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_1 0x00000504
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_7 0x0000001c
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_2 0x00000508
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_8 0x00000020
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_3 0x0000050c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_9 0x00000024
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_4 0x00000510
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_10 0x00000028
-#define REG_DSI_8960_PHY_REGULATOR_CAL_PWR_CFG 0x00000518
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_11 0x0000002c
-#define REG_DSI_8960_PHY_CAL_HW_TRIGGER 0x00000528
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_12 0x00000030
-#define REG_DSI_8960_PHY_CAL_SW_CFG_0 0x0000052c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_13 0x00000034
-#define REG_DSI_8960_PHY_CAL_SW_CFG_1 0x00000530
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_14 0x00000038
-#define REG_DSI_8960_PHY_CAL_SW_CFG_2 0x00000534
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_15 0x0000003c
-#define REG_DSI_8960_PHY_CAL_HW_CFG_0 0x00000538
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_16 0x00000040
-#define REG_DSI_8960_PHY_CAL_HW_CFG_1 0x0000053c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_17 0x00000044
-#define REG_DSI_8960_PHY_CAL_HW_CFG_2 0x00000540
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_18 0x00000048
-#define REG_DSI_8960_PHY_CAL_HW_CFG_3 0x00000544
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_19 0x0000004c
-#define REG_DSI_8960_PHY_CAL_HW_CFG_4 0x00000548
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_20 0x00000050
-#define REG_DSI_8960_PHY_CAL_STATUS 0x00000550
-#define DSI_8960_PHY_CAL_STATUS_CAL_BUSY 0x00000010
+#define REG_DSI_28nm_8960_PHY_PLL_RDY 0x00000080
+#define DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY 0x00000001
static inline uint32_t REG_DSI_28nm_PHY_LN(uint32_t i0) { return 0x00000000 + 0x40*i0; }
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8d82973fe9db..4c49868efcda 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -278,7 +278,7 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
}
for (i = 0; i < num; i++) {
- if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
+ if (regulator_can_change_voltage(s[i].consumer)) {
ret = regulator_set_voltage(s[i].consumer,
regs[i].min_voltage, regs[i].max_voltage);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index 5de505e627be..80ec65e47468 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 401ff58d6893..f1f955f571fa 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -178,7 +178,7 @@ static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
}
for (i = 0; i < num; i++) {
- if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
+ if (regulator_can_change_voltage(s[i].consumer)) {
ret = regulator_set_voltage(s[i].consumer,
regs[i].min_voltage, regs[i].max_voltage);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index f1a7c7b46420..edf74110ced7 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -99,16 +99,14 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_1(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_2(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_3(i), 0);
+ dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i), 0x1);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i), 0x97);
}
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(0), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(1), 0x5);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(2), 0xa);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(3), 0xf);
+ dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_4, 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_1, 0xc0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR0, 0x1);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR1, 0xbb);
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index 06cbddfc914f..7d7662e69e11 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -45,7 +45,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#define REG_SFPB_CFG 0x00000058
+enum sfpb_ahb_arb_master_port_en {
+ SFPB_MASTER_PORT_ENABLE = 3,
+ SFPB_MASTER_PORT_DISABLE = 0,
+};
+
+#define REG_SFPB_GPREG 0x00000058
+#define SFPB_GPREG_MASTER_PORT_EN__MASK 0x00001800
+#define SFPB_GPREG_MASTER_PORT_EN__SHIFT 11
+static inline uint32_t SFPB_GPREG_MASTER_PORT_EN(enum sfpb_ahb_arb_master_port_en val)
+{
+ return ((val) << SFPB_GPREG_MASTER_PORT_EN__SHIFT) & SFPB_GPREG_MASTER_PORT_EN__MASK;
+}
#endif /* SFPB_XML */
diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h
index bef1d65fe28c..90bf5ed46746 100644
--- a/drivers/gpu/drm/msm/edp/edp.xml.h
+++ b/drivers/gpu/drm/msm/edp/edp.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 101b324cdeef..1f4a95eeb348 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -328,6 +328,9 @@ fail:
.item ## _names = item ##_names_ ## entry, \
.item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
+static const char *pwr_reg_names_none[] = {};
+static const char *hpd_reg_names_none[] = {};
+
static struct hdmi_platform_config hdmi_tx_8660_config = {
.phy_init = hdmi_phy_8x60_init,
};
@@ -367,18 +370,26 @@ static struct hdmi_platform_config hdmi_tx_8084_config = {
.hpd_freq = hpd_clk_freq_8x74,
};
-static const char *hpd_reg_names_8x94[] = {};
-
static struct hdmi_platform_config hdmi_tx_8994_config = {
.phy_init = NULL, /* nothing to do for this HDMI PHY 20nm */
HDMI_CFG(pwr_reg, 8x74),
- HDMI_CFG(hpd_reg, 8x94),
+ HDMI_CFG(hpd_reg, none),
+ HDMI_CFG(pwr_clk, 8x74),
+ HDMI_CFG(hpd_clk, 8x74),
+ .hpd_freq = hpd_clk_freq_8x74,
+};
+
+static struct hdmi_platform_config hdmi_tx_8996_config = {
+ .phy_init = NULL,
+ HDMI_CFG(pwr_reg, none),
+ HDMI_CFG(hpd_reg, none),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq = hpd_clk_freq_8x74,
};
static const struct of_device_id dt_match[] = {
+ { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8996_config },
{ .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8994_config },
{ .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config },
{ .compatible = "qcom,hdmi-tx-8974", .data = &hdmi_tx_8974_config },
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index 0b1b5586ff35..10c45700aefe 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index 2aa23b98f8aa..dbd9cc4daf2e 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 74b86734fef5..d5d94575fa1b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index e9dee367b597..30d57e74c42f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -99,22 +99,28 @@ static const struct drm_plane_funcs mdp4_plane_funcs = {
};
static int mdp4_plane_prepare_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
struct mdp4_kms *mdp4_kms = get_kms(plane);
+ struct drm_framebuffer *fb = new_state->fb;
+
+ if (!fb)
+ return 0;
DBG("%s: prepare: FB[%u]", mdp4_plane->name, fb->base.id);
return msm_framebuffer_prepare(fb, mdp4_kms->id);
}
static void mdp4_plane_cleanup_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *old_state)
{
struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
struct mdp4_kms *mdp4_kms = get_kms(plane);
+ struct drm_framebuffer *fb = old_state->fb;
+
+ if (!fb)
+ return;
DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id);
msm_framebuffer_cleanup(fb, mdp4_kms->id);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index 3469f50d5590..c37da9c61e29 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -895,6 +895,7 @@ static inline uint32_t MDP5_PIPE_SRC_OP_MODE_BWC(enum mdp5_pipe_bwc val)
#define MDP5_PIPE_SRC_OP_MODE_IGC_ROM_1 0x00040000
#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE 0x00400000
#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE_ODD 0x00800000
+#define MDP5_PIPE_SRC_OP_MODE_SW_PIX_EXT_OVERRIDE 0x80000000
static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000003c + __offset_PIPE(i0); }
@@ -932,6 +933,83 @@ static inline uint32_t MDP5_PIPE_DECIMATION_HORZ(uint32_t val)
return ((val) << MDP5_PIPE_DECIMATION_HORZ__SHIFT) & MDP5_PIPE_DECIMATION_HORZ__MASK;
}
+static inline uint32_t __offset_SW_PIX_EXT(enum mdp_component_type idx)
+{
+ switch (idx) {
+ case COMP_0: return 0x00000100;
+ case COMP_1_2: return 0x00000110;
+ case COMP_3: return 0x00000120;
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000000 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT_LR(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000000 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__MASK 0x000000ff
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__SHIFT 0
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__MASK 0x0000ff00
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__SHIFT 8
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__MASK 0x00ff0000
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__SHIFT 16
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__MASK 0xff000000
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__SHIFT 24
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT_TB(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000004 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__MASK 0x000000ff
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__SHIFT 0
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__MASK 0x0000ff00
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__SHIFT 8
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__MASK 0x00ff0000
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__SHIFT 16
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__MASK 0xff000000
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__SHIFT 24
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000008 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__MASK 0x0000ffff
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__SHIFT 0
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__MASK 0xffff0000
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__SHIFT 16
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__SHIFT) & MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__MASK;
+}
+
static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00000204 + __offset_PIPE(i0); }
#define MDP5_PIPE_SCALE_CONFIG_SCALEX_EN 0x00000001
#define MDP5_PIPE_SCALE_CONFIG_SCALEY_EN 0x00000002
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index a1e26f23c7cc..bb1225aa2f75 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -27,6 +27,8 @@ const struct mdp5_cfg_hw msm8x74v1_config = {
.mdp = {
.count = 1,
.base = { 0x00100 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 22,
@@ -96,6 +98,8 @@ const struct mdp5_cfg_hw msm8x74v2_config = {
.mdp = {
.count = 1,
.base = { 0x00100 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 22,
@@ -165,6 +169,8 @@ const struct mdp5_cfg_hw apq8084_config = {
.mdp = {
.count = 1,
.base = { 0x00100 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 44,
@@ -242,6 +248,8 @@ const struct mdp5_cfg_hw msm8x16_config = {
.mdp = {
.count = 1,
.base = { 0x01000 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 8,
@@ -301,6 +309,8 @@ const struct mdp5_cfg_hw msm8x94_config = {
.mdp = {
.count = 1,
.base = { 0x01000 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 44,
@@ -370,7 +380,89 @@ const struct mdp5_cfg_hw msm8x94_config = {
[3] = INTF_HDMI,
},
},
- .max_clk = 320000000,
+ .max_clk = 400000000,
+};
+
+const struct mdp5_cfg_hw msm8x96_config = {
+ .name = "msm8x96",
+ .mdp = {
+ .count = 1,
+ .base = { 0x01000 },
+ .caps = MDP_CAP_DSC |
+ MDP_CAP_CDM |
+ 0,
+ },
+ .ctl = {
+ .count = 5,
+ .base = { 0x02000, 0x02200, 0x02400, 0x02600, 0x02800 },
+ .flush_hw_mask = 0xf4ffffff,
+ },
+ .pipe_vig = {
+ .count = 4,
+ .base = { 0x05000, 0x07000, 0x09000, 0x0b000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ MDP_PIPE_CAP_CSC |
+ MDP_PIPE_CAP_DECIMATION |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_rgb = {
+ .count = 4,
+ .base = { 0x15000, 0x17000, 0x19000, 0x1b000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ MDP_PIPE_CAP_DECIMATION |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_dma = {
+ .count = 2,
+ .base = { 0x25000, 0x27000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .lm = {
+ .count = 6,
+ .base = { 0x45000, 0x46000, 0x47000, 0x48000, 0x49000, 0x4a000 },
+ .nb_stages = 8,
+ .max_width = 2560,
+ .max_height = 0xFFFF,
+ },
+ .dspp = {
+ .count = 2,
+ .base = { 0x55000, 0x57000 },
+ },
+ .ad = {
+ .count = 3,
+ .base = { 0x79000, 0x79800, 0x7a000 },
+ },
+ .pp = {
+ .count = 4,
+ .base = { 0x71000, 0x71800, 0x72000, 0x72800 },
+ },
+ .cdm = {
+ .count = 1,
+ .base = { 0x7a200 },
+ },
+ .dsc = {
+ .count = 2,
+ .base = { 0x81000, 0x81400 },
+ },
+ .intf = {
+ .base = { 0x6b000, 0x6b800, 0x6c000, 0x6c800, 0x6d000 },
+ .connect = {
+ [0] = INTF_DISABLED,
+ [1] = INTF_DSI,
+ [2] = INTF_DSI,
+ [3] = INTF_HDMI,
+ },
+ },
+ .max_clk = 412500000,
};
static const struct mdp5_cfg_handler cfg_handlers[] = {
@@ -379,6 +471,7 @@ static const struct mdp5_cfg_handler cfg_handlers[] = {
{ .revision = 3, .config = { .hw = &apq8084_config } },
{ .revision = 6, .config = { .hw = &msm8x16_config } },
{ .revision = 9, .config = { .hw = &msm8x94_config } },
+ { .revision = 7, .config = { .hw = &msm8x96_config } },
};
static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index efb918d9f68b..050e1618c836 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -61,7 +61,12 @@ struct mdp5_smp_block {
int mmb_size; /* MMB: size in bytes */
uint32_t clients[MAX_CLIENTS]; /* SMP port allocation /pipe */
mdp5_smp_state_t reserved_state;/* SMP MMBs statically allocated */
- int reserved[MAX_CLIENTS]; /* # of MMBs allocated per client */
+ uint8_t reserved[MAX_CLIENTS]; /* # of MMBs allocated per client */
+};
+
+struct mdp5_mdp_block {
+ MDP5_SUB_BLOCK_DEFINITION;
+ uint32_t caps; /* MDP capabilities: MDP_CAP_xxx bits */
};
#define MDP5_INTF_NUM_MAX 5
@@ -74,7 +79,7 @@ struct mdp5_intf_block {
struct mdp5_cfg_hw {
char *name;
- struct mdp5_sub_block mdp;
+ struct mdp5_mdp_block mdp;
struct mdp5_smp_block smp;
struct mdp5_ctl_block ctl;
struct mdp5_pipe_block pipe_vig;
@@ -84,6 +89,8 @@ struct mdp5_cfg_hw {
struct mdp5_sub_block dspp;
struct mdp5_sub_block ad;
struct mdp5_sub_block pp;
+ struct mdp5_sub_block dsc;
+ struct mdp5_sub_block cdm;
struct mdp5_intf_block intf;
uint32_t max_clk;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 047cb0433ccb..b532faa8026d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -452,15 +452,19 @@ static void read_hw_revision(struct mdp5_kms *mdp5_kms,
}
static int get_clk(struct platform_device *pdev, struct clk **clkp,
- const char *name)
+ const char *name, bool mandatory)
{
struct device *dev = &pdev->dev;
struct clk *clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
+ if (IS_ERR(clk) && mandatory) {
dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk));
return PTR_ERR(clk);
}
- *clkp = clk;
+ if (IS_ERR(clk))
+ DBG("skipping %s", name);
+ else
+ *clkp = clk;
+
return 0;
}
@@ -514,25 +518,26 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
goto fail;
}
- ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk");
+ /* mandatory clocks: */
+ ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk");
+ ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src");
+ ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk");
+ ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk");
- if (ret)
- DBG("failed to get (optional) lut_clk clock");
- ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk");
+ ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk", true);
if (ret)
goto fail;
+ /* optional clocks: */
+ get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk", false);
+
/* we need to set a default rate before enabling. Set a safe
* rate first, then figure out hw revision, and then set a
* more optimal rate:
@@ -549,15 +554,23 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
}
config = mdp5_cfg_get_config(mdp5_kms->cfg);
+ mdp5_kms->caps = config->hw->mdp.caps;
/* TODO: compute core clock rate at runtime */
clk_set_rate(mdp5_kms->src_clk, config->hw->max_clk);
- mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
- if (IS_ERR(mdp5_kms->smp)) {
- ret = PTR_ERR(mdp5_kms->smp);
- mdp5_kms->smp = NULL;
- goto fail;
+ /*
+ * Some chipsets have a Shared Memory Pool (SMP), while others
+ * have dedicated latency buffering per source pipe instead;
+ * this section initializes the SMP:
+ */
+ if (mdp5_kms->caps & MDP_CAP_SMP) {
+ mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
+ if (IS_ERR(mdp5_kms->smp)) {
+ ret = PTR_ERR(mdp5_kms->smp);
+ mdp5_kms->smp = NULL;
+ goto fail;
+ }
}
mdp5_kms->ctlm = mdp5_ctlm_init(dev, mdp5_kms->mmio, mdp5_kms->cfg);
@@ -586,6 +599,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
dev_err(dev->dev, "failed to init iommu: %d\n", ret);
+ iommu_domain_free(config->platform.iommu);
goto fail;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 0bb62423586e..84f65d415598 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -32,6 +32,8 @@ struct mdp5_kms {
struct drm_device *dev;
struct mdp5_cfg_handler *cfg;
+ uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */
+
/* mapper-id used to request GEM buffer mapped for scanout: */
int id;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 07fb62fea6dc..81cd49045ffc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -250,22 +250,28 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
};
static int mdp5_plane_prepare_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct mdp5_kms *mdp5_kms = get_kms(plane);
+ struct drm_framebuffer *fb = new_state->fb;
+
+ if (!new_state->fb)
+ return 0;
DBG("%s: prepare: FB[%u]", mdp5_plane->name, fb->base.id);
return msm_framebuffer_prepare(fb, mdp5_kms->id);
}
static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *old_state)
{
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct mdp5_kms *mdp5_kms = get_kms(plane);
+ struct drm_framebuffer *fb = old_state->fb;
+
+ if (!fb)
+ return;
DBG("%s: cleanup: FB[%u]", mdp5_plane->name, fb->base.id);
msm_framebuffer_cleanup(fb, mdp5_kms->id);
@@ -494,7 +500,7 @@ static int calc_phase_step(uint32_t src, uint32_t dst, uint32_t *out_phase)
static int calc_scalex_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
- uint32_t phasex_steps[2])
+ uint32_t phasex_steps[COMP_MAX])
{
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
@@ -510,15 +516,16 @@ static int calc_scalex_steps(struct drm_plane *plane,
hsub = drm_format_horz_chroma_subsampling(pixel_format);
- phasex_steps[0] = phasex_step;
- phasex_steps[1] = phasex_step / hsub;
+ phasex_steps[COMP_0] = phasex_step;
+ phasex_steps[COMP_3] = phasex_step;
+ phasex_steps[COMP_1_2] = phasex_step / hsub;
return 0;
}
static int calc_scaley_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
- uint32_t phasey_steps[2])
+ uint32_t phasey_steps[COMP_MAX])
{
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
@@ -534,46 +541,127 @@ static int calc_scaley_steps(struct drm_plane *plane,
vsub = drm_format_vert_chroma_subsampling(pixel_format);
- phasey_steps[0] = phasey_step;
- phasey_steps[1] = phasey_step / vsub;
+ phasey_steps[COMP_0] = phasey_step;
+ phasey_steps[COMP_3] = phasey_step;
+ phasey_steps[COMP_1_2] = phasey_step / vsub;
return 0;
}
-static uint32_t get_scale_config(enum mdp_chroma_samp_type chroma_sample,
- uint32_t src, uint32_t dest, bool hor)
+static uint32_t get_scale_config(const struct mdp_format *format,
+ uint32_t src, uint32_t dst, bool horz)
{
- uint32_t y_filter = (src <= dest) ? SCALE_FILTER_CA : SCALE_FILTER_PCMN;
- uint32_t y_a_filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
- uint32_t uv_filter = ((src / 2) <= dest) ? /* 2x upsample */
- SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
- uint32_t value = 0;
-
- if (chroma_sample == CHROMA_420 || chroma_sample == CHROMA_H2V1) {
- if (hor)
- value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter);
- else
- value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter);
- } else if (src != dest) {
- if (hor)
- value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter);
- else
- value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter);
+ bool scaling = format->is_yuv ? true : (src != dst);
+ uint32_t sub, pix_fmt = format->base.pixel_format;
+ uint32_t ya_filter, uv_filter;
+ bool yuv = format->is_yuv;
+
+ if (!scaling)
+ return 0;
+
+ if (yuv) {
+ sub = horz ? drm_format_horz_chroma_subsampling(pix_fmt) :
+ drm_format_vert_chroma_subsampling(pix_fmt);
+ uv_filter = ((src / sub) <= dst) ?
+ SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
}
+ ya_filter = (src <= dst) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
- return value;
+ if (horz)
+ return MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(ya_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(ya_filter) |
+ COND(yuv, MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter));
+ else
+ return MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(ya_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(ya_filter) |
+ COND(yuv, MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter));
}
+static void calc_pixel_ext(const struct mdp_format *format,
+ uint32_t src, uint32_t dst, uint32_t phase_step[2],
+ int pix_ext_edge1[COMP_MAX], int pix_ext_edge2[COMP_MAX],
+ bool horz)
+{
+ bool scaling = format->is_yuv ? true : (src != dst);
+ int i;
+
+ /*
+ * Note:
+ * We assume here that:
+ * 1. PCMN filter is used for downscale
+ * 2. bilinear filter is used for upscale
+ * 3. we are in a single pipe configuration
+ */
+
+ for (i = 0; i < COMP_MAX; i++) {
+ pix_ext_edge1[i] = 0;
+ pix_ext_edge2[i] = scaling ? 1 : 0;
+ }
+}
+
+static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
+ const struct mdp_format *format,
+ uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],
+ uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])
+{
+ uint32_t pix_fmt = format->base.pixel_format;
+ uint32_t lr, tb, req;
+ int i;
+
+ for (i = 0; i < COMP_MAX; i++) {
+ uint32_t roi_w = src_w;
+ uint32_t roi_h = src_h;
+
+ if (format->is_yuv && i == COMP_1_2) {
+ roi_w /= drm_format_horz_chroma_subsampling(pix_fmt);
+ roi_h /= drm_format_vert_chroma_subsampling(pix_fmt);
+ }
+
+ lr = (pe_left[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT(pe_left[i]) :
+ MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF(pe_left[i]);
+
+ lr |= (pe_right[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT(pe_right[i]) :
+ MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF(pe_right[i]);
+
+ tb = (pe_top[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT(pe_top[i]) :
+ MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF(pe_top[i]);
+
+ tb |= (pe_bottom[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT(pe_bottom[i]) :
+ MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF(pe_bottom[i]);
+
+ req = MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT(roi_w +
+ pe_left[i] + pe_right[i]);
+
+ req |= MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM(roi_h +
+ pe_top[i] + pe_bottom[i]);
+
+ mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_LR(pipe, i), lr);
+ mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_TB(pipe, i), tb);
+ mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS(pipe, i), req);
+
+ DBG("comp-%d (L/R): rpt=%d/%d, ovf=%d/%d, req=%d", i,
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT),
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT),
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF),
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF),
+ FIELD(req, MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT));
+
+ DBG("comp-%d (T/B): rpt=%d/%d, ovf=%d/%d, req=%d", i,
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT),
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT),
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF),
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF),
+ FIELD(req, MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM));
+ }
+}
+
+
static int mdp5_plane_mode_set(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
@@ -587,8 +675,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
enum mdp5_pipe pipe = mdp5_plane->pipe;
const struct mdp_format *format;
uint32_t nplanes, config = 0;
- /* below array -> index 0: comp 0/3 ; index 1: comp 1/2 */
- uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,};
+ uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
+ bool pe = mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT;
+ int pe_left[COMP_MAX], pe_right[COMP_MAX];
+ int pe_top[COMP_MAX], pe_bottom[COMP_MAX];
uint32_t hdecm = 0, vdecm = 0;
uint32_t pix_format;
bool vflip, hflip;
@@ -615,10 +705,12 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
/* Request some memory from the SMP: */
- ret = mdp5_smp_request(mdp5_kms->smp,
- mdp5_plane->pipe, format, src_w, false);
- if (ret)
- return ret;
+ if (mdp5_kms->smp) {
+ ret = mdp5_smp_request(mdp5_kms->smp,
+ mdp5_plane->pipe, format, src_w, false);
+ if (ret)
+ return ret;
+ }
/*
* Currently we update the hw for allocations/requests immediately,
@@ -626,7 +718,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
* would move into atomic->check_plane_state(), while updating the
* hw would remain here:
*/
- mdp5_smp_configure(mdp5_kms->smp, pipe);
+ if (mdp5_kms->smp)
+ mdp5_smp_configure(mdp5_kms->smp, pipe);
ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, phasex_step);
if (ret)
@@ -636,11 +729,18 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
if (ret)
return ret;
+ if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
+ calc_pixel_ext(format, src_w, crtc_w, phasex_step,
+ pe_left, pe_right, true);
+ calc_pixel_ext(format, src_h, crtc_h, phasey_step,
+ pe_top, pe_bottom, false);
+ }
+
/* TODO calc hdecm, vdecm */
/* SCALE is used to both scale and up-sample chroma components */
- config |= get_scale_config(format->chroma_sample, src_w, crtc_w, true);
- config |= get_scale_config(format->chroma_sample, src_h, crtc_h, false);
+ config |= get_scale_config(format, src_w, crtc_w, true);
+ config |= get_scale_config(format, src_h, crtc_h, false);
DBG("scale config = %x", config);
hflip = !!(pstate->rotation & BIT(DRM_REFLECT_X));
@@ -689,20 +789,26 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe),
(hflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_LR : 0) |
(vflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_UD : 0) |
+ COND(pe, MDP5_PIPE_SRC_OP_MODE_SW_PIX_EXT_OVERRIDE) |
MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS));
/* not using secure mode: */
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
+ if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT)
+ mdp5_write_pixel_ext(mdp5_kms, pipe, format,
+ src_w, pe_left, pe_right,
+ src_h, pe_top, pe_bottom);
+
if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
- phasex_step[0]);
+ phasex_step[COMP_0]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
- phasey_step[0]);
+ phasey_step[COMP_0]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
- phasex_step[1]);
+ phasex_step[COMP_1_2]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
- phasey_step[1]);
+ phasey_step[COMP_1_2]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
MDP5_PIPE_DECIMATION_VERT(vdecm) |
MDP5_PIPE_DECIMATION_HORZ(hdecm));
@@ -732,7 +838,8 @@ void mdp5_plane_complete_flip(struct drm_plane *plane)
DBG("%s: complete flip", mdp5_plane->name);
- mdp5_smp_commit(mdp5_kms->smp, pipe);
+ if (mdp5_kms->smp)
+ mdp5_smp_commit(mdp5_kms->smp, pipe);
to_mdp5_plane_state(plane->state)->pending = false;
}
@@ -758,7 +865,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
enum mdp5_pipe pipe = mdp5_plane->pipe;
- if (!plane_enabled(plane->state)) {
+ if (!plane_enabled(plane->state) && mdp5_kms->smp) {
DBG("%s: free SMP", mdp5_plane->name);
mdp5_smp_release(mdp5_kms->smp, pipe);
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
index 563cca972dcb..6f425c25d9fe 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
@@ -90,7 +90,7 @@
struct mdp5_smp {
struct drm_device *dev;
- const struct mdp5_smp_block *cfg;
+ uint8_t reserved[MAX_CLIENTS]; /* fixed MMBs allocation per client */
int blk_cnt;
int blk_size;
@@ -141,10 +141,10 @@ static int smp_request_block(struct mdp5_smp *smp,
struct mdp5_kms *mdp5_kms = get_kms(smp);
struct mdp5_client_smp_state *ps = &smp->client_state[cid];
int i, ret, avail, cur_nblks, cnt = smp->blk_cnt;
- int reserved;
+ uint8_t reserved;
unsigned long flags;
- reserved = smp->cfg->reserved[cid];
+ reserved = smp->reserved[cid];
spin_lock_irqsave(&smp->state_lock, flags);
@@ -405,12 +405,12 @@ struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_blo
}
smp->dev = dev;
- smp->cfg = cfg;
smp->blk_cnt = cfg->mmb_count;
smp->blk_size = cfg->mmb_size;
/* statically tied MMBs cannot be re-allocated: */
bitmap_copy(smp->state, cfg->reserved_state, smp->blk_cnt);
+ memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
spin_lock_init(&smp->state_lock);
return smp;
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index 4f792c4e40f4..0aec1ac1f6d0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -78,6 +78,13 @@ enum mdp_alpha_type {
BG_PIXEL = 3,
};
+enum mdp_component_type {
+ COMP_0 = 0,
+ COMP_1_2 = 1,
+ COMP_3 = 2,
+ COMP_MAX = 3,
+};
+
enum mdp_bpc {
BPC1 = 0,
BPC5 = 1,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 46a94e7d50e2..303130320748 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -100,12 +100,18 @@ struct mdp_format {
uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
+/* MDP capabilities */
+#define MDP_CAP_SMP BIT(0) /* Shared Memory Pool */
+#define MDP_CAP_DSC BIT(1) /* VESA Display Stream Compression */
+#define MDP_CAP_CDM BIT(2) /* Chroma Down Module (HDMI 2.0 YUV) */
+
/* MDP pipe capabilities */
#define MDP_PIPE_CAP_HFLIP BIT(0)
#define MDP_PIPE_CAP_VFLIP BIT(1)
#define MDP_PIPE_CAP_SCALE BIT(2)
#define MDP_PIPE_CAP_CSC BIT(3)
#define MDP_PIPE_CAP_DECIMATION BIT(4)
+#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5)
static inline bool pipe_supports_yuv(uint32_t pipe_caps)
{
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 1ceb4f22dd89..7eb253bc24df 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -125,7 +125,7 @@ static void complete_commit(struct msm_commit *c)
drm_atomic_helper_commit_modeset_disables(dev, state);
- drm_atomic_helper_commit_planes(dev, state);
+ drm_atomic_helper_commit_planes(dev, state, false);
drm_atomic_helper_commit_modeset_enables(dev, state);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 0339c5d82d37..b88ce514eb8e 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -21,11 +21,9 @@
static void msm_fb_output_poll_changed(struct drm_device *dev)
{
-#ifdef CONFIG_DRM_MSM_FBDEV
struct msm_drm_private *priv = dev->dev_private;
if (priv->fbdev)
drm_fb_helper_hotplug_event(priv->fbdev);
-#endif
}
static const struct drm_mode_config_funcs mode_config_funcs = {
@@ -56,7 +54,7 @@ module_param(reglog, bool, 0600);
#define reglog 0
#endif
-#ifdef CONFIG_DRM_MSM_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
static bool fbdev = true;
MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer");
module_param(fbdev, bool, 0600);
@@ -423,7 +421,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
drm_mode_config_reset(dev);
-#ifdef CONFIG_DRM_MSM_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
if (fbdev)
priv->fbdev = msm_fbdev_init(dev);
#endif
@@ -491,11 +489,9 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
static void msm_lastclose(struct drm_device *dev)
{
-#ifdef CONFIG_DRM_MSM_FBDEV
struct msm_drm_private *priv = dev->dev_private;
if (priv->fbdev)
drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
-#endif
}
static irqreturn_t msm_irq(int irq, void *arg)
@@ -531,24 +527,24 @@ static void msm_irq_uninstall(struct drm_device *dev)
kms->funcs->irq_uninstall(kms);
}
-static int msm_enable_vblank(struct drm_device *dev, int crtc_id)
+static int msm_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
if (!kms)
return -ENXIO;
- DBG("dev=%p, crtc=%d", dev, crtc_id);
- return vblank_ctrl_queue_work(priv, crtc_id, true);
+ DBG("dev=%p, crtc=%u", dev, pipe);
+ return vblank_ctrl_queue_work(priv, pipe, true);
}
-static void msm_disable_vblank(struct drm_device *dev, int crtc_id)
+static void msm_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
if (!kms)
return;
- DBG("dev=%p, crtc=%d", dev, crtc_id);
- vblank_ctrl_queue_work(priv, crtc_id, false);
+ DBG("dev=%p, crtc=%u", dev, pipe);
+ vblank_ctrl_queue_work(priv, pipe, false);
}
/*
@@ -932,13 +928,13 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
}
static const struct drm_ioctl_desc msm_ioctls[] = {
- DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW),
};
static const struct vm_operations_struct vm_ops = {
@@ -978,7 +974,7 @@ static struct drm_driver msm_driver = {
.irq_preinstall = msm_irq_preinstall,
.irq_postinstall = msm_irq_postinstall,
.irq_uninstall = msm_irq_uninstall,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = msm_enable_vblank,
.disable_vblank = msm_disable_vblank,
.gem_free_object = msm_gem_free_object,
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index f97a1964ef39..3f6ec077b51d 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -68,12 +68,7 @@ static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
if (drm_device_is_unplugged(dev))
return -ENODEV;
- mutex_lock(&dev->struct_mutex);
-
ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma);
-
- mutex_unlock(&dev->struct_mutex);
-
if (ret) {
pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
return ret;
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 831461bc98a5..121975b07cd4 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -45,9 +45,7 @@ int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
int ret;
- mutex_lock(&obj->dev->struct_mutex);
ret = drm_gem_mmap_obj(obj, obj->size, vma);
- mutex_unlock(&obj->dev->struct_mutex);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 8f70d9248ac5..6b02ada6579a 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -651,6 +651,14 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
if (iommu) {
dev_info(drm->dev, "%s: using IOMMU\n", name);
gpu->mmu = msm_iommu_new(&pdev->dev, iommu);
+ if (IS_ERR(gpu->mmu)) {
+ ret = PTR_ERR(gpu->mmu);
+ dev_err(drm->dev, "failed to init iommu: %d\n", ret);
+ gpu->mmu = NULL;
+ iommu_domain_free(iommu);
+ goto fail;
+ }
+
} else {
dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
index 08c6f5e50610..903c473d266f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
@@ -32,7 +32,7 @@
#include "hw.h"
#include "tvnv17.h"
-char *nv17_tv_norm_names[NUM_TV_NORMS] = {
+const char * const nv17_tv_norm_names[NUM_TV_NORMS] = {
[TV_NORM_PAL] = "PAL",
[TV_NORM_PAL_M] = "PAL-M",
[TV_NORM_PAL_N] = "PAL-N",
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
index 459910b6bb32..1b07521cde0d 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
@@ -85,7 +85,7 @@ struct nv17_tv_encoder {
#define to_tv_enc(x) container_of(nouveau_encoder(x), \
struct nv17_tv_encoder, base)
-extern char *nv17_tv_norm_names[NUM_TV_NORMS];
+extern const char * const nv17_tv_norm_names[NUM_TV_NORMS];
extern struct nv17_tv_norm_params {
enum {
diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h
index 3accc99d8e0b..9fcab67c8557 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/os.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/os.h
@@ -27,6 +27,7 @@
#include <linux/agp_backend.h>
#include <linux/reset.h>
#include <linux/iommu.h>
+#include <linux/of_device.h>
#include <asm/unaligned.h>
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
index 5aa2480da25f..16641cec18a2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
@@ -4,6 +4,7 @@
#include <core/mm.h>
struct nvkm_device_tegra {
+ const struct nvkm_device_tegra_func *func;
struct nvkm_device device;
struct platform_device *pdev;
int irq;
@@ -28,7 +29,17 @@ struct nvkm_device_tegra {
int gpu_speedo;
};
-int nvkm_device_tegra_new(struct platform_device *,
+struct nvkm_device_tegra_func {
+ /*
+ * If an IOMMU is used, indicates which address bit will trigger a
+ * IOMMU translation when set (when this bit is not set, IOMMU is
+ * bypassed). A value of 0 means an IOMMU is never used.
+ */
+ u8 iommu_bit;
+};
+
+int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *,
+ struct platform_device *,
const char *cfg, const char *dbg,
bool detect, bool mmio, u64 subdev_mask,
struct nvkm_device **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
index 33be260ddd38..a47d46dda704 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
@@ -15,6 +15,7 @@ enum dcb_gpio_func_name {
DCB_GPIO_VID5 = 0x74,
DCB_GPIO_VID6 = 0x75,
DCB_GPIO_VID7 = 0x76,
+ DCB_GPIO_VID_PWM = 0x81,
};
#define DCB_GPIO_LOG_DIR 0x02
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h
index d606875c125a..3a643df6de04 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h
@@ -4,8 +4,6 @@ struct nvbios_pmuT {
};
u32 nvbios_pmuTe(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u32 nvbios_pmuTp(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
- struct nvbios_pmuT *);
struct nvbios_pmuE {
u8 type;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
index 3a9abd38aca8..dca6c060a24f 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
@@ -39,6 +39,7 @@ struct nvbios_ramcfg {
unsigned ramcfg_timing;
unsigned ramcfg_DLLoff;
unsigned ramcfg_RON;
+ unsigned ramcfg_FBVDDQ;
union {
struct {
unsigned ramcfg_00_03_01:1;
@@ -78,7 +79,6 @@ struct nvbios_ramcfg {
unsigned ramcfg_11_01_04:1;
unsigned ramcfg_11_01_08:1;
unsigned ramcfg_11_01_10:1;
- unsigned ramcfg_11_01_20:1;
unsigned ramcfg_11_01_40:1;
unsigned ramcfg_11_01_80:1;
unsigned ramcfg_11_02_03:2;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
index eb2de4b85bbd..b0df610cec2b 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
@@ -1,11 +1,24 @@
#ifndef __NVBIOS_VOLT_H__
#define __NVBIOS_VOLT_H__
+
+enum nvbios_volt_type {
+ NVBIOS_VOLT_GPIO = 0,
+ NVBIOS_VOLT_PWM,
+};
+
struct nvbios_volt {
- u8 vidmask;
+ enum nvbios_volt_type type;
u32 min;
u32 max;
u32 base;
+
+ /* GPIO mode */
+ u8 vidmask;
s16 step;
+
+ /* PWM mode */
+ u32 pwm_freq;
+ u32 pwm_range;
};
u16 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
index 6a04d9c07944..33a057c334f2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
@@ -14,6 +14,7 @@ int nvkm_hwsq_fini(struct nvkm_hwsq **, bool exec);
void nvkm_hwsq_wr32(struct nvkm_hwsq *, u32 addr, u32 data);
void nvkm_hwsq_setf(struct nvkm_hwsq *, u8 flag, int data);
void nvkm_hwsq_wait(struct nvkm_hwsq *, u8 flag, u8 data);
+void nvkm_hwsq_wait_vblank(struct nvkm_hwsq *);
void nvkm_hwsq_nsec(struct nvkm_hwsq *, u32 nsec);
int nv04_bus_new(struct nvkm_device *, int, struct nvkm_bus **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
index 9d512cd5a0a7..c4dcd2680fe1 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
@@ -3,6 +3,7 @@
#include <core/subdev.h>
int gf100_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
+int gf117_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
int gk104_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
int gk20a_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
index c773b5e958b4..3d4dbbf9aab3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
@@ -30,7 +30,11 @@ void nvkm_ltc_tags_clear(struct nvkm_ltc *, u32 first, u32 count);
int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]);
int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32);
+void nvkm_ltc_invalidate(struct nvkm_ltc *);
+void nvkm_ltc_flush(struct nvkm_ltc *);
+
int gf100_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
int gk104_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
+int gk20a_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
int gm107_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
index 5b3c054f3b55..fee0a97c44c5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
@@ -24,11 +24,14 @@ struct nvkm_pci {
u32 nvkm_pci_rd32(struct nvkm_pci *, u16 addr);
void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data);
void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data);
+u32 nvkm_pci_mask(struct nvkm_pci *, u16 addr, u32 mask, u32 value);
void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow);
int nv04_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
int nv40_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
+int nv46_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
int nv4c_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
-int nv50_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
+int g84_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
+int g94_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
int gf100_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
index 62ed0880b0e1..82d3e28918fd 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
@@ -59,6 +59,16 @@ void nvkm_timer_alarm_cancel(struct nvkm_timer *, struct nvkm_alarm *);
#define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond)
#define nvkm_msec(d,m,cond...) nvkm_usec((d), (m) * 1000, ##cond)
+#define nvkm_wait_nsec(d,n,addr,mask,data) \
+ nvkm_nsec(d, n, \
+ if ((nvkm_rd32(d, (addr)) & (mask)) == (data)) \
+ break; \
+ )
+#define nvkm_wait_usec(d,u,addr,mask,data) \
+ nvkm_wait_nsec((d), (u) * 1000, (addr), (mask), (data))
+#define nvkm_wait_msec(d,m,addr,mask,data) \
+ nvkm_wait_usec((d), (m) * 1000, (addr), (mask), (data))
+
int nv04_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
int nv40_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
int nv41_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
index 5c8a3f1196de..b458d046dba7 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
@@ -18,5 +18,6 @@ int nvkm_volt_get(struct nvkm_volt *);
int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition);
int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index d336c2247d6a..7f50cf5f929e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -25,6 +25,7 @@
#include <nvif/driver.h>
#include <nvif/ioctl.h>
#include <nvif/class.h>
+#include <nvif/unpack.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
@@ -32,11 +33,10 @@
#include "nouveau_chan.h"
#include "nouveau_abi16.h"
-struct nouveau_abi16 *
-nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
+static struct nouveau_abi16 *
+nouveau_abi16(struct drm_file *file_priv)
{
struct nouveau_cli *cli = nouveau_cli(file_priv);
- mutex_lock(&cli->mutex);
if (!cli->abi16) {
struct nouveau_abi16 *abi16;
cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL);
@@ -51,8 +51,7 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
* device (ie. the one that belongs to the fd it
* opened)
*/
- if (nvif_device_init(&cli->base.object,
- NOUVEAU_ABI16_DEVICE, NV_DEVICE,
+ if (nvif_device_init(&cli->base.object, 0, NV_DEVICE,
&args, sizeof(args),
&abi16->device) == 0)
return cli->abi16;
@@ -60,12 +59,21 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
kfree(cli->abi16);
cli->abi16 = NULL;
}
-
- mutex_unlock(&cli->mutex);
}
return cli->abi16;
}
+struct nouveau_abi16 *
+nouveau_abi16_get(struct drm_file *file_priv)
+{
+ struct nouveau_cli *cli = nouveau_cli(file_priv);
+ mutex_lock(&cli->mutex);
+ if (nouveau_abi16(file_priv))
+ return cli->abi16;
+ mutex_unlock(&cli->mutex);
+ return NULL;
+}
+
int
nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
{
@@ -133,7 +141,6 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
/* destroy channel object, all children will be killed too */
if (chan->chan) {
- abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff));
nouveau_channel_idle(chan->chan);
nouveau_channel_del(&chan->chan);
}
@@ -238,7 +245,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
struct drm_nouveau_channel_alloc *init = data;
struct nouveau_cli *cli = nouveau_cli(file_priv);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nvif_device *device;
int ret;
@@ -268,26 +275,21 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
return nouveau_abi16_put(abi16, -EINVAL);
/* allocate "abi16 channel" data and make up a handle for it */
- init->channel = __ffs64(~abi16->handles);
- if (~abi16->handles == 0)
- return nouveau_abi16_put(abi16, -ENOSPC);
-
chan = kzalloc(sizeof(*chan), GFP_KERNEL);
if (!chan)
return nouveau_abi16_put(abi16, -ENOMEM);
INIT_LIST_HEAD(&chan->notifiers);
list_add(&chan->head, &abi16->channels);
- abi16->handles |= (1ULL << init->channel);
/* create channel object and initialise dma and fence management */
- ret = nouveau_channel_new(drm, device,
- NOUVEAU_ABI16_CHAN(init->channel),
- init->fb_ctxdma_handle,
+ ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
init->tt_ctxdma_handle, &chan->chan);
if (ret)
goto done;
+ init->channel = chan->chan->chid;
+
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
NOUVEAU_GEM_DOMAIN_GART;
@@ -338,7 +340,7 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
struct nouveau_abi16_chan *chan;
list_for_each_entry(chan, &abi16->channels, head) {
- if (chan->chan->user.handle == NOUVEAU_ABI16_CHAN(channel))
+ if (chan->chan->chid == channel)
return chan;
}
@@ -346,10 +348,48 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
}
int
+nouveau_abi16_usif(struct drm_file *file_priv, void *data, u32 size)
+{
+ union {
+ struct nvif_ioctl_v0 v0;
+ } *args = data;
+ struct nouveau_abi16_chan *chan;
+ struct nouveau_abi16 *abi16;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ switch (args->v0.type) {
+ case NVIF_IOCTL_V0_NEW:
+ case NVIF_IOCTL_V0_MTHD:
+ case NVIF_IOCTL_V0_SCLASS:
+ break;
+ default:
+ return -EACCES;
+ }
+ } else
+ return ret;
+
+ if (!(abi16 = nouveau_abi16(file_priv)))
+ return -ENOMEM;
+
+ if (args->v0.token != ~0ULL) {
+ if (!(chan = nouveau_abi16_chan(abi16, args->v0.token)))
+ return -EINVAL;
+ args->v0.object = nvif_handle(&chan->chan->user);
+ args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+ return 0;
+ }
+
+ args->v0.object = nvif_handle(&abi16->device.object);
+ args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+ return 0;
+}
+
+int
nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_channel_free *req = data;
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
if (unlikely(!abi16))
@@ -366,7 +406,7 @@ int
nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_grobj_alloc *init = data;
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
struct nvif_client *client;
@@ -459,7 +499,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_notifierobj_alloc *info = data;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
struct nvif_device *device = &abi16->device;
@@ -531,7 +571,7 @@ int
nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_gpuobj_free *fini = data;
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
int ret = -ENOENT;
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h
index 6584557afa40..841cc556fad8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.h
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h
@@ -33,11 +33,11 @@ struct nouveau_abi16 {
u64 handles;
};
-struct nouveau_drm;
-struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *, struct drm_device *);
+struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *);
int nouveau_abi16_put(struct nouveau_abi16 *, int);
void nouveau_abi16_fini(struct nouveau_abi16 *);
s32 nouveau_abi16_swclass(struct nouveau_drm *);
+int nouveau_abi16_usif(struct drm_file *, void *data, u32 size);
#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1)
#define NOUVEAU_GEM_DOMAIN_GART (1 << 2)
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index df2d9818aba3..8b8332e46f24 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -206,7 +206,7 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev)
return VGA_SWITCHEROO_DIS;
}
-static struct vga_switcheroo_handler nouveau_dsm_handler = {
+static const struct vga_switcheroo_handler nouveau_dsm_handler = {
.switchto = nouveau_dsm_switchto,
.power_state = nouveau_dsm_power_state,
.get_client_id = nouveau_dsm_get_client_id,
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 15057b39491c..78f520d05de9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -574,7 +574,7 @@ static struct ttm_tt *
nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
uint32_t page_flags, struct page *dummy_read)
{
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
struct nouveau_drm *drm = nouveau_bdev(bdev);
if (drm->agp.bridge) {
@@ -1366,7 +1366,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
/* System memory */
return 0;
case TTM_PL_TT:
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (drm->agp.bridge) {
mem->bus.offset = mem->start << PAGE_SHIFT;
mem->bus.base = drm->agp.base;
@@ -1496,7 +1496,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
ttm->caching_state == tt_uncached)
return ttm_dma_populate(ttm_dma, dev->dev);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (drm->agp.bridge) {
return ttm_agp_tt_populate(ttm);
}
@@ -1563,7 +1563,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
return;
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (drm->agp.bridge) {
ttm_agp_tt_unpopulate(ttm);
return;
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index ff5e59db49db..1860f389f21f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -55,10 +55,8 @@ nouveau_channel_idle(struct nouveau_channel *chan)
}
if (ret) {
- NV_PRINTK(err, cli, "failed to idle channel "
- "0x%08x [%s]\n",
- chan->user.handle,
- nvxx_client(&cli->base)->name);
+ NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n",
+ chan->chid, nvxx_client(&cli->base)->name);
return ret;
}
}
@@ -89,7 +87,7 @@ nouveau_channel_del(struct nouveau_channel **pchan)
static int
nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
- u32 handle, u32 size, struct nouveau_channel **pchan)
+ u32 size, struct nouveau_channel **pchan)
{
struct nouveau_cli *cli = (void *)device->object.client;
struct nvkm_mmu *mmu = nvxx_mmu(device);
@@ -174,8 +172,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
}
}
- ret = nvif_object_init(&device->object, NVDRM_PUSH |
- (handle & 0xffff), NV_DMA_FROM_MEMORY,
+ ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY,
&args, sizeof(args), &chan->push.ctxdma);
if (ret) {
nouveau_channel_del(pchan);
@@ -187,7 +184,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
- u32 handle, u32 engine, struct nouveau_channel **pchan)
+ u32 engine, struct nouveau_channel **pchan)
{
static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A,
KEPLER_CHANNEL_GPFIFO_A,
@@ -206,7 +203,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
int ret;
/* allocate dma push buffer */
- ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan);
+ ret = nouveau_channel_prep(drm, device, 0x12000, &chan);
*pchan = chan;
if (ret)
return ret;
@@ -236,7 +233,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
size = sizeof(args.nv50);
}
- ret = nvif_object_init(&device->object, handle, *oclass++,
+ ret = nvif_object_init(&device->object, 0, *oclass++,
&args, size, &chan->user);
if (ret == 0) {
if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A)
@@ -256,7 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
static int
nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
- u32 handle, struct nouveau_channel **pchan)
+ struct nouveau_channel **pchan)
{
static const u16 oclasses[] = { NV40_CHANNEL_DMA,
NV17_CHANNEL_DMA,
@@ -269,7 +266,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
int ret;
/* allocate dma push buffer */
- ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan);
+ ret = nouveau_channel_prep(drm, device, 0x10000, &chan);
*pchan = chan;
if (ret)
return ret;
@@ -280,7 +277,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
args.offset = chan->push.vma.offset;
do {
- ret = nvif_object_init(&device->object, handle, *oclass++,
+ ret = nvif_object_init(&device->object, 0, *oclass++,
&args, sizeof(args), &chan->user);
if (ret == 0) {
chan->chid = args.chid;
@@ -401,8 +398,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
int
nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
- u32 handle, u32 arg0, u32 arg1,
- struct nouveau_channel **pchan)
+ u32 arg0, u32 arg1, struct nouveau_channel **pchan)
{
struct nouveau_cli *cli = (void *)device->object.client;
bool super;
@@ -412,10 +408,10 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
super = cli->base.super;
cli->base.super = true;
- ret = nouveau_channel_ind(drm, device, handle, arg0, pchan);
+ ret = nouveau_channel_ind(drm, device, arg0, pchan);
if (ret) {
NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
- ret = nouveau_channel_dma(drm, device, handle, pchan);
+ ret = nouveau_channel_dma(drm, device, pchan);
if (ret) {
NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
goto done;
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h
index 2ed32414cb69..48062c94f36d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.h
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.h
@@ -42,8 +42,7 @@ struct nouveau_channel {
int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
- u32 handle, u32 arg0, u32 arg1,
- struct nouveau_channel **);
+ u32 arg0, u32 arg1, struct nouveau_channel **);
void nouveau_channel_del(struct nouveau_channel **);
int nouveau_channel_idle(struct nouveau_channel *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index cc6c228e11c8..db6bc6760545 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -51,12 +51,12 @@ nouveau_display_vblank_handler(struct nvif_notify *notify)
}
int
-nouveau_display_vblank_enable(struct drm_device *dev, int head)
+nouveau_display_vblank_enable(struct drm_device *dev, unsigned int pipe)
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- if (nv_crtc->index == head) {
+ if (nv_crtc->index == pipe) {
nvif_notify_get(&nv_crtc->vblank);
return 0;
}
@@ -65,12 +65,12 @@ nouveau_display_vblank_enable(struct drm_device *dev, int head)
}
void
-nouveau_display_vblank_disable(struct drm_device *dev, int head)
+nouveau_display_vblank_disable(struct drm_device *dev, unsigned int pipe)
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- if (nv_crtc->index == head) {
+ if (nv_crtc->index == pipe) {
nvif_notify_put(&nv_crtc->vblank);
return;
}
@@ -103,6 +103,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
.base.head = nouveau_crtc(crtc)->index,
};
struct nouveau_display *disp = nouveau_display(crtc->dev);
+ struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
int ret, retry = 1;
do {
@@ -116,7 +117,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
break;
}
- if (retry) ndelay(crtc->linedur_ns);
+ if (retry) ndelay(vblank->linedur_ns);
} while (retry--);
*hpos = args.scan.hline;
@@ -131,13 +132,15 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
}
int
-nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
- int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
+ unsigned int flags, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode)
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if (nouveau_crtc(crtc)->index == head) {
+ if (nouveau_crtc(crtc)->index == pipe) {
return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
stime, etime);
}
@@ -147,15 +150,15 @@ nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
}
int
-nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
- struct timeval *time, unsigned flags)
+nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe,
+ int *max_error, struct timeval *time, unsigned flags)
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if (nouveau_crtc(crtc)->index == head) {
+ if (nouveau_crtc(crtc)->index == pipe) {
return drm_calc_vbltimestamp_from_scanoutpos(dev,
- head, max_error, time, flags, crtc,
+ pipe, max_error, time, flags,
&crtc->hwmode);
}
}
@@ -469,9 +472,13 @@ nouveau_display_create(struct drm_device *dev)
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
- } else {
+ } else
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) {
dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192;
+ } else {
+ dev->mode_config.max_width = 16384;
+ dev->mode_config.max_height = 16384;
}
dev->mode_config.preferred_depth = 24;
@@ -502,9 +509,8 @@ nouveau_display_create(struct drm_device *dev)
int i;
for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
- ret = nvif_object_init(&drm->device.object,
- NVDRM_DISPLAY, oclass[i],
- NULL, 0, &disp->disp);
+ ret = nvif_object_init(&drm->device.object, 0,
+ oclass[i], NULL, 0, &disp->disp);
}
if (ret == 0) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index a6213e2425c5..856abe0f070d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -65,11 +65,12 @@ int nouveau_display_init(struct drm_device *dev);
void nouveau_display_fini(struct drm_device *dev);
int nouveau_display_suspend(struct drm_device *dev, bool runtime);
void nouveau_display_resume(struct drm_device *dev, bool runtime);
-int nouveau_display_vblank_enable(struct drm_device *, int);
-void nouveau_display_vblank_disable(struct drm_device *, int);
-int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int,
- int *, int *, ktime_t *, ktime_t *);
-int nouveau_display_vblstamp(struct drm_device *, int, int *,
+int nouveau_display_vblank_enable(struct drm_device *, unsigned int);
+void nouveau_display_vblank_disable(struct drm_device *, unsigned int);
+int nouveau_display_scanoutpos(struct drm_device *, unsigned int,
+ unsigned int, int *, int *, ktime_t *,
+ ktime_t *, const struct drm_display_mode *);
+int nouveau_display_vblstamp(struct drm_device *, unsigned int, int *,
struct timeval *, unsigned);
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index ccefb645fd55..1d3ee5179ab8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -208,7 +208,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
}
if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
- ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+ ret = nouveau_channel_new(drm, &drm->device,
KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
0, &drm->cechan);
@@ -221,7 +221,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
if (device->info.chipset >= 0xa3 &&
device->info.chipset != 0xaa &&
device->info.chipset != 0xac) {
- ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+ ret = nouveau_channel_new(drm, &drm->device,
NvDmaFB, NvDmaTT, &drm->cechan);
if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
@@ -233,8 +233,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
arg1 = NvDmaTT;
}
- ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1,
- &drm->channel);
+ ret = nouveau_channel_new(drm, &drm->device, arg0, arg1, &drm->channel);
if (ret) {
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
nouveau_accel_fini(drm);
@@ -403,8 +402,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
nouveau_get_hdmi_dev(drm);
- ret = nvif_device_init(&drm->client.base.object,
- NVDRM_DEVICE, NV_DEVICE,
+ ret = nvif_device_init(&drm->client.base.object, 0, NV_DEVICE,
&(struct nv_device_v0) {
.device = ~0,
}, sizeof(struct nv_device_v0),
@@ -862,18 +860,18 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
static const struct drm_ioctl_desc
nouveau_ioctls[] = {
- DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW),
};
long
@@ -934,7 +932,7 @@ driver_stub = {
.debugfs_cleanup = nouveau_debugfs_takedown,
#endif
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = nouveau_display_vblank_enable,
.disable_vblank = nouveau_display_vblank_disable,
.get_scanout_position = nouveau_display_scanoutpos,
@@ -1030,13 +1028,14 @@ nouveau_drm_pci_driver = {
};
struct drm_device *
-nouveau_platform_device_create(struct platform_device *pdev,
+nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
+ struct platform_device *pdev,
struct nvkm_device **pdevice)
{
struct drm_device *drm;
int err;
- err = nvkm_device_tegra_new(pdev, nouveau_config, nouveau_debug,
+ err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug,
true, true, ~0ULL, pdevice);
if (err)
goto err_free;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 3c902c24a8dd..3050042e6c6d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -10,7 +10,7 @@
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 3
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_PATCHLEVEL 1
/*
* 1.1.1:
@@ -33,6 +33,8 @@
* 1.3.0:
* - NVIF ABI modified, safe because only (current) users are test
* programs that get directly linked with NVKM.
+ * 1.3.1:
+ * - implemented limited ABI16/NVIF interop
*/
#include <nvif/client.h>
@@ -74,11 +76,6 @@ enum nouveau_drm_notify_route {
};
enum nouveau_drm_handle {
- NVDRM_CLIENT = 0xffffffff,
- NVDRM_DEVICE = 0xdddddddd,
- NVDRM_CONTROL = 0xdddddddc,
- NVDRM_DISPLAY = 0xd1500000,
- NVDRM_PUSH = 0xbbbb0000, /* |= client chid */
NVDRM_CHAN = 0xcccc0000, /* |= client chid */
NVDRM_NVSW = 0x55550000,
};
@@ -183,8 +180,11 @@ nouveau_drm(struct drm_device *dev)
int nouveau_pmops_suspend(struct device *);
int nouveau_pmops_resume(struct device *);
+#include <nvkm/core/tegra.h>
+
struct drm_device *
-nouveau_platform_device_create(struct platform_device *, struct nvkm_device **);
+nouveau_platform_device_create(const struct nvkm_device_tegra_func *,
+ struct platform_device *, struct nvkm_device **);
void nouveau_drm_device_remove(struct drm_device *dev);
#define NV_PRINTK(l,c,f,a...) do { \
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 2791701685dc..59f27e774acb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -178,8 +178,30 @@ nouveau_fbcon_sync(struct fb_info *info)
return 0;
}
+static int
+nouveau_fbcon_open(struct fb_info *info, int user)
+{
+ struct nouveau_fbdev *fbcon = info->par;
+ struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ int ret = pm_runtime_get_sync(drm->dev->dev);
+ if (ret < 0 && ret != -EACCES)
+ return ret;
+ return 0;
+}
+
+static int
+nouveau_fbcon_release(struct fb_info *info, int user)
+{
+ struct nouveau_fbdev *fbcon = info->par;
+ struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ pm_runtime_put(drm->dev->dev);
+ return 0;
+}
+
static struct fb_ops nouveau_fbcon_ops = {
.owner = THIS_MODULE,
+ .fb_open = nouveau_fbcon_open,
+ .fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = nouveau_fbcon_fillrect,
@@ -195,6 +217,8 @@ static struct fb_ops nouveau_fbcon_ops = {
static struct fb_ops nouveau_fbcon_sw_ops = {
.owner = THIS_MODULE,
+ .fb_open = nouveau_fbcon_open,
+ .fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 2c9981512d27..a0865c49ec83 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -84,8 +84,10 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
}
ret = pm_runtime_get_sync(dev);
- if (ret < 0 && ret != -EACCES)
+ if (ret < 0 && ret != -EACCES) {
+ kfree(vma);
goto out;
+ }
ret = nouveau_bo_vma_add(nvbo, cli->vm, vma);
if (ret)
@@ -227,11 +229,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct nvkm_vma *vma;
- if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+ if (is_power_of_2(nvbo->valid_domains))
+ rep->domain = nvbo->valid_domains;
+ else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
rep->domain = NOUVEAU_GEM_DOMAIN_GART;
else
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
-
rep->offset = nvbo->bo.offset;
if (cli->vm) {
vma = nouveau_bo_vma_find(nvbo, cli->vm);
@@ -665,7 +668,7 @@ int
nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_cli *cli = nouveau_cli(file_priv);
struct nouveau_abi16_chan *temp;
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -681,7 +684,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
return -ENOMEM;
list_for_each_entry(temp, &abi16->channels, head) {
- if (temp->chan->user.handle == (NVDRM_CHAN | req->channel)) {
+ if (temp->chan->chid == req->channel) {
chan = temp->chan;
break;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
index 3eb665453165..60e32c4e4e49 100644
--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -23,11 +23,14 @@
static int nouveau_platform_probe(struct platform_device *pdev)
{
+ const struct nvkm_device_tegra_func *func;
struct nvkm_device *device;
struct drm_device *drm;
int ret;
- drm = nouveau_platform_device_create(pdev, &device);
+ func = of_device_get_match_data(&pdev->dev);
+
+ drm = nouveau_platform_device_create(func, pdev, &device);
if (IS_ERR(drm))
return PTR_ERR(drm);
@@ -48,9 +51,19 @@ static int nouveau_platform_remove(struct platform_device *pdev)
}
#if IS_ENABLED(CONFIG_OF)
+static const struct nvkm_device_tegra_func gk20a_platform_data = {
+ .iommu_bit = 34,
+};
+
static const struct of_device_id nouveau_platform_match[] = {
- { .compatible = "nvidia,gk20a" },
- { .compatible = "nvidia,gm20b" },
+ {
+ .compatible = "nvidia,gk20a",
+ .data = &gk20a_platform_data,
+ },
+ {
+ .compatible = "nvidia,gm20b",
+ .data = &gk20a_platform_data,
+ },
{ }
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
index d12a5faee047..5dac3546c1b8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
@@ -188,9 +188,8 @@ nouveau_sysfs_init(struct drm_device *dev)
if (!sysfs)
return -ENOMEM;
- ret = nvif_object_init(&device->object, NVDRM_CONTROL,
- NVIF_IOCTL_NEW_V0_CONTROL, NULL, 0,
- &sysfs->ctrl);
+ ret = nvif_object_init(&device->object, 0, NVIF_IOCTL_NEW_V0_CONTROL,
+ NULL, 0, &sysfs->ctrl);
if (ret == 0)
device_create_file(nvxx_device(device)->dev, &dev_attr_pstate);
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 3f0fb55cb473..d2e7d209f651 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -29,6 +29,9 @@
#include "nouveau_gem.h"
#include "drm_legacy.h"
+
+#include <core/tegra.h>
+
static int
nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
{
@@ -338,7 +341,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
struct nvkm_device *device = nvxx_device(&drm->device);
struct nvkm_pci *pci = device->pci;
struct drm_device *dev = drm->dev;
- u32 bits;
+ u8 bits;
int ret;
if (pci && pci->agp.bridge) {
@@ -350,20 +353,31 @@ nouveau_ttm_init(struct nouveau_drm *drm)
bits = nvxx_mmu(&drm->device)->dma_bits;
if (nvxx_device(&drm->device)->func->pci) {
- if (drm->agp.bridge ||
- !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
+ if (drm->agp.bridge)
bits = 32;
+ } else if (device->func->tegra) {
+ struct nvkm_device_tegra *tegra = device->func->tegra(device);
- ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
- if (ret)
- return ret;
+ /*
+ * If the platform can use a IOMMU, then the addressable DMA
+ * space is constrained by the IOMMU bit
+ */
+ if (tegra->func->iommu_bit)
+ bits = min(bits, tegra->func->iommu_bit);
+
+ }
- ret = pci_set_consistent_dma_mask(dev->pdev,
- DMA_BIT_MASK(bits));
- if (ret)
- pci_set_consistent_dma_mask(dev->pdev,
- DMA_BIT_MASK(32));
+ ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits));
+ if (ret && bits != 32) {
+ bits = 32;
+ ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits));
}
+ if (ret)
+ return ret;
+
+ ret = dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(bits));
+ if (ret)
+ dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(32));
ret = nouveau_ttm_global_init(drm);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c
index cb1182d7e80e..89dc4ce63490 100644
--- a/drivers/gpu/drm/nouveau/nouveau_usif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -24,6 +24,7 @@
#include "nouveau_drm.h"
#include "nouveau_usif.h"
+#include "nouveau_abi16.h"
#include <nvif/notify.h>
#include <nvif/unpack.h>
@@ -316,11 +317,21 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
} else
goto done;
+ /* USIF slightly abuses some return-only ioctl members in order
+ * to provide interoperability with the older ABI16 objects
+ */
mutex_lock(&cli->mutex);
+ if (argv->v0.route) {
+ if (ret = -EINVAL, argv->v0.route == 0xff)
+ ret = nouveau_abi16_usif(filp, argv, argc);
+ if (ret) {
+ mutex_unlock(&cli->mutex);
+ goto done;
+ }
+ }
+
switch (argv->v0.type) {
case NVIF_IOCTL_V0_NEW:
- /* ... except if we're creating children */
- argv->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
ret = usif_object_new(filp, data, size, argv, argc);
break;
case NVIF_IOCTL_V0_NTFY_NEW:
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 4ae87aed4505..c053c50b346a 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -68,7 +68,6 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp,
const s32 *oclass, u8 head, void *data, u32 size,
struct nv50_chan *chan)
{
- const u32 handle = (oclass[0] << 16) | head;
struct nvif_sclass *sclass;
int ret, i, n;
@@ -81,7 +80,7 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp,
while (oclass[0]) {
for (i = 0; i < n; i++) {
if (sclass[i].oclass == oclass[0]) {
- ret = nvif_object_init(disp, handle, oclass[0],
+ ret = nvif_object_init(disp, 0, oclass[0],
data, size, &chan->user);
if (ret == 0)
nvif_object_map(&chan->user);
@@ -231,8 +230,8 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
if (!dmac->ptr)
return -ENOMEM;
- ret = nvif_object_init(&device->object, 0xd0000000,
- NV_DMA_FROM_MEMORY, &(struct nv_dma_v0) {
+ ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY,
+ &(struct nv_dma_v0) {
.target = NV_DMA_V0_TARGET_PCI_US,
.access = NV_DMA_V0_ACCESS_RD,
.start = dmac->handle + 0x0000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 94a906b8cb88..bbc9824af6e0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -637,7 +637,7 @@ nv46_chipset = {
.imem = nv40_instmem_new,
.mc = nv44_mc_new,
.mmu = nv44_mmu_new,
- .pci = nv4c_pci_new,
+ .pci = nv46_pci_new,
.therm = nv40_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -822,7 +822,7 @@ nv50_chipset = {
.mc = nv50_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv50_pci_new,
+ .pci = nv46_pci_new,
.therm = nv50_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -929,7 +929,7 @@ nv84_chipset = {
.mc = nv50_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv50_pci_new,
+ .pci = g84_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -961,7 +961,7 @@ nv86_chipset = {
.mc = nv50_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv50_pci_new,
+ .pci = g84_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -993,7 +993,7 @@ nv92_chipset = {
.mc = nv50_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv50_pci_new,
+ .pci = g84_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1025,7 +1025,7 @@ nv94_chipset = {
.mc = nv50_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1057,7 +1057,7 @@ nv96_chipset = {
.mc = nv50_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1089,7 +1089,7 @@ nv98_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1121,7 +1121,7 @@ nva0_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1153,7 +1153,7 @@ nva3_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gt215_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1187,7 +1187,7 @@ nva5_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gt215_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1220,7 +1220,7 @@ nva8_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gt215_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1253,7 +1253,7 @@ nvaa_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1285,7 +1285,7 @@ nvac_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = g84_therm_new,
.timer = nv41_timer_new,
.volt = nv40_volt_new,
@@ -1317,7 +1317,7 @@ nvaf_chipset = {
.mc = g98_mc_new,
.mmu = nv50_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gt215_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1388,7 +1388,7 @@ nvc1_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1423,7 +1423,7 @@ nvc3_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1566,7 +1566,7 @@ nvcf_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
@@ -1595,13 +1595,13 @@ nvd7_chipset = {
.fuse = gf100_fuse_new,
.gpio = gf119_gpio_new,
.i2c = gf117_i2c_new,
- .ibus = gf100_ibus_new,
+ .ibus = gf117_ibus_new,
.imem = nv50_instmem_new,
.ltc = gf100_ltc_new,
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
.ce[0] = gf100_ce_new,
@@ -1628,13 +1628,13 @@ nvd9_chipset = {
.fuse = gf100_fuse_new,
.gpio = gf119_gpio_new,
.i2c = gf119_i2c_new,
- .ibus = gf100_ibus_new,
+ .ibus = gf117_ibus_new,
.imem = nv50_instmem_new,
.ltc = gf100_ltc_new,
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gf119_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
@@ -1669,11 +1669,11 @@ nve4_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gk104_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1706,11 +1706,11 @@ nve6_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gk104_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1743,11 +1743,11 @@ nve7_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
- .pmu = gf119_pmu_new,
+ .pci = g94_pci_new,
+ .pmu = gk104_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1804,11 +1804,11 @@ nvf0_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gk110_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1840,11 +1840,11 @@ nvf1_chipset = {
.mc = gf100_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gk110_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1876,11 +1876,11 @@ nv106_chipset = {
.mc = gk20a_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gk208_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1912,11 +1912,11 @@ nv108_chipset = {
.mc = gk20a_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gk208_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[1] = gk104_ce_new,
.ce[2] = gk104_ce_new,
@@ -1948,10 +1948,11 @@ nv117_chipset = {
.mc = gk20a_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gm107_pmu_new,
.therm = gm107_therm_new,
.timer = gk20a_timer_new,
+ .volt = gk104_volt_new,
.ce[0] = gk104_ce_new,
.ce[2] = gk104_ce_new,
.disp = gm107_disp_new,
@@ -1978,9 +1979,10 @@ nv124_chipset = {
.mc = gk20a_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gm107_pmu_new,
.timer = gk20a_timer_new,
+ .volt = gk104_volt_new,
.ce[0] = gm204_ce_new,
.ce[1] = gm204_ce_new,
.ce[2] = gm204_ce_new,
@@ -2008,9 +2010,10 @@ nv126_chipset = {
.mc = gk20a_mc_new,
.mmu = gf100_mmu_new,
.mxm = nv50_mxm_new,
- .pci = nv40_pci_new,
+ .pci = g94_pci_new,
.pmu = gm107_pmu_new,
.timer = gk20a_timer_new,
+ .volt = gk104_volt_new,
.ce[0] = gm204_ce_new,
.ce[1] = gm204_ce_new,
.ce[2] = gm204_ce_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index e8eb14e438f4..e3c783d0e2ab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -259,6 +259,12 @@ nvkm_device_pci_10de_0df4[] = {
};
static const struct nvkm_device_pci_vendor
+nvkm_device_pci_10de_0fcd[] = {
+ { 0x17aa, 0x3801, NULL, { .War00C800_0 = true } }, /* Lenovo Y510P */
+ {}
+};
+
+static const struct nvkm_device_pci_vendor
nvkm_device_pci_10de_0fd2[] = {
{ 0x1028, 0x0595, "GeForce GT 640M LE" },
{ 0x1028, 0x05b2, "GeForce GT 640M LE" },
@@ -678,6 +684,7 @@ nvkm_device_pci_10de_1189[] = {
static const struct nvkm_device_pci_vendor
nvkm_device_pci_10de_1199[] = {
{ 0x1458, 0xd001, "GeForce GTX 760" },
+ { 0x1462, 0x1106, "GeForce GTX 780M", { .War00C800_0 = true } }, /* Medion Erazer X7827 */
{}
};
@@ -1349,7 +1356,7 @@ nvkm_device_pci_10de[] = {
{ 0x0fc6, "GeForce GTX 650" },
{ 0x0fc8, "GeForce GT 740" },
{ 0x0fc9, "GeForce GT 730" },
- { 0x0fcd, "GeForce GT 755M" },
+ { 0x0fcd, "GeForce GT 755M", nvkm_device_pci_10de_0fcd },
{ 0x0fce, "GeForce GT 640M LE" },
{ 0x0fd1, "GeForce GT 650M" },
{ 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index da57c8a60608..7f8a42721eb2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -85,6 +85,9 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
unsigned long pgsize_bitmap;
int ret;
+ if (!tdev->func->iommu_bit)
+ return;
+
mutex_init(&tdev->iommu.mutex);
if (iommu_present(&platform_bus_type)) {
@@ -114,7 +117,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
goto free_domain;
ret = nvkm_mm_init(&tdev->iommu.mm, 0,
- (1ULL << 40) >> tdev->iommu.pgshift, 1);
+ (1ULL << tdev->func->iommu_bit) >>
+ tdev->iommu.pgshift, 1);
if (ret)
goto detach_device;
}
@@ -237,7 +241,8 @@ nvkm_device_tegra_func = {
};
int
-nvkm_device_tegra_new(struct platform_device *pdev,
+nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
+ struct platform_device *pdev,
const char *cfg, const char *dbg,
bool detect, bool mmio, u64 subdev_mask,
struct nvkm_device **pdevice)
@@ -248,6 +253,7 @@ nvkm_device_tegra_new(struct platform_device *pdev,
if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
return -ENOMEM;
*pdevice = &tdev->device;
+ tdev->func = func;
tdev->pdev = pdev;
tdev->irq = -1;
@@ -285,7 +291,8 @@ nvkm_device_tegra_new(struct platform_device *pdev,
}
#else
int
-nvkm_device_tegra_new(struct platform_device *pdev,
+nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
+ struct platform_device *pdev,
const char *cfg, const char *dbg,
bool detect, bool mmio, u64 subdev_mask,
struct nvkm_device **pdevice)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
index 62d3fb66d0ec..2be846374d39 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
@@ -109,7 +109,7 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
return -EINVAL;
}
-static struct nvkm_object_func
+static const struct nvkm_object_func
nv04_disp_root = {
.mthd = nv04_disp_mthd,
.ntfy = nvkm_disp_ntfy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index f1358a564e3e..dda7a7d224c9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -882,6 +882,7 @@ static const struct nvkm_enum gf100_mp_warp_error[] = {
{ 0x0d, "GPR_OUT_OF_BOUNDS" },
{ 0x0e, "MEM_OUT_OF_BOUNDS" },
{ 0x0f, "UNALIGNED_MEM_ACCESS" },
+ { 0x10, "INVALID_ADDR_SPACE" },
{ 0x11, "INVALID_PARAM" },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
index d13187409d68..d081ee41fc14 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
@@ -98,6 +98,7 @@ gf110_gr = {
{ -1, -1, FERMI_B, &gf100_fermi },
{ -1, -1, FERMI_C, &gf100_fermi },
{ -1, -1, FERMI_COMPUTE_A },
+ { -1, -1, FERMI_COMPUTE_B },
{}
}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
index 28483d8bf3d2..d8e8af4d3b30 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
@@ -135,6 +135,7 @@ gf117_gr = {
{ -1, -1, FERMI_B, &gf100_fermi },
{ -1, -1, FERMI_C, &gf100_fermi },
{ -1, -1, FERMI_COMPUTE_A },
+ { -1, -1, FERMI_COMPUTE_B },
{}
}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
index 9811a72e0313..01faf9a73774 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
@@ -189,6 +189,7 @@ gf119_gr = {
{ -1, -1, FERMI_B, &gf100_fermi },
{ -1, -1, FERMI_C, &gf100_fermi },
{ -1, -1, FERMI_COMPUTE_A },
+ { -1, -1, FERMI_COMPUTE_B },
{}
}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
index 0db9be202c42..2721592d3031 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
@@ -633,7 +633,7 @@ nvkm_perfmon_dtor(struct nvkm_object *object)
return perfmon;
}
-static struct nvkm_object_func
+static const struct nvkm_object_func
nvkm_perfmon = {
.dtor = nvkm_perfmon_dtor,
.mthd = nvkm_perfmon_mthd,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
index 65af31441e9c..a7d69ce7abc1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
@@ -267,6 +267,12 @@ init_i2c(struct nvbios_init *init, int index)
index = NVKM_I2C_BUS_PRI;
if (init->outp && init->outp->i2c_upper_default)
index = NVKM_I2C_BUS_SEC;
+ } else
+ if (index == 0x80) {
+ index = NVKM_I2C_BUS_PRI;
+ } else
+ if (index == 0x81) {
+ index = NVKM_I2C_BUS_SEC;
}
bus = nvkm_i2c_bus_find(i2c, index);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c
index 441ec451b788..c268e5afe852 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c
@@ -62,19 +62,6 @@ nvbios_pmuTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
}
u32
-nvbios_pmuTp(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
- struct nvbios_pmuT *info)
-{
- u32 data = nvbios_pmuTe(bios, ver, hdr, cnt, len);
- memset(info, 0x00, sizeof(*info));
- switch (!!data * *ver) {
- default:
- break;
- }
- return data;
-}
-
-u32
nvbios_pmuEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
{
u8 cnt, len;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
index e0ec2a6b7b79..212800ecdce9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
@@ -8,7 +8,10 @@ struct nvbios_source {
void *(*init)(struct nvkm_bios *, const char *);
void (*fini)(void *);
u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
+ u32 (*size)(void *);
bool rw;
+ bool ignore_checksum;
+ bool no_pcir;
};
int nvbios_extend(struct nvkm_bios *, u32 length);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
index f0e1fc74a52e..d0ae7454764e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
@@ -171,6 +171,7 @@ nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx,
p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x03) & 0x04) >> 2;
p->ramcfg_00_03_08 = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3;
p->ramcfg_RON = (nvbios_rd08(bios, data + 0x03) & 0x10) >> 3;
+ p->ramcfg_FBVDDQ = (nvbios_rd08(bios, data + 0x03) & 0x80) >> 7;
p->ramcfg_00_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1;
p->ramcfg_00_04_04 = (nvbios_rd08(bios, data + 0x04) & 0x04) >> 2;
p->ramcfg_00_04_20 = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5;
@@ -205,6 +206,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6;
p->ramcfg_10_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0;
p->ramcfg_10_04_01 = (nvbios_rd08(bios, data + 0x04) & 0x01) >> 0;
+ p->ramcfg_FBVDDQ = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3;
p->ramcfg_10_05 = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0;
p->ramcfg_10_06 = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0;
p->ramcfg_10_07 = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0;
@@ -219,7 +221,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
p->ramcfg_11_01_04 = (nvbios_rd08(bios, data + 0x01) & 0x04) >> 2;
p->ramcfg_11_01_08 = (nvbios_rd08(bios, data + 0x01) & 0x08) >> 3;
p->ramcfg_11_01_10 = (nvbios_rd08(bios, data + 0x01) & 0x10) >> 4;
- p->ramcfg_11_01_20 = (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5;
+ p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5;
p->ramcfg_11_01_40 = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6;
p->ramcfg_11_01_80 = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7;
p->ramcfg_11_02_03 = (nvbios_rd08(bios, data + 0x02) & 0x03) >> 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
index 792f017525f6..b2557e87afdd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
@@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto)
u32 read = mthd->func->read(data, start, limit - start, bios);
bios->size = start + read;
}
- return bios->size >= limit;
+ return bios->size >= upto;
}
static int
@@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
struct nvbios_image image;
int score = 1;
- if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
- nvkm_debug(subdev, "%08x: header fetch failed\n", offset);
- return 0;
- }
+ if (mthd->func->no_pcir) {
+ image.base = 0;
+ image.type = 0;
+ image.size = mthd->func->size(mthd->data);
+ image.last = 1;
+ } else {
+ if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
+ nvkm_debug(subdev, "%08x: header fetch failed\n",
+ offset);
+ return 0;
+ }
- if (!nvbios_image(bios, idx, &image)) {
- nvkm_debug(subdev, "image %d invalid\n", idx);
- return 0;
+ if (!nvbios_image(bios, idx, &image)) {
+ nvkm_debug(subdev, "image %d invalid\n", idx);
+ return 0;
+ }
}
nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
image.base, image.type, image.size);
@@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
switch (image.type) {
case 0x00:
- if (nvbios_checksum(&bios->data[image.base], image.size)) {
+ if (!mthd->func->ignore_checksum &&
+ nvbios_checksum(&bios->data[image.base], image.size)) {
nvkm_debug(subdev, "%08x: checksum failed\n",
image.base);
if (mthd->func->rw)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
index bd60d7dd09f5..4bf486b57101 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
@@ -21,6 +21,7 @@
*
*/
#include "priv.h"
+
#include <core/pci.h>
#if defined(__powerpc__)
@@ -33,17 +34,26 @@ static u32
of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
struct priv *priv = data;
- if (offset + length <= priv->size) {
+ if (offset < priv->size) {
+ length = min_t(u32, length, priv->size - offset);
memcpy_fromio(bios->data + offset, priv->data + offset, length);
return length;
}
return 0;
}
+static u32
+of_size(void *data)
+{
+ struct priv *priv = data;
+ return priv->size;
+}
+
static void *
of_init(struct nvkm_bios *bios, const char *name)
{
- struct pci_dev *pdev = bios->subdev.device->func->pci(bios->subdev.device)->pdev;
+ struct nvkm_device *device = bios->subdev.device;
+ struct pci_dev *pdev = device->func->pci(device)->pdev;
struct device_node *dn;
struct priv *priv;
if (!(dn = pci_device_to_OF_node(pdev)))
@@ -62,7 +72,10 @@ nvbios_of = {
.init = of_init,
.fini = (void(*)(void *))kfree,
.read = of_read,
+ .size = of_size,
.rw = false,
+ .ignore_checksum = true,
+ .no_pcir = true,
};
#else
const struct nvbios_source
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
index 615804c3887b..6e0a33648be9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
@@ -73,15 +73,19 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
memset(info, 0x00, sizeof(*info));
switch (!!volt * *ver) {
case 0x12:
+ info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04);
break;
case 0x20:
+ info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x05);
break;
case 0x30:
+ info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04);
break;
case 0x40:
+ info->type = NVBIOS_VOLT_GPIO;
info->base = nvbios_rd32(bios, volt + 0x04);
info->step = nvbios_rd16(bios, volt + 0x08);
info->vidmask = nvbios_rd08(bios, volt + 0x0b);
@@ -90,11 +94,20 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
info->max = info->base;
break;
case 0x50:
- info->vidmask = nvbios_rd08(bios, volt + 0x06);
info->min = nvbios_rd32(bios, volt + 0x0a);
info->max = nvbios_rd32(bios, volt + 0x0e);
info->base = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
- info->step = nvbios_rd16(bios, volt + 0x16);
+
+ /* offset 4 seems to be a flag byte */
+ if (nvbios_rd32(bios, volt + 0x4) & 1) {
+ info->type = NVBIOS_VOLT_PWM;
+ info->pwm_freq = nvbios_rd32(bios, volt + 0x5) / 1000;
+ info->pwm_range = nvbios_rd32(bios, volt + 0x16);
+ } else {
+ info->type = NVBIOS_VOLT_GPIO;
+ info->vidmask = nvbios_rd08(bios, volt + 0x06);
+ info->step = nvbios_rd16(bios, volt + 0x16);
+ }
break;
}
return volt;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
index 79f1cf513b36..2a5668938f2f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
@@ -132,6 +132,38 @@ nvkm_hwsq_wait(struct nvkm_hwsq *hwsq, u8 flag, u8 data)
}
void
+nvkm_hwsq_wait_vblank(struct nvkm_hwsq *hwsq)
+{
+ struct nvkm_subdev *subdev = hwsq->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 heads, x, y, px = 0;
+ int i, head_sync;
+
+ heads = nvkm_rd32(device, 0x610050);
+ for (i = 0; i < 2; i++) {
+ /* Heuristic: sync to head with biggest resolution */
+ if (heads & (2 << (i << 3))) {
+ x = nvkm_rd32(device, 0x610b40 + (0x540 * i));
+ y = (x & 0xffff0000) >> 16;
+ x &= 0x0000ffff;
+ if ((x * y) > px) {
+ px = (x * y);
+ head_sync = i;
+ }
+ }
+ }
+
+ if (px == 0) {
+ nvkm_debug(subdev, "WAIT VBLANK !NO ACTIVE HEAD\n");
+ return;
+ }
+
+ nvkm_debug(subdev, "WAIT VBLANK HEAD%d\n", head_sync);
+ nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x0);
+ nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x1);
+}
+
+void
nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec)
{
u8 shift = 0, usec = nsec / 1000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
index 8117ec5a1468..54ec3b131dfd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
@@ -134,6 +134,12 @@ hwsq_wait(struct hwsq *ram, u8 flag, u8 data)
}
static inline void
+hwsq_wait_vblank(struct hwsq *ram)
+{
+ nvkm_hwsq_wait_vblank(ram->hwsq);
+}
+
+static inline void
hwsq_nsec(struct hwsq *ram, u32 nsec)
{
nvkm_hwsq_nsec(ram->hwsq, nsec);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c
index 347da9ee20f5..f97e3ec196bb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c
@@ -44,5 +44,5 @@ int
g84_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
{
return nv50_clk_new_(&g84_clk, device, index,
- (device->chipset == 0xa0), pclk);
+ (device->chipset >= 0x94), pclk);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
index 79b523aa52aa..60ece0a8a2e1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
@@ -63,7 +63,7 @@ ramgddr3_wr_lo[] = {
{ 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 },
{ 11, 0 }, { 13 , 1 },
/* the below are mentioned in some, but not all, gddr3 docs */
- { 4, 1 }, { 6, 3 }, { 12, 1 },
+ { 4, 0 }, { 6, 3 }, { 12, 1 },
{ -1 }
};
@@ -87,15 +87,17 @@ nvkm_gddr3_calc(struct nvkm_ram *ram)
WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
/* XXX: Get these values from the VBIOS instead */
DLL = !(ram->mr[1] & 0x1);
- ODT = (ram->mr[1] & 0x004) >> 2 |
- (ram->mr[1] & 0x040) >> 5 |
- (ram->mr[1] & 0x200) >> 7;
RON = !(ram->mr[1] & 0x300) >> 8;
break;
default:
return -ENOSYS;
}
+ if (ram->next->bios.timing_ver == 0x20 ||
+ ram->next->bios.ramcfg_timing == 0xff) {
+ ODT = (ram->mr[1] & 0xc) >> 2;
+ }
+
hi = ram->mr[2] & 0x1;
CL = ramxlat(hi ? ramgddr3_cl_hi : ramgddr3_cl_lo, CL);
WR = ramxlat(ramgddr3_wr_lo, WR);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c
index 24f83b09e6a1..2cc074d3901a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c
@@ -38,11 +38,12 @@ nvkm_gddr5_calc(struct nvkm_ram *ram, bool nuts)
int WL, CL, WR, at[2], dt, ds;
int rq = ram->freq < 1000000; /* XXX */
+ xd = !ram->next->bios.ramcfg_DLLoff;
+
switch (ram->next->bios.ramcfg_ver) {
case 0x11:
pd = ram->next->bios.ramcfg_11_01_80;
lf = ram->next->bios.ramcfg_11_01_40;
- xd = !ram->next->bios.ramcfg_11_01_20;
vh = ram->next->bios.ramcfg_11_02_10;
vr = ram->next->bios.ramcfg_11_02_04;
vo = ram->next->bios.ramcfg_11_06;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
index 989355622aac..9df45030ff9f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
@@ -673,6 +673,25 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq)
* DDR3
******************************************************************************/
+static void
+nvkm_sddr3_dll_reset(struct gk104_ramfuc *fuc)
+{
+ ram_nuke(fuc, mr[0]);
+ ram_mask(fuc, mr[0], 0x100, 0x100);
+ ram_mask(fuc, mr[0], 0x100, 0x000);
+}
+
+static void
+nvkm_sddr3_dll_disable(struct gk104_ramfuc *fuc)
+{
+ u32 mr1_old = ram_rd32(fuc, mr[1]);
+
+ if (!(mr1_old & 0x1)) {
+ ram_mask(fuc, mr[1], 0x1, 0x1);
+ ram_nsec(fuc, 1000);
+ }
+}
+
static int
gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
{
@@ -702,6 +721,10 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000);
ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
+
+ if (next->bios.ramcfg_DLLoff)
+ nvkm_sddr3_dll_disable(fuc);
+
ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */
ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000);
@@ -879,17 +902,20 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */
ram_nsec(fuc, 1000);
- ram_nuke(fuc, mr[0]);
- ram_mask(fuc, mr[0], 0x100, 0x100);
- ram_mask(fuc, mr[0], 0x100, 0x000);
+ if (!next->bios.ramcfg_DLLoff) {
+ ram_mask(fuc, mr[1], 0x1, 0x0);
+ nvkm_sddr3_dll_reset(fuc);
+ }
- ram_mask(fuc, mr[2], 0xfff, ram->base.mr[2]);
+ ram_mask(fuc, mr[2], 0x00000fff, ram->base.mr[2]);
+ ram_mask(fuc, mr[1], 0xffffffff, ram->base.mr[1]);
ram_wr32(fuc, mr[0], ram->base.mr[0]);
ram_nsec(fuc, 1000);
- ram_nuke(fuc, mr[0]);
- ram_mask(fuc, mr[0], 0x100, 0x100);
- ram_mask(fuc, mr[0], 0x100, 0x000);
+ if (!next->bios.ramcfg_DLLoff) {
+ nvkm_sddr3_dll_reset(fuc);
+ ram_nsec(fuc, 1000);
+ }
if (vc == 0 && ram_have(fuc, gpio2E)) {
u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]);
@@ -945,6 +971,67 @@ gk104_ram_calc_data(struct gk104_ram *ram, u32 khz, struct nvkm_ram_data *data)
}
static int
+gk104_calc_pll_output(int fN, int M, int N, int P, int clk)
+{
+ return ((clk * N) + (((u16)(fN + 4096) * clk) >> 13)) / (M * P);
+}
+
+static int
+gk104_pll_calc_hiclk(int target_khz, int crystal,
+ int *N1, int *fN1, int *M1, int *P1,
+ int *N2, int *M2, int *P2)
+{
+ int best_clk = 0, best_err = target_khz, p_ref, n_ref;
+ bool upper = false;
+
+ *M1 = 1;
+ /* M has to be 1, otherwise it gets unstable */
+ *M2 = 1;
+ /* can be 1 or 2, sticking with 1 for simplicity */
+ *P2 = 1;
+
+ for (p_ref = 0x7; p_ref >= 0x5; --p_ref) {
+ for (n_ref = 0x25; n_ref <= 0x2b; ++n_ref) {
+ int cur_N, cur_clk, cur_err;
+
+ cur_clk = gk104_calc_pll_output(0, 1, n_ref, p_ref, crystal);
+ cur_N = target_khz / cur_clk;
+ cur_err = target_khz
+ - gk104_calc_pll_output(0xf000, 1, cur_N, 1, cur_clk);
+
+ /* we found a better combination */
+ if (cur_err < best_err) {
+ best_err = cur_err;
+ best_clk = cur_clk;
+ *N2 = cur_N;
+ *N1 = n_ref;
+ *P1 = p_ref;
+ upper = false;
+ }
+
+ cur_N += 1;
+ cur_err = gk104_calc_pll_output(0xf000, 1, cur_N, 1, cur_clk)
+ - target_khz;
+ if (cur_err < best_err) {
+ best_err = cur_err;
+ best_clk = cur_clk;
+ *N2 = cur_N;
+ *N1 = n_ref;
+ *P1 = p_ref;
+ upper = true;
+ }
+ }
+ }
+
+ /* adjust fN to get closer to the target clock */
+ *fN1 = (u16)((((best_err / *N2 * *P2) * (*P1 * *M1)) << 13) / crystal);
+ if (upper)
+ *fN1 = (u16)(1 - *fN1);
+
+ return gk104_calc_pll_output(*fN1, 1, *N1, *P1, crystal);
+}
+
+static int
gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next)
{
struct gk104_ramfuc *fuc = &ram->fuc;
@@ -968,31 +1055,24 @@ gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next)
* kepler boards, no idea how/why they're chosen.
*/
refclk = next->freq;
- if (ram->mode == 2)
- refclk = fuc->mempll.refclk;
-
- /* calculate refpll coefficients */
- ret = gt215_pll_calc(subdev, &fuc->refpll, refclk, &ram->N1,
- &ram->fN1, &ram->M1, &ram->P1);
- fuc->mempll.refclk = ret;
- if (ret <= 0) {
- nvkm_error(subdev, "unable to calc refpll\n");
- return -EINVAL;
- }
-
- /* calculate mempll coefficients, if we're using it */
if (ram->mode == 2) {
- /* post-divider doesn't work... the reg takes the values but
- * appears to completely ignore it. there *is* a bit at
- * bit 28 that appears to divide the clock by 2 if set.
- */
- fuc->mempll.min_p = 1;
- fuc->mempll.max_p = 2;
-
- ret = gt215_pll_calc(subdev, &fuc->mempll, next->freq,
- &ram->N2, NULL, &ram->M2, &ram->P2);
+ ret = gk104_pll_calc_hiclk(next->freq, subdev->device->crystal,
+ &ram->N1, &ram->fN1, &ram->M1, &ram->P1,
+ &ram->N2, &ram->M2, &ram->P2);
+ fuc->mempll.refclk = ret;
+ if (ret <= 0) {
+ nvkm_error(subdev, "unable to calc plls\n");
+ return -EINVAL;
+ }
+ nvkm_debug(subdev, "sucessfully calced PLLs for clock %i kHz"
+ " (refclock: %i kHz)\n", next->freq, ret);
+ } else {
+ /* calculate refpll coefficients */
+ ret = gt215_pll_calc(subdev, &fuc->refpll, refclk, &ram->N1,
+ &ram->fN1, &ram->M1, &ram->P1);
+ fuc->mempll.refclk = ret;
if (ret <= 0) {
- nvkm_error(subdev, "unable to calc mempll\n");
+ nvkm_error(subdev, "unable to calc refpll\n");
return -EINVAL;
}
}
@@ -1600,6 +1680,7 @@ gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
break;
case NVKM_RAM_TYPE_DDR3:
ram->fuc.r_mr[0] = ramfuc_reg(0x10f300);
+ ram->fuc.r_mr[1] = ramfuc_reg(0x10f304);
ram->fuc.r_mr[2] = ramfuc_reg(0x10f320);
break;
default:
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index 5c08ae8023fa..d15ea886df27 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -34,9 +34,6 @@
#include <subdev/clk/gt215.h>
#include <subdev/gpio.h>
-/* XXX: Remove when memx gains GPIO support */
-extern int nv50_gpio_location(int line, u32 *reg, u32 *shift);
-
struct gt215_ramfuc {
struct ramfuc base;
struct ramfuc_reg r_0x001610;
@@ -75,7 +72,7 @@ struct gt215_ramfuc {
struct ramfuc_reg r_0x111400;
struct ramfuc_reg r_0x611200;
struct ramfuc_reg r_mr[4];
- struct ramfuc_reg r_gpioFBVREF;
+ struct ramfuc_reg r_gpio[4];
};
struct gt215_ltrain {
@@ -466,24 +463,27 @@ gt215_ram_lock_pll(struct gt215_ramfuc *fuc, struct gt215_clk_info *mclk)
}
static void
-gt215_ram_fbvref(struct gt215_ramfuc *fuc, u32 val)
+gt215_ram_gpio(struct gt215_ramfuc *fuc, u8 tag, u32 val)
{
struct nvkm_gpio *gpio = fuc->base.fb->subdev.device->gpio;
struct dcb_gpio_func func;
u32 reg, sh, gpio_val;
int ret;
- if (nvkm_gpio_get(gpio, 0, 0x2e, DCB_GPIO_UNUSED) != val) {
- ret = nvkm_gpio_find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func);
+ if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) {
+ ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func);
if (ret)
return;
- nv50_gpio_location(func.line, &reg, &sh);
- gpio_val = ram_rd32(fuc, gpioFBVREF);
+ reg = func.line >> 3;
+ sh = (func.line & 0x7) << 2;
+ gpio_val = ram_rd32(fuc, gpio[reg]);
if (gpio_val & (8 << sh))
val = !val;
+ if (!(func.log[1] & 1))
+ val = !val;
- ram_mask(fuc, gpioFBVREF, (0x3 << sh), ((val | 0x2) << sh));
+ ram_mask(fuc, gpio[reg], (0x3 << sh), ((val | 0x2) << sh));
ram_nsec(fuc, 20000);
}
}
@@ -498,6 +498,7 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq)
struct nvkm_device *device = subdev->device;
struct nvkm_bios *bios = device->bios;
struct gt215_clk_info mclk;
+ struct nvkm_gpio *gpio = device->gpio;
struct nvkm_ram_data *next;
u8 ver, hdr, cnt, len, strap;
u32 data;
@@ -642,8 +643,8 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq)
break;
}
- if (fuc->r_gpioFBVREF.addr && next->bios.timing_10_ODT)
- gt215_ram_fbvref(fuc, 0);
+ if (next->bios.timing_10_ODT)
+ gt215_ram_gpio(fuc, 0x2e, 1);
/* Brace RAM for impact */
ram_wr32(fuc, 0x1002d4, 0x00000001);
@@ -656,6 +657,23 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq)
if (device->chipset == 0xa3 && freq <= 500000)
ram_mask(fuc, 0x100700, 0x00000006, 0x00000006);
+ /* Alter FBVDD/Q, apparently must be done with PLL disabled, thus
+ * set it to bypass */
+ if (nvkm_gpio_get(gpio, 0, 0x18, DCB_GPIO_UNUSED) ==
+ next->bios.ramcfg_FBVDDQ) {
+ data = ram_rd32(fuc, 0x004000) & 0x9;
+
+ if (data == 0x1)
+ ram_mask(fuc, 0x004000, 0x8, 0x8);
+ if (data & 0x1)
+ ram_mask(fuc, 0x004000, 0x1, 0x0);
+
+ gt215_ram_gpio(fuc, 0x18, !next->bios.ramcfg_FBVDDQ);
+
+ if (data & 0x1)
+ ram_mask(fuc, 0x004000, 0x1, 0x1);
+ }
+
/* Fiddle with clocks */
/* There's 4 scenario's
* pll->pll: first switch to a 324MHz clock, set up new PLL, switch
@@ -753,39 +771,43 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq)
unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100;
r111100 = ram_rd32(fuc, 0x111100) & ~0x3a800000;
- if (next->bios.ramcfg_10_02_04) {
- switch (ram->base.type) {
- case NVKM_RAM_TYPE_DDR3:
- if (device->chipset != 0xa8)
- r111100 |= 0x00000004;
- /* no break */
- case NVKM_RAM_TYPE_DDR2:
- r111100 |= 0x08000000;
- break;
- default:
- break;
- }
- } else {
- switch (ram->base.type) {
- case NVKM_RAM_TYPE_DDR2:
- r111100 |= 0x1a800000;
+ /* NVA8 seems to skip various bits related to ramcfg_10_02_04 */
+ if (device->chipset == 0xa8) {
+ r111100 |= 0x08000000;
+ if (!next->bios.ramcfg_10_02_04)
unk714 |= 0x00000010;
- break;
- case NVKM_RAM_TYPE_DDR3:
- if (device->chipset == 0xa8) {
- r111100 |= 0x08000000;
- } else {
- r111100 &= ~0x00000004;
+ } else {
+ if (next->bios.ramcfg_10_02_04) {
+ switch (ram->base.type) {
+ case NVKM_RAM_TYPE_DDR2:
+ case NVKM_RAM_TYPE_DDR3:
+ r111100 &= ~0x00000020;
+ if (next->bios.ramcfg_10_02_10)
+ r111100 |= 0x08000004;
+ else
+ r111100 |= 0x00000024;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (ram->base.type) {
+ case NVKM_RAM_TYPE_DDR2:
+ case NVKM_RAM_TYPE_DDR3:
+ r111100 &= ~0x00000024;
r111100 |= 0x12800000;
+
+ if (next->bios.ramcfg_10_02_10)
+ r111100 |= 0x08000000;
+ unk714 |= 0x00000010;
+ break;
+ case NVKM_RAM_TYPE_GDDR3:
+ r111100 |= 0x30000000;
+ unk714 |= 0x00000020;
+ break;
+ default:
+ break;
}
- unk714 |= 0x00000010;
- break;
- case NVKM_RAM_TYPE_GDDR3:
- r111100 |= 0x30000000;
- unk714 |= 0x00000020;
- break;
- default:
- break;
}
}
@@ -809,8 +831,8 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq)
ram_mask(fuc, 0x100718, 0xffffffff, unk718);
ram_mask(fuc, 0x111100, 0xffffffff, r111100);
- if (fuc->r_gpioFBVREF.addr && !next->bios.timing_10_ODT)
- gt215_ram_fbvref(fuc, 1);
+ if (!next->bios.timing_10_ODT)
+ gt215_ram_gpio(fuc, 0x2e, 0);
/* Reset DLL */
if (!next->bios.ramcfg_DLLoff)
@@ -919,10 +941,7 @@ gt215_ram_func = {
int
gt215_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
{
- struct nvkm_gpio *gpio = fb->subdev.device->gpio;
- struct dcb_gpio_func func;
struct gt215_ram *ram;
- u32 reg, shift;
int ret, i;
if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL)))
@@ -981,12 +1000,10 @@ gt215_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
ram->fuc.r_mr[2] = ramfuc_reg(0x1002e0);
ram->fuc.r_mr[3] = ramfuc_reg(0x1002e4);
}
-
- ret = nvkm_gpio_find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func);
- if (ret == 0) {
- nv50_gpio_location(func.line, &reg, &shift);
- ram->fuc.r_gpioFBVREF = ramfuc_reg(reg);
- }
+ ram->fuc.r_gpio[0] = ramfuc_reg(0x00e104);
+ ram->fuc.r_gpio[1] = ramfuc_reg(0x00e108);
+ ram->fuc.r_gpio[2] = ramfuc_reg(0x00e120);
+ ram->fuc.r_gpio[3] = ramfuc_reg(0x00e124);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index 9197e0ef5cdb..87bde8ff2d6b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -33,6 +33,7 @@
#include <subdev/bios/rammap.h>
#include <subdev/bios/timing.h>
#include <subdev/clk/pll.h>
+#include <subdev/gpio.h>
struct nv50_ramseq {
struct hwsq base;
@@ -59,6 +60,7 @@ struct nv50_ramseq {
struct hwsq_reg r_0x611200;
struct hwsq_reg r_timing[9];
struct hwsq_reg r_mr[4];
+ struct hwsq_reg r_gpio[4];
};
struct nv50_ram {
@@ -144,6 +146,38 @@ nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing)
nvkm_debug(subdev, " 240: %08x\n", timing[8]);
return 0;
}
+
+static int
+nv50_ram_timing_read(struct nv50_ram *ram, u32 *timing)
+{
+ unsigned int i;
+ struct nvbios_ramcfg *cfg = &ram->base.target.bios;
+ struct nvkm_subdev *subdev = &ram->base.fb->subdev;
+ struct nvkm_device *device = subdev->device;
+
+ for (i = 0; i <= 8; i++)
+ timing[i] = nvkm_rd32(device, 0x100220 + (i * 4));
+
+ /* Derive the bare minimum for the MR calculation to succeed */
+ cfg->timing_ver = 0x10;
+ T(CL) = (timing[3] & 0xff) + 1;
+
+ switch (ram->base.type) {
+ case NVKM_RAM_TYPE_DDR2:
+ T(CWL) = T(CL) - 1;
+ break;
+ case NVKM_RAM_TYPE_GDDR3:
+ T(CWL) = ((timing[2] & 0xff000000) >> 24) + 1;
+ break;
+ default:
+ return -ENOSYS;
+ break;
+ }
+
+ T(WR) = ((timing[1] >> 24) & 0xff) - 1 - T(CWL);
+
+ return 0;
+}
#undef T
static void
@@ -154,6 +188,33 @@ nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq)
ram_nsec(hwsq, 24000);
}
+static void
+nv50_ram_gpio(struct nv50_ramseq *hwsq, u8 tag, u32 val)
+{
+ struct nvkm_gpio *gpio = hwsq->base.subdev->device->gpio;
+ struct dcb_gpio_func func;
+ u32 reg, sh, gpio_val;
+ int ret;
+
+ if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) {
+ ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func);
+ if (ret)
+ return;
+
+ reg = func.line >> 3;
+ sh = (func.line & 0x7) << 2;
+ gpio_val = ram_rd32(hwsq, gpio[reg]);
+
+ if (gpio_val & (8 << sh))
+ val = !val;
+ if (!(func.log[1] & 1))
+ val = !val;
+
+ ram_mask(hwsq, gpio[reg], (0x3 << sh), ((val | 0x2) << sh));
+ ram_nsec(hwsq, 20000);
+ }
+}
+
static int
nv50_ram_calc(struct nvkm_ram *base, u32 freq)
{
@@ -213,10 +274,11 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
strap, data, ver, hdr);
return -EINVAL;
}
+ nv50_ram_timing_calc(ram, timing);
+ } else {
+ nv50_ram_timing_read(ram, timing);
}
- nv50_ram_timing_calc(ram, timing);
-
ret = ram_init(hwsq, subdev);
if (ret)
return ret;
@@ -235,14 +297,18 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
break;
}
- if (ret)
+ if (ret) {
+ nvkm_error(subdev, "Could not calculate MR\n");
return ret;
+ }
+
+ if (subdev->device->chipset <= 0x96 && !next->bios.ramcfg_00_03_02)
+ ram_mask(hwsq, 0x100710, 0x00000200, 0x00000000);
/* Always disable this bit during reclock */
ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000);
- ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */
- ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */
+ ram_wait_vblank(hwsq);
ram_wr32(hwsq, 0x611200, 0x00003300);
ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */
ram_nsec(hwsq, 8000);
@@ -250,6 +316,9 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */
ram_nsec(hwsq, 2000);
+ if (next->bios.timing_10_ODT)
+ nv50_ram_gpio(hwsq, 0x2e, 1);
+
ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */
ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */
ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */
@@ -286,8 +355,12 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
next->bios.rammap_00_16_40 << 14);
ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1);
ram_mask(hwsq, 0x004008, 0x91ff0000, r004008);
- if (subdev->device->chipset >= 0x96)
+
+ /* XXX: GDDR3 only? */
+ if (subdev->device->chipset >= 0x92)
ram_wr32(hwsq, 0x100da0, r100da0);
+
+ nv50_ram_gpio(hwsq, 0x18, !next->bios.ramcfg_FBVDDQ);
ram_nsec(hwsq, 64000); /*XXX*/
ram_nsec(hwsq, 32000); /*XXX*/
@@ -329,19 +402,33 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 << 12);
/* XXX: A lot of this could be "chipset"/"ram type" specific stuff */
- unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000101;
+ unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000100;
unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020;
unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100;
unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100;
+ if (subdev->device->chipset <= 0x96) {
+ unk710 &= ~0x0000006e;
+ unk714 &= ~0x00000100;
+
+ if (!next->bios.ramcfg_00_03_08)
+ unk710 |= 0x00000060;
+ if (!next->bios.ramcfg_FBVDDQ)
+ unk714 |= 0x00000100;
+ if ( next->bios.ramcfg_00_04_04)
+ unk710 |= 0x0000000e;
+ } else {
+ unk710 &= ~0x00000001;
+
+ if (!next->bios.ramcfg_00_03_08)
+ unk710 |= 0x00000001;
+ }
if ( next->bios.ramcfg_00_03_01)
unk71c |= 0x00000100;
if ( next->bios.ramcfg_00_03_02)
unk710 |= 0x00000100;
- if (!next->bios.ramcfg_00_03_08) {
- unk710 |= 0x1;
- unk714 |= 0x20;
- }
+ if (!next->bios.ramcfg_00_03_08)
+ unk714 |= 0x00000020;
if ( next->bios.ramcfg_00_04_04)
unk714 |= 0x70000000;
if ( next->bios.ramcfg_00_04_20)
@@ -352,6 +439,8 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
ram_mask(hwsq, 0x100718, 0xffffffff, unk718);
ram_mask(hwsq, 0x100710, 0xffffffff, unk710);
+ /* XXX: G94 does not even test these regs in trace. Harmless we do it,
+ * but why is it omitted? */
if (next->bios.rammap_00_16_20) {
ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 |
next->bios.ramcfg_00_06 << 8 |
@@ -364,6 +453,9 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
}
ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]);
+ if (!next->bios.timing_10_ODT)
+ nv50_ram_gpio(hwsq, 0x2e, 0);
+
/* Reset DLL */
if (!next->bios.ramcfg_DLLoff)
nvkm_sddr2_dll_reset(hwsq);
@@ -379,6 +471,8 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000);
if (next->bios.ramcfg_00_03_02)
ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000);
+ if (subdev->device->chipset <= 0x96 && next->bios.ramcfg_00_03_02)
+ ram_mask(hwsq, 0x100710, 0x00000200, 0x00000200);
return 0;
}
@@ -634,5 +728,10 @@ nv50_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4);
}
+ ram->hwsq.r_gpio[0] = hwsq_reg(0x00e104);
+ ram->hwsq.r_gpio[1] = hwsq_reg(0x00e108);
+ ram->hwsq.r_gpio[2] = hwsq_reg(0x00e120);
+ ram->hwsq.r_gpio[3] = hwsq_reg(0x00e124);
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
index 0f1f97ccd5f6..8df7306d5729 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
@@ -11,5 +11,6 @@
#define ram_mask(s,r,m,d) hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d))
#define ram_setf(s,f,d) hwsq_setf(&(s)->base, (f), (d))
#define ram_wait(s,f,d) hwsq_wait(&(s)->base, (f), (d))
+#define ram_wait_vblank(s) hwsq_wait_vblank(&(s)->base)
#define ram_nsec(s,n) hwsq_nsec(&(s)->base, (n))
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
index 86bf67456b14..b9f1ffdfc602 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
@@ -76,6 +76,12 @@ nvkm_sddr2_calc(struct nvkm_ram *ram)
return -ENOSYS;
}
+ if (ram->next->bios.timing_ver == 0x20 ||
+ ram->next->bios.ramcfg_timing == 0xff) {
+ ODT = (ram->mr[1] & 0x004) >> 2 |
+ (ram->mr[1] & 0x040) >> 5;
+ }
+
CL = ramxlat(ramddr2_cl, CL);
WR = ramxlat(ramddr2_wr, WR);
if (CL < 0 || WR < 0)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
index b4edc97dc8c5..26900333b1d6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
@@ -70,6 +70,8 @@ nvkm_sddr3_calc(struct nvkm_ram *ram)
{
int CWL, CL, WR, DLL = 0, ODT = 0;
+ DLL = !ram->next->bios.ramcfg_DLLoff;
+
switch (ram->next->bios.timing_ver) {
case 0x10:
if (ram->next->bios.timing_hdr < 0x17) {
@@ -79,7 +81,6 @@ nvkm_sddr3_calc(struct nvkm_ram *ram)
CWL = ram->next->bios.timing_10_CWL;
CL = ram->next->bios.timing_10_CL;
WR = ram->next->bios.timing_10_WR;
- DLL = !ram->next->bios.ramcfg_DLLoff;
ODT = ram->next->bios.timing_10_ODT;
break;
case 0x20:
@@ -87,7 +88,6 @@ nvkm_sddr3_calc(struct nvkm_ram *ram)
CL = (ram->next->bios.timing[1] & 0x0000001f) >> 0;
WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
/* XXX: Get these values from the VBIOS instead */
- DLL = !(ram->mr[1] & 0x1);
ODT = (ram->mr[1] & 0x004) >> 2 |
(ram->mr[1] & 0x040) >> 5 |
(ram->mr[1] & 0x200) >> 7;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c
index 8996649209ab..73923fd5f7f2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c
@@ -54,7 +54,7 @@ nv50_gpio_reset(struct nvkm_gpio *gpio, u8 match)
}
}
-int
+static int
nv50_gpio_location(int line, u32 *reg, u32 *shift)
{
const u32 nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild
index a0b12d27284a..de888fa62b3e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild
@@ -1,3 +1,4 @@
nvkm-y += nvkm/subdev/ibus/gf100.o
+nvkm-y += nvkm/subdev/ibus/gf117.o
nvkm-y += nvkm/subdev/ibus/gk104.o
nvkm-y += nvkm/subdev/ibus/gk20a.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
index 37a0496f7ed1..72d6330d243d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
@@ -21,7 +21,7 @@
*
* Authors: Ben Skeggs
*/
-#include <subdev/ibus.h>
+#include "priv.h"
static void
gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
@@ -56,7 +56,7 @@ gf100_ibus_intr_gpc(struct nvkm_subdev *ibus, int i)
nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000);
}
-static void
+void
gf100_ibus_intr(struct nvkm_subdev *ibus)
{
struct nvkm_device *device = ibus->device;
@@ -92,8 +92,21 @@ gf100_ibus_intr(struct nvkm_subdev *ibus)
}
}
+static int
+gf100_ibus_init(struct nvkm_subdev *ibus)
+{
+ struct nvkm_device *device = ibus->device;
+ nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800);
+ nvkm_wr32(device, 0x12232c, 0x00100064);
+ nvkm_wr32(device, 0x122330, 0x00100064);
+ nvkm_wr32(device, 0x122334, 0x00100064);
+ nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100);
+ return 0;
+}
+
static const struct nvkm_subdev_func
gf100_ibus = {
+ .init = gf100_ibus_init,
.intr = gf100_ibus_intr,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c
new file mode 100644
index 000000000000..f69f263c5906
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015 Samuel Pitosiet
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Samuel Pitoiset
+ */
+#include "priv.h"
+
+static int
+gf117_ibus_init(struct nvkm_subdev *ibus)
+{
+ struct nvkm_device *device = ibus->device;
+ nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800);
+ nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100);
+ nvkm_mask(device, 0x1223b0, 0x0003ffff, 0x00000fff);
+ return 0;
+}
+
+static const struct nvkm_subdev_func
+gf117_ibus = {
+ .init = gf117_ibus_init,
+ .intr = gf100_ibus_intr,
+};
+
+int
+gf117_ibus_new(struct nvkm_device *device, int index,
+ struct nvkm_subdev **pibus)
+{
+ struct nvkm_subdev *ibus;
+ if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
+ return -ENOMEM;
+ nvkm_subdev_ctor(&gf117_ibus, device, index, 0, ibus);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
new file mode 100644
index 000000000000..48e1b6365ce6
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
@@ -0,0 +1,7 @@
+#ifndef __NVKM_IBUS_PRIV_H__
+#define __NVKM_IBUS_PRIV_H__
+
+#include <subdev/ibus.h>
+
+void gf100_ibus_intr(struct nvkm_subdev *);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
index cd7feb1b25f6..14107b5b7811 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
@@ -23,35 +23,42 @@
/*
* GK20A does not have dedicated video memory, and to accurately represent this
* fact Nouveau will not create a RAM device for it. Therefore its instmem
- * implementation must be done directly on top of system memory, while providing
- * coherent read and write operations.
+ * implementation must be done directly on top of system memory, while
+ * preserving coherency for read and write operations.
*
* Instmem can be allocated through two means:
- * 1) If an IOMMU mapping has been probed, the IOMMU API is used to make memory
+ * 1) If an IOMMU unit has been probed, the IOMMU API is used to make memory
* pages contiguous to the GPU. This is the preferred way.
- * 2) If no IOMMU mapping is probed, the DMA API is used to allocate physically
+ * 2) If no IOMMU unit is probed, the DMA API is used to allocate physically
* contiguous memory.
*
- * In both cases CPU read and writes are performed using PRAMIN (i.e. using the
- * GPU path) to ensure these operations are coherent for the GPU. This allows us
- * to use more "relaxed" allocation parameters when using the DMA API, since we
- * never need a kernel mapping.
+ * In both cases CPU read and writes are performed by creating a write-combined
+ * mapping. The GPU L2 cache must thus be flushed/invalidated when required. To
+ * be conservative we do this every time we acquire or release an instobj, but
+ * ideally L2 management should be handled at a higher level.
+ *
+ * To improve performance, CPU mappings are not removed upon instobj release.
+ * Instead they are placed into a LRU list to be recycled when the mapped space
+ * goes beyond a certain threshold. At the moment this limit is 1MB.
*/
-#define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base)
#include "priv.h"
#include <core/memory.h>
#include <core/mm.h>
#include <core/tegra.h>
#include <subdev/fb.h>
-
-#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
+#include <subdev/ltc.h>
struct gk20a_instobj {
struct nvkm_memory memory;
- struct gk20a_instmem *imem;
struct nvkm_mem mem;
+ struct gk20a_instmem *imem;
+
+ /* CPU mapping */
+ u32 *vaddr;
+ struct list_head vaddr_node;
};
+#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
/*
* Used for objects allocated using the DMA API
@@ -59,10 +66,12 @@ struct gk20a_instobj {
struct gk20a_instobj_dma {
struct gk20a_instobj base;
- void *cpuaddr;
+ u32 *cpuaddr;
dma_addr_t handle;
struct nvkm_mm_node r;
};
+#define gk20a_instobj_dma(p) \
+ container_of(gk20a_instobj(p), struct gk20a_instobj_dma, base)
/*
* Used for objects flattened using the IOMMU API
@@ -70,25 +79,38 @@ struct gk20a_instobj_dma {
struct gk20a_instobj_iommu {
struct gk20a_instobj base;
- /* array of base.mem->size pages */
+ /* will point to the higher half of pages */
+ dma_addr_t *dma_addrs;
+ /* array of base.mem->size pages (+ dma_addr_ts) */
struct page *pages[];
};
+#define gk20a_instobj_iommu(p) \
+ container_of(gk20a_instobj(p), struct gk20a_instobj_iommu, base)
struct gk20a_instmem {
struct nvkm_instmem base;
- unsigned long lock_flags;
+
+ /* protects vaddr_* and gk20a_instobj::vaddr* */
spinlock_t lock;
- u64 addr;
+
+ /* CPU mappings LRU */
+ unsigned int vaddr_use;
+ unsigned int vaddr_max;
+ struct list_head vaddr_lru;
/* Only used if IOMMU if present */
struct mutex *mm_mutex;
struct nvkm_mm *mm;
struct iommu_domain *domain;
unsigned long iommu_pgshift;
+ u16 iommu_bit;
/* Only used by DMA API */
struct dma_attrs attrs;
+
+ void __iomem * (*cpu_map)(struct nvkm_memory *);
};
+#define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base)
static enum nvkm_memory_target
gk20a_instobj_target(struct nvkm_memory *memory)
@@ -100,7 +122,6 @@ static u64
gk20a_instobj_addr(struct nvkm_memory *memory)
{
return gk20a_instobj(memory)->mem.offset;
-
}
static u64
@@ -110,107 +131,223 @@ gk20a_instobj_size(struct nvkm_memory *memory)
}
static void __iomem *
+gk20a_instobj_cpu_map_dma(struct nvkm_memory *memory)
+{
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory);
+ struct device *dev = node->base.imem->base.subdev.device->dev;
+ int npages = nvkm_memory_size(memory) >> 12;
+ struct page *pages[npages];
+ int i;
+
+ /* we shouldn't see a gk20a on anything but arm/arm64 anyways */
+ /* phys_to_page does not exist on all platforms... */
+ pages[0] = pfn_to_page(dma_to_phys(dev, node->handle) >> PAGE_SHIFT);
+ for (i = 1; i < npages; i++)
+ pages[i] = pages[0] + i;
+
+ return vmap(pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+#else
+ BUG();
+ return NULL;
+#endif
+}
+
+static void __iomem *
+gk20a_instobj_cpu_map_iommu(struct nvkm_memory *memory)
+{
+ struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory);
+ int npages = nvkm_memory_size(memory) >> 12;
+
+ return vmap(node->pages, npages, VM_MAP,
+ pgprot_writecombine(PAGE_KERNEL));
+}
+
+/*
+ * Must be called while holding gk20a_instmem_lock
+ */
+static void
+gk20a_instmem_vaddr_gc(struct gk20a_instmem *imem, const u64 size)
+{
+ while (imem->vaddr_use + size > imem->vaddr_max) {
+ struct gk20a_instobj *obj;
+
+ /* no candidate that can be unmapped, abort... */
+ if (list_empty(&imem->vaddr_lru))
+ break;
+
+ obj = list_first_entry(&imem->vaddr_lru, struct gk20a_instobj,
+ vaddr_node);
+ list_del(&obj->vaddr_node);
+ vunmap(obj->vaddr);
+ obj->vaddr = NULL;
+ imem->vaddr_use -= nvkm_memory_size(&obj->memory);
+ nvkm_debug(&imem->base.subdev, "(GC) vaddr used: %x/%x\n",
+ imem->vaddr_use, imem->vaddr_max);
+
+ }
+}
+
+static void __iomem *
gk20a_instobj_acquire(struct nvkm_memory *memory)
{
- struct gk20a_instmem *imem = gk20a_instobj(memory)->imem;
+ struct gk20a_instobj *node = gk20a_instobj(memory);
+ struct gk20a_instmem *imem = node->imem;
+ struct nvkm_ltc *ltc = imem->base.subdev.device->ltc;
+ const u64 size = nvkm_memory_size(memory);
unsigned long flags;
+
+ nvkm_ltc_flush(ltc);
+
spin_lock_irqsave(&imem->lock, flags);
- imem->lock_flags = flags;
- return NULL;
+
+ if (node->vaddr) {
+ /* remove us from the LRU list since we cannot be unmapped */
+ list_del(&node->vaddr_node);
+
+ goto out;
+ }
+
+ /* try to free some address space if we reached the limit */
+ gk20a_instmem_vaddr_gc(imem, size);
+
+ node->vaddr = imem->cpu_map(memory);
+
+ if (!node->vaddr) {
+ nvkm_error(&imem->base.subdev, "cannot map instobj - "
+ "this is not going to end well...\n");
+ goto out;
+ }
+
+ imem->vaddr_use += size;
+ nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n",
+ imem->vaddr_use, imem->vaddr_max);
+
+out:
+ spin_unlock_irqrestore(&imem->lock, flags);
+
+ return node->vaddr;
}
static void
gk20a_instobj_release(struct nvkm_memory *memory)
{
- struct gk20a_instmem *imem = gk20a_instobj(memory)->imem;
- spin_unlock_irqrestore(&imem->lock, imem->lock_flags);
-}
+ struct gk20a_instobj *node = gk20a_instobj(memory);
+ struct gk20a_instmem *imem = node->imem;
+ struct nvkm_ltc *ltc = imem->base.subdev.device->ltc;
+ unsigned long flags;
-/*
- * Use PRAMIN to read/write data and avoid coherency issues.
- * PRAMIN uses the GPU path and ensures data will always be coherent.
- *
- * A dynamic mapping based solution would be desirable in the future, but
- * the issue remains of how to maintain coherency efficiently. On ARM it is
- * not easy (if possible at all?) to create uncached temporary mappings.
- */
+ spin_lock_irqsave(&imem->lock, flags);
+
+ /* add ourselves to the LRU list so our CPU mapping can be freed */
+ list_add_tail(&node->vaddr_node, &imem->vaddr_lru);
+
+ spin_unlock_irqrestore(&imem->lock, flags);
+
+ wmb();
+ nvkm_ltc_invalidate(ltc);
+}
static u32
gk20a_instobj_rd32(struct nvkm_memory *memory, u64 offset)
{
struct gk20a_instobj *node = gk20a_instobj(memory);
- struct gk20a_instmem *imem = node->imem;
- struct nvkm_device *device = imem->base.subdev.device;
- u64 base = (node->mem.offset + offset) & 0xffffff00000ULL;
- u64 addr = (node->mem.offset + offset) & 0x000000fffffULL;
- u32 data;
-
- if (unlikely(imem->addr != base)) {
- nvkm_wr32(device, 0x001700, base >> 16);
- imem->addr = base;
- }
- data = nvkm_rd32(device, 0x700000 + addr);
- return data;
+
+ return node->vaddr[offset / 4];
}
static void
gk20a_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data)
{
struct gk20a_instobj *node = gk20a_instobj(memory);
- struct gk20a_instmem *imem = node->imem;
- struct nvkm_device *device = imem->base.subdev.device;
- u64 base = (node->mem.offset + offset) & 0xffffff00000ULL;
- u64 addr = (node->mem.offset + offset) & 0x000000fffffULL;
- if (unlikely(imem->addr != base)) {
- nvkm_wr32(device, 0x001700, base >> 16);
- imem->addr = base;
- }
- nvkm_wr32(device, 0x700000 + addr, data);
+ node->vaddr[offset / 4] = data;
}
static void
gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset)
{
struct gk20a_instobj *node = gk20a_instobj(memory);
+
nvkm_vm_map_at(vma, offset, &node->mem);
}
+/*
+ * Clear the CPU mapping of an instobj if it exists
+ */
static void
-gk20a_instobj_dtor_dma(struct gk20a_instobj *_node)
+gk20a_instobj_dtor(struct gk20a_instobj *node)
+{
+ struct gk20a_instmem *imem = node->imem;
+ struct gk20a_instobj *obj;
+ unsigned long flags;
+
+ spin_lock_irqsave(&imem->lock, flags);
+
+ if (!node->vaddr)
+ goto out;
+
+ list_for_each_entry(obj, &imem->vaddr_lru, vaddr_node) {
+ if (obj == node) {
+ list_del(&obj->vaddr_node);
+ break;
+ }
+ }
+ vunmap(node->vaddr);
+ node->vaddr = NULL;
+ imem->vaddr_use -= nvkm_memory_size(&node->memory);
+ nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n",
+ imem->vaddr_use, imem->vaddr_max);
+
+out:
+ spin_unlock_irqrestore(&imem->lock, flags);
+}
+
+static void *
+gk20a_instobj_dtor_dma(struct nvkm_memory *memory)
{
- struct gk20a_instobj_dma *node = (void *)_node;
- struct gk20a_instmem *imem = _node->imem;
+ struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory);
+ struct gk20a_instmem *imem = node->base.imem;
struct device *dev = imem->base.subdev.device->dev;
+ gk20a_instobj_dtor(&node->base);
+
if (unlikely(!node->cpuaddr))
- return;
+ goto out;
- dma_free_attrs(dev, _node->mem.size << PAGE_SHIFT, node->cpuaddr,
+ dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->cpuaddr,
node->handle, &imem->attrs);
+
+out:
+ return node;
}
-static void
-gk20a_instobj_dtor_iommu(struct gk20a_instobj *_node)
+static void *
+gk20a_instobj_dtor_iommu(struct nvkm_memory *memory)
{
- struct gk20a_instobj_iommu *node = (void *)_node;
- struct gk20a_instmem *imem = _node->imem;
+ struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory);
+ struct gk20a_instmem *imem = node->base.imem;
+ struct device *dev = imem->base.subdev.device->dev;
struct nvkm_mm_node *r;
int i;
- if (unlikely(list_empty(&_node->mem.regions)))
- return;
+ gk20a_instobj_dtor(&node->base);
+
+ if (unlikely(list_empty(&node->base.mem.regions)))
+ goto out;
- r = list_first_entry(&_node->mem.regions, struct nvkm_mm_node,
+ r = list_first_entry(&node->base.mem.regions, struct nvkm_mm_node,
rl_entry);
- /* clear bit 34 to unmap pages */
- r->offset &= ~BIT(34 - imem->iommu_pgshift);
+ /* clear IOMMU bit to unmap pages */
+ r->offset &= ~BIT(imem->iommu_bit - imem->iommu_pgshift);
/* Unmap pages from GPU address space and free them */
- for (i = 0; i < _node->mem.size; i++) {
+ for (i = 0; i < node->base.mem.size; i++) {
iommu_unmap(imem->domain,
(r->offset + i) << imem->iommu_pgshift, PAGE_SIZE);
+ dma_unmap_page(dev, node->dma_addrs[i], PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
__free_page(node->pages[i]);
}
@@ -218,25 +355,27 @@ gk20a_instobj_dtor_iommu(struct gk20a_instobj *_node)
mutex_lock(imem->mm_mutex);
nvkm_mm_free(imem->mm, &r);
mutex_unlock(imem->mm_mutex);
-}
-
-static void *
-gk20a_instobj_dtor(struct nvkm_memory *memory)
-{
- struct gk20a_instobj *node = gk20a_instobj(memory);
- struct gk20a_instmem *imem = node->imem;
-
- if (imem->domain)
- gk20a_instobj_dtor_iommu(node);
- else
- gk20a_instobj_dtor_dma(node);
+out:
return node;
}
static const struct nvkm_memory_func
-gk20a_instobj_func = {
- .dtor = gk20a_instobj_dtor,
+gk20a_instobj_func_dma = {
+ .dtor = gk20a_instobj_dtor_dma,
+ .target = gk20a_instobj_target,
+ .addr = gk20a_instobj_addr,
+ .size = gk20a_instobj_size,
+ .acquire = gk20a_instobj_acquire,
+ .release = gk20a_instobj_release,
+ .rd32 = gk20a_instobj_rd32,
+ .wr32 = gk20a_instobj_wr32,
+ .map = gk20a_instobj_map,
+};
+
+static const struct nvkm_memory_func
+gk20a_instobj_func_iommu = {
+ .dtor = gk20a_instobj_dtor_iommu,
.target = gk20a_instobj_target,
.addr = gk20a_instobj_addr,
.size = gk20a_instobj_size,
@@ -259,6 +398,8 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
return -ENOMEM;
*_node = &node->base;
+ nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory);
+
node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
&node->handle, GFP_KERNEL,
&imem->attrs);
@@ -292,24 +433,40 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
{
struct gk20a_instobj_iommu *node;
struct nvkm_subdev *subdev = &imem->base.subdev;
+ struct device *dev = subdev->device->dev;
struct nvkm_mm_node *r;
int ret;
int i;
- if (!(node = kzalloc(sizeof(*node) +
- sizeof( node->pages[0]) * npages, GFP_KERNEL)))
+ /*
+ * despite their variable size, instmem allocations are small enough
+ * (< 1 page) to be handled by kzalloc
+ */
+ if (!(node = kzalloc(sizeof(*node) + ((sizeof(node->pages[0]) +
+ sizeof(*node->dma_addrs)) * npages), GFP_KERNEL)))
return -ENOMEM;
*_node = &node->base;
+ node->dma_addrs = (void *)(node->pages + npages);
+
+ nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory);
/* Allocate backing memory */
for (i = 0; i < npages; i++) {
struct page *p = alloc_page(GFP_KERNEL);
+ dma_addr_t dma_adr;
if (p == NULL) {
ret = -ENOMEM;
goto free_pages;
}
node->pages[i] = p;
+ dma_adr = dma_map_page(dev, p, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, dma_adr)) {
+ nvkm_error(subdev, "DMA mapping error!\n");
+ ret = -ENOMEM;
+ goto free_pages;
+ }
+ node->dma_addrs[i] = dma_adr;
}
mutex_lock(imem->mm_mutex);
@@ -318,16 +475,15 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
align >> imem->iommu_pgshift, &r);
mutex_unlock(imem->mm_mutex);
if (ret) {
- nvkm_error(subdev, "virtual space is full!\n");
+ nvkm_error(subdev, "IOMMU space is full!\n");
goto free_pages;
}
/* Map into GPU address space */
for (i = 0; i < npages; i++) {
- struct page *p = node->pages[i];
u32 offset = (r->offset + i) << imem->iommu_pgshift;
- ret = iommu_map(imem->domain, offset, page_to_phys(p),
+ ret = iommu_map(imem->domain, offset, node->dma_addrs[i],
PAGE_SIZE, IOMMU_READ | IOMMU_WRITE);
if (ret < 0) {
nvkm_error(subdev, "IOMMU mapping failure: %d\n", ret);
@@ -340,8 +496,8 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
}
}
- /* Bit 34 tells that an address is to be resolved through the IOMMU */
- r->offset |= BIT(34 - imem->iommu_pgshift);
+ /* IOMMU bit tells that an address is to be resolved through the IOMMU */
+ r->offset |= BIT(imem->iommu_bit - imem->iommu_pgshift);
node->base.mem.offset = ((u64)r->offset) << imem->iommu_pgshift;
@@ -356,8 +512,13 @@ release_area:
mutex_unlock(imem->mm_mutex);
free_pages:
- for (i = 0; i < npages && node->pages[i] != NULL; i++)
+ for (i = 0; i < npages && node->pages[i] != NULL; i++) {
+ dma_addr_t dma_addr = node->dma_addrs[i];
+ if (dma_addr)
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
__free_page(node->pages[i]);
+ }
return ret;
}
@@ -367,8 +528,8 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
struct nvkm_memory **pmemory)
{
struct gk20a_instmem *imem = gk20a_instmem(base);
- struct gk20a_instobj *node = NULL;
struct nvkm_subdev *subdev = &imem->base.subdev;
+ struct gk20a_instobj *node = NULL;
int ret;
nvkm_debug(subdev, "%s (%s): size: %x align: %x\n", __func__,
@@ -388,7 +549,6 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
if (ret)
return ret;
- nvkm_memory_ctor(&gk20a_instobj_func, &node->memory);
node->imem = imem;
/* present memory for being mapped using small pages */
@@ -402,15 +562,25 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
return 0;
}
-static void
-gk20a_instmem_fini(struct nvkm_instmem *base)
+static void *
+gk20a_instmem_dtor(struct nvkm_instmem *base)
{
- gk20a_instmem(base)->addr = ~0ULL;
+ struct gk20a_instmem *imem = gk20a_instmem(base);
+
+ /* perform some sanity checks... */
+ if (!list_empty(&imem->vaddr_lru))
+ nvkm_warn(&base->subdev, "instobj LRU not empty!\n");
+
+ if (imem->vaddr_use != 0)
+ nvkm_warn(&base->subdev, "instobj vmap area not empty! "
+ "0x%x bytes still mapped\n", imem->vaddr_use);
+
+ return imem;
}
static const struct nvkm_instmem_func
gk20a_instmem = {
- .fini = gk20a_instmem_fini,
+ .dtor = gk20a_instmem_dtor,
.memory_new = gk20a_instobj_new,
.persistent = true,
.zero = false,
@@ -429,23 +599,28 @@ gk20a_instmem_new(struct nvkm_device *device, int index,
spin_lock_init(&imem->lock);
*pimem = &imem->base;
+ /* do not allow more than 1MB of CPU-mapped instmem */
+ imem->vaddr_use = 0;
+ imem->vaddr_max = 0x100000;
+ INIT_LIST_HEAD(&imem->vaddr_lru);
+
if (tdev->iommu.domain) {
- imem->domain = tdev->iommu.domain;
+ imem->mm_mutex = &tdev->iommu.mutex;
imem->mm = &tdev->iommu.mm;
+ imem->domain = tdev->iommu.domain;
imem->iommu_pgshift = tdev->iommu.pgshift;
- imem->mm_mutex = &tdev->iommu.mutex;
+ imem->cpu_map = gk20a_instobj_cpu_map_iommu;
+ imem->iommu_bit = tdev->func->iommu_bit;
nvkm_info(&imem->base.subdev, "using IOMMU\n");
} else {
init_dma_attrs(&imem->attrs);
- /*
- * We will access instmem through PRAMIN and thus do not need a
- * consistent CPU pointer or kernel mapping
- */
+ /* We will access the memory through our own mapping */
dma_set_attr(DMA_ATTR_NON_CONSISTENT, &imem->attrs);
dma_set_attr(DMA_ATTR_WEAK_ORDERING, &imem->attrs);
dma_set_attr(DMA_ATTR_WRITE_COMBINE, &imem->attrs);
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem->attrs);
+ imem->cpu_map = gk20a_instobj_cpu_map_dma;
nvkm_info(&imem->base.subdev, "using DMA API\n");
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
index 930d25b6e63c..85b1464c0194 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
@@ -67,6 +67,20 @@ nvkm_ltc_zbc_depth_get(struct nvkm_ltc *ltc, int index, const u32 depth)
return index;
}
+void
+nvkm_ltc_invalidate(struct nvkm_ltc *ltc)
+{
+ if (ltc->func->invalidate)
+ ltc->func->invalidate(ltc);
+}
+
+void
+nvkm_ltc_flush(struct nvkm_ltc *ltc)
+{
+ if (ltc->func->flush)
+ ltc->func->flush(ltc);
+}
+
static void
nvkm_ltc_intr(struct nvkm_subdev *subdev)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
index 45ac765b753e..fb0de83da13c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
@@ -122,6 +122,36 @@ gf100_ltc_intr(struct nvkm_ltc *ltc)
}
}
+void
+gf100_ltc_invalidate(struct nvkm_ltc *ltc)
+{
+ struct nvkm_device *device = ltc->subdev.device;
+ s64 taken;
+
+ nvkm_wr32(device, 0x70004, 0x00000001);
+ taken = nvkm_wait_msec(device, 2, 0x70004, 0x00000003, 0x00000000);
+ if (taken < 0)
+ nvkm_warn(&ltc->subdev, "LTC invalidate timeout\n");
+
+ if (taken > 0)
+ nvkm_debug(&ltc->subdev, "LTC invalidate took %lld ns\n", taken);
+}
+
+void
+gf100_ltc_flush(struct nvkm_ltc *ltc)
+{
+ struct nvkm_device *device = ltc->subdev.device;
+ s64 taken;
+
+ nvkm_wr32(device, 0x70010, 0x00000001);
+ taken = nvkm_wait_msec(device, 2, 0x70010, 0x00000003, 0x00000000);
+ if (taken < 0)
+ nvkm_warn(&ltc->subdev, "LTC flush timeout\n");
+
+ if (taken > 0)
+ nvkm_debug(&ltc->subdev, "LTC flush took %lld ns\n", taken);
+}
+
/* TODO: Figure out tag memory details and drop the over-cautious allocation.
*/
int
@@ -215,6 +245,8 @@ gf100_ltc = {
.zbc = 16,
.zbc_clear_color = gf100_ltc_zbc_clear_color,
.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
+ .invalidate = gf100_ltc_invalidate,
+ .flush = gf100_ltc_flush,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c
index 839e6b4c597b..b4f6e0034d58 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c
@@ -45,6 +45,8 @@ gk104_ltc = {
.zbc = 16,
.zbc_clear_color = gf100_ltc_zbc_clear_color,
.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
+ .invalidate = gf100_ltc_invalidate,
+ .flush = gf100_ltc_flush,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
index 389331bb63ba..3043bbfd7384 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
@@ -138,6 +138,8 @@ gm107_ltc = {
.zbc = 16,
.zbc_clear_color = gm107_ltc_zbc_clear_color,
.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
+ .invalidate = gf100_ltc_invalidate,
+ .flush = gf100_ltc_flush,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
index 4e05037cc99f..4e3755b82769 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
@@ -17,6 +17,9 @@ struct nvkm_ltc_func {
int zbc;
void (*zbc_clear_color)(struct nvkm_ltc *, int, const u32[4]);
void (*zbc_clear_depth)(struct nvkm_ltc *, int, const u32);
+
+ void (*invalidate)(struct nvkm_ltc *);
+ void (*flush)(struct nvkm_ltc *);
};
int gf100_ltc_oneinit(struct nvkm_ltc *);
@@ -26,4 +29,6 @@ void gf100_ltc_cbc_clear(struct nvkm_ltc *, u32, u32);
void gf100_ltc_cbc_wait(struct nvkm_ltc *);
void gf100_ltc_zbc_clear_color(struct nvkm_ltc *, int, const u32[4]);
void gf100_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32);
+void gf100_ltc_invalidate(struct nvkm_ltc *);
+void gf100_ltc_flush(struct nvkm_ltc *);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild
index 99672c3d0bad..4476ef75acd6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild
@@ -2,6 +2,8 @@ nvkm-y += nvkm/subdev/pci/agp.o
nvkm-y += nvkm/subdev/pci/base.o
nvkm-y += nvkm/subdev/pci/nv04.o
nvkm-y += nvkm/subdev/pci/nv40.o
+nvkm-y += nvkm/subdev/pci/nv46.o
nvkm-y += nvkm/subdev/pci/nv4c.o
-nvkm-y += nvkm/subdev/pci/nv50.o
+nvkm-y += nvkm/subdev/pci/g84.o
+nvkm-y += nvkm/subdev/pci/g94.o
nvkm-y += nvkm/subdev/pci/gf100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
index 814cb51cc873..385a90f91ed6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
@@ -35,6 +35,8 @@ static const struct nvkm_device_agp_quirk
nvkm_device_agp_quirks[] = {
/* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */
{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
+ /* SiS 761 does not support AGP cards, use PCI mode */
+ { PCI_VENDOR_ID_SI, 0x0761, PCI_ANY_ID, PCI_ANY_ID, 0 },
{},
};
@@ -137,8 +139,10 @@ nvkm_agp_ctor(struct nvkm_pci *pci)
while (quirk->hostbridge_vendor) {
if (info.device->vendor == quirk->hostbridge_vendor &&
info.device->device == quirk->hostbridge_device &&
- pci->pdev->vendor == quirk->chip_vendor &&
- pci->pdev->device == quirk->chip_device) {
+ (quirk->chip_vendor == (u16)PCI_ANY_ID ||
+ pci->pdev->vendor == quirk->chip_vendor) &&
+ (quirk->chip_device == (u16)PCI_ANY_ID ||
+ pci->pdev->device == quirk->chip_device)) {
nvkm_info(subdev, "forcing default agp mode to %dX, "
"use NvAGP=<mode> to override\n",
quirk->mode);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
index d1c148e51922..d671dcfaff3c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
@@ -46,6 +46,14 @@ nvkm_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data)
pci->func->wr32(pci, addr, data);
}
+u32
+nvkm_pci_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32 value)
+{
+ u32 data = pci->func->rd32(pci, addr);
+ pci->func->wr32(pci, addr, (data & ~mask) | value);
+ return data;
+}
+
void
nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow)
{
@@ -111,6 +119,9 @@ nvkm_pci_init(struct nvkm_subdev *subdev)
return ret;
}
+ if (pci->func->init)
+ pci->func->init(pci);
+
ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c
new file mode 100644
index 000000000000..3faa6bfb895b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+#include <core/pci.h>
+
+void
+g84_pci_init(struct nvkm_pci *pci)
+{
+ /* The following only concerns PCIe cards. */
+ if (!pci_is_pcie(pci->pdev))
+ return;
+
+ /* Tag field is 8-bit long, regardless of EXT_TAG.
+ * However, if EXT_TAG is disabled, only the lower 5 bits of the tag
+ * field should be used, limiting the number of request to 32.
+ *
+ * Apparently, 0x041c stores some limit on the number of requests
+ * possible, so if EXT_TAG is disabled, limit that requests number to
+ * 32
+ *
+ * Fixes fdo#86537
+ */
+ if (nvkm_pci_rd32(pci, 0x007c) & 0x00000020)
+ nvkm_pci_mask(pci, 0x0080, 0x00000100, 0x00000100);
+ else
+ nvkm_pci_mask(pci, 0x041c, 0x00000060, 0x00000000);
+}
+
+static const struct nvkm_pci_func
+g84_pci_func = {
+ .init = g84_pci_init,
+ .rd32 = nv40_pci_rd32,
+ .wr08 = nv40_pci_wr08,
+ .wr32 = nv40_pci_wr32,
+ .msi_rearm = nv46_pci_msi_rearm,
+};
+
+int
+g84_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci)
+{
+ return nvkm_pci_new_(&g84_pci_func, device, index, ppci);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c
new file mode 100644
index 000000000000..cd311ee311cc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+static const struct nvkm_pci_func
+g94_pci_func = {
+ .init = g84_pci_init,
+ .rd32 = nv40_pci_rd32,
+ .wr08 = nv40_pci_wr08,
+ .wr32 = nv40_pci_wr32,
+ .msi_rearm = nv40_pci_msi_rearm,
+};
+
+int
+g94_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci)
+{
+ return nvkm_pci_new_(&g94_pci_func, device, index, ppci);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c
index 86f8226532d3..25e1ae70867f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c
@@ -31,6 +31,7 @@ gf100_pci_msi_rearm(struct nvkm_pci *pci)
static const struct nvkm_pci_func
gf100_pci_func = {
+ .init = g84_pci_init,
.rd32 = nv40_pci_rd32,
.wr08 = nv40_pci_wr08,
.wr32 = nv40_pci_wr32,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c
index 090a187f165f..6eb417765802 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c
@@ -44,7 +44,7 @@ nv40_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data)
nvkm_wr32(device, 0x088000 + addr, data);
}
-static void
+void
nv40_pci_msi_rearm(struct nvkm_pci *pci)
{
nvkm_pci_wr08(pci, 0x0068, 0xff);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c
index 3e167d4a381f..fc617e4c0ab6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c
@@ -25,11 +25,11 @@
#include <core/pci.h>
-/* MSI re-arm through the PRI appears to be broken on the original G80,
+/* MSI re-arm through the PRI appears to be broken on NV46/NV50/G84/G86/G92,
* so we access it via alternate PCI config space mechanisms.
*/
-static void
-nv50_pci_msi_rearm(struct nvkm_pci *pci)
+void
+nv46_pci_msi_rearm(struct nvkm_pci *pci)
{
struct nvkm_device *device = pci->subdev.device;
struct pci_dev *pdev = device->func->pci(device)->pdev;
@@ -37,15 +37,15 @@ nv50_pci_msi_rearm(struct nvkm_pci *pci)
}
static const struct nvkm_pci_func
-nv50_pci_func = {
+nv46_pci_func = {
.rd32 = nv40_pci_rd32,
.wr08 = nv40_pci_wr08,
.wr32 = nv40_pci_wr32,
- .msi_rearm = nv50_pci_msi_rearm,
+ .msi_rearm = nv46_pci_msi_rearm,
};
int
-nv50_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci)
+nv46_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci)
{
- return nvkm_pci_new_(&nv50_pci_func, device, index, ppci);
+ return nvkm_pci_new_(&nv46_pci_func, device, index, ppci);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
index d22c2c117106..cf46d38d0b0a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
@@ -7,6 +7,7 @@ int nvkm_pci_new_(const struct nvkm_pci_func *, struct nvkm_device *,
int index, struct nvkm_pci **);
struct nvkm_pci_func {
+ void (*init)(struct nvkm_pci *);
u32 (*rd32)(struct nvkm_pci *, u16 addr);
void (*wr08)(struct nvkm_pci *, u16 addr, u8 data);
void (*wr32)(struct nvkm_pci *, u16 addr, u32 data);
@@ -16,4 +17,9 @@ struct nvkm_pci_func {
u32 nv40_pci_rd32(struct nvkm_pci *, u16);
void nv40_pci_wr08(struct nvkm_pci *, u16, u8);
void nv40_pci_wr32(struct nvkm_pci *, u16, u32);
+void nv40_pci_msi_rearm(struct nvkm_pci *);
+
+void nv46_pci_msi_rearm(struct nvkm_pci *);
+
+void g84_pci_init(struct nvkm_pci *pci);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index 27a79c0c3888..d95eb8659d1b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -28,7 +28,7 @@
void
nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
{
- if (pmu->func->pgob)
+ if (pmu && pmu->func->pgob)
pmu->func->pgob(pmu, enable);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
index e33f5c03b9ac..d942fa7b9f18 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
@@ -27,6 +27,7 @@
#include "fuc/gf119.fuc4.h"
#include <core/option.h>
+#include <subdev/fuse.h>
#include <subdev/timer.h>
static void
@@ -57,6 +58,9 @@ gk104_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
{
struct nvkm_device *device = pmu->subdev.device;
+ if (!(nvkm_fuse_read(device->fuse, 0x31c) & 0x00000001))
+ return;
+
nvkm_mask(device, 0x000200, 0x00001000, 0x00000000);
nvkm_rd32(device, 0x000200);
nvkm_mask(device, 0x000200, 0x08000000, 0x08000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
index 6b46ff4213a3..b035c6e28be8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
@@ -1,4 +1,5 @@
nvkm-y += nvkm/subdev/volt/base.o
nvkm-y += nvkm/subdev/volt/gpio.o
nvkm-y += nvkm/subdev/volt/nv40.o
+nvkm-y += nvkm/subdev/volt/gk104.o
nvkm-y += nvkm/subdev/volt/gk20a.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
index 4752dbd33923..50b5649ad1a4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
@@ -30,7 +30,12 @@
int
nvkm_volt_get(struct nvkm_volt *volt)
{
- int ret = volt->func->vid_get(volt), i;
+ int ret, i;
+
+ if (volt->func->volt_get)
+ return volt->func->volt_get(volt);
+
+ ret = volt->func->vid_get(volt);
if (ret >= 0) {
for (i = 0; i < volt->vid_nr; i++) {
if (volt->vid[i].vid == ret)
@@ -46,6 +51,10 @@ nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
{
struct nvkm_subdev *subdev = &volt->subdev;
int i, ret = -EINVAL;
+
+ if (volt->func->volt_set)
+ return volt->func->volt_set(volt, uv);
+
for (i = 0; i < volt->vid_nr; i++) {
if (volt->vid[i].uv == uv) {
ret = volt->func->vid_set(volt, volt->vid[i].vid);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
new file mode 100644
index 000000000000..b61509e26ec9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2015 Martin Peres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Martin Peres
+ */
+#include "priv.h"
+
+#include <subdev/volt.h>
+#include <subdev/gpio.h>
+#include <subdev/bios.h>
+#include <subdev/bios/volt.h>
+
+#define gk104_volt(p) container_of((p), struct gk104_volt, base)
+struct gk104_volt {
+ struct nvkm_volt base;
+ struct nvbios_volt bios;
+};
+
+int
+gk104_volt_get(struct nvkm_volt *base)
+{
+ struct nvbios_volt *bios = &gk104_volt(base)->bios;
+ struct nvkm_device *device = base->subdev.device;
+ u32 div, duty;
+
+ div = nvkm_rd32(device, 0x20340);
+ duty = nvkm_rd32(device, 0x20344);
+
+ return bios->base + bios->pwm_range * duty / div;
+}
+
+int
+gk104_volt_set(struct nvkm_volt *base, u32 uv)
+{
+ struct nvbios_volt *bios = &gk104_volt(base)->bios;
+ struct nvkm_device *device = base->subdev.device;
+ u32 div, duty;
+
+ /* the blob uses this crystal frequency, let's use it too. */
+ div = 27648000 / bios->pwm_freq;
+ duty = (uv - bios->base) * div / bios->pwm_range;
+
+ nvkm_wr32(device, 0x20340, div);
+ nvkm_wr32(device, 0x20344, 0x8000000 | duty);
+
+ return 0;
+}
+
+static const struct nvkm_volt_func
+gk104_volt_pwm = {
+ .volt_get = gk104_volt_get,
+ .volt_set = gk104_volt_set,
+}, gk104_volt_gpio = {
+ .vid_get = nvkm_voltgpio_get,
+ .vid_set = nvkm_voltgpio_set,
+};
+
+int
+gk104_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
+{
+ const struct nvkm_volt_func *volt_func = &gk104_volt_gpio;
+ struct dcb_gpio_func gpio;
+ struct nvbios_volt bios;
+ struct gk104_volt *volt;
+ u8 ver, hdr, cnt, len;
+ const char *mode;
+
+ if (!nvbios_volt_parse(device->bios, &ver, &hdr, &cnt, &len, &bios))
+ return 0;
+
+ if (!nvkm_gpio_find(device->gpio, 0, DCB_GPIO_VID_PWM, 0xff, &gpio) &&
+ bios.type == NVBIOS_VOLT_PWM) {
+ volt_func = &gk104_volt_pwm;
+ }
+
+ if (!(volt = kzalloc(sizeof(*volt), GFP_KERNEL)))
+ return -ENOMEM;
+ nvkm_volt_ctor(volt_func, device, index, &volt->base);
+ *pvolt = &volt->base;
+ volt->bios = bios;
+
+ /* now that we have a subdev, we can show an error if we found through
+ * the voltage table that we were supposed to use the PWN mode but we
+ * did not find the right GPIO for it.
+ */
+ if (bios.type == NVBIOS_VOLT_PWM && volt_func != &gk104_volt_pwm) {
+ nvkm_error(&volt->base.subdev,
+ "Type mismatch between the voltage table type and "
+ "the GPIO table. Fallback to GPIO mode.\n");
+ }
+
+ if (volt_func == &gk104_volt_gpio) {
+ nvkm_voltgpio_init(&volt->base);
+ mode = "GPIO";
+ } else
+ mode = "PWM";
+
+ nvkm_debug(&volt->base.subdev, "Using %s mode\n", mode);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
index 394f37c723af..d5140d991161 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
@@ -9,6 +9,8 @@ int nvkm_volt_new_(const struct nvkm_volt_func *, struct nvkm_device *,
int index, struct nvkm_volt **);
struct nvkm_volt_func {
+ int (*volt_get)(struct nvkm_volt *);
+ int (*volt_set)(struct nvkm_volt *, u32 uv);
int (*vid_get)(struct nvkm_volt *);
int (*vid_set)(struct nvkm_volt *, u8 vid);
int (*set_id)(struct nvkm_volt *, u8 id, int condition);
@@ -17,4 +19,8 @@ struct nvkm_volt_func {
int nvkm_voltgpio_init(struct nvkm_volt *);
int nvkm_voltgpio_get(struct nvkm_volt *);
int nvkm_voltgpio_set(struct nvkm_volt *, u8);
+
+int nvkm_voltpwm_init(struct nvkm_volt *volt);
+int nvkm_voltpwm_get(struct nvkm_volt *volt);
+int nvkm_voltpwm_set(struct nvkm_volt *volt, u32 uv);
#endif
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 9a4ba4f03567..ad09590e8a46 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -412,9 +412,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
dispc_mgr_go(omap_crtc->channel);
omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
}
-
- crtc->invert_dimensions = !!(crtc->primary->state->rotation &
- (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270)));
}
static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 419c2e49adf5..5c6609cbb6a2 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -96,7 +96,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
dispc_runtime_get();
drm_atomic_helper_commit_modeset_disables(dev, old_state);
- drm_atomic_helper_commit_planes(dev, old_state);
+ drm_atomic_helper_commit_planes(dev, old_state, false);
drm_atomic_helper_commit_modeset_enables(dev, old_state);
omap_atomic_wait_for_completion(dev, old_state);
@@ -626,12 +626,12 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
}
static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
- DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_UNLOCKED|DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_AUTH),
};
/*
@@ -753,7 +753,7 @@ static void dev_lastclose(struct drm_device *dev)
{
int i;
- /* we don't support vga-switcheroo.. so just make sure the fbdev
+ /* we don't support vga_switcheroo.. so just make sure the fbdev
* mode is active
*/
struct omap_drm_private *priv = dev->dev_private;
@@ -839,7 +839,7 @@ static struct drm_driver omap_drm_driver = {
.preclose = dev_preclose,
.postclose = dev_postclose,
.set_busid = drm_platform_set_busid,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = omap_irq_enable_vblank,
.disable_vblank = omap_irq_disable_vblank,
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 12081e61d45a..5c367aad8a6e 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -129,8 +129,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
int omap_gem_resume(struct device *dev);
#endif
-int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id);
-void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id);
+int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe);
+void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe);
void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 51b1219af87f..636a1f921569 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -171,7 +171,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
uint32_t w = win->src_w;
uint32_t h = win->src_h;
- switch (win->rotation & 0xf) {
+ switch (win->rotation & DRM_ROTATE_MASK) {
default:
dev_err(fb->dev->dev, "invalid rotation: %02x",
(uint32_t)win->rotation);
@@ -209,7 +209,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
info->rotation_type = OMAP_DSS_ROT_TILER;
info->screen_width = omap_gem_tiled_stride(plane->bo, orient);
} else {
- switch (win->rotation & 0xf) {
+ switch (win->rotation & DRM_ROTATE_MASK) {
case 0:
case BIT(DRM_ROTATE_0):
/* OK */
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index 0cc71c9d08d5..27c297672076 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -140,15 +140,12 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
struct vm_area_struct *vma)
{
struct drm_gem_object *obj = buffer->priv;
- struct drm_device *dev = obj->dev;
int ret = 0;
if (WARN_ON(!obj->filp))
return -EINVAL;
- mutex_lock(&dev->struct_mutex);
ret = drm_gem_mmap_obj(obj, omap_gem_mmap_size(obj), vma);
- mutex_unlock(&dev->struct_mutex);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 249c0330d6ce..60e1e8016708 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -134,7 +134,7 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
/**
* enable_vblank - enable vblank interrupt events
* @dev: DRM device
- * @crtc: which irq to enable
+ * @pipe: which irq to enable
*
* Enable vblank interrupts for @crtc. If the device doesn't have
* a hardware vblank counter, this routine should be a no-op, since
@@ -144,13 +144,13 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
* Zero on success, appropriate errno if the given @crtc's vblank
* interrupt cannot be enabled.
*/
-int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id)
+int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct omap_drm_private *priv = dev->dev_private;
- struct drm_crtc *crtc = priv->crtcs[crtc_id];
+ struct drm_crtc *crtc = priv->crtcs[pipe];
unsigned long flags;
- DBG("dev=%p, crtc=%d", dev, crtc_id);
+ DBG("dev=%p, crtc=%u", dev, pipe);
spin_lock_irqsave(&list_lock, flags);
priv->vblank_mask |= pipe2vbl(crtc);
@@ -163,19 +163,19 @@ int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id)
/**
* disable_vblank - disable vblank interrupt events
* @dev: DRM device
- * @crtc: which irq to enable
+ * @pipe: which irq to enable
*
* Disable vblank interrupts for @crtc. If the device doesn't have
* a hardware vblank counter, this routine should be a no-op, since
* interrupts will have to stay on to keep the count accurate.
*/
-void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id)
+void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct omap_drm_private *priv = dev->dev_private;
- struct drm_crtc *crtc = priv->crtcs[crtc_id];
+ struct drm_crtc *crtc = priv->crtcs[pipe];
unsigned long flags;
- DBG("dev=%p, crtc=%d", dev, crtc_id);
+ DBG("dev=%p, crtc=%u", dev, pipe);
spin_lock_irqsave(&list_lock, flags);
priv->vblank_mask &= ~pipe2vbl(crtc);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 098904696a5c..3054bda72688 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -60,17 +60,19 @@ to_omap_plane_state(struct drm_plane_state *state)
}
static int omap_plane_prepare_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
- return omap_framebuffer_pin(fb);
+ if (!new_state->fb)
+ return 0;
+
+ return omap_framebuffer_pin(new_state->fb);
}
static void omap_plane_cleanup_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *old_state)
{
- omap_framebuffer_unpin(fb);
+ if (old_state->fb)
+ omap_framebuffer_unpin(old_state->fb);
}
static void omap_plane_atomic_update(struct drm_plane *plane,
@@ -106,7 +108,7 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
win.src_x = state->src_x >> 16;
win.src_y = state->src_y >> 16;
- switch (state->rotation & 0xf) {
+ switch (state->rotation & DRM_ROTATE_MASK) {
case BIT(DRM_ROTATE_90):
case BIT(DRM_ROTATE_270):
win.src_w = state->src_h >> 16;
diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c
index a7b4939cee6d..6989238b276a 100644
--- a/drivers/gpu/drm/panel/panel-lg-lg4573.c
+++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c
@@ -287,7 +287,6 @@ static struct spi_driver lg4573_driver = {
.remove = lg4573_remove,
.driver = {
.name = "lg4573",
- .owner = THIS_MODULE,
.of_match_table = lg4573_of_match,
},
};
diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c
index b202377135e7..3cf4cf6a6942 100644
--- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c
+++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c
@@ -378,7 +378,6 @@ static struct spi_driver ld9040_driver = {
.remove = ld9040_remove,
.driver = {
.name = "panel-samsung-ld9040",
- .owner = THIS_MODULE,
.of_match_table = ld9040_of_match,
},
};
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 4649bd2ed340..183aea1abebc 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -244,6 +244,10 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
ret = qxl_bo_reserve(bo, false);
if (ret)
return ret;
+ ret = qxl_bo_pin(bo, bo->type, NULL);
+ qxl_bo_unreserve(bo);
+ if (ret)
+ return ret;
qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0,
&norect, one_clip_rect, inc);
@@ -257,7 +261,11 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
}
drm_vblank_put(dev, qcrtc->index);
- qxl_bo_unreserve(bo);
+ ret = qxl_bo_reserve(bo, false);
+ if (!ret) {
+ qxl_bo_unpin(bo);
+ qxl_bo_unreserve(bo);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 83f6f0b5e9ef..7307b07fe06b 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -196,17 +196,18 @@ static int qxl_pm_restore(struct device *dev)
return qxl_drm_resume(drm_dev, false);
}
-static u32 qxl_noop_get_vblank_counter(struct drm_device *dev, int crtc)
+static u32 qxl_noop_get_vblank_counter(struct drm_device *dev,
+ unsigned int pipe)
{
return 0;
}
-static int qxl_noop_enable_vblank(struct drm_device *dev, int crtc)
+static int qxl_noop_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
return 0;
}
-static void qxl_noop_disable_vblank(struct drm_device *dev, int crtc)
+static void qxl_noop_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
}
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 41c422fee31a..c4a552637c93 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -144,14 +144,17 @@ static void qxl_dirty_update(struct qxl_fbdev *qfbdev,
spin_lock_irqsave(&qfbdev->dirty.lock, flags);
- if (qfbdev->dirty.y1 < y)
- y = qfbdev->dirty.y1;
- if (qfbdev->dirty.y2 > y2)
- y2 = qfbdev->dirty.y2;
- if (qfbdev->dirty.x1 < x)
- x = qfbdev->dirty.x1;
- if (qfbdev->dirty.x2 > x2)
- x2 = qfbdev->dirty.x2;
+ if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) &&
+ (qfbdev->dirty.x2 - qfbdev->dirty.x1)) {
+ if (qfbdev->dirty.y1 < y)
+ y = qfbdev->dirty.y1;
+ if (qfbdev->dirty.y2 > y2)
+ y2 = qfbdev->dirty.y2;
+ if (qfbdev->dirty.x1 < x)
+ x = qfbdev->dirty.x1;
+ if (qfbdev->dirty.x2 > x2)
+ x2 = qfbdev->dirty.x2;
+ }
qfbdev->dirty.x1 = x;
qfbdev->dirty.x2 = x2;
diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
index bda5c5f80c24..2ae8577497ca 100644
--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
+++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
@@ -422,21 +422,21 @@ static int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data,
}
const struct drm_ioctl_desc qxl_ioctls[] = {
- DRM_IOCTL_DEF_DRV(QXL_ALLOC, qxl_alloc_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(QXL_ALLOC, qxl_alloc_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(QXL_MAP, qxl_map_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(QXL_MAP, qxl_map_ioctl, DRM_AUTH),
DRM_IOCTL_DEF_DRV(QXL_EXECBUFFER, qxl_execbuffer_ioctl,
- DRM_AUTH|DRM_UNLOCKED),
+ DRM_AUTH),
DRM_IOCTL_DEF_DRV(QXL_UPDATE_AREA, qxl_update_area_ioctl,
- DRM_AUTH|DRM_UNLOCKED),
+ DRM_AUTH),
DRM_IOCTL_DEF_DRV(QXL_GETPARAM, qxl_getparam_ioctl,
- DRM_AUTH|DRM_UNLOCKED),
+ DRM_AUTH),
DRM_IOCTL_DEF_DRV(QXL_CLIENTCAP, qxl_clientcap_ioctl,
- DRM_AUTH|DRM_UNLOCKED),
+ DRM_AUTH),
DRM_IOCTL_DEF_DRV(QXL_ALLOC_SURF, qxl_alloc_surf_ioctl,
- DRM_AUTH|DRM_UNLOCKED),
+ DRM_AUTH),
};
int qxl_max_ioctls = ARRAY_SIZE(qxl_ioctls);
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index b66ec331c17c..4efa8e261baf 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -307,7 +307,7 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
if (idr_ret < 0)
return idr_ret;
- bo = qxl_bo_ref(to_qxl_bo(entry->tv.bo));
+ bo = to_qxl_bo(entry->tv.bo);
(*release)->release_offset = create_rel->release_offset + 64;
@@ -316,8 +316,6 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
info = qxl_release_map(qdev, *release);
info->id = idr_ret;
qxl_release_unmap(qdev, *release, info);
-
- qxl_bo_unref(&bo);
return 0;
}
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index 2c45ac9c1dc3..14fd83b5f497 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -311,7 +311,7 @@ static void r128_cce_init_ring_buffer(struct drm_device *dev,
/* The manual (p. 2) says this address is in "VM space". This
* means it's an offset from the start of AGP space.
*/
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (!dev_priv->is_pci)
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
else
@@ -505,7 +505,7 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
(drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
init->sarea_priv_offset);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (!dev_priv->is_pci) {
drm_legacy_ioremap_wc(dev_priv->cce_ring, dev);
drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev);
@@ -529,7 +529,7 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
(void *)(unsigned long)dev->agp_buffer_map->offset;
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (!dev_priv->is_pci)
dev_priv->cce_buffers_offset = dev->agp->base;
else
@@ -552,7 +552,7 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
dev_priv->sarea_priv->last_dispatch = 0;
R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->is_pci) {
#endif
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
@@ -568,7 +568,7 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
return -ENOMEM;
}
R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
}
#endif
@@ -600,7 +600,7 @@ int r128_do_cleanup_cce(struct drm_device *dev)
if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (!dev_priv->is_pci) {
if (dev_priv->cce_ring != NULL)
drm_legacy_ioremapfree(dev_priv->cce_ring, dev);
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 723e5d6f10a4..09143b840482 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -154,9 +154,9 @@ extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n);
extern int r128_do_cce_idle(drm_r128_private_t *dev_priv);
extern int r128_do_cleanup_cce(struct drm_device *dev);
-extern int r128_enable_vblank(struct drm_device *dev, int crtc);
-extern void r128_disable_vblank(struct drm_device *dev, int crtc);
-extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int r128_enable_vblank(struct drm_device *dev, unsigned int pipe);
+extern void r128_disable_vblank(struct drm_device *dev, unsigned int pipe);
+extern u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
extern irqreturn_t r128_driver_irq_handler(int irq, void *arg);
extern void r128_driver_irq_preinstall(struct drm_device *dev);
extern int r128_driver_irq_postinstall(struct drm_device *dev);
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
index c2ae496babb7..9730f4918944 100644
--- a/drivers/gpu/drm/r128/r128_irq.c
+++ b/drivers/gpu/drm/r128/r128_irq.c
@@ -34,11 +34,11 @@
#include <drm/r128_drm.h>
#include "r128_drv.h"
-u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
+u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
const drm_r128_private_t *dev_priv = dev->dev_private;
- if (crtc != 0)
+ if (pipe != 0)
return 0;
return atomic_read(&dev_priv->vbl_received);
@@ -62,12 +62,12 @@ irqreturn_t r128_driver_irq_handler(int irq, void *arg)
return IRQ_NONE;
}
-int r128_enable_vblank(struct drm_device *dev, int crtc)
+int r128_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
drm_r128_private_t *dev_priv = dev->dev_private;
- if (crtc != 0) {
- DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
+ if (pipe != 0) {
+ DRM_ERROR("%s: bad crtc %u\n", __func__, pipe);
return -EINVAL;
}
@@ -75,10 +75,10 @@ int r128_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-void r128_disable_vblank(struct drm_device *dev, int crtc)
+void r128_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
- if (crtc != 0)
- DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
+ if (pipe != 0)
+ DRM_ERROR("%s: bad crtc %u\n", __func__, pipe);
/*
* FIXME: implement proper interrupt disable by using the vblank
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 9cd49c584263..bd73b4069069 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -179,6 +179,7 @@ radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_NATIVE_WRITE:
case DP_AUX_I2C_WRITE:
+ case DP_AUX_I2C_WRITE_STATUS_UPDATE:
/* The atom implementation only supports writes with a max payload of
* 12 bytes since it uses 4 bits for the total count (header + payload)
* in the parameter space. The atom interface supports 16 byte
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 65adb9c72377..bb292143997e 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -237,6 +237,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
backlight_update_status(bd);
DRM_INFO("radeon atom DIG backlight initialized\n");
+ rdev->mode_info.bl_encoder = radeon_encoder;
return;
@@ -1624,9 +1625,14 @@ radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
} else
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
- struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+ if (rdev->mode_info.bl_encoder) {
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ } else {
+ args.ucAction = ATOM_LCD_BLON;
+ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+ }
}
break;
case DRM_MODE_DPMS_STANDBY:
@@ -1706,8 +1712,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
}
- if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
- atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+ if (rdev->mode_info.bl_encoder)
+ atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ else
+ atombios_dig_transmitter_setup(encoder,
+ ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+ }
if (ext_encoder)
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
break;
diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c
index 98d009e154bf..9fec4d09f383 100644
--- a/drivers/gpu/drm/radeon/cayman_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c
@@ -32,7 +32,7 @@
* evergreen cards need to use the 3D engine to blit data which requires
* quite a bit of hw state setup. Rather than pull the whole 3D driver
* (which normally generates the 3D state) into the DRM, we opt to use
- * statically generated state tables. The regsiter state and shaders
+ * statically generated state tables. The register state and shaders
* were hand generated to support blitting functionality. See the 3D
* driver or documentation for descriptions of the registers and
* shader instructions.
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0acde1949c18..7f33767d7ed6 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1404,44 +1404,20 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
* @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address)
*
- * Does the actual pageflip (evergreen+).
- * During vblank we take the crtc lock and wait for the update_pending
- * bit to go high, when it does, we release the lock, and allow the
- * double buffered update to take place.
- * Returns the current update pending status.
+ * Triggers the actual pageflip by updating the primary
+ * surface base address (evergreen+).
*/
void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
- u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
- int i;
-
- /* Lock the graphics update lock */
- tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
- WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
/* update the scanout addresses */
- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
- upper_32_bits(crtc_base));
- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
- (u32)crtc_base);
-
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32)crtc_base);
-
- /* Wait for update_pending to go high. */
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
- break;
- udelay(1);
- }
- DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
-
- /* Unlock the lock, so double-buffering can take place inside vblank */
- tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
- WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+ /* post the write */
+ RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset);
}
/**
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
index d43383470cdf..1a96ddb3e5ed 100644
--- a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
@@ -32,7 +32,7 @@
* evergreen cards need to use the 3D engine to blit data which requires
* quite a bit of hw state setup. Rather than pull the whole 3D driver
* (which normally generates the 3D state) into the DRM, we opt to use
- * statically generated state tables. The regsiter state and shaders
+ * statically generated state tables. The register state and shaders
* were hand generated to support blitting functionality. See the 3D
* driver or documentation for descriptions of the registers and
* shader instructions.
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index c9e0fbbf76a3..46f87d4aaf31 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -34,6 +34,8 @@
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
+#define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm)
+
int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
struct radeon_bo_list **cs_reloc);
struct evergreen_cs_track {
@@ -84,6 +86,7 @@ struct evergreen_cs_track {
u32 htile_surface;
struct radeon_bo *htile_bo;
unsigned long indirect_draw_buffer_size;
+ const unsigned *reg_safe_bm;
};
static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
@@ -444,7 +447,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
* command stream.
*/
if (!surf.mode) {
- volatile u32 *ib = p->ib.ptr;
+ uint32_t *ib = p->ib.ptr;
unsigned long tmp, nby, bsize, size, min = 0;
/* find the height the ddx wants */
@@ -1083,41 +1086,18 @@ static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
}
/**
- * evergreen_cs_check_reg() - check if register is authorized or not
+ * evergreen_cs_handle_reg() - process registers that need special handling.
* @parser: parser structure holding parsing context
* @reg: register we are testing
* @idx: index into the cs buffer
- *
- * This function will test against evergreen_reg_safe_bm and return 0
- * if register is safe. If register is not flag as safe this function
- * will test it against a list of register needind special handling.
*/
-static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int evergreen_cs_handle_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
{
struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
struct radeon_bo_list *reloc;
- u32 last_reg;
- u32 m, i, tmp, *ib;
+ u32 tmp, *ib;
int r;
- if (p->rdev->family >= CHIP_CAYMAN)
- last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
- else
- last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
-
- i = (reg >> 7);
- if (i >= last_reg) {
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return -EINVAL;
- }
- m = 1 << ((reg >> 2) & 31);
- if (p->rdev->family >= CHIP_CAYMAN) {
- if (!(cayman_reg_safe_bm[i] & m))
- return 0;
- } else {
- if (!(evergreen_reg_safe_bm[i] & m))
- return 0;
- }
ib = p->ib.ptr;
switch (reg) {
/* force following reg to 0 in an attempt to disable out buffer
@@ -1764,29 +1744,27 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
return 0;
}
-static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+/**
+ * evergreen_is_safe_reg() - check if register is authorized or not
+ * @parser: parser structure holding parsing context
+ * @reg: register we are testing
+ *
+ * This function will test against reg_safe_bm and return true
+ * if register is safe or false otherwise.
+ */
+static inline bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg)
{
- u32 last_reg, m, i;
-
- if (p->rdev->family >= CHIP_CAYMAN)
- last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
- else
- last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+ struct evergreen_cs_track *track = p->track;
+ u32 m, i;
i = (reg >> 7);
- if (i >= last_reg) {
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+ if (unlikely(i >= REG_SAFE_BM_SIZE)) {
return false;
}
m = 1 << ((reg >> 2) & 31);
- if (p->rdev->family >= CHIP_CAYMAN) {
- if (!(cayman_reg_safe_bm[i] & m))
- return true;
- } else {
- if (!(evergreen_reg_safe_bm[i] & m))
- return true;
- }
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+ if (!(track->reg_safe_bm[i] & m))
+ return true;
+
return false;
}
@@ -1795,7 +1773,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
{
struct radeon_bo_list *reloc;
struct evergreen_cs_track *track;
- volatile u32 *ib;
+ uint32_t *ib;
unsigned idx;
unsigned i;
unsigned start_reg, end_reg, reg;
@@ -2321,9 +2299,10 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
return -EINVAL;
}
- for (i = 0; i < pkt->count; i++) {
- reg = start_reg + (4 * i);
- r = evergreen_cs_check_reg(p, reg, idx+1+i);
+ for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) {
+ if (evergreen_is_safe_reg(p, reg))
+ continue;
+ r = evergreen_cs_handle_reg(p, reg, idx);
if (r)
return r;
}
@@ -2337,9 +2316,10 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
return -EINVAL;
}
- for (i = 0; i < pkt->count; i++) {
- reg = start_reg + (4 * i);
- r = evergreen_cs_check_reg(p, reg, idx+1+i);
+ for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) {
+ if (evergreen_is_safe_reg(p, reg))
+ continue;
+ r = evergreen_cs_handle_reg(p, reg, idx);
if (r)
return r;
}
@@ -2594,8 +2574,11 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
} else {
/* SRC is a reg. */
reg = radeon_get_ib_value(p, idx+1) << 2;
- if (!evergreen_is_safe_reg(p, reg, idx+1))
+ if (!evergreen_is_safe_reg(p, reg)) {
+ dev_warn(p->dev, "forbidden register 0x%08x at %d\n",
+ reg, idx + 1);
return -EINVAL;
+ }
}
if (idx_value & 0x2) {
u64 offset;
@@ -2618,8 +2601,11 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
} else {
/* DST is a reg. */
reg = radeon_get_ib_value(p, idx+3) << 2;
- if (!evergreen_is_safe_reg(p, reg, idx+3))
+ if (!evergreen_is_safe_reg(p, reg)) {
+ dev_warn(p->dev, "forbidden register 0x%08x at %d\n",
+ reg, idx + 3);
return -EINVAL;
+ }
}
break;
case PACKET3_NOP:
@@ -2644,11 +2630,15 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
if (track == NULL)
return -ENOMEM;
evergreen_cs_track_init(track);
- if (p->rdev->family >= CHIP_CAYMAN)
+ if (p->rdev->family >= CHIP_CAYMAN) {
tmp = p->rdev->config.cayman.tile_config;
- else
+ track->reg_safe_bm = cayman_reg_safe_bm;
+ } else {
tmp = p->rdev->config.evergreen.tile_config;
-
+ track->reg_safe_bm = evergreen_reg_safe_bm;
+ }
+ BUILD_BUG_ON(ARRAY_SIZE(cayman_reg_safe_bm) != REG_SAFE_BM_SIZE);
+ BUILD_BUG_ON(ARRAY_SIZE(evergreen_reg_safe_bm) != REG_SAFE_BM_SIZE);
switch (tmp & 0xf) {
case 0:
track->npipes = 1;
@@ -2757,7 +2747,7 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
struct radeon_cs_chunk *ib_chunk = p->chunk_ib;
struct radeon_bo_list *src_reloc, *dst_reloc, *dst2_reloc;
u32 header, cmd, count, sub_cmd;
- volatile u32 *ib = p->ib.ptr;
+ uint32_t *ib = p->ib.ptr;
u32 idx;
u64 src_offset, dst_offset, dst2_offset;
int r;
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.c b/drivers/gpu/drm/radeon/r600_blit_shaders.c
index 34c8b2340f33..443cbe59b274 100644
--- a/drivers/gpu/drm/radeon/r600_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/r600_blit_shaders.c
@@ -32,7 +32,7 @@
* R6xx+ cards need to use the 3D engine to blit data which requires
* quite a bit of hw state setup. Rather than pull the whole 3D driver
* (which normally generates the 3D state) into the DRM, we opt to use
- * statically generated state tables. The regsiter state and shaders
+ * statically generated state tables. The register state and shaders
* were hand generated to support blitting functionality. See the 3D
* driver or documentation for descriptions of the registers and
* shader instructions.
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 98f9adaccc3d..e231eeafef23 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -1837,7 +1837,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
SET_RING_HEAD(dev_priv, 0);
dev_priv->ring.tail = 0;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
rptr_addr = dev_priv->ring_rptr->offset
- dev->agp->base +
@@ -1863,7 +1863,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
dev_priv->ring.size_l2qw);
#endif
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
/* XXX */
radeon_write_agp_base(dev_priv, dev->agp->base);
@@ -1946,7 +1946,7 @@ int r600_do_cleanup_cp(struct drm_device *dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
if (dev_priv->cp_ring != NULL) {
drm_legacy_ioremapfree(dev_priv->cp_ring, dev);
@@ -2089,7 +2089,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
}
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
/* XXX */
if (dev_priv->flags & RADEON_IS_AGP) {
drm_legacy_ioremap_wc(dev_priv->cp_ring, dev);
@@ -2148,7 +2148,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
* location in the card and on the bus, though we have to
* align it down.
*/
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
/* XXX */
if (dev_priv->flags & RADEON_IS_AGP) {
base = dev->agp->base;
@@ -2175,7 +2175,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
base, dev_priv->gart_vm_start);
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
/* XXX */
if (dev_priv->flags & RADEON_IS_AGP)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
@@ -2212,7 +2212,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
/* XXX turn off pcie gart */
} else
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f03b7eb15233..b6cbd816537e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1658,6 +1658,7 @@ struct radeon_pm {
u8 fan_max_rpm;
/* dpm */
bool dpm_enabled;
+ bool sysfs_initialized;
struct radeon_dpm dpm;
};
diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c
index 77e9d07c55b6..59acd0e5c2c6 100644
--- a/drivers/gpu/drm/radeon/radeon_acpi.c
+++ b/drivers/gpu/drm/radeon/radeon_acpi.c
@@ -25,7 +25,6 @@
#include <linux/acpi.h>
#include <linux/slab.h>
#include <linux/power_supply.h>
-#include <linux/vga_switcheroo.h>
#include <acpi/video.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c
index a9297b2c3524..fe994aac3b04 100644
--- a/drivers/gpu/drm/radeon/radeon_agp.c
+++ b/drivers/gpu/drm/radeon/radeon_agp.c
@@ -28,7 +28,7 @@
#include "radeon.h"
#include <drm/radeon_drm.h>
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
struct radeon_agpmode_quirk {
u32 hostbridge_vendor;
@@ -123,7 +123,7 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
int radeon_agp_init(struct radeon_device *rdev)
{
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list;
struct drm_agp_mode mode;
struct drm_agp_info info;
@@ -257,7 +257,7 @@ int radeon_agp_init(struct radeon_device *rdev)
void radeon_agp_resume(struct radeon_device *rdev)
{
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
int r;
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
@@ -269,7 +269,7 @@ void radeon_agp_resume(struct radeon_device *rdev)
void radeon_agp_fini(struct radeon_device *rdev)
{
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (rdev->ddev->agp && rdev->ddev->agp->acquired) {
drm_agp_release(rdev->ddev);
}
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index f2421bc3e901..1d4d4520a0ac 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -31,7 +31,6 @@
#include <drm/drm_crtc_helper.h>
#include <drm/radeon_drm.h>
#include <linux/vgaarb.h>
-#include <linux/vga_switcheroo.h>
#include "radeon_reg.h"
#include "radeon.h"
#include "radeon_asic.h"
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 8bc7d0bbd3c8..c4b4f298a283 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -499,7 +499,7 @@ static int radeon_atpx_get_client_id(struct pci_dev *pdev)
return VGA_SWITCHEROO_DIS;
}
-static struct vga_switcheroo_handler radeon_atpx_handler = {
+static const struct vga_switcheroo_handler radeon_atpx_handler = {
.switchto = radeon_atpx_switchto,
.power_state = radeon_atpx_power_state,
.init = radeon_atpx_init,
@@ -535,7 +535,7 @@ static bool radeon_atpx_detect(void)
if (has_atpx && vga_count == 2) {
acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
- printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
+ printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n",
acpi_method_name);
radeon_atpx_priv.atpx_detected = true;
return true;
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index d27e4ccb848c..21b6732425c5 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -30,7 +30,6 @@
#include "radeon.h"
#include "atom.h"
-#include <linux/vga_switcheroo.h>
#include <linux/slab.h>
#include <linux/acpi.h>
/*
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index ea134a7d51a5..500287eff55d 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -762,7 +762,7 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
((dev_priv->gart_vm_start - 1) & 0xffff0000)
| (dev_priv->fb_location >> 16));
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
radeon_write_agp_base(dev_priv, dev->agp->base);
@@ -791,7 +791,7 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
SET_RING_HEAD(dev_priv, cur_read_ptr);
dev_priv->ring.tail = cur_read_ptr;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
dev_priv->ring_rptr->offset
@@ -1335,7 +1335,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
}
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
drm_legacy_ioremap_wc(dev_priv->cp_ring, dev);
drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev);
@@ -1394,7 +1394,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
* location in the card and on the bus, though we have to
* align it down.
*/
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
base = dev->agp->base;
/* Check if valid */
@@ -1424,7 +1424,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
RADEON_READ(RADEON_CONFIG_APER_SIZE);
}
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- dev->agp->base
@@ -1455,7 +1455,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
@@ -1566,7 +1566,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
if (dev_priv->cp_ring != NULL) {
drm_legacy_ioremapfree(dev_priv->cp_ring, dev);
@@ -1625,7 +1625,7 @@ static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_pri
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (dev_priv->flags & RADEON_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index f3f562f6d848..c566993a2ec3 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1197,7 +1197,7 @@ static void radeon_check_arguments(struct radeon_device *rdev)
* radeon_switcheroo_set_state - set switcheroo state
*
* @pdev: pci dev pointer
- * @state: vga switcheroo state
+ * @state: vga_switcheroo state
*
* Callback for the switcheroo driver. Suspends or resumes the
* the asics before or after it is powered up using ACPI methods.
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index d2e9e9efc159..a8d9927ed9eb 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -323,7 +323,8 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
*/
if (update_pending &&
(DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
- &vpos, &hpos, NULL, NULL)) &&
+ &vpos, &hpos, NULL, NULL,
+ &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) &&
((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
(vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
/* crtc didn't flip in this target vblank interval,
@@ -1633,18 +1634,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
radeon_fbdev_init(rdev);
drm_kms_helper_poll_init(rdev->ddev);
- if (rdev->pm.dpm_enabled) {
- /* do dpm late init */
- ret = radeon_pm_late_init(rdev);
- if (ret) {
- rdev->pm.dpm_enabled = false;
- DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
- }
- /* set the dpm state for PX since there won't be
- * a modeset to call this.
- */
- radeon_pm_compute_clocks(rdev);
- }
+ /* do pm late init */
+ ret = radeon_pm_late_init(rdev);
return 0;
}
@@ -1798,8 +1789,10 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
* unknown small number of scanlines wrt. real scanout position.
*
*/
-int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
- int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+ unsigned int flags, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode)
{
u32 stat_crtc = 0, vbl = 0, position = 0;
int vbl_start, vbl_end, vtotal, ret = 0;
@@ -1814,42 +1807,42 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
*stime = ktime_get();
if (ASIC_IS_DCE4(rdev)) {
- if (crtc == 0) {
+ if (pipe == 0) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC0_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
EVERGREEN_CRTC0_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 1) {
+ if (pipe == 1) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC1_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
EVERGREEN_CRTC1_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 2) {
+ if (pipe == 2) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC2_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
EVERGREEN_CRTC2_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 3) {
+ if (pipe == 3) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC3_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
EVERGREEN_CRTC3_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 4) {
+ if (pipe == 4) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC4_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
EVERGREEN_CRTC4_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 5) {
+ if (pipe == 5) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC5_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
@@ -1857,19 +1850,19 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
ret |= DRM_SCANOUTPOS_VALID;
}
} else if (ASIC_IS_AVIVO(rdev)) {
- if (crtc == 0) {
+ if (pipe == 0) {
vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END);
position = RREG32(AVIVO_D1CRTC_STATUS_POSITION);
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 1) {
+ if (pipe == 1) {
vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END);
position = RREG32(AVIVO_D2CRTC_STATUS_POSITION);
ret |= DRM_SCANOUTPOS_VALID;
}
} else {
/* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */
- if (crtc == 0) {
+ if (pipe == 0) {
/* Assume vbl_end == 0, get vbl_start from
* upper 16 bits.
*/
@@ -1883,7 +1876,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
ret |= DRM_SCANOUTPOS_VALID;
}
- if (crtc == 1) {
+ if (pipe == 1) {
vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) &
RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT;
position = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
@@ -1914,7 +1907,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
}
else {
/* No: Fake something reasonable which gives at least ok results. */
- vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
+ vbl_start = mode->crtc_vdisplay;
vbl_end = 0;
}
@@ -1930,7 +1923,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
/* Inside "upper part" of vblank area? Apply corrective offset if so: */
if (in_vbl && (*vpos >= vbl_start)) {
- vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+ vtotal = mode->crtc_vtotal;
*vpos = *vpos - vtotal;
}
@@ -1952,8 +1945,8 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
- vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
- vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+ vbl_start = mode->crtc_vdisplay;
+ vtotal = mode->crtc_vtotal;
if (vbl_start - *vpos < vtotal / 100) {
*vpos -= vtotal;
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 6cddae44fa6e..744f5c49c664 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -283,6 +283,7 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master);
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
+ drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
drm_mode_connector_set_path_property(connector, pathprop);
return connector;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 5751446677d3..5b6a6f5b3619 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -105,10 +105,10 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
struct drm_file *file_priv);
int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
-u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);
-int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);
-void radeon_disable_vblank_kms(struct drm_device *dev, int crtc);
-int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
+int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
+void radeon_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
int *max_error,
struct timeval *vblank_time,
unsigned flags);
@@ -124,10 +124,10 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gobj,
int flags);
-extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
- unsigned int flags,
- int *vpos, int *hpos, ktime_t *stime,
- ktime_t *etime);
+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int crtc,
+ unsigned int flags, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode);
extern bool radeon_is_px(struct drm_device *dev);
extern const struct drm_ioctl_desc radeon_ioctls_kms[];
extern int radeon_max_kms_ioctl;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 46bd3938282c..0caafc7a6e17 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -404,9 +404,9 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
extern void radeon_do_release(struct drm_device * dev);
-extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
-extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
-extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 radeon_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
+extern int radeon_enable_vblank(struct drm_device *dev, unsigned int pipe);
+extern void radeon_disable_vblank(struct drm_device *dev, unsigned int pipe);
extern irqreturn_t radeon_driver_irq_handler(int irq, void *arg);
extern void radeon_driver_irq_preinstall(struct drm_device * dev);
extern int radeon_driver_irq_postinstall(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index ef99917f000d..c6ee80216cf4 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -194,7 +194,6 @@ static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
radeon_atom_backlight_init(radeon_encoder, connector);
else
radeon_legacy_backlight_init(radeon_encoder, connector);
- rdev->mode_info.bl_encoder = radeon_encoder;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 1aa657fe31cb..26da2f4d7b4f 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -397,3 +397,19 @@ void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector
{
drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
}
+
+void radeon_fbdev_restore_mode(struct radeon_device *rdev)
+{
+ struct radeon_fbdev *rfbdev = rdev->mode_info.rfbdev;
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ if (!rfbdev)
+ return;
+
+ fb_helper = &rfbdev->helper;
+
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+ if (ret)
+ DRM_DEBUG("failed to restore crtc mode\n");
+}
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
index 244b19bab2e7..688afb62f7c4 100644
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -62,12 +62,12 @@ static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
}
-int radeon_enable_vblank(struct drm_device *dev, int crtc)
+int radeon_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
- switch (crtc) {
+ switch (pipe) {
case 0:
r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
break;
@@ -75,12 +75,12 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc)
r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
break;
default:
- DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
- crtc);
+ DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
+ pipe);
return -EINVAL;
}
} else {
- switch (crtc) {
+ switch (pipe) {
case 0:
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
break;
@@ -88,8 +88,8 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc)
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
break;
default:
- DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
- crtc);
+ DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
+ pipe);
return -EINVAL;
}
}
@@ -97,12 +97,12 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-void radeon_disable_vblank(struct drm_device *dev, int crtc)
+void radeon_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
- switch (crtc) {
+ switch (pipe) {
case 0:
r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
break;
@@ -110,12 +110,12 @@ void radeon_disable_vblank(struct drm_device *dev, int crtc)
r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
break;
default:
- DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
- crtc);
+ DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
+ pipe);
break;
}
} else {
- switch (crtc) {
+ switch (pipe) {
case 0:
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
break;
@@ -123,8 +123,8 @@ void radeon_disable_vblank(struct drm_device *dev, int crtc)
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
break;
default:
- DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
- crtc);
+ DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
+ pipe);
break;
}
}
@@ -255,7 +255,7 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
return ret;
}
-u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
+u32 radeon_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -264,18 +264,18 @@ u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
return -EINVAL;
}
- if (crtc < 0 || crtc > 1) {
- DRM_ERROR("Invalid crtc %d\n", crtc);
+ if (pipe > 1) {
+ DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
- if (crtc == 0)
+ if (pipe == 0)
return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
else
return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
} else {
- if (crtc == 0)
+ if (pipe == 0)
return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
else
return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 4a119c255ba9..0ec6fcca16d3 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -181,7 +181,9 @@ static void radeon_set_filp_rights(struct drm_device *dev,
struct drm_file *applier,
uint32_t *value)
{
- mutex_lock(&dev->struct_mutex);
+ struct radeon_device *rdev = dev->dev_private;
+
+ mutex_lock(&rdev->gem.mutex);
if (*value == 1) {
/* wants rights */
if (!*owner)
@@ -192,7 +194,7 @@ static void radeon_set_filp_rights(struct drm_device *dev,
*owner = NULL;
}
*value = *owner == applier ? 1 : 0;
- mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&rdev->gem.mutex);
}
/*
@@ -598,14 +600,17 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
* Outdated mess for old drm with Xorg being in charge (void function now).
*/
/**
- * radeon_driver_firstopen_kms - drm callback for last close
+ * radeon_driver_lastclose_kms - drm callback for last close
*
* @dev: drm dev pointer
*
- * Switch vga switcheroo state after last close (all asics).
+ * Switch vga_switcheroo state after last close (all asics).
*/
void radeon_driver_lastclose_kms(struct drm_device *dev)
{
+ struct radeon_device *rdev = dev->dev_private;
+
+ radeon_fbdev_restore_mode(rdev);
vga_switcheroo_process_delayed_switch();
}
@@ -724,10 +729,14 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
struct drm_file *file_priv)
{
struct radeon_device *rdev = dev->dev_private;
+
+ mutex_lock(&rdev->gem.mutex);
if (rdev->hyperz_filp == file_priv)
rdev->hyperz_filp = NULL;
if (rdev->cmask_filp == file_priv)
rdev->cmask_filp = NULL;
+ mutex_unlock(&rdev->gem.mutex);
+
radeon_uvd_free_handles(rdev, file_priv);
radeon_vce_free_handles(rdev, file_priv);
}
@@ -841,92 +850,52 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
/* Helper routine in DRM core does all the work: */
return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
vblank_time, flags,
- drmcrtc, &drmcrtc->hwmode);
+ &drmcrtc->hwmode);
}
-#define KMS_INVALID_IOCTL(name) \
-static int name(struct drm_device *dev, void *data, struct drm_file \
- *file_priv) \
-{ \
- DRM_ERROR("invalid ioctl with kms %s\n", __func__); \
- return -EINVAL; \
-}
-
-/*
- * All these ioctls are invalid in kms world.
- */
-KMS_INVALID_IOCTL(radeon_cp_init_kms)
-KMS_INVALID_IOCTL(radeon_cp_start_kms)
-KMS_INVALID_IOCTL(radeon_cp_stop_kms)
-KMS_INVALID_IOCTL(radeon_cp_reset_kms)
-KMS_INVALID_IOCTL(radeon_cp_idle_kms)
-KMS_INVALID_IOCTL(radeon_cp_resume_kms)
-KMS_INVALID_IOCTL(radeon_engine_reset_kms)
-KMS_INVALID_IOCTL(radeon_fullscreen_kms)
-KMS_INVALID_IOCTL(radeon_cp_swap_kms)
-KMS_INVALID_IOCTL(radeon_cp_clear_kms)
-KMS_INVALID_IOCTL(radeon_cp_vertex_kms)
-KMS_INVALID_IOCTL(radeon_cp_indices_kms)
-KMS_INVALID_IOCTL(radeon_cp_texture_kms)
-KMS_INVALID_IOCTL(radeon_cp_stipple_kms)
-KMS_INVALID_IOCTL(radeon_cp_indirect_kms)
-KMS_INVALID_IOCTL(radeon_cp_vertex2_kms)
-KMS_INVALID_IOCTL(radeon_cp_cmdbuf_kms)
-KMS_INVALID_IOCTL(radeon_cp_getparam_kms)
-KMS_INVALID_IOCTL(radeon_cp_flip_kms)
-KMS_INVALID_IOCTL(radeon_mem_alloc_kms)
-KMS_INVALID_IOCTL(radeon_mem_free_kms)
-KMS_INVALID_IOCTL(radeon_mem_init_heap_kms)
-KMS_INVALID_IOCTL(radeon_irq_emit_kms)
-KMS_INVALID_IOCTL(radeon_irq_wait_kms)
-KMS_INVALID_IOCTL(radeon_cp_setparam_kms)
-KMS_INVALID_IOCTL(radeon_surface_alloc_kms)
-KMS_INVALID_IOCTL(radeon_surface_free_kms)
-
-
const struct drm_ioctl_desc radeon_ioctls_kms[] = {
- DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(RADEON_CP_START, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_RESET, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_SWAP, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_CLEAR, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_VERTEX, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_INDICES, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_FLIP, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_ALLOC, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_FREE, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, drm_invalid_op, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, drm_invalid_op, DRM_AUTH),
/* KMS */
- DRM_IOCTL_DEF_DRV(RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_OP, radeon_gem_op_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(RADEON_GEM_USERPTR, radeon_gem_userptr_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_OP, radeon_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(RADEON_GEM_USERPTR, radeon_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
};
int radeon_max_kms_ioctl = ARRAY_SIZE(radeon_ioctls_kms);
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 45715307db71..30de43366eae 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -441,6 +441,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
backlight_update_status(bd);
DRM_INFO("radeon legacy LVDS backlight initialized\n");
+ rdev->mode_info.bl_encoder = radeon_encoder;
return;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index aecc3e3dec0c..830e171c3a9e 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -874,10 +874,10 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
int x, int y);
extern void radeon_cursor_reset(struct drm_crtc *crtc);
-extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
- unsigned int flags,
- int *vpos, int *hpos, ktime_t *stime,
- ktime_t *etime);
+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+ unsigned int flags, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode);
extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
extern struct edid *
@@ -980,6 +980,7 @@ int radeon_fbdev_init(struct radeon_device *rdev);
void radeon_fbdev_fini(struct radeon_device *rdev);
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
+void radeon_fbdev_restore_mode(struct radeon_device *rdev);
void radeon_fb_output_poll_changed(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index d3024883b844..84d45633d28c 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -221,11 +221,17 @@ int radeon_bo_create(struct radeon_device *rdev,
if (!(rdev->flags & RADEON_IS_PCIE))
bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
+ /* Write-combined CPU mappings of GTT cause GPU hangs with RV6xx
+ * See https://bugs.freedesktop.org/show_bug.cgi?id=91268
+ */
+ if (rdev->family >= CHIP_RV610 && rdev->family <= CHIP_RV635)
+ bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
+
#ifdef CONFIG_X86_32
/* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
* See https://bugs.freedesktop.org/show_bug.cgi?id=84627
*/
- bo->flags &= ~RADEON_GEM_GTT_WC;
+ bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
#elif defined(CONFIG_X86) && !defined(CONFIG_X86_PAT)
/* Don't try to enable write-combining when it can't work, or things
* may be slow
@@ -235,9 +241,10 @@ int radeon_bo_create(struct radeon_device *rdev,
#warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
thanks to write-combining
- DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
- "better performance thanks to write-combining\n");
- bo->flags &= ~RADEON_GEM_GTT_WC;
+ if (bo->flags & RADEON_GEM_GTT_WC)
+ DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
+ "better performance thanks to write-combining\n");
+ bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
#endif
radeon_ttm_placement_from_domain(bo, domain);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 05751f3f8444..f4f03dcc1530 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -717,10 +717,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
struct radeon_device *rdev = dev_get_drvdata(dev);
umode_t effective_mode = attr->mode;
- /* Skip limit attributes if DPM is not enabled */
+ /* Skip attributes if DPM is not enabled */
if (rdev->pm.pm_method != PM_METHOD_DPM &&
(attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
- attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+ attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
return 0;
/* Skip fan attributes if fan is not present */
@@ -1326,14 +1330,6 @@ static int radeon_pm_init_old(struct radeon_device *rdev)
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
if (rdev->pm.num_power_states > 1) {
- /* where's the best place to put these? */
- ret = device_create_file(rdev->dev, &dev_attr_power_profile);
- if (ret)
- DRM_ERROR("failed to create device file for power profile\n");
- ret = device_create_file(rdev->dev, &dev_attr_power_method);
- if (ret)
- DRM_ERROR("failed to create device file for power method\n");
-
if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for PM!\n");
}
@@ -1391,20 +1387,6 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
goto dpm_failed;
rdev->pm.dpm_enabled = true;
- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
- if (ret)
- DRM_ERROR("failed to create device file for dpm state\n");
- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
- if (ret)
- DRM_ERROR("failed to create device file for dpm state\n");
- /* XXX: these are noops for dpm but are here for backwards compat */
- ret = device_create_file(rdev->dev, &dev_attr_power_profile);
- if (ret)
- DRM_ERROR("failed to create device file for power profile\n");
- ret = device_create_file(rdev->dev, &dev_attr_power_method);
- if (ret)
- DRM_ERROR("failed to create device file for power method\n");
-
if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for dpm!\n");
}
@@ -1545,9 +1527,50 @@ int radeon_pm_late_init(struct radeon_device *rdev)
int ret = 0;
if (rdev->pm.pm_method == PM_METHOD_DPM) {
- mutex_lock(&rdev->pm.mutex);
- ret = radeon_dpm_late_enable(rdev);
- mutex_unlock(&rdev->pm.mutex);
+ if (rdev->pm.dpm_enabled) {
+ if (!rdev->pm.sysfs_initialized) {
+ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+ if (ret)
+ DRM_ERROR("failed to create device file for dpm state\n");
+ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+ if (ret)
+ DRM_ERROR("failed to create device file for dpm state\n");
+ /* XXX: these are noops for dpm but are here for backwards compat */
+ ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+ if (ret)
+ DRM_ERROR("failed to create device file for power profile\n");
+ ret = device_create_file(rdev->dev, &dev_attr_power_method);
+ if (ret)
+ DRM_ERROR("failed to create device file for power method\n");
+ rdev->pm.sysfs_initialized = true;
+ }
+
+ mutex_lock(&rdev->pm.mutex);
+ ret = radeon_dpm_late_enable(rdev);
+ mutex_unlock(&rdev->pm.mutex);
+ if (ret) {
+ rdev->pm.dpm_enabled = false;
+ DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+ } else {
+ /* set the dpm state for PX since there won't be
+ * a modeset to call this.
+ */
+ radeon_pm_compute_clocks(rdev);
+ }
+ }
+ } else {
+ if ((rdev->pm.num_power_states > 1) &&
+ (!rdev->pm.sysfs_initialized)) {
+ /* where's the best place to put these? */
+ ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+ if (ret)
+ DRM_ERROR("failed to create device file for power profile\n");
+ ret = device_create_file(rdev->dev, &dev_attr_power_method);
+ if (ret)
+ DRM_ERROR("failed to create device file for power method\n");
+ if (!ret)
+ rdev->pm.sysfs_initialized = true;
+ }
}
return ret;
}
@@ -1733,7 +1756,9 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
*/
for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
if (rdev->pm.active_crtcs & (1 << crtc)) {
- vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL);
+ vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0,
+ &vpos, &hpos, NULL, NULL,
+ &rdev->mode_info.crtcs[crtc]->base.hwmode);
if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
!(vbl_status & DRM_SCANOUTPOS_IN_VBLANK))
in_vbl = false;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 06ac59fe332a..e34307459e50 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -144,7 +144,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
if (!rdev->ddev->agp) {
DRM_ERROR("AGP is not enabled for memory type %u\n",
@@ -461,7 +461,7 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_
/* system memory */
return 0;
case TTM_PL_TT:
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
/* RADEON_IS_AGP is set only if AGP is active */
mem->bus.offset = mem->start << PAGE_SHIFT;
@@ -680,7 +680,7 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev,
struct radeon_ttm_tt *gtt;
rdev = radeon_get_rdev(bdev);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
return ttm_agp_tt_create(bdev, rdev->ddev->agp->bridge,
size, page_flags, dummy_read_page);
@@ -736,7 +736,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
}
rdev = radeon_get_rdev(ttm->bdev);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
return ttm_agp_tt_populate(ttm);
}
@@ -787,7 +787,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm)
return;
rdev = radeon_get_rdev(ttm->bdev);
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
ttm_agp_tt_unpopulate(ttm);
return;
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index e9115d3f67b0..a82b891ae1fe 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -2927,7 +2927,8 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
{ PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
{ PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
{ PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
- { PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 },
+ { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 },
+ { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
{ 0, 0, 0, 0 },
};
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 11485a4a16ae..d4e0a39568f6 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -1,6 +1,6 @@
config DRM_RCAR_DU
tristate "DRM Support for R-Car Display Unit"
- depends on DRM && ARM && HAVE_DMA_ATTRS
+ depends on DRM && ARM && HAVE_DMA_ATTRS && OF
depends on ARCH_SHMOBILE || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 780ca11512ba..40422f6b645e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -84,16 +84,17 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.num_lvds = 2,
};
+/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2,
.routes = {
- /* R8A7791 has one RGB output, one LVDS output and one
+ /* R8A779[13] has one RGB output, one LVDS output and one
* (currently unsupported) TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
- .possible_crtcs = BIT(1),
+ .possible_crtcs = BIT(1) | BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
@@ -106,19 +107,34 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.num_lvds = 1,
};
-static const struct platform_device_id rcar_du_id_table[] = {
- { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
- { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
- { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
- { }
+static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+ | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+ .num_crtcs = 2,
+ .routes = {
+ /* R8A7794 has two RGB outputs and one (currently unsupported)
+ * TCON output.
+ */
+ [RCAR_DU_OUTPUT_DPAD0] = {
+ .possible_crtcs = BIT(0),
+ .encoder_type = DRM_MODE_ENCODER_NONE,
+ .port = 0,
+ },
+ [RCAR_DU_OUTPUT_DPAD1] = {
+ .possible_crtcs = BIT(1),
+ .encoder_type = DRM_MODE_ENCODER_NONE,
+ .port = 1,
+ },
+ },
+ .num_lvds = 0,
};
-MODULE_DEVICE_TABLE(platform, rcar_du_id_table);
-
static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
+ { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
+ { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
{ }
};
@@ -167,8 +183,7 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
init_waitqueue_head(&rcdu->commit.wait);
rcdu->dev = &pdev->dev;
- rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data
- : (void *)platform_get_device_id(pdev)->driver_data;
+ rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
rcdu->ddev = dev;
dev->dev_private = rcdu;
@@ -221,20 +236,20 @@ static void rcar_du_lastclose(struct drm_device *dev)
drm_fbdev_cma_restore_mode(rcdu->fbdev);
}
-static int rcar_du_enable_vblank(struct drm_device *dev, int crtc)
+static int rcar_du_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct rcar_du_device *rcdu = dev->dev_private;
- rcar_du_crtc_enable_vblank(&rcdu->crtcs[crtc], true);
+ rcar_du_crtc_enable_vblank(&rcdu->crtcs[pipe], true);
return 0;
}
-static void rcar_du_disable_vblank(struct drm_device *dev, int crtc)
+static void rcar_du_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct rcar_du_device *rcdu = dev->dev_private;
- rcar_du_crtc_enable_vblank(&rcdu->crtcs[crtc], false);
+ rcar_du_crtc_enable_vblank(&rcdu->crtcs[pipe], false);
}
static const struct file_operations rcar_du_fops = {
@@ -259,7 +274,7 @@ static struct drm_driver rcar_du_driver = {
.preclose = rcar_du_preclose,
.lastclose = rcar_du_lastclose,
.set_busid = drm_platform_set_busid,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = rcar_du_enable_vblank,
.disable_vblank = rcar_du_disable_vblank,
.gem_free_object = drm_gem_cma_free_object,
@@ -340,7 +355,6 @@ static struct platform_driver rcar_du_platform_driver = {
.pm = &rcar_du_pm_ops,
.of_match_table = rcar_du_of_table,
},
- .id_table = rcar_du_id_table,
};
module_platform_driver(rcar_du_platform_driver);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 7fd39a7d91c8..8e2ffe025153 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,9 +49,10 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
/* The DEFR8 register for the first group also controls RGB output
- * routing to DPAD0
+ * routing to DPAD0 for DU instances that support it.
*/
- if (rgrp->index == 0)
+ if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
+ rgrp->index == 0)
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
rcar_du_group_write(rgrp, DEFR8, defr8);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 56518eb1269a..ca12e8ca5552 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -456,7 +456,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
/* Apply the atomic update. */
drm_atomic_helper_commit_modeset_disables(dev, old_state);
drm_atomic_helper_commit_modeset_enables(dev, old_state);
- drm_atomic_helper_commit_planes(dev, old_state);
+ drm_atomic_helper_commit_planes(dev, old_state, false);
drm_atomic_helper_wait_for_vblanks(dev, old_state);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index c66986414bb4..ffa583712cd9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -273,29 +273,6 @@ static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
.atomic_update = rcar_du_plane_atomic_update,
};
-static void rcar_du_plane_reset(struct drm_plane *plane)
-{
- struct rcar_du_plane_state *state;
-
- if (plane->state && plane->state->fb)
- drm_framebuffer_unreference(plane->state->fb);
-
- kfree(plane->state);
- plane->state = NULL;
-
- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (state == NULL)
- return;
-
- state->hwindex = -1;
- state->alpha = 255;
- state->colorkey = RCAR_DU_COLORKEY_NONE;
- state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
-
- plane->state = &state->state;
- plane->state->plane = plane;
-}
-
static struct drm_plane_state *
rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane)
{
@@ -322,6 +299,28 @@ static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
kfree(to_rcar_plane_state(state));
}
+static void rcar_du_plane_reset(struct drm_plane *plane)
+{
+ struct rcar_du_plane_state *state;
+
+ if (plane->state) {
+ rcar_du_plane_atomic_destroy_state(plane, plane->state);
+ plane->state = NULL;
+ }
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state == NULL)
+ return;
+
+ state->hwindex = -1;
+ state->alpha = 255;
+ state->colorkey = RCAR_DU_COLORKEY_NONE;
+ state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
+
+ plane->state = &state->state;
+ plane->state->plane = plane;
+}
+
static int rcar_du_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 9a0c2911272a..f22e1e1ee64a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -103,7 +103,8 @@ static struct drm_crtc *rockchip_crtc_from_pipe(struct drm_device *drm,
return NULL;
}
-static int rockchip_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
+static int rockchip_drm_crtc_enable_vblank(struct drm_device *dev,
+ unsigned int pipe)
{
struct rockchip_drm_private *priv = dev->dev_private;
struct drm_crtc *crtc = rockchip_crtc_from_pipe(dev, pipe);
@@ -115,7 +116,8 @@ static int rockchip_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
return 0;
}
-static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
+static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
+ unsigned int pipe)
{
struct rockchip_drm_private *priv = dev->dev_private;
struct drm_crtc *crtc = rockchip_crtc_from_pipe(dev, pipe);
@@ -277,7 +279,7 @@ static struct drm_driver rockchip_drm_driver = {
.load = rockchip_drm_load,
.unload = rockchip_drm_unload,
.lastclose = rockchip_drm_lastclose,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = rockchip_drm_crtc_enable_vblank,
.disable_vblank = rockchip_drm_crtc_disable_vblank,
.gem_vm_ops = &rockchip_drm_vm_ops,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index a6d9104f7f15..8caea0a33dd8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -79,12 +79,9 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj,
int rockchip_gem_mmap_buf(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
- struct drm_device *drm = obj->dev;
int ret;
- mutex_lock(&drm->struct_mutex);
ret = drm_gem_mmap_obj(obj, obj->size, vma);
- mutex_unlock(&drm->struct_mutex);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index 666321de7b99..04e66e3751b4 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -231,7 +231,7 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg)
return IRQ_HANDLED;
}
-static int shmob_drm_enable_vblank(struct drm_device *dev, int crtc)
+static int shmob_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct shmob_drm_device *sdev = dev->dev_private;
@@ -240,7 +240,7 @@ static int shmob_drm_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-static void shmob_drm_disable_vblank(struct drm_device *dev, int crtc)
+static void shmob_drm_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct shmob_drm_device *sdev = dev->dev_private;
@@ -269,7 +269,7 @@ static struct drm_driver shmob_drm_driver = {
.preclose = shmob_drm_preclose,
.set_busid = drm_platform_set_busid,
.irq_handler = shmob_drm_irq,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = shmob_drm_enable_vblank,
.disable_vblank = shmob_drm_disable_vblank,
.gem_free_object = drm_gem_cma_free_object,
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
index 16f972b2a76a..328f8a750976 100644
--- a/drivers/gpu/drm/sis/sis_drv.h
+++ b/drivers/gpu/drm/sis/sis_drv.h
@@ -67,6 +67,10 @@ typedef struct drm_sis_private {
struct idr object_idr;
} drm_sis_private_t;
+struct sis_file_private {
+ struct list_head obj_list;
+};
+
extern int sis_idle(struct drm_device *dev);
extern void sis_reclaim_buffers_locked(struct drm_device *dev,
struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index fbccc105819b..10c1b1926e6f 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -6,12 +6,6 @@ config DRM_STI
select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER
select DRM_PANEL
- select FW_LOADER_USER_HELPER_FALLBACK
+ select FW_LOADER
help
Choose this option to enable DRM on STM stiH41x chipset
-
-config DRM_STI_FBDEV
- bool "DRM frame buffer device for STMicroelectronics SoC stiH41x Serie"
- depends on DRM_STI
- help
- Choose this option to enable FBDEV on top of DRM for STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile
index e27490b492a5..b8057620b3b3 100644
--- a/drivers/gpu/drm/sti/Makefile
+++ b/drivers/gpu/drm/sti/Makefile
@@ -1,26 +1,23 @@
-sticompositor-y := \
+sti-drm-y := \
sti_mixer.o \
sti_gdp.o \
sti_vid.o \
sti_cursor.o \
sti_compositor.o \
sti_crtc.o \
- sti_plane.o
-
-stihdmi-y := sti_hdmi.o \
+ sti_plane.o \
+ sti_crtc.o \
+ sti_plane.o \
+ sti_hdmi.o \
sti_hdmi_tx3g0c55phy.o \
sti_hdmi_tx3g4c28phy.o \
-
-stidvo-y := sti_dvo.o \
- sti_awg_utils.o
-
-obj-$(CONFIG_DRM_STI) = \
+ sti_dvo.o \
+ sti_awg_utils.o \
sti_vtg.o \
sti_vtac.o \
- stihdmi.o \
sti_hda.o \
sti_tvout.o \
- sticompositor.o \
sti_hqvdp.o \
- stidvo.o \
sti_drv.o
+
+obj-$(CONFIG_DRM_STI) = sti-drm.o
diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c
index 6029a2e3db1d..00d0698be9d3 100644
--- a/drivers/gpu/drm/sti/sti_awg_utils.c
+++ b/drivers/gpu/drm/sti/sti_awg_utils.c
@@ -65,7 +65,6 @@ static int awg_generate_instr(enum opcode opcode,
mux = 0;
data_enable = 0;
- arg = (arg << 22) >> 22;
arg &= (0x3ff);
break;
case REPEAT:
@@ -77,14 +76,12 @@ static int awg_generate_instr(enum opcode opcode,
mux = 0;
data_enable = 0;
- arg = (arg << 22) >> 22;
arg &= (0x3ff);
break;
case JUMP:
mux = 0;
data_enable = 0;
arg |= 0x40; /* for jump instruction 7th bit is 1 */
- arg = (arg << 22) >> 22;
arg &= 0x3ff;
break;
case STOP:
@@ -94,7 +91,6 @@ static int awg_generate_instr(enum opcode opcode,
case RPTSET:
case RPLSET:
case HOLD:
- arg = (arg << 24) >> 24;
arg &= (0x0ff);
break;
default:
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index c652627b1bca..afed2171beb9 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -263,7 +263,7 @@ static int sti_compositor_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver sti_compositor_driver = {
+struct platform_driver sti_compositor_driver = {
.driver = {
.name = "sti-compositor",
.of_match_table = compositor_of_match,
@@ -272,8 +272,6 @@ static struct platform_driver sti_compositor_driver = {
.remove = sti_compositor_remove,
};
-module_platform_driver(sti_compositor_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c
index 018ffc970e96..3ae09dcd4fd8 100644
--- a/drivers/gpu/drm/sti/sti_crtc.c
+++ b/drivers/gpu/drm/sti/sti_crtc.c
@@ -226,7 +226,7 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
}
}
-static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
+static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
.enable = sti_crtc_enable,
.disable = sti_crtc_disabling,
.mode_fixup = sti_crtc_mode_fixup,
@@ -254,15 +254,17 @@ static int sti_crtc_set_property(struct drm_crtc *crtc,
int sti_crtc_vblank_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
- struct drm_device *drm_dev;
struct sti_compositor *compo =
container_of(nb, struct sti_compositor, vtg_vblank_nb);
- int *crtc = data;
+ struct drm_crtc *crtc = data;
+ struct sti_mixer *mixer;
unsigned long flags;
struct sti_private *priv;
+ unsigned int pipe;
- drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
- priv = drm_dev->dev_private;
+ priv = crtc->dev->dev_private;
+ pipe = drm_crtc_index(crtc);
+ mixer = compo->mixer[pipe];
if ((event != VTG_TOP_FIELD_EVENT) &&
(event != VTG_BOTTOM_FIELD_EVENT)) {
@@ -270,44 +272,45 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
return -EINVAL;
}
- drm_handle_vblank(drm_dev, *crtc);
+ drm_crtc_handle_vblank(crtc);
- spin_lock_irqsave(&drm_dev->event_lock, flags);
- if (compo->mixer[*crtc]->pending_event) {
- drm_send_vblank_event(drm_dev, -1,
- compo->mixer[*crtc]->pending_event);
- drm_vblank_put(drm_dev, *crtc);
- compo->mixer[*crtc]->pending_event = NULL;
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ if (mixer->pending_event) {
+ drm_crtc_send_vblank_event(crtc, mixer->pending_event);
+ drm_crtc_vblank_put(crtc);
+ mixer->pending_event = NULL;
}
- spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
- if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) {
+ if (mixer->status == STI_MIXER_DISABLING) {
struct drm_plane *p;
/* Disable mixer only if all overlay planes (GDP and VDP)
* are disabled */
- list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
+ list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
+ head) {
struct sti_plane *plane = to_sti_plane(p);
if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
if (plane->status != STI_PLANE_DISABLED)
return 0;
}
- sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc);
+ sti_crtc_disable(crtc);
}
return 0;
}
-int sti_crtc_enable_vblank(struct drm_device *dev, int crtc)
+int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct sti_private *dev_priv = dev->dev_private;
struct sti_compositor *compo = dev_priv->compo;
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+ struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
DRM_DEBUG_DRIVER("\n");
- if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
+ if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ?
compo->vtg_main : compo->vtg_aux,
vtg_vblank_nb, crtc)) {
DRM_ERROR("Cannot register VTG notifier\n");
@@ -316,29 +319,28 @@ int sti_crtc_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-EXPORT_SYMBOL(sti_crtc_enable_vblank);
-void sti_crtc_disable_vblank(struct drm_device *drm_dev, int crtc)
+void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
{
struct sti_private *priv = drm_dev->dev_private;
struct sti_compositor *compo = priv->compo;
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+ struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
DRM_DEBUG_DRIVER("\n");
- if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
+ if (sti_vtg_unregister_client(pipe == STI_MIXER_MAIN ?
compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
/* free the resources of the pending requests */
- if (compo->mixer[crtc]->pending_event) {
- drm_vblank_put(drm_dev, crtc);
- compo->mixer[crtc]->pending_event = NULL;
+ if (compo->mixer[pipe]->pending_event) {
+ drm_crtc_vblank_put(crtc);
+ compo->mixer[pipe]->pending_event = NULL;
}
}
-EXPORT_SYMBOL(sti_crtc_disable_vblank);
-static struct drm_crtc_funcs sti_crtc_funcs = {
+static const struct drm_crtc_funcs sti_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.destroy = sti_crtc_destroy,
@@ -357,7 +359,6 @@ bool sti_crtc_is_main(struct drm_crtc *crtc)
return false;
}
-EXPORT_SYMBOL(sti_crtc_is_main);
int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
struct drm_plane *primary, struct drm_plane *cursor)
diff --git a/drivers/gpu/drm/sti/sti_crtc.h b/drivers/gpu/drm/sti/sti_crtc.h
index 51963e6ddbe7..3f2d89a3634d 100644
--- a/drivers/gpu/drm/sti/sti_crtc.h
+++ b/drivers/gpu/drm/sti/sti_crtc.h
@@ -13,8 +13,8 @@ struct sti_mixer;
int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
struct drm_plane *primary, struct drm_plane *cursor);
-int sti_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void sti_crtc_disable_vblank(struct drm_device *dev, int crtc);
+int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe);
+void sti_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe);
int sti_crtc_vblank_cb(struct notifier_block *nb,
unsigned long event, void *data);
bool sti_crtc_is_main(struct drm_crtc *drm_crtc);
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 6f4af6a8ba1b..1469987949d8 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -59,7 +59,7 @@ static void sti_atomic_complete(struct sti_private *private,
*/
drm_atomic_helper_commit_modeset_disables(drm, state);
- drm_atomic_helper_commit_planes(drm, state);
+ drm_atomic_helper_commit_planes(drm, state, false);
drm_atomic_helper_commit_modeset_enables(drm, state);
drm_atomic_helper_wait_for_vblanks(drm, state);
@@ -107,7 +107,7 @@ static int sti_atomic_commit(struct drm_device *drm,
return 0;
}
-static struct drm_mode_config_funcs sti_mode_config_funcs = {
+static const struct drm_mode_config_funcs sti_mode_config_funcs = {
.fb_create = drm_fb_cma_create,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = sti_atomic_commit,
@@ -123,8 +123,8 @@ static void sti_mode_config_init(struct drm_device *dev)
* this value would be used to check framebuffer size limitation
* at drm_mode_addfb().
*/
- dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
- dev->mode_config.max_height = STI_MAX_FB_WIDTH;
+ dev->mode_config.max_width = STI_MAX_FB_WIDTH;
+ dev->mode_config.max_height = STI_MAX_FB_HEIGHT;
dev->mode_config.funcs = &sti_mode_config_funcs;
}
@@ -160,11 +160,10 @@ static int sti_load(struct drm_device *dev, unsigned long flags)
drm_mode_config_reset(dev);
-#ifdef CONFIG_DRM_STI_FBDEV
drm_fbdev_cma_init(dev, 32,
dev->mode_config.num_crtc,
dev->mode_config.num_connector);
-#endif
+
return 0;
}
@@ -201,7 +200,7 @@ static struct drm_driver sti_driver = {
.dumb_destroy = drm_gem_dumb_destroy,
.fops = &sti_driver_fops,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = sti_crtc_enable_vblank,
.disable_vblank = sti_crtc_disable_vblank,
@@ -287,7 +286,29 @@ static struct platform_driver sti_platform_driver = {
},
};
-module_platform_driver(sti_platform_driver);
+static struct platform_driver * const drivers[] = {
+ &sti_tvout_driver,
+ &sti_vtac_driver,
+ &sti_hqvdp_driver,
+ &sti_hdmi_driver,
+ &sti_hda_driver,
+ &sti_dvo_driver,
+ &sti_vtg_driver,
+ &sti_compositor_driver,
+ &sti_platform_driver,
+};
+
+static int sti_drm_init(void)
+{
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_init(sti_drm_init);
+
+static void sti_drm_exit(void)
+{
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_exit(sti_drm_exit);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h
index 9372f69e1859..30ddc20841c3 100644
--- a/drivers/gpu/drm/sti/sti_drv.h
+++ b/drivers/gpu/drm/sti/sti_drv.h
@@ -32,4 +32,13 @@ struct sti_private {
} commit;
};
+extern struct platform_driver sti_tvout_driver;
+extern struct platform_driver sti_vtac_driver;
+extern struct platform_driver sti_hqvdp_driver;
+extern struct platform_driver sti_hdmi_driver;
+extern struct platform_driver sti_hda_driver;
+extern struct platform_driver sti_dvo_driver;
+extern struct platform_driver sti_vtg_driver;
+extern struct platform_driver sti_compositor_driver;
+
#endif
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index d141d645bd13..45cbe2bf7dd6 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -329,7 +329,8 @@ struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector)
return dvo_connector->encoder;
}
-static struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = {
+static const
+struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = {
.get_modes = sti_dvo_connector_get_modes,
.mode_valid = sti_dvo_connector_mode_valid,
.best_encoder = sti_dvo_best_encoder,
@@ -364,7 +365,7 @@ static void sti_dvo_connector_destroy(struct drm_connector *connector)
kfree(dvo_connector);
}
-static struct drm_connector_funcs sti_dvo_connector_funcs = {
+static const struct drm_connector_funcs sti_dvo_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = sti_dvo_connector_detect,
@@ -557,8 +558,6 @@ struct platform_driver sti_dvo_driver = {
.remove = sti_dvo_remove,
};
-module_platform_driver(sti_dvo_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 9365670427ad..c85dc7d6b005 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -492,7 +492,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
/* Register gdp callback */
if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ?
compo->vtg_main : compo->vtg_aux,
- &gdp->vtg_field_nb, mixer->id)) {
+ &gdp->vtg_field_nb, crtc)) {
DRM_ERROR("Cannot register VTG notifier\n");
return;
}
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 598cd78b0b16..d735daccd458 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -589,7 +589,8 @@ struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector)
return hda_connector->encoder;
}
-static struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
+static const
+struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
.get_modes = sti_hda_connector_get_modes,
.mode_valid = sti_hda_connector_mode_valid,
.best_encoder = sti_hda_best_encoder,
@@ -611,7 +612,7 @@ static void sti_hda_connector_destroy(struct drm_connector *connector)
kfree(hda_connector);
}
-static struct drm_connector_funcs sti_hda_connector_funcs = {
+static const struct drm_connector_funcs sti_hda_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = sti_hda_connector_detect,
@@ -784,8 +785,6 @@ struct platform_driver sti_hda_driver = {
.remove = sti_hda_remove,
};
-module_platform_driver(sti_hda_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 09e29e43423e..cd501563c0cc 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -628,7 +628,8 @@ struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
return hdmi_connector->encoder;
}
-static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
+static const
+struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
.get_modes = sti_hdmi_connector_get_modes,
.mode_valid = sti_hdmi_connector_mode_valid,
.best_encoder = sti_hdmi_best_encoder,
@@ -663,7 +664,7 @@ static void sti_hdmi_connector_destroy(struct drm_connector *connector)
kfree(hdmi_connector);
}
-static struct drm_connector_funcs sti_hdmi_connector_funcs = {
+static const struct drm_connector_funcs sti_hdmi_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = sti_hdmi_connector_detect,
@@ -700,18 +701,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
encoder = sti_hdmi_find_encoder(drm_dev);
if (!encoder)
- goto err_adapt;
+ return -EINVAL;
connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
if (!connector)
- goto err_adapt;
-
+ return -EINVAL;
connector->hdmi = hdmi;
bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
if (!bridge)
- goto err_adapt;
+ return -EINVAL;
bridge->driver_private = hdmi;
bridge->funcs = &sti_hdmi_bridge_funcs;
@@ -748,8 +748,7 @@ err_sysfs:
drm_connector_unregister(drm_connector);
err_connector:
drm_connector_cleanup(drm_connector);
-err_adapt:
- put_device(&hdmi->ddc_adapt->dev);
+
return -EINVAL;
}
@@ -794,13 +793,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);
if (ddc) {
- hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc);
- if (!hdmi->ddc_adapt) {
- of_node_put(ddc);
- return -EPROBE_DEFER;
- }
-
+ hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);
of_node_put(ddc);
+ if (!hdmi->ddc_adapt)
+ return -EPROBE_DEFER;
}
hdmi->dev = pdev->dev;
@@ -809,24 +805,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
if (!res) {
DRM_ERROR("Invalid hdmi resource\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto release_adapter;
}
hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
- if (!hdmi->regs)
- return -ENOMEM;
+ if (!hdmi->regs) {
+ ret = -ENOMEM;
+ goto release_adapter;
+ }
if (of_device_is_compatible(np, "st,stih416-hdmi")) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"syscfg");
if (!res) {
DRM_ERROR("Invalid syscfg resource\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto release_adapter;
}
hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
resource_size(res));
- if (!hdmi->syscfg)
- return -ENOMEM;
-
+ if (!hdmi->syscfg) {
+ ret = -ENOMEM;
+ goto release_adapter;
+ }
}
hdmi->phy_ops = (struct hdmi_phy_ops *)
@@ -836,25 +837,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
hdmi->clk_pix = devm_clk_get(dev, "pix");
if (IS_ERR(hdmi->clk_pix)) {
DRM_ERROR("Cannot get hdmi_pix clock\n");
- return PTR_ERR(hdmi->clk_pix);
+ ret = PTR_ERR(hdmi->clk_pix);
+ goto release_adapter;
}
hdmi->clk_tmds = devm_clk_get(dev, "tmds");
if (IS_ERR(hdmi->clk_tmds)) {
DRM_ERROR("Cannot get hdmi_tmds clock\n");
- return PTR_ERR(hdmi->clk_tmds);
+ ret = PTR_ERR(hdmi->clk_tmds);
+ goto release_adapter;
}
hdmi->clk_phy = devm_clk_get(dev, "phy");
if (IS_ERR(hdmi->clk_phy)) {
DRM_ERROR("Cannot get hdmi_phy clock\n");
- return PTR_ERR(hdmi->clk_phy);
+ ret = PTR_ERR(hdmi->clk_phy);
+ goto release_adapter;
}
hdmi->clk_audio = devm_clk_get(dev, "audio");
if (IS_ERR(hdmi->clk_audio)) {
DRM_ERROR("Cannot get hdmi_audio clock\n");
- return PTR_ERR(hdmi->clk_audio);
+ ret = PTR_ERR(hdmi->clk_audio);
+ goto release_adapter;
}
hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
@@ -867,7 +872,7 @@ static int sti_hdmi_probe(struct platform_device *pdev)
hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
if (ret) {
DRM_ERROR("Failed to register HDMI interrupt\n");
- return ret;
+ goto release_adapter;
}
hdmi->reset = devm_reset_control_get(dev, "hdmi");
@@ -878,16 +883,20 @@ static int sti_hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdmi);
return component_add(&pdev->dev, &sti_hdmi_ops);
+
+ release_adapter:
+ i2c_put_adapter(hdmi->ddc_adapt);
+
+ return ret;
}
static int sti_hdmi_remove(struct platform_device *pdev)
{
struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
- if (hdmi->ddc_adapt)
- put_device(&hdmi->ddc_adapt->dev);
-
+ i2c_put_adapter(hdmi->ddc_adapt);
component_del(&pdev->dev, &sti_hdmi_ops);
+
return 0;
}
@@ -901,8 +910,6 @@ struct platform_driver sti_hdmi_driver = {
.remove = sti_hdmi_remove,
};
-module_platform_driver(sti_hdmi_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index 7c8f9b8bfae1..ea0690bc77d5 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
memset(hqvdp->hqvdp_cmd, 0, size);
}
+static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
+{
+ /* Configure Plugs (same for RD & WR) */
+ writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
+ writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
+ writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
+ writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
+ writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
+ writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
+ writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
+
+ writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
+ writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
+ writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
+ writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
+ writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
+ writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
+ writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
+}
+
+/**
+ * sti_hqvdp_start_xp70
+ * @hqvdp: hqvdp pointer
+ *
+ * Run the xP70 initialization sequence
+ */
+static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp)
+{
+ const struct firmware *firmware;
+ u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
+ u8 *data;
+ int i;
+ struct fw_header {
+ int rd_size;
+ int wr_size;
+ int pmem_size;
+ int dmem_size;
+ } *header;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (hqvdp->xp70_initialized) {
+ DRM_INFO("HQVDP XP70 already initialized\n");
+ return;
+ }
+
+ /* Request firmware */
+ if (request_firmware(&firmware, HQVDP_FMW_NAME, hqvdp->dev)) {
+ DRM_ERROR("Can't get HQVDP firmware\n");
+ return;
+ }
+
+ /* Check firmware parts */
+ if (!firmware) {
+ DRM_ERROR("Firmware not available\n");
+ return;
+ }
+
+ header = (struct fw_header *)firmware->data;
+ if (firmware->size < sizeof(*header)) {
+ DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
+ goto out;
+ }
+ if ((sizeof(*header) + header->rd_size + header->wr_size +
+ header->pmem_size + header->dmem_size) != firmware->size) {
+ DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
+ sizeof(*header), header->rd_size, header->wr_size,
+ header->pmem_size, header->dmem_size,
+ firmware->size);
+ goto out;
+ }
+
+ data = (u8 *)firmware->data;
+ data += sizeof(*header);
+ fw_rd_plug = (void *)data;
+ data += header->rd_size;
+ fw_wr_plug = (void *)data;
+ data += header->wr_size;
+ fw_pmem = (void *)data;
+ data += header->pmem_size;
+ fw_dmem = (void *)data;
+
+ /* Enable clock */
+ if (clk_prepare_enable(hqvdp->clk))
+ DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
+
+ /* Reset */
+ writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
+
+ for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
+ if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
+ & STARTUP_CTRL1_RST_DONE)
+ break;
+ msleep(POLL_DELAY_MS);
+ }
+ if (i == POLL_MAX_ATTEMPT) {
+ DRM_ERROR("Could not reset\n");
+ goto out;
+ }
+
+ /* Init Read & Write plugs */
+ for (i = 0; i < header->rd_size / 4; i++)
+ writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
+ for (i = 0; i < header->wr_size / 4; i++)
+ writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
+
+ sti_hqvdp_init_plugs(hqvdp);
+
+ /* Authorize Idle Mode */
+ writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
+
+ /* Prevent VTG interruption during the boot */
+ writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
+ writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
+
+ /* Download PMEM & DMEM */
+ for (i = 0; i < header->pmem_size / 4; i++)
+ writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
+ for (i = 0; i < header->dmem_size / 4; i++)
+ writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
+
+ /* Enable fetch */
+ writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
+
+ /* Wait end of boot */
+ for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
+ if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
+ & INFO_XP70_FW_READY)
+ break;
+ msleep(POLL_DELAY_MS);
+ }
+ if (i == POLL_MAX_ATTEMPT) {
+ DRM_ERROR("Could not boot\n");
+ goto out;
+ }
+
+ /* Launch Vsync */
+ writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
+
+ DRM_INFO("HQVDP XP70 initialized\n");
+
+ hqvdp->xp70_initialized = true;
+
+out:
+ release_firmware(firmware);
+}
+
static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
struct drm_plane_state *oldstate)
{
@@ -754,6 +901,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
if (first_prepare) {
+ /* Start HQVDP XP70 coprocessor */
+ sti_hqvdp_start_xp70(hqvdp);
+
/* Prevent VTG shutdown */
if (clk_prepare_enable(hqvdp->clk_pix_main)) {
DRM_ERROR("Failed to prepare/enable pix main clk\n");
@@ -763,7 +913,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
/* Register VTG Vsync callback to handle bottom fields */
if (sti_vtg_register_client(hqvdp->vtg,
&hqvdp->vtg_nb,
- mixer->id)) {
+ crtc)) {
DRM_ERROR("Cannot register VTG notifier\n");
return;
}
@@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
return &hqvdp->plane.drm_plane;
}
-static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
-{
- /* Configure Plugs (same for RD & WR) */
- writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
- writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
- writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
- writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
- writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
- writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
- writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
-
- writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
- writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
- writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
- writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
- writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
- writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
- writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
-}
-
-/**
- * sti_hqvdp_start_xp70
- * @firmware: firmware found
- * @ctxt: hqvdp structure
- *
- * Run the xP70 initialization sequence
- */
-static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
-{
- struct sti_hqvdp *hqvdp = ctxt;
- u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
- u8 *data;
- int i;
- struct fw_header {
- int rd_size;
- int wr_size;
- int pmem_size;
- int dmem_size;
- } *header;
-
- DRM_DEBUG_DRIVER("\n");
-
- if (hqvdp->xp70_initialized) {
- DRM_INFO("HQVDP XP70 already initialized\n");
- return;
- }
-
- /* Check firmware parts */
- if (!firmware) {
- DRM_ERROR("Firmware not available\n");
- return;
- }
-
- header = (struct fw_header *) firmware->data;
- if (firmware->size < sizeof(*header)) {
- DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
- goto out;
- }
- if ((sizeof(*header) + header->rd_size + header->wr_size +
- header->pmem_size + header->dmem_size) != firmware->size) {
- DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
- sizeof(*header), header->rd_size, header->wr_size,
- header->pmem_size, header->dmem_size,
- firmware->size);
- goto out;
- }
-
- data = (u8 *) firmware->data;
- data += sizeof(*header);
- fw_rd_plug = (void *) data;
- data += header->rd_size;
- fw_wr_plug = (void *) data;
- data += header->wr_size;
- fw_pmem = (void *) data;
- data += header->pmem_size;
- fw_dmem = (void *) data;
-
- /* Enable clock */
- if (clk_prepare_enable(hqvdp->clk))
- DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
-
- /* Reset */
- writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
-
- for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
- if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
- & STARTUP_CTRL1_RST_DONE)
- break;
- msleep(POLL_DELAY_MS);
- }
- if (i == POLL_MAX_ATTEMPT) {
- DRM_ERROR("Could not reset\n");
- goto out;
- }
-
- /* Init Read & Write plugs */
- for (i = 0; i < header->rd_size / 4; i++)
- writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
- for (i = 0; i < header->wr_size / 4; i++)
- writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
-
- sti_hqvdp_init_plugs(hqvdp);
-
- /* Authorize Idle Mode */
- writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
-
- /* Prevent VTG interruption during the boot */
- writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
- writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
-
- /* Download PMEM & DMEM */
- for (i = 0; i < header->pmem_size / 4; i++)
- writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
- for (i = 0; i < header->dmem_size / 4; i++)
- writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
-
- /* Enable fetch */
- writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
-
- /* Wait end of boot */
- for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
- if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
- & INFO_XP70_FW_READY)
- break;
- msleep(POLL_DELAY_MS);
- }
- if (i == POLL_MAX_ATTEMPT) {
- DRM_ERROR("Could not boot\n");
- goto out;
- }
-
- /* Launch Vsync */
- writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
-
- DRM_INFO("HQVDP XP70 initialized\n");
-
- hqvdp->xp70_initialized = true;
-
-out:
- release_firmware(firmware);
-}
-
int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
{
struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
struct drm_device *drm_dev = data;
struct drm_plane *plane;
- int err;
DRM_DEBUG_DRIVER("\n");
hqvdp->drm_dev = drm_dev;
- /* Request for firmware */
- err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
- HQVDP_FMW_NAME, hqvdp->dev,
- GFP_KERNEL, hqvdp, sti_hqvdp_start_xp70);
- if (err) {
- DRM_ERROR("Can't get HQVDP firmware\n");
- return err;
- }
-
/* Create HQVDP plane once xp70 is initialized */
plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
if (!plane)
@@ -1090,8 +1088,6 @@ struct platform_driver sti_hqvdp_driver = {
.remove = sti_hqvdp_remove,
};
-module_platform_driver(sti_hqvdp_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
index 0182e9365004..49db835dce03 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -10,6 +10,11 @@
#include "sti_mixer.h"
#include "sti_vtg.h"
+/* Module parameter to set the background color of the mixer */
+static unsigned int bkg_color = 0x000000;
+MODULE_PARM_DESC(bkgcolor, "Value of the background color 0xRRGGBB");
+module_param_named(bkgcolor, bkg_color, int, 0644);
+
/* Identity: G=Y , B=Cb , R=Cr */
static const u32 mixerColorSpaceMatIdentity[] = {
0x10000000, 0x00000000, 0x10000000, 0x00001000,
@@ -58,7 +63,6 @@ const char *sti_mixer_to_str(struct sti_mixer *mixer)
return "<UNKNOWN MIXER>";
}
}
-EXPORT_SYMBOL(sti_mixer_to_str);
static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
{
@@ -81,11 +85,9 @@ void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
}
static void sti_mixer_set_background_color(struct sti_mixer *mixer,
- u8 red, u8 green, u8 blue)
+ unsigned int rgb)
{
- u32 val = (red << 16) | (green << 8) | blue;
-
- sti_mixer_reg_write(mixer, GAM_MIXER_BKC, val);
+ sti_mixer_reg_write(mixer, GAM_MIXER_BKC, rgb);
}
static void sti_mixer_set_background_area(struct sti_mixer *mixer,
@@ -175,7 +177,7 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
- sti_mixer_set_background_color(mixer, 0xFF, 0, 0);
+ sti_mixer_set_background_color(mixer, bkg_color);
sti_mixer_set_background_area(mixer, mode);
sti_mixer_set_background_status(mixer, true);
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
index d5c5e91f2956..2e5c751910c5 100644
--- a/drivers/gpu/drm/sti/sti_plane.c
+++ b/drivers/gpu/drm/sti/sti_plane.c
@@ -42,7 +42,6 @@ const char *sti_plane_to_str(struct sti_plane *plane)
return "<UNKNOWN PLANE>";
}
}
-EXPORT_SYMBOL(sti_plane_to_str);
static void sti_plane_destroy(struct drm_plane *drm_plane)
{
@@ -108,7 +107,6 @@ void sti_plane_init_property(struct sti_plane *plane,
plane->drm_plane.base.id,
sti_plane_to_str(plane), plane->zorder);
}
-EXPORT_SYMBOL(sti_plane_init_property);
struct drm_plane_funcs sti_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane,
@@ -119,4 +117,3 @@ struct drm_plane_funcs sti_plane_helpers_funcs = {
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
-EXPORT_SYMBOL(sti_plane_helpers_funcs);
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index c1aac8e66fb5..c8a4c5dae2b6 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -735,8 +735,6 @@ struct platform_driver sti_tvout_driver = {
.remove = sti_tvout_remove,
};
-module_platform_driver(sti_tvout_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtac.c b/drivers/gpu/drm/sti/sti_vtac.c
index 97bcdac23ae1..b1eb0d77630d 100644
--- a/drivers/gpu/drm/sti/sti_vtac.c
+++ b/drivers/gpu/drm/sti/sti_vtac.c
@@ -216,8 +216,6 @@ struct platform_driver sti_vtac_driver = {
.remove = sti_vtac_remove,
};
-module_platform_driver(sti_vtac_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c
index aa8097137701..d56630c60039 100644
--- a/drivers/gpu/drm/sti/sti_vtg.c
+++ b/drivers/gpu/drm/sti/sti_vtg.c
@@ -79,7 +79,7 @@ LIST_HEAD(vtg_lookup);
* @irq: VTG irq
* @type: VTG type (main or aux)
* @notifier_list: notifier callback
- * @crtc_id: the crtc id for vblank event
+ * @crtc: the CRTC for vblank event
* @slave: slave vtg
* @link: List node to link the structure in lookup list
*/
@@ -90,7 +90,7 @@ struct sti_vtg {
int irq;
u32 irq_status;
struct raw_notifier_head notifier_list;
- int crtc_id;
+ struct drm_crtc *crtc;
struct sti_vtg *slave;
struct list_head link;
};
@@ -110,7 +110,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np)
}
return NULL;
}
-EXPORT_SYMBOL(of_vtg_find);
static void vtg_reset(struct sti_vtg *vtg)
{
@@ -242,7 +241,6 @@ void sti_vtg_set_config(struct sti_vtg *vtg,
else
vtg_enable_irq(vtg);
}
-EXPORT_SYMBOL(sti_vtg_set_config);
/**
* sti_vtg_get_line_number
@@ -265,7 +263,6 @@ u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y)
return start_line + y;
}
-EXPORT_SYMBOL(sti_vtg_get_line_number);
/**
* sti_vtg_get_pixel_number
@@ -281,18 +278,16 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
{
return mode.htotal - mode.hsync_start + x;
}
-EXPORT_SYMBOL(sti_vtg_get_pixel_number);
-int sti_vtg_register_client(struct sti_vtg *vtg,
- struct notifier_block *nb, int crtc_id)
+int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
+ struct drm_crtc *crtc)
{
if (vtg->slave)
- return sti_vtg_register_client(vtg->slave, nb, crtc_id);
+ return sti_vtg_register_client(vtg->slave, nb, crtc);
- vtg->crtc_id = crtc_id;
+ vtg->crtc = crtc;
return raw_notifier_chain_register(&vtg->notifier_list, nb);
}
-EXPORT_SYMBOL(sti_vtg_register_client);
int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
{
@@ -301,7 +296,6 @@ int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
}
-EXPORT_SYMBOL(sti_vtg_unregister_client);
static irqreturn_t vtg_irq_thread(int irq, void *arg)
{
@@ -311,7 +305,7 @@ static irqreturn_t vtg_irq_thread(int irq, void *arg)
event = (vtg->irq_status & VTG_IRQ_TOP) ?
VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT;
- raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id);
+ raw_notifier_call_chain(&vtg->notifier_list, event, vtg->crtc);
return IRQ_HANDLED;
}
@@ -406,8 +400,6 @@ struct platform_driver sti_vtg_driver = {
.remove = vtg_remove,
};
-module_platform_driver(sti_vtg_driver);
-
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtg.h b/drivers/gpu/drm/sti/sti_vtg.h
index e84d23f1f57f..cd2439f89d05 100644
--- a/drivers/gpu/drm/sti/sti_vtg.h
+++ b/drivers/gpu/drm/sti/sti_vtg.h
@@ -17,8 +17,8 @@ struct notifier_block;
struct sti_vtg *of_vtg_find(struct device_node *np);
void sti_vtg_set_config(struct sti_vtg *vtg,
const struct drm_display_mode *mode);
-int sti_vtg_register_client(struct sti_vtg *vtg,
- struct notifier_block *nb, int crtc_id);
+int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
+ struct drm_crtc *crtc);
int sti_vtg_unregister_client(struct sti_vtg *vtg,
struct notifier_block *nb);
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index ddefb85dc4f7..e9f24a85a103 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -480,14 +480,12 @@ static const struct drm_plane_funcs tegra_primary_plane_funcs = {
};
static int tegra_plane_prepare_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *new_state)
{
return 0;
}
static void tegra_plane_cleanup_fb(struct drm_plane *plane,
- struct drm_framebuffer *fb,
const struct drm_plane_state *old_fb)
{
}
@@ -1696,6 +1694,7 @@ static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
static int tegra_dc_init(struct host1x_client *client)
{
struct drm_device *drm = dev_get_drvdata(client->parent);
+ unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
struct tegra_dc *dc = host1x_client_to_dc(client);
struct tegra_drm *tegra = drm->dev_private;
struct drm_plane *primary = NULL;
@@ -1703,6 +1702,10 @@ static int tegra_dc_init(struct host1x_client *client)
u32 value;
int err;
+ dc->syncpt = host1x_syncpt_request(dc->dev, flags);
+ if (!dc->syncpt)
+ dev_warn(dc->dev, "failed to allocate syncpoint\n");
+
if (tegra->domain) {
err = iommu_attach_device(tegra->domain, dc->dev);
if (err < 0) {
@@ -1849,6 +1852,8 @@ static int tegra_dc_exit(struct host1x_client *client)
dc->domain = NULL;
}
+ host1x_syncpt_free(dc->syncpt);
+
return 0;
}
@@ -1961,7 +1966,6 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
static int tegra_dc_probe(struct platform_device *pdev)
{
- unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
const struct of_device_id *id;
struct resource *regs;
struct tegra_dc *dc;
@@ -2036,10 +2040,6 @@ static int tegra_dc_probe(struct platform_device *pdev)
return -ENXIO;
}
- dc->syncpt = host1x_syncpt_request(&pdev->dev, flags);
- if (!dc->syncpt)
- dev_warn(&pdev->dev, "failed to allocate syncpoint\n");
-
INIT_LIST_HEAD(&dc->client.list);
dc->client.ops = &dc_client_ops;
dc->client.dev = &pdev->dev;
@@ -2067,8 +2067,6 @@ static int tegra_dc_remove(struct platform_device *pdev)
struct tegra_dc *dc = platform_get_drvdata(pdev);
int err;
- host1x_syncpt_free(dc->syncpt);
-
err = host1x_client_unregister(&dc->client);
if (err < 0) {
dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 224a7dc8e4ed..6aecb6647313 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -119,6 +119,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
*/
if (msg->size < 1) {
switch (msg->request & ~DP_AUX_I2C_MOT) {
+ case DP_AUX_I2C_WRITE_STATUS_UPDATE:
case DP_AUX_I2C_WRITE:
case DP_AUX_I2C_READ:
value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY;
@@ -149,7 +150,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
break;
- case DP_AUX_I2C_STATUS:
+ case DP_AUX_I2C_WRITE_STATUS_UPDATE:
if (msg->request & DP_AUX_I2C_MOT)
value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ;
else
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 6d88cf1fcd1c..159ef515cab1 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -56,7 +56,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra,
*/
drm_atomic_helper_commit_modeset_disables(drm, state);
- drm_atomic_helper_commit_planes(drm, state);
+ drm_atomic_helper_commit_planes(drm, state, false);
drm_atomic_helper_commit_modeset_enables(drm, state);
drm_atomic_helper_wait_for_vblanks(drm, state);
@@ -778,20 +778,20 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
#ifdef CONFIG_DRM_TEGRA_STAGING
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, 0),
#endif
};
@@ -822,7 +822,8 @@ static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm,
return NULL;
}
-static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe)
+static u32 tegra_drm_get_vblank_counter(struct drm_device *drm,
+ unsigned int pipe)
{
struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
struct tegra_dc *dc = to_tegra_dc(crtc);
@@ -833,7 +834,7 @@ static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe)
return tegra_dc_get_vblank_counter(dc);
}
-static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
+static int tegra_drm_enable_vblank(struct drm_device *drm, unsigned int pipe)
{
struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
struct tegra_dc *dc = to_tegra_dc(crtc);
@@ -846,7 +847,7 @@ static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
return 0;
}
-static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
+static void tegra_drm_disable_vblank(struct drm_device *drm, unsigned int pipe)
{
struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
struct tegra_dc *dc = to_tegra_dc(crtc);
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 07c844b746b4..1004075fd088 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -341,7 +341,6 @@ fini:
static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
{
-
drm_fb_helper_unregister_fbi(&fbdev->base);
drm_fb_helper_release_fbi(&fbdev->base);
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index da1715ebdd71..3eff7cf75d25 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -555,11 +555,11 @@ static int tegra_sor_compute_params(struct tegra_sor *sor,
error = div_s64(active_sym - approx, tu_size);
error *= params->num_clocks;
- if (error <= 0 && abs64(error) < params->error) {
+ if (error <= 0 && abs(error) < params->error) {
params->active_count = div_u64(active_count, f);
params->active_polarity = active_polarity;
params->active_frac = active_frac;
- params->error = abs64(error);
+ params->error = abs(error);
params->tu_size = tu_size;
if (error == 0)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 0f283a3b932c..876cad58b1f9 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -425,13 +425,13 @@ static void enable_vblank(struct drm_device *dev, bool enable)
tilcdc_clear(dev, reg, mask);
}
-static int tilcdc_enable_vblank(struct drm_device *dev, int crtc)
+static int tilcdc_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
enable_vblank(dev, true);
return 0;
}
-static void tilcdc_disable_vblank(struct drm_device *dev, int crtc)
+static void tilcdc_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
enable_vblank(dev, false);
}
@@ -563,7 +563,7 @@ static struct drm_driver tilcdc_driver = {
.irq_preinstall = tilcdc_irq_preinstall,
.irq_postinstall = tilcdc_irq_postinstall,
.irq_uninstall = tilcdc_irq_uninstall,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = tilcdc_enable_vblank,
.disable_vblank = tilcdc_disable_vblank,
.gem_free_object = drm_gem_cma_free_object,
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
new file mode 100644
index 000000000000..2d7d115ddf3f
--- /dev/null
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -0,0 +1,14 @@
+config DRM_VC4
+ tristate "Broadcom VC4 Graphics"
+ depends on ARCH_BCM2835 || COMPILE_TEST
+ depends on DRM && HAVE_DMA_ATTRS
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_GEM_CMA_HELPER
+ help
+ Choose this option if you have a system that has a Broadcom
+ VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835.
+
+ This driver requires that "avoid_warnings=2" be present in
+ the config.txt for the firmware, to keep it from smashing
+ our display setup.
diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
new file mode 100644
index 000000000000..32b4f9cd8f52
--- /dev/null
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -0,0 +1,17 @@
+ccflags-y := -Iinclude/drm
+
+# Please keep these build lists sorted!
+
+# core driver code
+vc4-y := \
+ vc4_bo.o \
+ vc4_crtc.o \
+ vc4_drv.o \
+ vc4_kms.o \
+ vc4_hdmi.o \
+ vc4_hvs.o \
+ vc4_plane.o
+
+vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
+
+obj-$(CONFIG_DRM_VC4) += vc4.o
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
new file mode 100644
index 000000000000..ab9f5108ae1a
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2015 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.
+ */
+
+/* DOC: VC4 GEM BO management support.
+ *
+ * The VC4 GPU architecture (both scanout and rendering) has direct
+ * access to system memory with no MMU in between. To support it, we
+ * use the GEM CMA helper functions to allocate contiguous ranges of
+ * physical memory for our BOs.
+ */
+
+#include "vc4_drv.h"
+
+struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size)
+{
+ struct drm_gem_cma_object *cma_obj;
+
+ cma_obj = drm_gem_cma_create(dev, size);
+ if (IS_ERR(cma_obj))
+ return NULL;
+ else
+ return to_vc4_bo(&cma_obj->base);
+}
+
+int vc4_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+ struct vc4_bo *bo = NULL;
+ int ret;
+
+ if (args->pitch < min_pitch)
+ args->pitch = min_pitch;
+
+ if (args->size < args->pitch * args->height)
+ args->size = args->pitch * args->height;
+
+ bo = vc4_bo_create(dev, roundup(args->size, PAGE_SIZE));
+ if (!bo)
+ return -ENOMEM;
+
+ ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);
+ drm_gem_object_unreference_unlocked(&bo->base.base);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
new file mode 100644
index 000000000000..265064c62d49
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -0,0 +1,673 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * DOC: VC4 CRTC module
+ *
+ * In VC4, the Pixel Valve is what most closely corresponds to the
+ * DRM's concept of a CRTC. The PV generates video timings from the
+ * output's clock plus its configuration. It pulls scaled pixels from
+ * the HVS at that timing, and feeds it to the encoder.
+ *
+ * However, the DRM CRTC also collects the configuration of all the
+ * DRM planes attached to it. As a result, this file also manages
+ * setup of the VC4 HVS's display elements on the CRTC.
+ *
+ * The 2835 has 3 different pixel valves. pv0 in the audio power
+ * domain feeds DSI0 or DPI, while pv1 feeds DS1 or SMI. pv2 in the
+ * image domain can feed either HDMI or the SDTV controller. The
+ * pixel valve chooses from the CPRMAN clocks (HSM for HDMI, VEC for
+ * SDTV, etc.) according to which output type is chosen in the mux.
+ *
+ * For power management, the pixel valve's registers are all clocked
+ * by the AXI clock, while the timings and FIFOs make use of the
+ * output-specific clock. Since the encoders also directly consume
+ * the CPRMAN clocks, and know what timings they need, they are the
+ * ones that set the clock.
+ */
+
+#include "drm_atomic.h"
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "linux/clk.h"
+#include "linux/component.h"
+#include "linux/of_device.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+struct vc4_crtc {
+ struct drm_crtc base;
+ const struct vc4_crtc_data *data;
+ void __iomem *regs;
+
+ /* Which HVS channel we're using for our CRTC. */
+ int channel;
+
+ /* Pointer to the actual hardware display list memory for the
+ * crtc.
+ */
+ u32 __iomem *dlist;
+
+ u32 dlist_size; /* in dwords */
+
+ struct drm_pending_vblank_event *event;
+};
+
+static inline struct vc4_crtc *
+to_vc4_crtc(struct drm_crtc *crtc)
+{
+ return (struct vc4_crtc *)crtc;
+}
+
+struct vc4_crtc_data {
+ /* Which channel of the HVS this pixelvalve sources from. */
+ int hvs_channel;
+
+ enum vc4_encoder_type encoder0_type;
+ enum vc4_encoder_type encoder1_type;
+};
+
+#define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
+#define CRTC_READ(offset) readl(vc4_crtc->regs + (offset))
+
+#define CRTC_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} crtc_regs[] = {
+ CRTC_REG(PV_CONTROL),
+ CRTC_REG(PV_V_CONTROL),
+ CRTC_REG(PV_VSYNCD),
+ CRTC_REG(PV_HORZA),
+ CRTC_REG(PV_HORZB),
+ CRTC_REG(PV_VERTA),
+ CRTC_REG(PV_VERTB),
+ CRTC_REG(PV_VERTA_EVEN),
+ CRTC_REG(PV_VERTB_EVEN),
+ CRTC_REG(PV_INTEN),
+ CRTC_REG(PV_INTSTAT),
+ CRTC_REG(PV_STAT),
+ CRTC_REG(PV_HACT_ACT),
+};
+
+static void vc4_crtc_dump_regs(struct vc4_crtc *vc4_crtc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(crtc_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ crtc_regs[i].reg, crtc_regs[i].name,
+ CRTC_READ(crtc_regs[i].reg));
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_crtc_debugfs_regs(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ int crtc_index = (uintptr_t)node->info_ent->data;
+ struct drm_crtc *crtc;
+ struct vc4_crtc *vc4_crtc;
+ int i;
+
+ i = 0;
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (i == crtc_index)
+ break;
+ i++;
+ }
+ if (!crtc)
+ return 0;
+ vc4_crtc = to_vc4_crtc(crtc);
+
+ for (i = 0; i < ARRAY_SIZE(crtc_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ crtc_regs[i].name, crtc_regs[i].reg,
+ CRTC_READ(crtc_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif
+
+static void vc4_crtc_destroy(struct drm_crtc *crtc)
+{
+ drm_crtc_cleanup(crtc);
+}
+
+static u32 vc4_get_fifo_full_level(u32 format)
+{
+ static const u32 fifo_len_bytes = 64;
+ static const u32 hvs_latency_pix = 6;
+
+ switch (format) {
+ case PV_CONTROL_FORMAT_DSIV_16:
+ case PV_CONTROL_FORMAT_DSIC_16:
+ return fifo_len_bytes - 2 * hvs_latency_pix;
+ case PV_CONTROL_FORMAT_DSIV_18:
+ return fifo_len_bytes - 14;
+ case PV_CONTROL_FORMAT_24:
+ case PV_CONTROL_FORMAT_DSIV_24:
+ default:
+ return fifo_len_bytes - 3 * hvs_latency_pix;
+ }
+}
+
+/*
+ * Returns the clock select bit for the connector attached to the
+ * CRTC.
+ */
+static int vc4_get_clock_select(struct drm_crtc *crtc)
+{
+ struct drm_connector *connector;
+
+ drm_for_each_connector(connector, crtc->dev) {
+ if (connector->state->crtc == crtc) {
+ struct drm_encoder *encoder = connector->encoder;
+ struct vc4_encoder *vc4_encoder =
+ to_vc4_encoder(encoder);
+
+ return vc4_encoder->clock_select;
+ }
+ }
+
+ return -1;
+}
+
+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_crtc_state *state = crtc->state;
+ struct drm_display_mode *mode = &state->adjusted_mode;
+ bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
+ u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0));
+ u32 format = PV_CONTROL_FORMAT_24;
+ bool debug_dump_regs = false;
+ int clock_select = vc4_get_clock_select(crtc);
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc));
+ vc4_crtc_dump_regs(vc4_crtc);
+ }
+
+ /* Reset the PV fifo. */
+ CRTC_WRITE(PV_CONTROL, 0);
+ CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+ CRTC_WRITE(PV_CONTROL, 0);
+
+ CRTC_WRITE(PV_HORZA,
+ VC4_SET_FIELD(mode->htotal - mode->hsync_end,
+ PV_HORZA_HBP) |
+ VC4_SET_FIELD(mode->hsync_end - mode->hsync_start,
+ PV_HORZA_HSYNC));
+ CRTC_WRITE(PV_HORZB,
+ VC4_SET_FIELD(mode->hsync_start - mode->hdisplay,
+ PV_HORZB_HFP) |
+ VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
+
+ if (interlace) {
+ CRTC_WRITE(PV_VERTA_EVEN,
+ VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
+ PV_VERTA_VBP) |
+ VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+ PV_VERTA_VSYNC));
+ CRTC_WRITE(PV_VERTB_EVEN,
+ VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+ PV_VERTB_VFP) |
+ VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+ }
+
+ CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
+
+ CRTC_WRITE(PV_V_CONTROL,
+ PV_VCONTROL_CONTINUOUS |
+ (interlace ? PV_VCONTROL_INTERLACE : 0));
+
+ CRTC_WRITE(PV_CONTROL,
+ VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
+ VC4_SET_FIELD(vc4_get_fifo_full_level(format),
+ PV_CONTROL_FIFO_LEVEL) |
+ PV_CONTROL_CLR_AT_START |
+ PV_CONTROL_TRIGGER_UNDERFLOW |
+ PV_CONTROL_WAIT_HSTART |
+ VC4_SET_FIELD(clock_select, PV_CONTROL_CLK_SELECT) |
+ PV_CONTROL_FIFO_CLR |
+ PV_CONTROL_EN);
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
+ vc4_crtc_dump_regs(vc4_crtc);
+ }
+}
+
+static void require_hvs_enabled(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ WARN_ON_ONCE((HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE) !=
+ SCALER_DISPCTRL_ENABLE);
+}
+
+static void vc4_crtc_disable(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ u32 chan = vc4_crtc->channel;
+ int ret;
+ require_hvs_enabled(dev);
+
+ CRTC_WRITE(PV_V_CONTROL,
+ CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
+ ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
+ WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
+
+ if (HVS_READ(SCALER_DISPCTRLX(chan)) &
+ SCALER_DISPCTRLX_ENABLE) {
+ HVS_WRITE(SCALER_DISPCTRLX(chan),
+ SCALER_DISPCTRLX_RESET);
+
+ /* While the docs say that reset is self-clearing, it
+ * seems it doesn't actually.
+ */
+ HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+ }
+
+ /* Once we leave, the scaler should be disabled and its fifo empty. */
+
+ WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
+
+ WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
+ SCALER_DISPSTATX_MODE) !=
+ SCALER_DISPSTATX_MODE_DISABLED);
+
+ WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
+ (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
+ SCALER_DISPSTATX_EMPTY);
+}
+
+static void vc4_crtc_enable(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_crtc_state *state = crtc->state;
+ struct drm_display_mode *mode = &state->adjusted_mode;
+
+ require_hvs_enabled(dev);
+
+ /* Turn on the scaler, which will wait for vstart to start
+ * compositing.
+ */
+ HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel),
+ VC4_SET_FIELD(mode->hdisplay, SCALER_DISPCTRLX_WIDTH) |
+ VC4_SET_FIELD(mode->vdisplay, SCALER_DISPCTRLX_HEIGHT) |
+ SCALER_DISPCTRLX_ENABLE);
+
+ /* Turn on the pixel valve, which will emit the vstart signal. */
+ CRTC_WRITE(PV_V_CONTROL,
+ CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+}
+
+static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct drm_plane *plane;
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ u32 dlist_count = 0;
+
+ /* The pixelvalve can only feed one encoder (and encoders are
+ * 1:1 with connectors.)
+ */
+ if (drm_atomic_connectors_for_crtc(state->state, crtc) > 1)
+ return -EINVAL;
+
+ drm_atomic_crtc_state_for_each_plane(plane, state) {
+ struct drm_plane_state *plane_state =
+ state->state->plane_states[drm_plane_index(plane)];
+
+ /* plane might not have changed, in which case take
+ * current state:
+ */
+ if (!plane_state)
+ plane_state = plane->state;
+
+ dlist_count += vc4_plane_dlist_size(plane_state);
+ }
+
+ dlist_count++; /* Account for SCALER_CTL0_END. */
+
+ if (!vc4_crtc->dlist || dlist_count > vc4_crtc->dlist_size) {
+ vc4_crtc->dlist = ((u32 __iomem *)vc4->hvs->dlist +
+ HVS_BOOTLOADER_DLIST_END);
+ vc4_crtc->dlist_size = ((SCALER_DLIST_SIZE >> 2) -
+ HVS_BOOTLOADER_DLIST_END);
+
+ if (dlist_count > vc4_crtc->dlist_size) {
+ DRM_DEBUG_KMS("dlist too large for CRTC (%d > %d).\n",
+ dlist_count, vc4_crtc->dlist_size);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_plane *plane;
+ bool debug_dump_regs = false;
+ u32 __iomem *dlist_next = vc4_crtc->dlist;
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
+ vc4_hvs_dump_state(dev);
+ }
+
+ /* Copy all the active planes' dlist contents to the hardware dlist.
+ *
+ * XXX: If the new display list was large enough that it
+ * overlapped a currently-read display list, we need to do
+ * something like disable scanout before putting in the new
+ * list. For now, we're safe because we only have the two
+ * planes.
+ */
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
+ dlist_next += vc4_plane_write_dlist(plane, dlist_next);
+ }
+
+ if (dlist_next == vc4_crtc->dlist) {
+ /* If no planes were enabled, use the SCALER_CTL0_END
+ * at the start of the display list memory (in the
+ * bootloader section). We'll rewrite that
+ * SCALER_CTL0_END, just in case, though.
+ */
+ writel(SCALER_CTL0_END, vc4->hvs->dlist);
+ HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel), 0);
+ } else {
+ writel(SCALER_CTL0_END, dlist_next);
+ dlist_next++;
+
+ HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+ (u32 __iomem *)vc4_crtc->dlist -
+ (u32 __iomem *)vc4->hvs->dlist);
+
+ /* Make the next display list start after ours. */
+ vc4_crtc->dlist_size -= (dlist_next - vc4_crtc->dlist);
+ vc4_crtc->dlist = dlist_next;
+ }
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
+ vc4_hvs_dump_state(dev);
+ }
+
+ if (crtc->state->event) {
+ unsigned long flags;
+
+ crtc->state->event->pipe = drm_crtc_index(crtc);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ vc4_crtc->event = crtc->state->event;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ crtc->state->event = NULL;
+ }
+}
+
+int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id];
+
+ CRTC_WRITE(PV_INTEN, PV_INT_VFP_START);
+
+ return 0;
+}
+
+void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id];
+
+ CRTC_WRITE(PV_INTEN, 0);
+}
+
+static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
+{
+ struct drm_crtc *crtc = &vc4_crtc->base;
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (vc4_crtc->event) {
+ drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
+ vc4_crtc->event = NULL;
+ }
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
+{
+ struct vc4_crtc *vc4_crtc = data;
+ u32 stat = CRTC_READ(PV_INTSTAT);
+ irqreturn_t ret = IRQ_NONE;
+
+ if (stat & PV_INT_VFP_START) {
+ CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
+ drm_crtc_handle_vblank(&vc4_crtc->base);
+ vc4_crtc_handle_page_flip(vc4_crtc);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static const struct drm_crtc_funcs vc4_crtc_funcs = {
+ .set_config = drm_atomic_helper_set_config,
+ .destroy = vc4_crtc_destroy,
+ .page_flip = drm_atomic_helper_page_flip,
+ .set_property = NULL,
+ .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
+ .cursor_move = NULL, /* handled by drm_mode_cursor_universal */
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
+ .mode_set_nofb = vc4_crtc_mode_set_nofb,
+ .disable = vc4_crtc_disable,
+ .enable = vc4_crtc_enable,
+ .atomic_check = vc4_crtc_atomic_check,
+ .atomic_flush = vc4_crtc_atomic_flush,
+};
+
+/* Frees the page flip event when the DRM device is closed with the
+ * event still outstanding.
+ */
+void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) {
+ vc4_crtc->event->base.destroy(&vc4_crtc->event->base);
+ drm_crtc_vblank_put(crtc);
+ vc4_crtc->event = NULL;
+ }
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static const struct vc4_crtc_data pv0_data = {
+ .hvs_channel = 0,
+ .encoder0_type = VC4_ENCODER_TYPE_DSI0,
+ .encoder1_type = VC4_ENCODER_TYPE_DPI,
+};
+
+static const struct vc4_crtc_data pv1_data = {
+ .hvs_channel = 2,
+ .encoder0_type = VC4_ENCODER_TYPE_DSI1,
+ .encoder1_type = VC4_ENCODER_TYPE_SMI,
+};
+
+static const struct vc4_crtc_data pv2_data = {
+ .hvs_channel = 1,
+ .encoder0_type = VC4_ENCODER_TYPE_VEC,
+ .encoder1_type = VC4_ENCODER_TYPE_HDMI,
+};
+
+static const struct of_device_id vc4_crtc_dt_match[] = {
+ { .compatible = "brcm,bcm2835-pixelvalve0", .data = &pv0_data },
+ { .compatible = "brcm,bcm2835-pixelvalve1", .data = &pv1_data },
+ { .compatible = "brcm,bcm2835-pixelvalve2", .data = &pv2_data },
+ {}
+};
+
+static void vc4_set_crtc_possible_masks(struct drm_device *drm,
+ struct drm_crtc *crtc)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_encoder *encoder;
+
+ drm_for_each_encoder(encoder, drm) {
+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+
+ if (vc4_encoder->type == vc4_crtc->data->encoder0_type) {
+ vc4_encoder->clock_select = 0;
+ encoder->possible_crtcs |= drm_crtc_mask(crtc);
+ } else if (vc4_encoder->type == vc4_crtc->data->encoder1_type) {
+ vc4_encoder->clock_select = 1;
+ encoder->possible_crtcs |= drm_crtc_mask(crtc);
+ }
+ }
+}
+
+static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = to_vc4_dev(drm);
+ struct vc4_crtc *vc4_crtc;
+ struct drm_crtc *crtc;
+ struct drm_plane *primary_plane, *cursor_plane;
+ const struct of_device_id *match;
+ int ret;
+
+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+ if (!vc4_crtc)
+ return -ENOMEM;
+ crtc = &vc4_crtc->base;
+
+ match = of_match_device(vc4_crtc_dt_match, dev);
+ if (!match)
+ return -ENODEV;
+ vc4_crtc->data = match->data;
+
+ vc4_crtc->regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(vc4_crtc->regs))
+ return PTR_ERR(vc4_crtc->regs);
+
+ /* For now, we create just the primary and the legacy cursor
+ * planes. We should be able to stack more planes on easily,
+ * but to do that we would need to compute the bandwidth
+ * requirement of the plane configuration, and reject ones
+ * that will take too much.
+ */
+ primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
+ if (IS_ERR(primary_plane)) {
+ dev_err(dev, "failed to construct primary plane\n");
+ ret = PTR_ERR(primary_plane);
+ goto err;
+ }
+
+ cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
+ if (IS_ERR(cursor_plane)) {
+ dev_err(dev, "failed to construct cursor plane\n");
+ ret = PTR_ERR(cursor_plane);
+ goto err_primary;
+ }
+
+ drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
+ &vc4_crtc_funcs);
+ drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
+ primary_plane->crtc = crtc;
+ cursor_plane->crtc = crtc;
+ vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc;
+ vc4_crtc->channel = vc4_crtc->data->hvs_channel;
+
+ CRTC_WRITE(PV_INTEN, 0);
+ CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+ vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc);
+ if (ret)
+ goto err_cursor;
+
+ vc4_set_crtc_possible_masks(drm, crtc);
+
+ platform_set_drvdata(pdev, vc4_crtc);
+
+ return 0;
+
+err_cursor:
+ cursor_plane->funcs->destroy(cursor_plane);
+err_primary:
+ primary_plane->funcs->destroy(primary_plane);
+err:
+ return ret;
+}
+
+static void vc4_crtc_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev);
+
+ vc4_crtc_destroy(&vc4_crtc->base);
+
+ CRTC_WRITE(PV_INTEN, 0);
+
+ platform_set_drvdata(pdev, NULL);
+}
+
+static const struct component_ops vc4_crtc_ops = {
+ .bind = vc4_crtc_bind,
+ .unbind = vc4_crtc_unbind,
+};
+
+static int vc4_crtc_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_crtc_ops);
+}
+
+static int vc4_crtc_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_crtc_ops);
+ return 0;
+}
+
+struct platform_driver vc4_crtc_driver = {
+ .probe = vc4_crtc_dev_probe,
+ .remove = vc4_crtc_dev_remove,
+ .driver = {
+ .name = "vc4_crtc",
+ .of_match_table = vc4_crtc_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c
new file mode 100644
index 000000000000..4297b0a5b74e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/circ_buf.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <drm/drmP.h>
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+static const struct drm_info_list vc4_debugfs_list[] = {
+ {"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
+ {"hvs_regs", vc4_hvs_debugfs_regs, 0},
+ {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
+ {"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1},
+ {"crtc2_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)2},
+};
+
+#define VC4_DEBUGFS_ENTRIES ARRAY_SIZE(vc4_debugfs_list)
+
+int
+vc4_debugfs_init(struct drm_minor *minor)
+{
+ return drm_debugfs_create_files(vc4_debugfs_list, VC4_DEBUGFS_ENTRIES,
+ minor->debugfs_root, minor);
+}
+
+void
+vc4_debugfs_cleanup(struct drm_minor *minor)
+{
+ drm_debugfs_remove_files(vc4_debugfs_list, VC4_DEBUGFS_ENTRIES, minor);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
new file mode 100644
index 000000000000..d5db9e0f3b73
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include "drm_fb_cma_helper.h"
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+#define DRIVER_NAME "vc4"
+#define DRIVER_DESC "Broadcom VC4 graphics"
+#define DRIVER_DATE "20140616"
+#define DRIVER_MAJOR 0
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+/* Helper function for mapping the regs on a platform device. */
+void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index)
+{
+ struct resource *res;
+ void __iomem *map;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, index);
+ map = devm_ioremap_resource(&dev->dev, res);
+ if (IS_ERR(map)) {
+ DRM_ERROR("Failed to map registers: %ld\n", PTR_ERR(map));
+ return map;
+ }
+
+ return map;
+}
+
+static void vc4_drm_preclose(struct drm_device *dev, struct drm_file *file)
+{
+ struct drm_crtc *crtc;
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+ vc4_cancel_page_flip(crtc, file);
+}
+
+static void vc4_lastclose(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (vc4->fbdev)
+ drm_fbdev_cma_restore_mode(vc4->fbdev);
+}
+
+static const struct file_operations vc4_drm_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .mmap = drm_gem_cma_mmap,
+ .poll = drm_poll,
+ .read = drm_read,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .llseek = noop_llseek,
+};
+
+static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
+};
+
+static struct drm_driver vc4_drm_driver = {
+ .driver_features = (DRIVER_MODESET |
+ DRIVER_ATOMIC |
+ DRIVER_GEM |
+ DRIVER_PRIME),
+ .lastclose = vc4_lastclose,
+ .preclose = vc4_drm_preclose,
+
+ .enable_vblank = vc4_enable_vblank,
+ .disable_vblank = vc4_disable_vblank,
+ .get_vblank_counter = drm_vblank_count,
+
+#if defined(CONFIG_DEBUG_FS)
+ .debugfs_init = vc4_debugfs_init,
+ .debugfs_cleanup = vc4_debugfs_cleanup,
+#endif
+
+ .gem_free_object = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+
+ .dumb_create = vc4_dumb_create,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+
+ .ioctls = vc4_drm_ioctls,
+ .num_ioctls = ARRAY_SIZE(vc4_drm_ioctls),
+ .fops = &vc4_drm_fops,
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int compare_dev(struct device *dev, void *data)
+{
+ return dev == data;
+}
+
+static void vc4_match_add_drivers(struct device *dev,
+ struct component_match **match,
+ struct platform_driver *const *drivers,
+ int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ struct device_driver *drv = &drivers[i]->driver;
+ struct device *p = NULL, *d;
+
+ while ((d = bus_find_device(&platform_bus_type, p, drv,
+ (void *)platform_bus_type.match))) {
+ put_device(p);
+ component_match_add(dev, match, compare_dev, d);
+ p = d;
+ }
+ put_device(p);
+ }
+}
+
+static int vc4_drm_bind(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm;
+ struct drm_connector *connector;
+ struct vc4_dev *vc4;
+ int ret = 0;
+
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL);
+ if (!vc4)
+ return -ENOMEM;
+
+ drm = drm_dev_alloc(&vc4_drm_driver, dev);
+ if (!drm)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drm);
+ vc4->dev = drm;
+ drm->dev_private = vc4;
+
+ drm_dev_set_unique(drm, dev_name(dev));
+
+ drm_mode_config_init(drm);
+ if (ret)
+ goto unref;
+
+ ret = component_bind_all(dev, drm);
+ if (ret)
+ goto unref;
+
+ ret = drm_dev_register(drm, 0);
+ if (ret < 0)
+ goto unbind_all;
+
+ /* Connector registration has to occur after DRM device
+ * registration, because it creates sysfs entries based on the
+ * DRM device.
+ */
+ list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+ ret = drm_connector_register(connector);
+ if (ret)
+ goto unregister;
+ }
+
+ vc4_kms_load(drm);
+
+ return 0;
+
+unregister:
+ drm_dev_unregister(drm);
+unbind_all:
+ component_unbind_all(dev, drm);
+unref:
+ drm_dev_unref(drm);
+ return ret;
+}
+
+static void vc4_drm_unbind(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = platform_get_drvdata(pdev);
+ struct vc4_dev *vc4 = to_vc4_dev(drm);
+
+ if (vc4->fbdev)
+ drm_fbdev_cma_fini(vc4->fbdev);
+
+ drm_mode_config_cleanup(drm);
+
+ drm_put_dev(drm);
+}
+
+static const struct component_master_ops vc4_drm_ops = {
+ .bind = vc4_drm_bind,
+ .unbind = vc4_drm_unbind,
+};
+
+static struct platform_driver *const component_drivers[] = {
+ &vc4_hdmi_driver,
+ &vc4_crtc_driver,
+ &vc4_hvs_driver,
+};
+
+static int vc4_platform_drm_probe(struct platform_device *pdev)
+{
+ struct component_match *match = NULL;
+ struct device *dev = &pdev->dev;
+
+ vc4_match_add_drivers(dev, &match,
+ component_drivers, ARRAY_SIZE(component_drivers));
+
+ return component_master_add_with_match(dev, &vc4_drm_ops, match);
+}
+
+static int vc4_platform_drm_remove(struct platform_device *pdev)
+{
+ component_master_del(&pdev->dev, &vc4_drm_ops);
+
+ return 0;
+}
+
+static const struct of_device_id vc4_of_match[] = {
+ { .compatible = "brcm,bcm2835-vc4", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, vc4_of_match);
+
+static struct platform_driver vc4_platform_driver = {
+ .probe = vc4_platform_drm_probe,
+ .remove = vc4_platform_drm_remove,
+ .driver = {
+ .name = "vc4-drm",
+ .of_match_table = vc4_of_match,
+ },
+};
+
+static int __init vc4_drm_register(void)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(component_drivers); i++) {
+ ret = platform_driver_register(component_drivers[i]);
+ if (ret) {
+ while (--i >= 0)
+ platform_driver_unregister(component_drivers[i]);
+ return ret;
+ }
+ }
+ return platform_driver_register(&vc4_platform_driver);
+}
+
+static void __exit vc4_drm_unregister(void)
+{
+ int i;
+
+ for (i = ARRAY_SIZE(component_drivers) - 1; i >= 0; i--)
+ platform_driver_unregister(component_drivers[i]);
+
+ platform_driver_unregister(&vc4_platform_driver);
+}
+
+module_init(vc4_drm_register);
+module_exit(vc4_drm_unregister);
+
+MODULE_ALIAS("platform:vc4-drm");
+MODULE_DESCRIPTION("Broadcom VC4 DRM Driver");
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
new file mode 100644
index 000000000000..fd8319fa682e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "drmP.h"
+#include "drm_gem_cma_helper.h"
+
+struct vc4_dev {
+ struct drm_device *dev;
+
+ struct vc4_hdmi *hdmi;
+ struct vc4_hvs *hvs;
+ struct vc4_crtc *crtc[3];
+
+ struct drm_fbdev_cma *fbdev;
+};
+
+static inline struct vc4_dev *
+to_vc4_dev(struct drm_device *dev)
+{
+ return (struct vc4_dev *)dev->dev_private;
+}
+
+struct vc4_bo {
+ struct drm_gem_cma_object base;
+};
+
+static inline struct vc4_bo *
+to_vc4_bo(struct drm_gem_object *bo)
+{
+ return (struct vc4_bo *)bo;
+}
+
+struct vc4_hvs {
+ struct platform_device *pdev;
+ void __iomem *regs;
+ void __iomem *dlist;
+};
+
+struct vc4_plane {
+ struct drm_plane base;
+};
+
+static inline struct vc4_plane *
+to_vc4_plane(struct drm_plane *plane)
+{
+ return (struct vc4_plane *)plane;
+}
+
+enum vc4_encoder_type {
+ VC4_ENCODER_TYPE_HDMI,
+ VC4_ENCODER_TYPE_VEC,
+ VC4_ENCODER_TYPE_DSI0,
+ VC4_ENCODER_TYPE_DSI1,
+ VC4_ENCODER_TYPE_SMI,
+ VC4_ENCODER_TYPE_DPI,
+};
+
+struct vc4_encoder {
+ struct drm_encoder base;
+ enum vc4_encoder_type type;
+ u32 clock_select;
+};
+
+static inline struct vc4_encoder *
+to_vc4_encoder(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct vc4_encoder, base);
+}
+
+#define HVS_READ(offset) readl(vc4->hvs->regs + offset)
+#define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset)
+
+/**
+ * _wait_for - magic (register) wait macro
+ *
+ * Does the right thing for modeset paths when run under kdgb or similar atomic
+ * contexts. Note that it's important that we check the condition again after
+ * having timed out, since the timeout could be due to preemption or similar and
+ * we've never had a chance to check the condition before the timeout.
+ */
+#define _wait_for(COND, MS, W) ({ \
+ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
+ int ret__ = 0; \
+ while (!(COND)) { \
+ if (time_after(jiffies, timeout__)) { \
+ if (!(COND)) \
+ ret__ = -ETIMEDOUT; \
+ break; \
+ } \
+ if (W && drm_can_sleep()) { \
+ msleep(W); \
+ } else { \
+ cpu_relax(); \
+ } \
+ } \
+ ret__; \
+})
+
+#define wait_for(COND, MS) _wait_for(COND, MS, 1)
+
+/* vc4_bo.c */
+void vc4_free_object(struct drm_gem_object *gem_obj);
+struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size);
+int vc4_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+struct dma_buf *vc4_prime_export(struct drm_device *dev,
+ struct drm_gem_object *obj, int flags);
+
+/* vc4_crtc.c */
+extern struct platform_driver vc4_crtc_driver;
+int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
+void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
+void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
+int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
+
+/* vc4_debugfs.c */
+int vc4_debugfs_init(struct drm_minor *minor);
+void vc4_debugfs_cleanup(struct drm_minor *minor);
+
+/* vc4_drv.c */
+void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index);
+
+/* vc4_hdmi.c */
+extern struct platform_driver vc4_hdmi_driver;
+int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused);
+
+/* vc4_hvs.c */
+extern struct platform_driver vc4_hvs_driver;
+void vc4_hvs_dump_state(struct drm_device *dev);
+int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused);
+
+/* vc4_kms.c */
+int vc4_kms_load(struct drm_device *dev);
+
+/* vc4_plane.c */
+struct drm_plane *vc4_plane_init(struct drm_device *dev,
+ enum drm_plane_type type);
+u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
+u32 vc4_plane_dlist_size(struct drm_plane_state *state);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
new file mode 100644
index 000000000000..da9a36d6e1d1
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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/>.
+ */
+
+/**
+ * DOC: VC4 Falcon HDMI module
+ *
+ * The HDMI core has a state machine and a PHY. Most of the unit
+ * operates off of the HSM clock from CPRMAN. It also internally uses
+ * the PLLH_PIX clock for the PHY.
+ */
+
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "drm_edid.h"
+#include "linux/clk.h"
+#include "linux/component.h"
+#include "linux/i2c.h"
+#include "linux/of_gpio.h"
+#include "linux/of_platform.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+/* General HDMI hardware state. */
+struct vc4_hdmi {
+ struct platform_device *pdev;
+
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+
+ struct i2c_adapter *ddc;
+ void __iomem *hdmicore_regs;
+ void __iomem *hd_regs;
+ int hpd_gpio;
+
+ struct clk *pixel_clock;
+ struct clk *hsm_clock;
+};
+
+#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+ struct vc4_encoder base;
+ bool hdmi_monitor;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+ struct drm_connector base;
+
+ /* Since the connector is attached to just the one encoder,
+ * this is the reference to it so we can do the best_encoder()
+ * hook.
+ */
+ struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+ return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
+#define HDMI_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} hdmi_regs[] = {
+ HDMI_REG(VC4_HDMI_CORE_REV),
+ HDMI_REG(VC4_HDMI_SW_RESET_CONTROL),
+ HDMI_REG(VC4_HDMI_HOTPLUG_INT),
+ HDMI_REG(VC4_HDMI_HOTPLUG),
+ HDMI_REG(VC4_HDMI_HORZA),
+ HDMI_REG(VC4_HDMI_HORZB),
+ HDMI_REG(VC4_HDMI_FIFO_CTL),
+ HDMI_REG(VC4_HDMI_SCHEDULER_CONTROL),
+ HDMI_REG(VC4_HDMI_VERTA0),
+ HDMI_REG(VC4_HDMI_VERTA1),
+ HDMI_REG(VC4_HDMI_VERTB0),
+ HDMI_REG(VC4_HDMI_VERTB1),
+ HDMI_REG(VC4_HDMI_TX_PHY_RESET_CTL),
+};
+
+static const struct {
+ u32 reg;
+ const char *name;
+} hd_regs[] = {
+ HDMI_REG(VC4_HD_M_CTL),
+ HDMI_REG(VC4_HD_MAI_CTL),
+ HDMI_REG(VC4_HD_VID_CTL),
+ HDMI_REG(VC4_HD_CSC_CTL),
+ HDMI_REG(VC4_HD_FRAME_COUNT),
+};
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ hdmi_regs[i].name, hdmi_regs[i].reg,
+ HDMI_READ(hdmi_regs[i].reg));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ hd_regs[i].name, hd_regs[i].reg,
+ HD_READ(hd_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static void vc4_hdmi_dump_regs(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ hdmi_regs[i].reg, hdmi_regs[i].name,
+ HDMI_READ(hdmi_regs[i].reg));
+ }
+ for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ hd_regs[i].reg, hd_regs[i].name,
+ HD_READ(hd_regs[i].reg));
+ }
+}
+
+static enum drm_connector_status
+vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct drm_device *dev = connector->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (vc4->hdmi->hpd_gpio) {
+ if (gpio_get_value(vc4->hdmi->hpd_gpio))
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+ }
+
+ if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+}
+
+static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+ struct vc4_hdmi_connector *vc4_connector =
+ to_vc4_hdmi_connector(connector);
+ struct drm_encoder *encoder = vc4_connector->encoder;
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+ struct drm_device *dev = connector->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int ret = 0;
+ struct edid *edid;
+
+ edid = drm_get_edid(connector, vc4->hdmi->ddc);
+ if (!edid)
+ return -ENODEV;
+
+ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+
+ return ret;
+}
+
+static struct drm_encoder *
+vc4_hdmi_connector_best_encoder(struct drm_connector *connector)
+{
+ struct vc4_hdmi_connector *hdmi_connector =
+ to_vc4_hdmi_connector(connector);
+ return hdmi_connector->encoder;
+}
+
+static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = vc4_hdmi_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = vc4_hdmi_connector_destroy,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = {
+ .get_modes = vc4_hdmi_connector_get_modes,
+ .best_encoder = vc4_hdmi_connector_best_encoder,
+};
+
+static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
+ struct drm_encoder *encoder)
+{
+ struct drm_connector *connector = NULL;
+ struct vc4_hdmi_connector *hdmi_connector;
+ int ret = 0;
+
+ hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
+ GFP_KERNEL);
+ if (!hdmi_connector) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ connector = &hdmi_connector->base;
+
+ hdmi_connector->encoder = encoder;
+
+ drm_connector_init(dev, connector, &vc4_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
+
+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT);
+
+ connector->interlace_allowed = 0;
+ connector->doublescan_allowed = 0;
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ return connector;
+
+ fail:
+ if (connector)
+ vc4_hdmi_connector_destroy(connector);
+
+ return ERR_PTR(ret);
+}
+
+static void vc4_hdmi_encoder_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
+ .destroy = vc4_hdmi_encoder_destroy,
+};
+
+static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *unadjusted_mode,
+ struct drm_display_mode *mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ bool debug_dump_regs = false;
+ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+ bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
+ u32 vactive = (mode->vdisplay >>
+ ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
+ u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+ VC4_HDMI_VERTA_VSP) |
+ VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+ VC4_HDMI_VERTA_VFP) |
+ VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL));
+ u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
+ VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
+ VC4_HDMI_VERTB_VBP));
+
+ if (debug_dump_regs) {
+ DRM_INFO("HDMI regs before:\n");
+ vc4_hdmi_dump_regs(dev);
+ }
+
+ HD_WRITE(VC4_HD_VID_CTL, 0);
+
+ clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000);
+
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
+ VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
+
+ HDMI_WRITE(VC4_HDMI_HORZA,
+ (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
+ (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
+ VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP));
+
+ HDMI_WRITE(VC4_HDMI_HORZB,
+ VC4_SET_FIELD(mode->htotal - mode->hsync_end,
+ VC4_HDMI_HORZB_HBP) |
+ VC4_SET_FIELD(mode->hsync_end - mode->hsync_start,
+ VC4_HDMI_HORZB_HSP) |
+ VC4_SET_FIELD(mode->hsync_start - mode->hdisplay,
+ VC4_HDMI_HORZB_HFP));
+
+ HDMI_WRITE(VC4_HDMI_VERTA0, verta);
+ HDMI_WRITE(VC4_HDMI_VERTA1, verta);
+
+ HDMI_WRITE(VC4_HDMI_VERTB0, vertb);
+ HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
+
+ HD_WRITE(VC4_HD_VID_CTL,
+ (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+ (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+
+ /* The RGB order applies even when CSC is disabled. */
+ HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
+ VC4_HD_CSC_CTL_ORDER));
+
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+
+ if (debug_dump_regs) {
+ DRM_INFO("HDMI regs after:\n");
+ vc4_hdmi_dump_regs(dev);
+ }
+}
+
+static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+ HD_WRITE(VC4_HD_VID_CTL,
+ HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
+}
+
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int ret;
+
+ HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
+
+ HD_WRITE(VC4_HD_VID_CTL,
+ HD_READ(VC4_HD_VID_CTL) |
+ VC4_HD_VID_CTL_ENABLE |
+ VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
+ VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+
+ if (vc4_encoder->hdmi_monitor) {
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
+
+ ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
+ } else {
+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+ ~(VC4_HDMI_RAM_PACKET_ENABLE));
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
+
+ ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
+ }
+
+ if (vc4_encoder->hdmi_monitor) {
+ u32 drift;
+
+ WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
+
+ /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set
+ * up the infoframe.
+ */
+
+ drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
+ drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
+
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
+ udelay(1000);
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
+
+ ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
+ VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
+ }
+}
+
+static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
+ .mode_set = vc4_hdmi_encoder_mode_set,
+ .disable = vc4_hdmi_encoder_disable,
+ .enable = vc4_hdmi_encoder_enable,
+};
+
+static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+ struct vc4_hdmi *hdmi;
+ struct vc4_hdmi_encoder *vc4_hdmi_encoder;
+ struct device_node *ddc_node;
+ u32 value;
+ int ret;
+
+ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
+ GFP_KERNEL);
+ if (!vc4_hdmi_encoder)
+ return -ENOMEM;
+ vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI;
+ hdmi->encoder = &vc4_hdmi_encoder->base.base;
+
+ hdmi->pdev = pdev;
+ hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(hdmi->hdmicore_regs))
+ return PTR_ERR(hdmi->hdmicore_regs);
+
+ hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
+ if (IS_ERR(hdmi->hd_regs))
+ return PTR_ERR(hdmi->hd_regs);
+
+ ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
+ if (!ddc_node) {
+ DRM_ERROR("Failed to find ddc node in device tree\n");
+ return -ENODEV;
+ }
+
+ hdmi->pixel_clock = devm_clk_get(dev, "pixel");
+ if (IS_ERR(hdmi->pixel_clock)) {
+ DRM_ERROR("Failed to get pixel clock\n");
+ return PTR_ERR(hdmi->pixel_clock);
+ }
+ hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+ if (IS_ERR(hdmi->hsm_clock)) {
+ DRM_ERROR("Failed to get HDMI state machine clock\n");
+ return PTR_ERR(hdmi->hsm_clock);
+ }
+
+ hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+ if (!hdmi->ddc) {
+ DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
+ return -EPROBE_DEFER;
+ }
+
+ /* Enable the clocks at startup. We can't quite recover from
+ * turning off the pixel clock during disable/enables yet, so
+ * it's always running.
+ */
+ ret = clk_prepare_enable(hdmi->pixel_clock);
+ if (ret) {
+ DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
+ goto err_put_i2c;
+ }
+
+ ret = clk_prepare_enable(hdmi->hsm_clock);
+ if (ret) {
+ DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
+ ret);
+ goto err_unprepare_pix;
+ }
+
+ /* Only use the GPIO HPD pin if present in the DT, otherwise
+ * we'll use the HDMI core's register.
+ */
+ if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
+ hdmi->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpios", 0);
+ if (hdmi->hpd_gpio < 0) {
+ ret = hdmi->hpd_gpio;
+ goto err_unprepare_hsm;
+ }
+ }
+
+ vc4->hdmi = hdmi;
+
+ /* HDMI core must be enabled. */
+ WARN_ON_ONCE((HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE) == 0);
+
+ drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
+
+ hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
+ if (IS_ERR(hdmi->connector)) {
+ ret = PTR_ERR(hdmi->connector);
+ goto err_destroy_encoder;
+ }
+
+ return 0;
+
+err_destroy_encoder:
+ vc4_hdmi_encoder_destroy(hdmi->encoder);
+err_unprepare_hsm:
+ clk_disable_unprepare(hdmi->hsm_clock);
+err_unprepare_pix:
+ clk_disable_unprepare(hdmi->pixel_clock);
+err_put_i2c:
+ put_device(&vc4->hdmi->ddc->dev);
+
+ return ret;
+}
+
+static void vc4_hdmi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+ struct vc4_hdmi *hdmi = vc4->hdmi;
+
+ vc4_hdmi_connector_destroy(hdmi->connector);
+ vc4_hdmi_encoder_destroy(hdmi->encoder);
+
+ clk_disable_unprepare(hdmi->pixel_clock);
+ clk_disable_unprepare(hdmi->hsm_clock);
+ put_device(&hdmi->ddc->dev);
+
+ vc4->hdmi = NULL;
+}
+
+static const struct component_ops vc4_hdmi_ops = {
+ .bind = vc4_hdmi_bind,
+ .unbind = vc4_hdmi_unbind,
+};
+
+static int vc4_hdmi_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_hdmi_ops);
+}
+
+static int vc4_hdmi_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_hdmi_ops);
+ return 0;
+}
+
+static const struct of_device_id vc4_hdmi_dt_match[] = {
+ { .compatible = "brcm,bcm2835-hdmi" },
+ {}
+};
+
+struct platform_driver vc4_hdmi_driver = {
+ .probe = vc4_hdmi_dev_probe,
+ .remove = vc4_hdmi_dev_remove,
+ .driver = {
+ .name = "vc4_hdmi",
+ .of_match_table = vc4_hdmi_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
new file mode 100644
index 000000000000..8098c5b21ba4
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * DOC: VC4 HVS module.
+ *
+ * The HVS is the piece of hardware that does translation, scaling,
+ * colorspace conversion, and compositing of pixels stored in
+ * framebuffers into a FIFO of pixels going out to the Pixel Valve
+ * (CRTC). It operates at the system clock rate (the system audio
+ * clock gate, specifically), which is much higher than the pixel
+ * clock rate.
+ *
+ * There is a single global HVS, with multiple output FIFOs that can
+ * be consumed by the PVs. This file just manages the resources for
+ * the HVS, while the vc4_crtc.c code actually drives HVS setup for
+ * each CRTC.
+ */
+
+#include "linux/component.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+#define HVS_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} hvs_regs[] = {
+ HVS_REG(SCALER_DISPCTRL),
+ HVS_REG(SCALER_DISPSTAT),
+ HVS_REG(SCALER_DISPID),
+ HVS_REG(SCALER_DISPECTRL),
+ HVS_REG(SCALER_DISPPROF),
+ HVS_REG(SCALER_DISPDITHER),
+ HVS_REG(SCALER_DISPEOLN),
+ HVS_REG(SCALER_DISPLIST0),
+ HVS_REG(SCALER_DISPLIST1),
+ HVS_REG(SCALER_DISPLIST2),
+ HVS_REG(SCALER_DISPLSTAT),
+ HVS_REG(SCALER_DISPLACT0),
+ HVS_REG(SCALER_DISPLACT1),
+ HVS_REG(SCALER_DISPLACT2),
+ HVS_REG(SCALER_DISPCTRL0),
+ HVS_REG(SCALER_DISPBKGND0),
+ HVS_REG(SCALER_DISPSTAT0),
+ HVS_REG(SCALER_DISPBASE0),
+ HVS_REG(SCALER_DISPCTRL1),
+ HVS_REG(SCALER_DISPBKGND1),
+ HVS_REG(SCALER_DISPSTAT1),
+ HVS_REG(SCALER_DISPBASE1),
+ HVS_REG(SCALER_DISPCTRL2),
+ HVS_REG(SCALER_DISPBKGND2),
+ HVS_REG(SCALER_DISPSTAT2),
+ HVS_REG(SCALER_DISPBASE2),
+ HVS_REG(SCALER_DISPALPHA2),
+};
+
+void vc4_hvs_dump_state(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hvs_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ hvs_regs[i].reg, hvs_regs[i].name,
+ HVS_READ(hvs_regs[i].reg));
+ }
+
+ DRM_INFO("HVS ctx:\n");
+ for (i = 0; i < 64; i += 4) {
+ DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ i * 4, i < HVS_BOOTLOADER_DLIST_END ? "B" : "D",
+ readl((u32 __iomem *)vc4->hvs->dlist + i + 0),
+ readl((u32 __iomem *)vc4->hvs->dlist + i + 1),
+ readl((u32 __iomem *)vc4->hvs->dlist + i + 2),
+ readl((u32 __iomem *)vc4->hvs->dlist + i + 3));
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hvs_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ hvs_regs[i].name, hvs_regs[i].reg,
+ HVS_READ(hvs_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif
+
+static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+ struct vc4_hvs *hvs = NULL;
+
+ hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL);
+ if (!hvs)
+ return -ENOMEM;
+
+ hvs->pdev = pdev;
+
+ hvs->regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(hvs->regs))
+ return PTR_ERR(hvs->regs);
+
+ hvs->dlist = hvs->regs + SCALER_DLIST_START;
+
+ vc4->hvs = hvs;
+ return 0;
+}
+
+static void vc4_hvs_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+
+ vc4->hvs = NULL;
+}
+
+static const struct component_ops vc4_hvs_ops = {
+ .bind = vc4_hvs_bind,
+ .unbind = vc4_hvs_unbind,
+};
+
+static int vc4_hvs_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_hvs_ops);
+}
+
+static int vc4_hvs_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_hvs_ops);
+ return 0;
+}
+
+static const struct of_device_id vc4_hvs_dt_match[] = {
+ { .compatible = "brcm,bcm2835-hvs" },
+ {}
+};
+
+struct platform_driver vc4_hvs_driver = {
+ .probe = vc4_hvs_dev_probe,
+ .remove = vc4_hvs_dev_remove,
+ .driver = {
+ .name = "vc4_hvs",
+ .of_match_table = vc4_hvs_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
new file mode 100644
index 000000000000..2e5597d10cc6
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * DOC: VC4 KMS
+ *
+ * This is the general code for implementing KMS mode setting that
+ * doesn't clearly associate with any of the other objects (plane,
+ * crtc, HDMI encoder).
+ */
+
+#include "drm_crtc.h"
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "drm_plane_helper.h"
+#include "drm_fb_cma_helper.h"
+#include "vc4_drv.h"
+
+static void vc4_output_poll_changed(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (vc4->fbdev)
+ drm_fbdev_cma_hotplug_event(vc4->fbdev);
+}
+
+static const struct drm_mode_config_funcs vc4_mode_funcs = {
+ .output_poll_changed = vc4_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+ .fb_create = drm_fb_cma_create,
+};
+
+int vc4_kms_load(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int ret;
+
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret < 0) {
+ dev_err(dev->dev, "failed to initialize vblank\n");
+ return ret;
+ }
+
+ dev->mode_config.max_width = 2048;
+ dev->mode_config.max_height = 2048;
+ dev->mode_config.funcs = &vc4_mode_funcs;
+ dev->mode_config.preferred_depth = 24;
+ dev->vblank_disable_allowed = true;
+
+ drm_mode_config_reset(dev);
+
+ vc4->fbdev = drm_fbdev_cma_init(dev, 32,
+ dev->mode_config.num_crtc,
+ dev->mode_config.num_connector);
+ if (IS_ERR(vc4->fbdev))
+ vc4->fbdev = NULL;
+
+ drm_kms_helper_poll_init(dev);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
new file mode 100644
index 000000000000..887f3caad0be
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * DOC: VC4 plane module
+ *
+ * Each DRM plane is a layer of pixels being scanned out by the HVS.
+ *
+ * At atomic modeset check time, we compute the HVS display element
+ * state that would be necessary for displaying the plane (giving us a
+ * chance to figure out if a plane configuration is invalid), then at
+ * atomic flush time the CRTC will ask us to write our element state
+ * into the region of the HVS that it has allocated for us.
+ */
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+#include "drm_atomic_helper.h"
+#include "drm_fb_cma_helper.h"
+#include "drm_plane_helper.h"
+
+struct vc4_plane_state {
+ struct drm_plane_state base;
+ u32 *dlist;
+ u32 dlist_size; /* Number of dwords in allocated for the display list */
+ u32 dlist_count; /* Number of used dwords in the display list. */
+};
+
+static inline struct vc4_plane_state *
+to_vc4_plane_state(struct drm_plane_state *state)
+{
+ return (struct vc4_plane_state *)state;
+}
+
+static const struct hvs_format {
+ u32 drm; /* DRM_FORMAT_* */
+ u32 hvs; /* HVS_FORMAT_* */
+ u32 pixel_order;
+ bool has_alpha;
+} hvs_formats[] = {
+ {
+ .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false,
+ },
+ {
+ .drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = true,
+ },
+};
+
+static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
+ if (hvs_formats[i].drm == drm_format)
+ return &hvs_formats[i];
+ }
+
+ return NULL;
+}
+
+static bool plane_enabled(struct drm_plane_state *state)
+{
+ return state->fb && state->crtc;
+}
+
+static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
+{
+ struct vc4_plane_state *vc4_state;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ vc4_state = kmemdup(plane->state, sizeof(*vc4_state), GFP_KERNEL);
+ if (!vc4_state)
+ return NULL;
+
+ __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base);
+
+ if (vc4_state->dlist) {
+ vc4_state->dlist = kmemdup(vc4_state->dlist,
+ vc4_state->dlist_count * 4,
+ GFP_KERNEL);
+ if (!vc4_state->dlist) {
+ kfree(vc4_state);
+ return NULL;
+ }
+ vc4_state->dlist_size = vc4_state->dlist_count;
+ }
+
+ return &vc4_state->base;
+}
+
+static void vc4_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+
+ kfree(vc4_state->dlist);
+ __drm_atomic_helper_plane_destroy_state(plane, &vc4_state->base);
+ kfree(state);
+}
+
+/* Called during init to allocate the plane's atomic state. */
+static void vc4_plane_reset(struct drm_plane *plane)
+{
+ struct vc4_plane_state *vc4_state;
+
+ WARN_ON(plane->state);
+
+ vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL);
+ if (!vc4_state)
+ return;
+
+ plane->state = &vc4_state->base;
+ vc4_state->base.plane = plane;
+}
+
+static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
+{
+ if (vc4_state->dlist_count == vc4_state->dlist_size) {
+ u32 new_size = max(4u, vc4_state->dlist_count * 2);
+ u32 *new_dlist = kmalloc(new_size * 4, GFP_KERNEL);
+
+ if (!new_dlist)
+ return;
+ memcpy(new_dlist, vc4_state->dlist, vc4_state->dlist_count * 4);
+
+ kfree(vc4_state->dlist);
+ vc4_state->dlist = new_dlist;
+ vc4_state->dlist_size = new_size;
+ }
+
+ vc4_state->dlist[vc4_state->dlist_count++] = val;
+}
+
+/* Writes out a full display list for an active plane to the plane's
+ * private dlist state.
+ */
+static int vc4_plane_mode_set(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+ u32 ctl0_offset = vc4_state->dlist_count;
+ const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format);
+ uint32_t offset = fb->offsets[0];
+ int crtc_x = state->crtc_x;
+ int crtc_y = state->crtc_y;
+ int crtc_w = state->crtc_w;
+ int crtc_h = state->crtc_h;
+
+ if (state->crtc_w << 16 != state->src_w ||
+ state->crtc_h << 16 != state->src_h) {
+ /* We don't support scaling yet, which involves
+ * allocating the LBM memory for scaling temporary
+ * storage, and putting filter kernels in the HVS
+ * context.
+ */
+ return -EINVAL;
+ }
+
+ if (crtc_x < 0) {
+ offset += drm_format_plane_cpp(fb->pixel_format, 0) * -crtc_x;
+ crtc_w += crtc_x;
+ crtc_x = 0;
+ }
+
+ if (crtc_y < 0) {
+ offset += fb->pitches[0] * -crtc_y;
+ crtc_h += crtc_y;
+ crtc_y = 0;
+ }
+
+ vc4_dlist_write(vc4_state,
+ SCALER_CTL0_VALID |
+ (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+ (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+ SCALER_CTL0_UNITY);
+
+ /* Position Word 0: Image Positions and Alpha Value */
+ vc4_dlist_write(vc4_state,
+ VC4_SET_FIELD(0xff, SCALER_POS0_FIXED_ALPHA) |
+ VC4_SET_FIELD(crtc_x, SCALER_POS0_START_X) |
+ VC4_SET_FIELD(crtc_y, SCALER_POS0_START_Y));
+
+ /* Position Word 1: Scaled Image Dimensions.
+ * Skipped due to SCALER_CTL0_UNITY scaling.
+ */
+
+ /* Position Word 2: Source Image Size, Alpha Mode */
+ vc4_dlist_write(vc4_state,
+ VC4_SET_FIELD(format->has_alpha ?
+ SCALER_POS2_ALPHA_MODE_PIPELINE :
+ SCALER_POS2_ALPHA_MODE_FIXED,
+ SCALER_POS2_ALPHA_MODE) |
+ VC4_SET_FIELD(crtc_w, SCALER_POS2_WIDTH) |
+ VC4_SET_FIELD(crtc_h, SCALER_POS2_HEIGHT));
+
+ /* Position Word 3: Context. Written by the HVS. */
+ vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+ /* Pointer Word 0: RGB / Y Pointer */
+ vc4_dlist_write(vc4_state, bo->paddr + offset);
+
+ /* Pointer Context Word 0: Written by the HVS */
+ vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+ /* Pitch word 0: Pointer 0 Pitch */
+ vc4_dlist_write(vc4_state,
+ VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH));
+
+ vc4_state->dlist[ctl0_offset] |=
+ VC4_SET_FIELD(vc4_state->dlist_count, SCALER_CTL0_SIZE);
+
+ return 0;
+}
+
+/* If a modeset involves changing the setup of a plane, the atomic
+ * infrastructure will call this to validate a proposed plane setup.
+ * However, if a plane isn't getting updated, this (and the
+ * corresponding vc4_plane_atomic_update) won't get called. Thus, we
+ * compute the dlist here and have all active plane dlists get updated
+ * in the CRTC's flush.
+ */
+static int vc4_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+
+ vc4_state->dlist_count = 0;
+
+ if (plane_enabled(state))
+ return vc4_plane_mode_set(plane, state);
+ else
+ return 0;
+}
+
+static void vc4_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ /* No contents here. Since we don't know where in the CRTC's
+ * dlist we should be stored, our dlist is uploaded to the
+ * hardware with vc4_plane_write_dlist() at CRTC atomic_flush
+ * time.
+ */
+}
+
+u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
+ int i;
+
+ /* Can't memcpy_toio() because it needs to be 32-bit writes. */
+ for (i = 0; i < vc4_state->dlist_count; i++)
+ writel(vc4_state->dlist[i], &dlist[i]);
+
+ return vc4_state->dlist_count;
+}
+
+u32 vc4_plane_dlist_size(struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+
+ return vc4_state->dlist_count;
+}
+
+static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
+ .prepare_fb = NULL,
+ .cleanup_fb = NULL,
+ .atomic_check = vc4_plane_atomic_check,
+ .atomic_update = vc4_plane_atomic_update,
+};
+
+static void vc4_plane_destroy(struct drm_plane *plane)
+{
+ drm_plane_helper_disable(plane);
+ drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs vc4_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = vc4_plane_destroy,
+ .set_property = NULL,
+ .reset = vc4_plane_reset,
+ .atomic_duplicate_state = vc4_plane_duplicate_state,
+ .atomic_destroy_state = vc4_plane_destroy_state,
+};
+
+struct drm_plane *vc4_plane_init(struct drm_device *dev,
+ enum drm_plane_type type)
+{
+ struct drm_plane *plane = NULL;
+ struct vc4_plane *vc4_plane;
+ u32 formats[ARRAY_SIZE(hvs_formats)];
+ int ret = 0;
+ unsigned i;
+
+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
+ GFP_KERNEL);
+ if (!vc4_plane) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
+ formats[i] = hvs_formats[i].drm;
+ plane = &vc4_plane->base;
+ ret = drm_universal_plane_init(dev, plane, 0xff,
+ &vc4_plane_funcs,
+ formats, ARRAY_SIZE(formats),
+ type);
+
+ drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
+
+ return plane;
+fail:
+ if (plane)
+ vc4_plane_destroy(plane);
+
+ return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
new file mode 100644
index 000000000000..9e4e904c668e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -0,0 +1,570 @@
+/*
+ * Copyright © 2014-2015 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.
+ */
+
+#ifndef VC4_REGS_H
+#define VC4_REGS_H
+
+#include <linux/bitops.h>
+
+#define VC4_MASK(high, low) ((u32)GENMASK(high, low))
+/* Using the GNU statement expression extension */
+#define VC4_SET_FIELD(value, field) \
+ ({ \
+ uint32_t fieldval = (value) << field##_SHIFT; \
+ WARN_ON((fieldval & ~field##_MASK) != 0); \
+ fieldval & field##_MASK; \
+ })
+
+#define VC4_GET_FIELD(word, field) (((word) & field##_MASK) >> \
+ field##_SHIFT)
+
+#define V3D_IDENT0 0x00000
+# define V3D_EXPECTED_IDENT0 \
+ ((2 << 24) | \
+ ('V' << 0) | \
+ ('3' << 8) | \
+ ('D' << 16))
+
+#define V3D_IDENT1 0x00004
+/* Multiples of 1kb */
+# define V3D_IDENT1_VPM_SIZE_MASK VC4_MASK(31, 28)
+# define V3D_IDENT1_VPM_SIZE_SHIFT 28
+# define V3D_IDENT1_NSEM_MASK VC4_MASK(23, 16)
+# define V3D_IDENT1_NSEM_SHIFT 16
+# define V3D_IDENT1_TUPS_MASK VC4_MASK(15, 12)
+# define V3D_IDENT1_TUPS_SHIFT 12
+# define V3D_IDENT1_QUPS_MASK VC4_MASK(11, 8)
+# define V3D_IDENT1_QUPS_SHIFT 8
+# define V3D_IDENT1_NSLC_MASK VC4_MASK(7, 4)
+# define V3D_IDENT1_NSLC_SHIFT 4
+# define V3D_IDENT1_REV_MASK VC4_MASK(3, 0)
+# define V3D_IDENT1_REV_SHIFT 0
+
+#define V3D_IDENT2 0x00008
+#define V3D_SCRATCH 0x00010
+#define V3D_L2CACTL 0x00020
+# define V3D_L2CACTL_L2CCLR BIT(2)
+# define V3D_L2CACTL_L2CDIS BIT(1)
+# define V3D_L2CACTL_L2CENA BIT(0)
+
+#define V3D_SLCACTL 0x00024
+# define V3D_SLCACTL_T1CC_MASK VC4_MASK(27, 24)
+# define V3D_SLCACTL_T1CC_SHIFT 24
+# define V3D_SLCACTL_T0CC_MASK VC4_MASK(19, 16)
+# define V3D_SLCACTL_T0CC_SHIFT 16
+# define V3D_SLCACTL_UCC_MASK VC4_MASK(11, 8)
+# define V3D_SLCACTL_UCC_SHIFT 8
+# define V3D_SLCACTL_ICC_MASK VC4_MASK(3, 0)
+# define V3D_SLCACTL_ICC_SHIFT 0
+
+#define V3D_INTCTL 0x00030
+#define V3D_INTENA 0x00034
+#define V3D_INTDIS 0x00038
+# define V3D_INT_SPILLUSE BIT(3)
+# define V3D_INT_OUTOMEM BIT(2)
+# define V3D_INT_FLDONE BIT(1)
+# define V3D_INT_FRDONE BIT(0)
+
+#define V3D_CT0CS 0x00100
+#define V3D_CT1CS 0x00104
+#define V3D_CTNCS(n) (V3D_CT0CS + 4 * n)
+# define V3D_CTRSTA BIT(15)
+# define V3D_CTSEMA BIT(12)
+# define V3D_CTRTSD BIT(8)
+# define V3D_CTRUN BIT(5)
+# define V3D_CTSUBS BIT(4)
+# define V3D_CTERR BIT(3)
+# define V3D_CTMODE BIT(0)
+
+#define V3D_CT0EA 0x00108
+#define V3D_CT1EA 0x0010c
+#define V3D_CTNEA(n) (V3D_CT0EA + 4 * (n))
+#define V3D_CT0CA 0x00110
+#define V3D_CT1CA 0x00114
+#define V3D_CTNCA(n) (V3D_CT0CA + 4 * (n))
+#define V3D_CT00RA0 0x00118
+#define V3D_CT01RA0 0x0011c
+#define V3D_CTNRA0(n) (V3D_CT00RA0 + 4 * (n))
+#define V3D_CT0LC 0x00120
+#define V3D_CT1LC 0x00124
+#define V3D_CTNLC(n) (V3D_CT0LC + 4 * (n))
+#define V3D_CT0PC 0x00128
+#define V3D_CT1PC 0x0012c
+#define V3D_CTNPC(n) (V3D_CT0PC + 4 * (n))
+
+#define V3D_PCS 0x00130
+# define V3D_BMOOM BIT(8)
+# define V3D_RMBUSY BIT(3)
+# define V3D_RMACTIVE BIT(2)
+# define V3D_BMBUSY BIT(1)
+# define V3D_BMACTIVE BIT(0)
+
+#define V3D_BFC 0x00134
+#define V3D_RFC 0x00138
+#define V3D_BPCA 0x00300
+#define V3D_BPCS 0x00304
+#define V3D_BPOA 0x00308
+#define V3D_BPOS 0x0030c
+#define V3D_BXCF 0x00310
+#define V3D_SQRSV0 0x00410
+#define V3D_SQRSV1 0x00414
+#define V3D_SQCNTL 0x00418
+#define V3D_SRQPC 0x00430
+#define V3D_SRQUA 0x00434
+#define V3D_SRQUL 0x00438
+#define V3D_SRQCS 0x0043c
+#define V3D_VPACNTL 0x00500
+#define V3D_VPMBASE 0x00504
+#define V3D_PCTRC 0x00670
+#define V3D_PCTRE 0x00674
+#define V3D_PCTR0 0x00680
+#define V3D_PCTRS0 0x00684
+#define V3D_PCTR1 0x00688
+#define V3D_PCTRS1 0x0068c
+#define V3D_PCTR2 0x00690
+#define V3D_PCTRS2 0x00694
+#define V3D_PCTR3 0x00698
+#define V3D_PCTRS3 0x0069c
+#define V3D_PCTR4 0x006a0
+#define V3D_PCTRS4 0x006a4
+#define V3D_PCTR5 0x006a8
+#define V3D_PCTRS5 0x006ac
+#define V3D_PCTR6 0x006b0
+#define V3D_PCTRS6 0x006b4
+#define V3D_PCTR7 0x006b8
+#define V3D_PCTRS7 0x006bc
+#define V3D_PCTR8 0x006c0
+#define V3D_PCTRS8 0x006c4
+#define V3D_PCTR9 0x006c8
+#define V3D_PCTRS9 0x006cc
+#define V3D_PCTR10 0x006d0
+#define V3D_PCTRS10 0x006d4
+#define V3D_PCTR11 0x006d8
+#define V3D_PCTRS11 0x006dc
+#define V3D_PCTR12 0x006e0
+#define V3D_PCTRS12 0x006e4
+#define V3D_PCTR13 0x006e8
+#define V3D_PCTRS13 0x006ec
+#define V3D_PCTR14 0x006f0
+#define V3D_PCTRS14 0x006f4
+#define V3D_PCTR15 0x006f8
+#define V3D_PCTRS15 0x006fc
+#define V3D_BGE 0x00f00
+#define V3D_FDBGO 0x00f04
+#define V3D_FDBGB 0x00f08
+#define V3D_FDBGR 0x00f0c
+#define V3D_FDBGS 0x00f10
+#define V3D_ERRSTAT 0x00f20
+
+#define PV_CONTROL 0x00
+# define PV_CONTROL_FORMAT_MASK VC4_MASK(23, 21)
+# define PV_CONTROL_FORMAT_SHIFT 21
+# define PV_CONTROL_FORMAT_24 0
+# define PV_CONTROL_FORMAT_DSIV_16 1
+# define PV_CONTROL_FORMAT_DSIC_16 2
+# define PV_CONTROL_FORMAT_DSIV_18 3
+# define PV_CONTROL_FORMAT_DSIV_24 4
+
+# define PV_CONTROL_FIFO_LEVEL_MASK VC4_MASK(20, 15)
+# define PV_CONTROL_FIFO_LEVEL_SHIFT 15
+# define PV_CONTROL_CLR_AT_START BIT(14)
+# define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13)
+# define PV_CONTROL_WAIT_HSTART BIT(12)
+# define PV_CONTROL_CLK_SELECT_DSI_VEC 0
+# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1
+# define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2)
+# define PV_CONTROL_CLK_SELECT_SHIFT 2
+# define PV_CONTROL_FIFO_CLR BIT(1)
+# define PV_CONTROL_EN BIT(0)
+
+#define PV_V_CONTROL 0x04
+# define PV_VCONTROL_INTERLACE BIT(4)
+# define PV_VCONTROL_CONTINUOUS BIT(1)
+# define PV_VCONTROL_VIDEN BIT(0)
+
+#define PV_VSYNCD 0x08
+
+#define PV_HORZA 0x0c
+# define PV_HORZA_HBP_MASK VC4_MASK(31, 16)
+# define PV_HORZA_HBP_SHIFT 16
+# define PV_HORZA_HSYNC_MASK VC4_MASK(15, 0)
+# define PV_HORZA_HSYNC_SHIFT 0
+
+#define PV_HORZB 0x10
+# define PV_HORZB_HFP_MASK VC4_MASK(31, 16)
+# define PV_HORZB_HFP_SHIFT 16
+# define PV_HORZB_HACTIVE_MASK VC4_MASK(15, 0)
+# define PV_HORZB_HACTIVE_SHIFT 0
+
+#define PV_VERTA 0x14
+# define PV_VERTA_VBP_MASK VC4_MASK(31, 16)
+# define PV_VERTA_VBP_SHIFT 16
+# define PV_VERTA_VSYNC_MASK VC4_MASK(15, 0)
+# define PV_VERTA_VSYNC_SHIFT 0
+
+#define PV_VERTB 0x18
+# define PV_VERTB_VFP_MASK VC4_MASK(31, 16)
+# define PV_VERTB_VFP_SHIFT 16
+# define PV_VERTB_VACTIVE_MASK VC4_MASK(15, 0)
+# define PV_VERTB_VACTIVE_SHIFT 0
+
+#define PV_VERTA_EVEN 0x1c
+#define PV_VERTB_EVEN 0x20
+
+#define PV_INTEN 0x24
+#define PV_INTSTAT 0x28
+# define PV_INT_VID_IDLE BIT(9)
+# define PV_INT_VFP_END BIT(8)
+# define PV_INT_VFP_START BIT(7)
+# define PV_INT_VACT_START BIT(6)
+# define PV_INT_VBP_START BIT(5)
+# define PV_INT_VSYNC_START BIT(4)
+# define PV_INT_HFP_START BIT(3)
+# define PV_INT_HACT_START BIT(2)
+# define PV_INT_HBP_START BIT(1)
+# define PV_INT_HSYNC_START BIT(0)
+
+#define PV_STAT 0x2c
+
+#define PV_HACT_ACT 0x30
+
+#define SCALER_DISPCTRL 0x00000000
+/* Global register for clock gating the HVS */
+# define SCALER_DISPCTRL_ENABLE BIT(31)
+# define SCALER_DISPCTRL_DSP2EISLUR BIT(15)
+# define SCALER_DISPCTRL_DSP1EISLUR BIT(14)
+/* Enables Display 0 short line and underrun contribution to
+ * SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are
+ * always enabled.
+ */
+# define SCALER_DISPCTRL_DSP0EISLUR BIT(13)
+# define SCALER_DISPCTRL_DSP2EIEOLN BIT(12)
+# define SCALER_DISPCTRL_DSP2EIEOF BIT(11)
+# define SCALER_DISPCTRL_DSP1EIEOLN BIT(10)
+# define SCALER_DISPCTRL_DSP1EIEOF BIT(9)
+/* Enables Display 0 end-of-line-N contribution to
+ * SCALER_DISPSTAT_IRQDISP0
+ */
+# define SCALER_DISPCTRL_DSP0EIEOLN BIT(8)
+/* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
+# define SCALER_DISPCTRL_DSP0EIEOF BIT(7)
+
+# define SCALER_DISPCTRL_SLVRDEIRQ BIT(6)
+# define SCALER_DISPCTRL_SLVWREIRQ BIT(5)
+# define SCALER_DISPCTRL_DMAEIRQ BIT(4)
+# define SCALER_DISPCTRL_DISP2EIRQ BIT(3)
+# define SCALER_DISPCTRL_DISP1EIRQ BIT(2)
+/* Enables interrupt generation on the enabled EOF/EOLN/EISLUR
+ * bits and short frames..
+ */
+# define SCALER_DISPCTRL_DISP0EIRQ BIT(1)
+/* Enables interrupt generation on scaler profiler interrupt. */
+# define SCALER_DISPCTRL_SCLEIRQ BIT(0)
+
+#define SCALER_DISPSTAT 0x00000004
+# define SCALER_DISPSTAT_COBLOW2 BIT(29)
+# define SCALER_DISPSTAT_EOLN2 BIT(28)
+# define SCALER_DISPSTAT_ESFRAME2 BIT(27)
+# define SCALER_DISPSTAT_ESLINE2 BIT(26)
+# define SCALER_DISPSTAT_EUFLOW2 BIT(25)
+# define SCALER_DISPSTAT_EOF2 BIT(24)
+
+# define SCALER_DISPSTAT_COBLOW1 BIT(21)
+# define SCALER_DISPSTAT_EOLN1 BIT(20)
+# define SCALER_DISPSTAT_ESFRAME1 BIT(19)
+# define SCALER_DISPSTAT_ESLINE1 BIT(18)
+# define SCALER_DISPSTAT_EUFLOW1 BIT(17)
+# define SCALER_DISPSTAT_EOF1 BIT(16)
+
+# define SCALER_DISPSTAT_RESP_MASK VC4_MASK(15, 14)
+# define SCALER_DISPSTAT_RESP_SHIFT 14
+# define SCALER_DISPSTAT_RESP_OKAY 0
+# define SCALER_DISPSTAT_RESP_EXOKAY 1
+# define SCALER_DISPSTAT_RESP_SLVERR 2
+# define SCALER_DISPSTAT_RESP_DECERR 3
+
+# define SCALER_DISPSTAT_COBLOW0 BIT(13)
+/* Set when the DISPEOLN line is done compositing. */
+# define SCALER_DISPSTAT_EOLN0 BIT(12)
+/* Set when VSTART is seen but there are still pixels in the current
+ * output line.
+ */
+# define SCALER_DISPSTAT_ESFRAME0 BIT(11)
+/* Set when HSTART is seen but there are still pixels in the current
+ * output line.
+ */
+# define SCALER_DISPSTAT_ESLINE0 BIT(10)
+/* Set when the the downstream tries to read from the display FIFO
+ * while it's empty.
+ */
+# define SCALER_DISPSTAT_EUFLOW0 BIT(9)
+/* Set when the display mode changes from RUN to EOF */
+# define SCALER_DISPSTAT_EOF0 BIT(8)
+
+/* Set on AXI invalid DMA ID error. */
+# define SCALER_DISPSTAT_DMA_ERROR BIT(7)
+/* Set on AXI slave read decode error */
+# define SCALER_DISPSTAT_IRQSLVRD BIT(6)
+/* Set on AXI slave write decode error */
+# define SCALER_DISPSTAT_IRQSLVWR BIT(5)
+/* Set when SCALER_DISPSTAT_DMA_ERROR is set, or
+ * SCALER_DISPSTAT_RESP_ERROR is not SCALER_DISPSTAT_RESP_OKAY.
+ */
+# define SCALER_DISPSTAT_IRQDMA BIT(4)
+# define SCALER_DISPSTAT_IRQDISP2 BIT(3)
+# define SCALER_DISPSTAT_IRQDISP1 BIT(2)
+/* Set when any of the EOF/EOLN/ESFRAME/ESLINE bits are set and their
+ * corresponding interrupt bit is enabled in DISPCTRL.
+ */
+# define SCALER_DISPSTAT_IRQDISP0 BIT(1)
+/* On read, the profiler interrupt. On write, clear *all* interrupt bits. */
+# define SCALER_DISPSTAT_IRQSCL BIT(0)
+
+#define SCALER_DISPID 0x00000008
+#define SCALER_DISPECTRL 0x0000000c
+#define SCALER_DISPPROF 0x00000010
+#define SCALER_DISPDITHER 0x00000014
+#define SCALER_DISPEOLN 0x00000018
+#define SCALER_DISPLIST0 0x00000020
+#define SCALER_DISPLIST1 0x00000024
+#define SCALER_DISPLIST2 0x00000028
+#define SCALER_DISPLSTAT 0x0000002c
+#define SCALER_DISPLISTX(x) (SCALER_DISPLIST0 + \
+ (x) * (SCALER_DISPLIST1 - \
+ SCALER_DISPLIST0))
+
+#define SCALER_DISPLACT0 0x00000030
+#define SCALER_DISPLACT1 0x00000034
+#define SCALER_DISPLACT2 0x00000038
+#define SCALER_DISPCTRL0 0x00000040
+# define SCALER_DISPCTRLX_ENABLE BIT(31)
+# define SCALER_DISPCTRLX_RESET BIT(30)
+# define SCALER_DISPCTRLX_WIDTH_MASK VC4_MASK(23, 12)
+# define SCALER_DISPCTRLX_WIDTH_SHIFT 12
+# define SCALER_DISPCTRLX_HEIGHT_MASK VC4_MASK(11, 0)
+# define SCALER_DISPCTRLX_HEIGHT_SHIFT 0
+
+#define SCALER_DISPBKGND0 0x00000044
+#define SCALER_DISPSTAT0 0x00000048
+#define SCALER_DISPBASE0 0x0000004c
+# define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30)
+# define SCALER_DISPSTATX_MODE_SHIFT 30
+# define SCALER_DISPSTATX_MODE_DISABLED 0
+# define SCALER_DISPSTATX_MODE_INIT 1
+# define SCALER_DISPSTATX_MODE_RUN 2
+# define SCALER_DISPSTATX_MODE_EOF 3
+# define SCALER_DISPSTATX_FULL BIT(29)
+# define SCALER_DISPSTATX_EMPTY BIT(28)
+#define SCALER_DISPCTRL1 0x00000050
+#define SCALER_DISPBKGND1 0x00000054
+#define SCALER_DISPSTAT1 0x00000058
+#define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \
+ (x) * (SCALER_DISPSTAT1 - \
+ SCALER_DISPSTAT0))
+#define SCALER_DISPBASE1 0x0000005c
+#define SCALER_DISPCTRL2 0x00000060
+#define SCALER_DISPCTRLX(x) (SCALER_DISPCTRL0 + \
+ (x) * (SCALER_DISPCTRL1 - \
+ SCALER_DISPCTRL0))
+#define SCALER_DISPBKGND2 0x00000064
+#define SCALER_DISPSTAT2 0x00000068
+#define SCALER_DISPBASE2 0x0000006c
+#define SCALER_DISPALPHA2 0x00000070
+#define SCALER_GAMADDR 0x00000078
+#define SCALER_GAMDATA 0x000000e0
+#define SCALER_DLIST_START 0x00002000
+#define SCALER_DLIST_SIZE 0x00004000
+
+#define VC4_HDMI_CORE_REV 0x000
+
+#define VC4_HDMI_SW_RESET_CONTROL 0x004
+# define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1)
+# define VC4_HDMI_SW_RESET_HDMI BIT(0)
+
+#define VC4_HDMI_HOTPLUG_INT 0x008
+
+#define VC4_HDMI_HOTPLUG 0x00c
+# define VC4_HDMI_HOTPLUG_CONNECTED BIT(0)
+
+#define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0
+# define VC4_HDMI_RAM_PACKET_ENABLE BIT(16)
+
+#define VC4_HDMI_HORZA 0x0c4
+# define VC4_HDMI_HORZA_VPOS BIT(14)
+# define VC4_HDMI_HORZA_HPOS BIT(13)
+/* Horizontal active pixels (hdisplay). */
+# define VC4_HDMI_HORZA_HAP_MASK VC4_MASK(12, 0)
+# define VC4_HDMI_HORZA_HAP_SHIFT 0
+
+#define VC4_HDMI_HORZB 0x0c8
+/* Horizontal pack porch (htotal - hsync_end). */
+# define VC4_HDMI_HORZB_HBP_MASK VC4_MASK(29, 20)
+# define VC4_HDMI_HORZB_HBP_SHIFT 20
+/* Horizontal sync pulse (hsync_end - hsync_start). */
+# define VC4_HDMI_HORZB_HSP_MASK VC4_MASK(19, 10)
+# define VC4_HDMI_HORZB_HSP_SHIFT 10
+/* Horizontal front porch (hsync_start - hdisplay). */
+# define VC4_HDMI_HORZB_HFP_MASK VC4_MASK(9, 0)
+# define VC4_HDMI_HORZB_HFP_SHIFT 0
+
+#define VC4_HDMI_FIFO_CTL 0x05c
+# define VC4_HDMI_FIFO_CTL_RECENTER_DONE BIT(14)
+# define VC4_HDMI_FIFO_CTL_USE_EMPTY BIT(13)
+# define VC4_HDMI_FIFO_CTL_ON_VB BIT(7)
+# define VC4_HDMI_FIFO_CTL_RECENTER BIT(6)
+# define VC4_HDMI_FIFO_CTL_FIFO_RESET BIT(5)
+# define VC4_HDMI_FIFO_CTL_USE_PLL_LOCK BIT(4)
+# define VC4_HDMI_FIFO_CTL_INV_CLK_XFR BIT(3)
+# define VC4_HDMI_FIFO_CTL_CAPTURE_PTR BIT(2)
+# define VC4_HDMI_FIFO_CTL_USE_FULL BIT(1)
+# define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N BIT(0)
+# define VC4_HDMI_FIFO_VALID_WRITE_MASK 0xefff
+
+#define VC4_HDMI_SCHEDULER_CONTROL 0x0c0
+# define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
+# define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
+# define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT BIT(3)
+# define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE BIT(1)
+# define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI BIT(0)
+
+#define VC4_HDMI_VERTA0 0x0cc
+#define VC4_HDMI_VERTA1 0x0d4
+/* Vertical sync pulse (vsync_end - vsync_start). */
+# define VC4_HDMI_VERTA_VSP_MASK VC4_MASK(24, 20)
+# define VC4_HDMI_VERTA_VSP_SHIFT 20
+/* Vertical front porch (vsync_start - vdisplay). */
+# define VC4_HDMI_VERTA_VFP_MASK VC4_MASK(19, 13)
+# define VC4_HDMI_VERTA_VFP_SHIFT 13
+/* Vertical active lines (vdisplay). */
+# define VC4_HDMI_VERTA_VAL_MASK VC4_MASK(12, 0)
+# define VC4_HDMI_VERTA_VAL_SHIFT 0
+
+#define VC4_HDMI_VERTB0 0x0d0
+#define VC4_HDMI_VERTB1 0x0d8
+/* Vertical sync pulse offset (for interlaced) */
+# define VC4_HDMI_VERTB_VSPO_MASK VC4_MASK(21, 9)
+# define VC4_HDMI_VERTB_VSPO_SHIFT 9
+/* Vertical pack porch (vtotal - vsync_end). */
+# define VC4_HDMI_VERTB_VBP_MASK VC4_MASK(8, 0)
+# define VC4_HDMI_VERTB_VBP_SHIFT 0
+
+#define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0
+
+#define VC4_HD_M_CTL 0x00c
+# define VC4_HD_M_SW_RST BIT(2)
+# define VC4_HD_M_ENABLE BIT(0)
+
+#define VC4_HD_MAI_CTL 0x014
+
+#define VC4_HD_VID_CTL 0x038
+# define VC4_HD_VID_CTL_ENABLE BIT(31)
+# define VC4_HD_VID_CTL_UNDERFLOW_ENABLE BIT(30)
+# define VC4_HD_VID_CTL_FRAME_COUNTER_RESET BIT(29)
+# define VC4_HD_VID_CTL_VSYNC_LOW BIT(28)
+# define VC4_HD_VID_CTL_HSYNC_LOW BIT(27)
+
+#define VC4_HD_CSC_CTL 0x040
+# define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5)
+# define VC4_HD_CSC_CTL_ORDER_SHIFT 5
+# define VC4_HD_CSC_CTL_ORDER_RGB 0
+# define VC4_HD_CSC_CTL_ORDER_BGR 1
+# define VC4_HD_CSC_CTL_ORDER_BRG 2
+# define VC4_HD_CSC_CTL_ORDER_GRB 3
+# define VC4_HD_CSC_CTL_ORDER_GBR 4
+# define VC4_HD_CSC_CTL_ORDER_RBG 5
+# define VC4_HD_CSC_CTL_PADMSB BIT(4)
+# define VC4_HD_CSC_CTL_MODE_MASK VC4_MASK(3, 2)
+# define VC4_HD_CSC_CTL_MODE_SHIFT 2
+# define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0
+# define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1
+# define VC4_HD_CSC_CTL_MODE_CUSTOM 2
+# define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
+# define VC4_HD_CSC_CTL_ENABLE BIT(0)
+
+#define VC4_HD_FRAME_COUNT 0x068
+
+/* HVS display list information. */
+#define HVS_BOOTLOADER_DLIST_END 32
+
+enum hvs_pixel_format {
+ /* 8bpp */
+ HVS_PIXEL_FORMAT_RGB332 = 0,
+ /* 16bpp */
+ HVS_PIXEL_FORMAT_RGBA4444 = 1,
+ HVS_PIXEL_FORMAT_RGB555 = 2,
+ HVS_PIXEL_FORMAT_RGBA5551 = 3,
+ HVS_PIXEL_FORMAT_RGB565 = 4,
+ /* 24bpp */
+ HVS_PIXEL_FORMAT_RGB888 = 5,
+ HVS_PIXEL_FORMAT_RGBA6666 = 6,
+ /* 32bpp */
+ HVS_PIXEL_FORMAT_RGBA8888 = 7
+};
+
+/* Note: the LSB is the rightmost character shown. Only valid for
+ * HVS_PIXEL_FORMAT_RGB8888, not RGB888.
+ */
+#define HVS_PIXEL_ORDER_RGBA 0
+#define HVS_PIXEL_ORDER_BGRA 1
+#define HVS_PIXEL_ORDER_ARGB 2
+#define HVS_PIXEL_ORDER_ABGR 3
+
+#define HVS_PIXEL_ORDER_XBRG 0
+#define HVS_PIXEL_ORDER_XRBG 1
+#define HVS_PIXEL_ORDER_XRGB 2
+#define HVS_PIXEL_ORDER_XBGR 3
+
+#define HVS_PIXEL_ORDER_XYCBCR 0
+#define HVS_PIXEL_ORDER_XYCRCB 1
+#define HVS_PIXEL_ORDER_YXCBCR 2
+#define HVS_PIXEL_ORDER_YXCRCB 3
+
+#define SCALER_CTL0_END BIT(31)
+#define SCALER_CTL0_VALID BIT(30)
+
+#define SCALER_CTL0_SIZE_MASK VC4_MASK(29, 24)
+#define SCALER_CTL0_SIZE_SHIFT 24
+
+#define SCALER_CTL0_HFLIP BIT(16)
+#define SCALER_CTL0_VFLIP BIT(15)
+
+#define SCALER_CTL0_ORDER_MASK VC4_MASK(14, 13)
+#define SCALER_CTL0_ORDER_SHIFT 13
+
+/* Set to indicate no scaling. */
+#define SCALER_CTL0_UNITY BIT(4)
+
+#define SCALER_CTL0_PIXEL_FORMAT_MASK VC4_MASK(3, 0)
+#define SCALER_CTL0_PIXEL_FORMAT_SHIFT 0
+
+#define SCALER_POS0_FIXED_ALPHA_MASK VC4_MASK(31, 24)
+#define SCALER_POS0_FIXED_ALPHA_SHIFT 24
+
+#define SCALER_POS0_START_Y_MASK VC4_MASK(23, 12)
+#define SCALER_POS0_START_Y_SHIFT 12
+
+#define SCALER_POS0_START_X_MASK VC4_MASK(11, 0)
+#define SCALER_POS0_START_X_SHIFT 0
+
+#define SCALER_POS2_ALPHA_MODE_MASK VC4_MASK(31, 30)
+#define SCALER_POS2_ALPHA_MODE_SHIFT 30
+#define SCALER_POS2_ALPHA_MODE_PIPELINE 0
+#define SCALER_POS2_ALPHA_MODE_FIXED 1
+#define SCALER_POS2_ALPHA_MODE_FIXED_NONZERO 2
+#define SCALER_POS2_ALPHA_MODE_FIXED_OVER_0x07 3
+
+#define SCALER_POS2_HEIGHT_MASK VC4_MASK(27, 16)
+#define SCALER_POS2_HEIGHT_SHIFT 16
+
+#define SCALER_POS2_WIDTH_MASK VC4_MASK(11, 0)
+#define SCALER_POS2_WIDTH_SHIFT 0
+
+#define SCALER_SRC_PITCH_MASK VC4_MASK(15, 0)
+#define SCALER_SRC_PITCH_SHIFT 0
+
+#endif /* VC4_REGS_H */
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
index 860062ef8814..c503a840fd88 100644
--- a/drivers/gpu/drm/vgem/vgem_drv.c
+++ b/drivers/gpu/drm/vgem/vgem_drv.c
@@ -235,66 +235,13 @@ unlock:
return ret;
}
-int vgem_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_vma_offset_node *node;
- struct drm_gem_object *obj;
- struct drm_vgem_gem_object *vgem_obj;
- int ret = 0;
-
- mutex_lock(&dev->struct_mutex);
-
- node = drm_vma_offset_exact_lookup(dev->vma_offset_manager,
- vma->vm_pgoff,
- vma_pages(vma));
- if (!node) {
- ret = -EINVAL;
- goto out_unlock;
- } else if (!drm_vma_node_is_allowed(node, filp)) {
- ret = -EACCES;
- goto out_unlock;
- }
-
- obj = container_of(node, struct drm_gem_object, vma_node);
-
- vgem_obj = to_vgem_bo(obj);
-
- if (obj->dma_buf && vgem_obj->use_dma_buf) {
- ret = dma_buf_mmap(obj->dma_buf, vma, 0);
- goto out_unlock;
- }
-
- if (!obj->dev->driver->gem_vm_ops) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_ops = obj->dev->driver->gem_vm_ops;
- vma->vm_private_data = vgem_obj;
- vma->vm_page_prot =
- pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
-
- mutex_unlock(&dev->struct_mutex);
- drm_gem_vm_open(vma);
- return ret;
-
-out_unlock:
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
-}
-
-
static struct drm_ioctl_desc vgem_ioctls[] = {
};
static const struct file_operations vgem_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
- .mmap = vgem_drm_gem_mmap,
+ .mmap = drm_gem_mmap,
.poll = drm_poll,
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index ef8c500b4a00..286a785fab4f 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -102,6 +102,10 @@ typedef struct drm_via_private {
uint32_t dma_diff;
} drm_via_private_t;
+struct via_file_private {
+ struct list_head obj_list;
+};
+
enum via_family {
VIA_OTHER = 0, /* Baseline */
VIA_PRO_GROUP_A, /* Another video engine and DMA commands */
@@ -136,9 +140,9 @@ extern int via_init_context(struct drm_device *dev, int context);
extern int via_final_context(struct drm_device *dev, int context);
extern int via_do_cleanup_map(struct drm_device *dev);
-extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
-extern int via_enable_vblank(struct drm_device *dev, int crtc);
-extern void via_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
+extern int via_enable_vblank(struct drm_device *dev, unsigned int pipe);
+extern void via_disable_vblank(struct drm_device *dev, unsigned int pipe);
extern irqreturn_t via_driver_irq_handler(int irq, void *arg);
extern void via_driver_irq_preinstall(struct drm_device *dev);
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
index 1319433816d3..ea8172c747a2 100644
--- a/drivers/gpu/drm/via/via_irq.c
+++ b/drivers/gpu/drm/via/via_irq.c
@@ -95,10 +95,11 @@ static unsigned time_diff(struct timeval *now, struct timeval *then)
1000000 - (then->tv_usec - now->tv_usec);
}
-u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
+u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
drm_via_private_t *dev_priv = dev->dev_private;
- if (crtc != 0)
+
+ if (pipe != 0)
return 0;
return atomic_read(&dev_priv->vbl_received);
@@ -170,13 +171,13 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv)
}
}
-int via_enable_vblank(struct drm_device *dev, int crtc)
+int via_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
drm_via_private_t *dev_priv = dev->dev_private;
u32 status;
- if (crtc != 0) {
- DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
+ if (pipe != 0) {
+ DRM_ERROR("%s: bad crtc %u\n", __func__, pipe);
return -EINVAL;
}
@@ -189,7 +190,7 @@ int via_enable_vblank(struct drm_device *dev, int crtc)
return 0;
}
-void via_disable_vblank(struct drm_device *dev, int crtc)
+void via_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
drm_via_private_t *dev_priv = dev->dev_private;
u32 status;
@@ -200,8 +201,8 @@ void via_disable_vblank(struct drm_device *dev, int crtc)
VIA_WRITE8(0x83d4, 0x11);
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
- if (crtc != 0)
- DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
+ if (pipe != 0)
+ DRM_ERROR("%s: bad crtc %u\n", __func__, pipe);
}
static int
diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile
index 2ee1602d77d4..3fb8eac1084f 100644
--- a/drivers/gpu/drm/virtio/Makefile
+++ b/drivers/gpu/drm/virtio/Makefile
@@ -6,6 +6,7 @@ ccflags-y := -Iinclude/drm
virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_drm_bus.o virtgpu_gem.o \
virtgpu_fb.o virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \
- virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o
+ virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
+ virtgpu_ioctl.o virtgpu_prime.o
obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
index db8b49101a8b..512263919282 100644
--- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c
+++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
@@ -34,8 +34,8 @@ virtio_gpu_debugfs_irq_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct virtio_gpu_device *vgdev = node->minor->dev->dev_private;
- seq_printf(m, "fence %ld %lld\n",
- atomic64_read(&vgdev->fence_drv.last_seq),
+ seq_printf(m, "fence %llu %lld\n",
+ (u64)atomic64_read(&vgdev->fence_drv.last_seq),
vgdev->fence_drv.sync_seq);
return 0;
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 4e160efc9402..f545913a56c7 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -90,6 +90,14 @@ static int virtio_gpu_crtc_cursor_set(struct drm_crtc *crtc,
cpu_to_le32(64),
cpu_to_le32(64),
0, 0, &fence);
+ ret = virtio_gpu_object_reserve(qobj, false);
+ if (!ret) {
+ reservation_object_add_excl_fence(qobj->tbo.resv,
+ &fence->f);
+ fence_put(&fence->f);
+ virtio_gpu_object_unreserve(qobj);
+ virtio_gpu_object_wait(qobj, false);
+ }
output->cursor.hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR);
output->cursor.resource_id = cpu_to_le32(qobj->hw_res_handle);
@@ -117,6 +125,51 @@ static int virtio_gpu_crtc_cursor_move(struct drm_crtc *crtc,
return 0;
}
+static int virtio_gpu_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t flags)
+{
+ struct virtio_gpu_device *vgdev = crtc->dev->dev_private;
+ struct virtio_gpu_output *output =
+ container_of(crtc, struct virtio_gpu_output, crtc);
+ struct drm_plane *plane = crtc->primary;
+ struct virtio_gpu_framebuffer *vgfb;
+ struct virtio_gpu_object *bo;
+ unsigned long irqflags;
+ uint32_t handle;
+
+ plane->fb = fb;
+ vgfb = to_virtio_gpu_framebuffer(plane->fb);
+ bo = gem_to_virtio_gpu_obj(vgfb->obj);
+ handle = bo->hw_res_handle;
+
+ DRM_DEBUG("handle 0x%x%s, crtc %dx%d\n", handle,
+ bo->dumb ? ", dumb" : "",
+ crtc->mode.hdisplay, crtc->mode.vdisplay);
+ if (bo->dumb) {
+ virtio_gpu_cmd_transfer_to_host_2d
+ (vgdev, handle, 0,
+ cpu_to_le32(crtc->mode.hdisplay),
+ cpu_to_le32(crtc->mode.vdisplay),
+ 0, 0, NULL);
+ }
+ virtio_gpu_cmd_set_scanout(vgdev, output->index, handle,
+ crtc->mode.hdisplay,
+ crtc->mode.vdisplay, 0, 0);
+ virtio_gpu_cmd_resource_flush(vgdev, handle, 0, 0,
+ crtc->mode.hdisplay,
+ crtc->mode.vdisplay);
+
+ if (event) {
+ spin_lock_irqsave(&crtc->dev->event_lock, irqflags);
+ drm_send_vblank_event(crtc->dev, -1, event);
+ spin_unlock_irqrestore(&crtc->dev->event_lock, irqflags);
+ }
+
+ return 0;
+}
+
static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
.cursor_set2 = virtio_gpu_crtc_cursor_set,
.cursor_move = virtio_gpu_crtc_cursor_move,
@@ -124,9 +177,7 @@ static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = drm_crtc_cleanup,
-#if 0 /* not (yet) working without vblank support according to docs */
- .page_flip = drm_atomic_helper_page_flip,
-#endif
+ .page_flip = virtio_gpu_page_flip,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 7d9610aaeff9..b40ed6061f05 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -73,6 +73,14 @@ static struct virtio_device_id id_table[] = {
};
static unsigned int features[] = {
+#ifdef __LITTLE_ENDIAN
+ /*
+ * Gallium command stream send by virgl is native endian.
+ * Because of that we only support little endian guests on
+ * little endian hosts.
+ */
+ VIRTIO_GPU_F_VIRGL,
+#endif
};
static struct virtio_driver virtio_gpu_driver = {
.feature_table = features,
@@ -110,10 +118,12 @@ static const struct file_operations virtio_gpu_driver_fops = {
static struct drm_driver driver = {
- .driver_features = DRIVER_MODESET | DRIVER_GEM,
+ .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER,
.set_busid = drm_virtio_set_busid,
.load = virtio_gpu_driver_load,
.unload = virtio_gpu_driver_unload,
+ .open = virtio_gpu_driver_open,
+ .postclose = virtio_gpu_driver_postclose,
.dumb_create = virtio_gpu_mode_dumb_create,
.dumb_map_offset = virtio_gpu_mode_dumb_mmap,
@@ -123,10 +133,26 @@ static struct drm_driver driver = {
.debugfs_init = virtio_gpu_debugfs_init,
.debugfs_cleanup = virtio_gpu_debugfs_takedown,
#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,
.gem_free_object = virtio_gpu_gem_free_object,
+ .gem_open_object = virtio_gpu_gem_object_open,
+ .gem_close_object = virtio_gpu_gem_object_close,
.fops = &virtio_gpu_driver_fops,
+ .ioctls = virtio_gpu_ioctls,
+ .num_ioctls = DRM_VIRTIO_NUM_IOCTLS,
+
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 6d4db2dba90b..79f0abe69b64 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -146,6 +146,21 @@ struct virtio_gpu_queue {
struct work_struct dequeue_work;
};
+struct virtio_gpu_drv_capset {
+ uint32_t id;
+ uint32_t max_version;
+ uint32_t max_size;
+};
+
+struct virtio_gpu_drv_cap_cache {
+ struct list_head head;
+ void *caps_cache;
+ uint32_t id;
+ uint32_t version;
+ uint32_t size;
+ atomic_t is_valid;
+};
+
struct virtio_gpu_device {
struct device *dev;
struct drm_device *ddev;
@@ -179,7 +194,13 @@ struct virtio_gpu_device {
struct idr ctx_id_idr;
spinlock_t ctx_id_idr_lock;
+ bool has_virgl_3d;
+
struct work_struct config_changed_work;
+
+ struct virtio_gpu_drv_capset *capsets;
+ uint32_t num_capsets;
+ struct list_head cap_cache;
};
struct virtio_gpu_fpriv {
@@ -193,6 +214,8 @@ extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
/* virtio_kms.c */
int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags);
int virtio_gpu_driver_unload(struct drm_device *dev);
+int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file);
+void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file);
/* virtio_gem.c */
void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj);
@@ -203,6 +226,10 @@ int virtio_gpu_gem_create(struct drm_file *file,
uint64_t size,
struct drm_gem_object **obj_p,
uint32_t *handle_p);
+int virtio_gpu_gem_object_open(struct drm_gem_object *obj,
+ struct drm_file *file);
+void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
+ struct drm_file *file);
struct virtio_gpu_object *virtio_gpu_alloc_object(struct drm_device *dev,
size_t size, bool kernel,
bool pinned);
@@ -260,10 +287,43 @@ void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev,
int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev);
void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev,
uint32_t resource_id);
+int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx);
+int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
+ int idx, int version,
+ struct virtio_gpu_drv_cap_cache **cache_p);
+void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
+ uint32_t nlen, const char *name);
+void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
+ uint32_t id);
+void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
+ uint32_t ctx_id,
+ uint32_t resource_id);
+void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
+ uint32_t ctx_id,
+ uint32_t resource_id);
+void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
+ void *data, uint32_t data_size,
+ uint32_t ctx_id, struct virtio_gpu_fence **fence);
+void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
+ uint32_t resource_id, uint32_t ctx_id,
+ uint64_t offset, uint32_t level,
+ struct virtio_gpu_box *box,
+ struct virtio_gpu_fence **fence);
+void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
+ uint32_t resource_id, uint32_t ctx_id,
+ uint64_t offset, uint32_t level,
+ struct virtio_gpu_box *box,
+ struct virtio_gpu_fence **fence);
+void
+virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_resource_create_3d *rc_3d,
+ struct virtio_gpu_fence **fence);
void virtio_gpu_ctrl_ack(struct virtqueue *vq);
void virtio_gpu_cursor_ack(struct virtqueue *vq);
+void virtio_gpu_fence_ack(struct virtqueue *vq);
void virtio_gpu_dequeue_ctrl_func(struct work_struct *work);
void virtio_gpu_dequeue_cursor_func(struct work_struct *work);
+void virtio_gpu_dequeue_fence_func(struct work_struct *work);
/* virtio_gpu_display.c */
int virtio_gpu_framebuffer_init(struct drm_device *dev,
@@ -299,6 +359,18 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
void virtio_gpu_object_free_sg_table(struct virtio_gpu_object *bo);
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,
+ struct vm_area_struct *vma);
+
static inline struct virtio_gpu_object*
virtio_gpu_object_ref(struct virtio_gpu_object *bo)
{
diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c
index 1da632631dac..cf4418709e76 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fence.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fence.c
@@ -61,7 +61,7 @@ static void virtio_timeline_value_str(struct fence *f, char *str, int size)
{
struct virtio_gpu_fence *fence = to_virtio_fence(f);
- snprintf(str, size, "%lu", atomic64_read(&fence->drv->last_seq));
+ snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
}
static const struct fence_ops virtio_fence_ops = {
@@ -81,7 +81,7 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
unsigned long irq_flags;
- *fence = kmalloc(sizeof(struct virtio_gpu_fence), GFP_KERNEL);
+ *fence = kmalloc(sizeof(struct virtio_gpu_fence), GFP_ATOMIC);
if ((*fence) == NULL)
return -ENOMEM;
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
index cfa0d27150bd..1feb7cee3f0d 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -138,3 +138,44 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
drm_gem_object_unreference_unlocked(gobj);
return 0;
}
+
+int virtio_gpu_gem_object_open(struct drm_gem_object *obj,
+ struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = obj->dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj);
+ int r;
+
+ if (!vgdev->has_virgl_3d)
+ return 0;
+
+ r = virtio_gpu_object_reserve(qobj, false);
+ if (r)
+ return r;
+
+ virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id,
+ qobj->hw_res_handle);
+ virtio_gpu_object_unreserve(qobj);
+ return 0;
+}
+
+void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
+ struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = obj->dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj);
+ int r;
+
+ if (!vgdev->has_virgl_3d)
+ return;
+
+ r = virtio_gpu_object_reserve(qobj, false);
+ if (r)
+ return;
+
+ virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
+ qobj->hw_res_handle);
+ virtio_gpu_object_unreserve(qobj);
+}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
new file mode 100644
index 000000000000..b4de18e65db8
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * Authors:
+ * Dave Airlie
+ * Alon Levy
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 <drm/drmP.h>
+#include "virtgpu_drv.h"
+#include <drm/virtgpu_drm.h>
+#include "ttm/ttm_execbuf_util.h"
+
+static void convert_to_hw_box(struct virtio_gpu_box *dst,
+ const struct drm_virtgpu_3d_box *src)
+{
+ dst->x = cpu_to_le32(src->x);
+ dst->y = cpu_to_le32(src->y);
+ dst->z = cpu_to_le32(src->z);
+ dst->w = cpu_to_le32(src->w);
+ dst->h = cpu_to_le32(src->h);
+ dst->d = cpu_to_le32(src->d);
+}
+
+static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct drm_virtgpu_map *virtio_gpu_map = data;
+
+ return virtio_gpu_mode_dumb_mmap(file_priv, vgdev->ddev,
+ virtio_gpu_map->handle,
+ &virtio_gpu_map->offset);
+}
+
+static int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
+ struct list_head *head)
+{
+ struct ttm_validate_buffer *buf;
+ struct ttm_buffer_object *bo;
+ struct virtio_gpu_object *qobj;
+ int ret;
+
+ ret = ttm_eu_reserve_buffers(ticket, head, true, NULL);
+ if (ret != 0)
+ return ret;
+
+ list_for_each_entry(buf, head, head) {
+ bo = buf->bo;
+ qobj = container_of(bo, struct virtio_gpu_object, tbo);
+ ret = ttm_bo_validate(bo, &qobj->placement, false, false);
+ if (ret) {
+ ttm_eu_backoff_reservation(ticket, head);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static void virtio_gpu_unref_list(struct list_head *head)
+{
+ struct ttm_validate_buffer *buf;
+ struct ttm_buffer_object *bo;
+ struct virtio_gpu_object *qobj;
+ list_for_each_entry(buf, head, head) {
+ bo = buf->bo;
+ qobj = container_of(bo, struct virtio_gpu_object, tbo);
+
+ drm_gem_object_unreference_unlocked(&qobj->gem_base);
+ }
+}
+
+static int virtio_gpu_execbuffer(struct drm_device *dev,
+ struct drm_virtgpu_execbuffer *exbuf,
+ struct drm_file *drm_file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv;
+ struct drm_gem_object *gobj;
+ struct virtio_gpu_fence *fence;
+ struct virtio_gpu_object *qobj;
+ int ret;
+ uint32_t *bo_handles = NULL;
+ void __user *user_bo_handles = NULL;
+ struct list_head validate_list;
+ struct ttm_validate_buffer *buflist = NULL;
+ int i;
+ struct ww_acquire_ctx ticket;
+ void *buf;
+
+ if (vgdev->has_virgl_3d == false)
+ return -ENOSYS;
+
+ INIT_LIST_HEAD(&validate_list);
+ if (exbuf->num_bo_handles) {
+
+ bo_handles = drm_malloc_ab(exbuf->num_bo_handles,
+ sizeof(uint32_t));
+ buflist = drm_calloc_large(exbuf->num_bo_handles,
+ sizeof(struct ttm_validate_buffer));
+ if (!bo_handles || !buflist) {
+ drm_free_large(bo_handles);
+ drm_free_large(buflist);
+ return -ENOMEM;
+ }
+
+ user_bo_handles = (void __user *)(uintptr_t)exbuf->bo_handles;
+ if (copy_from_user(bo_handles, user_bo_handles,
+ exbuf->num_bo_handles * sizeof(uint32_t))) {
+ ret = -EFAULT;
+ drm_free_large(bo_handles);
+ drm_free_large(buflist);
+ return ret;
+ }
+
+ for (i = 0; i < exbuf->num_bo_handles; i++) {
+ gobj = drm_gem_object_lookup(dev,
+ drm_file, bo_handles[i]);
+ if (!gobj) {
+ drm_free_large(bo_handles);
+ drm_free_large(buflist);
+ return -ENOENT;
+ }
+
+ qobj = gem_to_virtio_gpu_obj(gobj);
+ buflist[i].bo = &qobj->tbo;
+
+ list_add(&buflist[i].head, &validate_list);
+ }
+ drm_free_large(bo_handles);
+ }
+
+ ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
+ if (ret)
+ goto out_free;
+
+ buf = kmalloc(exbuf->size, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out_unresv;
+ }
+ if (copy_from_user(buf, (void __user *)(uintptr_t)exbuf->command,
+ exbuf->size)) {
+ kfree(buf);
+ ret = -EFAULT;
+ goto out_unresv;
+ }
+ virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
+ vfpriv->ctx_id, &fence);
+
+ ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
+
+ /* fence the command bo */
+ virtio_gpu_unref_list(&validate_list);
+ drm_free_large(buflist);
+ fence_put(&fence->f);
+ return 0;
+
+out_unresv:
+ ttm_eu_backoff_reservation(&ticket, &validate_list);
+out_free:
+ virtio_gpu_unref_list(&validate_list);
+ drm_free_large(buflist);
+ return ret;
+}
+
+/*
+ * Usage of execbuffer:
+ * Relocations need to take into account the full VIRTIO_GPUDrawable size.
+ * However, the command as passed from user space must *not* contain the initial
+ * VIRTIO_GPUReleaseInfo struct (first XXX bytes)
+ */
+static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_virtgpu_execbuffer *execbuffer = data;
+ return virtio_gpu_execbuffer(dev, execbuffer, file_priv);
+}
+
+
+static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct drm_virtgpu_getparam *param = data;
+ int value;
+
+ switch (param->param) {
+ case VIRTGPU_PARAM_3D_FEATURES:
+ value = vgdev->has_virgl_3d == true ? 1 : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (copy_to_user((void __user *)(unsigned long)param->value,
+ &value, sizeof(int))) {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct drm_virtgpu_resource_create *rc = data;
+ int ret;
+ uint32_t res_id;
+ struct virtio_gpu_object *qobj;
+ struct drm_gem_object *obj;
+ uint32_t handle = 0;
+ uint32_t size;
+ struct list_head validate_list;
+ struct ttm_validate_buffer mainbuf;
+ struct virtio_gpu_fence *fence = NULL;
+ struct ww_acquire_ctx ticket;
+ struct virtio_gpu_resource_create_3d rc_3d;
+
+ if (vgdev->has_virgl_3d == false) {
+ if (rc->depth > 1)
+ return -EINVAL;
+ if (rc->nr_samples > 1)
+ return -EINVAL;
+ if (rc->last_level > 1)
+ return -EINVAL;
+ if (rc->target != 2)
+ return -EINVAL;
+ if (rc->array_size > 1)
+ return -EINVAL;
+ }
+
+ INIT_LIST_HEAD(&validate_list);
+ memset(&mainbuf, 0, sizeof(struct ttm_validate_buffer));
+
+ virtio_gpu_resource_id_get(vgdev, &res_id);
+
+ size = rc->size;
+
+ /* allocate a single page size object */
+ if (size == 0)
+ size = PAGE_SIZE;
+
+ qobj = virtio_gpu_alloc_object(dev, size, false, false);
+ if (IS_ERR(qobj)) {
+ ret = PTR_ERR(qobj);
+ goto fail_id;
+ }
+ obj = &qobj->gem_base;
+
+ if (!vgdev->has_virgl_3d) {
+ virtio_gpu_cmd_create_resource(vgdev, res_id, rc->format,
+ rc->width, rc->height);
+
+ ret = virtio_gpu_object_attach(vgdev, qobj, res_id, NULL);
+ } else {
+ /* use a gem reference since unref list undoes them */
+ drm_gem_object_reference(&qobj->gem_base);
+ mainbuf.bo = &qobj->tbo;
+ list_add(&mainbuf.head, &validate_list);
+
+ ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
+ if (ret) {
+ DRM_DEBUG("failed to validate\n");
+ goto fail_unref;
+ }
+
+ rc_3d.resource_id = cpu_to_le32(res_id);
+ rc_3d.target = cpu_to_le32(rc->target);
+ rc_3d.format = cpu_to_le32(rc->format);
+ rc_3d.bind = cpu_to_le32(rc->bind);
+ rc_3d.width = cpu_to_le32(rc->width);
+ rc_3d.height = cpu_to_le32(rc->height);
+ rc_3d.depth = cpu_to_le32(rc->depth);
+ rc_3d.array_size = cpu_to_le32(rc->array_size);
+ rc_3d.last_level = cpu_to_le32(rc->last_level);
+ rc_3d.nr_samples = cpu_to_le32(rc->nr_samples);
+ rc_3d.flags = cpu_to_le32(rc->flags);
+
+ virtio_gpu_cmd_resource_create_3d(vgdev, &rc_3d, NULL);
+ ret = virtio_gpu_object_attach(vgdev, qobj, res_id, &fence);
+ if (ret) {
+ ttm_eu_backoff_reservation(&ticket, &validate_list);
+ goto fail_unref;
+ }
+ ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
+ }
+
+ qobj->hw_res_handle = res_id;
+
+ ret = drm_gem_handle_create(file_priv, obj, &handle);
+ if (ret) {
+
+ drm_gem_object_release(obj);
+ if (vgdev->has_virgl_3d) {
+ virtio_gpu_unref_list(&validate_list);
+ fence_put(&fence->f);
+ }
+ return ret;
+ }
+ drm_gem_object_unreference_unlocked(obj);
+
+ rc->res_handle = res_id; /* similiar to a VM address */
+ rc->bo_handle = handle;
+
+ if (vgdev->has_virgl_3d) {
+ virtio_gpu_unref_list(&validate_list);
+ fence_put(&fence->f);
+ }
+ return 0;
+fail_unref:
+ if (vgdev->has_virgl_3d) {
+ virtio_gpu_unref_list(&validate_list);
+ fence_put(&fence->f);
+ }
+//fail_obj:
+// drm_gem_object_handle_unreference_unlocked(obj);
+fail_id:
+ virtio_gpu_resource_id_put(vgdev, res_id);
+ return ret;
+}
+
+static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_virtgpu_resource_info *ri = data;
+ struct drm_gem_object *gobj = NULL;
+ struct virtio_gpu_object *qobj = NULL;
+
+ gobj = drm_gem_object_lookup(dev, file_priv, ri->bo_handle);
+ if (gobj == NULL)
+ return -ENOENT;
+
+ qobj = gem_to_virtio_gpu_obj(gobj);
+
+ ri->size = qobj->gem_base.size;
+ ri->res_handle = qobj->hw_res_handle;
+ drm_gem_object_unreference_unlocked(gobj);
+ return 0;
+}
+
+static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
+ void *data,
+ struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct drm_virtgpu_3d_transfer_from_host *args = data;
+ struct drm_gem_object *gobj = NULL;
+ struct virtio_gpu_object *qobj = NULL;
+ struct virtio_gpu_fence *fence;
+ int ret;
+ u32 offset = args->offset;
+ struct virtio_gpu_box box;
+
+ if (vgdev->has_virgl_3d == false)
+ return -ENOSYS;
+
+ gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+ if (gobj == NULL)
+ return -ENOENT;
+
+ qobj = gem_to_virtio_gpu_obj(gobj);
+
+ ret = virtio_gpu_object_reserve(qobj, false);
+ if (ret)
+ goto out;
+
+ ret = ttm_bo_validate(&qobj->tbo, &qobj->placement,
+ true, false);
+ if (unlikely(ret))
+ goto out_unres;
+
+ convert_to_hw_box(&box, &args->box);
+ virtio_gpu_cmd_transfer_from_host_3d
+ (vgdev, qobj->hw_res_handle,
+ vfpriv->ctx_id, offset, args->level,
+ &box, &fence);
+ reservation_object_add_excl_fence(qobj->tbo.resv,
+ &fence->f);
+
+ fence_put(&fence->f);
+out_unres:
+ virtio_gpu_object_unreserve(qobj);
+out:
+ drm_gem_object_unreference_unlocked(gobj);
+ return ret;
+}
+
+static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct drm_virtgpu_3d_transfer_to_host *args = data;
+ struct drm_gem_object *gobj = NULL;
+ struct virtio_gpu_object *qobj = NULL;
+ struct virtio_gpu_fence *fence;
+ struct virtio_gpu_box box;
+ int ret;
+ u32 offset = args->offset;
+
+ gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+ if (gobj == NULL)
+ return -ENOENT;
+
+ qobj = gem_to_virtio_gpu_obj(gobj);
+
+ ret = virtio_gpu_object_reserve(qobj, false);
+ if (ret)
+ goto out;
+
+ ret = ttm_bo_validate(&qobj->tbo, &qobj->placement,
+ true, false);
+ if (unlikely(ret))
+ goto out_unres;
+
+ convert_to_hw_box(&box, &args->box);
+ if (!vgdev->has_virgl_3d) {
+ virtio_gpu_cmd_transfer_to_host_2d
+ (vgdev, qobj->hw_res_handle, offset,
+ box.w, box.h, box.x, box.y, NULL);
+ } else {
+ virtio_gpu_cmd_transfer_to_host_3d
+ (vgdev, qobj->hw_res_handle,
+ vfpriv ? vfpriv->ctx_id : 0, offset,
+ args->level, &box, &fence);
+ reservation_object_add_excl_fence(qobj->tbo.resv,
+ &fence->f);
+ fence_put(&fence->f);
+ }
+
+out_unres:
+ virtio_gpu_object_unreserve(qobj);
+out:
+ drm_gem_object_unreference_unlocked(gobj);
+ return ret;
+}
+
+static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_virtgpu_3d_wait *args = data;
+ struct drm_gem_object *gobj = NULL;
+ struct virtio_gpu_object *qobj = NULL;
+ int ret;
+ bool nowait = false;
+
+ gobj = drm_gem_object_lookup(dev, file, args->handle);
+ if (gobj == NULL)
+ return -ENOENT;
+
+ qobj = gem_to_virtio_gpu_obj(gobj);
+
+ if (args->flags & VIRTGPU_WAIT_NOWAIT)
+ nowait = true;
+ ret = virtio_gpu_object_wait(qobj, nowait);
+
+ drm_gem_object_unreference_unlocked(gobj);
+ return ret;
+}
+
+static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct drm_virtgpu_get_caps *args = data;
+ int size;
+ int i;
+ int found_valid = -1;
+ int ret;
+ struct virtio_gpu_drv_cap_cache *cache_ent;
+ void *ptr;
+ if (vgdev->num_capsets == 0)
+ return -ENOSYS;
+
+ spin_lock(&vgdev->display_info_lock);
+ for (i = 0; i < vgdev->num_capsets; i++) {
+ if (vgdev->capsets[i].id == args->cap_set_id) {
+ if (vgdev->capsets[i].max_version >= args->cap_set_ver) {
+ found_valid = i;
+ break;
+ }
+ }
+ }
+
+ if (found_valid == -1) {
+ spin_unlock(&vgdev->display_info_lock);
+ return -EINVAL;
+ }
+
+ size = vgdev->capsets[found_valid].max_size;
+ if (args->size > size) {
+ spin_unlock(&vgdev->display_info_lock);
+ return -EINVAL;
+ }
+
+ list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
+ if (cache_ent->id == args->cap_set_id &&
+ cache_ent->version == args->cap_set_ver) {
+ ptr = cache_ent->caps_cache;
+ spin_unlock(&vgdev->display_info_lock);
+ goto copy_exit;
+ }
+ }
+ spin_unlock(&vgdev->display_info_lock);
+
+ /* not in cache - need to talk to hw */
+ virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver,
+ &cache_ent);
+
+ ret = wait_event_timeout(vgdev->resp_wq,
+ atomic_read(&cache_ent->is_valid), 5 * HZ);
+
+ ptr = cache_ent->caps_cache;
+
+copy_exit:
+ if (copy_to_user((void __user *)(unsigned long)args->addr, ptr, size))
+ return -EFAULT;
+
+ return 0;
+}
+
+struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
+ DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
+ virtio_gpu_resource_create_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ /* make transfer async to the main ring? - no sure, can we
+ thread these in the underlying GL */
+ DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
+ virtio_gpu_transfer_from_host_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
+ virtio_gpu_transfer_to_host_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+};
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 782766c00d70..06496a128162 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -52,6 +52,41 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
events_clear, &events_clear);
}
+static void virtio_gpu_ctx_id_get(struct virtio_gpu_device *vgdev,
+ uint32_t *resid)
+{
+ int handle;
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&vgdev->ctx_id_idr_lock);
+ handle = idr_alloc(&vgdev->ctx_id_idr, NULL, 1, 0, 0);
+ spin_unlock(&vgdev->ctx_id_idr_lock);
+ idr_preload_end();
+ *resid = handle;
+}
+
+static void virtio_gpu_ctx_id_put(struct virtio_gpu_device *vgdev, uint32_t id)
+{
+ spin_lock(&vgdev->ctx_id_idr_lock);
+ idr_remove(&vgdev->ctx_id_idr, id);
+ spin_unlock(&vgdev->ctx_id_idr_lock);
+}
+
+static void virtio_gpu_context_create(struct virtio_gpu_device *vgdev,
+ uint32_t nlen, const char *name,
+ uint32_t *ctx_id)
+{
+ virtio_gpu_ctx_id_get(vgdev, ctx_id);
+ virtio_gpu_cmd_context_create(vgdev, *ctx_id, nlen, name);
+}
+
+static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev,
+ uint32_t ctx_id)
+{
+ virtio_gpu_cmd_context_destroy(vgdev, ctx_id);
+ virtio_gpu_ctx_id_put(vgdev, ctx_id);
+}
+
static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
void (*work_func)(struct work_struct *work))
{
@@ -60,6 +95,36 @@ static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
INIT_WORK(&vgvq->dequeue_work, work_func);
}
+static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
+ int num_capsets)
+{
+ int i, ret;
+
+ vgdev->capsets = kcalloc(num_capsets,
+ sizeof(struct virtio_gpu_drv_capset),
+ GFP_KERNEL);
+ if (!vgdev->capsets) {
+ DRM_ERROR("failed to allocate cap sets\n");
+ return;
+ }
+ for (i = 0; i < num_capsets; i++) {
+ virtio_gpu_cmd_get_capset_info(vgdev, i);
+ ret = wait_event_timeout(vgdev->resp_wq,
+ vgdev->capsets[i].id > 0, 5 * HZ);
+ if (ret == 0) {
+ DRM_ERROR("timed out waiting for cap set %d\n", i);
+ kfree(vgdev->capsets);
+ vgdev->capsets = NULL;
+ return;
+ }
+ DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n",
+ i, vgdev->capsets[i].id,
+ vgdev->capsets[i].max_version,
+ vgdev->capsets[i].max_size);
+ }
+ vgdev->num_capsets = num_capsets;
+}
+
int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
{
static vq_callback_t *callbacks[] = {
@@ -70,7 +135,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
struct virtio_gpu_device *vgdev;
/* this will expand later */
struct virtqueue *vqs[2];
- u32 num_scanouts;
+ u32 num_scanouts, num_capsets;
int ret;
if (!virtio_has_feature(dev->virtdev, VIRTIO_F_VERSION_1))
@@ -96,9 +161,15 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&vgdev->fence_drv.lock);
INIT_LIST_HEAD(&vgdev->fence_drv.fences);
+ INIT_LIST_HEAD(&vgdev->cap_cache);
INIT_WORK(&vgdev->config_changed_work,
virtio_gpu_config_changed_work_func);
+ if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_VIRGL))
+ vgdev->has_virgl_3d = true;
+ DRM_INFO("virgl 3d acceleration %s\n",
+ vgdev->has_virgl_3d ? "enabled" : "not available");
+
ret = vgdev->vdev->config->find_vqs(vgdev->vdev, 2, vqs,
callbacks, names);
if (ret) {
@@ -129,6 +200,11 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
ret = -EINVAL;
goto err_scanouts;
}
+ DRM_INFO("number of scanouts: %d\n", num_scanouts);
+
+ virtio_cread(vgdev->vdev, struct virtio_gpu_config,
+ num_capsets, &num_capsets);
+ DRM_INFO("number of cap sets: %d\n", num_capsets);
ret = virtio_gpu_modeset_init(vgdev);
if (ret)
@@ -137,6 +213,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
virtio_device_ready(vgdev->vdev);
vgdev->vqs_ready = true;
+ if (num_capsets)
+ virtio_gpu_get_capsets(vgdev, num_capsets);
virtio_gpu_cmd_get_display_info(vgdev);
wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
5 * HZ);
@@ -157,6 +235,16 @@ err_vqs:
return ret;
}
+static void virtio_gpu_cleanup_cap_cache(struct virtio_gpu_device *vgdev)
+{
+ struct virtio_gpu_drv_cap_cache *cache_ent, *tmp;
+
+ list_for_each_entry_safe(cache_ent, tmp, &vgdev->cap_cache, head) {
+ kfree(cache_ent->caps_cache);
+ kfree(cache_ent);
+ }
+}
+
int virtio_gpu_driver_unload(struct drm_device *dev)
{
struct virtio_gpu_device *vgdev = dev->dev_private;
@@ -170,6 +258,49 @@ int virtio_gpu_driver_unload(struct drm_device *dev)
virtio_gpu_modeset_fini(vgdev);
virtio_gpu_ttm_fini(vgdev);
virtio_gpu_free_vbufs(vgdev);
+ virtio_gpu_cleanup_cap_cache(vgdev);
+ kfree(vgdev->capsets);
kfree(vgdev);
return 0;
}
+
+int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv;
+ uint32_t id;
+ char dbgname[64], tmpname[TASK_COMM_LEN];
+
+ /* can't create contexts without 3d renderer */
+ if (!vgdev->has_virgl_3d)
+ return 0;
+
+ get_task_comm(tmpname, current);
+ snprintf(dbgname, sizeof(dbgname), "%s", tmpname);
+ dbgname[63] = 0;
+ /* allocate a virt GPU context for this opener */
+ vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL);
+ if (!vfpriv)
+ return -ENOMEM;
+
+ virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
+
+ vfpriv->ctx_id = id;
+ file->driver_priv = vfpriv;
+ return 0;
+}
+
+void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv;
+
+ if (!vgdev->has_virgl_3d)
+ return;
+
+ vfpriv = file->driver_priv;
+
+ virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id);
+ kfree(vfpriv);
+ file->driver_priv = NULL;
+}
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index 2c624c784c1d..f300eba95bb1 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -82,24 +82,19 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
size = roundup(size, PAGE_SIZE);
ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size);
if (ret != 0)
- goto err_gem_init;
+ return ret;
bo->dumb = false;
virtio_gpu_init_ttm_placement(bo, pinned);
ret = ttm_bo_init(&vgdev->mman.bdev, &bo->tbo, size, type,
&bo->placement, 0, !kernel, NULL, acc_size,
NULL, NULL, &virtio_gpu_ttm_bo_destroy);
+ /* ttm_bo_init failure will call the destroy */
if (ret != 0)
- goto err_ttm_init;
+ return ret;
*bo_ptr = bo;
return 0;
-
-err_ttm_init:
- drm_gem_object_release(&bo->gem_base);
-err_gem_init:
- kfree(bo);
- return ret;
}
int virtio_gpu_object_kmap(struct virtio_gpu_object *bo, void **ptr)
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
new file mode 100644
index 000000000000..385e0eb9826a
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2014 Canonical
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Andreas Pokorny
+ */
+
+#include "virtgpu_drv.h"
+
+/* Empty Implementations as there should not be any other driver for a virtual
+ * device that might share buffers with virtgpu */
+
+int virtgpu_gem_prime_pin(struct drm_gem_object *obj)
+{
+ WARN_ONCE(1, "not implemented");
+ return -ENODEV;
+}
+
+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)
+{
+ WARN_ONCE(1, "not implemented");
+ return ERR_PTR(-ENODEV);
+}
+
+void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+ WARN_ONCE(1, "not implemented");
+}
+
+int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
+ struct vm_area_struct *area)
+{
+ return -ENODEV;
+}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c
index b092d7b9a292..9fd924cd2b7f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ttm.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c
@@ -32,6 +32,7 @@
#include <ttm/ttm_module.h>
#include <drm/drmP.h>
#include <drm/drm.h>
+#include <drm/virtgpu_drm.h>
#include "virtgpu_drv.h"
#include <linux/delay.h>
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 1698669f4185..5a0f8a745b9d 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -293,8 +293,8 @@ void virtio_gpu_dequeue_cursor_func(struct work_struct *work)
wake_up(&vgdev->cursorq.ack_queue);
}
-static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
- struct virtio_gpu_vbuffer *vbuf)
+static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_vbuffer *vbuf)
{
struct virtqueue *vq = vgdev->ctrlq.vq;
struct scatterlist *sgs[3], vcmd, vout, vresp;
@@ -320,7 +320,6 @@ static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
incnt++;
}
- spin_lock(&vgdev->ctrlq.qlock);
retry:
ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC);
if (ret == -ENOSPC) {
@@ -331,13 +330,55 @@ retry:
} else {
virtqueue_kick(vq);
}
- spin_unlock(&vgdev->ctrlq.qlock);
if (!ret)
ret = vq->num_free;
return ret;
}
+static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_vbuffer *vbuf)
+{
+ int rc;
+
+ spin_lock(&vgdev->ctrlq.qlock);
+ rc = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf);
+ spin_unlock(&vgdev->ctrlq.qlock);
+ return rc;
+}
+
+static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_vbuffer *vbuf,
+ struct virtio_gpu_ctrl_hdr *hdr,
+ struct virtio_gpu_fence **fence)
+{
+ struct virtqueue *vq = vgdev->ctrlq.vq;
+ int rc;
+
+again:
+ spin_lock(&vgdev->ctrlq.qlock);
+
+ /*
+ * Make sure we have enouth space in the virtqueue. If not
+ * wait here until we have.
+ *
+ * Without that virtio_gpu_queue_ctrl_buffer_nolock might have
+ * to wait for free space, which can result in fence ids being
+ * submitted out-of-order.
+ */
+ if (vq->num_free < 3) {
+ spin_unlock(&vgdev->ctrlq.qlock);
+ wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= 3);
+ goto again;
+ }
+
+ if (fence)
+ virtio_gpu_fence_emit(vgdev, hdr, fence);
+ rc = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf);
+ spin_unlock(&vgdev->ctrlq.qlock);
+ return rc;
+}
+
static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
struct virtio_gpu_vbuffer *vbuf)
{
@@ -490,9 +531,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
cmd_p->r.x = x;
cmd_p->r.y = y;
- if (fence)
- virtio_gpu_fence_emit(vgdev, &cmd_p->hdr, fence);
- virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
}
static void
@@ -515,9 +554,7 @@ virtio_gpu_cmd_resource_attach_backing(struct virtio_gpu_device *vgdev,
vbuf->data_buf = ents;
vbuf->data_size = sizeof(*ents) * nents;
- if (fence)
- virtio_gpu_fence_emit(vgdev, &cmd_p->hdr, fence);
- virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
}
static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
@@ -549,6 +586,47 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
drm_kms_helper_hotplug_event(vgdev->ddev);
}
+static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_vbuffer *vbuf)
+{
+ struct virtio_gpu_get_capset_info *cmd =
+ (struct virtio_gpu_get_capset_info *)vbuf->buf;
+ struct virtio_gpu_resp_capset_info *resp =
+ (struct virtio_gpu_resp_capset_info *)vbuf->resp_buf;
+ int i = le32_to_cpu(cmd->capset_index);
+
+ spin_lock(&vgdev->display_info_lock);
+ vgdev->capsets[i].id = le32_to_cpu(resp->capset_id);
+ vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version);
+ vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size);
+ spin_unlock(&vgdev->display_info_lock);
+ wake_up(&vgdev->resp_wq);
+}
+
+static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_vbuffer *vbuf)
+{
+ struct virtio_gpu_get_capset *cmd =
+ (struct virtio_gpu_get_capset *)vbuf->buf;
+ struct virtio_gpu_resp_capset *resp =
+ (struct virtio_gpu_resp_capset *)vbuf->resp_buf;
+ struct virtio_gpu_drv_cap_cache *cache_ent;
+
+ spin_lock(&vgdev->display_info_lock);
+ list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
+ if (cache_ent->version == le32_to_cpu(cmd->capset_version) &&
+ cache_ent->id == le32_to_cpu(cmd->capset_id)) {
+ memcpy(cache_ent->caps_cache, resp->capset_data,
+ cache_ent->size);
+ atomic_set(&cache_ent->is_valid, 1);
+ break;
+ }
+ }
+ spin_unlock(&vgdev->display_info_lock);
+ wake_up(&vgdev->resp_wq);
+}
+
+
int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
{
struct virtio_gpu_ctrl_hdr *cmd_p;
@@ -572,6 +650,230 @@ int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
return 0;
}
+int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx)
+{
+ struct virtio_gpu_get_capset_info *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+ void *resp_buf;
+
+ resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset_info),
+ GFP_KERNEL);
+ if (!resp_buf)
+ return -ENOMEM;
+
+ cmd_p = virtio_gpu_alloc_cmd_resp
+ (vgdev, &virtio_gpu_cmd_get_capset_info_cb, &vbuf,
+ sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_capset_info),
+ resp_buf);
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET_INFO);
+ cmd_p->capset_index = cpu_to_le32(idx);
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+ return 0;
+}
+
+int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
+ int idx, int version,
+ struct virtio_gpu_drv_cap_cache **cache_p)
+{
+ struct virtio_gpu_get_capset *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+ int max_size = vgdev->capsets[idx].max_size;
+ struct virtio_gpu_drv_cap_cache *cache_ent;
+ void *resp_buf;
+
+ if (idx > vgdev->num_capsets)
+ return -EINVAL;
+
+ if (version > vgdev->capsets[idx].max_version)
+ return -EINVAL;
+
+ cache_ent = kzalloc(sizeof(*cache_ent), GFP_KERNEL);
+ if (!cache_ent)
+ return -ENOMEM;
+
+ cache_ent->caps_cache = kmalloc(max_size, GFP_KERNEL);
+ if (!cache_ent->caps_cache) {
+ kfree(cache_ent);
+ return -ENOMEM;
+ }
+
+ resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset) + max_size,
+ GFP_KERNEL);
+ if (!resp_buf) {
+ kfree(cache_ent->caps_cache);
+ kfree(cache_ent);
+ return -ENOMEM;
+ }
+
+ cache_ent->version = version;
+ cache_ent->id = vgdev->capsets[idx].id;
+ atomic_set(&cache_ent->is_valid, 0);
+ cache_ent->size = max_size;
+ spin_lock(&vgdev->display_info_lock);
+ list_add_tail(&cache_ent->head, &vgdev->cap_cache);
+ spin_unlock(&vgdev->display_info_lock);
+
+ cmd_p = virtio_gpu_alloc_cmd_resp
+ (vgdev, &virtio_gpu_cmd_capset_cb, &vbuf, sizeof(*cmd_p),
+ sizeof(struct virtio_gpu_resp_capset) + max_size,
+ resp_buf);
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET);
+ cmd_p->capset_id = cpu_to_le32(vgdev->capsets[idx].id);
+ cmd_p->capset_version = cpu_to_le32(version);
+ *cache_p = cache_ent;
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+
+ return 0;
+}
+
+void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
+ uint32_t nlen, const char *name)
+{
+ struct virtio_gpu_ctx_create *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE);
+ cmd_p->hdr.ctx_id = cpu_to_le32(id);
+ cmd_p->nlen = cpu_to_le32(nlen);
+ strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name)-1);
+ cmd_p->debug_name[sizeof(cmd_p->debug_name)-1] = 0;
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
+ uint32_t id)
+{
+ struct virtio_gpu_ctx_destroy *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DESTROY);
+ cmd_p->hdr.ctx_id = cpu_to_le32(id);
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
+ uint32_t ctx_id,
+ uint32_t resource_id)
+{
+ struct virtio_gpu_ctx_resource *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE);
+ cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+ cmd_p->resource_id = cpu_to_le32(resource_id);
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+
+}
+
+void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
+ uint32_t ctx_id,
+ uint32_t resource_id)
+{
+ struct virtio_gpu_ctx_resource *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE);
+ cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+ cmd_p->resource_id = cpu_to_le32(resource_id);
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void
+virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_resource_create_3d *rc_3d,
+ struct virtio_gpu_fence **fence)
+{
+ struct virtio_gpu_resource_create_3d *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ *cmd_p = *rc_3d;
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D);
+ cmd_p->hdr.flags = 0;
+
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
+void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
+ uint32_t resource_id, uint32_t ctx_id,
+ uint64_t offset, uint32_t level,
+ struct virtio_gpu_box *box,
+ struct virtio_gpu_fence **fence)
+{
+ struct virtio_gpu_transfer_host_3d *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D);
+ cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+ cmd_p->resource_id = cpu_to_le32(resource_id);
+ cmd_p->box = *box;
+ cmd_p->offset = cpu_to_le64(offset);
+ cmd_p->level = cpu_to_le32(level);
+
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
+void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
+ uint32_t resource_id, uint32_t ctx_id,
+ uint64_t offset, uint32_t level,
+ struct virtio_gpu_box *box,
+ struct virtio_gpu_fence **fence)
+{
+ struct virtio_gpu_transfer_host_3d *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D);
+ cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+ cmd_p->resource_id = cpu_to_le32(resource_id);
+ cmd_p->box = *box;
+ cmd_p->offset = cpu_to_le64(offset);
+ cmd_p->level = cpu_to_le32(level);
+
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
+void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
+ void *data, uint32_t data_size,
+ uint32_t ctx_id, struct virtio_gpu_fence **fence)
+{
+ struct virtio_gpu_cmd_submit *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ vbuf->data_buf = data;
+ vbuf->data_size = data_size;
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SUBMIT_3D);
+ cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+ cmd_p->size = cpu_to_le32(data_size);
+
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object *obj,
uint32_t resource_id,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index 8a76821177a6..6377e8151000 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -415,16 +415,16 @@ static void vmw_cmdbuf_ctx_process(struct vmw_cmdbuf_man *man,
*
* Calls vmw_cmdbuf_ctx_process() on all contexts. If any context has
* command buffers left that are not submitted to hardware, Make sure
- * IRQ handling is turned on. Otherwise, make sure it's turned off. This
- * function may return -EAGAIN to indicate it should be rerun due to
- * possibly missed IRQs if IRQs has just been turned on.
+ * IRQ handling is turned on. Otherwise, make sure it's turned off.
*/
-static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
+static void vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
{
- int notempty = 0;
+ int notempty;
struct vmw_cmdbuf_context *ctx;
int i;
+retry:
+ notempty = 0;
for_each_cmdbuf_ctx(man, i, ctx)
vmw_cmdbuf_ctx_process(man, ctx, &notempty);
@@ -440,10 +440,8 @@ static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
man->irq_on = true;
/* Rerun in case we just missed an irq. */
- return -EAGAIN;
+ goto retry;
}
-
- return 0;
}
/**
@@ -468,8 +466,7 @@ static void vmw_cmdbuf_ctx_add(struct vmw_cmdbuf_man *man,
header->cb_context = cb_context;
list_add_tail(&header->list, &man->ctx[cb_context].submitted);
- if (vmw_cmdbuf_man_process(man) == -EAGAIN)
- vmw_cmdbuf_man_process(man);
+ vmw_cmdbuf_man_process(man);
}
/**
@@ -488,8 +485,7 @@ static void vmw_cmdbuf_man_tasklet(unsigned long data)
struct vmw_cmdbuf_man *man = (struct vmw_cmdbuf_man *) data;
spin_lock(&man->lock);
- if (vmw_cmdbuf_man_process(man) == -EAGAIN)
- (void) vmw_cmdbuf_man_process(man);
+ vmw_cmdbuf_man_process(man);
spin_unlock(&man->lock);
}
@@ -507,6 +503,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
struct vmw_cmdbuf_man *man =
container_of(work, struct vmw_cmdbuf_man, work);
struct vmw_cmdbuf_header *entry, *next;
+ uint32_t dummy;
bool restart = false;
spin_lock_bh(&man->lock);
@@ -523,6 +520,8 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
if (restart && vmw_cmdbuf_startstop(man, true))
DRM_ERROR("Failed restarting command buffer context 0.\n");
+ /* Send a new fence in case one was removed */
+ vmw_fifo_send_fence(man->dev_priv, &dummy);
}
/**
@@ -682,7 +681,7 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
DRM_MM_SEARCH_DEFAULT,
DRM_MM_CREATE_DEFAULT);
if (ret) {
- (void) vmw_cmdbuf_man_process(man);
+ vmw_cmdbuf_man_process(man);
ret = drm_mm_insert_node_generic(&man->mm, info->node,
info->page_size, 0, 0,
DRM_MM_SEARCH_DEFAULT,
@@ -1168,7 +1167,14 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man,
drm_mm_init(&man->mm, 0, size >> PAGE_SHIFT);
man->has_pool = true;
- man->default_size = default_size;
+
+ /*
+ * For now, set the default size to VMW_CMDBUF_INLINE_SIZE to
+ * prevent deadlocks from happening when vmw_cmdbuf_space_pool()
+ * needs to wait for space and we block on further command
+ * submissions to be able to free up space.
+ */
+ man->default_size = VMW_CMDBUF_INLINE_SIZE;
DRM_INFO("Using command buffers with %s pool.\n",
(man->using_mob) ? "MOB" : "DMA");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 2c7a25c71af2..a09cf8529b9f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -146,73 +146,73 @@
static const struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
vmw_kms_cursor_bypass_ioctl,
- DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+ DRM_MASTER | DRM_CONTROL_ALLOW),
VMW_IOCTL_DEF(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
- DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+ DRM_MASTER | DRM_CONTROL_ALLOW),
VMW_IOCTL_DEF(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
- DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+ DRM_MASTER | DRM_CONTROL_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
- DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+ DRM_MASTER | DRM_CONTROL_ALLOW),
VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_EXECBUF, NULL, DRM_AUTH | DRM_UNLOCKED |
+ DRM_AUTH | DRM_RENDER_ALLOW),
+ VMW_IOCTL_DEF(VMW_EXECBUF, NULL, DRM_AUTH |
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
vmw_fence_obj_signaled_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
/* these allow direct access to the framebuffers mark as master only */
VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
- DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+ DRM_MASTER | DRM_AUTH),
VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
vmw_present_readback_ioctl,
- DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+ DRM_MASTER | DRM_AUTH),
VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
vmw_kms_update_layout_ioctl,
- DRM_MASTER | DRM_UNLOCKED),
+ DRM_MASTER),
VMW_IOCTL_DEF(VMW_CREATE_SHADER,
vmw_shader_define_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_SHADER,
vmw_shader_destroy_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
vmw_gb_surface_define_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
vmw_gb_surface_reference_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_SYNCCPU,
vmw_user_dmabuf_synccpu_ioctl,
- DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
vmw_extended_context_define_ioctl,
- DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_AUTH | DRM_RENDER_ALLOW),
};
static struct pci_device_id vmw_pci_id_list[] = {
@@ -643,7 +643,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
init_waitqueue_head(&dev_priv->fence_queue);
init_waitqueue_head(&dev_priv->fifo_queue);
dev_priv->fence_queue_waiters = 0;
- atomic_set(&dev_priv->fifo_queue_waiters, 0);
+ dev_priv->fifo_queue_waiters = 0;
dev_priv->used_memory_size = 0;
@@ -752,8 +752,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
dev_priv->active_master = &dev_priv->fbdev_master;
- dev_priv->mmio_virt = ioremap_cache(dev_priv->mmio_start,
- dev_priv->mmio_size);
+ dev_priv->mmio_virt = memremap(dev_priv->mmio_start,
+ dev_priv->mmio_size, MEMREMAP_WB);
if (unlikely(dev_priv->mmio_virt == NULL)) {
ret = -ENOMEM;
@@ -907,7 +907,7 @@ out_no_irq:
out_no_device:
ttm_object_device_release(&dev_priv->tdev);
out_err4:
- iounmap(dev_priv->mmio_virt);
+ memunmap(dev_priv->mmio_virt);
out_err3:
vmw_ttm_global_release(dev_priv);
out_err0:
@@ -958,7 +958,7 @@ static int vmw_driver_unload(struct drm_device *dev)
pci_release_regions(dev->pdev);
ttm_object_device_release(&dev_priv->tdev);
- iounmap(dev_priv->mmio_virt);
+ memunmap(dev_priv->mmio_virt);
if (dev_priv->ctx.staged_bindings)
vmw_binding_state_free(dev_priv->ctx.staged_bindings);
vmw_ttm_global_release(dev_priv);
@@ -1062,14 +1062,6 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
mutex_unlock(&dev->master_mutex);
/*
- * Taking the drm_global_mutex after the TTM lock might deadlock
- */
- if (!(flags & DRM_UNLOCKED)) {
- DRM_ERROR("Refusing locked ioctl access.\n");
- return ERR_PTR(-EDEADLK);
- }
-
- /*
* Take the TTM lock. Possibly sleep waiting for the authenticating
* master to become master again, or for a SIGTERM if the
* authenticating master exits.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index f19fd39b43e1..a8ae9dfb83b7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -375,7 +375,7 @@ struct vmw_private {
uint32_t stdu_max_height;
uint32_t initial_width;
uint32_t initial_height;
- u32 __iomem *mmio_virt;
+ u32 *mmio_virt;
uint32_t capabilities;
uint32_t max_gmr_ids;
uint32_t max_gmr_pages;
@@ -440,13 +440,12 @@ struct vmw_private {
spinlock_t waiter_lock;
int fence_queue_waiters; /* Protected by waiter_lock */
int goal_queue_waiters; /* Protected by waiter_lock */
- int cmdbuf_waiters; /* Protected by irq_lock */
- int error_waiters; /* Protected by irq_lock */
- atomic_t fifo_queue_waiters;
+ int cmdbuf_waiters; /* Protected by waiter_lock */
+ int error_waiters; /* Protected by waiter_lock */
+ int fifo_queue_waiters; /* Protected by waiter_lock */
uint32_t last_read_seqno;
- spinlock_t irq_lock;
struct vmw_fence_manager *fman;
- uint32_t irq_mask;
+ uint32_t irq_mask; /* Updates protected by waiter_lock */
/*
* Device state
@@ -914,9 +913,9 @@ void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height);
-u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
-int vmw_enable_vblank(struct drm_device *dev, int crtc);
-void vmw_disable_vblank(struct drm_device *dev, int crtc);
+u32 vmw_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
+int vmw_enable_vblank(struct drm_device *dev, unsigned int pipe);
+void vmw_disable_vblank(struct drm_device *dev, unsigned int pipe);
int vmw_kms_present(struct vmw_private *dev_priv,
struct drm_file *file_priv,
struct vmw_framebuffer *vfb,
@@ -1206,4 +1205,30 @@ static inline void vmw_fifo_resource_dec(struct vmw_private *dev_priv)
{
atomic_dec(&dev_priv->num_fifo_resources);
}
+
+/**
+ * vmw_mmio_read - Perform a MMIO read from volatile memory
+ *
+ * @addr: The address to read from
+ *
+ * This function is intended to be equivalent to ioread32() on
+ * memremap'd memory, but without byteswapping.
+ */
+static inline u32 vmw_mmio_read(u32 *addr)
+{
+ return READ_ONCE(*addr);
+}
+
+/**
+ * vmw_mmio_write - Perform a MMIO write to volatile memory
+ *
+ * @addr: The address to write to
+ *
+ * This function is intended to be equivalent to iowrite32 on
+ * memremap'd memory, but without byteswapping.
+ */
+static inline void vmw_mmio_write(u32 value, u32 *addr)
+{
+ WRITE_ONCE(*addr, value);
+}
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 567ddede51d1..8e689b439890 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -142,8 +142,8 @@ static bool vmw_fence_enable_signaling(struct fence *f)
struct vmw_fence_manager *fman = fman_from_fence(fence);
struct vmw_private *dev_priv = fman->dev_priv;
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
- u32 seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ u32 *fifo_mem = dev_priv->mmio_virt;
+ u32 seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
if (seqno - fence->base.seqno < VMW_FENCE_WRAP)
return false;
@@ -386,14 +386,14 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
u32 passed_seqno)
{
u32 goal_seqno;
- u32 __iomem *fifo_mem;
+ u32 *fifo_mem;
struct vmw_fence_obj *fence;
if (likely(!fman->seqno_valid))
return false;
fifo_mem = fman->dev_priv->mmio_virt;
- goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ goal_seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE_GOAL);
if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
return false;
@@ -401,8 +401,8 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
list_for_each_entry(fence, &fman->fence_list, head) {
if (!list_empty(&fence->seq_passed_actions)) {
fman->seqno_valid = true;
- iowrite32(fence->base.seqno,
- fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ vmw_mmio_write(fence->base.seqno,
+ fifo_mem + SVGA_FIFO_FENCE_GOAL);
break;
}
}
@@ -430,18 +430,18 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
{
struct vmw_fence_manager *fman = fman_from_fence(fence);
u32 goal_seqno;
- u32 __iomem *fifo_mem;
+ u32 *fifo_mem;
if (fence_is_signaled_locked(&fence->base))
return false;
fifo_mem = fman->dev_priv->mmio_virt;
- goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ goal_seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE_GOAL);
if (likely(fman->seqno_valid &&
goal_seqno - fence->base.seqno < VMW_FENCE_WRAP))
return false;
- iowrite32(fence->base.seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ vmw_mmio_write(fence->base.seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL);
fman->seqno_valid = true;
return true;
@@ -453,9 +453,9 @@ static void __vmw_fences_update(struct vmw_fence_manager *fman)
struct list_head action_list;
bool needs_rerun;
uint32_t seqno, new_seqno;
- u32 __iomem *fifo_mem = fman->dev_priv->mmio_virt;
+ u32 *fifo_mem = fman->dev_priv->mmio_virt;
- seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
rerun:
list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
if (seqno - fence->base.seqno < VMW_FENCE_WRAP) {
@@ -477,7 +477,7 @@ rerun:
needs_rerun = vmw_fence_goal_new_locked(fman, seqno);
if (unlikely(needs_rerun)) {
- new_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ new_seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
if (new_seqno != seqno) {
seqno = new_seqno;
goto rerun;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 80c40c31d4f8..a8baf5f5e765 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -36,7 +36,7 @@ struct vmw_temp_set_context {
bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
uint32_t fifo_min, hwversion;
const struct vmw_fifo_state *fifo = &dev_priv->fifo;
@@ -60,15 +60,15 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
return false;
- fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+ fifo_min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
return false;
- hwversion = ioread32(fifo_mem +
- ((fifo->capabilities &
- SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
- SVGA_FIFO_3D_HWVERSION_REVISED :
- SVGA_FIFO_3D_HWVERSION));
+ hwversion = vmw_mmio_read(fifo_mem +
+ ((fifo->capabilities &
+ SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
+ SVGA_FIFO_3D_HWVERSION_REVISED :
+ SVGA_FIFO_3D_HWVERSION));
if (hwversion == 0)
return false;
@@ -85,13 +85,13 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
uint32_t caps;
if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
return false;
- caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+ caps = vmw_mmio_read(fifo_mem + SVGA_FIFO_CAPABILITIES);
if (caps & SVGA_FIFO_CAP_PITCHLOCK)
return true;
@@ -100,7 +100,7 @@ bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
uint32_t max;
uint32_t min;
@@ -137,19 +137,19 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
if (min < PAGE_SIZE)
min = PAGE_SIZE;
- iowrite32(min, fifo_mem + SVGA_FIFO_MIN);
- iowrite32(dev_priv->mmio_size, fifo_mem + SVGA_FIFO_MAX);
+ vmw_mmio_write(min, fifo_mem + SVGA_FIFO_MIN);
+ vmw_mmio_write(dev_priv->mmio_size, fifo_mem + SVGA_FIFO_MAX);
wmb();
- iowrite32(min, fifo_mem + SVGA_FIFO_NEXT_CMD);
- iowrite32(min, fifo_mem + SVGA_FIFO_STOP);
- iowrite32(0, fifo_mem + SVGA_FIFO_BUSY);
+ vmw_mmio_write(min, fifo_mem + SVGA_FIFO_NEXT_CMD);
+ vmw_mmio_write(min, fifo_mem + SVGA_FIFO_STOP);
+ vmw_mmio_write(0, fifo_mem + SVGA_FIFO_BUSY);
mb();
vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
- max = ioread32(fifo_mem + SVGA_FIFO_MAX);
- min = ioread32(fifo_mem + SVGA_FIFO_MIN);
- fifo->capabilities = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+ max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
+ min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
+ fifo->capabilities = vmw_mmio_read(fifo_mem + SVGA_FIFO_CAPABILITIES);
DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
(unsigned int) max,
@@ -157,7 +157,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
(unsigned int) fifo->capabilities);
atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
- iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
+ vmw_mmio_write(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
vmw_marker_queue_init(&fifo->marker_queue);
return 0;
@@ -165,31 +165,23 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
- static DEFINE_SPINLOCK(ping_lock);
- unsigned long irq_flags;
+ u32 *fifo_mem = dev_priv->mmio_virt;
- /*
- * The ping_lock is needed because we don't have an atomic
- * test-and-set of the SVGA_FIFO_BUSY register.
- */
- spin_lock_irqsave(&ping_lock, irq_flags);
- if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) {
- iowrite32(1, fifo_mem + SVGA_FIFO_BUSY);
+ preempt_disable();
+ if (cmpxchg(fifo_mem + SVGA_FIFO_BUSY, 0, 1) == 0)
vmw_write(dev_priv, SVGA_REG_SYNC, reason);
- }
- spin_unlock_irqrestore(&ping_lock, irq_flags);
+ preempt_enable();
}
void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
;
- dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ dev_priv->last_read_seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
dev_priv->config_done_state);
@@ -213,11 +205,11 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
static bool vmw_fifo_is_full(struct vmw_private *dev_priv, uint32_t bytes)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
- uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
- uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
- uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
- uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
+ u32 *fifo_mem = dev_priv->mmio_virt;
+ uint32_t max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
+ uint32_t next_cmd = vmw_mmio_read(fifo_mem + SVGA_FIFO_NEXT_CMD);
+ uint32_t min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
+ uint32_t stop = vmw_mmio_read(fifo_mem + SVGA_FIFO_STOP);
return ((max - next_cmd) + (stop - min) <= bytes);
}
@@ -260,7 +252,6 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
unsigned long timeout)
{
long ret = 1L;
- unsigned long irq_flags;
if (likely(!vmw_fifo_is_full(dev_priv, bytes)))
return 0;
@@ -270,16 +261,8 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
return vmw_fifo_wait_noirq(dev_priv, bytes,
interruptible, timeout);
- spin_lock(&dev_priv->waiter_lock);
- if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) {
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- outl(SVGA_IRQFLAG_FIFO_PROGRESS,
- dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- spin_unlock(&dev_priv->waiter_lock);
+ vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
+ &dev_priv->fifo_queue_waiters);
if (interruptible)
ret = wait_event_interruptible_timeout
@@ -295,14 +278,8 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
else if (likely(ret > 0))
ret = 0;
- spin_lock(&dev_priv->waiter_lock);
- if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- spin_unlock(&dev_priv->waiter_lock);
+ vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FIFO_PROGRESS,
+ &dev_priv->fifo_queue_waiters);
return ret;
}
@@ -321,7 +298,7 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
uint32_t bytes)
{
struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
uint32_t max;
uint32_t min;
uint32_t next_cmd;
@@ -329,9 +306,9 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
int ret;
mutex_lock(&fifo_state->fifo_mutex);
- max = ioread32(fifo_mem + SVGA_FIFO_MAX);
- min = ioread32(fifo_mem + SVGA_FIFO_MIN);
- next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+ max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
+ min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
+ next_cmd = vmw_mmio_read(fifo_mem + SVGA_FIFO_NEXT_CMD);
if (unlikely(bytes >= (max - min)))
goto out_err;
@@ -342,7 +319,7 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
fifo_state->reserved_size = bytes;
while (1) {
- uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
+ uint32_t stop = vmw_mmio_read(fifo_mem + SVGA_FIFO_STOP);
bool need_bounce = false;
bool reserve_in_place = false;
@@ -376,8 +353,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
fifo_state->using_bounce_buffer = false;
if (reserveable)
- iowrite32(bytes, fifo_mem +
- SVGA_FIFO_RESERVED);
+ vmw_mmio_write(bytes, fifo_mem +
+ SVGA_FIFO_RESERVED);
return (void __force *) (fifo_mem +
(next_cmd >> 2));
} else {
@@ -427,7 +404,7 @@ void *vmw_fifo_reserve_dx(struct vmw_private *dev_priv, uint32_t bytes,
}
static void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
- u32 __iomem *fifo_mem,
+ u32 *fifo_mem,
uint32_t next_cmd,
uint32_t max, uint32_t min, uint32_t bytes)
{
@@ -439,17 +416,16 @@ static void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
if (bytes < chunk_size)
chunk_size = bytes;
- iowrite32(bytes, fifo_mem + SVGA_FIFO_RESERVED);
+ vmw_mmio_write(bytes, fifo_mem + SVGA_FIFO_RESERVED);
mb();
- memcpy_toio(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
+ memcpy(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
rest = bytes - chunk_size;
if (rest)
- memcpy_toio(fifo_mem + (min >> 2), buffer + (chunk_size >> 2),
- rest);
+ memcpy(fifo_mem + (min >> 2), buffer + (chunk_size >> 2), rest);
}
static void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
- u32 __iomem *fifo_mem,
+ u32 *fifo_mem,
uint32_t next_cmd,
uint32_t max, uint32_t min, uint32_t bytes)
{
@@ -457,12 +433,12 @@ static void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
fifo_state->dynamic_buffer : fifo_state->static_buffer;
while (bytes > 0) {
- iowrite32(*buffer++, fifo_mem + (next_cmd >> 2));
+ vmw_mmio_write(*buffer++, fifo_mem + (next_cmd >> 2));
next_cmd += sizeof(uint32_t);
if (unlikely(next_cmd == max))
next_cmd = min;
mb();
- iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
+ vmw_mmio_write(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
mb();
bytes -= sizeof(uint32_t);
}
@@ -471,10 +447,10 @@ static void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
static void vmw_local_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
{
struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
- uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
- uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
- uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+ u32 *fifo_mem = dev_priv->mmio_virt;
+ uint32_t next_cmd = vmw_mmio_read(fifo_mem + SVGA_FIFO_NEXT_CMD);
+ uint32_t max = vmw_mmio_read(fifo_mem + SVGA_FIFO_MAX);
+ uint32_t min = vmw_mmio_read(fifo_mem + SVGA_FIFO_MIN);
bool reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
if (fifo_state->dx)
@@ -507,11 +483,11 @@ static void vmw_local_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
if (next_cmd >= max)
next_cmd -= max - min;
mb();
- iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
+ vmw_mmio_write(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
}
if (reserveable)
- iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED);
+ vmw_mmio_write(0, fifo_mem + SVGA_FIFO_RESERVED);
mb();
up_write(&fifo_state->rwsem);
vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 0a970afed93b..b8c6a03c8c54 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -64,7 +64,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
break;
case DRM_VMW_PARAM_FIFO_HW_VERSION:
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
const struct vmw_fifo_state *fifo = &dev_priv->fifo;
if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) {
@@ -73,11 +73,11 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
}
param->value =
- ioread32(fifo_mem +
- ((fifo->capabilities &
- SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
- SVGA_FIFO_3D_HWVERSION_REVISED :
- SVGA_FIFO_3D_HWVERSION));
+ vmw_mmio_read(fifo_mem +
+ ((fifo->capabilities &
+ SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
+ SVGA_FIFO_3D_HWVERSION_REVISED :
+ SVGA_FIFO_3D_HWVERSION));
break;
}
case DRM_VMW_PARAM_MAX_SURF_MEMORY:
@@ -122,6 +122,22 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
return 0;
}
+static u32 vmw_mask_multisample(unsigned int cap, u32 fmt_value)
+{
+ /* If the header is updated, update the format test as well! */
+ BUILD_BUG_ON(SVGA3D_DEVCAP_DXFMT_BC5_UNORM + 1 != SVGA3D_DEVCAP_MAX);
+
+ if (cap >= SVGA3D_DEVCAP_DXFMT_X8R8G8B8 &&
+ cap <= SVGA3D_DEVCAP_DXFMT_BC5_UNORM)
+ fmt_value &= ~(SVGADX_DXFMT_MULTISAMPLE_2 |
+ SVGADX_DXFMT_MULTISAMPLE_4 |
+ SVGADX_DXFMT_MULTISAMPLE_8);
+ else if (cap == SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES)
+ return 0;
+
+ return fmt_value;
+}
+
static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
size_t size)
{
@@ -147,7 +163,8 @@ static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
for (i = 0; i < max_size; ++i) {
vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
compat_cap->pairs[i][0] = i;
- compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+ compat_cap->pairs[i][1] = vmw_mask_multisample
+ (i, vmw_read(dev_priv, SVGA_REG_DEV_CAP));
}
spin_unlock(&dev_priv->cap_lock);
@@ -162,7 +179,7 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
(struct drm_vmw_get_3d_cap_arg *) data;
struct vmw_private *dev_priv = vmw_priv(dev);
uint32_t size;
- u32 __iomem *fifo_mem;
+ u32 *fifo_mem;
void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
void *bounce;
int ret;
@@ -202,7 +219,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
spin_lock(&dev_priv->cap_lock);
for (i = 0; i < num; ++i) {
vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
- *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+ *bounce32++ = vmw_mask_multisample
+ (i, vmw_read(dev_priv, SVGA_REG_DEV_CAP));
}
spin_unlock(&dev_priv->cap_lock);
} else if (gb_objects) {
@@ -211,7 +229,7 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
goto out_err;
} else {
fifo_mem = dev_priv->mmio_virt;
- memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+ memcpy(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
}
ret = copy_to_user(buffer, bounce, size);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index 9498a5e33c12..0c7e1723292c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -36,15 +36,13 @@ irqreturn_t vmw_irq_handler(int irq, void *arg)
struct vmw_private *dev_priv = vmw_priv(dev);
uint32_t status, masked_status;
- spin_lock(&dev_priv->irq_lock);
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- masked_status = status & dev_priv->irq_mask;
- spin_unlock(&dev_priv->irq_lock);
+ masked_status = status & READ_ONCE(dev_priv->irq_mask);
if (likely(status))
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- if (!masked_status)
+ if (!status)
return IRQ_NONE;
if (masked_status & (SVGA_IRQFLAG_ANY_FENCE |
@@ -72,8 +70,8 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)
void vmw_update_seqno(struct vmw_private *dev_priv,
struct vmw_fifo_state *fifo_state)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
- uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ u32 *fifo_mem = dev_priv->mmio_virt;
+ uint32_t seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
if (dev_priv->last_read_seqno != seqno) {
dev_priv->last_read_seqno = seqno;
@@ -178,8 +176,9 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
}
finish_wait(&dev_priv->fence_queue, &__wait);
if (ret == 0 && fifo_idle) {
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
- iowrite32(signal_seq, fifo_mem + SVGA_FIFO_FENCE);
+ u32 *fifo_mem = dev_priv->mmio_virt;
+
+ vmw_mmio_write(signal_seq, fifo_mem + SVGA_FIFO_FENCE);
}
wake_up_all(&dev_priv->fence_queue);
out_err:
@@ -189,65 +188,51 @@ out_err:
return ret;
}
-void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+void vmw_generic_waiter_add(struct vmw_private *dev_priv,
+ u32 flag, int *waiter_count)
{
- spin_lock(&dev_priv->waiter_lock);
- if (dev_priv->fence_queue_waiters++ == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- outl(SVGA_IRQFLAG_ANY_FENCE,
- dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE;
+ spin_lock_bh(&dev_priv->waiter_lock);
+ if ((*waiter_count)++ == 0) {
+ outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+ dev_priv->irq_mask |= flag;
vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
}
- spin_unlock(&dev_priv->waiter_lock);
+ spin_unlock_bh(&dev_priv->waiter_lock);
}
-void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
+ u32 flag, int *waiter_count)
{
- spin_lock(&dev_priv->waiter_lock);
- if (--dev_priv->fence_queue_waiters == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE;
+ spin_lock_bh(&dev_priv->waiter_lock);
+ if (--(*waiter_count) == 0) {
+ dev_priv->irq_mask &= ~flag;
vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
}
- spin_unlock(&dev_priv->waiter_lock);
+ spin_unlock_bh(&dev_priv->waiter_lock);
}
+void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+{
+ vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
+ &dev_priv->fence_queue_waiters);
+}
+
+void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+{
+ vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
+ &dev_priv->fence_queue_waiters);
+}
void vmw_goal_waiter_add(struct vmw_private *dev_priv)
{
- spin_lock(&dev_priv->waiter_lock);
- if (dev_priv->goal_queue_waiters++ == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- outl(SVGA_IRQFLAG_FENCE_GOAL,
- dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- spin_unlock(&dev_priv->waiter_lock);
+ vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
+ &dev_priv->goal_queue_waiters);
}
void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
{
- spin_lock(&dev_priv->waiter_lock);
- if (--dev_priv->goal_queue_waiters == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- spin_unlock(&dev_priv->waiter_lock);
+ vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
+ &dev_priv->goal_queue_waiters);
}
int vmw_wait_seqno(struct vmw_private *dev_priv,
@@ -304,7 +289,6 @@ void vmw_irq_preinstall(struct drm_device *dev)
if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
return;
- spin_lock_init(&dev_priv->irq_lock);
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
}
@@ -327,30 +311,3 @@ void vmw_irq_uninstall(struct drm_device *dev)
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
}
-
-void vmw_generic_waiter_add(struct vmw_private *dev_priv,
- u32 flag, int *waiter_count)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- if ((*waiter_count)++ == 0) {
- outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= flag;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- }
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-}
-
-void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
- u32 flag, int *waiter_count)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- if (--(*waiter_count) == 0) {
- dev_priv->irq_mask &= ~flag;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- }
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 15a6c01cd016..9fcd7f82995c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -78,7 +78,7 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv,
cmd->cursor.hotspotX = hotspotX;
cmd->cursor.hotspotY = hotspotY;
- vmw_fifo_commit(dev_priv, cmd_size);
+ vmw_fifo_commit_flush(dev_priv, cmd_size);
return 0;
}
@@ -123,14 +123,14 @@ err_unreserve:
void vmw_cursor_update_position(struct vmw_private *dev_priv,
bool show, int x, int y)
{
- u32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ u32 *fifo_mem = dev_priv->mmio_virt;
uint32_t count;
- iowrite32(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
- iowrite32(x, fifo_mem + SVGA_FIFO_CURSOR_X);
- iowrite32(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
- count = ioread32(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
- iowrite32(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+ vmw_mmio_write(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
+ vmw_mmio_write(x, fifo_mem + SVGA_FIFO_CURSOR_X);
+ vmw_mmio_write(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
+ count = vmw_mmio_read(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+ vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
}
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
@@ -1155,7 +1155,8 @@ int vmw_kms_write_svga(struct vmw_private *vmw_priv,
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
else if (vmw_fifo_have_pitchlock(vmw_priv))
- iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+ vmw_mmio_write(pitch, vmw_priv->mmio_virt +
+ SVGA_FIFO_PITCHLOCK);
vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bpp);
@@ -1181,8 +1182,8 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
vmw_priv->vga_pitchlock =
vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
else if (vmw_fifo_have_pitchlock(vmw_priv))
- vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt +
- SVGA_FIFO_PITCHLOCK);
+ vmw_priv->vga_pitchlock = vmw_mmio_read(vmw_priv->mmio_virt +
+ SVGA_FIFO_PITCHLOCK);
if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
return 0;
@@ -1230,8 +1231,8 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
vmw_priv->vga_pitchlock);
else if (vmw_fifo_have_pitchlock(vmw_priv))
- iowrite32(vmw_priv->vga_pitchlock,
- vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+ vmw_mmio_write(vmw_priv->vga_pitchlock,
+ vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
return 0;
@@ -1263,7 +1264,7 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
/**
* Function called by DRM code called with vbl_lock held.
*/
-u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+u32 vmw_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
return 0;
}
@@ -1271,7 +1272,7 @@ u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
/**
* Function called by DRM code called with vbl_lock held.
*/
-int vmw_enable_vblank(struct drm_device *dev, int crtc)
+int vmw_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
return -ENOSYS;
}
@@ -1279,7 +1280,7 @@ int vmw_enable_vblank(struct drm_device *dev, int crtc)
/**
* Function called by DRM code called with vbl_lock held.
*/
-void vmw_disable_vblank(struct drm_device *dev, int crtc)
+void vmw_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index c22e2df1b336..b1fc1c02792d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -717,6 +717,8 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
&event->event.tv_usec,
true);
vmw_fence_obj_unreference(&fence);
+ } else {
+ vmw_fifo_flush(dev_priv, false);
}
return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 64b50409fa07..7d620e82e000 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -657,7 +657,8 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
struct vmw_resource *res = &user_srf->srf.res;
*p_base = NULL;
- ttm_base_object_unref(&user_srf->backup_base);
+ if (user_srf->backup_base)
+ ttm_base_object_unref(&user_srf->backup_base);
vmw_resource_unreference(&res);
}
@@ -1290,6 +1291,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
uint32_t size;
uint32_t backup_handle;
+ if (req->multisample_count != 0)
+ return -EINVAL;
if (unlikely(vmw_user_surface_size == 0))
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c
index 791de9351eeb..cc3f1825c735 100644
--- a/drivers/gpu/host1x/hw/debug_hw.c
+++ b/drivers/gpu/host1x/hw/debug_hw.c
@@ -298,7 +298,7 @@ static void host1x_debug_show_mlocks(struct host1x *host, struct output *o)
host1x_sync_readl(host, HOST1X_SYNC_MLOCK_OWNER(i));
if (HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(owner))
host1x_debug_output(o, "%d: locked by channel %d\n",
- i, HOST1X_SYNC_MLOCK_OWNER_CHID_F(owner));
+ i, HOST1X_SYNC_MLOCK_OWNER_CHID_V(owner));
else if (HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(owner))
host1x_debug_output(o, "%d: locked by cpu\n", i);
else
diff --git a/drivers/gpu/host1x/hw/hw_host1x01_sync.h b/drivers/gpu/host1x/hw/hw_host1x01_sync.h
index ac704e579977..31238c285d46 100644
--- a/drivers/gpu/host1x/hw/hw_host1x01_sync.h
+++ b/drivers/gpu/host1x/hw/hw_host1x01_sync.h
@@ -131,12 +131,12 @@ static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
}
#define HOST1X_SYNC_MLOCK_OWNER(id) \
host1x_sync_mlock_owner_r(id)
-static inline u32 host1x_sync_mlock_owner_chid_f(u32 v)
+static inline u32 host1x_sync_mlock_owner_chid_v(u32 v)
{
- return (v & 0xf) << 8;
+ return (v >> 8) & 0xf;
}
-#define HOST1X_SYNC_MLOCK_OWNER_CHID_F(v) \
- host1x_sync_mlock_owner_chid_f(v)
+#define HOST1X_SYNC_MLOCK_OWNER_CHID_V(v) \
+ host1x_sync_mlock_owner_chid_v(v)
static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
{
return (r >> 1) & 0x1;
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_sync.h b/drivers/gpu/host1x/hw/hw_host1x02_sync.h
index 4495401525e8..540c7b65995f 100644
--- a/drivers/gpu/host1x/hw/hw_host1x02_sync.h
+++ b/drivers/gpu/host1x/hw/hw_host1x02_sync.h
@@ -131,12 +131,12 @@ static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
}
#define HOST1X_SYNC_MLOCK_OWNER(id) \
host1x_sync_mlock_owner_r(id)
-static inline u32 host1x_sync_mlock_owner_chid_f(u32 v)
+static inline u32 host1x_sync_mlock_owner_chid_v(u32 v)
{
- return (v & 0xf) << 8;
+ return (v >> 8) & 0xf;
}
-#define HOST1X_SYNC_MLOCK_OWNER_CHID_F(v) \
- host1x_sync_mlock_owner_chid_f(v)
+#define HOST1X_SYNC_MLOCK_OWNER_CHID_V(v) \
+ host1x_sync_mlock_owner_chid_v(v)
static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
{
return (r >> 1) & 0x1;
diff --git a/drivers/gpu/host1x/hw/hw_host1x04_sync.h b/drivers/gpu/host1x/hw/hw_host1x04_sync.h
index ef2275b5407a..3d6c8ec65934 100644
--- a/drivers/gpu/host1x/hw/hw_host1x04_sync.h
+++ b/drivers/gpu/host1x/hw/hw_host1x04_sync.h
@@ -131,12 +131,12 @@ static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
}
#define HOST1X_SYNC_MLOCK_OWNER(id) \
host1x_sync_mlock_owner_r(id)
-static inline u32 host1x_sync_mlock_owner_chid_f(u32 v)
+static inline u32 host1x_sync_mlock_owner_chid_v(u32 v)
{
- return (v & 0xf) << 8;
+ return (v >> 8) & 0xf;
}
-#define HOST1X_SYNC_MLOCK_OWNER_CHID_F(v) \
- host1x_sync_mlock_owner_chid_f(v)
+#define HOST1X_SYNC_MLOCK_OWNER_CHID_V(v) \
+ host1x_sync_mlock_owner_chid_v(v)
static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
{
return (r >> 1) & 0x1;
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index e5a38d202a21..ba47b30d28fa 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -57,10 +57,15 @@ EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);
enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
{
switch (drm_fourcc) {
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_BGRA5551:
case DRM_FORMAT_RGB565:
case DRM_FORMAT_BGR565:
case DRM_FORMAT_RGB888:
case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_ARGB4444:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_RGBX8888:
diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c
index 3bf05bc4ab67..63eb16bf2cf0 100644
--- a/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -452,7 +452,7 @@ void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
}
EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
-static const struct ipu_rgb def_rgb_32 = {
+static const struct ipu_rgb def_xrgb_32 = {
.red = { .offset = 16, .length = 8, },
.green = { .offset = 8, .length = 8, },
.blue = { .offset = 0, .length = 8, },
@@ -460,7 +460,7 @@ static const struct ipu_rgb def_rgb_32 = {
.bits_per_pixel = 32,
};
-static const struct ipu_rgb def_bgr_32 = {
+static const struct ipu_rgb def_xbgr_32 = {
.red = { .offset = 0, .length = 8, },
.green = { .offset = 8, .length = 8, },
.blue = { .offset = 16, .length = 8, },
@@ -468,6 +468,22 @@ static const struct ipu_rgb def_bgr_32 = {
.bits_per_pixel = 32,
};
+static const struct ipu_rgb def_rgbx_32 = {
+ .red = { .offset = 24, .length = 8, },
+ .green = { .offset = 16, .length = 8, },
+ .blue = { .offset = 8, .length = 8, },
+ .transp = { .offset = 0, .length = 8, },
+ .bits_per_pixel = 32,
+};
+
+static const struct ipu_rgb def_bgrx_32 = {
+ .red = { .offset = 8, .length = 8, },
+ .green = { .offset = 16, .length = 8, },
+ .blue = { .offset = 24, .length = 8, },
+ .transp = { .offset = 0, .length = 8, },
+ .bits_per_pixel = 32,
+};
+
static const struct ipu_rgb def_rgb_24 = {
.red = { .offset = 16, .length = 8, },
.green = { .offset = 8, .length = 8, },
@@ -500,6 +516,46 @@ static const struct ipu_rgb def_bgr_16 = {
.bits_per_pixel = 16,
};
+static const struct ipu_rgb def_argb_16 = {
+ .red = { .offset = 10, .length = 5, },
+ .green = { .offset = 5, .length = 5, },
+ .blue = { .offset = 0, .length = 5, },
+ .transp = { .offset = 15, .length = 1, },
+ .bits_per_pixel = 16,
+};
+
+static const struct ipu_rgb def_argb_16_4444 = {
+ .red = { .offset = 8, .length = 4, },
+ .green = { .offset = 4, .length = 4, },
+ .blue = { .offset = 0, .length = 4, },
+ .transp = { .offset = 12, .length = 4, },
+ .bits_per_pixel = 16,
+};
+
+static const struct ipu_rgb def_abgr_16 = {
+ .red = { .offset = 0, .length = 5, },
+ .green = { .offset = 5, .length = 5, },
+ .blue = { .offset = 10, .length = 5, },
+ .transp = { .offset = 15, .length = 1, },
+ .bits_per_pixel = 16,
+};
+
+static const struct ipu_rgb def_rgba_16 = {
+ .red = { .offset = 11, .length = 5, },
+ .green = { .offset = 6, .length = 5, },
+ .blue = { .offset = 1, .length = 5, },
+ .transp = { .offset = 0, .length = 1, },
+ .bits_per_pixel = 16,
+};
+
+static const struct ipu_rgb def_bgra_16 = {
+ .red = { .offset = 1, .length = 5, },
+ .green = { .offset = 6, .length = 5, },
+ .blue = { .offset = 11, .length = 5, },
+ .transp = { .offset = 0, .length = 1, },
+ .bits_per_pixel = 16,
+};
+
#define Y_OFFSET(pix, x, y) ((x) + pix->width * (y))
#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \
(pix->width * (y) / 4) + (x) / 2)
@@ -563,11 +619,19 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
break;
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XBGR8888:
- ipu_cpmem_set_format_rgb(ch, &def_bgr_32);
+ ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
break;
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB8888:
- ipu_cpmem_set_format_rgb(ch, &def_rgb_32);
+ ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
+ break;
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
+ break;
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
break;
case DRM_FORMAT_BGR888:
ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
@@ -581,6 +645,21 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
case DRM_FORMAT_BGR565:
ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
break;
+ case DRM_FORMAT_ARGB1555:
+ ipu_cpmem_set_format_rgb(ch, &def_argb_16);
+ break;
+ case DRM_FORMAT_ABGR1555:
+ ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
+ break;
+ case DRM_FORMAT_RGBA5551:
+ ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
+ break;
+ case DRM_FORMAT_BGRA5551:
+ ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
+ break;
+ case DRM_FORMAT_ARGB4444:
+ ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c
index 752cdd2da89a..06631ac61b04 100644
--- a/drivers/gpu/ipu-v3/ipu-csi.c
+++ b/drivers/gpu/ipu-v3/ipu-csi.c
@@ -202,7 +202,7 @@ static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
u32 ipu_clk)
{
u32 temp;
- u32 div_ratio;
+ int div_ratio;
div_ratio = (ipu_clk / pixel_clk) - 1;
@@ -271,6 +271,7 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code)
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
+ case MEDIA_BUS_FMT_Y8_1X8:
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
cfg->mipi_dt = MIPI_DT_RAW8;
cfg->data_width = IPU_CSI_DATA_WIDTH_8;
@@ -538,7 +539,7 @@ void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
temp = ipu_csi_read(csi, CSI_TST_CTRL);
- if (active == false) {
+ if (!active) {
temp &= ~CSI_TEST_GEN_MODE_EN;
ipu_csi_write(csi, temp, CSI_TST_CTRL);
} else {
diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 9ef2e1f54ca4..d3ad5347342c 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -183,12 +183,19 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
}
if (interlaced) {
- dc_link_event(dc, DC_EVT_NL, 0, 3);
- dc_link_event(dc, DC_EVT_EOL, 0, 2);
- dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1);
+ int addr;
+
+ if (dc->di)
+ addr = 1;
+ else
+ addr = 0;
+
+ dc_link_event(dc, DC_EVT_NL, addr, 3);
+ dc_link_event(dc, DC_EVT_EOL, addr, 2);
+ dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
/* Init template microcode */
- dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
+ dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, 6, 1);
} else {
if (dc->di) {
dc_link_event(dc, DC_EVT_NL, 2, 3);
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 2970c6bb668c..359268e3a166 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -71,6 +71,10 @@ enum di_sync_wave {
DI_SYNC_HSYNC = 3,
DI_SYNC_VSYNC = 4,
DI_SYNC_DE = 6,
+
+ DI_SYNC_CNT1 = 2, /* counter >= 2 only */
+ DI_SYNC_CNT4 = 5, /* counter >= 5 only */
+ DI_SYNC_CNT5 = 6, /* counter >= 6 only */
};
#define SYNC_WAVE 0
@@ -211,66 +215,59 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di,
sig->mode.hback_porch + sig->mode.hfront_porch;
u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
sig->mode.vback_porch + sig->mode.vfront_porch;
- u32 reg;
struct di_sync_config cfg[] = {
{
- .run_count = h_total / 2 - 1,
- .run_src = DI_SYNC_CLK,
+ /* 1: internal VSYNC for each frame */
+ .run_count = v_total * 2 - 1,
+ .run_src = 3, /* == counter 7 */
}, {
- .run_count = h_total - 11,
+ /* PIN2: HSYNC waveform */
+ .run_count = h_total - 1,
.run_src = DI_SYNC_CLK,
- .cnt_down = 4,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_CLK,
+ .cnt_down = sig->mode.hsync_len * 2,
}, {
- .run_count = v_total * 2 - 1,
- .run_src = DI_SYNC_INT_HSYNC,
- .offset_count = 1,
- .offset_src = DI_SYNC_INT_HSYNC,
- .cnt_down = 4,
+ /* PIN3: VSYNC waveform */
+ .run_count = v_total - 1,
+ .run_src = 4, /* == counter 7 */
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = 4, /* == counter 7 */
+ .cnt_down = sig->mode.vsync_len * 2,
+ .cnt_clr_src = DI_SYNC_CNT1,
}, {
- .run_count = v_total / 2 - 1,
+ /* 4: Field */
+ .run_count = v_total / 2,
.run_src = DI_SYNC_HSYNC,
- .offset_count = sig->mode.vback_porch,
- .offset_src = DI_SYNC_HSYNC,
+ .offset_count = h_total / 2,
+ .offset_src = DI_SYNC_CLK,
.repeat_count = 2,
- .cnt_clr_src = DI_SYNC_VSYNC,
- }, {
- .run_src = DI_SYNC_HSYNC,
- .repeat_count = sig->mode.vactive / 2,
- .cnt_clr_src = 4,
- }, {
- .run_count = v_total - 1,
- .run_src = DI_SYNC_HSYNC,
+ .cnt_clr_src = DI_SYNC_CNT1,
}, {
- .run_count = v_total / 2 - 1,
+ /* 5: Active lines */
.run_src = DI_SYNC_HSYNC,
- .offset_count = 9,
+ .offset_count = (sig->mode.vsync_len +
+ sig->mode.vback_porch) / 2,
.offset_src = DI_SYNC_HSYNC,
- .repeat_count = 2,
- .cnt_clr_src = DI_SYNC_VSYNC,
+ .repeat_count = sig->mode.vactive / 2,
+ .cnt_clr_src = DI_SYNC_CNT4,
}, {
+ /* 6: Active pixel, referenced by DC */
.run_src = DI_SYNC_CLK,
- .offset_count = sig->mode.hback_porch,
+ .offset_count = sig->mode.hsync_len +
+ sig->mode.hback_porch,
.offset_src = DI_SYNC_CLK,
.repeat_count = sig->mode.hactive,
- .cnt_clr_src = 5,
+ .cnt_clr_src = DI_SYNC_CNT5,
}, {
- .run_count = v_total - 1,
- .run_src = DI_SYNC_INT_HSYNC,
- .offset_count = v_total / 2,
- .offset_src = DI_SYNC_INT_HSYNC,
- .cnt_clr_src = DI_SYNC_HSYNC,
- .cnt_down = 4,
+ /* 7: Half line HSYNC */
+ .run_count = h_total / 2 - 1,
+ .run_src = DI_SYNC_CLK,
}
};
ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
- /* set gentime select and tag sel */
- reg = ipu_di_read(di, DI_SW_GEN1(9));
- reg &= 0x1FFFFFFF;
- reg |= (3 - 1) << 29 | 0x00008000;
- ipu_di_write(di, reg, DI_SW_GEN1(9));
-
ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
}
@@ -543,6 +540,29 @@ int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
}
EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
+static u32 ipu_di_gen_polarity(int pin)
+{
+ switch (pin) {
+ case 1:
+ return DI_GEN_POLARITY_1;
+ case 2:
+ return DI_GEN_POLARITY_2;
+ case 3:
+ return DI_GEN_POLARITY_3;
+ case 4:
+ return DI_GEN_POLARITY_4;
+ case 5:
+ return DI_GEN_POLARITY_5;
+ case 6:
+ return DI_GEN_POLARITY_6;
+ case 7:
+ return DI_GEN_POLARITY_7;
+ case 8:
+ return DI_GEN_POLARITY_8;
+ }
+ return 0;
+}
+
int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
{
u32 reg;
@@ -582,15 +602,8 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
/* set y_sel = 1 */
di_gen |= 0x10000000;
- di_gen |= DI_GEN_POLARITY_5;
- di_gen |= DI_GEN_POLARITY_8;
-
- vsync_cnt = 7;
- if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
- di_gen |= DI_GEN_POLARITY_3;
- if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
- di_gen |= DI_GEN_POLARITY_2;
+ vsync_cnt = 3;
} else {
ipu_di_sync_config_noninterlaced(di, sig, div);
@@ -602,25 +615,13 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
*/
if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
vsync_cnt = 6;
-
- if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) {
- if (sig->hsync_pin == 2)
- di_gen |= DI_GEN_POLARITY_2;
- else if (sig->hsync_pin == 4)
- di_gen |= DI_GEN_POLARITY_4;
- else if (sig->hsync_pin == 7)
- di_gen |= DI_GEN_POLARITY_7;
- }
- if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) {
- if (sig->vsync_pin == 3)
- di_gen |= DI_GEN_POLARITY_3;
- else if (sig->vsync_pin == 6)
- di_gen |= DI_GEN_POLARITY_6;
- else if (sig->vsync_pin == 8)
- di_gen |= DI_GEN_POLARITY_8;
- }
}
+ if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
+ di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
+ if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
+ di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
+
if (sig->clk_pol)
di_gen |= DI_GEN_POLARITY_DISP_CLK;
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 21060668fd25..41edd5a3f100 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -1,53 +1,135 @@
/*
+ * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
+ *
* Copyright (c) 2010 Red Hat Inc.
* Author : Dave Airlie <airlied@redhat.com>
*
+ * Copyright (c) 2015 Lukas Wunner <lukas@wunner.de>
*
- * Licensed under GPLv2
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
*
- * Switcher interface - methods require for ATPX and DCM
- * - switchto - this throws the output MUX switch
- * - discrete_set_power - sets the power state for the discrete card
+ * 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.
*
- * GPU driver interface
- * - set_gpu_state - this should do the equiv of s/r for the card
- * - this should *not* set the discrete power state
- * - switch_check - check if the device is in a position to switch now
*/
#define pr_fmt(fmt) "vga_switcheroo: " fmt
-#include <linux/module.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/fs.h>
+#include <linux/console.h>
#include <linux/debugfs.h>
#include <linux/fb.h>
-
+#include <linux/fs.h>
+#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/console.h>
-#include <linux/vga_switcheroo.h>
#include <linux/pm_runtime.h>
-
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
#include <linux/vgaarb.h>
+#include <linux/vga_switcheroo.h>
+
+/**
+ * DOC: Overview
+ *
+ * vga_switcheroo is the Linux subsystem for laptop hybrid graphics.
+ * These come in two flavors:
+ *
+ * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs.
+ * * muxless: Dual GPUs but only one of them is connected to outputs.
+ * The other one is merely used to offload rendering, its results
+ * are copied over PCIe into the framebuffer. On Linux this is
+ * supported with DRI PRIME.
+ *
+ * Hybrid graphics started to appear in the late Naughties and were initially
+ * all muxed. Newer laptops moved to a muxless architecture for cost reasons.
+ * A notable exception is the MacBook Pro which continues to use a mux.
+ * Muxes come with varying capabilities: Some switch only the panel, others
+ * can also switch external displays. Some switch all display pins at once
+ * while others can switch just the DDC lines. (To allow EDID probing
+ * for the inactive GPU.) Also, muxes are often used to cut power to the
+ * discrete GPU while it is not used.
+ *
+ * DRM drivers register GPUs with vga_switcheroo, these are heretoforth called
+ * clients. The mux is called the handler. Muxless machines also register a
+ * handler to control the power state of the discrete GPU, its ->switchto
+ * callback is a no-op for obvious reasons. The discrete GPU is often equipped
+ * with an HDA controller for the HDMI/DP audio signal, this will also
+ * register as a client so that vga_switcheroo can take care of the correct
+ * suspend/resume order when changing the discrete GPU's power state. In total
+ * there can thus be up to three clients: Two vga clients (GPUs) and one audio
+ * client (on the discrete GPU). The code is mostly prepared to support
+ * machines with more than two GPUs should they become available.
+ * The GPU to which the outputs are currently switched is called the
+ * active client in vga_switcheroo parlance. The GPU not in use is the
+ * inactive client.
+ */
+/**
+ * struct vga_switcheroo_client - registered client
+ * @pdev: client pci device
+ * @fb_info: framebuffer to which console is remapped on switching
+ * @pwr_state: current power state
+ * @ops: client callbacks
+ * @id: client identifier. Determining the id requires the handler,
+ * so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID
+ * and later given their true id in vga_switcheroo_enable()
+ * @active: whether the outputs are currently switched to this client
+ * @driver_power_control: whether power state is controlled by the driver's
+ * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs
+ * interface is a no-op so as not to interfere with runtime pm
+ * @list: client list
+ *
+ * Registered client. A client can be either a GPU or an audio device on a GPU.
+ * For audio clients, the @fb_info, @active and @driver_power_control members
+ * are bogus.
+ */
struct vga_switcheroo_client {
struct pci_dev *pdev;
struct fb_info *fb_info;
- int pwr_state;
+ enum vga_switcheroo_state pwr_state;
const struct vga_switcheroo_client_ops *ops;
- int id;
+ enum vga_switcheroo_client_id id;
bool active;
bool driver_power_control;
struct list_head list;
};
+/*
+ * protects access to struct vgasr_priv
+ */
static DEFINE_MUTEX(vgasr_mutex);
+/**
+ * struct vgasr_priv - vga_switcheroo private data
+ * @active: whether vga_switcheroo is enabled.
+ * Prerequisite is the registration of two GPUs and a handler
+ * @delayed_switch_active: whether a delayed switch is pending
+ * @delayed_client_id: client to which a delayed switch is pending
+ * @debugfs_root: directory for vga_switcheroo debugfs interface
+ * @switch_file: file for vga_switcheroo debugfs interface
+ * @registered_clients: number of registered GPUs
+ * (counting only vga clients, not audio clients)
+ * @clients: list of registered clients
+ * @handler: registered handler
+ *
+ * vga_switcheroo private data. Currently only one vga_switcheroo instance
+ * per system is supported.
+ */
struct vgasr_priv {
-
bool active;
bool delayed_switch_active;
enum vga_switcheroo_client_id delayed_client_id;
@@ -58,12 +140,13 @@ struct vgasr_priv {
int registered_clients;
struct list_head clients;
- struct vga_switcheroo_handler *handler;
+ const struct vga_switcheroo_handler *handler;
};
#define ID_BIT_AUDIO 0x100
#define client_is_audio(c) ((c)->id & ID_BIT_AUDIO)
-#define client_is_vga(c) ((c)->id == -1 || !client_is_audio(c))
+#define client_is_vga(c) ((c)->id == VGA_SWITCHEROO_UNKNOWN_ID || \
+ !client_is_audio(c))
#define client_id(c) ((c)->id & ~ID_BIT_AUDIO)
static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
@@ -91,7 +174,7 @@ static void vga_switcheroo_enable(void)
vgasr_priv.handler->init();
list_for_each_entry(client, &vgasr_priv.clients, list) {
- if (client->id != -1)
+ if (client->id != VGA_SWITCHEROO_UNKNOWN_ID)
continue;
ret = vgasr_priv.handler->get_client_id(client->pdev);
if (ret < 0)
@@ -103,7 +186,16 @@ static void vga_switcheroo_enable(void)
vgasr_priv.active = true;
}
-int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
+/**
+ * vga_switcheroo_register_handler() - register handler
+ * @handler: handler callbacks
+ *
+ * Register handler. Enable vga_switcheroo if two vga clients have already
+ * registered.
+ *
+ * Return: 0 on success, -EINVAL if a handler was already registered.
+ */
+int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler)
{
mutex_lock(&vgasr_mutex);
if (vgasr_priv.handler) {
@@ -121,6 +213,11 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
}
EXPORT_SYMBOL(vga_switcheroo_register_handler);
+/**
+ * vga_switcheroo_unregister_handler() - unregister handler
+ *
+ * Unregister handler. Disable vga_switcheroo.
+ */
void vga_switcheroo_unregister_handler(void)
{
mutex_lock(&vgasr_mutex);
@@ -136,7 +233,8 @@ EXPORT_SYMBOL(vga_switcheroo_unregister_handler);
static int register_client(struct pci_dev *pdev,
const struct vga_switcheroo_client_ops *ops,
- int id, bool active, bool driver_power_control)
+ enum vga_switcheroo_client_id id, bool active,
+ bool driver_power_control)
{
struct vga_switcheroo_client *client;
@@ -164,21 +262,45 @@ static int register_client(struct pci_dev *pdev,
return 0;
}
+/**
+ * vga_switcheroo_register_client - register vga client
+ * @pdev: client pci device
+ * @ops: client callbacks
+ * @driver_power_control: whether power state is controlled by the driver's
+ * runtime pm
+ *
+ * Register vga client (GPU). Enable vga_switcheroo if another GPU and a
+ * handler have already registered. The power state of the client is assumed
+ * to be ON.
+ *
+ * Return: 0 on success, -ENOMEM on memory allocation error.
+ */
int vga_switcheroo_register_client(struct pci_dev *pdev,
const struct vga_switcheroo_client_ops *ops,
bool driver_power_control)
{
- return register_client(pdev, ops, -1,
+ return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID,
pdev == vga_default_device(),
driver_power_control);
}
EXPORT_SYMBOL(vga_switcheroo_register_client);
+/**
+ * vga_switcheroo_register_audio_client - register audio client
+ * @pdev: client pci device
+ * @ops: client callbacks
+ * @id: client identifier
+ *
+ * Register audio client (audio device on a GPU). The power state of the
+ * client is assumed to be ON.
+ *
+ * Return: 0 on success, -ENOMEM on memory allocation error.
+ */
int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
const struct vga_switcheroo_client_ops *ops,
- int id, bool active)
+ enum vga_switcheroo_client_id id)
{
- return register_client(pdev, ops, id | ID_BIT_AUDIO, active, false);
+ return register_client(pdev, ops, id | ID_BIT_AUDIO, false, false);
}
EXPORT_SYMBOL(vga_switcheroo_register_audio_client);
@@ -194,7 +316,8 @@ find_client_from_pci(struct list_head *head, struct pci_dev *pdev)
}
static struct vga_switcheroo_client *
-find_client_from_id(struct list_head *head, int client_id)
+find_client_from_id(struct list_head *head,
+ enum vga_switcheroo_client_id client_id)
{
struct vga_switcheroo_client *client;
@@ -210,24 +333,42 @@ find_active_client(struct list_head *head)
struct vga_switcheroo_client *client;
list_for_each_entry(client, head, list)
- if (client->active && client_is_vga(client))
+ if (client->active)
return client;
return NULL;
}
-int vga_switcheroo_get_client_state(struct pci_dev *pdev)
+/**
+ * vga_switcheroo_get_client_state() - obtain power state of a given client
+ * @pdev: client pci device
+ *
+ * Obtain power state of a given client as seen from vga_switcheroo.
+ * The function is only called from hda_intel.c.
+ *
+ * Return: Power state.
+ */
+enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *pdev)
{
struct vga_switcheroo_client *client;
+ enum vga_switcheroo_state ret;
+ mutex_lock(&vgasr_mutex);
client = find_client_from_pci(&vgasr_priv.clients, pdev);
if (!client)
- return VGA_SWITCHEROO_NOT_FOUND;
- if (!vgasr_priv.active)
- return VGA_SWITCHEROO_INIT;
- return client->pwr_state;
+ ret = VGA_SWITCHEROO_NOT_FOUND;
+ else
+ ret = client->pwr_state;
+ mutex_unlock(&vgasr_mutex);
+ return ret;
}
EXPORT_SYMBOL(vga_switcheroo_get_client_state);
+/**
+ * vga_switcheroo_unregister_client() - unregister client
+ * @pdev: client pci device
+ *
+ * Unregister client. Disable vga_switcheroo if this is a vga client (GPU).
+ */
void vga_switcheroo_unregister_client(struct pci_dev *pdev)
{
struct vga_switcheroo_client *client;
@@ -249,6 +390,14 @@ void vga_switcheroo_unregister_client(struct pci_dev *pdev)
}
EXPORT_SYMBOL(vga_switcheroo_unregister_client);
+/**
+ * vga_switcheroo_client_fb_set() - set framebuffer of a given client
+ * @pdev: client pci device
+ * @info: framebuffer
+ *
+ * Set framebuffer of a given client. The console will be remapped to this
+ * on switching.
+ */
void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
struct fb_info *info)
{
@@ -262,6 +411,42 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
}
EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
+/**
+ * DOC: Manual switching and manual power control
+ *
+ * In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch
+ * can be read to retrieve the current vga_switcheroo state and commands
+ * can be written to it to change the state. The file appears as soon as
+ * two GPU drivers and one handler have registered with vga_switcheroo.
+ * The following commands are understood:
+ *
+ * * OFF: Power off the device not in use.
+ * * ON: Power on the device not in use.
+ * * IGD: Switch to the integrated graphics device.
+ * Power on the integrated GPU if necessary, power off the discrete GPU.
+ * Prerequisite is that no user space processes (e.g. Xorg, alsactl)
+ * have opened device files of the GPUs or the audio client. If the
+ * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/
+ * and /dev/snd/controlC1 to identify processes blocking the switch.
+ * * DIS: Switch to the discrete graphics device.
+ * * DIGD: Delayed switch to the integrated graphics device.
+ * This will perform the switch once the last user space process has
+ * closed the device files of the GPUs and the audio client.
+ * * DDIS: Delayed switch to the discrete graphics device.
+ * * MIGD: Mux-only switch to the integrated graphics device.
+ * Does not remap console or change the power state of either gpu.
+ * If the integrated GPU is currently off, the screen will turn black.
+ * If it is on, the screen will show whatever happens to be in VRAM.
+ * Either way, the user has to blindly enter the command to switch back.
+ * * MDIS: Mux-only switch to the discrete graphics device.
+ *
+ * For GPUs whose power state is controlled by the driver's runtime pm,
+ * the ON and OFF commands are a no-op (see next section).
+ *
+ * For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands
+ * should not be used.
+ */
+
static int vga_switcheroo_show(struct seq_file *m, void *v)
{
struct vga_switcheroo_client *client;
@@ -312,7 +497,8 @@ static int vga_switchoff(struct vga_switcheroo_client *client)
return 0;
}
-static void set_audio_state(int id, int state)
+static void set_audio_state(enum vga_switcheroo_client_id id,
+ enum vga_switcheroo_state state)
{
struct vga_switcheroo_client *client;
@@ -399,7 +585,7 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
int ret;
bool delay = false, can_switch;
bool just_mux = false;
- int client_id = -1;
+ enum vga_switcheroo_client_id client_id = VGA_SWITCHEROO_UNKNOWN_ID;
struct vga_switcheroo_client *client = NULL;
if (cnt > 63)
@@ -468,7 +654,7 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
client_id = VGA_SWITCHEROO_DIS;
}
- if (client_id == -1)
+ if (client_id == VGA_SWITCHEROO_UNKNOWN_ID)
goto out;
client = find_client_from_id(&vgasr_priv.clients, client_id);
if (!client)
@@ -559,6 +745,16 @@ fail:
return -1;
}
+/**
+ * vga_switcheroo_process_delayed_switch() - helper for delayed switching
+ *
+ * Process a delayed switch if one is pending. DRM drivers should call this
+ * from their ->lastclose callback.
+ *
+ * Return: 0 on success. -EINVAL if no delayed switch is pending, if the client
+ * has unregistered in the meantime or if there are other clients blocking the
+ * switch. If the actual switch fails, an error is reported and 0 is returned.
+ */
int vga_switcheroo_process_delayed_switch(void)
{
struct vga_switcheroo_client *client;
@@ -589,6 +785,39 @@ err:
}
EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
+/**
+ * DOC: Driver power control
+ *
+ * In this mode of use, the discrete GPU automatically powers up and down at
+ * the discretion of the driver's runtime pm. On muxed machines, the user may
+ * still influence the muxer state by way of the debugfs interface, however
+ * the ON and OFF commands become a no-op for the discrete GPU.
+ *
+ * This mode is the default on Nvidia HybridPower/Optimus and ATI PowerXpress.
+ * Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel
+ * command line disables it.
+ *
+ * When the driver decides to power up or down, it notifies vga_switcheroo
+ * thereof so that it can (a) power the audio device on the GPU up or down,
+ * and (b) update its internal power state representation for the device.
+ * This is achieved by vga_switcheroo_set_dynamic_switch().
+ *
+ * After the GPU has been suspended, the handler needs to be called to cut
+ * power to the GPU. Likewise it needs to reinstate power before the GPU
+ * can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(),
+ * which augments the GPU's suspend/resume functions by the requisite
+ * calls to the handler.
+ *
+ * When the audio device resumes, the GPU needs to be woken. This is achieved
+ * by vga_switcheroo_init_domain_pm_optimus_hdmi_audio(), which augments the
+ * audio device's resume function.
+ *
+ * On muxed machines, if the mux is initially switched to the discrete GPU,
+ * the user ends up with a black screen when the GPU powers down after boot.
+ * As a workaround, the mux is forced to the integrated GPU on runtime suspend,
+ * cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917
+ */
+
static void vga_switcheroo_power_switch(struct pci_dev *pdev,
enum vga_switcheroo_state state)
{
@@ -607,22 +836,32 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev,
vgasr_priv.handler->power_state(client->id, state);
}
-/* force a PCI device to a certain state - mainly to turn off audio clients */
-
+/**
+ * vga_switcheroo_set_dynamic_switch() - helper for driver power control
+ * @pdev: client pci device
+ * @dynamic: new power state
+ *
+ * Helper for GPUs whose power state is controlled by the driver's runtime pm.
+ * When the driver decides to power up or down, it notifies vga_switcheroo
+ * thereof using this helper so that it can (a) power the audio device on
+ * the GPU up or down, and (b) update its internal power state representation
+ * for the device.
+ */
void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
enum vga_switcheroo_state dynamic)
{
struct vga_switcheroo_client *client;
+ mutex_lock(&vgasr_mutex);
client = find_client_from_pci(&vgasr_priv.clients, pdev);
- if (!client)
- return;
-
- if (!client->driver_power_control)
+ if (!client || !client->driver_power_control) {
+ mutex_unlock(&vgasr_mutex);
return;
+ }
client->pwr_state = dynamic;
set_audio_state(client->id, dynamic);
+ mutex_unlock(&vgasr_mutex);
}
EXPORT_SYMBOL(vga_switcheroo_set_dynamic_switch);
@@ -635,9 +874,11 @@ static int vga_switcheroo_runtime_suspend(struct device *dev)
ret = dev->bus->pm->runtime_suspend(dev);
if (ret)
return ret;
+ mutex_lock(&vgasr_mutex);
if (vgasr_priv.handler->switchto)
vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD);
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF);
+ mutex_unlock(&vgasr_mutex);
return 0;
}
@@ -646,7 +887,9 @@ static int vga_switcheroo_runtime_resume(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
int ret;
+ mutex_lock(&vgasr_mutex);
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_ON);
+ mutex_unlock(&vgasr_mutex);
ret = dev->bus->pm->runtime_resume(dev);
if (ret)
return ret;
@@ -654,8 +897,18 @@ static int vga_switcheroo_runtime_resume(struct device *dev)
return 0;
}
-/* this version is for the case where the power switch is separate
- to the device being powered down. */
+/**
+ * vga_switcheroo_init_domain_pm_ops() - helper for driver power control
+ * @dev: vga client device
+ * @domain: power domain
+ *
+ * Helper for GPUs whose power state is controlled by the driver's runtime pm.
+ * After the GPU has been suspended, the handler needs to be called to cut
+ * power to the GPU. Likewise it needs to reinstate power before the GPU
+ * can resume. To this end, this helper augments the suspend/resume functions
+ * by the requisite calls to the handler. It needs only be called on platforms
+ * where the power switch is separate to the device being powered down.
+ */
int vga_switcheroo_init_domain_pm_ops(struct device *dev,
struct dev_pm_domain *domain)
{
@@ -682,33 +935,50 @@ EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
+ struct vga_switcheroo_client *client;
+ struct device *video_dev = NULL;
int ret;
- struct vga_switcheroo_client *client, *found = NULL;
/* we need to check if we have to switch back on the video
device so the audio device can come back */
+ mutex_lock(&vgasr_mutex);
list_for_each_entry(client, &vgasr_priv.clients, list) {
if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
client_is_vga(client)) {
- found = client;
- ret = pm_runtime_get_sync(&client->pdev->dev);
- if (ret) {
- if (ret != 1)
- return ret;
- }
+ video_dev = &client->pdev->dev;
break;
}
}
+ mutex_unlock(&vgasr_mutex);
+
+ if (video_dev) {
+ ret = pm_runtime_get_sync(video_dev);
+ if (ret && ret != 1)
+ return ret;
+ }
ret = dev->bus->pm->runtime_resume(dev);
/* put the reference for the gpu */
- if (found) {
- pm_runtime_mark_last_busy(&found->pdev->dev);
- pm_runtime_put_autosuspend(&found->pdev->dev);
+ if (video_dev) {
+ pm_runtime_mark_last_busy(video_dev);
+ pm_runtime_put_autosuspend(video_dev);
}
return ret;
}
+/**
+ * vga_switcheroo_init_domain_pm_optimus_hdmi_audio() - helper for driver
+ * power control
+ * @dev: audio client device
+ * @domain: power domain
+ *
+ * Helper for GPUs whose power state is controlled by the driver's runtime pm.
+ * When the audio device resumes, the GPU needs to be woken. This helper
+ * augments the audio device's resume function to do that.
+ *
+ * Return: 0 on success, -EINVAL if no power management operations are
+ * defined for this device.
+ */
int
vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev,
struct dev_pm_domain *domain)
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index a0b433456107..3166e4bc4eb6 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -531,7 +531,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
return false;
/* Allocate structure */
- vgadev = kmalloc(sizeof(struct vga_device), GFP_KERNEL);
+ vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL);
if (vgadev == NULL) {
pr_err("failed to allocate pci device\n");
/*
@@ -541,8 +541,6 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
return false;
}
- memset(vgadev, 0, sizeof(*vgadev));
-
/* Take lock & check for duplicates */
spin_lock_irqsave(&vga_lock, flags);
if (vgadev_find(pdev) != NULL) {
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6ab51ae3c39d..513a16cc6e18 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -171,6 +171,16 @@ config HID_CHICONY
---help---
Support for Chicony Tactical pad.
+config HID_CORSAIR
+ tristate "Corsair devices"
+ depends on HID && USB && LEDS_CLASS
+ ---help---
+ Support for Corsair devices that are not fully compliant with the
+ HID standard.
+
+ Supported devices:
+ - Vengeance K90
+
config HID_PRODIKEYS
tristate "Prodikeys PC-MIDI Keyboard support"
depends on HID && SND
@@ -257,6 +267,12 @@ config HID_GEMBIRD
---help---
Support for Gembird JPD-DualForce 2.
+config HID_GFRM
+ tristate "Google Fiber TV Box remote control support"
+ depends on HID
+ ---help---
+ Support for Google Fiber TV Box remote controls
+
config HID_HOLTEK
tristate "Holtek HID devices"
depends on USB_HID
@@ -672,9 +688,8 @@ config HID_SAITEK
Supported devices:
- PS1000 Dual Analog Pad
- - R.A.T.9 Gaming Mouse
- - R.A.T.7 Gaming Mouse
- - M.M.O.7 Gaming Mouse
+ - Saitek R.A.T.7, R.A.T.9, M.M.O.7 Gaming Mice
+ - Mad Catz R.A.T.5, R.A.T.9 Gaming Mice
config HID_SAMSUNG
tristate "Samsung InfraRed remote control or keyboards"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e6441bc7dae4..00011fee08b9 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
+obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o
obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
@@ -37,6 +38,7 @@ obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
obj-$(CONFIG_HID_ELO) += hid-elo.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
+obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c
index 0e6a42d37eb6..07cbc70f00e7 100644
--- a/drivers/hid/hid-appleir.c
+++ b/drivers/hid/hid-appleir.c
@@ -256,7 +256,7 @@ out:
return 0;
}
-static void appleir_input_configured(struct hid_device *hid,
+static int appleir_input_configured(struct hid_device *hid,
struct hid_input *hidinput)
{
struct input_dev *input_dev = hidinput->input;
@@ -275,6 +275,8 @@ static void appleir_input_configured(struct hid_device *hid,
for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
set_bit(appleir->keymap[i], input_dev->keybit);
clear_bit(KEY_RESERVED, input_dev->keybit);
+
+ return 0;
}
static int appleir_input_mapping(struct hid_device *hid,
diff --git a/drivers/hid/hid-aureal.c b/drivers/hid/hid-aureal.c
index 340ba9d394a0..3280aff28e90 100644
--- a/drivers/hid/hid-aureal.c
+++ b/drivers/hid/hid-aureal.c
@@ -23,7 +23,8 @@ static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc,
if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n");
rdesc[53] = 0x65;
- } return rdesc;
+ }
+ return rdesc;
}
static const struct hid_device_id aureal_devices[] = {
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 70a11ac38119..c6f7a694f67a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -725,6 +725,7 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
(hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
+ hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
@@ -1611,7 +1612,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
"Multi-Axis Controller"
};
const char *type, *bus;
- char buf[64];
+ char buf[64] = "";
unsigned int i;
int len;
int ret;
@@ -1678,6 +1679,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
case BUS_BLUETOOTH:
bus = "BLUETOOTH";
break;
+ case BUS_I2C:
+ bus = "I2C";
+ break;
default:
bus = "<UNKNOWN>";
}
@@ -1828,6 +1832,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
@@ -1896,6 +1901,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
@@ -1928,6 +1934,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
@@ -1981,6 +1988,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c
new file mode 100644
index 000000000000..bcefb9ebb026
--- /dev/null
+++ b/drivers/hid/hid-corsair.c
@@ -0,0 +1,673 @@
+/*
+ * HID driver for Corsair devices
+ *
+ * Supported devices:
+ * - Vengeance K90 Keyboard
+ *
+ * Copyright (c) 2015 Clement Vuchener
+ */
+
+/*
+ * 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/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/leds.h>
+
+#include "hid-ids.h"
+
+#define CORSAIR_USE_K90_MACRO (1<<0)
+#define CORSAIR_USE_K90_BACKLIGHT (1<<1)
+
+struct k90_led {
+ struct led_classdev cdev;
+ int brightness;
+ struct work_struct work;
+ bool removed;
+};
+
+struct k90_drvdata {
+ struct k90_led record_led;
+};
+
+struct corsair_drvdata {
+ unsigned long quirks;
+ struct k90_drvdata *k90;
+ struct k90_led *backlight;
+};
+
+#define K90_GKEY_COUNT 18
+
+static int corsair_usage_to_gkey(unsigned int usage)
+{
+ /* G1 (0xd0) to G16 (0xdf) */
+ if (usage >= 0xd0 && usage <= 0xdf)
+ return usage - 0xd0 + 1;
+ /* G17 (0xe8) to G18 (0xe9) */
+ if (usage >= 0xe8 && usage <= 0xe9)
+ return usage - 0xe8 + 17;
+ return 0;
+}
+
+static unsigned short corsair_gkey_map[K90_GKEY_COUNT] = {
+ BTN_TRIGGER_HAPPY1,
+ BTN_TRIGGER_HAPPY2,
+ BTN_TRIGGER_HAPPY3,
+ BTN_TRIGGER_HAPPY4,
+ BTN_TRIGGER_HAPPY5,
+ BTN_TRIGGER_HAPPY6,
+ BTN_TRIGGER_HAPPY7,
+ BTN_TRIGGER_HAPPY8,
+ BTN_TRIGGER_HAPPY9,
+ BTN_TRIGGER_HAPPY10,
+ BTN_TRIGGER_HAPPY11,
+ BTN_TRIGGER_HAPPY12,
+ BTN_TRIGGER_HAPPY13,
+ BTN_TRIGGER_HAPPY14,
+ BTN_TRIGGER_HAPPY15,
+ BTN_TRIGGER_HAPPY16,
+ BTN_TRIGGER_HAPPY17,
+ BTN_TRIGGER_HAPPY18,
+};
+
+module_param_array_named(gkey_codes, corsair_gkey_map, ushort, NULL, S_IRUGO);
+MODULE_PARM_DESC(gkey_codes, "Key codes for the G-keys");
+
+static unsigned short corsair_record_keycodes[2] = {
+ BTN_TRIGGER_HAPPY19,
+ BTN_TRIGGER_HAPPY20
+};
+
+module_param_array_named(recordkey_codes, corsair_record_keycodes, ushort,
+ NULL, S_IRUGO);
+MODULE_PARM_DESC(recordkey_codes, "Key codes for the MR (start and stop record) button");
+
+static unsigned short corsair_profile_keycodes[3] = {
+ BTN_TRIGGER_HAPPY21,
+ BTN_TRIGGER_HAPPY22,
+ BTN_TRIGGER_HAPPY23
+};
+
+module_param_array_named(profilekey_codes, corsair_profile_keycodes, ushort,
+ NULL, S_IRUGO);
+MODULE_PARM_DESC(profilekey_codes, "Key codes for the profile buttons");
+
+#define CORSAIR_USAGE_SPECIAL_MIN 0xf0
+#define CORSAIR_USAGE_SPECIAL_MAX 0xff
+
+#define CORSAIR_USAGE_MACRO_RECORD_START 0xf6
+#define CORSAIR_USAGE_MACRO_RECORD_STOP 0xf7
+
+#define CORSAIR_USAGE_PROFILE 0xf1
+#define CORSAIR_USAGE_M1 0xf1
+#define CORSAIR_USAGE_M2 0xf2
+#define CORSAIR_USAGE_M3 0xf3
+#define CORSAIR_USAGE_PROFILE_MAX 0xf3
+
+#define CORSAIR_USAGE_META_OFF 0xf4
+#define CORSAIR_USAGE_META_ON 0xf5
+
+#define CORSAIR_USAGE_LIGHT 0xfa
+#define CORSAIR_USAGE_LIGHT_OFF 0xfa
+#define CORSAIR_USAGE_LIGHT_DIM 0xfb
+#define CORSAIR_USAGE_LIGHT_MEDIUM 0xfc
+#define CORSAIR_USAGE_LIGHT_BRIGHT 0xfd
+#define CORSAIR_USAGE_LIGHT_MAX 0xfd
+
+/* USB control protocol */
+
+#define K90_REQUEST_BRIGHTNESS 49
+#define K90_REQUEST_MACRO_MODE 2
+#define K90_REQUEST_STATUS 4
+#define K90_REQUEST_GET_MODE 5
+#define K90_REQUEST_PROFILE 20
+
+#define K90_MACRO_MODE_SW 0x0030
+#define K90_MACRO_MODE_HW 0x0001
+
+#define K90_MACRO_LED_ON 0x0020
+#define K90_MACRO_LED_OFF 0x0040
+
+/*
+ * LED class devices
+ */
+
+#define K90_BACKLIGHT_LED_SUFFIX "::backlight"
+#define K90_RECORD_LED_SUFFIX "::record"
+
+static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev)
+{
+ int ret;
+ struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
+ struct device *dev = led->cdev.dev->parent;
+ struct usb_interface *usbif = to_usb_interface(dev->parent);
+ struct usb_device *usbdev = interface_to_usbdev(usbif);
+ int brightness;
+ char data[8];
+
+ ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+ K90_REQUEST_STATUS,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, 0, 0, data, 8,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret < 0) {
+ dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
+ ret);
+ return -EIO;
+ }
+ brightness = data[4];
+ if (brightness < 0 || brightness > 3) {
+ dev_warn(dev,
+ "Read invalid backlight brightness: %02hhx.\n",
+ data[4]);
+ return -EIO;
+ }
+ return brightness;
+}
+
+static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
+{
+ struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
+
+ return led->brightness;
+}
+
+static void k90_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
+
+ led->brightness = brightness;
+ schedule_work(&led->work);
+}
+
+static void k90_backlight_work(struct work_struct *work)
+{
+ int ret;
+ struct k90_led *led = container_of(work, struct k90_led, work);
+ struct device *dev;
+ struct usb_interface *usbif;
+ struct usb_device *usbdev;
+
+ if (led->removed)
+ return;
+
+ dev = led->cdev.dev->parent;
+ usbif = to_usb_interface(dev->parent);
+ usbdev = interface_to_usbdev(usbif);
+
+ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+ K90_REQUEST_BRIGHTNESS,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, led->brightness, 0,
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (ret != 0)
+ dev_warn(dev, "Failed to set backlight brightness (error: %d).\n",
+ ret);
+}
+
+static void k90_record_led_work(struct work_struct *work)
+{
+ int ret;
+ struct k90_led *led = container_of(work, struct k90_led, work);
+ struct device *dev;
+ struct usb_interface *usbif;
+ struct usb_device *usbdev;
+ int value;
+
+ if (led->removed)
+ return;
+
+ dev = led->cdev.dev->parent;
+ usbif = to_usb_interface(dev->parent);
+ usbdev = interface_to_usbdev(usbif);
+
+ if (led->brightness > 0)
+ value = K90_MACRO_LED_ON;
+ else
+ value = K90_MACRO_LED_OFF;
+
+ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+ K90_REQUEST_MACRO_MODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, value, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret != 0)
+ dev_warn(dev, "Failed to set record LED state (error: %d).\n",
+ ret);
+}
+
+/*
+ * Keyboard attributes
+ */
+
+static ssize_t k90_show_macro_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct usb_interface *usbif = to_usb_interface(dev->parent);
+ struct usb_device *usbdev = interface_to_usbdev(usbif);
+ const char *macro_mode;
+ char data[8];
+
+ ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+ K90_REQUEST_GET_MODE,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, 0, 0, data, 2,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret < 0) {
+ dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
+ ret);
+ return -EIO;
+ }
+
+ switch (data[0]) {
+ case K90_MACRO_MODE_HW:
+ macro_mode = "HW";
+ break;
+
+ case K90_MACRO_MODE_SW:
+ macro_mode = "SW";
+ break;
+ default:
+ dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
+ data[0]);
+ return -EIO;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+}
+
+static ssize_t k90_store_macro_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ struct usb_interface *usbif = to_usb_interface(dev->parent);
+ struct usb_device *usbdev = interface_to_usbdev(usbif);
+ __u16 value;
+
+ if (strncmp(buf, "SW", 2) == 0)
+ value = K90_MACRO_MODE_SW;
+ else if (strncmp(buf, "HW", 2) == 0)
+ value = K90_MACRO_MODE_HW;
+ else
+ return -EINVAL;
+
+ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+ K90_REQUEST_MACRO_MODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, value, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret != 0) {
+ dev_warn(dev, "Failed to set macro mode.\n");
+ return ret;
+ }
+
+ return count;
+}
+
+static ssize_t k90_show_current_profile(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ struct usb_interface *usbif = to_usb_interface(dev->parent);
+ struct usb_device *usbdev = interface_to_usbdev(usbif);
+ int current_profile;
+ char data[8];
+
+ ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+ K90_REQUEST_STATUS,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, 0, 0, data, 8,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret < 0) {
+ dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
+ ret);
+ return -EIO;
+ }
+ current_profile = data[7];
+ if (current_profile < 1 || current_profile > 3) {
+ dev_warn(dev, "Read invalid current profile: %02hhx.\n",
+ data[7]);
+ return -EIO;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+}
+
+static ssize_t k90_store_current_profile(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ struct usb_interface *usbif = to_usb_interface(dev->parent);
+ struct usb_device *usbdev = interface_to_usbdev(usbif);
+ int profile;
+
+ if (kstrtoint(buf, 10, &profile))
+ return -EINVAL;
+ if (profile < 1 || profile > 3)
+ return -EINVAL;
+
+ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+ K90_REQUEST_PROFILE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, profile, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret != 0) {
+ dev_warn(dev, "Failed to change current profile (error %d).\n",
+ ret);
+ return ret;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(macro_mode, 0644, k90_show_macro_mode, k90_store_macro_mode);
+static DEVICE_ATTR(current_profile, 0644, k90_show_current_profile,
+ k90_store_current_profile);
+
+static struct attribute *k90_attrs[] = {
+ &dev_attr_macro_mode.attr,
+ &dev_attr_current_profile.attr,
+ NULL
+};
+
+static const struct attribute_group k90_attr_group = {
+ .attrs = k90_attrs,
+};
+
+/*
+ * Driver functions
+ */
+
+static int k90_init_backlight(struct hid_device *dev)
+{
+ int ret;
+ struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+ size_t name_sz;
+ char *name;
+
+ drvdata->backlight = kzalloc(sizeof(struct k90_led), GFP_KERNEL);
+ if (!drvdata->backlight) {
+ ret = -ENOMEM;
+ goto fail_backlight_alloc;
+ }
+
+ name_sz =
+ strlen(dev_name(&dev->dev)) + sizeof(K90_BACKLIGHT_LED_SUFFIX);
+ name = kzalloc(name_sz, GFP_KERNEL);
+ if (!name) {
+ ret = -ENOMEM;
+ goto fail_name_alloc;
+ }
+ snprintf(name, name_sz, "%s" K90_BACKLIGHT_LED_SUFFIX,
+ dev_name(&dev->dev));
+ drvdata->backlight->removed = false;
+ drvdata->backlight->cdev.name = name;
+ drvdata->backlight->cdev.max_brightness = 3;
+ drvdata->backlight->cdev.brightness_set = k90_brightness_set;
+ drvdata->backlight->cdev.brightness_get = k90_backlight_get;
+ INIT_WORK(&drvdata->backlight->work, k90_backlight_work);
+ ret = led_classdev_register(&dev->dev, &drvdata->backlight->cdev);
+ if (ret != 0)
+ goto fail_register_cdev;
+
+ return 0;
+
+fail_register_cdev:
+ kfree(drvdata->backlight->cdev.name);
+fail_name_alloc:
+ kfree(drvdata->backlight);
+ drvdata->backlight = NULL;
+fail_backlight_alloc:
+ return ret;
+}
+
+static int k90_init_macro_functions(struct hid_device *dev)
+{
+ int ret;
+ struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+ struct k90_drvdata *k90;
+ size_t name_sz;
+ char *name;
+
+ k90 = kzalloc(sizeof(struct k90_drvdata), GFP_KERNEL);
+ if (!k90) {
+ ret = -ENOMEM;
+ goto fail_drvdata;
+ }
+ drvdata->k90 = k90;
+
+ /* Init LED device for record LED */
+ name_sz = strlen(dev_name(&dev->dev)) + sizeof(K90_RECORD_LED_SUFFIX);
+ name = kzalloc(name_sz, GFP_KERNEL);
+ if (!name) {
+ ret = -ENOMEM;
+ goto fail_record_led_alloc;
+ }
+ snprintf(name, name_sz, "%s" K90_RECORD_LED_SUFFIX,
+ dev_name(&dev->dev));
+ k90->record_led.removed = false;
+ k90->record_led.cdev.name = name;
+ k90->record_led.cdev.max_brightness = 1;
+ k90->record_led.cdev.brightness_set = k90_brightness_set;
+ k90->record_led.cdev.brightness_get = k90_record_led_get;
+ INIT_WORK(&k90->record_led.work, k90_record_led_work);
+ k90->record_led.brightness = 0;
+ ret = led_classdev_register(&dev->dev, &k90->record_led.cdev);
+ if (ret != 0)
+ goto fail_record_led;
+
+ /* Init attributes */
+ ret = sysfs_create_group(&dev->dev.kobj, &k90_attr_group);
+ if (ret != 0)
+ goto fail_sysfs;
+
+ return 0;
+
+fail_sysfs:
+ k90->record_led.removed = true;
+ led_classdev_unregister(&k90->record_led.cdev);
+ cancel_work_sync(&k90->record_led.work);
+fail_record_led:
+ kfree(k90->record_led.cdev.name);
+fail_record_led_alloc:
+ kfree(k90);
+fail_drvdata:
+ drvdata->k90 = NULL;
+ return ret;
+}
+
+static void k90_cleanup_backlight(struct hid_device *dev)
+{
+ struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+
+ if (drvdata->backlight) {
+ drvdata->backlight->removed = true;
+ led_classdev_unregister(&drvdata->backlight->cdev);
+ cancel_work_sync(&drvdata->backlight->work);
+ kfree(drvdata->backlight->cdev.name);
+ kfree(drvdata->backlight);
+ }
+}
+
+static void k90_cleanup_macro_functions(struct hid_device *dev)
+{
+ struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+ struct k90_drvdata *k90 = drvdata->k90;
+
+ if (k90) {
+ sysfs_remove_group(&dev->dev.kobj, &k90_attr_group);
+
+ k90->record_led.removed = true;
+ led_classdev_unregister(&k90->record_led.cdev);
+ cancel_work_sync(&k90->record_led.work);
+ kfree(k90->record_led.cdev.name);
+
+ kfree(k90);
+ }
+}
+
+static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id)
+{
+ int ret;
+ unsigned long quirks = id->driver_data;
+ struct corsair_drvdata *drvdata;
+ struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
+
+ drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
+ GFP_KERNEL);
+ if (drvdata == NULL)
+ return -ENOMEM;
+ drvdata->quirks = quirks;
+ hid_set_drvdata(dev, drvdata);
+
+ ret = hid_parse(dev);
+ if (ret != 0) {
+ hid_err(dev, "parse failed\n");
+ return ret;
+ }
+ ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
+ if (ret != 0) {
+ hid_err(dev, "hw start failed\n");
+ return ret;
+ }
+
+ if (usbif->cur_altsetting->desc.bInterfaceNumber == 0) {
+ if (quirks & CORSAIR_USE_K90_MACRO) {
+ ret = k90_init_macro_functions(dev);
+ if (ret != 0)
+ hid_warn(dev, "Failed to initialize K90 macro functions.\n");
+ }
+ if (quirks & CORSAIR_USE_K90_BACKLIGHT) {
+ ret = k90_init_backlight(dev);
+ if (ret != 0)
+ hid_warn(dev, "Failed to initialize K90 backlight.\n");
+ }
+ }
+
+ return 0;
+}
+
+static void corsair_remove(struct hid_device *dev)
+{
+ k90_cleanup_macro_functions(dev);
+ k90_cleanup_backlight(dev);
+
+ hid_hw_stop(dev);
+}
+
+static int corsair_event(struct hid_device *dev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+
+ if (!drvdata->k90)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case CORSAIR_USAGE_MACRO_RECORD_START:
+ drvdata->k90->record_led.brightness = 1;
+ break;
+ case CORSAIR_USAGE_MACRO_RECORD_STOP:
+ drvdata->k90->record_led.brightness = 0;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int corsair_input_mapping(struct hid_device *dev,
+ struct hid_input *input,
+ struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit,
+ int *max)
+{
+ int gkey;
+
+ gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE);
+ if (gkey != 0) {
+ hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+ corsair_gkey_map[gkey - 1]);
+ return 1;
+ }
+ if ((usage->hid & HID_USAGE) >= CORSAIR_USAGE_SPECIAL_MIN &&
+ (usage->hid & HID_USAGE) <= CORSAIR_USAGE_SPECIAL_MAX) {
+ switch (usage->hid & HID_USAGE) {
+ case CORSAIR_USAGE_MACRO_RECORD_START:
+ hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+ corsair_record_keycodes[0]);
+ return 1;
+
+ case CORSAIR_USAGE_MACRO_RECORD_STOP:
+ hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+ corsair_record_keycodes[1]);
+ return 1;
+
+ case CORSAIR_USAGE_M1:
+ hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+ corsair_profile_keycodes[0]);
+ return 1;
+
+ case CORSAIR_USAGE_M2:
+ hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+ corsair_profile_keycodes[1]);
+ return 1;
+
+ case CORSAIR_USAGE_M3:
+ hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+ corsair_profile_keycodes[2]);
+ return 1;
+
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id corsair_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
+ .driver_data = CORSAIR_USE_K90_MACRO |
+ CORSAIR_USE_K90_BACKLIGHT },
+ {}
+};
+
+MODULE_DEVICE_TABLE(hid, corsair_devices);
+
+static struct hid_driver corsair_driver = {
+ .name = "corsair",
+ .id_table = corsair_devices,
+ .probe = corsair_probe,
+ .event = corsair_event,
+ .remove = corsair_remove,
+ .input_mapping = corsair_input_mapping,
+};
+
+static int __init corsair_init(void)
+{
+ return hid_register_driver(&corsair_driver);
+}
+
+static void corsair_exit(void)
+{
+ hid_unregister_driver(&corsair_driver);
+}
+
+module_init(corsair_init);
+module_exit(corsair_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Clement Vuchener");
+MODULE_DESCRIPTION("HID driver for Corsair devices");
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c
index ce0644424f58..1d78ba3b799e 100644
--- a/drivers/hid/hid-dr.c
+++ b/drivers/hid/hid-dr.c
@@ -234,6 +234,58 @@ static __u8 pid0011_rdesc_fixed[] = {
0xC0 /* End Collection */
};
+static __u8 pid0006_rdesc_fixed[] = {
+ 0x05, 0x01, /* Usage Page (Generic Desktop) */
+ 0x09, 0x04, /* Usage (Joystick) */
+ 0xA1, 0x01, /* Collection (Application) */
+ 0xA1, 0x02, /* Collection (Logical) */
+ 0x75, 0x08, /* Report Size (8) */
+ 0x95, 0x05, /* Report Count (5) */
+ 0x15, 0x00, /* Logical Minimum (0) */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255) */
+ 0x35, 0x00, /* Physical Minimum (0) */
+ 0x46, 0xFF, 0x00, /* Physical Maximum (255) */
+ 0x09, 0x30, /* Usage (X) */
+ 0x09, 0x33, /* Usage (Ry) */
+ 0x09, 0x32, /* Usage (Z) */
+ 0x09, 0x31, /* Usage (Y) */
+ 0x09, 0x34, /* Usage (Ry) */
+ 0x81, 0x02, /* Input (Variable) */
+ 0x75, 0x04, /* Report Size (4) */
+ 0x95, 0x01, /* Report Count (1) */
+ 0x25, 0x07, /* Logical Maximum (7) */
+ 0x46, 0x3B, 0x01, /* Physical Maximum (315) */
+ 0x65, 0x14, /* Unit (Centimeter) */
+ 0x09, 0x39, /* Usage (Hat switch) */
+ 0x81, 0x42, /* Input (Variable) */
+ 0x65, 0x00, /* Unit (None) */
+ 0x75, 0x01, /* Report Size (1) */
+ 0x95, 0x0C, /* Report Count (12) */
+ 0x25, 0x01, /* Logical Maximum (1) */
+ 0x45, 0x01, /* Physical Maximum (1) */
+ 0x05, 0x09, /* Usage Page (Button) */
+ 0x19, 0x01, /* Usage Minimum (0x01) */
+ 0x29, 0x0C, /* Usage Maximum (0x0C) */
+ 0x81, 0x02, /* Input (Variable) */
+ 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */
+ 0x75, 0x01, /* Report Size (1) */
+ 0x95, 0x08, /* Report Count (8) */
+ 0x25, 0x01, /* Logical Maximum (1) */
+ 0x45, 0x01, /* Physical Maximum (1) */
+ 0x09, 0x01, /* Usage (0x01) */
+ 0x81, 0x02, /* Input (Variable) */
+ 0xC0, /* End Collection */
+ 0xA1, 0x02, /* Collection (Logical) */
+ 0x75, 0x08, /* Report Size (8) */
+ 0x95, 0x07, /* Report Count (7) */
+ 0x46, 0xFF, 0x00, /* Physical Maximum (255) */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255) */
+ 0x09, 0x02, /* Usage (0x02) */
+ 0x91, 0x02, /* Output (Variable) */
+ 0xC0, /* End Collection */
+ 0xC0 /* End Collection */
+};
+
static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
@@ -244,6 +296,12 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(pid0011_rdesc_fixed);
}
break;
+ case 0x0006:
+ if (*rsize == sizeof(pid0006_rdesc_fixed)) {
+ rdesc = pid0006_rdesc_fixed;
+ *rsize = sizeof(pid0006_rdesc_fixed);
+ }
+ break;
}
return rdesc;
}
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c
index d0bd13b62dc2..6e3848a8d8dd 100644
--- a/drivers/hid/hid-elecom.c
+++ b/drivers/hid/hid-elecom.c
@@ -27,7 +27,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
rdesc[47] = 0x00;
}
- return rdesc;
+ return rdesc;
}
static const struct hid_device_id elecom_devices[] = {
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
index 4e49462870ab..aad8c162a825 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
@@ -37,7 +37,7 @@ static bool use_fw_quirk = true;
module_param(use_fw_quirk, bool, S_IRUGO);
MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)");
-static void elo_input_configured(struct hid_device *hdev,
+static int elo_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
struct input_dev *input = hidinput->input;
@@ -45,6 +45,8 @@ static void elo_input_configured(struct hid_device *hdev,
set_bit(BTN_TOUCH, input->keybit);
set_bit(ABS_PRESSURE, input->absbit);
input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0);
+
+ return 0;
}
static void elo_process_data(struct input_dev *input, const u8 *data, int size)
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
new file mode 100644
index 000000000000..075b1c020846
--- /dev/null
+++ b/drivers/hid/hid-gfrm.c
@@ -0,0 +1,159 @@
+/*
+ * HID driver for Google Fiber TV Box remote controls
+ *
+ * Copyright (c) 2014-2015 Google Inc.
+ *
+ * Author: Petri Gynther <pgynther@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 <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define GFRM100 1 /* Google Fiber GFRM100 (Bluetooth classic) */
+#define GFRM200 2 /* Google Fiber GFRM200 (Bluetooth LE) */
+
+#define GFRM100_SEARCH_KEY_REPORT_ID 0xF7
+#define GFRM100_SEARCH_KEY_DOWN 0x0
+#define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
+#define GFRM100_SEARCH_KEY_UP 0x2
+
+static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
+static u8 search_key_up[3] = {0x40, 0x00, 0x00};
+
+static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
+
+ if (hdev_type == GFRM100) {
+ if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
+ /* Consumer.0004 -> KEY_INFO */
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_INFO);
+ return 1;
+ }
+
+ if (usage->hid == (HID_UP_CONSUMER | 0x41)) {
+ /* Consumer.0041 -> KEY_OK */
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_OK);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *data, int size)
+{
+ unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
+ int ret = 0;
+
+ if (hdev_type != GFRM100)
+ return 0;
+
+ if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
+ return 0;
+
+ /*
+ * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
+ * reports. Ignore audio data.
+ */
+ switch (data[1]) {
+ case GFRM100_SEARCH_KEY_DOWN:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+ sizeof(search_key_dn), 1);
+ break;
+
+ case GFRM100_SEARCH_KEY_AUDIO_DATA:
+ break;
+
+ case GFRM100_SEARCH_KEY_UP:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+ sizeof(search_key_up), 1);
+ break;
+
+ default:
+ break;
+ }
+
+ return (ret < 0) ? ret : -1;
+}
+
+static int gfrm_input_configured(struct hid_device *hid, struct hid_input *hidinput)
+{
+ /*
+ * Enable software autorepeat with:
+ * - repeat delay: 400 msec
+ * - repeat period: 100 msec
+ */
+ input_enable_softrepeat(hidinput->input, 400, 100);
+ return 0;
+}
+
+static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ hid_set_drvdata(hdev, (void *) id->driver_data);
+
+ ret = hid_parse(hdev);
+ if (ret)
+ goto done;
+
+ if (id->driver_data == GFRM100) {
+ /*
+ * GFRM100 HID Report Descriptor does not describe the Search
+ * key reports. Thus, we need to add it manually here, so that
+ * those reports reach gfrm_raw_event() from hid_input_report().
+ */
+ if (!hid_register_report(hdev, HID_INPUT_REPORT,
+ GFRM100_SEARCH_KEY_REPORT_ID)) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+done:
+ return ret;
+}
+
+static void gfrm_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id gfrm_devices[] = {
+ { HID_BLUETOOTH_DEVICE(0x58, 0x2000),
+ .driver_data = GFRM100 },
+ { HID_BLUETOOTH_DEVICE(0x471, 0x2210),
+ .driver_data = GFRM200 },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, gfrm_devices);
+
+static struct hid_driver gfrm_driver = {
+ .name = "gfrm",
+ .id_table = gfrm_devices,
+ .probe = gfrm_probe,
+ .remove = gfrm_remove,
+ .input_mapping = gfrm_input_mapping,
+ .raw_event = gfrm_raw_event,
+ .input_configured = gfrm_input_configured,
+};
+
+module_hid_driver(gfrm_driver);
+
+MODULE_AUTHOR("Petri Gynther <pgynther@google.com>");
+MODULE_DESCRIPTION("Google Fiber TV Box remote control driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f769208276ae..ac1feea51be3 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -251,6 +251,9 @@
#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff
+#define USB_VENDOR_ID_CORSAIR 0x1b1c
+#define USB_DEVICE_ID_CORSAIR_K90 0x1b02
+
#define USB_VENDOR_ID_CREATIVELABS 0x041e
#define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801
@@ -288,6 +291,7 @@
#define USB_DEVICE_ID_DMI_ENC 0x5fab
#define USB_VENDOR_ID_DRAGONRISE 0x0079
+#define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800
#define USB_VENDOR_ID_DWAV 0x0eef
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
@@ -510,6 +514,7 @@
#define USB_VENDOR_ID_ITE 0x048d
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
+#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
#define USB_VENDOR_ID_JABRA 0x0b0e
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
@@ -646,6 +651,7 @@
#define USB_VENDOR_ID_MADCATZ 0x0738
#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
+#define USB_DEVICE_ID_MADCATZ_RAT5 0x1705
#define USB_DEVICE_ID_MADCATZ_RAT9 0x1709
#define USB_VENDOR_ID_MCC 0x09db
@@ -679,6 +685,7 @@
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc
+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 53aeaf6252c7..2ba6bf69b7d0 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1510,8 +1510,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
- if (drv->input_configured)
- drv->input_configured(hid, hidinput);
+ if (drv->input_configured &&
+ drv->input_configured(hid, hidinput))
+ goto out_cleanup;
if (input_register_device(hidinput->input))
goto out_cleanup;
hidinput = NULL;
@@ -1532,8 +1533,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
if (hidinput) {
- if (drv->input_configured)
- drv->input_configured(hid, hidinput);
+ if (drv->input_configured &&
+ drv->input_configured(hid, hidinput))
+ goto out_cleanup;
if (input_register_device(hidinput->input))
goto out_cleanup;
}
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index e4bc6cb6d7fa..8979f1fd5208 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -848,7 +848,7 @@ static void lenovo_remove(struct hid_device *hdev)
hid_hw_stop(hdev);
}
-static void lenovo_input_configured(struct hid_device *hdev,
+static int lenovo_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
switch (hdev->product) {
@@ -863,6 +863,8 @@ static void lenovo_input_configured(struct hid_device *hdev,
}
break;
}
+
+ return 0;
}
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 5332fb7d072a..c20ac76c0a8c 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
usage->code == ABS_Y || usage->code == ABS_Z ||
usage->code == ABS_RZ)) {
switch (hdev->product) {
+ case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
case USB_DEVICE_ID_LOGITECH_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
@@ -658,10 +659,18 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
+ struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
+ __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
struct lg_drv_data *drv_data;
int ret;
+ /* Only work with the 1st interface (G29 presents multiple) */
+ if (iface_num != 0) {
+ dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
+ return -ENODEV;
+ }
+
drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
if (!drv_data) {
hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 02cec83caac3..fbddcb37ae98 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -45,7 +45,8 @@
#define LG4FF_MODE_G25_IDX 3
#define LG4FF_MODE_DFGT_IDX 4
#define LG4FF_MODE_G27_IDX 5
-#define LG4FF_MODE_MAX_IDX 6
+#define LG4FF_MODE_G29_IDX 6
+#define LG4FF_MODE_MAX_IDX 7
#define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX)
#define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX)
@@ -53,6 +54,7 @@
#define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX)
#define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX)
#define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX)
+#define LG4FF_MODE_G29 BIT(LG4FF_MODE_G29_IDX)
#define LG4FF_DFEX_TAG "DF-EX"
#define LG4FF_DFEX_NAME "Driving Force / Formula EX"
@@ -62,6 +64,8 @@
#define LG4FF_G25_NAME "G25 Racing Wheel"
#define LG4FF_G27_TAG "G27"
#define LG4FF_G27_NAME "G27 Racing Wheel"
+#define LG4FF_G29_TAG "G29"
+#define LG4FF_G29_NAME "G29 Racing Wheel"
#define LG4FF_DFGT_TAG "DFGT"
#define LG4FF_DFGT_NAME "Driving Force GT"
@@ -114,16 +118,12 @@ struct lg4ff_compat_mode_switch {
};
struct lg4ff_wheel_ident_info {
+ const u32 modes;
const u16 mask;
const u16 result;
const u16 real_product_id;
};
-struct lg4ff_wheel_ident_checklist {
- const u32 count;
- const struct lg4ff_wheel_ident_info *models[];
-};
-
struct lg4ff_multimode_wheel {
const u16 product_id;
const u32 alternate_modes;
@@ -144,6 +144,7 @@ static const struct lg4ff_wheel lg4ff_devices[] = {
{USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
+ {USB_DEVICE_ID_LOGITECH_G29_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
{USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}
};
@@ -161,6 +162,9 @@ static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = {
{USB_DEVICE_ID_LOGITECH_G27_WHEEL,
LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
LG4FF_G27_TAG, LG4FF_G27_NAME},
+ {USB_DEVICE_ID_LOGITECH_G29_WHEEL,
+ LG4FF_MODE_NATIVE | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+ LG4FF_G29_TAG, LG4FF_G29_NAME},
};
static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
@@ -169,41 +173,61 @@ static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
[LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME},
[LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME},
[LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
- [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME}
+ [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME},
+ [LG4FF_MODE_G29_IDX] = {USB_DEVICE_ID_LOGITECH_G29_WHEEL, LG4FF_G29_TAG, LG4FF_G29_NAME},
};
/* Multimode wheel identificators */
static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
+ LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xf000,
0x1000,
USB_DEVICE_ID_LOGITECH_DFP_WHEEL
};
static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
+ LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x1200,
USB_DEVICE_ID_LOGITECH_G25_WHEEL
};
static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
+ LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xfff0,
0x1230,
USB_DEVICE_ID_LOGITECH_G27_WHEEL
};
static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
+ LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x1300,
USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
};
+static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info = {
+ LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+ 0xfff8,
+ 0x1350,
+ USB_DEVICE_ID_LOGITECH_G29_WHEEL
+};
+
+static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info2 = {
+ LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+ 0xff00,
+ 0x8900,
+ USB_DEVICE_ID_LOGITECH_G29_WHEEL
+};
+
/* Multimode wheel identification checklists */
-static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = {
- 4,
- {&lg4ff_dfgt_ident_info,
- &lg4ff_g27_ident_info,
- &lg4ff_g25_ident_info,
- &lg4ff_dfp_ident_info}
+static const struct lg4ff_wheel_ident_info *lg4ff_main_checklist[] = {
+ &lg4ff_g29_ident_info,
+ &lg4ff_g29_ident_info2,
+ &lg4ff_dfgt_ident_info,
+ &lg4ff_g27_ident_info,
+ &lg4ff_g25_ident_info,
+ &lg4ff_dfp_ident_info
};
/* Compatibility mode switching commands */
@@ -238,6 +262,12 @@ static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = {
0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G27 with detach */
};
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g29 = {
+ 2,
+ {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */
+ 0xf8, 0x09, 0x05, 0x01, 0x01, 0x00, 0x00} /* Switch mode to G29 with detach */
+};
+
/* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */
static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = {
1,
@@ -651,6 +681,23 @@ static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(cons
return NULL;
}
break;
+ case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+ switch (target_product_id) {
+ case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+ return &lg4ff_mode_switch_ext09_dfp;
+ case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+ return &lg4ff_mode_switch_ext09_dfgt;
+ case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+ return &lg4ff_mode_switch_ext09_g25;
+ case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+ return &lg4ff_mode_switch_ext09_g27;
+ case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
+ return &lg4ff_mode_switch_ext09_g29;
+ /* G29 can only be switched to DF-EX, DFP, DFGT, G25, G27 or its native mode */
+ default:
+ return NULL;
+ }
+ break;
case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
switch (target_product_id) {
case USB_DEVICE_ID_LOGITECH_WHEEL:
@@ -1037,41 +1084,28 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde
static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice)
{
- const struct lg4ff_wheel_ident_checklist *checklist;
- int i, from_idx, to_idx;
+ u32 current_mode;
+ int i;
- switch (reported_product_id) {
- case USB_DEVICE_ID_LOGITECH_WHEEL:
- case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
- checklist = &lg4ff_main_checklist;
- from_idx = 0;
- to_idx = checklist->count - 1;
- break;
- case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
- checklist = &lg4ff_main_checklist;
- from_idx = 0;
- to_idx = checklist->count - 2; /* End identity check at G25 */
- break;
- case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
- checklist = &lg4ff_main_checklist;
- from_idx = 1; /* Start identity check at G27 */
- to_idx = checklist->count - 3; /* End identity check at G27 */
- break;
- case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
- checklist = &lg4ff_main_checklist;
- from_idx = 0;
- to_idx = checklist->count - 4; /* End identity check at DFGT */
- break;
- default:
- return 0;
+ /* identify current mode from USB PID */
+ for (i = 1; i < ARRAY_SIZE(lg4ff_alternate_modes); i++) {
+ dbg_hid("Testing whether PID is %X\n", lg4ff_alternate_modes[i].product_id);
+ if (reported_product_id == lg4ff_alternate_modes[i].product_id)
+ break;
}
- for (i = from_idx; i <= to_idx; i++) {
- const u16 mask = checklist->models[i]->mask;
- const u16 result = checklist->models[i]->result;
- const u16 real_product_id = checklist->models[i]->real_product_id;
+ if (i == ARRAY_SIZE(lg4ff_alternate_modes))
+ return 0;
+
+ current_mode = BIT(i);
+
+ for (i = 0; i < ARRAY_SIZE(lg4ff_main_checklist); i++) {
+ const u16 mask = lg4ff_main_checklist[i]->mask;
+ const u16 result = lg4ff_main_checklist[i]->result;
+ const u16 real_product_id = lg4ff_main_checklist[i]->real_product_id;
- if ((bcdDevice & mask) == result) {
+ if ((current_mode & lg4ff_main_checklist[i]->modes) && \
+ (bcdDevice & mask) == result) {
dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id);
return real_product_id;
}
@@ -1246,12 +1280,13 @@ int lg4ff_init(struct hid_device *hid)
entry->wdata.set_range(hid, entry->wdata.range);
#ifdef CONFIG_LEDS_CLASS
- /* register led subsystem - G27 only */
+ /* register led subsystem - G27/G29 only */
entry->wdata.led_state = 0;
for (j = 0; j < 5; j++)
entry->wdata.led[j] = NULL;
- if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
+ if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL ||
+ lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G29_WHEEL) {
struct led_classdev *led;
size_t name_sz;
char *name;
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 484196459305..5fd97860aec4 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -33,6 +33,11 @@ module_param(disable_raw_mode, bool, 0644);
MODULE_PARM_DESC(disable_raw_mode,
"Disable Raw mode reporting for touchpads and keep firmware gestures.");
+static bool disable_tap_to_click;
+module_param(disable_tap_to_click, bool, 0644);
+MODULE_PARM_DESC(disable_tap_to_click,
+ "Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently).");
+
#define REPORT_ID_HIDPP_SHORT 0x10
#define REPORT_ID_HIDPP_LONG 0x11
@@ -41,10 +46,15 @@ MODULE_PARM_DESC(disable_raw_mode,
#define HIDPP_QUIRK_CLASS_WTP BIT(0)
#define HIDPP_QUIRK_CLASS_M560 BIT(1)
+#define HIDPP_QUIRK_CLASS_K400 BIT(2)
/* bits 2..20 are reserved for classes */
-#define HIDPP_QUIRK_DELAYED_INIT BIT(21)
+#define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
+#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
+
+#define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \
+ HIDPP_QUIRK_CONNECT_EVENTS)
/*
* There are two hidpp protocols in use, the first version hidpp10 is known
@@ -553,6 +563,52 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp)
}
/* -------------------------------------------------------------------------- */
+/* 0x6010: Touchpad FW items */
+/* -------------------------------------------------------------------------- */
+
+#define HIDPP_PAGE_TOUCHPAD_FW_ITEMS 0x6010
+
+#define CMD_TOUCHPAD_FW_ITEMS_SET 0x10
+
+struct hidpp_touchpad_fw_items {
+ uint8_t presence;
+ uint8_t desired_state;
+ uint8_t state;
+ uint8_t persistent;
+};
+
+/**
+ * send a set state command to the device by reading the current items->state
+ * field. items is then filled with the current state.
+ */
+static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp,
+ u8 feature_index,
+ struct hidpp_touchpad_fw_items *items)
+{
+ struct hidpp_report response;
+ int ret;
+ u8 *params = (u8 *)response.fap.params;
+
+ ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+ CMD_TOUCHPAD_FW_ITEMS_SET, &items->state, 1, &response);
+
+ if (ret > 0) {
+ hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+ __func__, ret);
+ return -EPROTO;
+ }
+ if (ret)
+ return ret;
+
+ items->presence = params[0];
+ items->desired_state = params[1];
+ items->state = params[2];
+ items->persistent = params[3];
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
/* 0x6100: TouchPadRawXY */
/* -------------------------------------------------------------------------- */
@@ -1132,6 +1188,75 @@ static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return -1;
}
+/* ------------------------------------------------------------------------- */
+/* Logitech K400 devices */
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The Logitech K400 keyboard has an embedded touchpad which is seen
+ * as a mouse from the OS point of view. There is a hardware shortcut to disable
+ * tap-to-click but the setting is not remembered accross reset, annoying some
+ * users.
+ *
+ * We can toggle this feature from the host by using the feature 0x6010:
+ * Touchpad FW items
+ */
+
+struct k400_private_data {
+ u8 feature_index;
+};
+
+static int k400_disable_tap_to_click(struct hidpp_device *hidpp)
+{
+ struct k400_private_data *k400 = hidpp->private_data;
+ struct hidpp_touchpad_fw_items items = {};
+ int ret;
+ u8 feature_type;
+
+ if (!k400->feature_index) {
+ ret = hidpp_root_get_feature(hidpp,
+ HIDPP_PAGE_TOUCHPAD_FW_ITEMS,
+ &k400->feature_index, &feature_type);
+ if (ret)
+ /* means that the device is not powered up */
+ return ret;
+ }
+
+ ret = hidpp_touchpad_fw_items_set(hidpp, k400->feature_index, &items);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int k400_allocate(struct hid_device *hdev)
+{
+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+ struct k400_private_data *k400;
+
+ k400 = devm_kzalloc(&hdev->dev, sizeof(struct k400_private_data),
+ GFP_KERNEL);
+ if (!k400)
+ return -ENOMEM;
+
+ hidpp->private_data = k400;
+
+ return 0;
+};
+
+static int k400_connect(struct hid_device *hdev, bool connected)
+{
+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+ if (!connected)
+ return 0;
+
+ if (!disable_tap_to_click)
+ return 0;
+
+ return k400_disable_tap_to_click(hidpp);
+}
+
/* -------------------------------------------------------------------------- */
/* Generic HID++ devices */
/* -------------------------------------------------------------------------- */
@@ -1160,13 +1285,15 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
m560_populate_input(hidpp, input, origin_is_hid_core);
}
-static void hidpp_input_configured(struct hid_device *hdev,
+static int hidpp_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
struct input_dev *input = hidinput->input;
hidpp_populate_input(hidpp, input, true);
+
+ return 0;
}
static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
@@ -1203,7 +1330,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
if (unlikely(hidpp_report_is_connect_event(report))) {
atomic_set(&hidpp->connected,
!(report->rap.params[0] & (1 << 6)));
- if ((hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) &&
+ if ((hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) &&
(schedule_work(&hidpp->work) == 0))
dbg_hid("%s: connect event already queued\n", __func__);
return 1;
@@ -1328,23 +1455,30 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
ret = m560_send_config_command(hdev, connected);
if (ret)
return;
+ } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
+ ret = k400_connect(hdev, connected);
+ if (ret)
+ return;
}
if (!connected || hidpp->delayed_input)
return;
+ /* the device is already connected, we can ask for its name and
+ * protocol */
if (!hidpp->protocol_major) {
ret = !hidpp_is_connected(hidpp);
if (ret) {
hid_err(hdev, "Can not get the protocol version.\n");
return;
}
+ hid_info(hdev, "HID++ %u.%u device connected.\n",
+ hidpp->protocol_major, hidpp->protocol_minor);
}
- /* the device is already connected, we can ask for its name and
- * protocol */
- hid_info(hdev, "HID++ %u.%u device connected.\n",
- hidpp->protocol_major, hidpp->protocol_minor);
+ if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT))
+ /* if HID created the input nodes for us, we can stop now */
+ return;
if (!hidpp->name || hidpp->name == hdev->name) {
name = hidpp_get_device_name(hidpp);
@@ -1397,7 +1531,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (disable_raw_mode) {
hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;
- hidpp->quirks &= ~HIDPP_QUIRK_DELAYED_INIT;
+ hidpp->quirks &= ~HIDPP_QUIRK_CONNECT_EVENTS;
+ hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT;
}
if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
@@ -1408,6 +1543,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = m560_allocate(hdev);
if (ret)
goto allocate_fail;
+ } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
+ ret = k400_allocate(hdev);
+ if (ret)
+ goto allocate_fail;
}
INIT_WORK(&hidpp->work, delayed_work_cb);
@@ -1448,7 +1587,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
/* Block incoming packets */
hid_device_io_stop(hdev);
- if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+ if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
connect_mask &= ~HID_CONNECT_HIDINPUT;
ret = hid_hw_start(hdev, connect_mask);
@@ -1457,7 +1596,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto hid_hw_start_fail;
}
- if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) {
+ if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) {
/* Allow incoming packets */
hid_device_io_start(hdev);
@@ -1502,6 +1641,10 @@ static const struct hid_device_id hidpp_devices[] = {
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
USB_VENDOR_ID_LOGITECH, 0x402d),
.driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
+ { /* Keyboard logitech K400 */
+ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
+ USB_VENDOR_ID_LOGITECH, 0x4024),
+ .driver_data = HIDPP_QUIRK_CONNECT_EVENTS | HIDPP_QUIRK_CLASS_K400 },
{ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 29a74c1efcb8..d6fa496d0ca2 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -471,18 +471,22 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
return 0;
}
-static void magicmouse_input_configured(struct hid_device *hdev,
+static int magicmouse_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+ int ret;
- int ret = magicmouse_setup_input(msc->input, hdev);
+ ret = magicmouse_setup_input(msc->input, hdev);
if (ret) {
hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
/* clean msc->input to notify probe() of the failure */
msc->input = NULL;
+ return ret;
}
+
+ return 0;
}
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 9aa3515090a7..77a2cf3e4afe 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -278,6 +278,8 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_DUPLICATE_USAGES },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3),
.driver_data = MS_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2),
+ .driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
.driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 426b2f1a3450..3d664d01305e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -309,6 +309,41 @@ static struct attribute_group mt_attribute_group = {
.attrs = sysfs_attrs
};
+static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
+{
+ struct mt_device *td = hid_get_drvdata(hdev);
+ int ret, size = hid_report_len(report);
+ u8 *buf;
+
+ /*
+ * Only fetch the feature report if initial reports are not already
+ * been retrieved. Currently this is only done for Windows 8 touch
+ * devices.
+ */
+ if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS))
+ return;
+ if (td->mtclass.name != MT_CLS_WIN_8)
+ return;
+
+ buf = hid_alloc_report_buf(report, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ ret = hid_hw_raw_request(hdev, report->id, buf, size,
+ HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+ if (ret < 0) {
+ dev_warn(&hdev->dev, "failed to fetch feature %d\n",
+ report->id);
+ } else {
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
+ size, 0);
+ if (ret)
+ dev_warn(&hdev->dev, "failed to report feature\n");
+ }
+
+ kfree(buf);
+}
+
static void mt_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage)
{
@@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hid_device *hdev,
break;
case HID_DG_CONTACTMAX:
+ mt_get_feature(hdev, field->report);
+
td->maxcontact_report_id = field->report->id;
td->maxcontacts = field->value[0];
if (!td->maxcontacts &&
@@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hid_device *hdev,
break;
}
+ mt_get_feature(hdev, field->report);
if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
td->is_buttonpad = true;
@@ -725,12 +763,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
mt_sync_frame(td, report->field[0]->hidinput->input);
}
-static void mt_touch_input_configured(struct hid_device *hdev,
+static int mt_touch_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
struct input_dev *input = hi->input;
+ int ret;
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
@@ -752,9 +791,12 @@ static void mt_touch_input_configured(struct hid_device *hdev,
if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+ ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+ if (ret)
+ return ret;
td->mt_flags = 0;
+ return 0;
}
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -930,15 +972,19 @@ static void mt_post_parse(struct mt_device *td)
cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
-static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
char *name;
const char *suffix = NULL;
struct hid_field *field = hi->report->field[0];
+ int ret;
- if (hi->report->id == td->mt_report_id)
- mt_touch_input_configured(hdev, hi);
+ if (hi->report->id == td->mt_report_id) {
+ ret = mt_touch_input_configured(hdev, hi);
+ if (ret)
+ return ret;
+ }
/*
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
@@ -968,6 +1014,9 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
case HID_DG_TOUCHSCREEN:
/* we do not set suffix = "Touchscreen" */
break;
+ case HID_DG_TOUCHPAD:
+ suffix = "Touchpad";
+ break;
case HID_GD_SYSTEM_CONTROL:
suffix = "System Control";
break;
@@ -989,6 +1038,8 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
hi->input->name = name;
}
}
+
+ return 0;
}
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -1026,8 +1077,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
* reports. Fortunately, the Win8 spec says that all touches
* should be sent during each report, making the initialization
* of input reports unnecessary.
+ *
+ * In addition some touchpads do not behave well if we read
+ * all feature reports from them. Instead we prevent
+ * initial report fetching and then selectively fetch each
+ * report we are interested in.
*/
- hdev->quirks |= HID_QUIRK_NO_INIT_INPUT_REPORTS;
+ hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
if (!td) {
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 600f2075512f..756d1ef9bd99 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -859,14 +859,14 @@ not_claimed_input:
return 1;
}
-static void ntrig_input_configured(struct hid_device *hid,
+static int ntrig_input_configured(struct hid_device *hid,
struct hid_input *hidinput)
{
struct input_dev *input = hidinput->input;
if (hidinput->report->maxfield < 1)
- return;
+ return 0;
switch (hidinput->report->field[0]->application) {
case HID_DG_PEN:
@@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid,
"N-Trig MultiTouch";
break;
}
+
+ return 0;
}
static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index e3e98ccf137b..3a207c0ac0e3 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -427,7 +427,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data)
pm->midi_octave = 2;
dbg_hid("pcmidi mode: %d octave: %d\n",
pm->midi_mode, pm->midi_octave);
- continue;
+ continue;
} else
key = KEY_MESSENGER;
break;
@@ -695,7 +695,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
if (err < 0) {
pk_error("failed to register pc-midi sound card: error %d\n",
err);
- goto fail_register;
+ goto fail_register;
}
dbg_hid("pcmidi_snd_initialise finished ok\n");
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 2c148129beb2..67cd059a8f46 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -1173,7 +1173,7 @@ static int rmi_populate(struct hid_device *hdev)
return 0;
}
-static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct rmi_data *data = hid_get_drvdata(hdev);
struct input_dev *input = hi->input;
@@ -1185,10 +1185,10 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
hid_dbg(hdev, "Opening low level driver\n");
ret = hid_hw_open(hdev);
if (ret)
- return;
+ return ret;
if (!(data->device_flags & RMI_DEVICE))
- return;
+ return 0;
/* Allow incoming hid reports */
hid_device_io_start(hdev);
@@ -1228,7 +1228,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
- input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+ ret = input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+ if (ret < 0)
+ goto exit;
if (data->button_count) {
__set_bit(EV_KEY, input->evbit);
@@ -1244,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
exit:
hid_device_io_stop(hdev);
hid_hw_close(hdev);
+ return ret;
}
static int rmi_input_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c
index a014f21275d8..2f84b26f1167 100644
--- a/drivers/hid/hid-saitek.c
+++ b/drivers/hid/hid-saitek.c
@@ -177,6 +177,8 @@ static int saitek_event(struct hid_device *hdev, struct hid_field *field,
static const struct hid_device_id saitek_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000),
.driver_data = SAITEK_FIX_PS1000 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5),
+ .driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD),
.driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index a76eb2a0a987..92870cdb52d9 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -593,6 +593,20 @@ static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc,
}
}
+ /* Checks if the report descriptor of Thinkpad Helix 2 has a logical
+ * minimum for magnetic flux axis greater than the maximum */
+ if (hdev->product == USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA &&
+ *rsize == 2558 && rdesc[913] == 0x17 && rdesc[914] == 0x40 &&
+ rdesc[915] == 0x81 && rdesc[916] == 0x08 &&
+ rdesc[917] == 0x00 && rdesc[918] == 0x27 &&
+ rdesc[921] == 0x07 && rdesc[922] == 0x00) {
+ /* Sets negative logical minimum for mag x, y and z */
+ rdesc[914] = rdesc[935] = rdesc[956] = 0xc0;
+ rdesc[915] = rdesc[936] = rdesc[957] = 0x7e;
+ rdesc[916] = rdesc[937] = rdesc[958] = 0xf7;
+ rdesc[917] = rdesc[938] = rdesc[959] = 0xff;
+ }
+
return rdesc;
}
@@ -646,8 +660,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
GFP_KERNEL);
if (sd->hid_sensor_hub_client_devs == NULL) {
hid_err(hdev, "Failed to allocate memory for mfd cells\n");
- ret = -ENOMEM;
- goto err_stop_hw;
+ ret = -ENOMEM;
+ goto err_stop_hw;
}
for (i = 0; i < hdev->maxcollection; ++i) {
@@ -684,8 +698,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
collection->usage);
if (name == NULL) {
hid_err(hdev, "Failed MFD device name\n");
- ret = -ENOMEM;
- goto err_stop_hw;
+ ret = -ENOMEM;
+ goto err_stop_hw;
}
sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].name = name;
@@ -777,6 +791,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
USB_DEVICE_ID_ITE_LENOVO_YOGA),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
+ USB_DEVICE_ID_ITE_LENOVO_YOGA2),
+ .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
HID_ANY_ID) },
{ }
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 661f94f8ab8b..774cd2210566 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1360,20 +1360,27 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count,
return 0;
}
-static void sony_input_configured(struct hid_device *hdev,
+static int sony_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
struct sony_sc *sc = hid_get_drvdata(hdev);
+ int ret;
/*
* The Dualshock 4 touchpad supports 2 touches and has a
* resolution of 1920x942 (44.86 dots/mm).
*/
if (sc->quirks & DUALSHOCK4_CONTROLLER) {
- if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0)
+ ret = sony_register_touchpad(hidinput, 2, 1920, 942);
+ if (ret) {
hid_err(sc->hdev,
- "Unable to initialize multi-touch slots\n");
+ "Unable to initialize multi-touch slots: %d\n",
+ ret);
+ return ret;
+ }
}
+
+ return 0;
}
/*
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index b905d501e752..85ac43517e3f 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -731,7 +731,7 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
-static void uclogic_input_configured(struct hid_device *hdev,
+static int uclogic_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
char *name;
@@ -741,7 +741,7 @@ static void uclogic_input_configured(struct hid_device *hdev,
/* no report associated (HID_QUIRK_MULTI_INPUT not set) */
if (!hi->report)
- return;
+ return 0;
field = hi->report->field[0];
@@ -774,6 +774,8 @@ static void uclogic_input_configured(struct hid_device *hdev,
hi->input->name = name;
}
}
+
+ return 0;
}
/**
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 2871f3c81a4c..10bd8e6e4c9c 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -1028,6 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client,
snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
client->name, hid->vendor, hid->product);
+ strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
ret = hid_add_device(hid);
if (ret) {
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1dff8f0015ba..94bb137abe32 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -71,6 +71,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
@@ -91,6 +92,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 9a4912c1828d..e06af5b9f59e 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -211,7 +211,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
* Bamboo models do not support HID_DG_CONTACTMAX.
* And, Bamboo Pen only descriptor contains touch.
*/
- if (features->type != BAMBOO_PT) {
+ if (features->type > BAMBOO_PT) {
/* ISDv4 touch devices at least supports one touch point */
if (finger && !features->touch_max)
features->touch_max = 1;
@@ -222,7 +222,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
features->x_max = field->logical_maximum;
if (finger) {
features->x_phy = field->physical_maximum;
- if (features->type != BAMBOO_PT) {
+ if ((features->type != BAMBOO_PT) &&
+ (features->type != BAMBOO_TOUCH)) {
features->unit = field->unit;
features->unitExpo = field->unit_exponent;
}
@@ -232,7 +233,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
features->y_max = field->logical_maximum;
if (finger) {
features->y_phy = field->physical_maximum;
- if (features->type != BAMBOO_PT) {
+ if ((features->type != BAMBOO_PT) &&
+ (features->type != BAMBOO_TOUCH)) {
features->unit = field->unit;
features->unitExpo = field->unit_exponent;
}
@@ -420,7 +422,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
/* MT Tablet PC touch */
return wacom_set_device_mode(hdev, 3, 4, 4);
}
- else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
+ else if (features->type == WACOM_24HDT) {
return wacom_set_device_mode(hdev, 18, 3, 2);
}
else if (features->type == WACOM_27QHDT) {
@@ -430,7 +432,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
return wacom_set_device_mode(hdev, 2, 2, 2);
}
} else if (features->device_type & WACOM_DEVICETYPE_PEN) {
- if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
+ if (features->type <= BAMBOO_PT) {
return wacom_set_device_mode(hdev, 2, 2, 2);
}
}
@@ -1547,15 +1549,16 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_wac1->features =
*((struct wacom_features *)id->driver_data);
wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN;
- if (wacom_wac1->features.type != INTUOSHT &&
- wacom_wac1->features.type != BAMBOO_PT)
- wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
wacom_set_default_phy(&wacom_wac1->features);
wacom_calculate_res(&wacom_wac1->features);
snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen",
wacom_wac1->features.name);
- snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
- wacom_wac1->features.name);
+ if (wacom_wac1->features.type < BAMBOO_PEN ||
+ wacom_wac1->features.type > BAMBOO_PT) {
+ snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
+ wacom_wac1->features.name);
+ wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
+ }
wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
wacom_wac1->shared->type = wacom_wac1->features.type;
wacom_wac1->pid = wacom_wac->pid;
@@ -1566,7 +1569,8 @@ static void wacom_wireless_work(struct work_struct *work)
/* Touch interface */
if (wacom_wac1->features.touch_max ||
- wacom_wac1->features.type == INTUOSHT) {
+ (wacom_wac1->features.type >= INTUOSHT &&
+ wacom_wac1->features.type <= BAMBOO_PT)) {
wacom_wac2->features =
*((struct wacom_features *)id->driver_data);
wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
@@ -1575,20 +1579,22 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_calculate_res(&wacom_wac2->features);
snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX,
"%s (WL) Finger",wacom_wac2->features.name);
- snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
- "%s (WL) Pad",wacom_wac2->features.name);
if (wacom_wac1->features.touch_max)
wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH;
- if (wacom_wac1->features.type == INTUOSHT ||
- wacom_wac1->features.type == BAMBOO_PT)
+ if (wacom_wac1->features.type >= INTUOSHT &&
+ wacom_wac1->features.type <= BAMBOO_PT) {
+ snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
+ "%s (WL) Pad",wacom_wac2->features.name);
wacom_wac2->features.device_type |= WACOM_DEVICETYPE_PAD;
+ }
wacom_wac2->pid = wacom_wac->pid;
error = wacom_allocate_inputs(wacom2) ||
wacom_register_inputs(wacom2);
if (error)
goto fail;
- if (wacom_wac1->features.type == INTUOSHT &&
+ if ((wacom_wac1->features.type == INTUOSHT ||
+ wacom_wac1->features.type == INTUOSHT2) &&
wacom_wac1->features.touch_max)
wacom_wac->shared->touch_input = wacom_wac2->touch_input;
}
@@ -1812,11 +1818,27 @@ static int wacom_probe(struct hid_device *hdev,
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(hdev, features);
+ /* touch only Bamboo doesn't support pen */
+ if ((features->type == BAMBOO_TOUCH) &&
+ (features->device_type & WACOM_DEVICETYPE_PEN)) {
+ error = -ENODEV;
+ goto fail_hw_start;
+ }
+
+ /* pen only Bamboo neither support touch nor pad */
+ if ((features->type == BAMBOO_PEN) &&
+ ((features->device_type & WACOM_DEVICETYPE_TOUCH) ||
+ (features->device_type & WACOM_DEVICETYPE_PAD))) {
+ error = -ENODEV;
+ goto fail_hw_start;
+ }
+
if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
error = hid_hw_open(hdev);
- if (wacom_wac->features.type == INTUOSHT &&
- wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
+ if ((wacom_wac->features.type == INTUOSHT ||
+ wacom_wac->features.type == INTUOSHT2) &&
+ (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)) {
wacom_wac->shared->touch_input = wacom_wac->touch_input;
}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 0215ab62bb93..01a4f05c1642 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -765,13 +765,15 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
/* general pen packet */
if ((data[1] & 0xb8) == 0xa0) {
t = (data[6] << 2) | ((data[7] >> 6) & 3);
- if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) {
+ if (features->pressure_max == 2047) {
t = (t << 1) | (data[1] & 1);
}
input_report_abs(input, ABS_PRESSURE, t);
- input_report_abs(input, ABS_TILT_X,
+ if (features->type != INTUOSHT2) {
+ input_report_abs(input, ABS_TILT_X,
(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
- input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
+ input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
+ }
input_report_key(input, BTN_STYLUS, data[1] & 2);
input_report_key(input, BTN_STYLUS2, data[1] & 4);
input_report_key(input, BTN_TOUCH, t > 10);
@@ -799,6 +801,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
data[0] != WACOM_REPORT_INTUOSREAD &&
data[0] != WACOM_REPORT_INTUOSWRITE &&
data[0] != WACOM_REPORT_INTUOSPAD &&
+ data[0] != WACOM_REPORT_INTUOS_PEN &&
data[0] != WACOM_REPORT_CINTIQ &&
data[0] != WACOM_REPORT_CINTIQPAD &&
data[0] != WACOM_REPORT_INTUOS5PAD) {
@@ -948,6 +951,27 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
} else {
input_report_abs(input, ABS_MISC, 0);
}
+
+ } else if (features->type == CINTIQ_COMPANION_2) {
+ input_report_key(input, BTN_1, (data[1] & 0x02));
+ input_report_key(input, BTN_2, (data[2] & 0x01));
+ input_report_key(input, BTN_3, (data[2] & 0x02));
+ input_report_key(input, BTN_4, (data[2] & 0x04));
+ input_report_key(input, BTN_5, (data[2] & 0x08));
+ input_report_key(input, BTN_6, (data[1] & 0x04));
+
+ input_report_key(input, BTN_7, (data[2] & 0x10)); /* Right */
+ input_report_key(input, BTN_8, (data[2] & 0x20)); /* Up */
+ input_report_key(input, BTN_9, (data[2] & 0x40)); /* Left */
+ input_report_key(input, BTN_A, (data[2] & 0x80)); /* Down */
+ input_report_key(input, BTN_0, (data[1] & 0x01)); /* Center */
+
+ if (data[2] | (data[1] & 0x07)) {
+ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+ } else {
+ input_report_abs(input, ABS_MISC, 0);
+ }
+
} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
int i;
@@ -1628,6 +1652,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
break;
case HID_DG_CONTACTCOUNT:
+ wacom_wac->hid_data.cc_report = field->report->id;
wacom_wac->hid_data.cc_index = field->index;
wacom_wac->hid_data.cc_value_index = usage->usage_index;
break;
@@ -1715,7 +1740,32 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct hid_data* hid_data = &wacom_wac->hid_data;
- if (hid_data->cc_index >= 0) {
+ if (hid_data->cc_report != 0 &&
+ hid_data->cc_report != report->id) {
+ int i;
+
+ hid_data->cc_report = report->id;
+ hid_data->cc_index = -1;
+ hid_data->cc_value_index = -1;
+
+ for (i = 0; i < report->maxfield; i++) {
+ struct hid_field *field = report->field[i];
+ int j;
+
+ for (j = 0; j < field->maxusage; j++) {
+ if (field->usage[j].hid == HID_DG_CONTACTCOUNT) {
+ hid_data->cc_index = i;
+ hid_data->cc_value_index = j;
+
+ /* break */
+ i = report->maxfield;
+ j = field->maxusage;
+ }
+ }
+ }
+ }
+ if (hid_data->cc_report != 0 &&
+ hid_data->cc_index >= 0) {
struct hid_field *field = report->field[hid_data->cc_index];
int value = field->value[hid_data->cc_value_index];
if (value)
@@ -1896,7 +1946,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
int y = (data[3] << 4) | (data[4] & 0x0f);
int width, height;
- if (features->type >= INTUOSPS && features->type <= INTUOSHT) {
+ if (features->type >= INTUOSPS && features->type <= INTUOSHT2) {
width = data[5] * 100;
height = data[6] * 100;
} else {
@@ -1924,7 +1974,7 @@ static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
struct input_dev *input = wacom->pad_input;
struct wacom_features *features = &wacom->features;
- if (features->type == INTUOSHT) {
+ if (features->type == INTUOSHT || features->type == INTUOSHT2) {
input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0);
input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
} else {
@@ -1939,7 +1989,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
{
unsigned char *data = wacom->data;
int count = data[1] & 0x07;
- int i;
+ int touch_changed = 0, i;
if (data[0] != 0x02)
return 0;
@@ -1949,15 +1999,16 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
int offset = (8 * i) + 2;
int msg_id = data[offset];
- if (msg_id >= 2 && msg_id <= 17)
+ if (msg_id >= 2 && msg_id <= 17) {
wacom_bpt3_touch_msg(wacom, data + offset);
- else if (msg_id == 128)
+ touch_changed++;
+ } else if (msg_id == 128)
wacom_bpt3_button_msg(wacom, data + offset);
}
- /* only update the touch if we actually have a touchpad */
- if (wacom->touch_registered) {
+ /* only update touch if we actually have a touchpad and touch data changed */
+ if (wacom->touch_registered && touch_changed) {
input_mt_sync_frame(wacom->touch_input);
wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
}
@@ -2038,7 +2089,12 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
{
- if (len == WACOM_PKGLEN_BBTOUCH)
+ struct wacom_features *features = &wacom->features;
+
+ if ((features->type == INTUOSHT2) &&
+ (features->device_type & WACOM_DEVICETYPE_PEN))
+ return wacom_intuos_irq(wacom);
+ else if (len == WACOM_PKGLEN_BBTOUCH)
return wacom_bpt_touch(wacom);
else if (len == WACOM_PKGLEN_BBTOUCH3)
return wacom_bpt3_touch(wacom);
@@ -2145,7 +2201,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
if (connected) {
int pid, battery, charging;
- if ((wacom->shared->type == INTUOSHT) &&
+ if ((wacom->shared->type == INTUOSHT ||
+ wacom->shared->type == INTUOSHT2) &&
wacom->shared->touch_input &&
wacom->shared->touch_max) {
input_report_switch(wacom->shared->touch_input,
@@ -2183,7 +2240,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
if (data[0] != WACOM_REPORT_USB)
return 0;
- if (features->type == INTUOSHT &&
+ if ((features->type == INTUOSHT ||
+ features->type == INTUOSHT2) &&
wacom_wac->shared->touch_input &&
features->touch_max) {
input_report_switch(wacom_wac->shared->touch_input,
@@ -2264,6 +2322,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case WACOM_27QHD:
case DTK:
case CINTIQ_HYBRID:
+ case CINTIQ_COMPANION_2:
sync = wacom_intuos_irq(wacom_wac);
break;
@@ -2300,7 +2359,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
break;
case BAMBOO_PT:
+ case BAMBOO_PEN:
+ case BAMBOO_TOUCH:
case INTUOSHT:
+ case INTUOSHT2:
if (wacom_wac->data[0] == WACOM_REPORT_USB)
sync = wacom_status_irq(wacom_wac, len);
else
@@ -2337,22 +2399,31 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
}
}
-static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
+static void wacom_setup_basic_pro_pen(struct wacom_wac *wacom_wac)
{
struct input_dev *input_dev = wacom_wac->pen_input;
input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
- __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
- __set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
- __set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
- __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
__set_bit(BTN_STYLUS, input_dev->keybit);
__set_bit(BTN_STYLUS2, input_dev->keybit);
input_set_abs_params(input_dev, ABS_DISTANCE,
0, wacom_wac->features.distance_max, 0, 0);
+}
+
+static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
+{
+ struct input_dev *input_dev = wacom_wac->pen_input;
+
+ wacom_setup_basic_pro_pen(wacom_wac);
+
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
+ __set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
+ __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
+
input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0);
input_abs_set_res(input_dev, ABS_TILT_X, 57);
@@ -2387,9 +2458,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)
/* The pen and pad share the same interface on most devices */
if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 ||
- features->type == DTUS || features->type == WACOM_MO ||
- (features->type >= INTUOS3S && features->type <= WACOM_13HD &&
- features->type != INTUOSHT)) {
+ features->type == DTUS ||
+ (features->type >= INTUOS3S && features->type <= WACOM_MO)) {
if (features->device_type & WACOM_DEVICETYPE_PEN)
features->device_type |= WACOM_DEVICETYPE_PAD;
}
@@ -2406,12 +2476,12 @@ void wacom_setup_device_quirks(struct wacom *wacom)
* interface (PacketSize of WACOM_PKGLEN_BBTOUCH3), override the
* tablet values.
*/
- if ((features->type >= INTUOS5S && features->type <= INTUOSHT) ||
- (features->type == BAMBOO_PT)) {
+ if ((features->type >= INTUOS5S && features->type <= INTUOSPL) ||
+ (features->type >= INTUOSHT && features->type <= BAMBOO_PT)) {
if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
if (features->touch_max)
features->device_type |= WACOM_DEVICETYPE_TOUCH;
- if (features->type == BAMBOO_PT || features->type == INTUOSHT)
+ if (features->type >= INTUOSHT && features->type <= BAMBOO_PT)
features->device_type |= WACOM_DEVICETYPE_PAD;
features->x_max = 4096;
@@ -2520,6 +2590,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
case CINTIQ:
case WACOM_13HD:
case CINTIQ_HYBRID:
+ case CINTIQ_COMPANION_2:
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
input_abs_set_res(input_dev, ABS_Z, 287);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -2598,16 +2669,22 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
case INTUOSHT:
case BAMBOO_PT:
- __clear_bit(ABS_MISC, input_dev->absbit);
-
+ case BAMBOO_PEN:
+ case INTUOSHT2:
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
- __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
- __set_bit(BTN_TOOL_PEN, input_dev->keybit);
- __set_bit(BTN_STYLUS, input_dev->keybit);
- __set_bit(BTN_STYLUS2, input_dev->keybit);
- input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+
+ if (features->type == INTUOSHT2) {
+ wacom_setup_basic_pro_pen(wacom_wac);
+ } else {
+ __clear_bit(ABS_MISC, input_dev->absbit);
+ __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+ __set_bit(BTN_STYLUS2, input_dev->keybit);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0,
features->distance_max,
0, 0);
+ }
break;
case BAMBOO_PAD:
__clear_bit(ABS_MISC, input_dev->absbit);
@@ -2688,11 +2765,13 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
break;
case INTUOSHT:
+ case INTUOSHT2:
input_dev->evbit[0] |= BIT_MASK(EV_SW);
__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
/* fall through */
case BAMBOO_PT:
+ case BAMBOO_TOUCH:
if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
input_set_abs_params(input_dev,
ABS_MT_TOUCH_MAJOR,
@@ -2752,6 +2831,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
switch (features->type) {
case CINTIQ_HYBRID:
+ case CINTIQ_COMPANION_2:
case DTK:
case DTUS:
case GRAPHIRE_BT:
@@ -2845,6 +2925,8 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
case INTUOSHT:
case BAMBOO_PT:
+ case BAMBOO_TOUCH:
+ case INTUOSHT2:
__clear_bit(ABS_MISC, input_dev->absbit);
__set_bit(BTN_LEFT, input_dev->keybit);
@@ -3131,7 +3213,8 @@ static const struct wacom_features wacom_features_0x32F =
WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
static const struct wacom_features wacom_features_0x336 =
{ "Wacom DTU1141", 23472, 13203, 1023, 0,
- DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+ DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+ WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
static const struct wacom_features wacom_features_0x57 =
{ "Wacom DTK2241", 95640, 54060, 2047, 63,
DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
@@ -3235,11 +3318,10 @@ static const struct wacom_features wacom_features_0x47 =
{ "Wacom Intuos2 6x8", 20320, 16240, 1023, 31,
INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x84 =
- { "Wacom Wireless Receiver", 0, 0, 0, 0,
- WIRELESS, 0, 0, .touch_max = 16 };
+ { "Wacom Wireless Receiver", .type = WIRELESS, .touch_max = 16 };
static const struct wacom_features wacom_features_0xD0 =
{ "Wacom Bamboo 2FG", 14720, 9200, 1023, 31,
- BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+ BAMBOO_TOUCH, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD1 =
{ "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31,
BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
@@ -3251,10 +3333,10 @@ static const struct wacom_features wacom_features_0xD3 =
BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD4 =
{ "Wacom Bamboo Pen", 14720, 9200, 1023, 31,
- BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD5 =
{ "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31,
- BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD6 =
{ "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31,
BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
@@ -3281,7 +3363,7 @@ static const struct wacom_features wacom_features_0xDF =
BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 };
static const struct wacom_features wacom_features_0x300 =
{ "Wacom Bamboo One S", 14720, 9225, 1023, 31,
- BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x301 =
{ "Wacom Bamboo One M", 21648, 13530, 1023, 31,
BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -3324,14 +3406,38 @@ static const struct wacom_features wacom_features_0x318 =
static const struct wacom_features wacom_features_0x319 =
{ "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
.type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
+static const struct wacom_features wacom_features_0x325 =
+ { "Wacom ISDv5 325", 59552, 33848, 2047, 63,
+ CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11,
+ WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };
+static const struct wacom_features wacom_features_0x326 = /* Touch */
+ { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
+ .oPid = 0x325 };
static const struct wacom_features wacom_features_0x323 =
{ "Wacom Intuos P M", 21600, 13500, 1023, 31,
INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x331 =
- { "Wacom Express Key Remote", 0, 0, 0, 0,
- REMOTE, 0, 0, 18, .check_for_hid_type = true,
+ { "Wacom Express Key Remote", .type = REMOTE,
+ .numbered_buttons = 18, .check_for_hid_type = true,
.hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33B =
+ { "Wacom Intuos S 2", 15200, 9500, 2047, 63,
+ INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33C =
+ { "Wacom Intuos PT S 2", 15200, 9500, 2047, 63,
+ INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33D =
+ { "Wacom Intuos P M 2", 21600, 13500, 2047, 63,
+ INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33E =
+ { "Wacom Intuos PT M 2", 21600, 13500, 2047, 63,
+ INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_HID_ANY_ID =
{ "Wacom HID", .type = HID_GENERIC };
@@ -3483,6 +3589,8 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x318) },
{ USB_DEVICE_WACOM(0x319) },
{ USB_DEVICE_WACOM(0x323) },
+ { USB_DEVICE_WACOM(0x325) },
+ { USB_DEVICE_WACOM(0x326) },
{ USB_DEVICE_WACOM(0x32A) },
{ USB_DEVICE_WACOM(0x32B) },
{ USB_DEVICE_WACOM(0x32C) },
@@ -3491,6 +3599,10 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x333) },
{ USB_DEVICE_WACOM(0x335) },
{ USB_DEVICE_WACOM(0x336) },
+ { USB_DEVICE_WACOM(0x33B) },
+ { USB_DEVICE_WACOM(0x33C) },
+ { USB_DEVICE_WACOM(0x33D) },
+ { USB_DEVICE_WACOM(0x33E) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) },
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 1e270d401e18..877c24a5df94 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -68,6 +68,7 @@
#define WACOM_REPORT_BPAD_PEN 3
#define WACOM_REPORT_BPAD_TOUCH 16
#define WACOM_REPORT_DEVICE_LIST 16
+#define WACOM_REPORT_INTUOS_PEN 16
#define WACOM_REPORT_REMOTE 17
/* device quirks */
@@ -117,22 +118,26 @@ enum {
INTUOSPS,
INTUOSPM,
INTUOSPL,
- INTUOSHT,
WACOM_21UX2,
WACOM_22HD,
DTK,
WACOM_24HD,
WACOM_27QHD,
CINTIQ_HYBRID,
+ CINTIQ_COMPANION_2,
CINTIQ,
WACOM_BEE,
WACOM_13HD,
WACOM_MO,
- WIRELESS,
+ BAMBOO_PEN,
+ INTUOSHT,
+ INTUOSHT2,
+ BAMBOO_TOUCH,
BAMBOO_PT,
WACOM_24HDT,
WACOM_27QHDT,
BAMBOO_PAD,
+ WIRELESS,
REMOTE,
TABLETPC, /* add new TPC below */
TABLETPCE,
@@ -198,6 +203,7 @@ struct hid_data {
int width;
int height;
int id;
+ int cc_report;
int cc_index;
int cc_value_index;
int num_expected;
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index e5c7a969f28b..a38af68cf326 100644
--- a/drivers/hsi/clients/ssi_protocol.c
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -783,7 +783,7 @@ static void ssip_rx_strans(struct hsi_client *cl, u32 cmd)
}
ssip_set_rxstate(ssi, RECEIVING);
if (unlikely(SSIP_MSG_ID(cmd) != ssi->rxid)) {
- dev_err(&cl->device, "START TRANS id %d expeceted %d\n",
+ dev_err(&cl->device, "START TRANS id %d expected %d\n",
SSIP_MSG_ID(cmd), ssi->rxid);
spin_unlock(&ssi->lock);
goto out1;
diff --git a/drivers/hsi/controllers/omap_ssi.c b/drivers/hsi/controllers/omap_ssi.c
index 089c6c3feb3e..f6d3100b7a32 100644
--- a/drivers/hsi/controllers/omap_ssi.c
+++ b/drivers/hsi/controllers/omap_ssi.c
@@ -295,27 +295,14 @@ static int __init ssi_get_iomem(struct platform_device *pd,
const char *name, void __iomem **pbase, dma_addr_t *phy)
{
struct resource *mem;
- struct resource *ioarea;
void __iomem *base;
struct hsi_controller *ssi = platform_get_drvdata(pd);
mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
- if (!mem) {
- dev_err(&pd->dev, "IO memory region missing (%s)\n", name);
- return -ENXIO;
- }
- ioarea = devm_request_mem_region(&ssi->device, mem->start,
- resource_size(mem), dev_name(&pd->dev));
- if (!ioarea) {
- dev_err(&pd->dev, "%s IO memory region request failed\n",
- mem->name);
- return -ENXIO;
- }
- base = devm_ioremap(&ssi->device, mem->start, resource_size(mem));
- if (!base) {
- dev_err(&pd->dev, "%s IO remap failed\n", mem->name);
- return -ENXIO;
- }
+ base = devm_ioremap_resource(&ssi->device, mem);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
*pbase = base;
if (phy)
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index 1f8652b3de06..02e66032ae73 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -1111,7 +1111,7 @@ static int __init ssi_port_probe(struct platform_device *pd)
struct omap_ssi_port *omap_port;
struct hsi_controller *ssi = dev_get_drvdata(pd->dev.parent);
struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
- u32 cawake_gpio = 0;
+ int cawake_gpio = 0;
u32 port_id;
int err;
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
index fe9371271ce2..df380d55c58f 100644
--- a/drivers/hsi/hsi.c
+++ b/drivers/hsi/hsi.c
@@ -85,12 +85,14 @@ struct hsi_client *hsi_new_client(struct hsi_port *port,
cl = kzalloc(sizeof(*cl), GFP_KERNEL);
if (!cl)
- return NULL;
+ goto err;
cl->tx_cfg = info->tx_cfg;
if (cl->tx_cfg.channels) {
size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);
cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL);
+ if (!cl->tx_cfg.channels)
+ goto err_tx;
memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size);
}
@@ -98,6 +100,8 @@ struct hsi_client *hsi_new_client(struct hsi_port *port,
if (cl->rx_cfg.channels) {
size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);
cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL);
+ if (!cl->rx_cfg.channels)
+ goto err_rx;
memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size);
}
@@ -114,6 +118,12 @@ struct hsi_client *hsi_new_client(struct hsi_port *port,
}
return cl;
+err_rx:
+ kfree(cl->tx_cfg.channels);
+err_tx:
+ kfree(cl);
+err:
+ return NULL;
}
EXPORT_SYMBOL_GPL(hsi_new_client);
@@ -300,7 +310,6 @@ static void hsi_add_client_from_dt(struct hsi_port *port,
if (device_register(&cl->device) < 0) {
pr_err("hsi: failed to register client: %s\n", name);
put_device(&cl->device);
- goto err3;
}
return;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 3d70e36c918e..3782636562a1 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -63,9 +63,6 @@ enum hv_cpuid_function {
/* Define version of the synthetic interrupt controller. */
#define HV_SYNIC_VERSION (1)
-/* Define the expected SynIC version. */
-#define HV_SYNIC_VERSION_1 (0x1)
-
/* Define synthetic interrupt controller message constants. */
#define HV_MESSAGE_SIZE (256)
#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240)
@@ -105,8 +102,6 @@ enum hv_message_type {
HVMSG_X64_LEGACY_FP_ERROR = 0x80010005
};
-/* Define the number of synthetic interrupt sources. */
-#define HV_SYNIC_SINT_COUNT (16)
#define HV_SYNIC_STIMER_COUNT (4)
/* Define invalid partition identifier. */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e13c902e8966..8f59f057cdf4 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -321,6 +321,15 @@ config SENSORS_APPLESMC
Say Y here if you have an applicable laptop and want to experience
the awesome power of applesmc.
+config SENSORS_ARM_SCPI
+ tristate "ARM SCPI Sensors"
+ depends on ARM_SCPI_PROTOCOL
+ depends on THERMAL || !THERMAL_OF
+ help
+ This driver provides support for temperature, voltage, current
+ and power sensors available on ARM Ltd's SCP based platforms. The
+ actual number and type of sensors exported depend on the platform.
+
config SENSORS_ASB100
tristate "Asus ASB100 Bach"
depends on X86 && I2C
@@ -840,6 +849,16 @@ config SENSORS_MAX6697
This driver can also be built as a module. If so, the module
will be called max6697.
+config SENSORS_MAX31790
+ tristate "Maxim MAX31790 sensor chip"
+ depends on I2C
+ help
+ If you say yes here you get support for 6-Channel PWM-Output
+ Fan RPM Controller.
+
+ This driver can also be built as a module. If so, the module
+ will be called max31790.
+
config SENSORS_HTU21
tristate "Measurement Specialties HTU21D humidity/temperature sensors"
depends on I2C
@@ -1453,6 +1472,7 @@ config SENSORS_INA209
config SENSORS_INA2XX
tristate "Texas Instruments INA219 and compatibles"
depends on I2C
+ select REGMAP_I2C
help
If you say yes here you get support for INA219, INA220, INA226,
INA230, and INA231 power monitor chips.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 9e0f3dd2841d..12a32398fdcc 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
+obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o
obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
@@ -115,6 +116,7 @@ obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
+obj-$(CONFIG_SENSORS_MAX31790) += max31790.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c
index 1fd46859ed29..d87cae8c635f 100644
--- a/drivers/hwmon/abx500.c
+++ b/drivers/hwmon/abx500.c
@@ -377,7 +377,7 @@ static int setup_irqs(struct platform_device *pdev)
}
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
- abx500_temp_irq_handler, IRQF_NO_SUSPEND, "abx500-temp", pdev);
+ abx500_temp_irq_handler, 0, "abx500-temp", pdev);
if (ret < 0)
dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret);
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index 11955467fc0f..202c1fbb3407 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -157,7 +157,6 @@ MODULE_DEVICE_TABLE(spi, ad7314_id);
static struct spi_driver ad7314_driver = {
.driver = {
.name = "ad7314",
- .owner = THIS_MODULE,
},
.probe = ad7314_probe,
.remove = ad7314_remove,
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index 04c08c2f79b8..69e0bb97e597 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -234,7 +234,6 @@ MODULE_DEVICE_TABLE(spi, adcxx_ids);
static struct spi_driver adcxx_driver = {
.driver = {
.name = "adcxx",
- .owner = THIS_MODULE,
},
.id_table = adcxx_ids,
.probe = adcxx_probe,
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index 3eff73b6220d..4fd9e4de1972 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -237,7 +237,6 @@ static int ads7871_remove(struct spi_device *spi)
static struct spi_driver ads7871_driver = {
.driver = {
.name = DEVICE_NAME,
- .owner = THIS_MODULE,
},
.probe = ads7871_probe,
diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c
index 5994cf68e0a4..ec02f4f0d67a 100644
--- a/drivers/hwmon/adt7310.c
+++ b/drivers/hwmon/adt7310.c
@@ -104,7 +104,6 @@ MODULE_DEVICE_TABLE(spi, adt7310_id);
static struct spi_driver adt7310_driver = {
.driver = {
.name = "adt7310",
- .owner = THIS_MODULE,
.pm = ADT7X10_DEV_PM_OPS,
},
.probe = adt7310_spi_probe,
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 0af63da6b603..0af7fd311979 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -537,7 +537,7 @@ static int applesmc_init_index(struct applesmc_registers *s)
static int applesmc_init_smcreg_try(void)
{
struct applesmc_registers *s = &smcreg;
- bool left_light_sensor, right_light_sensor;
+ bool left_light_sensor = 0, right_light_sensor = 0;
unsigned int count;
u8 tmp[1];
int ret;
@@ -1138,7 +1138,7 @@ out:
return ret;
}
-/* Create accelerometer ressources */
+/* Create accelerometer resources */
static int applesmc_create_accelerometer(void)
{
struct input_dev *idev;
@@ -1191,7 +1191,7 @@ out:
return ret;
}
-/* Release all ressources used by the accelerometer */
+/* Release all resources used by the accelerometer */
static void applesmc_release_accelerometer(void)
{
if (!smcreg.has_accelerometer)
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 3e03379e7c5d..6a27eb2fed17 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -52,7 +52,7 @@ module_param_named(tjmax, force_tjmax, int, 0444);
MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
-#define NUM_REAL_CORES 32 /* Number of Real cores per cpu */
+#define NUM_REAL_CORES 128 /* Number of Real cores per cpu */
#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index e80ee23b62d3..5f7067d7b625 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -26,6 +26,7 @@
#include <linux/pci.h>
#include <linux/bitops.h>
#include <asm/processor.h>
+#include <asm/msr.h>
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
@@ -41,12 +42,21 @@ MODULE_LICENSE("GPL");
#define REG_TDP_RUNNING_AVERAGE 0xe0
#define REG_TDP_LIMIT3 0xe8
+#define FAM15H_MIN_NUM_ATTRS 2
+#define FAM15H_NUM_GROUPS 2
+
+#define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b
+
struct fam15h_power_data {
struct pci_dev *pdev;
unsigned int tdp_to_watts;
unsigned int base_tdp;
unsigned int processor_pwr_watts;
unsigned int cpu_pwr_sample_ratio;
+ const struct attribute_group *groups[FAM15H_NUM_GROUPS];
+ struct attribute_group group;
+ /* maximum accumulated power of a compute unit */
+ u64 max_cu_acc_power;
};
static ssize_t show_power(struct device *dev,
@@ -105,29 +115,36 @@ static ssize_t show_power_crit(struct device *dev,
}
static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL);
-static umode_t fam15h_power_is_visible(struct kobject *kobj,
- struct attribute *attr,
- int index)
+static int fam15h_power_init_attrs(struct pci_dev *pdev,
+ struct fam15h_power_data *data)
{
- /* power1_input is only reported for Fam15h, Models 00h-0fh */
- if (attr == &dev_attr_power1_input.attr &&
- (boot_cpu_data.x86 != 0x15 || boot_cpu_data.x86_model > 0xf))
- return 0;
+ int n = FAM15H_MIN_NUM_ATTRS;
+ struct attribute **fam15h_power_attrs;
+ struct cpuinfo_x86 *c = &boot_cpu_data;
- return attr->mode;
-}
+ if (c->x86 == 0x15 &&
+ (c->x86_model <= 0xf ||
+ (c->x86_model >= 0x60 && c->x86_model <= 0x6f)))
+ n += 1;
-static struct attribute *fam15h_power_attrs[] = {
- &dev_attr_power1_input.attr,
- &dev_attr_power1_crit.attr,
- NULL
-};
+ fam15h_power_attrs = devm_kcalloc(&pdev->dev, n,
+ sizeof(*fam15h_power_attrs),
+ GFP_KERNEL);
-static const struct attribute_group fam15h_power_group = {
- .attrs = fam15h_power_attrs,
- .is_visible = fam15h_power_is_visible,
-};
-__ATTRIBUTE_GROUPS(fam15h_power);
+ if (!fam15h_power_attrs)
+ return -ENOMEM;
+
+ n = 0;
+ fam15h_power_attrs[n++] = &dev_attr_power1_crit.attr;
+ if (c->x86 == 0x15 &&
+ (c->x86_model <= 0xf ||
+ (c->x86_model >= 0x60 && c->x86_model <= 0x6f)))
+ fam15h_power_attrs[n++] = &dev_attr_power1_input.attr;
+
+ data->group.attrs = fam15h_power_attrs;
+
+ return 0;
+}
static bool should_load_on_this_node(struct pci_dev *f4)
{
@@ -186,11 +203,12 @@ static int fam15h_power_resume(struct pci_dev *pdev)
#define fam15h_power_resume NULL
#endif
-static void fam15h_power_init_data(struct pci_dev *f4,
- struct fam15h_power_data *data)
+static int fam15h_power_init_data(struct pci_dev *f4,
+ struct fam15h_power_data *data)
{
u32 val, eax, ebx, ecx, edx;
u64 tmp;
+ int ret;
pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val);
data->base_tdp = val >> 16;
@@ -211,11 +229,15 @@ static void fam15h_power_init_data(struct pci_dev *f4,
/* convert to microWatt */
data->processor_pwr_watts = (tmp * 15625) >> 10;
+ ret = fam15h_power_init_attrs(f4, data);
+ if (ret)
+ return ret;
+
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
/* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */
if (!(edx & BIT(12)))
- return;
+ return 0;
/*
* determine the ratio of the compute unit power accumulator
@@ -223,14 +245,24 @@ static void fam15h_power_init_data(struct pci_dev *f4,
* Fn8000_0007:ECX
*/
data->cpu_pwr_sample_ratio = ecx;
+
+ if (rdmsrl_safe(MSR_F15H_CU_MAX_PWR_ACCUMULATOR, &tmp)) {
+ pr_err("Failed to read max compute unit power accumulator MSR\n");
+ return -ENODEV;
+ }
+
+ data->max_cu_acc_power = tmp;
+
+ return 0;
}
static int fam15h_power_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+ const struct pci_device_id *id)
{
struct fam15h_power_data *data;
struct device *dev = &pdev->dev;
struct device *hwmon_dev;
+ int ret;
/*
* though we ignore every other northbridge, we still have to
@@ -246,12 +278,17 @@ static int fam15h_power_probe(struct pci_dev *pdev,
if (!data)
return -ENOMEM;
- fam15h_power_init_data(pdev, data);
+ ret = fam15h_power_init_data(pdev, data);
+ if (ret)
+ return ret;
+
data->pdev = pdev;
+ data->groups[0] = &data->group;
+
hwmon_dev = devm_hwmon_device_register_with_groups(dev, "fam15h_power",
data,
- fam15h_power_groups);
+ &data->groups[0]);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c
index 4255514b2c72..55b5a8ff1cfe 100644
--- a/drivers/hwmon/ibmpowernv.c
+++ b/drivers/hwmon/ibmpowernv.c
@@ -474,11 +474,18 @@ static const struct platform_device_id opal_sensor_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, opal_sensor_driver_ids);
+static const struct of_device_id opal_sensor_match[] = {
+ { .compatible = "ibm,opal-sensor" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, opal_sensor_match);
+
static struct platform_driver ibmpowernv_driver = {
.probe = ibmpowernv_probe,
.id_table = opal_sensor_driver_ids,
.driver = {
.name = DRVNAME,
+ .of_match_table = opal_sensor_match,
},
};
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 4d2815079fc2..b24f1d3045f0 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -37,6 +37,7 @@
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/util_macros.h>
+#include <linux/regmap.h>
#include <linux/platform_data/ina2xx.h>
@@ -84,6 +85,11 @@
*/
#define INA226_TOTAL_CONV_TIME_DEFAULT 2200
+static struct regmap_config ina2xx_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+};
+
enum ina2xx_ids { ina219, ina226 };
struct ina2xx_config {
@@ -97,20 +103,13 @@ struct ina2xx_config {
};
struct ina2xx_data {
- struct i2c_client *client;
const struct ina2xx_config *config;
long rshunt;
- u16 curr_config;
-
- struct mutex update_lock;
- bool valid;
- unsigned long last_updated;
- int update_interval; /* in jiffies */
+ struct mutex config_lock;
+ struct regmap *regmap;
- int kind;
const struct attribute_group *groups[INA2XX_MAX_ATTRIBUTE_GROUPS];
- u16 regs[INA2XX_MAX_REGISTERS];
};
static const struct ina2xx_config ina2xx_config[] = {
@@ -153,7 +152,11 @@ static int ina226_reg_to_interval(u16 config)
return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000);
}
-static u16 ina226_interval_to_reg(int interval, u16 config)
+/*
+ * Return the new, shifted AVG field value of CONFIG register,
+ * to use with regmap_update_bits
+ */
+static u16 ina226_interval_to_reg(int interval)
{
int avg, avg_bits;
@@ -162,15 +165,7 @@ static u16 ina226_interval_to_reg(int interval, u16 config)
avg_bits = find_closest(avg, ina226_avg_tab,
ARRAY_SIZE(ina226_avg_tab));
- return (config & ~INA226_AVG_RD_MASK) | INA226_SHIFT_AVG(avg_bits);
-}
-
-static void ina226_set_update_interval(struct ina2xx_data *data)
-{
- int ms;
-
- ms = ina226_reg_to_interval(data->curr_config);
- data->update_interval = msecs_to_jiffies(ms);
+ return INA226_SHIFT_AVG(avg_bits);
}
static int ina2xx_calibrate(struct ina2xx_data *data)
@@ -178,8 +173,7 @@ static int ina2xx_calibrate(struct ina2xx_data *data)
u16 val = DIV_ROUND_CLOSEST(data->config->calibration_factor,
data->rshunt);
- return i2c_smbus_write_word_swapped(data->client,
- INA2XX_CALIBRATION, val);
+ return regmap_write(data->regmap, INA2XX_CALIBRATION, val);
}
/*
@@ -187,12 +181,8 @@ static int ina2xx_calibrate(struct ina2xx_data *data)
*/
static int ina2xx_init(struct ina2xx_data *data)
{
- struct i2c_client *client = data->client;
- int ret;
-
- /* device configuration */
- ret = i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
- data->curr_config);
+ int ret = regmap_write(data->regmap, INA2XX_CONFIG,
+ data->config->config_default);
if (ret < 0)
return ret;
@@ -203,47 +193,52 @@ static int ina2xx_init(struct ina2xx_data *data)
return ina2xx_calibrate(data);
}
-static int ina2xx_do_update(struct device *dev)
+static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval)
{
struct ina2xx_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int i, rv, retry;
+ int ret, retry;
- dev_dbg(&client->dev, "Starting ina2xx update\n");
+ dev_dbg(dev, "Starting register %d read\n", reg);
for (retry = 5; retry; retry--) {
- /* Read all registers */
- for (i = 0; i < data->config->registers; i++) {
- rv = i2c_smbus_read_word_swapped(client, i);
- if (rv < 0)
- return rv;
- data->regs[i] = rv;
- }
+
+ ret = regmap_read(data->regmap, reg, regval);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dev, "read %d, val = 0x%04x\n", reg, *regval);
/*
* If the current value in the calibration register is 0, the
* power and current registers will also remain at 0. In case
* the chip has been reset let's check the calibration
* register and reinitialize if needed.
+ * We do that extra read of the calibration register if there
+ * is some hint of a chip reset.
*/
- if (data->regs[INA2XX_CALIBRATION] == 0) {
- dev_warn(dev, "chip not calibrated, reinitializing\n");
-
- rv = ina2xx_init(data);
- if (rv < 0)
- return rv;
-
- /*
- * Let's make sure the power and current registers
- * have been updated before trying again.
- */
- msleep(INA2XX_MAX_DELAY);
- continue;
+ if (*regval == 0) {
+ unsigned int cal;
+
+ ret = regmap_read(data->regmap, INA2XX_CALIBRATION,
+ &cal);
+ if (ret < 0)
+ return ret;
+
+ if (cal == 0) {
+ dev_warn(dev, "chip not calibrated, reinitializing\n");
+
+ ret = ina2xx_init(data);
+ if (ret < 0)
+ return ret;
+ /*
+ * Let's make sure the power and current
+ * registers have been updated before trying
+ * again.
+ */
+ msleep(INA2XX_MAX_DELAY);
+ continue;
+ }
}
-
- data->last_updated = jiffies;
- data->valid = 1;
-
return 0;
}
@@ -256,51 +251,31 @@ static int ina2xx_do_update(struct device *dev)
return -ENODEV;
}
-static struct ina2xx_data *ina2xx_update_device(struct device *dev)
-{
- struct ina2xx_data *data = dev_get_drvdata(dev);
- struct ina2xx_data *ret = data;
- unsigned long after;
- int rv;
-
- mutex_lock(&data->update_lock);
-
- after = data->last_updated + data->update_interval;
- if (time_after(jiffies, after) || !data->valid) {
- rv = ina2xx_do_update(dev);
- if (rv < 0)
- ret = ERR_PTR(rv);
- }
-
- mutex_unlock(&data->update_lock);
- return ret;
-}
-
-static int ina2xx_get_value(struct ina2xx_data *data, u8 reg)
+static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
+ unsigned int regval)
{
int val;
switch (reg) {
case INA2XX_SHUNT_VOLTAGE:
/* signed register */
- val = DIV_ROUND_CLOSEST((s16)data->regs[reg],
- data->config->shunt_div);
+ val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div);
break;
case INA2XX_BUS_VOLTAGE:
- val = (data->regs[reg] >> data->config->bus_voltage_shift)
+ val = (regval >> data->config->bus_voltage_shift)
* data->config->bus_voltage_lsb;
val = DIV_ROUND_CLOSEST(val, 1000);
break;
case INA2XX_POWER:
- val = data->regs[reg] * data->config->power_lsb;
+ val = regval * data->config->power_lsb;
break;
case INA2XX_CURRENT:
/* signed register, LSB=1mA (selected), in mA */
- val = (s16)data->regs[reg];
+ val = (s16)regval;
break;
case INA2XX_CALIBRATION:
val = DIV_ROUND_CLOSEST(data->config->calibration_factor,
- data->regs[reg]);
+ regval);
break;
default:
/* programmer goofed */
@@ -316,25 +291,25 @@ static ssize_t ina2xx_show_value(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ina2xx_data *data = ina2xx_update_device(dev);
+ struct ina2xx_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+
+ int err = ina2xx_read_reg(dev, attr->index, &regval);
- if (IS_ERR(data))
- return PTR_ERR(data);
+ if (err < 0)
+ return err;
return snprintf(buf, PAGE_SIZE, "%d\n",
- ina2xx_get_value(data, attr->index));
+ ina2xx_get_value(data, attr->index, regval));
}
static ssize_t ina2xx_set_shunt(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
- struct ina2xx_data *data = ina2xx_update_device(dev);
unsigned long val;
int status;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
+ struct ina2xx_data *data = dev_get_drvdata(dev);
status = kstrtoul(buf, 10, &val);
if (status < 0)
@@ -345,10 +320,10 @@ static ssize_t ina2xx_set_shunt(struct device *dev,
val > data->config->calibration_factor)
return -EINVAL;
- mutex_lock(&data->update_lock);
+ mutex_lock(&data->config_lock);
data->rshunt = val;
status = ina2xx_calibrate(data);
- mutex_unlock(&data->update_lock);
+ mutex_unlock(&data->config_lock);
if (status < 0)
return status;
@@ -370,17 +345,9 @@ static ssize_t ina226_set_interval(struct device *dev,
if (val > INT_MAX || val == 0)
return -EINVAL;
- mutex_lock(&data->update_lock);
- data->curr_config = ina226_interval_to_reg(val,
- data->regs[INA2XX_CONFIG]);
- status = i2c_smbus_write_word_swapped(data->client,
- INA2XX_CONFIG,
- data->curr_config);
-
- ina226_set_update_interval(data);
- /* Make sure the next access re-reads all registers. */
- data->valid = 0;
- mutex_unlock(&data->update_lock);
+ status = regmap_update_bits(data->regmap, INA2XX_CONFIG,
+ INA226_AVG_RD_MASK,
+ ina226_interval_to_reg(val));
if (status < 0)
return status;
@@ -390,18 +357,15 @@ static ssize_t ina226_set_interval(struct device *dev,
static ssize_t ina226_show_interval(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct ina2xx_data *data = ina2xx_update_device(dev);
+ struct ina2xx_data *data = dev_get_drvdata(dev);
+ int status;
+ unsigned int regval;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ status = regmap_read(data->regmap, INA2XX_CONFIG, &regval);
+ if (status)
+ return status;
- /*
- * We don't use data->update_interval here as we want to display
- * the actual interval used by the chip and jiffies_to_msecs()
- * doesn't seem to be accurate enough.
- */
- return snprintf(buf, PAGE_SIZE, "%d\n",
- ina226_reg_to_interval(data->regs[INA2XX_CONFIG]));
+ return snprintf(buf, PAGE_SIZE, "%d\n", ina226_reg_to_interval(regval));
}
/* shunt voltage */
@@ -455,60 +419,51 @@ static const struct attribute_group ina226_group = {
static int ina2xx_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct i2c_adapter *adapter = client->adapter;
- struct ina2xx_platform_data *pdata;
struct device *dev = &client->dev;
struct ina2xx_data *data;
struct device *hwmon_dev;
u32 val;
int ret, group = 0;
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
- return -ENODEV;
-
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- if (dev_get_platdata(dev)) {
- pdata = dev_get_platdata(dev);
- data->rshunt = pdata->shunt_uohms;
- } else if (!of_property_read_u32(dev->of_node,
- "shunt-resistor", &val)) {
- data->rshunt = val;
- } else {
- data->rshunt = INA2XX_RSHUNT_DEFAULT;
- }
-
/* set the device type */
- data->kind = id->driver_data;
- data->config = &ina2xx_config[data->kind];
- data->curr_config = data->config->config_default;
- data->client = client;
+ data->config = &ina2xx_config[id->driver_data];
- /*
- * Ina226 has a variable update_interval. For ina219 we
- * use a constant value.
- */
- if (data->kind == ina226)
- ina226_set_update_interval(data);
- else
- data->update_interval = HZ / INA2XX_CONVERSION_RATE;
+ if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) {
+ struct ina2xx_platform_data *pdata = dev_get_platdata(dev);
+
+ if (pdata)
+ val = pdata->shunt_uohms;
+ else
+ val = INA2XX_RSHUNT_DEFAULT;
+ }
- if (data->rshunt <= 0 ||
- data->rshunt > data->config->calibration_factor)
+ if (val <= 0 || val > data->config->calibration_factor)
return -ENODEV;
+ data->rshunt = val;
+
+ ina2xx_regmap_config.max_register = data->config->registers;
+
+ data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(dev, "failed to allocate register map\n");
+ return PTR_ERR(data->regmap);
+ }
+
ret = ina2xx_init(data);
if (ret < 0) {
dev_err(dev, "error configuring the device: %d\n", ret);
return -ENODEV;
}
- mutex_init(&data->update_lock);
+ mutex_init(&data->config_lock);
data->groups[group++] = &ina2xx_group;
- if (data->kind == ina226)
+ if (id->driver_data == ina226)
data->groups[group++] = &ina226_group;
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 1e7bdcdcb295..9cdfde6515ad 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -60,7 +60,6 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
* Control]
*/
#define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4
-#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573
static void amd_nb_smu_index_read(struct pci_dev *pdev, unsigned int devfn,
int offset, u32 *val)
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 9296e9daf774..583f883a4cfe 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -199,7 +199,6 @@ MODULE_DEVICE_TABLE(spi, lm70_ids);
static struct spi_driver lm70_driver = {
.driver = {
.name = "lm70",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(lm70_of_ids),
},
.id_table = lm70_ids,
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index e4e57bbafb10..0addc84ba948 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -57,6 +57,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
tmp175,
tmp275,
tmp75,
+ tmp75c,
};
/* Addresses scanned */
@@ -280,6 +281,11 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->resolution = 12;
data->sample_time = HZ / 2;
break;
+ case tmp75c:
+ clr_mask |= 1 << 5; /* not one-shot mode */
+ data->resolution = 12;
+ data->sample_time = HZ / 4;
+ break;
}
/* configure as specified */
@@ -343,6 +349,7 @@ static const struct i2c_device_id lm75_ids[] = {
{ "tmp175", tmp175, },
{ "tmp275", tmp275, },
{ "tmp75", tmp75, },
+ { "tmp75c", tmp75c, },
{ /* LIST END */ }
};
MODULE_DEVICE_TABLE(i2c, lm75_ids);
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index f67d71ee8386..36544c4f653c 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -277,7 +277,6 @@ MODULE_DEVICE_TABLE(spi, max1111_ids);
static struct spi_driver max1111_driver = {
.driver = {
.name = "max1111",
- .owner = THIS_MODULE,
},
.id_table = max1111_ids,
.probe = max1111_probe,
diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c
new file mode 100644
index 000000000000..69c0ac80a946
--- /dev/null
+++ b/drivers/hwmon/max31790.c
@@ -0,0 +1,603 @@
+/*
+ * max31790.c - Part of lm_sensors, Linux kernel modules for hardware
+ * monitoring.
+ *
+ * (C) 2015 by Il Han <corone.il.han@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/* MAX31790 registers */
+#define MAX31790_REG_GLOBAL_CONFIG 0x00
+#define MAX31790_REG_FAN_CONFIG(ch) (0x02 + (ch))
+#define MAX31790_REG_FAN_DYNAMICS(ch) (0x08 + (ch))
+#define MAX31790_REG_FAN_FAULT_STATUS2 0x10
+#define MAX31790_REG_FAN_FAULT_STATUS1 0x11
+#define MAX31790_REG_TACH_COUNT(ch) (0x18 + (ch) * 2)
+#define MAX31790_REG_PWM_DUTY_CYCLE(ch) (0x30 + (ch) * 2)
+#define MAX31790_REG_PWMOUT(ch) (0x40 + (ch) * 2)
+#define MAX31790_REG_TARGET_COUNT(ch) (0x50 + (ch) * 2)
+
+/* Fan Config register bits */
+#define MAX31790_FAN_CFG_RPM_MODE 0x80
+#define MAX31790_FAN_CFG_TACH_INPUT_EN 0x08
+#define MAX31790_FAN_CFG_TACH_INPUT 0x01
+
+/* Fan Dynamics register bits */
+#define MAX31790_FAN_DYN_SR_SHIFT 5
+#define MAX31790_FAN_DYN_SR_MASK 0xE0
+#define SR_FROM_REG(reg) (((reg) & MAX31790_FAN_DYN_SR_MASK) \
+ >> MAX31790_FAN_DYN_SR_SHIFT)
+
+#define FAN_RPM_MIN 120
+#define FAN_RPM_MAX 7864320
+
+#define RPM_FROM_REG(reg, sr) (((reg) >> 4) ? \
+ ((60 * (sr) * 8192) / ((reg) >> 4)) : \
+ FAN_RPM_MAX)
+#define RPM_TO_REG(rpm, sr) ((60 * (sr) * 8192) / ((rpm) * 2))
+
+#define NR_CHANNEL 6
+
+/*
+ * Client data (each client gets its own)
+ */
+struct max31790_data {
+ struct i2c_client *client;
+ struct mutex update_lock;
+ bool valid; /* zero until following fields are valid */
+ unsigned long last_updated; /* in jiffies */
+
+ /* register values */
+ u8 fan_config[NR_CHANNEL];
+ u8 fan_dynamics[NR_CHANNEL];
+ u16 fault_status;
+ u16 tach[NR_CHANNEL * 2];
+ u16 pwm[NR_CHANNEL];
+ u16 target_count[NR_CHANNEL];
+};
+
+static struct max31790_data *max31790_update_device(struct device *dev)
+{
+ struct max31790_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ struct max31790_data *ret = data;
+ int i;
+ int rv;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+ rv = i2c_smbus_read_byte_data(client,
+ MAX31790_REG_FAN_FAULT_STATUS1);
+ if (rv < 0)
+ goto abort;
+ data->fault_status = rv & 0x3F;
+
+ rv = i2c_smbus_read_byte_data(client,
+ MAX31790_REG_FAN_FAULT_STATUS2);
+ if (rv < 0)
+ goto abort;
+ data->fault_status |= (rv & 0x3F) << 6;
+
+ for (i = 0; i < NR_CHANNEL; i++) {
+ rv = i2c_smbus_read_word_swapped(client,
+ MAX31790_REG_TACH_COUNT(i));
+ if (rv < 0)
+ goto abort;
+ data->tach[i] = rv;
+
+ if (data->fan_config[i]
+ & MAX31790_FAN_CFG_TACH_INPUT) {
+ rv = i2c_smbus_read_word_swapped(client,
+ MAX31790_REG_TACH_COUNT(NR_CHANNEL
+ + i));
+ if (rv < 0)
+ goto abort;
+ data->tach[NR_CHANNEL + i] = rv;
+ } else {
+ rv = i2c_smbus_read_word_swapped(client,
+ MAX31790_REG_PWMOUT(i));
+ if (rv < 0)
+ goto abort;
+ data->pwm[i] = rv;
+
+ rv = i2c_smbus_read_word_swapped(client,
+ MAX31790_REG_TARGET_COUNT(i));
+ if (rv < 0)
+ goto abort;
+ data->target_count[i] = rv;
+ }
+ }
+
+ data->last_updated = jiffies;
+ data->valid = true;
+ }
+ goto done;
+
+abort:
+ data->valid = false;
+ ret = ERR_PTR(rv);
+
+done:
+ mutex_unlock(&data->update_lock);
+
+ return ret;
+}
+
+static const u8 tach_period[8] = { 1, 2, 4, 8, 16, 32, 32, 32 };
+
+static u8 get_tach_period(u8 fan_dynamics)
+{
+ return tach_period[SR_FROM_REG(fan_dynamics)];
+}
+
+static u8 bits_for_tach_period(int rpm)
+{
+ u8 bits;
+
+ if (rpm < 500)
+ bits = 0x0;
+ else if (rpm < 1000)
+ bits = 0x1;
+ else if (rpm < 2000)
+ bits = 0x2;
+ else if (rpm < 4000)
+ bits = 0x3;
+ else if (rpm < 8000)
+ bits = 0x4;
+ else
+ bits = 0x5;
+
+ return bits;
+}
+
+static ssize_t get_fan(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = max31790_update_device(dev);
+ int sr, rpm;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ sr = get_tach_period(data->fan_dynamics[attr->index]);
+ rpm = RPM_FROM_REG(data->tach[attr->index], sr);
+
+ return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t get_fan_target(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = max31790_update_device(dev);
+ int sr, rpm;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ sr = get_tach_period(data->fan_dynamics[attr->index]);
+ rpm = RPM_FROM_REG(data->target_count[attr->index], sr);
+
+ return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t set_fan_target(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ u8 bits;
+ int sr;
+ int target_count;
+ unsigned long rpm;
+ int err;
+
+ err = kstrtoul(buf, 10, &rpm);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+
+ rpm = clamp_val(rpm, FAN_RPM_MIN, FAN_RPM_MAX);
+ bits = bits_for_tach_period(rpm);
+ data->fan_dynamics[attr->index] =
+ ((data->fan_dynamics[attr->index]
+ & ~MAX31790_FAN_DYN_SR_MASK)
+ | (bits << MAX31790_FAN_DYN_SR_SHIFT));
+ err = i2c_smbus_write_byte_data(client,
+ MAX31790_REG_FAN_DYNAMICS(attr->index),
+ data->fan_dynamics[attr->index]);
+
+ if (err < 0) {
+ mutex_unlock(&data->update_lock);
+ return err;
+ }
+
+ sr = get_tach_period(data->fan_dynamics[attr->index]);
+ target_count = RPM_TO_REG(rpm, sr);
+ target_count = clamp_val(target_count, 0x1, 0x7FF);
+
+ data->target_count[attr->index] = target_count << 5;
+
+ err = i2c_smbus_write_word_swapped(client,
+ MAX31790_REG_TARGET_COUNT(attr->index),
+ data->target_count[attr->index]);
+
+ mutex_unlock(&data->update_lock);
+
+ if (err < 0)
+ return err;
+
+ return count;
+}
+
+static ssize_t get_pwm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = max31790_update_device(dev);
+ int pwm;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ pwm = data->pwm[attr->index] >> 8;
+
+ return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_pwm(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ unsigned long pwm;
+ int err;
+
+ err = kstrtoul(buf, 10, &pwm);
+ if (err)
+ return err;
+
+ if (pwm > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+
+ data->pwm[attr->index] = pwm << 8;
+ err = i2c_smbus_write_word_swapped(client,
+ MAX31790_REG_PWMOUT(attr->index),
+ data->pwm[attr->index]);
+
+ mutex_unlock(&data->update_lock);
+
+ if (err < 0)
+ return err;
+
+ return count;
+}
+
+static ssize_t get_pwm_enable(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = max31790_update_device(dev);
+ int mode;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ if (data->fan_config[attr->index] & MAX31790_FAN_CFG_RPM_MODE)
+ mode = 2;
+ else if (data->fan_config[attr->index] & MAX31790_FAN_CFG_TACH_INPUT_EN)
+ mode = 1;
+ else
+ mode = 0;
+
+ return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t set_pwm_enable(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ unsigned long mode;
+ int err;
+
+ err = kstrtoul(buf, 10, &mode);
+ if (err)
+ return err;
+
+ switch (mode) {
+ case 0:
+ data->fan_config[attr->index] =
+ data->fan_config[attr->index]
+ & ~(MAX31790_FAN_CFG_TACH_INPUT_EN
+ | MAX31790_FAN_CFG_RPM_MODE);
+ break;
+ case 1:
+ data->fan_config[attr->index] =
+ (data->fan_config[attr->index]
+ | MAX31790_FAN_CFG_TACH_INPUT_EN)
+ & ~MAX31790_FAN_CFG_RPM_MODE;
+ break;
+ case 2:
+ data->fan_config[attr->index] =
+ data->fan_config[attr->index]
+ | MAX31790_FAN_CFG_TACH_INPUT_EN
+ | MAX31790_FAN_CFG_RPM_MODE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->update_lock);
+
+ err = i2c_smbus_write_byte_data(client,
+ MAX31790_REG_FAN_CONFIG(attr->index),
+ data->fan_config[attr->index]);
+
+ mutex_unlock(&data->update_lock);
+
+ if (err < 0)
+ return err;
+
+ return count;
+}
+
+static ssize_t get_fan_fault(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct max31790_data *data = max31790_update_device(dev);
+ int fault;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ fault = !!(data->fault_status & (1 << attr->index));
+
+ return sprintf(buf, "%d\n", fault);
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, get_fan, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, get_fan, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, get_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, get_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, get_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, get_fan_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, get_fan_fault, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, get_fan, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, get_fan, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, get_fan, NULL, 8);
+static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, get_fan, NULL, 9);
+static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, get_fan, NULL, 10);
+static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, get_fan, NULL, 11);
+
+static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, get_fan_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, get_fan_fault, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan9_fault, S_IRUGO, get_fan_fault, NULL, 8);
+static SENSOR_DEVICE_ATTR(fan10_fault, S_IRUGO, get_fan_fault, NULL, 9);
+static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, get_fan_fault, NULL, 10);
+static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, get_fan_fault, NULL, 11);
+
+static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO,
+ get_fan_target, set_fan_target, 0);
+static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO,
+ get_fan_target, set_fan_target, 1);
+static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO,
+ get_fan_target, set_fan_target, 2);
+static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO,
+ get_fan_target, set_fan_target, 3);
+static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO,
+ get_fan_target, set_fan_target, 4);
+static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO,
+ get_fan_target, set_fan_target, 5);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 3);
+static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 4);
+static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 5);
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+ get_pwm_enable, set_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
+ get_pwm_enable, set_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
+ get_pwm_enable, set_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO,
+ get_pwm_enable, set_pwm_enable, 3);
+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO,
+ get_pwm_enable, set_pwm_enable, 4);
+static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO,
+ get_pwm_enable, set_pwm_enable, 5);
+
+static struct attribute *max31790_attrs[] = {
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan5_input.dev_attr.attr,
+ &sensor_dev_attr_fan6_input.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_fault.dev_attr.attr,
+ &sensor_dev_attr_fan2_fault.dev_attr.attr,
+ &sensor_dev_attr_fan3_fault.dev_attr.attr,
+ &sensor_dev_attr_fan4_fault.dev_attr.attr,
+ &sensor_dev_attr_fan5_fault.dev_attr.attr,
+ &sensor_dev_attr_fan6_fault.dev_attr.attr,
+
+ &sensor_dev_attr_fan7_input.dev_attr.attr,
+ &sensor_dev_attr_fan8_input.dev_attr.attr,
+ &sensor_dev_attr_fan9_input.dev_attr.attr,
+ &sensor_dev_attr_fan10_input.dev_attr.attr,
+ &sensor_dev_attr_fan11_input.dev_attr.attr,
+ &sensor_dev_attr_fan12_input.dev_attr.attr,
+
+ &sensor_dev_attr_fan7_fault.dev_attr.attr,
+ &sensor_dev_attr_fan8_fault.dev_attr.attr,
+ &sensor_dev_attr_fan9_fault.dev_attr.attr,
+ &sensor_dev_attr_fan10_fault.dev_attr.attr,
+ &sensor_dev_attr_fan11_fault.dev_attr.attr,
+ &sensor_dev_attr_fan12_fault.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_target.dev_attr.attr,
+ &sensor_dev_attr_fan2_target.dev_attr.attr,
+ &sensor_dev_attr_fan3_target.dev_attr.attr,
+ &sensor_dev_attr_fan4_target.dev_attr.attr,
+ &sensor_dev_attr_fan5_target.dev_attr.attr,
+ &sensor_dev_attr_fan6_target.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm4.dev_attr.attr,
+ &sensor_dev_attr_pwm5.dev_attr.attr,
+ &sensor_dev_attr_pwm6.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm4_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm5_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm6_enable.dev_attr.attr,
+ NULL
+};
+
+static umode_t max31790_attrs_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct max31790_data *data = dev_get_drvdata(dev);
+ struct device_attribute *devattr =
+ container_of(a, struct device_attribute, attr);
+ int index = to_sensor_dev_attr(devattr)->index % NR_CHANNEL;
+ u8 fan_config;
+
+ fan_config = data->fan_config[index];
+
+ if (n >= NR_CHANNEL * 2 && n < NR_CHANNEL * 4 &&
+ !(fan_config & MAX31790_FAN_CFG_TACH_INPUT))
+ return 0;
+ if (n >= NR_CHANNEL * 4 && (fan_config & MAX31790_FAN_CFG_TACH_INPUT))
+ return 0;
+
+ return a->mode;
+}
+
+static const struct attribute_group max31790_group = {
+ .attrs = max31790_attrs,
+ .is_visible = max31790_attrs_visible,
+};
+__ATTRIBUTE_GROUPS(max31790);
+
+static int max31790_init_client(struct i2c_client *client,
+ struct max31790_data *data)
+{
+ int i, rv;
+
+ for (i = 0; i < NR_CHANNEL; i++) {
+ rv = i2c_smbus_read_byte_data(client,
+ MAX31790_REG_FAN_CONFIG(i));
+ if (rv < 0)
+ return rv;
+ data->fan_config[i] = rv;
+
+ rv = i2c_smbus_read_byte_data(client,
+ MAX31790_REG_FAN_DYNAMICS(i));
+ if (rv < 0)
+ return rv;
+ data->fan_dynamics[i] = rv;
+ }
+
+ return 0;
+}
+
+static int max31790_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct device *dev = &client->dev;
+ struct max31790_data *data;
+ struct device *hwmon_dev;
+ int err;
+
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
+
+ data = devm_kzalloc(dev, sizeof(struct max31790_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->client = client;
+ mutex_init(&data->update_lock);
+
+ /*
+ * Initialize the max31790 chip
+ */
+ err = max31790_init_client(client, data);
+ if (err)
+ return err;
+
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+ client->name, data, max31790_groups);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id max31790_id[] = {
+ { "max31790", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max31790_id);
+
+static struct i2c_driver max31790_driver = {
+ .class = I2C_CLASS_HWMON,
+ .probe = max31790_probe,
+ .driver = {
+ .name = "max31790",
+ },
+ .id_table = max31790_id,
+};
+
+module_i2c_driver(max31790_driver);
+
+MODULE_AUTHOR("Il Han <corone.il.han@gmail.com>");
+MODULE_DESCRIPTION("MAX31790 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 8b4fa55e46c6..d7ebdf8651f5 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -515,16 +515,24 @@ static const char *const nct6779_temp_label[] = {
"PCH_DIM1_TEMP",
"PCH_DIM2_TEMP",
"PCH_DIM3_TEMP",
- "BYTE_TEMP"
+ "BYTE_TEMP",
+ "",
+ "",
+ "",
+ "",
+ "Virtual_TEMP"
};
-static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
+#define NCT6779_NUM_LABELS (ARRAY_SIZE(nct6779_temp_label) - 5)
+#define NCT6791_NUM_LABELS ARRAY_SIZE(nct6779_temp_label)
+
+static const u16 NCT6779_REG_TEMP_ALTERNATE[NCT6791_NUM_LABELS - 1]
= { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
0x408, 0 };
-static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
+static const u16 NCT6779_REG_TEMP_CRIT[NCT6791_NUM_LABELS - 1]
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
/* NCT6791 specific data */
@@ -557,6 +565,76 @@ static const u16 NCT6792_REG_TEMP_MON[] = {
static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
+static const char *const nct6792_temp_label[] = {
+ "",
+ "SYSTIN",
+ "CPUTIN",
+ "AUXTIN0",
+ "AUXTIN1",
+ "AUXTIN2",
+ "AUXTIN3",
+ "",
+ "SMBUSMASTER 0",
+ "SMBUSMASTER 1",
+ "SMBUSMASTER 2",
+ "SMBUSMASTER 3",
+ "SMBUSMASTER 4",
+ "SMBUSMASTER 5",
+ "SMBUSMASTER 6",
+ "SMBUSMASTER 7",
+ "PECI Agent 0",
+ "PECI Agent 1",
+ "PCH_CHIP_CPU_MAX_TEMP",
+ "PCH_CHIP_TEMP",
+ "PCH_CPU_TEMP",
+ "PCH_MCH_TEMP",
+ "PCH_DIM0_TEMP",
+ "PCH_DIM1_TEMP",
+ "PCH_DIM2_TEMP",
+ "PCH_DIM3_TEMP",
+ "BYTE_TEMP",
+ "PECI Agent 0 Calibration",
+ "PECI Agent 1 Calibration",
+ "",
+ "",
+ "Virtual_TEMP"
+};
+
+static const char *const nct6793_temp_label[] = {
+ "",
+ "SYSTIN",
+ "CPUTIN",
+ "AUXTIN0",
+ "AUXTIN1",
+ "AUXTIN2",
+ "AUXTIN3",
+ "",
+ "SMBUSMASTER 0",
+ "SMBUSMASTER 1",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "PECI Agent 0",
+ "PECI Agent 1",
+ "PCH_CHIP_CPU_MAX_TEMP",
+ "PCH_CHIP_TEMP",
+ "PCH_CPU_TEMP",
+ "PCH_MCH_TEMP",
+ "Agent0 Dimm0 ",
+ "Agent0 Dimm1",
+ "Agent1 Dimm0",
+ "Agent1 Dimm1",
+ "BYTE_TEMP0",
+ "BYTE_TEMP1",
+ "PECI Agent 0 Calibration",
+ "PECI Agent 1 Calibration",
+ "",
+ "Virtual_TEMP"
+};
+
/* NCT6102D/NCT6106D specific data */
#define NCT6106_REG_VBAT 0x318
@@ -3605,7 +3683,7 @@ static int nct6775_probe(struct platform_device *pdev)
data->speed_tolerance_limit = 63;
data->temp_label = nct6779_temp_label;
- data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
+ data->temp_label_num = NCT6779_NUM_LABELS;
data->REG_CONFIG = NCT6775_REG_CONFIG;
data->REG_VBAT = NCT6775_REG_VBAT;
@@ -3682,8 +3760,19 @@ static int nct6775_probe(struct platform_device *pdev)
data->tolerance_mask = 0x07;
data->speed_tolerance_limit = 63;
- data->temp_label = nct6779_temp_label;
- data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
+ switch (data->kind) {
+ default:
+ case nct6791:
+ data->temp_label = nct6779_temp_label;
+ break;
+ case nct6792:
+ data->temp_label = nct6792_temp_label;
+ break;
+ case nct6793:
+ data->temp_label = nct6793_temp_label;
+ break;
+ }
+ data->temp_label_num = NCT6791_NUM_LABELS;
data->REG_CONFIG = NCT6775_REG_CONFIG;
data->REG_VBAT = NCT6775_REG_VBAT;
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
new file mode 100644
index 000000000000..7e20567bc369
--- /dev/null
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -0,0 +1,289 @@
+/*
+ * System Control and Power Interface(SCPI) based hwmon sensor driver
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Punit Agrawal <punit.agrawal@arm.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 "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/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scpi_protocol.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/thermal.h>
+
+struct sensor_data {
+ struct scpi_sensor_info info;
+ struct device_attribute dev_attr_input;
+ struct device_attribute dev_attr_label;
+ char input[20];
+ char label[20];
+};
+
+struct scpi_thermal_zone {
+ struct list_head list;
+ int sensor_id;
+ struct scpi_sensors *scpi_sensors;
+ struct thermal_zone_device *tzd;
+};
+
+struct scpi_sensors {
+ struct scpi_ops *scpi_ops;
+ struct sensor_data *data;
+ struct list_head thermal_zones;
+ struct attribute **attrs;
+ struct attribute_group group;
+ const struct attribute_group *groups[2];
+};
+
+static int scpi_read_temp(void *dev, int *temp)
+{
+ struct scpi_thermal_zone *zone = dev;
+ struct scpi_sensors *scpi_sensors = zone->scpi_sensors;
+ struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
+ struct sensor_data *sensor = &scpi_sensors->data[zone->sensor_id];
+ u32 value;
+ int ret;
+
+ ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value);
+ if (ret)
+ return ret;
+
+ *temp = value;
+ return 0;
+}
+
+/* hwmon callback functions */
+static ssize_t
+scpi_show_sensor(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scpi_sensors *scpi_sensors = dev_get_drvdata(dev);
+ struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
+ struct sensor_data *sensor;
+ u32 value;
+ int ret;
+
+ sensor = container_of(attr, struct sensor_data, dev_attr_input);
+
+ ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t
+scpi_show_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_data *sensor;
+
+ sensor = container_of(attr, struct sensor_data, dev_attr_label);
+
+ return sprintf(buf, "%s\n", sensor->info.name);
+}
+
+static void
+unregister_thermal_zones(struct platform_device *pdev,
+ struct scpi_sensors *scpi_sensors)
+{
+ struct list_head *pos;
+
+ list_for_each(pos, &scpi_sensors->thermal_zones) {
+ struct scpi_thermal_zone *zone;
+
+ zone = list_entry(pos, struct scpi_thermal_zone, list);
+ thermal_zone_of_sensor_unregister(&pdev->dev, zone->tzd);
+ }
+}
+
+static struct thermal_zone_of_device_ops scpi_sensor_ops = {
+ .get_temp = scpi_read_temp,
+};
+
+static int scpi_hwmon_probe(struct platform_device *pdev)
+{
+ u16 nr_sensors, i;
+ int num_temp = 0, num_volt = 0, num_current = 0, num_power = 0;
+ struct scpi_ops *scpi_ops;
+ struct device *hwdev, *dev = &pdev->dev;
+ struct scpi_sensors *scpi_sensors;
+ int ret, idx;
+
+ scpi_ops = get_scpi_ops();
+ if (!scpi_ops)
+ return -EPROBE_DEFER;
+
+ ret = scpi_ops->sensor_get_capability(&nr_sensors);
+ if (ret)
+ return ret;
+
+ if (!nr_sensors)
+ return -ENODEV;
+
+ scpi_sensors = devm_kzalloc(dev, sizeof(*scpi_sensors), GFP_KERNEL);
+ if (!scpi_sensors)
+ return -ENOMEM;
+
+ scpi_sensors->data = devm_kcalloc(dev, nr_sensors,
+ sizeof(*scpi_sensors->data), GFP_KERNEL);
+ if (!scpi_sensors->data)
+ return -ENOMEM;
+
+ scpi_sensors->attrs = devm_kcalloc(dev, (nr_sensors * 2) + 1,
+ sizeof(*scpi_sensors->attrs), GFP_KERNEL);
+ if (!scpi_sensors->attrs)
+ return -ENOMEM;
+
+ scpi_sensors->scpi_ops = scpi_ops;
+
+ for (i = 0, idx = 0; i < nr_sensors; i++) {
+ struct sensor_data *sensor = &scpi_sensors->data[idx];
+
+ ret = scpi_ops->sensor_get_info(i, &sensor->info);
+ if (ret)
+ return ret;
+
+ switch (sensor->info.class) {
+ case TEMPERATURE:
+ snprintf(sensor->input, sizeof(sensor->input),
+ "temp%d_input", num_temp + 1);
+ snprintf(sensor->label, sizeof(sensor->input),
+ "temp%d_label", num_temp + 1);
+ num_temp++;
+ break;
+ case VOLTAGE:
+ snprintf(sensor->input, sizeof(sensor->input),
+ "in%d_input", num_volt);
+ snprintf(sensor->label, sizeof(sensor->input),
+ "in%d_label", num_volt);
+ num_volt++;
+ break;
+ case CURRENT:
+ snprintf(sensor->input, sizeof(sensor->input),
+ "curr%d_input", num_current + 1);
+ snprintf(sensor->label, sizeof(sensor->input),
+ "curr%d_label", num_current + 1);
+ num_current++;
+ break;
+ case POWER:
+ snprintf(sensor->input, sizeof(sensor->input),
+ "power%d_input", num_power + 1);
+ snprintf(sensor->label, sizeof(sensor->input),
+ "power%d_label", num_power + 1);
+ num_power++;
+ break;
+ default:
+ continue;
+ }
+
+ sensor->dev_attr_input.attr.mode = S_IRUGO;
+ 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.show = scpi_show_label;
+ sensor->dev_attr_label.attr.name = sensor->label;
+
+ scpi_sensors->attrs[idx << 1] = &sensor->dev_attr_input.attr;
+ scpi_sensors->attrs[(idx << 1) + 1] = &sensor->dev_attr_label.attr;
+
+ sysfs_attr_init(scpi_sensors->attrs[idx << 1]);
+ sysfs_attr_init(scpi_sensors->attrs[(idx << 1) + 1]);
+ idx++;
+ }
+
+ scpi_sensors->group.attrs = scpi_sensors->attrs;
+ scpi_sensors->groups[0] = &scpi_sensors->group;
+
+ platform_set_drvdata(pdev, scpi_sensors);
+
+ hwdev = devm_hwmon_device_register_with_groups(dev,
+ "scpi_sensors", scpi_sensors, scpi_sensors->groups);
+
+ if (IS_ERR(hwdev))
+ return PTR_ERR(hwdev);
+
+ /*
+ * Register the temperature sensors with the thermal framework
+ * to allow their usage in setting up the thermal zones from
+ * device tree.
+ *
+ * NOTE: Not all temperature sensors maybe used for thermal
+ * control
+ */
+ INIT_LIST_HEAD(&scpi_sensors->thermal_zones);
+ for (i = 0; i < nr_sensors; i++) {
+ struct sensor_data *sensor = &scpi_sensors->data[i];
+ struct scpi_thermal_zone *zone;
+
+ if (sensor->info.class != TEMPERATURE)
+ continue;
+
+ zone = devm_kzalloc(dev, sizeof(*zone), GFP_KERNEL);
+ if (!zone) {
+ ret = -ENOMEM;
+ goto unregister_tzd;
+ }
+
+ zone->sensor_id = i;
+ zone->scpi_sensors = scpi_sensors;
+ zone->tzd = thermal_zone_of_sensor_register(dev,
+ sensor->info.sensor_id, zone, &scpi_sensor_ops);
+ /*
+ * The call to thermal_zone_of_sensor_register returns
+ * an error for sensors that are not associated with
+ * any thermal zones or if the thermal subsystem is
+ * not configured.
+ */
+ if (IS_ERR(zone->tzd)) {
+ devm_kfree(dev, zone);
+ continue;
+ }
+ list_add(&zone->list, &scpi_sensors->thermal_zones);
+ }
+
+ return 0;
+
+unregister_tzd:
+ unregister_thermal_zones(pdev, scpi_sensors);
+ return ret;
+}
+
+static int scpi_hwmon_remove(struct platform_device *pdev)
+{
+ struct scpi_sensors *scpi_sensors = platform_get_drvdata(pdev);
+
+ unregister_thermal_zones(pdev, scpi_sensors);
+
+ return 0;
+}
+
+static const struct of_device_id scpi_of_match[] = {
+ {.compatible = "arm,scpi-sensors"},
+ {},
+};
+
+static struct platform_driver scpi_hwmon_platdrv = {
+ .driver = {
+ .name = "scpi-hwmon",
+ .owner = THIS_MODULE,
+ .of_match_table = scpi_of_match,
+ },
+ .probe = scpi_hwmon_probe,
+ .remove = scpi_hwmon_remove,
+};
+module_platform_driver(scpi_hwmon_platdrv);
+
+MODULE_AUTHOR("Punit Agrawal <punit.agrawal@arm.com>");
+MODULE_DESCRIPTION("ARM SCPI HWMON interface driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index bf2476ed9356..d630b7ece735 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -191,7 +191,8 @@ static void etm_set_prog(struct etm_drvdata *drvdata)
isb();
if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 1)) {
dev_err(drvdata->dev,
- "timeout observed when probing at offset %#x\n", ETMSR);
+ "%s: timeout observed when probing at offset %#x\n",
+ __func__, ETMSR);
}
}
@@ -209,7 +210,8 @@ static void etm_clr_prog(struct etm_drvdata *drvdata)
isb();
if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 0)) {
dev_err(drvdata->dev,
- "timeout observed when probing at offset %#x\n", ETMSR);
+ "%s: timeout observed when probing at offset %#x\n",
+ __func__, ETMSR);
}
}
@@ -313,14 +315,6 @@ static void etm_enable_hw(void *info)
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
}
-static int etm_trace_id_simple(struct etm_drvdata *drvdata)
-{
- if (!drvdata->enable)
- return drvdata->traceid;
-
- return (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
-}
-
static int etm_trace_id(struct coresight_device *csdev)
{
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -1506,44 +1500,17 @@ static ssize_t timestamp_event_store(struct device *dev,
}
static DEVICE_ATTR_RW(timestamp_event);
-static ssize_t status_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t cpu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- int ret;
- unsigned long flags;
+ int val;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- pm_runtime_get_sync(drvdata->dev);
- spin_lock_irqsave(&drvdata->spinlock, flags);
-
- CS_UNLOCK(drvdata->base);
- ret = sprintf(buf,
- "ETMCCR: 0x%08x\n"
- "ETMCCER: 0x%08x\n"
- "ETMSCR: 0x%08x\n"
- "ETMIDR: 0x%08x\n"
- "ETMCR: 0x%08x\n"
- "ETMTRACEIDR: 0x%08x\n"
- "Enable event: 0x%08x\n"
- "Enable start/stop: 0x%08x\n"
- "Enable control: CR1 0x%08x CR2 0x%08x\n"
- "CPU affinity: %d\n",
- drvdata->etmccr, drvdata->etmccer,
- etm_readl(drvdata, ETMSCR), etm_readl(drvdata, ETMIDR),
- etm_readl(drvdata, ETMCR), etm_trace_id_simple(drvdata),
- etm_readl(drvdata, ETMTEEVR),
- etm_readl(drvdata, ETMTSSCR),
- etm_readl(drvdata, ETMTECR1),
- etm_readl(drvdata, ETMTECR2),
- drvdata->cpu);
- CS_LOCK(drvdata->base);
-
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- pm_runtime_put(drvdata->dev);
+ val = drvdata->cpu;
+ return scnprintf(buf, PAGE_SIZE, "%d\n", val);
- return ret;
}
-static DEVICE_ATTR_RO(status);
+static DEVICE_ATTR_RO(cpu);
static ssize_t traceid_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -1619,11 +1586,61 @@ static struct attribute *coresight_etm_attrs[] = {
&dev_attr_ctxid_mask.attr,
&dev_attr_sync_freq.attr,
&dev_attr_timestamp_event.attr,
- &dev_attr_status.attr,
&dev_attr_traceid.attr,
+ &dev_attr_cpu.attr,
+ NULL,
+};
+
+#define coresight_simple_func(name, offset) \
+static ssize_t name##_show(struct device *_dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct etm_drvdata *drvdata = dev_get_drvdata(_dev->parent); \
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", \
+ readl_relaxed(drvdata->base + offset)); \
+} \
+DEVICE_ATTR_RO(name)
+
+coresight_simple_func(etmccr, ETMCCR);
+coresight_simple_func(etmccer, ETMCCER);
+coresight_simple_func(etmscr, ETMSCR);
+coresight_simple_func(etmidr, ETMIDR);
+coresight_simple_func(etmcr, ETMCR);
+coresight_simple_func(etmtraceidr, ETMTRACEIDR);
+coresight_simple_func(etmteevr, ETMTEEVR);
+coresight_simple_func(etmtssvr, ETMTSSCR);
+coresight_simple_func(etmtecr1, ETMTECR1);
+coresight_simple_func(etmtecr2, ETMTECR2);
+
+static struct attribute *coresight_etm_mgmt_attrs[] = {
+ &dev_attr_etmccr.attr,
+ &dev_attr_etmccer.attr,
+ &dev_attr_etmscr.attr,
+ &dev_attr_etmidr.attr,
+ &dev_attr_etmcr.attr,
+ &dev_attr_etmtraceidr.attr,
+ &dev_attr_etmteevr.attr,
+ &dev_attr_etmtssvr.attr,
+ &dev_attr_etmtecr1.attr,
+ &dev_attr_etmtecr2.attr,
+ NULL,
+};
+
+static const struct attribute_group coresight_etm_group = {
+ .attrs = coresight_etm_attrs,
+};
+
+
+static const struct attribute_group coresight_etm_mgmt_group = {
+ .attrs = coresight_etm_mgmt_attrs,
+ .name = "mgmt",
+};
+
+static const struct attribute_group *coresight_etm_groups[] = {
+ &coresight_etm_group,
+ &coresight_etm_mgmt_group,
NULL,
};
-ATTRIBUTE_GROUPS(coresight_etm);
static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
void *hcpu)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 254a81a4e6f4..a6707642bb23 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -136,7 +136,9 @@ static void etm4_enable_hw(void *info)
writel_relaxed(drvdata->cntr_val[i],
drvdata->base + TRCCNTVRn(i));
}
- for (i = 0; i < drvdata->nr_resource; i++)
+
+ /* Resource selector pair 0 is always implemented and reserved */
+ for (i = 2; i < drvdata->nr_resource * 2; i++)
writel_relaxed(drvdata->res_ctrl[i],
drvdata->base + TRCRSCTLRn(i));
@@ -489,8 +491,9 @@ static ssize_t reset_store(struct device *dev,
drvdata->cntr_val[i] = 0x0;
}
- drvdata->res_idx = 0x0;
- for (i = 0; i < drvdata->nr_resource; i++)
+ /* Resource selector pair 0 is always implemented and reserved */
+ drvdata->res_idx = 0x2;
+ for (i = 2; i < drvdata->nr_resource * 2; i++)
drvdata->res_ctrl[i] = 0x0;
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
@@ -1732,7 +1735,7 @@ static ssize_t res_idx_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
/* Resource selector pair 0 is always implemented and reserved */
- if ((val == 0) || (val >= drvdata->nr_resource))
+ if (val < 2 || val >= drvdata->nr_resource * 2)
return -EINVAL;
/*
@@ -2416,8 +2419,13 @@ static void etm4_init_arch_data(void *info)
drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3);
/* NUMPC, bits[15:12] number of PE comparator inputs for tracing */
drvdata->nr_pe_cmp = BMVAL(etmidr4, 12, 15);
- /* NUMRSPAIR, bits[19:16] the number of resource pairs for tracing */
- drvdata->nr_resource = BMVAL(etmidr4, 16, 19);
+ /*
+ * NUMRSPAIR, bits[19:16]
+ * The number of resource pairs conveyed by the HW starts at 0, i.e a
+ * value of 0x0 indicate 1 resource pair, 0x1 indicate two and so on.
+ * As such add 1 to the value of NUMRSPAIR for a better representation.
+ */
+ drvdata->nr_resource = BMVAL(etmidr4, 16, 19) + 1;
/*
* NUMSSCC, bits[23:20] the number of single-shot
* comparator control for tracing
@@ -2504,6 +2512,8 @@ static void etm4_init_default_data(struct etmv4_drvdata *drvdata)
drvdata->cntr_val[i] = 0x0;
}
+ /* Resource selector pair 0 is always implemented and reserved */
+ drvdata->res_idx = 0x2;
for (i = 2; i < drvdata->nr_resource * 2; i++)
drvdata->res_ctrl[i] = 0x0;
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 894531d315b8..e25492137d8b 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -240,6 +240,11 @@ static int coresight_enable_path(struct list_head *path)
int ret = 0;
struct coresight_device *cd;
+ /*
+ * At this point we have a full @path, from source to sink. The
+ * sink is the first entry and the source the last one. Go through
+ * all the components and enable them one by one.
+ */
list_for_each_entry(cd, path, path_link) {
if (cd == list_first_entry(path, struct coresight_device,
path_link)) {
diff --git a/drivers/hwtracing/intel_th/Kconfig b/drivers/hwtracing/intel_th/Kconfig
new file mode 100644
index 000000000000..b7a9073d968b
--- /dev/null
+++ b/drivers/hwtracing/intel_th/Kconfig
@@ -0,0 +1,72 @@
+config INTEL_TH
+ tristate "Intel(R) Trace Hub controller"
+ help
+ Intel(R) Trace Hub (TH) is a set of hardware blocks (subdevices) that
+ produce, switch and output trace data from multiple hardware and
+ software sources over several types of trace output ports encoded
+ in System Trace Protocol (MIPI STPv2) and is intended to perform
+ full system debugging.
+
+ This option enables intel_th bus and common code used by TH
+ subdevices to interact with each other and hardware and for
+ platform glue layers to drive Intel TH devices.
+
+ Say Y here to enable Intel(R) Trace Hub controller support.
+
+if INTEL_TH
+
+config INTEL_TH_PCI
+ tristate "Intel(R) Trace Hub PCI controller"
+ depends on PCI
+ help
+ Intel(R) Trace Hub may exist as a PCI device. This option enables
+ support glue layer for PCI-based Intel TH.
+
+ Say Y here to enable PCI Intel TH support.
+
+config INTEL_TH_GTH
+ tristate "Intel(R) Trace Hub Global Trace Hub"
+ help
+ Global Trace Hub (GTH) is the central component of the
+ Intel TH infrastructure and acts as a switch for source
+ and output devices. This driver is required for other
+ Intel TH subdevices to initialize.
+
+ Say Y here to enable GTH subdevice of Intel(R) Trace Hub.
+
+config INTEL_TH_STH
+ tristate "Intel(R) Trace Hub Software Trace Hub support"
+ depends on STM
+ help
+ Software Trace Hub (STH) enables trace data from software
+ trace sources to be sent out via Intel(R) Trace Hub. It
+ uses stm class device to interface with its sources.
+
+ Say Y here to enable STH subdevice of Intel(R) Trace Hub.
+
+config INTEL_TH_MSU
+ tristate "Intel(R) Trace Hub Memory Storage Unit"
+ help
+ Memory Storage Unit (MSU) trace output device enables
+ storing STP traces to system memory. It supports single
+ and multiblock modes of operation and provides read()
+ and mmap() access to the collected data.
+
+ Say Y here to enable MSU output device for Intel TH.
+
+config INTEL_TH_PTI
+ tristate "Intel(R) Trace Hub PTI output"
+ help
+ Parallel Trace Interface unit (PTI) is a trace output device
+ of Intel TH architecture that facilitates STP trace output via
+ a PTI port.
+
+ Say Y to enable PTI output of Intel TH data.
+
+config INTEL_TH_DEBUG
+ bool "Intel(R) Trace Hub debugging"
+ depends on DEBUG_FS
+ help
+ Say Y here to enable debugging.
+
+endif
diff --git a/drivers/hwtracing/intel_th/Makefile b/drivers/hwtracing/intel_th/Makefile
new file mode 100644
index 000000000000..81d42fe918f7
--- /dev/null
+++ b/drivers/hwtracing/intel_th/Makefile
@@ -0,0 +1,18 @@
+obj-$(CONFIG_INTEL_TH) += intel_th.o
+intel_th-y := core.o
+intel_th-$(CONFIG_INTEL_TH_DEBUG) += debug.o
+
+obj-$(CONFIG_INTEL_TH_PCI) += intel_th_pci.o
+intel_th_pci-y := pci.o
+
+obj-$(CONFIG_INTEL_TH_GTH) += intel_th_gth.o
+intel_th_gth-y := gth.o
+
+obj-$(CONFIG_INTEL_TH_STH) += intel_th_sth.o
+intel_th_sth-y := sth.o
+
+obj-$(CONFIG_INTEL_TH_MSU) += intel_th_msu.o
+intel_th_msu-y := msu.o
+
+obj-$(CONFIG_INTEL_TH_PTI) += intel_th_pti.o
+intel_th_pti-y := pti.o
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
new file mode 100644
index 000000000000..165d3001c301
--- /dev/null
+++ b/drivers/hwtracing/intel_th/core.c
@@ -0,0 +1,692 @@
+/*
+ * Intel(R) Trace Hub driver core
+ *
+ * Copyright (C) 2014-2015 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) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/kdev_t.h>
+#include <linux/debugfs.h>
+#include <linux/idr.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+
+#include "intel_th.h"
+#include "debug.h"
+
+static DEFINE_IDA(intel_th_ida);
+
+static int intel_th_match(struct device *dev, struct device_driver *driver)
+{
+ struct intel_th_driver *thdrv = to_intel_th_driver(driver);
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+
+ if (thdev->type == INTEL_TH_SWITCH &&
+ (!thdrv->enable || !thdrv->disable))
+ return 0;
+
+ return !strcmp(thdev->name, driver->name);
+}
+
+static int intel_th_child_remove(struct device *dev, void *data)
+{
+ device_release_driver(dev);
+
+ return 0;
+}
+
+static int intel_th_probe(struct device *dev)
+{
+ struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver);
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+ struct intel_th_driver *hubdrv;
+ struct intel_th_device *hub = NULL;
+ int ret;
+
+ if (thdev->type == INTEL_TH_SWITCH)
+ hub = thdev;
+ else if (dev->parent)
+ hub = to_intel_th_device(dev->parent);
+
+ if (!hub || !hub->dev.driver)
+ return -EPROBE_DEFER;
+
+ hubdrv = to_intel_th_driver(hub->dev.driver);
+
+ ret = thdrv->probe(to_intel_th_device(dev));
+ if (ret)
+ return ret;
+
+ if (thdev->type == INTEL_TH_OUTPUT &&
+ !intel_th_output_assigned(thdev))
+ ret = hubdrv->assign(hub, thdev);
+
+ return ret;
+}
+
+static int intel_th_remove(struct device *dev)
+{
+ struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver);
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+ struct intel_th_device *hub = to_intel_th_device(dev->parent);
+ int err;
+
+ if (thdev->type == INTEL_TH_SWITCH) {
+ err = device_for_each_child(dev, thdev, intel_th_child_remove);
+ if (err)
+ return err;
+ }
+
+ thdrv->remove(thdev);
+
+ if (intel_th_output_assigned(thdev)) {
+ struct intel_th_driver *hubdrv =
+ to_intel_th_driver(dev->parent->driver);
+
+ if (hub->dev.driver)
+ hubdrv->unassign(hub, thdev);
+ }
+
+ return 0;
+}
+
+static struct bus_type intel_th_bus = {
+ .name = "intel_th",
+ .dev_attrs = NULL,
+ .match = intel_th_match,
+ .probe = intel_th_probe,
+ .remove = intel_th_remove,
+};
+
+static void intel_th_device_free(struct intel_th_device *thdev);
+
+static void intel_th_device_release(struct device *dev)
+{
+ intel_th_device_free(to_intel_th_device(dev));
+}
+
+static struct device_type intel_th_source_device_type = {
+ .name = "intel_th_source_device",
+ .release = intel_th_device_release,
+};
+
+static char *intel_th_output_devnode(struct device *dev, umode_t *mode,
+ kuid_t *uid, kgid_t *gid)
+{
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+ char *node;
+
+ if (thdev->id >= 0)
+ node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", 0, thdev->name,
+ thdev->id);
+ else
+ node = kasprintf(GFP_KERNEL, "intel_th%d/%s", 0, thdev->name);
+
+ return node;
+}
+
+static ssize_t port_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+
+ if (thdev->output.port >= 0)
+ return scnprintf(buf, PAGE_SIZE, "%u\n", thdev->output.port);
+
+ return scnprintf(buf, PAGE_SIZE, "unassigned\n");
+}
+
+static DEVICE_ATTR_RO(port);
+
+static int intel_th_output_activate(struct intel_th_device *thdev)
+{
+ struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver);
+
+ if (thdrv->activate)
+ return thdrv->activate(thdev);
+
+ intel_th_trace_enable(thdev);
+
+ return 0;
+}
+
+static void intel_th_output_deactivate(struct intel_th_device *thdev)
+{
+ struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver);
+
+ if (thdrv->deactivate)
+ thdrv->deactivate(thdev);
+ else
+ intel_th_trace_disable(thdev);
+}
+
+static ssize_t active_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", thdev->output.active);
+}
+
+static ssize_t active_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct intel_th_device *thdev = to_intel_th_device(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if (!!val != thdev->output.active) {
+ if (val)
+ ret = intel_th_output_activate(thdev);
+ else
+ intel_th_output_deactivate(thdev);
+ }
+
+ return ret ? ret : size;
+}
+
+static DEVICE_ATTR_RW(active);
+
+static struct attribute *intel_th_output_attrs[] = {
+ &dev_attr_port.attr,
+ &dev_attr_active.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(intel_th_output);
+
+static struct device_type intel_th_output_device_type = {
+ .name = "intel_th_output_device",
+ .groups = intel_th_output_groups,
+ .release = intel_th_device_release,
+ .devnode = intel_th_output_devnode,
+};
+
+static struct device_type intel_th_switch_device_type = {
+ .name = "intel_th_switch_device",
+ .release = intel_th_device_release,
+};
+
+static struct device_type *intel_th_device_type[] = {
+ [INTEL_TH_SOURCE] = &intel_th_source_device_type,
+ [INTEL_TH_OUTPUT] = &intel_th_output_device_type,
+ [INTEL_TH_SWITCH] = &intel_th_switch_device_type,
+};
+
+int intel_th_driver_register(struct intel_th_driver *thdrv)
+{
+ if (!thdrv->probe || !thdrv->remove)
+ return -EINVAL;
+
+ thdrv->driver.bus = &intel_th_bus;
+
+ return driver_register(&thdrv->driver);
+}
+EXPORT_SYMBOL_GPL(intel_th_driver_register);
+
+void intel_th_driver_unregister(struct intel_th_driver *thdrv)
+{
+ driver_unregister(&thdrv->driver);
+}
+EXPORT_SYMBOL_GPL(intel_th_driver_unregister);
+
+static struct intel_th_device *
+intel_th_device_alloc(struct intel_th *th, unsigned int type, const char *name,
+ int id)
+{
+ struct device *parent;
+ struct intel_th_device *thdev;
+
+ if (type == INTEL_TH_SWITCH)
+ parent = th->dev;
+ else
+ parent = &th->hub->dev;
+
+ thdev = kzalloc(sizeof(*thdev) + strlen(name) + 1, GFP_KERNEL);
+ if (!thdev)
+ return NULL;
+
+ thdev->id = id;
+ thdev->type = type;
+
+ strcpy(thdev->name, name);
+ device_initialize(&thdev->dev);
+ thdev->dev.bus = &intel_th_bus;
+ thdev->dev.type = intel_th_device_type[type];
+ thdev->dev.parent = parent;
+ thdev->dev.dma_mask = parent->dma_mask;
+ thdev->dev.dma_parms = parent->dma_parms;
+ dma_set_coherent_mask(&thdev->dev, parent->coherent_dma_mask);
+ if (id >= 0)
+ dev_set_name(&thdev->dev, "%d-%s%d", th->id, name, id);
+ else
+ dev_set_name(&thdev->dev, "%d-%s", th->id, name);
+
+ return thdev;
+}
+
+static int intel_th_device_add_resources(struct intel_th_device *thdev,
+ struct resource *res, int nres)
+{
+ struct resource *r;
+
+ r = kmemdup(res, sizeof(*res) * nres, GFP_KERNEL);
+ if (!r)
+ return -ENOMEM;
+
+ thdev->resource = r;
+ thdev->num_resources = nres;
+
+ return 0;
+}
+
+static void intel_th_device_remove(struct intel_th_device *thdev)
+{
+ device_del(&thdev->dev);
+ put_device(&thdev->dev);
+}
+
+static void intel_th_device_free(struct intel_th_device *thdev)
+{
+ kfree(thdev->resource);
+ kfree(thdev);
+}
+
+/*
+ * Intel(R) Trace Hub subdevices
+ */
+static struct intel_th_subdevice {
+ const char *name;
+ struct resource res[3];
+ unsigned nres;
+ unsigned type;
+ unsigned otype;
+ int id;
+} intel_th_subdevices[TH_SUBDEVICE_MAX] = {
+ {
+ .nres = 1,
+ .res = {
+ {
+ .start = REG_GTH_OFFSET,
+ .end = REG_GTH_OFFSET + REG_GTH_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ .name = "gth",
+ .type = INTEL_TH_SWITCH,
+ .id = -1,
+ },
+ {
+ .nres = 2,
+ .res = {
+ {
+ .start = REG_MSU_OFFSET,
+ .end = REG_MSU_OFFSET + REG_MSU_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = BUF_MSU_OFFSET,
+ .end = BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ .name = "msc",
+ .id = 0,
+ .type = INTEL_TH_OUTPUT,
+ .otype = GTH_MSU,
+ },
+ {
+ .nres = 2,
+ .res = {
+ {
+ .start = REG_MSU_OFFSET,
+ .end = REG_MSU_OFFSET + REG_MSU_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = BUF_MSU_OFFSET,
+ .end = BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ .name = "msc",
+ .id = 1,
+ .type = INTEL_TH_OUTPUT,
+ .otype = GTH_MSU,
+ },
+ {
+ .nres = 2,
+ .res = {
+ {
+ .start = REG_STH_OFFSET,
+ .end = REG_STH_OFFSET + REG_STH_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = TH_MMIO_SW,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ .id = -1,
+ .name = "sth",
+ .type = INTEL_TH_SOURCE,
+ },
+ {
+ .nres = 1,
+ .res = {
+ {
+ .start = REG_PTI_OFFSET,
+ .end = REG_PTI_OFFSET + REG_PTI_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ .id = -1,
+ .name = "pti",
+ .type = INTEL_TH_OUTPUT,
+ .otype = GTH_PTI,
+ },
+ {
+ .nres = 1,
+ .res = {
+ {
+ .start = REG_DCIH_OFFSET,
+ .end = REG_DCIH_OFFSET + REG_DCIH_LENGTH - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ .id = -1,
+ .name = "dcih",
+ .type = INTEL_TH_OUTPUT,
+ },
+};
+
+static int intel_th_populate(struct intel_th *th, struct resource *devres,
+ unsigned int ndevres, int irq)
+{
+ struct resource res[3];
+ unsigned int req = 0;
+ int i, err;
+
+ /* create devices for each intel_th_subdevice */
+ for (i = 0; i < ARRAY_SIZE(intel_th_subdevices); i++) {
+ struct intel_th_subdevice *subdev = &intel_th_subdevices[i];
+ struct intel_th_device *thdev;
+ int r;
+
+ thdev = intel_th_device_alloc(th, subdev->type, subdev->name,
+ subdev->id);
+ if (!thdev) {
+ err = -ENOMEM;
+ goto kill_subdevs;
+ }
+
+ memcpy(res, subdev->res,
+ sizeof(struct resource) * subdev->nres);
+
+ for (r = 0; r < subdev->nres; r++) {
+ int bar = TH_MMIO_CONFIG;
+
+ /*
+ * Take .end == 0 to mean 'take the whole bar',
+ * .start then tells us which bar it is. Default to
+ * TH_MMIO_CONFIG.
+ */
+ if (!res[r].end && res[r].flags == IORESOURCE_MEM) {
+ bar = res[r].start;
+ res[r].start = 0;
+ res[r].end = resource_size(&devres[bar]) - 1;
+ }
+
+ if (res[r].flags & IORESOURCE_MEM) {
+ res[r].start += devres[bar].start;
+ res[r].end += devres[bar].start;
+
+ dev_dbg(th->dev, "%s:%d @ %pR\n",
+ subdev->name, r, &res[r]);
+ } else if (res[r].flags & IORESOURCE_IRQ) {
+ res[r].start = irq;
+ }
+ }
+
+ err = intel_th_device_add_resources(thdev, res, subdev->nres);
+ if (err) {
+ put_device(&thdev->dev);
+ goto kill_subdevs;
+ }
+
+ if (subdev->type == INTEL_TH_OUTPUT) {
+ thdev->dev.devt = MKDEV(th->major, i);
+ thdev->output.type = subdev->otype;
+ thdev->output.port = -1;
+ }
+
+ err = device_add(&thdev->dev);
+ if (err) {
+ put_device(&thdev->dev);
+ goto kill_subdevs;
+ }
+
+ /* need switch driver to be loaded to enumerate the rest */
+ if (subdev->type == INTEL_TH_SWITCH && !req) {
+ th->hub = thdev;
+ err = request_module("intel_th_%s", subdev->name);
+ if (!err)
+ req++;
+ }
+
+ th->thdev[i] = thdev;
+ }
+
+ return 0;
+
+kill_subdevs:
+ for (i-- ; i >= 0; i--)
+ intel_th_device_remove(th->thdev[i]);
+
+ return err;
+}
+
+static int match_devt(struct device *dev, void *data)
+{
+ dev_t devt = (dev_t)(unsigned long)data;
+
+ return dev->devt == devt;
+}
+
+static int intel_th_output_open(struct inode *inode, struct file *file)
+{
+ const struct file_operations *fops;
+ struct intel_th_driver *thdrv;
+ struct device *dev;
+ int err;
+
+ dev = bus_find_device(&intel_th_bus, NULL,
+ (void *)(unsigned long)inode->i_rdev,
+ match_devt);
+ if (!dev || !dev->driver)
+ return -ENODEV;
+
+ thdrv = to_intel_th_driver(dev->driver);
+ fops = fops_get(thdrv->fops);
+ if (!fops)
+ return -ENODEV;
+
+ replace_fops(file, fops);
+
+ file->private_data = to_intel_th_device(dev);
+
+ if (file->f_op->open) {
+ err = file->f_op->open(inode, file);
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct file_operations intel_th_output_fops = {
+ .open = intel_th_output_open,
+ .llseek = noop_llseek,
+};
+
+/**
+ * intel_th_alloc() - allocate a new Intel TH device and its subdevices
+ * @dev: parent device
+ * @devres: parent's resources
+ * @ndevres: number of resources
+ * @irq: irq number
+ */
+struct intel_th *
+intel_th_alloc(struct device *dev, struct resource *devres,
+ unsigned int ndevres, int irq)
+{
+ struct intel_th *th;
+ int err;
+
+ th = kzalloc(sizeof(*th), GFP_KERNEL);
+ if (!th)
+ return ERR_PTR(-ENOMEM);
+
+ th->id = ida_simple_get(&intel_th_ida, 0, 0, GFP_KERNEL);
+ if (th->id < 0) {
+ err = th->id;
+ goto err_alloc;
+ }
+
+ th->major = __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS,
+ "intel_th/output", &intel_th_output_fops);
+ if (th->major < 0) {
+ err = th->major;
+ goto err_ida;
+ }
+ th->dev = dev;
+
+ err = intel_th_populate(th, devres, ndevres, irq);
+ if (err)
+ goto err_chrdev;
+
+ return th;
+
+err_chrdev:
+ __unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS,
+ "intel_th/output");
+
+err_ida:
+ ida_simple_remove(&intel_th_ida, th->id);
+
+err_alloc:
+ kfree(th);
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(intel_th_alloc);
+
+void intel_th_free(struct intel_th *th)
+{
+ int i;
+
+ for (i = 0; i < TH_SUBDEVICE_MAX; i++)
+ if (th->thdev[i] != th->hub)
+ intel_th_device_remove(th->thdev[i]);
+
+ intel_th_device_remove(th->hub);
+
+ __unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS,
+ "intel_th/output");
+
+ ida_simple_remove(&intel_th_ida, th->id);
+
+ kfree(th);
+}
+EXPORT_SYMBOL_GPL(intel_th_free);
+
+/**
+ * intel_th_trace_enable() - enable tracing for an output device
+ * @thdev: output device that requests tracing be enabled
+ */
+int intel_th_trace_enable(struct intel_th_device *thdev)
+{
+ struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
+ struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+
+ if (WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH))
+ return -EINVAL;
+
+ if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT))
+ return -EINVAL;
+
+ hubdrv->enable(hub, &thdev->output);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(intel_th_trace_enable);
+
+/**
+ * intel_th_trace_disable() - disable tracing for an output device
+ * @thdev: output device that requests tracing be disabled
+ */
+int intel_th_trace_disable(struct intel_th_device *thdev)
+{
+ struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
+ struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+
+ WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH);
+ if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT))
+ return -EINVAL;
+
+ hubdrv->disable(hub, &thdev->output);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(intel_th_trace_disable);
+
+int intel_th_set_output(struct intel_th_device *thdev,
+ unsigned int master)
+{
+ struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
+ struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+
+ if (!hubdrv->set_output)
+ return -ENOTSUPP;
+
+ return hubdrv->set_output(hub, master);
+}
+EXPORT_SYMBOL_GPL(intel_th_set_output);
+
+static int __init intel_th_init(void)
+{
+ intel_th_debug_init();
+
+ return bus_register(&intel_th_bus);
+}
+subsys_initcall(intel_th_init);
+
+static void __exit intel_th_exit(void)
+{
+ intel_th_debug_done();
+
+ bus_unregister(&intel_th_bus);
+}
+module_exit(intel_th_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/intel_th/debug.c b/drivers/hwtracing/intel_th/debug.c
new file mode 100644
index 000000000000..788a1f0a97ad
--- /dev/null
+++ b/drivers/hwtracing/intel_th/debug.c
@@ -0,0 +1,36 @@
+/*
+ * Intel(R) Trace Hub driver debugging
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/debugfs.h>
+
+#include "intel_th.h"
+#include "debug.h"
+
+struct dentry *intel_th_dbg;
+
+void intel_th_debug_init(void)
+{
+ intel_th_dbg = debugfs_create_dir("intel_th", NULL);
+ if (IS_ERR(intel_th_dbg))
+ intel_th_dbg = NULL;
+}
+
+void intel_th_debug_done(void)
+{
+ debugfs_remove(intel_th_dbg);
+ intel_th_dbg = NULL;
+}
diff --git a/drivers/hwtracing/intel_th/debug.h b/drivers/hwtracing/intel_th/debug.h
new file mode 100644
index 000000000000..88311bad3ba4
--- /dev/null
+++ b/drivers/hwtracing/intel_th/debug.h
@@ -0,0 +1,34 @@
+/*
+ * Intel(R) Trace Hub driver debugging
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#ifndef __INTEL_TH_DEBUG_H__
+#define __INTEL_TH_DEBUG_H__
+
+#ifdef CONFIG_INTEL_TH_DEBUG
+extern struct dentry *intel_th_dbg;
+
+void intel_th_debug_init(void);
+void intel_th_debug_done(void);
+#else
+static inline void intel_th_debug_init(void)
+{
+}
+
+static inline void intel_th_debug_done(void)
+{
+}
+#endif
+
+#endif /* __INTEL_TH_DEBUG_H__ */
diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c
new file mode 100644
index 000000000000..2dc5378ccd3a
--- /dev/null
+++ b/drivers/hwtracing/intel_th/gth.c
@@ -0,0 +1,706 @@
+/*
+ * Intel(R) Trace Hub Global Trace Hub
+ *
+ * Copyright (C) 2014-2015 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) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/bitmap.h>
+
+#include "intel_th.h"
+#include "gth.h"
+
+struct gth_device;
+
+/**
+ * struct gth_output - GTH view on an output port
+ * @gth: backlink to the GTH device
+ * @output: link to output device's output descriptor
+ * @index: output port number
+ * @port_type: one of GTH_* port type values
+ * @master: bitmap of masters configured for this output
+ */
+struct gth_output {
+ struct gth_device *gth;
+ struct intel_th_output *output;
+ unsigned int index;
+ unsigned int port_type;
+ DECLARE_BITMAP(master, TH_CONFIGURABLE_MASTERS + 1);
+};
+
+/**
+ * struct gth_device - GTH device
+ * @dev: driver core's device
+ * @base: register window base address
+ * @output_group: attributes describing output ports
+ * @master_group: attributes describing master assignments
+ * @output: output ports
+ * @master: master/output port assignments
+ * @gth_lock: serializes accesses to GTH bits
+ */
+struct gth_device {
+ struct device *dev;
+ void __iomem *base;
+
+ struct attribute_group output_group;
+ struct attribute_group master_group;
+ struct gth_output output[TH_POSSIBLE_OUTPUTS];
+ signed char master[TH_CONFIGURABLE_MASTERS + 1];
+ spinlock_t gth_lock;
+};
+
+static void gth_output_set(struct gth_device *gth, int port,
+ unsigned int config)
+{
+ unsigned long reg = port & 4 ? REG_GTH_GTHOPT1 : REG_GTH_GTHOPT0;
+ u32 val;
+ int shift = (port & 3) * 8;
+
+ val = ioread32(gth->base + reg);
+ val &= ~(0xff << shift);
+ val |= config << shift;
+ iowrite32(val, gth->base + reg);
+}
+
+static unsigned int gth_output_get(struct gth_device *gth, int port)
+{
+ unsigned long reg = port & 4 ? REG_GTH_GTHOPT1 : REG_GTH_GTHOPT0;
+ u32 val;
+ int shift = (port & 3) * 8;
+
+ val = ioread32(gth->base + reg);
+ val &= 0xff << shift;
+ val >>= shift;
+
+ return val;
+}
+
+static void gth_smcfreq_set(struct gth_device *gth, int port,
+ unsigned int freq)
+{
+ unsigned long reg = REG_GTH_SMCR0 + ((port / 2) * 4);
+ int shift = (port & 1) * 16;
+ u32 val;
+
+ val = ioread32(gth->base + reg);
+ val &= ~(0xffff << shift);
+ val |= freq << shift;
+ iowrite32(val, gth->base + reg);
+}
+
+static unsigned int gth_smcfreq_get(struct gth_device *gth, int port)
+{
+ unsigned long reg = REG_GTH_SMCR0 + ((port / 2) * 4);
+ int shift = (port & 1) * 16;
+ u32 val;
+
+ val = ioread32(gth->base + reg);
+ val &= 0xffff << shift;
+ val >>= shift;
+
+ return val;
+}
+
+/*
+ * "masters" attribute group
+ */
+
+struct master_attribute {
+ struct device_attribute attr;
+ struct gth_device *gth;
+ unsigned int master;
+};
+
+static void
+gth_master_set(struct gth_device *gth, unsigned int master, int port)
+{
+ unsigned int reg = REG_GTH_SWDEST0 + ((master >> 1) & ~3u);
+ unsigned int shift = (master & 0x7) * 4;
+ u32 val;
+
+ if (master >= 256) {
+ reg = REG_GTH_GSWTDEST;
+ shift = 0;
+ }
+
+ val = ioread32(gth->base + reg);
+ val &= ~(0xf << shift);
+ if (port >= 0)
+ val |= (0x8 | port) << shift;
+ iowrite32(val, gth->base + reg);
+}
+
+/*static int gth_master_get(struct gth_device *gth, unsigned int master)
+{
+ unsigned int reg = REG_GTH_SWDEST0 + ((master >> 1) & ~3u);
+ unsigned int shift = (master & 0x7) * 4;
+ u32 val;
+
+ if (master >= 256) {
+ reg = REG_GTH_GSWTDEST;
+ shift = 0;
+ }
+
+ val = ioread32(gth->base + reg);
+ val &= (0xf << shift);
+ val >>= shift;
+
+ return val ? val & 0x7 : -1;
+ }*/
+
+static ssize_t master_attr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct master_attribute *ma =
+ container_of(attr, struct master_attribute, attr);
+ struct gth_device *gth = ma->gth;
+ size_t count;
+ int port;
+
+ spin_lock(&gth->gth_lock);
+ port = gth->master[ma->master];
+ spin_unlock(&gth->gth_lock);
+
+ if (port >= 0)
+ count = snprintf(buf, PAGE_SIZE, "%x\n", port);
+ else
+ count = snprintf(buf, PAGE_SIZE, "disabled\n");
+
+ return count;
+}
+
+static ssize_t master_attr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct master_attribute *ma =
+ container_of(attr, struct master_attribute, attr);
+ struct gth_device *gth = ma->gth;
+ int old_port, port;
+
+ if (kstrtoint(buf, 10, &port) < 0)
+ return -EINVAL;
+
+ if (port >= TH_POSSIBLE_OUTPUTS || port < -1)
+ return -EINVAL;
+
+ spin_lock(&gth->gth_lock);
+
+ /* disconnect from the previous output port, if any */
+ old_port = gth->master[ma->master];
+ if (old_port >= 0) {
+ gth->master[ma->master] = -1;
+ clear_bit(ma->master, gth->output[old_port].master);
+ if (gth->output[old_port].output->active)
+ gth_master_set(gth, ma->master, -1);
+ }
+
+ /* connect to the new output port, if any */
+ if (port >= 0) {
+ /* check if there's a driver for this port */
+ if (!gth->output[port].output) {
+ count = -ENODEV;
+ goto unlock;
+ }
+
+ set_bit(ma->master, gth->output[port].master);
+
+ /* if the port is active, program this setting */
+ if (gth->output[port].output->active)
+ gth_master_set(gth, ma->master, port);
+ }
+
+ gth->master[ma->master] = port;
+
+unlock:
+ spin_unlock(&gth->gth_lock);
+
+ return count;
+}
+
+struct output_attribute {
+ struct device_attribute attr;
+ struct gth_device *gth;
+ unsigned int port;
+ unsigned int parm;
+};
+
+#define OUTPUT_PARM(_name, _mask, _r, _w, _what) \
+ [TH_OUTPUT_PARM(_name)] = { .name = __stringify(_name), \
+ .get = gth_ ## _what ## _get, \
+ .set = gth_ ## _what ## _set, \
+ .mask = (_mask), \
+ .readable = (_r), \
+ .writable = (_w) }
+
+static const struct output_parm {
+ const char *name;
+ unsigned int (*get)(struct gth_device *gth, int port);
+ void (*set)(struct gth_device *gth, int port,
+ unsigned int val);
+ unsigned int mask;
+ unsigned int readable : 1,
+ writable : 1;
+} output_parms[] = {
+ OUTPUT_PARM(port, 0x7, 1, 0, output),
+ OUTPUT_PARM(null, BIT(3), 1, 1, output),
+ OUTPUT_PARM(drop, BIT(4), 1, 1, output),
+ OUTPUT_PARM(reset, BIT(5), 1, 0, output),
+ OUTPUT_PARM(flush, BIT(7), 0, 1, output),
+ OUTPUT_PARM(smcfreq, 0xffff, 1, 1, smcfreq),
+};
+
+static void
+gth_output_parm_set(struct gth_device *gth, int port, unsigned int parm,
+ unsigned int val)
+{
+ unsigned int config = output_parms[parm].get(gth, port);
+ unsigned int mask = output_parms[parm].mask;
+ unsigned int shift = __ffs(mask);
+
+ config &= ~mask;
+ config |= (val << shift) & mask;
+ output_parms[parm].set(gth, port, config);
+}
+
+static unsigned int
+gth_output_parm_get(struct gth_device *gth, int port, unsigned int parm)
+{
+ unsigned int config = output_parms[parm].get(gth, port);
+ unsigned int mask = output_parms[parm].mask;
+ unsigned int shift = __ffs(mask);
+
+ config &= mask;
+ config >>= shift;
+ return config;
+}
+
+/*
+ * Reset outputs and sources
+ */
+static int intel_th_gth_reset(struct gth_device *gth)
+{
+ u32 scratchpad;
+ int port, i;
+
+ scratchpad = ioread32(gth->base + REG_GTH_SCRPD0);
+ if (scratchpad & SCRPD_DEBUGGER_IN_USE)
+ return -EBUSY;
+
+ /* output ports */
+ for (port = 0; port < 8; port++) {
+ if (gth_output_parm_get(gth, port, TH_OUTPUT_PARM(port)) ==
+ GTH_NONE)
+ continue;
+
+ gth_output_set(gth, port, 0);
+ gth_smcfreq_set(gth, port, 16);
+ }
+ /* disable overrides */
+ iowrite32(0, gth->base + REG_GTH_DESTOVR);
+
+ /* masters swdest_0~31 and gswdest */
+ for (i = 0; i < 33; i++)
+ iowrite32(0, gth->base + REG_GTH_SWDEST0 + i * 4);
+
+ /* sources */
+ iowrite32(0, gth->base + REG_GTH_SCR);
+ iowrite32(0xfc, gth->base + REG_GTH_SCR2);
+
+ return 0;
+}
+
+/*
+ * "outputs" attribute group
+ */
+
+static ssize_t output_attr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct output_attribute *oa =
+ container_of(attr, struct output_attribute, attr);
+ struct gth_device *gth = oa->gth;
+ size_t count;
+
+ spin_lock(&gth->gth_lock);
+ count = snprintf(buf, PAGE_SIZE, "%x\n",
+ gth_output_parm_get(gth, oa->port, oa->parm));
+ spin_unlock(&gth->gth_lock);
+
+ return count;
+}
+
+static ssize_t output_attr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct output_attribute *oa =
+ container_of(attr, struct output_attribute, attr);
+ struct gth_device *gth = oa->gth;
+ unsigned int config;
+
+ if (kstrtouint(buf, 16, &config) < 0)
+ return -EINVAL;
+
+ spin_lock(&gth->gth_lock);
+ gth_output_parm_set(gth, oa->port, oa->parm, config);
+ spin_unlock(&gth->gth_lock);
+
+ return count;
+}
+
+static int intel_th_master_attributes(struct gth_device *gth)
+{
+ struct master_attribute *master_attrs;
+ struct attribute **attrs;
+ int i, nattrs = TH_CONFIGURABLE_MASTERS + 2;
+
+ attrs = devm_kcalloc(gth->dev, nattrs, sizeof(void *), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ master_attrs = devm_kcalloc(gth->dev, nattrs,
+ sizeof(struct master_attribute),
+ GFP_KERNEL);
+ if (!master_attrs)
+ return -ENOMEM;
+
+ for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++) {
+ char *name;
+
+ name = devm_kasprintf(gth->dev, GFP_KERNEL, "%d%s", i,
+ i == TH_CONFIGURABLE_MASTERS ? "+" : "");
+ if (!name)
+ return -ENOMEM;
+
+ master_attrs[i].attr.attr.name = name;
+ master_attrs[i].attr.attr.mode = S_IRUGO | S_IWUSR;
+ master_attrs[i].attr.show = master_attr_show;
+ master_attrs[i].attr.store = master_attr_store;
+
+ sysfs_attr_init(&master_attrs[i].attr.attr);
+ attrs[i] = &master_attrs[i].attr.attr;
+
+ master_attrs[i].gth = gth;
+ master_attrs[i].master = i;
+ }
+
+ gth->master_group.name = "masters";
+ gth->master_group.attrs = attrs;
+
+ return sysfs_create_group(&gth->dev->kobj, &gth->master_group);
+}
+
+static int intel_th_output_attributes(struct gth_device *gth)
+{
+ struct output_attribute *out_attrs;
+ struct attribute **attrs;
+ int i, j, nouts = TH_POSSIBLE_OUTPUTS;
+ int nparms = ARRAY_SIZE(output_parms);
+ int nattrs = nouts * nparms + 1;
+
+ attrs = devm_kcalloc(gth->dev, nattrs, sizeof(void *), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ out_attrs = devm_kcalloc(gth->dev, nattrs,
+ sizeof(struct output_attribute),
+ GFP_KERNEL);
+ if (!out_attrs)
+ return -ENOMEM;
+
+ for (i = 0; i < nouts; i++) {
+ for (j = 0; j < nparms; j++) {
+ unsigned int idx = i * nparms + j;
+ char *name;
+
+ name = devm_kasprintf(gth->dev, GFP_KERNEL, "%d_%s", i,
+ output_parms[j].name);
+ if (!name)
+ return -ENOMEM;
+
+ out_attrs[idx].attr.attr.name = name;
+
+ if (output_parms[j].readable) {
+ out_attrs[idx].attr.attr.mode |= S_IRUGO;
+ out_attrs[idx].attr.show = output_attr_show;
+ }
+
+ if (output_parms[j].writable) {
+ out_attrs[idx].attr.attr.mode |= S_IWUSR;
+ out_attrs[idx].attr.store = output_attr_store;
+ }
+
+ sysfs_attr_init(&out_attrs[idx].attr.attr);
+ attrs[idx] = &out_attrs[idx].attr.attr;
+
+ out_attrs[idx].gth = gth;
+ out_attrs[idx].port = i;
+ out_attrs[idx].parm = j;
+ }
+ }
+
+ gth->output_group.name = "outputs";
+ gth->output_group.attrs = attrs;
+
+ return sysfs_create_group(&gth->dev->kobj, &gth->output_group);
+}
+
+/**
+ * intel_th_gth_disable() - enable tracing to an output device
+ * @thdev: GTH device
+ * @output: output device's descriptor
+ *
+ * This will deconfigure all masters set to output to this device,
+ * disable tracing using force storeEn off signal and wait for the
+ * "pipeline empty" bit for corresponding output port.
+ */
+static void intel_th_gth_disable(struct intel_th_device *thdev,
+ struct intel_th_output *output)
+{
+ struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+ unsigned long count;
+ int master;
+ u32 reg;
+
+ spin_lock(&gth->gth_lock);
+ output->active = false;
+
+ for_each_set_bit(master, gth->output[output->port].master,
+ TH_CONFIGURABLE_MASTERS) {
+ gth_master_set(gth, master, -1);
+ }
+ spin_unlock(&gth->gth_lock);
+
+ iowrite32(0, gth->base + REG_GTH_SCR);
+ iowrite32(0xfd, gth->base + REG_GTH_SCR2);
+
+ /* wait on pipeline empty for the given port */
+ for (reg = 0, count = GTH_PLE_WAITLOOP_DEPTH;
+ count && !(reg & BIT(output->port)); count--) {
+ reg = ioread32(gth->base + REG_GTH_STAT);
+ cpu_relax();
+ }
+
+ /* clear force capture done for next captures */
+ iowrite32(0xfc, gth->base + REG_GTH_SCR2);
+
+ if (!count)
+ dev_dbg(&thdev->dev, "timeout waiting for GTH[%d] PLE\n",
+ output->port);
+}
+
+/**
+ * intel_th_gth_enable() - enable tracing to an output device
+ * @thdev: GTH device
+ * @output: output device's descriptor
+ *
+ * This will configure all masters set to output to this device and
+ * enable tracing using force storeEn signal.
+ */
+static void intel_th_gth_enable(struct intel_th_device *thdev,
+ struct intel_th_output *output)
+{
+ struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+ u32 scr = 0xfc0000;
+ int master;
+
+ spin_lock(&gth->gth_lock);
+ for_each_set_bit(master, gth->output[output->port].master,
+ TH_CONFIGURABLE_MASTERS + 1) {
+ gth_master_set(gth, master, output->port);
+ }
+
+ if (output->multiblock)
+ scr |= 0xff;
+
+ output->active = true;
+ spin_unlock(&gth->gth_lock);
+
+ iowrite32(scr, gth->base + REG_GTH_SCR);
+ iowrite32(0, gth->base + REG_GTH_SCR2);
+}
+
+/**
+ * intel_th_gth_assign() - assign output device to a GTH output port
+ * @thdev: GTH device
+ * @othdev: output device
+ *
+ * This will match a given output device parameters against present
+ * output ports on the GTH and fill out relevant bits in output device's
+ * descriptor.
+ *
+ * Return: 0 on success, -errno on error.
+ */
+static int intel_th_gth_assign(struct intel_th_device *thdev,
+ struct intel_th_device *othdev)
+{
+ struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+ int i, id;
+
+ if (othdev->type != INTEL_TH_OUTPUT)
+ return -EINVAL;
+
+ for (i = 0, id = 0; i < TH_POSSIBLE_OUTPUTS; i++) {
+ if (gth->output[i].port_type != othdev->output.type)
+ continue;
+
+ if (othdev->id == -1 || othdev->id == id)
+ goto found;
+
+ id++;
+ }
+
+ return -ENOENT;
+
+found:
+ spin_lock(&gth->gth_lock);
+ othdev->output.port = i;
+ othdev->output.active = false;
+ gth->output[i].output = &othdev->output;
+ spin_unlock(&gth->gth_lock);
+
+ return 0;
+}
+
+/**
+ * intel_th_gth_unassign() - deassociate an output device from its output port
+ * @thdev: GTH device
+ * @othdev: output device
+ */
+static void intel_th_gth_unassign(struct intel_th_device *thdev,
+ struct intel_th_device *othdev)
+{
+ struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+ int port = othdev->output.port;
+
+ spin_lock(&gth->gth_lock);
+ othdev->output.port = -1;
+ othdev->output.active = false;
+ gth->output[port].output = NULL;
+ spin_unlock(&gth->gth_lock);
+}
+
+static int
+intel_th_gth_set_output(struct intel_th_device *thdev, unsigned int master)
+{
+ struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+ int port = 0; /* FIXME: make default output configurable */
+
+ /*
+ * everything above TH_CONFIGURABLE_MASTERS is controlled by the
+ * same register
+ */
+ if (master > TH_CONFIGURABLE_MASTERS)
+ master = TH_CONFIGURABLE_MASTERS;
+
+ spin_lock(&gth->gth_lock);
+ if (gth->master[master] == -1) {
+ set_bit(master, gth->output[port].master);
+ gth->master[master] = port;
+ }
+ spin_unlock(&gth->gth_lock);
+
+ return 0;
+}
+
+static int intel_th_gth_probe(struct intel_th_device *thdev)
+{
+ struct device *dev = &thdev->dev;
+ struct gth_device *gth;
+ struct resource *res;
+ void __iomem *base;
+ int i, ret;
+
+ res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ gth = devm_kzalloc(dev, sizeof(*gth), GFP_KERNEL);
+ if (!gth)
+ return -ENOMEM;
+
+ gth->dev = dev;
+ gth->base = base;
+ spin_lock_init(&gth->gth_lock);
+
+ ret = intel_th_gth_reset(gth);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++)
+ gth->master[i] = -1;
+
+ for (i = 0; i < TH_POSSIBLE_OUTPUTS; i++) {
+ gth->output[i].gth = gth;
+ gth->output[i].index = i;
+ gth->output[i].port_type =
+ gth_output_parm_get(gth, i, TH_OUTPUT_PARM(port));
+ }
+
+ if (intel_th_output_attributes(gth) ||
+ intel_th_master_attributes(gth)) {
+ pr_warn("Can't initialize sysfs attributes\n");
+
+ if (gth->output_group.attrs)
+ sysfs_remove_group(&gth->dev->kobj, &gth->output_group);
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, gth);
+
+ return 0;
+}
+
+static void intel_th_gth_remove(struct intel_th_device *thdev)
+{
+ struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+
+ sysfs_remove_group(&gth->dev->kobj, &gth->output_group);
+ sysfs_remove_group(&gth->dev->kobj, &gth->master_group);
+}
+
+static struct intel_th_driver intel_th_gth_driver = {
+ .probe = intel_th_gth_probe,
+ .remove = intel_th_gth_remove,
+ .assign = intel_th_gth_assign,
+ .unassign = intel_th_gth_unassign,
+ .set_output = intel_th_gth_set_output,
+ .enable = intel_th_gth_enable,
+ .disable = intel_th_gth_disable,
+ .driver = {
+ .name = "gth",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_driver(intel_th_gth_driver,
+ intel_th_driver_register,
+ intel_th_driver_unregister);
+
+MODULE_ALIAS("intel_th_switch");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel(R) Trace Hub Global Trace Hub driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/intel_th/gth.h b/drivers/hwtracing/intel_th/gth.h
new file mode 100644
index 000000000000..3b714b7a61db
--- /dev/null
+++ b/drivers/hwtracing/intel_th/gth.h
@@ -0,0 +1,66 @@
+/*
+ * Intel(R) Trace Hub Global Trace Hub (GTH) data structures
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#ifndef __INTEL_TH_GTH_H__
+#define __INTEL_TH_GTH_H__
+
+/* Map output port parameter bits to symbolic names */
+#define TH_OUTPUT_PARM(name) \
+ TH_OUTPUT_ ## name
+
+enum intel_th_output_parm {
+ /* output port type */
+ TH_OUTPUT_PARM(port),
+ /* generate NULL packet */
+ TH_OUTPUT_PARM(null),
+ /* packet drop */
+ TH_OUTPUT_PARM(drop),
+ /* port in reset state */
+ TH_OUTPUT_PARM(reset),
+ /* flush out data */
+ TH_OUTPUT_PARM(flush),
+ /* mainenance packet frequency */
+ TH_OUTPUT_PARM(smcfreq),
+};
+
+/*
+ * Register offsets
+ */
+enum {
+ REG_GTH_GTHOPT0 = 0x00, /* Output ports 0..3 config */
+ REG_GTH_GTHOPT1 = 0x04, /* Output ports 4..7 config */
+ REG_GTH_SWDEST0 = 0x08, /* Switching destination masters 0..7 */
+ REG_GTH_GSWTDEST = 0x88, /* Global sw trace destination */
+ REG_GTH_SMCR0 = 0x9c, /* STP mainenance for ports 0/1 */
+ REG_GTH_SMCR1 = 0xa0, /* STP mainenance for ports 2/3 */
+ REG_GTH_SMCR2 = 0xa4, /* STP mainenance for ports 4/5 */
+ REG_GTH_SMCR3 = 0xa8, /* STP mainenance for ports 6/7 */
+ REG_GTH_SCR = 0xc8, /* Source control (storeEn override) */
+ REG_GTH_STAT = 0xd4, /* GTH status */
+ REG_GTH_SCR2 = 0xd8, /* Source control (force storeEn off) */
+ REG_GTH_DESTOVR = 0xdc, /* Destination override */
+ REG_GTH_SCRPD0 = 0xe0, /* ScratchPad[0] */
+ REG_GTH_SCRPD1 = 0xe4, /* ScratchPad[1] */
+ REG_GTH_SCRPD2 = 0xe8, /* ScratchPad[2] */
+ REG_GTH_SCRPD3 = 0xec, /* ScratchPad[3] */
+};
+
+/* Externall debugger is using Intel TH */
+#define SCRPD_DEBUGGER_IN_USE BIT(24)
+
+/* waiting for Pipeline Empty bit(s) to assert for GTH */
+#define GTH_PLE_WAITLOOP_DEPTH 10000
+
+#endif /* __INTEL_TH_GTH_H__ */
diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h
new file mode 100644
index 000000000000..57fd72b20fae
--- /dev/null
+++ b/drivers/hwtracing/intel_th/intel_th.h
@@ -0,0 +1,244 @@
+/*
+ * Intel(R) Trace Hub data structures
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#ifndef __INTEL_TH_H__
+#define __INTEL_TH_H__
+
+/* intel_th_device device types */
+enum {
+ /* Devices that generate trace data */
+ INTEL_TH_SOURCE = 0,
+ /* Output ports (MSC, PTI) */
+ INTEL_TH_OUTPUT,
+ /* Switch, the Global Trace Hub (GTH) */
+ INTEL_TH_SWITCH,
+};
+
+/**
+ * struct intel_th_output - descriptor INTEL_TH_OUTPUT type devices
+ * @port: output port number, assigned by the switch
+ * @type: GTH_{MSU,CTP,PTI}
+ * @multiblock: true for multiblock output configuration
+ * @active: true when this output is enabled
+ *
+ * Output port descriptor, used by switch driver to tell which output
+ * port this output device corresponds to. Filled in at output device's
+ * probe time by switch::assign(). Passed from output device driver to
+ * switch related code to enable/disable its port.
+ */
+struct intel_th_output {
+ int port;
+ unsigned int type;
+ bool multiblock;
+ bool active;
+};
+
+/**
+ * struct intel_th_device - device on the intel_th bus
+ * @dev: device
+ * @resource: array of resources available to this device
+ * @num_resources: number of resources in @resource array
+ * @type: INTEL_TH_{SOURCE,OUTPUT,SWITCH}
+ * @id: device instance or -1
+ * @output: output descriptor for INTEL_TH_OUTPUT devices
+ * @name: device name to match the driver
+ */
+struct intel_th_device {
+ struct device dev;
+ struct resource *resource;
+ unsigned int num_resources;
+ unsigned int type;
+ int id;
+
+ /* INTEL_TH_OUTPUT specific */
+ struct intel_th_output output;
+
+ char name[];
+};
+
+#define to_intel_th_device(_d) \
+ container_of((_d), struct intel_th_device, dev)
+
+/**
+ * intel_th_device_get_resource() - obtain @num'th resource of type @type
+ * @thdev: the device to search the resource for
+ * @type: resource type
+ * @num: number of the resource
+ */
+static inline struct resource *
+intel_th_device_get_resource(struct intel_th_device *thdev, unsigned int type,
+ unsigned int num)
+{
+ int i;
+
+ for (i = 0; i < thdev->num_resources; i++)
+ if (resource_type(&thdev->resource[i]) == type && !num--)
+ return &thdev->resource[i];
+
+ return NULL;
+}
+
+/**
+ * intel_th_output_assigned() - if an output device is assigned to a switch port
+ * @thdev: the output device
+ *
+ * Return: true if the device is INTEL_TH_OUTPUT *and* is assigned a port
+ */
+static inline bool
+intel_th_output_assigned(struct intel_th_device *thdev)
+{
+ return thdev->type == INTEL_TH_OUTPUT &&
+ thdev->output.port >= 0;
+}
+
+/**
+ * struct intel_th_driver - driver for an intel_th_device device
+ * @driver: generic driver
+ * @probe: probe method
+ * @remove: remove method
+ * @assign: match a given output type device against available outputs
+ * @unassign: deassociate an output type device from an output port
+ * @enable: enable tracing for a given output device
+ * @disable: disable tracing for a given output device
+ * @fops: file operations for device nodes
+ *
+ * Callbacks @probe and @remove are required for all device types.
+ * Switch device driver needs to fill in @assign, @enable and @disable
+ * callbacks.
+ */
+struct intel_th_driver {
+ struct device_driver driver;
+ int (*probe)(struct intel_th_device *thdev);
+ void (*remove)(struct intel_th_device *thdev);
+ /* switch (GTH) ops */
+ int (*assign)(struct intel_th_device *thdev,
+ struct intel_th_device *othdev);
+ void (*unassign)(struct intel_th_device *thdev,
+ struct intel_th_device *othdev);
+ void (*enable)(struct intel_th_device *thdev,
+ struct intel_th_output *output);
+ void (*disable)(struct intel_th_device *thdev,
+ struct intel_th_output *output);
+ /* output ops */
+ void (*irq)(struct intel_th_device *thdev);
+ int (*activate)(struct intel_th_device *thdev);
+ void (*deactivate)(struct intel_th_device *thdev);
+ /* file_operations for those who want a device node */
+ const struct file_operations *fops;
+
+ /* source ops */
+ int (*set_output)(struct intel_th_device *thdev,
+ unsigned int master);
+};
+
+#define to_intel_th_driver(_d) \
+ container_of((_d), struct intel_th_driver, driver)
+
+static inline struct intel_th_device *
+to_intel_th_hub(struct intel_th_device *thdev)
+{
+ struct device *parent = thdev->dev.parent;
+
+ if (!parent)
+ return NULL;
+
+ return to_intel_th_device(parent);
+}
+
+struct intel_th *
+intel_th_alloc(struct device *dev, struct resource *devres,
+ unsigned int ndevres, int irq);
+void intel_th_free(struct intel_th *th);
+
+int intel_th_driver_register(struct intel_th_driver *thdrv);
+void intel_th_driver_unregister(struct intel_th_driver *thdrv);
+
+int intel_th_trace_enable(struct intel_th_device *thdev);
+int intel_th_trace_disable(struct intel_th_device *thdev);
+int intel_th_set_output(struct intel_th_device *thdev,
+ unsigned int master);
+
+enum {
+ TH_MMIO_CONFIG = 0,
+ TH_MMIO_SW = 2,
+ TH_MMIO_END,
+};
+
+#define TH_SUBDEVICE_MAX 6
+#define TH_POSSIBLE_OUTPUTS 8
+#define TH_CONFIGURABLE_MASTERS 256
+#define TH_MSC_MAX 2
+
+/**
+ * struct intel_th - Intel TH controller
+ * @dev: driver core's device
+ * @thdev: subdevices
+ * @hub: "switch" subdevice (GTH)
+ * @id: this Intel TH controller's device ID in the system
+ * @major: device node major for output devices
+ */
+struct intel_th {
+ struct device *dev;
+
+ struct intel_th_device *thdev[TH_SUBDEVICE_MAX];
+ struct intel_th_device *hub;
+
+ int id;
+ int major;
+#ifdef CONFIG_INTEL_TH_DEBUG
+ struct dentry *dbg;
+#endif
+};
+
+/*
+ * Register windows
+ */
+enum {
+ /* Global Trace Hub (GTH) */
+ REG_GTH_OFFSET = 0x0000,
+ REG_GTH_LENGTH = 0x2000,
+
+ /* Software Trace Hub (STH) [0x4000..0x4fff] */
+ REG_STH_OFFSET = 0x4000,
+ REG_STH_LENGTH = 0x2000,
+
+ /* Memory Storage Unit (MSU) [0xa0000..0xa1fff] */
+ REG_MSU_OFFSET = 0xa0000,
+ REG_MSU_LENGTH = 0x02000,
+
+ /* Internal MSU trace buffer [0x80000..0x9ffff] */
+ BUF_MSU_OFFSET = 0x80000,
+ BUF_MSU_LENGTH = 0x20000,
+
+ /* PTI output == same window as GTH */
+ REG_PTI_OFFSET = REG_GTH_OFFSET,
+ REG_PTI_LENGTH = REG_GTH_LENGTH,
+
+ /* DCI Handler (DCIH) == some window as MSU */
+ REG_DCIH_OFFSET = REG_MSU_OFFSET,
+ REG_DCIH_LENGTH = REG_MSU_LENGTH,
+};
+
+/*
+ * GTH, output ports configuration
+ */
+enum {
+ GTH_NONE = 0,
+ GTH_MSU, /* memory/usb */
+ GTH_CTP, /* Common Trace Port */
+ GTH_PTI = 4, /* MIPI-PTI */
+};
+
+#endif
diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
new file mode 100644
index 000000000000..70ca27e45602
--- /dev/null
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -0,0 +1,1509 @@
+/*
+ * Intel(R) Trace Hub Memory Storage Unit
+ *
+ * Copyright (C) 2014-2015 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) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/sizes.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "intel_th.h"
+#include "msu.h"
+
+#define msc_dev(x) (&(x)->thdev->dev)
+
+/**
+ * struct msc_block - multiblock mode block descriptor
+ * @bdesc: pointer to hardware descriptor (beginning of the block)
+ * @addr: physical address of the block
+ */
+struct msc_block {
+ struct msc_block_desc *bdesc;
+ dma_addr_t addr;
+};
+
+/**
+ * struct msc_window - multiblock mode window descriptor
+ * @entry: window list linkage (msc::win_list)
+ * @pgoff: page offset into the buffer that this window starts at
+ * @nr_blocks: number of blocks (pages) in this window
+ * @block: array of block descriptors
+ */
+struct msc_window {
+ struct list_head entry;
+ unsigned long pgoff;
+ unsigned int nr_blocks;
+ struct msc *msc;
+ struct msc_block block[0];
+};
+
+/**
+ * struct msc_iter - iterator for msc buffer
+ * @entry: msc::iter_list linkage
+ * @msc: pointer to the MSC device
+ * @start_win: oldest window
+ * @win: current window
+ * @offset: current logical offset into the buffer
+ * @start_block: oldest block in the window
+ * @block: block number in the window
+ * @block_off: offset into current block
+ * @wrap_count: block wrapping handling
+ * @eof: end of buffer reached
+ */
+struct msc_iter {
+ struct list_head entry;
+ struct msc *msc;
+ struct msc_window *start_win;
+ struct msc_window *win;
+ unsigned long offset;
+ int start_block;
+ int block;
+ unsigned int block_off;
+ unsigned int wrap_count;
+ unsigned int eof;
+};
+
+/**
+ * struct msc - MSC device representation
+ * @reg_base: register window base address
+ * @thdev: intel_th_device pointer
+ * @win_list: list of windows in multiblock mode
+ * @nr_pages: total number of pages allocated for this buffer
+ * @single_sz: amount of data in single mode
+ * @single_wrap: single mode wrap occurred
+ * @base: buffer's base pointer
+ * @base_addr: buffer's base address
+ * @user_count: number of users of the buffer
+ * @mmap_count: number of mappings
+ * @buf_mutex: mutex to serialize access to buffer-related bits
+
+ * @enabled: MSC is enabled
+ * @wrap: wrapping is enabled
+ * @mode: MSC operating mode
+ * @burst_len: write burst length
+ * @index: number of this MSC in the MSU
+ */
+struct msc {
+ void __iomem *reg_base;
+ struct intel_th_device *thdev;
+
+ struct list_head win_list;
+ unsigned long nr_pages;
+ unsigned long single_sz;
+ unsigned int single_wrap : 1;
+ void *base;
+ dma_addr_t base_addr;
+
+ /* <0: no buffer, 0: no users, >0: active users */
+ atomic_t user_count;
+
+ atomic_t mmap_count;
+ struct mutex buf_mutex;
+
+ struct mutex iter_mutex;
+ struct list_head iter_list;
+
+ /* config */
+ unsigned int enabled : 1,
+ wrap : 1;
+ unsigned int mode;
+ unsigned int burst_len;
+ unsigned int index;
+};
+
+static inline bool msc_block_is_empty(struct msc_block_desc *bdesc)
+{
+ /* header hasn't been written */
+ if (!bdesc->valid_dw)
+ return true;
+
+ /* valid_dw includes the header */
+ if (!msc_data_sz(bdesc))
+ return true;
+
+ return false;
+}
+
+/**
+ * msc_oldest_window() - locate the window with oldest data
+ * @msc: MSC device
+ *
+ * This should only be used in multiblock mode. Caller should hold the
+ * msc::user_count reference.
+ *
+ * Return: the oldest window with valid data
+ */
+static struct msc_window *msc_oldest_window(struct msc *msc)
+{
+ struct msc_window *win;
+ u32 reg = ioread32(msc->reg_base + REG_MSU_MSC0NWSA);
+ unsigned long win_addr = (unsigned long)reg << PAGE_SHIFT;
+ unsigned int found = 0;
+
+ if (list_empty(&msc->win_list))
+ return NULL;
+
+ /*
+ * we might need a radix tree for this, depending on how
+ * many windows a typical user would allocate; ideally it's
+ * something like 2, in which case we're good
+ */
+ list_for_each_entry(win, &msc->win_list, entry) {
+ if (win->block[0].addr == win_addr)
+ found++;
+
+ /* skip the empty ones */
+ if (msc_block_is_empty(win->block[0].bdesc))
+ continue;
+
+ if (found)
+ return win;
+ }
+
+ return list_entry(msc->win_list.next, struct msc_window, entry);
+}
+
+/**
+ * msc_win_oldest_block() - locate the oldest block in a given window
+ * @win: window to look at
+ *
+ * Return: index of the block with the oldest data
+ */
+static unsigned int msc_win_oldest_block(struct msc_window *win)
+{
+ unsigned int blk;
+ struct msc_block_desc *bdesc = win->block[0].bdesc;
+
+ /* without wrapping, first block is the oldest */
+ if (!msc_block_wrapped(bdesc))
+ return 0;
+
+ /*
+ * with wrapping, last written block contains both the newest and the
+ * oldest data for this window.
+ */
+ for (blk = 0; blk < win->nr_blocks; blk++) {
+ bdesc = win->block[blk].bdesc;
+
+ if (msc_block_last_written(bdesc))
+ return blk;
+ }
+
+ return 0;
+}
+
+/**
+ * msc_is_last_win() - check if a window is the last one for a given MSC
+ * @win: window
+ * Return: true if @win is the last window in MSC's multiblock buffer
+ */
+static inline bool msc_is_last_win(struct msc_window *win)
+{
+ return win->entry.next == &win->msc->win_list;
+}
+
+/**
+ * msc_next_window() - return next window in the multiblock buffer
+ * @win: current window
+ *
+ * Return: window following the current one
+ */
+static struct msc_window *msc_next_window(struct msc_window *win)
+{
+ if (msc_is_last_win(win))
+ return list_entry(win->msc->win_list.next, struct msc_window,
+ entry);
+
+ return list_entry(win->entry.next, struct msc_window, entry);
+}
+
+static struct msc_block_desc *msc_iter_bdesc(struct msc_iter *iter)
+{
+ return iter->win->block[iter->block].bdesc;
+}
+
+static void msc_iter_init(struct msc_iter *iter)
+{
+ memset(iter, 0, sizeof(*iter));
+ iter->start_block = -1;
+ iter->block = -1;
+}
+
+static struct msc_iter *msc_iter_install(struct msc *msc)
+{
+ struct msc_iter *iter;
+
+ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return NULL;
+
+ msc_iter_init(iter);
+ iter->msc = msc;
+
+ mutex_lock(&msc->iter_mutex);
+ list_add_tail(&iter->entry, &msc->iter_list);
+ mutex_unlock(&msc->iter_mutex);
+
+ return iter;
+}
+
+static void msc_iter_remove(struct msc_iter *iter, struct msc *msc)
+{
+ mutex_lock(&msc->iter_mutex);
+ list_del(&iter->entry);
+ mutex_unlock(&msc->iter_mutex);
+
+ kfree(iter);
+}
+
+static void msc_iter_block_start(struct msc_iter *iter)
+{
+ if (iter->start_block != -1)
+ return;
+
+ iter->start_block = msc_win_oldest_block(iter->win);
+ iter->block = iter->start_block;
+ iter->wrap_count = 0;
+
+ /*
+ * start with the block with oldest data; if data has wrapped
+ * in this window, it should be in this block
+ */
+ if (msc_block_wrapped(msc_iter_bdesc(iter)))
+ iter->wrap_count = 2;
+
+}
+
+static int msc_iter_win_start(struct msc_iter *iter, struct msc *msc)
+{
+ /* already started, nothing to do */
+ if (iter->start_win)
+ return 0;
+
+ iter->start_win = msc_oldest_window(msc);
+ if (!iter->start_win)
+ return -EINVAL;
+
+ iter->win = iter->start_win;
+ iter->start_block = -1;
+
+ msc_iter_block_start(iter);
+
+ return 0;
+}
+
+static int msc_iter_win_advance(struct msc_iter *iter)
+{
+ iter->win = msc_next_window(iter->win);
+ iter->start_block = -1;
+
+ if (iter->win == iter->start_win) {
+ iter->eof++;
+ return 1;
+ }
+
+ msc_iter_block_start(iter);
+
+ return 0;
+}
+
+static int msc_iter_block_advance(struct msc_iter *iter)
+{
+ iter->block_off = 0;
+
+ /* wrapping */
+ if (iter->wrap_count && iter->block == iter->start_block) {
+ iter->wrap_count--;
+ if (!iter->wrap_count)
+ /* copied newest data from the wrapped block */
+ return msc_iter_win_advance(iter);
+ }
+
+ /* no wrapping, check for last written block */
+ if (!iter->wrap_count && msc_block_last_written(msc_iter_bdesc(iter)))
+ /* copied newest data for the window */
+ return msc_iter_win_advance(iter);
+
+ /* block advance */
+ if (++iter->block == iter->win->nr_blocks)
+ iter->block = 0;
+
+ /* no wrapping, sanity check in case there is no last written block */
+ if (!iter->wrap_count && iter->block == iter->start_block)
+ return msc_iter_win_advance(iter);
+
+ return 0;
+}
+
+/**
+ * msc_buffer_iterate() - go through multiblock buffer's data
+ * @iter: iterator structure
+ * @size: amount of data to scan
+ * @data: callback's private data
+ * @fn: iterator callback
+ *
+ * This will start at the window which will be written to next (containing
+ * the oldest data) and work its way to the current window, calling @fn
+ * for each chunk of data as it goes.
+ *
+ * Caller should have msc::user_count reference to make sure the buffer
+ * doesn't disappear from under us.
+ *
+ * Return: amount of data actually scanned.
+ */
+static ssize_t
+msc_buffer_iterate(struct msc_iter *iter, size_t size, void *data,
+ unsigned long (*fn)(void *, void *, size_t))
+{
+ struct msc *msc = iter->msc;
+ size_t len = size;
+ unsigned int advance;
+
+ if (iter->eof)
+ return 0;
+
+ /* start with the oldest window */
+ if (msc_iter_win_start(iter, msc))
+ return 0;
+
+ do {
+ unsigned long data_bytes = msc_data_sz(msc_iter_bdesc(iter));
+ void *src = (void *)msc_iter_bdesc(iter) + MSC_BDESC;
+ size_t tocopy = data_bytes, copied = 0;
+ size_t remaining = 0;
+
+ advance = 1;
+
+ /*
+ * If block wrapping happened, we need to visit the last block
+ * twice, because it contains both the oldest and the newest
+ * data in this window.
+ *
+ * First time (wrap_count==2), in the very beginning, to collect
+ * the oldest data, which is in the range
+ * (data_bytes..DATA_IN_PAGE).
+ *
+ * Second time (wrap_count==1), it's just like any other block,
+ * containing data in the range of [MSC_BDESC..data_bytes].
+ */
+ if (iter->block == iter->start_block && iter->wrap_count) {
+ tocopy = DATA_IN_PAGE - data_bytes;
+ src += data_bytes;
+ }
+
+ if (!tocopy)
+ goto next_block;
+
+ tocopy -= iter->block_off;
+ src += iter->block_off;
+
+ if (len < tocopy) {
+ tocopy = len;
+ advance = 0;
+ }
+
+ remaining = fn(data, src, tocopy);
+
+ if (remaining)
+ advance = 0;
+
+ copied = tocopy - remaining;
+ len -= copied;
+ iter->block_off += copied;
+ iter->offset += copied;
+
+ if (!advance)
+ break;
+
+next_block:
+ if (msc_iter_block_advance(iter))
+ break;
+
+ } while (len);
+
+ return size - len;
+}
+
+/**
+ * msc_buffer_clear_hw_header() - clear hw header for multiblock
+ * @msc: MSC device
+ */
+static void msc_buffer_clear_hw_header(struct msc *msc)
+{
+ struct msc_window *win;
+
+ mutex_lock(&msc->buf_mutex);
+ list_for_each_entry(win, &msc->win_list, entry) {
+ unsigned int blk;
+ size_t hw_sz = sizeof(struct msc_block_desc) -
+ offsetof(struct msc_block_desc, hw_tag);
+
+ for (blk = 0; blk < win->nr_blocks; blk++) {
+ struct msc_block_desc *bdesc = win->block[blk].bdesc;
+
+ memset(&bdesc->hw_tag, 0, hw_sz);
+ }
+ }
+ mutex_unlock(&msc->buf_mutex);
+}
+
+/**
+ * msc_configure() - set up MSC hardware
+ * @msc: the MSC device to configure
+ *
+ * Program storage mode, wrapping, burst length and trace buffer address
+ * into a given MSC. If msc::enabled is set, enable the trace, too.
+ */
+static int msc_configure(struct msc *msc)
+{
+ u32 reg;
+
+ if (msc->mode > MSC_MODE_MULTI)
+ return -ENOTSUPP;
+
+ if (msc->mode == MSC_MODE_MULTI)
+ msc_buffer_clear_hw_header(msc);
+
+ reg = msc->base_addr >> PAGE_SHIFT;
+ iowrite32(reg, msc->reg_base + REG_MSU_MSC0BAR);
+
+ if (msc->mode == MSC_MODE_SINGLE) {
+ reg = msc->nr_pages;
+ iowrite32(reg, msc->reg_base + REG_MSU_MSC0SIZE);
+ }
+
+ reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
+ reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD);
+
+ reg |= msc->mode << __ffs(MSC_MODE);
+ reg |= msc->burst_len << __ffs(MSC_LEN);
+ /*if (msc->mode == MSC_MODE_MULTI)
+ reg |= MSC_RD_HDR_OVRD; */
+ if (msc->wrap)
+ reg |= MSC_WRAPEN;
+ if (msc->enabled)
+ reg |= MSC_EN;
+
+ iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
+
+ if (msc->enabled) {
+ msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
+ intel_th_trace_enable(msc->thdev);
+ }
+
+ return 0;
+}
+
+/**
+ * msc_disable() - disable MSC hardware
+ * @msc: MSC device to disable
+ *
+ * If @msc is enabled, disable tracing on the switch and then disable MSC
+ * storage.
+ */
+static void msc_disable(struct msc *msc)
+{
+ unsigned long count;
+ u32 reg;
+
+ if (!msc->enabled)
+ return;
+
+ intel_th_trace_disable(msc->thdev);
+
+ for (reg = 0, count = MSC_PLE_WAITLOOP_DEPTH;
+ count && !(reg & MSCSTS_PLE); count--) {
+ reg = ioread32(msc->reg_base + REG_MSU_MSC0STS);
+ cpu_relax();
+ }
+
+ if (!count)
+ dev_dbg(msc_dev(msc), "timeout waiting for MSC0 PLE\n");
+
+ if (msc->mode == MSC_MODE_SINGLE) {
+ msc->single_wrap = !!(reg & MSCSTS_WRAPSTAT);
+
+ reg = ioread32(msc->reg_base + REG_MSU_MSC0MWP);
+ msc->single_sz = reg & ((msc->nr_pages << PAGE_SHIFT) - 1);
+ dev_dbg(msc_dev(msc), "MSCnMWP: %08x/%08lx, wrap: %d\n",
+ reg, msc->single_sz, msc->single_wrap);
+ }
+
+ reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
+ reg &= ~MSC_EN;
+ iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
+ msc->enabled = 0;
+
+ iowrite32(0, msc->reg_base + REG_MSU_MSC0BAR);
+ iowrite32(0, msc->reg_base + REG_MSU_MSC0SIZE);
+
+ dev_dbg(msc_dev(msc), "MSCnNWSA: %08x\n",
+ ioread32(msc->reg_base + REG_MSU_MSC0NWSA));
+
+ reg = ioread32(msc->reg_base + REG_MSU_MSC0STS);
+ dev_dbg(msc_dev(msc), "MSCnSTS: %08x\n", reg);
+}
+
+static int intel_th_msc_activate(struct intel_th_device *thdev)
+{
+ struct msc *msc = dev_get_drvdata(&thdev->dev);
+ int ret = 0;
+
+ if (!atomic_inc_unless_negative(&msc->user_count))
+ return -ENODEV;
+
+ mutex_lock(&msc->iter_mutex);
+ if (!list_empty(&msc->iter_list))
+ ret = -EBUSY;
+ mutex_unlock(&msc->iter_mutex);
+
+ if (ret) {
+ atomic_dec(&msc->user_count);
+ return ret;
+ }
+
+ msc->enabled = 1;
+
+ return msc_configure(msc);
+}
+
+static void intel_th_msc_deactivate(struct intel_th_device *thdev)
+{
+ struct msc *msc = dev_get_drvdata(&thdev->dev);
+
+ msc_disable(msc);
+
+ atomic_dec(&msc->user_count);
+}
+
+/**
+ * msc_buffer_contig_alloc() - allocate a contiguous buffer for SINGLE mode
+ * @msc: MSC device
+ * @size: allocation size in bytes
+ *
+ * This modifies msc::base, which requires msc::buf_mutex to serialize, so the
+ * caller is expected to hold it.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int msc_buffer_contig_alloc(struct msc *msc, unsigned long size)
+{
+ unsigned int order = get_order(size);
+ struct page *page;
+
+ if (!size)
+ return 0;
+
+ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
+ if (!page)
+ return -ENOMEM;
+
+ split_page(page, order);
+ msc->nr_pages = size >> PAGE_SHIFT;
+ msc->base = page_address(page);
+ msc->base_addr = page_to_phys(page);
+
+ return 0;
+}
+
+/**
+ * msc_buffer_contig_free() - free a contiguous buffer
+ * @msc: MSC configured in SINGLE mode
+ */
+static void msc_buffer_contig_free(struct msc *msc)
+{
+ unsigned long off;
+
+ for (off = 0; off < msc->nr_pages << PAGE_SHIFT; off += PAGE_SIZE) {
+ struct page *page = virt_to_page(msc->base + off);
+
+ page->mapping = NULL;
+ __free_page(page);
+ }
+
+ msc->nr_pages = 0;
+}
+
+/**
+ * msc_buffer_contig_get_page() - find a page at a given offset
+ * @msc: MSC configured in SINGLE mode
+ * @pgoff: page offset
+ *
+ * Return: page, if @pgoff is within the range, NULL otherwise.
+ */
+static struct page *msc_buffer_contig_get_page(struct msc *msc,
+ unsigned long pgoff)
+{
+ if (pgoff >= msc->nr_pages)
+ return NULL;
+
+ return virt_to_page(msc->base + (pgoff << PAGE_SHIFT));
+}
+
+/**
+ * msc_buffer_win_alloc() - alloc a window for a multiblock mode
+ * @msc: MSC device
+ * @nr_blocks: number of pages in this window
+ *
+ * This modifies msc::win_list and msc::base, which requires msc::buf_mutex
+ * to serialize, so the caller is expected to hold it.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks)
+{
+ struct msc_window *win;
+ unsigned long size = PAGE_SIZE;
+ int i, ret = -ENOMEM;
+
+ if (!nr_blocks)
+ return 0;
+
+ win = kzalloc(offsetof(struct msc_window, block[nr_blocks]),
+ GFP_KERNEL);
+ if (!win)
+ return -ENOMEM;
+
+ if (!list_empty(&msc->win_list)) {
+ struct msc_window *prev = list_entry(msc->win_list.prev,
+ struct msc_window, entry);
+
+ win->pgoff = prev->pgoff + prev->nr_blocks;
+ }
+
+ for (i = 0; i < nr_blocks; i++) {
+ win->block[i].bdesc = dma_alloc_coherent(msc_dev(msc), size,
+ &win->block[i].addr,
+ GFP_KERNEL);
+
+#ifdef CONFIG_X86
+ /* Set the page as uncached */
+ set_memory_uc((unsigned long)win->block[i].bdesc, 1);
+#endif
+
+ if (!win->block[i].bdesc)
+ goto err_nomem;
+ }
+
+ win->msc = msc;
+ win->nr_blocks = nr_blocks;
+
+ if (list_empty(&msc->win_list)) {
+ msc->base = win->block[0].bdesc;
+ msc->base_addr = win->block[0].addr;
+ }
+
+ list_add_tail(&win->entry, &msc->win_list);
+ msc->nr_pages += nr_blocks;
+
+ return 0;
+
+err_nomem:
+ for (i--; i >= 0; i--) {
+#ifdef CONFIG_X86
+ /* Reset the page to write-back before releasing */
+ set_memory_wb((unsigned long)win->block[i].bdesc, 1);
+#endif
+ dma_free_coherent(msc_dev(msc), size, win->block[i].bdesc,
+ win->block[i].addr);
+ }
+ kfree(win);
+
+ return ret;
+}
+
+/**
+ * msc_buffer_win_free() - free a window from MSC's window list
+ * @msc: MSC device
+ * @win: window to free
+ *
+ * This modifies msc::win_list and msc::base, which requires msc::buf_mutex
+ * to serialize, so the caller is expected to hold it.
+ */
+static void msc_buffer_win_free(struct msc *msc, struct msc_window *win)
+{
+ int i;
+
+ msc->nr_pages -= win->nr_blocks;
+
+ list_del(&win->entry);
+ if (list_empty(&msc->win_list)) {
+ msc->base = NULL;
+ msc->base_addr = 0;
+ }
+
+ for (i = 0; i < win->nr_blocks; i++) {
+ struct page *page = virt_to_page(win->block[i].bdesc);
+
+ page->mapping = NULL;
+#ifdef CONFIG_X86
+ /* Reset the page to write-back before releasing */
+ set_memory_wb((unsigned long)win->block[i].bdesc, 1);
+#endif
+ dma_free_coherent(msc_dev(win->msc), PAGE_SIZE,
+ win->block[i].bdesc, win->block[i].addr);
+ }
+
+ kfree(win);
+}
+
+/**
+ * msc_buffer_relink() - set up block descriptors for multiblock mode
+ * @msc: MSC device
+ *
+ * This traverses msc::win_list, which requires msc::buf_mutex to serialize,
+ * so the caller is expected to hold it.
+ */
+static void msc_buffer_relink(struct msc *msc)
+{
+ struct msc_window *win, *next_win;
+
+ /* call with msc::mutex locked */
+ list_for_each_entry(win, &msc->win_list, entry) {
+ unsigned int blk;
+ u32 sw_tag = 0;
+
+ /*
+ * Last window's next_win should point to the first window
+ * and MSC_SW_TAG_LASTWIN should be set.
+ */
+ if (msc_is_last_win(win)) {
+ sw_tag |= MSC_SW_TAG_LASTWIN;
+ next_win = list_entry(msc->win_list.next,
+ struct msc_window, entry);
+ } else {
+ next_win = list_entry(win->entry.next,
+ struct msc_window, entry);
+ }
+
+ for (blk = 0; blk < win->nr_blocks; blk++) {
+ struct msc_block_desc *bdesc = win->block[blk].bdesc;
+
+ memset(bdesc, 0, sizeof(*bdesc));
+
+ bdesc->next_win = next_win->block[0].addr >> PAGE_SHIFT;
+
+ /*
+ * Similarly to last window, last block should point
+ * to the first one.
+ */
+ if (blk == win->nr_blocks - 1) {
+ sw_tag |= MSC_SW_TAG_LASTBLK;
+ bdesc->next_blk =
+ win->block[0].addr >> PAGE_SHIFT;
+ } else {
+ bdesc->next_blk =
+ win->block[blk + 1].addr >> PAGE_SHIFT;
+ }
+
+ bdesc->sw_tag = sw_tag;
+ bdesc->block_sz = PAGE_SIZE / 64;
+ }
+ }
+
+ /*
+ * Make the above writes globally visible before tracing is
+ * enabled to make sure hardware sees them coherently.
+ */
+ wmb();
+}
+
+static void msc_buffer_multi_free(struct msc *msc)
+{
+ struct msc_window *win, *iter;
+
+ list_for_each_entry_safe(win, iter, &msc->win_list, entry)
+ msc_buffer_win_free(msc, win);
+}
+
+static int msc_buffer_multi_alloc(struct msc *msc, unsigned long *nr_pages,
+ unsigned int nr_wins)
+{
+ int ret, i;
+
+ for (i = 0; i < nr_wins; i++) {
+ ret = msc_buffer_win_alloc(msc, nr_pages[i]);
+ if (ret) {
+ msc_buffer_multi_free(msc);
+ return ret;
+ }
+ }
+
+ msc_buffer_relink(msc);
+
+ return 0;
+}
+
+/**
+ * msc_buffer_free() - free buffers for MSC
+ * @msc: MSC device
+ *
+ * Free MSC's storage buffers.
+ *
+ * This modifies msc::win_list and msc::base, which requires msc::buf_mutex to
+ * serialize, so the caller is expected to hold it.
+ */
+static void msc_buffer_free(struct msc *msc)
+{
+ if (msc->mode == MSC_MODE_SINGLE)
+ msc_buffer_contig_free(msc);
+ else if (msc->mode == MSC_MODE_MULTI)
+ msc_buffer_multi_free(msc);
+}
+
+/**
+ * msc_buffer_alloc() - allocate a buffer for MSC
+ * @msc: MSC device
+ * @size: allocation size in bytes
+ *
+ * Allocate a storage buffer for MSC, depending on the msc::mode, it will be
+ * either done via msc_buffer_contig_alloc() for SINGLE operation mode or
+ * msc_buffer_win_alloc() for multiblock operation. The latter allocates one
+ * window per invocation, so in multiblock mode this can be called multiple
+ * times for the same MSC to allocate multiple windows.
+ *
+ * This modifies msc::win_list and msc::base, which requires msc::buf_mutex
+ * to serialize, so the caller is expected to hold it.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int msc_buffer_alloc(struct msc *msc, unsigned long *nr_pages,
+ unsigned int nr_wins)
+{
+ int ret;
+
+ /* -1: buffer not allocated */
+ if (atomic_read(&msc->user_count) != -1)
+ return -EBUSY;
+
+ if (msc->mode == MSC_MODE_SINGLE) {
+ if (nr_wins != 1)
+ return -EINVAL;
+
+ ret = msc_buffer_contig_alloc(msc, nr_pages[0] << PAGE_SHIFT);
+ } else if (msc->mode == MSC_MODE_MULTI) {
+ ret = msc_buffer_multi_alloc(msc, nr_pages, nr_wins);
+ } else {
+ ret = -ENOTSUPP;
+ }
+
+ if (!ret) {
+ /* allocation should be visible before the counter goes to 0 */
+ smp_mb__before_atomic();
+
+ if (WARN_ON_ONCE(atomic_cmpxchg(&msc->user_count, -1, 0) != -1))
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * msc_buffer_unlocked_free_unless_used() - free a buffer unless it's in use
+ * @msc: MSC device
+ *
+ * This will free MSC buffer unless it is in use or there is no allocated
+ * buffer.
+ * Caller needs to hold msc::buf_mutex.
+ *
+ * Return: 0 on successful deallocation or if there was no buffer to
+ * deallocate, -EBUSY if there are active users.
+ */
+static int msc_buffer_unlocked_free_unless_used(struct msc *msc)
+{
+ int count, ret = 0;
+
+ count = atomic_cmpxchg(&msc->user_count, 0, -1);
+
+ /* > 0: buffer is allocated and has users */
+ if (count > 0)
+ ret = -EBUSY;
+ /* 0: buffer is allocated, no users */
+ else if (!count)
+ msc_buffer_free(msc);
+ /* < 0: no buffer, nothing to do */
+
+ return ret;
+}
+
+/**
+ * msc_buffer_free_unless_used() - free a buffer unless it's in use
+ * @msc: MSC device
+ *
+ * This is a locked version of msc_buffer_unlocked_free_unless_used().
+ */
+static int msc_buffer_free_unless_used(struct msc *msc)
+{
+ int ret;
+
+ mutex_lock(&msc->buf_mutex);
+ ret = msc_buffer_unlocked_free_unless_used(msc);
+ mutex_unlock(&msc->buf_mutex);
+
+ return ret;
+}
+
+/**
+ * msc_buffer_get_page() - get MSC buffer page at a given offset
+ * @msc: MSC device
+ * @pgoff: page offset into the storage buffer
+ *
+ * This traverses msc::win_list, so holding msc::buf_mutex is expected from
+ * the caller.
+ *
+ * Return: page if @pgoff corresponds to a valid buffer page or NULL.
+ */
+static struct page *msc_buffer_get_page(struct msc *msc, unsigned long pgoff)
+{
+ struct msc_window *win;
+
+ if (msc->mode == MSC_MODE_SINGLE)
+ return msc_buffer_contig_get_page(msc, pgoff);
+
+ list_for_each_entry(win, &msc->win_list, entry)
+ if (pgoff >= win->pgoff && pgoff < win->pgoff + win->nr_blocks)
+ goto found;
+
+ return NULL;
+
+found:
+ pgoff -= win->pgoff;
+ return virt_to_page(win->block[pgoff].bdesc);
+}
+
+/**
+ * struct msc_win_to_user_struct - data for copy_to_user() callback
+ * @buf: userspace buffer to copy data to
+ * @offset: running offset
+ */
+struct msc_win_to_user_struct {
+ char __user *buf;
+ unsigned long offset;
+};
+
+/**
+ * msc_win_to_user() - iterator for msc_buffer_iterate() to copy data to user
+ * @data: callback's private data
+ * @src: source buffer
+ * @len: amount of data to copy from the source buffer
+ */
+static unsigned long msc_win_to_user(void *data, void *src, size_t len)
+{
+ struct msc_win_to_user_struct *u = data;
+ unsigned long ret;
+
+ ret = copy_to_user(u->buf + u->offset, src, len);
+ u->offset += len - ret;
+
+ return ret;
+}
+
+
+/*
+ * file operations' callbacks
+ */
+
+static int intel_th_msc_open(struct inode *inode, struct file *file)
+{
+ struct intel_th_device *thdev = file->private_data;
+ struct msc *msc = dev_get_drvdata(&thdev->dev);
+ struct msc_iter *iter;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ iter = msc_iter_install(msc);
+ if (!iter)
+ return -ENOMEM;
+
+ file->private_data = iter;
+
+ return nonseekable_open(inode, file);
+}
+
+static int intel_th_msc_release(struct inode *inode, struct file *file)
+{
+ struct msc_iter *iter = file->private_data;
+ struct msc *msc = iter->msc;
+
+ msc_iter_remove(iter, msc);
+
+ return 0;
+}
+
+static ssize_t
+msc_single_to_user(struct msc *msc, char __user *buf, loff_t off, size_t len)
+{
+ unsigned long size = msc->nr_pages << PAGE_SHIFT, rem = len;
+ unsigned long start = off, tocopy = 0;
+
+ if (msc->single_wrap) {
+ start += msc->single_sz;
+ if (start < size) {
+ tocopy = min(rem, size - start);
+ if (copy_to_user(buf, msc->base + start, tocopy))
+ return -EFAULT;
+
+ buf += tocopy;
+ rem -= tocopy;
+ start += tocopy;
+ }
+
+ start &= size - 1;
+ if (rem) {
+ tocopy = min(rem, msc->single_sz - start);
+ if (copy_to_user(buf, msc->base + start, tocopy))
+ return -EFAULT;
+
+ rem -= tocopy;
+ }
+
+ return len - rem;
+ }
+
+ if (copy_to_user(buf, msc->base + start, rem))
+ return -EFAULT;
+
+ return len;
+}
+
+static ssize_t intel_th_msc_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct msc_iter *iter = file->private_data;
+ struct msc *msc = iter->msc;
+ size_t size;
+ loff_t off = *ppos;
+ ssize_t ret = 0;
+
+ if (!atomic_inc_unless_negative(&msc->user_count))
+ return 0;
+
+ if (msc->enabled) {
+ ret = -EBUSY;
+ goto put_count;
+ }
+
+ if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap)
+ size = msc->single_sz;
+ else
+ size = msc->nr_pages << PAGE_SHIFT;
+
+ if (!size)
+ return 0;
+
+ if (off >= size) {
+ len = 0;
+ goto put_count;
+ }
+ if (off + len >= size)
+ len = size - off;
+
+ if (msc->mode == MSC_MODE_SINGLE) {
+ ret = msc_single_to_user(msc, buf, off, len);
+ if (ret >= 0)
+ *ppos += ret;
+ } else if (msc->mode == MSC_MODE_MULTI) {
+ struct msc_win_to_user_struct u = {
+ .buf = buf,
+ .offset = 0,
+ };
+
+ ret = msc_buffer_iterate(iter, len, &u, msc_win_to_user);
+ if (ret >= 0)
+ *ppos = iter->offset;
+ } else {
+ ret = -ENOTSUPP;
+ }
+
+put_count:
+ atomic_dec(&msc->user_count);
+
+ return ret;
+}
+
+/*
+ * vm operations callbacks (vm_ops)
+ */
+
+static void msc_mmap_open(struct vm_area_struct *vma)
+{
+ struct msc_iter *iter = vma->vm_file->private_data;
+ struct msc *msc = iter->msc;
+
+ atomic_inc(&msc->mmap_count);
+}
+
+static void msc_mmap_close(struct vm_area_struct *vma)
+{
+ struct msc_iter *iter = vma->vm_file->private_data;
+ struct msc *msc = iter->msc;
+ unsigned long pg;
+
+ if (!atomic_dec_and_mutex_lock(&msc->mmap_count, &msc->buf_mutex))
+ return;
+
+ /* drop page _counts */
+ for (pg = 0; pg < msc->nr_pages; pg++) {
+ struct page *page = msc_buffer_get_page(msc, pg);
+
+ if (WARN_ON_ONCE(!page))
+ continue;
+
+ if (page->mapping)
+ page->mapping = NULL;
+ }
+
+ /* last mapping -- drop user_count */
+ atomic_dec(&msc->user_count);
+ mutex_unlock(&msc->buf_mutex);
+}
+
+static int msc_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct msc_iter *iter = vma->vm_file->private_data;
+ struct msc *msc = iter->msc;
+
+ vmf->page = msc_buffer_get_page(msc, vmf->pgoff);
+ if (!vmf->page)
+ return VM_FAULT_SIGBUS;
+
+ get_page(vmf->page);
+ vmf->page->mapping = vma->vm_file->f_mapping;
+ vmf->page->index = vmf->pgoff;
+
+ return 0;
+}
+
+static const struct vm_operations_struct msc_mmap_ops = {
+ .open = msc_mmap_open,
+ .close = msc_mmap_close,
+ .fault = msc_mmap_fault,
+};
+
+static int intel_th_msc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start;
+ struct msc_iter *iter = vma->vm_file->private_data;
+ struct msc *msc = iter->msc;
+ int ret = -EINVAL;
+
+ if (!size || offset_in_page(size))
+ return -EINVAL;
+
+ if (vma->vm_pgoff)
+ return -EINVAL;
+
+ /* grab user_count once per mmap; drop in msc_mmap_close() */
+ if (!atomic_inc_unless_negative(&msc->user_count))
+ return -EINVAL;
+
+ if (msc->mode != MSC_MODE_SINGLE &&
+ msc->mode != MSC_MODE_MULTI)
+ goto out;
+
+ if (size >> PAGE_SHIFT != msc->nr_pages)
+ goto out;
+
+ atomic_set(&msc->mmap_count, 1);
+ ret = 0;
+
+out:
+ if (ret)
+ atomic_dec(&msc->user_count);
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_DONTEXPAND | VM_DONTCOPY;
+ vma->vm_ops = &msc_mmap_ops;
+ return ret;
+}
+
+static const struct file_operations intel_th_msc_fops = {
+ .open = intel_th_msc_open,
+ .release = intel_th_msc_release,
+ .read = intel_th_msc_read,
+ .mmap = intel_th_msc_mmap,
+ .llseek = no_llseek,
+};
+
+static int intel_th_msc_init(struct msc *msc)
+{
+ atomic_set(&msc->user_count, -1);
+
+ msc->mode = MSC_MODE_MULTI;
+ mutex_init(&msc->buf_mutex);
+ INIT_LIST_HEAD(&msc->win_list);
+
+ mutex_init(&msc->iter_mutex);
+ INIT_LIST_HEAD(&msc->iter_list);
+
+ msc->burst_len =
+ (ioread32(msc->reg_base + REG_MSU_MSC0CTL) & MSC_LEN) >>
+ __ffs(MSC_LEN);
+
+ return 0;
+}
+
+static const char * const msc_mode[] = {
+ [MSC_MODE_SINGLE] = "single",
+ [MSC_MODE_MULTI] = "multi",
+ [MSC_MODE_EXI] = "ExI",
+ [MSC_MODE_DEBUG] = "debug",
+};
+
+static ssize_t
+wrap_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct msc *msc = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", msc->wrap);
+}
+
+static ssize_t
+wrap_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct msc *msc = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ msc->wrap = !!val;
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(wrap);
+
+static ssize_t
+mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct msc *msc = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", msc_mode[msc->mode]);
+}
+
+static ssize_t
+mode_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct msc *msc = dev_get_drvdata(dev);
+ size_t len = size;
+ char *cp;
+ int i, ret;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ cp = memchr(buf, '\n', len);
+ if (cp)
+ len = cp - buf;
+
+ for (i = 0; i < ARRAY_SIZE(msc_mode); i++)
+ if (!strncmp(msc_mode[i], buf, len))
+ goto found;
+
+ return -EINVAL;
+
+found:
+ mutex_lock(&msc->buf_mutex);
+ ret = msc_buffer_unlocked_free_unless_used(msc);
+ if (!ret)
+ msc->mode = i;
+ mutex_unlock(&msc->buf_mutex);
+
+ return ret ? ret : size;
+}
+
+static DEVICE_ATTR_RW(mode);
+
+static ssize_t
+nr_pages_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct msc *msc = dev_get_drvdata(dev);
+ struct msc_window *win;
+ size_t count = 0;
+
+ mutex_lock(&msc->buf_mutex);
+
+ if (msc->mode == MSC_MODE_SINGLE)
+ count = scnprintf(buf, PAGE_SIZE, "%ld\n", msc->nr_pages);
+ else if (msc->mode == MSC_MODE_MULTI) {
+ list_for_each_entry(win, &msc->win_list, entry) {
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "%d%c", win->nr_blocks,
+ msc_is_last_win(win) ? '\n' : ',');
+ }
+ } else {
+ count = scnprintf(buf, PAGE_SIZE, "unsupported\n");
+ }
+
+ mutex_unlock(&msc->buf_mutex);
+
+ return count;
+}
+
+static ssize_t
+nr_pages_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct msc *msc = dev_get_drvdata(dev);
+ unsigned long val, *win = NULL, *rewin;
+ size_t len = size;
+ const char *p = buf;
+ char *end, *s;
+ int ret, nr_wins = 0;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ ret = msc_buffer_free_unless_used(msc);
+ if (ret)
+ return ret;
+
+ /* scan the comma-separated list of allocation sizes */
+ end = memchr(buf, '\n', len);
+ if (end)
+ len = end - buf;
+
+ do {
+ end = memchr(p, ',', len);
+ s = kstrndup(p, end ? end - p : len, GFP_KERNEL);
+ ret = kstrtoul(s, 10, &val);
+ kfree(s);
+
+ if (ret || !val)
+ goto free_win;
+
+ if (nr_wins && msc->mode == MSC_MODE_SINGLE) {
+ ret = -EINVAL;
+ goto free_win;
+ }
+
+ nr_wins++;
+ rewin = krealloc(win, sizeof(*win) * nr_wins, GFP_KERNEL);
+ if (!rewin) {
+ kfree(win);
+ return -ENOMEM;
+ }
+
+ win = rewin;
+ win[nr_wins - 1] = val;
+
+ if (!end)
+ break;
+
+ len -= end - p;
+ p = end + 1;
+ } while (len);
+
+ mutex_lock(&msc->buf_mutex);
+ ret = msc_buffer_alloc(msc, win, nr_wins);
+ mutex_unlock(&msc->buf_mutex);
+
+free_win:
+ kfree(win);
+
+ return ret ? ret : size;
+}
+
+static DEVICE_ATTR_RW(nr_pages);
+
+static struct attribute *msc_output_attrs[] = {
+ &dev_attr_wrap.attr,
+ &dev_attr_mode.attr,
+ &dev_attr_nr_pages.attr,
+ NULL,
+};
+
+static struct attribute_group msc_output_group = {
+ .attrs = msc_output_attrs,
+};
+
+static int intel_th_msc_probe(struct intel_th_device *thdev)
+{
+ struct device *dev = &thdev->dev;
+ struct resource *res;
+ struct msc *msc;
+ void __iomem *base;
+ int err;
+
+ res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ msc = devm_kzalloc(dev, sizeof(*msc), GFP_KERNEL);
+ if (!msc)
+ return -ENOMEM;
+
+ msc->index = thdev->id;
+
+ msc->thdev = thdev;
+ msc->reg_base = base + msc->index * 0x100;
+
+ err = intel_th_msc_init(msc);
+ if (err)
+ return err;
+
+ err = sysfs_create_group(&dev->kobj, &msc_output_group);
+ if (err)
+ return err;
+
+ dev_set_drvdata(dev, msc);
+
+ return 0;
+}
+
+static void intel_th_msc_remove(struct intel_th_device *thdev)
+{
+ sysfs_remove_group(&thdev->dev.kobj, &msc_output_group);
+}
+
+static struct intel_th_driver intel_th_msc_driver = {
+ .probe = intel_th_msc_probe,
+ .remove = intel_th_msc_remove,
+ .activate = intel_th_msc_activate,
+ .deactivate = intel_th_msc_deactivate,
+ .fops = &intel_th_msc_fops,
+ .driver = {
+ .name = "msc",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_driver(intel_th_msc_driver,
+ intel_th_driver_register,
+ intel_th_driver_unregister);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel(R) Trace Hub Memory Storage Unit driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/intel_th/msu.h b/drivers/hwtracing/intel_th/msu.h
new file mode 100644
index 000000000000..9b710e4aa98a
--- /dev/null
+++ b/drivers/hwtracing/intel_th/msu.h
@@ -0,0 +1,116 @@
+/*
+ * Intel(R) Trace Hub Memory Storage Unit (MSU) data structures
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#ifndef __INTEL_TH_MSU_H__
+#define __INTEL_TH_MSU_H__
+
+enum {
+ REG_MSU_MSUPARAMS = 0x0000,
+ REG_MSU_MSUSTS = 0x0008,
+ REG_MSU_MSC0CTL = 0x0100, /* MSC0 control */
+ REG_MSU_MSC0STS = 0x0104, /* MSC0 status */
+ REG_MSU_MSC0BAR = 0x0108, /* MSC0 output base address */
+ REG_MSU_MSC0SIZE = 0x010c, /* MSC0 output size */
+ REG_MSU_MSC0MWP = 0x0110, /* MSC0 write pointer */
+ REG_MSU_MSC0NWSA = 0x011c, /* MSC0 next window start address */
+
+ REG_MSU_MSC1CTL = 0x0200, /* MSC1 control */
+ REG_MSU_MSC1STS = 0x0204, /* MSC1 status */
+ REG_MSU_MSC1BAR = 0x0208, /* MSC1 output base address */
+ REG_MSU_MSC1SIZE = 0x020c, /* MSC1 output size */
+ REG_MSU_MSC1MWP = 0x0210, /* MSC1 write pointer */
+ REG_MSU_MSC1NWSA = 0x021c, /* MSC1 next window start address */
+};
+
+/* MSUSTS bits */
+#define MSUSTS_MSU_INT BIT(0)
+
+/* MSCnCTL bits */
+#define MSC_EN BIT(0)
+#define MSC_WRAPEN BIT(1)
+#define MSC_RD_HDR_OVRD BIT(2)
+#define MSC_MODE (BIT(4) | BIT(5))
+#define MSC_LEN (BIT(8) | BIT(9) | BIT(10))
+
+/* MSC operating modes (MSC_MODE) */
+enum {
+ MSC_MODE_SINGLE = 0,
+ MSC_MODE_MULTI,
+ MSC_MODE_EXI,
+ MSC_MODE_DEBUG,
+};
+
+/* MSCnSTS bits */
+#define MSCSTS_WRAPSTAT BIT(1) /* Wrap occurred */
+#define MSCSTS_PLE BIT(2) /* Pipeline Empty */
+
+/*
+ * Multiblock/multiwindow block descriptor
+ */
+struct msc_block_desc {
+ u32 sw_tag;
+ u32 block_sz;
+ u32 next_blk;
+ u32 next_win;
+ u32 res0[4];
+ u32 hw_tag;
+ u32 valid_dw;
+ u32 ts_low;
+ u32 ts_high;
+ u32 res1[4];
+} __packed;
+
+#define MSC_BDESC sizeof(struct msc_block_desc)
+#define DATA_IN_PAGE (PAGE_SIZE - MSC_BDESC)
+
+/* MSC multiblock sw tag bits */
+#define MSC_SW_TAG_LASTBLK BIT(0)
+#define MSC_SW_TAG_LASTWIN BIT(1)
+
+/* MSC multiblock hw tag bits */
+#define MSC_HW_TAG_TRIGGER BIT(0)
+#define MSC_HW_TAG_BLOCKWRAP BIT(1)
+#define MSC_HW_TAG_WINWRAP BIT(2)
+#define MSC_HW_TAG_ENDBIT BIT(3)
+
+static inline unsigned long msc_data_sz(struct msc_block_desc *bdesc)
+{
+ if (!bdesc->valid_dw)
+ return 0;
+
+ return bdesc->valid_dw * 4 - MSC_BDESC;
+}
+
+static inline bool msc_block_wrapped(struct msc_block_desc *bdesc)
+{
+ if (bdesc->hw_tag & MSC_HW_TAG_BLOCKWRAP)
+ return true;
+
+ return false;
+}
+
+static inline bool msc_block_last_written(struct msc_block_desc *bdesc)
+{
+ if ((bdesc->hw_tag & MSC_HW_TAG_ENDBIT) ||
+ (msc_data_sz(bdesc) != DATA_IN_PAGE))
+ return true;
+
+ return false;
+}
+
+/* waiting for Pipeline Empty bit(s) to assert for MSC */
+#define MSC_PLE_WAITLOOP_DEPTH 10000
+
+#endif /* __INTEL_TH_MSU_H__ */
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
new file mode 100644
index 000000000000..641e87936064
--- /dev/null
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -0,0 +1,86 @@
+/*
+ * Intel(R) Trace Hub pci driver
+ *
+ * Copyright (C) 2014-2015 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) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/pci.h>
+
+#include "intel_th.h"
+
+#define DRIVER_NAME "intel_th_pci"
+
+#define BAR_MASK (BIT(TH_MMIO_CONFIG) | BIT(TH_MMIO_SW))
+
+static int intel_th_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct intel_th *th;
+ int err;
+
+ err = pcim_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME);
+ if (err)
+ return err;
+
+ th = intel_th_alloc(&pdev->dev, pdev->resource,
+ DEVICE_COUNT_RESOURCE, pdev->irq);
+ if (IS_ERR(th))
+ return PTR_ERR(th);
+
+ pci_set_drvdata(pdev, th);
+
+ return 0;
+}
+
+static void intel_th_pci_remove(struct pci_dev *pdev)
+{
+ struct intel_th *th = pci_get_drvdata(pdev);
+
+ intel_th_free(th);
+}
+
+static const struct pci_device_id intel_th_pci_id_table[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9d26),
+ .driver_data = (kernel_ulong_t)0,
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126),
+ .driver_data = (kernel_ulong_t)0,
+ },
+ { 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, intel_th_pci_id_table);
+
+static struct pci_driver intel_th_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = intel_th_pci_id_table,
+ .probe = intel_th_pci_probe,
+ .remove = intel_th_pci_remove,
+};
+
+module_pci_driver(intel_th_pci_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel(R) Trace Hub PCI controller driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>");
diff --git a/drivers/hwtracing/intel_th/pti.c b/drivers/hwtracing/intel_th/pti.c
new file mode 100644
index 000000000000..57cbfdcc7ef0
--- /dev/null
+++ b/drivers/hwtracing/intel_th/pti.c
@@ -0,0 +1,252 @@
+/*
+ * Intel(R) Trace Hub PTI output driver
+ *
+ * Copyright (C) 2014-2015 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) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/sizes.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+
+#include "intel_th.h"
+#include "pti.h"
+
+struct pti_device {
+ void __iomem *base;
+ struct intel_th_device *thdev;
+ unsigned int mode;
+ unsigned int freeclk;
+ unsigned int clkdiv;
+ unsigned int patgen;
+};
+
+/* map PTI widths to MODE settings of PTI_CTL register */
+static const unsigned int pti_mode[] = {
+ 0, 4, 8, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static int pti_width_mode(unsigned int width)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pti_mode); i++)
+ if (pti_mode[i] == width)
+ return i;
+
+ return -EINVAL;
+}
+
+static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pti_device *pti = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", pti_mode[pti->mode]);
+}
+
+static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pti_device *pti = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ ret = pti_width_mode(val);
+ if (ret < 0)
+ return ret;
+
+ pti->mode = ret;
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(mode);
+
+static ssize_t
+freerunning_clock_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pti_device *pti = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", pti->freeclk);
+}
+
+static ssize_t
+freerunning_clock_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pti_device *pti = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ pti->freeclk = !!val;
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(freerunning_clock);
+
+static ssize_t
+clock_divider_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pti_device *pti = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", 1u << pti->clkdiv);
+}
+
+static ssize_t
+clock_divider_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pti_device *pti = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if (!is_power_of_2(val) || val > 8 || !val)
+ return -EINVAL;
+
+ pti->clkdiv = val;
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(clock_divider);
+
+static struct attribute *pti_output_attrs[] = {
+ &dev_attr_mode.attr,
+ &dev_attr_freerunning_clock.attr,
+ &dev_attr_clock_divider.attr,
+ NULL,
+};
+
+static struct attribute_group pti_output_group = {
+ .attrs = pti_output_attrs,
+};
+
+static int intel_th_pti_activate(struct intel_th_device *thdev)
+{
+ struct pti_device *pti = dev_get_drvdata(&thdev->dev);
+ u32 ctl = PTI_EN;
+
+ if (pti->patgen)
+ ctl |= pti->patgen << __ffs(PTI_PATGENMODE);
+ if (pti->freeclk)
+ ctl |= PTI_FCEN;
+ ctl |= pti->mode << __ffs(PTI_MODE);
+ ctl |= pti->clkdiv << __ffs(PTI_CLKDIV);
+
+ iowrite32(ctl, pti->base + REG_PTI_CTL);
+
+ intel_th_trace_enable(thdev);
+
+ return 0;
+}
+
+static void intel_th_pti_deactivate(struct intel_th_device *thdev)
+{
+ struct pti_device *pti = dev_get_drvdata(&thdev->dev);
+
+ intel_th_trace_disable(thdev);
+
+ iowrite32(0, pti->base + REG_PTI_CTL);
+}
+
+static void read_hw_config(struct pti_device *pti)
+{
+ u32 ctl = ioread32(pti->base + REG_PTI_CTL);
+
+ pti->mode = (ctl & PTI_MODE) >> __ffs(PTI_MODE);
+ pti->clkdiv = (ctl & PTI_CLKDIV) >> __ffs(PTI_CLKDIV);
+ pti->freeclk = !!(ctl & PTI_FCEN);
+
+ if (!pti_mode[pti->mode])
+ pti->mode = pti_width_mode(4);
+ if (!pti->clkdiv)
+ pti->clkdiv = 1;
+}
+
+static int intel_th_pti_probe(struct intel_th_device *thdev)
+{
+ struct device *dev = &thdev->dev;
+ struct resource *res;
+ struct pti_device *pti;
+ void __iomem *base;
+ int ret;
+
+ res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ pti = devm_kzalloc(dev, sizeof(*pti), GFP_KERNEL);
+ if (!pti)
+ return -ENOMEM;
+
+ pti->thdev = thdev;
+ pti->base = base;
+
+ read_hw_config(pti);
+
+ ret = sysfs_create_group(&dev->kobj, &pti_output_group);
+ if (ret)
+ return ret;
+
+ dev_set_drvdata(dev, pti);
+
+ return 0;
+}
+
+static void intel_th_pti_remove(struct intel_th_device *thdev)
+{
+}
+
+static struct intel_th_driver intel_th_pti_driver = {
+ .probe = intel_th_pti_probe,
+ .remove = intel_th_pti_remove,
+ .activate = intel_th_pti_activate,
+ .deactivate = intel_th_pti_deactivate,
+ .driver = {
+ .name = "pti",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_driver(intel_th_pti_driver,
+ intel_th_driver_register,
+ intel_th_driver_unregister);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel(R) Trace Hub PTI output driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/intel_th/pti.h b/drivers/hwtracing/intel_th/pti.h
new file mode 100644
index 000000000000..20883f5628cf
--- /dev/null
+++ b/drivers/hwtracing/intel_th/pti.h
@@ -0,0 +1,29 @@
+/*
+ * Intel(R) Trace Hub PTI output data structures
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#ifndef __INTEL_TH_STH_H__
+#define __INTEL_TH_STH_H__
+
+enum {
+ REG_PTI_CTL = 0x1c00,
+};
+
+#define PTI_EN BIT(0)
+#define PTI_FCEN BIT(1)
+#define PTI_MODE 0xf0
+#define PTI_CLKDIV 0x000f0000
+#define PTI_PATGENMODE 0x00f00000
+
+#endif /* __INTEL_TH_STH_H__ */
diff --git a/drivers/hwtracing/intel_th/sth.c b/drivers/hwtracing/intel_th/sth.c
new file mode 100644
index 000000000000..56101c33e10f
--- /dev/null
+++ b/drivers/hwtracing/intel_th/sth.c
@@ -0,0 +1,259 @@
+/*
+ * Intel(R) Trace Hub Software Trace Hub support
+ *
+ * Copyright (C) 2014-2015 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) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+
+#include "intel_th.h"
+#include "sth.h"
+
+struct sth_device {
+ void __iomem *base;
+ void __iomem *channels;
+ phys_addr_t channels_phys;
+ struct device *dev;
+ struct stm_data stm;
+ unsigned int sw_nmasters;
+};
+
+static struct intel_th_channel __iomem *
+sth_channel(struct sth_device *sth, unsigned int master, unsigned int channel)
+{
+ struct intel_th_channel __iomem *sw_map = sth->channels;
+
+ return &sw_map[(master - sth->stm.sw_start) * sth->stm.sw_nchannels +
+ channel];
+}
+
+static void sth_iowrite(void __iomem *dest, const unsigned char *payload,
+ unsigned int size)
+{
+ switch (size) {
+#ifdef CONFIG_64BIT
+ case 8:
+ writeq_relaxed(*(u64 *)payload, dest);
+ break;
+#endif
+ case 4:
+ writel_relaxed(*(u32 *)payload, dest);
+ break;
+ case 2:
+ writew_relaxed(*(u16 *)payload, dest);
+ break;
+ case 1:
+ writeb_relaxed(*(u8 *)payload, dest);
+ break;
+ default:
+ break;
+ }
+}
+
+static ssize_t sth_stm_packet(struct stm_data *stm_data, unsigned int master,
+ unsigned int channel, unsigned int packet,
+ unsigned int flags, unsigned int size,
+ const unsigned char *payload)
+{
+ struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
+ struct intel_th_channel __iomem *out =
+ sth_channel(sth, master, channel);
+ u64 __iomem *outp = &out->Dn;
+ unsigned long reg = REG_STH_TRIG;
+
+#ifndef CONFIG_64BIT
+ if (size > 4)
+ size = 4;
+#endif
+
+ size = rounddown_pow_of_two(size);
+
+ switch (packet) {
+ /* Global packets (GERR, XSYNC, TRIG) are sent with register writes */
+ case STP_PACKET_GERR:
+ reg += 4;
+ case STP_PACKET_XSYNC:
+ reg += 8;
+ case STP_PACKET_TRIG:
+ if (flags & STP_PACKET_TIMESTAMPED)
+ reg += 4;
+ iowrite8(*payload, sth->base + reg);
+ break;
+
+ case STP_PACKET_MERR:
+ sth_iowrite(&out->MERR, payload, size);
+ break;
+
+ case STP_PACKET_FLAG:
+ if (flags & STP_PACKET_TIMESTAMPED)
+ outp = (u64 __iomem *)&out->FLAG_TS;
+ else
+ outp = (u64 __iomem *)&out->FLAG;
+
+ size = 1;
+ sth_iowrite(outp, payload, size);
+ break;
+
+ case STP_PACKET_USER:
+ if (flags & STP_PACKET_TIMESTAMPED)
+ outp = &out->USER_TS;
+ else
+ outp = &out->USER;
+ sth_iowrite(outp, payload, size);
+ break;
+
+ case STP_PACKET_DATA:
+ outp = &out->Dn;
+
+ if (flags & STP_PACKET_TIMESTAMPED)
+ outp += 2;
+ if (flags & STP_PACKET_MARKED)
+ outp++;
+
+ sth_iowrite(outp, payload, size);
+ break;
+ }
+
+ return size;
+}
+
+static phys_addr_t
+sth_stm_mmio_addr(struct stm_data *stm_data, unsigned int master,
+ unsigned int channel, unsigned int nr_chans)
+{
+ struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
+ phys_addr_t addr;
+
+ master -= sth->stm.sw_start;
+ addr = sth->channels_phys + (master * sth->stm.sw_nchannels + channel) *
+ sizeof(struct intel_th_channel);
+
+ if (offset_in_page(addr) ||
+ offset_in_page(nr_chans * sizeof(struct intel_th_channel)))
+ return 0;
+
+ return addr;
+}
+
+static int sth_stm_link(struct stm_data *stm_data, unsigned int master,
+ unsigned int channel)
+{
+ struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
+
+ intel_th_set_output(to_intel_th_device(sth->dev), master);
+
+ return 0;
+}
+
+static int intel_th_sw_init(struct sth_device *sth)
+{
+ u32 reg;
+
+ reg = ioread32(sth->base + REG_STH_STHCAP1);
+ sth->stm.sw_nchannels = reg & 0xff;
+
+ reg = ioread32(sth->base + REG_STH_STHCAP0);
+ sth->stm.sw_start = reg & 0xffff;
+ sth->stm.sw_end = reg >> 16;
+
+ sth->sw_nmasters = sth->stm.sw_end - sth->stm.sw_start;
+ dev_dbg(sth->dev, "sw_start: %x sw_end: %x masters: %x nchannels: %x\n",
+ sth->stm.sw_start, sth->stm.sw_end, sth->sw_nmasters,
+ sth->stm.sw_nchannels);
+
+ return 0;
+}
+
+static int intel_th_sth_probe(struct intel_th_device *thdev)
+{
+ struct device *dev = &thdev->dev;
+ struct sth_device *sth;
+ struct resource *res;
+ void __iomem *base, *channels;
+ int err;
+
+ res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
+
+ channels = devm_ioremap(dev, res->start, resource_size(res));
+ if (!channels)
+ return -ENOMEM;
+
+ sth = devm_kzalloc(dev, sizeof(*sth), GFP_KERNEL);
+ if (!sth)
+ return -ENOMEM;
+
+ sth->dev = dev;
+ sth->base = base;
+ sth->channels = channels;
+ sth->channels_phys = res->start;
+ sth->stm.name = dev_name(dev);
+ sth->stm.packet = sth_stm_packet;
+ sth->stm.mmio_addr = sth_stm_mmio_addr;
+ sth->stm.sw_mmiosz = sizeof(struct intel_th_channel);
+ sth->stm.link = sth_stm_link;
+
+ err = intel_th_sw_init(sth);
+ if (err)
+ return err;
+
+ err = stm_register_device(dev, &sth->stm, THIS_MODULE);
+ if (err) {
+ dev_err(dev, "stm_register_device failed\n");
+ return err;
+ }
+
+ dev_set_drvdata(dev, sth);
+
+ return 0;
+}
+
+static void intel_th_sth_remove(struct intel_th_device *thdev)
+{
+ struct sth_device *sth = dev_get_drvdata(&thdev->dev);
+
+ stm_unregister_device(&sth->stm);
+}
+
+static struct intel_th_driver intel_th_sth_driver = {
+ .probe = intel_th_sth_probe,
+ .remove = intel_th_sth_remove,
+ .driver = {
+ .name = "sth",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_driver(intel_th_sth_driver,
+ intel_th_driver_register,
+ intel_th_driver_unregister);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel(R) Trace Hub Software Trace Hub driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@intel.com>");
diff --git a/drivers/hwtracing/intel_th/sth.h b/drivers/hwtracing/intel_th/sth.h
new file mode 100644
index 000000000000..f1390cd4f2ed
--- /dev/null
+++ b/drivers/hwtracing/intel_th/sth.h
@@ -0,0 +1,42 @@
+/*
+ * Intel(R) Trace Hub Software Trace Hub (STH) data structures
+ *
+ * Copyright (C) 2014-2015 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.
+ */
+
+#ifndef __INTEL_TH_STH_H__
+#define __INTEL_TH_STH_H__
+
+enum {
+ REG_STH_STHCAP0 = 0x0000, /* capabilities pt1 */
+ REG_STH_STHCAP1 = 0x0004, /* capabilities pt2 */
+ REG_STH_TRIG = 0x0008, /* TRIG packet payload */
+ REG_STH_TRIG_TS = 0x000c, /* TRIG_TS packet payload */
+ REG_STH_XSYNC = 0x0010, /* XSYNC packet payload */
+ REG_STH_XSYNC_TS = 0x0014, /* XSYNC_TS packet payload */
+ REG_STH_GERR = 0x0018, /* GERR packet payload */
+};
+
+struct intel_th_channel {
+ u64 Dn;
+ u64 DnM;
+ u64 DnTS;
+ u64 DnMTS;
+ u64 USER;
+ u64 USER_TS;
+ u32 FLAG;
+ u32 FLAG_TS;
+ u32 MERR;
+ u32 __unused;
+} __packed;
+
+#endif /* __INTEL_TH_STH_H__ */
diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
new file mode 100644
index 000000000000..83e9f591a54b
--- /dev/null
+++ b/drivers/hwtracing/stm/Kconfig
@@ -0,0 +1,26 @@
+config STM
+ tristate "System Trace Module devices"
+ select CONFIGFS_FS
+ help
+ A System Trace Module (STM) is a device exporting data in System
+ Trace Protocol (STP) format as defined by MIPI STP standards.
+ Examples of such devices are Intel(R) Trace Hub and Coresight STM.
+
+ Say Y here to enable System Trace Module device support.
+
+config STM_DUMMY
+ tristate "Dummy STM driver"
+ help
+ This is a simple dummy device that pretends to be an stm device
+ and discards your data. Use for stm class testing.
+
+ If you don't know what this is, say N.
+
+config STM_SOURCE_CONSOLE
+ tristate "Kernel console over STM devices"
+ help
+ This is a kernel space trace source that sends kernel log
+ messages to trace hosts over STM devices.
+
+ If you want to send kernel console messages over STM devices,
+ say Y.
diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
new file mode 100644
index 000000000000..f9312c38dd7a
--- /dev/null
+++ b/drivers/hwtracing/stm/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_STM) += stm_core.o
+
+stm_core-y := core.o policy.o
+
+obj-$(CONFIG_STM_DUMMY) += dummy_stm.o
+
+obj-$(CONFIG_STM_SOURCE_CONSOLE) += stm_console.o
+
+stm_console-y := console.o
diff --git a/drivers/hwtracing/stm/console.c b/drivers/hwtracing/stm/console.c
new file mode 100644
index 000000000000..c9d9a8d2ff52
--- /dev/null
+++ b/drivers/hwtracing/stm/console.c
@@ -0,0 +1,80 @@
+/*
+ * Simple kernel console driver for STM devices
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * STM console will send kernel messages over STM devices to a trace host.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+
+static int stm_console_link(struct stm_source_data *data);
+static void stm_console_unlink(struct stm_source_data *data);
+
+static struct stm_console {
+ struct stm_source_data data;
+ struct console console;
+} stm_console = {
+ .data = {
+ .name = "console",
+ .nr_chans = 1,
+ .link = stm_console_link,
+ .unlink = stm_console_unlink,
+ },
+};
+
+static void
+stm_console_write(struct console *con, const char *buf, unsigned len)
+{
+ struct stm_console *sc = container_of(con, struct stm_console, console);
+
+ stm_source_write(&sc->data, 0, buf, len);
+}
+
+static int stm_console_link(struct stm_source_data *data)
+{
+ struct stm_console *sc = container_of(data, struct stm_console, data);
+
+ strcpy(sc->console.name, "stm_console");
+ sc->console.write = stm_console_write;
+ sc->console.flags = CON_ENABLED | CON_PRINTBUFFER;
+ register_console(&sc->console);
+
+ return 0;
+}
+
+static void stm_console_unlink(struct stm_source_data *data)
+{
+ struct stm_console *sc = container_of(data, struct stm_console, data);
+
+ unregister_console(&sc->console);
+}
+
+static int stm_console_init(void)
+{
+ return stm_source_register_device(NULL, &stm_console.data);
+}
+
+static void stm_console_exit(void)
+{
+ stm_source_unregister_device(&stm_console.data);
+}
+
+module_init(stm_console_init);
+module_exit(stm_console_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("stm_console driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
new file mode 100644
index 000000000000..b6445d9e5453
--- /dev/null
+++ b/drivers/hwtracing/stm/core.c
@@ -0,0 +1,1032 @@
+/*
+ * System Trace Module (STM) infrastructure
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * STM class implements generic infrastructure for System Trace Module devices
+ * as defined in MIPI STPv2 specification.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/compat.h>
+#include <linux/kdev_t.h>
+#include <linux/srcu.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include "stm.h"
+
+#include <uapi/linux/stm.h>
+
+static unsigned int stm_core_up;
+
+/*
+ * The SRCU here makes sure that STM device doesn't disappear from under a
+ * stm_source_write() caller, which may want to have as little overhead as
+ * possible.
+ */
+static struct srcu_struct stm_source_srcu;
+
+static ssize_t masters_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct stm_device *stm = to_stm_device(dev);
+ int ret;
+
+ ret = sprintf(buf, "%u %u\n", stm->data->sw_start, stm->data->sw_end);
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(masters);
+
+static ssize_t channels_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct stm_device *stm = to_stm_device(dev);
+ int ret;
+
+ ret = sprintf(buf, "%u\n", stm->data->sw_nchannels);
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(channels);
+
+static struct attribute *stm_attrs[] = {
+ &dev_attr_masters.attr,
+ &dev_attr_channels.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(stm);
+
+static struct class stm_class = {
+ .name = "stm",
+ .dev_groups = stm_groups,
+};
+
+static int stm_dev_match(struct device *dev, const void *data)
+{
+ const char *name = data;
+
+ return sysfs_streq(name, dev_name(dev));
+}
+
+/**
+ * stm_find_device() - find stm device by name
+ * @buf: character buffer containing the name
+ *
+ * This is called when either policy gets assigned to an stm device or an
+ * stm_source device gets linked to an stm device.
+ *
+ * This grabs device's reference (get_device()) and module reference, both
+ * of which the calling path needs to make sure to drop with stm_put_device().
+ *
+ * Return: stm device pointer or null if lookup failed.
+ */
+struct stm_device *stm_find_device(const char *buf)
+{
+ struct stm_device *stm;
+ struct device *dev;
+
+ if (!stm_core_up)
+ return NULL;
+
+ dev = class_find_device(&stm_class, NULL, buf, stm_dev_match);
+ if (!dev)
+ return NULL;
+
+ stm = to_stm_device(dev);
+ if (!try_module_get(stm->owner)) {
+ put_device(dev);
+ return NULL;
+ }
+
+ return stm;
+}
+
+/**
+ * stm_put_device() - drop references on the stm device
+ * @stm: stm device, previously acquired by stm_find_device()
+ *
+ * This drops the module reference and device reference taken by
+ * stm_find_device().
+ */
+void stm_put_device(struct stm_device *stm)
+{
+ module_put(stm->owner);
+ put_device(&stm->dev);
+}
+
+/*
+ * Internally we only care about software-writable masters here, that is the
+ * ones in the range [stm_data->sw_start..stm_data..sw_end], however we need
+ * original master numbers to be visible externally, since they are the ones
+ * that will appear in the STP stream. Thus, the internal bookkeeping uses
+ * $master - stm_data->sw_start to reference master descriptors and such.
+ */
+
+#define __stm_master(_s, _m) \
+ ((_s)->masters[(_m) - (_s)->data->sw_start])
+
+static inline struct stp_master *
+stm_master(struct stm_device *stm, unsigned int idx)
+{
+ if (idx < stm->data->sw_start || idx > stm->data->sw_end)
+ return NULL;
+
+ return __stm_master(stm, idx);
+}
+
+static int stp_master_alloc(struct stm_device *stm, unsigned int idx)
+{
+ struct stp_master *master;
+ size_t size;
+
+ size = ALIGN(stm->data->sw_nchannels, 8) / 8;
+ size += sizeof(struct stp_master);
+ master = kzalloc(size, GFP_ATOMIC);
+ if (!master)
+ return -ENOMEM;
+
+ master->nr_free = stm->data->sw_nchannels;
+ __stm_master(stm, idx) = master;
+
+ return 0;
+}
+
+static void stp_master_free(struct stm_device *stm, unsigned int idx)
+{
+ struct stp_master *master = stm_master(stm, idx);
+
+ if (!master)
+ return;
+
+ __stm_master(stm, idx) = NULL;
+ kfree(master);
+}
+
+static void stm_output_claim(struct stm_device *stm, struct stm_output *output)
+{
+ struct stp_master *master = stm_master(stm, output->master);
+
+ if (WARN_ON_ONCE(master->nr_free < output->nr_chans))
+ return;
+
+ bitmap_allocate_region(&master->chan_map[0], output->channel,
+ ilog2(output->nr_chans));
+
+ master->nr_free -= output->nr_chans;
+}
+
+static void
+stm_output_disclaim(struct stm_device *stm, struct stm_output *output)
+{
+ struct stp_master *master = stm_master(stm, output->master);
+
+ bitmap_release_region(&master->chan_map[0], output->channel,
+ ilog2(output->nr_chans));
+
+ output->nr_chans = 0;
+ master->nr_free += output->nr_chans;
+}
+
+/*
+ * This is like bitmap_find_free_region(), except it can ignore @start bits
+ * at the beginning.
+ */
+static int find_free_channels(unsigned long *bitmap, unsigned int start,
+ unsigned int end, unsigned int width)
+{
+ unsigned int pos;
+ int i;
+
+ for (pos = start; pos < end + 1; pos = ALIGN(pos, width)) {
+ pos = find_next_zero_bit(bitmap, end + 1, pos);
+ if (pos + width > end + 1)
+ break;
+
+ if (pos & (width - 1))
+ continue;
+
+ for (i = 1; i < width && !test_bit(pos + i, bitmap); i++)
+ ;
+ if (i == width)
+ return pos;
+ }
+
+ return -1;
+}
+
+static unsigned int
+stm_find_master_chan(struct stm_device *stm, unsigned int width,
+ unsigned int *mstart, unsigned int mend,
+ unsigned int *cstart, unsigned int cend)
+{
+ struct stp_master *master;
+ unsigned int midx;
+ int pos, err;
+
+ for (midx = *mstart; midx <= mend; midx++) {
+ if (!stm_master(stm, midx)) {
+ err = stp_master_alloc(stm, midx);
+ if (err)
+ return err;
+ }
+
+ master = stm_master(stm, midx);
+
+ if (!master->nr_free)
+ continue;
+
+ pos = find_free_channels(master->chan_map, *cstart, cend,
+ width);
+ if (pos < 0)
+ continue;
+
+ *mstart = midx;
+ *cstart = pos;
+ return 0;
+ }
+
+ return -ENOSPC;
+}
+
+static int stm_output_assign(struct stm_device *stm, unsigned int width,
+ struct stp_policy_node *policy_node,
+ struct stm_output *output)
+{
+ unsigned int midx, cidx, mend, cend;
+ int ret = -EINVAL;
+
+ if (width > stm->data->sw_nchannels)
+ return -EINVAL;
+
+ if (policy_node) {
+ stp_policy_node_get_ranges(policy_node,
+ &midx, &mend, &cidx, &cend);
+ } else {
+ midx = stm->data->sw_start;
+ cidx = 0;
+ mend = stm->data->sw_end;
+ cend = stm->data->sw_nchannels - 1;
+ }
+
+ spin_lock(&stm->mc_lock);
+ /* output is already assigned -- shouldn't happen */
+ if (WARN_ON_ONCE(output->nr_chans))
+ goto unlock;
+
+ ret = stm_find_master_chan(stm, width, &midx, mend, &cidx, cend);
+ if (ret)
+ goto unlock;
+
+ output->master = midx;
+ output->channel = cidx;
+ output->nr_chans = width;
+ stm_output_claim(stm, output);
+ dev_dbg(&stm->dev, "assigned %u:%u (+%u)\n", midx, cidx, width);
+
+ ret = 0;
+unlock:
+ spin_unlock(&stm->mc_lock);
+
+ return ret;
+}
+
+static void stm_output_free(struct stm_device *stm, struct stm_output *output)
+{
+ spin_lock(&stm->mc_lock);
+ if (output->nr_chans)
+ stm_output_disclaim(stm, output);
+ spin_unlock(&stm->mc_lock);
+}
+
+static int major_match(struct device *dev, const void *data)
+{
+ unsigned int major = *(unsigned int *)data;
+
+ return MAJOR(dev->devt) == major;
+}
+
+static int stm_char_open(struct inode *inode, struct file *file)
+{
+ struct stm_file *stmf;
+ struct device *dev;
+ unsigned int major = imajor(inode);
+ int err = -ENODEV;
+
+ dev = class_find_device(&stm_class, NULL, &major, major_match);
+ if (!dev)
+ return -ENODEV;
+
+ stmf = kzalloc(sizeof(*stmf), GFP_KERNEL);
+ if (!stmf)
+ return -ENOMEM;
+
+ stmf->stm = to_stm_device(dev);
+
+ if (!try_module_get(stmf->stm->owner))
+ goto err_free;
+
+ file->private_data = stmf;
+
+ return nonseekable_open(inode, file);
+
+err_free:
+ kfree(stmf);
+
+ return err;
+}
+
+static int stm_char_release(struct inode *inode, struct file *file)
+{
+ struct stm_file *stmf = file->private_data;
+
+ stm_output_free(stmf->stm, &stmf->output);
+ stm_put_device(stmf->stm);
+ kfree(stmf);
+
+ return 0;
+}
+
+static int stm_file_assign(struct stm_file *stmf, char *id, unsigned int width)
+{
+ struct stm_device *stm = stmf->stm;
+ int ret;
+
+ stmf->policy_node = stp_policy_node_lookup(stm, id);
+
+ ret = stm_output_assign(stm, width, stmf->policy_node, &stmf->output);
+
+ if (stmf->policy_node)
+ stp_policy_node_put(stmf->policy_node);
+
+ return ret;
+}
+
+static void stm_write(struct stm_data *data, unsigned int master,
+ unsigned int channel, const char *buf, size_t count)
+{
+ unsigned int flags = STP_PACKET_TIMESTAMPED;
+ const unsigned char *p = buf, nil = 0;
+ size_t pos;
+ ssize_t sz;
+
+ for (pos = 0, p = buf; count > pos; pos += sz, p += sz) {
+ sz = min_t(unsigned int, count - pos, 8);
+ sz = data->packet(data, master, channel, STP_PACKET_DATA, flags,
+ sz, p);
+ flags = 0;
+ }
+
+ data->packet(data, master, channel, STP_PACKET_FLAG, 0, 0, &nil);
+}
+
+static ssize_t stm_char_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct stm_file *stmf = file->private_data;
+ struct stm_device *stm = stmf->stm;
+ char *kbuf;
+ int err;
+
+ /*
+ * if no m/c have been assigned to this writer up to this
+ * point, use "default" policy entry
+ */
+ if (!stmf->output.nr_chans) {
+ err = stm_file_assign(stmf, "default", 1);
+ /*
+ * EBUSY means that somebody else just assigned this
+ * output, which is just fine for write()
+ */
+ if (err && err != -EBUSY)
+ return err;
+ }
+
+ kbuf = kmalloc(count + 1, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+ err = copy_from_user(kbuf, buf, count);
+ if (err) {
+ kfree(kbuf);
+ return -EFAULT;
+ }
+
+ stm_write(stm->data, stmf->output.master, stmf->output.channel, kbuf,
+ count);
+
+ kfree(kbuf);
+
+ return count;
+}
+
+static int stm_char_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct stm_file *stmf = file->private_data;
+ struct stm_device *stm = stmf->stm;
+ unsigned long size, phys;
+
+ if (!stm->data->mmio_addr)
+ return -EOPNOTSUPP;
+
+ if (vma->vm_pgoff)
+ return -EINVAL;
+
+ size = vma->vm_end - vma->vm_start;
+
+ if (stmf->output.nr_chans * stm->data->sw_mmiosz != size)
+ return -EINVAL;
+
+ phys = stm->data->mmio_addr(stm->data, stmf->output.master,
+ stmf->output.channel,
+ stmf->output.nr_chans);
+
+ if (!phys)
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
+ vm_iomap_memory(vma, phys, size);
+
+ return 0;
+}
+
+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;
+ int ret = -EINVAL;
+ u32 size;
+
+ if (stmf->output.nr_chans)
+ return -EBUSY;
+
+ if (copy_from_user(&size, arg, sizeof(size)))
+ return -EFAULT;
+
+ if (size >= PATH_MAX + sizeof(*id))
+ return -EINVAL;
+
+ /*
+ * size + 1 to make sure the .id string at the bottom is terminated,
+ * which is also why memdup_user() is not useful here
+ */
+ id = kzalloc(size + 1, GFP_KERNEL);
+ if (!id)
+ return -ENOMEM;
+
+ if (copy_from_user(id, arg, size)) {
+ ret = -EFAULT;
+ goto err_free;
+ }
+
+ if (id->__reserved_0 || id->__reserved_1)
+ goto err_free;
+
+ if (id->width < 1 ||
+ id->width > PAGE_SIZE / stm->data->sw_mmiosz)
+ goto err_free;
+
+ ret = stm_file_assign(stmf, id->id, id->width);
+ if (ret)
+ goto err_free;
+
+ ret = 0;
+
+ if (stm->data->link)
+ ret = stm->data->link(stm->data, stmf->output.master,
+ stmf->output.channel);
+
+ if (ret) {
+ stm_output_free(stmf->stm, &stmf->output);
+ stm_put_device(stmf->stm);
+ }
+
+err_free:
+ kfree(id);
+
+ return ret;
+}
+
+static int stm_char_policy_get_ioctl(struct stm_file *stmf, void __user *arg)
+{
+ struct stp_policy_id id = {
+ .size = sizeof(id),
+ .master = stmf->output.master,
+ .channel = stmf->output.channel,
+ .width = stmf->output.nr_chans,
+ .__reserved_0 = 0,
+ .__reserved_1 = 0,
+ };
+
+ return copy_to_user(arg, &id, id.size) ? -EFAULT : 0;
+}
+
+static long
+stm_char_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct stm_file *stmf = file->private_data;
+ struct stm_data *stm_data = stmf->stm->data;
+ int err = -ENOTTY;
+ u64 options;
+
+ switch (cmd) {
+ case STP_POLICY_ID_SET:
+ err = stm_char_policy_set_ioctl(stmf, (void __user *)arg);
+ if (err)
+ return err;
+
+ return stm_char_policy_get_ioctl(stmf, (void __user *)arg);
+
+ case STP_POLICY_ID_GET:
+ return stm_char_policy_get_ioctl(stmf, (void __user *)arg);
+
+ case STP_SET_OPTIONS:
+ if (copy_from_user(&options, (u64 __user *)arg, sizeof(u64)))
+ return -EFAULT;
+
+ if (stm_data->set_options)
+ err = stm_data->set_options(stm_data,
+ stmf->output.master,
+ stmf->output.channel,
+ stmf->output.nr_chans,
+ options);
+
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+static long
+stm_char_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return stm_char_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+}
+#else
+#define stm_char_compat_ioctl NULL
+#endif
+
+static const struct file_operations stm_fops = {
+ .open = stm_char_open,
+ .release = stm_char_release,
+ .write = stm_char_write,
+ .mmap = stm_char_mmap,
+ .unlocked_ioctl = stm_char_ioctl,
+ .compat_ioctl = stm_char_compat_ioctl,
+ .llseek = no_llseek,
+};
+
+static void stm_device_release(struct device *dev)
+{
+ struct stm_device *stm = to_stm_device(dev);
+
+ kfree(stm);
+}
+
+int stm_register_device(struct device *parent, struct stm_data *stm_data,
+ struct module *owner)
+{
+ struct stm_device *stm;
+ unsigned int nmasters;
+ int err = -ENOMEM;
+
+ if (!stm_core_up)
+ return -EPROBE_DEFER;
+
+ if (!stm_data->packet || !stm_data->sw_nchannels)
+ return -EINVAL;
+
+ nmasters = stm_data->sw_end - stm_data->sw_start;
+ stm = kzalloc(sizeof(*stm) + nmasters * sizeof(void *), GFP_KERNEL);
+ if (!stm)
+ return -ENOMEM;
+
+ stm->major = register_chrdev(0, stm_data->name, &stm_fops);
+ if (stm->major < 0)
+ goto err_free;
+
+ device_initialize(&stm->dev);
+ stm->dev.devt = MKDEV(stm->major, 0);
+ stm->dev.class = &stm_class;
+ stm->dev.parent = parent;
+ stm->dev.release = stm_device_release;
+
+ err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
+ if (err)
+ goto err_device;
+
+ err = device_add(&stm->dev);
+ if (err)
+ goto err_device;
+
+ spin_lock_init(&stm->link_lock);
+ INIT_LIST_HEAD(&stm->link_list);
+
+ spin_lock_init(&stm->mc_lock);
+ mutex_init(&stm->policy_mutex);
+ stm->sw_nmasters = nmasters;
+ stm->owner = owner;
+ stm->data = stm_data;
+ stm_data->stm = stm;
+
+ return 0;
+
+err_device:
+ put_device(&stm->dev);
+err_free:
+ kfree(stm);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(stm_register_device);
+
+static void __stm_source_link_drop(struct stm_source_device *src,
+ struct stm_device *stm);
+
+void stm_unregister_device(struct stm_data *stm_data)
+{
+ struct stm_device *stm = stm_data->stm;
+ struct stm_source_device *src, *iter;
+ int i;
+
+ spin_lock(&stm->link_lock);
+ list_for_each_entry_safe(src, iter, &stm->link_list, link_entry) {
+ __stm_source_link_drop(src, stm);
+ }
+ spin_unlock(&stm->link_lock);
+
+ synchronize_srcu(&stm_source_srcu);
+
+ unregister_chrdev(stm->major, stm_data->name);
+
+ mutex_lock(&stm->policy_mutex);
+ if (stm->policy)
+ stp_policy_unbind(stm->policy);
+ mutex_unlock(&stm->policy_mutex);
+
+ for (i = 0; i < stm->sw_nmasters; i++)
+ stp_master_free(stm, i);
+
+ device_unregister(&stm->dev);
+ stm_data->stm = NULL;
+}
+EXPORT_SYMBOL_GPL(stm_unregister_device);
+
+/**
+ * stm_source_link_add() - connect an stm_source device to an stm device
+ * @src: stm_source device
+ * @stm: stm device
+ *
+ * This function establishes a link from stm_source to an stm device so that
+ * the former can send out trace data to the latter.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int stm_source_link_add(struct stm_source_device *src,
+ struct stm_device *stm)
+{
+ char *id;
+ int err;
+
+ spin_lock(&stm->link_lock);
+ spin_lock(&src->link_lock);
+
+ /* src->link is dereferenced under stm_source_srcu but not the list */
+ rcu_assign_pointer(src->link, stm);
+ list_add_tail(&src->link_entry, &stm->link_list);
+
+ spin_unlock(&src->link_lock);
+ spin_unlock(&stm->link_lock);
+
+ id = kstrdup(src->data->name, GFP_KERNEL);
+ if (id) {
+ src->policy_node =
+ stp_policy_node_lookup(stm, id);
+
+ kfree(id);
+ }
+
+ err = stm_output_assign(stm, src->data->nr_chans,
+ src->policy_node, &src->output);
+
+ if (src->policy_node)
+ stp_policy_node_put(src->policy_node);
+
+ if (err)
+ goto fail_detach;
+
+ /* this is to notify the STM device that a new link has been made */
+ if (stm->data->link)
+ err = stm->data->link(stm->data, src->output.master,
+ src->output.channel);
+
+ if (err)
+ goto fail_free_output;
+
+ /* this is to let the source carry out all necessary preparations */
+ if (src->data->link)
+ src->data->link(src->data);
+
+ return 0;
+
+fail_free_output:
+ stm_output_free(stm, &src->output);
+ stm_put_device(stm);
+
+fail_detach:
+ spin_lock(&stm->link_lock);
+ spin_lock(&src->link_lock);
+
+ rcu_assign_pointer(src->link, NULL);
+ list_del_init(&src->link_entry);
+
+ spin_unlock(&src->link_lock);
+ spin_unlock(&stm->link_lock);
+
+ return err;
+}
+
+/**
+ * __stm_source_link_drop() - detach stm_source from an stm device
+ * @src: stm_source device
+ * @stm: stm device
+ *
+ * If @stm is @src::link, disconnect them from one another and put the
+ * reference on the @stm device.
+ *
+ * Caller must hold stm::link_lock.
+ */
+static void __stm_source_link_drop(struct stm_source_device *src,
+ struct stm_device *stm)
+{
+ struct stm_device *link;
+
+ spin_lock(&src->link_lock);
+ link = srcu_dereference_check(src->link, &stm_source_srcu, 1);
+ if (WARN_ON_ONCE(link != stm)) {
+ spin_unlock(&src->link_lock);
+ return;
+ }
+
+ stm_output_free(link, &src->output);
+ /* caller must hold stm::link_lock */
+ list_del_init(&src->link_entry);
+ /* matches stm_find_device() from stm_source_link_store() */
+ stm_put_device(link);
+ rcu_assign_pointer(src->link, NULL);
+
+ spin_unlock(&src->link_lock);
+}
+
+/**
+ * stm_source_link_drop() - detach stm_source from its stm device
+ * @src: stm_source device
+ *
+ * Unlinking means disconnecting from source's STM device; after this
+ * writes will be unsuccessful until it is linked to a new STM device.
+ *
+ * This will happen on "stm_source_link" sysfs attribute write to undo
+ * the existing link (if any), or on linked STM device's de-registration.
+ */
+static void stm_source_link_drop(struct stm_source_device *src)
+{
+ struct stm_device *stm;
+ int idx;
+
+ idx = srcu_read_lock(&stm_source_srcu);
+ stm = srcu_dereference(src->link, &stm_source_srcu);
+
+ if (stm) {
+ if (src->data->unlink)
+ src->data->unlink(src->data);
+
+ spin_lock(&stm->link_lock);
+ __stm_source_link_drop(src, stm);
+ spin_unlock(&stm->link_lock);
+ }
+
+ srcu_read_unlock(&stm_source_srcu, idx);
+}
+
+static ssize_t stm_source_link_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct stm_source_device *src = to_stm_source_device(dev);
+ struct stm_device *stm;
+ int idx, ret;
+
+ idx = srcu_read_lock(&stm_source_srcu);
+ stm = srcu_dereference(src->link, &stm_source_srcu);
+ ret = sprintf(buf, "%s\n",
+ stm ? dev_name(&stm->dev) : "<none>");
+ srcu_read_unlock(&stm_source_srcu, idx);
+
+ return ret;
+}
+
+static ssize_t stm_source_link_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct stm_source_device *src = to_stm_source_device(dev);
+ struct stm_device *link;
+ int err;
+
+ stm_source_link_drop(src);
+
+ link = stm_find_device(buf);
+ if (!link)
+ return -EINVAL;
+
+ err = stm_source_link_add(src, link);
+ if (err)
+ stm_put_device(link);
+
+ return err ? : count;
+}
+
+static DEVICE_ATTR_RW(stm_source_link);
+
+static struct attribute *stm_source_attrs[] = {
+ &dev_attr_stm_source_link.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(stm_source);
+
+static struct class stm_source_class = {
+ .name = "stm_source",
+ .dev_groups = stm_source_groups,
+};
+
+static void stm_source_device_release(struct device *dev)
+{
+ struct stm_source_device *src = to_stm_source_device(dev);
+
+ kfree(src);
+}
+
+/**
+ * stm_source_register_device() - register an stm_source device
+ * @parent: parent device
+ * @data: device description structure
+ *
+ * This will create a device of stm_source class that can write
+ * data to an stm device once linked.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int stm_source_register_device(struct device *parent,
+ struct stm_source_data *data)
+{
+ struct stm_source_device *src;
+ int err;
+
+ if (!stm_core_up)
+ return -EPROBE_DEFER;
+
+ src = kzalloc(sizeof(*src), GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+
+ device_initialize(&src->dev);
+ src->dev.class = &stm_source_class;
+ src->dev.parent = parent;
+ src->dev.release = stm_source_device_release;
+
+ err = kobject_set_name(&src->dev.kobj, "%s", data->name);
+ if (err)
+ goto err;
+
+ err = device_add(&src->dev);
+ if (err)
+ goto err;
+
+ spin_lock_init(&src->link_lock);
+ INIT_LIST_HEAD(&src->link_entry);
+ src->data = data;
+ data->src = src;
+
+ return 0;
+
+err:
+ put_device(&src->dev);
+ kfree(src);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(stm_source_register_device);
+
+/**
+ * stm_source_unregister_device() - unregister an stm_source device
+ * @data: device description that was used to register the device
+ *
+ * This will remove a previously created stm_source device from the system.
+ */
+void stm_source_unregister_device(struct stm_source_data *data)
+{
+ struct stm_source_device *src = data->src;
+
+ stm_source_link_drop(src);
+
+ device_destroy(&stm_source_class, src->dev.devt);
+}
+EXPORT_SYMBOL_GPL(stm_source_unregister_device);
+
+int stm_source_write(struct stm_source_data *data, unsigned int chan,
+ const char *buf, size_t count)
+{
+ struct stm_source_device *src = data->src;
+ struct stm_device *stm;
+ int idx;
+
+ if (!src->output.nr_chans)
+ return -ENODEV;
+
+ if (chan >= src->output.nr_chans)
+ return -EINVAL;
+
+ idx = srcu_read_lock(&stm_source_srcu);
+
+ stm = srcu_dereference(src->link, &stm_source_srcu);
+ if (stm)
+ stm_write(stm->data, src->output.master,
+ src->output.channel + chan,
+ buf, count);
+ else
+ count = -ENODEV;
+
+ srcu_read_unlock(&stm_source_srcu, idx);
+
+ return count;
+}
+EXPORT_SYMBOL_GPL(stm_source_write);
+
+static int __init stm_core_init(void)
+{
+ int err;
+
+ err = class_register(&stm_class);
+ if (err)
+ return err;
+
+ err = class_register(&stm_source_class);
+ if (err)
+ goto err_stm;
+
+ err = stp_configfs_init();
+ if (err)
+ goto err_src;
+
+ init_srcu_struct(&stm_source_srcu);
+
+ stm_core_up++;
+
+ return 0;
+
+err_src:
+ class_unregister(&stm_source_class);
+err_stm:
+ class_unregister(&stm_class);
+
+ return err;
+}
+
+module_init(stm_core_init);
+
+static void __exit stm_core_exit(void)
+{
+ cleanup_srcu_struct(&stm_source_srcu);
+ class_unregister(&stm_source_class);
+ class_unregister(&stm_class);
+ stp_configfs_exit();
+}
+
+module_exit(stm_core_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("System Trace Module device class");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/stm/dummy_stm.c b/drivers/hwtracing/stm/dummy_stm.c
new file mode 100644
index 000000000000..3709bef0b21f
--- /dev/null
+++ b/drivers/hwtracing/stm/dummy_stm.c
@@ -0,0 +1,66 @@
+/*
+ * A dummy STM device for stm/stm_source class testing.
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * STM class implements generic infrastructure for System Trace Module devices
+ * as defined in MIPI STPv2 specification.
+ */
+
+#undef DEBUG
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+
+static ssize_t
+dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
+ unsigned int channel, unsigned int packet, unsigned int flags,
+ unsigned int size, const unsigned char *payload)
+{
+#ifdef DEBUG
+ u64 pl = 0;
+
+ if (payload)
+ pl = *(u64 *)payload;
+
+ if (size < 8)
+ pl &= (1ull << (size * 8)) - 1;
+ trace_printk("[%u:%u] [pkt: %x/%x] (%llx)\n", master, channel,
+ packet, size, pl);
+#endif
+ return size;
+}
+
+static struct stm_data dummy_stm = {
+ .name = "dummy_stm",
+ .sw_start = 0x0000,
+ .sw_end = 0xffff,
+ .sw_nchannels = 0xffff,
+ .packet = dummy_stm_packet,
+};
+
+static int dummy_stm_init(void)
+{
+ return stm_register_device(NULL, &dummy_stm, THIS_MODULE);
+}
+
+static void dummy_stm_exit(void)
+{
+ stm_unregister_device(&dummy_stm);
+}
+
+module_init(dummy_stm_init);
+module_exit(dummy_stm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("dummy_stm device");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c
new file mode 100644
index 000000000000..11ab6d01adf6
--- /dev/null
+++ b/drivers/hwtracing/stm/policy.c
@@ -0,0 +1,472 @@
+/*
+ * System Trace Module (STM) master/channel allocation policy management
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * A master/channel allocation policy allows mapping string identifiers to
+ * master and channel ranges, where allocation can be done.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/configfs.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+#include "stm.h"
+
+/*
+ * STP Master/Channel allocation policy configfs layout.
+ */
+
+struct stp_policy {
+ struct config_group group;
+ struct stm_device *stm;
+};
+
+struct stp_policy_node {
+ struct config_group group;
+ struct stp_policy *policy;
+ unsigned int first_master;
+ unsigned int last_master;
+ unsigned int first_channel;
+ unsigned int last_channel;
+};
+
+static struct configfs_subsystem stp_policy_subsys;
+
+void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
+ unsigned int *mstart, unsigned int *mend,
+ unsigned int *cstart, unsigned int *cend)
+{
+ *mstart = policy_node->first_master;
+ *mend = policy_node->last_master;
+ *cstart = policy_node->first_channel;
+ *cend = policy_node->last_channel;
+}
+
+static inline char *stp_policy_node_name(struct stp_policy_node *policy_node)
+{
+ return policy_node->group.cg_item.ci_name ? : "<none>";
+}
+
+static inline struct stp_policy *to_stp_policy(struct config_item *item)
+{
+ return item ?
+ container_of(to_config_group(item), struct stp_policy, group) :
+ NULL;
+}
+
+static inline struct stp_policy_node *
+to_stp_policy_node(struct config_item *item)
+{
+ return item ?
+ container_of(to_config_group(item), struct stp_policy_node,
+ group) :
+ NULL;
+}
+
+static ssize_t
+stp_policy_node_masters_show(struct config_item *item, char *page)
+{
+ struct stp_policy_node *policy_node = to_stp_policy_node(item);
+ ssize_t count;
+
+ count = sprintf(page, "%u %u\n", policy_node->first_master,
+ policy_node->last_master);
+
+ return count;
+}
+
+static ssize_t
+stp_policy_node_masters_store(struct config_item *item, const char *page,
+ size_t count)
+{
+ struct stp_policy_node *policy_node = to_stp_policy_node(item);
+ unsigned int first, last;
+ struct stm_device *stm;
+ char *p = (char *)page;
+ ssize_t ret = -ENODEV;
+
+ if (sscanf(p, "%u %u", &first, &last) != 2)
+ return -EINVAL;
+
+ mutex_lock(&stp_policy_subsys.su_mutex);
+ stm = policy_node->policy->stm;
+ if (!stm)
+ goto unlock;
+
+ /* must be within [sw_start..sw_end], which is an inclusive range */
+ if (first > INT_MAX || last > INT_MAX || first > last ||
+ first < stm->data->sw_start ||
+ last > stm->data->sw_end) {
+ ret = -ERANGE;
+ goto unlock;
+ }
+
+ ret = count;
+ policy_node->first_master = first;
+ policy_node->last_master = last;
+
+unlock:
+ mutex_unlock(&stp_policy_subsys.su_mutex);
+
+ return ret;
+}
+
+static ssize_t
+stp_policy_node_channels_show(struct config_item *item, char *page)
+{
+ struct stp_policy_node *policy_node = to_stp_policy_node(item);
+ ssize_t count;
+
+ count = sprintf(page, "%u %u\n", policy_node->first_channel,
+ policy_node->last_channel);
+
+ return count;
+}
+
+static ssize_t
+stp_policy_node_channels_store(struct config_item *item, const char *page,
+ size_t count)
+{
+ struct stp_policy_node *policy_node = to_stp_policy_node(item);
+ unsigned int first, last;
+ struct stm_device *stm;
+ char *p = (char *)page;
+ ssize_t ret = -ENODEV;
+
+ if (sscanf(p, "%u %u", &first, &last) != 2)
+ return -EINVAL;
+
+ mutex_lock(&stp_policy_subsys.su_mutex);
+ stm = policy_node->policy->stm;
+ if (!stm)
+ goto unlock;
+
+ if (first > INT_MAX || last > INT_MAX || first > last ||
+ last >= stm->data->sw_nchannels) {
+ ret = -ERANGE;
+ goto unlock;
+ }
+
+ ret = count;
+ policy_node->first_channel = first;
+ policy_node->last_channel = last;
+
+unlock:
+ mutex_unlock(&stp_policy_subsys.su_mutex);
+
+ return ret;
+}
+
+static void stp_policy_node_release(struct config_item *item)
+{
+ kfree(to_stp_policy_node(item));
+}
+
+static struct configfs_item_operations stp_policy_node_item_ops = {
+ .release = stp_policy_node_release,
+};
+
+CONFIGFS_ATTR(stp_policy_node_, masters);
+CONFIGFS_ATTR(stp_policy_node_, channels);
+
+static struct configfs_attribute *stp_policy_node_attrs[] = {
+ &stp_policy_node_attr_masters,
+ &stp_policy_node_attr_channels,
+ NULL,
+};
+
+static struct config_item_type stp_policy_type;
+static struct config_item_type stp_policy_node_type;
+
+static struct config_group *
+stp_policy_node_make(struct config_group *group, const char *name)
+{
+ struct stp_policy_node *policy_node, *parent_node;
+ struct stp_policy *policy;
+
+ if (group->cg_item.ci_type == &stp_policy_type) {
+ policy = container_of(group, struct stp_policy, group);
+ } else {
+ parent_node = container_of(group, struct stp_policy_node,
+ group);
+ policy = parent_node->policy;
+ }
+
+ if (!policy->stm)
+ return ERR_PTR(-ENODEV);
+
+ policy_node = kzalloc(sizeof(struct stp_policy_node), GFP_KERNEL);
+ if (!policy_node)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&policy_node->group, name,
+ &stp_policy_node_type);
+
+ policy_node->policy = policy;
+
+ /* default values for the attributes */
+ policy_node->first_master = policy->stm->data->sw_start;
+ policy_node->last_master = policy->stm->data->sw_end;
+ policy_node->first_channel = 0;
+ policy_node->last_channel = policy->stm->data->sw_nchannels - 1;
+
+ return &policy_node->group;
+}
+
+static void
+stp_policy_node_drop(struct config_group *group, struct config_item *item)
+{
+ config_item_put(item);
+}
+
+static struct configfs_group_operations stp_policy_node_group_ops = {
+ .make_group = stp_policy_node_make,
+ .drop_item = stp_policy_node_drop,
+};
+
+static struct config_item_type stp_policy_node_type = {
+ .ct_item_ops = &stp_policy_node_item_ops,
+ .ct_group_ops = &stp_policy_node_group_ops,
+ .ct_attrs = stp_policy_node_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/*
+ * Root group: policies.
+ */
+static ssize_t stp_policy_device_show(struct config_item *item,
+ char *page)
+{
+ struct stp_policy *policy = to_stp_policy(item);
+ ssize_t count;
+
+ count = sprintf(page, "%s\n",
+ (policy && policy->stm) ?
+ policy->stm->data->name :
+ "<none>");
+
+ return count;
+}
+
+CONFIGFS_ATTR_RO(stp_policy_, device);
+
+static struct configfs_attribute *stp_policy_attrs[] = {
+ &stp_policy_attr_device,
+ NULL,
+};
+
+void stp_policy_unbind(struct stp_policy *policy)
+{
+ struct stm_device *stm = policy->stm;
+
+ if (WARN_ON_ONCE(!policy->stm))
+ return;
+
+ mutex_lock(&stm->policy_mutex);
+ stm->policy = NULL;
+ mutex_unlock(&stm->policy_mutex);
+
+ policy->stm = NULL;
+
+ stm_put_device(stm);
+}
+
+static void stp_policy_release(struct config_item *item)
+{
+ struct stp_policy *policy = to_stp_policy(item);
+
+ stp_policy_unbind(policy);
+ kfree(policy);
+}
+
+static struct configfs_item_operations stp_policy_item_ops = {
+ .release = stp_policy_release,
+};
+
+static struct configfs_group_operations stp_policy_group_ops = {
+ .make_group = stp_policy_node_make,
+};
+
+static struct config_item_type stp_policy_type = {
+ .ct_item_ops = &stp_policy_item_ops,
+ .ct_group_ops = &stp_policy_group_ops,
+ .ct_attrs = stp_policy_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *
+stp_policies_make(struct config_group *group, const char *name)
+{
+ struct config_group *ret;
+ struct stm_device *stm;
+ char *devname, *p;
+
+ devname = kasprintf(GFP_KERNEL, "%s", name);
+ if (!devname)
+ return ERR_PTR(-ENOMEM);
+
+ /*
+ * node must look like <device_name>.<policy_name>, where
+ * <device_name> is the name of an existing stm device and
+ * <policy_name> is an arbitrary string
+ */
+ p = strchr(devname, '.');
+ if (!p) {
+ kfree(devname);
+ return ERR_PTR(-EINVAL);
+ }
+
+ *p++ = '\0';
+
+ stm = stm_find_device(devname);
+ kfree(devname);
+
+ if (!stm)
+ return ERR_PTR(-ENODEV);
+
+ mutex_lock(&stm->policy_mutex);
+ if (stm->policy) {
+ ret = ERR_PTR(-EBUSY);
+ goto unlock_policy;
+ }
+
+ stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL);
+ if (!stm->policy) {
+ ret = ERR_PTR(-ENOMEM);
+ goto unlock_policy;
+ }
+
+ config_group_init_type_name(&stm->policy->group, name,
+ &stp_policy_type);
+ stm->policy->stm = stm;
+
+ ret = &stm->policy->group;
+
+unlock_policy:
+ mutex_unlock(&stm->policy_mutex);
+
+ if (IS_ERR(ret))
+ stm_put_device(stm);
+
+ return ret;
+}
+
+static struct configfs_group_operations stp_policies_group_ops = {
+ .make_group = stp_policies_make,
+};
+
+static struct config_item_type stp_policies_type = {
+ .ct_group_ops = &stp_policies_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem stp_policy_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "stp-policy",
+ .ci_type = &stp_policies_type,
+ },
+ },
+};
+
+/*
+ * Lock the policy mutex from the outside
+ */
+static struct stp_policy_node *
+__stp_policy_node_lookup(struct stp_policy *policy, char *s)
+{
+ struct stp_policy_node *policy_node, *ret;
+ struct list_head *head = &policy->group.cg_children;
+ struct config_item *item;
+ char *start, *end = s;
+
+ if (list_empty(head))
+ return NULL;
+
+ /* return the first entry if everything else fails */
+ item = list_entry(head->next, struct config_item, ci_entry);
+ ret = to_stp_policy_node(item);
+
+next:
+ for (;;) {
+ start = strsep(&end, "/");
+ if (!start)
+ break;
+
+ if (!*start)
+ continue;
+
+ list_for_each_entry(item, head, ci_entry) {
+ policy_node = to_stp_policy_node(item);
+
+ if (!strcmp(start,
+ policy_node->group.cg_item.ci_name)) {
+ ret = policy_node;
+
+ if (!end)
+ goto out;
+
+ head = &policy_node->group.cg_children;
+ goto next;
+ }
+ }
+ break;
+ }
+
+out:
+ return ret;
+}
+
+
+struct stp_policy_node *
+stp_policy_node_lookup(struct stm_device *stm, char *s)
+{
+ struct stp_policy_node *policy_node = NULL;
+
+ mutex_lock(&stp_policy_subsys.su_mutex);
+
+ mutex_lock(&stm->policy_mutex);
+ if (stm->policy)
+ policy_node = __stp_policy_node_lookup(stm->policy, s);
+ mutex_unlock(&stm->policy_mutex);
+
+ if (policy_node)
+ config_item_get(&policy_node->group.cg_item);
+ mutex_unlock(&stp_policy_subsys.su_mutex);
+
+ return policy_node;
+}
+
+void stp_policy_node_put(struct stp_policy_node *policy_node)
+{
+ config_item_put(&policy_node->group.cg_item);
+}
+
+int __init stp_configfs_init(void)
+{
+ int err;
+
+ config_group_init(&stp_policy_subsys.su_group);
+ mutex_init(&stp_policy_subsys.su_mutex);
+ err = configfs_register_subsystem(&stp_policy_subsys);
+
+ return err;
+}
+
+void __exit stp_configfs_exit(void)
+{
+ configfs_unregister_subsystem(&stp_policy_subsys);
+}
diff --git a/drivers/hwtracing/stm/stm.h b/drivers/hwtracing/stm/stm.h
new file mode 100644
index 000000000000..95ece0292c99
--- /dev/null
+++ b/drivers/hwtracing/stm/stm.h
@@ -0,0 +1,87 @@
+/*
+ * System Trace Module (STM) infrastructure
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * STM class implements generic infrastructure for System Trace Module devices
+ * as defined in MIPI STPv2 specification.
+ */
+
+#ifndef _STM_STM_H_
+#define _STM_STM_H_
+
+struct stp_policy;
+struct stp_policy_node;
+
+struct stp_policy_node *
+stp_policy_node_lookup(struct stm_device *stm, char *s);
+void stp_policy_node_put(struct stp_policy_node *policy_node);
+void stp_policy_unbind(struct stp_policy *policy);
+
+void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
+ unsigned int *mstart, unsigned int *mend,
+ unsigned int *cstart, unsigned int *cend);
+int stp_configfs_init(void);
+void stp_configfs_exit(void);
+
+struct stp_master {
+ unsigned int nr_free;
+ unsigned long chan_map[0];
+};
+
+struct stm_device {
+ struct device dev;
+ struct module *owner;
+ struct stp_policy *policy;
+ struct mutex policy_mutex;
+ int major;
+ unsigned int sw_nmasters;
+ struct stm_data *data;
+ spinlock_t link_lock;
+ struct list_head link_list;
+ /* master allocation */
+ spinlock_t mc_lock;
+ struct stp_master *masters[0];
+};
+
+#define to_stm_device(_d) \
+ container_of((_d), struct stm_device, dev)
+
+struct stm_output {
+ unsigned int master;
+ unsigned int channel;
+ unsigned int nr_chans;
+};
+
+struct stm_file {
+ struct stm_device *stm;
+ struct stp_policy_node *policy_node;
+ struct stm_output output;
+};
+
+struct stm_device *stm_find_device(const char *name);
+void stm_put_device(struct stm_device *stm);
+
+struct stm_source_device {
+ struct device dev;
+ struct stm_source_data *data;
+ spinlock_t link_lock;
+ struct stm_device __rcu *link;
+ struct list_head link_entry;
+ /* one output per stm_source device */
+ struct stp_policy_node *policy_node;
+ struct stm_output output;
+};
+
+#define to_stm_source_device(_d) \
+ container_of((_d), struct stm_source_device, dev)
+
+#endif /* _STM_STM_H_ */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 08b86178e8fb..7b0aa82ea38b 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -124,6 +124,9 @@ config I2C_I801
BayTrail (SOC)
Sunrise Point-H (PCH)
Sunrise Point-LP (PCH)
+ DNV (SOC)
+ Broxton (SOC)
+ Lewisburg (PCH)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
@@ -422,7 +425,7 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
config I2C_CADENCE
tristate "Cadence I2C Controller"
- depends on ARCH_ZYNQ
+ depends on ARCH_ZYNQ || ARM64
help
Say yes here to select Cadence I2C Host Controller. This controller is
e.g. used by Xilinx Zynq.
@@ -582,10 +585,10 @@ config I2C_IMG
config I2C_IMX
tristate "IMX I2C interface"
- depends on ARCH_MXC
+ depends on ARCH_MXC || ARCH_LAYERSCAPE
help
Say Y here if you want to use the IIC bus controller on
- the Freescale i.MX/MXC processors.
+ the Freescale i.MX/MXC or Layerscape processors.
This driver can also be built as a module. If so, the module
will be called i2c-imx.
@@ -902,6 +905,22 @@ config I2C_TEGRA
If you say yes to this option, support will be included for the
I2C controller embedded in NVIDIA Tegra SOCs
+config I2C_UNIPHIER
+ tristate "UniPhier FIFO-less I2C controller"
+ depends on ARCH_UNIPHIER
+ help
+ If you say yes to this option, support will be included for
+ the UniPhier FIFO-less I2C interface embedded in PH1-LD4, PH1-sLD8,
+ or older UniPhier SoCs.
+
+config I2C_UNIPHIER_F
+ tristate "UniPhier FIFO-builtin I2C controller"
+ depends on ARCH_UNIPHIER
+ help
+ If you say yes to this option, support will be included for
+ the UniPhier FIFO-builtin I2C interface embedded in PH1-Pro4,
+ PH1-Pro5, or newer UniPhier SoCs.
+
config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support"
depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 6df3b303bd09..37f2819b4560 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -87,6 +87,8 @@ obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
+obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
+obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 1c758cd1e1ba..10835d1f559b 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -347,8 +347,14 @@ error:
static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
{
- if (!dev->buf_len)
+ /*
+ * If we are in this case, it means there is garbage data in RHR, so
+ * delete them.
+ */
+ if (!dev->buf_len) {
+ at91_twi_read(dev, AT91_TWI_RHR);
return;
+ }
/* 8bit read works with and without FIFO */
*dev->buf = readb_relaxed(dev->base + AT91_TWI_RHR);
@@ -465,19 +471,73 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
if (!irqstatus)
return IRQ_NONE;
- else if (irqstatus & AT91_TWI_RXRDY)
+ /*
+ * In reception, the behavior of the twi device (before sama5d2) is
+ * weird. There is some magic about RXRDY flag! When a data has been
+ * almost received, the reception of a new one is anticipated if there
+ * is no stop command to send. That is the reason why ask for sending
+ * the stop command not on the last data but on the second last one.
+ *
+ * Unfortunately, we could still have the RXRDY flag set even if the
+ * transfer is done and we have read the last data. It might happen
+ * when the i2c slave device sends too quickly data after receiving the
+ * ack from the master. The data has been almost received before having
+ * the order to send stop. In this case, sending the stop command could
+ * cause a RXRDY interrupt with a TXCOMP one. It is better to manage
+ * the RXRDY interrupt first in order to not keep garbage data in the
+ * Receive Holding Register for the next transfer.
+ */
+ if (irqstatus & AT91_TWI_RXRDY)
at91_twi_read_next_byte(dev);
- else if (irqstatus & AT91_TWI_TXRDY)
- at91_twi_write_next_byte(dev);
-
- /* catch error flags */
- dev->transfer_status |= status;
+ /*
+ * When a NACK condition is detected, the I2C controller sets the NACK,
+ * TXCOMP and TXRDY bits all together in the Status Register (SR).
+ *
+ * 1 - Handling NACK errors with CPU write transfer.
+ *
+ * In such case, we should not write the next byte into the Transmit
+ * Holding Register (THR) otherwise the I2C controller would start a new
+ * transfer and the I2C slave is likely to reply by another NACK.
+ *
+ * 2 - Handling NACK errors with DMA write transfer.
+ *
+ * By setting the TXRDY bit in the SR, the I2C controller also triggers
+ * the DMA controller to write the next data into the THR. Then the
+ * result depends on the hardware version of the I2C controller.
+ *
+ * 2a - Without support of the Alternative Command mode.
+ *
+ * This is the worst case: the DMA controller is triggered to write the
+ * next data into the THR, hence starting a new transfer: the I2C slave
+ * is likely to reply by another NACK.
+ * Concurrently, this interrupt handler is likely to be called to manage
+ * the first NACK before the I2C controller detects the second NACK and
+ * sets once again the NACK bit into the SR.
+ * When handling the first NACK, this interrupt handler disables the I2C
+ * controller interruptions, especially the NACK interrupt.
+ * Hence, the NACK bit is pending into the SR. This is why we should
+ * read the SR to clear all pending interrupts at the beginning of
+ * at91_do_twi_transfer() before actually starting a new transfer.
+ *
+ * 2b - With support of the Alternative Command mode.
+ *
+ * When a NACK condition is detected, the I2C controller also locks the
+ * THR (and sets the LOCK bit in the SR): even though the DMA controller
+ * is triggered by the TXRDY bit to write the next data into the THR,
+ * this data actually won't go on the I2C bus hence a second NACK is not
+ * generated.
+ */
if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) {
at91_disable_twi_interrupts(dev);
complete(&dev->cmd_complete);
+ } else if (irqstatus & AT91_TWI_TXRDY) {
+ at91_twi_write_next_byte(dev);
}
+ /* catch error flags */
+ dev->transfer_status |= status;
+
return IRQ_HANDLED;
}
@@ -537,6 +597,9 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
reinit_completion(&dev->cmd_complete);
dev->transfer_status = 0;
+ /* Clear pending interrupts, such as NACK. */
+ at91_twi_read(dev, AT91_TWI_SR);
+
if (dev->fifo_size) {
unsigned fifo_mr = at91_twi_read(dev, AT91_TWI_FMR);
@@ -558,11 +621,6 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
} else if (dev->msg->flags & I2C_M_RD) {
unsigned start_flags = AT91_TWI_START;
- if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
- dev_err(dev->dev, "RXRDY still set!");
- at91_twi_read(dev, AT91_TWI_RHR);
- }
-
/* if only one byte is to be read, immediately stop transfer */
if (!has_alt_cmd && dev->buf_len <= 1 &&
!(dev->msg->flags & I2C_M_RECV_LEN))
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index a6aae84e5706..5bcb1f0bb334 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -48,7 +48,6 @@ struct i2c_au1550_data {
void __iomem *psc_base;
int xfer_timeout;
struct i2c_adapter adap;
- struct resource *ioarea;
};
static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
@@ -284,10 +283,10 @@ static void i2c_au1550_setup(struct i2c_au1550_data *priv)
/* Set the protocol timer values. See Table 71 in the
* Au1550 Data Book for standard timing values.
*/
- WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
- PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
- PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
- PSC_SMBTMR_SET_CH(15));
+ WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(20) | \
+ PSC_SMBTMR_SET_PU(20) | PSC_SMBTMR_SET_SH(20) | \
+ PSC_SMBTMR_SET_SU(20) | PSC_SMBTMR_SET_CL(20) | \
+ PSC_SMBTMR_SET_CH(20));
cfg |= PSC_SMBCFG_DE_ENABLE;
WR(priv, PSC_SMBCFG, cfg);
@@ -315,30 +314,16 @@ i2c_au1550_probe(struct platform_device *pdev)
struct resource *r;
int ret;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- ret = -ENODEV;
- goto out;
- }
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
- if (!priv) {
- ret = -ENOMEM;
- goto out;
- }
-
- priv->ioarea = request_mem_region(r->start, resource_size(r),
- pdev->name);
- if (!priv->ioarea) {
- ret = -EBUSY;
- goto out_mem;
- }
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->psc_base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(priv->psc_base))
+ return PTR_ERR(priv->psc_base);
- priv->psc_base = ioremap(r->start, resource_size(r));
- if (!priv->psc_base) {
- ret = -EIO;
- goto out_map;
- }
priv->xfer_timeout = 200;
priv->adap.nr = pdev->id;
@@ -351,20 +336,13 @@ i2c_au1550_probe(struct platform_device *pdev)
i2c_au1550_setup(priv);
ret = i2c_add_numbered_adapter(&priv->adap);
- if (ret == 0) {
- platform_set_drvdata(pdev, priv);
- return 0;
+ if (ret) {
+ i2c_au1550_disable(priv);
+ return ret;
}
- i2c_au1550_disable(priv);
- iounmap(priv->psc_base);
-out_map:
- release_resource(priv->ioarea);
- kfree(priv->ioarea);
-out_mem:
- kfree(priv);
-out:
- return ret;
+ platform_set_drvdata(pdev, priv);
+ return 0;
}
static int i2c_au1550_remove(struct platform_device *pdev)
@@ -373,10 +351,6 @@ static int i2c_au1550_remove(struct platform_device *pdev)
i2c_del_adapter(&priv->adap);
i2c_au1550_disable(priv);
- iounmap(priv->psc_base);
- release_resource(priv->ioarea);
- kfree(priv->ioarea);
- kfree(priv);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 3fbb9a035532..c5628a42170a 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -181,6 +181,7 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
u32 clkh;
u32 clkl;
u32 input_clock = clk_get_rate(dev->clk);
+ struct device_node *of_node = dev->dev->of_node;
/* NOTE: I2C Clock divider programming info
* As per I2C specs the following formulas provide prescaler
@@ -196,6 +197,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
* where if PSC == 0, d = 7,
* if PSC == 1, d = 6
* if PSC > 1 , d = 5
+ *
+ * Note:
+ * d is always 6 on Keystone I2C controller
*/
/* get minimum of 7 MHz clock, but max of 12 MHz */
@@ -204,6 +208,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
psc++; /* better to run under spec than over */
d = (psc >= 2) ? 5 : 7 - psc;
+ if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c"))
+ d = 6;
+
clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000));
/* Avoid driving the bus too fast because of rounding errors above */
if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000)
@@ -726,6 +733,7 @@ static struct i2c_algorithm i2c_davinci_algo = {
static const struct of_device_id davinci_i2c_of_match[] = {
{.compatible = "ti,davinci-i2c", },
+ {.compatible = "ti,keystone-i2c", },
{},
};
MODULE_DEVICE_TABLE(of, davinci_i2c_of_match);
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 7441cdc1b34a..8c48b27ba059 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -165,7 +165,7 @@ static char *abort_sources[] = {
"lost arbitration",
};
-u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+static u32 dw_readl(struct dw_i2c_dev *dev, int offset)
{
u32 value;
@@ -181,7 +181,7 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset)
return value;
}
-void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
{
if (dev->accessor_flags & ACCESS_SWAP)
b = swab32(b);
@@ -438,7 +438,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
__i2c_dw_enable(dev, true);
/* Clear and enable interrupts */
- i2c_dw_clear_int(dev);
+ dw_readl(dev, DW_IC_CLR_INTR);
dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
}
@@ -618,7 +618,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
/*
* Prepare controller for a transaction and call i2c_dw_xfer_msg
*/
-int
+static int
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
@@ -702,14 +702,17 @@ done_nolock:
return ret;
}
-EXPORT_SYMBOL_GPL(i2c_dw_xfer);
-u32 i2c_dw_func(struct i2c_adapter *adap)
+static u32 i2c_dw_func(struct i2c_adapter *adap)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
return dev->functionality;
}
-EXPORT_SYMBOL_GPL(i2c_dw_func);
+
+static struct i2c_algorithm i2c_dw_algo = {
+ .master_xfer = i2c_dw_xfer,
+ .functionality = i2c_dw_func,
+};
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
{
@@ -770,7 +773,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
* Interrupt service routine. This gets called whenever an I2C interrupt
* occurs.
*/
-irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
{
struct dw_i2c_dev *dev = dev_id;
u32 stat, enabled;
@@ -813,20 +816,6 @@ tx_aborted:
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_GPL(i2c_dw_isr);
-
-void i2c_dw_enable(struct dw_i2c_dev *dev)
-{
- /* Enable the adapter */
- __i2c_dw_enable(dev, true);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_enable);
-
-u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
-{
- return dw_readl(dev, DW_IC_ENABLE);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
void i2c_dw_disable(struct dw_i2c_dev *dev)
{
@@ -839,12 +828,6 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
}
EXPORT_SYMBOL_GPL(i2c_dw_disable);
-void i2c_dw_clear_int(struct dw_i2c_dev *dev)
-{
- dw_readl(dev, DW_IC_CLR_INTR);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_clear_int);
-
void i2c_dw_disable_int(struct dw_i2c_dev *dev)
{
dw_writel(dev, 0, DW_IC_INTR_MASK);
@@ -857,5 +840,40 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
}
EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
+int i2c_dw_probe(struct dw_i2c_dev *dev)
+{
+ struct i2c_adapter *adap = &dev->adapter;
+ int r;
+
+ init_completion(&dev->cmd_complete);
+ mutex_init(&dev->lock);
+
+ r = i2c_dw_init(dev);
+ if (r)
+ return r;
+
+ snprintf(adap->name, sizeof(adap->name),
+ "Synopsys DesignWare I2C adapter");
+ adap->algo = &i2c_dw_algo;
+ adap->dev.parent = dev->dev;
+ i2c_set_adapdata(adap, dev);
+
+ i2c_dw_disable_int(dev);
+ r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
+ dev_name(dev->dev), dev);
+ if (r) {
+ dev_err(dev->dev, "failure requesting irq %i: %d\n",
+ dev->irq, r);
+ return r;
+ }
+
+ r = i2c_add_numbered_adapter(adap);
+ if (r)
+ dev_err(dev->dev, "failure adding adapter: %d\n", r);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(i2c_dw_probe);
+
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 9630222abf32..1d50898e7b24 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -112,19 +112,11 @@ struct dw_i2c_dev {
#define ACCESS_SWAP 0x00000001
#define ACCESS_16BIT 0x00000002
-extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
-extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
extern int i2c_dw_init(struct dw_i2c_dev *dev);
-extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
- int num);
-extern u32 i2c_dw_func(struct i2c_adapter *adap);
-extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
-extern void i2c_dw_enable(struct dw_i2c_dev *dev);
-extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
extern void i2c_dw_disable(struct dw_i2c_dev *dev);
-extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
+extern int i2c_dw_probe(struct dw_i2c_dev *dev);
#if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL)
extern int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index df23e8c30e6f..1543d35d228d 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
+#include <linux/acpi.h>
#include "i2c-designware-core.h"
#define DRIVER_NAME "i2c-designware-pci"
@@ -158,11 +159,6 @@ static struct dw_pci_controller dw_pci_controllers[] = {
},
};
-static struct i2c_algorithm i2c_dw_algo = {
- .master_xfer = i2c_dw_xfer,
- .functionality = i2c_dw_func,
-};
-
#ifdef CONFIG_PM
static int i2c_dw_pci_suspend(struct device *dev)
{
@@ -222,13 +218,12 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
if (!dev)
return -ENOMEM;
- init_completion(&dev->cmd_complete);
- mutex_init(&dev->lock);
dev->clk = NULL;
dev->controller = controller;
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
dev->base = pcim_iomap_table(pdev)[0];
dev->dev = &pdev->dev;
+ dev->irq = pdev->irq;
dev->functionality = controller->functionality |
DW_DEFAULT_FUNCTIONALITY;
@@ -246,34 +241,16 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
dev->tx_fifo_depth = controller->tx_fifo_depth;
dev->rx_fifo_depth = controller->rx_fifo_depth;
- r = i2c_dw_init(dev);
- if (r)
- return r;
adap = &dev->adapter;
- i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
adap->class = 0;
- adap->algo = &i2c_dw_algo;
- adap->dev.parent = &pdev->dev;
+ ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->nr = controller->bus_num;
- snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci");
-
- r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr,
- IRQF_SHARED | IRQF_COND_SUSPEND, adap->name, dev);
- if (r) {
- dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
- return r;
- }
-
- i2c_dw_disable_int(dev);
- i2c_dw_clear_int(dev);
- r = i2c_add_numbered_adapter(adap);
- if (r) {
- dev_err(&pdev->dev, "failure adding adapter\n");
+ r = i2c_dw_probe(dev);
+ if (r)
return r;
- }
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev);
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3dd2de31a2f8..809579ecb5a4 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -41,16 +42,28 @@
#include <linux/platform_data/i2c-designware.h>
#include "i2c-designware-core.h"
-static struct i2c_algorithm i2c_dw_algo = {
- .master_xfer = i2c_dw_xfer,
- .functionality = i2c_dw_func,
-};
static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
{
return clk_get_rate(dev->clk)/1000;
}
#ifdef CONFIG_ACPI
+/*
+ * The HCNT/LCNT information coming from ACPI should be the most accurate
+ * for given platform. However, some systems get it wrong. On such systems
+ * we get better results by calculating those based on the input clock.
+ */
+static const struct dmi_system_id dw_i2c_no_acpi_params[] = {
+ {
+ .ident = "Dell Inspiron 7348",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"),
+ },
+ },
+ { }
+};
+
static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
u16 *hcnt, u16 *lcnt, u32 *sda_hold)
{
@@ -58,6 +71,9 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
acpi_handle handle = ACPI_HANDLE(&pdev->dev);
union acpi_object *obj;
+ if (dmi_check_system(dw_i2c_no_acpi_params))
+ return;
+
if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
return;
@@ -77,7 +93,6 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
static int dw_i2c_acpi_configure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
- const struct acpi_device_id *id;
dev->adapter.nr = -1;
dev->tx_fifo_depth = 32;
@@ -91,29 +106,9 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
&dev->sda_hold_time);
- /*
- * Provide a way for Designware I2C host controllers that are not
- * based on Intel LPSS to specify their input clock frequency via
- * id->driver_data.
- */
- id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
- if (id && id->driver_data)
- clk_register_fixed_rate(&pdev->dev, dev_name(&pdev->dev), NULL,
- CLK_IS_ROOT, id->driver_data);
-
return 0;
}
-static void dw_i2c_acpi_unconfigure(struct platform_device *pdev)
-{
- struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
- const struct acpi_device_id *id;
-
- id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
- if (id && id->driver_data)
- clk_unregister(dev->clk);
-}
-
static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT33C2", 0 },
{ "INT33C3", 0 },
@@ -121,7 +116,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT3433", 0 },
{ "80860F41", 0 },
{ "808622C1", 0 },
- { "AMD0010", 133 * 1000 * 1000 },
+ { "AMD0010", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -130,10 +125,9 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
{
return -ENODEV;
}
-static inline void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { }
#endif
-static int dw_i2c_probe(struct platform_device *pdev)
+static int dw_i2c_plat_probe(struct platform_device *pdev)
{
struct dw_i2c_dev *dev;
struct i2c_adapter *adap;
@@ -155,8 +149,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
if (IS_ERR(dev->base))
return PTR_ERR(dev->base);
- init_completion(&dev->cmd_complete);
- mutex_init(&dev->lock);
dev->dev = &pdev->dev;
dev->irq = irq;
platform_set_drvdata(pdev, dev);
@@ -231,34 +223,13 @@ static int dw_i2c_probe(struct platform_device *pdev)
dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1;
dev->adapter.nr = pdev->id;
}
- r = i2c_dw_init(dev);
- if (r)
- return r;
-
- i2c_dw_disable_int(dev);
- r = devm_request_irq(&pdev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
- pdev->name, dev);
- if (r) {
- dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
- return r;
- }
adap = &dev->adapter;
- i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_DEPRECATED;
- strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
- sizeof(adap->name));
- adap->algo = &i2c_dw_algo;
- adap->dev.parent = &pdev->dev;
+ ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->dev.of_node = pdev->dev.of_node;
- r = i2c_add_numbered_adapter(adap);
- if (r) {
- dev_err(&pdev->dev, "failure adding adapter\n");
- return r;
- }
-
if (dev->pm_runtime_disabled) {
pm_runtime_forbid(&pdev->dev);
} else {
@@ -268,10 +239,16 @@ static int dw_i2c_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
}
+ r = i2c_dw_probe(dev);
+ if (r) {
+ pm_runtime_disable(&pdev->dev);
+ return r;
+ }
+
return 0;
}
-static int dw_i2c_remove(struct platform_device *pdev)
+static int dw_i2c_plat_remove(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
@@ -285,9 +262,6 @@ static int dw_i2c_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- if (has_acpi_companion(&pdev->dev))
- dw_i2c_acpi_unconfigure(pdev);
-
return 0;
}
@@ -300,23 +274,23 @@ MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif
#ifdef CONFIG_PM_SLEEP
-static int dw_i2c_prepare(struct device *dev)
+static int dw_i2c_plat_prepare(struct device *dev)
{
return pm_runtime_suspended(dev);
}
-static void dw_i2c_complete(struct device *dev)
+static void dw_i2c_plat_complete(struct device *dev)
{
if (dev->power.direct_complete)
pm_request_resume(dev);
}
#else
-#define dw_i2c_prepare NULL
-#define dw_i2c_complete NULL
+#define dw_i2c_plat_prepare NULL
+#define dw_i2c_plat_complete NULL
#endif
#ifdef CONFIG_PM
-static int dw_i2c_suspend(struct device *dev)
+static int dw_i2c_plat_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
@@ -327,7 +301,7 @@ static int dw_i2c_suspend(struct device *dev)
return 0;
}
-static int dw_i2c_resume(struct device *dev)
+static int dw_i2c_plat_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
@@ -341,10 +315,10 @@ static int dw_i2c_resume(struct device *dev)
}
static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
- .prepare = dw_i2c_prepare,
- .complete = dw_i2c_complete,
- SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_suspend, dw_i2c_resume)
- SET_RUNTIME_PM_OPS(dw_i2c_suspend, dw_i2c_resume, NULL)
+ .prepare = dw_i2c_plat_prepare,
+ .complete = dw_i2c_plat_complete,
+ SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
+ SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
};
#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
@@ -356,8 +330,8 @@ static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
MODULE_ALIAS("platform:i2c_designware");
static struct platform_driver dw_i2c_driver = {
- .probe = dw_i2c_probe,
- .remove = dw_i2c_remove,
+ .probe = dw_i2c_plat_probe,
+ .remove = dw_i2c_plat_remove,
.driver = {
.name = "i2c_designware",
.of_match_table = of_match_ptr(dw_i2c_of_match),
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index eaef9bc9d88c..f62d69799a9c 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -60,6 +60,10 @@
* BayTrail (SOC) 0x0f12 32 hard yes yes yes
* Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes
* Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes
+ * DNV (SOC) 0x19df 32 hard yes yes yes
+ * Broxton (SOC) 0x5ad4 32 hard yes yes yes
+ * Lewisburg (PCH) 0xa1a3 32 hard yes yes yes
+ * Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -202,6 +206,10 @@
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS 0x9d23
+#define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df
+#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
+#define PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS 0xa1a3
+#define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223
struct i801_mux_config {
char *gpio_chip;
@@ -863,6 +871,10 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) },
{ 0, }
};
@@ -1251,11 +1263,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
priv->adapter.owner = THIS_MODULE;
priv->adapter.class = i801_get_adapter_class(priv);
priv->adapter.algo = &smbus_algorithm;
+ priv->adapter.dev.parent = &dev->dev;
+ ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
+ priv->adapter.retries = 3;
priv->pci_dev = dev;
switch (dev->device) {
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS:
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS:
+ case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ;
priv->features |= FEATURE_SMBUS_PEC;
@@ -1381,12 +1397,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
i801_add_tco(priv);
- /* set up the sysfs linkage to our parent device */
- priv->adapter.dev.parent = &dev->dev;
-
- /* Retry up to 3 times on lost arbitration */
- priv->adapter.retries = 3;
-
snprintf(priv->adapter.name, sizeof(priv->adapter.name),
"SMBus I801 adapter at %04lx", priv->smba);
err = i2c_add_adapter(&priv->adapter);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 722f839cfa3c..ab492301581a 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -798,6 +798,7 @@ static const struct of_device_id ibm_iic_match[] = {
{ .compatible = "ibm,iic", },
{}
};
+MODULE_DEVICE_TABLE(of, ibm_iic_match);
static struct platform_driver ibm_iic_driver = {
.driver = {
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index 00ffd6613680..3795fe130ef2 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -278,8 +278,6 @@
#define ISR_COMPLETE(err) (ISR_COMPLETE_M | (ISR_STATUS_M & (err)))
#define ISR_FATAL(err) (ISR_COMPLETE(err) | ISR_FATAL_M)
-#define REL_SOC_IP_SCB_2_2_1 0x00020201
-
enum img_i2c_mode {
MODE_INACTIVE,
MODE_RAW,
@@ -536,6 +534,7 @@ static void img_i2c_read_fifo(struct img_i2c *i2c)
u32 fifo_status;
u8 data;
+ img_i2c_wr_rd_fence(i2c);
fifo_status = img_i2c_readl(i2c, SCB_FIFO_STATUS_REG);
if (fifo_status & FIFO_READ_EMPTY)
break;
@@ -544,7 +543,6 @@ static void img_i2c_read_fifo(struct img_i2c *i2c)
*i2c->msg.buf = data;
img_i2c_writel(i2c, SCB_READ_FIFO_REG, 0xff);
- img_i2c_wr_rd_fence(i2c);
i2c->msg.len--;
i2c->msg.buf++;
}
@@ -556,12 +554,12 @@ static void img_i2c_write_fifo(struct img_i2c *i2c)
while (i2c->msg.len) {
u32 fifo_status;
+ img_i2c_wr_rd_fence(i2c);
fifo_status = img_i2c_readl(i2c, SCB_FIFO_STATUS_REG);
if (fifo_status & FIFO_WRITE_FULL)
break;
img_i2c_writel(i2c, SCB_WRITE_DATA_REG, *i2c->msg.buf);
- img_i2c_wr_rd_fence(i2c);
i2c->msg.len--;
i2c->msg.buf++;
}
@@ -859,7 +857,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
}
/* Enable transaction halt on start bit */
- if (!i2c->last_msg && i2c->line_status & LINESTAT_START_BIT_DET) {
+ if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) {
img_i2c_transaction_halt(i2c, true);
/* we're no longer interested in the slave event */
i2c->int_enable &= ~INT_SLAVE_EVENT;
@@ -1062,6 +1060,15 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
i2c->last_msg = (i == num - 1);
reinit_completion(&i2c->msg_complete);
+ /*
+ * Clear line status and all interrupts before starting a
+ * transfer, as we may have unserviced interrupts from
+ * previous transfers that might be handled in the context
+ * of the new transfer.
+ */
+ img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0);
+ img_i2c_writel(i2c, SCB_CLEAR_REG, ~0);
+
if (atomic)
img_i2c_atomic_start(i2c);
else if (msg->flags & I2C_M_RD)
@@ -1120,13 +1127,8 @@ static int img_i2c_init(struct img_i2c *i2c)
return -EINVAL;
}
- if (rev == REL_SOC_IP_SCB_2_2_1) {
- i2c->need_wr_rd_fence = true;
- dev_info(i2c->adap.dev.parent, "fence quirk enabled");
- }
-
- bitrate_khz = i2c->bitrate / 1000;
- clk_khz = clk_get_rate(i2c->scb_clk) / 1000;
+ /* Fencing enabled by default. */
+ i2c->need_wr_rd_fence = true;
/* Determine what mode we're in from the bitrate */
timing = timings[0];
@@ -1136,6 +1138,17 @@ static int img_i2c_init(struct img_i2c *i2c)
break;
}
}
+ if (i2c->bitrate > timings[ARRAY_SIZE(timings) - 1].max_bitrate) {
+ dev_warn(i2c->adap.dev.parent,
+ "requested bitrate (%u) is higher than the max bitrate supported (%u)\n",
+ i2c->bitrate,
+ timings[ARRAY_SIZE(timings) - 1].max_bitrate);
+ timing = timings[ARRAY_SIZE(timings) - 1];
+ i2c->bitrate = timing.max_bitrate;
+ }
+
+ bitrate_khz = i2c->bitrate / 1000;
+ clk_khz = clk_get_rate(i2c->scb_clk) / 1000;
/* Find the prescale that would give us that inc (approx delay = 0) */
prescale = SCB_OPT_INC * clk_khz / (256 * 16 * bitrate_khz);
@@ -1182,32 +1195,32 @@ static int img_i2c_init(struct img_i2c *i2c)
((bitrate_khz * clk_period) / 2))
int_bitrate++;
- /* Setup TCKH value */
- tckh = timing.tckh / clk_period;
- if (timing.tckh % clk_period)
- tckh++;
+ /*
+ * Setup clock duty cycle, start with 50% and adjust TCKH and TCKL
+ * values from there if they don't meet minimum timing requirements
+ */
+ tckh = int_bitrate / 2;
+ tckl = int_bitrate - tckh;
- if (tckh > 0)
- data = tckh - 1;
- else
- data = 0;
+ /* Adjust TCKH and TCKL values */
+ data = DIV_ROUND_UP(timing.tckl, clk_period);
- img_i2c_writel(i2c, SCB_TIME_TCKH_REG, data);
+ if (tckl < data) {
+ tckl = data;
+ tckh = int_bitrate - tckl;
+ }
- /* Setup TCKL value */
- tckl = int_bitrate - tckh;
+ if (tckh > 0)
+ --tckh;
if (tckl > 0)
- data = tckl - 1;
- else
- data = 0;
+ --tckl;
- img_i2c_writel(i2c, SCB_TIME_TCKL_REG, data);
+ img_i2c_writel(i2c, SCB_TIME_TCKH_REG, tckh);
+ img_i2c_writel(i2c, SCB_TIME_TCKL_REG, tckl);
/* Setup TSDH value */
- tsdh = timing.tsdh / clk_period;
- if (timing.tsdh % clk_period)
- tsdh++;
+ tsdh = DIV_ROUND_UP(timing.tsdh, clk_period);
if (tsdh > 1)
data = tsdh - 1;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 785aa674a4da..9bb0b056b25f 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -49,6 +49,8 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/i2c-imx.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
@@ -207,6 +209,11 @@ struct imx_i2c_struct {
unsigned int cur_clk;
unsigned int bitrate;
const struct imx_i2c_hwdata *hwdata;
+ struct i2c_bus_recovery_info rinfo;
+
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_pins_default;
+ struct pinctrl_state *pinctrl_pins_gpio;
struct imx_i2c_dma *dma;
};
@@ -461,7 +468,7 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
{
if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__);
- return -EIO; /* No ACK */
+ return -ENXIO; /* No ACK */
}
dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__);
@@ -896,6 +903,13 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx);
+ if (result) {
+ if (i2c_imx->adapter.bus_recovery_info) {
+ i2c_recover_bus(&i2c_imx->adapter);
+ result = i2c_imx_start(i2c_imx);
+ }
+ }
+
if (result)
goto fail0;
@@ -956,6 +970,55 @@ fail0:
return (result < 0) ? result : num;
}
+static void i2c_imx_prepare_recovery(struct i2c_adapter *adap)
+{
+ struct imx_i2c_struct *i2c_imx;
+
+ i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
+
+ pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_gpio);
+}
+
+static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
+{
+ struct imx_i2c_struct *i2c_imx;
+
+ i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
+
+ pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
+}
+
+static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
+ struct platform_device *pdev)
+{
+ struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo;
+
+ i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
+ PINCTRL_STATE_DEFAULT);
+ i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
+ "gpio");
+ rinfo->sda_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+ "sda-gpios", 0, NULL);
+ rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+ "scl-gpios", 0, NULL);
+
+ if (!gpio_is_valid(rinfo->sda_gpio) ||
+ !gpio_is_valid(rinfo->scl_gpio) ||
+ IS_ERR(i2c_imx->pinctrl_pins_default) ||
+ IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
+ dev_dbg(&pdev->dev, "recovery information incomplete\n");
+ return;
+ }
+
+ dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
+ rinfo->sda_gpio, rinfo->scl_gpio);
+
+ rinfo->prepare_recovery = i2c_imx_prepare_recovery;
+ rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
+ rinfo->recover_bus = i2c_generic_gpio_recovery;
+ i2c_imx->adapter.bus_recovery_info = rinfo;
+}
+
static u32 i2c_imx_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
@@ -1023,6 +1086,13 @@ static int i2c_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't enable I2C clock\n");
return ret;
}
+
+ i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(i2c_imx->pinctrl)) {
+ ret = PTR_ERR(i2c_imx->pinctrl);
+ goto clk_disable;
+ }
+
/* Request IRQ */
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
pdev->name, i2c_imx);
@@ -1056,6 +1126,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
goto clk_disable;
}
+ i2c_imx_init_recovery_info(i2c_imx, pdev);
+
/* Set up platform driver data */
platform_set_drvdata(pdev, i2c_imx);
clk_disable_unprepare(i2c_imx->clk);
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
index f994712d0904..7ba795b24e75 100644
--- a/drivers/i2c/busses/i2c-ismt.c
+++ b/drivers/i2c/busses/i2c-ismt.c
@@ -67,7 +67,7 @@
#include <linux/acpi.h>
#include <linux/interrupt.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
/* PCI Address Constants */
#define SMBBAR 0
@@ -165,14 +165,13 @@ struct ismt_desc {
struct ismt_priv {
struct i2c_adapter adapter;
- void *smba; /* PCI BAR */
+ void __iomem *smba; /* PCI BAR */
struct pci_dev *pci_dev;
struct ismt_desc *hw; /* descriptor virt base addr */
dma_addr_t io_rng_dma; /* descriptor HW base addr */
u8 head; /* ring buffer head pointer */
struct completion cmp; /* interrupt completion */
u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* temp R/W data buffer */
- bool using_msi; /* type of interrupt flag */
};
/**
@@ -398,7 +397,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
/* Initialize common control bits */
- if (likely(priv->using_msi))
+ if (likely(pci_dev_msi_enabled(priv->pci_dev)))
desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR;
else
desc->control = ISMT_DESC_FAIR;
@@ -789,11 +788,8 @@ static int ismt_int_init(struct ismt_priv *priv)
/* Try using MSI interrupts */
err = pci_enable_msi(priv->pci_dev);
- if (err) {
- dev_warn(&priv->pci_dev->dev,
- "Unable to use MSI interrupts, falling back to legacy\n");
+ if (err)
goto intx;
- }
err = devm_request_irq(&priv->pci_dev->dev,
priv->pci_dev->irq,
@@ -806,11 +802,13 @@ static int ismt_int_init(struct ismt_priv *priv)
goto intx;
}
- priv->using_msi = true;
- goto done;
+ return 0;
/* Try using legacy interrupts */
intx:
+ dev_warn(&priv->pci_dev->dev,
+ "Unable to use MSI interrupts, falling back to legacy\n");
+
err = devm_request_irq(&priv->pci_dev->dev,
priv->pci_dev->irq,
ismt_do_interrupt,
@@ -819,12 +817,9 @@ intx:
priv);
if (err) {
dev_err(&priv->pci_dev->dev, "no usable interrupts\n");
- return -ENODEV;
+ return err;
}
- priv->using_msi = false;
-
-done:
return 0;
}
@@ -847,17 +842,13 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENOMEM;
pci_set_drvdata(pdev, priv);
+
i2c_set_adapdata(&priv->adapter, priv);
priv->adapter.owner = THIS_MODULE;
-
priv->adapter.class = I2C_CLASS_HWMON;
-
priv->adapter.algo = &smbus_algorithm;
-
- /* set up the sysfs linkage to our parent device */
priv->adapter.dev.parent = &pdev->dev;
-
- /* number of retries on lost arbitration */
+ ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev));
priv->adapter.retries = ISMT_MAX_RETRIES;
priv->pci_dev = pdev;
@@ -904,8 +895,7 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
priv->smba = pcim_iomap(pdev, SMBBAR, len);
if (!priv->smba) {
dev_err(&pdev->dev, "Unable to ioremap SMBus BAR\n");
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) ||
@@ -915,32 +905,26 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
DMA_BIT_MASK(32)) != 0)) {
dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n",
pdev);
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
}
err = ismt_dev_init(priv);
if (err)
- goto fail;
+ return err;
ismt_hw_init(priv);
err = ismt_int_init(priv);
if (err)
- goto fail;
+ return err;
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
return 0;
-
-fail:
- pci_release_region(pdev, SMBBAR);
- return err;
}
/**
@@ -952,47 +936,13 @@ static void ismt_remove(struct pci_dev *pdev)
struct ismt_priv *priv = pci_get_drvdata(pdev);
i2c_del_adapter(&priv->adapter);
- pci_release_region(pdev, SMBBAR);
}
-/**
- * ismt_suspend() - place the device in suspend
- * @pdev: PCI-Express device
- * @mesg: PM message
- */
-#ifdef CONFIG_PM
-static int ismt_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
- pci_save_state(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
- return 0;
-}
-
-/**
- * ismt_resume() - PCI resume code
- * @pdev: PCI-Express device
- */
-static int ismt_resume(struct pci_dev *pdev)
-{
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- return pci_enable_device(pdev);
-}
-
-#else
-
-#define ismt_suspend NULL
-#define ismt_resume NULL
-
-#endif
-
static struct pci_driver ismt_driver = {
.name = "ismt_smbus",
.id_table = ismt_ids,
.probe = ismt_probe,
.remove = ismt_remove,
- .suspend = ismt_suspend,
- .resume = ismt_resume,
};
module_pci_driver(ismt_driver);
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 5e176adca8e8..71d3929adf54 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -475,6 +475,7 @@ static const struct of_device_id meson_i2c_match[] = {
{ .compatible = "amlogic,meson6-i2c" },
{ },
};
+MODULE_DEVICE_TABLE(of, meson_i2c_match);
static struct platform_driver meson_i2c_driver = {
.probe = meson_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index c02e6c018c39..9b867169142f 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -728,11 +728,27 @@ static int mtk_i2c_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int mtk_i2c_resume(struct device *dev)
+{
+ struct mtk_i2c *i2c = dev_get_drvdata(dev);
+
+ mtk_i2c_init_hw(i2c);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops mtk_i2c_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(NULL, mtk_i2c_resume)
+};
+
static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe,
.remove = mtk_i2c_remove,
.driver = {
.name = I2C_DRV_NAME,
+ .pm = &mtk_i2c_pm,
.of_match_table = of_match_ptr(mtk_i2c_of_match),
},
};
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 30059c1df2a3..5801227b97ab 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -669,8 +669,6 @@ mv64xxx_i2c_can_offload(struct mv64xxx_i2c_data *drv_data)
struct i2c_msg *msgs = drv_data->msgs;
int num = drv_data->num_msgs;
- return false;
-
if (!drv_data->offload_enabled)
return false;
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index abf5db7e441e..11b7b87311ed 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -92,6 +92,16 @@ static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
iowrite32(value, i2c->base + (reg << i2c->reg_shift));
}
+static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value)
+{
+ iowrite16be(value, i2c->base + (reg << i2c->reg_shift));
+}
+
+static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value)
+{
+ iowrite32be(value, i2c->base + (reg << i2c->reg_shift));
+}
+
static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
{
return ioread8(i2c->base + (reg << i2c->reg_shift));
@@ -107,6 +117,16 @@ static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg)
return ioread32(i2c->base + (reg << i2c->reg_shift));
}
+static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg)
+{
+ return ioread16be(i2c->base + (reg << i2c->reg_shift));
+}
+
+static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg)
+{
+ return ioread32be(i2c->base + (reg << i2c->reg_shift));
+}
+
static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
{
i2c->setreg(i2c, reg, value);
@@ -428,6 +448,9 @@ static int ocores_i2c_probe(struct platform_device *pdev)
i2c->reg_io_width = 1; /* Set to default value */
if (!i2c->setreg || !i2c->getreg) {
+ bool be = pdata ? pdata->big_endian :
+ of_device_is_big_endian(pdev->dev.of_node);
+
switch (i2c->reg_io_width) {
case 1:
i2c->setreg = oc_setreg_8;
@@ -435,13 +458,13 @@ static int ocores_i2c_probe(struct platform_device *pdev)
break;
case 2:
- i2c->setreg = oc_setreg_16;
- i2c->getreg = oc_getreg_16;
+ i2c->setreg = be ? oc_setreg_16be : oc_setreg_16;
+ i2c->getreg = be ? oc_getreg_16be : oc_getreg_16;
break;
case 4:
- i2c->setreg = oc_setreg_32;
- i2c->getreg = oc_getreg_32;
+ i2c->setreg = be ? oc_setreg_32be : oc_setreg_32;
+ i2c->getreg = be ? oc_getreg_32be : oc_getreg_32;
break;
default:
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index e814a36d9b78..7ea67aa46fb7 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -496,7 +496,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
struct i2c_msg *pmsg;
int rc = 0, completed = 0, i;
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
- u32 stat = ioread32(I2C_REG_STS(alg_data));
+ u32 stat;
dev_dbg(&alg_data->adapter.dev,
"%s(): entering: %d messages, stat = %04x.\n",
@@ -600,7 +600,7 @@ static int i2c_pnx_controller_suspend(struct device *dev)
{
struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
- clk_disable(alg_data->clk);
+ clk_disable_unprepare(alg_data->clk);
return 0;
}
@@ -609,7 +609,7 @@ static int i2c_pnx_controller_resume(struct device *dev)
{
struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
- return clk_enable(alg_data->clk);
+ return clk_prepare_enable(alg_data->clk);
}
static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
@@ -659,9 +659,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
if (IS_ERR(alg_data->clk))
return PTR_ERR(alg_data->clk);
- init_timer(&alg_data->mif.timer);
- alg_data->mif.timer.function = i2c_pnx_timeout;
- alg_data->mif.timer.data = (unsigned long)alg_data;
+ setup_timer(&alg_data->mif.timer, i2c_pnx_timeout,
+ (unsigned long)alg_data);
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
"%s", pdev->name);
@@ -672,7 +671,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
if (IS_ERR(alg_data->ioaddr))
return PTR_ERR(alg_data->ioaddr);
- ret = clk_enable(alg_data->clk);
+ ret = clk_prepare_enable(alg_data->clk);
if (ret)
return ret;
@@ -726,7 +725,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
return 0;
out_clock:
- clk_disable(alg_data->clk);
+ clk_disable_unprepare(alg_data->clk);
return ret;
}
@@ -735,7 +734,7 @@ static int i2c_pnx_remove(struct platform_device *pdev)
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
i2c_del_adapter(&alg_data->adapter);
- clk_disable(alg_data->clk);
+ clk_disable_unprepare(alg_data->clk);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 645e4b79d968..0d351954db02 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -46,12 +46,15 @@ struct pxa_reg_layout {
u32 icr;
u32 isr;
u32 isar;
+ u32 ilcr;
+ u32 iwcr;
};
enum pxa_i2c_types {
REGS_PXA2XX,
REGS_PXA3XX,
REGS_CE4100,
+ REGS_PXA910,
};
/*
@@ -79,12 +82,22 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.isr = 0x04,
/* no isar register */
},
+ [REGS_PXA910] = {
+ .ibmr = 0x00,
+ .idbr = 0x08,
+ .icr = 0x10,
+ .isr = 0x18,
+ .isar = 0x20,
+ .ilcr = 0x28,
+ .iwcr = 0x30,
+ },
};
static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REGS_PXA2XX },
{ "pxa3xx-pwri2c", REGS_PXA3XX },
{ "ce4100-i2c", REGS_CE4100 },
+ { "pxa910-i2c", REGS_PXA910 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -124,6 +137,23 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
#define ISR_SAD (1 << 9) /* slave address detected */
#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
+/* bit field shift & mask */
+#define ILCR_SLV_SHIFT 0
+#define ILCR_SLV_MASK (0x1FF << ILCR_SLV_SHIFT)
+#define ILCR_FLV_SHIFT 9
+#define ILCR_FLV_MASK (0x1FF << ILCR_FLV_SHIFT)
+#define ILCR_HLVL_SHIFT 18
+#define ILCR_HLVL_MASK (0x1FF << ILCR_HLVL_SHIFT)
+#define ILCR_HLVH_SHIFT 27
+#define ILCR_HLVH_MASK (0x1F << ILCR_HLVH_SHIFT)
+
+#define IWCR_CNT_SHIFT 0
+#define IWCR_CNT_MASK (0x1F << IWCR_CNT_SHIFT)
+#define IWCR_HS_CNT1_SHIFT 5
+#define IWCR_HS_CNT1_MASK (0x1F << IWCR_HS_CNT1_SHIFT)
+#define IWCR_HS_CNT2_SHIFT 10
+#define IWCR_HS_CNT2_MASK (0x1F << IWCR_HS_CNT2_SHIFT)
+
struct pxa_i2c {
spinlock_t lock;
wait_queue_head_t wait;
@@ -150,6 +180,8 @@ struct pxa_i2c {
void __iomem *reg_icr;
void __iomem *reg_isr;
void __iomem *reg_isar;
+ void __iomem *reg_ilcr;
+ void __iomem *reg_iwcr;
unsigned long iobase;
unsigned long iosize;
@@ -168,6 +200,8 @@ struct pxa_i2c {
#define _ICR(i2c) ((i2c)->reg_icr)
#define _ISR(i2c) ((i2c)->reg_isr)
#define _ISAR(i2c) ((i2c)->reg_isar)
+#define _ILCR(i2c) ((i2c)->reg_ilcr)
+#define _IWCR(i2c) ((i2c)->reg_iwcr)
/*
* I2C Slave mode address
@@ -1102,7 +1136,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
static const struct of_device_id i2c_pxa_dt_ids[] = {
{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
- { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX },
+ { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
{}
};
MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
@@ -1203,6 +1237,11 @@ static int i2c_pxa_probe(struct platform_device *dev)
if (i2c_type != REGS_CE4100)
i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
+ if (i2c_type == REGS_PXA910) {
+ i2c->reg_ilcr = i2c->reg_base + pxa_reg_layout[i2c_type].ilcr;
+ i2c->reg_iwcr = i2c->reg_base + pxa_reg_layout[i2c_type].iwcr;
+ }
+
i2c->iobase = res->start;
i2c->iosize = resource_size(res);
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index d8361dada584..b0ae560b38c3 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -27,7 +27,6 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/i2c.h>
-#include <linux/i2c/i2c-rcar.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
@@ -103,6 +102,7 @@
enum rcar_i2c_type {
I2C_RCAR_GEN1,
I2C_RCAR_GEN2,
+ I2C_RCAR_GEN3,
};
struct rcar_i2c_priv {
@@ -178,6 +178,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
cdf_width = 2;
break;
case I2C_RCAR_GEN2:
+ case I2C_RCAR_GEN3:
cdf_width = 3;
break;
default:
@@ -625,13 +626,13 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
{ .compatible = "renesas,i2c-r8a7792", .data = (void *)I2C_RCAR_GEN2 },
{ .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 },
{ .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
+ { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 },
{},
};
MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
static int rcar_i2c_probe(struct platform_device *pdev)
{
- struct i2c_rcar_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct rcar_i2c_priv *priv;
struct i2c_adapter *adap;
struct resource *res;
@@ -650,15 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
}
bus_speed = 100000; /* default 100 kHz */
- ret = of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed);
- if (ret < 0 && pdata && pdata->bus_speed)
- bus_speed = pdata->bus_speed;
+ of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed);
- if (pdev->dev.of_node)
- priv->devtype = (long)of_match_device(rcar_i2c_dt_ids,
- dev)->data;
- else
- priv->devtype = platform_get_device_id(pdev)->driver_data;
+ priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data;
ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
if (ret < 0)
@@ -690,15 +685,16 @@ static int rcar_i2c_probe(struct platform_device *pdev)
return ret;
}
+ pm_runtime_enable(dev);
+ platform_set_drvdata(pdev, priv);
+
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(dev, "reg adap failed: %d\n", ret);
+ pm_runtime_disable(dev);
return ret;
}
- pm_runtime_enable(dev);
- platform_set_drvdata(pdev, priv);
-
dev_info(dev, "probed\n");
return 0;
@@ -715,14 +711,6 @@ static int rcar_i2c_remove(struct platform_device *pdev)
return 0;
}
-static const struct platform_device_id rcar_i2c_id_table[] = {
- { "i2c-rcar", I2C_RCAR_GEN1 },
- { "i2c-rcar_gen1", I2C_RCAR_GEN1 },
- { "i2c-rcar_gen2", I2C_RCAR_GEN2 },
- {},
-};
-MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table);
-
static struct platform_driver rcar_i2c_driver = {
.driver = {
.name = "i2c-rcar",
@@ -730,7 +718,6 @@ static struct platform_driver rcar_i2c_driver = {
},
.probe = rcar_i2c_probe,
.remove = rcar_i2c_remove,
- .id_table = rcar_i2c_id_table,
};
module_platform_driver(rcar_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 72e97e306bd9..c1935ebd6a9c 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -858,6 +858,7 @@ static const struct of_device_id rk3x_i2c_match[] = {
{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
{},
};
+MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
static int rk3x_i2c_probe(struct platform_device *pdev)
{
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 50bfd8cef5f2..5df819610d52 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1243,17 +1243,19 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
i2c->adap.nr = i2c->pdata->bus_num;
i2c->adap.dev.of_node = pdev->dev.of_node;
+ platform_set_drvdata(pdev, i2c);
+
+ pm_runtime_enable(&pdev->dev);
+
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+ pm_runtime_disable(&pdev->dev);
s3c24xx_i2c_deregister_cpufreq(i2c);
clk_unprepare(i2c->clk);
return ret;
}
- platform_set_drvdata(pdev, i2c);
-
- pm_runtime_enable(&pdev->dev);
pm_runtime_enable(&i2c->adap.dev);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 47659a925e09..7d2bd3ec2d2d 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -836,6 +836,7 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
{ .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config },
+ { .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config },
{},
};
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index 1092d4eeeb54..13e51ef6af73 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -358,11 +358,29 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
if (err < 0)
bitrate = SIRFSOC_I2C_DEFAULT_SPEED;
- if (bitrate < 100000)
- regval =
- (2 * ctrl_speed) / (bitrate * 11);
- else
+ /*
+ * Due to some hardware design issues, we need to tune the formula.
+ * Since i2c is open drain interface that allows the slave to
+ * stall the transaction by holding the SCL line at '0', the RTL
+ * implementation is waiting for SCL feedback from the pin after
+ * setting it to High-Z ('1'). This wait adds to the high-time
+ * interval counter few cycles of the input synchronization
+ * (depending on the SCL_FILTER_REG field), and also the time it
+ * takes for the board pull-up resistor to rise the SCL line.
+ * For slow SCL settings these additions are negligible,
+ * but they start to affect the speed when clock is set to faster
+ * frequencies.
+ * Through the actual tests, use the different user_div value(which
+ * in the divider formular 'Fio / (Fi2c * user_div)') to adapt
+ * the different ranges of i2c bus clock frequency, to make the SCL
+ * more accurate.
+ */
+ if (bitrate <= 30000)
regval = ctrl_speed / (bitrate * 5);
+ else if (bitrate > 30000 && bitrate <= 280000)
+ regval = (2 * ctrl_speed) / (bitrate * 11);
+ else
+ regval = ctrl_speed / (bitrate * 6);
writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL);
if (regval > 0xFF)
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 4885da9e9298..460c134832ac 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -977,6 +977,7 @@ static const struct of_device_id stu300_dt_match[] = {
{ .compatible = "st,ddci2c" },
{},
};
+MODULE_DEVICE_TABLE(of, stu300_dt_match);
static struct platform_driver stu300_i2c_driver = {
.driver = {
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index b7e1a3655421..a0522fcc4ff8 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -873,7 +873,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
sizeof(i2c_dev->adapter.name));
- i2c_dev->adapter.algo = &tegra_i2c_algo;
i2c_dev->adapter.dev.parent = &pdev->dev;
i2c_dev->adapter.nr = pdev->id;
i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
new file mode 100644
index 000000000000..e8d03bcfe3e0
--- /dev/null
+++ b/drivers/i2c/busses/i2c-uniphier-f.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.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/clk.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define UNIPHIER_FI2C_CR 0x00 /* control register */
+#define UNIPHIER_FI2C_CR_MST BIT(3) /* master mode */
+#define UNIPHIER_FI2C_CR_STA BIT(2) /* start condition */
+#define UNIPHIER_FI2C_CR_STO BIT(1) /* stop condition */
+#define UNIPHIER_FI2C_CR_NACK BIT(0) /* do not return ACK */
+#define UNIPHIER_FI2C_DTTX 0x04 /* TX FIFO */
+#define UNIPHIER_FI2C_DTTX_CMD BIT(8) /* send command (slave addr) */
+#define UNIPHIER_FI2C_DTTX_RD BIT(0) /* read transaction */
+#define UNIPHIER_FI2C_DTRX 0x04 /* RX FIFO */
+#define UNIPHIER_FI2C_SLAD 0x0c /* slave address */
+#define UNIPHIER_FI2C_CYC 0x10 /* clock cycle control */
+#define UNIPHIER_FI2C_LCTL 0x14 /* clock low period control */
+#define UNIPHIER_FI2C_SSUT 0x18 /* restart/stop setup time control */
+#define UNIPHIER_FI2C_DSUT 0x1c /* data setup time control */
+#define UNIPHIER_FI2C_INT 0x20 /* interrupt status */
+#define UNIPHIER_FI2C_IE 0x24 /* interrupt enable */
+#define UNIPHIER_FI2C_IC 0x28 /* interrupt clear */
+#define UNIPHIER_FI2C_INT_TE BIT(9) /* TX FIFO empty */
+#define UNIPHIER_FI2C_INT_RF BIT(8) /* RX FIFO full */
+#define UNIPHIER_FI2C_INT_TC BIT(7) /* send complete (STOP) */
+#define UNIPHIER_FI2C_INT_RC BIT(6) /* receive complete (STOP) */
+#define UNIPHIER_FI2C_INT_TB BIT(5) /* sent specified bytes */
+#define UNIPHIER_FI2C_INT_RB BIT(4) /* received specified bytes */
+#define UNIPHIER_FI2C_INT_NA BIT(2) /* no ACK */
+#define UNIPHIER_FI2C_INT_AL BIT(1) /* arbitration lost */
+#define UNIPHIER_FI2C_SR 0x2c /* status register */
+#define UNIPHIER_FI2C_SR_DB BIT(12) /* device busy */
+#define UNIPHIER_FI2C_SR_STS BIT(11) /* stop condition detected */
+#define UNIPHIER_FI2C_SR_BB BIT(8) /* bus busy */
+#define UNIPHIER_FI2C_SR_RFF BIT(3) /* RX FIFO full */
+#define UNIPHIER_FI2C_SR_RNE BIT(2) /* RX FIFO not empty */
+#define UNIPHIER_FI2C_SR_TNF BIT(1) /* TX FIFO not full */
+#define UNIPHIER_FI2C_SR_TFE BIT(0) /* TX FIFO empty */
+#define UNIPHIER_FI2C_RST 0x34 /* reset control */
+#define UNIPHIER_FI2C_RST_TBRST BIT(2) /* clear TX FIFO */
+#define UNIPHIER_FI2C_RST_RBRST BIT(1) /* clear RX FIFO */
+#define UNIPHIER_FI2C_RST_RST BIT(0) /* forcible bus reset */
+#define UNIPHIER_FI2C_BM 0x38 /* bus monitor */
+#define UNIPHIER_FI2C_BM_SDAO BIT(3) /* output for SDA line */
+#define UNIPHIER_FI2C_BM_SDAS BIT(2) /* readback of SDA line */
+#define UNIPHIER_FI2C_BM_SCLO BIT(1) /* output for SCL line */
+#define UNIPHIER_FI2C_BM_SCLS BIT(0) /* readback of SCL line */
+#define UNIPHIER_FI2C_NOISE 0x3c /* noise filter control */
+#define UNIPHIER_FI2C_TBC 0x40 /* TX byte count setting */
+#define UNIPHIER_FI2C_RBC 0x44 /* RX byte count setting */
+#define UNIPHIER_FI2C_TBCM 0x48 /* TX byte count monitor */
+#define UNIPHIER_FI2C_RBCM 0x4c /* RX byte count monitor */
+#define UNIPHIER_FI2C_BRST 0x50 /* bus reset */
+#define UNIPHIER_FI2C_BRST_FOEN BIT(1) /* normal operation */
+#define UNIPHIER_FI2C_BRST_RSCL BIT(0) /* release SCL */
+
+#define UNIPHIER_FI2C_INT_FAULTS \
+ (UNIPHIER_FI2C_INT_NA | UNIPHIER_FI2C_INT_AL)
+#define UNIPHIER_FI2C_INT_STOP \
+ (UNIPHIER_FI2C_INT_TC | UNIPHIER_FI2C_INT_RC)
+
+#define UNIPHIER_FI2C_RD BIT(0)
+#define UNIPHIER_FI2C_STOP BIT(1)
+#define UNIPHIER_FI2C_MANUAL_NACK BIT(2)
+#define UNIPHIER_FI2C_BYTE_WISE BIT(3)
+#define UNIPHIER_FI2C_DEFER_STOP_COMP BIT(4)
+
+#define UNIPHIER_FI2C_DEFAULT_SPEED 100000
+#define UNIPHIER_FI2C_MAX_SPEED 400000
+#define UNIPHIER_FI2C_FIFO_SIZE 8
+
+struct uniphier_fi2c_priv {
+ struct completion comp;
+ struct i2c_adapter adap;
+ void __iomem *membase;
+ struct clk *clk;
+ unsigned int len;
+ u8 *buf;
+ u32 enabled_irqs;
+ int error;
+ unsigned int flags;
+ unsigned int busy_cnt;
+};
+
+static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv,
+ bool first)
+{
+ int fifo_space = UNIPHIER_FI2C_FIFO_SIZE;
+
+ /*
+ * TX-FIFO stores slave address in it for the first access.
+ * Decrement the counter.
+ */
+ if (first)
+ fifo_space--;
+
+ while (priv->len) {
+ if (fifo_space-- <= 0)
+ break;
+
+ dev_dbg(&priv->adap.dev, "write data: %02x\n", *priv->buf);
+ writel(*priv->buf++, priv->membase + UNIPHIER_FI2C_DTTX);
+ priv->len--;
+ }
+}
+
+static void uniphier_fi2c_drain_rxfifo(struct uniphier_fi2c_priv *priv)
+{
+ int fifo_left = priv->flags & UNIPHIER_FI2C_BYTE_WISE ?
+ 1 : UNIPHIER_FI2C_FIFO_SIZE;
+
+ while (priv->len) {
+ if (fifo_left-- <= 0)
+ break;
+
+ *priv->buf++ = readl(priv->membase + UNIPHIER_FI2C_DTRX);
+ dev_dbg(&priv->adap.dev, "read data: %02x\n", priv->buf[-1]);
+ priv->len--;
+ }
+}
+
+static void uniphier_fi2c_set_irqs(struct uniphier_fi2c_priv *priv)
+{
+ writel(priv->enabled_irqs, priv->membase + UNIPHIER_FI2C_IE);
+}
+
+static void uniphier_fi2c_clear_irqs(struct uniphier_fi2c_priv *priv)
+{
+ writel(-1, priv->membase + UNIPHIER_FI2C_IC);
+}
+
+static void uniphier_fi2c_stop(struct uniphier_fi2c_priv *priv)
+{
+ dev_dbg(&priv->adap.dev, "stop condition\n");
+
+ priv->enabled_irqs |= UNIPHIER_FI2C_INT_STOP;
+ uniphier_fi2c_set_irqs(priv);
+ writel(UNIPHIER_FI2C_CR_MST | UNIPHIER_FI2C_CR_STO,
+ priv->membase + UNIPHIER_FI2C_CR);
+}
+
+static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
+{
+ struct uniphier_fi2c_priv *priv = dev_id;
+ u32 irq_status;
+
+ irq_status = readl(priv->membase + UNIPHIER_FI2C_INT);
+
+ dev_dbg(&priv->adap.dev,
+ "interrupt: enabled_irqs=%04x, irq_status=%04x\n",
+ priv->enabled_irqs, irq_status);
+
+ if (irq_status & UNIPHIER_FI2C_INT_STOP)
+ goto complete;
+
+ if (unlikely(irq_status & UNIPHIER_FI2C_INT_AL)) {
+ dev_dbg(&priv->adap.dev, "arbitration lost\n");
+ priv->error = -EAGAIN;
+ goto complete;
+ }
+
+ if (unlikely(irq_status & UNIPHIER_FI2C_INT_NA)) {
+ dev_dbg(&priv->adap.dev, "could not get ACK\n");
+ priv->error = -ENXIO;
+ if (priv->flags & UNIPHIER_FI2C_RD) {
+ /*
+ * work around a hardware bug:
+ * The receive-completed interrupt is never set even if
+ * STOP condition is detected after the address phase
+ * of read transaction fails to get ACK.
+ * To avoid time-out error, we issue STOP here,
+ * but do not wait for its completion.
+ * It should be checked after exiting this handler.
+ */
+ uniphier_fi2c_stop(priv);
+ priv->flags |= UNIPHIER_FI2C_DEFER_STOP_COMP;
+ goto complete;
+ }
+ goto stop;
+ }
+
+ if (irq_status & UNIPHIER_FI2C_INT_TE) {
+ if (!priv->len)
+ goto data_done;
+
+ uniphier_fi2c_fill_txfifo(priv, false);
+ goto handled;
+ }
+
+ if (irq_status & (UNIPHIER_FI2C_INT_RF | UNIPHIER_FI2C_INT_RB)) {
+ uniphier_fi2c_drain_rxfifo(priv);
+ if (!priv->len)
+ goto data_done;
+
+ if (unlikely(priv->flags & UNIPHIER_FI2C_MANUAL_NACK)) {
+ if (priv->len <= UNIPHIER_FI2C_FIFO_SIZE &&
+ !(priv->flags & UNIPHIER_FI2C_BYTE_WISE)) {
+ dev_dbg(&priv->adap.dev,
+ "enable read byte count IRQ\n");
+ priv->enabled_irqs |= UNIPHIER_FI2C_INT_RB;
+ uniphier_fi2c_set_irqs(priv);
+ priv->flags |= UNIPHIER_FI2C_BYTE_WISE;
+ }
+ if (priv->len <= 1) {
+ dev_dbg(&priv->adap.dev, "set NACK\n");
+ writel(UNIPHIER_FI2C_CR_MST |
+ UNIPHIER_FI2C_CR_NACK,
+ priv->membase + UNIPHIER_FI2C_CR);
+ }
+ }
+
+ goto handled;
+ }
+
+ return IRQ_NONE;
+
+data_done:
+ if (priv->flags & UNIPHIER_FI2C_STOP) {
+stop:
+ uniphier_fi2c_stop(priv);
+ } else {
+complete:
+ priv->enabled_irqs = 0;
+ uniphier_fi2c_set_irqs(priv);
+ complete(&priv->comp);
+ }
+
+handled:
+ uniphier_fi2c_clear_irqs(priv);
+
+ return IRQ_HANDLED;
+}
+
+static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr)
+{
+ priv->enabled_irqs |= UNIPHIER_FI2C_INT_TE;
+ /* do not use TX byte counter */
+ writel(0, priv->membase + UNIPHIER_FI2C_TBC);
+ /* set slave address */
+ writel(UNIPHIER_FI2C_DTTX_CMD | addr << 1,
+ priv->membase + UNIPHIER_FI2C_DTTX);
+ /* first chunk of data */
+ uniphier_fi2c_fill_txfifo(priv, true);
+}
+
+static void uniphier_fi2c_rx_init(struct uniphier_fi2c_priv *priv, u16 addr)
+{
+ priv->flags |= UNIPHIER_FI2C_RD;
+
+ if (likely(priv->len < 256)) {
+ /*
+ * If possible, use RX byte counter.
+ * It can automatically handle NACK for the last byte.
+ */
+ writel(priv->len, priv->membase + UNIPHIER_FI2C_RBC);
+ priv->enabled_irqs |= UNIPHIER_FI2C_INT_RF |
+ UNIPHIER_FI2C_INT_RB;
+ } else {
+ /*
+ * The byte counter can not count over 256. In this case,
+ * do not use it at all. Drain data when FIFO gets full,
+ * but treat the last portion as a special case.
+ */
+ writel(0, priv->membase + UNIPHIER_FI2C_RBC);
+ priv->flags |= UNIPHIER_FI2C_MANUAL_NACK;
+ priv->enabled_irqs |= UNIPHIER_FI2C_INT_RF;
+ }
+
+ /* set slave address with RD bit */
+ writel(UNIPHIER_FI2C_DTTX_CMD | UNIPHIER_FI2C_DTTX_RD | addr << 1,
+ priv->membase + UNIPHIER_FI2C_DTTX);
+}
+
+static void uniphier_fi2c_reset(struct uniphier_fi2c_priv *priv)
+{
+ writel(UNIPHIER_FI2C_RST_RST, priv->membase + UNIPHIER_FI2C_RST);
+}
+
+static void uniphier_fi2c_prepare_operation(struct uniphier_fi2c_priv *priv)
+{
+ writel(UNIPHIER_FI2C_BRST_FOEN | UNIPHIER_FI2C_BRST_RSCL,
+ priv->membase + UNIPHIER_FI2C_BRST);
+}
+
+static void uniphier_fi2c_recover(struct uniphier_fi2c_priv *priv)
+{
+ uniphier_fi2c_reset(priv);
+ i2c_recover_bus(&priv->adap);
+}
+
+static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap,
+ struct i2c_msg *msg, bool stop)
+{
+ struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap);
+ bool is_read = msg->flags & I2C_M_RD;
+ unsigned long time_left;
+
+ dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, stop=%d\n",
+ is_read ? "receive" : "transmit", msg->addr, msg->len, stop);
+
+ priv->len = msg->len;
+ priv->buf = msg->buf;
+ priv->enabled_irqs = UNIPHIER_FI2C_INT_FAULTS;
+ priv->error = 0;
+ priv->flags = 0;
+
+ if (stop)
+ priv->flags |= UNIPHIER_FI2C_STOP;
+
+ reinit_completion(&priv->comp);
+ uniphier_fi2c_clear_irqs(priv);
+ writel(UNIPHIER_FI2C_RST_TBRST | UNIPHIER_FI2C_RST_RBRST,
+ priv->membase + UNIPHIER_FI2C_RST); /* reset TX/RX FIFO */
+
+ if (is_read)
+ uniphier_fi2c_rx_init(priv, msg->addr);
+ else
+ uniphier_fi2c_tx_init(priv, msg->addr);
+
+ uniphier_fi2c_set_irqs(priv);
+
+ dev_dbg(&adap->dev, "start condition\n");
+ writel(UNIPHIER_FI2C_CR_MST | UNIPHIER_FI2C_CR_STA,
+ priv->membase + UNIPHIER_FI2C_CR);
+
+ time_left = wait_for_completion_timeout(&priv->comp, adap->timeout);
+ if (!time_left) {
+ dev_err(&adap->dev, "transaction timeout.\n");
+ uniphier_fi2c_recover(priv);
+ return -ETIMEDOUT;
+ }
+ dev_dbg(&adap->dev, "complete\n");
+
+ if (unlikely(priv->flags & UNIPHIER_FI2C_DEFER_STOP_COMP)) {
+ u32 status = readl(priv->membase + UNIPHIER_FI2C_SR);
+
+ if (!(status & UNIPHIER_FI2C_SR_STS) ||
+ status & UNIPHIER_FI2C_SR_BB) {
+ dev_err(&adap->dev,
+ "stop condition was not completed.\n");
+ uniphier_fi2c_recover(priv);
+ return -EBUSY;
+ }
+ }
+
+ return priv->error;
+}
+
+static int uniphier_fi2c_check_bus_busy(struct i2c_adapter *adap)
+{
+ struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap);
+
+ if (readl(priv->membase + UNIPHIER_FI2C_SR) & UNIPHIER_FI2C_SR_DB) {
+ if (priv->busy_cnt++ > 3) {
+ /*
+ * If bus busy continues too long, it is probably
+ * in a wrong state. Try bus recovery.
+ */
+ uniphier_fi2c_recover(priv);
+ priv->busy_cnt = 0;
+ }
+
+ return -EAGAIN;
+ }
+
+ priv->busy_cnt = 0;
+ return 0;
+}
+
+static int uniphier_fi2c_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct i2c_msg *msg, *emsg = msgs + num;
+ int ret;
+
+ ret = uniphier_fi2c_check_bus_busy(adap);
+ if (ret)
+ return ret;
+
+ for (msg = msgs; msg < emsg; msg++) {
+ /* If next message is read, skip the stop condition */
+ bool stop = !(msg + 1 < emsg && msg[1].flags & I2C_M_RD);
+ /* but, force it if I2C_M_STOP is set */
+ if (msg->flags & I2C_M_STOP)
+ stop = true;
+
+ ret = uniphier_fi2c_master_xfer_one(adap, msg, stop);
+ if (ret)
+ return ret;
+ }
+
+ return num;
+}
+
+static u32 uniphier_fi2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm uniphier_fi2c_algo = {
+ .master_xfer = uniphier_fi2c_master_xfer,
+ .functionality = uniphier_fi2c_functionality,
+};
+
+static int uniphier_fi2c_get_scl(struct i2c_adapter *adap)
+{
+ struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap);
+
+ return !!(readl(priv->membase + UNIPHIER_FI2C_BM) &
+ UNIPHIER_FI2C_BM_SCLS);
+}
+
+static void uniphier_fi2c_set_scl(struct i2c_adapter *adap, int val)
+{
+ struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap);
+
+ writel(val ? UNIPHIER_FI2C_BRST_RSCL : 0,
+ priv->membase + UNIPHIER_FI2C_BRST);
+}
+
+static int uniphier_fi2c_get_sda(struct i2c_adapter *adap)
+{
+ struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap);
+
+ return !!(readl(priv->membase + UNIPHIER_FI2C_BM) &
+ UNIPHIER_FI2C_BM_SDAS);
+}
+
+static void uniphier_fi2c_unprepare_recovery(struct i2c_adapter *adap)
+{
+ uniphier_fi2c_prepare_operation(i2c_get_adapdata(adap));
+}
+
+static struct i2c_bus_recovery_info uniphier_fi2c_bus_recovery_info = {
+ .recover_bus = i2c_generic_scl_recovery,
+ .get_scl = uniphier_fi2c_get_scl,
+ .set_scl = uniphier_fi2c_set_scl,
+ .get_sda = uniphier_fi2c_get_sda,
+ .unprepare_recovery = uniphier_fi2c_unprepare_recovery,
+};
+
+static int uniphier_fi2c_clk_init(struct device *dev,
+ struct uniphier_fi2c_priv *priv)
+{
+ struct device_node *np = dev->of_node;
+ unsigned long clk_rate;
+ u32 bus_speed, clk_count;
+ int ret;
+
+ if (of_property_read_u32(np, "clock-frequency", &bus_speed))
+ bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;
+
+ if (bus_speed > UNIPHIER_FI2C_MAX_SPEED)
+ bus_speed = UNIPHIER_FI2C_MAX_SPEED;
+
+ /* Get input clk rate through clk driver */
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get clock\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ clk_rate = clk_get_rate(priv->clk);
+
+ uniphier_fi2c_reset(priv);
+
+ clk_count = clk_rate / bus_speed;
+
+ writel(clk_count, priv->membase + UNIPHIER_FI2C_CYC);
+ writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_LCTL);
+ writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_SSUT);
+ writel(clk_count / 16, priv->membase + UNIPHIER_FI2C_DSUT);
+
+ uniphier_fi2c_prepare_operation(priv);
+
+ return 0;
+}
+
+static int uniphier_fi2c_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct uniphier_fi2c_priv *priv;
+ struct resource *regs;
+ int irq;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->membase = devm_ioremap_resource(dev, regs);
+ if (IS_ERR(priv->membase))
+ return PTR_ERR(priv->membase);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "failed to get IRQ number");
+ return irq;
+ }
+
+ init_completion(&priv->comp);
+ priv->adap.owner = THIS_MODULE;
+ priv->adap.algo = &uniphier_fi2c_algo;
+ priv->adap.dev.parent = dev;
+ priv->adap.dev.of_node = dev->of_node;
+ strlcpy(priv->adap.name, "UniPhier FI2C", sizeof(priv->adap.name));
+ priv->adap.bus_recovery_info = &uniphier_fi2c_bus_recovery_info;
+ i2c_set_adapdata(&priv->adap, priv);
+ platform_set_drvdata(pdev, priv);
+
+ ret = uniphier_fi2c_clk_init(dev, priv);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0,
+ pdev->name, priv);
+ if (ret) {
+ dev_err(dev, "failed to request irq %d\n", irq);
+ goto err;
+ }
+
+ ret = i2c_add_adapter(&priv->adap);
+ if (ret) {
+ dev_err(dev, "failed to add I2C adapter\n");
+ goto err;
+ }
+
+err:
+ if (ret)
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static int uniphier_fi2c_remove(struct platform_device *pdev)
+{
+ struct uniphier_fi2c_priv *priv = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&priv->adap);
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static const struct of_device_id uniphier_fi2c_match[] = {
+ { .compatible = "socionext,uniphier-fi2c" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_fi2c_match);
+
+static struct platform_driver uniphier_fi2c_drv = {
+ .probe = uniphier_fi2c_probe,
+ .remove = uniphier_fi2c_remove,
+ .driver = {
+ .name = "uniphier-fi2c",
+ .of_match_table = uniphier_fi2c_match,
+ },
+};
+module_platform_driver(uniphier_fi2c_drv);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier FIFO-builtin I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
new file mode 100644
index 000000000000..e3c3861c3325
--- /dev/null
+++ b/drivers/i2c/busses/i2c-uniphier.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.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/clk.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define UNIPHIER_I2C_DTRM 0x00 /* TX register */
+#define UNIPHIER_I2C_DTRM_IRQEN BIT(11) /* enable interrupt */
+#define UNIPHIER_I2C_DTRM_STA BIT(10) /* start condition */
+#define UNIPHIER_I2C_DTRM_STO BIT(9) /* stop condition */
+#define UNIPHIER_I2C_DTRM_NACK BIT(8) /* do not return ACK */
+#define UNIPHIER_I2C_DTRM_RD BIT(0) /* read transaction */
+#define UNIPHIER_I2C_DREC 0x04 /* RX register */
+#define UNIPHIER_I2C_DREC_MST BIT(14) /* 1 = master, 0 = slave */
+#define UNIPHIER_I2C_DREC_TX BIT(13) /* 1 = transmit, 0 = receive */
+#define UNIPHIER_I2C_DREC_STS BIT(12) /* stop condition detected */
+#define UNIPHIER_I2C_DREC_LRB BIT(11) /* no ACK */
+#define UNIPHIER_I2C_DREC_LAB BIT(9) /* arbitration lost */
+#define UNIPHIER_I2C_DREC_BBN BIT(8) /* bus not busy */
+#define UNIPHIER_I2C_MYAD 0x08 /* slave address */
+#define UNIPHIER_I2C_CLK 0x0c /* clock frequency control */
+#define UNIPHIER_I2C_BRST 0x10 /* bus reset */
+#define UNIPHIER_I2C_BRST_FOEN BIT(1) /* normal operation */
+#define UNIPHIER_I2C_BRST_RSCL BIT(0) /* release SCL */
+#define UNIPHIER_I2C_HOLD 0x14 /* hold time control */
+#define UNIPHIER_I2C_BSTS 0x18 /* bus status monitor */
+#define UNIPHIER_I2C_BSTS_SDA BIT(1) /* readback of SDA line */
+#define UNIPHIER_I2C_BSTS_SCL BIT(0) /* readback of SCL line */
+#define UNIPHIER_I2C_NOISE 0x1c /* noise filter control */
+#define UNIPHIER_I2C_SETUP 0x20 /* setup time control */
+
+#define UNIPHIER_I2C_DEFAULT_SPEED 100000
+#define UNIPHIER_I2C_MAX_SPEED 400000
+
+struct uniphier_i2c_priv {
+ struct completion comp;
+ struct i2c_adapter adap;
+ void __iomem *membase;
+ struct clk *clk;
+ unsigned int busy_cnt;
+};
+
+static irqreturn_t uniphier_i2c_interrupt(int irq, void *dev_id)
+{
+ struct uniphier_i2c_priv *priv = dev_id;
+
+ /*
+ * This hardware uses edge triggered interrupt. Do not touch the
+ * hardware registers in this handler to make sure to catch the next
+ * interrupt edge. Just send a complete signal and return.
+ */
+ complete(&priv->comp);
+
+ return IRQ_HANDLED;
+}
+
+static int uniphier_i2c_xfer_byte(struct i2c_adapter *adap, u32 txdata,
+ u32 *rxdatap)
+{
+ struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
+ unsigned long time_left;
+ u32 rxdata;
+
+ reinit_completion(&priv->comp);
+
+ txdata |= UNIPHIER_I2C_DTRM_IRQEN;
+ dev_dbg(&adap->dev, "write data: 0x%04x\n", txdata);
+ writel(txdata, priv->membase + UNIPHIER_I2C_DTRM);
+
+ time_left = wait_for_completion_timeout(&priv->comp, adap->timeout);
+ if (unlikely(!time_left)) {
+ dev_err(&adap->dev, "transaction timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ rxdata = readl(priv->membase + UNIPHIER_I2C_DREC);
+ dev_dbg(&adap->dev, "read data: 0x%04x\n", rxdata);
+
+ if (rxdatap)
+ *rxdatap = rxdata;
+
+ return 0;
+}
+
+static int uniphier_i2c_send_byte(struct i2c_adapter *adap, u32 txdata)
+{
+ u32 rxdata;
+ int ret;
+
+ ret = uniphier_i2c_xfer_byte(adap, txdata, &rxdata);
+ if (ret)
+ return ret;
+
+ if (unlikely(rxdata & UNIPHIER_I2C_DREC_LAB)) {
+ dev_dbg(&adap->dev, "arbitration lost\n");
+ return -EAGAIN;
+ }
+ if (unlikely(rxdata & UNIPHIER_I2C_DREC_LRB)) {
+ dev_dbg(&adap->dev, "could not get ACK\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int uniphier_i2c_tx(struct i2c_adapter *adap, u16 addr, u16 len,
+ const u8 *buf)
+{
+ int ret;
+
+ dev_dbg(&adap->dev, "start condition\n");
+ ret = uniphier_i2c_send_byte(adap, addr << 1 |
+ UNIPHIER_I2C_DTRM_STA |
+ UNIPHIER_I2C_DTRM_NACK);
+ if (ret)
+ return ret;
+
+ while (len--) {
+ ret = uniphier_i2c_send_byte(adap,
+ UNIPHIER_I2C_DTRM_NACK | *buf++);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int uniphier_i2c_rx(struct i2c_adapter *adap, u16 addr, u16 len,
+ u8 *buf)
+{
+ int ret;
+
+ dev_dbg(&adap->dev, "start condition\n");
+ ret = uniphier_i2c_send_byte(adap, addr << 1 |
+ UNIPHIER_I2C_DTRM_STA |
+ UNIPHIER_I2C_DTRM_NACK |
+ UNIPHIER_I2C_DTRM_RD);
+ if (ret)
+ return ret;
+
+ while (len--) {
+ u32 rxdata;
+
+ ret = uniphier_i2c_xfer_byte(adap,
+ len ? 0 : UNIPHIER_I2C_DTRM_NACK,
+ &rxdata);
+ if (ret)
+ return ret;
+ *buf++ = rxdata;
+ }
+
+ return 0;
+}
+
+static int uniphier_i2c_stop(struct i2c_adapter *adap)
+{
+ dev_dbg(&adap->dev, "stop condition\n");
+ return uniphier_i2c_send_byte(adap, UNIPHIER_I2C_DTRM_STO |
+ UNIPHIER_I2C_DTRM_NACK);
+}
+
+static int uniphier_i2c_master_xfer_one(struct i2c_adapter *adap,
+ struct i2c_msg *msg, bool stop)
+{
+ bool is_read = msg->flags & I2C_M_RD;
+ bool recovery = false;
+ int ret;
+
+ dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, stop=%d\n",
+ is_read ? "receive" : "transmit", msg->addr, msg->len, stop);
+
+ if (is_read)
+ ret = uniphier_i2c_rx(adap, msg->addr, msg->len, msg->buf);
+ else
+ ret = uniphier_i2c_tx(adap, msg->addr, msg->len, msg->buf);
+
+ if (ret == -EAGAIN) /* could not acquire bus. bail out without STOP */
+ return ret;
+
+ if (ret == -ETIMEDOUT) {
+ /* This error is fatal. Needs recovery. */
+ stop = false;
+ recovery = true;
+ }
+
+ if (stop) {
+ int ret2 = uniphier_i2c_stop(adap);
+
+ if (ret2) {
+ /* Failed to issue STOP. The bus needs recovery. */
+ recovery = true;
+ ret = ret ?: ret2;
+ }
+ }
+
+ if (recovery)
+ i2c_recover_bus(adap);
+
+ return ret;
+}
+
+static int uniphier_i2c_check_bus_busy(struct i2c_adapter *adap)
+{
+ struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ if (!(readl(priv->membase + UNIPHIER_I2C_DREC) &
+ UNIPHIER_I2C_DREC_BBN)) {
+ if (priv->busy_cnt++ > 3) {
+ /*
+ * If bus busy continues too long, it is probably
+ * in a wrong state. Try bus recovery.
+ */
+ i2c_recover_bus(adap);
+ priv->busy_cnt = 0;
+ }
+
+ return -EAGAIN;
+ }
+
+ priv->busy_cnt = 0;
+ return 0;
+}
+
+static int uniphier_i2c_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct i2c_msg *msg, *emsg = msgs + num;
+ int ret;
+
+ ret = uniphier_i2c_check_bus_busy(adap);
+ if (ret)
+ return ret;
+
+ for (msg = msgs; msg < emsg; msg++) {
+ /* If next message is read, skip the stop condition */
+ bool stop = !(msg + 1 < emsg && msg[1].flags & I2C_M_RD);
+ /* but, force it if I2C_M_STOP is set */
+ if (msg->flags & I2C_M_STOP)
+ stop = true;
+
+ ret = uniphier_i2c_master_xfer_one(adap, msg, stop);
+ if (ret)
+ return ret;
+ }
+
+ return num;
+}
+
+static u32 uniphier_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm uniphier_i2c_algo = {
+ .master_xfer = uniphier_i2c_master_xfer,
+ .functionality = uniphier_i2c_functionality,
+};
+
+static void uniphier_i2c_reset(struct uniphier_i2c_priv *priv, bool reset_on)
+{
+ u32 val = UNIPHIER_I2C_BRST_RSCL;
+
+ val |= reset_on ? 0 : UNIPHIER_I2C_BRST_FOEN;
+ writel(val, priv->membase + UNIPHIER_I2C_BRST);
+}
+
+static int uniphier_i2c_get_scl(struct i2c_adapter *adap)
+{
+ struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ return !!(readl(priv->membase + UNIPHIER_I2C_BSTS) &
+ UNIPHIER_I2C_BSTS_SCL);
+}
+
+static void uniphier_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+ struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ writel(val ? UNIPHIER_I2C_BRST_RSCL : 0,
+ priv->membase + UNIPHIER_I2C_BRST);
+}
+
+static int uniphier_i2c_get_sda(struct i2c_adapter *adap)
+{
+ struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ return !!(readl(priv->membase + UNIPHIER_I2C_BSTS) &
+ UNIPHIER_I2C_BSTS_SDA);
+}
+
+static void uniphier_i2c_unprepare_recovery(struct i2c_adapter *adap)
+{
+ uniphier_i2c_reset(i2c_get_adapdata(adap), false);
+}
+
+static struct i2c_bus_recovery_info uniphier_i2c_bus_recovery_info = {
+ .recover_bus = i2c_generic_scl_recovery,
+ .get_scl = uniphier_i2c_get_scl,
+ .set_scl = uniphier_i2c_set_scl,
+ .get_sda = uniphier_i2c_get_sda,
+ .unprepare_recovery = uniphier_i2c_unprepare_recovery,
+};
+
+static int uniphier_i2c_clk_init(struct device *dev,
+ struct uniphier_i2c_priv *priv)
+{
+ struct device_node *np = dev->of_node;
+ unsigned long clk_rate;
+ u32 bus_speed;
+ int ret;
+
+ if (of_property_read_u32(np, "clock-frequency", &bus_speed))
+ bus_speed = UNIPHIER_I2C_DEFAULT_SPEED;
+
+ if (bus_speed > UNIPHIER_I2C_MAX_SPEED)
+ bus_speed = UNIPHIER_I2C_MAX_SPEED;
+
+ /* Get input clk rate through clk driver */
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get clock\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ clk_rate = clk_get_rate(priv->clk);
+
+ uniphier_i2c_reset(priv, true);
+
+ writel((clk_rate / bus_speed / 2 << 16) | (clk_rate / bus_speed),
+ priv->membase + UNIPHIER_I2C_CLK);
+
+ uniphier_i2c_reset(priv, false);
+
+ return 0;
+}
+
+static int uniphier_i2c_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct uniphier_i2c_priv *priv;
+ struct resource *regs;
+ int irq;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->membase = devm_ioremap_resource(dev, regs);
+ if (IS_ERR(priv->membase))
+ return PTR_ERR(priv->membase);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "failed to get IRQ number");
+ return irq;
+ }
+
+ init_completion(&priv->comp);
+ priv->adap.owner = THIS_MODULE;
+ priv->adap.algo = &uniphier_i2c_algo;
+ priv->adap.dev.parent = dev;
+ priv->adap.dev.of_node = dev->of_node;
+ strlcpy(priv->adap.name, "UniPhier I2C", sizeof(priv->adap.name));
+ priv->adap.bus_recovery_info = &uniphier_i2c_bus_recovery_info;
+ i2c_set_adapdata(&priv->adap, priv);
+ platform_set_drvdata(pdev, priv);
+
+ ret = uniphier_i2c_clk_init(dev, priv);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name,
+ priv);
+ if (ret) {
+ dev_err(dev, "failed to request irq %d\n", irq);
+ goto err;
+ }
+
+ ret = i2c_add_adapter(&priv->adap);
+ if (ret) {
+ dev_err(dev, "failed to add I2C adapter\n");
+ goto err;
+ }
+
+err:
+ if (ret)
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static int uniphier_i2c_remove(struct platform_device *pdev)
+{
+ struct uniphier_i2c_priv *priv = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&priv->adap);
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static const struct of_device_id uniphier_i2c_match[] = {
+ { .compatible = "socionext,uniphier-i2c" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_i2c_match);
+
+static struct platform_driver uniphier_i2c_drv = {
+ .probe = uniphier_i2c_probe,
+ .remove = uniphier_i2c_remove,
+ .driver = {
+ .name = "uniphier-i2c",
+ .of_match_table = uniphier_i2c_match,
+ },
+};
+module_platform_driver(uniphier_i2c_drv);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index e23a7b068c60..0b20449e48cf 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -662,8 +662,10 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)
static void xiic_start_xfer(struct xiic_i2c *i2c)
{
-
+ spin_lock(&i2c->lock);
+ xiic_reinit(i2c);
__xiic_start_xfer(i2c);
+ spin_unlock(&i2c->lock);
}
static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5f89f1e3c2f2..ba8eb087f224 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -99,27 +99,40 @@ struct gsb_buffer {
};
} __packed;
-static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+struct acpi_i2c_lookup {
+ struct i2c_board_info *info;
+ acpi_handle adapter_handle;
+ acpi_handle device_handle;
+};
+
+static int acpi_i2c_find_address(struct acpi_resource *ares, void *data)
{
- struct i2c_board_info *info = data;
+ struct acpi_i2c_lookup *lookup = data;
+ struct i2c_board_info *info = lookup->info;
+ struct acpi_resource_i2c_serialbus *sb;
+ acpi_handle adapter_handle;
+ acpi_status status;
- if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- struct acpi_resource_i2c_serialbus *sb;
+ if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+ return 1;
- sb = &ares->data.i2c_serial_bus;
- if (!info->addr && sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
- info->addr = sb->slave_address;
- if (sb->access_mode == ACPI_I2C_10BIT_MODE)
- info->flags |= I2C_CLIENT_TEN;
- }
- } else if (!info->irq) {
- struct resource r;
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
+ return 1;
- if (acpi_dev_resource_interrupt(ares, 0, &r))
- info->irq = r.start;
+ /*
+ * Extract the ResourceSource and make sure that the handle matches
+ * with the I2C adapter handle.
+ */
+ status = acpi_get_handle(lookup->device_handle,
+ sb->resource_source.string_ptr,
+ &adapter_handle);
+ if (ACPI_SUCCESS(status) && adapter_handle == lookup->adapter_handle) {
+ info->addr = sb->slave_address;
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ info->flags |= I2C_CLIENT_TEN;
}
- /* Tell the ACPI core to skip this resource */
return 1;
}
@@ -128,6 +141,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
{
struct i2c_adapter *adapter = data;
struct list_head resource_list;
+ struct acpi_i2c_lookup lookup;
+ struct resource_entry *entry;
struct i2c_board_info info;
struct acpi_device *adev;
int ret;
@@ -140,14 +155,37 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
memset(&info, 0, sizeof(info));
info.fwnode = acpi_fwnode_handle(adev);
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.adapter_handle = ACPI_HANDLE(&adapter->dev);
+ lookup.device_handle = handle;
+ lookup.info = &info;
+
+ /*
+ * Look up for I2cSerialBus resource with ResourceSource that
+ * matches with this adapter.
+ */
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list,
- acpi_i2c_add_resource, &info);
+ acpi_i2c_find_address, &lookup);
acpi_dev_free_resource_list(&resource_list);
if (ret < 0 || !info.addr)
return AE_OK;
+ /* Then fill IRQ number if any */
+ ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+ if (ret < 0)
+ return AE_OK;
+
+ resource_list_for_each_entry(entry, &resource_list) {
+ if (resource_type(entry->res) == IORESOURCE_IRQ) {
+ info.irq = entry->res->start;
+ break;
+ }
+ }
+
+ acpi_dev_free_resource_list(&resource_list);
+
adev->power.flags.ignore_parent = true;
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
if (!i2c_new_device(adapter, &info)) {
@@ -160,6 +198,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
return AE_OK;
}
+#define ACPI_I2C_MAX_SCAN_DEPTH 32
+
/**
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
* @adap: pointer to adapter
@@ -170,17 +210,13 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
*/
static void acpi_i2c_register_devices(struct i2c_adapter *adap)
{
- acpi_handle handle;
acpi_status status;
- if (!adap->dev.parent)
+ if (!has_acpi_companion(&adap->dev))
return;
- handle = ACPI_HANDLE(adap->dev.parent);
- if (!handle)
- return;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_I2C_MAX_SCAN_DEPTH,
acpi_i2c_add_device, NULL,
adap, NULL);
if (ACPI_FAILURE(status))
@@ -679,7 +715,7 @@ static int i2c_device_probe(struct device *dev)
if (wakeirq > 0 && wakeirq != client->irq)
status = dev_pm_set_dedicated_wake_irq(dev, wakeirq);
else if (client->irq > 0)
- status = dev_pm_set_wake_irq(dev, wakeirq);
+ status = dev_pm_set_wake_irq(dev, client->irq);
else
status = 0;
@@ -694,12 +730,12 @@ static int i2c_device_probe(struct device *dev)
goto err_clear_wakeup_irq;
status = dev_pm_domain_attach(&client->dev, true);
- if (status != -EPROBE_DEFER) {
- status = driver->probe(client, i2c_match_id(driver->id_table,
- client));
- if (status)
- goto err_detach_pm_domain;
- }
+ if (status == -EPROBE_DEFER)
+ goto err_clear_wakeup_irq;
+
+ status = driver->probe(client, i2c_match_id(driver->id_table, client));
+ if (status)
+ goto err_detach_pm_domain;
return 0;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 71c7a3975b62..2413ec9f8207 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -235,7 +235,7 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
return result;
}
-static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
+static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
unsigned long arg)
{
struct i2c_rdwr_ioctl_data rdwr_arg;
@@ -250,7 +250,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
- if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+ if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
return -EINVAL;
rdwr_pa = memdup_user(rdwr_arg.msgs,
@@ -421,16 +421,6 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case I2C_SLAVE:
case I2C_SLAVE_FORCE:
- /* NOTE: devices set up to work with "new style" drivers
- * can't use I2C_SLAVE, even when the device node is not
- * bound to a driver. Only I2C_SLAVE_FORCE will work.
- *
- * Setting the PEC flag here won't affect kernel drivers,
- * which will be using the i2c_client node registered with
- * the driver model core. Likewise, when that client has
- * the PEC flag already set, the i2c-dev driver won't see
- * (or use) this setting.
- */
if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
@@ -446,6 +436,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
client->flags &= ~I2C_M_TEN;
return 0;
case I2C_PEC:
+ /*
+ * Setting the PEC flag here won't affect kernel drivers,
+ * which will be using the i2c_client node registered with
+ * the driver model core. Likewise, when that client has
+ * the PEC flag already set, the i2c-dev driver won't see
+ * (or use) this setting.
+ */
if (arg)
client->flags |= I2C_CLIENT_PEC;
else
@@ -456,7 +453,7 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return put_user(funcs, (unsigned long __user *)arg);
case I2C_RDWR:
- return i2cdev_ioctl_rdrw(client, arg);
+ return i2cdev_ioctl_rdwr(client, arg);
case I2C_SMBUS:
return i2cdev_ioctl_smbus(client, arg);
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 2ba7c0fbc615..00fc5b1c7b66 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/of.h>
+#include <linux/acpi.h>
/* multiplexer per channel data */
struct i2c_mux_priv {
@@ -173,6 +174,13 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
}
}
+ /*
+ * Associate the mux channel with an ACPI node.
+ */
+ if (has_acpi_companion(mux_dev))
+ acpi_preset_companion(&priv->adap.dev, ACPI_COMPANION(mux_dev),
+ chan_id);
+
if (force_nr) {
priv->adap.nr = force_nr;
ret = i2c_add_numbered_adapter(&priv->adap);
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 1362ad80a76c..05352f490d60 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -92,7 +92,7 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
struct request *rq;
int error;
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_DRV_PRIV;
rq->special = (char *)pc;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 64a6b827b3dd..ef907fd5ba98 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -441,7 +441,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
struct request *rq;
int error;
- rq = blk_get_request(drive->queue, write, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, write, __GFP_RECLAIM);
memcpy(rq->cmd, cmd, BLK_MAX_CDB);
rq->cmd_type = REQ_TYPE_ATA_PC;
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 066e39036518..474173eb31bb 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -303,7 +303,7 @@ int ide_cdrom_reset(struct cdrom_device_info *cdi)
struct request *rq;
int ret;
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_DRV_PRIV;
rq->cmd_flags = REQ_QUIET;
ret = blk_execute_rq(drive->queue, cd->disk, rq, 0);
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c
index b05a74d78ef5..0dd43b4fcec6 100644
--- a/drivers/ide/ide-devsets.c
+++ b/drivers/ide/ide-devsets.c
@@ -165,7 +165,7 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
if (!(setting->flags & DS_SYNC))
return setting->set(drive, arg);
- rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq = blk_get_request(q, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_DRV_PRIV;
rq->cmd_len = 5;
rq->cmd[0] = REQ_DEVSET_EXEC;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 56b9708894a5..37a8a907febe 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -477,7 +477,7 @@ static int set_multcount(ide_drive_t *drive, int arg)
if (drive->special_flags & IDE_SFLAG_SET_MULTMODE)
return -EBUSY;
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
drive->mult_req = arg;
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index aa2e9b77b20d..d05db2469209 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -125,7 +125,7 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
if (NULL == (void *) arg) {
struct request *rq;
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
err = blk_execute_rq(drive->queue, NULL, rq, 0);
blk_put_request(rq);
@@ -221,7 +221,7 @@ static int generic_drive_reset(ide_drive_t *drive)
struct request *rq;
int ret = 0;
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_DRV_PRIV;
rq->cmd_len = 1;
rq->cmd[0] = REQ_DRIVE_RESET;
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index c80868520488..2d7dca56dd24 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -31,7 +31,7 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
}
spin_unlock_irq(&hwif->lock);
- rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq = blk_get_request(q, READ, __GFP_RECLAIM);
rq->cmd[0] = REQ_PARK_HEADS;
rq->cmd_len = 1;
rq->cmd_type = REQ_TYPE_DRV_PRIV;
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 081e43458d50..e34af488693a 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -18,7 +18,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
}
memset(&rqpm, 0, sizeof(rqpm));
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_ATA_PM_SUSPEND;
rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_SUSPEND;
@@ -88,7 +88,7 @@ int generic_ide_resume(struct device *dev)
}
memset(&rqpm, 0, sizeof(rqpm));
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_ATA_PM_RESUME;
rq->cmd_flags |= REQ_PREEMPT;
rq->special = &rqpm;
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index f5d51d1d09ee..12fa04997dcc 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -852,7 +852,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE);
BUG_ON(size < 0 || size % tape->blk_size);
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_DRV_PRIV;
rq->cmd[13] = cmd;
rq->rq_disk = tape->disk;
@@ -860,7 +860,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
if (size) {
ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
- __GFP_WAIT);
+ __GFP_RECLAIM);
if (ret)
goto out_put;
}
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 0979e126fff1..a716693417a3 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -430,7 +430,7 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
int error;
int rw = !(cmd->tf_flags & IDE_TFLAG_WRITE) ? READ : WRITE;
- rq = blk_get_request(drive->queue, rw, __GFP_WAIT);
+ rq = blk_get_request(drive->queue, rw, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
/*
@@ -441,7 +441,7 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
*/
if (nsect) {
error = blk_rq_map_kern(drive->queue, rq, buf,
- nsect * SECTOR_SIZE, __GFP_WAIT);
+ nsect * SECTOR_SIZE, __GFP_RECLAIM);
if (error)
goto put_req;
}
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index df73cbd9387e..9ad014a7afc7 100644
--- a/drivers/ide/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
@@ -22,6 +22,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/ktime.h>
#include <asm/io.h>
@@ -243,13 +244,13 @@ static long read_counter(u32 dma_base)
*/
static long detect_pll_input_clock(unsigned long dma_base)
{
- struct timeval start_time, end_time;
+ ktime_t start_time, end_time;
long start_count, end_count;
long pll_input, usec_elapsed;
u8 scr1;
start_count = read_counter(dma_base);
- do_gettimeofday(&start_time);
+ start_time = ktime_get();
/* Start the test mode */
outb(0x01, dma_base + 0x01);
@@ -261,7 +262,7 @@ static long detect_pll_input_clock(unsigned long dma_base)
mdelay(10);
end_count = read_counter(dma_base);
- do_gettimeofday(&end_time);
+ end_time = ktime_get();
/* Stop the test mode */
outb(0x01, dma_base + 0x01);
@@ -273,8 +274,7 @@ static long detect_pll_input_clock(unsigned long dma_base)
* Calculate the input clock in Hz
* (the clock counter is 30 bit wide and counts down)
*/
- usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
- (end_time.tv_usec - start_time.tv_usec);
+ usec_elapsed = ktime_us_delta(end_time, start_time);
pll_input = ((start_count - end_count) & 0x3fffffff) / 10 *
(10000000 / usec_elapsed);
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 98ba761cbb9c..923f56598d4b 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -263,7 +263,6 @@ MODULE_DEVICE_TABLE(spi, kxsd9_id);
static struct spi_driver kxsd9_driver = {
.driver = {
.name = "kxsd9",
- .owner = THIS_MODULE,
},
.probe = kxsd9_probe,
.remove = kxsd9_remove,
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 9d973f1e74ac..70f042797f15 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -149,8 +149,6 @@
#define ST_ACCEL_4_BDU_MASK 0x40
#define ST_ACCEL_4_DRDY_IRQ_ADDR 0x21
#define ST_ACCEL_4_DRDY_IRQ_INT1_MASK 0x04
-#define ST_ACCEL_4_IG1_EN_ADDR 0x21
-#define ST_ACCEL_4_IG1_EN_MASK 0x08
#define ST_ACCEL_4_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 5 */
@@ -490,10 +488,6 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.drdy_irq = {
.addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
- .ig1 = {
- .en_addr = ST_ACCEL_4_IG1_EN_ADDR,
- .en_mask = ST_ACCEL_4_IG1_EN_MASK,
- },
},
.multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
.bootime = 2, /* guess */
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index e82bedfaeb9b..fcd5847a3fd3 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -65,7 +65,6 @@ MODULE_DEVICE_TABLE(spi, st_accel_id_table);
static struct spi_driver st_accel_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-accel-spi",
},
.probe = st_accel_spi_probe,
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 70f78c3062a7..21e19b60e2b9 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -509,7 +509,6 @@ MODULE_DEVICE_TABLE(spi, ad7266_id);
static struct spi_driver ad7266_driver = {
.driver = {
.name = "ad7266",
- .owner = THIS_MODULE,
},
.probe = ad7266_probe,
.remove = ad7266_remove,
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index 4a8c0a2f49b6..62bb8f7ce4a0 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -378,7 +378,6 @@ MODULE_DEVICE_TABLE(spi, ad7298_id);
static struct spi_driver ad7298_driver = {
.driver = {
.name = "ad7298",
- .owner = THIS_MODULE,
},
.probe = ad7298_probe,
.remove = ad7298_remove,
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index ce400ec176f1..be85c2a0ad97 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -302,7 +302,6 @@ MODULE_DEVICE_TABLE(spi, ad7476_id);
static struct spi_driver ad7476_driver = {
.driver = {
.name = "ad7476",
- .owner = THIS_MODULE,
},
.probe = ad7476_probe,
.remove = ad7476_remove,
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index c19f8fd1b4b7..cf172d58cd44 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -440,7 +440,6 @@ MODULE_DEVICE_TABLE(spi, ad7791_spi_ids);
static struct spi_driver ad7791_driver = {
.driver = {
.name = "ad7791",
- .owner = THIS_MODULE,
},
.probe = ad7791_probe,
.remove = ad7791_remove,
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index d3eeb3fb46c2..7b07bb651671 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -101,7 +101,7 @@
#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */
/* ID Register Bit Designations (AD7793_REG_ID) */
-#define AD7785_ID 0xB
+#define AD7785_ID 0x3
#define AD7792_ID 0xA
#define AD7793_ID 0xB
#define AD7794_ID 0xF
@@ -851,7 +851,6 @@ MODULE_DEVICE_TABLE(spi, ad7793_id);
static struct spi_driver ad7793_driver = {
.driver = {
.name = "ad7793",
- .owner = THIS_MODULE,
},
.probe = ad7793_probe,
.remove = ad7793_remove,
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 2fd012ee99f5..2d3c397e66ad 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -356,7 +356,6 @@ MODULE_DEVICE_TABLE(spi, ad7887_id);
static struct spi_driver ad7887_driver = {
.driver = {
.name = "ad7887",
- .owner = THIS_MODULE,
},
.probe = ad7887_probe,
.remove = ad7887_remove,
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 28732c28e819..45e29ccd824f 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -357,7 +357,6 @@ MODULE_DEVICE_TABLE(spi, ad7923_id);
static struct spi_driver ad7923_driver = {
.driver = {
.name = "ad7923",
- .owner = THIS_MODULE,
},
.probe = ad7923_probe,
.remove = ad7923_remove,
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
index 54a8302aaace..41d495c6035e 100644
--- a/drivers/iio/adc/max1027.c
+++ b/drivers/iio/adc/max1027.c
@@ -509,7 +509,6 @@ static struct spi_driver max1027_driver = {
.driver = {
.name = "max1027",
.of_match_table = of_match_ptr(max1027_adc_dt_ids),
- .owner = THIS_MODULE,
},
.probe = max1027_probe,
.remove = max1027_remove,
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 9fcb8b61e300..d1c05f6eed18 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -433,7 +433,6 @@ static struct spi_driver mcp320x_driver = {
.driver = {
.name = "mcp320x",
.of_match_table = of_match_ptr(mcp320x_dt_ids),
- .owner = THIS_MODULE,
},
.probe = mcp320x_probe,
.remove = mcp320x_remove,
diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c
index 98c0d2b444bf..ff6f7f63c8d9 100644
--- a/drivers/iio/adc/ti-adc128s052.c
+++ b/drivers/iio/adc/ti-adc128s052.c
@@ -192,7 +192,6 @@ static struct spi_driver adc128_driver = {
.driver = {
.name = "adc128s052",
.of_match_table = of_match_ptr(adc128_of_match),
- .owner = THIS_MODULE,
},
.probe = adc128_probe,
.remove = adc128_remove,
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index ebe415f10640..0c74869a540a 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -45,13 +45,18 @@
#include <linux/types.h>
#include <linux/gfp.h>
#include <linux/err.h>
+#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
+#define TWL4030_USB_SEL_MADC_MCPC (1<<3)
+#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB
+
/**
* struct twl4030_madc_data - a container for madc info
* @dev: Pointer to device structure for madc
* @lock: Mutex protecting this data structure
+ * @regulator: Pointer to bias regulator for madc
* @requests: Array of request struct corresponding to SW1, SW2 and RT
* @use_second_irq: IRQ selection (main or co-processor)
* @imr: Interrupt mask register of MADC
@@ -60,6 +65,7 @@
struct twl4030_madc_data {
struct device *dev;
struct mutex lock; /* mutex protecting this data structure */
+ struct regulator *usb3v1;
struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
bool use_second_irq;
u8 imr;
@@ -841,6 +847,32 @@ static int twl4030_madc_probe(struct platform_device *pdev)
}
twl4030_madc = madc;
+ /* Configure MADC[3:6] */
+ ret = twl_i2c_read_u8(TWL_MODULE_USB, &regval,
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to read reg CARKIT_ANA_CTRL 0x%X\n",
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ goto err_i2c;
+ }
+ regval |= TWL4030_USB_SEL_MADC_MCPC;
+ ret = twl_i2c_write_u8(TWL_MODULE_USB, regval,
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to write reg CARKIT_ANA_CTRL 0x%X\n",
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ goto err_i2c;
+ }
+
+ /* Enable 3v1 bias regulator for MADC[3:6] */
+ madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1");
+ if (IS_ERR(madc->usb3v1))
+ return -ENODEV;
+
+ ret = regulator_enable(madc->usb3v1);
+ if (ret)
+ dev_err(madc->dev, "could not enable 3v1 bias regulator\n");
+
ret = iio_device_register(iio_dev);
if (ret) {
dev_err(&pdev->dev, "could not register iio device\n");
@@ -866,6 +898,8 @@ static int twl4030_madc_remove(struct platform_device *pdev)
twl4030_madc_set_current_generator(madc, 0, 0);
twl4030_madc_set_power(madc, 0);
+ regulator_disable(madc->usb3v1);
+
return 0;
}
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 599cde3d03a1..b10f629cc44b 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -106,6 +106,13 @@
#define DEFAULT_SAMPLE_TIME 1000
+/* V at 25°C of 696 mV */
+#define VF610_VTEMP25_3V0 950
+/* V at 25°C of 699 mV */
+#define VF610_VTEMP25_3V3 867
+/* Typical sensor slope coefficient at all temperatures */
+#define VF610_TEMP_SLOPE_COEFF 1840
+
enum clk_sel {
VF610_ADCIOC_BUSCLK_SET,
VF610_ADCIOC_ALTCLK_SET,
@@ -197,6 +204,8 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
adc_feature->clk_div = 8;
}
+ adck_rate = ipg_rate / adc_feature->clk_div;
+
/*
* Determine the long sample time adder value to be used based
* on the default minimum sample time provided.
@@ -221,7 +230,6 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
* BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
* LSTAdder(Long Sample Time): 3, 5, 7, 9, 13, 17, 21, 25 ADCK cycles
*/
- adck_rate = ipg_rate / info->adc_feature.clk_div;
for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
info->sample_freq_avail[i] =
adck_rate / (6 + vf610_hw_avgs[i] *
@@ -663,11 +671,13 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
break;
case IIO_TEMP:
/*
- * Calculate in degree Celsius times 1000
- * Using sensor slope of 1.84 mV/°C and
- * V at 25°C of 696 mV
- */
- *val = 25000 - ((int)info->value - 864) * 1000000 / 1840;
+ * Calculate in degree Celsius times 1000
+ * Using the typical sensor slope of 1.84 mV/°C
+ * and VREFH_ADC at 3.3V, V at 25°C of 699 mV
+ */
+ *val = 25000 - ((int)info->value - VF610_VTEMP25_3V3) *
+ 1000000 / VF610_TEMP_SLOPE_COEFF;
+
break;
default:
mutex_unlock(&indio_dev->mlock);
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index c2b5f1095848..0a6beb3d99cb 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -841,6 +841,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
case XADC_REG_VCCINT:
case XADC_REG_VCCAUX:
case XADC_REG_VREFP:
+ case XADC_REG_VREFN:
case XADC_REG_VCCBRAM:
case XADC_REG_VCCPINT:
case XADC_REG_VCCPAUX:
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index 32b82a2dc894..102c7174da5b 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -200,7 +200,6 @@ MODULE_DEVICE_TABLE(spi, ad8366_id);
static struct spi_driver ad8366_driver = {
.driver = {
.name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
},
.probe = ad8366_probe,
.remove = ad8366_remove,
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index d338bb595db3..ea7adb638d99 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -700,7 +700,6 @@ static struct spi_driver ssp_driver = {
.remove = ssp_remove,
.driver = {
.pm = &ssp_pm_ops,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(ssp_of_match),
.name = "sensorhub"
},
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index c067e6821496..81ca0081a019 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -113,12 +113,16 @@ enum ad5064_type {
ID_AD5065,
ID_AD5628_1,
ID_AD5628_2,
+ ID_AD5629_1,
+ ID_AD5629_2,
ID_AD5648_1,
ID_AD5648_2,
ID_AD5666_1,
ID_AD5666_2,
ID_AD5668_1,
ID_AD5668_2,
+ ID_AD5669_1,
+ ID_AD5669_2,
};
static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
@@ -291,7 +295,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
{ },
};
-#define AD5064_CHANNEL(chan, addr, bits) { \
+#define AD5064_CHANNEL(chan, addr, bits, _shift) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
@@ -303,36 +307,39 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
.sign = 'u', \
.realbits = (bits), \
.storagebits = 16, \
- .shift = 20 - bits, \
+ .shift = (_shift), \
}, \
.ext_info = ad5064_ext_info, \
}
-#define DECLARE_AD5064_CHANNELS(name, bits) \
+#define DECLARE_AD5064_CHANNELS(name, bits, shift) \
const struct iio_chan_spec name[] = { \
- AD5064_CHANNEL(0, 0, bits), \
- AD5064_CHANNEL(1, 1, bits), \
- AD5064_CHANNEL(2, 2, bits), \
- AD5064_CHANNEL(3, 3, bits), \
- AD5064_CHANNEL(4, 4, bits), \
- AD5064_CHANNEL(5, 5, bits), \
- AD5064_CHANNEL(6, 6, bits), \
- AD5064_CHANNEL(7, 7, bits), \
+ AD5064_CHANNEL(0, 0, bits, shift), \
+ AD5064_CHANNEL(1, 1, bits, shift), \
+ AD5064_CHANNEL(2, 2, bits, shift), \
+ AD5064_CHANNEL(3, 3, bits, shift), \
+ AD5064_CHANNEL(4, 4, bits, shift), \
+ AD5064_CHANNEL(5, 5, bits, shift), \
+ AD5064_CHANNEL(6, 6, bits, shift), \
+ AD5064_CHANNEL(7, 7, bits, shift), \
}
-#define DECLARE_AD5065_CHANNELS(name, bits) \
+#define DECLARE_AD5065_CHANNELS(name, bits, shift) \
const struct iio_chan_spec name[] = { \
- AD5064_CHANNEL(0, 0, bits), \
- AD5064_CHANNEL(1, 3, bits), \
+ AD5064_CHANNEL(0, 0, bits, shift), \
+ AD5064_CHANNEL(1, 3, bits, shift), \
}
-static DECLARE_AD5064_CHANNELS(ad5024_channels, 12);
-static DECLARE_AD5064_CHANNELS(ad5044_channels, 14);
-static DECLARE_AD5064_CHANNELS(ad5064_channels, 16);
+static DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8);
+static DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6);
+static DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4);
-static DECLARE_AD5065_CHANNELS(ad5025_channels, 12);
-static DECLARE_AD5065_CHANNELS(ad5045_channels, 14);
-static DECLARE_AD5065_CHANNELS(ad5065_channels, 16);
+static DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8);
+static DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6);
+static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4);
+
+static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4);
+static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0);
static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
[ID_AD5024] = {
@@ -382,6 +389,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
.channels = ad5024_channels,
.num_channels = 8,
},
+ [ID_AD5629_1] = {
+ .shared_vref = true,
+ .internal_vref = 2500000,
+ .channels = ad5629_channels,
+ .num_channels = 8,
+ },
+ [ID_AD5629_2] = {
+ .shared_vref = true,
+ .internal_vref = 5000000,
+ .channels = ad5629_channels,
+ .num_channels = 8,
+ },
[ID_AD5648_1] = {
.shared_vref = true,
.internal_vref = 2500000,
@@ -418,6 +437,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
.channels = ad5064_channels,
.num_channels = 8,
},
+ [ID_AD5669_1] = {
+ .shared_vref = true,
+ .internal_vref = 2500000,
+ .channels = ad5669_channels,
+ .num_channels = 8,
+ },
+ [ID_AD5669_2] = {
+ .shared_vref = true,
+ .internal_vref = 5000000,
+ .channels = ad5669_channels,
+ .num_channels = 8,
+ },
};
static inline unsigned int ad5064_num_vref(struct ad5064_state *st)
@@ -568,7 +599,6 @@ MODULE_DEVICE_TABLE(spi, ad5064_spi_ids);
static struct spi_driver ad5064_spi_driver = {
.driver = {
.name = "ad5064",
- .owner = THIS_MODULE,
},
.probe = ad5064_spi_probe,
.remove = ad5064_spi_remove,
@@ -598,10 +628,16 @@ static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd,
unsigned int addr, unsigned int val)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
+ int ret;
st->data.i2c[0] = (cmd << 4) | addr;
put_unaligned_be16(val, &st->data.i2c[1]);
- return i2c_master_send(i2c, st->data.i2c, 3);
+
+ ret = i2c_master_send(i2c, st->data.i2c, 3);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int ad5064_i2c_probe(struct i2c_client *i2c,
@@ -617,12 +653,12 @@ static int ad5064_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id ad5064_i2c_ids[] = {
- {"ad5629-1", ID_AD5628_1},
- {"ad5629-2", ID_AD5628_2},
- {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */
- {"ad5669-1", ID_AD5668_1},
- {"ad5669-2", ID_AD5668_2},
- {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */
+ {"ad5629-1", ID_AD5629_1},
+ {"ad5629-2", ID_AD5629_2},
+ {"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */
+ {"ad5669-1", ID_AD5669_1},
+ {"ad5669-2", ID_AD5669_2},
+ {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */
{}
};
MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c
index 64634d7f578e..8ba0e9c50176 100644
--- a/drivers/iio/dac/ad5360.c
+++ b/drivers/iio/dac/ad5360.c
@@ -549,7 +549,6 @@ MODULE_DEVICE_TABLE(spi, ad5360_ids);
static struct spi_driver ad5360_driver = {
.driver = {
.name = "ad5360",
- .owner = THIS_MODULE,
},
.probe = ad5360_probe,
.remove = ad5360_remove,
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 130de9b3e0bf..97d2c5111f43 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -519,7 +519,6 @@ MODULE_DEVICE_TABLE(spi, ad5380_spi_ids);
static struct spi_driver ad5380_spi_driver = {
.driver = {
.name = "ad5380",
- .owner = THIS_MODULE,
},
.probe = ad5380_spi_probe,
.remove = ad5380_spi_remove,
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 787ef1d859c6..968712be967f 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -524,7 +524,6 @@ static int ad5421_probe(struct spi_device *spi)
static struct spi_driver ad5421_driver = {
.driver = {
.name = "ad5421",
- .owner = THIS_MODULE,
},
.probe = ad5421_probe,
};
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 07e17d72a3f3..b555552a0d80 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -481,7 +481,6 @@ static int ad5446_spi_remove(struct spi_device *spi)
static struct spi_driver ad5446_spi_driver = {
.driver = {
.name = "ad5446",
- .owner = THIS_MODULE,
},
.probe = ad5446_spi_probe,
.remove = ad5446_spi_remove,
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
index 64d7256cbb6d..5f3202339420 100644
--- a/drivers/iio/dac/ad5449.c
+++ b/drivers/iio/dac/ad5449.c
@@ -356,7 +356,6 @@ MODULE_DEVICE_TABLE(spi, ad5449_spi_ids);
static struct spi_driver ad5449_spi_driver = {
.driver = {
.name = "ad5449",
- .owner = THIS_MODULE,
},
.probe = ad5449_spi_probe,
.remove = ad5449_spi_remove,
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e6e9756580af..4e4c20d6d8b5 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -363,7 +363,6 @@ MODULE_DEVICE_TABLE(spi, ad5504_id);
static struct spi_driver ad5504_driver = {
.driver = {
.name = "ad5504",
- .owner = THIS_MODULE,
},
.probe = ad5504_probe,
.remove = ad5504_remove,
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index e98428df0d44..5489ec43b95d 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -306,7 +306,6 @@ MODULE_DEVICE_TABLE(spi, ad5624r_id);
static struct spi_driver ad5624r_driver = {
.driver = {
.name = "ad5624r",
- .owner = THIS_MODULE,
},
.probe = ad5624r_probe,
.remove = ad5624r_remove,
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 15c73e20272d..d1d8450c19f6 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -395,7 +395,6 @@ MODULE_DEVICE_TABLE(spi, ad5686_id);
static struct spi_driver ad5686_driver = {
.driver = {
.name = "ad5686",
- .owner = THIS_MODULE,
},
.probe = ad5686_probe,
.remove = ad5686_remove,
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index a7c851f62d7c..bfb350a85a16 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -610,7 +610,6 @@ MODULE_DEVICE_TABLE(spi, ad5755_id);
static struct spi_driver ad5755_driver = {
.driver = {
.name = "ad5755",
- .owner = THIS_MODULE,
},
.probe = ad5755_probe,
.id_table = ad5755_id,
diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c
index d0d38165339d..9a547bbf7d2b 100644
--- a/drivers/iio/dac/ad5764.c
+++ b/drivers/iio/dac/ad5764.c
@@ -357,7 +357,6 @@ MODULE_DEVICE_TABLE(spi, ad5764_ids);
static struct spi_driver ad5764_driver = {
.driver = {
.name = "ad5764",
- .owner = THIS_MODULE,
},
.probe = ad5764_probe,
.remove = ad5764_remove,
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 5ba785f18589..33e4ae5c42f8 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -461,7 +461,6 @@ MODULE_DEVICE_TABLE(spi, ad5791_id);
static struct spi_driver ad5791_driver = {
.driver = {
.name = "ad5791",
- .owner = THIS_MODULE,
},
.probe = ad5791_probe,
.remove = ad5791_remove,
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index 18a4ad5ff8c5..e690dd11e99f 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -297,7 +297,6 @@ static struct spi_driver ad7303_driver = {
.driver = {
.name = "ad7303",
.of_match_table = of_match_ptr(ad7303_spi_of_match),
- .owner = THIS_MODULE,
},
.probe = ad7303_probe,
.remove = ad7303_remove,
diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c
index 92cf4ca6981d..3854d201a5d6 100644
--- a/drivers/iio/dac/mcp4922.c
+++ b/drivers/iio/dac/mcp4922.c
@@ -203,7 +203,6 @@ MODULE_DEVICE_TABLE(spi, mcp4922_id);
static struct spi_driver mcp4922_driver = {
.driver = {
.name = "mcp4922",
- .owner = THIS_MODULE,
},
.probe = mcp4922_probe,
.remove = mcp4922_remove,
diff --git a/drivers/iio/dummy/iio_simple_dummy.c b/drivers/iio/dummy/iio_simple_dummy.c
index 381f90ff468a..43fe4ba7d0dc 100644
--- a/drivers/iio/dummy/iio_simple_dummy.c
+++ b/drivers/iio/dummy/iio_simple_dummy.c
@@ -137,7 +137,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
*/
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
/* The ordering of elements in the buffer via an enum */
- .scan_index = voltage0,
+ .scan_index = DUMMY_INDEX_VOLTAGE_0,
.scan_type = { /* Description of storage in buffer */
.sign = 'u', /* unsigned */
.realbits = 13, /* 13 bits */
@@ -176,7 +176,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
* sampling_frequency
* The frequency in Hz at which the channels are sampled
*/
- .scan_index = diffvoltage1m2,
+ .scan_index = DUMMY_INDEX_DIFFVOLTAGE_1M2,
.scan_type = { /* Description of storage in buffer */
.sign = 's', /* signed */
.realbits = 12, /* 12 bits */
@@ -194,7 +194,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- .scan_index = diffvoltage3m4,
+ .scan_index = DUMMY_INDEX_DIFFVOLTAGE_3M4,
.scan_type = {
.sign = 's',
.realbits = 11,
@@ -221,7 +221,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
BIT(IIO_CHAN_INFO_CALIBSCALE) |
BIT(IIO_CHAN_INFO_CALIBBIAS),
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- .scan_index = accelx,
+ .scan_index = DUMMY_INDEX_ACCELX,
.scan_type = { /* Description of storage in buffer */
.sign = 's', /* signed */
.realbits = 16, /* 16 bits */
@@ -364,8 +364,7 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT_PLUS_MICRO;
break;
case 1:
- /* all differential adc channels ->
- * 0.000001344 */
+ /* all differential adc -> 0.000001344 */
*val = 0;
*val2 = 1344;
ret = IIO_VAL_INT_PLUS_NANO;
diff --git a/drivers/iio/dummy/iio_simple_dummy.h b/drivers/iio/dummy/iio_simple_dummy.h
index 5c2f4d0401dc..b9069a180672 100644
--- a/drivers/iio/dummy/iio_simple_dummy.h
+++ b/drivers/iio/dummy/iio_simple_dummy.h
@@ -98,18 +98,18 @@ iio_simple_dummy_events_unregister(struct iio_dev *indio_dev)
/**
* enum iio_simple_dummy_scan_elements - scan index enum
- * @voltage0: the single ended voltage channel
- * @diffvoltage1m2: first differential channel
- * @diffvoltage3m4: second differenial channel
- * @accelx: acceleration channel
+ * @DUMMY_INDEX_VOLTAGE_0: the single ended voltage channel
+ * @DUMMY_INDEX_DIFFVOLTAGE_1M2: first differential channel
+ * @DUMMY_INDEX_DIFFVOLTAGE_3M4: second differential channel
+ * @DUMMY_INDEX_ACCELX: acceleration channel
*
* Enum provides convenient numbering for the scan index.
*/
enum iio_simple_dummy_scan_elements {
- voltage0,
- diffvoltage1m2,
- diffvoltage3m4,
- accelx,
+ DUMMY_INDEX_VOLTAGE_0,
+ DUMMY_INDEX_DIFFVOLTAGE_1M2,
+ DUMMY_INDEX_DIFFVOLTAGE_3M4,
+ DUMMY_INDEX_ACCELX,
};
#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER
diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c
index 00ed7745f3c5..cf44a6f79431 100644
--- a/drivers/iio/dummy/iio_simple_dummy_buffer.c
+++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c
@@ -27,10 +27,10 @@
/* Some fake data */
static const s16 fakedata[] = {
- [voltage0] = 7,
- [diffvoltage1m2] = -33,
- [diffvoltage3m4] = -2,
- [accelx] = 344,
+ [DUMMY_INDEX_VOLTAGE_0] = 7,
+ [DUMMY_INDEX_DIFFVOLTAGE_1M2] = -33,
+ [DUMMY_INDEX_DIFFVOLTAGE_3M4] = -2,
+ [DUMMY_INDEX_ACCELX] = 344,
};
/**
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index 50ed8d1ca45a..44a30f286de1 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -1027,7 +1027,6 @@ MODULE_DEVICE_TABLE(spi, ad9523_id);
static struct spi_driver ad9523_driver = {
.driver = {
.name = "ad9523",
- .owner = THIS_MODULE,
},
.probe = ad9523_probe,
.remove = ad9523_remove,
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index 73f27e0a08dd..d2d824b446f5 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -634,7 +634,6 @@ static struct spi_driver adf4350_driver = {
.driver = {
.name = "adf4350",
.of_match_table = of_match_ptr(adf4350_of_match),
- .owner = THIS_MODULE,
},
.probe = adf4350_probe,
.remove = adf4350_remove,
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
index add509837269..ad31a1372a04 100644
--- a/drivers/iio/gyro/adis16080.c
+++ b/drivers/iio/gyro/adis16080.c
@@ -228,7 +228,6 @@ MODULE_DEVICE_TABLE(spi, adis16080_ids);
static struct spi_driver adis16080_driver = {
.driver = {
.name = "adis16080",
- .owner = THIS_MODULE,
},
.probe = adis16080_probe,
.remove = adis16080_remove,
diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c
index 8d08c7ed1ea6..e5241f41e65e 100644
--- a/drivers/iio/gyro/adis16130.c
+++ b/drivers/iio/gyro/adis16130.c
@@ -167,7 +167,6 @@ static int adis16130_probe(struct spi_device *spi)
static struct spi_driver adis16130_driver = {
.driver = {
.name = "adis16130",
- .owner = THIS_MODULE,
},
.probe = adis16130_probe,
};
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
index bb09bff25103..b04faf93e1bc 100644
--- a/drivers/iio/gyro/adis16136.c
+++ b/drivers/iio/gyro/adis16136.c
@@ -572,7 +572,6 @@ MODULE_DEVICE_TABLE(spi, adis16136_ids);
static struct spi_driver adis16136_driver = {
.driver = {
.name = "adis16136",
- .owner = THIS_MODULE,
},
.id_table = adis16136_ids,
.probe = adis16136_probe,
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 00c6ad9bf35f..7da8825f4791 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -435,7 +435,6 @@ MODULE_DEVICE_TABLE(spi, adis16260_id);
static struct spi_driver adis16260_driver = {
.driver = {
.name = "adis16260",
- .owner = THIS_MODULE,
},
.probe = adis16260_probe,
.remove = adis16260_remove,
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index eb0e08ec9e20..a330d4288bb0 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -456,7 +456,6 @@ MODULE_DEVICE_TABLE(spi, adxrs450_id);
static struct spi_driver adxrs450_driver = {
.driver = {
.name = "adxrs450",
- .owner = THIS_MODULE,
},
.probe = adxrs450_probe,
.id_table = adxrs450_id,
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
index e59bead6bc3c..d2b7a5fa344c 100644
--- a/drivers/iio/gyro/st_gyro_spi.c
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -60,7 +60,6 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
static struct spi_driver st_gyro_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-gyro-spi",
},
.probe = st_gyro_spi_probe,
diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c
index 12128d1ca570..71991b5c0658 100644
--- a/drivers/iio/humidity/si7020.c
+++ b/drivers/iio/humidity/si7020.c
@@ -50,10 +50,10 @@ static int si7020_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- ret = i2c_smbus_read_word_data(*client,
- chan->type == IIO_TEMP ?
- SI7020CMD_TEMP_HOLD :
- SI7020CMD_RH_HOLD);
+ ret = i2c_smbus_read_word_swapped(*client,
+ chan->type == IIO_TEMP ?
+ SI7020CMD_TEMP_HOLD :
+ SI7020CMD_RH_HOLD);
if (ret < 0)
return ret;
*val = ret >> 2;
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index 72bcc2491d1d..fb7c0dbed51c 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -990,7 +990,6 @@ MODULE_DEVICE_TABLE(spi, adis16400_id);
static struct spi_driver adis16400_driver = {
.driver = {
.name = "adis16400",
- .owner = THIS_MODULE,
},
.id_table = adis16400_id,
.probe = adis16400_probe,
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index 16d430461414..8cf84d3488b2 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -898,7 +898,6 @@ MODULE_DEVICE_TABLE(spi, adis16480_ids);
static struct spi_driver adis16480_driver = {
.driver = {
.name = "adis16480",
- .owner = THIS_MODULE,
},
.id_table = adis16480_ids,
.probe = adis16480_probe,
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index 0abca2c6afa6..6325e7dc8e03 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE(spi, st_magn_id_table);
static struct spi_driver st_magn_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-magn-spi",
},
.probe = st_magn_spi_probe,
diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c
index 08ee6e88c79f..aaa0c4ba91a7 100644
--- a/drivers/iio/pressure/ms5611_spi.c
+++ b/drivers/iio/pressure/ms5611_spi.c
@@ -117,7 +117,6 @@ MODULE_DEVICE_TABLE(spi, ms5611_id);
static struct spi_driver ms5611_driver = {
.driver = {
.name = "ms5611",
- .owner = THIS_MODULE,
},
.id_table = ms5611_id,
.probe = ms5611_spi_probe,
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index 1ffa6d4d349c..40c0692ff1de 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -56,7 +56,6 @@ MODULE_DEVICE_TABLE(spi, st_press_id_table);
static struct spi_driver st_press_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-press-spi",
},
.probe = st_press_spi_probe,
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index e95035136889..f4d29d5dbd5f 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -450,7 +450,6 @@ static struct spi_driver as3935_driver = {
.driver = {
.name = "as3935",
.of_match_table = of_match_ptr(as3935_of_match),
- .owner = THIS_MODULE,
.pm = AS3935_PM_OPS,
},
.probe = as3935_probe,
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 746cdf56bc76..34b1adad07aa 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -128,7 +128,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
int ret = -EADDRNOTAVAIL;
if (dev_addr->bound_dev_if) {
- dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+ dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
if (!dev)
return -ENODEV;
ret = rdma_copy_addr(dev_addr, dev, NULL);
@@ -138,7 +138,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
switch (addr->sa_family) {
case AF_INET:
- dev = ip_dev_find(&init_net,
+ dev = ip_dev_find(dev_addr->net,
((struct sockaddr_in *) addr)->sin_addr.s_addr);
if (!dev)
@@ -149,12 +149,11 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
*vlan_id = rdma_vlan_dev_vlan_id(dev);
dev_put(dev);
break;
-
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
rcu_read_lock();
- for_each_netdev_rcu(&init_net, dev) {
- if (ipv6_chk_addr(&init_net,
+ for_each_netdev_rcu(dev_addr->net, dev) {
+ if (ipv6_chk_addr(dev_addr->net,
&((struct sockaddr_in6 *) addr)->sin6_addr,
dev, 1)) {
ret = rdma_copy_addr(dev_addr, dev, NULL);
@@ -236,7 +235,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
fl4.daddr = dst_ip;
fl4.saddr = src_ip;
fl4.flowi4_oif = addr->bound_dev_if;
- rt = ip_route_output_key(&init_net, &fl4);
+ rt = ip_route_output_key(addr->net, &fl4);
if (IS_ERR(rt)) {
ret = PTR_ERR(rt);
goto out;
@@ -278,12 +277,12 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
fl6.saddr = src_in->sin6_addr;
fl6.flowi6_oif = addr->bound_dev_if;
- dst = ip6_route_output(&init_net, NULL, &fl6);
+ dst = ip6_route_output(addr->net, NULL, &fl6);
if ((ret = dst->error))
goto put;
if (ipv6_addr_any(&fl6.saddr)) {
- ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev,
+ ret = ipv6_dev_get_saddr(addr->net, ip6_dst_idev(dst)->dev,
&fl6.daddr, 0, &fl6.saddr);
if (ret)
goto put;
@@ -458,7 +457,7 @@ static void resolve_cb(int status, struct sockaddr *src_addr,
}
int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgid,
- u8 *dmac, u16 *vlan_id)
+ u8 *dmac, u16 *vlan_id, int if_index)
{
int ret = 0;
struct rdma_dev_addr dev_addr;
@@ -476,6 +475,8 @@ int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgi
rdma_gid2ip(&dgid_addr._sockaddr, dgid);
memset(&dev_addr, 0, sizeof(dev_addr));
+ dev_addr.bound_dev_if = if_index;
+ dev_addr.net = &init_net;
ctx.addr = &dev_addr;
init_completion(&ctx.comp);
@@ -510,6 +511,7 @@ int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
rdma_gid2ip(&gid_addr._sockaddr, sgid);
memset(&dev_addr, 0, sizeof(dev_addr));
+ dev_addr.net = &init_net;
ret = rdma_translate_ip(&gid_addr._sockaddr, &dev_addr, vlan_id);
if (ret)
return ret;
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 0429040304fd..4fa524dfb6cf 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -126,7 +126,7 @@ void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *
mad_send_wr = container_of(send_buf,
struct ib_mad_send_wr_private,
send_buf);
- mad_send_wr->send_wr.wr.ud.port_num = port_num;
+ mad_send_wr->send_wr.port_num = port_num;
}
if (ib_post_send_mad(send_buf, NULL)) {
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 8f66c67ff0df..89bebeada38b 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -409,10 +409,10 @@ static int ib_cache_gid_find(struct ib_device *ib_dev,
mask, port, index);
}
-int ib_cache_gid_find_by_port(struct ib_device *ib_dev,
- const union ib_gid *gid,
- u8 port, struct net_device *ndev,
- u16 *index)
+int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
+ const union ib_gid *gid,
+ u8 port, struct net_device *ndev,
+ u16 *index)
{
int local_index;
struct ib_gid_table **ports_table = ib_dev->cache.gid_cache;
@@ -438,6 +438,82 @@ int ib_cache_gid_find_by_port(struct ib_device *ib_dev,
return -ENOENT;
}
+EXPORT_SYMBOL(ib_find_cached_gid_by_port);
+
+/**
+ * ib_find_gid_by_filter - Returns the GID table index where a specified
+ * GID value occurs
+ * @device: The device to query.
+ * @gid: The GID value to search for.
+ * @port_num: The port number of the device where the GID value could be
+ * searched.
+ * @filter: The filter function is executed on any matching GID in the table.
+ * If the filter function returns true, the corresponding index is returned,
+ * otherwise, we continue searching the GID table. It's guaranteed that
+ * while filter is executed, ndev field is valid and the structure won't
+ * change. filter is executed in an atomic context. filter must not be NULL.
+ * @index: The index into the cached GID table where the GID was found. This
+ * parameter may be NULL.
+ *
+ * ib_cache_gid_find_by_filter() searches for the specified GID value
+ * of which the filter function returns true in the port's GID table.
+ * This function is only supported on RoCE ports.
+ *
+ */
+static int ib_cache_gid_find_by_filter(struct ib_device *ib_dev,
+ const union ib_gid *gid,
+ u8 port,
+ bool (*filter)(const union ib_gid *,
+ const struct ib_gid_attr *,
+ void *),
+ void *context,
+ u16 *index)
+{
+ struct ib_gid_table **ports_table = ib_dev->cache.gid_cache;
+ struct ib_gid_table *table;
+ unsigned int i;
+ bool found = false;
+
+ if (!ports_table)
+ return -EOPNOTSUPP;
+
+ if (port < rdma_start_port(ib_dev) ||
+ port > rdma_end_port(ib_dev) ||
+ !rdma_protocol_roce(ib_dev, port))
+ return -EPROTONOSUPPORT;
+
+ table = ports_table[port - rdma_start_port(ib_dev)];
+
+ for (i = 0; i < table->sz; i++) {
+ struct ib_gid_attr attr;
+ unsigned long flags;
+
+ read_lock_irqsave(&table->data_vec[i].lock, flags);
+ if (table->data_vec[i].props & GID_TABLE_ENTRY_INVALID)
+ goto next;
+
+ if (memcmp(gid, &table->data_vec[i].gid, sizeof(*gid)))
+ goto next;
+
+ memcpy(&attr, &table->data_vec[i].attr, sizeof(attr));
+
+ if (filter(gid, &attr, context))
+ found = true;
+
+next:
+ read_unlock_irqrestore(&table->data_vec[i].lock, flags);
+
+ if (found)
+ break;
+ }
+
+ if (!found)
+ return -ENOENT;
+
+ if (index)
+ *index = i;
+ return 0;
+}
static struct ib_gid_table *alloc_gid_table(int sz)
{
@@ -508,12 +584,12 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
memset(&gid_attr, 0, sizeof(gid_attr));
gid_attr.ndev = ndev;
+ mutex_lock(&table->lock);
ix = find_gid(table, NULL, NULL, true, GID_ATTR_FIND_MASK_DEFAULT);
/* Coudn't find default GID location */
WARN_ON(ix < 0);
- mutex_lock(&table->lock);
if (!__ib_cache_gid_get(ib_dev, port, ix,
&current_gid, &current_gid_attr) &&
mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
@@ -649,24 +725,44 @@ static int gid_table_setup_one(struct ib_device *ib_dev)
int ib_get_cached_gid(struct ib_device *device,
u8 port_num,
int index,
- union ib_gid *gid)
+ union ib_gid *gid,
+ struct ib_gid_attr *gid_attr)
{
if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device))
return -EINVAL;
- return __ib_cache_gid_get(device, port_num, index, gid, NULL);
+ return __ib_cache_gid_get(device, port_num, index, gid, gid_attr);
}
EXPORT_SYMBOL(ib_get_cached_gid);
int ib_find_cached_gid(struct ib_device *device,
const union ib_gid *gid,
+ struct net_device *ndev,
u8 *port_num,
u16 *index)
{
- return ib_cache_gid_find(device, gid, NULL, port_num, index);
+ return ib_cache_gid_find(device, gid, ndev, port_num, index);
}
EXPORT_SYMBOL(ib_find_cached_gid);
+int ib_find_gid_by_filter(struct ib_device *device,
+ const union ib_gid *gid,
+ u8 port_num,
+ bool (*filter)(const union ib_gid *gid,
+ const struct ib_gid_attr *,
+ void *),
+ void *context, u16 *index)
+{
+ /* Only RoCE GID table supports filter function */
+ if (!rdma_cap_roce_gid_table(device, port_num) && filter)
+ return -EPROTONOSUPPORT;
+
+ return ib_cache_gid_find_by_filter(device, gid,
+ port_num, filter,
+ context, index);
+}
+EXPORT_SYMBOL(ib_find_gid_by_filter);
+
int ib_get_cached_pkey(struct ib_device *device,
u8 port_num,
int index,
@@ -845,7 +941,7 @@ static void ib_cache_update(struct ib_device *device,
if (!use_roce_gid_table) {
for (i = 0; i < gid_cache->table_len; ++i) {
ret = ib_query_gid(device, port, i,
- gid_cache->table + i);
+ gid_cache->table + i, NULL);
if (ret) {
printk(KERN_WARNING "ib_query_gid failed (%d) for %s (index %d)\n",
ret, device->name, i);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index ea4db9c1d44f..0a26dd6d9b19 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -179,8 +179,6 @@ struct cm_av {
struct ib_ah_attr ah_attr;
u16 pkey_index;
u8 timeout;
- u8 valid;
- u8 smac[ETH_ALEN];
};
struct cm_work {
@@ -361,17 +359,21 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
unsigned long flags;
int ret;
u8 p;
+ struct net_device *ndev = ib_get_ndev_from_path(path);
read_lock_irqsave(&cm.device_lock, flags);
list_for_each_entry(cm_dev, &cm.device_list, list) {
if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
- &p, NULL)) {
+ ndev, &p, NULL)) {
port = cm_dev->port[p-1];
break;
}
}
read_unlock_irqrestore(&cm.device_lock, flags);
+ if (ndev)
+ dev_put(ndev);
+
if (!port)
return -EINVAL;
@@ -384,9 +386,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path,
&av->ah_attr);
av->timeout = path->packet_life_time + 1;
- memcpy(av->smac, path->smac, sizeof(av->smac));
- av->valid = 1;
return 0;
}
@@ -835,6 +835,11 @@ retest:
case IB_CM_SIDR_REQ_RCVD:
spin_unlock_irq(&cm_id_priv->lock);
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
+ spin_lock_irq(&cm.lock);
+ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
+ rb_erase(&cm_id_priv->sidr_id_node,
+ &cm.remote_sidr_table);
+ spin_unlock_irq(&cm.lock);
break;
case IB_CM_REQ_SENT:
case IB_CM_MRA_REQ_RCVD:
@@ -1634,11 +1639,11 @@ static int cm_req_handler(struct cm_work *work)
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
memcpy(work->path[0].dmac, cm_id_priv->av.ah_attr.dmac, ETH_ALEN);
- work->path[0].vlan_id = cm_id_priv->av.ah_attr.vlan_id;
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
if (ret) {
ib_get_cached_gid(work->port->cm_dev->ib_device,
- work->port->port_num, 0, &work->path[0].sgid);
+ work->port->port_num, 0, &work->path[0].sgid,
+ NULL);
ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,
&work->path[0].sgid, sizeof work->path[0].sgid,
NULL, 0);
@@ -3172,7 +3177,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
spin_lock_irqsave(&cm.lock, flags);
- rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
+ rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+ RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
+ }
spin_unlock_irqrestore(&cm.lock, flags);
return 0;
@@ -3610,32 +3618,6 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
*qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |
IB_QP_DEST_QPN | IB_QP_RQ_PSN;
qp_attr->ah_attr = cm_id_priv->av.ah_attr;
- if (!cm_id_priv->av.valid) {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- return -EINVAL;
- }
- if (cm_id_priv->av.ah_attr.vlan_id != 0xffff) {
- qp_attr->vlan_id = cm_id_priv->av.ah_attr.vlan_id;
- *qp_attr_mask |= IB_QP_VID;
- }
- if (!is_zero_ether_addr(cm_id_priv->av.smac)) {
- memcpy(qp_attr->smac, cm_id_priv->av.smac,
- sizeof(qp_attr->smac));
- *qp_attr_mask |= IB_QP_SMAC;
- }
- if (cm_id_priv->alt_av.valid) {
- if (cm_id_priv->alt_av.ah_attr.vlan_id != 0xffff) {
- qp_attr->alt_vlan_id =
- cm_id_priv->alt_av.ah_attr.vlan_id;
- *qp_attr_mask |= IB_QP_ALT_VID;
- }
- if (!is_zero_ether_addr(cm_id_priv->alt_av.smac)) {
- memcpy(qp_attr->alt_smac,
- cm_id_priv->alt_av.smac,
- sizeof(qp_attr->alt_smac));
- *qp_attr_mask |= IB_QP_ALT_SMAC;
- }
- }
qp_attr->path_mtu = cm_id_priv->path_mtu;
qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b1ab13f3e182..944cd90417bc 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -44,6 +44,8 @@
#include <linux/module.h>
#include <net/route.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
#include <net/tcp.h>
#include <net/ipv6.h>
#include <net/ip_fib.h>
@@ -86,7 +88,7 @@ static const char * const cma_events[] = {
[RDMA_CM_EVENT_TIMEWAIT_EXIT] = "timewait exit",
};
-const char *rdma_event_msg(enum rdma_cm_event_type event)
+const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event)
{
size_t index = event;
@@ -110,22 +112,33 @@ static LIST_HEAD(dev_list);
static LIST_HEAD(listen_any_list);
static DEFINE_MUTEX(lock);
static struct workqueue_struct *cma_wq;
-static DEFINE_IDR(tcp_ps);
-static DEFINE_IDR(udp_ps);
-static DEFINE_IDR(ipoib_ps);
-static DEFINE_IDR(ib_ps);
+static int cma_pernet_id;
-static struct idr *cma_idr(enum rdma_port_space ps)
+struct cma_pernet {
+ struct idr tcp_ps;
+ struct idr udp_ps;
+ struct idr ipoib_ps;
+ struct idr ib_ps;
+};
+
+static struct cma_pernet *cma_pernet(struct net *net)
{
+ return net_generic(net, cma_pernet_id);
+}
+
+static struct idr *cma_pernet_idr(struct net *net, enum rdma_port_space ps)
+{
+ struct cma_pernet *pernet = cma_pernet(net);
+
switch (ps) {
case RDMA_PS_TCP:
- return &tcp_ps;
+ return &pernet->tcp_ps;
case RDMA_PS_UDP:
- return &udp_ps;
+ return &pernet->udp_ps;
case RDMA_PS_IPOIB:
- return &ipoib_ps;
+ return &pernet->ipoib_ps;
case RDMA_PS_IB:
- return &ib_ps;
+ return &pernet->ib_ps;
default:
return NULL;
}
@@ -145,24 +158,25 @@ struct rdma_bind_list {
unsigned short port;
};
-static int cma_ps_alloc(enum rdma_port_space ps,
+static int cma_ps_alloc(struct net *net, enum rdma_port_space ps,
struct rdma_bind_list *bind_list, int snum)
{
- struct idr *idr = cma_idr(ps);
+ struct idr *idr = cma_pernet_idr(net, ps);
return idr_alloc(idr, bind_list, snum, snum + 1, GFP_KERNEL);
}
-static struct rdma_bind_list *cma_ps_find(enum rdma_port_space ps, int snum)
+static struct rdma_bind_list *cma_ps_find(struct net *net,
+ enum rdma_port_space ps, int snum)
{
- struct idr *idr = cma_idr(ps);
+ struct idr *idr = cma_pernet_idr(net, ps);
return idr_find(idr, snum);
}
-static void cma_ps_remove(enum rdma_port_space ps, int snum)
+static void cma_ps_remove(struct net *net, enum rdma_port_space ps, int snum)
{
- struct idr *idr = cma_idr(ps);
+ struct idr *idr = cma_pernet_idr(net, ps);
idr_remove(idr, snum);
}
@@ -427,10 +441,11 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a
}
static inline int cma_validate_port(struct ib_device *device, u8 port,
- union ib_gid *gid, int dev_type)
+ union ib_gid *gid, int dev_type,
+ int bound_if_index)
{
- u8 found_port;
int ret = -ENODEV;
+ struct net_device *ndev = NULL;
if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port))
return ret;
@@ -438,9 +453,13 @@ static inline int cma_validate_port(struct ib_device *device, u8 port,
if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port))
return ret;
- ret = ib_find_cached_gid(device, gid, &found_port, NULL);
- if (port != found_port)
- return -ENODEV;
+ if (dev_type == ARPHRD_ETHER)
+ ndev = dev_get_by_index(&init_net, bound_if_index);
+
+ ret = ib_find_cached_gid_by_port(device, gid, port, ndev, NULL);
+
+ if (ndev)
+ dev_put(ndev);
return ret;
}
@@ -472,7 +491,8 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
&iboe_gid : &gid;
ret = cma_validate_port(cma_dev->device, port, gidp,
- dev_addr->dev_type);
+ dev_addr->dev_type,
+ dev_addr->bound_dev_if);
if (!ret) {
id_priv->id.port_num = port;
goto out;
@@ -490,7 +510,8 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
&iboe_gid : &gid;
ret = cma_validate_port(cma_dev->device, port, gidp,
- dev_addr->dev_type);
+ dev_addr->dev_type,
+ dev_addr->bound_dev_if);
if (!ret) {
id_priv->id.port_num = port;
goto out;
@@ -531,7 +552,9 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index))
continue;
- for (i = 0; !ib_get_cached_gid(cur_dev->device, p, i, &gid); i++) {
+ for (i = 0; !ib_get_cached_gid(cur_dev->device, p, i,
+ &gid, NULL);
+ i++) {
if (!memcmp(&gid, dgid, sizeof(gid))) {
cma_dev = cur_dev;
sgid = gid;
@@ -577,7 +600,8 @@ static int cma_disable_callback(struct rdma_id_private *id_priv,
return 0;
}
-struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+struct rdma_cm_id *rdma_create_id(struct net *net,
+ rdma_cm_event_handler event_handler,
void *context, enum rdma_port_space ps,
enum ib_qp_type qp_type)
{
@@ -601,6 +625,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
INIT_LIST_HEAD(&id_priv->listen_list);
INIT_LIST_HEAD(&id_priv->mc_list);
get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
+ id_priv->id.route.addr.dev_addr.net = get_net(net);
return &id_priv->id;
}
@@ -718,18 +743,12 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
goto out;
ret = ib_query_gid(id_priv->id.device, id_priv->id.port_num,
- qp_attr.ah_attr.grh.sgid_index, &sgid);
+ qp_attr.ah_attr.grh.sgid_index, &sgid, NULL);
if (ret)
goto out;
BUG_ON(id_priv->cma_dev->device != id_priv->id.device);
- if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
- ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL);
-
- if (ret)
- goto out;
- }
if (conn_param)
qp_attr.max_dest_rd_atomic = conn_param->responder_resources;
ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
@@ -1067,14 +1086,14 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
sizeof(req->local_gid));
req->has_gid = true;
req->service_id = req_param->primary_path->service_id;
- req->pkey = req_param->bth_pkey;
+ req->pkey = be16_to_cpu(req_param->primary_path->pkey);
break;
case IB_CM_SIDR_REQ_RECEIVED:
req->device = sidr_param->listen_id->device;
req->port = sidr_param->port;
req->has_gid = false;
req->service_id = sidr_param->service_id;
- req->pkey = sidr_param->bth_pkey;
+ req->pkey = sidr_param->pkey;
break;
default:
return -EINVAL;
@@ -1232,17 +1251,35 @@ static bool cma_match_private_data(struct rdma_id_private *id_priv,
return true;
}
+static bool cma_protocol_roce_dev_port(struct ib_device *device, int port_num)
+{
+ enum rdma_link_layer ll = rdma_port_get_link_layer(device, port_num);
+ enum rdma_transport_type transport =
+ rdma_node_get_transport(device->node_type);
+
+ return ll == IB_LINK_LAYER_ETHERNET && transport == RDMA_TRANSPORT_IB;
+}
+
+static bool cma_protocol_roce(const struct rdma_cm_id *id)
+{
+ struct ib_device *device = id->device;
+ const int port_num = id->port_num ?: rdma_start_port(device);
+
+ return cma_protocol_roce_dev_port(device, port_num);
+}
+
static bool cma_match_net_dev(const struct rdma_id_private *id_priv,
const struct net_device *net_dev)
{
const struct rdma_addr *addr = &id_priv->id.route.addr;
if (!net_dev)
- /* This request is an AF_IB request */
- return addr->src_addr.ss_family == AF_IB;
+ /* This request is an AF_IB request or a RoCE request */
+ return addr->src_addr.ss_family == AF_IB ||
+ cma_protocol_roce(&id_priv->id);
return !addr->dev_addr.bound_dev_if ||
- (net_eq(dev_net(net_dev), &init_net) &&
+ (net_eq(dev_net(net_dev), addr->dev_addr.net) &&
addr->dev_addr.bound_dev_if == net_dev->ifindex);
}
@@ -1294,15 +1331,20 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) {
/* Assuming the protocol is AF_IB */
*net_dev = NULL;
+ } else if (cma_protocol_roce_dev_port(req.device, req.port)) {
+ /* TODO find the net dev matching the request parameters
+ * through the RoCE GID table */
+ *net_dev = NULL;
} else {
return ERR_CAST(*net_dev);
}
}
- bind_list = cma_ps_find(rdma_ps_from_service_id(req.service_id),
+ bind_list = cma_ps_find(*net_dev ? dev_net(*net_dev) : &init_net,
+ rdma_ps_from_service_id(req.service_id),
cma_port_from_service_id(req.service_id));
id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev);
- if (IS_ERR(id_priv)) {
+ if (IS_ERR(id_priv) && *net_dev) {
dev_put(*net_dev);
*net_dev = NULL;
}
@@ -1370,6 +1412,7 @@ static void cma_cancel_operation(struct rdma_id_private *id_priv,
static void cma_release_port(struct rdma_id_private *id_priv)
{
struct rdma_bind_list *bind_list = id_priv->bind_list;
+ struct net *net = id_priv->id.route.addr.dev_addr.net;
if (!bind_list)
return;
@@ -1377,7 +1420,7 @@ static void cma_release_port(struct rdma_id_private *id_priv)
mutex_lock(&lock);
hlist_del(&id_priv->node);
if (hlist_empty(&bind_list->owners)) {
- cma_ps_remove(bind_list->ps, bind_list->port);
+ cma_ps_remove(net, bind_list->ps, bind_list->port);
kfree(bind_list);
}
mutex_unlock(&lock);
@@ -1436,6 +1479,7 @@ void rdma_destroy_id(struct rdma_cm_id *id)
cma_deref_id(id_priv->id.context);
kfree(id_priv->id.route.path_rec);
+ put_net(id_priv->id.route.addr.dev_addr.net);
kfree(id_priv);
}
EXPORT_SYMBOL(rdma_destroy_id);
@@ -1566,7 +1610,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
ib_event->param.req_rcvd.primary_path->service_id;
int ret;
- id = rdma_create_id(listen_id->event_handler, listen_id->context,
+ id = rdma_create_id(listen_id->route.addr.dev_addr.net,
+ listen_id->event_handler, listen_id->context,
listen_id->ps, ib_event->param.req_rcvd.qp_type);
if (IS_ERR(id))
return NULL;
@@ -1593,11 +1638,16 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
if (ret)
goto err;
} else {
- /* An AF_IB connection */
- WARN_ON_ONCE(ss_family != AF_IB);
-
- cma_translate_ib((struct sockaddr_ib *)cma_src_addr(id_priv),
- &rt->addr.dev_addr);
+ if (!cma_protocol_roce(listen_id) &&
+ cma_any_addr(cma_src_addr(id_priv))) {
+ rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
+ rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+ ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
+ } else if (!cma_any_addr(cma_src_addr(id_priv))) {
+ ret = cma_translate_addr(cma_src_addr(id_priv), &rt->addr.dev_addr);
+ if (ret)
+ goto err;
+ }
}
rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
@@ -1616,9 +1666,10 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
struct rdma_id_private *id_priv;
struct rdma_cm_id *id;
const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family;
+ struct net *net = listen_id->route.addr.dev_addr.net;
int ret;
- id = rdma_create_id(listen_id->event_handler, listen_id->context,
+ id = rdma_create_id(net, listen_id->event_handler, listen_id->context,
listen_id->ps, IB_QPT_UD);
if (IS_ERR(id))
return NULL;
@@ -1635,13 +1686,12 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
if (ret)
goto err;
} else {
- /* An AF_IB connection */
- WARN_ON_ONCE(ss_family != AF_IB);
-
- if (!cma_any_addr(cma_src_addr(id_priv)))
- cma_translate_ib((struct sockaddr_ib *)
- cma_src_addr(id_priv),
- &id->route.addr.dev_addr);
+ if (!cma_any_addr(cma_src_addr(id_priv))) {
+ ret = cma_translate_addr(cma_src_addr(id_priv),
+ &id->route.addr.dev_addr);
+ if (ret)
+ goto err;
+ }
}
id_priv->state = RDMA_CM_CONNECT;
@@ -1856,7 +1906,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
return -ECONNABORTED;
/* Create a new RDMA id for the new IW CM ID */
- new_cm_id = rdma_create_id(listen_id->id.event_handler,
+ new_cm_id = rdma_create_id(listen_id->id.route.addr.dev_addr.net,
+ listen_id->id.event_handler,
listen_id->id.context,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(new_cm_id)) {
@@ -1984,12 +2035,13 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
{
struct rdma_id_private *dev_id_priv;
struct rdma_cm_id *id;
+ struct net *net = id_priv->id.route.addr.dev_addr.net;
int ret;
if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
return;
- id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps,
+ id = rdma_create_id(net, cma_listen_handler, id_priv, id_priv->id.ps,
id_priv->id.qp_type);
if (IS_ERR(id))
return;
@@ -2268,16 +2320,17 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
route->num_paths = 1;
- if (addr->dev_addr.bound_dev_if)
+ if (addr->dev_addr.bound_dev_if) {
ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if);
+ route->path_rec->net = &init_net;
+ route->path_rec->ifindex = addr->dev_addr.bound_dev_if;
+ }
if (!ndev) {
ret = -ENODEV;
goto err2;
}
- route->path_rec->vlan_id = rdma_vlan_dev_vlan_id(ndev);
memcpy(route->path_rec->dmac, addr->dev_addr.dst_dev_addr, ETH_ALEN);
- memcpy(route->path_rec->smac, ndev->dev_addr, ndev->addr_len);
rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr,
&route->path_rec->sgid);
@@ -2400,7 +2453,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv)
p = 1;
port_found:
- ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid);
+ ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid, NULL);
if (ret)
goto out;
@@ -2662,7 +2715,8 @@ static int cma_alloc_port(enum rdma_port_space ps,
if (!bind_list)
return -ENOMEM;
- ret = cma_ps_alloc(ps, bind_list, snum);
+ ret = cma_ps_alloc(id_priv->id.route.addr.dev_addr.net, ps, bind_list,
+ snum);
if (ret < 0)
goto err;
@@ -2681,13 +2735,14 @@ static int cma_alloc_any_port(enum rdma_port_space ps,
static unsigned int last_used_port;
int low, high, remaining;
unsigned int rover;
+ struct net *net = id_priv->id.route.addr.dev_addr.net;
- inet_get_local_port_range(&init_net, &low, &high);
+ inet_get_local_port_range(net, &low, &high);
remaining = (high - low) + 1;
rover = prandom_u32() % remaining + low;
retry:
if (last_used_port != rover &&
- !cma_ps_find(ps, (unsigned short)rover)) {
+ !cma_ps_find(net, ps, (unsigned short)rover)) {
int ret = cma_alloc_port(ps, id_priv, rover);
/*
* Remember previously used port number in order to avoid
@@ -2753,7 +2808,7 @@ static int cma_use_port(enum rdma_port_space ps,
if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
return -EACCES;
- bind_list = cma_ps_find(ps, snum);
+ bind_list = cma_ps_find(id_priv->id.route.addr.dev_addr.net, ps, snum);
if (!bind_list) {
ret = cma_alloc_port(ps, id_priv, snum);
} else {
@@ -2945,8 +3000,11 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
if (addr->sa_family == AF_INET)
id_priv->afonly = 1;
#if IS_ENABLED(CONFIG_IPV6)
- else if (addr->sa_family == AF_INET6)
- id_priv->afonly = init_net.ipv6.sysctl.bindv6only;
+ else if (addr->sa_family == AF_INET6) {
+ struct net *net = id_priv->id.route.addr.dev_addr.net;
+
+ id_priv->afonly = net->ipv6.sysctl.bindv6only;
+ }
#endif
}
ret = cma_get_port(id_priv);
@@ -3751,6 +3809,7 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id
dev_addr = &id_priv->id.route.addr.dev_addr;
if ((dev_addr->bound_dev_if == ndev->ifindex) &&
+ (net_eq(dev_net(ndev), dev_addr->net)) &&
memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
ndev->name, &id_priv->id);
@@ -3776,9 +3835,6 @@ static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
struct rdma_id_private *id_priv;
int ret = NOTIFY_DONE;
- if (dev_net(ndev) != &init_net)
- return NOTIFY_DONE;
-
if (event != NETDEV_BONDING_FAILOVER)
return NOTIFY_DONE;
@@ -3973,6 +4029,35 @@ static const struct ibnl_client_cbs cma_cb_table[] = {
.module = THIS_MODULE },
};
+static int cma_init_net(struct net *net)
+{
+ struct cma_pernet *pernet = cma_pernet(net);
+
+ idr_init(&pernet->tcp_ps);
+ idr_init(&pernet->udp_ps);
+ idr_init(&pernet->ipoib_ps);
+ idr_init(&pernet->ib_ps);
+
+ return 0;
+}
+
+static void cma_exit_net(struct net *net)
+{
+ struct cma_pernet *pernet = cma_pernet(net);
+
+ idr_destroy(&pernet->tcp_ps);
+ idr_destroy(&pernet->udp_ps);
+ idr_destroy(&pernet->ipoib_ps);
+ idr_destroy(&pernet->ib_ps);
+}
+
+static struct pernet_operations cma_pernet_operations = {
+ .init = cma_init_net,
+ .exit = cma_exit_net,
+ .id = &cma_pernet_id,
+ .size = sizeof(struct cma_pernet),
+};
+
static int __init cma_init(void)
{
int ret;
@@ -3981,6 +4066,10 @@ static int __init cma_init(void)
if (!cma_wq)
return -ENOMEM;
+ ret = register_pernet_subsys(&cma_pernet_operations);
+ if (ret)
+ goto err_wq;
+
ib_sa_register_client(&sa_client);
rdma_addr_register_client(&addr_client);
register_netdevice_notifier(&cma_nb);
@@ -3998,6 +4087,7 @@ err:
unregister_netdevice_notifier(&cma_nb);
rdma_addr_unregister_client(&addr_client);
ib_sa_unregister_client(&sa_client);
+err_wq:
destroy_workqueue(cma_wq);
return ret;
}
@@ -4009,11 +4099,8 @@ static void __exit cma_cleanup(void)
unregister_netdevice_notifier(&cma_nb);
rdma_addr_unregister_client(&addr_client);
ib_sa_unregister_client(&sa_client);
+ unregister_pernet_subsys(&cma_pernet_operations);
destroy_workqueue(cma_wq);
- idr_destroy(&tcp_ps);
- idr_destroy(&udp_ps);
- idr_destroy(&ipoib_ps);
- idr_destroy(&ib_ps);
}
module_init(cma_init);
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 70bb36ebb03b..5cf6eb716f00 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -46,8 +46,8 @@ void ib_device_unregister_sysfs(struct ib_device *device);
void ib_cache_setup(void);
void ib_cache_cleanup(void);
-int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
- struct ib_qp_attr *qp_attr, int *qp_attr_mask);
+int ib_resolve_eth_dmac(struct ib_qp *qp,
+ struct ib_qp_attr *qp_attr, int *qp_attr_mask);
typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port,
struct net_device *idev, void *cookie);
@@ -65,11 +65,6 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter filter,
roce_netdev_callback cb,
void *cookie);
-int ib_cache_gid_find_by_port(struct ib_device *ib_dev,
- const union ib_gid *gid,
- u8 port, struct net_device *ndev,
- u16 *index);
-
enum ib_cache_gid_default_mode {
IB_CACHE_GID_DEFAULT_MODE_SET,
IB_CACHE_GID_DEFAULT_MODE_DELETE
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 17639117afc6..179e8134d57f 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -672,14 +672,20 @@ EXPORT_SYMBOL(ib_query_port);
* @port_num:Port number to query
* @index:GID table index to query
* @gid:Returned GID
+ * @attr: Returned GID attributes related to this GID index (only in RoCE).
+ * NULL means ignore.
*
* ib_query_gid() fetches the specified GID table entry.
*/
int ib_query_gid(struct ib_device *device,
- u8 port_num, int index, union ib_gid *gid)
+ u8 port_num, int index, union ib_gid *gid,
+ struct ib_gid_attr *attr)
{
if (rdma_cap_roce_gid_table(device, port_num))
- return ib_get_cached_gid(device, port_num, index, gid);
+ return ib_get_cached_gid(device, port_num, index, gid, attr);
+
+ if (attr)
+ return -EINVAL;
return device->query_gid(device, port_num, index, gid);
}
@@ -819,27 +825,28 @@ EXPORT_SYMBOL(ib_modify_port);
* a specified GID value occurs.
* @device: The device to query.
* @gid: The GID value to search for.
+ * @ndev: The ndev related to the GID to search for.
* @port_num: The port number of the device where the GID value was found.
* @index: The index into the GID table where the GID was found. This
* parameter may be NULL.
*/
int ib_find_gid(struct ib_device *device, union ib_gid *gid,
- u8 *port_num, u16 *index)
+ struct net_device *ndev, u8 *port_num, u16 *index)
{
union ib_gid tmp_gid;
int ret, port, i;
for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) {
if (rdma_cap_roce_gid_table(device, port)) {
- if (!ib_cache_gid_find_by_port(device, gid, port,
- NULL, index)) {
+ if (!ib_find_cached_gid_by_port(device, gid, port,
+ ndev, index)) {
*port_num = port;
return 0;
}
}
for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
- ret = ib_query_gid(device, port, i, &tmp_gid);
+ ret = ib_query_gid(device, port, i, &tmp_gid, NULL);
if (ret)
return ret;
if (!memcmp(&tmp_gid, gid, sizeof *gid)) {
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 4b5c72311deb..8d8af7a41a30 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -752,7 +752,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_device *device = mad_agent_priv->agent.device;
u8 port_num;
struct ib_wc mad_wc;
- struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
+ struct ib_ud_wr *send_wr = &mad_send_wr->send_wr;
size_t mad_size = port_mad_size(mad_agent_priv->qp_info->port_priv);
u16 out_mad_pkey_index = 0;
u16 drslid;
@@ -761,7 +761,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
if (rdma_cap_ib_switch(device) &&
smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
- port_num = send_wr->wr.ud.port_num;
+ port_num = send_wr->port_num;
else
port_num = mad_agent_priv->agent.port_num;
@@ -832,9 +832,9 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
}
build_smp_wc(mad_agent_priv->agent.qp,
- send_wr->wr_id, drslid,
- send_wr->wr.ud.pkey_index,
- send_wr->wr.ud.port_num, &mad_wc);
+ send_wr->wr.wr_id, drslid,
+ send_wr->pkey_index,
+ send_wr->port_num, &mad_wc);
if (opa && smp->base_version == OPA_MGMT_BASE_VERSION) {
mad_wc.byte_len = mad_send_wr->send_buf.hdr_len
@@ -894,7 +894,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
local->mad_send_wr = mad_send_wr;
if (opa) {
- local->mad_send_wr->send_wr.wr.ud.pkey_index = out_mad_pkey_index;
+ local->mad_send_wr->send_wr.pkey_index = out_mad_pkey_index;
local->return_wc_byte_len = mad_size;
}
/* Reference MAD agent until send side of local completion handled */
@@ -1039,14 +1039,14 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
mad_send_wr->sg_list[1].lkey = mad_agent->qp->pd->local_dma_lkey;
- mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
- mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
- mad_send_wr->send_wr.num_sge = 2;
- mad_send_wr->send_wr.opcode = IB_WR_SEND;
- mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;
- mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;
- mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
- mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
+ mad_send_wr->send_wr.wr.wr_id = (unsigned long) mad_send_wr;
+ mad_send_wr->send_wr.wr.sg_list = mad_send_wr->sg_list;
+ mad_send_wr->send_wr.wr.num_sge = 2;
+ mad_send_wr->send_wr.wr.opcode = IB_WR_SEND;
+ mad_send_wr->send_wr.wr.send_flags = IB_SEND_SIGNALED;
+ mad_send_wr->send_wr.remote_qpn = remote_qpn;
+ mad_send_wr->send_wr.remote_qkey = IB_QP_SET_QKEY;
+ mad_send_wr->send_wr.pkey_index = pkey_index;
if (rmpp_active) {
ret = alloc_send_rmpp_list(mad_send_wr, mad_size, gfp_mask);
@@ -1151,7 +1151,7 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
/* Set WR ID to find mad_send_wr upon completion */
qp_info = mad_send_wr->mad_agent_priv->qp_info;
- mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
+ mad_send_wr->send_wr.wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;
mad_agent = mad_send_wr->send_buf.mad_agent;
@@ -1179,7 +1179,7 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
spin_lock_irqsave(&qp_info->send_queue.lock, flags);
if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
- ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
+ ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr.wr,
&bad_send_wr);
list = &qp_info->send_queue.list;
} else {
@@ -1244,7 +1244,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
* request associated with the completion
*/
next_send_buf = send_buf->next;
- mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;
+ mad_send_wr->send_wr.ah = send_buf->ah;
if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==
IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
@@ -1877,7 +1877,7 @@ static inline int rcv_has_same_gid(const struct ib_mad_agent_private *mad_agent_
((1 << lmc) - 1)));
} else {
if (ib_get_cached_gid(device, port_num,
- attr.grh.sgid_index, &sgid))
+ attr.grh.sgid_index, &sgid, NULL))
return 0;
return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
16);
@@ -2457,7 +2457,7 @@ retry:
ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
if (queued_send_wr) {
- ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
+ ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr.wr,
&bad_send_wr);
if (ret) {
dev_err(&port_priv->device->dev,
@@ -2515,7 +2515,7 @@ static void mad_error_handler(struct ib_mad_port_private *port_priv,
struct ib_send_wr *bad_send_wr;
mad_send_wr->retry = 0;
- ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr,
+ ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr.wr,
&bad_send_wr);
if (ret)
ib_mad_send_done_handler(port_priv, wc);
@@ -2713,7 +2713,7 @@ static void local_completions(struct work_struct *work)
build_smp_wc(recv_mad_agent->agent.qp,
(unsigned long) local->mad_send_wr,
be16_to_cpu(IB_LID_PERMISSIVE),
- local->mad_send_wr->send_wr.wr.ud.pkey_index,
+ local->mad_send_wr->send_wr.pkey_index,
recv_mad_agent->agent.port_num, &wc);
local->mad_priv->header.recv_wc.wc = &wc;
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 4a4f7aad0978..990698a6ab4b 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -123,7 +123,7 @@ struct ib_mad_send_wr_private {
struct ib_mad_send_buf send_buf;
u64 header_mapping;
u64 payload_mapping;
- struct ib_send_wr send_wr;
+ struct ib_ud_wr send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
__be64 tid;
unsigned long timeout;
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index d38d8b2b2979..bb6685fb08c6 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -729,7 +729,8 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
u16 gid_index;
u8 p;
- ret = ib_find_cached_gid(device, &rec->port_gid, &p, &gid_index);
+ ret = ib_find_cached_gid(device, &rec->port_gid,
+ NULL, &p, &gid_index);
if (ret)
return ret;
diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c
index 6b24cba1e474..178f98482e13 100644
--- a/drivers/infiniband/core/roce_gid_mgmt.c
+++ b/drivers/infiniband/core/roce_gid_mgmt.c
@@ -250,25 +250,44 @@ static void enum_netdev_ipv4_ips(struct ib_device *ib_dev,
u8 port, struct net_device *ndev)
{
struct in_device *in_dev;
+ struct sin_list {
+ struct list_head list;
+ struct sockaddr_in ip;
+ };
+ struct sin_list *sin_iter;
+ struct sin_list *sin_temp;
+ LIST_HEAD(sin_list);
if (ndev->reg_state >= NETREG_UNREGISTERING)
return;
- in_dev = in_dev_get(ndev);
- if (!in_dev)
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(ndev);
+ if (!in_dev) {
+ rcu_read_unlock();
return;
+ }
for_ifa(in_dev) {
- struct sockaddr_in ip;
+ struct sin_list *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
- ip.sin_family = AF_INET;
- ip.sin_addr.s_addr = ifa->ifa_address;
- update_gid_ip(GID_ADD, ib_dev, port, ndev,
- (struct sockaddr *)&ip);
+ if (!entry) {
+ pr_warn("roce_gid_mgmt: couldn't allocate entry for IPv4 update\n");
+ continue;
+ }
+ entry->ip.sin_family = AF_INET;
+ entry->ip.sin_addr.s_addr = ifa->ifa_address;
+ list_add_tail(&entry->list, &sin_list);
}
endfor_ifa(in_dev);
+ rcu_read_unlock();
- in_dev_put(in_dev);
+ list_for_each_entry_safe(sin_iter, sin_temp, &sin_list, list) {
+ update_gid_ip(GID_ADD, ib_dev, port, ndev,
+ (struct sockaddr *)&sin_iter->ip);
+ list_del(&sin_iter->list);
+ kfree(sin_iter);
+ }
}
static void enum_netdev_ipv6_ips(struct ib_device *ib_dev,
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 8c014b33d8e0..2aba774f835b 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1007,26 +1007,29 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
force_grh = rdma_cap_eth_ah(device, port_num);
if (rec->hop_limit > 1 || force_grh) {
+ struct net_device *ndev = ib_get_ndev_from_path(rec);
+
ah_attr->ah_flags = IB_AH_GRH;
ah_attr->grh.dgid = rec->dgid;
- ret = ib_find_cached_gid(device, &rec->sgid, &port_num,
+ ret = ib_find_cached_gid(device, &rec->sgid, ndev, &port_num,
&gid_index);
- if (ret)
+ if (ret) {
+ if (ndev)
+ dev_put(ndev);
return ret;
+ }
ah_attr->grh.sgid_index = gid_index;
ah_attr->grh.flow_label = be32_to_cpu(rec->flow_label);
ah_attr->grh.hop_limit = rec->hop_limit;
ah_attr->grh.traffic_class = rec->traffic_class;
+ if (ndev)
+ dev_put(ndev);
}
if (force_grh) {
memcpy(ah_attr->dmac, rec->dmac, ETH_ALEN);
- ah_attr->vlan_id = rec->vlan_id;
- } else {
- ah_attr->vlan_id = 0xffff;
}
-
return 0;
}
EXPORT_SYMBOL(ib_init_ah_from_path);
@@ -1083,7 +1086,7 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
{
- bool preload = !!(gfp_mask & __GFP_WAIT);
+ bool preload = gfpflags_allow_blocking(gfp_mask);
unsigned long flags;
int ret, id;
@@ -1150,9 +1153,9 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),
mad->data, &rec);
- rec.vlan_id = 0xffff;
+ rec.net = NULL;
+ rec.ifindex = 0;
memset(rec.dmac, 0, ETH_ALEN);
- memset(rec.smac, 0, ETH_ALEN);
query->callback(status, &rec, query->context);
} else
query->callback(status, NULL, query->context);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 34cdd74b0a17..b1f37d4095fa 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -289,7 +289,7 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
union ib_gid gid;
ssize_t ret;
- ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid);
+ ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid, NULL);
if (ret)
return ret;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index a53fc9b01c69..8b5a934e1133 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -42,6 +42,7 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/module.h>
+#include <linux/nsproxy.h>
#include <rdma/rdma_user_cm.h>
#include <rdma/ib_marshall.h>
@@ -472,7 +473,8 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
return -ENOMEM;
ctx->uid = cmd.uid;
- ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps, qp_type);
+ ctx->cm_id = rdma_create_id(current->nsproxy->net_ns,
+ ucma_event_handler, ctx, cmd.ps, qp_type);
if (IS_ERR(ctx->cm_id)) {
ret = PTR_ERR(ctx->cm_id);
goto err1;
@@ -1211,7 +1213,6 @@ static int ucma_set_ib_path(struct ucma_context *ctx,
return -EINVAL;
memset(&sa_path, 0, sizeof(sa_path));
- sa_path.vlan_id = 0xffff;
ib_sa_unpack_path(path_data->path_rec, &sa_path);
ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
@@ -1624,11 +1625,16 @@ static int ucma_open(struct inode *inode, struct file *filp)
if (!file)
return -ENOMEM;
+ file->close_wq = create_singlethread_workqueue("ucma_close_id");
+ if (!file->close_wq) {
+ kfree(file);
+ return -ENOMEM;
+ }
+
INIT_LIST_HEAD(&file->event_list);
INIT_LIST_HEAD(&file->ctx_list);
init_waitqueue_head(&file->poll_wait);
mutex_init(&file->mut);
- file->close_wq = create_singlethread_workqueue("ucma_close_id");
filp->private_data = file;
file->filp = filp;
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 3863d33c243d..94bbd8c155fc 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -272,5 +272,6 @@ IB_UVERBS_DECLARE_EX_CMD(create_flow);
IB_UVERBS_DECLARE_EX_CMD(destroy_flow);
IB_UVERBS_DECLARE_EX_CMD(query_device);
IB_UVERBS_DECLARE_EX_CMD(create_cq);
+IB_UVERBS_DECLARE_EX_CMD(create_qp);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index be4cb9f04be3..94816aeb95a0 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1478,7 +1478,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof(cmd)))
return -EFAULT;
- INIT_UDATA(&ucore, buf, cmd.response, sizeof(cmd), sizeof(resp));
+ INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd), sizeof(resp));
INIT_UDATA(&uhw, buf + sizeof(cmd),
(unsigned long)cmd.response + sizeof(resp),
@@ -1741,66 +1741,65 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
return in_len;
}
-ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
- struct ib_device *ib_dev,
- const char __user *buf, int in_len,
- int out_len)
-{
- struct ib_uverbs_create_qp cmd;
- struct ib_uverbs_create_qp_resp resp;
- struct ib_udata udata;
- struct ib_uqp_object *obj;
- struct ib_device *device;
- struct ib_pd *pd = NULL;
- struct ib_xrcd *xrcd = NULL;
- struct ib_uobject *uninitialized_var(xrcd_uobj);
- struct ib_cq *scq = NULL, *rcq = NULL;
- struct ib_srq *srq = NULL;
- struct ib_qp *qp;
- struct ib_qp_init_attr attr;
- int ret;
-
- if (out_len < sizeof resp)
- return -ENOSPC;
-
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
+static int create_qp(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw,
+ struct ib_uverbs_ex_create_qp *cmd,
+ size_t cmd_sz,
+ int (*cb)(struct ib_uverbs_file *file,
+ struct ib_uverbs_ex_create_qp_resp *resp,
+ struct ib_udata *udata),
+ void *context)
+{
+ struct ib_uqp_object *obj;
+ struct ib_device *device;
+ struct ib_pd *pd = NULL;
+ struct ib_xrcd *xrcd = NULL;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
+ struct ib_cq *scq = NULL, *rcq = NULL;
+ struct ib_srq *srq = NULL;
+ struct ib_qp *qp;
+ char *buf;
+ struct ib_qp_init_attr attr;
+ struct ib_uverbs_ex_create_qp_resp resp;
+ int ret;
- if (cmd.qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
+ if (cmd->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
return -EPERM;
- INIT_UDATA(&udata, buf + sizeof cmd,
- (unsigned long) cmd.response + sizeof resp,
- in_len - sizeof cmd, out_len - sizeof resp);
-
obj = kzalloc(sizeof *obj, GFP_KERNEL);
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class);
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext,
+ &qp_lock_class);
down_write(&obj->uevent.uobject.mutex);
- if (cmd.qp_type == IB_QPT_XRC_TGT) {
- xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+ if (cmd->qp_type == IB_QPT_XRC_TGT) {
+ xrcd = idr_read_xrcd(cmd->pd_handle, file->ucontext,
+ &xrcd_uobj);
if (!xrcd) {
ret = -EINVAL;
goto err_put;
}
device = xrcd->device;
} else {
- if (cmd.qp_type == IB_QPT_XRC_INI) {
- cmd.max_recv_wr = cmd.max_recv_sge = 0;
+ if (cmd->qp_type == IB_QPT_XRC_INI) {
+ cmd->max_recv_wr = 0;
+ cmd->max_recv_sge = 0;
} else {
- if (cmd.is_srq) {
- srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+ if (cmd->is_srq) {
+ srq = idr_read_srq(cmd->srq_handle,
+ file->ucontext);
if (!srq || srq->srq_type != IB_SRQT_BASIC) {
ret = -EINVAL;
goto err_put;
}
}
- if (cmd.recv_cq_handle != cmd.send_cq_handle) {
- rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0);
+ if (cmd->recv_cq_handle != cmd->send_cq_handle) {
+ rcq = idr_read_cq(cmd->recv_cq_handle,
+ file->ucontext, 0);
if (!rcq) {
ret = -EINVAL;
goto err_put;
@@ -1808,9 +1807,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
}
}
- scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq);
+ scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq);
rcq = rcq ?: scq;
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
if (!pd || !scq) {
ret = -EINVAL;
goto err_put;
@@ -1825,31 +1824,49 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.recv_cq = rcq;
attr.srq = srq;
attr.xrcd = xrcd;
- attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
- attr.qp_type = cmd.qp_type;
+ attr.sq_sig_type = cmd->sq_sig_all ? IB_SIGNAL_ALL_WR :
+ IB_SIGNAL_REQ_WR;
+ attr.qp_type = cmd->qp_type;
attr.create_flags = 0;
- attr.cap.max_send_wr = cmd.max_send_wr;
- attr.cap.max_recv_wr = cmd.max_recv_wr;
- attr.cap.max_send_sge = cmd.max_send_sge;
- attr.cap.max_recv_sge = cmd.max_recv_sge;
- attr.cap.max_inline_data = cmd.max_inline_data;
+ attr.cap.max_send_wr = cmd->max_send_wr;
+ attr.cap.max_recv_wr = cmd->max_recv_wr;
+ attr.cap.max_send_sge = cmd->max_send_sge;
+ attr.cap.max_recv_sge = cmd->max_recv_sge;
+ attr.cap.max_inline_data = cmd->max_inline_data;
obj->uevent.events_reported = 0;
INIT_LIST_HEAD(&obj->uevent.event_list);
INIT_LIST_HEAD(&obj->mcast_list);
- if (cmd.qp_type == IB_QPT_XRC_TGT)
+ if (cmd_sz >= offsetof(typeof(*cmd), create_flags) +
+ sizeof(cmd->create_flags))
+ attr.create_flags = cmd->create_flags;
+
+ if (attr.create_flags & ~IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ buf = (void *)cmd + sizeof(*cmd);
+ if (cmd_sz > sizeof(*cmd))
+ if (!(buf[0] == 0 && !memcmp(buf, buf + 1,
+ cmd_sz - sizeof(*cmd) - 1))) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ if (cmd->qp_type == IB_QPT_XRC_TGT)
qp = ib_create_qp(pd, &attr);
else
- qp = device->create_qp(pd, &attr, &udata);
+ qp = device->create_qp(pd, &attr, uhw);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
}
- if (cmd.qp_type != IB_QPT_XRC_TGT) {
+ if (cmd->qp_type != IB_QPT_XRC_TGT) {
qp->real_qp = qp;
qp->device = device;
qp->pd = pd;
@@ -1875,19 +1892,20 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
goto err_destroy;
memset(&resp, 0, sizeof resp);
- resp.qpn = qp->qp_num;
- resp.qp_handle = obj->uevent.uobject.id;
- resp.max_recv_sge = attr.cap.max_recv_sge;
- resp.max_send_sge = attr.cap.max_send_sge;
- resp.max_recv_wr = attr.cap.max_recv_wr;
- resp.max_send_wr = attr.cap.max_send_wr;
- resp.max_inline_data = attr.cap.max_inline_data;
+ resp.base.qpn = qp->qp_num;
+ resp.base.qp_handle = obj->uevent.uobject.id;
+ resp.base.max_recv_sge = attr.cap.max_recv_sge;
+ resp.base.max_send_sge = attr.cap.max_send_sge;
+ resp.base.max_recv_wr = attr.cap.max_recv_wr;
+ resp.base.max_send_wr = attr.cap.max_send_wr;
+ resp.base.max_inline_data = attr.cap.max_inline_data;
- if (copy_to_user((void __user *) (unsigned long) cmd.response,
- &resp, sizeof resp)) {
- ret = -EFAULT;
- goto err_copy;
- }
+ resp.response_length = offsetof(typeof(resp), response_length) +
+ sizeof(resp.response_length);
+
+ ret = cb(file, &resp, ucore);
+ if (ret)
+ goto err_cb;
if (xrcd) {
obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
@@ -1913,9 +1931,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
up_write(&obj->uevent.uobject.mutex);
- return in_len;
-
-err_copy:
+ return 0;
+err_cb:
idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
err_destroy:
@@ -1937,6 +1954,113 @@ err_put:
return ret;
}
+static int ib_uverbs_create_qp_cb(struct ib_uverbs_file *file,
+ struct ib_uverbs_ex_create_qp_resp *resp,
+ struct ib_udata *ucore)
+{
+ if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base)))
+ return -EFAULT;
+
+ return 0;
+}
+
+ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_qp cmd;
+ struct ib_uverbs_ex_create_qp cmd_ex;
+ struct ib_udata ucore;
+ struct ib_udata uhw;
+ ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp);
+ int err;
+
+ if (out_len < resp_size)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof(cmd)))
+ return -EFAULT;
+
+ INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd),
+ resp_size);
+ INIT_UDATA(&uhw, buf + sizeof(cmd),
+ (unsigned long)cmd.response + resp_size,
+ in_len - sizeof(cmd), out_len - resp_size);
+
+ memset(&cmd_ex, 0, sizeof(cmd_ex));
+ cmd_ex.user_handle = cmd.user_handle;
+ cmd_ex.pd_handle = cmd.pd_handle;
+ cmd_ex.send_cq_handle = cmd.send_cq_handle;
+ cmd_ex.recv_cq_handle = cmd.recv_cq_handle;
+ cmd_ex.srq_handle = cmd.srq_handle;
+ cmd_ex.max_send_wr = cmd.max_send_wr;
+ cmd_ex.max_recv_wr = cmd.max_recv_wr;
+ cmd_ex.max_send_sge = cmd.max_send_sge;
+ cmd_ex.max_recv_sge = cmd.max_recv_sge;
+ cmd_ex.max_inline_data = cmd.max_inline_data;
+ cmd_ex.sq_sig_all = cmd.sq_sig_all;
+ cmd_ex.qp_type = cmd.qp_type;
+ cmd_ex.is_srq = cmd.is_srq;
+
+ err = create_qp(file, &ucore, &uhw, &cmd_ex,
+ offsetof(typeof(cmd_ex), is_srq) +
+ sizeof(cmd.is_srq), ib_uverbs_create_qp_cb,
+ NULL);
+
+ if (err)
+ return err;
+
+ return in_len;
+}
+
+static int ib_uverbs_ex_create_qp_cb(struct ib_uverbs_file *file,
+ struct ib_uverbs_ex_create_qp_resp *resp,
+ struct ib_udata *ucore)
+{
+ if (ib_copy_to_udata(ucore, resp, resp->response_length))
+ return -EFAULT;
+
+ return 0;
+}
+
+int ib_uverbs_ex_create_qp(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_create_qp_resp resp;
+ struct ib_uverbs_ex_create_qp cmd = {0};
+ int err;
+
+ if (ucore->inlen < (offsetof(typeof(cmd), comp_mask) +
+ sizeof(cmd.comp_mask)))
+ return -EINVAL;
+
+ err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ if (cmd.reserved)
+ return -EINVAL;
+
+ if (ucore->outlen < (offsetof(typeof(resp), response_length) +
+ sizeof(resp.response_length)))
+ return -ENOSPC;
+
+ err = create_qp(file, ucore, uhw, &cmd,
+ min(ucore->inlen, sizeof(cmd)),
+ ib_uverbs_ex_create_qp_cb, NULL);
+
+ if (err)
+ return err;
+
+ return 0;
+}
+
ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
struct ib_device *ib_dev,
const char __user *buf, int in_len, int out_len)
@@ -2221,7 +2345,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
if (qp->real_qp == qp) {
- ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
+ ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
if (ret)
goto release_qp;
ret = qp->device->modify_qp(qp, attr,
@@ -2303,6 +2427,12 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
return in_len;
}
+static void *alloc_wr(size_t wr_size, __u32 num_sge)
+{
+ return kmalloc(ALIGN(wr_size, sizeof (struct ib_sge)) +
+ num_sge * sizeof (struct ib_sge), GFP_KERNEL);
+};
+
ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
struct ib_device *ib_dev,
const char __user *buf, int in_len,
@@ -2351,14 +2481,83 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
goto out_put;
}
- next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
- user_wr->num_sge * sizeof (struct ib_sge),
- GFP_KERNEL);
- if (!next) {
- ret = -ENOMEM;
+ if (is_ud) {
+ struct ib_ud_wr *ud;
+
+ if (user_wr->opcode != IB_WR_SEND &&
+ user_wr->opcode != IB_WR_SEND_WITH_IMM) {
+ ret = -EINVAL;
+ goto out_put;
+ }
+
+ ud = alloc_wr(sizeof(*ud), user_wr->num_sge);
+ if (!ud) {
+ ret = -ENOMEM;
+ goto out_put;
+ }
+
+ ud->ah = idr_read_ah(user_wr->wr.ud.ah, file->ucontext);
+ if (!ud->ah) {
+ kfree(ud);
+ ret = -EINVAL;
+ goto out_put;
+ }
+ ud->remote_qpn = user_wr->wr.ud.remote_qpn;
+ ud->remote_qkey = user_wr->wr.ud.remote_qkey;
+
+ next = &ud->wr;
+ } else if (user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+ user_wr->opcode == IB_WR_RDMA_WRITE ||
+ user_wr->opcode == IB_WR_RDMA_READ) {
+ struct ib_rdma_wr *rdma;
+
+ rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge);
+ if (!rdma) {
+ ret = -ENOMEM;
+ goto out_put;
+ }
+
+ rdma->remote_addr = user_wr->wr.rdma.remote_addr;
+ rdma->rkey = user_wr->wr.rdma.rkey;
+
+ next = &rdma->wr;
+ } else if (user_wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+ user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
+ struct ib_atomic_wr *atomic;
+
+ atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge);
+ if (!atomic) {
+ ret = -ENOMEM;
+ goto out_put;
+ }
+
+ atomic->remote_addr = user_wr->wr.atomic.remote_addr;
+ atomic->compare_add = user_wr->wr.atomic.compare_add;
+ atomic->swap = user_wr->wr.atomic.swap;
+ atomic->rkey = user_wr->wr.atomic.rkey;
+
+ next = &atomic->wr;
+ } else if (user_wr->opcode == IB_WR_SEND ||
+ user_wr->opcode == IB_WR_SEND_WITH_IMM ||
+ user_wr->opcode == IB_WR_SEND_WITH_INV) {
+ next = alloc_wr(sizeof(*next), user_wr->num_sge);
+ if (!next) {
+ ret = -ENOMEM;
+ goto out_put;
+ }
+ } else {
+ ret = -EINVAL;
goto out_put;
}
+ if (user_wr->opcode == IB_WR_SEND_WITH_IMM ||
+ user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+ next->ex.imm_data =
+ (__be32 __force) user_wr->ex.imm_data;
+ } else if (user_wr->opcode == IB_WR_SEND_WITH_INV) {
+ next->ex.invalidate_rkey = user_wr->ex.invalidate_rkey;
+ }
+
if (!last)
wr = next;
else
@@ -2371,60 +2570,6 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
next->opcode = user_wr->opcode;
next->send_flags = user_wr->send_flags;
- if (is_ud) {
- if (next->opcode != IB_WR_SEND &&
- next->opcode != IB_WR_SEND_WITH_IMM) {
- ret = -EINVAL;
- goto out_put;
- }
-
- next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
- file->ucontext);
- if (!next->wr.ud.ah) {
- ret = -EINVAL;
- goto out_put;
- }
- next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn;
- next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
- if (next->opcode == IB_WR_SEND_WITH_IMM)
- next->ex.imm_data =
- (__be32 __force) user_wr->ex.imm_data;
- } else {
- switch (next->opcode) {
- case IB_WR_RDMA_WRITE_WITH_IMM:
- next->ex.imm_data =
- (__be32 __force) user_wr->ex.imm_data;
- case IB_WR_RDMA_WRITE:
- case IB_WR_RDMA_READ:
- next->wr.rdma.remote_addr =
- user_wr->wr.rdma.remote_addr;
- next->wr.rdma.rkey =
- user_wr->wr.rdma.rkey;
- break;
- case IB_WR_SEND_WITH_IMM:
- next->ex.imm_data =
- (__be32 __force) user_wr->ex.imm_data;
- break;
- case IB_WR_SEND_WITH_INV:
- next->ex.invalidate_rkey =
- user_wr->ex.invalidate_rkey;
- break;
- case IB_WR_ATOMIC_CMP_AND_SWP:
- case IB_WR_ATOMIC_FETCH_AND_ADD:
- next->wr.atomic.remote_addr =
- user_wr->wr.atomic.remote_addr;
- next->wr.atomic.compare_add =
- user_wr->wr.atomic.compare_add;
- next->wr.atomic.swap = user_wr->wr.atomic.swap;
- next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
- case IB_WR_SEND:
- break;
- default:
- ret = -EINVAL;
- goto out_put;
- }
- }
-
if (next->num_sge) {
next->sg_list = (void *) next +
ALIGN(sizeof *next, sizeof (struct ib_sge));
@@ -2458,8 +2603,8 @@ out_put:
put_qp_read(qp);
while (wr) {
- if (is_ud && wr->wr.ud.ah)
- put_ah_read(wr->wr.ud.ah);
+ if (is_ud && ud_wr(wr)->ah)
+ put_ah_read(ud_wr(wr)->ah);
next = wr->next;
kfree(wr);
wr = next;
@@ -2698,7 +2843,6 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
attr.grh.sgid_index = cmd.attr.grh.sgid_index;
attr.grh.hop_limit = cmd.attr.grh.hop_limit;
attr.grh.traffic_class = cmd.attr.grh.traffic_class;
- attr.vlan_id = 0;
memset(&attr.dmac, 0, sizeof(attr.dmac));
memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index c29a660c72fe..e3ef28861be6 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -127,6 +127,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow,
[IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
[IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq,
+ [IB_USER_VERBS_EX_CMD_CREATE_QP] = ib_uverbs_ex_create_qp,
};
static void ib_uverbs_add_one(struct ib_device *device);
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
index abd97247443e..7d2f14c9bbef 100644
--- a/drivers/infiniband/core/uverbs_marshall.c
+++ b/drivers/infiniband/core/uverbs_marshall.c
@@ -141,8 +141,8 @@ void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
dst->preference = src->preference;
dst->packet_life_time_selector = src->packet_life_time_selector;
- memset(dst->smac, 0, sizeof(dst->smac));
memset(dst->dmac, 0, sizeof(dst->dmac));
- dst->vlan_id = 0xffff;
+ dst->net = NULL;
+ dst->ifindex = 0;
}
EXPORT_SYMBOL(ib_copy_path_rec_from_user);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index e1f2c9887f3f..043a60ee6836 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -41,6 +41,9 @@
#include <linux/export.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <net/addrconf.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
@@ -70,7 +73,7 @@ static const char * const ib_events[] = {
[IB_EVENT_GID_CHANGE] = "GID changed",
};
-const char *ib_event_msg(enum ib_event_type event)
+const char *__attribute_const__ ib_event_msg(enum ib_event_type event)
{
size_t index = event;
@@ -104,7 +107,7 @@ static const char * const wc_statuses[] = {
[IB_WC_GENERAL_ERR] = "general error",
};
-const char *ib_wc_status_msg(enum ib_wc_status status)
+const char *__attribute_const__ ib_wc_status_msg(enum ib_wc_status status)
{
size_t index = status;
@@ -308,6 +311,35 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
}
EXPORT_SYMBOL(ib_create_ah);
+struct find_gid_index_context {
+ u16 vlan_id;
+};
+
+static bool find_gid_index(const union ib_gid *gid,
+ const struct ib_gid_attr *gid_attr,
+ void *context)
+{
+ struct find_gid_index_context *ctx =
+ (struct find_gid_index_context *)context;
+
+ if ((!!(ctx->vlan_id != 0xffff) == !is_vlan_dev(gid_attr->ndev)) ||
+ (is_vlan_dev(gid_attr->ndev) &&
+ vlan_dev_vlan_id(gid_attr->ndev) != ctx->vlan_id))
+ return false;
+
+ return true;
+}
+
+static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
+ u16 vlan_id, const union ib_gid *sgid,
+ u16 *gid_index)
+{
+ struct find_gid_index_context context = {.vlan_id = vlan_id};
+
+ return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index,
+ &context, gid_index);
+}
+
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
const struct ib_wc *wc, const struct ib_grh *grh,
struct ib_ah_attr *ah_attr)
@@ -318,21 +350,30 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
memset(ah_attr, 0, sizeof *ah_attr);
if (rdma_cap_eth_ah(device, port_num)) {
+ u16 vlan_id = wc->wc_flags & IB_WC_WITH_VLAN ?
+ wc->vlan_id : 0xffff;
+
if (!(wc->wc_flags & IB_WC_GRH))
return -EPROTOTYPE;
- if (wc->wc_flags & IB_WC_WITH_SMAC &&
- wc->wc_flags & IB_WC_WITH_VLAN) {
- memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
- ah_attr->vlan_id = wc->vlan_id;
- } else {
+ if (!(wc->wc_flags & IB_WC_WITH_SMAC) ||
+ !(wc->wc_flags & IB_WC_WITH_VLAN)) {
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
- ah_attr->dmac, &ah_attr->vlan_id);
+ ah_attr->dmac,
+ wc->wc_flags & IB_WC_WITH_VLAN ?
+ NULL : &vlan_id,
+ 0);
if (ret)
return ret;
}
- } else {
- ah_attr->vlan_id = 0xffff;
+
+ ret = get_sgid_index_from_eth(device, port_num, vlan_id,
+ &grh->dgid, &gid_index);
+ if (ret)
+ return ret;
+
+ if (wc->wc_flags & IB_WC_WITH_SMAC)
+ memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
}
ah_attr->dlid = wc->slid;
@@ -344,10 +385,13 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
ah_attr->ah_flags = IB_AH_GRH;
ah_attr->grh.dgid = grh->sgid;
- ret = ib_find_cached_gid(device, &grh->dgid, &port_num,
- &gid_index);
- if (ret)
- return ret;
+ if (!rdma_cap_eth_ah(device, port_num)) {
+ ret = ib_find_cached_gid_by_port(device, &grh->dgid,
+ port_num, NULL,
+ &gid_index);
+ if (ret)
+ return ret;
+ }
ah_attr->grh.sgid_index = (u8) gid_index;
flow_class = be32_to_cpu(grh->version_tclass_flow);
@@ -617,9 +661,7 @@ EXPORT_SYMBOL(ib_create_qp);
static const struct {
int valid;
enum ib_qp_attr_mask req_param[IB_QPT_MAX];
- enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX];
enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
- enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX];
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = {
[IB_QPS_RESET] = { .valid = 1 },
@@ -700,12 +742,6 @@ static const struct {
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER),
},
- .req_param_add_eth = {
- [IB_QPT_RC] = (IB_QP_SMAC),
- [IB_QPT_UC] = (IB_QP_SMAC),
- [IB_QPT_XRC_INI] = (IB_QP_SMAC),
- [IB_QPT_XRC_TGT] = (IB_QP_SMAC)
- },
.opt_param = {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
@@ -726,21 +762,7 @@ static const struct {
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
},
- .opt_param_add_eth = {
- [IB_QPT_RC] = (IB_QP_ALT_SMAC |
- IB_QP_VID |
- IB_QP_ALT_VID),
- [IB_QPT_UC] = (IB_QP_ALT_SMAC |
- IB_QP_VID |
- IB_QP_ALT_VID),
- [IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC |
- IB_QP_VID |
- IB_QP_ALT_VID),
- [IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC |
- IB_QP_VID |
- IB_QP_ALT_VID)
- }
- }
+ },
},
[IB_QPS_RTR] = {
[IB_QPS_RESET] = { .valid = 1 },
@@ -962,13 +984,6 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
req_param = qp_state_table[cur_state][next_state].req_param[type];
opt_param = qp_state_table[cur_state][next_state].opt_param[type];
- if (ll == IB_LINK_LAYER_ETHERNET) {
- req_param |= qp_state_table[cur_state][next_state].
- req_param_add_eth[type];
- opt_param |= qp_state_table[cur_state][next_state].
- opt_param_add_eth[type];
- }
-
if ((mask & req_param) != req_param)
return 0;
@@ -979,40 +994,52 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
}
EXPORT_SYMBOL(ib_modify_qp_is_ok);
-int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
- struct ib_qp_attr *qp_attr, int *qp_attr_mask)
+int ib_resolve_eth_dmac(struct ib_qp *qp,
+ struct ib_qp_attr *qp_attr, int *qp_attr_mask)
{
int ret = 0;
- union ib_gid sgid;
- if ((*qp_attr_mask & IB_QP_AV) &&
- (rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) {
- ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num,
- qp_attr->ah_attr.grh.sgid_index, &sgid);
- if (ret)
- goto out;
+ if (*qp_attr_mask & IB_QP_AV) {
+ if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) ||
+ qp_attr->ah_attr.port_num > rdma_end_port(qp->device))
+ return -EINVAL;
+
+ if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))
+ return 0;
+
if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
- rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac);
- rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac);
- if (!(*qp_attr_mask & IB_QP_VID))
- qp_attr->vlan_id = rdma_get_vlan_id(&sgid);
+ rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw,
+ qp_attr->ah_attr.dmac);
} else {
- ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid,
- qp_attr->ah_attr.dmac, &qp_attr->vlan_id);
- if (ret)
- goto out;
- ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL);
- if (ret)
+ union ib_gid sgid;
+ struct ib_gid_attr sgid_attr;
+ int ifindex;
+
+ ret = ib_query_gid(qp->device,
+ qp_attr->ah_attr.port_num,
+ qp_attr->ah_attr.grh.sgid_index,
+ &sgid, &sgid_attr);
+
+ if (ret || !sgid_attr.ndev) {
+ if (!ret)
+ ret = -ENXIO;
goto out;
+ }
+
+ ifindex = sgid_attr.ndev->ifindex;
+
+ ret = rdma_addr_find_dmac_by_grh(&sgid,
+ &qp_attr->ah_attr.grh.dgid,
+ qp_attr->ah_attr.dmac,
+ NULL, ifindex);
+
+ dev_put(sgid_attr.ndev);
}
- *qp_attr_mask |= IB_QP_SMAC;
- if (qp_attr->vlan_id < 0xFFFF)
- *qp_attr_mask |= IB_QP_VID;
}
out:
return ret;
}
-EXPORT_SYMBOL(ib_resolve_eth_l2_attrs);
+EXPORT_SYMBOL(ib_resolve_eth_dmac);
int ib_modify_qp(struct ib_qp *qp,
@@ -1021,7 +1048,7 @@ int ib_modify_qp(struct ib_qp *qp,
{
int ret;
- ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask);
+ ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask);
if (ret)
return ret;
@@ -1253,31 +1280,6 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd,
}
EXPORT_SYMBOL(ib_alloc_mr);
-struct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device,
- int max_page_list_len)
-{
- struct ib_fast_reg_page_list *page_list;
-
- if (!device->alloc_fast_reg_page_list)
- return ERR_PTR(-ENOSYS);
-
- page_list = device->alloc_fast_reg_page_list(device, max_page_list_len);
-
- if (!IS_ERR(page_list)) {
- page_list->device = device;
- page_list->max_page_list_len = max_page_list_len;
- }
-
- return page_list;
-}
-EXPORT_SYMBOL(ib_alloc_fast_reg_page_list);
-
-void ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
-{
- page_list->device->free_fast_reg_page_list(page_list);
-}
-EXPORT_SYMBOL(ib_free_fast_reg_page_list);
-
/* Memory windows */
struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type)
@@ -1469,3 +1471,110 @@ int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS;
}
EXPORT_SYMBOL(ib_check_mr_status);
+
+/**
+ * ib_map_mr_sg() - Map the largest prefix of a dma mapped SG list
+ * and set it the memory region.
+ * @mr: memory region
+ * @sg: dma mapped scatterlist
+ * @sg_nents: number of entries in sg
+ * @page_size: page vector desired page size
+ *
+ * Constraints:
+ * - The first sg element is allowed to have an offset.
+ * - Each sg element must be aligned to page_size (or physically
+ * contiguous to the previous element). In case an sg element has a
+ * non contiguous offset, the mapping prefix will not include it.
+ * - The last sg element is allowed to have length less than page_size.
+ * - If sg_nents total byte length exceeds the mr max_num_sge * page_size
+ * then only max_num_sg entries will be mapped.
+ *
+ * Returns the number of sg elements that were mapped to the memory region.
+ *
+ * After this completes successfully, the memory region
+ * is ready for registration.
+ */
+int ib_map_mr_sg(struct ib_mr *mr,
+ struct scatterlist *sg,
+ int sg_nents,
+ unsigned int page_size)
+{
+ if (unlikely(!mr->device->map_mr_sg))
+ return -ENOSYS;
+
+ mr->page_size = page_size;
+
+ return mr->device->map_mr_sg(mr, sg, sg_nents);
+}
+EXPORT_SYMBOL(ib_map_mr_sg);
+
+/**
+ * ib_sg_to_pages() - Convert the largest prefix of a sg list
+ * to a page vector
+ * @mr: memory region
+ * @sgl: dma mapped scatterlist
+ * @sg_nents: number of entries in sg
+ * @set_page: driver page assignment function pointer
+ *
+ * Core service helper for drivers to covert the largest
+ * prefix of given sg list to a page vector. The sg list
+ * prefix converted is the prefix that meet the requirements
+ * of ib_map_mr_sg.
+ *
+ * Returns the number of sg elements that were assigned to
+ * a page vector.
+ */
+int ib_sg_to_pages(struct ib_mr *mr,
+ struct scatterlist *sgl,
+ int sg_nents,
+ int (*set_page)(struct ib_mr *, u64))
+{
+ struct scatterlist *sg;
+ u64 last_end_dma_addr = 0, last_page_addr = 0;
+ unsigned int last_page_off = 0;
+ u64 page_mask = ~((u64)mr->page_size - 1);
+ int i;
+
+ mr->iova = sg_dma_address(&sgl[0]);
+ mr->length = 0;
+
+ for_each_sg(sgl, sg, sg_nents, i) {
+ u64 dma_addr = sg_dma_address(sg);
+ unsigned int dma_len = sg_dma_len(sg);
+ u64 end_dma_addr = dma_addr + dma_len;
+ u64 page_addr = dma_addr & page_mask;
+
+ if (i && page_addr != dma_addr) {
+ if (last_end_dma_addr != dma_addr) {
+ /* gap */
+ goto done;
+
+ } else if (last_page_off + dma_len <= mr->page_size) {
+ /* chunk this fragment with the last */
+ mr->length += dma_len;
+ last_end_dma_addr += dma_len;
+ last_page_off += dma_len;
+ continue;
+ } else {
+ /* map starting from the next page */
+ page_addr = last_page_addr + mr->page_size;
+ dma_len -= mr->page_size - last_page_off;
+ }
+ }
+
+ do {
+ if (unlikely(set_page(mr, page_addr)))
+ goto done;
+ page_addr += mr->page_size;
+ } while (page_addr < end_dma_addr);
+
+ mr->length += dma_len;
+ last_end_dma_addr = end_dma_addr;
+ last_page_addr = end_dma_addr & page_mask;
+ last_page_off = end_dma_addr & ~page_mask;
+ }
+
+done:
+ return i;
+}
+EXPORT_SYMBOL(ib_sg_to_pages);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cq.c b/drivers/infiniband/hw/cxgb3/iwch_cq.c
index cf5474ae68ff..cfe404925a39 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cq.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cq.c
@@ -123,7 +123,7 @@ static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
wc->opcode = IB_WC_LOCAL_INV;
break;
case T3_FAST_REGISTER:
- wc->opcode = IB_WC_FAST_REG_MR;
+ wc->opcode = IB_WC_REG_MR;
break;
default:
printk(KERN_ERR MOD "Unexpected opcode %d "
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 93308c45f298..c34725ca0bb4 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -463,6 +463,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
return -EINVAL;
mhp = to_iwch_mr(ib_mr);
+ kfree(mhp->pages);
rhp = mhp->rhp;
mmid = mhp->attr.stag >> 8;
cxio_dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
@@ -821,6 +822,12 @@ static struct ib_mr *iwch_alloc_mr(struct ib_pd *pd,
if (!mhp)
goto err;
+ mhp->pages = kcalloc(max_num_sg, sizeof(u64), GFP_KERNEL);
+ if (!mhp->pages) {
+ ret = -ENOMEM;
+ goto pl_err;
+ }
+
mhp->rhp = rhp;
ret = iwch_alloc_pbl(mhp, max_num_sg);
if (ret)
@@ -847,31 +854,34 @@ err3:
err2:
iwch_free_pbl(mhp);
err1:
+ kfree(mhp->pages);
+pl_err:
kfree(mhp);
err:
return ERR_PTR(ret);
}
-static struct ib_fast_reg_page_list *iwch_alloc_fastreg_pbl(
- struct ib_device *device,
- int page_list_len)
+static int iwch_set_page(struct ib_mr *ibmr, u64 addr)
{
- struct ib_fast_reg_page_list *page_list;
+ struct iwch_mr *mhp = to_iwch_mr(ibmr);
- page_list = kmalloc(sizeof *page_list + page_list_len * sizeof(u64),
- GFP_KERNEL);
- if (!page_list)
- return ERR_PTR(-ENOMEM);
+ if (unlikely(mhp->npages == mhp->attr.pbl_size))
+ return -ENOMEM;
- page_list->page_list = (u64 *)(page_list + 1);
- page_list->max_page_list_len = page_list_len;
+ mhp->pages[mhp->npages++] = addr;
- return page_list;
+ return 0;
}
-static void iwch_free_fastreg_pbl(struct ib_fast_reg_page_list *page_list)
+static int iwch_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
{
- kfree(page_list);
+ struct iwch_mr *mhp = to_iwch_mr(ibmr);
+
+ mhp->npages = 0;
+
+ return ib_sg_to_pages(ibmr, sg, sg_nents, iwch_set_page);
}
static int iwch_destroy_qp(struct ib_qp *ib_qp)
@@ -1450,8 +1460,7 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.bind_mw = iwch_bind_mw;
dev->ibdev.dealloc_mw = iwch_dealloc_mw;
dev->ibdev.alloc_mr = iwch_alloc_mr;
- dev->ibdev.alloc_fast_reg_page_list = iwch_alloc_fastreg_pbl;
- dev->ibdev.free_fast_reg_page_list = iwch_free_fastreg_pbl;
+ dev->ibdev.map_mr_sg = iwch_map_mr_sg;
dev->ibdev.attach_mcast = iwch_multicast_attach;
dev->ibdev.detach_mcast = iwch_multicast_detach;
dev->ibdev.process_mad = iwch_process_mad;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index 87c14b0c5ac0..2ac85b86a680 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -77,6 +77,8 @@ struct iwch_mr {
struct iwch_dev *rhp;
u64 kva;
struct tpt_attributes attr;
+ u64 *pages;
+ u32 npages;
};
typedef struct iwch_mw iwch_mw_handle;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index b57c0befd962..d0548fc6395e 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -95,8 +95,8 @@ static int build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
wqe->write.reserved[0] = 0;
wqe->write.reserved[1] = 0;
wqe->write.reserved[2] = 0;
- wqe->write.stag_sink = cpu_to_be32(wr->wr.rdma.rkey);
- wqe->write.to_sink = cpu_to_be64(wr->wr.rdma.remote_addr);
+ wqe->write.stag_sink = cpu_to_be32(rdma_wr(wr)->rkey);
+ wqe->write.to_sink = cpu_to_be64(rdma_wr(wr)->remote_addr);
if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
plen = 4;
@@ -137,8 +137,8 @@ static int build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr,
wqe->read.local_inv = 0;
wqe->read.reserved[0] = 0;
wqe->read.reserved[1] = 0;
- wqe->read.rem_stag = cpu_to_be32(wr->wr.rdma.rkey);
- wqe->read.rem_to = cpu_to_be64(wr->wr.rdma.remote_addr);
+ wqe->read.rem_stag = cpu_to_be32(rdma_wr(wr)->rkey);
+ wqe->read.rem_to = cpu_to_be64(rdma_wr(wr)->remote_addr);
wqe->read.local_stag = cpu_to_be32(wr->sg_list[0].lkey);
wqe->read.local_len = cpu_to_be32(wr->sg_list[0].length);
wqe->read.local_to = cpu_to_be64(wr->sg_list[0].addr);
@@ -146,27 +146,28 @@ static int build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr,
return 0;
}
-static int build_fastreg(union t3_wr *wqe, struct ib_send_wr *wr,
- u8 *flit_cnt, int *wr_cnt, struct t3_wq *wq)
+static int build_memreg(union t3_wr *wqe, struct ib_reg_wr *wr,
+ u8 *flit_cnt, int *wr_cnt, struct t3_wq *wq)
{
+ struct iwch_mr *mhp = to_iwch_mr(wr->mr);
int i;
__be64 *p;
- if (wr->wr.fast_reg.page_list_len > T3_MAX_FASTREG_DEPTH)
+ if (mhp->npages > T3_MAX_FASTREG_DEPTH)
return -EINVAL;
*wr_cnt = 1;
- wqe->fastreg.stag = cpu_to_be32(wr->wr.fast_reg.rkey);
- wqe->fastreg.len = cpu_to_be32(wr->wr.fast_reg.length);
- wqe->fastreg.va_base_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);
+ wqe->fastreg.stag = cpu_to_be32(wr->key);
+ wqe->fastreg.len = cpu_to_be32(mhp->ibmr.length);
+ wqe->fastreg.va_base_hi = cpu_to_be32(mhp->ibmr.iova >> 32);
wqe->fastreg.va_base_lo_fbo =
- cpu_to_be32(wr->wr.fast_reg.iova_start & 0xffffffff);
+ cpu_to_be32(mhp->ibmr.iova & 0xffffffff);
wqe->fastreg.page_type_perms = cpu_to_be32(
- V_FR_PAGE_COUNT(wr->wr.fast_reg.page_list_len) |
- V_FR_PAGE_SIZE(wr->wr.fast_reg.page_shift-12) |
+ V_FR_PAGE_COUNT(mhp->npages) |
+ V_FR_PAGE_SIZE(ilog2(wr->mr->page_size) - 12) |
V_FR_TYPE(TPT_VATO) |
- V_FR_PERMS(iwch_ib_to_tpt_access(wr->wr.fast_reg.access_flags)));
+ V_FR_PERMS(iwch_ib_to_tpt_access(wr->access)));
p = &wqe->fastreg.pbl_addrs[0];
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++, p++) {
+ for (i = 0; i < mhp->npages; i++, p++) {
/* If we need a 2nd WR, then set it up */
if (i == T3_MAX_FASTREG_FRAG) {
@@ -175,14 +176,14 @@ static int build_fastreg(union t3_wr *wqe, struct ib_send_wr *wr,
Q_PTR2IDX((wq->wptr+1), wq->size_log2));
build_fw_riwrh((void *)wqe, T3_WR_FASTREG, 0,
Q_GENBIT(wq->wptr + 1, wq->size_log2),
- 0, 1 + wr->wr.fast_reg.page_list_len - T3_MAX_FASTREG_FRAG,
+ 0, 1 + mhp->npages - T3_MAX_FASTREG_FRAG,
T3_EOP);
p = &wqe->pbl_frag.pbl_addrs[0];
}
- *p = cpu_to_be64((u64)wr->wr.fast_reg.page_list->page_list[i]);
+ *p = cpu_to_be64((u64)mhp->pages[i]);
}
- *flit_cnt = 5 + wr->wr.fast_reg.page_list_len;
+ *flit_cnt = 5 + mhp->npages;
if (*flit_cnt > 15)
*flit_cnt = 15;
return 0;
@@ -414,10 +415,10 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
if (!qhp->wq.oldest_read)
qhp->wq.oldest_read = sqp;
break;
- case IB_WR_FAST_REG_MR:
+ case IB_WR_REG_MR:
t3_wr_opcode = T3_WR_FASTREG;
- err = build_fastreg(wqe, wr, &t3_wr_flit_cnt,
- &wr_cnt, &qhp->wq);
+ err = build_memreg(wqe, reg_wr(wr), &t3_wr_flit_cnt,
+ &wr_cnt, &qhp->wq);
break;
case IB_WR_LOCAL_INV:
if (wr->send_flags & IB_SEND_FENCE)
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index debc39d2cbc2..c9cffced00ca 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -632,22 +632,18 @@ static void best_mtu(const unsigned short *mtus, unsigned short mtu,
static int send_connect(struct c4iw_ep *ep)
{
- struct cpl_act_open_req *req;
- struct cpl_t5_act_open_req *t5_req;
- struct cpl_act_open_req6 *req6;
- struct cpl_t5_act_open_req6 *t5_req6;
+ struct cpl_act_open_req *req = NULL;
+ struct cpl_t5_act_open_req *t5req = NULL;
+ struct cpl_t6_act_open_req *t6req = NULL;
+ struct cpl_act_open_req6 *req6 = NULL;
+ struct cpl_t5_act_open_req6 *t5req6 = NULL;
+ struct cpl_t6_act_open_req6 *t6req6 = NULL;
struct sk_buff *skb;
u64 opt0;
u32 opt2;
unsigned int mtu_idx;
int wscale;
- int wrlen;
- int sizev4 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
- sizeof(struct cpl_act_open_req) :
- sizeof(struct cpl_t5_act_open_req);
- int sizev6 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
- sizeof(struct cpl_act_open_req6) :
- sizeof(struct cpl_t5_act_open_req6);
+ int win, sizev4, sizev6, wrlen;
struct sockaddr_in *la = (struct sockaddr_in *)
&ep->com.mapped_local_addr;
struct sockaddr_in *ra = (struct sockaddr_in *)
@@ -656,8 +652,28 @@ static int send_connect(struct c4iw_ep *ep)
&ep->com.mapped_local_addr;
struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)
&ep->com.mapped_remote_addr;
- int win;
int ret;
+ enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
+ u32 isn = (prandom_u32() & ~7UL) - 1;
+
+ switch (CHELSIO_CHIP_VERSION(adapter_type)) {
+ case CHELSIO_T4:
+ sizev4 = sizeof(struct cpl_act_open_req);
+ sizev6 = sizeof(struct cpl_act_open_req6);
+ break;
+ case CHELSIO_T5:
+ sizev4 = sizeof(struct cpl_t5_act_open_req);
+ sizev6 = sizeof(struct cpl_t5_act_open_req6);
+ break;
+ case CHELSIO_T6:
+ sizev4 = sizeof(struct cpl_t6_act_open_req);
+ sizev6 = sizeof(struct cpl_t6_act_open_req6);
+ break;
+ default:
+ pr_err("T%d Chip is not supported\n",
+ CHELSIO_CHIP_VERSION(adapter_type));
+ return -EINVAL;
+ }
wrlen = (ep->com.remote_addr.ss_family == AF_INET) ?
roundup(sizev4, 16) :
@@ -706,7 +722,10 @@ static int send_connect(struct c4iw_ep *ep)
opt2 |= SACK_EN_F;
if (wscale && enable_tcp_window_scaling)
opt2 |= WND_SCALE_EN_F;
- if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+ if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) {
+ if (peer2peer)
+ isn += 4;
+
opt2 |= T5_OPT_2_VALID_F;
opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
opt2 |= T5_ISS_F;
@@ -718,102 +737,109 @@ static int send_connect(struct c4iw_ep *ep)
t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure);
- if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
- if (ep->com.remote_addr.ss_family == AF_INET) {
- req = (struct cpl_act_open_req *) skb_put(skb, wrlen);
+ if (ep->com.remote_addr.ss_family == AF_INET) {
+ switch (CHELSIO_CHIP_VERSION(adapter_type)) {
+ case CHELSIO_T4:
+ req = (struct cpl_act_open_req *)skb_put(skb, wrlen);
INIT_TP_WR(req, 0);
- OPCODE_TID(req) = cpu_to_be32(
- MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
- ((ep->rss_qid << 14) | ep->atid)));
- req->local_port = la->sin_port;
- req->peer_port = ra->sin_port;
- req->local_ip = la->sin_addr.s_addr;
- req->peer_ip = ra->sin_addr.s_addr;
- req->opt0 = cpu_to_be64(opt0);
+ break;
+ case CHELSIO_T5:
+ t5req = (struct cpl_t5_act_open_req *)skb_put(skb,
+ wrlen);
+ INIT_TP_WR(t5req, 0);
+ req = (struct cpl_act_open_req *)t5req;
+ break;
+ case CHELSIO_T6:
+ t6req = (struct cpl_t6_act_open_req *)skb_put(skb,
+ wrlen);
+ INIT_TP_WR(t6req, 0);
+ req = (struct cpl_act_open_req *)t6req;
+ t5req = (struct cpl_t5_act_open_req *)t6req;
+ break;
+ default:
+ pr_err("T%d Chip is not supported\n",
+ CHELSIO_CHIP_VERSION(adapter_type));
+ ret = -EINVAL;
+ goto clip_release;
+ }
+
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+ ((ep->rss_qid<<14) | ep->atid)));
+ req->local_port = la->sin_port;
+ req->peer_port = ra->sin_port;
+ req->local_ip = la->sin_addr.s_addr;
+ req->peer_ip = ra->sin_addr.s_addr;
+ req->opt0 = cpu_to_be64(opt0);
+
+ if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
req->params = cpu_to_be32(cxgb4_select_ntuple(
ep->com.dev->rdev.lldi.ports[0],
ep->l2t));
req->opt2 = cpu_to_be32(opt2);
} else {
+ t5req->params = cpu_to_be64(FILTER_TUPLE_V(
+ cxgb4_select_ntuple(
+ ep->com.dev->rdev.lldi.ports[0],
+ ep->l2t)));
+ t5req->rsvd = cpu_to_be32(isn);
+ PDBG("%s snd_isn %u\n", __func__, t5req->rsvd);
+ t5req->opt2 = cpu_to_be32(opt2);
+ }
+ } else {
+ switch (CHELSIO_CHIP_VERSION(adapter_type)) {
+ case CHELSIO_T4:
req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
-
INIT_TP_WR(req6, 0);
- OPCODE_TID(req6) = cpu_to_be32(
- MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
- ((ep->rss_qid<<14)|ep->atid)));
- req6->local_port = la6->sin6_port;
- req6->peer_port = ra6->sin6_port;
- req6->local_ip_hi = *((__be64 *)
- (la6->sin6_addr.s6_addr));
- req6->local_ip_lo = *((__be64 *)
- (la6->sin6_addr.s6_addr + 8));
- req6->peer_ip_hi = *((__be64 *)
- (ra6->sin6_addr.s6_addr));
- req6->peer_ip_lo = *((__be64 *)
- (ra6->sin6_addr.s6_addr + 8));
- req6->opt0 = cpu_to_be64(opt0);
+ break;
+ case CHELSIO_T5:
+ t5req6 = (struct cpl_t5_act_open_req6 *)skb_put(skb,
+ wrlen);
+ INIT_TP_WR(t5req6, 0);
+ req6 = (struct cpl_act_open_req6 *)t5req6;
+ break;
+ case CHELSIO_T6:
+ t6req6 = (struct cpl_t6_act_open_req6 *)skb_put(skb,
+ wrlen);
+ INIT_TP_WR(t6req6, 0);
+ req6 = (struct cpl_act_open_req6 *)t6req6;
+ t5req6 = (struct cpl_t5_act_open_req6 *)t6req6;
+ break;
+ default:
+ pr_err("T%d Chip is not supported\n",
+ CHELSIO_CHIP_VERSION(adapter_type));
+ ret = -EINVAL;
+ goto clip_release;
+ }
+
+ OPCODE_TID(req6) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+ ((ep->rss_qid<<14)|ep->atid)));
+ req6->local_port = la6->sin6_port;
+ req6->peer_port = ra6->sin6_port;
+ req6->local_ip_hi = *((__be64 *)(la6->sin6_addr.s6_addr));
+ req6->local_ip_lo = *((__be64 *)(la6->sin6_addr.s6_addr + 8));
+ req6->peer_ip_hi = *((__be64 *)(ra6->sin6_addr.s6_addr));
+ req6->peer_ip_lo = *((__be64 *)(ra6->sin6_addr.s6_addr + 8));
+ req6->opt0 = cpu_to_be64(opt0);
+
+ if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
req6->params = cpu_to_be32(cxgb4_select_ntuple(
ep->com.dev->rdev.lldi.ports[0],
ep->l2t));
req6->opt2 = cpu_to_be32(opt2);
- }
- } else {
- u32 isn = (prandom_u32() & ~7UL) - 1;
-
- if (peer2peer)
- isn += 4;
-
- if (ep->com.remote_addr.ss_family == AF_INET) {
- t5_req = (struct cpl_t5_act_open_req *)
- skb_put(skb, wrlen);
- INIT_TP_WR(t5_req, 0);
- OPCODE_TID(t5_req) = cpu_to_be32(
- MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
- ((ep->rss_qid << 14) | ep->atid)));
- t5_req->local_port = la->sin_port;
- t5_req->peer_port = ra->sin_port;
- t5_req->local_ip = la->sin_addr.s_addr;
- t5_req->peer_ip = ra->sin_addr.s_addr;
- t5_req->opt0 = cpu_to_be64(opt0);
- t5_req->params = cpu_to_be64(FILTER_TUPLE_V(
- cxgb4_select_ntuple(
- ep->com.dev->rdev.lldi.ports[0],
- ep->l2t)));
- t5_req->rsvd = cpu_to_be32(isn);
- PDBG("%s snd_isn %u\n", __func__,
- be32_to_cpu(t5_req->rsvd));
- t5_req->opt2 = cpu_to_be32(opt2);
} else {
- t5_req6 = (struct cpl_t5_act_open_req6 *)
- skb_put(skb, wrlen);
- INIT_TP_WR(t5_req6, 0);
- OPCODE_TID(t5_req6) = cpu_to_be32(
- MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
- ((ep->rss_qid<<14)|ep->atid)));
- t5_req6->local_port = la6->sin6_port;
- t5_req6->peer_port = ra6->sin6_port;
- t5_req6->local_ip_hi = *((__be64 *)
- (la6->sin6_addr.s6_addr));
- t5_req6->local_ip_lo = *((__be64 *)
- (la6->sin6_addr.s6_addr + 8));
- t5_req6->peer_ip_hi = *((__be64 *)
- (ra6->sin6_addr.s6_addr));
- t5_req6->peer_ip_lo = *((__be64 *)
- (ra6->sin6_addr.s6_addr + 8));
- t5_req6->opt0 = cpu_to_be64(opt0);
- t5_req6->params = cpu_to_be64(FILTER_TUPLE_V(
- cxgb4_select_ntuple(
+ t5req6->params = cpu_to_be64(FILTER_TUPLE_V(
+ cxgb4_select_ntuple(
ep->com.dev->rdev.lldi.ports[0],
ep->l2t)));
- t5_req6->rsvd = cpu_to_be32(isn);
- PDBG("%s snd_isn %u\n", __func__,
- be32_to_cpu(t5_req6->rsvd));
- t5_req6->opt2 = cpu_to_be32(opt2);
+ t5req6->rsvd = cpu_to_be32(isn);
+ PDBG("%s snd_isn %u\n", __func__, t5req6->rsvd);
+ t5req6->opt2 = cpu_to_be32(opt2);
}
}
set_bit(ACT_OPEN_REQ, &ep->com.history);
ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+clip_release:
if (ret && ep->com.remote_addr.ss_family == AF_INET6)
cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0],
(const u32 *)&la6->sin6_addr.s6_addr, 1);
@@ -1196,6 +1222,8 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
if ((status == 0) || (status == -ECONNREFUSED)) {
if (!ep->tried_with_mpa_v1) {
/* this means MPA_v2 is used */
+ event.ord = ep->ird;
+ event.ird = ep->ord;
event.private_data_len = ep->plen -
sizeof(struct mpa_v2_conn_params);
event.private_data = ep->mpa_pkt +
@@ -1203,6 +1231,8 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
sizeof(struct mpa_v2_conn_params);
} else {
/* this means MPA_v1 is used */
+ event.ord = cur_max_read_depth(ep->com.dev);
+ event.ird = cur_max_read_depth(ep->com.dev);
event.private_data_len = ep->plen;
event.private_data = ep->mpa_pkt +
sizeof(struct mpa_message);
@@ -1265,8 +1295,8 @@ static void established_upcall(struct c4iw_ep *ep)
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
memset(&event, 0, sizeof(event));
event.event = IW_CM_EVENT_ESTABLISHED;
- event.ird = ep->ird;
- event.ord = ep->ord;
+ event.ird = ep->ord;
+ event.ord = ep->ird;
if (ep->com.cm_id) {
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -1898,7 +1928,7 @@ static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
struct dst_entry *dst, struct c4iw_dev *cdev,
- bool clear_mpa_v1)
+ bool clear_mpa_v1, enum chip_type adapter_type)
{
struct neighbour *n;
int err, step;
@@ -1933,7 +1963,8 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
goto out;
ep->mtu = pdev->mtu;
ep->tx_chan = cxgb4_port_chan(pdev);
- ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+ ep->smac_idx = cxgb4_tp_smt_idx(adapter_type,
+ cxgb4_port_viid(pdev));
step = cdev->rdev.lldi.ntxq /
cdev->rdev.lldi.nchan;
ep->txq_idx = cxgb4_port_idx(pdev) * step;
@@ -1952,7 +1983,8 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
goto out;
ep->mtu = dst_mtu(dst);
ep->tx_chan = cxgb4_port_chan(pdev);
- ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+ ep->smac_idx = cxgb4_tp_smt_idx(adapter_type,
+ cxgb4_port_viid(pdev));
step = cdev->rdev.lldi.ntxq /
cdev->rdev.lldi.nchan;
ep->txq_idx = cxgb4_port_idx(pdev) * step;
@@ -2025,7 +2057,8 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
err = -EHOSTUNREACH;
goto fail3;
}
- err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false);
+ err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false,
+ ep->com.dev->rdev.lldi.adapter_type);
if (err) {
pr_err("%s - cannot alloc l2e.\n", __func__);
goto fail4;
@@ -2213,13 +2246,14 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
int wscale;
struct cpl_t5_pass_accept_rpl *rpl5 = NULL;
int win;
+ enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
BUG_ON(skb_cloned(skb));
skb_get(skb);
rpl = cplhdr(skb);
- if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+ if (!is_t4(adapter_type)) {
skb_trim(skb, roundup(sizeof(*rpl5), 16));
rpl5 = (void *)rpl;
INIT_TP_WR(rpl5, ep->hwtid);
@@ -2266,12 +2300,16 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
const struct tcphdr *tcph;
u32 hlen = ntohl(req->hdr_len);
- tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) +
- IP_HDR_LEN_G(hlen);
+ if (CHELSIO_CHIP_VERSION(adapter_type) <= CHELSIO_T5)
+ tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) +
+ IP_HDR_LEN_G(hlen);
+ else
+ tcph = (const void *)(req + 1) +
+ T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen);
if (tcph->ece && tcph->cwr)
opt2 |= CCTRL_ECN_V(1);
}
- if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+ if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) {
u32 isn = (prandom_u32() & ~7UL) - 1;
opt2 |= T5_OPT_2_VALID_F;
opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
@@ -2302,12 +2340,16 @@ static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb)
return;
}
-static void get_4tuple(struct cpl_pass_accept_req *req, int *iptype,
- __u8 *local_ip, __u8 *peer_ip,
+static void get_4tuple(struct cpl_pass_accept_req *req, enum chip_type type,
+ int *iptype, __u8 *local_ip, __u8 *peer_ip,
__be16 *local_port, __be16 *peer_port)
{
- int eth_len = ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
- int ip_len = IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
+ int eth_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
+ ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
+ T6_ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
+ int ip_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
+ IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
+ T6_IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len);
struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len);
struct tcphdr *tcp = (struct tcphdr *)
@@ -2362,7 +2404,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
- get_4tuple(req, &iptype, local_ip, peer_ip, &local_port, &peer_port);
+ get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, &iptype,
+ local_ip, peer_ip, &local_port, &peer_port);
/* Find output route */
if (iptype == 4) {
@@ -2397,7 +2440,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
- err = import_ep(child_ep, iptype, peer_ip, dst, dev, false);
+ err = import_ep(child_ep, iptype, peer_ip, dst, dev, false,
+ parent_ep->com.dev->rdev.lldi.adapter_type);
if (err) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__);
@@ -2929,7 +2973,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
} else {
if (peer2peer &&
(ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
- (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
+ (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ird == 0)
ep->ird = 1;
}
@@ -3189,7 +3233,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
goto fail2;
}
- err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true);
+ err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true,
+ ep->com.dev->rdev.lldi.adapter_type);
if (err) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
goto fail3;
@@ -3260,6 +3305,10 @@ static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
sin->sin_addr.s_addr, sin->sin_port, 0,
ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0);
if (err == -EBUSY) {
+ if (c4iw_fatal_error(&ep->com.dev->rdev)) {
+ err = -EIO;
+ break;
+ }
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(usecs_to_jiffies(100));
}
@@ -3593,20 +3642,23 @@ static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
{
- u32 l2info;
- u16 vlantag, len, hdr_len, eth_hdr_len;
+ __be32 l2info;
+ __be16 hdr_len, vlantag, len;
+ u16 eth_hdr_len;
+ int tcp_hdr_len, ip_hdr_len;
u8 intf;
struct cpl_rx_pkt *cpl = cplhdr(skb);
struct cpl_pass_accept_req *req;
struct tcp_options_received tmp_opt;
struct c4iw_dev *dev;
+ enum chip_type type;
dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
/* Store values from cpl_rx_pkt in temporary location. */
- vlantag = (__force u16) cpl->vlan;
- len = (__force u16) cpl->len;
- l2info = (__force u32) cpl->l2info;
- hdr_len = (__force u16) cpl->hdr_len;
+ vlantag = cpl->vlan;
+ len = cpl->len;
+ l2info = cpl->l2info;
+ hdr_len = cpl->hdr_len;
intf = cpl->iff;
__skb_pull(skb, sizeof(*req) + sizeof(struct rss_header));
@@ -3623,20 +3675,28 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
memset(req, 0, sizeof(*req));
req->l2info = cpu_to_be16(SYN_INTF_V(intf) |
SYN_MAC_IDX_V(RX_MACIDX_G(
- (__force int) htonl(l2info))) |
+ be32_to_cpu(l2info))) |
SYN_XACT_MATCH_F);
- eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
- RX_ETHHDR_LEN_G((__force int)htonl(l2info)) :
- RX_T5_ETHHDR_LEN_G((__force int)htonl(l2info));
- req->hdr_len = cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(
- (__force int) htonl(l2info))) |
- TCP_HDR_LEN_V(RX_TCPHDR_LEN_G(
- (__force int) htons(hdr_len))) |
- IP_HDR_LEN_V(RX_IPHDR_LEN_G(
- (__force int) htons(hdr_len))) |
- ETH_HDR_LEN_V(RX_ETHHDR_LEN_G(eth_hdr_len)));
- req->vlan = (__force __be16) vlantag;
- req->len = (__force __be16) len;
+ type = dev->rdev.lldi.adapter_type;
+ tcp_hdr_len = RX_TCPHDR_LEN_G(be16_to_cpu(hdr_len));
+ ip_hdr_len = RX_IPHDR_LEN_G(be16_to_cpu(hdr_len));
+ req->hdr_len =
+ cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(be32_to_cpu(l2info))));
+ if (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) {
+ eth_hdr_len = is_t4(type) ?
+ RX_ETHHDR_LEN_G(be32_to_cpu(l2info)) :
+ RX_T5_ETHHDR_LEN_G(be32_to_cpu(l2info));
+ req->hdr_len |= cpu_to_be32(TCP_HDR_LEN_V(tcp_hdr_len) |
+ IP_HDR_LEN_V(ip_hdr_len) |
+ ETH_HDR_LEN_V(eth_hdr_len));
+ } else { /* T6 and later */
+ eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(l2info));
+ req->hdr_len |= cpu_to_be32(T6_TCP_HDR_LEN_V(tcp_hdr_len) |
+ T6_IP_HDR_LEN_V(ip_hdr_len) |
+ T6_ETH_HDR_LEN_V(eth_hdr_len));
+ }
+ req->vlan = vlantag;
+ req->len = len;
req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) |
PASS_OPEN_TOS_V(tos));
req->tcpopt.mss = htons(tmp_opt.mss_clamp);
@@ -3755,9 +3815,22 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
- eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
- RX_ETHHDR_LEN_G(htonl(cpl->l2info)) :
- RX_T5_ETHHDR_LEN_G(htonl(cpl->l2info));
+ switch (CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)) {
+ case CHELSIO_T4:
+ eth_hdr_len = RX_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info));
+ break;
+ case CHELSIO_T5:
+ eth_hdr_len = RX_T5_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info));
+ break;
+ case CHELSIO_T6:
+ eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info));
+ break;
+ default:
+ pr_err("T%d Chip is not supported\n",
+ CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type));
+ goto reject;
+ }
+
if (eth_hdr_len == ETH_HLEN) {
eh = (struct ethhdr *)(req + 1);
iph = (struct iphdr *)(eh + 1);
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 92d518382a9f..de9cd6901752 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -752,7 +752,7 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
wc->opcode = IB_WC_LOCAL_INV;
break;
case FW_RI_FAST_REGISTER:
- wc->opcode = IB_WC_FAST_REG_MR;
+ wc->opcode = IB_WC_REG_MR;
break;
default:
printk(KERN_ERR MOD "Unexpected opcode %d "
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 1a297391b54c..58fce1742b8d 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -962,12 +962,12 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
devp->rdev.lldi.sge_egrstatuspagesize;
/*
- * For T5 devices, we map all of BAR2 with WC.
+ * For T5/T6 devices, we map all of BAR2 with WC.
* For T4 devices with onchip qp mem, we map only that part
* of BAR2 with WC.
*/
devp->rdev.bar2_pa = pci_resource_start(devp->rdev.lldi.pdev, 2);
- if (is_t5(devp->rdev.lldi.adapter_type)) {
+ if (!is_t4(devp->rdev.lldi.adapter_type)) {
devp->rdev.bar2_kva = ioremap_wc(devp->rdev.bar2_pa,
pci_resource_len(devp->rdev.lldi.pdev, 2));
if (!devp->rdev.bar2_kva) {
@@ -1267,11 +1267,9 @@ static int enable_qp_db(int id, void *p, void *data)
static void resume_rc_qp(struct c4iw_qp *qp)
{
spin_lock(&qp->lock);
- t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc,
- is_t5(qp->rhp->rdev.lldi.adapter_type), NULL);
+ t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc, NULL);
qp->wq.sq.wq_pidx_inc = 0;
- t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc,
- is_t5(qp->rhp->rdev.lldi.adapter_type), NULL);
+ t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc, NULL);
qp->wq.rq.wq_pidx_inc = 0;
spin_unlock(&qp->lock);
}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index c7bb38c931a5..00e55faa086a 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -386,6 +386,10 @@ struct c4iw_mr {
struct c4iw_dev *rhp;
u64 kva;
struct tpt_attributes attr;
+ u64 *mpl;
+ dma_addr_t mpl_addr;
+ u32 max_mpl_len;
+ u32 mpl_len;
};
static inline struct c4iw_mr *to_c4iw_mr(struct ib_mr *ibmr)
@@ -405,20 +409,6 @@ static inline struct c4iw_mw *to_c4iw_mw(struct ib_mw *ibmw)
return container_of(ibmw, struct c4iw_mw, ibmw);
}
-struct c4iw_fr_page_list {
- struct ib_fast_reg_page_list ibpl;
- DEFINE_DMA_UNMAP_ADDR(mapping);
- dma_addr_t dma_addr;
- struct c4iw_dev *dev;
- int pll_len;
-};
-
-static inline struct c4iw_fr_page_list *to_c4iw_fr_page_list(
- struct ib_fast_reg_page_list *ibpl)
-{
- return container_of(ibpl, struct c4iw_fr_page_list, ibpl);
-}
-
struct c4iw_cq {
struct ib_cq ibcq;
struct c4iw_dev *rhp;
@@ -966,13 +956,12 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param);
int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len);
void c4iw_qp_add_ref(struct ib_qp *qp);
void c4iw_qp_rem_ref(struct ib_qp *qp);
-void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *page_list);
-struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(
- struct ib_device *device,
- int page_list_len);
struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_num_sg);
+int c4iw_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents);
int c4iw_dealloc_mw(struct ib_mw *mw);
struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type);
struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start,
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 026b91ebd5e2..e1629ab58db7 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -144,7 +144,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
if (i == (num_wqe-1)) {
req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR) |
FW_WR_COMPL_F);
- req->wr.wr_lo = (__force __be64)&wr_wait;
+ req->wr.wr_lo = (__force __be64)(unsigned long)&wr_wait;
} else
req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR));
req->wr.wr_mid = cpu_to_be32(
@@ -863,6 +863,7 @@ struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
u32 mmid;
u32 stag = 0;
int ret = 0;
+ int length = roundup(max_num_sg * sizeof(u64), 32);
if (mr_type != IB_MR_TYPE_MEM_REG ||
max_num_sg > t4_max_fr_depth(use_dsgl))
@@ -876,6 +877,14 @@ struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
goto err;
}
+ mhp->mpl = dma_alloc_coherent(&rhp->rdev.lldi.pdev->dev,
+ length, &mhp->mpl_addr, GFP_KERNEL);
+ if (!mhp->mpl) {
+ ret = -ENOMEM;
+ goto err_mpl;
+ }
+ mhp->max_mpl_len = length;
+
mhp->rhp = rhp;
ret = alloc_pbl(mhp, max_num_sg);
if (ret)
@@ -905,54 +914,35 @@ err2:
c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
mhp->attr.pbl_size << 3);
err1:
+ dma_free_coherent(&mhp->rhp->rdev.lldi.pdev->dev,
+ mhp->max_mpl_len, mhp->mpl, mhp->mpl_addr);
+err_mpl:
kfree(mhp);
err:
return ERR_PTR(ret);
}
-struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,
- int page_list_len)
+static int c4iw_set_page(struct ib_mr *ibmr, u64 addr)
{
- struct c4iw_fr_page_list *c4pl;
- struct c4iw_dev *dev = to_c4iw_dev(device);
- dma_addr_t dma_addr;
- int pll_len = roundup(page_list_len * sizeof(u64), 32);
-
- c4pl = kmalloc(sizeof(*c4pl), GFP_KERNEL);
- if (!c4pl)
- return ERR_PTR(-ENOMEM);
+ struct c4iw_mr *mhp = to_c4iw_mr(ibmr);
- c4pl->ibpl.page_list = dma_alloc_coherent(&dev->rdev.lldi.pdev->dev,
- pll_len, &dma_addr,
- GFP_KERNEL);
- if (!c4pl->ibpl.page_list) {
- kfree(c4pl);
- return ERR_PTR(-ENOMEM);
- }
- dma_unmap_addr_set(c4pl, mapping, dma_addr);
- c4pl->dma_addr = dma_addr;
- c4pl->dev = dev;
- c4pl->pll_len = pll_len;
+ if (unlikely(mhp->mpl_len == mhp->max_mpl_len))
+ return -ENOMEM;
- PDBG("%s c4pl %p pll_len %u page_list %p dma_addr %pad\n",
- __func__, c4pl, c4pl->pll_len, c4pl->ibpl.page_list,
- &c4pl->dma_addr);
+ mhp->mpl[mhp->mpl_len++] = addr;
- return &c4pl->ibpl;
+ return 0;
}
-void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)
+int c4iw_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
{
- struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);
+ struct c4iw_mr *mhp = to_c4iw_mr(ibmr);
- PDBG("%s c4pl %p pll_len %u page_list %p dma_addr %pad\n",
- __func__, c4pl, c4pl->pll_len, c4pl->ibpl.page_list,
- &c4pl->dma_addr);
+ mhp->mpl_len = 0;
- dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev,
- c4pl->pll_len,
- c4pl->ibpl.page_list, dma_unmap_addr(c4pl, mapping));
- kfree(c4pl);
+ return ib_sg_to_pages(ibmr, sg, sg_nents, c4iw_set_page);
}
int c4iw_dereg_mr(struct ib_mr *ib_mr)
@@ -970,6 +960,9 @@ int c4iw_dereg_mr(struct ib_mr *ib_mr)
rhp = mhp->rhp;
mmid = mhp->attr.stag >> 8;
remove_handle(rhp, &rhp->mmidr, mmid);
+ if (mhp->mpl)
+ dma_free_coherent(&mhp->rhp->rdev.lldi.pdev->dev,
+ mhp->max_mpl_len, mhp->mpl, mhp->mpl_addr);
dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
mhp->attr.pbl_addr);
if (mhp->attr.pbl_size)
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 7746113552e7..0a7d99818b17 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -209,7 +209,7 @@ static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
if (addr >= rdev->oc_mw_pa)
vma->vm_page_prot = t4_pgprot_wc(vma->vm_page_prot);
else {
- if (is_t5(rdev->lldi.adapter_type))
+ if (!is_t4(rdev->lldi.adapter_type))
vma->vm_page_prot =
t4_pgprot_wc(vma->vm_page_prot);
else
@@ -557,8 +557,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.bind_mw = c4iw_bind_mw;
dev->ibdev.dealloc_mw = c4iw_dealloc_mw;
dev->ibdev.alloc_mr = c4iw_alloc_mr;
- dev->ibdev.alloc_fast_reg_page_list = c4iw_alloc_fastreg_pbl;
- dev->ibdev.free_fast_reg_page_list = c4iw_free_fastreg_pbl;
+ dev->ibdev.map_mr_sg = c4iw_map_mr_sg;
dev->ibdev.attach_mcast = c4iw_multicast_attach;
dev->ibdev.detach_mcast = c4iw_multicast_detach;
dev->ibdev.process_mad = c4iw_process_mad;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 6517e1208ccb..aa515afee724 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -528,8 +528,8 @@ static int build_rdma_write(struct t4_sq *sq, union t4_wr *wqe,
if (wr->num_sge > T4_MAX_SEND_SGE)
return -EINVAL;
wqe->write.r2 = 0;
- wqe->write.stag_sink = cpu_to_be32(wr->wr.rdma.rkey);
- wqe->write.to_sink = cpu_to_be64(wr->wr.rdma.remote_addr);
+ wqe->write.stag_sink = cpu_to_be32(rdma_wr(wr)->rkey);
+ wqe->write.to_sink = cpu_to_be64(rdma_wr(wr)->remote_addr);
if (wr->num_sge) {
if (wr->send_flags & IB_SEND_INLINE) {
ret = build_immd(sq, wqe->write.u.immd_src, wr,
@@ -566,10 +566,10 @@ static int build_rdma_read(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
if (wr->num_sge > 1)
return -EINVAL;
if (wr->num_sge) {
- wqe->read.stag_src = cpu_to_be32(wr->wr.rdma.rkey);
- wqe->read.to_src_hi = cpu_to_be32((u32)(wr->wr.rdma.remote_addr
+ wqe->read.stag_src = cpu_to_be32(rdma_wr(wr)->rkey);
+ wqe->read.to_src_hi = cpu_to_be32((u32)(rdma_wr(wr)->remote_addr
>> 32));
- wqe->read.to_src_lo = cpu_to_be32((u32)wr->wr.rdma.remote_addr);
+ wqe->read.to_src_lo = cpu_to_be32((u32)rdma_wr(wr)->remote_addr);
wqe->read.stag_sink = cpu_to_be32(wr->sg_list[0].lkey);
wqe->read.plen = cpu_to_be32(wr->sg_list[0].length);
wqe->read.to_sink_hi = cpu_to_be32((u32)(wr->sg_list[0].addr
@@ -605,47 +605,41 @@ static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe,
return 0;
}
-static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
- struct ib_send_wr *wr, u8 *len16, u8 t5dev)
+static int build_memreg(struct t4_sq *sq, union t4_wr *wqe,
+ struct ib_reg_wr *wr, u8 *len16, u8 t5dev)
{
-
+ struct c4iw_mr *mhp = to_c4iw_mr(wr->mr);
struct fw_ri_immd *imdp;
__be64 *p;
int i;
- int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32);
+ int pbllen = roundup(mhp->mpl_len * sizeof(u64), 32);
int rem;
- if (wr->wr.fast_reg.page_list_len >
- t4_max_fr_depth(use_dsgl))
+ if (mhp->mpl_len > t4_max_fr_depth(use_dsgl))
return -EINVAL;
wqe->fr.qpbinde_to_dcacpu = 0;
- wqe->fr.pgsz_shift = wr->wr.fast_reg.page_shift - 12;
+ wqe->fr.pgsz_shift = ilog2(wr->mr->page_size) - 12;
wqe->fr.addr_type = FW_RI_VA_BASED_TO;
- wqe->fr.mem_perms = c4iw_ib_to_tpt_access(wr->wr.fast_reg.access_flags);
+ wqe->fr.mem_perms = c4iw_ib_to_tpt_access(wr->access);
wqe->fr.len_hi = 0;
- wqe->fr.len_lo = cpu_to_be32(wr->wr.fast_reg.length);
- wqe->fr.stag = cpu_to_be32(wr->wr.fast_reg.rkey);
- wqe->fr.va_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);
- wqe->fr.va_lo_fbo = cpu_to_be32(wr->wr.fast_reg.iova_start &
+ wqe->fr.len_lo = cpu_to_be32(mhp->ibmr.length);
+ wqe->fr.stag = cpu_to_be32(wr->key);
+ wqe->fr.va_hi = cpu_to_be32(mhp->ibmr.iova >> 32);
+ wqe->fr.va_lo_fbo = cpu_to_be32(mhp->ibmr.iova &
0xffffffff);
if (t5dev && use_dsgl && (pbllen > max_fr_immd)) {
- struct c4iw_fr_page_list *c4pl =
- to_c4iw_fr_page_list(wr->wr.fast_reg.page_list);
struct fw_ri_dsgl *sglp;
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
- wr->wr.fast_reg.page_list->page_list[i] = (__force u64)
- cpu_to_be64((u64)
- wr->wr.fast_reg.page_list->page_list[i]);
- }
+ for (i = 0; i < mhp->mpl_len; i++)
+ mhp->mpl[i] = (__force u64)cpu_to_be64((u64)mhp->mpl[i]);
sglp = (struct fw_ri_dsgl *)(&wqe->fr + 1);
sglp->op = FW_RI_DATA_DSGL;
sglp->r1 = 0;
sglp->nsge = cpu_to_be16(1);
- sglp->addr0 = cpu_to_be64(c4pl->dma_addr);
+ sglp->addr0 = cpu_to_be64(mhp->mpl_addr);
sglp->len0 = cpu_to_be32(pbllen);
*len16 = DIV_ROUND_UP(sizeof(wqe->fr) + sizeof(*sglp), 16);
@@ -657,9 +651,8 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
imdp->immdlen = cpu_to_be32(pbllen);
p = (__be64 *)(imdp + 1);
rem = pbllen;
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
- *p = cpu_to_be64(
- (u64)wr->wr.fast_reg.page_list->page_list[i]);
+ for (i = 0; i < mhp->mpl_len; i++) {
+ *p = cpu_to_be64((u64)mhp->mpl[i]);
rem -= sizeof(*p);
if (++p == (__be64 *)&sq->queue[sq->size])
p = (__be64 *)sq->queue;
@@ -712,8 +705,7 @@ static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc)
spin_lock_irqsave(&qhp->rhp->lock, flags);
spin_lock(&qhp->lock);
if (qhp->rhp->db_state == NORMAL)
- t4_ring_sq_db(&qhp->wq, inc,
- is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
+ t4_ring_sq_db(&qhp->wq, inc, NULL);
else {
add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
qhp->wq.sq.wq_pidx_inc += inc;
@@ -730,8 +722,7 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc)
spin_lock_irqsave(&qhp->rhp->lock, flags);
spin_lock(&qhp->lock);
if (qhp->rhp->db_state == NORMAL)
- t4_ring_rq_db(&qhp->wq, inc,
- is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
+ t4_ring_rq_db(&qhp->wq, inc, NULL);
else {
add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
qhp->wq.rq.wq_pidx_inc += inc;
@@ -813,13 +804,13 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
if (!qhp->wq.sq.oldest_read)
qhp->wq.sq.oldest_read = swsqe;
break;
- case IB_WR_FAST_REG_MR:
+ case IB_WR_REG_MR:
fw_opcode = FW_RI_FR_NSMR_WR;
swsqe->opcode = FW_RI_FAST_REGISTER;
- err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16,
- is_t5(
- qhp->rhp->rdev.lldi.adapter_type) ?
- 1 : 0);
+ err = build_memreg(&qhp->wq.sq, wqe, reg_wr(wr), &len16,
+ is_t5(
+ qhp->rhp->rdev.lldi.adapter_type) ?
+ 1 : 0);
break;
case IB_WR_LOCAL_INV:
if (wr->send_flags & IB_SEND_FENCE)
@@ -860,8 +851,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
}
if (!qhp->rhp->rdev.status_page->db_off) {
- t4_ring_sq_db(&qhp->wq, idx,
- is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
+ t4_ring_sq_db(&qhp->wq, idx, wqe);
spin_unlock_irqrestore(&qhp->lock, flag);
} else {
spin_unlock_irqrestore(&qhp->lock, flag);
@@ -934,8 +924,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
num_wrs--;
}
if (!qhp->rhp->rdev.status_page->db_off) {
- t4_ring_rq_db(&qhp->wq, idx,
- is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
+ t4_ring_rq_db(&qhp->wq, idx, wqe);
spin_unlock_irqrestore(&qhp->lock, flag);
} else {
spin_unlock_irqrestore(&qhp->lock, flag);
@@ -1875,7 +1864,7 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
attrs.rq_db_inc = attr->rq_psn;
mask |= (attr_mask & IB_QP_SQ_PSN) ? C4IW_QP_ATTR_SQ_DB : 0;
mask |= (attr_mask & IB_QP_RQ_PSN) ? C4IW_QP_ATTR_RQ_DB : 0;
- if (is_t5(to_c4iw_qp(ibqp)->rhp->rdev.lldi.adapter_type) &&
+ if (!is_t4(to_c4iw_qp(ibqp)->rhp->rdev.lldi.adapter_type) &&
(mask & (C4IW_QP_ATTR_SQ_DB|C4IW_QP_ATTR_RQ_DB)))
return -EINVAL;
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 274a7ab13bef..1092a2d1f607 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -455,8 +455,7 @@ static inline void pio_copy(u64 __iomem *dst, u64 *src)
}
}
-static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5,
- union t4_wr *wqe)
+static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, union t4_wr *wqe)
{
/* Flush host queue memory writes. */
@@ -482,7 +481,7 @@ static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5,
writel(QID_V(wq->sq.qid) | PIDX_V(inc), wq->db);
}
-static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5,
+static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc,
union t4_recv_wr *wqe)
{
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 1688a17de4fe..86af71351d9a 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -76,7 +76,10 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr
struct mlx4_dev *dev = ibdev->dev;
int is_mcast = 0;
struct in6_addr in6;
- u16 vlan_tag;
+ u16 vlan_tag = 0xffff;
+ union ib_gid sgid;
+ struct ib_gid_attr gid_attr;
+ int ret;
memcpy(&in6, ah_attr->grh.dgid.raw, sizeof(in6));
if (rdma_is_multicast_addr(&in6)) {
@@ -85,7 +88,17 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr
} else {
memcpy(ah->av.eth.mac, ah_attr->dmac, ETH_ALEN);
}
- vlan_tag = ah_attr->vlan_id;
+ ret = ib_get_cached_gid(pd->device, ah_attr->port_num,
+ ah_attr->grh.sgid_index, &sgid, &gid_attr);
+ if (ret)
+ return ERR_PTR(ret);
+ memset(ah->av.eth.s_mac, 0, ETH_ALEN);
+ if (gid_attr.ndev) {
+ if (is_vlan_dev(gid_attr.ndev))
+ vlan_tag = vlan_dev_vlan_id(gid_attr.ndev);
+ memcpy(ah->av.eth.s_mac, gid_attr.ndev->dev_addr, ETH_ALEN);
+ dev_put(gid_attr.ndev);
+ }
if (vlan_tag < 0x1000)
vlan_tag |= (ah_attr->sl & 7) << 13;
ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 5fd49f9435f9..b88fc8f5ab18 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -818,7 +818,7 @@ repoll:
wc->opcode = IB_WC_LSO;
break;
case MLX4_OPCODE_FMR:
- wc->opcode = IB_WC_FAST_REG_MR;
+ wc->opcode = IB_WC_REG_MR;
break;
case MLX4_OPCODE_LOCAL_INVAL:
wc->opcode = IB_WC_LOCAL_INV;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 1cd75ff02251..870e56b6b25f 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -457,7 +457,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
struct ib_grh *grh, struct ib_mad *mad)
{
struct ib_sge list;
- struct ib_send_wr wr, *bad_wr;
+ struct ib_ud_wr wr;
+ struct ib_send_wr *bad_wr;
struct mlx4_ib_demux_pv_ctx *tun_ctx;
struct mlx4_ib_demux_pv_qp *tun_qp;
struct mlx4_rcv_tunnel_mad *tun_mad;
@@ -582,18 +583,18 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
list.length = sizeof (struct mlx4_rcv_tunnel_mad);
list.lkey = tun_ctx->pd->local_dma_lkey;
- wr.wr.ud.ah = ah;
- wr.wr.ud.port_num = port;
- wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
- wr.wr.ud.remote_qpn = dqpn;
- wr.next = NULL;
- wr.wr_id = ((u64) tun_tx_ix) | MLX4_TUN_SET_WRID_QPN(dest_qpt);
- wr.sg_list = &list;
- wr.num_sge = 1;
- wr.opcode = IB_WR_SEND;
- wr.send_flags = IB_SEND_SIGNALED;
-
- ret = ib_post_send(src_qp, &wr, &bad_wr);
+ wr.ah = ah;
+ wr.port_num = port;
+ wr.remote_qkey = IB_QP_SET_QKEY;
+ wr.remote_qpn = dqpn;
+ wr.wr.next = NULL;
+ wr.wr.wr_id = ((u64) tun_tx_ix) | MLX4_TUN_SET_WRID_QPN(dest_qpt);
+ wr.wr.sg_list = &list;
+ wr.wr.num_sge = 1;
+ wr.wr.opcode = IB_WR_SEND;
+ wr.wr.send_flags = IB_SEND_SIGNALED;
+
+ ret = ib_post_send(src_qp, &wr.wr, &bad_wr);
out:
if (ret)
ib_destroy_ah(ah);
@@ -824,18 +825,29 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
{
struct mlx4_counter counter_stats;
struct mlx4_ib_dev *dev = to_mdev(ibdev);
- int err;
+ struct counter_index *tmp_counter;
+ int err = IB_MAD_RESULT_FAILURE, stats_avail = 0;
if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
return -EINVAL;
memset(&counter_stats, 0, sizeof(counter_stats));
- err = mlx4_get_counter_stats(dev->dev,
- dev->counters[port_num - 1].index,
- &counter_stats, 0);
- if (err)
- err = IB_MAD_RESULT_FAILURE;
- else {
+ mutex_lock(&dev->counters_table[port_num - 1].mutex);
+ list_for_each_entry(tmp_counter,
+ &dev->counters_table[port_num - 1].counters_list,
+ list) {
+ err = mlx4_get_counter_stats(dev->dev,
+ tmp_counter->index,
+ &counter_stats, 0);
+ if (err) {
+ err = IB_MAD_RESULT_FAILURE;
+ stats_avail = 0;
+ break;
+ }
+ stats_avail = 1;
+ }
+ mutex_unlock(&dev->counters_table[port_num - 1].mutex);
+ if (stats_avail) {
memset(out_mad->data, 0, sizeof out_mad->data);
switch (counter_stats.counter_mode & 0xf) {
case 0:
@@ -1172,10 +1184,11 @@ static int is_proxy_qp0(struct mlx4_ib_dev *dev, int qpn, int slave)
int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
enum ib_qp_type dest_qpt, u16 pkey_index,
u32 remote_qpn, u32 qkey, struct ib_ah_attr *attr,
- u8 *s_mac, struct ib_mad *mad)
+ u8 *s_mac, u16 vlan_id, struct ib_mad *mad)
{
struct ib_sge list;
- struct ib_send_wr wr, *bad_wr;
+ struct ib_ud_wr wr;
+ struct ib_send_wr *bad_wr;
struct mlx4_ib_demux_pv_ctx *sqp_ctx;
struct mlx4_ib_demux_pv_qp *sqp;
struct mlx4_mad_snd_buf *sqp_mad;
@@ -1246,22 +1259,25 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
list.length = sizeof (struct mlx4_mad_snd_buf);
list.lkey = sqp_ctx->pd->local_dma_lkey;
- wr.wr.ud.ah = ah;
- wr.wr.ud.port_num = port;
- wr.wr.ud.pkey_index = wire_pkey_ix;
- wr.wr.ud.remote_qkey = qkey;
- wr.wr.ud.remote_qpn = remote_qpn;
- wr.next = NULL;
- wr.wr_id = ((u64) wire_tx_ix) | MLX4_TUN_SET_WRID_QPN(src_qpnum);
- wr.sg_list = &list;
- wr.num_sge = 1;
- wr.opcode = IB_WR_SEND;
- wr.send_flags = IB_SEND_SIGNALED;
+ wr.ah = ah;
+ wr.port_num = port;
+ wr.pkey_index = wire_pkey_ix;
+ wr.remote_qkey = qkey;
+ wr.remote_qpn = remote_qpn;
+ wr.wr.next = NULL;
+ wr.wr.wr_id = ((u64) wire_tx_ix) | MLX4_TUN_SET_WRID_QPN(src_qpnum);
+ wr.wr.sg_list = &list;
+ wr.wr.num_sge = 1;
+ wr.wr.opcode = IB_WR_SEND;
+ wr.wr.send_flags = IB_SEND_SIGNALED;
if (s_mac)
memcpy(to_mah(ah)->av.eth.s_mac, s_mac, 6);
+ if (vlan_id < 0x1000)
+ vlan_id |= (attr->sl & 7) << 13;
+ to_mah(ah)->av.eth.vlan = cpu_to_be16(vlan_id);
- ret = ib_post_send(send_qp, &wr, &bad_wr);
+ ret = ib_post_send(send_qp, &wr.wr, &bad_wr);
out:
if (ret)
ib_destroy_ah(ah);
@@ -1295,6 +1311,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
u8 *slave_id;
int slave;
int port;
+ u16 vlan_id;
/* Get slave that sent this packet */
if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
@@ -1383,10 +1400,10 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);
memcpy(ah_attr.dmac, tunnel->hdr.mac, 6);
- ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan);
+ vlan_id = be16_to_cpu(tunnel->hdr.vlan);
/* if slave have default vlan use it */
mlx4_get_slave_default_vlan(dev->dev, ctx->port, slave,
- &ah_attr.vlan_id, &ah_attr.sl);
+ &vlan_id, &ah_attr.sl);
mlx4_ib_send_to_wire(dev, slave, ctx->port,
is_proxy_qp0(dev, wc->src_qp, slave) ?
@@ -1394,7 +1411,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
be16_to_cpu(tunnel->hdr.pkey_index),
be32_to_cpu(tunnel->hdr.remote_qpn),
be32_to_cpu(tunnel->hdr.qkey),
- &ah_attr, wc->smac, &tunnel->mad);
+ &ah_attr, wc->smac, vlan_id, &tunnel->mad);
}
static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index efecdf0216d8..f567160a4a56 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -335,7 +335,7 @@ int mlx4_ib_gid_index_to_real_index(struct mlx4_ib_dev *ibdev,
if (!rdma_cap_roce_gid_table(&ibdev->ib_dev, port_num))
return index;
- ret = ib_get_cached_gid(&ibdev->ib_dev, port_num, index, &gid);
+ ret = ib_get_cached_gid(&ibdev->ib_dev, port_num, index, &gid, NULL);
if (ret)
return ret;
@@ -442,6 +442,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
}
+ props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
+
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
props->vendor_part_id = dev->dev->persist->pdev->device;
@@ -754,7 +756,7 @@ static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
if (!rdma_cap_roce_gid_table(ibdev, port))
return -ENODEV;
- ret = ib_get_cached_gid(ibdev, port, index, gid);
+ ret = ib_get_cached_gid(ibdev, port, index, gid, NULL);
if (ret == -EAGAIN) {
memcpy(gid, &zgid, sizeof(*gid));
return 0;
@@ -1247,6 +1249,22 @@ static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
return 0;
}
+static void mlx4_ib_delete_counters_table(struct mlx4_ib_dev *ibdev,
+ struct mlx4_ib_counters *ctr_table)
+{
+ struct counter_index *counter, *tmp_count;
+
+ mutex_lock(&ctr_table->mutex);
+ list_for_each_entry_safe(counter, tmp_count, &ctr_table->counters_list,
+ list) {
+ if (counter->allocated)
+ mlx4_counter_free(ibdev->dev, counter->index);
+ list_del(&counter->list);
+ kfree(counter);
+ }
+ mutex_unlock(&ctr_table->mutex);
+}
+
int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
union ib_gid *gid)
{
@@ -2131,6 +2149,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
int num_req_counters;
int allocated;
u32 counter_index;
+ struct counter_index *new_counter_index = NULL;
pr_info_once("%s", mlx4_ib_version);
@@ -2247,8 +2266,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.rereg_user_mr = mlx4_ib_rereg_user_mr;
ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr;
ibdev->ib_dev.alloc_mr = mlx4_ib_alloc_mr;
- ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
- ibdev->ib_dev.free_fast_reg_page_list = mlx4_ib_free_fast_reg_page_list;
+ ibdev->ib_dev.map_mr_sg = mlx4_ib_map_mr_sg;
ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach;
ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
@@ -2293,7 +2311,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.uverbs_ex_cmd_mask |=
(1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE) |
- (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ);
+ (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ) |
+ (1ull << IB_USER_VERBS_EX_CMD_CREATE_QP);
mlx4_ib_alloc_eqs(dev, ibdev);
@@ -2302,6 +2321,11 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
if (init_node_data(ibdev))
goto err_map;
+ for (i = 0; i < ibdev->num_ports; ++i) {
+ mutex_init(&ibdev->counters_table[i].mutex);
+ INIT_LIST_HEAD(&ibdev->counters_table[i].counters_list);
+ }
+
num_req_counters = mlx4_is_bonded(dev) ? 1 : ibdev->num_ports;
for (i = 0; i < num_req_counters; ++i) {
mutex_init(&ibdev->qp1_proxy_lock[i]);
@@ -2320,15 +2344,34 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
counter_index = mlx4_get_default_counter_index(dev,
i + 1);
}
- ibdev->counters[i].index = counter_index;
- ibdev->counters[i].allocated = allocated;
+ new_counter_index = kmalloc(sizeof(*new_counter_index),
+ GFP_KERNEL);
+ if (!new_counter_index) {
+ if (allocated)
+ mlx4_counter_free(ibdev->dev, counter_index);
+ goto err_counter;
+ }
+ new_counter_index->index = counter_index;
+ new_counter_index->allocated = allocated;
+ list_add_tail(&new_counter_index->list,
+ &ibdev->counters_table[i].counters_list);
+ ibdev->counters_table[i].default_counter = counter_index;
pr_info("counter index %d for port %d allocated %d\n",
counter_index, i + 1, allocated);
}
if (mlx4_is_bonded(dev))
for (i = 1; i < ibdev->num_ports ; ++i) {
- ibdev->counters[i].index = ibdev->counters[0].index;
- ibdev->counters[i].allocated = 0;
+ new_counter_index =
+ kmalloc(sizeof(struct counter_index),
+ GFP_KERNEL);
+ if (!new_counter_index)
+ goto err_counter;
+ new_counter_index->index = counter_index;
+ new_counter_index->allocated = 0;
+ list_add_tail(&new_counter_index->list,
+ &ibdev->counters_table[i].counters_list);
+ ibdev->counters_table[i].default_counter =
+ counter_index;
}
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
@@ -2437,12 +2480,9 @@ err_steer_qp_release:
mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
ibdev->steer_qpn_count);
err_counter:
- for (i = 0; i < ibdev->num_ports; ++i) {
- if (ibdev->counters[i].index != -1 &&
- ibdev->counters[i].allocated)
- mlx4_counter_free(ibdev->dev,
- ibdev->counters[i].index);
- }
+ for (i = 0; i < ibdev->num_ports; ++i)
+ mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[i]);
+
err_map:
iounmap(ibdev->uar_map);
@@ -2546,9 +2586,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
iounmap(ibdev->uar_map);
for (p = 0; p < ibdev->num_ports; ++p)
- if (ibdev->counters[p].index != -1 &&
- ibdev->counters[p].allocated)
- mlx4_counter_free(ibdev->dev, ibdev->counters[p].index);
+ mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[p]);
+
mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
mlx4_CLOSE_PORT(dev, p);
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
index 2d5bccd71fc6..99451d887266 100644
--- a/drivers/infiniband/hw/mlx4/mcg.c
+++ b/drivers/infiniband/hw/mlx4/mcg.c
@@ -222,7 +222,7 @@ static int send_mad_to_wire(struct mlx4_ib_demux_ctx *ctx, struct ib_mad *mad)
spin_unlock_irqrestore(&dev->sm_lock, flags);
return mlx4_ib_send_to_wire(dev, mlx4_master_func_num(dev->dev),
ctx->port, IB_QPT_GSI, 0, 1, IB_QP1_QKEY,
- &ah_attr, NULL, mad);
+ &ah_attr, NULL, 0xffff, mad);
}
static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 1e7b23bb2eb0..1caa11edac03 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -129,10 +129,17 @@ struct mlx4_ib_cq {
struct list_head recv_qp_list;
};
+#define MLX4_MR_PAGES_ALIGN 0x40
+
struct mlx4_ib_mr {
struct ib_mr ibmr;
+ __be64 *pages;
+ dma_addr_t page_map;
+ u32 npages;
+ u32 max_pages;
struct mlx4_mr mmr;
struct ib_umem *umem;
+ void *pages_alloc;
};
struct mlx4_ib_mw {
@@ -140,12 +147,6 @@ struct mlx4_ib_mw {
struct mlx4_mw mmw;
};
-struct mlx4_ib_fast_reg_page_list {
- struct ib_fast_reg_page_list ibfrpl;
- __be64 *mapped_page_list;
- dma_addr_t map;
-};
-
struct mlx4_ib_fmr {
struct ib_fmr ibfmr;
struct mlx4_fmr mfmr;
@@ -320,6 +321,7 @@ struct mlx4_ib_qp {
struct list_head qps_list;
struct list_head cq_recv_list;
struct list_head cq_send_list;
+ struct counter_index *counter_index;
};
struct mlx4_ib_srq {
@@ -528,10 +530,17 @@ struct mlx4_ib_iov_port {
};
struct counter_index {
+ struct list_head list;
u32 index;
u8 allocated;
};
+struct mlx4_ib_counters {
+ struct list_head counters_list;
+ struct mutex mutex; /* mutex for accessing counters list */
+ u32 default_counter;
+};
+
struct mlx4_ib_dev {
struct ib_device ib_dev;
struct mlx4_dev *dev;
@@ -550,7 +559,7 @@ struct mlx4_ib_dev {
struct mutex cap_mask_mutex;
bool ib_active;
struct mlx4_ib_iboe iboe;
- struct counter_index counters[MLX4_MAX_PORTS];
+ struct mlx4_ib_counters counters_table[MLX4_MAX_PORTS];
int *eq_table;
struct kobject *iov_parent;
struct kobject *ports_parent;
@@ -638,11 +647,6 @@ static inline struct mlx4_ib_mw *to_mmw(struct ib_mw *ibmw)
return container_of(ibmw, struct mlx4_ib_mw, ibmw);
}
-static inline struct mlx4_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_page_list *ibfrpl)
-{
- return container_of(ibfrpl, struct mlx4_ib_fast_reg_page_list, ibfrpl);
-}
-
static inline struct mlx4_ib_fmr *to_mfmr(struct ib_fmr *ibfmr)
{
return container_of(ibfmr, struct mlx4_ib_fmr, ibfmr);
@@ -706,10 +710,9 @@ int mlx4_ib_dealloc_mw(struct ib_mw *mw);
struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_num_sg);
-struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
- int page_list_len);
-void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list);
-
+int mlx4_ib_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents);
int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev,
@@ -813,7 +816,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
enum ib_qp_type dest_qpt, u16 pkey_index, u32 remote_qpn,
u32 qkey, struct ib_ah_attr *attr, u8 *s_mac,
- struct ib_mad *mad);
+ u16 vlan_id, struct ib_mad *mad);
__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 2542fd3c1a49..4d1e1c632603 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -59,7 +59,7 @@ struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc)
struct mlx4_ib_mr *mr;
int err;
- mr = kmalloc(sizeof *mr, GFP_KERNEL);
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
@@ -140,7 +140,7 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
int err;
int n;
- mr = kmalloc(sizeof *mr, GFP_KERNEL);
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
@@ -271,11 +271,59 @@ release_mpt_entry:
return err;
}
+static int
+mlx4_alloc_priv_pages(struct ib_device *device,
+ struct mlx4_ib_mr *mr,
+ int max_pages)
+{
+ int size = max_pages * sizeof(u64);
+ int add_size;
+ int ret;
+
+ add_size = max_t(int, MLX4_MR_PAGES_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
+
+ mr->pages_alloc = kzalloc(size + add_size, GFP_KERNEL);
+ if (!mr->pages_alloc)
+ return -ENOMEM;
+
+ mr->pages = PTR_ALIGN(mr->pages_alloc, MLX4_MR_PAGES_ALIGN);
+
+ mr->page_map = dma_map_single(device->dma_device, mr->pages,
+ size, DMA_TO_DEVICE);
+
+ if (dma_mapping_error(device->dma_device, mr->page_map)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ return 0;
+err:
+ kfree(mr->pages_alloc);
+
+ return ret;
+}
+
+static void
+mlx4_free_priv_pages(struct mlx4_ib_mr *mr)
+{
+ if (mr->pages) {
+ struct ib_device *device = mr->ibmr.device;
+ int size = mr->max_pages * sizeof(u64);
+
+ dma_unmap_single(device->dma_device, mr->page_map,
+ size, DMA_TO_DEVICE);
+ kfree(mr->pages_alloc);
+ mr->pages = NULL;
+ }
+}
+
int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
{
struct mlx4_ib_mr *mr = to_mmr(ibmr);
int ret;
+ mlx4_free_priv_pages(mr);
+
ret = mlx4_mr_free(to_mdev(ibmr->device)->dev, &mr->mmr);
if (ret)
return ret;
@@ -321,21 +369,21 @@ err_free:
int mlx4_ib_bind_mw(struct ib_qp *qp, struct ib_mw *mw,
struct ib_mw_bind *mw_bind)
{
- struct ib_send_wr wr;
+ struct ib_bind_mw_wr wr;
struct ib_send_wr *bad_wr;
int ret;
memset(&wr, 0, sizeof(wr));
- wr.opcode = IB_WR_BIND_MW;
- wr.wr_id = mw_bind->wr_id;
- wr.send_flags = mw_bind->send_flags;
- wr.wr.bind_mw.mw = mw;
- wr.wr.bind_mw.bind_info = mw_bind->bind_info;
- wr.wr.bind_mw.rkey = ib_inc_rkey(mw->rkey);
-
- ret = mlx4_ib_post_send(qp, &wr, &bad_wr);
+ wr.wr.opcode = IB_WR_BIND_MW;
+ wr.wr.wr_id = mw_bind->wr_id;
+ wr.wr.send_flags = mw_bind->send_flags;
+ wr.mw = mw;
+ wr.bind_info = mw_bind->bind_info;
+ wr.rkey = ib_inc_rkey(mw->rkey);
+
+ ret = mlx4_ib_post_send(qp, &wr.wr, &bad_wr);
if (!ret)
- mw->rkey = wr.wr.bind_mw.rkey;
+ mw->rkey = wr.rkey;
return ret;
}
@@ -362,7 +410,7 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
max_num_sg > MLX4_MAX_FAST_REG_PAGES)
return ERR_PTR(-EINVAL);
- mr = kmalloc(sizeof *mr, GFP_KERNEL);
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
@@ -371,71 +419,30 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
if (err)
goto err_free;
+ err = mlx4_alloc_priv_pages(pd->device, mr, max_num_sg);
+ if (err)
+ goto err_free_mr;
+
+ mr->max_pages = max_num_sg;
+
err = mlx4_mr_enable(dev->dev, &mr->mmr);
if (err)
- goto err_mr;
+ goto err_free_pl;
mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key;
mr->umem = NULL;
return &mr->ibmr;
-err_mr:
+err_free_pl:
+ mlx4_free_priv_pages(mr);
+err_free_mr:
(void) mlx4_mr_free(dev->dev, &mr->mmr);
-
err_free:
kfree(mr);
return ERR_PTR(err);
}
-struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
- int page_list_len)
-{
- struct mlx4_ib_dev *dev = to_mdev(ibdev);
- struct mlx4_ib_fast_reg_page_list *mfrpl;
- int size = page_list_len * sizeof (u64);
-
- if (page_list_len > MLX4_MAX_FAST_REG_PAGES)
- return ERR_PTR(-EINVAL);
-
- mfrpl = kmalloc(sizeof *mfrpl, GFP_KERNEL);
- if (!mfrpl)
- return ERR_PTR(-ENOMEM);
-
- mfrpl->ibfrpl.page_list = kmalloc(size, GFP_KERNEL);
- if (!mfrpl->ibfrpl.page_list)
- goto err_free;
-
- mfrpl->mapped_page_list = dma_alloc_coherent(&dev->dev->persist->
- pdev->dev,
- size, &mfrpl->map,
- GFP_KERNEL);
- if (!mfrpl->mapped_page_list)
- goto err_free;
-
- WARN_ON(mfrpl->map & 0x3f);
-
- return &mfrpl->ibfrpl;
-
-err_free:
- kfree(mfrpl->ibfrpl.page_list);
- kfree(mfrpl);
- return ERR_PTR(-ENOMEM);
-}
-
-void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
-{
- struct mlx4_ib_dev *dev = to_mdev(page_list->device);
- struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
- int size = page_list->max_page_list_len * sizeof (u64);
-
- dma_free_coherent(&dev->dev->persist->pdev->dev, size,
- mfrpl->mapped_page_list,
- mfrpl->map);
- kfree(mfrpl->ibfrpl.page_list);
- kfree(mfrpl);
-}
-
struct ib_fmr *mlx4_ib_fmr_alloc(struct ib_pd *pd, int acc,
struct ib_fmr_attr *fmr_attr)
{
@@ -528,3 +535,37 @@ int mlx4_ib_fmr_dealloc(struct ib_fmr *ibfmr)
return err;
}
+
+static int mlx4_set_page(struct ib_mr *ibmr, u64 addr)
+{
+ struct mlx4_ib_mr *mr = to_mmr(ibmr);
+
+ if (unlikely(mr->npages == mr->max_pages))
+ return -ENOMEM;
+
+ mr->pages[mr->npages++] = cpu_to_be64(addr | MLX4_MTT_FLAG_PRESENT);
+
+ return 0;
+}
+
+int mlx4_ib_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
+{
+ struct mlx4_ib_mr *mr = to_mmr(ibmr);
+ int rc;
+
+ mr->npages = 0;
+
+ ib_dma_sync_single_for_cpu(ibmr->device, mr->page_map,
+ sizeof(u64) * mr->max_pages,
+ DMA_TO_DEVICE);
+
+ rc = ib_sg_to_pages(ibmr, sg, sg_nents, mlx4_set_page);
+
+ ib_dma_sync_single_for_device(ibmr->device, mr->page_map,
+ sizeof(u64) * mr->max_pages,
+ DMA_TO_DEVICE);
+
+ return rc;
+}
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 4ad9be3ad61c..a2e4ca56da44 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -111,7 +111,7 @@ static const __be32 mlx4_ib_opcode[] = {
[IB_WR_ATOMIC_FETCH_AND_ADD] = cpu_to_be32(MLX4_OPCODE_ATOMIC_FA),
[IB_WR_SEND_WITH_INV] = cpu_to_be32(MLX4_OPCODE_SEND_INVAL),
[IB_WR_LOCAL_INV] = cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL),
- [IB_WR_FAST_REG_MR] = cpu_to_be32(MLX4_OPCODE_FMR),
+ [IB_WR_REG_MR] = cpu_to_be32(MLX4_OPCODE_FMR),
[IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = cpu_to_be32(MLX4_OPCODE_MASKED_ATOMIC_CS),
[IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = cpu_to_be32(MLX4_OPCODE_MASKED_ATOMIC_FA),
[IB_WR_BIND_MW] = cpu_to_be32(MLX4_OPCODE_BIND_MW),
@@ -617,6 +617,18 @@ static int qp0_enabled_vf(struct mlx4_dev *dev, int qpn)
return 0;
}
+static void mlx4_ib_free_qp_counter(struct mlx4_ib_dev *dev,
+ struct mlx4_ib_qp *qp)
+{
+ mutex_lock(&dev->counters_table[qp->port - 1].mutex);
+ mlx4_counter_free(dev->dev, qp->counter_index->index);
+ list_del(&qp->counter_index->list);
+ mutex_unlock(&dev->counters_table[qp->port - 1].mutex);
+
+ kfree(qp->counter_index);
+ qp->counter_index = NULL;
+}
+
static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp **caller_qp,
@@ -746,9 +758,6 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
} else {
qp->sq_no_prefetch = 0;
- if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
- qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
-
if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
qp->flags |= MLX4_IB_QP_LSO;
@@ -822,6 +831,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
goto err_proxy;
}
+ if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
+ qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
+
err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp, gfp);
if (err)
goto err_qpn;
@@ -1086,6 +1098,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
{
struct mlx4_ib_qp *qp = NULL;
int err;
+ int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
u16 xrcdn = 0;
gfp_t gfp;
@@ -1109,8 +1122,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
}
if (init_attr->create_flags &&
- (udata ||
- ((init_attr->create_flags & ~(MLX4_IB_SRIOV_SQP | MLX4_IB_QP_CREATE_USE_GFP_NOIO)) &&
+ ((udata && init_attr->create_flags & ~(sup_u_create_flags)) ||
+ ((init_attr->create_flags & ~(MLX4_IB_SRIOV_SQP |
+ MLX4_IB_QP_CREATE_USE_GFP_NOIO |
+ MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK)) &&
init_attr->qp_type != IB_QPT_UD) ||
((init_attr->create_flags & MLX4_IB_SRIOV_SQP) &&
init_attr->qp_type > IB_QPT_GSI)))
@@ -1189,6 +1204,9 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
mutex_unlock(&dev->qp1_proxy_lock[mqp->port - 1]);
}
+ if (mqp->counter_index)
+ mlx4_ib_free_qp_counter(dev, mqp);
+
pd = get_pd(mqp);
destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
@@ -1391,11 +1409,12 @@ static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_qp_attr *qp,
enum ib_qp_attr_mask qp_attr_mask,
struct mlx4_ib_qp *mqp,
- struct mlx4_qp_path *path, u8 port)
+ struct mlx4_qp_path *path, u8 port,
+ u16 vlan_id, u8 *smac)
{
return _mlx4_set_path(dev, &qp->ah_attr,
- mlx4_mac_to_u64((u8 *)qp->smac),
- (qp_attr_mask & IB_QP_VID) ? qp->vlan_id : 0xffff,
+ mlx4_mac_to_u64(smac),
+ vlan_id,
path, &mqp->pri, port);
}
@@ -1406,9 +1425,8 @@ static int mlx4_set_alt_path(struct mlx4_ib_dev *dev,
struct mlx4_qp_path *path, u8 port)
{
return _mlx4_set_path(dev, &qp->alt_ah_attr,
- mlx4_mac_to_u64((u8 *)qp->alt_smac),
- (qp_attr_mask & IB_QP_ALT_VID) ?
- qp->alt_vlan_id : 0xffff,
+ 0,
+ 0xffff,
path, &mqp->alt, port);
}
@@ -1424,7 +1442,8 @@ static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
}
}
-static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac,
+static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev,
+ struct mlx4_ib_qp *qp,
struct mlx4_qp_context *context)
{
u64 u64_mac;
@@ -1447,6 +1466,40 @@ static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *
return 0;
}
+static int create_qp_lb_counter(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
+{
+ struct counter_index *new_counter_index;
+ int err;
+ u32 tmp_idx;
+
+ if (rdma_port_get_link_layer(&dev->ib_dev, qp->port) !=
+ IB_LINK_LAYER_ETHERNET ||
+ !(qp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK) ||
+ !(dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK))
+ return 0;
+
+ err = mlx4_counter_alloc(dev->dev, &tmp_idx);
+ if (err)
+ return err;
+
+ new_counter_index = kmalloc(sizeof(*new_counter_index), GFP_KERNEL);
+ if (!new_counter_index) {
+ mlx4_counter_free(dev->dev, tmp_idx);
+ return -ENOMEM;
+ }
+
+ new_counter_index->index = tmp_idx;
+ new_counter_index->allocated = 1;
+ qp->counter_index = new_counter_index;
+
+ mutex_lock(&dev->counters_table[qp->port - 1].mutex);
+ list_add_tail(&new_counter_index->list,
+ &dev->counters_table[qp->port - 1].counters_list);
+ mutex_unlock(&dev->counters_table[qp->port - 1].mutex);
+
+ return 0;
+}
+
static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
const struct ib_qp_attr *attr, int attr_mask,
enum ib_qp_state cur_state, enum ib_qp_state new_state)
@@ -1460,6 +1513,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
int sqd_event;
int steer_qp = 0;
int err = -EINVAL;
+ int counter_index;
/* APM is not supported under RoCE */
if (attr_mask & IB_QP_ALT_PATH &&
@@ -1519,6 +1573,9 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
context->sq_size_stride |= qp->sq.wqe_shift - 4;
+ if (new_state == IB_QPS_RESET && qp->counter_index)
+ mlx4_ib_free_qp_counter(dev, qp);
+
if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
context->xrcd = cpu_to_be32((u32) qp->xrcdn);
@@ -1543,10 +1600,24 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
- if (dev->counters[qp->port - 1].index != -1) {
- context->pri_path.counter_index =
- dev->counters[qp->port - 1].index;
+ err = create_qp_lb_counter(dev, qp);
+ if (err)
+ goto out;
+
+ counter_index =
+ dev->counters_table[qp->port - 1].default_counter;
+ if (qp->counter_index)
+ counter_index = qp->counter_index->index;
+
+ if (counter_index != -1) {
+ context->pri_path.counter_index = counter_index;
optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX;
+ if (qp->counter_index) {
+ context->pri_path.fl |=
+ MLX4_FL_ETH_SRC_CHECK_MC_LB;
+ context->pri_path.vlan_control |=
+ MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
+ }
} else
context->pri_path.counter_index =
MLX4_SINK_COUNTER_INDEX(dev->dev);
@@ -1565,9 +1636,33 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
if (attr_mask & IB_QP_AV) {
+ u8 port_num = mlx4_is_bonded(to_mdev(ibqp->device)->dev) ? 1 :
+ attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
+ union ib_gid gid;
+ struct ib_gid_attr gid_attr;
+ u16 vlan = 0xffff;
+ u8 smac[ETH_ALEN];
+ int status = 0;
+
+ if (rdma_cap_eth_ah(&dev->ib_dev, port_num) &&
+ attr->ah_attr.ah_flags & IB_AH_GRH) {
+ int index = attr->ah_attr.grh.sgid_index;
+
+ status = ib_get_cached_gid(ibqp->device, port_num,
+ index, &gid, &gid_attr);
+ if (!status && !memcmp(&gid, &zgid, sizeof(gid)))
+ status = -ENOENT;
+ if (!status && gid_attr.ndev) {
+ vlan = rdma_vlan_dev_vlan_id(gid_attr.ndev);
+ memcpy(smac, gid_attr.ndev->dev_addr, ETH_ALEN);
+ dev_put(gid_attr.ndev);
+ }
+ }
+ if (status)
+ goto out;
+
if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
- attr_mask & IB_QP_PORT ?
- attr->port_num : qp->port))
+ port_num, vlan, smac))
goto out;
optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH |
@@ -1704,7 +1799,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_UD ||
qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI ||
qp->mlx4_ib_qp_type == MLX4_IB_QPT_TUN_GSI) {
- err = handle_eth_ud_smac_index(dev, qp, (u8 *)attr->smac, context);
+ err = handle_eth_ud_smac_index(dev, qp, context);
if (err) {
err = -EINVAL;
goto out;
@@ -1848,6 +1943,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
}
out:
+ if (err && qp->counter_index)
+ mlx4_ib_free_qp_counter(dev, qp);
if (err && steer_qp)
mlx4_ib_steer_qp_reg(dev, qp, 0);
kfree(context);
@@ -2036,14 +2133,14 @@ static int vf_get_qp0_qkey(struct mlx4_dev *dev, int qpn, u32 *qkey)
}
static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
- struct ib_send_wr *wr,
+ struct ib_ud_wr *wr,
void *wqe, unsigned *mlx_seg_len)
{
struct mlx4_ib_dev *mdev = to_mdev(sqp->qp.ibqp.device);
struct ib_device *ib_dev = &mdev->ib_dev;
struct mlx4_wqe_mlx_seg *mlx = wqe;
struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
- struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+ struct mlx4_ib_ah *ah = to_mah(wr->ah);
u16 pkey;
u32 qkey;
int send_size;
@@ -2051,13 +2148,13 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
int spc;
int i;
- if (wr->opcode != IB_WR_SEND)
+ if (wr->wr.opcode != IB_WR_SEND)
return -EINVAL;
send_size = 0;
- for (i = 0; i < wr->num_sge; ++i)
- send_size += wr->sg_list[i].length;
+ for (i = 0; i < wr->wr.num_sge; ++i)
+ send_size += wr->wr.sg_list[i].length;
/* for proxy-qp0 sends, need to add in size of tunnel header */
/* for tunnel-qp0 sends, tunnel header is already in s/g list */
@@ -2082,11 +2179,11 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
mlx->rlid = sqp->ud_header.lrh.destination_lid;
sqp->ud_header.lrh.virtual_lane = 0;
- sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+ sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_TUN_SMI_OWNER)
- sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+ sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
else
sqp->ud_header.bth.destination_qpn =
cpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]);
@@ -2158,14 +2255,14 @@ static void mlx4_u64_to_smac(u8 *dst_mac, u64 src_mac)
}
}
-static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_ud_wr *wr,
void *wqe, unsigned *mlx_seg_len)
{
struct ib_device *ib_dev = sqp->qp.ibqp.device;
struct mlx4_wqe_mlx_seg *mlx = wqe;
struct mlx4_wqe_ctrl_seg *ctrl = wqe;
struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
- struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+ struct mlx4_ib_ah *ah = to_mah(wr->ah);
union ib_gid sgid;
u16 pkey;
int send_size;
@@ -2179,8 +2276,8 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
bool is_grh;
send_size = 0;
- for (i = 0; i < wr->num_sge; ++i)
- send_size += wr->sg_list[i].length;
+ for (i = 0; i < wr->wr.num_sge; ++i)
+ send_size += wr->wr.sg_list[i].length;
is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET;
is_grh = mlx4_ib_ah_grh_present(ah);
@@ -2197,7 +2294,10 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
} else {
err = ib_get_cached_gid(ib_dev,
be32_to_cpu(ah->av.ib.port_pd) >> 24,
- ah->av.ib.gid_index, &sgid);
+ ah->av.ib.gid_index, &sgid,
+ NULL);
+ if (!err && !memcmp(&sgid, &zgid, sizeof(sgid)))
+ err = -ENOENT;
if (err)
return err;
}
@@ -2239,7 +2339,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
ib_get_cached_gid(ib_dev,
be32_to_cpu(ah->av.ib.port_pd) >> 24,
ah->av.ib.gid_index,
- &sqp->ud_header.grh.source_gid);
+ &sqp->ud_header.grh.source_gid, NULL);
}
memcpy(sqp->ud_header.grh.destination_gid.raw,
ah->av.ib.dgid, 16);
@@ -2257,7 +2357,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
mlx->rlid = sqp->ud_header.lrh.destination_lid;
}
- switch (wr->opcode) {
+ switch (wr->wr.opcode) {
case IB_WR_SEND:
sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY;
sqp->ud_header.immediate_present = 0;
@@ -2265,7 +2365,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
case IB_WR_SEND_WITH_IMM:
sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
sqp->ud_header.immediate_present = 1;
- sqp->ud_header.immediate_data = wr->ex.imm_data;
+ sqp->ud_header.immediate_data = wr->wr.ex.imm_data;
break;
default:
return -EINVAL;
@@ -2308,16 +2408,16 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
}
- sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+ sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
if (!sqp->qp.ibqp.qp_num)
ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey);
else
- ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->wr.ud.pkey_index, &pkey);
+ ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->pkey_index, &pkey);
sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
- sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+ sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
- sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ?
- sqp->qkey : wr->wr.ud.remote_qkey);
+ sqp->ud_header.deth.qkey = cpu_to_be32(wr->remote_qkey & 0x80000000 ?
+ sqp->qkey : wr->remote_qkey);
sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.ibqp.qp_num);
header_size = ib_ud_header_pack(&sqp->ud_header, sqp->header_buf);
@@ -2405,43 +2505,39 @@ static __be32 convert_access(int acc)
cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
}
-static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
+static void set_reg_seg(struct mlx4_wqe_fmr_seg *fseg,
+ struct ib_reg_wr *wr)
{
- struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
- int i;
-
- for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i)
- mfrpl->mapped_page_list[i] =
- cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] |
- MLX4_MTT_FLAG_PRESENT);
+ struct mlx4_ib_mr *mr = to_mmr(wr->mr);
- fseg->flags = convert_access(wr->wr.fast_reg.access_flags);
- fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey);
- fseg->buf_list = cpu_to_be64(mfrpl->map);
- fseg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start);
- fseg->reg_len = cpu_to_be64(wr->wr.fast_reg.length);
+ fseg->flags = convert_access(wr->access);
+ fseg->mem_key = cpu_to_be32(wr->key);
+ fseg->buf_list = cpu_to_be64(mr->page_map);
+ fseg->start_addr = cpu_to_be64(mr->ibmr.iova);
+ fseg->reg_len = cpu_to_be64(mr->ibmr.length);
fseg->offset = 0; /* XXX -- is this just for ZBVA? */
- fseg->page_size = cpu_to_be32(wr->wr.fast_reg.page_shift);
+ fseg->page_size = cpu_to_be32(ilog2(mr->ibmr.page_size));
fseg->reserved[0] = 0;
fseg->reserved[1] = 0;
}
-static void set_bind_seg(struct mlx4_wqe_bind_seg *bseg, struct ib_send_wr *wr)
+static void set_bind_seg(struct mlx4_wqe_bind_seg *bseg,
+ struct ib_bind_mw_wr *wr)
{
bseg->flags1 =
- convert_access(wr->wr.bind_mw.bind_info.mw_access_flags) &
+ convert_access(wr->bind_info.mw_access_flags) &
cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ |
MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE |
MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC);
bseg->flags2 = 0;
- if (wr->wr.bind_mw.mw->type == IB_MW_TYPE_2)
+ if (wr->mw->type == IB_MW_TYPE_2)
bseg->flags2 |= cpu_to_be32(MLX4_WQE_BIND_TYPE_2);
- if (wr->wr.bind_mw.bind_info.mw_access_flags & IB_ZERO_BASED)
+ if (wr->bind_info.mw_access_flags & IB_ZERO_BASED)
bseg->flags2 |= cpu_to_be32(MLX4_WQE_BIND_ZERO_BASED);
- bseg->new_rkey = cpu_to_be32(wr->wr.bind_mw.rkey);
- bseg->lkey = cpu_to_be32(wr->wr.bind_mw.bind_info.mr->lkey);
- bseg->addr = cpu_to_be64(wr->wr.bind_mw.bind_info.addr);
- bseg->length = cpu_to_be64(wr->wr.bind_mw.bind_info.length);
+ bseg->new_rkey = cpu_to_be32(wr->rkey);
+ bseg->lkey = cpu_to_be32(wr->bind_info.mr->lkey);
+ bseg->addr = cpu_to_be64(wr->bind_info.addr);
+ bseg->length = cpu_to_be64(wr->bind_info.length);
}
static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
@@ -2458,46 +2554,47 @@ static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg,
rseg->reserved = 0;
}
-static void set_atomic_seg(struct mlx4_wqe_atomic_seg *aseg, struct ib_send_wr *wr)
+static void set_atomic_seg(struct mlx4_wqe_atomic_seg *aseg,
+ struct ib_atomic_wr *wr)
{
- if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
- aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
- aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add);
- } else if (wr->opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
- aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
- aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add_mask);
+ if (wr->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
+ aseg->swap_add = cpu_to_be64(wr->swap);
+ aseg->compare = cpu_to_be64(wr->compare_add);
+ } else if (wr->wr.opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
+ aseg->swap_add = cpu_to_be64(wr->compare_add);
+ aseg->compare = cpu_to_be64(wr->compare_add_mask);
} else {
- aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
+ aseg->swap_add = cpu_to_be64(wr->compare_add);
aseg->compare = 0;
}
}
static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
- struct ib_send_wr *wr)
+ struct ib_atomic_wr *wr)
{
- aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
- aseg->swap_add_mask = cpu_to_be64(wr->wr.atomic.swap_mask);
- aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add);
- aseg->compare_mask = cpu_to_be64(wr->wr.atomic.compare_add_mask);
+ aseg->swap_add = cpu_to_be64(wr->swap);
+ aseg->swap_add_mask = cpu_to_be64(wr->swap_mask);
+ aseg->compare = cpu_to_be64(wr->compare_add);
+ aseg->compare_mask = cpu_to_be64(wr->compare_add_mask);
}
static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
- struct ib_send_wr *wr)
+ struct ib_ud_wr *wr)
{
- memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
- dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
- dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
- dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
- memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
+ memcpy(dseg->av, &to_mah(wr->ah)->av, sizeof (struct mlx4_av));
+ dseg->dqpn = cpu_to_be32(wr->remote_qpn);
+ dseg->qkey = cpu_to_be32(wr->remote_qkey);
+ dseg->vlan = to_mah(wr->ah)->av.eth.vlan;
+ memcpy(dseg->mac, to_mah(wr->ah)->av.eth.mac, 6);
}
static void set_tunnel_datagram_seg(struct mlx4_ib_dev *dev,
struct mlx4_wqe_datagram_seg *dseg,
- struct ib_send_wr *wr,
+ struct ib_ud_wr *wr,
enum mlx4_ib_qp_type qpt)
{
- union mlx4_ext_av *av = &to_mah(wr->wr.ud.ah)->av;
+ union mlx4_ext_av *av = &to_mah(wr->ah)->av;
struct mlx4_av sqp_av = {0};
int port = *((u8 *) &av->ib.port_pd) & 0x3;
@@ -2516,18 +2613,18 @@ static void set_tunnel_datagram_seg(struct mlx4_ib_dev *dev,
dseg->qkey = cpu_to_be32(IB_QP_SET_QKEY);
}
-static void build_tunnel_header(struct ib_send_wr *wr, void *wqe, unsigned *mlx_seg_len)
+static void build_tunnel_header(struct ib_ud_wr *wr, void *wqe, unsigned *mlx_seg_len)
{
struct mlx4_wqe_inline_seg *inl = wqe;
struct mlx4_ib_tunnel_header hdr;
- struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+ struct mlx4_ib_ah *ah = to_mah(wr->ah);
int spc;
int i;
memcpy(&hdr.av, &ah->av, sizeof hdr.av);
- hdr.remote_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
- hdr.pkey_index = cpu_to_be16(wr->wr.ud.pkey_index);
- hdr.qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+ hdr.remote_qpn = cpu_to_be32(wr->remote_qpn);
+ hdr.pkey_index = cpu_to_be16(wr->pkey_index);
+ hdr.qkey = cpu_to_be32(wr->remote_qkey);
memcpy(hdr.mac, ah->av.eth.mac, 6);
hdr.vlan = ah->av.eth.vlan;
@@ -2599,22 +2696,22 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
dseg->addr = cpu_to_be64(sg->addr);
}
-static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
+static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_ud_wr *wr,
struct mlx4_ib_qp *qp, unsigned *lso_seg_len,
__be32 *lso_hdr_sz, __be32 *blh)
{
- unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
+ unsigned halign = ALIGN(sizeof *wqe + wr->hlen, 16);
if (unlikely(halign > MLX4_IB_CACHE_LINE_SIZE))
*blh = cpu_to_be32(1 << 6);
if (unlikely(!(qp->flags & MLX4_IB_QP_LSO) &&
- wr->num_sge > qp->sq.max_gs - (halign >> 4)))
+ wr->wr.num_sge > qp->sq.max_gs - (halign >> 4)))
return -EINVAL;
- memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
+ memcpy(wqe->header, wr->header, wr->hlen);
- *lso_hdr_sz = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
+ *lso_hdr_sz = cpu_to_be32(wr->mss << 16 | wr->hlen);
*lso_seg_len = halign;
return 0;
}
@@ -2713,11 +2810,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_ATOMIC_CMP_AND_SWP:
case IB_WR_ATOMIC_FETCH_AND_ADD:
case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
- set_raddr_seg(wqe, wr->wr.atomic.remote_addr,
- wr->wr.atomic.rkey);
+ set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
+ atomic_wr(wr)->rkey);
wqe += sizeof (struct mlx4_wqe_raddr_seg);
- set_atomic_seg(wqe, wr);
+ set_atomic_seg(wqe, atomic_wr(wr));
wqe += sizeof (struct mlx4_wqe_atomic_seg);
size += (sizeof (struct mlx4_wqe_raddr_seg) +
@@ -2726,11 +2823,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
- set_raddr_seg(wqe, wr->wr.atomic.remote_addr,
- wr->wr.atomic.rkey);
+ set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
+ atomic_wr(wr)->rkey);
wqe += sizeof (struct mlx4_wqe_raddr_seg);
- set_masked_atomic_seg(wqe, wr);
+ set_masked_atomic_seg(wqe, atomic_wr(wr));
wqe += sizeof (struct mlx4_wqe_masked_atomic_seg);
size += (sizeof (struct mlx4_wqe_raddr_seg) +
@@ -2741,8 +2838,8 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_RDMA_READ:
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
- set_raddr_seg(wqe, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
wqe += sizeof (struct mlx4_wqe_raddr_seg);
size += sizeof (struct mlx4_wqe_raddr_seg) / 16;
break;
@@ -2755,18 +2852,18 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
size += sizeof (struct mlx4_wqe_local_inval_seg) / 16;
break;
- case IB_WR_FAST_REG_MR:
+ case IB_WR_REG_MR:
ctrl->srcrb_flags |=
cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER);
- set_fmr_seg(wqe, wr);
- wqe += sizeof (struct mlx4_wqe_fmr_seg);
- size += sizeof (struct mlx4_wqe_fmr_seg) / 16;
+ set_reg_seg(wqe, reg_wr(wr));
+ wqe += sizeof(struct mlx4_wqe_fmr_seg);
+ size += sizeof(struct mlx4_wqe_fmr_seg) / 16;
break;
case IB_WR_BIND_MW:
ctrl->srcrb_flags |=
cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER);
- set_bind_seg(wqe, wr);
+ set_bind_seg(wqe, bind_mw_wr(wr));
wqe += sizeof(struct mlx4_wqe_bind_seg);
size += sizeof(struct mlx4_wqe_bind_seg) / 16;
break;
@@ -2777,7 +2874,8 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case MLX4_IB_QPT_TUN_SMI_OWNER:
- err = build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
+ err = build_sriov_qp0_header(to_msqp(qp), ud_wr(wr),
+ ctrl, &seglen);
if (unlikely(err)) {
*bad_wr = wr;
goto out;
@@ -2788,19 +2886,20 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case MLX4_IB_QPT_TUN_SMI:
case MLX4_IB_QPT_TUN_GSI:
/* this is a UD qp used in MAD responses to slaves. */
- set_datagram_seg(wqe, wr);
+ set_datagram_seg(wqe, ud_wr(wr));
/* set the forced-loopback bit in the data seg av */
*(__be32 *) wqe |= cpu_to_be32(0x80000000);
wqe += sizeof (struct mlx4_wqe_datagram_seg);
size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
break;
case MLX4_IB_QPT_UD:
- set_datagram_seg(wqe, wr);
+ set_datagram_seg(wqe, ud_wr(wr));
wqe += sizeof (struct mlx4_wqe_datagram_seg);
size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
if (wr->opcode == IB_WR_LSO) {
- err = build_lso_seg(wqe, wr, qp, &seglen, &lso_hdr_sz, &blh);
+ err = build_lso_seg(wqe, ud_wr(wr), qp, &seglen,
+ &lso_hdr_sz, &blh);
if (unlikely(err)) {
*bad_wr = wr;
goto out;
@@ -2812,7 +2911,8 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case MLX4_IB_QPT_PROXY_SMI_OWNER:
- err = build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
+ err = build_sriov_qp0_header(to_msqp(qp), ud_wr(wr),
+ ctrl, &seglen);
if (unlikely(err)) {
*bad_wr = wr;
goto out;
@@ -2823,7 +2923,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
add_zero_len_inline(wqe);
wqe += 16;
size++;
- build_tunnel_header(wr, wqe, &seglen);
+ build_tunnel_header(ud_wr(wr), wqe, &seglen);
wqe += seglen;
size += seglen / 16;
break;
@@ -2833,18 +2933,20 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
* In this case we first add a UD segment targeting
* the tunnel qp, and then add a header with address
* information */
- set_tunnel_datagram_seg(to_mdev(ibqp->device), wqe, wr,
+ set_tunnel_datagram_seg(to_mdev(ibqp->device), wqe,
+ ud_wr(wr),
qp->mlx4_ib_qp_type);
wqe += sizeof (struct mlx4_wqe_datagram_seg);
size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
- build_tunnel_header(wr, wqe, &seglen);
+ build_tunnel_header(ud_wr(wr), wqe, &seglen);
wqe += seglen;
size += seglen / 16;
break;
case MLX4_IB_QPT_SMI:
case MLX4_IB_QPT_GSI:
- err = build_mlx_header(to_msqp(qp), wr, ctrl, &seglen);
+ err = build_mlx_header(to_msqp(qp), ud_wr(wr), ctrl,
+ &seglen);
if (unlikely(err)) {
*bad_wr = wr;
goto out;
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
index 2d0dbbf38ceb..3dfd287256d6 100644
--- a/drivers/infiniband/hw/mlx5/cq.c
+++ b/drivers/infiniband/hw/mlx5/cq.c
@@ -109,8 +109,8 @@ static enum ib_wc_opcode get_umr_comp(struct mlx5_ib_wq *wq, int idx)
case IB_WR_LOCAL_INV:
return IB_WC_LOCAL_INV;
- case IB_WR_FAST_REG_MR:
- return IB_WC_FAST_REG_MR;
+ case IB_WR_REG_MR:
+ return IB_WC_REG_MR;
default:
pr_warn("unknown completion status\n");
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index f1ccd40beae9..7e97cb55a6bf 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -30,7 +30,7 @@
* SOFTWARE.
*/
-#include <asm-generic/kmap_types.h>
+#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -1425,8 +1425,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach;
dev->ib_dev.process_mad = mlx5_ib_process_mad;
dev->ib_dev.alloc_mr = mlx5_ib_alloc_mr;
- dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list;
- dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list;
+ dev->ib_dev.map_mr_sg = mlx5_ib_map_mr_sg;
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
dev->ib_dev.get_port_immutable = mlx5_port_immutable;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 22123b79d550..633347260b79 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -245,6 +245,7 @@ enum mlx5_ib_qp_flags {
};
struct mlx5_umr_wr {
+ struct ib_send_wr wr;
union {
u64 virt_addr;
u64 offset;
@@ -257,6 +258,11 @@ struct mlx5_umr_wr {
u32 mkey;
};
+static inline struct mlx5_umr_wr *umr_wr(struct ib_send_wr *wr)
+{
+ return container_of(wr, struct mlx5_umr_wr, wr);
+}
+
struct mlx5_shared_mr_info {
int mr_id;
struct ib_umem *umem;
@@ -313,6 +319,11 @@ enum mlx5_ib_mtt_access_flags {
struct mlx5_ib_mr {
struct ib_mr ibmr;
+ void *descs;
+ dma_addr_t desc_map;
+ int ndescs;
+ int max_descs;
+ int desc_size;
struct mlx5_core_mr mmr;
struct ib_umem *umem;
struct mlx5_shared_mr_info *smr_info;
@@ -324,12 +335,7 @@ struct mlx5_ib_mr {
struct mlx5_create_mkey_mbox_out out;
struct mlx5_core_sig_ctx *sig;
int live;
-};
-
-struct mlx5_ib_fast_reg_page_list {
- struct ib_fast_reg_page_list ibfrpl;
- __be64 *mapped_page_list;
- dma_addr_t map;
+ void *descs_alloc;
};
struct mlx5_ib_umr_context {
@@ -358,20 +364,6 @@ enum {
MLX5_FMR_BUSY,
};
-struct mlx5_ib_fmr {
- struct ib_fmr ibfmr;
- struct mlx5_core_mr mr;
- int access_flags;
- int state;
- /* protect fmr state
- */
- spinlock_t lock;
- u64 wrid;
- struct ib_send_wr wr[2];
- u8 page_shift;
- struct ib_fast_reg_page_list page_list;
-};
-
struct mlx5_cache_ent {
struct list_head head;
/* sync access to the cahce entry
@@ -456,11 +448,6 @@ static inline struct mlx5_ib_dev *to_mdev(struct ib_device *ibdev)
return container_of(ibdev, struct mlx5_ib_dev, ib_dev);
}
-static inline struct mlx5_ib_fmr *to_mfmr(struct ib_fmr *ibfmr)
-{
- return container_of(ibfmr, struct mlx5_ib_fmr, ibfmr);
-}
-
static inline struct mlx5_ib_cq *to_mcq(struct ib_cq *ibcq)
{
return container_of(ibcq, struct mlx5_ib_cq, ibcq);
@@ -501,11 +488,6 @@ static inline struct mlx5_ib_mr *to_mmr(struct ib_mr *ibmr)
return container_of(ibmr, struct mlx5_ib_mr, ibmr);
}
-static inline struct mlx5_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_page_list *ibfrpl)
-{
- return container_of(ibfrpl, struct mlx5_ib_fast_reg_page_list, ibfrpl);
-}
-
struct mlx5_ib_ah {
struct ib_ah ibah;
struct mlx5_av av;
@@ -573,15 +555,9 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr);
struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_num_sg);
-struct ib_fast_reg_page_list *mlx5_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
- int page_list_len);
-void mlx5_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list);
-struct ib_fmr *mlx5_ib_fmr_alloc(struct ib_pd *pd, int acc,
- struct ib_fmr_attr *fmr_attr);
-int mlx5_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
- int npages, u64 iova);
-int mlx5_ib_unmap_fmr(struct list_head *fmr_list);
-int mlx5_ib_fmr_dealloc(struct ib_fmr *ibfmr);
+int mlx5_ib_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents);
int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
const struct ib_wc *in_wc, const struct ib_grh *in_grh,
const struct ib_mad_hdr *in, size_t in_mad_size,
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 54a15b5d336d..ec8993a7b3be 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -687,7 +687,7 @@ static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr,
int access_flags)
{
struct mlx5_ib_dev *dev = to_mdev(pd->device);
- struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
+ struct mlx5_umr_wr *umrwr = umr_wr(wr);
sg->addr = dma;
sg->length = ALIGN(sizeof(u64) * n, 64);
@@ -715,7 +715,7 @@ static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr,
static void prep_umr_unreg_wqe(struct mlx5_ib_dev *dev,
struct ib_send_wr *wr, u32 key)
{
- struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
+ struct mlx5_umr_wr *umrwr = umr_wr(wr);
wr->send_flags = MLX5_IB_SEND_UMR_UNREG | MLX5_IB_SEND_UMR_FAIL_IF_FREE;
wr->opcode = MLX5_IB_WR_UMR;
@@ -752,7 +752,8 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
struct device *ddev = dev->ib_dev.dma_device;
struct umr_common *umrc = &dev->umrc;
struct mlx5_ib_umr_context umr_context;
- struct ib_send_wr wr, *bad;
+ struct mlx5_umr_wr umrwr;
+ struct ib_send_wr *bad;
struct mlx5_ib_mr *mr;
struct ib_sge sg;
int size;
@@ -798,14 +799,14 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
goto free_pas;
}
- memset(&wr, 0, sizeof(wr));
- wr.wr_id = (u64)(unsigned long)&umr_context;
- prep_umr_reg_wqe(pd, &wr, &sg, dma, npages, mr->mmr.key, page_shift,
- virt_addr, len, access_flags);
+ memset(&umrwr, 0, sizeof(umrwr));
+ umrwr.wr.wr_id = (u64)(unsigned long)&umr_context;
+ prep_umr_reg_wqe(pd, &umrwr.wr, &sg, dma, npages, mr->mmr.key,
+ page_shift, virt_addr, len, access_flags);
mlx5_ib_init_umr_context(&umr_context);
down(&umrc->sem);
- err = ib_post_send(umrc->qp, &wr, &bad);
+ err = ib_post_send(umrc->qp, &umrwr.wr, &bad);
if (err) {
mlx5_ib_warn(dev, "post send failed, err %d\n", err);
goto unmap_dma;
@@ -851,8 +852,8 @@ int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index, int npages,
int size;
__be64 *pas;
dma_addr_t dma;
- struct ib_send_wr wr, *bad;
- struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr.wr.fast_reg;
+ struct ib_send_wr *bad;
+ struct mlx5_umr_wr wr;
struct ib_sge sg;
int err = 0;
const int page_index_alignment = MLX5_UMR_MTT_ALIGNMENT / sizeof(u64);
@@ -917,26 +918,26 @@ int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index, int npages,
dma_sync_single_for_device(ddev, dma, size, DMA_TO_DEVICE);
memset(&wr, 0, sizeof(wr));
- wr.wr_id = (u64)(unsigned long)&umr_context;
+ wr.wr.wr_id = (u64)(unsigned long)&umr_context;
sg.addr = dma;
sg.length = ALIGN(npages * sizeof(u64),
MLX5_UMR_MTT_ALIGNMENT);
sg.lkey = dev->umrc.pd->local_dma_lkey;
- wr.send_flags = MLX5_IB_SEND_UMR_FAIL_IF_FREE |
+ wr.wr.send_flags = MLX5_IB_SEND_UMR_FAIL_IF_FREE |
MLX5_IB_SEND_UMR_UPDATE_MTT;
- wr.sg_list = &sg;
- wr.num_sge = 1;
- wr.opcode = MLX5_IB_WR_UMR;
- umrwr->npages = sg.length / sizeof(u64);
- umrwr->page_shift = PAGE_SHIFT;
- umrwr->mkey = mr->mmr.key;
- umrwr->target.offset = start_page_index;
+ wr.wr.sg_list = &sg;
+ wr.wr.num_sge = 1;
+ wr.wr.opcode = MLX5_IB_WR_UMR;
+ wr.npages = sg.length / sizeof(u64);
+ wr.page_shift = PAGE_SHIFT;
+ wr.mkey = mr->mmr.key;
+ wr.target.offset = start_page_index;
mlx5_ib_init_umr_context(&umr_context);
down(&umrc->sem);
- err = ib_post_send(umrc->qp, &wr, &bad);
+ err = ib_post_send(umrc->qp, &wr.wr, &bad);
if (err) {
mlx5_ib_err(dev, "UMR post send failed, err %d\n", err);
} else {
@@ -1122,16 +1123,17 @@ static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
{
struct umr_common *umrc = &dev->umrc;
struct mlx5_ib_umr_context umr_context;
- struct ib_send_wr wr, *bad;
+ struct mlx5_umr_wr umrwr;
+ struct ib_send_wr *bad;
int err;
- memset(&wr, 0, sizeof(wr));
- wr.wr_id = (u64)(unsigned long)&umr_context;
- prep_umr_unreg_wqe(dev, &wr, mr->mmr.key);
+ memset(&umrwr.wr, 0, sizeof(umrwr));
+ umrwr.wr.wr_id = (u64)(unsigned long)&umr_context;
+ prep_umr_unreg_wqe(dev, &umrwr.wr, mr->mmr.key);
mlx5_ib_init_umr_context(&umr_context);
down(&umrc->sem);
- err = ib_post_send(umrc->qp, &wr, &bad);
+ err = ib_post_send(umrc->qp, &umrwr.wr, &bad);
if (err) {
up(&umrc->sem);
mlx5_ib_dbg(dev, "err %d\n", err);
@@ -1151,6 +1153,52 @@ error:
return err;
}
+static int
+mlx5_alloc_priv_descs(struct ib_device *device,
+ struct mlx5_ib_mr *mr,
+ int ndescs,
+ int desc_size)
+{
+ int size = ndescs * desc_size;
+ int add_size;
+ int ret;
+
+ add_size = max_t(int, MLX5_UMR_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
+
+ mr->descs_alloc = kzalloc(size + add_size, GFP_KERNEL);
+ if (!mr->descs_alloc)
+ return -ENOMEM;
+
+ mr->descs = PTR_ALIGN(mr->descs_alloc, MLX5_UMR_ALIGN);
+
+ mr->desc_map = dma_map_single(device->dma_device, mr->descs,
+ size, DMA_TO_DEVICE);
+ if (dma_mapping_error(device->dma_device, mr->desc_map)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ return 0;
+err:
+ kfree(mr->descs_alloc);
+
+ return ret;
+}
+
+static void
+mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
+{
+ if (mr->descs) {
+ struct ib_device *device = mr->ibmr.device;
+ int size = mr->max_descs * mr->desc_size;
+
+ dma_unmap_single(device->dma_device, mr->desc_map,
+ size, DMA_TO_DEVICE);
+ kfree(mr->descs_alloc);
+ mr->descs = NULL;
+ }
+}
+
static int clean_mr(struct mlx5_ib_mr *mr)
{
struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
@@ -1170,6 +1218,8 @@ static int clean_mr(struct mlx5_ib_mr *mr)
mr->sig = NULL;
}
+ mlx5_free_priv_descs(mr);
+
if (!umred) {
err = destroy_mkey(dev, mr);
if (err) {
@@ -1259,6 +1309,14 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
if (mr_type == IB_MR_TYPE_MEM_REG) {
access_mode = MLX5_ACCESS_MODE_MTT;
in->seg.log2_page_size = PAGE_SHIFT;
+
+ err = mlx5_alloc_priv_descs(pd->device, mr,
+ ndescs, sizeof(u64));
+ if (err)
+ goto err_free_in;
+
+ mr->desc_size = sizeof(u64);
+ mr->max_descs = ndescs;
} else if (mr_type == IB_MR_TYPE_SIGNATURE) {
u32 psv_index[2];
@@ -1315,6 +1373,7 @@ err_destroy_psv:
mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
mr->sig->psv_wire.psv_idx);
}
+ mlx5_free_priv_descs(mr);
err_free_sig:
kfree(mr->sig);
err_free_in:
@@ -1324,48 +1383,6 @@ err_free:
return ERR_PTR(err);
}
-struct ib_fast_reg_page_list *mlx5_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
- int page_list_len)
-{
- struct mlx5_ib_fast_reg_page_list *mfrpl;
- int size = page_list_len * sizeof(u64);
-
- mfrpl = kmalloc(sizeof(*mfrpl), GFP_KERNEL);
- if (!mfrpl)
- return ERR_PTR(-ENOMEM);
-
- mfrpl->ibfrpl.page_list = kmalloc(size, GFP_KERNEL);
- if (!mfrpl->ibfrpl.page_list)
- goto err_free;
-
- mfrpl->mapped_page_list = dma_alloc_coherent(ibdev->dma_device,
- size, &mfrpl->map,
- GFP_KERNEL);
- if (!mfrpl->mapped_page_list)
- goto err_free;
-
- WARN_ON(mfrpl->map & 0x3f);
-
- return &mfrpl->ibfrpl;
-
-err_free:
- kfree(mfrpl->ibfrpl.page_list);
- kfree(mfrpl);
- return ERR_PTR(-ENOMEM);
-}
-
-void mlx5_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
-{
- struct mlx5_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
- struct mlx5_ib_dev *dev = to_mdev(page_list->device);
- int size = page_list->max_page_list_len * sizeof(u64);
-
- dma_free_coherent(&dev->mdev->pdev->dev, size, mfrpl->mapped_page_list,
- mfrpl->map);
- kfree(mfrpl->ibfrpl.page_list);
- kfree(mfrpl);
-}
-
int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
struct ib_mr_status *mr_status)
{
@@ -1406,3 +1423,39 @@ int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
done:
return ret;
}
+
+static int mlx5_set_page(struct ib_mr *ibmr, u64 addr)
+{
+ struct mlx5_ib_mr *mr = to_mmr(ibmr);
+ __be64 *descs;
+
+ if (unlikely(mr->ndescs == mr->max_descs))
+ return -ENOMEM;
+
+ descs = mr->descs;
+ descs[mr->ndescs++] = cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
+
+ return 0;
+}
+
+int mlx5_ib_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
+{
+ struct mlx5_ib_mr *mr = to_mmr(ibmr);
+ int n;
+
+ mr->ndescs = 0;
+
+ ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
+ mr->desc_size * mr->max_descs,
+ DMA_TO_DEVICE);
+
+ n = ib_sg_to_pages(ibmr, sg, sg_nents, mlx5_set_page);
+
+ ib_dma_sync_single_for_device(ibmr->device, mr->desc_map,
+ mr->desc_size * mr->max_descs,
+ DMA_TO_DEVICE);
+
+ return n;
+}
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 6f521a3418e8..307bdbca8938 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -64,7 +64,7 @@ static const u32 mlx5_ib_opcode[] = {
[IB_WR_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_FA,
[IB_WR_SEND_WITH_INV] = MLX5_OPCODE_SEND_INVAL,
[IB_WR_LOCAL_INV] = MLX5_OPCODE_UMR,
- [IB_WR_FAST_REG_MR] = MLX5_OPCODE_UMR,
+ [IB_WR_REG_MR] = MLX5_OPCODE_UMR,
[IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_MASKED_CS,
[IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_MASKED_FA,
[MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR,
@@ -1838,9 +1838,9 @@ static __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg,
static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg,
struct ib_send_wr *wr)
{
- memcpy(&dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof(struct mlx5_av));
- dseg->av.dqp_dct = cpu_to_be32(wr->wr.ud.remote_qpn | MLX5_EXTENDED_UD_AV);
- dseg->av.key.qkey.qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+ memcpy(&dseg->av, &to_mah(ud_wr(wr)->ah)->av, sizeof(struct mlx5_av));
+ dseg->av.dqp_dct = cpu_to_be32(ud_wr(wr)->remote_qpn | MLX5_EXTENDED_UD_AV);
+ dseg->av.key.qkey.qkey = cpu_to_be32(ud_wr(wr)->remote_qkey);
}
static void set_data_ptr_seg(struct mlx5_wqe_data_seg *dseg, struct ib_sge *sg)
@@ -1896,22 +1896,24 @@ static __be64 sig_mkey_mask(void)
return cpu_to_be64(result);
}
-static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
- struct ib_send_wr *wr, int li)
+static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
+ struct mlx5_ib_mr *mr)
{
- memset(umr, 0, sizeof(*umr));
-
- if (li) {
- umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE);
- umr->flags = 1 << 7;
- return;
- }
+ int ndescs = mr->ndescs;
- umr->flags = (1 << 5); /* fail if not free */
- umr->klm_octowords = get_klm_octo(wr->wr.fast_reg.page_list_len);
+ memset(umr, 0, sizeof(*umr));
+ umr->flags = MLX5_UMR_CHECK_NOT_FREE;
+ umr->klm_octowords = get_klm_octo(ndescs);
umr->mkey_mask = frwr_mkey_mask();
}
+static void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr)
+{
+ memset(umr, 0, sizeof(*umr));
+ umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE);
+ umr->flags = 1 << 7;
+}
+
static __be64 get_umr_reg_mr_mask(void)
{
u64 result;
@@ -1952,7 +1954,7 @@ static __be64 get_umr_update_mtt_mask(void)
static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
struct ib_send_wr *wr)
{
- struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
+ struct mlx5_umr_wr *umrwr = umr_wr(wr);
memset(umr, 0, sizeof(*umr));
@@ -1987,29 +1989,31 @@ static u8 get_umr_flags(int acc)
MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN;
}
-static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr,
- int li, int *writ)
+static void set_reg_mkey_seg(struct mlx5_mkey_seg *seg,
+ struct mlx5_ib_mr *mr,
+ u32 key, int access)
{
- memset(seg, 0, sizeof(*seg));
- if (li) {
- seg->status = MLX5_MKEY_STATUS_FREE;
- return;
- }
+ int ndescs = ALIGN(mr->ndescs, 8) >> 1;
- seg->flags = get_umr_flags(wr->wr.fast_reg.access_flags) |
- MLX5_ACCESS_MODE_MTT;
- *writ = seg->flags & (MLX5_PERM_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE);
- seg->qpn_mkey7_0 = cpu_to_be32((wr->wr.fast_reg.rkey & 0xff) | 0xffffff00);
+ memset(seg, 0, sizeof(*seg));
+ seg->flags = get_umr_flags(access) | MLX5_ACCESS_MODE_MTT;
+ seg->qpn_mkey7_0 = cpu_to_be32((key & 0xff) | 0xffffff00);
seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL);
- seg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start);
- seg->len = cpu_to_be64(wr->wr.fast_reg.length);
- seg->xlt_oct_size = cpu_to_be32((wr->wr.fast_reg.page_list_len + 1) / 2);
- seg->log2_page_size = wr->wr.fast_reg.page_shift;
+ seg->start_addr = cpu_to_be64(mr->ibmr.iova);
+ seg->len = cpu_to_be64(mr->ibmr.length);
+ seg->xlt_oct_size = cpu_to_be32(ndescs);
+ seg->log2_page_size = ilog2(mr->ibmr.page_size);
+}
+
+static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg)
+{
+ memset(seg, 0, sizeof(*seg));
+ seg->status = MLX5_MKEY_STATUS_FREE;
}
static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr)
{
- struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
+ struct mlx5_umr_wr *umrwr = umr_wr(wr);
memset(seg, 0, sizeof(*seg));
if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) {
@@ -2028,21 +2032,14 @@ static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *w
mlx5_mkey_variant(umrwr->mkey));
}
-static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg,
- struct ib_send_wr *wr,
- struct mlx5_core_dev *mdev,
- struct mlx5_ib_pd *pd,
- int writ)
+static void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg,
+ struct mlx5_ib_mr *mr,
+ struct mlx5_ib_pd *pd)
{
- struct mlx5_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
- u64 *page_list = wr->wr.fast_reg.page_list->page_list;
- u64 perm = MLX5_EN_RD | (writ ? MLX5_EN_WR : 0);
- int i;
+ int bcount = mr->desc_size * mr->ndescs;
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++)
- mfrpl->mapped_page_list[i] = cpu_to_be64(page_list[i] | perm);
- dseg->addr = cpu_to_be64(mfrpl->map);
- dseg->byte_count = cpu_to_be32(ALIGN(sizeof(u64) * wr->wr.fast_reg.page_list_len, 64));
+ dseg->addr = cpu_to_be64(mr->desc_map);
+ dseg->byte_count = cpu_to_be32(ALIGN(bcount, 64));
dseg->lkey = cpu_to_be32(pd->ibpd.local_dma_lkey);
}
@@ -2224,22 +2221,22 @@ static int mlx5_set_bsf(struct ib_mr *sig_mr,
return 0;
}
-static int set_sig_data_segment(struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
- void **seg, int *size)
+static int set_sig_data_segment(struct ib_sig_handover_wr *wr,
+ struct mlx5_ib_qp *qp, void **seg, int *size)
{
- struct ib_sig_attrs *sig_attrs = wr->wr.sig_handover.sig_attrs;
- struct ib_mr *sig_mr = wr->wr.sig_handover.sig_mr;
+ struct ib_sig_attrs *sig_attrs = wr->sig_attrs;
+ struct ib_mr *sig_mr = wr->sig_mr;
struct mlx5_bsf *bsf;
- u32 data_len = wr->sg_list->length;
- u32 data_key = wr->sg_list->lkey;
- u64 data_va = wr->sg_list->addr;
+ u32 data_len = wr->wr.sg_list->length;
+ u32 data_key = wr->wr.sg_list->lkey;
+ u64 data_va = wr->wr.sg_list->addr;
int ret;
int wqe_size;
- if (!wr->wr.sig_handover.prot ||
- (data_key == wr->wr.sig_handover.prot->lkey &&
- data_va == wr->wr.sig_handover.prot->addr &&
- data_len == wr->wr.sig_handover.prot->length)) {
+ if (!wr->prot ||
+ (data_key == wr->prot->lkey &&
+ data_va == wr->prot->addr &&
+ data_len == wr->prot->length)) {
/**
* Source domain doesn't contain signature information
* or data and protection are interleaved in memory.
@@ -2273,8 +2270,8 @@ static int set_sig_data_segment(struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
struct mlx5_stride_block_ctrl_seg *sblock_ctrl;
struct mlx5_stride_block_entry *data_sentry;
struct mlx5_stride_block_entry *prot_sentry;
- u32 prot_key = wr->wr.sig_handover.prot->lkey;
- u64 prot_va = wr->wr.sig_handover.prot->addr;
+ u32 prot_key = wr->prot->lkey;
+ u64 prot_va = wr->prot->addr;
u16 block_size = sig_attrs->mem.sig.dif.pi_interval;
int prot_size;
@@ -2326,16 +2323,16 @@ static int set_sig_data_segment(struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
}
static void set_sig_mkey_segment(struct mlx5_mkey_seg *seg,
- struct ib_send_wr *wr, u32 nelements,
+ struct ib_sig_handover_wr *wr, u32 nelements,
u32 length, u32 pdn)
{
- struct ib_mr *sig_mr = wr->wr.sig_handover.sig_mr;
+ struct ib_mr *sig_mr = wr->sig_mr;
u32 sig_key = sig_mr->rkey;
u8 sigerr = to_mmr(sig_mr)->sig->sigerr_count & 1;
memset(seg, 0, sizeof(*seg));
- seg->flags = get_umr_flags(wr->wr.sig_handover.access_flags) |
+ seg->flags = get_umr_flags(wr->access_flags) |
MLX5_ACCESS_MODE_KLM;
seg->qpn_mkey7_0 = cpu_to_be32((sig_key & 0xff) | 0xffffff00);
seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL | sigerr << 26 |
@@ -2346,7 +2343,7 @@ static void set_sig_mkey_segment(struct mlx5_mkey_seg *seg,
}
static void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
- struct ib_send_wr *wr, u32 nelements)
+ u32 nelements)
{
memset(umr, 0, sizeof(*umr));
@@ -2357,37 +2354,37 @@ static void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
}
-static int set_sig_umr_wr(struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
+static int set_sig_umr_wr(struct ib_send_wr *send_wr, struct mlx5_ib_qp *qp,
void **seg, int *size)
{
- struct mlx5_ib_mr *sig_mr = to_mmr(wr->wr.sig_handover.sig_mr);
+ struct ib_sig_handover_wr *wr = sig_handover_wr(send_wr);
+ struct mlx5_ib_mr *sig_mr = to_mmr(wr->sig_mr);
u32 pdn = get_pd(qp)->pdn;
u32 klm_oct_size;
int region_len, ret;
- if (unlikely(wr->num_sge != 1) ||
- unlikely(wr->wr.sig_handover.access_flags &
- IB_ACCESS_REMOTE_ATOMIC) ||
+ if (unlikely(wr->wr.num_sge != 1) ||
+ unlikely(wr->access_flags & IB_ACCESS_REMOTE_ATOMIC) ||
unlikely(!sig_mr->sig) || unlikely(!qp->signature_en) ||
unlikely(!sig_mr->sig->sig_status_checked))
return -EINVAL;
/* length of the protected region, data + protection */
- region_len = wr->sg_list->length;
- if (wr->wr.sig_handover.prot &&
- (wr->wr.sig_handover.prot->lkey != wr->sg_list->lkey ||
- wr->wr.sig_handover.prot->addr != wr->sg_list->addr ||
- wr->wr.sig_handover.prot->length != wr->sg_list->length))
- region_len += wr->wr.sig_handover.prot->length;
+ region_len = wr->wr.sg_list->length;
+ if (wr->prot &&
+ (wr->prot->lkey != wr->wr.sg_list->lkey ||
+ wr->prot->addr != wr->wr.sg_list->addr ||
+ wr->prot->length != wr->wr.sg_list->length))
+ region_len += wr->prot->length;
/**
* KLM octoword size - if protection was provided
* then we use strided block format (3 octowords),
* else we use single KLM (1 octoword)
**/
- klm_oct_size = wr->wr.sig_handover.prot ? 3 : 1;
+ klm_oct_size = wr->prot ? 3 : 1;
- set_sig_umr_segment(*seg, wr, klm_oct_size);
+ set_sig_umr_segment(*seg, klm_oct_size);
*seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
*size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
if (unlikely((*seg == qp->sq.qend)))
@@ -2433,38 +2430,52 @@ static int set_psv_wr(struct ib_sig_domain *domain,
return 0;
}
-static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size,
- struct mlx5_core_dev *mdev, struct mlx5_ib_pd *pd, struct mlx5_ib_qp *qp)
+static int set_reg_wr(struct mlx5_ib_qp *qp,
+ struct ib_reg_wr *wr,
+ void **seg, int *size)
{
- int writ = 0;
- int li;
+ struct mlx5_ib_mr *mr = to_mmr(wr->mr);
+ struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
- li = wr->opcode == IB_WR_LOCAL_INV ? 1 : 0;
- if (unlikely(wr->send_flags & IB_SEND_INLINE))
+ if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) {
+ mlx5_ib_warn(to_mdev(qp->ibqp.device),
+ "Invalid IB_SEND_INLINE send flag\n");
return -EINVAL;
+ }
- set_frwr_umr_segment(*seg, wr, li);
+ set_reg_umr_seg(*seg, mr);
*seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
*size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
if (unlikely((*seg == qp->sq.qend)))
*seg = mlx5_get_send_wqe(qp, 0);
- set_mkey_segment(*seg, wr, li, &writ);
+
+ set_reg_mkey_seg(*seg, mr, wr->key, wr->access);
*seg += sizeof(struct mlx5_mkey_seg);
*size += sizeof(struct mlx5_mkey_seg) / 16;
if (unlikely((*seg == qp->sq.qend)))
*seg = mlx5_get_send_wqe(qp, 0);
- if (!li) {
- if (unlikely(wr->wr.fast_reg.page_list_len >
- wr->wr.fast_reg.page_list->max_page_list_len))
- return -ENOMEM;
- set_frwr_pages(*seg, wr, mdev, pd, writ);
- *seg += sizeof(struct mlx5_wqe_data_seg);
- *size += (sizeof(struct mlx5_wqe_data_seg) / 16);
- }
+ set_reg_data_seg(*seg, mr, pd);
+ *seg += sizeof(struct mlx5_wqe_data_seg);
+ *size += (sizeof(struct mlx5_wqe_data_seg) / 16);
+
return 0;
}
+static void set_linv_wr(struct mlx5_ib_qp *qp, void **seg, int *size)
+{
+ set_linv_umr_seg(*seg);
+ *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
+ *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
+ if (unlikely((*seg == qp->sq.qend)))
+ *seg = mlx5_get_send_wqe(qp, 0);
+ set_linv_mkey_seg(*seg);
+ *seg += sizeof(struct mlx5_mkey_seg);
+ *size += sizeof(struct mlx5_mkey_seg) / 16;
+ if (unlikely((*seg == qp->sq.qend)))
+ *seg = mlx5_get_send_wqe(qp, 0);
+}
+
static void dump_wqe(struct mlx5_ib_qp *qp, int idx, int size_16)
{
__be32 *p = NULL;
@@ -2578,7 +2589,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
{
struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */
struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
- struct mlx5_core_dev *mdev = dev->mdev;
struct mlx5_ib_qp *qp = to_mqp(ibqp);
struct mlx5_ib_mr *mr;
struct mlx5_wqe_data_seg *dpseg;
@@ -2627,7 +2637,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
switch (ibqp->qp_type) {
case IB_QPT_XRC_INI:
xrc = seg;
- xrc->xrc_srqn = htonl(wr->xrc_remote_srq_num);
seg += sizeof(*xrc);
size += sizeof(*xrc) / 16;
/* fall through */
@@ -2636,8 +2645,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_RDMA_READ:
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
- set_raddr_seg(seg, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(seg, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
seg += sizeof(struct mlx5_wqe_raddr_seg);
size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
break;
@@ -2654,22 +2663,16 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
qp->sq.wr_data[idx] = IB_WR_LOCAL_INV;
ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey);
- err = set_frwr_li_wr(&seg, wr, &size, mdev, to_mpd(ibqp->pd), qp);
- if (err) {
- mlx5_ib_warn(dev, "\n");
- *bad_wr = wr;
- goto out;
- }
+ set_linv_wr(qp, &seg, &size);
num_sge = 0;
break;
- case IB_WR_FAST_REG_MR:
+ case IB_WR_REG_MR:
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
- qp->sq.wr_data[idx] = IB_WR_FAST_REG_MR;
- ctrl->imm = cpu_to_be32(wr->wr.fast_reg.rkey);
- err = set_frwr_li_wr(&seg, wr, &size, mdev, to_mpd(ibqp->pd), qp);
+ qp->sq.wr_data[idx] = IB_WR_REG_MR;
+ ctrl->imm = cpu_to_be32(reg_wr(wr)->key);
+ err = set_reg_wr(qp, reg_wr(wr), &seg, &size);
if (err) {
- mlx5_ib_warn(dev, "\n");
*bad_wr = wr;
goto out;
}
@@ -2678,7 +2681,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_REG_SIG_MR:
qp->sq.wr_data[idx] = IB_WR_REG_SIG_MR;
- mr = to_mmr(wr->wr.sig_handover.sig_mr);
+ mr = to_mmr(sig_handover_wr(wr)->sig_mr);
ctrl->imm = cpu_to_be32(mr->ibmr.rkey);
err = set_sig_umr_wr(wr, qp, &seg, &size);
@@ -2706,7 +2709,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- err = set_psv_wr(&wr->wr.sig_handover.sig_attrs->mem,
+ err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->mem,
mr->sig->psv_memory.psv_idx, &seg,
&size);
if (err) {
@@ -2728,7 +2731,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
- err = set_psv_wr(&wr->wr.sig_handover.sig_attrs->wire,
+ err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->wire,
mr->sig->psv_wire.psv_idx, &seg,
&size);
if (err) {
@@ -2752,8 +2755,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
switch (wr->opcode) {
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
- set_raddr_seg(seg, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(seg, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
seg += sizeof(struct mlx5_wqe_raddr_seg);
size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
break;
@@ -2780,7 +2783,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
qp->sq.wr_data[idx] = MLX5_IB_WR_UMR;
- ctrl->imm = cpu_to_be32(wr->wr.fast_reg.rkey);
+ ctrl->imm = cpu_to_be32(umr_wr(wr)->mkey);
set_reg_umr_segment(seg, wr);
seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 32f6c6315454..bcac294042f5 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -281,7 +281,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
ib_get_cached_gid(&dev->ib_dev,
be32_to_cpu(ah->av->port_pd) >> 24,
ah->av->gid_index % dev->limits.gid_table_len,
- &header->grh.source_gid);
+ &header->grh.source_gid, NULL);
memcpy(header->grh.destination_gid.raw,
ah->av->dgid, 16);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index e354b2f04ad9..35fe506e2cfa 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1476,7 +1476,7 @@ void mthca_free_qp(struct mthca_dev *dev,
/* Create UD header for an MLX send and build a data segment for it */
static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
- int ind, struct ib_send_wr *wr,
+ int ind, struct ib_ud_wr *wr,
struct mthca_mlx_seg *mlx,
struct mthca_data_seg *data)
{
@@ -1485,10 +1485,10 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
u16 pkey;
ib_ud_header_init(256, /* assume a MAD */ 1, 0, 0,
- mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0,
+ mthca_ah_grh_present(to_mah(wr->ah)), 0,
&sqp->ud_header);
- err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header);
+ err = mthca_read_ah(dev, to_mah(wr->ah), &sqp->ud_header);
if (err)
return err;
mlx->flags &= ~cpu_to_be32(MTHCA_NEXT_SOLICIT | 1);
@@ -1499,7 +1499,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
mlx->rlid = sqp->ud_header.lrh.destination_lid;
mlx->vcrc = 0;
- switch (wr->opcode) {
+ switch (wr->wr.opcode) {
case IB_WR_SEND:
sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY;
sqp->ud_header.immediate_present = 0;
@@ -1507,7 +1507,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
case IB_WR_SEND_WITH_IMM:
sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
sqp->ud_header.immediate_present = 1;
- sqp->ud_header.immediate_data = wr->ex.imm_data;
+ sqp->ud_header.immediate_data = wr->wr.ex.imm_data;
break;
default:
return -EINVAL;
@@ -1516,18 +1516,18 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0;
if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
- sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+ sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
if (!sqp->qp.ibqp.qp_num)
ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
sqp->pkey_index, &pkey);
else
ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
- wr->wr.ud.pkey_index, &pkey);
+ wr->pkey_index, &pkey);
sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
- sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+ sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
- sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ?
- sqp->qkey : wr->wr.ud.remote_qkey);
+ sqp->ud_header.deth.qkey = cpu_to_be32(wr->remote_qkey & 0x80000000 ?
+ sqp->qkey : wr->remote_qkey);
sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.ibqp.qp_num);
header_size = ib_ud_header_pack(&sqp->ud_header,
@@ -1569,34 +1569,34 @@ static __always_inline void set_raddr_seg(struct mthca_raddr_seg *rseg,
}
static __always_inline void set_atomic_seg(struct mthca_atomic_seg *aseg,
- struct ib_send_wr *wr)
+ struct ib_atomic_wr *wr)
{
- if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
- aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
- aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add);
+ if (wr->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
+ aseg->swap_add = cpu_to_be64(wr->swap);
+ aseg->compare = cpu_to_be64(wr->compare_add);
} else {
- aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
+ aseg->swap_add = cpu_to_be64(wr->compare_add);
aseg->compare = 0;
}
}
static void set_tavor_ud_seg(struct mthca_tavor_ud_seg *useg,
- struct ib_send_wr *wr)
+ struct ib_ud_wr *wr)
{
- useg->lkey = cpu_to_be32(to_mah(wr->wr.ud.ah)->key);
- useg->av_addr = cpu_to_be64(to_mah(wr->wr.ud.ah)->avdma);
- useg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
- useg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+ useg->lkey = cpu_to_be32(to_mah(wr->ah)->key);
+ useg->av_addr = cpu_to_be64(to_mah(wr->ah)->avdma);
+ useg->dqpn = cpu_to_be32(wr->remote_qpn);
+ useg->qkey = cpu_to_be32(wr->remote_qkey);
}
static void set_arbel_ud_seg(struct mthca_arbel_ud_seg *useg,
- struct ib_send_wr *wr)
+ struct ib_ud_wr *wr)
{
- memcpy(useg->av, to_mah(wr->wr.ud.ah)->av, MTHCA_AV_SIZE);
- useg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
- useg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+ memcpy(useg->av, to_mah(wr->ah)->av, MTHCA_AV_SIZE);
+ useg->dqpn = cpu_to_be32(wr->remote_qpn);
+ useg->qkey = cpu_to_be32(wr->remote_qkey);
}
int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
@@ -1664,11 +1664,11 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
switch (wr->opcode) {
case IB_WR_ATOMIC_CMP_AND_SWP:
case IB_WR_ATOMIC_FETCH_AND_ADD:
- set_raddr_seg(wqe, wr->wr.atomic.remote_addr,
- wr->wr.atomic.rkey);
+ set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
+ atomic_wr(wr)->rkey);
wqe += sizeof (struct mthca_raddr_seg);
- set_atomic_seg(wqe, wr);
+ set_atomic_seg(wqe, atomic_wr(wr));
wqe += sizeof (struct mthca_atomic_seg);
size += (sizeof (struct mthca_raddr_seg) +
sizeof (struct mthca_atomic_seg)) / 16;
@@ -1677,8 +1677,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
case IB_WR_RDMA_READ:
- set_raddr_seg(wqe, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
wqe += sizeof (struct mthca_raddr_seg);
size += sizeof (struct mthca_raddr_seg) / 16;
break;
@@ -1694,8 +1694,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
switch (wr->opcode) {
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
- set_raddr_seg(wqe, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
wqe += sizeof (struct mthca_raddr_seg);
size += sizeof (struct mthca_raddr_seg) / 16;
break;
@@ -1708,13 +1708,13 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case UD:
- set_tavor_ud_seg(wqe, wr);
+ set_tavor_ud_seg(wqe, ud_wr(wr));
wqe += sizeof (struct mthca_tavor_ud_seg);
size += sizeof (struct mthca_tavor_ud_seg) / 16;
break;
case MLX:
- err = build_mlx_header(dev, to_msqp(qp), ind, wr,
+ err = build_mlx_header(dev, to_msqp(qp), ind, ud_wr(wr),
wqe - sizeof (struct mthca_next_seg),
wqe);
if (err) {
@@ -2005,11 +2005,11 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
switch (wr->opcode) {
case IB_WR_ATOMIC_CMP_AND_SWP:
case IB_WR_ATOMIC_FETCH_AND_ADD:
- set_raddr_seg(wqe, wr->wr.atomic.remote_addr,
- wr->wr.atomic.rkey);
+ set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
+ atomic_wr(wr)->rkey);
wqe += sizeof (struct mthca_raddr_seg);
- set_atomic_seg(wqe, wr);
+ set_atomic_seg(wqe, atomic_wr(wr));
wqe += sizeof (struct mthca_atomic_seg);
size += (sizeof (struct mthca_raddr_seg) +
sizeof (struct mthca_atomic_seg)) / 16;
@@ -2018,8 +2018,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_RDMA_READ:
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
- set_raddr_seg(wqe, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
wqe += sizeof (struct mthca_raddr_seg);
size += sizeof (struct mthca_raddr_seg) / 16;
break;
@@ -2035,8 +2035,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
switch (wr->opcode) {
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
- set_raddr_seg(wqe, wr->wr.rdma.remote_addr,
- wr->wr.rdma.rkey);
+ set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
+ rdma_wr(wr)->rkey);
wqe += sizeof (struct mthca_raddr_seg);
size += sizeof (struct mthca_raddr_seg) / 16;
break;
@@ -2049,13 +2049,13 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case UD:
- set_arbel_ud_seg(wqe, wr);
+ set_arbel_ud_seg(wqe, ud_wr(wr));
wqe += sizeof (struct mthca_arbel_ud_seg);
size += sizeof (struct mthca_arbel_ud_seg) / 16;
break;
case MLX:
- err = build_mlx_header(dev, to_msqp(qp), ind, wr,
+ err = build_mlx_header(dev, to_msqp(qp), ind, ud_wr(wr),
wqe - sizeof (struct mthca_next_seg),
wqe);
if (err) {
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index d748e4b31b8d..c9080208aad2 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1200,12 +1200,6 @@ struct nes_fast_mr_wqe_pbl {
dma_addr_t paddr;
};
-struct nes_ib_fast_reg_page_list {
- struct ib_fast_reg_page_list ibfrpl;
- struct nes_fast_mr_wqe_pbl nes_wqe_pbl;
- u64 pbl;
-};
-
struct nes_listener {
struct work_struct work;
struct workqueue_struct *wq;
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 70acda91eb2a..6a0bdfa0ce2e 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1325,9 +1325,6 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev,
"%u.%u", nesadapter->firmware_version >> 16,
nesadapter->firmware_version & 0x000000ff);
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
- drvinfo->testinfo_len = 0;
- drvinfo->eedump_len = 0;
- drvinfo->regdump_len = 0;
}
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 44cb513f9a87..137880a19ebe 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -51,6 +51,7 @@ atomic_t qps_created;
atomic_t sw_qps_destroyed;
static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
+static int nes_dereg_mr(struct ib_mr *ib_mr);
/**
* nes_alloc_mw
@@ -443,79 +444,46 @@ static struct ib_mr *nes_alloc_mr(struct ib_pd *ibpd,
} else {
kfree(nesmr);
nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
- ibmr = ERR_PTR(-ENOMEM);
+ return ERR_PTR(-ENOMEM);
}
+
+ nesmr->pages = pci_alloc_consistent(nesdev->pcidev,
+ max_num_sg * sizeof(u64),
+ &nesmr->paddr);
+ if (!nesmr->paddr)
+ goto err;
+
+ nesmr->max_pages = max_num_sg;
+
return ibmr;
+
+err:
+ nes_dereg_mr(ibmr);
+
+ return ERR_PTR(-ENOMEM);
}
-/*
- * nes_alloc_fast_reg_page_list
- */
-static struct ib_fast_reg_page_list *nes_alloc_fast_reg_page_list(
- struct ib_device *ibdev,
- int page_list_len)
+static int nes_set_page(struct ib_mr *ibmr, u64 addr)
{
- struct nes_vnic *nesvnic = to_nesvnic(ibdev);
- struct nes_device *nesdev = nesvnic->nesdev;
- struct ib_fast_reg_page_list *pifrpl;
- struct nes_ib_fast_reg_page_list *pnesfrpl;
+ struct nes_mr *nesmr = to_nesmr(ibmr);
- if (page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))
- return ERR_PTR(-E2BIG);
- /*
- * Allocate the ib_fast_reg_page_list structure, the
- * nes_fast_bpl structure, and the PLB table.
- */
- pnesfrpl = kmalloc(sizeof(struct nes_ib_fast_reg_page_list) +
- page_list_len * sizeof(u64), GFP_KERNEL);
-
- if (!pnesfrpl)
- return ERR_PTR(-ENOMEM);
+ if (unlikely(nesmr->npages == nesmr->max_pages))
+ return -ENOMEM;
- pifrpl = &pnesfrpl->ibfrpl;
- pifrpl->page_list = &pnesfrpl->pbl;
- pifrpl->max_page_list_len = page_list_len;
- /*
- * Allocate the WQE PBL
- */
- pnesfrpl->nes_wqe_pbl.kva = pci_alloc_consistent(nesdev->pcidev,
- page_list_len * sizeof(u64),
- &pnesfrpl->nes_wqe_pbl.paddr);
+ nesmr->pages[nesmr->npages++] = cpu_to_le64(addr);
- if (!pnesfrpl->nes_wqe_pbl.kva) {
- kfree(pnesfrpl);
- return ERR_PTR(-ENOMEM);
- }
- nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, "
- "ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, "
- "pbl.paddr = %llx\n", pnesfrpl, &pnesfrpl->ibfrpl,
- pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva,
- (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr);
-
- return pifrpl;
+ return 0;
}
-/*
- * nes_free_fast_reg_page_list
- */
-static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl)
+static int nes_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
{
- struct nes_vnic *nesvnic = to_nesvnic(pifrpl->device);
- struct nes_device *nesdev = nesvnic->nesdev;
- struct nes_ib_fast_reg_page_list *pnesfrpl;
+ struct nes_mr *nesmr = to_nesmr(ibmr);
- pnesfrpl = container_of(pifrpl, struct nes_ib_fast_reg_page_list, ibfrpl);
- /*
- * Free the WQE PBL.
- */
- pci_free_consistent(nesdev->pcidev,
- pifrpl->max_page_list_len * sizeof(u64),
- pnesfrpl->nes_wqe_pbl.kva,
- pnesfrpl->nes_wqe_pbl.paddr);
- /*
- * Free the PBL structure
- */
- kfree(pnesfrpl);
+ nesmr->npages = 0;
+
+ return ib_sg_to_pages(ibmr, sg, sg_nents, nes_set_page);
}
/**
@@ -2683,6 +2651,13 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
u16 major_code;
u16 minor_code;
+
+ if (nesmr->pages)
+ pci_free_consistent(nesdev->pcidev,
+ nesmr->max_pages * sizeof(u64),
+ nesmr->pages,
+ nesmr->paddr);
+
if (nesmr->region) {
ib_umem_release(nesmr->region);
}
@@ -3372,9 +3347,9 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
- ib_wr->wr.rdma.rkey);
+ rdma_wr(ib_wr)->rkey);
set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
- ib_wr->wr.rdma.remote_addr);
+ rdma_wr(ib_wr)->remote_addr);
if ((ib_wr->send_flags & IB_SEND_INLINE) &&
((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
@@ -3409,9 +3384,9 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
}
set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
- ib_wr->wr.rdma.remote_addr);
+ rdma_wr(ib_wr)->remote_addr);
set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
- ib_wr->wr.rdma.rkey);
+ rdma_wr(ib_wr)->rkey);
set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX,
ib_wr->sg_list->length);
set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
@@ -3425,19 +3400,13 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX,
ib_wr->ex.invalidate_rkey);
break;
- case IB_WR_FAST_REG_MR:
+ case IB_WR_REG_MR:
{
- int i;
- int flags = ib_wr->wr.fast_reg.access_flags;
- struct nes_ib_fast_reg_page_list *pnesfrpl =
- container_of(ib_wr->wr.fast_reg.page_list,
- struct nes_ib_fast_reg_page_list,
- ibfrpl);
- u64 *src_page_list = pnesfrpl->ibfrpl.page_list;
- u64 *dst_page_list = pnesfrpl->nes_wqe_pbl.kva;
-
- if (ib_wr->wr.fast_reg.page_list_len >
- (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) {
+ struct nes_mr *mr = to_nesmr(reg_wr(ib_wr)->mr);
+ int page_shift = ilog2(reg_wr(ib_wr)->mr->page_size);
+ int flags = reg_wr(ib_wr)->access;
+
+ if (mr->npages > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) {
nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n");
err = -EINVAL;
break;
@@ -3445,19 +3414,19 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
wqe_misc = NES_IWARP_SQ_OP_FAST_REG;
set_wqe_64bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX,
- ib_wr->wr.fast_reg.iova_start);
+ mr->ibmr.iova);
set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
- ib_wr->wr.fast_reg.length);
+ mr->ibmr.length);
set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
- ib_wr->wr.fast_reg.rkey);
- /* Set page size: */
- if (ib_wr->wr.fast_reg.page_shift == 12) {
+ reg_wr(ib_wr)->key);
+
+ if (page_shift == 12) {
wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K;
- } else if (ib_wr->wr.fast_reg.page_shift == 21) {
+ } else if (page_shift == 21) {
wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M;
} else {
nes_debug(NES_DBG_IW_TX, "Invalid page shift,"
@@ -3465,6 +3434,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
err = -EINVAL;
break;
}
+
/* Set access_flags */
wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ;
if (flags & IB_ACCESS_LOCAL_WRITE)
@@ -3480,35 +3450,22 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND;
/* Fill in PBL info: */
- if (ib_wr->wr.fast_reg.page_list_len >
- pnesfrpl->ibfrpl.max_page_list_len) {
- nes_debug(NES_DBG_IW_TX, "Invalid page list length,"
- " ib_wr=%p, value=%u, max=%u\n",
- ib_wr, ib_wr->wr.fast_reg.page_list_len,
- pnesfrpl->ibfrpl.max_page_list_len);
- err = -EINVAL;
- break;
- }
-
set_wqe_64bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX,
- pnesfrpl->nes_wqe_pbl.paddr);
+ mr->paddr);
set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX,
- ib_wr->wr.fast_reg.page_list_len * 8);
-
- for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++)
- dst_page_list[i] = cpu_to_le64(src_page_list[i]);
+ mr->npages * 8);
- nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %llx, "
+ nes_debug(NES_DBG_IW_TX, "SQ_REG_MR: iova_start: %llx, "
"length: %d, rkey: %0x, pgl_paddr: %llx, "
"page_list_len: %u, wqe_misc: %x\n",
- (unsigned long long) ib_wr->wr.fast_reg.iova_start,
- ib_wr->wr.fast_reg.length,
- ib_wr->wr.fast_reg.rkey,
- (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr,
- ib_wr->wr.fast_reg.page_list_len,
+ (unsigned long long) mr->ibmr.iova,
+ mr->ibmr.length,
+ reg_wr(ib_wr)->key,
+ (unsigned long long) mr->paddr,
+ mr->npages,
wqe_misc);
break;
}
@@ -3751,7 +3708,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
entry->opcode = IB_WC_LOCAL_INV;
break;
case NES_IWARP_SQ_OP_FAST_REG:
- entry->opcode = IB_WC_FAST_REG_MR;
+ entry->opcode = IB_WC_REG_MR;
break;
}
@@ -3939,8 +3896,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
nesibdev->ibdev.bind_mw = nes_bind_mw;
nesibdev->ibdev.alloc_mr = nes_alloc_mr;
- nesibdev->ibdev.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list;
- nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list;
+ nesibdev->ibdev.map_mr_sg = nes_map_mr_sg;
nesibdev->ibdev.attach_mcast = nes_multicast_attach;
nesibdev->ibdev.detach_mcast = nes_multicast_detach;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 309b31c31ae1..a204b677af22 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -79,6 +79,10 @@ struct nes_mr {
u16 pbls_used;
u8 mode;
u8 pbl_4k;
+ __le64 *pages;
+ dma_addr_t paddr;
+ u32 max_pages;
+ u32 npages;
};
struct nes_hw_pb {
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
index b4091ab48db0..ae80590aabdf 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -55,7 +55,7 @@
#include <be_roce.h>
#include "ocrdma_sli.h"
-#define OCRDMA_ROCE_DRV_VERSION "10.6.0.0"
+#define OCRDMA_ROCE_DRV_VERSION "11.0.0.0"
#define OCRDMA_ROCE_DRV_DESC "Emulex OneConnect RoCE Driver"
#define OCRDMA_NODE_DESC "Emulex OneConnect RoCE HCA"
@@ -193,6 +193,8 @@ struct ocrdma_mr {
struct ib_mr ibmr;
struct ib_umem *umem;
struct ocrdma_hw_mr hwmr;
+ u64 *pages;
+ u32 npages;
};
struct ocrdma_stats {
@@ -278,7 +280,6 @@ struct ocrdma_dev {
u32 hba_port_num;
struct list_head entry;
- struct rcu_head rcu;
int id;
u64 *stag_arr;
u8 sl; /* service level */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index 44766fee1f4e..9820074be59d 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -45,6 +45,7 @@
#include <rdma/ib_addr.h>
#include <rdma/ib_mad.h>
+#include <rdma/ib_cache.h>
#include "ocrdma.h"
#include "ocrdma_verbs.h"
@@ -56,10 +57,9 @@
static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
struct ib_ah_attr *attr, union ib_gid *sgid,
- int pdid, bool *isvlan)
+ int pdid, bool *isvlan, u16 vlan_tag)
{
int status = 0;
- u16 vlan_tag;
struct ocrdma_eth_vlan eth;
struct ocrdma_grh grh;
int eth_sz;
@@ -68,7 +68,6 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
memset(&grh, 0, sizeof(grh));
/* VLAN */
- vlan_tag = attr->vlan_id;
if (!vlan_tag || (vlan_tag > 0xFFF))
vlan_tag = dev->pvid;
if (vlan_tag || dev->pfc_state) {
@@ -115,9 +114,11 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
{
u32 *ahid_addr;
- bool isvlan = false;
int status;
struct ocrdma_ah *ah;
+ bool isvlan = false;
+ u16 vlan_tag = 0xffff;
+ struct ib_gid_attr sgid_attr;
struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
union ib_gid sgid;
@@ -135,18 +136,25 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
if (status)
goto av_err;
- status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index, &sgid);
+ status = ib_get_cached_gid(&dev->ibdev, 1, attr->grh.sgid_index, &sgid,
+ &sgid_attr);
if (status) {
pr_err("%s(): Failed to query sgid, status = %d\n",
__func__, status);
goto av_conf_err;
}
+ if (sgid_attr.ndev) {
+ if (is_vlan_dev(sgid_attr.ndev))
+ vlan_tag = vlan_dev_vlan_id(sgid_attr.ndev);
+ dev_put(sgid_attr.ndev);
+ }
if ((pd->uctx) &&
(!rdma_is_multicast_addr((struct in6_addr *)attr->grh.dgid.raw)) &&
(!rdma_link_local_addr((struct in6_addr *)attr->grh.dgid.raw))) {
status = rdma_addr_find_dmac_by_grh(&sgid, &attr->grh.dgid,
- attr->dmac, &attr->vlan_id);
+ attr->dmac, &vlan_tag,
+ sgid_attr.ndev->ifindex);
if (status) {
pr_err("%s(): Failed to resolve dmac from gid."
"status = %d\n", __func__, status);
@@ -154,7 +162,7 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
}
}
- status = set_av_attr(dev, ah, attr, &sgid, pd->id, &isvlan);
+ status = set_av_attr(dev, ah, attr, &sgid, pd->id, &isvlan, vlan_tag);
if (status)
goto av_conf_err;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index aab391a15db4..30f67bebffa3 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -47,6 +47,7 @@
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_cache.h>
#include "ocrdma.h"
#include "ocrdma_hw.h"
@@ -678,11 +679,33 @@ static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev,
int dev_event = 0;
int type = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_TYPE_MASK) >>
OCRDMA_AE_MCQE_EVENT_TYPE_SHIFT;
+ u16 qpid = cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPID_MASK;
+ u16 cqid = cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQID_MASK;
- if (cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPVALID)
- qp = dev->qp_tbl[cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPID_MASK];
- if (cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQVALID)
- cq = dev->cq_tbl[cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQID_MASK];
+ /*
+ * Some FW version returns wrong qp or cq ids in CQEs.
+ * Checking whether the IDs are valid
+ */
+
+ if (cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPVALID) {
+ if (qpid < dev->attr.max_qp)
+ qp = dev->qp_tbl[qpid];
+ if (qp == NULL) {
+ pr_err("ocrdma%d:Async event - qpid %u is not valid\n",
+ dev->id, qpid);
+ return;
+ }
+ }
+
+ if (cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQVALID) {
+ if (cqid < dev->attr.max_cq)
+ cq = dev->cq_tbl[cqid];
+ if (cq == NULL) {
+ pr_err("ocrdma%d:Async event - cqid %u is not valid\n",
+ dev->id, cqid);
+ return;
+ }
+ }
memset(&ib_evt, 0, sizeof(ib_evt));
@@ -2448,6 +2471,7 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
int status;
struct ib_ah_attr *ah_attr = &attrs->ah_attr;
union ib_gid sgid, zgid;
+ struct ib_gid_attr sgid_attr;
u32 vlan_id = 0xFFFF;
u8 mac_addr[6];
struct ocrdma_dev *dev = get_ocrdma_dev(qp->ibqp.device);
@@ -2466,10 +2490,14 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
cmd->flags |= OCRDMA_QP_PARA_FLOW_LBL_VALID;
memcpy(&cmd->params.dgid[0], &ah_attr->grh.dgid.raw[0],
sizeof(cmd->params.dgid));
- status = ocrdma_query_gid(&dev->ibdev, 1,
- ah_attr->grh.sgid_index, &sgid);
- if (status)
- return status;
+
+ status = ib_get_cached_gid(&dev->ibdev, 1, ah_attr->grh.sgid_index,
+ &sgid, &sgid_attr);
+ if (!status && sgid_attr.ndev) {
+ vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev);
+ memcpy(mac_addr, sgid_attr.ndev->dev_addr, ETH_ALEN);
+ dev_put(sgid_attr.ndev);
+ }
memset(&zgid, 0, sizeof(zgid));
if (!memcmp(&sgid, &zgid, sizeof(zgid)))
@@ -2486,17 +2514,15 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
ocrdma_cpu_to_le32(&cmd->params.dgid[0], sizeof(cmd->params.dgid));
ocrdma_cpu_to_le32(&cmd->params.sgid[0], sizeof(cmd->params.sgid));
cmd->params.vlan_dmac_b4_to_b5 = mac_addr[4] | (mac_addr[5] << 8);
- if (attr_mask & IB_QP_VID) {
- vlan_id = attrs->vlan_id;
- } else if (dev->pfc_state) {
- vlan_id = 0;
- pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
- dev->id);
- pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
- dev->id);
- }
if (vlan_id < 0x1000) {
+ if (dev->pfc_state) {
+ vlan_id = 0;
+ pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
+ dev->id);
+ pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
+ dev->id);
+ }
cmd->params.vlan_dmac_b4_to_b5 |=
vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT;
cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 87aa55df7c82..62b7009daa6c 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -63,8 +63,6 @@ MODULE_DESCRIPTION(OCRDMA_ROCE_DRV_DESC " " OCRDMA_ROCE_DRV_VERSION);
MODULE_AUTHOR("Emulex Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-static LIST_HEAD(ocrdma_dev_list);
-static DEFINE_SPINLOCK(ocrdma_devlist_lock);
static DEFINE_IDR(ocrdma_dev_id);
void ocrdma_get_guid(struct ocrdma_dev *dev, u8 *guid)
@@ -182,8 +180,7 @@ static int ocrdma_register_device(struct ocrdma_dev *dev)
dev->ibdev.reg_user_mr = ocrdma_reg_user_mr;
dev->ibdev.alloc_mr = ocrdma_alloc_mr;
- dev->ibdev.alloc_fast_reg_page_list = ocrdma_alloc_frmr_page_list;
- dev->ibdev.free_fast_reg_page_list = ocrdma_free_frmr_page_list;
+ dev->ibdev.map_mr_sg = ocrdma_map_mr_sg;
/* mandatory to support user space verbs consumer. */
dev->ibdev.alloc_ucontext = ocrdma_alloc_ucontext;
@@ -325,9 +322,6 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
for (i = 0; i < ARRAY_SIZE(ocrdma_attributes); i++)
if (device_create_file(&dev->ibdev.dev, ocrdma_attributes[i]))
goto sysfs_err;
- spin_lock(&ocrdma_devlist_lock);
- list_add_tail_rcu(&dev->entry, &ocrdma_dev_list);
- spin_unlock(&ocrdma_devlist_lock);
/* Init stats */
ocrdma_add_port_stats(dev);
/* Interrupt Moderation */
@@ -356,9 +350,8 @@ idr_err:
return NULL;
}
-static void ocrdma_remove_free(struct rcu_head *rcu)
+static void ocrdma_remove_free(struct ocrdma_dev *dev)
{
- struct ocrdma_dev *dev = container_of(rcu, struct ocrdma_dev, rcu);
idr_remove(&ocrdma_dev_id, dev->id);
kfree(dev->mbx_cmd);
@@ -375,15 +368,9 @@ static void ocrdma_remove(struct ocrdma_dev *dev)
ib_unregister_device(&dev->ibdev);
ocrdma_rem_port_stats(dev);
-
- spin_lock(&ocrdma_devlist_lock);
- list_del_rcu(&dev->entry);
- spin_unlock(&ocrdma_devlist_lock);
-
ocrdma_free_resources(dev);
ocrdma_cleanup_hw(dev);
-
- call_rcu(&dev->rcu, ocrdma_remove_free);
+ ocrdma_remove_free(dev);
}
static int ocrdma_open(struct ocrdma_dev *dev)
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
index 69334e214571..86c303a620c1 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
@@ -855,9 +855,9 @@ void ocrdma_rem_port_stats(struct ocrdma_dev *dev)
{
if (!dev->dir)
return;
+ debugfs_remove(dev->dir);
mutex_destroy(&dev->stats_lock);
ocrdma_release_stats_mem(dev);
- debugfs_remove(dev->dir);
}
void ocrdma_init_debugfs(void)
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 1f3affb6a477..583001bcfb8f 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -73,7 +73,7 @@ int ocrdma_query_gid(struct ib_device *ibdev, u8 port,
if (index >= OCRDMA_MAX_SGID)
return -EINVAL;
- ret = ib_get_cached_gid(ibdev, port, index, sgid);
+ ret = ib_get_cached_gid(ibdev, port, index, sgid, NULL);
if (ret == -EAGAIN) {
memcpy(sgid, &zgid, sizeof(*sgid));
return 0;
@@ -1013,6 +1013,7 @@ int ocrdma_dereg_mr(struct ib_mr *ib_mr)
(void) ocrdma_mbx_dealloc_lkey(dev, mr->hwmr.fr_mr, mr->hwmr.lkey);
+ kfree(mr->pages);
ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr);
/* it could be user registered memory. */
@@ -1997,13 +1998,13 @@ static void ocrdma_build_ud_hdr(struct ocrdma_qp *qp,
{
struct ocrdma_ewqe_ud_hdr *ud_hdr =
(struct ocrdma_ewqe_ud_hdr *)(hdr + 1);
- struct ocrdma_ah *ah = get_ocrdma_ah(wr->wr.ud.ah);
+ struct ocrdma_ah *ah = get_ocrdma_ah(ud_wr(wr)->ah);
- ud_hdr->rsvd_dest_qpn = wr->wr.ud.remote_qpn;
+ ud_hdr->rsvd_dest_qpn = ud_wr(wr)->remote_qpn;
if (qp->qp_type == IB_QPT_GSI)
ud_hdr->qkey = qp->qkey;
else
- ud_hdr->qkey = wr->wr.ud.remote_qkey;
+ ud_hdr->qkey = ud_wr(wr)->remote_qkey;
ud_hdr->rsvd_ahid = ah->id;
if (ah->av->valid & OCRDMA_AV_VLAN_VALID)
hdr->cw |= (OCRDMA_FLAG_AH_VLAN_PR << OCRDMA_WQE_FLAGS_SHIFT);
@@ -2106,9 +2107,9 @@ static int ocrdma_build_write(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
status = ocrdma_build_inline_sges(qp, hdr, sge, wr, wqe_size);
if (status)
return status;
- ext_rw->addr_lo = wr->wr.rdma.remote_addr;
- ext_rw->addr_hi = upper_32_bits(wr->wr.rdma.remote_addr);
- ext_rw->lrkey = wr->wr.rdma.rkey;
+ ext_rw->addr_lo = rdma_wr(wr)->remote_addr;
+ ext_rw->addr_hi = upper_32_bits(rdma_wr(wr)->remote_addr);
+ ext_rw->lrkey = rdma_wr(wr)->rkey;
ext_rw->len = hdr->total_len;
return 0;
}
@@ -2126,46 +2127,12 @@ static void ocrdma_build_read(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
hdr->cw |= (OCRDMA_READ << OCRDMA_WQE_OPCODE_SHIFT);
hdr->cw |= (OCRDMA_TYPE_LKEY << OCRDMA_WQE_TYPE_SHIFT);
- ext_rw->addr_lo = wr->wr.rdma.remote_addr;
- ext_rw->addr_hi = upper_32_bits(wr->wr.rdma.remote_addr);
- ext_rw->lrkey = wr->wr.rdma.rkey;
+ ext_rw->addr_lo = rdma_wr(wr)->remote_addr;
+ ext_rw->addr_hi = upper_32_bits(rdma_wr(wr)->remote_addr);
+ ext_rw->lrkey = rdma_wr(wr)->rkey;
ext_rw->len = hdr->total_len;
}
-static void build_frmr_pbes(struct ib_send_wr *wr, struct ocrdma_pbl *pbl_tbl,
- struct ocrdma_hw_mr *hwmr)
-{
- int i;
- u64 buf_addr = 0;
- int num_pbes;
- struct ocrdma_pbe *pbe;
-
- pbe = (struct ocrdma_pbe *)pbl_tbl->va;
- num_pbes = 0;
-
- /* go through the OS phy regions & fill hw pbe entries into pbls. */
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
- /* number of pbes can be more for one OS buf, when
- * buffers are of different sizes.
- * split the ib_buf to one or more pbes.
- */
- buf_addr = wr->wr.fast_reg.page_list->page_list[i];
- pbe->pa_lo = cpu_to_le32((u32) (buf_addr & PAGE_MASK));
- pbe->pa_hi = cpu_to_le32((u32) upper_32_bits(buf_addr));
- num_pbes += 1;
- pbe++;
-
- /* if the pbl is full storing the pbes,
- * move to next pbl.
- */
- if (num_pbes == (hwmr->pbl_size/sizeof(u64))) {
- pbl_tbl++;
- pbe = (struct ocrdma_pbe *)pbl_tbl->va;
- }
- }
- return;
-}
-
static int get_encoded_page_size(int pg_sz)
{
/* Max size is 256M 4096 << 16 */
@@ -2176,48 +2143,59 @@ static int get_encoded_page_size(int pg_sz)
return i;
}
-
-static int ocrdma_build_fr(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
- struct ib_send_wr *wr)
+static int ocrdma_build_reg(struct ocrdma_qp *qp,
+ struct ocrdma_hdr_wqe *hdr,
+ struct ib_reg_wr *wr)
{
u64 fbo;
struct ocrdma_ewqe_fr *fast_reg = (struct ocrdma_ewqe_fr *)(hdr + 1);
- struct ocrdma_mr *mr;
- struct ocrdma_dev *dev = get_ocrdma_dev(qp->ibqp.device);
+ struct ocrdma_mr *mr = get_ocrdma_mr(wr->mr);
+ struct ocrdma_pbl *pbl_tbl = mr->hwmr.pbl_table;
+ struct ocrdma_pbe *pbe;
u32 wqe_size = sizeof(*fast_reg) + sizeof(*hdr);
+ int num_pbes = 0, i;
wqe_size = roundup(wqe_size, OCRDMA_WQE_ALIGN_BYTES);
- if (wr->wr.fast_reg.page_list_len > dev->attr.max_pages_per_frmr)
- return -EINVAL;
-
hdr->cw |= (OCRDMA_FR_MR << OCRDMA_WQE_OPCODE_SHIFT);
hdr->cw |= ((wqe_size / OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT);
- if (wr->wr.fast_reg.page_list_len == 0)
- BUG();
- if (wr->wr.fast_reg.access_flags & IB_ACCESS_LOCAL_WRITE)
+ if (wr->access & IB_ACCESS_LOCAL_WRITE)
hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_LOCAL_WR;
- if (wr->wr.fast_reg.access_flags & IB_ACCESS_REMOTE_WRITE)
+ if (wr->access & IB_ACCESS_REMOTE_WRITE)
hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_REMOTE_WR;
- if (wr->wr.fast_reg.access_flags & IB_ACCESS_REMOTE_READ)
+ if (wr->access & IB_ACCESS_REMOTE_READ)
hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_REMOTE_RD;
- hdr->lkey = wr->wr.fast_reg.rkey;
- hdr->total_len = wr->wr.fast_reg.length;
+ hdr->lkey = wr->key;
+ hdr->total_len = mr->ibmr.length;
- fbo = wr->wr.fast_reg.iova_start -
- (wr->wr.fast_reg.page_list->page_list[0] & PAGE_MASK);
+ fbo = mr->ibmr.iova - mr->pages[0];
- fast_reg->va_hi = upper_32_bits(wr->wr.fast_reg.iova_start);
- fast_reg->va_lo = (u32) (wr->wr.fast_reg.iova_start & 0xffffffff);
+ fast_reg->va_hi = upper_32_bits(mr->ibmr.iova);
+ fast_reg->va_lo = (u32) (mr->ibmr.iova & 0xffffffff);
fast_reg->fbo_hi = upper_32_bits(fbo);
fast_reg->fbo_lo = (u32) fbo & 0xffffffff;
- fast_reg->num_sges = wr->wr.fast_reg.page_list_len;
- fast_reg->size_sge =
- get_encoded_page_size(1 << wr->wr.fast_reg.page_shift);
- mr = (struct ocrdma_mr *) (unsigned long)
- dev->stag_arr[(hdr->lkey >> 8) & (OCRDMA_MAX_STAG - 1)];
- build_frmr_pbes(wr, mr->hwmr.pbl_table, &mr->hwmr);
+ fast_reg->num_sges = mr->npages;
+ fast_reg->size_sge = get_encoded_page_size(mr->ibmr.page_size);
+
+ pbe = pbl_tbl->va;
+ for (i = 0; i < mr->npages; i++) {
+ u64 buf_addr = mr->pages[i];
+
+ pbe->pa_lo = cpu_to_le32((u32) (buf_addr & PAGE_MASK));
+ pbe->pa_hi = cpu_to_le32((u32) upper_32_bits(buf_addr));
+ num_pbes += 1;
+ pbe++;
+
+ /* if the pbl is full storing the pbes,
+ * move to next pbl.
+ */
+ if (num_pbes == (mr->hwmr.pbl_size/sizeof(u64))) {
+ pbl_tbl++;
+ pbe = (struct ocrdma_pbe *)pbl_tbl->va;
+ }
+ }
+
return 0;
}
@@ -2300,8 +2278,8 @@ int ocrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT;
hdr->lkey = wr->ex.invalidate_rkey;
break;
- case IB_WR_FAST_REG_MR:
- status = ocrdma_build_fr(qp, hdr, wr);
+ case IB_WR_REG_MR:
+ status = ocrdma_build_reg(qp, hdr, reg_wr(wr));
break;
default:
status = -EINVAL;
@@ -2567,7 +2545,7 @@ static void ocrdma_update_wc(struct ocrdma_qp *qp, struct ib_wc *ibwc,
ibwc->opcode = IB_WC_SEND;
break;
case OCRDMA_FR_MR:
- ibwc->opcode = IB_WC_FAST_REG_MR;
+ ibwc->opcode = IB_WC_REG_MR;
break;
case OCRDMA_LKEY_INV:
ibwc->opcode = IB_WC_LOCAL_INV;
@@ -2933,16 +2911,11 @@ expand_cqe:
}
stop_cqe:
cq->getp = cur_getp;
- if (cq->deferred_arm) {
- ocrdma_ring_cq_db(dev, cq->id, true, cq->deferred_sol,
- polled_hw_cqes);
+ if (cq->deferred_arm || polled_hw_cqes) {
+ ocrdma_ring_cq_db(dev, cq->id, cq->deferred_arm,
+ cq->deferred_sol, polled_hw_cqes);
cq->deferred_arm = false;
cq->deferred_sol = false;
- } else {
- /* We need to pop the CQE. No need to arm */
- ocrdma_ring_cq_db(dev, cq->id, false, cq->deferred_sol,
- polled_hw_cqes);
- cq->deferred_sol = false;
}
return i;
@@ -3058,6 +3031,12 @@ struct ib_mr *ocrdma_alloc_mr(struct ib_pd *ibpd,
if (!mr)
return ERR_PTR(-ENOMEM);
+ mr->pages = kcalloc(max_num_sg, sizeof(u64), GFP_KERNEL);
+ if (!mr->pages) {
+ status = -ENOMEM;
+ goto pl_err;
+ }
+
status = ocrdma_get_pbl_info(dev, mr, max_num_sg);
if (status)
goto pbl_err;
@@ -3081,30 +3060,12 @@ struct ib_mr *ocrdma_alloc_mr(struct ib_pd *ibpd,
mbx_err:
ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr);
pbl_err:
+ kfree(mr->pages);
+pl_err:
kfree(mr);
return ERR_PTR(-ENOMEM);
}
-struct ib_fast_reg_page_list *ocrdma_alloc_frmr_page_list(struct ib_device
- *ibdev,
- int page_list_len)
-{
- struct ib_fast_reg_page_list *frmr_list;
- int size;
-
- size = sizeof(*frmr_list) + (page_list_len * sizeof(u64));
- frmr_list = kzalloc(size, GFP_KERNEL);
- if (!frmr_list)
- return ERR_PTR(-ENOMEM);
- frmr_list->page_list = (u64 *)(frmr_list + 1);
- return frmr_list;
-}
-
-void ocrdma_free_frmr_page_list(struct ib_fast_reg_page_list *page_list)
-{
- kfree(page_list);
-}
-
#define MAX_KERNEL_PBE_SIZE 65536
static inline int count_kernel_pbes(struct ib_phys_buf *buf_list,
int buf_cnt, u32 *pbe_size)
@@ -3267,3 +3228,26 @@ pbl_err:
kfree(mr);
return ERR_PTR(status);
}
+
+static int ocrdma_set_page(struct ib_mr *ibmr, u64 addr)
+{
+ struct ocrdma_mr *mr = get_ocrdma_mr(ibmr);
+
+ if (unlikely(mr->npages == mr->hwmr.num_pbes))
+ return -ENOMEM;
+
+ mr->pages[mr->npages++] = addr;
+
+ return 0;
+}
+
+int ocrdma_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
+{
+ struct ocrdma_mr *mr = get_ocrdma_mr(ibmr);
+
+ mr->npages = 0;
+
+ return ib_sg_to_pages(ibmr, sg, sg_nents, ocrdma_set_page);
+}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index 308c16857a5d..a2f3b4dc20b0 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -125,9 +125,8 @@ struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length,
struct ib_mr *ocrdma_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_num_sg);
-struct ib_fast_reg_page_list *ocrdma_alloc_frmr_page_list(struct ib_device
- *ibdev,
- int page_list_len);
-void ocrdma_free_frmr_page_list(struct ib_fast_reg_page_list *page_list);
+int ocrdma_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents);
#endif /* __OCRDMA_VERBS_H__ */
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 7e00470adc30..4ff340fe904f 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1680,7 +1680,7 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd)
* heavy filesystem activity makes these fail, and we can
* use compound pages.
*/
- gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP;
+ gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP;
egrcnt = rcd->rcvegrcnt;
egroff = rcd->rcvegr_tid_base;
diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c
index 5afaa218508d..d725c565518d 100644
--- a/drivers/infiniband/hw/qib/qib_keys.c
+++ b/drivers/infiniband/hw/qib/qib_keys.c
@@ -336,14 +336,15 @@ bail:
}
/*
- * Initialize the memory region specified by the work reqeust.
+ * Initialize the memory region specified by the work request.
*/
-int qib_fast_reg_mr(struct qib_qp *qp, struct ib_send_wr *wr)
+int qib_reg_mr(struct qib_qp *qp, struct ib_reg_wr *wr)
{
struct qib_lkey_table *rkt = &to_idev(qp->ibqp.device)->lk_table;
struct qib_pd *pd = to_ipd(qp->ibqp.pd);
- struct qib_mregion *mr;
- u32 rkey = wr->wr.fast_reg.rkey;
+ struct qib_mr *mr = to_imr(wr->mr);
+ struct qib_mregion *mrg;
+ u32 key = wr->key;
unsigned i, n, m;
int ret = -EINVAL;
unsigned long flags;
@@ -351,33 +352,33 @@ int qib_fast_reg_mr(struct qib_qp *qp, struct ib_send_wr *wr)
size_t ps;
spin_lock_irqsave(&rkt->lock, flags);
- if (pd->user || rkey == 0)
+ if (pd->user || key == 0)
goto bail;
- mr = rcu_dereference_protected(
- rkt->table[(rkey >> (32 - ib_qib_lkey_table_size))],
+ mrg = rcu_dereference_protected(
+ rkt->table[(key >> (32 - ib_qib_lkey_table_size))],
lockdep_is_held(&rkt->lock));
- if (unlikely(mr == NULL || qp->ibqp.pd != mr->pd))
+ if (unlikely(mrg == NULL || qp->ibqp.pd != mrg->pd))
goto bail;
- if (wr->wr.fast_reg.page_list_len > mr->max_segs)
+ if (mr->npages > mrg->max_segs)
goto bail;
- ps = 1UL << wr->wr.fast_reg.page_shift;
- if (wr->wr.fast_reg.length > ps * wr->wr.fast_reg.page_list_len)
+ ps = mr->ibmr.page_size;
+ if (mr->ibmr.length > ps * mr->npages)
goto bail;
- mr->user_base = wr->wr.fast_reg.iova_start;
- mr->iova = wr->wr.fast_reg.iova_start;
- mr->lkey = rkey;
- mr->length = wr->wr.fast_reg.length;
- mr->access_flags = wr->wr.fast_reg.access_flags;
- page_list = wr->wr.fast_reg.page_list->page_list;
+ mrg->user_base = mr->ibmr.iova;
+ mrg->iova = mr->ibmr.iova;
+ mrg->lkey = key;
+ mrg->length = mr->ibmr.length;
+ mrg->access_flags = wr->access;
+ page_list = mr->pages;
m = 0;
n = 0;
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
- mr->map[m]->segs[n].vaddr = (void *) page_list[i];
- mr->map[m]->segs[n].length = ps;
+ for (i = 0; i < mr->npages; i++) {
+ mrg->map[m]->segs[n].vaddr = (void *) page_list[i];
+ mrg->map[m]->segs[n].length = ps;
if (++n == QIB_SEGSZ) {
m++;
n = 0;
diff --git a/drivers/infiniband/hw/qib/qib_mr.c b/drivers/infiniband/hw/qib/qib_mr.c
index 19220dcb9a3b..294f5c706be9 100644
--- a/drivers/infiniband/hw/qib/qib_mr.c
+++ b/drivers/infiniband/hw/qib/qib_mr.c
@@ -303,6 +303,7 @@ int qib_dereg_mr(struct ib_mr *ibmr)
int ret = 0;
unsigned long timeout;
+ kfree(mr->pages);
qib_free_lkey(&mr->mr);
qib_put_mr(&mr->mr); /* will set completion if last */
@@ -323,7 +324,7 @@ out:
/*
* Allocate a memory region usable with the
- * IB_WR_FAST_REG_MR send work request.
+ * IB_WR_REG_MR send work request.
*
* Return the memory region on success, otherwise return an errno.
*/
@@ -340,37 +341,38 @@ struct ib_mr *qib_alloc_mr(struct ib_pd *pd,
if (IS_ERR(mr))
return (struct ib_mr *)mr;
+ mr->pages = kcalloc(max_num_sg, sizeof(u64), GFP_KERNEL);
+ if (!mr->pages)
+ goto err;
+
return &mr->ibmr;
+
+err:
+ qib_dereg_mr(&mr->ibmr);
+ return ERR_PTR(-ENOMEM);
}
-struct ib_fast_reg_page_list *
-qib_alloc_fast_reg_page_list(struct ib_device *ibdev, int page_list_len)
+static int qib_set_page(struct ib_mr *ibmr, u64 addr)
{
- unsigned size = page_list_len * sizeof(u64);
- struct ib_fast_reg_page_list *pl;
-
- if (size > PAGE_SIZE)
- return ERR_PTR(-EINVAL);
-
- pl = kzalloc(sizeof(*pl), GFP_KERNEL);
- if (!pl)
- return ERR_PTR(-ENOMEM);
+ struct qib_mr *mr = to_imr(ibmr);
- pl->page_list = kzalloc(size, GFP_KERNEL);
- if (!pl->page_list)
- goto err_free;
+ if (unlikely(mr->npages == mr->mr.max_segs))
+ return -ENOMEM;
- return pl;
+ mr->pages[mr->npages++] = addr;
-err_free:
- kfree(pl);
- return ERR_PTR(-ENOMEM);
+ return 0;
}
-void qib_free_fast_reg_page_list(struct ib_fast_reg_page_list *pl)
+int qib_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents)
{
- kfree(pl->page_list);
- kfree(pl);
+ struct qib_mr *mr = to_imr(ibmr);
+
+ mr->npages = 0;
+
+ return ib_sg_to_pages(ibmr, sg, sg_nents, qib_set_page);
}
/**
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 4fa88ba2963e..40f85bb3e0d3 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -436,7 +436,7 @@ static void clear_mr_refs(struct qib_qp *qp, int clr_sends)
if (qp->ibqp.qp_type == IB_QPT_UD ||
qp->ibqp.qp_type == IB_QPT_SMI ||
qp->ibqp.qp_type == IB_QPT_GSI)
- atomic_dec(&to_iah(wqe->wr.wr.ud.ah)->refcount);
+ atomic_dec(&to_iah(wqe->ud_wr.ah)->refcount);
if (++qp->s_last >= qp->s_size)
qp->s_last = 0;
}
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index 4544d6f88ad7..e6b7556d5221 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -373,10 +373,11 @@ int qib_make_rc_req(struct qib_qp *qp)
qp->s_flags |= QIB_S_WAIT_SSN_CREDIT;
goto bail;
}
+
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
hwords += sizeof(struct ib_reth) / sizeof(u32);
wqe->lpsn = wqe->psn;
@@ -386,15 +387,15 @@ int qib_make_rc_req(struct qib_qp *qp)
len = pmtu;
break;
}
- if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ if (wqe->rdma_wr.wr.opcode == IB_WR_RDMA_WRITE)
qp->s_state = OP(RDMA_WRITE_ONLY);
else {
- qp->s_state =
- OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ qp->s_state = OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
/* Immediate data comes after RETH */
- ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;
+ ohdr->u.rc.imm_data =
+ wqe->rdma_wr.wr.ex.imm_data;
hwords += 1;
- if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ if (wqe->rdma_wr.wr.send_flags & IB_SEND_SOLICITED)
bth0 |= IB_BTH_SOLICITED;
}
bth2 |= IB_BTH_REQ_ACK;
@@ -424,10 +425,11 @@ int qib_make_rc_req(struct qib_qp *qp)
qp->s_next_psn += (len - 1) / pmtu;
wqe->lpsn = qp->s_next_psn++;
}
+
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
qp->s_state = OP(RDMA_READ_REQUEST);
hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32);
@@ -455,24 +457,24 @@ int qib_make_rc_req(struct qib_qp *qp)
qp->s_lsn++;
wqe->lpsn = wqe->psn;
}
- if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
+ if (wqe->atomic_wr.wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
qp->s_state = OP(COMPARE_SWAP);
ohdr->u.atomic_eth.swap_data = cpu_to_be64(
- wqe->wr.wr.atomic.swap);
+ wqe->atomic_wr.swap);
ohdr->u.atomic_eth.compare_data = cpu_to_be64(
- wqe->wr.wr.atomic.compare_add);
+ wqe->atomic_wr.compare_add);
} else {
qp->s_state = OP(FETCH_ADD);
ohdr->u.atomic_eth.swap_data = cpu_to_be64(
- wqe->wr.wr.atomic.compare_add);
+ wqe->atomic_wr.compare_add);
ohdr->u.atomic_eth.compare_data = 0;
}
ohdr->u.atomic_eth.vaddr[0] = cpu_to_be32(
- wqe->wr.wr.atomic.remote_addr >> 32);
+ wqe->atomic_wr.remote_addr >> 32);
ohdr->u.atomic_eth.vaddr[1] = cpu_to_be32(
- wqe->wr.wr.atomic.remote_addr);
+ wqe->atomic_wr.remote_addr);
ohdr->u.atomic_eth.rkey = cpu_to_be32(
- wqe->wr.wr.atomic.rkey);
+ wqe->atomic_wr.rkey);
hwords += sizeof(struct ib_atomic_eth) / sizeof(u32);
ss = NULL;
len = 0;
@@ -597,9 +599,9 @@ int qib_make_rc_req(struct qib_qp *qp)
*/
len = ((qp->s_psn - wqe->psn) & QIB_PSN_MASK) * pmtu;
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len);
+ cpu_to_be64(wqe->rdma_wr.remote_addr + len);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(wqe->length - len);
qp->s_state = OP(RDMA_READ_REQUEST);
hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32);
diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index 22e356ca8058..b1aa21bdd484 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -459,8 +459,8 @@ again:
if (wqe->length == 0)
break;
if (unlikely(!qib_rkey_ok(qp, &qp->r_sge.sge, wqe->length,
- wqe->wr.wr.rdma.remote_addr,
- wqe->wr.wr.rdma.rkey,
+ wqe->rdma_wr.remote_addr,
+ wqe->rdma_wr.rkey,
IB_ACCESS_REMOTE_WRITE)))
goto acc_err;
qp->r_sge.sg_list = NULL;
@@ -472,8 +472,8 @@ again:
if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
goto inv_err;
if (unlikely(!qib_rkey_ok(qp, &sqp->s_sge.sge, wqe->length,
- wqe->wr.wr.rdma.remote_addr,
- wqe->wr.wr.rdma.rkey,
+ wqe->rdma_wr.remote_addr,
+ wqe->rdma_wr.rkey,
IB_ACCESS_REMOTE_READ)))
goto acc_err;
release = 0;
@@ -490,18 +490,18 @@ again:
if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC)))
goto inv_err;
if (unlikely(!qib_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64),
- wqe->wr.wr.atomic.remote_addr,
- wqe->wr.wr.atomic.rkey,
+ wqe->atomic_wr.remote_addr,
+ wqe->atomic_wr.rkey,
IB_ACCESS_REMOTE_ATOMIC)))
goto acc_err;
/* Perform atomic OP and save result. */
maddr = (atomic64_t *) qp->r_sge.sge.vaddr;
- sdata = wqe->wr.wr.atomic.compare_add;
+ sdata = wqe->atomic_wr.compare_add;
*(u64 *) sqp->s_sge.sge.vaddr =
- (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ?
+ (wqe->atomic_wr.wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ?
(u64) atomic64_add_return(sdata, maddr) - sdata :
(u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr,
- sdata, wqe->wr.wr.atomic.swap);
+ sdata, wqe->atomic_wr.swap);
qib_put_mr(qp->r_sge.sge.mr);
qp->r_sge.num_sge = 0;
goto send_comp;
@@ -785,7 +785,7 @@ void qib_send_complete(struct qib_qp *qp, struct qib_swqe *wqe,
if (qp->ibqp.qp_type == IB_QPT_UD ||
qp->ibqp.qp_type == IB_QPT_SMI ||
qp->ibqp.qp_type == IB_QPT_GSI)
- atomic_dec(&to_iah(wqe->wr.wr.ud.ah)->refcount);
+ atomic_dec(&to_iah(wqe->ud_wr.ah)->refcount);
/* See ch. 11.2.4.1 and 10.7.3.1 */
if (!(qp->s_flags & QIB_S_SIGNAL_REQ_WR) ||
diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c
index aa3a8035bb68..06a564589c35 100644
--- a/drivers/infiniband/hw/qib/qib_uc.c
+++ b/drivers/infiniband/hw/qib/qib_uc.c
@@ -129,9 +129,9 @@ int qib_make_uc_req(struct qib_qp *qp)
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
hwords += sizeof(struct ib_reth) / 4;
if (len > pmtu) {
diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c
index 26243b722b5e..59193f67ea78 100644
--- a/drivers/infiniband/hw/qib/qib_ud.c
+++ b/drivers/infiniband/hw/qib/qib_ud.c
@@ -59,7 +59,7 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe)
u32 length;
enum ib_qp_type sqptype, dqptype;
- qp = qib_lookup_qpn(ibp, swqe->wr.wr.ud.remote_qpn);
+ qp = qib_lookup_qpn(ibp, swqe->ud_wr.remote_qpn);
if (!qp) {
ibp->n_pkt_drops++;
return;
@@ -76,7 +76,7 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe)
goto drop;
}
- ah_attr = &to_iah(swqe->wr.wr.ud.ah)->attr;
+ ah_attr = &to_iah(swqe->ud_wr.ah)->attr;
ppd = ppd_from_ibp(ibp);
if (qp->ibqp.qp_num > 1) {
@@ -106,8 +106,8 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe)
if (qp->ibqp.qp_num) {
u32 qkey;
- qkey = (int)swqe->wr.wr.ud.remote_qkey < 0 ?
- sqp->qkey : swqe->wr.wr.ud.remote_qkey;
+ qkey = (int)swqe->ud_wr.remote_qkey < 0 ?
+ sqp->qkey : swqe->ud_wr.remote_qkey;
if (unlikely(qkey != qp->qkey)) {
u16 lid;
@@ -210,7 +210,7 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe)
wc.qp = &qp->ibqp;
wc.src_qp = sqp->ibqp.qp_num;
wc.pkey_index = qp->ibqp.qp_type == IB_QPT_GSI ?
- swqe->wr.wr.ud.pkey_index : 0;
+ swqe->ud_wr.pkey_index : 0;
wc.slid = ppd->lid | (ah_attr->src_path_bits & ((1 << ppd->lmc) - 1));
wc.sl = ah_attr->sl;
wc.dlid_path_bits = ah_attr->dlid & ((1 << ppd->lmc) - 1);
@@ -277,7 +277,7 @@ int qib_make_ud_req(struct qib_qp *qp)
/* Construct the header. */
ibp = to_iport(qp->ibqp.device, qp->port_num);
ppd = ppd_from_ibp(ibp);
- ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr;
+ ah_attr = &to_iah(wqe->ud_wr.ah)->attr;
if (ah_attr->dlid >= QIB_MULTICAST_LID_BASE) {
if (ah_attr->dlid != QIB_PERMISSIVE_LID)
this_cpu_inc(ibp->pmastats->n_multicast_xmit);
@@ -363,7 +363,7 @@ int qib_make_ud_req(struct qib_qp *qp)
bth0 |= extra_bytes << 20;
bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? QIB_DEFAULT_P_KEY :
qib_get_pkey(ibp, qp->ibqp.qp_type == IB_QPT_GSI ?
- wqe->wr.wr.ud.pkey_index : qp->s_pkey_index);
+ wqe->ud_wr.pkey_index : qp->s_pkey_index);
ohdr->bth[0] = cpu_to_be32(bth0);
/*
* Use the multicast QP if the destination LID is a multicast LID.
@@ -371,14 +371,14 @@ int qib_make_ud_req(struct qib_qp *qp)
ohdr->bth[1] = ah_attr->dlid >= QIB_MULTICAST_LID_BASE &&
ah_attr->dlid != QIB_PERMISSIVE_LID ?
cpu_to_be32(QIB_MULTICAST_QPN) :
- cpu_to_be32(wqe->wr.wr.ud.remote_qpn);
+ cpu_to_be32(wqe->ud_wr.remote_qpn);
ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & QIB_PSN_MASK);
/*
* Qkeys with the high order bit set mean use the
* qkey from the QP context instead of the WR (see 10.2.5).
*/
- ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->wr.wr.ud.remote_qkey < 0 ?
- qp->qkey : wqe->wr.wr.ud.remote_qkey);
+ ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->ud_wr.remote_qkey < 0 ?
+ qp->qkey : wqe->ud_wr.remote_qkey);
ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
done:
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index 3dcc4985b60f..de6cb6fcda8d 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -362,8 +362,8 @@ static int qib_post_one_send(struct qib_qp *qp, struct ib_send_wr *wr,
* undefined operations.
* Make sure buffer is large enough to hold the result for atomics.
*/
- if (wr->opcode == IB_WR_FAST_REG_MR) {
- if (qib_fast_reg_mr(qp, wr))
+ if (wr->opcode == IB_WR_REG_MR) {
+ if (qib_reg_mr(qp, reg_wr(wr)))
goto bail_inval;
} else if (qp->ibqp.qp_type == IB_QPT_UC) {
if ((unsigned) wr->opcode >= IB_WR_RDMA_READ)
@@ -374,7 +374,7 @@ static int qib_post_one_send(struct qib_qp *qp, struct ib_send_wr *wr,
wr->opcode != IB_WR_SEND_WITH_IMM)
goto bail_inval;
/* Check UD destination address PD */
- if (qp->ibqp.pd != wr->wr.ud.ah->pd)
+ if (qp->ibqp.pd != ud_wr(wr)->ah->pd)
goto bail_inval;
} else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD)
goto bail_inval;
@@ -397,7 +397,23 @@ static int qib_post_one_send(struct qib_qp *qp, struct ib_send_wr *wr,
rkt = &to_idev(qp->ibqp.device)->lk_table;
pd = to_ipd(qp->ibqp.pd);
wqe = get_swqe_ptr(qp, qp->s_head);
- wqe->wr = *wr;
+
+ if (qp->ibqp.qp_type != IB_QPT_UC &&
+ qp->ibqp.qp_type != IB_QPT_RC)
+ memcpy(&wqe->ud_wr, ud_wr(wr), sizeof(wqe->ud_wr));
+ else if (wr->opcode == IB_WR_REG_MR)
+ memcpy(&wqe->reg_wr, reg_wr(wr),
+ sizeof(wqe->reg_wr));
+ else if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE ||
+ wr->opcode == IB_WR_RDMA_READ)
+ memcpy(&wqe->rdma_wr, rdma_wr(wr), sizeof(wqe->rdma_wr));
+ else if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+ wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+ memcpy(&wqe->atomic_wr, atomic_wr(wr), sizeof(wqe->atomic_wr));
+ else
+ memcpy(&wqe->wr, wr, sizeof(wqe->wr));
+
wqe->length = 0;
j = 0;
if (wr->num_sge) {
@@ -426,7 +442,7 @@ static int qib_post_one_send(struct qib_qp *qp, struct ib_send_wr *wr,
qp->port_num - 1)->ibmtu)
goto bail_inval_free;
else
- atomic_inc(&to_iah(wr->wr.ud.ah)->refcount);
+ atomic_inc(&to_iah(ud_wr(wr)->ah)->refcount);
wqe->ssn = qp->s_ssn++;
qp->s_head = next;
@@ -2244,8 +2260,7 @@ int qib_register_ib_device(struct qib_devdata *dd)
ibdev->reg_user_mr = qib_reg_user_mr;
ibdev->dereg_mr = qib_dereg_mr;
ibdev->alloc_mr = qib_alloc_mr;
- ibdev->alloc_fast_reg_page_list = qib_alloc_fast_reg_page_list;
- ibdev->free_fast_reg_page_list = qib_free_fast_reg_page_list;
+ ibdev->map_mr_sg = qib_map_mr_sg;
ibdev->alloc_fmr = qib_alloc_fmr;
ibdev->map_phys_fmr = qib_map_phys_fmr;
ibdev->unmap_fmr = qib_unmap_fmr;
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index a08df70e8503..2baf5ad251ed 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -330,6 +330,8 @@ struct qib_mr {
struct ib_mr ibmr;
struct ib_umem *umem;
struct qib_mregion mr; /* must be last */
+ u64 *pages;
+ u32 npages;
};
/*
@@ -338,7 +340,13 @@ struct qib_mr {
* in qp->s_max_sge.
*/
struct qib_swqe {
- struct ib_send_wr wr; /* don't use wr.sg_list */
+ union {
+ struct ib_send_wr wr; /* don't use wr.sg_list */
+ struct ib_ud_wr ud_wr;
+ struct ib_reg_wr reg_wr;
+ struct ib_rdma_wr rdma_wr;
+ struct ib_atomic_wr atomic_wr;
+ };
u32 psn; /* first packet sequence number */
u32 lpsn; /* last packet sequence number */
u32 ssn; /* send sequence number */
@@ -1038,12 +1046,11 @@ struct ib_mr *qib_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_entries);
-struct ib_fast_reg_page_list *qib_alloc_fast_reg_page_list(
- struct ib_device *ibdev, int page_list_len);
-
-void qib_free_fast_reg_page_list(struct ib_fast_reg_page_list *pl);
+int qib_map_mr_sg(struct ib_mr *ibmr,
+ struct scatterlist *sg,
+ int sg_nents);
-int qib_fast_reg_mr(struct qib_qp *qp, struct ib_send_wr *wr);
+int qib_reg_mr(struct qib_qp *qp, struct ib_reg_wr *wr);
struct ib_fmr *qib_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
struct ib_fmr_attr *fmr_attr);
diff --git a/drivers/infiniband/hw/usnic/usnic.h b/drivers/infiniband/hw/usnic/usnic.h
index 5be13d8991bc..f903502d3883 100644
--- a/drivers/infiniband/hw/usnic/usnic.h
+++ b/drivers/infiniband/hw/usnic/usnic.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_abi.h b/drivers/infiniband/hw/usnic/usnic_abi.h
index 04a66229584e..7fe9502ce8d3 100644
--- a/drivers/infiniband/hw/usnic/usnic_abi.h
+++ b/drivers/infiniband/hw/usnic/usnic_abi.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h b/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
index 393567266142..596e0ed49a8e 100644
--- a/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
+++ b/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_common_util.h b/drivers/infiniband/hw/usnic/usnic_common_util.h
index 9d737ed5e55d..b54986de5f0c 100644
--- a/drivers/infiniband/hw/usnic/usnic_common_util.h
+++ b/drivers/infiniband/hw/usnic/usnic_common_util.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_debugfs.c b/drivers/infiniband/hw/usnic/usnic_debugfs.c
index 5d13860161a4..5e55b8bc6fe4 100644
--- a/drivers/infiniband/hw/usnic/usnic_debugfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_debugfs.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_debugfs.h b/drivers/infiniband/hw/usnic/usnic_debugfs.h
index 4087d24a88f6..98453e91daa6 100644
--- a/drivers/infiniband/hw/usnic/usnic_debugfs.h
+++ b/drivers/infiniband/hw/usnic/usnic_debugfs.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.c b/drivers/infiniband/hw/usnic/usnic_fwd.c
index e3c9bd9d3ba3..3c37dd59c04e 100644
--- a/drivers/infiniband/hw/usnic/usnic_fwd.c
+++ b/drivers/infiniband/hw/usnic/usnic_fwd.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.h b/drivers/infiniband/hw/usnic/usnic_fwd.h
index 93713a2230b3..3a8add9ddf46 100644
--- a/drivers/infiniband/hw/usnic/usnic_fwd.h
+++ b/drivers/infiniband/hw/usnic/usnic_fwd.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_ib.h b/drivers/infiniband/hw/usnic/usnic_ib.h
index e5a9297dd1bd..525bf272671e 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index 34c49b8105fe..565c881a44ba 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
@@ -328,16 +343,15 @@ static void *usnic_ib_device_add(struct pci_dev *dev)
netdev = pci_get_drvdata(dev);
us_ibdev = (struct usnic_ib_dev *)ib_alloc_device(sizeof(*us_ibdev));
- if (IS_ERR_OR_NULL(us_ibdev)) {
+ if (!us_ibdev) {
usnic_err("Device %s context alloc failed\n",
netdev_name(pci_get_drvdata(dev)));
- return ERR_PTR(us_ibdev ? PTR_ERR(us_ibdev) : -EFAULT);
+ return ERR_PTR(-EFAULT);
}
us_ibdev->ufdev = usnic_fwd_dev_alloc(dev);
- if (IS_ERR_OR_NULL(us_ibdev->ufdev)) {
- usnic_err("Failed to alloc ufdev for %s with err %ld\n",
- pci_name(dev), PTR_ERR(us_ibdev->ufdev));
+ if (!us_ibdev->ufdev) {
+ usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev));
goto err_dealloc;
}
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
index db3588df3546..fcea3a24d3eb 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
@@ -221,8 +236,8 @@ create_roce_custom_flow(struct usnic_ib_qp_grp *qp_grp,
/* Create Flow Handle */
qp_flow = kzalloc(sizeof(*qp_flow), GFP_ATOMIC);
- if (IS_ERR_OR_NULL(qp_flow)) {
- err = qp_flow ? PTR_ERR(qp_flow) : -ENOMEM;
+ if (!qp_flow) {
+ err = -ENOMEM;
goto out_dealloc_flow;
}
qp_flow->flow = flow;
@@ -296,8 +311,8 @@ create_udp_flow(struct usnic_ib_qp_grp *qp_grp,
/* Create qp_flow */
qp_flow = kzalloc(sizeof(*qp_flow), GFP_ATOMIC);
- if (IS_ERR_OR_NULL(qp_flow)) {
- err = qp_flow ? PTR_ERR(qp_flow) : -ENOMEM;
+ if (!qp_flow) {
+ err = -ENOMEM;
goto out_dealloc_flow;
}
qp_flow->flow = flow;
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
index b0aafe8db0c3..b1458be1d402 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index 27dc67c1689f..3412ea06116e 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
index 0d09b493cd02..3d98e16cfeaf 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 7df43827cb29..f8e3211689a3 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
index 0bd04efa16f3..414eaa566bd9 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_log.h b/drivers/infiniband/hw/usnic/usnic_log.h
index 75777a66c684..183fcb6a952f 100644
--- a/drivers/infiniband/hw/usnic/usnic_log.h
+++ b/drivers/infiniband/hw/usnic/usnic_log.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_transport.c b/drivers/infiniband/hw/usnic/usnic_transport.c
index ddef6f77a78c..de318389a301 100644
--- a/drivers/infiniband/hw/usnic/usnic_transport.c
+++ b/drivers/infiniband/hw/usnic/usnic_transport.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_transport.h b/drivers/infiniband/hw/usnic/usnic_transport.h
index 7e5dc6d9f462..9a7a2d9755c0 100644
--- a/drivers/infiniband/hw/usnic/usnic_transport.h
+++ b/drivers/infiniband/hw/usnic/usnic_transport.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
index cb2337f0532b..645a5f6e6c88 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -7,7 +7,7 @@
* 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:
+ * BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.h b/drivers/infiniband/hw/usnic/usnic_uiom.h
index 70440996e8f2..45ca7c1613a7 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.h
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
index 3a4288e0fbac..42b4b4c4e452 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2014, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
index d4f752e258fd..c0b0b876ab90 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
+++ b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.c b/drivers/infiniband/hw/usnic/usnic_vnic.c
index 656b88c39eda..66de93fb8ea9 100644
--- a/drivers/infiniband/hw/usnic/usnic_vnic.c
+++ b/drivers/infiniband/hw/usnic/usnic_vnic.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.h b/drivers/infiniband/hw/usnic/usnic_vnic.h
index 14d931a8829d..a08423e478af 100644
--- a/drivers/infiniband/hw/usnic/usnic_vnic.h
+++ b/drivers/infiniband/hw/usnic/usnic_vnic.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 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
+ * 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
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 4cd5428a2399..3ede10309754 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -360,7 +360,7 @@ struct ipoib_dev_priv {
unsigned tx_head;
unsigned tx_tail;
struct ib_sge tx_sge[MAX_SKB_FRAGS + 1];
- struct ib_send_wr tx_wr;
+ struct ib_ud_wr tx_wr;
unsigned tx_outstanding;
struct ib_wc send_wc[MAX_SEND_CQE];
@@ -495,6 +495,7 @@ void ipoib_dev_cleanup(struct net_device *dev);
void ipoib_mcast_join_task(struct work_struct *work);
void ipoib_mcast_carrier_on_task(struct work_struct *work);
void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb);
+void ipoib_mcast_free(struct ipoib_mcast *mc);
void ipoib_mcast_restart_task(struct work_struct *work);
int ipoib_mcast_start_thread(struct net_device *dev);
@@ -527,7 +528,7 @@ static inline void ipoib_build_sge(struct ipoib_dev_priv *priv,
priv->tx_sge[i + off].addr = mapping[i + off];
priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
}
- priv->tx_wr.num_sge = nr_frags + off;
+ priv->tx_wr.wr.num_sge = nr_frags + off;
}
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index c78dc1638030..3ae9726efb98 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -700,9 +700,9 @@ static inline int post_send(struct ipoib_dev_priv *priv,
ipoib_build_sge(priv, tx_req);
- priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM;
+ priv->tx_wr.wr.wr_id = wr_id | IPOIB_OP_CM;
- return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr);
+ return ib_post_send(tx->qp, &priv->tx_wr.wr, &bad_wr);
}
void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index d266667ca9b8..5ea0c14070d1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -518,19 +518,19 @@ static inline int post_send(struct ipoib_dev_priv *priv,
ipoib_build_sge(priv, tx_req);
- priv->tx_wr.wr_id = wr_id;
- priv->tx_wr.wr.ud.remote_qpn = qpn;
- priv->tx_wr.wr.ud.ah = address;
+ priv->tx_wr.wr.wr_id = wr_id;
+ priv->tx_wr.remote_qpn = qpn;
+ priv->tx_wr.ah = address;
if (head) {
- priv->tx_wr.wr.ud.mss = skb_shinfo(skb)->gso_size;
- priv->tx_wr.wr.ud.header = head;
- priv->tx_wr.wr.ud.hlen = hlen;
- priv->tx_wr.opcode = IB_WR_LSO;
+ priv->tx_wr.mss = skb_shinfo(skb)->gso_size;
+ priv->tx_wr.header = head;
+ priv->tx_wr.hlen = hlen;
+ priv->tx_wr.wr.opcode = IB_WR_LSO;
} else
- priv->tx_wr.opcode = IB_WR_SEND;
+ priv->tx_wr.wr.opcode = IB_WR_SEND;
- return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr);
+ return ib_post_send(priv->qp, &priv->tx_wr.wr, &bad_wr);
}
void ipoib_send(struct net_device *dev, struct sk_buff *skb,
@@ -583,9 +583,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
}
if (skb->ip_summed == CHECKSUM_PARTIAL)
- priv->tx_wr.send_flags |= IB_SEND_IP_CSUM;
+ priv->tx_wr.wr.send_flags |= IB_SEND_IP_CSUM;
else
- priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
+ priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
if (++priv->tx_outstanding == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index f74316e679d2..7d3281866ffc 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -461,7 +461,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf)
netdev_update_features(dev);
dev_set_mtu(dev, ipoib_cm_max_mtu(dev));
rtnl_unlock();
- priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
+ priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
ipoib_flush_paths(dev);
rtnl_lock();
@@ -1207,8 +1207,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
- list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
+ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
ipoib_mcast_leave(dev, mcast);
+ ipoib_mcast_free(mcast);
+ }
}
static void ipoib_reap_neigh(struct work_struct *work)
@@ -1858,7 +1860,7 @@ static struct net_device *ipoib_add_port(const char *format,
priv->dev->broadcast[8] = priv->pkey >> 8;
priv->dev->broadcast[9] = priv->pkey & 0xff;
- result = ib_query_gid(hca, port, 0, &priv->local_gid);
+ result = ib_query_gid(hca, port, 0, &priv->local_gid, NULL);
if (result) {
printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n",
hca->name, port, result);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 136cbefe00f8..f357ca67a41c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -106,7 +106,7 @@ static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
queue_delayed_work(priv->wq, &priv->mcast_task, 0);
}
-static void ipoib_mcast_free(struct ipoib_mcast *mcast)
+void ipoib_mcast_free(struct ipoib_mcast *mcast)
{
struct net_device *dev = mcast->dev;
int tx_dropped = 0;
@@ -245,7 +245,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
spin_unlock_irq(&priv->lock);
- priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
+ priv->tx_wr.remote_qkey = priv->qkey;
set_qkey = 1;
}
@@ -561,7 +561,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
}
priv->local_lid = port_attr.lid;
- if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
+ if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid, NULL))
ipoib_warn(priv, "ib_query_gid() failed\n");
else
memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 78845b6e8b81..d48c5bae7877 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -221,9 +221,9 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
for (i = 0; i < MAX_SKB_FRAGS + 1; ++i)
priv->tx_sge[i].lkey = priv->pd->local_dma_lkey;
- priv->tx_wr.opcode = IB_WR_SEND;
- priv->tx_wr.sg_list = priv->tx_sge;
- priv->tx_wr.send_flags = IB_SEND_SIGNALED;
+ priv->tx_wr.wr.opcode = IB_WR_SEND;
+ priv->tx_wr.wr.sg_list = priv->tx_sge;
+ priv->tx_wr.wr.send_flags = IB_SEND_SIGNALED;
priv->rx_sge[0].lkey = priv->pd->local_dma_lkey;
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index f58ff96b6cbb..9080161e01af 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -111,7 +111,7 @@ module_param_named(pi_guard, iser_pi_guard, int, S_IRUGO);
MODULE_PARM_DESC(pi_guard, "T10-PI guard_type [deprecated]");
/*
- * iscsi_iser_recv() - Process a successfull recv completion
+ * iscsi_iser_recv() - Process a successful recv completion
* @conn: iscsi connection
* @hdr: iscsi header
* @rx_data: buffer containing receive data payload
@@ -126,7 +126,6 @@ iscsi_iser_recv(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
{
int rc = 0;
int datalen;
- int ahslen;
/* verify PDU length */
datalen = ntoh24(hdr->dlength);
@@ -141,9 +140,6 @@ iscsi_iser_recv(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
iser_dbg("aligned datalen (%d) hdr, %d (IB)\n",
datalen, rx_data_len);
- /* read AHS */
- ahslen = hdr->hlength * 4;
-
rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len);
if (rc && rc != ISCSI_ERR_NO_SCSI_CMD)
goto error;
@@ -766,9 +762,7 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */
stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
- stats->custom_length = 1;
- strcpy(stats->custom[0].desc, "fmr_unalign_cnt");
- stats->custom[0].value = conn->fmr_unalign_cnt;
+ stats->custom_length = 0;
}
static int iscsi_iser_get_ep_param(struct iscsi_endpoint *ep,
@@ -973,6 +967,13 @@ static umode_t iser_attr_is_visible(int param_type, int param)
return 0;
}
+static int iscsi_iser_slave_alloc(struct scsi_device *sdev)
+{
+ blk_queue_virt_boundary(sdev->request_queue, ~MASK_4K);
+
+ return 0;
+}
+
static struct scsi_host_template iscsi_iser_sht = {
.module = THIS_MODULE,
.name = "iSCSI Initiator over iSER",
@@ -985,7 +986,8 @@ static struct scsi_host_template iscsi_iser_sht = {
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
.target_alloc = iscsi_target_alloc,
- .use_clustering = DISABLE_CLUSTERING,
+ .use_clustering = ENABLE_CLUSTERING,
+ .slave_alloc = iscsi_iser_slave_alloc,
.proc_name = "iscsi_iser",
.this_id = -1,
.track_queue_depth = 1,
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index a5edd6ede692..8a5998e6a407 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -227,18 +227,13 @@ enum iser_data_dir {
* @size: num entries of this sg
* @data_len: total beffer byte len
* @dma_nents: returned by dma_map_sg
- * @orig_sg: pointer to the original sg list (in case
- * we used a copy)
- * @orig_size: num entris of orig sg list
*/
struct iser_data_buf {
struct scatterlist *sg;
- unsigned int size;
+ int size;
unsigned long data_len;
unsigned int dma_nents;
- struct scatterlist *orig_sg;
- unsigned int orig_size;
- };
+};
/* fwd declarations */
struct iser_device;
@@ -300,7 +295,11 @@ struct iser_tx_desc {
int num_sge;
bool mapped;
u8 wr_idx;
- struct ib_send_wr wrs[ISER_MAX_WRS];
+ union iser_wr {
+ struct ib_send_wr send;
+ struct ib_reg_wr fast_reg;
+ struct ib_sig_handover_wr sig;
+ } wrs[ISER_MAX_WRS];
struct iser_mem_reg data_reg;
struct iser_mem_reg prot_reg;
struct ib_sig_attrs sig_attrs;
@@ -413,7 +412,6 @@ struct iser_device {
*
* @mr: memory region
* @fmr_pool: pool of fmrs
- * @frpl: fast reg page list used by frwrs
* @page_vec: fast reg page list used by fmr pool
* @mr_valid: is mr valid indicator
*/
@@ -422,10 +420,7 @@ struct iser_reg_resources {
struct ib_mr *mr;
struct ib_fmr_pool *fmr_pool;
};
- union {
- struct ib_fast_reg_page_list *frpl;
- struct iser_page_vec *page_vec;
- };
+ struct iser_page_vec *page_vec;
u8 mr_valid:1;
};
@@ -712,11 +707,11 @@ iser_reg_desc_put_fmr(struct ib_conn *ib_conn,
static inline struct ib_send_wr *
iser_tx_next_wr(struct iser_tx_desc *tx_desc)
{
- struct ib_send_wr *cur_wr = &tx_desc->wrs[tx_desc->wr_idx];
+ struct ib_send_wr *cur_wr = &tx_desc->wrs[tx_desc->wr_idx].send;
struct ib_send_wr *last_wr;
if (tx_desc->wr_idx) {
- last_wr = &tx_desc->wrs[tx_desc->wr_idx - 1];
+ last_wr = &tx_desc->wrs[tx_desc->wr_idx - 1].send;
last_wr->next = cur_wr;
}
tx_desc->wr_idx++;
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index d511879d8cdf..ffd00c420729 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -661,48 +661,14 @@ void iser_task_rdma_init(struct iscsi_iser_task *iser_task)
void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
{
- int is_rdma_data_aligned = 1;
- int is_rdma_prot_aligned = 1;
int prot_count = scsi_prot_sg_count(iser_task->sc);
- /* if we were reading, copy back to unaligned sglist,
- * anyway dma_unmap and free the copy
- */
- if (iser_task->data[ISER_DIR_IN].orig_sg) {
- is_rdma_data_aligned = 0;
- iser_finalize_rdma_unaligned_sg(iser_task,
- &iser_task->data[ISER_DIR_IN],
- ISER_DIR_IN);
- }
-
- if (iser_task->data[ISER_DIR_OUT].orig_sg) {
- is_rdma_data_aligned = 0;
- iser_finalize_rdma_unaligned_sg(iser_task,
- &iser_task->data[ISER_DIR_OUT],
- ISER_DIR_OUT);
- }
-
- if (iser_task->prot[ISER_DIR_IN].orig_sg) {
- is_rdma_prot_aligned = 0;
- iser_finalize_rdma_unaligned_sg(iser_task,
- &iser_task->prot[ISER_DIR_IN],
- ISER_DIR_IN);
- }
-
- if (iser_task->prot[ISER_DIR_OUT].orig_sg) {
- is_rdma_prot_aligned = 0;
- iser_finalize_rdma_unaligned_sg(iser_task,
- &iser_task->prot[ISER_DIR_OUT],
- ISER_DIR_OUT);
- }
-
if (iser_task->dir[ISER_DIR_IN]) {
iser_unreg_rdma_mem(iser_task, ISER_DIR_IN);
- if (is_rdma_data_aligned)
- iser_dma_unmap_task_data(iser_task,
- &iser_task->data[ISER_DIR_IN],
- DMA_FROM_DEVICE);
- if (prot_count && is_rdma_prot_aligned)
+ iser_dma_unmap_task_data(iser_task,
+ &iser_task->data[ISER_DIR_IN],
+ DMA_FROM_DEVICE);
+ if (prot_count)
iser_dma_unmap_task_data(iser_task,
&iser_task->prot[ISER_DIR_IN],
DMA_FROM_DEVICE);
@@ -710,11 +676,10 @@ void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
if (iser_task->dir[ISER_DIR_OUT]) {
iser_unreg_rdma_mem(iser_task, ISER_DIR_OUT);
- if (is_rdma_data_aligned)
- iser_dma_unmap_task_data(iser_task,
- &iser_task->data[ISER_DIR_OUT],
- DMA_TO_DEVICE);
- if (prot_count && is_rdma_prot_aligned)
+ iser_dma_unmap_task_data(iser_task,
+ &iser_task->data[ISER_DIR_OUT],
+ DMA_TO_DEVICE);
+ if (prot_count)
iser_dma_unmap_task_data(iser_task,
&iser_task->prot[ISER_DIR_OUT],
DMA_TO_DEVICE);
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index 4c46d67d37a1..ea765fb9664d 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -88,113 +88,6 @@ int iser_assign_reg_ops(struct iser_device *device)
return 0;
}
-static void
-iser_free_bounce_sg(struct iser_data_buf *data)
-{
- struct scatterlist *sg;
- int count;
-
- for_each_sg(data->sg, sg, data->size, count)
- __free_page(sg_page(sg));
-
- kfree(data->sg);
-
- data->sg = data->orig_sg;
- data->size = data->orig_size;
- data->orig_sg = NULL;
- data->orig_size = 0;
-}
-
-static int
-iser_alloc_bounce_sg(struct iser_data_buf *data)
-{
- struct scatterlist *sg;
- struct page *page;
- unsigned long length = data->data_len;
- int i = 0, nents = DIV_ROUND_UP(length, PAGE_SIZE);
-
- sg = kcalloc(nents, sizeof(*sg), GFP_ATOMIC);
- if (!sg)
- goto err;
-
- sg_init_table(sg, nents);
- while (length) {
- u32 page_len = min_t(u32, length, PAGE_SIZE);
-
- page = alloc_page(GFP_ATOMIC);
- if (!page)
- goto err;
-
- sg_set_page(&sg[i], page, page_len, 0);
- length -= page_len;
- i++;
- }
-
- data->orig_sg = data->sg;
- data->orig_size = data->size;
- data->sg = sg;
- data->size = nents;
-
- return 0;
-
-err:
- for (; i > 0; i--)
- __free_page(sg_page(&sg[i - 1]));
- kfree(sg);
-
- return -ENOMEM;
-}
-
-static void
-iser_copy_bounce(struct iser_data_buf *data, bool to_buffer)
-{
- struct scatterlist *osg, *bsg = data->sg;
- void *oaddr, *baddr;
- unsigned int left = data->data_len;
- unsigned int bsg_off = 0;
- int i;
-
- for_each_sg(data->orig_sg, osg, data->orig_size, i) {
- unsigned int copy_len, osg_off = 0;
-
- oaddr = kmap_atomic(sg_page(osg)) + osg->offset;
- copy_len = min(left, osg->length);
- while (copy_len) {
- unsigned int len = min(copy_len, bsg->length - bsg_off);
-
- baddr = kmap_atomic(sg_page(bsg)) + bsg->offset;
- if (to_buffer)
- memcpy(baddr + bsg_off, oaddr + osg_off, len);
- else
- memcpy(oaddr + osg_off, baddr + bsg_off, len);
-
- kunmap_atomic(baddr - bsg->offset);
- osg_off += len;
- bsg_off += len;
- copy_len -= len;
-
- if (bsg_off >= bsg->length) {
- bsg = sg_next(bsg);
- bsg_off = 0;
- }
- }
- kunmap_atomic(oaddr - osg->offset);
- left -= osg_off;
- }
-}
-
-static inline void
-iser_copy_from_bounce(struct iser_data_buf *data)
-{
- iser_copy_bounce(data, false);
-}
-
-static inline void
-iser_copy_to_bounce(struct iser_data_buf *data)
-{
- iser_copy_bounce(data, true);
-}
-
struct iser_fr_desc *
iser_reg_desc_get_fr(struct ib_conn *ib_conn)
{
@@ -238,62 +131,6 @@ iser_reg_desc_put_fmr(struct ib_conn *ib_conn,
{
}
-/**
- * iser_start_rdma_unaligned_sg
- */
-static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
- struct iser_data_buf *data,
- enum iser_data_dir cmd_dir)
-{
- struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
- int rc;
-
- rc = iser_alloc_bounce_sg(data);
- if (rc) {
- iser_err("Failed to allocate bounce for data len %lu\n",
- data->data_len);
- return rc;
- }
-
- if (cmd_dir == ISER_DIR_OUT)
- iser_copy_to_bounce(data);
-
- data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size,
- (cmd_dir == ISER_DIR_OUT) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (!data->dma_nents) {
- iser_err("Got dma_nents %d, something went wrong...\n",
- data->dma_nents);
- rc = -ENOMEM;
- goto err;
- }
-
- return 0;
-err:
- iser_free_bounce_sg(data);
- return rc;
-}
-
-/**
- * iser_finalize_rdma_unaligned_sg
- */
-
-void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
- struct iser_data_buf *data,
- enum iser_data_dir cmd_dir)
-{
- struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
-
- ib_dma_unmap_sg(dev, data->sg, data->size,
- (cmd_dir == ISER_DIR_OUT) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
- if (cmd_dir == ISER_DIR_IN)
- iser_copy_from_bounce(data);
-
- iser_free_bounce_sg(data);
-}
-
#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & ~MASK_4K) == 0)
/**
@@ -355,64 +192,6 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
return cur_page;
}
-
-/**
- * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
- * for RDMA sub-list of a scatter-gather list of memory buffers, and returns
- * the number of entries which are aligned correctly. Supports the case where
- * consecutive SG elements are actually fragments of the same physcial page.
- */
-static int iser_data_buf_aligned_len(struct iser_data_buf *data,
- struct ib_device *ibdev,
- unsigned sg_tablesize)
-{
- struct scatterlist *sg, *sgl, *next_sg = NULL;
- u64 start_addr, end_addr;
- int i, ret_len, start_check = 0;
-
- if (data->dma_nents == 1)
- return 1;
-
- sgl = data->sg;
- start_addr = ib_sg_dma_address(ibdev, sgl);
-
- if (unlikely(sgl[0].offset &&
- data->data_len >= sg_tablesize * PAGE_SIZE)) {
- iser_dbg("can't register length %lx with offset %x "
- "fall to bounce buffer\n", data->data_len,
- sgl[0].offset);
- return 0;
- }
-
- for_each_sg(sgl, sg, data->dma_nents, i) {
- if (start_check && !IS_4K_ALIGNED(start_addr))
- break;
-
- next_sg = sg_next(sg);
- if (!next_sg)
- break;
-
- end_addr = start_addr + ib_sg_dma_len(ibdev, sg);
- start_addr = ib_sg_dma_address(ibdev, next_sg);
-
- if (end_addr == start_addr) {
- start_check = 0;
- continue;
- } else
- start_check = 1;
-
- if (!IS_4K_ALIGNED(end_addr))
- break;
- }
- ret_len = (next_sg) ? i : i+1;
-
- if (unlikely(ret_len != data->dma_nents))
- iser_warn("rdma alignment violation (%d/%d aligned)\n",
- ret_len, data->dma_nents);
-
- return ret_len;
-}
-
static void iser_data_buf_dump(struct iser_data_buf *data,
struct ib_device *ibdev)
{
@@ -483,31 +262,6 @@ iser_reg_dma(struct iser_device *device, struct iser_data_buf *mem,
return 0;
}
-static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task,
- struct iser_data_buf *mem,
- enum iser_data_dir cmd_dir)
-{
- struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn;
- struct iser_device *device = iser_task->iser_conn->ib_conn.device;
-
- iscsi_conn->fmr_unalign_cnt++;
-
- if (iser_debug_level > 0)
- iser_data_buf_dump(mem, device->ib_device);
-
- /* unmap the command data before accessing it */
- iser_dma_unmap_task_data(iser_task, mem,
- (cmd_dir == ISER_DIR_OUT) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
- /* allocate copy buf, if we are writing, copy the */
- /* unaligned scatterlist, dma map the copy */
- if (iser_start_rdma_unaligned_sg(iser_task, mem, cmd_dir) != 0)
- return -ENOMEM;
-
- return 0;
-}
-
/**
* iser_reg_page_vec - Register physical memory
*
@@ -683,7 +437,7 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
{
struct iser_tx_desc *tx_desc = &iser_task->desc;
struct ib_sig_attrs *sig_attrs = &tx_desc->sig_attrs;
- struct ib_send_wr *wr;
+ struct ib_sig_handover_wr *wr;
int ret;
memset(sig_attrs, 0, sizeof(*sig_attrs));
@@ -693,26 +447,24 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
iser_set_prot_checks(iser_task->sc, &sig_attrs->check_mask);
- if (!pi_ctx->sig_mr_valid) {
- wr = iser_tx_next_wr(tx_desc);
- iser_inv_rkey(wr, pi_ctx->sig_mr);
- }
-
- wr = iser_tx_next_wr(tx_desc);
- wr->opcode = IB_WR_REG_SIG_MR;
- wr->wr_id = ISER_FASTREG_LI_WRID;
- wr->sg_list = &data_reg->sge;
- wr->num_sge = 1;
- wr->send_flags = 0;
- wr->wr.sig_handover.sig_attrs = sig_attrs;
- wr->wr.sig_handover.sig_mr = pi_ctx->sig_mr;
+ if (!pi_ctx->sig_mr_valid)
+ iser_inv_rkey(iser_tx_next_wr(tx_desc), pi_ctx->sig_mr);
+
+ wr = sig_handover_wr(iser_tx_next_wr(tx_desc));
+ wr->wr.opcode = IB_WR_REG_SIG_MR;
+ wr->wr.wr_id = ISER_FASTREG_LI_WRID;
+ wr->wr.sg_list = &data_reg->sge;
+ wr->wr.num_sge = 1;
+ wr->wr.send_flags = 0;
+ wr->sig_attrs = sig_attrs;
+ wr->sig_mr = pi_ctx->sig_mr;
if (scsi_prot_sg_count(iser_task->sc))
- wr->wr.sig_handover.prot = &prot_reg->sge;
+ wr->prot = &prot_reg->sge;
else
- wr->wr.sig_handover.prot = NULL;
- wr->wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_READ |
- IB_ACCESS_REMOTE_WRITE;
+ wr->prot = NULL;
+ wr->access_flags = IB_ACCESS_LOCAL_WRITE |
+ IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_WRITE;
pi_ctx->sig_mr_valid = 0;
sig_reg->sge.lkey = pi_ctx->sig_mr->lkey;
@@ -720,7 +472,7 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
sig_reg->sge.addr = 0;
sig_reg->sge.length = scsi_transfer_length(iser_task->sc);
- iser_dbg("sig reg: lkey: 0x%x, rkey: 0x%x, addr: 0x%llx, length: %u\n",
+ iser_dbg("lkey=0x%x rkey=0x%x addr=0x%llx length=%u\n",
sig_reg->sge.lkey, sig_reg->rkey, sig_reg->sge.addr,
sig_reg->sge.length);
err:
@@ -732,69 +484,41 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
struct iser_reg_resources *rsc,
struct iser_mem_reg *reg)
{
- struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
- struct iser_device *device = ib_conn->device;
- struct ib_mr *mr = rsc->mr;
- struct ib_fast_reg_page_list *frpl = rsc->frpl;
struct iser_tx_desc *tx_desc = &iser_task->desc;
- struct ib_send_wr *wr;
- int offset, size, plen;
+ struct ib_mr *mr = rsc->mr;
+ struct ib_reg_wr *wr;
+ int n;
- plen = iser_sg_to_page_vec(mem, device->ib_device, frpl->page_list,
- &offset, &size);
- if (plen * SIZE_4K < size) {
- iser_err("fast reg page_list too short to hold this SG\n");
- return -EINVAL;
- }
+ if (!rsc->mr_valid)
+ iser_inv_rkey(iser_tx_next_wr(tx_desc), mr);
- if (!rsc->mr_valid) {
- wr = iser_tx_next_wr(tx_desc);
- iser_inv_rkey(wr, mr);
+ n = ib_map_mr_sg(mr, mem->sg, mem->size, SIZE_4K);
+ if (unlikely(n != mem->size)) {
+ iser_err("failed to map sg (%d/%d)\n",
+ n, mem->size);
+ return n < 0 ? n : -EINVAL;
}
- wr = iser_tx_next_wr(tx_desc);
- wr->opcode = IB_WR_FAST_REG_MR;
- wr->wr_id = ISER_FASTREG_LI_WRID;
- wr->send_flags = 0;
- wr->wr.fast_reg.iova_start = frpl->page_list[0] + offset;
- wr->wr.fast_reg.page_list = frpl;
- wr->wr.fast_reg.page_list_len = plen;
- wr->wr.fast_reg.page_shift = SHIFT_4K;
- wr->wr.fast_reg.length = size;
- wr->wr.fast_reg.rkey = mr->rkey;
- wr->wr.fast_reg.access_flags = (IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE |
- IB_ACCESS_REMOTE_READ);
+ wr = reg_wr(iser_tx_next_wr(tx_desc));
+ wr->wr.opcode = IB_WR_REG_MR;
+ wr->wr.wr_id = ISER_FASTREG_LI_WRID;
+ wr->wr.send_flags = 0;
+ wr->wr.num_sge = 0;
+ wr->mr = mr;
+ wr->key = mr->rkey;
+ wr->access = IB_ACCESS_LOCAL_WRITE |
+ IB_ACCESS_REMOTE_WRITE |
+ IB_ACCESS_REMOTE_READ;
+
rsc->mr_valid = 0;
reg->sge.lkey = mr->lkey;
reg->rkey = mr->rkey;
- reg->sge.addr = frpl->page_list[0] + offset;
- reg->sge.length = size;
+ reg->sge.addr = mr->iova;
+ reg->sge.length = mr->length;
- iser_dbg("fast reg: lkey=0x%x, rkey=0x%x, addr=0x%llx,"
- " length=0x%x\n", reg->sge.lkey, reg->rkey,
- reg->sge.addr, reg->sge.length);
-
- return 0;
-}
-
-static int
-iser_handle_unaligned_buf(struct iscsi_iser_task *task,
- struct iser_data_buf *mem,
- enum iser_data_dir dir)
-{
- struct iser_conn *iser_conn = task->iser_conn;
- struct iser_device *device = iser_conn->ib_conn.device;
- int err, aligned_len;
-
- aligned_len = iser_data_buf_aligned_len(mem, device->ib_device,
- iser_conn->scsi_sg_tablesize);
- if (aligned_len != mem->dma_nents) {
- err = fall_to_bounce_buf(task, mem, dir);
- if (err)
- return err;
- }
+ iser_dbg("lkey=0x%x rkey=0x%x addr=0x%llx length=0x%x\n",
+ reg->sge.lkey, reg->rkey, reg->sge.addr, reg->sge.length);
return 0;
}
@@ -841,10 +565,6 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *task,
bool use_dma_key;
int err;
- err = iser_handle_unaligned_buf(task, mem, dir);
- if (unlikely(err))
- return err;
-
use_dma_key = (mem->dma_nents == 1 && !iser_always_reg &&
scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL);
@@ -867,10 +587,6 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *task,
if (scsi_prot_sg_count(task->sc)) {
mem = &task->prot[dir];
- err = iser_handle_unaligned_buf(task, mem, dir);
- if (unlikely(err))
- goto err_reg;
-
err = iser_reg_prot_sg(task, mem, desc,
use_dma_key, prot_reg);
if (unlikely(err))
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 85132d867bc8..a93070210109 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -293,35 +293,21 @@ iser_alloc_reg_res(struct ib_device *ib_device,
{
int ret;
- res->frpl = ib_alloc_fast_reg_page_list(ib_device, size);
- if (IS_ERR(res->frpl)) {
- ret = PTR_ERR(res->frpl);
- iser_err("Failed to allocate ib_fast_reg_page_list err=%d\n",
- ret);
- return PTR_ERR(res->frpl);
- }
-
res->mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG, size);
if (IS_ERR(res->mr)) {
ret = PTR_ERR(res->mr);
iser_err("Failed to allocate ib_fast_reg_mr err=%d\n", ret);
- goto fast_reg_mr_failure;
+ return ret;
}
res->mr_valid = 1;
return 0;
-
-fast_reg_mr_failure:
- ib_free_fast_reg_page_list(res->frpl);
-
- return ret;
}
static void
iser_free_reg_res(struct iser_reg_resources *rsc)
{
ib_dereg_mr(rsc->mr);
- ib_free_fast_reg_page_list(rsc->frpl);
}
static int
@@ -1017,7 +1003,7 @@ int iser_connect(struct iser_conn *iser_conn,
ib_conn->beacon.wr_id = ISER_BEACON_WRID;
ib_conn->beacon.opcode = IB_WR_SEND;
- ib_conn->cma_id = rdma_create_id(iser_cma_handler,
+ ib_conn->cma_id = rdma_create_id(&init_net, iser_cma_handler,
(void *)iser_conn,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(ib_conn->cma_id)) {
@@ -1135,7 +1121,7 @@ int iser_post_send(struct ib_conn *ib_conn, struct iser_tx_desc *tx_desc,
wr->opcode = IB_WR_SEND;
wr->send_flags = signal ? IB_SEND_SIGNALED : 0;
- ib_ret = ib_post_send(ib_conn->qp, &tx_desc->wrs[0], &bad_wr);
+ ib_ret = ib_post_send(ib_conn->qp, &tx_desc->wrs[0].send, &bad_wr);
if (ib_ret)
iser_err("ib_post_send failed, ret:%d opcode:%d\n",
ib_ret, bad_wr->opcode);
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index aa59037d7504..dfbbbb28090b 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -473,10 +473,8 @@ isert_conn_free_fastreg_pool(struct isert_conn *isert_conn)
list_for_each_entry_safe(fr_desc, tmp,
&isert_conn->fr_pool, list) {
list_del(&fr_desc->list);
- ib_free_fast_reg_page_list(fr_desc->data_frpl);
ib_dereg_mr(fr_desc->data_mr);
if (fr_desc->pi_ctx) {
- ib_free_fast_reg_page_list(fr_desc->pi_ctx->prot_frpl);
ib_dereg_mr(fr_desc->pi_ctx->prot_mr);
ib_dereg_mr(fr_desc->pi_ctx->sig_mr);
kfree(fr_desc->pi_ctx);
@@ -504,22 +502,13 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
return -ENOMEM;
}
- pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(device,
- ISCSI_ISER_SG_TABLESIZE);
- if (IS_ERR(pi_ctx->prot_frpl)) {
- isert_err("Failed to allocate prot frpl err=%ld\n",
- PTR_ERR(pi_ctx->prot_frpl));
- ret = PTR_ERR(pi_ctx->prot_frpl);
- goto err_pi_ctx;
- }
-
pi_ctx->prot_mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
ISCSI_ISER_SG_TABLESIZE);
if (IS_ERR(pi_ctx->prot_mr)) {
isert_err("Failed to allocate prot frmr err=%ld\n",
PTR_ERR(pi_ctx->prot_mr));
ret = PTR_ERR(pi_ctx->prot_mr);
- goto err_prot_frpl;
+ goto err_pi_ctx;
}
desc->ind |= ISERT_PROT_KEY_VALID;
@@ -539,8 +528,6 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
err_prot_mr:
ib_dereg_mr(pi_ctx->prot_mr);
-err_prot_frpl:
- ib_free_fast_reg_page_list(pi_ctx->prot_frpl);
err_pi_ctx:
kfree(pi_ctx);
@@ -551,34 +538,18 @@ static int
isert_create_fr_desc(struct ib_device *ib_device, struct ib_pd *pd,
struct fast_reg_descriptor *fr_desc)
{
- int ret;
-
- fr_desc->data_frpl = ib_alloc_fast_reg_page_list(ib_device,
- ISCSI_ISER_SG_TABLESIZE);
- if (IS_ERR(fr_desc->data_frpl)) {
- isert_err("Failed to allocate data frpl err=%ld\n",
- PTR_ERR(fr_desc->data_frpl));
- return PTR_ERR(fr_desc->data_frpl);
- }
-
fr_desc->data_mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
ISCSI_ISER_SG_TABLESIZE);
if (IS_ERR(fr_desc->data_mr)) {
isert_err("Failed to allocate data frmr err=%ld\n",
PTR_ERR(fr_desc->data_mr));
- ret = PTR_ERR(fr_desc->data_mr);
- goto err_data_frpl;
+ return PTR_ERR(fr_desc->data_mr);
}
fr_desc->ind |= ISERT_DATA_KEY_VALID;
isert_dbg("Created fr_desc %p\n", fr_desc);
return 0;
-
-err_data_frpl:
- ib_free_fast_reg_page_list(fr_desc->data_frpl);
-
- return ret;
}
static int
@@ -1579,7 +1550,6 @@ isert_rx_do_work(struct iser_rx_desc *rx_desc, struct isert_conn *isert_conn)
struct iser_hdr *iser_hdr = &rx_desc->iser_header;
uint64_t read_va = 0, write_va = 0;
uint32_t read_stag = 0, write_stag = 0;
- int rc;
switch (iser_hdr->flags & 0xF0) {
case ISCSI_CTRL:
@@ -1606,8 +1576,8 @@ isert_rx_do_work(struct iser_rx_desc *rx_desc, struct isert_conn *isert_conn)
break;
}
- rc = isert_rx_opcode(isert_conn, rx_desc,
- read_stag, read_va, write_stag, write_va);
+ isert_rx_opcode(isert_conn, rx_desc,
+ read_stag, read_va, write_stag, write_va);
}
static void
@@ -1716,10 +1686,10 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
isert_unmap_data_buf(isert_conn, &wr->data);
}
- if (wr->send_wr) {
+ if (wr->rdma_wr) {
isert_dbg("Cmd %p free send_wr\n", isert_cmd);
- kfree(wr->send_wr);
- wr->send_wr = NULL;
+ kfree(wr->rdma_wr);
+ wr->rdma_wr = NULL;
}
if (wr->ib_sge) {
@@ -1754,7 +1724,7 @@ isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
}
wr->ib_sge = NULL;
- wr->send_wr = NULL;
+ wr->rdma_wr = NULL;
}
static void
@@ -1923,7 +1893,7 @@ isert_completion_rdma_write(struct iser_tx_desc *tx_desc,
}
device->unreg_rdma_mem(isert_cmd, isert_conn);
- wr->send_wr_num = 0;
+ wr->rdma_wr_num = 0;
if (ret)
transport_send_check_condition_and_sense(se_cmd,
se_cmd->pi_err, 0);
@@ -1951,7 +1921,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
iscsit_stop_dataout_timer(cmd);
device->unreg_rdma_mem(isert_cmd, isert_conn);
cmd->write_data_done = wr->data.len;
- wr->send_wr_num = 0;
+ wr->rdma_wr_num = 0;
isert_dbg("Cmd: %p RDMA_READ comp calling execute_cmd\n", isert_cmd);
spin_lock_bh(&cmd->istate_lock);
@@ -2403,7 +2373,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
static int
isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
- struct ib_sge *ib_sge, struct ib_send_wr *send_wr,
+ struct ib_sge *ib_sge, struct ib_rdma_wr *rdma_wr,
u32 data_left, u32 offset)
{
struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
@@ -2418,8 +2388,8 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
sg_nents = min(cmd->se_cmd.t_data_nents - sg_off, isert_conn->max_sge);
page_off = offset % PAGE_SIZE;
- send_wr->sg_list = ib_sge;
- send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
+ rdma_wr->wr.sg_list = ib_sge;
+ rdma_wr->wr.wr_id = (uintptr_t)&isert_cmd->tx_desc;
/*
* Perform mapping of TCM scatterlist memory ib_sge dma_addr.
*/
@@ -2444,11 +2414,11 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
isert_dbg("Incrementing ib_sge pointer to %p\n", ib_sge);
}
- send_wr->num_sge = ++i;
+ rdma_wr->wr.num_sge = ++i;
isert_dbg("Set outgoing sg_list: %p num_sg: %u from TCM SGLs\n",
- send_wr->sg_list, send_wr->num_sge);
+ rdma_wr->wr.sg_list, rdma_wr->wr.num_sge);
- return send_wr->num_sge;
+ return rdma_wr->wr.num_sge;
}
static int
@@ -2459,7 +2429,7 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
struct isert_conn *isert_conn = conn->context;
struct isert_data_buf *data = &wr->data;
- struct ib_send_wr *send_wr;
+ struct ib_rdma_wr *rdma_wr;
struct ib_sge *ib_sge;
u32 offset, data_len, data_left, rdma_write_max, va_offset = 0;
int ret = 0, i, ib_sge_cnt;
@@ -2484,11 +2454,11 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
}
wr->ib_sge = ib_sge;
- wr->send_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge);
- wr->send_wr = kzalloc(sizeof(struct ib_send_wr) * wr->send_wr_num,
+ wr->rdma_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge);
+ wr->rdma_wr = kzalloc(sizeof(struct ib_rdma_wr) * wr->rdma_wr_num,
GFP_KERNEL);
- if (!wr->send_wr) {
- isert_dbg("Unable to allocate wr->send_wr\n");
+ if (!wr->rdma_wr) {
+ isert_dbg("Unable to allocate wr->rdma_wr\n");
ret = -ENOMEM;
goto unmap_cmd;
}
@@ -2496,31 +2466,31 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
wr->isert_cmd = isert_cmd;
rdma_write_max = isert_conn->max_sge * PAGE_SIZE;
- for (i = 0; i < wr->send_wr_num; i++) {
- send_wr = &isert_cmd->rdma_wr.send_wr[i];
+ for (i = 0; i < wr->rdma_wr_num; i++) {
+ rdma_wr = &isert_cmd->rdma_wr.rdma_wr[i];
data_len = min(data_left, rdma_write_max);
- send_wr->send_flags = 0;
+ rdma_wr->wr.send_flags = 0;
if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) {
- send_wr->opcode = IB_WR_RDMA_WRITE;
- send_wr->wr.rdma.remote_addr = isert_cmd->read_va + offset;
- send_wr->wr.rdma.rkey = isert_cmd->read_stag;
- if (i + 1 == wr->send_wr_num)
- send_wr->next = &isert_cmd->tx_desc.send_wr;
+ rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+ rdma_wr->remote_addr = isert_cmd->read_va + offset;
+ rdma_wr->rkey = isert_cmd->read_stag;
+ if (i + 1 == wr->rdma_wr_num)
+ rdma_wr->wr.next = &isert_cmd->tx_desc.send_wr;
else
- send_wr->next = &wr->send_wr[i + 1];
+ rdma_wr->wr.next = &wr->rdma_wr[i + 1].wr;
} else {
- send_wr->opcode = IB_WR_RDMA_READ;
- send_wr->wr.rdma.remote_addr = isert_cmd->write_va + va_offset;
- send_wr->wr.rdma.rkey = isert_cmd->write_stag;
- if (i + 1 == wr->send_wr_num)
- send_wr->send_flags = IB_SEND_SIGNALED;
+ rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+ rdma_wr->remote_addr = isert_cmd->write_va + va_offset;
+ rdma_wr->rkey = isert_cmd->write_stag;
+ if (i + 1 == wr->rdma_wr_num)
+ rdma_wr->wr.send_flags = IB_SEND_SIGNALED;
else
- send_wr->next = &wr->send_wr[i + 1];
+ rdma_wr->wr.next = &wr->rdma_wr[i + 1].wr;
}
ib_sge_cnt = isert_build_rdma_wr(isert_conn, isert_cmd, ib_sge,
- send_wr, data_len, offset);
+ rdma_wr, data_len, offset);
ib_sge += ib_sge_cnt;
offset += data_len;
@@ -2535,45 +2505,6 @@ unmap_cmd:
return ret;
}
-static int
-isert_map_fr_pagelist(struct ib_device *ib_dev,
- struct scatterlist *sg_start, int sg_nents, u64 *fr_pl)
-{
- u64 start_addr, end_addr, page, chunk_start = 0;
- struct scatterlist *tmp_sg;
- int i = 0, new_chunk, last_ent, n_pages;
-
- n_pages = 0;
- new_chunk = 1;
- last_ent = sg_nents - 1;
- for_each_sg(sg_start, tmp_sg, sg_nents, i) {
- start_addr = ib_sg_dma_address(ib_dev, tmp_sg);
- if (new_chunk)
- chunk_start = start_addr;
- end_addr = start_addr + ib_sg_dma_len(ib_dev, tmp_sg);
-
- isert_dbg("SGL[%d] dma_addr: 0x%llx len: %u\n",
- i, (unsigned long long)tmp_sg->dma_address,
- tmp_sg->length);
-
- if ((end_addr & ~PAGE_MASK) && i < last_ent) {
- new_chunk = 0;
- continue;
- }
- new_chunk = 1;
-
- page = chunk_start & PAGE_MASK;
- do {
- fr_pl[n_pages++] = page;
- isert_dbg("Mapped page_list[%d] page_addr: 0x%llx\n",
- n_pages - 1, page);
- page += PAGE_SIZE;
- } while (page < end_addr);
- }
-
- return n_pages;
-}
-
static inline void
isert_inv_rkey(struct ib_send_wr *inv_wr, struct ib_mr *mr)
{
@@ -2599,11 +2530,9 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
struct isert_device *device = isert_conn->device;
struct ib_device *ib_dev = device->ib_device;
struct ib_mr *mr;
- struct ib_fast_reg_page_list *frpl;
- struct ib_send_wr fr_wr, inv_wr;
- struct ib_send_wr *bad_wr, *wr = NULL;
- int ret, pagelist_len;
- u32 page_off;
+ struct ib_reg_wr reg_wr;
+ struct ib_send_wr inv_wr, *bad_wr, *wr = NULL;
+ int ret, n;
if (mem->dma_nents == 1) {
sge->lkey = device->pd->local_dma_lkey;
@@ -2614,45 +2543,41 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
return 0;
}
- if (ind == ISERT_DATA_KEY_VALID) {
+ if (ind == ISERT_DATA_KEY_VALID)
/* Registering data buffer */
mr = fr_desc->data_mr;
- frpl = fr_desc->data_frpl;
- } else {
+ else
/* Registering protection buffer */
mr = fr_desc->pi_ctx->prot_mr;
- frpl = fr_desc->pi_ctx->prot_frpl;
- }
-
- page_off = mem->offset % PAGE_SIZE;
-
- isert_dbg("Use fr_desc %p sg_nents %d offset %u\n",
- fr_desc, mem->nents, mem->offset);
-
- pagelist_len = isert_map_fr_pagelist(ib_dev, mem->sg, mem->nents,
- &frpl->page_list[0]);
if (!(fr_desc->ind & ind)) {
isert_inv_rkey(&inv_wr, mr);
wr = &inv_wr;
}
- /* Prepare FASTREG WR */
- memset(&fr_wr, 0, sizeof(fr_wr));
- fr_wr.wr_id = ISER_FASTREG_LI_WRID;
- fr_wr.opcode = IB_WR_FAST_REG_MR;
- fr_wr.wr.fast_reg.iova_start = frpl->page_list[0] + page_off;
- fr_wr.wr.fast_reg.page_list = frpl;
- fr_wr.wr.fast_reg.page_list_len = pagelist_len;
- fr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
- fr_wr.wr.fast_reg.length = mem->len;
- fr_wr.wr.fast_reg.rkey = mr->rkey;
- fr_wr.wr.fast_reg.access_flags = IB_ACCESS_LOCAL_WRITE;
+ n = ib_map_mr_sg(mr, mem->sg, mem->nents, PAGE_SIZE);
+ if (unlikely(n != mem->nents)) {
+ isert_err("failed to map mr sg (%d/%d)\n",
+ n, mem->nents);
+ return n < 0 ? n : -EINVAL;
+ }
+
+ isert_dbg("Use fr_desc %p sg_nents %d offset %u\n",
+ fr_desc, mem->nents, mem->offset);
+
+ reg_wr.wr.next = NULL;
+ reg_wr.wr.opcode = IB_WR_REG_MR;
+ reg_wr.wr.wr_id = ISER_FASTREG_LI_WRID;
+ reg_wr.wr.send_flags = 0;
+ reg_wr.wr.num_sge = 0;
+ reg_wr.mr = mr;
+ reg_wr.key = mr->lkey;
+ reg_wr.access = IB_ACCESS_LOCAL_WRITE;
if (!wr)
- wr = &fr_wr;
+ wr = &reg_wr.wr;
else
- wr->next = &fr_wr;
+ wr->next = &reg_wr.wr;
ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
if (ret) {
@@ -2662,8 +2587,8 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
fr_desc->ind &= ~ind;
sge->lkey = mr->lkey;
- sge->addr = frpl->page_list[0] + page_off;
- sge->length = mem->len;
+ sge->addr = mr->iova;
+ sge->length = mr->length;
isert_dbg("sge: addr: 0x%llx length: %u lkey: %x\n",
sge->addr, sge->length, sge->lkey);
@@ -2733,8 +2658,8 @@ isert_reg_sig_mr(struct isert_conn *isert_conn,
struct isert_rdma_wr *rdma_wr,
struct fast_reg_descriptor *fr_desc)
{
- struct ib_send_wr sig_wr, inv_wr;
- struct ib_send_wr *bad_wr, *wr = NULL;
+ struct ib_sig_handover_wr sig_wr;
+ struct ib_send_wr inv_wr, *bad_wr, *wr = NULL;
struct pi_context *pi_ctx = fr_desc->pi_ctx;
struct ib_sig_attrs sig_attrs;
int ret;
@@ -2752,20 +2677,20 @@ isert_reg_sig_mr(struct isert_conn *isert_conn,
}
memset(&sig_wr, 0, sizeof(sig_wr));
- sig_wr.opcode = IB_WR_REG_SIG_MR;
- sig_wr.wr_id = ISER_FASTREG_LI_WRID;
- sig_wr.sg_list = &rdma_wr->ib_sg[DATA];
- sig_wr.num_sge = 1;
- sig_wr.wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE;
- sig_wr.wr.sig_handover.sig_attrs = &sig_attrs;
- sig_wr.wr.sig_handover.sig_mr = pi_ctx->sig_mr;
+ sig_wr.wr.opcode = IB_WR_REG_SIG_MR;
+ sig_wr.wr.wr_id = ISER_FASTREG_LI_WRID;
+ sig_wr.wr.sg_list = &rdma_wr->ib_sg[DATA];
+ sig_wr.wr.num_sge = 1;
+ sig_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
+ sig_wr.sig_attrs = &sig_attrs;
+ sig_wr.sig_mr = pi_ctx->sig_mr;
if (se_cmd->t_prot_sg)
- sig_wr.wr.sig_handover.prot = &rdma_wr->ib_sg[PROT];
+ sig_wr.prot = &rdma_wr->ib_sg[PROT];
if (!wr)
- wr = &sig_wr;
+ wr = &sig_wr.wr;
else
- wr->next = &sig_wr;
+ wr->next = &sig_wr.wr;
ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
if (ret) {
@@ -2859,7 +2784,7 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
struct isert_conn *isert_conn = conn->context;
struct fast_reg_descriptor *fr_desc = NULL;
- struct ib_send_wr *send_wr;
+ struct ib_rdma_wr *rdma_wr;
struct ib_sge *ib_sg;
u32 offset;
int ret = 0;
@@ -2900,26 +2825,26 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
memcpy(&wr->s_ib_sge, ib_sg, sizeof(*ib_sg));
wr->ib_sge = &wr->s_ib_sge;
- wr->send_wr_num = 1;
- memset(&wr->s_send_wr, 0, sizeof(*send_wr));
- wr->send_wr = &wr->s_send_wr;
+ wr->rdma_wr_num = 1;
+ memset(&wr->s_rdma_wr, 0, sizeof(wr->s_rdma_wr));
+ wr->rdma_wr = &wr->s_rdma_wr;
wr->isert_cmd = isert_cmd;
- send_wr = &isert_cmd->rdma_wr.s_send_wr;
- send_wr->sg_list = &wr->s_ib_sge;
- send_wr->num_sge = 1;
- send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
+ rdma_wr = &isert_cmd->rdma_wr.s_rdma_wr;
+ rdma_wr->wr.sg_list = &wr->s_ib_sge;
+ rdma_wr->wr.num_sge = 1;
+ rdma_wr->wr.wr_id = (uintptr_t)&isert_cmd->tx_desc;
if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) {
- send_wr->opcode = IB_WR_RDMA_WRITE;
- send_wr->wr.rdma.remote_addr = isert_cmd->read_va;
- send_wr->wr.rdma.rkey = isert_cmd->read_stag;
- send_wr->send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
+ rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+ rdma_wr->remote_addr = isert_cmd->read_va;
+ rdma_wr->rkey = isert_cmd->read_stag;
+ rdma_wr->wr.send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
0 : IB_SEND_SIGNALED;
} else {
- send_wr->opcode = IB_WR_RDMA_READ;
- send_wr->wr.rdma.remote_addr = isert_cmd->write_va;
- send_wr->wr.rdma.rkey = isert_cmd->write_stag;
- send_wr->send_flags = IB_SEND_SIGNALED;
+ rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+ rdma_wr->remote_addr = isert_cmd->write_va;
+ rdma_wr->rkey = isert_cmd->write_stag;
+ rdma_wr->wr.send_flags = IB_SEND_SIGNALED;
}
return 0;
@@ -2967,8 +2892,8 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
isert_init_send_wr(isert_conn, isert_cmd,
&isert_cmd->tx_desc.send_wr);
- isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
- wr->send_wr_num += 1;
+ isert_cmd->rdma_wr.s_rdma_wr.wr.next = &isert_cmd->tx_desc.send_wr;
+ wr->rdma_wr_num += 1;
rc = isert_post_recv(isert_conn, isert_cmd->rx_desc);
if (rc) {
@@ -2977,7 +2902,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
}
}
- rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
+ rc = ib_post_send(isert_conn->qp, &wr->rdma_wr->wr, &wr_failed);
if (rc)
isert_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n");
@@ -3011,7 +2936,7 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
return rc;
}
- rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
+ rc = ib_post_send(isert_conn->qp, &wr->rdma_wr->wr, &wr_failed);
if (rc)
isert_warn("ib_post_send() failed for IB_WR_RDMA_READ\n");
@@ -3097,7 +3022,7 @@ isert_setup_id(struct isert_np *isert_np)
sa = (struct sockaddr *)&np->np_sockaddr;
isert_dbg("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa);
- id = rdma_create_id(isert_cma_handler, isert_np,
+ id = rdma_create_id(&init_net, isert_cma_handler, isert_np,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(id)) {
isert_err("rdma_create_id() failed: %ld\n", PTR_ERR(id));
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index c5b99bcecbcf..3d7fbc47c343 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -84,14 +84,12 @@ enum isert_indicator {
struct pi_context {
struct ib_mr *prot_mr;
- struct ib_fast_reg_page_list *prot_frpl;
struct ib_mr *sig_mr;
};
struct fast_reg_descriptor {
struct list_head list;
struct ib_mr *data_mr;
- struct ib_fast_reg_page_list *data_frpl;
u8 ind;
struct pi_context *pi_ctx;
};
@@ -117,9 +115,9 @@ struct isert_rdma_wr {
enum iser_ib_op_code iser_ib_op;
struct ib_sge *ib_sge;
struct ib_sge s_ib_sge;
- int send_wr_num;
- struct ib_send_wr *send_wr;
- struct ib_send_wr s_send_wr;
+ int rdma_wr_num;
+ struct ib_rdma_wr *rdma_wr;
+ struct ib_rdma_wr s_rdma_wr;
struct ib_sge ib_sg[3];
struct isert_data_buf data;
struct isert_data_buf prot;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index b481490ad257..9909022dc6c3 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -340,8 +340,6 @@ static void srp_destroy_fr_pool(struct srp_fr_pool *pool)
return;
for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
- if (d->frpl)
- ib_free_fast_reg_page_list(d->frpl);
if (d->mr)
ib_dereg_mr(d->mr);
}
@@ -362,7 +360,6 @@ static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
struct srp_fr_pool *pool;
struct srp_fr_desc *d;
struct ib_mr *mr;
- struct ib_fast_reg_page_list *frpl;
int i, ret = -EINVAL;
if (pool_size <= 0)
@@ -385,12 +382,6 @@ static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
goto destroy_pool;
}
d->mr = mr;
- frpl = ib_alloc_fast_reg_page_list(device, max_page_list_len);
- if (IS_ERR(frpl)) {
- ret = PTR_ERR(frpl);
- goto destroy_pool;
- }
- d->frpl = frpl;
list_add_tail(&d->entry, &pool->free_list);
}
@@ -849,11 +840,12 @@ static void srp_free_req_data(struct srp_target_port *target,
for (i = 0; i < target->req_ring_size; ++i) {
req = &ch->req_ring[i];
- if (dev->use_fast_reg)
+ if (dev->use_fast_reg) {
kfree(req->fr_list);
- else
+ } else {
kfree(req->fmr_list);
- kfree(req->map_page);
+ kfree(req->map_page);
+ }
if (req->indirect_dma_addr) {
ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
target->indirect_size,
@@ -887,14 +879,15 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch)
GFP_KERNEL);
if (!mr_list)
goto out;
- if (srp_dev->use_fast_reg)
+ if (srp_dev->use_fast_reg) {
req->fr_list = mr_list;
- else
+ } else {
req->fmr_list = mr_list;
- req->map_page = kmalloc(srp_dev->max_pages_per_mr *
- sizeof(void *), GFP_KERNEL);
- if (!req->map_page)
- goto out;
+ req->map_page = kmalloc(srp_dev->max_pages_per_mr *
+ sizeof(void *), GFP_KERNEL);
+ if (!req->map_page)
+ goto out;
+ }
req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
if (!req->indirect_desc)
goto out;
@@ -1286,6 +1279,17 @@ static int srp_map_finish_fmr(struct srp_map_state *state,
if (state->fmr.next >= state->fmr.end)
return -ENOMEM;
+ WARN_ON_ONCE(!dev->use_fmr);
+
+ if (state->npages == 0)
+ return 0;
+
+ if (state->npages == 1 && target->global_mr) {
+ srp_map_desc(state, state->base_dma_addr, state->dma_len,
+ target->global_mr->rkey);
+ goto reset_state;
+ }
+
fmr = ib_fmr_pool_map_phys(ch->fmr_pool, state->pages,
state->npages, io_addr);
if (IS_ERR(fmr))
@@ -1297,6 +1301,10 @@ static int srp_map_finish_fmr(struct srp_map_state *state,
srp_map_desc(state, state->base_dma_addr & ~dev->mr_page_mask,
state->dma_len, fmr->fmr->rkey);
+reset_state:
+ state->npages = 0;
+ state->dma_len = 0;
+
return 0;
}
@@ -1306,13 +1314,26 @@ static int srp_map_finish_fr(struct srp_map_state *state,
struct srp_target_port *target = ch->target;
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_send_wr *bad_wr;
- struct ib_send_wr wr;
+ struct ib_reg_wr wr;
struct srp_fr_desc *desc;
u32 rkey;
+ int n, err;
if (state->fr.next >= state->fr.end)
return -ENOMEM;
+ WARN_ON_ONCE(!dev->use_fast_reg);
+
+ if (state->sg_nents == 0)
+ return 0;
+
+ if (state->sg_nents == 1 && target->global_mr) {
+ srp_map_desc(state, sg_dma_address(state->sg),
+ sg_dma_len(state->sg),
+ target->global_mr->rkey);
+ return 1;
+ }
+
desc = srp_fr_pool_get(ch->fr_pool);
if (!desc)
return -ENOMEM;
@@ -1320,56 +1341,33 @@ static int srp_map_finish_fr(struct srp_map_state *state,
rkey = ib_inc_rkey(desc->mr->rkey);
ib_update_fast_reg_key(desc->mr, rkey);
- memcpy(desc->frpl->page_list, state->pages,
- sizeof(state->pages[0]) * state->npages);
-
- memset(&wr, 0, sizeof(wr));
- wr.opcode = IB_WR_FAST_REG_MR;
- wr.wr_id = FAST_REG_WR_ID_MASK;
- wr.wr.fast_reg.iova_start = state->base_dma_addr;
- wr.wr.fast_reg.page_list = desc->frpl;
- wr.wr.fast_reg.page_list_len = state->npages;
- wr.wr.fast_reg.page_shift = ilog2(dev->mr_page_size);
- wr.wr.fast_reg.length = state->dma_len;
- wr.wr.fast_reg.access_flags = (IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_READ |
- IB_ACCESS_REMOTE_WRITE);
- wr.wr.fast_reg.rkey = desc->mr->lkey;
+ n = ib_map_mr_sg(desc->mr, state->sg, state->sg_nents,
+ dev->mr_page_size);
+ if (unlikely(n < 0))
+ return n;
+
+ wr.wr.next = NULL;
+ wr.wr.opcode = IB_WR_REG_MR;
+ wr.wr.wr_id = FAST_REG_WR_ID_MASK;
+ wr.wr.num_sge = 0;
+ wr.wr.send_flags = 0;
+ wr.mr = desc->mr;
+ wr.key = desc->mr->rkey;
+ wr.access = (IB_ACCESS_LOCAL_WRITE |
+ IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_WRITE);
*state->fr.next++ = desc;
state->nmdesc++;
- srp_map_desc(state, state->base_dma_addr, state->dma_len,
- desc->mr->rkey);
+ srp_map_desc(state, desc->mr->iova,
+ desc->mr->length, desc->mr->rkey);
- return ib_post_send(ch->qp, &wr, &bad_wr);
-}
+ err = ib_post_send(ch->qp, &wr.wr, &bad_wr);
+ if (unlikely(err))
+ return err;
-static int srp_finish_mapping(struct srp_map_state *state,
- struct srp_rdma_ch *ch)
-{
- struct srp_target_port *target = ch->target;
- struct srp_device *dev = target->srp_host->srp_dev;
- int ret = 0;
-
- WARN_ON_ONCE(!dev->use_fast_reg && !dev->use_fmr);
-
- if (state->npages == 0)
- return 0;
-
- if (state->npages == 1 && target->global_mr)
- srp_map_desc(state, state->base_dma_addr, state->dma_len,
- target->global_mr->rkey);
- else
- ret = dev->use_fast_reg ? srp_map_finish_fr(state, ch) :
- srp_map_finish_fmr(state, ch);
-
- if (ret == 0) {
- state->npages = 0;
- state->dma_len = 0;
- }
-
- return ret;
+ return n;
}
static int srp_map_sg_entry(struct srp_map_state *state,
@@ -1389,7 +1387,7 @@ static int srp_map_sg_entry(struct srp_map_state *state,
while (dma_len) {
unsigned offset = dma_addr & ~dev->mr_page_mask;
if (state->npages == dev->max_pages_per_mr || offset != 0) {
- ret = srp_finish_mapping(state, ch);
+ ret = srp_map_finish_fmr(state, ch);
if (ret)
return ret;
}
@@ -1411,51 +1409,83 @@ static int srp_map_sg_entry(struct srp_map_state *state,
*/
ret = 0;
if (len != dev->mr_page_size)
- ret = srp_finish_mapping(state, ch);
+ ret = srp_map_finish_fmr(state, ch);
return ret;
}
-static int srp_map_sg(struct srp_map_state *state, struct srp_rdma_ch *ch,
- struct srp_request *req, struct scatterlist *scat,
- int count)
+static int srp_map_sg_fmr(struct srp_map_state *state, struct srp_rdma_ch *ch,
+ struct srp_request *req, struct scatterlist *scat,
+ int count)
{
- struct srp_target_port *target = ch->target;
- struct srp_device *dev = target->srp_host->srp_dev;
struct scatterlist *sg;
int i, ret;
- state->desc = req->indirect_desc;
- state->pages = req->map_page;
- if (dev->use_fast_reg) {
- state->fr.next = req->fr_list;
- state->fr.end = req->fr_list + target->cmd_sg_cnt;
- } else if (dev->use_fmr) {
- state->fmr.next = req->fmr_list;
- state->fmr.end = req->fmr_list + target->cmd_sg_cnt;
- }
+ state->desc = req->indirect_desc;
+ state->pages = req->map_page;
+ state->fmr.next = req->fmr_list;
+ state->fmr.end = req->fmr_list + ch->target->cmd_sg_cnt;
- if (dev->use_fast_reg || dev->use_fmr) {
- for_each_sg(scat, sg, count, i) {
- ret = srp_map_sg_entry(state, ch, sg, i);
- if (ret)
- goto out;
- }
- ret = srp_finish_mapping(state, ch);
+ for_each_sg(scat, sg, count, i) {
+ ret = srp_map_sg_entry(state, ch, sg, i);
if (ret)
- goto out;
- } else {
- for_each_sg(scat, sg, count, i) {
- srp_map_desc(state, ib_sg_dma_address(dev->dev, sg),
- ib_sg_dma_len(dev->dev, sg),
- target->global_mr->rkey);
- }
+ return ret;
}
+ ret = srp_map_finish_fmr(state, ch);
+ if (ret)
+ return ret;
+
req->nmdesc = state->nmdesc;
- ret = 0;
-out:
- return ret;
+ return 0;
+}
+
+static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
+ struct srp_request *req, struct scatterlist *scat,
+ int count)
+{
+ state->desc = req->indirect_desc;
+ state->fr.next = req->fr_list;
+ state->fr.end = req->fr_list + ch->target->cmd_sg_cnt;
+ state->sg = scat;
+ state->sg_nents = scsi_sg_count(req->scmnd);
+
+ while (state->sg_nents) {
+ int i, n;
+
+ n = srp_map_finish_fr(state, ch);
+ if (unlikely(n < 0))
+ return n;
+
+ state->sg_nents -= n;
+ for (i = 0; i < n; i++)
+ state->sg = sg_next(state->sg);
+ }
+
+ req->nmdesc = state->nmdesc;
+
+ return 0;
+}
+
+static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
+ struct srp_request *req, struct scatterlist *scat,
+ int count)
+{
+ struct srp_target_port *target = ch->target;
+ struct srp_device *dev = target->srp_host->srp_dev;
+ struct scatterlist *sg;
+ int i;
+
+ state->desc = req->indirect_desc;
+ for_each_sg(scat, sg, count, i) {
+ srp_map_desc(state, ib_sg_dma_address(dev->dev, sg),
+ ib_sg_dma_len(dev->dev, sg),
+ target->global_mr->rkey);
+ }
+
+ req->nmdesc = state->nmdesc;
+
+ return 0;
}
/*
@@ -1474,6 +1504,7 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
struct srp_map_state state;
struct srp_direct_buf idb_desc;
u64 idb_pages[1];
+ struct scatterlist idb_sg[1];
int ret;
memset(&state, 0, sizeof(state));
@@ -1481,20 +1512,32 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
state.gen.next = next_mr;
state.gen.end = end_mr;
state.desc = &idb_desc;
- state.pages = idb_pages;
- state.pages[0] = (req->indirect_dma_addr &
- dev->mr_page_mask);
- state.npages = 1;
state.base_dma_addr = req->indirect_dma_addr;
state.dma_len = idb_len;
- ret = srp_finish_mapping(&state, ch);
- if (ret < 0)
- goto out;
+
+ if (dev->use_fast_reg) {
+ state.sg = idb_sg;
+ state.sg_nents = 1;
+ sg_set_buf(idb_sg, req->indirect_desc, idb_len);
+ idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
+ ret = srp_map_finish_fr(&state, ch);
+ if (ret < 0)
+ return ret;
+ } else if (dev->use_fmr) {
+ state.pages = idb_pages;
+ state.pages[0] = (req->indirect_dma_addr &
+ dev->mr_page_mask);
+ state.npages = 1;
+ ret = srp_map_finish_fmr(&state, ch);
+ if (ret < 0)
+ return ret;
+ } else {
+ return -EINVAL;
+ }
*idb_rkey = idb_desc.key;
-out:
- return ret;
+ return 0;
}
static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
@@ -1563,7 +1606,12 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
target->indirect_size, DMA_TO_DEVICE);
memset(&state, 0, sizeof(state));
- srp_map_sg(&state, ch, req, scat, count);
+ if (dev->use_fast_reg)
+ srp_map_sg_fr(&state, ch, req, scat, count);
+ else if (dev->use_fmr)
+ srp_map_sg_fmr(&state, ch, req, scat, count);
+ else
+ srp_map_sg_dma(&state, ch, req, scat, count);
/* We've mapped the request, now pull as much of the indirect
* descriptor table as we can into the command buffer. If this
@@ -2750,7 +2798,6 @@ static struct scsi_host_template srp_template = {
.cmd_per_lun = SRP_DEFAULT_CMD_SQ_SIZE,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = srp_host_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -3181,10 +3228,6 @@ static ssize_t srp_create_target(struct device *dev,
if (ret)
goto out;
- ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
- if (ret)
- goto out;
-
target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
if (!srp_conn_unique(target->srp_host, target)) {
@@ -3213,7 +3256,7 @@ static ssize_t srp_create_target(struct device *dev,
INIT_WORK(&target->tl_err_work, srp_tl_err_work);
INIT_WORK(&target->remove_work, srp_remove_work);
spin_lock_init(&target->lock);
- ret = ib_query_gid(ibdev, host->port, 0, &target->sgid);
+ ret = ib_query_gid(ibdev, host->port, 0, &target->sgid, NULL);
if (ret)
goto out;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 3608f2e4819c..87a2a919dc43 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -242,7 +242,6 @@ struct srp_iu {
struct srp_fr_desc {
struct list_head entry;
struct ib_mr *mr;
- struct ib_fast_reg_page_list *frpl;
};
/**
@@ -294,11 +293,17 @@ struct srp_map_state {
} gen;
};
struct srp_direct_buf *desc;
- u64 *pages;
+ union {
+ u64 *pages;
+ struct scatterlist *sg;
+ };
dma_addr_t base_dma_addr;
u32 dma_len;
u32 total_len;
- unsigned int npages;
+ union {
+ unsigned int npages;
+ int sg_nents;
+ };
unsigned int nmdesc;
unsigned int ndesc;
};
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index f6fe0414139b..2e2fe818ca9f 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -43,9 +43,7 @@
#include <linux/atomic.h>
#include <scsi/scsi_proto.h>
#include <scsi/scsi_tcq.h>
-#include <target/configfs_macros.h>
#include <target/target_core_base.h>
-#include <target/target_core_fabric_configfs.h>
#include <target/target_core_fabric.h>
#include "ib_srpt.h"
@@ -546,7 +544,8 @@ static int srpt_refresh_port(struct srpt_port *sport)
sport->sm_lid = port_attr.sm_lid;
sport->lid = port_attr.lid;
- ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);
+ ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid,
+ NULL);
if (ret)
goto err_query_port;
@@ -2822,7 +2821,7 @@ static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
struct srpt_send_ioctx *ioctx)
{
- struct ib_send_wr wr;
+ struct ib_rdma_wr wr;
struct ib_send_wr *bad_wr;
struct rdma_iu *riu;
int i;
@@ -2850,29 +2849,29 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
for (i = 0; i < n_rdma; ++i, ++riu) {
if (dir == DMA_FROM_DEVICE) {
- wr.opcode = IB_WR_RDMA_WRITE;
- wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+ wr.wr.opcode = IB_WR_RDMA_WRITE;
+ wr.wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
SRPT_RDMA_WRITE_LAST :
SRPT_RDMA_MID,
ioctx->ioctx.index);
} else {
- wr.opcode = IB_WR_RDMA_READ;
- wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+ wr.wr.opcode = IB_WR_RDMA_READ;
+ wr.wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
SRPT_RDMA_READ_LAST :
SRPT_RDMA_MID,
ioctx->ioctx.index);
}
- wr.next = NULL;
- wr.wr.rdma.remote_addr = riu->raddr;
- wr.wr.rdma.rkey = riu->rkey;
- wr.num_sge = riu->sge_cnt;
- wr.sg_list = riu->sge;
+ wr.wr.next = NULL;
+ wr.remote_addr = riu->raddr;
+ wr.rkey = riu->rkey;
+ wr.wr.num_sge = riu->sge_cnt;
+ wr.wr.sg_list = riu->sge;
/* only get completion event for the last rdma write */
if (i == (n_rdma - 1) && dir == DMA_TO_DEVICE)
- wr.send_flags = IB_SEND_SIGNALED;
+ wr.wr.send_flags = IB_SEND_SIGNALED;
- ret = ib_post_send(ch->qp, &wr, &bad_wr);
+ ret = ib_post_send(ch->qp, &wr.wr, &bad_wr);
if (ret)
break;
}
@@ -2881,11 +2880,11 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
pr_err("%s[%d]: ib_post_send() returned %d for %d/%d\n",
__func__, __LINE__, ret, i, n_rdma);
if (ret && i > 0) {
- wr.num_sge = 0;
- wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
- wr.send_flags = IB_SEND_SIGNALED;
+ wr.wr.num_sge = 0;
+ wr.wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
+ wr.wr.send_flags = IB_SEND_SIGNALED;
while (ch->state == CH_LIVE &&
- ib_post_send(ch->qp, &wr, &bad_wr) != 0) {
+ ib_post_send(ch->qp, &wr.wr, &bad_wr) != 0) {
pr_info("Trying to abort failed RDMA transfer [%d]\n",
ioctx->ioctx.index);
msleep(1000);
@@ -3545,20 +3544,19 @@ static void srpt_cleanup_nodeacl(struct se_node_acl *se_nacl)
spin_unlock_irq(&sport->port_acl_lock);
}
-static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t srpt_tpg_attrib_srp_max_rdma_size_show(struct config_item *item,
+ char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
return sprintf(page, "%u\n", sport->port_attrib.srp_max_rdma_size);
}
-static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t srpt_tpg_attrib_srp_max_rdma_size_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
unsigned long val;
int ret;
@@ -3583,22 +3581,19 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
return count;
}
-TF_TPG_ATTRIB_ATTR(srpt, srp_max_rdma_size, S_IRUGO | S_IWUSR);
-
-static ssize_t srpt_tpg_attrib_show_srp_max_rsp_size(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t srpt_tpg_attrib_srp_max_rsp_size_show(struct config_item *item,
+ char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
return sprintf(page, "%u\n", sport->port_attrib.srp_max_rsp_size);
}
-static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t srpt_tpg_attrib_srp_max_rsp_size_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
unsigned long val;
int ret;
@@ -3623,22 +3618,19 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
return count;
}
-TF_TPG_ATTRIB_ATTR(srpt, srp_max_rsp_size, S_IRUGO | S_IWUSR);
-
-static ssize_t srpt_tpg_attrib_show_srp_sq_size(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t srpt_tpg_attrib_srp_sq_size_show(struct config_item *item,
+ char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
return sprintf(page, "%u\n", sport->port_attrib.srp_sq_size);
}
-static ssize_t srpt_tpg_attrib_store_srp_sq_size(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t srpt_tpg_attrib_srp_sq_size_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
unsigned long val;
int ret;
@@ -3663,29 +3655,29 @@ static ssize_t srpt_tpg_attrib_store_srp_sq_size(
return count;
}
-TF_TPG_ATTRIB_ATTR(srpt, srp_sq_size, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(srpt_tpg_attrib_, srp_max_rdma_size);
+CONFIGFS_ATTR(srpt_tpg_attrib_, srp_max_rsp_size);
+CONFIGFS_ATTR(srpt_tpg_attrib_, srp_sq_size);
static struct configfs_attribute *srpt_tpg_attrib_attrs[] = {
- &srpt_tpg_attrib_srp_max_rdma_size.attr,
- &srpt_tpg_attrib_srp_max_rsp_size.attr,
- &srpt_tpg_attrib_srp_sq_size.attr,
+ &srpt_tpg_attrib_attr_srp_max_rdma_size,
+ &srpt_tpg_attrib_attr_srp_max_rsp_size,
+ &srpt_tpg_attrib_attr_srp_sq_size,
NULL,
};
-static ssize_t srpt_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t srpt_tpg_enable_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
return snprintf(page, PAGE_SIZE, "%d\n", (sport->enabled) ? 1: 0);
}
-static ssize_t srpt_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t srpt_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
unsigned long tmp;
int ret;
@@ -3708,10 +3700,10 @@ static ssize_t srpt_tpg_store_enable(
return count;
}
-TF_TPG_BASE_ATTR(srpt, enable, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(srpt_tpg_, enable);
static struct configfs_attribute *srpt_tpg_attrs[] = {
- &srpt_tpg_enable.attr,
+ &srpt_tpg_attr_enable,
NULL,
};
@@ -3781,16 +3773,15 @@ static void srpt_drop_tport(struct se_wwn *wwn)
pr_debug("drop_tport(%s\n", config_item_name(&sport->port_wwn.wwn_group.cg_item));
}
-static ssize_t srpt_wwn_show_attr_version(struct target_fabric_configfs *tf,
- char *buf)
+static ssize_t srpt_wwn_version_show(struct config_item *item, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", DRV_VERSION);
}
-TF_WWN_ATTR_RO(srpt, version);
+CONFIGFS_ATTR_RO(srpt_wwn_, version);
static struct configfs_attribute *srpt_wwn_attrs[] = {
- &srpt_wwn_version.attr,
+ &srpt_wwn_attr_version,
NULL,
};
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 08d496411f75..e9ae3d500a55 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -56,12 +56,57 @@ struct evdev_client {
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
- int clk_type;
+ unsigned int clk_type;
bool revoked;
+ unsigned long *evmasks[EV_CNT];
unsigned int bufsize;
struct input_event buffer[];
};
+static size_t evdev_get_mask_cnt(unsigned int type)
+{
+ static const size_t counts[EV_CNT] = {
+ /* EV_SYN==0 is EV_CNT, _not_ SYN_CNT, see EVIOCGBIT */
+ [EV_SYN] = EV_CNT,
+ [EV_KEY] = KEY_CNT,
+ [EV_REL] = REL_CNT,
+ [EV_ABS] = ABS_CNT,
+ [EV_MSC] = MSC_CNT,
+ [EV_SW] = SW_CNT,
+ [EV_LED] = LED_CNT,
+ [EV_SND] = SND_CNT,
+ [EV_FF] = FF_CNT,
+ };
+
+ return (type < EV_CNT) ? counts[type] : 0;
+}
+
+/* requires the buffer lock to be held */
+static bool __evdev_is_filtered(struct evdev_client *client,
+ unsigned int type,
+ unsigned int code)
+{
+ unsigned long *mask;
+ size_t cnt;
+
+ /* EV_SYN and unknown codes are never filtered */
+ if (type == EV_SYN || type >= EV_CNT)
+ return false;
+
+ /* first test whether the type is filtered */
+ mask = client->evmasks[0];
+ if (mask && !test_bit(type, mask))
+ return true;
+
+ /* unknown values are never filtered */
+ cnt = evdev_get_mask_cnt(type);
+ if (!cnt || code >= cnt)
+ return false;
+
+ mask = client->evmasks[type];
+ return mask && !test_bit(code, mask);
+}
+
/* flush queued events of type @type, caller must hold client->buffer_lock */
static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
{
@@ -146,37 +191,39 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
{
unsigned long flags;
-
- if (client->clk_type == clkid)
- return 0;
+ unsigned int clk_type;
switch (clkid) {
case CLOCK_REALTIME:
- client->clk_type = EV_CLK_REAL;
+ clk_type = EV_CLK_REAL;
break;
case CLOCK_MONOTONIC:
- client->clk_type = EV_CLK_MONO;
+ clk_type = EV_CLK_MONO;
break;
case CLOCK_BOOTTIME:
- client->clk_type = EV_CLK_BOOT;
+ clk_type = EV_CLK_BOOT;
break;
default:
return -EINVAL;
}
- /*
- * Flush pending events and queue SYN_DROPPED event,
- * but only if the queue is not empty.
- */
- spin_lock_irqsave(&client->buffer_lock, flags);
+ if (client->clk_type != clk_type) {
+ client->clk_type = clk_type;
- if (client->head != client->tail) {
- client->packet_head = client->head = client->tail;
- __evdev_queue_syn_dropped(client);
- }
+ /*
+ * Flush pending events and queue SYN_DROPPED event,
+ * but only if the queue is not empty.
+ */
+ spin_lock_irqsave(&client->buffer_lock, flags);
- spin_unlock_irqrestore(&client->buffer_lock, flags);
+ if (client->head != client->tail) {
+ client->packet_head = client->head = client->tail;
+ __evdev_queue_syn_dropped(client);
+ }
+
+ spin_unlock_irqrestore(&client->buffer_lock, flags);
+ }
return 0;
}
@@ -226,12 +273,21 @@ static void evdev_pass_values(struct evdev_client *client,
spin_lock(&client->buffer_lock);
for (v = vals; v != vals + count; v++) {
+ if (__evdev_is_filtered(client, v->type, v->code))
+ continue;
+
+ if (v->type == EV_SYN && v->code == SYN_REPORT) {
+ /* drop empty SYN_REPORT */
+ if (client->packet_head == client->head)
+ continue;
+
+ wakeup = true;
+ }
+
event.type = v->type;
event.code = v->code;
event.value = v->value;
__pass_event(client, &event);
- if (v->type == EV_SYN && v->code == SYN_REPORT)
- wakeup = true;
}
spin_unlock(&client->buffer_lock);
@@ -410,6 +466,7 @@ static int evdev_release(struct inode *inode, struct file *file)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
+ unsigned int i;
mutex_lock(&evdev->mutex);
evdev_ungrab(evdev, client);
@@ -417,6 +474,9 @@ static int evdev_release(struct inode *inode, struct file *file)
evdev_detach_client(evdev, client);
+ for (i = 0; i < EV_CNT; ++i)
+ kfree(client->evmasks[i]);
+
kvfree(client);
evdev_close_device(evdev);
@@ -627,7 +687,46 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
return len;
}
+
+static int bits_from_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, const void __user *p, int compat)
+{
+ int len, i;
+
+ if (compat) {
+ if (maxlen % sizeof(compat_long_t))
+ return -EINVAL;
+
+ len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
+ if (len > maxlen)
+ len = maxlen;
+
+ for (i = 0; i < len / sizeof(compat_long_t); i++)
+ if (copy_from_user((compat_long_t *) bits +
+ i + 1 - ((i % 2) << 1),
+ (compat_long_t __user *) p + i,
+ sizeof(compat_long_t)))
+ return -EFAULT;
+ if (i % 2)
+ *((compat_long_t *) bits + i - 1) = 0;
+
+ } else {
+ if (maxlen % sizeof(long))
+ return -EINVAL;
+
+ len = BITS_TO_LONGS(maxbit) * sizeof(long);
+ if (len > maxlen)
+ len = maxlen;
+
+ if (copy_from_user(bits, p, len))
+ return -EFAULT;
+ }
+
+ return len;
+}
+
#else
+
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, void __user *p, int compat)
{
@@ -640,6 +739,24 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
return copy_to_user(p, bits, len) ? -EFAULT : len;
}
+
+static int bits_from_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, const void __user *p, int compat)
+{
+ size_t chunk_size = compat ? sizeof(compat_long_t) : sizeof(long);
+ int len;
+
+ if (maxlen % chunk_size)
+ return -EINVAL;
+
+ len = compat ? BITS_TO_LONGS_COMPAT(maxbit) : BITS_TO_LONGS(maxbit);
+ len *= chunk_size;
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_from_user(bits, p, len) ? -EFAULT : len;
+}
+
#endif /* __BIG_ENDIAN */
#else
@@ -655,6 +772,21 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
return copy_to_user(p, bits, len) ? -EFAULT : len;
}
+static int bits_from_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, const void __user *p, int compat)
+{
+ int len;
+
+ if (maxlen % sizeof(long))
+ return -EINVAL;
+
+ len = BITS_TO_LONGS(maxbit) * sizeof(long);
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_from_user(bits, p, len) ? -EFAULT : len;
+}
+
#endif /* CONFIG_COMPAT */
static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
@@ -849,6 +981,81 @@ static int evdev_revoke(struct evdev *evdev, struct evdev_client *client,
return 0;
}
+/* must be called with evdev-mutex held */
+static int evdev_set_mask(struct evdev_client *client,
+ unsigned int type,
+ const void __user *codes,
+ u32 codes_size,
+ int compat)
+{
+ unsigned long flags, *mask, *oldmask;
+ size_t cnt;
+ int error;
+
+ /* we allow unknown types and 'codes_size > size' for forward-compat */
+ cnt = evdev_get_mask_cnt(type);
+ if (!cnt)
+ return 0;
+
+ mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL);
+ if (!mask)
+ return -ENOMEM;
+
+ error = bits_from_user(mask, cnt - 1, codes_size, codes, compat);
+ if (error < 0) {
+ kfree(mask);
+ return error;
+ }
+
+ spin_lock_irqsave(&client->buffer_lock, flags);
+ oldmask = client->evmasks[type];
+ client->evmasks[type] = mask;
+ spin_unlock_irqrestore(&client->buffer_lock, flags);
+
+ kfree(oldmask);
+
+ return 0;
+}
+
+/* must be called with evdev-mutex held */
+static int evdev_get_mask(struct evdev_client *client,
+ unsigned int type,
+ void __user *codes,
+ u32 codes_size,
+ int compat)
+{
+ unsigned long *mask;
+ size_t cnt, size, xfer_size;
+ int i;
+ int error;
+
+ /* we allow unknown types and 'codes_size > size' for forward-compat */
+ cnt = evdev_get_mask_cnt(type);
+ size = sizeof(unsigned long) * BITS_TO_LONGS(cnt);
+ xfer_size = min_t(size_t, codes_size, size);
+
+ if (cnt > 0) {
+ mask = client->evmasks[type];
+ if (mask) {
+ error = bits_to_user(mask, cnt - 1,
+ xfer_size, codes, compat);
+ if (error < 0)
+ return error;
+ } else {
+ /* fake mask with all bits set */
+ for (i = 0; i < xfer_size; i++)
+ if (put_user(0xffU, (u8 __user *)codes + i))
+ return -EFAULT;
+ }
+ }
+
+ if (xfer_size < codes_size)
+ if (clear_user(codes + xfer_size, codes_size - xfer_size))
+ return -EFAULT;
+
+ return 0;
+}
+
static long evdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p, int compat_mode)
{
@@ -856,6 +1063,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
struct evdev *evdev = client->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
+ struct input_mask mask;
struct ff_effect effect;
int __user *ip = (int __user *)p;
unsigned int i, t, u, v;
@@ -917,6 +1125,30 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
else
return evdev_revoke(evdev, client, file);
+ case EVIOCGMASK: {
+ void __user *codes_ptr;
+
+ if (copy_from_user(&mask, p, sizeof(mask)))
+ return -EFAULT;
+
+ codes_ptr = (void __user *)(unsigned long)mask.codes_ptr;
+ return evdev_get_mask(client,
+ mask.type, codes_ptr, mask.codes_size,
+ compat_mode);
+ }
+
+ case EVIOCSMASK: {
+ const void __user *codes_ptr;
+
+ if (copy_from_user(&mask, p, sizeof(mask)))
+ return -EFAULT;
+
+ codes_ptr = (const void __user *)(unsigned long)mask.codes_ptr;
+ return evdev_set_mask(client,
+ mask.type, codes_ptr, mask.codes_size,
+ compat_mode);
+ }
+
case EVIOCSCLOCKID:
if (copy_from_user(&i, p, sizeof(unsigned int)))
return -EFAULT;
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index c64208267198..8f2042432c85 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -273,14 +273,14 @@ int input_ff_event(struct input_dev *dev, unsigned int type,
switch (code) {
case FF_GAIN:
- if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff)
+ if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU)
break;
ff->set_gain(dev, value);
break;
case FF_AUTOCENTER:
- if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff)
+ if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU)
break;
ff->set_autocenter(dev, value);
@@ -318,6 +318,11 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
return -EINVAL;
}
+ if (max_effects > FF_MAX_EFFECTS) {
+ dev_err(&dev->dev, "cannot allocate more than FF_MAX_EFFECTS effects\n");
+ return -EINVAL;
+ }
+
ff_dev_size = sizeof(struct ff_device) +
max_effects * sizeof(struct file *);
if (ff_dev_size < max_effects) /* overflow */
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5391abd28b27..880605959aa6 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2045,6 +2045,23 @@ static void devm_input_device_unregister(struct device *dev, void *res)
}
/**
+ * input_enable_softrepeat - enable software autorepeat
+ * @dev: input device
+ * @delay: repeat delay
+ * @period: repeat period
+ *
+ * Enable software autorepeat on the input device.
+ */
+void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
+{
+ dev->timer.data = (unsigned long) dev;
+ dev->timer.function = input_repeat_key;
+ dev->rep[REP_DELAY] = delay;
+ dev->rep[REP_PERIOD] = period;
+}
+EXPORT_SYMBOL(input_enable_softrepeat);
+
+/**
* input_register_device - register device with input core
* @dev: device to be registered
*
@@ -2108,12 +2125,8 @@ int input_register_device(struct input_dev *dev)
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
*/
- if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
- dev->timer.data = (long) dev;
- dev->timer.function = input_repeat_key;
- dev->rep[REP_DELAY] = 250;
- dev->rep[REP_PERIOD] = 33;
- }
+ if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD])
+ input_enable_softrepeat(dev, 250, 33);
if (!dev->getkeycode)
dev->getkeycode = input_default_getkeycode;
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 6cb5a3e5f9a1..5d11fea3c8ec 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -444,14 +444,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
len = min(len, sizeof(joydev->abspam));
/* Validate the map. */
- abspam = kmalloc(len, GFP_KERNEL);
- if (!abspam)
- return -ENOMEM;
-
- if (copy_from_user(abspam, argp, len)) {
- retval = -EFAULT;
- goto out;
- }
+ abspam = memdup_user(argp, len);
+ if (IS_ERR(abspam))
+ return PTR_ERR(abspam);
for (i = 0; i < joydev->nabs; i++) {
if (abspam[i] > ABS_MAX) {
@@ -480,14 +475,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
len = min(len, sizeof(joydev->keypam));
/* Validate the map. */
- keypam = kmalloc(len, GFP_KERNEL);
- if (!keypam)
- return -ENOMEM;
-
- if (copy_from_user(keypam, argp, len)) {
- retval = -EFAULT;
- goto out;
- }
+ keypam = memdup_user(argp, len);
+ if (IS_ERR(keypam))
+ return PTR_ERR(keypam);
for (i = 0; i < joydev->nkey; i++) {
if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 8e7de5c7754f..932d07307454 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -48,7 +48,7 @@ struct db9_config {
};
#define DB9_MAX_PORTS 3
-static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata;
+static struct db9_config db9_cfg[DB9_MAX_PORTS];
module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0);
MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
@@ -106,6 +106,7 @@ struct db9 {
struct pardevice *pd;
int mode;
int used;
+ int parportno;
struct mutex mutex;
char phys[DB9_MAX_DEVICES][32];
};
@@ -553,54 +554,60 @@ static void db9_close(struct input_dev *dev)
mutex_unlock(&db9->mutex);
}
-static struct db9 __init *db9_probe(int parport, int mode)
+static void db9_attach(struct parport *pp)
{
struct db9 *db9;
const struct db9_mode_data *db9_mode;
- struct parport *pp;
struct pardevice *pd;
struct input_dev *input_dev;
- int i, j;
- int err;
+ int i, j, port_idx;
+ int mode;
+ struct pardev_cb db9_parport_cb;
+
+ for (port_idx = 0; port_idx < DB9_MAX_PORTS; port_idx++) {
+ if (db9_cfg[port_idx].nargs == 0 ||
+ db9_cfg[port_idx].args[DB9_ARG_PARPORT] < 0)
+ continue;
+
+ if (db9_cfg[port_idx].args[DB9_ARG_PARPORT] == pp->number)
+ break;
+ }
+
+ if (port_idx == DB9_MAX_PORTS) {
+ pr_debug("Not using parport%d.\n", pp->number);
+ return;
+ }
+
+ mode = db9_cfg[port_idx].args[DB9_ARG_MODE];
if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
- err = -EINVAL;
- goto err_out;
+ return;
}
db9_mode = &db9_modes[mode];
- pp = parport_find_number(parport);
- if (!pp) {
- printk(KERN_ERR "db9.c: no such parport\n");
- err = -ENODEV;
- goto err_out;
- }
-
if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
- err = -EINVAL;
- goto err_put_pp;
+ return;
}
- pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ db9_parport_cb.flags = PARPORT_FLAG_EXCL;
+
+ pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx);
if (!pd) {
printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
- err = -EBUSY;
- goto err_put_pp;
+ return;
}
db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
- if (!db9) {
- printk(KERN_ERR "db9.c: Not enough memory\n");
- err = -ENOMEM;
+ if (!db9)
goto err_unreg_pardev;
- }
mutex_init(&db9->mutex);
db9->pd = pd;
db9->mode = mode;
+ db9->parportno = pp->number;
init_timer(&db9->timer);
db9->timer.data = (long) db9;
db9->timer.function = db9_timer;
@@ -610,7 +617,6 @@ static struct db9 __init *db9_probe(int parport, int mode)
db9->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "db9.c: Not enough memory for input device\n");
- err = -ENOMEM;
goto err_unreg_devs;
}
@@ -639,13 +645,12 @@ static struct db9 __init *db9_probe(int parport, int mode)
input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
}
- err = input_register_device(input_dev);
- if (err)
+ if (input_register_device(input_dev))
goto err_free_dev;
}
- parport_put_port(pp);
- return db9;
+ db9_base[port_idx] = db9;
+ return;
err_free_dev:
input_free_device(db9->dev[i]);
@@ -655,15 +660,23 @@ static struct db9 __init *db9_probe(int parport, int mode)
kfree(db9);
err_unreg_pardev:
parport_unregister_device(pd);
- err_put_pp:
- parport_put_port(pp);
- err_out:
- return ERR_PTR(err);
}
-static void db9_remove(struct db9 *db9)
+static void db9_detach(struct parport *port)
{
int i;
+ struct db9 *db9;
+
+ for (i = 0; i < DB9_MAX_PORTS; i++) {
+ if (db9_base[i] && db9_base[i]->parportno == port->number)
+ break;
+ }
+
+ if (i == DB9_MAX_PORTS)
+ return;
+
+ db9 = db9_base[i];
+ db9_base[i] = NULL;
for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
input_unregister_device(db9->dev[i]);
@@ -671,11 +684,17 @@ static void db9_remove(struct db9 *db9)
kfree(db9);
}
+static struct parport_driver db9_parport_driver = {
+ .name = "db9",
+ .match_port = db9_attach,
+ .detach = db9_detach,
+ .devmodel = true,
+};
+
static int __init db9_init(void)
{
int i;
int have_dev = 0;
- int err = 0;
for (i = 0; i < DB9_MAX_PORTS; i++) {
if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0)
@@ -683,37 +702,21 @@ static int __init db9_init(void)
if (db9_cfg[i].nargs < 2) {
printk(KERN_ERR "db9.c: Device type must be specified.\n");
- err = -EINVAL;
- break;
- }
-
- db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT],
- db9_cfg[i].args[DB9_ARG_MODE]);
- if (IS_ERR(db9_base[i])) {
- err = PTR_ERR(db9_base[i]);
- break;
+ return -EINVAL;
}
have_dev = 1;
}
- if (err) {
- while (--i >= 0)
- if (db9_base[i])
- db9_remove(db9_base[i]);
- return err;
- }
+ if (!have_dev)
+ return -ENODEV;
- return have_dev ? 0 : -ENODEV;
+ return parport_register_driver(&db9_parport_driver);
}
static void __exit db9_exit(void)
{
- int i;
-
- for (i = 0; i < DB9_MAX_PORTS; i++)
- if (db9_base[i])
- db9_remove(db9_base[i]);
+ parport_unregister_driver(&db9_parport_driver);
}
module_init(db9_init);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index e68e49786483..5a672dcac0d8 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -53,7 +53,7 @@ struct gc_config {
unsigned int nargs;
};
-static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata;
+static struct gc_config gc_cfg[GC_MAX_PORTS];
module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
@@ -92,6 +92,7 @@ struct gc {
struct timer_list timer;
int pad_count[GC_MAX];
int used;
+ int parportno;
struct mutex mutex;
};
@@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data,
return 0;
}
-static int __init gc_n64_init_ff(struct input_dev *dev, int i)
+static int gc_n64_init_ff(struct input_dev *dev, int i)
{
struct gc_subdev *sdev;
int err;
@@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev)
mutex_unlock(&gc->mutex);
}
-static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
+static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
{
struct gc_pad *pad = &gc->pads[idx];
struct input_dev *input_dev;
@@ -926,46 +927,55 @@ err_free_dev:
return err;
}
-static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
+static void gc_attach(struct parport *pp)
{
struct gc *gc;
- struct parport *pp;
struct pardevice *pd;
- int i;
+ int i, port_idx;
int count = 0;
- int err;
+ int *pads, n_pads;
+ struct pardev_cb gc_parport_cb;
+
+ for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) {
+ if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0)
+ continue;
+
+ if (gc_cfg[port_idx].args[0] == pp->number)
+ break;
+ }
- pp = parport_find_number(parport);
- if (!pp) {
- pr_err("no such parport %d\n", parport);
- err = -EINVAL;
- goto err_out;
+ if (port_idx == GC_MAX_PORTS) {
+ pr_debug("Not using parport%d.\n", pp->number);
+ return;
}
+ pads = gc_cfg[port_idx].args + 1;
+ n_pads = gc_cfg[port_idx].nargs - 1;
- pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ gc_parport_cb.flags = PARPORT_FLAG_EXCL;
+
+ pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb,
+ port_idx);
if (!pd) {
pr_err("parport busy already - lp.o loaded?\n");
- err = -EBUSY;
- goto err_put_pp;
+ return;
}
gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
if (!gc) {
pr_err("Not enough memory\n");
- err = -ENOMEM;
goto err_unreg_pardev;
}
mutex_init(&gc->mutex);
gc->pd = pd;
+ gc->parportno = pp->number;
setup_timer(&gc->timer, gc_timer, (long) gc);
for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
if (!pads[i])
continue;
- err = gc_setup_pad(gc, i, pads[i]);
- if (err)
+ if (gc_setup_pad(gc, i, pads[i]))
goto err_unreg_devs;
count++;
@@ -973,12 +983,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
if (count == 0) {
pr_err("No valid devices specified\n");
- err = -EINVAL;
goto err_free_gc;
}
- parport_put_port(pp);
- return gc;
+ gc_base[port_idx] = gc;
+ return;
err_unreg_devs:
while (--i >= 0)
@@ -988,15 +997,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
kfree(gc);
err_unreg_pardev:
parport_unregister_device(pd);
- err_put_pp:
- parport_put_port(pp);
- err_out:
- return ERR_PTR(err);
}
-static void gc_remove(struct gc *gc)
+static void gc_detach(struct parport *port)
{
int i;
+ struct gc *gc;
+
+ for (i = 0; i < GC_MAX_PORTS; i++) {
+ if (gc_base[i] && gc_base[i]->parportno == port->number)
+ break;
+ }
+
+ if (i == GC_MAX_PORTS)
+ return;
+
+ gc = gc_base[i];
+ gc_base[i] = NULL;
for (i = 0; i < GC_MAX_DEVICES; i++)
if (gc->pads[i].dev)
@@ -1005,11 +1022,17 @@ static void gc_remove(struct gc *gc)
kfree(gc);
}
+static struct parport_driver gc_parport_driver = {
+ .name = "gamecon",
+ .match_port = gc_attach,
+ .detach = gc_detach,
+ .devmodel = true,
+};
+
static int __init gc_init(void)
{
int i;
int have_dev = 0;
- int err = 0;
for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0)
@@ -1017,37 +1040,21 @@ static int __init gc_init(void)
if (gc_cfg[i].nargs < 2) {
pr_err("at least one device must be specified\n");
- err = -EINVAL;
- break;
- }
-
- gc_base[i] = gc_probe(gc_cfg[i].args[0],
- gc_cfg[i].args + 1, gc_cfg[i].nargs - 1);
- if (IS_ERR(gc_base[i])) {
- err = PTR_ERR(gc_base[i]);
- break;
+ return -EINVAL;
}
have_dev = 1;
}
- if (err) {
- while (--i >= 0)
- if (gc_base[i])
- gc_remove(gc_base[i]);
- return err;
- }
+ if (!have_dev)
+ return -ENODEV;
- return have_dev ? 0 : -ENODEV;
+ return parport_register_driver(&gc_parport_driver);
}
static void __exit gc_exit(void)
{
- int i;
-
- for (i = 0; i < GC_MAX_PORTS; i++)
- if (gc_base[i])
- gc_remove(gc_base[i]);
+ parport_unregister_driver(&gc_parport_driver);
}
module_init(gc_init);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 891797ad76bc..9f5bca26bd2f 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -49,7 +49,7 @@ struct tgfx_config {
unsigned int nargs;
};
-static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata;
+static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS];
module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
@@ -81,6 +81,7 @@ static struct tgfx {
char phys[TGFX_MAX_DEVICES][32];
int sticks;
int used;
+ int parportno;
struct mutex sem;
} *tgfx_base[TGFX_MAX_PORTS];
@@ -156,38 +157,48 @@ static void tgfx_close(struct input_dev *dev)
* tgfx_probe() probes for tg gamepads.
*/
-static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
+static void tgfx_attach(struct parport *pp)
{
struct tgfx *tgfx;
struct input_dev *input_dev;
- struct parport *pp;
struct pardevice *pd;
- int i, j;
- int err;
+ int i, j, port_idx;
+ int *n_buttons, n_devs;
+ struct pardev_cb tgfx_parport_cb;
+
+ for (port_idx = 0; port_idx < TGFX_MAX_PORTS; port_idx++) {
+ if (tgfx_cfg[port_idx].nargs == 0 ||
+ tgfx_cfg[port_idx].args[0] < 0)
+ continue;
+ if (tgfx_cfg[port_idx].args[0] == pp->number)
+ break;
+ }
- pp = parport_find_number(parport);
- if (!pp) {
- printk(KERN_ERR "turbografx.c: no such parport\n");
- err = -EINVAL;
- goto err_out;
+ if (port_idx == TGFX_MAX_PORTS) {
+ pr_debug("Not using parport%d.\n", pp->number);
+ return;
}
+ n_buttons = tgfx_cfg[port_idx].args + 1;
+ n_devs = tgfx_cfg[port_idx].nargs - 1;
+
+ tgfx_parport_cb.flags = PARPORT_FLAG_EXCL;
- pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb,
+ port_idx);
if (!pd) {
- printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
- err = -EBUSY;
- goto err_put_pp;
+ pr_err("parport busy already - lp.o loaded?\n");
+ return;
}
tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
if (!tgfx) {
printk(KERN_ERR "turbografx.c: Not enough memory\n");
- err = -ENOMEM;
goto err_unreg_pardev;
}
mutex_init(&tgfx->sem);
tgfx->pd = pd;
+ tgfx->parportno = pp->number;
init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx;
tgfx->timer.function = tgfx_timer;
@@ -198,14 +209,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
if (n_buttons[i] > ARRAY_SIZE(tgfx_buttons)) {
printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
- err = -EINVAL;
goto err_unreg_devs;
}
tgfx->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
- err = -ENOMEM;
goto err_unreg_devs;
}
@@ -234,19 +243,17 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
for (j = 0; j < n_buttons[i]; j++)
set_bit(tgfx_buttons[j], input_dev->keybit);
- err = input_register_device(tgfx->dev[i]);
- if (err)
+ if (input_register_device(tgfx->dev[i]))
goto err_free_dev;
}
if (!tgfx->sticks) {
printk(KERN_ERR "turbografx.c: No valid devices specified\n");
- err = -EINVAL;
goto err_free_tgfx;
}
- parport_put_port(pp);
- return tgfx;
+ tgfx_base[port_idx] = tgfx;
+ return;
err_free_dev:
input_free_device(tgfx->dev[i]);
@@ -258,15 +265,23 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
kfree(tgfx);
err_unreg_pardev:
parport_unregister_device(pd);
- err_put_pp:
- parport_put_port(pp);
- err_out:
- return ERR_PTR(err);
}
-static void tgfx_remove(struct tgfx *tgfx)
+static void tgfx_detach(struct parport *port)
{
int i;
+ struct tgfx *tgfx;
+
+ for (i = 0; i < TGFX_MAX_PORTS; i++) {
+ if (tgfx_base[i] && tgfx_base[i]->parportno == port->number)
+ break;
+ }
+
+ if (i == TGFX_MAX_PORTS)
+ return;
+
+ tgfx = tgfx_base[i];
+ tgfx_base[i] = NULL;
for (i = 0; i < TGFX_MAX_DEVICES; i++)
if (tgfx->dev[i])
@@ -275,11 +290,17 @@ static void tgfx_remove(struct tgfx *tgfx)
kfree(tgfx);
}
+static struct parport_driver tgfx_parport_driver = {
+ .name = "turbografx",
+ .match_port = tgfx_attach,
+ .detach = tgfx_detach,
+ .devmodel = true,
+};
+
static int __init tgfx_init(void)
{
int i;
int have_dev = 0;
- int err = 0;
for (i = 0; i < TGFX_MAX_PORTS; i++) {
if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0)
@@ -287,38 +308,21 @@ static int __init tgfx_init(void)
if (tgfx_cfg[i].nargs < 2) {
printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
- err = -EINVAL;
- break;
- }
-
- tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0],
- tgfx_cfg[i].args + 1,
- tgfx_cfg[i].nargs - 1);
- if (IS_ERR(tgfx_base[i])) {
- err = PTR_ERR(tgfx_base[i]);
- break;
+ return -EINVAL;
}
have_dev = 1;
}
- if (err) {
- while (--i >= 0)
- if (tgfx_base[i])
- tgfx_remove(tgfx_base[i]);
- return err;
- }
+ if (!have_dev)
+ return -ENODEV;
- return have_dev ? 0 : -ENODEV;
+ return parport_register_driver(&tgfx_parport_driver);
}
static void __exit tgfx_exit(void)
{
- int i;
-
- for (i = 0; i < TGFX_MAX_PORTS; i++)
- if (tgfx_base[i])
- tgfx_remove(tgfx_base[i]);
+ parport_unregister_driver(&tgfx_parport_driver);
}
module_init(tgfx_init);
diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c
index a8bc2fe170dd..9c07fe911075 100644
--- a/drivers/input/joystick/walkera0701.c
+++ b/drivers/input/joystick/walkera0701.c
@@ -150,7 +150,7 @@ static void walkera0701_irq_handler(void *handler_data)
if (w->counter == 24) { /* full frame */
walkera0701_parse_frame(w);
w->counter = NO_SYNC;
- if (abs64(pulse_time - SYNC_PULSE) < RESERVE) /* new frame sync */
+ if (abs(pulse_time - SYNC_PULSE) < RESERVE) /* new frame sync */
w->counter = 0;
} else {
if ((pulse_time > (ANALOG_MIN_PULSE - RESERVE)
@@ -161,7 +161,7 @@ static void walkera0701_irq_handler(void *handler_data)
} else
w->counter = NO_SYNC;
}
- } else if (abs64(pulse_time - SYNC_PULSE - BIN0_PULSE) <
+ } else if (abs(pulse_time - SYNC_PULSE - BIN0_PULSE) <
RESERVE + BIN1_PULSE - BIN0_PULSE) /* frame sync .. */
w->counter = 0;
@@ -200,35 +200,38 @@ static void walkera0701_close(struct input_dev *dev)
parport_release(w->pardevice);
}
-static int walkera0701_connect(struct walkera_dev *w, int parport)
+static void walkera0701_attach(struct parport *pp)
{
- int error;
+ struct pardev_cb walkera0701_parport_cb;
+ struct walkera_dev *w = &w_dev;
- w->parport = parport_find_number(parport);
- if (!w->parport) {
- pr_err("parport %d does not exist\n", parport);
- return -ENODEV;
+ if (pp->number != walkera0701_pp_no) {
+ pr_debug("Not using parport%d.\n", pp->number);
+ return;
}
- if (w->parport->irq == -1) {
+ if (pp->irq == -1) {
pr_err("parport %d does not have interrupt assigned\n",
- parport);
- error = -EINVAL;
- goto err_put_parport;
+ pp->number);
+ return;
}
- w->pardevice = parport_register_device(w->parport, "walkera0701",
- NULL, NULL, walkera0701_irq_handler,
- PARPORT_DEV_EXCL, w);
+ w->parport = pp;
+
+ walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL;
+ walkera0701_parport_cb.irq_func = walkera0701_irq_handler;
+ walkera0701_parport_cb.private = w;
+
+ w->pardevice = parport_register_dev_model(pp, "walkera0701",
+ &walkera0701_parport_cb, 0);
+
if (!w->pardevice) {
pr_err("failed to register parport device\n");
- error = -EIO;
- goto err_put_parport;
+ return;
}
if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) {
pr_err("failed to negotiate parport mode\n");
- error = -EIO;
goto err_unregister_device;
}
@@ -238,7 +241,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
w->input_dev = input_allocate_device();
if (!w->input_dev) {
pr_err("failed to allocate input device\n");
- error = -ENOMEM;
goto err_unregister_device;
}
@@ -265,38 +267,46 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0);
input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0);
- error = input_register_device(w->input_dev);
- if (error) {
+ if (input_register_device(w->input_dev)) {
pr_err("failed to register input device\n");
goto err_free_input_dev;
}
- return 0;
+ return;
err_free_input_dev:
input_free_device(w->input_dev);
err_unregister_device:
parport_unregister_device(w->pardevice);
-err_put_parport:
- parport_put_port(w->parport);
- return error;
}
-static void walkera0701_disconnect(struct walkera_dev *w)
+static void walkera0701_detach(struct parport *port)
{
+ struct walkera_dev *w = &w_dev;
+
+ if (!w->pardevice || w->parport->number != port->number)
+ return;
+
input_unregister_device(w->input_dev);
parport_unregister_device(w->pardevice);
- parport_put_port(w->parport);
+ w->parport = NULL;
}
+static struct parport_driver walkera0701_parport_driver = {
+ .name = "walkera0701",
+ .match_port = walkera0701_attach,
+ .detach = walkera0701_detach,
+ .devmodel = true,
+};
+
static int __init walkera0701_init(void)
{
- return walkera0701_connect(&w_dev, walkera0701_pp_no);
+ return parport_register_driver(&walkera0701_parport_driver);
}
static void __exit walkera0701_exit(void)
{
- walkera0701_disconnect(&w_dev);
+ parport_unregister_driver(&walkera0701_parport_driver);
}
module_init(walkera0701_init);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f8850f9cb331..fd4100d56d8c 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -125,6 +125,7 @@ static const struct xpad_device {
{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
+ { 0x045e, 0x02dd, "Microsoft X-Box One pad (Covert Forces)", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
@@ -204,7 +205,7 @@ static const struct xpad_device {
{ 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 },
- { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", 0, XTYPE_XBOX360 },
+ { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 },
@@ -242,7 +243,6 @@ static const signed short xpad_btn_triggers[] = {
-1
};
-
static const signed short xpad360_btn[] = { /* buttons for x360 controller */
BTN_TL, BTN_TR, /* Button LB/RB */
BTN_MODE, /* The big X button */
@@ -328,9 +328,6 @@ struct usb_xpad {
unsigned char *idata; /* input data */
dma_addr_t idata_dma;
- struct urb *bulk_out;
- unsigned char *bdata;
-
struct urb *irq_out; /* urb for interrupt out report */
unsigned char *odata; /* output data */
dma_addr_t odata_dma;
@@ -344,7 +341,8 @@ struct usb_xpad {
int mapping; /* map d-pad to buttons or to axes */
int xtype; /* type of xbox device */
- unsigned long led_no; /* led to lit on xbox360 controllers */
+ int pad_nr; /* the order x360 pads were attached */
+ const char *name; /* name of the device */
};
/*
@@ -356,7 +354,6 @@ struct usb_xpad {
* The used report descriptor was taken from ITO Takayukis website:
* http://euc.jp/periphs/xbox-controller.ja.html
*/
-
static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
{
struct input_dev *dev = xpad->dev;
@@ -439,7 +436,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
- } else {
+ }
+
+ /*
+ * This should be a simple else block. However historically
+ * xbox360w has mapped DPAD to buttons while xbox360 did not. This
+ * made no sense, but now we can not just switch back and have to
+ * support both behaviors.
+ */
+ if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
+ xpad->xtype == XTYPE_XBOX360W) {
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y,
@@ -505,14 +511,12 @@ static void xpad_identify_controller(struct usb_xpad *xpad);
* 01.1 - Pad state (Bytes 4+) valid
*
*/
-
static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
{
/* Presence change */
if (data[0] & 0x08) {
if (data[1] & 0x80) {
xpad->pad_present = 1;
- usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
/*
* Light up the segment corresponding to
* controller number.
@@ -674,28 +678,6 @@ exit:
__func__, retval);
}
-static void xpad_bulk_out(struct urb *urb)
-{
- struct usb_xpad *xpad = urb->context;
- struct device *dev = &xpad->intf->dev;
-
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dev_dbg(dev, "%s - urb shutting down with status: %d\n",
- __func__, urb->status);
- break;
- default:
- dev_dbg(dev, "%s - nonzero urb status received: %d\n",
- __func__, urb->status);
- }
-}
-
static void xpad_irq_out(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
@@ -786,84 +768,109 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
}
}
+static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
+{
+ int retval;
+
+ mutex_lock(&xpad->odata_mutex);
+
+ xpad->odata[0] = 0x08;
+ xpad->odata[1] = 0x00;
+ xpad->odata[2] = 0x0F;
+ xpad->odata[3] = 0xC0;
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ xpad->odata[8] = 0x00;
+ xpad->odata[9] = 0x00;
+ xpad->odata[10] = 0x00;
+ xpad->odata[11] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 12;
+
+ retval = usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+
+ mutex_unlock(&xpad->odata_mutex);
+
+ return retval;
+}
+
#ifdef CONFIG_JOYSTICK_XPAD_FF
static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
+ __u16 strong;
+ __u16 weak;
- if (effect->type == FF_RUMBLE) {
- __u16 strong = effect->u.rumble.strong_magnitude;
- __u16 weak = effect->u.rumble.weak_magnitude;
-
- switch (xpad->xtype) {
-
- case XTYPE_XBOX:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x06;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = strong / 256; /* left actuator */
- xpad->odata[4] = 0x00;
- xpad->odata[5] = weak / 256; /* right actuator */
- xpad->irq_out->transfer_buffer_length = 6;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- case XTYPE_XBOX360:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x08;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = strong / 256; /* left actuator? */
- xpad->odata[4] = weak / 256; /* right actuator? */
- xpad->odata[5] = 0x00;
- xpad->odata[6] = 0x00;
- xpad->odata[7] = 0x00;
- xpad->irq_out->transfer_buffer_length = 8;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- case XTYPE_XBOX360W:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x01;
- xpad->odata[2] = 0x0F;
- xpad->odata[3] = 0xC0;
- xpad->odata[4] = 0x00;
- xpad->odata[5] = strong / 256;
- xpad->odata[6] = weak / 256;
- xpad->odata[7] = 0x00;
- xpad->odata[8] = 0x00;
- xpad->odata[9] = 0x00;
- xpad->odata[10] = 0x00;
- xpad->odata[11] = 0x00;
- xpad->irq_out->transfer_buffer_length = 12;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- case XTYPE_XBOXONE:
- xpad->odata[0] = 0x09; /* activate rumble */
- xpad->odata[1] = 0x08;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = 0x08; /* continuous effect */
- xpad->odata[4] = 0x00; /* simple rumble mode */
- xpad->odata[5] = 0x03; /* L and R actuator only */
- xpad->odata[6] = 0x00; /* TODO: LT actuator */
- xpad->odata[7] = 0x00; /* TODO: RT actuator */
- xpad->odata[8] = strong / 256; /* left actuator */
- xpad->odata[9] = weak / 256; /* right actuator */
- xpad->odata[10] = 0x80; /* length of pulse */
- xpad->odata[11] = 0x00; /* stop period of pulse */
- xpad->irq_out->transfer_buffer_length = 12;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- default:
- dev_dbg(&xpad->dev->dev,
- "%s - rumble command sent to unsupported xpad type: %d\n",
- __func__, xpad->xtype);
- return -1;
- }
+ if (effect->type != FF_RUMBLE)
+ return 0;
+
+ strong = effect->u.rumble.strong_magnitude;
+ weak = effect->u.rumble.weak_magnitude;
+
+ switch (xpad->xtype) {
+ case XTYPE_XBOX:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x06;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256; /* left actuator */
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = weak / 256; /* right actuator */
+ xpad->irq_out->transfer_buffer_length = 6;
+ break;
+
+ case XTYPE_XBOX360:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256; /* left actuator? */
+ xpad->odata[4] = weak / 256; /* right actuator? */
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 8;
+ break;
+
+ case XTYPE_XBOX360W:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x01;
+ xpad->odata[2] = 0x0F;
+ xpad->odata[3] = 0xC0;
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = strong / 256;
+ xpad->odata[6] = weak / 256;
+ xpad->odata[7] = 0x00;
+ xpad->odata[8] = 0x00;
+ xpad->odata[9] = 0x00;
+ xpad->odata[10] = 0x00;
+ xpad->odata[11] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 12;
+ break;
+
+ case XTYPE_XBOXONE:
+ xpad->odata[0] = 0x09; /* activate rumble */
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = 0x08; /* continuous effect */
+ xpad->odata[4] = 0x00; /* simple rumble mode */
+ xpad->odata[5] = 0x03; /* L and R actuator only */
+ xpad->odata[6] = 0x00; /* TODO: LT actuator */
+ xpad->odata[7] = 0x00; /* TODO: RT actuator */
+ xpad->odata[8] = strong / 256; /* left actuator */
+ xpad->odata[9] = weak / 256; /* right actuator */
+ xpad->odata[10] = 0x80; /* length of pulse */
+ xpad->odata[11] = 0x00; /* stop period of pulse */
+ xpad->irq_out->transfer_buffer_length = 12;
+ break;
+
+ default:
+ dev_dbg(&xpad->dev->dev,
+ "%s - rumble command sent to unsupported xpad type: %d\n",
+ __func__, xpad->xtype);
+ return -EINVAL;
}
- return 0;
+ return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
}
static int xpad_init_ff(struct usb_xpad *xpad)
@@ -882,6 +889,9 @@ static int xpad_init_ff(struct usb_xpad *xpad) { return 0; }
#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
#include <linux/leds.h>
+#include <linux/idr.h>
+
+static DEFINE_IDA(xpad_pad_seq);
struct xpad_led {
char name[16];
@@ -890,6 +900,7 @@ struct xpad_led {
};
/**
+ * set the LEDs on Xbox360 / Wireless Controllers
* @param command
* 0: off
* 1: all blink, then previous setting
@@ -942,10 +953,13 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
mutex_unlock(&xpad->odata_mutex);
}
+/*
+ * Light up the segment corresponding to the pad number on
+ * Xbox 360 Controllers.
+ */
static void xpad_identify_controller(struct usb_xpad *xpad)
{
- /* Light up the segment corresponding to controller number */
- xpad_send_led_command(xpad, (xpad->led_no % 4) + 2);
+ xpad_send_led_command(xpad, (xpad->pad_nr % 4) + 2);
}
static void xpad_led_set(struct led_classdev *led_cdev,
@@ -959,7 +973,6 @@ static void xpad_led_set(struct led_classdev *led_cdev,
static int xpad_led_probe(struct usb_xpad *xpad)
{
- static atomic_t led_seq = ATOMIC_INIT(-1);
struct xpad_led *led;
struct led_classdev *led_cdev;
int error;
@@ -971,9 +984,13 @@ static int xpad_led_probe(struct usb_xpad *xpad)
if (!led)
return -ENOMEM;
- xpad->led_no = atomic_inc_return(&led_seq);
+ xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL);
+ if (xpad->pad_nr < 0) {
+ error = xpad->pad_nr;
+ goto err_free_mem;
+ }
- snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->led_no);
+ snprintf(led->name, sizeof(led->name), "xpad%d", xpad->pad_nr);
led->xpad = xpad;
led_cdev = &led->led_cdev;
@@ -981,16 +998,26 @@ static int xpad_led_probe(struct usb_xpad *xpad)
led_cdev->brightness_set = xpad_led_set;
error = led_classdev_register(&xpad->udev->dev, led_cdev);
- if (error) {
- kfree(led);
- xpad->led = NULL;
- return error;
- }
+ if (error)
+ goto err_free_id;
- /* Light up the segment corresponding to controller number */
- xpad_identify_controller(xpad);
+ if (xpad->xtype == XTYPE_XBOX360) {
+ /*
+ * Light up the segment corresponding to controller
+ * number on wired devices. On wireless we'll do that
+ * when they respond to "presence" packet.
+ */
+ xpad_identify_controller(xpad);
+ }
return 0;
+
+err_free_id:
+ ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
+err_free_mem:
+ kfree(led);
+ xpad->led = NULL;
+ return error;
}
static void xpad_led_disconnect(struct usb_xpad *xpad)
@@ -999,6 +1026,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)
if (xpad_led) {
led_classdev_unregister(&xpad_led->led_cdev);
+ ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
kfree(xpad_led);
}
}
@@ -1008,7 +1036,6 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { }
static void xpad_identify_controller(struct usb_xpad *xpad) { }
#endif
-
static int xpad_open(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
@@ -1068,11 +1095,107 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
}
}
+static void xpad_deinit_input(struct usb_xpad *xpad)
+{
+ xpad_led_disconnect(xpad);
+ input_unregister_device(xpad->dev);
+}
+
+static int xpad_init_input(struct usb_xpad *xpad)
+{
+ struct input_dev *input_dev;
+ int i, error;
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ xpad->dev = input_dev;
+ input_dev->name = xpad->name;
+ input_dev->phys = xpad->phys;
+ usb_to_input_id(xpad->udev, &input_dev->id);
+ input_dev->dev.parent = &xpad->intf->dev;
+
+ input_set_drvdata(input_dev, xpad);
+
+ input_dev->open = xpad_open;
+ input_dev->close = xpad_close;
+
+ __set_bit(EV_KEY, input_dev->evbit);
+
+ if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
+ __set_bit(EV_ABS, input_dev->evbit);
+ /* set up axes */
+ for (i = 0; xpad_abs[i] >= 0; i++)
+ xpad_set_up_abs(input_dev, xpad_abs[i]);
+ }
+
+ /* set up standard buttons */
+ for (i = 0; xpad_common_btn[i] >= 0; i++)
+ __set_bit(xpad_common_btn[i], input_dev->keybit);
+
+ /* set up model-specific ones */
+ if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
+ xpad->xtype == XTYPE_XBOXONE) {
+ for (i = 0; xpad360_btn[i] >= 0; i++)
+ __set_bit(xpad360_btn[i], input_dev->keybit);
+ } else {
+ for (i = 0; xpad_btn[i] >= 0; i++)
+ __set_bit(xpad_btn[i], input_dev->keybit);
+ }
+
+ if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
+ for (i = 0; xpad_btn_pad[i] >= 0; i++)
+ __set_bit(xpad_btn_pad[i], input_dev->keybit);
+ }
+
+ /*
+ * This should be a simple else block. However historically
+ * xbox360w has mapped DPAD to buttons while xbox360 did not. This
+ * made no sense, but now we can not just switch back and have to
+ * support both behaviors.
+ */
+ if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
+ xpad->xtype == XTYPE_XBOX360W) {
+ for (i = 0; xpad_abs_pad[i] >= 0; i++)
+ xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+ }
+
+ if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
+ for (i = 0; xpad_btn_triggers[i] >= 0; i++)
+ __set_bit(xpad_btn_triggers[i], input_dev->keybit);
+ } else {
+ for (i = 0; xpad_abs_triggers[i] >= 0; i++)
+ xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
+ }
+
+ error = xpad_init_ff(xpad);
+ if (error)
+ goto err_free_input;
+
+ error = xpad_led_probe(xpad);
+ if (error)
+ goto err_destroy_ff;
+
+ error = input_register_device(xpad->dev);
+ if (error)
+ goto err_disconnect_led;
+
+ return 0;
+
+err_disconnect_led:
+ xpad_led_disconnect(xpad);
+err_destroy_ff:
+ input_ff_destroy(input_dev);
+err_free_input:
+ input_free_device(input_dev);
+ return error;
+}
+
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_xpad *xpad;
- struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
int ep_irq_in_idx;
int i, error;
@@ -1094,29 +1217,30 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
}
xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!xpad || !input_dev) {
- error = -ENOMEM;
- goto fail1;
- }
+ if (!xpad)
+ return -ENOMEM;
+
+ usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+ strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->idata_dma);
if (!xpad->idata) {
error = -ENOMEM;
- goto fail1;
+ goto err_free_mem;
}
xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
if (!xpad->irq_in) {
error = -ENOMEM;
- goto fail2;
+ goto err_free_idata;
}
xpad->udev = udev;
xpad->intf = intf;
xpad->mapping = xpad_device[i].mapping;
xpad->xtype = xpad_device[i].xtype;
+ xpad->name = xpad_device[i].name;
if (xpad->xtype == XTYPE_UNKNOWN) {
if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
@@ -1124,8 +1248,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->xtype = XTYPE_XBOX360W;
else
xpad->xtype = XTYPE_XBOX360;
- } else
+ } else {
xpad->xtype = XTYPE_XBOX;
+ }
if (dpad_to_buttons)
xpad->mapping |= MAP_DPAD_TO_BUTTONS;
@@ -1135,70 +1260,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->mapping |= MAP_STICKS_TO_NULL;
}
- xpad->dev = input_dev;
- usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
- strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
-
- input_dev->name = xpad_device[i].name;
- input_dev->phys = xpad->phys;
- usb_to_input_id(udev, &input_dev->id);
- input_dev->dev.parent = &intf->dev;
-
- input_set_drvdata(input_dev, xpad);
-
- input_dev->open = xpad_open;
- input_dev->close = xpad_close;
-
- input_dev->evbit[0] = BIT_MASK(EV_KEY);
-
- if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
- input_dev->evbit[0] |= BIT_MASK(EV_ABS);
- /* set up axes */
- for (i = 0; xpad_abs[i] >= 0; i++)
- xpad_set_up_abs(input_dev, xpad_abs[i]);
- }
-
- /* set up standard buttons */
- for (i = 0; xpad_common_btn[i] >= 0; i++)
- __set_bit(xpad_common_btn[i], input_dev->keybit);
-
- /* set up model-specific ones */
- if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
- xpad->xtype == XTYPE_XBOXONE) {
- for (i = 0; xpad360_btn[i] >= 0; i++)
- __set_bit(xpad360_btn[i], input_dev->keybit);
- } else {
- for (i = 0; xpad_btn[i] >= 0; i++)
- __set_bit(xpad_btn[i], input_dev->keybit);
- }
-
- if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
- for (i = 0; xpad_btn_pad[i] >= 0; i++)
- __set_bit(xpad_btn_pad[i], input_dev->keybit);
- } else {
- for (i = 0; xpad_abs_pad[i] >= 0; i++)
- xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
- }
-
- if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
- for (i = 0; xpad_btn_triggers[i] >= 0; i++)
- __set_bit(xpad_btn_triggers[i], input_dev->keybit);
- } else {
- for (i = 0; xpad_abs_triggers[i] >= 0; i++)
- xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
- }
-
error = xpad_init_output(intf, xpad);
if (error)
- goto fail3;
-
- error = xpad_init_ff(xpad);
- if (error)
- goto fail4;
-
- error = xpad_led_probe(xpad);
- if (error)
- goto fail5;
+ goto err_free_in_urb;
/* Xbox One controller has in/out endpoints swapped. */
ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0;
@@ -1211,59 +1275,13 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->irq_in->transfer_dma = xpad->idata_dma;
xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- error = input_register_device(xpad->dev);
- if (error)
- goto fail6;
-
usb_set_intfdata(intf, xpad);
- if (xpad->xtype == XTYPE_XBOX360W) {
- /*
- * Setup the message to set the LEDs on the
- * controller when it shows up
- */
- xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
- if (!xpad->bulk_out) {
- error = -ENOMEM;
- goto fail7;
- }
-
- xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
- if (!xpad->bdata) {
- error = -ENOMEM;
- goto fail8;
- }
-
- xpad->bdata[2] = 0x08;
- switch (intf->cur_altsetting->desc.bInterfaceNumber) {
- case 0:
- xpad->bdata[3] = 0x42;
- break;
- case 2:
- xpad->bdata[3] = 0x43;
- break;
- case 4:
- xpad->bdata[3] = 0x44;
- break;
- case 6:
- xpad->bdata[3] = 0x45;
- }
-
- ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
- if (usb_endpoint_is_bulk_out(ep_irq_in)) {
- usb_fill_bulk_urb(xpad->bulk_out, udev,
- usb_sndbulkpipe(udev,
- ep_irq_in->bEndpointAddress),
- xpad->bdata, XPAD_PKT_LEN,
- xpad_bulk_out, xpad);
- } else {
- usb_fill_int_urb(xpad->bulk_out, udev,
- usb_sndintpipe(udev,
- ep_irq_in->bEndpointAddress),
- xpad->bdata, XPAD_PKT_LEN,
- xpad_bulk_out, xpad, 0);
- }
+ error = xpad_init_input(xpad);
+ if (error)
+ goto err_deinit_output;
+ if (xpad->xtype == XTYPE_XBOX360W) {
/*
* Submit the int URB immediately rather than waiting for open
* because we get status messages from the device whether
@@ -1274,22 +1292,32 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->irq_in->dev = xpad->udev;
error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
if (error)
- goto fail9;
- }
+ goto err_deinit_input;
+ /*
+ * Send presence packet.
+ * This will force the controller to resend connection packets.
+ * This is useful in the case we activate the module after the
+ * adapter has been plugged in, as it won't automatically
+ * send us info about the controllers.
+ */
+ error = xpad_inquiry_pad_presence(xpad);
+ if (error)
+ goto err_kill_in_urb;
+ }
return 0;
- fail9: kfree(xpad->bdata);
- fail8: usb_free_urb(xpad->bulk_out);
- fail7: input_unregister_device(input_dev);
- input_dev = NULL;
- fail6: xpad_led_disconnect(xpad);
- fail5: if (input_dev)
- input_ff_destroy(input_dev);
- fail4: xpad_deinit_output(xpad);
- fail3: usb_free_urb(xpad->irq_in);
- fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
- fail1: input_free_device(input_dev);
+err_kill_in_urb:
+ usb_kill_urb(xpad->irq_in);
+err_deinit_input:
+ xpad_deinit_input(xpad);
+err_deinit_output:
+ xpad_deinit_output(xpad);
+err_free_in_urb:
+ usb_free_urb(xpad->irq_in);
+err_free_idata:
+ usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+err_free_mem:
kfree(xpad);
return error;
@@ -1299,13 +1327,10 @@ static void xpad_disconnect(struct usb_interface *intf)
{
struct usb_xpad *xpad = usb_get_intfdata (intf);
- xpad_led_disconnect(xpad);
- input_unregister_device(xpad->dev);
+ xpad_deinit_input(xpad);
xpad_deinit_output(xpad);
if (xpad->xtype == XTYPE_XBOX360W) {
- usb_kill_urb(xpad->bulk_out);
- usb_free_urb(xpad->bulk_out);
usb_kill_urb(xpad->irq_in);
}
@@ -1313,7 +1338,6 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
- kfree(xpad->bdata);
kfree(xpad);
usb_set_intfdata(intf, NULL);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 2e80107ff630..ddd8148d51d7 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -516,7 +516,7 @@ config KEYBOARD_SAMSUNG
module will be called samsung-keypad.
config KEYBOARD_GOLDFISH_EVENTS
- depends on GOLDFISH
+ depends on GOLDFISH || COMPILE_TEST
tristate "Generic Input Event device for Goldfish"
help
Say Y here to get an input event device for the Goldfish virtual
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 9d517ca7eb5a..bef317ff7352 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -341,8 +341,14 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
const struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
- int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low;
+ int state = gpio_get_value_cansleep(button->gpio);
+ if (state < 0) {
+ dev_err(input->dev.parent, "failed to get gpio state\n");
+ return;
+ }
+
+ state = (state ? 1 : 0) ^ button->active_low;
if (type == EV_ABS) {
if (state)
input_event(input, type, button->code, button->value);
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 870cfa6e2c44..62bdb1d48c49 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -40,10 +40,36 @@ struct gpio_keys_polled_dev {
struct input_polled_dev *poll_dev;
struct device *dev;
const struct gpio_keys_platform_data *pdata;
+ unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)];
+ unsigned long abs_axis_seen[BITS_TO_LONGS(ABS_CNT)];
struct gpio_keys_button_data data[0];
};
-static void gpio_keys_polled_check_state(struct input_dev *input,
+static void gpio_keys_button_event(struct input_polled_dev *dev,
+ struct gpio_keys_button *button,
+ int state)
+{
+ struct gpio_keys_polled_dev *bdev = dev->private;
+ struct input_dev *input = dev->input;
+ unsigned int type = button->type ?: EV_KEY;
+
+ if (type == EV_REL) {
+ if (state) {
+ input_event(input, type, button->code, button->value);
+ __set_bit(button->code, bdev->rel_axis_seen);
+ }
+ } else if (type == EV_ABS) {
+ if (state) {
+ input_event(input, type, button->code, button->value);
+ __set_bit(button->code, bdev->abs_axis_seen);
+ }
+ } else {
+ input_event(input, type, button->code, state);
+ input_sync(input);
+ }
+}
+
+static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
struct gpio_keys_button *button,
struct gpio_keys_button_data *bdata)
{
@@ -54,11 +80,9 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
else
state = !!gpiod_get_value(button->gpiod);
- if (state != bdata->last_state) {
- unsigned int type = button->type ?: EV_KEY;
+ gpio_keys_button_event(dev, button, state);
- input_event(input, type, button->code, state);
- input_sync(input);
+ if (state != bdata->last_state) {
bdata->count = 0;
bdata->last_state = state;
}
@@ -71,15 +95,33 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
struct input_dev *input = dev->input;
int i;
+ memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen));
+ memset(bdev->abs_axis_seen, 0, sizeof(bdev->abs_axis_seen));
+
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button_data *bdata = &bdev->data[i];
- if (bdata->count < bdata->threshold)
+ if (bdata->count < bdata->threshold) {
bdata->count++;
- else
- gpio_keys_polled_check_state(input, &pdata->buttons[i],
+ gpio_keys_button_event(dev, &pdata->buttons[i],
+ bdata->last_state);
+ } else {
+ gpio_keys_polled_check_state(dev, &pdata->buttons[i],
bdata);
+ }
+ }
+
+ for_each_set_bit(i, input->relbit, REL_CNT) {
+ if (!test_bit(i, bdev->rel_axis_seen))
+ input_event(input, EV_REL, i, 0);
+ }
+
+ for_each_set_bit(i, input->absbit, ABS_CNT) {
+ if (!test_bit(i, bdev->abs_axis_seen))
+ input_event(input, EV_ABS, i, 0);
}
+
+ input_sync(input);
}
static void gpio_keys_polled_open(struct input_polled_dev *dev)
@@ -152,6 +194,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
&button->type))
button->type = EV_KEY;
+ if (fwnode_property_read_u32(child, "linux,input-value",
+ (u32 *)&button->value))
+ button->value = 1;
+
button->wakeup =
fwnode_property_read_bool(child, "wakeup-source") ||
/* legacy name */
@@ -168,6 +214,25 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
return pdata;
}
+static void gpio_keys_polled_set_abs_params(struct input_dev *input,
+ const struct gpio_keys_platform_data *pdata, unsigned int code)
+{
+ int i, min = 0, max = 0;
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_keys_button *button = &pdata->buttons[i];
+
+ if (button->type != EV_ABS || button->code != code)
+ continue;
+
+ if (button->value < min)
+ min = button->value;
+ if (button->value > max)
+ max = button->value;
+ }
+ input_set_abs_params(input, code, min, max, 0, 0);
+}
+
static const struct of_device_id gpio_keys_polled_of_match[] = {
{ .compatible = "gpio-keys-polled", },
{ },
@@ -274,6 +339,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
pdata->poll_interval);
input_set_capability(input, type, button->code);
+ if (type == EV_ABS)
+ gpio_keys_polled_set_abs_params(input, pdata,
+ button->code);
}
bdev->poll_dev = poll_dev;
@@ -290,9 +358,11 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
/* report initial state of the buttons */
for (i = 0; i < pdata->nbuttons; i++)
- gpio_keys_polled_check_state(input, &pdata->buttons[i],
+ gpio_keys_polled_check_state(poll_dev, &pdata->buttons[i],
&bdev->data[i]);
+ input_sync(input);
+
return 0;
}
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index c7d5b1666fc3..8567ee47761e 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -54,7 +54,7 @@
/**
* struct ske_keypad - data structure used by keypad driver
* @irq: irq no
- * @reg_base: ske regsiters base address
+ * @reg_base: ske registers base address
* @input: pointer to input device object
* @board: keypad platform device
* @keymap: matrix scan code table for keycodes
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 78fd24ca3813..9adf13a5864a 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -110,8 +110,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
- pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");;
-
+ pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");
if (!pdata->snvs) {
dev_err(&pdev->dev, "Can't get snvs syscon\n");
return -ENODEV;
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index f97c73bd14f8..acc5394afb03 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -517,7 +517,8 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
if (of_find_property(np, "nvidia,needs-ghost-filter", NULL))
kbc->use_ghost_filter = true;
- if (of_find_property(np, "nvidia,wakeup-source", NULL))
+ if (of_property_read_bool(np, "wakeup-source") ||
+ of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */
kbc->wakeup = true;
if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) {
@@ -705,7 +706,7 @@ static int tegra_kbc_probe(struct platform_device *pdev)
input_set_drvdata(kbc->idev, kbc);
err = devm_request_irq(&pdev->dev, kbc->irq, tegra_kbc_isr,
- IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc);
+ IRQF_TRIGGER_HIGH, pdev->name, kbc);
if (err) {
dev_err(&pdev->dev, "failed to request keyboard IRQ\n");
return err;
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 906dd1b25e41..d6d16fa78281 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -94,11 +94,11 @@ config INPUT_BMA150
module will be called bma150.
config INPUT_E3X0_BUTTON
- tristate "NI Ettus Research USRP E3x0 Button support."
+ tristate "NI Ettus Research USRP E3xx Button support."
default n
help
Say Y here to enable support for the NI Ettus Research
- USRP E3x0 Button.
+ USRP E3xx Button.
To compile this driver as a module, choose M here: the
module will be called e3x0_button.
@@ -599,11 +599,11 @@ config INPUT_DA9055_ONKEY
will be called da9055_onkey.
config INPUT_DA9063_ONKEY
- tristate "Dialog DA9063 OnKey"
- depends on MFD_DA9063
+ tristate "Dialog DA9062/63 OnKey"
+ depends on MFD_DA9063 || MFD_DA9062
help
- Support the ONKEY of Dialog DA9063 Power Management IC as an
- input device reporting power button statue.
+ Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
+ as an input device capable of reporting the power button status.
To compile this driver as a module, choose M here: the module
will be called da9063_onkey.
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index 189bdc8e91a5..2f047738bc0b 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -85,15 +85,6 @@ static int ad714x_i2c_probe(struct i2c_client *client,
return 0;
}
-static int ad714x_i2c_remove(struct i2c_client *client)
-{
- struct ad714x_chip *chip = i2c_get_clientdata(client);
-
- ad714x_remove(chip);
-
- return 0;
-}
-
static const struct i2c_device_id ad714x_id[] = {
{ "ad7142_captouch", 0 },
{ "ad7143_captouch", 0 },
@@ -110,7 +101,6 @@ static struct i2c_driver ad714x_i2c_driver = {
.pm = &ad714x_i2c_pm,
},
.probe = ad714x_i2c_probe,
- .remove = ad714x_i2c_remove,
.id_table = ad714x_id,
};
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index a79e50b58bf5..aac910326447 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -101,23 +101,12 @@ static int ad714x_spi_probe(struct spi_device *spi)
return 0;
}
-static int ad714x_spi_remove(struct spi_device *spi)
-{
- struct ad714x_chip *chip = spi_get_drvdata(spi);
-
- ad714x_remove(chip);
-
- return 0;
-}
-
static struct spi_driver ad714x_spi_driver = {
.driver = {
.name = "ad714x_captouch",
- .owner = THIS_MODULE,
.pm = &ad714x_spi_pm,
},
.probe = ad714x_spi_probe,
- .remove = ad714x_spi_remove,
};
module_spi_driver(ad714x_spi_driver);
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c
index 7a61e9ee682c..84b51dd51f6e 100644
--- a/drivers/input/misc/ad714x.c
+++ b/drivers/input/misc/ad714x.c
@@ -960,13 +960,12 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
return IRQ_HANDLED;
}
-#define MAX_DEVICE_NUM 8
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
ad714x_read_t read, ad714x_write_t write)
{
- int i, alloc_idx;
+ int i;
int error;
- struct input_dev *input[MAX_DEVICE_NUM];
+ struct input_dev *input;
struct ad714x_platform_data *plat_data = dev_get_platdata(dev);
struct ad714x_chip *ad714x;
@@ -982,25 +981,25 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
if (irq <= 0) {
dev_err(dev, "IRQ not configured!\n");
error = -EINVAL;
- goto err_out;
+ return ERR_PTR(error);
}
if (dev_get_platdata(dev) == NULL) {
dev_err(dev, "platform data for ad714x doesn't exist\n");
error = -EINVAL;
- goto err_out;
+ return ERR_PTR(error);
}
- ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) +
- sizeof(*sd_drv) * plat_data->slider_num +
- sizeof(*wl_drv) * plat_data->wheel_num +
- sizeof(*tp_drv) * plat_data->touchpad_num +
- sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL);
+ ad714x = devm_kzalloc(dev, sizeof(*ad714x) + sizeof(*ad714x->sw) +
+ sizeof(*sd_drv) * plat_data->slider_num +
+ sizeof(*wl_drv) * plat_data->wheel_num +
+ sizeof(*tp_drv) * plat_data->touchpad_num +
+ sizeof(*bt_drv) * plat_data->button_num,
+ GFP_KERNEL);
if (!ad714x) {
error = -ENOMEM;
- goto err_out;
+ return ERR_PTR(error);
}
-
ad714x->hw = plat_data;
drv_mem = ad714x + 1;
@@ -1022,47 +1021,40 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
error = ad714x_hw_detect(ad714x);
if (error)
- goto err_free_mem;
+ return ERR_PTR(error);
/* initialize and request sw/hw resources */
ad714x_hw_init(ad714x);
mutex_init(&ad714x->mutex);
- /*
- * Allocate and register AD714X input device
- */
- alloc_idx = 0;
-
/* a slider uses one input_dev instance */
if (ad714x->hw->slider_num > 0) {
struct ad714x_slider_plat *sd_plat = ad714x->hw->slider;
for (i = 0; i < ad714x->hw->slider_num; i++) {
- sd_drv[i].input = input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
- error = -ENOMEM;
- goto err_free_dev;
- }
-
- __set_bit(EV_ABS, input[alloc_idx]->evbit);
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
- __set_bit(ABS_X, input[alloc_idx]->absbit);
- __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
- input_set_abs_params(input[alloc_idx],
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return ERR_PTR(-ENOMEM);
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(ABS_X, input->absbit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input,
ABS_X, 0, sd_plat->max_coord, 0, 0);
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_slider";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_slider";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
+ return ERR_PTR(error);
- alloc_idx++;
+ sd_drv[i].input = input;
}
}
@@ -1071,30 +1063,28 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel;
for (i = 0; i < ad714x->hw->wheel_num; i++) {
- wl_drv[i].input = input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
- error = -ENOMEM;
- goto err_free_dev;
- }
-
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
- __set_bit(EV_ABS, input[alloc_idx]->evbit);
- __set_bit(ABS_WHEEL, input[alloc_idx]->absbit);
- __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
- input_set_abs_params(input[alloc_idx],
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return ERR_PTR(-ENOMEM);
+
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(ABS_WHEEL, input->absbit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input,
ABS_WHEEL, 0, wl_plat->max_coord, 0, 0);
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_wheel";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_wheel";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
+ return ERR_PTR(error);
- alloc_idx++;
+ wl_drv[i].input = input;
}
}
@@ -1103,33 +1093,31 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
for (i = 0; i < ad714x->hw->touchpad_num; i++) {
- tp_drv[i].input = input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
- error = -ENOMEM;
- goto err_free_dev;
- }
-
- __set_bit(EV_ABS, input[alloc_idx]->evbit);
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
- __set_bit(ABS_X, input[alloc_idx]->absbit);
- __set_bit(ABS_Y, input[alloc_idx]->absbit);
- __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
- input_set_abs_params(input[alloc_idx],
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return ERR_PTR(-ENOMEM);
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(ABS_X, input->absbit);
+ __set_bit(ABS_Y, input->absbit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input,
ABS_X, 0, tp_plat->x_max_coord, 0, 0);
- input_set_abs_params(input[alloc_idx],
+ input_set_abs_params(input,
ABS_Y, 0, tp_plat->y_max_coord, 0, 0);
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_pad";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_pad";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
+ return ERR_PTR(error);
- alloc_idx++;
+ tp_drv[i].input = input;
}
}
@@ -1137,82 +1125,44 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
if (ad714x->hw->button_num > 0) {
struct ad714x_button_plat *bt_plat = ad714x->hw->button;
- input[alloc_idx] = input_allocate_device();
- if (!input[alloc_idx]) {
+ input = devm_input_allocate_device(dev);
+ if (!input) {
error = -ENOMEM;
- goto err_free_dev;
+ return ERR_PTR(error);
}
- __set_bit(EV_KEY, input[alloc_idx]->evbit);
+ __set_bit(EV_KEY, input->evbit);
for (i = 0; i < ad714x->hw->button_num; i++) {
- bt_drv[i].input = input[alloc_idx];
- __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit);
+ bt_drv[i].input = input;
+ __set_bit(bt_plat[i].keycode, input->keybit);
}
- input[alloc_idx]->id.bustype = bus_type;
- input[alloc_idx]->id.product = ad714x->product;
- input[alloc_idx]->id.version = ad714x->version;
- input[alloc_idx]->name = "ad714x_captouch_button";
- input[alloc_idx]->dev.parent = dev;
+ input->id.bustype = bus_type;
+ input->id.product = ad714x->product;
+ input->id.version = ad714x->version;
+ input->name = "ad714x_captouch_button";
+ input->dev.parent = dev;
- error = input_register_device(input[alloc_idx]);
+ error = input_register_device(input);
if (error)
- goto err_free_dev;
-
- alloc_idx++;
+ return ERR_PTR(error);
}
irqflags = plat_data->irqflags ?: IRQF_TRIGGER_FALLING;
irqflags |= IRQF_ONESHOT;
- error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
- irqflags, "ad714x_captouch", ad714x);
+ error = devm_request_threaded_irq(dev, ad714x->irq, NULL,
+ ad714x_interrupt_thread,
+ irqflags, "ad714x_captouch", ad714x);
if (error) {
dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
- goto err_unreg_dev;
+ return ERR_PTR(error);
}
return ad714x;
-
- err_free_dev:
- dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx);
- input_free_device(input[alloc_idx]);
- err_unreg_dev:
- while (--alloc_idx >= 0)
- input_unregister_device(input[alloc_idx]);
- err_free_mem:
- kfree(ad714x);
- err_out:
- return ERR_PTR(error);
}
EXPORT_SYMBOL(ad714x_probe);
-void ad714x_remove(struct ad714x_chip *ad714x)
-{
- struct ad714x_platform_data *hw = ad714x->hw;
- struct ad714x_driver_data *sw = ad714x->sw;
- int i;
-
- free_irq(ad714x->irq, ad714x);
-
- /* unregister and free all input devices */
-
- for (i = 0; i < hw->slider_num; i++)
- input_unregister_device(sw->slider[i].input);
-
- for (i = 0; i < hw->wheel_num; i++)
- input_unregister_device(sw->wheel[i].input);
-
- for (i = 0; i < hw->touchpad_num; i++)
- input_unregister_device(sw->touchpad[i].input);
-
- if (hw->button_num)
- input_unregister_device(sw->button[0].input);
-
- kfree(ad714x);
-}
-EXPORT_SYMBOL(ad714x_remove);
-
#ifdef CONFIG_PM
int ad714x_disable(struct ad714x_chip *ad714x)
{
diff --git a/drivers/input/misc/ad714x.h b/drivers/input/misc/ad714x.h
index 3c85455aa66d..5d65d303b9bf 100644
--- a/drivers/input/misc/ad714x.h
+++ b/drivers/input/misc/ad714x.h
@@ -50,6 +50,5 @@ int ad714x_disable(struct ad714x_chip *ad714x);
int ad714x_enable(struct ad714x_chip *ad714x);
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
ad714x_read_t read, ad714x_write_t write);
-void ad714x_remove(struct ad714x_chip *ad714x);
#endif
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
index da6e76b58dab..3ec03ad88eed 100644
--- a/drivers/input/misc/adxl34x-spi.c
+++ b/drivers/input/misc/adxl34x-spi.c
@@ -120,7 +120,6 @@ static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
static struct spi_driver adxl34x_driver = {
.driver = {
.name = "adxl34x",
- .owner = THIS_MODULE,
.pm = &adxl34x_spi_pm,
},
.probe = adxl34x_spi_probe,
diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index f577585ef999..8eb697db82d0 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -1,5 +1,5 @@
/*
- * OnKey device driver for DA9063
+ * OnKey device driver for DA9063 and DA9062 PMICs
* Copyright (C) 2015 Dialog Semiconductor Ltd.
*
* This program is free software; you can redistribute it and/or
@@ -24,36 +24,96 @@
#include <linux/mfd/da9063/core.h>
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
+#include <linux/mfd/da9062/core.h>
+#include <linux/mfd/da9062/registers.h>
+
+struct da906x_chip_config {
+ /* REGS */
+ int onkey_status;
+ int onkey_pwr_signalling;
+ int onkey_fault_log;
+ int onkey_shutdown;
+ /* MASKS */
+ int onkey_nonkey_mask;
+ int onkey_nonkey_lock_mask;
+ int onkey_key_reset_mask;
+ int onkey_shutdown_mask;
+ /* NAMES */
+ const char *name;
+};
struct da9063_onkey {
- struct da9063 *hw;
struct delayed_work work;
struct input_dev *input;
struct device *dev;
+ struct regmap *regmap;
+ const struct da906x_chip_config *config;
+ char phys[32];
bool key_power;
};
+static const struct da906x_chip_config da9063_regs = {
+ /* REGS */
+ .onkey_status = DA9063_REG_STATUS_A,
+ .onkey_pwr_signalling = DA9063_REG_CONTROL_B,
+ .onkey_fault_log = DA9063_REG_FAULT_LOG,
+ .onkey_shutdown = DA9063_REG_CONTROL_F,
+ /* MASKS */
+ .onkey_nonkey_mask = DA9063_NONKEY,
+ .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK,
+ .onkey_key_reset_mask = DA9063_KEY_RESET,
+ .onkey_shutdown_mask = DA9063_SHUTDOWN,
+ /* NAMES */
+ .name = DA9063_DRVNAME_ONKEY,
+};
+
+static const struct da906x_chip_config da9062_regs = {
+ /* REGS */
+ .onkey_status = DA9062AA_STATUS_A,
+ .onkey_pwr_signalling = DA9062AA_CONTROL_B,
+ .onkey_fault_log = DA9062AA_FAULT_LOG,
+ .onkey_shutdown = DA9062AA_CONTROL_F,
+ /* MASKS */
+ .onkey_nonkey_mask = DA9062AA_NONKEY_MASK,
+ .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK,
+ .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK,
+ .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK,
+ /* NAMES */
+ .name = "da9062-onkey",
+};
+
+static const struct of_device_id da9063_compatible_reg_id_table[] = {
+ { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
+ { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
+ { },
+};
+
static void da9063_poll_on(struct work_struct *work)
{
- struct da9063_onkey *onkey = container_of(work, struct da9063_onkey,
- work.work);
+ struct da9063_onkey *onkey = container_of(work,
+ struct da9063_onkey,
+ work.work);
+ const struct da906x_chip_config *config = onkey->config;
unsigned int val;
int fault_log = 0;
bool poll = true;
int error;
/* Poll to see when the pin is released */
- error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
+ error = regmap_read(onkey->regmap,
+ config->onkey_status,
+ &val);
if (error) {
dev_err(onkey->dev,
"Failed to read ON status: %d\n", error);
goto err_poll;
}
- if (!(val & DA9063_NONKEY)) {
- error = regmap_update_bits(onkey->hw->regmap,
- DA9063_REG_CONTROL_B,
- DA9063_NONKEY_LOCK, 0);
+ if (!(val & config->onkey_nonkey_mask)) {
+ error = regmap_update_bits(onkey->regmap,
+ config->onkey_pwr_signalling,
+ config->onkey_nonkey_lock_mask,
+ 0);
if (error) {
dev_err(onkey->dev,
"Failed to reset the Key Delay %d\n", error);
@@ -70,15 +130,16 @@ static void da9063_poll_on(struct work_struct *work)
* If the fault log KEY_RESET is detected, then clear it
* and shut down the system.
*/
- error = regmap_read(onkey->hw->regmap,
- DA9063_REG_FAULT_LOG, &fault_log);
+ error = regmap_read(onkey->regmap,
+ config->onkey_fault_log,
+ &fault_log);
if (error) {
dev_warn(&onkey->input->dev,
"Cannot read FAULT_LOG: %d\n", error);
- } else if (fault_log & DA9063_KEY_RESET) {
- error = regmap_write(onkey->hw->regmap,
- DA9063_REG_FAULT_LOG,
- DA9063_KEY_RESET);
+ } else if (fault_log & config->onkey_key_reset_mask) {
+ error = regmap_write(onkey->regmap,
+ config->onkey_fault_log,
+ config->onkey_key_reset_mask);
if (error) {
dev_warn(&onkey->input->dev,
"Cannot reset KEY_RESET fault log: %d\n",
@@ -88,10 +149,10 @@ static void da9063_poll_on(struct work_struct *work)
* and then send shutdown command
*/
dev_dbg(&onkey->input->dev,
- "Sending SHUTDOWN to DA9063 ...\n");
- error = regmap_write(onkey->hw->regmap,
- DA9063_REG_CONTROL_F,
- DA9063_SHUTDOWN);
+ "Sending SHUTDOWN to DA9063 ...\n");
+ error = regmap_write(onkey->regmap,
+ config->onkey_shutdown,
+ config->onkey_shutdown_mask);
if (error)
dev_err(&onkey->input->dev,
"Cannot SHUTDOWN DA9063: %d\n",
@@ -107,11 +168,14 @@ err_poll:
static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
{
struct da9063_onkey *onkey = data;
+ const struct da906x_chip_config *config = onkey->config;
unsigned int val;
int error;
- error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
- if (onkey->key_power && !error && (val & DA9063_NONKEY)) {
+ error = regmap_read(onkey->regmap,
+ config->onkey_status,
+ &val);
+ if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
input_report_key(onkey->input, KEY_POWER, 1);
input_sync(onkey->input);
schedule_delayed_work(&onkey->work, 0);
@@ -139,9 +203,15 @@ static int da9063_onkey_probe(struct platform_device *pdev)
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
struct da9063_onkey *onkey;
+ const struct of_device_id *match;
int irq;
int error;
+ match = of_match_node(da9063_compatible_reg_id_table,
+ pdev->dev.of_node);
+ if (!match)
+ return -ENXIO;
+
onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
GFP_KERNEL);
if (!onkey) {
@@ -149,8 +219,14 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ onkey->config = match->data;
onkey->dev = &pdev->dev;
- onkey->hw = da9063;
+
+ onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!onkey->regmap) {
+ dev_err(&pdev->dev, "Parent regmap unavailable.\n");
+ return -ENXIO;
+ }
if (pdata)
onkey->key_power = pdata->key_power;
@@ -165,8 +241,10 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
}
- onkey->input->name = DA9063_DRVNAME_ONKEY;
- onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0";
+ onkey->input->name = onkey->config->name;
+ snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
+ onkey->config->name);
+ onkey->input->phys = onkey->phys;
onkey->input->dev.parent = &pdev->dev;
if (onkey->key_power)
@@ -216,11 +294,12 @@ static struct platform_driver da9063_onkey_driver = {
.probe = da9063_onkey_probe,
.driver = {
.name = DA9063_DRVNAME_ONKEY,
+ .of_match_table = da9063_compatible_reg_id_table,
},
};
module_platform_driver(da9063_onkey_driver);
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
-MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063");
+MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 45e0e3e55de2..1c8c56efc995 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -198,7 +198,7 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
/* Read the i8042 real-time clock */
-static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_rt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
unsigned int days;
@@ -209,15 +209,15 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
days = (unsigned int)(raw >> 24) & 0xffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100) + days * 86400;
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (tenms / 100) + (time64_t)days * 86400;
return 0;
}
/* Read the i8042 fast handshake timer */
-static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
+static inline int hp_sdc_rtc_read_fhs(struct timespec64 *res) {
int64_t raw;
unsigned int tenms;
@@ -226,15 +226,15 @@ static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
tenms = (unsigned int)raw & 0xffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 match timer (a.k.a. alarm) */
-static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_mt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
@@ -243,15 +243,15 @@ static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 delay timer */
-static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_dt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
@@ -260,15 +260,15 @@ static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 cycle timer (a.k.a. periodic) */
-static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
+static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
@@ -277,8 +277,8 @@ static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
- res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
- res->tv_sec = (time_t)(tenms / 100);
+ res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
+ res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
@@ -433,7 +433,7 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
#define YN(bit) ("no")
#define NY(bit) ("yes")
struct rtc_time tm;
- struct timeval tv;
+ struct timespec64 tv;
memset(&tm, 0, sizeof(struct rtc_time));
@@ -452,36 +452,36 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
if (hp_sdc_rtc_read_rt(&tv)) {
seq_puts(m, "i8042 rtc\t: READ FAILED!\n");
} else {
- seq_printf(m, "i8042 rtc\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "i8042 rtc\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_fhs(&tv)) {
seq_puts(m, "handshake\t: READ FAILED!\n");
} else {
- seq_printf(m, "handshake\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "handshake\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_mt(&tv)) {
seq_puts(m, "alarm\t\t: READ FAILED!\n");
} else {
- seq_printf(m, "alarm\t\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "alarm\t\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_dt(&tv)) {
seq_puts(m, "delay\t\t: READ FAILED!\n");
} else {
- seq_printf(m, "delay\t\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "delay\t\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_ct(&tv)) {
seq_puts(m, "periodic\t: READ FAILED!\n");
} else {
- seq_printf(m, "periodic\t: %ld.%02d seconds\n",
- tv.tv_sec, (int)tv.tv_usec/1000);
+ seq_printf(m, "periodic\t: %lld.%02ld seconds\n",
+ (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
seq_printf(m,
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index e058d711256a..efaffcc57e36 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -635,7 +635,6 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
struct input_dev *input_dev = tj9->input_dev;
- int retval = 0;
mutex_lock(&input_dev->mutex);
@@ -643,7 +642,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
kxtj9_enable(tj9);
mutex_unlock(&input_dev->mutex);
- return retval;
+ return 0;
}
static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index f27f81ee84ed..8aee71986430 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -26,6 +26,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
+#include <linux/pm.h>
#define DRV_NAME "rotary-encoder"
@@ -142,6 +143,55 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
+{
+ struct rotary_encoder *encoder = dev_id;
+ unsigned char sum;
+ int state;
+
+ state = rotary_encoder_get_state(encoder->pdata);
+
+ /*
+ * We encode the previous and the current state using a byte.
+ * The previous state in the MSB nibble, the current state in the LSB
+ * nibble. Then use a table to decide the direction of the turn.
+ */
+ sum = (encoder->last_stable << 4) + state;
+ switch (sum) {
+ case 0x31:
+ case 0x10:
+ case 0x02:
+ case 0x23:
+ encoder->dir = 0; /* clockwise */
+ break;
+
+ case 0x13:
+ case 0x01:
+ case 0x20:
+ case 0x32:
+ encoder->dir = 1; /* counter-clockwise */
+ break;
+
+ default:
+ /*
+ * Ignore all other values. This covers the case when the
+ * state didn't change (a spurious interrupt) and the
+ * cases where the state changed by two steps, making it
+ * impossible to tell the direction.
+ *
+ * In either case, don't report any event and save the
+ * state for later.
+ */
+ goto out;
+ }
+
+ rotary_encoder_report_event(encoder);
+
+out:
+ encoder->last_stable = state;
+ return IRQ_HANDLED;
+}
+
#ifdef CONFIG_OF
static const struct of_device_id rotary_encoder_of_match[] = {
{ .compatible = "rotary-encoder", },
@@ -156,6 +206,7 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
struct device_node *np = dev->of_node;
struct rotary_encoder_platform_data *pdata;
enum of_gpio_flags flags;
+ int error;
if (!of_id || !np)
return NULL;
@@ -174,12 +225,27 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
- pdata->relative_axis = !!of_get_property(np,
- "rotary-encoder,relative-axis", NULL);
- pdata->rollover = !!of_get_property(np,
- "rotary-encoder,rollover", NULL);
- pdata->half_period = !!of_get_property(np,
- "rotary-encoder,half-period", NULL);
+ pdata->relative_axis =
+ of_property_read_bool(np, "rotary-encoder,relative-axis");
+ pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover");
+
+ error = of_property_read_u32(np, "rotary-encoder,steps-per-period",
+ &pdata->steps_per_period);
+ if (error) {
+ /*
+ * The 'half-period' property has been deprecated, you must use
+ * 'steps-per-period' and set an appropriate value, but we still
+ * need to parse it to maintain compatibility.
+ */
+ if (of_property_read_bool(np, "rotary-encoder,half-period")) {
+ pdata->steps_per_period = 2;
+ } else {
+ /* Fallback to one step per period behavior */
+ pdata->steps_per_period = 1;
+ }
+ }
+
+ pdata->wakeup_source = of_property_read_bool(np, "wakeup-source");
return pdata;
}
@@ -250,12 +316,23 @@ static int rotary_encoder_probe(struct platform_device *pdev)
encoder->irq_a = gpio_to_irq(pdata->gpio_a);
encoder->irq_b = gpio_to_irq(pdata->gpio_b);
- /* request the IRQs */
- if (pdata->half_period) {
+ switch (pdata->steps_per_period) {
+ case 4:
+ handler = &rotary_encoder_quarter_period_irq;
+ encoder->last_stable = rotary_encoder_get_state(pdata);
+ break;
+ case 2:
handler = &rotary_encoder_half_period_irq;
encoder->last_stable = rotary_encoder_get_state(pdata);
- } else {
+ break;
+ case 1:
handler = &rotary_encoder_irq;
+ break;
+ default:
+ dev_err(dev, "'%d' is not a valid steps-per-period value\n",
+ pdata->steps_per_period);
+ err = -EINVAL;
+ goto exit_free_gpio_b;
}
err = request_irq(encoder->irq_a, handler,
@@ -280,6 +357,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
goto exit_free_irq_b;
}
+ device_init_wakeup(&pdev->dev, pdata->wakeup_source);
+
platform_set_drvdata(pdev, encoder);
return 0;
@@ -306,6 +385,8 @@ static int rotary_encoder_remove(struct platform_device *pdev)
struct rotary_encoder *encoder = platform_get_drvdata(pdev);
const struct rotary_encoder_platform_data *pdata = encoder->pdata;
+ device_init_wakeup(&pdev->dev, false);
+
free_irq(encoder->irq_a, encoder);
free_irq(encoder->irq_b, encoder);
gpio_free(pdata->gpio_a);
@@ -320,11 +401,41 @@ static int rotary_encoder_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int rotary_encoder_suspend(struct device *dev)
+{
+ struct rotary_encoder *encoder = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(encoder->irq_a);
+ enable_irq_wake(encoder->irq_b);
+ }
+
+ return 0;
+}
+
+static int rotary_encoder_resume(struct device *dev)
+{
+ struct rotary_encoder *encoder = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(encoder->irq_a);
+ disable_irq_wake(encoder->irq_b);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops,
+ rotary_encoder_suspend, rotary_encoder_resume);
+
static struct platform_driver rotary_encoder_driver = {
.probe = rotary_encoder_probe,
.remove = rotary_encoder_remove,
.driver = {
.name = DRV_NAME,
+ .pm = &rotary_encoder_pm_ops,
.of_match_table = of_match_ptr(rotary_encoder_of_match),
}
};
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index 23d0549539d4..0a9ad2cfb55c 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -129,8 +129,14 @@ static int xenkbd_probe(struct xenbus_device *dev,
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
abs = 0;
- if (abs)
- xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+ if (abs) {
+ ret = xenbus_printf(XBT_NIL, dev->nodename,
+ "request-abs-pointer", "1");
+ if (ret) {
+ pr_warning("xenkbd: can't request abs-pointer");
+ abs = 0;
+ }
+ }
/* keyboard */
kbd = input_allocate_device();
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4d246861d692..41e6cb501e6a 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -100,7 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
6-byte ALPS packet */
-#define ALPS_DELL 0x100 /* device is a Dell laptop */
+#define ALPS_STICK_BITS 0x100 /* separate stick button bits */
#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
static const struct alps_model_info alps_model_data[] = {
@@ -159,6 +159,43 @@ static const struct alps_protocol_info alps_v8_protocol_data = {
ALPS_PROTO_V8, 0x18, 0x18, 0
};
+/*
+ * Some v2 models report the stick buttons in separate bits
+ */
+static const struct dmi_system_id alps_dmi_has_separate_stick_buttons[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ /* Extrapolated from other entries */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D420"),
+ },
+ },
+ {
+ /* Reported-by: Hans de Bruin <jmdebruin@xmsnet.nl> */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D430"),
+ },
+ },
+ {
+ /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D620"),
+ },
+ },
+ {
+ /* Extrapolated from other entries */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D630"),
+ },
+ },
+#endif
+ { }
+};
+
static void alps_set_abs_params_st(struct alps_data *priv,
struct input_dev *dev1);
static void alps_set_abs_params_semi_mt(struct alps_data *priv,
@@ -253,9 +290,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
return;
}
- /* Dell non interleaved V2 dualpoint has separate stick button bits */
- if (priv->proto_version == ALPS_PROTO_V2 &&
- priv->flags == (ALPS_DELL | ALPS_PASS | ALPS_DUALPOINT)) {
+ /* Some models have separate stick button bits */
+ if (priv->flags & ALPS_STICK_BITS) {
left |= packet[0] & 1;
right |= packet[0] & 2;
middle |= packet[0] & 4;
@@ -2552,8 +2588,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
priv->byte0 = protocol->byte0;
priv->mask0 = protocol->mask0;
priv->flags = protocol->flags;
- if (dmi_name_in_vendors("Dell"))
- priv->flags |= ALPS_DELL;
priv->x_max = 2000;
priv->y_max = 1400;
@@ -2568,6 +2602,8 @@ static int alps_set_protocol(struct psmouse *psmouse,
priv->set_abs_params = alps_set_abs_params_st;
priv->x_max = 1023;
priv->y_max = 767;
+ if (dmi_check_system(alps_dmi_has_separate_stick_buttons))
+ priv->flags |= ALPS_STICK_BITS;
break;
case ALPS_PROTO_V3:
diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c
index 5f191071d44a..e4eb048d1bf6 100644
--- a/drivers/input/mouse/cyapa_gen6.c
+++ b/drivers/input/mouse/cyapa_gen6.c
@@ -241,14 +241,10 @@ static int cyapa_gen6_read_sys_info(struct cyapa *cyapa)
memcpy(&cyapa->product_id[13], &resp_data[62], 2);
cyapa->product_id[15] = '\0';
+ /* Get the number of Rx electrodes. */
rotat_align = resp_data[68];
- if (rotat_align) {
- cyapa->electrodes_rx = cyapa->electrodes_y;
- cyapa->electrodes_rx = cyapa->electrodes_y;
- } else {
- cyapa->electrodes_rx = cyapa->electrodes_x;
- cyapa->electrodes_rx = cyapa->electrodes_y;
- }
+ cyapa->electrodes_rx =
+ rotat_align ? cyapa->electrodes_y : cyapa->electrodes_x;
cyapa->aligned_electrodes_rx = (cyapa->electrodes_rx + 3) & ~3u;
if (!cyapa->electrodes_x || !cyapa->electrodes_y ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 2955f1d0ca6c..537ebb0e193a 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1520,6 +1520,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E544"),
},
},
+ {
+ /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
+ },
+ },
#endif
{ }
};
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 200841b77edb..c3d05b4d3118 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -292,4 +292,18 @@ config SERIO_SUN4I_PS2
To compile this driver as a module, choose M here: the
module will be called sun4i-ps2.
+config USERIO
+ tristate "User space serio port driver support"
+ help
+ Say Y here if you want to support user level drivers for serio
+ subsystem accessible under char device 10:240 - /dev/userio. Using
+ this facility userspace programs can implement serio ports that
+ will be used by the standard in-kernel serio consumer drivers,
+ such as psmouse and atkbd.
+
+ To compile this driver as a module, choose M here: the module will be
+ called userio.
+
+ If you are unsure, say N.
+
endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index c600089b7a34..2374ef9b33d7 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o
obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o
obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o
obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o
+obj-$(CONFIG_USERIO) += userio.o
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index db91de539ee3..454195709a82 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/i8042.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
#include <asm/io.h>
@@ -1170,7 +1171,8 @@ static int i8042_pm_suspend(struct device *dev)
{
int i;
- i8042_controller_reset(true);
+ if (pm_suspend_via_firmware())
+ i8042_controller_reset(true);
/* Set up serio interrupts for system wakeup. */
for (i = 0; i < I8042_NUM_PORTS; i++) {
@@ -1183,8 +1185,17 @@ static int i8042_pm_suspend(struct device *dev)
return 0;
}
+static int i8042_pm_resume_noirq(struct device *dev)
+{
+ if (!pm_resume_via_firmware())
+ i8042_interrupt(0, NULL);
+
+ return 0;
+}
+
static int i8042_pm_resume(struct device *dev)
{
+ bool force_reset;
int i;
for (i = 0; i < I8042_NUM_PORTS; i++) {
@@ -1195,11 +1206,21 @@ static int i8042_pm_resume(struct device *dev)
}
/*
- * On resume from S2R we always try to reset the controller
- * to bring it in a sane state. (In case of S2D we expect
- * BIOS to reset the controller for us.)
+ * If platform firmware was not going to be involved in suspend, we did
+ * not restore the controller state to whatever it had been at boot
+ * time, so we do not need to do anything.
*/
- return i8042_controller_resume(true);
+ if (!pm_suspend_via_firmware())
+ return 0;
+
+ /*
+ * We only need to reset the controller if we are resuming after handing
+ * off control to the platform firmware, otherwise we can simply restore
+ * the mode.
+ */
+ force_reset = pm_resume_via_firmware();
+
+ return i8042_controller_resume(force_reset);
}
static int i8042_pm_thaw(struct device *dev)
@@ -1223,6 +1244,7 @@ static int i8042_pm_restore(struct device *dev)
static const struct dev_pm_ops i8042_pm_ops = {
.suspend = i8042_pm_suspend,
+ .resume_noirq = i8042_pm_resume_noirq,
.resume = i8042_pm_resume,
.thaw = i8042_pm_thaw,
.poweroff = i8042_pm_reset,
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index 1e8cd6f1fe9e..92c31b8f8fb4 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -141,19 +141,15 @@ static void parkbd_interrupt(void *dev_id)
parkbd_last = jiffies;
}
-static int parkbd_getport(void)
+static int parkbd_getport(struct parport *pp)
{
- struct parport *pp;
+ struct pardev_cb parkbd_parport_cb;
- pp = parport_find_number(parkbd_pp_no);
+ parkbd_parport_cb.irq_func = parkbd_interrupt;
+ parkbd_parport_cb.flags = PARPORT_FLAG_EXCL;
- if (pp == NULL) {
- printk(KERN_ERR "parkbd: no such parport\n");
- return -ENODEV;
- }
-
- parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
- parport_put_port(pp);
+ parkbd_dev = parport_register_dev_model(pp, "parkbd",
+ &parkbd_parport_cb, 0);
if (!parkbd_dev)
return -ENODEV;
@@ -168,7 +164,7 @@ static int parkbd_getport(void)
return 0;
}
-static struct serio * __init parkbd_allocate_serio(void)
+static struct serio *parkbd_allocate_serio(void)
{
struct serio *serio;
@@ -183,19 +179,21 @@ static struct serio * __init parkbd_allocate_serio(void)
return serio;
}
-static int __init parkbd_init(void)
+static void parkbd_attach(struct parport *pp)
{
- int err;
+ if (pp->number != parkbd_pp_no) {
+ pr_debug("Not using parport%d.\n", pp->number);
+ return;
+ }
- err = parkbd_getport();
- if (err)
- return err;
+ if (parkbd_getport(pp))
+ return;
parkbd_port = parkbd_allocate_serio();
if (!parkbd_port) {
parport_release(parkbd_dev);
parport_unregister_device(parkbd_dev);
- return -ENOMEM;
+ return;
}
parkbd_writelines(3);
@@ -205,14 +203,35 @@ static int __init parkbd_init(void)
printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
- return 0;
+ return;
}
-static void __exit parkbd_exit(void)
+static void parkbd_detach(struct parport *port)
{
+ if (!parkbd_port || port->number != parkbd_pp_no)
+ return;
+
parport_release(parkbd_dev);
serio_unregister_port(parkbd_port);
parport_unregister_device(parkbd_dev);
+ parkbd_port = NULL;
+}
+
+static struct parport_driver parkbd_parport_driver = {
+ .name = "parkbd",
+ .match_port = parkbd_attach,
+ .detach = parkbd_detach,
+ .devmodel = true,
+};
+
+static int __init parkbd_init(void)
+{
+ return parport_register_driver(&parkbd_parport_driver);
+}
+
+static void __exit parkbd_exit(void)
+{
+ parport_unregister_driver(&parkbd_parport_driver);
}
module_init(parkbd_init);
diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c
new file mode 100644
index 000000000000..df1fd41860ac
--- /dev/null
+++ b/drivers/input/serio/userio.c
@@ -0,0 +1,285 @@
+/*
+ * userio kernel serio device emulation module
+ * Copyright (C) 2015 Red Hat
+ * Copyright (C) 2015 Stephen Chandler Paul <thatslyude@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser 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 Lesser
+ * General Public License for more details.
+ */
+
+#include <linux/circ_buf.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <uapi/linux/userio.h>
+
+#define USERIO_NAME "userio"
+#define USERIO_BUFSIZE 16
+
+static struct miscdevice userio_misc;
+
+struct userio_device {
+ struct serio *serio;
+ struct mutex mutex;
+
+ bool running;
+
+ u8 head;
+ u8 tail;
+
+ spinlock_t buf_lock;
+ unsigned char buf[USERIO_BUFSIZE];
+
+ wait_queue_head_t waitq;
+};
+
+/**
+ * userio_device_write - Write data from serio to a userio device in userspace
+ * @id: The serio port for the userio device
+ * @val: The data to write to the device
+ */
+static int userio_device_write(struct serio *id, unsigned char val)
+{
+ struct userio_device *userio = id->port_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&userio->buf_lock, flags);
+
+ userio->buf[userio->head] = val;
+ userio->head = (userio->head + 1) % USERIO_BUFSIZE;
+
+ if (userio->head == userio->tail)
+ dev_warn(userio_misc.this_device,
+ "Buffer overflowed, userio client isn't keeping up");
+
+ spin_unlock_irqrestore(&userio->buf_lock, flags);
+
+ wake_up_interruptible(&userio->waitq);
+
+ return 0;
+}
+
+static int userio_char_open(struct inode *inode, struct file *file)
+{
+ struct userio_device *userio;
+
+ userio = kzalloc(sizeof(struct userio_device), GFP_KERNEL);
+ if (!userio)
+ return -ENOMEM;
+
+ mutex_init(&userio->mutex);
+ spin_lock_init(&userio->buf_lock);
+ init_waitqueue_head(&userio->waitq);
+
+ userio->serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!userio->serio) {
+ kfree(userio);
+ return -ENOMEM;
+ }
+
+ userio->serio->write = userio_device_write;
+ userio->serio->port_data = userio;
+
+ file->private_data = userio;
+
+ return 0;
+}
+
+static int userio_char_release(struct inode *inode, struct file *file)
+{
+ struct userio_device *userio = file->private_data;
+
+ if (userio->running) {
+ /*
+ * Don't free the serio port here, serio_unregister_port()
+ * does it for us.
+ */
+ serio_unregister_port(userio->serio);
+ } else {
+ kfree(userio->serio);
+ }
+
+ kfree(userio);
+
+ return 0;
+}
+
+static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
+ size_t count, loff_t *ppos)
+{
+ struct userio_device *userio = file->private_data;
+ int error;
+ size_t nonwrap_len, copylen;
+ unsigned char buf[USERIO_BUFSIZE];
+ unsigned long flags;
+
+ /*
+ * By the time we get here, the data that was waiting might have
+ * been taken by another thread. Grab the buffer lock and check if
+ * there's still any data waiting, otherwise repeat this process
+ * until we have data (unless the file descriptor is non-blocking
+ * of course).
+ */
+ for (;;) {
+ spin_lock_irqsave(&userio->buf_lock, flags);
+
+ nonwrap_len = CIRC_CNT_TO_END(userio->head,
+ userio->tail,
+ USERIO_BUFSIZE);
+ copylen = min(nonwrap_len, count);
+ if (copylen) {
+ memcpy(buf, &userio->buf[userio->tail], copylen);
+ userio->tail = (userio->tail + copylen) %
+ USERIO_BUFSIZE;
+ }
+
+ spin_unlock_irqrestore(&userio->buf_lock, flags);
+
+ if (nonwrap_len)
+ break;
+
+ /* buffer was/is empty */
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ /*
+ * count == 0 is special - no IO is done but we check
+ * for error conditions (see above).
+ */
+ if (count == 0)
+ return 0;
+
+ error = wait_event_interruptible(userio->waitq,
+ userio->head != userio->tail);
+ if (error)
+ return error;
+ }
+
+ if (copylen)
+ if (copy_to_user(user_buffer, buf, copylen))
+ return -EFAULT;
+
+ return copylen;
+}
+
+static ssize_t userio_char_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct userio_device *userio = file->private_data;
+ struct userio_cmd cmd;
+ int error;
+
+ if (count != sizeof(cmd)) {
+ dev_warn(userio_misc.this_device, "Invalid payload size\n");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&cmd, buffer, sizeof(cmd)))
+ return -EFAULT;
+
+ error = mutex_lock_interruptible(&userio->mutex);
+ if (error)
+ return error;
+
+ switch (cmd.type) {
+ case USERIO_CMD_REGISTER:
+ if (!userio->serio->id.type) {
+ dev_warn(userio_misc.this_device,
+ "No port type given on /dev/userio\n");
+
+ error = -EINVAL;
+ goto out;
+ }
+
+ if (userio->running) {
+ dev_warn(userio_misc.this_device,
+ "Begin command sent, but we're already running\n");
+ error = -EBUSY;
+ goto out;
+ }
+
+ userio->running = true;
+ serio_register_port(userio->serio);
+ break;
+
+ case USERIO_CMD_SET_PORT_TYPE:
+ if (userio->running) {
+ dev_warn(userio_misc.this_device,
+ "Can't change port type on an already running userio instance\n");
+ error = -EBUSY;
+ goto out;
+ }
+
+ userio->serio->id.type = cmd.data;
+ break;
+
+ case USERIO_CMD_SEND_INTERRUPT:
+ if (!userio->running) {
+ dev_warn(userio_misc.this_device,
+ "The device must be registered before sending interrupts\n");
+ error = -ENODEV;
+ goto out;
+ }
+
+ serio_interrupt(userio->serio, cmd.data, 0);
+ break;
+
+ default:
+ error = -EOPNOTSUPP;
+ goto out;
+ }
+
+out:
+ mutex_unlock(&userio->mutex);
+ return error ?: count;
+}
+
+static unsigned int userio_char_poll(struct file *file, poll_table *wait)
+{
+ struct userio_device *userio = file->private_data;
+
+ poll_wait(file, &userio->waitq, wait);
+
+ if (userio->head != userio->tail)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static const struct file_operations userio_fops = {
+ .owner = THIS_MODULE,
+ .open = userio_char_open,
+ .release = userio_char_release,
+ .read = userio_char_read,
+ .write = userio_char_write,
+ .poll = userio_char_poll,
+ .llseek = no_llseek,
+};
+
+static struct miscdevice userio_misc = {
+ .fops = &userio_fops,
+ .minor = USERIO_MINOR,
+ .name = USERIO_NAME,
+};
+module_driver(userio_misc, misc_register, misc_deregister);
+
+MODULE_ALIAS_MISCDEV(USERIO_MINOR);
+MODULE_ALIAS("devname:" USERIO_NAME);
+
+MODULE_AUTHOR("Stephen Chandler Paul <thatslyude@gmail.com>");
+MODULE_DESCRIPTION("Virtual Serio Device Support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 600dcceff542..ae33da7ab51f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -295,6 +295,19 @@ config TOUCHSCREEN_EGALAX
To compile this driver as a module, choose M here: the
module will be called egalax_ts.
+config TOUCHSCREEN_FT6236
+ tristate "FT6236 I2C touchscreen"
+ depends on I2C
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ Say Y here to enable support for the I2C connected FT6x06 and
+ FT6x36 family of capacitive touchscreen drivers.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ft6236.
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
@@ -926,10 +939,27 @@ config TOUCHSCREEN_TSC_SERIO
To compile this driver as a module, choose M here: the
module will be called tsc40.
+config TOUCHSCREEN_TSC200X_CORE
+ tristate
+
+config TOUCHSCREEN_TSC2004
+ tristate "TSC2004 based touchscreens"
+ depends on I2C
+ select REGMAP_I2C
+ select TOUCHSCREEN_TSC200X_CORE
+ help
+ Say Y here if you have a TSC2004 based touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tsc2004.
+
config TOUCHSCREEN_TSC2005
tristate "TSC2005 based touchscreens"
depends on SPI_MASTER
select REGMAP_SPI
+ select TOUCHSCREEN_TSC200X_CORE
help
Say Y here if you have a TSC2005 based touchscreen.
@@ -1006,6 +1036,7 @@ config TOUCHSCREEN_SUN4I
config TOUCHSCREEN_SUR40
tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
+ depends on VIDEO_V4L2
select INPUT_POLLDEV
select VIDEOBUF2_DMA_SG
help
@@ -1064,4 +1095,15 @@ config TOUCHSCREEN_COLIBRI_VF50
To compile this driver as a module, choose M here: the
module will be called colibri_vf50_ts.
+config TOUCHSCREEN_ROHM_BU21023
+ tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a touchscreen using ROHM BU21023/24.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bu21023_ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 1b79cc09744a..cbaa6abb08da 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
+obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
@@ -68,6 +69,8 @@ obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o
+obj-$(CONFIG_TOUCHSCREEN_TSC200X_CORE) += tsc200x-core.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2004) += tsc2004.o
obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
@@ -87,3 +90,4 @@ obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
+obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index da4e5bb5e045..9c250ae780d9 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -843,7 +843,6 @@ static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
static struct spi_driver ad7877_driver = {
.driver = {
.name = "ad7877",
- .owner = THIS_MODULE,
.pm = &ad7877_pm,
},
.probe = ad7877_probe,
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
index 1a7b1143536e..48033c2689ab 100644
--- a/drivers/input/touchscreen/ad7879-spi.c
+++ b/drivers/input/touchscreen/ad7879-spi.c
@@ -149,7 +149,6 @@ static int ad7879_spi_remove(struct spi_device *spi)
static struct spi_driver ad7879_spi_driver = {
.driver = {
.name = "ad7879",
- .owner = THIS_MODULE,
.pm = &ad7879_pm_ops,
},
.probe = ad7879_spi_probe,
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 0f5f968592bd..a61b2153ab8c 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -529,10 +529,8 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias,
ts, ads7846_attr_groups);
- if (IS_ERR(ts->hwmon))
- return PTR_ERR(ts->hwmon);
- return 0;
+ return PTR_ERR_OR_ZERO(ts->hwmon);
}
static void ads784x_hwmon_unregister(struct spi_device *spi,
@@ -668,18 +666,22 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val)
static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
{
+ int value;
struct spi_transfer *t =
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
if (ts->model == 7845) {
- return be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
+ value = be16_to_cpup((__be16 *)&(((char *)t->rx_buf)[1]));
} else {
/*
* adjust: on-wire is a must-ignore bit, a BE12 value, then
* padding; built from two 8 bit values written msb-first.
*/
- return be16_to_cpup((__be16 *)t->rx_buf) >> 3;
+ value = be16_to_cpup((__be16 *)t->rx_buf);
}
+
+ /* enforce ADC output is 12 bits width */
+ return (value >> 3) & 0xfff;
}
static void ads7846_update_value(struct spi_message *m, int val)
@@ -1496,7 +1498,6 @@ static int ads7846_remove(struct spi_device *spi)
static struct spi_driver ads7846_driver = {
.driver = {
.name = "ads7846",
- .owner = THIS_MODULE,
.pm = &ads7846_pm,
.of_match_table = of_match_ptr(ads7846_dt_ids),
},
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 38c06f754acd..6592fc5d48b4 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -399,13 +399,8 @@ static int auo_pixcir_stop(struct auo_pixcir_ts *ts)
static int auo_pixcir_input_open(struct input_dev *dev)
{
struct auo_pixcir_ts *ts = input_get_drvdata(dev);
- int ret;
-
- ret = auo_pixcir_start(ts);
- if (ret)
- return ret;
- return 0;
+ return auo_pixcir_start(ts);
}
static void auo_pixcir_input_close(struct input_dev *dev)
diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c
index a9f95c7d3c00..564e49002d5d 100644
--- a/drivers/input/touchscreen/cyttsp4_i2c.c
+++ b/drivers/input/touchscreen/cyttsp4_i2c.c
@@ -50,10 +50,7 @@ static int cyttsp4_i2c_probe(struct i2c_client *client,
ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq,
CYTTSP4_I2C_DATA_SIZE);
- if (IS_ERR(ts))
- return PTR_ERR(ts);
-
- return 0;
+ return PTR_ERR_OR_ZERO(ts);
}
static int cyttsp4_i2c_remove(struct i2c_client *client)
diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c
index b19434cebbf6..ec5f7c74f048 100644
--- a/drivers/input/touchscreen/cyttsp4_spi.c
+++ b/drivers/input/touchscreen/cyttsp4_spi.c
@@ -185,7 +185,6 @@ static int cyttsp4_spi_remove(struct spi_device *spi)
static struct spi_driver cyttsp4_spi_driver = {
.driver = {
.name = CYTTSP4_SPI_NAME,
- .owner = THIS_MODULE,
.pm = &cyttsp4_pm_ops,
},
.probe = cyttsp4_spi_probe,
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
index 4728bcb1916c..bbeeb2488b57 100644
--- a/drivers/input/touchscreen/cyttsp_spi.c
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -182,7 +182,6 @@ static int cyttsp_spi_remove(struct spi_device *spi)
static struct spi_driver cyttsp_spi_driver = {
.driver = {
.name = CY_SPI_NAME,
- .owner = THIS_MODULE,
.pm = &cyttsp_pm_ops,
},
.probe = cyttsp_spi_probe,
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 48de1e8b3c93..0b0f8c17f3f7 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/ratelimit.h>
+#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/i2c.h>
@@ -34,13 +35,10 @@
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
-#include <linux/input/edt-ft5x06.h>
-
-#define MAX_SUPPORT_POINTS 5
+#include <linux/of_device.h>
#define WORK_REGISTER_THRESHOLD 0x00
#define WORK_REGISTER_REPORT_RATE 0x08
@@ -91,9 +89,8 @@ struct edt_ft5x06_ts_data {
u16 num_x;
u16 num_y;
- int reset_pin;
- int irq_pin;
- int wake_pin;
+ struct gpio_desc *reset_gpio;
+ struct gpio_desc *wake_gpio;
#if defined(CONFIG_DEBUG_FS)
struct dentry *debug_dir;
@@ -107,6 +104,7 @@ struct edt_ft5x06_ts_data {
int gain;
int offset;
int report_rate;
+ int max_support_points;
char name[EDT_NAME_LEN];
@@ -114,6 +112,10 @@ struct edt_ft5x06_ts_data {
enum edt_ver version;
};
+struct edt_i2c_chip_data {
+ int max_support_points;
+};
+
static int edt_ft5x06_ts_readwrite(struct i2c_client *client,
u16 wr_len, u8 *wr_buf,
u16 rd_len, u8 *rd_buf)
@@ -170,9 +172,9 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
struct edt_ft5x06_ts_data *tsdata = dev_id;
struct device *dev = &tsdata->client->dev;
u8 cmd;
- u8 rdbuf[29];
+ u8 rdbuf[63];
int i, type, x, y, id;
- int offset, tplen, datalen;
+ int offset, tplen, datalen, crclen;
int error;
switch (tsdata->version) {
@@ -180,14 +182,14 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
cmd = 0xf9; /* tell the controller to send touch data */
offset = 5; /* where the actual touch data starts */
tplen = 4; /* data comes in so called frames */
- datalen = 26; /* how much bytes to listen for */
+ crclen = 1; /* length of the crc data */
break;
case M09:
- cmd = 0x02;
- offset = 1;
+ cmd = 0x0;
+ offset = 3;
tplen = 6;
- datalen = 29;
+ crclen = 0;
break;
default:
@@ -195,6 +197,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
}
memset(rdbuf, 0, sizeof(rdbuf));
+ datalen = tplen * tsdata->max_support_points + offset + crclen;
error = edt_ft5x06_ts_readwrite(tsdata->client,
sizeof(cmd), &cmd,
@@ -219,7 +222,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
goto out;
}
- for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
+ for (i = 0; i < tsdata->max_support_points; i++) {
u8 *buf = &rdbuf[i * tplen + offset];
bool down;
@@ -752,45 +755,6 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
#endif /* CONFIG_DEBUGFS */
-static int edt_ft5x06_ts_reset(struct i2c_client *client,
- struct edt_ft5x06_ts_data *tsdata)
-{
- int error;
-
- if (gpio_is_valid(tsdata->wake_pin)) {
- error = devm_gpio_request_one(&client->dev,
- tsdata->wake_pin, GPIOF_OUT_INIT_LOW,
- "edt-ft5x06 wake");
- if (error) {
- dev_err(&client->dev,
- "Failed to request GPIO %d as wake pin, error %d\n",
- tsdata->wake_pin, error);
- return error;
- }
-
- msleep(5);
- gpio_set_value(tsdata->wake_pin, 1);
- }
- if (gpio_is_valid(tsdata->reset_pin)) {
- /* this pulls reset down, enabling the low active reset */
- error = devm_gpio_request_one(&client->dev,
- tsdata->reset_pin, GPIOF_OUT_INIT_LOW,
- "edt-ft5x06 reset");
- if (error) {
- dev_err(&client->dev,
- "Failed to request GPIO %d as reset pin, error %d\n",
- tsdata->reset_pin, error);
- return error;
- }
-
- msleep(5);
- gpio_set_value(tsdata->reset_pin, 1);
- msleep(300);
- }
-
- return 0;
-}
-
static int edt_ft5x06_ts_identify(struct i2c_client *client,
struct edt_ft5x06_ts_data *tsdata,
char *fw_version)
@@ -850,44 +814,24 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
return 0;
}
-#define EDT_ATTR_CHECKSET(name, reg) \
-do { \
- if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \
- pdata->name <= edt_ft5x06_attr_##name.limit_high) \
- edt_ft5x06_register_write(tsdata, reg, pdata->name); \
-} while (0)
-
-#define EDT_GET_PROP(name, reg) { \
- u32 val; \
- if (of_property_read_u32(np, #name, &val) == 0) \
- edt_ft5x06_register_write(tsdata, reg, val); \
-}
-
-static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np,
- struct edt_ft5x06_ts_data *tsdata)
+static void edt_ft5x06_ts_get_defaults(struct device *dev,
+ struct edt_ft5x06_ts_data *tsdata)
{
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
+ u32 val;
+ int error;
- EDT_GET_PROP(threshold, reg_addr->reg_threshold);
- EDT_GET_PROP(gain, reg_addr->reg_gain);
- EDT_GET_PROP(offset, reg_addr->reg_offset);
-}
+ error = device_property_read_u32(dev, "threshold", &val);
+ if (!error)
+ reg_addr->reg_threshold = val;
-static void
-edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
- const struct edt_ft5x06_platform_data *pdata)
-{
- struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
-
- if (!pdata->use_parameters)
- return;
+ error = device_property_read_u32(dev, "gain", &val);
+ if (!error)
+ reg_addr->reg_gain = val;
- /* pick up defaults from the platform data */
- EDT_ATTR_CHECKSET(threshold, reg_addr->reg_threshold);
- EDT_ATTR_CHECKSET(gain, reg_addr->reg_gain);
- EDT_ATTR_CHECKSET(offset, reg_addr->reg_offset);
- if (reg_addr->reg_report_rate != NO_REGISTER)
- EDT_ATTR_CHECKSET(report_rate, reg_addr->reg_report_rate);
+ error = device_property_read_u32(dev, "offset", &val);
+ if (!error)
+ reg_addr->reg_offset = val;
}
static void
@@ -931,37 +875,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
}
}
-#ifdef CONFIG_OF
-static int edt_ft5x06_i2c_ts_probe_dt(struct device *dev,
- struct edt_ft5x06_ts_data *tsdata)
-{
- struct device_node *np = dev->of_node;
-
- /*
- * irq_pin is not needed for DT setup.
- * irq is associated via 'interrupts' property in DT
- */
- tsdata->irq_pin = -EINVAL;
- tsdata->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
- tsdata->wake_pin = of_get_named_gpio(np, "wake-gpios", 0);
-
- return 0;
-}
-#else
-static inline int edt_ft5x06_i2c_ts_probe_dt(struct device *dev,
- struct edt_ft5x06_ts_data *tsdata)
-{
- return -ENODEV;
-}
-#endif
-
static int edt_ft5x06_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct edt_ft5x06_platform_data *pdata =
- dev_get_platdata(&client->dev);
+ const struct edt_i2c_chip_data *chip_data;
struct edt_ft5x06_ts_data *tsdata;
struct input_dev *input;
+ unsigned long irq_flags;
int error;
char fw_version[EDT_NAME_LEN];
@@ -973,32 +893,43 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
return -ENOMEM;
}
- if (!pdata) {
- error = edt_ft5x06_i2c_ts_probe_dt(&client->dev, tsdata);
- if (error) {
- dev_err(&client->dev,
- "DT probe failed and no platform data present\n");
- return error;
- }
- } else {
- tsdata->reset_pin = pdata->reset_pin;
- tsdata->irq_pin = pdata->irq_pin;
- tsdata->wake_pin = -EINVAL;
+ chip_data = of_device_get_match_data(&client->dev);
+ if (!chip_data)
+ chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
+ if (!chip_data || !chip_data->max_support_points) {
+ dev_err(&client->dev, "invalid or missing chip data\n");
+ return -EINVAL;
}
- error = edt_ft5x06_ts_reset(client, tsdata);
- if (error)
+ tsdata->max_support_points = chip_data->max_support_points;
+
+ tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
+ "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(tsdata->reset_gpio)) {
+ error = PTR_ERR(tsdata->reset_gpio);
+ dev_err(&client->dev,
+ "Failed to request GPIO reset pin, error %d\n", error);
+ return error;
+ }
+
+ tsdata->wake_gpio = devm_gpiod_get_optional(&client->dev,
+ "wake", GPIOD_OUT_LOW);
+ if (IS_ERR(tsdata->wake_gpio)) {
+ error = PTR_ERR(tsdata->wake_gpio);
+ dev_err(&client->dev,
+ "Failed to request GPIO wake pin, error %d\n", error);
return error;
+ }
- if (gpio_is_valid(tsdata->irq_pin)) {
- error = devm_gpio_request_one(&client->dev, tsdata->irq_pin,
- GPIOF_IN, "edt-ft5x06 irq");
- if (error) {
- dev_err(&client->dev,
- "Failed to request GPIO %d, error %d\n",
- tsdata->irq_pin, error);
- return error;
- }
+ if (tsdata->wake_gpio) {
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(tsdata->wake_gpio, 1);
+ }
+
+ if (tsdata->reset_gpio) {
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(tsdata->reset_gpio, 0);
+ msleep(300);
}
input = devm_input_allocate_device(&client->dev);
@@ -1019,12 +950,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
}
edt_ft5x06_ts_set_regs(tsdata);
-
- if (!pdata)
- edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata);
- else
- edt_ft5x06_ts_get_defaults(tsdata, pdata);
-
+ edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
edt_ft5x06_ts_get_parameters(tsdata);
dev_dbg(&client->dev,
@@ -1040,10 +966,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_MT_POSITION_Y,
0, tsdata->num_y * 64 - 1, 0, 0);
- if (!pdata)
- touchscreen_parse_properties(input, true);
+ touchscreen_parse_properties(input, true);
- error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, INPUT_MT_DIRECT);
+ error = input_mt_init_slots(input, tsdata->max_support_points,
+ INPUT_MT_DIRECT);
if (error) {
dev_err(&client->dev, "Unable to init MT slots.\n");
return error;
@@ -1052,9 +978,13 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
input_set_drvdata(input, tsdata);
i2c_set_clientdata(client, tsdata);
- error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
- edt_ft5x06_ts_isr,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ irq_flags = irq_get_trigger_type(client->irq);
+ if (irq_flags == IRQF_TRIGGER_NONE)
+ irq_flags = IRQF_TRIGGER_FALLING;
+ irq_flags |= IRQF_ONESHOT;
+
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, edt_ft5x06_ts_isr, irq_flags,
client->name, tsdata);
if (error) {
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
@@ -1074,7 +1004,9 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
dev_dbg(&client->dev,
"EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n",
- client->irq, tsdata->wake_pin, tsdata->reset_pin);
+ client->irq,
+ tsdata->wake_gpio ? desc_to_gpio(tsdata->wake_gpio) : -1,
+ tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1);
return 0;
@@ -1116,17 +1048,27 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);
+static const struct edt_i2c_chip_data edt_ft5x06_data = {
+ .max_support_points = 5,
+};
+
+static const struct edt_i2c_chip_data edt_ft5506_data = {
+ .max_support_points = 10,
+};
+
static const struct i2c_device_id edt_ft5x06_ts_id[] = {
- { "edt-ft5x06", 0, },
+ { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
+ { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
#ifdef CONFIG_OF
static const struct of_device_id edt_ft5x06_of_match[] = {
- { .compatible = "edt,edt-ft5206", },
- { .compatible = "edt,edt-ft5306", },
- { .compatible = "edt,edt-ft5406", },
+ { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data },
+ { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
+ { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
+ { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
diff --git a/drivers/input/touchscreen/ft6236.c b/drivers/input/touchscreen/ft6236.c
new file mode 100644
index 000000000000..d240d2e212bd
--- /dev/null
+++ b/drivers/input/touchscreen/ft6236.c
@@ -0,0 +1,326 @@
+/*
+ * FocalTech FT6236 TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * 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/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/property.h>
+
+#define FT6236_MAX_TOUCH_POINTS 2
+
+#define FT6236_REG_TH_GROUP 0x80
+#define FT6236_REG_PERIODACTIVE 0x88
+#define FT6236_REG_LIB_VER_H 0xa1
+#define FT6236_REG_LIB_VER_L 0xa2
+#define FT6236_REG_CIPHER 0xa3
+#define FT6236_REG_FIRMID 0xa6
+#define FT6236_REG_FOCALTECH_ID 0xa8
+#define FT6236_REG_RELEASE_CODE_ID 0xaf
+
+#define FT6236_EVENT_PRESS_DOWN 0
+#define FT6236_EVENT_LIFT_UP 1
+#define FT6236_EVENT_CONTACT 2
+#define FT6236_EVENT_NO_EVENT 3
+
+struct ft6236_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct gpio_desc *reset_gpio;
+ u32 max_x;
+ u32 max_y;
+ bool invert_x;
+ bool invert_y;
+ bool swap_xy;
+};
+
+/*
+ * This struct is a touchpoint as stored in hardware. Note that the id,
+ * as well as the event, are stored in the upper nybble of the hi byte.
+ */
+struct ft6236_touchpoint {
+ union {
+ u8 xhi;
+ u8 event;
+ };
+ u8 xlo;
+ union {
+ u8 yhi;
+ u8 id;
+ };
+ u8 ylo;
+ u8 weight;
+ u8 misc;
+} __packed;
+
+/* This packet represents the register map as read from offset 0 */
+struct ft6236_packet {
+ u8 dev_mode;
+ u8 gest_id;
+ u8 touches;
+ struct ft6236_touchpoint points[FT6236_MAX_TOUCH_POINTS];
+} __packed;
+
+static int ft6236_read(struct i2c_client *client, u8 reg, u8 len, void *data)
+{
+ int error;
+
+ error = i2c_smbus_read_i2c_block_data(client, reg, len, data);
+ if (error < 0)
+ return error;
+
+ if (error != len)
+ return -EIO;
+
+ return 0;
+}
+
+static irqreturn_t ft6236_interrupt(int irq, void *dev_id)
+{
+ struct ft6236_data *ft6236 = dev_id;
+ struct device *dev = &ft6236->client->dev;
+ struct input_dev *input = ft6236->input;
+ struct ft6236_packet buf;
+ u8 touches;
+ int i, error;
+
+ error = ft6236_read(ft6236->client, 0, sizeof(buf), &buf);
+ if (error) {
+ dev_err(dev, "read touchdata failed %d\n", error);
+ return IRQ_HANDLED;
+ }
+
+ touches = buf.touches & 0xf;
+ if (touches > FT6236_MAX_TOUCH_POINTS) {
+ dev_dbg(dev,
+ "%d touch points reported, only %d are supported\n",
+ touches, FT6236_MAX_TOUCH_POINTS);
+ touches = FT6236_MAX_TOUCH_POINTS;
+ }
+
+ for (i = 0; i < touches; i++) {
+ struct ft6236_touchpoint *point = &buf.points[i];
+ u16 x = ((point->xhi & 0xf) << 8) | buf.points[i].xlo;
+ u16 y = ((point->yhi & 0xf) << 8) | buf.points[i].ylo;
+ u8 event = point->event >> 6;
+ u8 id = point->id >> 4;
+ bool act = (event == FT6236_EVENT_PRESS_DOWN ||
+ event == FT6236_EVENT_CONTACT);
+
+ input_mt_slot(input, id);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, act);
+ if (!act)
+ continue;
+
+ if (ft6236->invert_x)
+ x = ft6236->max_x - x;
+
+ if (ft6236->invert_y)
+ y = ft6236->max_y - y;
+
+ if (ft6236->swap_xy) {
+ input_report_abs(input, ABS_MT_POSITION_X, y);
+ input_report_abs(input, ABS_MT_POSITION_Y, x);
+ } else {
+ input_report_abs(input, ABS_MT_POSITION_X, x);
+ input_report_abs(input, ABS_MT_POSITION_Y, y);
+ }
+ }
+
+ input_mt_sync_frame(input);
+ input_sync(input);
+
+ return IRQ_HANDLED;
+}
+
+static u8 ft6236_debug_read_byte(struct ft6236_data *ft6236, u8 reg)
+{
+ struct i2c_client *client = ft6236->client;
+ u8 val = 0;
+ int error;
+
+ error = ft6236_read(client, reg, 1, &val);
+ if (error)
+ dev_dbg(&client->dev,
+ "error reading register 0x%02x: %d\n", reg, error);
+
+ return val;
+}
+
+static void ft6236_debug_info(struct ft6236_data *ft6236)
+{
+ struct device *dev = &ft6236->client->dev;
+
+ dev_dbg(dev, "Touch threshold is %d\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_TH_GROUP) * 4);
+ dev_dbg(dev, "Report rate is %dHz\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_PERIODACTIVE) * 10);
+ dev_dbg(dev, "Firmware library version 0x%02x%02x\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_H),
+ ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_L));
+ dev_dbg(dev, "Firmware version 0x%02x\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_FIRMID));
+ dev_dbg(dev, "Chip vendor ID 0x%02x\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_CIPHER));
+ dev_dbg(dev, "CTPM vendor ID 0x%02x\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_FOCALTECH_ID));
+ dev_dbg(dev, "Release code version 0x%02x\n",
+ ft6236_debug_read_byte(ft6236, FT6236_REG_RELEASE_CODE_ID));
+}
+
+static void ft6236_reset(struct ft6236_data *ft6236)
+{
+ if (!ft6236->reset_gpio)
+ return;
+
+ gpiod_set_value_cansleep(ft6236->reset_gpio, 1);
+ usleep_range(5000, 20000);
+ gpiod_set_value_cansleep(ft6236->reset_gpio, 0);
+ msleep(300);
+}
+
+static int ft6236_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct ft6236_data *ft6236;
+ struct input_dev *input;
+ u32 fuzz_x = 0, fuzz_y = 0;
+ u8 val;
+ int error;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENXIO;
+
+ if (!client->irq) {
+ dev_err(dev, "irq is missing\n");
+ return -EINVAL;
+ }
+
+ ft6236 = devm_kzalloc(dev, sizeof(*ft6236), GFP_KERNEL);
+ if (!ft6236)
+ return -ENOMEM;
+
+ ft6236->client = client;
+ ft6236->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ft6236->reset_gpio)) {
+ error = PTR_ERR(ft6236->reset_gpio);
+ if (error != -EPROBE_DEFER)
+ dev_err(dev, "error getting reset gpio: %d\n", error);
+ return error;
+ }
+
+ ft6236_reset(ft6236);
+
+ /* verify that the controller is present */
+ error = ft6236_read(client, 0x00, 1, &val);
+ if (error) {
+ dev_err(dev, "failed to read from controller: %d\n", error);
+ return error;
+ }
+
+ ft6236_debug_info(ft6236);
+
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return -ENOMEM;
+
+ ft6236->input = input;
+ input->name = client->name;
+ input->id.bustype = BUS_I2C;
+
+ if (device_property_read_u32(dev, "touchscreen-size-x",
+ &ft6236->max_x) ||
+ device_property_read_u32(dev, "touchscreen-size-y",
+ &ft6236->max_y)) {
+ dev_err(dev, "touchscreen-size-x and/or -y missing\n");
+ return -EINVAL;
+ }
+
+ device_property_read_u32(dev, "touchscreen-fuzz-x", &fuzz_x);
+ device_property_read_u32(dev, "touchscreen-fuzz-y", &fuzz_y);
+ ft6236->invert_x = device_property_read_bool(dev,
+ "touchscreen-inverted-x");
+ ft6236->invert_y = device_property_read_bool(dev,
+ "touchscreen-inverted-y");
+ ft6236->swap_xy = device_property_read_bool(dev,
+ "touchscreen-swapped-x-y");
+
+ if (ft6236->swap_xy) {
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+ ft6236->max_y, fuzz_y, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+ ft6236->max_x, fuzz_x, 0);
+ } else {
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+ ft6236->max_x, fuzz_x, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+ ft6236->max_y, fuzz_y, 0);
+ }
+
+ error = input_mt_init_slots(input, FT6236_MAX_TOUCH_POINTS,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (error)
+ return error;
+
+ error = devm_request_threaded_irq(dev, client->irq, NULL,
+ ft6236_interrupt, IRQF_ONESHOT,
+ client->name, ft6236);
+ if (error) {
+ dev_err(dev, "request irq %d failed: %d\n", client->irq, error);
+ return error;
+ }
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(dev, "failed to register input device: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ft6236_of_match[] = {
+ { .compatible = "focaltech,ft6236", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ft6236_of_match);
+#endif
+
+static const struct i2c_device_id ft6236_id[] = {
+ { "ft6236", },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ft6236_id);
+
+static struct i2c_driver ft6236_driver = {
+ .driver = {
+ .name = "ft6236",
+ .of_match_table = of_match_ptr(ft6236_of_match),
+ },
+ .probe = ft6236_probe,
+ .id_table = ft6236_id,
+};
+module_i2c_driver(ft6236_driver);
+
+MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
+MODULE_AUTHOR("Noralf Trønnes <noralf@tronnes.org>");
+MODULE_DESCRIPTION("FocalTech FT6236 TouchScreen driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index 24d704cd9f88..7fbb3b0c8571 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -139,14 +139,14 @@ static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
tsc_readl(tsc, LPC32XX_TSC_CON) &
~LPC32XX_TSC_ADCCON_AUTO_EN);
- clk_disable(tsc->clk);
+ clk_disable_unprepare(tsc->clk);
}
static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
{
u32 tmp;
- clk_enable(tsc->clk);
+ clk_prepare_enable(tsc->clk);
tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 91621725bfb5..4b961ad9f0b5 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -377,8 +377,6 @@ static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
goto unlock;
}
}
-
- enable_irq_wake(client->irq);
} else if (input->users) {
ret = pixcir_stop(ts);
}
@@ -399,7 +397,6 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
mutex_lock(&input->mutex);
if (device_may_wakeup(&client->dev)) {
- disable_irq_wake(client->irq);
if (!input->users) {
ret = pixcir_stop(ts);
@@ -564,14 +561,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return error;
i2c_set_clientdata(client, tsdata);
- device_init_wakeup(&client->dev, 1);
-
- return 0;
-}
-
-static int pixcir_i2c_ts_remove(struct i2c_client *client)
-{
- device_init_wakeup(&client->dev, 0);
return 0;
}
@@ -609,7 +598,6 @@ static struct i2c_driver pixcir_i2c_ts_driver = {
.of_match_table = of_match_ptr(pixcir_of_match),
},
.probe = pixcir_i2c_ts_probe,
- .remove = pixcir_i2c_ts_remove,
.id_table = pixcir_i2c_ts_id,
};
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
new file mode 100644
index 000000000000..ba6024f93469
--- /dev/null
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -0,0 +1,1218 @@
+/*
+ * ROHM BU21023/24 Dual touch support resistive touch screen driver
+ * Copyright (C) 2012 ROHM CO.,LTD.
+ *
+ * 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/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define BU21023_NAME "bu21023_ts"
+#define BU21023_FIRMWARE_NAME "bu21023.bin"
+
+#define MAX_CONTACTS 2
+
+#define AXIS_ADJUST 4
+#define AXIS_OFFSET 8
+
+#define FIRMWARE_BLOCK_SIZE 32U
+#define FIRMWARE_RETRY_MAX 4
+
+#define SAMPLING_DELAY 12 /* msec */
+
+#define CALIBRATION_RETRY_MAX 6
+
+#define ROHM_TS_ABS_X_MIN 40
+#define ROHM_TS_ABS_X_MAX 990
+#define ROHM_TS_ABS_Y_MIN 160
+#define ROHM_TS_ABS_Y_MAX 920
+#define ROHM_TS_DISPLACEMENT_MAX 0 /* zero for infinite */
+
+/*
+ * BU21023GUL/BU21023MUV/BU21024FV-M registers map
+ */
+#define VADOUT_YP_H 0x00
+#define VADOUT_YP_L 0x01
+#define VADOUT_XP_H 0x02
+#define VADOUT_XP_L 0x03
+#define VADOUT_YN_H 0x04
+#define VADOUT_YN_L 0x05
+#define VADOUT_XN_H 0x06
+#define VADOUT_XN_L 0x07
+
+#define PRM1_X_H 0x08
+#define PRM1_X_L 0x09
+#define PRM1_Y_H 0x0a
+#define PRM1_Y_L 0x0b
+#define PRM2_X_H 0x0c
+#define PRM2_X_L 0x0d
+#define PRM2_Y_H 0x0e
+#define PRM2_Y_L 0x0f
+
+#define MLT_PRM_MONI_X 0x10
+#define MLT_PRM_MONI_Y 0x11
+
+#define DEBUG_MONI_1 0x12
+#define DEBUG_MONI_2 0x13
+
+#define VADOUT_ZX_H 0x14
+#define VADOUT_ZX_L 0x15
+#define VADOUT_ZY_H 0x16
+#define VADOUT_ZY_L 0x17
+
+#define Z_PARAM_H 0x18
+#define Z_PARAM_L 0x19
+
+/*
+ * Value for VADOUT_*_L
+ */
+#define VADOUT_L_MASK 0x01
+
+/*
+ * Value for PRM*_*_L
+ */
+#define PRM_L_MASK 0x01
+
+#define POS_X1_H 0x20
+#define POS_X1_L 0x21
+#define POS_Y1_H 0x22
+#define POS_Y1_L 0x23
+#define POS_X2_H 0x24
+#define POS_X2_L 0x25
+#define POS_Y2_H 0x26
+#define POS_Y2_L 0x27
+
+/*
+ * Value for POS_*_L
+ */
+#define POS_L_MASK 0x01
+
+#define TOUCH 0x28
+#define TOUCH_DETECT 0x01
+
+#define TOUCH_GESTURE 0x29
+#define SINGLE_TOUCH 0x01
+#define DUAL_TOUCH 0x03
+#define TOUCH_MASK 0x03
+#define CALIBRATION_REQUEST 0x04
+#define CALIBRATION_STATUS 0x08
+#define CALIBRATION_MASK 0x0c
+#define GESTURE_SPREAD 0x10
+#define GESTURE_PINCH 0x20
+#define GESTURE_ROTATE_R 0x40
+#define GESTURE_ROTATE_L 0x80
+
+#define INT_STATUS 0x2a
+#define INT_MASK 0x3d
+#define INT_CLEAR 0x3e
+
+/*
+ * Values for INT_*
+ */
+#define COORD_UPDATE 0x01
+#define CALIBRATION_DONE 0x02
+#define SLEEP_IN 0x04
+#define SLEEP_OUT 0x08
+#define PROGRAM_LOAD_DONE 0x10
+#define ERROR 0x80
+#define INT_ALL 0x9f
+
+#define ERR_STATUS 0x2b
+#define ERR_MASK 0x3f
+
+/*
+ * Values for ERR_*
+ */
+#define ADC_TIMEOUT 0x01
+#define CPU_TIMEOUT 0x02
+#define CALIBRATION_ERR 0x04
+#define PROGRAM_LOAD_ERR 0x10
+
+#define COMMON_SETUP1 0x30
+#define PROGRAM_LOAD_HOST 0x02
+#define PROGRAM_LOAD_EEPROM 0x03
+#define CENSOR_4PORT 0x04
+#define CENSOR_8PORT 0x00 /* Not supported by BU21023 */
+#define CALIBRATION_TYPE_DEFAULT 0x08
+#define CALIBRATION_TYPE_SPECIAL 0x00
+#define INT_ACTIVE_HIGH 0x10
+#define INT_ACTIVE_LOW 0x00
+#define AUTO_CALIBRATION 0x40
+#define MANUAL_CALIBRATION 0x00
+#define COMMON_SETUP1_DEFAULT 0x4e
+
+#define COMMON_SETUP2 0x31
+#define MAF_NONE 0x00
+#define MAF_1SAMPLE 0x01
+#define MAF_3SAMPLES 0x02
+#define MAF_5SAMPLES 0x03
+#define INV_Y 0x04
+#define INV_X 0x08
+#define SWAP_XY 0x10
+
+#define COMMON_SETUP3 0x32
+#define EN_SLEEP 0x01
+#define EN_MULTI 0x02
+#define EN_GESTURE 0x04
+#define EN_INTVL 0x08
+#define SEL_STEP 0x10
+#define SEL_MULTI 0x20
+#define SEL_TBL_DEFAULT 0x40
+
+#define INTERVAL_TIME 0x33
+#define INTERVAL_TIME_DEFAULT 0x10
+
+#define STEP_X 0x34
+#define STEP_X_DEFAULT 0x41
+
+#define STEP_Y 0x35
+#define STEP_Y_DEFAULT 0x8d
+
+#define OFFSET_X 0x38
+#define OFFSET_X_DEFAULT 0x0c
+
+#define OFFSET_Y 0x39
+#define OFFSET_Y_DEFAULT 0x0c
+
+#define THRESHOLD_TOUCH 0x3a
+#define THRESHOLD_TOUCH_DEFAULT 0xa0
+
+#define THRESHOLD_GESTURE 0x3b
+#define THRESHOLD_GESTURE_DEFAULT 0x17
+
+#define SYSTEM 0x40
+#define ANALOG_POWER_ON 0x01
+#define ANALOG_POWER_OFF 0x00
+#define CPU_POWER_ON 0x02
+#define CPU_POWER_OFF 0x00
+
+#define FORCE_CALIBRATION 0x42
+#define FORCE_CALIBRATION_ON 0x01
+#define FORCE_CALIBRATION_OFF 0x00
+
+#define CPU_FREQ 0x50 /* 10 / (reg + 1) MHz */
+#define CPU_FREQ_10MHZ 0x00
+#define CPU_FREQ_5MHZ 0x01
+#define CPU_FREQ_1MHZ 0x09
+
+#define EEPROM_ADDR 0x51
+
+#define CALIBRATION_ADJUST 0x52
+#define CALIBRATION_ADJUST_DEFAULT 0x00
+
+#define THRESHOLD_SLEEP_IN 0x53
+
+#define EVR_XY 0x56
+#define EVR_XY_DEFAULT 0x10
+
+#define PRM_SWOFF_TIME 0x57
+#define PRM_SWOFF_TIME_DEFAULT 0x04
+
+#define PROGRAM_VERSION 0x5f
+
+#define ADC_CTRL 0x60
+#define ADC_DIV_MASK 0x1f /* The minimum value is 4 */
+#define ADC_DIV_DEFAULT 0x08
+
+#define ADC_WAIT 0x61
+#define ADC_WAIT_DEFAULT 0x0a
+
+#define SWCONT 0x62
+#define SWCONT_DEFAULT 0x0f
+
+#define EVR_X 0x63
+#define EVR_X_DEFAULT 0x86
+
+#define EVR_Y 0x64
+#define EVR_Y_DEFAULT 0x64
+
+#define TEST1 0x65
+#define DUALTOUCH_STABILIZE_ON 0x01
+#define DUALTOUCH_STABILIZE_OFF 0x00
+#define DUALTOUCH_REG_ON 0x20
+#define DUALTOUCH_REG_OFF 0x00
+
+#define CALIBRATION_REG1 0x68
+#define CALIBRATION_REG1_DEFAULT 0xd9
+
+#define CALIBRATION_REG2 0x69
+#define CALIBRATION_REG2_DEFAULT 0x36
+
+#define CALIBRATION_REG3 0x6a
+#define CALIBRATION_REG3_DEFAULT 0x32
+
+#define EX_ADDR_H 0x70
+#define EX_ADDR_L 0x71
+#define EX_WDAT 0x72
+#define EX_RDAT 0x73
+#define EX_CHK_SUM1 0x74
+#define EX_CHK_SUM2 0x75
+#define EX_CHK_SUM3 0x76
+
+struct rohm_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+
+ bool initialized;
+
+ unsigned int contact_count[MAX_CONTACTS + 1];
+ int finger_count;
+
+ u8 setup2;
+};
+
+/*
+ * rohm_i2c_burst_read - execute combined I2C message for ROHM BU21023/24
+ * @client: Handle to ROHM BU21023/24
+ * @start: Where to start read address from ROHM BU21023/24
+ * @buf: Where to store read data from ROHM BU21023/24
+ * @len: How many bytes to read
+ *
+ * Returns negative errno, else zero on success.
+ *
+ * Note
+ * In BU21023/24 burst read, stop condition is needed after "address write".
+ * Therefore, transmission is performed in 2 steps.
+ */
+static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
+ size_t len)
+{
+ struct i2c_adapter *adap = client->adapter;
+ struct i2c_msg msg[2];
+ int i, ret = 0;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &start;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = buf;
+
+ i2c_lock_adapter(adap);
+
+ for (i = 0; i < 2; i++) {
+ if (__i2c_transfer(adap, &msg[i], 1) < 0) {
+ ret = -EIO;
+ break;
+ }
+ }
+
+ i2c_unlock_adapter(adap);
+
+ return ret;
+}
+
+static int rohm_ts_manual_calibration(struct rohm_ts_data *ts)
+{
+ struct i2c_client *client = ts->client;
+ struct device *dev = &client->dev;
+ u8 buf[33]; /* for PRM1_X_H(0x08)-TOUCH(0x28) */
+
+ int retry;
+ bool success = false;
+ bool first_time = true;
+ bool calibration_done;
+
+ u8 reg1, reg2, reg3;
+ s32 reg1_orig, reg2_orig, reg3_orig;
+ s32 val;
+
+ int calib_x = 0, calib_y = 0;
+ int reg_x, reg_y;
+ int err_x, err_y;
+
+ int error, error2;
+ int i;
+
+ reg1_orig = i2c_smbus_read_byte_data(client, CALIBRATION_REG1);
+ if (reg1_orig < 0)
+ return reg1_orig;
+
+ reg2_orig = i2c_smbus_read_byte_data(client, CALIBRATION_REG2);
+ if (reg2_orig < 0)
+ return reg2_orig;
+
+ reg3_orig = i2c_smbus_read_byte_data(client, CALIBRATION_REG3);
+ if (reg3_orig < 0)
+ return reg3_orig;
+
+ error = i2c_smbus_write_byte_data(client, INT_MASK,
+ COORD_UPDATE | SLEEP_IN | SLEEP_OUT |
+ PROGRAM_LOAD_DONE);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client, TEST1,
+ DUALTOUCH_STABILIZE_ON);
+ if (error)
+ goto out;
+
+ for (retry = 0; retry < CALIBRATION_RETRY_MAX; retry++) {
+ /* wait 2 sampling for update */
+ mdelay(2 * SAMPLING_DELAY);
+
+#define READ_CALIB_BUF(reg) buf[((reg) - PRM1_X_H)]
+
+ error = rohm_i2c_burst_read(client, PRM1_X_H, buf, sizeof(buf));
+ if (error)
+ goto out;
+
+ if (READ_CALIB_BUF(TOUCH) & TOUCH_DETECT)
+ continue;
+
+ if (first_time) {
+ /* generate calibration parameter */
+ calib_x = ((int)READ_CALIB_BUF(PRM1_X_H) << 2 |
+ READ_CALIB_BUF(PRM1_X_L)) - AXIS_OFFSET;
+ calib_y = ((int)READ_CALIB_BUF(PRM1_Y_H) << 2 |
+ READ_CALIB_BUF(PRM1_Y_L)) - AXIS_OFFSET;
+
+ error = i2c_smbus_write_byte_data(client, TEST1,
+ DUALTOUCH_STABILIZE_ON | DUALTOUCH_REG_ON);
+ if (error)
+ goto out;
+
+ first_time = false;
+ } else {
+ /* generate adjustment parameter */
+ err_x = (int)READ_CALIB_BUF(PRM1_X_H) << 2 |
+ READ_CALIB_BUF(PRM1_X_L);
+ err_y = (int)READ_CALIB_BUF(PRM1_Y_H) << 2 |
+ READ_CALIB_BUF(PRM1_Y_L);
+
+ /* X axis ajust */
+ if (err_x <= 4)
+ calib_x -= AXIS_ADJUST;
+ else if (err_x >= 60)
+ calib_x += AXIS_ADJUST;
+
+ /* Y axis ajust */
+ if (err_y <= 4)
+ calib_y -= AXIS_ADJUST;
+ else if (err_y >= 60)
+ calib_y += AXIS_ADJUST;
+ }
+
+ /* generate calibration setting value */
+ reg_x = calib_x + ((calib_x & 0x200) << 1);
+ reg_y = calib_y + ((calib_y & 0x200) << 1);
+
+ /* convert for register format */
+ reg1 = reg_x >> 3;
+ reg2 = (reg_y & 0x7) << 4 | (reg_x & 0x7);
+ reg3 = reg_y >> 3;
+
+ error = i2c_smbus_write_byte_data(client,
+ CALIBRATION_REG1, reg1);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client,
+ CALIBRATION_REG2, reg2);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client,
+ CALIBRATION_REG3, reg3);
+ if (error)
+ goto out;
+
+ /*
+ * force calibration sequcence
+ */
+ error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION,
+ FORCE_CALIBRATION_OFF);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION,
+ FORCE_CALIBRATION_ON);
+ if (error)
+ goto out;
+
+ /* clear all interrupts */
+ error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff);
+ if (error)
+ goto out;
+
+ /*
+ * Wait for the status change of calibration, max 10 sampling
+ */
+ calibration_done = false;
+
+ for (i = 0; i < 10; i++) {
+ mdelay(SAMPLING_DELAY);
+
+ val = i2c_smbus_read_byte_data(client, TOUCH_GESTURE);
+ if (!(val & CALIBRATION_MASK)) {
+ calibration_done = true;
+ break;
+ } else if (val < 0) {
+ error = val;
+ goto out;
+ }
+ }
+
+ if (calibration_done) {
+ val = i2c_smbus_read_byte_data(client, INT_STATUS);
+ if (val == CALIBRATION_DONE) {
+ success = true;
+ break;
+ } else if (val < 0) {
+ error = val;
+ goto out;
+ }
+ } else {
+ dev_warn(dev, "calibration timeout\n");
+ }
+ }
+
+ if (!success) {
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_REG1,
+ reg1_orig);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_REG2,
+ reg2_orig);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_REG3,
+ reg3_orig);
+ if (error)
+ goto out;
+
+ /* calibration data enable */
+ error = i2c_smbus_write_byte_data(client, TEST1,
+ DUALTOUCH_STABILIZE_ON |
+ DUALTOUCH_REG_ON);
+ if (error)
+ goto out;
+
+ /* wait 10 sampling */
+ mdelay(10 * SAMPLING_DELAY);
+
+ error = -EBUSY;
+ }
+
+out:
+ error2 = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL);
+ if (!error2)
+ /* Clear all interrupts */
+ error2 = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff);
+
+ return error ? error : error2;
+}
+
+static const unsigned int untouch_threshold[3] = { 0, 1, 5 };
+static const unsigned int single_touch_threshold[3] = { 0, 0, 4 };
+static const unsigned int dual_touch_threshold[3] = { 10, 8, 0 };
+
+static irqreturn_t rohm_ts_soft_irq(int irq, void *dev_id)
+{
+ struct rohm_ts_data *ts = dev_id;
+ struct i2c_client *client = ts->client;
+ struct input_dev *input_dev = ts->input;
+ struct device *dev = &client->dev;
+
+ u8 buf[10]; /* for POS_X1_H(0x20)-TOUCH_GESTURE(0x29) */
+
+ struct input_mt_pos pos[MAX_CONTACTS];
+ int slots[MAX_CONTACTS];
+ u8 touch_flags;
+ unsigned int threshold;
+ int finger_count = -1;
+ int prev_finger_count = ts->finger_count;
+ int count;
+ int error;
+ int i;
+
+ error = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL);
+ if (error)
+ return IRQ_HANDLED;
+
+ /* Clear all interrupts */
+ error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff);
+ if (error)
+ return IRQ_HANDLED;
+
+#define READ_POS_BUF(reg) buf[((reg) - POS_X1_H)]
+
+ error = rohm_i2c_burst_read(client, POS_X1_H, buf, sizeof(buf));
+ if (error)
+ return IRQ_HANDLED;
+
+ touch_flags = READ_POS_BUF(TOUCH_GESTURE) & TOUCH_MASK;
+ if (touch_flags) {
+ /* generate coordinates */
+ pos[0].x = ((s16)READ_POS_BUF(POS_X1_H) << 2) |
+ READ_POS_BUF(POS_X1_L);
+ pos[0].y = ((s16)READ_POS_BUF(POS_Y1_H) << 2) |
+ READ_POS_BUF(POS_Y1_L);
+ pos[1].x = ((s16)READ_POS_BUF(POS_X2_H) << 2) |
+ READ_POS_BUF(POS_X2_L);
+ pos[1].y = ((s16)READ_POS_BUF(POS_Y2_H) << 2) |
+ READ_POS_BUF(POS_Y2_L);
+ }
+
+ switch (touch_flags) {
+ case 0:
+ threshold = untouch_threshold[prev_finger_count];
+ if (++ts->contact_count[0] >= threshold)
+ finger_count = 0;
+ break;
+
+ case SINGLE_TOUCH:
+ threshold = single_touch_threshold[prev_finger_count];
+ if (++ts->contact_count[1] >= threshold)
+ finger_count = 1;
+
+ if (finger_count == 1) {
+ if (pos[1].x != 0 && pos[1].y != 0) {
+ pos[0].x = pos[1].x;
+ pos[0].y = pos[1].y;
+ pos[1].x = 0;
+ pos[1].y = 0;
+ }
+ }
+ break;
+
+ case DUAL_TOUCH:
+ threshold = dual_touch_threshold[prev_finger_count];
+ if (++ts->contact_count[2] >= threshold)
+ finger_count = 2;
+ break;
+
+ default:
+ dev_dbg(dev,
+ "Three or more touches are not supported\n");
+ return IRQ_HANDLED;
+ }
+
+ if (finger_count >= 0) {
+ if (prev_finger_count != finger_count) {
+ count = ts->contact_count[finger_count];
+ memset(ts->contact_count, 0, sizeof(ts->contact_count));
+ ts->contact_count[finger_count] = count;
+ }
+
+ input_mt_assign_slots(input_dev, slots, pos,
+ finger_count, ROHM_TS_DISPLACEMENT_MAX);
+
+ for (i = 0; i < finger_count; i++) {
+ input_mt_slot(input_dev, slots[i]);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, true);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_X, pos[i].x);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_Y, pos[i].y);
+ }
+
+ input_mt_sync_frame(input_dev);
+ input_mt_report_pointer_emulation(input_dev, true);
+ input_sync(input_dev);
+
+ ts->finger_count = finger_count;
+ }
+
+ if (READ_POS_BUF(TOUCH_GESTURE) & CALIBRATION_REQUEST) {
+ error = rohm_ts_manual_calibration(ts);
+ if (error)
+ dev_warn(dev, "manual calibration failed: %d\n",
+ error);
+ }
+
+ i2c_smbus_write_byte_data(client, INT_MASK,
+ CALIBRATION_DONE | SLEEP_OUT | SLEEP_IN |
+ PROGRAM_LOAD_DONE);
+
+ return IRQ_HANDLED;
+}
+
+static int rohm_ts_load_firmware(struct i2c_client *client,
+ const char *firmware_name)
+{
+ struct device *dev = &client->dev;
+ const struct firmware *fw;
+ s32 status;
+ unsigned int offset, len, xfer_len;
+ unsigned int retry = 0;
+ int error, error2;
+
+ error = request_firmware(&fw, firmware_name, dev);
+ if (error) {
+ dev_err(dev, "unable to retrieve firmware %s: %d\n",
+ firmware_name, error);
+ return error;
+ }
+
+ error = i2c_smbus_write_byte_data(client, INT_MASK,
+ COORD_UPDATE | CALIBRATION_DONE |
+ SLEEP_IN | SLEEP_OUT);
+ if (error)
+ goto out;
+
+ do {
+ if (retry) {
+ dev_warn(dev, "retrying firmware load\n");
+
+ /* settings for retry */
+ error = i2c_smbus_write_byte_data(client, EX_WDAT, 0);
+ if (error)
+ goto out;
+ }
+
+ error = i2c_smbus_write_byte_data(client, EX_ADDR_H, 0);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client, EX_ADDR_L, 0);
+ if (error)
+ goto out;
+
+ error = i2c_smbus_write_byte_data(client, COMMON_SETUP1,
+ COMMON_SETUP1_DEFAULT);
+ if (error)
+ goto out;
+
+ /* firmware load to the device */
+ offset = 0;
+ len = fw->size;
+
+ while (len) {
+ xfer_len = min(FIRMWARE_BLOCK_SIZE, len);
+
+ error = i2c_smbus_write_i2c_block_data(client, EX_WDAT,
+ xfer_len, &fw->data[offset]);
+ if (error)
+ goto out;
+
+ len -= xfer_len;
+ offset += xfer_len;
+ }
+
+ /* check firmware load result */
+ status = i2c_smbus_read_byte_data(client, INT_STATUS);
+ if (status < 0) {
+ error = status;
+ goto out;
+ }
+
+ /* clear all interrupts */
+ error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff);
+ if (error)
+ goto out;
+
+ if (status == PROGRAM_LOAD_DONE)
+ break;
+
+ error = -EIO;
+ } while (++retry >= FIRMWARE_RETRY_MAX);
+
+out:
+ error2 = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL);
+
+ release_firmware(fw);
+
+ return error ? error : error2;
+}
+
+static ssize_t swap_xy_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rohm_ts_data *ts = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", !!(ts->setup2 & SWAP_XY));
+}
+
+static ssize_t swap_xy_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rohm_ts_data *ts = i2c_get_clientdata(client);
+ unsigned int val;
+ int error;
+
+ error = kstrtouint(buf, 0, &val);
+ if (error)
+ return error;
+
+ error = mutex_lock_interruptible(&ts->input->mutex);
+ if (error)
+ return error;
+
+ if (val)
+ ts->setup2 |= SWAP_XY;
+ else
+ ts->setup2 &= ~SWAP_XY;
+
+ if (ts->initialized)
+ error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2,
+ ts->setup2);
+
+ mutex_unlock(&ts->input->mutex);
+
+ return error ? error : count;
+}
+
+static ssize_t inv_x_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rohm_ts_data *ts = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", !!(ts->setup2 & INV_X));
+}
+
+static ssize_t inv_x_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rohm_ts_data *ts = i2c_get_clientdata(client);
+ unsigned int val;
+ int error;
+
+ error = kstrtouint(buf, 0, &val);
+ if (error)
+ return error;
+
+ error = mutex_lock_interruptible(&ts->input->mutex);
+ if (error)
+ return error;
+
+ if (val)
+ ts->setup2 |= INV_X;
+ else
+ ts->setup2 &= ~INV_X;
+
+ if (ts->initialized)
+ error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2,
+ ts->setup2);
+
+ mutex_unlock(&ts->input->mutex);
+
+ return error ? error : count;
+}
+
+static ssize_t inv_y_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rohm_ts_data *ts = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", !!(ts->setup2 & INV_Y));
+}
+
+static ssize_t inv_y_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rohm_ts_data *ts = i2c_get_clientdata(client);
+ unsigned int val;
+ int error;
+
+ error = kstrtouint(buf, 0, &val);
+ if (error)
+ return error;
+
+ error = mutex_lock_interruptible(&ts->input->mutex);
+ if (error)
+ return error;
+
+ if (val)
+ ts->setup2 |= INV_Y;
+ else
+ ts->setup2 &= ~INV_Y;
+
+ if (ts->initialized)
+ error = i2c_smbus_write_byte_data(client, COMMON_SETUP2,
+ ts->setup2);
+
+ mutex_unlock(&ts->input->mutex);
+
+ return error ? error : count;
+}
+
+static DEVICE_ATTR_RW(swap_xy);
+static DEVICE_ATTR_RW(inv_x);
+static DEVICE_ATTR_RW(inv_y);
+
+static struct attribute *rohm_ts_attrs[] = {
+ &dev_attr_swap_xy.attr,
+ &dev_attr_inv_x.attr,
+ &dev_attr_inv_y.attr,
+ NULL,
+};
+
+static const struct attribute_group rohm_ts_attr_group = {
+ .attrs = rohm_ts_attrs,
+};
+
+static int rohm_ts_device_init(struct i2c_client *client, u8 setup2)
+{
+ struct device *dev = &client->dev;
+ int error;
+
+ disable_irq(client->irq);
+
+ /*
+ * Wait 200usec for reset
+ */
+ udelay(200);
+
+ /* Release analog reset */
+ error = i2c_smbus_write_byte_data(client, SYSTEM,
+ ANALOG_POWER_ON | CPU_POWER_OFF);
+ if (error)
+ return error;
+
+ /* Waiting for the analog warm-up, max. 200usec */
+ udelay(200);
+
+ /* clear all interrupts */
+ error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, EX_WDAT, 0);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, COMMON_SETUP1, 0);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, COMMON_SETUP2, setup2);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, COMMON_SETUP3,
+ SEL_TBL_DEFAULT | EN_MULTI);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, THRESHOLD_GESTURE,
+ THRESHOLD_GESTURE_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, INTERVAL_TIME,
+ INTERVAL_TIME_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, CPU_FREQ, CPU_FREQ_10MHZ);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, PRM_SWOFF_TIME,
+ PRM_SWOFF_TIME_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, ADC_CTRL, ADC_DIV_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, ADC_WAIT, ADC_WAIT_DEFAULT);
+ if (error)
+ return error;
+
+ /*
+ * Panel setup, these values change with the panel.
+ */
+ error = i2c_smbus_write_byte_data(client, STEP_X, STEP_X_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, STEP_Y, STEP_Y_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, OFFSET_X, OFFSET_X_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, OFFSET_Y, OFFSET_Y_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, THRESHOLD_TOUCH,
+ THRESHOLD_TOUCH_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, EVR_XY, EVR_XY_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, EVR_X, EVR_X_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, EVR_Y, EVR_Y_DEFAULT);
+ if (error)
+ return error;
+
+ /* Fixed value settings */
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_ADJUST,
+ CALIBRATION_ADJUST_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, SWCONT, SWCONT_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, TEST1,
+ DUALTOUCH_STABILIZE_ON |
+ DUALTOUCH_REG_ON);
+ if (error)
+ return error;
+
+ error = rohm_ts_load_firmware(client, BU21023_FIRMWARE_NAME);
+ if (error) {
+ dev_err(dev, "failed to load firmware: %d\n", error);
+ return error;
+ }
+
+ /*
+ * Manual calibration results are not changed in same environment.
+ * If the force calibration is performed,
+ * the controller will not require calibration request interrupt
+ * when the typical values are set to the calibration registers.
+ */
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_REG1,
+ CALIBRATION_REG1_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_REG2,
+ CALIBRATION_REG2_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, CALIBRATION_REG3,
+ CALIBRATION_REG3_DEFAULT);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION,
+ FORCE_CALIBRATION_OFF);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION,
+ FORCE_CALIBRATION_ON);
+ if (error)
+ return error;
+
+ /* Clear all interrupts */
+ error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff);
+ if (error)
+ return error;
+
+ /* Enable coordinates update interrupt */
+ error = i2c_smbus_write_byte_data(client, INT_MASK,
+ CALIBRATION_DONE | SLEEP_OUT |
+ SLEEP_IN | PROGRAM_LOAD_DONE);
+ if (error)
+ return error;
+
+ error = i2c_smbus_write_byte_data(client, ERR_MASK,
+ PROGRAM_LOAD_ERR | CPU_TIMEOUT |
+ ADC_TIMEOUT);
+ if (error)
+ return error;
+
+ /* controller CPU power on */
+ error = i2c_smbus_write_byte_data(client, SYSTEM,
+ ANALOG_POWER_ON | CPU_POWER_ON);
+
+ enable_irq(client->irq);
+
+ return error;
+}
+
+static int rohm_ts_power_off(struct i2c_client *client)
+{
+ int error;
+
+ error = i2c_smbus_write_byte_data(client, SYSTEM,
+ ANALOG_POWER_ON | CPU_POWER_OFF);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to power off device CPU: %d\n", error);
+ return error;
+ }
+
+ error = i2c_smbus_write_byte_data(client, SYSTEM,
+ ANALOG_POWER_OFF | CPU_POWER_OFF);
+ if (error)
+ dev_err(&client->dev,
+ "failed to power off the device: %d\n", error);
+
+ return error;
+}
+
+static int rohm_ts_open(struct input_dev *input_dev)
+{
+ struct rohm_ts_data *ts = input_get_drvdata(input_dev);
+ struct i2c_client *client = ts->client;
+ int error;
+
+ if (!ts->initialized) {
+ error = rohm_ts_device_init(client, ts->setup2);
+ if (error) {
+ dev_err(&client->dev,
+ "device initialization failed: %d\n", error);
+ return error;
+ }
+
+ ts->initialized = true;
+ }
+
+ return 0;
+}
+
+static void rohm_ts_close(struct input_dev *input_dev)
+{
+ struct rohm_ts_data *ts = input_get_drvdata(input_dev);
+
+ rohm_ts_power_off(ts->client);
+
+ ts->initialized = false;
+}
+
+static void rohm_ts_remove_sysfs_group(void *_dev)
+{
+ struct device *dev = _dev;
+
+ sysfs_remove_group(&dev->kobj, &rohm_ts_attr_group);
+}
+
+static int rohm_bu21023_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct rohm_ts_data *ts;
+ struct input_dev *input;
+ int error;
+
+ if (!client->irq) {
+ dev_err(dev, "IRQ is not assigned\n");
+ return -EINVAL;
+ }
+
+ if (!client->adapter->algo->master_xfer) {
+ dev_err(dev, "I2C level transfers not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* Turn off CPU just in case */
+ error = rohm_ts_power_off(client);
+ if (error)
+ return error;
+
+ ts = devm_kzalloc(dev, sizeof(struct rohm_ts_data), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->client = client;
+ ts->setup2 = MAF_1SAMPLE;
+ i2c_set_clientdata(client, ts);
+
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return -ENOMEM;
+
+ input->name = BU21023_NAME;
+ input->id.bustype = BUS_I2C;
+ input->open = rohm_ts_open;
+ input->close = rohm_ts_close;
+
+ ts->input = input;
+ input_set_drvdata(input, ts);
+
+ input_set_abs_params(input, ABS_MT_POSITION_X,
+ ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y,
+ ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
+
+ error = input_mt_init_slots(input, MAX_CONTACTS,
+ INPUT_MT_DIRECT | INPUT_MT_TRACK |
+ INPUT_MT_DROP_UNUSED);
+ if (error) {
+ dev_err(dev, "failed to multi touch slots initialization\n");
+ return error;
+ }
+
+ error = devm_request_threaded_irq(dev, client->irq,
+ NULL, rohm_ts_soft_irq,
+ IRQF_ONESHOT, client->name, ts);
+ if (error) {
+ dev_err(dev, "failed to request IRQ: %d\n", error);
+ return error;
+ }
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(dev, "failed to register input device: %d\n", error);
+ return error;
+ }
+
+ error = sysfs_create_group(&dev->kobj, &rohm_ts_attr_group);
+ if (error) {
+ dev_err(dev, "failed to create sysfs group: %d\n", error);
+ return error;
+ }
+
+ error = devm_add_action(dev, rohm_ts_remove_sysfs_group, dev);
+ if (error) {
+ rohm_ts_remove_sysfs_group(dev);
+ dev_err(&client->dev,
+ "Failed to add sysfs cleanup action: %d\n",
+ error);
+ return error;
+ }
+
+ return error;
+}
+
+static const struct i2c_device_id rohm_bu21023_i2c_id[] = {
+ { BU21023_NAME, 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id);
+
+static struct i2c_driver rohm_bu21023_i2c_driver = {
+ .driver = {
+ .name = BU21023_NAME,
+ },
+ .probe = rohm_bu21023_i2c_probe,
+ .id_table = rohm_bu21023_i2c_id,
+};
+module_i2c_driver(rohm_bu21023_i2c_driver);
+
+MODULE_DESCRIPTION("ROHM BU21023/24 Touchscreen driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("ROHM Co., Ltd.");
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index 3f117637e832..d214f22ed305 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -38,6 +38,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
/* read 512 bytes from endpoint 0x86 -> get header + blobs */
@@ -163,7 +164,7 @@ struct sur40_state {
};
struct sur40_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -420,7 +421,7 @@ static void sur40_process_video(struct sur40_state *sur40)
dev_dbg(sur40->dev, "header acquired\n");
- sgt = vb2_dma_sg_plane_desc(&new_buf->vb, 0);
+ sgt = vb2_dma_sg_plane_desc(&new_buf->vb.vb2_buf, 0);
result = usb_sg_init(&sgr, sur40->usbdev,
usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
@@ -443,15 +444,15 @@ static void sur40_process_video(struct sur40_state *sur40)
goto err_poll;
/* mark as finished */
- v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
- new_buf->vb.v4l2_buf.sequence = sur40->sequence++;
- new_buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
- vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&new_buf->vb.timestamp);
+ new_buf->vb.sequence = sur40->sequence++;
+ new_buf->vb.field = V4L2_FIELD_NONE;
+ vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
dev_dbg(sur40->dev, "buffer marked done\n");
return;
err_poll:
- vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
/* Initialize input device parameters. */
@@ -643,10 +644,11 @@ static void sur40_disconnect(struct usb_interface *interface)
* minimum number: many DMA engines need a minimum of 2 buffers in the
* queue and you need to have another available for userspace processing.
*/
-static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int sur40_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct sur40_state *sur40 = vb2_get_drv_priv(q);
if (q->num_buffers + *nbuffers < 3)
@@ -701,7 +703,7 @@ static void return_all_buffers(struct sur40_state *sur40,
spin_lock(&sur40->qlock);
list_for_each_entry_safe(buf, node, &sur40->buf_list, list) {
- vb2_buffer_done(&buf->vb, state);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
list_del(&buf->list);
}
spin_unlock(&sur40->qlock);
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
index 4ffd829d1990..a340bfccdfb6 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -50,14 +50,7 @@ struct tps6507x_ts {
static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
{
- int err;
-
- err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
-
- if (err)
- return err;
-
- return 0;
+ return tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
}
static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data)
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
new file mode 100644
index 000000000000..7295c198aa08
--- /dev/null
+++ b/drivers/input/touchscreen/tsc2004.c
@@ -0,0 +1,83 @@
+/*
+ * TSC2004 touchscreen driver
+ *
+ * Copyright (C) 2015 QWERTY Embedded Design
+ * Copyright (C) 2015 EMAC 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.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include "tsc200x-core.h"
+
+static int tsc2004_cmd(struct device *dev, u8 cmd)
+{
+ u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
+ s32 data;
+ struct i2c_client *i2c = to_i2c_client(dev);
+
+ data = i2c_smbus_write_byte(i2c, tx);
+ if (data < 0) {
+ dev_err(dev, "%s: failed, command: %x i2c error: %d\n",
+ __func__, cmd, data);
+ return data;
+ }
+
+ return 0;
+}
+
+static int tsc2004_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+
+{
+ return tsc200x_probe(&i2c->dev, i2c->irq, BUS_I2C,
+ devm_regmap_init_i2c(i2c, &tsc200x_regmap_config),
+ tsc2004_cmd);
+}
+
+static int tsc2004_remove(struct i2c_client *i2c)
+{
+ return tsc200x_remove(&i2c->dev);
+}
+
+static const struct i2c_device_id tsc2004_idtable[] = {
+ { "tsc2004", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tsc2004_idtable);
+
+#ifdef CONFIG_OF
+static const struct of_device_id tsc2004_of_match[] = {
+ { .compatible = "ti,tsc2004" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tsc2004_of_match);
+#endif
+
+static struct i2c_driver tsc2004_driver = {
+ .driver = {
+ .name = "tsc2004",
+ .of_match_table = of_match_ptr(tsc2004_of_match),
+ .pm = &tsc200x_pm_ops,
+ },
+ .id_table = tsc2004_idtable,
+ .probe = tsc2004_probe,
+ .remove = tsc2004_remove,
+};
+module_i2c_driver(tsc2004_driver);
+
+MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
+MODULE_DESCRIPTION("TSC2004 Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index 0f65d02eeb26..b9f593dfd2ef 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -2,9 +2,10 @@
* TSC2005 touchscreen driver
*
* Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2015 QWERTY Embedded Design
+ * Copyright (C) 2015 EMAC Inc.
*
- * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
- * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
+ * Based on original tsc2005.c by Lauri Leukkunen <lauri.leukkunen@nokia.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
@@ -15,192 +16,32 @@
* but WITHOUT 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>
#include <linux/module.h>
#include <linux/input.h>
-#include <linux/input/touchscreen.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/of.h>
#include <linux/spi/spi.h>
-#include <linux/spi/tsc2005.h>
-#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
-#include <linux/gpio/consumer.h>
-
-/*
- * The touchscreen interface operates as follows:
- *
- * 1) Pen is pressed against the touchscreen.
- * 2) TSC2005 performs AD conversion.
- * 3) After the conversion is done TSC2005 drives DAV line down.
- * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
- * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
- * values.
- * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
- * tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
- * 7) When the penup timer expires, there have not been touch or DAV interrupts
- * during the last 40ms which means the pen has been lifted.
- *
- * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
- * after a configurable period (in ms) of activity. If esd_timeout is 0, the
- * watchdog is disabled.
- */
-
-/* control byte 1 */
-#define TSC2005_CMD 0x80
-#define TSC2005_CMD_NORMAL 0x00
-#define TSC2005_CMD_STOP 0x01
-#define TSC2005_CMD_12BIT 0x04
-
-/* control byte 0 */
-#define TSC2005_REG_READ 0x01 /* R/W access */
-#define TSC2005_REG_PND0 0x02 /* Power Not Down Control */
-#define TSC2005_REG_X (0x0 << 3)
-#define TSC2005_REG_Y (0x1 << 3)
-#define TSC2005_REG_Z1 (0x2 << 3)
-#define TSC2005_REG_Z2 (0x3 << 3)
-#define TSC2005_REG_AUX (0x4 << 3)
-#define TSC2005_REG_TEMP1 (0x5 << 3)
-#define TSC2005_REG_TEMP2 (0x6 << 3)
-#define TSC2005_REG_STATUS (0x7 << 3)
-#define TSC2005_REG_AUX_HIGH (0x8 << 3)
-#define TSC2005_REG_AUX_LOW (0x9 << 3)
-#define TSC2005_REG_TEMP_HIGH (0xA << 3)
-#define TSC2005_REG_TEMP_LOW (0xB << 3)
-#define TSC2005_REG_CFR0 (0xC << 3)
-#define TSC2005_REG_CFR1 (0xD << 3)
-#define TSC2005_REG_CFR2 (0xE << 3)
-#define TSC2005_REG_CONV_FUNC (0xF << 3)
-
-/* configuration register 0 */
-#define TSC2005_CFR0_PRECHARGE_276US 0x0040
-#define TSC2005_CFR0_STABTIME_1MS 0x0300
-#define TSC2005_CFR0_CLOCK_1MHZ 0x1000
-#define TSC2005_CFR0_RESOLUTION12 0x2000
-#define TSC2005_CFR0_PENMODE 0x8000
-#define TSC2005_CFR0_INITVALUE (TSC2005_CFR0_STABTIME_1MS | \
- TSC2005_CFR0_CLOCK_1MHZ | \
- TSC2005_CFR0_RESOLUTION12 | \
- TSC2005_CFR0_PRECHARGE_276US | \
- TSC2005_CFR0_PENMODE)
-
-/* bits common to both read and write of configuration register 0 */
-#define TSC2005_CFR0_RW_MASK 0x3fff
-
-/* configuration register 1 */
-#define TSC2005_CFR1_BATCHDELAY_4MS 0x0003
-#define TSC2005_CFR1_INITVALUE TSC2005_CFR1_BATCHDELAY_4MS
-
-/* configuration register 2 */
-#define TSC2005_CFR2_MAVE_Z 0x0004
-#define TSC2005_CFR2_MAVE_Y 0x0008
-#define TSC2005_CFR2_MAVE_X 0x0010
-#define TSC2005_CFR2_AVG_7 0x0800
-#define TSC2005_CFR2_MEDIUM_15 0x3000
-#define TSC2005_CFR2_INITVALUE (TSC2005_CFR2_MAVE_X | \
- TSC2005_CFR2_MAVE_Y | \
- TSC2005_CFR2_MAVE_Z | \
- TSC2005_CFR2_MEDIUM_15 | \
- TSC2005_CFR2_AVG_7)
-
-#define MAX_12BIT 0xfff
-#define TSC2005_DEF_X_FUZZ 4
-#define TSC2005_DEF_Y_FUZZ 8
-#define TSC2005_DEF_P_FUZZ 2
-#define TSC2005_DEF_RESISTOR 280
-
-#define TSC2005_SPI_MAX_SPEED_HZ 10000000
-#define TSC2005_PENUP_TIME_MS 40
-
-static const struct regmap_range tsc2005_writable_ranges[] = {
- regmap_reg_range(TSC2005_REG_AUX_HIGH, TSC2005_REG_CFR2),
-};
-
-static const struct regmap_access_table tsc2005_writable_table = {
- .yes_ranges = tsc2005_writable_ranges,
- .n_yes_ranges = ARRAY_SIZE(tsc2005_writable_ranges),
-};
-
-static struct regmap_config tsc2005_regmap_config = {
- .reg_bits = 8,
- .val_bits = 16,
- .reg_stride = 0x08,
- .max_register = 0x78,
- .read_flag_mask = TSC2005_REG_READ,
- .write_flag_mask = TSC2005_REG_PND0,
- .wr_table = &tsc2005_writable_table,
- .use_single_rw = true,
-};
-
-struct tsc2005_data {
- u16 x;
- u16 y;
- u16 z1;
- u16 z2;
-} __packed;
-#define TSC2005_DATA_REGS 4
-
-struct tsc2005 {
- struct spi_device *spi;
- struct regmap *regmap;
-
- struct input_dev *idev;
- char phys[32];
-
- struct mutex mutex;
-
- /* raw copy of previous x,y,z */
- int in_x;
- int in_y;
- int in_z1;
- int in_z2;
-
- spinlock_t lock;
- struct timer_list penup_timer;
+#include "tsc200x-core.h"
- unsigned int esd_timeout;
- struct delayed_work esd_work;
- unsigned long last_valid_interrupt;
-
- unsigned int x_plate_ohm;
-
- bool opened;
- bool suspended;
-
- bool pen_down;
-
- struct regulator *vio;
-
- struct gpio_desc *reset_gpio;
- void (*set_reset)(bool enable);
-};
-
-static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
+static int tsc2005_cmd(struct device *dev, u8 cmd)
{
- u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
+ u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
struct spi_transfer xfer = {
- .tx_buf = &tx,
- .len = 1,
- .bits_per_word = 8,
+ .tx_buf = &tx,
+ .len = 1,
+ .bits_per_word = 8,
};
struct spi_message msg;
+ struct spi_device *spi = to_spi_device(dev);
int error;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
- error = spi_sync(ts->spi, &msg);
+ error = spi_sync(spi, &msg);
if (error) {
- dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n",
+ dev_err(dev, "%s: failed, command: %x, spi error: %d\n",
__func__, cmd, error);
return error;
}
@@ -208,382 +49,10 @@ static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
return 0;
}
-static void tsc2005_update_pen_state(struct tsc2005 *ts,
- int x, int y, int pressure)
-{
- if (pressure) {
- input_report_abs(ts->idev, ABS_X, x);
- input_report_abs(ts->idev, ABS_Y, y);
- input_report_abs(ts->idev, ABS_PRESSURE, pressure);
- if (!ts->pen_down) {
- input_report_key(ts->idev, BTN_TOUCH, !!pressure);
- ts->pen_down = true;
- }
- } else {
- input_report_abs(ts->idev, ABS_PRESSURE, 0);
- if (ts->pen_down) {
- input_report_key(ts->idev, BTN_TOUCH, 0);
- ts->pen_down = false;
- }
- }
- input_sync(ts->idev);
- dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
- pressure);
-}
-
-static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
-{
- struct tsc2005 *ts = _ts;
- unsigned long flags;
- unsigned int pressure;
- struct tsc2005_data tsdata;
- int error;
-
- /* read the coordinates */
- error = regmap_bulk_read(ts->regmap, TSC2005_REG_X, &tsdata,
- TSC2005_DATA_REGS);
- if (unlikely(error))
- goto out;
-
- /* validate position */
- if (unlikely(tsdata.x > MAX_12BIT || tsdata.y > MAX_12BIT))
- goto out;
-
- /* Skip reading if the pressure components are out of range */
- if (unlikely(tsdata.z1 == 0 || tsdata.z2 > MAX_12BIT))
- goto out;
- if (unlikely(tsdata.z1 >= tsdata.z2))
- goto out;
-
- /*
- * Skip point if this is a pen down with the exact same values as
- * the value before pen-up - that implies SPI fed us stale data
- */
- if (!ts->pen_down &&
- ts->in_x == tsdata.x && ts->in_y == tsdata.y &&
- ts->in_z1 == tsdata.z1 && ts->in_z2 == tsdata.z2) {
- goto out;
- }
-
- /*
- * At this point we are happy we have a valid and useful reading.
- * Remember it for later comparisons. We may now begin downsampling.
- */
- ts->in_x = tsdata.x;
- ts->in_y = tsdata.y;
- ts->in_z1 = tsdata.z1;
- ts->in_z2 = tsdata.z2;
-
- /* Compute touch pressure resistance using equation #1 */
- pressure = tsdata.x * (tsdata.z2 - tsdata.z1) / tsdata.z1;
- pressure = pressure * ts->x_plate_ohm / 4096;
- if (unlikely(pressure > MAX_12BIT))
- goto out;
-
- spin_lock_irqsave(&ts->lock, flags);
-
- tsc2005_update_pen_state(ts, tsdata.x, tsdata.y, pressure);
- mod_timer(&ts->penup_timer,
- jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
-
- spin_unlock_irqrestore(&ts->lock, flags);
-
- ts->last_valid_interrupt = jiffies;
-out:
- return IRQ_HANDLED;
-}
-
-static void tsc2005_penup_timer(unsigned long data)
-{
- struct tsc2005 *ts = (struct tsc2005 *)data;
- unsigned long flags;
-
- spin_lock_irqsave(&ts->lock, flags);
- tsc2005_update_pen_state(ts, 0, 0, 0);
- spin_unlock_irqrestore(&ts->lock, flags);
-}
-
-static void tsc2005_start_scan(struct tsc2005 *ts)
-{
- regmap_write(ts->regmap, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
- regmap_write(ts->regmap, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
- regmap_write(ts->regmap, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
- tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
-}
-
-static void tsc2005_stop_scan(struct tsc2005 *ts)
-{
- tsc2005_cmd(ts, TSC2005_CMD_STOP);
-}
-
-static void tsc2005_set_reset(struct tsc2005 *ts, bool enable)
-{
- if (ts->reset_gpio)
- gpiod_set_value_cansleep(ts->reset_gpio, enable);
- else if (ts->set_reset)
- ts->set_reset(enable);
-}
-
-/* must be called with ts->mutex held */
-static void __tsc2005_disable(struct tsc2005 *ts)
-{
- tsc2005_stop_scan(ts);
-
- disable_irq(ts->spi->irq);
- del_timer_sync(&ts->penup_timer);
-
- cancel_delayed_work_sync(&ts->esd_work);
-
- enable_irq(ts->spi->irq);
-}
-
-/* must be called with ts->mutex held */
-static void __tsc2005_enable(struct tsc2005 *ts)
-{
- tsc2005_start_scan(ts);
-
- if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) {
- ts->last_valid_interrupt = jiffies;
- schedule_delayed_work(&ts->esd_work,
- round_jiffies_relative(
- msecs_to_jiffies(ts->esd_timeout)));
- }
-
-}
-
-static ssize_t tsc2005_selftest_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct tsc2005 *ts = dev_get_drvdata(dev);
- unsigned int temp_high;
- unsigned int temp_high_orig;
- unsigned int temp_high_test;
- bool success = true;
- int error;
-
- mutex_lock(&ts->mutex);
-
- /*
- * Test TSC2005 communications via temp high register.
- */
- __tsc2005_disable(ts);
-
- error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
- if (error) {
- dev_warn(dev, "selftest failed: read error %d\n", error);
- success = false;
- goto out;
- }
-
- temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
-
- error = regmap_write(ts->regmap, TSC2005_REG_TEMP_HIGH, temp_high_test);
- if (error) {
- dev_warn(dev, "selftest failed: write error %d\n", error);
- success = false;
- goto out;
- }
-
- error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high);
- if (error) {
- dev_warn(dev, "selftest failed: read error %d after write\n",
- error);
- success = false;
- goto out;
- }
-
- if (temp_high != temp_high_test) {
- dev_warn(dev, "selftest failed: %d != %d\n",
- temp_high, temp_high_test);
- success = false;
- }
-
- /* hardware reset */
- tsc2005_set_reset(ts, false);
- usleep_range(100, 500); /* only 10us required */
- tsc2005_set_reset(ts, true);
-
- if (!success)
- goto out;
-
- /* test that the reset really happened */
- error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high);
- if (error) {
- dev_warn(dev, "selftest failed: read error %d after reset\n",
- error);
- success = false;
- goto out;
- }
-
- if (temp_high != temp_high_orig) {
- dev_warn(dev, "selftest failed after reset: %d != %d\n",
- temp_high, temp_high_orig);
- success = false;
- }
-
-out:
- __tsc2005_enable(ts);
- mutex_unlock(&ts->mutex);
-
- return sprintf(buf, "%d\n", success);
-}
-
-static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
-
-static struct attribute *tsc2005_attrs[] = {
- &dev_attr_selftest.attr,
- NULL
-};
-
-static umode_t tsc2005_attr_is_visible(struct kobject *kobj,
- struct attribute *attr, int n)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct tsc2005 *ts = dev_get_drvdata(dev);
- umode_t mode = attr->mode;
-
- if (attr == &dev_attr_selftest.attr) {
- if (!ts->set_reset && !ts->reset_gpio)
- mode = 0;
- }
-
- return mode;
-}
-
-static const struct attribute_group tsc2005_attr_group = {
- .is_visible = tsc2005_attr_is_visible,
- .attrs = tsc2005_attrs,
-};
-
-static void tsc2005_esd_work(struct work_struct *work)
-{
- struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
- int error;
- unsigned int r;
-
- if (!mutex_trylock(&ts->mutex)) {
- /*
- * If the mutex is taken, it means that disable or enable is in
- * progress. In that case just reschedule the work. If the work
- * is not needed, it will be canceled by disable.
- */
- goto reschedule;
- }
-
- if (time_is_after_jiffies(ts->last_valid_interrupt +
- msecs_to_jiffies(ts->esd_timeout)))
- goto out;
-
- /* We should be able to read register without disabling interrupts. */
- error = regmap_read(ts->regmap, TSC2005_REG_CFR0, &r);
- if (!error &&
- !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
- goto out;
- }
-
- /*
- * If we could not read our known value from configuration register 0
- * then we should reset the controller as if from power-up and start
- * scanning again.
- */
- dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
-
- disable_irq(ts->spi->irq);
- del_timer_sync(&ts->penup_timer);
-
- tsc2005_update_pen_state(ts, 0, 0, 0);
-
- tsc2005_set_reset(ts, false);
- usleep_range(100, 500); /* only 10us required */
- tsc2005_set_reset(ts, true);
-
- enable_irq(ts->spi->irq);
- tsc2005_start_scan(ts);
-
-out:
- mutex_unlock(&ts->mutex);
-reschedule:
- /* re-arm the watchdog */
- schedule_delayed_work(&ts->esd_work,
- round_jiffies_relative(
- msecs_to_jiffies(ts->esd_timeout)));
-}
-
-static int tsc2005_open(struct input_dev *input)
-{
- struct tsc2005 *ts = input_get_drvdata(input);
-
- mutex_lock(&ts->mutex);
-
- if (!ts->suspended)
- __tsc2005_enable(ts);
-
- ts->opened = true;
-
- mutex_unlock(&ts->mutex);
-
- return 0;
-}
-
-static void tsc2005_close(struct input_dev *input)
-{
- struct tsc2005 *ts = input_get_drvdata(input);
-
- mutex_lock(&ts->mutex);
-
- if (!ts->suspended)
- __tsc2005_disable(ts);
-
- ts->opened = false;
-
- mutex_unlock(&ts->mutex);
-}
-
static int tsc2005_probe(struct spi_device *spi)
{
- const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev);
- struct device_node *np = spi->dev.of_node;
-
- struct tsc2005 *ts;
- struct input_dev *input_dev;
- unsigned int max_x = MAX_12BIT;
- unsigned int max_y = MAX_12BIT;
- unsigned int max_p = MAX_12BIT;
- unsigned int fudge_x = TSC2005_DEF_X_FUZZ;
- unsigned int fudge_y = TSC2005_DEF_Y_FUZZ;
- unsigned int fudge_p = TSC2005_DEF_P_FUZZ;
- unsigned int x_plate_ohm = TSC2005_DEF_RESISTOR;
- unsigned int esd_timeout;
int error;
- if (!np && !pdata) {
- dev_err(&spi->dev, "no platform data\n");
- return -ENODEV;
- }
-
- if (spi->irq <= 0) {
- dev_err(&spi->dev, "no irq\n");
- return -ENODEV;
- }
-
- if (pdata) {
- fudge_x = pdata->ts_x_fudge;
- fudge_y = pdata->ts_y_fudge;
- fudge_p = pdata->ts_pressure_fudge;
- max_x = pdata->ts_x_max;
- max_y = pdata->ts_y_max;
- max_p = pdata->ts_pressure_max;
- x_plate_ohm = pdata->ts_x_plate_ohm;
- esd_timeout = pdata->esd_timeout_ms;
- } else {
- x_plate_ohm = TSC2005_DEF_RESISTOR;
- of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
- esd_timeout = 0;
- of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
- &esd_timeout);
- }
-
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
if (!spi->max_speed_hz)
@@ -593,175 +62,27 @@ static int tsc2005_probe(struct spi_device *spi)
if (error)
return error;
- ts = devm_kzalloc(&spi->dev, sizeof(*ts), GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
-
- input_dev = devm_input_allocate_device(&spi->dev);
- if (!input_dev)
- return -ENOMEM;
-
- ts->spi = spi;
- ts->idev = input_dev;
-
- ts->regmap = devm_regmap_init_spi(spi, &tsc2005_regmap_config);
- if (IS_ERR(ts->regmap))
- return PTR_ERR(ts->regmap);
-
- ts->x_plate_ohm = x_plate_ohm;
- ts->esd_timeout = esd_timeout;
-
- ts->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
- GPIOD_OUT_HIGH);
- if (IS_ERR(ts->reset_gpio)) {
- error = PTR_ERR(ts->reset_gpio);
- dev_err(&spi->dev, "error acquiring reset gpio: %d\n", error);
- return error;
- }
-
- ts->vio = devm_regulator_get_optional(&spi->dev, "vio");
- if (IS_ERR(ts->vio)) {
- error = PTR_ERR(ts->vio);
- dev_err(&spi->dev, "vio regulator missing (%d)", error);
- return error;
- }
-
- if (!ts->reset_gpio && pdata)
- ts->set_reset = pdata->set_reset;
-
- mutex_init(&ts->mutex);
-
- spin_lock_init(&ts->lock);
- setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
-
- INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
-
- snprintf(ts->phys, sizeof(ts->phys),
- "%s/input-ts", dev_name(&spi->dev));
-
- input_dev->name = "TSC2005 touchscreen";
- input_dev->phys = ts->phys;
- input_dev->id.bustype = BUS_SPI;
- input_dev->dev.parent = &spi->dev;
- input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
- input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
-
- if (np)
- touchscreen_parse_properties(input_dev, false);
-
- input_dev->open = tsc2005_open;
- input_dev->close = tsc2005_close;
-
- input_set_drvdata(input_dev, ts);
-
- /* Ensure the touchscreen is off */
- tsc2005_stop_scan(ts);
-
- error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
- tsc2005_irq_thread,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- "tsc2005", ts);
- if (error) {
- dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
- return error;
- }
-
- /* enable regulator for DT */
- if (ts->vio) {
- error = regulator_enable(ts->vio);
- if (error)
- return error;
- }
-
- dev_set_drvdata(&spi->dev, ts);
- error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
- if (error) {
- dev_err(&spi->dev,
- "Failed to create sysfs attributes, err: %d\n", error);
- goto disable_regulator;
- }
-
- error = input_register_device(ts->idev);
- if (error) {
- dev_err(&spi->dev,
- "Failed to register input device, err: %d\n", error);
- goto err_remove_sysfs;
- }
-
- irq_set_irq_wake(spi->irq, 1);
- return 0;
-
-err_remove_sysfs:
- sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
-disable_regulator:
- if (ts->vio)
- regulator_disable(ts->vio);
- return error;
+ return tsc200x_probe(&spi->dev, spi->irq, BUS_SPI,
+ devm_regmap_init_spi(spi, &tsc200x_regmap_config),
+ tsc2005_cmd);
}
static int tsc2005_remove(struct spi_device *spi)
{
- struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
-
- sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
-
- if (ts->vio)
- regulator_disable(ts->vio);
-
- return 0;
-}
-
-static int __maybe_unused tsc2005_suspend(struct device *dev)
-{
- struct tsc2005 *ts = dev_get_drvdata(dev);
-
- mutex_lock(&ts->mutex);
-
- if (!ts->suspended && ts->opened)
- __tsc2005_disable(ts);
-
- ts->suspended = true;
-
- mutex_unlock(&ts->mutex);
-
- return 0;
-}
-
-static int __maybe_unused tsc2005_resume(struct device *dev)
-{
- struct tsc2005 *ts = dev_get_drvdata(dev);
-
- mutex_lock(&ts->mutex);
-
- if (ts->suspended && ts->opened)
- __tsc2005_enable(ts);
-
- ts->suspended = false;
-
- mutex_unlock(&ts->mutex);
-
- return 0;
+ return tsc200x_remove(&spi->dev);
}
-static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
-
static struct spi_driver tsc2005_driver = {
.driver = {
.name = "tsc2005",
- .owner = THIS_MODULE,
- .pm = &tsc2005_pm_ops,
+ .pm = &tsc200x_pm_ops,
},
.probe = tsc2005_probe,
.remove = tsc2005_remove,
};
-
module_spi_driver(tsc2005_driver);
-MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:tsc2005");
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
new file mode 100644
index 000000000000..15240c1ee850
--- /dev/null
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -0,0 +1,665 @@
+/*
+ * TSC2004/TSC2005 touchscreen driver core
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2015 QWERTY Embedded Design
+ * Copyright (C) 2015 EMAC Inc.
+ *
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.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>
+#include <linux/input.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/spi/tsc2005.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
+#include <linux/gpio/consumer.h>
+#include "tsc200x-core.h"
+
+/*
+ * The touchscreen interface operates as follows:
+ *
+ * 1) Pen is pressed against the touchscreen.
+ * 2) TSC200X performs AD conversion.
+ * 3) After the conversion is done TSC200X drives DAV line down.
+ * 4) GPIO IRQ is received and tsc200x_irq_thread() is scheduled.
+ * 5) tsc200x_irq_thread() queues up a transfer to fetch the x, y, z1, z2
+ * values.
+ * 6) tsc200x_irq_thread() reports coordinates to input layer and sets up
+ * tsc200x_penup_timer() to be called after TSC200X_PENUP_TIME_MS (40ms).
+ * 7) When the penup timer expires, there have not been touch or DAV interrupts
+ * during the last 40ms which means the pen has been lifted.
+ *
+ * ESD recovery via a hardware reset is done if the TSC200X doesn't respond
+ * after a configurable period (in ms) of activity. If esd_timeout is 0, the
+ * watchdog is disabled.
+ */
+
+static const struct regmap_range tsc200x_writable_ranges[] = {
+ regmap_reg_range(TSC200X_REG_AUX_HIGH, TSC200X_REG_CFR2),
+};
+
+static const struct regmap_access_table tsc200x_writable_table = {
+ .yes_ranges = tsc200x_writable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tsc200x_writable_ranges),
+};
+
+const struct regmap_config tsc200x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .reg_stride = 0x08,
+ .max_register = 0x78,
+ .read_flag_mask = TSC200X_REG_READ,
+ .write_flag_mask = TSC200X_REG_PND0,
+ .wr_table = &tsc200x_writable_table,
+ .use_single_rw = true,
+};
+EXPORT_SYMBOL_GPL(tsc200x_regmap_config);
+
+struct tsc200x_data {
+ u16 x;
+ u16 y;
+ u16 z1;
+ u16 z2;
+} __packed;
+#define TSC200X_DATA_REGS 4
+
+struct tsc200x {
+ struct device *dev;
+ struct regmap *regmap;
+ __u16 bustype;
+
+ struct input_dev *idev;
+ char phys[32];
+
+ struct mutex mutex;
+
+ /* raw copy of previous x,y,z */
+ int in_x;
+ int in_y;
+ int in_z1;
+ int in_z2;
+
+ spinlock_t lock;
+ struct timer_list penup_timer;
+
+ unsigned int esd_timeout;
+ struct delayed_work esd_work;
+ unsigned long last_valid_interrupt;
+
+ unsigned int x_plate_ohm;
+
+ bool opened;
+ bool suspended;
+
+ bool pen_down;
+
+ struct regulator *vio;
+
+ struct gpio_desc *reset_gpio;
+ void (*set_reset)(bool enable);
+ int (*tsc200x_cmd)(struct device *dev, u8 cmd);
+ int irq;
+};
+
+static void tsc200x_update_pen_state(struct tsc200x *ts,
+ int x, int y, int pressure)
+{
+ if (pressure) {
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+ if (!ts->pen_down) {
+ input_report_key(ts->idev, BTN_TOUCH, !!pressure);
+ ts->pen_down = true;
+ }
+ } else {
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ if (ts->pen_down) {
+ input_report_key(ts->idev, BTN_TOUCH, 0);
+ ts->pen_down = false;
+ }
+ }
+ input_sync(ts->idev);
+ dev_dbg(ts->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
+ pressure);
+}
+
+static irqreturn_t tsc200x_irq_thread(int irq, void *_ts)
+{
+ struct tsc200x *ts = _ts;
+ unsigned long flags;
+ unsigned int pressure;
+ struct tsc200x_data tsdata;
+ int error;
+
+ /* read the coordinates */
+ error = regmap_bulk_read(ts->regmap, TSC200X_REG_X, &tsdata,
+ TSC200X_DATA_REGS);
+ if (unlikely(error))
+ goto out;
+
+ /* validate position */
+ if (unlikely(tsdata.x > MAX_12BIT || tsdata.y > MAX_12BIT))
+ goto out;
+
+ /* Skip reading if the pressure components are out of range */
+ if (unlikely(tsdata.z1 == 0 || tsdata.z2 > MAX_12BIT))
+ goto out;
+ if (unlikely(tsdata.z1 >= tsdata.z2))
+ goto out;
+
+ /*
+ * Skip point if this is a pen down with the exact same values as
+ * the value before pen-up - that implies SPI fed us stale data
+ */
+ if (!ts->pen_down &&
+ ts->in_x == tsdata.x && ts->in_y == tsdata.y &&
+ ts->in_z1 == tsdata.z1 && ts->in_z2 == tsdata.z2) {
+ goto out;
+ }
+
+ /*
+ * At this point we are happy we have a valid and useful reading.
+ * Remember it for later comparisons. We may now begin downsampling.
+ */
+ ts->in_x = tsdata.x;
+ ts->in_y = tsdata.y;
+ ts->in_z1 = tsdata.z1;
+ ts->in_z2 = tsdata.z2;
+
+ /* Compute touch pressure resistance using equation #1 */
+ pressure = tsdata.x * (tsdata.z2 - tsdata.z1) / tsdata.z1;
+ pressure = pressure * ts->x_plate_ohm / 4096;
+ if (unlikely(pressure > MAX_12BIT))
+ goto out;
+
+ spin_lock_irqsave(&ts->lock, flags);
+
+ tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure);
+ mod_timer(&ts->penup_timer,
+ jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS));
+
+ spin_unlock_irqrestore(&ts->lock, flags);
+
+ ts->last_valid_interrupt = jiffies;
+out:
+ return IRQ_HANDLED;
+}
+
+static void tsc200x_penup_timer(unsigned long data)
+{
+ struct tsc200x *ts = (struct tsc200x *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->lock, flags);
+ tsc200x_update_pen_state(ts, 0, 0, 0);
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void tsc200x_start_scan(struct tsc200x *ts)
+{
+ regmap_write(ts->regmap, TSC200X_REG_CFR0, TSC200X_CFR0_INITVALUE);
+ regmap_write(ts->regmap, TSC200X_REG_CFR1, TSC200X_CFR1_INITVALUE);
+ regmap_write(ts->regmap, TSC200X_REG_CFR2, TSC200X_CFR2_INITVALUE);
+ ts->tsc200x_cmd(ts->dev, TSC200X_CMD_NORMAL);
+}
+
+static void tsc200x_stop_scan(struct tsc200x *ts)
+{
+ ts->tsc200x_cmd(ts->dev, TSC200X_CMD_STOP);
+}
+
+static void tsc200x_set_reset(struct tsc200x *ts, bool enable)
+{
+ if (ts->reset_gpio)
+ gpiod_set_value_cansleep(ts->reset_gpio, enable);
+ else if (ts->set_reset)
+ ts->set_reset(enable);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc200x_disable(struct tsc200x *ts)
+{
+ tsc200x_stop_scan(ts);
+
+ disable_irq(ts->irq);
+ del_timer_sync(&ts->penup_timer);
+
+ cancel_delayed_work_sync(&ts->esd_work);
+
+ enable_irq(ts->irq);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc200x_enable(struct tsc200x *ts)
+{
+ tsc200x_start_scan(ts);
+
+ if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) {
+ ts->last_valid_interrupt = jiffies;
+ schedule_delayed_work(&ts->esd_work,
+ round_jiffies_relative(
+ msecs_to_jiffies(ts->esd_timeout)));
+ }
+}
+
+static ssize_t tsc200x_selftest_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tsc200x *ts = dev_get_drvdata(dev);
+ unsigned int temp_high;
+ unsigned int temp_high_orig;
+ unsigned int temp_high_test;
+ bool success = true;
+ int error;
+
+ mutex_lock(&ts->mutex);
+
+ /*
+ * Test TSC200X communications via temp high register.
+ */
+ __tsc200x_disable(ts);
+
+ error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high_orig);
+ if (error) {
+ dev_warn(dev, "selftest failed: read error %d\n", error);
+ success = false;
+ goto out;
+ }
+
+ temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
+
+ error = regmap_write(ts->regmap, TSC200X_REG_TEMP_HIGH, temp_high_test);
+ if (error) {
+ dev_warn(dev, "selftest failed: write error %d\n", error);
+ success = false;
+ goto out;
+ }
+
+ error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high);
+ if (error) {
+ dev_warn(dev, "selftest failed: read error %d after write\n",
+ error);
+ success = false;
+ goto out;
+ }
+
+ if (temp_high != temp_high_test) {
+ dev_warn(dev, "selftest failed: %d != %d\n",
+ temp_high, temp_high_test);
+ success = false;
+ }
+
+ /* hardware reset */
+ tsc200x_set_reset(ts, false);
+ usleep_range(100, 500); /* only 10us required */
+ tsc200x_set_reset(ts, true);
+
+ if (!success)
+ goto out;
+
+ /* test that the reset really happened */
+ error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high);
+ if (error) {
+ dev_warn(dev, "selftest failed: read error %d after reset\n",
+ error);
+ success = false;
+ goto out;
+ }
+
+ if (temp_high != temp_high_orig) {
+ dev_warn(dev, "selftest failed after reset: %d != %d\n",
+ temp_high, temp_high_orig);
+ success = false;
+ }
+
+out:
+ __tsc200x_enable(ts);
+ mutex_unlock(&ts->mutex);
+
+ return sprintf(buf, "%d\n", success);
+}
+
+static DEVICE_ATTR(selftest, S_IRUGO, tsc200x_selftest_show, NULL);
+
+static struct attribute *tsc200x_attrs[] = {
+ &dev_attr_selftest.attr,
+ NULL
+};
+
+static umode_t tsc200x_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tsc200x *ts = dev_get_drvdata(dev);
+ umode_t mode = attr->mode;
+
+ if (attr == &dev_attr_selftest.attr) {
+ if (!ts->set_reset && !ts->reset_gpio)
+ mode = 0;
+ }
+
+ return mode;
+}
+
+static const struct attribute_group tsc200x_attr_group = {
+ .is_visible = tsc200x_attr_is_visible,
+ .attrs = tsc200x_attrs,
+};
+
+static void tsc200x_esd_work(struct work_struct *work)
+{
+ struct tsc200x *ts = container_of(work, struct tsc200x, esd_work.work);
+ int error;
+ unsigned int r;
+
+ if (!mutex_trylock(&ts->mutex)) {
+ /*
+ * If the mutex is taken, it means that disable or enable is in
+ * progress. In that case just reschedule the work. If the work
+ * is not needed, it will be canceled by disable.
+ */
+ goto reschedule;
+ }
+
+ if (time_is_after_jiffies(ts->last_valid_interrupt +
+ msecs_to_jiffies(ts->esd_timeout)))
+ goto out;
+
+ /* We should be able to read register without disabling interrupts. */
+ error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r);
+ if (!error &&
+ !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) {
+ goto out;
+ }
+
+ /*
+ * If we could not read our known value from configuration register 0
+ * then we should reset the controller as if from power-up and start
+ * scanning again.
+ */
+ dev_info(ts->dev, "TSC200X not responding - resetting\n");
+
+ disable_irq(ts->irq);
+ del_timer_sync(&ts->penup_timer);
+
+ tsc200x_update_pen_state(ts, 0, 0, 0);
+
+ tsc200x_set_reset(ts, false);
+ usleep_range(100, 500); /* only 10us required */
+ tsc200x_set_reset(ts, true);
+
+ enable_irq(ts->irq);
+ tsc200x_start_scan(ts);
+
+out:
+ mutex_unlock(&ts->mutex);
+reschedule:
+ /* re-arm the watchdog */
+ schedule_delayed_work(&ts->esd_work,
+ round_jiffies_relative(
+ msecs_to_jiffies(ts->esd_timeout)));
+}
+
+static int tsc200x_open(struct input_dev *input)
+{
+ struct tsc200x *ts = input_get_drvdata(input);
+
+ mutex_lock(&ts->mutex);
+
+ if (!ts->suspended)
+ __tsc200x_enable(ts);
+
+ ts->opened = true;
+
+ mutex_unlock(&ts->mutex);
+
+ return 0;
+}
+
+static void tsc200x_close(struct input_dev *input)
+{
+ struct tsc200x *ts = input_get_drvdata(input);
+
+ mutex_lock(&ts->mutex);
+
+ if (!ts->suspended)
+ __tsc200x_disable(ts);
+
+ ts->opened = false;
+
+ mutex_unlock(&ts->mutex);
+}
+
+int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
+ struct regmap *regmap,
+ int (*tsc200x_cmd)(struct device *dev, u8 cmd))
+{
+ const struct tsc2005_platform_data *pdata = dev_get_platdata(dev);
+ struct device_node *np = dev->of_node;
+
+ struct tsc200x *ts;
+ struct input_dev *input_dev;
+ unsigned int max_x = MAX_12BIT;
+ unsigned int max_y = MAX_12BIT;
+ unsigned int max_p = MAX_12BIT;
+ unsigned int fudge_x = TSC200X_DEF_X_FUZZ;
+ unsigned int fudge_y = TSC200X_DEF_Y_FUZZ;
+ unsigned int fudge_p = TSC200X_DEF_P_FUZZ;
+ unsigned int x_plate_ohm = TSC200X_DEF_RESISTOR;
+ unsigned int esd_timeout;
+ int error;
+
+ if (!np && !pdata) {
+ dev_err(dev, "no platform data\n");
+ return -ENODEV;
+ }
+
+ if (irq <= 0) {
+ dev_err(dev, "no irq\n");
+ return -ENODEV;
+ }
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ if (!tsc200x_cmd) {
+ dev_err(dev, "no cmd function\n");
+ return -ENODEV;
+ }
+
+ if (pdata) {
+ fudge_x = pdata->ts_x_fudge;
+ fudge_y = pdata->ts_y_fudge;
+ fudge_p = pdata->ts_pressure_fudge;
+ max_x = pdata->ts_x_max;
+ max_y = pdata->ts_y_max;
+ max_p = pdata->ts_pressure_max;
+ x_plate_ohm = pdata->ts_x_plate_ohm;
+ esd_timeout = pdata->esd_timeout_ms;
+ } else {
+ x_plate_ohm = TSC200X_DEF_RESISTOR;
+ of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
+ esd_timeout = 0;
+ of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
+ &esd_timeout);
+ }
+
+ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ input_dev = devm_input_allocate_device(dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ ts->irq = irq;
+ ts->dev = dev;
+ ts->idev = input_dev;
+ ts->regmap = regmap;
+ ts->tsc200x_cmd = tsc200x_cmd;
+ ts->x_plate_ohm = x_plate_ohm;
+ ts->esd_timeout = esd_timeout;
+
+ ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ts->reset_gpio)) {
+ error = PTR_ERR(ts->reset_gpio);
+ dev_err(dev, "error acquiring reset gpio: %d\n", error);
+ return error;
+ }
+
+ ts->vio = devm_regulator_get_optional(dev, "vio");
+ if (IS_ERR(ts->vio)) {
+ error = PTR_ERR(ts->vio);
+ dev_err(dev, "vio regulator missing (%d)", error);
+ return error;
+ }
+
+ if (!ts->reset_gpio && pdata)
+ ts->set_reset = pdata->set_reset;
+
+ mutex_init(&ts->mutex);
+
+ spin_lock_init(&ts->lock);
+ setup_timer(&ts->penup_timer, tsc200x_penup_timer, (unsigned long)ts);
+
+ INIT_DELAYED_WORK(&ts->esd_work, tsc200x_esd_work);
+
+ snprintf(ts->phys, sizeof(ts->phys),
+ "%s/input-ts", dev_name(dev));
+
+ input_dev->name = "TSC200X touchscreen";
+ input_dev->phys = ts->phys;
+ input_dev->id.bustype = bustype;
+ input_dev->dev.parent = dev;
+ input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
+
+ if (np)
+ touchscreen_parse_properties(input_dev, false);
+
+ input_dev->open = tsc200x_open;
+ input_dev->close = tsc200x_close;
+
+ input_set_drvdata(input_dev, ts);
+
+ /* Ensure the touchscreen is off */
+ tsc200x_stop_scan(ts);
+
+ error = devm_request_threaded_irq(dev, irq, NULL,
+ tsc200x_irq_thread,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "tsc200x", ts);
+ if (error) {
+ dev_err(dev, "Failed to request irq, err: %d\n", error);
+ return error;
+ }
+
+ /* enable regulator for DT */
+ if (ts->vio) {
+ error = regulator_enable(ts->vio);
+ if (error)
+ return error;
+ }
+
+ dev_set_drvdata(dev, ts);
+ error = sysfs_create_group(&dev->kobj, &tsc200x_attr_group);
+ if (error) {
+ dev_err(dev,
+ "Failed to create sysfs attributes, err: %d\n", error);
+ goto disable_regulator;
+ }
+
+ error = input_register_device(ts->idev);
+ if (error) {
+ dev_err(dev,
+ "Failed to register input device, err: %d\n", error);
+ goto err_remove_sysfs;
+ }
+
+ irq_set_irq_wake(irq, 1);
+ return 0;
+
+err_remove_sysfs:
+ sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
+disable_regulator:
+ if (ts->vio)
+ regulator_disable(ts->vio);
+ return error;
+}
+EXPORT_SYMBOL_GPL(tsc200x_probe);
+
+int tsc200x_remove(struct device *dev)
+{
+ struct tsc200x *ts = dev_get_drvdata(dev);
+
+ sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
+
+ if (ts->vio)
+ regulator_disable(ts->vio);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tsc200x_remove);
+
+static int __maybe_unused tsc200x_suspend(struct device *dev)
+{
+ struct tsc200x *ts = dev_get_drvdata(dev);
+
+ mutex_lock(&ts->mutex);
+
+ if (!ts->suspended && ts->opened)
+ __tsc200x_disable(ts);
+
+ ts->suspended = true;
+
+ mutex_unlock(&ts->mutex);
+
+ return 0;
+}
+
+static int __maybe_unused tsc200x_resume(struct device *dev)
+{
+ struct tsc200x *ts = dev_get_drvdata(dev);
+
+ mutex_lock(&ts->mutex);
+
+ if (ts->suspended && ts->opened)
+ __tsc200x_enable(ts);
+
+ ts->suspended = false;
+
+ mutex_unlock(&ts->mutex);
+
+ return 0;
+}
+
+SIMPLE_DEV_PM_OPS(tsc200x_pm_ops, tsc200x_suspend, tsc200x_resume);
+EXPORT_SYMBOL_GPL(tsc200x_pm_ops);
+
+MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_DESCRIPTION("TSC200x Touchscreen Driver Core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/tsc200x-core.h b/drivers/input/touchscreen/tsc200x-core.h
new file mode 100644
index 000000000000..7a482d102614
--- /dev/null
+++ b/drivers/input/touchscreen/tsc200x-core.h
@@ -0,0 +1,78 @@
+#ifndef _TSC200X_CORE_H
+#define _TSC200X_CORE_H
+
+/* control byte 1 */
+#define TSC200X_CMD 0x80
+#define TSC200X_CMD_NORMAL 0x00
+#define TSC200X_CMD_STOP 0x01
+#define TSC200X_CMD_12BIT 0x04
+
+/* control byte 0 */
+#define TSC200X_REG_READ 0x01 /* R/W access */
+#define TSC200X_REG_PND0 0x02 /* Power Not Down Control */
+#define TSC200X_REG_X (0x0 << 3)
+#define TSC200X_REG_Y (0x1 << 3)
+#define TSC200X_REG_Z1 (0x2 << 3)
+#define TSC200X_REG_Z2 (0x3 << 3)
+#define TSC200X_REG_AUX (0x4 << 3)
+#define TSC200X_REG_TEMP1 (0x5 << 3)
+#define TSC200X_REG_TEMP2 (0x6 << 3)
+#define TSC200X_REG_STATUS (0x7 << 3)
+#define TSC200X_REG_AUX_HIGH (0x8 << 3)
+#define TSC200X_REG_AUX_LOW (0x9 << 3)
+#define TSC200X_REG_TEMP_HIGH (0xA << 3)
+#define TSC200X_REG_TEMP_LOW (0xB << 3)
+#define TSC200X_REG_CFR0 (0xC << 3)
+#define TSC200X_REG_CFR1 (0xD << 3)
+#define TSC200X_REG_CFR2 (0xE << 3)
+#define TSC200X_REG_CONV_FUNC (0xF << 3)
+
+/* configuration register 0 */
+#define TSC200X_CFR0_PRECHARGE_276US 0x0040
+#define TSC200X_CFR0_STABTIME_1MS 0x0300
+#define TSC200X_CFR0_CLOCK_1MHZ 0x1000
+#define TSC200X_CFR0_RESOLUTION12 0x2000
+#define TSC200X_CFR0_PENMODE 0x8000
+#define TSC200X_CFR0_INITVALUE (TSC200X_CFR0_STABTIME_1MS | \
+ TSC200X_CFR0_CLOCK_1MHZ | \
+ TSC200X_CFR0_RESOLUTION12 | \
+ TSC200X_CFR0_PRECHARGE_276US | \
+ TSC200X_CFR0_PENMODE)
+
+/* bits common to both read and write of configuration register 0 */
+#define TSC200X_CFR0_RW_MASK 0x3fff
+
+/* configuration register 1 */
+#define TSC200X_CFR1_BATCHDELAY_4MS 0x0003
+#define TSC200X_CFR1_INITVALUE TSC200X_CFR1_BATCHDELAY_4MS
+
+/* configuration register 2 */
+#define TSC200X_CFR2_MAVE_Z 0x0004
+#define TSC200X_CFR2_MAVE_Y 0x0008
+#define TSC200X_CFR2_MAVE_X 0x0010
+#define TSC200X_CFR2_AVG_7 0x0800
+#define TSC200X_CFR2_MEDIUM_15 0x3000
+#define TSC200X_CFR2_INITVALUE (TSC200X_CFR2_MAVE_X | \
+ TSC200X_CFR2_MAVE_Y | \
+ TSC200X_CFR2_MAVE_Z | \
+ TSC200X_CFR2_MEDIUM_15 | \
+ TSC200X_CFR2_AVG_7)
+
+#define MAX_12BIT 0xfff
+#define TSC200X_DEF_X_FUZZ 4
+#define TSC200X_DEF_Y_FUZZ 8
+#define TSC200X_DEF_P_FUZZ 2
+#define TSC200X_DEF_RESISTOR 280
+
+#define TSC2005_SPI_MAX_SPEED_HZ 10000000
+#define TSC200X_PENUP_TIME_MS 40
+
+extern const struct regmap_config tsc200x_regmap_config;
+extern const struct dev_pm_ops tsc200x_pm_ops;
+
+int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
+ struct regmap *regmap,
+ int (*tsc200x_cmd)(struct device *dev, u8 cmd));
+int tsc200x_remove(struct device *dev);
+
+#endif
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 781d0f83050a..9bbadaaf6bc3 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -599,13 +599,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
static int zforce_input_open(struct input_dev *dev)
{
struct zforce_ts *ts = input_get_drvdata(dev);
- int ret;
- ret = zforce_start(ts);
- if (ret)
- return ret;
-
- return 0;
+ return zforce_start(ts);
}
static void zforce_input_close(struct input_dev *dev)
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d9da766719c8..b9094e9da537 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -23,8 +23,7 @@ config IOMMU_IO_PGTABLE
config IOMMU_IO_PGTABLE_LPAE
bool "ARMv7/v8 Long Descriptor Format"
select IOMMU_IO_PGTABLE
- # SWIOTLB guarantees a dma_to_phys() implementation
- depends on ARM || ARM64 || (COMPILE_TEST && SWIOTLB)
+ depends on HAS_DMA && (ARM || ARM64 || COMPILE_TEST)
help
Enable support for the ARM long descriptor pagetable format.
This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page
@@ -49,6 +48,13 @@ config OF_IOMMU
def_bool y
depends on OF && IOMMU_API
+# IOMMU-agnostic DMA-mapping layer
+config IOMMU_DMA
+ bool
+ depends on NEED_SG_DMA_LENGTH
+ select IOMMU_API
+ select IOMMU_IOVA
+
config FSL_PAMU
bool "Freescale IOMMU support"
depends on PPC32
@@ -135,6 +141,16 @@ config INTEL_IOMMU
and include PCI device scope covered by these DMA
remapping devices.
+config INTEL_IOMMU_SVM
+ bool "Support for Shared Virtual Memory with Intel IOMMU"
+ depends on INTEL_IOMMU && X86
+ select PCI_PASID
+ select MMU_NOTIFIER
+ help
+ Shared Virtual Memory (SVM) provides a facility for devices
+ to access DMA resources through process address space by
+ means of a Process Address Space ID (PASID).
+
config INTEL_IOMMU_DEFAULT_ON
def_bool y
prompt "Enable Intel DMA Remapping Devices by default"
@@ -362,6 +378,7 @@ config ARM_SMMU_V3
depends on ARM64 && PCI
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
+ select GENERIC_MSI_IRQ_DOMAIN
help
Support for implementations of the ARM System MMU architecture
version 3 providing translation support to a PCIe root complex.
@@ -369,4 +386,11 @@ config ARM_SMMU_V3
Say Y here if your system includes an IOMMU device implementing
the ARM SMMUv3 architecture.
+config S390_IOMMU
+ def_bool y if S390 && PCI
+ depends on S390 && PCI
+ select IOMMU_API
+ help
+ Support for the IOMMU API for s390 PCI devices.
+
endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6dcc513d711..68faca02225d 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_IOMMU_API) += iommu.o
obj-$(CONFIG_IOMMU_API) += iommu-traces.o
obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
+obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
obj-$(CONFIG_IOMMU_IOVA) += iova.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
obj-$(CONFIG_DMAR_TABLE) += dmar.o
obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o
+obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
@@ -23,3 +25,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o
obj-$(CONFIG_SHMOBILE_IPMMU) += shmobile-ipmmu.o
obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o
+obj-$(CONFIG_S390_IOMMU) += s390-iommu.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index f82060e778a2..8b2be1e7714f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -89,8 +89,6 @@ static struct dma_map_ops amd_iommu_dma_ops;
struct iommu_dev_data {
struct list_head list; /* For domain->dev_list */
struct list_head dev_data_list; /* For global dev_data_list */
- struct list_head alias_list; /* Link alias-groups together */
- struct iommu_dev_data *alias_data;/* The alias dev_data */
struct protection_domain *domain; /* Domain the device is bound to */
u16 devid; /* PCI Device ID */
bool iommu_v2; /* Device can make use of IOMMUv2 */
@@ -136,8 +134,6 @@ static struct iommu_dev_data *alloc_dev_data(u16 devid)
if (!dev_data)
return NULL;
- INIT_LIST_HEAD(&dev_data->alias_list);
-
dev_data->devid = devid;
spin_lock_irqsave(&dev_data_list_lock, flags);
@@ -147,17 +143,6 @@ static struct iommu_dev_data *alloc_dev_data(u16 devid)
return dev_data;
}
-static void free_dev_data(struct iommu_dev_data *dev_data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev_data_list_lock, flags);
- list_del(&dev_data->dev_data_list);
- spin_unlock_irqrestore(&dev_data_list_lock, flags);
-
- kfree(dev_data);
-}
-
static struct iommu_dev_data *search_dev_data(u16 devid)
{
struct iommu_dev_data *dev_data;
@@ -311,73 +296,10 @@ out:
iommu_group_put(group);
}
-static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
-{
- *(u16 *)data = alias;
- return 0;
-}
-
-static u16 get_alias(struct device *dev)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- u16 devid, ivrs_alias, pci_alias;
-
- devid = get_device_id(dev);
- ivrs_alias = amd_iommu_alias_table[devid];
- pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
-
- if (ivrs_alias == pci_alias)
- return ivrs_alias;
-
- /*
- * DMA alias showdown
- *
- * The IVRS is fairly reliable in telling us about aliases, but it
- * can't know about every screwy device. If we don't have an IVRS
- * reported alias, use the PCI reported alias. In that case we may
- * still need to initialize the rlookup and dev_table entries if the
- * alias is to a non-existent device.
- */
- if (ivrs_alias == devid) {
- if (!amd_iommu_rlookup_table[pci_alias]) {
- amd_iommu_rlookup_table[pci_alias] =
- amd_iommu_rlookup_table[devid];
- memcpy(amd_iommu_dev_table[pci_alias].data,
- amd_iommu_dev_table[devid].data,
- sizeof(amd_iommu_dev_table[pci_alias].data));
- }
-
- return pci_alias;
- }
-
- pr_info("AMD-Vi: Using IVRS reported alias %02x:%02x.%d "
- "for device %s[%04x:%04x], kernel reported alias "
- "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias),
- PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device,
- PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
- PCI_FUNC(pci_alias));
-
- /*
- * If we don't have a PCI DMA alias and the IVRS alias is on the same
- * bus, then the IVRS table may know about a quirk that we don't.
- */
- if (pci_alias == devid &&
- PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
- pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
- pdev->dma_alias_devfn = ivrs_alias & 0xff;
- pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
- PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
- dev_name(dev));
- }
-
- return ivrs_alias;
-}
-
static int iommu_init_device(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct iommu_dev_data *dev_data;
- u16 alias;
if (dev->archdata.iommu)
return 0;
@@ -386,24 +308,6 @@ static int iommu_init_device(struct device *dev)
if (!dev_data)
return -ENOMEM;
- alias = get_alias(dev);
-
- if (alias != dev_data->devid) {
- struct iommu_dev_data *alias_data;
-
- alias_data = find_dev_data(alias);
- if (alias_data == NULL) {
- pr_err("AMD-Vi: Warning: Unhandled device %s\n",
- dev_name(dev));
- free_dev_data(dev_data);
- return -ENOTSUPP;
- }
- dev_data->alias_data = alias_data;
-
- /* Add device to the alias_list */
- list_add(&dev_data->alias_list, &alias_data->alias_list);
- }
-
if (pci_iommuv2_capable(pdev)) {
struct amd_iommu *iommu;
@@ -445,9 +349,6 @@ static void iommu_uninit_device(struct device *dev)
iommu_group_remove_device(dev);
- /* Unlink from alias, it may change if another device is re-plugged */
- dev_data->alias_data = NULL;
-
/* Remove dma-ops */
dev->archdata.dma_ops = NULL;
@@ -633,7 +534,7 @@ static void iommu_poll_events(struct amd_iommu *iommu)
while (head != tail) {
iommu_print_event(iommu, iommu->evt_buf + head);
- head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
+ head = (head + EVENT_ENTRY_SIZE) % EVT_BUFFER_SIZE;
}
writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
@@ -783,7 +684,7 @@ static void copy_cmd_to_buffer(struct amd_iommu *iommu,
u8 *target;
target = iommu->cmd_buf + tail;
- tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
+ tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
/* Copy command to buffer */
memcpy(target, cmd, sizeof(*cmd));
@@ -950,15 +851,13 @@ static int iommu_queue_command_sync(struct amd_iommu *iommu,
u32 left, tail, head, next_tail;
unsigned long flags;
- WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
-
again:
spin_lock_irqsave(&iommu->lock, flags);
head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
- next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
- left = (head - next_tail) % iommu->cmd_buf_size;
+ next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
+ left = (head - next_tail) % CMD_BUFFER_SIZE;
if (left <= 2) {
struct iommu_cmd sync_cmd;
@@ -1114,11 +1013,15 @@ static int device_flush_iotlb(struct iommu_dev_data *dev_data,
static int device_flush_dte(struct iommu_dev_data *dev_data)
{
struct amd_iommu *iommu;
+ u16 alias;
int ret;
iommu = amd_iommu_rlookup_table[dev_data->devid];
+ alias = amd_iommu_alias_table[dev_data->devid];
ret = iommu_flush_dte(iommu, dev_data->devid);
+ if (!ret && alias != dev_data->devid)
+ ret = iommu_flush_dte(iommu, alias);
if (ret)
return ret;
@@ -1974,8 +1877,8 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
static void clear_dte_entry(u16 devid)
{
/* remove entry from the device table seen by the hardware */
- amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
- amd_iommu_dev_table[devid].data[1] = 0;
+ amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+ amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK;
amd_iommu_apply_erratum_63(devid);
}
@@ -1984,29 +1887,45 @@ static void do_attach(struct iommu_dev_data *dev_data,
struct protection_domain *domain)
{
struct amd_iommu *iommu;
+ u16 alias;
bool ats;
iommu = amd_iommu_rlookup_table[dev_data->devid];
+ alias = amd_iommu_alias_table[dev_data->devid];
ats = dev_data->ats.enabled;
/* Update data structures */
dev_data->domain = domain;
list_add(&dev_data->list, &domain->dev_list);
- set_dte_entry(dev_data->devid, domain, ats);
/* Do reference counting */
domain->dev_iommu[iommu->index] += 1;
domain->dev_cnt += 1;
- /* Flush the DTE entry */
+ /* Update device table */
+ set_dte_entry(dev_data->devid, domain, ats);
+ if (alias != dev_data->devid)
+ set_dte_entry(dev_data->devid, domain, ats);
+
device_flush_dte(dev_data);
}
static void do_detach(struct iommu_dev_data *dev_data)
{
struct amd_iommu *iommu;
+ u16 alias;
+
+ /*
+ * First check if the device is still attached. It might already
+ * be detached from its domain because the generic
+ * iommu_detach_group code detached it and we try again here in
+ * our alias handling.
+ */
+ if (!dev_data->domain)
+ return;
iommu = amd_iommu_rlookup_table[dev_data->devid];
+ alias = amd_iommu_alias_table[dev_data->devid];
/* decrease reference counters */
dev_data->domain->dev_iommu[iommu->index] -= 1;
@@ -2016,6 +1935,8 @@ static void do_detach(struct iommu_dev_data *dev_data)
dev_data->domain = NULL;
list_del(&dev_data->list);
clear_dte_entry(dev_data->devid);
+ if (alias != dev_data->devid)
+ clear_dte_entry(alias);
/* Flush the DTE entry */
device_flush_dte(dev_data);
@@ -2028,29 +1949,23 @@ static void do_detach(struct iommu_dev_data *dev_data)
static int __attach_device(struct iommu_dev_data *dev_data,
struct protection_domain *domain)
{
- struct iommu_dev_data *head, *entry;
int ret;
+ /*
+ * Must be called with IRQs disabled. Warn here to detect early
+ * when its not.
+ */
+ WARN_ON(!irqs_disabled());
+
/* lock domain */
spin_lock(&domain->lock);
- head = dev_data;
-
- if (head->alias_data != NULL)
- head = head->alias_data;
-
- /* Now we have the root of the alias group, if any */
-
ret = -EBUSY;
- if (head->domain != NULL)
+ if (dev_data->domain != NULL)
goto out_unlock;
/* Attach alias group root */
- do_attach(head, domain);
-
- /* Attach other devices in the alias group */
- list_for_each_entry(entry, &head->alias_list, alias_list)
- do_attach(entry, domain);
+ do_attach(dev_data, domain);
ret = 0;
@@ -2200,26 +2115,24 @@ static int attach_device(struct device *dev,
*/
static void __detach_device(struct iommu_dev_data *dev_data)
{
- struct iommu_dev_data *head, *entry;
struct protection_domain *domain;
- unsigned long flags;
- BUG_ON(!dev_data->domain);
-
- domain = dev_data->domain;
+ /*
+ * Must be called with IRQs disabled. Warn here to detect early
+ * when its not.
+ */
+ WARN_ON(!irqs_disabled());
- spin_lock_irqsave(&domain->lock, flags);
+ if (WARN_ON(!dev_data->domain))
+ return;
- head = dev_data;
- if (head->alias_data != NULL)
- head = head->alias_data;
+ domain = dev_data->domain;
- list_for_each_entry(entry, &head->alias_list, alias_list)
- do_detach(entry);
+ spin_lock(&domain->lock);
- do_detach(head);
+ do_detach(dev_data);
- spin_unlock_irqrestore(&domain->lock, flags);
+ spin_unlock(&domain->lock);
}
/*
@@ -2755,7 +2668,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
page = alloc_pages(flag | __GFP_NOWARN, get_order(size));
if (!page) {
- if (!(flag & __GFP_WAIT))
+ if (!gfpflags_allow_blocking(flag))
return NULL;
page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
@@ -3189,6 +3102,7 @@ static const struct iommu_ops amd_iommu_ops = {
.iova_to_phys = amd_iommu_iova_to_phys,
.add_device = amd_iommu_add_device,
.remove_device = amd_iommu_remove_device,
+ .device_group = pci_device_group,
.get_dm_regions = amd_iommu_get_dm_regions,
.put_dm_regions = amd_iommu_put_dm_regions,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 5ef347a13cb5..013bdfff2d4d 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -138,7 +138,7 @@ u16 amd_iommu_last_bdf; /* largest PCI device id we have
to handle */
LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings
we find in ACPI */
-u32 amd_iommu_unmap_flush; /* if true, flush on every unmap */
+bool amd_iommu_unmap_flush; /* if true, flush on every unmap */
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
system */
@@ -408,20 +408,6 @@ static inline int ivhd_entry_length(u8 *ivhd)
}
/*
- * This function reads the last device id the IOMMU has to handle from the PCI
- * capability header for this IOMMU
- */
-static int __init find_last_devid_on_pci(int bus, int dev, int fn, int cap_ptr)
-{
- u32 cap;
-
- cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET);
- update_last_devid(PCI_DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
-
- return 0;
-}
-
-/*
* After reading the highest device id from the IOMMU PCI capability header
* this function looks if there is a higher device id defined in the ACPI table
*/
@@ -433,14 +419,13 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h)
p += sizeof(*h);
end += h->length;
- find_last_devid_on_pci(PCI_BUS_NUM(h->devid),
- PCI_SLOT(h->devid),
- PCI_FUNC(h->devid),
- h->cap_ptr);
-
while (p < end) {
dev = (struct ivhd_entry *)p;
switch (dev->type) {
+ case IVHD_DEV_ALL:
+ /* Use maximum BDF value for DEV_ALL */
+ update_last_devid(0xffff);
+ break;
case IVHD_DEV_SELECT:
case IVHD_DEV_RANGE_END:
case IVHD_DEV_ALIAS:
@@ -513,17 +498,12 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table)
* write commands to that buffer later and the IOMMU will execute them
* asynchronously
*/
-static u8 * __init alloc_command_buffer(struct amd_iommu *iommu)
+static int __init alloc_command_buffer(struct amd_iommu *iommu)
{
- u8 *cmd_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
- get_order(CMD_BUFFER_SIZE));
-
- if (cmd_buf == NULL)
- return NULL;
+ iommu->cmd_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(CMD_BUFFER_SIZE));
- iommu->cmd_buf_size = CMD_BUFFER_SIZE | CMD_BUFFER_UNINITIALIZED;
-
- return cmd_buf;
+ return iommu->cmd_buf ? 0 : -ENOMEM;
}
/*
@@ -557,27 +537,20 @@ static void iommu_enable_command_buffer(struct amd_iommu *iommu)
&entry, sizeof(entry));
amd_iommu_reset_cmd_buffer(iommu);
- iommu->cmd_buf_size &= ~(CMD_BUFFER_UNINITIALIZED);
}
static void __init free_command_buffer(struct amd_iommu *iommu)
{
- free_pages((unsigned long)iommu->cmd_buf,
- get_order(iommu->cmd_buf_size & ~(CMD_BUFFER_UNINITIALIZED)));
+ free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE));
}
/* allocates the memory where the IOMMU will log its events to */
-static u8 * __init alloc_event_buffer(struct amd_iommu *iommu)
+static int __init alloc_event_buffer(struct amd_iommu *iommu)
{
- iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
- get_order(EVT_BUFFER_SIZE));
+ iommu->evt_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(EVT_BUFFER_SIZE));
- if (iommu->evt_buf == NULL)
- return NULL;
-
- iommu->evt_buf_size = EVT_BUFFER_SIZE;
-
- return iommu->evt_buf;
+ return iommu->evt_buf ? 0 : -ENOMEM;
}
static void iommu_enable_event_buffer(struct amd_iommu *iommu)
@@ -604,15 +577,12 @@ static void __init free_event_buffer(struct amd_iommu *iommu)
}
/* allocates the memory where the IOMMU will log its events to */
-static u8 * __init alloc_ppr_log(struct amd_iommu *iommu)
+static int __init alloc_ppr_log(struct amd_iommu *iommu)
{
- iommu->ppr_log = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
- get_order(PPR_LOG_SIZE));
+ iommu->ppr_log = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(PPR_LOG_SIZE));
- if (iommu->ppr_log == NULL)
- return NULL;
-
- return iommu->ppr_log;
+ return iommu->ppr_log ? 0 : -ENOMEM;
}
static void iommu_enable_ppr_log(struct amd_iommu *iommu)
@@ -835,20 +805,10 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
switch (e->type) {
case IVHD_DEV_ALL:
- DUMP_printk(" DEV_ALL\t\t\t first devid: %02x:%02x.%x"
- " last device %02x:%02x.%x flags: %02x\n",
- PCI_BUS_NUM(iommu->first_device),
- PCI_SLOT(iommu->first_device),
- PCI_FUNC(iommu->first_device),
- PCI_BUS_NUM(iommu->last_device),
- PCI_SLOT(iommu->last_device),
- PCI_FUNC(iommu->last_device),
- e->flags);
+ DUMP_printk(" DEV_ALL\t\t\tflags: %02x\n", e->flags);
- for (dev_i = iommu->first_device;
- dev_i <= iommu->last_device; ++dev_i)
- set_dev_entry_from_acpi(iommu, dev_i,
- e->flags, 0);
+ for (dev_i = 0; dev_i <= amd_iommu_last_bdf; ++dev_i)
+ set_dev_entry_from_acpi(iommu, dev_i, e->flags, 0);
break;
case IVHD_DEV_SELECT:
@@ -1004,17 +964,6 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
return 0;
}
-/* Initializes the device->iommu mapping for the driver */
-static int __init init_iommu_devices(struct amd_iommu *iommu)
-{
- u32 i;
-
- for (i = iommu->first_device; i <= iommu->last_device; ++i)
- set_iommu_for_device(iommu, i);
-
- return 0;
-}
-
static void __init free_iommu_one(struct amd_iommu *iommu)
{
free_command_buffer(iommu);
@@ -1111,12 +1060,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
if (!iommu->mmio_base)
return -ENOMEM;
- iommu->cmd_buf = alloc_command_buffer(iommu);
- if (!iommu->cmd_buf)
+ if (alloc_command_buffer(iommu))
return -ENOMEM;
- iommu->evt_buf = alloc_event_buffer(iommu);
- if (!iommu->evt_buf)
+ if (alloc_event_buffer(iommu))
return -ENOMEM;
iommu->int_enabled = false;
@@ -1135,8 +1082,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
*/
amd_iommu_rlookup_table[iommu->devid] = NULL;
- init_iommu_devices(iommu);
-
return 0;
}
@@ -1256,6 +1201,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
if (!iommu->dev)
return -ENODEV;
+ /* Prevent binding other PCI device drivers to IOMMU devices */
+ iommu->dev->match_driver = false;
+
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
&iommu->cap);
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
@@ -1263,11 +1211,6 @@ static int iommu_init_pci(struct amd_iommu *iommu)
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET,
&misc);
- iommu->first_device = PCI_DEVID(MMIO_GET_BUS(range),
- MMIO_GET_FD(range));
- iommu->last_device = PCI_DEVID(MMIO_GET_BUS(range),
- MMIO_GET_LD(range));
-
if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
amd_iommu_iotlb_sup = false;
@@ -1305,11 +1248,8 @@ static int iommu_init_pci(struct amd_iommu *iommu)
amd_iommu_v2_present = true;
}
- if (iommu_feature(iommu, FEATURE_PPR)) {
- iommu->ppr_log = alloc_ppr_log(iommu);
- if (!iommu->ppr_log)
- return -ENOMEM;
- }
+ if (iommu_feature(iommu, FEATURE_PPR) && alloc_ppr_log(iommu))
+ return -ENOMEM;
if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
amd_iommu_np_cache = true;
@@ -1755,11 +1695,8 @@ static void __init free_on_init_error(void)
free_pages((unsigned long)irq_lookup_table,
get_order(rlookup_table_size));
- if (amd_iommu_irq_cache) {
- kmem_cache_destroy(amd_iommu_irq_cache);
- amd_iommu_irq_cache = NULL;
-
- }
+ kmem_cache_destroy(amd_iommu_irq_cache);
+ amd_iommu_irq_cache = NULL;
free_pages((unsigned long)amd_iommu_rlookup_table,
get_order(rlookup_table_size));
@@ -2198,7 +2135,7 @@ int __init amd_iommu_detect(void)
iommu_detected = 1;
x86_init.iommu.iommu_init = amd_iommu_init;
- return 0;
+ return 1;
}
/****************************************************************************
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index f65908841be0..b08cf57bf455 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -295,8 +295,9 @@
#define IOMMU_PTE_IR (1ULL << 61)
#define IOMMU_PTE_IW (1ULL << 62)
-#define DTE_FLAG_IOTLB (0x01UL << 32)
-#define DTE_FLAG_GV (0x01ULL << 55)
+#define DTE_FLAG_IOTLB (1ULL << 32)
+#define DTE_FLAG_GV (1ULL << 55)
+#define DTE_FLAG_MASK (0x3ffULL << 32)
#define DTE_GLX_SHIFT (56)
#define DTE_GLX_MASK (3)
@@ -516,11 +517,6 @@ struct amd_iommu {
/* pci domain of this IOMMU */
u16 pci_seg;
- /* first device this IOMMU handles. read from PCI */
- u16 first_device;
- /* last device this IOMMU handles. read from PCI */
- u16 last_device;
-
/* start of exclusion range of that IOMMU */
u64 exclusion_start;
/* length of exclusion range of that IOMMU */
@@ -528,11 +524,7 @@ struct amd_iommu {
/* command buffer virtual address */
u8 *cmd_buf;
- /* size of command buffer */
- u32 cmd_buf_size;
- /* size of event buffer */
- u32 evt_buf_size;
/* event buffer virtual address */
u8 *evt_buf;
@@ -674,7 +666,7 @@ extern unsigned long *amd_iommu_pd_alloc_bitmap;
* If true, the addresses will be flushed on unmap time, not when
* they are reused
*/
-extern u32 amd_iommu_unmap_flush;
+extern bool amd_iommu_unmap_flush;
/* Smallest max PASID supported by any IOMMU in the system */
extern u32 amd_iommu_max_pasid;
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 1131664b918b..d21d4edf7236 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -516,6 +516,13 @@ static void do_fault(struct work_struct *work)
goto out;
}
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
+ /* handle_mm_fault would BUG_ON() */
+ up_read(&mm->mmap_sem);
+ handle_fault_error(fault);
+ goto out;
+ }
+
ret = handle_mm_fault(mm, vma, address, write);
if (ret & VM_FAULT_ERROR) {
/* failed to service fault */
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index dafaf59dc3b8..4e5118a4cd30 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -26,8 +26,10 @@
#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/msi.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
@@ -56,6 +58,7 @@
#define IDR0_TTF_SHIFT 2
#define IDR0_TTF_MASK 0x3
#define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT)
+#define IDR0_TTF_AARCH32_64 (3 << IDR0_TTF_SHIFT)
#define IDR0_S1P (1 << 1)
#define IDR0_S2P (1 << 0)
@@ -342,7 +345,8 @@
#define CMDQ_TLBI_0_VMID_SHIFT 32
#define CMDQ_TLBI_0_ASID_SHIFT 48
#define CMDQ_TLBI_1_LEAF (1UL << 0)
-#define CMDQ_TLBI_1_ADDR_MASK ~0xfffUL
+#define CMDQ_TLBI_1_VA_MASK ~0xfffUL
+#define CMDQ_TLBI_1_IPA_MASK 0xfffffffff000UL
#define CMDQ_PRI_0_SSID_SHIFT 12
#define CMDQ_PRI_0_SSID_MASK 0xfffffUL
@@ -401,6 +405,31 @@ enum pri_resp {
PRI_RESP_SUCC,
};
+enum arm_smmu_msi_index {
+ EVTQ_MSI_INDEX,
+ GERROR_MSI_INDEX,
+ PRIQ_MSI_INDEX,
+ ARM_SMMU_MAX_MSIS,
+};
+
+static phys_addr_t arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = {
+ [EVTQ_MSI_INDEX] = {
+ ARM_SMMU_EVTQ_IRQ_CFG0,
+ ARM_SMMU_EVTQ_IRQ_CFG1,
+ ARM_SMMU_EVTQ_IRQ_CFG2,
+ },
+ [GERROR_MSI_INDEX] = {
+ ARM_SMMU_GERROR_IRQ_CFG0,
+ ARM_SMMU_GERROR_IRQ_CFG1,
+ ARM_SMMU_GERROR_IRQ_CFG2,
+ },
+ [PRIQ_MSI_INDEX] = {
+ ARM_SMMU_PRIQ_IRQ_CFG0,
+ ARM_SMMU_PRIQ_IRQ_CFG1,
+ ARM_SMMU_PRIQ_IRQ_CFG2,
+ },
+};
+
struct arm_smmu_cmdq_ent {
/* Common fields */
u8 opcode;
@@ -568,7 +597,6 @@ struct arm_smmu_device {
unsigned int sid_bits;
struct arm_smmu_strtab_cfg strtab_cfg;
- struct list_head list;
};
/* SMMU private data for an IOMMU group */
@@ -603,10 +631,6 @@ struct arm_smmu_domain {
struct iommu_domain domain;
};
-/* Our list of SMMU instances */
-static DEFINE_SPINLOCK(arm_smmu_devices_lock);
-static LIST_HEAD(arm_smmu_devices);
-
struct arm_smmu_option_prop {
u32 opt;
const char *prop;
@@ -770,11 +794,13 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
break;
case CMDQ_OP_TLBI_NH_VA:
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
- /* Fallthrough */
+ cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
+ cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
+ break;
case CMDQ_OP_TLBI_S2_IPA:
cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT;
cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
- cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_ADDR_MASK;
+ cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK;
break;
case CMDQ_OP_TLBI_NH_ASID:
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
@@ -1423,7 +1449,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
struct io_pgtable_cfg *pgtbl_cfg)
{
int ret;
- u16 asid;
+ int asid;
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
@@ -1435,10 +1461,11 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
&cfg->cdptr_dma, GFP_KERNEL);
if (!cfg->cdptr) {
dev_warn(smmu->dev, "failed to allocate context descriptor\n");
+ ret = -ENOMEM;
goto out_free_asid;
}
- cfg->cd.asid = asid;
+ cfg->cd.asid = (u16)asid;
cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair[0];
@@ -1452,7 +1479,7 @@ out_free_asid:
static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
struct io_pgtable_cfg *pgtbl_cfg)
{
- u16 vmid;
+ int vmid;
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
@@ -1460,7 +1487,7 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
if (IS_ERR_VALUE(vmid))
return vmid;
- cfg->vmid = vmid;
+ cfg->vmid = (u16)vmid;
cfg->vttbr = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
cfg->vtcr = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
return 0;
@@ -1722,7 +1749,8 @@ static void __arm_smmu_release_pci_iommudata(void *data)
static struct arm_smmu_device *arm_smmu_get_for_pci_dev(struct pci_dev *pdev)
{
struct device_node *of_node;
- struct arm_smmu_device *curr, *smmu = NULL;
+ struct platform_device *smmu_pdev;
+ struct arm_smmu_device *smmu = NULL;
struct pci_bus *bus = pdev->bus;
/* Walk up to the root bus */
@@ -1735,14 +1763,10 @@ static struct arm_smmu_device *arm_smmu_get_for_pci_dev(struct pci_dev *pdev)
return NULL;
/* See if we can find an SMMU corresponding to the phandle */
- spin_lock(&arm_smmu_devices_lock);
- list_for_each_entry(curr, &arm_smmu_devices, list) {
- if (curr->dev->of_node == of_node) {
- smmu = curr;
- break;
- }
- }
- spin_unlock(&arm_smmu_devices_lock);
+ smmu_pdev = of_find_device_by_node(of_node);
+ if (smmu_pdev)
+ smmu = platform_get_drvdata(smmu_pdev);
+
of_node_put(of_node);
return smmu;
}
@@ -1898,6 +1922,7 @@ static struct iommu_ops arm_smmu_ops = {
.iova_to_phys = arm_smmu_iova_to_phys,
.add_device = arm_smmu_add_device,
.remove_device = arm_smmu_remove_device,
+ .device_group = pci_device_group,
.domain_get_attr = arm_smmu_domain_get_attr,
.domain_set_attr = arm_smmu_domain_set_attr,
.pgsize_bitmap = -1UL, /* Restricted during device attach */
@@ -2182,6 +2207,72 @@ static int arm_smmu_write_reg_sync(struct arm_smmu_device *smmu, u32 val,
1, ARM_SMMU_POLL_TIMEOUT_US);
}
+static void arm_smmu_free_msis(void *data)
+{
+ struct device *dev = data;
+ platform_msi_domain_free_irqs(dev);
+}
+
+static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+ phys_addr_t doorbell;
+ struct device *dev = msi_desc_to_dev(desc);
+ struct arm_smmu_device *smmu = dev_get_drvdata(dev);
+ phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index];
+
+ doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
+ doorbell &= MSI_CFG0_ADDR_MASK << MSI_CFG0_ADDR_SHIFT;
+
+ writeq_relaxed(doorbell, smmu->base + cfg[0]);
+ writel_relaxed(msg->data, smmu->base + cfg[1]);
+ writel_relaxed(MSI_CFG2_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]);
+}
+
+static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
+{
+ struct msi_desc *desc;
+ int ret, nvec = ARM_SMMU_MAX_MSIS;
+ struct device *dev = smmu->dev;
+
+ /* Clear the MSI address regs */
+ writeq_relaxed(0, smmu->base + ARM_SMMU_GERROR_IRQ_CFG0);
+ writeq_relaxed(0, smmu->base + ARM_SMMU_EVTQ_IRQ_CFG0);
+
+ if (smmu->features & ARM_SMMU_FEAT_PRI)
+ writeq_relaxed(0, smmu->base + ARM_SMMU_PRIQ_IRQ_CFG0);
+ else
+ nvec--;
+
+ if (!(smmu->features & ARM_SMMU_FEAT_MSI))
+ return;
+
+ /* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */
+ ret = platform_msi_domain_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg);
+ if (ret) {
+ dev_warn(dev, "failed to allocate MSIs\n");
+ return;
+ }
+
+ for_each_msi_entry(desc, dev) {
+ switch (desc->platform.msi_index) {
+ case EVTQ_MSI_INDEX:
+ smmu->evtq.q.irq = desc->irq;
+ break;
+ case GERROR_MSI_INDEX:
+ smmu->gerr_irq = desc->irq;
+ break;
+ case PRIQ_MSI_INDEX:
+ smmu->priq.q.irq = desc->irq;
+ break;
+ default: /* Unknown */
+ continue;
+ }
+ }
+
+ /* Add callback to free MSIs on teardown */
+ devm_add_action(dev, arm_smmu_free_msis, dev);
+}
+
static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
{
int ret, irq;
@@ -2195,11 +2286,9 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
return ret;
}
- /* Clear the MSI address regs */
- writeq_relaxed(0, smmu->base + ARM_SMMU_GERROR_IRQ_CFG0);
- writeq_relaxed(0, smmu->base + ARM_SMMU_EVTQ_IRQ_CFG0);
+ arm_smmu_setup_msis(smmu);
- /* Request wired interrupt lines */
+ /* Request interrupt lines */
irq = smmu->evtq.q.irq;
if (irq) {
ret = devm_request_threaded_irq(smmu->dev, irq,
@@ -2228,8 +2317,6 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
}
if (smmu->features & ARM_SMMU_FEAT_PRI) {
- writeq_relaxed(0, smmu->base + ARM_SMMU_PRIQ_IRQ_CFG0);
-
irq = smmu->priq.q.irq;
if (irq) {
ret = devm_request_threaded_irq(smmu->dev, irq,
@@ -2460,7 +2547,13 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
}
/* We only support the AArch64 table format at present */
- if ((reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) < IDR0_TTF_AARCH64) {
+ switch (reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) {
+ case IDR0_TTF_AARCH32_64:
+ smmu->ias = 40;
+ /* Fallthrough */
+ case IDR0_TTF_AARCH64:
+ break;
+ default:
dev_err(smmu->dev, "AArch64 table format not supported!\n");
return -ENXIO;
}
@@ -2541,8 +2634,7 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
dev_warn(smmu->dev,
"failed to set DMA mask for table walker\n");
- if (!smmu->ias)
- smmu->ias = smmu->oas;
+ smmu->ias = max(smmu->ias, smmu->oas);
dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
smmu->ias, smmu->oas, smmu->features);
@@ -2603,16 +2695,14 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
if (ret)
return ret;
+ /* Record our private device structure */
+ platform_set_drvdata(pdev, smmu);
+
/* Reset the device */
ret = arm_smmu_device_reset(smmu);
if (ret)
goto out_free_structures;
- /* Record our private device structure */
- INIT_LIST_HEAD(&smmu->list);
- spin_lock(&arm_smmu_devices_lock);
- list_add(&smmu->list, &arm_smmu_devices);
- spin_unlock(&arm_smmu_devices_lock);
return 0;
out_free_structures:
@@ -2622,21 +2712,7 @@ out_free_structures:
static int arm_smmu_device_remove(struct platform_device *pdev)
{
- struct arm_smmu_device *curr, *smmu = NULL;
- struct device *dev = &pdev->dev;
-
- spin_lock(&arm_smmu_devices_lock);
- list_for_each_entry(curr, &arm_smmu_devices, list) {
- if (curr->dev == dev) {
- smmu = curr;
- list_del(&smmu->list);
- break;
- }
- }
- spin_unlock(&arm_smmu_devices_lock);
-
- if (!smmu)
- return -ENODEV;
+ struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
arm_smmu_device_disable(smmu);
arm_smmu_free_structures(smmu);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 48a39dfa9777..47dc7a793f5c 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -70,6 +70,18 @@
((smmu->options & ARM_SMMU_OPT_SECURE_CFG_ACCESS) \
? 0x400 : 0))
+#ifdef CONFIG_64BIT
+#define smmu_writeq writeq_relaxed
+#else
+#define smmu_writeq(reg64, addr) \
+ do { \
+ u64 __val = (reg64); \
+ void __iomem *__addr = (addr); \
+ writel_relaxed(__val >> 32, __addr + 4); \
+ writel_relaxed(__val, __addr); \
+ } while (0)
+#endif
+
/* Configuration registers */
#define ARM_SMMU_GR0_sCR0 0x0
#define sCR0_CLIENTPD (1 << 0)
@@ -185,10 +197,8 @@
#define ARM_SMMU_CB_SCTLR 0x0
#define ARM_SMMU_CB_RESUME 0x8
#define ARM_SMMU_CB_TTBCR2 0x10
-#define ARM_SMMU_CB_TTBR0_LO 0x20
-#define ARM_SMMU_CB_TTBR0_HI 0x24
-#define ARM_SMMU_CB_TTBR1_LO 0x28
-#define ARM_SMMU_CB_TTBR1_HI 0x2c
+#define ARM_SMMU_CB_TTBR0 0x20
+#define ARM_SMMU_CB_TTBR1 0x28
#define ARM_SMMU_CB_TTBCR 0x30
#define ARM_SMMU_CB_S1_MAIR0 0x38
#define ARM_SMMU_CB_S1_MAIR1 0x3c
@@ -226,7 +236,7 @@
#define TTBCR2_SEP_SHIFT 15
#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
-#define TTBRn_HI_ASID_SHIFT 16
+#define TTBRn_ASID_SHIFT 48
#define FSR_MULTI (1 << 31)
#define FSR_SS (1 << 30)
@@ -695,12 +705,12 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
struct io_pgtable_cfg *pgtbl_cfg)
{
u32 reg;
+ u64 reg64;
bool stage1;
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- void __iomem *cb_base, *gr0_base, *gr1_base;
+ void __iomem *cb_base, *gr1_base;
- gr0_base = ARM_SMMU_GR0(smmu);
gr1_base = ARM_SMMU_GR1(smmu);
stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
@@ -738,22 +748,17 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
/* TTBRs */
if (stage1) {
- reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
- reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0] >> 32;
- reg |= ARM_SMMU_CB_ASID(cfg) << TTBRn_HI_ASID_SHIFT;
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI);
-
- reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR1_LO);
- reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1] >> 32;
- reg |= ARM_SMMU_CB_ASID(cfg) << TTBRn_HI_ASID_SHIFT;
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR1_HI);
+ reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
+
+ reg64 |= ((u64)ARM_SMMU_CB_ASID(cfg)) << TTBRn_ASID_SHIFT;
+ smmu_writeq(reg64, cb_base + ARM_SMMU_CB_TTBR0);
+
+ reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
+ reg64 |= ((u64)ARM_SMMU_CB_ASID(cfg)) << TTBRn_ASID_SHIFT;
+ smmu_writeq(reg64, cb_base + ARM_SMMU_CB_TTBR1);
} else {
- reg = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
- reg = pgtbl_cfg->arm_lpae_s2_cfg.vttbr >> 32;
- writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI);
+ reg64 = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
+ smmu_writeq(reg64, cb_base + ARM_SMMU_CB_TTBR0);
}
/* TTBCR */
@@ -1212,17 +1217,15 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
/* ATS1 registers can only be written atomically */
va = iova & ~0xfffUL;
-#ifdef CONFIG_64BIT
if (smmu->version == ARM_SMMU_V2)
- writeq_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR);
+ smmu_writeq(va, cb_base + ARM_SMMU_CB_ATS1PR);
else
-#endif
writel_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR);
if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,
!(tmp & ATSR_ACTIVE), 5, 50)) {
dev_err(dev,
- "iova to phys timed out on 0x%pad. Falling back to software table walk.\n",
+ "iova to phys timed out on %pad. Falling back to software table walk.\n",
&iova);
return ops->iova_to_phys(ops, iova);
}
@@ -1292,33 +1295,25 @@ static void __arm_smmu_release_pci_iommudata(void *data)
kfree(data);
}
-static int arm_smmu_add_pci_device(struct pci_dev *pdev)
+static int arm_smmu_init_pci_device(struct pci_dev *pdev,
+ struct iommu_group *group)
{
- int i, ret;
- u16 sid;
- struct iommu_group *group;
struct arm_smmu_master_cfg *cfg;
-
- group = iommu_group_get_for_dev(&pdev->dev);
- if (IS_ERR(group))
- return PTR_ERR(group);
+ u16 sid;
+ int i;
cfg = iommu_group_get_iommudata(group);
if (!cfg) {
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
- if (!cfg) {
- ret = -ENOMEM;
- goto out_put_group;
- }
+ if (!cfg)
+ return -ENOMEM;
iommu_group_set_iommudata(group, cfg,
__arm_smmu_release_pci_iommudata);
}
- if (cfg->num_streamids >= MAX_MASTER_STREAMIDS) {
- ret = -ENOSPC;
- goto out_put_group;
- }
+ if (cfg->num_streamids >= MAX_MASTER_STREAMIDS)
+ return -ENOSPC;
/*
* Assume Stream ID == Requester ID for now.
@@ -1334,16 +1329,13 @@ static int arm_smmu_add_pci_device(struct pci_dev *pdev)
cfg->streamids[cfg->num_streamids++] = sid;
return 0;
-out_put_group:
- iommu_group_put(group);
- return ret;
}
-static int arm_smmu_add_platform_device(struct device *dev)
+static int arm_smmu_init_platform_device(struct device *dev,
+ struct iommu_group *group)
{
- struct iommu_group *group;
- struct arm_smmu_master *master;
struct arm_smmu_device *smmu = find_smmu_for_device(dev);
+ struct arm_smmu_master *master;
if (!smmu)
return -ENODEV;
@@ -1352,21 +1344,20 @@ static int arm_smmu_add_platform_device(struct device *dev)
if (!master)
return -ENODEV;
- /* No automatic group creation for platform devices */
- group = iommu_group_alloc();
- if (IS_ERR(group))
- return PTR_ERR(group);
-
iommu_group_set_iommudata(group, &master->cfg, NULL);
- return iommu_group_add_device(group, dev);
+
+ return 0;
}
static int arm_smmu_add_device(struct device *dev)
{
- if (dev_is_pci(dev))
- return arm_smmu_add_pci_device(to_pci_dev(dev));
+ struct iommu_group *group;
+
+ group = iommu_group_get_for_dev(dev);
+ if (IS_ERR(group))
+ return PTR_ERR(group);
- return arm_smmu_add_platform_device(dev);
+ return 0;
}
static void arm_smmu_remove_device(struct device *dev)
@@ -1374,6 +1365,32 @@ static void arm_smmu_remove_device(struct device *dev)
iommu_group_remove_device(dev);
}
+static struct iommu_group *arm_smmu_device_group(struct device *dev)
+{
+ struct iommu_group *group;
+ int ret;
+
+ if (dev_is_pci(dev))
+ group = pci_device_group(dev);
+ else
+ group = generic_device_group(dev);
+
+ if (IS_ERR(group))
+ return group;
+
+ if (dev_is_pci(dev))
+ ret = arm_smmu_init_pci_device(to_pci_dev(dev), group);
+ else
+ ret = arm_smmu_init_platform_device(dev, group);
+
+ if (ret) {
+ iommu_group_put(group);
+ group = ERR_PTR(ret);
+ }
+
+ return group;
+}
+
static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
enum iommu_attr attr, void *data)
{
@@ -1430,6 +1447,7 @@ static struct iommu_ops arm_smmu_ops = {
.iova_to_phys = arm_smmu_iova_to_phys,
.add_device = arm_smmu_add_device,
.remove_device = arm_smmu_remove_device,
+ .device_group = arm_smmu_device_group,
.domain_get_attr = arm_smmu_domain_get_attr,
.domain_set_attr = arm_smmu_domain_set_attr,
.pgsize_bitmap = -1UL, /* Restricted during device attach */
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
new file mode 100644
index 000000000000..3a20db4f8604
--- /dev/null
+++ b/drivers/iommu/dma-iommu.c
@@ -0,0 +1,524 @@
+/*
+ * A fairly generic DMA-API to IOMMU-API glue layer.
+ *
+ * Copyright (C) 2014-2015 ARM Ltd.
+ *
+ * based in part on arch/arm/mm/dma-mapping.c:
+ * Copyright (C) 2000-2004 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/device.h>
+#include <linux/dma-iommu.h>
+#include <linux/huge_mm.h>
+#include <linux/iommu.h>
+#include <linux/iova.h>
+#include <linux/mm.h>
+
+int iommu_dma_init(void)
+{
+ return iova_cache_get();
+}
+
+/**
+ * iommu_get_dma_cookie - Acquire DMA-API resources for a domain
+ * @domain: IOMMU domain to prepare for DMA-API usage
+ *
+ * IOMMU drivers should normally call this from their domain_alloc
+ * callback when domain->type == IOMMU_DOMAIN_DMA.
+ */
+int iommu_get_dma_cookie(struct iommu_domain *domain)
+{
+ struct iova_domain *iovad;
+
+ if (domain->iova_cookie)
+ return -EEXIST;
+
+ iovad = kzalloc(sizeof(*iovad), GFP_KERNEL);
+ domain->iova_cookie = iovad;
+
+ return iovad ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(iommu_get_dma_cookie);
+
+/**
+ * iommu_put_dma_cookie - Release a domain's DMA mapping resources
+ * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
+ *
+ * IOMMU drivers should normally call this from their domain_free callback.
+ */
+void iommu_put_dma_cookie(struct iommu_domain *domain)
+{
+ struct iova_domain *iovad = domain->iova_cookie;
+
+ if (!iovad)
+ return;
+
+ put_iova_domain(iovad);
+ kfree(iovad);
+ domain->iova_cookie = NULL;
+}
+EXPORT_SYMBOL(iommu_put_dma_cookie);
+
+/**
+ * iommu_dma_init_domain - Initialise a DMA mapping domain
+ * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
+ * @base: IOVA at which the mappable address space starts
+ * @size: Size of IOVA space
+ *
+ * @base and @size should be exact multiples of IOMMU page granularity to
+ * avoid rounding surprises. If necessary, we reserve the page at address 0
+ * to ensure it is an invalid IOVA. It is safe to reinitialise a domain, but
+ * any change which could make prior IOVAs invalid will fail.
+ */
+int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, u64 size)
+{
+ struct iova_domain *iovad = domain->iova_cookie;
+ unsigned long order, base_pfn, end_pfn;
+
+ if (!iovad)
+ return -ENODEV;
+
+ /* Use the smallest supported page size for IOVA granularity */
+ order = __ffs(domain->ops->pgsize_bitmap);
+ base_pfn = max_t(unsigned long, 1, base >> order);
+ end_pfn = (base + size - 1) >> order;
+
+ /* Check the domain allows at least some access to the device... */
+ if (domain->geometry.force_aperture) {
+ if (base > domain->geometry.aperture_end ||
+ base + size <= domain->geometry.aperture_start) {
+ pr_warn("specified DMA range outside IOMMU capability\n");
+ return -EFAULT;
+ }
+ /* ...then finally give it a kicking to make sure it fits */
+ base_pfn = max_t(unsigned long, base_pfn,
+ domain->geometry.aperture_start >> order);
+ end_pfn = min_t(unsigned long, end_pfn,
+ domain->geometry.aperture_end >> order);
+ }
+
+ /* All we can safely do with an existing domain is enlarge it */
+ if (iovad->start_pfn) {
+ if (1UL << order != iovad->granule ||
+ base_pfn != iovad->start_pfn ||
+ end_pfn < iovad->dma_32bit_pfn) {
+ pr_warn("Incompatible range for DMA domain\n");
+ return -EFAULT;
+ }
+ iovad->dma_32bit_pfn = end_pfn;
+ } else {
+ init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(iommu_dma_init_domain);
+
+/**
+ * dma_direction_to_prot - Translate DMA API directions to IOMMU API page flags
+ * @dir: Direction of DMA transfer
+ * @coherent: Is the DMA master cache-coherent?
+ *
+ * Return: corresponding IOMMU API page protection flags
+ */
+int dma_direction_to_prot(enum dma_data_direction dir, bool coherent)
+{
+ int prot = coherent ? IOMMU_CACHE : 0;
+
+ switch (dir) {
+ case DMA_BIDIRECTIONAL:
+ return prot | IOMMU_READ | IOMMU_WRITE;
+ case DMA_TO_DEVICE:
+ return prot | IOMMU_READ;
+ case DMA_FROM_DEVICE:
+ return prot | IOMMU_WRITE;
+ default:
+ return 0;
+ }
+}
+
+static struct iova *__alloc_iova(struct iova_domain *iovad, size_t size,
+ dma_addr_t dma_limit)
+{
+ unsigned long shift = iova_shift(iovad);
+ unsigned long length = iova_align(iovad, size) >> shift;
+
+ /*
+ * Enforce size-alignment to be safe - there could perhaps be an
+ * attribute to control this per-device, or at least per-domain...
+ */
+ return alloc_iova(iovad, length, dma_limit >> shift, true);
+}
+
+/* The IOVA allocator knows what we mapped, so just unmap whatever that was */
+static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr)
+{
+ struct iova_domain *iovad = domain->iova_cookie;
+ unsigned long shift = iova_shift(iovad);
+ unsigned long pfn = dma_addr >> shift;
+ struct iova *iova = find_iova(iovad, pfn);
+ size_t size;
+
+ if (WARN_ON(!iova))
+ return;
+
+ size = iova_size(iova) << shift;
+ size -= iommu_unmap(domain, pfn << shift, size);
+ /* ...and if we can't, then something is horribly, horribly wrong */
+ WARN_ON(size > 0);
+ __free_iova(iovad, iova);
+}
+
+static void __iommu_dma_free_pages(struct page **pages, int count)
+{
+ while (count--)
+ __free_page(pages[count]);
+ kvfree(pages);
+}
+
+static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp)
+{
+ struct page **pages;
+ unsigned int i = 0, array_size = count * sizeof(*pages);
+
+ if (array_size <= PAGE_SIZE)
+ pages = kzalloc(array_size, GFP_KERNEL);
+ else
+ pages = vzalloc(array_size);
+ if (!pages)
+ return NULL;
+
+ /* IOMMU can map any pages, so himem can also be used here */
+ gfp |= __GFP_NOWARN | __GFP_HIGHMEM;
+
+ while (count) {
+ struct page *page = NULL;
+ int j, order = __fls(count);
+
+ /*
+ * Higher-order allocations are a convenience rather
+ * than a necessity, hence using __GFP_NORETRY until
+ * falling back to single-page allocations.
+ */
+ for (order = min(order, MAX_ORDER); order > 0; order--) {
+ page = alloc_pages(gfp | __GFP_NORETRY, order);
+ if (!page)
+ continue;
+ if (PageCompound(page)) {
+ if (!split_huge_page(page))
+ break;
+ __free_pages(page, order);
+ } else {
+ split_page(page, order);
+ break;
+ }
+ }
+ if (!page)
+ page = alloc_page(gfp);
+ if (!page) {
+ __iommu_dma_free_pages(pages, i);
+ return NULL;
+ }
+ j = 1 << order;
+ count -= j;
+ while (j--)
+ pages[i++] = page++;
+ }
+ return pages;
+}
+
+/**
+ * iommu_dma_free - Free a buffer allocated by iommu_dma_alloc()
+ * @dev: Device which owns this buffer
+ * @pages: Array of buffer pages as returned by iommu_dma_alloc()
+ * @size: Size of buffer in bytes
+ * @handle: DMA address of buffer
+ *
+ * Frees both the pages associated with the buffer, and the array
+ * describing them
+ */
+void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
+ dma_addr_t *handle)
+{
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle);
+ __iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
+ *handle = DMA_ERROR_CODE;
+}
+
+/**
+ * iommu_dma_alloc - Allocate and map a buffer contiguous in IOVA space
+ * @dev: Device to allocate memory for. Must be a real device
+ * attached to an iommu_dma_domain
+ * @size: Size of buffer in bytes
+ * @gfp: Allocation flags
+ * @prot: IOMMU mapping flags
+ * @handle: Out argument for allocated DMA handle
+ * @flush_page: Arch callback which must ensure PAGE_SIZE bytes from the
+ * given VA/PA are visible to the given non-coherent device.
+ *
+ * If @size is less than PAGE_SIZE, then a full CPU page will be allocated,
+ * but an IOMMU which supports smaller pages might not map the whole thing.
+ *
+ * Return: Array of struct page pointers describing the buffer,
+ * or NULL on failure.
+ */
+struct page **iommu_dma_alloc(struct device *dev, size_t size,
+ gfp_t gfp, int prot, dma_addr_t *handle,
+ void (*flush_page)(struct device *, const void *, phys_addr_t))
+{
+ struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+ struct iova_domain *iovad = domain->iova_cookie;
+ struct iova *iova;
+ struct page **pages;
+ struct sg_table sgt;
+ dma_addr_t dma_addr;
+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+ *handle = DMA_ERROR_CODE;
+
+ pages = __iommu_dma_alloc_pages(count, gfp);
+ if (!pages)
+ return NULL;
+
+ iova = __alloc_iova(iovad, size, dev->coherent_dma_mask);
+ if (!iova)
+ goto out_free_pages;
+
+ size = iova_align(iovad, size);
+ if (sg_alloc_table_from_pages(&sgt, pages, count, 0, size, GFP_KERNEL))
+ goto out_free_iova;
+
+ if (!(prot & IOMMU_CACHE)) {
+ struct sg_mapping_iter miter;
+ /*
+ * The CPU-centric flushing implied by SG_MITER_TO_SG isn't
+ * sufficient here, so skip it by using the "wrong" direction.
+ */
+ sg_miter_start(&miter, sgt.sgl, sgt.orig_nents, SG_MITER_FROM_SG);
+ while (sg_miter_next(&miter))
+ flush_page(dev, miter.addr, page_to_phys(miter.page));
+ sg_miter_stop(&miter);
+ }
+
+ dma_addr = iova_dma_addr(iovad, iova);
+ if (iommu_map_sg(domain, dma_addr, sgt.sgl, sgt.orig_nents, prot)
+ < size)
+ goto out_free_sg;
+
+ *handle = dma_addr;
+ sg_free_table(&sgt);
+ return pages;
+
+out_free_sg:
+ sg_free_table(&sgt);
+out_free_iova:
+ __free_iova(iovad, iova);
+out_free_pages:
+ __iommu_dma_free_pages(pages, count);
+ return NULL;
+}
+
+/**
+ * iommu_dma_mmap - Map a buffer into provided user VMA
+ * @pages: Array representing buffer from iommu_dma_alloc()
+ * @size: Size of buffer in bytes
+ * @vma: VMA describing requested userspace mapping
+ *
+ * Maps the pages of the buffer in @pages into @vma. The caller is responsible
+ * for verifying the correct size and protection of @vma beforehand.
+ */
+
+int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma)
+{
+ unsigned long uaddr = vma->vm_start;
+ unsigned int i, count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ int ret = -ENXIO;
+
+ for (i = vma->vm_pgoff; i < count && uaddr < vma->vm_end; i++) {
+ ret = vm_insert_page(vma, uaddr, pages[i]);
+ if (ret)
+ break;
+ uaddr += PAGE_SIZE;
+ }
+ return ret;
+}
+
+dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, int prot)
+{
+ dma_addr_t dma_addr;
+ struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+ struct iova_domain *iovad = domain->iova_cookie;
+ phys_addr_t phys = page_to_phys(page) + offset;
+ size_t iova_off = iova_offset(iovad, phys);
+ size_t len = iova_align(iovad, size + iova_off);
+ struct iova *iova = __alloc_iova(iovad, len, dma_get_mask(dev));
+
+ if (!iova)
+ return DMA_ERROR_CODE;
+
+ dma_addr = iova_dma_addr(iovad, iova);
+ if (iommu_map(domain, dma_addr, phys - iova_off, len, prot)) {
+ __free_iova(iovad, iova);
+ return DMA_ERROR_CODE;
+ }
+ return dma_addr + iova_off;
+}
+
+void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+}
+
+/*
+ * Prepare a successfully-mapped scatterlist to give back to the caller.
+ * Handling IOVA concatenation can come later, if needed
+ */
+static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
+ dma_addr_t dma_addr)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ /* Un-swizzling the fields here, hence the naming mismatch */
+ unsigned int s_offset = sg_dma_address(s);
+ unsigned int s_length = sg_dma_len(s);
+ unsigned int s_dma_len = s->length;
+
+ s->offset = s_offset;
+ s->length = s_length;
+ sg_dma_address(s) = dma_addr + s_offset;
+ dma_addr += s_dma_len;
+ }
+ return i;
+}
+
+/*
+ * If mapping failed, then just restore the original list,
+ * but making sure the DMA fields are invalidated.
+ */
+static void __invalidate_sg(struct scatterlist *sg, int nents)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ if (sg_dma_address(s) != DMA_ERROR_CODE)
+ s->offset = sg_dma_address(s);
+ if (sg_dma_len(s))
+ s->length = sg_dma_len(s);
+ sg_dma_address(s) = DMA_ERROR_CODE;
+ sg_dma_len(s) = 0;
+ }
+}
+
+/*
+ * The DMA API client is passing in a scatterlist which could describe
+ * any old buffer layout, but the IOMMU API requires everything to be
+ * aligned to IOMMU pages. Hence the need for this complicated bit of
+ * impedance-matching, to be able to hand off a suitably-aligned list,
+ * but still preserve the original offsets and sizes for the caller.
+ */
+int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, int prot)
+{
+ struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+ struct iova_domain *iovad = domain->iova_cookie;
+ struct iova *iova;
+ struct scatterlist *s, *prev = NULL;
+ dma_addr_t dma_addr;
+ size_t iova_len = 0;
+ int i;
+
+ /*
+ * Work out how much IOVA space we need, and align the segments to
+ * IOVA granules for the IOMMU driver to handle. With some clever
+ * trickery we can modify the list in-place, but reversibly, by
+ * hiding the original data in the as-yet-unused DMA fields.
+ */
+ for_each_sg(sg, s, nents, i) {
+ size_t s_offset = iova_offset(iovad, s->offset);
+ size_t s_length = s->length;
+
+ sg_dma_address(s) = s->offset;
+ sg_dma_len(s) = s_length;
+ s->offset -= s_offset;
+ s_length = iova_align(iovad, s_length + s_offset);
+ s->length = s_length;
+
+ /*
+ * The simple way to avoid the rare case of a segment
+ * crossing the boundary mask is to pad the previous one
+ * to end at a naturally-aligned IOVA for this one's size,
+ * at the cost of potentially over-allocating a little.
+ */
+ if (prev) {
+ size_t pad_len = roundup_pow_of_two(s_length);
+
+ pad_len = (pad_len - iova_len) & (pad_len - 1);
+ prev->length += pad_len;
+ iova_len += pad_len;
+ }
+
+ iova_len += s_length;
+ prev = s;
+ }
+
+ iova = __alloc_iova(iovad, iova_len, dma_get_mask(dev));
+ if (!iova)
+ goto out_restore_sg;
+
+ /*
+ * We'll leave any physical concatenation to the IOMMU driver's
+ * implementation - it knows better than we do.
+ */
+ dma_addr = iova_dma_addr(iovad, iova);
+ if (iommu_map_sg(domain, dma_addr, sg, nents, prot) < iova_len)
+ goto out_free_iova;
+
+ return __finalise_sg(dev, sg, nents, dma_addr);
+
+out_free_iova:
+ __free_iova(iovad, iova);
+out_restore_sg:
+ __invalidate_sg(sg, nents);
+ return 0;
+}
+
+void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+ /*
+ * The scatterlist segments are mapped into a single
+ * contiguous IOVA allocation, so this is incredibly easy.
+ */
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
+}
+
+int iommu_dma_supported(struct device *dev, u64 mask)
+{
+ /*
+ * 'Special' IOMMUs which don't have the same addressing capability
+ * as the CPU will have to wait until we have some way to query that
+ * before they'll be able to use this framework.
+ */
+ return 1;
+}
+
+int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return dma_addr == DMA_ERROR_CODE;
+}
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 8757f8dfc4e5..80e3c176008e 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1086,6 +1086,11 @@ static void free_iommu(struct intel_iommu *iommu)
iommu_device_destroy(iommu->iommu_dev);
if (iommu->irq) {
+ if (iommu->pr_irq) {
+ free_irq(iommu->pr_irq, iommu);
+ dmar_free_hwirq(iommu->pr_irq);
+ iommu->pr_irq = 0;
+ }
free_irq(iommu->irq, iommu);
dmar_free_hwirq(iommu->irq);
iommu->irq = 0;
@@ -1493,53 +1498,68 @@ static const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
}
}
+
+static inline int dmar_msi_reg(struct intel_iommu *iommu, int irq)
+{
+ if (iommu->irq == irq)
+ return DMAR_FECTL_REG;
+ else if (iommu->pr_irq == irq)
+ return DMAR_PECTL_REG;
+ else
+ BUG();
+}
+
void dmar_msi_unmask(struct irq_data *data)
{
struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
+ int reg = dmar_msi_reg(iommu, data->irq);
unsigned long flag;
/* unmask it */
raw_spin_lock_irqsave(&iommu->register_lock, flag);
- writel(0, iommu->reg + DMAR_FECTL_REG);
+ writel(0, iommu->reg + reg);
/* Read a reg to force flush the post write */
- readl(iommu->reg + DMAR_FECTL_REG);
+ readl(iommu->reg + reg);
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
void dmar_msi_mask(struct irq_data *data)
{
- unsigned long flag;
struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
+ int reg = dmar_msi_reg(iommu, data->irq);
+ unsigned long flag;
/* mask it */
raw_spin_lock_irqsave(&iommu->register_lock, flag);
- writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
+ writel(DMA_FECTL_IM, iommu->reg + reg);
/* Read a reg to force flush the post write */
- readl(iommu->reg + DMAR_FECTL_REG);
+ readl(iommu->reg + reg);
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
void dmar_msi_write(int irq, struct msi_msg *msg)
{
struct intel_iommu *iommu = irq_get_handler_data(irq);
+ int reg = dmar_msi_reg(iommu, irq);
unsigned long flag;
raw_spin_lock_irqsave(&iommu->register_lock, flag);
- writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
- writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
- writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
+ writel(msg->data, iommu->reg + reg + 4);
+ writel(msg->address_lo, iommu->reg + reg + 8);
+ writel(msg->address_hi, iommu->reg + reg + 12);
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
void dmar_msi_read(int irq, struct msi_msg *msg)
{
struct intel_iommu *iommu = irq_get_handler_data(irq);
+ int reg = dmar_msi_reg(iommu, irq);
unsigned long flag;
raw_spin_lock_irqsave(&iommu->register_lock, flag);
- msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
- msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
- msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
+ msg->data = readl(iommu->reg + reg + 4);
+ msg->address_lo = readl(iommu->reg + reg + 8);
+ msg->address_hi = readl(iommu->reg + reg + 12);
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 2570f2a25dc4..a34355fca37a 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -20,11 +20,11 @@
#include "fsl_pamu.h"
+#include <linux/fsl/guts.h>
#include <linux/interrupt.h>
#include <linux/genalloc.h>
#include <asm/mpc85xx.h>
-#include <asm/fsl_guts.h>
/* define indexes for each operation mapping scenario */
#define OMI_QMAN 0x00
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 1d452930c890..da0e1e30ef37 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -923,7 +923,7 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl);
/* We can partition PCIe devices so assign device group to the device */
if (pci_endpt_partioning) {
- group = iommu_group_get_for_dev(&pdev->dev);
+ group = pci_device_group(&pdev->dev);
/*
* PCIe controller is not a paritionable entity
@@ -956,44 +956,34 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
return group;
}
-static int fsl_pamu_add_device(struct device *dev)
+static struct iommu_group *fsl_pamu_device_group(struct device *dev)
{
struct iommu_group *group = ERR_PTR(-ENODEV);
- struct pci_dev *pdev;
- const u32 *prop;
- int ret = 0, len;
+ int len;
/*
* For platform devices we allocate a separate group for
* each of the devices.
*/
- if (dev_is_pci(dev)) {
- pdev = to_pci_dev(dev);
- /* Don't create device groups for virtual PCI bridges */
- if (pdev->subordinate)
- return 0;
+ if (dev_is_pci(dev))
+ group = get_pci_device_group(to_pci_dev(dev));
+ else if (of_get_property(dev->of_node, "fsl,liodn", &len))
+ group = get_device_iommu_group(dev);
- group = get_pci_device_group(pdev);
+ return group;
+}
- } else {
- prop = of_get_property(dev->of_node, "fsl,liodn", &len);
- if (prop)
- group = get_device_iommu_group(dev);
- }
+static int fsl_pamu_add_device(struct device *dev)
+{
+ struct iommu_group *group;
+ group = iommu_group_get_for_dev(dev);
if (IS_ERR(group))
return PTR_ERR(group);
- /*
- * Check if device has already been added to an iommu group.
- * Group could have already been created for a PCI device in
- * the iommu_group_get_for_dev path.
- */
- if (!dev->iommu_group)
- ret = iommu_group_add_device(group, dev);
-
iommu_group_put(group);
- return ret;
+
+ return 0;
}
static void fsl_pamu_remove_device(struct device *dev)
@@ -1072,6 +1062,7 @@ static const struct iommu_ops fsl_pamu_ops = {
.domain_get_attr = fsl_pamu_get_domain_attr,
.add_device = fsl_pamu_add_device,
.remove_device = fsl_pamu_remove_device,
+ .device_group = fsl_pamu_device_group,
};
int __init pamu_domain_init(void)
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 041bc1810a86..f1042daef9ad 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -34,6 +34,7 @@
#include <linux/mempool.h>
#include <linux/memory.h>
#include <linux/timer.h>
+#include <linux/io.h>
#include <linux/iova.h>
#include <linux/iommu.h>
#include <linux/intel-iommu.h>
@@ -418,10 +419,13 @@ struct device_domain_info {
struct list_head global; /* link to global list */
u8 bus; /* PCI bus number */
u8 devfn; /* PCI devfn number */
- struct {
- u8 enabled:1;
- u8 qdep;
- } ats; /* ATS state */
+ u8 pasid_supported:3;
+ u8 pasid_enabled:1;
+ u8 pri_supported:1;
+ u8 pri_enabled:1;
+ u8 ats_supported:1;
+ u8 ats_enabled:1;
+ u8 ats_qdep;
struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
struct intel_iommu *iommu; /* IOMMU used by this device */
struct dmar_domain *domain; /* pointer to domain */
@@ -497,13 +501,37 @@ static int dmar_forcedac;
static int intel_iommu_strict;
static int intel_iommu_superpage = 1;
static int intel_iommu_ecs = 1;
+static int intel_iommu_pasid28;
+static int iommu_identity_mapping;
+
+#define IDENTMAP_ALL 1
+#define IDENTMAP_GFX 2
+#define IDENTMAP_AZALIA 4
-/* We only actually use ECS when PASID support (on the new bit 40)
- * is also advertised. Some early implementations — the ones with
- * PASID support on bit 28 — have issues even when we *only* use
- * extended root/context tables. */
+/* Broadwell and Skylake have broken ECS support — normal so-called "second
+ * level" translation of DMA requests-without-PASID doesn't actually happen
+ * unless you also set the NESTE bit in an extended context-entry. Which of
+ * course means that SVM doesn't work because it's trying to do nested
+ * translation of the physical addresses it finds in the process page tables,
+ * through the IOVA->phys mapping found in the "second level" page tables.
+ *
+ * The VT-d specification was retroactively changed to change the definition
+ * of the capability bits and pretend that Broadwell/Skylake never happened...
+ * but unfortunately the wrong bit was changed. It's ECS which is broken, but
+ * for some reason it was the PASID capability bit which was redefined (from
+ * bit 28 on BDW/SKL to bit 40 in future).
+ *
+ * So our test for ECS needs to eschew those implementations which set the old
+ * PASID capabiity bit 28, since those are the ones on which ECS is broken.
+ * Unless we are working around the 'pasid28' limitations, that is, by putting
+ * the device into passthrough mode for normal DMA and thus masking the bug.
+ */
#define ecs_enabled(iommu) (intel_iommu_ecs && ecap_ecs(iommu->ecap) && \
- ecap_pasid(iommu->ecap))
+ (intel_iommu_pasid28 || !ecap_broken_pasid(iommu->ecap)))
+/* PASID support is thus enabled if ECS is enabled and *either* of the old
+ * or new capability bits are set. */
+#define pasid_enabled(iommu) (ecs_enabled(iommu) && \
+ (ecap_pasid(iommu->ecap) || ecap_broken_pasid(iommu->ecap)))
int intel_iommu_gfx_mapped;
EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
@@ -566,6 +594,11 @@ static int __init intel_iommu_setup(char *str)
printk(KERN_INFO
"Intel-IOMMU: disable extended context table support\n");
intel_iommu_ecs = 0;
+ } else if (!strncmp(str, "pasid28", 7)) {
+ printk(KERN_INFO
+ "Intel-IOMMU: enable pre-production PASID support\n");
+ intel_iommu_pasid28 = 1;
+ iommu_identity_mapping |= IDENTMAP_GFX;
}
str += strcspn(str, ",");
@@ -1407,37 +1440,22 @@ static struct device_domain_info *
iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
u8 bus, u8 devfn)
{
- bool found = false;
struct device_domain_info *info;
- struct pci_dev *pdev;
assert_spin_locked(&device_domain_lock);
- if (!ecap_dev_iotlb_support(iommu->ecap))
- return NULL;
-
if (!iommu->qi)
return NULL;
list_for_each_entry(info, &domain->devices, link)
if (info->iommu == iommu && info->bus == bus &&
info->devfn == devfn) {
- found = true;
+ if (info->ats_supported && info->dev)
+ return info;
break;
}
- if (!found || !info->dev || !dev_is_pci(info->dev))
- return NULL;
-
- pdev = to_pci_dev(info->dev);
-
- if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS))
- return NULL;
-
- if (!dmar_find_matched_atsr_unit(pdev))
- return NULL;
-
- return info;
+ return NULL;
}
static void iommu_enable_dev_iotlb(struct device_domain_info *info)
@@ -1448,20 +1466,48 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info)
return;
pdev = to_pci_dev(info->dev);
- if (pci_enable_ats(pdev, VTD_PAGE_SHIFT))
- return;
- info->ats.enabled = 1;
- info->ats.qdep = pci_ats_queue_depth(pdev);
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ /* The PCIe spec, in its wisdom, declares that the behaviour of
+ the device if you enable PASID support after ATS support is
+ undefined. So always enable PASID support on devices which
+ have it, even if we can't yet know if we're ever going to
+ use it. */
+ if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
+ info->pasid_enabled = 1;
+
+ if (info->pri_supported && !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
+ info->pri_enabled = 1;
+#endif
+ if (info->ats_supported && !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
+ info->ats_enabled = 1;
+ info->ats_qdep = pci_ats_queue_depth(pdev);
+ }
}
static void iommu_disable_dev_iotlb(struct device_domain_info *info)
{
- if (!info->ats.enabled)
+ struct pci_dev *pdev;
+
+ if (dev_is_pci(info->dev))
return;
- pci_disable_ats(to_pci_dev(info->dev));
- info->ats.enabled = 0;
+ pdev = to_pci_dev(info->dev);
+
+ if (info->ats_enabled) {
+ pci_disable_ats(pdev);
+ info->ats_enabled = 0;
+ }
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ if (info->pri_enabled) {
+ pci_disable_pri(pdev);
+ info->pri_enabled = 0;
+ }
+ if (info->pasid_enabled) {
+ pci_disable_pasid(pdev);
+ info->pasid_enabled = 0;
+ }
+#endif
}
static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
@@ -1473,11 +1519,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
spin_lock_irqsave(&device_domain_lock, flags);
list_for_each_entry(info, &domain->devices, link) {
- if (!info->ats.enabled)
+ if (!info->ats_enabled)
continue;
sid = info->bus << 8 | info->devfn;
- qdep = info->ats.qdep;
+ qdep = info->ats_qdep;
qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
}
spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -1667,6 +1713,14 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
/* free context mapping */
free_context_table(iommu);
+
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ if (pasid_enabled(iommu)) {
+ if (ecap_prs(iommu->ecap))
+ intel_svm_finish_prq(iommu);
+ intel_svm_free_pasid_tables(iommu);
+ }
+#endif
}
static struct dmar_domain *alloc_domain(int flags)
@@ -1934,8 +1988,10 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
}
info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
- translation = info ? CONTEXT_TT_DEV_IOTLB :
- CONTEXT_TT_MULTI_LEVEL;
+ if (info && info->ats_supported)
+ translation = CONTEXT_TT_DEV_IOTLB;
+ else
+ translation = CONTEXT_TT_MULTI_LEVEL;
context_set_address_root(context, virt_to_phys(pgd));
context_set_address_width(context, iommu->agaw);
@@ -2115,15 +2171,19 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
return -ENOMEM;
/* It is large page*/
if (largepage_lvl > 1) {
+ unsigned long nr_superpages, end_pfn;
+
pteval |= DMA_PTE_LARGE_PAGE;
lvl_pages = lvl_to_nr_pages(largepage_lvl);
+
+ nr_superpages = sg_res / lvl_pages;
+ end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
+
/*
* Ensure that old small page tables are
- * removed to make room for superpage,
- * if they exist.
+ * removed to make room for superpage(s).
*/
- dma_pte_free_pagetable(domain, iov_pfn,
- iov_pfn + lvl_pages - 1);
+ dma_pte_free_pagetable(domain, iov_pfn, end_pfn);
} else {
pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
}
@@ -2269,12 +2329,34 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
info->bus = bus;
info->devfn = devfn;
- info->ats.enabled = 0;
- info->ats.qdep = 0;
+ info->ats_supported = info->pasid_supported = info->pri_supported = 0;
+ info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
+ info->ats_qdep = 0;
info->dev = dev;
info->domain = domain;
info->iommu = iommu;
+ if (dev && dev_is_pci(dev)) {
+ struct pci_dev *pdev = to_pci_dev(info->dev);
+
+ if (ecap_dev_iotlb_support(iommu->ecap) &&
+ pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
+ dmar_find_matched_atsr_unit(pdev))
+ info->ats_supported = 1;
+
+ if (ecs_enabled(iommu)) {
+ if (pasid_enabled(iommu)) {
+ int features = pci_pasid_features(pdev);
+ if (features >= 0)
+ info->pasid_supported = features | 1;
+ }
+
+ if (info->ats_supported && ecap_prs(iommu->ecap) &&
+ pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI))
+ info->pri_supported = 1;
+ }
+ }
+
spin_lock_irqsave(&device_domain_lock, flags);
if (dev)
found = find_domain(dev);
@@ -2301,6 +2383,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
if (ret) {
spin_unlock_irqrestore(&device_domain_lock, flags);
+ free_devinfo_mem(info);
return NULL;
}
@@ -2399,11 +2482,6 @@ found_domain:
return domain;
}
-static int iommu_identity_mapping;
-#define IDENTMAP_ALL 1
-#define IDENTMAP_GFX 2
-#define IDENTMAP_AZALIA 4
-
static int iommu_domain_identity_map(struct dmar_domain *domain,
unsigned long long start,
unsigned long long end)
@@ -2429,17 +2507,11 @@ static int iommu_domain_identity_map(struct dmar_domain *domain,
DMA_PTE_READ|DMA_PTE_WRITE);
}
-static int iommu_prepare_identity_map(struct device *dev,
- unsigned long long start,
- unsigned long long end)
+static int domain_prepare_identity_map(struct device *dev,
+ struct dmar_domain *domain,
+ unsigned long long start,
+ unsigned long long end)
{
- struct dmar_domain *domain;
- int ret;
-
- domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
- if (!domain)
- return -ENOMEM;
-
/* For _hardware_ passthrough, don't bother. But for software
passthrough, we do it anyway -- it may indicate a memory
range which is reserved in E820, so which didn't get set
@@ -2459,8 +2531,7 @@ static int iommu_prepare_identity_map(struct device *dev,
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
- ret = -EIO;
- goto error;
+ return -EIO;
}
if (end >> agaw_to_width(domain->agaw)) {
@@ -2470,18 +2541,27 @@ static int iommu_prepare_identity_map(struct device *dev,
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
- ret = -EIO;
- goto error;
+ return -EIO;
}
- ret = iommu_domain_identity_map(domain, start, end);
- if (ret)
- goto error;
+ return iommu_domain_identity_map(domain, start, end);
+}
- return 0;
+static int iommu_prepare_identity_map(struct device *dev,
+ unsigned long long start,
+ unsigned long long end)
+{
+ struct dmar_domain *domain;
+ int ret;
+
+ domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ if (!domain)
+ return -ENOMEM;
+
+ ret = domain_prepare_identity_map(dev, domain, start, end);
+ if (ret)
+ domain_exit(domain);
- error:
- domain_exit(domain);
return ret;
}
@@ -2807,18 +2887,18 @@ static void intel_iommu_init_qi(struct intel_iommu *iommu)
}
static int copy_context_table(struct intel_iommu *iommu,
- struct root_entry __iomem *old_re,
+ struct root_entry *old_re,
struct context_entry **tbl,
int bus, bool ext)
{
int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
- struct context_entry __iomem *old_ce = NULL;
struct context_entry *new_ce = NULL, ce;
+ struct context_entry *old_ce = NULL;
struct root_entry re;
phys_addr_t old_ce_phys;
tbl_idx = ext ? bus * 2 : bus;
- memcpy_fromio(&re, old_re, sizeof(re));
+ memcpy(&re, old_re, sizeof(re));
for (devfn = 0; devfn < 256; devfn++) {
/* First calculate the correct index */
@@ -2853,7 +2933,8 @@ static int copy_context_table(struct intel_iommu *iommu,
}
ret = -ENOMEM;
- old_ce = ioremap_cache(old_ce_phys, PAGE_SIZE);
+ old_ce = memremap(old_ce_phys, PAGE_SIZE,
+ MEMREMAP_WB);
if (!old_ce)
goto out;
@@ -2865,7 +2946,7 @@ static int copy_context_table(struct intel_iommu *iommu,
}
/* Now copy the context entry */
- memcpy_fromio(&ce, old_ce + idx, sizeof(ce));
+ memcpy(&ce, old_ce + idx, sizeof(ce));
if (!__context_present(&ce))
continue;
@@ -2901,7 +2982,7 @@ static int copy_context_table(struct intel_iommu *iommu,
__iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
out_unmap:
- iounmap(old_ce);
+ memunmap(old_ce);
out:
return ret;
@@ -2909,8 +2990,8 @@ out:
static int copy_translation_tables(struct intel_iommu *iommu)
{
- struct root_entry __iomem *old_rt;
struct context_entry **ctxt_tbls;
+ struct root_entry *old_rt;
phys_addr_t old_rt_phys;
int ctxt_table_entries;
unsigned long flags;
@@ -2935,7 +3016,7 @@ static int copy_translation_tables(struct intel_iommu *iommu)
if (!old_rt_phys)
return -EINVAL;
- old_rt = ioremap_cache(old_rt_phys, PAGE_SIZE);
+ old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
if (!old_rt)
return -ENOMEM;
@@ -2984,7 +3065,7 @@ static int copy_translation_tables(struct intel_iommu *iommu)
ret = 0;
out_unmap:
- iounmap(old_rt);
+ memunmap(old_rt);
return ret;
}
@@ -3095,6 +3176,10 @@ static int __init init_dmars(void)
if (!ecap_pass_through(iommu->ecap))
hw_pass_through = 0;
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ if (pasid_enabled(iommu))
+ intel_svm_alloc_pasid_tables(iommu);
+#endif
}
if (iommu_pass_through)
@@ -3182,6 +3267,13 @@ domains_done:
iommu_flush_write_buffer(iommu);
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ if (pasid_enabled(iommu) && ecap_prs(iommu->ecap)) {
+ ret = intel_svm_enable_prq(iommu);
+ if (ret)
+ goto free_iommu;
+ }
+#endif
ret = dmar_set_interrupt(iommu);
if (ret)
goto free_iommu;
@@ -3241,7 +3333,10 @@ static struct iova *intel_alloc_iova(struct device *dev,
static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
{
+ struct dmar_rmrr_unit *rmrr;
struct dmar_domain *domain;
+ struct device *i_dev;
+ int i, ret;
domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
if (!domain) {
@@ -3250,6 +3345,23 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
return NULL;
}
+ /* We have a new domain - setup possible RMRRs for the device */
+ rcu_read_lock();
+ for_each_rmrr_units(rmrr) {
+ for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
+ i, i_dev) {
+ if (i_dev != dev)
+ continue;
+
+ ret = domain_prepare_identity_map(dev, domain,
+ rmrr->base_address,
+ rmrr->end_address);
+ if (ret)
+ dev_err(dev, "Mapping reserved region failed\n");
+ }
+ }
+ rcu_read_unlock();
+
return domain;
}
@@ -3535,7 +3647,7 @@ static void *intel_alloc_coherent(struct device *dev, size_t size,
flags |= GFP_DMA32;
}
- if (flags & __GFP_WAIT) {
+ if (gfpflags_allow_blocking(flags)) {
unsigned int count = size >> PAGE_SHIFT;
page = dma_alloc_from_contiguous(dev, count, order);
@@ -4110,6 +4222,11 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
if (ret)
goto out;
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ if (pasid_enabled(iommu))
+ intel_svm_alloc_pasid_tables(iommu);
+#endif
+
if (dmaru->ignored) {
/*
* we always have to disable PMRs or DMA may fail on this device
@@ -4121,6 +4238,14 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
intel_iommu_init_qi(iommu);
iommu_flush_write_buffer(iommu);
+
+#ifdef CONFIG_INTEL_IOMMU_SVM
+ if (pasid_enabled(iommu) && ecap_prs(iommu->ecap)) {
+ ret = intel_svm_enable_prq(iommu);
+ if (ret)
+ goto disable_iommu;
+ }
+#endif
ret = dmar_set_interrupt(iommu);
if (ret)
goto disable_iommu;
@@ -4189,14 +4314,17 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
dev = pci_physfn(dev);
for (bus = dev->bus; bus; bus = bus->parent) {
bridge = bus->self;
- if (!bridge || !pci_is_pcie(bridge) ||
+ /* If it's an integrated device, allow ATS */
+ if (!bridge)
+ return 1;
+ /* Connected via non-PCIe: no ATS */
+ if (!pci_is_pcie(bridge) ||
pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
return 0;
+ /* If we found the root port, look it up in the ATSR */
if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
break;
}
- if (!bridge)
- return 0;
rcu_read_lock();
list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
@@ -4860,6 +4988,114 @@ static void intel_iommu_remove_device(struct device *dev)
iommu_device_unlink(iommu->iommu_dev, dev);
}
+#ifdef CONFIG_INTEL_IOMMU_SVM
+int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
+{
+ struct device_domain_info *info;
+ struct context_entry *context;
+ struct dmar_domain *domain;
+ unsigned long flags;
+ u64 ctx_lo;
+ int ret;
+
+ domain = get_valid_domain_for_dev(sdev->dev);
+ if (!domain)
+ return -EINVAL;
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+ spin_lock(&iommu->lock);
+
+ ret = -EINVAL;
+ info = sdev->dev->archdata.iommu;
+ if (!info || !info->pasid_supported)
+ goto out;
+
+ context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
+ if (WARN_ON(!context))
+ goto out;
+
+ ctx_lo = context[0].lo;
+
+ sdev->did = domain->iommu_did[iommu->seq_id];
+ sdev->sid = PCI_DEVID(info->bus, info->devfn);
+
+ if (!(ctx_lo & CONTEXT_PASIDE)) {
+ context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
+ context[1].lo = (u64)virt_to_phys(iommu->pasid_table) | ecap_pss(iommu->ecap);
+ wmb();
+ /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
+ * extended to permit requests-with-PASID if the PASIDE bit
+ * is set. which makes sense. For CONTEXT_TT_PASS_THROUGH,
+ * however, the PASIDE bit is ignored and requests-with-PASID
+ * are unconditionally blocked. Which makes less sense.
+ * So convert from CONTEXT_TT_PASS_THROUGH to one of the new
+ * "guest mode" translation types depending on whether ATS
+ * is available or not. Annoyingly, we can't use the new
+ * modes *unless* PASIDE is set. */
+ if ((ctx_lo & CONTEXT_TT_MASK) == (CONTEXT_TT_PASS_THROUGH << 2)) {
+ ctx_lo &= ~CONTEXT_TT_MASK;
+ if (info->ats_supported)
+ ctx_lo |= CONTEXT_TT_PT_PASID_DEV_IOTLB << 2;
+ else
+ ctx_lo |= CONTEXT_TT_PT_PASID << 2;
+ }
+ ctx_lo |= CONTEXT_PASIDE;
+ if (iommu->pasid_state_table)
+ ctx_lo |= CONTEXT_DINVE;
+ if (info->pri_supported)
+ ctx_lo |= CONTEXT_PRS;
+ context[0].lo = ctx_lo;
+ wmb();
+ iommu->flush.flush_context(iommu, sdev->did, sdev->sid,
+ DMA_CCMD_MASK_NOBIT,
+ DMA_CCMD_DEVICE_INVL);
+ }
+
+ /* Enable PASID support in the device, if it wasn't already */
+ if (!info->pasid_enabled)
+ iommu_enable_dev_iotlb(info);
+
+ if (info->ats_enabled) {
+ sdev->dev_iotlb = 1;
+ sdev->qdep = info->ats_qdep;
+ if (sdev->qdep >= QI_DEV_EIOTLB_MAX_INVS)
+ sdev->qdep = 0;
+ }
+ ret = 0;
+
+ out:
+ spin_unlock(&iommu->lock);
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+
+ return ret;
+}
+
+struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
+{
+ struct intel_iommu *iommu;
+ u8 bus, devfn;
+
+ if (iommu_dummy(dev)) {
+ dev_warn(dev,
+ "No IOMMU translation for device; cannot enable SVM\n");
+ return NULL;
+ }
+
+ iommu = device_to_iommu(dev, &bus, &devfn);
+ if ((!iommu)) {
+ dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
+ return NULL;
+ }
+
+ if (!iommu->pasid_table) {
+ dev_err(dev, "PASID not enabled on IOMMU; cannot enable SVM\n");
+ return NULL;
+ }
+
+ return iommu;
+}
+#endif /* CONFIG_INTEL_IOMMU_SVM */
+
static const struct iommu_ops intel_iommu_ops = {
.capable = intel_iommu_capable,
.domain_alloc = intel_iommu_domain_alloc,
@@ -4872,6 +5108,7 @@ static const struct iommu_ops intel_iommu_ops = {
.iova_to_phys = intel_iommu_iova_to_phys,
.add_device = intel_iommu_add_device,
.remove_device = intel_iommu_remove_device,
+ .device_group = pci_device_group,
.pgsize_bitmap = INTEL_IOMMU_PGSIZES,
};
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
new file mode 100644
index 000000000000..c69e3f9ec958
--- /dev/null
+++ b/drivers/iommu/intel-svm.c
@@ -0,0 +1,602 @@
+/*
+ * Copyright © 2015 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.
+ *
+ * Authors: David Woodhouse <dwmw2@infradead.org>
+ */
+
+#include <linux/intel-iommu.h>
+#include <linux/mmu_notifier.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/intel-svm.h>
+#include <linux/rculist.h>
+#include <linux/pci.h>
+#include <linux/pci-ats.h>
+#include <linux/dmar.h>
+#include <linux/interrupt.h>
+
+static irqreturn_t prq_event_thread(int irq, void *d);
+
+struct pasid_entry {
+ u64 val;
+};
+
+struct pasid_state_entry {
+ u64 val;
+};
+
+int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu)
+{
+ struct page *pages;
+ int order;
+
+ order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT;
+ if (order < 0)
+ order = 0;
+
+ pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
+ if (!pages) {
+ pr_warn("IOMMU: %s: Failed to allocate PASID table\n",
+ iommu->name);
+ return -ENOMEM;
+ }
+ iommu->pasid_table = page_address(pages);
+ pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order);
+
+ if (ecap_dis(iommu->ecap)) {
+ pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
+ if (pages)
+ iommu->pasid_state_table = page_address(pages);
+ else
+ pr_warn("IOMMU: %s: Failed to allocate PASID state table\n",
+ iommu->name);
+ }
+
+ idr_init(&iommu->pasid_idr);
+
+ return 0;
+}
+
+int intel_svm_free_pasid_tables(struct intel_iommu *iommu)
+{
+ int order;
+
+ order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT;
+ if (order < 0)
+ order = 0;
+
+ if (iommu->pasid_table) {
+ free_pages((unsigned long)iommu->pasid_table, order);
+ iommu->pasid_table = NULL;
+ }
+ if (iommu->pasid_state_table) {
+ free_pages((unsigned long)iommu->pasid_state_table, order);
+ iommu->pasid_state_table = NULL;
+ }
+ idr_destroy(&iommu->pasid_idr);
+ return 0;
+}
+
+#define PRQ_ORDER 0
+
+int intel_svm_enable_prq(struct intel_iommu *iommu)
+{
+ struct page *pages;
+ int irq, ret;
+
+ pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
+ if (!pages) {
+ pr_warn("IOMMU: %s: Failed to allocate page request queue\n",
+ iommu->name);
+ return -ENOMEM;
+ }
+ iommu->prq = page_address(pages);
+
+ irq = dmar_alloc_hwirq(DMAR_UNITS_SUPPORTED + iommu->seq_id, iommu->node, iommu);
+ if (irq <= 0) {
+ pr_err("IOMMU: %s: Failed to create IRQ vector for page request queue\n",
+ iommu->name);
+ ret = -EINVAL;
+ err:
+ free_pages((unsigned long)iommu->prq, PRQ_ORDER);
+ iommu->prq = NULL;
+ return ret;
+ }
+ iommu->pr_irq = irq;
+
+ snprintf(iommu->prq_name, sizeof(iommu->prq_name), "dmar%d-prq", iommu->seq_id);
+
+ ret = request_threaded_irq(irq, NULL, prq_event_thread, IRQF_ONESHOT,
+ iommu->prq_name, iommu);
+ if (ret) {
+ pr_err("IOMMU: %s: Failed to request IRQ for page request queue\n",
+ iommu->name);
+ dmar_free_hwirq(irq);
+ goto err;
+ }
+ dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQA_REG, virt_to_phys(iommu->prq) | PRQ_ORDER);
+
+ return 0;
+}
+
+int intel_svm_finish_prq(struct intel_iommu *iommu)
+{
+ dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQA_REG, 0ULL);
+
+ free_irq(iommu->pr_irq, iommu);
+ dmar_free_hwirq(iommu->pr_irq);
+ iommu->pr_irq = 0;
+
+ free_pages((unsigned long)iommu->prq, PRQ_ORDER);
+ iommu->prq = NULL;
+
+ return 0;
+}
+
+static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev,
+ unsigned long address, unsigned long pages, int ih, int gl)
+{
+ struct qi_desc desc;
+
+ if (pages == -1) {
+ /* For global kernel pages we have to flush them in *all* PASIDs
+ * because that's the only option the hardware gives us. Despite
+ * the fact that they are actually only accessible through one. */
+ if (gl)
+ desc.low = QI_EIOTLB_PASID(svm->pasid) | QI_EIOTLB_DID(sdev->did) |
+ QI_EIOTLB_GRAN(QI_GRAN_ALL_ALL) | QI_EIOTLB_TYPE;
+ else
+ desc.low = QI_EIOTLB_PASID(svm->pasid) | QI_EIOTLB_DID(sdev->did) |
+ QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) | QI_EIOTLB_TYPE;
+ desc.high = 0;
+ } else {
+ int mask = ilog2(__roundup_pow_of_two(pages));
+
+ desc.low = QI_EIOTLB_PASID(svm->pasid) | QI_EIOTLB_DID(sdev->did) |
+ QI_EIOTLB_GRAN(QI_GRAN_PSI_PASID) | QI_EIOTLB_TYPE;
+ desc.high = QI_EIOTLB_ADDR(address) | QI_EIOTLB_GL(gl) |
+ QI_EIOTLB_IH(ih) | QI_EIOTLB_AM(mask);
+ }
+ qi_submit_sync(&desc, svm->iommu);
+
+ if (sdev->dev_iotlb) {
+ desc.low = QI_DEV_EIOTLB_PASID(svm->pasid) | QI_DEV_EIOTLB_SID(sdev->sid) |
+ QI_DEV_EIOTLB_QDEP(sdev->qdep) | QI_DEIOTLB_TYPE;
+ if (pages == -1) {
+ desc.high = QI_DEV_EIOTLB_ADDR(-1ULL >> 1) | QI_DEV_EIOTLB_SIZE;
+ } else if (pages > 1) {
+ /* The least significant zero bit indicates the size. So,
+ * for example, an "address" value of 0x12345f000 will
+ * flush from 0x123440000 to 0x12347ffff (256KiB). */
+ unsigned long last = address + ((unsigned long)(pages - 1) << VTD_PAGE_SHIFT);
+ unsigned long mask = __rounddown_pow_of_two(address ^ last);;
+
+ desc.high = QI_DEV_EIOTLB_ADDR((address & ~mask) | (mask - 1)) | QI_DEV_EIOTLB_SIZE;
+ } else {
+ desc.high = QI_DEV_EIOTLB_ADDR(address);
+ }
+ qi_submit_sync(&desc, svm->iommu);
+ }
+}
+
+static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
+ unsigned long pages, int ih, int gl)
+{
+ struct intel_svm_dev *sdev;
+
+ /* Try deferred invalidate if available */
+ if (svm->iommu->pasid_state_table &&
+ !cmpxchg64(&svm->iommu->pasid_state_table[svm->pasid].val, 0, 1ULL << 63))
+ return;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdev, &svm->devs, list)
+ intel_flush_svm_range_dev(svm, sdev, address, pages, ih, gl);
+ rcu_read_unlock();
+}
+
+static void intel_change_pte(struct mmu_notifier *mn, struct mm_struct *mm,
+ unsigned long address, pte_t pte)
+{
+ struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
+
+ intel_flush_svm_range(svm, address, 1, 1, 0);
+}
+
+static void intel_invalidate_page(struct mmu_notifier *mn, struct mm_struct *mm,
+ unsigned long address)
+{
+ struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
+
+ intel_flush_svm_range(svm, address, 1, 1, 0);
+}
+
+/* Pages have been freed at this point */
+static void intel_invalidate_range(struct mmu_notifier *mn,
+ struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+ struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
+
+ intel_flush_svm_range(svm, start,
+ (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 0, 0);
+}
+
+
+static void intel_flush_pasid_dev(struct intel_svm *svm, struct intel_svm_dev *sdev, int pasid)
+{
+ struct qi_desc desc;
+
+ desc.high = 0;
+ desc.low = QI_PC_TYPE | QI_PC_DID(sdev->did) | QI_PC_PASID_SEL | QI_PC_PASID(pasid);
+
+ qi_submit_sync(&desc, svm->iommu);
+}
+
+static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
+{
+ struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
+
+ svm->iommu->pasid_table[svm->pasid].val = 0;
+
+ /* There's no need to do any flush because we can't get here if there
+ * are any devices left anyway. */
+ WARN_ON(!list_empty(&svm->devs));
+}
+
+static const struct mmu_notifier_ops intel_mmuops = {
+ .release = intel_mm_release,
+ .change_pte = intel_change_pte,
+ .invalidate_page = intel_invalidate_page,
+ .invalidate_range = intel_invalidate_range,
+};
+
+static DEFINE_MUTEX(pasid_mutex);
+
+int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops)
+{
+ struct intel_iommu *iommu = intel_svm_device_to_iommu(dev);
+ struct intel_svm_dev *sdev;
+ struct intel_svm *svm = NULL;
+ struct mm_struct *mm = NULL;
+ int pasid_max;
+ int ret;
+
+ if (WARN_ON(!iommu))
+ return -EINVAL;
+
+ if (dev_is_pci(dev)) {
+ pasid_max = pci_max_pasids(to_pci_dev(dev));
+ if (pasid_max < 0)
+ return -EINVAL;
+ } else
+ pasid_max = 1 << 20;
+
+ if ((flags & SVM_FLAG_SUPERVISOR_MODE)) {
+ if (!ecap_srs(iommu->ecap))
+ return -EINVAL;
+ } else if (pasid) {
+ mm = get_task_mm(current);
+ BUG_ON(!mm);
+ }
+
+ mutex_lock(&pasid_mutex);
+ if (pasid && !(flags & SVM_FLAG_PRIVATE_PASID)) {
+ int i;
+
+ idr_for_each_entry(&iommu->pasid_idr, svm, i) {
+ if (svm->mm != mm ||
+ (svm->flags & SVM_FLAG_PRIVATE_PASID))
+ continue;
+
+ if (svm->pasid >= pasid_max) {
+ dev_warn(dev,
+ "Limited PASID width. Cannot use existing PASID %d\n",
+ svm->pasid);
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ list_for_each_entry(sdev, &svm->devs, list) {
+ if (dev == sdev->dev) {
+ if (sdev->ops != ops) {
+ ret = -EBUSY;
+ goto out;
+ }
+ sdev->users++;
+ goto success;
+ }
+ }
+
+ break;
+ }
+ }
+
+ sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+ if (!sdev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ sdev->dev = dev;
+
+ ret = intel_iommu_enable_pasid(iommu, sdev);
+ if (ret || !pasid) {
+ /* If they don't actually want to assign a PASID, this is
+ * just an enabling check/preparation. */
+ kfree(sdev);
+ goto out;
+ }
+ /* Finish the setup now we know we're keeping it */
+ sdev->users = 1;
+ sdev->ops = ops;
+ init_rcu_head(&sdev->rcu);
+
+ if (!svm) {
+ svm = kzalloc(sizeof(*svm), GFP_KERNEL);
+ if (!svm) {
+ ret = -ENOMEM;
+ kfree(sdev);
+ goto out;
+ }
+ svm->iommu = iommu;
+
+ if (pasid_max > 2 << ecap_pss(iommu->ecap))
+ pasid_max = 2 << ecap_pss(iommu->ecap);
+
+ /* Do not use PASID 0 in caching mode (virtualised IOMMU) */
+ ret = idr_alloc(&iommu->pasid_idr, svm,
+ !!cap_caching_mode(iommu->cap),
+ pasid_max - 1, GFP_KERNEL);
+ if (ret < 0) {
+ kfree(svm);
+ goto out;
+ }
+ svm->pasid = ret;
+ svm->notifier.ops = &intel_mmuops;
+ svm->mm = mm;
+ svm->flags = flags;
+ INIT_LIST_HEAD_RCU(&svm->devs);
+ ret = -ENOMEM;
+ if (mm) {
+ ret = mmu_notifier_register(&svm->notifier, mm);
+ if (ret) {
+ idr_remove(&svm->iommu->pasid_idr, svm->pasid);
+ kfree(svm);
+ kfree(sdev);
+ goto out;
+ }
+ iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1;
+ mm = NULL;
+ } else
+ iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11);
+ wmb();
+ /* In caching mode, we still have to flush with PASID 0 when
+ * a PASID table entry becomes present. Not entirely clear
+ * *why* that would be the case — surely we could just issue
+ * a flush with the PASID value that we've changed? The PASID
+ * is the index into the table, after all. It's not like domain
+ * IDs in the case of the equivalent context-entry change in
+ * caching mode. And for that matter it's not entirely clear why
+ * a VMM would be in the business of caching the PASID table
+ * anyway. Surely that can be left entirely to the guest? */
+ if (cap_caching_mode(iommu->cap))
+ intel_flush_pasid_dev(svm, sdev, 0);
+ }
+ list_add_rcu(&sdev->list, &svm->devs);
+
+ success:
+ *pasid = svm->pasid;
+ ret = 0;
+ out:
+ mutex_unlock(&pasid_mutex);
+ if (mm)
+ mmput(mm);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(intel_svm_bind_mm);
+
+int intel_svm_unbind_mm(struct device *dev, int pasid)
+{
+ struct intel_svm_dev *sdev;
+ struct intel_iommu *iommu;
+ struct intel_svm *svm;
+ int ret = -EINVAL;
+
+ mutex_lock(&pasid_mutex);
+ iommu = intel_svm_device_to_iommu(dev);
+ if (!iommu || !iommu->pasid_table)
+ goto out;
+
+ svm = idr_find(&iommu->pasid_idr, pasid);
+ if (!svm)
+ goto out;
+
+ list_for_each_entry(sdev, &svm->devs, list) {
+ if (dev == sdev->dev) {
+ ret = 0;
+ sdev->users--;
+ if (!sdev->users) {
+ list_del_rcu(&sdev->list);
+ /* Flush the PASID cache and IOTLB for this device.
+ * Note that we do depend on the hardware *not* using
+ * the PASID any more. Just as we depend on other
+ * devices never using PASIDs that they have no right
+ * to use. We have a *shared* PASID table, because it's
+ * large and has to be physically contiguous. So it's
+ * hard to be as defensive as we might like. */
+ intel_flush_pasid_dev(svm, sdev, svm->pasid);
+ intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+ kfree_rcu(sdev, rcu);
+
+ if (list_empty(&svm->devs)) {
+ mmu_notifier_unregister(&svm->notifier, svm->mm);
+
+ idr_remove(&svm->iommu->pasid_idr, svm->pasid);
+ if (svm->mm)
+ mmput(svm->mm);
+ /* We mandate that no page faults may be outstanding
+ * for the PASID when intel_svm_unbind_mm() is called.
+ * If that is not obeyed, subtle errors will happen.
+ * Let's make them less subtle... */
+ memset(svm, 0x6b, sizeof(*svm));
+ kfree(svm);
+ }
+ }
+ break;
+ }
+ }
+ out:
+ mutex_unlock(&pasid_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(intel_svm_unbind_mm);
+
+/* Page request queue descriptor */
+struct page_req_dsc {
+ u64 srr:1;
+ u64 bof:1;
+ u64 pasid_present:1;
+ u64 lpig:1;
+ u64 pasid:20;
+ u64 bus:8;
+ u64 private:23;
+ u64 prg_index:9;
+ u64 rd_req:1;
+ u64 wr_req:1;
+ u64 exe_req:1;
+ u64 priv_req:1;
+ u64 devfn:8;
+ u64 addr:52;
+};
+
+#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10)
+static irqreturn_t prq_event_thread(int irq, void *d)
+{
+ struct intel_iommu *iommu = d;
+ struct intel_svm *svm = NULL;
+ int head, tail, handled = 0;
+
+ tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
+ head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
+ while (head != tail) {
+ struct intel_svm_dev *sdev;
+ struct vm_area_struct *vma;
+ struct page_req_dsc *req;
+ struct qi_desc resp;
+ int ret, result;
+ u64 address;
+
+ handled = 1;
+
+ req = &iommu->prq[head / sizeof(*req)];
+
+ result = QI_RESP_FAILURE;
+ address = (u64)req->addr << VTD_PAGE_SHIFT;
+ if (!req->pasid_present) {
+ pr_err("%s: Page request without PASID: %08llx %08llx\n",
+ iommu->name, ((unsigned long long *)req)[0],
+ ((unsigned long long *)req)[1]);
+ goto bad_req;
+ }
+
+ if (!svm || svm->pasid != req->pasid) {
+ rcu_read_lock();
+ svm = idr_find(&iommu->pasid_idr, req->pasid);
+ /* It *can't* go away, because the driver is not permitted
+ * to unbind the mm while any page faults are outstanding.
+ * So we only need RCU to protect the internal idr code. */
+ rcu_read_unlock();
+
+ if (!svm) {
+ pr_err("%s: Page request for invalid PASID %d: %08llx %08llx\n",
+ iommu->name, req->pasid, ((unsigned long long *)req)[0],
+ ((unsigned long long *)req)[1]);
+ goto no_pasid;
+ }
+ }
+
+ result = QI_RESP_INVALID;
+ /* Since we're using init_mm.pgd directly, we should never take
+ * any faults on kernel addresses. */
+ if (!svm->mm)
+ goto bad_req;
+ down_read(&svm->mm->mmap_sem);
+ vma = find_extend_vma(svm->mm, address);
+ if (!vma || address < vma->vm_start)
+ goto invalid;
+
+ ret = handle_mm_fault(svm->mm, vma, address,
+ req->wr_req ? FAULT_FLAG_WRITE : 0);
+ if (ret & VM_FAULT_ERROR)
+ goto invalid;
+
+ result = QI_RESP_SUCCESS;
+ invalid:
+ up_read(&svm->mm->mmap_sem);
+ bad_req:
+ /* Accounting for major/minor faults? */
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdev, &svm->devs, list) {
+ if (sdev->sid == PCI_DEVID(req->bus, req->devfn))
+ break;
+ }
+ /* Other devices can go away, but the drivers are not permitted
+ * to unbind while any page faults might be in flight. So it's
+ * OK to drop the 'lock' here now we have it. */
+ rcu_read_unlock();
+
+ if (WARN_ON(&sdev->list == &svm->devs))
+ sdev = NULL;
+
+ if (sdev && sdev->ops && sdev->ops->fault_cb) {
+ int rwxp = (req->rd_req << 3) | (req->wr_req << 2) |
+ (req->exe_req << 1) | (req->priv_req);
+ sdev->ops->fault_cb(sdev->dev, req->pasid, req->addr, req->private, rwxp, result);
+ }
+ /* We get here in the error case where the PASID lookup failed,
+ and these can be NULL. Do not use them below this point! */
+ sdev = NULL;
+ svm = NULL;
+ no_pasid:
+ if (req->lpig) {
+ /* Page Group Response */
+ resp.low = QI_PGRP_PASID(req->pasid) |
+ QI_PGRP_DID((req->bus << 8) | req->devfn) |
+ QI_PGRP_PASID_P(req->pasid_present) |
+ QI_PGRP_RESP_TYPE;
+ resp.high = QI_PGRP_IDX(req->prg_index) |
+ QI_PGRP_PRIV(req->private) | QI_PGRP_RESP_CODE(result);
+
+ qi_submit_sync(&resp, iommu);
+ } else if (req->srr) {
+ /* Page Stream Response */
+ resp.low = QI_PSTRM_IDX(req->prg_index) |
+ QI_PSTRM_PRIV(req->private) | QI_PSTRM_BUS(req->bus) |
+ QI_PSTRM_PASID(req->pasid) | QI_PSTRM_RESP_TYPE;
+ resp.high = QI_PSTRM_ADDR(address) | QI_PSTRM_DEVFN(req->devfn) |
+ QI_PSTRM_RESP_CODE(result);
+
+ qi_submit_sync(&resp, iommu);
+ }
+
+ head = (head + sizeof(*req)) & PRQ_RING_MASK;
+ }
+
+ dmar_writeq(iommu->reg + DMAR_PQH_REG, tail);
+
+ return IRQ_RETVAL(handled);
+}
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 9ec4e0d94ffd..1fae1881648c 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -169,8 +169,26 @@ static int modify_irte(struct irq_2_iommu *irq_iommu,
index = irq_iommu->irte_index + irq_iommu->sub_handle;
irte = &iommu->ir_table->base[index];
- set_64bit(&irte->low, irte_modified->low);
- set_64bit(&irte->high, irte_modified->high);
+#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE)
+ if ((irte->pst == 1) || (irte_modified->pst == 1)) {
+ bool ret;
+
+ ret = cmpxchg_double(&irte->low, &irte->high,
+ irte->low, irte->high,
+ irte_modified->low, irte_modified->high);
+ /*
+ * We use cmpxchg16 to atomically update the 128-bit IRTE,
+ * and it cannot be updated by the hardware or other processors
+ * behind us, so the return value of cmpxchg16 should be the
+ * same as the old value.
+ */
+ WARN_ON(!ret);
+ } else
+#endif
+ {
+ set_64bit(&irte->low, irte_modified->low);
+ set_64bit(&irte->high, irte_modified->high);
+ }
__iommu_flush_cache(iommu, irte, sizeof(*irte));
rc = qi_flush_iec(iommu, index, 0);
@@ -384,7 +402,7 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
static int iommu_load_old_irte(struct intel_iommu *iommu)
{
- struct irte __iomem *old_ir_table;
+ struct irte *old_ir_table;
phys_addr_t irt_phys;
unsigned int i;
size_t size;
@@ -408,12 +426,12 @@ static int iommu_load_old_irte(struct intel_iommu *iommu)
size = INTR_REMAP_TABLE_ENTRIES*sizeof(struct irte);
/* Map the old IR table */
- old_ir_table = ioremap_cache(irt_phys, size);
+ old_ir_table = memremap(irt_phys, size, MEMREMAP_WB);
if (!old_ir_table)
return -ENOMEM;
/* Copy data over */
- memcpy_fromio(iommu->ir_table->base, old_ir_table, size);
+ memcpy(iommu->ir_table->base, old_ir_table, size);
__iommu_flush_cache(iommu, iommu->ir_table->base, size);
@@ -426,7 +444,7 @@ static int iommu_load_old_irte(struct intel_iommu *iommu)
bitmap_set(iommu->ir_table->bitmap, i, 1);
}
- iounmap(old_ir_table);
+ memunmap(old_ir_table);
return 0;
}
@@ -672,7 +690,7 @@ static int __init intel_prepare_irq_remapping(void)
if (!dmar_ir_support())
return -ENODEV;
- if (parse_ioapics_under_ir() != 1) {
+ if (parse_ioapics_under_ir()) {
pr_info("Not enabling interrupt remapping\n");
goto error;
}
@@ -727,7 +745,16 @@ static inline void set_irq_posting_cap(void)
struct intel_iommu *iommu;
if (!disable_irq_post) {
- intel_irq_remap_ops.capability |= 1 << IRQ_POSTING_CAP;
+ /*
+ * If IRTE is in posted format, the 'pda' field goes across the
+ * 64-bit boundary, we need use cmpxchg16b to atomically update
+ * it. We only expose posted-interrupt when X86_FEATURE_CX16
+ * is supported. Actually, hardware platforms supporting PI
+ * should have X86_FEATURE_CX16 support, this has been confirmed
+ * with Intel hardware guys.
+ */
+ if ( cpu_has_cx16 )
+ intel_irq_remap_ops.capability |= 1 << IRQ_POSTING_CAP;
for_each_iommu(iommu, drhd)
if (!cap_pi_support(iommu->cap)) {
@@ -907,16 +934,21 @@ static int __init parse_ioapics_under_ir(void)
bool ir_supported = false;
int ioapic_idx;
- for_each_iommu(iommu, drhd)
- if (ecap_ir_support(iommu->ecap)) {
- if (ir_parse_ioapic_hpet_scope(drhd->hdr, iommu))
- return -1;
+ for_each_iommu(iommu, drhd) {
+ int ret;
- ir_supported = true;
- }
+ if (!ecap_ir_support(iommu->ecap))
+ continue;
+
+ ret = ir_parse_ioapic_hpet_scope(drhd->hdr, iommu);
+ if (ret)
+ return ret;
+
+ ir_supported = true;
+ }
if (!ir_supported)
- return 0;
+ return -ENODEV;
for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
int ioapic_id = mpc_ioapic_id(ioapic_idx);
@@ -928,7 +960,7 @@ static int __init parse_ioapics_under_ir(void)
}
}
- return 1;
+ return 0;
}
static int __init ir_dev_scope_init(void)
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 73c07482f487..7df97777662d 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -202,9 +202,9 @@ typedef u64 arm_lpae_iopte;
static bool selftest_running = false;
-static dma_addr_t __arm_lpae_dma_addr(struct device *dev, void *pages)
+static dma_addr_t __arm_lpae_dma_addr(void *pages)
{
- return phys_to_dma(dev, virt_to_phys(pages));
+ return (dma_addr_t)virt_to_phys(pages);
}
static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
@@ -223,10 +223,10 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
goto out_free;
/*
* We depend on the IOMMU being able to work with any physical
- * address directly, so if the DMA layer suggests it can't by
- * giving us back some translation, that bodes very badly...
+ * address directly, so if the DMA layer suggests otherwise by
+ * translating or truncating them, that bodes very badly...
*/
- if (dma != __arm_lpae_dma_addr(dev, pages))
+ if (dma != virt_to_phys(pages))
goto out_unmap;
}
@@ -243,10 +243,8 @@ out_free:
static void __arm_lpae_free_pages(void *pages, size_t size,
struct io_pgtable_cfg *cfg)
{
- struct device *dev = cfg->iommu_dev;
-
if (!selftest_running)
- dma_unmap_single(dev, __arm_lpae_dma_addr(dev, pages),
+ dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
size, DMA_TO_DEVICE);
free_pages_exact(pages, size);
}
@@ -254,12 +252,11 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
struct io_pgtable_cfg *cfg)
{
- struct device *dev = cfg->iommu_dev;
-
*ptep = pte;
if (!selftest_running)
- dma_sync_single_for_device(dev, __arm_lpae_dma_addr(dev, ptep),
+ dma_sync_single_for_device(cfg->iommu_dev,
+ __arm_lpae_dma_addr(ptep),
sizeof(pte), DMA_TO_DEVICE);
}
@@ -629,6 +626,11 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
return NULL;
+ if (!selftest_running && cfg->iommu_dev->dma_pfn_offset) {
+ dev_err(cfg->iommu_dev, "Cannot accommodate DMA offset for IOMMU page tables\n");
+ return NULL;
+ }
+
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return NULL;
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 049df495c274..abae363c7b9b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -728,16 +728,35 @@ static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque)
}
/*
+ * Generic device_group call-back function. It just allocates one
+ * iommu-group per device.
+ */
+struct iommu_group *generic_device_group(struct device *dev)
+{
+ struct iommu_group *group;
+
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
+ return NULL;
+
+ return group;
+}
+
+/*
* Use standard PCI bus topology, isolation features, and DMA alias quirks
* to find or create an IOMMU group for a device.
*/
-static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
+struct iommu_group *pci_device_group(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
struct group_for_pci_data data;
struct pci_bus *bus;
struct iommu_group *group = NULL;
u64 devfns[4] = { 0 };
+ if (WARN_ON(!dev_is_pci(dev)))
+ return ERR_PTR(-EINVAL);
+
/*
* Find the upstream DMA alias for the device. A device must not
* be aliased due to topology in order to have its own IOMMU group.
@@ -791,14 +810,6 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
if (IS_ERR(group))
return NULL;
- /*
- * Try to allocate a default domain - needs support from the
- * IOMMU driver.
- */
- group->default_domain = __iommu_domain_alloc(pdev->dev.bus,
- IOMMU_DOMAIN_DMA);
- group->domain = group->default_domain;
-
return group;
}
@@ -814,6 +825,7 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
*/
struct iommu_group *iommu_group_get_for_dev(struct device *dev)
{
+ const struct iommu_ops *ops = dev->bus->iommu_ops;
struct iommu_group *group;
int ret;
@@ -821,14 +833,24 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev)
if (group)
return group;
- if (!dev_is_pci(dev))
- return ERR_PTR(-EINVAL);
+ group = ERR_PTR(-EINVAL);
- group = iommu_group_get_for_pci_dev(to_pci_dev(dev));
+ if (ops && ops->device_group)
+ group = ops->device_group(dev);
if (IS_ERR(group))
return group;
+ /*
+ * Try to allocate a default domain - needs support from the
+ * IOMMU driver.
+ */
+ if (!group->default_domain) {
+ group->default_domain = __iommu_domain_alloc(dev->bus,
+ IOMMU_DOMAIN_DMA);
+ group->domain = group->default_domain;
+ }
+
ret = iommu_group_add_device(group, dev);
if (ret) {
iommu_group_put(group);
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 913455a5fd40..8adaaeae3268 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -22,7 +22,7 @@ int irq_remap_broken;
int disable_sourceid_checking;
int no_x2apic_optout;
-int disable_irq_post = 1;
+int disable_irq_post = 0;
static int disable_irq_remap;
static struct irq_remap_ops *remap_ops;
@@ -58,14 +58,18 @@ static __init int setup_irqremap(char *str)
return -EINVAL;
while (*str) {
- if (!strncmp(str, "on", 2))
+ if (!strncmp(str, "on", 2)) {
disable_irq_remap = 0;
- else if (!strncmp(str, "off", 3))
+ disable_irq_post = 0;
+ } else if (!strncmp(str, "off", 3)) {
disable_irq_remap = 1;
- else if (!strncmp(str, "nosid", 5))
+ disable_irq_post = 1;
+ } else if (!strncmp(str, "nosid", 5))
disable_sourceid_checking = 1;
else if (!strncmp(str, "no_x2apic_optout", 16))
no_x2apic_optout = 1;
+ else if (!strncmp(str, "nopost", 6))
+ disable_irq_post = 1;
str += strcspn(str, ",");
while (*str == ',')
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 36d0033c2ccb..3dc5b65f3990 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -26,6 +26,8 @@
#include <linux/of_iommu.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
#include <asm/cacheflush.h>
@@ -112,6 +114,18 @@ void omap_iommu_restore_ctx(struct device *dev)
}
EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
+static void dra7_cfg_dspsys_mmu(struct omap_iommu *obj, bool enable)
+{
+ u32 val, mask;
+
+ if (!obj->syscfg)
+ return;
+
+ mask = (1 << (obj->id * DSP_SYS_MMU_CONFIG_EN_SHIFT));
+ val = enable ? mask : 0;
+ regmap_update_bits(obj->syscfg, DSP_SYS_MMU_CONFIG, mask, val);
+}
+
static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{
u32 l = iommu_read_reg(obj, MMU_CNTL);
@@ -147,6 +161,8 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
iommu_write_reg(obj, pa, MMU_TTB);
+ dra7_cfg_dspsys_mmu(obj, true);
+
if (obj->has_bus_err_back)
iommu_write_reg(obj, MMU_GP_REG_BUS_ERR_BACK_EN, MMU_GP_REG);
@@ -161,6 +177,7 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL);
+ dra7_cfg_dspsys_mmu(obj, false);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
@@ -864,6 +881,42 @@ static void omap_iommu_detach(struct omap_iommu *obj)
dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
}
+static int omap_iommu_dra7_get_dsp_system_cfg(struct platform_device *pdev,
+ struct omap_iommu *obj)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu"))
+ return 0;
+
+ if (!of_property_read_bool(np, "ti,syscon-mmuconfig")) {
+ dev_err(&pdev->dev, "ti,syscon-mmuconfig property is missing\n");
+ return -EINVAL;
+ }
+
+ obj->syscfg =
+ syscon_regmap_lookup_by_phandle(np, "ti,syscon-mmuconfig");
+ if (IS_ERR(obj->syscfg)) {
+ /* can fail with -EPROBE_DEFER */
+ ret = PTR_ERR(obj->syscfg);
+ return ret;
+ }
+
+ if (of_property_read_u32_index(np, "ti,syscon-mmuconfig", 1,
+ &obj->id)) {
+ dev_err(&pdev->dev, "couldn't get the IOMMU instance id within subsystem\n");
+ return -EINVAL;
+ }
+
+ if (obj->id != 0 && obj->id != 1) {
+ dev_err(&pdev->dev, "invalid IOMMU instance id\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* OMAP Device MMU(IOMMU) detection
*/
@@ -907,6 +960,10 @@ static int omap_iommu_probe(struct platform_device *pdev)
if (IS_ERR(obj->regbase))
return PTR_ERR(obj->regbase);
+ err = omap_iommu_dra7_get_dsp_system_cfg(pdev, obj);
+ if (err)
+ return err;
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENODEV;
@@ -943,6 +1000,7 @@ static const struct of_device_id omap_iommu_of_match[] = {
{ .compatible = "ti,omap2-iommu" },
{ .compatible = "ti,omap4-iommu" },
{ .compatible = "ti,dra7-iommu" },
+ { .compatible = "ti,dra7-dsp-iommu" },
{},
};
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index a656df2f9e03..59628e5017b4 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -30,6 +30,7 @@ struct iotlb_entry {
struct omap_iommu {
const char *name;
void __iomem *regbase;
+ struct regmap *syscfg;
struct device *dev;
struct iommu_domain *domain;
struct dentry *debug_dir;
@@ -48,6 +49,7 @@ struct omap_iommu {
void *ctx; /* iommu context: registres saved area */
int has_bus_err_back;
+ u32 id;
};
struct cr_regs {
@@ -159,6 +161,13 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
/*
+ * DSP_SYSTEM registers and bit definitions (applicable only for DRA7xx DSP)
+ */
+#define DSP_SYS_REVISION 0x00
+#define DSP_SYS_MMU_CONFIG 0x18
+#define DSP_SYS_MMU_CONFIG_EN_SHIFT 4
+
+/*
* utilities for super page(16MB, 1MB, 64KB and 4KB)
*/
diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
new file mode 100644
index 000000000000..471ee36b9c6e
--- /dev/null
+++ b/drivers/iommu/s390-iommu.c
@@ -0,0 +1,356 @@
+/*
+ * IOMMU API for s390 PCI devices
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
+ */
+
+#include <linux/pci.h>
+#include <linux/iommu.h>
+#include <linux/iommu-helper.h>
+#include <linux/pci.h>
+#include <linux/sizes.h>
+#include <asm/pci_dma.h>
+
+/*
+ * Physically contiguous memory regions can be mapped with 4 KiB alignment,
+ * we allow all page sizes that are an order of 4KiB (no special large page
+ * support so far).
+ */
+#define S390_IOMMU_PGSIZES (~0xFFFUL)
+
+struct s390_domain {
+ struct iommu_domain domain;
+ struct list_head devices;
+ unsigned long *dma_table;
+ spinlock_t dma_table_lock;
+ spinlock_t list_lock;
+};
+
+struct s390_domain_device {
+ struct list_head list;
+ struct zpci_dev *zdev;
+};
+
+static struct s390_domain *to_s390_domain(struct iommu_domain *dom)
+{
+ return container_of(dom, struct s390_domain, domain);
+}
+
+static bool s390_iommu_capable(enum iommu_cap cap)
+{
+ switch (cap) {
+ case IOMMU_CAP_CACHE_COHERENCY:
+ return true;
+ case IOMMU_CAP_INTR_REMAP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+struct iommu_domain *s390_domain_alloc(unsigned domain_type)
+{
+ struct s390_domain *s390_domain;
+
+ if (domain_type != IOMMU_DOMAIN_UNMANAGED)
+ return NULL;
+
+ s390_domain = kzalloc(sizeof(*s390_domain), GFP_KERNEL);
+ if (!s390_domain)
+ return NULL;
+
+ s390_domain->dma_table = dma_alloc_cpu_table();
+ if (!s390_domain->dma_table) {
+ kfree(s390_domain);
+ return NULL;
+ }
+
+ spin_lock_init(&s390_domain->dma_table_lock);
+ spin_lock_init(&s390_domain->list_lock);
+ INIT_LIST_HEAD(&s390_domain->devices);
+
+ return &s390_domain->domain;
+}
+
+void s390_domain_free(struct iommu_domain *domain)
+{
+ struct s390_domain *s390_domain = to_s390_domain(domain);
+
+ dma_cleanup_tables(s390_domain->dma_table);
+ kfree(s390_domain);
+}
+
+static int s390_iommu_attach_device(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct s390_domain *s390_domain = to_s390_domain(domain);
+ struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+ struct s390_domain_device *domain_device;
+ unsigned long flags;
+ int rc;
+
+ if (!zdev)
+ return -ENODEV;
+
+ domain_device = kzalloc(sizeof(*domain_device), GFP_KERNEL);
+ if (!domain_device)
+ return -ENOMEM;
+
+ if (zdev->dma_table)
+ zpci_dma_exit_device(zdev);
+
+ zdev->dma_table = s390_domain->dma_table;
+ rc = zpci_register_ioat(zdev, 0, zdev->start_dma + PAGE_OFFSET,
+ zdev->start_dma + zdev->iommu_size - 1,
+ (u64) zdev->dma_table);
+ if (rc)
+ goto out_restore;
+
+ spin_lock_irqsave(&s390_domain->list_lock, flags);
+ /* First device defines the DMA range limits */
+ if (list_empty(&s390_domain->devices)) {
+ domain->geometry.aperture_start = zdev->start_dma;
+ domain->geometry.aperture_end = zdev->end_dma;
+ domain->geometry.force_aperture = true;
+ /* Allow only devices with identical DMA range limits */
+ } else if (domain->geometry.aperture_start != zdev->start_dma ||
+ domain->geometry.aperture_end != zdev->end_dma) {
+ rc = -EINVAL;
+ spin_unlock_irqrestore(&s390_domain->list_lock, flags);
+ goto out_restore;
+ }
+ domain_device->zdev = zdev;
+ zdev->s390_domain = s390_domain;
+ list_add(&domain_device->list, &s390_domain->devices);
+ spin_unlock_irqrestore(&s390_domain->list_lock, flags);
+
+ return 0;
+
+out_restore:
+ zpci_dma_init_device(zdev);
+ kfree(domain_device);
+
+ return rc;
+}
+
+static void s390_iommu_detach_device(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct s390_domain *s390_domain = to_s390_domain(domain);
+ struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+ struct s390_domain_device *domain_device, *tmp;
+ unsigned long flags;
+ int found = 0;
+
+ if (!zdev)
+ return;
+
+ spin_lock_irqsave(&s390_domain->list_lock, flags);
+ list_for_each_entry_safe(domain_device, tmp, &s390_domain->devices,
+ list) {
+ if (domain_device->zdev == zdev) {
+ list_del(&domain_device->list);
+ kfree(domain_device);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&s390_domain->list_lock, flags);
+
+ if (found) {
+ zdev->s390_domain = NULL;
+ zpci_unregister_ioat(zdev, 0);
+ zpci_dma_init_device(zdev);
+ }
+}
+
+static int s390_iommu_add_device(struct device *dev)
+{
+ struct iommu_group *group;
+ int rc;
+
+ group = iommu_group_get(dev);
+ if (!group) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+ }
+
+ rc = iommu_group_add_device(group, dev);
+ iommu_group_put(group);
+
+ return rc;
+}
+
+static void s390_iommu_remove_device(struct device *dev)
+{
+ struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+ struct iommu_domain *domain;
+
+ /*
+ * This is a workaround for a scenario where the IOMMU API common code
+ * "forgets" to call the detach_dev callback: After binding a device
+ * to vfio-pci and completing the VFIO_SET_IOMMU ioctl (which triggers
+ * the attach_dev), removing the device via
+ * "echo 1 > /sys/bus/pci/devices/.../remove" won't trigger detach_dev,
+ * only remove_device will be called via the BUS_NOTIFY_REMOVED_DEVICE
+ * notifier.
+ *
+ * So let's call detach_dev from here if it hasn't been called before.
+ */
+ if (zdev && zdev->s390_domain) {
+ domain = iommu_get_domain_for_dev(dev);
+ if (domain)
+ s390_iommu_detach_device(domain, dev);
+ }
+
+ iommu_group_remove_device(dev);
+}
+
+static int s390_iommu_update_trans(struct s390_domain *s390_domain,
+ unsigned long pa, dma_addr_t dma_addr,
+ size_t size, int flags)
+{
+ struct s390_domain_device *domain_device;
+ u8 *page_addr = (u8 *) (pa & PAGE_MASK);
+ dma_addr_t start_dma_addr = dma_addr;
+ unsigned long irq_flags, nr_pages, i;
+ unsigned long *entry;
+ int rc = 0;
+
+ if (dma_addr < s390_domain->domain.geometry.aperture_start ||
+ dma_addr + size > s390_domain->domain.geometry.aperture_end)
+ return -EINVAL;
+
+ nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ if (!nr_pages)
+ return 0;
+
+ spin_lock_irqsave(&s390_domain->dma_table_lock, irq_flags);
+ for (i = 0; i < nr_pages; i++) {
+ entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr);
+ if (!entry) {
+ rc = -ENOMEM;
+ goto undo_cpu_trans;
+ }
+ dma_update_cpu_trans(entry, page_addr, flags);
+ page_addr += PAGE_SIZE;
+ dma_addr += PAGE_SIZE;
+ }
+
+ spin_lock(&s390_domain->list_lock);
+ list_for_each_entry(domain_device, &s390_domain->devices, list) {
+ rc = zpci_refresh_trans((u64) domain_device->zdev->fh << 32,
+ start_dma_addr, nr_pages * PAGE_SIZE);
+ if (rc)
+ break;
+ }
+ spin_unlock(&s390_domain->list_lock);
+
+undo_cpu_trans:
+ if (rc && ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)) {
+ flags = ZPCI_PTE_INVALID;
+ while (i-- > 0) {
+ page_addr -= PAGE_SIZE;
+ dma_addr -= PAGE_SIZE;
+ entry = dma_walk_cpu_trans(s390_domain->dma_table,
+ dma_addr);
+ if (!entry)
+ break;
+ dma_update_cpu_trans(entry, page_addr, flags);
+ }
+ }
+ spin_unlock_irqrestore(&s390_domain->dma_table_lock, irq_flags);
+
+ return rc;
+}
+
+static int s390_iommu_map(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot)
+{
+ struct s390_domain *s390_domain = to_s390_domain(domain);
+ int flags = ZPCI_PTE_VALID, rc = 0;
+
+ if (!(prot & IOMMU_READ))
+ return -EINVAL;
+
+ if (!(prot & IOMMU_WRITE))
+ flags |= ZPCI_TABLE_PROTECTED;
+
+ rc = s390_iommu_update_trans(s390_domain, (unsigned long) paddr, iova,
+ size, flags);
+
+ return rc;
+}
+
+static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
+ dma_addr_t iova)
+{
+ struct s390_domain *s390_domain = to_s390_domain(domain);
+ unsigned long *sto, *pto, *rto, flags;
+ unsigned int rtx, sx, px;
+ phys_addr_t phys = 0;
+
+ if (iova < domain->geometry.aperture_start ||
+ iova > domain->geometry.aperture_end)
+ return 0;
+
+ rtx = calc_rtx(iova);
+ sx = calc_sx(iova);
+ px = calc_px(iova);
+ rto = s390_domain->dma_table;
+
+ spin_lock_irqsave(&s390_domain->dma_table_lock, flags);
+ if (rto && reg_entry_isvalid(rto[rtx])) {
+ sto = get_rt_sto(rto[rtx]);
+ if (sto && reg_entry_isvalid(sto[sx])) {
+ pto = get_st_pto(sto[sx]);
+ if (pto && pt_entry_isvalid(pto[px]))
+ phys = pto[px] & ZPCI_PTE_ADDR_MASK;
+ }
+ }
+ spin_unlock_irqrestore(&s390_domain->dma_table_lock, flags);
+
+ return phys;
+}
+
+static size_t s390_iommu_unmap(struct iommu_domain *domain,
+ unsigned long iova, size_t size)
+{
+ struct s390_domain *s390_domain = to_s390_domain(domain);
+ int flags = ZPCI_PTE_INVALID;
+ phys_addr_t paddr;
+ int rc;
+
+ paddr = s390_iommu_iova_to_phys(domain, iova);
+ if (!paddr)
+ return 0;
+
+ rc = s390_iommu_update_trans(s390_domain, (unsigned long) paddr, iova,
+ size, flags);
+ if (rc)
+ return 0;
+
+ return size;
+}
+
+static struct iommu_ops s390_iommu_ops = {
+ .capable = s390_iommu_capable,
+ .domain_alloc = s390_domain_alloc,
+ .domain_free = s390_domain_free,
+ .attach_dev = s390_iommu_attach_device,
+ .detach_dev = s390_iommu_detach_device,
+ .map = s390_iommu_map,
+ .unmap = s390_iommu_unmap,
+ .iova_to_phys = s390_iommu_iova_to_phys,
+ .add_device = s390_iommu_add_device,
+ .remove_device = s390_iommu_remove_device,
+ .pgsize_bitmap = S390_IOMMU_PGSIZES,
+};
+
+static int __init s390_iommu_init(void)
+{
+ return bus_set_iommu(&pci_bus_type, &s390_iommu_ops);
+}
+subsys_initcall(s390_iommu_init);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 27b52c8729cd..4d7294e5d982 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -123,6 +123,7 @@ config RENESAS_INTC_IRQPIN
config RENESAS_IRQC
bool
+ select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
config ST_IRQCHIP
@@ -187,3 +188,8 @@ config IMX_GPCV2
select IRQ_DOMAIN
help
Enables the wakeup IRQs for IMX platforms with GPCv2 block
+
+config IRQ_MXS
+ def_bool y if MACH_ASM9260 || ARCH_MXS
+ select IRQ_DOMAIN
+ select STMP_DEVICE
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bb3048f00e64..177f78f6e6d6 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o
obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o
obj-$(CONFIG_ARCH_MMP) += irq-mmp.o
obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o
-obj-$(CONFIG_ARCH_MXS) += irq-mxs.o
+obj-$(CONFIG_IRQ_MXS) += irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
diff --git a/drivers/irqchip/alphascale_asm9260-icoll.h b/drivers/irqchip/alphascale_asm9260-icoll.h
new file mode 100644
index 000000000000..5cec108ee204
--- /dev/null
+++ b/drivers/irqchip/alphascale_asm9260-icoll.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.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.
+ */
+
+#ifndef _ALPHASCALE_ASM9260_ICOLL_H
+#define _ALPHASCALE_ASM9260_ICOLL_H
+
+#define ASM9260_NUM_IRQS 64
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+
+#define ASM9260_HW_ICOLL_VECTOR 0x0000
+/*
+ * bits 31:2
+ * This register presents the vector address for the interrupt currently
+ * active on the CPU IRQ input. Writing to this register notifies the
+ * interrupt collector that the interrupt service routine for the current
+ * interrupt has been entered.
+ * The exception trap should have a LDPC instruction from this address:
+ * LDPC ASM9260_HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
+ */
+
+/*
+ * The Interrupt Collector Level Acknowledge Register is used by software to
+ * indicate the completion of an interrupt on a specific level.
+ * This register is written at the very end of an interrupt service routine. If
+ * nesting is used then the CPU irq must be turned on before writing to this
+ * register to avoid a race condition in the CPU interrupt hardware.
+ */
+#define ASM9260_HW_ICOLL_LEVELACK 0x0010
+#define ASM9260_BM_LEVELn(nr) BIT(nr)
+
+#define ASM9260_HW_ICOLL_CTRL 0x0020
+/*
+ * ASM9260_BM_CTRL_SFTRST and ASM9260_BM_CTRL_CLKGATE are not available on
+ * asm9260.
+ */
+#define ASM9260_BM_CTRL_SFTRST BIT(31)
+#define ASM9260_BM_CTRL_CLKGATE BIT(30)
+/* disable interrupt level nesting */
+#define ASM9260_BM_CTRL_NO_NESTING BIT(19)
+/*
+ * Set this bit to one enable the RISC32-style read side effect associated with
+ * the vector address register. In this mode, interrupt in-service is signaled
+ * by the read of the ASM9260_HW_ICOLL_VECTOR register to acquire the interrupt
+ * vector address. Set this bit to zero for normal operation, in which the ISR
+ * signals in-service explicitly by means of a write to the
+ * ASM9260_HW_ICOLL_VECTOR register.
+ * 0 - Must Write to Vector register to go in-service.
+ * 1 - Go in-service as a read side effect
+ */
+#define ASM9260_BM_CTRL_ARM_RSE_MODE BIT(18)
+#define ASM9260_BM_CTRL_IRQ_ENABLE BIT(16)
+
+#define ASM9260_HW_ICOLL_STAT_OFFSET 0x0030
+/*
+ * bits 5:0
+ * Vector number of current interrupt. Multiply by 4 and add to vector base
+ * address to obtain the value in ASM9260_HW_ICOLL_VECTOR.
+ */
+
+/*
+ * RAW0 and RAW1 provides a read-only view of the raw interrupt request lines
+ * coming from various parts of the chip. Its purpose is to improve diagnostic
+ * observability.
+ */
+#define ASM9260_HW_ICOLL_RAW0 0x0040
+#define ASM9260_HW_ICOLL_RAW1 0x0050
+
+#define ASM9260_HW_ICOLL_INTERRUPT0 0x0060
+#define ASM9260_HW_ICOLL_INTERRUPTn(n) (0x0060 + ((n) >> 2) * 0x10)
+/*
+ * WARNING: Modifying the priority of an enabled interrupt may result in
+ * undefined behavior.
+ */
+#define ASM9260_BM_INT_PRIORITY_MASK 0x3
+#define ASM9260_BM_INT_ENABLE BIT(2)
+#define ASM9260_BM_INT_SOFTIRQ BIT(3)
+
+#define ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n) (((n) & 0x3) << 3)
+#define ASM9260_BM_ICOLL_INTERRUPTn_ENABLE(n) (1 << (2 + \
+ ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)))
+
+#define ASM9260_HW_ICOLL_VBASE 0x0160
+/*
+ * bits 31:2
+ * This bitfield holds the upper 30 bits of the base address of the vector
+ * table.
+ */
+
+#define ASM9260_HW_ICOLL_CLEAR0 0x01d0
+#define ASM9260_HW_ICOLL_CLEAR1 0x01e0
+#define ASM9260_HW_ICOLL_CLEARn(n) (((n >> 5) * 0x10) \
+ + SET_REG)
+#define ASM9260_BM_CLEAR_BIT(n) BIT(n & 0x1f)
+
+/* Scratchpad */
+#define ASM9260_HW_ICOLL_UNDEF_VECTOR 0x01f0
+#endif
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index cd7d3bc78e34..ead15be2d20a 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -144,7 +144,7 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
unsigned long *out_hwirq,
unsigned int *out_type)
{
- if (d->of_node != controller)
+ if (irq_domain_get_of_node(d) != controller)
return -EINVAL;
if (intsize < 2)
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 655cb967a1f2..3f3a8c3d2175 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -56,9 +56,6 @@
#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)
-#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5)
-#define ARMADA_370_XP_FABRIC_IRQ (3)
-
#define IPI_DOORBELL_START (0)
#define IPI_DOORBELL_END (8)
#define IPI_DOORBELL_MASK 0xFF
@@ -81,13 +78,10 @@ static phys_addr_t msi_doorbell_addr;
static inline bool is_percpu_irq(irq_hw_number_t irq)
{
- switch (irq) {
- case ARMADA_370_XP_TIMER0_PER_CPU_IRQ:
- case ARMADA_370_XP_FABRIC_IRQ:
+ if (irq <= ARMADA_370_XP_MAX_PER_CPU_IRQS)
return true;
- default:
- return false;
- }
+
+ return false;
}
/*
@@ -317,6 +311,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
handle_level_irq);
}
irq_set_probe(virq);
+ irq_clear_status_flags(virq, IRQ_NOAUTOEN);
return 0;
}
@@ -549,7 +544,7 @@ static void armada_370_xp_mpic_resume(void)
if (virq == 0)
continue;
- if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+ if (!is_percpu_irq(irq))
writel(irq, per_cpu_int_base +
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
else
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
index 63cd031b2c28..b12a5d58546f 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -114,7 +114,7 @@ int aic_common_irq_domain_xlate(struct irq_domain *d,
static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
{
- struct device_node *node = domain->of_node;
+ struct device_node *node = irq_domain_get_of_node(domain);
struct irq_chip_generic *gc;
struct aic_chip_data *aic;
struct property *prop;
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index f6d680485bee..62bb840c613f 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -70,16 +70,15 @@ static struct irq_domain *aic5_domain;
static asmlinkage void __exception_irq_entry
aic5_handle(struct pt_regs *regs)
{
- struct irq_domain_chip_generic *dgc = aic5_domain->gc;
- struct irq_chip_generic *gc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(aic5_domain, 0);
u32 irqnr;
u32 irqstat;
- irqnr = irq_reg_readl(gc, AT91_AIC5_IVR);
- irqstat = irq_reg_readl(gc, AT91_AIC5_ISR);
+ irqnr = irq_reg_readl(bgc, AT91_AIC5_IVR);
+ irqstat = irq_reg_readl(bgc, AT91_AIC5_ISR);
if (!irqstat)
- irq_reg_writel(gc, 0, AT91_AIC5_EOICR);
+ irq_reg_writel(bgc, 0, AT91_AIC5_EOICR);
else
handle_domain_irq(aic5_domain, irqnr, regs);
}
@@ -87,8 +86,7 @@ aic5_handle(struct pt_regs *regs)
static void aic5_mask(struct irq_data *d)
{
struct irq_domain *domain = d->domain;
- struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
/*
@@ -105,8 +103,7 @@ static void aic5_mask(struct irq_data *d)
static void aic5_unmask(struct irq_data *d)
{
struct irq_domain *domain = d->domain;
- struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
/*
@@ -123,14 +120,13 @@ static void aic5_unmask(struct irq_data *d)
static int aic5_retrigger(struct irq_data *d)
{
struct irq_domain *domain = d->domain;
- struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *gc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
/* Enable interrupt on AIC5 */
- irq_gc_lock(gc);
- irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
- irq_reg_writel(gc, 1, AT91_AIC5_ISCR);
- irq_gc_unlock(gc);
+ irq_gc_lock(bgc);
+ irq_reg_writel(bgc, d->hwirq, AT91_AIC5_SSR);
+ irq_reg_writel(bgc, 1, AT91_AIC5_ISCR);
+ irq_gc_unlock(bgc);
return 0;
}
@@ -138,18 +134,17 @@ static int aic5_retrigger(struct irq_data *d)
static int aic5_set_type(struct irq_data *d, unsigned type)
{
struct irq_domain *domain = d->domain;
- struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *gc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
unsigned int smr;
int ret;
- irq_gc_lock(gc);
- irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
- smr = irq_reg_readl(gc, AT91_AIC5_SMR);
+ irq_gc_lock(bgc);
+ irq_reg_writel(bgc, d->hwirq, AT91_AIC5_SSR);
+ smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
ret = aic_common_set_type(d, type, &smr);
if (!ret)
- irq_reg_writel(gc, smr, AT91_AIC5_SMR);
- irq_gc_unlock(gc);
+ irq_reg_writel(bgc, smr, AT91_AIC5_SMR);
+ irq_gc_unlock(bgc);
return ret;
}
@@ -159,7 +154,7 @@ static void aic5_suspend(struct irq_data *d)
{
struct irq_domain *domain = d->domain;
struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
int i;
u32 mask;
@@ -183,7 +178,7 @@ static void aic5_resume(struct irq_data *d)
{
struct irq_domain *domain = d->domain;
struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
int i;
u32 mask;
@@ -207,7 +202,7 @@ static void aic5_pm_shutdown(struct irq_data *d)
{
struct irq_domain *domain = d->domain;
struct irq_domain_chip_generic *dgc = domain->gc;
- struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
int i;
@@ -262,12 +257,11 @@ static int aic5_irq_domain_xlate(struct irq_domain *d,
irq_hw_number_t *out_hwirq,
unsigned int *out_type)
{
- struct irq_domain_chip_generic *dgc = d->gc;
- struct irq_chip_generic *gc;
+ struct irq_chip_generic *bgc = irq_get_domain_generic_chip(d, 0);
unsigned smr;
int ret;
- if (!dgc)
+ if (!bgc)
return -EINVAL;
ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
@@ -275,15 +269,13 @@ static int aic5_irq_domain_xlate(struct irq_domain *d,
if (ret)
return ret;
- gc = dgc->gc[0];
-
- irq_gc_lock(gc);
- irq_reg_writel(gc, *out_hwirq, AT91_AIC5_SSR);
- smr = irq_reg_readl(gc, AT91_AIC5_SMR);
+ irq_gc_lock(bgc);
+ irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR);
+ smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
ret = aic_common_set_priority(intspec[2], &smr);
if (!ret)
- irq_reg_writel(gc, intspec[2] | smr, AT91_AIC5_SMR);
- irq_gc_unlock(gc);
+ irq_reg_writel(bgc, intspec[2] | smr, AT91_AIC5_SMR);
+ irq_gc_unlock(bgc);
return ret;
}
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index a7f5626930f5..75573fa431ba 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -78,10 +78,13 @@ static struct irq_chip crossbar_chip = {
static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
irq_hw_number_t hwirq)
{
- struct of_phandle_args args;
+ struct irq_fwspec fwspec;
int i;
int err;
+ if (!irq_domain_get_of_node(domain->parent))
+ return -EINVAL;
+
raw_spin_lock(&cb->lock);
for (i = cb->int_max - 1; i >= 0; i--) {
if (cb->irq_map[i] == IRQ_FREE) {
@@ -94,13 +97,13 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
if (i < 0)
return -ENODEV;
- args.np = domain->parent->of_node;
- args.args_count = 3;
- args.args[0] = 0; /* SPI */
- args.args[1] = i;
- args.args[2] = IRQ_TYPE_LEVEL_HIGH;
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 3;
+ fwspec.param[0] = 0; /* SPI */
+ fwspec.param[1] = i;
+ fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
- err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+ err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
if (err)
cb->irq_map[i] = IRQ_FREE;
else
@@ -112,16 +115,16 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
unsigned int nr_irqs, void *data)
{
- struct of_phandle_args *args = data;
+ struct irq_fwspec *fwspec = data;
irq_hw_number_t hwirq;
int i;
- if (args->args_count != 3)
+ if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
- if (args->args[0] != 0)
+ if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
- hwirq = args->args[1];
+ hwirq = fwspec->param[1];
if ((hwirq + nr_irqs) > cb->max_crossbar_sources)
return -EINVAL; /* Can't deal with this */
@@ -166,28 +169,31 @@ static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
raw_spin_unlock(&cb->lock);
}
-static int crossbar_domain_xlate(struct irq_domain *d,
- struct device_node *controller,
- const u32 *intspec, unsigned int intsize,
- unsigned long *out_hwirq,
- unsigned int *out_type)
+static int crossbar_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
{
- if (d->of_node != controller)
- return -EINVAL; /* Shouldn't happen, really... */
- if (intsize != 3)
- return -EINVAL; /* Not GIC compliant */
- if (intspec[0] != 0)
- return -EINVAL; /* No PPI should point to this domain */
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 3)
+ return -EINVAL;
- *out_hwirq = intspec[1];
- *out_type = intspec[2];
- return 0;
+ /* No PPI should point to this domain */
+ if (fwspec->param[0] != 0)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[1];
+ *type = fwspec->param[2];
+ return 0;
+ }
+
+ return -EINVAL;
}
static const struct irq_domain_ops crossbar_domain_ops = {
- .alloc = crossbar_domain_alloc,
- .free = crossbar_domain_free,
- .xlate = crossbar_domain_xlate,
+ .alloc = crossbar_domain_alloc,
+ .free = crossbar_domain_free,
+ .translate = crossbar_domain_translate,
};
static int __init crossbar_of_init(struct device_node *node)
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index 9448e391cb71..f174ce0ca361 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -21,6 +21,17 @@
#include "irq-gic-common.h"
+void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
+ void *data)
+{
+ for (; quirks->desc; quirks++) {
+ if (quirks->iidr != (quirks->mask & iidr))
+ continue;
+ quirks->init(data);
+ pr_info("GIC: enabling workaround for %s\n", quirks->desc);
+ }
+}
+
int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void))
{
@@ -73,12 +84,15 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs,
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
/*
- * Disable all interrupts. Leave the PPI and SGIs alone
- * as they are enabled by redistributor registers.
+ * Deactivate and disable all SPIs. Leave the PPI and SGIs
+ * alone as they are in the redistributor registers on GICv3.
*/
- for (i = 32; i < gic_irqs; i += 32)
+ for (i = 32; i < gic_irqs; i += 32) {
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ base + GIC_DIST_ACTIVE_CLEAR + i / 8);
writel_relaxed(GICD_INT_EN_CLR_X32,
- base + GIC_DIST_ENABLE_CLEAR + i / 8);
+ base + GIC_DIST_ENABLE_CLEAR + i / 8);
+ }
if (sync_access)
sync_access();
@@ -91,7 +105,9 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
/*
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
+ * Make sure everything is deactivated.
*/
+ writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index 35a9884778bd..fff697db8e22 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -20,10 +20,19 @@
#include <linux/of.h>
#include <linux/irqdomain.h>
+struct gic_quirk {
+ const char *desc;
+ void (*init)(void *data);
+ u32 iidr;
+ u32 mask;
+};
+
int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void));
void gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void));
void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
+void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
+ void *data);
#endif /* _IRQ_GIC_COMMON_H */
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 12985daa66ab..87f8d104acab 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -37,19 +37,31 @@
#define V2M_MSI_SETSPI_NS 0x040
#define V2M_MIN_SPI 32
#define V2M_MAX_SPI 1019
+#define V2M_MSI_IIDR 0xFCC
#define V2M_MSI_TYPER_BASE_SPI(x) \
(((x) >> V2M_MSI_TYPER_BASE_SHIFT) & V2M_MSI_TYPER_BASE_MASK)
#define V2M_MSI_TYPER_NUM_SPI(x) ((x) & V2M_MSI_TYPER_NUM_MASK)
+/* APM X-Gene with GICv2m MSI_IIDR register value */
+#define XGENE_GICV2M_MSI_IIDR 0x06000170
+
+/* List of flags for specific v2m implementation */
+#define GICV2M_NEEDS_SPI_OFFSET 0x00000001
+
+static LIST_HEAD(v2m_nodes);
+static DEFINE_SPINLOCK(v2m_lock);
+
struct v2m_data {
- spinlock_t msi_cnt_lock;
+ struct list_head entry;
+ struct device_node *node;
struct resource res; /* GICv2m resource */
void __iomem *base; /* GICv2m virt address */
u32 spi_start; /* The SPI number that MSIs start */
u32 nr_spis; /* The number of SPIs for MSIs */
unsigned long *bm; /* MSI vector bitmap */
+ u32 flags; /* v2m flags for specific implementation */
};
static void gicv2m_mask_msi_irq(struct irq_data *d)
@@ -98,6 +110,9 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
msg->address_hi = upper_32_bits(addr);
msg->address_lo = lower_32_bits(addr);
msg->data = data->hwirq;
+
+ if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
+ msg->data -= v2m->spi_start;
}
static struct irq_chip gicv2m_irq_chip = {
@@ -113,17 +128,21 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
unsigned int virq,
irq_hw_number_t hwirq)
{
- struct of_phandle_args args;
+ struct irq_fwspec fwspec;
struct irq_data *d;
int err;
- args.np = domain->parent->of_node;
- args.args_count = 3;
- args.args[0] = 0;
- args.args[1] = hwirq - 32;
- args.args[2] = IRQ_TYPE_EDGE_RISING;
+ if (is_of_node(domain->parent->fwnode)) {
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 3;
+ fwspec.param[0] = 0;
+ fwspec.param[1] = hwirq - 32;
+ fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+ } else {
+ return -EINVAL;
+ }
- err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+ err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
if (err)
return err;
@@ -143,27 +162,30 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq)
return;
}
- spin_lock(&v2m->msi_cnt_lock);
+ spin_lock(&v2m_lock);
__clear_bit(pos, v2m->bm);
- spin_unlock(&v2m->msi_cnt_lock);
+ spin_unlock(&v2m_lock);
}
static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *args)
{
- struct v2m_data *v2m = domain->host_data;
+ struct v2m_data *v2m = NULL, *tmp;
int hwirq, offset, err = 0;
- spin_lock(&v2m->msi_cnt_lock);
- offset = find_first_zero_bit(v2m->bm, v2m->nr_spis);
- if (offset < v2m->nr_spis)
- __set_bit(offset, v2m->bm);
- else
- err = -ENOSPC;
- spin_unlock(&v2m->msi_cnt_lock);
+ spin_lock(&v2m_lock);
+ list_for_each_entry(tmp, &v2m_nodes, entry) {
+ offset = find_first_zero_bit(tmp->bm, tmp->nr_spis);
+ if (offset < tmp->nr_spis) {
+ __set_bit(offset, tmp->bm);
+ v2m = tmp;
+ break;
+ }
+ }
+ spin_unlock(&v2m_lock);
- if (err)
- return err;
+ if (!v2m)
+ return -ENOSPC;
hwirq = v2m->spi_start + offset;
@@ -224,12 +246,61 @@ static struct msi_domain_info gicv2m_pmsi_domain_info = {
.chip = &gicv2m_pmsi_irq_chip,
};
+static void gicv2m_teardown(void)
+{
+ struct v2m_data *v2m, *tmp;
+
+ list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) {
+ list_del(&v2m->entry);
+ kfree(v2m->bm);
+ iounmap(v2m->base);
+ of_node_put(v2m->node);
+ kfree(v2m);
+ }
+}
+
+static int gicv2m_allocate_domains(struct irq_domain *parent)
+{
+ struct irq_domain *inner_domain, *pci_domain, *plat_domain;
+ struct v2m_data *v2m;
+
+ v2m = list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry);
+ if (!v2m)
+ return 0;
+
+ inner_domain = irq_domain_create_tree(of_node_to_fwnode(v2m->node),
+ &gicv2m_domain_ops, v2m);
+ if (!inner_domain) {
+ pr_err("Failed to create GICv2m domain\n");
+ return -ENOMEM;
+ }
+
+ inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+ inner_domain->parent = parent;
+ pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(v2m->node),
+ &gicv2m_msi_domain_info,
+ inner_domain);
+ plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(v2m->node),
+ &gicv2m_pmsi_domain_info,
+ inner_domain);
+ if (!pci_domain || !plat_domain) {
+ pr_err("Failed to create MSI domains\n");
+ if (plat_domain)
+ irq_domain_remove(plat_domain);
+ if (pci_domain)
+ irq_domain_remove(pci_domain);
+ irq_domain_remove(inner_domain);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static int __init gicv2m_init_one(struct device_node *node,
struct irq_domain *parent)
{
int ret;
struct v2m_data *v2m;
- struct irq_domain *inner_domain, *pci_domain, *plat_domain;
v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
if (!v2m) {
@@ -237,6 +308,9 @@ static int __init gicv2m_init_one(struct device_node *node,
return -ENOMEM;
}
+ INIT_LIST_HEAD(&v2m->entry);
+ v2m->node = node;
+
ret = of_address_to_resource(node, 0, &v2m->res);
if (ret) {
pr_err("Failed to allocate v2m resource.\n");
@@ -266,6 +340,17 @@ static int __init gicv2m_init_one(struct device_node *node,
goto err_iounmap;
}
+ /*
+ * APM X-Gene GICv2m implementation has an erratum where
+ * the MSI data needs to be the offset from the spi_start
+ * in order to trigger the correct MSI interrupt. This is
+ * different from the standard GICv2m implementation where
+ * the MSI data is the absolute value within the range from
+ * spi_start to (spi_start + num_spis).
+ */
+ if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
+ v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+
v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
GFP_KERNEL);
if (!v2m->bm) {
@@ -273,43 +358,13 @@ static int __init gicv2m_init_one(struct device_node *node,
goto err_iounmap;
}
- inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m);
- if (!inner_domain) {
- pr_err("Failed to create GICv2m domain\n");
- ret = -ENOMEM;
- goto err_free_bm;
- }
-
- inner_domain->bus_token = DOMAIN_BUS_NEXUS;
- inner_domain->parent = parent;
- pci_domain = pci_msi_create_irq_domain(node, &gicv2m_msi_domain_info,
- inner_domain);
- plat_domain = platform_msi_create_irq_domain(node,
- &gicv2m_pmsi_domain_info,
- inner_domain);
- if (!pci_domain || !plat_domain) {
- pr_err("Failed to create MSI domains\n");
- ret = -ENOMEM;
- goto err_free_domains;
- }
-
- spin_lock_init(&v2m->msi_cnt_lock);
-
+ list_add_tail(&v2m->entry, &v2m_nodes);
pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
(unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
return 0;
-err_free_domains:
- if (plat_domain)
- irq_domain_remove(plat_domain);
- if (pci_domain)
- irq_domain_remove(pci_domain);
- if (inner_domain)
- irq_domain_remove(inner_domain);
-err_free_bm:
- kfree(v2m->bm);
err_iounmap:
iounmap(v2m->base);
err_free_v2m:
@@ -339,5 +394,9 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
}
}
+ if (!ret)
+ ret = gicv2m_allocate_domains(parent);
+ if (ret)
+ gicv2m_teardown();
return ret;
}
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index a7c8c9ffbafd..aee60ed025dc 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -42,7 +42,6 @@ static struct irq_chip its_msi_irq_chip = {
struct its_pci_alias {
struct pci_dev *pdev;
- u32 dev_id;
u32 count;
};
@@ -60,7 +59,6 @@ static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
{
struct its_pci_alias *dev_alias = data;
- dev_alias->dev_id = alias;
if (pdev != dev_alias->pdev)
dev_alias->count += its_pci_msi_vec_count(pdev);
@@ -86,7 +84,7 @@ static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias);
/* ITS specific DeviceID, as the core ITS ignores dev. */
- info->scratchpad[0].ul = dev_alias.dev_id;
+ info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
return msi_info->ops->msi_prepare(domain->parent,
dev, dev_alias.count, info);
@@ -125,7 +123,8 @@ static int __init its_pci_msi_init(void)
continue;
}
- if (!pci_msi_create_irq_domain(np, &its_pci_msi_domain_info,
+ if (!pci_msi_create_irq_domain(of_node_to_fwnode(np),
+ &its_pci_msi_domain_info,
parent)) {
pr_err("%s: unable to create PCI domain\n",
np->full_name);
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
index a86550562779..470b4aa7d62c 100644
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
@@ -29,13 +29,25 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
{
struct msi_domain_info *msi_info;
u32 dev_id;
- int ret;
+ int ret, index = 0;
msi_info = msi_get_domain_info(domain->parent);
/* Suck the DeviceID out of the msi-parent property */
- ret = of_property_read_u32_index(dev->of_node, "msi-parent",
- 1, &dev_id);
+ do {
+ struct of_phandle_args args;
+
+ ret = of_parse_phandle_with_args(dev->of_node,
+ "msi-parent", "#msi-cells",
+ index, &args);
+ if (args.np == irq_domain_get_of_node(domain)) {
+ if (WARN_ON(args.args_count != 1))
+ return -EINVAL;
+ dev_id = args.args[0];
+ break;
+ }
+ } while (!ret);
+
if (ret)
return ret;
@@ -78,7 +90,8 @@ static int __init its_pmsi_init(void)
continue;
}
- if (!platform_msi_create_irq_domain(np, &its_pmsi_domain_info,
+ if (!platform_msi_create_irq_domain(of_node_to_fwnode(np),
+ &its_pmsi_domain_info,
parent)) {
pr_err("%s: unable to create platform domain\n",
np->full_name);
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 25ceae9f7348..e23d1d18f9d6 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -37,7 +37,10 @@
#include <asm/cputype.h>
#include <asm/exception.h>
-#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1 << 0)
+#include "irq-gic-common.h"
+
+#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)
+#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
@@ -817,7 +820,22 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
int i;
int psz = SZ_64K;
u64 shr = GITS_BASER_InnerShareable;
- u64 cache = GITS_BASER_WaWb;
+ u64 cache;
+ u64 typer;
+ u32 ids;
+
+ if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) {
+ /*
+ * erratum 22375: only alloc 8MB table size
+ * erratum 24313: ignore memory access type
+ */
+ cache = 0;
+ ids = 0x14; /* 20 bits, 8MB */
+ } else {
+ cache = GITS_BASER_WaWb;
+ typer = readq_relaxed(its->base + GITS_TYPER);
+ ids = GITS_TYPER_DEVBITS(typer);
+ }
for (i = 0; i < GITS_BASER_NR_REGS; i++) {
u64 val = readq_relaxed(its->base + GITS_BASER + i * 8);
@@ -825,6 +843,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
int order = get_order(psz);
int alloc_size;
+ int alloc_pages;
u64 tmp;
void *base;
@@ -840,9 +859,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
* For other tables, only allocate a single page.
*/
if (type == GITS_BASER_TYPE_DEVICE) {
- u64 typer = readq_relaxed(its->base + GITS_TYPER);
- u32 ids = GITS_TYPER_DEVBITS(typer);
-
/*
* 'order' was initialized earlier to the default page
* granule of the the ITS. We can't have an allocation
@@ -859,6 +875,14 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
}
alloc_size = (1 << order) * PAGE_SIZE;
+ alloc_pages = (alloc_size / psz);
+ if (alloc_pages > GITS_BASER_PAGES_MAX) {
+ alloc_pages = GITS_BASER_PAGES_MAX;
+ order = get_order(GITS_BASER_PAGES_MAX * psz);
+ pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
+ node_name, order, alloc_pages);
+ }
+
base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!base) {
err = -ENOMEM;
@@ -887,7 +911,7 @@ retry_baser:
break;
}
- val |= (alloc_size / psz) - 1;
+ val |= alloc_pages - 1;
writeq_relaxed(val, its->base + GITS_BASER + i * 8);
tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
@@ -1241,15 +1265,19 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
unsigned int virq,
irq_hw_number_t hwirq)
{
- struct of_phandle_args args;
+ struct irq_fwspec fwspec;
- args.np = domain->parent->of_node;
- args.args_count = 3;
- args.args[0] = GIC_IRQ_TYPE_LPI;
- args.args[1] = hwirq;
- args.args[2] = IRQ_TYPE_EDGE_RISING;
+ if (irq_domain_get_of_node(domain->parent)) {
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 3;
+ fwspec.param[0] = GIC_IRQ_TYPE_LPI;
+ fwspec.param[1] = hwirq;
+ fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+ } else {
+ return -EINVAL;
+ }
- return irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+ return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
}
static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -1370,6 +1398,33 @@ static int its_force_quiescent(void __iomem *base)
}
}
+static void __maybe_unused its_enable_quirk_cavium_22375(void *data)
+{
+ struct its_node *its = data;
+
+ its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
+}
+
+static const struct gic_quirk its_quirks[] = {
+#ifdef CONFIG_CAVIUM_ERRATUM_22375
+ {
+ .desc = "ITS: Cavium errata 22375, 24313",
+ .iidr = 0xa100034c, /* ThunderX pass 1.x */
+ .mask = 0xffff0fff,
+ .init = its_enable_quirk_cavium_22375,
+ },
+#endif
+ {
+ }
+};
+
+static void its_enable_quirks(struct its_node *its)
+{
+ u32 iidr = readl_relaxed(its->base + GITS_IIDR);
+
+ gic_enable_quirks(iidr, its_quirks, its);
+}
+
static int its_probe(struct device_node *node, struct irq_domain *parent)
{
struct resource res;
@@ -1428,6 +1483,8 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
}
its->cmd_write = its->cmd_base;
+ its_enable_quirks(its);
+
err = its_alloc_tables(node->full_name, its);
if (err)
goto out_free_cmd;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 36ecfc870e5a..d7be6ddc34f6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -108,57 +108,17 @@ static void gic_redist_wait_for_rwp(void)
gic_do_wait_for_rwp(gic_data_rdist_rd_base());
}
-/* Low level accessors */
-static u64 __maybe_unused gic_read_iar(void)
-{
- u64 irqstat;
-
- asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
- return irqstat;
-}
-
-static void __maybe_unused gic_write_pmr(u64 val)
-{
- asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val));
-}
-
-static void __maybe_unused gic_write_ctlr(u64 val)
-{
- asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val));
- isb();
-}
-
-static void __maybe_unused gic_write_grpen1(u64 val)
-{
- asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" (val));
- isb();
-}
+#ifdef CONFIG_ARM64
+static DEFINE_STATIC_KEY_FALSE(is_cavium_thunderx);
-static void __maybe_unused gic_write_sgi1r(u64 val)
-{
- asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
-}
-
-static void gic_enable_sre(void)
+static u64 __maybe_unused gic_read_iar(void)
{
- u64 val;
-
- asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
- val |= ICC_SRE_EL1_SRE;
- asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val));
- isb();
-
- /*
- * Need to check that the SRE bit has actually been set. If
- * not, it means that SRE is disabled at EL2. We're going to
- * die painfully, and there is nothing we can do about it.
- *
- * Kindly inform the luser.
- */
- asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
- if (!(val & ICC_SRE_EL1_SRE))
- pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
+ if (static_branch_unlikely(&is_cavium_thunderx))
+ return gic_read_iar_cavium_thunderx();
+ else
+ return gic_read_iar_common();
}
+#endif
static void gic_enable_redist(bool enable)
{
@@ -359,11 +319,11 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
return 0;
}
-static u64 gic_mpidr_to_affinity(u64 mpidr)
+static u64 gic_mpidr_to_affinity(unsigned long mpidr)
{
u64 aff;
- aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
+ aff = ((u64)MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
MPIDR_AFFINITY_LEVEL(mpidr, 0));
@@ -373,7 +333,7 @@ static u64 gic_mpidr_to_affinity(u64 mpidr)
static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{
- u64 irqnr;
+ u32 irqnr;
do {
irqnr = gic_read_iar();
@@ -432,12 +392,12 @@ static void __init gic_dist_init(void)
*/
affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
for (i = 32; i < gic_data.irq_nr; i++)
- writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
+ gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
}
static int gic_populate_rdist(void)
{
- u64 mpidr = cpu_logical_map(smp_processor_id());
+ unsigned long mpidr = cpu_logical_map(smp_processor_id());
u64 typer;
u32 aff;
int i;
@@ -463,15 +423,14 @@ static int gic_populate_rdist(void)
}
do {
- typer = readq_relaxed(ptr + GICR_TYPER);
+ typer = gic_read_typer(ptr + GICR_TYPER);
if ((typer >> 32) == aff) {
u64 offset = ptr - gic_data.redist_regions[i].redist_base;
gic_data_rdist_rd_base() = ptr;
gic_data_rdist()->phys_base = gic_data.redist_regions[i].phys_base + offset;
- pr_info("CPU%d: found redistributor %llx region %d:%pa\n",
- smp_processor_id(),
- (unsigned long long)mpidr,
- i, &gic_data_rdist()->phys_base);
+ pr_info("CPU%d: found redistributor %lx region %d:%pa\n",
+ smp_processor_id(), mpidr, i,
+ &gic_data_rdist()->phys_base);
return 0;
}
@@ -486,15 +445,22 @@ static int gic_populate_rdist(void)
}
/* We couldn't even deal with ourselves... */
- WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
- smp_processor_id(), (unsigned long long)mpidr);
+ WARN(true, "CPU%d: mpidr %lx has no re-distributor!\n",
+ smp_processor_id(), mpidr);
return -ENODEV;
}
static void gic_cpu_sys_reg_init(void)
{
- /* Enable system registers */
- gic_enable_sre();
+ /*
+ * Need to check that the SRE bit has actually been set. If
+ * not, it means that SRE is disabled at EL2. We're going to
+ * die painfully, and there is nothing we can do about it.
+ *
+ * Kindly inform the luser.
+ */
+ if (!gic_enable_sre())
+ pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
/* Set priority mask register */
gic_write_pmr(DEFAULT_PMR_VALUE);
@@ -557,10 +523,10 @@ static struct notifier_block gic_cpu_notifier = {
};
static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
- u64 cluster_id)
+ unsigned long cluster_id)
{
int cpu = *base_cpu;
- u64 mpidr = cpu_logical_map(cpu);
+ unsigned long mpidr = cpu_logical_map(cpu);
u16 tlist = 0;
while (cpu < nr_cpu_ids) {
@@ -621,7 +587,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
smp_wmb();
for_each_cpu(cpu, mask) {
- u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL;
+ unsigned long cluster_id = cpu_logical_map(cpu) & ~0xffUL;
u16 tlist;
tlist = gic_compute_target_list(&cpu, mask, cluster_id);
@@ -657,7 +623,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
- writeq_relaxed(val, reg);
+ gic_write_irouter(val, reg);
/*
* If the interrupt was enabled, enabled it again. Otherwise,
@@ -771,32 +737,34 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
-static int gic_irq_domain_xlate(struct irq_domain *d,
- struct device_node *controller,
- const u32 *intspec, unsigned int intsize,
- unsigned long *out_hwirq, unsigned int *out_type)
+static int gic_irq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
{
- if (d->of_node != controller)
- return -EINVAL;
- if (intsize < 3)
- return -EINVAL;
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count < 3)
+ return -EINVAL;
- switch(intspec[0]) {
- case 0: /* SPI */
- *out_hwirq = intspec[1] + 32;
- break;
- case 1: /* PPI */
- *out_hwirq = intspec[1] + 16;
- break;
- case GIC_IRQ_TYPE_LPI: /* LPI */
- *out_hwirq = intspec[1];
- break;
- default:
- return -EINVAL;
+ switch (fwspec->param[0]) {
+ case 0: /* SPI */
+ *hwirq = fwspec->param[1] + 32;
+ break;
+ case 1: /* PPI */
+ *hwirq = fwspec->param[1] + 16;
+ break;
+ case GIC_IRQ_TYPE_LPI: /* LPI */
+ *hwirq = fwspec->param[1];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+ return 0;
}
- *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
- return 0;
+ return -EINVAL;
}
static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -805,10 +773,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
int i, ret;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
- struct of_phandle_args *irq_data = arg;
+ struct irq_fwspec *fwspec = arg;
- ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
- irq_data->args_count, &hwirq, &type);
+ ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
@@ -831,11 +798,19 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops gic_irq_domain_ops = {
- .xlate = gic_irq_domain_xlate,
+ .translate = gic_irq_domain_translate,
.alloc = gic_irq_domain_alloc,
.free = gic_irq_domain_free,
};
+static void gicv3_enable_quirks(void)
+{
+#ifdef CONFIG_ARM64
+ if (cpus_have_cap(ARM64_WORKAROUND_CAVIUM_23154))
+ static_branch_enable(&is_cavium_thunderx);
+#endif
+}
+
static int __init gic_of_init(struct device_node *node, struct device_node *parent)
{
void __iomem *dist_base;
@@ -901,6 +876,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
gic_data.nr_redist_regions = nr_redist_regions;
gic_data.redist_stride = redist_stride;
+ gicv3_enable_quirks();
+
/*
* Find out how many interrupts are supported.
* The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 982c09c2d791..abf2ffaed392 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -41,7 +41,6 @@
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqchip/arm-gic.h>
-#include <linux/irqchip/arm-gic-acpi.h>
#include <asm/cputype.h>
#include <asm/irq.h>
@@ -51,6 +50,19 @@
#include "irq-gic-common.h"
+#ifdef CONFIG_ARM64
+#include <asm/cpufeature.h>
+
+static void gic_check_cpu_features(void)
+{
+ WARN_TAINT_ONCE(cpus_have_cap(ARM64_HAS_SYSREG_GIC_CPUIF),
+ TAINT_CPU_OUT_OF_SPEC,
+ "GICv3 system registers enabled, broken firmware!\n");
+}
+#else
+#define gic_check_cpu_features() do { } while(0)
+#endif
+
union gic_base {
void __iomem *common_base;
void __percpu * __iomem *percpu_base;
@@ -61,9 +73,11 @@ struct gic_chip_data {
union gic_base cpu_base;
#ifdef CONFIG_CPU_PM
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+ u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
u32 __percpu *saved_ppi_enable;
+ u32 __percpu *saved_ppi_active;
u32 __percpu *saved_ppi_conf;
#endif
struct irq_domain *domain;
@@ -554,6 +568,10 @@ static void gic_dist_save(unsigned int gic_nr)
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
gic_data[gic_nr].saved_spi_enable[i] =
readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+ gic_data[gic_nr].saved_spi_active[i] =
+ readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
}
/*
@@ -592,9 +610,19 @@ static void gic_dist_restore(unsigned int gic_nr)
writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
dist_base + GIC_DIST_TARGET + i * 4);
- for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
dist_base + GIC_DIST_ENABLE_SET + i * 4);
+ }
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
+ writel_relaxed(gic_data[gic_nr].saved_spi_active[i],
+ dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+ }
writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
}
@@ -619,6 +647,10 @@ static void gic_cpu_save(unsigned int gic_nr)
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+ ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
+ for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+ ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
@@ -642,8 +674,18 @@ static void gic_cpu_restore(unsigned int gic_nr)
return;
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
- for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+ for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+ }
+
+ ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
+ for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
+ writel_relaxed(GICD_INT_EN_CLR_X32,
+ dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
+ writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+ }
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
@@ -698,6 +740,10 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
sizeof(u32));
BUG_ON(!gic->saved_ppi_enable);
+ gic->saved_ppi_active = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
+ sizeof(u32));
+ BUG_ON(!gic->saved_ppi_active);
+
gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
sizeof(u32));
BUG_ON(!gic->saved_ppi_conf);
@@ -903,28 +949,39 @@ static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
{
}
-static int gic_irq_domain_xlate(struct irq_domain *d,
- struct device_node *controller,
- const u32 *intspec, unsigned int intsize,
- unsigned long *out_hwirq, unsigned int *out_type)
+static int gic_irq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
{
- unsigned long ret = 0;
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count < 3)
+ return -EINVAL;
- if (d->of_node != controller)
- return -EINVAL;
- if (intsize < 3)
- return -EINVAL;
+ /* Get the interrupt number and add 16 to skip over SGIs */
+ *hwirq = fwspec->param[1] + 16;
- /* Get the interrupt number and add 16 to skip over SGIs */
- *out_hwirq = intspec[1] + 16;
+ /*
+ * For SPIs, we need to add 16 more to get the GIC irq
+ * ID number
+ */
+ if (!fwspec->param[0])
+ *hwirq += 16;
- /* For SPIs, we need to add 16 more to get the GIC irq ID number */
- if (!intspec[0])
- *out_hwirq += 16;
+ *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+ }
- *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+ if (fwspec->fwnode->type == FWNODE_IRQCHIP) {
+ if(fwspec->param_count != 2)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1];
+ return 0;
+ }
- return ret;
+ return -EINVAL;
}
#ifdef CONFIG_SMP
@@ -952,10 +1009,9 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
int i, ret;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
- struct of_phandle_args *irq_data = arg;
+ struct irq_fwspec *fwspec = arg;
- ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
- irq_data->args_count, &hwirq, &type);
+ ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
@@ -966,7 +1022,7 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
- .xlate = gic_irq_domain_xlate,
+ .translate = gic_irq_domain_translate,
.alloc = gic_irq_domain_alloc,
.free = irq_domain_free_irqs_top,
};
@@ -974,12 +1030,11 @@ static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
static const struct irq_domain_ops gic_irq_domain_ops = {
.map = gic_irq_domain_map,
.unmap = gic_irq_domain_unmap,
- .xlate = gic_irq_domain_xlate,
};
static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
void __iomem *dist_base, void __iomem *cpu_base,
- u32 percpu_offset, struct device_node *node)
+ u32 percpu_offset, struct fwnode_handle *handle)
{
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
@@ -987,6 +1042,8 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
BUG_ON(gic_nr >= MAX_GIC_NR);
+ gic_check_cpu_features();
+
gic = &gic_data[gic_nr];
#ifdef CONFIG_GIC_NON_BANKED
if (percpu_offset) { /* Frankein-GIC without banked registers... */
@@ -1031,11 +1088,11 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
gic_irqs = 1020;
gic->gic_irqs = gic_irqs;
- if (node) { /* DT case */
- gic->domain = irq_domain_add_linear(node, gic_irqs,
- &gic_irq_domain_hierarchy_ops,
- gic);
- } else { /* Non-DT case */
+ if (handle) { /* DT/ACPI */
+ gic->domain = irq_domain_create_linear(handle, gic_irqs,
+ &gic_irq_domain_hierarchy_ops,
+ gic);
+ } else { /* Legacy support */
/*
* For primary GICs, skip over SGIs.
* For secondary GICs, skip over PPIs, too.
@@ -1058,7 +1115,7 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
irq_base = irq_start;
}
- gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
+ gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base,
hwirq_base, &gic_irq_domain_ops, gic);
}
@@ -1087,17 +1144,15 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
gic_pm_init(gic);
}
-void __init gic_init_bases(unsigned int gic_nr, int irq_start,
- void __iomem *dist_base, void __iomem *cpu_base,
- u32 percpu_offset, struct device_node *node)
+void __init gic_init(unsigned int gic_nr, int irq_start,
+ void __iomem *dist_base, void __iomem *cpu_base)
{
/*
* Non-DT/ACPI systems won't run a hypervisor, so let's not
* bother with these...
*/
static_key_slow_dec(&supports_deactivate);
- __gic_init_bases(gic_nr, irq_start, dist_base, cpu_base,
- percpu_offset, node);
+ __gic_init_bases(gic_nr, irq_start, dist_base, cpu_base, 0, NULL);
}
#ifdef CONFIG_OF
@@ -1168,7 +1223,8 @@ gic_of_init(struct device_node *node, struct device_node *parent)
if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
percpu_offset = 0;
- __gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
+ __gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
+ &node->fwnode);
if (!gic_cnt)
gic_init_physaddr(node);
@@ -1191,11 +1247,12 @@ IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
+IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
#endif
#ifdef CONFIG_ACPI
-static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+static phys_addr_t cpu_phy_base __initdata;
static int __init
gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
@@ -1223,60 +1280,57 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
return 0;
}
-static int __init
-gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
- const unsigned long end)
+/* The things you have to do to just *count* something... */
+static int __init acpi_dummy_func(struct acpi_subtable_header *header,
+ const unsigned long end)
{
- struct acpi_madt_generic_distributor *dist;
+ return 0;
+}
- dist = (struct acpi_madt_generic_distributor *)header;
+static bool __init acpi_gic_redist_is_present(void)
+{
+ return acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+ acpi_dummy_func, 0) > 0;
+}
- if (BAD_MADT_ENTRY(dist, end))
- return -EINVAL;
+static bool __init gic_validate_dist(struct acpi_subtable_header *header,
+ struct acpi_probe_entry *ape)
+{
+ struct acpi_madt_generic_distributor *dist;
+ dist = (struct acpi_madt_generic_distributor *)header;
- dist_phy_base = dist->base_address;
- return 0;
+ return (dist->version == ape->driver_data &&
+ (dist->version != ACPI_MADT_GIC_VERSION_NONE ||
+ !acpi_gic_redist_is_present()));
}
-int __init
-gic_v2_acpi_init(struct acpi_table_header *table)
+#define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K)
+#define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K)
+
+static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
+ const unsigned long end)
{
+ struct acpi_madt_generic_distributor *dist;
void __iomem *cpu_base, *dist_base;
+ struct fwnode_handle *domain_handle;
int count;
/* Collect CPU base addresses */
- count = acpi_parse_entries(ACPI_SIG_MADT,
- sizeof(struct acpi_table_madt),
- gic_acpi_parse_madt_cpu, table,
- ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+ gic_acpi_parse_madt_cpu, 0);
if (count <= 0) {
pr_err("No valid GICC entries exist\n");
return -EINVAL;
}
- /*
- * Find distributor base address. We expect one distributor entry since
- * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
- */
- count = acpi_parse_entries(ACPI_SIG_MADT,
- sizeof(struct acpi_table_madt),
- gic_acpi_parse_madt_distributor, table,
- ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
- if (count <= 0) {
- pr_err("No valid GICD entries exist\n");
- return -EINVAL;
- } else if (count > 1) {
- pr_err("More than one GICD entry detected\n");
- return -EINVAL;
- }
-
cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
if (!cpu_base) {
pr_err("Unable to map GICC registers\n");
return -ENOMEM;
}
- dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE);
+ dist = (struct acpi_madt_generic_distributor *)header;
+ dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE);
if (!dist_base) {
pr_err("Unable to map GICD registers\n");
iounmap(cpu_base);
@@ -1292,14 +1346,25 @@ gic_v2_acpi_init(struct acpi_table_header *table)
static_key_slow_dec(&supports_deactivate);
/*
- * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
- * as default IRQ domain to allow for GSI registration and GSI to IRQ
- * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
+ * Initialize GIC instance zero (no multi-GIC support).
*/
- __gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
- irq_set_default_host(gic_data[0].domain);
+ domain_handle = irq_domain_alloc_fwnode(dist_base);
+ if (!domain_handle) {
+ pr_err("Unable to allocate domain handle\n");
+ iounmap(cpu_base);
+ iounmap(dist_base);
+ return -ENOMEM;
+ }
+
+ __gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
- acpi_irq_model = ACPI_IRQ_MODEL_GIC;
+ acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
return 0;
}
+IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+ gic_validate_dist, ACPI_MADT_GIC_VERSION_V2,
+ gic_v2_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v2_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+ gic_validate_dist, ACPI_MADT_GIC_VERSION_NONE,
+ gic_v2_acpi_init);
#endif
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 8f3ca8f3a62b..9688d2e2a636 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -325,7 +325,7 @@ static int hip04_irq_domain_xlate(struct irq_domain *d,
{
unsigned long ret = 0;
- if (d->of_node != controller)
+ if (irq_domain_get_of_node(d) != controller)
return -EINVAL;
if (intsize < 3)
return -EINVAL;
diff --git a/drivers/irqchip/irq-i8259.c b/drivers/irqchip/irq-i8259.c
index e484fd255321..6b304eb39bd2 100644
--- a/drivers/irqchip/irq-i8259.c
+++ b/drivers/irqchip/irq-i8259.c
@@ -377,8 +377,8 @@ int __init i8259_of_init(struct device_node *node, struct device_node *parent)
}
domain = __init_i8259_irqs(node);
- irq_set_handler_data(parent_irq, domain);
- irq_set_chained_handler(parent_irq, i8259_irq_dispatch);
+ irq_set_chained_handler_and_data(parent_irq, i8259_irq_dispatch,
+ domain);
return 0;
}
IRQCHIP_DECLARE(i8259, "intel,i8259", i8259_of_init);
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index e48d3305456f..15af9a9753e5 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -150,49 +150,42 @@ static struct irq_chip gpcv2_irqchip_data_chip = {
#endif
};
-static int imx_gpcv2_domain_xlate(struct irq_domain *domain,
- struct device_node *controller,
- const u32 *intspec,
- unsigned int intsize,
- unsigned long *out_hwirq,
- unsigned int *out_type)
+static int imx_gpcv2_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
{
- /* Shouldn't happen, really... */
- if (domain->of_node != controller)
- return -EINVAL;
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 3)
+ return -EINVAL;
- /* Not GIC compliant */
- if (intsize != 3)
- return -EINVAL;
+ /* No PPI should point to this domain */
+ if (fwspec->param[0] != 0)
+ return -EINVAL;
- /* No PPI should point to this domain */
- if (intspec[0] != 0)
- return -EINVAL;
+ *hwirq = fwspec->param[1];
+ *type = fwspec->param[2];
+ return 0;
+ }
- *out_hwirq = intspec[1];
- *out_type = intspec[2];
- return 0;
+ return -EINVAL;
}
static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
unsigned int irq, unsigned int nr_irqs,
void *data)
{
- struct of_phandle_args *args = data;
- struct of_phandle_args parent_args;
+ struct irq_fwspec *fwspec = data;
+ struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
+ unsigned int type;
+ int err;
int i;
- /* Not GIC compliant */
- if (args->args_count != 3)
- return -EINVAL;
-
- /* No PPI should point to this domain */
- if (args->args[0] != 0)
- return -EINVAL;
+ err = imx_gpcv2_domain_translate(domain, fwspec, &hwirq, &type);
+ if (err)
+ return err;
- /* Can't deal with this */
- hwirq = args->args[1];
if (hwirq >= GPC_MAX_IRQS)
return -EINVAL;
@@ -201,15 +194,16 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
&gpcv2_irqchip_data_chip, domain->host_data);
}
- parent_args = *args;
- parent_args.np = domain->parent->of_node;
- return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+ parent_fwspec = *fwspec;
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+ &parent_fwspec);
}
static struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
- .xlate = imx_gpcv2_domain_xlate,
- .alloc = imx_gpcv2_domain_alloc,
- .free = irq_domain_free_irqs_common,
+ .translate = imx_gpcv2_domain_translate,
+ .alloc = imx_gpcv2_domain_alloc,
+ .free = irq_domain_free_irqs_common,
};
static int __init imx_gpcv2_irqchip_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index aeaa061f0dbf..9e17ef27a183 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -29,6 +29,7 @@ struct gic_pcpu_mask {
DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
};
+static unsigned long __gic_base_addr;
static void __iomem *gic_base;
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
static DEFINE_SPINLOCK(gic_lock);
@@ -301,6 +302,17 @@ int gic_get_c0_fdc_int(void)
GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
}
+int gic_get_usm_range(struct resource *gic_usm_res)
+{
+ if (!gic_present)
+ return -1;
+
+ gic_usm_res->start = __gic_base_addr + USM_VISIBLE_SECTION_OFS;
+ gic_usm_res->end = gic_usm_res->start + (USM_VISIBLE_SECTION_SIZE - 1);
+
+ return 0;
+}
+
static void gic_handle_shared_int(bool chained)
{
unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
@@ -798,6 +810,8 @@ static void __init __gic_init(unsigned long gic_base_addr,
{
unsigned int gicconfig;
+ __gic_base_addr = gic_base_addr;
+
gic_base = ioremap_nocache(gic_base_addr, gic_addrspace_size);
gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index c8753da4c156..63ac73b1d9c8 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -67,22 +67,25 @@ static struct irq_chip mtk_sysirq_chip = {
.irq_set_affinity = irq_chip_set_affinity_parent,
};
-static int mtk_sysirq_domain_xlate(struct irq_domain *d,
- struct device_node *controller,
- const u32 *intspec, unsigned int intsize,
- unsigned long *out_hwirq,
- unsigned int *out_type)
+static int mtk_sysirq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
{
- if (intsize != 3)
- return -EINVAL;
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 3)
+ return -EINVAL;
- /* sysirq doesn't support PPI */
- if (intspec[0])
- return -EINVAL;
+ /* No PPI should point to this domain */
+ if (fwspec->param[0] != 0)
+ return -EINVAL;
- *out_hwirq = intspec[1];
- *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
- return 0;
+ *hwirq = fwspec->param[1];
+ *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+ }
+
+ return -EINVAL;
}
static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
@@ -90,30 +93,30 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
{
int i;
irq_hw_number_t hwirq;
- struct of_phandle_args *irq_data = arg;
- struct of_phandle_args gic_data = *irq_data;
+ struct irq_fwspec *fwspec = arg;
+ struct irq_fwspec gic_fwspec = *fwspec;
- if (irq_data->args_count != 3)
+ if (fwspec->param_count != 3)
return -EINVAL;
/* sysirq doesn't support PPI */
- if (irq_data->args[0])
+ if (fwspec->param[0])
return -EINVAL;
- hwirq = irq_data->args[1];
+ hwirq = fwspec->param[1];
for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&mtk_sysirq_chip,
domain->host_data);
- gic_data.np = domain->parent->of_node;
- return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+ gic_fwspec.fwnode = domain->parent->fwnode;
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec);
}
static const struct irq_domain_ops sysirq_domain_ops = {
- .xlate = mtk_sysirq_domain_xlate,
- .alloc = mtk_sysirq_domain_alloc,
- .free = irq_domain_free_irqs_common,
+ .translate = mtk_sysirq_domain_translate,
+ .alloc = mtk_sysirq_domain_alloc,
+ .free = irq_domain_free_irqs_common,
};
static int __init mtk_sysirq_of_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 604df63e2edf..c22e2d40cb30 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ * Add Alphascale ASM9260 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
@@ -28,20 +30,64 @@
#include <linux/stmp_device.h>
#include <asm/exception.h>
+#include "alphascale_asm9260-icoll.h"
+
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
#define HW_ICOLL_VECTOR 0x0000
#define HW_ICOLL_LEVELACK 0x0010
#define HW_ICOLL_CTRL 0x0020
#define HW_ICOLL_STAT_OFFSET 0x0070
-#define HW_ICOLL_INTERRUPTn_SET(n) (0x0124 + (n) * 0x10)
-#define HW_ICOLL_INTERRUPTn_CLR(n) (0x0128 + (n) * 0x10)
-#define BM_ICOLL_INTERRUPTn_ENABLE 0x00000004
+#define HW_ICOLL_INTERRUPT0 0x0120
+#define HW_ICOLL_INTERRUPTn(n) ((n) * 0x10)
+#define BM_ICOLL_INTR_ENABLE BIT(2)
#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 0x1
#define ICOLL_NUM_IRQS 128
-static void __iomem *icoll_base;
+enum icoll_type {
+ ICOLL,
+ ASM9260_ICOLL,
+};
+
+struct icoll_priv {
+ void __iomem *vector;
+ void __iomem *levelack;
+ void __iomem *ctrl;
+ void __iomem *stat;
+ void __iomem *intr;
+ void __iomem *clear;
+ enum icoll_type type;
+};
+
+static struct icoll_priv icoll_priv;
static struct irq_domain *icoll_domain;
+/* calculate bit offset depending on number of intterupt per register */
+static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
+{
+ /*
+ * mask lower part of hwirq to convert it
+ * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
+ */
+ return bit << ((d->hwirq & 3) << 3);
+}
+
+/* calculate mem offset depending on number of intterupt per register */
+static void __iomem *icoll_intr_reg(struct irq_data *d)
+{
+ /* offset = hwirq / intr_per_reg * 0x10 */
+ return icoll_priv.intr + ((d->hwirq >> 2) * 0x10);
+}
+
static void icoll_ack_irq(struct irq_data *d)
{
/*
@@ -50,19 +96,35 @@ static void icoll_ack_irq(struct irq_data *d)
* BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
*/
__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
- icoll_base + HW_ICOLL_LEVELACK);
+ icoll_priv.levelack);
}
static void icoll_mask_irq(struct irq_data *d)
{
- __raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
- icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
+ __raw_writel(BM_ICOLL_INTR_ENABLE,
+ icoll_priv.intr + CLR_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
}
static void icoll_unmask_irq(struct irq_data *d)
{
- __raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
- icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+ __raw_writel(BM_ICOLL_INTR_ENABLE,
+ icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
+}
+
+static void asm9260_mask_irq(struct irq_data *d)
+{
+ __raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+ icoll_intr_reg(d) + CLR_REG);
+}
+
+static void asm9260_unmask_irq(struct irq_data *d)
+{
+ __raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
+ icoll_priv.clear +
+ ASM9260_HW_ICOLL_CLEARn(d->hwirq));
+
+ __raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+ icoll_intr_reg(d) + SET_REG);
}
static struct irq_chip mxs_icoll_chip = {
@@ -71,19 +133,32 @@ static struct irq_chip mxs_icoll_chip = {
.irq_unmask = icoll_unmask_irq,
};
+static struct irq_chip asm9260_icoll_chip = {
+ .irq_ack = icoll_ack_irq,
+ .irq_mask = asm9260_mask_irq,
+ .irq_unmask = asm9260_unmask_irq,
+};
+
asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
{
u32 irqnr;
- irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
- __raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+ irqnr = __raw_readl(icoll_priv.stat);
+ __raw_writel(irqnr, icoll_priv.vector);
handle_domain_irq(icoll_domain, irqnr, regs);
}
static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
{
- irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
+ struct irq_chip *chip;
+
+ if (icoll_priv.type == ICOLL)
+ chip = &mxs_icoll_chip;
+ else
+ chip = &asm9260_icoll_chip;
+
+ irq_set_chip_and_handler(virq, chip, handle_level_irq);
return 0;
}
@@ -93,20 +168,80 @@ static const struct irq_domain_ops icoll_irq_domain_ops = {
.xlate = irq_domain_xlate_onecell,
};
+static void __init icoll_add_domain(struct device_node *np,
+ int num)
+{
+ icoll_domain = irq_domain_add_linear(np, num,
+ &icoll_irq_domain_ops, NULL);
+
+ if (!icoll_domain)
+ panic("%s: unable to create irq domain", np->full_name);
+}
+
+static void __iomem * __init icoll_init_iobase(struct device_node *np)
+{
+ void __iomem *icoll_base;
+
+ icoll_base = of_io_request_and_map(np, 0, np->name);
+ if (!icoll_base)
+ panic("%s: unable to map resource", np->full_name);
+ return icoll_base;
+}
+
static int __init icoll_of_init(struct device_node *np,
struct device_node *interrupt_parent)
{
- icoll_base = of_iomap(np, 0);
- WARN_ON(!icoll_base);
+ void __iomem *icoll_base;
+
+ icoll_priv.type = ICOLL;
+
+ icoll_base = icoll_init_iobase(np);
+ icoll_priv.vector = icoll_base + HW_ICOLL_VECTOR;
+ icoll_priv.levelack = icoll_base + HW_ICOLL_LEVELACK;
+ icoll_priv.ctrl = icoll_base + HW_ICOLL_CTRL;
+ icoll_priv.stat = icoll_base + HW_ICOLL_STAT_OFFSET;
+ icoll_priv.intr = icoll_base + HW_ICOLL_INTERRUPT0;
+ icoll_priv.clear = NULL;
/*
* Interrupt Collector reset, which initializes the priority
* for each irq to level 0.
*/
- stmp_reset_block(icoll_base + HW_ICOLL_CTRL);
+ stmp_reset_block(icoll_priv.ctrl);
- icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
- &icoll_irq_domain_ops, NULL);
- return icoll_domain ? 0 : -ENODEV;
+ icoll_add_domain(np, ICOLL_NUM_IRQS);
+
+ return 0;
}
IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
+
+static int __init asm9260_of_init(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ void __iomem *icoll_base;
+ int i;
+
+ icoll_priv.type = ASM9260_ICOLL;
+
+ icoll_base = icoll_init_iobase(np);
+ icoll_priv.vector = icoll_base + ASM9260_HW_ICOLL_VECTOR;
+ icoll_priv.levelack = icoll_base + ASM9260_HW_ICOLL_LEVELACK;
+ icoll_priv.ctrl = icoll_base + ASM9260_HW_ICOLL_CTRL;
+ icoll_priv.stat = icoll_base + ASM9260_HW_ICOLL_STAT_OFFSET;
+ icoll_priv.intr = icoll_base + ASM9260_HW_ICOLL_INTERRUPT0;
+ icoll_priv.clear = icoll_base + ASM9260_HW_ICOLL_CLEAR0;
+
+ writel_relaxed(ASM9260_BM_CTRL_IRQ_ENABLE,
+ icoll_priv.ctrl);
+ /*
+ * ASM9260 don't provide reset bit. So, we need to set level 0
+ * manually.
+ */
+ for (i = 0; i < 16 * 0x10; i += 0x10)
+ writel(0, icoll_priv.intr + i);
+
+ icoll_add_domain(np, ASM9260_NUM_IRQS);
+
+ return 0;
+}
+IRQCHIP_DECLARE(asm9260, "alphascale,asm9260-icoll", asm9260_of_init);
diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c
index a878b8d03868..b1777104fd9f 100644
--- a/drivers/irqchip/irq-nvic.c
+++ b/drivers/irqchip/irq-nvic.c
@@ -48,16 +48,26 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
handle_IRQ(irq, regs);
}
+static int nvic_irq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq, unsigned int *type)
+{
+ if (WARN_ON(fwspec->param_count < 1))
+ return -EINVAL;
+ *hwirq = fwspec->param[0];
+ *type = IRQ_TYPE_NONE;
+ return 0;
+}
+
static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *arg)
{
int i, ret;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
- struct of_phandle_args *irq_data = arg;
+ struct irq_fwspec *fwspec = arg;
- ret = irq_domain_xlate_onecell(domain, irq_data->np, irq_data->args,
- irq_data->args_count, &hwirq, &type);
+ ret = nvic_irq_domain_translate(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
@@ -68,7 +78,7 @@ static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops nvic_irq_domain_ops = {
- .xlate = irq_domain_xlate_onecell,
+ .translate = nvic_irq_domain_translate,
.alloc = nvic_irq_domain_alloc,
.free = irq_domain_free_irqs_top,
};
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 9525335723f6..c325806561be 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -361,14 +361,16 @@ static const struct irq_domain_ops intc_irqpin_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
};
-static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a7779 = {
+static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a777x = {
.irlm_bit = 23, /* ICR0.IRLM0 */
};
static const struct of_device_id intc_irqpin_dt_ids[] = {
{ .compatible = "renesas,intc-irqpin", },
+ { .compatible = "renesas,intc-irqpin-r8a7778",
+ .data = &intc_irqpin_irlm_r8a777x },
{ .compatible = "renesas,intc-irqpin-r8a7779",
- .data = &intc_irqpin_irlm_r8a7779 },
+ .data = &intc_irqpin_irlm_r8a777x },
{},
};
MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 35bf97ba4a3d..52304b139aa4 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -62,33 +62,20 @@ struct irqc_priv {
struct irqc_irq irq[IRQC_IRQ_MAX];
unsigned int number_of_irqs;
struct platform_device *pdev;
- struct irq_chip irq_chip;
+ struct irq_chip_generic *gc;
struct irq_domain *irq_domain;
struct clk *clk;
};
-static void irqc_dbg(struct irqc_irq *i, char *str)
-{
- dev_dbg(&i->p->pdev->dev, "%s (%d:%d)\n",
- str, i->requested_irq, i->hw_irq);
-}
-
-static void irqc_irq_enable(struct irq_data *d)
+static struct irqc_priv *irq_data_to_priv(struct irq_data *data)
{
- struct irqc_priv *p = irq_data_get_irq_chip_data(d);
- int hw_irq = irqd_to_hwirq(d);
-
- irqc_dbg(&p->irq[hw_irq], "enable");
- iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET);
+ return data->domain->host_data;
}
-static void irqc_irq_disable(struct irq_data *d)
+static void irqc_dbg(struct irqc_irq *i, char *str)
{
- struct irqc_priv *p = irq_data_get_irq_chip_data(d);
- int hw_irq = irqd_to_hwirq(d);
-
- irqc_dbg(&p->irq[hw_irq], "disable");
- iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS);
+ dev_dbg(&i->p->pdev->dev, "%s (%d:%d)\n",
+ str, i->requested_irq, i->hw_irq);
}
static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
@@ -101,7 +88,7 @@ static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
{
- struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+ struct irqc_priv *p = irq_data_to_priv(d);
int hw_irq = irqd_to_hwirq(d);
unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
u32 tmp;
@@ -120,7 +107,7 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
static int irqc_irq_set_wake(struct irq_data *d, unsigned int on)
{
- struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+ struct irqc_priv *p = irq_data_to_priv(d);
int hw_irq = irqd_to_hwirq(d);
irq_set_irq_wake(p->irq[hw_irq].requested_irq, on);
@@ -153,35 +140,11 @@ static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
-/*
- * This lock class tells lockdep that IRQC irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key irqc_irq_lock_class;
-
-static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct irqc_priv *p = h->host_data;
-
- irqc_dbg(&p->irq[hw], "map");
- irq_set_chip_data(virq, h->host_data);
- irq_set_lockdep_class(virq, &irqc_irq_lock_class);
- irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
- return 0;
-}
-
-static const struct irq_domain_ops irqc_irq_domain_ops = {
- .map = irqc_irq_domain_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
static int irqc_probe(struct platform_device *pdev)
{
struct irqc_priv *p;
struct resource *io;
struct resource *irq;
- struct irq_chip *irq_chip;
const char *name = dev_name(&pdev->dev);
int ret;
int k;
@@ -241,40 +204,51 @@ static int irqc_probe(struct platform_device *pdev)
p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
- irq_chip = &p->irq_chip;
- irq_chip->name = name;
- irq_chip->irq_mask = irqc_irq_disable;
- irq_chip->irq_unmask = irqc_irq_enable;
- irq_chip->irq_set_type = irqc_irq_set_type;
- irq_chip->irq_set_wake = irqc_irq_set_wake;
- irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
-
p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
p->number_of_irqs,
- &irqc_irq_domain_ops, p);
+ &irq_generic_chip_ops, p);
if (!p->irq_domain) {
ret = -ENXIO;
dev_err(&pdev->dev, "cannot initialize irq domain\n");
goto err2;
}
+ ret = irq_alloc_domain_generic_chips(p->irq_domain, p->number_of_irqs,
+ 1, name, handle_level_irq,
+ 0, 0, IRQ_GC_INIT_NESTED_LOCK);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot allocate generic chip\n");
+ goto err3;
+ }
+
+ p->gc = irq_get_domain_generic_chip(p->irq_domain, 0);
+ p->gc->reg_base = p->cpu_int_base;
+ p->gc->chip_types[0].regs.enable = IRQC_EN_SET;
+ p->gc->chip_types[0].regs.disable = IRQC_EN_STS;
+ p->gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+ p->gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+ p->gc->chip_types[0].chip.irq_set_type = irqc_irq_set_type;
+ p->gc->chip_types[0].chip.irq_set_wake = irqc_irq_set_wake;
+ p->gc->chip_types[0].chip.flags = IRQCHIP_MASK_ON_SUSPEND;
+
/* request interrupts one by one */
for (k = 0; k < p->number_of_irqs; k++) {
if (request_irq(p->irq[k].requested_irq, irqc_irq_handler,
0, name, &p->irq[k])) {
dev_err(&pdev->dev, "failed to request IRQ\n");
ret = -ENOENT;
- goto err3;
+ goto err4;
}
}
dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
return 0;
-err3:
+err4:
while (--k >= 0)
free_irq(p->irq[k].requested_irq, &p->irq[k]);
+err3:
irq_domain_remove(p->irq_domain);
err2:
iounmap(p->iomem);
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index 7154b011ddd2..c71914e8f596 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -311,7 +311,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
* and one big domain for the dt case where the subintc
* starts at hwirq number 32.
*/
- offset = (intc->domain->of_node) ? 32 : 0;
+ offset = irq_domain_get_of_node(intc->domain) ? 32 : 0;
chained_irq_enter(chip, desc);
@@ -342,7 +342,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
return false;
/* non-dt machines use individual domains */
- if (!intc->domain->of_node)
+ if (!irq_domain_get_of_node(intc->domain))
intc_offset = 0;
/* We have a problem that the INTOFFSET register does not always
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index c143dd58410c..4ef178078e5b 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -8,6 +8,9 @@
* warranty of any kind, whether express or implied.
*/
+#define DRV_NAME "sunxi-nmi"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/io.h>
@@ -96,8 +99,8 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
break;
default:
irq_gc_unlock(gc);
- pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n",
- __func__, data->irq);
+ pr_err("Cannot assign multiple trigger modes to IRQ %d.\n",
+ data->irq);
return -EBADR;
}
@@ -130,30 +133,29 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
domain = irq_domain_add_linear(node, 1, &irq_generic_chip_ops, NULL);
if (!domain) {
- pr_err("%s: Could not register interrupt domain.\n", node->name);
+ pr_err("Could not register interrupt domain.\n");
return -ENOMEM;
}
- ret = irq_alloc_domain_generic_chips(domain, 1, 2, node->name,
+ ret = irq_alloc_domain_generic_chips(domain, 1, 2, DRV_NAME,
handle_fasteoi_irq, clr, 0,
IRQ_GC_INIT_MASK_CACHE);
if (ret) {
- pr_err("%s: Could not allocate generic interrupt chip.\n",
- node->name);
- goto fail_irqd_remove;
+ pr_err("Could not allocate generic interrupt chip.\n");
+ goto fail_irqd_remove;
}
irq = irq_of_parse_and_map(node, 0);
if (irq <= 0) {
- pr_err("%s: unable to parse irq\n", node->name);
+ pr_err("unable to parse irq\n");
ret = -EINVAL;
goto fail_irqd_remove;
}
gc = irq_get_domain_generic_chip(domain, 0);
- gc->reg_base = of_iomap(node, 0);
+ gc->reg_base = of_io_request_and_map(node, 0, of_node_full_name(node));
if (!gc->reg_base) {
- pr_err("%s: unable to map resource\n", node->name);
+ pr_err("unable to map resource\n");
ret = -ENOMEM;
goto fail_irqd_remove;
}
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 2fd89eb88f3a..121ec301372e 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -214,47 +214,50 @@ static struct irq_chip tegra_ictlr_chip = {
.irq_unmask = tegra_unmask,
.irq_retrigger = tegra_retrigger,
.irq_set_wake = tegra_set_wake,
+ .irq_set_type = irq_chip_set_type_parent,
.flags = IRQCHIP_MASK_ON_SUSPEND,
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
#endif
};
-static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
- struct device_node *controller,
- const u32 *intspec,
- unsigned int intsize,
- unsigned long *out_hwirq,
- unsigned int *out_type)
+static int tegra_ictlr_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
{
- if (domain->of_node != controller)
- return -EINVAL; /* Shouldn't happen, really... */
- if (intsize != 3)
- return -EINVAL; /* Not GIC compliant */
- if (intspec[0] != GIC_SPI)
- return -EINVAL; /* No PPI should point to this domain */
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 3)
+ return -EINVAL;
- *out_hwirq = intspec[1];
- *out_type = intspec[2];
- return 0;
+ /* No PPI should point to this domain */
+ if (fwspec->param[0] != 0)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[1];
+ *type = fwspec->param[2];
+ return 0;
+ }
+
+ return -EINVAL;
}
static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs, void *data)
{
- struct of_phandle_args *args = data;
- struct of_phandle_args parent_args;
+ struct irq_fwspec *fwspec = data;
+ struct irq_fwspec parent_fwspec;
struct tegra_ictlr_info *info = domain->host_data;
irq_hw_number_t hwirq;
unsigned int i;
- if (args->args_count != 3)
+ if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
- if (args->args[0] != GIC_SPI)
+ if (fwspec->param[0] != GIC_SPI)
return -EINVAL; /* No PPI should point to this domain */
- hwirq = args->args[1];
+ hwirq = fwspec->param[1];
if (hwirq >= (num_ictlrs * 32))
return -EINVAL;
@@ -266,9 +269,10 @@ static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
info->base[ictlr]);
}
- parent_args = *args;
- parent_args.np = domain->parent->of_node;
- return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+ parent_fwspec = *fwspec;
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+ &parent_fwspec);
}
static void tegra_ictlr_domain_free(struct irq_domain *domain,
@@ -284,9 +288,9 @@ static void tegra_ictlr_domain_free(struct irq_domain *domain,
}
static const struct irq_domain_ops tegra_ictlr_domain_ops = {
- .xlate = tegra_ictlr_domain_xlate,
- .alloc = tegra_ictlr_domain_alloc,
- .free = tegra_ictlr_domain_free,
+ .translate = tegra_ictlr_domain_translate,
+ .alloc = tegra_ictlr_domain_alloc,
+ .free = tegra_ictlr_domain_free,
};
static int __init tegra_ictlr_init(struct device_node *node,
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
index 2c2255886401..56b5e3cb9de2 100644
--- a/drivers/irqchip/irq-vf610-mscm-ir.c
+++ b/drivers/irqchip/irq-vf610-mscm-ir.c
@@ -130,35 +130,51 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
{
int i;
irq_hw_number_t hwirq;
- struct of_phandle_args *irq_data = arg;
- struct of_phandle_args gic_data;
+ struct irq_fwspec *fwspec = arg;
+ struct irq_fwspec parent_fwspec;
- if (irq_data->args_count != 2)
+ if (!irq_domain_get_of_node(domain->parent))
return -EINVAL;
- hwirq = irq_data->args[0];
+ if (fwspec->param_count != 2)
+ return -EINVAL;
+
+ hwirq = fwspec->param[0];
for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&vf610_mscm_ir_irq_chip,
domain->host_data);
- gic_data.np = domain->parent->of_node;
+ parent_fwspec.fwnode = domain->parent->fwnode;
if (mscm_ir_data->is_nvic) {
- gic_data.args_count = 1;
- gic_data.args[0] = irq_data->args[0];
+ parent_fwspec.param_count = 1;
+ parent_fwspec.param[0] = fwspec->param[0];
} else {
- gic_data.args_count = 3;
- gic_data.args[0] = GIC_SPI;
- gic_data.args[1] = irq_data->args[0];
- gic_data.args[2] = irq_data->args[1];
+ parent_fwspec.param_count = 3;
+ parent_fwspec.param[0] = GIC_SPI;
+ parent_fwspec.param[1] = fwspec->param[0];
+ parent_fwspec.param[2] = fwspec->param[1];
}
- return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+ &parent_fwspec);
+}
+
+static int vf610_mscm_ir_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ if (WARN_ON(fwspec->param_count < 2))
+ return -EINVAL;
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+ return 0;
}
static const struct irq_domain_ops mscm_irq_domain_ops = {
- .xlate = irq_domain_xlate_twocell,
+ .translate = vf610_mscm_ir_domain_translate,
.alloc = vf610_mscm_ir_domain_alloc,
.free = irq_domain_free_irqs_common,
};
@@ -205,7 +221,8 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node,
goto out_unmap;
}
- if (of_device_is_compatible(domain->parent->of_node, "arm,armv7m-nvic"))
+ if (of_device_is_compatible(irq_domain_get_of_node(domain->parent),
+ "arm,armv7m-nvic"))
mscm_ir_data->is_nvic = true;
cpu_pm_register_notifier(&mscm_ir_notifier_block);
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
index afd1af3dfe5a..2b35e68bea82 100644
--- a/drivers/irqchip/irqchip.c
+++ b/drivers/irqchip/irqchip.c
@@ -8,7 +8,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/acpi_irq.h>
+#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/of_irq.h>
#include <linux/irqchip.h>
@@ -27,6 +27,5 @@ extern struct of_device_id __irqchip_of_table[];
void __init irqchip_init(void)
{
of_irq_init(__irqchip_of_table);
-
- acpi_irq_init();
+ acpi_probe_device_table(irqchip);
}
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 0e5d673871c0..9600cd771f1a 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -646,14 +646,14 @@ rx_d_frame(struct hfc4s8s_l1 *l1p, int ech)
f1 = Read_hfc8_stable(l1p->hw, A_F1);
f2 = Read_hfc8(l1p->hw, A_F2);
- df = f1 - f2;
- if ((f1 - f2) < 0)
- df = f1 - f2 + MAX_F_CNT + 1;
+ if (f1 < f2)
+ df = MAX_F_CNT + 1 + f1 - f2;
+ else
+ df = f1 - f2;
- if (!df) {
+ if (!df)
return; /* no complete frame in fifo */
- }
z1 = Read_hfc16_stable(l1p->hw, A_Z1);
z2 = Read_hfc16(l1p->hw, A_Z2);
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index 18accb0a79cc..c53a53f6efb6 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1247,7 +1247,7 @@ static void
l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct sk_buff *skb;
+ struct sk_buff *skb, *nskb;
struct Layer2 *l2 = &st->l2;
u_char header[MAX_HEADER_LEN];
int i, hdr_space_needed;
@@ -1262,14 +1262,10 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
return;
hdr_space_needed = l2headersize(l2, 0);
- if (hdr_space_needed > skb_headroom(skb)) {
- struct sk_buff *orig_skb = skb;
-
- skb = skb_realloc_headroom(skb, hdr_space_needed);
- if (!skb) {
- dev_kfree_skb(orig_skb);
- return;
- }
+ nskb = skb_realloc_headroom(skb, hdr_space_needed);
+ if (!nskb) {
+ skb_queue_head(&l2->i_queue, skb);
+ return;
}
spin_lock_irqsave(&l2->lock, flags);
if (test_bit(FLG_MOD128, &l2->flag))
@@ -1282,7 +1278,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
p1);
dev_kfree_skb(l2->windowar[p1]);
}
- l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
+ l2->windowar[p1] = skb;
i = sethdraddr(&st->l2, header, CMD);
@@ -1295,8 +1291,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
l2->vs = (l2->vs + 1) % 8;
}
spin_unlock_irqrestore(&l2->lock, flags);
- memcpy(skb_push(skb, i), header, i);
- st->l2.l2l1(st, PH_PULL | INDICATION, skb);
+ memcpy(skb_push(nskb, i), header, i);
+ st->l2.l2l1(st, PH_PULL | INDICATION, nskb);
test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
FsmDelTimer(&st->l2.t203, 13);
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index c4198fa490bf..9c1e8adaf4fc 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -301,6 +301,8 @@ isdn_ppp_open(int min, struct file *file)
is->compflags = 0;
is->reset = isdn_ppp_ccp_reset_alloc(is);
+ if (!is->reset)
+ return -ENOMEM;
is->lp = NULL;
is->mp_seqno = 0; /* MP sequence number */
@@ -320,6 +322,10 @@ isdn_ppp_open(int min, struct file *file)
* VJ header compression init
*/
is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
+ if (IS_ERR(is->slcomp)) {
+ isdn_ppp_ccp_reset_free(is);
+ return PTR_ERR(is->slcomp);
+ }
#endif
#ifdef CONFIG_IPPP_FILTER
is->pass_filter = NULL;
@@ -567,10 +573,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
is->maxcid = val;
#ifdef CONFIG_ISDN_PPP_VJ
sltmp = slhc_init(16, val);
- if (!sltmp) {
- printk(KERN_ERR "ippp, can't realloc slhc struct\n");
- return -ENOMEM;
- }
+ if (IS_ERR(sltmp))
+ return PTR_ERR(sltmp);
if (is->slcomp)
slhc_free(is->slcomp);
is->slcomp = sltmp;
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index bc912611fe09..2175225af742 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1582,7 +1582,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
* line status register.
*/
if (port->flags & ASYNC_INITIALIZED) {
- tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */
+ tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
index 8b1a66c6ca8a..e72b4e73cd61 100644
--- a/drivers/isdn/mISDN/dsp_pipeline.c
+++ b/drivers/isdn/mISDN/dsp_pipeline.c
@@ -235,7 +235,7 @@ void dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
{
- int len, incomplete = 0, found = 0;
+ int incomplete = 0, found = 0;
char *dup, *tok, *name, *args;
struct dsp_element_entry *entry, *n;
struct dsp_pipeline_entry *pipeline_entry;
@@ -247,17 +247,9 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
if (!list_empty(&pipeline->list))
_dsp_pipeline_destroy(pipeline);
- if (!cfg)
- return 0;
-
- len = strlen(cfg);
- if (!len)
- return 0;
-
- dup = kmalloc(len + 1, GFP_ATOMIC);
+ dup = kstrdup(cfg, GFP_ATOMIC);
if (!dup)
return 0;
- strcpy(dup, cfg);
while ((tok = strsep(&dup, "|"))) {
if (!strlen(tok))
continue;
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 949cabb88f1c..5eb380a25903 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -1476,7 +1476,7 @@ static void
l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
{
struct layer2 *l2 = fi->userdata;
- struct sk_buff *skb, *nskb, *oskb;
+ struct sk_buff *skb, *nskb;
u_char header[MAX_L2HEADER_LEN];
u_int i, p1;
@@ -1486,48 +1486,34 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
skb = skb_dequeue(&l2->i_queue);
if (!skb)
return;
-
- if (test_bit(FLG_MOD128, &l2->flag))
- p1 = (l2->vs - l2->va) % 128;
- else
- p1 = (l2->vs - l2->va) % 8;
- p1 = (p1 + l2->sow) % l2->window;
- if (l2->windowar[p1]) {
- printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
- mISDNDevName4ch(&l2->ch), p1);
- dev_kfree_skb(l2->windowar[p1]);
- }
- l2->windowar[p1] = skb;
i = sethdraddr(l2, header, CMD);
if (test_bit(FLG_MOD128, &l2->flag)) {
header[i++] = l2->vs << 1;
header[i++] = l2->vr << 1;
+ } else
+ header[i++] = (l2->vr << 5) | (l2->vs << 1);
+ nskb = skb_realloc_headroom(skb, i);
+ if (!nskb) {
+ printk(KERN_WARNING "%s: no headroom(%d) copy for IFrame\n",
+ mISDNDevName4ch(&l2->ch), i);
+ skb_queue_head(&l2->i_queue, skb);
+ return;
+ }
+ if (test_bit(FLG_MOD128, &l2->flag)) {
+ p1 = (l2->vs - l2->va) % 128;
l2->vs = (l2->vs + 1) % 128;
} else {
- header[i++] = (l2->vr << 5) | (l2->vs << 1);
+ p1 = (l2->vs - l2->va) % 8;
l2->vs = (l2->vs + 1) % 8;
}
-
- nskb = skb_clone(skb, GFP_ATOMIC);
- p1 = skb_headroom(nskb);
- if (p1 >= i)
- memcpy(skb_push(nskb, i), header, i);
- else {
- printk(KERN_WARNING
- "%s: L2 pull_iqueue skb header(%d/%d) too short\n",
- mISDNDevName4ch(&l2->ch), i, p1);
- oskb = nskb;
- nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
- if (!nskb) {
- dev_kfree_skb(oskb);
- printk(KERN_WARNING "%s: no skb mem in %s\n",
- mISDNDevName4ch(&l2->ch), __func__);
- return;
- }
- memcpy(skb_put(nskb, i), header, i);
- memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
- dev_kfree_skb(oskb);
+ p1 = (p1 + l2->sow) % l2->window;
+ if (l2->windowar[p1]) {
+ printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
+ mISDNDevName4ch(&l2->ch), p1);
+ dev_kfree_skb(l2->windowar[p1]);
}
+ l2->windowar[p1] = skb;
+ memcpy(skb_push(nskb, i), header, i);
l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb);
test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 42990f2d0317..b1ab8bdf8251 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -556,6 +556,16 @@ config LEDS_KTD2692
Say Y to enable this driver.
+config LEDS_SEAD3
+ tristate "LED support for the MIPS SEAD 3 board"
+ depends on LEDS_CLASS && MIPS_SEAD3
+ help
+ Say Y here to include support for the FLED and PLED LEDs on SEAD3 eval
+ boards.
+
+ This driver can also be built as a module. If so the module
+ will be called leds-sead3.
+
comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)"
config LEDS_BLINKM
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index b503f92dc2c4..e9d53092765d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o
obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o
obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o
obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o
+obj-$(CONFIG_LEDS_SEAD3) += leds-sead3.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index ca51d58bed24..7385f98dd54b 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -102,70 +102,6 @@ static const struct attribute_group *led_groups[] = {
NULL,
};
-static void led_timer_function(unsigned long data)
-{
- struct led_classdev *led_cdev = (void *)data;
- unsigned long brightness;
- unsigned long delay;
-
- if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
- led_set_brightness_async(led_cdev, LED_OFF);
- return;
- }
-
- if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
- led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
- return;
- }
-
- brightness = led_get_brightness(led_cdev);
- if (!brightness) {
- /* Time to switch the LED on. */
- if (led_cdev->delayed_set_value) {
- led_cdev->blink_brightness =
- led_cdev->delayed_set_value;
- led_cdev->delayed_set_value = 0;
- }
- brightness = led_cdev->blink_brightness;
- delay = led_cdev->blink_delay_on;
- } else {
- /* Store the current brightness value to be able
- * to restore it when the delay_off period is over.
- */
- led_cdev->blink_brightness = brightness;
- brightness = LED_OFF;
- delay = led_cdev->blink_delay_off;
- }
-
- led_set_brightness_async(led_cdev, brightness);
-
- /* Return in next iteration if led is in one-shot mode and we are in
- * the final blink state so that the led is toggled each delay_on +
- * delay_off milliseconds in worst case.
- */
- if (led_cdev->flags & LED_BLINK_ONESHOT) {
- if (led_cdev->flags & LED_BLINK_INVERT) {
- if (brightness)
- led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
- } else {
- if (!brightness)
- led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
- }
- }
-
- mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
-}
-
-static void set_brightness_delayed(struct work_struct *ws)
-{
- struct led_classdev *led_cdev =
- container_of(ws, struct led_classdev, set_brightness_work);
-
- led_stop_software_blink(led_cdev);
-
- led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
-}
-
/**
* led_classdev_suspend - suspend an led_classdev.
* @led_cdev: the led_classdev to suspend.
@@ -283,10 +219,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
led_update_brightness(led_cdev);
- INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
-
- setup_timer(&led_cdev->blink_timer, led_timer_function,
- (unsigned long)led_cdev);
+ led_init_core(led_cdev);
#ifdef CONFIG_LEDS_TRIGGERS
led_trigger_set_default(led_cdev);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 549de7e24cfd..c1c3af089634 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -25,6 +25,70 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list);
+static void led_timer_function(unsigned long data)
+{
+ struct led_classdev *led_cdev = (void *)data;
+ unsigned long brightness;
+ unsigned long delay;
+
+ if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
+ led_set_brightness_async(led_cdev, LED_OFF);
+ return;
+ }
+
+ if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
+ led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+ return;
+ }
+
+ brightness = led_get_brightness(led_cdev);
+ if (!brightness) {
+ /* Time to switch the LED on. */
+ if (led_cdev->delayed_set_value) {
+ led_cdev->blink_brightness =
+ led_cdev->delayed_set_value;
+ led_cdev->delayed_set_value = 0;
+ }
+ brightness = led_cdev->blink_brightness;
+ delay = led_cdev->blink_delay_on;
+ } else {
+ /* Store the current brightness value to be able
+ * to restore it when the delay_off period is over.
+ */
+ led_cdev->blink_brightness = brightness;
+ brightness = LED_OFF;
+ delay = led_cdev->blink_delay_off;
+ }
+
+ led_set_brightness_async(led_cdev, brightness);
+
+ /* Return in next iteration if led is in one-shot mode and we are in
+ * the final blink state so that the led is toggled each delay_on +
+ * delay_off milliseconds in worst case.
+ */
+ if (led_cdev->flags & LED_BLINK_ONESHOT) {
+ if (led_cdev->flags & LED_BLINK_INVERT) {
+ if (brightness)
+ led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+ } else {
+ if (!brightness)
+ led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+ }
+ }
+
+ mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
+}
+
+static void set_brightness_delayed(struct work_struct *ws)
+{
+ struct led_classdev *led_cdev =
+ container_of(ws, struct led_classdev, set_brightness_work);
+
+ led_stop_software_blink(led_cdev);
+
+ led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
+}
+
static void led_set_software_blink(struct led_classdev *led_cdev,
unsigned long delay_on,
unsigned long delay_off)
@@ -72,6 +136,15 @@ static void led_blink_setup(struct led_classdev *led_cdev,
led_set_software_blink(led_cdev, *delay_on, *delay_off);
}
+void led_init_core(struct led_classdev *led_cdev)
+{
+ INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
+
+ setup_timer(&led_cdev->blink_timer, led_timer_function,
+ (unsigned long)led_cdev);
+}
+EXPORT_SYMBOL_GPL(led_init_core);
+
void led_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 1497a09166d6..7870840e7cc9 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -142,6 +142,7 @@ static int pm860x_led_dt_init(struct platform_device *pdev,
of_property_read_u32(np, "marvell,88pm860x-iset",
&iset);
data->iset = PM8606_LED_CURRENT(iset);
+ of_node_put(np);
break;
}
}
diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c
index 1793727bc9ae..c7ea5c626331 100644
--- a/drivers/leds/leds-bcm6328.c
+++ b/drivers/leds/leds-bcm6328.c
@@ -41,6 +41,11 @@
#define BCM6328_SERIAL_LED_SHIFT_DIR BIT(16)
#define BCM6328_LED_SHIFT_TEST BIT(30)
#define BCM6328_LED_TEST BIT(31)
+#define BCM6328_INIT_MASK (BCM6328_SERIAL_LED_EN | \
+ BCM6328_SERIAL_LED_MUX | \
+ BCM6328_SERIAL_LED_CLK_NPOL | \
+ BCM6328_SERIAL_LED_DATA_PPOL | \
+ BCM6328_SERIAL_LED_SHIFT_DIR)
#define BCM6328_LED_MODE_MASK 3
#define BCM6328_LED_MODE_OFF 0
@@ -281,11 +286,10 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
"linux,default-trigger",
NULL);
+ spin_lock_irqsave(lock, flags);
if (!of_property_read_string(nc, "default-state", &state)) {
- spin_lock_irqsave(lock, flags);
if (!strcmp(state, "on")) {
led->cdev.brightness = LED_FULL;
- bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
} else if (!strcmp(state, "keep")) {
void __iomem *mode;
unsigned long val, shift;
@@ -296,21 +300,28 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
else
mode = mem + BCM6328_REG_MODE_LO;
- val = bcm6328_led_read(mode) >> (shift % 16);
+ val = bcm6328_led_read(mode) >>
+ BCM6328_LED_SHIFT(shift % 16);
val &= BCM6328_LED_MODE_MASK;
- if (val == BCM6328_LED_MODE_ON)
+ if ((led->active_low && val == BCM6328_LED_MODE_ON) ||
+ (!led->active_low && val == BCM6328_LED_MODE_OFF))
led->cdev.brightness = LED_FULL;
- else {
+ else
led->cdev.brightness = LED_OFF;
- bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
- }
} else {
led->cdev.brightness = LED_OFF;
- bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
}
- spin_unlock_irqrestore(lock, flags);
+ } else {
+ led->cdev.brightness = LED_OFF;
}
+ if ((led->active_low && led->cdev.brightness == LED_FULL) ||
+ (!led->active_low && led->cdev.brightness == LED_OFF))
+ bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
+ else
+ bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
+ spin_unlock_irqrestore(lock, flags);
+
led->cdev.brightness_set = bcm6328_led_set;
led->cdev.blink_set = bcm6328_blink_set;
@@ -360,9 +371,17 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_LO, 0);
val = bcm6328_led_read(mem + BCM6328_REG_INIT);
- val &= ~BCM6328_SERIAL_LED_EN;
+ val &= ~(BCM6328_INIT_MASK);
if (of_property_read_bool(np, "brcm,serial-leds"))
val |= BCM6328_SERIAL_LED_EN;
+ if (of_property_read_bool(np, "brcm,serial-mux"))
+ val |= BCM6328_SERIAL_LED_MUX;
+ if (of_property_read_bool(np, "brcm,serial-clk-low"))
+ val |= BCM6328_SERIAL_LED_CLK_NPOL;
+ if (!of_property_read_bool(np, "brcm,serial-dat-low"))
+ val |= BCM6328_SERIAL_LED_DATA_PPOL;
+ if (!of_property_read_bool(np, "brcm,serial-shift-inv"))
+ val |= BCM6328_SERIAL_LED_SHIFT_DIR;
bcm6328_led_write(mem + BCM6328_REG_INIT, val);
for_each_available_child_of_node(np, child) {
@@ -373,7 +392,7 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
continue;
if (reg >= BCM6328_LED_MAX_COUNT) {
- dev_err(dev, "invalid LED (>= %d)\n",
+ dev_err(dev, "invalid LED (%u >= %d)\n", reg,
BCM6328_LED_MAX_COUNT);
continue;
}
@@ -384,8 +403,10 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
rc = bcm6328_led(dev, child, reg, mem, lock,
blink_leds, blink_delay);
- if (rc < 0)
+ if (rc < 0) {
+ of_node_put(child);
return rc;
+ }
}
return 0;
diff --git a/drivers/leds/leds-bcm6358.c b/drivers/leds/leds-bcm6358.c
index 7ea3526702e0..82b4ee1bc87e 100644
--- a/drivers/leds/leds-bcm6358.c
+++ b/drivers/leds/leds-bcm6358.c
@@ -215,8 +215,10 @@ static int bcm6358_leds_probe(struct platform_device *pdev)
}
rc = bcm6358_led(dev, child, reg, mem, lock);
- if (rc < 0)
+ if (rc < 0) {
+ of_node_put(child);
return rc;
+ }
}
return 0;
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index d97522080491..9be195707b39 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -36,7 +36,6 @@ static struct led_classdev qube_front_led = {
static int cobalt_qube_led_probe(struct platform_device *pdev)
{
struct resource *res;
- int retval;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -49,31 +48,11 @@ static int cobalt_qube_led_probe(struct platform_device *pdev)
led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
writeb(led_value, led_port);
- retval = led_classdev_register(&pdev->dev, &qube_front_led);
- if (retval)
- goto err_null;
-
- return 0;
-
-err_null:
- led_port = NULL;
-
- return retval;
-}
-
-static int cobalt_qube_led_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&qube_front_led);
-
- if (led_port)
- led_port = NULL;
-
- return 0;
+ return devm_led_classdev_register(&pdev->dev, &qube_front_led);
}
static struct platform_driver cobalt_qube_led_driver = {
.probe = cobalt_qube_led_probe,
- .remove = cobalt_qube_led_remove,
.driver = {
.name = "cobalt-qube-leds",
},
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
index db3ba8b42517..314159610d24 100644
--- a/drivers/leds/leds-dac124s085.c
+++ b/drivers/leds/leds-dac124s085.c
@@ -122,7 +122,6 @@ static struct spi_driver dac124s085_driver = {
.remove = dac124s085_remove,
.driver = {
.name = "dac124s085",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index af1876a3a77c..5db4515a4fd7 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -291,9 +291,22 @@ static int gpio_led_remove(struct platform_device *pdev)
return 0;
}
+static void gpio_led_shutdown(struct platform_device *pdev)
+{
+ struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < priv->num_leds; i++) {
+ struct gpio_led_data *led = &priv->leds[i];
+
+ gpio_led_set(&led->cdev, LED_OFF);
+ }
+}
+
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
.remove = gpio_led_remove,
+ .shutdown = gpio_led_shutdown,
.driver = {
.name = "leds-gpio",
.of_match_table = of_gpio_leds_match,
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index 0b84c0113126..a6b8db0e27f1 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -59,28 +59,15 @@ static int hp6xxled_probe(struct platform_device *pdev)
{
int ret;
- ret = led_classdev_register(&pdev->dev, &hp6xx_red_led);
+ ret = devm_led_classdev_register(&pdev->dev, &hp6xx_red_led);
if (ret < 0)
return ret;
- ret = led_classdev_register(&pdev->dev, &hp6xx_green_led);
- if (ret < 0)
- led_classdev_unregister(&hp6xx_red_led);
-
- return ret;
-}
-
-static int hp6xxled_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&hp6xx_red_led);
- led_classdev_unregister(&hp6xx_green_led);
-
- return 0;
+ return devm_led_classdev_register(&pdev->dev, &hp6xx_green_led);
}
static struct platform_driver hp6xxled_driver = {
.probe = hp6xxled_probe,
- .remove = hp6xxled_remove,
.driver = {
.name = "hp6xx-led",
},
diff --git a/drivers/leds/leds-ipaq-micro.c b/drivers/leds/leds-ipaq-micro.c
index 3776f516cd88..fa262b6b25eb 100644
--- a/drivers/leds/leds-ipaq-micro.c
+++ b/drivers/leds/leds-ipaq-micro.c
@@ -16,9 +16,9 @@
#define LED_YELLOW 0x00
#define LED_GREEN 0x01
-#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */
-#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
-#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
+#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */
+#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
+#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
static void micro_leds_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
@@ -79,14 +79,14 @@ static int micro_leds_blink_set(struct led_classdev *led_cdev,
};
msg.tx_data[0] = LED_GREEN;
- if (*delay_on > IPAQ_LED_MAX_DUTY ||
+ if (*delay_on > IPAQ_LED_MAX_DUTY ||
*delay_off > IPAQ_LED_MAX_DUTY)
- return -EINVAL;
+ return -EINVAL;
- if (*delay_on == 0 && *delay_off == 0) {
- *delay_on = 100;
- *delay_off = 100;
- }
+ if (*delay_on == 0 && *delay_off == 0) {
+ *delay_on = 100;
+ *delay_off = 100;
+ }
msg.tx_data[1] = 0;
if (*delay_on >= IPAQ_LED_MAX_DUTY)
@@ -111,7 +111,7 @@ static int micro_leds_probe(struct platform_device *pdev)
{
int ret;
- ret = led_classdev_register(&pdev->dev, &micro_led);
+ ret = devm_led_classdev_register(&pdev->dev, &micro_led);
if (ret) {
dev_err(&pdev->dev, "registering led failed: %d\n", ret);
return ret;
@@ -121,18 +121,11 @@ static int micro_leds_probe(struct platform_device *pdev)
return 0;
}
-static int micro_leds_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&micro_led);
- return 0;
-}
-
static struct platform_driver micro_leds_device_driver = {
.driver = {
.name = "ipaq-micro-leds",
},
.probe = micro_leds_probe,
- .remove = micro_leds_remove,
};
module_platform_driver(micro_leds_device_driver);
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
index 80ba048889d6..24c4b53a6b93 100644
--- a/drivers/leds/leds-locomo.c
+++ b/drivers/leds/leds-locomo.c
@@ -59,23 +59,13 @@ static int locomoled_probe(struct locomo_dev *ldev)
{
int ret;
- ret = led_classdev_register(&ldev->dev, &locomo_led0);
+ ret = devm_led_classdev_register(&ldev->dev, &locomo_led0);
if (ret < 0)
return ret;
- ret = led_classdev_register(&ldev->dev, &locomo_led1);
- if (ret < 0)
- led_classdev_unregister(&locomo_led0);
-
- return ret;
+ return devm_led_classdev_register(&ldev->dev, &locomo_led1);
}
-static int locomoled_remove(struct locomo_dev *dev)
-{
- led_classdev_unregister(&locomo_led0);
- led_classdev_unregister(&locomo_led1);
- return 0;
-}
static struct locomo_driver locomoled_driver = {
.drv = {
@@ -83,7 +73,6 @@ static struct locomo_driver locomoled_driver = {
},
.devid = LOCOMO_DEVID_LED,
.probe = locomoled_probe,
- .remove = locomoled_remove,
};
static int __init locomoled_init(void)
diff --git a/drivers/leds/leds-menf21bmc.c b/drivers/leds/leds-menf21bmc.c
index 4b9eea815b1a..dec2a6e59676 100644
--- a/drivers/leds/leds-menf21bmc.c
+++ b/drivers/leds/leds-menf21bmc.c
@@ -87,36 +87,20 @@ static int menf21bmc_led_probe(struct platform_device *pdev)
leds[i].cdev.name = leds[i].name;
leds[i].cdev.brightness_set = menf21bmc_led_set;
leds[i].i2c_client = i2c_client;
- ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
- if (ret < 0)
- goto err_free_leds;
+ ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to register LED device\n");
+ return ret;
+ }
}
dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n");
return 0;
-err_free_leds:
- dev_err(&pdev->dev, "failed to register LED device\n");
-
- for (i = i - 1; i >= 0; i--)
- led_classdev_unregister(&leds[i].cdev);
-
- return ret;
-}
-
-static int menf21bmc_led_remove(struct platform_device *pdev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(leds); i++)
- led_classdev_unregister(&leds[i].cdev);
-
- return 0;
}
static struct platform_driver menf21bmc_led = {
.probe = menf21bmc_led_probe,
- .remove = menf21bmc_led_remove,
.driver = {
.name = "menf21bmc_led",
},
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
index ec3a2e8adcae..0d214c2e403c 100644
--- a/drivers/leds/leds-net48xx.c
+++ b/drivers/leds/leds-net48xx.c
@@ -39,18 +39,11 @@ static struct led_classdev net48xx_error_led = {
static int net48xx_led_probe(struct platform_device *pdev)
{
- return led_classdev_register(&pdev->dev, &net48xx_error_led);
-}
-
-static int net48xx_led_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&net48xx_error_led);
- return 0;
+ return devm_led_classdev_register(&pdev->dev, &net48xx_error_led);
}
static struct platform_driver net48xx_led_driver = {
.probe = net48xx_led_probe,
- .remove = net48xx_led_remove,
.driver = {
.name = DRVNAME,
},
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index 25e419752a7b..4b88b93244be 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -26,6 +26,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/leds.h>
#include <linux/platform_data/leds-kirkwood-netxbig.h>
@@ -70,7 +71,8 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
spin_unlock_irqrestore(&gpio_ext_lock, flags);
}
-static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+static int gpio_ext_init(struct platform_device *pdev,
+ struct netxbig_gpio_ext *gpio_ext)
{
int err;
int i;
@@ -80,46 +82,28 @@ static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
/* Configure address GPIOs. */
for (i = 0; i < gpio_ext->num_addr; i++) {
- err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW,
- "GPIO extension addr");
+ err = devm_gpio_request_one(&pdev->dev, gpio_ext->addr[i],
+ GPIOF_OUT_INIT_LOW,
+ "GPIO extension addr");
if (err)
- goto err_free_addr;
+ return err;
}
/* Configure data GPIOs. */
for (i = 0; i < gpio_ext->num_data; i++) {
- err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW,
- "GPIO extension data");
+ err = devm_gpio_request_one(&pdev->dev, gpio_ext->data[i],
+ GPIOF_OUT_INIT_LOW,
+ "GPIO extension data");
if (err)
- goto err_free_data;
+ return err;
}
/* Configure "enable select" GPIO. */
- err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW,
- "GPIO extension enable");
+ err = devm_gpio_request_one(&pdev->dev, gpio_ext->enable,
+ GPIOF_OUT_INIT_LOW,
+ "GPIO extension enable");
if (err)
- goto err_free_data;
+ return err;
return 0;
-
-err_free_data:
- for (i = i - 1; i >= 0; i--)
- gpio_free(gpio_ext->data[i]);
- i = gpio_ext->num_addr;
-err_free_addr:
- for (i = i - 1; i >= 0; i--)
- gpio_free(gpio_ext->addr[i]);
-
- return err;
-}
-
-static void gpio_ext_free(struct netxbig_gpio_ext *gpio_ext)
-{
- int i;
-
- gpio_free(gpio_ext->enable);
- for (i = gpio_ext->num_addr - 1; i >= 0; i--)
- gpio_free(gpio_ext->addr[i]);
- for (i = gpio_ext->num_data - 1; i >= 0; i--)
- gpio_free(gpio_ext->data[i]);
}
/*
@@ -132,7 +116,6 @@ struct netxbig_led_data {
int mode_addr;
int *mode_val;
int bright_addr;
- int bright_max;
struct netxbig_led_timer *timer;
int num_timer;
enum netxbig_led_mode mode;
@@ -194,7 +177,7 @@ static void netxbig_led_set(struct led_classdev *led_cdev,
struct netxbig_led_data *led_dat =
container_of(led_cdev, struct netxbig_led_data, cdev);
enum netxbig_led_mode mode;
- int mode_val, bright_val;
+ int mode_val;
int set_brightness = 1;
unsigned long flags;
@@ -220,12 +203,9 @@ static void netxbig_led_set(struct led_classdev *led_cdev,
* SATA LEDs. So, change the brightness setting for a single
* SATA LED will affect all the others.
*/
- if (set_brightness) {
- bright_val = DIV_ROUND_UP(value * led_dat->bright_max,
- LED_FULL);
+ if (set_brightness)
gpio_ext_set_value(led_dat->gpio_ext,
- led_dat->bright_addr, bright_val);
- }
+ led_dat->bright_addr, value);
spin_unlock_irqrestore(&led_dat->lock, flags);
}
@@ -299,18 +279,11 @@ static struct attribute *netxbig_led_attrs[] = {
};
ATTRIBUTE_GROUPS(netxbig_led);
-static void delete_netxbig_led(struct netxbig_led_data *led_dat)
+static int create_netxbig_led(struct platform_device *pdev,
+ struct netxbig_led_platform_data *pdata,
+ struct netxbig_led_data *led_dat,
+ const struct netxbig_led *template)
{
- led_classdev_unregister(&led_dat->cdev);
-}
-
-static int
-create_netxbig_led(struct platform_device *pdev,
- struct netxbig_led_data *led_dat,
- const struct netxbig_led *template)
-{
- struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
spin_lock_init(&led_dat->lock);
led_dat->gpio_ext = pdata->gpio_ext;
led_dat->cdev.name = template->name;
@@ -329,11 +302,11 @@ create_netxbig_led(struct platform_device *pdev,
*/
led_dat->sata = 0;
led_dat->cdev.brightness = LED_OFF;
+ led_dat->cdev.max_brightness = template->bright_max;
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
led_dat->mode_addr = template->mode_addr;
led_dat->mode_val = template->mode_val;
led_dat->bright_addr = template->bright_addr;
- led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1;
led_dat->timer = pdata->timer;
led_dat->num_timer = pdata->num_timer;
/*
@@ -343,67 +316,274 @@ create_netxbig_led(struct platform_device *pdev,
if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
led_dat->cdev.groups = netxbig_led_groups;
- return led_classdev_register(&pdev->dev, &led_dat->cdev);
+ return devm_led_classdev_register(&pdev->dev, &led_dat->cdev);
}
-static int netxbig_led_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF_GPIO
+static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
+ struct netxbig_gpio_ext *gpio_ext)
{
- struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct netxbig_led_data *leds_data;
- int i;
+ int *addr, *data;
+ int num_addr, num_data;
int ret;
+ int i;
- if (!pdata)
- return -EINVAL;
-
- leds_data = devm_kzalloc(&pdev->dev,
- sizeof(struct netxbig_led_data) * pdata->num_leds, GFP_KERNEL);
- if (!leds_data)
+ ret = of_gpio_named_count(np, "addr-gpios");
+ if (ret < 0) {
+ dev_err(dev,
+ "Failed to count GPIOs in DT property addr-gpios\n");
+ return ret;
+ }
+ num_addr = ret;
+ addr = devm_kzalloc(dev, num_addr * sizeof(*addr), GFP_KERNEL);
+ if (!addr)
return -ENOMEM;
- ret = gpio_ext_init(pdata->gpio_ext);
- if (ret < 0)
+ for (i = 0; i < num_addr; i++) {
+ ret = of_get_named_gpio(np, "addr-gpios", i);
+ if (ret < 0)
+ return ret;
+ addr[i] = ret;
+ }
+ gpio_ext->addr = addr;
+ gpio_ext->num_addr = num_addr;
+
+ ret = of_gpio_named_count(np, "data-gpios");
+ if (ret < 0) {
+ dev_err(dev,
+ "Failed to count GPIOs in DT property data-gpios\n");
return ret;
+ }
+ num_data = ret;
+ data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- for (i = 0; i < pdata->num_leds; i++) {
- ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]);
+ for (i = 0; i < num_data; i++) {
+ ret = of_get_named_gpio(np, "data-gpios", i);
if (ret < 0)
- goto err_free_leds;
+ return ret;
+ data[i] = ret;
}
+ gpio_ext->data = data;
+ gpio_ext->num_data = num_data;
- platform_set_drvdata(pdev, leds_data);
+ ret = of_get_named_gpio(np, "enable-gpio", 0);
+ if (ret < 0) {
+ dev_err(dev,
+ "Failed to get GPIO from DT property enable-gpio\n");
+ return ret;
+ }
+ gpio_ext->enable = ret;
return 0;
+}
+
+static int netxbig_leds_get_of_pdata(struct device *dev,
+ struct netxbig_led_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+ struct device_node *gpio_ext_np;
+ struct device_node *child;
+ struct netxbig_gpio_ext *gpio_ext;
+ struct netxbig_led_timer *timers;
+ struct netxbig_led *leds, *led;
+ int num_timers;
+ int num_leds = 0;
+ int ret;
+ int i;
-err_free_leds:
- for (i = i - 1; i >= 0; i--)
- delete_netxbig_led(&leds_data[i]);
+ /* GPIO extension */
+ gpio_ext_np = of_parse_phandle(np, "gpio-ext", 0);
+ if (!gpio_ext_np) {
+ dev_err(dev, "Failed to get DT handle gpio-ext\n");
+ return -EINVAL;
+ }
- gpio_ext_free(pdata->gpio_ext);
+ gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL);
+ if (!gpio_ext)
+ return -ENOMEM;
+ ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext);
+ if (ret)
+ return ret;
+ of_node_put(gpio_ext_np);
+ pdata->gpio_ext = gpio_ext;
+
+ /* Timers (optional) */
+ ret = of_property_count_u32_elems(np, "timers");
+ if (ret > 0) {
+ if (ret % 3)
+ return -EINVAL;
+ num_timers = ret / 3;
+ timers = devm_kzalloc(dev, num_timers * sizeof(*timers),
+ GFP_KERNEL);
+ if (!timers)
+ return -ENOMEM;
+ for (i = 0; i < num_timers; i++) {
+ u32 tmp;
+
+ of_property_read_u32_index(np, "timers", 3 * i,
+ &timers[i].mode);
+ if (timers[i].mode >= NETXBIG_LED_MODE_NUM)
+ return -EINVAL;
+ of_property_read_u32_index(np, "timers",
+ 3 * i + 1, &tmp);
+ timers[i].delay_on = tmp;
+ of_property_read_u32_index(np, "timers",
+ 3 * i + 2, &tmp);
+ timers[i].delay_off = tmp;
+ }
+ pdata->timer = timers;
+ pdata->num_timer = num_timers;
+ }
+
+ /* LEDs */
+ num_leds = of_get_child_count(np);
+ if (!num_leds) {
+ dev_err(dev, "No LED subnodes found in DT\n");
+ return -ENODEV;
+ }
+
+ leds = devm_kzalloc(dev, num_leds * sizeof(*leds), GFP_KERNEL);
+ if (!leds)
+ return -ENOMEM;
+
+ led = leds;
+ for_each_child_of_node(np, child) {
+ const char *string;
+ int *mode_val;
+ int num_modes;
+
+ ret = of_property_read_u32(child, "mode-addr",
+ &led->mode_addr);
+ if (ret)
+ goto err_node_put;
+
+ ret = of_property_read_u32(child, "bright-addr",
+ &led->bright_addr);
+ if (ret)
+ goto err_node_put;
+
+ ret = of_property_read_u32(child, "max-brightness",
+ &led->bright_max);
+ if (ret)
+ goto err_node_put;
+
+ mode_val =
+ devm_kzalloc(dev,
+ NETXBIG_LED_MODE_NUM * sizeof(*mode_val),
+ GFP_KERNEL);
+ if (!mode_val) {
+ ret = -ENOMEM;
+ goto err_node_put;
+ }
+
+ for (i = 0; i < NETXBIG_LED_MODE_NUM; i++)
+ mode_val[i] = NETXBIG_LED_INVALID_MODE;
+
+ ret = of_property_count_u32_elems(child, "mode-val");
+ if (ret < 0 || ret % 2) {
+ ret = -EINVAL;
+ goto err_node_put;
+ }
+ num_modes = ret / 2;
+ if (num_modes > NETXBIG_LED_MODE_NUM) {
+ ret = -EINVAL;
+ goto err_node_put;
+ }
+
+ for (i = 0; i < num_modes; i++) {
+ int mode;
+ int val;
+
+ of_property_read_u32_index(child,
+ "mode-val", 2 * i, &mode);
+ of_property_read_u32_index(child,
+ "mode-val", 2 * i + 1, &val);
+ if (mode >= NETXBIG_LED_MODE_NUM) {
+ ret = -EINVAL;
+ goto err_node_put;
+ }
+ mode_val[mode] = val;
+ }
+ led->mode_val = mode_val;
+
+ if (!of_property_read_string(child, "label", &string))
+ led->name = string;
+ else
+ led->name = child->name;
+
+ if (!of_property_read_string(child,
+ "linux,default-trigger", &string))
+ led->default_trigger = string;
+
+ led++;
+ }
+
+ pdata->leds = leds;
+ pdata->num_leds = num_leds;
+
+ return 0;
+
+err_node_put:
+ of_node_put(child);
return ret;
}
-static int netxbig_led_remove(struct platform_device *pdev)
+static const struct of_device_id of_netxbig_leds_match[] = {
+ { .compatible = "lacie,netxbig-leds", },
+ {},
+};
+#else
+static inline int
+netxbig_leds_get_of_pdata(struct device *dev,
+ struct netxbig_led_platform_data *pdata)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_OF_GPIO */
+
+static int netxbig_led_probe(struct platform_device *pdev)
{
struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct netxbig_led_data *leds_data;
int i;
+ int ret;
- leds_data = platform_get_drvdata(pdev);
+ if (!pdata) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata);
+ if (ret)
+ return ret;
+ }
+
+ leds_data = devm_kzalloc(&pdev->dev,
+ pdata->num_leds * sizeof(*leds_data),
+ GFP_KERNEL);
+ if (!leds_data)
+ return -ENOMEM;
- for (i = 0; i < pdata->num_leds; i++)
- delete_netxbig_led(&leds_data[i]);
+ ret = gpio_ext_init(pdev, pdata->gpio_ext);
+ if (ret < 0)
+ return ret;
- gpio_ext_free(pdata->gpio_ext);
+ for (i = 0; i < pdata->num_leds; i++) {
+ ret = create_netxbig_led(pdev, pdata,
+ &leds_data[i], &pdata->leds[i]);
+ if (ret < 0)
+ return ret;
+ }
return 0;
}
static struct platform_driver netxbig_led_driver = {
.probe = netxbig_led_probe,
- .remove = netxbig_led_remove,
.driver = {
- .name = "leds-netxbig",
+ .name = "leds-netxbig",
+ .of_match_table = of_match_ptr(of_netxbig_leds_match),
},
};
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
index 39870de20a26..12af1127d9b7 100644
--- a/drivers/leds/leds-ot200.c
+++ b/drivers/leds/leds-ot200.c
@@ -124,9 +124,9 @@ static int ot200_led_probe(struct platform_device *pdev)
leds[i].cdev.name = leds[i].name;
leds[i].cdev.brightness_set = ot200_led_brightness_set;
- ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
+ ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
if (ret < 0)
- goto err;
+ return ret;
}
leds_front = 0; /* turn off all front leds */
@@ -135,27 +135,10 @@ static int ot200_led_probe(struct platform_device *pdev)
outb(leds_back, 0x5a);
return 0;
-
-err:
- for (i = i - 1; i >= 0; i--)
- led_classdev_unregister(&leds[i].cdev);
-
- return ret;
-}
-
-static int ot200_led_remove(struct platform_device *pdev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(leds); i++)
- led_classdev_unregister(&leds[i].cdev);
-
- return 0;
}
static struct platform_driver ot200_led_driver = {
.probe = ot200_led_probe,
- .remove = ot200_led_remove,
.driver = {
.name = "leds-ot200",
},
diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c
index 2c5c5b12ab64..1e75e1fe9b72 100644
--- a/drivers/leds/leds-powernv.c
+++ b/drivers/leds/leds-powernv.c
@@ -262,15 +262,19 @@ static int powernv_led_classdev(struct platform_device *pdev,
while ((cur = of_prop_next_string(p, cur)) != NULL) {
powernv_led = devm_kzalloc(dev, sizeof(*powernv_led),
GFP_KERNEL);
- if (!powernv_led)
+ if (!powernv_led) {
+ of_node_put(np);
return -ENOMEM;
+ }
powernv_led->common = powernv_led_common;
powernv_led->loc_code = (char *)np->name;
rc = powernv_led_create(dev, powernv_led, cur);
- if (rc)
+ if (rc) {
+ of_node_put(np);
return rc;
+ }
} /* while end */
}
diff --git a/drivers/leds/leds-sead3.c b/drivers/leds/leds-sead3.c
new file mode 100644
index 000000000000..eb97a3271bb3
--- /dev/null
+++ b/drivers/leds/leds-sead3.c
@@ -0,0 +1,78 @@
+/*
+ * 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) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2015 Imagination Technologies, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mips-boards/sead3-addr.h>
+
+static void sead3_pled_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ writel(value, (void __iomem *)SEAD3_CPLD_P_LED);
+}
+
+static void sead3_fled_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ writel(value, (void __iomem *)SEAD3_CPLD_F_LED);
+}
+
+static struct led_classdev sead3_pled = {
+ .name = "sead3::pled",
+ .brightness_set = sead3_pled_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+};
+
+static struct led_classdev sead3_fled = {
+ .name = "sead3::fled",
+ .brightness_set = sead3_fled_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+};
+
+static int sead3_led_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = led_classdev_register(&pdev->dev, &sead3_pled);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&pdev->dev, &sead3_fled);
+ if (ret < 0)
+ led_classdev_unregister(&sead3_pled);
+
+ return ret;
+}
+
+static int sead3_led_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&sead3_pled);
+ led_classdev_unregister(&sead3_fled);
+
+ return 0;
+}
+
+static struct platform_driver sead3_led_driver = {
+ .probe = sead3_led_probe,
+ .remove = sead3_led_remove,
+ .driver = {
+ .name = "sead3-led",
+ },
+};
+
+module_platform_driver(sead3_led_driver);
+
+MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
+MODULE_DESCRIPTION("SEAD3 LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c
index 1ba3defdd460..473fb6b97ed4 100644
--- a/drivers/leds/leds-wrap.c
+++ b/drivers/leds/leds-wrap.c
@@ -76,39 +76,19 @@ static int wrap_led_probe(struct platform_device *pdev)
{
int ret;
- ret = led_classdev_register(&pdev->dev, &wrap_power_led);
+ ret = devm_led_classdev_register(&pdev->dev, &wrap_power_led);
if (ret < 0)
return ret;
- ret = led_classdev_register(&pdev->dev, &wrap_error_led);
+ ret = devm_led_classdev_register(&pdev->dev, &wrap_error_led);
if (ret < 0)
- goto err1;
-
- ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
- if (ret < 0)
- goto err2;
-
- return ret;
-
-err2:
- led_classdev_unregister(&wrap_error_led);
-err1:
- led_classdev_unregister(&wrap_power_led);
-
- return ret;
-}
+ return ret;
-static int wrap_led_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&wrap_power_led);
- led_classdev_unregister(&wrap_error_led);
- led_classdev_unregister(&wrap_extra_led);
- return 0;
+ return devm_led_classdev_register(&pdev->dev, &wrap_extra_led);
}
static struct platform_driver wrap_led_driver = {
.probe = wrap_led_probe,
- .remove = wrap_led_remove,
.driver = {
.name = DRVNAME,
},
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index bc89d7ace2c4..4238fbc31d35 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -44,6 +44,7 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
return led_cdev->brightness;
}
+void led_init_core(struct led_classdev *led_cdev);
void led_stop_software_blink(struct led_classdev *led_cdev);
extern struct rw_semaphore leds_list_lock;
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
index fea6871d2609..8622ce651ae2 100644
--- a/drivers/leds/trigger/ledtrig-heartbeat.c
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -27,6 +27,7 @@ struct heartbeat_trig_data {
unsigned int phase;
unsigned int period;
struct timer_list timer;
+ unsigned int invert;
};
static void led_heartbeat_function(unsigned long data)
@@ -56,21 +57,27 @@ static void led_heartbeat_function(unsigned long data)
msecs_to_jiffies(heartbeat_data->period);
delay = msecs_to_jiffies(70);
heartbeat_data->phase++;
- brightness = led_cdev->max_brightness;
+ if (!heartbeat_data->invert)
+ brightness = led_cdev->max_brightness;
break;
case 1:
delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
heartbeat_data->phase++;
+ if (heartbeat_data->invert)
+ brightness = led_cdev->max_brightness;
break;
case 2:
delay = msecs_to_jiffies(70);
heartbeat_data->phase++;
- brightness = led_cdev->max_brightness;
+ if (!heartbeat_data->invert)
+ brightness = led_cdev->max_brightness;
break;
default:
delay = heartbeat_data->period - heartbeat_data->period / 4 -
msecs_to_jiffies(70);
heartbeat_data->phase = 0;
+ if (heartbeat_data->invert)
+ brightness = led_cdev->max_brightness;
break;
}
@@ -78,15 +85,50 @@ static void led_heartbeat_function(unsigned long data)
mod_timer(&heartbeat_data->timer, jiffies + delay);
}
+static ssize_t led_invert_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+
+ return sprintf(buf, "%u\n", heartbeat_data->invert);
+}
+
+static ssize_t led_invert_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+ unsigned long state;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &state);
+ if (ret)
+ return ret;
+
+ heartbeat_data->invert = !!state;
+
+ return size;
+}
+
+static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
+
static void heartbeat_trig_activate(struct led_classdev *led_cdev)
{
struct heartbeat_trig_data *heartbeat_data;
+ int rc;
heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
if (!heartbeat_data)
return;
led_cdev->trigger_data = heartbeat_data;
+ rc = device_create_file(led_cdev->dev, &dev_attr_invert);
+ if (rc) {
+ kfree(led_cdev->trigger_data);
+ return;
+ }
+
setup_timer(&heartbeat_data->timer,
led_heartbeat_function, (unsigned long) led_cdev);
heartbeat_data->phase = 0;
@@ -100,6 +142,7 @@ static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
if (led_cdev->activated) {
del_timer_sync(&heartbeat_data->timer);
+ device_remove_file(led_cdev->dev, &dev_attr_invert);
kfree(heartbeat_data);
led_cdev->activated = false;
}
diff --git a/drivers/lightnvm/Kconfig b/drivers/lightnvm/Kconfig
new file mode 100644
index 000000000000..a16bf56d3f28
--- /dev/null
+++ b/drivers/lightnvm/Kconfig
@@ -0,0 +1,42 @@
+#
+# Open-Channel SSD NVM configuration
+#
+
+menuconfig NVM
+ bool "Open-Channel SSD target support"
+ depends on BLOCK
+ help
+ Say Y here to get to enable Open-channel SSDs.
+
+ Open-Channel SSDs implement a set of extension to SSDs, that
+ exposes direct access to the underlying non-volatile memory.
+
+ If you say N, all options in this submenu will be skipped and disabled
+ only do this if you know what you are doing.
+
+if NVM
+
+config NVM_DEBUG
+ bool "Open-Channel SSD debugging support"
+ ---help---
+ Exposes a debug management interface to create/remove targets at:
+
+ /sys/module/lnvm/parameters/configure_debug
+
+ It is required to create/remove targets without IOCTLs.
+
+config NVM_GENNVM
+ tristate "Generic NVM manager for Open-Channel SSDs"
+ ---help---
+ NVM media manager for Open-Channel SSDs that offload management
+ functionality to device, while keeping data placement and garbage
+ collection decisions on the host.
+
+config NVM_RRPC
+ tristate "Round-robin Hybrid Open-Channel SSD target"
+ ---help---
+ Allows an open-channel SSD to be exposed as a block device to the
+ host. The target is implemented using a linear mapping table and
+ cost-based garbage collection. It is optimized for 4K IO sizes.
+
+endif # NVM
diff --git a/drivers/lightnvm/Makefile b/drivers/lightnvm/Makefile
new file mode 100644
index 000000000000..7e0f42acb737
--- /dev/null
+++ b/drivers/lightnvm/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Open-Channel SSDs.
+#
+
+obj-$(CONFIG_NVM) := core.o
+obj-$(CONFIG_NVM_GENNVM) += gennvm.o
+obj-$(CONFIG_NVM_RRPC) += rrpc.o
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
new file mode 100644
index 000000000000..f659e605a406
--- /dev/null
+++ b/drivers/lightnvm/core.c
@@ -0,0 +1,826 @@
+/*
+ * Copyright (C) 2015 IT University of Copenhagen. All rights reserved.
+ * Initial release: Matias Bjorling <m@bjorling.me>
+ *
+ * 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/sem.h>
+#include <linux/bitmap.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/lightnvm.h>
+#include <uapi/linux/lightnvm.h>
+
+static LIST_HEAD(nvm_targets);
+static LIST_HEAD(nvm_mgrs);
+static LIST_HEAD(nvm_devices);
+static DECLARE_RWSEM(nvm_lock);
+
+static struct nvm_tgt_type *nvm_find_target_type(const char *name)
+{
+ struct nvm_tgt_type *tt;
+
+ list_for_each_entry(tt, &nvm_targets, list)
+ if (!strcmp(name, tt->name))
+ return tt;
+
+ return NULL;
+}
+
+int nvm_register_target(struct nvm_tgt_type *tt)
+{
+ int ret = 0;
+
+ down_write(&nvm_lock);
+ if (nvm_find_target_type(tt->name))
+ ret = -EEXIST;
+ else
+ list_add(&tt->list, &nvm_targets);
+ up_write(&nvm_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(nvm_register_target);
+
+void nvm_unregister_target(struct nvm_tgt_type *tt)
+{
+ if (!tt)
+ return;
+
+ down_write(&nvm_lock);
+ list_del(&tt->list);
+ up_write(&nvm_lock);
+}
+EXPORT_SYMBOL(nvm_unregister_target);
+
+void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags,
+ dma_addr_t *dma_handler)
+{
+ return dev->ops->dev_dma_alloc(dev->q, dev->ppalist_pool, mem_flags,
+ dma_handler);
+}
+EXPORT_SYMBOL(nvm_dev_dma_alloc);
+
+void nvm_dev_dma_free(struct nvm_dev *dev, void *ppa_list,
+ dma_addr_t dma_handler)
+{
+ dev->ops->dev_dma_free(dev->ppalist_pool, ppa_list, dma_handler);
+}
+EXPORT_SYMBOL(nvm_dev_dma_free);
+
+static struct nvmm_type *nvm_find_mgr_type(const char *name)
+{
+ struct nvmm_type *mt;
+
+ list_for_each_entry(mt, &nvm_mgrs, list)
+ if (!strcmp(name, mt->name))
+ return mt;
+
+ return NULL;
+}
+
+int nvm_register_mgr(struct nvmm_type *mt)
+{
+ int ret = 0;
+
+ down_write(&nvm_lock);
+ if (nvm_find_mgr_type(mt->name))
+ ret = -EEXIST;
+ else
+ list_add(&mt->list, &nvm_mgrs);
+ up_write(&nvm_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(nvm_register_mgr);
+
+void nvm_unregister_mgr(struct nvmm_type *mt)
+{
+ if (!mt)
+ return;
+
+ down_write(&nvm_lock);
+ list_del(&mt->list);
+ up_write(&nvm_lock);
+}
+EXPORT_SYMBOL(nvm_unregister_mgr);
+
+static struct nvm_dev *nvm_find_nvm_dev(const char *name)
+{
+ struct nvm_dev *dev;
+
+ list_for_each_entry(dev, &nvm_devices, devices)
+ if (!strcmp(name, dev->name))
+ return dev;
+
+ return NULL;
+}
+
+struct nvm_block *nvm_get_blk(struct nvm_dev *dev, struct nvm_lun *lun,
+ unsigned long flags)
+{
+ return dev->mt->get_blk(dev, lun, flags);
+}
+EXPORT_SYMBOL(nvm_get_blk);
+
+/* Assumes that all valid pages have already been moved on release to bm */
+void nvm_put_blk(struct nvm_dev *dev, struct nvm_block *blk)
+{
+ return dev->mt->put_blk(dev, blk);
+}
+EXPORT_SYMBOL(nvm_put_blk);
+
+int nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
+{
+ return dev->mt->submit_io(dev, rqd);
+}
+EXPORT_SYMBOL(nvm_submit_io);
+
+int nvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk)
+{
+ return dev->mt->erase_blk(dev, blk, 0);
+}
+EXPORT_SYMBOL(nvm_erase_blk);
+
+static void nvm_core_free(struct nvm_dev *dev)
+{
+ kfree(dev);
+}
+
+static int nvm_core_init(struct nvm_dev *dev)
+{
+ struct nvm_id *id = &dev->identity;
+ struct nvm_id_group *grp = &id->groups[0];
+
+ /* device values */
+ dev->nr_chnls = grp->num_ch;
+ dev->luns_per_chnl = grp->num_lun;
+ dev->pgs_per_blk = grp->num_pg;
+ dev->blks_per_lun = grp->num_blk;
+ dev->nr_planes = grp->num_pln;
+ dev->sec_size = grp->csecs;
+ dev->oob_size = grp->sos;
+ dev->sec_per_pg = grp->fpg_sz / grp->csecs;
+ dev->addr_mode = id->ppat;
+ dev->addr_format = id->ppaf;
+
+ dev->plane_mode = NVM_PLANE_SINGLE;
+ dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size;
+
+ if (grp->mpos & 0x020202)
+ dev->plane_mode = NVM_PLANE_DOUBLE;
+ if (grp->mpos & 0x040404)
+ dev->plane_mode = NVM_PLANE_QUAD;
+
+ /* calculated values */
+ dev->sec_per_pl = dev->sec_per_pg * dev->nr_planes;
+ dev->sec_per_blk = dev->sec_per_pl * dev->pgs_per_blk;
+ dev->sec_per_lun = dev->sec_per_blk * dev->blks_per_lun;
+ dev->nr_luns = dev->luns_per_chnl * dev->nr_chnls;
+
+ dev->total_blocks = dev->nr_planes *
+ dev->blks_per_lun *
+ dev->luns_per_chnl *
+ dev->nr_chnls;
+ dev->total_pages = dev->total_blocks * dev->pgs_per_blk;
+ INIT_LIST_HEAD(&dev->online_targets);
+
+ return 0;
+}
+
+static void nvm_free(struct nvm_dev *dev)
+{
+ if (!dev)
+ return;
+
+ if (dev->mt)
+ dev->mt->unregister_mgr(dev);
+
+ nvm_core_free(dev);
+}
+
+static int nvm_init(struct nvm_dev *dev)
+{
+ struct nvmm_type *mt;
+ int ret = 0;
+
+ if (!dev->q || !dev->ops)
+ return -EINVAL;
+
+ if (dev->ops->identity(dev->q, &dev->identity)) {
+ pr_err("nvm: device could not be identified\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ pr_debug("nvm: ver:%x nvm_vendor:%x groups:%u\n",
+ dev->identity.ver_id, dev->identity.vmnt,
+ dev->identity.cgrps);
+
+ if (dev->identity.ver_id != 1) {
+ pr_err("nvm: device not supported by kernel.");
+ goto err;
+ }
+
+ if (dev->identity.cgrps != 1) {
+ pr_err("nvm: only one group configuration supported.");
+ goto err;
+ }
+
+ ret = nvm_core_init(dev);
+ if (ret) {
+ pr_err("nvm: could not initialize core structures.\n");
+ goto err;
+ }
+
+ /* register with device with a supported manager */
+ list_for_each_entry(mt, &nvm_mgrs, list) {
+ ret = mt->register_mgr(dev);
+ if (ret < 0)
+ goto err; /* initialization failed */
+ if (ret > 0) {
+ dev->mt = mt;
+ break; /* successfully initialized */
+ }
+ }
+
+ if (!ret) {
+ pr_info("nvm: no compatible manager found.\n");
+ return 0;
+ }
+
+ pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
+ dev->name, dev->sec_per_pg, dev->nr_planes,
+ dev->pgs_per_blk, dev->blks_per_lun, dev->nr_luns,
+ dev->nr_chnls);
+ return 0;
+err:
+ nvm_free(dev);
+ pr_err("nvm: failed to initialize nvm\n");
+ return ret;
+}
+
+static void nvm_exit(struct nvm_dev *dev)
+{
+ if (dev->ppalist_pool)
+ dev->ops->destroy_dma_pool(dev->ppalist_pool);
+ nvm_free(dev);
+
+ pr_info("nvm: successfully unloaded\n");
+}
+
+int nvm_register(struct request_queue *q, char *disk_name,
+ struct nvm_dev_ops *ops)
+{
+ struct nvm_dev *dev;
+ int ret;
+
+ if (!ops->identity)
+ return -EINVAL;
+
+ dev = kzalloc(sizeof(struct nvm_dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->q = q;
+ dev->ops = ops;
+ strncpy(dev->name, disk_name, DISK_NAME_LEN);
+
+ ret = nvm_init(dev);
+ if (ret)
+ goto err_init;
+
+ down_write(&nvm_lock);
+ list_add(&dev->devices, &nvm_devices);
+ up_write(&nvm_lock);
+
+ if (dev->ops->max_phys_sect > 1) {
+ dev->ppalist_pool = dev->ops->create_dma_pool(dev->q,
+ "ppalist");
+ if (!dev->ppalist_pool) {
+ pr_err("nvm: could not create ppa pool\n");
+ return -ENOMEM;
+ }
+ } else if (dev->ops->max_phys_sect > 256) {
+ pr_info("nvm: max sectors supported is 256.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+err_init:
+ kfree(dev);
+ return ret;
+}
+EXPORT_SYMBOL(nvm_register);
+
+void nvm_unregister(char *disk_name)
+{
+ struct nvm_dev *dev = nvm_find_nvm_dev(disk_name);
+
+ if (!dev) {
+ pr_err("nvm: could not find device %s to unregister\n",
+ disk_name);
+ return;
+ }
+
+ nvm_exit(dev);
+
+ down_write(&nvm_lock);
+ list_del(&dev->devices);
+ up_write(&nvm_lock);
+}
+EXPORT_SYMBOL(nvm_unregister);
+
+static const struct block_device_operations nvm_fops = {
+ .owner = THIS_MODULE,
+};
+
+static int nvm_create_target(struct nvm_dev *dev,
+ struct nvm_ioctl_create *create)
+{
+ struct nvm_ioctl_create_simple *s = &create->conf.s;
+ struct request_queue *tqueue;
+ struct nvmm_type *mt;
+ struct gendisk *tdisk;
+ struct nvm_tgt_type *tt;
+ struct nvm_target *t;
+ void *targetdata;
+ int ret = 0;
+
+ if (!dev->mt) {
+ /* register with device with a supported NVM manager */
+ list_for_each_entry(mt, &nvm_mgrs, list) {
+ ret = mt->register_mgr(dev);
+ if (ret < 0)
+ return ret; /* initialization failed */
+ if (ret > 0) {
+ dev->mt = mt;
+ break; /* successfully initialized */
+ }
+ }
+
+ if (!ret) {
+ pr_info("nvm: no compatible nvm manager found.\n");
+ return -ENODEV;
+ }
+ }
+
+ tt = nvm_find_target_type(create->tgttype);
+ if (!tt) {
+ pr_err("nvm: target type %s not found\n", create->tgttype);
+ return -EINVAL;
+ }
+
+ down_write(&nvm_lock);
+ list_for_each_entry(t, &dev->online_targets, list) {
+ if (!strcmp(create->tgtname, t->disk->disk_name)) {
+ pr_err("nvm: target name already exists.\n");
+ up_write(&nvm_lock);
+ return -EINVAL;
+ }
+ }
+ up_write(&nvm_lock);
+
+ t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
+ if (!t)
+ return -ENOMEM;
+
+ tqueue = blk_alloc_queue_node(GFP_KERNEL, dev->q->node);
+ if (!tqueue)
+ goto err_t;
+ blk_queue_make_request(tqueue, tt->make_rq);
+
+ tdisk = alloc_disk(0);
+ if (!tdisk)
+ goto err_queue;
+
+ sprintf(tdisk->disk_name, "%s", create->tgtname);
+ tdisk->flags = GENHD_FL_EXT_DEVT;
+ tdisk->major = 0;
+ tdisk->first_minor = 0;
+ tdisk->fops = &nvm_fops;
+ tdisk->queue = tqueue;
+
+ targetdata = tt->init(dev, tdisk, s->lun_begin, s->lun_end);
+ if (IS_ERR(targetdata))
+ goto err_init;
+
+ tdisk->private_data = targetdata;
+ tqueue->queuedata = targetdata;
+
+ blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
+
+ set_capacity(tdisk, tt->capacity(targetdata));
+ add_disk(tdisk);
+
+ t->type = tt;
+ t->disk = tdisk;
+
+ down_write(&nvm_lock);
+ list_add_tail(&t->list, &dev->online_targets);
+ up_write(&nvm_lock);
+
+ return 0;
+err_init:
+ put_disk(tdisk);
+err_queue:
+ blk_cleanup_queue(tqueue);
+err_t:
+ kfree(t);
+ return -ENOMEM;
+}
+
+static void nvm_remove_target(struct nvm_target *t)
+{
+ struct nvm_tgt_type *tt = t->type;
+ struct gendisk *tdisk = t->disk;
+ struct request_queue *q = tdisk->queue;
+
+ lockdep_assert_held(&nvm_lock);
+
+ del_gendisk(tdisk);
+ if (tt->exit)
+ tt->exit(tdisk->private_data);
+
+ blk_cleanup_queue(q);
+
+ put_disk(tdisk);
+
+ list_del(&t->list);
+ kfree(t);
+}
+
+static int __nvm_configure_create(struct nvm_ioctl_create *create)
+{
+ struct nvm_dev *dev;
+ struct nvm_ioctl_create_simple *s;
+
+ dev = nvm_find_nvm_dev(create->dev);
+ if (!dev) {
+ pr_err("nvm: device not found\n");
+ return -EINVAL;
+ }
+
+ if (create->conf.type != NVM_CONFIG_TYPE_SIMPLE) {
+ pr_err("nvm: config type not valid\n");
+ return -EINVAL;
+ }
+ s = &create->conf.s;
+
+ if (s->lun_begin > s->lun_end || s->lun_end > dev->nr_luns) {
+ pr_err("nvm: lun out of bound (%u:%u > %u)\n",
+ s->lun_begin, s->lun_end, dev->nr_luns);
+ return -EINVAL;
+ }
+
+ return nvm_create_target(dev, create);
+}
+
+static int __nvm_configure_remove(struct nvm_ioctl_remove *remove)
+{
+ struct nvm_target *t = NULL;
+ struct nvm_dev *dev;
+ int ret = -1;
+
+ down_write(&nvm_lock);
+ list_for_each_entry(dev, &nvm_devices, devices)
+ list_for_each_entry(t, &dev->online_targets, list) {
+ if (!strcmp(remove->tgtname, t->disk->disk_name)) {
+ nvm_remove_target(t);
+ ret = 0;
+ break;
+ }
+ }
+ up_write(&nvm_lock);
+
+ if (ret) {
+ pr_err("nvm: target \"%s\" doesn't exist.\n", remove->tgtname);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_NVM_DEBUG
+static int nvm_configure_show(const char *val)
+{
+ struct nvm_dev *dev;
+ char opcode, devname[DISK_NAME_LEN];
+ int ret;
+
+ ret = sscanf(val, "%c %32s", &opcode, devname);
+ if (ret != 2) {
+ pr_err("nvm: invalid command. Use \"opcode devicename\".\n");
+ return -EINVAL;
+ }
+
+ dev = nvm_find_nvm_dev(devname);
+ if (!dev) {
+ pr_err("nvm: device not found\n");
+ return -EINVAL;
+ }
+
+ if (!dev->mt)
+ return 0;
+
+ dev->mt->free_blocks_print(dev);
+
+ return 0;
+}
+
+static int nvm_configure_remove(const char *val)
+{
+ struct nvm_ioctl_remove remove;
+ char opcode;
+ int ret;
+
+ ret = sscanf(val, "%c %256s", &opcode, remove.tgtname);
+ if (ret != 2) {
+ pr_err("nvm: invalid command. Use \"d targetname\".\n");
+ return -EINVAL;
+ }
+
+ remove.flags = 0;
+
+ return __nvm_configure_remove(&remove);
+}
+
+static int nvm_configure_create(const char *val)
+{
+ struct nvm_ioctl_create create;
+ char opcode;
+ int lun_begin, lun_end, ret;
+
+ ret = sscanf(val, "%c %256s %256s %48s %u:%u", &opcode, create.dev,
+ create.tgtname, create.tgttype,
+ &lun_begin, &lun_end);
+ if (ret != 6) {
+ pr_err("nvm: invalid command. Use \"opcode device name tgttype lun_begin:lun_end\".\n");
+ return -EINVAL;
+ }
+
+ create.flags = 0;
+ create.conf.type = NVM_CONFIG_TYPE_SIMPLE;
+ create.conf.s.lun_begin = lun_begin;
+ create.conf.s.lun_end = lun_end;
+
+ return __nvm_configure_create(&create);
+}
+
+
+/* Exposes administrative interface through /sys/module/lnvm/configure_by_str */
+static int nvm_configure_by_str_event(const char *val,
+ const struct kernel_param *kp)
+{
+ char opcode;
+ int ret;
+
+ ret = sscanf(val, "%c", &opcode);
+ if (ret != 1) {
+ pr_err("nvm: string must have the format of \"cmd ...\"\n");
+ return -EINVAL;
+ }
+
+ switch (opcode) {
+ case 'a':
+ return nvm_configure_create(val);
+ case 'd':
+ return nvm_configure_remove(val);
+ case 's':
+ return nvm_configure_show(val);
+ default:
+ pr_err("nvm: invalid command\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int nvm_configure_get(char *buf, const struct kernel_param *kp)
+{
+ int sz = 0;
+ char *buf_start = buf;
+ struct nvm_dev *dev;
+
+ buf += sprintf(buf, "available devices:\n");
+ down_write(&nvm_lock);
+ list_for_each_entry(dev, &nvm_devices, devices) {
+ if (sz > 4095 - DISK_NAME_LEN)
+ break;
+ buf += sprintf(buf, " %32s\n", dev->name);
+ }
+ up_write(&nvm_lock);
+
+ return buf - buf_start - 1;
+}
+
+static const struct kernel_param_ops nvm_configure_by_str_event_param_ops = {
+ .set = nvm_configure_by_str_event,
+ .get = nvm_configure_get,
+};
+
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "lnvm."
+
+module_param_cb(configure_debug, &nvm_configure_by_str_event_param_ops, NULL,
+ 0644);
+
+#endif /* CONFIG_NVM_DEBUG */
+
+static long nvm_ioctl_info(struct file *file, void __user *arg)
+{
+ struct nvm_ioctl_info *info;
+ struct nvm_tgt_type *tt;
+ int tgt_iter = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ info = memdup_user(arg, sizeof(struct nvm_ioctl_info));
+ if (IS_ERR(info))
+ return -EFAULT;
+
+ info->version[0] = NVM_VERSION_MAJOR;
+ info->version[1] = NVM_VERSION_MINOR;
+ info->version[2] = NVM_VERSION_PATCH;
+
+ down_write(&nvm_lock);
+ list_for_each_entry(tt, &nvm_targets, list) {
+ struct nvm_ioctl_info_tgt *tgt = &info->tgts[tgt_iter];
+
+ tgt->version[0] = tt->version[0];
+ tgt->version[1] = tt->version[1];
+ tgt->version[2] = tt->version[2];
+ strncpy(tgt->tgtname, tt->name, NVM_TTYPE_NAME_MAX);
+
+ tgt_iter++;
+ }
+
+ info->tgtsize = tgt_iter;
+ up_write(&nvm_lock);
+
+ if (copy_to_user(arg, info, sizeof(struct nvm_ioctl_info)))
+ return -EFAULT;
+
+ kfree(info);
+ return 0;
+}
+
+static long nvm_ioctl_get_devices(struct file *file, void __user *arg)
+{
+ struct nvm_ioctl_get_devices *devices;
+ struct nvm_dev *dev;
+ int i = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ devices = kzalloc(sizeof(struct nvm_ioctl_get_devices), GFP_KERNEL);
+ if (!devices)
+ return -ENOMEM;
+
+ down_write(&nvm_lock);
+ list_for_each_entry(dev, &nvm_devices, devices) {
+ struct nvm_ioctl_device_info *info = &devices->info[i];
+
+ sprintf(info->devname, "%s", dev->name);
+ if (dev->mt) {
+ info->bmversion[0] = dev->mt->version[0];
+ info->bmversion[1] = dev->mt->version[1];
+ info->bmversion[2] = dev->mt->version[2];
+ sprintf(info->bmname, "%s", dev->mt->name);
+ } else {
+ sprintf(info->bmname, "none");
+ }
+
+ i++;
+ if (i > 31) {
+ pr_err("nvm: max 31 devices can be reported.\n");
+ break;
+ }
+ }
+ up_write(&nvm_lock);
+
+ devices->nr_devices = i;
+
+ if (copy_to_user(arg, devices, sizeof(struct nvm_ioctl_get_devices)))
+ return -EFAULT;
+
+ kfree(devices);
+ return 0;
+}
+
+static long nvm_ioctl_dev_create(struct file *file, void __user *arg)
+{
+ struct nvm_ioctl_create create;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&create, arg, sizeof(struct nvm_ioctl_create)))
+ return -EFAULT;
+
+ create.dev[DISK_NAME_LEN - 1] = '\0';
+ create.tgttype[NVM_TTYPE_NAME_MAX - 1] = '\0';
+ create.tgtname[DISK_NAME_LEN - 1] = '\0';
+
+ if (create.flags != 0) {
+ pr_err("nvm: no flags supported\n");
+ return -EINVAL;
+ }
+
+ return __nvm_configure_create(&create);
+}
+
+static long nvm_ioctl_dev_remove(struct file *file, void __user *arg)
+{
+ struct nvm_ioctl_remove remove;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&remove, arg, sizeof(struct nvm_ioctl_remove)))
+ return -EFAULT;
+
+ remove.tgtname[DISK_NAME_LEN - 1] = '\0';
+
+ if (remove.flags != 0) {
+ pr_err("nvm: no flags supported\n");
+ return -EINVAL;
+ }
+
+ return __nvm_configure_remove(&remove);
+}
+
+static long nvm_ctl_ioctl(struct file *file, uint cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+ case NVM_INFO:
+ return nvm_ioctl_info(file, argp);
+ case NVM_GET_DEVICES:
+ return nvm_ioctl_get_devices(file, argp);
+ case NVM_DEV_CREATE:
+ return nvm_ioctl_dev_create(file, argp);
+ case NVM_DEV_REMOVE:
+ return nvm_ioctl_dev_remove(file, argp);
+ }
+ return 0;
+}
+
+static const struct file_operations _ctl_fops = {
+ .open = nonseekable_open,
+ .unlocked_ioctl = nvm_ctl_ioctl,
+ .owner = THIS_MODULE,
+ .llseek = noop_llseek,
+};
+
+static struct miscdevice _nvm_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "lightnvm",
+ .nodename = "lightnvm/control",
+ .fops = &_ctl_fops,
+};
+
+MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
+
+static int __init nvm_mod_init(void)
+{
+ int ret;
+
+ ret = misc_register(&_nvm_misc);
+ if (ret)
+ pr_err("nvm: misc_register failed for control device");
+
+ return ret;
+}
+
+static void __exit nvm_mod_exit(void)
+{
+ misc_deregister(&_nvm_misc);
+}
+
+MODULE_AUTHOR("Matias Bjorling <m@bjorling.me>");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+module_init(nvm_mod_init);
+module_exit(nvm_mod_exit);
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
new file mode 100644
index 000000000000..ae1fb2bdc5f4
--- /dev/null
+++ b/drivers/lightnvm/gennvm.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2015 Matias Bjorling <m@bjorling.me>
+ *
+ * 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Implementation of a generic nvm manager for Open-Channel SSDs.
+ */
+
+#include "gennvm.h"
+
+static void gennvm_blocks_free(struct nvm_dev *dev)
+{
+ struct gen_nvm *gn = dev->mp;
+ struct gen_lun *lun;
+ int i;
+
+ gennvm_for_each_lun(gn, lun, i) {
+ if (!lun->vlun.blocks)
+ break;
+ vfree(lun->vlun.blocks);
+ }
+}
+
+static void gennvm_luns_free(struct nvm_dev *dev)
+{
+ struct gen_nvm *gn = dev->mp;
+
+ kfree(gn->luns);
+}
+
+static int gennvm_luns_init(struct nvm_dev *dev, struct gen_nvm *gn)
+{
+ struct gen_lun *lun;
+ int i;
+
+ gn->luns = kcalloc(dev->nr_luns, sizeof(struct gen_lun), GFP_KERNEL);
+ if (!gn->luns)
+ return -ENOMEM;
+
+ gennvm_for_each_lun(gn, lun, i) {
+ spin_lock_init(&lun->vlun.lock);
+ INIT_LIST_HEAD(&lun->free_list);
+ INIT_LIST_HEAD(&lun->used_list);
+ INIT_LIST_HEAD(&lun->bb_list);
+
+ lun->reserved_blocks = 2; /* for GC only */
+ lun->vlun.id = i;
+ lun->vlun.lun_id = i % dev->luns_per_chnl;
+ lun->vlun.chnl_id = i / dev->luns_per_chnl;
+ lun->vlun.nr_free_blocks = dev->blks_per_lun;
+ }
+ return 0;
+}
+
+static int gennvm_block_bb(u32 lun_id, void *bb_bitmap, unsigned int nr_blocks,
+ void *private)
+{
+ struct gen_nvm *gn = private;
+ struct gen_lun *lun = &gn->luns[lun_id];
+ struct nvm_block *blk;
+ int i;
+
+ if (unlikely(bitmap_empty(bb_bitmap, nr_blocks)))
+ return 0;
+
+ i = -1;
+ while ((i = find_next_bit(bb_bitmap, nr_blocks, i + 1)) < nr_blocks) {
+ blk = &lun->vlun.blocks[i];
+ if (!blk) {
+ pr_err("gennvm: BB data is out of bounds.\n");
+ return -EINVAL;
+ }
+
+ list_move_tail(&blk->list, &lun->bb_list);
+ }
+
+ return 0;
+}
+
+static int gennvm_block_map(u64 slba, u32 nlb, __le64 *entries, void *private)
+{
+ struct nvm_dev *dev = private;
+ struct gen_nvm *gn = dev->mp;
+ sector_t max_pages = dev->total_pages * (dev->sec_size >> 9);
+ u64 elba = slba + nlb;
+ struct gen_lun *lun;
+ struct nvm_block *blk;
+ u64 i;
+ int lun_id;
+
+ if (unlikely(elba > dev->total_pages)) {
+ pr_err("gennvm: L2P data from device is out of bounds!\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nlb; i++) {
+ u64 pba = le64_to_cpu(entries[i]);
+
+ if (unlikely(pba >= max_pages && pba != U64_MAX)) {
+ pr_err("gennvm: L2P data entry is out of bounds!\n");
+ return -EINVAL;
+ }
+
+ /* Address zero is a special one. The first page on a disk is
+ * protected. It often holds internal device boot
+ * information.
+ */
+ if (!pba)
+ continue;
+
+ /* resolve block from physical address */
+ lun_id = div_u64(pba, dev->sec_per_lun);
+ lun = &gn->luns[lun_id];
+
+ /* Calculate block offset into lun */
+ pba = pba - (dev->sec_per_lun * lun_id);
+ blk = &lun->vlun.blocks[div_u64(pba, dev->sec_per_blk)];
+
+ if (!blk->type) {
+ /* at this point, we don't know anything about the
+ * block. It's up to the FTL on top to re-etablish the
+ * block state
+ */
+ list_move_tail(&blk->list, &lun->used_list);
+ blk->type = 1;
+ lun->vlun.nr_free_blocks--;
+ }
+ }
+
+ return 0;
+}
+
+static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn)
+{
+ struct gen_lun *lun;
+ struct nvm_block *block;
+ sector_t lun_iter, blk_iter, cur_block_id = 0;
+ int ret;
+
+ gennvm_for_each_lun(gn, lun, lun_iter) {
+ lun->vlun.blocks = vzalloc(sizeof(struct nvm_block) *
+ dev->blks_per_lun);
+ if (!lun->vlun.blocks)
+ return -ENOMEM;
+
+ for (blk_iter = 0; blk_iter < dev->blks_per_lun; blk_iter++) {
+ block = &lun->vlun.blocks[blk_iter];
+
+ INIT_LIST_HEAD(&block->list);
+
+ block->lun = &lun->vlun;
+ block->id = cur_block_id++;
+
+ /* First block is reserved for device */
+ if (unlikely(lun_iter == 0 && blk_iter == 0))
+ continue;
+
+ list_add_tail(&block->list, &lun->free_list);
+ }
+
+ if (dev->ops->get_bb_tbl) {
+ ret = dev->ops->get_bb_tbl(dev->q, lun->vlun.id,
+ dev->blks_per_lun, gennvm_block_bb, gn);
+ if (ret)
+ pr_err("gennvm: could not read BB table\n");
+ }
+ }
+
+ if (dev->ops->get_l2p_tbl) {
+ ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
+ gennvm_block_map, dev);
+ if (ret) {
+ pr_err("gennvm: could not read L2P table.\n");
+ pr_warn("gennvm: default block initialization");
+ }
+ }
+
+ return 0;
+}
+
+static int gennvm_register(struct nvm_dev *dev)
+{
+ struct gen_nvm *gn;
+ int ret;
+
+ gn = kzalloc(sizeof(struct gen_nvm), GFP_KERNEL);
+ if (!gn)
+ return -ENOMEM;
+
+ gn->nr_luns = dev->nr_luns;
+ dev->mp = gn;
+
+ ret = gennvm_luns_init(dev, gn);
+ if (ret) {
+ pr_err("gennvm: could not initialize luns\n");
+ goto err;
+ }
+
+ ret = gennvm_blocks_init(dev, gn);
+ if (ret) {
+ pr_err("gennvm: could not initialize blocks\n");
+ goto err;
+ }
+
+ return 1;
+err:
+ kfree(gn);
+ return ret;
+}
+
+static void gennvm_unregister(struct nvm_dev *dev)
+{
+ gennvm_blocks_free(dev);
+ gennvm_luns_free(dev);
+ kfree(dev->mp);
+ dev->mp = NULL;
+}
+
+static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
+ struct nvm_lun *vlun, unsigned long flags)
+{
+ struct gen_lun *lun = container_of(vlun, struct gen_lun, vlun);
+ struct nvm_block *blk = NULL;
+ int is_gc = flags & NVM_IOTYPE_GC;
+
+ spin_lock(&vlun->lock);
+
+ if (list_empty(&lun->free_list)) {
+ pr_err_ratelimited("gennvm: lun %u have no free pages available",
+ lun->vlun.id);
+ spin_unlock(&vlun->lock);
+ goto out;
+ }
+
+ while (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks) {
+ spin_unlock(&vlun->lock);
+ goto out;
+ }
+
+ blk = list_first_entry(&lun->free_list, struct nvm_block, list);
+ list_move_tail(&blk->list, &lun->used_list);
+ blk->type = 1;
+
+ lun->vlun.nr_free_blocks--;
+
+ spin_unlock(&vlun->lock);
+out:
+ return blk;
+}
+
+static void gennvm_put_blk(struct nvm_dev *dev, struct nvm_block *blk)
+{
+ struct nvm_lun *vlun = blk->lun;
+ struct gen_lun *lun = container_of(vlun, struct gen_lun, vlun);
+
+ spin_lock(&vlun->lock);
+
+ switch (blk->type) {
+ case 1:
+ list_move_tail(&blk->list, &lun->free_list);
+ lun->vlun.nr_free_blocks++;
+ blk->type = 0;
+ break;
+ case 2:
+ list_move_tail(&blk->list, &lun->bb_list);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ pr_err("gennvm: erroneous block type (%lu -> %u)\n",
+ blk->id, blk->type);
+ list_move_tail(&blk->list, &lun->bb_list);
+ }
+
+ spin_unlock(&vlun->lock);
+}
+
+static void gennvm_addr_to_generic_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
+{
+ int i;
+
+ if (rqd->nr_pages > 1) {
+ for (i = 0; i < rqd->nr_pages; i++)
+ rqd->ppa_list[i] = addr_to_generic_mode(dev,
+ rqd->ppa_list[i]);
+ } else {
+ rqd->ppa_addr = addr_to_generic_mode(dev, rqd->ppa_addr);
+ }
+}
+
+static void gennvm_generic_to_addr_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
+{
+ int i;
+
+ if (rqd->nr_pages > 1) {
+ for (i = 0; i < rqd->nr_pages; i++)
+ rqd->ppa_list[i] = generic_to_addr_mode(dev,
+ rqd->ppa_list[i]);
+ } else {
+ rqd->ppa_addr = generic_to_addr_mode(dev, rqd->ppa_addr);
+ }
+}
+
+static int gennvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
+{
+ if (!dev->ops->submit_io)
+ return 0;
+
+ /* Convert address space */
+ gennvm_generic_to_addr_mode(dev, rqd);
+
+ rqd->dev = dev;
+ return dev->ops->submit_io(dev->q, rqd);
+}
+
+static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa,
+ int type)
+{
+ struct gen_nvm *gn = dev->mp;
+ struct gen_lun *lun;
+ struct nvm_block *blk;
+
+ if (unlikely(ppa->g.ch > dev->nr_chnls ||
+ ppa->g.lun > dev->luns_per_chnl ||
+ ppa->g.blk > dev->blks_per_lun)) {
+ WARN_ON_ONCE(1);
+ pr_err("gennvm: ppa broken (ch: %u > %u lun: %u > %u blk: %u > %u",
+ ppa->g.ch, dev->nr_chnls,
+ ppa->g.lun, dev->luns_per_chnl,
+ ppa->g.blk, dev->blks_per_lun);
+ return;
+ }
+
+ lun = &gn->luns[ppa->g.lun * ppa->g.ch];
+ blk = &lun->vlun.blocks[ppa->g.blk];
+
+ /* will be moved to bb list on put_blk from target */
+ blk->type = type;
+}
+
+/* mark block bad. It is expected the target recover from the error. */
+static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd)
+{
+ int i;
+
+ if (!dev->ops->set_bb)
+ return;
+
+ if (dev->ops->set_bb(dev->q, rqd, 1))
+ return;
+
+ gennvm_addr_to_generic_mode(dev, rqd);
+
+ /* look up blocks and mark them as bad */
+ if (rqd->nr_pages > 1)
+ for (i = 0; i < rqd->nr_pages; i++)
+ gennvm_blk_set_type(dev, &rqd->ppa_list[i], 2);
+ else
+ gennvm_blk_set_type(dev, &rqd->ppa_addr, 2);
+}
+
+static int gennvm_end_io(struct nvm_rq *rqd, int error)
+{
+ struct nvm_tgt_instance *ins = rqd->ins;
+ int ret = 0;
+
+ switch (error) {
+ case NVM_RSP_SUCCESS:
+ break;
+ case NVM_RSP_ERR_EMPTYPAGE:
+ break;
+ case NVM_RSP_ERR_FAILWRITE:
+ gennvm_mark_blk_bad(rqd->dev, rqd);
+ default:
+ ret++;
+ }
+
+ ret += ins->tt->end_io(rqd, error);
+
+ return ret;
+}
+
+static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk,
+ unsigned long flags)
+{
+ int plane_cnt = 0, pl_idx, ret;
+ struct ppa_addr addr;
+ struct nvm_rq rqd;
+
+ if (!dev->ops->erase_block)
+ return 0;
+
+ addr = block_to_ppa(dev, blk);
+
+ if (dev->plane_mode == NVM_PLANE_SINGLE) {
+ rqd.nr_pages = 1;
+ rqd.ppa_addr = addr;
+ } else {
+ plane_cnt = (1 << dev->plane_mode);
+ rqd.nr_pages = plane_cnt;
+
+ rqd.ppa_list = nvm_dev_dma_alloc(dev, GFP_KERNEL,
+ &rqd.dma_ppa_list);
+ if (!rqd.ppa_list) {
+ pr_err("gennvm: failed to allocate dma memory\n");
+ return -ENOMEM;
+ }
+
+ for (pl_idx = 0; pl_idx < plane_cnt; pl_idx++) {
+ addr.g.pl = pl_idx;
+ rqd.ppa_list[pl_idx] = addr;
+ }
+ }
+
+ gennvm_generic_to_addr_mode(dev, &rqd);
+
+ ret = dev->ops->erase_block(dev->q, &rqd);
+
+ if (plane_cnt)
+ nvm_dev_dma_free(dev, rqd.ppa_list, rqd.dma_ppa_list);
+
+ return ret;
+}
+
+static struct nvm_lun *gennvm_get_lun(struct nvm_dev *dev, int lunid)
+{
+ struct gen_nvm *gn = dev->mp;
+
+ return &gn->luns[lunid].vlun;
+}
+
+static void gennvm_free_blocks_print(struct nvm_dev *dev)
+{
+ struct gen_nvm *gn = dev->mp;
+ struct gen_lun *lun;
+ unsigned int i;
+
+ gennvm_for_each_lun(gn, lun, i)
+ pr_info("%s: lun%8u\t%u\n",
+ dev->name, i, lun->vlun.nr_free_blocks);
+}
+
+static struct nvmm_type gennvm = {
+ .name = "gennvm",
+ .version = {0, 1, 0},
+
+ .register_mgr = gennvm_register,
+ .unregister_mgr = gennvm_unregister,
+
+ .get_blk = gennvm_get_blk,
+ .put_blk = gennvm_put_blk,
+
+ .submit_io = gennvm_submit_io,
+ .end_io = gennvm_end_io,
+ .erase_blk = gennvm_erase_blk,
+
+ .get_lun = gennvm_get_lun,
+ .free_blocks_print = gennvm_free_blocks_print,
+};
+
+static int __init gennvm_module_init(void)
+{
+ return nvm_register_mgr(&gennvm);
+}
+
+static void gennvm_module_exit(void)
+{
+ nvm_unregister_mgr(&gennvm);
+}
+
+module_init(gennvm_module_init);
+module_exit(gennvm_module_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Generic media manager for Open-Channel SSDs");
diff --git a/drivers/lightnvm/gennvm.h b/drivers/lightnvm/gennvm.h
new file mode 100644
index 000000000000..d23bd3501ddc
--- /dev/null
+++ b/drivers/lightnvm/gennvm.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright: Matias Bjorling <mb@bjorling.me>
+ *
+ * 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.
+ *
+ */
+
+#ifndef GENNVM_H_
+#define GENNVM_H_
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/lightnvm.h>
+
+struct gen_lun {
+ struct nvm_lun vlun;
+
+ int reserved_blocks;
+ /* lun block lists */
+ struct list_head used_list; /* In-use blocks */
+ struct list_head free_list; /* Not used blocks i.e. released
+ * and ready for use
+ */
+ struct list_head bb_list; /* Bad blocks. Mutually exclusive with
+ * free_list and used_list
+ */
+};
+
+struct gen_nvm {
+ int nr_luns;
+ struct gen_lun *luns;
+};
+
+#define gennvm_for_each_lun(bm, lun, i) \
+ for ((i) = 0, lun = &(bm)->luns[0]; \
+ (i) < (bm)->nr_luns; (i)++, lun = &(bm)->luns[(i)])
+
+#endif /* GENNVM_H_ */
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
new file mode 100644
index 000000000000..7ba64c87ba1c
--- /dev/null
+++ b/drivers/lightnvm/rrpc.c
@@ -0,0 +1,1324 @@
+/*
+ * Copyright (C) 2015 IT University of Copenhagen
+ * Initial release: Matias Bjorling <m@bjorling.me>
+ *
+ * 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.
+ *
+ * Implementation of a Round-robin page-based Hybrid FTL for Open-channel SSDs.
+ */
+
+#include "rrpc.h"
+
+static struct kmem_cache *rrpc_gcb_cache, *rrpc_rq_cache;
+static DECLARE_RWSEM(rrpc_lock);
+
+static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd, unsigned long flags);
+
+#define rrpc_for_each_lun(rrpc, rlun, i) \
+ for ((i) = 0, rlun = &(rrpc)->luns[0]; \
+ (i) < (rrpc)->nr_luns; (i)++, rlun = &(rrpc)->luns[(i)])
+
+static void rrpc_page_invalidate(struct rrpc *rrpc, struct rrpc_addr *a)
+{
+ struct rrpc_block *rblk = a->rblk;
+ unsigned int pg_offset;
+
+ lockdep_assert_held(&rrpc->rev_lock);
+
+ if (a->addr == ADDR_EMPTY || !rblk)
+ return;
+
+ spin_lock(&rblk->lock);
+
+ div_u64_rem(a->addr, rrpc->dev->pgs_per_blk, &pg_offset);
+ WARN_ON(test_and_set_bit(pg_offset, rblk->invalid_pages));
+ rblk->nr_invalid_pages++;
+
+ spin_unlock(&rblk->lock);
+
+ rrpc->rev_trans_map[a->addr - rrpc->poffset].addr = ADDR_EMPTY;
+}
+
+static void rrpc_invalidate_range(struct rrpc *rrpc, sector_t slba,
+ unsigned len)
+{
+ sector_t i;
+
+ spin_lock(&rrpc->rev_lock);
+ for (i = slba; i < slba + len; i++) {
+ struct rrpc_addr *gp = &rrpc->trans_map[i];
+
+ rrpc_page_invalidate(rrpc, gp);
+ gp->rblk = NULL;
+ }
+ spin_unlock(&rrpc->rev_lock);
+}
+
+static struct nvm_rq *rrpc_inflight_laddr_acquire(struct rrpc *rrpc,
+ sector_t laddr, unsigned int pages)
+{
+ struct nvm_rq *rqd;
+ struct rrpc_inflight_rq *inf;
+
+ rqd = mempool_alloc(rrpc->rq_pool, GFP_ATOMIC);
+ if (!rqd)
+ return ERR_PTR(-ENOMEM);
+
+ inf = rrpc_get_inflight_rq(rqd);
+ if (rrpc_lock_laddr(rrpc, laddr, pages, inf)) {
+ mempool_free(rqd, rrpc->rq_pool);
+ return NULL;
+ }
+
+ return rqd;
+}
+
+static void rrpc_inflight_laddr_release(struct rrpc *rrpc, struct nvm_rq *rqd)
+{
+ struct rrpc_inflight_rq *inf = rrpc_get_inflight_rq(rqd);
+
+ rrpc_unlock_laddr(rrpc, inf);
+
+ mempool_free(rqd, rrpc->rq_pool);
+}
+
+static void rrpc_discard(struct rrpc *rrpc, struct bio *bio)
+{
+ sector_t slba = bio->bi_iter.bi_sector / NR_PHY_IN_LOG;
+ sector_t len = bio->bi_iter.bi_size / RRPC_EXPOSED_PAGE_SIZE;
+ struct nvm_rq *rqd;
+
+ do {
+ rqd = rrpc_inflight_laddr_acquire(rrpc, slba, len);
+ schedule();
+ } while (!rqd);
+
+ if (IS_ERR(rqd)) {
+ pr_err("rrpc: unable to acquire inflight IO\n");
+ bio_io_error(bio);
+ return;
+ }
+
+ rrpc_invalidate_range(rrpc, slba, len);
+ rrpc_inflight_laddr_release(rrpc, rqd);
+}
+
+static int block_is_full(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ return (rblk->next_page == rrpc->dev->pgs_per_blk);
+}
+
+static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ struct nvm_block *blk = rblk->parent;
+
+ return blk->id * rrpc->dev->pgs_per_blk;
+}
+
+static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_dev *dev, u64 addr)
+{
+ struct ppa_addr paddr;
+
+ paddr.ppa = addr;
+ return __linear_to_generic_addr(dev, paddr);
+}
+
+/* requires lun->lock taken */
+static void rrpc_set_lun_cur(struct rrpc_lun *rlun, struct rrpc_block *rblk)
+{
+ struct rrpc *rrpc = rlun->rrpc;
+
+ BUG_ON(!rblk);
+
+ if (rlun->cur) {
+ spin_lock(&rlun->cur->lock);
+ WARN_ON(!block_is_full(rrpc, rlun->cur));
+ spin_unlock(&rlun->cur->lock);
+ }
+ rlun->cur = rblk;
+}
+
+static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun,
+ unsigned long flags)
+{
+ struct nvm_block *blk;
+ struct rrpc_block *rblk;
+
+ blk = nvm_get_blk(rrpc->dev, rlun->parent, 0);
+ if (!blk)
+ return NULL;
+
+ rblk = &rlun->blocks[blk->id];
+ blk->priv = rblk;
+
+ bitmap_zero(rblk->invalid_pages, rrpc->dev->pgs_per_blk);
+ rblk->next_page = 0;
+ rblk->nr_invalid_pages = 0;
+ atomic_set(&rblk->data_cmnt_size, 0);
+
+ return rblk;
+}
+
+static void rrpc_put_blk(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ nvm_put_blk(rrpc->dev, rblk->parent);
+}
+
+static struct rrpc_lun *get_next_lun(struct rrpc *rrpc)
+{
+ int next = atomic_inc_return(&rrpc->next_lun);
+
+ return &rrpc->luns[next % rrpc->nr_luns];
+}
+
+static void rrpc_gc_kick(struct rrpc *rrpc)
+{
+ struct rrpc_lun *rlun;
+ unsigned int i;
+
+ for (i = 0; i < rrpc->nr_luns; i++) {
+ rlun = &rrpc->luns[i];
+ queue_work(rrpc->krqd_wq, &rlun->ws_gc);
+ }
+}
+
+/*
+ * timed GC every interval.
+ */
+static void rrpc_gc_timer(unsigned long data)
+{
+ struct rrpc *rrpc = (struct rrpc *)data;
+
+ rrpc_gc_kick(rrpc);
+ mod_timer(&rrpc->gc_timer, jiffies + msecs_to_jiffies(10));
+}
+
+static void rrpc_end_sync_bio(struct bio *bio)
+{
+ struct completion *waiting = bio->bi_private;
+
+ if (bio->bi_error)
+ pr_err("nvm: gc request failed (%u).\n", bio->bi_error);
+
+ complete(waiting);
+}
+
+/*
+ * rrpc_move_valid_pages -- migrate live data off the block
+ * @rrpc: the 'rrpc' structure
+ * @block: the block from which to migrate live pages
+ *
+ * Description:
+ * GC algorithms may call this function to migrate remaining live
+ * pages off the block prior to erasing it. This function blocks
+ * further execution until the operation is complete.
+ */
+static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ struct request_queue *q = rrpc->dev->q;
+ struct rrpc_rev_addr *rev;
+ struct nvm_rq *rqd;
+ struct bio *bio;
+ struct page *page;
+ int slot;
+ int nr_pgs_per_blk = rrpc->dev->pgs_per_blk;
+ u64 phys_addr;
+ DECLARE_COMPLETION_ONSTACK(wait);
+
+ if (bitmap_full(rblk->invalid_pages, nr_pgs_per_blk))
+ return 0;
+
+ bio = bio_alloc(GFP_NOIO, 1);
+ if (!bio) {
+ pr_err("nvm: could not alloc bio to gc\n");
+ return -ENOMEM;
+ }
+
+ page = mempool_alloc(rrpc->page_pool, GFP_NOIO);
+
+ while ((slot = find_first_zero_bit(rblk->invalid_pages,
+ nr_pgs_per_blk)) < nr_pgs_per_blk) {
+
+ /* Lock laddr */
+ phys_addr = (rblk->parent->id * nr_pgs_per_blk) + slot;
+
+try:
+ spin_lock(&rrpc->rev_lock);
+ /* Get logical address from physical to logical table */
+ rev = &rrpc->rev_trans_map[phys_addr - rrpc->poffset];
+ /* already updated by previous regular write */
+ if (rev->addr == ADDR_EMPTY) {
+ spin_unlock(&rrpc->rev_lock);
+ continue;
+ }
+
+ rqd = rrpc_inflight_laddr_acquire(rrpc, rev->addr, 1);
+ if (IS_ERR_OR_NULL(rqd)) {
+ spin_unlock(&rrpc->rev_lock);
+ schedule();
+ goto try;
+ }
+
+ spin_unlock(&rrpc->rev_lock);
+
+ /* Perform read to do GC */
+ bio->bi_iter.bi_sector = rrpc_get_sector(rev->addr);
+ bio->bi_rw = READ;
+ bio->bi_private = &wait;
+ bio->bi_end_io = rrpc_end_sync_bio;
+
+ /* TODO: may fail when EXP_PG_SIZE > PAGE_SIZE */
+ bio_add_pc_page(q, bio, page, RRPC_EXPOSED_PAGE_SIZE, 0);
+
+ if (rrpc_submit_io(rrpc, bio, rqd, NVM_IOTYPE_GC)) {
+ pr_err("rrpc: gc read failed.\n");
+ rrpc_inflight_laddr_release(rrpc, rqd);
+ goto finished;
+ }
+ wait_for_completion_io(&wait);
+
+ bio_reset(bio);
+ reinit_completion(&wait);
+
+ bio->bi_iter.bi_sector = rrpc_get_sector(rev->addr);
+ bio->bi_rw = WRITE;
+ bio->bi_private = &wait;
+ bio->bi_end_io = rrpc_end_sync_bio;
+
+ bio_add_pc_page(q, bio, page, RRPC_EXPOSED_PAGE_SIZE, 0);
+
+ /* turn the command around and write the data back to a new
+ * address
+ */
+ if (rrpc_submit_io(rrpc, bio, rqd, NVM_IOTYPE_GC)) {
+ pr_err("rrpc: gc write failed.\n");
+ rrpc_inflight_laddr_release(rrpc, rqd);
+ goto finished;
+ }
+ wait_for_completion_io(&wait);
+
+ rrpc_inflight_laddr_release(rrpc, rqd);
+
+ bio_reset(bio);
+ }
+
+finished:
+ mempool_free(page, rrpc->page_pool);
+ bio_put(bio);
+
+ if (!bitmap_full(rblk->invalid_pages, nr_pgs_per_blk)) {
+ pr_err("nvm: failed to garbage collect block\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void rrpc_block_gc(struct work_struct *work)
+{
+ struct rrpc_block_gc *gcb = container_of(work, struct rrpc_block_gc,
+ ws_gc);
+ struct rrpc *rrpc = gcb->rrpc;
+ struct rrpc_block *rblk = gcb->rblk;
+ struct nvm_dev *dev = rrpc->dev;
+
+ pr_debug("nvm: block '%lu' being reclaimed\n", rblk->parent->id);
+
+ if (rrpc_move_valid_pages(rrpc, rblk))
+ goto done;
+
+ nvm_erase_blk(dev, rblk->parent);
+ rrpc_put_blk(rrpc, rblk);
+done:
+ mempool_free(gcb, rrpc->gcb_pool);
+}
+
+/* the block with highest number of invalid pages, will be in the beginning
+ * of the list
+ */
+static struct rrpc_block *rblock_max_invalid(struct rrpc_block *ra,
+ struct rrpc_block *rb)
+{
+ if (ra->nr_invalid_pages == rb->nr_invalid_pages)
+ return ra;
+
+ return (ra->nr_invalid_pages < rb->nr_invalid_pages) ? rb : ra;
+}
+
+/* linearly find the block with highest number of invalid pages
+ * requires lun->lock
+ */
+static struct rrpc_block *block_prio_find_max(struct rrpc_lun *rlun)
+{
+ struct list_head *prio_list = &rlun->prio_list;
+ struct rrpc_block *rblock, *max;
+
+ BUG_ON(list_empty(prio_list));
+
+ max = list_first_entry(prio_list, struct rrpc_block, prio);
+ list_for_each_entry(rblock, prio_list, prio)
+ max = rblock_max_invalid(max, rblock);
+
+ return max;
+}
+
+static void rrpc_lun_gc(struct work_struct *work)
+{
+ struct rrpc_lun *rlun = container_of(work, struct rrpc_lun, ws_gc);
+ struct rrpc *rrpc = rlun->rrpc;
+ struct nvm_lun *lun = rlun->parent;
+ struct rrpc_block_gc *gcb;
+ unsigned int nr_blocks_need;
+
+ nr_blocks_need = rrpc->dev->blks_per_lun / GC_LIMIT_INVERSE;
+
+ if (nr_blocks_need < rrpc->nr_luns)
+ nr_blocks_need = rrpc->nr_luns;
+
+ spin_lock(&lun->lock);
+ while (nr_blocks_need > lun->nr_free_blocks &&
+ !list_empty(&rlun->prio_list)) {
+ struct rrpc_block *rblock = block_prio_find_max(rlun);
+ struct nvm_block *block = rblock->parent;
+
+ if (!rblock->nr_invalid_pages)
+ break;
+
+ list_del_init(&rblock->prio);
+
+ BUG_ON(!block_is_full(rrpc, rblock));
+
+ pr_debug("rrpc: selected block '%lu' for GC\n", block->id);
+
+ gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC);
+ if (!gcb)
+ break;
+
+ gcb->rrpc = rrpc;
+ gcb->rblk = rblock;
+ INIT_WORK(&gcb->ws_gc, rrpc_block_gc);
+
+ queue_work(rrpc->kgc_wq, &gcb->ws_gc);
+
+ nr_blocks_need--;
+ }
+ spin_unlock(&lun->lock);
+
+ /* TODO: Hint that request queue can be started again */
+}
+
+static void rrpc_gc_queue(struct work_struct *work)
+{
+ struct rrpc_block_gc *gcb = container_of(work, struct rrpc_block_gc,
+ ws_gc);
+ struct rrpc *rrpc = gcb->rrpc;
+ struct rrpc_block *rblk = gcb->rblk;
+ struct nvm_lun *lun = rblk->parent->lun;
+ struct rrpc_lun *rlun = &rrpc->luns[lun->id - rrpc->lun_offset];
+
+ spin_lock(&rlun->lock);
+ list_add_tail(&rblk->prio, &rlun->prio_list);
+ spin_unlock(&rlun->lock);
+
+ mempool_free(gcb, rrpc->gcb_pool);
+ pr_debug("nvm: block '%lu' is full, allow GC (sched)\n",
+ rblk->parent->id);
+}
+
+static const struct block_device_operations rrpc_fops = {
+ .owner = THIS_MODULE,
+};
+
+static struct rrpc_lun *rrpc_get_lun_rr(struct rrpc *rrpc, int is_gc)
+{
+ unsigned int i;
+ struct rrpc_lun *rlun, *max_free;
+
+ if (!is_gc)
+ return get_next_lun(rrpc);
+
+ /* during GC, we don't care about RR, instead we want to make
+ * sure that we maintain evenness between the block luns.
+ */
+ max_free = &rrpc->luns[0];
+ /* prevent GC-ing lun from devouring pages of a lun with
+ * little free blocks. We don't take the lock as we only need an
+ * estimate.
+ */
+ rrpc_for_each_lun(rrpc, rlun, i) {
+ if (rlun->parent->nr_free_blocks >
+ max_free->parent->nr_free_blocks)
+ max_free = rlun;
+ }
+
+ return max_free;
+}
+
+static struct rrpc_addr *rrpc_update_map(struct rrpc *rrpc, sector_t laddr,
+ struct rrpc_block *rblk, u64 paddr)
+{
+ struct rrpc_addr *gp;
+ struct rrpc_rev_addr *rev;
+
+ BUG_ON(laddr >= rrpc->nr_pages);
+
+ gp = &rrpc->trans_map[laddr];
+ spin_lock(&rrpc->rev_lock);
+ if (gp->rblk)
+ rrpc_page_invalidate(rrpc, gp);
+
+ gp->addr = paddr;
+ gp->rblk = rblk;
+
+ rev = &rrpc->rev_trans_map[gp->addr - rrpc->poffset];
+ rev->addr = laddr;
+ spin_unlock(&rrpc->rev_lock);
+
+ return gp;
+}
+
+static u64 rrpc_alloc_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ u64 addr = ADDR_EMPTY;
+
+ spin_lock(&rblk->lock);
+ if (block_is_full(rrpc, rblk))
+ goto out;
+
+ addr = block_to_addr(rrpc, rblk) + rblk->next_page;
+
+ rblk->next_page++;
+out:
+ spin_unlock(&rblk->lock);
+ return addr;
+}
+
+/* Simple round-robin Logical to physical address translation.
+ *
+ * Retrieve the mapping using the active append point. Then update the ap for
+ * the next write to the disk.
+ *
+ * Returns rrpc_addr with the physical address and block. Remember to return to
+ * rrpc->addr_cache when request is finished.
+ */
+static struct rrpc_addr *rrpc_map_page(struct rrpc *rrpc, sector_t laddr,
+ int is_gc)
+{
+ struct rrpc_lun *rlun;
+ struct rrpc_block *rblk;
+ struct nvm_lun *lun;
+ u64 paddr;
+
+ rlun = rrpc_get_lun_rr(rrpc, is_gc);
+ lun = rlun->parent;
+
+ if (!is_gc && lun->nr_free_blocks < rrpc->nr_luns * 4)
+ return NULL;
+
+ spin_lock(&rlun->lock);
+
+ rblk = rlun->cur;
+retry:
+ paddr = rrpc_alloc_addr(rrpc, rblk);
+
+ if (paddr == ADDR_EMPTY) {
+ rblk = rrpc_get_blk(rrpc, rlun, 0);
+ if (rblk) {
+ rrpc_set_lun_cur(rlun, rblk);
+ goto retry;
+ }
+
+ if (is_gc) {
+ /* retry from emergency gc block */
+ paddr = rrpc_alloc_addr(rrpc, rlun->gc_cur);
+ if (paddr == ADDR_EMPTY) {
+ rblk = rrpc_get_blk(rrpc, rlun, 1);
+ if (!rblk) {
+ pr_err("rrpc: no more blocks");
+ goto err;
+ }
+
+ rlun->gc_cur = rblk;
+ paddr = rrpc_alloc_addr(rrpc, rlun->gc_cur);
+ }
+ rblk = rlun->gc_cur;
+ }
+ }
+
+ spin_unlock(&rlun->lock);
+ return rrpc_update_map(rrpc, laddr, rblk, paddr);
+err:
+ spin_unlock(&rlun->lock);
+ return NULL;
+}
+
+static void rrpc_run_gc(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ struct rrpc_block_gc *gcb;
+
+ gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC);
+ if (!gcb) {
+ pr_err("rrpc: unable to queue block for gc.");
+ return;
+ }
+
+ gcb->rrpc = rrpc;
+ gcb->rblk = rblk;
+
+ INIT_WORK(&gcb->ws_gc, rrpc_gc_queue);
+ queue_work(rrpc->kgc_wq, &gcb->ws_gc);
+}
+
+static void rrpc_end_io_write(struct rrpc *rrpc, struct rrpc_rq *rrqd,
+ sector_t laddr, uint8_t npages)
+{
+ struct rrpc_addr *p;
+ struct rrpc_block *rblk;
+ struct nvm_lun *lun;
+ int cmnt_size, i;
+
+ for (i = 0; i < npages; i++) {
+ p = &rrpc->trans_map[laddr + i];
+ rblk = p->rblk;
+ lun = rblk->parent->lun;
+
+ cmnt_size = atomic_inc_return(&rblk->data_cmnt_size);
+ if (unlikely(cmnt_size == rrpc->dev->pgs_per_blk))
+ rrpc_run_gc(rrpc, rblk);
+ }
+}
+
+static int rrpc_end_io(struct nvm_rq *rqd, int error)
+{
+ struct rrpc *rrpc = container_of(rqd->ins, struct rrpc, instance);
+ struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
+ uint8_t npages = rqd->nr_pages;
+ sector_t laddr = rrpc_get_laddr(rqd->bio) - npages;
+
+ if (bio_data_dir(rqd->bio) == WRITE)
+ rrpc_end_io_write(rrpc, rrqd, laddr, npages);
+
+ if (rrqd->flags & NVM_IOTYPE_GC)
+ return 0;
+
+ rrpc_unlock_rq(rrpc, rqd);
+ bio_put(rqd->bio);
+
+ if (npages > 1)
+ nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+ if (rqd->metadata)
+ nvm_dev_dma_free(rrpc->dev, rqd->metadata, rqd->dma_metadata);
+
+ mempool_free(rqd, rrpc->rq_pool);
+
+ return 0;
+}
+
+static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd, unsigned long flags, int npages)
+{
+ struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
+ struct rrpc_addr *gp;
+ sector_t laddr = rrpc_get_laddr(bio);
+ int is_gc = flags & NVM_IOTYPE_GC;
+ int i;
+
+ if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd)) {
+ nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+ return NVM_IO_REQUEUE;
+ }
+
+ for (i = 0; i < npages; i++) {
+ /* We assume that mapping occurs at 4KB granularity */
+ BUG_ON(!(laddr + i >= 0 && laddr + i < rrpc->nr_pages));
+ gp = &rrpc->trans_map[laddr + i];
+
+ if (gp->rblk) {
+ rqd->ppa_list[i] = rrpc_ppa_to_gaddr(rrpc->dev,
+ gp->addr);
+ } else {
+ BUG_ON(is_gc);
+ rrpc_unlock_laddr(rrpc, r);
+ nvm_dev_dma_free(rrpc->dev, rqd->ppa_list,
+ rqd->dma_ppa_list);
+ return NVM_IO_DONE;
+ }
+ }
+
+ rqd->opcode = NVM_OP_HBREAD;
+
+ return NVM_IO_OK;
+}
+
+static int rrpc_read_rq(struct rrpc *rrpc, struct bio *bio, struct nvm_rq *rqd,
+ unsigned long flags)
+{
+ struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
+ int is_gc = flags & NVM_IOTYPE_GC;
+ sector_t laddr = rrpc_get_laddr(bio);
+ struct rrpc_addr *gp;
+
+ if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd))
+ return NVM_IO_REQUEUE;
+
+ BUG_ON(!(laddr >= 0 && laddr < rrpc->nr_pages));
+ gp = &rrpc->trans_map[laddr];
+
+ if (gp->rblk) {
+ rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, gp->addr);
+ } else {
+ BUG_ON(is_gc);
+ rrpc_unlock_rq(rrpc, rqd);
+ return NVM_IO_DONE;
+ }
+
+ rqd->opcode = NVM_OP_HBREAD;
+ rrqd->addr = gp;
+
+ return NVM_IO_OK;
+}
+
+static int rrpc_write_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd, unsigned long flags, int npages)
+{
+ struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
+ struct rrpc_addr *p;
+ sector_t laddr = rrpc_get_laddr(bio);
+ int is_gc = flags & NVM_IOTYPE_GC;
+ int i;
+
+ if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd)) {
+ nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+ return NVM_IO_REQUEUE;
+ }
+
+ for (i = 0; i < npages; i++) {
+ /* We assume that mapping occurs at 4KB granularity */
+ p = rrpc_map_page(rrpc, laddr + i, is_gc);
+ if (!p) {
+ BUG_ON(is_gc);
+ rrpc_unlock_laddr(rrpc, r);
+ nvm_dev_dma_free(rrpc->dev, rqd->ppa_list,
+ rqd->dma_ppa_list);
+ rrpc_gc_kick(rrpc);
+ return NVM_IO_REQUEUE;
+ }
+
+ rqd->ppa_list[i] = rrpc_ppa_to_gaddr(rrpc->dev,
+ p->addr);
+ }
+
+ rqd->opcode = NVM_OP_HBWRITE;
+
+ return NVM_IO_OK;
+}
+
+static int rrpc_write_rq(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd, unsigned long flags)
+{
+ struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
+ struct rrpc_addr *p;
+ int is_gc = flags & NVM_IOTYPE_GC;
+ sector_t laddr = rrpc_get_laddr(bio);
+
+ if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd))
+ return NVM_IO_REQUEUE;
+
+ p = rrpc_map_page(rrpc, laddr, is_gc);
+ if (!p) {
+ BUG_ON(is_gc);
+ rrpc_unlock_rq(rrpc, rqd);
+ rrpc_gc_kick(rrpc);
+ return NVM_IO_REQUEUE;
+ }
+
+ rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, p->addr);
+ rqd->opcode = NVM_OP_HBWRITE;
+ rrqd->addr = p;
+
+ return NVM_IO_OK;
+}
+
+static int rrpc_setup_rq(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd, unsigned long flags, uint8_t npages)
+{
+ if (npages > 1) {
+ rqd->ppa_list = nvm_dev_dma_alloc(rrpc->dev, GFP_KERNEL,
+ &rqd->dma_ppa_list);
+ if (!rqd->ppa_list) {
+ pr_err("rrpc: not able to allocate ppa list\n");
+ return NVM_IO_ERR;
+ }
+
+ if (bio_rw(bio) == WRITE)
+ return rrpc_write_ppalist_rq(rrpc, bio, rqd, flags,
+ npages);
+
+ return rrpc_read_ppalist_rq(rrpc, bio, rqd, flags, npages);
+ }
+
+ if (bio_rw(bio) == WRITE)
+ return rrpc_write_rq(rrpc, bio, rqd, flags);
+
+ return rrpc_read_rq(rrpc, bio, rqd, flags);
+}
+
+static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd, unsigned long flags)
+{
+ int err;
+ struct rrpc_rq *rrq = nvm_rq_to_pdu(rqd);
+ uint8_t nr_pages = rrpc_get_pages(bio);
+ int bio_size = bio_sectors(bio) << 9;
+
+ if (bio_size < rrpc->dev->sec_size)
+ return NVM_IO_ERR;
+ else if (bio_size > rrpc->dev->max_rq_size)
+ return NVM_IO_ERR;
+
+ err = rrpc_setup_rq(rrpc, bio, rqd, flags, nr_pages);
+ if (err)
+ return err;
+
+ bio_get(bio);
+ rqd->bio = bio;
+ rqd->ins = &rrpc->instance;
+ rqd->nr_pages = nr_pages;
+ rrq->flags = flags;
+
+ err = nvm_submit_io(rrpc->dev, rqd);
+ if (err) {
+ pr_err("rrpc: I/O submission failed: %d\n", err);
+ return NVM_IO_ERR;
+ }
+
+ return NVM_IO_OK;
+}
+
+static blk_qc_t rrpc_make_rq(struct request_queue *q, struct bio *bio)
+{
+ struct rrpc *rrpc = q->queuedata;
+ struct nvm_rq *rqd;
+ int err;
+
+ if (bio->bi_rw & REQ_DISCARD) {
+ rrpc_discard(rrpc, bio);
+ return BLK_QC_T_NONE;
+ }
+
+ rqd = mempool_alloc(rrpc->rq_pool, GFP_KERNEL);
+ if (!rqd) {
+ pr_err_ratelimited("rrpc: not able to queue bio.");
+ bio_io_error(bio);
+ return BLK_QC_T_NONE;
+ }
+ memset(rqd, 0, sizeof(struct nvm_rq));
+
+ err = rrpc_submit_io(rrpc, bio, rqd, NVM_IOTYPE_NONE);
+ switch (err) {
+ case NVM_IO_OK:
+ return BLK_QC_T_NONE;
+ case NVM_IO_ERR:
+ bio_io_error(bio);
+ break;
+ case NVM_IO_DONE:
+ bio_endio(bio);
+ break;
+ case NVM_IO_REQUEUE:
+ spin_lock(&rrpc->bio_lock);
+ bio_list_add(&rrpc->requeue_bios, bio);
+ spin_unlock(&rrpc->bio_lock);
+ queue_work(rrpc->kgc_wq, &rrpc->ws_requeue);
+ break;
+ }
+
+ mempool_free(rqd, rrpc->rq_pool);
+ return BLK_QC_T_NONE;
+}
+
+static void rrpc_requeue(struct work_struct *work)
+{
+ struct rrpc *rrpc = container_of(work, struct rrpc, ws_requeue);
+ struct bio_list bios;
+ struct bio *bio;
+
+ bio_list_init(&bios);
+
+ spin_lock(&rrpc->bio_lock);
+ bio_list_merge(&bios, &rrpc->requeue_bios);
+ bio_list_init(&rrpc->requeue_bios);
+ spin_unlock(&rrpc->bio_lock);
+
+ while ((bio = bio_list_pop(&bios)))
+ rrpc_make_rq(rrpc->disk->queue, bio);
+}
+
+static void rrpc_gc_free(struct rrpc *rrpc)
+{
+ struct rrpc_lun *rlun;
+ int i;
+
+ if (rrpc->krqd_wq)
+ destroy_workqueue(rrpc->krqd_wq);
+
+ if (rrpc->kgc_wq)
+ destroy_workqueue(rrpc->kgc_wq);
+
+ if (!rrpc->luns)
+ return;
+
+ for (i = 0; i < rrpc->nr_luns; i++) {
+ rlun = &rrpc->luns[i];
+
+ if (!rlun->blocks)
+ break;
+ vfree(rlun->blocks);
+ }
+}
+
+static int rrpc_gc_init(struct rrpc *rrpc)
+{
+ rrpc->krqd_wq = alloc_workqueue("rrpc-lun", WQ_MEM_RECLAIM|WQ_UNBOUND,
+ rrpc->nr_luns);
+ if (!rrpc->krqd_wq)
+ return -ENOMEM;
+
+ rrpc->kgc_wq = alloc_workqueue("rrpc-bg", WQ_MEM_RECLAIM, 1);
+ if (!rrpc->kgc_wq)
+ return -ENOMEM;
+
+ setup_timer(&rrpc->gc_timer, rrpc_gc_timer, (unsigned long)rrpc);
+
+ return 0;
+}
+
+static void rrpc_map_free(struct rrpc *rrpc)
+{
+ vfree(rrpc->rev_trans_map);
+ vfree(rrpc->trans_map);
+}
+
+static int rrpc_l2p_update(u64 slba, u32 nlb, __le64 *entries, void *private)
+{
+ struct rrpc *rrpc = (struct rrpc *)private;
+ struct nvm_dev *dev = rrpc->dev;
+ struct rrpc_addr *addr = rrpc->trans_map + slba;
+ struct rrpc_rev_addr *raddr = rrpc->rev_trans_map;
+ sector_t max_pages = dev->total_pages * (dev->sec_size >> 9);
+ u64 elba = slba + nlb;
+ u64 i;
+
+ if (unlikely(elba > dev->total_pages)) {
+ pr_err("nvm: L2P data from device is out of bounds!\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nlb; i++) {
+ u64 pba = le64_to_cpu(entries[i]);
+ /* LNVM treats address-spaces as silos, LBA and PBA are
+ * equally large and zero-indexed.
+ */
+ if (unlikely(pba >= max_pages && pba != U64_MAX)) {
+ pr_err("nvm: L2P data entry is out of bounds!\n");
+ return -EINVAL;
+ }
+
+ /* Address zero is a special one. The first page on a disk is
+ * protected. As it often holds internal device boot
+ * information.
+ */
+ if (!pba)
+ continue;
+
+ addr[i].addr = pba;
+ raddr[pba].addr = slba + i;
+ }
+
+ return 0;
+}
+
+static int rrpc_map_init(struct rrpc *rrpc)
+{
+ struct nvm_dev *dev = rrpc->dev;
+ sector_t i;
+ int ret;
+
+ rrpc->trans_map = vzalloc(sizeof(struct rrpc_addr) * rrpc->nr_pages);
+ if (!rrpc->trans_map)
+ return -ENOMEM;
+
+ rrpc->rev_trans_map = vmalloc(sizeof(struct rrpc_rev_addr)
+ * rrpc->nr_pages);
+ if (!rrpc->rev_trans_map)
+ return -ENOMEM;
+
+ for (i = 0; i < rrpc->nr_pages; i++) {
+ struct rrpc_addr *p = &rrpc->trans_map[i];
+ struct rrpc_rev_addr *r = &rrpc->rev_trans_map[i];
+
+ p->addr = ADDR_EMPTY;
+ r->addr = ADDR_EMPTY;
+ }
+
+ if (!dev->ops->get_l2p_tbl)
+ return 0;
+
+ /* Bring up the mapping table from device */
+ ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
+ rrpc_l2p_update, rrpc);
+ if (ret) {
+ pr_err("nvm: rrpc: could not read L2P table.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/* Minimum pages needed within a lun */
+#define PAGE_POOL_SIZE 16
+#define ADDR_POOL_SIZE 64
+
+static int rrpc_core_init(struct rrpc *rrpc)
+{
+ down_write(&rrpc_lock);
+ if (!rrpc_gcb_cache) {
+ rrpc_gcb_cache = kmem_cache_create("rrpc_gcb",
+ sizeof(struct rrpc_block_gc), 0, 0, NULL);
+ if (!rrpc_gcb_cache) {
+ up_write(&rrpc_lock);
+ return -ENOMEM;
+ }
+
+ rrpc_rq_cache = kmem_cache_create("rrpc_rq",
+ sizeof(struct nvm_rq) + sizeof(struct rrpc_rq),
+ 0, 0, NULL);
+ if (!rrpc_rq_cache) {
+ kmem_cache_destroy(rrpc_gcb_cache);
+ up_write(&rrpc_lock);
+ return -ENOMEM;
+ }
+ }
+ up_write(&rrpc_lock);
+
+ rrpc->page_pool = mempool_create_page_pool(PAGE_POOL_SIZE, 0);
+ if (!rrpc->page_pool)
+ return -ENOMEM;
+
+ rrpc->gcb_pool = mempool_create_slab_pool(rrpc->dev->nr_luns,
+ rrpc_gcb_cache);
+ if (!rrpc->gcb_pool)
+ return -ENOMEM;
+
+ rrpc->rq_pool = mempool_create_slab_pool(64, rrpc_rq_cache);
+ if (!rrpc->rq_pool)
+ return -ENOMEM;
+
+ spin_lock_init(&rrpc->inflights.lock);
+ INIT_LIST_HEAD(&rrpc->inflights.reqs);
+
+ return 0;
+}
+
+static void rrpc_core_free(struct rrpc *rrpc)
+{
+ mempool_destroy(rrpc->page_pool);
+ mempool_destroy(rrpc->gcb_pool);
+ mempool_destroy(rrpc->rq_pool);
+}
+
+static void rrpc_luns_free(struct rrpc *rrpc)
+{
+ kfree(rrpc->luns);
+}
+
+static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)
+{
+ struct nvm_dev *dev = rrpc->dev;
+ struct rrpc_lun *rlun;
+ int i, j;
+
+ spin_lock_init(&rrpc->rev_lock);
+
+ rrpc->luns = kcalloc(rrpc->nr_luns, sizeof(struct rrpc_lun),
+ GFP_KERNEL);
+ if (!rrpc->luns)
+ return -ENOMEM;
+
+ /* 1:1 mapping */
+ for (i = 0; i < rrpc->nr_luns; i++) {
+ struct nvm_lun *lun = dev->mt->get_lun(dev, lun_begin + i);
+
+ if (dev->pgs_per_blk >
+ MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) {
+ pr_err("rrpc: number of pages per block too high.");
+ goto err;
+ }
+
+ rlun = &rrpc->luns[i];
+ rlun->rrpc = rrpc;
+ rlun->parent = lun;
+ INIT_LIST_HEAD(&rlun->prio_list);
+ INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
+ spin_lock_init(&rlun->lock);
+
+ rrpc->total_blocks += dev->blks_per_lun;
+ rrpc->nr_pages += dev->sec_per_lun;
+
+ rlun->blocks = vzalloc(sizeof(struct rrpc_block) *
+ rrpc->dev->blks_per_lun);
+ if (!rlun->blocks)
+ goto err;
+
+ for (j = 0; j < rrpc->dev->blks_per_lun; j++) {
+ struct rrpc_block *rblk = &rlun->blocks[j];
+ struct nvm_block *blk = &lun->blocks[j];
+
+ rblk->parent = blk;
+ INIT_LIST_HEAD(&rblk->prio);
+ spin_lock_init(&rblk->lock);
+ }
+ }
+
+ return 0;
+err:
+ return -ENOMEM;
+}
+
+static void rrpc_free(struct rrpc *rrpc)
+{
+ rrpc_gc_free(rrpc);
+ rrpc_map_free(rrpc);
+ rrpc_core_free(rrpc);
+ rrpc_luns_free(rrpc);
+
+ kfree(rrpc);
+}
+
+static void rrpc_exit(void *private)
+{
+ struct rrpc *rrpc = private;
+
+ del_timer(&rrpc->gc_timer);
+
+ flush_workqueue(rrpc->krqd_wq);
+ flush_workqueue(rrpc->kgc_wq);
+
+ rrpc_free(rrpc);
+}
+
+static sector_t rrpc_capacity(void *private)
+{
+ struct rrpc *rrpc = private;
+ struct nvm_dev *dev = rrpc->dev;
+ sector_t reserved, provisioned;
+
+ /* cur, gc, and two emergency blocks for each lun */
+ reserved = rrpc->nr_luns * dev->max_pages_per_blk * 4;
+ provisioned = rrpc->nr_pages - reserved;
+
+ if (reserved > rrpc->nr_pages) {
+ pr_err("rrpc: not enough space available to expose storage.\n");
+ return 0;
+ }
+
+ sector_div(provisioned, 10);
+ return provisioned * 9 * NR_PHY_IN_LOG;
+}
+
+/*
+ * Looks up the logical address from reverse trans map and check if its valid by
+ * comparing the logical to physical address with the physical address.
+ * Returns 0 on free, otherwise 1 if in use
+ */
+static void rrpc_block_map_update(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+ struct nvm_dev *dev = rrpc->dev;
+ int offset;
+ struct rrpc_addr *laddr;
+ u64 paddr, pladdr;
+
+ for (offset = 0; offset < dev->pgs_per_blk; offset++) {
+ paddr = block_to_addr(rrpc, rblk) + offset;
+
+ pladdr = rrpc->rev_trans_map[paddr].addr;
+ if (pladdr == ADDR_EMPTY)
+ continue;
+
+ laddr = &rrpc->trans_map[pladdr];
+
+ if (paddr == laddr->addr) {
+ laddr->rblk = rblk;
+ } else {
+ set_bit(offset, rblk->invalid_pages);
+ rblk->nr_invalid_pages++;
+ }
+ }
+}
+
+static int rrpc_blocks_init(struct rrpc *rrpc)
+{
+ struct rrpc_lun *rlun;
+ struct rrpc_block *rblk;
+ int lun_iter, blk_iter;
+
+ for (lun_iter = 0; lun_iter < rrpc->nr_luns; lun_iter++) {
+ rlun = &rrpc->luns[lun_iter];
+
+ for (blk_iter = 0; blk_iter < rrpc->dev->blks_per_lun;
+ blk_iter++) {
+ rblk = &rlun->blocks[blk_iter];
+ rrpc_block_map_update(rrpc, rblk);
+ }
+ }
+
+ return 0;
+}
+
+static int rrpc_luns_configure(struct rrpc *rrpc)
+{
+ struct rrpc_lun *rlun;
+ struct rrpc_block *rblk;
+ int i;
+
+ for (i = 0; i < rrpc->nr_luns; i++) {
+ rlun = &rrpc->luns[i];
+
+ rblk = rrpc_get_blk(rrpc, rlun, 0);
+ if (!rblk)
+ return -EINVAL;
+
+ rrpc_set_lun_cur(rlun, rblk);
+
+ /* Emergency gc block */
+ rblk = rrpc_get_blk(rrpc, rlun, 1);
+ if (!rblk)
+ return -EINVAL;
+ rlun->gc_cur = rblk;
+ }
+
+ return 0;
+}
+
+static struct nvm_tgt_type tt_rrpc;
+
+static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
+ int lun_begin, int lun_end)
+{
+ struct request_queue *bqueue = dev->q;
+ struct request_queue *tqueue = tdisk->queue;
+ struct rrpc *rrpc;
+ int ret;
+
+ if (!(dev->identity.dom & NVM_RSP_L2P)) {
+ pr_err("nvm: rrpc: device does not support l2p (%x)\n",
+ dev->identity.dom);
+ return ERR_PTR(-EINVAL);
+ }
+
+ rrpc = kzalloc(sizeof(struct rrpc), GFP_KERNEL);
+ if (!rrpc)
+ return ERR_PTR(-ENOMEM);
+
+ rrpc->instance.tt = &tt_rrpc;
+ rrpc->dev = dev;
+ rrpc->disk = tdisk;
+
+ bio_list_init(&rrpc->requeue_bios);
+ spin_lock_init(&rrpc->bio_lock);
+ INIT_WORK(&rrpc->ws_requeue, rrpc_requeue);
+
+ rrpc->nr_luns = lun_end - lun_begin + 1;
+
+ /* simple round-robin strategy */
+ atomic_set(&rrpc->next_lun, -1);
+
+ ret = rrpc_luns_init(rrpc, lun_begin, lun_end);
+ if (ret) {
+ pr_err("nvm: rrpc: could not initialize luns\n");
+ goto err;
+ }
+
+ rrpc->poffset = dev->sec_per_lun * lun_begin;
+ rrpc->lun_offset = lun_begin;
+
+ ret = rrpc_core_init(rrpc);
+ if (ret) {
+ pr_err("nvm: rrpc: could not initialize core\n");
+ goto err;
+ }
+
+ ret = rrpc_map_init(rrpc);
+ if (ret) {
+ pr_err("nvm: rrpc: could not initialize maps\n");
+ goto err;
+ }
+
+ ret = rrpc_blocks_init(rrpc);
+ if (ret) {
+ pr_err("nvm: rrpc: could not initialize state for blocks\n");
+ goto err;
+ }
+
+ ret = rrpc_luns_configure(rrpc);
+ if (ret) {
+ pr_err("nvm: rrpc: not enough blocks available in LUNs.\n");
+ goto err;
+ }
+
+ ret = rrpc_gc_init(rrpc);
+ if (ret) {
+ pr_err("nvm: rrpc: could not initialize gc\n");
+ goto err;
+ }
+
+ /* inherit the size from the underlying device */
+ blk_queue_logical_block_size(tqueue, queue_physical_block_size(bqueue));
+ blk_queue_max_hw_sectors(tqueue, queue_max_hw_sectors(bqueue));
+
+ pr_info("nvm: rrpc initialized with %u luns and %llu pages.\n",
+ rrpc->nr_luns, (unsigned long long)rrpc->nr_pages);
+
+ mod_timer(&rrpc->gc_timer, jiffies + msecs_to_jiffies(10));
+
+ return rrpc;
+err:
+ rrpc_free(rrpc);
+ return ERR_PTR(ret);
+}
+
+/* round robin, page-based FTL, and cost-based GC */
+static struct nvm_tgt_type tt_rrpc = {
+ .name = "rrpc",
+ .version = {1, 0, 0},
+
+ .make_rq = rrpc_make_rq,
+ .capacity = rrpc_capacity,
+ .end_io = rrpc_end_io,
+
+ .init = rrpc_init,
+ .exit = rrpc_exit,
+};
+
+static int __init rrpc_module_init(void)
+{
+ return nvm_register_target(&tt_rrpc);
+}
+
+static void rrpc_module_exit(void)
+{
+ nvm_unregister_target(&tt_rrpc);
+}
+
+module_init(rrpc_module_init);
+module_exit(rrpc_module_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Block-Device Target for Open-Channel SSDs");
diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h
new file mode 100644
index 000000000000..a9696a06c38c
--- /dev/null
+++ b/drivers/lightnvm/rrpc.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2015 IT University of Copenhagen
+ * Initial release: Matias Bjorling <m@bjorling.me>
+ *
+ * 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.
+ *
+ * Implementation of a Round-robin page-based Hybrid FTL for Open-channel SSDs.
+ */
+
+#ifndef RRPC_H_
+#define RRPC_H_
+
+#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
+#include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/vmalloc.h>
+
+#include <linux/lightnvm.h>
+
+/* Run only GC if less than 1/X blocks are free */
+#define GC_LIMIT_INVERSE 10
+#define GC_TIME_SECS 100
+
+#define RRPC_SECTOR (512)
+#define RRPC_EXPOSED_PAGE_SIZE (4096)
+
+#define NR_PHY_IN_LOG (RRPC_EXPOSED_PAGE_SIZE / RRPC_SECTOR)
+
+struct rrpc_inflight {
+ struct list_head reqs;
+ spinlock_t lock;
+};
+
+struct rrpc_inflight_rq {
+ struct list_head list;
+ sector_t l_start;
+ sector_t l_end;
+};
+
+struct rrpc_rq {
+ struct rrpc_inflight_rq inflight_rq;
+ struct rrpc_addr *addr;
+ unsigned long flags;
+};
+
+struct rrpc_block {
+ struct nvm_block *parent;
+ struct list_head prio;
+
+#define MAX_INVALID_PAGES_STORAGE 8
+ /* Bitmap for invalid page intries */
+ unsigned long invalid_pages[MAX_INVALID_PAGES_STORAGE];
+ /* points to the next writable page within a block */
+ unsigned int next_page;
+ /* number of pages that are invalid, wrt host page size */
+ unsigned int nr_invalid_pages;
+
+ spinlock_t lock;
+ atomic_t data_cmnt_size; /* data pages committed to stable storage */
+};
+
+struct rrpc_lun {
+ struct rrpc *rrpc;
+ struct nvm_lun *parent;
+ struct rrpc_block *cur, *gc_cur;
+ struct rrpc_block *blocks; /* Reference to block allocation */
+ struct list_head prio_list; /* Blocks that may be GC'ed */
+ struct work_struct ws_gc;
+
+ spinlock_t lock;
+};
+
+struct rrpc {
+ /* instance must be kept in top to resolve rrpc in unprep */
+ struct nvm_tgt_instance instance;
+
+ struct nvm_dev *dev;
+ struct gendisk *disk;
+
+ u64 poffset; /* physical page offset */
+ int lun_offset;
+
+ int nr_luns;
+ struct rrpc_lun *luns;
+
+ /* calculated values */
+ unsigned long long nr_pages;
+ unsigned long total_blocks;
+
+ /* Write strategy variables. Move these into each for structure for each
+ * strategy
+ */
+ atomic_t next_lun; /* Whenever a page is written, this is updated
+ * to point to the next write lun
+ */
+
+ spinlock_t bio_lock;
+ struct bio_list requeue_bios;
+ struct work_struct ws_requeue;
+
+ /* Simple translation map of logical addresses to physical addresses.
+ * The logical addresses is known by the host system, while the physical
+ * addresses are used when writing to the disk block device.
+ */
+ struct rrpc_addr *trans_map;
+ /* also store a reverse map for garbage collection */
+ struct rrpc_rev_addr *rev_trans_map;
+ spinlock_t rev_lock;
+
+ struct rrpc_inflight inflights;
+
+ mempool_t *addr_pool;
+ mempool_t *page_pool;
+ mempool_t *gcb_pool;
+ mempool_t *rq_pool;
+
+ struct timer_list gc_timer;
+ struct workqueue_struct *krqd_wq;
+ struct workqueue_struct *kgc_wq;
+};
+
+struct rrpc_block_gc {
+ struct rrpc *rrpc;
+ struct rrpc_block *rblk;
+ struct work_struct ws_gc;
+};
+
+/* Logical to physical mapping */
+struct rrpc_addr {
+ u64 addr;
+ struct rrpc_block *rblk;
+};
+
+/* Physical to logical mapping */
+struct rrpc_rev_addr {
+ u64 addr;
+};
+
+static inline sector_t rrpc_get_laddr(struct bio *bio)
+{
+ return bio->bi_iter.bi_sector / NR_PHY_IN_LOG;
+}
+
+static inline unsigned int rrpc_get_pages(struct bio *bio)
+{
+ return bio->bi_iter.bi_size / RRPC_EXPOSED_PAGE_SIZE;
+}
+
+static inline sector_t rrpc_get_sector(sector_t laddr)
+{
+ return laddr * NR_PHY_IN_LOG;
+}
+
+static inline int request_intersects(struct rrpc_inflight_rq *r,
+ sector_t laddr_start, sector_t laddr_end)
+{
+ return (laddr_end >= r->l_start && laddr_end <= r->l_end) &&
+ (laddr_start >= r->l_start && laddr_start <= r->l_end);
+}
+
+static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr,
+ unsigned pages, struct rrpc_inflight_rq *r)
+{
+ sector_t laddr_end = laddr + pages - 1;
+ struct rrpc_inflight_rq *rtmp;
+
+ spin_lock_irq(&rrpc->inflights.lock);
+ list_for_each_entry(rtmp, &rrpc->inflights.reqs, list) {
+ if (unlikely(request_intersects(rtmp, laddr, laddr_end))) {
+ /* existing, overlapping request, come back later */
+ spin_unlock_irq(&rrpc->inflights.lock);
+ return 1;
+ }
+ }
+
+ r->l_start = laddr;
+ r->l_end = laddr_end;
+
+ list_add_tail(&r->list, &rrpc->inflights.reqs);
+ spin_unlock_irq(&rrpc->inflights.lock);
+ return 0;
+}
+
+static inline int rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr,
+ unsigned pages,
+ struct rrpc_inflight_rq *r)
+{
+ BUG_ON((laddr + pages) > rrpc->nr_pages);
+
+ return __rrpc_lock_laddr(rrpc, laddr, pages, r);
+}
+
+static inline struct rrpc_inflight_rq *rrpc_get_inflight_rq(struct nvm_rq *rqd)
+{
+ struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
+
+ return &rrqd->inflight_rq;
+}
+
+static inline int rrpc_lock_rq(struct rrpc *rrpc, struct bio *bio,
+ struct nvm_rq *rqd)
+{
+ sector_t laddr = rrpc_get_laddr(bio);
+ unsigned int pages = rrpc_get_pages(bio);
+ struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
+
+ return rrpc_lock_laddr(rrpc, laddr, pages, r);
+}
+
+static inline void rrpc_unlock_laddr(struct rrpc *rrpc,
+ struct rrpc_inflight_rq *r)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rrpc->inflights.lock, flags);
+ list_del_init(&r->list);
+ spin_unlock_irqrestore(&rrpc->inflights.lock, flags);
+}
+
+static inline void rrpc_unlock_rq(struct rrpc *rrpc, struct nvm_rq *rqd)
+{
+ struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
+ uint8_t pages = rqd->nr_pages;
+
+ BUG_ON((r->l_start + pages) > rrpc->nr_pages);
+
+ rrpc_unlock_laddr(rrpc, r);
+}
+
+#endif /* RRPC_H_ */
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 5844b80bd90e..3e8b29e41420 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -166,9 +166,8 @@ config INPUT_ADBHID
Say Y here if you want to have ADB (Apple Desktop Bus) HID devices
such as keyboards, mice, joysticks, trackpads or graphic tablets
handled by the input layer. If you say Y here, make sure to say Y to
- the corresponding drivers "Keyboard support" (CONFIG_INPUT_KEYBDEV),
- "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and "Event interface
- support" (CONFIG_INPUT_EVDEV) as well.
+ the corresponding drivers "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and
+ "Event interface support" (CONFIG_INPUT_EVDEV) as well.
If unsure, say Y.
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index bbec5009cdc2..546d05f4358a 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -71,4 +71,18 @@ config BCM2835_MBOX
the services of the Videocore. Say Y here if you want to use the
BCM2835 Mailbox.
+config STI_MBOX
+ tristate "STI Mailbox framework support"
+ depends on ARCH_STI && OF
+ help
+ Mailbox implementation for STMicroelectonics family chips with
+ hardware for interprocessor communication.
+
+config MAILBOX_TEST
+ tristate "Mailbox Test Client"
+ depends on OF
+ help
+ Test client to help with testing new Controller driver
+ implementations.
+
endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 8e6d82218a09..92435ef11f26 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -2,6 +2,8 @@
obj-$(CONFIG_MAILBOX) += mailbox.o
+obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o
+
obj-$(CONFIG_ARM_MHU) += arm_mhu.o
obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
@@ -13,3 +15,5 @@ obj-$(CONFIG_PCC) += pcc.o
obj-$(CONFIG_ALTERA_MBOX) += mailbox-altera.o
obj-$(CONFIG_BCM2835_MBOX) += bcm2835-mailbox.o
+
+obj-$(CONFIG_STI_MBOX) += mailbox-sti.o
diff --git a/drivers/mailbox/mailbox-sti.c b/drivers/mailbox/mailbox-sti.c
new file mode 100644
index 000000000000..4835817c5365
--- /dev/null
+++ b/drivers/mailbox/mailbox-sti.c
@@ -0,0 +1,513 @@
+/*
+ * STi Mailbox
+ *
+ * Copyright (C) 2015 ST Microelectronics
+ *
+ * Author: Lee Jones <lee.jones@linaro.org> for ST Microelectronics
+ *
+ * Based on the original driver written by;
+ * Alexandre Torgue, Olivier Lebreton and Loic Pallardy
+ *
+ * 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/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "mailbox.h"
+
+#define STI_MBOX_INST_MAX 4 /* RAM saving: Max supported instances */
+#define STI_MBOX_CHAN_MAX 20 /* RAM saving: Max supported channels */
+
+#define STI_IRQ_VAL_OFFSET 0x04 /* Read interrupt status */
+#define STI_IRQ_SET_OFFSET 0x24 /* Generate a Tx channel interrupt */
+#define STI_IRQ_CLR_OFFSET 0x44 /* Clear pending Rx interrupts */
+#define STI_ENA_VAL_OFFSET 0x64 /* Read enable status */
+#define STI_ENA_SET_OFFSET 0x84 /* Enable a channel */
+#define STI_ENA_CLR_OFFSET 0xa4 /* Disable a channel */
+
+#define MBOX_BASE(mdev, inst) ((mdev)->base + ((inst) * 4))
+
+/**
+ * STi Mailbox device data
+ *
+ * An IP Mailbox is currently composed of 4 instances
+ * Each instance is currently composed of 32 channels
+ * This means that we have 128 channels per Mailbox
+ * A channel an be used for TX or RX
+ *
+ * @dev: Device to which it is attached
+ * @mbox: Representation of a communication channel controller
+ * @base: Base address of the register mapping region
+ * @name: Name of the mailbox
+ * @enabled: Local copy of enabled channels
+ * @lock: Mutex protecting enabled status
+ */
+struct sti_mbox_device {
+ struct device *dev;
+ struct mbox_controller *mbox;
+ void __iomem *base;
+ const char *name;
+ u32 enabled[STI_MBOX_INST_MAX];
+ spinlock_t lock;
+};
+
+/**
+ * STi Mailbox platform specific configuration
+ *
+ * @num_inst: Maximum number of instances in one HW Mailbox
+ * @num_chan: Maximum number of channel per instance
+ */
+struct sti_mbox_pdata {
+ unsigned int num_inst;
+ unsigned int num_chan;
+};
+
+/**
+ * STi Mailbox allocated channel information
+ *
+ * @mdev: Pointer to parent Mailbox device
+ * @instance: Instance number channel resides in
+ * @channel: Channel number pertaining to this container
+ */
+struct sti_channel {
+ struct sti_mbox_device *mdev;
+ unsigned int instance;
+ unsigned int channel;
+};
+
+static inline bool sti_mbox_channel_is_enabled(struct mbox_chan *chan)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct sti_mbox_device *mdev = chan_info->mdev;
+ unsigned int instance = chan_info->instance;
+ unsigned int channel = chan_info->channel;
+
+ return mdev->enabled[instance] & BIT(channel);
+}
+
+static inline
+struct mbox_chan *sti_mbox_to_channel(struct mbox_controller *mbox,
+ unsigned int instance,
+ unsigned int channel)
+{
+ struct sti_channel *chan_info;
+ int i;
+
+ for (i = 0; i < mbox->num_chans; i++) {
+ chan_info = mbox->chans[i].con_priv;
+ if (chan_info &&
+ chan_info->instance == instance &&
+ chan_info->channel == channel)
+ return &mbox->chans[i];
+ }
+
+ dev_err(mbox->dev,
+ "Channel not registered: instance: %d channel: %d\n",
+ instance, channel);
+
+ return NULL;
+}
+
+static void sti_mbox_enable_channel(struct mbox_chan *chan)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct sti_mbox_device *mdev = chan_info->mdev;
+ unsigned int instance = chan_info->instance;
+ unsigned int channel = chan_info->channel;
+ unsigned long flags;
+ void __iomem *base = MBOX_BASE(mdev, instance);
+
+ spin_lock_irqsave(&mdev->lock, flags);
+ mdev->enabled[instance] |= BIT(channel);
+ writel_relaxed(BIT(channel), base + STI_ENA_SET_OFFSET);
+ spin_unlock_irqrestore(&mdev->lock, flags);
+}
+
+static void sti_mbox_disable_channel(struct mbox_chan *chan)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct sti_mbox_device *mdev = chan_info->mdev;
+ unsigned int instance = chan_info->instance;
+ unsigned int channel = chan_info->channel;
+ unsigned long flags;
+ void __iomem *base = MBOX_BASE(mdev, instance);
+
+ spin_lock_irqsave(&mdev->lock, flags);
+ mdev->enabled[instance] &= ~BIT(channel);
+ writel_relaxed(BIT(channel), base + STI_ENA_CLR_OFFSET);
+ spin_unlock_irqrestore(&mdev->lock, flags);
+}
+
+static void sti_mbox_clear_irq(struct mbox_chan *chan)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct sti_mbox_device *mdev = chan_info->mdev;
+ unsigned int instance = chan_info->instance;
+ unsigned int channel = chan_info->channel;
+ void __iomem *base = MBOX_BASE(mdev, instance);
+
+ writel_relaxed(BIT(channel), base + STI_IRQ_CLR_OFFSET);
+}
+
+static struct mbox_chan *sti_mbox_irq_to_channel(struct sti_mbox_device *mdev,
+ unsigned int instance)
+{
+ struct mbox_controller *mbox = mdev->mbox;
+ struct mbox_chan *chan = NULL;
+ unsigned int channel;
+ unsigned long bits;
+ void __iomem *base = MBOX_BASE(mdev, instance);
+
+ bits = readl_relaxed(base + STI_IRQ_VAL_OFFSET);
+ if (!bits)
+ /* No IRQs fired in specified instance */
+ return NULL;
+
+ /* An IRQ has fired, find the associated channel */
+ for (channel = 0; bits; channel++) {
+ if (!test_and_clear_bit(channel, &bits))
+ continue;
+
+ chan = sti_mbox_to_channel(mbox, instance, channel);
+ if (chan) {
+ dev_dbg(mbox->dev,
+ "IRQ fired on instance: %d channel: %d\n",
+ instance, channel);
+ break;
+ }
+ }
+
+ return chan;
+}
+
+static irqreturn_t sti_mbox_thread_handler(int irq, void *data)
+{
+ struct sti_mbox_device *mdev = data;
+ struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
+ struct mbox_chan *chan;
+ unsigned int instance;
+
+ for (instance = 0; instance < pdata->num_inst; instance++) {
+keep_looking:
+ chan = sti_mbox_irq_to_channel(mdev, instance);
+ if (!chan)
+ continue;
+
+ mbox_chan_received_data(chan, NULL);
+ sti_mbox_clear_irq(chan);
+ sti_mbox_enable_channel(chan);
+ goto keep_looking;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sti_mbox_irq_handler(int irq, void *data)
+{
+ struct sti_mbox_device *mdev = data;
+ struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
+ struct sti_channel *chan_info;
+ struct mbox_chan *chan;
+ unsigned int instance;
+ int ret = IRQ_NONE;
+
+ for (instance = 0; instance < pdata->num_inst; instance++) {
+ chan = sti_mbox_irq_to_channel(mdev, instance);
+ if (!chan)
+ continue;
+ chan_info = chan->con_priv;
+
+ if (!sti_mbox_channel_is_enabled(chan)) {
+ dev_warn(mdev->dev,
+ "Unexpected IRQ: %s\n"
+ " instance: %d: channel: %d [enabled: %x]\n",
+ mdev->name, chan_info->instance,
+ chan_info->channel, mdev->enabled[instance]);
+
+ /* Only handle IRQ if no other valid IRQs were found */
+ if (ret == IRQ_NONE)
+ ret = IRQ_HANDLED;
+ continue;
+ }
+
+ sti_mbox_disable_channel(chan);
+ ret = IRQ_WAKE_THREAD;
+ }
+
+ if (ret == IRQ_NONE)
+ dev_err(mdev->dev, "Spurious IRQ - was a channel requested?\n");
+
+ return ret;
+}
+
+static bool sti_mbox_tx_is_ready(struct mbox_chan *chan)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct sti_mbox_device *mdev = chan_info->mdev;
+ unsigned int instance = chan_info->instance;
+ unsigned int channel = chan_info->channel;
+ void __iomem *base = MBOX_BASE(mdev, instance);
+
+ if (!(readl_relaxed(base + STI_ENA_VAL_OFFSET) & BIT(channel))) {
+ dev_dbg(mdev->dev, "Mbox: %s: inst: %d, chan: %d disabled\n",
+ mdev->name, instance, channel);
+ return false;
+ }
+
+ if (readl_relaxed(base + STI_IRQ_VAL_OFFSET) & BIT(channel)) {
+ dev_dbg(mdev->dev, "Mbox: %s: inst: %d, chan: %d not ready\n",
+ mdev->name, instance, channel);
+ return false;
+ }
+
+ return true;
+}
+
+static int sti_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct sti_mbox_device *mdev = chan_info->mdev;
+ unsigned int instance = chan_info->instance;
+ unsigned int channel = chan_info->channel;
+ void __iomem *base = MBOX_BASE(mdev, instance);
+
+ /* Send event to co-processor */
+ writel_relaxed(BIT(channel), base + STI_IRQ_SET_OFFSET);
+
+ dev_dbg(mdev->dev,
+ "Sent via Mailbox %s: instance: %d channel: %d\n",
+ mdev->name, instance, channel);
+
+ return 0;
+}
+
+static int sti_mbox_startup_chan(struct mbox_chan *chan)
+{
+ sti_mbox_clear_irq(chan);
+ sti_mbox_enable_channel(chan);
+
+ return 0;
+}
+
+static void sti_mbox_shutdown_chan(struct mbox_chan *chan)
+{
+ struct sti_channel *chan_info = chan->con_priv;
+ struct mbox_controller *mbox = chan_info->mdev->mbox;
+ int i;
+
+ for (i = 0; i < mbox->num_chans; i++)
+ if (chan == &mbox->chans[i])
+ break;
+
+ if (mbox->num_chans == i) {
+ dev_warn(mbox->dev, "Request to free non-existent channel\n");
+ return;
+ }
+
+ /* Reset channel */
+ sti_mbox_disable_channel(chan);
+ sti_mbox_clear_irq(chan);
+ chan->con_priv = NULL;
+}
+
+static struct mbox_chan *sti_mbox_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *spec)
+{
+ struct sti_mbox_device *mdev = dev_get_drvdata(mbox->dev);
+ struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
+ struct sti_channel *chan_info;
+ struct mbox_chan *chan = NULL;
+ unsigned int instance = spec->args[0];
+ unsigned int channel = spec->args[1];
+ int i;
+
+ /* Bounds checking */
+ if (instance >= pdata->num_inst || channel >= pdata->num_chan) {
+ dev_err(mbox->dev,
+ "Invalid channel requested instance: %d channel: %d\n",
+ instance, channel);
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (i = 0; i < mbox->num_chans; i++) {
+ chan_info = mbox->chans[i].con_priv;
+
+ /* Is requested channel free? */
+ if (chan_info &&
+ mbox->dev == chan_info->mdev->dev &&
+ instance == chan_info->instance &&
+ channel == chan_info->channel) {
+
+ dev_err(mbox->dev, "Channel in use\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ /*
+ * Find the first free slot, then continue checking
+ * to see if requested channel is in use
+ */
+ if (!chan && !chan_info)
+ chan = &mbox->chans[i];
+ }
+
+ if (!chan) {
+ dev_err(mbox->dev, "No free channels left\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ chan_info = devm_kzalloc(mbox->dev, sizeof(*chan_info), GFP_KERNEL);
+ if (!chan_info)
+ return ERR_PTR(-ENOMEM);
+
+ chan_info->mdev = mdev;
+ chan_info->instance = instance;
+ chan_info->channel = channel;
+
+ chan->con_priv = chan_info;
+
+ dev_info(mbox->dev,
+ "Mbox: %s: Created channel: instance: %d channel: %d\n",
+ mdev->name, instance, channel);
+
+ return chan;
+}
+
+static struct mbox_chan_ops sti_mbox_ops = {
+ .startup = sti_mbox_startup_chan,
+ .shutdown = sti_mbox_shutdown_chan,
+ .send_data = sti_mbox_send_data,
+ .last_tx_done = sti_mbox_tx_is_ready,
+};
+
+static const struct sti_mbox_pdata mbox_stih407_pdata = {
+ .num_inst = 4,
+ .num_chan = 32,
+};
+
+static const struct of_device_id sti_mailbox_match[] = {
+ {
+ .compatible = "st,stih407-mailbox",
+ .data = (void *)&mbox_stih407_pdata
+ },
+ { }
+};
+
+static int sti_mbox_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct mbox_controller *mbox;
+ struct sti_mbox_device *mdev;
+ struct device_node *np = pdev->dev.of_node;
+ struct mbox_chan *chans;
+ struct resource *res;
+ int irq;
+ int ret;
+
+ match = of_match_device(sti_mailbox_match, &pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "No configuration found\n");
+ return -ENODEV;
+ }
+ pdev->dev.platform_data = (struct sti_mbox_pdata *) match->data;
+
+ mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mdev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mdev->base = devm_ioremap_resource(&pdev->dev, res);
+ if (!mdev->base)
+ return -ENOMEM;
+
+ ret = of_property_read_string(np, "mbox-name", &mdev->name);
+ if (ret)
+ mdev->name = np->full_name;
+
+ mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
+ if (!mbox)
+ return -ENOMEM;
+
+ chans = devm_kzalloc(&pdev->dev,
+ sizeof(*chans) * STI_MBOX_CHAN_MAX, GFP_KERNEL);
+ if (!chans)
+ return -ENOMEM;
+
+ mdev->dev = &pdev->dev;
+ mdev->mbox = mbox;
+
+ spin_lock_init(&mdev->lock);
+
+ /* STi Mailbox does not have a Tx-Done or Tx-Ready IRQ */
+ mbox->txdone_irq = false;
+ mbox->txdone_poll = true;
+ mbox->txpoll_period = 100;
+ mbox->ops = &sti_mbox_ops;
+ mbox->dev = mdev->dev;
+ mbox->of_xlate = sti_mbox_xlate;
+ mbox->chans = chans;
+ mbox->num_chans = STI_MBOX_CHAN_MAX;
+
+ ret = mbox_controller_register(mbox);
+ if (ret)
+ return ret;
+
+ /* It's okay for Tx Mailboxes to not supply IRQs */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_info(&pdev->dev,
+ "%s: Registered Tx only Mailbox\n", mdev->name);
+ return 0;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq,
+ sti_mbox_irq_handler,
+ sti_mbox_thread_handler,
+ IRQF_ONESHOT, mdev->name, mdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't claim IRQ %d\n", irq);
+ mbox_controller_unregister(mbox);
+ return -EINVAL;
+ }
+
+ dev_info(&pdev->dev, "%s: Registered Tx/Rx Mailbox\n", mdev->name);
+
+ return 0;
+}
+
+static int sti_mbox_remove(struct platform_device *pdev)
+{
+ struct sti_mbox_device *mdev = platform_get_drvdata(pdev);
+
+ mbox_controller_unregister(mdev->mbox);
+
+ return 0;
+}
+
+static struct platform_driver sti_mbox_driver = {
+ .probe = sti_mbox_probe,
+ .remove = sti_mbox_remove,
+ .driver = {
+ .name = "sti-mailbox",
+ .of_match_table = sti_mailbox_match,
+ },
+};
+module_platform_driver(sti_mbox_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("STMicroelectronics Mailbox Controller");
+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
+MODULE_ALIAS("platform:mailbox-sti");
diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c
new file mode 100644
index 000000000000..684ae17dcf39
--- /dev/null
+++ b/drivers/mailbox/mailbox-test.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2015 ST Microelectronics
+ *
+ * Author: Lee Jones <lee.jones@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#define MBOX_MAX_SIG_LEN 8
+#define MBOX_MAX_MSG_LEN 128
+#define MBOX_BYTES_PER_LINE 16
+#define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
+#define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * \
+ (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
+
+static struct dentry *root_debugfs_dir;
+
+struct mbox_test_device {
+ struct device *dev;
+ void __iomem *mmio;
+ struct mbox_chan *tx_channel;
+ struct mbox_chan *rx_channel;
+ char *rx_buffer;
+ char *signal;
+ char *message;
+ spinlock_t lock;
+};
+
+static ssize_t mbox_test_signal_write(struct file *filp,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+ int ret;
+
+ if (!tdev->tx_channel) {
+ dev_err(tdev->dev, "Channel cannot do Tx\n");
+ return -EINVAL;
+ }
+
+ if (count > MBOX_MAX_SIG_LEN) {
+ dev_err(tdev->dev,
+ "Signal length %zd greater than max allowed %d\n",
+ count, MBOX_MAX_SIG_LEN);
+ return -EINVAL;
+ }
+
+ tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL);
+ if (!tdev->signal)
+ return -ENOMEM;
+
+ ret = copy_from_user(tdev->signal, userbuf, count);
+ if (ret) {
+ kfree(tdev->signal);
+ return -EFAULT;
+ }
+
+ return ret < 0 ? ret : count;
+}
+
+static const struct file_operations mbox_test_signal_ops = {
+ .write = mbox_test_signal_write,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static ssize_t mbox_test_message_write(struct file *filp,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+ void *data;
+ int ret;
+
+ if (!tdev->tx_channel) {
+ dev_err(tdev->dev, "Channel cannot do Tx\n");
+ return -EINVAL;
+ }
+
+ if (count > MBOX_MAX_MSG_LEN) {
+ dev_err(tdev->dev,
+ "Message length %zd greater than max allowed %d\n",
+ count, MBOX_MAX_MSG_LEN);
+ return -EINVAL;
+ }
+
+ tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
+ if (!tdev->message)
+ return -ENOMEM;
+
+ ret = copy_from_user(tdev->message, userbuf, count);
+ if (ret) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ /*
+ * A separate signal is only of use if there is
+ * MMIO to subsequently pass the message through
+ */
+ if (tdev->mmio && tdev->signal) {
+ print_hex_dump(KERN_INFO, "Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS,
+ MBOX_BYTES_PER_LINE, 1, tdev->signal, MBOX_MAX_SIG_LEN, true);
+
+ data = tdev->signal;
+ } else
+ data = tdev->message;
+
+ print_hex_dump(KERN_INFO, "Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
+ MBOX_BYTES_PER_LINE, 1, tdev->message, MBOX_MAX_MSG_LEN, true);
+
+ ret = mbox_send_message(tdev->tx_channel, data);
+ if (ret < 0)
+ dev_err(tdev->dev, "Failed to send message via mailbox\n");
+
+out:
+ kfree(tdev->signal);
+ kfree(tdev->message);
+
+ return ret < 0 ? ret : count;
+}
+
+static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+ unsigned long flags;
+ char *touser, *ptr;
+ int l = 0;
+ int ret;
+
+ touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
+ if (!touser)
+ return -ENOMEM;
+
+ if (!tdev->rx_channel) {
+ ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
+ ret = simple_read_from_buffer(userbuf, count, ppos,
+ touser, ret);
+ goto out;
+ }
+
+ if (tdev->rx_buffer[0] == '\0') {
+ ret = snprintf(touser, 9, "<EMPTY>\n");
+ ret = simple_read_from_buffer(userbuf, count, ppos,
+ touser, ret);
+ goto out;
+ }
+
+ spin_lock_irqsave(&tdev->lock, flags);
+
+ ptr = tdev->rx_buffer;
+ while (l < MBOX_HEXDUMP_MAX_LEN) {
+ hex_dump_to_buffer(ptr,
+ MBOX_BYTES_PER_LINE,
+ MBOX_BYTES_PER_LINE, 1, touser + l,
+ MBOX_HEXDUMP_LINE_LEN, true);
+
+ ptr += MBOX_BYTES_PER_LINE;
+ l += MBOX_HEXDUMP_LINE_LEN;
+ *(touser + (l - 1)) = '\n';
+ }
+ *(touser + l) = '\0';
+
+ memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN);
+
+ spin_unlock_irqrestore(&tdev->lock, flags);
+
+ ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN);
+out:
+ kfree(touser);
+ return ret;
+}
+
+static const struct file_operations mbox_test_message_ops = {
+ .write = mbox_test_message_write,
+ .read = mbox_test_message_read,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static int mbox_test_add_debugfs(struct platform_device *pdev,
+ struct mbox_test_device *tdev)
+{
+ if (!debugfs_initialized())
+ return 0;
+
+ root_debugfs_dir = debugfs_create_dir("mailbox", NULL);
+ if (!root_debugfs_dir) {
+ dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
+ return -EINVAL;
+ }
+
+ debugfs_create_file("message", 0600, root_debugfs_dir,
+ tdev, &mbox_test_message_ops);
+
+ debugfs_create_file("signal", 0200, root_debugfs_dir,
+ tdev, &mbox_test_signal_ops);
+
+ return 0;
+}
+
+static void mbox_test_receive_message(struct mbox_client *client, void *message)
+{
+ struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tdev->lock, flags);
+ if (tdev->mmio) {
+ memcpy_fromio(tdev->rx_buffer, tdev->mmio, MBOX_MAX_MSG_LEN);
+ print_hex_dump(KERN_INFO, "Client: Received [MMIO]: ",
+ DUMP_PREFIX_ADDRESS, MBOX_BYTES_PER_LINE, 1,
+ tdev->rx_buffer, MBOX_MAX_MSG_LEN, true);
+ } else if (message) {
+ print_hex_dump(KERN_INFO, "Client: Received [API]: ",
+ DUMP_PREFIX_ADDRESS, MBOX_BYTES_PER_LINE, 1,
+ message, MBOX_MAX_MSG_LEN, true);
+ memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
+ }
+ spin_unlock_irqrestore(&tdev->lock, flags);
+}
+
+static void mbox_test_prepare_message(struct mbox_client *client, void *message)
+{
+ struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
+
+ if (tdev->mmio) {
+ if (tdev->signal)
+ memcpy_toio(tdev->mmio, tdev->message, MBOX_MAX_MSG_LEN);
+ else
+ memcpy_toio(tdev->mmio, message, MBOX_MAX_MSG_LEN);
+ }
+}
+
+static void mbox_test_message_sent(struct mbox_client *client,
+ void *message, int r)
+{
+ if (r)
+ dev_warn(client->dev,
+ "Client: Message could not be sent: %d\n", r);
+ else
+ dev_info(client->dev,
+ "Client: Message sent\n");
+}
+
+static struct mbox_chan *
+mbox_test_request_channel(struct platform_device *pdev, const char *name)
+{
+ struct mbox_client *client;
+ struct mbox_chan *channel;
+
+ client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return ERR_PTR(-ENOMEM);
+
+ client->dev = &pdev->dev;
+ client->rx_callback = mbox_test_receive_message;
+ client->tx_prepare = mbox_test_prepare_message;
+ client->tx_done = mbox_test_message_sent;
+ client->tx_block = true;
+ client->knows_txdone = false;
+ client->tx_tout = 500;
+
+ channel = mbox_request_channel_byname(client, name);
+ if (IS_ERR(channel)) {
+ dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
+ return NULL;
+ }
+
+ return channel;
+}
+
+static int mbox_test_probe(struct platform_device *pdev)
+{
+ struct mbox_test_device *tdev;
+ struct resource *res;
+ int ret;
+
+ tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
+ if (!tdev)
+ return -ENOMEM;
+
+ /* It's okay for MMIO to be NULL */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ tdev->mmio = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(tdev->mmio))
+ tdev->mmio = NULL;
+
+ tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
+ tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
+
+ if (!tdev->tx_channel && !tdev->rx_channel)
+ return -EPROBE_DEFER;
+
+ tdev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, tdev);
+
+ spin_lock_init(&tdev->lock);
+
+ if (tdev->rx_channel) {
+ tdev->rx_buffer = devm_kzalloc(&pdev->dev,
+ MBOX_MAX_MSG_LEN, GFP_KERNEL);
+ if (!tdev->rx_buffer)
+ return -ENOMEM;
+ }
+
+ ret = mbox_test_add_debugfs(pdev, tdev);
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev, "Successfully registered\n");
+
+ return 0;
+}
+
+static int mbox_test_remove(struct platform_device *pdev)
+{
+ struct mbox_test_device *tdev = platform_get_drvdata(pdev);
+
+ debugfs_remove_recursive(root_debugfs_dir);
+
+ if (tdev->tx_channel)
+ mbox_free_channel(tdev->tx_channel);
+ if (tdev->rx_channel)
+ mbox_free_channel(tdev->rx_channel);
+
+ return 0;
+}
+
+static const struct of_device_id mbox_test_match[] = {
+ { .compatible = "mailbox_test" },
+ {},
+};
+
+static struct platform_driver mbox_test_driver = {
+ .driver = {
+ .name = "mailbox_sti_test",
+ .of_match_table = mbox_test_match,
+ },
+ .probe = mbox_test_probe,
+ .remove = mbox_test_remove,
+};
+module_platform_driver(mbox_test_driver);
+
+MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index a3dbfd9c6479..b7f636f15cac 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -38,6 +38,8 @@
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h>
+#include "mailbox.h"
+
#define MAILBOX_REVISION 0x000
#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
@@ -106,6 +108,7 @@ struct omap_mbox_fifo_info {
int rx_irq;
const char *name;
+ bool send_no_irq;
};
struct omap_mbox {
@@ -119,6 +122,7 @@ struct omap_mbox {
u32 ctx[OMAP4_MBOX_NR_REGS];
u32 intr_type;
struct mbox_chan *chan;
+ bool send_no_irq;
};
/* global variables for the mailbox devices */
@@ -418,6 +422,9 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
goto fail_request_irq;
}
+ if (mbox->send_no_irq)
+ mbox->chan->txdone_method = TXDONE_BY_ACK;
+
_omap_mbox_enable_irq(mbox, IRQ_RX);
return 0;
@@ -586,13 +593,27 @@ static void omap_mbox_chan_shutdown(struct mbox_chan *chan)
mutex_unlock(&mdev->cfg_lock);
}
-static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
+static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data)
{
- struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
int ret = -EBUSY;
- if (!mbox)
- return -EINVAL;
+ if (!mbox_fifo_full(mbox)) {
+ _omap_mbox_enable_irq(mbox, IRQ_RX);
+ mbox_fifo_write(mbox, (mbox_msg_t)data);
+ ret = 0;
+ _omap_mbox_disable_irq(mbox, IRQ_RX);
+
+ /* we must read and ack the interrupt directly from here */
+ mbox_fifo_read(mbox);
+ ack_mbox_irq(mbox, IRQ_RX);
+ }
+
+ return ret;
+}
+
+static int omap_mbox_chan_send(struct omap_mbox *mbox, void *data)
+{
+ int ret = -EBUSY;
if (!mbox_fifo_full(mbox)) {
mbox_fifo_write(mbox, (mbox_msg_t)data);
@@ -604,6 +625,22 @@ static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
return ret;
}
+static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
+{
+ struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
+ int ret;
+
+ if (!mbox)
+ return -EINVAL;
+
+ if (mbox->send_no_irq)
+ ret = omap_mbox_chan_send_noirq(mbox, data);
+ else
+ ret = omap_mbox_chan_send(mbox, data);
+
+ return ret;
+}
+
static const struct mbox_chan_ops omap_mbox_chan_ops = {
.startup = omap_mbox_chan_startup,
.send_data = omap_mbox_chan_send_data,
@@ -732,6 +769,9 @@ static int omap_mbox_probe(struct platform_device *pdev)
finfo->rx_usr = tmp[2];
finfo->name = child->name;
+
+ if (of_find_property(child, "ti,mbox-send-noirq", NULL))
+ finfo->send_no_irq = true;
} else {
finfo->tx_id = info->tx_id;
finfo->rx_id = info->rx_id;
@@ -791,6 +831,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr);
fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr);
+ mbox->send_no_irq = finfo->send_no_irq;
mbox->intr_type = intr_type;
mbox->parent = mdev;
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 68885a82e704..45d85aea9955 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -122,7 +122,7 @@ struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
*/
chan = get_pcc_channel(subspace_id);
- if (!chan || chan->cl) {
+ if (IS_ERR(chan) || chan->cl) {
dev_err(dev, "Channel not found for idx: %d\n", subspace_id);
return ERR_PTR(-EBUSY);
}
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c
index 9018ab83517a..a4be451074e5 100644
--- a/drivers/mcb/mcb-core.c
+++ b/drivers/mcb/mcb-core.c
@@ -409,6 +409,7 @@ static int mcb_init(void)
static void mcb_exit(void)
{
+ ida_destroy(&mcb_ida);
bus_unregister(&mcb_bus_type);
}
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
index 051645498b53..67d5e7d08df6 100644
--- a/drivers/mcb/mcb-pci.c
+++ b/drivers/mcb/mcb-pci.c
@@ -51,6 +51,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
priv->mapbase = pci_resource_start(pdev, 0);
if (!priv->mapbase) {
dev_err(&pdev->dev, "No PCI resource\n");
+ ret = -ENODEV;
goto out_disable;
}
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 3e01e6fb3424..7913fdcfc849 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -123,6 +123,7 @@ config MD_RAID456
tristate "RAID-4/RAID-5/RAID-6 mode"
depends on BLK_DEV_MD
select RAID6_PQ
+ select LIBCRC32C
select ASYNC_MEMCPY
select ASYNC_XOR
select ASYNC_PQ
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 462f443a4f85..f34979cd141a 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -17,7 +17,7 @@ dm-cache-smq-y += dm-cache-policy-smq.o
dm-cache-cleaner-y += dm-cache-policy-cleaner.o
dm-era-y += dm-era-target.o
md-mod-y += md.o bitmap.o
-raid456-y += raid5.o
+raid456-y += raid5.o raid5-cache.o
# Note: link order is important. All raid personalities
# and must come before md.o, as they each initialise
diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c
index 7a228de95fd7..9eaf1d6e8302 100644
--- a/drivers/md/bcache/closure.c
+++ b/drivers/md/bcache/closure.c
@@ -167,8 +167,6 @@ EXPORT_SYMBOL(closure_debug_destroy);
static struct dentry *debug;
-#define work_data_bits(work) ((unsigned long *)(&(work)->data))
-
static int debug_seq_show(struct seq_file *f, void *data)
{
struct closure *cl;
@@ -182,7 +180,7 @@ static int debug_seq_show(struct seq_file *f, void *data)
r & CLOSURE_REMAINING_MASK);
seq_printf(f, "%s%s%s%s\n",
- test_bit(WORK_STRUCT_PENDING,
+ test_bit(WORK_STRUCT_PENDING_BIT,
work_data_bits(&cl->work)) ? "Q" : "",
r & CLOSURE_RUNNING ? "R" : "",
r & CLOSURE_STACK ? "S" : "",
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 8e9877b04637..25fa8445bb24 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -958,7 +958,8 @@ static void cached_dev_nodata(struct closure *cl)
/* Cached devices - read & write stuff */
-static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t cached_dev_make_request(struct request_queue *q,
+ struct bio *bio)
{
struct search *s;
struct bcache_device *d = bio->bi_bdev->bd_disk->private_data;
@@ -997,6 +998,8 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
else
generic_make_request(bio);
}
+
+ return BLK_QC_T_NONE;
}
static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode,
@@ -1070,7 +1073,8 @@ static void flash_dev_nodata(struct closure *cl)
continue_at(cl, search_free, NULL);
}
-static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t flash_dev_make_request(struct request_queue *q,
+ struct bio *bio)
{
struct search *s;
struct closure *cl;
@@ -1093,7 +1097,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
continue_at_nobarrier(&s->cl,
flash_dev_nodata,
bcache_wq);
- return;
+ return BLK_QC_T_NONE;
} else if (rw) {
bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys,
&KEY(d->id, bio->bi_iter.bi_sector, 0),
@@ -1109,6 +1113,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
}
continue_at(cl, search_free, NULL);
+ return BLK_QC_T_NONE;
}
static int flash_dev_ioctl(struct bcache_device *d, fmode_t mode,
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 48b5890c28e3..4f22e919787a 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -613,12 +613,10 @@ re_read:
daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
write_behind = le32_to_cpu(sb->write_behind);
sectors_reserved = le32_to_cpu(sb->sectors_reserved);
- /* XXX: This is a hack to ensure that we don't use clustering
- * in case:
- * - dm-raid is in use and
- * - the nodes written in bitmap_sb is erroneous.
+ /* Setup nodes/clustername only if bitmap version is
+ * cluster-compatible
*/
- if (!bitmap->mddev->sync_super) {
+ if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) {
nodes = le32_to_cpu(sb->nodes);
strlcpy(bitmap->mddev->bitmap_info.cluster_name,
sb->cluster_name, 64);
@@ -628,7 +626,7 @@ re_read:
if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
reason = "bad magic";
else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
- le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
+ le32_to_cpu(sb->version) > BITMAP_MAJOR_CLUSTERED)
reason = "unrecognized superblock version";
else if (chunksize < 512)
reason = "bitmap chunksize too small";
@@ -1572,7 +1570,7 @@ void bitmap_close_sync(struct bitmap *bitmap)
}
EXPORT_SYMBOL(bitmap_close_sync);
-void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
+void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force)
{
sector_t s = 0;
sector_t blocks;
@@ -1583,7 +1581,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
bitmap->last_end_sync = jiffies;
return;
}
- if (time_before(jiffies, (bitmap->last_end_sync
+ if (!force && time_before(jiffies, (bitmap->last_end_sync
+ bitmap->mddev->bitmap_info.daemon_sleep)))
return;
wait_event(bitmap->mddev->recovery_wait,
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index f1f4dd01090d..7d5c3a610ca5 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -9,8 +9,10 @@
#define BITMAP_MAJOR_LO 3
/* version 4 insists the bitmap is in little-endian order
* with version 3, it is host-endian which is non-portable
+ * Version 5 is currently set only for clustered devices
*/
#define BITMAP_MAJOR_HI 4
+#define BITMAP_MAJOR_CLUSTERED 5
#define BITMAP_MAJOR_HOSTENDIAN 3
/*
@@ -255,7 +257,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int degraded);
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted);
void bitmap_close_sync(struct bitmap *bitmap);
-void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
+void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force);
void bitmap_unplug(struct bitmap *bitmap);
void bitmap_daemon_work(struct mddev *mddev);
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 83cc52eaf56d..2dd33085b331 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1598,11 +1598,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
c->bdev = bdev;
c->block_size = block_size;
- c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT;
- c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ?
- ffs(block_size) - 1 - PAGE_SHIFT : 0;
- c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ?
- PAGE_SHIFT - (ffs(block_size) - 1) : 0);
+ c->sectors_per_block_bits = __ffs(block_size) - SECTOR_SHIFT;
+ c->pages_per_block_bits = (__ffs(block_size) >= PAGE_SHIFT) ?
+ __ffs(block_size) - PAGE_SHIFT : 0;
+ c->blocks_per_page_bits = (__ffs(block_size) < PAGE_SHIFT ?
+ PAGE_SHIFT - __ffs(block_size) : 0);
c->aux_size = aux_size;
c->alloc_callback = alloc_callback;
@@ -1861,12 +1861,8 @@ static void __exit dm_bufio_exit(void)
cancel_delayed_work_sync(&dm_bufio_work);
destroy_workqueue(dm_bufio_wq);
- for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) {
- struct kmem_cache *kc = dm_bufio_caches[i];
-
- if (kc)
- kmem_cache_destroy(kc);
- }
+ for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++)
+ kmem_cache_destroy(dm_bufio_caches[i]);
for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++)
kfree(dm_bufio_cache_names[i]);
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 20cc36b01b77..f6543f3a970f 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -260,7 +260,9 @@ static int __superblock_all_zeroes(struct dm_block_manager *bm, bool *result)
}
}
- return dm_bm_unlock(b);
+ dm_bm_unlock(b);
+
+ return 0;
}
static void __setup_mapping_info(struct dm_cache_metadata *cmd)
@@ -465,7 +467,9 @@ static int __open_metadata(struct dm_cache_metadata *cmd)
dm_disk_bitset_init(cmd->tm, &cmd->discard_info);
sb_flags = le32_to_cpu(disk_super->flags);
cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags);
- return dm_bm_unlock(sblock);
+ dm_bm_unlock(sblock);
+
+ return 0;
bad:
dm_bm_unlock(sblock);
@@ -634,10 +638,10 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
disk_super = dm_block_data(sblock);
+ disk_super->flags = cpu_to_le32(cmd->flags);
if (mutator)
update_flags(disk_super, mutator);
- disk_super->flags = cpu_to_le32(cmd->flags);
disk_super->mapping_root = cpu_to_le64(cmd->root);
disk_super->hint_root = cpu_to_le64(cmd->hint_root);
disk_super->discard_root = cpu_to_le64(cmd->discard_root);
diff --git a/drivers/md/dm-cache-policy-cleaner.c b/drivers/md/dm-cache-policy-cleaner.c
index 8a096456579b..14aaaf059f06 100644
--- a/drivers/md/dm-cache-policy-cleaner.c
+++ b/drivers/md/dm-cache-policy-cleaner.c
@@ -83,7 +83,7 @@ static struct list_head *list_pop(struct list_head *q)
static int alloc_hash(struct hash *hash, unsigned elts)
{
hash->nr_buckets = next_power(elts >> 4, 16);
- hash->hash_bits = ffs(hash->nr_buckets) - 1;
+ hash->hash_bits = __ffs(hash->nr_buckets);
hash->table = vzalloc(sizeof(*hash->table) * hash->nr_buckets);
return hash->table ? 0 : -ENOMEM;
diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c
index aa1b41ca40f7..ddb26980cd66 100644
--- a/drivers/md/dm-cache-policy-mq.c
+++ b/drivers/md/dm-cache-policy-mq.c
@@ -1410,7 +1410,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
mq->generation_period = max((unsigned) from_cblock(cache_size), 1024U);
mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16);
- mq->hash_bits = ffs(mq->nr_buckets) - 1;
+ mq->hash_bits = __ffs(mq->nr_buckets);
mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets);
if (!mq->table)
goto bad_alloc_table;
diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
index 1ffbeb1b3ea6..28d4586748d0 100644
--- a/drivers/md/dm-cache-policy-smq.c
+++ b/drivers/md/dm-cache-policy-smq.c
@@ -566,7 +566,7 @@ static int h_init(struct hash_table *ht, struct entry_space *es, unsigned nr_ent
ht->es = es;
nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u));
- ht->hash_bits = ffs(nr_buckets) - 1;
+ ht->hash_bits = __ffs(nr_buckets);
ht->buckets = vmalloc(sizeof(*ht->buckets) * nr_buckets);
if (!ht->buckets)
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index dd90d1236f4a..2fd4c8296144 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -2309,8 +2309,7 @@ static void destroy(struct cache *cache)
{
unsigned i;
- if (cache->migration_pool)
- mempool_destroy(cache->migration_pool);
+ mempool_destroy(cache->migration_pool);
if (cache->all_io_ds)
dm_deferred_set_destroy(cache->all_io_ds);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 4b3b6f8aff0c..917d47e290ae 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -994,7 +994,7 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
struct bio_vec *bvec;
retry:
- if (unlikely(gfp_mask & __GFP_WAIT))
+ if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
mutex_lock(&cc->bio_alloc_lock);
clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
@@ -1010,7 +1010,7 @@ retry:
if (!page) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
- gfp_mask |= __GFP_WAIT;
+ gfp_mask |= __GFP_DIRECT_RECLAIM;
goto retry;
}
@@ -1027,7 +1027,7 @@ retry:
}
return_clone:
- if (unlikely(gfp_mask & __GFP_WAIT))
+ if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
mutex_unlock(&cc->bio_alloc_lock);
return clone;
@@ -1544,10 +1544,8 @@ static void crypt_dtr(struct dm_target *ti)
if (cc->bs)
bioset_free(cc->bs);
- if (cc->page_pool)
- mempool_destroy(cc->page_pool);
- if (cc->req_pool)
- mempool_destroy(cc->req_pool);
+ mempool_destroy(cc->page_pool);
+ mempool_destroy(cc->req_pool);
if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
cc->iv_gen_ops->dtr(cc);
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index b34f6e27293d..b4c356a21123 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -122,6 +122,7 @@ static void flush_expired_bios(struct work_struct *work)
* <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
*
* With separate write parameters, the first set is only used for reads.
+ * Offsets are specified in sectors.
* Delays are specified in milliseconds.
*/
static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
@@ -132,7 +133,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int ret;
if (argc != 3 && argc != 6) {
- ti->error = "requires exactly 3 or 6 arguments";
+ ti->error = "Requires exactly 3 or 6 arguments";
return -EINVAL;
}
@@ -237,7 +238,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
unsigned long expires = 0;
if (!delay || !atomic_read(&dc->may_delay))
- return 1;
+ return DM_MAPIO_REMAPPED;
delayed = dm_per_bio_data(bio, sizeof(struct dm_delay_info));
@@ -257,7 +258,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
queue_timeout(dc, expires);
- return 0;
+ return DM_MAPIO_SUBMITTED;
}
static void delay_presuspend(struct dm_target *ti)
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index 0119ebfb3d49..665bf3285618 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -343,7 +343,9 @@ static int superblock_all_zeroes(struct dm_block_manager *bm, bool *result)
}
}
- return dm_bm_unlock(b);
+ dm_bm_unlock(b);
+
+ return 0;
}
/*----------------------------------------------------------------*/
@@ -582,7 +584,9 @@ static int open_metadata(struct era_metadata *md)
md->metadata_snap = le64_to_cpu(disk->metadata_snap);
md->archived_writesets = true;
- return dm_bm_unlock(sblock);
+ dm_bm_unlock(sblock);
+
+ return 0;
bad:
dm_bm_unlock(sblock);
@@ -1046,12 +1050,7 @@ static int metadata_take_snap(struct era_metadata *md)
md->metadata_snap = dm_block_location(clone);
- r = dm_tm_unlock(md->tm, clone);
- if (r) {
- DMERR("%s: couldn't unlock clone", __func__);
- md->metadata_snap = SUPERBLOCK_LOCATION;
- return r;
- }
+ dm_tm_unlock(md->tm, clone);
return 0;
}
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 192bb8beeb6b..3997f34cfebc 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -183,7 +183,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
store->chunk_size = chunk_size;
store->chunk_mask = chunk_size - 1;
- store->chunk_shift = ffs(chunk_size) - 1;
+ store->chunk_shift = __ffs(chunk_size);
return 0;
}
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 645e8b4f808e..09e2afcafd2d 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -373,20 +373,20 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
}
}
-static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
+static int flakey_prepare_ioctl(struct dm_target *ti,
+ struct block_device **bdev, fmode_t *mode)
{
struct flakey_c *fc = ti->private;
- struct dm_dev *dev = fc->dev;
- int r = 0;
+
+ *bdev = fc->dev->bdev;
/*
* Only pass ioctls through if the device sizes match exactly.
*/
if (fc->start ||
- ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
- r = scsi_verify_blk_ioctl(NULL, cmd);
-
- return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+ ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+ return 1;
+ return 0;
}
static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
@@ -405,7 +405,7 @@ static struct target_type flakey_target = {
.map = flakey_map,
.end_io = flakey_end_io,
.status = flakey_status,
- .ioctl = flakey_ioctl,
+ .prepare_ioctl = flakey_prepare_ioctl,
.iterate_devices = flakey_iterate_devices,
};
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 6f8e83b2a6f8..81c5e1a1f363 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -65,8 +65,7 @@ struct dm_io_client *dm_io_client_create(void)
return client;
bad:
- if (client->pool)
- mempool_destroy(client->pool);
+ mempool_destroy(client->pool);
kfree(client);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 3a7cade5e27d..1452ed9aacb4 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -244,7 +244,7 @@ static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
*pages = NULL;
do {
- pl = alloc_pl(__GFP_NOWARN | __GFP_NORETRY);
+ pl = alloc_pl(__GFP_NOWARN | __GFP_NORETRY | __GFP_KSWAPD_RECLAIM);
if (unlikely(!pl)) {
/* Use reserved pages */
pl = kc->pages;
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 436f5c9b6aea..05c35aacb3aa 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -39,20 +39,20 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
lc = kmalloc(sizeof(*lc), GFP_KERNEL);
if (lc == NULL) {
- ti->error = "dm-linear: Cannot allocate linear context";
+ ti->error = "Cannot allocate linear context";
return -ENOMEM;
}
ret = -EINVAL;
if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
- ti->error = "dm-linear: Invalid device sector";
+ ti->error = "Invalid device sector";
goto bad;
}
lc->start = tmp;
ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
if (ret) {
- ti->error = "dm-linear: Device lookup failed";
+ ti->error = "Device lookup failed";
goto bad;
}
@@ -116,21 +116,21 @@ static void linear_status(struct dm_target *ti, status_type_t type,
}
}
-static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
- unsigned long arg)
+static int linear_prepare_ioctl(struct dm_target *ti,
+ struct block_device **bdev, fmode_t *mode)
{
struct linear_c *lc = (struct linear_c *) ti->private;
struct dm_dev *dev = lc->dev;
- int r = 0;
+
+ *bdev = dev->bdev;
/*
* Only pass ioctls through if the device sizes match exactly.
*/
if (lc->start ||
ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
- r = scsi_verify_blk_ioctl(NULL, cmd);
-
- return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+ return 1;
+ return 0;
}
static int linear_iterate_devices(struct dm_target *ti,
@@ -149,7 +149,7 @@ static struct target_type linear_target = {
.dtr = linear_dtr,
.map = linear_map,
.status = linear_status,
- .ioctl = linear_ioctl,
+ .prepare_ioctl = linear_prepare_ioctl,
.iterate_devices = linear_iterate_devices,
};
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 058256d2eeea..53b7b06d0aa8 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -313,8 +313,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
out:
kfree(devices_rdata);
if (r) {
- if (lc->flush_entry_pool)
- mempool_destroy(lc->flush_entry_pool);
+ mempool_destroy(lc->flush_entry_pool);
kfree(lc);
kfree(ctr_str);
} else {
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index b2912dbac8bc..624589d51c2c 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -714,20 +714,19 @@ static void log_writes_status(struct dm_target *ti, status_type_t type,
}
}
-static int log_writes_ioctl(struct dm_target *ti, unsigned int cmd,
- unsigned long arg)
+static int log_writes_prepare_ioctl(struct dm_target *ti,
+ struct block_device **bdev, fmode_t *mode)
{
struct log_writes_c *lc = ti->private;
struct dm_dev *dev = lc->dev;
- int r = 0;
+ *bdev = dev->bdev;
/*
* Only pass ioctls through if the device sizes match exactly.
*/
if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
- r = scsi_verify_blk_ioctl(NULL, cmd);
-
- return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+ return 1;
+ return 0;
}
static int log_writes_iterate_devices(struct dm_target *ti,
@@ -782,7 +781,7 @@ static struct target_type log_writes_target = {
.map = log_writes_map,
.end_io = normal_end_io,
.status = log_writes_status,
- .ioctl = log_writes_ioctl,
+ .prepare_ioctl = log_writes_prepare_ioctl,
.message = log_writes_message,
.iterate_devices = log_writes_iterate_devices,
.io_hints = log_writes_io_hints,
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5a67671a3973..aaa6caa46a9f 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1533,18 +1533,14 @@ out:
return r;
}
-static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
- unsigned long arg)
+static int multipath_prepare_ioctl(struct dm_target *ti,
+ struct block_device **bdev, fmode_t *mode)
{
struct multipath *m = ti->private;
struct pgpath *pgpath;
- struct block_device *bdev;
- fmode_t mode;
unsigned long flags;
int r;
- bdev = NULL;
- mode = 0;
r = 0;
spin_lock_irqsave(&m->lock, flags);
@@ -1555,26 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
pgpath = m->current_pgpath;
if (pgpath) {
- bdev = pgpath->path.dev->bdev;
- mode = pgpath->path.dev->mode;
+ *bdev = pgpath->path.dev->bdev;
+ *mode = pgpath->path.dev->mode;
}
if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
r = -ENOTCONN;
- else if (!bdev)
+ else if (!*bdev)
r = -EIO;
spin_unlock_irqrestore(&m->lock, flags);
- /*
- * Only pass ioctls through if the device sizes match exactly.
- */
- if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) {
- int err = scsi_verify_blk_ioctl(NULL, cmd);
- if (err)
- r = err;
- }
-
if (r == -ENOTCONN && !fatal_signal_pending(current)) {
spin_lock_irqsave(&m->lock, flags);
if (!m->current_pg) {
@@ -1587,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
dm_table_run_md_queue_async(m->ti->table);
}
- return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (!r && ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+ return 1;
+ return r;
}
static int multipath_iterate_devices(struct dm_target *ti,
@@ -1690,7 +1682,7 @@ out:
*---------------------------------------------------------------*/
static struct target_type multipath_target = {
.name = "multipath",
- .version = {1, 9, 0},
+ .version = {1, 10, 0},
.module = THIS_MODULE,
.ctr = multipath_ctr,
.dtr = multipath_dtr,
@@ -1703,7 +1695,7 @@ static struct target_type multipath_target = {
.resume = multipath_resume,
.status = multipath_status,
.message = multipath_message,
- .ioctl = multipath_ioctl,
+ .prepare_ioctl = multipath_prepare_ioctl,
.iterate_devices = multipath_iterate_devices,
.busy = multipath_busy,
};
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index b929fd5f4984..74cb7b991d41 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -193,7 +193,7 @@ struct dm_region_hash *dm_region_hash_create(
rh->max_recovery = max_recovery;
rh->log = log;
rh->region_size = region_size;
- rh->region_shift = ffs(region_size) - 1;
+ rh->region_shift = __ffs(region_size);
rwlock_init(&rh->hash_lock);
rh->mask = nr_buckets - 1;
rh->nr_buckets = nr_buckets;
@@ -249,9 +249,7 @@ void dm_region_hash_destroy(struct dm_region_hash *rh)
if (rh->log)
dm_dirty_log_destroy(rh->log);
- if (rh->region_pool)
- mempool_destroy(rh->region_pool);
-
+ mempool_destroy(rh->region_pool);
vfree(rh->buckets);
kfree(rh);
}
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index aeacad9be51d..3164b8bce294 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -322,7 +322,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
bdev_logical_block_size(dm_snap_cow(ps->store->snap)->
bdev) >> 9);
ps->store->chunk_mask = ps->store->chunk_size - 1;
- ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1;
+ ps->store->chunk_shift = __ffs(ps->store->chunk_size);
chunk_size_supplied = 0;
}
@@ -847,6 +847,7 @@ static void persistent_drop_snapshot(struct dm_exception_store *store)
static int persistent_ctr(struct dm_exception_store *store, char *options)
{
struct pstore *ps;
+ int r;
/* allocate the pstore */
ps = kzalloc(sizeof(*ps), GFP_KERNEL);
@@ -868,9 +869,9 @@ static int persistent_ctr(struct dm_exception_store *store, char *options)
ps->metadata_wq = alloc_workqueue("ksnaphd", WQ_MEM_RECLAIM, 0);
if (!ps->metadata_wq) {
- kfree(ps);
DMERR("couldn't start header metadata update thread");
- return -ENOMEM;
+ r = -ENOMEM;
+ goto err_workqueue;
}
if (options) {
@@ -879,13 +880,21 @@ static int persistent_ctr(struct dm_exception_store *store, char *options)
store->userspace_supports_overflow = true;
else {
DMERR("Unsupported persistent store option: %s", options);
- return -EINVAL;
+ r = -EINVAL;
+ goto err_options;
}
}
store->context = ps;
return 0;
+
+err_options:
+ destroy_workqueue(ps->metadata_wq);
+err_workqueue:
+ kfree(ps);
+
+ return r;
}
static unsigned persistent_status(struct dm_exception_store *store,
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 50fca469cafd..871c18fe000d 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -99,11 +99,11 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
if (sector_div(nr_regions, sctx->region_size))
nr_regions++;
- sctx->nr_regions = nr_regions;
- if (sctx->nr_regions != nr_regions || sctx->nr_regions >= ULONG_MAX) {
+ if (nr_regions >= ULONG_MAX) {
ti->error = "Region table too large";
return -EINVAL;
}
+ sctx->nr_regions = nr_regions;
nr_slots = nr_regions;
if (sector_div(nr_slots, sctx->region_entries_per_slot))
@@ -511,27 +511,24 @@ static void switch_status(struct dm_target *ti, status_type_t type,
*
* Passthrough all ioctls to the path for sector 0
*/
-static int switch_ioctl(struct dm_target *ti, unsigned cmd,
- unsigned long arg)
+static int switch_prepare_ioctl(struct dm_target *ti,
+ struct block_device **bdev, fmode_t *mode)
{
struct switch_ctx *sctx = ti->private;
- struct block_device *bdev;
- fmode_t mode;
unsigned path_nr;
- int r = 0;
path_nr = switch_get_path_nr(sctx, 0);
- bdev = sctx->path_list[path_nr].dmdev->bdev;
- mode = sctx->path_list[path_nr].dmdev->mode;
+ *bdev = sctx->path_list[path_nr].dmdev->bdev;
+ *mode = sctx->path_list[path_nr].dmdev->mode;
/*
* Only pass ioctls through if the device sizes match exactly.
*/
- if (ti->len + sctx->path_list[path_nr].start != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
- r = scsi_verify_blk_ioctl(NULL, cmd);
-
- return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+ if (ti->len + sctx->path_list[path_nr].start !=
+ i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+ return 1;
+ return 0;
}
static int switch_iterate_devices(struct dm_target *ti,
@@ -560,7 +557,7 @@ static struct target_type switch_target = {
.map = switch_map,
.message = switch_message,
.status = switch_status,
- .ioctl = switch_ioctl,
+ .prepare_ioctl = switch_prepare_ioctl,
.iterate_devices = switch_iterate_devices,
};
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index e76ed003769e..061152a43730 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1014,15 +1014,16 @@ static int dm_table_build_index(struct dm_table *t)
return r;
}
+static bool integrity_profile_exists(struct gendisk *disk)
+{
+ return !!blk_get_integrity(disk);
+}
+
/*
* Get a disk whose integrity profile reflects the table's profile.
- * If %match_all is true, all devices' profiles must match.
- * If %match_all is false, all devices must at least have an
- * allocated integrity profile; but uninitialized is ok.
* Returns NULL if integrity support was inconsistent or unavailable.
*/
-static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
- bool match_all)
+static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t)
{
struct list_head *devices = dm_table_get_devices(t);
struct dm_dev_internal *dd = NULL;
@@ -1030,10 +1031,8 @@ static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
list_for_each_entry(dd, devices, list) {
template_disk = dd->dm_dev->bdev->bd_disk;
- if (!blk_get_integrity(template_disk))
+ if (!integrity_profile_exists(template_disk))
goto no_integrity;
- if (!match_all && !blk_integrity_is_initialized(template_disk))
- continue; /* skip uninitialized profiles */
else if (prev_disk &&
blk_integrity_compare(prev_disk, template_disk) < 0)
goto no_integrity;
@@ -1052,34 +1051,40 @@ no_integrity:
}
/*
- * Register the mapped device for blk_integrity support if
- * the underlying devices have an integrity profile. But all devices
- * may not have matching profiles (checking all devices isn't reliable
+ * Register the mapped device for blk_integrity support if the
+ * underlying devices have an integrity profile. But all devices may
+ * not have matching profiles (checking all devices isn't reliable
* during table load because this table may use other DM device(s) which
- * must be resumed before they will have an initialized integity profile).
- * Stacked DM devices force a 2 stage integrity profile validation:
- * 1 - during load, validate all initialized integrity profiles match
- * 2 - during resume, validate all integrity profiles match
+ * must be resumed before they will have an initialized integity
+ * profile). Consequently, stacked DM devices force a 2 stage integrity
+ * profile validation: First pass during table load, final pass during
+ * resume.
*/
-static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
+static int dm_table_register_integrity(struct dm_table *t)
{
+ struct mapped_device *md = t->md;
struct gendisk *template_disk = NULL;
- template_disk = dm_table_get_integrity_disk(t, false);
+ template_disk = dm_table_get_integrity_disk(t);
if (!template_disk)
return 0;
- if (!blk_integrity_is_initialized(dm_disk(md))) {
+ if (!integrity_profile_exists(dm_disk(md))) {
t->integrity_supported = 1;
- return blk_integrity_register(dm_disk(md), NULL);
+ /*
+ * Register integrity profile during table load; we can do
+ * this because the final profile must match during resume.
+ */
+ blk_integrity_register(dm_disk(md),
+ blk_get_integrity(template_disk));
+ return 0;
}
/*
- * If DM device already has an initalized integrity
+ * If DM device already has an initialized integrity
* profile the new profile should not conflict.
*/
- if (blk_integrity_is_initialized(template_disk) &&
- blk_integrity_compare(dm_disk(md), template_disk) < 0) {
+ if (blk_integrity_compare(dm_disk(md), template_disk) < 0) {
DMWARN("%s: conflict with existing integrity profile: "
"%s profile mismatch",
dm_device_name(t->md),
@@ -1087,7 +1092,7 @@ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device
return 1;
}
- /* Preserve existing initialized integrity profile */
+ /* Preserve existing integrity profile */
t->integrity_supported = 1;
return 0;
}
@@ -1112,7 +1117,7 @@ int dm_table_complete(struct dm_table *t)
return r;
}
- r = dm_table_prealloc_integrity(t, t->md);
+ r = dm_table_register_integrity(t);
if (r) {
DMERR("could not register integrity profile.");
return r;
@@ -1278,29 +1283,30 @@ combine_limits:
}
/*
- * Set the integrity profile for this device if all devices used have
- * matching profiles. We're quite deep in the resume path but still
- * don't know if all devices (particularly DM devices this device
- * may be stacked on) have matching profiles. Even if the profiles
- * don't match we have no way to fail (to resume) at this point.
+ * Verify that all devices have an integrity profile that matches the
+ * DM device's registered integrity profile. If the profiles don't
+ * match then unregister the DM device's integrity profile.
*/
-static void dm_table_set_integrity(struct dm_table *t)
+static void dm_table_verify_integrity(struct dm_table *t)
{
struct gendisk *template_disk = NULL;
- if (!blk_get_integrity(dm_disk(t->md)))
- return;
+ if (t->integrity_supported) {
+ /*
+ * Verify that the original integrity profile
+ * matches all the devices in this table.
+ */
+ template_disk = dm_table_get_integrity_disk(t);
+ if (template_disk &&
+ blk_integrity_compare(dm_disk(t->md), template_disk) >= 0)
+ return;
+ }
- template_disk = dm_table_get_integrity_disk(t, true);
- if (template_disk)
- blk_integrity_register(dm_disk(t->md),
- blk_get_integrity(template_disk));
- else if (blk_integrity_is_initialized(dm_disk(t->md)))
- DMWARN("%s: device no longer has a valid integrity profile",
- dm_device_name(t->md));
- else
+ if (integrity_profile_exists(dm_disk(t->md))) {
DMWARN("%s: unable to establish an integrity profile",
dm_device_name(t->md));
+ blk_integrity_unregister(dm_disk(t->md));
+ }
}
static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev,
@@ -1500,7 +1506,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
else
queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
- dm_table_set_integrity(t);
+ dm_table_verify_integrity(t);
/*
* Determine whether or not this queue's I/O timings contribute
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 6ba47cfb1443..1fa45695b68a 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -396,7 +396,9 @@ static int __superblock_all_zeroes(struct dm_block_manager *bm, int *result)
}
}
- return dm_bm_unlock(b);
+ dm_bm_unlock(b);
+
+ return 0;
}
static void __setup_btree_details(struct dm_pool_metadata *pmd)
@@ -650,7 +652,9 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
}
__setup_btree_details(pmd);
- return dm_bm_unlock(sblock);
+ dm_bm_unlock(sblock);
+
+ return 0;
bad_cleanup_data_sm:
dm_sm_destroy(pmd->data_sm);
@@ -1297,7 +1301,9 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd)
dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root));
dm_sm_dec_block(pmd->metadata_sm, held_root);
- return dm_tm_unlock(pmd->tm, copy);
+ dm_tm_unlock(pmd->tm, copy);
+
+ return 0;
}
int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd)
@@ -1327,7 +1333,9 @@ static int __get_metadata_snap(struct dm_pool_metadata *pmd,
disk_super = dm_block_data(sblock);
*result = le64_to_cpu(disk_super->held_root);
- return dm_bm_unlock(sblock);
+ dm_bm_unlock(sblock);
+
+ return 0;
}
int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd,
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 6fcbfb063366..3897b90bd462 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3201,7 +3201,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
metadata_low_callback,
pool);
if (r)
- goto out_free_pt;
+ goto out_flags_changed;
pt->callbacks.congested_fn = pool_is_congested;
dm_table_add_target_callbacks(ti->table, &pt->callbacks);
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index edc624bccf9a..ccf41886ebcf 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -631,18 +631,17 @@ static void verity_status(struct dm_target *ti, status_type_t type,
}
}
-static int verity_ioctl(struct dm_target *ti, unsigned cmd,
- unsigned long arg)
+static int verity_prepare_ioctl(struct dm_target *ti,
+ struct block_device **bdev, fmode_t *mode)
{
struct dm_verity *v = ti->private;
- int r = 0;
+
+ *bdev = v->data_dev->bdev;
if (v->data_start ||
ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
- r = scsi_verify_blk_ioctl(NULL, cmd);
-
- return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
- cmd, arg);
+ return 1;
+ return 0;
}
static int verity_iterate_devices(struct dm_target *ti,
@@ -965,7 +964,7 @@ static struct target_type verity_target = {
.dtr = verity_dtr,
.map = verity_map,
.status = verity_status,
- .ioctl = verity_ioctl,
+ .prepare_ioctl = verity_prepare_ioctl,
.iterate_devices = verity_iterate_devices,
.io_hints = verity_io_hints,
};
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 1b5c6047e4f1..6e15f3565892 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -24,6 +24,7 @@
#include <linux/ktime.h>
#include <linux/elevator.h> /* for rq_end_sector() */
#include <linux/blk-mq.h>
+#include <linux/pr.h>
#include <trace/events/block.h>
@@ -555,18 +556,16 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return dm_get_geometry(md, geo);
}
-static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
+static int dm_get_live_table_for_ioctl(struct mapped_device *md,
+ struct dm_target **tgt, struct block_device **bdev,
+ fmode_t *mode, int *srcu_idx)
{
- struct mapped_device *md = bdev->bd_disk->private_data;
- int srcu_idx;
struct dm_table *map;
- struct dm_target *tgt;
- int r = -ENOTTY;
+ int r;
retry:
- map = dm_get_live_table(md, &srcu_idx);
-
+ r = -ENOTTY;
+ map = dm_get_live_table(md, srcu_idx);
if (!map || !dm_table_get_size(map))
goto out;
@@ -574,8 +573,9 @@ retry:
if (dm_table_get_num_targets(map) != 1)
goto out;
- tgt = dm_table_get_target(map, 0);
- if (!tgt->type->ioctl)
+ *tgt = dm_table_get_target(map, 0);
+
+ if (!(*tgt)->type->prepare_ioctl)
goto out;
if (dm_suspended_md(md)) {
@@ -583,16 +583,46 @@ retry:
goto out;
}
- r = tgt->type->ioctl(tgt, cmd, arg);
+ r = (*tgt)->type->prepare_ioctl(*tgt, bdev, mode);
+ if (r < 0)
+ goto out;
-out:
- dm_put_live_table(md, srcu_idx);
+ return r;
+out:
+ dm_put_live_table(md, *srcu_idx);
if (r == -ENOTCONN) {
msleep(10);
goto retry;
}
+ return r;
+}
+
+static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ struct dm_target *tgt;
+ int srcu_idx, r;
+
+ r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ /*
+ * Target determined this ioctl is being issued against
+ * a logical partition of the parent bdev; so extra
+ * validation is needed.
+ */
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+ if (r)
+ goto out;
+ }
+
+ r = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+out:
+ dm_put_live_table(md, srcu_idx);
return r;
}
@@ -1725,7 +1755,7 @@ static void __split_and_process_bio(struct mapped_device *md,
* The request function that just remaps the bio built up by
* dm_merge_bvec.
*/
-static void dm_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
{
int rw = bio_data_dir(bio);
struct mapped_device *md = q->queuedata;
@@ -1734,8 +1764,6 @@ static void dm_make_request(struct request_queue *q, struct bio *bio)
map = dm_get_live_table(md, &srcu_idx);
- blk_queue_split(q, &bio, q->bio_split);
-
generic_start_io_acct(rw, bio_sectors(bio), &dm_disk(md)->part0);
/* if we're suspended, we have to queue this io for later */
@@ -1746,12 +1774,12 @@ static void dm_make_request(struct request_queue *q, struct bio *bio)
queue_io(md, bio);
else
bio_io_error(bio);
- return;
+ return BLK_QC_T_NONE;
}
__split_and_process_bio(md, map, bio);
dm_put_live_table(md, srcu_idx);
- return;
+ return BLK_QC_T_NONE;
}
int dm_request_based(struct mapped_device *md)
@@ -2198,6 +2226,13 @@ static void dm_init_md_queue(struct mapped_device *md)
* This queue is new, so no concurrency on the queue_flags.
*/
queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue);
+
+ /*
+ * Initialize data that will only be used by a non-blk-mq DM queue
+ * - must do so here (in alloc_dev callchain) before queue is used
+ */
+ md->queue->queuedata = md;
+ md->queue->backing_dev_info.congested_data = md;
}
static void dm_init_old_md_queue(struct mapped_device *md)
@@ -2208,10 +2243,7 @@ static void dm_init_old_md_queue(struct mapped_device *md)
/*
* Initialize aspects of queue that aren't relevant for blk-mq
*/
- md->queue->queuedata = md;
md->queue->backing_dev_info.congested_fn = dm_any_congested;
- md->queue->backing_dev_info.congested_data = md;
-
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
}
@@ -2221,10 +2253,8 @@ static void cleanup_mapped_device(struct mapped_device *md)
destroy_workqueue(md->wq);
if (md->kworker_task)
kthread_stop(md->kworker_task);
- if (md->io_pool)
- mempool_destroy(md->io_pool);
- if (md->rq_pool)
- mempool_destroy(md->rq_pool);
+ mempool_destroy(md->io_pool);
+ mempool_destroy(md->rq_pool);
if (md->bs)
bioset_free(md->bs);
@@ -2234,8 +2264,6 @@ static void cleanup_mapped_device(struct mapped_device *md)
spin_lock(&_minor_lock);
md->disk->private_data = NULL;
spin_unlock(&_minor_lock);
- if (blk_get_integrity(md->disk))
- blk_integrity_unregister(md->disk);
del_gendisk(md->disk);
put_disk(md->disk);
}
@@ -2761,6 +2789,12 @@ int dm_setup_md_queue(struct mapped_device *md)
case DM_TYPE_BIO_BASED:
dm_init_old_md_queue(md);
blk_queue_make_request(md->queue, dm_make_request);
+ /*
+ * DM handles splitting bios as needed. Free the bio_split bioset
+ * since it won't be used (saves 1 process per bio-based DM device).
+ */
+ bioset_free(md->queue->bio_split);
+ md->queue->bio_split = NULL;
break;
}
@@ -3507,11 +3541,8 @@ void dm_free_md_mempools(struct dm_md_mempools *pools)
if (!pools)
return;
- if (pools->io_pool)
- mempool_destroy(pools->io_pool);
-
- if (pools->rq_pool)
- mempool_destroy(pools->rq_pool);
+ mempool_destroy(pools->io_pool);
+ mempool_destroy(pools->rq_pool);
if (pools->bs)
bioset_free(pools->bs);
@@ -3519,11 +3550,133 @@ void dm_free_md_mempools(struct dm_md_mempools *pools)
kfree(pools);
}
+static int dm_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
+ u32 flags)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ const struct pr_ops *ops;
+ struct dm_target *tgt;
+ fmode_t mode;
+ int srcu_idx, r;
+
+ r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+ if (r < 0)
+ return r;
+
+ ops = bdev->bd_disk->fops->pr_ops;
+ if (ops && ops->pr_register)
+ r = ops->pr_register(bdev, old_key, new_key, flags);
+ else
+ r = -EOPNOTSUPP;
+
+ dm_put_live_table(md, srcu_idx);
+ return r;
+}
+
+static int dm_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
+ u32 flags)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ const struct pr_ops *ops;
+ struct dm_target *tgt;
+ fmode_t mode;
+ int srcu_idx, r;
+
+ r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+ if (r < 0)
+ return r;
+
+ ops = bdev->bd_disk->fops->pr_ops;
+ if (ops && ops->pr_reserve)
+ r = ops->pr_reserve(bdev, key, type, flags);
+ else
+ r = -EOPNOTSUPP;
+
+ dm_put_live_table(md, srcu_idx);
+ return r;
+}
+
+static int dm_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ const struct pr_ops *ops;
+ struct dm_target *tgt;
+ fmode_t mode;
+ int srcu_idx, r;
+
+ r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+ if (r < 0)
+ return r;
+
+ ops = bdev->bd_disk->fops->pr_ops;
+ if (ops && ops->pr_release)
+ r = ops->pr_release(bdev, key, type);
+ else
+ r = -EOPNOTSUPP;
+
+ dm_put_live_table(md, srcu_idx);
+ return r;
+}
+
+static int dm_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
+ enum pr_type type, bool abort)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ const struct pr_ops *ops;
+ struct dm_target *tgt;
+ fmode_t mode;
+ int srcu_idx, r;
+
+ r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+ if (r < 0)
+ return r;
+
+ ops = bdev->bd_disk->fops->pr_ops;
+ if (ops && ops->pr_preempt)
+ r = ops->pr_preempt(bdev, old_key, new_key, type, abort);
+ else
+ r = -EOPNOTSUPP;
+
+ dm_put_live_table(md, srcu_idx);
+ return r;
+}
+
+static int dm_pr_clear(struct block_device *bdev, u64 key)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ const struct pr_ops *ops;
+ struct dm_target *tgt;
+ fmode_t mode;
+ int srcu_idx, r;
+
+ r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+ if (r < 0)
+ return r;
+
+ ops = bdev->bd_disk->fops->pr_ops;
+ if (ops && ops->pr_clear)
+ r = ops->pr_clear(bdev, key);
+ else
+ r = -EOPNOTSUPP;
+
+ dm_put_live_table(md, srcu_idx);
+ return r;
+}
+
+static const struct pr_ops dm_pr_ops = {
+ .pr_register = dm_pr_register,
+ .pr_reserve = dm_pr_reserve,
+ .pr_release = dm_pr_release,
+ .pr_preempt = dm_pr_preempt,
+ .pr_clear = dm_pr_clear,
+};
+
static const struct block_device_operations dm_blk_dops = {
.open = dm_blk_open,
.release = dm_blk_close,
.ioctl = dm_blk_ioctl,
.getgeo = dm_blk_getgeo,
+ .pr_ops = &dm_pr_ops,
.owner = THIS_MODULE
};
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index 11e3bc9d2a4b..d6a1126d85ce 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -28,6 +28,7 @@ struct dlm_lock_resource {
struct completion completion; /* completion for synchronized locking */
void (*bast)(void *arg, int mode); /* blocking AST function pointer*/
struct mddev *mddev; /* pointing back to mddev. */
+ int mode;
};
struct suspend_info {
@@ -53,8 +54,8 @@ struct md_cluster_info {
dlm_lockspace_t *lockspace;
int slot_number;
struct completion completion;
- struct mutex sb_mutex;
struct dlm_lock_resource *bitmap_lockres;
+ struct dlm_lock_resource *resync_lockres;
struct list_head suspend_list;
spinlock_t suspend_lock;
struct md_thread *recovery_thread;
@@ -79,20 +80,20 @@ enum msg_type {
};
struct cluster_msg {
- int type;
- int slot;
+ __le32 type;
+ __le32 slot;
/* TODO: Unionize this for smaller footprint */
- sector_t low;
- sector_t high;
+ __le64 low;
+ __le64 high;
char uuid[16];
- int raid_slot;
+ __le32 raid_slot;
};
static void sync_ast(void *arg)
{
struct dlm_lock_resource *res;
- res = (struct dlm_lock_resource *) arg;
+ res = arg;
complete(&res->completion);
}
@@ -106,6 +107,8 @@ static int dlm_lock_sync(struct dlm_lock_resource *res, int mode)
if (ret)
return ret;
wait_for_completion(&res->completion);
+ if (res->lksb.sb_status == 0)
+ res->mode = mode;
return res->lksb.sb_status;
}
@@ -127,6 +130,7 @@ static struct dlm_lock_resource *lockres_init(struct mddev *mddev,
init_completion(&res->completion);
res->ls = cinfo->lockspace;
res->mddev = mddev;
+ res->mode = DLM_LOCK_IV;
namelen = strlen(name);
res->name = kzalloc(namelen + 1, GFP_KERNEL);
if (!res->name) {
@@ -191,8 +195,8 @@ retry:
kfree(res);
}
-static void add_resync_info(struct mddev *mddev, struct dlm_lock_resource *lockres,
- sector_t lo, sector_t hi)
+static void add_resync_info(struct dlm_lock_resource *lockres,
+ sector_t lo, sector_t hi)
{
struct resync_info *ri;
@@ -210,7 +214,7 @@ static struct suspend_info *read_resync_info(struct mddev *mddev, struct dlm_loc
dlm_lock_sync(lockres, DLM_LOCK_CR);
memcpy(&ri, lockres->lksb.sb_lvbptr, sizeof(struct resync_info));
hi = le64_to_cpu(ri.hi);
- if (ri.hi > 0) {
+ if (hi > 0) {
s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL);
if (!s)
goto out;
@@ -345,7 +349,7 @@ static const struct dlm_lockspace_ops md_ls_ops = {
*/
static void ack_bast(void *arg, int mode)
{
- struct dlm_lock_resource *res = (struct dlm_lock_resource *)arg;
+ struct dlm_lock_resource *res = arg;
struct md_cluster_info *cinfo = res->mddev->cluster_info;
if (mode == DLM_LOCK_EX)
@@ -358,29 +362,32 @@ static void __remove_suspend_info(struct md_cluster_info *cinfo, int slot)
list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list)
if (slot == s->slot) {
- pr_info("%s:%d Deleting suspend_info: %d\n",
- __func__, __LINE__, slot);
list_del(&s->list);
kfree(s);
break;
}
}
-static void remove_suspend_info(struct md_cluster_info *cinfo, int slot)
+static void remove_suspend_info(struct mddev *mddev, int slot)
{
+ struct md_cluster_info *cinfo = mddev->cluster_info;
spin_lock_irq(&cinfo->suspend_lock);
__remove_suspend_info(cinfo, slot);
spin_unlock_irq(&cinfo->suspend_lock);
+ mddev->pers->quiesce(mddev, 2);
}
-static void process_suspend_info(struct md_cluster_info *cinfo,
+static void process_suspend_info(struct mddev *mddev,
int slot, sector_t lo, sector_t hi)
{
+ struct md_cluster_info *cinfo = mddev->cluster_info;
struct suspend_info *s;
if (!hi) {
- remove_suspend_info(cinfo, slot);
+ remove_suspend_info(mddev, slot);
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_wakeup_thread(mddev->thread);
return;
}
s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL);
@@ -389,11 +396,14 @@ static void process_suspend_info(struct md_cluster_info *cinfo,
s->slot = slot;
s->lo = lo;
s->hi = hi;
+ mddev->pers->quiesce(mddev, 1);
+ mddev->pers->quiesce(mddev, 0);
spin_lock_irq(&cinfo->suspend_lock);
/* Remove existing entry (if exists) before adding */
__remove_suspend_info(cinfo, slot);
list_add(&s->list, &cinfo->suspend_list);
spin_unlock_irq(&cinfo->suspend_lock);
+ mddev->pers->quiesce(mddev, 2);
}
static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
@@ -407,7 +417,7 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
len = snprintf(disk_uuid, 64, "DEVICE_UUID=");
sprintf(disk_uuid + len, "%pU", cmsg->uuid);
- snprintf(raid_slot, 16, "RAID_DISK=%d", cmsg->raid_slot);
+ snprintf(raid_slot, 16, "RAID_DISK=%d", le32_to_cpu(cmsg->raid_slot));
pr_info("%s:%d Sending kobject change with %s and %s\n", __func__, __LINE__, disk_uuid, raid_slot);
init_completion(&cinfo->newdisk_completion);
set_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state);
@@ -421,64 +431,59 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
-
- md_reload_sb(mddev);
+ md_reload_sb(mddev, le32_to_cpu(msg->raid_slot));
dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
}
static void process_remove_disk(struct mddev *mddev, struct cluster_msg *msg)
{
- struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
+ struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev,
+ le32_to_cpu(msg->raid_slot));
if (rdev)
md_kick_rdev_from_array(rdev);
else
- pr_warn("%s: %d Could not find disk(%d) to REMOVE\n", __func__, __LINE__, msg->raid_slot);
+ pr_warn("%s: %d Could not find disk(%d) to REMOVE\n",
+ __func__, __LINE__, le32_to_cpu(msg->raid_slot));
}
static void process_readd_disk(struct mddev *mddev, struct cluster_msg *msg)
{
- struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
+ struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev,
+ le32_to_cpu(msg->raid_slot));
if (rdev && test_bit(Faulty, &rdev->flags))
clear_bit(Faulty, &rdev->flags);
else
- pr_warn("%s: %d Could not find disk(%d) which is faulty", __func__, __LINE__, msg->raid_slot);
+ pr_warn("%s: %d Could not find disk(%d) which is faulty",
+ __func__, __LINE__, le32_to_cpu(msg->raid_slot));
}
static void process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg)
{
- switch (msg->type) {
+ if (WARN(mddev->cluster_info->slot_number - 1 == le32_to_cpu(msg->slot),
+ "node %d received it's own msg\n", le32_to_cpu(msg->slot)))
+ return;
+ switch (le32_to_cpu(msg->type)) {
case METADATA_UPDATED:
- pr_info("%s: %d Received message: METADATA_UPDATE from %d\n",
- __func__, __LINE__, msg->slot);
process_metadata_update(mddev, msg);
break;
case RESYNCING:
- pr_info("%s: %d Received message: RESYNCING from %d\n",
- __func__, __LINE__, msg->slot);
- process_suspend_info(mddev->cluster_info, msg->slot,
- msg->low, msg->high);
+ process_suspend_info(mddev, le32_to_cpu(msg->slot),
+ le64_to_cpu(msg->low),
+ le64_to_cpu(msg->high));
break;
case NEWDISK:
- pr_info("%s: %d Received message: NEWDISK from %d\n",
- __func__, __LINE__, msg->slot);
process_add_new_disk(mddev, msg);
break;
case REMOVE:
- pr_info("%s: %d Received REMOVE from %d\n",
- __func__, __LINE__, msg->slot);
process_remove_disk(mddev, msg);
break;
case RE_ADD:
- pr_info("%s: %d Received RE_ADD from %d\n",
- __func__, __LINE__, msg->slot);
process_readd_disk(mddev, msg);
break;
case BITMAP_NEEDS_SYNC:
- pr_info("%s: %d Received BITMAP_NEEDS_SYNC from %d\n",
- __func__, __LINE__, msg->slot);
- __recover_slot(mddev, msg->slot);
+ __recover_slot(mddev, le32_to_cpu(msg->slot));
break;
default:
pr_warn("%s:%d Received unknown message from %d\n",
@@ -528,11 +533,17 @@ static void recv_daemon(struct md_thread *thread)
/* lock_comm()
* Takes the lock on the TOKEN lock resource so no other
* node can communicate while the operation is underway.
+ * If called again, and the TOKEN lock is alread in EX mode
+ * return success. However, care must be taken that unlock_comm()
+ * is called only once.
*/
static int lock_comm(struct md_cluster_info *cinfo)
{
int error;
+ if (cinfo->token_lockres->mode == DLM_LOCK_EX)
+ return 0;
+
error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX);
if (error)
pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n",
@@ -542,6 +553,7 @@ static int lock_comm(struct md_cluster_info *cinfo)
static void unlock_comm(struct md_cluster_info *cinfo)
{
+ WARN_ON(cinfo->token_lockres->mode != DLM_LOCK_EX);
dlm_unlock_sync(cinfo->token_lockres);
}
@@ -696,7 +708,6 @@ static int join(struct mddev *mddev, int nodes)
init_completion(&cinfo->completion);
set_bit(MD_CLUSTER_BEGIN_JOIN_CLUSTER, &cinfo->state);
- mutex_init(&cinfo->sb_mutex);
mddev->cluster_info = cinfo;
memset(str, 0, 64);
@@ -753,6 +764,10 @@ static int join(struct mddev *mddev, int nodes)
goto err;
}
+ cinfo->resync_lockres = lockres_init(mddev, "resync", NULL, 0);
+ if (!cinfo->resync_lockres)
+ goto err;
+
ret = gather_all_resync_info(mddev, nodes);
if (ret)
goto err;
@@ -763,6 +778,7 @@ err:
lockres_free(cinfo->token_lockres);
lockres_free(cinfo->ack_lockres);
lockres_free(cinfo->no_new_dev_lockres);
+ lockres_free(cinfo->resync_lockres);
lockres_free(cinfo->bitmap_lockres);
if (cinfo->lockspace)
dlm_release_lockspace(cinfo->lockspace, 2);
@@ -771,12 +787,32 @@ err:
return ret;
}
+static void resync_bitmap(struct mddev *mddev)
+{
+ struct md_cluster_info *cinfo = mddev->cluster_info;
+ struct cluster_msg cmsg = {0};
+ int err;
+
+ cmsg.type = cpu_to_le32(BITMAP_NEEDS_SYNC);
+ err = sendmsg(cinfo, &cmsg);
+ if (err)
+ pr_err("%s:%d: failed to send BITMAP_NEEDS_SYNC message (%d)\n",
+ __func__, __LINE__, err);
+}
+
static int leave(struct mddev *mddev)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
if (!cinfo)
return 0;
+
+ /* BITMAP_NEEDS_SYNC message should be sent when node
+ * is leaving the cluster with dirty bitmap, also we
+ * can only deliver it when dlm connection is available */
+ if (cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector)
+ resync_bitmap(mddev);
+
md_unregister_thread(&cinfo->recovery_thread);
md_unregister_thread(&cinfo->recv_thread);
lockres_free(cinfo->message_lockres);
@@ -799,15 +835,6 @@ static int slot_number(struct mddev *mddev)
return cinfo->slot_number - 1;
}
-static void resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi)
-{
- struct md_cluster_info *cinfo = mddev->cluster_info;
-
- add_resync_info(mddev, cinfo->bitmap_lockres, lo, hi);
- /* Re-acquire the lock to refresh LVB */
- dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW);
-}
-
static int metadata_update_start(struct mddev *mddev)
{
return lock_comm(mddev->cluster_info);
@@ -817,59 +844,62 @@ static int metadata_update_finish(struct mddev *mddev)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
struct cluster_msg cmsg;
- int ret;
+ struct md_rdev *rdev;
+ int ret = 0;
+ int raid_slot = -1;
memset(&cmsg, 0, sizeof(cmsg));
cmsg.type = cpu_to_le32(METADATA_UPDATED);
- ret = __sendmsg(cinfo, &cmsg);
+ /* Pick up a good active device number to send.
+ */
+ rdev_for_each(rdev, mddev)
+ if (rdev->raid_disk > -1 && !test_bit(Faulty, &rdev->flags)) {
+ raid_slot = rdev->desc_nr;
+ break;
+ }
+ if (raid_slot >= 0) {
+ cmsg.raid_slot = cpu_to_le32(raid_slot);
+ ret = __sendmsg(cinfo, &cmsg);
+ } else
+ pr_warn("md-cluster: No good device id found to send\n");
unlock_comm(cinfo);
return ret;
}
-static int metadata_update_cancel(struct mddev *mddev)
+static void metadata_update_cancel(struct mddev *mddev)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
+ unlock_comm(cinfo);
+}
- return dlm_unlock_sync(cinfo->token_lockres);
+static int resync_start(struct mddev *mddev)
+{
+ struct md_cluster_info *cinfo = mddev->cluster_info;
+ cinfo->resync_lockres->flags |= DLM_LKF_NOQUEUE;
+ return dlm_lock_sync(cinfo->resync_lockres, DLM_LOCK_EX);
}
-static int resync_send(struct mddev *mddev, enum msg_type type,
- sector_t lo, sector_t hi)
+static int resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
- struct cluster_msg cmsg;
- int slot = cinfo->slot_number - 1;
+ struct cluster_msg cmsg = {0};
- pr_info("%s:%d lo: %llu hi: %llu\n", __func__, __LINE__,
- (unsigned long long)lo,
- (unsigned long long)hi);
- resync_info_update(mddev, lo, hi);
- cmsg.type = cpu_to_le32(type);
- cmsg.slot = cpu_to_le32(slot);
+ add_resync_info(cinfo->bitmap_lockres, lo, hi);
+ /* Re-acquire the lock to refresh LVB */
+ dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW);
+ cmsg.type = cpu_to_le32(RESYNCING);
cmsg.low = cpu_to_le64(lo);
cmsg.high = cpu_to_le64(hi);
- return sendmsg(cinfo, &cmsg);
-}
-static int resync_start(struct mddev *mddev, sector_t lo, sector_t hi)
-{
- pr_info("%s:%d\n", __func__, __LINE__);
- return resync_send(mddev, RESYNCING, lo, hi);
+ return sendmsg(cinfo, &cmsg);
}
-static void resync_finish(struct mddev *mddev)
+static int resync_finish(struct mddev *mddev)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
- struct cluster_msg cmsg;
- int slot = cinfo->slot_number - 1;
-
- pr_info("%s:%d\n", __func__, __LINE__);
- resync_send(mddev, RESYNCING, 0, 0);
- if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
- cmsg.type = cpu_to_le32(BITMAP_NEEDS_SYNC);
- cmsg.slot = cpu_to_le32(slot);
- sendmsg(cinfo, &cmsg);
- }
+ cinfo->resync_lockres->flags &= ~DLM_LKF_NOQUEUE;
+ dlm_unlock_sync(cinfo->resync_lockres);
+ return resync_info_update(mddev, 0, 0);
}
static int area_resyncing(struct mddev *mddev, int direction,
@@ -896,7 +926,11 @@ out:
return ret;
}
-static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
+/* add_new_disk() - initiates a disk add
+ * However, if this fails before writing md_update_sb(),
+ * add_new_disk_cancel() must be called to release token lock
+ */
+static int add_new_disk(struct mddev *mddev, struct md_rdev *rdev)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
struct cluster_msg cmsg;
@@ -907,7 +941,7 @@ static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
memset(&cmsg, 0, sizeof(cmsg));
cmsg.type = cpu_to_le32(NEWDISK);
memcpy(cmsg.uuid, uuid, 16);
- cmsg.raid_slot = rdev->desc_nr;
+ cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
lock_comm(cinfo);
ret = __sendmsg(cinfo, &cmsg);
if (ret)
@@ -918,22 +952,17 @@ static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
/* Some node does not "see" the device */
if (ret == -EAGAIN)
ret = -ENOENT;
+ if (ret)
+ unlock_comm(cinfo);
else
dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
return ret;
}
-static int add_new_disk_finish(struct mddev *mddev)
+static void add_new_disk_cancel(struct mddev *mddev)
{
- struct cluster_msg cmsg;
struct md_cluster_info *cinfo = mddev->cluster_info;
- int ret;
- /* Write sb and inform others */
- md_update_sb(mddev, 1);
- cmsg.type = METADATA_UPDATED;
- ret = __sendmsg(cinfo, &cmsg);
unlock_comm(cinfo);
- return ret;
}
static int new_disk_ack(struct mddev *mddev, bool ack)
@@ -953,10 +982,10 @@ static int new_disk_ack(struct mddev *mddev, bool ack)
static int remove_disk(struct mddev *mddev, struct md_rdev *rdev)
{
- struct cluster_msg cmsg;
+ struct cluster_msg cmsg = {0};
struct md_cluster_info *cinfo = mddev->cluster_info;
- cmsg.type = REMOVE;
- cmsg.raid_slot = rdev->desc_nr;
+ cmsg.type = cpu_to_le32(REMOVE);
+ cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
return __sendmsg(cinfo, &cmsg);
}
@@ -964,12 +993,12 @@ static int gather_bitmaps(struct md_rdev *rdev)
{
int sn, err;
sector_t lo, hi;
- struct cluster_msg cmsg;
+ struct cluster_msg cmsg = {0};
struct mddev *mddev = rdev->mddev;
struct md_cluster_info *cinfo = mddev->cluster_info;
- cmsg.type = RE_ADD;
- cmsg.raid_slot = rdev->desc_nr;
+ cmsg.type = cpu_to_le32(RE_ADD);
+ cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
err = sendmsg(cinfo, &cmsg);
if (err)
goto out;
@@ -993,15 +1022,15 @@ static struct md_cluster_operations cluster_ops = {
.join = join,
.leave = leave,
.slot_number = slot_number,
- .resync_info_update = resync_info_update,
.resync_start = resync_start,
.resync_finish = resync_finish,
+ .resync_info_update = resync_info_update,
.metadata_update_start = metadata_update_start,
.metadata_update_finish = metadata_update_finish,
.metadata_update_cancel = metadata_update_cancel,
.area_resyncing = area_resyncing,
- .add_new_disk_start = add_new_disk_start,
- .add_new_disk_finish = add_new_disk_finish,
+ .add_new_disk = add_new_disk,
+ .add_new_disk_cancel = add_new_disk_cancel,
.new_disk_ack = new_disk_ack,
.remove_disk = remove_disk,
.gather_bitmaps = gather_bitmaps,
@@ -1022,5 +1051,6 @@ static void cluster_exit(void)
module_init(cluster_init);
module_exit(cluster_exit);
+MODULE_AUTHOR("SUSE");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Clustering support for MD");
diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h
index 00defe2badbc..e75ea2613184 100644
--- a/drivers/md/md-cluster.h
+++ b/drivers/md/md-cluster.h
@@ -12,15 +12,15 @@ struct md_cluster_operations {
int (*join)(struct mddev *mddev, int nodes);
int (*leave)(struct mddev *mddev);
int (*slot_number)(struct mddev *mddev);
- void (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi);
- int (*resync_start)(struct mddev *mddev, sector_t lo, sector_t hi);
- void (*resync_finish)(struct mddev *mddev);
+ int (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi);
int (*metadata_update_start)(struct mddev *mddev);
int (*metadata_update_finish)(struct mddev *mddev);
- int (*metadata_update_cancel)(struct mddev *mddev);
+ void (*metadata_update_cancel)(struct mddev *mddev);
+ int (*resync_start)(struct mddev *mddev);
+ int (*resync_finish)(struct mddev *mddev);
int (*area_resyncing)(struct mddev *mddev, int direction, sector_t lo, sector_t hi);
- int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev);
- int (*add_new_disk_finish)(struct mddev *mddev);
+ int (*add_new_disk)(struct mddev *mddev, struct md_rdev *rdev);
+ void (*add_new_disk_cancel)(struct mddev *mddev);
int (*new_disk_ack)(struct mddev *mddev, bool ack);
int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev);
int (*gather_bitmaps)(struct md_rdev *rdev);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c702de18207a..807095f4c793 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -250,7 +250,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
* call has finished, the bio has been linked into some internal structure
* and so is visible to ->quiesce(), so we don't need the refcount any more.
*/
-static void md_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
{
const int rw = bio_data_dir(bio);
struct mddev *mddev = q->queuedata;
@@ -262,13 +262,13 @@ static void md_make_request(struct request_queue *q, struct bio *bio)
if (mddev == NULL || mddev->pers == NULL
|| !mddev->ready) {
bio_io_error(bio);
- return;
+ return BLK_QC_T_NONE;
}
if (mddev->ro == 1 && unlikely(rw == WRITE)) {
if (bio_sectors(bio) != 0)
bio->bi_error = -EROFS;
bio_endio(bio);
- return;
+ return BLK_QC_T_NONE;
}
smp_rmb(); /* Ensure implications of 'active' are visible */
rcu_read_lock();
@@ -302,6 +302,8 @@ static void md_make_request(struct request_queue *q, struct bio *bio)
if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
wake_up(&mddev->sb_wait);
+
+ return BLK_QC_T_NONE;
}
/* mddev_suspend makes sure no new requests are submitted
@@ -1608,7 +1610,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
++ev1;
if (rdev->desc_nr >= 0 &&
rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
- le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < 0xfffe)
+ (le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < MD_DISK_ROLE_MAX ||
+ le16_to_cpu(sb->dev_roles[rdev->desc_nr]) == MD_DISK_ROLE_JOURNAL))
if (ev1 < mddev->events)
return -EINVAL;
} else if (mddev->bitmap) {
@@ -1628,16 +1631,29 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
int role;
if (rdev->desc_nr < 0 ||
rdev->desc_nr >= le32_to_cpu(sb->max_dev)) {
- role = 0xffff;
+ role = MD_DISK_ROLE_SPARE;
rdev->desc_nr = -1;
} else
role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
switch(role) {
- case 0xffff: /* spare */
+ case MD_DISK_ROLE_SPARE: /* spare */
break;
- case 0xfffe: /* faulty */
+ case MD_DISK_ROLE_FAULTY: /* faulty */
set_bit(Faulty, &rdev->flags);
break;
+ case MD_DISK_ROLE_JOURNAL: /* journal device */
+ if (!(le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)) {
+ /* journal device without journal feature */
+ printk(KERN_WARNING
+ "md: journal device provided without journal feature, ignoring the device\n");
+ return -EINVAL;
+ }
+ set_bit(Journal, &rdev->flags);
+ rdev->journal_tail = le64_to_cpu(sb->journal_tail);
+ if (mddev->recovery_cp == MaxSector)
+ set_bit(MD_JOURNAL_CLEAN, &mddev->flags);
+ rdev->raid_disk = mddev->raid_disks;
+ break;
default:
rdev->saved_raid_disk = role;
if ((le32_to_cpu(sb->feature_map) &
@@ -1655,6 +1671,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
set_bit(WriteMostly, &rdev->flags);
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_REPLACEMENT)
set_bit(Replacement, &rdev->flags);
+ if (le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)
+ set_bit(MD_HAS_JOURNAL, &mddev->flags);
} else /* MULTIPATH are always insync */
set_bit(In_sync, &rdev->flags);
@@ -1679,6 +1697,8 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->events = cpu_to_le64(mddev->events);
if (mddev->in_sync)
sb->resync_offset = cpu_to_le64(mddev->recovery_cp);
+ else if (test_bit(MD_JOURNAL_CLEAN, &mddev->flags))
+ sb->resync_offset = cpu_to_le64(MaxSector);
else
sb->resync_offset = cpu_to_le64(0);
@@ -1702,7 +1722,7 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
}
- if (rdev->raid_disk >= 0 &&
+ if (rdev->raid_disk >= 0 && !test_bit(Journal, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags)) {
sb->feature_map |=
cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET);
@@ -1712,6 +1732,9 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->feature_map |=
cpu_to_le32(MD_FEATURE_RECOVERY_BITMAP);
}
+ /* Note: recovery_offset and journal_tail share space */
+ if (test_bit(Journal, &rdev->flags))
+ sb->journal_tail = cpu_to_le64(rdev->journal_tail);
if (test_bit(Replacement, &rdev->flags))
sb->feature_map |=
cpu_to_le32(MD_FEATURE_REPLACEMENT);
@@ -1735,6 +1758,9 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
}
}
+ if (mddev_is_clustered(mddev))
+ sb->feature_map |= cpu_to_le32(MD_FEATURE_CLUSTERED);
+
if (rdev->badblocks.count == 0)
/* Nothing to do for bad blocks*/ ;
else if (sb->bblog_offset == 0)
@@ -1785,18 +1811,23 @@ retry:
max_dev = le32_to_cpu(sb->max_dev);
for (i=0; i<max_dev;i++)
- sb->dev_roles[i] = cpu_to_le16(0xfffe);
+ sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_FAULTY);
+
+ if (test_bit(MD_HAS_JOURNAL, &mddev->flags))
+ sb->feature_map |= cpu_to_le32(MD_FEATURE_JOURNAL);
rdev_for_each(rdev2, mddev) {
i = rdev2->desc_nr;
if (test_bit(Faulty, &rdev2->flags))
- sb->dev_roles[i] = cpu_to_le16(0xfffe);
+ sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_FAULTY);
else if (test_bit(In_sync, &rdev2->flags))
sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk);
+ else if (test_bit(Journal, &rdev2->flags))
+ sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_JOURNAL);
else if (rdev2->raid_disk >= 0)
sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk);
else
- sb->dev_roles[i] = cpu_to_le16(0xffff);
+ sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_SPARE);
}
sb->sb_csum = calc_sb_1_csum(sb);
@@ -1912,13 +1943,23 @@ static int match_mddev_units(struct mddev *mddev1, struct mddev *mddev2)
struct md_rdev *rdev, *rdev2;
rcu_read_lock();
- rdev_for_each_rcu(rdev, mddev1)
- rdev_for_each_rcu(rdev2, mddev2)
+ rdev_for_each_rcu(rdev, mddev1) {
+ if (test_bit(Faulty, &rdev->flags) ||
+ test_bit(Journal, &rdev->flags) ||
+ rdev->raid_disk == -1)
+ continue;
+ rdev_for_each_rcu(rdev2, mddev2) {
+ if (test_bit(Faulty, &rdev2->flags) ||
+ test_bit(Journal, &rdev2->flags) ||
+ rdev2->raid_disk == -1)
+ continue;
if (rdev->bdev->bd_contains ==
rdev2->bdev->bd_contains) {
rcu_read_unlock();
return 1;
}
+ }
+ }
rcu_read_unlock();
return 0;
}
@@ -1962,12 +2003,9 @@ int md_integrity_register(struct mddev *mddev)
* All component devices are integrity capable and have matching
* profiles, register the common profile for the md device.
*/
- if (blk_integrity_register(mddev->gendisk,
- bdev_get_integrity(reference->bdev)) != 0) {
- printk(KERN_ERR "md: failed to register integrity for %s\n",
- mdname(mddev));
- return -EINVAL;
- }
+ blk_integrity_register(mddev->gendisk,
+ bdev_get_integrity(reference->bdev));
+
printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev));
if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) {
printk(KERN_ERR "md: failed to create integrity pool for %s\n",
@@ -1997,6 +2035,7 @@ void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
if (bi_rdev && blk_integrity_compare(mddev->gendisk,
rdev->bdev->bd_disk) >= 0)
return;
+ WARN_ON_ONCE(!mddev->suspended);
printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
blk_integrity_unregister(mddev->gendisk);
}
@@ -2196,23 +2235,77 @@ static void sync_sbs(struct mddev *mddev, int nospares)
}
}
+static bool does_sb_need_changing(struct mddev *mddev)
+{
+ struct md_rdev *rdev;
+ struct mdp_superblock_1 *sb;
+ int role;
+
+ /* Find a good rdev */
+ rdev_for_each(rdev, mddev)
+ if ((rdev->raid_disk >= 0) && !test_bit(Faulty, &rdev->flags))
+ break;
+
+ /* No good device found. */
+ if (!rdev)
+ return false;
+
+ sb = page_address(rdev->sb_page);
+ /* Check if a device has become faulty or a spare become active */
+ rdev_for_each(rdev, mddev) {
+ role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+ /* Device activated? */
+ if (role == 0xffff && rdev->raid_disk >=0 &&
+ !test_bit(Faulty, &rdev->flags))
+ return true;
+ /* Device turned faulty? */
+ if (test_bit(Faulty, &rdev->flags) && (role < 0xfffd))
+ return true;
+ }
+
+ /* Check if any mddev parameters have changed */
+ if ((mddev->dev_sectors != le64_to_cpu(sb->size)) ||
+ (mddev->reshape_position != le64_to_cpu(sb->reshape_position)) ||
+ (mddev->layout != le64_to_cpu(sb->layout)) ||
+ (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) ||
+ (mddev->chunk_sectors != le32_to_cpu(sb->chunksize)))
+ return true;
+
+ return false;
+}
+
void md_update_sb(struct mddev *mddev, int force_change)
{
struct md_rdev *rdev;
int sync_req;
int nospares = 0;
int any_badblocks_changed = 0;
+ int ret = -1;
if (mddev->ro) {
if (force_change)
set_bit(MD_CHANGE_DEVS, &mddev->flags);
return;
}
+
+ if (mddev_is_clustered(mddev)) {
+ if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags))
+ force_change = 1;
+ ret = md_cluster_ops->metadata_update_start(mddev);
+ /* Has someone else has updated the sb */
+ if (!does_sb_need_changing(mddev)) {
+ if (ret == 0)
+ md_cluster_ops->metadata_update_cancel(mddev);
+ clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+ return;
+ }
+ }
repeat:
/* First make sure individual recovery_offsets are correct */
rdev_for_each(rdev, mddev) {
if (rdev->raid_disk >= 0 &&
mddev->delta_disks >= 0 &&
+ !test_bit(Journal, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
mddev->curr_resync_completed > rdev->recovery_offset)
rdev->recovery_offset = mddev->curr_resync_completed;
@@ -2356,6 +2449,9 @@ repeat:
clear_bit(BlockedBadBlocks, &rdev->flags);
wake_up(&rdev->blocked_wait);
}
+
+ if (mddev_is_clustered(mddev) && ret == 0)
+ md_cluster_ops->metadata_update_finish(mddev);
}
EXPORT_SYMBOL(md_update_sb);
@@ -2431,6 +2527,10 @@ state_show(struct md_rdev *rdev, char *page)
len += sprintf(page+len, "%sin_sync",sep);
sep = ",";
}
+ if (test_bit(Journal, &flags)) {
+ len += sprintf(page+len, "%sjournal",sep);
+ sep = ",";
+ }
if (test_bit(WriteMostly, &flags)) {
len += sprintf(page+len, "%swrite_mostly",sep);
sep = ",";
@@ -2442,6 +2542,7 @@ state_show(struct md_rdev *rdev, char *page)
sep = ",";
}
if (!test_bit(Faulty, &flags) &&
+ !test_bit(Journal, &flags) &&
!test_bit(In_sync, &flags)) {
len += sprintf(page+len, "%sspare", sep);
sep = ",";
@@ -2490,17 +2591,16 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
err = -EBUSY;
else {
struct mddev *mddev = rdev->mddev;
- if (mddev_is_clustered(mddev))
- md_cluster_ops->remove_disk(mddev, rdev);
- md_kick_rdev_from_array(rdev);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
- if (mddev->pers)
- md_update_sb(mddev, 1);
- md_new_event(mddev);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
err = 0;
+ if (mddev_is_clustered(mddev))
+ err = md_cluster_ops->remove_disk(mddev, rdev);
+
+ if (err == 0) {
+ md_kick_rdev_from_array(rdev);
+ if (mddev->pers)
+ md_update_sb(mddev, 1);
+ md_new_event(mddev);
+ }
}
} else if (cmd_match(buf, "writemostly")) {
set_bit(WriteMostly, &rdev->flags);
@@ -2529,7 +2629,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
set_bit(In_sync, &rdev->flags);
err = 0;
- } else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0) {
+ } else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0 &&
+ !test_bit(Journal, &rdev->flags)) {
if (rdev->mddev->pers == NULL) {
clear_bit(In_sync, &rdev->flags);
rdev->saved_raid_disk = rdev->raid_disk;
@@ -2548,6 +2649,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
* check if recovery is needed.
*/
if (rdev->raid_disk >= 0 &&
+ !test_bit(Journal, &rdev->flags) &&
!test_bit(Replacement, &rdev->flags))
set_bit(WantReplacement, &rdev->flags);
set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
@@ -2625,7 +2727,9 @@ __ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store);
static ssize_t
slot_show(struct md_rdev *rdev, char *page)
{
- if (rdev->raid_disk < 0)
+ if (test_bit(Journal, &rdev->flags))
+ return sprintf(page, "journal\n");
+ else if (rdev->raid_disk < 0)
return sprintf(page, "none\n");
else
return sprintf(page, "%d\n", rdev->raid_disk);
@@ -2637,6 +2741,8 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
int slot;
int err;
+ if (test_bit(Journal, &rdev->flags))
+ return -EBUSY;
if (strncmp(buf, "none", 4)==0)
slot = -1;
else {
@@ -2688,15 +2794,9 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
rdev->saved_raid_disk = -1;
clear_bit(In_sync, &rdev->flags);
clear_bit(Bitmap_sync, &rdev->flags);
- err = rdev->mddev->pers->
- hot_add_disk(rdev->mddev, rdev);
- if (err) {
- rdev->raid_disk = -1;
- return err;
- } else
- sysfs_notify_dirent_safe(rdev->sysfs_state);
- if (sysfs_link_rdev(rdev->mddev, rdev))
- /* failure here is OK */;
+ remove_and_add_spares(rdev->mddev, rdev);
+ if (rdev->raid_disk == -1)
+ return -EBUSY;
/* don't wakeup anyone, leave that to userspace. */
} else {
if (slot >= rdev->mddev->raid_disks &&
@@ -2841,6 +2941,8 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
sector_t oldsectors = rdev->sectors;
sector_t sectors;
+ if (test_bit(Journal, &rdev->flags))
+ return -EBUSY;
if (strict_blocks_to_sectors(buf, &sectors) < 0)
return -EINVAL;
if (rdev->data_offset != rdev->new_data_offset)
@@ -3198,20 +3300,14 @@ static void analyze_sbs(struct mddev *mddev)
md_kick_rdev_from_array(rdev);
continue;
}
- /* No device should have a Candidate flag
- * when reading devices
- */
- if (test_bit(Candidate, &rdev->flags)) {
- pr_info("md: kicking Cluster Candidate %s from array!\n",
- bdevname(rdev->bdev, b));
- md_kick_rdev_from_array(rdev);
- }
}
if (mddev->level == LEVEL_MULTIPATH) {
rdev->desc_nr = i++;
rdev->raid_disk = rdev->desc_nr;
set_bit(In_sync, &rdev->flags);
- } else if (rdev->raid_disk >= (mddev->raid_disks - min(0, mddev->delta_disks))) {
+ } else if (rdev->raid_disk >=
+ (mddev->raid_disks - min(0, mddev->delta_disks)) &&
+ !test_bit(Journal, &rdev->flags)) {
rdev->raid_disk = -1;
clear_bit(In_sync, &rdev->flags);
}
@@ -3269,6 +3365,11 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
{
unsigned long msec;
+ if (mddev_is_clustered(mddev)) {
+ pr_info("md: Safemode is disabled for clustered mode\n");
+ return -EINVAL;
+ }
+
if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
return -EINVAL;
if (msec == 0)
@@ -3869,7 +3970,9 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
break;
case clean:
if (mddev->pers) {
- restart_array(mddev);
+ err = restart_array(mddev);
+ if (err)
+ break;
spin_lock(&mddev->lock);
if (atomic_read(&mddev->writes_pending) == 0) {
if (mddev->in_sync == 0) {
@@ -3887,7 +3990,9 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
break;
case active:
if (mddev->pers) {
- restart_array(mddev);
+ err = restart_array(mddev);
+ if (err)
+ break;
clear_bit(MD_CHANGE_PENDING, &mddev->flags);
wake_up(&mddev->sb_wait);
err = 0;
@@ -4066,12 +4171,8 @@ size_store(struct mddev *mddev, const char *buf, size_t len)
if (err)
return err;
if (mddev->pers) {
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
err = update_size(mddev, sectors);
md_update_sb(mddev, 1);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
} else {
if (mddev->dev_sectors == 0 ||
mddev->dev_sectors > sectors)
@@ -5183,7 +5284,10 @@ int md_run(struct mddev *mddev)
atomic_set(&mddev->max_corr_read_errors,
MD_DEFAULT_MAX_CORRECTED_READ_ERRORS);
mddev->safemode = 0;
- mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
+ if (mddev_is_clustered(mddev))
+ mddev->safemode_delay = 0;
+ else
+ mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
mddev->in_sync = 1;
smp_wmb();
spin_lock(&mddev->lock);
@@ -5226,6 +5330,9 @@ static int do_md_run(struct mddev *mddev)
goto out;
}
+ if (mddev_is_clustered(mddev))
+ md_allow_write(mddev);
+
md_wakeup_thread(mddev->thread);
md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
@@ -5248,6 +5355,25 @@ static int restart_array(struct mddev *mddev)
return -EINVAL;
if (!mddev->ro)
return -EBUSY;
+ if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) {
+ struct md_rdev *rdev;
+ bool has_journal = false;
+
+ rcu_read_lock();
+ rdev_for_each_rcu(rdev, mddev) {
+ if (test_bit(Journal, &rdev->flags) &&
+ !test_bit(Faulty, &rdev->flags)) {
+ has_journal = true;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ /* Don't restart rw with journal missing/faulty */
+ if (!has_journal)
+ return -EINVAL;
+ }
+
mddev->safemode = 0;
mddev->ro = 0;
set_disk_ro(disk, 0);
@@ -5309,8 +5435,6 @@ static void md_clean(struct mddev *mddev)
static void __md_stop_writes(struct mddev *mddev)
{
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
flush_workqueue(md_misc_wq);
if (mddev->sync_thread) {
@@ -5324,13 +5448,13 @@ static void __md_stop_writes(struct mddev *mddev)
md_super_wait(mddev);
if (mddev->ro == 0 &&
- (!mddev->in_sync || (mddev->flags & MD_UPDATE_SB_FLAGS))) {
+ ((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
+ (mddev->flags & MD_UPDATE_SB_FLAGS))) {
/* mark array as shutdown cleanly */
- mddev->in_sync = 1;
+ if (!mddev_is_clustered(mddev))
+ mddev->in_sync = 1;
md_update_sb(mddev, 1);
}
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
}
void md_stop_writes(struct mddev *mddev)
@@ -5542,7 +5666,6 @@ static int do_md_stop(struct mddev *mddev, int mode,
if (mddev->hold_active == UNTIL_STOP)
mddev->hold_active = 0;
}
- blk_integrity_unregister(disk);
md_new_event(mddev);
sysfs_notify_dirent_safe(mddev->sysfs_state);
return 0;
@@ -5792,6 +5915,8 @@ static int get_disk_info(struct mddev *mddev, void __user * arg)
info.state |= (1<<MD_DISK_ACTIVE);
info.state |= (1<<MD_DISK_SYNC);
}
+ if (test_bit(Journal, &rdev->flags))
+ info.state |= (1<<MD_DISK_JOURNAL);
if (test_bit(WriteMostly, &rdev->flags))
info.state |= (1<<MD_DISK_WRITEMOSTLY);
} else {
@@ -5906,23 +6031,18 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
else
clear_bit(WriteMostly, &rdev->flags);
+ if (info->state & (1<<MD_DISK_JOURNAL))
+ set_bit(Journal, &rdev->flags);
/*
* check whether the device shows up in other nodes
*/
if (mddev_is_clustered(mddev)) {
- if (info->state & (1 << MD_DISK_CANDIDATE)) {
- /* Through --cluster-confirm */
+ if (info->state & (1 << MD_DISK_CANDIDATE))
set_bit(Candidate, &rdev->flags);
- err = md_cluster_ops->new_disk_ack(mddev, true);
- if (err) {
- export_rdev(rdev);
- return err;
- }
- } else if (info->state & (1 << MD_DISK_CLUSTER_ADD)) {
+ else if (info->state & (1 << MD_DISK_CLUSTER_ADD)) {
/* --add initiated by this node */
- err = md_cluster_ops->add_new_disk_start(mddev, rdev);
+ err = md_cluster_ops->add_new_disk(mddev, rdev);
if (err) {
- md_cluster_ops->add_new_disk_finish(mddev);
export_rdev(rdev);
return err;
}
@@ -5931,13 +6051,23 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
rdev->raid_disk = -1;
err = bind_rdev_to_array(rdev, mddev);
+
if (err)
export_rdev(rdev);
- else
+
+ if (mddev_is_clustered(mddev)) {
+ if (info->state & (1 << MD_DISK_CANDIDATE))
+ md_cluster_ops->new_disk_ack(mddev, (err == 0));
+ else {
+ if (err)
+ md_cluster_ops->add_new_disk_cancel(mddev);
+ else
+ err = add_bound_rdev(rdev);
+ }
+
+ } else if (!err)
err = add_bound_rdev(rdev);
- if (mddev_is_clustered(mddev) &&
- (info->state & (1 << MD_DISK_CLUSTER_ADD)))
- md_cluster_ops->add_new_disk_finish(mddev);
+
return err;
}
@@ -5993,13 +6123,17 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
{
char b[BDEVNAME_SIZE];
struct md_rdev *rdev;
+ int ret = -1;
rdev = find_rdev(mddev, dev);
if (!rdev)
return -ENXIO;
if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
+ ret = md_cluster_ops->metadata_update_start(mddev);
+
+ if (rdev->raid_disk < 0)
+ goto kick_rdev;
clear_bit(Blocked, &rdev->flags);
remove_and_add_spares(mddev, rdev);
@@ -6007,20 +6141,19 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
if (rdev->raid_disk >= 0)
goto busy;
- if (mddev_is_clustered(mddev))
+kick_rdev:
+ if (mddev_is_clustered(mddev) && ret == 0)
md_cluster_ops->remove_disk(mddev, rdev);
md_kick_rdev_from_array(rdev);
md_update_sb(mddev, 1);
md_new_event(mddev);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
-
return 0;
busy:
- if (mddev_is_clustered(mddev))
+ if (mddev_is_clustered(mddev) && ret == 0)
md_cluster_ops->metadata_update_cancel(mddev);
+
printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
bdevname(rdev->bdev,b), mdname(mddev));
return -EBUSY;
@@ -6071,14 +6204,12 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
goto abort_export;
}
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
clear_bit(In_sync, &rdev->flags);
rdev->desc_nr = -1;
rdev->saved_raid_disk = -1;
err = bind_rdev_to_array(rdev, mddev);
if (err)
- goto abort_clustered;
+ goto abort_export;
/*
* The rest should better be atomic, we can have disk failures
@@ -6088,9 +6219,6 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
rdev->raid_disk = -1;
md_update_sb(mddev, 1);
-
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
/*
* Kick recovery, maybe this spare has to be added to the
* array immediately.
@@ -6100,9 +6228,6 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
md_new_event(mddev);
return 0;
-abort_clustered:
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_cancel(mddev);
abort_export:
export_rdev(rdev);
return err;
@@ -6420,8 +6545,6 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
return rv;
}
}
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
if (info->size >= 0 && mddev->dev_sectors / 2 != info->size)
rv = update_size(mddev, (sector_t)info->size * 2);
@@ -6479,12 +6602,8 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
}
}
md_update_sb(mddev, 1);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
return rv;
err:
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_cancel(mddev);
return rv;
}
@@ -7285,6 +7404,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
bdevname(rdev->bdev,b), rdev->desc_nr);
if (test_bit(WriteMostly, &rdev->flags))
seq_printf(seq, "(W)");
+ if (test_bit(Journal, &rdev->flags))
+ seq_printf(seq, "(J)");
if (test_bit(Faulty, &rdev->flags)) {
seq_printf(seq, "(F)");
continue;
@@ -7597,11 +7718,7 @@ int md_allow_write(struct mddev *mddev)
mddev->safemode == 0)
mddev->safemode = 1;
spin_unlock(&mddev->lock);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
md_update_sb(mddev, 0);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
sysfs_notify_dirent_safe(mddev->sysfs_state);
} else
spin_unlock(&mddev->lock);
@@ -7633,6 +7750,7 @@ void md_do_sync(struct md_thread *thread)
struct md_rdev *rdev;
char *desc, *action = NULL;
struct blk_plug plug;
+ bool cluster_resync_finished = false;
/* just incase thread restarts... */
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
@@ -7742,6 +7860,7 @@ void md_do_sync(struct md_thread *thread)
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev)
if (rdev->raid_disk >= 0 &&
+ !test_bit(Journal, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < j)
@@ -7802,9 +7921,6 @@ void md_do_sync(struct md_thread *thread)
md_new_event(mddev);
update_time = jiffies;
- if (mddev_is_clustered(mddev))
- md_cluster_ops->resync_start(mddev, j, max_sectors);
-
blk_start_plug(&plug);
while (j < max_sectors) {
sector_t sectors;
@@ -7868,8 +7984,6 @@ void md_do_sync(struct md_thread *thread)
j = max_sectors;
if (j > 2)
mddev->curr_resync = j;
- if (mddev_is_clustered(mddev))
- md_cluster_ops->resync_info_update(mddev, j, max_sectors);
mddev->curr_mark_cnt = io_sectors;
if (last_check == 0)
/* this is the earliest that rebuild will be
@@ -7940,7 +8054,11 @@ void md_do_sync(struct md_thread *thread)
mddev->curr_resync_completed = mddev->curr_resync;
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
- /* tell personality that we are finished */
+ /* tell personality and other nodes that we are finished */
+ if (mddev_is_clustered(mddev)) {
+ md_cluster_ops->resync_finish(mddev);
+ cluster_resync_finished = true;
+ }
mddev->pers->sync_request(mddev, max_sectors, &skipped);
if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
@@ -7968,6 +8086,7 @@ void md_do_sync(struct md_thread *thread)
rdev_for_each_rcu(rdev, mddev)
if (rdev->raid_disk >= 0 &&
mddev->delta_disks >= 0 &&
+ !test_bit(Journal, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < mddev->curr_resync)
@@ -7976,11 +8095,13 @@ void md_do_sync(struct md_thread *thread)
}
}
skip:
- if (mddev_is_clustered(mddev))
- md_cluster_ops->resync_finish(mddev);
-
set_bit(MD_CHANGE_DEVS, &mddev->flags);
+ if (mddev_is_clustered(mddev) &&
+ test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
+ !cluster_resync_finished)
+ md_cluster_ops->resync_finish(mddev);
+
spin_lock(&mddev->lock);
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
/* We completed so min/max setting can be forgotten if used. */
@@ -8011,7 +8132,8 @@ static int remove_and_add_spares(struct mddev *mddev,
rdev->raid_disk >= 0 &&
!test_bit(Blocked, &rdev->flags) &&
(test_bit(Faulty, &rdev->flags) ||
- ! test_bit(In_sync, &rdev->flags)) &&
+ (!test_bit(In_sync, &rdev->flags) &&
+ !test_bit(Journal, &rdev->flags))) &&
atomic_read(&rdev->nr_pending)==0) {
if (mddev->pers->hot_remove_disk(
mddev, rdev) == 0) {
@@ -8023,25 +8145,31 @@ static int remove_and_add_spares(struct mddev *mddev,
if (removed && mddev->kobj.sd)
sysfs_notify(&mddev->kobj, NULL, "degraded");
- if (this)
+ if (this && removed)
goto no_add;
rdev_for_each(rdev, mddev) {
+ if (this && this != rdev)
+ continue;
+ if (test_bit(Candidate, &rdev->flags))
+ continue;
if (rdev->raid_disk >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
+ !test_bit(Journal, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags))
spares++;
if (rdev->raid_disk >= 0)
continue;
if (test_bit(Faulty, &rdev->flags))
continue;
+ if (test_bit(Journal, &rdev->flags))
+ continue;
if (mddev->ro &&
! (rdev->saved_raid_disk >= 0 &&
!test_bit(Bitmap_sync, &rdev->flags)))
continue;
- if (rdev->saved_raid_disk < 0)
- rdev->recovery_offset = 0;
+ rdev->recovery_offset = 0;
if (mddev->pers->
hot_add_disk(mddev, rdev) == 0) {
if (sysfs_link_rdev(mddev, rdev))
@@ -8060,14 +8188,25 @@ no_add:
static void md_start_sync(struct work_struct *ws)
{
struct mddev *mddev = container_of(ws, struct mddev, del_work);
+ int ret = 0;
+
+ if (mddev_is_clustered(mddev)) {
+ ret = md_cluster_ops->resync_start(mddev);
+ if (ret) {
+ mddev->sync_thread = NULL;
+ goto out;
+ }
+ }
mddev->sync_thread = md_register_thread(md_do_sync,
mddev,
"resync");
+out:
if (!mddev->sync_thread) {
- printk(KERN_ERR "%s: could not start resync"
- " thread...\n",
- mdname(mddev));
+ if (!(mddev_is_clustered(mddev) && ret == -EAGAIN))
+ printk(KERN_ERR "%s: could not start resync"
+ " thread...\n",
+ mdname(mddev));
/* leave the spares where they are, it shouldn't hurt */
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -8186,13 +8325,8 @@ void md_check_recovery(struct mddev *mddev)
sysfs_notify_dirent_safe(mddev->sysfs_state);
}
- if (mddev->flags & MD_UPDATE_SB_FLAGS) {
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
+ if (mddev->flags & MD_UPDATE_SB_FLAGS)
md_update_sb(mddev, 0);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
- }
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
@@ -8290,8 +8424,6 @@ void md_reap_sync_thread(struct mddev *mddev)
set_bit(MD_CHANGE_DEVS, &mddev->flags);
}
}
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_start(mddev);
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
mddev->pers->finish_reshape)
mddev->pers->finish_reshape(mddev);
@@ -8304,8 +8436,6 @@ void md_reap_sync_thread(struct mddev *mddev)
rdev->saved_raid_disk = -1;
md_update_sb(mddev, 1);
- if (mddev_is_clustered(mddev))
- md_cluster_ops->metadata_update_finish(mddev);
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
@@ -8928,25 +9058,128 @@ err_wq:
return ret;
}
-void md_reload_sb(struct mddev *mddev)
+static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
{
- struct md_rdev *rdev, *tmp;
+ struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
+ struct md_rdev *rdev2;
+ int role, ret;
+ char b[BDEVNAME_SIZE];
- rdev_for_each_safe(rdev, tmp, mddev) {
- rdev->sb_loaded = 0;
- ClearPageUptodate(rdev->sb_page);
+ /* Check for change of roles in the active devices */
+ rdev_for_each(rdev2, mddev) {
+ if (test_bit(Faulty, &rdev2->flags))
+ continue;
+
+ /* Check if the roles changed */
+ role = le16_to_cpu(sb->dev_roles[rdev2->desc_nr]);
+
+ if (test_bit(Candidate, &rdev2->flags)) {
+ if (role == 0xfffe) {
+ pr_info("md: Removing Candidate device %s because add failed\n", bdevname(rdev2->bdev,b));
+ md_kick_rdev_from_array(rdev2);
+ continue;
+ }
+ else
+ clear_bit(Candidate, &rdev2->flags);
+ }
+
+ if (role != rdev2->raid_disk) {
+ /* got activated */
+ if (rdev2->raid_disk == -1 && role != 0xffff) {
+ rdev2->saved_raid_disk = role;
+ ret = remove_and_add_spares(mddev, rdev2);
+ pr_info("Activated spare: %s\n",
+ bdevname(rdev2->bdev,b));
+ continue;
+ }
+ /* device faulty
+ * We just want to do the minimum to mark the disk
+ * as faulty. The recovery is performed by the
+ * one who initiated the error.
+ */
+ if ((role == 0xfffe) || (role == 0xfffd)) {
+ md_error(mddev, rdev2);
+ clear_bit(Blocked, &rdev2->flags);
+ }
+ }
}
- mddev->raid_disks = 0;
- analyze_sbs(mddev);
- rdev_for_each_safe(rdev, tmp, mddev) {
- struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
- /* since we don't write to faulty devices, we figure out if the
- * disk is faulty by comparing events
- */
- if (mddev->events > sb->events)
- set_bit(Faulty, &rdev->flags);
+
+ if (mddev->raid_disks != le32_to_cpu(sb->raid_disks))
+ update_raid_disks(mddev, le32_to_cpu(sb->raid_disks));
+
+ /* Finally set the event to be up to date */
+ mddev->events = le64_to_cpu(sb->events);
+}
+
+static int read_rdev(struct mddev *mddev, struct md_rdev *rdev)
+{
+ int err;
+ struct page *swapout = rdev->sb_page;
+ struct mdp_superblock_1 *sb;
+
+ /* Store the sb page of the rdev in the swapout temporary
+ * variable in case we err in the future
+ */
+ rdev->sb_page = NULL;
+ alloc_disk_sb(rdev);
+ ClearPageUptodate(rdev->sb_page);
+ rdev->sb_loaded = 0;
+ err = super_types[mddev->major_version].load_super(rdev, NULL, mddev->minor_version);
+
+ if (err < 0) {
+ pr_warn("%s: %d Could not reload rdev(%d) err: %d. Restoring old values\n",
+ __func__, __LINE__, rdev->desc_nr, err);
+ put_page(rdev->sb_page);
+ rdev->sb_page = swapout;
+ rdev->sb_loaded = 1;
+ return err;
+ }
+
+ sb = page_address(rdev->sb_page);
+ /* Read the offset unconditionally, even if MD_FEATURE_RECOVERY_OFFSET
+ * is not set
+ */
+
+ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RECOVERY_OFFSET))
+ rdev->recovery_offset = le64_to_cpu(sb->recovery_offset);
+
+ /* The other node finished recovery, call spare_active to set
+ * device In_sync and mddev->degraded
+ */
+ if (rdev->recovery_offset == MaxSector &&
+ !test_bit(In_sync, &rdev->flags) &&
+ mddev->pers->spare_active(mddev))
+ sysfs_notify(&mddev->kobj, NULL, "degraded");
+
+ put_page(swapout);
+ return 0;
+}
+
+void md_reload_sb(struct mddev *mddev, int nr)
+{
+ struct md_rdev *rdev;
+ int err;
+
+ /* Find the rdev */
+ rdev_for_each_rcu(rdev, mddev) {
+ if (rdev->desc_nr == nr)
+ break;
+ }
+
+ if (!rdev || rdev->desc_nr != nr) {
+ pr_warn("%s: %d Could not find rdev with nr %d\n", __func__, __LINE__, nr);
+ return;
}
+ err = read_rdev(mddev, rdev);
+ if (err < 0)
+ return;
+
+ check_sb_changes(mddev, rdev);
+
+ /* Read all rdev's to update recovery_offset */
+ rdev_for_each_rcu(rdev, mddev)
+ read_rdev(mddev, rdev);
}
EXPORT_SYMBOL(md_reload_sb);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index ab339571e57f..2bea51edfab7 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -87,10 +87,16 @@ struct md_rdev {
* array and could again if we did a partial
* resync from the bitmap
*/
- sector_t recovery_offset;/* If this device has been partially
+ union {
+ sector_t recovery_offset;/* If this device has been partially
* recovered, this is where we were
* up to.
*/
+ sector_t journal_tail; /* If this device is a journal device,
+ * this is the journal tail (journal
+ * recovery start point)
+ */
+ };
atomic_t nr_pending; /* number of pending requests.
* only maintained for arrays that
@@ -172,6 +178,11 @@ enum flag_bits {
* This device is seen locally but not
* by the whole cluster
*/
+ Journal, /* This device is used as journal for
+ * raid-5/6.
+ * Usually, this device should be faster
+ * than other devices in the array
+ */
};
#define BB_LEN_MASK (0x00000000000001FFULL)
@@ -221,6 +232,8 @@ struct mddev {
#define MD_STILL_CLOSED 4 /* If set, then array has not been opened since
* md_ioctl checked on it.
*/
+#define MD_JOURNAL_CLEAN 5 /* A raid with journal is already clean */
+#define MD_HAS_JOURNAL 6 /* The raid array has journal feature set */
int suspended;
atomic_t active_io;
@@ -658,7 +671,7 @@ extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
struct mddev *mddev);
extern void md_unplug(struct blk_plug_cb *cb, bool from_schedule);
-extern void md_reload_sb(struct mddev *mddev);
+extern void md_reload_sb(struct mddev *mddev, int raid_disk);
extern void md_update_sb(struct mddev *mddev, int force);
extern void md_kick_rdev_from_array(struct md_rdev * rdev);
struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index d132f06afdd1..7331a80d89f1 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -264,7 +264,9 @@ static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
spin_unlock_irq(&conf->device_lock);
rcu_assign_pointer(p->rdev, rdev);
err = 0;
+ mddev_suspend(mddev);
md_integrity_add_rdev(rdev, mddev);
+ mddev_resume(mddev);
break;
}
diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c
index e64b61ad0ef3..431a03067d64 100644
--- a/drivers/md/persistent-data/dm-array.c
+++ b/drivers/md/persistent-data/dm-array.c
@@ -233,9 +233,9 @@ static int get_ablock(struct dm_array_info *info, dm_block_t b,
/*
* Unlocks an array block.
*/
-static int unlock_ablock(struct dm_array_info *info, struct dm_block *block)
+static void unlock_ablock(struct dm_array_info *info, struct dm_block *block)
{
- return dm_tm_unlock(info->btree_info.tm, block);
+ dm_tm_unlock(info->btree_info.tm, block);
}
/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 88dbe7b97c2c..f2393ba838eb 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -578,7 +578,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm,
}
EXPORT_SYMBOL_GPL(dm_bm_write_lock_zero);
-int dm_bm_unlock(struct dm_block *b)
+void dm_bm_unlock(struct dm_block *b)
{
struct buffer_aux *aux;
aux = dm_bufio_get_aux_data(to_buffer(b));
@@ -590,8 +590,6 @@ int dm_bm_unlock(struct dm_block *b)
bl_up_read(&aux->lock);
dm_bufio_release(to_buffer(b));
-
- return 0;
}
EXPORT_SYMBOL_GPL(dm_bm_unlock);
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
index 84330f59886d..3627d1b7667a 100644
--- a/drivers/md/persistent-data/dm-block-manager.h
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -94,7 +94,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
struct dm_block_validator *v,
struct dm_block **result);
-int dm_bm_unlock(struct dm_block *b);
+void dm_bm_unlock(struct dm_block *b);
/*
* It's a common idiom to have a superblock that should be committed last.
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h
index 8731b6ea026b..a240990a7f33 100644
--- a/drivers/md/persistent-data/dm-btree-internal.h
+++ b/drivers/md/persistent-data/dm-btree-internal.h
@@ -52,7 +52,7 @@ void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
struct dm_btree_value_type *vt);
int new_block(struct dm_btree_info *info, struct dm_block **result);
-int unlock_block(struct dm_btree_info *info, struct dm_block *b);
+void unlock_block(struct dm_btree_info *info, struct dm_block *b);
/*
* Spines keep track of the rolling locks. There are 2 variants, read-only
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index 421a36c593e3..21ea537bd55e 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -165,9 +165,9 @@ static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt
return 0;
}
-static int exit_child(struct dm_btree_info *info, struct child *c)
+static void exit_child(struct dm_btree_info *info, struct child *c)
{
- return dm_tm_unlock(info->tm, c->block);
+ dm_tm_unlock(info->tm, c->block);
}
static void shift(struct btree_node *left, struct btree_node *right, int count)
@@ -249,13 +249,10 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
__rebalance2(info, parent, &left, &right);
- r = exit_child(info, &left);
- if (r) {
- exit_child(info, &right);
- return r;
- }
+ exit_child(info, &left);
+ exit_child(info, &right);
- return exit_child(info, &right);
+ return 0;
}
/*
@@ -301,11 +298,16 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
{
int s;
uint32_t max_entries = le32_to_cpu(left->header.max_entries);
- unsigned target = (nr_left + nr_center + nr_right) / 3;
- BUG_ON(target > max_entries);
+ unsigned total = nr_left + nr_center + nr_right;
+ unsigned target_right = total / 3;
+ unsigned remainder = (target_right * 3) != total;
+ unsigned target_left = target_right + remainder;
+
+ BUG_ON(target_left > max_entries);
+ BUG_ON(target_right > max_entries);
if (nr_left < nr_right) {
- s = nr_left - target;
+ s = nr_left - target_left;
if (s < 0 && nr_center < -s) {
/* not enough in central node */
@@ -316,10 +318,10 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
} else
shift(left, center, s);
- shift(center, right, target - nr_right);
+ shift(center, right, target_right - nr_right);
} else {
- s = target - nr_right;
+ s = target_right - nr_right;
if (s > 0 && nr_center < s) {
/* not enough in central node */
shift(center, right, nr_center);
@@ -329,7 +331,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
} else
shift(center, right, s);
- shift(left, center, nr_left - target);
+ shift(left, center, nr_left - target_left);
}
*key_ptr(parent, c->index) = center->keys[0];
@@ -389,22 +391,9 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
__rebalance3(info, parent, &left, &center, &right);
- r = exit_child(info, &left);
- if (r) {
- exit_child(info, &center);
- exit_child(info, &right);
- return r;
- }
-
- r = exit_child(info, &center);
- if (r) {
- exit_child(info, &right);
- return r;
- }
-
- r = exit_child(info, &right);
- if (r)
- return r;
+ exit_child(info, &left);
+ exit_child(info, &center);
+ exit_child(info, &right);
return 0;
}
@@ -428,9 +417,7 @@ static int rebalance_children(struct shadow_spine *s,
memcpy(n, dm_block_data(child),
dm_bm_block_size(dm_tm_get_bm(info->tm)));
- r = dm_tm_unlock(info->tm, child);
- if (r)
- return r;
+ dm_tm_unlock(info->tm, child);
dm_tm_dec(info->tm, dm_block_location(child));
return 0;
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
index 0dee514ba4c5..b27b8091a1ca 100644
--- a/drivers/md/persistent-data/dm-btree-spine.c
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -117,9 +117,9 @@ int new_block(struct dm_btree_info *info, struct dm_block **result)
return dm_tm_new_block(info->tm, &btree_node_validator, result);
}
-int unlock_block(struct dm_btree_info *info, struct dm_block *b)
+void unlock_block(struct dm_btree_info *info, struct dm_block *b)
{
- return dm_tm_unlock(info->tm, b);
+ dm_tm_unlock(info->tm, b);
}
/*----------------------------------------------------------------*/
@@ -137,9 +137,7 @@ int exit_ro_spine(struct ro_spine *s)
int r = 0, i;
for (i = 0; i < s->count; i++) {
- int r2 = unlock_block(s->info, s->nodes[i]);
- if (r2 < 0)
- r = r2;
+ unlock_block(s->info, s->nodes[i]);
}
return r;
@@ -150,9 +148,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
int r;
if (s->count == 2) {
- r = unlock_block(s->info, s->nodes[0]);
- if (r < 0)
- return r;
+ unlock_block(s->info, s->nodes[0]);
s->nodes[0] = s->nodes[1];
s->count--;
}
@@ -194,9 +190,7 @@ int exit_shadow_spine(struct shadow_spine *s)
int r = 0, i;
for (i = 0; i < s->count; i++) {
- int r2 = unlock_block(s->info, s->nodes[i]);
- if (r2 < 0)
- r = r2;
+ unlock_block(s->info, s->nodes[i]);
}
return r;
@@ -208,9 +202,7 @@ int shadow_step(struct shadow_spine *s, dm_block_t b,
int r;
if (s->count == 2) {
- r = unlock_block(s->info, s->nodes[0]);
- if (r < 0)
- return r;
+ unlock_block(s->info, s->nodes[0]);
s->nodes[0] = s->nodes[1];
s->count--;
}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index b6cec258cc21..c573402033b2 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -141,7 +141,9 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
n->header.value_size = cpu_to_le32(info->value_type.size);
*root = dm_block_location(b);
- return unlock_block(info, b);
+ unlock_block(info, b);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(dm_btree_empty);
@@ -523,7 +525,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
r = new_block(s->info, &right);
if (r < 0) {
- /* FIXME: put left */
+ unlock_block(s->info, left);
return r;
}
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index aacbe70c2c2e..306d2e4502c4 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -259,9 +259,7 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
idx.blocknr = cpu_to_le64(dm_block_location(b));
- r = dm_tm_unlock(ll->tm, b);
- if (r < 0)
- return r;
+ dm_tm_unlock(ll->tm, b);
idx.nr_free = cpu_to_le32(ll->entries_per_block);
idx.none_free_before = 0;
@@ -293,7 +291,9 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
*result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
- return dm_tm_unlock(ll->tm, blk);
+ dm_tm_unlock(ll->tm, blk);
+
+ return 0;
}
static int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b,
@@ -373,9 +373,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
return r;
}
- r = dm_tm_unlock(ll->tm, blk);
- if (r < 0)
- return r;
+ dm_tm_unlock(ll->tm, blk);
*result = i * ll->entries_per_block + (dm_block_t) position;
return 0;
@@ -429,9 +427,7 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
if (ref_count <= 2) {
sm_set_bitmap(bm_le, bit, ref_count);
- r = dm_tm_unlock(ll->tm, nb);
- if (r < 0)
- return r;
+ dm_tm_unlock(ll->tm, nb);
if (old > 2) {
r = dm_btree_remove(&ll->ref_count_info,
@@ -445,9 +441,7 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
__le32 le_rc = cpu_to_le32(ref_count);
sm_set_bitmap(bm_le, bit, 3);
- r = dm_tm_unlock(ll->tm, nb);
- if (r < 0)
- return r;
+ dm_tm_unlock(ll->tm, nb);
__dm_bless_for_disk(&le_rc);
r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
@@ -556,7 +550,9 @@ static int metadata_ll_init_index(struct ll_disk *ll)
memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
ll->bitmap_root = dm_block_location(b);
- return dm_tm_unlock(ll->tm, b);
+ dm_tm_unlock(ll->tm, b);
+
+ return 0;
}
static int metadata_ll_open(struct ll_disk *ll)
@@ -570,7 +566,9 @@ static int metadata_ll_open(struct ll_disk *ll)
return r;
memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
- return dm_tm_unlock(ll->tm, block);
+ dm_tm_unlock(ll->tm, block);
+
+ return 0;
}
static dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
@@ -590,7 +588,9 @@ static int metadata_ll_commit(struct ll_disk *ll)
memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
ll->bitmap_root = dm_block_location(b);
- return dm_tm_unlock(ll->tm, b);
+ dm_tm_unlock(ll->tm, b);
+
+ return 0;
}
int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
index 9cb797d800cf..abe2c5dd0993 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.c
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -342,9 +342,9 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
}
EXPORT_SYMBOL_GPL(dm_tm_read_lock);
-int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
+void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
{
- return dm_bm_unlock(b);
+ dm_bm_unlock(b);
}
EXPORT_SYMBOL_GPL(dm_tm_unlock);
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h
index 2e0d4d66fb1b..f3a18be68f30 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.h
+++ b/drivers/md/persistent-data/dm-transaction-manager.h
@@ -94,7 +94,7 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
struct dm_block_validator *v,
struct dm_block **result);
-int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
+void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
/*
* Functions for altering the reference count of a block directly.
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ddd8a5f572aa..e2169ff6e0f0 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -90,6 +90,8 @@ static void r1bio_pool_free(void *r1_bio, void *data)
#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
#define RESYNC_WINDOW (RESYNC_BLOCK_SIZE * RESYNC_DEPTH)
#define RESYNC_WINDOW_SECTORS (RESYNC_WINDOW >> 9)
+#define CLUSTER_RESYNC_WINDOW (16 * RESYNC_WINDOW)
+#define CLUSTER_RESYNC_WINDOW_SECTORS (CLUSTER_RESYNC_WINDOW >> 9)
#define NEXT_NORMALIO_DISTANCE (3 * RESYNC_WINDOW_SECTORS)
static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
@@ -1590,6 +1592,15 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
+ /*
+ * find the disk ... but prefer rdev->saved_raid_disk
+ * if possible.
+ */
+ if (rdev->saved_raid_disk >= 0 &&
+ rdev->saved_raid_disk >= first &&
+ conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+ first = last = rdev->saved_raid_disk;
+
for (mirror = first; mirror <= last; mirror++) {
p = conf->mirrors+mirror;
if (!p->rdev) {
@@ -1621,7 +1632,9 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
break;
}
}
+ mddev_suspend(mddev);
md_integrity_add_rdev(rdev, mddev);
+ mddev_resume(mddev);
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
print_conf(conf);
@@ -2195,7 +2208,7 @@ static int narrow_write_error(struct r1bio *r1_bio, int i)
bio_trim(wbio, sector - r1_bio->sector, sectors);
wbio->bi_iter.bi_sector += rdev->data_offset;
wbio->bi_bdev = rdev->bdev;
- if (submit_bio_wait(WRITE, wbio) == 0)
+ if (submit_bio_wait(WRITE, wbio) < 0)
/* failure! */
ok = rdev_set_badblocks(rdev, sector,
sectors, 0)
@@ -2258,15 +2271,16 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
rdev_dec_pending(conf->mirrors[m].rdev,
conf->mddev);
}
- if (test_bit(R1BIO_WriteError, &r1_bio->state))
- close_write(r1_bio);
if (fail) {
spin_lock_irq(&conf->device_lock);
list_add(&r1_bio->retry_list, &conf->bio_end_io_list);
spin_unlock_irq(&conf->device_lock);
md_wakeup_thread(conf->mddev->thread);
- } else
+ } else {
+ if (test_bit(R1BIO_WriteError, &r1_bio->state))
+ close_write(r1_bio);
raid_end_bio_io(r1_bio);
+ }
}
static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
@@ -2385,6 +2399,10 @@ static void raid1d(struct md_thread *thread)
r1_bio = list_first_entry(&tmp, struct r1bio,
retry_list);
list_del(&r1_bio->retry_list);
+ if (mddev->degraded)
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ if (test_bit(R1BIO_WriteError, &r1_bio->state))
+ close_write(r1_bio);
raid_end_bio_io(r1_bio);
}
}
@@ -2488,6 +2506,11 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
bitmap_close_sync(mddev->bitmap);
close_sync(conf);
+
+ if (mddev_is_clustered(mddev)) {
+ conf->cluster_sync_low = 0;
+ conf->cluster_sync_high = 0;
+ }
return 0;
}
@@ -2508,7 +2531,12 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
return sync_blocks;
}
- bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+ /* we are incrementing sector_nr below. To be safe, we check against
+ * sector_nr + two times RESYNC_SECTORS
+ */
+
+ bitmap_cond_end_sync(mddev->bitmap, sector_nr,
+ mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
raise_barrier(conf, sector_nr);
@@ -2699,6 +2727,16 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
bio_full:
r1_bio->sectors = nr_sectors;
+ if (mddev_is_clustered(mddev) &&
+ conf->cluster_sync_high < sector_nr + nr_sectors) {
+ conf->cluster_sync_low = mddev->curr_resync_completed;
+ conf->cluster_sync_high = conf->cluster_sync_low + CLUSTER_RESYNC_WINDOW_SECTORS;
+ /* Send resync message */
+ md_cluster_ops->resync_info_update(mddev,
+ conf->cluster_sync_low,
+ conf->cluster_sync_high);
+ }
+
/* For a user-requested sync, we read all readable devices and do a
* compare
*/
@@ -3013,9 +3051,11 @@ static int raid1_reshape(struct mddev *mddev)
return -EINVAL;
}
- err = md_allow_write(mddev);
- if (err)
- return err;
+ if (!mddev_is_clustered(mddev)) {
+ err = md_allow_write(mddev);
+ if (err)
+ return err;
+ }
raid_disks = mddev->raid_disks + mddev->delta_disks;
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index c52d7139c5d7..61c39b390cd8 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -111,6 +111,13 @@ struct r1conf {
* the new thread here until we fully activate the array.
*/
struct md_thread *thread;
+
+ /* Keep track of cluster resync window to send to other
+ * nodes.
+ */
+ sector_t cluster_sync_low;
+ sector_t cluster_sync_high;
+
};
/*
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9f69dc526f8c..41d70bc9ba2f 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -39,6 +39,7 @@
* far_copies (stored in second byte of layout)
* far_offset (stored in bit 16 of layout )
* use_far_sets (stored in bit 17 of layout )
+ * use_far_sets_bugfixed (stored in bit 18 of layout )
*
* The data to be stored is divided into chunks using chunksize. Each device
* is divided into far_copies sections. In each section, chunks are laid out
@@ -1497,6 +1498,8 @@ static void status(struct seq_file *seq, struct mddev *mddev)
seq_printf(seq, " %d offset-copies", conf->geo.far_copies);
else
seq_printf(seq, " %d far-copies", conf->geo.far_copies);
+ if (conf->geo.far_set_size != conf->geo.raid_disks)
+ seq_printf(seq, " %d devices per set", conf->geo.far_set_size);
}
seq_printf(seq, " [%d/%d] [", conf->geo.raid_disks,
conf->geo.raid_disks - mddev->degraded);
@@ -1736,7 +1739,9 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
rcu_assign_pointer(p->rdev, rdev);
break;
}
+ mddev_suspend(mddev);
md_integrity_add_rdev(rdev, mddev);
+ mddev_resume(mddev);
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
@@ -2467,7 +2472,7 @@ static int narrow_write_error(struct r10bio *r10_bio, int i)
choose_data_offset(r10_bio, rdev) +
(sector - r10_bio->sector));
wbio->bi_bdev = rdev->bdev;
- if (submit_bio_wait(WRITE, wbio) == 0)
+ if (submit_bio_wait(WRITE, wbio) < 0)
/* Failure! */
ok = rdev_set_badblocks(rdev, sector,
sectors, 0)
@@ -2654,16 +2659,17 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
rdev_dec_pending(rdev, conf->mddev);
}
}
- if (test_bit(R10BIO_WriteError,
- &r10_bio->state))
- close_write(r10_bio);
if (fail) {
spin_lock_irq(&conf->device_lock);
list_add(&r10_bio->retry_list, &conf->bio_end_io_list);
spin_unlock_irq(&conf->device_lock);
md_wakeup_thread(conf->mddev->thread);
- } else
+ } else {
+ if (test_bit(R10BIO_WriteError,
+ &r10_bio->state))
+ close_write(r10_bio);
raid_end_bio_io(r10_bio);
+ }
}
}
@@ -2691,6 +2697,12 @@ static void raid10d(struct md_thread *thread)
r10_bio = list_first_entry(&tmp, struct r10bio,
retry_list);
list_del(&r10_bio->retry_list);
+ if (mddev->degraded)
+ set_bit(R10BIO_Degraded, &r10_bio->state);
+
+ if (test_bit(R10BIO_WriteError,
+ &r10_bio->state))
+ close_write(r10_bio);
raid_end_bio_io(r10_bio);
}
}
@@ -3137,7 +3149,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
/* resync. Schedule a read for every block at this virt offset */
int count = 0;
- bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+ bitmap_cond_end_sync(mddev->bitmap, sector_nr, 0);
if (!bitmap_start_sync(mddev->bitmap, sector_nr,
&sync_blocks, mddev->degraded) &&
@@ -3387,7 +3399,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
disks = mddev->raid_disks + mddev->delta_disks;
break;
}
- if (layout >> 18)
+ if (layout >> 19)
return -1;
if (chunk < (PAGE_SIZE >> 9) ||
!is_power_of_2(chunk))
@@ -3399,7 +3411,22 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
geo->near_copies = nc;
geo->far_copies = fc;
geo->far_offset = fo;
- geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks;
+ switch (layout >> 17) {
+ case 0: /* original layout. simple but not always optimal */
+ geo->far_set_size = disks;
+ break;
+ case 1: /* "improved" layout which was buggy. Hopefully no-one is
+ * actually using this, but leave code here just in case.*/
+ geo->far_set_size = disks/fc;
+ WARN(geo->far_set_size < fc,
+ "This RAID10 layout does not provide data safety - please backup and create new array\n");
+ break;
+ case 2: /* "improved" layout fixed to match documentation */
+ geo->far_set_size = fc * nc;
+ break;
+ default: /* Not a valid layout */
+ return -1;
+ }
geo->chunk_mask = chunk - 1;
geo->chunk_shift = ffz(~chunk);
return nc*fc;
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
new file mode 100644
index 000000000000..b887e04d7e5c
--- /dev/null
+++ b/drivers/md/raid5-cache.c
@@ -0,0 +1,1191 @@
+/*
+ * Copyright (C) 2015 Shaohua Li <shli@fb.com>
+ *
+ * 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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/blkdev.h>
+#include <linux/slab.h>
+#include <linux/raid/md_p.h>
+#include <linux/crc32c.h>
+#include <linux/random.h>
+#include "md.h"
+#include "raid5.h"
+
+/*
+ * metadata/data stored in disk with 4k size unit (a block) regardless
+ * underneath hardware sector size. only works with PAGE_SIZE == 4096
+ */
+#define BLOCK_SECTORS (8)
+
+/*
+ * reclaim runs every 1/4 disk size or 10G reclaimable space. This can prevent
+ * recovery scans a very long log
+ */
+#define RECLAIM_MAX_FREE_SPACE (10 * 1024 * 1024 * 2) /* sector */
+#define RECLAIM_MAX_FREE_SPACE_SHIFT (2)
+
+struct r5l_log {
+ struct md_rdev *rdev;
+
+ u32 uuid_checksum;
+
+ sector_t device_size; /* log device size, round to
+ * BLOCK_SECTORS */
+ sector_t max_free_space; /* reclaim run if free space is at
+ * this size */
+
+ sector_t last_checkpoint; /* log tail. where recovery scan
+ * starts from */
+ u64 last_cp_seq; /* log tail sequence */
+
+ sector_t log_start; /* log head. where new data appends */
+ u64 seq; /* log head sequence */
+
+ sector_t next_checkpoint;
+ u64 next_cp_seq;
+
+ struct mutex io_mutex;
+ struct r5l_io_unit *current_io; /* current io_unit accepting new data */
+
+ spinlock_t io_list_lock;
+ struct list_head running_ios; /* io_units which are still running,
+ * and have not yet been completely
+ * written to the log */
+ struct list_head io_end_ios; /* io_units which have been completely
+ * written to the log but not yet written
+ * to the RAID */
+ struct list_head flushing_ios; /* io_units which are waiting for log
+ * cache flush */
+ struct list_head finished_ios; /* io_units which settle down in log disk */
+ struct bio flush_bio;
+
+ struct kmem_cache *io_kc;
+
+ struct md_thread *reclaim_thread;
+ unsigned long reclaim_target; /* number of space that need to be
+ * reclaimed. if it's 0, reclaim spaces
+ * used by io_units which are in
+ * IO_UNIT_STRIPE_END state (eg, reclaim
+ * dones't wait for specific io_unit
+ * switching to IO_UNIT_STRIPE_END
+ * state) */
+ wait_queue_head_t iounit_wait;
+
+ struct list_head no_space_stripes; /* pending stripes, log has no space */
+ spinlock_t no_space_stripes_lock;
+
+ bool need_cache_flush;
+ bool in_teardown;
+};
+
+/*
+ * an IO range starts from a meta data block and end at the next meta data
+ * block. The io unit's the meta data block tracks data/parity followed it. io
+ * unit is written to log disk with normal write, as we always flush log disk
+ * first and then start move data to raid disks, there is no requirement to
+ * write io unit with FLUSH/FUA
+ */
+struct r5l_io_unit {
+ struct r5l_log *log;
+
+ struct page *meta_page; /* store meta block */
+ int meta_offset; /* current offset in meta_page */
+
+ struct bio *current_bio;/* current_bio accepting new data */
+
+ atomic_t pending_stripe;/* how many stripes not flushed to raid */
+ u64 seq; /* seq number of the metablock */
+ sector_t log_start; /* where the io_unit starts */
+ sector_t log_end; /* where the io_unit ends */
+ struct list_head log_sibling; /* log->running_ios */
+ struct list_head stripe_list; /* stripes added to the io_unit */
+
+ int state;
+ bool need_split_bio;
+};
+
+/* r5l_io_unit state */
+enum r5l_io_unit_state {
+ IO_UNIT_RUNNING = 0, /* accepting new IO */
+ IO_UNIT_IO_START = 1, /* io_unit bio start writing to log,
+ * don't accepting new bio */
+ IO_UNIT_IO_END = 2, /* io_unit bio finish writing to log */
+ IO_UNIT_STRIPE_END = 3, /* stripes data finished writing to raid */
+};
+
+static sector_t r5l_ring_add(struct r5l_log *log, sector_t start, sector_t inc)
+{
+ start += inc;
+ if (start >= log->device_size)
+ start = start - log->device_size;
+ return start;
+}
+
+static sector_t r5l_ring_distance(struct r5l_log *log, sector_t start,
+ sector_t end)
+{
+ if (end >= start)
+ return end - start;
+ else
+ return end + log->device_size - start;
+}
+
+static bool r5l_has_free_space(struct r5l_log *log, sector_t size)
+{
+ sector_t used_size;
+
+ used_size = r5l_ring_distance(log, log->last_checkpoint,
+ log->log_start);
+
+ return log->device_size > used_size + size;
+}
+
+static void r5l_free_io_unit(struct r5l_log *log, struct r5l_io_unit *io)
+{
+ __free_page(io->meta_page);
+ kmem_cache_free(log->io_kc, io);
+}
+
+static void r5l_move_io_unit_list(struct list_head *from, struct list_head *to,
+ enum r5l_io_unit_state state)
+{
+ struct r5l_io_unit *io;
+
+ while (!list_empty(from)) {
+ io = list_first_entry(from, struct r5l_io_unit, log_sibling);
+ /* don't change list order */
+ if (io->state >= state)
+ list_move_tail(&io->log_sibling, to);
+ else
+ break;
+ }
+}
+
+static void __r5l_set_io_unit_state(struct r5l_io_unit *io,
+ enum r5l_io_unit_state state)
+{
+ if (WARN_ON(io->state >= state))
+ return;
+ io->state = state;
+}
+
+static void r5l_io_run_stripes(struct r5l_io_unit *io)
+{
+ struct stripe_head *sh, *next;
+
+ list_for_each_entry_safe(sh, next, &io->stripe_list, log_list) {
+ list_del_init(&sh->log_list);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ raid5_release_stripe(sh);
+ }
+}
+
+static void r5l_log_run_stripes(struct r5l_log *log)
+{
+ struct r5l_io_unit *io, *next;
+
+ assert_spin_locked(&log->io_list_lock);
+
+ list_for_each_entry_safe(io, next, &log->running_ios, log_sibling) {
+ /* don't change list order */
+ if (io->state < IO_UNIT_IO_END)
+ break;
+
+ list_move_tail(&io->log_sibling, &log->finished_ios);
+ r5l_io_run_stripes(io);
+ }
+}
+
+static void r5l_log_endio(struct bio *bio)
+{
+ struct r5l_io_unit *io = bio->bi_private;
+ struct r5l_log *log = io->log;
+ unsigned long flags;
+
+ if (bio->bi_error)
+ md_error(log->rdev->mddev, log->rdev);
+
+ bio_put(bio);
+
+ spin_lock_irqsave(&log->io_list_lock, flags);
+ __r5l_set_io_unit_state(io, IO_UNIT_IO_END);
+ if (log->need_cache_flush)
+ r5l_move_io_unit_list(&log->running_ios, &log->io_end_ios,
+ IO_UNIT_IO_END);
+ else
+ r5l_log_run_stripes(log);
+ spin_unlock_irqrestore(&log->io_list_lock, flags);
+
+ if (log->need_cache_flush)
+ md_wakeup_thread(log->rdev->mddev->thread);
+}
+
+static void r5l_submit_current_io(struct r5l_log *log)
+{
+ struct r5l_io_unit *io = log->current_io;
+ struct r5l_meta_block *block;
+ unsigned long flags;
+ u32 crc;
+
+ if (!io)
+ return;
+
+ block = page_address(io->meta_page);
+ block->meta_size = cpu_to_le32(io->meta_offset);
+ crc = crc32c_le(log->uuid_checksum, block, PAGE_SIZE);
+ block->checksum = cpu_to_le32(crc);
+
+ log->current_io = NULL;
+ spin_lock_irqsave(&log->io_list_lock, flags);
+ __r5l_set_io_unit_state(io, IO_UNIT_IO_START);
+ spin_unlock_irqrestore(&log->io_list_lock, flags);
+
+ submit_bio(WRITE, io->current_bio);
+}
+
+static struct bio *r5l_bio_alloc(struct r5l_log *log)
+{
+ struct bio *bio = bio_kmalloc(GFP_NOIO | __GFP_NOFAIL, BIO_MAX_PAGES);
+
+ bio->bi_rw = WRITE;
+ bio->bi_bdev = log->rdev->bdev;
+ bio->bi_iter.bi_sector = log->rdev->data_offset + log->log_start;
+
+ return bio;
+}
+
+static void r5_reserve_log_entry(struct r5l_log *log, struct r5l_io_unit *io)
+{
+ log->log_start = r5l_ring_add(log, log->log_start, BLOCK_SECTORS);
+
+ /*
+ * If we filled up the log device start from the beginning again,
+ * which will require a new bio.
+ *
+ * Note: for this to work properly the log size needs to me a multiple
+ * of BLOCK_SECTORS.
+ */
+ if (log->log_start == 0)
+ io->need_split_bio = true;
+
+ io->log_end = log->log_start;
+}
+
+static struct r5l_io_unit *r5l_new_meta(struct r5l_log *log)
+{
+ struct r5l_io_unit *io;
+ struct r5l_meta_block *block;
+
+ /* We can't handle memory allocate failure so far */
+ io = kmem_cache_zalloc(log->io_kc, GFP_NOIO | __GFP_NOFAIL);
+ io->log = log;
+ INIT_LIST_HEAD(&io->log_sibling);
+ INIT_LIST_HEAD(&io->stripe_list);
+ io->state = IO_UNIT_RUNNING;
+
+ io->meta_page = alloc_page(GFP_NOIO | __GFP_NOFAIL | __GFP_ZERO);
+ block = page_address(io->meta_page);
+ block->magic = cpu_to_le32(R5LOG_MAGIC);
+ block->version = R5LOG_VERSION;
+ block->seq = cpu_to_le64(log->seq);
+ block->position = cpu_to_le64(log->log_start);
+
+ io->log_start = log->log_start;
+ io->meta_offset = sizeof(struct r5l_meta_block);
+ io->seq = log->seq++;
+
+ io->current_bio = r5l_bio_alloc(log);
+ io->current_bio->bi_end_io = r5l_log_endio;
+ io->current_bio->bi_private = io;
+ bio_add_page(io->current_bio, io->meta_page, PAGE_SIZE, 0);
+
+ r5_reserve_log_entry(log, io);
+
+ spin_lock_irq(&log->io_list_lock);
+ list_add_tail(&io->log_sibling, &log->running_ios);
+ spin_unlock_irq(&log->io_list_lock);
+
+ return io;
+}
+
+static int r5l_get_meta(struct r5l_log *log, unsigned int payload_size)
+{
+ if (log->current_io &&
+ log->current_io->meta_offset + payload_size > PAGE_SIZE)
+ r5l_submit_current_io(log);
+
+ if (!log->current_io)
+ log->current_io = r5l_new_meta(log);
+ return 0;
+}
+
+static void r5l_append_payload_meta(struct r5l_log *log, u16 type,
+ sector_t location,
+ u32 checksum1, u32 checksum2,
+ bool checksum2_valid)
+{
+ struct r5l_io_unit *io = log->current_io;
+ struct r5l_payload_data_parity *payload;
+
+ payload = page_address(io->meta_page) + io->meta_offset;
+ payload->header.type = cpu_to_le16(type);
+ payload->header.flags = cpu_to_le16(0);
+ payload->size = cpu_to_le32((1 + !!checksum2_valid) <<
+ (PAGE_SHIFT - 9));
+ payload->location = cpu_to_le64(location);
+ payload->checksum[0] = cpu_to_le32(checksum1);
+ if (checksum2_valid)
+ payload->checksum[1] = cpu_to_le32(checksum2);
+
+ io->meta_offset += sizeof(struct r5l_payload_data_parity) +
+ sizeof(__le32) * (1 + !!checksum2_valid);
+}
+
+static void r5l_append_payload_page(struct r5l_log *log, struct page *page)
+{
+ struct r5l_io_unit *io = log->current_io;
+
+ if (io->need_split_bio) {
+ struct bio *prev = io->current_bio;
+
+ io->current_bio = r5l_bio_alloc(log);
+ bio_chain(io->current_bio, prev);
+
+ submit_bio(WRITE, prev);
+ }
+
+ if (!bio_add_page(io->current_bio, page, PAGE_SIZE, 0))
+ BUG();
+
+ r5_reserve_log_entry(log, io);
+}
+
+static void r5l_log_stripe(struct r5l_log *log, struct stripe_head *sh,
+ int data_pages, int parity_pages)
+{
+ int i;
+ int meta_size;
+ struct r5l_io_unit *io;
+
+ meta_size =
+ ((sizeof(struct r5l_payload_data_parity) + sizeof(__le32))
+ * data_pages) +
+ sizeof(struct r5l_payload_data_parity) +
+ sizeof(__le32) * parity_pages;
+
+ r5l_get_meta(log, meta_size);
+ io = log->current_io;
+
+ for (i = 0; i < sh->disks; i++) {
+ if (!test_bit(R5_Wantwrite, &sh->dev[i].flags))
+ continue;
+ if (i == sh->pd_idx || i == sh->qd_idx)
+ continue;
+ r5l_append_payload_meta(log, R5LOG_PAYLOAD_DATA,
+ raid5_compute_blocknr(sh, i, 0),
+ sh->dev[i].log_checksum, 0, false);
+ r5l_append_payload_page(log, sh->dev[i].page);
+ }
+
+ if (sh->qd_idx >= 0) {
+ r5l_append_payload_meta(log, R5LOG_PAYLOAD_PARITY,
+ sh->sector, sh->dev[sh->pd_idx].log_checksum,
+ sh->dev[sh->qd_idx].log_checksum, true);
+ r5l_append_payload_page(log, sh->dev[sh->pd_idx].page);
+ r5l_append_payload_page(log, sh->dev[sh->qd_idx].page);
+ } else {
+ r5l_append_payload_meta(log, R5LOG_PAYLOAD_PARITY,
+ sh->sector, sh->dev[sh->pd_idx].log_checksum,
+ 0, false);
+ r5l_append_payload_page(log, sh->dev[sh->pd_idx].page);
+ }
+
+ list_add_tail(&sh->log_list, &io->stripe_list);
+ atomic_inc(&io->pending_stripe);
+ sh->log_io = io;
+}
+
+static void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
+/*
+ * running in raid5d, where reclaim could wait for raid5d too (when it flushes
+ * data from log to raid disks), so we shouldn't wait for reclaim here
+ */
+int r5l_write_stripe(struct r5l_log *log, struct stripe_head *sh)
+{
+ int write_disks = 0;
+ int data_pages, parity_pages;
+ int meta_size;
+ int reserve;
+ int i;
+
+ if (!log)
+ return -EAGAIN;
+ /* Don't support stripe batch */
+ if (sh->log_io || !test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags) ||
+ test_bit(STRIPE_SYNCING, &sh->state)) {
+ /* the stripe is written to log, we start writing it to raid */
+ clear_bit(STRIPE_LOG_TRAPPED, &sh->state);
+ return -EAGAIN;
+ }
+
+ for (i = 0; i < sh->disks; i++) {
+ void *addr;
+
+ if (!test_bit(R5_Wantwrite, &sh->dev[i].flags))
+ continue;
+ write_disks++;
+ /* checksum is already calculated in last run */
+ if (test_bit(STRIPE_LOG_TRAPPED, &sh->state))
+ continue;
+ addr = kmap_atomic(sh->dev[i].page);
+ sh->dev[i].log_checksum = crc32c_le(log->uuid_checksum,
+ addr, PAGE_SIZE);
+ kunmap_atomic(addr);
+ }
+ parity_pages = 1 + !!(sh->qd_idx >= 0);
+ data_pages = write_disks - parity_pages;
+
+ meta_size =
+ ((sizeof(struct r5l_payload_data_parity) + sizeof(__le32))
+ * data_pages) +
+ sizeof(struct r5l_payload_data_parity) +
+ sizeof(__le32) * parity_pages;
+ /* Doesn't work with very big raid array */
+ if (meta_size + sizeof(struct r5l_meta_block) > PAGE_SIZE)
+ return -EINVAL;
+
+ set_bit(STRIPE_LOG_TRAPPED, &sh->state);
+ /*
+ * The stripe must enter state machine again to finish the write, so
+ * don't delay.
+ */
+ clear_bit(STRIPE_DELAYED, &sh->state);
+ atomic_inc(&sh->count);
+
+ mutex_lock(&log->io_mutex);
+ /* meta + data */
+ reserve = (1 + write_disks) << (PAGE_SHIFT - 9);
+ if (r5l_has_free_space(log, reserve))
+ r5l_log_stripe(log, sh, data_pages, parity_pages);
+ else {
+ spin_lock(&log->no_space_stripes_lock);
+ list_add_tail(&sh->log_list, &log->no_space_stripes);
+ spin_unlock(&log->no_space_stripes_lock);
+
+ r5l_wake_reclaim(log, reserve);
+ }
+ mutex_unlock(&log->io_mutex);
+
+ return 0;
+}
+
+void r5l_write_stripe_run(struct r5l_log *log)
+{
+ if (!log)
+ return;
+ mutex_lock(&log->io_mutex);
+ r5l_submit_current_io(log);
+ mutex_unlock(&log->io_mutex);
+}
+
+int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio)
+{
+ if (!log)
+ return -ENODEV;
+ /*
+ * we flush log disk cache first, then write stripe data to raid disks.
+ * So if bio is finished, the log disk cache is flushed already. The
+ * recovery guarantees we can recovery the bio from log disk, so we
+ * don't need to flush again
+ */
+ if (bio->bi_iter.bi_size == 0) {
+ bio_endio(bio);
+ return 0;
+ }
+ bio->bi_rw &= ~REQ_FLUSH;
+ return -EAGAIN;
+}
+
+/* This will run after log space is reclaimed */
+static void r5l_run_no_space_stripes(struct r5l_log *log)
+{
+ struct stripe_head *sh;
+
+ spin_lock(&log->no_space_stripes_lock);
+ while (!list_empty(&log->no_space_stripes)) {
+ sh = list_first_entry(&log->no_space_stripes,
+ struct stripe_head, log_list);
+ list_del_init(&sh->log_list);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ raid5_release_stripe(sh);
+ }
+ spin_unlock(&log->no_space_stripes_lock);
+}
+
+static sector_t r5l_reclaimable_space(struct r5l_log *log)
+{
+ return r5l_ring_distance(log, log->last_checkpoint,
+ log->next_checkpoint);
+}
+
+static bool r5l_complete_finished_ios(struct r5l_log *log)
+{
+ struct r5l_io_unit *io, *next;
+ bool found = false;
+
+ assert_spin_locked(&log->io_list_lock);
+
+ list_for_each_entry_safe(io, next, &log->finished_ios, log_sibling) {
+ /* don't change list order */
+ if (io->state < IO_UNIT_STRIPE_END)
+ break;
+
+ log->next_checkpoint = io->log_start;
+ log->next_cp_seq = io->seq;
+
+ list_del(&io->log_sibling);
+ r5l_free_io_unit(log, io);
+
+ found = true;
+ }
+
+ return found;
+}
+
+static void __r5l_stripe_write_finished(struct r5l_io_unit *io)
+{
+ struct r5l_log *log = io->log;
+ unsigned long flags;
+
+ spin_lock_irqsave(&log->io_list_lock, flags);
+ __r5l_set_io_unit_state(io, IO_UNIT_STRIPE_END);
+
+ if (!r5l_complete_finished_ios(log)) {
+ spin_unlock_irqrestore(&log->io_list_lock, flags);
+ return;
+ }
+
+ if (r5l_reclaimable_space(log) > log->max_free_space)
+ r5l_wake_reclaim(log, 0);
+
+ spin_unlock_irqrestore(&log->io_list_lock, flags);
+ wake_up(&log->iounit_wait);
+}
+
+void r5l_stripe_write_finished(struct stripe_head *sh)
+{
+ struct r5l_io_unit *io;
+
+ io = sh->log_io;
+ sh->log_io = NULL;
+
+ if (io && atomic_dec_and_test(&io->pending_stripe))
+ __r5l_stripe_write_finished(io);
+}
+
+static void r5l_log_flush_endio(struct bio *bio)
+{
+ struct r5l_log *log = container_of(bio, struct r5l_log,
+ flush_bio);
+ unsigned long flags;
+ struct r5l_io_unit *io;
+
+ if (bio->bi_error)
+ md_error(log->rdev->mddev, log->rdev);
+
+ spin_lock_irqsave(&log->io_list_lock, flags);
+ list_for_each_entry(io, &log->flushing_ios, log_sibling)
+ r5l_io_run_stripes(io);
+ list_splice_tail_init(&log->flushing_ios, &log->finished_ios);
+ spin_unlock_irqrestore(&log->io_list_lock, flags);
+}
+
+/*
+ * Starting dispatch IO to raid.
+ * io_unit(meta) consists of a log. There is one situation we want to avoid. A
+ * broken meta in the middle of a log causes recovery can't find meta at the
+ * head of log. If operations require meta at the head persistent in log, we
+ * must make sure meta before it persistent in log too. A case is:
+ *
+ * stripe data/parity is in log, we start write stripe to raid disks. stripe
+ * data/parity must be persistent in log before we do the write to raid disks.
+ *
+ * The solution is we restrictly maintain io_unit list order. In this case, we
+ * only write stripes of an io_unit to raid disks till the io_unit is the first
+ * one whose data/parity is in log.
+ */
+void r5l_flush_stripe_to_raid(struct r5l_log *log)
+{
+ bool do_flush;
+
+ if (!log || !log->need_cache_flush)
+ return;
+
+ spin_lock_irq(&log->io_list_lock);
+ /* flush bio is running */
+ if (!list_empty(&log->flushing_ios)) {
+ spin_unlock_irq(&log->io_list_lock);
+ return;
+ }
+ list_splice_tail_init(&log->io_end_ios, &log->flushing_ios);
+ do_flush = !list_empty(&log->flushing_ios);
+ spin_unlock_irq(&log->io_list_lock);
+
+ if (!do_flush)
+ return;
+ bio_reset(&log->flush_bio);
+ log->flush_bio.bi_bdev = log->rdev->bdev;
+ log->flush_bio.bi_end_io = r5l_log_flush_endio;
+ submit_bio(WRITE_FLUSH, &log->flush_bio);
+}
+
+static void r5l_write_super(struct r5l_log *log, sector_t cp);
+static void r5l_write_super_and_discard_space(struct r5l_log *log,
+ sector_t end)
+{
+ struct block_device *bdev = log->rdev->bdev;
+ struct mddev *mddev;
+
+ r5l_write_super(log, end);
+
+ if (!blk_queue_discard(bdev_get_queue(bdev)))
+ return;
+
+ mddev = log->rdev->mddev;
+ /*
+ * This is to avoid a deadlock. r5l_quiesce holds reconfig_mutex and
+ * wait for this thread to finish. This thread waits for
+ * MD_CHANGE_PENDING clear, which is supposed to be done in
+ * md_check_recovery(). md_check_recovery() tries to get
+ * reconfig_mutex. Since r5l_quiesce already holds the mutex,
+ * md_check_recovery() fails, so the PENDING never get cleared. The
+ * in_teardown check workaround this issue.
+ */
+ if (!log->in_teardown) {
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+ set_bit(MD_CHANGE_PENDING, &mddev->flags);
+ md_wakeup_thread(mddev->thread);
+ wait_event(mddev->sb_wait,
+ !test_bit(MD_CHANGE_PENDING, &mddev->flags) ||
+ log->in_teardown);
+ /*
+ * r5l_quiesce could run after in_teardown check and hold
+ * mutex first. Superblock might get updated twice.
+ */
+ if (log->in_teardown)
+ md_update_sb(mddev, 1);
+ } else {
+ WARN_ON(!mddev_is_locked(mddev));
+ md_update_sb(mddev, 1);
+ }
+
+ /* discard IO error really doesn't matter, ignore it */
+ if (log->last_checkpoint < end) {
+ blkdev_issue_discard(bdev,
+ log->last_checkpoint + log->rdev->data_offset,
+ end - log->last_checkpoint, GFP_NOIO, 0);
+ } else {
+ blkdev_issue_discard(bdev,
+ log->last_checkpoint + log->rdev->data_offset,
+ log->device_size - log->last_checkpoint,
+ GFP_NOIO, 0);
+ blkdev_issue_discard(bdev, log->rdev->data_offset, end,
+ GFP_NOIO, 0);
+ }
+}
+
+
+static void r5l_do_reclaim(struct r5l_log *log)
+{
+ sector_t reclaim_target = xchg(&log->reclaim_target, 0);
+ sector_t reclaimable;
+ sector_t next_checkpoint;
+ u64 next_cp_seq;
+
+ spin_lock_irq(&log->io_list_lock);
+ /*
+ * move proper io_unit to reclaim list. We should not change the order.
+ * reclaimable/unreclaimable io_unit can be mixed in the list, we
+ * shouldn't reuse space of an unreclaimable io_unit
+ */
+ while (1) {
+ reclaimable = r5l_reclaimable_space(log);
+ if (reclaimable >= reclaim_target ||
+ (list_empty(&log->running_ios) &&
+ list_empty(&log->io_end_ios) &&
+ list_empty(&log->flushing_ios) &&
+ list_empty(&log->finished_ios)))
+ break;
+
+ md_wakeup_thread(log->rdev->mddev->thread);
+ wait_event_lock_irq(log->iounit_wait,
+ r5l_reclaimable_space(log) > reclaimable,
+ log->io_list_lock);
+ }
+
+ next_checkpoint = log->next_checkpoint;
+ next_cp_seq = log->next_cp_seq;
+ spin_unlock_irq(&log->io_list_lock);
+
+ BUG_ON(reclaimable < 0);
+ if (reclaimable == 0)
+ return;
+
+ /*
+ * write_super will flush cache of each raid disk. We must write super
+ * here, because the log area might be reused soon and we don't want to
+ * confuse recovery
+ */
+ r5l_write_super_and_discard_space(log, next_checkpoint);
+
+ mutex_lock(&log->io_mutex);
+ log->last_checkpoint = next_checkpoint;
+ log->last_cp_seq = next_cp_seq;
+ mutex_unlock(&log->io_mutex);
+
+ r5l_run_no_space_stripes(log);
+}
+
+static void r5l_reclaim_thread(struct md_thread *thread)
+{
+ struct mddev *mddev = thread->mddev;
+ struct r5conf *conf = mddev->private;
+ struct r5l_log *log = conf->log;
+
+ if (!log)
+ return;
+ r5l_do_reclaim(log);
+}
+
+static void r5l_wake_reclaim(struct r5l_log *log, sector_t space)
+{
+ unsigned long target;
+ unsigned long new = (unsigned long)space; /* overflow in theory */
+
+ do {
+ target = log->reclaim_target;
+ if (new < target)
+ return;
+ } while (cmpxchg(&log->reclaim_target, target, new) != target);
+ md_wakeup_thread(log->reclaim_thread);
+}
+
+void r5l_quiesce(struct r5l_log *log, int state)
+{
+ struct mddev *mddev;
+ if (!log || state == 2)
+ return;
+ if (state == 0) {
+ log->in_teardown = 0;
+ log->reclaim_thread = md_register_thread(r5l_reclaim_thread,
+ log->rdev->mddev, "reclaim");
+ } else if (state == 1) {
+ /*
+ * at this point all stripes are finished, so io_unit is at
+ * least in STRIPE_END state
+ */
+ log->in_teardown = 1;
+ /* make sure r5l_write_super_and_discard_space exits */
+ mddev = log->rdev->mddev;
+ wake_up(&mddev->sb_wait);
+ r5l_wake_reclaim(log, -1L);
+ md_unregister_thread(&log->reclaim_thread);
+ r5l_do_reclaim(log);
+ }
+}
+
+bool r5l_log_disk_error(struct r5conf *conf)
+{
+ /* don't allow write if journal disk is missing */
+ if (!conf->log)
+ return test_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
+ return test_bit(Faulty, &conf->log->rdev->flags);
+}
+
+struct r5l_recovery_ctx {
+ struct page *meta_page; /* current meta */
+ sector_t meta_total_blocks; /* total size of current meta and data */
+ sector_t pos; /* recovery position */
+ u64 seq; /* recovery position seq */
+};
+
+static int r5l_read_meta_block(struct r5l_log *log,
+ struct r5l_recovery_ctx *ctx)
+{
+ struct page *page = ctx->meta_page;
+ struct r5l_meta_block *mb;
+ u32 crc, stored_crc;
+
+ if (!sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page, READ, false))
+ return -EIO;
+
+ mb = page_address(page);
+ stored_crc = le32_to_cpu(mb->checksum);
+ mb->checksum = 0;
+
+ if (le32_to_cpu(mb->magic) != R5LOG_MAGIC ||
+ le64_to_cpu(mb->seq) != ctx->seq ||
+ mb->version != R5LOG_VERSION ||
+ le64_to_cpu(mb->position) != ctx->pos)
+ return -EINVAL;
+
+ crc = crc32c_le(log->uuid_checksum, mb, PAGE_SIZE);
+ if (stored_crc != crc)
+ return -EINVAL;
+
+ if (le32_to_cpu(mb->meta_size) > PAGE_SIZE)
+ return -EINVAL;
+
+ ctx->meta_total_blocks = BLOCK_SECTORS;
+
+ return 0;
+}
+
+static int r5l_recovery_flush_one_stripe(struct r5l_log *log,
+ struct r5l_recovery_ctx *ctx,
+ sector_t stripe_sect,
+ int *offset, sector_t *log_offset)
+{
+ struct r5conf *conf = log->rdev->mddev->private;
+ struct stripe_head *sh;
+ struct r5l_payload_data_parity *payload;
+ int disk_index;
+
+ sh = raid5_get_active_stripe(conf, stripe_sect, 0, 0, 0);
+ while (1) {
+ payload = page_address(ctx->meta_page) + *offset;
+
+ if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_DATA) {
+ raid5_compute_sector(conf,
+ le64_to_cpu(payload->location), 0,
+ &disk_index, sh);
+
+ sync_page_io(log->rdev, *log_offset, PAGE_SIZE,
+ sh->dev[disk_index].page, READ, false);
+ sh->dev[disk_index].log_checksum =
+ le32_to_cpu(payload->checksum[0]);
+ set_bit(R5_Wantwrite, &sh->dev[disk_index].flags);
+ ctx->meta_total_blocks += BLOCK_SECTORS;
+ } else {
+ disk_index = sh->pd_idx;
+ sync_page_io(log->rdev, *log_offset, PAGE_SIZE,
+ sh->dev[disk_index].page, READ, false);
+ sh->dev[disk_index].log_checksum =
+ le32_to_cpu(payload->checksum[0]);
+ set_bit(R5_Wantwrite, &sh->dev[disk_index].flags);
+
+ if (sh->qd_idx >= 0) {
+ disk_index = sh->qd_idx;
+ sync_page_io(log->rdev,
+ r5l_ring_add(log, *log_offset, BLOCK_SECTORS),
+ PAGE_SIZE, sh->dev[disk_index].page,
+ READ, false);
+ sh->dev[disk_index].log_checksum =
+ le32_to_cpu(payload->checksum[1]);
+ set_bit(R5_Wantwrite,
+ &sh->dev[disk_index].flags);
+ }
+ ctx->meta_total_blocks += BLOCK_SECTORS * conf->max_degraded;
+ }
+
+ *log_offset = r5l_ring_add(log, *log_offset,
+ le32_to_cpu(payload->size));
+ *offset += sizeof(struct r5l_payload_data_parity) +
+ sizeof(__le32) *
+ (le32_to_cpu(payload->size) >> (PAGE_SHIFT - 9));
+ if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_PARITY)
+ break;
+ }
+
+ for (disk_index = 0; disk_index < sh->disks; disk_index++) {
+ void *addr;
+ u32 checksum;
+
+ if (!test_bit(R5_Wantwrite, &sh->dev[disk_index].flags))
+ continue;
+ addr = kmap_atomic(sh->dev[disk_index].page);
+ checksum = crc32c_le(log->uuid_checksum, addr, PAGE_SIZE);
+ kunmap_atomic(addr);
+ if (checksum != sh->dev[disk_index].log_checksum)
+ goto error;
+ }
+
+ for (disk_index = 0; disk_index < sh->disks; disk_index++) {
+ struct md_rdev *rdev, *rrdev;
+
+ if (!test_and_clear_bit(R5_Wantwrite,
+ &sh->dev[disk_index].flags))
+ continue;
+
+ /* in case device is broken */
+ rdev = rcu_dereference(conf->disks[disk_index].rdev);
+ if (rdev)
+ sync_page_io(rdev, stripe_sect, PAGE_SIZE,
+ sh->dev[disk_index].page, WRITE, false);
+ rrdev = rcu_dereference(conf->disks[disk_index].replacement);
+ if (rrdev)
+ sync_page_io(rrdev, stripe_sect, PAGE_SIZE,
+ sh->dev[disk_index].page, WRITE, false);
+ }
+ raid5_release_stripe(sh);
+ return 0;
+
+error:
+ for (disk_index = 0; disk_index < sh->disks; disk_index++)
+ sh->dev[disk_index].flags = 0;
+ raid5_release_stripe(sh);
+ return -EINVAL;
+}
+
+static int r5l_recovery_flush_one_meta(struct r5l_log *log,
+ struct r5l_recovery_ctx *ctx)
+{
+ struct r5conf *conf = log->rdev->mddev->private;
+ struct r5l_payload_data_parity *payload;
+ struct r5l_meta_block *mb;
+ int offset;
+ sector_t log_offset;
+ sector_t stripe_sector;
+
+ mb = page_address(ctx->meta_page);
+ offset = sizeof(struct r5l_meta_block);
+ log_offset = r5l_ring_add(log, ctx->pos, BLOCK_SECTORS);
+
+ while (offset < le32_to_cpu(mb->meta_size)) {
+ int dd;
+
+ payload = (void *)mb + offset;
+ stripe_sector = raid5_compute_sector(conf,
+ le64_to_cpu(payload->location), 0, &dd, NULL);
+ if (r5l_recovery_flush_one_stripe(log, ctx, stripe_sector,
+ &offset, &log_offset))
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* copy data/parity from log to raid disks */
+static void r5l_recovery_flush_log(struct r5l_log *log,
+ struct r5l_recovery_ctx *ctx)
+{
+ while (1) {
+ if (r5l_read_meta_block(log, ctx))
+ return;
+ if (r5l_recovery_flush_one_meta(log, ctx))
+ return;
+ ctx->seq++;
+ ctx->pos = r5l_ring_add(log, ctx->pos, ctx->meta_total_blocks);
+ }
+}
+
+static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos,
+ u64 seq)
+{
+ struct page *page;
+ struct r5l_meta_block *mb;
+ u32 crc;
+
+ page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!page)
+ return -ENOMEM;
+ mb = page_address(page);
+ mb->magic = cpu_to_le32(R5LOG_MAGIC);
+ mb->version = R5LOG_VERSION;
+ mb->meta_size = cpu_to_le32(sizeof(struct r5l_meta_block));
+ mb->seq = cpu_to_le64(seq);
+ mb->position = cpu_to_le64(pos);
+ crc = crc32c_le(log->uuid_checksum, mb, PAGE_SIZE);
+ mb->checksum = cpu_to_le32(crc);
+
+ if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, WRITE_FUA, false)) {
+ __free_page(page);
+ return -EIO;
+ }
+ __free_page(page);
+ return 0;
+}
+
+static int r5l_recovery_log(struct r5l_log *log)
+{
+ struct r5l_recovery_ctx ctx;
+
+ ctx.pos = log->last_checkpoint;
+ ctx.seq = log->last_cp_seq;
+ ctx.meta_page = alloc_page(GFP_KERNEL);
+ if (!ctx.meta_page)
+ return -ENOMEM;
+
+ r5l_recovery_flush_log(log, &ctx);
+ __free_page(ctx.meta_page);
+
+ /*
+ * we did a recovery. Now ctx.pos points to an invalid meta block. New
+ * log will start here. but we can't let superblock point to last valid
+ * meta block. The log might looks like:
+ * | meta 1| meta 2| meta 3|
+ * meta 1 is valid, meta 2 is invalid. meta 3 could be valid. If
+ * superblock points to meta 1, we write a new valid meta 2n. if crash
+ * happens again, new recovery will start from meta 1. Since meta 2n is
+ * valid now, recovery will think meta 3 is valid, which is wrong.
+ * The solution is we create a new meta in meta2 with its seq == meta
+ * 1's seq + 10 and let superblock points to meta2. The same recovery will
+ * not think meta 3 is a valid meta, because its seq doesn't match
+ */
+ if (ctx.seq > log->last_cp_seq + 1) {
+ int ret;
+
+ ret = r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq + 10);
+ if (ret)
+ return ret;
+ log->seq = ctx.seq + 11;
+ log->log_start = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
+ r5l_write_super(log, ctx.pos);
+ } else {
+ log->log_start = ctx.pos;
+ log->seq = ctx.seq;
+ }
+ return 0;
+}
+
+static void r5l_write_super(struct r5l_log *log, sector_t cp)
+{
+ struct mddev *mddev = log->rdev->mddev;
+
+ log->rdev->journal_tail = cp;
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+}
+
+static int r5l_load_log(struct r5l_log *log)
+{
+ struct md_rdev *rdev = log->rdev;
+ struct page *page;
+ struct r5l_meta_block *mb;
+ sector_t cp = log->rdev->journal_tail;
+ u32 stored_crc, expected_crc;
+ bool create_super = false;
+ int ret;
+
+ /* Make sure it's valid */
+ if (cp >= rdev->sectors || round_down(cp, BLOCK_SECTORS) != cp)
+ cp = 0;
+ page = alloc_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ if (!sync_page_io(rdev, cp, PAGE_SIZE, page, READ, false)) {
+ ret = -EIO;
+ goto ioerr;
+ }
+ mb = page_address(page);
+
+ if (le32_to_cpu(mb->magic) != R5LOG_MAGIC ||
+ mb->version != R5LOG_VERSION) {
+ create_super = true;
+ goto create;
+ }
+ stored_crc = le32_to_cpu(mb->checksum);
+ mb->checksum = 0;
+ expected_crc = crc32c_le(log->uuid_checksum, mb, PAGE_SIZE);
+ if (stored_crc != expected_crc) {
+ create_super = true;
+ goto create;
+ }
+ if (le64_to_cpu(mb->position) != cp) {
+ create_super = true;
+ goto create;
+ }
+create:
+ if (create_super) {
+ log->last_cp_seq = prandom_u32();
+ cp = 0;
+ /*
+ * Make sure super points to correct address. Log might have
+ * data very soon. If super hasn't correct log tail address,
+ * recovery can't find the log
+ */
+ r5l_write_super(log, cp);
+ } else
+ log->last_cp_seq = le64_to_cpu(mb->seq);
+
+ log->device_size = round_down(rdev->sectors, BLOCK_SECTORS);
+ log->max_free_space = log->device_size >> RECLAIM_MAX_FREE_SPACE_SHIFT;
+ if (log->max_free_space > RECLAIM_MAX_FREE_SPACE)
+ log->max_free_space = RECLAIM_MAX_FREE_SPACE;
+ log->last_checkpoint = cp;
+
+ __free_page(page);
+
+ return r5l_recovery_log(log);
+ioerr:
+ __free_page(page);
+ return ret;
+}
+
+int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
+{
+ struct r5l_log *log;
+
+ if (PAGE_SIZE != 4096)
+ return -EINVAL;
+ log = kzalloc(sizeof(*log), GFP_KERNEL);
+ if (!log)
+ return -ENOMEM;
+ log->rdev = rdev;
+
+ log->need_cache_flush = (rdev->bdev->bd_disk->queue->flush_flags != 0);
+
+ log->uuid_checksum = crc32c_le(~0, rdev->mddev->uuid,
+ sizeof(rdev->mddev->uuid));
+
+ mutex_init(&log->io_mutex);
+
+ spin_lock_init(&log->io_list_lock);
+ INIT_LIST_HEAD(&log->running_ios);
+ INIT_LIST_HEAD(&log->io_end_ios);
+ INIT_LIST_HEAD(&log->flushing_ios);
+ INIT_LIST_HEAD(&log->finished_ios);
+ bio_init(&log->flush_bio);
+
+ log->io_kc = KMEM_CACHE(r5l_io_unit, 0);
+ if (!log->io_kc)
+ goto io_kc;
+
+ log->reclaim_thread = md_register_thread(r5l_reclaim_thread,
+ log->rdev->mddev, "reclaim");
+ if (!log->reclaim_thread)
+ goto reclaim_thread;
+ init_waitqueue_head(&log->iounit_wait);
+
+ INIT_LIST_HEAD(&log->no_space_stripes);
+ spin_lock_init(&log->no_space_stripes_lock);
+
+ if (r5l_load_log(log))
+ goto error;
+
+ conf->log = log;
+ return 0;
+error:
+ md_unregister_thread(&log->reclaim_thread);
+reclaim_thread:
+ kmem_cache_destroy(log->io_kc);
+io_kc:
+ kfree(log);
+ return -EINVAL;
+}
+
+void r5l_exit_log(struct r5l_log *log)
+{
+ md_unregister_thread(&log->reclaim_thread);
+ kmem_cache_destroy(log->io_kc);
+ kfree(log);
+}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 49bb8d3ff9be..704ef7fcfbf8 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -353,7 +353,7 @@ static void release_inactive_stripe_list(struct r5conf *conf,
struct list_head *list = &temp_inactive_list[size - 1];
/*
- * We don't hold any lock here yet, get_active_stripe() might
+ * We don't hold any lock here yet, raid5_get_active_stripe() might
* remove stripes from the list
*/
if (!list_empty_careful(list)) {
@@ -413,7 +413,7 @@ static int release_stripe_list(struct r5conf *conf,
return count;
}
-static void release_stripe(struct stripe_head *sh)
+void raid5_release_stripe(struct stripe_head *sh)
{
struct r5conf *conf = sh->raid_conf;
unsigned long flags;
@@ -658,9 +658,9 @@ static int has_failed(struct r5conf *conf)
return 0;
}
-static struct stripe_head *
-get_active_stripe(struct r5conf *conf, sector_t sector,
- int previous, int noblock, int noquiesce)
+struct stripe_head *
+raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
+ int previous, int noblock, int noquiesce)
{
struct stripe_head *sh;
int hash = stripe_hash_locks_hash(sector);
@@ -755,6 +755,10 @@ static void unlock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
/* Only freshly new full stripe normal write stripe can be added to a batch list */
static bool stripe_can_batch(struct stripe_head *sh)
{
+ struct r5conf *conf = sh->raid_conf;
+
+ if (conf->log)
+ return false;
return test_bit(STRIPE_BATCH_READY, &sh->state) &&
!test_bit(STRIPE_BITMAP_PENDING, &sh->state) &&
is_full_stripe_write(sh);
@@ -858,7 +862,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
unlock_out:
unlock_two_stripes(head, sh);
out:
- release_stripe(head);
+ raid5_release_stripe(head);
}
/* Determine if 'data_offset' or 'new_data_offset' should be used
@@ -895,6 +899,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
might_sleep();
+ if (r5l_write_stripe(conf->log, sh) == 0)
+ return;
for (i = disks; i--; ) {
int rw;
int replace_only = 0;
@@ -1208,7 +1214,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
return_io(&return_bi);
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
static void ops_run_biofill(struct stripe_head *sh)
@@ -1271,7 +1277,7 @@ static void ops_complete_compute(void *stripe_head_ref)
if (sh->check_state == check_state_compute_run)
sh->check_state = check_state_compute_result;
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
/* return a pointer to the address conversion region of the scribble buffer */
@@ -1697,7 +1703,7 @@ static void ops_complete_reconstruct(void *stripe_head_ref)
}
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
static void
@@ -1855,7 +1861,7 @@ static void ops_complete_check(void *stripe_head_ref)
sh->check_state = check_state_check_result;
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)
@@ -2017,7 +2023,7 @@ static int grow_one_stripe(struct r5conf *conf, gfp_t gfp)
/* we just created an active stripe so... */
atomic_inc(&conf->active_stripes);
- release_stripe(sh);
+ raid5_release_stripe(sh);
conf->max_nr_stripes++;
return 1;
}
@@ -2236,7 +2242,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
if (!p)
err = -ENOMEM;
}
- release_stripe(nsh);
+ raid5_release_stripe(nsh);
}
/* critical section pass, GFP_NOIO no longer needed */
@@ -2394,7 +2400,7 @@ static void raid5_end_read_request(struct bio * bi)
rdev_dec_pending(rdev, conf->mddev);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
static void raid5_end_write_request(struct bio *bi)
@@ -2468,14 +2474,12 @@ static void raid5_end_write_request(struct bio *bi)
if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags))
clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
if (sh->batch_head && sh != sh->batch_head)
- release_stripe(sh->batch_head);
+ raid5_release_stripe(sh->batch_head);
}
-static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous);
-
static void raid5_build_block(struct stripe_head *sh, int i, int previous)
{
struct r5dev *dev = &sh->dev[i];
@@ -2491,7 +2495,7 @@ static void raid5_build_block(struct stripe_head *sh, int i, int previous)
dev->rreq.bi_private = sh;
dev->flags = 0;
- dev->sector = compute_blocknr(sh, i, previous);
+ dev->sector = raid5_compute_blocknr(sh, i, previous);
}
static void error(struct mddev *mddev, struct md_rdev *rdev)
@@ -2524,9 +2528,9 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
* Input: a 'big' sector number,
* Output: index of the data and parity disk, and the sector # in them.
*/
-static sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
- int previous, int *dd_idx,
- struct stripe_head *sh)
+sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
+ int previous, int *dd_idx,
+ struct stripe_head *sh)
{
sector_t stripe, stripe2;
sector_t chunk_number;
@@ -2726,7 +2730,7 @@ static sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
return new_sector;
}
-static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous)
+sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous)
{
struct r5conf *conf = sh->raid_conf;
int raid_disks = sh->disks;
@@ -3098,6 +3102,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
if (bi)
bitmap_end = 1;
+ r5l_stripe_write_finished(sh);
+
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -3141,6 +3147,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
* the data has not reached the cache yet.
*/
if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
+ s->failed > conf->max_degraded &&
(!test_bit(R5_Insync, &sh->dev[i].flags) ||
test_bit(R5_ReadError, &sh->dev[i].flags))) {
spin_lock_irq(&sh->stripe_lock);
@@ -3497,8 +3504,12 @@ returnbi:
WARN_ON(test_bit(R5_SkipCopy, &dev->flags));
WARN_ON(dev->page != dev->orig_page);
}
+
+ r5l_stripe_write_finished(sh);
+
if (!discard_pending &&
test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
+ int hash;
clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
if (sh->qd_idx >= 0) {
@@ -3512,16 +3523,17 @@ returnbi:
* no updated data, so remove it from hash list and the stripe
* will be reinitialized
*/
- spin_lock_irq(&conf->device_lock);
unhash:
+ hash = sh->hash_lock_index;
+ spin_lock_irq(conf->hash_locks + hash);
remove_hash(sh);
+ spin_unlock_irq(conf->hash_locks + hash);
if (head_sh->batch_head) {
sh = list_first_entry(&sh->batch_list,
struct stripe_head, batch_list);
if (sh != head_sh)
goto unhash;
}
- spin_unlock_irq(&conf->device_lock);
sh = head_sh;
if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
@@ -3937,10 +3949,10 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
struct stripe_head *sh2;
struct async_submit_ctl submit;
- sector_t bn = compute_blocknr(sh, i, 1);
+ sector_t bn = raid5_compute_blocknr(sh, i, 1);
sector_t s = raid5_compute_sector(conf, bn, 0,
&dd_idx, NULL);
- sh2 = get_active_stripe(conf, s, 0, 1, 1);
+ sh2 = raid5_get_active_stripe(conf, s, 0, 1, 1);
if (sh2 == NULL)
/* so far only the early blocks of this stripe
* have been requested. When later blocks
@@ -3950,7 +3962,7 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
/* must have already done this block */
- release_stripe(sh2);
+ raid5_release_stripe(sh2);
continue;
}
@@ -3971,7 +3983,7 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
set_bit(STRIPE_EXPAND_READY, &sh2->state);
set_bit(STRIPE_HANDLE, &sh2->state);
}
- release_stripe(sh2);
+ raid5_release_stripe(sh2);
}
/* done submitting copies, wait for them to complete */
@@ -4006,6 +4018,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
s->expanded = test_bit(STRIPE_EXPAND_READY, &sh->state) && !sh->batch_head;
s->failed_num[0] = -1;
s->failed_num[1] = -1;
+ s->log_failed = r5l_log_disk_error(conf);
/* Now to look around and see what can be done */
rcu_read_lock();
@@ -4257,7 +4270,7 @@ static void break_stripe_batch_list(struct stripe_head *head_sh,
if (handle_flags == 0 ||
sh->state & handle_flags)
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
spin_lock_irq(&head_sh->stripe_lock);
head_sh->batch_head = NULL;
@@ -4318,6 +4331,9 @@ static void handle_stripe(struct stripe_head *sh)
analyse_stripe(sh, &s);
+ if (test_bit(STRIPE_LOG_TRAPPED, &sh->state))
+ goto finish;
+
if (s.handle_bad_blocks) {
set_bit(STRIPE_HANDLE, &sh->state);
goto finish;
@@ -4346,7 +4362,7 @@ static void handle_stripe(struct stripe_head *sh)
/* check if the array has lost more than max_degraded devices and,
* if so, some requests might need to be failed.
*/
- if (s.failed > conf->max_degraded) {
+ if (s.failed > conf->max_degraded || s.log_failed) {
sh->check_state = 0;
sh->reconstruct_state = 0;
break_stripe_batch_list(sh, 0);
@@ -4504,7 +4520,7 @@ static void handle_stripe(struct stripe_head *sh)
/* Finish reconstruct operations initiated by the expansion process */
if (sh->reconstruct_state == reconstruct_state_result) {
struct stripe_head *sh_src
- = get_active_stripe(conf, sh->sector, 1, 1, 1);
+ = raid5_get_active_stripe(conf, sh->sector, 1, 1, 1);
if (sh_src && test_bit(STRIPE_EXPAND_SOURCE, &sh_src->state)) {
/* sh cannot be written until sh_src has been read.
* so arrange for sh to be delayed a little
@@ -4514,11 +4530,11 @@ static void handle_stripe(struct stripe_head *sh)
if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE,
&sh_src->state))
atomic_inc(&conf->preread_active_stripes);
- release_stripe(sh_src);
+ raid5_release_stripe(sh_src);
goto finish;
}
if (sh_src)
- release_stripe(sh_src);
+ raid5_release_stripe(sh_src);
sh->reconstruct_state = reconstruct_state_idle;
clear_bit(STRIPE_EXPANDING, &sh->state);
@@ -5010,7 +5026,7 @@ static void release_stripe_plug(struct mddev *mddev,
struct raid5_plug_cb *cb;
if (!blk_cb) {
- release_stripe(sh);
+ raid5_release_stripe(sh);
return;
}
@@ -5026,7 +5042,7 @@ static void release_stripe_plug(struct mddev *mddev,
if (!test_and_set_bit(STRIPE_ON_UNPLUG_LIST, &sh->state))
list_add_tail(&sh->lru, &cb->list);
else
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
static void make_discard_request(struct mddev *mddev, struct bio *bi)
@@ -5061,12 +5077,12 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
DEFINE_WAIT(w);
int d;
again:
- sh = get_active_stripe(conf, logical_sector, 0, 0, 0);
+ sh = raid5_get_active_stripe(conf, logical_sector, 0, 0, 0);
prepare_to_wait(&conf->wait_for_overlap, &w,
TASK_UNINTERRUPTIBLE);
set_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags);
if (test_bit(STRIPE_SYNCING, &sh->state)) {
- release_stripe(sh);
+ raid5_release_stripe(sh);
schedule();
goto again;
}
@@ -5078,7 +5094,7 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
if (sh->dev[d].towrite || sh->dev[d].toread) {
set_bit(R5_Overlap, &sh->dev[d].flags);
spin_unlock_irq(&sh->stripe_lock);
- release_stripe(sh);
+ raid5_release_stripe(sh);
schedule();
goto again;
}
@@ -5134,8 +5150,15 @@ static void make_request(struct mddev *mddev, struct bio * bi)
bool do_prepare;
if (unlikely(bi->bi_rw & REQ_FLUSH)) {
- md_flush_request(mddev, bi);
- return;
+ int ret = r5l_handle_flush_request(conf->log, bi);
+
+ if (ret == 0)
+ return;
+ if (ret == -ENODEV) {
+ md_flush_request(mddev, bi);
+ return;
+ }
+ /* ret == -EAGAIN, fallback */
}
md_write_start(mddev, bi);
@@ -5208,7 +5231,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
- sh = get_active_stripe(conf, new_sector, previous,
+ sh = raid5_get_active_stripe(conf, new_sector, previous,
(bi->bi_rw&RWA_MASK), 0);
if (sh) {
if (unlikely(previous)) {
@@ -5229,7 +5252,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
must_retry = 1;
spin_unlock_irq(&conf->device_lock);
if (must_retry) {
- release_stripe(sh);
+ raid5_release_stripe(sh);
schedule();
do_prepare = true;
goto retry;
@@ -5239,14 +5262,14 @@ static void make_request(struct mddev *mddev, struct bio * bi)
/* Might have got the wrong stripe_head
* by accident
*/
- release_stripe(sh);
+ raid5_release_stripe(sh);
goto retry;
}
if (rw == WRITE &&
logical_sector >= mddev->suspend_lo &&
logical_sector < mddev->suspend_hi) {
- release_stripe(sh);
+ raid5_release_stripe(sh);
/* As the suspend_* range is controlled by
* userspace, we want an interruptible
* wait.
@@ -5269,7 +5292,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
* and wait a while
*/
md_wakeup_thread(mddev->thread);
- release_stripe(sh);
+ raid5_release_stripe(sh);
schedule();
do_prepare = true;
goto retry;
@@ -5456,7 +5479,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) {
int j;
int skipped_disk = 0;
- sh = get_active_stripe(conf, stripe_addr+i, 0, 0, 1);
+ sh = raid5_get_active_stripe(conf, stripe_addr+i, 0, 0, 1);
set_bit(STRIPE_EXPANDING, &sh->state);
atomic_inc(&conf->reshape_stripes);
/* If any of this stripe is beyond the end of the old
@@ -5469,7 +5492,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
if (conf->level == 6 &&
j == sh->qd_idx)
continue;
- s = compute_blocknr(sh, j, 0);
+ s = raid5_compute_blocknr(sh, j, 0);
if (s < raid5_size(mddev, 0, 0)) {
skipped_disk = 1;
continue;
@@ -5505,10 +5528,10 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
if (last_sector >= mddev->dev_sectors)
last_sector = mddev->dev_sectors - 1;
while (first_sector <= last_sector) {
- sh = get_active_stripe(conf, first_sector, 1, 0, 1);
+ sh = raid5_get_active_stripe(conf, first_sector, 1, 0, 1);
set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
first_sector += STRIPE_SECTORS;
}
/* Now that the sources are clearly marked, we can release
@@ -5517,7 +5540,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
while (!list_empty(&stripes)) {
sh = list_entry(stripes.next, struct stripe_head, lru);
list_del_init(&sh->lru);
- release_stripe(sh);
+ raid5_release_stripe(sh);
}
/* If this takes us to the resync_max point where we have to pause,
* then we need to write out the superblock.
@@ -5613,11 +5636,11 @@ static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int
return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
}
- bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+ bitmap_cond_end_sync(mddev->bitmap, sector_nr, false);
- sh = get_active_stripe(conf, sector_nr, 0, 1, 0);
+ sh = raid5_get_active_stripe(conf, sector_nr, 0, 1, 0);
if (sh == NULL) {
- sh = get_active_stripe(conf, sector_nr, 0, 0, 0);
+ sh = raid5_get_active_stripe(conf, sector_nr, 0, 0, 0);
/* make sure we don't swamp the stripe cache if someone else
* is trying to get access
*/
@@ -5641,7 +5664,7 @@ static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int
set_bit(STRIPE_SYNC_REQUESTED, &sh->state);
set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
+ raid5_release_stripe(sh);
return STRIPE_SECTORS;
}
@@ -5680,7 +5703,7 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
/* already done this stripe */
continue;
- sh = get_active_stripe(conf, sector, 0, 1, 1);
+ sh = raid5_get_active_stripe(conf, sector, 0, 1, 1);
if (!sh) {
/* failed to get a stripe - must wait */
@@ -5690,7 +5713,7 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
}
if (!add_stripe_bio(sh, raid_bio, dd_idx, 0, 0)) {
- release_stripe(sh);
+ raid5_release_stripe(sh);
raid5_set_bi_processed_stripes(raid_bio, scnt);
conf->retry_read_aligned = raid_bio;
return handled;
@@ -5698,7 +5721,7 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
set_bit(R5_ReadNoMerge, &sh->dev[dd_idx].flags);
handle_stripe(sh);
- release_stripe(sh);
+ raid5_release_stripe(sh);
handled++;
}
remaining = raid5_dec_bi_active_stripes(raid_bio);
@@ -5728,8 +5751,12 @@ static int handle_active_stripes(struct r5conf *conf, int group,
for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++)
if (!list_empty(temp_inactive_list + i))
break;
- if (i == NR_STRIPE_HASH_LOCKS)
+ if (i == NR_STRIPE_HASH_LOCKS) {
+ spin_unlock_irq(&conf->device_lock);
+ r5l_flush_stripe_to_raid(conf->log);
+ spin_lock_irq(&conf->device_lock);
return batch_size;
+ }
release_inactive = true;
}
spin_unlock_irq(&conf->device_lock);
@@ -5737,6 +5764,7 @@ static int handle_active_stripes(struct r5conf *conf, int group,
release_inactive_stripe_list(conf, temp_inactive_list,
NR_STRIPE_HASH_LOCKS);
+ r5l_flush_stripe_to_raid(conf->log);
if (release_inactive) {
spin_lock_irq(&conf->device_lock);
return 0;
@@ -5744,6 +5772,7 @@ static int handle_active_stripes(struct r5conf *conf, int group,
for (i = 0; i < batch_size; i++)
handle_stripe(batch[i]);
+ r5l_write_stripe_run(conf->log);
cond_resched();
@@ -5877,6 +5906,8 @@ static void raid5d(struct md_thread *thread)
mutex_unlock(&conf->cache_size_mutex);
}
+ r5l_flush_stripe_to_raid(conf->log);
+
async_tx_issue_pending_all();
blk_finish_plug(&plug);
@@ -6314,8 +6345,11 @@ static void raid5_free_percpu(struct r5conf *conf)
static void free_conf(struct r5conf *conf)
{
+ if (conf->log)
+ r5l_exit_log(conf->log);
if (conf->shrinker.seeks)
unregister_shrinker(&conf->shrinker);
+
free_thread_groups(conf);
shrink_stripes(conf);
raid5_free_percpu(conf);
@@ -6528,7 +6562,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
rdev_for_each(rdev, mddev) {
raid_disk = rdev->raid_disk;
if (raid_disk >= max_disks
- || raid_disk < 0)
+ || raid_disk < 0 || test_bit(Journal, &rdev->flags))
continue;
disk = conf->disks + raid_disk;
@@ -6648,6 +6682,7 @@ static int run(struct mddev *mddev)
int working_disks = 0;
int dirty_parity_disks = 0;
struct md_rdev *rdev;
+ struct md_rdev *journal_dev = NULL;
sector_t reshape_offset = 0;
int i;
long long min_offset_diff = 0;
@@ -6660,6 +6695,11 @@ static int run(struct mddev *mddev)
rdev_for_each(rdev, mddev) {
long long diff;
+
+ if (test_bit(Journal, &rdev->flags)) {
+ journal_dev = rdev;
+ continue;
+ }
if (rdev->raid_disk < 0)
continue;
diff = (rdev->new_data_offset - rdev->data_offset);
@@ -6693,6 +6733,12 @@ static int run(struct mddev *mddev)
int chunk_sectors;
int new_data_disks;
+ if (journal_dev) {
+ printk(KERN_ERR "md/raid:%s: don't support reshape with journal - aborting.\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+
if (mddev->new_level != mddev->level) {
printk(KERN_ERR "md/raid:%s: unsupported reshape "
"required - aborting.\n",
@@ -6768,6 +6814,13 @@ static int run(struct mddev *mddev)
if (IS_ERR(conf))
return PTR_ERR(conf);
+ if (test_bit(MD_HAS_JOURNAL, &mddev->flags) && !journal_dev) {
+ printk(KERN_ERR "md/raid:%s: journal disk is missing, force array readonly\n",
+ mdname(mddev));
+ mddev->ro = 1;
+ set_disk_ro(mddev->gendisk, 1);
+ }
+
conf->min_offset_diff = min_offset_diff;
mddev->thread = conf->thread;
conf->thread = NULL;
@@ -6971,6 +7024,14 @@ static int run(struct mddev *mddev)
mddev->queue);
}
+ if (journal_dev) {
+ char b[BDEVNAME_SIZE];
+
+ printk(KERN_INFO"md/raid:%s: using device %s as journal\n",
+ mdname(mddev), bdevname(journal_dev->bdev, b));
+ r5l_init_log(conf, journal_dev);
+ }
+
return 0;
abort:
md_unregister_thread(&mddev->thread);
@@ -7080,6 +7141,15 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
struct disk_info *p = conf->disks + number;
print_raid5_conf(conf);
+ if (test_bit(Journal, &rdev->flags)) {
+ /*
+ * journal disk is not removable, but we need give a chance to
+ * update superblock of other disks. Otherwise journal disk
+ * will be considered as 'fresh'
+ */
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+ return -EINVAL;
+ }
if (rdev == p->rdev)
rdevp = &p->rdev;
else if (rdev == p->replacement)
@@ -7142,6 +7212,8 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
int first = 0;
int last = conf->raid_disks - 1;
+ if (test_bit(Journal, &rdev->flags))
+ return -EINVAL;
if (mddev->recovery_disabled == conf->recovery_disabled)
return -EBUSY;
@@ -7203,6 +7275,8 @@ static int raid5_resize(struct mddev *mddev, sector_t sectors)
sector_t newsize;
struct r5conf *conf = mddev->private;
+ if (conf->log)
+ return -EINVAL;
sectors &= ~((sector_t)conf->chunk_sectors - 1);
newsize = raid5_size(mddev, sectors, mddev->raid_disks);
if (mddev->external_size &&
@@ -7254,6 +7328,8 @@ static int check_reshape(struct mddev *mddev)
{
struct r5conf *conf = mddev->private;
+ if (conf->log)
+ return -EINVAL;
if (mddev->delta_disks == 0 &&
mddev->new_layout == mddev->layout &&
mddev->new_chunk_sectors == mddev->chunk_sectors)
@@ -7530,6 +7606,7 @@ static void raid5_quiesce(struct mddev *mddev, int state)
unlock_all_device_hash_locks_irq(conf);
break;
}
+ r5l_quiesce(conf->log, state);
}
static void *raid45_takeover_raid0(struct mddev *mddev, int level)
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 828c2925e68f..a415e1cd39b8 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -223,6 +223,9 @@ struct stripe_head {
struct stripe_head *batch_head; /* protected by stripe lock */
spinlock_t batch_lock; /* only header's lock is useful */
struct list_head batch_list; /* protected by head's batch lock*/
+
+ struct r5l_io_unit *log_io;
+ struct list_head log_list;
/**
* struct stripe_operations
* @target - STRIPE_OP_COMPUTE_BLK target
@@ -244,6 +247,7 @@ struct stripe_head {
struct bio *toread, *read, *towrite, *written;
sector_t sector; /* sector of this page */
unsigned long flags;
+ u32 log_checksum;
} dev[1]; /* allocated with extra space depending of RAID geometry */
};
@@ -268,6 +272,7 @@ struct stripe_head_state {
struct bio_list return_bi;
struct md_rdev *blocked_rdev;
int handle_bad_blocks;
+ int log_failed;
};
/* Flags for struct r5dev.flags */
@@ -340,6 +345,7 @@ enum {
STRIPE_BITMAP_PENDING, /* Being added to bitmap, don't add
* to batch yet.
*/
+ STRIPE_LOG_TRAPPED, /* trapped into log */
};
#define STRIPE_EXPAND_SYNC_FLAGS \
@@ -543,6 +549,7 @@ struct r5conf {
struct r5worker_group *worker_groups;
int group_cnt;
int worker_cnt_per_group;
+ struct r5l_log *log;
};
@@ -609,4 +616,21 @@ static inline int algorithm_is_DDF(int layout)
extern void md_raid5_kick_device(struct r5conf *conf);
extern int raid5_set_cache_size(struct mddev *mddev, int size);
+extern sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous);
+extern void raid5_release_stripe(struct stripe_head *sh);
+extern sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
+ int previous, int *dd_idx,
+ struct stripe_head *sh);
+extern struct stripe_head *
+raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
+ int previous, int noblock, int noquiesce);
+extern int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev);
+extern void r5l_exit_log(struct r5l_log *log);
+extern int r5l_write_stripe(struct r5l_log *log, struct stripe_head *head_sh);
+extern void r5l_write_stripe_run(struct r5l_log *log);
+extern void r5l_flush_stripe_to_raid(struct r5l_log *log);
+extern void r5l_stripe_write_finished(struct stripe_head *sh);
+extern int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio);
+extern void r5l_quiesce(struct r5l_log *log, int state);
+extern bool r5l_log_disk_error(struct r5conf *conf);
#endif
diff --git a/drivers/media/dvb-core/demux.h b/drivers/media/dvb-core/demux.h
index 833191bcd810..ccc1f43cb9a9 100644
--- a/drivers/media/dvb-core/demux.h
+++ b/drivers/media/dvb-core/demux.h
@@ -32,9 +32,9 @@
#include <linux/time.h>
#include <linux/dvb/dmx.h>
-/*--------------------------------------------------------------------------*/
-/* Common definitions */
-/*--------------------------------------------------------------------------*/
+/*
+ * Common definitions
+ */
/*
* DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
@@ -45,7 +45,8 @@
#endif
/*
- * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
+ * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed
+ * filter.
*/
#ifndef DMX_MAX_SECTION_SIZE
@@ -55,139 +56,296 @@
#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
#endif
-
/*
- * enum dmx_success: Success codes for the Demux Callback API.
+ * TS packet reception
*/
-enum dmx_success {
- DMX_OK = 0, /* Received Ok */
- DMX_LENGTH_ERROR, /* Incorrect length */
- DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
- DMX_CRC_ERROR, /* Incorrect CRC */
- DMX_FRAME_ERROR, /* Frame alignment error */
- DMX_FIFO_ERROR, /* Receiver FIFO overrun */
- DMX_MISSED_ERROR /* Receiver missed packet */
-} ;
-
-/*--------------------------------------------------------------------------*/
-/* TS packet reception */
-/*--------------------------------------------------------------------------*/
-
-/* TS filter type for set() */
-
-#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */
-#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS
- payload (<=184 bytes per packet) to callback */
-#define TS_DECODER 4 /* send stream to built-in decoder (if present) */
-#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to
- the demux device, not to the dvr device */
+/**
+ * enum ts_filter_type - filter type bitmap for dmx_ts_feed.set()
+ *
+ * @TS_PACKET: Send TS packets (188 bytes) to callback (default).
+ * @TS_PAYLOAD_ONLY: In case TS_PACKET is set, only send the TS payload
+ * (<=184 bytes per packet) to callback
+ * @TS_DECODER: Send stream to built-in decoder (if present).
+ * @TS_DEMUX: In case TS_PACKET is set, send the TS to the demux
+ * device, not to the dvr device
+ */
+enum ts_filter_type {
+ TS_PACKET = 1,
+ TS_PAYLOAD_ONLY = 2,
+ TS_DECODER = 4,
+ TS_DEMUX = 8,
+};
+/**
+ * struct dmx_ts_feed - Structure that contains a TS feed filter
+ *
+ * @is_filtering: Set to non-zero when filtering in progress
+ * @parent: pointer to struct dmx_demux
+ * @priv: pointer to private data of the API client
+ * @set: sets the TS filter
+ * @start_filtering: starts TS filtering
+ * @stop_filtering: stops TS filtering
+ *
+ * A TS feed is typically mapped to a hardware PID filter on the demux chip.
+ * Using this API, the client can set the filtering properties to start/stop
+ * filtering TS packets on a particular TS feed.
+ */
struct dmx_ts_feed {
- int is_filtering; /* Set to non-zero when filtering in progress */
- struct dmx_demux *parent; /* Back-pointer */
- void *priv; /* Pointer to private data of the API client */
- int (*set) (struct dmx_ts_feed *feed,
- u16 pid,
- int type,
- enum dmx_ts_pes pes_type,
- size_t circular_buffer_size,
- struct timespec timeout);
- int (*start_filtering) (struct dmx_ts_feed* feed);
- int (*stop_filtering) (struct dmx_ts_feed* feed);
+ int is_filtering;
+ struct dmx_demux *parent;
+ void *priv;
+ int (*set)(struct dmx_ts_feed *feed,
+ u16 pid,
+ int type,
+ enum dmx_ts_pes pes_type,
+ size_t circular_buffer_size,
+ struct timespec timeout);
+ int (*start_filtering)(struct dmx_ts_feed *feed);
+ int (*stop_filtering)(struct dmx_ts_feed *feed);
};
-/*--------------------------------------------------------------------------*/
-/* Section reception */
-/*--------------------------------------------------------------------------*/
+/*
+ * Section reception
+ */
+/**
+ * struct dmx_section_filter - Structure that describes a section filter
+ *
+ * @filter_value: Contains up to 16 bytes (128 bits) of the TS section header
+ * that will be matched by the section filter
+ * @filter_mask: Contains a 16 bytes (128 bits) filter mask with the bits
+ * specified by @filter_value that will be used on the filter
+ * match logic.
+ * @filter_mode: Contains a 16 bytes (128 bits) filter mode.
+ * @parent: Pointer to struct dmx_section_feed.
+ * @priv: Pointer to private data of the API client.
+ *
+ *
+ * The @filter_mask controls which bits of @filter_value are compared with
+ * the section headers/payload. On a binary value of 1 in filter_mask, the
+ * corresponding bits are compared. The filter only accepts sections that are
+ * equal to filter_value in all the tested bit positions.
+ */
struct dmx_section_filter {
- u8 filter_value [DMX_MAX_FILTER_SIZE];
- u8 filter_mask [DMX_MAX_FILTER_SIZE];
- u8 filter_mode [DMX_MAX_FILTER_SIZE];
- struct dmx_section_feed* parent; /* Back-pointer */
- void* priv; /* Pointer to private data of the API client */
+ u8 filter_value[DMX_MAX_FILTER_SIZE];
+ u8 filter_mask[DMX_MAX_FILTER_SIZE];
+ u8 filter_mode[DMX_MAX_FILTER_SIZE];
+ struct dmx_section_feed *parent; /* Back-pointer */
+ void *priv; /* Pointer to private data of the API client */
};
+/**
+ * struct dmx_section_feed - Structure that contains a section feed filter
+ *
+ * @is_filtering: Set to non-zero when filtering in progress
+ * @parent: pointer to struct dmx_demux
+ * @priv: pointer to private data of the API client
+ * @check_crc: If non-zero, check the CRC values of filtered sections.
+ * @set: sets the section filter
+ * @allocate_filter: This function is used to allocate a section filter on
+ * the demux. It should only be called when no filtering
+ * is in progress on this section feed. If a filter cannot
+ * be allocated, the function fails with -ENOSPC.
+ * @release_filter: This function releases all the resources of a
+ * previously allocated section filter. The function
+ * should not be called while filtering is in progress
+ * on this section feed. After calling this function,
+ * the caller should not try to dereference the filter
+ * pointer.
+ * @start_filtering: starts section filtering
+ * @stop_filtering: stops section filtering
+ *
+ * A TS feed is typically mapped to a hardware PID filter on the demux chip.
+ * Using this API, the client can set the filtering properties to start/stop
+ * filtering TS packets on a particular TS feed.
+ */
struct dmx_section_feed {
- int is_filtering; /* Set to non-zero when filtering in progress */
- struct dmx_demux* parent; /* Back-pointer */
- void* priv; /* Pointer to private data of the API client */
+ int is_filtering;
+ struct dmx_demux *parent;
+ void *priv;
int check_crc;
+
+ /* private: Used internally at dvb_demux.c */
u32 crc_val;
u8 *secbuf;
u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
u16 secbufp, seclen, tsfeedp;
- int (*set) (struct dmx_section_feed* feed,
- u16 pid,
- size_t circular_buffer_size,
- int check_crc);
- int (*allocate_filter) (struct dmx_section_feed* feed,
- struct dmx_section_filter** filter);
- int (*release_filter) (struct dmx_section_feed* feed,
- struct dmx_section_filter* filter);
- int (*start_filtering) (struct dmx_section_feed* feed);
- int (*stop_filtering) (struct dmx_section_feed* feed);
+ /* public: */
+ int (*set)(struct dmx_section_feed *feed,
+ u16 pid,
+ size_t circular_buffer_size,
+ int check_crc);
+ int (*allocate_filter)(struct dmx_section_feed *feed,
+ struct dmx_section_filter **filter);
+ int (*release_filter)(struct dmx_section_feed *feed,
+ struct dmx_section_filter *filter);
+ int (*start_filtering)(struct dmx_section_feed *feed);
+ int (*stop_filtering)(struct dmx_section_feed *feed);
};
-/*--------------------------------------------------------------------------*/
-/* Callback functions */
-/*--------------------------------------------------------------------------*/
-
-typedef int (*dmx_ts_cb) ( const u8 * buffer1,
- size_t buffer1_length,
- const u8 * buffer2,
- size_t buffer2_length,
- struct dmx_ts_feed* source,
- enum dmx_success success);
+/*
+ * Callback functions
+ */
-typedef int (*dmx_section_cb) ( const u8 * buffer1,
- size_t buffer1_len,
- const u8 * buffer2,
- size_t buffer2_len,
- struct dmx_section_filter * source,
- enum dmx_success success);
+/**
+ * typedef dmx_ts_cb - DVB demux TS filter callback function prototype
+ *
+ * @buffer1: Pointer to the start of the filtered TS packets.
+ * @buffer1_length: Length of the TS data in buffer1.
+ * @buffer2: Pointer to the tail of the filtered TS packets, or NULL.
+ * @buffer2_length: Length of the TS data in buffer2.
+ * @source: Indicates which TS feed is the source of the callback.
+ *
+ * This function callback prototype, provided by the client of the demux API,
+ * is called from the demux code. The function is only called when filtering
+ * on ae TS feed has been enabled using the start_filtering() function at
+ * the &dmx_demux.
+ * Any TS packets that match the filter settings are copied to a circular
+ * buffer. The filtered TS packets are delivered to the client using this
+ * callback function. The size of the circular buffer is controlled by the
+ * circular_buffer_size parameter of the &dmx_ts_feed.@set function.
+ * It is expected that the @buffer1 and @buffer2 callback parameters point to
+ * addresses within the circular buffer, but other implementations are also
+ * possible. Note that the called party should not try to free the memory
+ * the @buffer1 and @buffer2 parameters point to.
+ *
+ * When this function is called, the @buffer1 parameter typically points to
+ * the start of the first undelivered TS packet within a circular buffer.
+ * The @buffer2 buffer parameter is normally NULL, except when the received
+ * TS packets have crossed the last address of the circular buffer and
+ * ”wrapped” to the beginning of the buffer. In the latter case the @buffer1
+ * parameter would contain an address within the circular buffer, while the
+ * @buffer2 parameter would contain the first address of the circular buffer.
+ * The number of bytes delivered with this function (i.e. @buffer1_length +
+ * @buffer2_length) is usually equal to the value of callback_length parameter
+ * given in the set() function, with one exception: if a timeout occurs before
+ * receiving callback_length bytes of TS data, any undelivered packets are
+ * immediately delivered to the client by calling this function. The timeout
+ * duration is controlled by the set() function in the TS Feed API.
+ *
+ * If a TS packet is received with errors that could not be fixed by the
+ * TS-level forward error correction (FEC), the Transport_error_indicator
+ * flag of the TS packet header should be set. The TS packet should not be
+ * discarded, as the error can possibly be corrected by a higher layer
+ * protocol. If the called party is slow in processing the callback, it
+ * is possible that the circular buffer eventually fills up. If this happens,
+ * the demux driver should discard any TS packets received while the buffer
+ * is full and return -EOVERFLOW.
+ *
+ * The type of data returned to the callback can be selected by the
+ * &dmx_ts_feed.@set function. The type parameter decides if the raw
+ * TS packet (TS_PACKET) or just the payload (TS_PACKET|TS_PAYLOAD_ONLY)
+ * should be returned. If additionally the TS_DECODER bit is set the stream
+ * will also be sent to the hardware MPEG decoder.
+ *
+ * Return:
+ * 0, on success;
+ * -EOVERFLOW, on buffer overflow.
+ */
+typedef int (*dmx_ts_cb)(const u8 *buffer1,
+ size_t buffer1_length,
+ const u8 *buffer2,
+ size_t buffer2_length,
+ struct dmx_ts_feed *source);
+
+/**
+ * typedef dmx_section_cb - DVB demux TS filter callback function prototype
+ *
+ * @buffer1: Pointer to the start of the filtered section, e.g.
+ * within the circular buffer of the demux driver.
+ * @buffer1_len: Length of the filtered section data in @buffer1,
+ * including headers and CRC.
+ * @buffer2: Pointer to the tail of the filtered section data,
+ * or NULL. Useful to handle the wrapping of a
+ * circular buffer.
+ * @buffer2_len: Length of the filtered section data in @buffer2,
+ * including headers and CRC.
+ * @source: Indicates which section feed is the source of the
+ * callback.
+ *
+ * This function callback prototype, provided by the client of the demux API,
+ * is called from the demux code. The function is only called when
+ * filtering of sections has been enabled using the function
+ * &dmx_ts_feed.@start_filtering. When the demux driver has received a
+ * complete section that matches at least one section filter, the client
+ * is notified via this callback function. Normally this function is called
+ * for each received section; however, it is also possible to deliver
+ * multiple sections with one callback, for example when the system load
+ * is high. If an error occurs while receiving a section, this
+ * function should be called with the corresponding error type set in the
+ * success field, whether or not there is data to deliver. The Section Feed
+ * implementation should maintain a circular buffer for received sections.
+ * However, this is not necessary if the Section Feed API is implemented as
+ * a client of the TS Feed API, because the TS Feed implementation then
+ * buffers the received data. The size of the circular buffer can be
+ * configured using the &dmx_ts_feed.@set function in the Section Feed API.
+ * If there is no room in the circular buffer when a new section is received,
+ * the section must be discarded. If this happens, the value of the success
+ * parameter should be DMX_OVERRUN_ERROR on the next callback.
+ */
+typedef int (*dmx_section_cb)(const u8 *buffer1,
+ size_t buffer1_len,
+ const u8 *buffer2,
+ size_t buffer2_len,
+ struct dmx_section_filter *source);
/*--------------------------------------------------------------------------*/
/* DVB Front-End */
/*--------------------------------------------------------------------------*/
+/**
+ * enum dmx_frontend_source - Used to identify the type of frontend
+ *
+ * @DMX_MEMORY_FE: The source of the demux is memory. It means that
+ * the MPEG-TS to be filtered comes from userspace,
+ * via write() syscall.
+ *
+ * @DMX_FRONTEND_0: The source of the demux is a frontend connected
+ * to the demux.
+ */
enum dmx_frontend_source {
DMX_MEMORY_FE,
DMX_FRONTEND_0,
- DMX_FRONTEND_1,
- DMX_FRONTEND_2,
- DMX_FRONTEND_3,
- DMX_STREAM_0, /* external stream input, e.g. LVDS */
- DMX_STREAM_1,
- DMX_STREAM_2,
- DMX_STREAM_3
};
+/**
+ * struct dmx_frontend - Structure that lists the frontends associated with
+ * a demux
+ *
+ * @connectivity_list: List of front-ends that can be connected to a
+ * particular demux;
+ * @source: Type of the frontend.
+ *
+ * FIXME: this structure should likely be replaced soon by some
+ * media-controller based logic.
+ */
struct dmx_frontend {
- struct list_head connectivity_list; /* List of front-ends that can
- be connected to a particular
- demux */
+ struct list_head connectivity_list;
enum dmx_frontend_source source;
};
-/*--------------------------------------------------------------------------*/
-/* MPEG-2 TS Demux */
-/*--------------------------------------------------------------------------*/
-
/*
- * Flags OR'ed in the capabilities field of struct dmx_demux.
+ * MPEG-2 TS Demux
*/
-#define DMX_TS_FILTERING 1
-#define DMX_PES_FILTERING 2
-#define DMX_SECTION_FILTERING 4
-#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
-#define DMX_CRC_CHECKING 16
-#define DMX_TS_DESCRAMBLING 32
+/**
+ * enum dmx_demux_caps - MPEG-2 TS Demux capabilities bitmap
+ *
+ * @DMX_TS_FILTERING: set if TS filtering is supported;
+ * @DMX_SECTION_FILTERING: set if section filtering is supported;
+ * @DMX_MEMORY_BASED_FILTERING: set if write() available.
+ *
+ * Those flags are OR'ed in the &dmx_demux.&capabilities field
+ */
+enum dmx_demux_caps {
+ DMX_TS_FILTERING = 1,
+ DMX_SECTION_FILTERING = 4,
+ DMX_MEMORY_BASED_FILTERING = 8,
+};
/*
* Demux resource type identifier.
@@ -200,42 +358,241 @@ struct dmx_frontend {
*.
*/
-#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
+#define DMX_FE_ENTRY(list) \
+ list_entry(list, struct dmx_frontend, connectivity_list)
+
+/**
+ * struct dmx_demux - Structure that contains the demux capabilities and
+ * callbacks.
+ *
+ * @capabilities: Bitfield of capability flags.
+ *
+ * @frontend: Front-end connected to the demux
+ *
+ * @priv: Pointer to private data of the API client
+ *
+ * @open: This function reserves the demux for use by the caller and, if
+ * necessary, initializes the demux. When the demux is no longer needed,
+ * the function @close should be called. It should be possible for
+ * multiple clients to access the demux at the same time. Thus, the
+ * function implementation should increment the demux usage count when
+ * @open is called and decrement it when @close is called.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -EUSERS, if maximum usage count was reached;
+ * -EINVAL, on bad parameter.
+ *
+ * @close: This function reserves the demux for use by the caller and, if
+ * necessary, initializes the demux. When the demux is no longer needed,
+ * the function @close should be called. It should be possible for
+ * multiple clients to access the demux at the same time. Thus, the
+ * function implementation should increment the demux usage count when
+ * @open is called and decrement it when @close is called.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -ENODEV, if demux was not in use (e. g. no users);
+ * -EINVAL, on bad parameter.
+ *
+ * @write: This function provides the demux driver with a memory buffer
+ * containing TS packets. Instead of receiving TS packets from the DVB
+ * front-end, the demux driver software will read packets from memory.
+ * Any clients of this demux with active TS, PES or Section filters will
+ * receive filtered data via the Demux callback API (see 0). The function
+ * returns when all the data in the buffer has been consumed by the demux.
+ * Demux hardware typically cannot read TS from memory. If this is the
+ * case, memory-based filtering has to be implemented entirely in software.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @buf function parameter contains a pointer to the TS data in
+ * kernel-space memory.
+ * The @count function parameter contains the length of the TS data.
+ * It returns
+ * 0 on success;
+ * -ERESTARTSYS, if mutex lock was interrupted;
+ * -EINTR, if a signal handling is pending;
+ * -ENODEV, if demux was removed;
+ * -EINVAL, on bad parameter.
+ *
+ * @allocate_ts_feed: Allocates a new TS feed, which is used to filter the TS
+ * packets carrying a certain PID. The TS feed normally corresponds to a
+ * hardware PID filter on the demux chip.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @feed function parameter contains a pointer to the TS feed API and
+ * instance data.
+ * The @callback function parameter contains a pointer to the callback
+ * function for passing received TS packet.
+ * It returns
+ * 0 on success;
+ * -ERESTARTSYS, if mutex lock was interrupted;
+ * -EBUSY, if no more TS feeds is available;
+ * -EINVAL, on bad parameter.
+ *
+ * @release_ts_feed: Releases the resources allocated with @allocate_ts_feed.
+ * Any filtering in progress on the TS feed should be stopped before
+ * calling this function.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @feed function parameter contains a pointer to the TS feed API and
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -EINVAL on bad parameter.
+ *
+ * @allocate_section_feed: Allocates a new section feed, i.e. a demux resource
+ * for filtering and receiving sections. On platforms with hardware
+ * support for section filtering, a section feed is directly mapped to
+ * the demux HW. On other platforms, TS packets are first PID filtered in
+ * hardware and a hardware section filter then emulated in software. The
+ * caller obtains an API pointer of type dmx_section_feed_t as an out
+ * parameter. Using this API the caller can set filtering parameters and
+ * start receiving sections.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @feed function parameter contains a pointer to the TS feed API and
+ * instance data.
+ * The @callback function parameter contains a pointer to the callback
+ * function for passing received TS packet.
+ * It returns
+ * 0 on success;
+ * -EBUSY, if no more TS feeds is available;
+ * -EINVAL, on bad parameter.
+ *
+ * @release_section_feed: Releases the resources allocated with
+ * @allocate_section_feed, including allocated filters. Any filtering in
+ * progress on the section feed should be stopped before calling this
+ * function.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @feed function parameter contains a pointer to the TS feed API and
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -EINVAL, on bad parameter.
+ *
+ * @add_frontend: Registers a connectivity between a demux and a front-end,
+ * i.e., indicates that the demux can be connected via a call to
+ * @connect_frontend to use the given front-end as a TS source. The
+ * client of this function has to allocate dynamic or static memory for
+ * the frontend structure and initialize its fields before calling this
+ * function. This function is normally called during the driver
+ * initialization. The caller must not free the memory of the frontend
+ * struct before successfully calling @remove_frontend.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @frontend function parameter contains a pointer to the front-end
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -EINVAL, on bad parameter.
+ *
+ * @remove_frontend: Indicates that the given front-end, registered by a call
+ * to @add_frontend, can no longer be connected as a TS source by this
+ * demux. The function should be called when a front-end driver or a demux
+ * driver is removed from the system. If the front-end is in use, the
+ * function fails with the return value of -EBUSY. After successfully
+ * calling this function, the caller can free the memory of the frontend
+ * struct if it was dynamically allocated before the @add_frontend
+ * operation.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @frontend function parameter contains a pointer to the front-end
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -ENODEV, if the front-end was not found,
+ * -EINVAL, on bad parameter.
+ *
+ * @get_frontends: Provides the APIs of the front-ends that have been
+ * registered for this demux. Any of the front-ends obtained with this
+ * call can be used as a parameter for @connect_frontend. The include
+ * file demux.h contains the macro DMX_FE_ENTRY() for converting an
+ * element of the generic type struct &list_head * to the type
+ * struct &dmx_frontend *. The caller must not free the memory of any of
+ * the elements obtained via this function call.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * It returns a struct list_head pointer to the list of front-end
+ * interfaces, or NULL in the case of an empty list.
+ *
+ * @connect_frontend: Connects the TS output of the front-end to the input of
+ * the demux. A demux can only be connected to a front-end registered to
+ * the demux with the function @add_frontend. It may or may not be
+ * possible to connect multiple demuxes to the same front-end, depending
+ * on the capabilities of the HW platform. When not used, the front-end
+ * should be released by calling @disconnect_frontend.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @frontend function parameter contains a pointer to the front-end
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -EINVAL, on bad parameter.
+ *
+ * @disconnect_frontend: Disconnects the demux and a front-end previously
+ * connected by a @connect_frontend call.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * It returns
+ * 0 on success;
+ * -EINVAL on bad parameter.
+ *
+ * @get_pes_pids: Get the PIDs for DMX_PES_AUDIO0, DMX_PES_VIDEO0,
+ * DMX_PES_TELETEXT0, DMX_PES_SUBTITLE0 and DMX_PES_PCR0.
+ * The @demux function parameter contains a pointer to the demux API and
+ * instance data.
+ * The @pids function parameter contains an array with five u16 elements
+ * where the PIDs will be stored.
+ * It returns
+ * 0 on success;
+ * -EINVAL on bad parameter.
+ */
struct dmx_demux {
- u32 capabilities; /* Bitfield of capability flags */
- struct dmx_frontend* frontend; /* Front-end connected to the demux */
- void* priv; /* Pointer to private data of the API client */
- int (*open) (struct dmx_demux* demux);
- int (*close) (struct dmx_demux* demux);
- int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
- int (*allocate_ts_feed) (struct dmx_demux* demux,
- struct dmx_ts_feed** feed,
- dmx_ts_cb callback);
- int (*release_ts_feed) (struct dmx_demux* demux,
- struct dmx_ts_feed* feed);
- int (*allocate_section_feed) (struct dmx_demux* demux,
- struct dmx_section_feed** feed,
- dmx_section_cb callback);
- int (*release_section_feed) (struct dmx_demux* demux,
- struct dmx_section_feed* feed);
- int (*add_frontend) (struct dmx_demux* demux,
- struct dmx_frontend* frontend);
- int (*remove_frontend) (struct dmx_demux* demux,
- struct dmx_frontend* frontend);
- struct list_head* (*get_frontends) (struct dmx_demux* demux);
- int (*connect_frontend) (struct dmx_demux* demux,
- struct dmx_frontend* frontend);
- int (*disconnect_frontend) (struct dmx_demux* demux);
-
- int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
-
- int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
-
- int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
-
- int (*get_stc) (struct dmx_demux* demux, unsigned int num,
- u64 *stc, unsigned int *base);
+ enum dmx_demux_caps capabilities;
+ struct dmx_frontend *frontend;
+ void *priv;
+ int (*open)(struct dmx_demux *demux);
+ int (*close)(struct dmx_demux *demux);
+ int (*write)(struct dmx_demux *demux, const char __user *buf,
+ size_t count);
+ int (*allocate_ts_feed)(struct dmx_demux *demux,
+ struct dmx_ts_feed **feed,
+ dmx_ts_cb callback);
+ int (*release_ts_feed)(struct dmx_demux *demux,
+ struct dmx_ts_feed *feed);
+ int (*allocate_section_feed)(struct dmx_demux *demux,
+ struct dmx_section_feed **feed,
+ dmx_section_cb callback);
+ int (*release_section_feed)(struct dmx_demux *demux,
+ struct dmx_section_feed *feed);
+ int (*add_frontend)(struct dmx_demux *demux,
+ struct dmx_frontend *frontend);
+ int (*remove_frontend)(struct dmx_demux *demux,
+ struct dmx_frontend *frontend);
+ struct list_head *(*get_frontends)(struct dmx_demux *demux);
+ int (*connect_frontend)(struct dmx_demux *demux,
+ struct dmx_frontend *frontend);
+ int (*disconnect_frontend)(struct dmx_demux *demux);
+
+ int (*get_pes_pids)(struct dmx_demux *demux, u16 *pids);
+
+ /* private: Not used upstream and never documented */
+#if 0
+ int (*get_caps)(struct dmx_demux *demux, struct dmx_caps *caps);
+ int (*set_source)(struct dmx_demux *demux, const dmx_source_t *src);
+#endif
+ /*
+ * private: Only used at av7110, to read some data from firmware.
+ * As this was never documented, we have no clue about what's
+ * there, and its usage on other drivers aren't encouraged.
+ */
+ int (*get_stc)(struct dmx_demux *demux, unsigned int num,
+ u64 *stc, unsigned int *base);
};
#endif /* #ifndef __DEMUX_H */
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index d0e3f9d85f34..ea9abde902e9 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -352,8 +352,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
- struct dmx_section_filter *filter,
- enum dmx_success success)
+ struct dmx_section_filter *filter)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret;
@@ -386,8 +385,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
- struct dmx_ts_feed *feed,
- enum dmx_success success)
+ struct dmx_ts_feed *feed)
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
@@ -1023,6 +1021,9 @@ static int dvb_demux_do_ioctl(struct file *file,
dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
break;
+#if 0
+ /* Not used upstream and never documented */
+
case DMX_GET_CAPS:
if (!dmxdev->demux->get_caps) {
ret = -EINVAL;
@@ -1038,6 +1039,7 @@ static int dvb_demux_do_ioctl(struct file *file,
}
ret = dmxdev->demux->set_source(dmxdev->demux, parg);
break;
+#endif
case DMX_GET_STC:
if (!dmxdev->demux->get_stc) {
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index c117fb3b4aff..0a46580b5376 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -257,6 +257,7 @@
#define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab
#define USB_PID_TERRATEC_H7 0x10b4
#define USB_PID_TERRATEC_H7_2 0x10a3
+#define USB_PID_TERRATEC_H7_3 0x10a5
#define USB_PID_TERRATEC_T3 0x10a0
#define USB_PID_TERRATEC_T5 0x10a1
#define USB_PID_NOXON_DAB_STICK 0x00b3
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb-core/dvb_ca_en50221.h
index aba3b4fbd704..1e4bbbd34d91 100644
--- a/drivers/media/dvb-core/dvb_ca_en50221.h
+++ b/drivers/media/dvb-core/dvb_ca_en50221.h
@@ -12,10 +12,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 Lesser 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.
*/
#ifndef _DVB_CA_EN50221_H_
@@ -37,50 +33,53 @@
#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0
#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1
-
-
-/* Structure describing a CA interface */
+/**
+ * struct dvb_ca_en50221- Structure describing a CA interface
+ *
+ * @owner: the module owning this structure
+ * @read_attribute_mem: function for reading attribute memory on the CAM
+ * @write_attribute_mem: function for writing attribute memory on the CAM
+ * @read_cam_control: function for reading the control interface on the CAM
+ * @write_cam_control: function for reading the control interface on the CAM
+ * @slot_reset: function to reset the CAM slot
+ * @slot_shutdown: function to shutdown a CAM slot
+ * @slot_ts_enable: function to enable the Transport Stream on a CAM slot
+ * @poll_slot_status: function to poll slot status. Only necessary if
+ * DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set.
+ * @data: private data, used by caller.
+ * @private: Opaque data used by the dvb_ca core. Do not modify!
+ *
+ * NOTE: the read_*, write_* and poll_slot_status functions will be
+ * called for different slots concurrently and need to use locks where
+ * and if appropriate. There will be no concurrent access to one slot.
+ */
struct dvb_ca_en50221 {
+ struct module *owner;
- /* the module owning this structure */
- struct module* owner;
-
- /* NOTE: the read_*, write_* and poll_slot_status functions will be
- * called for different slots concurrently and need to use locks where
- * and if appropriate. There will be no concurrent access to one slot.
- */
+ int (*read_attribute_mem)(struct dvb_ca_en50221 *ca,
+ int slot, int address);
+ int (*write_attribute_mem)(struct dvb_ca_en50221 *ca,
+ int slot, int address, u8 value);
- /* functions for accessing attribute memory on the CAM */
- int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
- int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
+ int (*read_cam_control)(struct dvb_ca_en50221 *ca,
+ int slot, u8 address);
+ int (*write_cam_control)(struct dvb_ca_en50221 *ca,
+ int slot, u8 address, u8 value);
- /* functions for accessing the control interface on the CAM */
- int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
- int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
+ int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot);
+ int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot);
+ int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot);
- /* Functions for controlling slots */
- int (*slot_reset)(struct dvb_ca_en50221* ca, int slot);
- int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot);
- int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot);
+ int (*poll_slot_status)(struct dvb_ca_en50221 *ca, int slot, int open);
- /*
- * Poll slot status.
- * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
- */
- int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
+ void *data;
- /* private data, used by caller */
- void* data;
-
- /* Opaque data used by the dvb_ca core. Do not modify! */
- void* private;
+ void *private;
};
-
-
-
-/* ******************************************************************************** */
-/* Functions for reporting IRQ events */
+/*
+ * Functions for reporting IRQ events
+ */
/**
* dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred.
@@ -89,7 +88,8 @@ struct dvb_ca_en50221 {
* @slot: Slot concerned.
* @change_type: One of the DVB_CA_CAMCHANGE_* values
*/
-void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
+void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot,
+ int change_type);
/**
* dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred.
@@ -97,7 +97,7 @@ void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int ch
* @pubca: CA instance.
* @slot: Slot concerned.
*/
-void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
+void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot);
/**
* dvb_ca_en50221_frda_irq - An FR or a DA IRQ has occurred.
@@ -105,12 +105,11 @@ void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
* @ca: CA instance.
* @slot: Slot concerned.
*/
-void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
-
+void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *ca, int slot);
-
-/* ******************************************************************************** */
-/* Initialisation/shutdown functions */
+/*
+ * Initialisation/shutdown functions
+ */
/**
* dvb_ca_en50221_init - Initialise a new DVB CA device.
@@ -122,15 +121,15 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
*
* @return 0 on success, nonzero on failure
*/
-extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
+extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
+ struct dvb_ca_en50221 *ca, int flags,
+ int slot_count);
/**
* dvb_ca_en50221_release - Release a DVB CA device.
*
* @ca: The associated dvb_ca instance.
*/
-extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
-
-
+extern void dvb_ca_en50221_release(struct dvb_ca_en50221 *ca);
#endif
diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
index 6c7ff0cdcd32..0cc5e935166c 100644
--- a/drivers/media/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -130,7 +130,7 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
feed->peslen += count;
- return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+ return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts);
}
static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
@@ -152,7 +152,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
return 0;
return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
- NULL, 0, &f->filter, DMX_OK);
+ NULL, 0, &f->filter);
}
static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
@@ -367,8 +367,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf);
else
- feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
- DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
}
if (feed->ts_type & TS_DECODER)
if (feed->demux->write_to_decoder)
@@ -469,7 +468,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
if (feed->pid == pid)
dvb_dmx_swfilter_packet_type(feed, buf);
else if (feed->pid == 0x2000)
- feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
}
}
@@ -588,7 +587,7 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
spin_lock_irqsave(&demux->lock, flags);
- demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
+ demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts);
spin_unlock_irqrestore(&demux->lock, flags);
}
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index b81e026edab3..ce4332e80a91 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -761,7 +761,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
- struct dmx_ts_feed *feed, enum dmx_success success)
+ struct dmx_ts_feed *feed)
{
struct net_device *dev = feed->priv;
@@ -870,8 +870,7 @@ static void dvb_net_sec(struct net_device *dev,
static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
- struct dmx_section_filter *filter,
- enum dmx_success success)
+ struct dmx_section_filter *filter)
{
struct net_device *dev = filter->priv;
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index c61a4f03a66f..1069a776bbdb 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -184,10 +184,6 @@ int dvb_unregister_adapter(struct dvb_adapter *adap);
* @pdvbdev: pointer to the place where the new struct dvb_device will be
* stored
* @template: Template used to create &pdvbdev;
- * @device: pointer to struct device that corresponds to the device driver
- * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter;
- * to select among them. Typically, initialized with:
- * DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums)
* @priv: private data
* @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND,
* DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
index 34b9441840da..445a15c2714f 100644
--- a/drivers/media/dvb-frontends/drxd_hard.c
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -2950,10 +2950,9 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
{
struct drxd_state *state = NULL;
- state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL);
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return NULL;
- memset(state, 0, sizeof(*state));
state->ops = drxd_ops;
state->dev = dev;
diff --git a/drivers/media/dvb-frontends/horus3a.h b/drivers/media/dvb-frontends/horus3a.h
index b055319d532e..c1e2d1834b78 100644
--- a/drivers/media/dvb-frontends/horus3a.h
+++ b/drivers/media/dvb-frontends/horus3a.h
@@ -46,8 +46,8 @@ extern struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
const struct horus3a_config *config,
struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend *horus3a_attach(
- const struct cxd2820r_config *config,
+static inline struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
+ const struct horus3a_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb-frontends/lnbh25.h b/drivers/media/dvb-frontends/lnbh25.h
index 69f30e21f6b3..1f329ef05acc 100644
--- a/drivers/media/dvb-frontends/lnbh25.h
+++ b/drivers/media/dvb-frontends/lnbh25.h
@@ -43,7 +43,7 @@ struct dvb_frontend *lnbh25_attach(
struct lnbh25_config *cfg,
struct i2c_adapter *i2c);
#else
-static inline dvb_frontend *lnbh25_attach(
+static inline struct dvb_frontend *lnbh25_attach(
struct dvb_frontend *fe,
struct lnbh25_config *cfg,
struct i2c_adapter *i2c)
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index ff31e7a01ca9..feeeb70d841e 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -18,6 +18,27 @@
static struct dvb_frontend_ops m88ds3103_ops;
+/* write single register with mask */
+static int m88ds3103_update_bits(struct m88ds3103_dev *dev,
+ u8 reg, u8 mask, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return regmap_bulk_write(dev->regmap, reg, &val, 1);
+}
+
/* write reg val table using reg addr auto increment */
static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
const struct m88ds3103_reg_val *tab, int tab_len)
@@ -394,10 +415,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
u8tmp2 = 0x00; /* 0b00 */
break;
}
- ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6);
+ ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6);
+ ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
if (ret)
goto err;
}
@@ -455,13 +476,13 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
if (ret)
goto err;
}
- ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08);
+ ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0xf1, 0x01);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80);
+ ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
if (ret)
goto err;
}
@@ -498,7 +519,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
switch (dev->cfg->ts_mode) {
case M88DS3103_TS_SERIAL:
case M88DS3103_TS_SERIAL_D7:
- ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1);
+ ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
if (ret)
goto err;
u8tmp1 = 0;
@@ -567,11 +588,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1);
+ ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4);
+ ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
if (ret)
goto err;
@@ -625,13 +646,13 @@ static int m88ds3103_init(struct dvb_frontend *fe)
dev->warm = false;
/* wake up device from sleep */
- ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01);
+ ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x01);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x00);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x00);
if (ret)
goto err;
@@ -749,18 +770,18 @@ static int m88ds3103_sleep(struct dvb_frontend *fe)
utmp = 0x29;
else
utmp = 0x27;
- ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, utmp, 0x01, 0x00);
if (ret)
goto err;
/* sleep */
- ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+ ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+ ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
if (ret)
goto err;
@@ -992,12 +1013,12 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe,
}
utmp = tone << 7 | dev->cfg->envelope_mode << 5;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
if (ret)
goto err;
utmp = 1 << 2;
- ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa1, reg_a1_mask, utmp);
if (ret)
goto err;
@@ -1047,7 +1068,7 @@ static int m88ds3103_set_voltage(struct dvb_frontend *fe,
voltage_dis ^= dev->cfg->lnb_en_pol;
utmp = voltage_dis << 1 | voltage_sel << 0;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0x03, utmp);
if (ret)
goto err;
@@ -1080,7 +1101,7 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
}
utmp = dev->cfg->envelope_mode << 5;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
if (ret)
goto err;
@@ -1115,12 +1136,12 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
} else {
dev_dbg(&client->dev, "diseqc tx timeout\n");
- ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+ ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
if (ret)
goto err;
}
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
if (ret)
goto err;
@@ -1152,7 +1173,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
}
utmp = dev->cfg->envelope_mode << 5;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
if (ret)
goto err;
@@ -1194,12 +1215,12 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
} else {
dev_dbg(&client->dev, "diseqc tx timeout\n");
- ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+ ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
if (ret)
goto err;
}
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
if (ret)
goto err;
@@ -1435,13 +1456,13 @@ static int m88ds3103_probe(struct i2c_client *client,
goto err_kfree;
/* sleep */
- ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
if (ret)
goto err_kfree;
- ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+ ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
if (ret)
goto err_kfree;
- ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+ ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
if (ret)
goto err_kfree;
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index d5b994f17612..dcd8d94c1037 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -29,6 +29,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <linux/platform_device.h>
@@ -107,7 +108,8 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
struct rtl2832_sdr_frame_buf {
- struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -304,13 +306,13 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
}
/* fill framebuffer */
- ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+ ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0);
len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer,
urb->actual_length);
- vb2_set_plane_payload(&fbuf->vb, 0, len);
- v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
- fbuf->vb.v4l2_buf.sequence = dev->sequence++;
- vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
+ v4l2_get_timestamp(&fbuf->vb.timestamp);
+ fbuf->vb.sequence = dev->sequence++;
+ vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
skip:
usb_submit_urb(urb, GFP_ATOMIC);
@@ -464,7 +466,7 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev)
buf = list_entry(dev->queued_bufs.next,
struct rtl2832_sdr_frame_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
}
@@ -488,7 +490,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
/* Videobuf2 operations */
static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt, unsigned int *nbuffers,
+ const void *parg, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
@@ -518,14 +520,15 @@ static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
struct rtl2832_sdr_frame_buf *buf =
- container_of(vb, struct rtl2832_sdr_frame_buf, vb);
+ container_of(vbuf, struct rtl2832_sdr_frame_buf, vb);
unsigned long flags;
/* Check the device has not disconnected between prep and queuing */
if (!dev->udev) {
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
return;
}
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 81788c5a44d8..821a8f481507 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -502,6 +502,10 @@ static int si2168_init(struct dvb_frontend *fe)
/* firmware is in the new format */
for (remaining = fw->size; remaining > 0; remaining -= 17) {
len = fw->data[fw->size - remaining];
+ if (len > SI2168_ARGLEN) {
+ ret = -EINVAL;
+ break;
+ }
memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
cmd.wlen = len;
cmd.rlen = 1;
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
index af5eaf2db2a0..38a20fe181ee 100644
--- a/drivers/media/i2c/ml86v7667.c
+++ b/drivers/media/i2c/ml86v7667.c
@@ -233,6 +233,15 @@ static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd,
return 0;
}
+static int ml86v7667_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct ml86v7667_priv *priv = to_ml86v7667(sd);
+
+ *std = priv->std;
+
+ return 0;
+}
+
static int ml86v7667_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
struct ml86v7667_priv *priv = to_ml86v7667(sd);
@@ -282,6 +291,7 @@ static const struct v4l2_ctrl_ops ml86v7667_ctrl_ops = {
};
static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = {
+ .g_std = ml86v7667_g_std,
.s_std = ml86v7667_s_std,
.querystd = ml86v7667_querystd,
.g_input_status = ml86v7667_g_input_status,
@@ -427,7 +437,6 @@ MODULE_DEVICE_TABLE(i2c, ml86v7667_id);
static struct i2c_driver ml86v7667_i2c_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
},
.probe = ml86v7667_probe,
.remove = ml86v7667_remove,
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index e691bba1945b..1ee6a5527c38 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -1133,7 +1133,7 @@ static int __ov965x_set_frame_interval(struct ov965x *ov965x,
if (mbus_fmt->width != iv->size.width ||
mbus_fmt->height != iv->size.height)
continue;
- err = abs64((u64)(iv->interval.numerator * 10000) /
+ err = abs((u64)(iv->interval.numerator * 10000) /
iv->interval.denominator - req_int);
if (err < min_err) {
fiv = iv;
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index 53c5ea89f0b9..51b26010403c 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -167,7 +167,7 @@ static int s5c73m3_i2c_read(struct i2c_client *client, u16 addr, u16 *data)
*/
ret = i2c_transfer(client->adapter, msg, 2);
if (ret == 2) {
- *data = be16_to_cpup((u16 *)rbuf);
+ *data = be16_to_cpup((__be16 *)rbuf);
v4l2_dbg(4, s5c73m3_dbg, client,
"%s: addr: 0x%04x, data: 0x%04x\n",
__func__, addr, *data);
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
index fa4a5ebda6b2..72ef9f936e6c 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
@@ -31,6 +31,7 @@ static const struct of_device_id s5c73m3_spi_ids[] = {
{ .compatible = "samsung,s5c73m3" },
{ }
};
+MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids);
enum spi_direction {
SPI_DIR_RX,
@@ -149,7 +150,6 @@ int s5c73m3_register_spi_driver(struct s5c73m3 *state)
spidrv->remove = s5c73m3_spi_remove;
spidrv->probe = s5c73m3_spi_probe;
spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
- spidrv->driver.owner = THIS_MODULE;
spidrv->driver.of_match_table = s5c73m3_spi_ids;
return spi_register_driver(spidrv);
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 636ebd6fe5dc..fb39dfd55e75 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -3131,6 +3131,7 @@ static const struct of_device_id smiapp_of_table[] = {
{ .compatible = "nokia,smia" },
{ },
};
+MODULE_DEVICE_TABLE(of, smiapp_of_table);
static const struct i2c_device_id smiapp_id_table[] = {
{ SMIAPP_NAME, 0 },
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 522a865c5c60..3c5fb2509c47 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -10,6 +10,7 @@
#include <linux/videodev2.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
#include <media/tvp5150.h>
#include <media/v4l2-ctrls.h>
@@ -1172,8 +1173,7 @@ static int tvp5150_probe(struct i2c_client *c,
sd->ctrl_handler = &core->hdl;
if (core->hdl.error) {
res = core->hdl.error;
- v4l2_ctrl_handler_free(&core->hdl);
- return res;
+ goto err;
}
v4l2_ctrl_handler_setup(&core->hdl);
@@ -1186,9 +1186,17 @@ static int tvp5150_probe(struct i2c_client *c,
core->rect.left = 0;
core->rect.width = TVP5150_H_MAX;
+ res = v4l2_async_register_subdev(sd);
+ if (res < 0)
+ goto err;
+
if (debug > 1)
tvp5150_log_status(sd);
return 0;
+
+err:
+ v4l2_ctrl_handler_free(&core->hdl);
+ return res;
}
static int tvp5150_remove(struct i2c_client *c)
@@ -1200,7 +1208,7 @@ static int tvp5150_remove(struct i2c_client *c)
"tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
c->addr << 1);
- v4l2_device_unregister_subdev(sd);
+ v4l2_async_unregister_subdev(sd);
v4l2_ctrl_handler_free(&decoder->hdl);
return 0;
}
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 153a46469814..767fe55ba08e 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -235,8 +235,8 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
media_entity_graph_walk_start(&graph, entity);
while ((entity = media_entity_graph_walk_next(&graph))) {
- DECLARE_BITMAP(active, entity->num_pads);
- DECLARE_BITMAP(has_no_links, entity->num_pads);
+ DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
+ DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
unsigned int i;
entity->stream_count++;
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 3632958f2158..15a4ebc2844d 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -3625,13 +3625,10 @@ static void
bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
unsigned int state)
{
- struct timeval ts;
-
if (NULL == wakeup)
return;
- v4l2_get_timestamp(&ts);
- wakeup->vb.ts = ts;
+ v4l2_get_timestamp(&wakeup->vb.ts);
wakeup->vb.field_count = btv->field_count;
wakeup->vb.state = state;
wake_up(&wakeup->vb.done);
diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig
index 1f88ccc174da..a01f0cc745cc 100644
--- a/drivers/media/pci/cobalt/Kconfig
+++ b/drivers/media/pci/cobalt/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_COBALT
tristate "Cisco Cobalt support"
- depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER
+ depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
depends on PCI_MSI && MTD_COMPLEX_MAPPINGS
depends on GPIOLIB || COMPILE_TEST
depends on SND
diff --git a/drivers/media/pci/cobalt/cobalt-cpld.c b/drivers/media/pci/cobalt/cobalt-cpld.c
index e83f5c9f7e7d..23c875fc173e 100644
--- a/drivers/media/pci/cobalt/cobalt-cpld.c
+++ b/drivers/media/pci/cobalt/cobalt-cpld.c
@@ -290,8 +290,8 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62).
*/
- cobalt_dbg(1, "%u: %02x %02x %02x %02x %02x %02x\n", f_out,
- regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]);
+ cobalt_dbg(1, "%u: %6ph\n", f_out, regs);
+
while (retries--) {
u8 read_regs[6];
@@ -330,9 +330,7 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
if (!memcmp(read_regs, regs, sizeof(read_regs)))
break;
- cobalt_dbg(1, "retry: %02x %02x %02x %02x %02x %02x\n",
- read_regs[0], read_regs[1], read_regs[2],
- read_regs[3], read_regs[4], read_regs[5]);
+ cobalt_dbg(1, "retry: %6ph\n", read_regs);
}
if (2 - retries)
cobalt_info("Needed %d retries\n", 2 - retries);
diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h
index c206df930669..b2f08e4a68bf 100644
--- a/drivers/media/pci/cobalt/cobalt-driver.h
+++ b/drivers/media/pci/cobalt/cobalt-driver.h
@@ -35,6 +35,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
#include "m00233_video_measure_memmap_package.h"
@@ -206,11 +207,12 @@ struct sg_dma_desc_info {
#define COBALT_STREAM_FL_ADV_IRQ 1
struct cobalt_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
-static inline struct cobalt_buffer *to_cobalt_buffer(struct vb2_buffer *vb2)
+static inline
+struct cobalt_buffer *to_cobalt_buffer(struct vb2_v4l2_buffer *vb2)
{
return container_of(vb2, struct cobalt_buffer, vb);
}
diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c
index d1f5898d11ba..3de26d0714b5 100644
--- a/drivers/media/pci/cobalt/cobalt-irq.c
+++ b/drivers/media/pci/cobalt/cobalt-irq.c
@@ -134,11 +134,12 @@ done:
skip = true;
s->skip_first_frames--;
}
- v4l2_get_timestamp(&cb->vb.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&cb->vb.timestamp);
/* TODO: the sequence number should be read from the FPGA so we
also know about dropped frames. */
- cb->vb.v4l2_buf.sequence = s->sequence++;
- vb2_buffer_done(&cb->vb, (skip || s->unstable_frame) ?
+ cb->vb.sequence = s->sequence++;
+ vb2_buffer_done(&cb->vb.vb2_buf,
+ (skip || s->unstable_frame) ?
VB2_BUF_STATE_REQUEUEING : VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
index 9756fd3e8af5..ff46e424262f 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -43,11 +43,11 @@ static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
/* vb2 DMA streaming ops */
-static int cobalt_queue_setup(struct vb2_queue *q,
- const struct v4l2_format *fmt,
+static int cobalt_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct cobalt_stream *s = q->drv_priv;
unsigned size = s->stride * s->height;
@@ -75,7 +75,7 @@ static int cobalt_buf_init(struct vb2_buffer *vb)
const size_t bytes =
COBALT_MAX_HEIGHT * max_pages_per_line * 0x20;
const size_t audio_bytes = ((1920 * 4) / PAGE_SIZE + 1) * 0x20;
- struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index];
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index];
struct sg_table *sg_desc = vb2_dma_sg_plane_desc(vb, 0);
unsigned size;
int ret;
@@ -105,17 +105,18 @@ static int cobalt_buf_init(struct vb2_buffer *vb)
static void cobalt_buf_cleanup(struct vb2_buffer *vb)
{
struct cobalt_stream *s = vb->vb2_queue->drv_priv;
- struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index];
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index];
descriptor_list_free(desc);
}
static int cobalt_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cobalt_stream *s = vb->vb2_queue->drv_priv;
vb2_set_plane_payload(vb, 0, s->stride * s->height);
- vb->v4l2_buf.field = V4L2_FIELD_NONE;
+ vbuf->field = V4L2_FIELD_NONE;
return 0;
}
@@ -128,7 +129,7 @@ static void chain_all_buffers(struct cobalt_stream *s)
list_for_each(p, &s->bufs) {
cb = list_entry(p, struct cobalt_buffer, list);
- desc[i] = &s->dma_desc_info[cb->vb.v4l2_buf.index];
+ desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index];
if (i > 0)
descriptor_list_chain(desc[i-1], desc[i]);
i++;
@@ -137,10 +138,11 @@ static void chain_all_buffers(struct cobalt_stream *s)
static void cobalt_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *q = vb->vb2_queue;
struct cobalt_stream *s = q->drv_priv;
- struct cobalt_buffer *cb = to_cobalt_buffer(vb);
- struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index];
+ struct cobalt_buffer *cb = to_cobalt_buffer(vbuf);
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index];
unsigned long flags;
/* Prepare new buffer */
@@ -284,7 +286,7 @@ static void cobalt_dma_start_streaming(struct cobalt_stream *s)
&vo->control);
}
cb = list_first_entry(&s->bufs, struct cobalt_buffer, list);
- omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.v4l2_buf.index]);
+ omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.vb2_buf.index]);
spin_unlock_irqrestore(&s->irqlock, flags);
}
@@ -381,7 +383,7 @@ static void cobalt_dma_stop_streaming(struct cobalt_stream *s)
spin_lock_irqsave(&s->irqlock, flags);
list_for_each(p, &s->bufs) {
cb = list_entry(p, struct cobalt_buffer, list);
- desc = &s->dma_desc_info[cb->vb.v4l2_buf.index];
+ desc = &s->dma_desc_info[cb->vb.vb2_buf.index];
/* Stop DMA after this descriptor chain */
descriptor_list_end_of_chain(desc);
}
@@ -416,7 +418,7 @@ static void cobalt_stop_streaming(struct vb2_queue *q)
list_for_each_safe(p, safe, &s->bufs) {
cb = list_entry(p, struct cobalt_buffer, list);
list_del(&cb->list);
- vb2_buffer_done(&cb->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&cb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&s->irqlock, flags);
diff --git a/drivers/media/pci/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c
index eabf00c6351b..1f8aa9a749a1 100644
--- a/drivers/media/pci/cx18/cx18-mailbox.c
+++ b/drivers/media/pci/cx18/cx18-mailbox.c
@@ -202,7 +202,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
}
if (dispatch) {
- vb_buf->vb.ts = ktime_to_timeval(ktime_get());
+ v4l2_get_timestamp(&vb_buf->vb.ts);
list_del(&vb_buf->vb.queue);
vb_buf->vb.state = VIDEOBUF_DONE;
wake_up(&vb_buf->vb.done);
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 63c0ee5d0bf5..88a3afb66d10 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -1155,17 +1155,19 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
+ container_of(vbuf, struct cx23885_buffer, vb);
return cx23885_buf_prepare(buf, &dev->ts1);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(dev, buf);
@@ -1173,8 +1175,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_buf_queue(&dev->ts1, buf);
@@ -1201,7 +1204,7 @@ static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count)
struct cx23885_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
spin_unlock_irqrestore(&dev->slock, flags);
return ret;
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 7aee76af7a85..e8f847226a19 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -427,12 +427,13 @@ static void cx23885_wakeup(struct cx23885_tsport *port,
buf = list_entry(q->active.next,
struct cx23885_buffer, queue);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.sequence = q->count++;
- dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index,
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.sequence = q->count++;
+ dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
+ buf->vb.vb2_buf.index,
count, q->count);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
int cx23885_sram_channel_setup(struct cx23885_dev *dev,
@@ -1453,12 +1454,12 @@ int cx23885_buf_prepare(struct cx23885_buffer *buf, struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
int size = port->ts_packet_size * port->ts_packet_count;
- struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
dprintk(1, "%s: %p\n", __func__, buf);
- if (vb2_plane_size(&buf->vb, 0) < size)
+ if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size)
return -EINVAL;
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
cx23885_risc_databuffer(dev->pci, &buf->risc,
sgt->sgl,
@@ -1503,7 +1504,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
if (list_empty(&cx88q->active)) {
list_add_tail(&buf->queue, &cx88q->active);
dprintk(1, "[%p/%d] %s - first active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.vb2_buf.index, __func__);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
@@ -1511,7 +1512,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
list_add_tail(&buf->queue, &cx88q->active);
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(1, "[%p/%d] %s - append to active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.vb2_buf.index, __func__);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -1530,9 +1531,10 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason)
buf = list_entry(q->active.next, struct cx23885_buffer,
queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index, reason, (unsigned long)buf->risc.dma);
+ buf, buf->vb.vb2_buf.index, reason,
+ (unsigned long)buf->risc.dma);
}
spin_unlock_irqrestore(&port->slock, flags);
}
@@ -1990,9 +1992,9 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
(unsigned long long)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ err = pci_set_dma_mask(pci_dev, 0xffffffff);
+ if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
goto fail_context;
}
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 6e8c24cdb2cd..c4307ad8594c 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -92,7 +92,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -110,18 +110,20 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
+ container_of(vbuf, struct cx23885_buffer, vb);
return cx23885_buf_prepare(buf, port);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
struct cx23885_dev *dev = port->dev;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(dev, buf);
@@ -129,8 +131,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_buf_queue(port, buf);
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index d362d3838c84..cf3cb1324c55 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -121,7 +121,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -138,8 +138,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
unsigned lines = VBI_PAL_LINE_COUNT;
@@ -161,7 +162,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
- struct cx23885_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
@@ -190,8 +192,10 @@ static void buffer_finish(struct vb2_buffer *vb)
*/
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb, struct cx23885_buffer, vb);
+ struct cx23885_buffer *buf = container_of(vbuf,
+ struct cx23885_buffer, vb);
struct cx23885_buffer *prev;
struct cx23885_dmaqueue *q = &dev->vbiq;
unsigned long flags;
@@ -206,7 +210,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->queue, &q->active);
spin_unlock_irqrestore(&dev->slock, flags);
dprintk(2, "[%p/%d] vbi_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -217,7 +221,7 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&dev->slock, flags);
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
}
@@ -245,7 +249,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q)
struct cx23885_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index ec76470d12a4..71a80e2b842c 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -104,12 +104,12 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
buf = list_entry(q->active.next,
struct cx23885_buffer, queue);
- buf->vb.v4l2_buf.sequence = q->count++;
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index,
- count, q->count);
+ buf->vb.sequence = q->count++;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
+ buf->vb.vb2_buf.index, count, q->count);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
@@ -315,7 +315,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
return 0;
}
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -329,9 +329,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
+ container_of(vbuf, struct cx23885_buffer, vb);
u32 line0_offset, line1_offset;
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int field_tff;
@@ -401,7 +402,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
BUG();
}
dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index,
+ buf, buf->vb.vb2_buf.index,
dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
return 0;
@@ -409,7 +410,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
- struct cx23885_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
@@ -438,8 +440,9 @@ static void buffer_finish(struct vb2_buffer *vb)
*/
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
struct cx23885_buffer *prev;
struct cx23885_dmaqueue *q = &dev->vidq;
@@ -455,7 +458,7 @@ static void buffer_queue(struct vb2_buffer *vb)
if (list_empty(&q->active)) {
list_add_tail(&buf->queue, &q->active);
dprintk(2, "[%p/%d] buffer_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(q->active.prev, struct cx23885_buffer,
@@ -463,7 +466,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->queue, &q->active);
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -492,7 +495,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q)
struct cx23885_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 027ead438194..c5ba0833f47a 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -170,7 +170,7 @@ struct cx23885_riscmem {
/* buffer for one video frame */
struct cx23885_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head queue;
/* cx23885 specific */
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index 24f964bcc53a..b602eba2b601 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -102,7 +102,7 @@ struct cx25821_audio_dev {
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
index 559f8293c53a..0042803a9de7 100644
--- a/drivers/media/pci/cx25821/cx25821-core.c
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -1319,7 +1319,8 @@ static int cx25821_initdev(struct pci_dev *pci_dev,
dev->pci_lat, (unsigned long long)dev->base_io_addr);
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ err = pci_set_dma_mask(pci_dev, 0xffffffff);
+ if (err) {
pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
err = -EIO;
goto fail_irq;
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index 7bc495e4ece2..26e3e296d615 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -130,10 +130,10 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
buf = list_entry(dmaq->active.next,
struct cx25821_buffer, queue);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.sequence = dmaq->count++;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.sequence = dmaq->count++;
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
spin_unlock(&dev->slock);
handled++;
@@ -141,10 +141,11 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
return handled;
}
-static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int cx25821_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct cx25821_channel *chan = q->drv_priv;
unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
@@ -159,10 +160,11 @@ static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fm
static int cx25821_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
struct cx25821_dev *dev = chan->dev;
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vbuf, struct cx25821_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
u32 line0_offset;
int bpl_local = LINE_SIZE_D1;
@@ -176,7 +178,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < chan->height * buf->bpl)
return -EINVAL;
vb2_set_plane_payload(vb, 0, chan->height * buf->bpl);
- buf->vb.v4l2_buf.field = chan->field;
+ buf->vb.field = chan->field;
if (chan->pixel_formats == PIXEL_FRMT_411) {
bpl_local = buf->bpl;
@@ -231,7 +233,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
}
dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index, chan->width, chan->height,
+ buf, buf->vb.vb2_buf.index, chan->width, chan->height,
chan->fmt->depth, chan->fmt->name,
(unsigned long)buf->risc.dma);
@@ -240,8 +242,9 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
static void cx25821_buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vbuf, struct cx25821_buffer, vb);
struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
struct cx25821_dev *dev = chan->dev;
@@ -250,8 +253,9 @@ static void cx25821_buffer_finish(struct vb2_buffer *vb)
static void cx25821_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vbuf, struct cx25821_buffer, vb);
struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
struct cx25821_dev *dev = chan->dev;
struct cx25821_buffer *prev;
@@ -300,7 +304,7 @@ static void cx25821_stop_streaming(struct vb2_queue *q)
struct cx25821_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
index d81a08a2df4f..a513b68be0fa 100644
--- a/drivers/media/pci/cx25821/cx25821.h
+++ b/drivers/media/pci/cx25821/cx25821.h
@@ -34,6 +34,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
#include "cx25821-reg.h"
@@ -127,7 +128,7 @@ struct cx25821_riscmem {
/* buffer for one video frame */
struct cx25821_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head queue;
/* cx25821 specific */
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 7f8dc60028d5..1b5268f9bb24 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -101,7 +101,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t;
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
@@ -890,9 +890,9 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
return err;
}
- if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(pci,DMA_BIT_MASK(32));
+ if (err) {
dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
- err = -EIO;
cx88_core_put(core, pci);
return err;
}
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 24216efa56e7..8b889135be8a 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -653,16 +653,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -672,8 +674,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
cx8802_buf_queue(dev, buf);
}
@@ -721,7 +724,7 @@ fail:
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
spin_unlock_irqrestore(&dev->slock, flags);
return err;
@@ -749,7 +752,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index aab7cf4c9825..9a43c7826b60 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -518,11 +518,11 @@ void cx88_wakeup(struct cx88_core *core,
buf = list_entry(q->active.next,
struct cx88_buffer, list);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.field = core->field;
- buf->vb.v4l2_buf.sequence = q->count++;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.field = core->field;
+ buf->vb.sequence = q->count++;
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
void cx88_shutdown(struct cx88_core *core)
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 9dfa5ee32a8f..f04835073844 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -82,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -99,16 +99,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -118,8 +120,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
cx8802_buf_queue(dev, buf);
}
@@ -149,7 +152,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 34f505744477..f34c229f9b37 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -214,7 +214,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
cx8802_start_dma(dev, q, buf);
return 0;
}
@@ -225,13 +225,13 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
struct cx88_buffer *buf)
{
int size = dev->ts_packet_size * dev->ts_packet_count;
- struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
struct cx88_riscmem *risc = &buf->risc;
int rc;
- if (vb2_plane_size(&buf->vb, 0) < size)
+ if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size)
return -EINVAL;
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
dev->ts_packet_size, dev->ts_packet_count, 0);
@@ -259,7 +259,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
dprintk( 1, "queue is empty - first active\n" );
list_add_tail(&buf->list, &cx88q->active);
dprintk(1,"[%p/%d] %s - first active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.vb2_buf.index, __func__);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -268,7 +268,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
list_add_tail(&buf->list, &cx88q->active);
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.vb2_buf.index, __func__);
}
}
@@ -284,7 +284,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev)
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock,flags);
}
@@ -393,7 +393,8 @@ static int cx8802_init_common(struct cx8802_dev *dev)
if (pci_enable_device(dev->pci))
return -EIO;
pci_set_master(dev->pci);
- if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(dev->pci,DMA_BIT_MASK(32));
+ if (err) {
printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
return -EIO;
}
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 7510e80eb2ff..007a5eee8e5e 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -100,14 +100,14 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
cx8800_start_vbi_dma(dev, q, buf);
return 0;
}
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -125,8 +125,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
unsigned int lines;
unsigned int size;
@@ -149,8 +150,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -160,8 +162,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_buffer *prev;
struct cx88_dmaqueue *q = &dev->vbiq;
@@ -174,7 +177,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->list, &q->active);
cx8800_start_vbi_dma(dev, q, buf);
dprintk(2,"[%p/%d] vbi_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -182,7 +185,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->list, &q->active);
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
}
@@ -213,7 +216,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 400e5caefd58..aef9acf351f6 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -420,7 +420,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
if (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
start_video_dma(dev, q, buf);
}
return 0;
@@ -429,7 +429,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -444,9 +444,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_core *core = dev->core;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
buf->bpl = core->width * dev->fmt->depth >> 3;
@@ -489,7 +490,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
break;
}
dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index,
+ buf, buf->vb.vb2_buf.index,
core->width, core->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
return 0;
@@ -497,8 +498,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -508,8 +510,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_buffer *prev;
struct cx88_core *core = dev->core;
struct cx88_dmaqueue *q = &dev->vidq;
@@ -522,7 +525,7 @@ static void buffer_queue(struct vb2_buffer *vb)
if (list_empty(&q->active)) {
list_add_tail(&buf->list, &q->active);
dprintk(2,"[%p/%d] buffer_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -530,7 +533,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->list, &q->active);
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
}
@@ -560,7 +563,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -1311,9 +1314,9 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(pci_dev,DMA_BIT_MASK(32));
+ if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
- err = -EIO;
goto fail_core;
}
dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 785fe2e0d702..2996eb3ea1fc 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -321,7 +321,7 @@ struct cx88_riscmem {
/* buffer for one video frame */
struct cx88_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
/* cx88 specific */
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index 8df634518927..d84abde5ea29 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -131,11 +131,12 @@ static int wait_i2c_reg(void __iomem *addr)
}
static int
-dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+dt3155_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct dt3155_priv *pd = vb2_get_drv_priv(vq);
unsigned size = pd->width * pd->height;
@@ -160,7 +161,7 @@ static int dt3155_buf_prepare(struct vb2_buffer *vb)
static int dt3155_start_streaming(struct vb2_queue *q, unsigned count)
{
struct dt3155_priv *pd = vb2_get_drv_priv(q);
- struct vb2_buffer *vb = pd->curr_buf;
+ struct vb2_buffer *vb = &pd->curr_buf->vb2_buf;
dma_addr_t dma_addr;
pd->sequence = 0;
@@ -208,7 +209,7 @@ static void dt3155_stop_streaming(struct vb2_queue *q)
spin_lock_irq(&pd->lock);
if (pd->curr_buf) {
- vb2_buffer_done(pd->curr_buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&pd->curr_buf->vb2_buf, VB2_BUF_STATE_ERROR);
pd->curr_buf = NULL;
}
@@ -222,6 +223,7 @@ static void dt3155_stop_streaming(struct vb2_queue *q)
static void dt3155_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
/* pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked */
@@ -229,7 +231,7 @@ static void dt3155_buf_queue(struct vb2_buffer *vb)
if (pd->curr_buf)
list_add_tail(&vb->done_entry, &pd->dmaq);
else
- pd->curr_buf = vb;
+ pd->curr_buf = vbuf;
spin_unlock_irq(&pd->lock);
}
@@ -269,14 +271,14 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
spin_lock(&ipd->lock);
if (ipd->curr_buf && !list_empty(&ipd->dmaq)) {
- v4l2_get_timestamp(&ipd->curr_buf->v4l2_buf.timestamp);
- ipd->curr_buf->v4l2_buf.sequence = ipd->sequence++;
- ipd->curr_buf->v4l2_buf.field = V4L2_FIELD_NONE;
- vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&ipd->curr_buf->timestamp);
+ ipd->curr_buf->sequence = ipd->sequence++;
+ ipd->curr_buf->field = V4L2_FIELD_NONE;
+ vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE);
ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
list_del(&ivb->done_entry);
- ipd->curr_buf = ivb;
+ ipd->curr_buf = to_vb2_v4l2_buffer(ivb);
dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START);
diff --git a/drivers/media/pci/dt3155/dt3155.h b/drivers/media/pci/dt3155/dt3155.h
index 4e1f4d598d57..b3531e0bc733 100644
--- a/drivers/media/pci/dt3155/dt3155.h
+++ b/drivers/media/pci/dt3155/dt3155.h
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
+#include <media/videobuf2-v4l2.h>
#define DT3155_NAME "dt3155"
#define DT3155_VER_MAJ 2
@@ -181,7 +182,7 @@ struct dt3155_priv {
struct pci_dev *pdev;
struct vb2_queue vidq;
struct vb2_alloc_ctx *alloc_ctx;
- struct vb2_buffer *curr_buf;
+ struct vb2_v4l2_buffer *curr_buf;
struct mutex mux;
struct list_head dmaq;
spinlock_t lock;
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
index 41fa21534edf..8a86b61a896d 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-main.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -41,6 +41,7 @@
#include "ivtv-alsa-pcm.h"
int ivtv_alsa_debug;
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
#define IVTV_DEBUG_ALSA_INFO(fmt, arg...) \
do { \
@@ -54,6 +55,10 @@ MODULE_PARM_DESC(debug,
"\t\t\t 1/0x0001: warning\n"
"\t\t\t 2/0x0002: info\n");
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index,
+ "Index value for IVTV ALSA capture interface(s).\n");
+
MODULE_AUTHOR("Andy Walls");
MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface");
MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder");
@@ -137,7 +142,7 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
struct ivtv *itv = to_ivtv(v4l2_dev);
struct snd_card *sc = NULL;
struct snd_ivtv_card *itvsc;
- int ret;
+ int ret, idx;
/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
@@ -145,8 +150,10 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
/* This is a no-op for us. We'll use the itv->instance */
/* (2) Create a card instance */
+ /* use first available id if not specified otherwise*/
+ idx = index[itv->instance] == -1 ? SNDRV_DEFAULT_IDX1 : index[itv->instance];
ret = snd_card_new(&itv->pdev->dev,
- SNDRV_DEFAULT_IDX1, /* use first available id */
+ idx,
SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
THIS_MODULE, 0, &sc);
if (ret) {
@@ -196,6 +203,9 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
goto err_exit_free;
}
+ IVTV_ALSA_INFO("%s: Instance %d registered as ALSA card %d\n",
+ __func__, itv->instance, sc->number);
+
return 0;
err_exit_free:
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c
index 2ad65eb29832..2b8e7b2f2b86 100644
--- a/drivers/media/pci/ivtv/ivtv-yuv.c
+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -75,15 +75,15 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
/* Get user pages for DMA Xfer */
- down_read(&current->mm->mmap_sem);
- y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
+ y_pages = get_user_pages_unlocked(current, current->mm,
+ y_dma.uaddr, y_dma.page_count, 0, 1,
+ &dma->map[0]);
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
if (y_pages == y_dma.page_count) {
- uv_pages = get_user_pages(current, current->mm,
- uv_dma.uaddr, uv_dma.page_count, 0, 1,
- &dma->map[y_pages], NULL);
+ uv_pages = get_user_pages_unlocked(current, current->mm,
+ uv_dma.uaddr, uv_dma.page_count, 0, 1,
+ &dma->map[y_pages]);
}
- up_read(&current->mm->mmap_sem);
if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
int rc = -EFAULT;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb.h b/drivers/media/pci/netup_unidvb/netup_unidvb.h
index fa951102d7fb..a67b28111905 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb.h
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb.h
@@ -54,7 +54,7 @@ struct netup_dma {
u8 num;
spinlock_t lock;
struct netup_unidvb_dev *ndev;
- struct netup_dma_regs *regs;
+ struct netup_dma_regs __iomem *regs;
u32 ring_buffer_size;
u8 *addr_virt;
dma_addr_t addr_phys;
@@ -82,7 +82,7 @@ struct netup_i2c {
wait_queue_head_t wq;
struct i2c_adapter adap;
struct netup_unidvb_dev *dev;
- struct netup_i2c_regs *regs;
+ struct netup_i2c_regs __iomem *regs;
struct i2c_msg *msg;
enum netup_i2c_state state;
u32 xmit_size;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
index 751b51b03593..f46ffac66ee9 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
@@ -147,7 +147,7 @@ static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
{
struct netup_ci_state *state = en50221->data;
struct netup_unidvb_dev *dev = state->dev;
- u8 val = state->membase8_config[addr];
+ u8 val = *((u8 __force *)state->membase8_io + addr);
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
@@ -162,7 +162,7 @@ static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
- state->membase8_config[addr] = data;
+ *((u8 __force *)state->membase8_io + addr) = data;
return 0;
}
@@ -171,7 +171,7 @@ static int netup_unidvb_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
{
struct netup_ci_state *state = en50221->data;
struct netup_unidvb_dev *dev = state->dev;
- u8 val = state->membase8_io[addr];
+ u8 val = *((u8 __force *)state->membase8_io + addr);
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
@@ -186,7 +186,7 @@ static int netup_unidvb_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
- state->membase8_io[addr] = data;
+ *((u8 __force *)state->membase8_io + addr) = data;
return 0;
}
@@ -226,7 +226,7 @@ int netup_unidvb_ci_register(struct netup_unidvb_dev *dev,
__func__, result);
return result;
}
- writew(NETUP_UNIDVB_IRQ_CI, (u16 *)(dev->bmmio0 + REG_IMASK_SET));
+ writew(NETUP_UNIDVB_IRQ_CI, dev->bmmio0 + REG_IMASK_SET);
dev_info(&pci_dev->dev,
"%s(): CI adapter %d init done\n", __func__, num);
return 0;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index 6d8bf6277647..3fdbd81b5580 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/list.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include "netup_unidvb.h"
@@ -110,7 +111,7 @@ struct netup_dma_regs {
} __packed __aligned(1);
struct netup_unidvb_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
u32 size;
};
@@ -189,12 +190,10 @@ static void netup_unidvb_dma_enable(struct netup_dma *dma, int enable)
"%s(): DMA%d enable %d\n", __func__, dma->num, enable);
if (enable) {
writel(BIT_DMA_RUN, &dma->regs->ctrlstat_set);
- writew(irq_mask,
- (u16 *)(dma->ndev->bmmio0 + REG_IMASK_SET));
+ writew(irq_mask, dma->ndev->bmmio0 + REG_IMASK_SET);
} else {
writel(BIT_DMA_RUN, &dma->regs->ctrlstat_clear);
- writew(irq_mask,
- (u16 *)(dma->ndev->bmmio0 + REG_IMASK_CLEAR));
+ writew(irq_mask, dma->ndev->bmmio0 + REG_IMASK_CLEAR);
}
}
@@ -278,7 +277,7 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id)
}
static int netup_unidvb_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers,
unsigned int *nplanes,
unsigned int sizes[],
@@ -300,7 +299,8 @@ static int netup_unidvb_queue_setup(struct vb2_queue *vq,
static int netup_unidvb_buf_prepare(struct vb2_buffer *vb)
{
struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
- struct netup_unidvb_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct netup_unidvb_buffer *buf = container_of(vbuf,
struct netup_unidvb_buffer, vb);
dev_dbg(&dma->ndev->pci_dev->dev, "%s(): buf 0x%p\n", __func__, buf);
@@ -312,7 +312,8 @@ static void netup_unidvb_buf_queue(struct vb2_buffer *vb)
{
unsigned long flags;
struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
- struct netup_unidvb_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct netup_unidvb_buffer *buf = container_of(vbuf,
struct netup_unidvb_buffer, vb);
dev_dbg(&dma->ndev->pci_dev->dev, "%s(): %p\n", __func__, buf);
@@ -509,7 +510,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma,
{
u32 copy_bytes, ring_bytes;
u32 buff_bytes = NETUP_DMA_PACKETS_COUNT * 188 - buf->size;
- u8 *p = vb2_plane_vaddr(&buf->vb, 0);
+ u8 *p = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
struct netup_unidvb_dev *ndev = dma->ndev;
if (p == NULL) {
@@ -522,7 +523,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma,
ring_bytes = dma->ring_buffer_size - dma->data_offset;
copy_bytes = (ring_bytes > buff_bytes) ?
buff_bytes : ring_bytes;
- memcpy_fromio(p, dma->addr_virt + dma->data_offset, copy_bytes);
+ memcpy_fromio(p, (u8 __iomem *)(dma->addr_virt + dma->data_offset), copy_bytes);
p += copy_bytes;
buf->size += copy_bytes;
buff_bytes -= copy_bytes;
@@ -535,7 +536,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma,
ring_bytes = dma->data_size;
copy_bytes = (ring_bytes > buff_bytes) ?
buff_bytes : ring_bytes;
- memcpy_fromio(p, dma->addr_virt + dma->data_offset, copy_bytes);
+ memcpy_fromio(p, (u8 __iomem *)(dma->addr_virt + dma->data_offset), copy_bytes);
buf->size += copy_bytes;
dma->data_size -= copy_bytes;
dma->data_offset += copy_bytes;
@@ -579,9 +580,9 @@ static void netup_unidvb_dma_worker(struct work_struct *work)
dev_dbg(&ndev->pci_dev->dev,
"%s(): buffer %p done, size %d\n",
__func__, buf, buf->size);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- vb2_set_plane_payload(&buf->vb, 0, buf->size);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
}
work_done:
@@ -599,7 +600,7 @@ static void netup_unidvb_queue_cleanup(struct netup_dma *dma)
buf = list_first_entry(&dma->free_buffers,
struct netup_unidvb_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dma->lock, flags);
}
@@ -641,10 +642,10 @@ static int netup_unidvb_dma_init(struct netup_unidvb_dev *ndev, int num)
__func__, num, dma->addr_virt,
(unsigned long long)dma->addr_phys,
dma->ring_buffer_size);
- memset_io(dma->addr_virt, 0, dma->ring_buffer_size);
+ memset_io((u8 __iomem *)dma->addr_virt, 0, dma->ring_buffer_size);
dma->addr_last = dma->addr_phys;
dma->high_addr = (u32)(dma->addr_phys & 0xC0000000);
- dma->regs = (struct netup_dma_regs *)(num == 0 ?
+ dma->regs = (struct netup_dma_regs __iomem *)(num == 0 ?
ndev->bmmio0 + NETUP_DMA0_ADDR :
ndev->bmmio0 + NETUP_DMA1_ADDR);
writel((NETUP_DMA_BLOCKS_COUNT << 24) |
@@ -809,7 +810,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
"%s(): board vendor 0x%x, revision 0x%x\n",
__func__, board_vendor, board_revision);
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ if (pci_set_dma_mask(pci_dev, 0xffffffff) < 0) {
dev_err(&pci_dev->dev,
"%s(): 32bit PCI DMA is not supported\n", __func__);
goto pci_detect_err;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c
index eaaa2d0a5fba..c09c52bc6eab 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c
@@ -320,7 +320,7 @@ static int netup_i2c_init(struct netup_unidvb_dev *ndev, int bus_num)
i2c = &ndev->i2c[bus_num];
spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wq);
- i2c->regs = (struct netup_i2c_regs *)(ndev->bmmio0 +
+ i2c->regs = (struct netup_i2c_regs __iomem *)(ndev->bmmio0 +
(bus_num == 0 ? NETUP_I2C_BUS0_ADDR : NETUP_I2C_BUS1_ADDR));
netup_i2c_reset(i2c);
i2c->adap = netup_i2c_adapter;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
index f55b3276f28d..f33c0de3e849 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
@@ -45,7 +45,7 @@ struct netup_spi_regs {
struct netup_spi {
struct device *dev;
struct spi_master *master;
- struct netup_spi_regs *regs;
+ struct netup_spi_regs __iomem *regs;
u8 __iomem *mmio;
spinlock_t lock;
wait_queue_head_t waitq;
@@ -80,11 +80,9 @@ irqreturn_t netup_spi_interrupt(struct netup_spi *spi)
u16 reg;
unsigned long flags;
- if (!spi) {
- dev_dbg(&spi->master->dev,
- "%s(): SPI not initialized\n", __func__);
+ if (!spi)
return IRQ_NONE;
- }
+
spin_lock_irqsave(&spi->lock, flags);
reg = readw(&spi->regs->control_stat);
if (!(reg & NETUP_SPI_CTRL_IRQ)) {
@@ -202,7 +200,7 @@ int netup_spi_init(struct netup_unidvb_dev *ndev)
spin_lock_init(&nspi->lock);
init_waitqueue_head(&nspi->waitq);
nspi->master = master;
- nspi->regs = (struct netup_spi_regs *)(ndev->bmmio0 + 0x4000);
+ nspi->regs = (struct netup_spi_regs __iomem *)(ndev->bmmio0 + 0x4000);
writew(2, &nspi->regs->clock_divider);
writew(NETUP_UNIDVB_IRQ_SPI, ndev->bmmio0 + REG_IMASK_SET);
ndev->spi = nspi;
@@ -234,11 +232,9 @@ void netup_spi_release(struct netup_unidvb_dev *ndev)
unsigned long flags;
struct netup_spi *spi = ndev->spi;
- if (!spi) {
- dev_dbg(&spi->master->dev,
- "%s(): SPI not initialized\n", __func__);
+ if (!spi)
return;
- }
+
spin_lock_irqsave(&spi->lock, flags);
reg = readw(&spi->regs->control_stat);
writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index c7405766609c..29d2094c42a0 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -5884,6 +5884,42 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM] = {
+ .name = "Leadtek Winfast TV2100 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_TNF_5335MF,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x0d,
+ .inputs = {{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE1,
+ .gpio = 0x00,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2,
+ .gpio = 0x08,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ .gpio = 0x08,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x04,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ .gpio = 0x08,
+ },
+ },
};
@@ -7149,6 +7185,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0xa10a,
.driver_data = SAA7134_BOARD_AVERMEDIA_505,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x107d,
+ .subdevice = 0x6f3a,
+ .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -7545,6 +7587,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+ case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM:
dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_FLYDVBS_LR300:
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 72d7f992375e..f720cea80e28 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -216,13 +216,14 @@ int saa7134_buffer_count(unsigned int size, unsigned int count)
int saa7134_buffer_startpage(struct saa7134_buf *buf)
{
- return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index;
+ return saa7134_buffer_pages(vb2_plane_size(&buf->vb2.vb2_buf, 0))
+ * buf->vb2.vb2_buf.index;
}
unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
{
unsigned long base;
- struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2.vb2_buf, 0);
base = saa7134_buffer_startpage(buf) * 4096;
base += dma->sgl[0].offset;
@@ -308,9 +309,9 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
core_dbg("buffer_finish %p\n", q->curr);
/* finish current buffer */
- v4l2_get_timestamp(&q->curr->vb2.v4l2_buf.timestamp);
- q->curr->vb2.v4l2_buf.sequence = q->seq_nr++;
- vb2_buffer_done(&q->curr->vb2, state);
+ v4l2_get_timestamp(&q->curr->vb2.timestamp);
+ q->curr->vb2.sequence = q->seq_nr++;
+ vb2_buffer_done(&q->curr->vb2.vb2_buf, state);
q->curr = NULL;
}
@@ -375,7 +376,8 @@ void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q)
if (!list_empty(&q->queue)) {
list_for_each_safe(pos, n, &q->queue) {
tmp = list_entry(pos, struct saa7134_buf, entry);
- vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&tmp->vb2.vb2_buf,
+ VB2_BUF_STATE_ERROR);
list_del(pos);
tmp = NULL;
}
@@ -949,9 +951,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+ if (err) {
pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
goto fail1;
}
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 11a172000291..69d32d3fa32c 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -835,6 +835,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keycode = 0xffff;
raw_decode = true;
break;
+ case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM:
+ ir_codes = RC_MAP_LEADTEK_Y04G0051;
+ mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */
+ mask_keyup = 0x0040000;
+ mask_keycode = 0xffff;
+ raw_decode = true;
+ break;
}
if (NULL == ir_codes) {
pr_err("Oops: IR config error [card=%d]\n", dev->board);
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 4b202fa5fbc4..7fb5ee7e20ac 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -79,8 +79,9 @@ static int buffer_activate(struct saa7134_dev *dev,
int saa7134_ts_buffer_init(struct vb2_buffer *vb2)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
@@ -91,9 +92,10 @@ EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int lines, llength, size;
@@ -107,14 +109,14 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
return -EINVAL;
vb2_set_plane_payload(vb2, 0, size);
- vb2->v4l2_buf.field = dev->field;
+ vbuf->field = dev->field;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -148,10 +150,12 @@ int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count)
list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
list_del(&buf->entry);
- vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
if (dmaq->curr) {
- vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
dmaq->curr = NULL;
}
return -EBUSY;
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 4d36586ad752..6271b0eb0265 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -83,7 +83,7 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
- struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+ struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;
unsigned long control, base;
vbi_dbg("buffer_activate [%p]\n", buf);
@@ -119,8 +119,9 @@ static int buffer_prepare(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
- struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int size;
if (dma->sgl->offset) {
@@ -137,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
saa7134_buffer_startpage(buf));
}
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -161,7 +162,8 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_init(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 035039cfae6d..518086c7aed5 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -791,7 +791,7 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
- struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+ struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;
unsigned long base,control,bpl;
unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */
@@ -872,7 +872,8 @@ static int buffer_activate(struct saa7134_dev *dev,
static int buffer_init(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
@@ -883,8 +884,9 @@ static int buffer_prepare(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
- struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int size;
if (dma->sgl->offset) {
@@ -896,13 +898,13 @@ static int buffer_prepare(struct vb2_buffer *vb2)
return -EINVAL;
vb2_set_plane_payload(vb2, 0, size);
- vb2->v4l2_buf.field = dev->field;
+ vbuf->field = dev->field;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -932,7 +934,8 @@ void saa7134_vb2_buffer_queue(struct vb2_buffer *vb)
{
struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb2);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
saa7134_buffer_queue(dev, dmaq, buf);
}
@@ -953,10 +956,12 @@ int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
list_del(&buf->entry);
- vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
if (dmaq->curr) {
- vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
dmaq->curr = NULL;
}
return -EBUSY;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 6b5f6f45d285..6b6d234f5cab 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -342,6 +342,7 @@ struct saa7134_card_ir {
#define SAA7134_BOARD_AVERMEDIA_A706 192
#define SAA7134_BOARD_WIS_VOYAGER 193
#define SAA7134_BOARD_AVERMEDIA_505 194
+#define SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM 195
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
@@ -459,7 +460,7 @@ struct saa7134_thread {
/* buffer for one video/vbi/ts frame */
struct saa7134_buf {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb2;
+ struct vb2_v4l2_buffer vb2;
/* saa7134 specific */
unsigned int top_seen;
@@ -819,7 +820,7 @@ void saa7134_video_fini(struct saa7134_dev *dev);
int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[]);
int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
diff --git a/drivers/media/pci/saa7164/Kconfig b/drivers/media/pci/saa7164/Kconfig
index a53db7d1c96e..9098ef5feca4 100644
--- a/drivers/media/pci/saa7164/Kconfig
+++ b/drivers/media/pci/saa7164/Kconfig
@@ -5,7 +5,6 @@ config VIDEO_SAA7164
select FW_LOADER
select VIDEO_TUNER
select VIDEO_TVEEPROM
- select VIDEOBUF_DVB
select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index 3206a826b80d..8bbd092fbe1d 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -1264,9 +1264,9 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
pci_set_master(pci_dev);
/* TODO */
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ err = pci_set_dma_mask(pci_dev, 0xffffffff);
+ if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
goto fail_irq;
}
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
index 4434e0f28c26..1b184c39ba97 100644
--- a/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -25,6 +25,18 @@
#define ENCODER_MIN_BITRATE 1000000
#define ENCODER_DEF_BITRATE 5000000
+/*
+ * This is a dummy non-zero value for the sizeimage field of v4l2_pix_format.
+ * It is not actually used for anything since this driver does not support
+ * stream I/O, only read(), and because this driver produces an MPEG stream
+ * and not discrete frames. But the V4L2 spec doesn't allow for this value
+ * to be 0, so set it to 0x10000 instead.
+ *
+ * If we ever change this driver to support stream I/O, then this field
+ * will be the size of the streaming buffers.
+ */
+#define SAA7164_SIZEIMAGE (0x10000)
+
static struct saa7164_tvnorm saa7164_tvnorms[] = {
{
.name = "NTSC-M",
@@ -35,24 +47,6 @@ static struct saa7164_tvnorm saa7164_tvnorms[] = {
}
};
-static const u32 saa7164_v4l2_ctrls[] = {
- V4L2_CID_BRIGHTNESS,
- V4L2_CID_CONTRAST,
- V4L2_CID_SATURATION,
- V4L2_CID_HUE,
- V4L2_CID_AUDIO_VOLUME,
- V4L2_CID_SHARPNESS,
- V4L2_CID_MPEG_STREAM_TYPE,
- V4L2_CID_MPEG_VIDEO_ASPECT,
- V4L2_CID_MPEG_VIDEO_B_FRAMES,
- V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- V4L2_CID_MPEG_AUDIO_MUTE,
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- V4L2_CID_MPEG_VIDEO_BITRATE,
- V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- 0
-};
-
/* Take the encoder configuration form the port struct and
* flush it to the hardware.
*/
@@ -211,10 +205,8 @@ static int saa7164_encoder_initialize(struct saa7164_port *port)
}
/* -- V4L2 --------------------------------------------------------- */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
+int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
struct saa7164_dev *dev = port->dev;
unsigned int i;
@@ -240,22 +232,33 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
return 0;
}
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+ return saa7164_s_std(fh->port, id);
+}
+
+int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id)
+{
*id = port->std;
return 0;
}
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
{
- int n;
+ struct saa7164_encoder_fh *fh = file->private_data;
+
+ return saa7164_g_std(fh->port, id);
+}
- char *inputs[] = { "tuner", "composite", "svideo", "aux",
- "composite 2", "svideo 2", "aux 2" };
+int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+ static const char * const inputs[] = {
+ "tuner", "composite", "svideo", "aux",
+ "composite 2", "svideo 2", "aux 2"
+ };
+ int n;
if (i->index >= 7)
return -EINVAL;
@@ -273,10 +276,8 @@ static int vidioc_enum_input(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+int saa7164_g_input(struct saa7164_port *port, unsigned int *i)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
struct saa7164_dev *dev = port->dev;
if (saa7164_api_get_videomux(port) != SAA_OK)
@@ -289,10 +290,15 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
return 0;
}
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+
+ return saa7164_g_input(fh->port, i);
+}
+
+int saa7164_s_input(struct saa7164_port *port, unsigned int i)
+{
struct saa7164_dev *dev = port->dev;
dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
@@ -308,8 +314,14 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
return 0;
}
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+ struct saa7164_encoder_fh *fh = file->private_data;
+
+ return saa7164_s_input(fh->port, i);
+}
+
+int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
{
struct saa7164_encoder_fh *fh = file->private_data;
struct saa7164_port *port = fh->port;
@@ -319,38 +331,45 @@ static int vidioc_g_tuner(struct file *file, void *priv,
return -EINVAL;
strcpy(t->name, "tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
+ t->rangelow = SAA7164_TV_MIN_FREQ;
+ t->rangehigh = SAA7164_TV_MAX_FREQ;
dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
return 0;
}
-static int vidioc_s_tuner(struct file *file, void *priv,
- const struct v4l2_tuner *t)
+int saa7164_s_tuner(struct file *file, void *priv,
+ const struct v4l2_tuner *t)
{
+ if (0 != t->index)
+ return -EINVAL;
+
/* Update the A/V core */
return 0;
}
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+ if (f->tuner)
+ return -EINVAL;
- f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = port->freq;
-
return 0;
}
-static int vidioc_s_frequency(struct file *file, void *priv,
- const struct v4l2_frequency *f)
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+
+ return saa7164_g_frequency(fh->port, f);
+}
+
+int saa7164_s_frequency(struct saa7164_port *port,
+ const struct v4l2_frequency *f)
+{
struct saa7164_dev *dev = port->dev;
struct saa7164_port *tsport;
struct dvb_frontend *fe;
@@ -370,16 +389,13 @@ static int vidioc_s_frequency(struct file *file, void *priv,
if (f->tuner != 0)
return -EINVAL;
- if (f->type != V4L2_TUNER_ANALOG_TV)
- return -EINVAL;
-
- port->freq = f->frequency;
+ port->freq = clamp(f->frequency,
+ SAA7164_TV_MIN_FREQ, SAA7164_TV_MAX_FREQ);
/* Update the hardware */
if (port->nr == SAA7164_PORT_ENC1)
tsport = &dev->ports[SAA7164_PORT_TS1];
- else
- if (port->nr == SAA7164_PORT_ENC2)
+ else if (port->nr == SAA7164_PORT_ENC2)
tsport = &dev->ports[SAA7164_PORT_TS2];
else
BUG();
@@ -396,253 +412,54 @@ static int vidioc_s_frequency(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
+static int vidioc_s_frequency(struct file *file, void *priv,
+ const struct v4l2_frequency *f)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
- case V4L2_CID_BRIGHTNESS:
- ctl->value = port->ctl_brightness;
- break;
- case V4L2_CID_CONTRAST:
- ctl->value = port->ctl_contrast;
- break;
- case V4L2_CID_SATURATION:
- ctl->value = port->ctl_saturation;
- break;
- case V4L2_CID_HUE:
- ctl->value = port->ctl_hue;
- break;
- case V4L2_CID_SHARPNESS:
- ctl->value = port->ctl_sharpness;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- ctl->value = port->ctl_volume;
- break;
- default:
- return -EINVAL;
- }
- return 0;
+ return saa7164_s_frequency(fh->port, f);
}
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
+static int saa7164_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
+ struct saa7164_port *port =
+ container_of(ctrl->handler, struct saa7164_port, ctrl_handler);
+ struct saa7164_encoder_params *params = &port->encoder_params;
int ret = 0;
- dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_brightness = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_BRIGHTNESS_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_brightness = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
break;
case V4L2_CID_CONTRAST:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_contrast = ctl->value;
- saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_contrast = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
break;
case V4L2_CID_SATURATION:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_saturation = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_SATURATION_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_saturation = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
break;
case V4L2_CID_HUE:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_hue = ctl->value;
- saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_hue = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
break;
case V4L2_CID_SHARPNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_sharpness = ctl->value;
- saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_sharpness = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
break;
case V4L2_CID_AUDIO_VOLUME:
- if ((ctl->value >= -83) && (ctl->value <= 24)) {
- port->ctl_volume = ctl->value;
- saa7164_api_set_audio_volume(port, port->ctl_volume);
- } else
- ret = -EINVAL;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int saa7164_get_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_encoder_params *params = &port->encoder_params;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- ctrl->value = params->bitrate;
- break;
- case V4L2_CID_MPEG_STREAM_TYPE:
- ctrl->value = params->stream_type;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- ctrl->value = params->ctl_mute;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- ctrl->value = params->ctl_aspect;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- ctrl->value = params->bitrate_mode;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- ctrl->value = params->refdist;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- ctrl->value = params->bitrate_peak;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- ctrl->value = params->gop_size;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_get_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
-static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
- int ret = -EINVAL;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
- (ctrl->value <= ENCODER_MAX_BITRATE))
- ret = 0;
+ port->ctl_volume = ctrl->val;
+ saa7164_api_set_audio_volume(port, port->ctl_volume);
break;
- case V4L2_CID_MPEG_STREAM_TYPE:
- if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
- (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
- ret = 0;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 1))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
- (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 255))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ||
- (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- if ((ctrl->value >= 1) &&
- (ctrl->value <= 3))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
- (ctrl->value <= ENCODER_MAX_BITRATE))
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
- }
-
- return -EINVAL;
-}
-
-static int saa7164_set_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_encoder_params *params = &port->encoder_params;
- int ret = 0;
-
- switch (ctrl->id) {
case V4L2_CID_MPEG_VIDEO_BITRATE:
- params->bitrate = ctrl->value;
+ params->bitrate = ctrl->val;
break;
case V4L2_CID_MPEG_STREAM_TYPE:
- params->stream_type = ctrl->value;
+ params->stream_type = ctrl->val;
break;
case V4L2_CID_MPEG_AUDIO_MUTE:
- params->ctl_mute = ctrl->value;
+ params->ctl_mute = ctrl->val;
ret = saa7164_api_audio_mute(port, params->ctl_mute);
if (ret != SAA_OK) {
printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
@@ -651,7 +468,7 @@ static int saa7164_set_ctrl(struct saa7164_port *port,
}
break;
case V4L2_CID_MPEG_VIDEO_ASPECT:
- params->ctl_aspect = ctrl->value;
+ params->ctl_aspect = ctrl->val;
ret = saa7164_api_set_aspect_ratio(port);
if (ret != SAA_OK) {
printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
@@ -660,55 +477,24 @@ static int saa7164_set_ctrl(struct saa7164_port *port,
}
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- params->bitrate_mode = ctrl->value;
+ params->bitrate_mode = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- params->refdist = ctrl->value;
+ params->refdist = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- params->bitrate_peak = ctrl->value;
+ params->bitrate_peak = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- params->gop_size = ctrl->value;
+ params->gop_size = ctrl->val;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
- /* TODO: Update the hardware */
-
return ret;
}
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- err = saa7164_set_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -745,145 +531,22 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7164_encoder_fh *fh = file->private_data;
struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
+ f->fmt.pix.sizeimage = SAA7164_SIZEIMAGE;
+ f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.width = port->width;
f->fmt.pix.height = port->height;
-
- dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n",
- port->width, port->height);
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
- dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
- port->width, port->height);
return 0;
}
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
-
- dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
- f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-
- return 0;
-}
-
-static int fill_queryctrl(struct saa7164_encoder_params *params,
- struct v4l2_queryctrl *c)
-{
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
- case V4L2_CID_CONTRAST:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
- case V4L2_CID_SATURATION:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
- case V4L2_CID_HUE:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
- case V4L2_CID_SHARPNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
- case V4L2_CID_MPEG_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
- case V4L2_CID_AUDIO_VOLUME:
- return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- return v4l2_ctrl_query_fill(c,
- ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
- 100000, ENCODER_DEF_BITRATE);
- case V4L2_CID_MPEG_STREAM_TYPE:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
- 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_VIDEO_ASPECT_1x1,
- V4L2_MPEG_VIDEO_ASPECT_221x100,
- 1, V4L2_MPEG_VIDEO_ASPECT_4x3);
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
- 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- return v4l2_ctrl_query_fill(c,
- 1, 3, 1, 1);
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- return v4l2_ctrl_query_fill(c,
- ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
- 100000, ENCODER_DEF_BITRATE);
- default:
- return -EINVAL;
- }
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- struct saa7164_encoder_fh *fh = priv;
- struct saa7164_port *port = fh->port;
- int i, next;
- u32 id = c->id;
-
- memset(c, 0, sizeof(*c));
-
- next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
- c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
- for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
- if (next) {
- if (c->id < saa7164_v4l2_ctrls[i])
- c->id = saa7164_v4l2_ctrls[i];
- else
- continue;
- }
-
- if (c->id == saa7164_v4l2_ctrls[i])
- return fill_queryctrl(&port->encoder_params, c);
-
- if (c->id < saa7164_v4l2_ctrls[i])
- break;
- }
-
- return -EINVAL;
-}
-
static int saa7164_encoder_stop_port(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
@@ -1084,8 +747,10 @@ static int fops_open(struct file *file)
if (NULL == fh)
return -ENOMEM;
- file->private_data = fh;
fh->port = port;
+ v4l2_fh_init(&fh->fh, video_devdata(file));
+ v4l2_fh_add(&fh->fh);
+ file->private_data = fh;
return 0;
}
@@ -1106,7 +771,8 @@ static int fops_release(struct file *file)
}
}
- file->private_data = NULL;
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
kfree(fh);
return 0;
@@ -1250,10 +916,11 @@ err:
static unsigned int fops_poll(struct file *file, poll_table *wait)
{
+ unsigned long req_events = poll_requested_events(wait);
struct saa7164_encoder_fh *fh =
(struct saa7164_encoder_fh *)file->private_data;
struct saa7164_port *port = fh->port;
- unsigned int mask = 0;
+ unsigned int mask = v4l2_ctrl_poll(file, wait);
port->last_poll_msecs_diff = port->last_poll_msecs;
port->last_poll_msecs = jiffies_to_msecs(jiffies);
@@ -1263,26 +930,18 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
saa7164_histogram_update(&port->poll_interval,
port->last_poll_msecs_diff);
- if (!video_is_registered(port->v4l_device))
- return -EIO;
+ if (!(req_events & (POLLIN | POLLRDNORM)))
+ return mask;
if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
if (atomic_inc_return(&port->v4l_reader_count) == 1) {
if (saa7164_encoder_initialize(port) < 0)
- return -EINVAL;
+ return mask | POLLERR;
saa7164_encoder_start_streaming(port);
msleep(200);
}
}
- /* blocking wait for buffer */
- if ((file->f_flags & O_NONBLOCK) == 0) {
- if (wait_event_interruptible(port->wait_read,
- saa7164_enc_next_buf(port))) {
- return -ERESTARTSYS;
- }
- }
-
/* Pull the first buffer from the used list */
if (!list_empty(&port->list_buf_used.list))
mask |= POLLIN | POLLRDNORM;
@@ -1290,6 +949,10 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
return mask;
}
+static const struct v4l2_ctrl_ops saa7164_ctrl_ops = {
+ .s_ctrl = saa7164_s_ctrl,
+};
+
static const struct v4l2_file_operations mpeg_fops = {
.owner = THIS_MODULE,
.open = fops_open,
@@ -1302,24 +965,21 @@ static const struct v4l2_file_operations mpeg_fops = {
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_s_std = vidioc_s_std,
.vidioc_g_std = vidioc_g_std,
- .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_enum_input = saa7164_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_tuner = saa7164_g_tuner,
+ .vidioc_s_tuner = saa7164_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
- .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
- .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
- .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_fmt_vid_cap = vidioc_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_fmt_vid_cap,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
static struct video_device saa7164_mpeg_template = {
@@ -1357,6 +1017,7 @@ static struct video_device *saa7164_encoder_alloc(
int saa7164_encoder_register(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
+ struct v4l2_ctrl_handler *hdl = &port->ctrl_handler;
int result = -ENODEV;
dprintk(DBGLVL_ENC, "%s()\n", __func__);
@@ -1381,19 +1042,52 @@ int saa7164_encoder_register(struct saa7164_port *port)
port->video_format = EU_VIDEO_FORMAT_MPEG_2;
port->audio_format = 0;
port->video_resolution = 0;
- port->ctl_brightness = 127;
- port->ctl_contrast = 66;
- port->ctl_hue = 128;
- port->ctl_saturation = 62;
- port->ctl_sharpness = 8;
- port->encoder_params.bitrate = ENCODER_DEF_BITRATE;
- port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE;
- port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
- port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
- port->encoder_params.ctl_mute = 0;
- port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
- port->encoder_params.refdist = 1;
- port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE;
+ port->freq = SAA7164_TV_MIN_FREQ;
+
+ v4l2_ctrl_handler_init(hdl, 14);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 255, 1, 66);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 255, 1, 62);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_HUE, 0, 255, 1, 128);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_SHARPNESS, 0x0, 0x0f, 1, 8);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_AUDIO_MUTE, 0x0, 0x01, 1, 0);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_AUDIO_VOLUME, -83, 24, 1, 20);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE,
+ ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
+ 100000, ENCODER_DEF_BITRATE);
+ v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_TYPE,
+ V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0,
+ V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+ v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_ASPECT,
+ V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
+ V4L2_MPEG_VIDEO_ASPECT_4x3);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, 15);
+ v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+ V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_B_FRAMES, 1, 3, 1, 1);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+ ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
+ 100000, ENCODER_DEF_BITRATE);
+ if (hdl->error) {
+ result = hdl->error;
+ goto failed;
+ }
+
port->std = V4L2_STD_NTSC_M;
if (port->encodernorm.id & V4L2_STD_525_60)
@@ -1412,6 +1106,8 @@ int saa7164_encoder_register(struct saa7164_port *port)
goto failed;
}
+ port->v4l_device->ctrl_handler = hdl;
+ v4l2_ctrl_handler_setup(hdl);
video_set_drvdata(port->v4l_device, port);
result = video_register_device(port->v4l_device,
VFL_TYPE_GRABBER, -1);
@@ -1466,6 +1162,7 @@ void saa7164_encoder_unregister(struct saa7164_port *port)
port->v4l_device = NULL;
}
+ v4l2_ctrl_handler_free(&port->ctrl_handler);
dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
}
diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c
index 859fd03d82f9..ee54491459a6 100644
--- a/drivers/media/pci/saa7164/saa7164-vbi.c
+++ b/drivers/media/pci/saa7164/saa7164-vbi.c
@@ -21,20 +21,6 @@
#include "saa7164.h"
-static struct saa7164_tvnorm saa7164_tvnorms[] = {
- {
- .name = "NTSC-M",
- .id = V4L2_STD_NTSC_M,
- }, {
- .name = "NTSC-JP",
- .id = V4L2_STD_NTSC_M_JP,
- }
-};
-
-static const u32 saa7164_v4l2_ctrls[] = {
- 0
-};
-
/* Take the encoder configuration from the port struct and
* flush it to the hardware.
*/
@@ -43,23 +29,13 @@ static void saa7164_vbi_configure(struct saa7164_port *port)
struct saa7164_dev *dev = port->dev;
dprintk(DBGLVL_VBI, "%s()\n", __func__);
- port->vbi_params.width = port->width;
- port->vbi_params.height = port->height;
+ port->vbi_params.width = port->enc_port->width;
+ port->vbi_params.height = port->enc_port->height;
port->vbi_params.is_50hz =
- (port->encodernorm.id & V4L2_STD_625_50) != 0;
+ (port->enc_port->encodernorm.id & V4L2_STD_625_50) != 0;
/* Set up the DIF (enable it) for analog mode by default */
saa7164_api_initialize_dif(port);
-
- /* Configure the correct video standard */
-#if 0
- saa7164_api_configure_dif(port, port->encodernorm.id);
-#endif
-
-#if 0
- /* Ensure the audio decoder is correct configured */
- saa7164_api_set_audio_std(port);
-#endif
dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
}
@@ -186,468 +162,50 @@ static int saa7164_vbi_initialize(struct saa7164_port *port)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
- unsigned int i;
- dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)id);
-
- for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
- if (id & saa7164_tvnorms[i].id)
- break;
- }
- if (i == ARRAY_SIZE(saa7164_tvnorms))
- return -EINVAL;
-
- port->encodernorm = saa7164_tvnorms[i];
- port->std = id;
-
- /* Update the audio decoder while is not running in
- * auto detect mode.
- */
- saa7164_api_set_audio_std(port);
-
- dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)id);
-
- return 0;
+ return saa7164_s_std(fh->port->enc_port, id);
}
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- *id = port->std;
- return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- int n;
-
- char *inputs[] = { "tuner", "composite", "svideo", "aux",
- "composite 2", "svideo 2", "aux 2" };
-
- if (i->index >= 7)
- return -EINVAL;
-
- strcpy(i->name, inputs[i->index]);
-
- if (i->index == 0)
- i->type = V4L2_INPUT_TYPE_TUNER;
- else
- i->type = V4L2_INPUT_TYPE_CAMERA;
-
- for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
- i->std |= saa7164_tvnorms[n].id;
-
- return 0;
+ return saa7164_g_std(fh->port->enc_port, id);
}
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- if (saa7164_api_get_videomux(port) != SAA_OK)
- return -EIO;
-
- *i = (port->mux_input - 1);
-
- dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i);
- return 0;
+ return saa7164_g_input(fh->port->enc_port, i);
}
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i);
-
- if (i >= 7)
- return -EINVAL;
-
- port->mux_input = i + 1;
- if (saa7164_api_set_videomux(port) != SAA_OK)
- return -EIO;
-
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- if (0 != t->index)
- return -EINVAL;
-
- strcpy(t->name, "tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
-
- dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
-
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- const struct v4l2_tuner *t)
-{
- /* Update the A/V core */
- return 0;
+ return saa7164_s_input(fh->port->enc_port, i);
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- f->type = V4L2_TUNER_ANALOG_TV;
- f->frequency = port->freq;
-
- return 0;
+ return saa7164_g_frequency(fh->port->enc_port, f);
}
static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
- struct saa7164_port *tsport;
- struct dvb_frontend *fe;
-
- /* TODO: Pull this for the std */
- struct analog_parameters params = {
- .mode = V4L2_TUNER_ANALOG_TV,
- .audmode = V4L2_TUNER_MODE_STEREO,
- .std = port->encodernorm.id,
- .frequency = f->frequency
- };
-
- /* Stop the encoder */
- dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__,
- f->frequency, f->tuner);
-
- if (f->tuner != 0)
- return -EINVAL;
-
- if (f->type != V4L2_TUNER_ANALOG_TV)
- return -EINVAL;
-
- port->freq = f->frequency;
-
- /* Update the hardware */
- if (port->nr == SAA7164_PORT_VBI1)
- tsport = &dev->ports[SAA7164_PORT_TS1];
- else
- if (port->nr == SAA7164_PORT_VBI2)
- tsport = &dev->ports[SAA7164_PORT_TS2];
- else
- BUG();
-
- fe = tsport->dvb.frontend;
-
- if (fe && fe->ops.tuner_ops.set_analog_params)
- fe->ops.tuner_ops.set_analog_params(fe, &params);
- else
- printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
-
- saa7164_vbi_initialize(port);
-
- return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
- case V4L2_CID_BRIGHTNESS:
- ctl->value = port->ctl_brightness;
- break;
- case V4L2_CID_CONTRAST:
- ctl->value = port->ctl_contrast;
- break;
- case V4L2_CID_SATURATION:
- ctl->value = port->ctl_saturation;
- break;
- case V4L2_CID_HUE:
- ctl->value = port->ctl_hue;
- break;
- case V4L2_CID_SHARPNESS:
- ctl->value = port->ctl_sharpness;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- ctl->value = port->ctl_volume;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
- int ret = 0;
-
- dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
- case V4L2_CID_BRIGHTNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_brightness = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_BRIGHTNESS_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_CONTRAST:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_contrast = ctl->value;
- saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_SATURATION:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_saturation = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_SATURATION_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_HUE:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_hue = ctl->value;
- saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_SHARPNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_sharpness = ctl->value;
- saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- if ((ctl->value >= -83) && (ctl->value <= 24)) {
- port->ctl_volume = ctl->value;
- saa7164_api_set_audio_volume(port, port->ctl_volume);
- } else
- ret = -EINVAL;
- break;
- default:
- ret = -EINVAL;
- }
+ int ret = saa7164_s_frequency(fh->port->enc_port, f);
+ if (ret == 0)
+ saa7164_vbi_initialize(fh->port);
return ret;
}
-static int saa7164_get_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_vbi_params *params = &port->vbi_params;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- ctrl->value = params->stream_type;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- ctrl->value = params->ctl_mute;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- ctrl->value = params->ctl_aspect;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- ctrl->value = params->refdist;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- ctrl->value = params->gop_size;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_get_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
-static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
- int ret = -EINVAL;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
- (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
- ret = 0;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 1))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
- (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 255))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- if ((ctrl->value >= 1) &&
- (ctrl->value <= 3))
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
- }
-
- return -EINVAL;
-}
-
-static int saa7164_set_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_vbi_params *params = &port->vbi_params;
- int ret = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- params->stream_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- params->ctl_mute = ctrl->value;
- ret = saa7164_api_audio_mute(port, params->ctl_mute);
- if (ret != SAA_OK) {
- printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
- ret);
- ret = -EIO;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- params->ctl_aspect = ctrl->value;
- ret = saa7164_api_set_aspect_ratio(port);
- if (ret != SAA_OK) {
- printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
- ret);
- ret = -EIO;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- params->refdist = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- params->gop_size = ctrl->value;
- break;
- default:
- return -EINVAL;
- }
-
- /* TODO: Update the hardware */
-
- return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- err = saa7164_set_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -672,144 +230,6 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- if (f->index != 0)
- return -EINVAL;
-
- strlcpy(f->description, "VBI", sizeof(f->description));
- f->pixelformat = V4L2_PIX_FMT_MPEG;
-
- return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
- f->fmt.pix.width = port->width;
- f->fmt.pix.height = port->height;
-
- dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n",
- port->width, port->height);
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
- dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
- port->width, port->height);
- return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
-
- dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
- f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-
- return 0;
-}
-
-static int fill_queryctrl(struct saa7164_vbi_params *params,
- struct v4l2_queryctrl *c)
-{
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
- case V4L2_CID_CONTRAST:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
- case V4L2_CID_SATURATION:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
- case V4L2_CID_HUE:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
- case V4L2_CID_SHARPNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
- case V4L2_CID_MPEG_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
- case V4L2_CID_AUDIO_VOLUME:
- return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
- case V4L2_CID_MPEG_STREAM_TYPE:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
- 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_VIDEO_ASPECT_1x1,
- V4L2_MPEG_VIDEO_ASPECT_221x100,
- 1, V4L2_MPEG_VIDEO_ASPECT_4x3);
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- return v4l2_ctrl_query_fill(c,
- 1, 3, 1, 1);
- default:
- return -EINVAL;
- }
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- struct saa7164_vbi_fh *fh = priv;
- struct saa7164_port *port = fh->port;
- int i, next;
- u32 id = c->id;
-
- memset(c, 0, sizeof(*c));
-
- next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
- c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
- for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
- if (next) {
- if (c->id < saa7164_v4l2_ctrls[i])
- c->id = saa7164_v4l2_ctrls[i];
- else
- continue;
- }
-
- if (c->id == saa7164_v4l2_ctrls[i])
- return fill_queryctrl(&port->vbi_params, c);
-
- if (c->id < saa7164_v4l2_ctrls[i])
- break;
- }
-
- return -EINVAL;
-}
-
static int saa7164_vbi_stop_port(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
@@ -999,7 +419,6 @@ static int saa7164_vbi_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
/* ntsc */
- f->fmt.vbi.samples_per_line = 1600;
f->fmt.vbi.samples_per_line = 1440;
f->fmt.vbi.sampling_rate = 27000000;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -1009,6 +428,7 @@ static int saa7164_vbi_fmt(struct file *file, void *priv,
f->fmt.vbi.count[0] = 18;
f->fmt.vbi.start[1] = 263 + 10 + 1;
f->fmt.vbi.count[1] = 18;
+ memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
return 0;
}
@@ -1031,8 +451,10 @@ static int fops_open(struct file *file)
if (NULL == fh)
return -ENOMEM;
- file->private_data = fh;
fh->port = port;
+ v4l2_fh_init(&fh->fh, video_devdata(file));
+ v4l2_fh_add(&fh->fh);
+ file->private_data = fh;
return 0;
}
@@ -1053,7 +475,8 @@ static int fops_release(struct file *file)
}
}
- file->private_data = NULL;
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
kfree(fh);
return 0;
@@ -1248,24 +671,14 @@ static const struct v4l2_file_operations vbi_fops = {
static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
.vidioc_s_std = vidioc_s_std,
.vidioc_g_std = vidioc_g_std,
- .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_enum_input = saa7164_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_tuner = saa7164_g_tuner,
+ .vidioc_s_tuner = saa7164_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_querycap = vidioc_querycap,
- .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
- .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
- .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
- .vidioc_queryctrl = vidioc_queryctrl,
.vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt,
.vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt,
.vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt,
@@ -1335,7 +748,7 @@ int saa7164_vbi_register(struct saa7164_port *port)
goto failed;
}
- port->std = V4L2_STD_NTSC_M;
+ port->enc_port = &dev->ports[port->nr - 2];
video_set_drvdata(port->v4l_device, port);
result = video_register_device(port->v4l_device,
VFL_TYPE_VBI, -1);
diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h
index 18906e0c80e1..8337524bfb8c 100644
--- a/drivers/media/pci/saa7164/saa7164.h
+++ b/drivers/media/pci/saa7164/saa7164.h
@@ -54,8 +54,6 @@
#include <media/tuner.h>
#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/videobuf-dvb.h>
#include <dvb_demux.h>
#include <dvb_frontend.h>
#include <dvb_net.h>
@@ -64,6 +62,8 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include "saa7164-reg.h"
#include "saa7164-types.h"
@@ -117,7 +117,11 @@
#define DBGLVL_CPU 8192
#define SAA7164_NORMS \
- (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443)
+ (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP)
+
+/* TV frequency range copied from tuner-core.c */
+#define SAA7164_TV_MIN_FREQ (44U * 16U)
+#define SAA7164_TV_MAX_FREQ (958U * 16U)
enum port_t {
SAA7164_MPEG_UNDEFINED = 0,
@@ -185,11 +189,13 @@ struct saa7164_subid {
};
struct saa7164_encoder_fh {
+ struct v4l2_fh fh;
struct saa7164_port *port;
atomic_t v4l_reading;
};
struct saa7164_vbi_fh {
+ struct v4l2_fh fh;
struct saa7164_port *port;
atomic_t v4l_reading;
};
@@ -381,12 +387,11 @@ struct saa7164_port {
/* Encoder */
/* Defaults established in saa7164-encoder.c */
struct saa7164_tvnorm encodernorm;
+ struct v4l2_ctrl_handler ctrl_handler;
v4l2_std_id std;
u32 height;
u32 width;
u32 freq;
- u32 ts_packet_size;
- u32 ts_packet_count;
u8 mux_input;
u8 encoder_profile;
u8 video_format;
@@ -419,6 +424,7 @@ struct saa7164_port {
/* V4L VBI */
struct tmComResVBIFormatDescrHeader vbi_fmt_ntsc;
struct saa7164_vbi_params vbi_params;
+ struct saa7164_port *enc_port;
/* Debug */
u32 sync_errors;
@@ -594,6 +600,16 @@ extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
/* ----------------------------------------------------------- */
/* saa7164-encoder.c */
+int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id);
+int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id);
+int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i);
+int saa7164_g_input(struct saa7164_port *port, unsigned int *i);
+int saa7164_s_input(struct saa7164_port *port, unsigned int i);
+int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+int saa7164_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t);
+int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f);
+int saa7164_s_frequency(struct saa7164_port *port,
+ const struct v4l2_frequency *f);
int saa7164_encoder_register(struct saa7164_port *port);
void saa7164_encoder_unregister(struct saa7164_port *port);
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 53fff5425c13..4432fd69b7cb 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -458,11 +458,12 @@ static inline u32 vop_usec(const vop_header *vh)
static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, const vop_header *vh)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int frame_size;
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
return -EIO;
@@ -470,7 +471,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
- return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+ return solo_send_desc(solo_enc, solo_enc->jpeg_len, sgt,
vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
SOLO_JPEG_EXT_SIZE(solo_dev));
@@ -479,8 +480,9 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, const vop_header *vh)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int frame_off, frame_size;
int skip = 0;
@@ -488,15 +490,15 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
return -EIO;
/* If this is a key frame, add extra header */
- vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
+ vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME);
if (!vop_type(vh)) {
skip = solo_enc->vop_len;
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
solo_enc->vop_len);
} else {
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+ vbuf->flags |= V4L2_BUF_FLAG_PFRAME;
vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
}
@@ -505,7 +507,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
- return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+ return solo_send_desc(solo_enc, skip, sgt, frame_off, frame_size,
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
}
@@ -513,6 +515,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
const vop_header *vh = enc_buf->vh;
int ret;
@@ -527,17 +530,18 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
}
if (!ret) {
- vb->v4l2_buf.sequence = solo_enc->sequence++;
- vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
- vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
+ vbuf->sequence = solo_enc->sequence++;
+ vbuf->timestamp.tv_sec = vop_sec(vh);
+ vbuf->timestamp.tv_usec = vop_usec(vh);
/* Check for motion flags */
if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
struct v4l2_event ev = {
.type = V4L2_EVENT_MOTION_DET,
.u.motion_det = {
- .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
- .frame_sequence = vb->v4l2_buf.sequence,
+ .flags
+ = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+ .frame_sequence = vbuf->sequence,
.region_mask = enc_buf->motion ? 1 : 0,
},
};
@@ -571,7 +575,7 @@ static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
list_del(&vb->list);
spin_unlock_irqrestore(&solo_enc->av_lock, flags);
- solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf);
+ solo_enc_fillbuf(solo_enc, &vb->vb.vb2_buf, enc_buf);
unlock:
mutex_unlock(&solo_enc->lock);
}
@@ -659,7 +663,7 @@ static int solo_ring_thread(void *data)
}
static int solo_enc_queue_setup(struct vb2_queue *q,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *num_buffers,
unsigned int *num_planes, unsigned int sizes[],
void *alloc_ctxs[])
@@ -678,10 +682,11 @@ static int solo_enc_queue_setup(struct vb2_queue *q,
static void solo_enc_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
struct solo_vb2_buf *solo_vb =
- container_of(vb, struct solo_vb2_buf, vb);
+ container_of(vbuf, struct solo_vb2_buf, vb);
spin_lock(&solo_enc->av_lock);
list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
@@ -734,25 +739,26 @@ static void solo_enc_stop_streaming(struct vb2_queue *q)
struct solo_vb2_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&solo_enc->av_lock, flags);
}
static void solo_enc_buf_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
switch (solo_enc->fmt) {
case V4L2_PIX_FMT_MPEG4:
case V4L2_PIX_FMT_H264:
- if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
- sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+ if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)
+ sg_copy_from_buffer(sgt->sgl, sgt->nents,
solo_enc->vop, solo_enc->vop_len);
break;
default: /* V4L2_PIX_FMT_MJPEG */
- sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+ sg_copy_from_buffer(sgt->sgl, sgt->nents,
solo_enc->jpeg_header, solo_enc->jpeg_len);
break;
}
@@ -1291,7 +1297,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->vidq.ops = &solo_enc_video_qops;
solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
solo_enc->vidq.drv_priv = solo_enc;
- solo_enc->vidq.gfp_flags = __GFP_DMA32;
+ solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
solo_enc->vidq.lock = &solo_enc->lock;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 63ae8a61f603..f7ce493b1fee 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -26,6 +26,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "solo6x10.h"
@@ -191,13 +192,14 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
static void solo_fillbuf(struct solo_dev *solo_dev,
struct vb2_buffer *vb)
{
- dma_addr_t vbuf;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ dma_addr_t addr;
unsigned int fdma_addr;
int error = -1;
int i;
- vbuf = vb2_dma_contig_plane_dma_addr(vb, 0);
- if (!vbuf)
+ addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (!addr)
goto finish_buf;
if (erase_off(solo_dev)) {
@@ -213,7 +215,7 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
(SOLO_HW_BPL * solo_vlines(solo_dev)));
- error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr,
+ error = solo_p2m_dma_t(solo_dev, 0, addr, fdma_addr,
solo_bytesperline(solo_dev),
solo_vlines(solo_dev), SOLO_HW_BPL);
}
@@ -222,8 +224,8 @@ finish_buf:
if (!error) {
vb2_set_plane_payload(vb, 0,
solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
- vb->v4l2_buf.sequence = solo_dev->sequence++;
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+ vbuf->sequence = solo_dev->sequence++;
+ v4l2_get_timestamp(&vbuf->timestamp);
}
vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
@@ -256,7 +258,7 @@ static void solo_thread_try(struct solo_dev *solo_dev)
spin_unlock(&solo_dev->slock);
- solo_fillbuf(solo_dev, &vb->vb);
+ solo_fillbuf(solo_dev, &vb->vb.vb2_buf);
}
assert_spin_locked(&solo_dev->slock);
@@ -311,7 +313,7 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
solo_dev->kthread = NULL;
}
-static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int solo_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -345,10 +347,11 @@ static void solo_stop_streaming(struct vb2_queue *q)
static void solo_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct solo_dev *solo_dev = vb2_get_drv_priv(vq);
struct solo_vb2_buf *solo_vb =
- container_of(vb, struct solo_vb2_buf, vb);
+ container_of(vbuf, struct solo_vb2_buf, vb);
spin_lock(&solo_dev->slock);
list_add_tail(&solo_vb->list, &solo_dev->vidq_active);
@@ -675,7 +678,7 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
solo_dev->vidq.drv_priv = solo_dev;
solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- solo_dev->vidq.gfp_flags = __GFP_DMA32;
+ solo_dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
solo_dev->vidq.lock = &solo_dev->lock;
ret = vb2_queue_init(&solo_dev->vidq);
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 27423d7f5410..4ab6586c0467 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -35,7 +35,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "solo6x10-regs.h"
@@ -135,7 +135,7 @@ struct solo_p2m_dev {
#define OSD_TEXT_MAX 44
struct solo_vb2_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 59b3a36a3639..6367b455a7e7 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -88,11 +88,11 @@
struct vip_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
dma_addr_t dma;
};
-static inline struct vip_buffer *to_vip_buffer(struct vb2_buffer *vb2)
+static inline struct vip_buffer *to_vip_buffer(struct vb2_v4l2_buffer *vb2)
{
return container_of(vb2, struct vip_buffer, vb);
}
@@ -265,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip)
/* Videobuf2 Operations */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -287,7 +287,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
};
static int buffer_init(struct vb2_buffer *vb)
{
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
vip_buf->dma = vb2_dma_contig_plane_dma_addr(vb, 0);
INIT_LIST_HEAD(&vip_buf->list);
@@ -296,8 +297,9 @@ static int buffer_init(struct vb2_buffer *vb)
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue);
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
unsigned long size;
size = vip->format.sizeimage;
@@ -307,14 +309,15 @@ static int buffer_prepare(struct vb2_buffer *vb)
return -EINVAL;
}
- vb2_set_plane_payload(&vip_buf->vb, 0, size);
+ vb2_set_plane_payload(&vip_buf->vb.vb2_buf, 0, size);
return 0;
}
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue);
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
spin_lock(&vip->lock);
list_add_tail(&vip_buf->list, &vip->buffer_list);
@@ -329,8 +332,9 @@ static void buffer_queue(struct vb2_buffer *vb)
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue);
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
/* Buffer handled, remove it from the list */
spin_lock(&vip->lock);
@@ -370,7 +374,7 @@ static void stop_streaming(struct vb2_queue *vq)
/* Release all active buffers */
spin_lock(&vip->lock);
list_for_each_entry_safe(vip_buf, node, &vip->buffer_list, list) {
- vb2_buffer_done(&vip_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&vip_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&vip_buf->list);
}
spin_unlock(&vip->lock);
@@ -813,9 +817,9 @@ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
/* Disable acquisition */
reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA);
/* Remove the active buffer from the list */
- v4l2_get_timestamp(&vip->active->vb.v4l2_buf.timestamp);
- vip->active->vb.v4l2_buf.sequence = vip->sequence++;
- vb2_buffer_done(&vip->active->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vip->active->vb.timestamp);
+ vip->active->vb.sequence = vip->sequence++;
+ vb2_buffer_done(&vip->active->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
return IRQ_HANDLED;
diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c
index 3f24fce74fc1..f89364951ebd 100644
--- a/drivers/media/pci/ttpci/av7110.c
+++ b/drivers/media/pci/ttpci/av7110.c
@@ -303,7 +303,6 @@ static int arm_thread(void *data)
static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
u8 *buffer2, size_t buffer2_len,
struct dvb_demux_filter *dvbdmxfilter,
- enum dmx_success success,
struct av7110 *av7110)
{
if (!dvbdmxfilter->feed->demux->dmx.frontend)
@@ -329,16 +328,14 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
}
return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
buffer2, buffer2_len,
- &dvbdmxfilter->filter,
- DMX_OK);
+ &dvbdmxfilter->filter);
case DMX_TYPE_TS:
if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
return 0;
if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
buffer2, buffer2_len,
- &dvbdmxfilter->feed->feed.ts,
- DMX_OK);
+ &dvbdmxfilter->feed->feed.ts);
else
av7110_p2t_write(buffer1, buffer1_len,
dvbdmxfilter->feed->pid,
@@ -422,7 +419,7 @@ static void debiirq(unsigned long cookie)
DvbDmxFilterCallback((u8 *)av7110->debi_virt,
av7110->debilen, NULL, 0,
av7110->handle2filter[handle],
- DMX_OK, av7110);
+ av7110);
xfer = RX_BUFF;
break;
diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c
index 9544cfc06601..9ed1ec7d3551 100644
--- a/drivers/media/pci/ttpci/av7110_av.c
+++ b/drivers/media/pci/ttpci/av7110_av.c
@@ -102,7 +102,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
buf[4] = buf[5] = 0;
if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
- &dvbdmxfeed->feed.ts, DMX_OK);
+ &dvbdmxfeed->feed.ts);
else
return dvb_filter_pes2ts(p2t, buf, len, 1);
}
@@ -112,7 +112,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
dvbdmxfeed->cb.ts(data, 188, NULL, 0,
- &dvbdmxfeed->feed.ts, DMX_OK);
+ &dvbdmxfeed->feed.ts);
return 0;
}
@@ -815,7 +815,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
memcpy(obuf + l, buf + c, TS_SIZE - l);
c = length;
}
- feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts);
pes_start = 0;
}
}
diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c
index 04706cc9b818..4e77618fbb2b 100644
--- a/drivers/media/pci/tw68/tw68-core.c
+++ b/drivers/media/pci/tw68/tw68-core.c
@@ -257,9 +257,9 @@ static int tw68_initdev(struct pci_dev *pci_dev,
dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat, (u64)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+ if (err) {
pr_info("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
goto fail1;
}
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 8355e55b4e8e..46642ef9151b 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -376,10 +376,11 @@ static int tw68_buffer_count(unsigned int size, unsigned int count)
/* ------------------------------------------------------------- */
/* vb2 queue operations */
-static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int tw68_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct tw68_dev *dev = vb2_get_drv_priv(q);
unsigned tot_bufs = q->num_buffers + *num_buffers;
@@ -423,9 +424,10 @@ static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
*/
static void tw68_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
- struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
struct tw68_buf *prev;
unsigned long flags;
@@ -457,9 +459,10 @@ static void tw68_buf_queue(struct vb2_buffer *vb)
*/
static int tw68_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
- struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
unsigned size, bpl;
@@ -499,9 +502,10 @@ static int tw68_buf_prepare(struct vb2_buffer *vb)
static void tw68_buf_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
- struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma);
}
@@ -528,7 +532,7 @@ static void tw68_stop_streaming(struct vb2_queue *q)
container_of(dev->active.next, struct tw68_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
}
@@ -975,7 +979,7 @@ int tw68_video_init2(struct tw68_dev *dev, int video_nr)
dev->vidq.ops = &tw68_video_qops;
dev->vidq.mem_ops = &vb2_dma_sg_memops;
dev->vidq.drv_priv = dev;
- dev->vidq.gfp_flags = __GFP_DMA32;
+ dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
dev->vidq.buf_struct_size = sizeof(struct tw68_buf);
dev->vidq.lock = &dev->lock;
dev->vidq.min_buffers_needed = 2;
@@ -1012,10 +1016,10 @@ void tw68_irq_video_done(struct tw68_dev *dev, unsigned long status)
buf = list_entry(dev->active.next, struct tw68_buf, list);
list_del(&buf->list);
spin_unlock(&dev->slock);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.field = dev->field;
- buf->vb.v4l2_buf.sequence = dev->seqnr++;
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.field = dev->field;
+ buf->vb.sequence = dev->seqnr++;
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
status &= ~(TW68_DMAPI);
if (0 == status)
return;
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index ef51e4d48866..6c7dcb300f34 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -36,6 +36,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
#include "tw68-reg.h"
@@ -118,7 +119,7 @@ struct tw68_dev; /* forward delclaration */
/* buffer for one video/vbi/ts frame */
struct tw68_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
unsigned int size;
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index dc75694ac12d..ccbc9742cb7a 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -233,7 +233,7 @@ config VIDEO_SH_VEU
config VIDEO_RENESAS_JPU
tristate "Renesas JPEG Processing Unit"
- depends on VIDEO_DEV && VIDEO_V4L2
+ depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
depends on ARCH_SHMOBILE || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index c8447fa3fd91..f0480d687f17 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -307,7 +307,8 @@ static inline struct vpfe_device *to_vpfe(struct vpfe_ccdc *ccdc)
return container_of(ccdc, struct vpfe_device, ccdc);
}
-static inline struct vpfe_cap_buffer *to_vpfe_buffer(struct vb2_buffer *vb)
+static inline
+struct vpfe_cap_buffer *to_vpfe_buffer(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct vpfe_cap_buffer, vb);
}
@@ -1257,14 +1258,14 @@ static inline void vpfe_schedule_next_buffer(struct vpfe_device *vpfe)
list_del(&vpfe->next_frm->list);
vpfe_set_sdr_addr(&vpfe->ccdc,
- vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0));
+ vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0));
}
static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe)
{
unsigned long addr;
- addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0) +
+ addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0) +
vpfe->field_off;
vpfe_set_sdr_addr(&vpfe->ccdc, addr);
@@ -1280,10 +1281,10 @@ static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe)
*/
static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe)
{
- v4l2_get_timestamp(&vpfe->cur_frm->vb.v4l2_buf.timestamp);
- vpfe->cur_frm->vb.v4l2_buf.field = vpfe->fmt.fmt.pix.field;
- vpfe->cur_frm->vb.v4l2_buf.sequence = vpfe->sequence++;
- vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vpfe->cur_frm->vb.timestamp);
+ vpfe->cur_frm->vb.field = vpfe->fmt.fmt.pix.field;
+ vpfe->cur_frm->vb.sequence = vpfe->sequence++;
+ vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
vpfe->cur_frm = vpfe->next_frm;
}
@@ -1907,10 +1908,11 @@ static void vpfe_calculate_offsets(struct vpfe_device *vpfe)
* the buffer count and buffer size
*/
static int vpfe_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage)
@@ -1942,6 +1944,7 @@ static int vpfe_queue_setup(struct vb2_queue *vq,
*/
static int vpfe_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue);
vb2_set_plane_payload(vb, 0, vpfe->fmt.fmt.pix.sizeimage);
@@ -1949,7 +1952,7 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb)
if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
return -EINVAL;
- vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field;
+ vbuf->field = vpfe->fmt.fmt.pix.field;
return 0;
}
@@ -1960,8 +1963,9 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb)
*/
static void vpfe_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue);
- struct vpfe_cap_buffer *buf = to_vpfe_buffer(vb);
+ struct vpfe_cap_buffer *buf = to_vpfe_buffer(vbuf);
unsigned long flags = 0;
/* add the buffer to the DMA queue */
@@ -2006,7 +2010,7 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
list_del(&vpfe->cur_frm->list);
spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags);
- addr = vb2_dma_contig_plane_dma_addr(&vpfe->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&vpfe->cur_frm->vb.vb2_buf, 0);
vpfe_set_sdr_addr(&vpfe->ccdc, (unsigned long)(addr));
@@ -2023,7 +2027,7 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
err:
list_for_each_entry_safe(buf, tmp, &vpfe->dma_queue, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
return ret;
@@ -2055,13 +2059,14 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */
spin_lock_irqsave(&vpfe->dma_queue_lock, flags);
if (vpfe->cur_frm == vpfe->next_frm) {
- vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
} else {
if (vpfe->cur_frm != NULL)
- vb2_buffer_done(&vpfe->cur_frm->vb,
+ vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
if (vpfe->next_frm != NULL)
- vb2_buffer_done(&vpfe->next_frm->vb,
+ vb2_buffer_done(&vpfe->next_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
}
@@ -2069,7 +2074,8 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
vpfe->next_frm = list_entry(vpfe->dma_queue.next,
struct vpfe_cap_buffer, list);
list_del(&vpfe->next_frm->list);
- vb2_buffer_done(&vpfe->next_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&vpfe->next_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags);
}
@@ -2546,11 +2552,12 @@ static int vpfe_probe(struct platform_device *pdev)
if (IS_ERR(ccdc->ccdc_cfg.base_addr))
return PTR_ERR(ccdc->ccdc_cfg.base_addr);
- vpfe->irq = platform_get_irq(pdev, 0);
- if (vpfe->irq <= 0) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
dev_err(&pdev->dev, "No IRQ resource\n");
return -ENODEV;
}
+ vpfe->irq = ret;
ret = devm_request_irq(vpfe->pdev, vpfe->irq, vpfe_isr, 0,
"vpfe_capture0", vpfe);
diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
index 5bfb35649a39..777bf97fea57 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.h
+++ b/drivers/media/platform/am437x/am437x-vpfe.h
@@ -31,6 +31,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "am437x-vpfe_regs.h"
@@ -104,7 +105,7 @@ struct vpfe_config {
};
struct vpfe_cap_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index b7e70fb05eb8..7764b9c482ef 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -54,7 +54,7 @@ struct bcap_format {
};
struct bcap_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -149,7 +149,7 @@ static const struct bcap_format bcap_formats[] = {
static irqreturn_t bcap_isr(int irq, void *dev_id);
-static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb)
+static struct bcap_buffer *to_bcap_vb(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct bcap_buffer, vb);
}
@@ -202,10 +202,11 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev)
}
static int bcap_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
if (fmt && fmt->fmt.pix.sizeimage < bcap_dev->fmt.sizeimage)
@@ -223,6 +224,7 @@ static int bcap_queue_setup(struct vb2_queue *vq,
static int bcap_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue);
unsigned long size = bcap_dev->fmt.sizeimage;
@@ -233,15 +235,16 @@ static int bcap_buffer_prepare(struct vb2_buffer *vb)
}
vb2_set_plane_payload(vb, 0, size);
- vb->v4l2_buf.field = bcap_dev->fmt.field;
+ vbuf->field = bcap_dev->fmt.field;
return 0;
}
static void bcap_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue);
- struct bcap_buffer *buf = to_bcap_vb(vb);
+ struct bcap_buffer *buf = to_bcap_vb(vbuf);
unsigned long flags;
spin_lock_irqsave(&bcap_dev->lock, flags);
@@ -251,8 +254,9 @@ static void bcap_buffer_queue(struct vb2_buffer *vb)
static void bcap_buffer_cleanup(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue);
- struct bcap_buffer *buf = to_bcap_vb(vb);
+ struct bcap_buffer *buf = to_bcap_vb(vbuf);
unsigned long flags;
spin_lock_irqsave(&bcap_dev->lock, flags);
@@ -333,7 +337,8 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
struct bcap_buffer, list);
/* remove buffer from the dma queue */
list_del_init(&bcap_dev->cur_frm->list);
- addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb.vb2_buf,
+ 0);
/* update DMA address */
ppi->ops->update_addr(ppi, (unsigned long)addr);
/* enable ppi */
@@ -344,7 +349,7 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
err:
list_for_each_entry_safe(buf, tmp, &bcap_dev->dma_queue, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
return ret;
@@ -367,13 +372,15 @@ static void bcap_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */
if (bcap_dev->cur_frm)
- vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
while (!list_empty(&bcap_dev->dma_queue)) {
bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
struct bcap_buffer, list);
list_del_init(&bcap_dev->cur_frm->list);
- vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
}
}
@@ -392,18 +399,19 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
{
struct ppi_if *ppi = dev_id;
struct bcap_device *bcap_dev = ppi->priv;
- struct vb2_buffer *vb = &bcap_dev->cur_frm->vb;
+ struct vb2_v4l2_buffer *vbuf = &bcap_dev->cur_frm->vb;
+ struct vb2_buffer *vb = &vbuf->vb2_buf;
dma_addr_t addr;
spin_lock(&bcap_dev->lock);
if (!list_empty(&bcap_dev->dma_queue)) {
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+ v4l2_get_timestamp(&vbuf->timestamp);
if (ppi->err) {
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
ppi->err = false;
} else {
- vb->v4l2_buf.sequence = bcap_dev->sequence++;
+ vbuf->sequence = bcap_dev->sequence++;
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
}
bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
@@ -420,7 +428,8 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
if (bcap_dev->stop) {
complete(&bcap_dev->comp);
} else {
- addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(
+ &bcap_dev->cur_frm->vb.vb2_buf, 0);
ppi->ops->update_addr(ppi, (unsigned long)addr);
ppi->ops->start(ppi);
}
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index fd7819d8922d..654e964f84a2 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -25,7 +25,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-vmalloc.h>
@@ -179,31 +179,32 @@ static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
}
static int coda_bitstream_queue(struct coda_ctx *ctx,
- struct vb2_buffer *src_buf)
+ struct vb2_v4l2_buffer *src_buf)
{
- u32 src_size = vb2_get_plane_payload(src_buf, 0);
+ u32 src_size = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
u32 n;
- n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0),
- src_size);
+ n = kfifo_in(&ctx->bitstream_fifo,
+ vb2_plane_vaddr(&src_buf->vb2_buf, 0), src_size);
if (n < src_size)
return -ENOSPC;
- src_buf->v4l2_buf.sequence = ctx->qsequence++;
+ src_buf->sequence = ctx->qsequence++;
return 0;
}
static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
- struct vb2_buffer *src_buf)
+ struct vb2_v4l2_buffer *src_buf)
{
int ret;
if (coda_get_bitstream_payload(ctx) +
- vb2_get_plane_payload(src_buf, 0) + 512 >= ctx->bitstream.size)
+ vb2_get_plane_payload(&src_buf->vb2_buf, 0) + 512 >=
+ ctx->bitstream.size)
return false;
- if (vb2_plane_vaddr(src_buf, 0) == NULL) {
+ if (vb2_plane_vaddr(&src_buf->vb2_buf, 0) == NULL) {
v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n");
return true;
}
@@ -224,7 +225,7 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
{
- struct vb2_buffer *src_buf;
+ struct vb2_v4l2_buffer *src_buf;
struct coda_buffer_meta *meta;
unsigned long flags;
u32 start;
@@ -257,7 +258,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
}
/* Dump empty buffers */
- if (!vb2_get_plane_payload(src_buf, 0)) {
+ if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) {
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
continue;
@@ -276,9 +277,9 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
meta = kmalloc(sizeof(*meta), GFP_KERNEL);
if (meta) {
- meta->sequence = src_buf->v4l2_buf.sequence;
- meta->timecode = src_buf->v4l2_buf.timecode;
- meta->timestamp = src_buf->v4l2_buf.timestamp;
+ meta->sequence = src_buf->sequence;
+ meta->timecode = src_buf->timecode;
+ meta->timestamp = src_buf->timestamp;
meta->start = start;
meta->end = ctx->bitstream_fifo.kfifo.in &
ctx->bitstream_fifo.kfifo.mask;
@@ -483,20 +484,21 @@ err:
return ret;
}
-static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
+static int coda_encode_header(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
int header_code, u8 *header, int *size)
{
+ struct vb2_buffer *vb = &buf->vb2_buf;
struct coda_dev *dev = ctx->dev;
size_t bufsize;
int ret;
int i;
if (dev->devtype->product == CODA_960)
- memset(vb2_plane_vaddr(buf, 0), 0, 64);
+ memset(vb2_plane_vaddr(vb, 0), 0, 64);
- coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0),
+ coda_write(dev, vb2_dma_contig_plane_dma_addr(vb, 0),
CODA_CMD_ENC_HEADER_BB_START);
- bufsize = vb2_plane_size(buf, 0);
+ bufsize = vb2_plane_size(vb, 0);
if (dev->devtype->product == CODA_960)
bufsize /= 1024;
coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
@@ -509,14 +511,14 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
if (dev->devtype->product == CODA_960) {
for (i = 63; i > 0; i--)
- if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0)
+ if (((char *)vb2_plane_vaddr(vb, 0))[i] != 0)
break;
*size = i + 1;
} else {
*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
}
- memcpy(header, vb2_plane_vaddr(buf, 0), *size);
+ memcpy(header, vb2_plane_vaddr(vb, 0), *size);
return 0;
}
@@ -799,7 +801,7 @@ static int coda_start_encoding(struct coda_ctx *ctx)
struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
struct coda_q_data *q_data_src, *q_data_dst;
u32 bitstream_buf, bitstream_size;
- struct vb2_buffer *buf;
+ struct vb2_v4l2_buffer *buf;
int gamma, ret, value;
u32 dst_fourcc;
int num_fb;
@@ -810,7 +812,7 @@ static int coda_start_encoding(struct coda_ctx *ctx)
dst_fourcc = q_data_dst->fourcc;
buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
+ bitstream_buf = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0);
bitstream_size = q_data_dst->sizeimage;
if (!coda_is_initialized(dev)) {
@@ -1185,7 +1187,7 @@ out:
static int coda_prepare_encode(struct coda_ctx *ctx)
{
struct coda_q_data *q_data_src, *q_data_dst;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
struct coda_dev *dev = ctx->dev;
int force_ipicture;
int quant_param = 0;
@@ -1200,8 +1202,8 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
dst_fourcc = q_data_dst->fourcc;
- src_buf->v4l2_buf.sequence = ctx->osequence;
- dst_buf->v4l2_buf.sequence = ctx->osequence;
+ src_buf->sequence = ctx->osequence;
+ dst_buf->sequence = ctx->osequence;
ctx->osequence++;
/*
@@ -1209,12 +1211,12 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
* frame as IDR. This is a problem for some decoders that can't
* recover when a frame is lost.
*/
- if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) {
- src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
- src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+ if (src_buf->sequence % ctx->params.gop_size) {
+ src_buf->flags |= V4L2_BUF_FLAG_PFRAME;
+ src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME;
} else {
- src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
- src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
+ src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+ src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
}
if (dev->devtype->product == CODA_960)
@@ -1224,9 +1226,9 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
* Copy headers at the beginning of the first frame for H.264 only.
* In MPEG4 they are already copied by the coda.
*/
- if (src_buf->v4l2_buf.sequence == 0) {
+ if (src_buf->sequence == 0) {
pic_stream_buffer_addr =
- vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
+ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) +
ctx->vpu_header_size[0] +
ctx->vpu_header_size[1] +
ctx->vpu_header_size[2];
@@ -1234,20 +1236,21 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
ctx->vpu_header_size[0] -
ctx->vpu_header_size[1] -
ctx->vpu_header_size[2];
- memcpy(vb2_plane_vaddr(dst_buf, 0),
+ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0),
&ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
- memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0],
- &ctx->vpu_header[1][0], ctx->vpu_header_size[1]);
- memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0] +
- ctx->vpu_header_size[1], &ctx->vpu_header[2][0],
- ctx->vpu_header_size[2]);
+ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
+ + ctx->vpu_header_size[0], &ctx->vpu_header[1][0],
+ ctx->vpu_header_size[1]);
+ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
+ + ctx->vpu_header_size[0] + ctx->vpu_header_size[1],
+ &ctx->vpu_header[2][0], ctx->vpu_header_size[2]);
} else {
pic_stream_buffer_addr =
- vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
pic_stream_buffer_size = q_data_dst->sizeimage;
}
- if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
+ if (src_buf->flags & V4L2_BUF_FLAG_KEYFRAME) {
force_ipicture = 1;
switch (dst_fourcc) {
case V4L2_PIX_FMT_H264:
@@ -1324,7 +1327,7 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
static void coda_finish_encode(struct coda_ctx *ctx)
{
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
struct coda_dev *dev = ctx->dev;
u32 wr_ptr, start_ptr;
@@ -1338,13 +1341,13 @@ static void coda_finish_encode(struct coda_ctx *ctx)
wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
/* Calculate bytesused field */
- if (dst_buf->v4l2_buf.sequence == 0) {
- vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr +
+ if (dst_buf->sequence == 0) {
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
ctx->vpu_header_size[0] +
ctx->vpu_header_size[1] +
ctx->vpu_header_size[2]);
} else {
- vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr);
}
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n",
@@ -1354,18 +1357,18 @@ static void coda_finish_encode(struct coda_ctx *ctx)
coda_read(dev, CODA_RET_ENC_PIC_FLAG);
if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) {
- dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
+ dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+ dst_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
} else {
- dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+ dst_buf->flags |= V4L2_BUF_FLAG_PFRAME;
+ dst_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME;
}
- dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_buf->v4l2_buf.flags |=
- src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
+ dst_buf->timestamp = src_buf->timestamp;
+ dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_buf->flags |=
+ src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_buf->timecode = src_buf->timecode;
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
@@ -1378,8 +1381,8 @@ static void coda_finish_encode(struct coda_ctx *ctx)
v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
"job finished: encoding frame (%d) (%s)\n",
- dst_buf->v4l2_buf.sequence,
- (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
+ dst_buf->sequence,
+ (dst_buf->flags & V4L2_BUF_FLAG_KEYFRAME) ?
"KEYFRAME" : "PFRAME");
}
@@ -1716,7 +1719,7 @@ static int coda_start_decoding(struct coda_ctx *ctx)
static int coda_prepare_decode(struct coda_ctx *ctx)
{
- struct vb2_buffer *dst_buf;
+ struct vb2_v4l2_buffer *dst_buf;
struct coda_dev *dev = ctx->dev;
struct coda_q_data *q_data_dst;
struct coda_buffer_meta *meta;
@@ -1763,7 +1766,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
* well as the rotator buffer output.
* ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames.
*/
- coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index,
+ coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->vb2_buf.index,
CODA9_CMD_DEC_PIC_ROT_INDEX);
reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
@@ -1838,7 +1841,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
struct coda_dev *dev = ctx->dev;
struct coda_q_data *q_data_src;
struct coda_q_data *q_data_dst;
- struct vb2_buffer *dst_buf;
+ struct vb2_v4l2_buffer *dst_buf;
struct coda_buffer_meta *meta;
unsigned long payload;
unsigned long flags;
@@ -2029,15 +2032,15 @@ static void coda_finish_decode(struct coda_ctx *ctx)
if (ctx->display_idx >= 0 &&
ctx->display_idx < ctx->num_internal_frames) {
dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- dst_buf->v4l2_buf.sequence = ctx->osequence++;
+ dst_buf->sequence = ctx->osequence++;
- dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+ dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME);
- dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx];
+ dst_buf->flags |= ctx->frame_types[ctx->display_idx];
meta = &ctx->frame_metas[ctx->display_idx];
- dst_buf->v4l2_buf.timecode = meta->timecode;
- dst_buf->v4l2_buf.timestamp = meta->timestamp;
+ dst_buf->timecode = meta->timecode;
+ dst_buf->timestamp = meta->timestamp;
trace_coda_dec_rot_done(ctx, dst_buf, meta);
@@ -2052,15 +2055,15 @@ static void coda_finish_decode(struct coda_ctx *ctx)
payload = width * height * 2;
break;
}
- vb2_set_plane_payload(dst_buf, 0, payload);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[display_idx] ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
"job finished: decoding frame (%d) (%s)\n",
- dst_buf->v4l2_buf.sequence,
- (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
+ dst_buf->sequence,
+ (dst_buf->flags & V4L2_BUF_FLAG_KEYFRAME) ?
"KEYFRAME" : "PFRAME");
} else {
v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index a4654e0c104d..15516a6e3a39 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -36,7 +36,7 @@
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-vmalloc.h>
@@ -84,9 +84,9 @@ unsigned int coda_read(struct coda_dev *dev, u32 reg)
}
void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
- struct vb2_buffer *buf, unsigned int reg_y)
+ struct vb2_v4l2_buffer *buf, unsigned int reg_y)
{
- u32 base_y = vb2_dma_contig_plane_dma_addr(buf, 0);
+ u32 base_y = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0);
u32 base_cb, base_cr;
switch (q_data->fourcc) {
@@ -684,17 +684,17 @@ static int coda_qbuf(struct file *file, void *priv,
}
static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx,
- struct vb2_buffer *buf)
+ struct vb2_v4l2_buffer *buf)
{
struct vb2_queue *src_vq;
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) &&
- (buf->v4l2_buf.sequence == (ctx->qsequence - 1)));
+ (buf->sequence == (ctx->qsequence - 1)));
}
-void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_buffer *buf,
+void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
enum vb2_buffer_state state)
{
const struct v4l2_event eos_event = {
@@ -702,7 +702,7 @@ void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_buffer *buf,
};
if (coda_buf_is_end_of_stream(ctx, buf)) {
- buf->v4l2_buf.flags |= V4L2_BUF_FLAG_LAST;
+ buf->flags |= V4L2_BUF_FLAG_LAST;
v4l2_event_queue_fh(&ctx->fh, &eos_event);
}
@@ -1131,8 +1131,7 @@ static void set_default_params(struct coda_ctx *ctx)
/*
* Queue operations
*/
-static int coda_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+static int coda_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -1175,6 +1174,7 @@ static int coda_buf_prepare(struct vb2_buffer *vb)
static void coda_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_queue *vq = vb->vb2_queue;
struct coda_q_data *q_data;
@@ -1193,12 +1193,12 @@ static void coda_buf_queue(struct vb2_buffer *vb)
if (vb2_get_plane_payload(vb, 0) == 0)
coda_bit_stream_end_flag(ctx);
mutex_lock(&ctx->bitstream_mutex);
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
if (vb2_is_streaming(vb->vb2_queue))
coda_fill_bitstream(ctx, true);
mutex_unlock(&ctx->bitstream_mutex);
} else {
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
}
@@ -1247,7 +1247,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
struct coda_ctx *ctx = vb2_get_drv_priv(q);
struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
struct coda_q_data *q_data_src, *q_data_dst;
- struct vb2_buffer *buf;
+ struct vb2_v4l2_buffer *buf;
int ret = 0;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
@@ -1338,7 +1338,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
{
struct coda_ctx *ctx = vb2_get_drv_priv(q);
struct coda_dev *dev = ctx->dev;
- struct vb2_buffer *buf;
+ struct vb2_v4l2_buffer *buf;
unsigned long flags;
bool stop;
diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c
index 11e734bc2cbd..96cd42a0baaf 100644
--- a/drivers/media/platform/coda/coda-jpeg.c
+++ b/drivers/media/platform/coda/coda-jpeg.c
@@ -178,12 +178,12 @@ int coda_jpeg_write_tables(struct coda_ctx *ctx)
return 0;
}
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
+bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_buffer *vb)
{
- void *vaddr = vb2_plane_vaddr(vb, 0);
+ void *vaddr = vb2_plane_vaddr(&vb->vb2_buf, 0);
u16 soi = be16_to_cpup((__be16 *)vaddr);
u16 eoi = be16_to_cpup((__be16 *)(vaddr +
- vb2_get_plane_payload(vb, 0) - 2));
+ vb2_get_plane_payload(&vb->vb2_buf, 0) - 2));
return soi == SOI_MARKER && eoi == EOI_MARKER;
}
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 59b2af9c7749..96532b06bd9e 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -24,7 +24,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "coda_regs.h"
@@ -243,7 +243,7 @@ extern int coda_debug;
void coda_write(struct coda_dev *dev, u32 data, u32 reg);
unsigned int coda_read(struct coda_dev *dev, u32 reg);
void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
- struct vb2_buffer *buf, unsigned int reg_y);
+ struct vb2_v4l2_buffer *buf, unsigned int reg_y);
int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
size_t size, const char *name, struct dentry *parent);
@@ -284,12 +284,12 @@ static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx)
void coda_bit_stream_end_flag(struct coda_ctx *ctx);
-void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_buffer *buf,
+void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
enum vb2_buffer_state state);
int coda_h264_padding(int size, char *p);
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
+bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_buffer *vb);
int coda_jpeg_write_tables(struct coda_ctx *ctx);
void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
diff --git a/drivers/media/platform/coda/trace.h b/drivers/media/platform/coda/trace.h
index d9099a0f7c32..f20666a4aa89 100644
--- a/drivers/media/platform/coda/trace.h
+++ b/drivers/media/platform/coda/trace.h
@@ -5,7 +5,7 @@
#define __CODA_TRACE_H__
#include <linux/tracepoint.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "coda.h"
@@ -49,7 +49,7 @@ TRACE_EVENT(coda_bit_done,
);
DECLARE_EVENT_CLASS(coda_buf_class,
- TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf),
+ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf),
@@ -61,7 +61,7 @@ DECLARE_EVENT_CLASS(coda_buf_class,
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
- __entry->index = buf->v4l2_buf.index;
+ __entry->index = buf->vb2_buf.index;
__entry->ctx = ctx->idx;
),
@@ -70,17 +70,17 @@ DECLARE_EVENT_CLASS(coda_buf_class,
);
DEFINE_EVENT(coda_buf_class, coda_enc_pic_run,
- TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf),
+ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf)
);
DEFINE_EVENT(coda_buf_class, coda_enc_pic_done,
- TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf),
+ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf)
);
DECLARE_EVENT_CLASS(coda_buf_meta_class,
- TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf,
+ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
struct coda_buffer_meta *meta),
TP_ARGS(ctx, buf, meta),
@@ -95,7 +95,7 @@ DECLARE_EVENT_CLASS(coda_buf_meta_class,
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
- __entry->index = buf->v4l2_buf.index;
+ __entry->index = buf->vb2_buf.index;
__entry->start = meta->start;
__entry->end = meta->end;
__entry->ctx = ctx->idx;
@@ -107,7 +107,7 @@ DECLARE_EVENT_CLASS(coda_buf_meta_class,
);
DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue,
- TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf,
+ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
struct coda_buffer_meta *meta),
TP_ARGS(ctx, buf, meta)
);
@@ -146,7 +146,7 @@ DEFINE_EVENT(coda_meta_class, coda_dec_pic_done,
);
DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done,
- TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf,
+ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
struct coda_buffer_meta *meta),
TP_ARGS(ctx, buf, meta)
);
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index f69cdd7da10c..6d91422c4e4c 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -74,8 +74,8 @@ static void vpbe_isr_even_field(struct vpbe_display *disp_obj,
if (layer->cur_frm == layer->next_frm)
return;
- v4l2_get_timestamp(&layer->cur_frm->vb.v4l2_buf.timestamp);
- vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&layer->cur_frm->vb.timestamp);
+ vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
/* Make cur_frm pointing to next_frm */
layer->cur_frm = layer->next_frm;
}
@@ -104,8 +104,8 @@ static void vpbe_isr_odd_field(struct vpbe_display *disp_obj,
list_del(&layer->next_frm->list);
spin_unlock(&disp_obj->dma_queue_lock);
/* Mark state of the frame to active */
- layer->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
- addr = vb2_dma_contig_plane_dma_addr(&layer->next_frm->vb, 0);
+ layer->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ addr = vb2_dma_contig_plane_dma_addr(&layer->next_frm->vb.vb2_buf, 0);
osd_device->ops.start_layer(osd_device,
layer->layer_info.id,
addr,
@@ -228,11 +228,12 @@ static int vpbe_buffer_prepare(struct vb2_buffer *vb)
* This function allocates memory for the buffers
*/
static int
-vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vpbe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
/* Get the file handle object and layer object */
struct vpbe_layer *layer = vb2_get_drv_priv(vq);
struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
@@ -259,8 +260,9 @@ vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
*/
static void vpbe_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
/* Get the file handle object and layer object */
- struct vpbe_disp_buffer *buf = container_of(vb,
+ struct vpbe_disp_buffer *buf = container_of(vbuf,
struct vpbe_disp_buffer, vb);
struct vpbe_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
struct vpbe_display *disp = layer->disp_dev;
@@ -290,7 +292,7 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)
/* Remove buffer from the buffer queue */
list_del(&layer->cur_frm->list);
/* Mark state of the current frame to active */
- layer->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+ layer->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
/* Initialize field_id and started member */
layer->field_id = 0;
@@ -299,10 +301,12 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret < 0) {
struct vpbe_disp_buffer *buf, *tmp;
- vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&layer->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
list_for_each_entry_safe(buf, tmp, &layer->dma_queue, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
return ret;
@@ -332,13 +336,14 @@ static void vpbe_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */
spin_lock_irqsave(&disp->dma_queue_lock, flags);
if (layer->cur_frm == layer->next_frm) {
- vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&layer->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
} else {
if (layer->cur_frm != NULL)
- vb2_buffer_done(&layer->cur_frm->vb,
+ vb2_buffer_done(&layer->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
if (layer->next_frm != NULL)
- vb2_buffer_done(&layer->next_frm->vb,
+ vb2_buffer_done(&layer->next_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
}
@@ -346,7 +351,8 @@ static void vpbe_stop_streaming(struct vb2_queue *vq)
layer->next_frm = list_entry(layer->dma_queue.next,
struct vpbe_disp_buffer, list);
list_del(&layer->next_frm->list);
- vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&layer->next_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
}
@@ -383,7 +389,7 @@ static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
unsigned long addr;
int ret;
- addr = vb2_dma_contig_plane_dma_addr(&layer->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&layer->cur_frm->vb.vb2_buf, 0);
/* Set address in the display registers */
osd_device->ops.start_layer(osd_device,
layer->layer_info.id,
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index a5f548138b91..c1e573b7cc6f 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -57,7 +57,8 @@ static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} };
/* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */
static int ycmux_mode;
-static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb)
+static inline
+struct vpif_cap_buffer *to_vpif_buffer(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct vpif_cap_buffer, vb);
}
@@ -72,6 +73,7 @@ static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb)
*/
static int vpif_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *q = vb->vb2_queue;
struct channel_obj *ch = vb2_get_drv_priv(q);
struct common_obj *common;
@@ -85,7 +87,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
return -EINVAL;
- vb->v4l2_buf.field = common->fmt.fmt.pix.field;
+ vbuf->field = common->fmt.fmt.pix.field;
addr = vb2_dma_contig_plane_dma_addr(vb, 0);
if (!IS_ALIGNED((addr + common->ytop_off), 8) ||
@@ -112,10 +114,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
* the buffer count and buffer size
*/
static int vpif_buffer_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct channel_obj *ch = vb2_get_drv_priv(vq);
struct common_obj *common;
@@ -145,8 +148,9 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
*/
static void vpif_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);
- struct vpif_cap_buffer *buf = to_vpif_buffer(vb);
+ struct vpif_cap_buffer *buf = to_vpif_buffer(vbuf);
struct common_obj *common;
unsigned long flags;
@@ -214,7 +218,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
list_del(&common->cur_frm->list);
spin_unlock_irqrestore(&common->irqlock, flags);
- addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb.vb2_buf, 0);
common->set_addr(addr + common->ytop_off,
addr + common->ybtm_off,
@@ -243,7 +247,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
err:
list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
spin_unlock_irqrestore(&common->irqlock, flags);
@@ -286,13 +290,14 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */
spin_lock_irqsave(&common->irqlock, flags);
if (common->cur_frm == common->next_frm) {
- vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
} else {
if (common->cur_frm != NULL)
- vb2_buffer_done(&common->cur_frm->vb,
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
if (common->next_frm != NULL)
- vb2_buffer_done(&common->next_frm->vb,
+ vb2_buffer_done(&common->next_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
}
@@ -300,7 +305,8 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
common->next_frm = list_entry(common->dma_queue.next,
struct vpif_cap_buffer, list);
list_del(&common->next_frm->list);
- vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&common->next_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&common->irqlock, flags);
}
@@ -325,9 +331,8 @@ static struct vb2_ops video_qops = {
*/
static void vpif_process_buffer_complete(struct common_obj *common)
{
- v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
- vb2_buffer_done(&common->cur_frm->vb,
- VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
/* Make curFrm pointing to nextFrm */
common->cur_frm = common->next_frm;
}
@@ -350,7 +355,7 @@ static void vpif_schedule_next_buffer(struct common_obj *common)
/* Remove that buffer from the buffer queue */
list_del(&common->next_frm->list);
spin_unlock(&common->irqlock);
- addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb.vb2_buf, 0);
/* Set top and bottom field addresses in VPIF registers */
common->set_addr(addr + common->ytop_off,
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h
index 8b8a663f6b22..4a7600929b61 100644
--- a/drivers/media/platform/davinci/vpif_capture.h
+++ b/drivers/media/platform/davinci/vpif_capture.h
@@ -52,7 +52,7 @@ struct video_obj {
};
struct vpif_cap_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 682e5d578bf7..fd2780306c17 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -53,7 +53,8 @@ static struct device *vpif_dev;
static void vpif_calculate_offsets(struct channel_obj *ch);
static void vpif_config_addr(struct channel_obj *ch, int muxmode);
-static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb)
+static inline
+struct vpif_disp_buffer *to_vpif_buffer(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct vpif_disp_buffer, vb);
}
@@ -68,6 +69,7 @@ static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb)
*/
static int vpif_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);
struct common_obj *common;
@@ -77,7 +79,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
return -EINVAL;
- vb->v4l2_buf.field = common->fmt.fmt.pix.field;
+ vbuf->field = common->fmt.fmt.pix.field;
if (vb->vb2_queue->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
unsigned long addr = vb2_dma_contig_plane_dma_addr(vb, 0);
@@ -107,10 +109,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
* the buffer count and buffer size
*/
static int vpif_buffer_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct channel_obj *ch = vb2_get_drv_priv(vq);
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
@@ -138,7 +141,8 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,
*/
static void vpif_buffer_queue(struct vb2_buffer *vb)
{
- struct vpif_disp_buffer *buf = to_vpif_buffer(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vpif_disp_buffer *buf = to_vpif_buffer(vbuf);
struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);
struct common_obj *common;
unsigned long flags;
@@ -197,7 +201,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
list_del(&common->cur_frm->list);
spin_unlock_irqrestore(&common->irqlock, flags);
- addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb.vb2_buf, 0);
common->set_addr((addr + common->ytop_off),
(addr + common->ybtm_off),
(addr + common->ctop_off),
@@ -229,7 +233,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
err:
list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
spin_unlock_irqrestore(&common->irqlock, flags);
@@ -264,13 +268,14 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */
spin_lock_irqsave(&common->irqlock, flags);
if (common->cur_frm == common->next_frm) {
- vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
} else {
if (common->cur_frm != NULL)
- vb2_buffer_done(&common->cur_frm->vb,
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
if (common->next_frm != NULL)
- vb2_buffer_done(&common->next_frm->vb,
+ vb2_buffer_done(&common->next_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
}
@@ -278,7 +283,8 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
common->next_frm = list_entry(common->dma_queue.next,
struct vpif_disp_buffer, list);
list_del(&common->next_frm->list);
- vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&common->next_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&common->irqlock, flags);
}
@@ -306,7 +312,7 @@ static void process_progressive_mode(struct common_obj *common)
spin_unlock(&common->irqlock);
/* Set top and bottom field addrs in VPIF registers */
- addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb.vb2_buf, 0);
common->set_addr(addr + common->ytop_off,
addr + common->ybtm_off,
addr + common->ctop_off,
@@ -324,10 +330,10 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
/* one frame is displayed If next frame is
* available, release cur_frm and move on */
/* Copy frame display time */
- v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
/* Change status of the cur_frm */
- vb2_buffer_done(&common->cur_frm->vb,
- VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_DONE);
/* Make cur_frm pointing to next_frm */
common->cur_frm = common->next_frm;
@@ -380,10 +386,10 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
if (!channel_first_int[i][channel_id]) {
/* Mark status of the cur_frm to
* done and unlock semaphore on it */
- v4l2_get_timestamp(&common->cur_frm->vb.
- v4l2_buf.timestamp);
- vb2_buffer_done(&common->cur_frm->vb,
- VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(
+ &common->cur_frm->vb.timestamp);
+ vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_DONE);
/* Make cur_frm pointing to next_frm */
common->cur_frm = common->next_frm;
}
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h
index 849e0e385f18..e7a1723a1b7a 100644
--- a/drivers/media/platform/davinci/vpif_display.h
+++ b/drivers/media/platform/davinci/vpif_display.h
@@ -62,7 +62,7 @@ struct video_obj {
};
struct vpif_disp_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index fa572aacdb3f..e93a2336cfa2 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -19,7 +19,7 @@
#include <linux/videodev2.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mem2mem.h>
@@ -136,7 +136,7 @@ struct gsc_fmt {
* @idx : index of G-Scaler input buffer
*/
struct gsc_input_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
int idx;
};
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index d5cffef2e227..d82e717acba7 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -77,7 +77,7 @@ static void gsc_m2m_stop_streaming(struct vb2_queue *q)
void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state)
{
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
if (!ctx || !ctx->m2m_ctx)
return;
@@ -86,11 +86,11 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state)
dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
if (src_vb && dst_vb) {
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
- dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode;
- dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.flags |=
- src_vb->v4l2_buf.flags
+ dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->timecode = src_vb->timecode;
+ dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->flags |=
+ src_vb->flags
& V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
v4l2_m2m_buf_done(src_vb, vb_state);
@@ -109,23 +109,23 @@ static void gsc_m2m_job_abort(void *priv)
static int gsc_get_bufs(struct gsc_ctx *ctx)
{
struct gsc_frame *s_frame, *d_frame;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
int ret;
s_frame = &ctx->s_frame;
d_frame = &ctx->d_frame;
src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
- ret = gsc_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
+ ret = gsc_prepare_addr(ctx, &src_vb->vb2_buf, s_frame, &s_frame->addr);
if (ret)
return ret;
dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
- ret = gsc_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
+ ret = gsc_prepare_addr(ctx, &dst_vb->vb2_buf, d_frame, &d_frame->addr);
if (ret)
return ret;
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
+ dst_vb->timestamp = src_vb->timestamp;
return 0;
}
@@ -212,7 +212,7 @@ put_device:
}
static int gsc_m2m_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *allocators[])
{
@@ -255,12 +255,13 @@ static int gsc_m2m_buf_prepare(struct vb2_buffer *vb)
static void gsc_m2m_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
if (ctx->m2m_ctx)
- v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
}
static struct vb2_ops gsc_m2m_qops = {
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index cfebf292e15a..99e57320e6f7 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -24,7 +24,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "common.h"
@@ -103,7 +103,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
/* Release unused buffers */
while (!suspend && !list_empty(&cap->pending_buf_q)) {
buf = fimc_pending_queue_pop(cap);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
/* If suspending put unused buffers onto pending queue */
while (!list_empty(&cap->active_buf_q)) {
@@ -111,7 +111,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
if (suspend)
fimc_pending_queue_add(cap, buf);
else
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
fimc_hw_reset(fimc);
@@ -183,8 +183,6 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
struct v4l2_subdev *csis = p->subdevs[IDX_CSIS];
struct fimc_frame *f = &cap->ctx->d_frame;
struct fimc_vid_buffer *v_buf;
- struct timeval *tv;
- struct timespec ts;
if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
wake_up(&fimc->irq_queue);
@@ -193,16 +191,12 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
if (!list_empty(&cap->active_buf_q) &&
test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) {
- ktime_get_real_ts(&ts);
-
v_buf = fimc_active_queue_pop(cap);
- tv = &v_buf->vb.v4l2_buf.timestamp;
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
- v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
+ v4l2_get_timestamp(&v_buf->vb.timestamp);
+ v_buf->vb.sequence = cap->frame_count++;
- vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&v_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
if (!list_empty(&cap->pending_buf_q)) {
@@ -233,7 +227,7 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
list_for_each_entry(v_buf, &cap->active_buf_q, list) {
if (v_buf->index != index)
continue;
- vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
+ vaddr = vb2_plane_vaddr(&v_buf->vb.vb2_buf, plane);
v4l2_subdev_call(csis, video, s_rx_buffer,
vaddr, &size);
break;
@@ -338,16 +332,17 @@ int fimc_capture_resume(struct fimc_dev *fimc)
if (list_empty(&vid_cap->pending_buf_q))
break;
buf = fimc_pending_queue_pop(vid_cap);
- buffer_queue(&buf->vb);
+ buffer_queue(&buf->vb.vb2_buf);
}
return 0;
}
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *allocators[])
{
+ const struct v4l2_format *pfmt = parg;
const struct v4l2_pix_format_mplane *pixm = NULL;
struct fimc_ctx *ctx = vq->drv_priv;
struct fimc_frame *frame = &ctx->d_frame;
@@ -410,8 +405,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct fimc_vid_buffer *buf
- = container_of(vb, struct fimc_vid_buffer, vb);
+ = container_of(vbuf, struct fimc_vid_buffer, vb);
struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct fimc_dev *fimc = ctx->fimc_dev;
struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
@@ -420,7 +416,7 @@ static void buffer_queue(struct vb2_buffer *vb)
int min_bufs;
spin_lock_irqsave(&fimc->slock, flags);
- fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr);
+ fimc_prepare_addr(ctx, &buf->vb.vb2_buf, &ctx->d_frame, &buf->paddr);
if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) &&
!test_bit(ST_CAPT_STREAM, &fimc->state) &&
@@ -1472,7 +1468,8 @@ void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
if (!list_empty(&fimc->vid_cap.active_buf_q)) {
buf = list_entry(fimc->vid_cap.active_buf_q.next,
struct fimc_vid_buffer, list);
- vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg));
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0,
+ *((u32 *)arg));
}
fimc_capture_irq_handler(fimc, 1);
fimc_deactivate_capture(fimc);
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index 1101c41ac117..cef2a7f07cdb 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -27,7 +27,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "fimc-core.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index 7328f0845065..d336fa2916df 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -22,7 +22,7 @@
#include <linux/sizes.h>
#include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mem2mem.h>
@@ -224,7 +224,7 @@ struct fimc_addr {
* @index: buffer index for the output DMA engine
*/
struct fimc_vid_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
struct fimc_addr paddr;
int index;
diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h
index e0be691af2d3..386eb49ece7e 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.h
+++ b/drivers/media/platform/exynos4-is/fimc-is.h
@@ -22,7 +22,7 @@
#include <linux/sizes.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
#include "fimc-isp.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
index 76b6b4d14616..6e6648446f00 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -28,7 +28,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/exynos-fimc.h>
@@ -39,10 +39,11 @@
#include "fimc-is-param.h"
static int isp_video_capture_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *pfmt,
+ const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *allocators[])
{
+ const struct v4l2_format *pfmt = parg;
struct fimc_isp *isp = vb2_get_drv_priv(vq);
struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt;
const struct v4l2_pix_format_mplane *pixm = NULL;
@@ -194,10 +195,11 @@ static int isp_video_capture_buffer_prepare(struct vb2_buffer *vb)
static void isp_video_capture_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue);
struct fimc_is_video *video = &isp->video_capture;
struct fimc_is *is = fimc_isp_to_is(isp);
- struct isp_video_buf *ivb = to_isp_video_buf(vb);
+ struct isp_video_buf *ivb = to_isp_video_buf(vbuf);
unsigned long flags;
unsigned int i;
@@ -220,7 +222,7 @@ static void isp_video_capture_buffer_queue(struct vb2_buffer *vb)
isp_dbg(2, &video->ve.vdev,
"dma_buf %pad (%d/%d/%d) addr: %pad\n",
- &buf_index, ivb->index, i, vb->v4l2_buf.index,
+ &buf_index, ivb->index, i, vb->index,
&ivb->dma_addr[i]);
}
@@ -242,7 +244,7 @@ static void isp_video_capture_buffer_queue(struct vb2_buffer *vb)
void fimc_isp_video_irq_handler(struct fimc_is *is)
{
struct fimc_is_video *video = &is->isp.video_capture;
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
int buf_index;
/* TODO: Ensure the DMA is really stopped in stop_streaming callback */
@@ -250,10 +252,10 @@ void fimc_isp_video_irq_handler(struct fimc_is *is)
return;
buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count;
- vb = &video->buffers[buf_index]->vb;
+ vbuf = &video->buffers[buf_index]->vb;
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vbuf->timestamp);
+ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
video->buf_mask &= ~BIT(buf_index);
fimc_is_hw_set_isp_buf_mask(is, video->buf_mask);
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.h b/drivers/media/platform/exynos4-is/fimc-isp-video.h
index 98c662654bb6..f79a1b348aa6 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.h
@@ -11,7 +11,7 @@
#ifndef FIMC_ISP_VIDEO__
#define FIMC_ISP_VIDEO__
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "fimc-isp.h"
#ifdef CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
index b99be09b49fc..c2d25df85db9 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp.h
@@ -21,7 +21,7 @@
#include <linux/videodev2.h>
#include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
#include <media/exynos-fimc.h>
@@ -102,7 +102,7 @@ struct fimc_isp_ctrls {
};
struct isp_video_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
dma_addr_t dma_addr[FIMC_ISP_MAX_PLANES];
unsigned int index;
};
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index ca6261a86a5f..60660c3a5de0 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -28,7 +28,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/exynos-fimc.h>
@@ -200,7 +200,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
/* Release unused buffers */
while (!suspend && !list_empty(&fimc->pending_buf_q)) {
buf = fimc_lite_pending_queue_pop(fimc);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
/* If suspending put unused buffers onto pending queue */
while (!list_empty(&fimc->active_buf_q)) {
@@ -208,7 +208,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
if (suspend)
fimc_lite_pending_queue_add(fimc, buf);
else
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&fimc->slock, flags);
@@ -254,8 +254,6 @@ static irqreturn_t flite_irq_handler(int irq, void *priv)
struct fimc_lite *fimc = priv;
struct flite_buffer *vbuf;
unsigned long flags;
- struct timeval *tv;
- struct timespec ts;
u32 intsrc;
spin_lock_irqsave(&fimc->slock, flags);
@@ -294,13 +292,10 @@ static irqreturn_t flite_irq_handler(int irq, void *priv)
test_bit(ST_FLITE_RUN, &fimc->state) &&
!list_empty(&fimc->active_buf_q)) {
vbuf = fimc_lite_active_queue_pop(fimc);
- ktime_get_ts(&ts);
- tv = &vbuf->vb.v4l2_buf.timestamp;
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
- vbuf->vb.v4l2_buf.sequence = fimc->frame_count++;
+ v4l2_get_timestamp(&vbuf->vb.timestamp);
+ vbuf->vb.sequence = fimc->frame_count++;
flite_hw_mask_dma_buffer(fimc, vbuf->index);
- vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
if (test_bit(ST_FLITE_CONFIG, &fimc->state))
@@ -360,10 +355,11 @@ static void stop_streaming(struct vb2_queue *q)
fimc_lite_stop_capture(fimc, false);
}
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *allocators[])
{
+ const struct v4l2_format *pfmt = parg;
const struct v4l2_pix_format_mplane *pixm = NULL;
struct fimc_lite *fimc = vq->drv_priv;
struct flite_frame *frame = &fimc->out_frame;
@@ -422,8 +418,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct flite_buffer *buf
- = container_of(vb, struct flite_buffer, vb);
+ = container_of(vbuf, struct flite_buffer, vb);
struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue);
unsigned long flags;
@@ -1637,7 +1634,7 @@ static int fimc_lite_resume(struct device *dev)
if (list_empty(&fimc->pending_buf_q))
break;
buf = fimc_lite_pending_queue_pop(fimc);
- buffer_queue(&buf->vb);
+ buffer_queue(&buf->vb.vb2_buf);
}
return 0;
}
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
index ea19dc7be63e..b302305dedbe 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.h
+++ b/drivers/media/platform/exynos4-is/fimc-lite.h
@@ -19,7 +19,7 @@
#include <linux/videodev2.h>
#include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
@@ -100,7 +100,7 @@ struct flite_frame {
* @index: DMA start address register's index
*/
struct flite_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
dma_addr_t paddr;
unsigned short index;
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index d2bfe7c2a6b4..4d1d64a46b21 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "common.h"
@@ -42,7 +42,7 @@ static unsigned int get_m2m_fmt_flags(unsigned int stream_type)
void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
{
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
if (!ctx || !ctx->fh.m2m_ctx)
return;
@@ -99,7 +99,7 @@ static void stop_streaming(struct vb2_queue *q)
static void fimc_device_run(void *priv)
{
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
struct fimc_ctx *ctx = priv;
struct fimc_frame *sf, *df;
struct fimc_dev *fimc;
@@ -123,19 +123,19 @@ static void fimc_device_run(void *priv)
}
src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- ret = fimc_prepare_addr(ctx, src_vb, sf, &sf->paddr);
+ ret = fimc_prepare_addr(ctx, &src_vb->vb2_buf, sf, &sf->paddr);
if (ret)
goto dma_unlock;
dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- ret = fimc_prepare_addr(ctx, dst_vb, df, &df->paddr);
+ ret = fimc_prepare_addr(ctx, &dst_vb->vb2_buf, df, &df->paddr);
if (ret)
goto dma_unlock;
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
- dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.flags |=
- src_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->flags |=
+ src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
/* Reconfigure hardware if the context has changed. */
if (fimc->m2m.ctx != ctx) {
@@ -176,7 +176,7 @@ static void fimc_job_abort(void *priv)
fimc_m2m_shutdown(priv);
}
-static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int fimc_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *allocators[])
{
@@ -220,8 +220,9 @@ static int fimc_buf_prepare(struct vb2_buffer *vb)
static void fimc_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
static struct vb2_ops fimc_qops = {
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index d74e1bec3d86..4b85105dc159 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -706,7 +706,8 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
else
offset = S5PCSIS_PKTDATA_ODD;
- memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+ memcpy(pktbuf->data, (u8 __force *)state->regs + offset,
+ pktbuf->len);
pktbuf->data = NULL;
rmb();
}
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index c07f367aa436..29973f9bf8db 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -200,18 +200,18 @@ static void dma_callback(void *data)
{
struct deinterlace_ctx *curr_ctx = data;
struct deinterlace_dev *pcdev = curr_ctx->dev;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
atomic_set(&pcdev->busy, 0);
src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
- dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.flags |=
- src_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode;
+ dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->flags |=
+ src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->timecode = src_vb->timecode;
v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
@@ -225,7 +225,7 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
int do_callback)
{
struct deinterlace_q_data *s_q_data;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
struct deinterlace_dev *pcdev = ctx->dev;
struct dma_chan *chan = pcdev->dma_chan;
struct dma_device *dmadev = chan->device;
@@ -243,8 +243,9 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
s_height = s_q_data->height;
s_size = s_width * s_height;
- p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
- p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+ p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf,
+ 0);
if (!p_in || !p_out) {
v4l2_err(&pcdev->v4l2_dev,
"Acquiring kernel pointers to buffers failed\n");
@@ -797,7 +798,7 @@ struct vb2_dc_conf {
};
static int deinterlace_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -849,8 +850,10 @@ static int deinterlace_buf_prepare(struct vb2_buffer *vb)
static void deinterlace_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
}
static struct vb2_ops deinterlace_qops = {
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 5e2b4df48b3c..aa2b44041d3f 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -201,18 +201,18 @@ struct mcam_dma_desc {
/*
* Our buffer type for working with videobuf2. Note that the vb2
- * developers have decreed that struct vb2_buffer must be at the
+ * developers have decreed that struct vb2_v4l2_buffer must be at the
* beginning of this structure.
*/
struct mcam_vb_buffer {
- struct vb2_buffer vb_buf;
+ struct vb2_v4l2_buffer vb_buf;
struct list_head queue;
struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
dma_addr_t dma_desc_pa; /* Descriptor physical address */
int dma_desc_nent; /* Number of mapped descriptors */
};
-static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
+static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct mcam_vb_buffer, vb_buf);
}
@@ -221,14 +221,14 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
* Hand a completed buffer back to user space.
*/
static void mcam_buffer_done(struct mcam_camera *cam, int frame,
- struct vb2_buffer *vbuf)
+ struct vb2_v4l2_buffer *vbuf)
{
- vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
- vbuf->v4l2_buf.sequence = cam->buf_seq[frame];
- vbuf->v4l2_buf.field = V4L2_FIELD_NONE;
- v4l2_get_timestamp(&vbuf->v4l2_buf.timestamp);
- vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage);
- vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE);
+ vbuf->vb2_buf.planes[0].bytesused = cam->pix_format.sizeimage;
+ vbuf->sequence = cam->buf_seq[frame];
+ vbuf->field = V4L2_FIELD_NONE;
+ v4l2_get_timestamp(&vbuf->timestamp);
+ vb2_set_plane_payload(&vbuf->vb2_buf, 0, cam->pix_format.sizeimage);
+ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
}
@@ -482,7 +482,8 @@ static void mcam_frame_tasklet(unsigned long data)
* Drop the lock during the big copy. This *should* be safe...
*/
spin_unlock_irqrestore(&cam->dev_lock, flags);
- memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno],
+ memcpy(vb2_plane_vaddr(&buf->vb_buf.vb2_buf, 0),
+ cam->dma_bufs[bufno],
cam->pix_format.sizeimage);
mcam_buffer_done(cam, bufno, &buf->vb_buf);
spin_lock_irqsave(&cam->dev_lock, flags);
@@ -548,7 +549,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
{
struct mcam_vb_buffer *buf;
dma_addr_t dma_handle;
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vb;
/*
* If there are no available buffers, go into single mode
@@ -570,7 +571,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
cam->vb_bufs[frame] = buf;
vb = &buf->vb_buf;
- dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
+ dma_handle = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
mcam_write_yuv_bases(cam, frame, dma_handle);
}
@@ -1048,10 +1049,11 @@ static int mcam_read_setup(struct mcam_camera *cam)
*/
static int mcam_vb_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt, unsigned int *nbufs,
+ const void *parg, unsigned int *nbufs,
unsigned int *num_planes, unsigned int sizes[],
void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct mcam_camera *cam = vb2_get_drv_priv(vq);
int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
@@ -1071,7 +1073,8 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
static void mcam_vb_buf_queue(struct vb2_buffer *vb)
{
- struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
unsigned long flags;
int start;
@@ -1096,14 +1099,14 @@ static void mcam_vb_requeue_bufs(struct vb2_queue *vq,
spin_lock_irqsave(&cam->dev_lock, flags);
list_for_each_entry_safe(buf, node, &cam->buffers, queue) {
- vb2_buffer_done(&buf->vb_buf, state);
+ vb2_buffer_done(&buf->vb_buf.vb2_buf, state);
list_del(&buf->queue);
}
for (i = 0; i < MAX_DMA_BUFS; i++) {
buf = cam->vb_bufs[i];
if (buf) {
- vb2_buffer_done(&buf->vb_buf, state);
+ vb2_buffer_done(&buf->vb_buf.vb2_buf, state);
cam->vb_bufs[i] = NULL;
}
}
@@ -1198,7 +1201,8 @@ static const struct vb2_ops mcam_vb2_ops = {
*/
static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
{
- struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
@@ -1214,7 +1218,8 @@ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
{
- struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
struct mcam_dma_desc *desc = mvb->dma_desc;
struct scatterlist *sg;
@@ -1230,8 +1235,9 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
- struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+ struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
dma_free_coherent(cam->dev, ndesc * sizeof(struct mcam_dma_desc),
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 97167f6ffd1e..35cd9e5aedf8 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -10,7 +10,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
/*
* Create our own symbols for the supported buffer modes, but, for now,
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 87314b743f55..03a1b606655d 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -351,7 +351,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data)
{
struct emmaprp_dev *pcdev = data;
struct emmaprp_ctx *curr_ctx;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
unsigned long flags;
u32 irqst;
@@ -375,13 +375,13 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data)
src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
- dst_vb->v4l2_buf.flags &=
+ dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->flags &=
~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.flags |=
- src_vb->v4l2_buf.flags
+ dst_vb->flags |=
+ src_vb->flags
& V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode;
+ dst_vb->timecode = src_vb->timecode;
spin_lock_irqsave(&pcdev->irqlock, flags);
v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
@@ -689,7 +689,7 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
* Queue operations
*/
static int emmaprp_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -742,8 +742,9 @@ static int emmaprp_buf_prepare(struct vb2_buffer *vb)
static void emmaprp_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
}
static struct vb2_ops emmaprp_qops = {
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index 20434e83e801..94d4c295d3d0 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -235,7 +235,7 @@ static int isp_stat_buf_queue(struct ispstat *stat)
if (!stat->active_buf)
return STAT_NO_BUF;
- ktime_get_ts(&stat->active_buf->ts);
+ v4l2_get_timestamp(&stat->active_buf->ts);
stat->active_buf->buf_size = stat->buf_size;
if (isp_stat_buf_check_magic(stat, stat->active_buf)) {
@@ -496,8 +496,7 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,
return PTR_ERR(buf);
}
- data->ts.tv_sec = buf->ts.tv_sec;
- data->ts.tv_usec = buf->ts.tv_nsec / NSEC_PER_USEC;
+ data->ts = buf->ts;
data->config_counter = buf->config_counter;
data->frame_number = buf->frame_number;
data->buf_size = buf->buf_size;
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index b79380d83fcf..6d9b0244f320 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -39,7 +39,7 @@ struct ispstat_buffer {
struct sg_table sgt;
void *virt_addr;
dma_addr_t dma_addr;
- struct timespec ts;
+ struct timeval ts;
u32 buf_size;
u32 frame_number;
u16 config_counter;
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 41bb8df91f72..f4f591652432 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -320,7 +320,7 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
*/
static int isp_video_queue_setup(struct vb2_queue *queue,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *count, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -342,8 +342,9 @@ static int isp_video_queue_setup(struct vb2_queue *queue,
static int isp_video_buffer_prepare(struct vb2_buffer *buf)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf);
struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
- struct isp_buffer *buffer = to_isp_buffer(buf);
+ struct isp_buffer *buffer = to_isp_buffer(vbuf);
struct isp_video *video = vfh->video;
dma_addr_t addr;
@@ -363,7 +364,8 @@ static int isp_video_buffer_prepare(struct vb2_buffer *buf)
return -EINVAL;
}
- vb2_set_plane_payload(&buffer->vb, 0, vfh->format.fmt.pix.sizeimage);
+ vb2_set_plane_payload(&buffer->vb.vb2_buf, 0,
+ vfh->format.fmt.pix.sizeimage);
buffer->dma = addr;
return 0;
@@ -380,8 +382,9 @@ static int isp_video_buffer_prepare(struct vb2_buffer *buf)
*/
static void isp_video_buffer_queue(struct vb2_buffer *buf)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf);
struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
- struct isp_buffer *buffer = to_isp_buffer(buf);
+ struct isp_buffer *buffer = to_isp_buffer(vbuf);
struct isp_video *video = vfh->video;
struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
enum isp_pipeline_state state;
@@ -392,7 +395,7 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf)
spin_lock_irqsave(&video->irqlock, flags);
if (unlikely(video->error)) {
- vb2_buffer_done(&buffer->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&video->irqlock, flags);
return;
}
@@ -464,7 +467,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
list_del(&buf->irqlist);
spin_unlock_irqrestore(&video->irqlock, flags);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&buf->vb.timestamp);
/* Do frame number propagation only if this is the output video node.
* Frame number either comes from the CSI receivers or it gets
@@ -473,15 +476,15 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
* first, so the input number might lag behind by 1 in some cases.
*/
if (video == pipe->output && !pipe->do_propagation)
- buf->vb.v4l2_buf.sequence =
+ buf->vb.sequence =
atomic_inc_return(&pipe->frame_number);
else
- buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number);
+ buf->vb.sequence = atomic_read(&pipe->frame_number);
if (pipe->field != V4L2_FIELD_NONE)
- buf->vb.v4l2_buf.sequence /= 2;
+ buf->vb.sequence /= 2;
- buf->vb.v4l2_buf.field = pipe->field;
+ buf->vb.field = pipe->field;
/* Report pipeline errors to userspace on the capture device side. */
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
@@ -491,7 +494,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
state = VB2_BUF_STATE_DONE;
}
- vb2_buffer_done(&buf->vb, state);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
spin_lock_irqsave(&video->irqlock, flags);
@@ -546,7 +549,7 @@ void omap3isp_video_cancel_stream(struct isp_video *video)
buf = list_first_entry(&video->dmaqueue,
struct isp_buffer, irqlist);
list_del(&buf->irqlist);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
video->error = true;
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 4071dd7060ea..bcf0e0acc8f3 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -20,7 +20,7 @@
#include <media/media-entity.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#define ISP_VIDEO_DRIVER_NAME "ispvideo"
#define ISP_VIDEO_DRIVER_VERSION "0.0.2"
@@ -122,7 +122,7 @@ static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
* @dma: DMA address
*/
struct isp_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head irqlist;
dma_addr_t dma;
};
diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
index 2973f070d328..f8e3e83c52a2 100644
--- a/drivers/media/platform/rcar_jpu.c
+++ b/drivers/media/platform/rcar_jpu.c
@@ -37,7 +37,7 @@
#include <media/v4l2-fh.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
@@ -471,7 +471,7 @@ static const char *error_to_text[16] = {
"Unknown"
};
-static struct jpu_buffer *vb2_to_jpu_buffer(struct vb2_buffer *vb)
+static struct jpu_buffer *vb2_to_jpu_buffer(struct vb2_v4l2_buffer *vb)
{
struct v4l2_m2m_buffer *b =
container_of(vb, struct v4l2_m2m_buffer, vb);
@@ -1015,10 +1015,11 @@ error_free:
* ============================================================================
*/
static int jpu_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct jpu_ctx *ctx = vb2_get_drv_priv(vq);
struct jpu_q_data *q_data;
unsigned int i;
@@ -1044,6 +1045,7 @@ static int jpu_queue_setup(struct vb2_queue *vq,
static int jpu_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct jpu_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct jpu_q_data *q_data;
unsigned int i;
@@ -1051,9 +1053,9 @@ static int jpu_buf_prepare(struct vb2_buffer *vb)
q_data = jpu_get_q_data(ctx, vb->vb2_queue->type);
if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
- if (vb->v4l2_buf.field == V4L2_FIELD_ANY)
- vb->v4l2_buf.field = V4L2_FIELD_NONE;
- if (vb->v4l2_buf.field != V4L2_FIELD_NONE) {
+ if (vbuf->field == V4L2_FIELD_ANY)
+ vbuf->field = V4L2_FIELD_NONE;
+ if (vbuf->field != V4L2_FIELD_NONE) {
dev_err(ctx->jpu->dev, "%s field isn't supported\n",
__func__);
return -EINVAL;
@@ -1080,10 +1082,11 @@ static int jpu_buf_prepare(struct vb2_buffer *vb)
static void jpu_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct jpu_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
if (!ctx->encoder && V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
- struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vb);
+ struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vbuf);
struct jpu_q_data *q_data, adjust;
void *buffer = vb2_plane_vaddr(vb, 0);
unsigned long buf_size = vb2_get_plane_payload(vb, 0);
@@ -1117,7 +1120,7 @@ static void jpu_buf_queue(struct vb2_buffer *vb)
}
if (ctx->fh.m2m_ctx)
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
return;
@@ -1128,14 +1131,15 @@ format_error:
static void jpu_buf_finish(struct vb2_buffer *vb)
{
- struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vbuf);
struct jpu_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct jpu_q_data *q_data = &ctx->out_q;
enum v4l2_buf_type type = vb->vb2_queue->type;
u8 *buffer;
if (vb->state == VB2_BUF_STATE_DONE)
- vb->v4l2_buf.sequence = jpu_get_q_data(ctx, type)->sequence++;
+ vbuf->sequence = jpu_get_q_data(ctx, type)->sequence++;
if (!ctx->encoder || vb->state != VB2_BUF_STATE_DONE ||
V4L2_TYPE_IS_OUTPUT(type))
@@ -1144,9 +1148,9 @@ static void jpu_buf_finish(struct vb2_buffer *vb)
buffer = vb2_plane_vaddr(vb, 0);
memcpy(buffer, jpeg_hdrs[jpu_buf->compr_quality], JPU_JPEG_HDR_SIZE);
- *(u16 *)(buffer + JPU_JPEG_HEIGHT_OFFSET) =
+ *(__be16 *)(buffer + JPU_JPEG_HEIGHT_OFFSET) =
cpu_to_be16(q_data->format.height);
- *(u16 *)(buffer + JPU_JPEG_WIDTH_OFFSET) =
+ *(__be16 *)(buffer + JPU_JPEG_WIDTH_OFFSET) =
cpu_to_be16(q_data->format.width);
*(buffer + JPU_JPEG_SUBS_OFFSET) = q_data->fmtinfo->subsampling;
}
@@ -1163,7 +1167,7 @@ static int jpu_start_streaming(struct vb2_queue *vq, unsigned count)
static void jpu_stop_streaming(struct vb2_queue *vq)
{
struct jpu_ctx *ctx = vb2_get_drv_priv(vq);
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vb;
unsigned long flags;
for (;;) {
@@ -1327,7 +1331,7 @@ static const struct v4l2_file_operations jpu_fops = {
static void jpu_cleanup(struct jpu_ctx *ctx, bool reset)
{
/* remove current buffers and finish job */
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
unsigned long flags;
spin_lock_irqsave(&ctx->jpu->lock, flags);
@@ -1353,7 +1357,7 @@ static void jpu_device_run(void *priv)
struct jpu *jpu = ctx->jpu;
struct jpu_buffer *jpu_buf;
struct jpu_q_data *q_data;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
unsigned int w, h, bpl;
unsigned char num_planes, subsampling;
unsigned long flags;
@@ -1389,10 +1393,12 @@ static void jpu_device_run(void *priv)
unsigned long src_1_addr, src_2_addr, dst_addr;
unsigned int redu, inft;
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
- src_1_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+ src_1_addr =
+ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
if (num_planes > 1)
- src_2_addr = vb2_dma_contig_plane_dma_addr(src_buf, 1);
+ src_2_addr = vb2_dma_contig_plane_dma_addr(
+ &src_buf->vb2_buf, 1);
else
src_2_addr = src_1_addr + w * h;
@@ -1453,10 +1459,12 @@ static void jpu_device_run(void *priv)
return;
}
- src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
- dst_1_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ src_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+ dst_1_addr =
+ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
if (q_data->fmtinfo->num_planes > 1)
- dst_2_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+ dst_2_addr = vb2_dma_contig_plane_dma_addr(
+ &dst_buf->vb2_buf, 1);
else
dst_2_addr = dst_1_addr + w * h;
@@ -1511,7 +1519,7 @@ static irqreturn_t jpu_irq_handler(int irq, void *dev_id)
{
struct jpu *jpu = dev_id;
struct jpu_ctx *curr_ctx;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
unsigned int int_status;
int_status = jpu_read(jpu, JINTS);
@@ -1547,18 +1555,18 @@ static irqreturn_t jpu_irq_handler(int irq, void *dev_id)
unsigned long payload_size = jpu_read(jpu, JCDTCU) << 16
| jpu_read(jpu, JCDTCM) << 8
| jpu_read(jpu, JCDTCD);
- vb2_set_plane_payload(dst_buf, 0,
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
payload_size + JPU_JPEG_HDR_SIZE);
}
- dst_buf->v4l2_buf.field = src_buf->v4l2_buf.field;
- dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
- if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE)
- dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_buf->v4l2_buf.flags |= src_buf->v4l2_buf.flags &
+ dst_buf->field = src_buf->field;
+ dst_buf->timestamp = src_buf->timestamp;
+ if (src_buf->flags & V4L2_BUF_FLAG_TIMECODE)
+ dst_buf->timecode = src_buf->timecode;
+ dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_buf->flags |= src_buf->flags &
V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_buf->v4l2_buf.flags = src_buf->v4l2_buf.flags &
+ dst_buf->flags = src_buf->flags &
(V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME |
V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index 76e6289a5612..537b858cb94a 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -34,7 +34,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "camif-core.h"
@@ -164,12 +164,12 @@ static int camif_reinitialize(struct camif_vp *vp)
/* Release unused buffers */
while (!list_empty(&vp->pending_buf_q)) {
buf = camif_pending_queue_pop(vp);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
while (!list_empty(&vp->active_buf_q)) {
buf = camif_active_queue_pop(vp);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&camif->slock, flags);
@@ -328,25 +328,19 @@ irqreturn_t s3c_camif_irq_handler(int irq, void *priv)
!list_empty(&vp->active_buf_q)) {
unsigned int index;
struct camif_buffer *vbuf;
- struct timeval *tv;
- struct timespec ts;
/*
* Get previous DMA write buffer index:
* 0 => DMA buffer 0, 2;
* 1 => DMA buffer 1, 3.
*/
index = (CISTATUS_FRAMECNT(status) + 2) & 1;
-
- ktime_get_ts(&ts);
vbuf = camif_active_queue_peek(vp, index);
if (!WARN_ON(vbuf == NULL)) {
/* Dequeue a filled buffer */
- tv = &vbuf->vb.v4l2_buf.timestamp;
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
- vbuf->vb.v4l2_buf.sequence = vp->frame_sequence++;
- vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vbuf->vb.timestamp);
+ vbuf->vb.sequence = vp->frame_sequence++;
+ vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
/* Set up an empty buffer at the DMA engine */
vbuf = camif_pending_queue_pop(vp);
@@ -441,10 +435,11 @@ static void stop_streaming(struct vb2_queue *vq)
camif_stop_capture(vp);
}
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *allocators[])
{
+ const struct v4l2_format *pfmt = parg;
const struct v4l2_pix_format *pix = NULL;
struct camif_vp *vp = vb2_get_drv_priv(vq);
struct camif_dev *camif = vp->camif;
@@ -496,13 +491,14 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
- struct camif_buffer *buf = container_of(vb, struct camif_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct camif_buffer *buf = container_of(vbuf, struct camif_buffer, vb);
struct camif_vp *vp = vb2_get_drv_priv(vb->vb2_queue);
struct camif_dev *camif = vp->camif;
unsigned long flags;
spin_lock_irqsave(&camif->slock, flags);
- WARN_ON(camif_prepare_addr(vp, &buf->vb, &buf->paddr));
+ WARN_ON(camif_prepare_addr(vp, &buf->vb.vb2_buf, &buf->paddr));
if (!(vp->state & ST_VP_STREAMING) && vp->active_buffers < 2) {
/* Schedule an empty buffer in H/W */
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index f47b332f0418..1ba9bb08f5da 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -32,7 +32,7 @@
#include <media/media-device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "camif-core.h"
diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h
index 35d2fcdc0036..adaf1969ef63 100644
--- a/drivers/media/platform/s3c-camif/camif-core.h
+++ b/drivers/media/platform/s3c-camif/camif-core.h
@@ -25,7 +25,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/s3c_camif.h>
#define S3C_CAMIF_DRIVER_NAME "s3c-camif"
@@ -322,7 +322,7 @@ struct camif_addr {
* @index: an identifier of this buffer at the DMA engine
*/
struct camif_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
struct camif_addr paddr;
unsigned int index;
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 421a7c3b595b..e1936d9d27da 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -23,7 +23,7 @@
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "g2d.h"
@@ -101,7 +101,7 @@ static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
}
}
-static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int g2d_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -134,8 +134,9 @@ static int g2d_buf_prepare(struct vb2_buffer *vb)
static void g2d_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
static struct vb2_ops g2d_qops = {
@@ -537,7 +538,7 @@ static irqreturn_t g2d_isr(int irq, void *prv)
{
struct g2d_dev *dev = prv;
struct g2d_ctx *ctx = dev->curr;
- struct vb2_buffer *src, *dst;
+ struct vb2_v4l2_buffer *src, *dst;
g2d_clear_int(dev);
clk_disable(dev->gate);
@@ -550,11 +551,11 @@ static irqreturn_t g2d_isr(int irq, void *prv)
BUG_ON(src == NULL);
BUG_ON(dst == NULL);
- dst->v4l2_buf.timecode = src->v4l2_buf.timecode;
- dst->v4l2_buf.timestamp = src->v4l2_buf.timestamp;
- dst->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst->v4l2_buf.flags |=
- src->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst->timecode = src->timecode;
+ dst->timestamp = src->timestamp;
+ dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst->flags |=
+ src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 9690f9dcb0ca..4a608cbe0fdb 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -26,7 +26,7 @@
#include <linux/string.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "jpeg-core.h"
@@ -626,6 +626,7 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
return exynos3250_decoded_subsampling[ctx->subsampling];
case SJPEG_EXYNOS4:
+ case SJPEG_EXYNOS5433:
if (ctx->subsampling > 2)
return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
return exynos4x12_decoded_subsampling[ctx->subsampling];
@@ -750,6 +751,208 @@ static void exynos4_jpeg_set_huff_tbl(void __iomem *base)
ARRAY_SIZE(hactblg0));
}
+static inline int __exynos4_huff_tbl(int class, int id, bool lenval)
+{
+ /*
+ * class: 0 - DC, 1 - AC
+ * id: 0 - Y, 1 - Cb/Cr
+ */
+ if (class) {
+ if (id)
+ return lenval ? EXYNOS4_HUFF_TBL_HACCL :
+ EXYNOS4_HUFF_TBL_HACCV;
+ return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV;
+
+ }
+ /* class == 0 */
+ if (id)
+ return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV;
+
+ return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV;
+}
+
+static inline int exynos4_huff_tbl_len(int class, int id)
+{
+ return __exynos4_huff_tbl(class, id, true);
+}
+
+static inline int exynos4_huff_tbl_val(int class, int id)
+{
+ return __exynos4_huff_tbl(class, id, false);
+}
+
+static int get_byte(struct s5p_jpeg_buffer *buf);
+static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word);
+static void skip(struct s5p_jpeg_buffer *buf, long len);
+
+static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)
+{
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ struct s5p_jpeg_buffer jpeg_buffer;
+ unsigned int word;
+ int c, x, components;
+
+ jpeg_buffer.size = 2; /* Ls */
+ jpeg_buffer.data =
+ (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sos + 2;
+ jpeg_buffer.curr = 0;
+
+ word = 0;
+
+ if (get_word_be(&jpeg_buffer, &word))
+ return;
+ jpeg_buffer.size = (long)word - 2;
+ jpeg_buffer.data += 2;
+ jpeg_buffer.curr = 0;
+
+ components = get_byte(&jpeg_buffer);
+ if (components == -1)
+ return;
+ while (components--) {
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ x = get_byte(&jpeg_buffer);
+ if (x == -1)
+ return;
+ exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c,
+ (((x >> 4) & 0x1) << 1) | (x & 0x1));
+ }
+
+}
+
+static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx)
+{
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ struct s5p_jpeg_buffer jpeg_buffer;
+ unsigned int word;
+ int c, i, n, j;
+
+ for (j = 0; j < ctx->out_q.dht.n; ++j) {
+ jpeg_buffer.size = ctx->out_q.dht.len[j];
+ jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) +
+ ctx->out_q.dht.marker[j];
+ jpeg_buffer.curr = 0;
+
+ word = 0;
+ while (jpeg_buffer.curr < jpeg_buffer.size) {
+ char id, class;
+
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ id = c & 0xf;
+ class = (c >> 4) & 0xf;
+ n = 0;
+ for (i = 0; i < 16; ++i) {
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ word |= c << ((i % 4) * 8);
+ if ((i + 1) % 4 == 0) {
+ writel(word, jpeg->regs +
+ exynos4_huff_tbl_len(class, id) +
+ (i / 4) * 4);
+ word = 0;
+ }
+ n += c;
+ }
+ word = 0;
+ for (i = 0; i < n; ++i) {
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ word |= c << ((i % 4) * 8);
+ if ((i + 1) % 4 == 0) {
+ writel(word, jpeg->regs +
+ exynos4_huff_tbl_val(class, id) +
+ (i / 4) * 4);
+ word = 0;
+ }
+ }
+ if (i % 4) {
+ writel(word, jpeg->regs +
+ exynos4_huff_tbl_val(class, id) + (i / 4) * 4);
+ }
+ word = 0;
+ }
+ }
+}
+
+static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx)
+{
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ struct s5p_jpeg_buffer jpeg_buffer;
+ int c, x, components;
+
+ jpeg_buffer.size = ctx->out_q.sof_len;
+ jpeg_buffer.data =
+ (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sof;
+ jpeg_buffer.curr = 0;
+
+ skip(&jpeg_buffer, 5); /* P, Y, X */
+ components = get_byte(&jpeg_buffer);
+ if (components == -1)
+ return;
+
+ exynos4_jpeg_set_dec_components(jpeg->regs, components);
+
+ while (components--) {
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ skip(&jpeg_buffer, 1);
+ x = get_byte(&jpeg_buffer);
+ if (x == -1)
+ return;
+ exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x);
+ }
+}
+
+static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx)
+{
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ struct s5p_jpeg_buffer jpeg_buffer;
+ unsigned int word;
+ int c, i, j;
+
+ for (j = 0; j < ctx->out_q.dqt.n; ++j) {
+ jpeg_buffer.size = ctx->out_q.dqt.len[j];
+ jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) +
+ ctx->out_q.dqt.marker[j];
+ jpeg_buffer.curr = 0;
+
+ word = 0;
+ while (jpeg_buffer.size - jpeg_buffer.curr >= 65) {
+ char id;
+
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ id = c & 0xf;
+ /* nonzero means extended mode - not supported */
+ if ((c >> 4) & 0xf)
+ return;
+ for (i = 0; i < 64; ++i) {
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ return;
+ word |= c << ((i % 4) * 8);
+ if ((i + 1) % 4 == 0) {
+ writel(word, jpeg->regs +
+ EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4);
+ word = 0;
+ }
+ }
+ word = 0;
+ }
+ }
+}
+
/*
* ============================================================================
* Device file operations
@@ -894,8 +1097,11 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
unsigned long buffer, unsigned long size,
struct s5p_jpeg_ctx *ctx)
{
- int c, components = 0, notfound;
- unsigned int height, width, word, subsampling = 0;
+ int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
+ unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0,
+ sof_len = 0;
+ unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER],
+ dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
long length;
struct s5p_jpeg_buffer jpeg_buffer;
@@ -904,7 +1110,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
jpeg_buffer.curr = 0;
notfound = 1;
- while (notfound) {
+ while (notfound || !sos) {
c = get_byte(&jpeg_buffer);
if (c == -1)
return false;
@@ -923,6 +1129,11 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
case SOF0:
if (get_word_be(&jpeg_buffer, &word))
break;
+ length = (long)word - 2;
+ if (!length)
+ return false;
+ sof = jpeg_buffer.curr; /* after 0xffc0 */
+ sof_len = length;
if (get_byte(&jpeg_buffer) == -1)
break;
if (get_word_be(&jpeg_buffer, &height))
@@ -932,7 +1143,6 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
components = get_byte(&jpeg_buffer);
if (components == -1)
break;
- notfound = 0;
if (components == 1) {
subsampling = 0x33;
@@ -941,8 +1151,40 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
subsampling = get_byte(&jpeg_buffer);
skip(&jpeg_buffer, 1);
}
-
+ if (components > 3)
+ return false;
skip(&jpeg_buffer, components * 2);
+ notfound = 0;
+ break;
+
+ case DQT:
+ if (get_word_be(&jpeg_buffer, &word))
+ break;
+ length = (long)word - 2;
+ if (!length)
+ return false;
+ if (n_dqt >= S5P_JPEG_MAX_MARKER)
+ return false;
+ dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */
+ dqt_len[n_dqt++] = length;
+ skip(&jpeg_buffer, length);
+ break;
+
+ case DHT:
+ if (get_word_be(&jpeg_buffer, &word))
+ break;
+ length = (long)word - 2;
+ if (!length)
+ return false;
+ if (n_dht >= S5P_JPEG_MAX_MARKER)
+ return false;
+ dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */
+ dht_len[n_dht++] = length;
+ skip(&jpeg_buffer, length);
+ break;
+
+ case SOS:
+ sos = jpeg_buffer.curr - 2; /* 0xffda */
break;
/* skip payload-less markers */
@@ -963,7 +1205,20 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
}
result->w = width;
result->h = height;
- result->size = components;
+ result->sos = sos;
+ result->dht.n = n_dht;
+ while (n_dht--) {
+ result->dht.marker[n_dht] = dht[n_dht];
+ result->dht.len[n_dht] = dht_len[n_dht];
+ }
+ result->dqt.n = n_dqt;
+ while (n_dqt--) {
+ result->dqt.marker[n_dqt] = dqt[n_dqt];
+ result->dqt.len[n_dqt] = dqt_len[n_dqt];
+ }
+ result->sof = sof;
+ result->sof_len = sof_len;
+ result->size = result->components = components;
switch (subsampling) {
case 0x11:
@@ -982,7 +1237,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
return false;
}
- return !notfound;
+ return !notfound && sos;
}
static int s5p_jpeg_querycap(struct file *file, void *priv,
@@ -1226,8 +1481,7 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
}
- if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) ||
- (ctx->mode != S5P_JPEG_DECODE))
+ if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE)
goto exit;
/*
@@ -1350,7 +1604,7 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
* the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
* page fault calculate proper buffer size in such a case.
*/
- if (ct->jpeg->variant->version == SJPEG_EXYNOS4 &&
+ if (ct->jpeg->variant->hw_ex4_compat &&
f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
f,
@@ -1889,9 +2143,36 @@ static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (jpeg->variant->version == SJPEG_EXYNOS5433 &&
+ ctx->mode == S5P_JPEG_DECODE)
+ jpeg_addr += ctx->out_q.sos;
exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
}
+static inline void exynos4_jpeg_set_img_fmt(void __iomem *base,
+ unsigned int img_fmt)
+{
+ __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4);
+}
+
+static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base,
+ unsigned int img_fmt)
+{
+ __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433);
+}
+
+static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base,
+ unsigned int out_fmt)
+{
+ __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4);
+}
+
+static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base,
+ unsigned int out_fmt)
+{
+ __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433);
+}
+
static void exynos4_jpeg_device_run(void *priv)
{
struct s5p_jpeg_ctx *ctx = priv;
@@ -1899,11 +2180,11 @@ static void exynos4_jpeg_device_run(void *priv)
unsigned int bitstream_size;
unsigned long flags;
- spin_lock_irqsave(&ctx->jpeg->slock, flags);
+ spin_lock_irqsave(&jpeg->slock, flags);
if (ctx->mode == S5P_JPEG_ENCODE) {
exynos4_jpeg_sw_reset(jpeg->regs);
- exynos4_jpeg_set_interrupt(jpeg->regs);
+ exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version);
exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
exynos4_jpeg_set_huff_tbl(jpeg->regs);
@@ -1920,27 +2201,56 @@ static void exynos4_jpeg_device_run(void *priv)
exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
ctx->cap_q.h);
- exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling);
- exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc);
+ if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) {
+ exynos4_jpeg_set_enc_out_fmt(jpeg->regs,
+ ctx->subsampling);
+ exynos4_jpeg_set_img_fmt(jpeg->regs,
+ ctx->out_q.fmt->fourcc);
+ } else {
+ exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
+ ctx->subsampling);
+ exynos5433_jpeg_set_img_fmt(jpeg->regs,
+ ctx->out_q.fmt->fourcc);
+ }
exynos4_jpeg_set_img_addr(ctx);
exynos4_jpeg_set_jpeg_addr(ctx);
exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
ctx->out_q.fmt->fourcc);
} else {
exynos4_jpeg_sw_reset(jpeg->regs);
- exynos4_jpeg_set_interrupt(jpeg->regs);
+ exynos4_jpeg_set_interrupt(jpeg->regs,
+ jpeg->variant->version);
exynos4_jpeg_set_img_addr(ctx);
exynos4_jpeg_set_jpeg_addr(ctx);
- exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc);
- bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
+ if (jpeg->variant->version == SJPEG_EXYNOS5433) {
+ exynos4_jpeg_parse_huff_tbl(ctx);
+ exynos4_jpeg_parse_decode_h_tbl(ctx);
+
+ exynos4_jpeg_parse_q_tbl(ctx);
+ exynos4_jpeg_parse_decode_q_tbl(ctx);
+
+ exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
+
+ exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
+ ctx->cap_q.h);
+ exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
+ ctx->subsampling);
+ exynos5433_jpeg_set_img_fmt(jpeg->regs,
+ ctx->cap_q.fmt->fourcc);
+ bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16);
+ } else {
+ exynos4_jpeg_set_img_fmt(jpeg->regs,
+ ctx->cap_q.fmt->fourcc);
+ bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
+ }
exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
}
exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
- spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+ spin_unlock_irqrestore(&jpeg->slock, flags);
}
static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
@@ -2120,7 +2430,7 @@ static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
*/
static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -2170,6 +2480,7 @@ static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
if (ctx->mode == S5P_JPEG_DECODE &&
@@ -2187,13 +2498,24 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
q_data = &ctx->out_q;
q_data->w = tmp.w;
q_data->h = tmp.h;
+ q_data->sos = tmp.sos;
+ memcpy(q_data->dht.marker, tmp.dht.marker,
+ sizeof(tmp.dht.marker));
+ memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len));
+ q_data->dht.n = tmp.dht.n;
+ memcpy(q_data->dqt.marker, tmp.dqt.marker,
+ sizeof(tmp.dqt.marker));
+ memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len));
+ q_data->dqt.n = tmp.dqt.n;
+ q_data->sof = tmp.sof;
+ q_data->sof_len = tmp.sof_len;
q_data = &ctx->cap_q;
q_data->w = tmp.w;
q_data->h = tmp.h;
}
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
@@ -2264,7 +2586,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
{
struct s5p_jpeg *jpeg = dev_id;
struct s5p_jpeg_ctx *curr_ctx;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
unsigned long payload_size = 0;
enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
bool enc_jpeg_too_large = false;
@@ -2298,15 +2620,15 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
payload_size = s5p_jpeg_compressed_size(jpeg->regs);
}
- dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
- dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_buf->v4l2_buf.flags |=
- src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_buf->timecode = src_buf->timecode;
+ dst_buf->timestamp = src_buf->timestamp;
+ dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_buf->flags |=
+ src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
v4l2_m2m_buf_done(src_buf, state);
if (curr_ctx->mode == S5P_JPEG_ENCODE)
- vb2_set_plane_payload(dst_buf, 0, payload_size);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
v4l2_m2m_buf_done(dst_buf, state);
v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
@@ -2321,7 +2643,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
{
unsigned int int_status;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
struct s5p_jpeg *jpeg = priv;
struct s5p_jpeg_ctx *curr_ctx;
unsigned long payload_size = 0;
@@ -2363,7 +2685,8 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
if (jpeg->irq_ret == OK_ENC_OR_DEC) {
if (curr_ctx->mode == S5P_JPEG_ENCODE) {
payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
- vb2_set_plane_payload(dst_vb, 0, payload_size);
+ vb2_set_plane_payload(&dst_vb->vb2_buf,
+ 0, payload_size);
}
v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
@@ -2373,7 +2696,8 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
}
v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
- curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
+ if (jpeg->variant->version == SJPEG_EXYNOS4)
+ curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
spin_unlock(&jpeg->slock);
return IRQ_HANDLED;
@@ -2383,7 +2707,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
{
struct s5p_jpeg *jpeg = dev_id;
struct s5p_jpeg_ctx *curr_ctx;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
unsigned long payload_size = 0;
enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
bool interrupt_timeout = false;
@@ -2427,12 +2751,12 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
- dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
- dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
+ dst_buf->timecode = src_buf->timecode;
+ dst_buf->timestamp = src_buf->timestamp;
v4l2_m2m_buf_done(src_buf, state);
if (curr_ctx->mode == S5P_JPEG_ENCODE)
- vb2_set_plane_payload(dst_buf, 0, payload_size);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
v4l2_m2m_buf_done(dst_buf, state);
v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
@@ -2455,7 +2779,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
{
struct s5p_jpeg *jpeg;
struct resource *res;
- int ret;
+ int i, ret;
/* JPEG IP abstraction struct */
jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
@@ -2490,23 +2814,21 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
}
/* clocks */
- jpeg->clk = clk_get(&pdev->dev, "jpeg");
- if (IS_ERR(jpeg->clk)) {
- dev_err(&pdev->dev, "cannot get clock\n");
- ret = PTR_ERR(jpeg->clk);
- return ret;
+ for (i = 0; i < jpeg->variant->num_clocks; i++) {
+ jpeg->clocks[i] = devm_clk_get(&pdev->dev,
+ jpeg->variant->clk_names[i]);
+ if (IS_ERR(jpeg->clocks[i])) {
+ dev_err(&pdev->dev, "failed to get clock: %s\n",
+ jpeg->variant->clk_names[i]);
+ return PTR_ERR(jpeg->clocks[i]);
+ }
}
- dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
-
- jpeg->sclk = clk_get(&pdev->dev, "sclk");
- if (IS_ERR(jpeg->sclk))
- dev_info(&pdev->dev, "sclk clock not available\n");
/* v4l2 device */
ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to register v4l2 device\n");
- goto clk_get_rollback;
+ return ret;
}
/* mem2mem device */
@@ -2603,17 +2925,13 @@ m2m_init_rollback:
device_register_rollback:
v4l2_device_unregister(&jpeg->v4l2_dev);
-clk_get_rollback:
- clk_put(jpeg->clk);
- if (!IS_ERR(jpeg->sclk))
- clk_put(jpeg->sclk);
-
return ret;
}
static int s5p_jpeg_remove(struct platform_device *pdev)
{
struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
+ int i;
pm_runtime_disable(jpeg->dev);
@@ -2624,15 +2942,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
v4l2_device_unregister(&jpeg->v4l2_dev);
if (!pm_runtime_status_suspended(&pdev->dev)) {
- clk_disable_unprepare(jpeg->clk);
- if (!IS_ERR(jpeg->sclk))
- clk_disable_unprepare(jpeg->sclk);
+ for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
+ clk_disable_unprepare(jpeg->clocks[i]);
}
- clk_put(jpeg->clk);
- if (!IS_ERR(jpeg->sclk))
- clk_put(jpeg->sclk);
-
return 0;
}
@@ -2640,10 +2953,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
static int s5p_jpeg_runtime_suspend(struct device *dev)
{
struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
+ int i;
- clk_disable_unprepare(jpeg->clk);
- if (!IS_ERR(jpeg->sclk))
- clk_disable_unprepare(jpeg->sclk);
+ for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
+ clk_disable_unprepare(jpeg->clocks[i]);
return 0;
}
@@ -2652,16 +2965,15 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
{
struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
unsigned long flags;
- int ret;
+ int i, ret;
- ret = clk_prepare_enable(jpeg->clk);
- if (ret < 0)
- return ret;
-
- if (!IS_ERR(jpeg->sclk)) {
- ret = clk_prepare_enable(jpeg->sclk);
- if (ret < 0)
+ for (i = 0; i < jpeg->variant->num_clocks; i++) {
+ ret = clk_prepare_enable(jpeg->clocks[i]);
+ if (ret) {
+ while (--i > 0)
+ clk_disable_unprepare(jpeg->clocks[i]);
return ret;
+ }
}
spin_lock_irqsave(&jpeg->slock, flags);
@@ -2715,6 +3027,8 @@ static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
.jpeg_irq = s5p_jpeg_irq,
.m2m_ops = &s5p_jpeg_m2m_ops,
.fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
+ .clk_names = {"jpeg"},
+ .num_clocks = 1,
};
static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
@@ -2723,6 +3037,8 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
.m2m_ops = &exynos3250_jpeg_m2m_ops,
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
.hw3250_compat = 1,
+ .clk_names = {"jpeg", "sclk"},
+ .num_clocks = 2,
};
static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
@@ -2731,6 +3047,9 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
.m2m_ops = &exynos4_jpeg_m2m_ops,
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
.htbl_reinit = 1,
+ .clk_names = {"jpeg"},
+ .num_clocks = 1,
+ .hw_ex4_compat = 1,
};
static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
@@ -2740,6 +3059,19 @@ static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, /* intentionally 3250 */
.hw3250_compat = 1,
.htbl_reinit = 1,
+ .clk_names = {"jpeg"},
+ .num_clocks = 1,
+};
+
+static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = {
+ .version = SJPEG_EXYNOS5433,
+ .jpeg_irq = exynos4_jpeg_irq,
+ .m2m_ops = &exynos4_jpeg_m2m_ops,
+ .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
+ .htbl_reinit = 1,
+ .clk_names = {"pclk", "aclk", "aclk_xiu", "sclk"},
+ .num_clocks = 4,
+ .hw_ex4_compat = 1,
};
static const struct of_device_id samsung_jpeg_match[] = {
@@ -2758,6 +3090,9 @@ static const struct of_device_id samsung_jpeg_match[] = {
}, {
.compatible = "samsung,exynos5420-jpeg",
.data = &exynos5420_jpeg_drvdata,
+ }, {
+ .compatible = "samsung,exynos5433-jpeg",
+ .data = &exynos5433_jpeg_drvdata,
},
{},
};
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h
index 7d9a9ed19cea..9b1db0934909 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h
@@ -20,6 +20,8 @@
#define S5P_JPEG_M2M_NAME "s5p-jpeg"
+#define JPEG_MAX_CLOCKS 4
+
/* JPEG compression quality setting */
#define S5P_JPEG_COMPR_QUAL_BEST 0
#define S5P_JPEG_COMPR_QUAL_WORST 3
@@ -40,9 +42,12 @@
/* a selection of JPEG markers */
#define TEM 0x01
#define SOF0 0xc0
+#define DHT 0xc4
#define RST 0xd0
#define SOI 0xd8
#define EOI 0xd9
+#define SOS 0xda
+#define DQT 0xdb
#define DHP 0xde
/* Flags that indicate a format can be used for capture/output */
@@ -66,12 +71,15 @@
#define SJPEG_SUBSAMPLING_422 0x21
#define SJPEG_SUBSAMPLING_420 0x22
+#define S5P_JPEG_MAX_MARKER 4
+
/* Version numbers */
enum sjpeg_version {
SJPEG_S5P,
SJPEG_EXYNOS3250,
SJPEG_EXYNOS4,
SJPEG_EXYNOS5420,
+ SJPEG_EXYNOS5433,
};
enum exynos4_jpeg_result {
@@ -100,8 +108,7 @@ enum exynos4_jpeg_img_quality_level {
* @m2m_dev: v4l2 mem2mem device data
* @regs: JPEG IP registers mapping
* @irq: JPEG IP irq
- * @clk: JPEG IP clock
- * @sclk: Exynos3250 JPEG IP special clock
+ * @clocks: JPEG IP clock(s)
* @dev: JPEG IP struct device
* @alloc_ctx: videobuf2 memory allocator's context
* @variant: driver variant to be used
@@ -121,8 +128,7 @@ struct s5p_jpeg {
void __iomem *regs;
unsigned int irq;
enum exynos4_jpeg_result irq_ret;
- struct clk *clk;
- struct clk *sclk;
+ struct clk *clocks[JPEG_MAX_CLOCKS];
struct device *dev;
void *alloc_ctx;
struct s5p_jpeg_variant *variant;
@@ -134,8 +140,11 @@ struct s5p_jpeg_variant {
unsigned int fmt_ver_flag;
unsigned int hw3250_compat:1;
unsigned int htbl_reinit:1;
+ unsigned int hw_ex4_compat:1;
struct v4l2_m2m_ops *m2m_ops;
irqreturn_t (*jpeg_irq)(int irq, void *priv);
+ const char *clk_names[JPEG_MAX_CLOCKS];
+ int num_clocks;
};
/**
@@ -161,16 +170,40 @@ struct s5p_jpeg_fmt {
};
/**
+ * s5p_jpeg_marker - collection of markers from jpeg header
+ * @marker: markers' positions relative to the buffer beginning
+ * @len: markers' payload lengths (without length field)
+ * @n: number of markers in collection
+ */
+struct s5p_jpeg_marker {
+ u32 marker[S5P_JPEG_MAX_MARKER];
+ u32 len[S5P_JPEG_MAX_MARKER];
+ u32 n;
+};
+
+/**
* s5p_jpeg_q_data - parameters of one queue
* @fmt: driver-specific format of this queue
* @w: image width
* @h: image height
+ * @sos: SOS marker's position relative to the buffer beginning
+ * @dht: DHT markers' positions relative to the buffer beginning
+ * @dqt: DQT markers' positions relative to the buffer beginning
+ * @sof: SOF0 marker's postition relative to the buffer beginning
+ * @sof_len: SOF0 marker's payload length (without length field itself)
+ * @components: number of image components
* @size: image buffer size in bytes
*/
struct s5p_jpeg_q_data {
struct s5p_jpeg_fmt *fmt;
u32 w;
u32 h;
+ u32 sos;
+ struct s5p_jpeg_marker dht;
+ struct s5p_jpeg_marker dqt;
+ u32 sof;
+ u32 sof_len;
+ u32 components;
u32 size;
};
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c
index ab6d6f43c96f..0912d0a892e2 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c
@@ -45,9 +45,20 @@ void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode)
}
}
-void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt)
+void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
+ unsigned int version)
{
unsigned int reg;
+ unsigned int exynos4_swap_chroma_cbcr;
+ unsigned int exynos4_swap_chroma_crcb;
+
+ if (version == SJPEG_EXYNOS4) {
+ exynos4_swap_chroma_cbcr = EXYNOS4_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_crcb = EXYNOS4_SWAP_CHROMA_CRCB;
+ } else {
+ exynos4_swap_chroma_cbcr = EXYNOS5433_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_crcb = EXYNOS5433_SWAP_CHROMA_CRCB;
+ }
reg = readl(base + EXYNOS4_IMG_FMT_REG) &
EXYNOS4_ENC_IN_FMT_MASK; /* clear except enc format */
@@ -67,48 +78,48 @@ void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt)
case V4L2_PIX_FMT_NV24:
reg = reg | EXYNOS4_ENC_YUV_444_IMG |
EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
- EXYNOS4_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_NV42:
reg = reg | EXYNOS4_ENC_YUV_444_IMG |
EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
- EXYNOS4_SWAP_CHROMA_CRCB;
+ exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_YUYV:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
- EXYNOS4_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_YVYU:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
- EXYNOS4_SWAP_CHROMA_CRCB;
+ exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_NV16:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
- EXYNOS4_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_NV61:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
- EXYNOS4_SWAP_CHROMA_CRCB;
+ exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_NV12:
reg = reg | EXYNOS4_DEC_YUV_420_IMG |
EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
- EXYNOS4_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_NV21:
reg = reg | EXYNOS4_DEC_YUV_420_IMG |
EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
- EXYNOS4_SWAP_CHROMA_CRCB;
+ exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_YUV420:
reg = reg | EXYNOS4_DEC_YUV_420_IMG |
EXYNOS4_YUV_420_IP_YUV_420_3P_IMG |
- EXYNOS4_SWAP_CHROMA_CBCR;
+ exynos4_swap_chroma_cbcr;
break;
default:
break;
@@ -118,12 +129,14 @@ void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt)
writel(reg, base + EXYNOS4_IMG_FMT_REG);
}
-void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt)
+void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
+ unsigned int version)
{
unsigned int reg;
reg = readl(base + EXYNOS4_IMG_FMT_REG) &
- ~EXYNOS4_ENC_FMT_MASK; /* clear enc format */
+ ~(version == SJPEG_EXYNOS4 ? EXYNOS4_ENC_FMT_MASK :
+ EXYNOS5433_ENC_FMT_MASK); /* clear enc format */
switch (out_fmt) {
case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
@@ -149,9 +162,18 @@ void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt)
writel(reg, base + EXYNOS4_IMG_FMT_REG);
}
-void exynos4_jpeg_set_interrupt(void __iomem *base)
+void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version)
{
- writel(EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
+ unsigned int reg;
+
+ if (version == SJPEG_EXYNOS4) {
+ reg = readl(base + EXYNOS4_INT_EN_REG) & ~EXYNOS4_INT_EN_MASK;
+ writel(reg | EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
+ } else {
+ reg = readl(base + EXYNOS4_INT_EN_REG) &
+ ~EXYNOS5433_INT_EN_MASK;
+ writel(reg | EXYNOS5433_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
+ }
}
unsigned int exynos4_jpeg_get_int_status(void __iomem *base)
@@ -234,6 +256,36 @@ void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
writel(reg, base + EXYNOS4_TBL_SEL_REG);
}
+void exynos4_jpeg_set_dec_components(void __iomem *base, int n)
+{
+ unsigned int reg;
+
+ reg = readl(base + EXYNOS4_TBL_SEL_REG);
+
+ reg |= EXYNOS4_NF(n);
+ writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
+void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x)
+{
+ unsigned int reg;
+
+ reg = readl(base + EXYNOS4_TBL_SEL_REG);
+
+ reg |= EXYNOS4_Q_TBL_COMP(c, x);
+ writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
+void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x)
+{
+ unsigned int reg;
+
+ reg = readl(base + EXYNOS4_TBL_SEL_REG);
+
+ reg |= EXYNOS4_HUFF_TBL_COMP(c, x);
+ writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt)
{
if (fmt == V4L2_PIX_FMT_GREY)
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h
index c228d28a4bc7..cf6ec055d63a 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h
@@ -15,10 +15,12 @@
void exynos4_jpeg_sw_reset(void __iomem *base);
void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode);
-void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt);
-void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt);
+void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
+ unsigned int version);
+void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
+ unsigned int version);
void exynos4_jpeg_set_enc_tbl(void __iomem *base);
-void exynos4_jpeg_set_interrupt(void __iomem *base);
+void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version);
unsigned int exynos4_jpeg_get_int_status(void __iomem *base);
void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value);
void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value);
@@ -30,6 +32,9 @@ void exynos4_jpeg_set_frame_buf_address(void __iomem *base,
struct s5p_jpeg_addr *jpeg_addr);
void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
enum exynos4_jpeg_img_quality_level level);
+void exynos4_jpeg_set_dec_components(void __iomem *base, int n);
+void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x);
+void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x);
void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt);
void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size);
unsigned int exynos4_jpeg_get_stream_size(void __iomem *base);
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
index 050fc440248f..1870400468b2 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-regs.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
@@ -231,12 +231,14 @@
/* JPEG INT Register bit */
#define EXYNOS4_INT_EN_MASK (0x1f << 0)
+#define EXYNOS5433_INT_EN_MASK (0x1ff << 0)
#define EXYNOS4_PROT_ERR_INT_EN (1 << 0)
#define EXYNOS4_IMG_COMPLETION_INT_EN (1 << 1)
#define EXYNOS4_DEC_INVALID_FORMAT_EN (1 << 2)
#define EXYNOS4_MULTI_SCAN_ERROR_EN (1 << 3)
#define EXYNOS4_FRAME_ERR_EN (1 << 4)
#define EXYNOS4_INT_EN_ALL (0x1f << 0)
+#define EXYNOS5433_INT_EN_ALL (0x1b6 << 0)
#define EXYNOS4_MOD_REG_PROC_ENC (0 << 3)
#define EXYNOS4_MOD_REG_PROC_DEC (1 << 3)
@@ -296,6 +298,8 @@
#define EXYNOS4_ENC_FMT_SHIFT 24
#define EXYNOS4_ENC_FMT_MASK (3 << EXYNOS4_ENC_FMT_SHIFT)
+#define EXYNOS5433_ENC_FMT_MASK (7 << EXYNOS4_ENC_FMT_SHIFT)
+
#define EXYNOS4_ENC_FMT_GRAY (0 << EXYNOS4_ENC_FMT_SHIFT)
#define EXYNOS4_ENC_FMT_YUV_444 (1 << EXYNOS4_ENC_FMT_SHIFT)
#define EXYNOS4_ENC_FMT_YUV_422 (2 << EXYNOS4_ENC_FMT_SHIFT)
@@ -305,6 +309,8 @@
#define EXYNOS4_SWAP_CHROMA_CRCB (1 << 26)
#define EXYNOS4_SWAP_CHROMA_CBCR (0 << 26)
+#define EXYNOS5433_SWAP_CHROMA_CRCB (1 << 27)
+#define EXYNOS5433_SWAP_CHROMA_CBCR (0 << 27)
/* JPEG HUFF count Register bit */
#define EXYNOS4_HUFF_COUNT_MASK 0xffff
@@ -316,35 +322,56 @@
#define EXYNOS4_DECODED_IMG_FMT_MASK 0x3
/* JPEG TBL SEL Register bit */
-#define EXYNOS4_Q_TBL_COMP1_0 (0 << 0)
-#define EXYNOS4_Q_TBL_COMP1_1 (1 << 0)
-#define EXYNOS4_Q_TBL_COMP1_2 (2 << 0)
-#define EXYNOS4_Q_TBL_COMP1_3 (3 << 0)
-
-#define EXYNOS4_Q_TBL_COMP2_0 (0 << 2)
-#define EXYNOS4_Q_TBL_COMP2_1 (1 << 2)
-#define EXYNOS4_Q_TBL_COMP2_2 (2 << 2)
-#define EXYNOS4_Q_TBL_COMP2_3 (3 << 2)
-
-#define EXYNOS4_Q_TBL_COMP3_0 (0 << 4)
-#define EXYNOS4_Q_TBL_COMP3_1 (1 << 4)
-#define EXYNOS4_Q_TBL_COMP3_2 (2 << 4)
-#define EXYNOS4_Q_TBL_COMP3_3 (3 << 4)
-
-#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 (0 << 6)
-#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 (1 << 6)
-#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 (2 << 6)
-#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 (3 << 6)
-
-#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 (0 << 8)
-#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 (1 << 8)
-#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 (2 << 8)
-#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 (3 << 8)
-
-#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 (0 << 10)
-#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 (1 << 10)
-#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 (2 << 10)
-#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 (3 << 10)
+#define EXYNOS4_Q_TBL_COMP(c, n) ((n) << (((c) - 1) << 1))
+
+#define EXYNOS4_Q_TBL_COMP1_0 EXYNOS4_Q_TBL_COMP(1, 0)
+#define EXYNOS4_Q_TBL_COMP1_1 EXYNOS4_Q_TBL_COMP(1, 1)
+#define EXYNOS4_Q_TBL_COMP1_2 EXYNOS4_Q_TBL_COMP(1, 2)
+#define EXYNOS4_Q_TBL_COMP1_3 EXYNOS4_Q_TBL_COMP(1, 3)
+
+#define EXYNOS4_Q_TBL_COMP2_0 EXYNOS4_Q_TBL_COMP(2, 0)
+#define EXYNOS4_Q_TBL_COMP2_1 EXYNOS4_Q_TBL_COMP(2, 1)
+#define EXYNOS4_Q_TBL_COMP2_2 EXYNOS4_Q_TBL_COMP(2, 2)
+#define EXYNOS4_Q_TBL_COMP2_3 EXYNOS4_Q_TBL_COMP(2, 3)
+
+#define EXYNOS4_Q_TBL_COMP3_0 EXYNOS4_Q_TBL_COMP(3, 0)
+#define EXYNOS4_Q_TBL_COMP3_1 EXYNOS4_Q_TBL_COMP(3, 1)
+#define EXYNOS4_Q_TBL_COMP3_2 EXYNOS4_Q_TBL_COMP(3, 2)
+#define EXYNOS4_Q_TBL_COMP3_3 EXYNOS4_Q_TBL_COMP(3, 3)
+
+#define EXYNOS4_HUFF_TBL_COMP(c, n) ((n) << ((((c) - 1) << 1) + 6))
+
+#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 \
+ EXYNOS4_HUFF_TBL_COMP(1, 0)
+#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 \
+ EXYNOS4_HUFF_TBL_COMP(1, 1)
+#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 \
+ EXYNOS4_HUFF_TBL_COMP(1, 2)
+#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 \
+ EXYNOS4_HUFF_TBL_COMP(1, 3)
+
+#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 \
+ EXYNOS4_HUFF_TBL_COMP(2, 0)
+#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 \
+ EXYNOS4_HUFF_TBL_COMP(2, 1)
+#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 \
+ EXYNOS4_HUFF_TBL_COMP(2, 2)
+#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 \
+ EXYNOS4_HUFF_TBL_COMP(2, 3)
+
+#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 \
+ EXYNOS4_HUFF_TBL_COMP(3, 0)
+#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 \
+ EXYNOS4_HUFF_TBL_COMP(3, 1)
+#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 \
+ EXYNOS4_HUFF_TBL_COMP(3, 2)
+#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 \
+ EXYNOS4_HUFF_TBL_COMP(3, 3)
+
+#define EXYNOS4_NF_SHIFT 16
+#define EXYNOS4_NF_MASK 0xff
+#define EXYNOS4_NF(x) \
+ (((x) << EXYNOS4_NF_SHIFT) & EXYNOS4_NF_MASK)
/* JPEG quantizer table register */
#define EXYNOS4_QTBL_CONTENT(n) (0x100 + (n) * 0x40)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 8de61dc1e142..3ffe2ecfd5ef 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,7 +22,7 @@
#include <media/v4l2-event.h>
#include <linux/workqueue.h>
#include <linux/of.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "s5p_mfc_common.h"
#include "s5p_mfc_ctrl.h"
#include "s5p_mfc_debug.h"
@@ -181,13 +181,6 @@ unlock:
mutex_unlock(&dev->mfc_mutex);
}
-static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
-{
- mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
- mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
- mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
-}
-
static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_buf *dst_buf;
@@ -199,22 +192,23 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
dst_buf = list_entry(ctx->dst_queue.next,
struct s5p_mfc_buf, list);
mfc_debug(2, "Cleaning up buffer: %d\n",
- dst_buf->b->v4l2_buf.index);
- vb2_set_plane_payload(dst_buf->b, 0, 0);
- vb2_set_plane_payload(dst_buf->b, 1, 0);
+ dst_buf->b->vb2_buf.index);
+ vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, 0);
+ vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, 0);
list_del(&dst_buf->list);
+ dst_buf->flags |= MFC_BUF_FLAG_EOS;
ctx->dst_queue_cnt--;
- dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
+ dst_buf->b->sequence = (ctx->sequence++);
if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
- dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
+ dst_buf->b->field = V4L2_FIELD_NONE;
else
- dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
- dst_buf->b->v4l2_buf.flags |= V4L2_BUF_FLAG_LAST;
+ dst_buf->b->field = V4L2_FIELD_INTERLACED;
+ dst_buf->b->flags |= V4L2_BUF_FLAG_LAST;
- ctx->dec_dst_flag &= ~(1 << dst_buf->b->v4l2_buf.index);
- vb2_buffer_done(dst_buf->b, VB2_BUF_STATE_DONE);
+ ctx->dec_dst_flag &= ~(1 << dst_buf->b->vb2_buf.index);
+ vb2_buffer_done(&dst_buf->b->vb2_buf, VB2_BUF_STATE_DONE);
}
}
@@ -235,27 +229,28 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
appropriate flags. */
src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
- if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
- dst_buf->b->v4l2_buf.timecode =
- src_buf->b->v4l2_buf.timecode;
- dst_buf->b->v4l2_buf.timestamp =
- src_buf->b->v4l2_buf.timestamp;
- dst_buf->b->v4l2_buf.flags &=
+ if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0)
+ == dec_y_addr) {
+ dst_buf->b->timecode =
+ src_buf->b->timecode;
+ dst_buf->b->timestamp =
+ src_buf->b->timestamp;
+ dst_buf->b->flags &=
~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_buf->b->v4l2_buf.flags |=
- src_buf->b->v4l2_buf.flags
+ dst_buf->b->flags |=
+ src_buf->b->flags
& V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
switch (frame_type) {
case S5P_FIMV_DECODE_FRAME_I_FRAME:
- dst_buf->b->v4l2_buf.flags |=
+ dst_buf->b->flags |=
V4L2_BUF_FLAG_KEYFRAME;
break;
case S5P_FIMV_DECODE_FRAME_P_FRAME:
- dst_buf->b->v4l2_buf.flags |=
+ dst_buf->b->flags |=
V4L2_BUF_FLAG_PFRAME;
break;
case S5P_FIMV_DECODE_FRAME_B_FRAME:
- dst_buf->b->v4l2_buf.flags |=
+ dst_buf->b->flags |=
V4L2_BUF_FLAG_BFRAME;
break;
default:
@@ -296,25 +291,28 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
* check which videobuf does it correspond to */
list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
/* Check if this is the buffer we're looking for */
- if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dspl_y_addr) {
+ if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0)
+ == dspl_y_addr) {
list_del(&dst_buf->list);
ctx->dst_queue_cnt--;
- dst_buf->b->v4l2_buf.sequence = ctx->sequence;
+ dst_buf->b->sequence = ctx->sequence;
if (s5p_mfc_hw_call(dev->mfc_ops,
get_pic_type_top, ctx) ==
s5p_mfc_hw_call(dev->mfc_ops,
get_pic_type_bot, ctx))
- dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
+ dst_buf->b->field = V4L2_FIELD_NONE;
else
- dst_buf->b->v4l2_buf.field =
+ dst_buf->b->field =
V4L2_FIELD_INTERLACED;
- vb2_set_plane_payload(dst_buf->b, 0, ctx->luma_size);
- vb2_set_plane_payload(dst_buf->b, 1, ctx->chroma_size);
- clear_bit(dst_buf->b->v4l2_buf.index,
+ vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0,
+ ctx->luma_size);
+ vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1,
+ ctx->chroma_size);
+ clear_bit(dst_buf->b->vb2_buf.index,
&ctx->dec_dst_flag);
- vb2_buffer_done(dst_buf->b,
- err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&dst_buf->b->vb2_buf, err ?
+ VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
break;
}
@@ -395,7 +393,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC &&
ctx->consumed_stream + STUFF_BYTE <
- src_buf->b->v4l2_planes[0].bytesused) {
+ src_buf->b->vb2_buf.planes[0].bytesused) {
/* Run MFC again on the same buffer */
mfc_debug(2, "Running again the same buffer\n");
ctx->after_packed_pb = 1;
@@ -407,9 +405,11 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
list_del(&src_buf->list);
ctx->src_queue_cnt--;
if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
- vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&src_buf->b->vb2_buf,
+ VB2_BUF_STATE_ERROR);
else
- vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&src_buf->b->vb2_buf,
+ VB2_BUF_STATE_DONE);
}
}
leave_handle_frame:
@@ -510,7 +510,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
struct s5p_mfc_buf, list);
if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
dev) <
- src_buf->b->v4l2_planes[0].bytesused)
+ src_buf->b->vb2_buf.planes[0].bytesused)
ctx->head_processed = 0;
else
ctx->head_processed = 1;
@@ -551,7 +551,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
struct s5p_mfc_buf, list);
list_del(&src_buf->list);
ctx->src_queue_cnt--;
- vb2_buffer_done(src_buf->b,
+ vb2_buffer_done(&src_buf->b->vb2_buf,
VB2_BUF_STATE_DONE);
}
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -573,17 +573,13 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
}
}
-static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
- unsigned int reason, unsigned int err)
+static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_buf *mb_entry;
mfc_debug(2, "Stream completed\n");
- s5p_mfc_clear_int_flags(dev);
- ctx->int_type = reason;
- ctx->int_err = err;
ctx->state = MFCINST_FINISHED;
spin_lock(&dev->irqlock);
@@ -592,8 +588,8 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
list);
list_del(&mb_entry->list);
ctx->dst_queue_cnt--;
- vb2_set_plane_payload(mb_entry->b, 0, 0);
- vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, 0);
+ vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
}
spin_unlock(&dev->irqlock);
@@ -640,6 +636,13 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
if (ctx->c_ops->post_frame_start) {
if (ctx->c_ops->post_frame_start(ctx))
mfc_err("post_frame_start() failed\n");
+
+ if (ctx->state == MFCINST_FINISHING &&
+ list_empty(&ctx->ref_queue)) {
+ s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
+ s5p_mfc_handle_stream_complete(ctx);
+ break;
+ }
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
@@ -685,7 +688,10 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
break;
case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
- s5p_mfc_handle_stream_complete(ctx, reason, err);
+ s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
+ ctx->int_type = reason;
+ ctx->int_err = err;
+ s5p_mfc_handle_stream_complete(ctx);
break;
case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 24262bbb1a35..d1a3f9b1bc44 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -21,7 +21,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "regs-mfc.h"
#include "regs-mfc-v8.h"
@@ -179,8 +179,8 @@ struct s5p_mfc_ctx;
* struct s5p_mfc_buf - MFC buffer
*/
struct s5p_mfc_buf {
+ struct vb2_v4l2_buffer *b;
struct list_head list;
- struct vb2_buffer *b;
union {
struct {
size_t luma;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index aebe4fd7f03a..8c5060a7534f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -22,7 +22,7 @@
#include <linux/workqueue.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "s5p_mfc_common.h"
#include "s5p_mfc_ctrl.h"
#include "s5p_mfc_debug.h"
@@ -645,17 +645,22 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
mfc_err("Call on DQBUF after unrecoverable error\n");
return -EIO;
}
- if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
- else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+
+ switch (buf->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
- if (ret == 0 && ctx->state == MFCINST_FINISHED &&
- list_empty(&ctx->vq_dst.done_list))
+ if (ret)
+ return ret;
+
+ if (ctx->state == MFCINST_FINISHED &&
+ (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS))
v4l2_event_queue_fh(&ctx->fh, &ev);
- } else {
- ret = -EINVAL;
+ return 0;
+ default:
+ return -EINVAL;
}
- return ret;
}
/* Export DMA buffer */
@@ -883,7 +888,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
};
static int s5p_mfc_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt, unsigned int *buf_count,
+ const void *parg, unsigned int *buf_count,
unsigned int *plane_count, unsigned int psize[],
void *allocators[])
{
@@ -945,6 +950,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
static int s5p_mfc_buf_init(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
unsigned int i;
@@ -964,8 +970,8 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
mfc_err("Plane buffer (CAPTURE) is too small\n");
return -EINVAL;
}
- i = vb->v4l2_buf.index;
- ctx->dst_bufs[i].b = vb;
+ i = vb->index;
+ ctx->dst_bufs[i].b = vbuf;
ctx->dst_bufs[i].cookie.raw.luma =
vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->dst_bufs[i].cookie.raw.chroma =
@@ -982,8 +988,8 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
return -EINVAL;
}
- i = vb->v4l2_buf.index;
- ctx->src_bufs[i].b = vb;
+ i = vb->index;
+ ctx->src_bufs[i].b = vbuf;
ctx->src_bufs[i].cookie.stream =
vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->src_bufs_cnt++;
@@ -1065,18 +1071,18 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
struct s5p_mfc_buf *mfc_buf;
if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
+ mfc_buf = &ctx->src_bufs[vb->index];
mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
spin_lock_irqsave(&dev->irqlock, flags);
list_add_tail(&mfc_buf->list, &ctx->src_queue);
ctx->src_queue_cnt++;
spin_unlock_irqrestore(&dev->irqlock, flags);
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
+ mfc_buf = &ctx->dst_bufs[vb->index];
mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
/* Mark destination as available for use by MFC */
spin_lock_irqsave(&dev->irqlock, flags);
- set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag);
+ set_bit(vb->index, &ctx->dec_dst_flag);
list_add_tail(&mfc_buf->list, &ctx->dst_queue);
ctx->dst_queue_cnt++;
spin_unlock_irqrestore(&dev->irqlock, flags);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 2e57e9f45b85..5c678ec9c9f2 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -23,7 +23,7 @@
#include <media/v4l2-event.h>
#include <linux/workqueue.h>
#include <media/v4l2-ctrls.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "s5p_mfc_common.h"
#include "s5p_mfc_ctrl.h"
#include "s5p_mfc_debug.h"
@@ -773,8 +773,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+ dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
s5p_mfc_hw_call_void(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -796,10 +796,11 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
struct s5p_mfc_buf, list);
list_del(&dst_mb->list);
ctx->dst_queue_cnt--;
- vb2_set_plane_payload(dst_mb->b, 0,
+ vb2_set_plane_payload(&dst_mb->b->vb2_buf, 0,
s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size,
dev));
- vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&dst_mb->b->vb2_buf,
+ VB2_BUF_STATE_DONE);
}
spin_unlock_irqrestore(&dev->irqlock, flags);
}
@@ -831,16 +832,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
- src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+ src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
s5p_mfc_hw_call_void(dev->mfc_ops, set_enc_frame_buffer, ctx,
src_y_addr, src_c_addr);
spin_unlock_irqrestore(&dev->irqlock, flags);
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+ dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
s5p_mfc_hw_call_void(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -869,25 +870,29 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
s5p_mfc_hw_call_void(dev->mfc_ops, get_enc_frame_buffer, ctx,
&enc_y_addr, &enc_c_addr);
list_for_each_entry(mb_entry, &ctx->src_queue, list) {
- mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
- mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
+ mb_y_addr = vb2_dma_contig_plane_dma_addr(
+ &mb_entry->b->vb2_buf, 0);
+ mb_c_addr = vb2_dma_contig_plane_dma_addr(
+ &mb_entry->b->vb2_buf, 1);
if ((enc_y_addr == mb_y_addr) &&
(enc_c_addr == mb_c_addr)) {
list_del(&mb_entry->list);
ctx->src_queue_cnt--;
- vb2_buffer_done(mb_entry->b,
+ vb2_buffer_done(&mb_entry->b->vb2_buf,
VB2_BUF_STATE_DONE);
break;
}
}
list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
- mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
- mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
+ mb_y_addr = vb2_dma_contig_plane_dma_addr(
+ &mb_entry->b->vb2_buf, 0);
+ mb_c_addr = vb2_dma_contig_plane_dma_addr(
+ &mb_entry->b->vb2_buf, 1);
if ((enc_y_addr == mb_y_addr) &&
(enc_c_addr == mb_c_addr)) {
list_del(&mb_entry->list);
ctx->ref_queue_cnt--;
- vb2_buffer_done(mb_entry->b,
+ vb2_buffer_done(&mb_entry->b->vb2_buf,
VB2_BUF_STATE_DONE);
break;
}
@@ -902,9 +907,9 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
list_add_tail(&mb_entry->list, &ctx->ref_queue);
ctx->ref_queue_cnt++;
}
- mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
- ctx->src_queue_cnt, ctx->ref_queue_cnt);
}
+ mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
+ ctx->src_queue_cnt, ctx->ref_queue_cnt);
if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) {
mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
list);
@@ -912,21 +917,22 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
ctx->dst_queue_cnt--;
switch (slice_type) {
case S5P_FIMV_ENC_SI_SLICE_TYPE_I:
- mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ mb_entry->b->flags |= V4L2_BUF_FLAG_KEYFRAME;
break;
case S5P_FIMV_ENC_SI_SLICE_TYPE_P:
- mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+ mb_entry->b->flags |= V4L2_BUF_FLAG_PFRAME;
break;
case S5P_FIMV_ENC_SI_SLICE_TYPE_B:
- mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_BFRAME;
+ mb_entry->b->flags |= V4L2_BUF_FLAG_BFRAME;
break;
}
- vb2_set_plane_payload(mb_entry->b, 0, strm_size);
- vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, strm_size);
+ vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
}
spin_unlock_irqrestore(&dev->irqlock, flags);
if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0))
clear_work_bit(ctx);
+
return 0;
}
@@ -1806,13 +1812,13 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
return -EINVAL;
}
mfc_debug(2, "index: %d, plane[%d] cookie: %pad\n",
- vb->v4l2_buf.index, i, &dma);
+ vb->index, i, &dma);
}
return 0;
}
static int s5p_mfc_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *buf_count, unsigned int *plane_count,
unsigned int psize[], void *allocators[])
{
@@ -1821,7 +1827,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
if (ctx->state != MFCINST_GOT_INST) {
- mfc_err("inavlid state: %d\n", ctx->state);
+ mfc_err("invalid state: %d\n", ctx->state);
return -EINVAL;
}
@@ -1861,7 +1867,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
}
} else {
- mfc_err("inavlid queue type: %d\n", vq->type);
+ mfc_err("invalid queue type: %d\n", vq->type);
return -EINVAL;
}
return 0;
@@ -1869,6 +1875,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
static int s5p_mfc_buf_init(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
unsigned int i;
@@ -1878,8 +1885,8 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
ret = check_vb_with_fmt(ctx->dst_fmt, vb);
if (ret < 0)
return ret;
- i = vb->v4l2_buf.index;
- ctx->dst_bufs[i].b = vb;
+ i = vb->index;
+ ctx->dst_bufs[i].b = vbuf;
ctx->dst_bufs[i].cookie.stream =
vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->dst_bufs_cnt++;
@@ -1887,15 +1894,15 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
ret = check_vb_with_fmt(ctx->src_fmt, vb);
if (ret < 0)
return ret;
- i = vb->v4l2_buf.index;
- ctx->src_bufs[i].b = vb;
+ i = vb->index;
+ ctx->src_bufs[i].b = vbuf;
ctx->src_bufs[i].cookie.raw.luma =
vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->src_bufs[i].cookie.raw.chroma =
vb2_dma_contig_plane_dma_addr(vb, 1);
ctx->src_bufs_cnt++;
} else {
- mfc_err("inavlid queue type: %d\n", vq->type);
+ mfc_err("invalid queue type: %d\n", vq->type);
return -EINVAL;
}
return 0;
@@ -1931,7 +1938,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
return -EINVAL;
}
} else {
- mfc_err("inavlid queue type: %d\n", vq->type);
+ mfc_err("invalid queue type: %d\n", vq->type);
return -EINVAL;
}
return 0;
@@ -2012,7 +2019,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
return;
}
if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
+ mfc_buf = &ctx->dst_bufs[vb->index];
mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
/* Mark destination as available for use by MFC */
spin_lock_irqsave(&dev->irqlock, flags);
@@ -2020,7 +2027,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
ctx->dst_queue_cnt++;
spin_unlock_irqrestore(&dev->irqlock, flags);
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
+ mfc_buf = &ctx->src_bufs[vb->index];
mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
spin_lock_irqsave(&dev->irqlock, flags);
list_add_tail(&mfc_buf->list, &ctx->src_queue);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 6402f76cc620..873c933bc7d4 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -1208,11 +1208,11 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
temp_vb->flags |= MFC_BUF_FLAG_USED;
s5p_mfc_set_dec_stream_buffer_v5(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
- ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
+ vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+ ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
- if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+ if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
last_frame = MFC_DEC_LAST_FRAME;
mfc_debug(2, "Setting ctx->state to FINISHING\n");
ctx->state = MFCINST_FINISHING;
@@ -1249,16 +1249,16 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
list);
src_mb->flags |= MFC_BUF_FLAG_USED;
- if (src_mb->b->v4l2_planes[0].bytesused == 0) {
+ if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
/* send null frame */
s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2,
dev->bank2);
ctx->state = MFCINST_FINISHING;
} else {
- src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
- 0);
- src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
- 1);
+ src_y_addr = vb2_dma_contig_plane_dma_addr(
+ &src_mb->b->vb2_buf, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(
+ &src_mb->b->vb2_buf, 1);
s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,
src_c_addr);
if (src_mb->flags & MFC_BUF_FLAG_EOS)
@@ -1267,13 +1267,13 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
}
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_mb->flags |= MFC_BUF_FLAG_USED;
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+ dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
mfc_debug(2, "encoding buffer with index=%d state=%d\n",
- src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
+ src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state);
s5p_mfc_encode_one_frame_v5(ctx);
return 0;
}
@@ -1289,10 +1289,11 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
mfc_debug(2, "Preparing to init decoding\n");
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
s5p_mfc_set_dec_desc_buffer(ctx);
- mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+ mfc_debug(2, "Header size: %d\n",
+ temp_vb->b->vb2_buf.planes[0].bytesused);
s5p_mfc_set_dec_stream_buffer_v5(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
- 0, temp_vb->b->v4l2_planes[0].bytesused);
+ vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+ 0, temp_vb->b->vb2_buf.planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
s5p_mfc_init_decode_v5(ctx);
@@ -1309,8 +1310,8 @@ static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
s5p_mfc_set_enc_ref_buffer_v5(ctx);
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+ dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
@@ -1342,10 +1343,11 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
return -EIO;
}
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+ mfc_debug(2, "Header size: %d\n",
+ temp_vb->b->vb2_buf.planes[0].bytesused);
s5p_mfc_set_dec_stream_buffer_v5(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
- 0, temp_vb->b->v4l2_planes[0].bytesused);
+ vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+ 0, temp_vb->b->vb2_buf.planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
@@ -1478,9 +1480,9 @@ static void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
while (!list_empty(lh)) {
b = list_entry(lh->next, struct s5p_mfc_buf, list);
- for (i = 0; i < b->b->num_planes; i++)
- vb2_set_plane_payload(b->b, i, 0);
- vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+ for (i = 0; i < b->b->vb2_buf.num_planes; i++)
+ vb2_set_plane_payload(&b->b->vb2_buf, i, 0);
+ vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&b->list);
}
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index e5cb30e1f718..b95845347348 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -522,7 +522,7 @@ static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
writel(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */
writel(size, mfc_regs->e_stream_buffer_size);
- mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d\n",
+ mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%x\n",
addr, size);
return 0;
@@ -554,7 +554,7 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
enc_recon_y_addr = readl(mfc_regs->e_recon_luma_dpb_addr);
enc_recon_c_addr = readl(mfc_regs->e_recon_chroma_dpb_addr);
- mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr);
+ mfc_debug(2, "recon y addr: 0x%08lx y_addr: 0x%08lx\n", enc_recon_y_addr, *y_addr);
mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr);
}
@@ -1483,6 +1483,7 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+ int cmd;
mfc_debug(2, "++\n");
@@ -1493,9 +1494,13 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
s5p_mfc_set_slice_mode(ctx);
+ if (ctx->state != MFCINST_FINISHING)
+ cmd = S5P_FIMV_CH_FRAME_START_V6;
+ else
+ cmd = S5P_FIMV_CH_LAST_FRAME_V6;
+
writel(ctx->inst_no, mfc_regs->instance_id);
- s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev,
- S5P_FIMV_CH_FRAME_START_V6, NULL);
+ s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL);
mfc_debug(2, "--\n");
@@ -1562,13 +1567,13 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
temp_vb->flags |= MFC_BUF_FLAG_USED;
s5p_mfc_set_dec_stream_buffer_v6(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+ vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
ctx->consumed_stream,
- temp_vb->b->v4l2_planes[0].bytesused);
+ temp_vb->b->vb2_buf.planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
- if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+ if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
last_frame = 1;
mfc_debug(2, "Setting ctx->state to FINISHING\n");
ctx->state = MFCINST_FINISHING;
@@ -1592,7 +1597,7 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
- if (list_empty(&ctx->src_queue)) {
+ if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
mfc_debug(2, "no src buffers.\n");
spin_unlock_irqrestore(&dev->irqlock, flags);
return -EAGAIN;
@@ -1604,20 +1609,33 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
return -EAGAIN;
}
- src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- src_mb->flags |= MFC_BUF_FLAG_USED;
- src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
- src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+ if (list_empty(&ctx->src_queue)) {
+ /* send null frame */
+ s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
+ src_mb = NULL;
+ } else {
+ src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ src_mb->flags |= MFC_BUF_FLAG_USED;
+ if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
+ s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
+ ctx->state = MFCINST_FINISHING;
+ } else {
+ src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
- mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr);
- mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr);
+ mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr);
+ mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr);
- s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+ s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+ if (src_mb->flags & MFC_BUF_FLAG_EOS)
+ ctx->state = MFCINST_FINISHING;
+ }
+ }
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_mb->flags |= MFC_BUF_FLAG_USED;
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+ dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
@@ -1639,10 +1657,10 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
mfc_debug(2, "Preparing to init decoding.\n");
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+ mfc_debug(2, "Header size: %d\n", temp_vb->b->vb2_buf.planes[0].bytesused);
s5p_mfc_set_dec_stream_buffer_v6(ctx,
- vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
- temp_vb->b->v4l2_planes[0].bytesused);
+ vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0,
+ temp_vb->b->vb2_buf.planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
s5p_mfc_init_decode_v6(ctx);
@@ -1659,8 +1677,8 @@ static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
- dst_size = vb2_plane_size(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+ dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
@@ -1836,9 +1854,9 @@ static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
while (!list_empty(lh)) {
b = list_entry(lh->next, struct s5p_mfc_buf, list);
- for (i = 0; i < b->b->num_planes; i++)
- vb2_set_plane_payload(b->b, i, 0);
- vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+ for (i = 0; i < b->b->vb2_buf.num_planes; i++)
+ vb2_set_plane_payload(&b->b->vb2_buf, i, 0);
+ vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&b->list);
}
}
diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h
index fb2acc53112a..42cd2709c41c 100644
--- a/drivers/media/platform/s5p-tv/mixer.h
+++ b/drivers/media/platform/s5p-tv/mixer.h
@@ -24,7 +24,7 @@
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <media/v4l2-device.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "regs-mixer.h"
@@ -113,7 +113,7 @@ struct mxr_geometry {
/** instance of a buffer */
struct mxr_buffer {
/** common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
/** node for layer's lists */
struct list_head list;
};
diff --git a/drivers/media/platform/s5p-tv/mixer_grp_layer.c b/drivers/media/platform/s5p-tv/mixer_grp_layer.c
index 74344c764daa..db3163b23ea0 100644
--- a/drivers/media/platform/s5p-tv/mixer_grp_layer.c
+++ b/drivers/media/platform/s5p-tv/mixer_grp_layer.c
@@ -86,7 +86,7 @@ static void mxr_graph_buffer_set(struct mxr_layer *layer,
dma_addr_t addr = 0;
if (buf)
- addr = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
}
diff --git a/drivers/media/platform/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c
index 5127acb1e571..a0ec14a1da13 100644
--- a/drivers/media/platform/s5p-tv/mixer_reg.c
+++ b/drivers/media/platform/s5p-tv/mixer_reg.c
@@ -279,7 +279,7 @@ static void mxr_irq_layer_handle(struct mxr_layer *layer)
layer->ops.buffer_set(layer, layer->update_buf);
if (done && done != layer->shadow_buf)
- vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&done->vb.vb2_buf, VB2_BUF_STATE_DONE);
done:
spin_unlock(&layer->enq_slock);
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 751f3b618337..dc1c679e136c 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -881,7 +881,7 @@ static const struct v4l2_file_operations mxr_fops = {
.unlocked_ioctl = video_ioctl2,
};
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
{
@@ -914,7 +914,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
static void buf_queue(struct vb2_buffer *vb)
{
- struct mxr_buffer *buffer = container_of(vb, struct mxr_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct mxr_buffer *buffer = container_of(vbuf, struct mxr_buffer, vb);
struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
struct mxr_device *mdev = layer->mdev;
unsigned long flags;
@@ -963,11 +964,13 @@ static void mxr_watchdog(unsigned long arg)
if (layer->update_buf == layer->shadow_buf)
layer->update_buf = NULL;
if (layer->update_buf) {
- vb2_buffer_done(&layer->update_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&layer->update_buf->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
layer->update_buf = NULL;
}
if (layer->shadow_buf) {
- vb2_buffer_done(&layer->shadow_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&layer->shadow_buf->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
layer->shadow_buf = NULL;
}
spin_unlock_irqrestore(&layer->enq_slock, flags);
@@ -991,7 +994,7 @@ static void stop_streaming(struct vb2_queue *vq)
/* set all buffer to be done */
list_for_each_entry_safe(buf, buf_tmp, &layer->enq_list, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&layer->enq_slock, flags);
diff --git a/drivers/media/platform/s5p-tv/mixer_vp_layer.c b/drivers/media/platform/s5p-tv/mixer_vp_layer.c
index c9388c45ad75..dd002a497dbb 100644
--- a/drivers/media/platform/s5p-tv/mixer_vp_layer.c
+++ b/drivers/media/platform/s5p-tv/mixer_vp_layer.c
@@ -97,9 +97,10 @@ static void mxr_vp_buffer_set(struct mxr_layer *layer,
mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
return;
}
- luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
+ luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
if (layer->fmt->num_subframes == 2) {
- chroma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 1);
+ chroma_addr[0] =
+ vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 1);
} else {
/* FIXME: mxr_get_plane_size compute integer division,
* which is slow and should not be performed in interrupt */
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index f5e3eb3a20ff..d6ab33e7060a 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -865,10 +865,11 @@ static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
/* ========== Queue operations ========== */
static int sh_veu_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *f,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *f = parg;
struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
struct sh_veu_vfmt *vfmt;
unsigned int size, count = *nbuffers;
@@ -931,9 +932,10 @@ static int sh_veu_buf_prepare(struct vb2_buffer *vb)
static void sh_veu_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
- dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->v4l2_buf.type);
- v4l2_m2m_buf_queue(veu->m2m_ctx, vb);
+ dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->type);
+ v4l2_m2m_buf_queue(veu->m2m_ctx, vbuf);
}
static const struct vb2_ops sh_veu_qops = {
@@ -1084,8 +1086,8 @@ static irqreturn_t sh_veu_bh(int irq, void *dev_id)
static irqreturn_t sh_veu_isr(int irq, void *dev_id)
{
struct sh_veu_dev *veu = dev_id;
- struct vb2_buffer *dst;
- struct vb2_buffer *src;
+ struct vb2_v4l2_buffer *dst;
+ struct vb2_v4l2_buffer *src;
u32 status = sh_veu_reg_read(veu, VEU_EVTR);
/* bundle read mode not used */
@@ -1105,11 +1107,11 @@ static irqreturn_t sh_veu_isr(int irq, void *dev_id)
if (!src || !dst)
return IRQ_NONE;
- dst->v4l2_buf.timestamp = src->v4l2_buf.timestamp;
- dst->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst->v4l2_buf.flags |=
- src->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst->v4l2_buf.timecode = src->v4l2_buf.timecode;
+ dst->timestamp = src->timestamp;
+ dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst->flags |=
+ src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst->timecode = src->timecode;
spin_lock(&veu->lock);
v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index fe5c8ab06bd5..2231f8922df3 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -27,6 +27,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mediabus.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
/* Mirror addresses are not available for all registers */
@@ -62,11 +63,12 @@ enum sh_vou_status {
#define VOU_MIN_IMAGE_HEIGHT 16
struct sh_vou_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
-static inline struct sh_vou_buffer *to_sh_vou_buffer(struct vb2_buffer *vb2)
+static inline struct
+sh_vou_buffer *to_sh_vou_buffer(struct vb2_v4l2_buffer *vb2)
{
return container_of(vb2, struct sh_vou_buffer, vb);
}
@@ -193,11 +195,11 @@ static struct sh_vou_fmt vou_fmt[] = {
};
static void sh_vou_schedule_next(struct sh_vou_device *vou_dev,
- struct vb2_buffer *vb)
+ struct vb2_v4l2_buffer *vbuf)
{
dma_addr_t addr1, addr2;
- addr1 = vb2_dma_contig_plane_dma_addr(vb, 0);
+ addr1 = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
switch (vou_dev->pix.pixelformat) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV16:
@@ -241,10 +243,11 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev)
}
/* Locking: caller holds fop_lock mutex */
-static int sh_vou_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int sh_vou_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
struct v4l2_pix_format *pix = &vou_dev->pix;
int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
@@ -282,8 +285,9 @@ static int sh_vou_buf_prepare(struct vb2_buffer *vb)
/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */
static void sh_vou_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sh_vou_device *vou_dev = vb2_get_drv_priv(vb->vb2_queue);
- struct sh_vou_buffer *shbuf = to_sh_vou_buffer(vb);
+ struct sh_vou_buffer *shbuf = to_sh_vou_buffer(vbuf);
unsigned long flags;
spin_lock_irqsave(&vou_dev->lock, flags);
@@ -302,7 +306,8 @@ static int sh_vou_start_streaming(struct vb2_queue *vq, unsigned int count)
video, s_stream, 1);
if (ret < 0 && ret != -ENOIOCTLCMD) {
list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) {
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
list_del(&buf->list);
}
vou_dev->active = NULL;
@@ -353,7 +358,7 @@ static void sh_vou_stop_streaming(struct vb2_queue *vq)
msleep(50);
spin_lock_irqsave(&vou_dev->lock, flags);
list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) {
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&buf->list);
}
vou_dev->active = NULL;
@@ -1066,10 +1071,10 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id)
list_del(&vb->list);
- v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
- vb->vb.v4l2_buf.sequence = vou_dev->sequence++;
- vb->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
- vb2_buffer_done(&vb->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vb->vb.timestamp);
+ vb->vb.sequence = vou_dev->sequence++;
+ vb->vb.field = V4L2_FIELD_INTERLACED;
+ vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE);
vou_dev->active = list_entry(vou_dev->buf_list.next,
struct sh_vou_buffer, list);
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 90701726a06a..454f68f0cdad 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -23,12 +23,13 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-#include <media/atmel-isi.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
#include <media/v4l2-of.h>
#include <media/videobuf2-dma-contig.h>
+#include "atmel-isi.h"
+
#define MAX_BUFFER_NUM 32
#define MAX_SUPPORT_WIDTH 2048
#define MAX_SUPPORT_HEIGHT 2048
@@ -59,7 +60,7 @@ struct isi_dma_desc {
/* Frame buffer data */
struct frame_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct isi_dma_desc *p_dma_desc;
struct list_head list;
};
@@ -102,62 +103,71 @@ static u32 isi_readl(struct atmel_isi *isi, u32 reg)
return readl(isi->regs + reg);
}
-static int configure_geometry(struct atmel_isi *isi, u32 width,
+static void configure_geometry(struct atmel_isi *isi, u32 width,
u32 height, u32 code)
{
- u32 cfg2, cr;
+ u32 cfg2;
+ /* According to sensor's output format to set cfg2 */
switch (code) {
- /* YUV, including grey */
+ default:
+ /* Grey */
case MEDIA_BUS_FMT_Y8_1X8:
- cr = ISI_CFG2_GRAYSCALE;
+ cfg2 = ISI_CFG2_GRAYSCALE | ISI_CFG2_COL_SPACE_YCbCr;
break;
+ /* YUV */
case MEDIA_BUS_FMT_VYUY8_2X8:
- cr = ISI_CFG2_YCC_SWAP_MODE_3;
+ cfg2 = ISI_CFG2_YCC_SWAP_MODE_3 | ISI_CFG2_COL_SPACE_YCbCr;
break;
case MEDIA_BUS_FMT_UYVY8_2X8:
- cr = ISI_CFG2_YCC_SWAP_MODE_2;
+ cfg2 = ISI_CFG2_YCC_SWAP_MODE_2 | ISI_CFG2_COL_SPACE_YCbCr;
break;
case MEDIA_BUS_FMT_YVYU8_2X8:
- cr = ISI_CFG2_YCC_SWAP_MODE_1;
+ cfg2 = ISI_CFG2_YCC_SWAP_MODE_1 | ISI_CFG2_COL_SPACE_YCbCr;
break;
case MEDIA_BUS_FMT_YUYV8_2X8:
- cr = ISI_CFG2_YCC_SWAP_DEFAULT;
+ cfg2 = ISI_CFG2_YCC_SWAP_DEFAULT | ISI_CFG2_COL_SPACE_YCbCr;
break;
/* RGB, TODO */
- default:
- return -EINVAL;
}
isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
-
- cfg2 = isi_readl(isi, ISI_CFG2);
- /* Set YCC swap mode */
- cfg2 &= ~ISI_CFG2_YCC_SWAP_MODE_MASK;
- cfg2 |= cr;
/* Set width */
- cfg2 &= ~(ISI_CFG2_IM_HSIZE_MASK);
cfg2 |= ((width - 1) << ISI_CFG2_IM_HSIZE_OFFSET) &
ISI_CFG2_IM_HSIZE_MASK;
/* Set height */
- cfg2 &= ~(ISI_CFG2_IM_VSIZE_MASK);
cfg2 |= ((height - 1) << ISI_CFG2_IM_VSIZE_OFFSET)
& ISI_CFG2_IM_VSIZE_MASK;
isi_writel(isi, ISI_CFG2, cfg2);
+}
- return 0;
+static bool is_supported(struct soc_camera_device *icd,
+ const u32 pixformat)
+{
+ switch (pixformat) {
+ /* YUV, including grey */
+ case V4L2_PIX_FMT_GREY:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_VYUY:
+ return true;
+ /* RGB, TODO */
+ default:
+ return false;
+ }
}
static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi)
{
if (isi->active) {
- struct vb2_buffer *vb = &isi->active->vb;
+ struct vb2_v4l2_buffer *vbuf = &isi->active->vb;
struct frame_buffer *buf = isi->active;
list_del_init(&buf->list);
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
- vb->v4l2_buf.sequence = isi->sequence++;
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vbuf->timestamp);
+ vbuf->sequence = isi->sequence++;
+ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
}
if (list_empty(&isi->video_buffer_list)) {
@@ -225,7 +235,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
}
timeout = wait_for_completion_timeout(&isi->complete,
- msecs_to_jiffies(100));
+ msecs_to_jiffies(500));
if (timeout == 0)
return -ETIMEDOUT;
@@ -235,7 +245,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
/* ------------------------------------------------------------------
Videobuf operations
------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -267,7 +277,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int buffer_init(struct vb2_buffer *vb)
{
- struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
buf->p_dma_desc = NULL;
INIT_LIST_HEAD(&buf->list);
@@ -277,8 +288,9 @@ static int buffer_init(struct vb2_buffer *vb)
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
- struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+ struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct atmel_isi *isi = ici->priv;
unsigned long size;
@@ -292,7 +304,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
return -EINVAL;
}
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(vb, 0, size);
if (!buf->p_dma_desc) {
if (list_empty(&isi->dma_desc_head)) {
@@ -319,10 +331,11 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_cleanup(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct atmel_isi *isi = ici->priv;
- struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+ struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
/* This descriptor is available now and we add to head list */
if (buf->p_dma_desc)
@@ -360,10 +373,11 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct atmel_isi *isi = ici->priv;
- struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb);
+ struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
unsigned long flags = 0;
spin_lock_irqsave(&isi->lock, flags);
@@ -396,6 +410,9 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
/* Disable all interrupts */
isi_writel(isi, ISI_INTDIS, (u32)~0UL);
+ configure_geometry(isi, icd->user_width, icd->user_height,
+ icd->current_fmt->code);
+
spin_lock_irq(&isi->lock);
/* Clear any pending interrupt */
isi_readl(isi, ISI_STATUS);
@@ -422,7 +439,7 @@ static void stop_streaming(struct vb2_queue *vq)
/* Release all active buffers */
list_for_each_entry_safe(buf, node, &isi->video_buffer_list, list) {
list_del_init(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irq(&isi->lock);
@@ -483,8 +500,6 @@ static int isi_camera_init_videobuf(struct vb2_queue *q,
static int isi_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct atmel_isi *isi = ici->priv;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
@@ -494,6 +509,10 @@ static int isi_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
+ /* check with atmel-isi support format, if not support use YUYV */
+ if (!is_supported(icd, pix->pixelformat))
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
dev_warn(icd->parent, "Format %x not found\n",
@@ -517,16 +536,6 @@ static int isi_camera_set_fmt(struct soc_camera_device *icd,
if (mf->code != xlate->code)
return -EINVAL;
- /* Enable PM and peripheral clock before operate isi registers */
- pm_runtime_get_sync(ici->v4l2_dev.dev);
-
- ret = configure_geometry(isi, pix->width, pix->height, xlate->code);
-
- pm_runtime_put(ici->v4l2_dev.dev);
-
- if (ret < 0)
- return ret;
-
pix->width = mf->width;
pix->height = mf->height;
pix->field = mf->field;
@@ -553,6 +562,10 @@ static int isi_camera_try_fmt(struct soc_camera_device *icd,
u32 pixfmt = pix->pixelformat;
int ret;
+ /* check with atmel-isi support format, if not support use YUYV */
+ if (!is_supported(icd, pix->pixelformat))
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (pixfmt && !xlate) {
dev_warn(icd->parent, "Format %x not found\n", pixfmt);
@@ -824,6 +837,11 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
+ dev_dbg(icd->parent, "vsync active %s, hsync active %s, sampling on pix clock %s edge\n",
+ common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? "low" : "high",
+ common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? "low" : "high",
+ common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING ? "falling" : "rising");
+
if (isi->pdata.has_emb_sync)
cfg1 |= ISI_CFG1_EMB_SYNC;
if (isi->pdata.full_mode)
@@ -873,7 +891,7 @@ static int atmel_isi_remove(struct platform_device *pdev)
return 0;
}
-static int atmel_isi_probe_dt(struct atmel_isi *isi,
+static int atmel_isi_parse_dt(struct atmel_isi *isi,
struct platform_device *pdev)
{
struct device_node *np= pdev->dev.of_node;
@@ -891,9 +909,10 @@ static int atmel_isi_probe_dt(struct atmel_isi *isi,
}
err = v4l2_of_parse_endpoint(np, &ep);
+ of_node_put(np);
if (err) {
dev_err(&pdev->dev, "Could not parse the endpoint\n");
- goto err_probe_dt;
+ return err;
}
switch (ep.bus.parallel.bus_width) {
@@ -907,14 +926,20 @@ static int atmel_isi_probe_dt(struct atmel_isi *isi,
default:
dev_err(&pdev->dev, "Unsupported bus width: %d\n",
ep.bus.parallel.bus_width);
- err = -EINVAL;
- goto err_probe_dt;
+ return -EINVAL;
}
-err_probe_dt:
- of_node_put(np);
+ if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+ isi->pdata.hsync_act_low = true;
+ if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+ isi->pdata.vsync_act_low = true;
+ if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+ isi->pdata.pclk_act_falling = true;
- return err;
+ if (ep.bus_type == V4L2_MBUS_BT656)
+ isi->pdata.has_emb_sync = true;
+
+ return 0;
}
static int atmel_isi_probe(struct platform_device *pdev)
@@ -923,16 +948,7 @@ static int atmel_isi_probe(struct platform_device *pdev)
struct atmel_isi *isi;
struct resource *regs;
int ret, i;
- struct device *dev = &pdev->dev;
struct soc_camera_host *soc_host;
- struct isi_platform_data *pdata;
-
- pdata = dev->platform_data;
- if ((!pdata || !pdata->data_width_flags) && !pdev->dev.of_node) {
- dev_err(&pdev->dev,
- "No config available for Atmel ISI\n");
- return -EINVAL;
- }
isi = devm_kzalloc(&pdev->dev, sizeof(struct atmel_isi), GFP_KERNEL);
if (!isi) {
@@ -944,13 +960,9 @@ static int atmel_isi_probe(struct platform_device *pdev)
if (IS_ERR(isi->pclk))
return PTR_ERR(isi->pclk);
- if (pdata) {
- memcpy(&isi->pdata, pdata, sizeof(isi->pdata));
- } else {
- ret = atmel_isi_probe_dt(isi, pdev);
- if (ret)
- return ret;
- }
+ ret = atmel_isi_parse_dt(isi, pdev);
+ if (ret)
+ return ret;
isi->active = NULL;
spin_lock_init(&isi->lock);
@@ -1014,11 +1026,6 @@ static int atmel_isi_probe(struct platform_device *pdev)
pm_suspend_ignore_children(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
- if (isi->pdata.asd_sizes) {
- soc_host->asd = isi->pdata.asd;
- soc_host->asd_sizes = isi->pdata.asd_sizes;
- }
-
ret = soc_camera_host_register(soc_host);
if (ret) {
dev_err(&pdev->dev, "Unable to register soc camera host\n");
@@ -1040,6 +1047,7 @@ err_alloc_ctx:
return ret;
}
+#ifdef CONFIG_PM
static int atmel_isi_runtime_suspend(struct device *dev)
{
struct soc_camera_host *soc_host = to_soc_camera_host(dev);
@@ -1058,6 +1066,7 @@ static int atmel_isi_runtime_resume(struct device *dev)
return clk_prepare_enable(isi->pclk);
}
+#endif /* CONFIG_PM */
static const struct dev_pm_ops atmel_isi_dev_pm_ops = {
SET_RUNTIME_PM_OPS(atmel_isi_runtime_suspend,
diff --git a/drivers/media/platform/soc_camera/atmel-isi.h b/drivers/media/platform/soc_camera/atmel-isi.h
new file mode 100644
index 000000000000..5acc771d2edc
--- /dev/null
+++ b/drivers/media/platform/soc_camera/atmel-isi.h
@@ -0,0 +1,128 @@
+/*
+ * Register definitions for the Atmel Image Sensor Interface.
+ *
+ * Copyright (C) 2011 Atmel Corporation
+ * Josh Wu, <josh.wu@atmel.com>
+ *
+ * Based on previous work by Lars Haring, <lars.haring@atmel.com>
+ * and Sedji Gaouaou
+ *
+ * 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 __ATMEL_ISI_H__
+#define __ATMEL_ISI_H__
+
+#include <linux/types.h>
+
+/* ISI_V2 register offsets */
+#define ISI_CFG1 0x0000
+#define ISI_CFG2 0x0004
+#define ISI_PSIZE 0x0008
+#define ISI_PDECF 0x000c
+#define ISI_Y2R_SET0 0x0010
+#define ISI_Y2R_SET1 0x0014
+#define ISI_R2Y_SET0 0x0018
+#define ISI_R2Y_SET1 0x001C
+#define ISI_R2Y_SET2 0x0020
+#define ISI_CTRL 0x0024
+#define ISI_STATUS 0x0028
+#define ISI_INTEN 0x002C
+#define ISI_INTDIS 0x0030
+#define ISI_INTMASK 0x0034
+#define ISI_DMA_CHER 0x0038
+#define ISI_DMA_CHDR 0x003C
+#define ISI_DMA_CHSR 0x0040
+#define ISI_DMA_P_ADDR 0x0044
+#define ISI_DMA_P_CTRL 0x0048
+#define ISI_DMA_P_DSCR 0x004C
+#define ISI_DMA_C_ADDR 0x0050
+#define ISI_DMA_C_CTRL 0x0054
+#define ISI_DMA_C_DSCR 0x0058
+
+/* Bitfields in CFG1 */
+#define ISI_CFG1_HSYNC_POL_ACTIVE_LOW (1 << 2)
+#define ISI_CFG1_VSYNC_POL_ACTIVE_LOW (1 << 3)
+#define ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING (1 << 4)
+#define ISI_CFG1_EMB_SYNC (1 << 6)
+#define ISI_CFG1_CRC_SYNC (1 << 7)
+/* Constants for FRATE(ISI_V2) */
+#define ISI_CFG1_FRATE_CAPTURE_ALL (0 << 8)
+#define ISI_CFG1_FRATE_DIV_2 (1 << 8)
+#define ISI_CFG1_FRATE_DIV_3 (2 << 8)
+#define ISI_CFG1_FRATE_DIV_4 (3 << 8)
+#define ISI_CFG1_FRATE_DIV_5 (4 << 8)
+#define ISI_CFG1_FRATE_DIV_6 (5 << 8)
+#define ISI_CFG1_FRATE_DIV_7 (6 << 8)
+#define ISI_CFG1_FRATE_DIV_8 (7 << 8)
+#define ISI_CFG1_FRATE_DIV_MASK (7 << 8)
+#define ISI_CFG1_DISCR (1 << 11)
+#define ISI_CFG1_FULL_MODE (1 << 12)
+/* Definition for THMASK(ISI_V2) */
+#define ISI_CFG1_THMASK_BEATS_4 (0 << 13)
+#define ISI_CFG1_THMASK_BEATS_8 (1 << 13)
+#define ISI_CFG1_THMASK_BEATS_16 (2 << 13)
+
+/* Bitfields in CFG2 */
+#define ISI_CFG2_GRAYSCALE (1 << 13)
+#define ISI_CFG2_COL_SPACE_YCbCr (0 << 15)
+#define ISI_CFG2_COL_SPACE_RGB (1 << 15)
+/* Constants for YCC_SWAP(ISI_V2) */
+#define ISI_CFG2_YCC_SWAP_DEFAULT (0 << 28)
+#define ISI_CFG2_YCC_SWAP_MODE_1 (1 << 28)
+#define ISI_CFG2_YCC_SWAP_MODE_2 (2 << 28)
+#define ISI_CFG2_YCC_SWAP_MODE_3 (3 << 28)
+#define ISI_CFG2_YCC_SWAP_MODE_MASK (3 << 28)
+#define ISI_CFG2_IM_VSIZE_OFFSET 0
+#define ISI_CFG2_IM_HSIZE_OFFSET 16
+#define ISI_CFG2_IM_VSIZE_MASK (0x7FF << ISI_CFG2_IM_VSIZE_OFFSET)
+#define ISI_CFG2_IM_HSIZE_MASK (0x7FF << ISI_CFG2_IM_HSIZE_OFFSET)
+
+/* Bitfields in CTRL */
+/* Also using in SR(ISI_V2) */
+#define ISI_CTRL_EN (1 << 0)
+#define ISI_CTRL_CDC (1 << 8)
+/* Also using in SR/IER/IDR/IMR(ISI_V2) */
+#define ISI_CTRL_DIS (1 << 1)
+#define ISI_CTRL_SRST (1 << 2)
+
+/* Bitfields in SR */
+#define ISI_SR_SIP (1 << 19)
+/* Also using in SR/IER/IDR/IMR */
+#define ISI_SR_VSYNC (1 << 10)
+#define ISI_SR_PXFR_DONE (1 << 16)
+#define ISI_SR_CXFR_DONE (1 << 17)
+#define ISI_SR_P_OVR (1 << 24)
+#define ISI_SR_C_OVR (1 << 25)
+#define ISI_SR_CRC_ERR (1 << 26)
+#define ISI_SR_FR_OVR (1 << 27)
+
+/* Bitfields in DMA_C_CTRL & in DMA_P_CTRL */
+#define ISI_DMA_CTRL_FETCH (1 << 0)
+#define ISI_DMA_CTRL_WB (1 << 1)
+#define ISI_DMA_CTRL_IEN (1 << 2)
+#define ISI_DMA_CTRL_DONE (1 << 3)
+
+/* Bitfields in DMA_CHSR/CHER/CHDR */
+#define ISI_DMA_CHSR_P_CH (1 << 0)
+#define ISI_DMA_CHSR_C_CH (1 << 1)
+
+/* Definition for isi_platform_data */
+#define ISI_DATAWIDTH_8 0x01
+#define ISI_DATAWIDTH_10 0x02
+
+struct v4l2_async_subdev;
+
+struct isi_platform_data {
+ u8 has_emb_sync;
+ u8 hsync_act_low;
+ u8 vsync_act_low;
+ u8 pclk_act_falling;
+ u8 full_mode;
+ u32 data_width_flags;
+ /* Using for ISI_CFG1 */
+ u32 frate;
+};
+
+#endif /* __ATMEL_ISI_H__ */
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index ea4c423f0cf8..1f28d21a3c9a 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -32,7 +32,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
@@ -225,7 +225,7 @@ struct mx2_buf_internal {
/* buffer for one video frame */
struct mx2_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct mx2_buf_internal internal;
};
@@ -469,10 +469,11 @@ static void mx2_camera_clock_stop(struct soc_camera_host *ici)
* Videobuf operations
*/
static int mx2_videobuf_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *count, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx2_camera_dev *pcdev = ici->priv;
@@ -530,11 +531,12 @@ out:
static void mx2_videobuf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici =
to_soc_camera_host(icd->parent);
struct mx2_camera_dev *pcdev = ici->priv;
- struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
+ struct mx2_buffer *buf = container_of(vbuf, struct mx2_buffer, vb);
unsigned long flags;
dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
@@ -664,7 +666,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
internal.queue);
buf->internal.bufnum = 0;
- vb = &buf->vb;
+ vb = &buf->vb.vb2_buf;
phys = vb2_dma_contig_plane_dma_addr(vb, 0);
mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
@@ -673,7 +675,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
internal.queue);
buf->internal.bufnum = 1;
- vb = &buf->vb;
+ vb = &buf->vb.vb2_buf;
phys = vb2_dma_contig_plane_dma_addr(vb, 0);
mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
@@ -1307,6 +1309,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
struct mx2_buf_internal *ibuf;
struct mx2_buffer *buf;
struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
unsigned long phys;
ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal,
@@ -1323,7 +1326,8 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
} else {
buf = mx2_ibuf_to_buf(ibuf);
- vb = &buf->vb;
+ vb = &buf->vb.vb2_buf;
+ vbuf = to_vb2_v4l2_buffer(vb);
#ifdef DEBUG
phys = vb2_dma_contig_plane_dma_addr(vb, 0);
if (prp->cfg.channel == 1) {
@@ -1347,8 +1351,8 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
vb2_get_plane_payload(vb, 0));
list_del_init(&buf->internal.queue);
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
- vb->v4l2_buf.sequence = pcdev->frame_count;
+ v4l2_get_timestamp(&vbuf->timestamp);
+ vbuf->sequence = pcdev->frame_count;
if (err)
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
else
@@ -1380,7 +1384,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
- vb = &buf->vb;
+ vb = &buf->vb.vb2_buf;
phys = vb2_dma_contig_plane_dma_addr(vb, 0);
mx27_update_emma_buf(pcdev, phys, bufnum);
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index ace41f53caca..49c3a257a916 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -63,7 +63,7 @@
struct mx3_camera_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head queue;
/* One descriptot per scatterlist (per frame) */
@@ -133,7 +133,7 @@ static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg)
__raw_writel(value, mx3->base + reg);
}
-static struct mx3_camera_buffer *to_mx3_vb(struct vb2_buffer *vb)
+static struct mx3_camera_buffer *to_mx3_vb(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct mx3_camera_buffer, vb);
}
@@ -151,14 +151,14 @@ static void mx3_cam_dma_done(void *arg)
spin_lock(&mx3_cam->lock);
if (mx3_cam->active) {
- struct vb2_buffer *vb = &mx3_cam->active->vb;
+ struct vb2_v4l2_buffer *vb = &mx3_cam->active->vb;
struct mx3_camera_buffer *buf = to_mx3_vb(vb);
list_del_init(&buf->queue);
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
- vb->v4l2_buf.field = mx3_cam->field;
- vb->v4l2_buf.sequence = mx3_cam->sequence++;
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vb->timestamp);
+ vb->field = mx3_cam->field;
+ vb->sequence = mx3_cam->sequence++;
+ vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
}
if (list_empty(&mx3_cam->capture)) {
@@ -185,10 +185,11 @@ static void mx3_cam_dma_done(void *arg)
* Calculate the __buffer__ (not data) size and number of buffers.
*/
static int mx3_videobuf_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *count, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
@@ -257,10 +258,11 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
static void mx3_videobuf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+ struct mx3_camera_buffer *buf = to_mx3_vb(vbuf);
struct scatterlist *sg = &buf->sg;
struct dma_async_tx_descriptor *txd;
struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
@@ -273,7 +275,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < new_size) {
dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n",
- vb->v4l2_buf.index, vb2_plane_size(vb, 0), new_size);
+ vbuf->vb2_buf.index, vb2_plane_size(vb, 0), new_size);
goto error;
}
@@ -357,10 +359,11 @@ error:
static void mx3_videobuf_release(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+ struct mx3_camera_buffer *buf = to_mx3_vb(vbuf);
struct dma_async_tx_descriptor *txd = buf->txd;
unsigned long flags;
@@ -390,10 +393,11 @@ static void mx3_videobuf_release(struct vb2_buffer *vb)
static int mx3_videobuf_init(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+ struct mx3_camera_buffer *buf = to_mx3_vb(vbuf);
if (!buf->txd) {
/* This is for locking debugging only */
@@ -424,7 +428,7 @@ static void mx3_stop_streaming(struct vb2_queue *q)
list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) {
list_del_init(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&mx3_cam->lock, flags);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 71dd71c0bd1f..efe57b23fac1 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -478,7 +478,7 @@ struct rcar_vin_priv {
struct soc_camera_host ici;
struct list_head capture;
#define MAX_BUFFER_NUM 3
- struct vb2_buffer *queue_buf[MAX_BUFFER_NUM];
+ struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM];
struct vb2_alloc_ctx *alloc_ctx;
enum v4l2_field field;
unsigned int pdata_flags;
@@ -492,7 +492,7 @@ struct rcar_vin_priv {
#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
struct rcar_vin_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -527,11 +527,12 @@ struct rcar_vin_cam {
* required
*/
static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *count,
unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct rcar_vin_priv *priv = ici->priv;
@@ -748,7 +749,7 @@ static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
/* Moves a buffer from the queue to the HW slots */
static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
{
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
dma_addr_t phys_addr_top;
int slot;
@@ -760,10 +761,11 @@ static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
if (slot < 0)
return 0;
- vb = &list_entry(priv->capture.next, struct rcar_vin_buffer, list)->vb;
- list_del_init(to_buf_list(vb));
- priv->queue_buf[slot] = vb;
- phys_addr_top = vb2_dma_contig_plane_dma_addr(vb, 0);
+ vbuf = &list_entry(priv->capture.next,
+ struct rcar_vin_buffer, list)->vb;
+ list_del_init(to_buf_list(vbuf));
+ priv->queue_buf[slot] = vbuf;
+ phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
return 1;
@@ -771,6 +773,7 @@ static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct rcar_vin_priv *priv = ici->priv;
@@ -780,7 +783,7 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < size) {
dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
- vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
+ vb->index, vb2_plane_size(vb, 0), size);
goto error;
}
@@ -791,14 +794,14 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
spin_lock_irq(&priv->lock);
- list_add_tail(to_buf_list(vb), &priv->capture);
+ list_add_tail(to_buf_list(vbuf), &priv->capture);
rcar_vin_fill_hw_slot(priv);
/* If we weren't running, and have enough buffers, start capturing! */
if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
if (rcar_vin_setup(priv)) {
/* Submit error */
- list_del_init(to_buf_list(vb));
+ list_del_init(to_buf_list(vbuf));
spin_unlock_irq(&priv->lock);
goto error;
}
@@ -854,7 +857,7 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq)
for (i = 0; i < MAX_BUFFER_NUM; i++) {
if (priv->queue_buf[i]) {
- vb2_buffer_done(priv->queue_buf[i],
+ vb2_buffer_done(&priv->queue_buf[i]->vb2_buf,
VB2_BUF_STATE_ERROR);
priv->queue_buf[i] = NULL;
}
@@ -862,7 +865,7 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq)
list_for_each_safe(buf_head, tmp, &priv->capture) {
vb2_buffer_done(&list_entry(buf_head,
- struct rcar_vin_buffer, list)->vb,
+ struct rcar_vin_buffer, list)->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
list_del_init(buf_head);
}
@@ -907,10 +910,11 @@ static irqreturn_t rcar_vin_irq(int irq, void *data)
else
slot = 0;
- priv->queue_buf[slot]->v4l2_buf.field = priv->field;
- priv->queue_buf[slot]->v4l2_buf.sequence = priv->sequence++;
- v4l2_get_timestamp(&priv->queue_buf[slot]->v4l2_buf.timestamp);
- vb2_buffer_done(priv->queue_buf[slot], VB2_BUF_STATE_DONE);
+ priv->queue_buf[slot]->field = priv->field;
+ priv->queue_buf[slot]->sequence = priv->sequence++;
+ v4l2_get_timestamp(&priv->queue_buf[slot]->timestamp);
+ vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf,
+ VB2_BUF_STATE_DONE);
priv->queue_buf[slot] = NULL;
if (priv->state != STOPPING)
@@ -964,7 +968,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct rcar_vin_priv *priv = ici->priv;
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
int i;
/* disable capture, disable interrupts */
@@ -978,10 +982,10 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
/* make sure active buffer is cancelled */
spin_lock_irq(&priv->lock);
for (i = 0; i < MAX_BUFFER_NUM; i++) {
- vb = priv->queue_buf[i];
- if (vb) {
- list_del_init(to_buf_list(vb));
- vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+ vbuf = priv->queue_buf[i];
+ if (vbuf) {
+ list_del_init(to_buf_list(vbuf));
+ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);
}
}
spin_unlock_irq(&priv->lock);
@@ -1602,11 +1606,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd,
case V4L2_FIELD_INTERLACED:
/* Query for standard if not explicitly mentioned _TB/_BT */
ret = v4l2_subdev_call(sd, video, querystd, &std);
- if (ret < 0)
- std = V4L2_STD_625_50;
-
- field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB :
- V4L2_FIELD_INTERLACED_BT;
+ if (ret == -ENOIOCTLCMD) {
+ field = V4L2_FIELD_NONE;
+ } else if (ret < 0) {
+ return ret;
+ } else {
+ field = std & V4L2_STD_625_50 ?
+ V4L2_FIELD_INTERLACED_TB :
+ V4L2_FIELD_INTERLACED_BT;
+ }
break;
}
@@ -1846,8 +1854,6 @@ MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
#endif
static struct platform_device_id rcar_vin_id_table[] = {
- { "r8a7791-vin", RCAR_GEN2 },
- { "r8a7790-vin", RCAR_GEN2 },
{ "r8a7779-vin", RCAR_H1 },
{ "r8a7778-vin", RCAR_M1 },
{ "uPD35004-vin", RCAR_E1 },
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index efdeea4490e8..67a669d826b8 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -93,7 +93,7 @@
/* per video frame buffer */
struct sh_mobile_ceu_buffer {
- struct vb2_buffer vb; /* v4l buffer must be first */
+ struct vb2_v4l2_buffer vb; /* v4l buffer must be first */
struct list_head queue;
};
@@ -112,7 +112,7 @@ struct sh_mobile_ceu_dev {
spinlock_t lock; /* Protects video buffer lists */
struct list_head capture;
- struct vb2_buffer *active;
+ struct vb2_v4l2_buffer *active;
struct vb2_alloc_ctx *alloc_ctx;
struct sh_mobile_ceu_info *pdata;
@@ -152,9 +152,9 @@ struct sh_mobile_ceu_cam {
u32 code;
};
-static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb)
+static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_v4l2_buffer *vbuf)
{
- return container_of(vb, struct sh_mobile_ceu_buffer, vb);
+ return container_of(vbuf, struct sh_mobile_ceu_buffer, vb);
}
static void ceu_write(struct sh_mobile_ceu_dev *priv,
@@ -210,11 +210,13 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
* for the current frame format if required
*/
static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *count, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
- struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
+ const struct v4l2_format *fmt = parg;
+ struct soc_camera_device *icd = container_of(vq,
+ struct soc_camera_device, vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -334,7 +336,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
bottom2 = CDBCR;
}
- phys_addr_top = vb2_dma_contig_plane_dma_addr(pcdev->active, 0);
+ phys_addr_top =
+ vb2_dma_contig_plane_dma_addr(&pcdev->active->vb2_buf, 0);
switch (icd->current_fmt->host_fmt->fourcc) {
case V4L2_PIX_FMT_NV12:
@@ -369,7 +372,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
{
- struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf);
/* Added list head initialization on alloc */
WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
@@ -379,17 +383,19 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
{
- struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct soc_camera_device *icd = container_of(vb->vb2_queue,
+ struct soc_camera_device, vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
- struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+ struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf);
unsigned long size;
size = icd->sizeimage;
if (vb2_plane_size(vb, 0) < size) {
dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
- vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
+ vb->index, vb2_plane_size(vb, 0), size);
goto error;
}
@@ -416,7 +422,7 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
* we are not interested in the return value of
* sh_mobile_ceu_capture here.
*/
- pcdev->active = vb;
+ pcdev->active = vbuf;
sh_mobile_ceu_capture(pcdev);
}
spin_unlock_irq(&pcdev->lock);
@@ -429,14 +435,16 @@ error:
static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
{
- struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct soc_camera_device *icd = container_of(vb->vb2_queue,
+ struct soc_camera_device, vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+ struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
spin_lock_irq(&pcdev->lock);
- if (pcdev->active == vb) {
+ if (pcdev->active == vbuf) {
/* disable capture (release DMA buffer), reset */
ceu_write(pcdev, CAPSR, 1 << 16);
pcdev->active = NULL;
@@ -458,7 +466,9 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
{
- struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct soc_camera_device *icd = container_of(vb->vb2_queue,
+ struct soc_camera_device, vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -467,7 +477,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
pcdev->buf_total);
/* This is for locking debugging only */
- INIT_LIST_HEAD(&to_ceu_vb(vb)->queue);
+ INIT_LIST_HEAD(&to_ceu_vb(vbuf)->queue);
return 0;
}
@@ -504,17 +514,17 @@ static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
{
struct sh_mobile_ceu_dev *pcdev = data;
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
int ret;
spin_lock(&pcdev->lock);
- vb = pcdev->active;
- if (!vb)
+ vbuf = pcdev->active;
+ if (!vbuf)
/* Stale interrupt from a released buffer */
goto out;
- list_del_init(&to_ceu_vb(vb)->queue);
+ list_del_init(&to_ceu_vb(vbuf)->queue);
if (!list_empty(&pcdev->capture))
pcdev->active = &list_entry(pcdev->capture.next,
@@ -523,12 +533,13 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
pcdev->active = NULL;
ret = sh_mobile_ceu_capture(pcdev);
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+ v4l2_get_timestamp(&vbuf->timestamp);
if (!ret) {
- vb->v4l2_buf.field = pcdev->field;
- vb->v4l2_buf.sequence = pcdev->sequence++;
+ vbuf->field = pcdev->field;
+ vbuf->sequence = pcdev->sequence++;
}
- vb2_buffer_done(vb, ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&vbuf->vb2_buf,
+ ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
out:
spin_unlock(&pcdev->lock);
@@ -633,7 +644,7 @@ static void sh_mobile_ceu_clock_stop(struct soc_camera_host *ici)
spin_lock_irq(&pcdev->lock);
if (pcdev->active) {
list_del_init(&to_ceu_vb(pcdev->active)->queue);
- vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&pcdev->active->vb2_buf, VB2_BUF_STATE_ERROR);
pcdev->active = NULL;
}
spin_unlock_irq(&pcdev->lock);
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 9087fed586fb..dc98122e78dc 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -38,7 +38,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-of.h>
#include <media/videobuf-core.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
@@ -1631,7 +1631,7 @@ static int soc_of_bind(struct soc_camera_host *ici,
struct soc_camera_async_client *sasc;
struct soc_of_info *info;
struct i2c_client *client;
- char clk_name[V4L2_SUBDEV_NAME_SIZE];
+ char clk_name[V4L2_SUBDEV_NAME_SIZE + 32];
int ret;
/* allocate a new subdev and add match info to it */
diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
index df61355b46f1..a0d267e017f6 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
@@ -180,7 +180,7 @@ static struct bdisp_frame *ctx_get_frame(struct bdisp_ctx *ctx,
static void bdisp_job_finish(struct bdisp_ctx *ctx, int vb_state)
{
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
if (WARN(!ctx || !ctx->fh.m2m_ctx, "Null hardware context\n"))
return;
@@ -191,10 +191,10 @@ static void bdisp_job_finish(struct bdisp_ctx *ctx, int vb_state)
dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
if (src_vb && dst_vb) {
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
- dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode;
- dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst_vb->v4l2_buf.flags |= src_vb->v4l2_buf.flags &
+ dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->timecode = src_vb->timecode;
+ dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->flags |= src_vb->flags &
V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
v4l2_m2m_buf_done(src_vb, vb_state);
@@ -281,23 +281,23 @@ static int bdisp_get_addr(struct bdisp_ctx *ctx, struct vb2_buffer *vb,
static int bdisp_get_bufs(struct bdisp_ctx *ctx)
{
struct bdisp_frame *src, *dst;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
int ret;
src = &ctx->src;
dst = &ctx->dst;
src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- ret = bdisp_get_addr(ctx, src_vb, src, src->paddr);
+ ret = bdisp_get_addr(ctx, &src_vb->vb2_buf, src, src->paddr);
if (ret)
return ret;
dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- ret = bdisp_get_addr(ctx, dst_vb, dst, dst->paddr);
+ ret = bdisp_get_addr(ctx, &dst_vb->vb2_buf, dst, dst->paddr);
if (ret)
return ret;
- dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
+ dst_vb->timestamp = src_vb->timestamp;
return 0;
}
@@ -438,10 +438,11 @@ static void bdisp_ctrls_delete(struct bdisp_ctx *ctx)
}
static int bdisp_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nb_buf, unsigned int *nb_planes,
unsigned int sizes[], void *allocators[])
{
+ const struct v4l2_format *fmt = parg;
struct bdisp_ctx *ctx = vb2_get_drv_priv(vq);
struct bdisp_frame *frame = ctx_get_frame(ctx, vq->type);
@@ -483,6 +484,7 @@ static int bdisp_buf_prepare(struct vb2_buffer *vb)
static void bdisp_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bdisp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
/* return to V4L2 any 0-size buffer so it can be dequeued by user */
@@ -493,13 +495,13 @@ static void bdisp_buf_queue(struct vb2_buffer *vb)
}
if (ctx->fh.m2m_ctx)
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
static int bdisp_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct bdisp_ctx *ctx = q->drv_priv;
- struct vb2_buffer *buf;
+ struct vb2_v4l2_buffer *buf;
int ret = pm_runtime_get_sync(ctx->bdisp_dev->dev);
if (ret < 0) {
diff --git a/drivers/media/platform/sti/c8sectpfe/Kconfig b/drivers/media/platform/sti/c8sectpfe/Kconfig
index 641ad8f34956..7420a50572d3 100644
--- a/drivers/media/platform/sti/c8sectpfe/Kconfig
+++ b/drivers/media/platform/sti/c8sectpfe/Kconfig
@@ -3,7 +3,6 @@ config DVB_C8SECTPFE
depends on PINCTRL && DVB_CORE && I2C
depends on ARCH_STI || ARCH_MULTIPLATFORM || COMPILE_TEST
select FW_LOADER
- select FW_LOADER_USER_HELPER_FALLBACK
select DEBUG_FS
select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
index 486aef50d99b..8490a65ae1c6 100644
--- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
+++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
@@ -1084,10 +1084,10 @@ static void load_dmem_segment(struct c8sectpfei *fei, Elf32_Phdr *phdr,
seg_num, phdr->p_paddr, phdr->p_filesz,
dst, phdr->p_memsz);
- memcpy((void __iomem *)dst, (void *)fw->data + phdr->p_offset,
+ memcpy((void __force *)dst, (void *)fw->data + phdr->p_offset,
phdr->p_filesz);
- memset((void __iomem *)dst + phdr->p_filesz, 0,
+ memset((void __force *)dst + phdr->p_filesz, 0,
phdr->p_memsz - phdr->p_filesz);
}
@@ -1097,7 +1097,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
Elf32_Ehdr *ehdr;
Elf32_Phdr *phdr;
u8 __iomem *dst;
- int err, i;
+ int err = 0, i;
if (!fw || !context)
return -EINVAL;
@@ -1106,7 +1106,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
/* go through the available ELF segments */
- for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
/* Only consider LOAD segments */
if (phdr->p_type != PT_LOAD)
@@ -1192,7 +1192,6 @@ err:
static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
{
- int ret;
int err;
dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
@@ -1207,7 +1206,7 @@ static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
if (err) {
dev_err(fei->dev, "request_firmware_nowait err: %d.\n", err);
complete_all(&fei->fw_ack);
- return ret;
+ return err;
}
return 0;
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index c44760b705da..de24effd984f 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -40,7 +40,7 @@
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "vpdma.h"
@@ -384,8 +384,8 @@ struct vpe_ctx {
unsigned int bufs_completed; /* bufs done in this batch */
struct vpe_q_data q_data[2]; /* src & dst queue data */
- struct vb2_buffer *src_vbs[VPE_MAX_SRC_BUFS];
- struct vb2_buffer *dst_vb;
+ struct vb2_v4l2_buffer *src_vbs[VPE_MAX_SRC_BUFS];
+ struct vb2_v4l2_buffer *dst_vb;
dma_addr_t mv_buf_dma[2]; /* dma addrs of motion vector in/out bufs */
void *mv_buf[2]; /* virtual addrs of motion vector bufs */
@@ -988,7 +988,7 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)
{
struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST];
const struct vpe_port_data *p_data = &port_data[port];
- struct vb2_buffer *vb = ctx->dst_vb;
+ struct vb2_buffer *vb = &ctx->dst_vb->vb2_buf;
struct vpe_fmt *fmt = q_data->fmt;
const struct vpdma_data_format *vpdma_fmt;
int mv_buf_selector = !ctx->src_mv_buf_selector;
@@ -1025,11 +1025,12 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)
{
struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC];
const struct vpe_port_data *p_data = &port_data[port];
- struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index];
+ struct vb2_buffer *vb = &ctx->src_vbs[p_data->vb_index]->vb2_buf;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vpe_fmt *fmt = q_data->fmt;
const struct vpdma_data_format *vpdma_fmt;
int mv_buf_selector = ctx->src_mv_buf_selector;
- int field = vb->v4l2_buf.field == V4L2_FIELD_BOTTOM;
+ int field = vbuf->field == V4L2_FIELD_BOTTOM;
int frame_width, frame_height;
dma_addr_t dma_addr;
u32 flags = 0;
@@ -1222,8 +1223,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
struct vpe_dev *dev = (struct vpe_dev *)data;
struct vpe_ctx *ctx;
struct vpe_q_data *d_q_data;
- struct vb2_buffer *s_vb, *d_vb;
- struct v4l2_buffer *s_buf, *d_buf;
+ struct vb2_v4l2_buffer *s_vb, *d_vb;
unsigned long flags;
u32 irqst0, irqst1;
@@ -1286,20 +1286,18 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
s_vb = ctx->src_vbs[0];
d_vb = ctx->dst_vb;
- s_buf = &s_vb->v4l2_buf;
- d_buf = &d_vb->v4l2_buf;
- d_buf->flags = s_buf->flags;
+ d_vb->flags = s_vb->flags;
+ d_vb->timestamp = s_vb->timestamp;
- d_buf->timestamp = s_buf->timestamp;
- if (s_buf->flags & V4L2_BUF_FLAG_TIMECODE)
- d_buf->timecode = s_buf->timecode;
+ if (s_vb->flags & V4L2_BUF_FLAG_TIMECODE)
+ d_vb->timecode = s_vb->timecode;
- d_buf->sequence = ctx->sequence;
+ d_vb->sequence = ctx->sequence;
d_q_data = &ctx->q_data[Q_DATA_DST];
if (d_q_data->flags & Q_DATA_INTERLACED) {
- d_buf->field = ctx->field;
+ d_vb->field = ctx->field;
if (ctx->field == V4L2_FIELD_BOTTOM) {
ctx->sequence++;
ctx->field = V4L2_FIELD_TOP;
@@ -1308,7 +1306,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
ctx->field = V4L2_FIELD_BOTTOM;
}
} else {
- d_buf->field = V4L2_FIELD_NONE;
+ d_vb->field = V4L2_FIELD_NONE;
ctx->sequence++;
}
@@ -1798,7 +1796,7 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
* Queue operations
*/
static int vpe_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -1825,6 +1823,7 @@ static int vpe_queue_setup(struct vb2_queue *vq,
static int vpe_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct vpe_q_data *q_data;
int i, num_planes;
@@ -1836,10 +1835,10 @@ static int vpe_buf_prepare(struct vb2_buffer *vb)
if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
if (!(q_data->flags & Q_DATA_INTERLACED)) {
- vb->v4l2_buf.field = V4L2_FIELD_NONE;
+ vbuf->field = V4L2_FIELD_NONE;
} else {
- if (vb->v4l2_buf.field != V4L2_FIELD_TOP &&
- vb->v4l2_buf.field != V4L2_FIELD_BOTTOM)
+ if (vbuf->field != V4L2_FIELD_TOP &&
+ vbuf->field != V4L2_FIELD_BOTTOM)
return -EINVAL;
}
}
@@ -1862,9 +1861,10 @@ static int vpe_buf_prepare(struct vb2_buffer *vb)
static void vpe_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
static int vpe_start_streaming(struct vb2_queue *q, unsigned int count)
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 295fde5fdb75..e18fb9f9ed2f 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -197,8 +197,8 @@ static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx,
static int device_process(struct vim2m_ctx *ctx,
- struct vb2_buffer *in_vb,
- struct vb2_buffer *out_vb)
+ struct vb2_v4l2_buffer *in_vb,
+ struct vb2_v4l2_buffer *out_vb)
{
struct vim2m_dev *dev = ctx->dev;
struct vim2m_q_data *q_data;
@@ -213,15 +213,16 @@ static int device_process(struct vim2m_ctx *ctx,
height = q_data->height;
bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
- p_in = vb2_plane_vaddr(in_vb, 0);
- p_out = vb2_plane_vaddr(out_vb, 0);
+ p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
+ p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
if (!p_in || !p_out) {
v4l2_err(&dev->v4l2_dev,
"Acquiring kernel pointers to buffers failed\n");
return -EFAULT;
}
- if (vb2_plane_size(in_vb, 0) > vb2_plane_size(out_vb, 0)) {
+ if (vb2_plane_size(&in_vb->vb2_buf, 0) >
+ vb2_plane_size(&out_vb->vb2_buf, 0)) {
v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
return -EINVAL;
}
@@ -231,16 +232,15 @@ static int device_process(struct vim2m_ctx *ctx,
bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
w = 0;
- out_vb->v4l2_buf.sequence = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
- in_vb->v4l2_buf.sequence = q_data->sequence++;
- memcpy(&out_vb->v4l2_buf.timestamp,
- &in_vb->v4l2_buf.timestamp,
- sizeof(struct timeval));
- if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE)
- memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode,
- sizeof(struct v4l2_timecode));
- out_vb->v4l2_buf.field = in_vb->v4l2_buf.field;
- out_vb->v4l2_buf.flags = in_vb->v4l2_buf.flags &
+ out_vb->sequence =
+ get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
+ in_vb->sequence = q_data->sequence++;
+ out_vb->timestamp = in_vb->timestamp;
+
+ if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
+ out_vb->timecode = in_vb->timecode;
+ out_vb->field = in_vb->field;
+ out_vb->flags = in_vb->flags &
(V4L2_BUF_FLAG_TIMECODE |
V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME |
@@ -374,7 +374,7 @@ static void device_run(void *priv)
{
struct vim2m_ctx *ctx = priv;
struct vim2m_dev *dev = ctx->dev;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -389,7 +389,7 @@ static void device_isr(unsigned long priv)
{
struct vim2m_dev *vim2m_dev = (struct vim2m_dev *)priv;
struct vim2m_ctx *curr_ctx;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
unsigned long flags;
curr_ctx = v4l2_m2m_get_curr_priv(vim2m_dev->m2m_dev);
@@ -710,10 +710,11 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
*/
static int vim2m_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
struct vim2m_q_data *q_data;
unsigned int size, count = *nbuffers;
@@ -747,6 +748,7 @@ static int vim2m_queue_setup(struct vb2_queue *vq,
static int vim2m_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct vim2m_q_data *q_data;
@@ -754,9 +756,9 @@ static int vim2m_buf_prepare(struct vb2_buffer *vb)
q_data = get_q_data(ctx, vb->vb2_queue->type);
if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
- if (vb->v4l2_buf.field == V4L2_FIELD_ANY)
- vb->v4l2_buf.field = V4L2_FIELD_NONE;
- if (vb->v4l2_buf.field != V4L2_FIELD_NONE) {
+ if (vbuf->field == V4L2_FIELD_ANY)
+ vbuf->field = V4L2_FIELD_NONE;
+ if (vbuf->field != V4L2_FIELD_NONE) {
dprintk(ctx->dev, "%s field isn't supported\n",
__func__);
return -EINVAL;
@@ -776,9 +778,10 @@ static int vim2m_buf_prepare(struct vb2_buffer *vb)
static void vim2m_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
static int vim2m_start_streaming(struct vb2_queue *q, unsigned count)
@@ -793,18 +796,18 @@ static int vim2m_start_streaming(struct vb2_queue *q, unsigned count)
static void vim2m_stop_streaming(struct vb2_queue *q)
{
struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
- struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
unsigned long flags;
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
- vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
else
- vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- if (vb == NULL)
+ vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ if (vbuf == NULL)
return;
spin_lock_irqsave(&ctx->dev->irqlock, flags);
- v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
}
}
diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig
index c3090932f06d..0885e93ad436 100644
--- a/drivers/media/platform/vivid/Kconfig
+++ b/drivers/media/platform/vivid/Kconfig
@@ -20,3 +20,11 @@ config VIDEO_VIVID
Say Y here if you want to test video apps or debug V4L devices.
When in doubt, say N.
+
+config VIDEO_VIVID_MAX_DEVS
+ int "Maximum number of devices"
+ depends on VIDEO_VIVID
+ default "64"
+ ---help---
+ This allows you to specify the maximum number of devices supported
+ by the vivid driver.
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index a047b4716741..ec125becb7af 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -51,7 +51,7 @@
#define VIVID_MODULE_NAME "vivid"
/* The maximum number of vivid devices */
-#define VIVID_MAX_DEVS 64
+#define VIVID_MAX_DEVS CONFIG_VIDEO_VIVID_MAX_DEVS
MODULE_DESCRIPTION("Virtual Video Test Driver");
MODULE_AUTHOR("Hans Verkuil");
@@ -1341,8 +1341,11 @@ static int vivid_remove(struct platform_device *pdev)
struct vivid_dev *dev;
unsigned i;
- for (i = 0; vivid_devs[i]; i++) {
+
+ for (i = 0; i < n_devs; i++) {
dev = vivid_devs[i];
+ if (!dev)
+ continue;
if (dev->has_vid_cap) {
v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index c72349c83fab..55b304a705d5 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -21,7 +21,7 @@
#define _VIVID_CORE_H_
#include <linux/fb.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ctrls.h>
@@ -93,7 +93,7 @@ extern struct vivid_fmt vivid_formats[];
/* buffer for one video frame */
struct vivid_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -123,6 +123,7 @@ enum vivid_colorspace {
VIVID_CS_SRGB,
VIVID_CS_ADOBERGB,
VIVID_CS_2020,
+ VIVID_CS_DCI_P3,
VIVID_CS_240M,
VIVID_CS_SYS_M,
VIVID_CS_SYS_BG,
@@ -451,6 +452,7 @@ struct vivid_dev {
unsigned sdr_buffersize;
unsigned sdr_adc_freq;
unsigned sdr_fm_freq;
+ unsigned sdr_fm_deviation;
int sdr_fixp_src_phase;
int sdr_fixp_mod_phase;
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 339c8b7e53c8..f41ac0b01fec 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -99,6 +99,7 @@
#define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94)
+#define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110)
/* General User Controls */
@@ -342,6 +343,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
V4L2_COLORSPACE_SRGB,
V4L2_COLORSPACE_ADOBERGB,
V4L2_COLORSPACE_BT2020,
+ V4L2_COLORSPACE_DCI_P3,
V4L2_COLORSPACE_SMPTE240M,
V4L2_COLORSPACE_470_SYSTEM_M,
V4L2_COLORSPACE_470_SYSTEM_BG,
@@ -548,7 +550,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_osd_mode = {
.id = VIVID_CID_OSD_TEXT_MODE,
.name = "OSD Text Mode",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 2,
+ .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
.qmenu = vivid_ctrl_osd_mode_strings,
};
@@ -640,7 +642,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = {
.id = VIVID_CID_TSTAMP_SRC,
.name = "Timestamp Source",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 1,
+ .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
.qmenu = vivid_ctrl_tstamp_src_strings,
};
@@ -701,6 +703,7 @@ static const char * const vivid_ctrl_colorspace_strings[] = {
"sRGB",
"AdobeRGB",
"BT.2020",
+ "DCI-P3",
"SMPTE 240M",
"470 System M",
"470 System BG",
@@ -712,7 +715,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_colorspace = {
.id = VIVID_CID_COLORSPACE,
.name = "Colorspace",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 7,
+ .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
.def = 2,
.qmenu = vivid_ctrl_colorspace_strings,
};
@@ -724,6 +727,8 @@ static const char * const vivid_ctrl_xfer_func_strings[] = {
"AdobeRGB",
"SMPTE 240M",
"None",
+ "DCI-P3",
+ "SMPTE 2084",
NULL,
};
@@ -732,7 +737,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_xfer_func = {
.id = VIVID_CID_XFER_FUNC,
.name = "Transfer Function",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 5,
+ .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
.qmenu = vivid_ctrl_xfer_func_strings,
};
@@ -754,7 +759,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
.id = VIVID_CID_YCBCR_ENC,
.name = "Y'CbCr Encoding",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 8,
+ .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
.qmenu = vivid_ctrl_ycbcr_enc_strings,
};
@@ -770,7 +775,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
.id = VIVID_CID_QUANTIZATION,
.name = "Quantization",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 2,
+ .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
.qmenu = vivid_ctrl_quantization_strings,
};
@@ -1088,7 +1093,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
.id = VIVID_CID_STD_SIGNAL_MODE,
.name = "Standard Signal Mode",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 5,
+ .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
.menu_skip_mask = 1 << 3,
.qmenu = vivid_ctrl_std_signal_mode_strings,
};
@@ -1257,6 +1262,36 @@ static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
};
+/* SDR Capture Controls */
+
+static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
+
+ switch (ctrl->id) {
+ case VIVID_CID_SDR_CAP_FM_DEVIATION:
+ dev->sdr_fm_deviation = ctrl->val;
+ break;
+ }
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
+ .s_ctrl = vivid_sdr_cap_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
+ .ops = &vivid_sdr_cap_ctrl_ops,
+ .id = VIVID_CID_SDR_CAP_FM_DEVIATION,
+ .name = "FM Deviation",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 100,
+ .max = 200000,
+ .def = 75000,
+ .step = 1,
+};
+
+
static const struct v4l2_ctrl_config vivid_ctrl_class = {
.ops = &vivid_user_gen_ctrl_ops,
.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
@@ -1314,7 +1349,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
v4l2_ctrl_handler_init(hdl_radio_tx, 17);
v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_sdr_cap, 18);
+ v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
/* User Controls */
@@ -1545,6 +1580,10 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
&vivid_radio_tx_ctrl_ops,
V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
}
+ if (dev->has_sdr_cap) {
+ v4l2_ctrl_new_custom(hdl_sdr_cap,
+ &vivid_ctrl_sdr_cap_fm_deviation, NULL);
+ }
if (hdl_user_gen->error)
return hdl_user_gen->error;
if (hdl_user_vid->error)
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 1727f5453f0b..83cc6d3b4784 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -236,8 +236,8 @@ static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
void *vbuf;
if (p == 0 || tpg_g_buffers(tpg) > 1)
- return vb2_plane_vaddr(&buf->vb, p);
- vbuf = vb2_plane_vaddr(&buf->vb, 0);
+ return vb2_plane_vaddr(&buf->vb.vb2_buf, p);
+ vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
for (i = 0; i < p; i++)
vbuf += bpl[i] * h / tpg->vdownsampling[i];
return vbuf;
@@ -246,7 +246,7 @@ static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
struct vivid_buffer *vid_cap_buf)
{
- bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index];
+ bool blank = dev->must_blank[vid_cap_buf->vb.vb2_buf.index];
struct tpg_data *tpg = &dev->tpg;
struct vivid_buffer *vid_out_buf = NULL;
unsigned vdiv = dev->fmt_out->vdownsampling[p];
@@ -283,12 +283,12 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
if (vid_out_buf == NULL)
return -ENODATA;
- vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field;
+ vid_cap_buf->vb.field = vid_out_buf->vb.field;
voutbuf = plane_vaddr(tpg, vid_out_buf, p,
dev->bytesperline_out, dev->fmt_out_rect.height);
if (p < dev->fmt_out->buffers)
- voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset;
+ voutbuf += vid_out_buf->vb.vb2_buf.planes[p].data_offset;
voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) +
(dev->loop_vid_out.top / vdiv) * stride_out;
vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) +
@@ -429,17 +429,19 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
bool is_loop = false;
if (dev->loop_video && dev->can_loop_video &&
- ((vivid_is_svid_cap(dev) && !VIVID_INVALID_SIGNAL(dev->std_signal_mode)) ||
- (vivid_is_hdmi_cap(dev) && !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode))))
+ ((vivid_is_svid_cap(dev) &&
+ !VIVID_INVALID_SIGNAL(dev->std_signal_mode)) ||
+ (vivid_is_hdmi_cap(dev) &&
+ !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode))))
is_loop = true;
- buf->vb.v4l2_buf.sequence = dev->vid_cap_seq_count;
+ buf->vb.sequence = dev->vid_cap_seq_count;
/*
* Take the timestamp now if the timestamp source is set to
* "Start of Exposure".
*/
if (dev->tstamp_src_is_soe)
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&buf->vb.timestamp);
if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
/*
* 60 Hz standards start with the bottom field, 50 Hz standards
@@ -447,19 +449,19 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
* then the field is TOP for 50 Hz and BOTTOM for 60 Hz
* standards.
*/
- buf->vb.v4l2_buf.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
+ buf->vb.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
/*
* The sequence counter counts frames, not fields. So divide
* by two.
*/
- buf->vb.v4l2_buf.sequence /= 2;
+ buf->vb.sequence /= 2;
} else {
- buf->vb.v4l2_buf.field = dev->field_cap;
+ buf->vb.field = dev->field_cap;
}
- tpg_s_field(tpg, buf->vb.v4l2_buf.field,
+ tpg_s_field(tpg, buf->vb.field,
dev->field_cap == V4L2_FIELD_ALTERNATE);
- tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
+ tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.vb2_buf.index]);
vivid_precalc_copy_rects(dev);
@@ -479,13 +481,16 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
}
tpg_calc_text_basep(tpg, basep, p, vbuf);
if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
- tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), p, vbuf);
+ tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev),
+ p, vbuf);
}
- dev->must_blank[buf->vb.v4l2_buf.index] = false;
+ dev->must_blank[buf->vb.vb2_buf.index] = false;
/* Updates stream time, only update at the start of a new frame. */
- if (dev->field_cap != V4L2_FIELD_ALTERNATE || (buf->vb.v4l2_buf.sequence & 1) == 0)
- dev->ms_vid_cap = jiffies_to_msecs(jiffies - dev->jiffies_vid_cap);
+ if (dev->field_cap != V4L2_FIELD_ALTERNATE ||
+ (buf->vb.sequence & 1) == 0)
+ dev->ms_vid_cap =
+ jiffies_to_msecs(jiffies - dev->jiffies_vid_cap);
ms = dev->ms_vid_cap;
if (dev->osd_mode <= 1) {
@@ -494,9 +499,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
(ms / (60 * 1000)) % 60,
(ms / 1000) % 60,
ms % 1000,
- buf->vb.v4l2_buf.sequence,
+ buf->vb.sequence,
(dev->field_cap == V4L2_FIELD_ALTERNATE) ?
- (buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ?
+ (buf->vb.field == V4L2_FIELD_TOP ?
" top" : " bottom") : "");
tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
}
@@ -553,8 +558,8 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
* the timestamp now.
*/
if (!dev->tstamp_src_is_soe)
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
}
/*
@@ -600,7 +605,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
struct tpg_data *tpg = &dev->tpg;
unsigned pixsize = tpg_g_twopixelsize(tpg, 0) / 2;
void *vbase = dev->fb_vbase_cap;
- void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+ void *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
unsigned img_width = dev->compose_cap.width;
unsigned img_height = dev->compose_cap.height;
unsigned stride = tpg->bytesperline[0];
@@ -616,7 +621,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
return;
if ((dev->overlay_cap_field == V4L2_FIELD_TOP ||
dev->overlay_cap_field == V4L2_FIELD_BOTTOM) &&
- dev->overlay_cap_field != buf->vb.v4l2_buf.field)
+ dev->overlay_cap_field != buf->vb.field)
return;
vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride;
@@ -699,17 +704,17 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs)
/* Fill buffer */
vivid_fillbuff(dev, vid_cap_buf);
dprintk(dev, 1, "filled buffer %d\n",
- vid_cap_buf->vb.v4l2_buf.index);
+ vid_cap_buf->vb.vb2_buf.index);
/* Handle overlay */
if (dev->overlay_cap_owner && dev->fb_cap.base &&
- dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
+ dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
vivid_overlay(dev, vid_cap_buf);
- vb2_buffer_done(&vid_cap_buf->vb, dev->dqbuf_error ?
+ vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vid_cap buffer %d done\n",
- vid_cap_buf->vb.v4l2_buf.index);
+ vid_cap_buf->vb.vb2_buf.index);
}
if (vbi_cap_buf) {
@@ -717,10 +722,10 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs)
vivid_sliced_vbi_cap_process(dev, vbi_cap_buf);
else
vivid_raw_vbi_cap_process(dev, vbi_cap_buf);
- vb2_buffer_done(&vbi_cap_buf->vb, dev->dqbuf_error ?
+ vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_cap %d done\n",
- vbi_cap_buf->vb.v4l2_buf.index);
+ vbi_cap_buf->vb.vb2_buf.index);
}
dev->dqbuf_error = false;
@@ -884,9 +889,9 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
buf = list_entry(dev->vid_cap_active.next,
struct vivid_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vid_cap buffer %d done\n",
- buf->vb.v4l2_buf.index);
+ buf->vb.vb2_buf.index);
}
}
@@ -897,9 +902,9 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
buf = list_entry(dev->vbi_cap_active.next,
struct vivid_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vbi_cap buffer %d done\n",
- buf->vb.v4l2_buf.index);
+ buf->vb.vb2_buf.index);
}
}
diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
index d9f36ccd7efb..c2c46dcdbe95 100644
--- a/drivers/media/platform/vivid/vivid-kthread-out.c
+++ b/drivers/media/platform/vivid/vivid-kthread-out.c
@@ -87,33 +87,33 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
return;
if (vid_out_buf) {
- vid_out_buf->vb.v4l2_buf.sequence = dev->vid_out_seq_count;
+ vid_out_buf->vb.sequence = dev->vid_out_seq_count;
if (dev->field_out == V4L2_FIELD_ALTERNATE) {
/*
- * The sequence counter counts frames, not fields. So divide
- * by two.
+ * The sequence counter counts frames, not fields.
+ * So divide by two.
*/
- vid_out_buf->vb.v4l2_buf.sequence /= 2;
+ vid_out_buf->vb.sequence /= 2;
}
- v4l2_get_timestamp(&vid_out_buf->vb.v4l2_buf.timestamp);
- vid_out_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
- vb2_buffer_done(&vid_out_buf->vb, dev->dqbuf_error ?
+ v4l2_get_timestamp(&vid_out_buf->vb.timestamp);
+ vid_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vid_out buffer %d done\n",
- vid_out_buf->vb.v4l2_buf.index);
+ vid_out_buf->vb.vb2_buf.index);
}
if (vbi_out_buf) {
if (dev->stream_sliced_vbi_out)
vivid_sliced_vbi_out_process(dev, vbi_out_buf);
- vbi_out_buf->vb.v4l2_buf.sequence = dev->vbi_out_seq_count;
- v4l2_get_timestamp(&vbi_out_buf->vb.v4l2_buf.timestamp);
- vbi_out_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
- vb2_buffer_done(&vbi_out_buf->vb, dev->dqbuf_error ?
+ vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
+ v4l2_get_timestamp(&vbi_out_buf->vb.timestamp);
+ vbi_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_out buffer %d done\n",
- vbi_out_buf->vb.v4l2_buf.index);
+ vbi_out_buf->vb.vb2_buf.index);
}
dev->dqbuf_error = false;
}
@@ -274,9 +274,9 @@ void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
buf = list_entry(dev->vid_out_active.next,
struct vivid_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vid_out buffer %d done\n",
- buf->vb.v4l2_buf.index);
+ buf->vb.vb2_buf.index);
}
}
@@ -287,9 +287,9 @@ void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
buf = list_entry(dev->vbi_out_active.next,
struct vivid_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vbi_out buffer %d done\n",
- buf->vb.v4l2_buf.index);
+ buf->vb.vb2_buf.index);
}
}
diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c
index 084d346fb4c4..e15eef6a94e5 100644
--- a/drivers/media/platform/vivid/vivid-osd.c
+++ b/drivers/media/platform/vivid/vivid-osd.c
@@ -85,6 +85,7 @@ static int vivid_fb_ioctl(struct fb_info *info, unsigned cmd, unsigned long arg)
case FBIOGET_VBLANK: {
struct fb_vblank vblank;
+ memset(&vblank, 0, sizeof(vblank));
vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT |
FB_VBLANK_HAVE_VSYNC;
vblank.count = 0;
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index d2f2188a0efe..082c401764ce 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
+#include <linux/math64.h>
#include <linux/videodev2.h>
#include <linux/v4l2-dv-timings.h>
#include <media/v4l2-common.h>
@@ -40,7 +41,7 @@ struct vivid_format {
};
/* format descriptions for capture and preview */
-static struct vivid_format formats[] = {
+static const struct vivid_format formats[] = {
{
.pixelformat = V4L2_SDR_FMT_CU8,
.buffersize = SDR_CAP_SAMPLES_PER_BUF * 2,
@@ -114,11 +115,11 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
spin_unlock(&dev->slock);
if (sdr_cap_buf) {
- sdr_cap_buf->vb.v4l2_buf.sequence = dev->sdr_cap_seq_count;
+ sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
vivid_sdr_cap_process(dev, sdr_cap_buf);
- v4l2_get_timestamp(&sdr_cap_buf->vb.v4l2_buf.timestamp);
- sdr_cap_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
- vb2_buffer_done(&sdr_cap_buf->vb, dev->dqbuf_error ?
+ v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp);
+ sdr_cap_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dev->dqbuf_error = false;
}
@@ -161,7 +162,8 @@ static int vivid_thread_sdr_cap(void *data)
/* Calculate the number of jiffies since we started streaming */
jiffies_since_start = cur_jiffies - dev->jiffies_sdr_cap;
/* Get the number of buffers streamed since the start */
- buffers_since_start = (u64)jiffies_since_start * dev->sdr_adc_freq +
+ buffers_since_start =
+ (u64)jiffies_since_start * dev->sdr_adc_freq +
(HZ * SDR_CAP_SAMPLES_PER_BUF) / 2;
do_div(buffers_since_start, HZ * SDR_CAP_SAMPLES_PER_BUF);
@@ -176,7 +178,8 @@ static int vivid_thread_sdr_cap(void *data)
dev->sdr_cap_seq_offset = buffers_since_start;
buffers_since_start = 0;
}
- dev->sdr_cap_seq_count = buffers_since_start + dev->sdr_cap_seq_offset;
+ dev->sdr_cap_seq_count =
+ buffers_since_start + dev->sdr_cap_seq_offset;
vivid_thread_sdr_cap_tick(dev);
mutex_unlock(&dev->mutex);
@@ -210,7 +213,7 @@ static int vivid_thread_sdr_cap(void *data)
return 0;
}
-static int sdr_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int sdr_cap_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned *nbuffers, unsigned *nplanes,
unsigned sizes[], void *alloc_ctxs[])
{
@@ -247,8 +250,9 @@ static int sdr_cap_buf_prepare(struct vb2_buffer *vb)
static void sdr_cap_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb);
+ struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
dprintk(dev, 1, "%s\n", __func__);
@@ -282,7 +286,8 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count)
list_for_each_entry_safe(buf, tmp, &dev->sdr_cap_active, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
}
return err;
@@ -299,9 +304,10 @@ static void sdr_cap_stop_streaming(struct vb2_queue *vq)
while (!list_empty(&dev->sdr_cap_active)) {
struct vivid_buffer *buf;
- buf = list_entry(dev->sdr_cap_active.next, struct vivid_buffer, list);
+ buf = list_entry(dev->sdr_cap_active.next,
+ struct vivid_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
/* shutdown control thread */
@@ -321,7 +327,8 @@ const struct vb2_ops vivid_sdr_cap_qops = {
.wait_finish = vb2_ops_wait_finish,
};
-int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band)
+int vivid_sdr_enum_freq_bands(struct file *file, void *fh,
+ struct v4l2_frequency_band *band)
{
switch (band->tuner) {
case 0:
@@ -339,7 +346,8 @@ int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency
}
}
-int vivid_sdr_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+int vivid_sdr_g_frequency(struct file *file, void *fh,
+ struct v4l2_frequency *vf)
{
struct vivid_dev *dev = video_drvdata(file);
@@ -357,7 +365,8 @@ int vivid_sdr_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf
}
}
-int vivid_sdr_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
+int vivid_sdr_s_frequency(struct file *file, void *fh,
+ const struct v4l2_frequency *vf)
{
struct vivid_dev *dev = video_drvdata(file);
unsigned freq = vf->frequency;
@@ -403,14 +412,16 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
case 0:
strlcpy(vt->name, "ADC", sizeof(vt->name));
vt->type = V4L2_TUNER_ADC;
- vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ vt->capability =
+ V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
vt->rangelow = bands_adc[0].rangelow;
vt->rangehigh = bands_adc[2].rangehigh;
return 0;
case 1:
strlcpy(vt->name, "RF", sizeof(vt->name));
vt->type = V4L2_TUNER_RF;
- vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ vt->capability =
+ V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
vt->rangelow = bands_fm[0].rangelow;
vt->rangehigh = bands_fm[0].rangehigh;
return 0;
@@ -488,47 +499,42 @@ int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f)
#define FIXP_N (15)
#define FIXP_FRAC (1 << FIXP_N)
#define FIXP_2PI ((int)(2 * 3.141592653589 * FIXP_FRAC))
+#define M_100000PI (3.14159 * 100000)
void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
{
- u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+ u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
unsigned long i;
- unsigned long plane_size = vb2_plane_size(&buf->vb, 0);
+ unsigned long plane_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+ s64 s64tmp;
s32 src_phase_step;
s32 mod_phase_step;
s32 fixp_i;
s32 fixp_q;
- /*
- * TODO: Generated beep tone goes very crackly when sample rate is
- * increased to ~1Msps or more. That is because of huge rounding error
- * of phase angle caused by used cosine implementation.
- */
-
/* calculate phase step */
#define BEEP_FREQ 1000 /* 1kHz beep */
src_phase_step = DIV_ROUND_CLOSEST(FIXP_2PI * BEEP_FREQ,
- dev->sdr_adc_freq);
+ dev->sdr_adc_freq);
for (i = 0; i < plane_size; i += 2) {
mod_phase_step = fixp_cos32_rad(dev->sdr_fixp_src_phase,
FIXP_2PI) >> (31 - FIXP_N);
dev->sdr_fixp_src_phase += src_phase_step;
- dev->sdr_fixp_mod_phase += mod_phase_step / 4;
+ s64tmp = (s64) mod_phase_step * dev->sdr_fm_deviation;
+ dev->sdr_fixp_mod_phase += div_s64(s64tmp, M_100000PI);
/*
- * Transfer phases to [0 / 2xPI] in order to avoid variable
+ * Transfer phase angle to [0, 2xPI] in order to avoid variable
* overflow and make it suitable for cosine implementation
* used, which does not support negative angles.
*/
- while (dev->sdr_fixp_mod_phase < FIXP_2PI)
- dev->sdr_fixp_mod_phase += FIXP_2PI;
- while (dev->sdr_fixp_mod_phase > FIXP_2PI)
- dev->sdr_fixp_mod_phase -= FIXP_2PI;
+ dev->sdr_fixp_src_phase %= FIXP_2PI;
+ dev->sdr_fixp_mod_phase %= FIXP_2PI;
- while (dev->sdr_fixp_src_phase > FIXP_2PI)
- dev->sdr_fixp_src_phase -= FIXP_2PI;
+ if (dev->sdr_fixp_mod_phase < 0)
+ dev->sdr_fixp_mod_phase += FIXP_2PI;
fixp_i = fixp_cos32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
fixp_q = fixp_sin32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
@@ -540,7 +546,7 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
switch (dev->sdr_pixelformat) {
case V4L2_SDR_FMT_CU8:
- /* convert 'fixp float' to u8 */
+ /* convert 'fixp float' to u8 [0, +255] */
/* u8 = X * 127.5 + 127.5; X is float [-1.0, +1.0] */
fixp_i = fixp_i * 1275 + FIXP_FRAC * 1275;
fixp_q = fixp_q * 1275 + FIXP_FRAC * 1275;
@@ -548,9 +554,10 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
*vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
break;
case V4L2_SDR_FMT_CS8:
- /* convert 'fixp float' to s8 */
- fixp_i = fixp_i * 1275;
- fixp_q = fixp_q * 1275;
+ /* convert 'fixp float' to s8 [-128, +127] */
+ /* s8 = X * 127.5 - 0.5; X is float [-1.0, +1.0] */
+ fixp_i = fixp_i * 1275 - FIXP_FRAC * 5;
+ fixp_q = fixp_q * 1275 - FIXP_FRAC * 5;
*vbuf++ = DIV_ROUND_CLOSEST(fixp_i, FIXP_FRAC * 10);
*vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
break;
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.c b/drivers/media/platform/vivid/vivid-tpg-colors.c
index 8f231a6e68c9..2299f0ce47c8 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.c
+++ b/drivers/media/platform/vivid/vivid-tpg-colors.c
@@ -598,7 +598,7 @@ const unsigned short tpg_linear_to_rec709[255 * 16 + 1] = {
};
/* Generated table */
-const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_NONE + 1][TPG_COLOR_CSC_BLACK + 1] = {
+const struct color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFER_FUNC_SMPTE2084 + 1][TPG_COLOR_CSC_BLACK + 1] = {
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_709][1] = { 2953, 2963, 586 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_709][2] = { 0, 2967, 2937 },
@@ -639,6 +639,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_NONE][5] = { 2256, 90, 133 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_NONE][6] = { 110, 96, 2113 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][1] = { 3186, 3194, 1121 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][2] = { 0, 3197, 3173 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][3] = { 523, 3216, 1112 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][4] = { 3237, 792, 3169 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][5] = { 3248, 944, 1094 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][6] = { 1017, 967, 3168 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][1] = { 3802, 3805, 2602 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][2] = { 0, 3806, 3797 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][3] = { 1780, 3812, 2592 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][4] = { 3820, 2215, 3796 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][5] = { 3824, 2409, 2574 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][6] = { 2491, 2435, 3795 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_709][1] = { 2953, 2963, 586 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_709][2] = { 0, 2967, 2937 },
@@ -679,6 +695,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_NONE][5] = { 2256, 90, 133 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_NONE][6] = { 110, 96, 2113 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][1] = { 3186, 3194, 1121 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][2] = { 0, 3197, 3173 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][3] = { 523, 3216, 1112 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][4] = { 3237, 792, 3169 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][5] = { 3248, 944, 1094 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][6] = { 1017, 967, 3168 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][1] = { 3802, 3805, 2602 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][2] = { 0, 3806, 3797 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][3] = { 1780, 3812, 2592 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][4] = { 3820, 2215, 3796 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][5] = { 3824, 2409, 2574 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][6] = { 2491, 2435, 3795 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 547 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_709][2] = { 547, 2939, 2939 },
@@ -719,46 +751,78 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_NONE][5] = { 2125, 130, 130 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2125 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][0] = { 2892, 2988, 2807 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][1] = { 2846, 3070, 843 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][2] = { 1656, 2962, 2783 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][3] = { 1572, 3045, 763 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][4] = { 2476, 229, 2742 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][5] = { 2420, 672, 614 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][6] = { 725, 63, 2718 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][7] = { 534, 561, 509 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][0] = { 3013, 3099, 2935 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][1] = { 2970, 3174, 1091 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][2] = { 1871, 3076, 2913 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][3] = { 1791, 3152, 1013 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][4] = { 2632, 468, 2876 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2581, 924, 866 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 976, 180, 2854 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 786, 813, 762 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 2990, 3077, 2912 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2947, 3153, 1119 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1859, 3053, 2889 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1782, 3130, 1047 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2608, 556, 2852 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2557, 964, 912 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1013, 309, 2830 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 839, 864, 817 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2879, 2975, 2793 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2832, 3059, 806 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1629, 2949, 2768 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][3] = { 1543, 3033, 725 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][4] = { 2457, 203, 2727 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][5] = { 2401, 633, 574 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][6] = { 687, 56, 2702 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][7] = { 493, 521, 469 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][0] = { 2060, 2194, 1943 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][1] = { 1995, 2314, 237 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][2] = { 725, 2157, 1911 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][3] = { 660, 2278, 205 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][4] = { 1525, 50, 1857 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][5] = { 1461, 171, 151 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][6] = { 190, 14, 1825 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][7] = { 126, 134, 118 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1084 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][2] = { 1084, 3175, 3175 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][3] = { 1084, 3175, 1084 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][4] = { 3175, 1084, 3175 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][5] = { 3175, 1084, 1084 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3175 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2563 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][2] = { 2563, 3798, 3798 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][3] = { 2563, 3798, 2563 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][4] = { 3798, 2563, 3798 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][5] = { 3798, 2563, 2563 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3798 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][1] = { 2892, 3034, 910 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][2] = { 1715, 2916, 2914 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][3] = { 1631, 3012, 828 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][4] = { 2497, 119, 2867 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][5] = { 2440, 649, 657 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][6] = { 740, 0, 2841 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3055, 3056 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][1] = { 3013, 3142, 1157 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][2] = { 1926, 3034, 3032 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][3] = { 1847, 3121, 1076 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][4] = { 2651, 304, 2990 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2599, 901, 909 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 991, 0, 2966 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2989, 3120, 1180 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1913, 3011, 3009 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1836, 3099, 1105 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2627, 413, 2966 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2576, 943, 951 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1026, 0, 2942 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2879, 3022, 874 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1688, 2903, 2901 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][3] = { 1603, 2999, 791 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][4] = { 2479, 106, 2853 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][5] = { 2422, 610, 618 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][6] = { 702, 0, 2827 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][1] = { 2059, 2262, 266 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][2] = { 771, 2092, 2089 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][3] = { 705, 2229, 231 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][4] = { 1550, 26, 2024 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][5] = { 1484, 163, 165 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][6] = { 196, 0, 1988 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][1] = { 3136, 3251, 1429 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][2] = { 2150, 3156, 3154 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][3] = { 2077, 3233, 1352 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][4] = { 2812, 589, 3116 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][5] = { 2765, 1182, 1190 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][6] = { 1270, 0, 3094 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][1] = { 3784, 3825, 2879 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][2] = { 3351, 3791, 3790 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][3] = { 3311, 3819, 2815 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][4] = { 3659, 1900, 3777 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][5] = { 3640, 2662, 2669 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][6] = { 2743, 0, 3769 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 464 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_709][2] = { 786, 2939, 2939 },
@@ -799,6 +863,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_NONE][5] = { 2041, 130, 130 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2149 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1003 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][2] = { 1313, 3175, 3175 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][3] = { 1313, 3175, 1003 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][4] = { 3126, 1084, 3188 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][5] = { 3126, 1084, 1084 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3188 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2476 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][2] = { 2782, 3798, 3798 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][3] = { 2782, 3798, 2476 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][4] = { 3780, 2563, 3803 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][5] = { 3780, 2563, 2563 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3803 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 547 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_709][2] = { 547, 2939, 2939 },
@@ -839,6 +919,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_NONE][5] = { 2125, 130, 130 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2125 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1084 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][2] = { 1084, 3175, 3175 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][3] = { 1084, 3175, 1084 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][4] = { 3175, 1084, 3175 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][5] = { 3175, 1084, 1084 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3175 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2563 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 2563, 3798, 3798 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 2563, 3798, 2563 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 3798, 2563, 3798 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 3798, 2563, 2563 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3798 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
[V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 },
[V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 },
@@ -879,6 +975,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 },
[V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 },
[V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2778 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 3306, 3798, 3798 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 3306, 3798, 2778 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 3661, 2563, 3781 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 3661, 2563, 2563 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3781 },
+ [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][1] = { 2877, 2923, 1058 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][2] = { 1837, 2840, 2916 },
@@ -919,6 +1031,78 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_NONE][5] = { 1382, 268, 162 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_NONE][6] = { 216, 152, 1917 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][1] = { 3124, 3161, 1566 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][2] = { 2255, 3094, 3156 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][3] = { 2166, 3080, 1506 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][4] = { 2754, 1477, 3071 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][5] = { 2690, 1431, 1182 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][6] = { 1318, 1153, 3051 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][1] = { 3780, 3793, 2984 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][2] = { 3406, 3768, 3791 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][3] = { 3359, 3763, 2939 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][4] = { 3636, 2916, 3760 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][5] = { 3609, 2880, 2661 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][6] = { 2786, 2633, 3753 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][1] = { 2936, 2934, 992 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][2] = { 1159, 2890, 2916 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][3] = { 1150, 2885, 921 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][4] = { 2751, 766, 2837 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][5] = { 2747, 747, 650 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][6] = { 563, 570, 2812 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3055 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][1] = { 3052, 3051, 1237 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][2] = { 1397, 3011, 3034 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][3] = { 1389, 3006, 1168 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][4] = { 2884, 1016, 2962 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][5] = { 2880, 998, 902 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][6] = { 816, 823, 2940 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][1] = { 3029, 3028, 1255 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][2] = { 1406, 2988, 3011 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][3] = { 1398, 2983, 1190 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][4] = { 2860, 1050, 2939 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][5] = { 2857, 1033, 945 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][6] = { 866, 873, 2916 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][1] = { 2923, 2921, 957 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][2] = { 1125, 2877, 2902 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][3] = { 1116, 2871, 885 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][4] = { 2736, 729, 2823 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][5] = { 2732, 710, 611 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][6] = { 523, 531, 2798 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][1] = { 2120, 2118, 305 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][2] = { 392, 2056, 2092 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][3] = { 387, 2049, 271 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][4] = { 1868, 206, 1983 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][5] = { 1863, 199, 163 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][6] = { 135, 137, 1950 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][1] = { 3172, 3170, 1505 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][2] = { 1657, 3135, 3155 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][3] = { 1649, 3130, 1439 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][4] = { 3021, 1294, 3091 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][5] = { 3018, 1276, 1184 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][6] = { 1100, 1107, 3071 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][1] = { 3797, 3796, 2938 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][2] = { 3049, 3783, 3791 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][3] = { 3044, 3782, 2887 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][4] = { 3741, 2765, 3768 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][5] = { 3740, 2749, 2663 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][6] = { 2580, 2587, 3760 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 },
};
#else
@@ -930,9 +1114,13 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N
#include <stdlib.h>
static const double rec709_to_ntsc1953[3][3] = {
- { 0.6689794, 0.2678309, 0.0323187 },
- { 0.0184901, 1.0742442, -0.0602820 },
- { 0.0162259, 0.0431716, 0.8549253 }
+ /*
+ * This transform uses the Bradford method to compensate for
+ * the different whitepoints.
+ */
+ { 0.6785011, 0.2883441, 0.0331548 },
+ { 0.0165284, 1.0518725, -0.0684009 },
+ { 0.0179230, 0.0506096, 0.9314674 }
};
static const double rec709_to_ebu[3][3] = {
@@ -965,6 +1153,16 @@ static const double rec709_to_bt2020[3][3] = {
{ 0.0163976, 0.0880301, 0.8955723 },
};
+static const double rec709_to_dcip3[3][3] = {
+ /*
+ * This transform uses the Bradford method to compensate for
+ * the different whitepoints.
+ */
+ { 0.8686648, 0.1288456, 0.0024896 },
+ { 0.0345479, 0.9618084, 0.0036437 },
+ { 0.0167785, 0.0710559, 0.9121655 }
+};
+
static void mult_matrix(double *r, double *g, double *b, const double m[3][3])
{
double ir, ig, ib;
@@ -1015,6 +1213,23 @@ static double transfer_rgb_to_adobergb(double v)
return pow(v, 1.0 / 2.19921875);
}
+static double transfer_rgb_to_dcip3(double v)
+{
+ return pow(v, 1.0 / 2.6);
+}
+
+static double transfer_rgb_to_smpte2084(double v)
+{
+ const double m1 = (2610.0 / 4096.0) / 4.0;
+ const double m2 = 128.0 * 2523.0 / 4096.0;
+ const double c1 = 3424.0 / 4096.0;
+ const double c2 = 32.0 * 2413.0 / 4096.0;
+ const double c3 = 32.0 * 2392.0 / 4096.0;
+
+ v = pow(v, m1);
+ return pow((c1 + c2 * v) / (1 + c3 * v), m2);
+}
+
static double transfer_srgb_to_rec709(double v)
{
return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v));
@@ -1049,6 +1264,9 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func,
case V4L2_COLORSPACE_BT2020:
mult_matrix(r, g, b, rec709_to_bt2020);
break;
+ case V4L2_COLORSPACE_DCI_P3:
+ mult_matrix(r, g, b, rec709_to_dcip3);
+ break;
case V4L2_COLORSPACE_SRGB:
case V4L2_COLORSPACE_REC709:
break;
@@ -1078,6 +1296,16 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func,
*g = transfer_rgb_to_adobergb(*g);
*b = transfer_rgb_to_adobergb(*b);
break;
+ case V4L2_XFER_FUNC_DCI_P3:
+ *r = transfer_rgb_to_dcip3(*r);
+ *g = transfer_rgb_to_dcip3(*g);
+ *b = transfer_rgb_to_dcip3(*b);
+ break;
+ case V4L2_XFER_FUNC_SMPTE2084:
+ *r = transfer_rgb_to_smpte2084(*r);
+ *g = transfer_rgb_to_smpte2084(*g);
+ *b = transfer_rgb_to_smpte2084(*b);
+ break;
case V4L2_XFER_FUNC_SMPTE240M:
*r = transfer_rgb_to_smpte240m(*r);
*g = transfer_rgb_to_smpte240m(*g);
@@ -1102,6 +1330,8 @@ int main(int argc, char **argv)
V4L2_COLORSPACE_SRGB,
V4L2_COLORSPACE_ADOBERGB,
V4L2_COLORSPACE_BT2020,
+ 0,
+ V4L2_COLORSPACE_DCI_P3,
};
static const char * const colorspace_names[] = {
"",
@@ -1115,6 +1345,8 @@ int main(int argc, char **argv)
"V4L2_COLORSPACE_SRGB",
"V4L2_COLORSPACE_ADOBERGB",
"V4L2_COLORSPACE_BT2020",
+ "",
+ "V4L2_COLORSPACE_DCI_P3",
};
static const char * const xfer_func_names[] = {
"",
@@ -1123,6 +1355,8 @@ int main(int argc, char **argv)
"V4L2_XFER_FUNC_ADOBERGB",
"V4L2_XFER_FUNC_SMPTE240M",
"V4L2_XFER_FUNC_NONE",
+ "V4L2_XFER_FUNC_DCI_P3",
+ "V4L2_XFER_FUNC_SMPTE2084",
};
int i;
int x;
@@ -1153,9 +1387,9 @@ int main(int argc, char **argv)
printf("\n};\n\n");
printf("/* Generated table */\n");
- printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_NONE + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
- for (c = 0; c <= V4L2_COLORSPACE_BT2020; c++) {
- for (x = 1; x <= V4L2_XFER_FUNC_NONE; x++) {
+ printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFER_FUNC_SMPTE2084 + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
+ for (c = 0; c <= V4L2_COLORSPACE_DCI_P3; c++) {
+ for (x = 1; x <= V4L2_XFER_FUNC_SMPTE2084; x++) {
for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) {
double r, g, b;
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.h b/drivers/media/platform/vivid/vivid-tpg-colors.h
index 86b8bf3fe745..4e5a76a1e25b 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.h
+++ b/drivers/media/platform/vivid/vivid-tpg-colors.h
@@ -61,8 +61,8 @@ enum tpg_color {
extern const struct color tpg_colors[TPG_COLOR_MAX];
extern const unsigned short tpg_rec709_to_linear[255 * 16 + 1];
extern const unsigned short tpg_linear_to_rec709[255 * 16 + 1];
-extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1]
- [V4L2_XFER_FUNC_NONE + 1]
+extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1]
+ [V4L2_XFER_FUNC_SMPTE2084 + 1]
[TPG_COLOR_CSC_BLACK + 1];
#endif
diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 1458c7955547..14256141f905 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -193,6 +193,14 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SBGGR12:
+ case V4L2_PIX_FMT_SGBRG12:
+ case V4L2_PIX_FMT_SGRBG12:
+ case V4L2_PIX_FMT_SRGGB12:
tpg->interleaved = true;
tpg->vdownsampling[1] = 1;
tpg->hdownsampling[1] = 1;
@@ -349,6 +357,17 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
tpg->twopixelsize[0] = 2;
tpg->twopixelsize[1] = 2;
break;
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SRGGB12:
+ case V4L2_PIX_FMT_SGRBG12:
+ case V4L2_PIX_FMT_SGBRG12:
+ case V4L2_PIX_FMT_SBGGR12:
+ tpg->twopixelsize[0] = 4;
+ tpg->twopixelsize[1] = 4;
+ break;
case V4L2_PIX_FMT_YUV422P:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
@@ -1112,6 +1131,70 @@ static void gen_twopix(struct tpg_data *tpg,
buf[0][offset] = odd ? g_u : r_y;
buf[1][offset] = odd ? b_v : g_u;
break;
+ case V4L2_PIX_FMT_SBGGR10:
+ buf[0][offset] = odd ? g_u << 2 : b_v << 2;
+ buf[0][offset + 1] = odd ? g_u >> 6 : b_v >> 6;
+ buf[1][offset] = odd ? r_y << 2 : g_u << 2;
+ buf[1][offset + 1] = odd ? r_y >> 6 : g_u >> 6;
+ buf[0][offset] |= (buf[0][offset] >> 2) & 3;
+ buf[1][offset] |= (buf[1][offset] >> 2) & 3;
+ break;
+ case V4L2_PIX_FMT_SGBRG10:
+ buf[0][offset] = odd ? b_v << 2 : g_u << 2;
+ buf[0][offset + 1] = odd ? b_v >> 6 : g_u >> 6;
+ buf[1][offset] = odd ? g_u << 2 : r_y << 2;
+ buf[1][offset + 1] = odd ? g_u >> 6 : r_y >> 6;
+ buf[0][offset] |= (buf[0][offset] >> 2) & 3;
+ buf[1][offset] |= (buf[1][offset] >> 2) & 3;
+ break;
+ case V4L2_PIX_FMT_SGRBG10:
+ buf[0][offset] = odd ? r_y << 2 : g_u << 2;
+ buf[0][offset + 1] = odd ? r_y >> 6 : g_u >> 6;
+ buf[1][offset] = odd ? g_u << 2 : b_v << 2;
+ buf[1][offset + 1] = odd ? g_u >> 6 : b_v >> 6;
+ buf[0][offset] |= (buf[0][offset] >> 2) & 3;
+ buf[1][offset] |= (buf[1][offset] >> 2) & 3;
+ break;
+ case V4L2_PIX_FMT_SRGGB10:
+ buf[0][offset] = odd ? g_u << 2 : r_y << 2;
+ buf[0][offset + 1] = odd ? g_u >> 6 : r_y >> 6;
+ buf[1][offset] = odd ? b_v << 2 : g_u << 2;
+ buf[1][offset + 1] = odd ? b_v >> 6 : g_u >> 6;
+ buf[0][offset] |= (buf[0][offset] >> 2) & 3;
+ buf[1][offset] |= (buf[1][offset] >> 2) & 3;
+ break;
+ case V4L2_PIX_FMT_SBGGR12:
+ buf[0][offset] = odd ? g_u << 4 : b_v << 4;
+ buf[0][offset + 1] = odd ? g_u >> 4 : b_v >> 4;
+ buf[1][offset] = odd ? r_y << 4 : g_u << 4;
+ buf[1][offset + 1] = odd ? r_y >> 4 : g_u >> 4;
+ buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
+ buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
+ break;
+ case V4L2_PIX_FMT_SGBRG12:
+ buf[0][offset] = odd ? b_v << 4 : g_u << 4;
+ buf[0][offset + 1] = odd ? b_v >> 4 : g_u >> 4;
+ buf[1][offset] = odd ? g_u << 4 : r_y << 4;
+ buf[1][offset + 1] = odd ? g_u >> 4 : r_y >> 4;
+ buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
+ buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
+ break;
+ case V4L2_PIX_FMT_SGRBG12:
+ buf[0][offset] = odd ? r_y << 4 : g_u << 4;
+ buf[0][offset + 1] = odd ? r_y >> 4 : g_u >> 4;
+ buf[1][offset] = odd ? g_u << 4 : b_v << 4;
+ buf[1][offset + 1] = odd ? g_u >> 4 : b_v >> 4;
+ buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
+ buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
+ break;
+ case V4L2_PIX_FMT_SRGGB12:
+ buf[0][offset] = odd ? g_u << 4 : r_y << 4;
+ buf[0][offset + 1] = odd ? g_u >> 4 : r_y >> 4;
+ buf[1][offset] = odd ? b_v << 4 : g_u << 4;
+ buf[1][offset + 1] = odd ? b_v >> 4 : g_u >> 4;
+ buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
+ buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
+ break;
}
}
@@ -1122,6 +1205,14 @@ unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line)
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SBGGR12:
+ case V4L2_PIX_FMT_SGBRG12:
+ case V4L2_PIX_FMT_SGRBG12:
+ case V4L2_PIX_FMT_SRGGB12:
return buf_line & 1;
default:
return 0;
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index ef81b01b53d2..e903d023e9df 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -94,36 +94,38 @@ static void vivid_g_fmt_vbi_cap(struct vivid_dev *dev, struct v4l2_vbi_format *v
void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
{
struct v4l2_vbi_format vbi;
- u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+ u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
vivid_g_fmt_vbi_cap(dev, &vbi);
- buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count;
+ buf->vb.sequence = dev->vbi_cap_seq_count;
if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- buf->vb.v4l2_buf.sequence /= 2;
+ buf->vb.sequence /= 2;
- vivid_sliced_vbi_cap_fill(dev, buf->vb.v4l2_buf.sequence);
+ vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
- memset(vbuf, 0x10, vb2_plane_size(&buf->vb, 0));
+ memset(vbuf, 0x10, vb2_plane_size(&buf->vb.vb2_buf, 0));
if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
}
-void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
+void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
+ struct vivid_buffer *buf)
{
- struct v4l2_sliced_vbi_data *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+ struct v4l2_sliced_vbi_data *vbuf =
+ vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count;
+ buf->vb.sequence = dev->vbi_cap_seq_count;
if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- buf->vb.v4l2_buf.sequence /= 2;
+ buf->vb.sequence /= 2;
- vivid_sliced_vbi_cap_fill(dev, buf->vb.v4l2_buf.sequence);
+ vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
- memset(vbuf, 0, vb2_plane_size(&buf->vb, 0));
+ memset(vbuf, 0, vb2_plane_size(&buf->vb.vb2_buf, 0));
if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) {
unsigned i;
@@ -131,11 +133,11 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu
vbuf[i] = dev->vbi_gen.data[i];
}
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
}
-static int vbi_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned *nbuffers, unsigned *nplanes,
unsigned sizes[], void *alloc_ctxs[])
{
@@ -187,8 +189,9 @@ static int vbi_cap_buf_prepare(struct vb2_buffer *vb)
static void vbi_cap_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb);
+ struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
dprintk(dev, 1, "%s\n", __func__);
@@ -215,7 +218,8 @@ static int vbi_cap_start_streaming(struct vb2_queue *vq, unsigned count)
list_for_each_entry_safe(buf, tmp, &dev->vbi_cap_active, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
}
return err;
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
index 4e4c70e1e04a..75c5709f938e 100644
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ b/drivers/media/platform/vivid/vivid-vbi-out.c
@@ -27,7 +27,7 @@
#include "vivid-vbi-out.h"
#include "vivid-vbi-cap.h"
-static int vbi_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_out_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned *nbuffers, unsigned *nplanes,
unsigned sizes[], void *alloc_ctxs[])
{
@@ -79,8 +79,9 @@ static int vbi_out_buf_prepare(struct vb2_buffer *vb)
static void vbi_out_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb);
+ struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
dprintk(dev, 1, "%s\n", __func__);
@@ -107,7 +108,8 @@ static int vbi_out_start_streaming(struct vb2_queue *vq, unsigned count)
list_for_each_entry_safe(buf, tmp, &dev->vbi_out_active, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
}
return err;
@@ -201,7 +203,8 @@ int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_forma
return 0;
}
-int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
+ struct v4l2_format *fmt)
{
struct vivid_dev *dev = video_drvdata(file);
struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
@@ -217,10 +220,13 @@ int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format
return 0;
}
-void vivid_sliced_vbi_out_process(struct vivid_dev *dev, struct vivid_buffer *buf)
+void vivid_sliced_vbi_out_process(struct vivid_dev *dev,
+ struct vivid_buffer *buf)
{
- struct v4l2_sliced_vbi_data *vbi = vb2_plane_vaddr(&buf->vb, 0);
- unsigned elems = vb2_get_plane_payload(&buf->vb, 0) / sizeof(*vbi);
+ struct v4l2_sliced_vbi_data *vbi =
+ vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+ unsigned elems =
+ vb2_get_plane_payload(&buf->vb.vb2_buf, 0) / sizeof(*vbi);
dev->vbi_out_have_cc[0] = false;
dev->vbi_out_have_cc[1] = false;
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index ed0b8788a66f..ef5412311b2f 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -95,10 +95,11 @@ static const struct v4l2_discrete_probe webcam_probe = {
VIVID_WEBCAM_SIZES
};
-static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned *nbuffers, unsigned *nplanes,
unsigned sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct vivid_dev *dev = vb2_get_drv_priv(vq);
unsigned buffers = tpg_g_buffers(&dev->tpg);
unsigned h = dev->fmt_cap_rect.height;
@@ -198,7 +199,7 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
}
vb2_set_plane_payload(vb, p, size);
- vb->v4l2_planes[p].data_offset = dev->fmt_cap->data_offset[p];
+ vb->planes[p].data_offset = dev->fmt_cap->data_offset[p];
}
return 0;
@@ -206,10 +207,11 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
static void vid_cap_buf_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct v4l2_timecode *tc = &vb->v4l2_buf.timecode;
+ struct v4l2_timecode *tc = &vbuf->timecode;
unsigned fps = 25;
- unsigned seq = vb->v4l2_buf.sequence;
+ unsigned seq = vbuf->sequence;
if (!vivid_is_sdtv_cap(dev))
return;
@@ -218,7 +220,7 @@ static void vid_cap_buf_finish(struct vb2_buffer *vb)
* Set the timecode. Rarely used, so it is interesting to
* test this.
*/
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_TIMECODE;
+ vbuf->flags |= V4L2_BUF_FLAG_TIMECODE;
if (dev->std_cap & V4L2_STD_525_60)
fps = 30;
tc->type = (fps == 30) ? V4L2_TC_TYPE_30FPS : V4L2_TC_TYPE_25FPS;
@@ -231,8 +233,9 @@ static void vid_cap_buf_finish(struct vb2_buffer *vb)
static void vid_cap_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb);
+ struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
dprintk(dev, 1, "%s\n", __func__);
@@ -268,7 +271,8 @@ static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count)
list_for_each_entry_safe(buf, tmp, &dev->vid_cap_active, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
}
return err;
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index fc73927a4abc..1678b730dba2 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -390,6 +390,62 @@ struct vivid_fmt vivid_formats[] = {
.buffers = 1,
},
{
+ .fourcc = V4L2_PIX_FMT_SBGGR10, /* Bayer BG/GR */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
.fourcc = V4L2_PIX_FMT_NV16M,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 8 },
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index c404e275eae0..b77acb6a7013 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -31,10 +31,11 @@
#include "vivid-kthread-out.h"
#include "vivid-vid-out.h"
-static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned *nbuffers, unsigned *nplanes,
unsigned sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct vivid_dev *dev = vb2_get_drv_priv(vq);
const struct vivid_fmt *vfmt = dev->fmt_out;
unsigned planes = vfmt->buffers;
@@ -109,6 +110,7 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
static int vid_out_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
unsigned long size;
unsigned planes;
@@ -131,14 +133,14 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb)
}
if (dev->field_out != V4L2_FIELD_ALTERNATE)
- vb->v4l2_buf.field = dev->field_out;
- else if (vb->v4l2_buf.field != V4L2_FIELD_TOP &&
- vb->v4l2_buf.field != V4L2_FIELD_BOTTOM)
+ vbuf->field = dev->field_out;
+ else if (vbuf->field != V4L2_FIELD_TOP &&
+ vbuf->field != V4L2_FIELD_BOTTOM)
return -EINVAL;
for (p = 0; p < planes; p++) {
size = dev->bytesperline_out[p] * dev->fmt_out_rect.height +
- vb->v4l2_planes[p].data_offset;
+ vb->planes[p].data_offset;
if (vb2_get_plane_payload(vb, p) < size) {
dprintk(dev, 1, "%s the payload is too small for plane %u (%lu < %lu)\n",
@@ -152,8 +154,9 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb)
static void vid_out_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb);
+ struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
dprintk(dev, 1, "%s\n", __func__);
@@ -186,7 +189,8 @@ static int vid_out_start_streaming(struct vb2_queue *vq, unsigned count)
list_for_each_entry_safe(buf, tmp, &dev->vid_out_active, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
}
return err;
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 3294529a3108..cd5248a9a271 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -200,10 +200,10 @@ static void rpf_vdev_queue(struct vsp1_video *video,
vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
buf->addr[0] + rpf->offsets[0]);
- if (buf->buf.num_planes > 1)
+ if (buf->buf.vb2_buf.num_planes > 1)
vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0,
buf->addr[1] + rpf->offsets[1]);
- if (buf->buf.num_planes > 2)
+ if (buf->buf.vb2_buf.num_planes > 2)
vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
buf->addr[2] + rpf->offsets[1]);
}
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 3c124c14ce14..5ce88e1f5d71 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -24,7 +24,7 @@
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-subdev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "vsp1.h"
@@ -610,11 +610,11 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
spin_unlock_irqrestore(&video->irqlock, flags);
- done->buf.v4l2_buf.sequence = video->sequence++;
- v4l2_get_timestamp(&done->buf.v4l2_buf.timestamp);
- for (i = 0; i < done->buf.num_planes; ++i)
- vb2_set_plane_payload(&done->buf, i, done->length[i]);
- vb2_buffer_done(&done->buf, VB2_BUF_STATE_DONE);
+ done->buf.sequence = video->sequence++;
+ v4l2_get_timestamp(&done->buf.timestamp);
+ for (i = 0; i < done->buf.vb2_buf.num_planes; ++i)
+ vb2_set_plane_payload(&done->buf.vb2_buf, i, done->length[i]);
+ vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE);
return next;
}
@@ -787,10 +787,11 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
*/
static int
-vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vsp1_video_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct vsp1_video *video = vb2_get_drv_priv(vq);
const struct v4l2_pix_format_mplane *format;
struct v4l2_pix_format_mplane pix_mp;
@@ -820,8 +821,9 @@ vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
- struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb);
+ struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf);
const struct v4l2_pix_format_mplane *format = &video->format;
unsigned int i;
@@ -841,9 +843,10 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
- struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb);
+ struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf);
unsigned long flags;
bool empty;
@@ -954,7 +957,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
/* Remove all buffers from the IRQ queue. */
spin_lock_irqsave(&video->irqlock, flags);
list_for_each_entry(buffer, &video->irqqueue, queue)
- vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
INIT_LIST_HEAD(&video->irqqueue);
spin_unlock_irqrestore(&video->irqlock, flags);
}
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 0887a4d2742c..a929aa81cdbf 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -18,7 +18,7 @@
#include <linux/wait.h>
#include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
struct vsp1_video;
@@ -94,7 +94,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
}
struct vsp1_video_buffer {
- struct vb2_buffer buf;
+ struct vb2_v4l2_buffer buf;
struct list_head queue;
dma_addr_t addr[3];
@@ -102,9 +102,9 @@ struct vsp1_video_buffer {
};
static inline struct vsp1_video_buffer *
-to_vsp1_video_buffer(struct vb2_buffer *vb)
+to_vsp1_video_buffer(struct vb2_v4l2_buffer *vbuf)
{
- return container_of(vb, struct vsp1_video_buffer, buf);
+ return container_of(vbuf, struct vsp1_video_buffer, buf);
}
struct vsp1_video_operations {
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 1d2b3a2f1573..95b62f4f77e7 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -201,9 +201,9 @@ static void wpf_vdev_queue(struct vsp1_video *video,
struct vsp1_rwpf *wpf = container_of(video, struct vsp1_rwpf, video);
vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]);
- if (buf->buf.num_planes > 1)
+ if (buf->buf.vb2_buf.num_planes > 1)
vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]);
- if (buf->buf.num_planes > 2)
+ if (buf->buf.vb2_buf.num_planes > 2)
vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]);
}
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index e779c93cb015..d11cc7072cd5 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -22,7 +22,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "xilinx-dma.h"
@@ -285,7 +285,7 @@ done:
* @dma: DMA channel that uses the buffer
*/
struct xvip_dma_buffer {
- struct vb2_buffer buf;
+ struct vb2_v4l2_buffer buf;
struct list_head queue;
struct xvip_dma *dma;
};
@@ -301,18 +301,19 @@ static void xvip_dma_complete(void *param)
list_del(&buf->queue);
spin_unlock(&dma->queued_lock);
- buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
- buf->buf.v4l2_buf.sequence = dma->sequence++;
- v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
- vb2_set_plane_payload(&buf->buf, 0, dma->format.sizeimage);
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+ buf->buf.field = V4L2_FIELD_NONE;
+ buf->buf.sequence = dma->sequence++;
+ v4l2_get_timestamp(&buf->buf.timestamp);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, dma->format.sizeimage);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
}
static int
-xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+xvip_dma_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct xvip_dma *dma = vb2_get_drv_priv(vq);
/* Make sure the image size is large enough. */
@@ -329,8 +330,9 @@ xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int xvip_dma_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
- struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vb);
+ struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vbuf);
buf->dma = dma;
@@ -339,8 +341,9 @@ static int xvip_dma_buffer_prepare(struct vb2_buffer *vb)
static void xvip_dma_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
- struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vb);
+ struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vbuf);
struct dma_async_tx_descriptor *desc;
dma_addr_t addr = vb2_dma_contig_plane_dma_addr(vb, 0);
u32 flags;
@@ -367,7 +370,7 @@ static void xvip_dma_buffer_queue(struct vb2_buffer *vb)
desc = dmaengine_prep_interleaved_dma(dma->dma, &dma->xt, flags);
if (!desc) {
dev_err(dma->xdev->dev, "Failed to prepare DMA transfer\n");
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
return;
}
desc->callback = xvip_dma_complete;
@@ -434,7 +437,7 @@ error:
/* Give back all queued buffers to videobuf2. */
spin_lock_irq(&dma->queued_lock);
list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_QUEUED);
list_del(&buf->queue);
}
spin_unlock_irq(&dma->queued_lock);
@@ -461,7 +464,7 @@ static void xvip_dma_stop_streaming(struct vb2_queue *vq)
/* Give back all queued buffers to videobuf2. */
spin_lock_irq(&dma->queued_lock);
list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&buf->queue);
}
spin_unlock_irq(&dma->queued_lock);
diff --git a/drivers/media/platform/xilinx/xilinx-dma.h b/drivers/media/platform/xilinx/xilinx-dma.h
index a540111f8d3d..7a1621a2ef40 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.h
+++ b/drivers/media/platform/xilinx/xilinx-dma.h
@@ -22,7 +22,7 @@
#include <media/media-entity.h>
#include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
struct dma_chan;
struct xvip_composite_device;
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index 1c087cb76815..d0549fba711c 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -257,7 +257,7 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
goto clkerr;
if (devm_request_irq(dev, priv->irq, hix5hd2_ir_rx_interrupt,
- IRQF_NO_SUSPEND, pdev->name, priv) < 0) {
+ 0, pdev->name, priv) < 0) {
dev_err(dev, "IRQ %d register failed\n", priv->irq);
ret = -EINVAL;
goto regerr;
diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c
index b533240f8ec0..3a12ef35682b 100644
--- a/drivers/media/tuners/msi001.c
+++ b/drivers/media/tuners/msi001.c
@@ -513,7 +513,6 @@ MODULE_DEVICE_TABLE(spi, msi001_id_table);
static struct spi_driver msi001_driver = {
.driver = {
.name = "msi001",
- .owner = THIS_MODULE,
.suppress_bind_attrs = true,
},
.probe = msi001_probe,
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 507382160e5e..ce157edd45fa 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -166,6 +166,10 @@ static int si2157_init(struct dvb_frontend *fe)
for (remaining = fw->size; remaining > 0; remaining -= 17) {
len = fw->data[fw->size - remaining];
+ if (len > SI2157_ARGLEN) {
+ dev_err(&client->dev, "Bad firmware length\n");
+ goto err_release_firmware;
+ }
memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
cmd.wlen = len;
cmd.rlen = 1;
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index 8f2e1c277c5f..fcbb49757614 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -21,6 +21,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
/* AirSpy USB API commands (from AirSpy Library) */
@@ -97,7 +98,8 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
struct airspy_frame_buf {
- struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -310,13 +312,13 @@ static void airspy_urb_complete(struct urb *urb)
}
/* fill framebuffer */
- ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+ ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0);
len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
urb->actual_length);
- vb2_set_plane_payload(&fbuf->vb, 0, len);
- v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
- fbuf->vb.v4l2_buf.sequence = s->sequence++;
- vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
+ v4l2_get_timestamp(&fbuf->vb.timestamp);
+ fbuf->vb.sequence = s->sequence++;
+ vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
skip:
usb_submit_urb(urb, GFP_ATOMIC);
@@ -459,7 +461,7 @@ static void airspy_cleanup_queued_bufs(struct airspy *s)
buf = list_entry(s->queued_bufs.next,
struct airspy_frame_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
}
@@ -486,7 +488,7 @@ static void airspy_disconnect(struct usb_interface *intf)
/* Videobuf2 operations */
static int airspy_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt, unsigned int *nbuffers,
+ const void *parg, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
struct airspy *s = vb2_get_drv_priv(vq);
@@ -505,14 +507,15 @@ static int airspy_queue_setup(struct vb2_queue *vq,
static void airspy_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
struct airspy_frame_buf *buf =
- container_of(vb, struct airspy_frame_buf, vb);
+ container_of(vbuf, struct airspy_frame_buf, vb);
unsigned long flags;
/* Check the device has not disconnected between prep and queuing */
if (unlikely(!s->udev)) {
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
return;
}
@@ -571,7 +574,8 @@ err_clear_bit:
list_for_each_entry_safe(buf, tmp, &s->queued_bufs, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
}
diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
index f67247cf1a5a..130c8b49bf7f 100644
--- a/drivers/media/usb/au0828/au0828-vbi.c
+++ b/drivers/media/usb/au0828/au0828-vbi.c
@@ -30,10 +30,11 @@
/* ------------------------------------------------------------------ */
-static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct au0828_dev *dev = vb2_get_drv_priv(vq);
unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
unsigned long size;
@@ -52,7 +53,6 @@ static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int vbi_buffer_prepare(struct vb2_buffer *vb)
{
struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
unsigned long size;
size = dev->vbi_width * dev->vbi_height * 2;
@@ -62,7 +62,7 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
__func__, vb2_plane_size(vb, 0), size);
return -EINVAL;
}
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(vb, 0, size);
return 0;
}
@@ -71,7 +71,9 @@ static void
vbi_buffer_queue(struct vb2_buffer *vb)
{
struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct au0828_buffer *buf =
+ container_of(vbuf, struct au0828_buffer, vb);
struct au0828_dmaqueue *vbiq = &dev->vbiq;
unsigned long flags = 0;
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 1a362a041ab3..45c622e234f7 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -302,20 +302,20 @@ static inline void buffer_filled(struct au0828_dev *dev,
struct au0828_dmaqueue *dma_q,
struct au0828_buffer *buf)
{
- struct vb2_buffer *vb = &buf->vb;
- struct vb2_queue *q = vb->vb2_queue;
+ struct vb2_v4l2_buffer *vb = &buf->vb;
+ struct vb2_queue *q = vb->vb2_buf.vb2_queue;
/* Advice that buffer was filled */
au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- vb->v4l2_buf.sequence = dev->frame_count++;
+ vb->sequence = dev->frame_count++;
else
- vb->v4l2_buf.sequence = dev->vbi_frame_count++;
+ vb->sequence = dev->vbi_frame_count++;
- vb->v4l2_buf.field = V4L2_FIELD_INTERLACED;
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ vb->field = V4L2_FIELD_INTERLACED;
+ v4l2_get_timestamp(&vb->timestamp);
+ vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
}
/*
@@ -531,11 +531,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
buf = dev->isoc_ctl.buf;
if (buf != NULL)
- outp = vb2_plane_vaddr(&buf->vb, 0);
+ outp = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
vbi_buf = dev->isoc_ctl.vbi_buf;
if (vbi_buf != NULL)
- vbioutp = vb2_plane_vaddr(&vbi_buf->vb, 0);
+ vbioutp = vb2_plane_vaddr(&vbi_buf->vb.vb2_buf, 0);
for (i = 0; i < urb->number_of_packets; i++) {
int status = urb->iso_frame_desc[i].status;
@@ -574,7 +574,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
vbioutp = NULL;
else
vbioutp = vb2_plane_vaddr(
- &vbi_buf->vb, 0);
+ &vbi_buf->vb.vb2_buf, 0);
/* Video */
if (buf != NULL)
@@ -583,7 +583,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
if (buf == NULL)
outp = NULL;
else
- outp = vb2_plane_vaddr(&buf->vb, 0);
+ outp = vb2_plane_vaddr(
+ &buf->vb.vb2_buf, 0);
/* As long as isoc traffic is arriving, keep
resetting the timer */
@@ -637,10 +638,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
return rc;
}
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct au0828_dev *dev = vb2_get_drv_priv(vq);
unsigned long img_size = dev->height * dev->bytesperline;
unsigned long size;
@@ -658,7 +660,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int
buffer_prepare(struct vb2_buffer *vb)
{
- struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct au0828_buffer *buf = container_of(vbuf,
+ struct au0828_buffer, vb);
struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
buf->length = dev->height * dev->bytesperline;
@@ -668,14 +672,15 @@ buffer_prepare(struct vb2_buffer *vb)
__func__, vb2_plane_size(vb, 0), buf->length);
return -EINVAL;
}
- vb2_set_plane_payload(&buf->vb, 0, buf->length);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->length);
return 0;
}
static void
buffer_queue(struct vb2_buffer *vb)
{
- struct au0828_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct au0828_buffer *buf = container_of(vbuf,
struct au0828_buffer,
vb);
struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
@@ -826,14 +831,15 @@ static void au0828_stop_streaming(struct vb2_queue *vq)
spin_lock_irqsave(&dev->slock, flags);
if (dev->isoc_ctl.buf != NULL) {
- vb2_buffer_done(&dev->isoc_ctl.buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&dev->isoc_ctl.buf->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
dev->isoc_ctl.buf = NULL;
}
while (!list_empty(&vidq->active)) {
struct au0828_buffer *buf;
buf = list_entry(vidq->active.next, struct au0828_buffer, list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&buf->list);
}
spin_unlock_irqrestore(&dev->slock, flags);
@@ -853,7 +859,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq)
spin_lock_irqsave(&dev->slock, flags);
if (dev->isoc_ctl.vbi_buf != NULL) {
- vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb,
+ vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
dev->isoc_ctl.vbi_buf = NULL;
}
@@ -862,7 +868,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq)
buf = list_entry(vbiq->active.next, struct au0828_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
@@ -911,7 +917,7 @@ static void au0828_vid_buffer_timeout(unsigned long data)
buf = dev->isoc_ctl.buf;
if (buf != NULL) {
- vid_data = vb2_plane_vaddr(&buf->vb, 0);
+ vid_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
memset(vid_data, 0x00, buf->length); /* Blank green frame */
buffer_filled(dev, dma_q, buf);
}
@@ -935,7 +941,7 @@ static void au0828_vbi_buffer_timeout(unsigned long data)
buf = dev->isoc_ctl.vbi_buf;
if (buf != NULL) {
- vbi_data = vb2_plane_vaddr(&buf->vb, 0);
+ vbi_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
memset(vbi_data, 0x00, buf->length);
buffer_filled(dev, dma_q, buf);
}
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 3b480005ce3b..60b59391ea2a 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -28,6 +28,7 @@
/* Analog */
#include <linux/videodev2.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
@@ -167,7 +168,7 @@ struct au0828_usb_isoc_ctl {
/* buffer for one video frame */
struct au0828_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
void *mem;
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index 9798160698a3..d0d8f08e37c8 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -1114,7 +1114,8 @@ int cx231xx_enum_input(struct file *file, void *priv,
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
u32 gen_stat;
- unsigned int ret, n;
+ unsigned int n;
+ int ret;
n = i->index;
if (n >= MAX_CX231XX_INPUT)
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index 0376c092bab8..1dd962535f97 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -847,6 +847,10 @@ static const struct usb_device_id dvbsky_id_table[] = {
USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI,
&dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI",
RC_MAP_TT_1500) },
+ { DVB_USB_DEVICE(USB_VID_TERRATEC,
+ USB_PID_TERRATEC_H7_3,
+ &dvbsky_t680c_props, "Terratec H7 Rev.4",
+ RC_MAP_TT_1500) },
{ }
};
MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index c3cac4c12fb3..5a503a6bb8c5 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -34,6 +34,14 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
unsigned int pipe;
u8 requesttype;
+ mutex_lock(&d->usb_mutex);
+
+ if (req->size > sizeof(dev->buf)) {
+ dev_err(&d->intf->dev, "too large message %u\n", req->size);
+ ret = -EINVAL;
+ goto err_mutex_unlock;
+ }
+
if (req->index & CMD_WR_FLAG) {
/* write */
memcpy(dev->buf, req->data, req->size);
@@ -50,14 +58,17 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
req->index, dev->buf, req->size);
if (ret < 0)
- goto err;
+ goto err_mutex_unlock;
/* read request, copy returned data to return buf */
if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
memcpy(req->data, dev->buf, req->size);
+ mutex_unlock(&d->usb_mutex);
+
return 0;
-err:
+err_mutex_unlock:
+ mutex_unlock(&d->usb_mutex);
dev_dbg(&d->intf->dev, "failed=%d\n", ret);
return ret;
}
@@ -1885,6 +1896,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
&rtl28xxu_props, "MSI DIGIVOX Micro HD", NULL) },
{ DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620,
&rtl28xxu_props, "Compro VideoMate U620F", NULL) },
+ { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0650,
+ &rtl28xxu_props, "Compro VideoMate U650F", NULL) },
{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394,
&rtl28xxu_props, "MaxMedia HU394-T", NULL) },
{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03,
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 9f6115a2ee01..138062960a73 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -71,7 +71,7 @@
struct rtl28xxu_dev {
- u8 buf[28];
+ u8 buf[128];
u8 chip_id;
u8 tuner;
char *tuner_name;
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index 744e7ed743e1..e23c285b3108 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -31,10 +31,11 @@
/* ------------------------------------------------------------------ */
-static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct em28xx *dev = vb2_get_drv_priv(vq);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
unsigned long size;
@@ -61,7 +62,6 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
{
struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
unsigned long size;
size = v4l2->vbi_width * v4l2->vbi_height * 2;
@@ -71,7 +71,7 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
__func__, vb2_plane_size(vb, 0), size);
return -EINVAL;
}
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(vb, 0, size);
return 0;
}
@@ -79,8 +79,10 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
static void
vbi_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+ struct em28xx_buffer *buf =
+ container_of(vbuf, struct em28xx_buffer, vb);
struct em28xx_dmaqueue *vbiq = &dev->vbiq;
unsigned long flags = 0;
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 4397ce5e78df..6a3cf342e087 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -433,14 +433,14 @@ static inline void finish_buffer(struct em28xx *dev,
{
em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
- buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++;
+ buf->vb.sequence = dev->v4l2->field_count++;
if (dev->v4l2->progressive)
- buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+ buf->vb.field = V4L2_FIELD_NONE;
else
- buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ buf->vb.field = V4L2_FIELD_INTERLACED;
+ v4l2_get_timestamp(&buf->vb.timestamp);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
/*
@@ -871,10 +871,11 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
Videobuf2 operations
------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct em28xx *dev = vb2_get_drv_priv(vq);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
unsigned long size;
@@ -900,12 +901,12 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int
buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
unsigned long size;
- em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
+ em28xx_videodbg("%s, field=%d\n", __func__, vbuf->field);
size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
@@ -914,7 +915,7 @@ buffer_prepare(struct vb2_buffer *vb)
__func__, vb2_plane_size(vb, 0), size);
return -EINVAL;
}
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(vb, 0, size);
return 0;
}
@@ -924,6 +925,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
struct em28xx *dev = vb2_get_drv_priv(vq);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
struct v4l2_frequency f;
+ struct v4l2_fh *owner;
int rc = 0;
em28xx_videodbg("%s\n", __func__);
@@ -964,7 +966,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
/* Ask tuner to go to analog or radio mode */
memset(&f, 0, sizeof(f));
f.frequency = v4l2->frequency;
- if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
+ owner = (struct v4l2_fh *)vq->owner;
+ if (owner && owner->vdev->vfl_type == VFL_TYPE_RADIO)
f.type = V4L2_TUNER_RADIO;
else
f.type = V4L2_TUNER_ANALOG_TV;
@@ -995,7 +998,8 @@ static void em28xx_stop_streaming(struct vb2_queue *vq)
spin_lock_irqsave(&dev->slock, flags);
if (dev->usb_ctl.vid_buf != NULL) {
- vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
dev->usb_ctl.vid_buf = NULL;
}
while (!list_empty(&vidq->active)) {
@@ -1003,7 +1007,7 @@ static void em28xx_stop_streaming(struct vb2_queue *vq)
buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -1026,7 +1030,8 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
spin_lock_irqsave(&dev->slock, flags);
if (dev->usb_ctl.vbi_buf != NULL) {
- vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
dev->usb_ctl.vbi_buf = NULL;
}
while (!list_empty(&vbiq->active)) {
@@ -1034,7 +1039,7 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -1042,8 +1047,10 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
static void
buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+ struct em28xx_buffer *buf =
+ container_of(vbuf, struct em28xx_buffer, vb);
struct em28xx_dmaqueue *vidq = &dev->vidq;
unsigned long flags = 0;
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index e6559c6f143c..76bf8ba372b3 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -35,6 +35,7 @@
#include <linux/kref.h>
#include <linux/videodev2.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
@@ -264,7 +265,7 @@ struct em28xx_fmt {
/* buffer for one video frame */
struct em28xx_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
void *mem;
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index 0ab81ec8897a..ae1cfa792c58 100644
--- a/drivers/media/usb/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -386,10 +386,10 @@ start_error:
*/
static inline void store_byte(struct go7007_buffer *vb, u8 byte)
{
- if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
- u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+ if (vb && vb->vb.vb2_buf.planes[0].bytesused < GO7007_BUF_SIZE) {
+ u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
- ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
+ ptr[vb->vb.vb2_buf.planes[0].bytesused++] = byte;
}
}
@@ -401,7 +401,7 @@ static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *v
.type = V4L2_EVENT_MOTION_DET,
.u.motion_det = {
.flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
- .frame_sequence = vb->vb.v4l2_buf.sequence,
+ .frame_sequence = vb->vb.sequence,
.region_mask = motion_regions,
},
};
@@ -417,7 +417,7 @@ static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *v
*/
static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb)
{
- u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ u32 *bytesused = &vb->vb.vb2_buf.planes[0].bytesused;
unsigned motion[4] = { 0, 0, 0, 0 };
u32 motion_regions = 0;
unsigned stride = (go->width + 7) >> 3;
@@ -458,25 +458,26 @@ static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buf
go->next_seq++;
return vb;
}
- bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ bytesused = &vb->vb.vb2_buf.planes[0].bytesused;
- vb->vb.v4l2_buf.sequence = go->next_seq++;
+ vb->vb.sequence = go->next_seq++;
if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
go7007_motion_regions(go, vb);
else
go7007_set_motion_regions(go, vb, 0);
- v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&vb->vb.timestamp);
vb_tmp = vb;
spin_lock(&go->spinlock);
list_del(&vb->list);
if (list_empty(&go->vidq_active))
vb = NULL;
else
- vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+ vb = list_first_entry(&go->vidq_active,
+ struct go7007_buffer, list);
go->active_buf = vb;
spin_unlock(&go->spinlock);
- vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&vb_tmp->vb.vb2_buf, VB2_BUF_STATE_DONE);
return vb;
}
@@ -519,9 +520,10 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
}
for (i = 0; i < length; ++i) {
- if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
+ if (vb && vb->vb.vb2_buf.planes[0].bytesused >=
+ GO7007_BUF_SIZE - 3) {
v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
- vb->vb.v4l2_planes[0].bytesused = 0;
+ vb->vb.vb2_buf.planes[0].bytesused = 0;
vb->frame_offset = 0;
vb->modet_active = 0;
vb = go->active_buf = NULL;
@@ -601,7 +603,8 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
vb = frame_boundary(go, vb);
go->seen_frame = buf[i] == frame_start_code;
if (vb && go->seen_frame)
- vb->frame_offset = vb->vb.v4l2_planes[0].bytesused;
+ vb->frame_offset =
+ vb->vb.vb2_buf.planes[0].bytesused;
}
/* Handle any special chunk types, or just write the
* start code to the (potentially new) buffer */
diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c
index 5f4c9b9e899a..60bf5f0644d1 100644
--- a/drivers/media/usb/go7007/go7007-fw.c
+++ b/drivers/media/usb/go7007/go7007-fw.c
@@ -379,7 +379,7 @@ static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
buf = kzalloc(4096, GFP_KERNEL);
if (buf == NULL)
- return -1;
+ return -ENOMEM;
for (i = 1; i < 32; ++i) {
mjpeg_frame_header(go, buf + size, i);
@@ -646,7 +646,7 @@ static int gen_mpeg1hdr_to_package(struct go7007 *go,
buf = kzalloc(5120, GFP_KERNEL);
if (buf == NULL)
- return -1;
+ return -ENOMEM;
framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
if (go->interlace_coding)
@@ -832,7 +832,7 @@ static int gen_mpeg4hdr_to_package(struct go7007 *go,
buf = kzalloc(5120, GFP_KERNEL);
if (buf == NULL)
- return -1;
+ return -ENOMEM;
framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
i = 368;
diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h
index 2251c3f99d1d..745185eb060b 100644
--- a/drivers/media/usb/go7007/go7007-priv.h
+++ b/drivers/media/usb/go7007/go7007-priv.h
@@ -20,7 +20,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
struct go7007;
@@ -136,7 +136,7 @@ struct go7007_hpi_ops {
#define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT)
struct go7007_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
unsigned int frame_offset;
u32 modet_active;
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index c57207e268c3..f3d187db9368 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -52,7 +52,7 @@ static bool valid_pixelformat(u32 pixelformat)
static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
{
- u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+ u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
switch (format) {
case V4L2_PIX_FMT_MJPEG:
@@ -369,7 +369,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
}
static int go7007_queue_setup(struct vb2_queue *q,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -386,8 +386,9 @@ static void go7007_buf_queue(struct vb2_buffer *vb)
{
struct vb2_queue *vq = vb->vb2_queue;
struct go7007 *go = vb2_get_drv_priv(vq);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct go7007_buffer *go7007_vb =
- container_of(vb, struct go7007_buffer, vb);
+ container_of(vbuf, struct go7007_buffer, vb);
unsigned long flags;
spin_lock_irqsave(&go->spinlock, flags);
@@ -397,12 +398,13 @@ static void go7007_buf_queue(struct vb2_buffer *vb)
static int go7007_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct go7007_buffer *go7007_vb =
- container_of(vb, struct go7007_buffer, vb);
+ container_of(vbuf, struct go7007_buffer, vb);
go7007_vb->modet_active = 0;
go7007_vb->frame_offset = 0;
- vb->v4l2_planes[0].bytesused = 0;
+ vb->planes[0].bytesused = 0;
return 0;
}
@@ -410,15 +412,15 @@ static void go7007_buf_finish(struct vb2_buffer *vb)
{
struct vb2_queue *vq = vb->vb2_queue;
struct go7007 *go = vb2_get_drv_priv(vq);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct go7007_buffer *go7007_vb =
- container_of(vb, struct go7007_buffer, vb);
+ container_of(vbuf, struct go7007_buffer, vb);
u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
- struct v4l2_buffer *buf = &vb->v4l2_buf;
- buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
+ vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
V4L2_BUF_FLAG_PFRAME);
- buf->flags |= frame_type_flag;
- buf->field = V4L2_FIELD_NONE;
+ vbuf->flags |= frame_type_flag;
+ vbuf->field = V4L2_FIELD_NONE;
}
static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index e54cee856a80..af5cd8213e8b 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -436,7 +436,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
}
j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j];
- frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get());
+ v4l2_get_timestamp(&frame->v4l2_buf.timestamp);
frame->v4l2_buf.sequence = gspca_dev->sequence++;
gspca_dev->image = frame->data;
gspca_dev->image_len = 0;
@@ -1909,7 +1909,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
}
/* get a frame */
- timestamp = ktime_to_timeval(ktime_get());
+ v4l2_get_timestamp(&timestamp);
timestamp.tv_sec--;
n = 2;
for (;;) {
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index fd1fa412e094..e05bfec90f46 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -21,6 +21,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
/* HackRF USB API commands (from HackRF Library) */
@@ -31,8 +32,10 @@ enum {
CMD_BOARD_ID_READ = 0x0e,
CMD_VERSION_STRING_READ = 0x0f,
CMD_SET_FREQ = 0x10,
+ CMD_AMP_ENABLE = 0x11,
CMD_SET_LNA_GAIN = 0x13,
CMD_SET_VGA_GAIN = 0x14,
+ CMD_SET_TXVGA_GAIN = 0x15,
};
/*
@@ -43,10 +46,10 @@ enum {
#define MAX_BULK_BUFS (6)
#define BULK_BUFFER_SIZE (128 * 512)
-static const struct v4l2_frequency_band bands_adc[] = {
+static const struct v4l2_frequency_band bands_adc_dac[] = {
{
.tuner = 0,
- .type = V4L2_TUNER_ADC,
+ .type = V4L2_TUNER_SDR,
.index = 0,
.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 200000,
@@ -54,7 +57,7 @@ static const struct v4l2_frequency_band bands_adc[] = {
},
};
-static const struct v4l2_frequency_band bands_rf[] = {
+static const struct v4l2_frequency_band bands_rx_tx[] = {
{
.tuner = 1,
.type = V4L2_TUNER_RF,
@@ -67,7 +70,6 @@ static const struct v4l2_frequency_band bands_rf[] = {
/* stream formats */
struct hackrf_format {
- char *name;
u32 pixelformat;
u32 buffersize;
};
@@ -75,7 +77,6 @@ struct hackrf_format {
/* format descriptions for capture and preview */
static struct hackrf_format formats[] = {
{
- .name = "Complex S8",
.pixelformat = V4L2_SDR_FMT_CS8,
.buffersize = BULK_BUFFER_SIZE,
},
@@ -84,28 +85,44 @@ static struct hackrf_format formats[] = {
static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
-struct hackrf_frame_buf {
- struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+struct hackrf_buffer {
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
struct hackrf_dev {
-#define POWER_ON (1 << 1)
-#define URB_BUF (1 << 2)
-#define USB_STATE_URB_BUF (1 << 3)
+#define USB_STATE_URB_BUF 1 /* XXX: set manually */
+#define RX_ON 4
+#define TX_ON 5
+#define RX_ADC_FREQUENCY 11
+#define TX_DAC_FREQUENCY 12
+#define RX_BANDWIDTH 13
+#define TX_BANDWIDTH 14
+#define RX_RF_FREQUENCY 15
+#define TX_RF_FREQUENCY 16
+#define RX_RF_GAIN 17
+#define TX_RF_GAIN 18
+#define RX_IF_GAIN 19
+#define RX_LNA_GAIN 20
+#define TX_LNA_GAIN 21
unsigned long flags;
+ struct usb_interface *intf;
struct device *dev;
struct usb_device *udev;
- struct video_device vdev;
+ struct video_device rx_vdev;
+ struct video_device tx_vdev;
struct v4l2_device v4l2_dev;
/* videobuf2 queue and queued buffers list */
- struct vb2_queue vb_queue;
- struct list_head queued_bufs;
- spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+ struct vb2_queue rx_vb2_queue;
+ struct vb2_queue tx_vb2_queue;
+ struct list_head rx_buffer_list;
+ struct list_head tx_buffer_list;
+ spinlock_t buffer_list_lock; /* Protects buffer_list */
unsigned sequence; /* Buffer sequence counter */
unsigned int vb_full; /* vb is full and packets dropped */
+ unsigned int vb_empty; /* vb is empty and packets dropped */
/* Note if taking both locks v4l2_lock must always be locked first! */
struct mutex v4l2_lock; /* Protects everything else */
@@ -125,16 +142,24 @@ struct hackrf_dev {
/* Current configuration */
unsigned int f_adc;
- unsigned int f_rf;
+ unsigned int f_dac;
+ unsigned int f_rx;
+ unsigned int f_tx;
u32 pixelformat;
u32 buffersize;
/* Controls */
- struct v4l2_ctrl_handler hdl;
- struct v4l2_ctrl *bandwidth_auto;
- struct v4l2_ctrl *bandwidth;
- struct v4l2_ctrl *lna_gain;
- struct v4l2_ctrl *if_gain;
+ struct v4l2_ctrl_handler rx_ctrl_handler;
+ struct v4l2_ctrl *rx_bandwidth_auto;
+ struct v4l2_ctrl *rx_bandwidth;
+ struct v4l2_ctrl *rx_rf_gain;
+ struct v4l2_ctrl *rx_lna_gain;
+ struct v4l2_ctrl *rx_if_gain;
+ struct v4l2_ctrl_handler tx_ctrl_handler;
+ struct v4l2_ctrl *tx_bandwidth_auto;
+ struct v4l2_ctrl *tx_bandwidth;
+ struct v4l2_ctrl *tx_rf_gain;
+ struct v4l2_ctrl *tx_lna_gain;
/* Sample rate calc */
unsigned long jiffies_next;
@@ -164,6 +189,7 @@ static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16 value,
switch (request) {
case CMD_SET_TRANSCEIVER_MODE:
case CMD_SET_FREQ:
+ case CMD_AMP_ENABLE:
case CMD_SAMPLE_RATE_SET:
case CMD_BASEBAND_FILTER_BANDWIDTH_SET:
pipe = usb_sndctrlpipe(dev->udev, 0);
@@ -173,6 +199,7 @@ static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16 value,
case CMD_VERSION_STRING_READ:
case CMD_SET_LNA_GAIN:
case CMD_SET_VGA_GAIN:
+ case CMD_SET_TXVGA_GAIN:
pipe = usb_rcvctrlpipe(dev->udev, 0);
requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
break;
@@ -205,25 +232,227 @@ err:
return ret;
}
+static int hackrf_set_params(struct hackrf_dev *dev)
+{
+ struct usb_interface *intf = dev->intf;
+ int ret, i;
+ u8 buf[8], u8tmp;
+ unsigned int uitmp, uitmp1, uitmp2;
+ const bool rx = test_bit(RX_ON, &dev->flags);
+ const bool tx = test_bit(TX_ON, &dev->flags);
+ static const struct {
+ u32 freq;
+ } bandwidth_lut[] = {
+ { 1750000}, /* 1.75 MHz */
+ { 2500000}, /* 2.5 MHz */
+ { 3500000}, /* 3.5 MHz */
+ { 5000000}, /* 5 MHz */
+ { 5500000}, /* 5.5 MHz */
+ { 6000000}, /* 6 MHz */
+ { 7000000}, /* 7 MHz */
+ { 8000000}, /* 8 MHz */
+ { 9000000}, /* 9 MHz */
+ {10000000}, /* 10 MHz */
+ {12000000}, /* 12 MHz */
+ {14000000}, /* 14 MHz */
+ {15000000}, /* 15 MHz */
+ {20000000}, /* 20 MHz */
+ {24000000}, /* 24 MHz */
+ {28000000}, /* 28 MHz */
+ };
+
+ if (!rx && !tx) {
+ dev_dbg(&intf->dev, "device is sleeping\n");
+ return 0;
+ }
+
+ /* ADC / DAC frequency */
+ if (rx && test_and_clear_bit(RX_ADC_FREQUENCY, &dev->flags)) {
+ dev_dbg(&intf->dev, "RX ADC frequency=%u Hz\n", dev->f_adc);
+ uitmp1 = dev->f_adc;
+ uitmp2 = 1;
+ set_bit(TX_DAC_FREQUENCY, &dev->flags);
+ } else if (tx && test_and_clear_bit(TX_DAC_FREQUENCY, &dev->flags)) {
+ dev_dbg(&intf->dev, "TX DAC frequency=%u Hz\n", dev->f_dac);
+ uitmp1 = dev->f_dac;
+ uitmp2 = 1;
+ set_bit(RX_ADC_FREQUENCY, &dev->flags);
+ } else {
+ uitmp1 = uitmp2 = 0;
+ }
+ if (uitmp1 || uitmp2) {
+ buf[0] = (uitmp1 >> 0) & 0xff;
+ buf[1] = (uitmp1 >> 8) & 0xff;
+ buf[2] = (uitmp1 >> 16) & 0xff;
+ buf[3] = (uitmp1 >> 24) & 0xff;
+ buf[4] = (uitmp2 >> 0) & 0xff;
+ buf[5] = (uitmp2 >> 8) & 0xff;
+ buf[6] = (uitmp2 >> 16) & 0xff;
+ buf[7] = (uitmp2 >> 24) & 0xff;
+ ret = hackrf_ctrl_msg(dev, CMD_SAMPLE_RATE_SET, 0, 0, buf, 8);
+ if (ret)
+ goto err;
+ }
+
+ /* bandwidth */
+ if (rx && test_and_clear_bit(RX_BANDWIDTH, &dev->flags)) {
+ if (dev->rx_bandwidth_auto->val == true)
+ uitmp = dev->f_adc;
+ else
+ uitmp = dev->rx_bandwidth->val;
+
+ for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
+ if (uitmp <= bandwidth_lut[i].freq) {
+ uitmp = bandwidth_lut[i].freq;
+ break;
+ }
+ }
+ dev->rx_bandwidth->val = uitmp;
+ dev->rx_bandwidth->cur.val = uitmp;
+ dev_dbg(&intf->dev, "RX bandwidth selected=%u\n", uitmp);
+ set_bit(TX_BANDWIDTH, &dev->flags);
+ } else if (tx && test_and_clear_bit(TX_BANDWIDTH, &dev->flags)) {
+ if (dev->tx_bandwidth_auto->val == true)
+ uitmp = dev->f_dac;
+ else
+ uitmp = dev->tx_bandwidth->val;
+
+ for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
+ if (uitmp <= bandwidth_lut[i].freq) {
+ uitmp = bandwidth_lut[i].freq;
+ break;
+ }
+ }
+ dev->tx_bandwidth->val = uitmp;
+ dev->tx_bandwidth->cur.val = uitmp;
+ dev_dbg(&intf->dev, "TX bandwidth selected=%u\n", uitmp);
+ set_bit(RX_BANDWIDTH, &dev->flags);
+ } else {
+ uitmp = 0;
+ }
+ if (uitmp) {
+ uitmp1 = uitmp2 = 0;
+ uitmp1 |= ((uitmp >> 0) & 0xff) << 0;
+ uitmp1 |= ((uitmp >> 8) & 0xff) << 8;
+ uitmp2 |= ((uitmp >> 16) & 0xff) << 0;
+ uitmp2 |= ((uitmp >> 24) & 0xff) << 8;
+ ret = hackrf_ctrl_msg(dev, CMD_BASEBAND_FILTER_BANDWIDTH_SET,
+ uitmp1, uitmp2, NULL, 0);
+ if (ret)
+ goto err;
+ }
+
+ /* RX / TX RF frequency */
+ if (rx && test_and_clear_bit(RX_RF_FREQUENCY, &dev->flags)) {
+ dev_dbg(&intf->dev, "RX RF frequency=%u Hz\n", dev->f_rx);
+ uitmp1 = dev->f_rx / 1000000;
+ uitmp2 = dev->f_rx % 1000000;
+ set_bit(TX_RF_FREQUENCY, &dev->flags);
+ } else if (tx && test_and_clear_bit(TX_RF_FREQUENCY, &dev->flags)) {
+ dev_dbg(&intf->dev, "TX RF frequency=%u Hz\n", dev->f_tx);
+ uitmp1 = dev->f_tx / 1000000;
+ uitmp2 = dev->f_tx % 1000000;
+ set_bit(RX_RF_FREQUENCY, &dev->flags);
+ } else {
+ uitmp1 = uitmp2 = 0;
+ }
+ if (uitmp1 || uitmp2) {
+ buf[0] = (uitmp1 >> 0) & 0xff;
+ buf[1] = (uitmp1 >> 8) & 0xff;
+ buf[2] = (uitmp1 >> 16) & 0xff;
+ buf[3] = (uitmp1 >> 24) & 0xff;
+ buf[4] = (uitmp2 >> 0) & 0xff;
+ buf[5] = (uitmp2 >> 8) & 0xff;
+ buf[6] = (uitmp2 >> 16) & 0xff;
+ buf[7] = (uitmp2 >> 24) & 0xff;
+ ret = hackrf_ctrl_msg(dev, CMD_SET_FREQ, 0, 0, buf, 8);
+ if (ret)
+ goto err;
+ }
+
+ /* RX RF gain */
+ if (rx && test_and_clear_bit(RX_RF_GAIN, &dev->flags)) {
+ dev_dbg(&intf->dev, "RX RF gain val=%d->%d\n",
+ dev->rx_rf_gain->cur.val, dev->rx_rf_gain->val);
+
+ u8tmp = (dev->rx_rf_gain->val) ? 1 : 0;
+ ret = hackrf_ctrl_msg(dev, CMD_AMP_ENABLE, u8tmp, 0, NULL, 0);
+ if (ret)
+ goto err;
+ set_bit(TX_RF_GAIN, &dev->flags);
+ }
+
+ /* TX RF gain */
+ if (tx && test_and_clear_bit(TX_RF_GAIN, &dev->flags)) {
+ dev_dbg(&intf->dev, "TX RF gain val=%d->%d\n",
+ dev->tx_rf_gain->cur.val, dev->tx_rf_gain->val);
+
+ u8tmp = (dev->tx_rf_gain->val) ? 1 : 0;
+ ret = hackrf_ctrl_msg(dev, CMD_AMP_ENABLE, u8tmp, 0, NULL, 0);
+ if (ret)
+ goto err;
+ set_bit(RX_RF_GAIN, &dev->flags);
+ }
+
+ /* RX LNA gain */
+ if (rx && test_and_clear_bit(RX_LNA_GAIN, &dev->flags)) {
+ dev_dbg(dev->dev, "RX LNA gain val=%d->%d\n",
+ dev->rx_lna_gain->cur.val, dev->rx_lna_gain->val);
+
+ ret = hackrf_ctrl_msg(dev, CMD_SET_LNA_GAIN, 0,
+ dev->rx_lna_gain->val, &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+
+ /* RX IF gain */
+ if (rx && test_and_clear_bit(RX_IF_GAIN, &dev->flags)) {
+ dev_dbg(&intf->dev, "IF gain val=%d->%d\n",
+ dev->rx_if_gain->cur.val, dev->rx_if_gain->val);
+
+ ret = hackrf_ctrl_msg(dev, CMD_SET_VGA_GAIN, 0,
+ dev->rx_if_gain->val, &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+
+ /* TX LNA gain */
+ if (tx && test_and_clear_bit(TX_LNA_GAIN, &dev->flags)) {
+ dev_dbg(&intf->dev, "TX LNA gain val=%d->%d\n",
+ dev->tx_lna_gain->cur.val, dev->tx_lna_gain->val);
+
+ ret = hackrf_ctrl_msg(dev, CMD_SET_TXVGA_GAIN, 0,
+ dev->tx_lna_gain->val, &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
+ return ret;
+}
+
/* Private functions */
-static struct hackrf_frame_buf *hackrf_get_next_fill_buf(struct hackrf_dev *dev)
+static struct hackrf_buffer *hackrf_get_next_buffer(struct hackrf_dev *dev,
+ struct list_head *buffer_list)
{
unsigned long flags;
- struct hackrf_frame_buf *buf = NULL;
+ struct hackrf_buffer *buffer = NULL;
- spin_lock_irqsave(&dev->queued_bufs_lock, flags);
- if (list_empty(&dev->queued_bufs))
+ spin_lock_irqsave(&dev->buffer_list_lock, flags);
+ if (list_empty(buffer_list))
goto leave;
- buf = list_entry(dev->queued_bufs.next, struct hackrf_frame_buf, list);
- list_del(&buf->list);
+ buffer = list_entry(buffer_list->next, struct hackrf_buffer, list);
+ list_del(&buffer->list);
leave:
- spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
- return buf;
+ spin_unlock_irqrestore(&dev->buffer_list_lock, flags);
+ return buffer;
}
-static unsigned int hackrf_convert_stream(struct hackrf_dev *dev,
- void *dst, void *src, unsigned int src_len)
+static void hackrf_copy_stream(struct hackrf_dev *dev, void *dst, void *src,
+ unsigned int src_len)
{
memcpy(dst, src, src_len);
@@ -243,22 +472,21 @@ static unsigned int hackrf_convert_stream(struct hackrf_dev *dev,
/* total number of samples */
dev->sample += src_len / 2;
-
- return src_len;
}
/*
* This gets called for the bulk stream pipe. This is done in interrupt
* time, so it has to be fast, not crash, and not stall. Neat.
*/
-static void hackrf_urb_complete(struct urb *urb)
+static void hackrf_urb_complete_in(struct urb *urb)
{
struct hackrf_dev *dev = urb->context;
- struct hackrf_frame_buf *fbuf;
+ struct usb_interface *intf = dev->intf;
+ struct hackrf_buffer *buffer;
+ unsigned int len;
- dev_dbg_ratelimited(dev->dev, "status=%d length=%d/%d errors=%d\n",
- urb->status, urb->actual_length,
- urb->transfer_buffer_length, urb->error_count);
+ dev_dbg_ratelimited(&intf->dev, "status=%d length=%u/%u\n", urb->status,
+ urb->actual_length, urb->transfer_buffer_length);
switch (urb->status) {
case 0: /* success */
@@ -269,33 +497,74 @@ static void hackrf_urb_complete(struct urb *urb)
case -ESHUTDOWN:
return;
default: /* error */
- dev_err_ratelimited(dev->dev, "URB failed %d\n", urb->status);
- break;
+ dev_err_ratelimited(&intf->dev, "URB failed %d\n", urb->status);
+ goto exit_usb_submit_urb;
}
- if (likely(urb->actual_length > 0)) {
- void *ptr;
- unsigned int len;
- /* get free framebuffer */
- fbuf = hackrf_get_next_fill_buf(dev);
- if (unlikely(fbuf == NULL)) {
- dev->vb_full++;
- dev_notice_ratelimited(dev->dev,
- "videobuf is full, %d packets dropped\n",
- dev->vb_full);
- goto skip;
- }
+ /* get buffer to write */
+ buffer = hackrf_get_next_buffer(dev, &dev->rx_buffer_list);
+ if (unlikely(buffer == NULL)) {
+ dev->vb_full++;
+ dev_notice_ratelimited(&intf->dev,
+ "buffer is full - %u packets dropped\n",
+ dev->vb_full);
+ goto exit_usb_submit_urb;
+ }
+
+ len = min_t(unsigned long, vb2_plane_size(&buffer->vb.vb2_buf, 0),
+ urb->actual_length);
+ hackrf_copy_stream(dev, vb2_plane_vaddr(&buffer->vb.vb2_buf, 0),
+ urb->transfer_buffer, len);
+ vb2_set_plane_payload(&buffer->vb.vb2_buf, 0, len);
+ buffer->vb.sequence = dev->sequence++;
+ v4l2_get_timestamp(&buffer->vb.timestamp);
+ vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE);
+exit_usb_submit_urb:
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static void hackrf_urb_complete_out(struct urb *urb)
+{
+ struct hackrf_dev *dev = urb->context;
+ struct usb_interface *intf = dev->intf;
+ struct hackrf_buffer *buffer;
+ unsigned int len;
+
+ dev_dbg_ratelimited(&intf->dev, "status=%d length=%u/%u\n", urb->status,
+ urb->actual_length, urb->transfer_buffer_length);
+
+ switch (urb->status) {
+ case 0: /* success */
+ case -ETIMEDOUT: /* NAK */
+ break;
+ case -ECONNRESET: /* kill */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* error */
+ dev_err_ratelimited(&intf->dev, "URB failed %d\n", urb->status);
+ }
- /* fill framebuffer */
- ptr = vb2_plane_vaddr(&fbuf->vb, 0);
- len = hackrf_convert_stream(dev, ptr, urb->transfer_buffer,
- urb->actual_length);
- vb2_set_plane_payload(&fbuf->vb, 0, len);
- v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
- fbuf->vb.v4l2_buf.sequence = dev->sequence++;
- vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ /* get buffer to read */
+ buffer = hackrf_get_next_buffer(dev, &dev->tx_buffer_list);
+ if (unlikely(buffer == NULL)) {
+ dev->vb_empty++;
+ dev_notice_ratelimited(&intf->dev,
+ "buffer is empty - %u packets dropped\n",
+ dev->vb_empty);
+ urb->actual_length = 0;
+ goto exit_usb_submit_urb;
}
-skip:
+
+ len = min_t(unsigned long, urb->transfer_buffer_length,
+ vb2_get_plane_payload(&buffer->vb.vb2_buf, 0));
+ hackrf_copy_stream(dev, urb->transfer_buffer,
+ vb2_plane_vaddr(&buffer->vb.vb2_buf, 0), len);
+ urb->actual_length = len;
+ buffer->vb.sequence = dev->sequence++;
+ v4l2_get_timestamp(&buffer->vb.timestamp);
+ vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE);
+exit_usb_submit_urb:
usb_submit_urb(urb, GFP_ATOMIC);
}
@@ -394,9 +663,19 @@ static int hackrf_free_urbs(struct hackrf_dev *dev)
return 0;
}
-static int hackrf_alloc_urbs(struct hackrf_dev *dev)
+static int hackrf_alloc_urbs(struct hackrf_dev *dev, bool rcv)
{
int i, j;
+ unsigned int pipe;
+ usb_complete_t complete;
+
+ if (rcv) {
+ pipe = usb_rcvbulkpipe(dev->udev, 0x81);
+ complete = &hackrf_urb_complete_in;
+ } else {
+ pipe = usb_sndbulkpipe(dev->udev, 0x02);
+ complete = &hackrf_urb_complete_out;
+ }
/* allocate the URBs */
for (i = 0; i < MAX_BULK_BUFS; i++) {
@@ -410,10 +689,10 @@ static int hackrf_alloc_urbs(struct hackrf_dev *dev)
}
usb_fill_bulk_urb(dev->urb_list[i],
dev->udev,
- usb_rcvbulkpipe(dev->udev, 0x81),
+ pipe,
dev->buf_list[i],
BULK_BUFFER_SIZE,
- hackrf_urb_complete, dev);
+ complete, dev);
dev->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
dev->urb_list[i]->transfer_dma = dev->dma_addr[i];
@@ -423,25 +702,6 @@ static int hackrf_alloc_urbs(struct hackrf_dev *dev)
return 0;
}
-/* Must be called with vb_queue_lock hold */
-static void hackrf_cleanup_queued_bufs(struct hackrf_dev *dev)
-{
- unsigned long flags;
-
- dev_dbg(dev->dev, "\n");
-
- spin_lock_irqsave(&dev->queued_bufs_lock, flags);
- while (!list_empty(&dev->queued_bufs)) {
- struct hackrf_frame_buf *buf;
-
- buf = list_entry(dev->queued_bufs.next,
- struct hackrf_frame_buf, list);
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
-}
-
/* The user yanked out the cable... */
static void hackrf_disconnect(struct usb_interface *intf)
{
@@ -455,7 +715,8 @@ static void hackrf_disconnect(struct usb_interface *intf)
/* No need to keep the urbs around after disconnection */
dev->udev = NULL;
v4l2_device_disconnect(&dev->v4l2_dev);
- video_unregister_device(&dev->vdev);
+ video_unregister_device(&dev->tx_vdev);
+ video_unregister_device(&dev->rx_vdev);
mutex_unlock(&dev->v4l2_lock);
mutex_unlock(&dev->vb_queue_lock);
@@ -463,8 +724,33 @@ static void hackrf_disconnect(struct usb_interface *intf)
}
/* Videobuf2 operations */
+static void hackrf_return_all_buffers(struct vb2_queue *vq,
+ enum vb2_buffer_state state)
+{
+ struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+ struct usb_interface *intf = dev->intf;
+ struct hackrf_buffer *buffer, *node;
+ struct list_head *buffer_list;
+ unsigned long flags;
+
+ dev_dbg(&intf->dev, "\n");
+
+ if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE)
+ buffer_list = &dev->rx_buffer_list;
+ else
+ buffer_list = &dev->tx_buffer_list;
+
+ spin_lock_irqsave(&dev->buffer_list_lock, flags);
+ list_for_each_entry_safe(buffer, node, buffer_list, list) {
+ dev_dbg(&intf->dev, "list_for_each_entry_safe\n");
+ vb2_buffer_done(&buffer->vb.vb2_buf, state);
+ list_del(&buffer->list);
+ }
+ spin_unlock_irqrestore(&dev->buffer_list_lock, flags);
+}
+
static int hackrf_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt, unsigned int *nbuffers,
+ const void *parg, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
struct hackrf_dev *dev = vb2_get_drv_priv(vq);
@@ -483,37 +769,62 @@ static int hackrf_queue_setup(struct vb2_queue *vq,
static void hackrf_buf_queue(struct vb2_buffer *vb)
{
- struct hackrf_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct hackrf_frame_buf *buf =
- container_of(vb, struct hackrf_frame_buf, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+ struct hackrf_buffer *buffer = container_of(vbuf, struct hackrf_buffer, vb);
+ struct list_head *buffer_list;
unsigned long flags;
- spin_lock_irqsave(&dev->queued_bufs_lock, flags);
- list_add_tail(&buf->list, &dev->queued_bufs);
- spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
+ dev_dbg_ratelimited(&dev->intf->dev, "\n");
+
+ if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE)
+ buffer_list = &dev->rx_buffer_list;
+ else
+ buffer_list = &dev->tx_buffer_list;
+
+ spin_lock_irqsave(&dev->buffer_list_lock, flags);
+ list_add_tail(&buffer->list, buffer_list);
+ spin_unlock_irqrestore(&dev->buffer_list_lock, flags);
}
static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+ struct usb_interface *intf = dev->intf;
int ret;
+ unsigned int mode;
- dev_dbg(dev->dev, "\n");
-
- if (!dev->udev)
- return -ENODEV;
+ dev_dbg(&intf->dev, "count=%i\n", count);
mutex_lock(&dev->v4l2_lock);
- dev->sequence = 0;
+ /* Allow only RX or TX, not both same time */
+ if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE) {
+ if (test_bit(TX_ON, &dev->flags)) {
+ ret = -EBUSY;
+ goto err_hackrf_return_all_buffers;
+ }
+
+ mode = 1;
+ set_bit(RX_ON, &dev->flags);
+ } else {
+ if (test_bit(RX_ON, &dev->flags)) {
+ ret = -EBUSY;
+ goto err_hackrf_return_all_buffers;
+ }
+
+ mode = 2;
+ set_bit(TX_ON, &dev->flags);
+ }
- set_bit(POWER_ON, &dev->flags);
+ dev->sequence = 0;
ret = hackrf_alloc_stream_bufs(dev);
if (ret)
goto err;
- ret = hackrf_alloc_urbs(dev);
+ ret = hackrf_alloc_urbs(dev, (mode == 1));
if (ret)
goto err;
@@ -521,39 +832,37 @@ static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret)
goto err;
+ ret = hackrf_set_params(dev);
+ if (ret)
+ goto err;
+
/* start hardware streaming */
- ret = hackrf_ctrl_msg(dev, CMD_SET_TRANSCEIVER_MODE, 1, 0, NULL, 0);
+ ret = hackrf_ctrl_msg(dev, CMD_SET_TRANSCEIVER_MODE, mode, 0, NULL, 0);
if (ret)
goto err;
- goto exit_mutex_unlock;
+ mutex_unlock(&dev->v4l2_lock);
+
+ return 0;
err:
hackrf_kill_urbs(dev);
hackrf_free_urbs(dev);
hackrf_free_stream_bufs(dev);
- clear_bit(POWER_ON, &dev->flags);
-
- /* return all queued buffers to vb2 */
- {
- struct hackrf_frame_buf *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp, &dev->queued_bufs, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
- }
- }
-
-exit_mutex_unlock:
+ clear_bit(RX_ON, &dev->flags);
+ clear_bit(TX_ON, &dev->flags);
+err_hackrf_return_all_buffers:
+ hackrf_return_all_buffers(vq, VB2_BUF_STATE_QUEUED);
mutex_unlock(&dev->v4l2_lock);
-
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
return ret;
}
static void hackrf_stop_streaming(struct vb2_queue *vq)
{
struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+ struct usb_interface *intf = dev->intf;
- dev_dbg(dev->dev, "\n");
+ dev_dbg(&intf->dev, "\n");
mutex_lock(&dev->v4l2_lock);
@@ -564,9 +873,12 @@ static void hackrf_stop_streaming(struct vb2_queue *vq)
hackrf_free_urbs(dev);
hackrf_free_stream_bufs(dev);
- hackrf_cleanup_queued_bufs(dev);
+ hackrf_return_all_buffers(vq, VB2_BUF_STATE_ERROR);
- clear_bit(POWER_ON, &dev->flags);
+ if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE)
+ clear_bit(RX_ON, &dev->flags);
+ else
+ clear_bit(TX_ON, &dev->flags);
mutex_unlock(&dev->v4l2_lock);
}
@@ -584,29 +896,46 @@ static int hackrf_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{
struct hackrf_dev *dev = video_drvdata(file);
+ struct usb_interface *intf = dev->intf;
+ struct video_device *vdev = video_devdata(file);
- dev_dbg(dev->dev, "\n");
+ dev_dbg(&intf->dev, "\n");
+
+ if (vdev->vfl_dir == VFL_DIR_RX)
+ cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+ else
+ cap->device_caps = V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+
+ cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
+ V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
+ V4L2_CAP_DEVICE_CAPS;
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, dev->vdev.name, sizeof(cap->card));
+ strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
- V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
-static int hackrf_s_fmt_sdr_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int hackrf_s_fmt_sdr(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct hackrf_dev *dev = video_drvdata(file);
- struct vb2_queue *q = &dev->vb_queue;
+ struct video_device *vdev = video_devdata(file);
+ struct vb2_queue *q;
int i;
dev_dbg(dev->dev, "pixelformat fourcc %4.4s\n",
(char *)&f->fmt.sdr.pixelformat);
+ if (vdev->vfl_dir == VFL_DIR_RX)
+ q = &dev->rx_vb2_queue;
+ else
+ q = &dev->tx_vb2_queue;
+
if (vb2_is_busy(q))
return -EBUSY;
@@ -628,8 +957,8 @@ static int hackrf_s_fmt_sdr_cap(struct file *file, void *priv,
return 0;
}
-static int hackrf_g_fmt_sdr_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int hackrf_g_fmt_sdr(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct hackrf_dev *dev = video_drvdata(file);
@@ -643,8 +972,8 @@ static int hackrf_g_fmt_sdr_cap(struct file *file, void *priv,
return 0;
}
-static int hackrf_try_fmt_sdr_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int hackrf_try_fmt_sdr(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct hackrf_dev *dev = video_drvdata(file);
int i;
@@ -666,8 +995,8 @@ static int hackrf_try_fmt_sdr_cap(struct file *file, void *priv,
return 0;
}
-static int hackrf_enum_fmt_sdr_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+static int hackrf_enum_fmt_sdr(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
{
struct hackrf_dev *dev = video_drvdata(file);
@@ -676,7 +1005,6 @@ static int hackrf_enum_fmt_sdr_cap(struct file *file, void *priv,
if (f->index >= NUM_FORMATS)
return -EINVAL;
- strlcpy(f->description, formats[f->index].name, sizeof(f->description));
f->pixelformat = formats[f->index].pixelformat;
return 0;
@@ -709,17 +1037,56 @@ static int hackrf_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
if (v->index == 0) {
strlcpy(v->name, "HackRF ADC", sizeof(v->name));
- v->type = V4L2_TUNER_ADC;
+ v->type = V4L2_TUNER_SDR;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
- v->rangelow = bands_adc[0].rangelow;
- v->rangehigh = bands_adc[0].rangehigh;
+ v->rangelow = bands_adc_dac[0].rangelow;
+ v->rangehigh = bands_adc_dac[0].rangehigh;
ret = 0;
} else if (v->index == 1) {
strlcpy(v->name, "HackRF RF", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
- v->rangelow = bands_rf[0].rangelow;
- v->rangehigh = bands_rf[0].rangehigh;
+ v->rangelow = bands_rx_tx[0].rangelow;
+ v->rangehigh = bands_rx_tx[0].rangehigh;
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int hackrf_s_modulator(struct file *file, void *fh,
+ const struct v4l2_modulator *a)
+{
+ struct hackrf_dev *dev = video_drvdata(file);
+
+ dev_dbg(dev->dev, "index=%d\n", a->index);
+
+ return a->index > 1 ? -EINVAL : 0;
+}
+
+static int hackrf_g_modulator(struct file *file, void *fh,
+ struct v4l2_modulator *a)
+{
+ struct hackrf_dev *dev = video_drvdata(file);
+ int ret;
+
+ dev_dbg(dev->dev, "index=%d\n", a->index);
+
+ if (a->index == 0) {
+ strlcpy(a->name, "HackRF DAC", sizeof(a->name));
+ a->type = V4L2_TUNER_SDR;
+ a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ a->rangelow = bands_adc_dac[0].rangelow;
+ a->rangehigh = bands_adc_dac[0].rangehigh;
+ ret = 0;
+ } else if (a->index == 1) {
+ strlcpy(a->name, "HackRF RF", sizeof(a->name));
+ a->type = V4L2_TUNER_RF;
+ a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ a->rangelow = bands_rx_tx[0].rangelow;
+ a->rangehigh = bands_rx_tx[0].rangehigh;
ret = 0;
} else {
ret = -EINVAL;
@@ -732,47 +1099,46 @@ static int hackrf_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct hackrf_dev *dev = video_drvdata(file);
+ struct usb_interface *intf = dev->intf;
+ struct video_device *vdev = video_devdata(file);
int ret;
- unsigned int upper, lower;
- u8 buf[8];
+ unsigned int uitmp;
- dev_dbg(dev->dev, "tuner=%d type=%d frequency=%u\n",
+ dev_dbg(&intf->dev, "tuner=%d type=%d frequency=%u\n",
f->tuner, f->type, f->frequency);
if (f->tuner == 0) {
- dev->f_adc = clamp_t(unsigned int, f->frequency,
- bands_adc[0].rangelow, bands_adc[0].rangehigh);
- dev_dbg(dev->dev, "ADC frequency=%u Hz\n", dev->f_adc);
- upper = dev->f_adc;
- lower = 1;
- buf[0] = (upper >> 0) & 0xff;
- buf[1] = (upper >> 8) & 0xff;
- buf[2] = (upper >> 16) & 0xff;
- buf[3] = (upper >> 24) & 0xff;
- buf[4] = (lower >> 0) & 0xff;
- buf[5] = (lower >> 8) & 0xff;
- buf[6] = (lower >> 16) & 0xff;
- buf[7] = (lower >> 24) & 0xff;
- ret = hackrf_ctrl_msg(dev, CMD_SAMPLE_RATE_SET, 0, 0, buf, 8);
+ uitmp = clamp(f->frequency, bands_adc_dac[0].rangelow,
+ bands_adc_dac[0].rangehigh);
+ if (vdev->vfl_dir == VFL_DIR_RX) {
+ dev->f_adc = uitmp;
+ set_bit(RX_ADC_FREQUENCY, &dev->flags);
+ } else {
+ dev->f_dac = uitmp;
+ set_bit(TX_DAC_FREQUENCY, &dev->flags);
+ }
} else if (f->tuner == 1) {
- dev->f_rf = clamp_t(unsigned int, f->frequency,
- bands_rf[0].rangelow, bands_rf[0].rangehigh);
- dev_dbg(dev->dev, "RF frequency=%u Hz\n", dev->f_rf);
- upper = dev->f_rf / 1000000;
- lower = dev->f_rf % 1000000;
- buf[0] = (upper >> 0) & 0xff;
- buf[1] = (upper >> 8) & 0xff;
- buf[2] = (upper >> 16) & 0xff;
- buf[3] = (upper >> 24) & 0xff;
- buf[4] = (lower >> 0) & 0xff;
- buf[5] = (lower >> 8) & 0xff;
- buf[6] = (lower >> 16) & 0xff;
- buf[7] = (lower >> 24) & 0xff;
- ret = hackrf_ctrl_msg(dev, CMD_SET_FREQ, 0, 0, buf, 8);
+ uitmp = clamp(f->frequency, bands_rx_tx[0].rangelow,
+ bands_rx_tx[0].rangehigh);
+ if (vdev->vfl_dir == VFL_DIR_RX) {
+ dev->f_rx = uitmp;
+ set_bit(RX_RF_FREQUENCY, &dev->flags);
+ } else {
+ dev->f_tx = uitmp;
+ set_bit(TX_RF_FREQUENCY, &dev->flags);
+ }
} else {
ret = -EINVAL;
+ goto err;
}
+ ret = hackrf_set_params(dev);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
return ret;
}
@@ -780,22 +1146,32 @@ static int hackrf_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
struct hackrf_dev *dev = video_drvdata(file);
+ struct usb_interface *intf = dev->intf;
+ struct video_device *vdev = video_devdata(file);
int ret;
dev_dbg(dev->dev, "tuner=%d type=%d\n", f->tuner, f->type);
if (f->tuner == 0) {
- f->type = V4L2_TUNER_ADC;
- f->frequency = dev->f_adc;
- ret = 0;
+ f->type = V4L2_TUNER_SDR;
+ if (vdev->vfl_dir == VFL_DIR_RX)
+ f->frequency = dev->f_adc;
+ else
+ f->frequency = dev->f_dac;
} else if (f->tuner == 1) {
f->type = V4L2_TUNER_RF;
- f->frequency = dev->f_rf;
- ret = 0;
+ if (vdev->vfl_dir == VFL_DIR_RX)
+ f->frequency = dev->f_rx;
+ else
+ f->frequency = dev->f_tx;
} else {
ret = -EINVAL;
+ goto err;
}
+ return 0;
+err:
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
return ret;
}
@@ -809,17 +1185,17 @@ static int hackrf_enum_freq_bands(struct file *file, void *priv,
band->tuner, band->type, band->index);
if (band->tuner == 0) {
- if (band->index >= ARRAY_SIZE(bands_adc)) {
+ if (band->index >= ARRAY_SIZE(bands_adc_dac)) {
ret = -EINVAL;
} else {
- *band = bands_adc[band->index];
+ *band = bands_adc_dac[band->index];
ret = 0;
}
} else if (band->tuner == 1) {
- if (band->index >= ARRAY_SIZE(bands_rf)) {
+ if (band->index >= ARRAY_SIZE(bands_rx_tx)) {
ret = -EINVAL;
} else {
- *band = bands_rf[band->index];
+ *band = bands_rx_tx[band->index];
ret = 0;
}
} else {
@@ -832,10 +1208,15 @@ static int hackrf_enum_freq_bands(struct file *file, void *priv,
static const struct v4l2_ioctl_ops hackrf_ioctl_ops = {
.vidioc_querycap = hackrf_querycap,
- .vidioc_s_fmt_sdr_cap = hackrf_s_fmt_sdr_cap,
- .vidioc_g_fmt_sdr_cap = hackrf_g_fmt_sdr_cap,
- .vidioc_enum_fmt_sdr_cap = hackrf_enum_fmt_sdr_cap,
- .vidioc_try_fmt_sdr_cap = hackrf_try_fmt_sdr_cap,
+ .vidioc_s_fmt_sdr_cap = hackrf_s_fmt_sdr,
+ .vidioc_g_fmt_sdr_cap = hackrf_g_fmt_sdr,
+ .vidioc_enum_fmt_sdr_cap = hackrf_enum_fmt_sdr,
+ .vidioc_try_fmt_sdr_cap = hackrf_try_fmt_sdr,
+
+ .vidioc_s_fmt_sdr_out = hackrf_s_fmt_sdr,
+ .vidioc_g_fmt_sdr_out = hackrf_g_fmt_sdr,
+ .vidioc_enum_fmt_sdr_out = hackrf_enum_fmt_sdr,
+ .vidioc_try_fmt_sdr_out = hackrf_try_fmt_sdr,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
@@ -843,6 +1224,7 @@ static const struct v4l2_ioctl_ops hackrf_ioctl_ops = {
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
@@ -850,6 +1232,9 @@ static const struct v4l2_ioctl_ops hackrf_ioctl_ops = {
.vidioc_s_tuner = hackrf_s_tuner,
.vidioc_g_tuner = hackrf_g_tuner,
+ .vidioc_s_modulator = hackrf_s_modulator,
+ .vidioc_g_modulator = hackrf_g_modulator,
+
.vidioc_s_frequency = hackrf_s_frequency,
.vidioc_g_frequency = hackrf_g_frequency,
.vidioc_enum_freq_bands = hackrf_enum_freq_bands,
@@ -864,6 +1249,7 @@ static const struct v4l2_file_operations hackrf_fops = {
.open = v4l2_fh_open,
.release = vb2_fop_release,
.read = vb2_fop_read,
+ .write = vb2_fop_write,
.poll = vb2_fop_poll,
.mmap = vb2_fop_mmap,
.unlocked_ioctl = video_ioctl2,
@@ -880,135 +1266,93 @@ static void hackrf_video_release(struct v4l2_device *v)
{
struct hackrf_dev *dev = container_of(v, struct hackrf_dev, v4l2_dev);
- v4l2_ctrl_handler_free(&dev->hdl);
+ dev_dbg(dev->dev, "\n");
+
+ v4l2_ctrl_handler_free(&dev->rx_ctrl_handler);
+ v4l2_ctrl_handler_free(&dev->tx_ctrl_handler);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
}
-static int hackrf_set_bandwidth(struct hackrf_dev *dev)
-{
- int ret, i;
- u16 u16tmp, u16tmp2;
- unsigned int bandwidth;
-
- static const struct {
- u32 freq;
- } bandwidth_lut[] = {
- { 1750000}, /* 1.75 MHz */
- { 2500000}, /* 2.5 MHz */
- { 3500000}, /* 3.5 MHz */
- { 5000000}, /* 5 MHz */
- { 5500000}, /* 5.5 MHz */
- { 6000000}, /* 6 MHz */
- { 7000000}, /* 7 MHz */
- { 8000000}, /* 8 MHz */
- { 9000000}, /* 9 MHz */
- {10000000}, /* 10 MHz */
- {12000000}, /* 12 MHz */
- {14000000}, /* 14 MHz */
- {15000000}, /* 15 MHz */
- {20000000}, /* 20 MHz */
- {24000000}, /* 24 MHz */
- {28000000}, /* 28 MHz */
- };
-
- dev_dbg(dev->dev, "bandwidth auto=%d->%d val=%d->%d f_adc=%u\n",
- dev->bandwidth_auto->cur.val,
- dev->bandwidth_auto->val, dev->bandwidth->cur.val,
- dev->bandwidth->val, dev->f_adc);
-
- if (dev->bandwidth_auto->val == true)
- bandwidth = dev->f_adc;
- else
- bandwidth = dev->bandwidth->val;
-
- for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
- if (bandwidth <= bandwidth_lut[i].freq) {
- bandwidth = bandwidth_lut[i].freq;
- break;
- }
- }
-
- dev->bandwidth->val = bandwidth;
- dev->bandwidth->cur.val = bandwidth;
-
- dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth);
-
- u16tmp = 0;
- u16tmp |= ((bandwidth >> 0) & 0xff) << 0;
- u16tmp |= ((bandwidth >> 8) & 0xff) << 8;
- u16tmp2 = 0;
- u16tmp2 |= ((bandwidth >> 16) & 0xff) << 0;
- u16tmp2 |= ((bandwidth >> 24) & 0xff) << 8;
-
- ret = hackrf_ctrl_msg(dev, CMD_BASEBAND_FILTER_BANDWIDTH_SET,
- u16tmp, u16tmp2, NULL, 0);
- if (ret)
- dev_dbg(dev->dev, "failed=%d\n", ret);
-
- return ret;
-}
-
-static int hackrf_set_lna_gain(struct hackrf_dev *dev)
-{
- int ret;
- u8 u8tmp;
-
- dev_dbg(dev->dev, "lna val=%d->%d\n",
- dev->lna_gain->cur.val, dev->lna_gain->val);
-
- ret = hackrf_ctrl_msg(dev, CMD_SET_LNA_GAIN, 0, dev->lna_gain->val,
- &u8tmp, 1);
- if (ret)
- dev_dbg(dev->dev, "failed=%d\n", ret);
-
- return ret;
-}
-
-static int hackrf_set_if_gain(struct hackrf_dev *dev)
+static int hackrf_s_ctrl_rx(struct v4l2_ctrl *ctrl)
{
+ struct hackrf_dev *dev = container_of(ctrl->handler,
+ struct hackrf_dev, rx_ctrl_handler);
+ struct usb_interface *intf = dev->intf;
int ret;
- u8 u8tmp;
- dev_dbg(dev->dev, "val=%d->%d\n",
- dev->if_gain->cur.val, dev->if_gain->val);
+ switch (ctrl->id) {
+ case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
+ case V4L2_CID_RF_TUNER_BANDWIDTH:
+ set_bit(RX_BANDWIDTH, &dev->flags);
+ break;
+ case V4L2_CID_RF_TUNER_RF_GAIN:
+ set_bit(RX_RF_GAIN, &dev->flags);
+ break;
+ case V4L2_CID_RF_TUNER_LNA_GAIN:
+ set_bit(RX_LNA_GAIN, &dev->flags);
+ break;
+ case V4L2_CID_RF_TUNER_IF_GAIN:
+ set_bit(RX_IF_GAIN, &dev->flags);
+ break;
+ default:
+ dev_dbg(&intf->dev, "unknown ctrl: id=%d name=%s\n",
+ ctrl->id, ctrl->name);
+ ret = -EINVAL;
+ goto err;
+ }
- ret = hackrf_ctrl_msg(dev, CMD_SET_VGA_GAIN, 0, dev->if_gain->val,
- &u8tmp, 1);
+ ret = hackrf_set_params(dev);
if (ret)
- dev_dbg(dev->dev, "failed=%d\n", ret);
+ goto err;
+ return 0;
+err:
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
return ret;
}
-static int hackrf_s_ctrl(struct v4l2_ctrl *ctrl)
+static int hackrf_s_ctrl_tx(struct v4l2_ctrl *ctrl)
{
struct hackrf_dev *dev = container_of(ctrl->handler,
- struct hackrf_dev, hdl);
+ struct hackrf_dev, tx_ctrl_handler);
+ struct usb_interface *intf = dev->intf;
int ret;
switch (ctrl->id) {
case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
case V4L2_CID_RF_TUNER_BANDWIDTH:
- ret = hackrf_set_bandwidth(dev);
+ set_bit(TX_BANDWIDTH, &dev->flags);
break;
case V4L2_CID_RF_TUNER_LNA_GAIN:
- ret = hackrf_set_lna_gain(dev);
+ set_bit(TX_LNA_GAIN, &dev->flags);
break;
- case V4L2_CID_RF_TUNER_IF_GAIN:
- ret = hackrf_set_if_gain(dev);
+ case V4L2_CID_RF_TUNER_RF_GAIN:
+ set_bit(TX_RF_GAIN, &dev->flags);
break;
default:
- dev_dbg(dev->dev, "unknown ctrl: id=%d name=%s\n",
- ctrl->id, ctrl->name);
+ dev_dbg(&intf->dev, "unknown ctrl: id=%d name=%s\n",
+ ctrl->id, ctrl->name);
ret = -EINVAL;
+ goto err;
}
+ ret = hackrf_set_params(dev);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
return ret;
}
-static const struct v4l2_ctrl_ops hackrf_ctrl_ops = {
- .s_ctrl = hackrf_s_ctrl,
+static const struct v4l2_ctrl_ops hackrf_ctrl_ops_rx = {
+ .s_ctrl = hackrf_s_ctrl_rx,
+};
+
+static const struct v4l2_ctrl_ops hackrf_ctrl_ops_tx = {
+ .s_ctrl = hackrf_s_ctrl_tx,
};
static int hackrf_probe(struct usb_interface *intf,
@@ -1019,19 +1363,29 @@ static int hackrf_probe(struct usb_interface *intf,
u8 u8tmp, buf[BUF_SIZE];
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL)
- return -ENOMEM;
+ if (!dev) {
+ ret = -ENOMEM;
+ goto err;
+ }
mutex_init(&dev->v4l2_lock);
mutex_init(&dev->vb_queue_lock);
- spin_lock_init(&dev->queued_bufs_lock);
- INIT_LIST_HEAD(&dev->queued_bufs);
+ spin_lock_init(&dev->buffer_list_lock);
+ INIT_LIST_HEAD(&dev->rx_buffer_list);
+ INIT_LIST_HEAD(&dev->tx_buffer_list);
+ dev->intf = intf;
dev->dev = &intf->dev;
dev->udev = interface_to_usbdev(intf);
- dev->f_adc = bands_adc[0].rangelow;
- dev->f_rf = bands_rf[0].rangelow;
dev->pixelformat = formats[0].pixelformat;
dev->buffersize = formats[0].buffersize;
+ dev->f_adc = bands_adc_dac[0].rangelow;
+ dev->f_dac = bands_adc_dac[0].rangelow;
+ dev->f_rx = bands_rx_tx[0].rangelow;
+ dev->f_tx = bands_rx_tx[0].rangelow;
+ set_bit(RX_ADC_FREQUENCY, &dev->flags);
+ set_bit(TX_DAC_FREQUENCY, &dev->flags);
+ set_bit(RX_RF_FREQUENCY, &dev->flags);
+ set_bit(TX_RF_FREQUENCY, &dev->flags);
/* Detect device */
ret = hackrf_ctrl_msg(dev, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
@@ -1040,83 +1394,143 @@ static int hackrf_probe(struct usb_interface *intf,
buf, BUF_SIZE);
if (ret) {
dev_err(dev->dev, "Could not detect board\n");
- goto err_free_mem;
+ goto err_kfree;
}
buf[BUF_SIZE - 1] = '\0';
-
dev_info(dev->dev, "Board ID: %02x\n", u8tmp);
dev_info(dev->dev, "Firmware version: %s\n", buf);
- /* Init videobuf2 queue structure */
- dev->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
- dev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
- dev->vb_queue.drv_priv = dev;
- dev->vb_queue.buf_struct_size = sizeof(struct hackrf_frame_buf);
- dev->vb_queue.ops = &hackrf_vb2_ops;
- dev->vb_queue.mem_ops = &vb2_vmalloc_memops;
- dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- ret = vb2_queue_init(&dev->vb_queue);
+ /* Init vb2 queue structure for receiver */
+ dev->rx_vb2_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+ dev->rx_vb2_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF |
+ VB2_READ;
+ dev->rx_vb2_queue.ops = &hackrf_vb2_ops;
+ dev->rx_vb2_queue.mem_ops = &vb2_vmalloc_memops;
+ dev->rx_vb2_queue.drv_priv = dev;
+ dev->rx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer);
+ dev->rx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ ret = vb2_queue_init(&dev->rx_vb2_queue);
if (ret) {
- dev_err(dev->dev, "Could not initialize vb2 queue\n");
- goto err_free_mem;
+ dev_err(dev->dev, "Could not initialize rx vb2 queue\n");
+ goto err_kfree;
}
- /* Init video_device structure */
- dev->vdev = hackrf_template;
- dev->vdev.queue = &dev->vb_queue;
- dev->vdev.queue->lock = &dev->vb_queue_lock;
- video_set_drvdata(&dev->vdev, dev);
+ /* Init vb2 queue structure for transmitter */
+ dev->tx_vb2_queue.type = V4L2_BUF_TYPE_SDR_OUTPUT;
+ dev->tx_vb2_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF |
+ VB2_WRITE;
+ dev->tx_vb2_queue.ops = &hackrf_vb2_ops;
+ dev->tx_vb2_queue.mem_ops = &vb2_vmalloc_memops;
+ dev->tx_vb2_queue.drv_priv = dev;
+ dev->tx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer);
+ dev->tx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ ret = vb2_queue_init(&dev->tx_vb2_queue);
+ if (ret) {
+ dev_err(dev->dev, "Could not initialize tx vb2 queue\n");
+ goto err_kfree;
+ }
+
+ /* Register controls for receiver */
+ v4l2_ctrl_handler_init(&dev->rx_ctrl_handler, 5);
+ dev->rx_bandwidth_auto = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+ &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+ 0, 1, 0, 1);
+ dev->rx_bandwidth = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+ &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_BANDWIDTH,
+ 1750000, 28000000, 50000, 1750000);
+ v4l2_ctrl_auto_cluster(2, &dev->rx_bandwidth_auto, 0, false);
+ dev->rx_rf_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+ &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_RF_GAIN, 0, 12, 12, 0);
+ dev->rx_lna_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+ &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 40, 8, 0);
+ dev->rx_if_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+ &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_IF_GAIN, 0, 62, 2, 0);
+ if (dev->rx_ctrl_handler.error) {
+ ret = dev->rx_ctrl_handler.error;
+ dev_err(dev->dev, "Could not initialize controls\n");
+ goto err_v4l2_ctrl_handler_free_rx;
+ }
+ v4l2_ctrl_handler_setup(&dev->rx_ctrl_handler);
+
+ /* Register controls for transmitter */
+ v4l2_ctrl_handler_init(&dev->tx_ctrl_handler, 4);
+ dev->tx_bandwidth_auto = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+ &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+ 0, 1, 0, 1);
+ dev->tx_bandwidth = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+ &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_BANDWIDTH,
+ 1750000, 28000000, 50000, 1750000);
+ v4l2_ctrl_auto_cluster(2, &dev->tx_bandwidth_auto, 0, false);
+ dev->tx_lna_gain = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+ &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 47, 1, 0);
+ dev->tx_rf_gain = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+ &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_RF_GAIN, 0, 15, 15, 0);
+ if (dev->tx_ctrl_handler.error) {
+ ret = dev->tx_ctrl_handler.error;
+ dev_err(dev->dev, "Could not initialize controls\n");
+ goto err_v4l2_ctrl_handler_free_tx;
+ }
+ v4l2_ctrl_handler_setup(&dev->tx_ctrl_handler);
/* Register the v4l2_device structure */
dev->v4l2_dev.release = hackrf_video_release;
ret = v4l2_device_register(&intf->dev, &dev->v4l2_dev);
if (ret) {
dev_err(dev->dev, "Failed to register v4l2-device (%d)\n", ret);
- goto err_free_mem;
+ goto err_v4l2_ctrl_handler_free_tx;
}
- /* Register controls */
- v4l2_ctrl_handler_init(&dev->hdl, 4);
- dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
- V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
- dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
- V4L2_CID_RF_TUNER_BANDWIDTH,
- 1750000, 28000000, 50000, 1750000);
- v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
- dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
- V4L2_CID_RF_TUNER_LNA_GAIN, 0, 40, 8, 0);
- dev->if_gain = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
- V4L2_CID_RF_TUNER_IF_GAIN, 0, 62, 2, 0);
- if (dev->hdl.error) {
- ret = dev->hdl.error;
- dev_err(dev->dev, "Could not initialize controls\n");
- goto err_free_controls;
+ /* Init video_device structure for receiver */
+ dev->rx_vdev = hackrf_template;
+ dev->rx_vdev.queue = &dev->rx_vb2_queue;
+ dev->rx_vdev.queue->lock = &dev->vb_queue_lock;
+ dev->rx_vdev.v4l2_dev = &dev->v4l2_dev;
+ dev->rx_vdev.ctrl_handler = &dev->rx_ctrl_handler;
+ dev->rx_vdev.lock = &dev->v4l2_lock;
+ dev->rx_vdev.vfl_dir = VFL_DIR_RX;
+ video_set_drvdata(&dev->rx_vdev, dev);
+ ret = video_register_device(&dev->rx_vdev, VFL_TYPE_SDR, -1);
+ if (ret) {
+ dev_err(dev->dev,
+ "Failed to register as video device (%d)\n", ret);
+ goto err_v4l2_device_unregister;
}
-
- v4l2_ctrl_handler_setup(&dev->hdl);
-
- dev->v4l2_dev.ctrl_handler = &dev->hdl;
- dev->vdev.v4l2_dev = &dev->v4l2_dev;
- dev->vdev.lock = &dev->v4l2_lock;
-
- ret = video_register_device(&dev->vdev, VFL_TYPE_SDR, -1);
+ dev_info(dev->dev, "Registered as %s\n",
+ video_device_node_name(&dev->rx_vdev));
+
+ /* Init video_device structure for transmitter */
+ dev->tx_vdev = hackrf_template;
+ dev->tx_vdev.queue = &dev->tx_vb2_queue;
+ dev->tx_vdev.queue->lock = &dev->vb_queue_lock;
+ dev->tx_vdev.v4l2_dev = &dev->v4l2_dev;
+ dev->tx_vdev.ctrl_handler = &dev->tx_ctrl_handler;
+ dev->tx_vdev.lock = &dev->v4l2_lock;
+ dev->tx_vdev.vfl_dir = VFL_DIR_TX;
+ video_set_drvdata(&dev->tx_vdev, dev);
+ ret = video_register_device(&dev->tx_vdev, VFL_TYPE_SDR, -1);
if (ret) {
- dev_err(dev->dev, "Failed to register as video device (%d)\n",
- ret);
- goto err_unregister_v4l2_dev;
+ dev_err(dev->dev,
+ "Failed to register as video device (%d)\n", ret);
+ goto err_video_unregister_device_rx;
}
dev_info(dev->dev, "Registered as %s\n",
- video_device_node_name(&dev->vdev));
+ video_device_node_name(&dev->tx_vdev));
+
dev_notice(dev->dev, "SDR API is still slightly experimental and functionality changes may follow\n");
return 0;
-
-err_free_controls:
- v4l2_ctrl_handler_free(&dev->hdl);
-err_unregister_v4l2_dev:
+err_video_unregister_device_rx:
+ video_unregister_device(&dev->rx_vdev);
+err_v4l2_device_unregister:
v4l2_device_unregister(&dev->v4l2_dev);
-err_free_mem:
+err_v4l2_ctrl_handler_free_tx:
+ v4l2_ctrl_handler_free(&dev->tx_ctrl_handler);
+err_v4l2_ctrl_handler_free_rx:
+ v4l2_ctrl_handler_free(&dev->rx_ctrl_handler);
+err_kfree:
kfree(dev);
+err:
+ dev_dbg(dev->dev, "failed=%d\n", ret);
return ret;
}
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
index 3f276d921cca..e06a21a4fbd9 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -28,6 +28,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <linux/usb.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <linux/spi/spi.h>
@@ -112,7 +113,8 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
struct msi2500_frame_buf {
- struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -431,10 +433,10 @@ static void msi2500_isoc_handler(struct urb *urb)
}
/* fill framebuffer */
- ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+ ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0);
flen = msi2500_convert_stream(dev, ptr, iso_buf, flen);
- vb2_set_plane_payload(&fbuf->vb, 0, flen);
- vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, flen);
+ vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
handler_end:
@@ -569,7 +571,7 @@ static void msi2500_cleanup_queued_bufs(struct msi2500_dev *dev)
buf = list_entry(dev->queued_bufs.next,
struct msi2500_frame_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
}
@@ -614,7 +616,7 @@ static int msi2500_querycap(struct file *file, void *fh,
/* Videobuf2 operations */
static int msi2500_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
@@ -633,15 +635,16 @@ static int msi2500_queue_setup(struct vb2_queue *vq,
static void msi2500_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct msi2500_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct msi2500_frame_buf *buf = container_of(vb,
+ struct msi2500_frame_buf *buf = container_of(vbuf,
struct msi2500_frame_buf,
vb);
unsigned long flags;
/* Check the device has not disconnected between prep and queuing */
if (unlikely(!dev->udev)) {
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
return;
}
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 702267e208ba..b79c36fd8cd2 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -240,9 +240,9 @@ static void pwc_frame_complete(struct pwc_device *pdev)
PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
" discarded.\n", fbuf->filled);
} else {
- fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
- fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
- vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ fbuf->vb.field = V4L2_FIELD_NONE;
+ fbuf->vb.sequence = pdev->vframe_count;
+ vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
pdev->fill_buf = NULL;
pdev->vsync = 0;
}
@@ -287,7 +287,7 @@ static void pwc_isoc_handler(struct urb *urb)
{
PWC_ERROR("Too many ISOC errors, bailing out.\n");
if (pdev->fill_buf) {
- vb2_buffer_done(&pdev->fill_buf->vb,
+ vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
pdev->fill_buf = NULL;
}
@@ -317,7 +317,7 @@ static void pwc_isoc_handler(struct urb *urb)
if (pdev->vsync == 1) {
v4l2_get_timestamp(
- &fbuf->vb.v4l2_buf.timestamp);
+ &fbuf->vb.timestamp);
pdev->vsync = 2;
}
@@ -520,7 +520,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev,
buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, state);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
}
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}
@@ -571,7 +571,7 @@ static void pwc_video_release(struct v4l2_device *v)
/***************************************************************************/
/* Videobuf2 operations */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -594,7 +594,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int buffer_init(struct vb2_buffer *vb)
{
- struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct pwc_frame_buf *buf =
+ container_of(vbuf, struct pwc_frame_buf, vb);
/* need vmalloc since frame buffer > 128K */
buf->data = vzalloc(PWC_FRAME_SIZE);
@@ -618,7 +620,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
- struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct pwc_frame_buf *buf =
+ container_of(vbuf, struct pwc_frame_buf, vb);
if (vb->state == VB2_BUF_STATE_DONE) {
/*
@@ -633,7 +637,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_cleanup(struct vb2_buffer *vb)
{
- struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct pwc_frame_buf *buf =
+ container_of(vbuf, struct pwc_frame_buf, vb);
vfree(buf->data);
}
@@ -641,12 +647,14 @@ static void buffer_cleanup(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
- struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct pwc_frame_buf *buf =
+ container_of(vbuf, struct pwc_frame_buf, vb);
unsigned long flags = 0;
/* Check the device has not disconnected between prep and queuing */
if (!pdev->udev) {
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
return;
}
@@ -695,7 +703,8 @@ static void stop_streaming(struct vb2_queue *vq)
pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_ERROR);
if (pdev->fill_buf)
- vb2_buffer_done(&pdev->fill_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
mutex_unlock(&pdev->v4l2_lock);
}
diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c
index b65903fbcf0d..98c46f93f119 100644
--- a/drivers/media/usb/pwc/pwc-uncompress.c
+++ b/drivers/media/usb/pwc/pwc-uncompress.c
@@ -40,7 +40,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
u16 *src;
u16 *dsty, *dstu, *dstv;
- image = vb2_plane_vaddr(&fbuf->vb, 0);
+ image = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0);
yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
@@ -55,12 +55,12 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
* determine this using the type of the webcam */
memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
memcpy(raw_frame+1, yuv, pdev->frame_size);
- vb2_set_plane_payload(&fbuf->vb, 0,
+ vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0,
pdev->frame_size + sizeof(struct pwc_raw_frame));
return 0;
}
- vb2_set_plane_payload(&fbuf->vb, 0,
+ vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0,
pdev->width * pdev->height * 3 / 2);
if (pdev->vbandlength == 0) {
diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h
index 81b017a554bc..3c73bdaae450 100644
--- a/drivers/media/usb/pwc/pwc.h
+++ b/drivers/media/usb/pwc/pwc.h
@@ -40,6 +40,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
#include <linux/input.h>
@@ -210,7 +211,8 @@ struct pwc_raw_frame {
/* intermediate buffers with raw data from the USB cam */
struct pwc_frame_buf
{
- struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vb;
struct list_head list;
void *data;
int filled; /* number of bytes filled */
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 0f3c34d47ec3..e7acb12ad21d 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -45,6 +45,7 @@
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/usb.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
@@ -293,7 +294,7 @@ struct s2255_fmt {
/* buffer for one video frame */
struct s2255_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -573,14 +574,14 @@ static void s2255_got_frame(struct s2255_vc *vc, int jpgsize)
buf = list_entry(vc->buf_list.next,
struct s2255_buffer, list);
list_del(&buf->list);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.field = vc->field;
- buf->vb.v4l2_buf.sequence = vc->frame_count;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.field = vc->field;
+ buf->vb.sequence = vc->frame_count;
spin_unlock_irqrestore(&vc->qlock, flags);
s2255_fillbuff(vc, buf, jpgsize);
/* tell v4l buffer was filled */
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
dprintk(dev, 2, "%s: [buf] [%p]\n", __func__, buf);
}
@@ -612,7 +613,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
{
int pos = 0;
const char *tmpbuf;
- char *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+ char *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
unsigned long last_frame;
struct s2255_dev *dev = vc->dev;
@@ -635,7 +636,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
break;
case V4L2_PIX_FMT_JPEG:
case V4L2_PIX_FMT_MJPEG:
- vb2_set_plane_payload(&buf->vb, 0, jpgsize);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, jpgsize);
memcpy(vbuf, tmpbuf, jpgsize);
break;
case V4L2_PIX_FMT_YUV422P:
@@ -659,7 +660,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
Videobuf operations
------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -674,7 +675,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue);
- struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct s2255_buffer *buf = container_of(vbuf, struct s2255_buffer, vb);
int w = vc->width;
int h = vc->height;
unsigned long size;
@@ -696,13 +698,14 @@ static int buffer_prepare(struct vb2_buffer *vb)
return -EINVAL;
}
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
return 0;
}
static void buffer_queue(struct vb2_buffer *vb)
{
- struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct s2255_buffer *buf = container_of(vbuf, struct s2255_buffer, vb);
struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue);
unsigned long flags = 0;
dprintk(vc->dev, 1, "%s\n", __func__);
@@ -1116,9 +1119,9 @@ static void stop_streaming(struct vb2_queue *vq)
spin_lock_irqsave(&vc->qlock, flags);
list_for_each_entry_safe(buf, node, &vc->buf_list, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(vc->dev, 2, "[%p/%d] done\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
spin_unlock_irqrestore(&vc->qlock, flags);
}
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index e12b10352871..0bd34f1e7fa9 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -664,7 +664,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
/*
* Videobuf2 operations
*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -695,8 +695,9 @@ static void buffer_queue(struct vb2_buffer *vb)
{
unsigned long flags;
struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct stk1160_buffer *buf =
- container_of(vb, struct stk1160_buffer, vb);
+ container_of(vbuf, struct stk1160_buffer, vb);
spin_lock_irqsave(&dev->buf_lock, flags);
if (!dev->udev) {
@@ -704,7 +705,7 @@ static void buffer_queue(struct vb2_buffer *vb)
* If the device is disconnected return the buffer to userspace
* directly. The next QBUF call will fail with -ENODEV.
*/
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
} else {
buf->mem = vb2_plane_vaddr(vb, 0);
@@ -717,7 +718,7 @@ static void buffer_queue(struct vb2_buffer *vb)
* the buffer to userspace directly.
*/
if (buf->length < dev->width * dev->height * 2)
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
else
list_add_tail(&buf->list, &dev->avail_bufs);
@@ -769,9 +770,9 @@ void stk1160_clear_queue(struct stk1160 *dev)
buf = list_first_entry(&dev->avail_bufs,
struct stk1160_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
stk1160_dbg("buffer [%p/%d] aborted\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
/* It's important to release the current buffer */
@@ -779,9 +780,9 @@ void stk1160_clear_queue(struct stk1160 *dev)
buf = dev->isoc_ctl.buf;
dev->isoc_ctl.buf = NULL;
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
stk1160_dbg("buffer [%p/%d] aborted\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
}
spin_unlock_irqrestore(&dev->buf_lock, flags);
}
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index 940c3eaea507..75654e676e80 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -96,13 +96,13 @@ void stk1160_buffer_done(struct stk1160 *dev)
{
struct stk1160_buffer *buf = dev->isoc_ctl.buf;
- buf->vb.v4l2_buf.sequence = dev->sequence++;
- buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
- buf->vb.v4l2_buf.bytesused = buf->bytesused;
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ buf->vb.sequence = dev->sequence++;
+ buf->vb.field = V4L2_FIELD_INTERLACED;
+ buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused;
+ v4l2_get_timestamp(&buf->vb.timestamp);
- vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
dev->isoc_ctl.buf = NULL;
}
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
index 72cc8e8cbef7..1ed1cc43cdb2 100644
--- a/drivers/media/usb/stk1160/stk1160.h
+++ b/drivers/media/usb/stk1160/stk1160.h
@@ -23,7 +23,7 @@
#include <linux/i2c.h>
#include <sound/core.h>
#include <sound/ac97_codec.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
@@ -77,7 +77,7 @@
/* Buffer for one video frame */
struct stk1160_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
void *mem;
diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c
index 74e5697d8678..e21c7aacecb6 100644
--- a/drivers/media/usb/tm6000/tm6000-alsa.c
+++ b/drivers/media/usb/tm6000/tm6000-alsa.c
@@ -42,7 +42,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c
index 7c3a7c55d969..a5de46f04247 100644
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -375,8 +375,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
struct ttusb_dec *dec = priv;
dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
- &dec->audio_filter->feed->feed.ts,
- DMX_OK);
+ &dec->audio_filter->feed->feed.ts);
return 0;
}
@@ -386,8 +385,7 @@ static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
struct ttusb_dec *dec = priv;
dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
- &dec->video_filter->feed->feed.ts,
- DMX_OK);
+ &dec->video_filter->feed->feed.ts);
return 0;
}
@@ -439,7 +437,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
if (output_pva) {
dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
- &dec->video_filter->feed->feed.ts, DMX_OK);
+ &dec->video_filter->feed->feed.ts);
return;
}
@@ -500,7 +498,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
case 0x02: /* MainAudioStream */
if (output_pva) {
dec->audio_filter->feed->cb.ts(pva, length, NULL, 0,
- &dec->audio_filter->feed->feed.ts, DMX_OK);
+ &dec->audio_filter->feed->feed.ts);
return;
}
@@ -538,7 +536,7 @@ static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
if (filter)
filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
- &filter->filter, DMX_OK);
+ &filter->filter);
}
static void ttusb_dec_process_packet(struct ttusb_dec *dec)
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 08fb0f2da64d..e645c9df2d94 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -29,7 +29,7 @@
*/
#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "usbtv.h"
@@ -306,7 +306,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
/* First available buffer. */
buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
- frame = vb2_plane_vaddr(&buf->vb, 0);
+ frame = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
/* Copy the chunk data. */
usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
@@ -314,17 +314,17 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
/* Last chunk in a frame, signalling an end */
if (odd && chunk_no == usbtv->n_chunks-1) {
- int size = vb2_plane_size(&buf->vb, 0);
+ int size = vb2_plane_size(&buf->vb.vb2_buf, 0);
enum vb2_buffer_state state = usbtv->chunks_done ==
usbtv->n_chunks ?
VB2_BUF_STATE_DONE :
VB2_BUF_STATE_ERROR;
- buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
- buf->vb.v4l2_buf.sequence = usbtv->sequence++;
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- vb2_set_plane_payload(&buf->vb, 0, size);
- vb2_buffer_done(&buf->vb, state);
+ buf->vb.field = V4L2_FIELD_INTERLACED;
+ buf->vb.sequence = usbtv->sequence++;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
list_del(&buf->list);
}
@@ -422,7 +422,7 @@ static void usbtv_stop(struct usbtv *usbtv)
while (!list_empty(&usbtv->bufs)) {
struct usbtv_buf *buf = list_first_entry(&usbtv->bufs,
struct usbtv_buf, list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&buf->list);
}
spin_unlock_irqrestore(&usbtv->buflock, flags);
@@ -599,9 +599,10 @@ static struct v4l2_file_operations usbtv_fops = {
};
static int usbtv_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt, unsigned int *nbuffers,
+ const void *parg, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct usbtv *usbtv = vb2_get_drv_priv(vq);
unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
@@ -617,8 +618,9 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
static void usbtv_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue);
- struct usbtv_buf *buf = container_of(vb, struct usbtv_buf, vb);
+ struct usbtv_buf *buf = container_of(vbuf, struct usbtv_buf, vb);
unsigned long flags;
if (usbtv->udev == NULL) {
diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h
index 968119581fab..19cb8bf7c4e9 100644
--- a/drivers/media/usb/usbtv/usbtv.h
+++ b/drivers/media/usb/usbtv/usbtv.h
@@ -24,6 +24,7 @@
#include <linux/usb.h>
#include <media/v4l2-device.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
/* Hardware. */
@@ -61,7 +62,7 @@ struct usbtv_norm_params {
/* A single videobuf2 frame buffer. */
struct usbtv_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 4b5b3e8fb7d3..d11fd6ac2df0 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -32,6 +32,7 @@
#define DRIVER_DESC "USB Video Class driver"
unsigned int uvc_clock_param = CLOCK_MONOTONIC;
+unsigned int uvc_hw_timestamps_param;
unsigned int uvc_no_drop_param;
static unsigned int uvc_quirks_param = -1;
unsigned int uvc_trace_param;
@@ -2078,6 +2079,8 @@ static int uvc_clock_param_set(const char *val, struct kernel_param *kp)
module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
&uvc_clock_param, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(clock, "Video buffers timestamp clock");
+module_param_named(hwtimestamps, uvc_hw_timestamps_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hwtimestamps, "Use hardware timestamps");
module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index f16b9b42689d..cfb868a48b5f 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -20,6 +20,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include "uvcvideo.h"
@@ -60,7 +61,7 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
queue);
list_del(&buf->queue);
buf->state = state;
- vb2_buffer_done(&buf->buf, vb2_state);
+ vb2_buffer_done(&buf->buf.vb2_buf, vb2_state);
}
}
@@ -68,10 +69,11 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
* videobuf2 queue operations
*/
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_streaming *stream = uvc_queue_to_stream(queue);
@@ -89,10 +91,11 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
- if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
return -EINVAL;
@@ -105,7 +108,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
buf->error = 0;
buf->mem = vb2_plane_vaddr(vb, 0);
buf->length = vb2_plane_size(vb, 0);
- if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
else
buf->bytesused = vb2_get_plane_payload(vb, 0);
@@ -115,8 +118,9 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
static void uvc_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
@@ -127,7 +131,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
* directly. The next QBUF call will fail with -ENODEV.
*/
buf->state = UVC_BUF_STATE_ERROR;
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -135,12 +139,13 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
static void uvc_buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
struct uvc_streaming *stream = uvc_queue_to_stream(queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
if (vb->state == VB2_BUF_STATE_DONE)
- uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+ uvc_video_clock_update(stream, vbuf, buf);
}
static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count)
@@ -398,7 +403,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
buf->error = 0;
buf->state = UVC_BUF_STATE_QUEUED;
buf->bytesused = 0;
- vb2_set_plane_payload(&buf->buf, 0, 0);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
return buf;
}
@@ -412,8 +417,8 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
spin_unlock_irqrestore(&queue->irqlock, flags);
buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
- vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
return nextbuf;
}
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index f839654ea436..2b276ab7764f 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -606,7 +606,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
* timestamp of the sliding window to 1s.
*/
void uvc_video_clock_update(struct uvc_streaming *stream,
- struct v4l2_buffer *v4l2_buf,
+ struct vb2_v4l2_buffer *vbuf,
struct uvc_buffer *buf)
{
struct uvc_clock *clock = &stream->clock;
@@ -623,6 +623,9 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
u32 rem;
u64 y;
+ if (!uvc_hw_timestamps_param)
+ return;
+
spin_lock_irqsave(&clock->lock, flags);
if (clock->count < clock->size)
@@ -696,14 +699,14 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
stream->dev->name,
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
- v4l2_buf->timestamp.tv_sec,
- (unsigned long)v4l2_buf->timestamp.tv_usec,
+ vbuf->timestamp.tv_sec,
+ (unsigned long)vbuf->timestamp.tv_usec,
x1, first->host_sof, first->dev_sof,
x2, last->host_sof, last->dev_sof, y1, y2);
/* Update the V4L2 buffer. */
- v4l2_buf->timestamp.tv_sec = ts.tv_sec;
- v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ vbuf->timestamp.tv_sec = ts.tv_sec;
+ vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
done:
spin_unlock_irqrestore(&stream->clock.lock, flags);
@@ -1029,10 +1032,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
uvc_video_get_ts(&ts);
- buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
- buf->buf.v4l2_buf.sequence = stream->sequence;
- buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
- buf->buf.v4l2_buf.timestamp.tv_usec =
+ buf->buf.field = V4L2_FIELD_NONE;
+ buf->buf.sequence = stream->sequence;
+ buf->buf.timestamp.tv_sec = ts.tv_sec;
+ buf->buf.timestamp.tv_usec =
ts.tv_nsec / NSEC_PER_USEC;
/* TODO: Handle PTS and SCR. */
@@ -1305,7 +1308,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
if (buf->bytesused == stream->queue.buf_used) {
stream->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_READY;
- buf->buf.v4l2_buf.sequence = ++stream->sequence;
+ buf->buf.sequence = ++stream->sequence;
uvc_queue_next_buffer(&stream->queue, buf);
stream->last_fid ^= UVC_STREAM_FID;
}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 816dd1a0fd81..f0f2391e1b43 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -15,7 +15,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
/* --------------------------------------------------------------------------
* UVC constants
@@ -354,7 +354,7 @@ enum uvc_buffer_state {
};
struct uvc_buffer {
- struct vb2_buffer buf;
+ struct vb2_v4l2_buffer buf;
struct list_head queue;
enum uvc_buffer_state state;
@@ -593,6 +593,7 @@ extern unsigned int uvc_clock_param;
extern unsigned int uvc_no_drop_param;
extern unsigned int uvc_trace_param;
extern unsigned int uvc_timeout_param;
+extern unsigned int uvc_hw_timestamps_param;
#define uvc_trace(flag, msg...) \
do { \
@@ -673,7 +674,7 @@ extern int uvc_probe_video(struct uvc_streaming *stream,
extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
__u8 intfnum, __u8 cs, void *data, __u16 size);
void uvc_video_clock_update(struct uvc_streaming *stream,
- struct v4l2_buffer *v4l2_buf,
+ struct vb2_v4l2_buffer *vbuf,
struct uvc_buffer *buf);
/* Status */
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 82876a67f144..9beece00869b 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -47,7 +47,7 @@ config V4L2_MEM2MEM_DEV
# Used by LED subsystem flash drivers
config V4L2_FLASH_LED_CLASS
tristate "V4L2 flash API for LED flash class devices"
- depends on VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on LEDS_CLASS_FLASH
---help---
Say Y here to enable V4L2 flash API support for LED flash
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index d1dd440d9d9b..1dc8bba2b198 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -14,7 +14,7 @@ ifeq ($(CONFIG_OF),y)
videodev-objs += v4l2-of.o
endif
ifeq ($(CONFIG_TRACEPOINTS),y)
- videodev-objs += v4l2-trace.o
+ videodev-objs += vb2-trace.o v4l2-trace.o
endif
obj-$(CONFIG_VIDEO_V4L2) += videodev.o
@@ -33,7 +33,7 @@ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
-obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o
+obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o
obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index af635430524e..327e83ac2469 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -147,6 +147,20 @@ static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp,
return 0;
}
+static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+{
+ if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+{
+ if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
+ return -EFAULT;
+ return 0;
+}
+
struct v4l2_format32 {
__u32 type; /* enum v4l2_buf_type */
union {
@@ -155,6 +169,7 @@ struct v4l2_format32 {
struct v4l2_window32 win;
struct v4l2_vbi_format vbi;
struct v4l2_sliced_vbi_format sliced;
+ struct v4l2_sdr_format sdr;
__u8 raw_data[200]; /* user-defined */
} fmt;
};
@@ -198,8 +213,11 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
default:
- printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+ pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
kp->type);
return -EINVAL;
}
@@ -242,8 +260,11 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
default:
- printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+ pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
kp->type);
return -EINVAL;
}
@@ -266,7 +287,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_
struct v4l2_standard32 {
__u32 index;
- __u32 id[2]; /* __u64 would get the alignment wrong */
+ compat_u64 id;
__u8 name[24];
struct v4l2_fract frameperiod; /* Frames, not fields */
__u32 framelines;
@@ -286,7 +307,7 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
put_user(kp->index, &up->index) ||
- copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
+ put_user(kp->id, &up->id) ||
copy_to_user(up->name, kp->name, 24) ||
copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
put_user(kp->framelines, &up->framelines) ||
@@ -587,10 +608,10 @@ struct v4l2_input32 {
__u32 type; /* Type of input */
__u32 audioset; /* Associated audios (bitfield) */
__u32 tuner; /* Associated tuner */
- v4l2_std_id std;
+ compat_u64 std;
__u32 status;
__u32 reserved[4];
-} __attribute__ ((packed));
+};
/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
Otherwise it is identical to the 32-bit version. */
@@ -609,11 +630,11 @@ static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __
}
struct v4l2_ext_controls32 {
- __u32 ctrl_class;
- __u32 count;
- __u32 error_idx;
- __u32 reserved[2];
- compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
+ __u32 ctrl_class;
+ __u32 count;
+ __u32 error_idx;
+ __u32 reserved[2];
+ compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
};
struct v4l2_ext_control32 {
@@ -655,7 +676,8 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
get_user(kp->ctrl_class, &up->ctrl_class) ||
get_user(kp->count, &up->count) ||
get_user(kp->error_idx, &up->error_idx) ||
- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+ copy_from_user(kp->reserved, up->reserved,
+ sizeof(kp->reserved)))
return -EFAULT;
n = kp->count;
if (n == 0) {
@@ -738,6 +760,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
struct v4l2_event32 {
__u32 type;
union {
+ compat_s64 value64;
__u8 data[64];
} u;
__u32 pending;
@@ -1033,8 +1056,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
ret = vdev->fops->compat_ioctl32(file, cmd, arg);
if (ret == -ENOIOCTLCMD)
- pr_warn("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
- _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
+ pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
+ _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
return ret;
}
EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index b6b7dcc1b77d..4a1d9fdd14bb 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -888,6 +888,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis";
case V4L2_CID_RDS_RECEPTION: return "RDS Reception";
case V4L2_CID_RF_TUNER_CLASS: return "RF Tuner Controls";
+ case V4L2_CID_RF_TUNER_RF_GAIN: return "RF Gain";
case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: return "LNA Gain, Auto";
case V4L2_CID_RF_TUNER_LNA_GAIN: return "LNA Gain";
case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: return "Mixer Gain, Auto";
@@ -1161,6 +1162,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_PILOT_TONE_FREQUENCY:
case V4L2_CID_TUNE_POWER_LEVEL:
case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
+ case V4L2_CID_RF_TUNER_RF_GAIN:
case V4L2_CID_RF_TUNER_LNA_GAIN:
case V4L2_CID_RF_TUNER_MIXER_GAIN:
case V4L2_CID_RF_TUNER_IF_GAIN:
@@ -2498,7 +2500,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr
/* We found a control with the given ID, so just get
the next valid one in the list. */
list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
- is_compound =
+ is_compound = ref->ctrl->is_array ||
ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
if (id < ref->ctrl->id &&
(is_compound & mask) == match)
@@ -2512,7 +2514,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr
is one, otherwise the first 'if' above would have
been true. */
list_for_each_entry(ref, &hdl->ctrl_refs, node) {
- is_compound =
+ is_compound = ref->ctrl->is_array ||
ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
if (id < ref->ctrl->id &&
(is_compound & mask) == match)
@@ -2884,7 +2886,7 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
* cur_to_user() calls below would need to be modified not to access
* userspace memory when called from get_ctrl().
*/
- if (!ctrl->is_int)
+ if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64)
return -EINVAL;
if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
@@ -2942,9 +2944,9 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
/* It's a driver bug if this happens. */
WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
- c.value = 0;
+ c.value64 = 0;
get_ctrl(ctrl, &c);
- return c.value;
+ return c.value64;
}
EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64);
@@ -3043,7 +3045,7 @@ static void update_from_auto_cluster(struct v4l2_ctrl *master)
{
int i;
- for (i = 0; i < master->ncontrols; i++)
+ for (i = 1; i < master->ncontrols; i++)
cur_to_new(master->cluster[i]);
if (!call_op(master, g_volatile_ctrl))
for (i = 1; i < master->ncontrols; i++)
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 71a1b93b0790..6b1eaeddbdb3 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -637,8 +637,8 @@ static void determine_valid_ioctls(struct video_device *vdev)
ops->vidioc_try_fmt_sliced_vbi_out)))
set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
- } else if (is_sdr) {
- /* SDR specific ioctls */
+ } else if (is_sdr && is_rx) {
+ /* SDR receiver specific ioctls */
if (ops->vidioc_enum_fmt_sdr_cap)
set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
if (ops->vidioc_g_fmt_sdr_cap)
@@ -647,6 +647,16 @@ static void determine_valid_ioctls(struct video_device *vdev)
set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
if (ops->vidioc_try_fmt_sdr_cap)
set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+ } else if (is_sdr && is_tx) {
+ /* SDR transmitter specific ioctls */
+ if (ops->vidioc_enum_fmt_sdr_out)
+ set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
+ if (ops->vidioc_g_fmt_sdr_out)
+ set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+ if (ops->vidioc_s_fmt_sdr_out)
+ set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+ if (ops->vidioc_try_fmt_sdr_out)
+ set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
}
if (is_vid || is_vbi || is_sdr) {
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 4a384fc765b8..7486af2c8ae4 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -26,7 +26,7 @@
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
#include <media/v4l2-device.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <trace/events/v4l2.h>
@@ -153,6 +153,7 @@ const char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
[V4L2_BUF_TYPE_SDR_CAPTURE] = "sdr-cap",
+ [V4L2_BUF_TYPE_SDR_OUTPUT] = "sdr-out",
};
EXPORT_SYMBOL(v4l2_type_names);
@@ -326,6 +327,7 @@ static void v4l_print_format(const void *arg, bool write_only)
sliced->service_lines[1][i]);
break;
case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
sdr = &p->fmt.sdr;
pr_cont(", pixelformat=%c%c%c%c\n",
(sdr->pixelformat >> 0) & 0xff,
@@ -974,6 +976,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
return 0;
break;
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
+ return 0;
+ break;
default:
break;
}
@@ -1324,6 +1330,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
break;
ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
break;
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ if (unlikely(!is_tx || !is_sdr || !ops->vidioc_enum_fmt_sdr_out))
+ break;
+ ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
+ break;
}
if (ret == 0)
v4l_fill_fmtdesc(p);
@@ -1418,6 +1429,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap))
break;
return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
+ break;
+ return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
}
return -EINVAL;
}
@@ -1497,6 +1512,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
break;
CLEAR_AFTER_FIELD(p, fmt.sdr);
return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ if (unlikely(!is_tx || !is_sdr || !ops->vidioc_s_fmt_sdr_out))
+ break;
+ CLEAR_AFTER_FIELD(p, fmt.sdr);
+ return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
}
return -EINVAL;
}
@@ -1576,6 +1596,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
break;
CLEAR_AFTER_FIELD(p, fmt.sdr);
return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+ if (unlikely(!is_tx || !is_sdr || !ops->vidioc_try_fmt_sdr_out))
+ break;
+ CLEAR_AFTER_FIELD(p, fmt.sdr);
+ return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
}
return -EINVAL;
}
@@ -1621,15 +1646,31 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
+ struct video_device *vfd = video_devdata(file);
struct v4l2_modulator *p = arg;
int err;
+ if (vfd->vfl_type == VFL_TYPE_RADIO)
+ p->type = V4L2_TUNER_RADIO;
+
err = ops->vidioc_g_modulator(file, fh, p);
if (!err)
p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
return err;
}
+static int v4l_s_modulator(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ struct v4l2_modulator *p = arg;
+
+ if (vfd->vfl_type == VFL_TYPE_RADIO)
+ p->type = V4L2_TUNER_RADIO;
+
+ return ops->vidioc_s_modulator(file, fh, p);
+}
+
static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
@@ -1637,7 +1678,7 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
struct v4l2_frequency *p = arg;
if (vfd->vfl_type == VFL_TYPE_SDR)
- p->type = V4L2_TUNER_ADC;
+ p->type = V4L2_TUNER_SDR;
else
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
@@ -1652,7 +1693,7 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
enum v4l2_tuner_type type;
if (vfd->vfl_type == VFL_TYPE_SDR) {
- if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
+ if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
return -EINVAL;
} else {
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
@@ -2277,7 +2318,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
int err;
if (vfd->vfl_type == VFL_TYPE_SDR) {
- if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
+ if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
return -EINVAL;
type = p->type;
} else {
@@ -2416,7 +2457,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0),
IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
- IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
+ IOCTL_INFO_FNC(VIDIOC_S_MODULATOR, v4l_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index ec3ad4eb0c57..61d56c940f80 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -17,7 +17,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
@@ -583,32 +583,25 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
goto end;
}
- if (m2m_ctx->m2m_dev->m2m_ops->unlock)
- m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
- else if (m2m_ctx->q_lock)
- mutex_unlock(m2m_ctx->q_lock);
-
+ spin_lock_irqsave(&src_q->done_lock, flags);
if (list_empty(&src_q->done_list))
poll_wait(file, &src_q->done_wq, wait);
+ spin_unlock_irqrestore(&src_q->done_lock, flags);
+
+ spin_lock_irqsave(&dst_q->done_lock, flags);
if (list_empty(&dst_q->done_list)) {
/*
* If the last buffer was dequeued from the capture queue,
* return immediately. DQBUF will return -EPIPE.
*/
- if (dst_q->last_buffer_dequeued)
+ if (dst_q->last_buffer_dequeued) {
+ spin_unlock_irqrestore(&dst_q->done_lock, flags);
return rc | POLLIN | POLLRDNORM;
+ }
poll_wait(file, &dst_q->done_wq, wait);
}
-
- if (m2m_ctx->m2m_dev->m2m_ops->lock)
- m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
- else if (m2m_ctx->q_lock) {
- if (mutex_lock_interruptible(m2m_ctx->q_lock)) {
- rc |= POLLERR;
- goto end;
- }
- }
+ spin_unlock_irqrestore(&dst_q->done_lock, flags);
spin_lock_irqsave(&src_q->done_lock, flags);
if (!list_empty(&src_q->done_list))
@@ -773,13 +766,15 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release);
*
* Call from buf_queue(), videobuf_queue_ops callback.
*/
-void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
+void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
+ struct vb2_v4l2_buffer *vbuf)
{
- struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb);
+ struct v4l2_m2m_buffer *b = container_of(vbuf,
+ struct v4l2_m2m_buffer, vb);
struct v4l2_m2m_queue_ctx *q_ctx;
unsigned long flags;
- q_ctx = get_queue_ctx(m2m_ctx, vb->vb2_queue->type);
+ q_ctx = get_queue_ctx(m2m_ctx, vbuf->vb2_buf.vb2_queue->type);
if (!q_ctx)
return;
diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
index ae10b0248c8e..7416010542c1 100644
--- a/drivers/media/v4l2-core/v4l2-trace.c
+++ b/drivers/media/v4l2-core/v4l2-trace.c
@@ -1,11 +1,11 @@
#include <media/v4l2-common.h>
#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#define CREATE_TRACE_POINTS
#include <trace/events/v4l2.h>
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_done);
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_queue);
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_dqbuf);
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_qbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_done);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
diff --git a/drivers/media/v4l2-core/vb2-trace.c b/drivers/media/v4l2-core/vb2-trace.c
new file mode 100644
index 000000000000..61e74f5936b3
--- /dev/null
+++ b/drivers/media/v4l2-core/vb2-trace.c
@@ -0,0 +1,9 @@
+#include <media/videobuf2-core.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/vb2.h>
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_done);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_queue);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_dqbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_qbuf);
diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c
index 926836d1813a..6c02989ee33f 100644
--- a/drivers/media/v4l2-core/videobuf-core.c
+++ b/drivers/media/v4l2-core/videobuf-core.c
@@ -576,7 +576,8 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
}
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
|| q->type == V4L2_BUF_TYPE_VBI_OUTPUT
- || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+ || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
+ || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) {
buf->size = b->bytesused;
buf->field = b->field;
buf->ts = b->timestamp;
@@ -1154,6 +1155,7 @@ unsigned int videobuf_poll_stream(struct file *file,
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
case V4L2_BUF_TYPE_VBI_OUTPUT:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
rc = POLLOUT | POLLWRNORM;
break;
default:
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 4f59b7ec05d0..33bdd81065e8 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1,5 +1,5 @@
/*
- * videobuf2-core.c - V4L2 driver helper framework
+ * videobuf2-core.c - video buffer 2 core framework
*
* Copyright (C) 2010 Samsung Electronics
*
@@ -24,164 +24,15 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-common.h>
#include <media/videobuf2-core.h>
-#include <trace/events/v4l2.h>
+#include <trace/events/vb2.h>
-static int debug;
-module_param(debug, int, 0644);
+#include "videobuf2-internal.h"
-#define dprintk(level, fmt, arg...) \
- do { \
- if (debug >= level) \
- pr_info("vb2: %s: " fmt, __func__, ## arg); \
- } while (0)
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-
-/*
- * If advanced debugging is on, then count how often each op is called
- * successfully, which can either be per-buffer or per-queue.
- *
- * This makes it easy to check that the 'init' and 'cleanup'
- * (and variations thereof) stay balanced.
- */
-
-#define log_memop(vb, op) \
- dprintk(2, "call_memop(%p, %d, %s)%s\n", \
- (vb)->vb2_queue, (vb)->v4l2_buf.index, #op, \
- (vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
-
-#define call_memop(vb, op, args...) \
-({ \
- struct vb2_queue *_q = (vb)->vb2_queue; \
- int err; \
- \
- log_memop(vb, op); \
- err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \
- if (!err) \
- (vb)->cnt_mem_ ## op++; \
- err; \
-})
-
-#define call_ptr_memop(vb, op, args...) \
-({ \
- struct vb2_queue *_q = (vb)->vb2_queue; \
- void *ptr; \
- \
- log_memop(vb, op); \
- ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \
- if (!IS_ERR_OR_NULL(ptr)) \
- (vb)->cnt_mem_ ## op++; \
- ptr; \
-})
-
-#define call_void_memop(vb, op, args...) \
-({ \
- struct vb2_queue *_q = (vb)->vb2_queue; \
- \
- log_memop(vb, op); \
- if (_q->mem_ops->op) \
- _q->mem_ops->op(args); \
- (vb)->cnt_mem_ ## op++; \
-})
-
-#define log_qop(q, op) \
- dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \
- (q)->ops->op ? "" : " (nop)")
-
-#define call_qop(q, op, args...) \
-({ \
- int err; \
- \
- log_qop(q, op); \
- err = (q)->ops->op ? (q)->ops->op(args) : 0; \
- if (!err) \
- (q)->cnt_ ## op++; \
- err; \
-})
-
-#define call_void_qop(q, op, args...) \
-({ \
- log_qop(q, op); \
- if ((q)->ops->op) \
- (q)->ops->op(args); \
- (q)->cnt_ ## op++; \
-})
-
-#define log_vb_qop(vb, op, args...) \
- dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \
- (vb)->vb2_queue, (vb)->v4l2_buf.index, #op, \
- (vb)->vb2_queue->ops->op ? "" : " (nop)")
-
-#define call_vb_qop(vb, op, args...) \
-({ \
- int err; \
- \
- log_vb_qop(vb, op); \
- err = (vb)->vb2_queue->ops->op ? \
- (vb)->vb2_queue->ops->op(args) : 0; \
- if (!err) \
- (vb)->cnt_ ## op++; \
- err; \
-})
-
-#define call_void_vb_qop(vb, op, args...) \
-({ \
- log_vb_qop(vb, op); \
- if ((vb)->vb2_queue->ops->op) \
- (vb)->vb2_queue->ops->op(args); \
- (vb)->cnt_ ## op++; \
-})
-
-#else
-
-#define call_memop(vb, op, args...) \
- ((vb)->vb2_queue->mem_ops->op ? \
- (vb)->vb2_queue->mem_ops->op(args) : 0)
-
-#define call_ptr_memop(vb, op, args...) \
- ((vb)->vb2_queue->mem_ops->op ? \
- (vb)->vb2_queue->mem_ops->op(args) : NULL)
-
-#define call_void_memop(vb, op, args...) \
- do { \
- if ((vb)->vb2_queue->mem_ops->op) \
- (vb)->vb2_queue->mem_ops->op(args); \
- } while (0)
-
-#define call_qop(q, op, args...) \
- ((q)->ops->op ? (q)->ops->op(args) : 0)
-
-#define call_void_qop(q, op, args...) \
- do { \
- if ((q)->ops->op) \
- (q)->ops->op(args); \
- } while (0)
-
-#define call_vb_qop(vb, op, args...) \
- ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
-
-#define call_void_vb_qop(vb, op, args...) \
- do { \
- if ((vb)->vb2_queue->ops->op) \
- (vb)->vb2_queue->ops->op(args); \
- } while (0)
-
-#endif
-
-/* Flags that are set by the vb2 core */
-#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
- V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
- V4L2_BUF_FLAG_PREPARED | \
- V4L2_BUF_FLAG_TIMESTAMP_MASK)
-/* Output buffer flags that should be passed on to the driver */
-#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
- V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
+int vb2_debug;
+EXPORT_SYMBOL_GPL(vb2_debug);
+module_param_named(debug, vb2_debug, int, 0644);
static void __vb2_queue_cancel(struct vb2_queue *q);
static void __enqueue_in_driver(struct vb2_buffer *vb);
@@ -193,7 +44,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
{
struct vb2_queue *q = vb->vb2_queue;
enum dma_data_direction dma_dir =
- V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
@@ -211,7 +62,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
/* Associate allocator private data with this plane */
vb->planes[plane].mem_priv = mem_priv;
- vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+ vb->planes[plane].length = q->plane_sizes[plane];
}
return 0;
@@ -235,8 +86,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
for (plane = 0; plane < vb->num_planes; ++plane) {
call_void_memop(vb, put, vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
- dprintk(3, "freed plane %d of buffer %d\n", plane,
- vb->v4l2_buf.index);
+ dprintk(3, "freed plane %d of buffer %d\n", plane, vb->index);
}
}
@@ -269,7 +119,9 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
call_void_memop(vb, detach_dmabuf, p->mem_priv);
dma_buf_put(p->dbuf);
- memset(p, 0, sizeof(*p));
+ p->mem_priv = NULL;
+ p->dbuf = NULL;
+ p->dbuf_mapped = 0;
}
/**
@@ -299,7 +151,7 @@ static void __setup_lengths(struct vb2_queue *q, unsigned int n)
continue;
for (plane = 0; plane < vb->num_planes; ++plane)
- vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+ vb->planes[plane].length = q->plane_sizes[plane];
}
}
@@ -314,10 +166,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
unsigned long off;
if (q->num_buffers) {
- struct v4l2_plane *p;
+ struct vb2_plane *p;
vb = q->bufs[q->num_buffers - 1];
- p = &vb->v4l2_planes[vb->num_planes - 1];
- off = PAGE_ALIGN(p->m.mem_offset + p->length);
+ p = &vb->planes[vb->num_planes - 1];
+ off = PAGE_ALIGN(p->m.offset + p->length);
} else {
off = 0;
}
@@ -328,12 +180,12 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
continue;
for (plane = 0; plane < vb->num_planes; ++plane) {
- vb->v4l2_planes[plane].m.mem_offset = off;
+ vb->planes[plane].m.offset = off;
dprintk(3, "buffer %d, plane %d offset 0x%08lx\n",
buffer, plane, off);
- off += vb->v4l2_planes[plane].length;
+ off += vb->planes[plane].length;
off = PAGE_ALIGN(off);
}
}
@@ -346,7 +198,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
*
* Returns the number of buffers successfully allocated.
*/
-static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
+static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
unsigned int num_buffers, unsigned int num_planes)
{
unsigned int buffer;
@@ -361,19 +213,15 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
break;
}
- /* Length stores number of planes for multiplanar buffers */
- if (V4L2_TYPE_IS_MULTIPLANAR(q->type))
- vb->v4l2_buf.length = num_planes;
-
vb->state = VB2_BUF_STATE_DEQUEUED;
vb->vb2_queue = q;
vb->num_planes = num_planes;
- vb->v4l2_buf.index = q->num_buffers + buffer;
- vb->v4l2_buf.type = q->type;
- vb->v4l2_buf.memory = memory;
+ vb->index = q->num_buffers + buffer;
+ vb->type = q->type;
+ vb->memory = memory;
/* Allocate video buffer memory for the MMAP type */
- if (memory == V4L2_MEMORY_MMAP) {
+ if (memory == VB2_MEMORY_MMAP) {
ret = __vb2_buf_mem_alloc(vb);
if (ret) {
dprintk(1, "failed allocating memory for "
@@ -400,7 +248,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
}
__setup_lengths(q, buffer);
- if (memory == V4L2_MEMORY_MMAP)
+ if (memory == VB2_MEMORY_MMAP)
__setup_offsets(q, buffer);
dprintk(1, "allocated %d buffers, %d plane(s) each\n",
@@ -424,9 +272,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
continue;
/* Free MMAP buffers or release USERPTR buffers */
- if (q->memory == V4L2_MEMORY_MMAP)
+ if (q->memory == VB2_MEMORY_MMAP)
__vb2_buf_mem_free(vb);
- else if (q->memory == V4L2_MEMORY_DMABUF)
+ else if (q->memory == VB2_MEMORY_DMABUF)
__vb2_buf_dmabuf_put(vb);
else
__vb2_buf_userptr_put(vb);
@@ -482,7 +330,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming ||
q->cnt_wait_prepare != q->cnt_wait_finish;
- if (unbalanced || debug) {
+ if (unbalanced || vb2_debug) {
pr_info("vb2: counters for queue %p:%s\n", q,
unbalanced ? " UNBALANCED!" : "");
pr_info("vb2: setup: %u start_streaming: %u stop_streaming: %u\n",
@@ -508,7 +356,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
vb->cnt_buf_prepare != vb->cnt_buf_finish ||
vb->cnt_buf_init != vb->cnt_buf_cleanup;
- if (unbalanced || debug) {
+ if (unbalanced || vb2_debug) {
pr_info("vb2: counters for queue %p, buffer %d:%s\n",
q, buffer, unbalanced ? " UNBALANCED!" : "");
pr_info("vb2: buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n",
@@ -550,76 +398,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
}
/**
- * __verify_planes_array() - verify that the planes array passed in struct
- * v4l2_buffer from userspace can be safely used
- */
-static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
-{
- if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
- return 0;
-
- /* Is memory for copying plane information present? */
- if (NULL == b->m.planes) {
- dprintk(1, "multi-planar buffer passed but "
- "planes array not provided\n");
- return -EINVAL;
- }
-
- if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
- dprintk(1, "incorrect planes array length, "
- "expected %d, got %d\n", vb->num_planes, b->length);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * __verify_length() - Verify that the bytesused value for each plane fits in
- * the plane length and that the data offset doesn't exceed the bytesused value.
- */
-static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
-{
- unsigned int length;
- unsigned int bytesused;
- unsigned int plane;
-
- if (!V4L2_TYPE_IS_OUTPUT(b->type))
- return 0;
-
- if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
- for (plane = 0; plane < vb->num_planes; ++plane) {
- length = (b->memory == V4L2_MEMORY_USERPTR ||
- b->memory == V4L2_MEMORY_DMABUF)
- ? b->m.planes[plane].length
- : vb->v4l2_planes[plane].length;
- bytesused = b->m.planes[plane].bytesused
- ? b->m.planes[plane].bytesused : length;
-
- if (b->m.planes[plane].bytesused > length)
- return -EINVAL;
-
- if (b->m.planes[plane].data_offset > 0 &&
- b->m.planes[plane].data_offset >= bytesused)
- return -EINVAL;
- }
- } else {
- length = (b->memory == V4L2_MEMORY_USERPTR)
- ? b->length : vb->v4l2_planes[0].length;
- bytesused = b->bytesused ? b->bytesused : length;
-
- if (b->bytesused > length)
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * __buffer_in_use() - return true if the buffer is in use and
+ * vb2_buffer_in_use() - return true if the buffer is in use and
* the queue cannot be freed (by the means of REQBUFS(0)) call
*/
-static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
{
unsigned int plane;
for (plane = 0; plane < vb->num_planes; ++plane) {
@@ -635,6 +417,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
}
return false;
}
+EXPORT_SYMBOL(vb2_buffer_in_use);
/**
* __buffers_in_use() - return true if any buffers on the queue are in use and
@@ -644,122 +427,30 @@ static bool __buffers_in_use(struct vb2_queue *q)
{
unsigned int buffer;
for (buffer = 0; buffer < q->num_buffers; ++buffer) {
- if (__buffer_in_use(q, q->bufs[buffer]))
+ if (vb2_buffer_in_use(q, q->bufs[buffer]))
return true;
}
return false;
}
/**
- * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
- * returned to userspace
- */
-static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
-{
- struct vb2_queue *q = vb->vb2_queue;
-
- /* Copy back data such as timestamp, flags, etc. */
- memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
- b->reserved2 = vb->v4l2_buf.reserved2;
- b->reserved = vb->v4l2_buf.reserved;
-
- if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
- /*
- * Fill in plane-related data if userspace provided an array
- * for it. The caller has already verified memory and size.
- */
- b->length = vb->num_planes;
- memcpy(b->m.planes, vb->v4l2_planes,
- b->length * sizeof(struct v4l2_plane));
- } else {
- /*
- * We use length and offset in v4l2_planes array even for
- * single-planar buffers, but userspace does not.
- */
- b->length = vb->v4l2_planes[0].length;
- b->bytesused = vb->v4l2_planes[0].bytesused;
- if (q->memory == V4L2_MEMORY_MMAP)
- b->m.offset = vb->v4l2_planes[0].m.mem_offset;
- else if (q->memory == V4L2_MEMORY_USERPTR)
- b->m.userptr = vb->v4l2_planes[0].m.userptr;
- else if (q->memory == V4L2_MEMORY_DMABUF)
- b->m.fd = vb->v4l2_planes[0].m.fd;
- }
-
- /*
- * Clear any buffer state related flags.
- */
- b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
- b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
- if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
- V4L2_BUF_FLAG_TIMESTAMP_COPY) {
- /*
- * For non-COPY timestamps, drop timestamp source bits
- * and obtain the timestamp source from the queue.
- */
- b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- }
-
- switch (vb->state) {
- case VB2_BUF_STATE_QUEUED:
- case VB2_BUF_STATE_ACTIVE:
- b->flags |= V4L2_BUF_FLAG_QUEUED;
- break;
- case VB2_BUF_STATE_ERROR:
- b->flags |= V4L2_BUF_FLAG_ERROR;
- /* fall through */
- case VB2_BUF_STATE_DONE:
- b->flags |= V4L2_BUF_FLAG_DONE;
- break;
- case VB2_BUF_STATE_PREPARED:
- b->flags |= V4L2_BUF_FLAG_PREPARED;
- break;
- case VB2_BUF_STATE_PREPARING:
- case VB2_BUF_STATE_DEQUEUED:
- case VB2_BUF_STATE_REQUEUEING:
- /* nothing */
- break;
- }
-
- if (__buffer_in_use(q, vb))
- b->flags |= V4L2_BUF_FLAG_MAPPED;
-}
-
-/**
- * vb2_querybuf() - query video buffer information
+ * vb2_core_querybuf() - query video buffer information
* @q: videobuf queue
- * @b: buffer struct passed from userspace to vidioc_querybuf handler
- * in driver
+ * @index: id number of the buffer
+ * @pb: buffer struct passed from userspace
*
* Should be called from vidioc_querybuf ioctl handler in driver.
- * This function will verify the passed v4l2_buffer structure and fill the
- * relevant information for the userspace.
+ * The passed buffer should have been verified.
+ * This function fills the relevant information for the userspace.
*
* The return values from this function are intended to be directly returned
* from vidioc_querybuf handler in driver.
*/
-int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
{
- struct vb2_buffer *vb;
- int ret;
-
- if (b->type != q->type) {
- dprintk(1, "wrong buffer type\n");
- return -EINVAL;
- }
-
- if (b->index >= q->num_buffers) {
- dprintk(1, "buffer index out of range\n");
- return -EINVAL;
- }
- vb = q->bufs[b->index];
- ret = __verify_planes_array(vb, b);
- if (!ret)
- __fill_v4l2_buffer(vb, b);
- return ret;
+ return call_bufop(q, fill_user_buffer, q->bufs[index], pb);
}
-EXPORT_SYMBOL(vb2_querybuf);
+EXPORT_SYMBOL_GPL(vb2_core_querybuf);
/**
* __verify_userptr_ops() - verify that all memory operations required for
@@ -802,14 +493,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
}
/**
- * __verify_memory_type() - Check whether the memory type and buffer type
+ * vb2_verify_memory_type() - Check whether the memory type and buffer type
* passed to a buffer operation are compatible with the queue.
*/
-static int __verify_memory_type(struct vb2_queue *q,
- enum v4l2_memory memory, enum v4l2_buf_type type)
+int vb2_verify_memory_type(struct vb2_queue *q,
+ enum vb2_memory memory, unsigned int type)
{
- if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
- memory != V4L2_MEMORY_DMABUF) {
+ if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
+ memory != VB2_MEMORY_DMABUF) {
dprintk(1, "unsupported memory type\n");
return -EINVAL;
}
@@ -823,17 +514,17 @@ static int __verify_memory_type(struct vb2_queue *q,
* Make sure all the required memory ops for given memory type
* are available.
*/
- if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
+ if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
dprintk(1, "MMAP for current setup unsupported\n");
return -EINVAL;
}
- if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
+ if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
dprintk(1, "USERPTR for current setup unsupported\n");
return -EINVAL;
}
- if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
+ if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
dprintk(1, "DMABUF for current setup unsupported\n");
return -EINVAL;
}
@@ -849,11 +540,13 @@ static int __verify_memory_type(struct vb2_queue *q,
}
return 0;
}
+EXPORT_SYMBOL(vb2_verify_memory_type);
/**
- * __reqbufs() - Initiate streaming
+ * vb2_core_reqbufs() - Initiate streaming
* @q: videobuf2 queue
- * @req: struct passed from userspace to vidioc_reqbufs handler in driver
+ * @memory: memory type
+ * @count: requested buffer count
*
* Should be called from vidioc_reqbufs ioctl handler of a driver.
* This function:
@@ -873,7 +566,8 @@ static int __verify_memory_type(struct vb2_queue *q,
* The return values from this function are intended to be directly returned
* from vidioc_reqbufs handler in driver.
*/
-static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
+ unsigned int *count)
{
unsigned int num_buffers, allocated_buffers, num_planes = 0;
int ret;
@@ -883,13 +577,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
return -EBUSY;
}
- if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
+ if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
/*
* We already have buffers allocated, so first check if they
* are not in use and can be freed.
*/
mutex_lock(&q->mmap_lock);
- if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
+ if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
mutex_unlock(&q->mmap_lock);
dprintk(1, "memory in use, cannot free\n");
return -EBUSY;
@@ -910,18 +604,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
* In case of REQBUFS(0) return immediately without calling
* driver's queue_setup() callback and allocating resources.
*/
- if (req->count == 0)
+ if (*count == 0)
return 0;
}
/*
* Make sure the requested values and current defaults are sane.
*/
- num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
+ num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
- q->memory = req->memory;
+ q->memory = memory;
/*
* Ask the driver how many buffers and planes per buffer it requires.
@@ -933,7 +627,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
return ret;
/* Finally, allocate buffers and video memory */
- allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
+ allocated_buffers =
+ __vb2_queue_alloc(q, memory, num_buffers, num_planes);
if (allocated_buffers == 0) {
dprintk(1, "memory allocation failed\n");
return -ENOMEM;
@@ -982,31 +677,19 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
* Return the number of successfully allocated buffers
* to the userspace.
*/
- req->count = allocated_buffers;
- q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+ *count = allocated_buffers;
+ q->waiting_for_buffers = !q->is_output;
return 0;
}
+EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
/**
- * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
- * type values.
+ * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
* @q: videobuf2 queue
- * @req: struct passed from userspace to vidioc_reqbufs handler in driver
- */
-int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
-{
- int ret = __verify_memory_type(q, req->memory, req->type);
-
- return ret ? ret : __reqbufs(q, req);
-}
-EXPORT_SYMBOL_GPL(vb2_reqbufs);
-
-/**
- * __create_bufs() - Allocate buffers and any required auxiliary structs
- * @q: videobuf2 queue
- * @create: creation parameters, passed from userspace to vidioc_create_bufs
- * handler in driver
+ * @memory: memory type
+ * @count: requested buffer count
+ * @parg: parameter passed to device driver
*
* Should be called from vidioc_create_bufs ioctl handler of a driver.
* This function:
@@ -1017,12 +700,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
* The return values from this function are intended to be directly returned
* from vidioc_create_bufs handler in driver.
*/
-static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
+ unsigned int *count, const void *parg)
{
unsigned int num_planes = 0, num_buffers, allocated_buffers;
int ret;
- if (q->num_buffers == VIDEO_MAX_FRAME) {
+ if (q->num_buffers == VB2_MAX_FRAME) {
dprintk(1, "maximum number of buffers already allocated\n");
return -ENOBUFS;
}
@@ -1030,23 +714,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
if (!q->num_buffers) {
memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
- q->memory = create->memory;
- q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+ q->memory = memory;
+ q->waiting_for_buffers = !q->is_output;
}
- num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
+ num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
/*
* Ask the driver, whether the requested number of buffers, planes per
* buffer and their sizes are acceptable
*/
- ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+ ret = call_qop(q, queue_setup, q, parg, &num_buffers,
&num_planes, q->plane_sizes, q->alloc_ctx);
if (ret)
return ret;
/* Finally, allocate buffers and video memory */
- allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
+ allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
num_planes);
if (allocated_buffers == 0) {
dprintk(1, "memory allocation failed\n");
@@ -1063,7 +747,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
* q->num_buffers contains the total number of buffers, that the
* queue driver has set up
*/
- ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+ ret = call_qop(q, queue_setup, q, parg, &num_buffers,
&num_planes, q->plane_sizes, q->alloc_ctx);
if (!ret && allocated_buffers < num_buffers)
@@ -1093,28 +777,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
* Return the number of successfully allocated buffers
* to the userspace.
*/
- create->count = allocated_buffers;
+ *count = allocated_buffers;
return 0;
}
-
-/**
- * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
- * memory and type values.
- * @q: videobuf2 queue
- * @create: creation parameters, passed from userspace to vidioc_create_bufs
- * handler in driver
- */
-int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
-{
- int ret = __verify_memory_type(q, create->memory, create->format.type);
-
- create->index = q->num_buffers;
- if (create->count == 0)
- return ret != -EBUSY ? ret : 0;
- return ret ? ret : __create_bufs(q, create);
-}
-EXPORT_SYMBOL_GPL(vb2_create_bufs);
+EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
/**
* vb2_plane_vaddr() - Return a kernel virtual address of a given plane
@@ -1197,7 +864,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
vb->cnt_buf_done++;
#endif
dprintk(4, "done processing on buffer %d, state: %d\n",
- vb->v4l2_buf.index, state);
+ vb->index, state);
/* sync buffers */
for (plane = 0; plane < vb->num_planes; ++plane)
@@ -1256,182 +923,41 @@ void vb2_discard_done(struct vb2_queue *q)
}
EXPORT_SYMBOL_GPL(vb2_discard_done);
-static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
-{
- static bool check_once;
-
- if (check_once)
- return;
-
- check_once = true;
- WARN_ON(1);
-
- pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
- if (vb->vb2_queue->allow_zero_bytesused)
- pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
- else
- pr_warn("use the actual size instead.\n");
-}
-
-/**
- * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
- * v4l2_buffer by the userspace. The caller has already verified that struct
- * v4l2_buffer has a valid number of planes.
- */
-static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
- struct v4l2_plane *v4l2_planes)
-{
- unsigned int plane;
-
- if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
- if (b->memory == V4L2_MEMORY_USERPTR) {
- for (plane = 0; plane < vb->num_planes; ++plane) {
- v4l2_planes[plane].m.userptr =
- b->m.planes[plane].m.userptr;
- v4l2_planes[plane].length =
- b->m.planes[plane].length;
- }
- }
- if (b->memory == V4L2_MEMORY_DMABUF) {
- for (plane = 0; plane < vb->num_planes; ++plane) {
- v4l2_planes[plane].m.fd =
- b->m.planes[plane].m.fd;
- v4l2_planes[plane].length =
- b->m.planes[plane].length;
- }
- }
-
- /* Fill in driver-provided information for OUTPUT types */
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- /*
- * Will have to go up to b->length when API starts
- * accepting variable number of planes.
- *
- * If bytesused == 0 for the output buffer, then fall
- * back to the full buffer size. In that case
- * userspace clearly never bothered to set it and
- * it's a safe assumption that they really meant to
- * use the full plane sizes.
- *
- * Some drivers, e.g. old codec drivers, use bytesused == 0
- * as a way to indicate that streaming is finished.
- * In that case, the driver should use the
- * allow_zero_bytesused flag to keep old userspace
- * applications working.
- */
- for (plane = 0; plane < vb->num_planes; ++plane) {
- struct v4l2_plane *pdst = &v4l2_planes[plane];
- struct v4l2_plane *psrc = &b->m.planes[plane];
-
- if (psrc->bytesused == 0)
- vb2_warn_zero_bytesused(vb);
-
- if (vb->vb2_queue->allow_zero_bytesused)
- pdst->bytesused = psrc->bytesused;
- else
- pdst->bytesused = psrc->bytesused ?
- psrc->bytesused : pdst->length;
- pdst->data_offset = psrc->data_offset;
- }
- }
- } else {
- /*
- * Single-planar buffers do not use planes array,
- * so fill in relevant v4l2_buffer struct fields instead.
- * In videobuf we use our internal V4l2_planes struct for
- * single-planar buffers as well, for simplicity.
- *
- * If bytesused == 0 for the output buffer, then fall back
- * to the full buffer size as that's a sensible default.
- *
- * Some drivers, e.g. old codec drivers, use bytesused == 0 as
- * a way to indicate that streaming is finished. In that case,
- * the driver should use the allow_zero_bytesused flag to keep
- * old userspace applications working.
- */
- if (b->memory == V4L2_MEMORY_USERPTR) {
- v4l2_planes[0].m.userptr = b->m.userptr;
- v4l2_planes[0].length = b->length;
- }
-
- if (b->memory == V4L2_MEMORY_DMABUF) {
- v4l2_planes[0].m.fd = b->m.fd;
- v4l2_planes[0].length = b->length;
- }
-
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- if (b->bytesused == 0)
- vb2_warn_zero_bytesused(vb);
-
- if (vb->vb2_queue->allow_zero_bytesused)
- v4l2_planes[0].bytesused = b->bytesused;
- else
- v4l2_planes[0].bytesused = b->bytesused ?
- b->bytesused : v4l2_planes[0].length;
- } else
- v4l2_planes[0].bytesused = 0;
-
- }
-
- /* Zero flags that the vb2 core handles */
- vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
- if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
- V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
- /*
- * Non-COPY timestamps and non-OUTPUT queues will get
- * their timestamp and timestamp source flags from the
- * queue.
- */
- vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- }
-
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- /*
- * For output buffers mask out the timecode flag:
- * this will be handled later in vb2_internal_qbuf().
- * The 'field' is valid metadata for this output buffer
- * and so that needs to be copied here.
- */
- vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE;
- vb->v4l2_buf.field = b->field;
- } else {
- /* Zero any output buffer flags as this is a capture buffer */
- vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS;
- }
-}
-
/**
* __qbuf_mmap() - handle qbuf of an MMAP buffer
*/
-static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_mmap(struct vb2_buffer *vb, const void *pb)
{
- __fill_vb2_buffer(vb, b, vb->v4l2_planes);
- return call_vb_qop(vb, buf_prepare, vb);
+ int ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+ vb, pb, vb->planes);
+ return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
}
/**
* __qbuf_userptr() - handle qbuf of a USERPTR buffer
*/
-static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb)
{
- struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
void *mem_priv;
unsigned int plane;
int ret;
enum dma_data_direction dma_dir =
- V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
- __fill_vb2_buffer(vb, b, planes);
+ ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
+ if (ret)
+ return ret;
for (plane = 0; plane < vb->num_planes; ++plane) {
/* Skip the plane if already verified */
- if (vb->v4l2_planes[plane].m.userptr &&
- vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
- && vb->v4l2_planes[plane].length == planes[plane].length)
+ if (vb->planes[plane].m.userptr &&
+ vb->planes[plane].m.userptr == planes[plane].m.userptr
+ && vb->planes[plane].length == planes[plane].length)
continue;
dprintk(3, "userspace address for plane %d changed, "
@@ -1457,7 +983,10 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
}
vb->planes[plane].mem_priv = NULL;
- memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
+ vb->planes[plane].bytesused = 0;
+ vb->planes[plane].length = 0;
+ vb->planes[plane].m.userptr = 0;
+ vb->planes[plane].data_offset = 0;
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
@@ -1476,8 +1005,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
* Now that everything is in order, copy relevant information
* provided by userspace.
*/
- for (plane = 0; plane < vb->num_planes; ++plane)
- vb->v4l2_planes[plane] = planes[plane];
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ vb->planes[plane].bytesused = planes[plane].bytesused;
+ vb->planes[plane].length = planes[plane].length;
+ vb->planes[plane].m.userptr = planes[plane].m.userptr;
+ vb->planes[plane].data_offset = planes[plane].data_offset;
+ }
if (reacquired) {
/*
@@ -1504,10 +1037,11 @@ err:
/* In case of errors, release planes that were already acquired */
for (plane = 0; plane < vb->num_planes; ++plane) {
if (vb->planes[plane].mem_priv)
- call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
+ call_void_memop(vb, put_userptr,
+ vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
- vb->v4l2_planes[plane].m.userptr = 0;
- vb->v4l2_planes[plane].length = 0;
+ vb->planes[plane].m.userptr = 0;
+ vb->planes[plane].length = 0;
}
return ret;
@@ -1516,20 +1050,22 @@ err:
/**
* __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
*/
-static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb)
{
- struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
void *mem_priv;
unsigned int plane;
int ret;
enum dma_data_direction dma_dir =
- V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
- __fill_vb2_buffer(vb, b, planes);
+ ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
+ if (ret)
+ return ret;
for (plane = 0; plane < vb->num_planes; ++plane) {
struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
@@ -1554,7 +1090,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
/* Skip the plane if already verified */
if (dbuf == vb->planes[plane].dbuf &&
- vb->v4l2_planes[plane].length == planes[plane].length) {
+ vb->planes[plane].length == planes[plane].length) {
dma_buf_put(dbuf);
continue;
}
@@ -1568,11 +1104,15 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
/* Release previously acquired memory if present */
__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
- memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
+ vb->planes[plane].bytesused = 0;
+ vb->planes[plane].length = 0;
+ vb->planes[plane].m.fd = 0;
+ vb->planes[plane].data_offset = 0;
/* Acquire each plane's memory */
- mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
- dbuf, planes[plane].length, dma_dir);
+ mem_priv = call_ptr_memop(vb, attach_dmabuf,
+ q->alloc_ctx[plane], dbuf, planes[plane].length,
+ dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
@@ -1602,8 +1142,12 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
* Now that everything is in order, copy relevant information
* provided by userspace.
*/
- for (plane = 0; plane < vb->num_planes; ++plane)
- vb->v4l2_planes[plane] = planes[plane];
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ vb->planes[plane].bytesused = planes[plane].bytesused;
+ vb->planes[plane].length = planes[plane].length;
+ vb->planes[plane].m.fd = planes[plane].m.fd;
+ vb->planes[plane].data_offset = planes[plane].data_offset;
+ }
if (reacquired) {
/*
@@ -1652,49 +1196,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
call_void_vb_qop(vb, buf_queue, vb);
}
-static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __buf_prepare(struct vb2_buffer *vb, const void *pb)
{
struct vb2_queue *q = vb->vb2_queue;
int ret;
- ret = __verify_length(vb, b);
- if (ret < 0) {
- dprintk(1, "plane parameters verification failed: %d\n", ret);
- return ret;
- }
- if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
- /*
- * If the format's field is ALTERNATE, then the buffer's field
- * should be either TOP or BOTTOM, not ALTERNATE since that
- * makes no sense. The driver has to know whether the
- * buffer represents a top or a bottom field in order to
- * program any DMA correctly. Using ALTERNATE is wrong, since
- * that just says that it is either a top or a bottom field,
- * but not which of the two it is.
- */
- dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
- return -EINVAL;
- }
-
if (q->error) {
dprintk(1, "fatal error occurred on queue\n");
return -EIO;
}
vb->state = VB2_BUF_STATE_PREPARING;
- vb->v4l2_buf.timestamp.tv_sec = 0;
- vb->v4l2_buf.timestamp.tv_usec = 0;
- vb->v4l2_buf.sequence = 0;
switch (q->memory) {
- case V4L2_MEMORY_MMAP:
- ret = __qbuf_mmap(vb, b);
+ case VB2_MEMORY_MMAP:
+ ret = __qbuf_mmap(vb, pb);
break;
- case V4L2_MEMORY_USERPTR:
- ret = __qbuf_userptr(vb, b);
+ case VB2_MEMORY_USERPTR:
+ ret = __qbuf_userptr(vb, pb);
break;
- case V4L2_MEMORY_DMABUF:
- ret = __qbuf_dmabuf(vb, b);
+ case VB2_MEMORY_DMABUF:
+ ret = __qbuf_dmabuf(vb, pb);
break;
default:
WARN(1, "Invalid queue type\n");
@@ -1708,79 +1230,48 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
return ret;
}
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
- const char *opname)
-{
- if (b->type != q->type) {
- dprintk(1, "%s: invalid buffer type\n", opname);
- return -EINVAL;
- }
-
- if (b->index >= q->num_buffers) {
- dprintk(1, "%s: buffer index out of range\n", opname);
- return -EINVAL;
- }
-
- if (q->bufs[b->index] == NULL) {
- /* Should never happen */
- dprintk(1, "%s: buffer is NULL\n", opname);
- return -EINVAL;
- }
-
- if (b->memory != q->memory) {
- dprintk(1, "%s: invalid memory type\n", opname);
- return -EINVAL;
- }
-
- return __verify_planes_array(q->bufs[b->index], b);
-}
-
/**
- * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace
+ * to the kernel
* @q: videobuf2 queue
- * @b: buffer structure passed from userspace to vidioc_prepare_buf
+ * @index: id number of the buffer
+ * @pb: buffer structure passed from userspace to vidioc_prepare_buf
* handler in driver
*
* Should be called from vidioc_prepare_buf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) calls buf_prepare callback in the driver (if provided), in which
- * driver-specific buffer initialization can be performed,
+ * The passed buffer should have been verified.
+ * This function calls buf_prepare callback in the driver (if provided),
+ * in which driver-specific buffer initialization can be performed,
*
* The return values from this function are intended to be directly returned
* from vidioc_prepare_buf handler in driver.
*/
-int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
{
struct vb2_buffer *vb;
int ret;
- if (vb2_fileio_is_active(q)) {
- dprintk(1, "file io in progress\n");
- return -EBUSY;
- }
-
- ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
- if (ret)
- return ret;
-
- vb = q->bufs[b->index];
+ vb = q->bufs[index];
if (vb->state != VB2_BUF_STATE_DEQUEUED) {
dprintk(1, "invalid buffer state %d\n",
vb->state);
return -EINVAL;
}
- ret = __buf_prepare(vb, b);
- if (!ret) {
- /* Fill buffer information for the userspace */
- __fill_v4l2_buffer(vb, b);
+ ret = __buf_prepare(vb, pb);
+ if (ret)
+ return ret;
+
+ /* Fill buffer information for the userspace */
+ ret = call_bufop(q, fill_user_buffer, vb, pb);
+ if (ret)
+ return ret;
+
+ dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
- dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index);
- }
return ret;
}
-EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
/**
* vb2_start_streaming() - Attempt to start streaming.
@@ -1845,19 +1336,34 @@ static int vb2_start_streaming(struct vb2_queue *q)
return ret;
}
-static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+/**
+ * vb2_core_qbuf() - Queue a buffer from userspace
+ * @q: videobuf2 queue
+ * @index: id number of the buffer
+ * @pb: buffer structure passed from userspace to vidioc_qbuf handler
+ * in driver
+ *
+ * Should be called from vidioc_qbuf ioctl handler of a driver.
+ * The passed buffer should have been verified.
+ * This function:
+ * 1) if necessary, calls buf_prepare callback in the driver (if provided), in
+ * which driver-specific buffer initialization can be performed,
+ * 2) if streaming is on, queues the buffer in driver by the means of buf_queue
+ * callback for processing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_qbuf handler in driver.
+ */
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
{
- int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
struct vb2_buffer *vb;
+ int ret;
- if (ret)
- return ret;
-
- vb = q->bufs[b->index];
+ vb = q->bufs[index];
switch (vb->state) {
case VB2_BUF_STATE_DEQUEUED:
- ret = __buf_prepare(vb, b);
+ ret = __buf_prepare(vb, pb);
if (ret)
return ret;
break;
@@ -1879,18 +1385,8 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
q->queued_count++;
q->waiting_for_buffers = false;
vb->state = VB2_BUF_STATE_QUEUED;
- if (V4L2_TYPE_IS_OUTPUT(q->type)) {
- /*
- * For output buffers copy the timestamp if needed,
- * and the timecode field and flag if needed.
- */
- if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY)
- vb->v4l2_buf.timestamp = b->timestamp;
- vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
- if (b->flags & V4L2_BUF_FLAG_TIMECODE)
- vb->v4l2_buf.timecode = b->timecode;
- }
+
+ call_bufop(q, set_timestamp, vb, pb);
trace_vb2_qbuf(q, vb);
@@ -1902,7 +1398,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
__enqueue_in_driver(vb);
/* Fill buffer information for the userspace */
- __fill_v4l2_buffer(vb, b);
+ ret = call_bufop(q, fill_user_buffer, vb, pb);
+ if (ret)
+ return ret;
/*
* If streamon has been called, and we haven't yet called
@@ -1917,37 +1415,10 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
return ret;
}
- dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
+ dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
return 0;
}
-
-/**
- * vb2_qbuf() - Queue a buffer from userspace
- * @q: videobuf2 queue
- * @b: buffer structure passed from userspace to vidioc_qbuf handler
- * in driver
- *
- * Should be called from vidioc_qbuf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
- * which driver-specific buffer initialization can be performed,
- * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
- * callback for processing.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_qbuf handler in driver.
- */
-int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
-{
- if (vb2_fileio_is_active(q)) {
- dprintk(1, "file io in progress\n");
- return -EBUSY;
- }
-
- return vb2_internal_qbuf(q, b);
-}
-EXPORT_SYMBOL_GPL(vb2_qbuf);
+EXPORT_SYMBOL_GPL(vb2_core_qbuf);
/**
* __vb2_wait_for_done_vb() - wait for a buffer to become available
@@ -2031,7 +1502,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
* Will sleep if required for nonblocking == false.
*/
static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
- struct v4l2_buffer *b, int nonblocking)
+ int nonblocking)
{
unsigned long flags;
int ret;
@@ -2052,10 +1523,10 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
/*
* Only remove the buffer from done_list if v4l2_buffer can handle all
* the planes.
+ * Verifying planes is NOT necessary since it already has been checked
+ * before the buffer is queued/prepared. So it can never fail.
*/
- ret = __verify_planes_array(*vb, b);
- if (!ret)
- list_del(&(*vb)->done_entry);
+ list_del(&(*vb)->done_entry);
spin_unlock_irqrestore(&q->done_lock, flags);
return ret;
@@ -2098,7 +1569,7 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
vb->state = VB2_BUF_STATE_DEQUEUED;
/* unmap DMABUF buffer */
- if (q->memory == V4L2_MEMORY_DMABUF)
+ if (q->memory == VB2_MEMORY_DMABUF)
for (i = 0; i < vb->num_planes; ++i) {
if (!vb->planes[i].dbuf_mapped)
continue;
@@ -2107,16 +1578,33 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
}
}
-static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+/**
+ * vb2_dqbuf() - Dequeue a buffer to the userspace
+ * @q: videobuf2 queue
+ * @pb: buffer structure passed from userspace to vidioc_dqbuf handler
+ * in driver
+ * @nonblocking: if true, this call will not sleep waiting for a buffer if no
+ * buffers ready for dequeuing are present. Normally the driver
+ * would be passing (file->f_flags & O_NONBLOCK) here
+ *
+ * Should be called from vidioc_dqbuf ioctl handler of a driver.
+ * The passed buffer should have been verified.
+ * This function:
+ * 1) calls buf_finish callback in the driver (if provided), in which
+ * driver can perform any additional operations that may be required before
+ * returning the buffer to userspace, such as cache sync,
+ * 2) the buffer struct members are filled with relevant information for
+ * the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_dqbuf handler in driver.
+ */
+int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
{
struct vb2_buffer *vb = NULL;
int ret;
- if (b->type != q->type) {
- dprintk(1, "invalid buffer type\n");
- return -EINVAL;
- }
- ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
+ ret = __vb2_get_done_vb(q, &vb, nonblocking);
if (ret < 0)
return ret;
@@ -2135,55 +1623,26 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n
call_void_vb_qop(vb, buf_finish, vb);
/* Fill buffer information for the userspace */
- __fill_v4l2_buffer(vb, b);
+ ret = call_bufop(q, fill_user_buffer, vb, pb);
+ if (ret)
+ return ret;
+
/* Remove from videobuf queue */
list_del(&vb->queued_entry);
q->queued_count--;
trace_vb2_dqbuf(q, vb);
- if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
- vb->v4l2_buf.flags & V4L2_BUF_FLAG_LAST)
- q->last_buffer_dequeued = true;
/* go back to dequeued state */
__vb2_dqbuf(vb);
dprintk(1, "dqbuf of buffer %d, with state %d\n",
- vb->v4l2_buf.index, vb->state);
+ vb->index, vb->state);
return 0;
-}
-/**
- * vb2_dqbuf() - Dequeue a buffer to the userspace
- * @q: videobuf2 queue
- * @b: buffer structure passed from userspace to vidioc_dqbuf handler
- * in driver
- * @nonblocking: if true, this call will not sleep waiting for a buffer if no
- * buffers ready for dequeuing are present. Normally the driver
- * would be passing (file->f_flags & O_NONBLOCK) here
- *
- * Should be called from vidioc_dqbuf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) calls buf_finish callback in the driver (if provided), in which
- * driver can perform any additional operations that may be required before
- * returning the buffer to userspace, such as cache sync,
- * 3) the buffer struct members are filled with relevant information for
- * the userspace.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_dqbuf handler in driver.
- */
-int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
-{
- if (vb2_fileio_is_active(q)) {
- dprintk(1, "file io in progress\n");
- return -EBUSY;
- }
- return vb2_internal_dqbuf(q, b, nonblocking);
}
-EXPORT_SYMBOL_GPL(vb2_dqbuf);
+EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
/**
* __vb2_queue_cancel() - cancel and stop (pause) streaming
@@ -2253,7 +1712,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
}
}
-static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
{
int ret;
@@ -2295,6 +1754,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
dprintk(3, "successful\n");
return 0;
}
+EXPORT_SYMBOL_GPL(vb2_core_streamon);
/**
* vb2_queue_error() - signal a fatal error on the queue
@@ -2317,30 +1777,7 @@ void vb2_queue_error(struct vb2_queue *q)
}
EXPORT_SYMBOL_GPL(vb2_queue_error);
-/**
- * vb2_streamon - start streaming
- * @q: videobuf2 queue
- * @type: type argument passed from userspace to vidioc_streamon handler
- *
- * Should be called from vidioc_streamon handler of a driver.
- * This function:
- * 1) verifies current state
- * 2) passes any previously queued buffers to the driver and starts streaming
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_streamon handler in the driver.
- */
-int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
-{
- if (vb2_fileio_is_active(q)) {
- dprintk(1, "file io in progress\n");
- return -EBUSY;
- }
- return vb2_internal_streamon(q, type);
-}
-EXPORT_SYMBOL_GPL(vb2_streamon);
-
-static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+int vb2_core_streamoff(struct vb2_queue *q, unsigned int type)
{
if (type != q->type) {
dprintk(1, "invalid stream type\n");
@@ -2357,37 +1794,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
* their normal dequeued state.
*/
__vb2_queue_cancel(q);
- q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+ q->waiting_for_buffers = !q->is_output;
q->last_buffer_dequeued = false;
dprintk(3, "successful\n");
return 0;
}
-
-/**
- * vb2_streamoff - stop streaming
- * @q: videobuf2 queue
- * @type: type argument passed from userspace to vidioc_streamoff handler
- *
- * Should be called from vidioc_streamoff handler of a driver.
- * This function:
- * 1) verifies current state,
- * 2) stop streaming and dequeues any queued buffers, including those previously
- * passed to the driver (after waiting for the driver to finish).
- *
- * This call can be used for pausing playback.
- * The return values from this function are intended to be directly returned
- * from vidioc_streamoff handler in the driver
- */
-int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
-{
- if (vb2_fileio_is_active(q)) {
- dprintk(1, "file io in progress\n");
- return -EBUSY;
- }
- return vb2_internal_streamoff(q, type);
-}
-EXPORT_SYMBOL_GPL(vb2_streamoff);
+EXPORT_SYMBOL_GPL(vb2_core_streamoff);
/**
* __find_plane_by_offset() - find plane associated with the given offset off
@@ -2407,7 +1820,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
vb = q->bufs[buffer];
for (plane = 0; plane < vb->num_planes; ++plane) {
- if (vb->v4l2_planes[plane].m.mem_offset == off) {
+ if (vb->planes[plane].m.offset == off) {
*_buffer = buffer;
*_plane = plane;
return 0;
@@ -2419,22 +1832,27 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
}
/**
- * vb2_expbuf() - Export a buffer as a file descriptor
+ * vb2_core_expbuf() - Export a buffer as a file descriptor
* @q: videobuf2 queue
- * @eb: export buffer structure passed from userspace to vidioc_expbuf
- * handler in driver
+ * @fd: file descriptor associated with DMABUF (set by driver) *
+ * @type: buffer type
+ * @index: id number of the buffer
+ * @plane: index of the plane to be exported, 0 for single plane queues
+ * @flags: flags for newly created file, currently only O_CLOEXEC is
+ * supported, refer to manual of open syscall for more details
*
* The return values from this function are intended to be directly returned
* from vidioc_expbuf handler in driver.
*/
-int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+ unsigned int index, unsigned int plane, unsigned int flags)
{
struct vb2_buffer *vb = NULL;
struct vb2_plane *vb_plane;
int ret;
struct dma_buf *dbuf;
- if (q->memory != V4L2_MEMORY_MMAP) {
+ if (q->memory != VB2_MEMORY_MMAP) {
dprintk(1, "queue is not currently set up for mmap\n");
return -EINVAL;
}
@@ -2444,24 +1862,24 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
return -EINVAL;
}
- if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
+ if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
return -EINVAL;
}
- if (eb->type != q->type) {
+ if (type != q->type) {
dprintk(1, "invalid buffer type\n");
return -EINVAL;
}
- if (eb->index >= q->num_buffers) {
+ if (index >= q->num_buffers) {
dprintk(1, "buffer index out of range\n");
return -EINVAL;
}
- vb = q->bufs[eb->index];
+ vb = q->bufs[index];
- if (eb->plane >= vb->num_planes) {
+ if (plane >= vb->num_planes) {
dprintk(1, "buffer plane out of range\n");
return -EINVAL;
}
@@ -2471,30 +1889,31 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
return -EBUSY;
}
- vb_plane = &vb->planes[eb->plane];
+ vb_plane = &vb->planes[plane];
- dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
+ dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
+ flags & O_ACCMODE);
if (IS_ERR_OR_NULL(dbuf)) {
dprintk(1, "failed to export buffer %d, plane %d\n",
- eb->index, eb->plane);
+ index, plane);
return -EINVAL;
}
- ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
+ ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
if (ret < 0) {
dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
- eb->index, eb->plane, ret);
+ index, plane, ret);
dma_buf_put(dbuf);
return ret;
}
dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
- eb->index, eb->plane, ret);
- eb->fd = ret;
+ index, plane, ret);
+ *fd = ret;
return 0;
}
-EXPORT_SYMBOL_GPL(vb2_expbuf);
+EXPORT_SYMBOL_GPL(vb2_core_expbuf);
/**
* vb2_mmap() - map video buffers into application address space
@@ -2523,7 +1942,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
int ret;
unsigned long length;
- if (q->memory != V4L2_MEMORY_MMAP) {
+ if (q->memory != VB2_MEMORY_MMAP) {
dprintk(1, "queue is not currently set up for mmap\n");
return -EINVAL;
}
@@ -2535,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
dprintk(1, "invalid vma flags, VM_SHARED needed\n");
return -EINVAL;
}
- if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+ if (q->is_output) {
if (!(vma->vm_flags & VM_WRITE)) {
dprintk(1, "invalid vma flags, VM_WRITE needed\n");
return -EINVAL;
@@ -2565,7 +1984,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
* The buffer length was page_aligned at __vb2_buf_mem_alloc(),
* so, we need to do the same here.
*/
- length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
+ length = PAGE_ALIGN(vb->planes[plane].length);
if (length < (vma->vm_end - vma->vm_start)) {
dprintk(1,
"MMAP invalid, as it would overflow buffer length\n");
@@ -2596,7 +2015,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
void *vaddr;
int ret;
- if (q->memory != V4L2_MEMORY_MMAP) {
+ if (q->memory != VB2_MEMORY_MMAP) {
dprintk(1, "queue is not currently set up for mmap\n");
return -EINVAL;
}
@@ -2616,123 +2035,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
#endif
-static int __vb2_init_fileio(struct vb2_queue *q, int read);
-static int __vb2_cleanup_fileio(struct vb2_queue *q);
-
-/**
- * vb2_poll() - implements poll userspace operation
- * @q: videobuf2 queue
- * @file: file argument passed to the poll file operation handler
- * @wait: wait argument passed to the poll file operation handler
- *
- * This function implements poll file operation handler for a driver.
- * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
- * be informed that the file descriptor of a video device is available for
- * reading.
- * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
- * will be reported as available for writing.
- *
- * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
- * pending events.
- *
- * The return values from this function are intended to be directly returned
- * from poll handler in driver.
- */
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
-{
- struct video_device *vfd = video_devdata(file);
- unsigned long req_events = poll_requested_events(wait);
- struct vb2_buffer *vb = NULL;
- unsigned int res = 0;
- unsigned long flags;
-
- if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
- struct v4l2_fh *fh = file->private_data;
-
- if (v4l2_event_pending(fh))
- res = POLLPRI;
- else if (req_events & POLLPRI)
- poll_wait(file, &fh->wait, wait);
- }
-
- if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
- return res;
- if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
- return res;
-
- /*
- * Start file I/O emulator only if streaming API has not been used yet.
- */
- if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
- if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
- (req_events & (POLLIN | POLLRDNORM))) {
- if (__vb2_init_fileio(q, 1))
- return res | POLLERR;
- }
- if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
- (req_events & (POLLOUT | POLLWRNORM))) {
- if (__vb2_init_fileio(q, 0))
- return res | POLLERR;
- /*
- * Write to OUTPUT queue can be done immediately.
- */
- return res | POLLOUT | POLLWRNORM;
- }
- }
-
- /*
- * There is nothing to wait for if the queue isn't streaming, or if the
- * error flag is set.
- */
- if (!vb2_is_streaming(q) || q->error)
- return res | POLLERR;
- /*
- * For compatibility with vb1: if QBUF hasn't been called yet, then
- * return POLLERR as well. This only affects capture queues, output
- * queues will always initialize waiting_for_buffers to false.
- */
- if (q->waiting_for_buffers)
- return res | POLLERR;
-
- /*
- * For output streams you can write as long as there are fewer buffers
- * queued than there are buffers available.
- */
- if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
- return res | POLLOUT | POLLWRNORM;
-
- if (list_empty(&q->done_list)) {
- /*
- * If the last buffer was dequeued from a capture queue,
- * return immediately. DQBUF will return -EPIPE.
- */
- if (q->last_buffer_dequeued)
- return res | POLLIN | POLLRDNORM;
-
- poll_wait(file, &q->done_wq, wait);
- }
-
- /*
- * Take first buffer available for dequeuing.
- */
- spin_lock_irqsave(&q->done_lock, flags);
- if (!list_empty(&q->done_list))
- vb = list_first_entry(&q->done_list, struct vb2_buffer,
- done_entry);
- spin_unlock_irqrestore(&q->done_lock, flags);
-
- if (vb && (vb->state == VB2_BUF_STATE_DONE
- || vb->state == VB2_BUF_STATE_ERROR)) {
- return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
- res | POLLOUT | POLLWRNORM :
- res | POLLIN | POLLRDNORM;
- }
- return res;
-}
-EXPORT_SYMBOL_GPL(vb2_poll);
-
/**
- * vb2_queue_init() - initialize a videobuf2 queue
+ * vb2_core_queue_init() - initialize a videobuf2 queue
* @q: videobuf2 queue; this structure should be allocated in driver
*
* The vb2_queue structure should be allocated by the driver. The driver is
@@ -2742,7 +2046,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
* to the struct vb2_queue description in include/media/videobuf2-core.h
* for more information.
*/
-int vb2_queue_init(struct vb2_queue *q)
+int vb2_core_queue_init(struct vb2_queue *q)
{
/*
* Sanity check
@@ -2753,16 +2057,9 @@ int vb2_queue_init(struct vb2_queue *q)
WARN_ON(!q->type) ||
WARN_ON(!q->io_modes) ||
WARN_ON(!q->ops->queue_setup) ||
- WARN_ON(!q->ops->buf_queue) ||
- WARN_ON(q->timestamp_flags &
- ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
- V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+ WARN_ON(!q->ops->buf_queue))
return -EINVAL;
- /* Warn that the driver should choose an appropriate timestamp type */
- WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
-
INIT_LIST_HEAD(&q->queued_list);
INIT_LIST_HEAD(&q->done_list);
spin_lock_init(&q->done_lock);
@@ -2774,819 +2071,24 @@ int vb2_queue_init(struct vb2_queue *q)
return 0;
}
-EXPORT_SYMBOL_GPL(vb2_queue_init);
+EXPORT_SYMBOL_GPL(vb2_core_queue_init);
/**
- * vb2_queue_release() - stop streaming, release the queue and free memory
+ * vb2_core_queue_release() - stop streaming, release the queue and free memory
* @q: videobuf2 queue
*
* This function stops streaming and performs necessary clean ups, including
* freeing video buffer memory. The driver is responsible for freeing
* the vb2_queue structure itself.
*/
-void vb2_queue_release(struct vb2_queue *q)
+void vb2_core_queue_release(struct vb2_queue *q)
{
- __vb2_cleanup_fileio(q);
__vb2_queue_cancel(q);
mutex_lock(&q->mmap_lock);
__vb2_queue_free(q, q->num_buffers);
mutex_unlock(&q->mmap_lock);
}
-EXPORT_SYMBOL_GPL(vb2_queue_release);
-
-/**
- * struct vb2_fileio_buf - buffer context used by file io emulator
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. This structure is used for
- * tracking context related to the buffers.
- */
-struct vb2_fileio_buf {
- void *vaddr;
- unsigned int size;
- unsigned int pos;
- unsigned int queued:1;
-};
-
-/**
- * struct vb2_fileio_data - queue context used by file io emulator
- *
- * @cur_index: the index of the buffer currently being read from or
- * written to. If equal to q->num_buffers then a new buffer
- * must be dequeued.
- * @initial_index: in the read() case all buffers are queued up immediately
- * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
- * buffers. However, in the write() case no buffers are initially
- * queued, instead whenever a buffer is full it is queued up by
- * __vb2_perform_fileio(). Only once all available buffers have
- * been queued up will __vb2_perform_fileio() start to dequeue
- * buffers. This means that initially __vb2_perform_fileio()
- * needs to know what buffer index to use when it is queuing up
- * the buffers for the first time. That initial index is stored
- * in this field. Once it is equal to q->num_buffers all
- * available buffers have been queued and __vb2_perform_fileio()
- * should start the normal dequeue/queue cycle.
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. For proper operation it required
- * this structure to save the driver state between each call of the read
- * or write function.
- */
-struct vb2_fileio_data {
- struct v4l2_requestbuffers req;
- struct v4l2_plane p;
- struct v4l2_buffer b;
- struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
- unsigned int cur_index;
- unsigned int initial_index;
- unsigned int q_count;
- unsigned int dq_count;
- unsigned read_once:1;
- unsigned write_immediately:1;
-};
-
-/**
- * __vb2_init_fileio() - initialize file io emulator
- * @q: videobuf2 queue
- * @read: mode selector (1 means read, 0 means write)
- */
-static int __vb2_init_fileio(struct vb2_queue *q, int read)
-{
- struct vb2_fileio_data *fileio;
- int i, ret;
- unsigned int count = 0;
-
- /*
- * Sanity check
- */
- if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
- (!read && !(q->io_modes & VB2_WRITE))))
- return -EINVAL;
-
- /*
- * Check if device supports mapping buffers to kernel virtual space.
- */
- if (!q->mem_ops->vaddr)
- return -EBUSY;
-
- /*
- * Check if streaming api has not been already activated.
- */
- if (q->streaming || q->num_buffers > 0)
- return -EBUSY;
-
- /*
- * Start with count 1, driver can increase it in queue_setup()
- */
- count = 1;
-
- dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
- (read) ? "read" : "write", count, q->fileio_read_once,
- q->fileio_write_immediately);
-
- fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
- if (fileio == NULL)
- return -ENOMEM;
-
- fileio->read_once = q->fileio_read_once;
- fileio->write_immediately = q->fileio_write_immediately;
-
- /*
- * Request buffers and use MMAP type to force driver
- * to allocate buffers by itself.
- */
- fileio->req.count = count;
- fileio->req.memory = V4L2_MEMORY_MMAP;
- fileio->req.type = q->type;
- q->fileio = fileio;
- ret = __reqbufs(q, &fileio->req);
- if (ret)
- goto err_kfree;
-
- /*
- * Check if plane_count is correct
- * (multiplane buffers are not supported).
- */
- if (q->bufs[0]->num_planes != 1) {
- ret = -EBUSY;
- goto err_reqbufs;
- }
-
- /*
- * Get kernel address of each buffer.
- */
- for (i = 0; i < q->num_buffers; i++) {
- fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
- if (fileio->bufs[i].vaddr == NULL) {
- ret = -EINVAL;
- goto err_reqbufs;
- }
- fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
- }
-
- /*
- * Read mode requires pre queuing of all buffers.
- */
- if (read) {
- bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
-
- /*
- * Queue all buffers.
- */
- for (i = 0; i < q->num_buffers; i++) {
- struct v4l2_buffer *b = &fileio->b;
-
- memset(b, 0, sizeof(*b));
- b->type = q->type;
- if (is_multiplanar) {
- memset(&fileio->p, 0, sizeof(fileio->p));
- b->m.planes = &fileio->p;
- b->length = 1;
- }
- b->memory = q->memory;
- b->index = i;
- ret = vb2_internal_qbuf(q, b);
- if (ret)
- goto err_reqbufs;
- fileio->bufs[i].queued = 1;
- }
- /*
- * All buffers have been queued, so mark that by setting
- * initial_index to q->num_buffers
- */
- fileio->initial_index = q->num_buffers;
- fileio->cur_index = q->num_buffers;
- }
-
- /*
- * Start streaming.
- */
- ret = vb2_internal_streamon(q, q->type);
- if (ret)
- goto err_reqbufs;
-
- return ret;
-
-err_reqbufs:
- fileio->req.count = 0;
- __reqbufs(q, &fileio->req);
-
-err_kfree:
- q->fileio = NULL;
- kfree(fileio);
- return ret;
-}
-
-/**
- * __vb2_cleanup_fileio() - free resourced used by file io emulator
- * @q: videobuf2 queue
- */
-static int __vb2_cleanup_fileio(struct vb2_queue *q)
-{
- struct vb2_fileio_data *fileio = q->fileio;
-
- if (fileio) {
- vb2_internal_streamoff(q, q->type);
- q->fileio = NULL;
- fileio->req.count = 0;
- vb2_reqbufs(q, &fileio->req);
- kfree(fileio);
- dprintk(3, "file io emulator closed\n");
- }
- return 0;
-}
-
-/**
- * __vb2_perform_fileio() - perform a single file io (read or write) operation
- * @q: videobuf2 queue
- * @data: pointed to target userspace buffer
- * @count: number of bytes to read or write
- * @ppos: file handle position tracking pointer
- * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
- * @read: access mode selector (1 means read, 0 means write)
- */
-static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblock, int read)
-{
- struct vb2_fileio_data *fileio;
- struct vb2_fileio_buf *buf;
- bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
- /*
- * When using write() to write data to an output video node the vb2 core
- * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
- * else is able to provide this information with the write() operation.
- */
- bool set_timestamp = !read &&
- (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY;
- int ret, index;
-
- dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
- read ? "read" : "write", (long)*ppos, count,
- nonblock ? "non" : "");
-
- if (!data)
- return -EINVAL;
-
- /*
- * Initialize emulator on first call.
- */
- if (!vb2_fileio_is_active(q)) {
- ret = __vb2_init_fileio(q, read);
- dprintk(3, "vb2_init_fileio result: %d\n", ret);
- if (ret)
- return ret;
- }
- fileio = q->fileio;
-
- /*
- * Check if we need to dequeue the buffer.
- */
- index = fileio->cur_index;
- if (index >= q->num_buffers) {
- /*
- * Call vb2_dqbuf to get buffer back.
- */
- memset(&fileio->b, 0, sizeof(fileio->b));
- fileio->b.type = q->type;
- fileio->b.memory = q->memory;
- if (is_multiplanar) {
- memset(&fileio->p, 0, sizeof(fileio->p));
- fileio->b.m.planes = &fileio->p;
- fileio->b.length = 1;
- }
- ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
- dprintk(5, "vb2_dqbuf result: %d\n", ret);
- if (ret)
- return ret;
- fileio->dq_count += 1;
-
- fileio->cur_index = index = fileio->b.index;
- buf = &fileio->bufs[index];
-
- /*
- * Get number of bytes filled by the driver
- */
- buf->pos = 0;
- buf->queued = 0;
- buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
- : vb2_plane_size(q->bufs[index], 0);
- /* Compensate for data_offset on read in the multiplanar case. */
- if (is_multiplanar && read &&
- fileio->b.m.planes[0].data_offset < buf->size) {
- buf->pos = fileio->b.m.planes[0].data_offset;
- buf->size -= buf->pos;
- }
- } else {
- buf = &fileio->bufs[index];
- }
-
- /*
- * Limit count on last few bytes of the buffer.
- */
- if (buf->pos + count > buf->size) {
- count = buf->size - buf->pos;
- dprintk(5, "reducing read count: %zd\n", count);
- }
-
- /*
- * Transfer data to userspace.
- */
- dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
- count, index, buf->pos);
- if (read)
- ret = copy_to_user(data, buf->vaddr + buf->pos, count);
- else
- ret = copy_from_user(buf->vaddr + buf->pos, data, count);
- if (ret) {
- dprintk(3, "error copying data\n");
- return -EFAULT;
- }
-
- /*
- * Update counters.
- */
- buf->pos += count;
- *ppos += count;
-
- /*
- * Queue next buffer if required.
- */
- if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
- /*
- * Check if this is the last buffer to read.
- */
- if (read && fileio->read_once && fileio->dq_count == 1) {
- dprintk(3, "read limit reached\n");
- return __vb2_cleanup_fileio(q);
- }
-
- /*
- * Call vb2_qbuf and give buffer to the driver.
- */
- memset(&fileio->b, 0, sizeof(fileio->b));
- fileio->b.type = q->type;
- fileio->b.memory = q->memory;
- fileio->b.index = index;
- fileio->b.bytesused = buf->pos;
- if (is_multiplanar) {
- memset(&fileio->p, 0, sizeof(fileio->p));
- fileio->p.bytesused = buf->pos;
- fileio->b.m.planes = &fileio->p;
- fileio->b.length = 1;
- }
- if (set_timestamp)
- v4l2_get_timestamp(&fileio->b.timestamp);
- ret = vb2_internal_qbuf(q, &fileio->b);
- dprintk(5, "vb2_dbuf result: %d\n", ret);
- if (ret)
- return ret;
-
- /*
- * Buffer has been queued, update the status
- */
- buf->pos = 0;
- buf->queued = 1;
- buf->size = vb2_plane_size(q->bufs[index], 0);
- fileio->q_count += 1;
- /*
- * If we are queuing up buffers for the first time, then
- * increase initial_index by one.
- */
- if (fileio->initial_index < q->num_buffers)
- fileio->initial_index++;
- /*
- * The next buffer to use is either a buffer that's going to be
- * queued for the first time (initial_index < q->num_buffers)
- * or it is equal to q->num_buffers, meaning that the next
- * time we need to dequeue a buffer since we've now queued up
- * all the 'first time' buffers.
- */
- fileio->cur_index = fileio->initial_index;
- }
-
- /*
- * Return proper number of bytes processed.
- */
- if (ret == 0)
- ret = count;
- return ret;
-}
-
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblocking)
-{
- return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
-}
-EXPORT_SYMBOL_GPL(vb2_read);
-
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
- loff_t *ppos, int nonblocking)
-{
- return __vb2_perform_fileio(q, (char __user *) data, count,
- ppos, nonblocking, 0);
-}
-EXPORT_SYMBOL_GPL(vb2_write);
-
-struct vb2_threadio_data {
- struct task_struct *thread;
- vb2_thread_fnc fnc;
- void *priv;
- bool stop;
-};
-
-static int vb2_thread(void *data)
-{
- struct vb2_queue *q = data;
- struct vb2_threadio_data *threadio = q->threadio;
- struct vb2_fileio_data *fileio = q->fileio;
- bool set_timestamp = false;
- int prequeue = 0;
- int index = 0;
- int ret = 0;
-
- if (V4L2_TYPE_IS_OUTPUT(q->type)) {
- prequeue = q->num_buffers;
- set_timestamp =
- (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY;
- }
-
- set_freezable();
-
- for (;;) {
- struct vb2_buffer *vb;
-
- /*
- * Call vb2_dqbuf to get buffer back.
- */
- memset(&fileio->b, 0, sizeof(fileio->b));
- fileio->b.type = q->type;
- fileio->b.memory = q->memory;
- if (prequeue) {
- fileio->b.index = index++;
- prequeue--;
- } else {
- call_void_qop(q, wait_finish, q);
- if (!threadio->stop)
- ret = vb2_internal_dqbuf(q, &fileio->b, 0);
- call_void_qop(q, wait_prepare, q);
- dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
- }
- if (ret || threadio->stop)
- break;
- try_to_freeze();
-
- vb = q->bufs[fileio->b.index];
- if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
- if (threadio->fnc(vb, threadio->priv))
- break;
- call_void_qop(q, wait_finish, q);
- if (set_timestamp)
- v4l2_get_timestamp(&fileio->b.timestamp);
- if (!threadio->stop)
- ret = vb2_internal_qbuf(q, &fileio->b);
- call_void_qop(q, wait_prepare, q);
- if (ret || threadio->stop)
- break;
- }
-
- /* Hmm, linux becomes *very* unhappy without this ... */
- while (!kthread_should_stop()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- }
- return 0;
-}
-
-/*
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
- const char *thread_name)
-{
- struct vb2_threadio_data *threadio;
- int ret = 0;
-
- if (q->threadio)
- return -EBUSY;
- if (vb2_is_busy(q))
- return -EBUSY;
- if (WARN_ON(q->fileio))
- return -EBUSY;
-
- threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
- if (threadio == NULL)
- return -ENOMEM;
- threadio->fnc = fnc;
- threadio->priv = priv;
-
- ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
- dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
- if (ret)
- goto nomem;
- q->threadio = threadio;
- threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
- if (IS_ERR(threadio->thread)) {
- ret = PTR_ERR(threadio->thread);
- threadio->thread = NULL;
- goto nothread;
- }
- return 0;
-
-nothread:
- __vb2_cleanup_fileio(q);
-nomem:
- kfree(threadio);
- return ret;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_start);
-
-int vb2_thread_stop(struct vb2_queue *q)
-{
- struct vb2_threadio_data *threadio = q->threadio;
- int err;
-
- if (threadio == NULL)
- return 0;
- threadio->stop = true;
- /* Wake up all pending sleeps in the thread */
- vb2_queue_error(q);
- err = kthread_stop(threadio->thread);
- __vb2_cleanup_fileio(q);
- threadio->thread = NULL;
- kfree(threadio);
- q->threadio = NULL;
- return err;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_stop);
-
-/*
- * The following functions are not part of the vb2 core API, but are helper
- * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
- * and struct vb2_ops.
- * They contain boilerplate code that most if not all drivers have to do
- * and so they simplify the driver code.
- */
-
-/* The queue is busy if there is a owner and you are not that owner. */
-static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
-{
- return vdev->queue->owner && vdev->queue->owner != file->private_data;
-}
-
-/* vb2 ioctl helpers */
-
-int vb2_ioctl_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *p)
-{
- struct video_device *vdev = video_devdata(file);
- int res = __verify_memory_type(vdev->queue, p->memory, p->type);
-
- if (res)
- return res;
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- res = __reqbufs(vdev->queue, p);
- /* If count == 0, then the owner has released all buffers and he
- is no longer owner of the queue. Otherwise we have a new owner. */
- if (res == 0)
- vdev->queue->owner = p->count ? file->private_data : NULL;
- return res;
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
-
-int vb2_ioctl_create_bufs(struct file *file, void *priv,
- struct v4l2_create_buffers *p)
-{
- struct video_device *vdev = video_devdata(file);
- int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
-
- p->index = vdev->queue->num_buffers;
- /* If count == 0, then just check if memory and type are valid.
- Any -EBUSY result from __verify_memory_type can be mapped to 0. */
- if (p->count == 0)
- return res != -EBUSY ? res : 0;
- if (res)
- return res;
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- res = __create_bufs(vdev->queue, p);
- if (res == 0)
- vdev->queue->owner = file->private_data;
- return res;
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
-
-int vb2_ioctl_prepare_buf(struct file *file, void *priv,
- struct v4l2_buffer *p)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- return vb2_prepare_buf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
-
-int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
- struct video_device *vdev = video_devdata(file);
-
- /* No need to call vb2_queue_is_busy(), anyone can query buffers. */
- return vb2_querybuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
-
-int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- return vb2_qbuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
-
-int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
-
-int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- return vb2_streamon(vdev->queue, i);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
-
-int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- return vb2_streamoff(vdev->queue, i);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
-
-int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vb2_queue_is_busy(vdev, file))
- return -EBUSY;
- return vb2_expbuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
-
-/* v4l2_file_operations helpers */
-
-int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct video_device *vdev = video_devdata(file);
-
- return vb2_mmap(vdev->queue, vma);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_mmap);
-
-int _vb2_fop_release(struct file *file, struct mutex *lock)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (lock)
- mutex_lock(lock);
- if (file->private_data == vdev->queue->owner) {
- vb2_queue_release(vdev->queue);
- vdev->queue->owner = NULL;
- }
- if (lock)
- mutex_unlock(lock);
- return v4l2_fh_release(file);
-}
-EXPORT_SYMBOL_GPL(_vb2_fop_release);
-
-int vb2_fop_release(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
- struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-
- return _vb2_fop_release(file, lock);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_release);
-
-ssize_t vb2_fop_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct video_device *vdev = video_devdata(file);
- struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
- int err = -EBUSY;
-
- if (!(vdev->queue->io_modes & VB2_WRITE))
- return -EINVAL;
- if (lock && mutex_lock_interruptible(lock))
- return -ERESTARTSYS;
- if (vb2_queue_is_busy(vdev, file))
- goto exit;
- err = vb2_write(vdev->queue, buf, count, ppos,
- file->f_flags & O_NONBLOCK);
- if (vdev->queue->fileio)
- vdev->queue->owner = file->private_data;
-exit:
- if (lock)
- mutex_unlock(lock);
- return err;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_write);
-
-ssize_t vb2_fop_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct video_device *vdev = video_devdata(file);
- struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
- int err = -EBUSY;
-
- if (!(vdev->queue->io_modes & VB2_READ))
- return -EINVAL;
- if (lock && mutex_lock_interruptible(lock))
- return -ERESTARTSYS;
- if (vb2_queue_is_busy(vdev, file))
- goto exit;
- err = vb2_read(vdev->queue, buf, count, ppos,
- file->f_flags & O_NONBLOCK);
- if (vdev->queue->fileio)
- vdev->queue->owner = file->private_data;
-exit:
- if (lock)
- mutex_unlock(lock);
- return err;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_read);
-
-unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
-{
- struct video_device *vdev = video_devdata(file);
- struct vb2_queue *q = vdev->queue;
- struct mutex *lock = q->lock ? q->lock : vdev->lock;
- unsigned res;
- void *fileio;
-
- /*
- * If this helper doesn't know how to lock, then you shouldn't be using
- * it but you should write your own.
- */
- WARN_ON(!lock);
-
- if (lock && mutex_lock_interruptible(lock))
- return POLLERR;
-
- fileio = q->fileio;
-
- res = vb2_poll(vdev->queue, file, wait);
-
- /* If fileio was started, then we have a new queue owner. */
- if (!fileio && q->fileio)
- q->owner = file->private_data;
- if (lock)
- mutex_unlock(lock);
- return res;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_poll);
-
-#ifndef CONFIG_MMU
-unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
-{
- struct video_device *vdev = video_devdata(file);
-
- return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
-#endif
-
-/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
-
-void vb2_ops_wait_prepare(struct vb2_queue *vq)
-{
- mutex_unlock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
-
-void vb2_ops_wait_finish(struct vb2_queue *vq)
-{
- mutex_lock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+EXPORT_SYMBOL_GPL(vb2_core_queue_release);
MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 2397ceb1dc6b..c33127284cfe 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -17,7 +17,7 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-memops.h>
@@ -100,7 +100,8 @@ static void vb2_dc_prepare(void *buf_priv)
if (!sgt || buf->db_attach)
return;
- dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+ dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents,
+ buf->dma_dir);
}
static void vb2_dc_finish(void *buf_priv)
@@ -112,7 +113,7 @@ static void vb2_dc_finish(void *buf_priv)
if (!sgt || buf->db_attach)
return;
- dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+ dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
}
/*********************************************/
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index be7bd6535c9d..9985c89f0513 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -17,7 +17,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-memops.h>
#include <media/videobuf2-dma-sg.h>
@@ -210,7 +210,8 @@ static void vb2_dma_sg_prepare(void *buf_priv)
if (buf->db_attach)
return;
- dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+ dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents,
+ buf->dma_dir);
}
static void vb2_dma_sg_finish(void *buf_priv)
@@ -222,7 +223,7 @@ static void vb2_dma_sg_finish(void *buf_priv)
if (buf->db_attach)
return;
- dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+ dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
}
static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
new file mode 100644
index 000000000000..79018c749282
--- /dev/null
+++ b/drivers/media/v4l2-core/videobuf2-internal.h
@@ -0,0 +1,161 @@
+#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
+#define _MEDIA_VIDEOBUF2_INTERNAL_H
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <media/videobuf2-core.h>
+
+extern int vb2_debug;
+
+#define dprintk(level, fmt, arg...) \
+ do { \
+ if (vb2_debug >= level) \
+ pr_info("vb2: %s: " fmt, __func__, ## arg); \
+ } while (0)
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+/*
+ * If advanced debugging is on, then count how often each op is called
+ * successfully, which can either be per-buffer or per-queue.
+ *
+ * This makes it easy to check that the 'init' and 'cleanup'
+ * (and variations thereof) stay balanced.
+ */
+
+#define log_memop(vb, op) \
+ dprintk(2, "call_memop(%p, %d, %s)%s\n", \
+ (vb)->vb2_queue, (vb)->index, #op, \
+ (vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
+
+#define call_memop(vb, op, args...) \
+({ \
+ struct vb2_queue *_q = (vb)->vb2_queue; \
+ int err; \
+ \
+ log_memop(vb, op); \
+ err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \
+ if (!err) \
+ (vb)->cnt_mem_ ## op++; \
+ err; \
+})
+
+#define call_ptr_memop(vb, op, args...) \
+({ \
+ struct vb2_queue *_q = (vb)->vb2_queue; \
+ void *ptr; \
+ \
+ log_memop(vb, op); \
+ ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \
+ if (!IS_ERR_OR_NULL(ptr)) \
+ (vb)->cnt_mem_ ## op++; \
+ ptr; \
+})
+
+#define call_void_memop(vb, op, args...) \
+({ \
+ struct vb2_queue *_q = (vb)->vb2_queue; \
+ \
+ log_memop(vb, op); \
+ if (_q->mem_ops->op) \
+ _q->mem_ops->op(args); \
+ (vb)->cnt_mem_ ## op++; \
+})
+
+#define log_qop(q, op) \
+ dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \
+ (q)->ops->op ? "" : " (nop)")
+
+#define call_qop(q, op, args...) \
+({ \
+ int err; \
+ \
+ log_qop(q, op); \
+ err = (q)->ops->op ? (q)->ops->op(args) : 0; \
+ if (!err) \
+ (q)->cnt_ ## op++; \
+ err; \
+})
+
+#define call_void_qop(q, op, args...) \
+({ \
+ log_qop(q, op); \
+ if ((q)->ops->op) \
+ (q)->ops->op(args); \
+ (q)->cnt_ ## op++; \
+})
+
+#define log_vb_qop(vb, op, args...) \
+ dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \
+ (vb)->vb2_queue, (vb)->index, #op, \
+ (vb)->vb2_queue->ops->op ? "" : " (nop)")
+
+#define call_vb_qop(vb, op, args...) \
+({ \
+ int err; \
+ \
+ log_vb_qop(vb, op); \
+ err = (vb)->vb2_queue->ops->op ? \
+ (vb)->vb2_queue->ops->op(args) : 0; \
+ if (!err) \
+ (vb)->cnt_ ## op++; \
+ err; \
+})
+
+#define call_void_vb_qop(vb, op, args...) \
+({ \
+ log_vb_qop(vb, op); \
+ if ((vb)->vb2_queue->ops->op) \
+ (vb)->vb2_queue->ops->op(args); \
+ (vb)->cnt_ ## op++; \
+})
+
+#else
+
+#define call_memop(vb, op, args...) \
+ ((vb)->vb2_queue->mem_ops->op ? \
+ (vb)->vb2_queue->mem_ops->op(args) : 0)
+
+#define call_ptr_memop(vb, op, args...) \
+ ((vb)->vb2_queue->mem_ops->op ? \
+ (vb)->vb2_queue->mem_ops->op(args) : NULL)
+
+#define call_void_memop(vb, op, args...) \
+ do { \
+ if ((vb)->vb2_queue->mem_ops->op) \
+ (vb)->vb2_queue->mem_ops->op(args); \
+ } while (0)
+
+#define call_qop(q, op, args...) \
+ ((q)->ops->op ? (q)->ops->op(args) : 0)
+
+#define call_void_qop(q, op, args...) \
+ do { \
+ if ((q)->ops->op) \
+ (q)->ops->op(args); \
+ } while (0)
+
+#define call_vb_qop(vb, op, args...) \
+ ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
+
+#define call_void_vb_qop(vb, op, args...) \
+ do { \
+ if ((vb)->vb2_queue->ops->op) \
+ (vb)->vb2_queue->ops->op(args); \
+ } while (0)
+
+#endif
+
+#define call_bufop(q, op, args...) \
+({ \
+ int ret = 0; \
+ if (q && q->buf_ops && q->buf_ops->op) \
+ ret = q->buf_ops->op(args); \
+ ret; \
+})
+
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
+int vb2_verify_memory_type(struct vb2_queue *q,
+ enum vb2_memory memory, unsigned int type);
+#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c
index 48c6a49c4928..dbec5923fcf0 100644
--- a/drivers/media/v4l2-core/videobuf2-memops.c
+++ b/drivers/media/v4l2-core/videobuf2-memops.c
@@ -19,7 +19,7 @@
#include <linux/sched.h>
#include <linux/file.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-memops.h>
/**
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
new file mode 100644
index 000000000000..27b4b9e7c0c2
--- /dev/null
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -0,0 +1,1661 @@
+/*
+ * videobuf2-v4l2.c - V4L2 driver helper framework
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.com>
+ * Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * The vb2_thread implementation was based on code from videobuf-dvb.c:
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-common.h>
+
+#include <media/videobuf2-v4l2.h>
+
+#include "videobuf2-internal.h"
+
+/* Flags that are set by the vb2 core */
+#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+ V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
+ V4L2_BUF_FLAG_PREPARED | \
+ V4L2_BUF_FLAG_TIMESTAMP_MASK)
+/* Output buffer flags that should be passed on to the driver */
+#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
+ V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
+
+/**
+ * __verify_planes_array() - verify that the planes array passed in struct
+ * v4l2_buffer from userspace can be safely used
+ */
+static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+ if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
+ return 0;
+
+ /* Is memory for copying plane information present? */
+ if (NULL == b->m.planes) {
+ dprintk(1, "multi-planar buffer passed but "
+ "planes array not provided\n");
+ return -EINVAL;
+ }
+
+ if (b->length < vb->num_planes || b->length > VB2_MAX_PLANES) {
+ dprintk(1, "incorrect planes array length, "
+ "expected %d, got %d\n", vb->num_planes, b->length);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * __verify_length() - Verify that the bytesused value for each plane fits in
+ * the plane length and that the data offset doesn't exceed the bytesused value.
+ */
+static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+ unsigned int length;
+ unsigned int bytesused;
+ unsigned int plane;
+
+ if (!V4L2_TYPE_IS_OUTPUT(b->type))
+ return 0;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ length = (b->memory == VB2_MEMORY_USERPTR ||
+ b->memory == VB2_MEMORY_DMABUF)
+ ? b->m.planes[plane].length
+ : vb->planes[plane].length;
+ bytesused = b->m.planes[plane].bytesused
+ ? b->m.planes[plane].bytesused : length;
+
+ if (b->m.planes[plane].bytesused > length)
+ return -EINVAL;
+
+ if (b->m.planes[plane].data_offset > 0 &&
+ b->m.planes[plane].data_offset >= bytesused)
+ return -EINVAL;
+ }
+ } else {
+ length = (b->memory == VB2_MEMORY_USERPTR)
+ ? b->length : vb->planes[0].length;
+
+ if (b->bytesused > length)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
+{
+ const struct v4l2_buffer *b = pb;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vb2_queue *q = vb->vb2_queue;
+
+ if (q->is_output) {
+ /*
+ * For output buffers copy the timestamp if needed,
+ * and the timecode field and flag if needed.
+ */
+ if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+ V4L2_BUF_FLAG_TIMESTAMP_COPY)
+ vbuf->timestamp = b->timestamp;
+ vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
+ if (b->flags & V4L2_BUF_FLAG_TIMECODE)
+ vbuf->timecode = b->timecode;
+ }
+ return 0;
+};
+
+static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
+{
+ static bool check_once;
+
+ if (check_once)
+ return;
+
+ check_once = true;
+ WARN_ON(1);
+
+ pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
+ if (vb->vb2_queue->allow_zero_bytesused)
+ pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
+ else
+ pr_warn("use the actual size instead.\n");
+}
+
+static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
+ const char *opname)
+{
+ if (b->type != q->type) {
+ dprintk(1, "%s: invalid buffer type\n", opname);
+ return -EINVAL;
+ }
+
+ if (b->index >= q->num_buffers) {
+ dprintk(1, "%s: buffer index out of range\n", opname);
+ return -EINVAL;
+ }
+
+ if (q->bufs[b->index] == NULL) {
+ /* Should never happen */
+ dprintk(1, "%s: buffer is NULL\n", opname);
+ return -EINVAL;
+ }
+
+ if (b->memory != q->memory) {
+ dprintk(1, "%s: invalid memory type\n", opname);
+ return -EINVAL;
+ }
+
+ return __verify_planes_array(q->bufs[b->index], b);
+}
+
+/**
+ * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
+ * returned to userspace
+ */
+static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
+{
+ struct v4l2_buffer *b = pb;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vb2_queue *q = vb->vb2_queue;
+ unsigned int plane;
+
+ /* Copy back data such as timestamp, flags, etc. */
+ b->index = vb->index;
+ b->type = vb->type;
+ b->memory = vb->memory;
+ b->bytesused = 0;
+
+ b->flags = vbuf->flags;
+ b->field = vbuf->field;
+ b->timestamp = vbuf->timestamp;
+ b->timecode = vbuf->timecode;
+ b->sequence = vbuf->sequence;
+ b->reserved2 = 0;
+ b->reserved = 0;
+
+ if (q->is_multiplanar) {
+ /*
+ * Fill in plane-related data if userspace provided an array
+ * for it. The caller has already verified memory and size.
+ */
+ b->length = vb->num_planes;
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ struct v4l2_plane *pdst = &b->m.planes[plane];
+ struct vb2_plane *psrc = &vb->planes[plane];
+
+ pdst->bytesused = psrc->bytesused;
+ pdst->length = psrc->length;
+ if (q->memory == VB2_MEMORY_MMAP)
+ pdst->m.mem_offset = psrc->m.offset;
+ else if (q->memory == VB2_MEMORY_USERPTR)
+ pdst->m.userptr = psrc->m.userptr;
+ else if (q->memory == VB2_MEMORY_DMABUF)
+ pdst->m.fd = psrc->m.fd;
+ pdst->data_offset = psrc->data_offset;
+ memset(pdst->reserved, 0, sizeof(pdst->reserved));
+ }
+ } else {
+ /*
+ * We use length and offset in v4l2_planes array even for
+ * single-planar buffers, but userspace does not.
+ */
+ b->length = vb->planes[0].length;
+ b->bytesused = vb->planes[0].bytesused;
+ if (q->memory == VB2_MEMORY_MMAP)
+ b->m.offset = vb->planes[0].m.offset;
+ else if (q->memory == VB2_MEMORY_USERPTR)
+ b->m.userptr = vb->planes[0].m.userptr;
+ else if (q->memory == VB2_MEMORY_DMABUF)
+ b->m.fd = vb->planes[0].m.fd;
+ }
+
+ /*
+ * Clear any buffer state related flags.
+ */
+ b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
+ b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
+ if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
+ V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+ /*
+ * For non-COPY timestamps, drop timestamp source bits
+ * and obtain the timestamp source from the queue.
+ */
+ b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ }
+
+ switch (vb->state) {
+ case VB2_BUF_STATE_QUEUED:
+ case VB2_BUF_STATE_ACTIVE:
+ b->flags |= V4L2_BUF_FLAG_QUEUED;
+ break;
+ case VB2_BUF_STATE_ERROR:
+ b->flags |= V4L2_BUF_FLAG_ERROR;
+ /* fall through */
+ case VB2_BUF_STATE_DONE:
+ b->flags |= V4L2_BUF_FLAG_DONE;
+ break;
+ case VB2_BUF_STATE_PREPARED:
+ b->flags |= V4L2_BUF_FLAG_PREPARED;
+ break;
+ case VB2_BUF_STATE_PREPARING:
+ case VB2_BUF_STATE_DEQUEUED:
+ case VB2_BUF_STATE_REQUEUEING:
+ /* nothing */
+ break;
+ }
+
+ if (vb2_buffer_in_use(q, vb))
+ b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+ return 0;
+}
+
+/**
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
+ * v4l2_buffer by the userspace. It also verifies that struct
+ * v4l2_buffer has a valid number of planes.
+ */
+static int __fill_vb2_buffer(struct vb2_buffer *vb,
+ const void *pb, struct vb2_plane *planes)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ const struct v4l2_buffer *b = pb;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ unsigned int plane;
+ int ret;
+
+ ret = __verify_length(vb, b);
+ if (ret < 0) {
+ dprintk(1, "plane parameters verification failed: %d\n", ret);
+ return ret;
+ }
+ if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
+ /*
+ * If the format's field is ALTERNATE, then the buffer's field
+ * should be either TOP or BOTTOM, not ALTERNATE since that
+ * makes no sense. The driver has to know whether the
+ * buffer represents a top or a bottom field in order to
+ * program any DMA correctly. Using ALTERNATE is wrong, since
+ * that just says that it is either a top or a bottom field,
+ * but not which of the two it is.
+ */
+ dprintk(1, "the field is incorrectly set to ALTERNATE "
+ "for an output buffer\n");
+ return -EINVAL;
+ }
+ vbuf->timestamp.tv_sec = 0;
+ vbuf->timestamp.tv_usec = 0;
+ vbuf->sequence = 0;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ if (b->memory == VB2_MEMORY_USERPTR) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ planes[plane].m.userptr =
+ b->m.planes[plane].m.userptr;
+ planes[plane].length =
+ b->m.planes[plane].length;
+ }
+ }
+ if (b->memory == VB2_MEMORY_DMABUF) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ planes[plane].m.fd =
+ b->m.planes[plane].m.fd;
+ planes[plane].length =
+ b->m.planes[plane].length;
+ }
+ }
+
+ /* Fill in driver-provided information for OUTPUT types */
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ /*
+ * Will have to go up to b->length when API starts
+ * accepting variable number of planes.
+ *
+ * If bytesused == 0 for the output buffer, then fall
+ * back to the full buffer size. In that case
+ * userspace clearly never bothered to set it and
+ * it's a safe assumption that they really meant to
+ * use the full plane sizes.
+ *
+ * Some drivers, e.g. old codec drivers, use bytesused == 0
+ * as a way to indicate that streaming is finished.
+ * In that case, the driver should use the
+ * allow_zero_bytesused flag to keep old userspace
+ * applications working.
+ */
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ struct vb2_plane *pdst = &planes[plane];
+ struct v4l2_plane *psrc = &b->m.planes[plane];
+
+ if (psrc->bytesused == 0)
+ vb2_warn_zero_bytesused(vb);
+
+ if (vb->vb2_queue->allow_zero_bytesused)
+ pdst->bytesused = psrc->bytesused;
+ else
+ pdst->bytesused = psrc->bytesused ?
+ psrc->bytesused : pdst->length;
+ pdst->data_offset = psrc->data_offset;
+ }
+ }
+ } else {
+ /*
+ * Single-planar buffers do not use planes array,
+ * so fill in relevant v4l2_buffer struct fields instead.
+ * In videobuf we use our internal V4l2_planes struct for
+ * single-planar buffers as well, for simplicity.
+ *
+ * If bytesused == 0 for the output buffer, then fall back
+ * to the full buffer size as that's a sensible default.
+ *
+ * Some drivers, e.g. old codec drivers, use bytesused == 0 as
+ * a way to indicate that streaming is finished. In that case,
+ * the driver should use the allow_zero_bytesused flag to keep
+ * old userspace applications working.
+ */
+ if (b->memory == VB2_MEMORY_USERPTR) {
+ planes[0].m.userptr = b->m.userptr;
+ planes[0].length = b->length;
+ }
+
+ if (b->memory == VB2_MEMORY_DMABUF) {
+ planes[0].m.fd = b->m.fd;
+ planes[0].length = b->length;
+ }
+
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ if (b->bytesused == 0)
+ vb2_warn_zero_bytesused(vb);
+
+ if (vb->vb2_queue->allow_zero_bytesused)
+ planes[0].bytesused = b->bytesused;
+ else
+ planes[0].bytesused = b->bytesused ?
+ b->bytesused : planes[0].length;
+ } else
+ planes[0].bytesused = 0;
+
+ }
+
+ /* Zero flags that the vb2 core handles */
+ vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
+ if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
+ V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
+ /*
+ * Non-COPY timestamps and non-OUTPUT queues will get
+ * their timestamp and timestamp source flags from the
+ * queue.
+ */
+ vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ }
+
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ /*
+ * For output buffers mask out the timecode flag:
+ * this will be handled later in vb2_internal_qbuf().
+ * The 'field' is valid metadata for this output buffer
+ * and so that needs to be copied here.
+ */
+ vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
+ vbuf->field = b->field;
+ } else {
+ /* Zero any output buffer flags as this is a capture buffer */
+ vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
+ }
+
+ return 0;
+}
+
+static const struct vb2_buf_ops v4l2_buf_ops = {
+ .fill_user_buffer = __fill_v4l2_buffer,
+ .fill_vb2_buffer = __fill_vb2_buffer,
+ .set_timestamp = __set_timestamp,
+};
+
+/**
+ * vb2_querybuf() - query video buffer information
+ * @q: videobuf queue
+ * @b: buffer struct passed from userspace to vidioc_querybuf handler
+ * in driver
+ *
+ * Should be called from vidioc_querybuf ioctl handler in driver.
+ * This function will verify the passed v4l2_buffer structure and fill the
+ * relevant information for the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_querybuf handler in driver.
+ */
+int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ struct vb2_buffer *vb;
+ int ret;
+
+ if (b->type != q->type) {
+ dprintk(1, "wrong buffer type\n");
+ return -EINVAL;
+ }
+
+ if (b->index >= q->num_buffers) {
+ dprintk(1, "buffer index out of range\n");
+ return -EINVAL;
+ }
+ vb = q->bufs[b->index];
+ ret = __verify_planes_array(vb, b);
+
+ return ret ? ret : vb2_core_querybuf(q, b->index, b);
+}
+EXPORT_SYMBOL(vb2_querybuf);
+
+/**
+ * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
+ * the memory and type values.
+ * @q: videobuf2 queue
+ * @req: struct passed from userspace to vidioc_reqbufs handler
+ * in driver
+ */
+int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+{
+ int ret = vb2_verify_memory_type(q, req->memory, req->type);
+
+ return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
+}
+EXPORT_SYMBOL_GPL(vb2_reqbufs);
+
+/**
+ * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * @q: videobuf2 queue
+ * @b: buffer structure passed from userspace to vidioc_prepare_buf
+ * handler in driver
+ *
+ * Should be called from vidioc_prepare_buf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_prepare callback in the driver (if provided), in which
+ * driver-specific buffer initialization can be performed,
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_prepare_buf handler in driver.
+ */
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ int ret;
+
+ if (vb2_fileio_is_active(q)) {
+ dprintk(1, "file io in progress\n");
+ return -EBUSY;
+ }
+
+ ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
+
+ return ret ? ret : vb2_core_prepare_buf(q, b->index, b);
+}
+EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+
+/**
+ * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
+ * the memory and type values.
+ * @q: videobuf2 queue
+ * @create: creation parameters, passed from userspace to vidioc_create_bufs
+ * handler in driver
+ */
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+{
+ int ret = vb2_verify_memory_type(q, create->memory,
+ create->format.type);
+
+ create->index = q->num_buffers;
+ if (create->count == 0)
+ return ret != -EBUSY ? ret : 0;
+ return ret ? ret : vb2_core_create_bufs(q, create->memory,
+ &create->count, &create->format);
+}
+EXPORT_SYMBOL_GPL(vb2_create_bufs);
+
+static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
+
+ return ret ? ret : vb2_core_qbuf(q, b->index, b);
+}
+
+/**
+ * vb2_qbuf() - Queue a buffer from userspace
+ * @q: videobuf2 queue
+ * @b: buffer structure passed from userspace to vidioc_qbuf handler
+ * in driver
+ *
+ * Should be called from vidioc_qbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
+ * which driver-specific buffer initialization can be performed,
+ * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
+ * callback for processing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_qbuf handler in driver.
+ */
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ if (vb2_fileio_is_active(q)) {
+ dprintk(1, "file io in progress\n");
+ return -EBUSY;
+ }
+
+ return vb2_internal_qbuf(q, b);
+}
+EXPORT_SYMBOL_GPL(vb2_qbuf);
+
+static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
+ bool nonblocking)
+{
+ int ret;
+
+ if (b->type != q->type) {
+ dprintk(1, "invalid buffer type\n");
+ return -EINVAL;
+ }
+
+ ret = vb2_core_dqbuf(q, b, nonblocking);
+
+ if (!ret && !q->is_output &&
+ b->flags & V4L2_BUF_FLAG_LAST)
+ q->last_buffer_dequeued = true;
+
+ return ret;
+}
+
+/**
+ * vb2_dqbuf() - Dequeue a buffer to the userspace
+ * @q: videobuf2 queue
+ * @b: buffer structure passed from userspace to vidioc_dqbuf handler
+ * in driver
+ * @nonblocking: if true, this call will not sleep waiting for a buffer if no
+ * buffers ready for dequeuing are present. Normally the driver
+ * would be passing (file->f_flags & O_NONBLOCK) here
+ *
+ * Should be called from vidioc_dqbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_finish callback in the driver (if provided), in which
+ * driver can perform any additional operations that may be required before
+ * returning the buffer to userspace, such as cache sync,
+ * 3) the buffer struct members are filled with relevant information for
+ * the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_dqbuf handler in driver.
+ */
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+{
+ if (vb2_fileio_is_active(q)) {
+ dprintk(1, "file io in progress\n");
+ return -EBUSY;
+ }
+ return vb2_internal_dqbuf(q, b, nonblocking);
+}
+EXPORT_SYMBOL_GPL(vb2_dqbuf);
+
+/**
+ * vb2_streamon - start streaming
+ * @q: videobuf2 queue
+ * @type: type argument passed from userspace to vidioc_streamon handler
+ *
+ * Should be called from vidioc_streamon handler of a driver.
+ * This function:
+ * 1) verifies current state
+ * 2) passes any previously queued buffers to the driver and starts streaming
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamon handler in the driver.
+ */
+int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+ if (vb2_fileio_is_active(q)) {
+ dprintk(1, "file io in progress\n");
+ return -EBUSY;
+ }
+ return vb2_core_streamon(q, type);
+}
+EXPORT_SYMBOL_GPL(vb2_streamon);
+
+/**
+ * vb2_streamoff - stop streaming
+ * @q: videobuf2 queue
+ * @type: type argument passed from userspace to vidioc_streamoff handler
+ *
+ * Should be called from vidioc_streamoff handler of a driver.
+ * This function:
+ * 1) verifies current state,
+ * 2) stop streaming and dequeues any queued buffers, including those previously
+ * passed to the driver (after waiting for the driver to finish).
+ *
+ * This call can be used for pausing playback.
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamoff handler in the driver
+ */
+int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+ if (vb2_fileio_is_active(q)) {
+ dprintk(1, "file io in progress\n");
+ return -EBUSY;
+ }
+ return vb2_core_streamoff(q, type);
+}
+EXPORT_SYMBOL_GPL(vb2_streamoff);
+
+/**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q: videobuf2 queue
+ * @eb: export buffer structure passed from userspace to vidioc_expbuf
+ * handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+ return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
+ eb->plane, eb->flags);
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
+/**
+ * vb2_queue_init() - initialize a videobuf2 queue
+ * @q: videobuf2 queue; this structure should be allocated in driver
+ *
+ * The vb2_queue structure should be allocated by the driver. The driver is
+ * responsible of clearing it's content and setting initial values for some
+ * required entries before calling this function.
+ * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
+ * to the struct vb2_queue description in include/media/videobuf2-core.h
+ * for more information.
+ */
+int vb2_queue_init(struct vb2_queue *q)
+{
+ /*
+ * Sanity check
+ */
+ if (WARN_ON(!q) ||
+ WARN_ON(q->timestamp_flags &
+ ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
+ V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+ return -EINVAL;
+
+ /* Warn that the driver should choose an appropriate timestamp type */
+ WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+ V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
+
+ /* Warn that vb2_memory should match with v4l2_memory */
+ if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
+ || WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
+ || WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
+ return -EINVAL;
+
+ if (q->buf_struct_size == 0)
+ q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
+
+ q->buf_ops = &v4l2_buf_ops;
+ q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
+ q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
+
+ return vb2_core_queue_init(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_init);
+
+static int __vb2_init_fileio(struct vb2_queue *q, int read);
+static int __vb2_cleanup_fileio(struct vb2_queue *q);
+
+/**
+ * vb2_queue_release() - stop streaming, release the queue and free memory
+ * @q: videobuf2 queue
+ *
+ * This function stops streaming and performs necessary clean ups, including
+ * freeing video buffer memory. The driver is responsible for freeing
+ * the vb2_queue structure itself.
+ */
+void vb2_queue_release(struct vb2_queue *q)
+{
+ __vb2_cleanup_fileio(q);
+ vb2_core_queue_release(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_release);
+
+/**
+ * vb2_poll() - implements poll userspace operation
+ * @q: videobuf2 queue
+ * @file: file argument passed to the poll file operation handler
+ * @wait: wait argument passed to the poll file operation handler
+ *
+ * This function implements poll file operation handler for a driver.
+ * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
+ * be informed that the file descriptor of a video device is available for
+ * reading.
+ * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
+ * will be reported as available for writing.
+ *
+ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
+ * pending events.
+ *
+ * The return values from this function are intended to be directly returned
+ * from poll handler in driver.
+ */
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
+{
+ struct video_device *vfd = video_devdata(file);
+ unsigned long req_events = poll_requested_events(wait);
+ struct vb2_buffer *vb = NULL;
+ unsigned int res = 0;
+ unsigned long flags;
+
+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+ struct v4l2_fh *fh = file->private_data;
+
+ if (v4l2_event_pending(fh))
+ res = POLLPRI;
+ else if (req_events & POLLPRI)
+ poll_wait(file, &fh->wait, wait);
+ }
+
+ if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
+ return res;
+ if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
+ return res;
+
+ /*
+ * Start file I/O emulator only if streaming API has not been used yet.
+ */
+ if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
+ if (!q->is_output && (q->io_modes & VB2_READ) &&
+ (req_events & (POLLIN | POLLRDNORM))) {
+ if (__vb2_init_fileio(q, 1))
+ return res | POLLERR;
+ }
+ if (q->is_output && (q->io_modes & VB2_WRITE) &&
+ (req_events & (POLLOUT | POLLWRNORM))) {
+ if (__vb2_init_fileio(q, 0))
+ return res | POLLERR;
+ /*
+ * Write to OUTPUT queue can be done immediately.
+ */
+ return res | POLLOUT | POLLWRNORM;
+ }
+ }
+
+ /*
+ * There is nothing to wait for if the queue isn't streaming, or if the
+ * error flag is set.
+ */
+ if (!vb2_is_streaming(q) || q->error)
+ return res | POLLERR;
+ /*
+ * For compatibility with vb1: if QBUF hasn't been called yet, then
+ * return POLLERR as well. This only affects capture queues, output
+ * queues will always initialize waiting_for_buffers to false.
+ */
+ if (q->waiting_for_buffers)
+ return res | POLLERR;
+
+ /*
+ * For output streams you can write as long as there are fewer buffers
+ * queued than there are buffers available.
+ */
+ if (q->is_output && q->queued_count < q->num_buffers)
+ return res | POLLOUT | POLLWRNORM;
+
+ if (list_empty(&q->done_list)) {
+ /*
+ * If the last buffer was dequeued from a capture queue,
+ * return immediately. DQBUF will return -EPIPE.
+ */
+ if (q->last_buffer_dequeued)
+ return res | POLLIN | POLLRDNORM;
+
+ poll_wait(file, &q->done_wq, wait);
+ }
+
+ /*
+ * Take first buffer available for dequeuing.
+ */
+ spin_lock_irqsave(&q->done_lock, flags);
+ if (!list_empty(&q->done_list))
+ vb = list_first_entry(&q->done_list, struct vb2_buffer,
+ done_entry);
+ spin_unlock_irqrestore(&q->done_lock, flags);
+
+ if (vb && (vb->state == VB2_BUF_STATE_DONE
+ || vb->state == VB2_BUF_STATE_ERROR)) {
+ return (q->is_output) ?
+ res | POLLOUT | POLLWRNORM :
+ res | POLLIN | POLLRDNORM;
+ }
+ return res;
+}
+EXPORT_SYMBOL_GPL(vb2_poll);
+
+/**
+ * struct vb2_fileio_buf - buffer context used by file io emulator
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. This structure is used for
+ * tracking context related to the buffers.
+ */
+struct vb2_fileio_buf {
+ void *vaddr;
+ unsigned int size;
+ unsigned int pos;
+ unsigned int queued:1;
+};
+
+/**
+ * struct vb2_fileio_data - queue context used by file io emulator
+ *
+ * @cur_index: the index of the buffer currently being read from or
+ * written to. If equal to q->num_buffers then a new buffer
+ * must be dequeued.
+ * @initial_index: in the read() case all buffers are queued up immediately
+ * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
+ * buffers. However, in the write() case no buffers are initially
+ * queued, instead whenever a buffer is full it is queued up by
+ * __vb2_perform_fileio(). Only once all available buffers have
+ * been queued up will __vb2_perform_fileio() start to dequeue
+ * buffers. This means that initially __vb2_perform_fileio()
+ * needs to know what buffer index to use when it is queuing up
+ * the buffers for the first time. That initial index is stored
+ * in this field. Once it is equal to q->num_buffers all
+ * available buffers have been queued and __vb2_perform_fileio()
+ * should start the normal dequeue/queue cycle.
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. For proper operation it required
+ * this structure to save the driver state between each call of the read
+ * or write function.
+ */
+struct vb2_fileio_data {
+ struct v4l2_requestbuffers req;
+ struct v4l2_plane p;
+ struct v4l2_buffer b;
+ struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
+ unsigned int cur_index;
+ unsigned int initial_index;
+ unsigned int q_count;
+ unsigned int dq_count;
+ unsigned read_once:1;
+ unsigned write_immediately:1;
+};
+
+/**
+ * __vb2_init_fileio() - initialize file io emulator
+ * @q: videobuf2 queue
+ * @read: mode selector (1 means read, 0 means write)
+ */
+static int __vb2_init_fileio(struct vb2_queue *q, int read)
+{
+ struct vb2_fileio_data *fileio;
+ int i, ret;
+ unsigned int count = 0;
+
+ /*
+ * Sanity check
+ */
+ if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
+ (!read && !(q->io_modes & VB2_WRITE))))
+ return -EINVAL;
+
+ /*
+ * Check if device supports mapping buffers to kernel virtual space.
+ */
+ if (!q->mem_ops->vaddr)
+ return -EBUSY;
+
+ /*
+ * Check if streaming api has not been already activated.
+ */
+ if (q->streaming || q->num_buffers > 0)
+ return -EBUSY;
+
+ /*
+ * Start with count 1, driver can increase it in queue_setup()
+ */
+ count = 1;
+
+ dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
+ (read) ? "read" : "write", count, q->fileio_read_once,
+ q->fileio_write_immediately);
+
+ fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
+ if (fileio == NULL)
+ return -ENOMEM;
+
+ fileio->read_once = q->fileio_read_once;
+ fileio->write_immediately = q->fileio_write_immediately;
+
+ /*
+ * Request buffers and use MMAP type to force driver
+ * to allocate buffers by itself.
+ */
+ fileio->req.count = count;
+ fileio->req.memory = VB2_MEMORY_MMAP;
+ fileio->req.type = q->type;
+ q->fileio = fileio;
+ ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+ if (ret)
+ goto err_kfree;
+
+ /*
+ * Check if plane_count is correct
+ * (multiplane buffers are not supported).
+ */
+ if (q->bufs[0]->num_planes != 1) {
+ ret = -EBUSY;
+ goto err_reqbufs;
+ }
+
+ /*
+ * Get kernel address of each buffer.
+ */
+ for (i = 0; i < q->num_buffers; i++) {
+ fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+ if (fileio->bufs[i].vaddr == NULL) {
+ ret = -EINVAL;
+ goto err_reqbufs;
+ }
+ fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+ }
+
+ /*
+ * Read mode requires pre queuing of all buffers.
+ */
+ if (read) {
+ bool is_multiplanar = q->is_multiplanar;
+
+ /*
+ * Queue all buffers.
+ */
+ for (i = 0; i < q->num_buffers; i++) {
+ struct v4l2_buffer *b = &fileio->b;
+
+ memset(b, 0, sizeof(*b));
+ b->type = q->type;
+ if (is_multiplanar) {
+ memset(&fileio->p, 0, sizeof(fileio->p));
+ b->m.planes = &fileio->p;
+ b->length = 1;
+ }
+ b->memory = q->memory;
+ b->index = i;
+ ret = vb2_internal_qbuf(q, b);
+ if (ret)
+ goto err_reqbufs;
+ fileio->bufs[i].queued = 1;
+ }
+ /*
+ * All buffers have been queued, so mark that by setting
+ * initial_index to q->num_buffers
+ */
+ fileio->initial_index = q->num_buffers;
+ fileio->cur_index = q->num_buffers;
+ }
+
+ /*
+ * Start streaming.
+ */
+ ret = vb2_core_streamon(q, q->type);
+ if (ret)
+ goto err_reqbufs;
+
+ return ret;
+
+err_reqbufs:
+ fileio->req.count = 0;
+ vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+
+err_kfree:
+ q->fileio = NULL;
+ kfree(fileio);
+ return ret;
+}
+
+/**
+ * __vb2_cleanup_fileio() - free resourced used by file io emulator
+ * @q: videobuf2 queue
+ */
+static int __vb2_cleanup_fileio(struct vb2_queue *q)
+{
+ struct vb2_fileio_data *fileio = q->fileio;
+
+ if (fileio) {
+ vb2_core_streamoff(q, q->type);
+ q->fileio = NULL;
+ fileio->req.count = 0;
+ vb2_reqbufs(q, &fileio->req);
+ kfree(fileio);
+ dprintk(3, "file io emulator closed\n");
+ }
+ return 0;
+}
+
+/**
+ * __vb2_perform_fileio() - perform a single file io (read or write) operation
+ * @q: videobuf2 queue
+ * @data: pointed to target userspace buffer
+ * @count: number of bytes to read or write
+ * @ppos: file handle position tracking pointer
+ * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
+ * @read: access mode selector (1 means read, 0 means write)
+ */
+static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblock, int read)
+{
+ struct vb2_fileio_data *fileio;
+ struct vb2_fileio_buf *buf;
+ bool is_multiplanar = q->is_multiplanar;
+ /*
+ * When using write() to write data to an output video node the vb2 core
+ * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
+ * else is able to provide this information with the write() operation.
+ */
+ bool set_timestamp = !read &&
+ (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+ V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ int ret, index;
+
+ dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
+ read ? "read" : "write", (long)*ppos, count,
+ nonblock ? "non" : "");
+
+ if (!data)
+ return -EINVAL;
+
+ /*
+ * Initialize emulator on first call.
+ */
+ if (!vb2_fileio_is_active(q)) {
+ ret = __vb2_init_fileio(q, read);
+ dprintk(3, "vb2_init_fileio result: %d\n", ret);
+ if (ret)
+ return ret;
+ }
+ fileio = q->fileio;
+
+ /*
+ * Check if we need to dequeue the buffer.
+ */
+ index = fileio->cur_index;
+ if (index >= q->num_buffers) {
+ /*
+ * Call vb2_dqbuf to get buffer back.
+ */
+ memset(&fileio->b, 0, sizeof(fileio->b));
+ fileio->b.type = q->type;
+ fileio->b.memory = q->memory;
+ if (is_multiplanar) {
+ memset(&fileio->p, 0, sizeof(fileio->p));
+ fileio->b.m.planes = &fileio->p;
+ fileio->b.length = 1;
+ }
+ ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
+ dprintk(5, "vb2_dqbuf result: %d\n", ret);
+ if (ret)
+ return ret;
+ fileio->dq_count += 1;
+
+ fileio->cur_index = index = fileio->b.index;
+ buf = &fileio->bufs[index];
+
+ /*
+ * Get number of bytes filled by the driver
+ */
+ buf->pos = 0;
+ buf->queued = 0;
+ buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
+ : vb2_plane_size(q->bufs[index], 0);
+ /* Compensate for data_offset on read in the multiplanar case. */
+ if (is_multiplanar && read &&
+ fileio->b.m.planes[0].data_offset < buf->size) {
+ buf->pos = fileio->b.m.planes[0].data_offset;
+ buf->size -= buf->pos;
+ }
+ } else {
+ buf = &fileio->bufs[index];
+ }
+
+ /*
+ * Limit count on last few bytes of the buffer.
+ */
+ if (buf->pos + count > buf->size) {
+ count = buf->size - buf->pos;
+ dprintk(5, "reducing read count: %zd\n", count);
+ }
+
+ /*
+ * Transfer data to userspace.
+ */
+ dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
+ count, index, buf->pos);
+ if (read)
+ ret = copy_to_user(data, buf->vaddr + buf->pos, count);
+ else
+ ret = copy_from_user(buf->vaddr + buf->pos, data, count);
+ if (ret) {
+ dprintk(3, "error copying data\n");
+ return -EFAULT;
+ }
+
+ /*
+ * Update counters.
+ */
+ buf->pos += count;
+ *ppos += count;
+
+ /*
+ * Queue next buffer if required.
+ */
+ if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
+ /*
+ * Check if this is the last buffer to read.
+ */
+ if (read && fileio->read_once && fileio->dq_count == 1) {
+ dprintk(3, "read limit reached\n");
+ return __vb2_cleanup_fileio(q);
+ }
+
+ /*
+ * Call vb2_qbuf and give buffer to the driver.
+ */
+ memset(&fileio->b, 0, sizeof(fileio->b));
+ fileio->b.type = q->type;
+ fileio->b.memory = q->memory;
+ fileio->b.index = index;
+ fileio->b.bytesused = buf->pos;
+ if (is_multiplanar) {
+ memset(&fileio->p, 0, sizeof(fileio->p));
+ fileio->p.bytesused = buf->pos;
+ fileio->b.m.planes = &fileio->p;
+ fileio->b.length = 1;
+ }
+ if (set_timestamp)
+ v4l2_get_timestamp(&fileio->b.timestamp);
+ ret = vb2_internal_qbuf(q, &fileio->b);
+ dprintk(5, "vb2_dbuf result: %d\n", ret);
+ if (ret)
+ return ret;
+
+ /*
+ * Buffer has been queued, update the status
+ */
+ buf->pos = 0;
+ buf->queued = 1;
+ buf->size = vb2_plane_size(q->bufs[index], 0);
+ fileio->q_count += 1;
+ /*
+ * If we are queuing up buffers for the first time, then
+ * increase initial_index by one.
+ */
+ if (fileio->initial_index < q->num_buffers)
+ fileio->initial_index++;
+ /*
+ * The next buffer to use is either a buffer that's going to be
+ * queued for the first time (initial_index < q->num_buffers)
+ * or it is equal to q->num_buffers, meaning that the next
+ * time we need to dequeue a buffer since we've now queued up
+ * all the 'first time' buffers.
+ */
+ fileio->cur_index = fileio->initial_index;
+ }
+
+ /*
+ * Return proper number of bytes processed.
+ */
+ if (ret == 0)
+ ret = count;
+ return ret;
+}
+
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblocking)
+{
+ return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
+}
+EXPORT_SYMBOL_GPL(vb2_read);
+
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+ loff_t *ppos, int nonblocking)
+{
+ return __vb2_perform_fileio(q, (char __user *) data, count,
+ ppos, nonblocking, 0);
+}
+EXPORT_SYMBOL_GPL(vb2_write);
+
+struct vb2_threadio_data {
+ struct task_struct *thread;
+ vb2_thread_fnc fnc;
+ void *priv;
+ bool stop;
+};
+
+static int vb2_thread(void *data)
+{
+ struct vb2_queue *q = data;
+ struct vb2_threadio_data *threadio = q->threadio;
+ struct vb2_fileio_data *fileio = q->fileio;
+ bool set_timestamp = false;
+ int prequeue = 0;
+ int index = 0;
+ int ret = 0;
+
+ if (q->is_output) {
+ prequeue = q->num_buffers;
+ set_timestamp =
+ (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+ V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ }
+
+ set_freezable();
+
+ for (;;) {
+ struct vb2_buffer *vb;
+
+ /*
+ * Call vb2_dqbuf to get buffer back.
+ */
+ memset(&fileio->b, 0, sizeof(fileio->b));
+ fileio->b.type = q->type;
+ fileio->b.memory = q->memory;
+ if (prequeue) {
+ fileio->b.index = index++;
+ prequeue--;
+ } else {
+ call_void_qop(q, wait_finish, q);
+ if (!threadio->stop)
+ ret = vb2_internal_dqbuf(q, &fileio->b, 0);
+ call_void_qop(q, wait_prepare, q);
+ dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
+ }
+ if (ret || threadio->stop)
+ break;
+ try_to_freeze();
+
+ vb = q->bufs[fileio->b.index];
+ if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
+ if (threadio->fnc(vb, threadio->priv))
+ break;
+ call_void_qop(q, wait_finish, q);
+ if (set_timestamp)
+ v4l2_get_timestamp(&fileio->b.timestamp);
+ if (!threadio->stop)
+ ret = vb2_internal_qbuf(q, &fileio->b);
+ call_void_qop(q, wait_prepare, q);
+ if (ret || threadio->stop)
+ break;
+ }
+
+ /* Hmm, linux becomes *very* unhappy without this ... */
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ return 0;
+}
+
+/*
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+ const char *thread_name)
+{
+ struct vb2_threadio_data *threadio;
+ int ret = 0;
+
+ if (q->threadio)
+ return -EBUSY;
+ if (vb2_is_busy(q))
+ return -EBUSY;
+ if (WARN_ON(q->fileio))
+ return -EBUSY;
+
+ threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
+ if (threadio == NULL)
+ return -ENOMEM;
+ threadio->fnc = fnc;
+ threadio->priv = priv;
+
+ ret = __vb2_init_fileio(q, !q->is_output);
+ dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
+ if (ret)
+ goto nomem;
+ q->threadio = threadio;
+ threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
+ if (IS_ERR(threadio->thread)) {
+ ret = PTR_ERR(threadio->thread);
+ threadio->thread = NULL;
+ goto nothread;
+ }
+ return 0;
+
+nothread:
+ __vb2_cleanup_fileio(q);
+nomem:
+ kfree(threadio);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_start);
+
+int vb2_thread_stop(struct vb2_queue *q)
+{
+ struct vb2_threadio_data *threadio = q->threadio;
+ int err;
+
+ if (threadio == NULL)
+ return 0;
+ threadio->stop = true;
+ /* Wake up all pending sleeps in the thread */
+ vb2_queue_error(q);
+ err = kthread_stop(threadio->thread);
+ __vb2_cleanup_fileio(q);
+ threadio->thread = NULL;
+ kfree(threadio);
+ q->threadio = NULL;
+ return err;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_stop);
+
+/*
+ * The following functions are not part of the vb2 core API, but are helper
+ * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
+ * and struct vb2_ops.
+ * They contain boilerplate code that most if not all drivers have to do
+ * and so they simplify the driver code.
+ */
+
+/* The queue is busy if there is a owner and you are not that owner. */
+static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
+{
+ return vdev->queue->owner && vdev->queue->owner != file->private_data;
+}
+
+/* vb2 ioctl helpers */
+
+int vb2_ioctl_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *p)
+{
+ struct video_device *vdev = video_devdata(file);
+ int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
+
+ if (res)
+ return res;
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
+ /* If count == 0, then the owner has released all buffers and he
+ is no longer owner of the queue. Otherwise we have a new owner. */
+ if (res == 0)
+ vdev->queue->owner = p->count ? file->private_data : NULL;
+ return res;
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
+
+int vb2_ioctl_create_bufs(struct file *file, void *priv,
+ struct v4l2_create_buffers *p)
+{
+ struct video_device *vdev = video_devdata(file);
+ int res = vb2_verify_memory_type(vdev->queue, p->memory,
+ p->format.type);
+
+ p->index = vdev->queue->num_buffers;
+ /*
+ * If count == 0, then just check if memory and type are valid.
+ * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
+ */
+ if (p->count == 0)
+ return res != -EBUSY ? res : 0;
+ if (res)
+ return res;
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ res = vb2_core_create_bufs(vdev->queue, p->memory, &p->count,
+ &p->format);
+ if (res == 0)
+ vdev->queue->owner = file->private_data;
+ return res;
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
+
+int vb2_ioctl_prepare_buf(struct file *file, void *priv,
+ struct v4l2_buffer *p)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ return vb2_prepare_buf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
+
+int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ /* No need to call vb2_queue_is_busy(), anyone can query buffers. */
+ return vb2_querybuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
+
+int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ return vb2_qbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
+
+int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
+
+int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ return vb2_streamon(vdev->queue, i);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
+
+int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ return vb2_streamoff(vdev->queue, i);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
+
+int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (vb2_queue_is_busy(vdev, file))
+ return -EBUSY;
+ return vb2_expbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
+
+/* v4l2_file_operations helpers */
+
+int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ return vb2_mmap(vdev->queue, vma);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_mmap);
+
+int _vb2_fop_release(struct file *file, struct mutex *lock)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ if (lock)
+ mutex_lock(lock);
+ if (file->private_data == vdev->queue->owner) {
+ vb2_queue_release(vdev->queue);
+ vdev->queue->owner = NULL;
+ }
+ if (lock)
+ mutex_unlock(lock);
+ return v4l2_fh_release(file);
+}
+EXPORT_SYMBOL_GPL(_vb2_fop_release);
+
+int vb2_fop_release(struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+
+ return _vb2_fop_release(file, lock);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_release);
+
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+ int err = -EBUSY;
+
+ if (!(vdev->queue->io_modes & VB2_WRITE))
+ return -EINVAL;
+ if (lock && mutex_lock_interruptible(lock))
+ return -ERESTARTSYS;
+ if (vb2_queue_is_busy(vdev, file))
+ goto exit;
+ err = vb2_write(vdev->queue, buf, count, ppos,
+ file->f_flags & O_NONBLOCK);
+ if (vdev->queue->fileio)
+ vdev->queue->owner = file->private_data;
+exit:
+ if (lock)
+ mutex_unlock(lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_write);
+
+ssize_t vb2_fop_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+ int err = -EBUSY;
+
+ if (!(vdev->queue->io_modes & VB2_READ))
+ return -EINVAL;
+ if (lock && mutex_lock_interruptible(lock))
+ return -ERESTARTSYS;
+ if (vb2_queue_is_busy(vdev, file))
+ goto exit;
+ err = vb2_read(vdev->queue, buf, count, ppos,
+ file->f_flags & O_NONBLOCK);
+ if (vdev->queue->fileio)
+ vdev->queue->owner = file->private_data;
+exit:
+ if (lock)
+ mutex_unlock(lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_read);
+
+unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct vb2_queue *q = vdev->queue;
+ struct mutex *lock = q->lock ? q->lock : vdev->lock;
+ unsigned res;
+ void *fileio;
+
+ /*
+ * If this helper doesn't know how to lock, then you shouldn't be using
+ * it but you should write your own.
+ */
+ WARN_ON(!lock);
+
+ if (lock && mutex_lock_interruptible(lock))
+ return POLLERR;
+
+ fileio = q->fileio;
+
+ res = vb2_poll(vdev->queue, file, wait);
+
+ /* If fileio was started, then we have a new queue owner. */
+ if (!fileio && q->fileio)
+ q->owner = file->private_data;
+ if (lock)
+ mutex_unlock(lock);
+ return res;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_poll);
+
+#ifndef CONFIG_MMU
+unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
+#endif
+
+/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
+
+void vb2_ops_wait_prepare(struct vb2_queue *vq)
+{
+ mutex_unlock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
+
+void vb2_ops_wait_finish(struct vb2_queue *vq)
+{
+ mutex_lock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+
+MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
+MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index ecb8f0c7f025..1c302743a1fd 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -17,7 +17,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <media/videobuf2-memops.h>
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c6a644b22af4..6f3154613dc7 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -58,12 +58,18 @@ config OMAP_GPMC
memory drives like NOR, NAND, OneNAND, SRAM.
config OMAP_GPMC_DEBUG
- bool
+ bool "Enable GPMC debug output and skip reset of GPMC during init"
depends on OMAP_GPMC
help
Enables verbose debugging mostly to decode the bootloader provided
- timings. Enable this during development to configure devices
- connected to the GPMC bus.
+ timings. To preserve the bootloader provided timings, the reset
+ of GPMC is skipped during init. Enable this during development to
+ configure devices connected to the GPMC bus.
+
+ NOTE: In addition to matching the register setup with the bootloader
+ you also need to match the GPMC FCLK frequency used by the
+ bootloader or else the GPMC timings won't be identical with the
+ bootloader timings.
config MVEBU_DEVBUS
bool "Marvell EBU Device Bus Controller"
diff --git a/drivers/memory/fsl-corenet-cf.c b/drivers/memory/fsl-corenet-cf.c
index d708ded5457b..662d050243be 100644
--- a/drivers/memory/fsl-corenet-cf.c
+++ b/drivers/memory/fsl-corenet-cf.c
@@ -61,6 +61,7 @@ static const struct of_device_id ccf_matches[] = {
},
{}
};
+MODULE_DEVICE_TABLE(of, ccf_matches);
struct ccf_err_regs {
u32 errdet; /* 0x00 Error Detect Register */
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 32ac049f2bc4..6515dfc2b805 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -696,7 +696,6 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
int div;
u32 l;
- gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings");
div = gpmc_calc_divider(t->sync_clk);
if (div < 0)
return div;
@@ -1988,6 +1987,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
if (ret < 0)
goto err;
+ gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
ret = gpmc_cs_program_settings(cs, &gpmc_s);
if (ret < 0)
goto err;
diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c
index b2ef6072fbf4..ff57195b4e37 100644
--- a/drivers/memory/pl172.c
+++ b/drivers/memory/pl172.c
@@ -118,7 +118,8 @@ static int pl172_setup_static(struct amba_device *adev,
if (of_property_read_bool(np, "mpmc,extended-wait"))
cfg |= MPMC_STATIC_CFG_EW;
- if (of_property_read_bool(np, "mpmc,buffer-enable"))
+ if (amba_part(adev) == 0x172 &&
+ of_property_read_bool(np, "mpmc,buffer-enable"))
cfg |= MPMC_STATIC_CFG_B;
if (of_property_read_bool(np, "mpmc,write-protect"))
@@ -190,6 +191,8 @@ static int pl172_parse_cs_config(struct amba_device *adev,
}
static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"};
+static const char * const pl175_revisions[] = {"r1"};
+static const char * const pl176_revisions[] = {"r0"};
static int pl172_probe(struct amba_device *adev, const struct amba_id *id)
{
@@ -202,6 +205,12 @@ static int pl172_probe(struct amba_device *adev, const struct amba_id *id)
if (amba_part(adev) == 0x172) {
if (amba_rev(adev) < ARRAY_SIZE(pl172_revisions))
rev = pl172_revisions[amba_rev(adev)];
+ } else if (amba_part(adev) == 0x175) {
+ if (amba_rev(adev) < ARRAY_SIZE(pl175_revisions))
+ rev = pl175_revisions[amba_rev(adev)];
+ } else if (amba_part(adev) == 0x176) {
+ if (amba_rev(adev) < ARRAY_SIZE(pl176_revisions))
+ rev = pl176_revisions[amba_rev(adev)];
}
dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev);
@@ -278,9 +287,20 @@ static int pl172_remove(struct amba_device *adev)
}
static const struct amba_id pl172_ids[] = {
+ /* PrimeCell MPMC PL172, EMC found on NXP LPC18xx and LPC43xx */
{
- .id = 0x07341172,
- .mask = 0xffffffff,
+ .id = 0x07041172,
+ .mask = 0x3f0fffff,
+ },
+ /* PrimeCell MPMC PL175, EMC found on NXP LPC32xx */
+ {
+ .id = 0x07041175,
+ .mask = 0x3f0fffff,
+ },
+ /* PrimeCell MPMC PL176 */
+ {
+ .id = 0x89041176,
+ .mask = 0xff0fffff,
},
{ 0, 0 },
};
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
index ca7d97a9a9ba..a579a0f25840 100644
--- a/drivers/memory/ti-aemif.c
+++ b/drivers/memory/ti-aemif.c
@@ -324,6 +324,7 @@ static const struct of_device_id aemif_of_match[] = {
{ .compatible = "ti,da850-aemif", },
{},
};
+MODULE_DEVICE_TABLE(of, aemif_of_match);
static int aemif_probe(struct platform_device *pdev)
{
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index fc7393729081..02b5f69e1a42 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -1038,6 +1038,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
int i, buflist_ent;
int sg_spill = MAX_FRAGS_SPILL1;
int dir;
+
+ if (bytes < 0)
+ return NULL;
+
/* initialization */
*frags = 0;
*blp = NULL;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 005a88b9f440..7ebccfa8072a 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1994,7 +1994,6 @@ static struct scsi_host_template mptsas_driver_template = {
.cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = mptscsih_host_attrs,
- .use_blk_tags = 1,
};
static int mptsas_get_linkerrors(struct sas_phy *phy)
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
index 5e72f65ef94c..63445ea6b0bf 100644
--- a/drivers/mfd/88pm80x.c
+++ b/drivers/mfd/88pm80x.c
@@ -33,6 +33,8 @@ static struct pm80x_chip_mapping chip_mapping[] = {
{0x3, CHIP_PM800},
/* 88PM805 chip id number */
{0x0, CHIP_PM805},
+ /* 88PM860 chip id number */
+ {0x4, CHIP_PM860},
};
/*
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 99d63675f073..4d92df6ef9fe 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
additional drivers must be enabled in order to use the
functionality of the device.
+config MFD_ATMEL_FLEXCOM
+ tristate "Atmel Flexcom (Flexible Serial Communication Unit)"
+ select MFD_CORE
+ depends on OF
+ help
+ Select this to get support for Atmel Flexcom. This is a wrapper
+ which embeds a SPI controller, a I2C controller and a USART. Only
+ one function can be used at a time. The choice is done at boot time
+ by the probe function of this MFD driver according to a device tree
+ property.
+
config MFD_ATMEL_HLCDC
tristate "Atmel HLCDC (High-end LCD Controller)"
select MFD_CORE
@@ -725,9 +736,10 @@ config MFD_RTSX_PCI
select MFD_CORE
help
This supports for Realtek PCI-Express card reader including rts5209,
- rts5229, rtl8411, etc. Realtek card reader supports access to many
- types of memory cards, such as Memory Stick, Memory Stick Pro,
- Secure Digital and MultiMediaCard.
+ rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
+ Realtek card reader supports access to many types of memory cards,
+ such as Memory Stick, Memory Stick Pro, Secure Digital and
+ MultiMediaCard.
config MFD_RT5033
tristate "Richtek RT5033 Power Management IC"
@@ -1059,6 +1071,7 @@ config MFD_PALMAS
config TPS6105X
tristate "TI TPS61050/61052 Boost Converters"
depends on I2C
+ select REGMAP_I2C
select REGULATOR
select MFD_CORE
select REGULATOR_FIXED_VOLTAGE
@@ -1471,7 +1484,7 @@ config MFD_WM8994
config MFD_STW481X
tristate "Support for ST Microelectronics STw481x"
- depends on I2C && ARCH_NOMADIK
+ depends on I2C && (ARCH_NOMADIK || COMPILE_TEST)
select REGMAP_I2C
select MFD_CORE
help
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a59e3fcc8626..a8b76b81b467 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o
obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o
obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o
obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
@@ -190,5 +191,6 @@ obj-$(CONFIG_MFD_RT5033) += rt5033.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 44cfdbb295db..d474732cc65c 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -24,6 +24,7 @@
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
#include <linux/slab.h>
+#include <linux/platform_device.h>
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/registers.h>
@@ -69,8 +70,6 @@ EXPORT_SYMBOL_GPL(arizona_clk32k_enable);
int arizona_clk32k_disable(struct arizona *arizona)
{
- int ret = 0;
-
mutex_lock(&arizona->clk_lock);
BUG_ON(arizona->clk32k_ref <= 0);
@@ -90,7 +89,7 @@ int arizona_clk32k_disable(struct arizona *arizona)
mutex_unlock(&arizona->clk_lock);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(arizona_clk32k_disable);
@@ -462,6 +461,50 @@ static int wm5102_clear_write_sequencer(struct arizona *arizona)
}
#ifdef CONFIG_PM
+static int arizona_isolate_dcvdd(struct arizona *arizona)
+{
+ int ret;
+
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_ISOLATION_CONTROL,
+ ARIZONA_ISOLATE_DCVDD1,
+ ARIZONA_ISOLATE_DCVDD1);
+ if (ret != 0)
+ dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", ret);
+
+ return ret;
+}
+
+static int arizona_connect_dcvdd(struct arizona *arizona)
+{
+ int ret;
+
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_ISOLATION_CONTROL,
+ ARIZONA_ISOLATE_DCVDD1, 0);
+ if (ret != 0)
+ dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret);
+
+ return ret;
+}
+
+static int arizona_is_jack_det_active(struct arizona *arizona)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to check jack det status: %d\n", ret);
+ return ret;
+ } else if (val & ARIZONA_JD1_ENA) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
static int arizona_runtime_resume(struct device *dev)
{
struct arizona *arizona = dev_get_drvdata(dev);
@@ -501,14 +544,9 @@ static int arizona_runtime_resume(struct device *dev)
switch (arizona->type) {
case WM5102:
if (arizona->external_dcvdd) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_ISOLATION_CONTROL,
- ARIZONA_ISOLATE_DCVDD1, 0);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Failed to connect DCVDD: %d\n", ret);
+ ret = arizona_connect_dcvdd(arizona);
+ if (ret != 0)
goto err;
- }
}
ret = wm5102_patch(arizona);
@@ -533,14 +571,9 @@ static int arizona_runtime_resume(struct device *dev)
goto err;
if (arizona->external_dcvdd) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_ISOLATION_CONTROL,
- ARIZONA_ISOLATE_DCVDD1, 0);
- if (ret) {
- dev_err(arizona->dev,
- "Failed to connect DCVDD: %d\n", ret);
+ ret = arizona_connect_dcvdd(arizona);
+ if (ret != 0)
goto err;
- }
} else {
/*
* As this is only called for the internal regulator
@@ -571,14 +604,9 @@ static int arizona_runtime_resume(struct device *dev)
goto err;
if (arizona->external_dcvdd) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_ISOLATION_CONTROL,
- ARIZONA_ISOLATE_DCVDD1, 0);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Failed to connect DCVDD: %d\n", ret);
+ ret = arizona_connect_dcvdd(arizona);
+ if (ret != 0)
goto err;
- }
}
break;
}
@@ -600,49 +628,50 @@ err:
static int arizona_runtime_suspend(struct device *dev)
{
struct arizona *arizona = dev_get_drvdata(dev);
- unsigned int val;
+ int jd_active = 0;
int ret;
dev_dbg(arizona->dev, "Entering AoD mode\n");
- ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
- if (ret) {
- dev_err(dev, "Failed to check jack det status: %d\n", ret);
- return ret;
- }
-
- if (arizona->external_dcvdd) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_ISOLATION_CONTROL,
- ARIZONA_ISOLATE_DCVDD1,
- ARIZONA_ISOLATE_DCVDD1);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n",
- ret);
- return ret;
- }
- }
-
switch (arizona->type) {
case WM5110:
case WM8280:
- if (arizona->external_dcvdd)
- break;
+ jd_active = arizona_is_jack_det_active(arizona);
+ if (jd_active < 0)
+ return jd_active;
- /*
- * As this is only called for the internal regulator
- * (where we know voltage ranges available) it is ok
- * to request an exact range.
- */
- ret = regulator_set_voltage(arizona->dcvdd, 1175000, 1175000);
- if (ret < 0) {
- dev_err(arizona->dev,
- "Failed to set suspend voltage: %d\n", ret);
- return ret;
+ if (arizona->external_dcvdd) {
+ ret = arizona_isolate_dcvdd(arizona);
+ if (ret != 0)
+ return ret;
+ } else {
+ /*
+ * As this is only called for the internal regulator
+ * (where we know voltage ranges available) it is ok
+ * to request an exact range.
+ */
+ ret = regulator_set_voltage(arizona->dcvdd,
+ 1175000, 1175000);
+ if (ret < 0) {
+ dev_err(arizona->dev,
+ "Failed to set suspend voltage: %d\n",
+ ret);
+ return ret;
+ }
}
break;
case WM5102:
- if (!(val & ARIZONA_JD1_ENA)) {
+ jd_active = arizona_is_jack_det_active(arizona);
+ if (jd_active < 0)
+ return jd_active;
+
+ if (arizona->external_dcvdd) {
+ ret = arizona_isolate_dcvdd(arizona);
+ if (ret != 0)
+ return ret;
+ }
+
+ if (!jd_active) {
ret = regmap_write(arizona->regmap,
ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0);
if (ret) {
@@ -654,6 +683,15 @@ static int arizona_runtime_suspend(struct device *dev)
}
break;
default:
+ jd_active = arizona_is_jack_det_active(arizona);
+ if (jd_active < 0)
+ return jd_active;
+
+ if (arizona->external_dcvdd) {
+ ret = arizona_isolate_dcvdd(arizona);
+ if (ret != 0)
+ return ret;
+ }
break;
}
@@ -662,7 +700,7 @@ static int arizona_runtime_suspend(struct device *dev)
regulator_disable(arizona->dcvdd);
/* Allow us to completely power down if no jack detection */
- if (!(val & ARIZONA_JD1_ENA)) {
+ if (!jd_active) {
dev_dbg(arizona->dev, "Fully powering off\n");
arizona->has_fully_powered_off = true;
@@ -928,7 +966,8 @@ int arizona_dev_init(struct arizona *arizona)
const char *type_name;
unsigned int reg, val, mask;
int (*apply_patch)(struct arizona *) = NULL;
- int ret, i;
+ const struct mfd_cell *subdevs = NULL;
+ int n_subdevs, ret, i;
dev_set_drvdata(arizona->dev, arizona);
mutex_init(&arizona->clk_lock);
@@ -1089,74 +1128,95 @@ int arizona_dev_init(struct arizona *arizona)
arizona->rev &= ARIZONA_DEVICE_REVISION_MASK;
switch (reg) {
-#ifdef CONFIG_MFD_WM5102
case 0x5102:
- type_name = "WM5102";
- if (arizona->type != WM5102) {
- dev_err(arizona->dev, "WM5102 registered as %d\n",
- arizona->type);
- arizona->type = WM5102;
+ if (IS_ENABLED(CONFIG_MFD_WM5102)) {
+ type_name = "WM5102";
+ if (arizona->type != WM5102) {
+ dev_warn(arizona->dev,
+ "WM5102 registered as %d\n",
+ arizona->type);
+ arizona->type = WM5102;
+ }
+
+ apply_patch = wm5102_patch;
+ arizona->rev &= 0x7;
+ subdevs = wm5102_devs;
+ n_subdevs = ARRAY_SIZE(wm5102_devs);
}
- apply_patch = wm5102_patch;
- arizona->rev &= 0x7;
break;
-#endif
-#ifdef CONFIG_MFD_WM5110
case 0x5110:
- switch (arizona->type) {
- case WM5110:
- type_name = "WM5110";
- break;
- case WM8280:
- type_name = "WM8280";
- break;
- default:
- type_name = "WM5110";
- dev_err(arizona->dev, "WM5110 registered as %d\n",
- arizona->type);
- arizona->type = WM5110;
- break;
+ if (IS_ENABLED(CONFIG_MFD_WM5110)) {
+ switch (arizona->type) {
+ case WM5110:
+ type_name = "WM5110";
+ break;
+ case WM8280:
+ type_name = "WM8280";
+ break;
+ default:
+ type_name = "WM5110";
+ dev_warn(arizona->dev,
+ "WM5110 registered as %d\n",
+ arizona->type);
+ arizona->type = WM5110;
+ break;
+ }
+
+ apply_patch = wm5110_patch;
+ subdevs = wm5110_devs;
+ n_subdevs = ARRAY_SIZE(wm5110_devs);
}
- apply_patch = wm5110_patch;
break;
-#endif
-#ifdef CONFIG_MFD_WM8997
case 0x8997:
- type_name = "WM8997";
- if (arizona->type != WM8997) {
- dev_err(arizona->dev, "WM8997 registered as %d\n",
- arizona->type);
- arizona->type = WM8997;
+ if (IS_ENABLED(CONFIG_MFD_WM8997)) {
+ type_name = "WM8997";
+ if (arizona->type != WM8997) {
+ dev_warn(arizona->dev,
+ "WM8997 registered as %d\n",
+ arizona->type);
+ arizona->type = WM8997;
+ }
+
+ apply_patch = wm8997_patch;
+ subdevs = wm8997_devs;
+ n_subdevs = ARRAY_SIZE(wm8997_devs);
}
- apply_patch = wm8997_patch;
break;
-#endif
-#ifdef CONFIG_MFD_WM8998
case 0x6349:
- switch (arizona->type) {
- case WM8998:
- type_name = "WM8998";
- break;
-
- case WM1814:
- type_name = "WM1814";
- break;
+ if (IS_ENABLED(CONFIG_MFD_WM8998)) {
+ switch (arizona->type) {
+ case WM8998:
+ type_name = "WM8998";
+ break;
+
+ case WM1814:
+ type_name = "WM1814";
+ break;
+
+ default:
+ type_name = "WM8998";
+ dev_warn(arizona->dev,
+ "WM8998 registered as %d\n",
+ arizona->type);
+ arizona->type = WM8998;
+ }
- default:
- type_name = "WM8998";
- dev_err(arizona->dev, "WM8998 registered as %d\n",
- arizona->type);
- arizona->type = WM8998;
+ apply_patch = wm8998_patch;
+ subdevs = wm8998_devs;
+ n_subdevs = ARRAY_SIZE(wm8998_devs);
}
-
- apply_patch = wm8998_patch;
break;
-#endif
default:
dev_err(arizona->dev, "Unknown device ID %x\n", reg);
goto err_reset;
}
+ if (!subdevs) {
+ dev_err(arizona->dev,
+ "No kernel support for device ID %x\n", reg);
+ goto err_reset;
+ }
+
dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A');
if (apply_patch) {
@@ -1342,28 +1402,10 @@ int arizona_dev_init(struct arizona *arizona)
arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked",
arizona_underclocked, arizona);
- switch (arizona->type) {
- case WM5102:
- ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
- ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
- break;
- case WM5110:
- case WM8280:
- ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
- ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
- break;
- case WM8997:
- ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
- ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
- break;
- case WM8998:
- case WM1814:
- ret = mfd_add_devices(arizona->dev, -1, wm8998_devs,
- ARRAY_SIZE(wm8998_devs), NULL, 0, NULL);
- break;
- }
+ ret = mfd_add_devices(arizona->dev, PLATFORM_DEVID_NONE,
+ subdevs, n_subdevs, NULL, 0, NULL);
- if (ret != 0) {
+ if (ret) {
dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret);
goto err_irq;
}
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index cea1b409fa27..4e3afd1861fc 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -27,7 +27,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct arizona *arizona;
- const struct regmap_config *regmap_config;
+ const struct regmap_config *regmap_config = NULL;
unsigned long type;
int ret;
@@ -37,31 +37,32 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
type = id->driver_data;
switch (type) {
-#ifdef CONFIG_MFD_WM5102
case WM5102:
- regmap_config = &wm5102_i2c_regmap;
+ if (IS_ENABLED(CONFIG_MFD_WM5102))
+ regmap_config = &wm5102_i2c_regmap;
break;
-#endif
-#ifdef CONFIG_MFD_WM5110
case WM5110:
case WM8280:
- regmap_config = &wm5110_i2c_regmap;
+ if (IS_ENABLED(CONFIG_MFD_WM5110))
+ regmap_config = &wm5110_i2c_regmap;
break;
-#endif
-#ifdef CONFIG_MFD_WM8997
case WM8997:
- regmap_config = &wm8997_i2c_regmap;
+ if (IS_ENABLED(CONFIG_MFD_WM8997))
+ regmap_config = &wm8997_i2c_regmap;
break;
-#endif
-#ifdef CONFIG_MFD_WM8998
case WM8998:
case WM1814:
- regmap_config = &wm8998_i2c_regmap;
+ if (IS_ENABLED(CONFIG_MFD_WM8998))
+ regmap_config = &wm8998_i2c_regmap;
break;
-#endif
default:
- dev_err(&i2c->dev, "Unknown device type %ld\n",
- id->driver_data);
+ dev_err(&i2c->dev, "Unknown device type %ld\n", type);
+ return -EINVAL;
+ }
+
+ if (!regmap_config) {
+ dev_err(&i2c->dev,
+ "No kernel support for device type %ld\n", type);
return -EINVAL;
}
@@ -77,7 +78,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
return ret;
}
- arizona->type = id->driver_data;
+ arizona->type = type;
arizona->dev = &i2c->dev;
arizona->irq = i2c->irq;
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 2cac4f463f1e..3d425e93ce84 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -169,7 +169,7 @@ static struct irq_chip arizona_irq_chip = {
static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct regmap_irq_chip_data *data = h->host_data;
+ struct arizona *data = h->host_data;
irq_set_chip_data(virq, data);
irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq);
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index 1e845f6d407b..befbc89bfd34 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -27,7 +27,7 @@ static int arizona_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct arizona *arizona;
- const struct regmap_config *regmap_config;
+ const struct regmap_config *regmap_config = NULL;
unsigned long type;
int ret;
@@ -37,20 +37,23 @@ static int arizona_spi_probe(struct spi_device *spi)
type = id->driver_data;
switch (type) {
-#ifdef CONFIG_MFD_WM5102
case WM5102:
- regmap_config = &wm5102_spi_regmap;
+ if (IS_ENABLED(CONFIG_MFD_WM5102))
+ regmap_config = &wm5102_spi_regmap;
break;
-#endif
-#ifdef CONFIG_MFD_WM5110
case WM5110:
case WM8280:
- regmap_config = &wm5110_spi_regmap;
+ if (IS_ENABLED(CONFIG_MFD_WM5110))
+ regmap_config = &wm5110_spi_regmap;
break;
-#endif
default:
- dev_err(&spi->dev, "Unknown device type %ld\n",
- id->driver_data);
+ dev_err(&spi->dev, "Unknown device type %ld\n", type);
+ return -EINVAL;
+ }
+
+ if (!regmap_config) {
+ dev_err(&spi->dev,
+ "No kernel support for device type %ld\n", type);
return -EINVAL;
}
@@ -66,7 +69,7 @@ static int arizona_spi_probe(struct spi_device *spi)
return ret;
}
- arizona->type = id->driver_data;
+ arizona->type = type;
arizona->dev = &spi->dev;
arizona->irq = spi->irq;
@@ -93,7 +96,6 @@ MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
static struct spi_driver arizona_spi_driver = {
.driver = {
.name = "arizona",
- .owner = THIS_MODULE,
.pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match),
},
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644
index 000000000000..e8e67be6b493
--- /dev/null
+++ b/drivers/mfd/atmel-flexcom.c
@@ -0,0 +1,104 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitchen@atmel.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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <dt-bindings/mfd/atmel-flexcom.h>
+
+/* I/O register offsets */
+#define FLEX_MR 0x0 /* Mode Register */
+#define FLEX_VERSION 0xfc /* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_OFFSET (0) /* Operating Mode */
+#define FLEX_MR_OPMODE_MASK (0x3 << FLEX_MR_OPMODE_OFFSET)
+#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \
+ FLEX_MR_OPMODE_MASK)
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct clk *clk;
+ struct resource *res;
+ void __iomem *base;
+ u32 opmode;
+ int err;
+
+ err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode);
+ if (err)
+ return err;
+
+ if (opmode < ATMEL_FLEXCOM_MODE_USART ||
+ opmode > ATMEL_FLEXCOM_MODE_TWI)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ err = clk_prepare_enable(clk);
+ if (err)
+ return err;
+
+ /*
+ * Set the Operating Mode in the Mode Register: only the selected device
+ * is clocked. Hence, registers of the other serial devices remain
+ * inaccessible and are read as zero. Also the external I/O lines of the
+ * Flexcom are muxed to reach the selected device.
+ */
+ writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR);
+
+ clk_disable_unprepare(clk);
+
+ return of_platform_populate(np, NULL, NULL, &pdev->dev);
+}
+
+static const struct of_device_id atmel_flexcom_of_match[] = {
+ { .compatible = "atmel,sama5d2-flexcom" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match);
+
+static struct platform_driver atmel_flexcom_driver = {
+ .probe = atmel_flexcom_probe,
+ .driver = {
+ .name = "atmel_flexcom",
+ .of_match_table = atmel_flexcom_of_match,
+ },
+};
+
+module_platform_driver(atmel_flexcom_driver);
+
+MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@atmel.com>");
+MODULE_DESCRIPTION("Atmel Flexcom MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c
index 3fff6b5d0426..06c205868573 100644
--- a/drivers/mfd/atmel-hlcdc.c
+++ b/drivers/mfd/atmel-hlcdc.c
@@ -148,6 +148,7 @@ static const struct of_device_id atmel_hlcdc_match[] = {
{ .compatible = "atmel,sama5d4-hlcdc" },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, atmel_hlcdc_match);
static struct platform_driver atmel_hlcdc_driver = {
.probe = atmel_hlcdc_probe,
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 3f576b76c322..9842199e2e6c 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -161,6 +161,21 @@ static struct resource axp22x_pek_resources[] = {
},
};
+static struct resource axp288_power_button_resources[] = {
+ {
+ .name = "PEK_DBR",
+ .start = AXP288_IRQ_POKN,
+ .end = AXP288_IRQ_POKN,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "PEK_DBF",
+ .start = AXP288_IRQ_POKP,
+ .end = AXP288_IRQ_POKP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct resource axp288_fuel_gauge_resources[] = {
{
.start = AXP288_IRQ_QWBTU,
@@ -572,6 +587,11 @@ static struct mfd_cell axp288_cells[] = {
.resources = axp288_fuel_gauge_resources,
},
{
+ .name = "axp20x-pek",
+ .num_resources = ARRAY_SIZE(axp288_power_button_resources),
+ .resources = axp288_power_button_resources,
+ },
+ {
.name = "axp288_pmic_acpi",
},
};
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index da2af5b4f855..320aaefee718 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -128,4 +128,3 @@ module_i2c_driver(bcm590xx_i2c_driver);
MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
MODULE_DESCRIPTION("BCM590xx multi-function driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:bcm590xx");
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index d06e4b46db80..56a466469664 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -344,6 +344,12 @@ static int cros_ec_i2c_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
cros_ec_i2c_resume);
+static const struct of_device_id cros_ec_i2c_of_match[] = {
+ { .compatible = "google,cros-ec-i2c", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
+
static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 },
{ }
@@ -353,6 +359,7 @@ MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
static struct i2c_driver cros_ec_driver = {
.driver = {
.name = "cros-ec-i2c",
+ .of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops,
},
.probe = cros_ec_i2c_probe,
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 30a296b4e748..6a0f6ec67c6b 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -717,7 +717,6 @@ static struct spi_driver cros_ec_driver_spi = {
.driver = {
.name = "cros-ec-spi",
.of_match_table = of_match_ptr(cros_ec_spi_of_match),
- .owner = THIS_MODULE,
.pm = &cros_ec_spi_pm_ops,
},
.probe = cros_ec_spi_probe,
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index ef7fe2ae2fa4..37e4426ef061 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -532,11 +532,7 @@ static int da903x_probe(struct i2c_client *client,
return ret;
}
- ret = da903x_add_subdevs(chip, pdata);
- if (ret)
- return ret;
-
- return 0;
+ return da903x_add_subdevs(chip, pdata);
}
static int da903x_remove(struct i2c_client *client)
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index 46e3840c7a37..c0bf68a3e614 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -51,6 +51,9 @@ static bool da9052_reg_readable(struct device *dev, unsigned int reg)
case DA9052_GPIO_2_3_REG:
case DA9052_GPIO_4_5_REG:
case DA9052_GPIO_6_7_REG:
+ case DA9052_GPIO_8_9_REG:
+ case DA9052_GPIO_10_11_REG:
+ case DA9052_GPIO_12_13_REG:
case DA9052_GPIO_14_15_REG:
case DA9052_ID_0_1_REG:
case DA9052_ID_2_3_REG:
@@ -178,6 +181,9 @@ static bool da9052_reg_writeable(struct device *dev, unsigned int reg)
case DA9052_GPIO_2_3_REG:
case DA9052_GPIO_4_5_REG:
case DA9052_GPIO_6_7_REG:
+ case DA9052_GPIO_8_9_REG:
+ case DA9052_GPIO_10_11_REG:
+ case DA9052_GPIO_12_13_REG:
case DA9052_GPIO_14_15_REG:
case DA9052_ID_0_1_REG:
case DA9052_ID_2_3_REG:
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 02887001e800..2697ffb08009 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -174,11 +174,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
return ret;
}
- ret = da9052_device_init(da9052, id->driver_data);
- if (ret != 0)
- return ret;
-
- return 0;
+ return da9052_device_init(da9052, id->driver_data);
}
static int da9052_i2c_remove(struct i2c_client *client)
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
index b5de8a6856c0..b9ea1b27db64 100644
--- a/drivers/mfd/da9052-spi.c
+++ b/drivers/mfd/da9052-spi.c
@@ -56,11 +56,7 @@ static int da9052_spi_probe(struct spi_device *spi)
return ret;
}
- ret = da9052_device_init(da9052, id->driver_data);
- if (ret != 0)
- return ret;
-
- return 0;
+ return da9052_device_init(da9052, id->driver_data);
}
static int da9052_spi_remove(struct spi_device *spi)
@@ -86,7 +82,6 @@ static struct spi_driver da9052_spi_driver = {
.id_table = da9052_spi_id,
.driver = {
.name = "da9052",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c
index f80d9471f2e7..a9ad024ec6b0 100644
--- a/drivers/mfd/da9062-core.c
+++ b/drivers/mfd/da9062-core.c
@@ -198,7 +198,7 @@ static int da9062_clear_fault_log(struct da9062 *chip)
return ret;
}
-int get_device_type(struct da9062 *chip)
+static int da9062_get_device_type(struct da9062 *chip)
{
int device_id, variant_id, variant_mrc;
int ret;
@@ -466,7 +466,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
dev_warn(chip->dev, "Cannot clear fault log\n");
- ret = get_device_type(chip);
+ ret = da9062_get_device_type(chip);
if (ret)
return ret;
diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
index 94b9bbd1a69b..195fdcfa1a0d 100644
--- a/drivers/mfd/da9150-core.c
+++ b/drivers/mfd/da9150-core.c
@@ -23,6 +23,77 @@
#include <linux/mfd/da9150/core.h>
#include <linux/mfd/da9150/registers.h>
+/* Raw device access, used for QIF */
+static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count,
+ u8 *buf)
+{
+ struct i2c_msg xfer;
+ int ret;
+
+ /*
+ * Read is split into two transfers as device expects STOP/START rather
+ * than repeated start to carry out this kind of access.
+ */
+
+ /* Write address */
+ xfer.addr = client->addr;
+ xfer.flags = 0;
+ xfer.len = 1;
+ xfer.buf = &addr;
+
+ ret = i2c_transfer(client->adapter, &xfer, 1);
+ if (ret != 1) {
+ if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+ }
+
+ /* Read data */
+ xfer.addr = client->addr;
+ xfer.flags = I2C_M_RD;
+ xfer.len = count;
+ xfer.buf = buf;
+
+ ret = i2c_transfer(client->adapter, &xfer, 1);
+ if (ret == 1)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int da9150_i2c_write_device(struct i2c_client *client, u8 addr,
+ int count, const u8 *buf)
+{
+ struct i2c_msg xfer;
+ u8 *reg_data;
+ int ret;
+
+ reg_data = kzalloc(1 + count, GFP_KERNEL);
+ if (!reg_data)
+ return -ENOMEM;
+
+ reg_data[0] = addr;
+ memcpy(&reg_data[1], buf, count);
+
+ /* Write address & data */
+ xfer.addr = client->addr;
+ xfer.flags = 0;
+ xfer.len = 1 + count;
+ xfer.buf = reg_data;
+
+ ret = i2c_transfer(client->adapter, &xfer, 1);
+ kfree(reg_data);
+ if (ret == 1)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = {
.volatile_reg = da9150_volatile_reg,
};
+void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf)
+{
+ int ret;
+
+ ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf);
+ if (ret < 0)
+ dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n",
+ addr, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_read_qif);
+
+void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf)
+{
+ int ret;
+
+ ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf);
+ if (ret < 0)
+ dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n",
+ addr, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_write_qif);
+
u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
{
int val, ret;
@@ -262,54 +355,45 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = {
};
static struct resource da9150_gpadc_resources[] = {
- {
- .name = "GPADC",
- .start = DA9150_IRQ_GPADC,
- .end = DA9150_IRQ_GPADC,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"),
};
static struct resource da9150_charger_resources[] = {
- {
- .name = "CHG_STATUS",
- .start = DA9150_IRQ_CHG,
- .end = DA9150_IRQ_CHG,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHG_TJUNC",
- .start = DA9150_IRQ_TJUNC,
- .end = DA9150_IRQ_TJUNC,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHG_VFAULT",
- .start = DA9150_IRQ_VFAULT,
- .end = DA9150_IRQ_VFAULT,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHG_VBUS",
- .start = DA9150_IRQ_VBUS,
- .end = DA9150_IRQ_VBUS,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"),
+ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"),
+ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"),
+ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"),
+};
+
+static struct resource da9150_fg_resources[] = {
+ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"),
+};
+
+enum da9150_dev_idx {
+ DA9150_GPADC_IDX = 0,
+ DA9150_CHARGER_IDX,
+ DA9150_FG_IDX,
};
static struct mfd_cell da9150_devs[] = {
- {
+ [DA9150_GPADC_IDX] = {
.name = "da9150-gpadc",
.of_compatible = "dlg,da9150-gpadc",
.resources = da9150_gpadc_resources,
.num_resources = ARRAY_SIZE(da9150_gpadc_resources),
},
- {
+ [DA9150_CHARGER_IDX] = {
.name = "da9150-charger",
.of_compatible = "dlg,da9150-charger",
.resources = da9150_charger_resources,
.num_resources = ARRAY_SIZE(da9150_charger_resources),
},
+ [DA9150_FG_IDX] = {
+ .name = "da9150-fuel-gauge",
+ .of_compatible = "dlg,da9150-fuel-gauge",
+ .resources = da9150_fg_resources,
+ .num_resources = ARRAY_SIZE(da9150_fg_resources),
+ },
};
static int da9150_probe(struct i2c_client *client,
@@ -317,6 +401,7 @@ static int da9150_probe(struct i2c_client *client,
{
struct da9150 *da9150;
struct da9150_pdata *pdata = dev_get_platdata(&client->dev);
+ int qif_addr;
int ret;
da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL);
@@ -335,16 +420,41 @@ static int da9150_probe(struct i2c_client *client,
return ret;
}
- da9150->irq_base = pdata ? pdata->irq_base : -1;
+ /* Setup secondary I2C interface for QIF access */
+ qif_addr = da9150_reg_read(da9150, DA9150_CORE2WIRE_CTRL_A);
+ qif_addr = (qif_addr & DA9150_CORE_BASE_ADDR_MASK) >> 1;
+ qif_addr |= DA9150_QIF_I2C_ADDR_LSB;
+ da9150->core_qif = i2c_new_dummy(client->adapter, qif_addr);
+ if (!da9150->core_qif) {
+ dev_err(da9150->dev, "Failed to attach QIF client\n");
+ return -ENODEV;
+ }
+
+ i2c_set_clientdata(da9150->core_qif, da9150);
+
+ if (pdata) {
+ da9150->irq_base = pdata->irq_base;
+
+ da9150_devs[DA9150_FG_IDX].platform_data = pdata->fg_pdata;
+ da9150_devs[DA9150_FG_IDX].pdata_size =
+ sizeof(struct da9150_fg_pdata);
+ } else {
+ da9150->irq_base = -1;
+ }
ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
da9150->irq_base, &da9150_regmap_irq_chip,
&da9150->regmap_irq_data);
- if (ret)
- return ret;
+ if (ret) {
+ dev_err(da9150->dev, "Failed to add regmap irq chip: %d\n",
+ ret);
+ goto regmap_irq_fail;
+ }
+
da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
+
enable_irq_wake(da9150->irq);
ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
@@ -352,11 +462,17 @@ static int da9150_probe(struct i2c_client *client,
da9150->irq_base, NULL);
if (ret) {
dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
- regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
- return ret;
+ goto mfd_fail;
}
return 0;
+
+mfd_fail:
+ regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
+regmap_irq_fail:
+ i2c_unregister_device(da9150->core_qif);
+
+ return ret;
}
static int da9150_remove(struct i2c_client *client)
@@ -365,6 +481,7 @@ static int da9150_remove(struct i2c_client *client)
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
mfd_remove_devices(da9150->dev);
+ i2c_unregister_device(da9150->core_qif);
return 0;
}
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index b279205659a4..542b47c6bcd2 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -513,7 +513,6 @@ static struct spi_driver ezxpcap_driver = {
.remove = ezx_pcap_remove,
.driver = {
.name = "ezx-pcap",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c
index 95b2ff8f223a..f9ded45a992d 100644
--- a/drivers/mfd/hi6421-pmic-core.c
+++ b/drivers/mfd/hi6421-pmic-core.c
@@ -97,6 +97,7 @@ static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
{ .compatible = "hisilicon,hi6421-pmic", },
{ },
};
+MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match_tbl);
static struct platform_driver hi6421_pmic_driver = {
.driver = {
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index 1bd5b042c8b3..0c6ff727b2ec 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -318,7 +318,6 @@ static int htcpld_setup_chip_irq(
struct htcpld_data *htcpld;
struct htcpld_chip *chip;
unsigned int irq, irq_end;
- int ret = 0;
/* Get the platform and driver data */
htcpld = platform_get_drvdata(pdev);
@@ -333,7 +332,7 @@ static int htcpld_setup_chip_irq(
irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
}
- return ret;
+ return 0;
}
static int htcpld_register_chip_i2c(
diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c
index 0d92d73bfa0e..b6fd9041f82f 100644
--- a/drivers/mfd/intel-lpss-acpi.c
+++ b/drivers/mfd/intel-lpss-acpi.c
@@ -25,10 +25,26 @@ static const struct intel_lpss_platform_info spt_info = {
.clk_rate = 120000000,
};
+static const struct intel_lpss_platform_info bxt_info = {
+ .clk_rate = 100000000,
+};
+
+static const struct intel_lpss_platform_info bxt_i2c_info = {
+ .clk_rate = 133000000,
+};
+
static const struct acpi_device_id intel_lpss_acpi_ids[] = {
/* SPT */
{ "INT3446", (kernel_ulong_t)&spt_info },
{ "INT3447", (kernel_ulong_t)&spt_info },
+ /* BXT */
+ { "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
+ { "80860ABC", (kernel_ulong_t)&bxt_info },
+ { "80860AC2", (kernel_ulong_t)&bxt_info },
+ /* APL */
+ { "80865AAC", (kernel_ulong_t)&bxt_i2c_info },
+ { "80865ABC", (kernel_ulong_t)&bxt_info },
+ { "80865AC2", (kernel_ulong_t)&bxt_info },
{ }
};
MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids);
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 9236dffeb4d6..5bfdfccbb9a1 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -70,7 +70,52 @@ static const struct intel_lpss_platform_info spt_uart_info = {
.clk_con_id = "baudclk",
};
+static const struct intel_lpss_platform_info bxt_info = {
+ .clk_rate = 100000000,
+};
+
+static const struct intel_lpss_platform_info bxt_uart_info = {
+ .clk_rate = 100000000,
+ .clk_con_id = "baudclk",
+};
+
+static const struct intel_lpss_platform_info bxt_i2c_info = {
+ .clk_rate = 133000000,
+};
+
static const struct pci_device_id intel_lpss_pci_ids[] = {
+ /* BXT */
+ { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0ab0), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0ab2), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0ab4), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0ab6), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0ab8), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0aba), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x0abc), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x0abe), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x0ac0), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x0ac2), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x0ac4), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x0ac6), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x0aee), (kernel_ulong_t)&bxt_uart_info },
+ /* APL */
+ { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x5ac2), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info },
/* SPT-LP */
{ PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info },
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index fdf4d5c1add2..6255513f54c7 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -25,6 +25,7 @@
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include "intel-lpss.h"
@@ -52,8 +53,7 @@
#define LPSS_PRIV_SSP_REG 0x20
#define LPSS_PRIV_SSP_REG_DIS_DMA_FIN BIT(0)
-#define LPSS_PRIV_REMAP_ADDR_LO 0x40
-#define LPSS_PRIV_REMAP_ADDR_HI 0x44
+#define LPSS_PRIV_REMAP_ADDR 0x40
#define LPSS_PRIV_CAPS 0xfc
#define LPSS_PRIV_CAPS_NO_IDMA BIT(8)
@@ -250,12 +250,7 @@ static void intel_lpss_set_remap_addr(const struct intel_lpss *lpss)
{
resource_size_t addr = lpss->info->mem->start;
- writel(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR_LO);
-#if BITS_PER_LONG > 32
- writel(addr >> 32, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI);
-#else
- writel(0, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI);
-#endif
+ lo_hi_writeq(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR);
}
static void intel_lpss_deassert_reset(const struct intel_lpss *lpss)
diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h
index f28cb28a62f8..2c7f8d7c0595 100644
--- a/drivers/mfd/intel-lpss.h
+++ b/drivers/mfd/intel-lpss.h
@@ -42,6 +42,8 @@ int intel_lpss_resume(struct device *dev);
.thaw = intel_lpss_resume, \
.poweroff = intel_lpss_suspend, \
.restore = intel_lpss_resume,
+#else
+#define INTEL_LPSS_SLEEP_PM_OPS
#endif
#define INTEL_LPSS_RUNTIME_PM_OPS \
diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c
index 1ce16037d043..042137465300 100644
--- a/drivers/mfd/intel_quark_i2c_gpio.c
+++ b/drivers/mfd/intel_quark_i2c_gpio.c
@@ -31,6 +31,10 @@
#define MFD_I2C_BAR 0
#define MFD_GPIO_BAR 1
+/* ACPI _ADR value to match the child node */
+#define MFD_ACPI_MATCH_GPIO 0ULL
+#define MFD_ACPI_MATCH_I2C 1ULL
+
/* The base GPIO number under GPIOLIB framework */
#define INTEL_QUARK_MFD_GPIO_BASE 8
@@ -82,27 +86,37 @@ static struct resource intel_quark_i2c_res[] = {
},
};
+static struct mfd_cell_acpi_match intel_quark_acpi_match_i2c = {
+ .adr = MFD_ACPI_MATCH_I2C,
+};
+
static struct resource intel_quark_gpio_res[] = {
[INTEL_QUARK_IORES_MEM] = {
.flags = IORESOURCE_MEM,
},
};
+static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
+ .adr = MFD_ACPI_MATCH_GPIO,
+};
+
static struct mfd_cell intel_quark_mfd_cells[] = {
{
- .id = MFD_I2C_BAR,
- .name = "i2c_designware",
- .num_resources = ARRAY_SIZE(intel_quark_i2c_res),
- .resources = intel_quark_i2c_res,
- .ignore_resource_conflicts = true,
- },
- {
.id = MFD_GPIO_BAR,
.name = "gpio-dwapb",
+ .acpi_match = &intel_quark_acpi_match_gpio,
.num_resources = ARRAY_SIZE(intel_quark_gpio_res),
.resources = intel_quark_gpio_res,
.ignore_resource_conflicts = true,
},
+ {
+ .id = MFD_I2C_BAR,
+ .name = "i2c_designware",
+ .acpi_match = &intel_quark_acpi_match_i2c,
+ .num_resources = ARRAY_SIZE(intel_quark_i2c_res),
+ .resources = intel_quark_i2c_res,
+ .ignore_resource_conflicts = true,
+ },
};
static const struct pci_device_id intel_quark_mfd_ids[] = {
@@ -248,12 +262,11 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
dev_set_drvdata(&pdev->dev, quark_mfd);
- ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]);
+ ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]);
if (ret)
return ret;
- ret = intel_quark_gpio_setup(pdev,
- &intel_quark_mfd_cells[MFD_GPIO_BAR]);
+ ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]);
if (ret)
return ret;
diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c
new file mode 100644
index 000000000000..b9428767e615
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
@@ -0,0 +1,477 @@
+/*
+ * MFD core driver for Intel Broxton Whiskey Cove PMIC
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_bxtwc.h>
+#include <asm/intel_pmc_ipc.h>
+
+/* PMIC device registers */
+#define REG_ADDR_MASK 0xFF00
+#define REG_ADDR_SHIFT 8
+#define REG_OFFSET_MASK 0xFF
+
+/* Interrupt Status Registers */
+#define BXTWC_IRQLVL1 0x4E02
+#define BXTWC_PWRBTNIRQ 0x4E03
+
+#define BXTWC_THRM0IRQ 0x4E04
+#define BXTWC_THRM1IRQ 0x4E05
+#define BXTWC_THRM2IRQ 0x4E06
+#define BXTWC_BCUIRQ 0x4E07
+#define BXTWC_ADCIRQ 0x4E08
+#define BXTWC_CHGR0IRQ 0x4E09
+#define BXTWC_CHGR1IRQ 0x4E0A
+#define BXTWC_GPIOIRQ0 0x4E0B
+#define BXTWC_GPIOIRQ1 0x4E0C
+#define BXTWC_CRITIRQ 0x4E0D
+
+/* Interrupt MASK Registers */
+#define BXTWC_MIRQLVL1 0x4E0E
+#define BXTWC_MPWRTNIRQ 0x4E0F
+
+#define BXTWC_MTHRM0IRQ 0x4E12
+#define BXTWC_MTHRM1IRQ 0x4E13
+#define BXTWC_MTHRM2IRQ 0x4E14
+#define BXTWC_MBCUIRQ 0x4E15
+#define BXTWC_MADCIRQ 0x4E16
+#define BXTWC_MCHGR0IRQ 0x4E17
+#define BXTWC_MCHGR1IRQ 0x4E18
+#define BXTWC_MGPIO0IRQ 0x4E19
+#define BXTWC_MGPIO1IRQ 0x4E1A
+#define BXTWC_MCRITIRQ 0x4E1B
+
+/* Whiskey Cove PMIC share same ACPI ID between different platforms */
+#define BROXTON_PMIC_WC_HRV 4
+
+/* Manage in two IRQ chips since mask registers are not consecutive */
+enum bxtwc_irqs {
+ /* Level 1 */
+ BXTWC_PWRBTN_LVL1_IRQ = 0,
+ BXTWC_TMU_LVL1_IRQ,
+ BXTWC_THRM_LVL1_IRQ,
+ BXTWC_BCU_LVL1_IRQ,
+ BXTWC_ADC_LVL1_IRQ,
+ BXTWC_CHGR_LVL1_IRQ,
+ BXTWC_GPIO_LVL1_IRQ,
+ BXTWC_CRIT_LVL1_IRQ,
+
+ /* Level 2 */
+ BXTWC_PWRBTN_IRQ,
+};
+
+enum bxtwc_irqs_level2 {
+ /* Level 2 */
+ BXTWC_THRM0_IRQ = 0,
+ BXTWC_THRM1_IRQ,
+ BXTWC_THRM2_IRQ,
+ BXTWC_BCU_IRQ,
+ BXTWC_ADC_IRQ,
+ BXTWC_CHGR0_IRQ,
+ BXTWC_CHGR1_IRQ,
+ BXTWC_GPIO0_IRQ,
+ BXTWC_GPIO1_IRQ,
+ BXTWC_CRIT_IRQ,
+};
+
+static const struct regmap_irq bxtwc_regmap_irqs[] = {
+ REGMAP_IRQ_REG(BXTWC_PWRBTN_LVL1_IRQ, 0, BIT(0)),
+ REGMAP_IRQ_REG(BXTWC_TMU_LVL1_IRQ, 0, BIT(1)),
+ REGMAP_IRQ_REG(BXTWC_THRM_LVL1_IRQ, 0, BIT(2)),
+ REGMAP_IRQ_REG(BXTWC_BCU_LVL1_IRQ, 0, BIT(3)),
+ REGMAP_IRQ_REG(BXTWC_ADC_LVL1_IRQ, 0, BIT(4)),
+ REGMAP_IRQ_REG(BXTWC_CHGR_LVL1_IRQ, 0, BIT(5)),
+ REGMAP_IRQ_REG(BXTWC_GPIO_LVL1_IRQ, 0, BIT(6)),
+ REGMAP_IRQ_REG(BXTWC_CRIT_LVL1_IRQ, 0, BIT(7)),
+ REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03),
+};
+
+static const struct regmap_irq bxtwc_regmap_irqs_level2[] = {
+ REGMAP_IRQ_REG(BXTWC_THRM0_IRQ, 0, 0xff),
+ REGMAP_IRQ_REG(BXTWC_THRM1_IRQ, 1, 0xbf),
+ REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff),
+ REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
+ REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
+ REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
+ REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
+ REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
+ REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
+ REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
+};
+
+static struct regmap_irq_chip bxtwc_regmap_irq_chip = {
+ .name = "bxtwc_irq_chip",
+ .status_base = BXTWC_IRQLVL1,
+ .mask_base = BXTWC_MIRQLVL1,
+ .irqs = bxtwc_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs),
+ .num_regs = 2,
+};
+
+static struct regmap_irq_chip bxtwc_regmap_irq_chip_level2 = {
+ .name = "bxtwc_irq_chip_level2",
+ .status_base = BXTWC_THRM0IRQ,
+ .mask_base = BXTWC_MTHRM0IRQ,
+ .irqs = bxtwc_regmap_irqs_level2,
+ .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_level2),
+ .num_regs = 10,
+};
+
+static struct resource gpio_resources[] = {
+ DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"),
+ DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"),
+};
+
+static struct resource adc_resources[] = {
+ DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"),
+};
+
+static struct resource charger_resources[] = {
+ DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"),
+ DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"),
+};
+
+static struct resource thermal_resources[] = {
+ DEFINE_RES_IRQ(BXTWC_THRM0_IRQ),
+ DEFINE_RES_IRQ(BXTWC_THRM1_IRQ),
+ DEFINE_RES_IRQ(BXTWC_THRM2_IRQ),
+};
+
+static struct resource bcu_resources[] = {
+ DEFINE_RES_IRQ_NAMED(BXTWC_BCU_IRQ, "BCU"),
+};
+
+static struct mfd_cell bxt_wc_dev[] = {
+ {
+ .name = "bxt_wcove_gpadc",
+ .num_resources = ARRAY_SIZE(adc_resources),
+ .resources = adc_resources,
+ },
+ {
+ .name = "bxt_wcove_thermal",
+ .num_resources = ARRAY_SIZE(thermal_resources),
+ .resources = thermal_resources,
+ },
+ {
+ .name = "bxt_wcove_ext_charger",
+ .num_resources = ARRAY_SIZE(charger_resources),
+ .resources = charger_resources,
+ },
+ {
+ .name = "bxt_wcove_bcu",
+ .num_resources = ARRAY_SIZE(bcu_resources),
+ .resources = bcu_resources,
+ },
+ {
+ .name = "bxt_wcove_gpio",
+ .num_resources = ARRAY_SIZE(gpio_resources),
+ .resources = gpio_resources,
+ },
+ {
+ .name = "bxt_wcove_region",
+ },
+};
+
+static int regmap_ipc_byte_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ int ret;
+ int i2c_addr;
+ u8 ipc_in[2];
+ u8 ipc_out[4];
+ struct intel_soc_pmic *pmic = context;
+
+ if (reg & REG_ADDR_MASK)
+ i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+ else {
+ i2c_addr = BXTWC_DEVICE1_ADDR;
+ if (!i2c_addr) {
+ dev_err(pmic->dev, "I2C address not set\n");
+ return -EINVAL;
+ }
+ }
+ reg &= REG_OFFSET_MASK;
+
+ ipc_in[0] = reg;
+ ipc_in[1] = i2c_addr;
+ ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
+ PMC_IPC_PMIC_ACCESS_READ,
+ ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1);
+ if (ret) {
+ dev_err(pmic->dev, "Failed to read from PMIC\n");
+ return ret;
+ }
+ *val = ipc_out[0];
+
+ return 0;
+}
+
+static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ int ret;
+ int i2c_addr;
+ u8 ipc_in[3];
+ struct intel_soc_pmic *pmic = context;
+
+ if (reg & REG_ADDR_MASK)
+ i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+ else {
+ i2c_addr = BXTWC_DEVICE1_ADDR;
+ if (!i2c_addr) {
+ dev_err(pmic->dev, "I2C address not set\n");
+ return -EINVAL;
+ }
+ }
+ reg &= REG_OFFSET_MASK;
+
+ ipc_in[0] = reg;
+ ipc_in[1] = i2c_addr;
+ ipc_in[2] = val;
+ ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
+ PMC_IPC_PMIC_ACCESS_WRITE,
+ ipc_in, sizeof(ipc_in), NULL, 0);
+ if (ret) {
+ dev_err(pmic->dev, "Failed to write to PMIC\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* sysfs interfaces to r/w PMIC registers, required by initial script */
+static unsigned long bxtwc_reg_addr;
+static ssize_t bxtwc_reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "0x%lx\n", bxtwc_reg_addr);
+}
+
+static ssize_t bxtwc_reg_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ if (kstrtoul(buf, 0, &bxtwc_reg_addr)) {
+ dev_err(dev, "Invalid register address\n");
+ return -EINVAL;
+ }
+ return (ssize_t)count;
+}
+
+static ssize_t bxtwc_val_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ unsigned int val;
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ ret = regmap_read(pmic->regmap, bxtwc_reg_addr, &val);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read 0x%lx\n", bxtwc_reg_addr);
+ return -EIO;
+ }
+
+ return sprintf(buf, "0x%02x\n", val);
+}
+
+static ssize_t bxtwc_val_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ unsigned int val;
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ ret = kstrtouint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(pmic->regmap, bxtwc_reg_addr, val);
+ if (ret) {
+ dev_err(dev, "Failed to write value 0x%02x to address 0x%lx",
+ val, bxtwc_reg_addr);
+ return -EIO;
+ }
+ return count;
+}
+
+static DEVICE_ATTR(addr, S_IWUSR | S_IRUSR, bxtwc_reg_show, bxtwc_reg_store);
+static DEVICE_ATTR(val, S_IWUSR | S_IRUSR, bxtwc_val_show, bxtwc_val_store);
+static struct attribute *bxtwc_attrs[] = {
+ &dev_attr_addr.attr,
+ &dev_attr_val.attr,
+ NULL
+};
+
+static const struct attribute_group bxtwc_group = {
+ .attrs = bxtwc_attrs,
+};
+
+static const struct regmap_config bxtwc_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .reg_write = regmap_ipc_byte_reg_write,
+ .reg_read = regmap_ipc_byte_reg_read,
+};
+
+static int bxtwc_probe(struct platform_device *pdev)
+{
+ int ret;
+ acpi_handle handle;
+ acpi_status status;
+ unsigned long long hrv;
+ struct intel_soc_pmic *pmic;
+
+ handle = ACPI_HANDLE(&pdev->dev);
+ status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n");
+ return -ENODEV;
+ }
+ if (hrv != BROXTON_PMIC_WC_HRV) {
+ dev_err(&pdev->dev, "Invalid PMIC hardware revision: %llu\n",
+ hrv);
+ return -ENODEV;
+ }
+
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Invalid IRQ\n");
+ return ret;
+ }
+ pmic->irq = ret;
+
+ dev_set_drvdata(&pdev->dev, pmic);
+ pmic->dev = &pdev->dev;
+
+ pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic,
+ &bxtwc_regmap_config);
+ if (IS_ERR(pmic->regmap)) {
+ ret = PTR_ERR(pmic->regmap);
+ dev_err(&pdev->dev, "Failed to initialise regmap: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+ IRQF_ONESHOT | IRQF_SHARED,
+ 0, &bxtwc_regmap_irq_chip,
+ &pmic->irq_chip_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add IRQ chip\n");
+ return ret;
+ }
+
+ ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+ IRQF_ONESHOT | IRQF_SHARED,
+ 0, &bxtwc_regmap_irq_chip_level2,
+ &pmic->irq_chip_data_level2);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add secondary IRQ chip\n");
+ goto err_irq_chip_level2;
+ }
+
+ ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
+ ARRAY_SIZE(bxt_wc_dev), NULL, 0,
+ NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add devices\n");
+ goto err_mfd;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret);
+ goto err_sysfs;
+ }
+
+ return 0;
+
+err_sysfs:
+ mfd_remove_devices(&pdev->dev);
+err_mfd:
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
+err_irq_chip_level2:
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+
+ return ret;
+}
+
+static int bxtwc_remove(struct platform_device *pdev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
+
+ sysfs_remove_group(&pdev->dev.kobj, &bxtwc_group);
+ mfd_remove_devices(&pdev->dev);
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
+
+ return 0;
+}
+
+static void bxtwc_shutdown(struct platform_device *pdev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
+
+ disable_irq(pmic->irq);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bxtwc_suspend(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ disable_irq(pmic->irq);
+
+ return 0;
+}
+
+static int bxtwc_resume(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ enable_irq(pmic->irq);
+ return 0;
+}
+#endif
+static SIMPLE_DEV_PM_OPS(bxtwc_pm_ops, bxtwc_suspend, bxtwc_resume);
+
+static const struct acpi_device_id bxtwc_acpi_ids[] = {
+ { "INT34D3", },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, pmic_acpi_ids);
+
+static struct platform_driver bxtwc_driver = {
+ .probe = bxtwc_probe,
+ .remove = bxtwc_remove,
+ .shutdown = bxtwc_shutdown,
+ .driver = {
+ .name = "BXTWC PMIC",
+ .pm = &bxtwc_pm_ops,
+ .acpi_match_table = ACPI_PTR(bxtwc_acpi_ids),
+ },
+};
+
+module_platform_driver(bxtwc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Qipeng Zha<qipeng.zha@intel.com>");
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 463f4eae20c1..05b924542ee2 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -448,7 +448,6 @@ static int kempld_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct kempld_device_data *pld;
struct resource *ioport;
- int ret;
pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
if (!pld)
@@ -471,11 +470,7 @@ static int kempld_probe(struct platform_device *pdev)
mutex_init(&pld->lock);
platform_set_drvdata(pdev, pld);
- ret = kempld_detect_device(pld);
- if (ret)
- return ret;
-
- return 0;
+ return kempld_detect_device(pld);
}
static int kempld_remove(struct platform_device *pdev)
@@ -756,7 +751,6 @@ MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
static int __init kempld_init(void)
{
const struct dmi_system_id *id;
- int ret;
if (force_device_id[0]) {
for (id = kempld_dmi_table;
@@ -771,11 +765,7 @@ static int __init kempld_init(void)
return -ENODEV;
}
- ret = platform_driver_register(&kempld_driver);
- if (ret)
- return ret;
-
- return 0;
+ return platform_driver_register(&kempld_driver);
}
static void __exit kempld_exit(void)
diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 643f3750e830..5abcbb2e8849 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -472,11 +472,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533,
if (ret)
return ret;
- ret = lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
- if (ret)
- return ret;
-
- return 0;
+ return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
}
static int lm3533_device_init(struct lm3533 *lm3533)
@@ -596,7 +592,6 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct lm3533 *lm3533;
- int ret;
dev_dbg(&i2c->dev, "%s\n", __func__);
@@ -613,11 +608,7 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
lm3533->dev = &i2c->dev;
lm3533->irq = i2c->irq;
- ret = lm3533_device_init(lm3533);
- if (ret)
- return ret;
-
- return 0;
+ return lm3533_device_init(lm3533);
}
static int lm3533_i2c_remove(struct i2c_client *i2c)
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index c5a9a08b5dfb..b514f3cf140d 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -132,24 +132,18 @@ static struct resource gpio_ich_res[] = {
},
};
-enum lpc_cells {
- LPC_WDT = 0,
- LPC_GPIO,
+static struct mfd_cell lpc_ich_wdt_cell = {
+ .name = "iTCO_wdt",
+ .num_resources = ARRAY_SIZE(wdt_ich_res),
+ .resources = wdt_ich_res,
+ .ignore_resource_conflicts = true,
};
-static struct mfd_cell lpc_ich_cells[] = {
- [LPC_WDT] = {
- .name = "iTCO_wdt",
- .num_resources = ARRAY_SIZE(wdt_ich_res),
- .resources = wdt_ich_res,
- .ignore_resource_conflicts = true,
- },
- [LPC_GPIO] = {
- .name = "gpio_ich",
- .num_resources = ARRAY_SIZE(gpio_ich_res),
- .resources = gpio_ich_res,
- .ignore_resource_conflicts = true,
- },
+static struct mfd_cell lpc_ich_gpio_cell = {
+ .name = "gpio_ich",
+ .num_resources = ARRAY_SIZE(gpio_ich_res),
+ .resources = gpio_ich_res,
+ .ignore_resource_conflicts = true,
};
/* chipset related info */
@@ -841,7 +835,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
struct itco_wdt_platform_data *pdata;
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct lpc_ich_info *info;
- struct mfd_cell *cell = &lpc_ich_cells[LPC_WDT];
+ struct mfd_cell *cell = &lpc_ich_wdt_cell;
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -860,7 +854,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
- struct mfd_cell *cell = &lpc_ich_cells[LPC_GPIO];
+ struct mfd_cell *cell = &lpc_ich_gpio_cell;
cell->platform_data = &lpc_chipset_info[priv->chipset];
cell->pdata_size = sizeof(struct lpc_ich_info);
@@ -904,7 +898,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
- lpc_ich_cells[LPC_GPIO].num_resources--;
+ lpc_ich_gpio_cell.num_resources--;
goto gpe0_done;
}
@@ -918,7 +912,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
* the platform_device subsystem doesn't see this resource
* or it will register an invalid region.
*/
- lpc_ich_cells[LPC_GPIO].num_resources--;
+ lpc_ich_gpio_cell.num_resources--;
acpi_conflict = true;
} else {
lpc_ich_enable_acpi_space(dev);
@@ -958,12 +952,12 @@ gpe0_done:
lpc_ich_finalize_gpio_cell(dev);
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
- &lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL);
+ &lpc_ich_gpio_cell, 1, NULL, 0, NULL);
gpio_done:
if (acpi_conflict)
pr_warn("Resource conflict(s) found affecting %s\n",
- lpc_ich_cells[LPC_GPIO].name);
+ lpc_ich_gpio_cell.name);
return ret;
}
@@ -1007,7 +1001,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
*/
if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
/* Don't register iomem for TCO ver 1 */
- lpc_ich_cells[LPC_WDT].num_resources--;
+ lpc_ich_wdt_cell.num_resources--;
} else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) {
pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
base_addr = base_addr_cfg & 0xffffc000;
@@ -1035,7 +1029,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
goto wdt_done;
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
- &lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL);
+ &lpc_ich_wdt_cell, 1, NULL, 0, NULL);
wdt_done:
return ret;
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c
index c52162ea3d0a..586098f1b233 100644
--- a/drivers/mfd/max77843.c
+++ b/drivers/mfd/max77843.c
@@ -80,7 +80,7 @@ static int max77843_chg_init(struct max77693_dev *max77843)
if (!max77843->i2c_chg) {
dev_err(&max77843->i2c->dev,
"Cannot allocate I2C device for Charger\n");
- return PTR_ERR(max77843->i2c_chg);
+ return -ENODEV;
}
i2c_set_clientdata(max77843->i2c_chg, max77843);
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index d3cfa9cf5c8f..156ed6f92aa3 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -55,6 +55,7 @@ static const struct of_device_id max8997_pmic_dt_match[] = {
{ .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 },
{},
};
+MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match);
#endif
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 58a170e45d88..cbc1e5ed599c 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -177,7 +177,6 @@ static struct spi_driver mc13xxx_spi_driver = {
.id_table = mc13xxx_device_id,
.driver = {
.name = "mc13xxx",
- .owner = THIS_MODULE,
.of_match_table = mc13xxx_dt_ids,
},
.probe = mc13xxx_spi_probe,
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index c17635d3e504..60b60dc63ddd 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -82,29 +82,49 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
static void mfd_acpi_add_device(const struct mfd_cell *cell,
struct platform_device *pdev)
{
- struct acpi_device *parent_adev;
+ const struct mfd_cell_acpi_match *match = cell->acpi_match;
+ struct acpi_device *parent, *child;
struct acpi_device *adev;
- parent_adev = ACPI_COMPANION(pdev->dev.parent);
- if (!parent_adev)
+ parent = ACPI_COMPANION(pdev->dev.parent);
+ if (!parent)
return;
/*
- * MFD child device gets its ACPI handle either from the ACPI
- * device directly under the parent that matches the acpi_pnpid or
- * it will use the parent handle if is no acpi_pnpid is given.
+ * MFD child device gets its ACPI handle either from the ACPI device
+ * directly under the parent that matches the either _HID or _CID, or
+ * _ADR or it will use the parent handle if is no ID is given.
+ *
+ * Note that use of _ADR is a grey area in the ACPI specification,
+ * though Intel Galileo Gen2 is using it to distinguish the children
+ * devices.
*/
- adev = parent_adev;
- if (cell->acpi_pnpid) {
- struct acpi_device_id ids[2] = {};
- struct acpi_device *child_adev;
-
- strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
- list_for_each_entry(child_adev, &parent_adev->children, node)
- if (acpi_match_device_ids(child_adev, ids)) {
- adev = child_adev;
- break;
+ adev = parent;
+ if (match) {
+ if (match->pnpid) {
+ struct acpi_device_id ids[2] = {};
+
+ strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
+ list_for_each_entry(child, &parent->children, node) {
+ if (acpi_match_device_ids(child, ids)) {
+ adev = child;
+ break;
+ }
+ }
+ } else {
+ unsigned long long adr;
+ acpi_status status;
+
+ list_for_each_entry(child, &parent->children, node) {
+ status = acpi_evaluate_integer(child->handle,
+ "_ADR", NULL,
+ &adr);
+ if (ACPI_SUCCESS(status) && match->adr == adr) {
+ adev = child;
+ break;
+ }
}
+ }
}
ACPI_COMPANION_SET(&pdev->dev, adev);
diff --git a/drivers/mfd/pcf50633-irq.c b/drivers/mfd/pcf50633-irq.c
index 498286cbb530..71d43edf110c 100644
--- a/drivers/mfd/pcf50633-irq.c
+++ b/drivers/mfd/pcf50633-irq.c
@@ -55,7 +55,7 @@ EXPORT_SYMBOL_GPL(pcf50633_free_irq);
static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
{
u8 reg, bit;
- int ret = 0, idx;
+ int idx;
idx = irq >> 3;
reg = PCF50633_REG_INT1M + idx;
@@ -72,7 +72,7 @@ static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
mutex_unlock(&pcf->lock);
- return ret;
+ return 0;
}
int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 6afc9fabd94c..207a3bd68559 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -550,7 +550,7 @@ static int qcom_rpm_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev,
irq_ack,
qcom_rpm_ack_interrupt,
- IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
+ IRQF_TRIGGER_RISING,
"qcom_rpm_ack",
rpm);
if (ret) {
diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c
index d60f91619c4a..2b95485f0057 100644
--- a/drivers/mfd/rt5033.c
+++ b/drivers/mfd/rt5033.c
@@ -47,6 +47,9 @@ static const struct mfd_cell rt5033_devs[] = {
}, {
.name = "rt5033-battery",
.of_compatible = "richtek,rt5033-battery",
+ }, {
+ .name = "rt5033-led",
+ .of_compatible = "richtek,rt5033-led",
},
};
@@ -137,7 +140,6 @@ static struct i2c_driver rt5033_driver = {
};
module_i2c_driver(rt5033_driver);
-MODULE_ALIAS("i2c:rt5033");
MODULE_DESCRIPTION("Richtek RT5033 multi-function core driver");
MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
index 373e253c33df..b95beecf767f 100644
--- a/drivers/mfd/rts5209.c
+++ b/drivers/mfd/rts5209.c
@@ -138,11 +138,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x00);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- return 0;
+ return rtsx_pci_send_cmd(pcr, 100);
}
static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c
index ce012d78ce2a..ff296a4bf3d2 100644
--- a/drivers/mfd/rts5227.c
+++ b/drivers/mfd/rts5227.c
@@ -26,6 +26,14 @@
#include "rtsx_pcr.h"
+static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)
+{
+ u8 val;
+
+ rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+ return val & 0x0F;
+}
+
static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
{
u8 driving_3v3[4][3] = {
@@ -88,7 +96,7 @@ static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
if (pm_state == HOST_ENTER_S3)
- rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
+ rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10);
rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
}
@@ -121,7 +129,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);
return rtsx_pci_send_cmd(pcr, 100);
}
@@ -179,11 +187,7 @@ static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
SD_POWER_MASK, SD_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- return 0;
+ return rtsx_pci_send_cmd(pcr, 100);
}
static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
@@ -298,8 +302,73 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);
+ pcr->ic_version = rts5227_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
+
+ pcr->reg_pm_ctrl3 = PM_CTRL3;
+}
+
+static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
+{
+ int err;
+
+ err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,
+ 0x00);
+ if (err < 0)
+ return err;
+
+ if (is_version(pcr, 0x522A, IC_VER_A)) {
+ err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
+ PHY_RCR2_INIT_27S);
+ if (err)
+ return err;
+
+ rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);
+ rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);
+ rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);
+ rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);
+ }
+
+ return 0;
+}
+
+static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+ rts5227_extra_init_hw(pcr);
+
+ rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
+ FUNC_FORCE_UPME_XMT_DBG);
+ rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
+ rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
+ rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);
+
+ return 0;
+}
+
+/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
+ */
+static const struct pcr_ops rts522a_pcr_ops = {
+ .fetch_vendor_settings = rts5227_fetch_vendor_settings,
+ .extra_init_hw = rts522a_extra_init_hw,
+ .optimize_phy = rts522a_optimize_phy,
+ .turn_on_led = rts5227_turn_on_led,
+ .turn_off_led = rts5227_turn_off_led,
+ .enable_auto_blink = rts5227_enable_auto_blink,
+ .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,
+ .cd_deglitch = NULL,
+ .conv_clk_and_div_n = NULL,
+ .force_power_down = rts5227_force_power_down,
+};
+
+void rts522a_init_params(struct rtsx_pcr *pcr)
+{
+ rts5227_init_params(pcr);
+
+ pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
}
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
index ace45384ec8b..9ed9dc84eac8 100644
--- a/drivers/mfd/rts5229.c
+++ b/drivers/mfd/rts5229.c
@@ -129,11 +129,7 @@ static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
SD_POWER_MASK, SD_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- return 0;
+ return rtsx_pci_send_cmd(pcr, 100);
}
static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c
index eb2d5866f719..40f8bb14fc59 100644
--- a/drivers/mfd/rts5249.c
+++ b/drivers/mfd/rts5249.c
@@ -234,11 +234,7 @@ static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
SD_POWER_MASK, SD_VCC_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- return 0;
+ return rtsx_pci_send_cmd(pcr, 100);
}
static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index a66540a49079..98029ee0959e 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -55,6 +55,7 @@ static const struct pci_device_id rtsx_pci_ids[] = {
{ PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
@@ -561,8 +562,6 @@ EXPORT_SYMBOL_GPL(rtsx_pci_write_ppbuf);
static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
{
- int err;
-
rtsx_pci_init_cmd(pcr);
while (*tbl & 0xFFFF0000) {
@@ -571,11 +570,7 @@ static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
tbl++;
}
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- return 0;
+ return rtsx_pci_send_cmd(pcr, 100);
}
int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
@@ -1102,6 +1097,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
rts5227_init_params(pcr);
break;
+ case 0x522A:
+ rts522a_init_params(pcr);
+ break;
+
case 0x5249:
rts5249_init_params(pcr);
break;
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
index ce48842570d7..931d1ae3ce32 100644
--- a/drivers/mfd/rtsx_pcr.h
+++ b/drivers/mfd/rtsx_pcr.h
@@ -27,6 +27,8 @@
#define MIN_DIV_N_PCR 80
#define MAX_DIV_N_PCR 208
+#define RTS522A_PM_CTRL3 0xFF7E
+
#define RTS524A_PME_FORCE_CTL 0xFF78
#define RTS524A_PM_CTRL3 0xFF7E
@@ -38,6 +40,7 @@ void rts5229_init_params(struct rtsx_pcr *pcr);
void rtl8411_init_params(struct rtsx_pcr *pcr);
void rtl8402_init_params(struct rtsx_pcr *pcr);
void rts5227_init_params(struct rtsx_pcr *pcr);
+void rts522a_init_params(struct rtsx_pcr *pcr);
void rts5249_init_params(struct rtsx_pcr *pcr);
void rts524a_init_params(struct rtsx_pcr *pcr);
void rts525a_init_params(struct rtsx_pcr *pcr);
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index d206a3e8fe87..989076d6cb83 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -103,12 +103,9 @@ static const struct mfd_cell s2mpa01_devs[] = {
};
static const struct mfd_cell s2mpu02_devs[] = {
- { .name = "s2mpu02-pmic", },
- { .name = "s2mpu02-rtc", },
{
- .name = "s2mpu02-clk",
- .of_compatible = "samsung,s2mpu02-clk",
- }
+ .name = "s2mpu02-pmic",
+ },
};
#ifdef CONFIG_OF
@@ -253,6 +250,38 @@ static const struct regmap_config s5m8767_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
+{
+ unsigned int val;
+
+ /* For each device type, the REG_ID is always the first register */
+ if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
+ dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
+}
+
+static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
+{
+ int err;
+
+ if (sec_pmic->device_type != S2MPS13X)
+ return;
+
+ if (sec_pmic->pdata->disable_wrstbi) {
+ /*
+ * If WRSTBI pin is pulled down this feature must be disabled
+ * because each Suspend to RAM will trigger buck voltage reset
+ * to default values.
+ */
+ err = regmap_update_bits(sec_pmic->regmap_pmic,
+ S2MPS13_REG_WRSTBI,
+ S2MPS13_REG_WRSTBI_MASK, 0x0);
+ if (err)
+ dev_warn(sec_pmic->dev,
+ "Cannot initialize WRSTBI config: %d\n",
+ err);
+ }
+}
+
#ifdef CONFIG_OF
/*
* Only the common platform data elements for s5m8767 are parsed here from the
@@ -278,6 +307,10 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
* not parsed here.
*/
+ pd->manual_poweroff = of_property_read_bool(dev->of_node,
+ "samsung,s2mps11-acokb-ground");
+ pd->disable_wrstbi = of_property_read_bool(dev->of_node,
+ "samsung,s2mps11-wrstbi-ground");
return pd;
}
#else
@@ -423,6 +456,8 @@ static int sec_pmic_probe(struct i2c_client *i2c,
goto err_mfd;
device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
+ sec_pmic_configure(sec_pmic);
+ sec_pmic_dump_rev(sec_pmic);
return ret;
@@ -440,6 +475,33 @@ static int sec_pmic_remove(struct i2c_client *i2c)
return 0;
}
+static void sec_pmic_shutdown(struct i2c_client *i2c)
+{
+ struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+ unsigned int reg, mask;
+
+ if (!sec_pmic->pdata->manual_poweroff)
+ return;
+
+ switch (sec_pmic->device_type) {
+ case S2MPS11X:
+ reg = S2MPS11_REG_CTRL1;
+ mask = S2MPS11_CTRL1_PWRHOLD_MASK;
+ break;
+ default:
+ /*
+ * Currently only one board with S2MPS11 needs this, so just
+ * ignore the rest.
+ */
+ dev_warn(sec_pmic->dev,
+ "Unsupported device %lu for manual power off\n",
+ sec_pmic->device_type);
+ return;
+ }
+
+ regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);
+}
+
#ifdef CONFIG_PM_SLEEP
static int sec_pmic_suspend(struct device *dev)
{
@@ -491,6 +553,7 @@ static struct i2c_driver sec_pmic_driver = {
},
.probe = sec_pmic_probe,
.remove = sec_pmic_remove,
+ .shutdown = sec_pmic_shutdown,
.id_table = sec_pmic_id,
};
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 91077efc8050..c646784c5a7d 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1719,6 +1719,7 @@ static const struct of_device_id of_sm501_match_tbl[] = {
{ .compatible = "smi,sm501", },
{ /* end */ }
};
+MODULE_DEVICE_TABLE(of, of_sm501_match_tbl);
static struct platform_driver sm501_plat_driver = {
.driver = {
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
index 618ba244d98a..f8b14ab8b9d7 100644
--- a/drivers/mfd/stmpe-spi.c
+++ b/drivers/mfd/stmpe-spi.c
@@ -135,7 +135,6 @@ static struct spi_driver stmpe_spi_driver = {
.driver = {
.name = "stmpe-spi",
.of_match_table = of_match_ptr(stmpe_spi_of_match),
- .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &stmpe_dev_pm_ops,
#endif
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index e971af86ce1e..8222e374e4b1 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -795,6 +795,7 @@ static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
return 2;
case STMPE_BLOCK_KEYPAD:
+ case STMPE_BLOCK_PWM:
return 1;
case STMPE_BLOCK_GPIO:
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index 5de95c265c1a..51c54951c220 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -16,7 +16,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
-#include <linux/mutex.h>
+#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
@@ -25,73 +25,18 @@
#include <linux/mfd/core.h>
#include <linux/mfd/tps6105x.h>
-int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value)
-{
- int ret;
-
- ret = mutex_lock_interruptible(&tps6105x->lock);
- if (ret)
- return ret;
- ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value);
- mutex_unlock(&tps6105x->lock);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-EXPORT_SYMBOL(tps6105x_set);
-
-int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf)
-{
- int ret;
-
- ret = mutex_lock_interruptible(&tps6105x->lock);
- if (ret)
- return ret;
- ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
- mutex_unlock(&tps6105x->lock);
- if (ret < 0)
- return ret;
-
- *buf = ret;
- return 0;
-}
-EXPORT_SYMBOL(tps6105x_get);
-
-/*
- * Masks off the bits in the mask and sets the bits in the bitvalues
- * parameter in one atomic operation
- */
-int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
- u8 bitmask, u8 bitvalues)
-{
- int ret;
- u8 regval;
-
- ret = mutex_lock_interruptible(&tps6105x->lock);
- if (ret)
- return ret;
- ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
- if (ret < 0)
- goto fail;
- regval = ret;
- regval = (~bitmask & regval) | (bitmask & bitvalues);
- ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval);
-fail:
- mutex_unlock(&tps6105x->lock);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-EXPORT_SYMBOL(tps6105x_mask_and_set);
+static struct regmap_config tps6105x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TPS6105X_REG_3,
+};
static int tps6105x_startup(struct tps6105x *tps6105x)
{
int ret;
- u8 regval;
+ unsigned int regval;
- ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+ ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);
if (ret)
return ret;
switch (regval >> TPS6105X_REG0_MODE_SHIFT) {
@@ -119,37 +64,59 @@ static int tps6105x_startup(struct tps6105x *tps6105x)
}
/*
- * MFD cells - we have one cell which is selected operation
- * mode, and we always have a GPIO cell.
+ * MFD cells - we always have a GPIO cell and we have one cell
+ * which is selected operation mode.
*/
-static struct mfd_cell tps6105x_cells[] = {
- {
- /* name will be runtime assigned */
- .id = -1,
- },
- {
- .name = "tps6105x-gpio",
- .id = -1,
- },
+static struct mfd_cell tps6105x_gpio_cell = {
+ .name = "tps6105x-gpio",
+};
+
+static struct mfd_cell tps6105x_leds_cell = {
+ .name = "tps6105x-leds",
+};
+
+static struct mfd_cell tps6105x_flash_cell = {
+ .name = "tps6105x-flash",
};
+static struct mfd_cell tps6105x_regulator_cell = {
+ .name = "tps6105x-regulator",
+};
+
+static int tps6105x_add_device(struct tps6105x *tps6105x,
+ struct mfd_cell *cell)
+{
+ cell->platform_data = tps6105x;
+ cell->pdata_size = sizeof(*tps6105x);
+
+ return mfd_add_devices(&tps6105x->client->dev,
+ PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL);
+}
+
static int tps6105x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps6105x *tps6105x;
struct tps6105x_platform_data *pdata;
int ret;
- int i;
+
+ pdata = dev_get_platdata(&client->dev);
+ if (!pdata) {
+ dev_err(&client->dev, "missing platform data\n");
+ return -ENODEV;
+ }
tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
if (!tps6105x)
return -ENOMEM;
+ tps6105x->regmap = devm_regmap_init_i2c(client, &tps6105x_regmap_config);
+ if (IS_ERR(tps6105x->regmap))
+ return PTR_ERR(tps6105x->regmap);
+
i2c_set_clientdata(client, tps6105x);
tps6105x->client = client;
- pdata = dev_get_platdata(&client->dev);
tps6105x->pdata = pdata;
- mutex_init(&tps6105x->lock);
ret = tps6105x_startup(tps6105x);
if (ret) {
@@ -157,38 +124,33 @@ static int tps6105x_probe(struct i2c_client *client,
return ret;
}
- /* Remove warning texts when you implement new cell drivers */
+ ret = tps6105x_add_device(tps6105x, &tps6105x_gpio_cell);
+ if (ret)
+ return ret;
+
switch (pdata->mode) {
case TPS6105X_MODE_SHUTDOWN:
dev_info(&client->dev,
"present, not used for anything, only GPIO\n");
break;
case TPS6105X_MODE_TORCH:
- tps6105x_cells[0].name = "tps6105x-leds";
- dev_warn(&client->dev,
- "torch mode is unsupported\n");
+ ret = tps6105x_add_device(tps6105x, &tps6105x_leds_cell);
break;
case TPS6105X_MODE_TORCH_FLASH:
- tps6105x_cells[0].name = "tps6105x-flash";
- dev_warn(&client->dev,
- "flash mode is unsupported\n");
+ ret = tps6105x_add_device(tps6105x, &tps6105x_flash_cell);
break;
case TPS6105X_MODE_VOLTAGE:
- tps6105x_cells[0].name ="tps6105x-regulator";
+ ret = tps6105x_add_device(tps6105x, &tps6105x_regulator_cell);
break;
default:
+ dev_warn(&client->dev, "invalid mode: %d\n", pdata->mode);
break;
}
- /* Set up and register the platform devices. */
- for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) {
- /* One state holder for all drivers, this is simple */
- tps6105x_cells[i].platform_data = tps6105x;
- tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
- }
+ if (ret)
+ mfd_remove_devices(&client->dev);
- return mfd_add_devices(&client->dev, 0, tps6105x_cells,
- ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
+ return ret;
}
static int tps6105x_remove(struct i2c_client *client)
@@ -198,7 +160,7 @@ static int tps6105x_remove(struct i2c_client *client)
mfd_remove_devices(&client->dev);
/* Put chip in shutdown mode */
- tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+ regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
TPS6105X_REG0_MODE_MASK,
TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index 55add0453ae9..d32b54426b70 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -39,6 +39,10 @@ static const struct mfd_cell tps65217s[] = {
.name = "tps65217-bl",
.of_compatible = "ti,tps65217-bl",
},
+ {
+ .name = "tps65217-charger",
+ .of_compatible = "ti,tps65217-charger",
+ },
};
/**
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index de60ad98bd9f..d59aa55b1495 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -111,7 +111,6 @@ static int tps65912_spi_remove(struct spi_device *spi)
static struct spi_driver tps65912_spi_driver = {
.driver = {
.name = "tps65912",
- .owner = THIS_MODULE,
},
.probe = tps65912_spi_probe,
.remove = tps65912_spi_remove,
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index a151ee2eed2a..08a693cd38cc 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -647,6 +647,8 @@ static int twl6040_probe(struct i2c_client *client,
twl6040->clk32k = devm_clk_get(&client->dev, "clk32k");
if (IS_ERR(twl6040->clk32k)) {
+ if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
dev_info(&client->dev, "clk32k is not handled\n");
twl6040->clk32k = NULL;
}
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index c4b9374efd76..2bb2d0467a92 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -250,7 +250,7 @@ static const struct reg_sequence wm5110_revd_patch[] = {
};
/* Add extra headphone write sequence locations */
-static const struct reg_default wm5110_reve_patch[] = {
+static const struct reg_sequence wm5110_reve_patch[] = {
{ 0x80, 0x3 },
{ 0x80, 0x3 },
{ 0x4b, 0x138 },
@@ -1481,6 +1481,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000C04, 0xA101 }, /* R3076 - GPIO5 CTRL */
{ 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */
{ 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */
+ { 0x00000C18, 0x0000 }, /* R3096 - GP Switch 1 */
{ 0x00000C20, 0x8002 }, /* R3104 - Misc Pad Ctrl 1 */
{ 0x00000C21, 0x8001 }, /* R3105 - Misc Pad Ctrl 2 */
{ 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */
@@ -1632,6 +1633,185 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */
{ 0x00000F00, 0x0000 }, /* R3840 - Clock Control */
{ 0x00000F01, 0x0000 }, /* R3841 - ANC_SRC */
+ { 0x00000F08, 0x001c }, /* R3848 - ANC Coefficient */
+ { 0x00000F09, 0x0000 }, /* R3849 - ANC Coefficient */
+ { 0x00000F0A, 0x0000 }, /* R3850 - ANC Coefficient */
+ { 0x00000F0B, 0x0000 }, /* R3851 - ANC Coefficient */
+ { 0x00000F0C, 0x0000 }, /* R3852 - ANC Coefficient */
+ { 0x00000F0D, 0x0000 }, /* R3853 - ANC Coefficient */
+ { 0x00000F0E, 0x0000 }, /* R3854 - ANC Coefficient */
+ { 0x00000F0F, 0x0000 }, /* R3855 - ANC Coefficient */
+ { 0x00000F10, 0x0000 }, /* R3856 - ANC Coefficient */
+ { 0x00000F11, 0x0000 }, /* R3857 - ANC Coefficient */
+ { 0x00000F12, 0x0000 }, /* R3858 - ANC Coefficient */
+ { 0x00000F15, 0x0000 }, /* R3861 - FCL Filter Control */
+ { 0x00000F17, 0x0004 }, /* R3863 - FCL ADC Reformatter Control */
+ { 0x00000F18, 0x0004 }, /* R3864 - ANC Coefficient */
+ { 0x00000F19, 0x0002 }, /* R3865 - ANC Coefficient */
+ { 0x00000F1A, 0x0000 }, /* R3866 - ANC Coefficient */
+ { 0x00000F1B, 0x0010 }, /* R3867 - ANC Coefficient */
+ { 0x00000F1C, 0x0000 }, /* R3868 - ANC Coefficient */
+ { 0x00000F1D, 0x0000 }, /* R3869 - ANC Coefficient */
+ { 0x00000F1E, 0x0000 }, /* R3870 - ANC Coefficient */
+ { 0x00000F1F, 0x0000 }, /* R3871 - ANC Coefficient */
+ { 0x00000F20, 0x0000 }, /* R3872 - ANC Coefficient */
+ { 0x00000F21, 0x0000 }, /* R3873 - ANC Coefficient */
+ { 0x00000F22, 0x0000 }, /* R3874 - ANC Coefficient */
+ { 0x00000F23, 0x0000 }, /* R3875 - ANC Coefficient */
+ { 0x00000F24, 0x0000 }, /* R3876 - ANC Coefficient */
+ { 0x00000F25, 0x0000 }, /* R3877 - ANC Coefficient */
+ { 0x00000F26, 0x0000 }, /* R3878 - ANC Coefficient */
+ { 0x00000F27, 0x0000 }, /* R3879 - ANC Coefficient */
+ { 0x00000F28, 0x0000 }, /* R3880 - ANC Coefficient */
+ { 0x00000F29, 0x0000 }, /* R3881 - ANC Coefficient */
+ { 0x00000F2A, 0x0000 }, /* R3882 - ANC Coefficient */
+ { 0x00000F2B, 0x0000 }, /* R3883 - ANC Coefficient */
+ { 0x00000F2C, 0x0000 }, /* R3884 - ANC Coefficient */
+ { 0x00000F2D, 0x0000 }, /* R3885 - ANC Coefficient */
+ { 0x00000F2E, 0x0000 }, /* R3886 - ANC Coefficient */
+ { 0x00000F2F, 0x0000 }, /* R3887 - ANC Coefficient */
+ { 0x00000F30, 0x0000 }, /* R3888 - ANC Coefficient */
+ { 0x00000F31, 0x0000 }, /* R3889 - ANC Coefficient */
+ { 0x00000F32, 0x0000 }, /* R3890 - ANC Coefficient */
+ { 0x00000F33, 0x0000 }, /* R3891 - ANC Coefficient */
+ { 0x00000F34, 0x0000 }, /* R3892 - ANC Coefficient */
+ { 0x00000F35, 0x0000 }, /* R3893 - ANC Coefficient */
+ { 0x00000F36, 0x0000 }, /* R3894 - ANC Coefficient */
+ { 0x00000F37, 0x0000 }, /* R3895 - ANC Coefficient */
+ { 0x00000F38, 0x0000 }, /* R3896 - ANC Coefficient */
+ { 0x00000F39, 0x0000 }, /* R3897 - ANC Coefficient */
+ { 0x00000F3A, 0x0000 }, /* R3898 - ANC Coefficient */
+ { 0x00000F3B, 0x0000 }, /* R3899 - ANC Coefficient */
+ { 0x00000F3C, 0x0000 }, /* R3900 - ANC Coefficient */
+ { 0x00000F3D, 0x0000 }, /* R3901 - ANC Coefficient */
+ { 0x00000F3E, 0x0000 }, /* R3902 - ANC Coefficient */
+ { 0x00000F3F, 0x0000 }, /* R3903 - ANC Coefficient */
+ { 0x00000F40, 0x0000 }, /* R3904 - ANC Coefficient */
+ { 0x00000F41, 0x0000 }, /* R3905 - ANC Coefficient */
+ { 0x00000F42, 0x0000 }, /* R3906 - ANC Coefficient */
+ { 0x00000F43, 0x0000 }, /* R3907 - ANC Coefficient */
+ { 0x00000F44, 0x0000 }, /* R3908 - ANC Coefficient */
+ { 0x00000F45, 0x0000 }, /* R3909 - ANC Coefficient */
+ { 0x00000F46, 0x0000 }, /* R3910 - ANC Coefficient */
+ { 0x00000F47, 0x0000 }, /* R3911 - ANC Coefficient */
+ { 0x00000F48, 0x0000 }, /* R3912 - ANC Coefficient */
+ { 0x00000F49, 0x0000 }, /* R3913 - ANC Coefficient */
+ { 0x00000F4A, 0x0000 }, /* R3914 - ANC Coefficient */
+ { 0x00000F4B, 0x0000 }, /* R3915 - ANC Coefficient */
+ { 0x00000F4C, 0x0000 }, /* R3916 - ANC Coefficient */
+ { 0x00000F4D, 0x0000 }, /* R3917 - ANC Coefficient */
+ { 0x00000F4E, 0x0000 }, /* R3918 - ANC Coefficient */
+ { 0x00000F4F, 0x0000 }, /* R3919 - ANC Coefficient */
+ { 0x00000F50, 0x0000 }, /* R3920 - ANC Coefficient */
+ { 0x00000F51, 0x0000 }, /* R3921 - ANC Coefficient */
+ { 0x00000F52, 0x0000 }, /* R3922 - ANC Coefficient */
+ { 0x00000F53, 0x0000 }, /* R3923 - ANC Coefficient */
+ { 0x00000F54, 0x0000 }, /* R3924 - ANC Coefficient */
+ { 0x00000F55, 0x0000 }, /* R3925 - ANC Coefficient */
+ { 0x00000F56, 0x0000 }, /* R3926 - ANC Coefficient */
+ { 0x00000F57, 0x0000 }, /* R3927 - ANC Coefficient */
+ { 0x00000F58, 0x0000 }, /* R3928 - ANC Coefficient */
+ { 0x00000F59, 0x0000 }, /* R3929 - ANC Coefficient */
+ { 0x00000F5A, 0x0000 }, /* R3930 - ANC Coefficient */
+ { 0x00000F5B, 0x0000 }, /* R3931 - ANC Coefficient */
+ { 0x00000F5C, 0x0000 }, /* R3932 - ANC Coefficient */
+ { 0x00000F5D, 0x0000 }, /* R3933 - ANC Coefficient */
+ { 0x00000F5E, 0x0000 }, /* R3934 - ANC Coefficient */
+ { 0x00000F5F, 0x0000 }, /* R3935 - ANC Coefficient */
+ { 0x00000F60, 0x0000 }, /* R3936 - ANC Coefficient */
+ { 0x00000F61, 0x0000 }, /* R3937 - ANC Coefficient */
+ { 0x00000F62, 0x0000 }, /* R3938 - ANC Coefficient */
+ { 0x00000F63, 0x0000 }, /* R3939 - ANC Coefficient */
+ { 0x00000F64, 0x0000 }, /* R3940 - ANC Coefficient */
+ { 0x00000F65, 0x0000 }, /* R3941 - ANC Coefficient */
+ { 0x00000F66, 0x0000 }, /* R3942 - ANC Coefficient */
+ { 0x00000F67, 0x0000 }, /* R3943 - ANC Coefficient */
+ { 0x00000F68, 0x0000 }, /* R3944 - ANC Coefficient */
+ { 0x00000F69, 0x0000 }, /* R3945 - ANC Coefficient */
+ { 0x00000F70, 0x0000 }, /* R3952 - FCR Filter Control */
+ { 0x00000F72, 0x0004 }, /* R3954 - FCR ADC Reformatter Control */
+ { 0x00000F73, 0x0004 }, /* R3955 - ANC Coefficient */
+ { 0x00000F74, 0x0002 }, /* R3956 - ANC Coefficient */
+ { 0x00000F75, 0x0000 }, /* R3957 - ANC Coefficient */
+ { 0x00000F76, 0x0010 }, /* R3958 - ANC Coefficient */
+ { 0x00000F77, 0x0000 }, /* R3959 - ANC Coefficient */
+ { 0x00000F78, 0x0000 }, /* R3960 - ANC Coefficient */
+ { 0x00000F79, 0x0000 }, /* R3961 - ANC Coefficient */
+ { 0x00000F7A, 0x0000 }, /* R3962 - ANC Coefficient */
+ { 0x00000F7B, 0x0000 }, /* R3963 - ANC Coefficient */
+ { 0x00000F7C, 0x0000 }, /* R3964 - ANC Coefficient */
+ { 0x00000F7D, 0x0000 }, /* R3965 - ANC Coefficient */
+ { 0x00000F7E, 0x0000 }, /* R3966 - ANC Coefficient */
+ { 0x00000F7F, 0x0000 }, /* R3967 - ANC Coefficient */
+ { 0x00000F80, 0x0000 }, /* R3968 - ANC Coefficient */
+ { 0x00000F81, 0x0000 }, /* R3969 - ANC Coefficient */
+ { 0x00000F82, 0x0000 }, /* R3970 - ANC Coefficient */
+ { 0x00000F83, 0x0000 }, /* R3971 - ANC Coefficient */
+ { 0x00000F84, 0x0000 }, /* R3972 - ANC Coefficient */
+ { 0x00000F85, 0x0000 }, /* R3973 - ANC Coefficient */
+ { 0x00000F86, 0x0000 }, /* R3974 - ANC Coefficient */
+ { 0x00000F87, 0x0000 }, /* R3975 - ANC Coefficient */
+ { 0x00000F88, 0x0000 }, /* R3976 - ANC Coefficient */
+ { 0x00000F89, 0x0000 }, /* R3977 - ANC Coefficient */
+ { 0x00000F8A, 0x0000 }, /* R3978 - ANC Coefficient */
+ { 0x00000F8B, 0x0000 }, /* R3979 - ANC Coefficient */
+ { 0x00000F8C, 0x0000 }, /* R3980 - ANC Coefficient */
+ { 0x00000F8D, 0x0000 }, /* R3981 - ANC Coefficient */
+ { 0x00000F8E, 0x0000 }, /* R3982 - ANC Coefficient */
+ { 0x00000F8F, 0x0000 }, /* R3983 - ANC Coefficient */
+ { 0x00000F90, 0x0000 }, /* R3984 - ANC Coefficient */
+ { 0x00000F91, 0x0000 }, /* R3985 - ANC Coefficient */
+ { 0x00000F92, 0x0000 }, /* R3986 - ANC Coefficient */
+ { 0x00000F93, 0x0000 }, /* R3987 - ANC Coefficient */
+ { 0x00000F94, 0x0000 }, /* R3988 - ANC Coefficient */
+ { 0x00000F95, 0x0000 }, /* R3989 - ANC Coefficient */
+ { 0x00000F96, 0x0000 }, /* R3990 - ANC Coefficient */
+ { 0x00000F97, 0x0000 }, /* R3991 - ANC Coefficient */
+ { 0x00000F98, 0x0000 }, /* R3992 - ANC Coefficient */
+ { 0x00000F99, 0x0000 }, /* R3993 - ANC Coefficient */
+ { 0x00000F9A, 0x0000 }, /* R3994 - ANC Coefficient */
+ { 0x00000F9B, 0x0000 }, /* R3995 - ANC Coefficient */
+ { 0x00000F9C, 0x0000 }, /* R3996 - ANC Coefficient */
+ { 0x00000F9D, 0x0000 }, /* R3997 - ANC Coefficient */
+ { 0x00000F9E, 0x0000 }, /* R3998 - ANC Coefficient */
+ { 0x00000F9F, 0x0000 }, /* R3999 - ANC Coefficient */
+ { 0x00000FA0, 0x0000 }, /* R4000 - ANC Coefficient */
+ { 0x00000FA1, 0x0000 }, /* R4001 - ANC Coefficient */
+ { 0x00000FA2, 0x0000 }, /* R4002 - ANC Coefficient */
+ { 0x00000FA3, 0x0000 }, /* R4003 - ANC Coefficient */
+ { 0x00000FA4, 0x0000 }, /* R4004 - ANC Coefficient */
+ { 0x00000FA5, 0x0000 }, /* R4005 - ANC Coefficient */
+ { 0x00000FA6, 0x0000 }, /* R4006 - ANC Coefficient */
+ { 0x00000FA7, 0x0000 }, /* R4007 - ANC Coefficient */
+ { 0x00000FA8, 0x0000 }, /* R4008 - ANC Coefficient */
+ { 0x00000FA9, 0x0000 }, /* R4009 - ANC Coefficient */
+ { 0x00000FAA, 0x0000 }, /* R4010 - ANC Coefficient */
+ { 0x00000FAB, 0x0000 }, /* R4011 - ANC Coefficient */
+ { 0x00000FAC, 0x0000 }, /* R4012 - ANC Coefficient */
+ { 0x00000FAD, 0x0000 }, /* R4013 - ANC Coefficient */
+ { 0x00000FAE, 0x0000 }, /* R4014 - ANC Coefficient */
+ { 0x00000FAF, 0x0000 }, /* R4015 - ANC Coefficient */
+ { 0x00000FB0, 0x0000 }, /* R4016 - ANC Coefficient */
+ { 0x00000FB1, 0x0000 }, /* R4017 - ANC Coefficient */
+ { 0x00000FB2, 0x0000 }, /* R4018 - ANC Coefficient */
+ { 0x00000FB3, 0x0000 }, /* R4019 - ANC Coefficient */
+ { 0x00000FB4, 0x0000 }, /* R4020 - ANC Coefficient */
+ { 0x00000FB5, 0x0000 }, /* R4021 - ANC Coefficient */
+ { 0x00000FB6, 0x0000 }, /* R4022 - ANC Coefficient */
+ { 0x00000FB7, 0x0000 }, /* R4023 - ANC Coefficient */
+ { 0x00000FB8, 0x0000 }, /* R4024 - ANC Coefficient */
+ { 0x00000FB9, 0x0000 }, /* R4025 - ANC Coefficient */
+ { 0x00000FBA, 0x0000 }, /* R4026 - ANC Coefficient */
+ { 0x00000FBB, 0x0000 }, /* R4027 - ANC Coefficient */
+ { 0x00000FBC, 0x0000 }, /* R4028 - ANC Coefficient */
+ { 0x00000FBD, 0x0000 }, /* R4029 - ANC Coefficient */
+ { 0x00000FBE, 0x0000 }, /* R4030 - ANC Coefficient */
+ { 0x00000FBF, 0x0000 }, /* R4031 - ANC Coefficient */
+ { 0x00000FC0, 0x0000 }, /* R4032 - ANC Coefficient */
+ { 0x00000FC1, 0x0000 }, /* R4033 - ANC Coefficient */
+ { 0x00000FC2, 0x0000 }, /* R4034 - ANC Coefficient */
+ { 0x00000FC3, 0x0000 }, /* R4035 - ANC Coefficient */
+ { 0x00000FC4, 0x0000 }, /* R4036 - ANC Coefficient */
{ 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */
{ 0x00001200, 0x0010 }, /* R4608 - DSP2 Control 1 */
{ 0x00001300, 0x0010 }, /* R4864 - DSP3 Control 1 */
@@ -1811,6 +1991,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_MIC_DETECT_1:
case ARIZONA_MIC_DETECT_2:
case ARIZONA_MIC_DETECT_3:
+ case ARIZONA_MIC_DETECT_4:
case ARIZONA_MIC_DETECT_LEVEL_1:
case ARIZONA_MIC_DETECT_LEVEL_2:
case ARIZONA_MIC_DETECT_LEVEL_3:
@@ -1910,6 +2091,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_HP1_SHORT_CIRCUIT_CTRL:
case ARIZONA_HP2_SHORT_CIRCUIT_CTRL:
case ARIZONA_HP3_SHORT_CIRCUIT_CTRL:
+ case ARIZONA_HP_TEST_CTRL_1:
case ARIZONA_AIF1_BCLK_CTRL:
case ARIZONA_AIF1_TX_PIN_CTRL:
case ARIZONA_AIF1_RX_PIN_CTRL:
@@ -2527,6 +2709,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_GPIO5_CTRL:
case ARIZONA_IRQ_CTRL_1:
case ARIZONA_GPIO_DEBOUNCE_CONFIG:
+ case ARIZONA_GP_SWITCH_1:
case ARIZONA_MISC_PAD_CTRL_1:
case ARIZONA_MISC_PAD_CTRL_2:
case ARIZONA_MISC_PAD_CTRL_3:
@@ -2706,6 +2889,13 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_CLOCK_CONTROL:
case ARIZONA_ANC_SRC:
case ARIZONA_DSP_STATUS:
+ case ARIZONA_ANC_COEFF_START ... ARIZONA_ANC_COEFF_END:
+ case ARIZONA_FCL_FILTER_CONTROL:
+ case ARIZONA_FCL_ADC_REFORMATTER_CONTROL:
+ case ARIZONA_FCL_COEFF_START ... ARIZONA_FCL_COEFF_END:
+ case ARIZONA_FCR_FILTER_CONTROL:
+ case ARIZONA_FCR_ADC_REFORMATTER_CONTROL:
+ case ARIZONA_FCR_COEFF_START ... ARIZONA_FCR_COEFF_END:
case ARIZONA_DSP1_CONTROL_1:
case ARIZONA_DSP1_CLOCKING_1:
case ARIZONA_DSP1_STATUS_1:
@@ -2847,12 +3037,14 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
case ARIZONA_MIC_DETECT_3:
+ case ARIZONA_MIC_DETECT_4:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_HEADPHONE_DETECT_2:
case ARIZONA_INPUT_ENABLES_STATUS:
case ARIZONA_OUTPUT_STATUS_1:
case ARIZONA_RAW_OUTPUT_STATUS_1:
+ case ARIZONA_HP_TEST_CTRL_1:
case ARIZONA_SLIMBUS_RX_PORT_STATUS:
case ARIZONA_SLIMBUS_TX_PORT_STATUS:
case ARIZONA_INTERRUPT_STATUS_1:
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 28366a90e1ad..3e0e99ec5836 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1626,7 +1626,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
mutex_init(&wm831x->io_lock);
mutex_init(&wm831x->key_lock);
dev_set_drvdata(wm831x->dev, wm831x);
- wm831x->soft_shutdown = pdata->soft_shutdown;
+
+ if (pdata)
+ wm831x->soft_shutdown = pdata->soft_shutdown;
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
if (ret < 0) {
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index b8a5e3b34ec7..80482aeb246a 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -96,7 +96,6 @@ MODULE_DEVICE_TABLE(spi, wm831x_spi_ids);
static struct spi_driver wm831x_spi_driver = {
.driver = {
.name = "wm831x",
- .owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.id_table = wm831x_spi_ids,
diff --git a/drivers/mfd/wm8998-tables.c b/drivers/mfd/wm8998-tables.c
index e6de3cd8a9aa..4c2dce77cdfc 100644
--- a/drivers/mfd/wm8998-tables.c
+++ b/drivers/mfd/wm8998-tables.c
@@ -21,7 +21,7 @@
#define WM8998_NUM_AOD_ISR 2
#define WM8998_NUM_ISR 5
-static const struct reg_default wm8998_rev_a_patch[] = {
+static const struct reg_sequence wm8998_rev_a_patch[] = {
{ 0x0212, 0x0000 },
{ 0x0211, 0x0014 },
{ 0x04E4, 0x0E0D },
@@ -199,8 +199,6 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */
{ 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */
{ 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */
- { 0x0000006E, 0x01FF }, /* R110 - Trigger Sequence Select 32 */
- { 0x0000006F, 0x01FF }, /* R111 - Trigger Sequence Select 33 */
{ 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
{ 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
{ 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */
@@ -270,16 +268,13 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
{ 0x00000293, 0x0080 }, /* R659 - Accessory Detect Mode 1 */
{ 0x0000029B, 0x0000 }, /* R667 - Headphone Detect 1 */
- { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */
{ 0x000002A2, 0x0000 }, /* R674 - Micd Clamp control */
{ 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */
{ 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */
- { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */
{ 0x000002A6, 0x3737 }, /* R678 - Mic Detect Level 1 */
{ 0x000002A7, 0x2C37 }, /* R679 - Mic Detect Level 2 */
{ 0x000002A8, 0x1422 }, /* R680 - Mic Detect Level 3 */
{ 0x000002A9, 0x030A }, /* R681 - Mic Detect Level 4 */
- { 0x000002AB, 0x0000 }, /* R683 - Mic Detect 4 */
{ 0x000002CB, 0x0000 }, /* R715 - Isolation control */
{ 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */
{ 0x00000300, 0x0000 }, /* R768 - Input Enables */
@@ -707,13 +702,11 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */
{ 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */
{ 0x00000D1C, 0xFEFF }, /* R3356 - IRQ2 Status 5 Mask */
- { 0x00000D1D, 0xFFFF }, /* R3357 - IRQ2 Status 6 Mask */
{ 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */
{ 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */
{ 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */
{ 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */
{ 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */
- { 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */
{ 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */
{ 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */
{ 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */
@@ -833,7 +826,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg)
switch (reg) {
case ARIZONA_SOFTWARE_RESET:
case ARIZONA_DEVICE_REVISION:
- case ARIZONA_CTRL_IF_SPI_CFG_1:
case ARIZONA_CTRL_IF_I2C1_CFG_1:
case ARIZONA_CTRL_IF_I2C1_CFG_2:
case ARIZONA_WRITE_SEQUENCER_CTRL_0:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ccccc2943f2f..22892c701c63 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -414,7 +414,7 @@ config TI_DAC7512
config VMWARE_BALLOON
tristate "VMware Balloon Driver"
- depends on X86 && HYPERVISOR_GUEST
+ depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST
help
This is VMware physical memory management driver which acts
like a "balloon" that can be inflated to reclaim physical pages
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index d11187d36ddd..4f832002d116 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -117,4 +117,3 @@ module_i2c_driver(ad_dpot_i2c_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("digital potentiometer I2C bus driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("i2c:ad_dpot");
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
index f4c82eafa8e5..39a7f517ee7e 100644
--- a/drivers/misc/ad525x_dpot-spi.c
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -132,7 +132,6 @@ MODULE_DEVICE_TABLE(spi, ad_dpot_spi_id);
static struct spi_driver ad_dpot_spi_driver = {
.driver = {
.name = "ad_dpot",
- .owner = THIS_MODULE,
},
.probe = ad_dpot_spi_probe,
.remove = ad_dpot_spi_remove,
diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
index 0ca05c3ec8d6..ac24a4bd63f7 100644
--- a/drivers/misc/atmel_tclib.c
+++ b/drivers/misc/atmel_tclib.c
@@ -125,6 +125,10 @@ static int __init tc_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
+ tc->slow_clk = devm_clk_get(&pdev->dev, "slow_clk");
+ if (IS_ERR(tc->slow_clk))
+ return PTR_ERR(tc->slow_clk);
+
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tc->regs = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(tc->regs))
diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
index 864ecac32373..17ecbf95ff15 100644
--- a/drivers/misc/bmp085-spi.c
+++ b/drivers/misc/bmp085-spi.c
@@ -64,7 +64,6 @@ MODULE_DEVICE_TABLE(spi, bmp085_id);
static struct spi_driver bmp085_spi_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = BMP085_NAME,
.of_match_table = bmp085_of_match
},
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index 464419b36440..cc8645b5369d 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -926,7 +926,7 @@ struct c2port_device *c2port_device_register(char *name,
c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
"c2port%d", c2dev->id);
- if (unlikely(IS_ERR(c2dev->dev))) {
+ if (IS_ERR(c2dev->dev)) {
ret = PTR_ERR(c2dev->dev);
goto error_device_create;
}
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 8af12c884b04..103baf0e0c5b 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -105,6 +105,7 @@ EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs);
void cxl_free_afu_irqs(struct cxl_context *ctx)
{
+ afu_irq_name_free(ctx);
cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
}
EXPORT_SYMBOL_GPL(cxl_free_afu_irqs);
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index e762f85ee233..2faa1270d085 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -275,6 +275,9 @@ static void reclaim_ctx(struct rcu_head *rcu)
if (ctx->kernelapi)
kfree(ctx->mapping);
+ if (ctx->irq_bitmap)
+ kfree(ctx->irq_bitmap);
+
kfree(ctx);
}
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 1c30ef77073d..0cfb9c129f27 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -677,6 +677,7 @@ int cxl_register_serr_irq(struct cxl_afu *afu);
void cxl_release_serr_irq(struct cxl_afu *afu);
int afu_register_irqs(struct cxl_context *ctx, u32 count);
void afu_release_irqs(struct cxl_context *ctx, void *cookie);
+void afu_irq_name_free(struct cxl_context *ctx);
irqreturn_t cxl_slice_irq_err(int irq, void *data);
int cxl_debugfs_init(void);
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index a30bf285b5bd..7ccd2998be92 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -120,9 +120,16 @@ int afu_release(struct inode *inode, struct file *file)
__func__, ctx->pe);
cxl_context_detach(ctx);
- mutex_lock(&ctx->mapping_lock);
- ctx->mapping = NULL;
- mutex_unlock(&ctx->mapping_lock);
+
+ /*
+ * Delete the context's mapping pointer, unless it's created by the
+ * kernel API, in which case leave it so it can be freed by reclaim_ctx()
+ */
+ if (!ctx->kernelapi) {
+ mutex_lock(&ctx->mapping_lock);
+ ctx->mapping = NULL;
+ mutex_unlock(&ctx->mapping_lock);
+ }
put_device(&ctx->afu->dev);
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
index 583b42afeda2..09a406058c46 100644
--- a/drivers/misc/cxl/irq.c
+++ b/drivers/misc/cxl/irq.c
@@ -414,7 +414,7 @@ void cxl_release_psl_irq(struct cxl_afu *afu)
kfree(afu->psl_irq_name);
}
-static void afu_irq_name_free(struct cxl_context *ctx)
+void afu_irq_name_free(struct cxl_context *ctx)
{
struct cxl_irq_name *irq_name, *tmp;
@@ -524,7 +524,5 @@ void afu_release_irqs(struct cxl_context *ctx, void *cookie)
afu_irq_name_free(ctx);
cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
- kfree(ctx->irq_bitmap);
- ctx->irq_bitmap = NULL;
ctx->irq_count = 0;
}
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index b37f2e8004f5..d2e75c88f4d2 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -457,6 +457,7 @@ static int activate_afu_directed(struct cxl_afu *afu)
dev_info(&afu->dev, "Activating AFU directed mode\n");
+ afu->num_procs = afu->max_procs_virtualised;
if (afu->spa == NULL) {
if (cxl_alloc_spa(afu))
return -ENOMEM;
@@ -468,7 +469,6 @@ static int activate_afu_directed(struct cxl_afu *afu)
cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L);
afu->current_mode = CXL_MODE_DIRECTED;
- afu->num_procs = afu->max_procs_virtualised;
if ((rc = cxl_chardev_m_afu_add(afu)))
return rc;
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index a5e977192b61..85761d7eb333 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -1035,6 +1035,32 @@ static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev)
return 0;
}
+/*
+ * Workaround a PCIe Host Bridge defect on some cards, that can cause
+ * malformed Transaction Layer Packet (TLP) errors to be erroneously
+ * reported. Mask this error in the Uncorrectable Error Mask Register.
+ *
+ * The upper nibble of the PSL revision is used to distinguish between
+ * different cards. The affected ones have it set to 0.
+ */
+static void cxl_fixup_malformed_tlp(struct cxl *adapter, struct pci_dev *dev)
+{
+ int aer;
+ u32 data;
+
+ if (adapter->psl_rev & 0xf000)
+ return;
+ if (!(aer = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)))
+ return;
+ pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &data);
+ if (data & PCI_ERR_UNC_MALF_TLP)
+ if (data & PCI_ERR_UNC_INTN)
+ return;
+ data |= PCI_ERR_UNC_MALF_TLP;
+ data |= PCI_ERR_UNC_INTN;
+ pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, data);
+}
+
static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev)
{
if (adapter->vsec_status & CXL_STATUS_SECOND_PORT)
@@ -1134,6 +1160,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
if ((rc = cxl_vsec_looks_ok(adapter, dev)))
return rc;
+ cxl_fixup_malformed_tlp(adapter, dev);
+
if ((rc = setup_cxl_bars(dev)))
return rc;
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c
index 94b520896b18..c241e15cacb1 100644
--- a/drivers/misc/cxl/vphb.c
+++ b/drivers/misc/cxl/vphb.c
@@ -290,8 +290,10 @@ void cxl_pci_vphb_remove(struct cxl_afu *afu)
return;
phb = afu->phb;
+ afu->phb = NULL;
pci_remove_root_bus(phb->bus);
+ pcibios_free_controller(phb);
}
struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index c6cb7f8f325e..5d7c0900fa1b 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -21,6 +21,7 @@
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/of.h>
+#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/platform_data/at24.h>
@@ -131,6 +132,12 @@ static const struct i2c_device_id at24_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, at24_ids);
+static const struct acpi_device_id at24_acpi_ids[] = {
+ { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
+
/*-------------------------------------------------------------------------*/
/*
@@ -467,21 +474,29 @@ static void at24_get_ofdata(struct i2c_client *client,
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct at24_platform_data chip;
+ kernel_ulong_t magic = 0;
bool writable;
int use_smbus = 0;
int use_smbus_write = 0;
struct at24_data *at24;
int err;
unsigned i, num_addresses;
- kernel_ulong_t magic;
if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data;
} else {
- if (!id->driver_data)
+ if (id) {
+ magic = id->driver_data;
+ } else {
+ const struct acpi_device_id *aid;
+
+ aid = acpi_match_device(at24_acpi_ids, &client->dev);
+ if (aid)
+ magic = aid->driver_data;
+ }
+ if (!magic)
return -ENODEV;
- magic = id->driver_data;
chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
magic >>= AT24_SIZE_BYTELEN;
chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
@@ -661,6 +676,7 @@ static int at24_remove(struct i2c_client *client)
static struct i2c_driver at24_driver = {
.driver = {
.name = "at24",
+ .acpi_match_table = ACPI_PTR(at24_acpi_ids),
},
.probe = at24_probe,
.remove = at24_remove,
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 0a1af93ec638..f850ef556bcc 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -462,7 +462,6 @@ MODULE_DEVICE_TABLE(of, at25_of_match);
static struct spi_driver at25_driver = {
.driver = {
.name = "at25",
- .owner = THIS_MODULE,
.of_match_table = at25_of_match,
},
.probe = at25_probe,
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index a6bd9e3fe9d3..ff63f05edc76 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -370,7 +370,6 @@ static int eeprom_93xx46_remove(struct spi_device *spi)
static struct spi_driver eeprom_93xx46_driver = {
.driver = {
.name = "93xx46",
- .owner = THIS_MODULE,
},
.probe = eeprom_93xx46_probe,
.remove = eeprom_93xx46_remove,
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h
index e7353449874b..cb851c14ca4b 100644
--- a/drivers/misc/genwqe/card_base.h
+++ b/drivers/misc/genwqe/card_base.h
@@ -514,7 +514,7 @@ int __genwqe_execute_ddcb(struct genwqe_dev *cd,
/**
* __genwqe_execute_raw_ddcb() - Execute DDCB request without addr translation
*
- * This version will not do address translation or any modifcation of
+ * This version will not do address translation or any modification of
* the DDCB data. It is used e.g. for the MoveFlash DDCB which is
* entirely prepared by the driver itself. That means the appropriate
* DMA addresses are already in the DDCB and do not need any
diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c
index 6d51e5f08664..353ee0cc733d 100644
--- a/drivers/misc/genwqe/card_ddcb.c
+++ b/drivers/misc/genwqe/card_ddcb.c
@@ -203,7 +203,7 @@ struct genwqe_ddcb_cmd *ddcb_requ_alloc(void)
{
struct ddcb_requ *req;
- req = kzalloc(sizeof(*req), GFP_ATOMIC);
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return NULL;
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 70e62d6a3231..7f1b282d7d96 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -449,7 +449,7 @@ static int genwqe_mmap(struct file *filp, struct vm_area_struct *vma)
if (get_order(vsize) > MAX_ORDER)
return -ENOMEM;
- dma_map = kzalloc(sizeof(struct dma_mapping), GFP_ATOMIC);
+ dma_map = kzalloc(sizeof(struct dma_mapping), GFP_KERNEL);
if (dma_map == NULL)
return -ENOMEM;
@@ -785,7 +785,7 @@ static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m)
map_addr = (m->addr & PAGE_MASK);
map_size = round_up(m->size + (m->addr & ~PAGE_MASK), PAGE_SIZE);
- dma_map = kzalloc(sizeof(struct dma_mapping), GFP_ATOMIC);
+ dma_map = kzalloc(sizeof(struct dma_mapping), GFP_KERNEL);
if (dma_map == NULL)
return -ENOMEM;
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 1ca94e6fa8fb..222367cc8c81 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -220,7 +220,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
if (get_order(size) > MAX_ORDER)
return NULL;
- return pci_alloc_consistent(cd->pci_dev, size, dma_handle);
+ return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle,
+ GFP_KERNEL);
}
void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size,
@@ -229,7 +230,7 @@ void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size,
if (vaddr == NULL)
return;
- pci_free_consistent(cd->pci_dev, size, vaddr, dma_handle);
+ dma_free_coherent(&cd->pci_dev->dev, size, vaddr, dma_handle);
}
static void genwqe_unmap_pages(struct genwqe_dev *cd, dma_addr_t *dma_list,
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index b83e3ca12a41..d6a901cd4222 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -2,7 +2,7 @@
* Driver for the HP iLO management processor.
*
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
- * David Altobelli <david.altobelli@hp.com>
+ * David Altobelli <david.altobelli@hpe.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
@@ -902,11 +902,11 @@ static void __exit ilo_exit(void)
MODULE_VERSION("1.4.1");
MODULE_ALIAS(ILO_NAME);
MODULE_DESCRIPTION(ILO_NAME);
-MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
+MODULE_AUTHOR("David Altobelli <david.altobelli@hpe.com>");
MODULE_LICENSE("GPL v2");
module_param(max_ccb, uint, 0444);
-MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (16)");
+MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8-24)(default=16)");
module_init(ilo_init);
module_exit(ilo_exit);
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
index 9a60bd4d3c49..99635dd9dbac 100644
--- a/drivers/misc/kgdbts.c
+++ b/drivers/misc/kgdbts.c
@@ -1112,6 +1112,7 @@ static int __init init_kgdbts(void)
return configure_kgdbts();
}
+device_initcall(init_kgdbts);
static int kgdbts_get_char(void)
{
@@ -1180,10 +1181,9 @@ static struct kgdb_io kgdbts_io_ops = {
.post_exception = kgdbts_post_exp_handler,
};
-module_init(init_kgdbts);
+/*
+ * not really modular, but the easiest way to keep compat with existing
+ * bootargs behaviour is to continue using module_param here.
+ */
module_param_call(kgdbts, param_set_kgdbts_var, param_get_string, &kps, 0644);
MODULE_PARM_DESC(kgdbts, "<A|V1|V2>[F#|S#][N#]");
-MODULE_DESCRIPTION("KGDB Test Suite");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Wind River Systems, Inc.");
-
diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c
index c544f1f50f52..626fdcaf2510 100644
--- a/drivers/misc/lattice-ecp3-config.c
+++ b/drivers/misc/lattice-ecp3-config.c
@@ -235,7 +235,6 @@ MODULE_DEVICE_TABLE(spi, lattice_ecp3_id);
static struct spi_driver lattice_ecp3_driver = {
.driver = {
.name = "lattice-ecp3",
- .owner = THIS_MODULE,
},
.probe = lattice_ecp3_probe,
.remove = lattice_ecp3_remove,
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
index b2f6e1651ac9..e575475123c8 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -138,7 +138,6 @@ static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
static struct spi_driver lis302dl_spi_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
.pm = &lis3lv02d_spi_pm,
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
},
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index b5abe34120b8..11fdadc68e53 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -472,7 +472,7 @@ static void lkdtm_do_action(enum ctype which)
break;
}
case CT_ACCESS_USERSPACE: {
- unsigned long user_addr, tmp;
+ unsigned long user_addr, tmp = 0;
unsigned long *ptr;
user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
@@ -483,6 +483,12 @@ static void lkdtm_do_action(enum ctype which)
return;
}
+ if (copy_to_user((void __user *)user_addr, &tmp, sizeof(tmp))) {
+ pr_warn("copy_to_user failed\n");
+ vm_munmap(user_addr, PAGE_SIZE);
+ return;
+ }
+
ptr = (unsigned long *)user_addr;
pr_info("attempting bad read at %p\n", ptr);
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 1e42781592d8..cd0403f09267 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -458,7 +458,7 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
return;
}
- if (dev->iamthif_canceled != 1) {
+ if (!dev->iamthif_canceled) {
dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
dev->iamthif_stall_timer = 0;
list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 3e536ca85f7d..020de5919c21 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -285,11 +285,11 @@ static struct mei_fixup {
};
/**
- * mei_cl_dev_fixup - run fixup handlers
+ * mei_cldev_fixup - run fixup handlers
*
* @cldev: me client device
*/
-void mei_cl_dev_fixup(struct mei_cl_device *cldev)
+void mei_cl_bus_dev_fixup(struct mei_cl_device *cldev)
{
struct mei_fixup *f;
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index eef1c6b46ad8..0b05aa938799 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -91,7 +91,7 @@ out:
* __mei_cl_recv - internal client receive (read)
*
* @cl: host client
- * @buf: buffer to send
+ * @buf: buffer to receive
* @length: buffer length
*
* Return: read size in bytes of < 0 on error
@@ -165,7 +165,7 @@ out:
}
/**
- * mei_cl_send - me device send (write)
+ * mei_cldev_send - me device send (write)
*
* @cldev: me client device
* @buf: buffer to send
@@ -173,7 +173,7 @@ out:
*
* Return: written size in bytes or < 0 on error
*/
-ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
+ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
struct mei_cl *cl = cldev->cl;
@@ -182,18 +182,18 @@ ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
return __mei_cl_send(cl, buf, length, 1);
}
-EXPORT_SYMBOL_GPL(mei_cl_send);
+EXPORT_SYMBOL_GPL(mei_cldev_send);
/**
- * mei_cl_recv - client receive (read)
+ * mei_cldev_recv - client receive (read)
*
* @cldev: me client device
- * @buf: buffer to send
+ * @buf: buffer to receive
* @length: buffer length
*
* Return: read size in bytes of < 0 on error
*/
-ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
+ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
struct mei_cl *cl = cldev->cl;
@@ -202,15 +202,15 @@ ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
return __mei_cl_recv(cl, buf, length);
}
-EXPORT_SYMBOL_GPL(mei_cl_recv);
+EXPORT_SYMBOL_GPL(mei_cldev_recv);
/**
- * mei_bus_event_work - dispatch rx event for a bus device
+ * mei_cl_bus_event_work - dispatch rx event for a bus device
* and schedule new work
*
* @work: work
*/
-static void mei_bus_event_work(struct work_struct *work)
+static void mei_cl_bus_event_work(struct work_struct *work)
{
struct mei_cl_device *cldev;
@@ -272,7 +272,7 @@ void mei_cl_bus_rx_event(struct mei_cl *cl)
}
/**
- * mei_cl_register_event_cb - register event callback
+ * mei_cldev_register_event_cb - register event callback
*
* @cldev: me client devices
* @event_cb: callback function
@@ -283,9 +283,9 @@ void mei_cl_bus_rx_event(struct mei_cl *cl)
* -EALREADY if an callback is already registered
* <0 on other errors
*/
-int mei_cl_register_event_cb(struct mei_cl_device *cldev,
- unsigned long events_mask,
- mei_cl_event_cb_t event_cb, void *context)
+int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
+ unsigned long events_mask,
+ mei_cldev_event_cb_t event_cb, void *context)
{
int ret;
@@ -296,7 +296,7 @@ int mei_cl_register_event_cb(struct mei_cl_device *cldev,
cldev->events_mask = events_mask;
cldev->event_cb = event_cb;
cldev->event_context = context;
- INIT_WORK(&cldev->event_work, mei_bus_event_work);
+ INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
ret = mei_cl_read_start(cldev->cl, 0, NULL);
@@ -314,42 +314,81 @@ int mei_cl_register_event_cb(struct mei_cl_device *cldev,
return 0;
}
-EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
+EXPORT_SYMBOL_GPL(mei_cldev_register_event_cb);
/**
- * mei_cl_get_drvdata - driver data getter
+ * mei_cldev_get_drvdata - driver data getter
*
* @cldev: mei client device
*
* Return: driver private data
*/
-void *mei_cl_get_drvdata(const struct mei_cl_device *cldev)
+void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
{
return dev_get_drvdata(&cldev->dev);
}
-EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
+EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
/**
- * mei_cl_set_drvdata - driver data setter
+ * mei_cldev_set_drvdata - driver data setter
*
* @cldev: mei client device
* @data: data to store
*/
-void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data)
+void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
{
dev_set_drvdata(&cldev->dev, data);
}
-EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
+EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
+
+/**
+ * mei_cldev_uuid - return uuid of the underlying me client
+ *
+ * @cldev: mei client device
+ *
+ * Return: me client uuid
+ */
+const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev)
+{
+ return mei_me_cl_uuid(cldev->me_cl);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_uuid);
+
+/**
+ * mei_cldev_ver - return protocol version of the underlying me client
+ *
+ * @cldev: mei client device
+ *
+ * Return: me client protocol version
+ */
+u8 mei_cldev_ver(const struct mei_cl_device *cldev)
+{
+ return mei_me_cl_ver(cldev->me_cl);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_ver);
+
+/**
+ * mei_cldev_enabled - check whether the device is enabled
+ *
+ * @cldev: mei client device
+ *
+ * Return: true if me client is initialized and connected
+ */
+bool mei_cldev_enabled(struct mei_cl_device *cldev)
+{
+ return cldev->cl && mei_cl_is_connected(cldev->cl);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_enabled);
/**
- * mei_cl_enable_device - enable me client device
+ * mei_cldev_enable_device - enable me client device
* create connection with me client
*
* @cldev: me client device
*
* Return: 0 on success and < 0 on error
*/
-int mei_cl_enable_device(struct mei_cl_device *cldev)
+int mei_cldev_enable(struct mei_cl_device *cldev)
{
struct mei_device *bus = cldev->bus;
struct mei_cl *cl;
@@ -389,17 +428,17 @@ out:
return ret;
}
-EXPORT_SYMBOL_GPL(mei_cl_enable_device);
+EXPORT_SYMBOL_GPL(mei_cldev_enable);
/**
- * mei_cl_disable_device - disable me client device
+ * mei_cldev_disable - disable me client device
* disconnect form the me client
*
* @cldev: me client device
*
* Return: 0 on success and < 0 on error
*/
-int mei_cl_disable_device(struct mei_cl_device *cldev)
+int mei_cldev_disable(struct mei_cl_device *cldev)
{
struct mei_device *bus;
struct mei_cl *cl;
@@ -437,7 +476,7 @@ out:
mutex_unlock(&bus->device_lock);
return err;
}
-EXPORT_SYMBOL_GPL(mei_cl_disable_device);
+EXPORT_SYMBOL_GPL(mei_cldev_disable);
/**
* mei_cl_device_find - find matching entry in the driver id table
@@ -453,17 +492,26 @@ struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
{
const struct mei_cl_device_id *id;
const uuid_le *uuid;
+ u8 version;
+ bool match;
uuid = mei_me_cl_uuid(cldev->me_cl);
+ version = mei_me_cl_ver(cldev->me_cl);
id = cldrv->id_table;
while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
if (!uuid_le_cmp(*uuid, id->uuid)) {
+ match = true;
- if (!cldev->name[0])
- return id;
+ if (cldev->name[0])
+ if (strncmp(cldev->name, id->name,
+ sizeof(id->name)))
+ match = false;
- if (!strncmp(cldev->name, id->name, sizeof(id->name)))
+ if (id->version != MEI_CL_VERSION_ANY)
+ if (id->version != version)
+ match = false;
+ if (match)
return id;
}
@@ -590,6 +638,19 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
}
static DEVICE_ATTR_RO(uuid);
+static ssize_t version_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ u8 version = mei_me_cl_ver(cldev->me_cl);
+ size_t len;
+
+ len = snprintf(buf, PAGE_SIZE, "%02X", version);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(version);
+
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
char *buf)
{
@@ -597,20 +658,19 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
size_t len;
- len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
- cldev->name, MEI_CL_UUID_ARGS(uuid->b));
-
+ len = snprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}
static DEVICE_ATTR_RO(modalias);
-static struct attribute *mei_cl_dev_attrs[] = {
+static struct attribute *mei_cldev_attrs[] = {
&dev_attr_name.attr,
&dev_attr_uuid.attr,
+ &dev_attr_version.attr,
&dev_attr_modalias.attr,
NULL,
};
-ATTRIBUTE_GROUPS(mei_cl_dev);
+ATTRIBUTE_GROUPS(mei_cldev);
/**
* mei_cl_device_uevent - me client bus uevent handler
@@ -624,6 +684,10 @@ static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+ u8 version = mei_me_cl_ver(cldev->me_cl);
+
+ if (add_uevent_var(env, "MEI_CL_VERSION=%d", version))
+ return -ENOMEM;
if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
return -ENOMEM;
@@ -631,8 +695,8 @@ static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
return -ENOMEM;
- if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
- cldev->name, MEI_CL_UUID_ARGS(uuid->b)))
+ if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
+ cldev->name, uuid, version))
return -ENOMEM;
return 0;
@@ -640,7 +704,7 @@ static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
static struct bus_type mei_cl_bus_type = {
.name = "mei",
- .dev_groups = mei_cl_dev_groups,
+ .dev_groups = mei_cldev_groups,
.match = mei_cl_device_match,
.probe = mei_cl_device_probe,
.remove = mei_cl_device_remove,
@@ -661,7 +725,7 @@ static void mei_dev_bus_put(struct mei_device *bus)
put_device(bus->dev);
}
-static void mei_cl_dev_release(struct device *dev)
+static void mei_cl_bus_dev_release(struct device *dev)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
@@ -674,19 +738,32 @@ static void mei_cl_dev_release(struct device *dev)
}
static struct device_type mei_cl_device_type = {
- .release = mei_cl_dev_release,
+ .release = mei_cl_bus_dev_release,
};
/**
- * mei_cl_dev_alloc - initialize and allocate mei client device
+ * mei_cl_bus_set_name - set device name for me client device
+ *
+ * @cldev: me client device
+ */
+static inline void mei_cl_bus_set_name(struct mei_cl_device *cldev)
+{
+ dev_set_name(&cldev->dev, "mei:%s:%pUl:%02X",
+ cldev->name,
+ mei_me_cl_uuid(cldev->me_cl),
+ mei_me_cl_ver(cldev->me_cl));
+}
+
+/**
+ * mei_cl_bus_dev_alloc - initialize and allocate mei client device
*
* @bus: mei device
* @me_cl: me client
*
* Return: allocated device structur or NULL on allocation failure
*/
-static struct mei_cl_device *mei_cl_dev_alloc(struct mei_device *bus,
- struct mei_me_client *me_cl)
+static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
+ struct mei_me_client *me_cl)
{
struct mei_cl_device *cldev;
@@ -700,6 +777,7 @@ static struct mei_cl_device *mei_cl_dev_alloc(struct mei_device *bus,
cldev->dev.type = &mei_cl_device_type;
cldev->bus = mei_dev_bus_get(bus);
cldev->me_cl = mei_me_cl_get(me_cl);
+ mei_cl_bus_set_name(cldev);
cldev->is_added = 0;
INIT_LIST_HEAD(&cldev->bus_list);
@@ -715,15 +793,15 @@ static struct mei_cl_device *mei_cl_dev_alloc(struct mei_device *bus,
*
* Return: true if the device is eligible for enumeration
*/
-static bool mei_cl_dev_setup(struct mei_device *bus,
- struct mei_cl_device *cldev)
+static bool mei_cl_bus_dev_setup(struct mei_device *bus,
+ struct mei_cl_device *cldev)
{
cldev->do_match = 1;
- mei_cl_dev_fixup(cldev);
+ mei_cl_bus_dev_fixup(cldev);
+ /* the device name can change during fix up */
if (cldev->do_match)
- dev_set_name(&cldev->dev, "mei:%s:%pUl",
- cldev->name, mei_me_cl_uuid(cldev->me_cl));
+ mei_cl_bus_set_name(cldev);
return cldev->do_match == 1;
}
@@ -739,7 +817,9 @@ static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
{
int ret;
- dev_dbg(cldev->bus->dev, "adding %pUL\n", mei_me_cl_uuid(cldev->me_cl));
+ dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
+ mei_me_cl_uuid(cldev->me_cl),
+ mei_me_cl_ver(cldev->me_cl));
ret = device_add(&cldev->dev);
if (!ret)
cldev->is_added = 1;
@@ -762,17 +842,20 @@ static void mei_cl_bus_dev_stop(struct mei_cl_device *cldev)
* mei_cl_bus_dev_destroy - destroy me client devices object
*
* @cldev: me client device
+ *
+ * Locking: called under "dev->cl_bus_lock" lock
*/
static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
{
+
+ WARN_ON(!mutex_is_locked(&cldev->bus->cl_bus_lock));
+
if (!cldev->is_added)
return;
device_del(&cldev->dev);
- mutex_lock(&cldev->bus->cl_bus_lock);
list_del_init(&cldev->bus_list);
- mutex_unlock(&cldev->bus->cl_bus_lock);
cldev->is_added = 0;
put_device(&cldev->dev);
@@ -798,35 +881,40 @@ void mei_cl_bus_remove_devices(struct mei_device *bus)
{
struct mei_cl_device *cldev, *next;
+ mutex_lock(&bus->cl_bus_lock);
list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
mei_cl_bus_remove_device(cldev);
+ mutex_unlock(&bus->cl_bus_lock);
}
/**
- * mei_cl_dev_init - allocate and initializes an mei client devices
+ * mei_cl_bus_dev_init - allocate and initializes an mei client devices
* based on me client
*
* @bus: mei device
* @me_cl: me client
+ *
+ * Locking: called under "dev->cl_bus_lock" lock
*/
-static void mei_cl_dev_init(struct mei_device *bus, struct mei_me_client *me_cl)
+static void mei_cl_bus_dev_init(struct mei_device *bus,
+ struct mei_me_client *me_cl)
{
struct mei_cl_device *cldev;
+ WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));
+
dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));
if (me_cl->bus_added)
return;
- cldev = mei_cl_dev_alloc(bus, me_cl);
+ cldev = mei_cl_bus_dev_alloc(bus, me_cl);
if (!cldev)
return;
- mutex_lock(&cldev->bus->cl_bus_lock);
me_cl->bus_added = true;
list_add_tail(&cldev->bus_list, &bus->device_list);
- mutex_unlock(&cldev->bus->cl_bus_lock);
}
@@ -841,12 +929,13 @@ void mei_cl_bus_rescan(struct mei_device *bus)
struct mei_cl_device *cldev, *n;
struct mei_me_client *me_cl;
+ mutex_lock(&bus->cl_bus_lock);
+
down_read(&bus->me_clients_rwsem);
list_for_each_entry(me_cl, &bus->me_clients, list)
- mei_cl_dev_init(bus, me_cl);
+ mei_cl_bus_dev_init(bus, me_cl);
up_read(&bus->me_clients_rwsem);
- mutex_lock(&bus->cl_bus_lock);
list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
if (!mei_me_cl_is_active(cldev->me_cl)) {
@@ -857,7 +946,7 @@ void mei_cl_bus_rescan(struct mei_device *bus)
if (cldev->is_added)
continue;
- if (mei_cl_dev_setup(bus, cldev))
+ if (mei_cl_bus_dev_setup(bus, cldev))
mei_cl_bus_dev_add(cldev);
else {
list_del_init(&cldev->bus_list);
@@ -869,7 +958,8 @@ void mei_cl_bus_rescan(struct mei_device *bus)
dev_dbg(bus->dev, "rescan end");
}
-int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner)
+int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
+ struct module *owner)
{
int err;
@@ -885,15 +975,15 @@ int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner)
return 0;
}
-EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
+EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
-void mei_cl_driver_unregister(struct mei_cl_driver *cldrv)
+void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
{
driver_unregister(&cldrv->driver);
pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
}
-EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
+EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
int __init mei_cl_bus_init(void)
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 1c7cad07d731..04e1aa39243f 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -68,6 +68,18 @@ static inline const uuid_le *mei_me_cl_uuid(const struct mei_me_client *me_cl)
return &me_cl->props.protocol_name;
}
+/**
+ * mei_me_cl_ver - return me client protocol version
+ *
+ * @me_cl: me client
+ *
+ * Return: me client protocol version
+ */
+static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl)
+{
+ return me_cl->props.protocol_version;
+}
+
/*
* MEI IO Functions
*/
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 8504dbeacd3b..a138d8a27ab5 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -215,7 +215,7 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name)
f = debugfs_create_file("active", S_IRUSR, dir,
dev, &mei_dbgfs_fops_active);
if (!f) {
- dev_err(dev->dev, "meclients: registration failed\n");
+ dev_err(dev->dev, "active: registration failed\n");
goto err;
}
f = debugfs_create_file("devstate", S_IRUSR, dir,
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 6d7c188fb65c..e7b7aad0999b 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -281,7 +281,7 @@ int mei_hbm_start_req(struct mei_device *dev)
return 0;
}
-/*
+/**
* mei_hbm_enum_clients_req - sends enumeration client request message.
*
* @dev: the device structure
@@ -314,7 +314,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
return 0;
}
-/*
+/**
* mei_hbm_me_cl_add - add new me client to the list
*
* @dev: the device structure
@@ -569,7 +569,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
return 0;
}
-/*
+/**
* mei_hbm_pg - sends pg command
*
* @dev: the device structure
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 65511d39d89b..25b1997a62cb 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -150,7 +150,7 @@ static inline u32 mei_me_d0i3c_read(const struct mei_device *dev)
u32 reg;
reg = mei_me_reg_read(to_me_hw(dev), H_D0I3C);
- trace_mei_reg_read(dev->dev, "H_D0I3C", H_CSR, reg);
+ trace_mei_reg_read(dev->dev, "H_D0I3C", H_D0I3C, reg);
return reg;
}
@@ -163,7 +163,7 @@ static inline u32 mei_me_d0i3c_read(const struct mei_device *dev)
*/
static inline void mei_me_d0i3c_write(struct mei_device *dev, u32 reg)
{
- trace_mei_reg_write(dev->dev, "H_D0I3C", H_CSR, reg);
+ trace_mei_reg_write(dev->dev, "H_D0I3C", H_D0I3C, reg);
mei_me_reg_write(to_me_hw(dev), H_D0I3C, reg);
}
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index e374661652cd..3edafc8d3ad4 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -329,10 +329,10 @@ void mei_stop(struct mei_device *dev)
{
dev_dbg(dev->dev, "stopping the device.\n");
- mei_cancel_work(dev);
-
mei_cl_bus_remove_devices(dev);
+ mei_cancel_work(dev);
+
mutex_lock(&dev->device_lock);
mei_wd_stop(dev);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index c418d7888994..64b568a0268d 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -21,6 +21,7 @@
#include <linux/fs.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include <linux/mei.h>
@@ -147,6 +148,9 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
cb->read_time = jiffies;
cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx);
list_move_tail(&cb->list, &complete_list->list);
+ } else {
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_request_autosuspend(dev->dev);
}
out:
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index e25ee16c658e..4250555d5e72 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -275,32 +275,33 @@ struct mei_cl {
struct mei_cl_device *cldev;
};
-/** struct mei_hw_ops
+/**
+ * struct mei_hw_ops - hw specific ops
*
* @host_is_ready : query for host readiness
-
+ *
* @hw_is_ready : query if hw is ready
* @hw_reset : reset hw
* @hw_start : start hw after reset
* @hw_config : configure hw
-
+ *
* @fw_status : get fw status registers
* @pg_state : power gating state of the device
* @pg_in_transition : is device now in pg transition
* @pg_is_enabled : is power gating enabled
-
+ *
* @intr_clear : clear pending interrupts
* @intr_enable : enable interrupts
* @intr_disable : disable interrupts
-
+ *
* @hbuf_free_slots : query for write buffer empty slots
* @hbuf_is_ready : query if write buffer is empty
* @hbuf_max_len : query for write buffer max len
-
+ *
* @write : write a message to FW
-
+ *
* @rdbuf_full_slots : query how many slots are filled
-
+ *
* @read_hdr : get first 4 bytes (header)
* @read : read a buffer from the FW
*/
@@ -340,7 +341,7 @@ struct mei_hw_ops {
/* MEI bus API*/
void mei_cl_bus_rescan(struct mei_device *bus);
-void mei_cl_dev_fixup(struct mei_cl_device *dev);
+void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
bool blocking);
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
@@ -528,7 +529,7 @@ struct mei_device {
DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
unsigned long me_client_index;
- u32 allow_fixed_address;
+ bool allow_fixed_address;
struct mei_cl wd_cl;
enum mei_wd_states wd_state;
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index e9f2f56c370d..40677df7f996 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -36,7 +36,7 @@ comment "Intel MIC Host Driver"
config INTEL_MIC_HOST
tristate "Intel MIC Host Driver"
- depends on 64BIT && PCI && X86 && INTEL_MIC_BUS && SCIF_BUS
+ depends on 64BIT && PCI && X86 && INTEL_MIC_BUS && SCIF_BUS && MIC_COSM
select VHOST_RING
help
This enables Host Driver support for the Intel Many Integrated
@@ -56,7 +56,7 @@ comment "Intel MIC Card Driver"
config INTEL_MIC_CARD
tristate "Intel MIC Card Driver"
- depends on 64BIT && X86 && INTEL_MIC_BUS && SCIF_BUS
+ depends on 64BIT && X86 && INTEL_MIC_BUS && SCIF_BUS && MIC_COSM
select VIRTIO
help
This enables card driver support for the Intel Many Integrated
@@ -74,7 +74,8 @@ comment "SCIF Driver"
config SCIF
tristate "SCIF Driver"
- depends on 64BIT && PCI && X86 && SCIF_BUS
+ depends on 64BIT && PCI && X86 && SCIF_BUS && IOMMU_SUPPORT
+ select IOMMU_IOVA
help
This enables SCIF Driver support for the Intel Many Integrated
Core (MIC) family of PCIe form factor coprocessor devices that
@@ -88,3 +89,21 @@ config SCIF
More information about the Intel MIC family as well as the Linux
OS and tools for MIC to use with this driver are available from
<http://software.intel.com/en-us/mic-developer>.
+
+comment "Intel MIC Coprocessor State Management (COSM) Drivers"
+
+config MIC_COSM
+ tristate "Intel MIC Coprocessor State Management (COSM) Drivers"
+ depends on 64BIT && PCI && X86 && SCIF
+ help
+ This enables COSM driver support for the Intel Many
+ Integrated Core (MIC) family of PCIe form factor coprocessor
+ devices. COSM drivers implement functions such as boot,
+ shutdown, reset and reboot of MIC devices.
+
+ If you are building a host kernel with an Intel MIC device then
+ say M (recommended) or Y, else say N. If unsure say N.
+
+ More information about the Intel MIC family as well as the Linux
+ OS and tools for MIC to use with this driver are available from
+ <http://software.intel.com/en-us/mic-developer>.
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
index a74042c58649..e288a1106738 100644
--- a/drivers/misc/mic/Makefile
+++ b/drivers/misc/mic/Makefile
@@ -6,3 +6,5 @@ obj-$(CONFIG_INTEL_MIC_HOST) += host/
obj-$(CONFIG_INTEL_MIC_CARD) += card/
obj-y += bus/
obj-$(CONFIG_SCIF) += scif/
+obj-$(CONFIG_MIC_COSM) += cosm/
+obj-$(CONFIG_MIC_COSM) += cosm_client/
diff --git a/drivers/misc/mic/bus/Makefile b/drivers/misc/mic/bus/Makefile
index 1ed37e234c96..761842b0d0bb 100644
--- a/drivers/misc/mic/bus/Makefile
+++ b/drivers/misc/mic/bus/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o
obj-$(CONFIG_SCIF_BUS) += scif_bus.o
+obj-$(CONFIG_MIC_COSM) += cosm_bus.o
diff --git a/drivers/misc/mic/bus/cosm_bus.c b/drivers/misc/mic/bus/cosm_bus.c
new file mode 100644
index 000000000000..d31d6c6e6cb1
--- /dev/null
+++ b/drivers/misc/mic/bus/cosm_bus.c
@@ -0,0 +1,141 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC COSM Bus Driver
+ */
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/idr.h>
+#include "cosm_bus.h"
+
+/* Unique numbering for cosm devices. */
+static DEFINE_IDA(cosm_index_ida);
+
+static int cosm_dev_probe(struct device *d)
+{
+ struct cosm_device *dev = dev_to_cosm(d);
+ struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
+
+ return drv->probe(dev);
+}
+
+static int cosm_dev_remove(struct device *d)
+{
+ struct cosm_device *dev = dev_to_cosm(d);
+ struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
+
+ drv->remove(dev);
+ return 0;
+}
+
+static struct bus_type cosm_bus = {
+ .name = "cosm_bus",
+ .probe = cosm_dev_probe,
+ .remove = cosm_dev_remove,
+};
+
+int cosm_register_driver(struct cosm_driver *driver)
+{
+ driver->driver.bus = &cosm_bus;
+ return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(cosm_register_driver);
+
+void cosm_unregister_driver(struct cosm_driver *driver)
+{
+ driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(cosm_unregister_driver);
+
+static inline void cosm_release_dev(struct device *d)
+{
+ struct cosm_device *cdev = dev_to_cosm(d);
+
+ kfree(cdev);
+}
+
+struct cosm_device *
+cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops)
+{
+ struct cosm_device *cdev;
+ int ret;
+
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ if (!cdev)
+ return ERR_PTR(-ENOMEM);
+
+ cdev->dev.parent = pdev;
+ cdev->dev.release = cosm_release_dev;
+ cdev->hw_ops = hw_ops;
+ dev_set_drvdata(&cdev->dev, cdev);
+ cdev->dev.bus = &cosm_bus;
+
+ /* Assign a unique device index and hence name */
+ ret = ida_simple_get(&cosm_index_ida, 0, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto free_cdev;
+
+ cdev->index = ret;
+ cdev->dev.id = ret;
+ dev_set_name(&cdev->dev, "cosm-dev%u", cdev->index);
+
+ ret = device_register(&cdev->dev);
+ if (ret)
+ goto ida_remove;
+ return cdev;
+ida_remove:
+ ida_simple_remove(&cosm_index_ida, cdev->index);
+free_cdev:
+ put_device(&cdev->dev);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(cosm_register_device);
+
+void cosm_unregister_device(struct cosm_device *dev)
+{
+ int index = dev->index; /* save for after device release */
+
+ device_unregister(&dev->dev);
+ ida_simple_remove(&cosm_index_ida, index);
+}
+EXPORT_SYMBOL_GPL(cosm_unregister_device);
+
+struct cosm_device *cosm_find_cdev_by_id(int id)
+{
+ struct device *dev = subsys_find_device_by_id(&cosm_bus, id, NULL);
+
+ return dev ? container_of(dev, struct cosm_device, dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(cosm_find_cdev_by_id);
+
+static int __init cosm_init(void)
+{
+ return bus_register(&cosm_bus);
+}
+
+static void __exit cosm_exit(void)
+{
+ bus_unregister(&cosm_bus);
+ ida_destroy(&cosm_index_ida);
+}
+
+core_initcall(cosm_init);
+module_exit(cosm_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC card OS state management bus driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/bus/cosm_bus.h b/drivers/misc/mic/bus/cosm_bus.h
new file mode 100644
index 000000000000..f7c57f266916
--- /dev/null
+++ b/drivers/misc/mic/bus/cosm_bus.h
@@ -0,0 +1,134 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC COSM Bus Driver
+ */
+#ifndef _COSM_BUS_H_
+#define _COSM_BUS_H_
+
+#include <linux/scif.h>
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+
+/**
+ * cosm_device - representation of a cosm device
+ *
+ * @attr_group: Pointer to list of sysfs attribute groups.
+ * @sdev: Device for sysfs entries.
+ * @state: MIC state.
+ * @shutdown_status: MIC status reported by card for shutdown/crashes.
+ * @shutdown_status_int: Internal shutdown status maintained by the driver
+ * @cosm_mutex: Mutex for synchronizing access to data structures.
+ * @reset_trigger_work: Work for triggering reset requests.
+ * @scif_work: Work for handling per device SCIF connections
+ * @cmdline: Kernel command line.
+ * @firmware: Firmware file name.
+ * @ramdisk: Ramdisk file name.
+ * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
+ * @log_buf_addr: Log buffer address for MIC.
+ * @log_buf_len: Log buffer length address for MIC.
+ * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
+ * @hw_ops: the hardware bus ops for this device.
+ * @dev: underlying device.
+ * @index: unique position on the cosm bus
+ * @dbg_dir: debug fs directory
+ * @newepd: new endpoint from scif accept to be assigned to this cdev
+ * @epd: SCIF endpoint for this cdev
+ * @heartbeat_watchdog_enable: if heartbeat watchdog is enabled for this cdev
+ * @sysfs_heartbeat_enable: sysfs setting for disabling heartbeat notification
+ */
+struct cosm_device {
+ const struct attribute_group **attr_group;
+ struct device *sdev;
+ u8 state;
+ u8 shutdown_status;
+ u8 shutdown_status_int;
+ struct mutex cosm_mutex;
+ struct work_struct reset_trigger_work;
+ struct work_struct scif_work;
+ char *cmdline;
+ char *firmware;
+ char *ramdisk;
+ char *bootmode;
+ void *log_buf_addr;
+ int *log_buf_len;
+ struct kernfs_node *state_sysfs;
+ struct cosm_hw_ops *hw_ops;
+ struct device dev;
+ int index;
+ struct dentry *dbg_dir;
+ scif_epd_t newepd;
+ scif_epd_t epd;
+ bool heartbeat_watchdog_enable;
+ bool sysfs_heartbeat_enable;
+};
+
+/**
+ * cosm_driver - operations for a cosm driver
+ *
+ * @driver: underlying device driver (populate name and owner).
+ * @probe: the function to call when a device is found. Returns 0 or -errno.
+ * @remove: the function to call when a device is removed.
+ */
+struct cosm_driver {
+ struct device_driver driver;
+ int (*probe)(struct cosm_device *dev);
+ void (*remove)(struct cosm_device *dev);
+};
+
+/**
+ * cosm_hw_ops - cosm bus ops
+ *
+ * @reset: trigger MIC reset
+ * @force_reset: force MIC reset
+ * @post_reset: inform MIC reset is complete
+ * @ready: is MIC ready for OS download
+ * @start: boot MIC
+ * @stop: prepare MIC for reset
+ * @family: return MIC HW family string
+ * @stepping: return MIC HW stepping string
+ * @aper: return MIC PCIe aperture
+ */
+struct cosm_hw_ops {
+ void (*reset)(struct cosm_device *cdev);
+ void (*force_reset)(struct cosm_device *cdev);
+ void (*post_reset)(struct cosm_device *cdev, enum mic_states state);
+ bool (*ready)(struct cosm_device *cdev);
+ int (*start)(struct cosm_device *cdev, int id);
+ void (*stop)(struct cosm_device *cdev, bool force);
+ ssize_t (*family)(struct cosm_device *cdev, char *buf);
+ ssize_t (*stepping)(struct cosm_device *cdev, char *buf);
+ struct mic_mw *(*aper)(struct cosm_device *cdev);
+};
+
+struct cosm_device *
+cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops);
+void cosm_unregister_device(struct cosm_device *dev);
+int cosm_register_driver(struct cosm_driver *drv);
+void cosm_unregister_driver(struct cosm_driver *drv);
+struct cosm_device *cosm_find_cdev_by_id(int id);
+
+static inline struct cosm_device *dev_to_cosm(struct device *dev)
+{
+ return container_of(dev, struct cosm_device, dev);
+}
+
+static inline struct cosm_driver *drv_to_cosm(struct device_driver *drv)
+{
+ return container_of(drv, struct cosm_driver, driver);
+}
+#endif /* _COSM_BUS_H */
diff --git a/drivers/misc/mic/bus/mic_bus.c b/drivers/misc/mic/bus/mic_bus.c
index 961ae90aae47..be37890abb93 100644
--- a/drivers/misc/mic/bus/mic_bus.c
+++ b/drivers/misc/mic/bus/mic_bus.c
@@ -25,9 +25,6 @@
#include <linux/idr.h>
#include <linux/mic_bus.h>
-/* Unique numbering for mbus devices. */
-static DEFINE_IDA(mbus_index_ida);
-
static ssize_t device_show(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -147,7 +144,8 @@ static void mbus_release_dev(struct device *d)
struct mbus_device *
mbus_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
- struct mbus_hw_ops *hw_ops, void __iomem *mmio_va)
+ struct mbus_hw_ops *hw_ops, int index,
+ void __iomem *mmio_va)
{
int ret;
struct mbus_device *mbdev;
@@ -166,13 +164,7 @@ mbus_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
mbdev->dev.release = mbus_release_dev;
mbdev->hw_ops = hw_ops;
mbdev->dev.bus = &mic_bus;
-
- /* Assign a unique device index and hence name. */
- ret = ida_simple_get(&mbus_index_ida, 0, 0, GFP_KERNEL);
- if (ret < 0)
- goto free_mbdev;
-
- mbdev->index = ret;
+ mbdev->index = index;
dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index);
/*
* device_register() causes the bus infrastructure to look for a
@@ -180,22 +172,17 @@ mbus_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
*/
ret = device_register(&mbdev->dev);
if (ret)
- goto ida_remove;
+ goto free_mbdev;
return mbdev;
-ida_remove:
- ida_simple_remove(&mbus_index_ida, mbdev->index);
free_mbdev:
- kfree(mbdev);
+ put_device(&mbdev->dev);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(mbus_register_device);
void mbus_unregister_device(struct mbus_device *mbdev)
{
- int index = mbdev->index; /* save for after device release */
-
device_unregister(&mbdev->dev);
- ida_simple_remove(&mbus_index_ida, index);
}
EXPORT_SYMBOL_GPL(mbus_unregister_device);
@@ -207,7 +194,6 @@ static int __init mbus_init(void)
static void __exit mbus_exit(void)
{
bus_unregister(&mic_bus);
- ida_destroy(&mbus_index_ida);
}
core_initcall(mbus_init);
diff --git a/drivers/misc/mic/bus/scif_bus.c b/drivers/misc/mic/bus/scif_bus.c
index 2da7ceed015d..ff6e01c25810 100644
--- a/drivers/misc/mic/bus/scif_bus.c
+++ b/drivers/misc/mic/bus/scif_bus.c
@@ -28,7 +28,6 @@ static ssize_t device_show(struct device *d,
return sprintf(buf, "0x%04x\n", dev->id.device);
}
-
static DEVICE_ATTR_RO(device);
static ssize_t vendor_show(struct device *d,
@@ -38,7 +37,6 @@ static ssize_t vendor_show(struct device *d,
return sprintf(buf, "0x%04x\n", dev->id.vendor);
}
-
static DEVICE_ATTR_RO(vendor);
static ssize_t modalias_show(struct device *d,
@@ -49,7 +47,6 @@ static ssize_t modalias_show(struct device *d,
return sprintf(buf, "scif:d%08Xv%08X\n",
dev->id.device, dev->id.vendor);
}
-
static DEVICE_ATTR_RO(modalias);
static struct attribute *scif_dev_attrs[] = {
@@ -144,7 +141,8 @@ struct scif_hw_dev *
scif_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
struct scif_hw_ops *hw_ops, u8 dnode, u8 snode,
struct mic_mw *mmio, struct mic_mw *aper, void *dp,
- void __iomem *rdp, struct dma_chan **chan, int num_chan)
+ void __iomem *rdp, struct dma_chan **chan, int num_chan,
+ bool card_rel_da)
{
int ret;
struct scif_hw_dev *sdev;
@@ -171,6 +169,7 @@ scif_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
dma_set_mask(&sdev->dev, DMA_BIT_MASK(64));
sdev->dma_ch = chan;
sdev->num_dma_ch = num_chan;
+ sdev->card_rel_da = card_rel_da;
dev_set_name(&sdev->dev, "scif-dev%u", sdev->dnode);
/*
* device_register() causes the bus infrastructure to look for a
@@ -181,7 +180,7 @@ scif_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
goto free_sdev;
return sdev;
free_sdev:
- kfree(sdev);
+ put_device(&sdev->dev);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(scif_register_device);
diff --git a/drivers/misc/mic/bus/scif_bus.h b/drivers/misc/mic/bus/scif_bus.h
index 335a228a8236..94f29ac608b6 100644
--- a/drivers/misc/mic/bus/scif_bus.h
+++ b/drivers/misc/mic/bus/scif_bus.h
@@ -46,6 +46,8 @@ struct scif_hw_dev_id {
* @rdp - Remote device page
* @dma_ch - Array of DMA channels
* @num_dma_ch - Number of DMA channels available
+ * @card_rel_da - Set to true if DMA addresses programmed in the DMA engine
+ * are relative to the card point of view
*/
struct scif_hw_dev {
struct scif_hw_ops *hw_ops;
@@ -59,6 +61,7 @@ struct scif_hw_dev {
void __iomem *rdp;
struct dma_chan **dma_ch;
int num_dma_ch;
+ bool card_rel_da;
};
/**
@@ -114,7 +117,8 @@ scif_register_device(struct device *pdev, int id,
struct scif_hw_ops *hw_ops, u8 dnode, u8 snode,
struct mic_mw *mmio, struct mic_mw *aper,
void *dp, void __iomem *rdp,
- struct dma_chan **chan, int num_chan);
+ struct dma_chan **chan, int num_chan,
+ bool card_rel_da);
void scif_unregister_device(struct scif_hw_dev *sdev);
static inline struct scif_hw_dev *dev_to_scif(struct device *dev)
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
index 6338908b2252..d0edaf7e0cd5 100644
--- a/drivers/misc/mic/card/mic_device.c
+++ b/drivers/misc/mic/card/mic_device.c
@@ -37,71 +37,6 @@
#include "mic_virtio.h"
static struct mic_driver *g_drv;
-static struct mic_irq *shutdown_cookie;
-
-static void mic_notify_host(u8 state)
-{
- struct mic_driver *mdrv = g_drv;
- struct mic_bootparam __iomem *bootparam = mdrv->dp;
-
- iowrite8(state, &bootparam->shutdown_status);
- dev_dbg(mdrv->dev, "%s %d system_state %d\n",
- __func__, __LINE__, state);
- mic_send_intr(&mdrv->mdev, ioread8(&bootparam->c2h_shutdown_db));
-}
-
-static int mic_panic_event(struct notifier_block *this, unsigned long event,
- void *ptr)
-{
- struct mic_driver *mdrv = g_drv;
- struct mic_bootparam __iomem *bootparam = mdrv->dp;
-
- iowrite8(-1, &bootparam->h2c_config_db);
- iowrite8(-1, &bootparam->h2c_shutdown_db);
- mic_notify_host(MIC_CRASHED);
- return NOTIFY_DONE;
-}
-
-static struct notifier_block mic_panic = {
- .notifier_call = mic_panic_event,
-};
-
-static irqreturn_t mic_shutdown_isr(int irq, void *data)
-{
- struct mic_driver *mdrv = g_drv;
- struct mic_bootparam __iomem *bootparam = mdrv->dp;
-
- mic_ack_interrupt(&g_drv->mdev);
- if (ioread8(&bootparam->shutdown_card))
- orderly_poweroff(true);
- return IRQ_HANDLED;
-}
-
-static int mic_shutdown_init(void)
-{
- int rc = 0;
- struct mic_driver *mdrv = g_drv;
- struct mic_bootparam __iomem *bootparam = mdrv->dp;
- int shutdown_db;
-
- shutdown_db = mic_next_card_db();
- shutdown_cookie = mic_request_card_irq(mic_shutdown_isr, NULL,
- "Shutdown", mdrv, shutdown_db);
- if (IS_ERR(shutdown_cookie))
- rc = PTR_ERR(shutdown_cookie);
- else
- iowrite8(shutdown_db, &bootparam->h2c_shutdown_db);
- return rc;
-}
-
-static void mic_shutdown_uninit(void)
-{
- struct mic_driver *mdrv = g_drv;
- struct mic_bootparam __iomem *bootparam = mdrv->dp;
-
- iowrite8(-1, &bootparam->h2c_shutdown_db);
- mic_free_card_irq(shutdown_cookie, mdrv);
-}
static int __init mic_dp_init(void)
{
@@ -359,11 +294,7 @@ int __init mic_driver_init(struct mic_driver *mdrv)
u8 node_id;
g_drv = mdrv;
- /*
- * Unloading the card module is not supported. The MIC card module
- * handles fundamental operations like host/card initiated shutdowns
- * and informing the host about card crashes and cannot be unloaded.
- */
+ /* Unloading the card module is not supported. */
if (!try_module_get(mdrv->dev->driver->owner)) {
rc = -ENODEV;
goto done;
@@ -374,12 +305,9 @@ int __init mic_driver_init(struct mic_driver *mdrv)
rc = mic_init_irq();
if (rc)
goto dp_uninit;
- rc = mic_shutdown_init();
- if (rc)
- goto irq_uninit;
if (!mic_request_dma_chans(mdrv)) {
rc = -ENODEV;
- goto shutdown_uninit;
+ goto irq_uninit;
}
rc = mic_devices_init(mdrv);
if (rc)
@@ -390,21 +318,18 @@ int __init mic_driver_init(struct mic_driver *mdrv)
NULL, &scif_hw_ops,
0, node_id, &mdrv->mdev.mmio, NULL,
NULL, mdrv->dp, mdrv->dma_ch,
- mdrv->num_dma_ch);
+ mdrv->num_dma_ch, true);
if (IS_ERR(mdrv->scdev)) {
rc = PTR_ERR(mdrv->scdev);
goto device_uninit;
}
mic_create_card_debug_dir(mdrv);
- atomic_notifier_chain_register(&panic_notifier_list, &mic_panic);
done:
return rc;
device_uninit:
mic_devices_uninit(mdrv);
dma_free:
mic_free_dma_chans(mdrv);
-shutdown_uninit:
- mic_shutdown_uninit();
irq_uninit:
mic_uninit_irq();
dp_uninit:
@@ -425,13 +350,6 @@ void mic_driver_uninit(struct mic_driver *mdrv)
scif_unregister_device(mdrv->scdev);
mic_devices_uninit(mdrv);
mic_free_dma_chans(mdrv);
- /*
- * Inform the host about the shutdown status i.e. poweroff/restart etc.
- * The module cannot be unloaded so the only code path to call
- * mic_devices_uninit(..) is the shutdown callback.
- */
- mic_notify_host(system_state);
- mic_shutdown_uninit();
mic_uninit_irq();
mic_dp_uninit();
module_put(mdrv->dev->driver->owner);
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
index 77fd41781c2e..b2958ce2368c 100644
--- a/drivers/misc/mic/card/mic_x100.c
+++ b/drivers/misc/mic/card/mic_x100.c
@@ -261,7 +261,7 @@ static int __init mic_probe(struct platform_device *pdev)
mic_hw_intr_init(mdrv);
platform_set_drvdata(pdev, mdrv);
mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC,
- NULL, &mbus_hw_ops,
+ NULL, &mbus_hw_ops, 0,
mdrv->mdev.mmio.va);
if (IS_ERR(mdrv->dma_mbdev)) {
rc = PTR_ERR(mdrv->dma_mbdev);
diff --git a/drivers/misc/mic/common/mic_dev.h b/drivers/misc/mic/common/mic_dev.h
index 0b58c46045dc..50776772ebdf 100644
--- a/drivers/misc/mic/common/mic_dev.h
+++ b/drivers/misc/mic/common/mic_dev.h
@@ -21,6 +21,19 @@
#ifndef __MIC_DEV_H__
#define __MIC_DEV_H__
+/* The maximum number of MIC devices supported in a single host system. */
+#define MIC_MAX_NUM_DEVS 128
+
+/**
+ * enum mic_hw_family - The hardware family to which a device belongs.
+ */
+enum mic_hw_family {
+ MIC_FAMILY_X100 = 0,
+ MIC_FAMILY_X200,
+ MIC_FAMILY_UNKNOWN,
+ MIC_FAMILY_LAST
+};
+
/**
* struct mic_mw - MIC memory window
*
diff --git a/drivers/misc/mic/cosm/Makefile b/drivers/misc/mic/cosm/Makefile
new file mode 100644
index 000000000000..b85d4d49df46
--- /dev/null
+++ b/drivers/misc/mic/cosm/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile - Intel MIC Coprocessor State Management (COSM) Driver
+# Copyright(c) 2015, Intel Corporation.
+#
+obj-$(CONFIG_MIC_COSM) += mic_cosm.o
+
+mic_cosm-objs := cosm_main.o
+mic_cosm-objs += cosm_debugfs.o
+mic_cosm-objs += cosm_sysfs.o
+mic_cosm-objs += cosm_scif_server.o
diff --git a/drivers/misc/mic/cosm/cosm_debugfs.c b/drivers/misc/mic/cosm/cosm_debugfs.c
new file mode 100644
index 000000000000..216cb3cd2fe3
--- /dev/null
+++ b/drivers/misc/mic/cosm/cosm_debugfs.c
@@ -0,0 +1,156 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC Coprocessor State Management (COSM) Driver
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include "cosm_main.h"
+
+/* Debugfs parent dir */
+static struct dentry *cosm_dbg;
+
+/**
+ * cosm_log_buf_show - Display MIC kernel log buffer
+ *
+ * log_buf addr/len is read from System.map by user space
+ * and populated in sysfs entries.
+ */
+static int cosm_log_buf_show(struct seq_file *s, void *unused)
+{
+ void __iomem *log_buf_va;
+ int __iomem *log_buf_len_va;
+ struct cosm_device *cdev = s->private;
+ void *kva;
+ int size;
+ u64 aper_offset;
+
+ if (!cdev || !cdev->log_buf_addr || !cdev->log_buf_len)
+ goto done;
+
+ mutex_lock(&cdev->cosm_mutex);
+ switch (cdev->state) {
+ case MIC_BOOTING:
+ case MIC_ONLINE:
+ case MIC_SHUTTING_DOWN:
+ break;
+ default:
+ goto unlock;
+ }
+
+ /*
+ * Card kernel will never be relocated and any kernel text/data mapping
+ * can be translated to phys address by subtracting __START_KERNEL_map.
+ */
+ aper_offset = (u64)cdev->log_buf_len - __START_KERNEL_map;
+ log_buf_len_va = cdev->hw_ops->aper(cdev)->va + aper_offset;
+ aper_offset = (u64)cdev->log_buf_addr - __START_KERNEL_map;
+ log_buf_va = cdev->hw_ops->aper(cdev)->va + aper_offset;
+
+ size = ioread32(log_buf_len_va);
+ kva = kmalloc(size, GFP_KERNEL);
+ if (!kva)
+ goto unlock;
+
+ memcpy_fromio(kva, log_buf_va, size);
+ seq_write(s, kva, size);
+ kfree(kva);
+unlock:
+ mutex_unlock(&cdev->cosm_mutex);
+done:
+ return 0;
+}
+
+static int cosm_log_buf_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cosm_log_buf_show, inode->i_private);
+}
+
+static const struct file_operations log_buf_ops = {
+ .owner = THIS_MODULE,
+ .open = cosm_log_buf_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release
+};
+
+/**
+ * cosm_force_reset_show - Force MIC reset
+ *
+ * Invokes the force_reset COSM bus op instead of the standard reset
+ * op in case a force reset of the MIC device is required
+ */
+static int cosm_force_reset_show(struct seq_file *s, void *pos)
+{
+ struct cosm_device *cdev = s->private;
+
+ cosm_stop(cdev, true);
+ return 0;
+}
+
+static int cosm_force_reset_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cosm_force_reset_show, inode->i_private);
+}
+
+static const struct file_operations force_reset_ops = {
+ .owner = THIS_MODULE,
+ .open = cosm_force_reset_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release
+};
+
+void cosm_create_debug_dir(struct cosm_device *cdev)
+{
+ char name[16];
+
+ if (!cosm_dbg)
+ return;
+
+ scnprintf(name, sizeof(name), "mic%d", cdev->index);
+ cdev->dbg_dir = debugfs_create_dir(name, cosm_dbg);
+ if (!cdev->dbg_dir)
+ return;
+
+ debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev, &log_buf_ops);
+ debugfs_create_file("force_reset", 0444, cdev->dbg_dir, cdev,
+ &force_reset_ops);
+}
+
+void cosm_delete_debug_dir(struct cosm_device *cdev)
+{
+ if (!cdev->dbg_dir)
+ return;
+
+ debugfs_remove_recursive(cdev->dbg_dir);
+}
+
+void cosm_init_debugfs(void)
+{
+ cosm_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (!cosm_dbg)
+ pr_err("can't create debugfs dir\n");
+}
+
+void cosm_exit_debugfs(void)
+{
+ debugfs_remove(cosm_dbg);
+}
diff --git a/drivers/misc/mic/cosm/cosm_main.c b/drivers/misc/mic/cosm/cosm_main.c
new file mode 100644
index 000000000000..4b4b356c797d
--- /dev/null
+++ b/drivers/misc/mic/cosm/cosm_main.c
@@ -0,0 +1,388 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC Coprocessor State Management (COSM) Driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/cred.h>
+#include "cosm_main.h"
+
+static const char cosm_driver_name[] = "mic";
+
+/* COSM ID allocator */
+static struct ida g_cosm_ida;
+/* Class of MIC devices for sysfs accessibility. */
+static struct class *g_cosm_class;
+/* Number of MIC devices */
+static atomic_t g_num_dev;
+
+/**
+ * cosm_hw_reset - Issue a HW reset for the MIC device
+ * @cdev: pointer to cosm_device instance
+ */
+static void cosm_hw_reset(struct cosm_device *cdev, bool force)
+{
+ int i;
+
+#define MIC_RESET_TO (45)
+ if (force && cdev->hw_ops->force_reset)
+ cdev->hw_ops->force_reset(cdev);
+ else
+ cdev->hw_ops->reset(cdev);
+
+ for (i = 0; i < MIC_RESET_TO; i++) {
+ if (cdev->hw_ops->ready(cdev)) {
+ cosm_set_state(cdev, MIC_READY);
+ return;
+ }
+ /*
+ * Resets typically take 10s of seconds to complete.
+ * Since an MMIO read is required to check if the
+ * firmware is ready or not, a 1 second delay works nicely.
+ */
+ msleep(1000);
+ }
+ cosm_set_state(cdev, MIC_RESET_FAILED);
+}
+
+/**
+ * cosm_start - Start the MIC
+ * @cdev: pointer to cosm_device instance
+ *
+ * This function prepares an MIC for boot and initiates boot.
+ * RETURNS: An appropriate -ERRNO error value on error, or 0 for success.
+ */
+int cosm_start(struct cosm_device *cdev)
+{
+ const struct cred *orig_cred;
+ struct cred *override_cred;
+ int rc;
+
+ mutex_lock(&cdev->cosm_mutex);
+ if (!cdev->bootmode) {
+ dev_err(&cdev->dev, "%s %d bootmode not set\n",
+ __func__, __LINE__);
+ rc = -EINVAL;
+ goto unlock_ret;
+ }
+retry:
+ if (cdev->state != MIC_READY) {
+ dev_err(&cdev->dev, "%s %d MIC state not READY\n",
+ __func__, __LINE__);
+ rc = -EINVAL;
+ goto unlock_ret;
+ }
+ if (!cdev->hw_ops->ready(cdev)) {
+ cosm_hw_reset(cdev, false);
+ /*
+ * The state will either be MIC_READY if the reset succeeded
+ * or MIC_RESET_FAILED if the firmware reset failed.
+ */
+ goto retry;
+ }
+
+ /*
+ * Set credentials to root to allow non-root user to download initramsfs
+ * with 600 permissions
+ */
+ override_cred = prepare_creds();
+ if (!override_cred) {
+ dev_err(&cdev->dev, "%s %d prepare_creds failed\n",
+ __func__, __LINE__);
+ rc = -ENOMEM;
+ goto unlock_ret;
+ }
+ override_cred->fsuid = GLOBAL_ROOT_UID;
+ orig_cred = override_creds(override_cred);
+
+ rc = cdev->hw_ops->start(cdev, cdev->index);
+
+ revert_creds(orig_cred);
+ put_cred(override_cred);
+ if (rc)
+ goto unlock_ret;
+
+ /*
+ * If linux is being booted, card is treated 'online' only
+ * when the scif interface in the card is up. If anything else
+ * is booted, we set card to 'online' immediately.
+ */
+ if (!strcmp(cdev->bootmode, "linux"))
+ cosm_set_state(cdev, MIC_BOOTING);
+ else
+ cosm_set_state(cdev, MIC_ONLINE);
+unlock_ret:
+ mutex_unlock(&cdev->cosm_mutex);
+ if (rc)
+ dev_err(&cdev->dev, "cosm_start failed rc %d\n", rc);
+ return rc;
+}
+
+/**
+ * cosm_stop - Prepare the MIC for reset and trigger reset
+ * @cdev: pointer to cosm_device instance
+ * @force: force a MIC to reset even if it is already reset and ready.
+ *
+ * RETURNS: None
+ */
+void cosm_stop(struct cosm_device *cdev, bool force)
+{
+ mutex_lock(&cdev->cosm_mutex);
+ if (cdev->state != MIC_READY || force) {
+ /*
+ * Don't call hw_ops if they have been called previously.
+ * stop(..) calls device_unregister and will crash the system if
+ * called multiple times.
+ */
+ bool call_hw_ops = cdev->state != MIC_RESET_FAILED &&
+ cdev->state != MIC_READY;
+
+ if (cdev->state != MIC_RESETTING)
+ cosm_set_state(cdev, MIC_RESETTING);
+ cdev->heartbeat_watchdog_enable = false;
+ if (call_hw_ops)
+ cdev->hw_ops->stop(cdev, force);
+ cosm_hw_reset(cdev, force);
+ cosm_set_shutdown_status(cdev, MIC_NOP);
+ if (call_hw_ops && cdev->hw_ops->post_reset)
+ cdev->hw_ops->post_reset(cdev, cdev->state);
+ }
+ mutex_unlock(&cdev->cosm_mutex);
+ flush_work(&cdev->scif_work);
+}
+
+/**
+ * cosm_reset_trigger_work - Trigger MIC reset
+ * @work: The work structure
+ *
+ * This work is scheduled whenever the host wants to reset the MIC.
+ */
+static void cosm_reset_trigger_work(struct work_struct *work)
+{
+ struct cosm_device *cdev = container_of(work, struct cosm_device,
+ reset_trigger_work);
+ cosm_stop(cdev, false);
+}
+
+/**
+ * cosm_reset - Schedule MIC reset
+ * @cdev: pointer to cosm_device instance
+ *
+ * RETURNS: An -EINVAL if the card is already READY or 0 for success.
+ */
+int cosm_reset(struct cosm_device *cdev)
+{
+ int rc = 0;
+
+ mutex_lock(&cdev->cosm_mutex);
+ if (cdev->state != MIC_READY) {
+ cosm_set_state(cdev, MIC_RESETTING);
+ schedule_work(&cdev->reset_trigger_work);
+ } else {
+ dev_err(&cdev->dev, "%s %d MIC is READY\n", __func__, __LINE__);
+ rc = -EINVAL;
+ }
+ mutex_unlock(&cdev->cosm_mutex);
+ return rc;
+}
+
+/**
+ * cosm_shutdown - Initiate MIC shutdown.
+ * @cdev: pointer to cosm_device instance
+ *
+ * RETURNS: None
+ */
+int cosm_shutdown(struct cosm_device *cdev)
+{
+ struct cosm_msg msg = { .id = COSM_MSG_SHUTDOWN };
+ int rc = 0;
+
+ mutex_lock(&cdev->cosm_mutex);
+ if (cdev->state != MIC_ONLINE) {
+ rc = -EINVAL;
+ dev_err(&cdev->dev, "%s %d skipping shutdown in state: %s\n",
+ __func__, __LINE__, cosm_state_string[cdev->state]);
+ goto err;
+ }
+
+ if (!cdev->epd) {
+ rc = -ENOTCONN;
+ dev_err(&cdev->dev, "%s %d scif endpoint not connected rc %d\n",
+ __func__, __LINE__, rc);
+ goto err;
+ }
+
+ rc = scif_send(cdev->epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
+ if (rc < 0) {
+ dev_err(&cdev->dev, "%s %d scif_send failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto err;
+ }
+ cdev->heartbeat_watchdog_enable = false;
+ cosm_set_state(cdev, MIC_SHUTTING_DOWN);
+ rc = 0;
+err:
+ mutex_unlock(&cdev->cosm_mutex);
+ return rc;
+}
+
+static int cosm_driver_probe(struct cosm_device *cdev)
+{
+ int rc;
+
+ /* Initialize SCIF server at first probe */
+ if (atomic_add_return(1, &g_num_dev) == 1) {
+ rc = cosm_scif_init();
+ if (rc)
+ goto scif_exit;
+ }
+ mutex_init(&cdev->cosm_mutex);
+ INIT_WORK(&cdev->reset_trigger_work, cosm_reset_trigger_work);
+ INIT_WORK(&cdev->scif_work, cosm_scif_work);
+ cdev->sysfs_heartbeat_enable = true;
+ cosm_sysfs_init(cdev);
+ cdev->sdev = device_create_with_groups(g_cosm_class, cdev->dev.parent,
+ MKDEV(0, cdev->index), cdev, cdev->attr_group,
+ "mic%d", cdev->index);
+ if (IS_ERR(cdev->sdev)) {
+ rc = PTR_ERR(cdev->sdev);
+ dev_err(&cdev->dev, "device_create_with_groups failed rc %d\n",
+ rc);
+ goto scif_exit;
+ }
+
+ cdev->state_sysfs = sysfs_get_dirent(cdev->sdev->kobj.sd,
+ "state");
+ if (!cdev->state_sysfs) {
+ rc = -ENODEV;
+ dev_err(&cdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
+ goto destroy_device;
+ }
+ cosm_create_debug_dir(cdev);
+ return 0;
+destroy_device:
+ device_destroy(g_cosm_class, MKDEV(0, cdev->index));
+scif_exit:
+ if (atomic_dec_and_test(&g_num_dev))
+ cosm_scif_exit();
+ return rc;
+}
+
+static void cosm_driver_remove(struct cosm_device *cdev)
+{
+ cosm_delete_debug_dir(cdev);
+ sysfs_put(cdev->state_sysfs);
+ device_destroy(g_cosm_class, MKDEV(0, cdev->index));
+ flush_work(&cdev->reset_trigger_work);
+ cosm_stop(cdev, false);
+ if (atomic_dec_and_test(&g_num_dev))
+ cosm_scif_exit();
+
+ /* These sysfs entries might have allocated */
+ kfree(cdev->cmdline);
+ kfree(cdev->firmware);
+ kfree(cdev->ramdisk);
+ kfree(cdev->bootmode);
+}
+
+static int cosm_suspend(struct device *dev)
+{
+ struct cosm_device *cdev = dev_to_cosm(dev);
+
+ mutex_lock(&cdev->cosm_mutex);
+ switch (cdev->state) {
+ /**
+ * Suspend/freeze hooks in userspace have already shutdown the card.
+ * Card should be 'ready' in most cases. It is however possible that
+ * some userspace application initiated a boot. In those cases, we
+ * simply reset the card.
+ */
+ case MIC_ONLINE:
+ case MIC_BOOTING:
+ case MIC_SHUTTING_DOWN:
+ mutex_unlock(&cdev->cosm_mutex);
+ cosm_stop(cdev, false);
+ break;
+ default:
+ mutex_unlock(&cdev->cosm_mutex);
+ break;
+ }
+ return 0;
+}
+
+static const struct dev_pm_ops cosm_pm_ops = {
+ .suspend = cosm_suspend,
+ .freeze = cosm_suspend
+};
+
+static struct cosm_driver cosm_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .pm = &cosm_pm_ops,
+ },
+ .probe = cosm_driver_probe,
+ .remove = cosm_driver_remove
+};
+
+static int __init cosm_init(void)
+{
+ int ret;
+
+ cosm_init_debugfs();
+
+ g_cosm_class = class_create(THIS_MODULE, cosm_driver_name);
+ if (IS_ERR(g_cosm_class)) {
+ ret = PTR_ERR(g_cosm_class);
+ pr_err("class_create failed ret %d\n", ret);
+ goto cleanup_debugfs;
+ }
+
+ ida_init(&g_cosm_ida);
+ ret = cosm_register_driver(&cosm_driver);
+ if (ret) {
+ pr_err("cosm_register_driver failed ret %d\n", ret);
+ goto ida_destroy;
+ }
+ return 0;
+ida_destroy:
+ ida_destroy(&g_cosm_ida);
+ class_destroy(g_cosm_class);
+cleanup_debugfs:
+ cosm_exit_debugfs();
+ return ret;
+}
+
+static void __exit cosm_exit(void)
+{
+ cosm_unregister_driver(&cosm_driver);
+ ida_destroy(&g_cosm_ida);
+ class_destroy(g_cosm_class);
+ cosm_exit_debugfs();
+}
+
+module_init(cosm_init);
+module_exit(cosm_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC Coprocessor State Management (COSM) Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/cosm/cosm_main.h b/drivers/misc/mic/cosm/cosm_main.h
new file mode 100644
index 000000000000..f01156fca881
--- /dev/null
+++ b/drivers/misc/mic/cosm/cosm_main.h
@@ -0,0 +1,70 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC Coprocessor State Management (COSM) Driver
+ *
+ */
+#ifndef _COSM_COSM_H_
+#define _COSM_COSM_H_
+
+#include <linux/scif.h>
+#include "../bus/cosm_bus.h"
+
+#define COSM_HEARTBEAT_SEND_SEC 30
+#define SCIF_COSM_LISTEN_PORT 201
+
+/**
+ * enum COSM msg id's
+ * @COSM_MSG_SHUTDOWN: host->card trigger shutdown
+ * @COSM_MSG_SYNC_TIME: host->card send host time to card to sync time
+ * @COSM_MSG_HEARTBEAT: card->host heartbeat
+ * @COSM_MSG_SHUTDOWN_STATUS: card->host with shutdown status as payload
+ */
+enum cosm_msg_id {
+ COSM_MSG_SHUTDOWN,
+ COSM_MSG_SYNC_TIME,
+ COSM_MSG_HEARTBEAT,
+ COSM_MSG_SHUTDOWN_STATUS,
+};
+
+struct cosm_msg {
+ u64 id;
+ union {
+ u64 shutdown_status;
+ struct timespec64 timespec;
+ };
+};
+
+extern const char * const cosm_state_string[];
+extern const char * const cosm_shutdown_status_string[];
+
+void cosm_sysfs_init(struct cosm_device *cdev);
+int cosm_start(struct cosm_device *cdev);
+void cosm_stop(struct cosm_device *cdev, bool force);
+int cosm_reset(struct cosm_device *cdev);
+int cosm_shutdown(struct cosm_device *cdev);
+void cosm_set_state(struct cosm_device *cdev, u8 state);
+void cosm_set_shutdown_status(struct cosm_device *cdev, u8 status);
+void cosm_init_debugfs(void);
+void cosm_exit_debugfs(void);
+void cosm_create_debug_dir(struct cosm_device *cdev);
+void cosm_delete_debug_dir(struct cosm_device *cdev);
+int cosm_scif_init(void);
+void cosm_scif_exit(void);
+void cosm_scif_work(struct work_struct *work);
+
+#endif
diff --git a/drivers/misc/mic/cosm/cosm_scif_server.c b/drivers/misc/mic/cosm/cosm_scif_server.c
new file mode 100644
index 000000000000..5696df4326b5
--- /dev/null
+++ b/drivers/misc/mic/cosm/cosm_scif_server.c
@@ -0,0 +1,405 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC Coprocessor State Management (COSM) Driver
+ *
+ */
+#include <linux/kthread.h>
+#include "cosm_main.h"
+
+/*
+ * The COSM driver uses SCIF to communicate between the management node and the
+ * MIC cards. SCIF is used to (a) Send a shutdown command to the card (b)
+ * receive a shutdown status back from the card upon completion of shutdown and
+ * (c) receive periodic heartbeat messages from the card used to deduce if the
+ * card has crashed.
+ *
+ * A COSM server consisting of a SCIF listening endpoint waits for incoming
+ * connections from the card. Upon acceptance of the connection, a separate
+ * work-item is scheduled to handle SCIF message processing for that card. The
+ * life-time of this work-item is therefore the time from which the connection
+ * from a card is accepted to the time at which the connection is closed. A new
+ * work-item starts each time the card boots and is alive till the card (a)
+ * shuts down (b) is reset (c) crashes (d) cosm_client driver on the card is
+ * unloaded.
+ *
+ * From the point of view of COSM interactions with SCIF during card
+ * shutdown, reset and crash are as follows:
+ *
+ * Card shutdown
+ * -------------
+ * 1. COSM client on the card invokes orderly_poweroff() in response to SHUTDOWN
+ * message from the host.
+ * 2. Card driver shutdown callback invokes scif_unregister_device(..) resulting
+ * in scif_remove(..) getting called on the card
+ * 3. scif_remove -> scif_stop -> scif_handle_remove_node ->
+ * scif_peer_unregister_device -> device_unregister for the host peer device
+ * 4. During device_unregister remove(..) method of cosm_client is invoked which
+ * closes the COSM SCIF endpoint on the card. This results in a SCIF_DISCNCT
+ * message being sent to host SCIF. SCIF_DISCNCT message processing on the
+ * host SCIF sets the host COSM SCIF endpoint state to DISCONNECTED and wakes
+ * up the host COSM thread blocked in scif_poll(..) resulting in
+ * scif_poll(..) returning POLLHUP.
+ * 5. On the card, scif_peer_release_dev is next called which results in an
+ * SCIF_EXIT message being sent to the host and after receiving the
+ * SCIF_EXIT_ACK from the host the peer device teardown on the card is
+ * complete.
+ * 6. As part of the SCIF_EXIT message processing on the host, host sends a
+ * SCIF_REMOVE_NODE to itself corresponding to the card being removed. This
+ * starts a similar SCIF peer device teardown sequence on the host
+ * corresponding to the card being shut down.
+ *
+ * Card reset
+ * ----------
+ * The case of interest here is when the card has not been previously shut down
+ * since most of the steps below are skipped in that case:
+
+ * 1. cosm_stop(..) invokes hw_ops->stop(..) method of the base PCIe driver
+ * which unregisters the SCIF HW device resulting in scif_remove(..) being
+ * called on the host.
+ * 2. scif_remove(..) calls scif_disconnect_node(..) which results in a
+ * SCIF_EXIT message being sent to the card.
+ * 3. The card executes scif_stop() as part of SCIF_EXIT message
+ * processing. This results in the COSM endpoint on the card being closed and
+ * the SCIF host peer device on the card getting unregistered similar to
+ * steps 3, 4 and 5 for the card shutdown case above. scif_poll(..) on the
+ * host returns POLLHUP as a result.
+ * 4. On the host, card peer device unregister and SCIF HW remove(..) also
+ * subsequently complete.
+ *
+ * Card crash
+ * ----------
+ * If a reset is issued after the card has crashed, there is no SCIF_DISCNT
+ * message from the card which would result in scif_poll(..) returning
+ * POLLHUP. In this case when the host SCIF driver sends a SCIF_REMOVE_NODE
+ * message to itself resulting in the card SCIF peer device being unregistered,
+ * this results in a scif_peer_release_dev -> scif_cleanup_scifdev->
+ * scif_invalidate_ep call sequence which sets the endpoint state to
+ * DISCONNECTED and results in scif_poll(..) returning POLLHUP.
+ */
+
+#define COSM_SCIF_BACKLOG 16
+#define COSM_HEARTBEAT_CHECK_DELTA_SEC 10
+#define COSM_HEARTBEAT_TIMEOUT_SEC \
+ (COSM_HEARTBEAT_SEND_SEC + COSM_HEARTBEAT_CHECK_DELTA_SEC)
+#define COSM_HEARTBEAT_TIMEOUT_MSEC (COSM_HEARTBEAT_TIMEOUT_SEC * MSEC_PER_SEC)
+
+static struct task_struct *server_thread;
+static scif_epd_t listen_epd;
+
+/* Publish MIC card's shutdown status to user space MIC daemon */
+static void cosm_update_mic_status(struct cosm_device *cdev)
+{
+ if (cdev->shutdown_status_int != MIC_NOP) {
+ cosm_set_shutdown_status(cdev, cdev->shutdown_status_int);
+ cdev->shutdown_status_int = MIC_NOP;
+ }
+}
+
+/* Store MIC card's shutdown status internally when it is received */
+static void cosm_shutdown_status_int(struct cosm_device *cdev,
+ enum mic_status shutdown_status)
+{
+ switch (shutdown_status) {
+ case MIC_HALTED:
+ case MIC_POWER_OFF:
+ case MIC_RESTART:
+ case MIC_CRASHED:
+ break;
+ default:
+ dev_err(&cdev->dev, "%s %d Unexpected shutdown_status %d\n",
+ __func__, __LINE__, shutdown_status);
+ return;
+ };
+ cdev->shutdown_status_int = shutdown_status;
+ cdev->heartbeat_watchdog_enable = false;
+
+ if (cdev->state != MIC_SHUTTING_DOWN)
+ cosm_set_state(cdev, MIC_SHUTTING_DOWN);
+}
+
+/* Non-blocking recv. Read and process all available messages */
+static void cosm_scif_recv(struct cosm_device *cdev)
+{
+ struct cosm_msg msg;
+ int rc;
+
+ while (1) {
+ rc = scif_recv(cdev->epd, &msg, sizeof(msg), 0);
+ if (!rc) {
+ break;
+ } else if (rc < 0) {
+ dev_dbg(&cdev->dev, "%s: %d rc %d\n",
+ __func__, __LINE__, rc);
+ break;
+ }
+ dev_dbg(&cdev->dev, "%s: %d rc %d id 0x%llx\n",
+ __func__, __LINE__, rc, msg.id);
+
+ switch (msg.id) {
+ case COSM_MSG_SHUTDOWN_STATUS:
+ cosm_shutdown_status_int(cdev, msg.shutdown_status);
+ break;
+ case COSM_MSG_HEARTBEAT:
+ /* Nothing to do, heartbeat only unblocks scif_poll */
+ break;
+ default:
+ dev_err(&cdev->dev, "%s: %d unknown msg.id %lld\n",
+ __func__, __LINE__, msg.id);
+ break;
+ }
+ }
+}
+
+/* Publish crashed status for this MIC card */
+static void cosm_set_crashed(struct cosm_device *cdev)
+{
+ dev_err(&cdev->dev, "node alive timeout\n");
+ cosm_shutdown_status_int(cdev, MIC_CRASHED);
+ cosm_update_mic_status(cdev);
+}
+
+/* Send host time to the MIC card to sync system time between host and MIC */
+static void cosm_send_time(struct cosm_device *cdev)
+{
+ struct cosm_msg msg = { .id = COSM_MSG_SYNC_TIME };
+ int rc;
+
+ getnstimeofday64(&msg.timespec);
+ rc = scif_send(cdev->epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
+ if (rc < 0)
+ dev_err(&cdev->dev, "%s %d scif_send failed rc %d\n",
+ __func__, __LINE__, rc);
+}
+
+/*
+ * Close this cosm_device's endpoint after its peer endpoint on the card has
+ * been closed. In all cases except MIC card crash POLLHUP on the host is
+ * triggered by the client's endpoint being closed.
+ */
+static void cosm_scif_close(struct cosm_device *cdev)
+{
+ /*
+ * Because SHUTDOWN_STATUS message is sent by the MIC cards in the
+ * reboot notifier when shutdown is still not complete, we notify mpssd
+ * to reset the card when SCIF endpoint is closed.
+ */
+ cosm_update_mic_status(cdev);
+ scif_close(cdev->epd);
+ cdev->epd = NULL;
+ dev_dbg(&cdev->dev, "%s %d\n", __func__, __LINE__);
+}
+
+/*
+ * Set card state to ONLINE when a new SCIF connection from a MIC card is
+ * received. Normally the state is BOOTING when the connection comes in, but can
+ * be ONLINE if cosm_client driver on the card was unloaded and then reloaded.
+ */
+static int cosm_set_online(struct cosm_device *cdev)
+{
+ int rc = 0;
+
+ if (MIC_BOOTING == cdev->state || MIC_ONLINE == cdev->state) {
+ cdev->heartbeat_watchdog_enable = cdev->sysfs_heartbeat_enable;
+ cdev->epd = cdev->newepd;
+ if (cdev->state == MIC_BOOTING)
+ cosm_set_state(cdev, MIC_ONLINE);
+ cosm_send_time(cdev);
+ dev_dbg(&cdev->dev, "%s %d\n", __func__, __LINE__);
+ } else {
+ dev_warn(&cdev->dev, "%s %d not going online in state: %s\n",
+ __func__, __LINE__, cosm_state_string[cdev->state]);
+ rc = -EINVAL;
+ }
+ /* Drop reference acquired by bus_find_device in the server thread */
+ put_device(&cdev->dev);
+ return rc;
+}
+
+/*
+ * Work function for handling work for a SCIF connection from a particular MIC
+ * card. It first sets the card state to ONLINE and then calls scif_poll to
+ * block on activity such as incoming messages on the SCIF endpoint. When the
+ * endpoint is closed, the work function exits, completing its life cycle, from
+ * MIC card boot to card shutdown/reset/crash.
+ */
+void cosm_scif_work(struct work_struct *work)
+{
+ struct cosm_device *cdev = container_of(work, struct cosm_device,
+ scif_work);
+ struct scif_pollepd pollepd;
+ int rc;
+
+ mutex_lock(&cdev->cosm_mutex);
+ if (cosm_set_online(cdev))
+ goto exit;
+
+ while (1) {
+ pollepd.epd = cdev->epd;
+ pollepd.events = POLLIN;
+
+ /* Drop the mutex before blocking in scif_poll(..) */
+ mutex_unlock(&cdev->cosm_mutex);
+ /* poll(..) with timeout on our endpoint */
+ rc = scif_poll(&pollepd, 1, COSM_HEARTBEAT_TIMEOUT_MSEC);
+ mutex_lock(&cdev->cosm_mutex);
+ if (rc < 0) {
+ dev_err(&cdev->dev, "%s %d scif_poll rc %d\n",
+ __func__, __LINE__, rc);
+ continue;
+ }
+
+ /* There is a message from the card */
+ if (pollepd.revents & POLLIN)
+ cosm_scif_recv(cdev);
+
+ /* The peer endpoint is closed or this endpoint disconnected */
+ if (pollepd.revents & POLLHUP) {
+ cosm_scif_close(cdev);
+ break;
+ }
+
+ /* Did we timeout from poll? */
+ if (!rc && cdev->heartbeat_watchdog_enable)
+ cosm_set_crashed(cdev);
+ }
+exit:
+ dev_dbg(&cdev->dev, "%s %d exiting\n", __func__, __LINE__);
+ mutex_unlock(&cdev->cosm_mutex);
+}
+
+/*
+ * COSM SCIF server thread function. Accepts incoming SCIF connections from MIC
+ * cards, finds the correct cosm_device to associate that connection with and
+ * schedules individual work items for each MIC card.
+ */
+static int cosm_scif_server(void *unused)
+{
+ struct cosm_device *cdev;
+ scif_epd_t newepd;
+ struct scif_port_id port_id;
+ int rc;
+
+ allow_signal(SIGKILL);
+
+ while (!kthread_should_stop()) {
+ rc = scif_accept(listen_epd, &port_id, &newepd,
+ SCIF_ACCEPT_SYNC);
+ if (rc < 0) {
+ if (-ERESTARTSYS != rc)
+ pr_err("%s %d rc %d\n", __func__, __LINE__, rc);
+ continue;
+ }
+
+ /*
+ * Associate the incoming connection with a particular
+ * cosm_device, COSM device ID == SCIF node ID - 1
+ */
+ cdev = cosm_find_cdev_by_id(port_id.node - 1);
+ if (!cdev)
+ continue;
+ cdev->newepd = newepd;
+ schedule_work(&cdev->scif_work);
+ }
+
+ pr_debug("%s %d Server thread stopped\n", __func__, __LINE__);
+ return 0;
+}
+
+static int cosm_scif_listen(void)
+{
+ int rc;
+
+ listen_epd = scif_open();
+ if (!listen_epd) {
+ pr_err("%s %d scif_open failed\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ rc = scif_bind(listen_epd, SCIF_COSM_LISTEN_PORT);
+ if (rc < 0) {
+ pr_err("%s %d scif_bind failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto err;
+ }
+
+ rc = scif_listen(listen_epd, COSM_SCIF_BACKLOG);
+ if (rc < 0) {
+ pr_err("%s %d scif_listen rc %d\n", __func__, __LINE__, rc);
+ goto err;
+ }
+ pr_debug("%s %d listen_epd set up\n", __func__, __LINE__);
+ return 0;
+err:
+ scif_close(listen_epd);
+ listen_epd = NULL;
+ return rc;
+}
+
+static void cosm_scif_listen_exit(void)
+{
+ pr_debug("%s %d closing listen_epd\n", __func__, __LINE__);
+ if (listen_epd) {
+ scif_close(listen_epd);
+ listen_epd = NULL;
+ }
+}
+
+/*
+ * Create a listening SCIF endpoint and a server kthread which accepts incoming
+ * SCIF connections from MIC cards
+ */
+int cosm_scif_init(void)
+{
+ int rc = cosm_scif_listen();
+
+ if (rc) {
+ pr_err("%s %d cosm_scif_listen rc %d\n",
+ __func__, __LINE__, rc);
+ goto err;
+ }
+
+ server_thread = kthread_run(cosm_scif_server, NULL, "cosm_server");
+ if (IS_ERR(server_thread)) {
+ rc = PTR_ERR(server_thread);
+ pr_err("%s %d kthread_run rc %d\n", __func__, __LINE__, rc);
+ goto listen_exit;
+ }
+ return 0;
+listen_exit:
+ cosm_scif_listen_exit();
+err:
+ return rc;
+}
+
+/* Stop the running server thread and close the listening SCIF endpoint */
+void cosm_scif_exit(void)
+{
+ int rc;
+
+ if (!IS_ERR_OR_NULL(server_thread)) {
+ rc = send_sig(SIGKILL, server_thread, 0);
+ if (rc) {
+ pr_err("%s %d send_sig rc %d\n",
+ __func__, __LINE__, rc);
+ return;
+ }
+ kthread_stop(server_thread);
+ }
+
+ cosm_scif_listen_exit();
+}
diff --git a/drivers/misc/mic/cosm/cosm_sysfs.c b/drivers/misc/mic/cosm/cosm_sysfs.c
new file mode 100644
index 000000000000..29d6863b6e59
--- /dev/null
+++ b/drivers/misc/mic/cosm/cosm_sysfs.c
@@ -0,0 +1,461 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC Coprocessor State Management (COSM) Driver
+ *
+ */
+#include <linux/slab.h>
+#include "cosm_main.h"
+
+/*
+ * A state-to-string lookup table, for exposing a human readable state
+ * via sysfs. Always keep in sync with enum cosm_states
+ */
+const char * const cosm_state_string[] = {
+ [MIC_READY] = "ready",
+ [MIC_BOOTING] = "booting",
+ [MIC_ONLINE] = "online",
+ [MIC_SHUTTING_DOWN] = "shutting_down",
+ [MIC_RESETTING] = "resetting",
+ [MIC_RESET_FAILED] = "reset_failed",
+};
+
+/*
+ * A shutdown-status-to-string lookup table, for exposing a human
+ * readable state via sysfs. Always keep in sync with enum cosm_shutdown_status
+ */
+const char * const cosm_shutdown_status_string[] = {
+ [MIC_NOP] = "nop",
+ [MIC_CRASHED] = "crashed",
+ [MIC_HALTED] = "halted",
+ [MIC_POWER_OFF] = "poweroff",
+ [MIC_RESTART] = "restart",
+};
+
+void cosm_set_shutdown_status(struct cosm_device *cdev, u8 shutdown_status)
+{
+ dev_dbg(&cdev->dev, "Shutdown Status %s -> %s\n",
+ cosm_shutdown_status_string[cdev->shutdown_status],
+ cosm_shutdown_status_string[shutdown_status]);
+ cdev->shutdown_status = shutdown_status;
+}
+
+void cosm_set_state(struct cosm_device *cdev, u8 state)
+{
+ dev_dbg(&cdev->dev, "State %s -> %s\n",
+ cosm_state_string[cdev->state],
+ cosm_state_string[state]);
+ cdev->state = state;
+ sysfs_notify_dirent(cdev->state_sysfs);
+}
+
+static ssize_t
+family_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ return cdev->hw_ops->family(cdev, buf);
+}
+static DEVICE_ATTR_RO(family);
+
+static ssize_t
+stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ return cdev->hw_ops->stepping(cdev, buf);
+}
+static DEVICE_ATTR_RO(stepping);
+
+static ssize_t
+state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev || cdev->state >= MIC_LAST)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ cosm_state_string[cdev->state]);
+}
+
+static ssize_t
+state_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ int rc;
+
+ if (!cdev)
+ return -EINVAL;
+
+ if (sysfs_streq(buf, "boot")) {
+ rc = cosm_start(cdev);
+ goto done;
+ }
+ if (sysfs_streq(buf, "reset")) {
+ rc = cosm_reset(cdev);
+ goto done;
+ }
+
+ if (sysfs_streq(buf, "shutdown")) {
+ rc = cosm_shutdown(cdev);
+ goto done;
+ }
+ rc = -EINVAL;
+done:
+ if (rc)
+ count = rc;
+ return count;
+}
+static DEVICE_ATTR_RW(state);
+
+static ssize_t shutdown_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev || cdev->shutdown_status >= MIC_STATUS_LAST)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ cosm_shutdown_status_string[cdev->shutdown_status]);
+}
+static DEVICE_ATTR_RO(shutdown_status);
+
+static ssize_t
+heartbeat_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", cdev->sysfs_heartbeat_enable);
+}
+
+static ssize_t
+heartbeat_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ int enable;
+ int ret;
+
+ if (!cdev)
+ return -EINVAL;
+
+ mutex_lock(&cdev->cosm_mutex);
+ ret = kstrtoint(buf, 10, &enable);
+ if (ret)
+ goto unlock;
+
+ cdev->sysfs_heartbeat_enable = enable;
+ /* if state is not online, cdev->heartbeat_watchdog_enable is 0 */
+ if (cdev->state == MIC_ONLINE)
+ cdev->heartbeat_watchdog_enable = enable;
+ ret = count;
+unlock:
+ mutex_unlock(&cdev->cosm_mutex);
+ return ret;
+}
+static DEVICE_ATTR_RW(heartbeat_enable);
+
+static ssize_t
+cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ char *cmdline;
+
+ if (!cdev)
+ return -EINVAL;
+
+ cmdline = cdev->cmdline;
+
+ if (cmdline)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
+ return 0;
+}
+
+static ssize_t
+cmdline_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ mutex_lock(&cdev->cosm_mutex);
+ kfree(cdev->cmdline);
+
+ cdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
+ if (!cdev->cmdline) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+
+ strncpy(cdev->cmdline, buf, count);
+
+ if (cdev->cmdline[count - 1] == '\n')
+ cdev->cmdline[count - 1] = '\0';
+ else
+ cdev->cmdline[count] = '\0';
+unlock:
+ mutex_unlock(&cdev->cosm_mutex);
+ return count;
+}
+static DEVICE_ATTR_RW(cmdline);
+
+static ssize_t
+firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ char *firmware;
+
+ if (!cdev)
+ return -EINVAL;
+
+ firmware = cdev->firmware;
+
+ if (firmware)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
+ return 0;
+}
+
+static ssize_t
+firmware_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ mutex_lock(&cdev->cosm_mutex);
+ kfree(cdev->firmware);
+
+ cdev->firmware = kmalloc(count + 1, GFP_KERNEL);
+ if (!cdev->firmware) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+ strncpy(cdev->firmware, buf, count);
+
+ if (cdev->firmware[count - 1] == '\n')
+ cdev->firmware[count - 1] = '\0';
+ else
+ cdev->firmware[count] = '\0';
+unlock:
+ mutex_unlock(&cdev->cosm_mutex);
+ return count;
+}
+static DEVICE_ATTR_RW(firmware);
+
+static ssize_t
+ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ char *ramdisk;
+
+ if (!cdev)
+ return -EINVAL;
+
+ ramdisk = cdev->ramdisk;
+
+ if (ramdisk)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
+ return 0;
+}
+
+static ssize_t
+ramdisk_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ mutex_lock(&cdev->cosm_mutex);
+ kfree(cdev->ramdisk);
+
+ cdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
+ if (!cdev->ramdisk) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+
+ strncpy(cdev->ramdisk, buf, count);
+
+ if (cdev->ramdisk[count - 1] == '\n')
+ cdev->ramdisk[count - 1] = '\0';
+ else
+ cdev->ramdisk[count] = '\0';
+unlock:
+ mutex_unlock(&cdev->cosm_mutex);
+ return count;
+}
+static DEVICE_ATTR_RW(ramdisk);
+
+static ssize_t
+bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ char *bootmode;
+
+ if (!cdev)
+ return -EINVAL;
+
+ bootmode = cdev->bootmode;
+
+ if (bootmode)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
+ return 0;
+}
+
+static ssize_t
+bootmode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "flash"))
+ return -EINVAL;
+
+ mutex_lock(&cdev->cosm_mutex);
+ kfree(cdev->bootmode);
+
+ cdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
+ if (!cdev->bootmode) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+
+ strncpy(cdev->bootmode, buf, count);
+
+ if (cdev->bootmode[count - 1] == '\n')
+ cdev->bootmode[count - 1] = '\0';
+ else
+ cdev->bootmode[count] = '\0';
+unlock:
+ mutex_unlock(&cdev->cosm_mutex);
+ return count;
+}
+static DEVICE_ATTR_RW(bootmode);
+
+static ssize_t
+log_buf_addr_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%p\n", cdev->log_buf_addr);
+}
+
+static ssize_t
+log_buf_addr_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ int ret;
+ unsigned long addr;
+
+ if (!cdev)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 16, &addr);
+ if (ret)
+ goto exit;
+
+ cdev->log_buf_addr = (void *)addr;
+ ret = count;
+exit:
+ return ret;
+}
+static DEVICE_ATTR_RW(log_buf_addr);
+
+static ssize_t
+log_buf_len_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+
+ if (!cdev)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%p\n", cdev->log_buf_len);
+}
+
+static ssize_t
+log_buf_len_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cosm_device *cdev = dev_get_drvdata(dev);
+ int ret;
+ unsigned long addr;
+
+ if (!cdev)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 16, &addr);
+ if (ret)
+ goto exit;
+
+ cdev->log_buf_len = (int *)addr;
+ ret = count;
+exit:
+ return ret;
+}
+static DEVICE_ATTR_RW(log_buf_len);
+
+static struct attribute *cosm_default_attrs[] = {
+ &dev_attr_family.attr,
+ &dev_attr_stepping.attr,
+ &dev_attr_state.attr,
+ &dev_attr_shutdown_status.attr,
+ &dev_attr_heartbeat_enable.attr,
+ &dev_attr_cmdline.attr,
+ &dev_attr_firmware.attr,
+ &dev_attr_ramdisk.attr,
+ &dev_attr_bootmode.attr,
+ &dev_attr_log_buf_addr.attr,
+ &dev_attr_log_buf_len.attr,
+
+ NULL
+};
+
+ATTRIBUTE_GROUPS(cosm_default);
+
+void cosm_sysfs_init(struct cosm_device *cdev)
+{
+ cdev->attr_group = cosm_default_groups;
+}
diff --git a/drivers/misc/mic/cosm_client/Makefile b/drivers/misc/mic/cosm_client/Makefile
new file mode 100644
index 000000000000..6f751a519a09
--- /dev/null
+++ b/drivers/misc/mic/cosm_client/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile - Intel MIC COSM Client Driver
+# Copyright(c) 2015, Intel Corporation.
+#
+obj-$(CONFIG_MIC_COSM) += cosm_client.o
+
+cosm_client-objs += cosm_scif_client.o
diff --git a/drivers/misc/mic/cosm_client/cosm_scif_client.c b/drivers/misc/mic/cosm_client/cosm_scif_client.c
new file mode 100644
index 000000000000..03e98bf1ac15
--- /dev/null
+++ b/drivers/misc/mic/cosm_client/cosm_scif_client.c
@@ -0,0 +1,275 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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".
+ *
+ * Intel MIC COSM Client Driver
+ *
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/kthread.h>
+#include "../cosm/cosm_main.h"
+
+#define COSM_SCIF_MAX_RETRIES 10
+#define COSM_HEARTBEAT_SEND_MSEC (COSM_HEARTBEAT_SEND_SEC * MSEC_PER_SEC)
+
+static struct task_struct *client_thread;
+static scif_epd_t client_epd;
+static struct scif_peer_dev *client_spdev;
+
+/*
+ * Reboot notifier: receives shutdown status from the OS and communicates it
+ * back to the COSM process on the host
+ */
+static int cosm_reboot_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct cosm_msg msg = { .id = COSM_MSG_SHUTDOWN_STATUS };
+ int rc;
+
+ event = (event == SYS_RESTART) ? SYSTEM_RESTART : event;
+ dev_info(&client_spdev->dev, "%s %d received event %ld\n",
+ __func__, __LINE__, event);
+
+ msg.shutdown_status = event;
+ rc = scif_send(client_epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
+ if (rc < 0)
+ dev_err(&client_spdev->dev, "%s %d scif_send rc %d\n",
+ __func__, __LINE__, rc);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block cosm_reboot = {
+ .notifier_call = cosm_reboot_event,
+};
+
+/* Set system time from timespec value received from the host */
+static void cosm_set_time(struct cosm_msg *msg)
+{
+ int rc = do_settimeofday64(&msg->timespec);
+
+ if (rc)
+ dev_err(&client_spdev->dev, "%s: %d settimeofday rc %d\n",
+ __func__, __LINE__, rc);
+}
+
+/* COSM client receive message processing */
+static void cosm_client_recv(void)
+{
+ struct cosm_msg msg;
+ int rc;
+
+ while (1) {
+ rc = scif_recv(client_epd, &msg, sizeof(msg), 0);
+ if (!rc) {
+ return;
+ } else if (rc < 0) {
+ dev_err(&client_spdev->dev, "%s: %d rc %d\n",
+ __func__, __LINE__, rc);
+ return;
+ }
+
+ dev_dbg(&client_spdev->dev, "%s: %d rc %d id 0x%llx\n",
+ __func__, __LINE__, rc, msg.id);
+
+ switch (msg.id) {
+ case COSM_MSG_SYNC_TIME:
+ cosm_set_time(&msg);
+ break;
+ case COSM_MSG_SHUTDOWN:
+ orderly_poweroff(true);
+ break;
+ default:
+ dev_err(&client_spdev->dev, "%s: %d unknown id %lld\n",
+ __func__, __LINE__, msg.id);
+ break;
+ }
+ }
+}
+
+/* Initiate connection to the COSM server on the host */
+static int cosm_scif_connect(void)
+{
+ struct scif_port_id port_id;
+ int i, rc;
+
+ client_epd = scif_open();
+ if (!client_epd) {
+ dev_err(&client_spdev->dev, "%s %d scif_open failed\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ port_id.node = 0;
+ port_id.port = SCIF_COSM_LISTEN_PORT;
+
+ for (i = 0; i < COSM_SCIF_MAX_RETRIES; i++) {
+ rc = scif_connect(client_epd, &port_id);
+ if (rc < 0)
+ msleep(1000);
+ else
+ break;
+ }
+
+ if (rc < 0) {
+ dev_err(&client_spdev->dev, "%s %d scif_connect rc %d\n",
+ __func__, __LINE__, rc);
+ scif_close(client_epd);
+ client_epd = NULL;
+ }
+ return rc < 0 ? rc : 0;
+}
+
+/* Close host SCIF connection */
+static void cosm_scif_connect_exit(void)
+{
+ if (client_epd) {
+ scif_close(client_epd);
+ client_epd = NULL;
+ }
+}
+
+/*
+ * COSM SCIF client thread function: waits for messages from the host and sends
+ * a heartbeat to the host
+ */
+static int cosm_scif_client(void *unused)
+{
+ struct cosm_msg msg = { .id = COSM_MSG_HEARTBEAT };
+ struct scif_pollepd pollepd;
+ int rc;
+
+ allow_signal(SIGKILL);
+
+ while (!kthread_should_stop()) {
+ pollepd.epd = client_epd;
+ pollepd.events = POLLIN;
+
+ rc = scif_poll(&pollepd, 1, COSM_HEARTBEAT_SEND_MSEC);
+ if (rc < 0) {
+ if (-EINTR != rc)
+ dev_err(&client_spdev->dev,
+ "%s %d scif_poll rc %d\n",
+ __func__, __LINE__, rc);
+ continue;
+ }
+
+ if (pollepd.revents & POLLIN)
+ cosm_client_recv();
+
+ msg.id = COSM_MSG_HEARTBEAT;
+ rc = scif_send(client_epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
+ if (rc < 0)
+ dev_err(&client_spdev->dev, "%s %d scif_send rc %d\n",
+ __func__, __LINE__, rc);
+ }
+
+ dev_dbg(&client_spdev->dev, "%s %d Client thread stopped\n",
+ __func__, __LINE__);
+ return 0;
+}
+
+static void cosm_scif_probe(struct scif_peer_dev *spdev)
+{
+ int rc;
+
+ dev_dbg(&spdev->dev, "%s %d: dnode %d\n",
+ __func__, __LINE__, spdev->dnode);
+
+ /* We are only interested in the host with spdev->dnode == 0 */
+ if (spdev->dnode)
+ return;
+
+ client_spdev = spdev;
+ rc = cosm_scif_connect();
+ if (rc)
+ goto exit;
+
+ rc = register_reboot_notifier(&cosm_reboot);
+ if (rc) {
+ dev_err(&spdev->dev,
+ "reboot notifier registration failed rc %d\n", rc);
+ goto connect_exit;
+ }
+
+ client_thread = kthread_run(cosm_scif_client, NULL, "cosm_client");
+ if (IS_ERR(client_thread)) {
+ rc = PTR_ERR(client_thread);
+ dev_err(&spdev->dev, "%s %d kthread_run rc %d\n",
+ __func__, __LINE__, rc);
+ goto unreg_reboot;
+ }
+ return;
+unreg_reboot:
+ unregister_reboot_notifier(&cosm_reboot);
+connect_exit:
+ cosm_scif_connect_exit();
+exit:
+ client_spdev = NULL;
+}
+
+static void cosm_scif_remove(struct scif_peer_dev *spdev)
+{
+ int rc;
+
+ dev_dbg(&spdev->dev, "%s %d: dnode %d\n",
+ __func__, __LINE__, spdev->dnode);
+
+ if (spdev->dnode)
+ return;
+
+ if (!IS_ERR_OR_NULL(client_thread)) {
+ rc = send_sig(SIGKILL, client_thread, 0);
+ if (rc) {
+ pr_err("%s %d send_sig rc %d\n",
+ __func__, __LINE__, rc);
+ return;
+ }
+ kthread_stop(client_thread);
+ }
+ unregister_reboot_notifier(&cosm_reboot);
+ cosm_scif_connect_exit();
+ client_spdev = NULL;
+}
+
+static struct scif_client scif_client_cosm = {
+ .name = KBUILD_MODNAME,
+ .probe = cosm_scif_probe,
+ .remove = cosm_scif_remove,
+};
+
+static int __init cosm_client_init(void)
+{
+ int rc = scif_client_register(&scif_client_cosm);
+
+ if (rc)
+ pr_err("scif_client_register failed rc %d\n", rc);
+ return rc;
+}
+
+static void __exit cosm_client_exit(void)
+{
+ scif_client_unregister(&scif_client_cosm);
+}
+
+module_init(cosm_client_init);
+module_exit(cosm_client_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC card OS state management client driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
index c2197f999394..004d3db0f990 100644
--- a/drivers/misc/mic/host/Makefile
+++ b/drivers/misc/mic/host/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
mic_host-objs := mic_main.o
mic_host-objs += mic_x100.o
-mic_host-objs += mic_sysfs.o
mic_host-objs += mic_smpt.o
mic_host-objs += mic_intr.o
mic_host-objs += mic_boot.o
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
index e5f6a5e7bca1..7845564dff64 100644
--- a/drivers/misc/mic/host/mic_boot.c
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -22,9 +22,9 @@
#include <linux/firmware.h>
#include <linux/pci.h>
#include <linux/kmod.h>
-
#include <linux/mic_common.h>
#include <linux/mic_bus.h>
+#include "../bus/scif_bus.h"
#include "../common/mic_dev.h"
#include "mic_device.h"
#include "mic_smpt.h"
@@ -99,7 +99,7 @@ static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
int i, j, ret;
dma_addr_t da;
- ret = dma_map_sg(mdev->sdev->parent, sg, nents, dir);
+ ret = dma_map_sg(&mdev->pdev->dev, sg, nents, dir);
if (ret <= 0)
return 0;
@@ -115,7 +115,7 @@ err:
mic_unmap(mdev, sg_dma_address(s), s->length);
sg_dma_address(s) = mic_to_dma_addr(mdev, sg_dma_address(s));
}
- dma_unmap_sg(mdev->sdev->parent, sg, nents, dir);
+ dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
return 0;
}
@@ -135,7 +135,7 @@ static void __mic_dma_unmap_sg(struct device *dev,
mic_unmap(mdev, sg_dma_address(s), s->length);
sg_dma_address(s) = da;
}
- dma_unmap_sg(mdev->sdev->parent, sg, nents, dir);
+ dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
}
static struct dma_map_ops __mic_dma_ops = {
@@ -270,48 +270,13 @@ static struct mbus_hw_ops mbus_hw_ops = {
.ack_interrupt = _mic_ack_interrupt,
};
-/**
- * mic_reset - Reset the MIC device.
- * @mdev: pointer to mic_device instance
- */
-static void mic_reset(struct mic_device *mdev)
-{
- int i;
-
-#define MIC_RESET_TO (45)
-
- reinit_completion(&mdev->reset_wait);
- mdev->ops->reset_fw_ready(mdev);
- mdev->ops->reset(mdev);
-
- for (i = 0; i < MIC_RESET_TO; i++) {
- if (mdev->ops->is_fw_ready(mdev))
- goto done;
- /*
- * Resets typically take 10s of seconds to complete.
- * Since an MMIO read is required to check if the
- * firmware is ready or not, a 1 second delay works nicely.
- */
- msleep(1000);
- }
- mic_set_state(mdev, MIC_RESET_FAILED);
-done:
- complete_all(&mdev->reset_wait);
-}
-
/* Initialize the MIC bootparams */
void mic_bootparam_init(struct mic_device *mdev)
{
struct mic_bootparam *bootparam = mdev->dp;
bootparam->magic = cpu_to_le32(MIC_MAGIC);
- bootparam->c2h_shutdown_db = mdev->shutdown_db;
- bootparam->h2c_shutdown_db = -1;
bootparam->h2c_config_db = -1;
- bootparam->shutdown_status = 0;
- bootparam->shutdown_card = 0;
- /* Total nodes = number of MICs + 1 for self node */
- bootparam->tot_nodes = atomic_read(&g_num_mics) + 1;
bootparam->node_id = mdev->id + 1;
bootparam->scif_host_dma_addr = 0x0;
bootparam->scif_card_dma_addr = 0x0;
@@ -319,6 +284,26 @@ void mic_bootparam_init(struct mic_device *mdev)
bootparam->h2c_scif_db = -1;
}
+static inline struct mic_device *cosmdev_to_mdev(struct cosm_device *cdev)
+{
+ return dev_get_drvdata(cdev->dev.parent);
+}
+
+static void _mic_reset(struct cosm_device *cdev)
+{
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
+
+ mdev->ops->reset_fw_ready(mdev);
+ mdev->ops->reset(mdev);
+}
+
+static bool _mic_ready(struct cosm_device *cdev)
+{
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
+
+ return mdev->ops->is_fw_ready(mdev);
+}
+
/**
* mic_request_dma_chans - Request DMA channels
* @mdev: pointer to mic_device instance
@@ -336,14 +321,14 @@ static int mic_request_dma_chans(struct mic_device *mdev)
do {
chan = dma_request_channel(mask, mdev->ops->dma_filter,
- mdev->sdev->parent);
+ &mdev->pdev->dev);
if (chan) {
mdev->dma_ch[mdev->num_dma_ch++] = chan;
if (mdev->num_dma_ch >= MIC_MAX_DMA_CHAN)
break;
}
} while (chan);
- dev_info(mdev->sdev->parent, "DMA channels # %d\n", mdev->num_dma_ch);
+ dev_info(&mdev->pdev->dev, "DMA channels # %d\n", mdev->num_dma_ch);
return mdev->num_dma_ch;
}
@@ -365,34 +350,24 @@ static void mic_free_dma_chans(struct mic_device *mdev)
}
/**
- * mic_start - Start the MIC.
- * @mdev: pointer to mic_device instance
- * @buf: buffer containing boot string including firmware/ramdisk path.
+ * _mic_start - Start the MIC.
+ * @cdev: pointer to cosm_device instance
+ * @id: MIC device id/index provided by COSM used in other drivers like SCIF
*
* This function prepares an MIC for boot and initiates boot.
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ *
+ * For all cosm_hw_ops the caller holds a mutex to ensure serialization.
*/
-int mic_start(struct mic_device *mdev, const char *buf)
+static int _mic_start(struct cosm_device *cdev, int id)
{
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
int rc;
- mutex_lock(&mdev->mic_mutex);
+
mic_bootparam_init(mdev);
-retry:
- if (MIC_OFFLINE != mdev->state) {
- rc = -EINVAL;
- goto unlock_ret;
- }
- if (!mdev->ops->is_fw_ready(mdev)) {
- mic_reset(mdev);
- /*
- * The state will either be MIC_OFFLINE if the reset succeeded
- * or MIC_RESET_FAILED if the firmware reset failed.
- */
- goto retry;
- }
- mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent,
+ mdev->dma_mbdev = mbus_register_device(&mdev->pdev->dev,
MBUS_DEV_DMA_HOST, &mic_dma_ops,
- &mbus_hw_ops, mdev->mmio.va);
+ &mbus_hw_ops, id, mdev->mmio.va);
if (IS_ERR(mdev->dma_mbdev)) {
rc = PTR_ERR(mdev->dma_mbdev);
goto unlock_ret;
@@ -401,16 +376,18 @@ retry:
rc = -ENODEV;
goto dma_remove;
}
- mdev->scdev = scif_register_device(mdev->sdev->parent, MIC_SCIF_DEV,
+ mdev->scdev = scif_register_device(&mdev->pdev->dev, MIC_SCIF_DEV,
&__mic_dma_ops, &scif_hw_ops,
- mdev->id + 1, 0, &mdev->mmio,
+ id + 1, 0, &mdev->mmio,
&mdev->aper, mdev->dp, NULL,
- mdev->dma_ch, mdev->num_dma_ch);
+ mdev->dma_ch, mdev->num_dma_ch,
+ true);
if (IS_ERR(mdev->scdev)) {
rc = PTR_ERR(mdev->scdev);
goto dma_free;
}
- rc = mdev->ops->load_mic_fw(mdev, buf);
+
+ rc = mdev->ops->load_mic_fw(mdev, NULL);
if (rc)
goto scif_remove;
mic_smpt_restore(mdev);
@@ -419,7 +396,6 @@ retry:
mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
mdev->ops->send_firmware_intr(mdev);
- mic_set_state(mdev, MIC_ONLINE);
goto unlock_ret;
scif_remove:
scif_unregister_device(mdev->scdev);
@@ -428,198 +404,79 @@ dma_free:
dma_remove:
mbus_unregister_device(mdev->dma_mbdev);
unlock_ret:
- mutex_unlock(&mdev->mic_mutex);
return rc;
}
/**
- * mic_stop - Prepare the MIC for reset and trigger reset.
- * @mdev: pointer to mic_device instance
+ * _mic_stop - Prepare the MIC for reset and trigger reset.
+ * @cdev: pointer to cosm_device instance
* @force: force a MIC to reset even if it is already offline.
*
* RETURNS: None.
*/
-void mic_stop(struct mic_device *mdev, bool force)
-{
- mutex_lock(&mdev->mic_mutex);
- if (MIC_OFFLINE != mdev->state || force) {
- scif_unregister_device(mdev->scdev);
- mic_virtio_reset_devices(mdev);
- mic_free_dma_chans(mdev);
- mbus_unregister_device(mdev->dma_mbdev);
- mic_bootparam_init(mdev);
- mic_reset(mdev);
- if (MIC_RESET_FAILED == mdev->state)
- goto unlock;
- mic_set_shutdown_status(mdev, MIC_NOP);
- if (MIC_SUSPENDED != mdev->state)
- mic_set_state(mdev, MIC_OFFLINE);
- }
-unlock:
- mutex_unlock(&mdev->mic_mutex);
-}
-
-/**
- * mic_shutdown - Initiate MIC shutdown.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: None.
- */
-void mic_shutdown(struct mic_device *mdev)
+static void _mic_stop(struct cosm_device *cdev, bool force)
{
- struct mic_bootparam *bootparam = mdev->dp;
- s8 db = bootparam->h2c_shutdown_db;
-
- mutex_lock(&mdev->mic_mutex);
- if (MIC_ONLINE == mdev->state && db != -1) {
- bootparam->shutdown_card = 1;
- mdev->ops->send_intr(mdev, db);
- mic_set_state(mdev, MIC_SHUTTING_DOWN);
- }
- mutex_unlock(&mdev->mic_mutex);
-}
-
-/**
- * mic_shutdown_work - Handle shutdown interrupt from MIC.
- * @work: The work structure.
- *
- * This work is scheduled whenever the host has received a shutdown
- * interrupt from the MIC.
- */
-void mic_shutdown_work(struct work_struct *work)
-{
- struct mic_device *mdev = container_of(work, struct mic_device,
- shutdown_work);
- struct mic_bootparam *bootparam = mdev->dp;
-
- mutex_lock(&mdev->mic_mutex);
- mic_set_shutdown_status(mdev, bootparam->shutdown_status);
- bootparam->shutdown_status = 0;
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
/*
- * if state is MIC_SUSPENDED, OSPM suspend is in progress. We do not
- * change the state here so as to prevent users from booting the card
- * during and after the suspend operation.
+ * Since SCIF handles card shutdown and reset (using COSM), it will
+ * will be the first to be registered and the last to be
+ * unregistered.
*/
- if (MIC_SHUTTING_DOWN != mdev->state &&
- MIC_SUSPENDED != mdev->state)
- mic_set_state(mdev, MIC_SHUTTING_DOWN);
- mutex_unlock(&mdev->mic_mutex);
+ mic_virtio_reset_devices(mdev);
+ scif_unregister_device(mdev->scdev);
+ mic_free_dma_chans(mdev);
+ mbus_unregister_device(mdev->dma_mbdev);
+ mic_bootparam_init(mdev);
}
-/**
- * mic_reset_trigger_work - Trigger MIC reset.
- * @work: The work structure.
- *
- * This work is scheduled whenever the host wants to reset the MIC.
- */
-void mic_reset_trigger_work(struct work_struct *work)
+static ssize_t _mic_family(struct cosm_device *cdev, char *buf)
{
- struct mic_device *mdev = container_of(work, struct mic_device,
- reset_trigger_work);
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
+ static const char *family[MIC_FAMILY_LAST] = { "x100", "Unknown" };
- mic_stop(mdev, false);
+ return scnprintf(buf, PAGE_SIZE, "%s\n", family[mdev->family]);
}
-/**
- * mic_complete_resume - Complete MIC Resume after an OSPM suspend/hibernate
- * event.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: None.
- */
-void mic_complete_resume(struct mic_device *mdev)
+static ssize_t _mic_stepping(struct cosm_device *cdev, char *buf)
{
- if (mdev->state != MIC_SUSPENDED) {
- dev_warn(mdev->sdev->parent, "state %d should be %d\n",
- mdev->state, MIC_SUSPENDED);
- return;
- }
-
- /* Make sure firmware is ready */
- if (!mdev->ops->is_fw_ready(mdev))
- mic_stop(mdev, true);
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
+ const char *string = "??";
- mutex_lock(&mdev->mic_mutex);
- mic_set_state(mdev, MIC_OFFLINE);
- mutex_unlock(&mdev->mic_mutex);
-}
-
-/**
- * mic_prepare_suspend - Handle suspend notification for the MIC device.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: None.
- */
-void mic_prepare_suspend(struct mic_device *mdev)
-{
- unsigned long timeout;
-
-#define MIC_SUSPEND_TIMEOUT (60 * HZ)
-
- mutex_lock(&mdev->mic_mutex);
- switch (mdev->state) {
- case MIC_OFFLINE:
- /*
- * Card is already offline. Set state to MIC_SUSPENDED
- * to prevent users from booting the card.
- */
- mic_set_state(mdev, MIC_SUSPENDED);
- mutex_unlock(&mdev->mic_mutex);
+ switch (mdev->stepping) {
+ case MIC_A0_STEP:
+ string = "A0";
break;
- case MIC_ONLINE:
- /*
- * Card is online. Set state to MIC_SUSPENDING and notify
- * MIC user space daemon which will issue card
- * shutdown and reset.
- */
- mic_set_state(mdev, MIC_SUSPENDING);
- mutex_unlock(&mdev->mic_mutex);
- timeout = wait_for_completion_timeout(&mdev->reset_wait,
- MIC_SUSPEND_TIMEOUT);
- /* Force reset the card if the shutdown completion timed out */
- if (!timeout) {
- mutex_lock(&mdev->mic_mutex);
- mic_set_state(mdev, MIC_SUSPENDED);
- mutex_unlock(&mdev->mic_mutex);
- mic_stop(mdev, true);
- }
+ case MIC_B0_STEP:
+ string = "B0";
+ break;
+ case MIC_B1_STEP:
+ string = "B1";
break;
- case MIC_SHUTTING_DOWN:
- /*
- * Card is shutting down. Set state to MIC_SUSPENDED
- * to prevent further boot of the card.
- */
- mic_set_state(mdev, MIC_SUSPENDED);
- mutex_unlock(&mdev->mic_mutex);
- timeout = wait_for_completion_timeout(&mdev->reset_wait,
- MIC_SUSPEND_TIMEOUT);
- /* Force reset the card if the shutdown completion timed out */
- if (!timeout)
- mic_stop(mdev, true);
+ case MIC_C0_STEP:
+ string = "C0";
break;
default:
- mutex_unlock(&mdev->mic_mutex);
break;
}
+ return scnprintf(buf, PAGE_SIZE, "%s\n", string);
}
-/**
- * mic_suspend - Initiate MIC suspend. Suspend merely issues card shutdown.
- * @mdev: pointer to mic_device instance
- *
- * RETURNS: None.
- */
-void mic_suspend(struct mic_device *mdev)
+static struct mic_mw *_mic_aper(struct cosm_device *cdev)
{
- struct mic_bootparam *bootparam = mdev->dp;
- s8 db = bootparam->h2c_shutdown_db;
+ struct mic_device *mdev = cosmdev_to_mdev(cdev);
- mutex_lock(&mdev->mic_mutex);
- if (MIC_SUSPENDING == mdev->state && db != -1) {
- bootparam->shutdown_card = 1;
- mdev->ops->send_intr(mdev, db);
- mic_set_state(mdev, MIC_SUSPENDED);
- }
- mutex_unlock(&mdev->mic_mutex);
+ return &mdev->aper;
}
+
+struct cosm_hw_ops cosm_hw_ops = {
+ .reset = _mic_reset,
+ .force_reset = _mic_reset,
+ .post_reset = NULL,
+ .ready = _mic_ready,
+ .start = _mic_start,
+ .stop = _mic_stop,
+ .family = _mic_family,
+ .stepping = _mic_stepping,
+ .aper = _mic_aper,
+};
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
index 3c9ea4896f3c..10581600777a 100644
--- a/drivers/misc/mic/host/mic_debugfs.c
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -31,71 +31,6 @@
/* Debugfs parent dir */
static struct dentry *mic_dbg;
-/**
- * mic_log_buf_show - Display MIC kernel log buffer.
- *
- * log_buf addr/len is read from System.map by user space
- * and populated in sysfs entries.
- */
-static int mic_log_buf_show(struct seq_file *s, void *unused)
-{
- void __iomem *log_buf_va;
- int __iomem *log_buf_len_va;
- struct mic_device *mdev = s->private;
- void *kva;
- int size;
- unsigned long aper_offset;
-
- if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len)
- goto done;
- /*
- * Card kernel will never be relocated and any kernel text/data mapping
- * can be translated to phys address by subtracting __START_KERNEL_map.
- */
- aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map;
- log_buf_len_va = mdev->aper.va + aper_offset;
- aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map;
- log_buf_va = mdev->aper.va + aper_offset;
- size = ioread32(log_buf_len_va);
-
- kva = kmalloc(size, GFP_KERNEL);
- if (!kva)
- goto done;
- mutex_lock(&mdev->mic_mutex);
- memcpy_fromio(kva, log_buf_va, size);
- switch (mdev->state) {
- case MIC_ONLINE:
- /* Fall through */
- case MIC_SHUTTING_DOWN:
- seq_write(s, kva, size);
- break;
- default:
- break;
- }
- mutex_unlock(&mdev->mic_mutex);
- kfree(kva);
-done:
- return 0;
-}
-
-static int mic_log_buf_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mic_log_buf_show, inode->i_private);
-}
-
-static int mic_log_buf_release(struct inode *inode, struct file *file)
-{
- return single_release(inode, file);
-}
-
-static const struct file_operations log_buf_ops = {
- .owner = THIS_MODULE,
- .open = mic_log_buf_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = mic_log_buf_release
-};
-
static int mic_smpt_show(struct seq_file *s, void *pos)
{
int i;
@@ -138,32 +73,6 @@ static const struct file_operations smpt_file_ops = {
.release = mic_smpt_debug_release
};
-static int mic_soft_reset_show(struct seq_file *s, void *pos)
-{
- struct mic_device *mdev = s->private;
-
- mic_stop(mdev, true);
- return 0;
-}
-
-static int mic_soft_reset_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mic_soft_reset_show, inode->i_private);
-}
-
-static int mic_soft_reset_debug_release(struct inode *inode, struct file *file)
-{
- return single_release(inode, file);
-}
-
-static const struct file_operations soft_reset_ops = {
- .owner = THIS_MODULE,
- .open = mic_soft_reset_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = mic_soft_reset_debug_release
-};
-
static int mic_post_code_show(struct seq_file *s, void *pos)
{
struct mic_device *mdev = s->private;
@@ -204,18 +113,8 @@ static int mic_dp_show(struct seq_file *s, void *pos)
seq_printf(s, "Bootparam: magic 0x%x\n",
bootparam->magic);
- seq_printf(s, "Bootparam: h2c_shutdown_db %d\n",
- bootparam->h2c_shutdown_db);
seq_printf(s, "Bootparam: h2c_config_db %d\n",
bootparam->h2c_config_db);
- seq_printf(s, "Bootparam: c2h_shutdown_db %d\n",
- bootparam->c2h_shutdown_db);
- seq_printf(s, "Bootparam: shutdown_status %d\n",
- bootparam->shutdown_status);
- seq_printf(s, "Bootparam: shutdown_card %d\n",
- bootparam->shutdown_card);
- seq_printf(s, "Bootparam: tot_nodes %d\n",
- bootparam->tot_nodes);
seq_printf(s, "Bootparam: node_id %d\n",
bootparam->node_id);
seq_printf(s, "Bootparam: c2h_scif_db %d\n",
@@ -392,8 +291,7 @@ static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
int i, j;
u16 entry;
u16 vector;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
if (pci_dev_msi_enabled(pdev)) {
for (i = 0; i < mdev->irq_info.num_vectors; i++) {
@@ -454,20 +352,18 @@ static const struct file_operations msi_irq_info_ops = {
*/
void mic_create_debug_dir(struct mic_device *mdev)
{
+ char name[16];
+
if (!mic_dbg)
return;
- mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg);
+ scnprintf(name, sizeof(name), "mic%d", mdev->id);
+ mdev->dbg_dir = debugfs_create_dir(name, mic_dbg);
if (!mdev->dbg_dir)
return;
- debugfs_create_file("log_buf", 0444, mdev->dbg_dir, mdev, &log_buf_ops);
-
debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops);
- debugfs_create_file("soft_reset", 0444, mdev->dbg_dir, mdev,
- &soft_reset_ops);
-
debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
&post_code_ops);
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
index 01a7555aa648..461184a12fbb 100644
--- a/drivers/misc/mic/host/mic_device.h
+++ b/drivers/misc/mic/host/mic_device.h
@@ -26,21 +26,12 @@
#include <linux/notifier.h>
#include <linux/irqreturn.h>
#include <linux/dmaengine.h>
+#include <linux/miscdevice.h>
#include <linux/mic_bus.h>
#include "../bus/scif_bus.h"
+#include "../bus/cosm_bus.h"
#include "mic_intr.h"
-/* The maximum number of MIC devices supported in a single host system. */
-#define MIC_MAX_NUM_DEVS 256
-
-/**
- * enum mic_hw_family - The hardware family to which a device belongs.
- */
-enum mic_hw_family {
- MIC_FAMILY_X100 = 0,
- MIC_FAMILY_UNKNOWN
-};
-
/**
* enum mic_stepping - MIC stepping ids.
*/
@@ -51,6 +42,8 @@ enum mic_stepping {
MIC_C0_STEP = 0x20,
};
+extern struct cosm_hw_ops cosm_hw_ops;
+
/**
* struct mic_device - MIC device information for each card.
*
@@ -60,8 +53,7 @@ enum mic_stepping {
* @ops: MIC HW specific operations.
* @id: The unique device id for this MIC device.
* @stepping: Stepping ID.
- * @attr_group: Pointer to list of sysfs attribute groups.
- * @sdev: Device for sysfs entries.
+ * @pdev: Underlying PCI device.
* @mic_mutex: Mutex for synchronizing access to mic_device.
* @intr_ops: HW specific interrupt operations.
* @smpt_ops: Hardware specific SMPT operations.
@@ -69,30 +61,17 @@ enum mic_stepping {
* @intr_info: H/W specific interrupt information.
* @irq_info: The OS specific irq information
* @dbg_dir: debugfs directory of this MIC device.
- * @cmdline: Kernel command line.
- * @firmware: Firmware file name.
- * @ramdisk: Ramdisk file name.
- * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
* @bootaddr: MIC boot address.
- * @reset_trigger_work: Work for triggering reset requests.
- * @shutdown_work: Work for handling shutdown interrupts.
- * @state: MIC state.
- * @shutdown_status: MIC status reported by card for shutdown/crashes.
- * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
- * @reset_wait: Waitqueue for sleeping while reset completes.
- * @log_buf_addr: Log buffer address for MIC.
- * @log_buf_len: Log buffer length address for MIC.
* @dp: virtio device page
* @dp_dma_addr: virtio device page DMA address.
- * @shutdown_db: shutdown doorbell.
- * @shutdown_cookie: shutdown cookie.
- * @cdev: Character device for MIC.
+ * @name: name for the misc char device
+ * @miscdev: registered misc char device
* @vdev_list: list of virtio devices.
- * @pm_notifier: Handles PM notifications from the OS.
* @dma_mbdev: MIC BUS DMA device.
* @dma_ch - Array of DMA channels
* @num_dma_ch - Number of DMA channels available
* @scdev: SCIF device on the SCIF virtual bus.
+ * @cosm_dev: COSM device
*/
struct mic_device {
struct mic_mw mmio;
@@ -101,8 +80,7 @@ struct mic_device {
struct mic_hw_ops *ops;
int id;
enum mic_stepping stepping;
- const struct attribute_group **attr_group;
- struct device *sdev;
+ struct pci_dev *pdev;
struct mutex mic_mutex;
struct mic_hw_intr_ops *intr_ops;
struct mic_smpt_ops *smpt_ops;
@@ -110,30 +88,17 @@ struct mic_device {
struct mic_intr_info *intr_info;
struct mic_irq_info irq_info;
struct dentry *dbg_dir;
- char *cmdline;
- char *firmware;
- char *ramdisk;
- char *bootmode;
u32 bootaddr;
- struct work_struct reset_trigger_work;
- struct work_struct shutdown_work;
- u8 state;
- u8 shutdown_status;
- struct kernfs_node *state_sysfs;
- struct completion reset_wait;
- void *log_buf_addr;
- int *log_buf_len;
void *dp;
dma_addr_t dp_dma_addr;
- int shutdown_db;
- struct mic_irq *shutdown_cookie;
- struct cdev cdev;
+ char name[16];
+ struct miscdevice miscdev;
struct list_head vdev_list;
- struct notifier_block pm_notifier;
struct mbus_device *dma_mbdev;
struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
int num_dma_ch;
struct scif_hw_dev *scdev;
+ struct cosm_device *cosm_dev;
};
/**
@@ -199,38 +164,9 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
iowrite32(val, mw->va + offset);
}
-static inline struct dma_chan *mic_request_dma_chan(struct mic_device *mdev)
-{
- dma_cap_mask_t mask;
- struct dma_chan *chan;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_MEMCPY, mask);
- chan = dma_request_channel(mask, mdev->ops->dma_filter,
- mdev->sdev->parent);
- if (chan)
- return chan;
- dev_err(mdev->sdev->parent, "%s %d unable to acquire channel\n",
- __func__, __LINE__);
- return NULL;
-}
-
-void mic_sysfs_init(struct mic_device *mdev);
-int mic_start(struct mic_device *mdev, const char *buf);
-void mic_stop(struct mic_device *mdev, bool force);
-void mic_shutdown(struct mic_device *mdev);
-void mic_reset_delayed_work(struct work_struct *work);
-void mic_reset_trigger_work(struct work_struct *work);
-void mic_shutdown_work(struct work_struct *work);
void mic_bootparam_init(struct mic_device *mdev);
-void mic_set_state(struct mic_device *mdev, u8 state);
-void mic_set_shutdown_status(struct mic_device *mdev, u8 status);
void mic_create_debug_dir(struct mic_device *dev);
void mic_delete_debug_dir(struct mic_device *dev);
void __init mic_init_debugfs(void);
void mic_exit_debugfs(void);
-void mic_prepare_suspend(struct mic_device *mdev);
-void mic_complete_resume(struct mic_device *mdev);
-void mic_suspend(struct mic_device *mdev);
-extern atomic_t g_num_mics;
#endif
diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c
index 85776d7327f3..8cc1d90cd949 100644
--- a/drivers/misc/mic/host/mic_fops.c
+++ b/drivers/misc/mic/host/mic_fops.c
@@ -30,8 +30,8 @@
int mic_open(struct inode *inode, struct file *f)
{
struct mic_vdev *mvdev;
- struct mic_device *mdev = container_of(inode->i_cdev,
- struct mic_device, cdev);
+ struct mic_device *mdev = container_of(f->private_data,
+ struct mic_device, miscdev);
mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
if (!mvdev)
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
index b4ca6c884d19..08ca3e372fa4 100644
--- a/drivers/misc/mic/host/mic_intr.c
+++ b/drivers/misc/mic/host/mic_intr.c
@@ -30,8 +30,7 @@ static irqreturn_t mic_thread_fn(int irq, void *dev)
struct mic_intr_info *intr_info = mdev->intr_info;
struct mic_irq_info *irq_info = &mdev->irq_info;
struct mic_intr_cb *intr_cb;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
int i;
spin_lock(&irq_info->mic_thread_lock);
@@ -57,8 +56,7 @@ static irqreturn_t mic_interrupt(int irq, void *dev)
struct mic_intr_info *intr_info = mdev->intr_info;
struct mic_irq_info *irq_info = &mdev->irq_info;
struct mic_intr_cb *intr_cb;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
u32 mask;
int i;
@@ -83,7 +81,7 @@ static irqreturn_t mic_interrupt(int irq, void *dev)
/* Return the interrupt offset from the index. Index is 0 based. */
static u16 mic_map_src_to_offset(struct mic_device *mdev,
- int intr_src, enum mic_intr_type type)
+ int intr_src, enum mic_intr_type type)
{
if (type >= MIC_NUM_INTR_TYPES)
return MIC_NUM_OFFSETS;
@@ -214,7 +212,7 @@ static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
mdev->irq_info.msix_entries[i].entry = i;
rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries,
- MIC_MIN_MSIX);
+ MIC_MIN_MSIX);
if (rc) {
dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
goto err_enable_msix;
@@ -229,7 +227,7 @@ static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
goto err_nomem2;
}
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
return 0;
err_nomem2:
@@ -281,7 +279,6 @@ static void mic_release_callbacks(struct mic_device *mdev)
spin_lock(&mdev->irq_info.mic_thread_lock);
spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
for (i = 0; i < MIC_NUM_OFFSETS; i++) {
-
if (list_empty(&mdev->irq_info.cb_list[i]))
break;
@@ -443,12 +440,11 @@ mic_request_threaded_irq(struct mic_device *mdev,
unsigned long cookie = 0;
u16 entry;
struct mic_intr_cb *intr_cb;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
offset = mic_map_src_to_offset(mdev, intr_src, type);
if (offset >= MIC_NUM_OFFSETS) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"Error mapping index %d to a valid source id.\n",
intr_src);
rc = -EINVAL;
@@ -458,7 +454,7 @@ mic_request_threaded_irq(struct mic_device *mdev,
if (mdev->irq_info.num_vectors > 1) {
msix = mic_get_available_vector(mdev);
if (!msix) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"No MSIx vectors available for use.\n");
rc = -ENOSPC;
goto err;
@@ -467,7 +463,7 @@ mic_request_threaded_irq(struct mic_device *mdev,
rc = request_threaded_irq(msix->vector, handler, thread_fn,
0, name, data);
if (rc) {
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"request irq failed rc = %d\n", rc);
goto err;
}
@@ -476,13 +472,13 @@ mic_request_threaded_irq(struct mic_device *mdev,
mdev->intr_ops->program_msi_to_src_map(mdev,
entry, offset, true);
cookie = MK_COOKIE(entry, offset);
- dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
+ dev_dbg(&mdev->pdev->dev, "irq: %d assigned for src: %d\n",
msix->vector, intr_src);
} else {
intr_cb = mic_register_intr_callback(mdev, offset, handler,
thread_fn, data);
if (IS_ERR(intr_cb)) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"No available callback entries for use\n");
rc = PTR_ERR(intr_cb);
goto err;
@@ -495,7 +491,7 @@ mic_request_threaded_irq(struct mic_device *mdev,
entry, offset, true);
}
cookie = MK_COOKIE(entry, intr_cb->cb_id);
- dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
+ dev_dbg(&mdev->pdev->dev, "callback %d registered for src: %d\n",
intr_cb->cb_id, intr_src);
}
return (struct mic_irq *)cookie;
@@ -515,20 +511,19 @@ err:
* returns: none.
*/
void mic_free_irq(struct mic_device *mdev,
- struct mic_irq *cookie, void *data)
+ struct mic_irq *cookie, void *data)
{
u32 offset;
u32 entry;
u8 src_id;
unsigned int irq;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
entry = GET_ENTRY((unsigned long)cookie);
offset = GET_OFFSET((unsigned long)cookie);
if (mdev->irq_info.num_vectors > 1) {
if (entry >= mdev->irq_info.num_vectors) {
- dev_warn(mdev->sdev->parent,
+ dev_warn(&mdev->pdev->dev,
"entry %d should be < num_irq %d\n",
entry, mdev->irq_info.num_vectors);
return;
@@ -539,12 +534,12 @@ void mic_free_irq(struct mic_device *mdev,
mdev->intr_ops->program_msi_to_src_map(mdev,
entry, offset, false);
- dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
+ dev_dbg(&mdev->pdev->dev, "irq: %d freed\n", irq);
} else {
irq = pdev->irq;
src_id = mic_unregister_intr_callback(mdev, offset);
if (src_id >= MIC_NUM_OFFSETS) {
- dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
+ dev_warn(&mdev->pdev->dev, "Error unregistering callback\n");
return;
}
if (pci_dev_msi_enabled(pdev)) {
@@ -552,7 +547,7 @@ void mic_free_irq(struct mic_device *mdev,
mdev->intr_ops->program_msi_to_src_map(mdev,
entry, src_id, false);
}
- dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
+ dev_dbg(&mdev->pdev->dev, "callback %d unregistered for src: %d\n",
offset, src_id);
}
}
@@ -579,7 +574,7 @@ int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
rc = mic_setup_intx(mdev, pdev);
if (rc) {
- dev_err(mdev->sdev->parent, "no usable interrupts\n");
+ dev_err(&mdev->pdev->dev, "no usable interrupts\n");
return rc;
}
done:
@@ -635,8 +630,7 @@ void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
void mic_intr_restore(struct mic_device *mdev)
{
int entry, offset;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
if (!pci_dev_msi_enabled(pdev))
return;
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
index 456462932151..153894e7ed5b 100644
--- a/drivers/misc/mic/host/mic_main.c
+++ b/drivers/misc/mic/host/mic_main.c
@@ -16,17 +16,11 @@
* the file called "COPYING".
*
* Intel MIC Host driver.
- *
- * Global TODO's across the driver to be added after initial base
- * patches are accepted upstream:
- * 1) Enable DMA support.
- * 2) Enable per vring interrupt support.
*/
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/poll.h>
-#include <linux/suspend.h>
#include <linux/mic_common.h>
#include "../common/mic_dev.h"
@@ -63,12 +57,8 @@ MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
/* ID allocator for MIC devices */
static struct ida g_mic_ida;
-/* Class of MIC devices for sysfs accessibility. */
-static struct class *g_mic_class;
/* Base device node number for MIC devices */
static dev_t g_mic_devno;
-/* Track the total number of MIC devices */
-atomic_t g_num_mics;
static const struct file_operations mic_fops = {
.open = mic_open,
@@ -83,17 +73,14 @@ static const struct file_operations mic_fops = {
static int mic_dp_init(struct mic_device *mdev)
{
mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
- if (!mdev->dp) {
- dev_err(mdev->sdev->parent, "%s %d err %d\n",
- __func__, __LINE__, -ENOMEM);
+ if (!mdev->dp)
return -ENOMEM;
- }
mdev->dp_dma_addr = mic_map_single(mdev,
mdev->dp, MIC_DP_SIZE);
if (mic_map_error(mdev->dp_dma_addr)) {
kfree(mdev->dp);
- dev_err(mdev->sdev->parent, "%s %d err %d\n",
+ dev_err(&mdev->pdev->dev, "%s %d err %d\n",
__func__, __LINE__, -ENOMEM);
return -ENOMEM;
}
@@ -110,30 +97,6 @@ static void mic_dp_uninit(struct mic_device *mdev)
}
/**
- * mic_shutdown_db - Shutdown doorbell interrupt handler.
- */
-static irqreturn_t mic_shutdown_db(int irq, void *data)
-{
- struct mic_device *mdev = data;
- struct mic_bootparam *bootparam = mdev->dp;
-
- mdev->ops->intr_workarounds(mdev);
-
- switch (bootparam->shutdown_status) {
- case MIC_HALTED:
- case MIC_POWER_OFF:
- case MIC_RESTART:
- /* Fall through */
- case MIC_CRASHED:
- schedule_work(&mdev->shutdown_work);
- break;
- default:
- break;
- };
- return IRQ_HANDLED;
-}
-
-/**
* mic_ops_init: Initialize HW specific operation tables.
*
* @mdev: pointer to mic_device instance
@@ -190,43 +153,6 @@ static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
}
/**
-* mic_pm_notifier: Notifier callback function that handles
-* PM notifications.
-*
-* @notifier_block: The notifier structure.
-* @pm_event: The event for which the driver was notified.
-* @unused: Meaningless. Always NULL.
-*
-* returns NOTIFY_DONE
-*/
-static int mic_pm_notifier(struct notifier_block *notifier,
- unsigned long pm_event, void *unused)
-{
- struct mic_device *mdev = container_of(notifier,
- struct mic_device, pm_notifier);
-
- switch (pm_event) {
- case PM_HIBERNATION_PREPARE:
- /* Fall through */
- case PM_SUSPEND_PREPARE:
- mic_prepare_suspend(mdev);
- break;
- case PM_POST_HIBERNATION:
- /* Fall through */
- case PM_POST_SUSPEND:
- /* Fall through */
- case PM_POST_RESTORE:
- mic_complete_resume(mdev);
- break;
- case PM_RESTORE_PREPARE:
- break;
- default:
- break;
- }
- return NOTIFY_DONE;
-}
-
-/**
* mic_device_init - Allocates and initializes the MIC device structure
*
* @mdev: pointer to mic_device instance
@@ -234,52 +160,16 @@ static int mic_pm_notifier(struct notifier_block *notifier,
*
* returns none.
*/
-static int
+static void
mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
{
- int rc;
-
+ mdev->pdev = pdev;
mdev->family = mic_get_family(pdev);
mdev->stepping = pdev->revision;
mic_ops_init(mdev);
- mic_sysfs_init(mdev);
mutex_init(&mdev->mic_mutex);
mdev->irq_info.next_avail_src = 0;
- INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work);
- INIT_WORK(&mdev->shutdown_work, mic_shutdown_work);
- init_completion(&mdev->reset_wait);
INIT_LIST_HEAD(&mdev->vdev_list);
- mdev->pm_notifier.notifier_call = mic_pm_notifier;
- rc = register_pm_notifier(&mdev->pm_notifier);
- if (rc) {
- dev_err(&pdev->dev, "register_pm_notifier failed rc %d\n",
- rc);
- goto register_pm_notifier_fail;
- }
- return 0;
-register_pm_notifier_fail:
- flush_work(&mdev->shutdown_work);
- flush_work(&mdev->reset_trigger_work);
- return rc;
-}
-
-/**
- * mic_device_uninit - Frees resources allocated during mic_device_init(..)
- *
- * @mdev: pointer to mic_device instance
- *
- * returns none
- */
-static void mic_device_uninit(struct mic_device *mdev)
-{
- /* The cmdline sysfs entry might have allocated cmdline */
- kfree(mdev->cmdline);
- kfree(mdev->firmware);
- kfree(mdev->ramdisk);
- kfree(mdev->bootmode);
- flush_work(&mdev->reset_trigger_work);
- flush_work(&mdev->shutdown_work);
- unregister_pm_notifier(&mdev->pm_notifier);
}
/**
@@ -291,7 +181,7 @@ static void mic_device_uninit(struct mic_device *mdev)
* returns 0 on success, < 0 on failure.
*/
static int mic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
int rc;
struct mic_device *mdev;
@@ -309,16 +199,12 @@ static int mic_probe(struct pci_dev *pdev,
goto ida_fail;
}
- rc = mic_device_init(mdev, pdev);
- if (rc) {
- dev_err(&pdev->dev, "mic_device_init failed rc %d\n", rc);
- goto device_init_fail;
- }
+ mic_device_init(mdev, pdev);
rc = pci_enable_device(pdev);
if (rc) {
dev_err(&pdev->dev, "failed to enable pci device.\n");
- goto uninit_device;
+ goto ida_remove;
}
pci_set_master(pdev);
@@ -367,62 +253,39 @@ static int mic_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, mdev);
- mdev->sdev = device_create_with_groups(g_mic_class, &pdev->dev,
- MKDEV(MAJOR(g_mic_devno), mdev->id), NULL,
- mdev->attr_group, "mic%d", mdev->id);
- if (IS_ERR(mdev->sdev)) {
- rc = PTR_ERR(mdev->sdev);
- dev_err(&pdev->dev,
- "device_create_with_groups failed rc %d\n", rc);
- goto smpt_uninit;
- }
- mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd, "state");
- if (!mdev->state_sysfs) {
- rc = -ENODEV;
- dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
- goto destroy_device;
- }
-
rc = mic_dp_init(mdev);
if (rc) {
dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
- goto sysfs_put;
- }
- mutex_lock(&mdev->mic_mutex);
-
- mdev->shutdown_db = mic_next_db(mdev);
- mdev->shutdown_cookie = mic_request_threaded_irq(mdev, mic_shutdown_db,
- NULL, "shutdown-interrupt", mdev,
- mdev->shutdown_db, MIC_INTR_DB);
- if (IS_ERR(mdev->shutdown_cookie)) {
- rc = PTR_ERR(mdev->shutdown_cookie);
- mutex_unlock(&mdev->mic_mutex);
- goto dp_uninit;
+ goto smpt_uninit;
}
- mutex_unlock(&mdev->mic_mutex);
mic_bootparam_init(mdev);
mic_create_debug_dir(mdev);
- cdev_init(&mdev->cdev, &mic_fops);
- mdev->cdev.owner = THIS_MODULE;
- rc = cdev_add(&mdev->cdev, MKDEV(MAJOR(g_mic_devno), mdev->id), 1);
+
+ mdev->miscdev.minor = MISC_DYNAMIC_MINOR;
+ snprintf(mdev->name, sizeof(mdev->name), "mic%d", mdev->id);
+ mdev->miscdev.name = mdev->name;
+ mdev->miscdev.fops = &mic_fops;
+ mdev->miscdev.parent = &mdev->pdev->dev;
+ rc = misc_register(&mdev->miscdev);
if (rc) {
- dev_err(&pdev->dev, "cdev_add err id %d rc %d\n", mdev->id, rc);
+ dev_err(&pdev->dev, "misc_register err id %d rc %d\n",
+ mdev->id, rc);
goto cleanup_debug_dir;
}
- atomic_inc(&g_num_mics);
+
+ mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops);
+ if (IS_ERR(mdev->cosm_dev)) {
+ rc = PTR_ERR(mdev->cosm_dev);
+ dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc);
+ goto misc_dereg;
+ }
return 0;
+misc_dereg:
+ misc_deregister(&mdev->miscdev);
cleanup_debug_dir:
mic_delete_debug_dir(mdev);
- mutex_lock(&mdev->mic_mutex);
- mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
- mutex_unlock(&mdev->mic_mutex);
-dp_uninit:
mic_dp_uninit(mdev);
-sysfs_put:
- sysfs_put(mdev->state_sysfs);
-destroy_device:
- device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
smpt_uninit:
mic_smpt_uninit(mdev);
free_interrupts:
@@ -435,9 +298,7 @@ release_regions:
pci_release_regions(pdev);
disable_device:
pci_disable_device(pdev);
-uninit_device:
- mic_device_uninit(mdev);
-device_init_fail:
+ida_remove:
ida_simple_remove(&g_mic_ida, mdev->id);
ida_fail:
kfree(mdev);
@@ -461,22 +322,14 @@ static void mic_remove(struct pci_dev *pdev)
if (!mdev)
return;
- mic_stop(mdev, false);
- atomic_dec(&g_num_mics);
- cdev_del(&mdev->cdev);
+ cosm_unregister_device(mdev->cosm_dev);
+ misc_deregister(&mdev->miscdev);
mic_delete_debug_dir(mdev);
- mutex_lock(&mdev->mic_mutex);
- mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
- mutex_unlock(&mdev->mic_mutex);
- flush_work(&mdev->shutdown_work);
mic_dp_uninit(mdev);
- sysfs_put(mdev->state_sysfs);
- device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
mic_smpt_uninit(mdev);
mic_free_interrupts(mdev, pdev);
- iounmap(mdev->mmio.va);
iounmap(mdev->aper.va);
- mic_device_uninit(mdev);
+ iounmap(mdev->mmio.va);
pci_release_regions(pdev);
pci_disable_device(pdev);
ida_simple_remove(&g_mic_ida, mdev->id);
@@ -495,32 +348,23 @@ static int __init mic_init(void)
int ret;
ret = alloc_chrdev_region(&g_mic_devno, 0,
- MIC_MAX_NUM_DEVS, mic_driver_name);
+ MIC_MAX_NUM_DEVS, mic_driver_name);
if (ret) {
pr_err("alloc_chrdev_region failed ret %d\n", ret);
goto error;
}
- g_mic_class = class_create(THIS_MODULE, mic_driver_name);
- if (IS_ERR(g_mic_class)) {
- ret = PTR_ERR(g_mic_class);
- pr_err("class_create failed ret %d\n", ret);
- goto cleanup_chrdev;
- }
-
mic_init_debugfs();
ida_init(&g_mic_ida);
ret = pci_register_driver(&mic_driver);
if (ret) {
pr_err("pci_register_driver failed ret %d\n", ret);
- goto cleanup_debugfs;
+ goto cleanup_chrdev;
}
return ret;
-cleanup_debugfs:
+cleanup_chrdev:
ida_destroy(&g_mic_ida);
mic_exit_debugfs();
- class_destroy(g_mic_class);
-cleanup_chrdev:
unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
error:
return ret;
@@ -531,7 +375,6 @@ static void __exit mic_exit(void)
pci_unregister_driver(&mic_driver);
ida_destroy(&g_mic_ida);
mic_exit_debugfs();
- class_destroy(g_mic_class);
unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
}
diff --git a/drivers/misc/mic/host/mic_smpt.c b/drivers/misc/mic/host/mic_smpt.c
index cec82034875f..c3f958580fb0 100644
--- a/drivers/misc/mic/host/mic_smpt.c
+++ b/drivers/misc/mic/host/mic_smpt.c
@@ -76,7 +76,7 @@ mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
/* Populate an SMPT entry and update the reference counts. */
static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
- int entries, struct mic_device *mdev)
+ int entries, struct mic_device *mdev)
{
struct mic_smpt_info *smpt_info = mdev->smpt;
int i;
@@ -97,7 +97,7 @@ static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
* for a given DMA address and size.
*/
static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
- int entries, s64 *ref, size_t size)
+ int entries, s64 *ref, size_t size)
{
int spt;
int ae = 0;
@@ -148,7 +148,7 @@ found:
* and the starting smpt address
*/
static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
- size_t size, s64 *ref, u64 *smpt_start)
+ size_t size, s64 *ref, u64 *smpt_start)
{
u64 start = dma_addr;
u64 end = dma_addr + size;
@@ -181,7 +181,7 @@ dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
dma_addr_t dma_addr;
if (!mic_is_system_addr(mdev, mic_addr)) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
return -EINVAL;
}
@@ -218,7 +218,7 @@ dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
return mic_addr;
num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
- ref, &smpt_start);
+ ref, &smpt_start);
/* Set the smpt table appropriately and get 16G aligned mic address */
mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
@@ -231,7 +231,7 @@ dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
* else generate mic_addr by adding the 16G offset in dma_addr
*/
if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"mic_map failed dma_addr 0x%llx size 0x%lx\n",
dma_addr, size);
return mic_addr;
@@ -264,7 +264,7 @@ void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
return;
if (!mic_is_system_addr(mdev, mic_addr)) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"invalid address: 0x%llx\n", mic_addr);
return;
}
@@ -284,7 +284,7 @@ void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
for (i = spt; i < spt + num_smpt; i++) {
smpt_info->entry[i].ref_count -= ref[i - spt];
if (smpt_info->entry[i].ref_count < 0)
- dev_warn(mdev->sdev->parent,
+ dev_warn(&mdev->pdev->dev,
"ref count for entry %d is negative\n", i);
}
spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
@@ -307,15 +307,14 @@ void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
{
dma_addr_t mic_addr = 0;
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
dma_addr_t dma_addr =
pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
if (!pci_dma_mapping_error(pdev, dma_addr)) {
mic_addr = mic_map(mdev, dma_addr, size);
if (!mic_addr) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"mic_map failed dma_addr 0x%llx size 0x%lx\n",
dma_addr, size);
pci_unmap_single(pdev, dma_addr,
@@ -339,8 +338,7 @@ dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
void
mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
{
- struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev *pdev = mdev->pdev;
dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
mic_unmap(mdev, mic_addr, size);
pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
@@ -399,18 +397,18 @@ void mic_smpt_uninit(struct mic_device *mdev)
struct mic_smpt_info *smpt_info = mdev->smpt;
int i;
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
mdev->id, smpt_info->ref_count,
smpt_info->map_count, smpt_info->unmap_count);
for (i = 0; i < smpt_info->info.num_reg; i++) {
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
i, smpt_info->entry[i].dma_addr,
smpt_info->entry[i].ref_count);
if (smpt_info->entry[i].ref_count)
- dev_warn(mdev->sdev->parent,
+ dev_warn(&mdev->pdev->dev,
"ref count for entry %d is not zero\n", i);
}
kfree(smpt_info->entry);
diff --git a/drivers/misc/mic/host/mic_sysfs.c b/drivers/misc/mic/host/mic_sysfs.c
deleted file mode 100644
index 6dd864e4a617..000000000000
--- a/drivers/misc/mic/host/mic_sysfs.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Intel MIC Platform Software Stack (MPSS)
- *
- * Copyright(c) 2013 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT 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".
- *
- * Intel MIC Host driver.
- *
- */
-#include <linux/pci.h>
-
-#include <linux/mic_common.h>
-#include "../common/mic_dev.h"
-#include "mic_device.h"
-
-/*
- * A state-to-string lookup table, for exposing a human readable state
- * via sysfs. Always keep in sync with enum mic_states
- */
-static const char * const mic_state_string[] = {
- [MIC_OFFLINE] = "offline",
- [MIC_ONLINE] = "online",
- [MIC_SHUTTING_DOWN] = "shutting_down",
- [MIC_RESET_FAILED] = "reset_failed",
- [MIC_SUSPENDING] = "suspending",
- [MIC_SUSPENDED] = "suspended",
-};
-
-/*
- * A shutdown-status-to-string lookup table, for exposing a human
- * readable state via sysfs. Always keep in sync with enum mic_shutdown_status
- */
-static const char * const mic_shutdown_status_string[] = {
- [MIC_NOP] = "nop",
- [MIC_CRASHED] = "crashed",
- [MIC_HALTED] = "halted",
- [MIC_POWER_OFF] = "poweroff",
- [MIC_RESTART] = "restart",
-};
-
-void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status)
-{
- dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n",
- mic_shutdown_status_string[mdev->shutdown_status],
- mic_shutdown_status_string[shutdown_status]);
- mdev->shutdown_status = shutdown_status;
-}
-
-void mic_set_state(struct mic_device *mdev, u8 state)
-{
- dev_dbg(mdev->sdev->parent, "State %s -> %s\n",
- mic_state_string[mdev->state],
- mic_state_string[state]);
- mdev->state = state;
- sysfs_notify_dirent(mdev->state_sysfs);
-}
-
-static ssize_t
-family_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- static const char x100[] = "x100";
- static const char unknown[] = "Unknown";
- const char *card = NULL;
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- switch (mdev->family) {
- case MIC_FAMILY_X100:
- card = x100;
- break;
- default:
- card = unknown;
- break;
- }
- return scnprintf(buf, PAGE_SIZE, "%s\n", card);
-}
-static DEVICE_ATTR_RO(family);
-
-static ssize_t
-stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- char *string = "??";
-
- if (!mdev)
- return -EINVAL;
-
- switch (mdev->stepping) {
- case MIC_A0_STEP:
- string = "A0";
- break;
- case MIC_B0_STEP:
- string = "B0";
- break;
- case MIC_B1_STEP:
- string = "B1";
- break;
- case MIC_C0_STEP:
- string = "C0";
- break;
- default:
- break;
- }
- return scnprintf(buf, PAGE_SIZE, "%s\n", string);
-}
-static DEVICE_ATTR_RO(stepping);
-
-static ssize_t
-state_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev || mdev->state >= MIC_LAST)
- return -EINVAL;
-
- return scnprintf(buf, PAGE_SIZE, "%s\n",
- mic_state_string[mdev->state]);
-}
-
-static ssize_t
-state_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int rc = 0;
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- if (!mdev)
- return -EINVAL;
- if (sysfs_streq(buf, "boot")) {
- rc = mic_start(mdev, buf);
- if (rc) {
- dev_err(mdev->sdev->parent,
- "mic_boot failed rc %d\n", rc);
- count = rc;
- }
- goto done;
- }
-
- if (sysfs_streq(buf, "reset")) {
- schedule_work(&mdev->reset_trigger_work);
- goto done;
- }
-
- if (sysfs_streq(buf, "shutdown")) {
- mic_shutdown(mdev);
- goto done;
- }
-
- if (sysfs_streq(buf, "suspend")) {
- mic_suspend(mdev);
- goto done;
- }
-
- count = -EINVAL;
-done:
- return count;
-}
-static DEVICE_ATTR_RW(state);
-
-static ssize_t shutdown_status_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST)
- return -EINVAL;
-
- return scnprintf(buf, PAGE_SIZE, "%s\n",
- mic_shutdown_status_string[mdev->shutdown_status]);
-}
-static DEVICE_ATTR_RO(shutdown_status);
-
-static ssize_t
-cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- char *cmdline;
-
- if (!mdev)
- return -EINVAL;
-
- cmdline = mdev->cmdline;
-
- if (cmdline)
- return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
- return 0;
-}
-
-static ssize_t
-cmdline_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- mutex_lock(&mdev->mic_mutex);
- kfree(mdev->cmdline);
-
- mdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
- if (!mdev->cmdline) {
- count = -ENOMEM;
- goto unlock;
- }
-
- strncpy(mdev->cmdline, buf, count);
-
- if (mdev->cmdline[count - 1] == '\n')
- mdev->cmdline[count - 1] = '\0';
- else
- mdev->cmdline[count] = '\0';
-unlock:
- mutex_unlock(&mdev->mic_mutex);
- return count;
-}
-static DEVICE_ATTR_RW(cmdline);
-
-static ssize_t
-firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- char *firmware;
-
- if (!mdev)
- return -EINVAL;
-
- firmware = mdev->firmware;
-
- if (firmware)
- return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
- return 0;
-}
-
-static ssize_t
-firmware_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- mutex_lock(&mdev->mic_mutex);
- kfree(mdev->firmware);
-
- mdev->firmware = kmalloc(count + 1, GFP_KERNEL);
- if (!mdev->firmware) {
- count = -ENOMEM;
- goto unlock;
- }
- strncpy(mdev->firmware, buf, count);
-
- if (mdev->firmware[count - 1] == '\n')
- mdev->firmware[count - 1] = '\0';
- else
- mdev->firmware[count] = '\0';
-unlock:
- mutex_unlock(&mdev->mic_mutex);
- return count;
-}
-static DEVICE_ATTR_RW(firmware);
-
-static ssize_t
-ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- char *ramdisk;
-
- if (!mdev)
- return -EINVAL;
-
- ramdisk = mdev->ramdisk;
-
- if (ramdisk)
- return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
- return 0;
-}
-
-static ssize_t
-ramdisk_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- mutex_lock(&mdev->mic_mutex);
- kfree(mdev->ramdisk);
-
- mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
- if (!mdev->ramdisk) {
- count = -ENOMEM;
- goto unlock;
- }
-
- strncpy(mdev->ramdisk, buf, count);
-
- if (mdev->ramdisk[count - 1] == '\n')
- mdev->ramdisk[count - 1] = '\0';
- else
- mdev->ramdisk[count] = '\0';
-unlock:
- mutex_unlock(&mdev->mic_mutex);
- return count;
-}
-static DEVICE_ATTR_RW(ramdisk);
-
-static ssize_t
-bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- char *bootmode;
-
- if (!mdev)
- return -EINVAL;
-
- bootmode = mdev->bootmode;
-
- if (bootmode)
- return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
- return 0;
-}
-
-static ssize_t
-bootmode_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf"))
- return -EINVAL;
-
- mutex_lock(&mdev->mic_mutex);
- kfree(mdev->bootmode);
-
- mdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
- if (!mdev->bootmode) {
- count = -ENOMEM;
- goto unlock;
- }
-
- strncpy(mdev->bootmode, buf, count);
-
- if (mdev->bootmode[count - 1] == '\n')
- mdev->bootmode[count - 1] = '\0';
- else
- mdev->bootmode[count] = '\0';
-unlock:
- mutex_unlock(&mdev->mic_mutex);
- return count;
-}
-static DEVICE_ATTR_RW(bootmode);
-
-static ssize_t
-log_buf_addr_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr);
-}
-
-static ssize_t
-log_buf_addr_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- int ret;
- unsigned long addr;
-
- if (!mdev)
- return -EINVAL;
-
- ret = kstrtoul(buf, 16, &addr);
- if (ret)
- goto exit;
-
- mdev->log_buf_addr = (void *)addr;
- ret = count;
-exit:
- return ret;
-}
-static DEVICE_ATTR_RW(log_buf_addr);
-
-static ssize_t
-log_buf_len_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
-
- if (!mdev)
- return -EINVAL;
-
- return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len);
-}
-
-static ssize_t
-log_buf_len_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mic_device *mdev = dev_get_drvdata(dev->parent);
- int ret;
- unsigned long addr;
-
- if (!mdev)
- return -EINVAL;
-
- ret = kstrtoul(buf, 16, &addr);
- if (ret)
- goto exit;
-
- mdev->log_buf_len = (int *)addr;
- ret = count;
-exit:
- return ret;
-}
-static DEVICE_ATTR_RW(log_buf_len);
-
-static struct attribute *mic_default_attrs[] = {
- &dev_attr_family.attr,
- &dev_attr_stepping.attr,
- &dev_attr_state.attr,
- &dev_attr_shutdown_status.attr,
- &dev_attr_cmdline.attr,
- &dev_attr_firmware.attr,
- &dev_attr_ramdisk.attr,
- &dev_attr_bootmode.attr,
- &dev_attr_log_buf_addr.attr,
- &dev_attr_log_buf_len.attr,
-
- NULL
-};
-
-ATTRIBUTE_GROUPS(mic_default);
-
-void mic_sysfs_init(struct mic_device *mdev)
-{
- mdev->attr_group = mic_default_groups;
-}
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
index cc08e9f733c9..58b107a24a8b 100644
--- a/drivers/misc/mic/host/mic_virtio.c
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -23,7 +23,6 @@
#include <linux/uaccess.h>
#include <linux/dmaengine.h>
#include <linux/mic_common.h>
-
#include "../common/mic_dev.h"
#include "mic_device.h"
#include "mic_smpt.h"
@@ -62,7 +61,7 @@ static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst,
}
error:
if (err)
- dev_err(mdev->sdev->parent, "%s %d err %d\n",
+ dev_err(&mdev->pdev->dev, "%s %d err %d\n",
__func__, __LINE__, err);
return err;
}
@@ -440,7 +439,7 @@ void mic_virtio_reset_devices(struct mic_device *mdev)
struct list_head *pos, *tmp;
struct mic_vdev *mvdev;
- dev_dbg(mdev->sdev->parent, "%s\n", __func__);
+ dev_dbg(&mdev->pdev->dev, "%s\n", __func__);
list_for_each_safe(pos, tmp, &mdev->vdev_list) {
mvdev = list_entry(pos, struct mic_vdev, list);
@@ -686,7 +685,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
mvr->head = USHRT_MAX;
mvr->mvdev = mvdev;
mvr->vrh.notify = mic_notify;
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"%s %d index %d va %p info %p vr_size 0x%x\n",
__func__, __LINE__, i, vr->va, vr->info, vr_size);
mvr->buf = (void *)__get_free_pages(GFP_KERNEL,
@@ -704,7 +703,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
mvdev->virtio_db, MIC_INTR_DB);
if (IS_ERR(mvdev->virtio_cookie)) {
ret = PTR_ERR(mvdev->virtio_cookie);
- dev_dbg(mdev->sdev->parent, "request irq failed\n");
+ dev_dbg(&mdev->pdev->dev, "request irq failed\n");
goto err;
}
@@ -720,7 +719,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
smp_wmb();
dd->type = type;
- dev_dbg(mdev->sdev->parent, "Added virtio device id %d\n", dd->type);
+ dev_dbg(&mdev->pdev->dev, "Added virtio device id %d\n", dd->type);
db = bootparam->h2c_config_db;
if (db != -1)
@@ -755,7 +754,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
db = bootparam->h2c_config_db;
if (db == -1)
goto skip_hot_remove;
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"Requesting hot remove id %d\n", mvdev->virtio_id);
mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
mdev->ops->send_intr(mdev, db);
@@ -765,7 +764,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
if (ret)
break;
}
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"Device id %d config_change %d guest_ack %d retry %d\n",
mvdev->virtio_id, mvdev->dc->config_change,
mvdev->dc->guest_ack, retry);
@@ -794,7 +793,7 @@ skip_hot_remove:
tmp_mvdev = list_entry(pos, struct mic_vdev, list);
if (tmp_mvdev == mvdev) {
list_del(pos);
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"Removing virtio device id %d\n",
mvdev->virtio_id);
break;
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
index d574efb853d9..a80631f2790d 100644
--- a/drivers/misc/mic/host/mic_virtio.h
+++ b/drivers/misc/mic/host/mic_virtio.h
@@ -124,7 +124,7 @@ void mic_bh_handler(struct work_struct *work);
/* Helper API to obtain the MIC PCIe device */
static inline struct device *mic_dev(struct mic_vdev *mvdev)
{
- return mvdev->mdev->sdev->parent;
+ return &mvdev->mdev->pdev->dev;
}
/* Helper API to check if a virtio device is initialized */
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
index 3341e90dede4..8118ac48c764 100644
--- a/drivers/misc/mic/host/mic_x100.c
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -43,7 +43,7 @@
static void
mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
{
- dev_dbg(mdev->sdev->parent, "Writing 0x%x to scratch pad index %d\n",
+ dev_dbg(&mdev->pdev->dev, "Writing 0x%x to scratch pad index %d\n",
val, idx);
mic_mmio_write(&mdev->mmio, val,
MIC_X100_SBOX_BASE_ADDRESS +
@@ -66,7 +66,7 @@ mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
MIC_X100_SBOX_BASE_ADDRESS +
MIC_X100_SBOX_SPAD0 + idx * 4);
- dev_dbg(mdev->sdev->parent,
+ dev_dbg(&mdev->pdev->dev,
"Reading 0x%x from scratch pad index %d\n", val, idx);
return val;
}
@@ -126,7 +126,7 @@ static void mic_x100_disable_interrupts(struct mic_device *mdev)
* @mdev: pointer to mic_device instance
*/
static void mic_x100_send_sbox_intr(struct mic_device *mdev,
- int doorbell)
+ int doorbell)
{
struct mic_mw *mw = &mdev->mmio;
u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
@@ -147,7 +147,7 @@ static void mic_x100_send_sbox_intr(struct mic_device *mdev,
* @mdev: pointer to mic_device instance
*/
static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
- int doorbell)
+ int doorbell)
{
int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
/* Ensure that the interrupt is ordered w.r.t. previous stores. */
@@ -359,15 +359,14 @@ mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw)
boot_mem = mdev->aper.len >> 20;
buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
- if (!buf) {
- dev_err(mdev->sdev->parent,
- "%s %d allocation failed\n", __func__, __LINE__);
+ if (!buf)
return -ENOMEM;
- }
+
len += snprintf(buf, CMDLINE_SIZE - len,
" mem=%dM", boot_mem);
- if (mdev->cmdline)
- snprintf(buf + len, CMDLINE_SIZE - len, " %s", mdev->cmdline);
+ if (mdev->cosm_dev->cmdline)
+ snprintf(buf + len, CMDLINE_SIZE - len, " %s",
+ mdev->cosm_dev->cmdline);
memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
kfree(buf);
return 0;
@@ -386,12 +385,11 @@ mic_x100_load_ramdisk(struct mic_device *mdev)
int rc;
struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr;
- rc = request_firmware(&fw,
- mdev->ramdisk, mdev->sdev->parent);
+ rc = request_firmware(&fw, mdev->cosm_dev->ramdisk, &mdev->pdev->dev);
if (rc < 0) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"ramdisk request_firmware failed: %d %s\n",
- rc, mdev->ramdisk);
+ rc, mdev->cosm_dev->ramdisk);
goto error;
}
/*
@@ -423,10 +421,10 @@ mic_x100_get_boot_addr(struct mic_device *mdev)
scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
- dev_dbg(mdev->sdev->parent, "%s %d boot_addr 0x%x\n",
+ dev_dbg(&mdev->pdev->dev, "%s %d boot_addr 0x%x\n",
__func__, __LINE__, boot_addr);
if (boot_addr > (1 << 31)) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"incorrect bootaddr 0x%x\n",
boot_addr);
rc = -EINVAL;
@@ -454,37 +452,37 @@ mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
if (rc)
goto error;
/* load OS */
- rc = request_firmware(&fw, mdev->firmware, mdev->sdev->parent);
+ rc = request_firmware(&fw, mdev->cosm_dev->firmware, &mdev->pdev->dev);
if (rc < 0) {
- dev_err(mdev->sdev->parent,
+ dev_err(&mdev->pdev->dev,
"ramdisk request_firmware failed: %d %s\n",
- rc, mdev->firmware);
+ rc, mdev->cosm_dev->firmware);
goto error;
}
if (mdev->bootaddr > mdev->aper.len - fw->size) {
rc = -EINVAL;
- dev_err(mdev->sdev->parent, "%s %d rc %d bootaddr 0x%x\n",
+ dev_err(&mdev->pdev->dev, "%s %d rc %d bootaddr 0x%x\n",
__func__, __LINE__, rc, mdev->bootaddr);
release_firmware(fw);
goto error;
}
memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
- if (!strcmp(mdev->bootmode, "elf"))
+ if (!strcmp(mdev->cosm_dev->bootmode, "flash"))
goto done;
/* load command line */
rc = mic_x100_load_command_line(mdev, fw);
if (rc) {
- dev_err(mdev->sdev->parent, "%s %d rc %d\n",
+ dev_err(&mdev->pdev->dev, "%s %d rc %d\n",
__func__, __LINE__, rc);
goto error;
}
release_firmware(fw);
/* load ramdisk */
- if (mdev->ramdisk)
+ if (mdev->cosm_dev->ramdisk)
rc = mic_x100_load_ramdisk(mdev);
error:
- dev_dbg(mdev->sdev->parent, "%s %d rc %d\n", __func__, __LINE__, rc);
+ dev_dbg(&mdev->pdev->dev, "%s %d rc %d\n", __func__, __LINE__, rc);
done:
return rc;
}
diff --git a/drivers/misc/mic/scif/Makefile b/drivers/misc/mic/scif/Makefile
index bf10bb7e2b91..29cfc3e51ac9 100644
--- a/drivers/misc/mic/scif/Makefile
+++ b/drivers/misc/mic/scif/Makefile
@@ -13,3 +13,8 @@ scif-objs += scif_epd.o
scif-objs += scif_rb.o
scif-objs += scif_nodeqp.o
scif-objs += scif_nm.o
+scif-objs += scif_dma.o
+scif-objs += scif_fence.o
+scif-objs += scif_mmap.o
+scif-objs += scif_rma.o
+scif-objs += scif_rma_list.o
diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c
index f39d3135a9ef..ddc9e4b08b5c 100644
--- a/drivers/misc/mic/scif/scif_api.c
+++ b/drivers/misc/mic/scif/scif_api.c
@@ -37,9 +37,21 @@ enum conn_async_state {
ASYNC_CONN_FLUSH_WORK /* async work flush in progress */
};
+/*
+ * File operations for anonymous inode file associated with a SCIF endpoint,
+ * used in kernel mode SCIF poll. Kernel mode SCIF poll calls portions of the
+ * poll API in the kernel and these take in a struct file *. Since a struct
+ * file is not available to kernel mode SCIF, it uses an anonymous file for
+ * this purpose.
+ */
+const struct file_operations scif_anon_fops = {
+ .owner = THIS_MODULE,
+};
+
scif_epd_t scif_open(void)
{
struct scif_endpt *ep;
+ int err;
might_sleep();
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -50,15 +62,22 @@ scif_epd_t scif_open(void)
if (!ep->qp_info.qp)
goto err_qp_alloc;
+ err = scif_anon_inode_getfile(ep);
+ if (err)
+ goto err_anon_inode;
+
spin_lock_init(&ep->lock);
mutex_init(&ep->sendlock);
mutex_init(&ep->recvlock);
+ scif_rma_ep_init(ep);
ep->state = SCIFEP_UNBOUND;
dev_dbg(scif_info.mdev.this_device,
"SCIFAPI open: ep %p success\n", ep);
return ep;
+err_anon_inode:
+ kfree(ep->qp_info.qp);
err_qp_alloc:
kfree(ep);
err_ep_alloc:
@@ -166,8 +185,11 @@ int scif_close(scif_epd_t epd)
switch (oldstate) {
case SCIFEP_ZOMBIE:
+ dev_err(scif_info.mdev.this_device,
+ "SCIFAPI close: zombie state unexpected\n");
case SCIFEP_DISCONNECTED:
spin_unlock(&ep->lock);
+ scif_unregister_all_windows(epd);
/* Remove from the disconnected list */
mutex_lock(&scif_info.connlock);
list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
@@ -189,6 +211,7 @@ int scif_close(scif_epd_t epd)
case SCIFEP_CLOSING:
{
spin_unlock(&ep->lock);
+ scif_unregister_all_windows(epd);
scif_disconnect_ep(ep);
break;
}
@@ -200,7 +223,7 @@ int scif_close(scif_epd_t epd)
struct scif_endpt *aep;
spin_unlock(&ep->lock);
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
/* remove from listen list */
list_for_each_safe(pos, tmpq, &scif_info.listen) {
@@ -222,7 +245,7 @@ int scif_close(scif_epd_t epd)
break;
}
}
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
mutex_lock(&scif_info.connlock);
list_for_each_safe(pos, tmpq, &scif_info.connected) {
tmpep = list_entry(pos,
@@ -242,13 +265,13 @@ int scif_close(scif_epd_t epd)
}
mutex_unlock(&scif_info.connlock);
scif_teardown_ep(aep);
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
scif_add_epd_to_zombie_list(aep, SCIF_EPLOCK_HELD);
ep->acceptcnt--;
}
spin_lock(&ep->lock);
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
/* Remove and reject any pending connection requests. */
while (ep->conreqcnt) {
@@ -279,6 +302,7 @@ int scif_close(scif_epd_t epd)
}
}
scif_put_port(ep->port.port);
+ scif_anon_inode_fput(ep);
scif_teardown_ep(ep);
scif_add_epd_to_zombie_list(ep, !SCIF_EPLOCK_HELD);
return 0;
@@ -409,9 +433,9 @@ int scif_listen(scif_epd_t epd, int backlog)
scif_teardown_ep(ep);
ep->qp_info.qp = NULL;
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
list_add_tail(&ep->list, &scif_info.listen);
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
return 0;
}
EXPORT_SYMBOL_GPL(scif_listen);
@@ -450,6 +474,13 @@ static int scif_conn_func(struct scif_endpt *ep)
struct scifmsg msg;
struct device *spdev;
+ err = scif_reserve_dma_chan(ep);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ ep->state = SCIFEP_BOUND;
+ goto connect_error_simple;
+ }
/* Initiate the first part of the endpoint QP setup */
err = scif_setup_qp_connect(ep->qp_info.qp, &ep->qp_info.qp_offset,
SCIF_ENDPT_QP_SIZE, ep->remote_dev);
@@ -558,8 +589,10 @@ void scif_conn_handler(struct work_struct *work)
list_del(&ep->conn_list);
}
spin_unlock(&scif_info.nb_connect_lock);
- if (ep)
+ if (ep) {
ep->conn_err = scif_conn_func(ep);
+ wake_up_interruptible(&ep->conn_pend_wq);
+ }
} while (ep);
}
@@ -660,6 +693,7 @@ int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block)
ep->remote_dev = &scif_dev[dst->node];
ep->qp_info.qp->magic = SCIFEP_MAGIC;
if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
+ init_waitqueue_head(&ep->conn_pend_wq);
spin_lock(&scif_info.nb_connect_lock);
list_add_tail(&ep->conn_list, &scif_info.nb_connect_list);
spin_unlock(&scif_info.nb_connect_lock);
@@ -782,12 +816,25 @@ retry_connection:
cep->remote_dev = &scif_dev[peer->node];
cep->remote_ep = conreq->msg.payload[0];
+ scif_rma_ep_init(cep);
+
+ err = scif_reserve_dma_chan(cep);
+ if (err) {
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto scif_accept_error_qpalloc;
+ }
+
cep->qp_info.qp = kzalloc(sizeof(*cep->qp_info.qp), GFP_KERNEL);
if (!cep->qp_info.qp) {
err = -ENOMEM;
goto scif_accept_error_qpalloc;
}
+ err = scif_anon_inode_getfile(cep);
+ if (err)
+ goto scif_accept_error_anon_inode;
+
cep->qp_info.qp->magic = SCIFEP_MAGIC;
spdev = scif_get_peer_dev(cep->remote_dev);
if (IS_ERR(spdev)) {
@@ -858,6 +905,8 @@ retry:
spin_unlock(&cep->lock);
return 0;
scif_accept_error_map:
+ scif_anon_inode_fput(cep);
+scif_accept_error_anon_inode:
scif_teardown_ep(cep);
scif_accept_error_qpalloc:
kfree(cep);
@@ -1247,6 +1296,134 @@ int scif_recv(scif_epd_t epd, void *msg, int len, int flags)
}
EXPORT_SYMBOL_GPL(scif_recv);
+static inline void _scif_poll_wait(struct file *f, wait_queue_head_t *wq,
+ poll_table *p, struct scif_endpt *ep)
+{
+ /*
+ * Because poll_wait makes a GFP_KERNEL allocation, give up the lock
+ * and regrab it afterwards. Because the endpoint state might have
+ * changed while the lock was given up, the state must be checked
+ * again after re-acquiring the lock. The code in __scif_pollfd(..)
+ * does this.
+ */
+ spin_unlock(&ep->lock);
+ poll_wait(f, wq, p);
+ spin_lock(&ep->lock);
+}
+
+unsigned int
+__scif_pollfd(struct file *f, poll_table *wait, struct scif_endpt *ep)
+{
+ unsigned int mask = 0;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI pollfd: ep %p %s\n", ep, scif_ep_states[ep->state]);
+
+ spin_lock(&ep->lock);
+
+ /* Endpoint is waiting for a non-blocking connect to complete */
+ if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
+ _scif_poll_wait(f, &ep->conn_pend_wq, wait, ep);
+ if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
+ if (ep->state == SCIFEP_CONNECTED ||
+ ep->state == SCIFEP_DISCONNECTED ||
+ ep->conn_err)
+ mask |= POLLOUT;
+ goto exit;
+ }
+ }
+
+ /* Endpoint is listening for incoming connection requests */
+ if (ep->state == SCIFEP_LISTENING) {
+ _scif_poll_wait(f, &ep->conwq, wait, ep);
+ if (ep->state == SCIFEP_LISTENING) {
+ if (ep->conreqcnt)
+ mask |= POLLIN;
+ goto exit;
+ }
+ }
+
+ /* Endpoint is connected or disconnected */
+ if (ep->state == SCIFEP_CONNECTED || ep->state == SCIFEP_DISCONNECTED) {
+ if (poll_requested_events(wait) & POLLIN)
+ _scif_poll_wait(f, &ep->recvwq, wait, ep);
+ if (poll_requested_events(wait) & POLLOUT)
+ _scif_poll_wait(f, &ep->sendwq, wait, ep);
+ if (ep->state == SCIFEP_CONNECTED ||
+ ep->state == SCIFEP_DISCONNECTED) {
+ /* Data can be read without blocking */
+ if (scif_rb_count(&ep->qp_info.qp->inbound_q, 1))
+ mask |= POLLIN;
+ /* Data can be written without blocking */
+ if (scif_rb_space(&ep->qp_info.qp->outbound_q))
+ mask |= POLLOUT;
+ /* Return POLLHUP if endpoint is disconnected */
+ if (ep->state == SCIFEP_DISCONNECTED)
+ mask |= POLLHUP;
+ goto exit;
+ }
+ }
+
+ /* Return POLLERR if the endpoint is in none of the above states */
+ mask |= POLLERR;
+exit:
+ spin_unlock(&ep->lock);
+ return mask;
+}
+
+/**
+ * scif_poll() - Kernel mode SCIF poll
+ * @ufds: Array of scif_pollepd structures containing the end points
+ * and events to poll on
+ * @nfds: Size of the ufds array
+ * @timeout_msecs: Timeout in msecs, -ve implies infinite timeout
+ *
+ * The code flow in this function is based on do_poll(..) in select.c
+ *
+ * Returns the number of endpoints which have pending events or 0 in
+ * the event of a timeout. If a signal is used for wake up, -EINTR is
+ * returned.
+ */
+int
+scif_poll(struct scif_pollepd *ufds, unsigned int nfds, long timeout_msecs)
+{
+ struct poll_wqueues table;
+ poll_table *pt;
+ int i, mask, count = 0, timed_out = timeout_msecs == 0;
+ u64 timeout = timeout_msecs < 0 ? MAX_SCHEDULE_TIMEOUT
+ : msecs_to_jiffies(timeout_msecs);
+
+ poll_initwait(&table);
+ pt = &table.pt;
+ while (1) {
+ for (i = 0; i < nfds; i++) {
+ pt->_key = ufds[i].events | POLLERR | POLLHUP;
+ mask = __scif_pollfd(ufds[i].epd->anon,
+ pt, ufds[i].epd);
+ mask &= ufds[i].events | POLLERR | POLLHUP;
+ if (mask) {
+ count++;
+ pt->_qproc = NULL;
+ }
+ ufds[i].revents = mask;
+ }
+ pt->_qproc = NULL;
+ if (!count) {
+ count = table.error;
+ if (signal_pending(current))
+ count = -EINTR;
+ }
+ if (count || timed_out)
+ break;
+
+ if (!schedule_timeout_interruptible(timeout))
+ timed_out = 1;
+ }
+ poll_freewait(&table);
+ return count;
+}
+EXPORT_SYMBOL_GPL(scif_poll);
+
int scif_get_node_ids(u16 *nodes, int len, u16 *self)
{
int online = 0;
@@ -1274,3 +1451,46 @@ int scif_get_node_ids(u16 *nodes, int len, u16 *self)
return online;
}
EXPORT_SYMBOL_GPL(scif_get_node_ids);
+
+static int scif_add_client_dev(struct device *dev, struct subsys_interface *si)
+{
+ struct scif_client *client =
+ container_of(si, struct scif_client, si);
+ struct scif_peer_dev *spdev =
+ container_of(dev, struct scif_peer_dev, dev);
+
+ if (client->probe)
+ client->probe(spdev);
+ return 0;
+}
+
+static void scif_remove_client_dev(struct device *dev,
+ struct subsys_interface *si)
+{
+ struct scif_client *client =
+ container_of(si, struct scif_client, si);
+ struct scif_peer_dev *spdev =
+ container_of(dev, struct scif_peer_dev, dev);
+
+ if (client->remove)
+ client->remove(spdev);
+}
+
+void scif_client_unregister(struct scif_client *client)
+{
+ subsys_interface_unregister(&client->si);
+}
+EXPORT_SYMBOL_GPL(scif_client_unregister);
+
+int scif_client_register(struct scif_client *client)
+{
+ struct subsys_interface *si = &client->si;
+
+ si->name = client->name;
+ si->subsys = &scif_peer_bus;
+ si->add_dev = scif_add_client_dev;
+ si->remove_dev = scif_remove_client_dev;
+
+ return subsys_interface_register(&client->si);
+}
+EXPORT_SYMBOL_GPL(scif_client_register);
diff --git a/drivers/misc/mic/scif/scif_debugfs.c b/drivers/misc/mic/scif/scif_debugfs.c
index 51f14e2a1196..6884dad97e17 100644
--- a/drivers/misc/mic/scif/scif_debugfs.c
+++ b/drivers/misc/mic/scif/scif_debugfs.c
@@ -62,10 +62,87 @@ static const struct file_operations scif_dev_ops = {
.release = scif_dev_test_release
};
-void __init scif_init_debugfs(void)
+static void scif_display_window(struct scif_window *window, struct seq_file *s)
+{
+ int j;
+ struct scatterlist *sg;
+ scif_pinned_pages_t pin = window->pinned_pages;
+
+ seq_printf(s, "window %p type %d temp %d offset 0x%llx ",
+ window, window->type, window->temp, window->offset);
+ seq_printf(s, "nr_pages 0x%llx nr_contig_chunks 0x%x prot %d ",
+ window->nr_pages, window->nr_contig_chunks, window->prot);
+ seq_printf(s, "ref_count %d magic 0x%llx peer_window 0x%llx ",
+ window->ref_count, window->magic, window->peer_window);
+ seq_printf(s, "unreg_state 0x%x va_for_temp 0x%lx\n",
+ window->unreg_state, window->va_for_temp);
+
+ for (j = 0; j < window->nr_contig_chunks; j++)
+ seq_printf(s, "page[%d] dma_addr 0x%llx num_pages 0x%llx\n", j,
+ window->dma_addr[j], window->num_pages[j]);
+
+ if (window->type == SCIF_WINDOW_SELF && pin)
+ for (j = 0; j < window->nr_pages; j++)
+ seq_printf(s, "page[%d] = pinned_pages %p address %p\n",
+ j, pin->pages[j],
+ page_address(pin->pages[j]));
+
+ if (window->st)
+ for_each_sg(window->st->sgl, sg, window->st->nents, j)
+ seq_printf(s, "sg[%d] dma addr 0x%llx length 0x%x\n",
+ j, sg_dma_address(sg), sg_dma_len(sg));
+}
+
+static void scif_display_all_windows(struct list_head *head, struct seq_file *s)
{
- struct dentry *d;
+ struct list_head *item;
+ struct scif_window *window;
+ list_for_each(item, head) {
+ window = list_entry(item, struct scif_window, list);
+ scif_display_window(window, s);
+ }
+}
+
+static int scif_rma_test(struct seq_file *s, void *unused)
+{
+ struct scif_endpt *ep;
+ struct list_head *pos;
+
+ mutex_lock(&scif_info.connlock);
+ list_for_each(pos, &scif_info.connected) {
+ ep = list_entry(pos, struct scif_endpt, list);
+ seq_printf(s, "ep %p self windows\n", ep);
+ mutex_lock(&ep->rma_info.rma_lock);
+ scif_display_all_windows(&ep->rma_info.reg_list, s);
+ seq_printf(s, "ep %p remote windows\n", ep);
+ scif_display_all_windows(&ep->rma_info.remote_reg_list, s);
+ mutex_unlock(&ep->rma_info.rma_lock);
+ }
+ mutex_unlock(&scif_info.connlock);
+ return 0;
+}
+
+static int scif_rma_test_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, scif_rma_test, inode->i_private);
+}
+
+static int scif_rma_test_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations scif_rma_ops = {
+ .owner = THIS_MODULE,
+ .open = scif_rma_test_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = scif_rma_test_release
+};
+
+void __init scif_init_debugfs(void)
+{
scif_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (!scif_dbg) {
dev_err(scif_info.mdev.this_device,
@@ -73,8 +150,8 @@ void __init scif_init_debugfs(void)
return;
}
- d = debugfs_create_file("scif_dev", 0444, scif_dbg,
- NULL, &scif_dev_ops);
+ debugfs_create_file("scif_dev", 0444, scif_dbg, NULL, &scif_dev_ops);
+ debugfs_create_file("scif_rma", 0444, scif_dbg, NULL, &scif_rma_ops);
debugfs_create_u8("en_msg_log", 0666, scif_dbg, &scif_info.en_msg_log);
debugfs_create_u8("p2p_enable", 0666, scif_dbg, &scif_info.p2p_enable);
}
diff --git a/drivers/misc/mic/scif/scif_dma.c b/drivers/misc/mic/scif/scif_dma.c
new file mode 100644
index 000000000000..95a13c629a8e
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_dma.c
@@ -0,0 +1,1979 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#include "scif_main.h"
+#include "scif_map.h"
+
+/*
+ * struct scif_dma_comp_cb - SCIF DMA completion callback
+ *
+ * @dma_completion_func: DMA completion callback
+ * @cb_cookie: DMA completion callback cookie
+ * @temp_buf: Temporary buffer
+ * @temp_buf_to_free: Temporary buffer to be freed
+ * @is_cache: Is a kmem_cache allocated buffer
+ * @dst_offset: Destination registration offset
+ * @dst_window: Destination registration window
+ * @len: Length of the temp buffer
+ * @temp_phys: DMA address of the temp buffer
+ * @sdev: The SCIF device
+ * @header_padding: padding for cache line alignment
+ */
+struct scif_dma_comp_cb {
+ void (*dma_completion_func)(void *cookie);
+ void *cb_cookie;
+ u8 *temp_buf;
+ u8 *temp_buf_to_free;
+ bool is_cache;
+ s64 dst_offset;
+ struct scif_window *dst_window;
+ size_t len;
+ dma_addr_t temp_phys;
+ struct scif_dev *sdev;
+ int header_padding;
+};
+
+/**
+ * struct scif_copy_work - Work for DMA copy
+ *
+ * @src_offset: Starting source offset
+ * @dst_offset: Starting destination offset
+ * @src_window: Starting src registered window
+ * @dst_window: Starting dst registered window
+ * @loopback: true if this is a loopback DMA transfer
+ * @len: Length of the transfer
+ * @comp_cb: DMA copy completion callback
+ * @remote_dev: The remote SCIF peer device
+ * @fence_type: polling or interrupt based
+ * @ordered: is this a tail byte ordered DMA transfer
+ */
+struct scif_copy_work {
+ s64 src_offset;
+ s64 dst_offset;
+ struct scif_window *src_window;
+ struct scif_window *dst_window;
+ int loopback;
+ size_t len;
+ struct scif_dma_comp_cb *comp_cb;
+ struct scif_dev *remote_dev;
+ int fence_type;
+ bool ordered;
+};
+
+#ifndef list_entry_next
+#define list_entry_next(pos, member) \
+ list_entry(pos->member.next, typeof(*pos), member)
+#endif
+
+/**
+ * scif_reserve_dma_chan:
+ * @ep: Endpoint Descriptor.
+ *
+ * This routine reserves a DMA channel for a particular
+ * endpoint. All DMA transfers for an endpoint are always
+ * programmed on the same DMA channel.
+ */
+int scif_reserve_dma_chan(struct scif_endpt *ep)
+{
+ int err = 0;
+ struct scif_dev *scifdev;
+ struct scif_hw_dev *sdev;
+ struct dma_chan *chan;
+
+ /* Loopback DMAs are not supported on the management node */
+ if (!scif_info.nodeid && scifdev_self(ep->remote_dev))
+ return 0;
+ if (scif_info.nodeid)
+ scifdev = &scif_dev[0];
+ else
+ scifdev = ep->remote_dev;
+ sdev = scifdev->sdev;
+ if (!sdev->num_dma_ch)
+ return -ENODEV;
+ chan = sdev->dma_ch[scifdev->dma_ch_idx];
+ scifdev->dma_ch_idx = (scifdev->dma_ch_idx + 1) % sdev->num_dma_ch;
+ mutex_lock(&ep->rma_info.rma_lock);
+ ep->rma_info.dma_chan = chan;
+ mutex_unlock(&ep->rma_info.rma_lock);
+ return err;
+}
+
+#ifdef CONFIG_MMU_NOTIFIER
+/**
+ * scif_rma_destroy_tcw:
+ *
+ * This routine destroys temporary cached windows
+ */
+static
+void __scif_rma_destroy_tcw(struct scif_mmu_notif *mmn,
+ struct scif_endpt *ep,
+ u64 start, u64 len)
+{
+ struct list_head *item, *tmp;
+ struct scif_window *window;
+ u64 start_va, end_va;
+ u64 end = start + len;
+
+ if (end <= start)
+ return;
+
+ list_for_each_safe(item, tmp, &mmn->tc_reg_list) {
+ window = list_entry(item, struct scif_window, list);
+ ep = (struct scif_endpt *)window->ep;
+ if (!len)
+ break;
+ start_va = window->va_for_temp;
+ end_va = start_va + (window->nr_pages << PAGE_SHIFT);
+ if (start < start_va && end <= start_va)
+ break;
+ if (start >= end_va)
+ continue;
+ __scif_rma_destroy_tcw_helper(window);
+ }
+}
+
+static void scif_rma_destroy_tcw(struct scif_mmu_notif *mmn, u64 start, u64 len)
+{
+ struct scif_endpt *ep = mmn->ep;
+
+ spin_lock(&ep->rma_info.tc_lock);
+ __scif_rma_destroy_tcw(mmn, ep, start, len);
+ spin_unlock(&ep->rma_info.tc_lock);
+}
+
+static void scif_rma_destroy_tcw_ep(struct scif_endpt *ep)
+{
+ struct list_head *item, *tmp;
+ struct scif_mmu_notif *mmn;
+
+ list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) {
+ mmn = list_entry(item, struct scif_mmu_notif, list);
+ scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
+ }
+}
+
+static void __scif_rma_destroy_tcw_ep(struct scif_endpt *ep)
+{
+ struct list_head *item, *tmp;
+ struct scif_mmu_notif *mmn;
+
+ spin_lock(&ep->rma_info.tc_lock);
+ list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) {
+ mmn = list_entry(item, struct scif_mmu_notif, list);
+ __scif_rma_destroy_tcw(mmn, ep, 0, ULONG_MAX);
+ }
+ spin_unlock(&ep->rma_info.tc_lock);
+}
+
+static bool scif_rma_tc_can_cache(struct scif_endpt *ep, size_t cur_bytes)
+{
+ if ((cur_bytes >> PAGE_SHIFT) > scif_info.rma_tc_limit)
+ return false;
+ if ((atomic_read(&ep->rma_info.tcw_total_pages)
+ + (cur_bytes >> PAGE_SHIFT)) >
+ scif_info.rma_tc_limit) {
+ dev_info(scif_info.mdev.this_device,
+ "%s %d total=%d, current=%zu reached max\n",
+ __func__, __LINE__,
+ atomic_read(&ep->rma_info.tcw_total_pages),
+ (1 + (cur_bytes >> PAGE_SHIFT)));
+ scif_rma_destroy_tcw_invalid();
+ __scif_rma_destroy_tcw_ep(ep);
+ }
+ return true;
+}
+
+static void scif_mmu_notifier_release(struct mmu_notifier *mn,
+ struct mm_struct *mm)
+{
+ struct scif_mmu_notif *mmn;
+
+ mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
+ scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
+ schedule_work(&scif_info.misc_work);
+}
+
+static void scif_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
+ struct mm_struct *mm,
+ unsigned long address)
+{
+ struct scif_mmu_notif *mmn;
+
+ mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
+ scif_rma_destroy_tcw(mmn, address, PAGE_SIZE);
+}
+
+static void scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
+ struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+ struct scif_mmu_notif *mmn;
+
+ mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
+ scif_rma_destroy_tcw(mmn, start, end - start);
+}
+
+static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
+ struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+ /*
+ * Nothing to do here, everything needed was done in
+ * invalidate_range_start.
+ */
+}
+
+static const struct mmu_notifier_ops scif_mmu_notifier_ops = {
+ .release = scif_mmu_notifier_release,
+ .clear_flush_young = NULL,
+ .invalidate_page = scif_mmu_notifier_invalidate_page,
+ .invalidate_range_start = scif_mmu_notifier_invalidate_range_start,
+ .invalidate_range_end = scif_mmu_notifier_invalidate_range_end};
+
+static void scif_ep_unregister_mmu_notifier(struct scif_endpt *ep)
+{
+ struct scif_endpt_rma_info *rma = &ep->rma_info;
+ struct scif_mmu_notif *mmn = NULL;
+ struct list_head *item, *tmp;
+
+ mutex_lock(&ep->rma_info.mmn_lock);
+ list_for_each_safe(item, tmp, &rma->mmn_list) {
+ mmn = list_entry(item, struct scif_mmu_notif, list);
+ mmu_notifier_unregister(&mmn->ep_mmu_notifier, mmn->mm);
+ list_del(item);
+ kfree(mmn);
+ }
+ mutex_unlock(&ep->rma_info.mmn_lock);
+}
+
+static void scif_init_mmu_notifier(struct scif_mmu_notif *mmn,
+ struct mm_struct *mm, struct scif_endpt *ep)
+{
+ mmn->ep = ep;
+ mmn->mm = mm;
+ mmn->ep_mmu_notifier.ops = &scif_mmu_notifier_ops;
+ INIT_LIST_HEAD(&mmn->list);
+ INIT_LIST_HEAD(&mmn->tc_reg_list);
+}
+
+static struct scif_mmu_notif *
+scif_find_mmu_notifier(struct mm_struct *mm, struct scif_endpt_rma_info *rma)
+{
+ struct scif_mmu_notif *mmn;
+ struct list_head *item;
+
+ list_for_each(item, &rma->mmn_list) {
+ mmn = list_entry(item, struct scif_mmu_notif, list);
+ if (mmn->mm == mm)
+ return mmn;
+ }
+ return NULL;
+}
+
+static struct scif_mmu_notif *
+scif_add_mmu_notifier(struct mm_struct *mm, struct scif_endpt *ep)
+{
+ struct scif_mmu_notif *mmn
+ = kzalloc(sizeof(*mmn), GFP_KERNEL);
+
+ if (!mmn)
+ return ERR_PTR(ENOMEM);
+
+ scif_init_mmu_notifier(mmn, current->mm, ep);
+ if (mmu_notifier_register(&mmn->ep_mmu_notifier,
+ current->mm)) {
+ kfree(mmn);
+ return ERR_PTR(EBUSY);
+ }
+ list_add(&mmn->list, &ep->rma_info.mmn_list);
+ return mmn;
+}
+
+/*
+ * Called from the misc thread to destroy temporary cached windows and
+ * unregister the MMU notifier for the SCIF endpoint.
+ */
+void scif_mmu_notif_handler(struct work_struct *work)
+{
+ struct list_head *pos, *tmpq;
+ struct scif_endpt *ep;
+restart:
+ scif_rma_destroy_tcw_invalid();
+ spin_lock(&scif_info.rmalock);
+ list_for_each_safe(pos, tmpq, &scif_info.mmu_notif_cleanup) {
+ ep = list_entry(pos, struct scif_endpt, mmu_list);
+ list_del(&ep->mmu_list);
+ spin_unlock(&scif_info.rmalock);
+ scif_rma_destroy_tcw_ep(ep);
+ scif_ep_unregister_mmu_notifier(ep);
+ goto restart;
+ }
+ spin_unlock(&scif_info.rmalock);
+}
+
+static bool scif_is_set_reg_cache(int flags)
+{
+ return !!(flags & SCIF_RMA_USECACHE);
+}
+#else
+static struct scif_mmu_notif *
+scif_find_mmu_notifier(struct mm_struct *mm,
+ struct scif_endpt_rma_info *rma)
+{
+ return NULL;
+}
+
+static struct scif_mmu_notif *
+scif_add_mmu_notifier(struct mm_struct *mm, struct scif_endpt *ep)
+{
+ return NULL;
+}
+
+void scif_mmu_notif_handler(struct work_struct *work)
+{
+}
+
+static bool scif_is_set_reg_cache(int flags)
+{
+ return false;
+}
+
+static bool scif_rma_tc_can_cache(struct scif_endpt *ep, size_t cur_bytes)
+{
+ return false;
+}
+#endif
+
+/**
+ * scif_register_temp:
+ * @epd: End Point Descriptor.
+ * @addr: virtual address to/from which to copy
+ * @len: length of range to copy
+ * @out_offset: computed offset returned by reference.
+ * @out_window: allocated registered window returned by reference.
+ *
+ * Create a temporary registered window. The peer will not know about this
+ * window. This API is used for scif_vreadfrom()/scif_vwriteto() API's.
+ */
+static int
+scif_register_temp(scif_epd_t epd, unsigned long addr, size_t len, int prot,
+ off_t *out_offset, struct scif_window **out_window)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ int err;
+ scif_pinned_pages_t pinned_pages;
+ size_t aligned_len;
+
+ aligned_len = ALIGN(len, PAGE_SIZE);
+
+ err = __scif_pin_pages((void *)(addr & PAGE_MASK),
+ aligned_len, &prot, 0, &pinned_pages);
+ if (err)
+ return err;
+
+ pinned_pages->prot = prot;
+
+ /* Compute the offset for this registration */
+ err = scif_get_window_offset(ep, 0, 0,
+ aligned_len >> PAGE_SHIFT,
+ (s64 *)out_offset);
+ if (err)
+ goto error_unpin;
+
+ /* Allocate and prepare self registration window */
+ *out_window = scif_create_window(ep, aligned_len >> PAGE_SHIFT,
+ *out_offset, true);
+ if (!*out_window) {
+ scif_free_window_offset(ep, NULL, *out_offset);
+ err = -ENOMEM;
+ goto error_unpin;
+ }
+
+ (*out_window)->pinned_pages = pinned_pages;
+ (*out_window)->nr_pages = pinned_pages->nr_pages;
+ (*out_window)->prot = pinned_pages->prot;
+
+ (*out_window)->va_for_temp = addr & PAGE_MASK;
+ err = scif_map_window(ep->remote_dev, *out_window);
+ if (err) {
+ /* Something went wrong! Rollback */
+ scif_destroy_window(ep, *out_window);
+ *out_window = NULL;
+ } else {
+ *out_offset |= (addr - (*out_window)->va_for_temp);
+ }
+ return err;
+error_unpin:
+ if (err)
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ scif_unpin_pages(pinned_pages);
+ return err;
+}
+
+#define SCIF_DMA_TO (3 * HZ)
+
+/*
+ * scif_sync_dma - Program a DMA without an interrupt descriptor
+ *
+ * @dev - The address of the pointer to the device instance used
+ * for DMA registration.
+ * @chan - DMA channel to be used.
+ * @sync_wait: Wait for DMA to complete?
+ *
+ * Return 0 on success and -errno on error.
+ */
+static int scif_sync_dma(struct scif_hw_dev *sdev, struct dma_chan *chan,
+ bool sync_wait)
+{
+ int err = 0;
+ struct dma_async_tx_descriptor *tx = NULL;
+ enum dma_ctrl_flags flags = DMA_PREP_FENCE;
+ dma_cookie_t cookie;
+ struct dma_device *ddev;
+
+ if (!chan) {
+ err = -EIO;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ ddev = chan->device;
+
+ tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, flags);
+ if (!tx) {
+ err = -ENOMEM;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto release;
+ }
+ cookie = tx->tx_submit(tx);
+
+ if (dma_submit_error(cookie)) {
+ err = -ENOMEM;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto release;
+ }
+ if (!sync_wait) {
+ dma_async_issue_pending(chan);
+ } else {
+ if (dma_sync_wait(chan, cookie) == DMA_COMPLETE) {
+ err = 0;
+ } else {
+ err = -EIO;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ }
+ }
+release:
+ return err;
+}
+
+static void scif_dma_callback(void *arg)
+{
+ struct completion *done = (struct completion *)arg;
+
+ complete(done);
+}
+
+#define SCIF_DMA_SYNC_WAIT true
+#define SCIF_DMA_POLL BIT(0)
+#define SCIF_DMA_INTR BIT(1)
+
+/*
+ * scif_async_dma - Program a DMA with an interrupt descriptor
+ *
+ * @dev - The address of the pointer to the device instance used
+ * for DMA registration.
+ * @chan - DMA channel to be used.
+ * Return 0 on success and -errno on error.
+ */
+static int scif_async_dma(struct scif_hw_dev *sdev, struct dma_chan *chan)
+{
+ int err = 0;
+ struct dma_device *ddev;
+ struct dma_async_tx_descriptor *tx = NULL;
+ enum dma_ctrl_flags flags = DMA_PREP_INTERRUPT | DMA_PREP_FENCE;
+ DECLARE_COMPLETION_ONSTACK(done_wait);
+ dma_cookie_t cookie;
+ enum dma_status status;
+
+ if (!chan) {
+ err = -EIO;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ ddev = chan->device;
+
+ tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, flags);
+ if (!tx) {
+ err = -ENOMEM;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto release;
+ }
+ reinit_completion(&done_wait);
+ tx->callback = scif_dma_callback;
+ tx->callback_param = &done_wait;
+ cookie = tx->tx_submit(tx);
+
+ if (dma_submit_error(cookie)) {
+ err = -ENOMEM;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto release;
+ }
+ dma_async_issue_pending(chan);
+
+ err = wait_for_completion_timeout(&done_wait, SCIF_DMA_TO);
+ if (!err) {
+ err = -EIO;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto release;
+ }
+ err = 0;
+ status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+ if (status != DMA_COMPLETE) {
+ err = -EIO;
+ dev_err(&sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto release;
+ }
+release:
+ return err;
+}
+
+/*
+ * scif_drain_dma_poll - Drain all outstanding DMA operations for a particular
+ * DMA channel via polling.
+ *
+ * @sdev - The SCIF device
+ * @chan - DMA channel
+ * Return 0 on success and -errno on error.
+ */
+static int scif_drain_dma_poll(struct scif_hw_dev *sdev, struct dma_chan *chan)
+{
+ if (!chan)
+ return -EINVAL;
+ return scif_sync_dma(sdev, chan, SCIF_DMA_SYNC_WAIT);
+}
+
+/*
+ * scif_drain_dma_intr - Drain all outstanding DMA operations for a particular
+ * DMA channel via interrupt based blocking wait.
+ *
+ * @sdev - The SCIF device
+ * @chan - DMA channel
+ * Return 0 on success and -errno on error.
+ */
+int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan)
+{
+ if (!chan)
+ return -EINVAL;
+ return scif_async_dma(sdev, chan);
+}
+
+/**
+ * scif_rma_destroy_windows:
+ *
+ * This routine destroys all windows queued for cleanup
+ */
+void scif_rma_destroy_windows(void)
+{
+ struct list_head *item, *tmp;
+ struct scif_window *window;
+ struct scif_endpt *ep;
+ struct dma_chan *chan;
+
+ might_sleep();
+restart:
+ spin_lock(&scif_info.rmalock);
+ list_for_each_safe(item, tmp, &scif_info.rma) {
+ window = list_entry(item, struct scif_window,
+ list);
+ ep = (struct scif_endpt *)window->ep;
+ chan = ep->rma_info.dma_chan;
+
+ list_del_init(&window->list);
+ spin_unlock(&scif_info.rmalock);
+ if (!chan || !scifdev_alive(ep) ||
+ !scif_drain_dma_intr(ep->remote_dev->sdev,
+ ep->rma_info.dma_chan))
+ /* Remove window from global list */
+ window->unreg_state = OP_COMPLETED;
+ else
+ dev_warn(&ep->remote_dev->sdev->dev,
+ "DMA engine hung?\n");
+ if (window->unreg_state == OP_COMPLETED) {
+ if (window->type == SCIF_WINDOW_SELF)
+ scif_destroy_window(ep, window);
+ else
+ scif_destroy_remote_window(window);
+ atomic_dec(&ep->rma_info.tw_refcount);
+ }
+ goto restart;
+ }
+ spin_unlock(&scif_info.rmalock);
+}
+
+/**
+ * scif_rma_destroy_tcw:
+ *
+ * This routine destroys temporary cached registered windows
+ * which have been queued for cleanup.
+ */
+void scif_rma_destroy_tcw_invalid(void)
+{
+ struct list_head *item, *tmp;
+ struct scif_window *window;
+ struct scif_endpt *ep;
+ struct dma_chan *chan;
+
+ might_sleep();
+restart:
+ spin_lock(&scif_info.rmalock);
+ list_for_each_safe(item, tmp, &scif_info.rma_tc) {
+ window = list_entry(item, struct scif_window, list);
+ ep = (struct scif_endpt *)window->ep;
+ chan = ep->rma_info.dma_chan;
+ list_del_init(&window->list);
+ spin_unlock(&scif_info.rmalock);
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (!chan || !scifdev_alive(ep) ||
+ !scif_drain_dma_intr(ep->remote_dev->sdev,
+ ep->rma_info.dma_chan)) {
+ atomic_sub(window->nr_pages,
+ &ep->rma_info.tcw_total_pages);
+ scif_destroy_window(ep, window);
+ atomic_dec(&ep->rma_info.tcw_refcount);
+ } else {
+ dev_warn(&ep->remote_dev->sdev->dev,
+ "DMA engine hung?\n");
+ }
+ mutex_unlock(&ep->rma_info.rma_lock);
+ goto restart;
+ }
+ spin_unlock(&scif_info.rmalock);
+}
+
+static inline
+void *_get_local_va(off_t off, struct scif_window *window, size_t len)
+{
+ int page_nr = (off - window->offset) >> PAGE_SHIFT;
+ off_t page_off = off & ~PAGE_MASK;
+ void *va = NULL;
+
+ if (window->type == SCIF_WINDOW_SELF) {
+ struct page **pages = window->pinned_pages->pages;
+
+ va = page_address(pages[page_nr]) + page_off;
+ }
+ return va;
+}
+
+static inline
+void *ioremap_remote(off_t off, struct scif_window *window,
+ size_t len, struct scif_dev *dev,
+ struct scif_window_iter *iter)
+{
+ dma_addr_t phys = scif_off_to_dma_addr(window, off, NULL, iter);
+
+ /*
+ * If the DMA address is not card relative then we need the DMA
+ * addresses to be an offset into the bar. The aperture base was already
+ * added so subtract it here since scif_ioremap is going to add it again
+ */
+ if (!scifdev_self(dev) && window->type == SCIF_WINDOW_PEER &&
+ dev->sdev->aper && !dev->sdev->card_rel_da)
+ phys = phys - dev->sdev->aper->pa;
+ return scif_ioremap(phys, len, dev);
+}
+
+static inline void
+iounmap_remote(void *virt, size_t size, struct scif_copy_work *work)
+{
+ scif_iounmap(virt, size, work->remote_dev);
+}
+
+/*
+ * Takes care of ordering issue caused by
+ * 1. Hardware: Only in the case of cpu copy from mgmt node to card
+ * because of WC memory.
+ * 2. Software: If memcpy reorders copy instructions for optimization.
+ * This could happen at both mgmt node and card.
+ */
+static inline void
+scif_ordered_memcpy_toio(char *dst, const char *src, size_t count)
+{
+ if (!count)
+ return;
+
+ memcpy_toio((void __iomem __force *)dst, src, --count);
+ /* Order the last byte with the previous stores */
+ wmb();
+ *(dst + count) = *(src + count);
+}
+
+static inline void scif_unaligned_cpy_toio(char *dst, const char *src,
+ size_t count, bool ordered)
+{
+ if (ordered)
+ scif_ordered_memcpy_toio(dst, src, count);
+ else
+ memcpy_toio((void __iomem __force *)dst, src, count);
+}
+
+static inline
+void scif_ordered_memcpy_fromio(char *dst, const char *src, size_t count)
+{
+ if (!count)
+ return;
+
+ memcpy_fromio(dst, (void __iomem __force *)src, --count);
+ /* Order the last byte with the previous loads */
+ rmb();
+ *(dst + count) = *(src + count);
+}
+
+static inline void scif_unaligned_cpy_fromio(char *dst, const char *src,
+ size_t count, bool ordered)
+{
+ if (ordered)
+ scif_ordered_memcpy_fromio(dst, src, count);
+ else
+ memcpy_fromio(dst, (void __iomem __force *)src, count);
+}
+
+#define SCIF_RMA_ERROR_CODE (~(dma_addr_t)0x0)
+
+/*
+ * scif_off_to_dma_addr:
+ * Obtain the dma_addr given the window and the offset.
+ * @window: Registered window.
+ * @off: Window offset.
+ * @nr_bytes: Return the number of contiguous bytes till next DMA addr index.
+ * @index: Return the index of the dma_addr array found.
+ * @start_off: start offset of index of the dma addr array found.
+ * The nr_bytes provides the callee an estimate of the maximum possible
+ * DMA xfer possible while the index/start_off provide faster lookups
+ * for the next iteration.
+ */
+dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
+ size_t *nr_bytes, struct scif_window_iter *iter)
+{
+ int i, page_nr;
+ s64 start, end;
+ off_t page_off;
+
+ if (window->nr_pages == window->nr_contig_chunks) {
+ page_nr = (off - window->offset) >> PAGE_SHIFT;
+ page_off = off & ~PAGE_MASK;
+
+ if (nr_bytes)
+ *nr_bytes = PAGE_SIZE - page_off;
+ return window->dma_addr[page_nr] | page_off;
+ }
+ if (iter) {
+ i = iter->index;
+ start = iter->offset;
+ } else {
+ i = 0;
+ start = window->offset;
+ }
+ for (; i < window->nr_contig_chunks; i++) {
+ end = start + (window->num_pages[i] << PAGE_SHIFT);
+ if (off >= start && off < end) {
+ if (iter) {
+ iter->index = i;
+ iter->offset = start;
+ }
+ if (nr_bytes)
+ *nr_bytes = end - off;
+ return (window->dma_addr[i] + (off - start));
+ }
+ start += (window->num_pages[i] << PAGE_SHIFT);
+ }
+ dev_err(scif_info.mdev.this_device,
+ "%s %d BUG. Addr not found? window %p off 0x%llx\n",
+ __func__, __LINE__, window, off);
+ return SCIF_RMA_ERROR_CODE;
+}
+
+/*
+ * Copy between rma window and temporary buffer
+ */
+static void scif_rma_local_cpu_copy(s64 offset, struct scif_window *window,
+ u8 *temp, size_t rem_len, bool to_temp)
+{
+ void *window_virt;
+ size_t loop_len;
+ int offset_in_page;
+ s64 end_offset;
+
+ offset_in_page = offset & ~PAGE_MASK;
+ loop_len = PAGE_SIZE - offset_in_page;
+
+ if (rem_len < loop_len)
+ loop_len = rem_len;
+
+ window_virt = _get_local_va(offset, window, loop_len);
+ if (!window_virt)
+ return;
+ if (to_temp)
+ memcpy(temp, window_virt, loop_len);
+ else
+ memcpy(window_virt, temp, loop_len);
+
+ offset += loop_len;
+ temp += loop_len;
+ rem_len -= loop_len;
+
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ while (rem_len) {
+ if (offset == end_offset) {
+ window = list_entry_next(window, list);
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ }
+ loop_len = min(PAGE_SIZE, rem_len);
+ window_virt = _get_local_va(offset, window, loop_len);
+ if (!window_virt)
+ return;
+ if (to_temp)
+ memcpy(temp, window_virt, loop_len);
+ else
+ memcpy(window_virt, temp, loop_len);
+ offset += loop_len;
+ temp += loop_len;
+ rem_len -= loop_len;
+ }
+}
+
+/**
+ * scif_rma_completion_cb:
+ * @data: RMA cookie
+ *
+ * RMA interrupt completion callback.
+ */
+static void scif_rma_completion_cb(void *data)
+{
+ struct scif_dma_comp_cb *comp_cb = data;
+
+ /* Free DMA Completion CB. */
+ if (comp_cb->dst_window)
+ scif_rma_local_cpu_copy(comp_cb->dst_offset,
+ comp_cb->dst_window,
+ comp_cb->temp_buf +
+ comp_cb->header_padding,
+ comp_cb->len, false);
+ scif_unmap_single(comp_cb->temp_phys, comp_cb->sdev,
+ SCIF_KMEM_UNALIGNED_BUF_SIZE);
+ if (comp_cb->is_cache)
+ kmem_cache_free(unaligned_cache,
+ comp_cb->temp_buf_to_free);
+ else
+ kfree(comp_cb->temp_buf_to_free);
+}
+
+/* Copies between temporary buffer and offsets provided in work */
+static int
+scif_rma_list_dma_copy_unaligned(struct scif_copy_work *work,
+ u8 *temp, struct dma_chan *chan,
+ bool src_local)
+{
+ struct scif_dma_comp_cb *comp_cb = work->comp_cb;
+ dma_addr_t window_dma_addr, temp_dma_addr;
+ dma_addr_t temp_phys = comp_cb->temp_phys;
+ size_t loop_len, nr_contig_bytes = 0, remaining_len = work->len;
+ int offset_in_ca, ret = 0;
+ s64 end_offset, offset;
+ struct scif_window *window;
+ void *window_virt_addr;
+ size_t tail_len;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_device *dev = chan->device;
+ dma_cookie_t cookie;
+
+ if (src_local) {
+ offset = work->dst_offset;
+ window = work->dst_window;
+ } else {
+ offset = work->src_offset;
+ window = work->src_window;
+ }
+
+ offset_in_ca = offset & (L1_CACHE_BYTES - 1);
+ if (offset_in_ca) {
+ loop_len = L1_CACHE_BYTES - offset_in_ca;
+ loop_len = min(loop_len, remaining_len);
+ window_virt_addr = ioremap_remote(offset, window,
+ loop_len,
+ work->remote_dev,
+ NULL);
+ if (!window_virt_addr)
+ return -ENOMEM;
+ if (src_local)
+ scif_unaligned_cpy_toio(window_virt_addr, temp,
+ loop_len,
+ work->ordered &&
+ !(remaining_len - loop_len));
+ else
+ scif_unaligned_cpy_fromio(temp, window_virt_addr,
+ loop_len, work->ordered &&
+ !(remaining_len - loop_len));
+ iounmap_remote(window_virt_addr, loop_len, work);
+
+ offset += loop_len;
+ temp += loop_len;
+ temp_phys += loop_len;
+ remaining_len -= loop_len;
+ }
+
+ offset_in_ca = offset & ~PAGE_MASK;
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+
+ tail_len = remaining_len & (L1_CACHE_BYTES - 1);
+ remaining_len -= tail_len;
+ while (remaining_len) {
+ if (offset == end_offset) {
+ window = list_entry_next(window, list);
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ }
+ if (scif_is_mgmt_node())
+ temp_dma_addr = temp_phys;
+ else
+ /* Fix if we ever enable IOMMU on the card */
+ temp_dma_addr = (dma_addr_t)virt_to_phys(temp);
+ window_dma_addr = scif_off_to_dma_addr(window, offset,
+ &nr_contig_bytes,
+ NULL);
+ loop_len = min(nr_contig_bytes, remaining_len);
+ if (src_local) {
+ if (work->ordered && !tail_len &&
+ !(remaining_len - loop_len) &&
+ loop_len != L1_CACHE_BYTES) {
+ /*
+ * Break up the last chunk of the transfer into
+ * two steps. if there is no tail to guarantee
+ * DMA ordering. SCIF_DMA_POLLING inserts
+ * a status update descriptor in step 1 which
+ * acts as a double sided synchronization fence
+ * for the DMA engine to ensure that the last
+ * cache line in step 2 is updated last.
+ */
+ /* Step 1) DMA: Body Length - L1_CACHE_BYTES. */
+ tx =
+ dev->device_prep_dma_memcpy(chan,
+ window_dma_addr,
+ temp_dma_addr,
+ loop_len -
+ L1_CACHE_BYTES,
+ DMA_PREP_FENCE);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ offset += (loop_len - L1_CACHE_BYTES);
+ temp_dma_addr += (loop_len - L1_CACHE_BYTES);
+ window_dma_addr += (loop_len - L1_CACHE_BYTES);
+ remaining_len -= (loop_len - L1_CACHE_BYTES);
+ loop_len = remaining_len;
+
+ /* Step 2) DMA: L1_CACHE_BYTES */
+ tx =
+ dev->device_prep_dma_memcpy(chan,
+ window_dma_addr,
+ temp_dma_addr,
+ loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ } else {
+ tx =
+ dev->device_prep_dma_memcpy(chan,
+ window_dma_addr,
+ temp_dma_addr,
+ loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ }
+ } else {
+ tx = dev->device_prep_dma_memcpy(chan, temp_dma_addr,
+ window_dma_addr, loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ }
+ if (ret < 0)
+ goto err;
+ offset += loop_len;
+ temp += loop_len;
+ temp_phys += loop_len;
+ remaining_len -= loop_len;
+ offset_in_ca = 0;
+ }
+ if (tail_len) {
+ if (offset == end_offset) {
+ window = list_entry_next(window, list);
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ }
+ window_virt_addr = ioremap_remote(offset, window, tail_len,
+ work->remote_dev,
+ NULL);
+ if (!window_virt_addr)
+ return -ENOMEM;
+ /*
+ * The CPU copy for the tail bytes must be initiated only once
+ * previous DMA transfers for this endpoint have completed
+ * to guarantee ordering.
+ */
+ if (work->ordered) {
+ struct scif_dev *rdev = work->remote_dev;
+
+ ret = scif_drain_dma_intr(rdev->sdev, chan);
+ if (ret)
+ return ret;
+ }
+ if (src_local)
+ scif_unaligned_cpy_toio(window_virt_addr, temp,
+ tail_len, work->ordered);
+ else
+ scif_unaligned_cpy_fromio(temp, window_virt_addr,
+ tail_len, work->ordered);
+ iounmap_remote(window_virt_addr, tail_len, work);
+ }
+ tx = dev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_INTERRUPT);
+ if (!tx) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ tx->callback = &scif_rma_completion_cb;
+ tx->callback_param = comp_cb;
+ cookie = tx->tx_submit(tx);
+
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ dma_async_issue_pending(chan);
+ return 0;
+err:
+ dev_err(scif_info.mdev.this_device,
+ "%s %d Desc Prog Failed ret %d\n",
+ __func__, __LINE__, ret);
+ return ret;
+}
+
+/*
+ * _scif_rma_list_dma_copy_aligned:
+ *
+ * Traverse all the windows and perform DMA copy.
+ */
+static int _scif_rma_list_dma_copy_aligned(struct scif_copy_work *work,
+ struct dma_chan *chan)
+{
+ dma_addr_t src_dma_addr, dst_dma_addr;
+ size_t loop_len, remaining_len, src_contig_bytes = 0;
+ size_t dst_contig_bytes = 0;
+ struct scif_window_iter src_win_iter;
+ struct scif_window_iter dst_win_iter;
+ s64 end_src_offset, end_dst_offset;
+ struct scif_window *src_window = work->src_window;
+ struct scif_window *dst_window = work->dst_window;
+ s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
+ int ret = 0;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_device *dev = chan->device;
+ dma_cookie_t cookie;
+
+ remaining_len = work->len;
+
+ scif_init_window_iter(src_window, &src_win_iter);
+ scif_init_window_iter(dst_window, &dst_win_iter);
+ end_src_offset = src_window->offset +
+ (src_window->nr_pages << PAGE_SHIFT);
+ end_dst_offset = dst_window->offset +
+ (dst_window->nr_pages << PAGE_SHIFT);
+ while (remaining_len) {
+ if (src_offset == end_src_offset) {
+ src_window = list_entry_next(src_window, list);
+ end_src_offset = src_window->offset +
+ (src_window->nr_pages << PAGE_SHIFT);
+ scif_init_window_iter(src_window, &src_win_iter);
+ }
+ if (dst_offset == end_dst_offset) {
+ dst_window = list_entry_next(dst_window, list);
+ end_dst_offset = dst_window->offset +
+ (dst_window->nr_pages << PAGE_SHIFT);
+ scif_init_window_iter(dst_window, &dst_win_iter);
+ }
+
+ /* compute dma addresses for transfer */
+ src_dma_addr = scif_off_to_dma_addr(src_window, src_offset,
+ &src_contig_bytes,
+ &src_win_iter);
+ dst_dma_addr = scif_off_to_dma_addr(dst_window, dst_offset,
+ &dst_contig_bytes,
+ &dst_win_iter);
+ loop_len = min(src_contig_bytes, dst_contig_bytes);
+ loop_len = min(loop_len, remaining_len);
+ if (work->ordered && !(remaining_len - loop_len)) {
+ /*
+ * Break up the last chunk of the transfer into two
+ * steps to ensure that the last byte in step 2 is
+ * updated last.
+ */
+ /* Step 1) DMA: Body Length - 1 */
+ tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
+ src_dma_addr,
+ loop_len - 1,
+ DMA_PREP_FENCE);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ src_offset += (loop_len - 1);
+ dst_offset += (loop_len - 1);
+ src_dma_addr += (loop_len - 1);
+ dst_dma_addr += (loop_len - 1);
+ remaining_len -= (loop_len - 1);
+ loop_len = remaining_len;
+
+ /* Step 2) DMA: 1 BYTES */
+ tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
+ src_dma_addr, loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ } else {
+ tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
+ src_dma_addr, loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ }
+ src_offset += loop_len;
+ dst_offset += loop_len;
+ remaining_len -= loop_len;
+ }
+ return ret;
+err:
+ dev_err(scif_info.mdev.this_device,
+ "%s %d Desc Prog Failed ret %d\n",
+ __func__, __LINE__, ret);
+ return ret;
+}
+
+/*
+ * scif_rma_list_dma_copy_aligned:
+ *
+ * Traverse all the windows and perform DMA copy.
+ */
+static int scif_rma_list_dma_copy_aligned(struct scif_copy_work *work,
+ struct dma_chan *chan)
+{
+ dma_addr_t src_dma_addr, dst_dma_addr;
+ size_t loop_len, remaining_len, tail_len, src_contig_bytes = 0;
+ size_t dst_contig_bytes = 0;
+ int src_cache_off;
+ s64 end_src_offset, end_dst_offset;
+ struct scif_window_iter src_win_iter;
+ struct scif_window_iter dst_win_iter;
+ void *src_virt, *dst_virt;
+ struct scif_window *src_window = work->src_window;
+ struct scif_window *dst_window = work->dst_window;
+ s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
+ int ret = 0;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_device *dev = chan->device;
+ dma_cookie_t cookie;
+
+ remaining_len = work->len;
+ scif_init_window_iter(src_window, &src_win_iter);
+ scif_init_window_iter(dst_window, &dst_win_iter);
+
+ src_cache_off = src_offset & (L1_CACHE_BYTES - 1);
+ if (src_cache_off != 0) {
+ /* Head */
+ loop_len = L1_CACHE_BYTES - src_cache_off;
+ loop_len = min(loop_len, remaining_len);
+ src_dma_addr = __scif_off_to_dma_addr(src_window, src_offset);
+ dst_dma_addr = __scif_off_to_dma_addr(dst_window, dst_offset);
+ if (src_window->type == SCIF_WINDOW_SELF)
+ src_virt = _get_local_va(src_offset, src_window,
+ loop_len);
+ else
+ src_virt = ioremap_remote(src_offset, src_window,
+ loop_len,
+ work->remote_dev, NULL);
+ if (!src_virt)
+ return -ENOMEM;
+ if (dst_window->type == SCIF_WINDOW_SELF)
+ dst_virt = _get_local_va(dst_offset, dst_window,
+ loop_len);
+ else
+ dst_virt = ioremap_remote(dst_offset, dst_window,
+ loop_len,
+ work->remote_dev, NULL);
+ if (!dst_virt) {
+ if (src_window->type != SCIF_WINDOW_SELF)
+ iounmap_remote(src_virt, loop_len, work);
+ return -ENOMEM;
+ }
+ if (src_window->type == SCIF_WINDOW_SELF)
+ scif_unaligned_cpy_toio(dst_virt, src_virt, loop_len,
+ remaining_len == loop_len ?
+ work->ordered : false);
+ else
+ scif_unaligned_cpy_fromio(dst_virt, src_virt, loop_len,
+ remaining_len == loop_len ?
+ work->ordered : false);
+ if (src_window->type != SCIF_WINDOW_SELF)
+ iounmap_remote(src_virt, loop_len, work);
+ if (dst_window->type != SCIF_WINDOW_SELF)
+ iounmap_remote(dst_virt, loop_len, work);
+ src_offset += loop_len;
+ dst_offset += loop_len;
+ remaining_len -= loop_len;
+ }
+
+ end_src_offset = src_window->offset +
+ (src_window->nr_pages << PAGE_SHIFT);
+ end_dst_offset = dst_window->offset +
+ (dst_window->nr_pages << PAGE_SHIFT);
+ tail_len = remaining_len & (L1_CACHE_BYTES - 1);
+ remaining_len -= tail_len;
+ while (remaining_len) {
+ if (src_offset == end_src_offset) {
+ src_window = list_entry_next(src_window, list);
+ end_src_offset = src_window->offset +
+ (src_window->nr_pages << PAGE_SHIFT);
+ scif_init_window_iter(src_window, &src_win_iter);
+ }
+ if (dst_offset == end_dst_offset) {
+ dst_window = list_entry_next(dst_window, list);
+ end_dst_offset = dst_window->offset +
+ (dst_window->nr_pages << PAGE_SHIFT);
+ scif_init_window_iter(dst_window, &dst_win_iter);
+ }
+
+ /* compute dma addresses for transfer */
+ src_dma_addr = scif_off_to_dma_addr(src_window, src_offset,
+ &src_contig_bytes,
+ &src_win_iter);
+ dst_dma_addr = scif_off_to_dma_addr(dst_window, dst_offset,
+ &dst_contig_bytes,
+ &dst_win_iter);
+ loop_len = min(src_contig_bytes, dst_contig_bytes);
+ loop_len = min(loop_len, remaining_len);
+ if (work->ordered && !tail_len &&
+ !(remaining_len - loop_len)) {
+ /*
+ * Break up the last chunk of the transfer into two
+ * steps. if there is no tail to gurantee DMA ordering.
+ * Passing SCIF_DMA_POLLING inserts a status update
+ * descriptor in step 1 which acts as a double sided
+ * synchronization fence for the DMA engine to ensure
+ * that the last cache line in step 2 is updated last.
+ */
+ /* Step 1) DMA: Body Length - L1_CACHE_BYTES. */
+ tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
+ src_dma_addr,
+ loop_len -
+ L1_CACHE_BYTES,
+ DMA_PREP_FENCE);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ src_offset += (loop_len - L1_CACHE_BYTES);
+ dst_offset += (loop_len - L1_CACHE_BYTES);
+ src_dma_addr += (loop_len - L1_CACHE_BYTES);
+ dst_dma_addr += (loop_len - L1_CACHE_BYTES);
+ remaining_len -= (loop_len - L1_CACHE_BYTES);
+ loop_len = remaining_len;
+
+ /* Step 2) DMA: L1_CACHE_BYTES */
+ tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
+ src_dma_addr,
+ loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ } else {
+ tx = dev->device_prep_dma_memcpy(chan, dst_dma_addr,
+ src_dma_addr,
+ loop_len, 0);
+ if (!tx) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ dma_async_issue_pending(chan);
+ }
+ src_offset += loop_len;
+ dst_offset += loop_len;
+ remaining_len -= loop_len;
+ }
+ remaining_len = tail_len;
+ if (remaining_len) {
+ loop_len = remaining_len;
+ if (src_offset == end_src_offset)
+ src_window = list_entry_next(src_window, list);
+ if (dst_offset == end_dst_offset)
+ dst_window = list_entry_next(dst_window, list);
+
+ src_dma_addr = __scif_off_to_dma_addr(src_window, src_offset);
+ dst_dma_addr = __scif_off_to_dma_addr(dst_window, dst_offset);
+ /*
+ * The CPU copy for the tail bytes must be initiated only once
+ * previous DMA transfers for this endpoint have completed to
+ * guarantee ordering.
+ */
+ if (work->ordered) {
+ struct scif_dev *rdev = work->remote_dev;
+
+ ret = scif_drain_dma_poll(rdev->sdev, chan);
+ if (ret)
+ return ret;
+ }
+ if (src_window->type == SCIF_WINDOW_SELF)
+ src_virt = _get_local_va(src_offset, src_window,
+ loop_len);
+ else
+ src_virt = ioremap_remote(src_offset, src_window,
+ loop_len,
+ work->remote_dev, NULL);
+ if (!src_virt)
+ return -ENOMEM;
+
+ if (dst_window->type == SCIF_WINDOW_SELF)
+ dst_virt = _get_local_va(dst_offset, dst_window,
+ loop_len);
+ else
+ dst_virt = ioremap_remote(dst_offset, dst_window,
+ loop_len,
+ work->remote_dev, NULL);
+ if (!dst_virt) {
+ if (src_window->type != SCIF_WINDOW_SELF)
+ iounmap_remote(src_virt, loop_len, work);
+ return -ENOMEM;
+ }
+
+ if (src_window->type == SCIF_WINDOW_SELF)
+ scif_unaligned_cpy_toio(dst_virt, src_virt, loop_len,
+ work->ordered);
+ else
+ scif_unaligned_cpy_fromio(dst_virt, src_virt,
+ loop_len, work->ordered);
+ if (src_window->type != SCIF_WINDOW_SELF)
+ iounmap_remote(src_virt, loop_len, work);
+
+ if (dst_window->type != SCIF_WINDOW_SELF)
+ iounmap_remote(dst_virt, loop_len, work);
+ remaining_len -= loop_len;
+ }
+ return ret;
+err:
+ dev_err(scif_info.mdev.this_device,
+ "%s %d Desc Prog Failed ret %d\n",
+ __func__, __LINE__, ret);
+ return ret;
+}
+
+/*
+ * scif_rma_list_cpu_copy:
+ *
+ * Traverse all the windows and perform CPU copy.
+ */
+static int scif_rma_list_cpu_copy(struct scif_copy_work *work)
+{
+ void *src_virt, *dst_virt;
+ size_t loop_len, remaining_len;
+ int src_page_off, dst_page_off;
+ s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
+ struct scif_window *src_window = work->src_window;
+ struct scif_window *dst_window = work->dst_window;
+ s64 end_src_offset, end_dst_offset;
+ int ret = 0;
+ struct scif_window_iter src_win_iter;
+ struct scif_window_iter dst_win_iter;
+
+ remaining_len = work->len;
+
+ scif_init_window_iter(src_window, &src_win_iter);
+ scif_init_window_iter(dst_window, &dst_win_iter);
+ while (remaining_len) {
+ src_page_off = src_offset & ~PAGE_MASK;
+ dst_page_off = dst_offset & ~PAGE_MASK;
+ loop_len = min(PAGE_SIZE -
+ max(src_page_off, dst_page_off),
+ remaining_len);
+
+ if (src_window->type == SCIF_WINDOW_SELF)
+ src_virt = _get_local_va(src_offset, src_window,
+ loop_len);
+ else
+ src_virt = ioremap_remote(src_offset, src_window,
+ loop_len,
+ work->remote_dev,
+ &src_win_iter);
+ if (!src_virt) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (dst_window->type == SCIF_WINDOW_SELF)
+ dst_virt = _get_local_va(dst_offset, dst_window,
+ loop_len);
+ else
+ dst_virt = ioremap_remote(dst_offset, dst_window,
+ loop_len,
+ work->remote_dev,
+ &dst_win_iter);
+ if (!dst_virt) {
+ if (src_window->type == SCIF_WINDOW_PEER)
+ iounmap_remote(src_virt, loop_len, work);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (work->loopback) {
+ memcpy(dst_virt, src_virt, loop_len);
+ } else {
+ if (src_window->type == SCIF_WINDOW_SELF)
+ memcpy_toio((void __iomem __force *)dst_virt,
+ src_virt, loop_len);
+ else
+ memcpy_fromio(dst_virt,
+ (void __iomem __force *)src_virt,
+ loop_len);
+ }
+ if (src_window->type == SCIF_WINDOW_PEER)
+ iounmap_remote(src_virt, loop_len, work);
+
+ if (dst_window->type == SCIF_WINDOW_PEER)
+ iounmap_remote(dst_virt, loop_len, work);
+
+ src_offset += loop_len;
+ dst_offset += loop_len;
+ remaining_len -= loop_len;
+ if (remaining_len) {
+ end_src_offset = src_window->offset +
+ (src_window->nr_pages << PAGE_SHIFT);
+ end_dst_offset = dst_window->offset +
+ (dst_window->nr_pages << PAGE_SHIFT);
+ if (src_offset == end_src_offset) {
+ src_window = list_entry_next(src_window, list);
+ scif_init_window_iter(src_window,
+ &src_win_iter);
+ }
+ if (dst_offset == end_dst_offset) {
+ dst_window = list_entry_next(dst_window, list);
+ scif_init_window_iter(dst_window,
+ &dst_win_iter);
+ }
+ }
+ }
+error:
+ return ret;
+}
+
+static int scif_rma_list_dma_copy_wrapper(struct scif_endpt *epd,
+ struct scif_copy_work *work,
+ struct dma_chan *chan, off_t loffset)
+{
+ int src_cache_off, dst_cache_off;
+ s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
+ u8 *temp = NULL;
+ bool src_local = true, dst_local = false;
+ struct scif_dma_comp_cb *comp_cb;
+ dma_addr_t src_dma_addr, dst_dma_addr;
+ int err;
+
+ if (is_dma_copy_aligned(chan->device, 1, 1, 1))
+ return _scif_rma_list_dma_copy_aligned(work, chan);
+
+ src_cache_off = src_offset & (L1_CACHE_BYTES - 1);
+ dst_cache_off = dst_offset & (L1_CACHE_BYTES - 1);
+
+ if (dst_cache_off == src_cache_off)
+ return scif_rma_list_dma_copy_aligned(work, chan);
+
+ if (work->loopback)
+ return scif_rma_list_cpu_copy(work);
+ src_dma_addr = __scif_off_to_dma_addr(work->src_window, src_offset);
+ dst_dma_addr = __scif_off_to_dma_addr(work->dst_window, dst_offset);
+ src_local = work->src_window->type == SCIF_WINDOW_SELF;
+ dst_local = work->dst_window->type == SCIF_WINDOW_SELF;
+
+ dst_local = dst_local;
+ /* Allocate dma_completion cb */
+ comp_cb = kzalloc(sizeof(*comp_cb), GFP_KERNEL);
+ if (!comp_cb)
+ goto error;
+
+ work->comp_cb = comp_cb;
+ comp_cb->cb_cookie = comp_cb;
+ comp_cb->dma_completion_func = &scif_rma_completion_cb;
+
+ if (work->len + (L1_CACHE_BYTES << 1) < SCIF_KMEM_UNALIGNED_BUF_SIZE) {
+ comp_cb->is_cache = false;
+ /* Allocate padding bytes to align to a cache line */
+ temp = kmalloc(work->len + (L1_CACHE_BYTES << 1),
+ GFP_KERNEL);
+ if (!temp)
+ goto free_comp_cb;
+ comp_cb->temp_buf_to_free = temp;
+ /* kmalloc(..) does not guarantee cache line alignment */
+ if (!IS_ALIGNED((u64)temp, L1_CACHE_BYTES))
+ temp = PTR_ALIGN(temp, L1_CACHE_BYTES);
+ } else {
+ comp_cb->is_cache = true;
+ temp = kmem_cache_alloc(unaligned_cache, GFP_KERNEL);
+ if (!temp)
+ goto free_comp_cb;
+ comp_cb->temp_buf_to_free = temp;
+ }
+
+ if (src_local) {
+ temp += dst_cache_off;
+ scif_rma_local_cpu_copy(work->src_offset, work->src_window,
+ temp, work->len, true);
+ } else {
+ comp_cb->dst_window = work->dst_window;
+ comp_cb->dst_offset = work->dst_offset;
+ work->src_offset = work->src_offset - src_cache_off;
+ comp_cb->len = work->len;
+ work->len = ALIGN(work->len + src_cache_off, L1_CACHE_BYTES);
+ comp_cb->header_padding = src_cache_off;
+ }
+ comp_cb->temp_buf = temp;
+
+ err = scif_map_single(&comp_cb->temp_phys, temp,
+ work->remote_dev, SCIF_KMEM_UNALIGNED_BUF_SIZE);
+ if (err)
+ goto free_temp_buf;
+ comp_cb->sdev = work->remote_dev;
+ if (scif_rma_list_dma_copy_unaligned(work, temp, chan, src_local) < 0)
+ goto free_temp_buf;
+ if (!src_local)
+ work->fence_type = SCIF_DMA_INTR;
+ return 0;
+free_temp_buf:
+ if (comp_cb->is_cache)
+ kmem_cache_free(unaligned_cache, comp_cb->temp_buf_to_free);
+ else
+ kfree(comp_cb->temp_buf_to_free);
+free_comp_cb:
+ kfree(comp_cb);
+error:
+ return -ENOMEM;
+}
+
+/**
+ * scif_rma_copy:
+ * @epd: end point descriptor.
+ * @loffset: offset in local registered address space to/from which to copy
+ * @addr: user virtual address to/from which to copy
+ * @len: length of range to copy
+ * @roffset: offset in remote registered address space to/from which to copy
+ * @flags: flags
+ * @dir: LOCAL->REMOTE or vice versa.
+ * @last_chunk: true if this is the last chunk of a larger transfer
+ *
+ * Validate parameters, check if src/dst registered ranges requested for copy
+ * are valid and initiate either CPU or DMA copy.
+ */
+static int scif_rma_copy(scif_epd_t epd, off_t loffset, unsigned long addr,
+ size_t len, off_t roffset, int flags,
+ enum scif_rma_dir dir, bool last_chunk)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct scif_rma_req remote_req;
+ struct scif_rma_req req;
+ struct scif_window *local_window = NULL;
+ struct scif_window *remote_window = NULL;
+ struct scif_copy_work copy_work;
+ bool loopback;
+ int err = 0;
+ struct dma_chan *chan;
+ struct scif_mmu_notif *mmn = NULL;
+ bool cache = false;
+ struct device *spdev;
+
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ if (flags && !(flags & (SCIF_RMA_USECPU | SCIF_RMA_USECACHE |
+ SCIF_RMA_SYNC | SCIF_RMA_ORDERED)))
+ return -EINVAL;
+
+ loopback = scifdev_self(ep->remote_dev) ? true : false;
+ copy_work.fence_type = ((flags & SCIF_RMA_SYNC) && last_chunk) ?
+ SCIF_DMA_POLL : 0;
+ copy_work.ordered = !!((flags & SCIF_RMA_ORDERED) && last_chunk);
+
+ /* Use CPU for Mgmt node <-> Mgmt node copies */
+ if (loopback && scif_is_mgmt_node()) {
+ flags |= SCIF_RMA_USECPU;
+ copy_work.fence_type = 0x0;
+ }
+
+ cache = scif_is_set_reg_cache(flags);
+
+ remote_req.out_window = &remote_window;
+ remote_req.offset = roffset;
+ remote_req.nr_bytes = len;
+ /*
+ * If transfer is from local to remote then the remote window
+ * must be writeable and vice versa.
+ */
+ remote_req.prot = dir == SCIF_LOCAL_TO_REMOTE ? VM_WRITE : VM_READ;
+ remote_req.type = SCIF_WINDOW_PARTIAL;
+ remote_req.head = &ep->rma_info.remote_reg_list;
+
+ spdev = scif_get_peer_dev(ep->remote_dev);
+ if (IS_ERR(spdev)) {
+ err = PTR_ERR(spdev);
+ return err;
+ }
+
+ if (addr && cache) {
+ mutex_lock(&ep->rma_info.mmn_lock);
+ mmn = scif_find_mmu_notifier(current->mm, &ep->rma_info);
+ if (!mmn)
+ scif_add_mmu_notifier(current->mm, ep);
+ mutex_unlock(&ep->rma_info.mmn_lock);
+ if (IS_ERR(mmn)) {
+ scif_put_peer_dev(spdev);
+ return PTR_ERR(mmn);
+ }
+ cache = cache && !scif_rma_tc_can_cache(ep, len);
+ }
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (addr) {
+ req.out_window = &local_window;
+ req.nr_bytes = ALIGN(len + (addr & ~PAGE_MASK),
+ PAGE_SIZE);
+ req.va_for_temp = addr & PAGE_MASK;
+ req.prot = (dir == SCIF_LOCAL_TO_REMOTE ?
+ VM_READ : VM_WRITE | VM_READ);
+ /* Does a valid local window exist? */
+ if (mmn) {
+ spin_lock(&ep->rma_info.tc_lock);
+ req.head = &mmn->tc_reg_list;
+ err = scif_query_tcw(ep, &req);
+ spin_unlock(&ep->rma_info.tc_lock);
+ }
+ if (!mmn || err) {
+ err = scif_register_temp(epd, req.va_for_temp,
+ req.nr_bytes, req.prot,
+ &loffset, &local_window);
+ if (err) {
+ mutex_unlock(&ep->rma_info.rma_lock);
+ goto error;
+ }
+ if (!cache)
+ goto skip_cache;
+ atomic_inc(&ep->rma_info.tcw_refcount);
+ atomic_add_return(local_window->nr_pages,
+ &ep->rma_info.tcw_total_pages);
+ if (mmn) {
+ spin_lock(&ep->rma_info.tc_lock);
+ scif_insert_tcw(local_window,
+ &mmn->tc_reg_list);
+ spin_unlock(&ep->rma_info.tc_lock);
+ }
+ }
+skip_cache:
+ loffset = local_window->offset +
+ (addr - local_window->va_for_temp);
+ } else {
+ req.out_window = &local_window;
+ req.offset = loffset;
+ /*
+ * If transfer is from local to remote then the self window
+ * must be readable and vice versa.
+ */
+ req.prot = dir == SCIF_LOCAL_TO_REMOTE ? VM_READ : VM_WRITE;
+ req.nr_bytes = len;
+ req.type = SCIF_WINDOW_PARTIAL;
+ req.head = &ep->rma_info.reg_list;
+ /* Does a valid local window exist? */
+ err = scif_query_window(&req);
+ if (err) {
+ mutex_unlock(&ep->rma_info.rma_lock);
+ goto error;
+ }
+ }
+
+ /* Does a valid remote window exist? */
+ err = scif_query_window(&remote_req);
+ if (err) {
+ mutex_unlock(&ep->rma_info.rma_lock);
+ goto error;
+ }
+
+ /*
+ * Prepare copy_work for submitting work to the DMA kernel thread
+ * or CPU copy routine.
+ */
+ copy_work.len = len;
+ copy_work.loopback = loopback;
+ copy_work.remote_dev = ep->remote_dev;
+ if (dir == SCIF_LOCAL_TO_REMOTE) {
+ copy_work.src_offset = loffset;
+ copy_work.src_window = local_window;
+ copy_work.dst_offset = roffset;
+ copy_work.dst_window = remote_window;
+ } else {
+ copy_work.src_offset = roffset;
+ copy_work.src_window = remote_window;
+ copy_work.dst_offset = loffset;
+ copy_work.dst_window = local_window;
+ }
+
+ if (flags & SCIF_RMA_USECPU) {
+ scif_rma_list_cpu_copy(&copy_work);
+ } else {
+ chan = ep->rma_info.dma_chan;
+ err = scif_rma_list_dma_copy_wrapper(epd, &copy_work,
+ chan, loffset);
+ }
+ if (addr && !cache)
+ atomic_inc(&ep->rma_info.tw_refcount);
+
+ mutex_unlock(&ep->rma_info.rma_lock);
+
+ if (last_chunk) {
+ struct scif_dev *rdev = ep->remote_dev;
+
+ if (copy_work.fence_type == SCIF_DMA_POLL)
+ err = scif_drain_dma_poll(rdev->sdev,
+ ep->rma_info.dma_chan);
+ else if (copy_work.fence_type == SCIF_DMA_INTR)
+ err = scif_drain_dma_intr(rdev->sdev,
+ ep->rma_info.dma_chan);
+ }
+
+ if (addr && !cache)
+ scif_queue_for_cleanup(local_window, &scif_info.rma);
+ scif_put_peer_dev(spdev);
+ return err;
+error:
+ if (err) {
+ if (addr && local_window && !cache)
+ scif_destroy_window(ep, local_window);
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d len 0x%lx\n",
+ __func__, __LINE__, err, len);
+ }
+ scif_put_peer_dev(spdev);
+ return err;
+}
+
+int scif_readfrom(scif_epd_t epd, off_t loffset, size_t len,
+ off_t roffset, int flags)
+{
+ int err;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI readfrom: ep %p loffset 0x%lx len 0x%lx offset 0x%lx flags 0x%x\n",
+ epd, loffset, len, roffset, flags);
+ if (scif_unaligned(loffset, roffset)) {
+ while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
+ err = scif_rma_copy(epd, loffset, 0x0,
+ SCIF_MAX_UNALIGNED_BUF_SIZE,
+ roffset, flags,
+ SCIF_REMOTE_TO_LOCAL, false);
+ if (err)
+ goto readfrom_err;
+ loffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
+ }
+ }
+ err = scif_rma_copy(epd, loffset, 0x0, len,
+ roffset, flags, SCIF_REMOTE_TO_LOCAL, true);
+readfrom_err:
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_readfrom);
+
+int scif_writeto(scif_epd_t epd, off_t loffset, size_t len,
+ off_t roffset, int flags)
+{
+ int err;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI writeto: ep %p loffset 0x%lx len 0x%lx roffset 0x%lx flags 0x%x\n",
+ epd, loffset, len, roffset, flags);
+ if (scif_unaligned(loffset, roffset)) {
+ while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
+ err = scif_rma_copy(epd, loffset, 0x0,
+ SCIF_MAX_UNALIGNED_BUF_SIZE,
+ roffset, flags,
+ SCIF_LOCAL_TO_REMOTE, false);
+ if (err)
+ goto writeto_err;
+ loffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
+ }
+ }
+ err = scif_rma_copy(epd, loffset, 0x0, len,
+ roffset, flags, SCIF_LOCAL_TO_REMOTE, true);
+writeto_err:
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_writeto);
+
+int scif_vreadfrom(scif_epd_t epd, void *addr, size_t len,
+ off_t roffset, int flags)
+{
+ int err;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI vreadfrom: ep %p addr %p len 0x%lx roffset 0x%lx flags 0x%x\n",
+ epd, addr, len, roffset, flags);
+ if (scif_unaligned((off_t __force)addr, roffset)) {
+ if (len > SCIF_MAX_UNALIGNED_BUF_SIZE)
+ flags &= ~SCIF_RMA_USECACHE;
+
+ while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
+ err = scif_rma_copy(epd, 0, (u64)addr,
+ SCIF_MAX_UNALIGNED_BUF_SIZE,
+ roffset, flags,
+ SCIF_REMOTE_TO_LOCAL, false);
+ if (err)
+ goto vreadfrom_err;
+ addr += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
+ }
+ }
+ err = scif_rma_copy(epd, 0, (u64)addr, len,
+ roffset, flags, SCIF_REMOTE_TO_LOCAL, true);
+vreadfrom_err:
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_vreadfrom);
+
+int scif_vwriteto(scif_epd_t epd, void *addr, size_t len,
+ off_t roffset, int flags)
+{
+ int err;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI vwriteto: ep %p addr %p len 0x%lx roffset 0x%lx flags 0x%x\n",
+ epd, addr, len, roffset, flags);
+ if (scif_unaligned((off_t __force)addr, roffset)) {
+ if (len > SCIF_MAX_UNALIGNED_BUF_SIZE)
+ flags &= ~SCIF_RMA_USECACHE;
+
+ while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
+ err = scif_rma_copy(epd, 0, (u64)addr,
+ SCIF_MAX_UNALIGNED_BUF_SIZE,
+ roffset, flags,
+ SCIF_LOCAL_TO_REMOTE, false);
+ if (err)
+ goto vwriteto_err;
+ addr += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
+ len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
+ }
+ }
+ err = scif_rma_copy(epd, 0, (u64)addr, len,
+ roffset, flags, SCIF_LOCAL_TO_REMOTE, true);
+vwriteto_err:
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_vwriteto);
diff --git a/drivers/misc/mic/scif/scif_epd.c b/drivers/misc/mic/scif/scif_epd.c
index b4bfbb08a8e3..00e5d6d66e7b 100644
--- a/drivers/misc/mic/scif/scif_epd.c
+++ b/drivers/misc/mic/scif/scif_epd.c
@@ -65,14 +65,14 @@ void scif_teardown_ep(void *endpt)
void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held)
{
if (!eplock_held)
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
spin_lock(&ep->lock);
ep->state = SCIFEP_ZOMBIE;
spin_unlock(&ep->lock);
list_add_tail(&ep->list, &scif_info.zombie);
scif_info.nr_zombies++;
if (!eplock_held)
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
schedule_work(&scif_info.misc_work);
}
@@ -81,16 +81,15 @@ static struct scif_endpt *scif_find_listen_ep(u16 port)
struct scif_endpt *ep = NULL;
struct list_head *pos, *tmpq;
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
list_for_each_safe(pos, tmpq, &scif_info.listen) {
ep = list_entry(pos, struct scif_endpt, list);
if (ep->port.port == port) {
- spin_lock(&ep->lock);
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
return ep;
}
}
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
return NULL;
}
@@ -99,14 +98,17 @@ void scif_cleanup_zombie_epd(void)
struct list_head *pos, *tmpq;
struct scif_endpt *ep;
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
list_for_each_safe(pos, tmpq, &scif_info.zombie) {
ep = list_entry(pos, struct scif_endpt, list);
- list_del(pos);
- scif_info.nr_zombies--;
- kfree(ep);
+ if (scif_rma_ep_can_uninit(ep)) {
+ list_del(pos);
+ scif_info.nr_zombies--;
+ put_iova_domain(&ep->rma_info.iovad);
+ kfree(ep);
+ }
}
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
}
/**
@@ -137,6 +139,8 @@ void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg)
if (!ep)
/* Send reject due to no listening ports */
goto conreq_sendrej_free;
+ else
+ spin_lock(&ep->lock);
if (ep->backlog <= ep->conreqcnt) {
/* Send reject due to too many pending requests */
diff --git a/drivers/misc/mic/scif/scif_epd.h b/drivers/misc/mic/scif/scif_epd.h
index 331322a25213..1771d7a9b8d0 100644
--- a/drivers/misc/mic/scif/scif_epd.h
+++ b/drivers/misc/mic/scif/scif_epd.h
@@ -96,7 +96,11 @@ struct scif_endpt_qp_info {
* @conn_port: Connection port
* @conn_err: Errors during connection
* @conn_async_state: Async connection
+ * @conn_pend_wq: Used by poll while waiting for incoming connections
* @conn_list: List of async connection requests
+ * @rma_info: Information for triggering SCIF RMA and DMA operations
+ * @mmu_list: link to list of MMU notifier cleanup work
+ * @anon: anonymous file for use in kernel mode scif poll
*/
struct scif_endpt {
enum scif_epd_state state;
@@ -125,7 +129,11 @@ struct scif_endpt {
struct scif_port_id conn_port;
int conn_err;
int conn_async_state;
+ wait_queue_head_t conn_pend_wq;
struct list_head conn_list;
+ struct scif_endpt_rma_info rma_info;
+ struct list_head mmu_list;
+ struct file *anon;
};
static inline int scifdev_alive(struct scif_endpt *ep)
@@ -133,6 +141,43 @@ static inline int scifdev_alive(struct scif_endpt *ep)
return _scifdev_alive(ep->remote_dev);
}
+/*
+ * scif_verify_epd:
+ * ep: SCIF endpoint
+ *
+ * Checks several generic error conditions and returns the
+ * appropriate error.
+ */
+static inline int scif_verify_epd(struct scif_endpt *ep)
+{
+ if (ep->state == SCIFEP_DISCONNECTED)
+ return -ECONNRESET;
+
+ if (ep->state != SCIFEP_CONNECTED)
+ return -ENOTCONN;
+
+ if (!scifdev_alive(ep))
+ return -ENODEV;
+
+ return 0;
+}
+
+static inline int scif_anon_inode_getfile(scif_epd_t epd)
+{
+ epd->anon = anon_inode_getfile("scif", &scif_anon_fops, NULL, 0);
+ if (IS_ERR(epd->anon))
+ return PTR_ERR(epd->anon);
+ return 0;
+}
+
+static inline void scif_anon_inode_fput(scif_epd_t epd)
+{
+ if (epd->anon) {
+ fput(epd->anon);
+ epd->anon = NULL;
+ }
+}
+
void scif_cleanup_zombie_epd(void);
void scif_teardown_ep(void *endpt);
void scif_cleanup_ep_qp(struct scif_endpt *ep);
@@ -157,4 +202,9 @@ void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
int __scif_flush(scif_epd_t epd);
+int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd);
+unsigned int __scif_pollfd(struct file *f, poll_table *wait,
+ struct scif_endpt *ep);
+int __scif_pin_pages(void *addr, size_t len, int *out_prot,
+ int map_flags, scif_pinned_pages_t *pages);
#endif /* SCIF_EPD_H */
diff --git a/drivers/misc/mic/scif/scif_fd.c b/drivers/misc/mic/scif/scif_fd.c
index eccf7e7135f9..f7e826142a72 100644
--- a/drivers/misc/mic/scif/scif_fd.c
+++ b/drivers/misc/mic/scif/scif_fd.c
@@ -34,6 +34,20 @@ static int scif_fdclose(struct inode *inode, struct file *f)
return scif_close(priv);
}
+static int scif_fdmmap(struct file *f, struct vm_area_struct *vma)
+{
+ struct scif_endpt *priv = f->private_data;
+
+ return scif_mmap(vma, priv);
+}
+
+static unsigned int scif_fdpoll(struct file *f, poll_table *wait)
+{
+ struct scif_endpt *priv = f->private_data;
+
+ return __scif_pollfd(f, wait, priv);
+}
+
static int scif_fdflush(struct file *f, fl_owner_t id)
{
struct scif_endpt *ep = f->private_data;
@@ -140,12 +154,12 @@ static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
* Add to the list of user mode eps where the second half
* of the accept is not yet completed.
*/
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
list_add_tail(&((*ep)->miacceptlist), &scif_info.uaccept);
list_add_tail(&((*ep)->liacceptlist), &priv->li_accept);
(*ep)->listenep = priv;
priv->acceptcnt++;
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
return 0;
}
@@ -163,7 +177,7 @@ static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
return -EFAULT;
/* Remove form the user accept queue */
- spin_lock(&scif_info.eplock);
+ mutex_lock(&scif_info.eplock);
list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
tmpep = list_entry(pos,
struct scif_endpt, miacceptlist);
@@ -175,7 +189,7 @@ static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
}
if (!fep) {
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
return -ENOENT;
}
@@ -190,9 +204,10 @@ static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
}
}
- spin_unlock(&scif_info.eplock);
+ mutex_unlock(&scif_info.eplock);
/* Free the resources automatically created from the open. */
+ scif_anon_inode_fput(priv);
scif_teardown_ep(priv);
scif_add_epd_to_zombie_list(priv, !SCIF_EPLOCK_HELD);
f->private_data = newep;
@@ -290,6 +305,157 @@ getnodes_err1:
getnodes_err2:
return err;
}
+ case SCIF_REG:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_reg reg;
+ off_t ret;
+
+ if (copy_from_user(&reg, argp, sizeof(reg))) {
+ err = -EFAULT;
+ goto reg_err;
+ }
+ if (reg.flags & SCIF_MAP_KERNEL) {
+ err = -EINVAL;
+ goto reg_err;
+ }
+ ret = scif_register(priv, (void *)reg.addr, reg.len,
+ reg.offset, reg.prot, reg.flags);
+ if (ret < 0) {
+ err = (int)ret;
+ goto reg_err;
+ }
+
+ if (copy_to_user(&((struct scifioctl_reg __user *)argp)
+ ->out_offset, &ret, sizeof(reg.out_offset))) {
+ err = -EFAULT;
+ goto reg_err;
+ }
+ err = 0;
+reg_err:
+ scif_err_debug(err, "scif_register");
+ return err;
+ }
+ case SCIF_UNREG:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_unreg unreg;
+
+ if (copy_from_user(&unreg, argp, sizeof(unreg))) {
+ err = -EFAULT;
+ goto unreg_err;
+ }
+ err = scif_unregister(priv, unreg.offset, unreg.len);
+unreg_err:
+ scif_err_debug(err, "scif_unregister");
+ return err;
+ }
+ case SCIF_READFROM:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_copy copy;
+
+ if (copy_from_user(&copy, argp, sizeof(copy))) {
+ err = -EFAULT;
+ goto readfrom_err;
+ }
+ err = scif_readfrom(priv, copy.loffset, copy.len, copy.roffset,
+ copy.flags);
+readfrom_err:
+ scif_err_debug(err, "scif_readfrom");
+ return err;
+ }
+ case SCIF_WRITETO:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_copy copy;
+
+ if (copy_from_user(&copy, argp, sizeof(copy))) {
+ err = -EFAULT;
+ goto writeto_err;
+ }
+ err = scif_writeto(priv, copy.loffset, copy.len, copy.roffset,
+ copy.flags);
+writeto_err:
+ scif_err_debug(err, "scif_writeto");
+ return err;
+ }
+ case SCIF_VREADFROM:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_copy copy;
+
+ if (copy_from_user(&copy, argp, sizeof(copy))) {
+ err = -EFAULT;
+ goto vreadfrom_err;
+ }
+ err = scif_vreadfrom(priv, (void __force *)copy.addr, copy.len,
+ copy.roffset, copy.flags);
+vreadfrom_err:
+ scif_err_debug(err, "scif_vreadfrom");
+ return err;
+ }
+ case SCIF_VWRITETO:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_copy copy;
+
+ if (copy_from_user(&copy, argp, sizeof(copy))) {
+ err = -EFAULT;
+ goto vwriteto_err;
+ }
+ err = scif_vwriteto(priv, (void __force *)copy.addr, copy.len,
+ copy.roffset, copy.flags);
+vwriteto_err:
+ scif_err_debug(err, "scif_vwriteto");
+ return err;
+ }
+ case SCIF_FENCE_MARK:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_fence_mark mark;
+ int tmp_mark = 0;
+
+ if (copy_from_user(&mark, argp, sizeof(mark))) {
+ err = -EFAULT;
+ goto fence_mark_err;
+ }
+ err = scif_fence_mark(priv, mark.flags, &tmp_mark);
+ if (err)
+ goto fence_mark_err;
+ if (copy_to_user((void __user *)mark.mark, &tmp_mark,
+ sizeof(tmp_mark))) {
+ err = -EFAULT;
+ goto fence_mark_err;
+ }
+fence_mark_err:
+ scif_err_debug(err, "scif_fence_mark");
+ return err;
+ }
+ case SCIF_FENCE_WAIT:
+ {
+ struct scif_endpt *priv = f->private_data;
+
+ err = scif_fence_wait(priv, arg);
+ scif_err_debug(err, "scif_fence_wait");
+ return err;
+ }
+ case SCIF_FENCE_SIGNAL:
+ {
+ struct scif_endpt *priv = f->private_data;
+ struct scifioctl_fence_signal signal;
+
+ if (copy_from_user(&signal, argp, sizeof(signal))) {
+ err = -EFAULT;
+ goto fence_signal_err;
+ }
+
+ err = scif_fence_signal(priv, signal.loff, signal.lval,
+ signal.roff, signal.rval, signal.flags);
+fence_signal_err:
+ scif_err_debug(err, "scif_fence_signal");
+ return err;
+ }
}
return -EINVAL;
}
@@ -298,6 +464,8 @@ const struct file_operations scif_fops = {
.open = scif_fdopen,
.release = scif_fdclose,
.unlocked_ioctl = scif_fdioctl,
+ .mmap = scif_fdmmap,
+ .poll = scif_fdpoll,
.flush = scif_fdflush,
.owner = THIS_MODULE,
};
diff --git a/drivers/misc/mic/scif/scif_fence.c b/drivers/misc/mic/scif/scif_fence.c
new file mode 100644
index 000000000000..7f2c96f57066
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_fence.c
@@ -0,0 +1,771 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+
+#include "scif_main.h"
+
+/**
+ * scif_recv_mark: Handle SCIF_MARK request
+ * @msg: Interrupt message
+ *
+ * The peer has requested a mark.
+ */
+void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ int mark, err;
+
+ err = _scif_fence_mark(ep, &mark);
+ if (err)
+ msg->uop = SCIF_MARK_NACK;
+ else
+ msg->uop = SCIF_MARK_ACK;
+ msg->payload[0] = ep->remote_ep;
+ msg->payload[2] = mark;
+ scif_nodeqp_send(ep->remote_dev, msg);
+}
+
+/**
+ * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages.
+ * @msg: Interrupt message
+ *
+ * The peer has responded to a SCIF_MARK message.
+ */
+void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ struct scif_fence_info *fence_req =
+ (struct scif_fence_info *)msg->payload[1];
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (msg->uop == SCIF_MARK_ACK) {
+ fence_req->state = OP_COMPLETED;
+ fence_req->dma_mark = (int)msg->payload[2];
+ } else {
+ fence_req->state = OP_FAILED;
+ }
+ mutex_unlock(&ep->rma_info.rma_lock);
+ complete(&fence_req->comp);
+}
+
+/**
+ * scif_recv_wait: Handle SCIF_WAIT request
+ * @msg: Interrupt message
+ *
+ * The peer has requested waiting on a fence.
+ */
+void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ struct scif_remote_fence_info *fence;
+
+ /*
+ * Allocate structure for remote fence information and
+ * send a NACK if the allocation failed. The peer will
+ * return ENOMEM upon receiving a NACK.
+ */
+ fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence) {
+ msg->payload[0] = ep->remote_ep;
+ msg->uop = SCIF_WAIT_NACK;
+ scif_nodeqp_send(ep->remote_dev, msg);
+ return;
+ }
+
+ /* Prepare the fence request */
+ memcpy(&fence->msg, msg, sizeof(struct scifmsg));
+ INIT_LIST_HEAD(&fence->list);
+
+ /* Insert to the global remote fence request list */
+ mutex_lock(&scif_info.fencelock);
+ atomic_inc(&ep->rma_info.fence_refcount);
+ list_add_tail(&fence->list, &scif_info.fence);
+ mutex_unlock(&scif_info.fencelock);
+
+ schedule_work(&scif_info.misc_work);
+}
+
+/**
+ * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages.
+ * @msg: Interrupt message
+ *
+ * The peer has responded to a SCIF_WAIT message.
+ */
+void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ struct scif_fence_info *fence_req =
+ (struct scif_fence_info *)msg->payload[1];
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (msg->uop == SCIF_WAIT_ACK)
+ fence_req->state = OP_COMPLETED;
+ else
+ fence_req->state = OP_FAILED;
+ mutex_unlock(&ep->rma_info.rma_lock);
+ complete(&fence_req->comp);
+}
+
+/**
+ * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request
+ * @msg: Interrupt message
+ *
+ * The peer has requested a signal on a local offset.
+ */
+void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ int err;
+
+ err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
+ SCIF_WINDOW_SELF);
+ if (err)
+ msg->uop = SCIF_SIG_NACK;
+ else
+ msg->uop = SCIF_SIG_ACK;
+ msg->payload[0] = ep->remote_ep;
+ scif_nodeqp_send(ep->remote_dev, msg);
+}
+
+/**
+ * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request
+ * @msg: Interrupt message
+ *
+ * The peer has requested a signal on a remote offset.
+ */
+void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ int err;
+
+ err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
+ SCIF_WINDOW_PEER);
+ if (err)
+ msg->uop = SCIF_SIG_NACK;
+ else
+ msg->uop = SCIF_SIG_ACK;
+ msg->payload[0] = ep->remote_ep;
+ scif_nodeqp_send(ep->remote_dev, msg);
+}
+
+/**
+ * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages.
+ * @msg: Interrupt message
+ *
+ * The peer has responded to a signal request.
+ */
+void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ struct scif_fence_info *fence_req =
+ (struct scif_fence_info *)msg->payload[3];
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (msg->uop == SCIF_SIG_ACK)
+ fence_req->state = OP_COMPLETED;
+ else
+ fence_req->state = OP_FAILED;
+ mutex_unlock(&ep->rma_info.rma_lock);
+ complete(&fence_req->comp);
+}
+
+static inline void *scif_get_local_va(off_t off, struct scif_window *window)
+{
+ struct page **pages = window->pinned_pages->pages;
+ int page_nr = (off - window->offset) >> PAGE_SHIFT;
+ off_t page_off = off & ~PAGE_MASK;
+
+ return page_address(pages[page_nr]) + page_off;
+}
+
+static void scif_prog_signal_cb(void *arg)
+{
+ struct scif_status *status = arg;
+
+ dma_pool_free(status->ep->remote_dev->signal_pool, status,
+ status->src_dma_addr);
+}
+
+static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct dma_chan *chan = ep->rma_info.dma_chan;
+ struct dma_device *ddev = chan->device;
+ bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1);
+ struct dma_async_tx_descriptor *tx;
+ struct scif_status *status = NULL;
+ dma_addr_t src;
+ dma_cookie_t cookie;
+ int err;
+
+ tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
+ if (!tx) {
+ err = -ENOMEM;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto alloc_fail;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ err = (int)cookie;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto alloc_fail;
+ }
+ dma_async_issue_pending(chan);
+ if (x100) {
+ /*
+ * For X100 use the status descriptor to write the value to
+ * the destination.
+ */
+ tx = ddev->device_prep_dma_imm_data(chan, dst, val, 0);
+ } else {
+ status = dma_pool_alloc(ep->remote_dev->signal_pool, GFP_KERNEL,
+ &src);
+ if (!status) {
+ err = -ENOMEM;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto alloc_fail;
+ }
+ status->val = val;
+ status->src_dma_addr = src;
+ status->ep = ep;
+ src += offsetof(struct scif_status, val);
+ tx = ddev->device_prep_dma_memcpy(chan, dst, src, sizeof(val),
+ DMA_PREP_INTERRUPT);
+ }
+ if (!tx) {
+ err = -ENOMEM;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto dma_fail;
+ }
+ if (!x100) {
+ tx->callback = scif_prog_signal_cb;
+ tx->callback_param = status;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ err = -EIO;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto dma_fail;
+ }
+ dma_async_issue_pending(chan);
+ return 0;
+dma_fail:
+ if (!x100)
+ dma_pool_free(ep->remote_dev->signal_pool, status,
+ status->src_dma_addr);
+alloc_fail:
+ return err;
+}
+
+/*
+ * scif_prog_signal:
+ * @epd - Endpoint Descriptor
+ * @offset - registered address to write @val to
+ * @val - Value to be written at @offset
+ * @type - Type of the window.
+ *
+ * Arrange to write a value to the registered offset after ensuring that the
+ * offset provided is indeed valid.
+ */
+int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
+ enum scif_window_type type)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct scif_window *window = NULL;
+ struct scif_rma_req req;
+ dma_addr_t dst_dma_addr;
+ int err;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ req.out_window = &window;
+ req.offset = offset;
+ req.nr_bytes = sizeof(u64);
+ req.prot = SCIF_PROT_WRITE;
+ req.type = SCIF_WINDOW_SINGLE;
+ if (type == SCIF_WINDOW_SELF)
+ req.head = &ep->rma_info.reg_list;
+ else
+ req.head = &ep->rma_info.remote_reg_list;
+ /* Does a valid window exist? */
+ err = scif_query_window(&req);
+ if (err) {
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto unlock_ret;
+ }
+
+ if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) {
+ u64 *dst_virt;
+
+ if (type == SCIF_WINDOW_SELF)
+ dst_virt = scif_get_local_va(offset, window);
+ else
+ dst_virt =
+ scif_get_local_va(offset, (struct scif_window *)
+ window->peer_window);
+ *dst_virt = val;
+ } else {
+ dst_dma_addr = __scif_off_to_dma_addr(window, offset);
+ err = _scif_prog_signal(epd, dst_dma_addr, val);
+ }
+unlock_ret:
+ mutex_unlock(&ep->rma_info.rma_lock);
+ return err;
+}
+
+static int _scif_fence_wait(scif_epd_t epd, int mark)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE;
+ int err;
+
+ /* Wait for DMA callback in scif_fence_mark_cb(..) */
+ err = wait_event_interruptible_timeout(ep->rma_info.markwq,
+ dma_async_is_tx_complete(
+ ep->rma_info.dma_chan,
+ cookie, NULL, NULL) ==
+ DMA_COMPLETE,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ if (!err)
+ err = -ETIMEDOUT;
+ else if (err > 0)
+ err = 0;
+ return err;
+}
+
+/**
+ * scif_rma_handle_remote_fences:
+ *
+ * This routine services remote fence requests.
+ */
+void scif_rma_handle_remote_fences(void)
+{
+ struct list_head *item, *tmp;
+ struct scif_remote_fence_info *fence;
+ struct scif_endpt *ep;
+ int mark, err;
+
+ might_sleep();
+ mutex_lock(&scif_info.fencelock);
+ list_for_each_safe(item, tmp, &scif_info.fence) {
+ fence = list_entry(item, struct scif_remote_fence_info,
+ list);
+ /* Remove fence from global list */
+ list_del(&fence->list);
+
+ /* Initiate the fence operation */
+ ep = (struct scif_endpt *)fence->msg.payload[0];
+ mark = fence->msg.payload[2];
+ err = _scif_fence_wait(ep, mark);
+ if (err)
+ fence->msg.uop = SCIF_WAIT_NACK;
+ else
+ fence->msg.uop = SCIF_WAIT_ACK;
+ fence->msg.payload[0] = ep->remote_ep;
+ scif_nodeqp_send(ep->remote_dev, &fence->msg);
+ kfree(fence);
+ if (!atomic_sub_return(1, &ep->rma_info.fence_refcount))
+ schedule_work(&scif_info.misc_work);
+ }
+ mutex_unlock(&scif_info.fencelock);
+}
+
+static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark)
+{
+ int err;
+ struct scifmsg msg;
+ struct scif_fence_info *fence_req;
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+
+ fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
+ if (!fence_req) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ fence_req->state = OP_IN_PROGRESS;
+ init_completion(&fence_req->comp);
+
+ msg.src = ep->port;
+ msg.uop = uop;
+ msg.payload[0] = ep->remote_ep;
+ msg.payload[1] = (u64)fence_req;
+ if (uop == SCIF_WAIT)
+ msg.payload[2] = mark;
+ spin_lock(&ep->lock);
+ if (ep->state == SCIFEP_CONNECTED)
+ err = scif_nodeqp_send(ep->remote_dev, &msg);
+ else
+ err = -ENOTCONN;
+ spin_unlock(&ep->lock);
+ if (err)
+ goto error_free;
+retry:
+ /* Wait for a SCIF_WAIT_(N)ACK message */
+ err = wait_for_completion_timeout(&fence_req->comp,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ if (!err && scifdev_alive(ep))
+ goto retry;
+ if (!err)
+ err = -ENODEV;
+ if (err > 0)
+ err = 0;
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (err < 0) {
+ if (fence_req->state == OP_IN_PROGRESS)
+ fence_req->state = OP_FAILED;
+ }
+ if (fence_req->state == OP_FAILED && !err)
+ err = -ENOMEM;
+ if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED)
+ *out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark;
+ mutex_unlock(&ep->rma_info.rma_lock);
+error_free:
+ kfree(fence_req);
+error:
+ return err;
+}
+
+/**
+ * scif_send_fence_mark:
+ * @epd: end point descriptor.
+ * @out_mark: Output DMA mark reported by peer.
+ *
+ * Send a remote fence mark request.
+ */
+static int scif_send_fence_mark(scif_epd_t epd, int *out_mark)
+{
+ return _scif_send_fence(epd, SCIF_MARK, 0, out_mark);
+}
+
+/**
+ * scif_send_fence_wait:
+ * @epd: end point descriptor.
+ * @mark: DMA mark to wait for.
+ *
+ * Send a remote fence wait request.
+ */
+static int scif_send_fence_wait(scif_epd_t epd, int mark)
+{
+ return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
+}
+
+static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
+ struct scif_fence_info *fence_req)
+{
+ int err;
+
+retry:
+ /* Wait for a SCIF_SIG_(N)ACK message */
+ err = wait_for_completion_timeout(&fence_req->comp,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ if (!err && scifdev_alive(ep))
+ goto retry;
+ if (!err)
+ err = -ENODEV;
+ if (err > 0)
+ err = 0;
+ if (err < 0) {
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (fence_req->state == OP_IN_PROGRESS)
+ fence_req->state = OP_FAILED;
+ mutex_unlock(&ep->rma_info.rma_lock);
+ }
+ if (fence_req->state == OP_FAILED && !err)
+ err = -ENXIO;
+ return err;
+}
+
+/**
+ * scif_send_fence_signal:
+ * @epd - endpoint descriptor
+ * @loff - local offset
+ * @lval - local value to write to loffset
+ * @roff - remote offset
+ * @rval - remote value to write to roffset
+ * @flags - flags
+ *
+ * Sends a remote fence signal request
+ */
+static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval,
+ off_t loff, u64 lval, int flags)
+{
+ int err = 0;
+ struct scifmsg msg;
+ struct scif_fence_info *fence_req;
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+
+ fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
+ if (!fence_req) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ fence_req->state = OP_IN_PROGRESS;
+ init_completion(&fence_req->comp);
+ msg.src = ep->port;
+ if (flags & SCIF_SIGNAL_LOCAL) {
+ msg.uop = SCIF_SIG_LOCAL;
+ msg.payload[0] = ep->remote_ep;
+ msg.payload[1] = roff;
+ msg.payload[2] = rval;
+ msg.payload[3] = (u64)fence_req;
+ spin_lock(&ep->lock);
+ if (ep->state == SCIFEP_CONNECTED)
+ err = scif_nodeqp_send(ep->remote_dev, &msg);
+ else
+ err = -ENOTCONN;
+ spin_unlock(&ep->lock);
+ if (err)
+ goto error_free;
+ err = _scif_send_fence_signal_wait(ep, fence_req);
+ if (err)
+ goto error_free;
+ }
+ fence_req->state = OP_IN_PROGRESS;
+
+ if (flags & SCIF_SIGNAL_REMOTE) {
+ msg.uop = SCIF_SIG_REMOTE;
+ msg.payload[0] = ep->remote_ep;
+ msg.payload[1] = loff;
+ msg.payload[2] = lval;
+ msg.payload[3] = (u64)fence_req;
+ spin_lock(&ep->lock);
+ if (ep->state == SCIFEP_CONNECTED)
+ err = scif_nodeqp_send(ep->remote_dev, &msg);
+ else
+ err = -ENOTCONN;
+ spin_unlock(&ep->lock);
+ if (err)
+ goto error_free;
+ err = _scif_send_fence_signal_wait(ep, fence_req);
+ }
+error_free:
+ kfree(fence_req);
+error:
+ return err;
+}
+
+static void scif_fence_mark_cb(void *arg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)arg;
+
+ wake_up_interruptible(&ep->rma_info.markwq);
+ atomic_dec(&ep->rma_info.fence_refcount);
+}
+
+/*
+ * _scif_fence_mark:
+ *
+ * @epd - endpoint descriptor
+ * Set up a mark for this endpoint and return the value of the mark.
+ */
+int _scif_fence_mark(scif_epd_t epd, int *mark)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct dma_chan *chan = ep->rma_info.dma_chan;
+ struct dma_device *ddev = chan->device;
+ struct dma_async_tx_descriptor *tx;
+ dma_cookie_t cookie;
+ int err;
+
+ tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
+ if (!tx) {
+ err = -ENOMEM;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ err = (int)cookie;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ dma_async_issue_pending(chan);
+ tx = ddev->device_prep_dma_interrupt(chan, DMA_PREP_INTERRUPT);
+ if (!tx) {
+ err = -ENOMEM;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ tx->callback = scif_fence_mark_cb;
+ tx->callback_param = ep;
+ *mark = cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ err = (int)cookie;
+ dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ atomic_inc(&ep->rma_info.fence_refcount);
+ dma_async_issue_pending(chan);
+ return 0;
+}
+
+#define SCIF_LOOPB_MAGIC_MARK 0xdead
+
+int scif_fence_mark(scif_epd_t epd, int flags, int *mark)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ int err = 0;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n",
+ ep, flags, *mark);
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ /* Invalid flags? */
+ if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))
+ return -EINVAL;
+
+ /* At least one of init self or peer RMA should be set */
+ if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
+ return -EINVAL;
+
+ /* Exactly one of init self or peer RMA should be set but not both */
+ if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
+ return -EINVAL;
+
+ /*
+ * Management node loopback does not need to use DMA.
+ * Return a valid mark to be symmetric.
+ */
+ if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
+ *mark = SCIF_LOOPB_MAGIC_MARK;
+ return 0;
+ }
+
+ if (flags & SCIF_FENCE_INIT_SELF)
+ err = _scif_fence_mark(epd, mark);
+ else
+ err = scif_send_fence_mark(ep, mark);
+
+ if (err)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n",
+ ep, flags, *mark, err);
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_fence_mark);
+
+int scif_fence_wait(scif_epd_t epd, int mark)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ int err = 0;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI fence_wait: ep %p mark 0x%x\n",
+ ep, mark);
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+ /*
+ * Management node loopback does not need to use DMA.
+ * The only valid mark provided is 0 so simply
+ * return success if the mark is valid.
+ */
+ if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
+ if (mark == SCIF_LOOPB_MAGIC_MARK)
+ return 0;
+ else
+ return -EINVAL;
+ }
+ if (mark & SCIF_REMOTE_FENCE)
+ err = scif_send_fence_wait(epd, mark);
+ else
+ err = _scif_fence_wait(epd, mark);
+ if (err < 0)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_fence_wait);
+
+int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval,
+ off_t roff, u64 rval, int flags)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ int err = 0;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx rval 0x%llx flags 0x%x\n",
+ ep, loff, lval, roff, rval, flags);
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ /* Invalid flags? */
+ if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER |
+ SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))
+ return -EINVAL;
+
+ /* At least one of init self or peer RMA should be set */
+ if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
+ return -EINVAL;
+
+ /* Exactly one of init self or peer RMA should be set but not both */
+ if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
+ return -EINVAL;
+
+ /* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE required */
+ if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)))
+ return -EINVAL;
+
+ /* Only Dword offsets allowed */
+ if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1)))
+ return -EINVAL;
+
+ /* Only Dword aligned offsets allowed */
+ if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1)))
+ return -EINVAL;
+
+ if (flags & SCIF_FENCE_INIT_PEER) {
+ err = scif_send_fence_signal(epd, roff, rval, loff,
+ lval, flags);
+ } else {
+ /* Local Signal in Local RAS */
+ if (flags & SCIF_SIGNAL_LOCAL) {
+ err = scif_prog_signal(epd, loff, lval,
+ SCIF_WINDOW_SELF);
+ if (err)
+ goto error_ret;
+ }
+
+ /* Signal in Remote RAS */
+ if (flags & SCIF_SIGNAL_REMOTE)
+ err = scif_prog_signal(epd, roff,
+ rval, SCIF_WINDOW_PEER);
+ }
+error_ret:
+ if (err)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_fence_signal);
diff --git a/drivers/misc/mic/scif/scif_main.c b/drivers/misc/mic/scif/scif_main.c
index 6ce851f5c7e6..36d847af1209 100644
--- a/drivers/misc/mic/scif/scif_main.c
+++ b/drivers/misc/mic/scif/scif_main.c
@@ -34,6 +34,7 @@ struct scif_info scif_info = {
};
struct scif_dev *scif_dev;
+struct kmem_cache *unaligned_cache;
static atomic_t g_loopb_cnt;
/* Runs in the context of intr_wq */
@@ -80,35 +81,6 @@ irqreturn_t scif_intr_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static int scif_peer_probe(struct scif_peer_dev *spdev)
-{
- struct scif_dev *scifdev = &scif_dev[spdev->dnode];
-
- mutex_lock(&scif_info.conflock);
- scif_info.total++;
- scif_info.maxid = max_t(u32, spdev->dnode, scif_info.maxid);
- mutex_unlock(&scif_info.conflock);
- rcu_assign_pointer(scifdev->spdev, spdev);
-
- /* In the future SCIF kernel client devices will be added here */
- return 0;
-}
-
-static void scif_peer_remove(struct scif_peer_dev *spdev)
-{
- struct scif_dev *scifdev = &scif_dev[spdev->dnode];
-
- /* In the future SCIF kernel client devices will be removed here */
- spdev = rcu_dereference(scifdev->spdev);
- if (spdev)
- RCU_INIT_POINTER(scifdev->spdev, NULL);
- synchronize_rcu();
-
- mutex_lock(&scif_info.conflock);
- scif_info.total--;
- mutex_unlock(&scif_info.conflock);
-}
-
static void scif_qp_setup_handler(struct work_struct *work)
{
struct scif_dev *scifdev = container_of(work, struct scif_dev,
@@ -139,20 +111,13 @@ static void scif_qp_setup_handler(struct work_struct *work)
}
}
-static int scif_setup_scifdev(struct scif_hw_dev *sdev)
+static int scif_setup_scifdev(void)
{
+ /* We support a maximum of 129 SCIF nodes including the mgmt node */
+#define MAX_SCIF_NODES 129
int i;
- u8 num_nodes;
-
- if (sdev->snode) {
- struct mic_bootparam __iomem *bp = sdev->rdp;
-
- num_nodes = ioread8(&bp->tot_nodes);
- } else {
- struct mic_bootparam *bp = sdev->dp;
+ u8 num_nodes = MAX_SCIF_NODES;
- num_nodes = bp->tot_nodes;
- }
scif_dev = kcalloc(num_nodes, sizeof(*scif_dev), GFP_KERNEL);
if (!scif_dev)
return -ENOMEM;
@@ -163,7 +128,7 @@ static int scif_setup_scifdev(struct scif_hw_dev *sdev)
scifdev->exit = OP_IDLE;
init_waitqueue_head(&scifdev->disconn_wq);
mutex_init(&scifdev->lock);
- INIT_WORK(&scifdev->init_msg_work, scif_qp_response_ack);
+ INIT_WORK(&scifdev->peer_add_work, scif_add_peer_device);
INIT_DELAYED_WORK(&scifdev->p2p_dwork,
scif_poll_qp_state);
INIT_DELAYED_WORK(&scifdev->qp_dwork,
@@ -181,27 +146,21 @@ static void scif_destroy_scifdev(void)
static int scif_probe(struct scif_hw_dev *sdev)
{
- struct scif_dev *scifdev;
+ struct scif_dev *scifdev = &scif_dev[sdev->dnode];
int rc;
dev_set_drvdata(&sdev->dev, sdev);
+ scifdev->sdev = sdev;
+
if (1 == atomic_add_return(1, &g_loopb_cnt)) {
- struct scif_dev *loopb_dev;
+ struct scif_dev *loopb_dev = &scif_dev[sdev->snode];
- rc = scif_setup_scifdev(sdev);
- if (rc)
- goto exit;
- scifdev = &scif_dev[sdev->dnode];
- scifdev->sdev = sdev;
- loopb_dev = &scif_dev[sdev->snode];
loopb_dev->sdev = sdev;
rc = scif_setup_loopback_qp(loopb_dev);
if (rc)
- goto free_sdev;
- } else {
- scifdev = &scif_dev[sdev->dnode];
- scifdev->sdev = sdev;
+ goto exit;
}
+
rc = scif_setup_intr_wq(scifdev);
if (rc)
goto destroy_loopb;
@@ -237,8 +196,6 @@ destroy_intr:
destroy_loopb:
if (atomic_dec_and_test(&g_loopb_cnt))
scif_destroy_loopback_qp(&scif_dev[sdev->snode]);
-free_sdev:
- scif_destroy_scifdev();
exit:
return rc;
}
@@ -290,13 +247,6 @@ static void scif_remove(struct scif_hw_dev *sdev)
scifdev->sdev = NULL;
}
-static struct scif_peer_driver scif_peer_driver = {
- .driver.name = KBUILD_MODNAME,
- .driver.owner = THIS_MODULE,
- .probe = scif_peer_probe,
- .remove = scif_peer_remove,
-};
-
static struct scif_hw_dev_id id_table[] = {
{ MIC_SCIF_DEV, SCIF_DEV_ANY_ID },
{ 0 },
@@ -312,29 +262,54 @@ static struct scif_driver scif_driver = {
static int _scif_init(void)
{
- spin_lock_init(&scif_info.eplock);
+ int rc;
+
+ mutex_init(&scif_info.eplock);
+ spin_lock_init(&scif_info.rmalock);
spin_lock_init(&scif_info.nb_connect_lock);
spin_lock_init(&scif_info.port_lock);
mutex_init(&scif_info.conflock);
mutex_init(&scif_info.connlock);
+ mutex_init(&scif_info.fencelock);
INIT_LIST_HEAD(&scif_info.uaccept);
INIT_LIST_HEAD(&scif_info.listen);
INIT_LIST_HEAD(&scif_info.zombie);
INIT_LIST_HEAD(&scif_info.connected);
INIT_LIST_HEAD(&scif_info.disconnected);
+ INIT_LIST_HEAD(&scif_info.rma);
+ INIT_LIST_HEAD(&scif_info.rma_tc);
+ INIT_LIST_HEAD(&scif_info.mmu_notif_cleanup);
+ INIT_LIST_HEAD(&scif_info.fence);
INIT_LIST_HEAD(&scif_info.nb_connect_list);
init_waitqueue_head(&scif_info.exitwq);
+ scif_info.rma_tc_limit = SCIF_RMA_TEMP_CACHE_LIMIT;
scif_info.en_msg_log = 0;
scif_info.p2p_enable = 1;
+ rc = scif_setup_scifdev();
+ if (rc)
+ goto error;
+ unaligned_cache = kmem_cache_create("Unaligned_DMA",
+ SCIF_KMEM_UNALIGNED_BUF_SIZE,
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!unaligned_cache) {
+ rc = -ENOMEM;
+ goto free_sdev;
+ }
INIT_WORK(&scif_info.misc_work, scif_misc_handler);
+ INIT_WORK(&scif_info.mmu_notif_work, scif_mmu_notif_handler);
INIT_WORK(&scif_info.conn_work, scif_conn_handler);
idr_init(&scif_ports);
return 0;
+free_sdev:
+ scif_destroy_scifdev();
+error:
+ return rc;
}
static void _scif_exit(void)
{
idr_destroy(&scif_ports);
+ kmem_cache_destroy(unaligned_cache);
scif_destroy_scifdev();
}
@@ -344,15 +319,13 @@ static int __init scif_init(void)
int rc;
_scif_init();
+ iova_cache_get();
rc = scif_peer_bus_init();
if (rc)
goto exit;
- rc = scif_peer_register_driver(&scif_peer_driver);
- if (rc)
- goto peer_bus_exit;
rc = scif_register_driver(&scif_driver);
if (rc)
- goto unreg_scif_peer;
+ goto peer_bus_exit;
rc = misc_register(mdev);
if (rc)
goto unreg_scif;
@@ -360,8 +333,6 @@ static int __init scif_init(void)
return 0;
unreg_scif:
scif_unregister_driver(&scif_driver);
-unreg_scif_peer:
- scif_peer_unregister_driver(&scif_peer_driver);
peer_bus_exit:
scif_peer_bus_exit();
exit:
@@ -374,8 +345,8 @@ static void __exit scif_exit(void)
scif_exit_debugfs();
misc_deregister(&scif_info.mdev);
scif_unregister_driver(&scif_driver);
- scif_peer_unregister_driver(&scif_peer_driver);
scif_peer_bus_exit();
+ iova_cache_put();
_scif_exit();
}
diff --git a/drivers/misc/mic/scif/scif_main.h b/drivers/misc/mic/scif/scif_main.h
index 580bc63e1b23..a08f0b600a9e 100644
--- a/drivers/misc/mic/scif/scif_main.h
+++ b/drivers/misc/mic/scif/scif_main.h
@@ -22,15 +22,18 @@
#include <linux/pci.h>
#include <linux/miscdevice.h>
#include <linux/dmaengine.h>
+#include <linux/iova.h>
+#include <linux/anon_inodes.h>
#include <linux/file.h>
+#include <linux/vmalloc.h>
#include <linux/scif.h>
-
#include "../common/mic_dev.h"
#define SCIF_MGMT_NODE 0
#define SCIF_DEFAULT_WATCHDOG_TO 30
#define SCIF_NODE_ACCEPT_TIMEOUT (3 * HZ)
#define SCIF_NODE_ALIVE_TIMEOUT (SCIF_DEFAULT_WATCHDOG_TO * HZ)
+#define SCIF_RMA_TEMP_CACHE_LIMIT 0x20000
/*
* Generic state used for certain node QP message exchanges
@@ -73,13 +76,21 @@ enum scif_msg_state {
* @loopb_work: Used for submitting work to loopb_wq
* @loopb_recv_q: List of messages received on the loopb_wq
* @card_initiated_exit: set when the card has initiated the exit
+ * @rmalock: Synchronize access to RMA operations
+ * @fencelock: Synchronize access to list of remote fences requested.
+ * @rma: List of temporary registered windows to be destroyed.
+ * @rma_tc: List of temporary registered & cached Windows to be destroyed
+ * @fence: List of remote fence requests
+ * @mmu_notif_work: Work for registration caching MMU notifier workqueue
+ * @mmu_notif_cleanup: List of temporary cached windows for reg cache
+ * @rma_tc_limit: RMA temporary cache limit
*/
struct scif_info {
u8 nodeid;
u8 maxid;
u8 total;
u32 nr_zombies;
- spinlock_t eplock;
+ struct mutex eplock;
struct mutex connlock;
spinlock_t nb_connect_lock;
spinlock_t port_lock;
@@ -102,6 +113,14 @@ struct scif_info {
struct work_struct loopb_work;
struct list_head loopb_recv_q;
bool card_initiated_exit;
+ spinlock_t rmalock;
+ struct mutex fencelock;
+ struct list_head rma;
+ struct list_head rma_tc;
+ struct list_head fence;
+ struct work_struct mmu_notif_work;
+ struct list_head mmu_notif_cleanup;
+ unsigned long rma_tc_limit;
};
/*
@@ -139,7 +158,7 @@ struct scif_p2p_info {
* @db: doorbell the peer will trigger to generate an interrupt on self
* @rdb: Doorbell to trigger on the peer to generate an interrupt on the peer
* @cookie: Cookie received while registering the interrupt handler
- * init_msg_work: work scheduled for SCIF_INIT message processing
+ * @peer_add_work: Work for handling device_add for peer devices
* @p2p_dwork: Delayed work to enable polling for P2P state
* @qp_dwork: Delayed work for enabling polling for remote QP information
* @p2p_retry: Number of times to retry polling of P2P state
@@ -152,6 +171,8 @@ struct scif_p2p_info {
* @disconn_rescnt: Keeps track of number of node remove requests sent
* @exit: Status of exit message
* @qp_dma_addr: Queue pair DMA address passed to the peer
+ * @dma_ch_idx: Round robin index for DMA channels
+ * @signal_pool: DMA pool used for scheduling scif_fence_signal DMA's
*/
struct scif_dev {
u8 node;
@@ -165,7 +186,7 @@ struct scif_dev {
int db;
int rdb;
struct mic_irq *cookie;
- struct work_struct init_msg_work;
+ struct work_struct peer_add_work;
struct delayed_work p2p_dwork;
struct delayed_work qp_dwork;
int p2p_retry;
@@ -178,17 +199,25 @@ struct scif_dev {
atomic_t disconn_rescnt;
enum scif_msg_state exit;
dma_addr_t qp_dma_addr;
+ int dma_ch_idx;
+ struct dma_pool *signal_pool;
};
+extern bool scif_reg_cache_enable;
+extern bool scif_ulimit_check;
extern struct scif_info scif_info;
extern struct idr scif_ports;
+extern struct bus_type scif_peer_bus;
extern struct scif_dev *scif_dev;
extern const struct file_operations scif_fops;
+extern const struct file_operations scif_anon_fops;
/* Size of the RB for the Node QP */
#define SCIF_NODE_QP_SIZE 0x10000
#include "scif_nodeqp.h"
+#include "scif_rma.h"
+#include "scif_rma_list.h"
/*
* scifdev_self:
diff --git a/drivers/misc/mic/scif/scif_map.h b/drivers/misc/mic/scif/scif_map.h
index 20e50b4e19b2..3e86360ba5a6 100644
--- a/drivers/misc/mic/scif/scif_map.h
+++ b/drivers/misc/mic/scif/scif_map.h
@@ -80,7 +80,7 @@ scif_unmap_single(dma_addr_t local, struct scif_dev *scifdev,
size_t size)
{
if (!scifdev_self(scifdev)) {
- if (scifdev_is_p2p(scifdev) && local > scifdev->base_addr)
+ if (scifdev_is_p2p(scifdev))
local = local - scifdev->base_addr;
dma_unmap_single(&scifdev->sdev->dev, local,
size, DMA_BIDIRECTIONAL);
@@ -110,4 +110,27 @@ scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev)
sdev->hw_ops->iounmap(sdev, (void __force __iomem *)virt);
}
}
+
+static __always_inline int
+scif_map_page(dma_addr_t *dma_handle, struct page *page,
+ struct scif_dev *scifdev)
+{
+ int err = 0;
+
+ if (scifdev_self(scifdev)) {
+ *dma_handle = page_to_phys(page);
+ } else {
+ struct scif_hw_dev *sdev = scifdev->sdev;
+ *dma_handle = dma_map_page(&sdev->dev,
+ page, 0x0, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&sdev->dev, *dma_handle))
+ err = -ENOMEM;
+ else if (scifdev_is_p2p(scifdev))
+ *dma_handle = *dma_handle + scifdev->base_addr;
+ }
+ if (err)
+ *dma_handle = 0;
+ return err;
+}
#endif /* SCIF_MAP_H */
diff --git a/drivers/misc/mic/scif/scif_mmap.c b/drivers/misc/mic/scif/scif_mmap.c
new file mode 100644
index 000000000000..49cb8f7b4672
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_mmap.c
@@ -0,0 +1,699 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#include "scif_main.h"
+
+/*
+ * struct scif_vma_info - Information about a remote memory mapping
+ * created via scif_mmap(..)
+ * @vma: VM area struct
+ * @list: link to list of active vmas
+ */
+struct scif_vma_info {
+ struct vm_area_struct *vma;
+ struct list_head list;
+};
+
+void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_rma_req req;
+ struct scif_window *window = NULL;
+ struct scif_window *recv_window =
+ (struct scif_window *)msg->payload[0];
+ struct scif_endpt *ep;
+
+ ep = (struct scif_endpt *)recv_window->ep;
+ req.out_window = &window;
+ req.offset = recv_window->offset;
+ req.prot = recv_window->prot;
+ req.nr_bytes = recv_window->nr_pages << PAGE_SHIFT;
+ req.type = SCIF_WINDOW_FULL;
+ req.head = &ep->rma_info.reg_list;
+ msg->payload[0] = ep->remote_ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Does a valid window exist? */
+ if (scif_query_window(&req)) {
+ dev_err(&scifdev->sdev->dev,
+ "%s %d -ENXIO\n", __func__, __LINE__);
+ msg->uop = SCIF_UNREGISTER_ACK;
+ goto error;
+ }
+
+ scif_put_window(window, window->nr_pages);
+
+ if (!window->ref_count) {
+ atomic_inc(&ep->rma_info.tw_refcount);
+ ep->rma_info.async_list_del = 1;
+ list_del_init(&window->list);
+ scif_free_window_offset(ep, window, window->offset);
+ }
+error:
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (window && !window->ref_count)
+ scif_queue_for_cleanup(window, &scif_info.rma);
+}
+
+/*
+ * Remove valid remote memory mappings created via scif_mmap(..) from the
+ * process address space since the remote node is lost
+ */
+static void __scif_zap_mmaps(struct scif_endpt *ep)
+{
+ struct list_head *item;
+ struct scif_vma_info *info;
+ struct vm_area_struct *vma;
+ unsigned long size;
+
+ spin_lock(&ep->lock);
+ list_for_each(item, &ep->rma_info.vma_list) {
+ info = list_entry(item, struct scif_vma_info, list);
+ vma = info->vma;
+ size = vma->vm_end - vma->vm_start;
+ zap_vma_ptes(vma, vma->vm_start, size);
+ dev_dbg(scif_info.mdev.this_device,
+ "%s ep %p zap vma %p size 0x%lx\n",
+ __func__, ep, info->vma, size);
+ }
+ spin_unlock(&ep->lock);
+}
+
+/*
+ * Traverse the list of endpoints for a particular remote node and
+ * zap valid remote memory mappings since the remote node is lost
+ */
+static void _scif_zap_mmaps(int node, struct list_head *head)
+{
+ struct scif_endpt *ep;
+ struct list_head *item;
+
+ mutex_lock(&scif_info.connlock);
+ list_for_each(item, head) {
+ ep = list_entry(item, struct scif_endpt, list);
+ if (ep->remote_dev->node == node)
+ __scif_zap_mmaps(ep);
+ }
+ mutex_unlock(&scif_info.connlock);
+}
+
+/*
+ * Wrapper for removing remote memory mappings for a particular node. This API
+ * is called by peer nodes as part of handling a lost node.
+ */
+void scif_zap_mmaps(int node)
+{
+ _scif_zap_mmaps(node, &scif_info.connected);
+ _scif_zap_mmaps(node, &scif_info.disconnected);
+}
+
+/*
+ * This API is only called while handling a lost node:
+ * a) Remote node is dead.
+ * b) Remote memory mappings have been zapped
+ * So we can traverse the remote_reg_list without any locks. Since
+ * the window has not yet been unregistered we can drop the ref count
+ * and queue it to the cleanup thread.
+ */
+static void __scif_cleanup_rma_for_zombies(struct scif_endpt *ep)
+{
+ struct list_head *pos, *tmp;
+ struct scif_window *window;
+
+ list_for_each_safe(pos, tmp, &ep->rma_info.remote_reg_list) {
+ window = list_entry(pos, struct scif_window, list);
+ if (window->ref_count)
+ scif_put_window(window, window->nr_pages);
+ else
+ dev_err(scif_info.mdev.this_device,
+ "%s %d unexpected\n",
+ __func__, __LINE__);
+ if (!window->ref_count) {
+ atomic_inc(&ep->rma_info.tw_refcount);
+ list_del_init(&window->list);
+ scif_queue_for_cleanup(window, &scif_info.rma);
+ }
+ }
+}
+
+/* Cleanup remote registration lists for zombie endpoints */
+void scif_cleanup_rma_for_zombies(int node)
+{
+ struct scif_endpt *ep;
+ struct list_head *item;
+
+ mutex_lock(&scif_info.eplock);
+ list_for_each(item, &scif_info.zombie) {
+ ep = list_entry(item, struct scif_endpt, list);
+ if (ep->remote_dev && ep->remote_dev->node == node)
+ __scif_cleanup_rma_for_zombies(ep);
+ }
+ mutex_unlock(&scif_info.eplock);
+ flush_work(&scif_info.misc_work);
+}
+
+/* Insert the VMA into the per endpoint VMA list */
+static int scif_insert_vma(struct scif_endpt *ep, struct vm_area_struct *vma)
+{
+ struct scif_vma_info *info;
+ int err = 0;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ err = -ENOMEM;
+ goto done;
+ }
+ info->vma = vma;
+ spin_lock(&ep->lock);
+ list_add_tail(&info->list, &ep->rma_info.vma_list);
+ spin_unlock(&ep->lock);
+done:
+ return err;
+}
+
+/* Delete the VMA from the per endpoint VMA list */
+static void scif_delete_vma(struct scif_endpt *ep, struct vm_area_struct *vma)
+{
+ struct list_head *item;
+ struct scif_vma_info *info;
+
+ spin_lock(&ep->lock);
+ list_for_each(item, &ep->rma_info.vma_list) {
+ info = list_entry(item, struct scif_vma_info, list);
+ if (info->vma == vma) {
+ list_del(&info->list);
+ kfree(info);
+ break;
+ }
+ }
+ spin_unlock(&ep->lock);
+}
+
+static phys_addr_t scif_get_phys(phys_addr_t phys, struct scif_endpt *ep)
+{
+ struct scif_dev *scifdev = (struct scif_dev *)ep->remote_dev;
+ struct scif_hw_dev *sdev = scifdev->sdev;
+ phys_addr_t out_phys, apt_base = 0;
+
+ /*
+ * If the DMA address is card relative then we need to add the
+ * aperture base for mmap to work correctly
+ */
+ if (!scifdev_self(scifdev) && sdev->aper && sdev->card_rel_da)
+ apt_base = sdev->aper->pa;
+ out_phys = apt_base + phys;
+ return out_phys;
+}
+
+int scif_get_pages(scif_epd_t epd, off_t offset, size_t len,
+ struct scif_range **pages)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct scif_rma_req req;
+ struct scif_window *window = NULL;
+ int nr_pages, err, i;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI get_pinned_pages: ep %p offset 0x%lx len 0x%lx\n",
+ ep, offset, len);
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ if (!len || (offset < 0) ||
+ (offset + len < offset) ||
+ (ALIGN(offset, PAGE_SIZE) != offset) ||
+ (ALIGN(len, PAGE_SIZE) != len))
+ return -EINVAL;
+
+ nr_pages = len >> PAGE_SHIFT;
+
+ req.out_window = &window;
+ req.offset = offset;
+ req.prot = 0;
+ req.nr_bytes = len;
+ req.type = SCIF_WINDOW_SINGLE;
+ req.head = &ep->rma_info.remote_reg_list;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Does a valid window exist? */
+ err = scif_query_window(&req);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error;
+ }
+
+ /* Allocate scif_range */
+ *pages = kzalloc(sizeof(**pages), GFP_KERNEL);
+ if (!*pages) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ /* Allocate phys addr array */
+ (*pages)->phys_addr = scif_zalloc(nr_pages * sizeof(dma_addr_t));
+ if (!((*pages)->phys_addr)) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ if (scif_is_mgmt_node() && !scifdev_self(ep->remote_dev)) {
+ /* Allocate virtual address array */
+ ((*pages)->va = scif_zalloc(nr_pages * sizeof(void *)));
+ if (!(*pages)->va) {
+ err = -ENOMEM;
+ goto error;
+ }
+ }
+ /* Populate the values */
+ (*pages)->cookie = window;
+ (*pages)->nr_pages = nr_pages;
+ (*pages)->prot_flags = window->prot;
+
+ for (i = 0; i < nr_pages; i++) {
+ (*pages)->phys_addr[i] =
+ __scif_off_to_dma_addr(window, offset +
+ (i * PAGE_SIZE));
+ (*pages)->phys_addr[i] = scif_get_phys((*pages)->phys_addr[i],
+ ep);
+ if (scif_is_mgmt_node() && !scifdev_self(ep->remote_dev))
+ (*pages)->va[i] =
+ ep->remote_dev->sdev->aper->va +
+ (*pages)->phys_addr[i] -
+ ep->remote_dev->sdev->aper->pa;
+ }
+
+ scif_get_window(window, nr_pages);
+error:
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (err) {
+ if (*pages) {
+ scif_free((*pages)->phys_addr,
+ nr_pages * sizeof(dma_addr_t));
+ scif_free((*pages)->va,
+ nr_pages * sizeof(void *));
+ kfree(*pages);
+ *pages = NULL;
+ }
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_get_pages);
+
+int scif_put_pages(struct scif_range *pages)
+{
+ struct scif_endpt *ep;
+ struct scif_window *window;
+ struct scifmsg msg;
+
+ if (!pages || !pages->cookie)
+ return -EINVAL;
+
+ window = pages->cookie;
+
+ if (!window || window->magic != SCIFEP_MAGIC)
+ return -EINVAL;
+
+ ep = (struct scif_endpt *)window->ep;
+ /*
+ * If the state is SCIFEP_CONNECTED or SCIFEP_DISCONNECTED then the
+ * callee should be allowed to release references to the pages,
+ * else the endpoint was not connected in the first place,
+ * hence the ENOTCONN.
+ */
+ if (ep->state != SCIFEP_CONNECTED && ep->state != SCIFEP_DISCONNECTED)
+ return -ENOTCONN;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+
+ scif_put_window(window, pages->nr_pages);
+
+ /* Initiate window destruction if ref count is zero */
+ if (!window->ref_count) {
+ list_del(&window->list);
+ mutex_unlock(&ep->rma_info.rma_lock);
+ scif_drain_dma_intr(ep->remote_dev->sdev,
+ ep->rma_info.dma_chan);
+ /* Inform the peer about this window being destroyed. */
+ msg.uop = SCIF_MUNMAP;
+ msg.src = ep->port;
+ msg.payload[0] = window->peer_window;
+ /* No error handling for notification messages */
+ scif_nodeqp_send(ep->remote_dev, &msg);
+ /* Destroy this window from the peer's registered AS */
+ scif_destroy_remote_window(window);
+ } else {
+ mutex_unlock(&ep->rma_info.rma_lock);
+ }
+
+ scif_free(pages->phys_addr, pages->nr_pages * sizeof(dma_addr_t));
+ scif_free(pages->va, pages->nr_pages * sizeof(void *));
+ kfree(pages);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scif_put_pages);
+
+/*
+ * scif_rma_list_mmap:
+ *
+ * Traverse the remote registration list starting from start_window:
+ * 1) Create VtoP mappings via remap_pfn_range(..)
+ * 2) Once step 1) and 2) complete successfully then traverse the range of
+ * windows again and bump the reference count.
+ * RMA lock must be held.
+ */
+static int scif_rma_list_mmap(struct scif_window *start_window, s64 offset,
+ int nr_pages, struct vm_area_struct *vma)
+{
+ s64 end_offset, loop_offset = offset;
+ struct scif_window *window = start_window;
+ int loop_nr_pages, nr_pages_left = nr_pages;
+ struct scif_endpt *ep = (struct scif_endpt *)start_window->ep;
+ struct list_head *head = &ep->rma_info.remote_reg_list;
+ int i, err = 0;
+ dma_addr_t phys_addr;
+ struct scif_window_iter src_win_iter;
+ size_t contig_bytes = 0;
+
+ might_sleep();
+ list_for_each_entry_from(window, head, list) {
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ loop_nr_pages = min_t(int,
+ (end_offset - loop_offset) >> PAGE_SHIFT,
+ nr_pages_left);
+ scif_init_window_iter(window, &src_win_iter);
+ for (i = 0; i < loop_nr_pages; i++) {
+ phys_addr = scif_off_to_dma_addr(window, loop_offset,
+ &contig_bytes,
+ &src_win_iter);
+ phys_addr = scif_get_phys(phys_addr, ep);
+ err = remap_pfn_range(vma,
+ vma->vm_start +
+ loop_offset - offset,
+ phys_addr >> PAGE_SHIFT,
+ PAGE_SIZE,
+ vma->vm_page_prot);
+ if (err)
+ goto error;
+ loop_offset += PAGE_SIZE;
+ }
+ nr_pages_left -= loop_nr_pages;
+ if (!nr_pages_left)
+ break;
+ }
+ /*
+ * No more failures expected. Bump up the ref count for all
+ * the windows. Another traversal from start_window required
+ * for handling errors encountered across windows during
+ * remap_pfn_range(..).
+ */
+ loop_offset = offset;
+ nr_pages_left = nr_pages;
+ window = start_window;
+ head = &ep->rma_info.remote_reg_list;
+ list_for_each_entry_from(window, head, list) {
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ loop_nr_pages = min_t(int,
+ (end_offset - loop_offset) >> PAGE_SHIFT,
+ nr_pages_left);
+ scif_get_window(window, loop_nr_pages);
+ nr_pages_left -= loop_nr_pages;
+ loop_offset += (loop_nr_pages << PAGE_SHIFT);
+ if (!nr_pages_left)
+ break;
+ }
+error:
+ if (err)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ return err;
+}
+
+/*
+ * scif_rma_list_munmap:
+ *
+ * Traverse the remote registration list starting from window:
+ * 1) Decrement ref count.
+ * 2) If the ref count drops to zero then send a SCIF_MUNMAP message to peer.
+ * RMA lock must be held.
+ */
+static void scif_rma_list_munmap(struct scif_window *start_window,
+ s64 offset, int nr_pages)
+{
+ struct scifmsg msg;
+ s64 loop_offset = offset, end_offset;
+ int loop_nr_pages, nr_pages_left = nr_pages;
+ struct scif_endpt *ep = (struct scif_endpt *)start_window->ep;
+ struct list_head *head = &ep->rma_info.remote_reg_list;
+ struct scif_window *window = start_window, *_window;
+
+ msg.uop = SCIF_MUNMAP;
+ msg.src = ep->port;
+ loop_offset = offset;
+ nr_pages_left = nr_pages;
+ list_for_each_entry_safe_from(window, _window, head, list) {
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ loop_nr_pages = min_t(int,
+ (end_offset - loop_offset) >> PAGE_SHIFT,
+ nr_pages_left);
+ scif_put_window(window, loop_nr_pages);
+ if (!window->ref_count) {
+ struct scif_dev *rdev = ep->remote_dev;
+
+ scif_drain_dma_intr(rdev->sdev,
+ ep->rma_info.dma_chan);
+ /* Inform the peer about this munmap */
+ msg.payload[0] = window->peer_window;
+ /* No error handling for Notification messages. */
+ scif_nodeqp_send(ep->remote_dev, &msg);
+ list_del(&window->list);
+ /* Destroy this window from the peer's registered AS */
+ scif_destroy_remote_window(window);
+ }
+ nr_pages_left -= loop_nr_pages;
+ loop_offset += (loop_nr_pages << PAGE_SHIFT);
+ if (!nr_pages_left)
+ break;
+ }
+}
+
+/*
+ * The private data field of each VMA used to mmap a remote window
+ * points to an instance of struct vma_pvt
+ */
+struct vma_pvt {
+ struct scif_endpt *ep; /* End point for remote window */
+ s64 offset; /* offset within remote window */
+ bool valid_offset; /* offset is valid only if the original
+ * mmap request was for a single page
+ * else the offset within the vma is
+ * the correct offset
+ */
+ struct kref ref;
+};
+
+static void vma_pvt_release(struct kref *ref)
+{
+ struct vma_pvt *vmapvt = container_of(ref, struct vma_pvt, ref);
+
+ kfree(vmapvt);
+}
+
+/**
+ * scif_vma_open - VMA open driver callback
+ * @vma: VMM memory area.
+ * The open method is called by the kernel to allow the subsystem implementing
+ * the VMA to initialize the area. This method is invoked any time a new
+ * reference to the VMA is made (when a process forks, for example).
+ * The one exception happens when the VMA is first created by mmap;
+ * in this case, the driver's mmap method is called instead.
+ * This function is also invoked when an existing VMA is split by the kernel
+ * due to a call to munmap on a subset of the VMA resulting in two VMAs.
+ * The kernel invokes this function only on one of the two VMAs.
+ */
+static void scif_vma_open(struct vm_area_struct *vma)
+{
+ struct vma_pvt *vmapvt = vma->vm_private_data;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI vma open: vma_start 0x%lx vma_end 0x%lx\n",
+ vma->vm_start, vma->vm_end);
+ scif_insert_vma(vmapvt->ep, vma);
+ kref_get(&vmapvt->ref);
+}
+
+/**
+ * scif_munmap - VMA close driver callback.
+ * @vma: VMM memory area.
+ * When an area is destroyed, the kernel calls its close operation.
+ * Note that there's no usage count associated with VMA's; the area
+ * is opened and closed exactly once by each process that uses it.
+ */
+static void scif_munmap(struct vm_area_struct *vma)
+{
+ struct scif_endpt *ep;
+ struct vma_pvt *vmapvt = vma->vm_private_data;
+ int nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ s64 offset;
+ struct scif_rma_req req;
+ struct scif_window *window = NULL;
+ int err;
+
+ might_sleep();
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI munmap: vma_start 0x%lx vma_end 0x%lx\n",
+ vma->vm_start, vma->vm_end);
+ ep = vmapvt->ep;
+ offset = vmapvt->valid_offset ? vmapvt->offset :
+ (vma->vm_pgoff) << PAGE_SHIFT;
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI munmap: ep %p nr_pages 0x%x offset 0x%llx\n",
+ ep, nr_pages, offset);
+ req.out_window = &window;
+ req.offset = offset;
+ req.nr_bytes = vma->vm_end - vma->vm_start;
+ req.prot = vma->vm_flags & (VM_READ | VM_WRITE);
+ req.type = SCIF_WINDOW_PARTIAL;
+ req.head = &ep->rma_info.remote_reg_list;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+
+ err = scif_query_window(&req);
+ if (err)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ else
+ scif_rma_list_munmap(window, offset, nr_pages);
+
+ mutex_unlock(&ep->rma_info.rma_lock);
+ /*
+ * The kernel probably zeroes these out but we still want
+ * to clean up our own mess just in case.
+ */
+ vma->vm_ops = NULL;
+ vma->vm_private_data = NULL;
+ kref_put(&vmapvt->ref, vma_pvt_release);
+ scif_delete_vma(ep, vma);
+}
+
+static const struct vm_operations_struct scif_vm_ops = {
+ .open = scif_vma_open,
+ .close = scif_munmap,
+};
+
+/**
+ * scif_mmap - Map pages in virtual address space to a remote window.
+ * @vma: VMM memory area.
+ * @epd: endpoint descriptor
+ *
+ * Return: Upon successful completion, scif_mmap() returns zero
+ * else an apt error is returned as documented in scif.h
+ */
+int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd)
+{
+ struct scif_rma_req req;
+ struct scif_window *window = NULL;
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ s64 start_offset = vma->vm_pgoff << PAGE_SHIFT;
+ int nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ int err;
+ struct vma_pvt *vmapvt;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI mmap: ep %p start_offset 0x%llx nr_pages 0x%x\n",
+ ep, start_offset, nr_pages);
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ might_sleep();
+
+ err = scif_insert_vma(ep, vma);
+ if (err)
+ return err;
+
+ vmapvt = kzalloc(sizeof(*vmapvt), GFP_KERNEL);
+ if (!vmapvt) {
+ scif_delete_vma(ep, vma);
+ return -ENOMEM;
+ }
+
+ vmapvt->ep = ep;
+ kref_init(&vmapvt->ref);
+
+ req.out_window = &window;
+ req.offset = start_offset;
+ req.nr_bytes = vma->vm_end - vma->vm_start;
+ req.prot = vma->vm_flags & (VM_READ | VM_WRITE);
+ req.type = SCIF_WINDOW_PARTIAL;
+ req.head = &ep->rma_info.remote_reg_list;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Does a valid window exist? */
+ err = scif_query_window(&req);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error_unlock;
+ }
+
+ /* Default prot for loopback */
+ if (!scifdev_self(ep->remote_dev))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ /*
+ * VM_DONTCOPY - Do not copy this vma on fork
+ * VM_DONTEXPAND - Cannot expand with mremap()
+ * VM_RESERVED - Count as reserved_vm like IO
+ * VM_PFNMAP - Page-ranges managed without "struct page"
+ * VM_IO - Memory mapped I/O or similar
+ *
+ * We do not want to copy this VMA automatically on a fork(),
+ * expand this VMA due to mremap() or swap out these pages since
+ * the VMA is actually backed by physical pages in the remote
+ * node's physical memory and not via a struct page.
+ */
+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP;
+
+ if (!scifdev_self(ep->remote_dev))
+ vma->vm_flags |= VM_IO | VM_PFNMAP;
+
+ /* Map this range of windows */
+ err = scif_rma_list_mmap(window, start_offset, nr_pages, vma);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error_unlock;
+ }
+ /* Set up the driver call back */
+ vma->vm_ops = &scif_vm_ops;
+ vma->vm_private_data = vmapvt;
+error_unlock:
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (err) {
+ kfree(vmapvt);
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ scif_delete_vma(ep, vma);
+ }
+ return err;
+}
diff --git a/drivers/misc/mic/scif/scif_nm.c b/drivers/misc/mic/scif/scif_nm.c
index 9b4c5382d6a7..79f26a02a1cb 100644
--- a/drivers/misc/mic/scif/scif_nm.c
+++ b/drivers/misc/mic/scif/scif_nm.c
@@ -34,6 +34,7 @@ static void scif_invalidate_ep(int node)
list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
ep = list_entry(pos, struct scif_endpt, list);
if (ep->remote_dev->node == node) {
+ scif_unmap_all_windows(ep);
spin_lock(&ep->lock);
scif_cleanup_ep_qp(ep);
spin_unlock(&ep->lock);
@@ -50,6 +51,7 @@ static void scif_invalidate_ep(int node)
wake_up_interruptible(&ep->sendwq);
wake_up_interruptible(&ep->recvwq);
spin_unlock(&ep->lock);
+ scif_unmap_all_windows(ep);
}
}
mutex_unlock(&scif_info.connlock);
@@ -61,8 +63,8 @@ void scif_free_qp(struct scif_dev *scifdev)
if (!qp)
return;
- scif_free_coherent((void *)qp->inbound_q.rb_base,
- qp->local_buf, scifdev, qp->inbound_q.size);
+ scif_unmap_single(qp->local_buf, scifdev, qp->inbound_q.size);
+ kfree(qp->inbound_q.rb_base);
scif_unmap_single(qp->local_qp, scifdev, sizeof(struct scif_qp));
kfree(scifdev->qpairs);
scifdev->qpairs = NULL;
@@ -125,8 +127,12 @@ void scif_cleanup_scifdev(struct scif_dev *dev)
}
scif_destroy_intr_wq(dev);
}
+ flush_work(&scif_info.misc_work);
scif_destroy_p2p(dev);
scif_invalidate_ep(dev->node);
+ scif_zap_mmaps(dev->node);
+ scif_cleanup_rma_for_zombies(dev->node);
+ flush_work(&scif_info.misc_work);
scif_send_acks(dev);
if (!dev->node && scif_info.card_initiated_exit) {
/*
@@ -147,14 +153,8 @@ void scif_cleanup_scifdev(struct scif_dev *dev)
void scif_handle_remove_node(int node)
{
struct scif_dev *scifdev = &scif_dev[node];
- struct scif_peer_dev *spdev;
-
- rcu_read_lock();
- spdev = rcu_dereference(scifdev->spdev);
- rcu_read_unlock();
- if (spdev)
- scif_peer_unregister_device(spdev);
- else
+
+ if (scif_peer_unregister_device(scifdev))
scif_send_acks(scifdev);
}
diff --git a/drivers/misc/mic/scif/scif_nodeqp.c b/drivers/misc/mic/scif/scif_nodeqp.c
index 6dfdae3452d6..c66ca1a5814e 100644
--- a/drivers/misc/mic/scif/scif_nodeqp.c
+++ b/drivers/misc/mic/scif/scif_nodeqp.c
@@ -105,18 +105,22 @@
int scif_setup_qp_connect(struct scif_qp *qp, dma_addr_t *qp_offset,
int local_size, struct scif_dev *scifdev)
{
- void *local_q = NULL;
+ void *local_q = qp->inbound_q.rb_base;
int err = 0;
u32 tmp_rd = 0;
spin_lock_init(&qp->send_lock);
spin_lock_init(&qp->recv_lock);
- local_q = kzalloc(local_size, GFP_KERNEL);
+ /* Allocate rb only if not already allocated */
if (!local_q) {
- err = -ENOMEM;
- return err;
+ local_q = kzalloc(local_size, GFP_KERNEL);
+ if (!local_q) {
+ err = -ENOMEM;
+ return err;
+ }
}
+
err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
if (err)
goto kfree;
@@ -260,6 +264,11 @@ int scif_setup_qp_connect_response(struct scif_dev *scifdev,
r_buf,
get_count_order(remote_size));
/*
+ * Because the node QP may already be processing an INIT message, set
+ * the read pointer so the cached read offset isn't lost
+ */
+ qp->remote_qp->local_read = qp->inbound_q.current_read_offset;
+ /*
* resetup the inbound_q now that we know where the
* inbound_read really is.
*/
@@ -426,6 +435,21 @@ free_p2p:
return NULL;
}
+/* Uninitialize and release resources from a p2p mapping */
+static void scif_deinit_p2p_info(struct scif_dev *scifdev,
+ struct scif_p2p_info *p2p)
+{
+ struct scif_hw_dev *sdev = scifdev->sdev;
+
+ dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
+ p2p->sg_nentries[SCIF_PPI_MMIO], DMA_BIDIRECTIONAL);
+ dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
+ p2p->sg_nentries[SCIF_PPI_APER], DMA_BIDIRECTIONAL);
+ scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
+ scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
+ kfree(p2p);
+}
+
/**
* scif_node_connect: Respond to SCIF_NODE_CONNECT interrupt message
* @dst: Destination node
@@ -468,8 +492,10 @@ static void scif_node_connect(struct scif_dev *scifdev, int dst)
if (!p2p_ij)
return;
p2p_ji = scif_init_p2p_info(dev_j, dev_i);
- if (!p2p_ji)
+ if (!p2p_ji) {
+ scif_deinit_p2p_info(dev_i, p2p_ij);
return;
+ }
list_add_tail(&p2p_ij->ppi_list, &dev_i->p2p);
list_add_tail(&p2p_ji->ppi_list, &dev_j->p2p);
@@ -529,27 +555,6 @@ static void scif_p2p_setup(void)
}
}
-void scif_qp_response_ack(struct work_struct *work)
-{
- struct scif_dev *scifdev = container_of(work, struct scif_dev,
- init_msg_work);
- struct scif_peer_dev *spdev;
-
- /* Drop the INIT message if it has already been received */
- if (_scifdev_alive(scifdev))
- return;
-
- spdev = scif_peer_register_device(scifdev);
- if (IS_ERR(spdev))
- return;
-
- if (scif_is_mgmt_node()) {
- mutex_lock(&scif_info.conflock);
- scif_p2p_setup();
- mutex_unlock(&scif_info.conflock);
- }
-}
-
static char *message_types[] = {"BAD",
"INIT",
"EXIT",
@@ -568,7 +573,29 @@ static char *message_types[] = {"BAD",
"DISCNT_ACK",
"CLIENT_SENT",
"CLIENT_RCVD",
- "SCIF_GET_NODE_INFO"};
+ "SCIF_GET_NODE_INFO",
+ "REGISTER",
+ "REGISTER_ACK",
+ "REGISTER_NACK",
+ "UNREGISTER",
+ "UNREGISTER_ACK",
+ "UNREGISTER_NACK",
+ "ALLOC_REQ",
+ "ALLOC_GNT",
+ "ALLOC_REJ",
+ "FREE_PHYS",
+ "FREE_VIRT",
+ "MUNMAP",
+ "MARK",
+ "MARK_ACK",
+ "MARK_NACK",
+ "WAIT",
+ "WAIT_ACK",
+ "WAIT_NACK",
+ "SIGNAL_LOCAL",
+ "SIGNAL_REMOTE",
+ "SIG_ACK",
+ "SIG_NACK"};
static void
scif_display_message(struct scif_dev *scifdev, struct scifmsg *msg,
@@ -662,10 +689,16 @@ int scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
*
* Work queue handler for servicing miscellaneous SCIF tasks.
* Examples include:
- * 1) Cleanup of zombie endpoints.
+ * 1) Remote fence requests.
+ * 2) Destruction of temporary registered windows
+ * created during scif_vreadfrom()/scif_vwriteto().
+ * 3) Cleanup of zombie endpoints.
*/
void scif_misc_handler(struct work_struct *work)
{
+ scif_rma_handle_remote_fences();
+ scif_rma_destroy_windows();
+ scif_rma_destroy_tcw_invalid();
scif_cleanup_zombie_epd();
}
@@ -682,13 +715,14 @@ scif_init(struct scif_dev *scifdev, struct scifmsg *msg)
* address to complete initializing the inbound_q.
*/
flush_delayed_work(&scifdev->qp_dwork);
- /*
- * Delegate the peer device registration to a workqueue, otherwise if
- * SCIF client probe (called during peer device registration) calls
- * scif_connect(..), it will block the message processing thread causing
- * a deadlock.
- */
- schedule_work(&scifdev->init_msg_work);
+
+ scif_peer_register_device(scifdev);
+
+ if (scif_is_mgmt_node()) {
+ mutex_lock(&scif_info.conflock);
+ scif_p2p_setup();
+ mutex_unlock(&scif_info.conflock);
+ }
}
/**
@@ -838,13 +872,13 @@ void scif_poll_qp_state(struct work_struct *work)
msecs_to_jiffies(SCIF_NODE_QP_TIMEOUT));
return;
}
- scif_peer_register_device(peerdev);
return;
timeout:
dev_err(&peerdev->sdev->dev,
"%s %d remote node %d offline, state = 0x%x\n",
__func__, __LINE__, peerdev->node, qp->qp_state);
qp->remote_qp->qp_state = SCIF_QP_OFFLINE;
+ scif_peer_unregister_device(peerdev);
scif_cleanup_scifdev(peerdev);
}
@@ -894,6 +928,9 @@ scif_node_add_ack(struct scif_dev *scifdev, struct scifmsg *msg)
goto local_error;
peerdev->rdb = msg->payload[2];
qp->remote_qp->qp_state = SCIF_QP_ONLINE;
+
+ scif_peer_register_device(peerdev);
+
schedule_delayed_work(&peerdev->p2p_dwork, 0);
return;
local_error:
@@ -1007,6 +1044,27 @@ static void (*scif_intr_func[SCIF_MAX_MSG + 1])
scif_clientsend, /* SCIF_CLIENT_SENT */
scif_clientrcvd, /* SCIF_CLIENT_RCVD */
scif_get_node_info_resp,/* SCIF_GET_NODE_INFO */
+ scif_recv_reg, /* SCIF_REGISTER */
+ scif_recv_reg_ack, /* SCIF_REGISTER_ACK */
+ scif_recv_reg_nack, /* SCIF_REGISTER_NACK */
+ scif_recv_unreg, /* SCIF_UNREGISTER */
+ scif_recv_unreg_ack, /* SCIF_UNREGISTER_ACK */
+ scif_recv_unreg_nack, /* SCIF_UNREGISTER_NACK */
+ scif_alloc_req, /* SCIF_ALLOC_REQ */
+ scif_alloc_gnt_rej, /* SCIF_ALLOC_GNT */
+ scif_alloc_gnt_rej, /* SCIF_ALLOC_REJ */
+ scif_free_virt, /* SCIF_FREE_VIRT */
+ scif_recv_munmap, /* SCIF_MUNMAP */
+ scif_recv_mark, /* SCIF_MARK */
+ scif_recv_mark_resp, /* SCIF_MARK_ACK */
+ scif_recv_mark_resp, /* SCIF_MARK_NACK */
+ scif_recv_wait, /* SCIF_WAIT */
+ scif_recv_wait_resp, /* SCIF_WAIT_ACK */
+ scif_recv_wait_resp, /* SCIF_WAIT_NACK */
+ scif_recv_sig_local, /* SCIF_SIG_LOCAL */
+ scif_recv_sig_remote, /* SCIF_SIG_REMOTE */
+ scif_recv_sig_resp, /* SCIF_SIG_ACK */
+ scif_recv_sig_resp, /* SCIF_SIG_NACK */
};
/**
@@ -1169,7 +1227,6 @@ int scif_setup_loopback_qp(struct scif_dev *scifdev)
int err = 0;
void *local_q;
struct scif_qp *qp;
- struct scif_peer_dev *spdev;
err = scif_setup_intr_wq(scifdev);
if (err)
@@ -1216,15 +1273,11 @@ int scif_setup_loopback_qp(struct scif_dev *scifdev)
&qp->local_write,
local_q, get_count_order(SCIF_NODE_QP_SIZE));
scif_info.nodeid = scifdev->node;
- spdev = scif_peer_register_device(scifdev);
- if (IS_ERR(spdev)) {
- err = PTR_ERR(spdev);
- goto free_local_q;
- }
+
+ scif_peer_register_device(scifdev);
+
scif_info.loopb_dev = scifdev;
return err;
-free_local_q:
- kfree(local_q);
free_qpairs:
kfree(scifdev->qpairs);
destroy_loopb_wq:
@@ -1243,13 +1296,7 @@ exit:
*/
int scif_destroy_loopback_qp(struct scif_dev *scifdev)
{
- struct scif_peer_dev *spdev;
-
- rcu_read_lock();
- spdev = rcu_dereference(scifdev->spdev);
- rcu_read_unlock();
- if (spdev)
- scif_peer_unregister_device(spdev);
+ scif_peer_unregister_device(scifdev);
destroy_workqueue(scif_info.loopb_wq);
scif_destroy_intr_wq(scifdev);
kfree(scifdev->qpairs->outbound_q.rb_base);
diff --git a/drivers/misc/mic/scif/scif_nodeqp.h b/drivers/misc/mic/scif/scif_nodeqp.h
index 6c0ed6783479..95896273138e 100644
--- a/drivers/misc/mic/scif/scif_nodeqp.h
+++ b/drivers/misc/mic/scif/scif_nodeqp.h
@@ -74,7 +74,28 @@
#define SCIF_CLIENT_SENT 16 /* Notify the peer that data has been written */
#define SCIF_CLIENT_RCVD 17 /* Notify the peer that data has been read */
#define SCIF_GET_NODE_INFO 18 /* Get current node mask from the mgmt node*/
-#define SCIF_MAX_MSG SCIF_GET_NODE_INFO
+#define SCIF_REGISTER 19 /* Tell peer about a new registered window */
+#define SCIF_REGISTER_ACK 20 /* Notify peer about unregistration success */
+#define SCIF_REGISTER_NACK 21 /* Notify peer about registration success */
+#define SCIF_UNREGISTER 22 /* Tell peer about unregistering a window */
+#define SCIF_UNREGISTER_ACK 23 /* Notify peer about registration failure */
+#define SCIF_UNREGISTER_NACK 24 /* Notify peer about unregistration failure */
+#define SCIF_ALLOC_REQ 25 /* Request a mapped buffer */
+#define SCIF_ALLOC_GNT 26 /* Notify peer about allocation success */
+#define SCIF_ALLOC_REJ 27 /* Notify peer about allocation failure */
+#define SCIF_FREE_VIRT 28 /* Free previously allocated virtual memory */
+#define SCIF_MUNMAP 29 /* Acknowledgment for a SCIF_MMAP request */
+#define SCIF_MARK 30 /* SCIF Remote Fence Mark Request */
+#define SCIF_MARK_ACK 31 /* SCIF Remote Fence Mark Success */
+#define SCIF_MARK_NACK 32 /* SCIF Remote Fence Mark Failure */
+#define SCIF_WAIT 33 /* SCIF Remote Fence Wait Request */
+#define SCIF_WAIT_ACK 34 /* SCIF Remote Fence Wait Success */
+#define SCIF_WAIT_NACK 35 /* SCIF Remote Fence Wait Failure */
+#define SCIF_SIG_LOCAL 36 /* SCIF Remote Fence Local Signal Request */
+#define SCIF_SIG_REMOTE 37 /* SCIF Remote Fence Remote Signal Request */
+#define SCIF_SIG_ACK 38 /* SCIF Remote Fence Remote Signal Success */
+#define SCIF_SIG_NACK 39 /* SCIF Remote Fence Remote Signal Failure */
+#define SCIF_MAX_MSG SCIF_SIG_NACK
/*
* struct scifmsg - Node QP message format
@@ -92,6 +113,24 @@ struct scifmsg {
} __packed;
/*
+ * struct scif_allocmsg - Used with SCIF_ALLOC_REQ to request
+ * the remote note to allocate memory
+ *
+ * phys_addr: Physical address of the buffer
+ * vaddr: Virtual address of the buffer
+ * size: Size of the buffer
+ * state: Current state
+ * allocwq: wait queue for status
+ */
+struct scif_allocmsg {
+ dma_addr_t phys_addr;
+ unsigned long vaddr;
+ size_t size;
+ enum scif_msg_state state;
+ wait_queue_head_t allocwq;
+};
+
+/*
* struct scif_qp - Node Queue Pair
*
* Interesting structure -- a little difficult because we can only
@@ -158,7 +197,6 @@ int scif_setup_qp_connect_response(struct scif_dev *scifdev,
int scif_setup_loopback_qp(struct scif_dev *scifdev);
int scif_destroy_loopback_qp(struct scif_dev *scifdev);
void scif_poll_qp_state(struct work_struct *work);
-void scif_qp_response_ack(struct work_struct *work);
void scif_destroy_p2p(struct scif_dev *scifdev);
void scif_send_exit(struct scif_dev *scifdev);
static inline struct device *scif_get_peer_dev(struct scif_dev *scifdev)
diff --git a/drivers/misc/mic/scif/scif_peer_bus.c b/drivers/misc/mic/scif/scif_peer_bus.c
index 589ae9ad2501..6ffa3bdbd45b 100644
--- a/drivers/misc/mic/scif/scif_peer_bus.c
+++ b/drivers/misc/mic/scif/scif_peer_bus.c
@@ -24,93 +24,152 @@ dev_to_scif_peer(struct device *dev)
return container_of(dev, struct scif_peer_dev, dev);
}
-static inline struct scif_peer_driver *
-drv_to_scif_peer(struct device_driver *drv)
-{
- return container_of(drv, struct scif_peer_driver, driver);
-}
+struct bus_type scif_peer_bus = {
+ .name = "scif_peer_bus",
+};
-static int scif_peer_dev_match(struct device *dv, struct device_driver *dr)
+static void scif_peer_release_dev(struct device *d)
{
- return !strncmp(dev_name(dv), dr->name, 4);
+ struct scif_peer_dev *sdev = dev_to_scif_peer(d);
+ struct scif_dev *scifdev = &scif_dev[sdev->dnode];
+
+ scif_cleanup_scifdev(scifdev);
+ kfree(sdev);
}
-static int scif_peer_dev_probe(struct device *d)
+static int scif_peer_initialize_device(struct scif_dev *scifdev)
{
- struct scif_peer_dev *dev = dev_to_scif_peer(d);
- struct scif_peer_driver *drv = drv_to_scif_peer(dev->dev.driver);
+ struct scif_peer_dev *spdev;
+ int ret;
- return drv->probe(dev);
-}
+ spdev = kzalloc(sizeof(*spdev), GFP_KERNEL);
+ if (!spdev) {
+ ret = -ENOMEM;
+ goto err;
+ }
-static int scif_peer_dev_remove(struct device *d)
-{
- struct scif_peer_dev *dev = dev_to_scif_peer(d);
- struct scif_peer_driver *drv = drv_to_scif_peer(dev->dev.driver);
+ spdev->dev.parent = scifdev->sdev->dev.parent;
+ spdev->dev.release = scif_peer_release_dev;
+ spdev->dnode = scifdev->node;
+ spdev->dev.bus = &scif_peer_bus;
+ dev_set_name(&spdev->dev, "scif_peer-dev%u", spdev->dnode);
+
+ device_initialize(&spdev->dev);
+ get_device(&spdev->dev);
+ rcu_assign_pointer(scifdev->spdev, spdev);
- drv->remove(dev);
+ mutex_lock(&scif_info.conflock);
+ scif_info.total++;
+ scif_info.maxid = max_t(u32, spdev->dnode, scif_info.maxid);
+ mutex_unlock(&scif_info.conflock);
return 0;
+err:
+ dev_err(&scifdev->sdev->dev,
+ "dnode %d: initialize_device rc %d\n", scifdev->node, ret);
+ return ret;
}
-static struct bus_type scif_peer_bus = {
- .name = "scif_peer_bus",
- .match = scif_peer_dev_match,
- .probe = scif_peer_dev_probe,
- .remove = scif_peer_dev_remove,
-};
-
-int scif_peer_register_driver(struct scif_peer_driver *driver)
+static int scif_peer_add_device(struct scif_dev *scifdev)
{
- driver->driver.bus = &scif_peer_bus;
- return driver_register(&driver->driver);
+ struct scif_peer_dev *spdev = rcu_dereference(scifdev->spdev);
+ char pool_name[16];
+ int ret;
+
+ ret = device_add(&spdev->dev);
+ put_device(&spdev->dev);
+ if (ret) {
+ dev_err(&scifdev->sdev->dev,
+ "dnode %d: peer device_add failed\n", scifdev->node);
+ goto put_spdev;
+ }
+
+ scnprintf(pool_name, sizeof(pool_name), "scif-%d", spdev->dnode);
+ scifdev->signal_pool = dmam_pool_create(pool_name, &scifdev->sdev->dev,
+ sizeof(struct scif_status), 1,
+ 0);
+ if (!scifdev->signal_pool) {
+ dev_err(&scifdev->sdev->dev,
+ "dnode %d: dmam_pool_create failed\n", scifdev->node);
+ ret = -ENOMEM;
+ goto del_spdev;
+ }
+ dev_dbg(&spdev->dev, "Added peer dnode %d\n", spdev->dnode);
+ return 0;
+del_spdev:
+ device_del(&spdev->dev);
+put_spdev:
+ RCU_INIT_POINTER(scifdev->spdev, NULL);
+ synchronize_rcu();
+ put_device(&spdev->dev);
+
+ mutex_lock(&scif_info.conflock);
+ scif_info.total--;
+ mutex_unlock(&scif_info.conflock);
+ return ret;
}
-void scif_peer_unregister_driver(struct scif_peer_driver *driver)
+void scif_add_peer_device(struct work_struct *work)
{
- driver_unregister(&driver->driver);
+ struct scif_dev *scifdev = container_of(work, struct scif_dev,
+ peer_add_work);
+
+ scif_peer_add_device(scifdev);
}
-static void scif_peer_release_dev(struct device *d)
+/*
+ * Peer device registration is split into a device_initialize and a device_add.
+ * The reason for doing this is as follows: First, peer device registration
+ * itself cannot be done in the message processing thread and must be delegated
+ * to another workqueue, otherwise if SCIF client probe, called during peer
+ * device registration, calls scif_connect(..), it will block the message
+ * processing thread causing a deadlock. Next, device_initialize is done in the
+ * "top-half" message processing thread and device_add in the "bottom-half"
+ * workqueue. If this is not done, SCIF_CNCT_REQ message processing executing
+ * concurrently with SCIF_INIT message processing is unable to get a reference
+ * on the peer device, thereby failing the connect request.
+ */
+void scif_peer_register_device(struct scif_dev *scifdev)
{
- struct scif_peer_dev *sdev = dev_to_scif_peer(d);
- struct scif_dev *scifdev = &scif_dev[sdev->dnode];
+ int ret;
- scif_cleanup_scifdev(scifdev);
- kfree(sdev);
+ mutex_lock(&scifdev->lock);
+ ret = scif_peer_initialize_device(scifdev);
+ if (ret)
+ goto exit;
+ schedule_work(&scifdev->peer_add_work);
+exit:
+ mutex_unlock(&scifdev->lock);
}
-struct scif_peer_dev *
-scif_peer_register_device(struct scif_dev *scifdev)
+int scif_peer_unregister_device(struct scif_dev *scifdev)
{
- int ret;
struct scif_peer_dev *spdev;
- spdev = kzalloc(sizeof(*spdev), GFP_KERNEL);
- if (!spdev)
- return ERR_PTR(-ENOMEM);
-
- spdev->dev.parent = scifdev->sdev->dev.parent;
- spdev->dev.release = scif_peer_release_dev;
- spdev->dnode = scifdev->node;
- spdev->dev.bus = &scif_peer_bus;
+ mutex_lock(&scifdev->lock);
+ /* Flush work to ensure device register is complete */
+ flush_work(&scifdev->peer_add_work);
- dev_set_name(&spdev->dev, "scif_peer-dev%u", spdev->dnode);
/*
- * device_register() causes the bus infrastructure to look for a
- * matching driver.
+ * Continue holding scifdev->lock since theoretically unregister_device
+ * can be called simultaneously from multiple threads
*/
- ret = device_register(&spdev->dev);
- if (ret)
- goto free_spdev;
- return spdev;
-free_spdev:
- kfree(spdev);
- return ERR_PTR(ret);
-}
-
-void scif_peer_unregister_device(struct scif_peer_dev *sdev)
-{
- device_unregister(&sdev->dev);
+ spdev = rcu_dereference(scifdev->spdev);
+ if (!spdev) {
+ mutex_unlock(&scifdev->lock);
+ return -ENODEV;
+ }
+
+ RCU_INIT_POINTER(scifdev->spdev, NULL);
+ synchronize_rcu();
+ mutex_unlock(&scifdev->lock);
+
+ dev_dbg(&spdev->dev, "Removing peer dnode %d\n", spdev->dnode);
+ device_unregister(&spdev->dev);
+
+ mutex_lock(&scif_info.conflock);
+ scif_info.total--;
+ mutex_unlock(&scif_info.conflock);
+ return 0;
}
int scif_peer_bus_init(void)
diff --git a/drivers/misc/mic/scif/scif_peer_bus.h b/drivers/misc/mic/scif/scif_peer_bus.h
index 33f0dbb30152..a3b8dd2edaa5 100644
--- a/drivers/misc/mic/scif/scif_peer_bus.h
+++ b/drivers/misc/mic/scif/scif_peer_bus.h
@@ -19,47 +19,13 @@
#include <linux/device.h>
#include <linux/mic_common.h>
-
-/*
- * Peer devices show up as PCIe devices for the mgmt node but not the cards.
- * The mgmt node discovers all the cards on the PCIe bus and informs the other
- * cards about their peers. Upon notification of a peer a node adds a peer
- * device to the peer bus to maintain symmetry in the way devices are
- * discovered across all nodes in the SCIF network.
- */
-/**
- * scif_peer_dev - representation of a peer SCIF device
- * @dev: underlying device
- * @dnode - The destination node which this device will communicate with.
- */
-struct scif_peer_dev {
- struct device dev;
- u8 dnode;
-};
-
-/**
- * scif_peer_driver - operations for a scif_peer I/O driver
- * @driver: underlying device driver (populate name and owner).
- * @id_table: the ids serviced by this driver.
- * @probe: the function to call when a device is found. Returns 0 or -errno.
- * @remove: the function to call when a device is removed.
- */
-struct scif_peer_driver {
- struct device_driver driver;
- const struct scif_peer_dev_id *id_table;
-
- int (*probe)(struct scif_peer_dev *dev);
- void (*remove)(struct scif_peer_dev *dev);
-};
+#include <linux/scif.h>
struct scif_dev;
-int scif_peer_register_driver(struct scif_peer_driver *driver);
-void scif_peer_unregister_driver(struct scif_peer_driver *driver);
-
-struct scif_peer_dev *scif_peer_register_device(struct scif_dev *sdev);
-void scif_peer_unregister_device(struct scif_peer_dev *sdev);
-
+void scif_add_peer_device(struct work_struct *work);
+void scif_peer_register_device(struct scif_dev *sdev);
+int scif_peer_unregister_device(struct scif_dev *scifdev);
int scif_peer_bus_init(void);
void scif_peer_bus_exit(void);
#endif /* _SCIF_PEER_BUS_H */
diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c
new file mode 100644
index 000000000000..8310b4dbff06
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_rma.c
@@ -0,0 +1,1775 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#include <linux/dma_remapping.h>
+#include <linux/pagemap.h>
+#include "scif_main.h"
+#include "scif_map.h"
+
+/* Used to skip ulimit checks for registrations with SCIF_MAP_KERNEL flag */
+#define SCIF_MAP_ULIMIT 0x40
+
+bool scif_ulimit_check = 1;
+
+/**
+ * scif_rma_ep_init:
+ * @ep: end point
+ *
+ * Initialize RMA per EP data structures.
+ */
+void scif_rma_ep_init(struct scif_endpt *ep)
+{
+ struct scif_endpt_rma_info *rma = &ep->rma_info;
+
+ mutex_init(&rma->rma_lock);
+ init_iova_domain(&rma->iovad, PAGE_SIZE, SCIF_IOVA_START_PFN,
+ SCIF_DMA_64BIT_PFN);
+ spin_lock_init(&rma->tc_lock);
+ mutex_init(&rma->mmn_lock);
+ INIT_LIST_HEAD(&rma->reg_list);
+ INIT_LIST_HEAD(&rma->remote_reg_list);
+ atomic_set(&rma->tw_refcount, 0);
+ atomic_set(&rma->tcw_refcount, 0);
+ atomic_set(&rma->tcw_total_pages, 0);
+ atomic_set(&rma->fence_refcount, 0);
+
+ rma->async_list_del = 0;
+ rma->dma_chan = NULL;
+ INIT_LIST_HEAD(&rma->mmn_list);
+ INIT_LIST_HEAD(&rma->vma_list);
+ init_waitqueue_head(&rma->markwq);
+}
+
+/**
+ * scif_rma_ep_can_uninit:
+ * @ep: end point
+ *
+ * Returns 1 if an endpoint can be uninitialized and 0 otherwise.
+ */
+int scif_rma_ep_can_uninit(struct scif_endpt *ep)
+{
+ int ret = 0;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Destroy RMA Info only if both lists are empty */
+ if (list_empty(&ep->rma_info.reg_list) &&
+ list_empty(&ep->rma_info.remote_reg_list) &&
+ list_empty(&ep->rma_info.mmn_list) &&
+ !atomic_read(&ep->rma_info.tw_refcount) &&
+ !atomic_read(&ep->rma_info.tcw_refcount) &&
+ !atomic_read(&ep->rma_info.fence_refcount))
+ ret = 1;
+ mutex_unlock(&ep->rma_info.rma_lock);
+ return ret;
+}
+
+/**
+ * scif_create_pinned_pages:
+ * @nr_pages: number of pages in window
+ * @prot: read/write protection
+ *
+ * Allocate and prepare a set of pinned pages.
+ */
+static struct scif_pinned_pages *
+scif_create_pinned_pages(int nr_pages, int prot)
+{
+ struct scif_pinned_pages *pin;
+
+ might_sleep();
+ pin = scif_zalloc(sizeof(*pin));
+ if (!pin)
+ goto error;
+
+ pin->pages = scif_zalloc(nr_pages * sizeof(*pin->pages));
+ if (!pin->pages)
+ goto error_free_pinned_pages;
+
+ pin->prot = prot;
+ pin->magic = SCIFEP_MAGIC;
+ return pin;
+
+error_free_pinned_pages:
+ scif_free(pin, sizeof(*pin));
+error:
+ return NULL;
+}
+
+/**
+ * scif_destroy_pinned_pages:
+ * @pin: A set of pinned pages.
+ *
+ * Deallocate resources for pinned pages.
+ */
+static int scif_destroy_pinned_pages(struct scif_pinned_pages *pin)
+{
+ int j;
+ int writeable = pin->prot & SCIF_PROT_WRITE;
+ int kernel = SCIF_MAP_KERNEL & pin->map_flags;
+
+ for (j = 0; j < pin->nr_pages; j++) {
+ if (pin->pages[j] && !kernel) {
+ if (writeable)
+ SetPageDirty(pin->pages[j]);
+ put_page(pin->pages[j]);
+ }
+ }
+
+ scif_free(pin->pages,
+ pin->nr_pages * sizeof(*pin->pages));
+ scif_free(pin, sizeof(*pin));
+ return 0;
+}
+
+/*
+ * scif_create_window:
+ * @ep: end point
+ * @nr_pages: number of pages
+ * @offset: registration offset
+ * @temp: true if a temporary window is being created
+ *
+ * Allocate and prepare a self registration window.
+ */
+struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
+ s64 offset, bool temp)
+{
+ struct scif_window *window;
+
+ might_sleep();
+ window = scif_zalloc(sizeof(*window));
+ if (!window)
+ goto error;
+
+ window->dma_addr = scif_zalloc(nr_pages * sizeof(*window->dma_addr));
+ if (!window->dma_addr)
+ goto error_free_window;
+
+ window->num_pages = scif_zalloc(nr_pages * sizeof(*window->num_pages));
+ if (!window->num_pages)
+ goto error_free_window;
+
+ window->offset = offset;
+ window->ep = (u64)ep;
+ window->magic = SCIFEP_MAGIC;
+ window->reg_state = OP_IDLE;
+ init_waitqueue_head(&window->regwq);
+ window->unreg_state = OP_IDLE;
+ init_waitqueue_head(&window->unregwq);
+ INIT_LIST_HEAD(&window->list);
+ window->type = SCIF_WINDOW_SELF;
+ window->temp = temp;
+ return window;
+
+error_free_window:
+ scif_free(window->dma_addr,
+ nr_pages * sizeof(*window->dma_addr));
+ scif_free(window, sizeof(*window));
+error:
+ return NULL;
+}
+
+/**
+ * scif_destroy_incomplete_window:
+ * @ep: end point
+ * @window: registration window
+ *
+ * Deallocate resources for self window.
+ */
+static void scif_destroy_incomplete_window(struct scif_endpt *ep,
+ struct scif_window *window)
+{
+ int err;
+ int nr_pages = window->nr_pages;
+ struct scif_allocmsg *alloc = &window->alloc_handle;
+ struct scifmsg msg;
+
+retry:
+ /* Wait for a SCIF_ALLOC_GNT/REJ message */
+ err = wait_event_timeout(alloc->allocwq,
+ alloc->state != OP_IN_PROGRESS,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ if (!err && scifdev_alive(ep))
+ goto retry;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ if (alloc->state == OP_COMPLETED) {
+ msg.uop = SCIF_FREE_VIRT;
+ msg.src = ep->port;
+ msg.payload[0] = ep->remote_ep;
+ msg.payload[1] = window->alloc_handle.vaddr;
+ msg.payload[2] = (u64)window;
+ msg.payload[3] = SCIF_REGISTER;
+ _scif_nodeqp_send(ep->remote_dev, &msg);
+ }
+ mutex_unlock(&ep->rma_info.rma_lock);
+
+ scif_free_window_offset(ep, window, window->offset);
+ scif_free(window->dma_addr, nr_pages * sizeof(*window->dma_addr));
+ scif_free(window->num_pages, nr_pages * sizeof(*window->num_pages));
+ scif_free(window, sizeof(*window));
+}
+
+/**
+ * scif_unmap_window:
+ * @remote_dev: SCIF remote device
+ * @window: registration window
+ *
+ * Delete any DMA mappings created for a registered self window
+ */
+void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window *window)
+{
+ int j;
+
+ if (scif_is_iommu_enabled() && !scifdev_self(remote_dev)) {
+ if (window->st) {
+ dma_unmap_sg(&remote_dev->sdev->dev,
+ window->st->sgl, window->st->nents,
+ DMA_BIDIRECTIONAL);
+ sg_free_table(window->st);
+ kfree(window->st);
+ window->st = NULL;
+ }
+ } else {
+ for (j = 0; j < window->nr_contig_chunks; j++) {
+ if (window->dma_addr[j]) {
+ scif_unmap_single(window->dma_addr[j],
+ remote_dev,
+ window->num_pages[j] <<
+ PAGE_SHIFT);
+ window->dma_addr[j] = 0x0;
+ }
+ }
+ }
+}
+
+static inline struct mm_struct *__scif_acquire_mm(void)
+{
+ if (scif_ulimit_check)
+ return get_task_mm(current);
+ return NULL;
+}
+
+static inline void __scif_release_mm(struct mm_struct *mm)
+{
+ if (mm)
+ mmput(mm);
+}
+
+static inline int
+__scif_dec_pinned_vm_lock(struct mm_struct *mm,
+ int nr_pages, bool try_lock)
+{
+ if (!mm || !nr_pages || !scif_ulimit_check)
+ return 0;
+ if (try_lock) {
+ if (!down_write_trylock(&mm->mmap_sem)) {
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err\n", __func__, __LINE__);
+ return -1;
+ }
+ } else {
+ down_write(&mm->mmap_sem);
+ }
+ mm->pinned_vm -= nr_pages;
+ up_write(&mm->mmap_sem);
+ return 0;
+}
+
+static inline int __scif_check_inc_pinned_vm(struct mm_struct *mm,
+ int nr_pages)
+{
+ unsigned long locked, lock_limit;
+
+ if (!mm || !nr_pages || !scif_ulimit_check)
+ return 0;
+
+ locked = nr_pages;
+ locked += mm->pinned_vm;
+ lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
+ dev_err(scif_info.mdev.this_device,
+ "locked(%lu) > lock_limit(%lu)\n",
+ locked, lock_limit);
+ return -ENOMEM;
+ }
+ mm->pinned_vm = locked;
+ return 0;
+}
+
+/**
+ * scif_destroy_window:
+ * @ep: end point
+ * @window: registration window
+ *
+ * Deallocate resources for self window.
+ */
+int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window)
+{
+ int j;
+ struct scif_pinned_pages *pinned_pages = window->pinned_pages;
+ int nr_pages = window->nr_pages;
+
+ might_sleep();
+ if (!window->temp && window->mm) {
+ __scif_dec_pinned_vm_lock(window->mm, window->nr_pages, 0);
+ __scif_release_mm(window->mm);
+ window->mm = NULL;
+ }
+
+ scif_free_window_offset(ep, window, window->offset);
+ scif_unmap_window(ep->remote_dev, window);
+ /*
+ * Decrement references for this set of pinned pages from
+ * this window.
+ */
+ j = atomic_sub_return(1, &pinned_pages->ref_count);
+ if (j < 0)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d incorrect ref count %d\n",
+ __func__, __LINE__, j);
+ /*
+ * If the ref count for pinned_pages is zero then someone
+ * has already called scif_unpin_pages() for it and we should
+ * destroy the page cache.
+ */
+ if (!j)
+ scif_destroy_pinned_pages(window->pinned_pages);
+ scif_free(window->dma_addr, nr_pages * sizeof(*window->dma_addr));
+ scif_free(window->num_pages, nr_pages * sizeof(*window->num_pages));
+ window->magic = 0;
+ scif_free(window, sizeof(*window));
+ return 0;
+}
+
+/**
+ * scif_create_remote_lookup:
+ * @remote_dev: SCIF remote device
+ * @window: remote window
+ *
+ * Allocate and prepare lookup entries for the remote
+ * end to copy over the physical addresses.
+ * Returns 0 on success and appropriate errno on failure.
+ */
+static int scif_create_remote_lookup(struct scif_dev *remote_dev,
+ struct scif_window *window)
+{
+ int i, j, err = 0;
+ int nr_pages = window->nr_pages;
+ bool vmalloc_dma_phys, vmalloc_num_pages;
+
+ might_sleep();
+ /* Map window */
+ err = scif_map_single(&window->mapped_offset,
+ window, remote_dev, sizeof(*window));
+ if (err)
+ goto error_window;
+
+ /* Compute the number of lookup entries. 21 == 2MB Shift */
+ window->nr_lookup = ALIGN(nr_pages * PAGE_SIZE,
+ ((2) * 1024 * 1024)) >> 21;
+
+ window->dma_addr_lookup.lookup =
+ scif_alloc_coherent(&window->dma_addr_lookup.offset,
+ remote_dev, window->nr_lookup *
+ sizeof(*window->dma_addr_lookup.lookup),
+ GFP_KERNEL | __GFP_ZERO);
+ if (!window->dma_addr_lookup.lookup) {
+ err = -ENOMEM;
+ goto error_window;
+ }
+
+ window->num_pages_lookup.lookup =
+ scif_alloc_coherent(&window->num_pages_lookup.offset,
+ remote_dev, window->nr_lookup *
+ sizeof(*window->num_pages_lookup.lookup),
+ GFP_KERNEL | __GFP_ZERO);
+ if (!window->num_pages_lookup.lookup) {
+ err = -ENOMEM;
+ goto error_window;
+ }
+
+ vmalloc_dma_phys = is_vmalloc_addr(&window->dma_addr[0]);
+ vmalloc_num_pages = is_vmalloc_addr(&window->num_pages[0]);
+
+ /* Now map each of the pages containing physical addresses */
+ for (i = 0, j = 0; i < nr_pages; i += SCIF_NR_ADDR_IN_PAGE, j++) {
+ err = scif_map_page(&window->dma_addr_lookup.lookup[j],
+ vmalloc_dma_phys ?
+ vmalloc_to_page(&window->dma_addr[i]) :
+ virt_to_page(&window->dma_addr[i]),
+ remote_dev);
+ if (err)
+ goto error_window;
+ err = scif_map_page(&window->num_pages_lookup.lookup[j],
+ vmalloc_dma_phys ?
+ vmalloc_to_page(&window->num_pages[i]) :
+ virt_to_page(&window->num_pages[i]),
+ remote_dev);
+ if (err)
+ goto error_window;
+ }
+ return 0;
+error_window:
+ return err;
+}
+
+/**
+ * scif_destroy_remote_lookup:
+ * @remote_dev: SCIF remote device
+ * @window: remote window
+ *
+ * Destroy lookup entries used for the remote
+ * end to copy over the physical addresses.
+ */
+static void scif_destroy_remote_lookup(struct scif_dev *remote_dev,
+ struct scif_window *window)
+{
+ int i, j;
+
+ if (window->nr_lookup) {
+ struct scif_rma_lookup *lup = &window->dma_addr_lookup;
+ struct scif_rma_lookup *npup = &window->num_pages_lookup;
+
+ for (i = 0, j = 0; i < window->nr_pages;
+ i += SCIF_NR_ADDR_IN_PAGE, j++) {
+ if (lup->lookup && lup->lookup[j])
+ scif_unmap_single(lup->lookup[j],
+ remote_dev,
+ PAGE_SIZE);
+ if (npup->lookup && npup->lookup[j])
+ scif_unmap_single(npup->lookup[j],
+ remote_dev,
+ PAGE_SIZE);
+ }
+ if (lup->lookup)
+ scif_free_coherent(lup->lookup, lup->offset,
+ remote_dev, window->nr_lookup *
+ sizeof(*lup->lookup));
+ if (npup->lookup)
+ scif_free_coherent(npup->lookup, npup->offset,
+ remote_dev, window->nr_lookup *
+ sizeof(*npup->lookup));
+ if (window->mapped_offset)
+ scif_unmap_single(window->mapped_offset,
+ remote_dev, sizeof(*window));
+ window->nr_lookup = 0;
+ }
+}
+
+/**
+ * scif_create_remote_window:
+ * @ep: end point
+ * @nr_pages: number of pages in window
+ *
+ * Allocate and prepare a remote registration window.
+ */
+static struct scif_window *
+scif_create_remote_window(struct scif_dev *scifdev, int nr_pages)
+{
+ struct scif_window *window;
+
+ might_sleep();
+ window = scif_zalloc(sizeof(*window));
+ if (!window)
+ goto error_ret;
+
+ window->magic = SCIFEP_MAGIC;
+ window->nr_pages = nr_pages;
+
+ window->dma_addr = scif_zalloc(nr_pages * sizeof(*window->dma_addr));
+ if (!window->dma_addr)
+ goto error_window;
+
+ window->num_pages = scif_zalloc(nr_pages *
+ sizeof(*window->num_pages));
+ if (!window->num_pages)
+ goto error_window;
+
+ if (scif_create_remote_lookup(scifdev, window))
+ goto error_window;
+
+ window->type = SCIF_WINDOW_PEER;
+ window->unreg_state = OP_IDLE;
+ INIT_LIST_HEAD(&window->list);
+ return window;
+error_window:
+ scif_destroy_remote_window(window);
+error_ret:
+ return NULL;
+}
+
+/**
+ * scif_destroy_remote_window:
+ * @ep: end point
+ * @window: remote registration window
+ *
+ * Deallocate resources for remote window.
+ */
+void
+scif_destroy_remote_window(struct scif_window *window)
+{
+ scif_free(window->dma_addr, window->nr_pages *
+ sizeof(*window->dma_addr));
+ scif_free(window->num_pages, window->nr_pages *
+ sizeof(*window->num_pages));
+ window->magic = 0;
+ scif_free(window, sizeof(*window));
+}
+
+/**
+ * scif_iommu_map: create DMA mappings if the IOMMU is enabled
+ * @remote_dev: SCIF remote device
+ * @window: remote registration window
+ *
+ * Map the physical pages using dma_map_sg(..) and then detect the number
+ * of contiguous DMA mappings allocated
+ */
+static int scif_iommu_map(struct scif_dev *remote_dev,
+ struct scif_window *window)
+{
+ struct scatterlist *sg;
+ int i, err;
+ scif_pinned_pages_t pin = window->pinned_pages;
+
+ window->st = kzalloc(sizeof(*window->st), GFP_KERNEL);
+ if (!window->st)
+ return -ENOMEM;
+
+ err = sg_alloc_table(window->st, window->nr_pages, GFP_KERNEL);
+ if (err)
+ return err;
+
+ for_each_sg(window->st->sgl, sg, window->st->nents, i)
+ sg_set_page(sg, pin->pages[i], PAGE_SIZE, 0x0);
+
+ err = dma_map_sg(&remote_dev->sdev->dev, window->st->sgl,
+ window->st->nents, DMA_BIDIRECTIONAL);
+ if (!err)
+ return -ENOMEM;
+ /* Detect contiguous ranges of DMA mappings */
+ sg = window->st->sgl;
+ for (i = 0; sg; i++) {
+ dma_addr_t last_da;
+
+ window->dma_addr[i] = sg_dma_address(sg);
+ window->num_pages[i] = sg_dma_len(sg) >> PAGE_SHIFT;
+ last_da = sg_dma_address(sg) + sg_dma_len(sg);
+ while ((sg = sg_next(sg)) && sg_dma_address(sg) == last_da) {
+ window->num_pages[i] +=
+ (sg_dma_len(sg) >> PAGE_SHIFT);
+ last_da = window->dma_addr[i] +
+ sg_dma_len(sg);
+ }
+ window->nr_contig_chunks++;
+ }
+ return 0;
+}
+
+/**
+ * scif_map_window:
+ * @remote_dev: SCIF remote device
+ * @window: self registration window
+ *
+ * Map pages of a window into the aperture/PCI.
+ * Also determine addresses required for DMA.
+ */
+int
+scif_map_window(struct scif_dev *remote_dev, struct scif_window *window)
+{
+ int i, j, k, err = 0, nr_contig_pages;
+ scif_pinned_pages_t pin;
+ phys_addr_t phys_prev, phys_curr;
+
+ might_sleep();
+
+ pin = window->pinned_pages;
+
+ if (intel_iommu_enabled && !scifdev_self(remote_dev))
+ return scif_iommu_map(remote_dev, window);
+
+ for (i = 0, j = 0; i < window->nr_pages; i += nr_contig_pages, j++) {
+ phys_prev = page_to_phys(pin->pages[i]);
+ nr_contig_pages = 1;
+
+ /* Detect physically contiguous chunks */
+ for (k = i + 1; k < window->nr_pages; k++) {
+ phys_curr = page_to_phys(pin->pages[k]);
+ if (phys_curr != (phys_prev + PAGE_SIZE))
+ break;
+ phys_prev = phys_curr;
+ nr_contig_pages++;
+ }
+ window->num_pages[j] = nr_contig_pages;
+ window->nr_contig_chunks++;
+ if (scif_is_mgmt_node()) {
+ /*
+ * Management node has to deal with SMPT on X100 and
+ * hence the DMA mapping is required
+ */
+ err = scif_map_single(&window->dma_addr[j],
+ phys_to_virt(page_to_phys(
+ pin->pages[i])),
+ remote_dev,
+ nr_contig_pages << PAGE_SHIFT);
+ if (err)
+ return err;
+ } else {
+ window->dma_addr[j] = page_to_phys(pin->pages[i]);
+ }
+ }
+ return err;
+}
+
+/**
+ * scif_send_scif_unregister:
+ * @ep: end point
+ * @window: self registration window
+ *
+ * Send a SCIF_UNREGISTER message.
+ */
+static int scif_send_scif_unregister(struct scif_endpt *ep,
+ struct scif_window *window)
+{
+ struct scifmsg msg;
+
+ msg.uop = SCIF_UNREGISTER;
+ msg.src = ep->port;
+ msg.payload[0] = window->alloc_handle.vaddr;
+ msg.payload[1] = (u64)window;
+ return scif_nodeqp_send(ep->remote_dev, &msg);
+}
+
+/**
+ * scif_unregister_window:
+ * @window: self registration window
+ *
+ * Send an unregistration request and wait for a response.
+ */
+int scif_unregister_window(struct scif_window *window)
+{
+ int err = 0;
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+ bool send_msg = false;
+
+ might_sleep();
+ switch (window->unreg_state) {
+ case OP_IDLE:
+ {
+ window->unreg_state = OP_IN_PROGRESS;
+ send_msg = true;
+ /* fall through */
+ }
+ case OP_IN_PROGRESS:
+ {
+ scif_get_window(window, 1);
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (send_msg) {
+ err = scif_send_scif_unregister(ep, window);
+ if (err) {
+ window->unreg_state = OP_COMPLETED;
+ goto done;
+ }
+ } else {
+ /* Return ENXIO since unregistration is in progress */
+ mutex_lock(&ep->rma_info.rma_lock);
+ return -ENXIO;
+ }
+retry:
+ /* Wait for a SCIF_UNREGISTER_(N)ACK message */
+ err = wait_event_timeout(window->unregwq,
+ window->unreg_state != OP_IN_PROGRESS,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ if (!err && scifdev_alive(ep))
+ goto retry;
+ if (!err) {
+ err = -ENODEV;
+ window->unreg_state = OP_COMPLETED;
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ }
+ if (err > 0)
+ err = 0;
+done:
+ mutex_lock(&ep->rma_info.rma_lock);
+ scif_put_window(window, 1);
+ break;
+ }
+ case OP_FAILED:
+ {
+ if (!scifdev_alive(ep)) {
+ err = -ENODEV;
+ window->unreg_state = OP_COMPLETED;
+ }
+ break;
+ }
+ case OP_COMPLETED:
+ break;
+ default:
+ err = -ENODEV;
+ }
+
+ if (window->unreg_state == OP_COMPLETED && window->ref_count)
+ scif_put_window(window, window->nr_pages);
+
+ if (!window->ref_count) {
+ atomic_inc(&ep->rma_info.tw_refcount);
+ list_del_init(&window->list);
+ scif_free_window_offset(ep, window, window->offset);
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if ((!!(window->pinned_pages->map_flags & SCIF_MAP_KERNEL)) &&
+ scifdev_alive(ep)) {
+ scif_drain_dma_intr(ep->remote_dev->sdev,
+ ep->rma_info.dma_chan);
+ } else {
+ if (!__scif_dec_pinned_vm_lock(window->mm,
+ window->nr_pages, 1)) {
+ __scif_release_mm(window->mm);
+ window->mm = NULL;
+ }
+ }
+ scif_queue_for_cleanup(window, &scif_info.rma);
+ mutex_lock(&ep->rma_info.rma_lock);
+ }
+ return err;
+}
+
+/**
+ * scif_send_alloc_request:
+ * @ep: end point
+ * @window: self registration window
+ *
+ * Send a remote window allocation request
+ */
+static int scif_send_alloc_request(struct scif_endpt *ep,
+ struct scif_window *window)
+{
+ struct scifmsg msg;
+ struct scif_allocmsg *alloc = &window->alloc_handle;
+
+ /* Set up the Alloc Handle */
+ alloc->state = OP_IN_PROGRESS;
+ init_waitqueue_head(&alloc->allocwq);
+
+ /* Send out an allocation request */
+ msg.uop = SCIF_ALLOC_REQ;
+ msg.payload[1] = window->nr_pages;
+ msg.payload[2] = (u64)&window->alloc_handle;
+ return _scif_nodeqp_send(ep->remote_dev, &msg);
+}
+
+/**
+ * scif_prep_remote_window:
+ * @ep: end point
+ * @window: self registration window
+ *
+ * Send a remote window allocation request, wait for an allocation response,
+ * and prepares the remote window by copying over the page lists
+ */
+static int scif_prep_remote_window(struct scif_endpt *ep,
+ struct scif_window *window)
+{
+ struct scifmsg msg;
+ struct scif_window *remote_window;
+ struct scif_allocmsg *alloc = &window->alloc_handle;
+ dma_addr_t *dma_phys_lookup, *tmp, *num_pages_lookup, *tmp1;
+ int i = 0, j = 0;
+ int nr_contig_chunks, loop_nr_contig_chunks;
+ int remaining_nr_contig_chunks, nr_lookup;
+ int err, map_err;
+
+ map_err = scif_map_window(ep->remote_dev, window);
+ if (map_err)
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d map_err %d\n", __func__, __LINE__, map_err);
+ remaining_nr_contig_chunks = window->nr_contig_chunks;
+ nr_contig_chunks = window->nr_contig_chunks;
+retry:
+ /* Wait for a SCIF_ALLOC_GNT/REJ message */
+ err = wait_event_timeout(alloc->allocwq,
+ alloc->state != OP_IN_PROGRESS,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Synchronize with the thread waking up allocwq */
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (!err && scifdev_alive(ep))
+ goto retry;
+
+ if (!err)
+ err = -ENODEV;
+
+ if (err > 0)
+ err = 0;
+ else
+ return err;
+
+ /* Bail out. The remote end rejected this request */
+ if (alloc->state == OP_FAILED)
+ return -ENOMEM;
+
+ if (map_err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, map_err);
+ msg.uop = SCIF_FREE_VIRT;
+ msg.src = ep->port;
+ msg.payload[0] = ep->remote_ep;
+ msg.payload[1] = window->alloc_handle.vaddr;
+ msg.payload[2] = (u64)window;
+ msg.payload[3] = SCIF_REGISTER;
+ spin_lock(&ep->lock);
+ if (ep->state == SCIFEP_CONNECTED)
+ err = _scif_nodeqp_send(ep->remote_dev, &msg);
+ else
+ err = -ENOTCONN;
+ spin_unlock(&ep->lock);
+ return err;
+ }
+
+ remote_window = scif_ioremap(alloc->phys_addr, sizeof(*window),
+ ep->remote_dev);
+
+ /* Compute the number of lookup entries. 21 == 2MB Shift */
+ nr_lookup = ALIGN(nr_contig_chunks, SCIF_NR_ADDR_IN_PAGE)
+ >> ilog2(SCIF_NR_ADDR_IN_PAGE);
+
+ dma_phys_lookup =
+ scif_ioremap(remote_window->dma_addr_lookup.offset,
+ nr_lookup *
+ sizeof(*remote_window->dma_addr_lookup.lookup),
+ ep->remote_dev);
+ num_pages_lookup =
+ scif_ioremap(remote_window->num_pages_lookup.offset,
+ nr_lookup *
+ sizeof(*remote_window->num_pages_lookup.lookup),
+ ep->remote_dev);
+
+ while (remaining_nr_contig_chunks) {
+ loop_nr_contig_chunks = min_t(int, remaining_nr_contig_chunks,
+ (int)SCIF_NR_ADDR_IN_PAGE);
+ /* #1/2 - Copy physical addresses over to the remote side */
+
+ /* #2/2 - Copy DMA addresses (addresses that are fed into the
+ * DMA engine) We transfer bus addresses which are then
+ * converted into a MIC physical address on the remote
+ * side if it is a MIC, if the remote node is a mgmt node we
+ * transfer the MIC physical address
+ */
+ tmp = scif_ioremap(dma_phys_lookup[j],
+ loop_nr_contig_chunks *
+ sizeof(*window->dma_addr),
+ ep->remote_dev);
+ tmp1 = scif_ioremap(num_pages_lookup[j],
+ loop_nr_contig_chunks *
+ sizeof(*window->num_pages),
+ ep->remote_dev);
+ if (scif_is_mgmt_node()) {
+ memcpy_toio((void __force __iomem *)tmp,
+ &window->dma_addr[i], loop_nr_contig_chunks
+ * sizeof(*window->dma_addr));
+ memcpy_toio((void __force __iomem *)tmp1,
+ &window->num_pages[i], loop_nr_contig_chunks
+ * sizeof(*window->num_pages));
+ } else {
+ if (scifdev_is_p2p(ep->remote_dev)) {
+ /*
+ * add remote node's base address for this node
+ * to convert it into a MIC address
+ */
+ int m;
+ dma_addr_t dma_addr;
+
+ for (m = 0; m < loop_nr_contig_chunks; m++) {
+ dma_addr = window->dma_addr[i + m] +
+ ep->remote_dev->base_addr;
+ writeq(dma_addr,
+ (void __force __iomem *)&tmp[m]);
+ }
+ memcpy_toio((void __force __iomem *)tmp1,
+ &window->num_pages[i],
+ loop_nr_contig_chunks
+ * sizeof(*window->num_pages));
+ } else {
+ /* Mgmt node or loopback - transfer DMA
+ * addresses as is, this is the same as a
+ * MIC physical address (we use the dma_addr
+ * and not the phys_addr array since the
+ * phys_addr is only setup if there is a mmap()
+ * request from the mgmt node)
+ */
+ memcpy_toio((void __force __iomem *)tmp,
+ &window->dma_addr[i],
+ loop_nr_contig_chunks *
+ sizeof(*window->dma_addr));
+ memcpy_toio((void __force __iomem *)tmp1,
+ &window->num_pages[i],
+ loop_nr_contig_chunks *
+ sizeof(*window->num_pages));
+ }
+ }
+ remaining_nr_contig_chunks -= loop_nr_contig_chunks;
+ i += loop_nr_contig_chunks;
+ j++;
+ scif_iounmap(tmp, loop_nr_contig_chunks *
+ sizeof(*window->dma_addr), ep->remote_dev);
+ scif_iounmap(tmp1, loop_nr_contig_chunks *
+ sizeof(*window->num_pages), ep->remote_dev);
+ }
+
+ /* Prepare the remote window for the peer */
+ remote_window->peer_window = (u64)window;
+ remote_window->offset = window->offset;
+ remote_window->prot = window->prot;
+ remote_window->nr_contig_chunks = nr_contig_chunks;
+ remote_window->ep = ep->remote_ep;
+ scif_iounmap(num_pages_lookup,
+ nr_lookup *
+ sizeof(*remote_window->num_pages_lookup.lookup),
+ ep->remote_dev);
+ scif_iounmap(dma_phys_lookup,
+ nr_lookup *
+ sizeof(*remote_window->dma_addr_lookup.lookup),
+ ep->remote_dev);
+ scif_iounmap(remote_window, sizeof(*remote_window), ep->remote_dev);
+ window->peer_window = alloc->vaddr;
+ return err;
+}
+
+/**
+ * scif_send_scif_register:
+ * @ep: end point
+ * @window: self registration window
+ *
+ * Send a SCIF_REGISTER message if EP is connected and wait for a
+ * SCIF_REGISTER_(N)ACK message else send a SCIF_FREE_VIRT
+ * message so that the peer can free its remote window allocated earlier.
+ */
+static int scif_send_scif_register(struct scif_endpt *ep,
+ struct scif_window *window)
+{
+ int err = 0;
+ struct scifmsg msg;
+
+ msg.src = ep->port;
+ msg.payload[0] = ep->remote_ep;
+ msg.payload[1] = window->alloc_handle.vaddr;
+ msg.payload[2] = (u64)window;
+ spin_lock(&ep->lock);
+ if (ep->state == SCIFEP_CONNECTED) {
+ msg.uop = SCIF_REGISTER;
+ window->reg_state = OP_IN_PROGRESS;
+ err = _scif_nodeqp_send(ep->remote_dev, &msg);
+ spin_unlock(&ep->lock);
+ if (!err) {
+retry:
+ /* Wait for a SCIF_REGISTER_(N)ACK message */
+ err = wait_event_timeout(window->regwq,
+ window->reg_state !=
+ OP_IN_PROGRESS,
+ SCIF_NODE_ALIVE_TIMEOUT);
+ if (!err && scifdev_alive(ep))
+ goto retry;
+ err = !err ? -ENODEV : 0;
+ if (window->reg_state == OP_FAILED)
+ err = -ENOTCONN;
+ }
+ } else {
+ msg.uop = SCIF_FREE_VIRT;
+ msg.payload[3] = SCIF_REGISTER;
+ err = _scif_nodeqp_send(ep->remote_dev, &msg);
+ spin_unlock(&ep->lock);
+ if (!err)
+ err = -ENOTCONN;
+ }
+ return err;
+}
+
+/**
+ * scif_get_window_offset:
+ * @ep: end point descriptor
+ * @flags: flags
+ * @offset: offset hint
+ * @num_pages: number of pages
+ * @out_offset: computed offset returned by reference.
+ *
+ * Compute/Claim a new offset for this EP.
+ */
+int scif_get_window_offset(struct scif_endpt *ep, int flags, s64 offset,
+ int num_pages, s64 *out_offset)
+{
+ s64 page_index;
+ struct iova *iova_ptr;
+ int err = 0;
+
+ if (flags & SCIF_MAP_FIXED) {
+ page_index = SCIF_IOVA_PFN(offset);
+ iova_ptr = reserve_iova(&ep->rma_info.iovad, page_index,
+ page_index + num_pages - 1);
+ if (!iova_ptr)
+ err = -EADDRINUSE;
+ } else {
+ iova_ptr = alloc_iova(&ep->rma_info.iovad, num_pages,
+ SCIF_DMA_63BIT_PFN - 1, 0);
+ if (!iova_ptr)
+ err = -ENOMEM;
+ }
+ if (!err)
+ *out_offset = (iova_ptr->pfn_lo) << PAGE_SHIFT;
+ return err;
+}
+
+/**
+ * scif_free_window_offset:
+ * @ep: end point descriptor
+ * @window: registration window
+ * @offset: Offset to be freed
+ *
+ * Free offset for this EP. The callee is supposed to grab
+ * the RMA mutex before calling this API.
+ */
+void scif_free_window_offset(struct scif_endpt *ep,
+ struct scif_window *window, s64 offset)
+{
+ if ((window && !window->offset_freed) || !window) {
+ free_iova(&ep->rma_info.iovad, offset >> PAGE_SHIFT);
+ if (window)
+ window->offset_freed = true;
+ }
+}
+
+/**
+ * scif_alloc_req: Respond to SCIF_ALLOC_REQ interrupt message
+ * @msg: Interrupt message
+ *
+ * Remote side is requesting a memory allocation.
+ */
+void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ int err;
+ struct scif_window *window = NULL;
+ int nr_pages = msg->payload[1];
+
+ window = scif_create_remote_window(scifdev, nr_pages);
+ if (!window) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ /* The peer's allocation request is granted */
+ msg->uop = SCIF_ALLOC_GNT;
+ msg->payload[0] = (u64)window;
+ msg->payload[1] = window->mapped_offset;
+ err = scif_nodeqp_send(scifdev, msg);
+ if (err)
+ scif_destroy_remote_window(window);
+ return;
+error:
+ /* The peer's allocation request is rejected */
+ dev_err(&scifdev->sdev->dev,
+ "%s %d error %d alloc_ptr %p nr_pages 0x%x\n",
+ __func__, __LINE__, err, window, nr_pages);
+ msg->uop = SCIF_ALLOC_REJ;
+ scif_nodeqp_send(scifdev, msg);
+}
+
+/**
+ * scif_alloc_gnt_rej: Respond to SCIF_ALLOC_GNT/REJ interrupt message
+ * @msg: Interrupt message
+ *
+ * Remote side responded to a memory allocation.
+ */
+void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_allocmsg *handle = (struct scif_allocmsg *)msg->payload[2];
+ struct scif_window *window = container_of(handle, struct scif_window,
+ alloc_handle);
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ handle->vaddr = msg->payload[0];
+ handle->phys_addr = msg->payload[1];
+ if (msg->uop == SCIF_ALLOC_GNT)
+ handle->state = OP_COMPLETED;
+ else
+ handle->state = OP_FAILED;
+ wake_up(&handle->allocwq);
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+/**
+ * scif_free_virt: Respond to SCIF_FREE_VIRT interrupt message
+ * @msg: Interrupt message
+ *
+ * Free up memory kmalloc'd earlier.
+ */
+void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_window *window = (struct scif_window *)msg->payload[1];
+
+ scif_destroy_remote_window(window);
+}
+
+static void
+scif_fixup_aper_base(struct scif_dev *dev, struct scif_window *window)
+{
+ int j;
+ struct scif_hw_dev *sdev = dev->sdev;
+ phys_addr_t apt_base = 0;
+
+ /*
+ * Add the aperture base if the DMA address is not card relative
+ * since the DMA addresses need to be an offset into the bar
+ */
+ if (!scifdev_self(dev) && window->type == SCIF_WINDOW_PEER &&
+ sdev->aper && !sdev->card_rel_da)
+ apt_base = sdev->aper->pa;
+ else
+ return;
+
+ for (j = 0; j < window->nr_contig_chunks; j++) {
+ if (window->num_pages[j])
+ window->dma_addr[j] += apt_base;
+ else
+ break;
+ }
+}
+
+/**
+ * scif_recv_reg: Respond to SCIF_REGISTER interrupt message
+ * @msg: Interrupt message
+ *
+ * Update remote window list with a new registered window.
+ */
+void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
+ struct scif_window *window =
+ (struct scif_window *)msg->payload[1];
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ spin_lock(&ep->lock);
+ if (ep->state == SCIFEP_CONNECTED) {
+ msg->uop = SCIF_REGISTER_ACK;
+ scif_nodeqp_send(ep->remote_dev, msg);
+ scif_fixup_aper_base(ep->remote_dev, window);
+ /* No further failures expected. Insert new window */
+ scif_insert_window(window, &ep->rma_info.remote_reg_list);
+ } else {
+ msg->uop = SCIF_REGISTER_NACK;
+ scif_nodeqp_send(ep->remote_dev, msg);
+ }
+ spin_unlock(&ep->lock);
+ mutex_unlock(&ep->rma_info.rma_lock);
+ /* free up any lookup resources now that page lists are transferred */
+ scif_destroy_remote_lookup(ep->remote_dev, window);
+ /*
+ * We could not insert the window but we need to
+ * destroy the window.
+ */
+ if (msg->uop == SCIF_REGISTER_NACK)
+ scif_destroy_remote_window(window);
+}
+
+/**
+ * scif_recv_unreg: Respond to SCIF_UNREGISTER interrupt message
+ * @msg: Interrupt message
+ *
+ * Remove window from remote registration list;
+ */
+void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_rma_req req;
+ struct scif_window *window = NULL;
+ struct scif_window *recv_window =
+ (struct scif_window *)msg->payload[0];
+ struct scif_endpt *ep;
+ int del_window = 0;
+
+ ep = (struct scif_endpt *)recv_window->ep;
+ req.out_window = &window;
+ req.offset = recv_window->offset;
+ req.prot = 0;
+ req.nr_bytes = recv_window->nr_pages << PAGE_SHIFT;
+ req.type = SCIF_WINDOW_FULL;
+ req.head = &ep->rma_info.remote_reg_list;
+ msg->payload[0] = ep->remote_ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Does a valid window exist? */
+ if (scif_query_window(&req)) {
+ dev_err(&scifdev->sdev->dev,
+ "%s %d -ENXIO\n", __func__, __LINE__);
+ msg->uop = SCIF_UNREGISTER_ACK;
+ goto error;
+ }
+ if (window) {
+ if (window->ref_count)
+ scif_put_window(window, window->nr_pages);
+ else
+ dev_err(&scifdev->sdev->dev,
+ "%s %d ref count should be +ve\n",
+ __func__, __LINE__);
+ window->unreg_state = OP_COMPLETED;
+ if (!window->ref_count) {
+ msg->uop = SCIF_UNREGISTER_ACK;
+ atomic_inc(&ep->rma_info.tw_refcount);
+ ep->rma_info.async_list_del = 1;
+ list_del_init(&window->list);
+ del_window = 1;
+ } else {
+ /* NACK! There are valid references to this window */
+ msg->uop = SCIF_UNREGISTER_NACK;
+ }
+ } else {
+ /* The window did not make its way to the list at all. ACK */
+ msg->uop = SCIF_UNREGISTER_ACK;
+ scif_destroy_remote_window(recv_window);
+ }
+error:
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (del_window)
+ scif_drain_dma_intr(ep->remote_dev->sdev,
+ ep->rma_info.dma_chan);
+ scif_nodeqp_send(ep->remote_dev, msg);
+ if (del_window)
+ scif_queue_for_cleanup(window, &scif_info.rma);
+}
+
+/**
+ * scif_recv_reg_ack: Respond to SCIF_REGISTER_ACK interrupt message
+ * @msg: Interrupt message
+ *
+ * Wake up the window waiting to complete registration.
+ */
+void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_window *window =
+ (struct scif_window *)msg->payload[2];
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ window->reg_state = OP_COMPLETED;
+ wake_up(&window->regwq);
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+/**
+ * scif_recv_reg_nack: Respond to SCIF_REGISTER_NACK interrupt message
+ * @msg: Interrupt message
+ *
+ * Wake up the window waiting to inform it that registration
+ * cannot be completed.
+ */
+void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_window *window =
+ (struct scif_window *)msg->payload[2];
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ window->reg_state = OP_FAILED;
+ wake_up(&window->regwq);
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+/**
+ * scif_recv_unreg_ack: Respond to SCIF_UNREGISTER_ACK interrupt message
+ * @msg: Interrupt message
+ *
+ * Wake up the window waiting to complete unregistration.
+ */
+void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_window *window =
+ (struct scif_window *)msg->payload[1];
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ window->unreg_state = OP_COMPLETED;
+ wake_up(&window->unregwq);
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+/**
+ * scif_recv_unreg_nack: Respond to SCIF_UNREGISTER_NACK interrupt message
+ * @msg: Interrupt message
+ *
+ * Wake up the window waiting to inform it that unregistration
+ * cannot be completed immediately.
+ */
+void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg)
+{
+ struct scif_window *window =
+ (struct scif_window *)msg->payload[1];
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ window->unreg_state = OP_FAILED;
+ wake_up(&window->unregwq);
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+int __scif_pin_pages(void *addr, size_t len, int *out_prot,
+ int map_flags, scif_pinned_pages_t *pages)
+{
+ struct scif_pinned_pages *pinned_pages;
+ int nr_pages, err = 0, i;
+ bool vmalloc_addr = false;
+ bool try_upgrade = false;
+ int prot = *out_prot;
+ int ulimit = 0;
+ struct mm_struct *mm = NULL;
+
+ /* Unsupported flags */
+ if (map_flags & ~(SCIF_MAP_KERNEL | SCIF_MAP_ULIMIT))
+ return -EINVAL;
+ ulimit = !!(map_flags & SCIF_MAP_ULIMIT);
+
+ /* Unsupported protection requested */
+ if (prot & ~(SCIF_PROT_READ | SCIF_PROT_WRITE))
+ return -EINVAL;
+
+ /* addr/len must be page aligned. len should be non zero */
+ if (!len ||
+ (ALIGN((u64)addr, PAGE_SIZE) != (u64)addr) ||
+ (ALIGN((u64)len, PAGE_SIZE) != (u64)len))
+ return -EINVAL;
+
+ might_sleep();
+
+ nr_pages = len >> PAGE_SHIFT;
+
+ /* Allocate a set of pinned pages */
+ pinned_pages = scif_create_pinned_pages(nr_pages, prot);
+ if (!pinned_pages)
+ return -ENOMEM;
+
+ if (map_flags & SCIF_MAP_KERNEL) {
+ if (is_vmalloc_addr(addr))
+ vmalloc_addr = true;
+
+ for (i = 0; i < nr_pages; i++) {
+ if (vmalloc_addr)
+ pinned_pages->pages[i] =
+ vmalloc_to_page(addr + (i * PAGE_SIZE));
+ else
+ pinned_pages->pages[i] =
+ virt_to_page(addr + (i * PAGE_SIZE));
+ }
+ pinned_pages->nr_pages = nr_pages;
+ pinned_pages->map_flags = SCIF_MAP_KERNEL;
+ } else {
+ /*
+ * SCIF supports registration caching. If a registration has
+ * been requested with read only permissions, then we try
+ * to pin the pages with RW permissions so that a subsequent
+ * transfer with RW permission can hit the cache instead of
+ * invalidating it. If the upgrade fails with RW then we
+ * revert back to R permission and retry
+ */
+ if (prot == SCIF_PROT_READ)
+ try_upgrade = true;
+ prot |= SCIF_PROT_WRITE;
+retry:
+ mm = current->mm;
+ down_write(&mm->mmap_sem);
+ if (ulimit) {
+ err = __scif_check_inc_pinned_vm(mm, nr_pages);
+ if (err) {
+ up_write(&mm->mmap_sem);
+ pinned_pages->nr_pages = 0;
+ goto error_unmap;
+ }
+ }
+
+ pinned_pages->nr_pages = get_user_pages(
+ current,
+ mm,
+ (u64)addr,
+ nr_pages,
+ !!(prot & SCIF_PROT_WRITE),
+ 0,
+ pinned_pages->pages,
+ NULL);
+ up_write(&mm->mmap_sem);
+ if (nr_pages != pinned_pages->nr_pages) {
+ if (try_upgrade) {
+ if (ulimit)
+ __scif_dec_pinned_vm_lock(mm,
+ nr_pages, 0);
+ /* Roll back any pinned pages */
+ for (i = 0; i < pinned_pages->nr_pages; i++) {
+ if (pinned_pages->pages[i])
+ put_page(
+ pinned_pages->pages[i]);
+ }
+ prot &= ~SCIF_PROT_WRITE;
+ try_upgrade = false;
+ goto retry;
+ }
+ }
+ pinned_pages->map_flags = 0;
+ }
+
+ if (pinned_pages->nr_pages < nr_pages) {
+ err = -EFAULT;
+ pinned_pages->nr_pages = nr_pages;
+ goto dec_pinned;
+ }
+
+ *out_prot = prot;
+ atomic_set(&pinned_pages->ref_count, 1);
+ *pages = pinned_pages;
+ return err;
+dec_pinned:
+ if (ulimit)
+ __scif_dec_pinned_vm_lock(mm, nr_pages, 0);
+ /* Something went wrong! Rollback */
+error_unmap:
+ pinned_pages->nr_pages = nr_pages;
+ scif_destroy_pinned_pages(pinned_pages);
+ *pages = NULL;
+ dev_dbg(scif_info.mdev.this_device,
+ "%s %d err %d len 0x%lx\n", __func__, __LINE__, err, len);
+ return err;
+}
+
+int scif_pin_pages(void *addr, size_t len, int prot,
+ int map_flags, scif_pinned_pages_t *pages)
+{
+ return __scif_pin_pages(addr, len, &prot, map_flags, pages);
+}
+EXPORT_SYMBOL_GPL(scif_pin_pages);
+
+int scif_unpin_pages(scif_pinned_pages_t pinned_pages)
+{
+ int err = 0, ret;
+
+ if (!pinned_pages || SCIFEP_MAGIC != pinned_pages->magic)
+ return -EINVAL;
+
+ ret = atomic_sub_return(1, &pinned_pages->ref_count);
+ if (ret < 0) {
+ dev_err(scif_info.mdev.this_device,
+ "%s %d scif_unpin_pages called without pinning? rc %d\n",
+ __func__, __LINE__, ret);
+ return -EINVAL;
+ }
+ /*
+ * Destroy the window if the ref count for this set of pinned
+ * pages has dropped to zero. If it is positive then there is
+ * a valid registered window which is backed by these pages and
+ * it will be destroyed once all such windows are unregistered.
+ */
+ if (!ret)
+ err = scif_destroy_pinned_pages(pinned_pages);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_unpin_pages);
+
+static inline void
+scif_insert_local_window(struct scif_window *window, struct scif_endpt *ep)
+{
+ mutex_lock(&ep->rma_info.rma_lock);
+ scif_insert_window(window, &ep->rma_info.reg_list);
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+off_t scif_register_pinned_pages(scif_epd_t epd,
+ scif_pinned_pages_t pinned_pages,
+ off_t offset, int map_flags)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ s64 computed_offset;
+ struct scif_window *window;
+ int err;
+ size_t len;
+ struct device *spdev;
+
+ /* Unsupported flags */
+ if (map_flags & ~SCIF_MAP_FIXED)
+ return -EINVAL;
+
+ len = pinned_pages->nr_pages << PAGE_SHIFT;
+
+ /*
+ * Offset is not page aligned/negative or offset+len
+ * wraps around with SCIF_MAP_FIXED.
+ */
+ if ((map_flags & SCIF_MAP_FIXED) &&
+ ((ALIGN(offset, PAGE_SIZE) != offset) ||
+ (offset < 0) ||
+ (offset + (off_t)len < offset)))
+ return -EINVAL;
+
+ might_sleep();
+
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+ /*
+ * It is an error to pass pinned_pages to scif_register_pinned_pages()
+ * after calling scif_unpin_pages().
+ */
+ if (!atomic_add_unless(&pinned_pages->ref_count, 1, 0))
+ return -EINVAL;
+
+ /* Compute the offset for this registration */
+ err = scif_get_window_offset(ep, map_flags, offset,
+ len, &computed_offset);
+ if (err) {
+ atomic_sub(1, &pinned_pages->ref_count);
+ return err;
+ }
+
+ /* Allocate and prepare self registration window */
+ window = scif_create_window(ep, pinned_pages->nr_pages,
+ computed_offset, false);
+ if (!window) {
+ atomic_sub(1, &pinned_pages->ref_count);
+ scif_free_window_offset(ep, NULL, computed_offset);
+ return -ENOMEM;
+ }
+
+ window->pinned_pages = pinned_pages;
+ window->nr_pages = pinned_pages->nr_pages;
+ window->prot = pinned_pages->prot;
+
+ spdev = scif_get_peer_dev(ep->remote_dev);
+ if (IS_ERR(spdev)) {
+ err = PTR_ERR(spdev);
+ scif_destroy_window(ep, window);
+ return err;
+ }
+ err = scif_send_alloc_request(ep, window);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error_unmap;
+ }
+
+ /* Prepare the remote registration window */
+ err = scif_prep_remote_window(ep, window);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error_unmap;
+ }
+
+ /* Tell the peer about the new window */
+ err = scif_send_scif_register(ep, window);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error_unmap;
+ }
+
+ scif_put_peer_dev(spdev);
+ /* No further failures expected. Insert new window */
+ scif_insert_local_window(window, ep);
+ return computed_offset;
+error_unmap:
+ scif_destroy_window(ep, window);
+ scif_put_peer_dev(spdev);
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_register_pinned_pages);
+
+off_t scif_register(scif_epd_t epd, void *addr, size_t len, off_t offset,
+ int prot, int map_flags)
+{
+ scif_pinned_pages_t pinned_pages;
+ off_t err;
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ s64 computed_offset;
+ struct scif_window *window;
+ struct mm_struct *mm = NULL;
+ struct device *spdev;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI register: ep %p addr %p len 0x%lx offset 0x%lx prot 0x%x map_flags 0x%x\n",
+ epd, addr, len, offset, prot, map_flags);
+ /* Unsupported flags */
+ if (map_flags & ~(SCIF_MAP_FIXED | SCIF_MAP_KERNEL))
+ return -EINVAL;
+
+ /*
+ * Offset is not page aligned/negative or offset+len
+ * wraps around with SCIF_MAP_FIXED.
+ */
+ if ((map_flags & SCIF_MAP_FIXED) &&
+ ((ALIGN(offset, PAGE_SIZE) != offset) ||
+ (offset < 0) ||
+ (offset + (off_t)len < offset)))
+ return -EINVAL;
+
+ /* Unsupported protection requested */
+ if (prot & ~(SCIF_PROT_READ | SCIF_PROT_WRITE))
+ return -EINVAL;
+
+ /* addr/len must be page aligned. len should be non zero */
+ if (!len || (ALIGN((u64)addr, PAGE_SIZE) != (u64)addr) ||
+ (ALIGN(len, PAGE_SIZE) != len))
+ return -EINVAL;
+
+ might_sleep();
+
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ /* Compute the offset for this registration */
+ err = scif_get_window_offset(ep, map_flags, offset,
+ len >> PAGE_SHIFT, &computed_offset);
+ if (err)
+ return err;
+
+ spdev = scif_get_peer_dev(ep->remote_dev);
+ if (IS_ERR(spdev)) {
+ err = PTR_ERR(spdev);
+ scif_free_window_offset(ep, NULL, computed_offset);
+ return err;
+ }
+ /* Allocate and prepare self registration window */
+ window = scif_create_window(ep, len >> PAGE_SHIFT,
+ computed_offset, false);
+ if (!window) {
+ scif_free_window_offset(ep, NULL, computed_offset);
+ scif_put_peer_dev(spdev);
+ return -ENOMEM;
+ }
+
+ window->nr_pages = len >> PAGE_SHIFT;
+
+ err = scif_send_alloc_request(ep, window);
+ if (err) {
+ scif_destroy_incomplete_window(ep, window);
+ scif_put_peer_dev(spdev);
+ return err;
+ }
+
+ if (!(map_flags & SCIF_MAP_KERNEL)) {
+ mm = __scif_acquire_mm();
+ map_flags |= SCIF_MAP_ULIMIT;
+ }
+ /* Pin down the pages */
+ err = __scif_pin_pages(addr, len, &prot,
+ map_flags & (SCIF_MAP_KERNEL | SCIF_MAP_ULIMIT),
+ &pinned_pages);
+ if (err) {
+ scif_destroy_incomplete_window(ep, window);
+ __scif_release_mm(mm);
+ goto error;
+ }
+
+ window->pinned_pages = pinned_pages;
+ window->prot = pinned_pages->prot;
+ window->mm = mm;
+
+ /* Prepare the remote registration window */
+ err = scif_prep_remote_window(ep, window);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %ld\n", __func__, __LINE__, err);
+ goto error_unmap;
+ }
+
+ /* Tell the peer about the new window */
+ err = scif_send_scif_register(ep, window);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %ld\n", __func__, __LINE__, err);
+ goto error_unmap;
+ }
+
+ scif_put_peer_dev(spdev);
+ /* No further failures expected. Insert new window */
+ scif_insert_local_window(window, ep);
+ dev_dbg(&ep->remote_dev->sdev->dev,
+ "SCIFAPI register: ep %p addr %p len 0x%lx computed_offset 0x%llx\n",
+ epd, addr, len, computed_offset);
+ return computed_offset;
+error_unmap:
+ scif_destroy_window(ep, window);
+error:
+ scif_put_peer_dev(spdev);
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %ld\n", __func__, __LINE__, err);
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_register);
+
+int
+scif_unregister(scif_epd_t epd, off_t offset, size_t len)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct scif_window *window = NULL;
+ struct scif_rma_req req;
+ int nr_pages, err;
+ struct device *spdev;
+
+ dev_dbg(scif_info.mdev.this_device,
+ "SCIFAPI unregister: ep %p offset 0x%lx len 0x%lx\n",
+ ep, offset, len);
+ /* len must be page aligned. len should be non zero */
+ if (!len ||
+ (ALIGN((u64)len, PAGE_SIZE) != (u64)len))
+ return -EINVAL;
+
+ /* Offset is not page aligned or offset+len wraps around */
+ if ((ALIGN(offset, PAGE_SIZE) != offset) ||
+ (offset + (off_t)len < offset))
+ return -EINVAL;
+
+ err = scif_verify_epd(ep);
+ if (err)
+ return err;
+
+ might_sleep();
+ nr_pages = len >> PAGE_SHIFT;
+
+ req.out_window = &window;
+ req.offset = offset;
+ req.prot = 0;
+ req.nr_bytes = len;
+ req.type = SCIF_WINDOW_FULL;
+ req.head = &ep->rma_info.reg_list;
+
+ spdev = scif_get_peer_dev(ep->remote_dev);
+ if (IS_ERR(spdev)) {
+ err = PTR_ERR(spdev);
+ return err;
+ }
+ mutex_lock(&ep->rma_info.rma_lock);
+ /* Does a valid window exist? */
+ err = scif_query_window(&req);
+ if (err) {
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+ goto error;
+ }
+ /* Unregister all the windows in this range */
+ err = scif_rma_list_unregister(window, offset, nr_pages);
+ if (err)
+ dev_err(&ep->remote_dev->sdev->dev,
+ "%s %d err %d\n", __func__, __LINE__, err);
+error:
+ mutex_unlock(&ep->rma_info.rma_lock);
+ scif_put_peer_dev(spdev);
+ return err;
+}
+EXPORT_SYMBOL_GPL(scif_unregister);
diff --git a/drivers/misc/mic/scif/scif_rma.h b/drivers/misc/mic/scif/scif_rma.h
new file mode 100644
index 000000000000..fa6722279196
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_rma.h
@@ -0,0 +1,464 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * 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 Corporation.
+ *
+ * This program 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.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 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.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#ifndef SCIF_RMA_H
+#define SCIF_RMA_H
+
+#include <linux/dma_remapping.h>
+#include <linux/mmu_notifier.h>
+
+#include "../bus/scif_bus.h"
+
+/* If this bit is set then the mark is a remote fence mark */
+#define SCIF_REMOTE_FENCE_BIT 31
+/* Magic value used to indicate a remote fence request */
+#define SCIF_REMOTE_FENCE BIT_ULL(SCIF_REMOTE_FENCE_BIT)
+
+#define SCIF_MAX_UNALIGNED_BUF_SIZE (1024 * 1024ULL)
+#define SCIF_KMEM_UNALIGNED_BUF_SIZE (SCIF_MAX_UNALIGNED_BUF_SIZE + \
+ (L1_CACHE_BYTES << 1))
+
+#define SCIF_IOVA_START_PFN (1)
+#define SCIF_IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
+#define SCIF_DMA_64BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(64))
+#define SCIF_DMA_63BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(63))
+
+/*
+ * struct scif_endpt_rma_info - Per Endpoint Remote Memory Access Information
+ *
+ * @reg_list: List of registration windows for self
+ * @remote_reg_list: List of registration windows for peer
+ * @iovad: Offset generator
+ * @rma_lock: Synchronizes access to self/remote list and also protects the
+ * window from being destroyed while RMAs are in progress.
+ * @tc_lock: Synchronizes access to temporary cached windows list
+ * for SCIF Registration Caching.
+ * @mmn_lock: Synchronizes access to the list of MMU notifiers registered
+ * @tw_refcount: Keeps track of number of outstanding temporary registered
+ * windows created by scif_vreadfrom/scif_vwriteto which have
+ * not been destroyed.
+ * @tcw_refcount: Same as tw_refcount but for temporary cached windows
+ * @tcw_total_pages: Same as tcw_refcount but in terms of pages pinned
+ * @mmn_list: MMU notifier so that we can destroy the windows when required
+ * @fence_refcount: Keeps track of number of outstanding remote fence
+ * requests which have been received by the peer.
+ * @dma_chan: DMA channel used for all DMA transfers for this endpoint.
+ * @async_list_del: Detect asynchronous list entry deletion
+ * @vma_list: List of vmas with remote memory mappings
+ * @markwq: Wait queue used for scif_fence_mark/scif_fence_wait
+*/
+struct scif_endpt_rma_info {
+ struct list_head reg_list;
+ struct list_head remote_reg_list;
+ struct iova_domain iovad;
+ struct mutex rma_lock;
+ spinlock_t tc_lock;
+ struct mutex mmn_lock;
+ atomic_t tw_refcount;
+ atomic_t tcw_refcount;
+ atomic_t tcw_total_pages;
+ struct list_head mmn_list;
+ atomic_t fence_refcount;
+ struct dma_chan *dma_chan;
+ int async_list_del;
+ struct list_head vma_list;
+ wait_queue_head_t markwq;
+};
+
+/*
+ * struct scif_fence_info - used for tracking fence requests
+ *
+ * @state: State of this transfer
+ * @wq: Fences wait on this queue
+ * @dma_mark: Used for storing the DMA mark
+ */
+struct scif_fence_info {
+ enum scif_msg_state state;
+ struct completion comp;
+ int dma_mark;
+};
+
+/*
+ * struct scif_remote_fence_info - used for tracking remote fence requests
+ *
+ * @msg: List of SCIF node QP fence messages
+ * @list: Link to list of remote fence requests
+ */
+struct scif_remote_fence_info {
+ struct scifmsg msg;
+ struct list_head list;
+};
+
+/*
+ * Specifies whether an RMA operation can span across partial windows, a single
+ * window or multiple contiguous windows. Mmaps can span across partial windows.
+ * Unregistration can span across complete windows. scif_get_pages() can span a
+ * single window. A window can also be of type self or peer.
+ */
+enum scif_window_type {
+ SCIF_WINDOW_PARTIAL,
+ SCIF_WINDOW_SINGLE,
+ SCIF_WINDOW_FULL,
+ SCIF_WINDOW_SELF,
+ SCIF_WINDOW_PEER
+};
+
+/* The number of physical addresses that can be stored in a PAGE. */
+#define SCIF_NR_ADDR_IN_PAGE (0x1000 >> 3)
+
+/*
+ * struct scif_rma_lookup - RMA lookup data structure for page list transfers
+ *
+ * Store an array of lookup offsets. Each offset in this array maps
+ * one 4K page containing 512 physical addresses i.e. 2MB. 512 such
+ * offsets in a 4K page will correspond to 1GB of registered address space.
+
+ * @lookup: Array of offsets
+ * @offset: DMA offset of lookup array
+ */
+struct scif_rma_lookup {
+ dma_addr_t *lookup;
+ dma_addr_t offset;
+};
+
+/*
+ * struct scif_pinned_pages - A set of pinned pages obtained with
+ * scif_pin_pages() which could be part of multiple registered
+ * windows across different end points.
+ *
+ * @nr_pages: Number of pages which is defined as a s64 instead of an int
+ * to avoid sign extension with buffers >= 2GB
+ * @prot: read/write protections
+ * @map_flags: Flags specified during the pin operation
+ * @ref_count: Reference count bumped in terms of number of pages
+ * @magic: A magic value
+ * @pages: Array of pointers to struct pages populated with get_user_pages(..)
+ */
+struct scif_pinned_pages {
+ s64 nr_pages;
+ int prot;
+ int map_flags;
+ atomic_t ref_count;
+ u64 magic;
+ struct page **pages;
+};
+
+/*
+ * struct scif_status - Stores DMA status update information
+ *
+ * @src_dma_addr: Source buffer DMA address
+ * @val: src location for value to be written to the destination
+ * @ep: SCIF endpoint
+ */
+struct scif_status {
+ dma_addr_t src_dma_addr;
+ u64 val;
+ struct scif_endpt *ep;
+};
+
+/*
+ * struct scif_window - Registration Window for Self and Remote
+ *
+ * @nr_pages: Number of pages which is defined as a s64 instead of an int
+ * to avoid sign extension with buffers >= 2GB
+ * @nr_contig_chunks: Number of contiguous physical chunks
+ * @prot: read/write protections
+ * @ref_count: reference count in terms of number of pages
+ * @magic: Cookie to detect corruption
+ * @offset: registered offset
+ * @va_for_temp: va address that this window represents
+ * @dma_mark: Used to determine if all DMAs against the window are done
+ * @ep: Pointer to EP. Useful for passing EP around with messages to
+ avoid expensive list traversals.
+ * @list: link to list of windows for the endpoint
+ * @type: self or peer window
+ * @peer_window: Pointer to peer window. Useful for sending messages to peer
+ * without requiring an extra list traversal
+ * @unreg_state: unregistration state
+ * @offset_freed: True if the offset has been freed
+ * @temp: True for temporary windows created via scif_vreadfrom/scif_vwriteto
+ * @mm: memory descriptor for the task_struct which initiated the RMA
+ * @st: scatter gather table for DMA mappings with IOMMU enabled
+ * @pinned_pages: The set of pinned_pages backing this window
+ * @alloc_handle: Handle for sending ALLOC_REQ
+ * @regwq: Wait Queue for an registration (N)ACK
+ * @reg_state: Registration state
+ * @unregwq: Wait Queue for an unregistration (N)ACK
+ * @dma_addr_lookup: Lookup for physical addresses used for DMA
+ * @nr_lookup: Number of entries in lookup
+ * @mapped_offset: Offset used to map the window by the peer
+ * @dma_addr: Array of physical addresses used for Mgmt node & MIC initiated DMA
+ * @num_pages: Array specifying number of pages for each physical address
+ */
+struct scif_window {
+ s64 nr_pages;
+ int nr_contig_chunks;
+ int prot;
+ int ref_count;
+ u64 magic;
+ s64 offset;
+ unsigned long va_for_temp;
+ int dma_mark;
+ u64 ep;
+ struct list_head list;
+ enum scif_window_type type;
+ u64 peer_window;
+ enum scif_msg_state unreg_state;
+ bool offset_freed;
+ bool temp;
+ struct mm_struct *mm;
+ struct sg_table *st;
+ union {
+ struct {
+ struct scif_pinned_pages *pinned_pages;
+ struct scif_allocmsg alloc_handle;
+ wait_queue_head_t regwq;
+ enum scif_msg_state reg_state;
+ wait_queue_head_t unregwq;
+ };
+ struct {
+ struct scif_rma_lookup dma_addr_lookup;
+ struct scif_rma_lookup num_pages_lookup;
+ int nr_lookup;
+ dma_addr_t mapped_offset;
+ };
+ };
+ dma_addr_t *dma_addr;
+ u64 *num_pages;
+} __packed;
+
+/*
+ * scif_mmu_notif - SCIF mmu notifier information
+ *
+ * @mmu_notifier ep_mmu_notifier: MMU notifier operations
+ * @tc_reg_list: List of temp registration windows for self
+ * @mm: memory descriptor for the task_struct which initiated the RMA
+ * @ep: SCIF endpoint
+ * @list: link to list of MMU notifier information
+ */
+struct scif_mmu_notif {
+#ifdef CONFIG_MMU_NOTIFIER
+ struct mmu_notifier ep_mmu_notifier;
+#endif
+ struct list_head tc_reg_list;
+ struct mm_struct *mm;
+ struct scif_endpt *ep;
+ struct list_head list;
+};
+
+enum scif_rma_dir {
+ SCIF_LOCAL_TO_REMOTE,
+ SCIF_REMOTE_TO_LOCAL
+};
+
+extern struct kmem_cache *unaligned_cache;
+/* Initialize RMA for this EP */
+void scif_rma_ep_init(struct scif_endpt *ep);
+/* Check if epd can be uninitialized */
+int scif_rma_ep_can_uninit(struct scif_endpt *ep);
+/* Obtain a new offset. Callee must grab RMA lock */
+int scif_get_window_offset(struct scif_endpt *ep, int flags,
+ s64 offset, int nr_pages, s64 *out_offset);
+/* Free offset. Callee must grab RMA lock */
+void scif_free_window_offset(struct scif_endpt *ep,
+ struct scif_window *window, s64 offset);
+/* Create self registration window */
+struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
+ s64 offset, bool temp);
+/* Destroy self registration window.*/
+int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window);
+void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window *window);
+/* Map pages of self window to Aperture/PCI */
+int scif_map_window(struct scif_dev *remote_dev,
+ struct scif_window *window);
+/* Unregister a self window */
+int scif_unregister_window(struct scif_window *window);
+/* Destroy remote registration window */
+void
+scif_destroy_remote_window(struct scif_window *window);
+/* remove valid remote memory mappings from process address space */
+void scif_zap_mmaps(int node);
+/* Query if any applications have remote memory mappings */
+bool scif_rma_do_apps_have_mmaps(int node);
+/* Cleanup remote registration lists for zombie endpoints */
+void scif_cleanup_rma_for_zombies(int node);
+/* Reserve a DMA channel for a particular endpoint */
+int scif_reserve_dma_chan(struct scif_endpt *ep);
+/* Setup a DMA mark for an endpoint */
+int _scif_fence_mark(scif_epd_t epd, int *mark);
+int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
+ enum scif_window_type type);
+void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg);
+void scif_mmu_notif_handler(struct work_struct *work);
+void scif_rma_handle_remote_fences(void);
+void scif_rma_destroy_windows(void);
+void scif_rma_destroy_tcw_invalid(void);
+int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan);
+
+struct scif_window_iter {
+ s64 offset;
+ int index;
+};
+
+static inline void
+scif_init_window_iter(struct scif_window *window, struct scif_window_iter *iter)
+{
+ iter->offset = window->offset;
+ iter->index = 0;
+}
+
+dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
+ size_t *nr_bytes,
+ struct scif_window_iter *iter);
+static inline
+dma_addr_t __scif_off_to_dma_addr(struct scif_window *window, s64 off)
+{
+ return scif_off_to_dma_addr(window, off, NULL, NULL);
+}
+
+static inline bool scif_unaligned(off_t src_offset, off_t dst_offset)
+{
+ src_offset = src_offset & (L1_CACHE_BYTES - 1);
+ dst_offset = dst_offset & (L1_CACHE_BYTES - 1);
+ return !(src_offset == dst_offset);
+}
+
+/*
+ * scif_zalloc:
+ * @size: Size of the allocation request.
+ *
+ * Helper API which attempts to allocate zeroed pages via
+ * __get_free_pages(..) first and then falls back on
+ * vzalloc(..) if that fails.
+ */
+static inline void *scif_zalloc(size_t size)
+{
+ void *ret = NULL;
+ size_t align = ALIGN(size, PAGE_SIZE);
+
+ if (align && get_order(align) < MAX_ORDER)
+ ret = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(align));
+ return ret ? ret : vzalloc(align);
+}
+
+/*
+ * scif_free:
+ * @addr: Address to be freed.
+ * @size: Size of the allocation.
+ * Helper API which frees memory allocated via scif_zalloc().
+ */
+static inline void scif_free(void *addr, size_t size)
+{
+ size_t align = ALIGN(size, PAGE_SIZE);
+
+ if (is_vmalloc_addr(addr))
+ vfree(addr);
+ else
+ free_pages((unsigned long)addr, get_order(align));
+}
+
+static inline void scif_get_window(struct scif_window *window, int nr_pages)
+{
+ window->ref_count += nr_pages;
+}
+
+static inline void scif_put_window(struct scif_window *window, int nr_pages)
+{
+ window->ref_count -= nr_pages;
+}
+
+static inline void scif_set_window_ref(struct scif_window *window, int nr_pages)
+{
+ window->ref_count = nr_pages;
+}
+
+static inline void
+scif_queue_for_cleanup(struct scif_window *window, struct list_head *list)
+{
+ spin_lock(&scif_info.rmalock);
+ list_add_tail(&window->list, list);
+ spin_unlock(&scif_info.rmalock);
+ schedule_work(&scif_info.misc_work);
+}
+
+static inline void __scif_rma_destroy_tcw_helper(struct scif_window *window)
+{
+ list_del_init(&window->list);
+ scif_queue_for_cleanup(window, &scif_info.rma_tc);
+}
+
+static inline bool scif_is_iommu_enabled(void)
+{
+#ifdef CONFIG_INTEL_IOMMU
+ return intel_iommu_enabled;
+#else
+ return false;
+#endif
+}
+#endif /* SCIF_RMA_H */
diff --git a/drivers/misc/mic/scif/scif_rma_list.c b/drivers/misc/mic/scif/scif_rma_list.c
new file mode 100644
index 000000000000..e1ef8daedd5a
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_rma_list.c
@@ -0,0 +1,291 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#include "scif_main.h"
+#include <linux/mmu_notifier.h>
+#include <linux/highmem.h>
+
+/*
+ * scif_insert_tcw:
+ *
+ * Insert a temp window to the temp registration list sorted by va_for_temp.
+ * RMA lock must be held.
+ */
+void scif_insert_tcw(struct scif_window *window, struct list_head *head)
+{
+ struct scif_window *curr = NULL;
+ struct scif_window *prev = list_entry(head, struct scif_window, list);
+ struct list_head *item;
+
+ INIT_LIST_HEAD(&window->list);
+ /* Compare with tail and if the entry is new tail add it to the end */
+ if (!list_empty(head)) {
+ curr = list_entry(head->prev, struct scif_window, list);
+ if (curr->va_for_temp < window->va_for_temp) {
+ list_add_tail(&window->list, head);
+ return;
+ }
+ }
+ list_for_each(item, head) {
+ curr = list_entry(item, struct scif_window, list);
+ if (curr->va_for_temp > window->va_for_temp)
+ break;
+ prev = curr;
+ }
+ list_add(&window->list, &prev->list);
+}
+
+/*
+ * scif_insert_window:
+ *
+ * Insert a window to the self registration list sorted by offset.
+ * RMA lock must be held.
+ */
+void scif_insert_window(struct scif_window *window, struct list_head *head)
+{
+ struct scif_window *curr = NULL, *prev = NULL;
+ struct list_head *item;
+
+ INIT_LIST_HEAD(&window->list);
+ list_for_each(item, head) {
+ curr = list_entry(item, struct scif_window, list);
+ if (curr->offset > window->offset)
+ break;
+ prev = curr;
+ }
+ if (!prev)
+ list_add(&window->list, head);
+ else
+ list_add(&window->list, &prev->list);
+ scif_set_window_ref(window, window->nr_pages);
+}
+
+/*
+ * scif_query_tcw:
+ *
+ * Query the temp cached registration list of ep for an overlapping window
+ * in case of permission mismatch, destroy the previous window. if permissions
+ * match and overlap is partial, destroy the window but return the new range
+ * RMA lock must be held.
+ */
+int scif_query_tcw(struct scif_endpt *ep, struct scif_rma_req *req)
+{
+ struct list_head *item, *temp, *head = req->head;
+ struct scif_window *window;
+ u64 start_va_window, start_va_req = req->va_for_temp;
+ u64 end_va_window, end_va_req = start_va_req + req->nr_bytes;
+
+ if (!req->nr_bytes)
+ return -EINVAL;
+ /*
+ * Avoid traversing the entire list to find out that there
+ * is no entry that matches
+ */
+ if (!list_empty(head)) {
+ window = list_last_entry(head, struct scif_window, list);
+ end_va_window = window->va_for_temp +
+ (window->nr_pages << PAGE_SHIFT);
+ if (start_va_req > end_va_window)
+ return -ENXIO;
+ }
+ list_for_each_safe(item, temp, head) {
+ window = list_entry(item, struct scif_window, list);
+ start_va_window = window->va_for_temp;
+ end_va_window = window->va_for_temp +
+ (window->nr_pages << PAGE_SHIFT);
+ if (start_va_req < start_va_window &&
+ end_va_req < start_va_window)
+ break;
+ if (start_va_req >= end_va_window)
+ continue;
+ if ((window->prot & req->prot) == req->prot) {
+ if (start_va_req >= start_va_window &&
+ end_va_req <= end_va_window) {
+ *req->out_window = window;
+ return 0;
+ }
+ /* expand window */
+ if (start_va_req < start_va_window) {
+ req->nr_bytes +=
+ start_va_window - start_va_req;
+ req->va_for_temp = start_va_window;
+ }
+ if (end_va_req >= end_va_window)
+ req->nr_bytes += end_va_window - end_va_req;
+ }
+ /* Destroy the old window to create a new one */
+ __scif_rma_destroy_tcw_helper(window);
+ break;
+ }
+ return -ENXIO;
+}
+
+/*
+ * scif_query_window:
+ *
+ * Query the registration list and check if a valid contiguous
+ * range of windows exist.
+ * RMA lock must be held.
+ */
+int scif_query_window(struct scif_rma_req *req)
+{
+ struct list_head *item;
+ struct scif_window *window;
+ s64 end_offset, offset = req->offset;
+ u64 tmp_min, nr_bytes_left = req->nr_bytes;
+
+ if (!req->nr_bytes)
+ return -EINVAL;
+
+ list_for_each(item, req->head) {
+ window = list_entry(item, struct scif_window, list);
+ end_offset = window->offset +
+ (window->nr_pages << PAGE_SHIFT);
+ if (offset < window->offset)
+ /* Offset not found! */
+ return -ENXIO;
+ if (offset >= end_offset)
+ continue;
+ /* Check read/write protections. */
+ if ((window->prot & req->prot) != req->prot)
+ return -EPERM;
+ if (nr_bytes_left == req->nr_bytes)
+ /* Store the first window */
+ *req->out_window = window;
+ tmp_min = min((u64)end_offset - offset, nr_bytes_left);
+ nr_bytes_left -= tmp_min;
+ offset += tmp_min;
+ /*
+ * Range requested encompasses
+ * multiple windows contiguously.
+ */
+ if (!nr_bytes_left) {
+ /* Done for partial window */
+ if (req->type == SCIF_WINDOW_PARTIAL ||
+ req->type == SCIF_WINDOW_SINGLE)
+ return 0;
+ /* Extra logic for full windows */
+ if (offset == end_offset)
+ /* Spanning multiple whole windows */
+ return 0;
+ /* Not spanning multiple whole windows */
+ return -ENXIO;
+ }
+ if (req->type == SCIF_WINDOW_SINGLE)
+ break;
+ }
+ dev_err(scif_info.mdev.this_device,
+ "%s %d ENXIO\n", __func__, __LINE__);
+ return -ENXIO;
+}
+
+/*
+ * scif_rma_list_unregister:
+ *
+ * Traverse the self registration list starting from window:
+ * 1) Call scif_unregister_window(..)
+ * RMA lock must be held.
+ */
+int scif_rma_list_unregister(struct scif_window *window,
+ s64 offset, int nr_pages)
+{
+ struct scif_endpt *ep = (struct scif_endpt *)window->ep;
+ struct list_head *head = &ep->rma_info.reg_list;
+ s64 end_offset;
+ int err = 0;
+ int loop_nr_pages;
+ struct scif_window *_window;
+
+ list_for_each_entry_safe_from(window, _window, head, list) {
+ end_offset = window->offset + (window->nr_pages << PAGE_SHIFT);
+ loop_nr_pages = min((int)((end_offset - offset) >> PAGE_SHIFT),
+ nr_pages);
+ err = scif_unregister_window(window);
+ if (err)
+ return err;
+ nr_pages -= loop_nr_pages;
+ offset += (loop_nr_pages << PAGE_SHIFT);
+ if (!nr_pages)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * scif_unmap_all_window:
+ *
+ * Traverse all the windows in the self registration list and:
+ * 1) Delete any DMA mappings created
+ */
+void scif_unmap_all_windows(scif_epd_t epd)
+{
+ struct list_head *item, *tmp;
+ struct scif_window *window;
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct list_head *head = &ep->rma_info.reg_list;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+ list_for_each_safe(item, tmp, head) {
+ window = list_entry(item, struct scif_window, list);
+ scif_unmap_window(ep->remote_dev, window);
+ }
+ mutex_unlock(&ep->rma_info.rma_lock);
+}
+
+/*
+ * scif_unregister_all_window:
+ *
+ * Traverse all the windows in the self registration list and:
+ * 1) Call scif_unregister_window(..)
+ * RMA lock must be held.
+ */
+int scif_unregister_all_windows(scif_epd_t epd)
+{
+ struct list_head *item, *tmp;
+ struct scif_window *window;
+ struct scif_endpt *ep = (struct scif_endpt *)epd;
+ struct list_head *head = &ep->rma_info.reg_list;
+ int err = 0;
+
+ mutex_lock(&ep->rma_info.rma_lock);
+retry:
+ item = NULL;
+ tmp = NULL;
+ list_for_each_safe(item, tmp, head) {
+ window = list_entry(item, struct scif_window, list);
+ ep->rma_info.async_list_del = 0;
+ err = scif_unregister_window(window);
+ if (err)
+ dev_err(scif_info.mdev.this_device,
+ "%s %d err %d\n",
+ __func__, __LINE__, err);
+ /*
+ * Need to restart list traversal if there has been
+ * an asynchronous list entry deletion.
+ */
+ if (ACCESS_ONCE(ep->rma_info.async_list_del))
+ goto retry;
+ }
+ mutex_unlock(&ep->rma_info.rma_lock);
+ if (!list_empty(&ep->rma_info.mmn_list)) {
+ spin_lock(&scif_info.rmalock);
+ list_add_tail(&ep->mmu_list, &scif_info.mmu_notif_cleanup);
+ spin_unlock(&scif_info.rmalock);
+ schedule_work(&scif_info.mmu_notif_work);
+ }
+ return err;
+}
diff --git a/drivers/misc/mic/scif/scif_rma_list.h b/drivers/misc/mic/scif/scif_rma_list.h
new file mode 100644
index 000000000000..7d58d1d551b0
--- /dev/null
+++ b/drivers/misc/mic/scif/scif_rma_list.h
@@ -0,0 +1,57 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#ifndef SCIF_RMA_LIST_H
+#define SCIF_RMA_LIST_H
+
+/*
+ * struct scif_rma_req - Self Registration list RMA Request query
+ *
+ * @out_window - Returns the window if found
+ * @offset: Starting offset
+ * @nr_bytes: number of bytes
+ * @prot: protection requested i.e. read or write or both
+ * @type: Specify single, partial or multiple windows
+ * @head: Head of list on which to search
+ * @va_for_temp: VA for searching temporary cached windows
+ */
+struct scif_rma_req {
+ struct scif_window **out_window;
+ union {
+ s64 offset;
+ unsigned long va_for_temp;
+ };
+ size_t nr_bytes;
+ int prot;
+ enum scif_window_type type;
+ struct list_head *head;
+};
+
+/* Insert */
+void scif_insert_window(struct scif_window *window, struct list_head *head);
+void scif_insert_tcw(struct scif_window *window,
+ struct list_head *head);
+/* Query */
+int scif_query_window(struct scif_rma_req *request);
+int scif_query_tcw(struct scif_endpt *ep, struct scif_rma_req *request);
+/* Called from close to unregister all self windows */
+int scif_unregister_all_windows(scif_epd_t epd);
+void scif_unmap_all_windows(scif_epd_t epd);
+/* Traverse list and unregister */
+int scif_rma_list_unregister(struct scif_window *window, s64 offset,
+ int nr_pages);
+#endif /* SCIF_RMA_LIST_H */
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
index 2f30badc6ffd..1ee8e82ba710 100644
--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -196,12 +196,6 @@ void tfh_write_restart(struct gru_tlb_fault_handle *tfh,
start_instruction(tfh);
}
-void tfh_restart(struct gru_tlb_fault_handle *tfh)
-{
- tfh->opc = TFHOP_RESTART;
- start_instruction(tfh);
-}
-
void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh)
{
tfh->opc = TFHOP_USER_POLLING_MODE;
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index 3f998b924d8f..3d7bd36a1c89 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -524,7 +524,6 @@ int tfh_write_only(struct gru_tlb_fault_handle *tfh, unsigned long paddr,
int gaa, unsigned long vaddr, int asid, int dirty, int pagesize);
void tfh_write_restart(struct gru_tlb_fault_handle *tfh, unsigned long paddr,
int gaa, unsigned long vaddr, int asid, int dirty, int pagesize);
-void tfh_restart(struct gru_tlb_fault_handle *tfh);
void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh);
void tfh_exception(struct gru_tlb_fault_handle *tfh);
diff --git a/drivers/misc/sgi-gru/grukdump.c b/drivers/misc/sgi-gru/grukdump.c
index a3700a56b8ff..313da3150262 100644
--- a/drivers/misc/sgi-gru/grukdump.c
+++ b/drivers/misc/sgi-gru/grukdump.c
@@ -78,11 +78,10 @@ static int gru_dump_tfm(struct gru_state *gru,
void __user *ubuf, void __user *ubufend)
{
struct gru_tlb_fault_map *tfm;
- int i, ret, bytes;
+ int i;
- bytes = GRU_NUM_TFM * GRU_CACHE_LINE_BYTES;
- if (bytes > ubufend - ubuf)
- ret = -EFBIG;
+ if (GRU_NUM_TFM * GRU_CACHE_LINE_BYTES > ubufend - ubuf)
+ return -EFBIG;
for (i = 0; i < GRU_NUM_TFM; i++) {
tfm = get_tfm(gru->gs_gru_base_vaddr, i);
@@ -99,11 +98,10 @@ static int gru_dump_tgh(struct gru_state *gru,
void __user *ubuf, void __user *ubufend)
{
struct gru_tlb_global_handle *tgh;
- int i, ret, bytes;
+ int i;
- bytes = GRU_NUM_TGH * GRU_CACHE_LINE_BYTES;
- if (bytes > ubufend - ubuf)
- ret = -EFBIG;
+ if (GRU_NUM_TGH * GRU_CACHE_LINE_BYTES > ubufend - ubuf)
+ return -EFBIG;
for (i = 0; i < GRU_NUM_TGH; i++) {
tgh = get_tgh(gru->gs_gru_base_vaddr, i);
@@ -196,7 +194,7 @@ int gru_dump_chiplet_request(unsigned long arg)
return -EFAULT;
/* Currently, only dump by gid is implemented */
- if (req.gid >= gru_max_gids || req.gid < 0)
+ if (req.gid >= gru_max_gids)
return -EINVAL;
gru = GID_TO_GRU(req.gid);
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 913de07e577c..967b9dd24fe9 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -160,7 +160,12 @@ static void gru_load_kernel_context(struct gru_blade_state *bs, int blade_id)
down_write(&bs->bs_kgts_sema);
if (!bs->bs_kgts) {
- bs->bs_kgts = gru_alloc_gts(NULL, 0, 0, 0, 0, 0);
+ do {
+ bs->bs_kgts = gru_alloc_gts(NULL, 0, 0, 0, 0, 0);
+ if (!IS_ERR(bs->bs_kgts))
+ break;
+ msleep(1);
+ } while (true);
bs->bs_kgts->ts_user_blade_id = blade_id;
}
kgts = bs->bs_kgts;
@@ -429,8 +434,8 @@ int gru_get_cb_exception_detail(void *cb,
return 0;
}
-char *gru_get_cb_exception_detail_str(int ret, void *cb,
- char *buf, int size)
+static char *gru_get_cb_exception_detail_str(int ret, void *cb,
+ char *buf, int size)
{
struct gru_control_block_status *gen = (void *)cb;
struct control_block_extended_exc_detail excdet;
@@ -505,7 +510,7 @@ int gru_wait_proc(void *cb)
return ret;
}
-void gru_abort(int ret, void *cb, char *str)
+static void gru_abort(int ret, void *cb, char *str)
{
char buf[GRU_EXC_STR_SIZE];
@@ -997,7 +1002,6 @@ static int quicktest1(unsigned long arg)
{
struct gru_message_queue_desc mqd;
void *p, *mq;
- unsigned long *dw;
int i, ret = -EIO;
char mes[GRU_CACHE_LINE_BYTES], *m;
@@ -1007,7 +1011,6 @@ static int quicktest1(unsigned long arg)
return -ENOMEM;
mq = ALIGNUP(p, 1024);
memset(mes, 0xee, sizeof(mes));
- dw = mq;
gru_create_message_queue(&mqd, mq, 8 * GRU_CACHE_LINE_BYTES, 0, 0, 0);
for (i = 0; i < 6; i++) {
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index ae16c8cb4f3e..1525870f460a 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -930,6 +930,7 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct gru_thread_state *gts;
unsigned long paddr, vaddr;
+ unsigned long expires;
vaddr = (unsigned long)vmf->virtual_address;
gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
@@ -954,7 +955,8 @@ again:
mutex_unlock(&gts->ts_ctxlock);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */
- if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies)
+ expires = gts->ts_steal_jiffies + GRU_STEAL_DELAY;
+ if (time_before(expires, jiffies))
gru_steal_context(gts);
goto again;
}
diff --git a/drivers/misc/sgi-gru/grutlbpurge.c b/drivers/misc/sgi-gru/grutlbpurge.c
index 2129274ef7ab..e936d43895d2 100644
--- a/drivers/misc/sgi-gru/grutlbpurge.c
+++ b/drivers/misc/sgi-gru/grutlbpurge.c
@@ -306,19 +306,20 @@ struct gru_mm_struct *gru_register_mmu_notifier(void)
atomic_inc(&gms->ms_refcnt);
} else {
gms = kzalloc(sizeof(*gms), GFP_KERNEL);
- if (gms) {
- STAT(gms_alloc);
- spin_lock_init(&gms->ms_asid_lock);
- gms->ms_notifier.ops = &gru_mmuops;
- atomic_set(&gms->ms_refcnt, 1);
- init_waitqueue_head(&gms->ms_wait_queue);
- err = __mmu_notifier_register(&gms->ms_notifier, current->mm);
- if (err)
- goto error;
- }
+ if (!gms)
+ return ERR_PTR(-ENOMEM);
+ STAT(gms_alloc);
+ spin_lock_init(&gms->ms_asid_lock);
+ gms->ms_notifier.ops = &gru_mmuops;
+ atomic_set(&gms->ms_refcnt, 1);
+ init_waitqueue_head(&gms->ms_wait_queue);
+ err = __mmu_notifier_register(&gms->ms_notifier, current->mm);
+ if (err)
+ goto error;
}
- gru_dbg(grudev, "gms %p, refcnt %d\n", gms,
- atomic_read(&gms->ms_refcnt));
+ if (gms)
+ gru_dbg(grudev, "gms %p, refcnt %d\n", gms,
+ atomic_read(&gms->ms_refcnt));
return gms;
error:
kfree(gms);
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
index b8374cdaf9c9..ee120dcbb3e6 100644
--- a/drivers/misc/spear13xx_pcie_gadget.c
+++ b/drivers/misc/spear13xx_pcie_gadget.c
@@ -220,11 +220,17 @@ static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
/*
* configfs interfaces show/store functions
*/
-static ssize_t pcie_gadget_show_link(
- struct spear_pcie_gadget_config *config,
- char *buf)
+
+static struct pcie_gadget_target *to_target(struct config_item *item)
{
- struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+ return item ?
+ container_of(to_configfs_subsystem(to_config_group(item)),
+ struct pcie_gadget_target, subsys) : NULL;
+}
+
+static ssize_t pcie_gadget_link_show(struct config_item *item, char *buf)
+{
+ struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
return sprintf(buf, "UP");
@@ -232,11 +238,10 @@ static ssize_t pcie_gadget_show_link(
return sprintf(buf, "DOWN");
}
-static ssize_t pcie_gadget_store_link(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_link_store(struct config_item *item,
const char *buf, size_t count)
{
- struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+ struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
if (sysfs_streq(buf, "UP"))
writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
@@ -250,17 +255,15 @@ static ssize_t pcie_gadget_store_link(
return count;
}
-static ssize_t pcie_gadget_show_int_type(
- struct spear_pcie_gadget_config *config,
- char *buf)
+static ssize_t pcie_gadget_int_type_show(struct config_item *item, char *buf)
{
- return sprintf(buf, "%s", config->int_type);
+ return sprintf(buf, "%s", to_target(item)->int_type);
}
-static ssize_t pcie_gadget_store_int_type(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_int_type_store(struct config_item *item,
const char *buf, size_t count)
{
+ struct spear_pcie_gadget_config *config = to_target(item)
u32 cap, vec, flags;
ulong vector;
@@ -288,11 +291,10 @@ static ssize_t pcie_gadget_store_int_type(
return count;
}
-static ssize_t pcie_gadget_show_no_of_msi(
- struct spear_pcie_gadget_config *config,
- char *buf)
+static ssize_t pcie_gadget_no_of_msi_show(struct config_item *item, char *buf)
{
- struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+ struct spear_pcie_gadget_config *config = to_target(item)
+ struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
u32 cap, vec, flags;
ulong vector;
@@ -313,13 +315,12 @@ static ssize_t pcie_gadget_show_no_of_msi(
return sprintf(buf, "%lu", vector);
}
-static ssize_t pcie_gadget_store_no_of_msi(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_no_of_msi_store(struct config_item *item,
const char *buf, size_t count)
{
int ret;
- ret = kstrtoul(buf, 0, &config->requested_msi);
+ ret = kstrtoul(buf, 0, &to_target(item)->requested_msi);
if (ret)
return ret;
@@ -329,11 +330,10 @@ static ssize_t pcie_gadget_store_no_of_msi(
return count;
}
-static ssize_t pcie_gadget_store_inta(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_inta_store(struct config_item *item,
const char *buf, size_t count)
{
- struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+ struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
ulong en;
int ret;
@@ -351,10 +351,10 @@ static ssize_t pcie_gadget_store_inta(
return count;
}
-static ssize_t pcie_gadget_store_send_msi(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_send_msi_store(struct config_item *item,
const char *buf, size_t count)
{
+ struct spear_pcie_gadget_config *config = to_target(item)
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
ulong vector;
u32 ven_msi;
@@ -388,19 +388,16 @@ static ssize_t pcie_gadget_store_send_msi(
return count;
}
-static ssize_t pcie_gadget_show_vendor_id(
- struct spear_pcie_gadget_config *config,
- char *buf)
+static ssize_t pcie_gadget_vendor_id_show(struct config_item *item, char *buf)
{
u32 id;
- spear_dbi_read_reg(config, PCI_VENDOR_ID, 2, &id);
+ spear_dbi_read_reg(to_target(item), PCI_VENDOR_ID, 2, &id);
return sprintf(buf, "%x", id);
}
-static ssize_t pcie_gadget_store_vendor_id(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_vendor_id_store(struct config_item *item,
const char *buf, size_t count)
{
ulong id;
@@ -410,24 +407,21 @@ static ssize_t pcie_gadget_store_vendor_id(
if (ret)
return ret;
- spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
+ spear_dbi_write_reg(to_target(item), PCI_VENDOR_ID, 2, id);
return count;
}
-static ssize_t pcie_gadget_show_device_id(
- struct spear_pcie_gadget_config *config,
- char *buf)
+static ssize_t pcie_gadget_device_id_show(struct config_item *item, char *buf)
{
u32 id;
- spear_dbi_read_reg(config, PCI_DEVICE_ID, 2, &id);
+ spear_dbi_read_reg(to_target(item), PCI_DEVICE_ID, 2, &id);
return sprintf(buf, "%x", id);
}
-static ssize_t pcie_gadget_store_device_id(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_device_id_store(struct config_item *item,
const char *buf, size_t count)
{
ulong id;
@@ -437,22 +431,20 @@ static ssize_t pcie_gadget_store_device_id(
if (ret)
return ret;
- spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
+ spear_dbi_write_reg(to_target(item), PCI_DEVICE_ID, 2, id);
return count;
}
-static ssize_t pcie_gadget_show_bar0_size(
- struct spear_pcie_gadget_config *config,
- char *buf)
+static ssize_t pcie_gadget_bar0_size_show(struct config_item *item, char *buf)
{
- return sprintf(buf, "%lx", config->bar0_size);
+ return sprintf(buf, "%lx", to_target(item)->bar0_size);
}
-static ssize_t pcie_gadget_store_bar0_size(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_size_store(struct config_item *item,
const char *buf, size_t count)
{
+ struct spear_pcie_gadget_config *config = to_target(item)
ulong size;
u32 pos, pos1;
u32 no_of_bit = 0;
@@ -489,21 +481,20 @@ static ssize_t pcie_gadget_store_bar0_size(
return count;
}
-static ssize_t pcie_gadget_show_bar0_address(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_address_show(struct config_item *item,
char *buf)
{
- struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+ struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
u32 address = readl(&app_reg->pim0_mem_addr_start);
return sprintf(buf, "%x", address);
}
-static ssize_t pcie_gadget_store_bar0_address(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_address_store(struct config_item *item,
const char *buf, size_t count)
{
+ struct spear_pcie_gadget_config *config = to_target(item)
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
ulong address;
int ret;
@@ -524,15 +515,13 @@ static ssize_t pcie_gadget_store_bar0_address(
return count;
}
-static ssize_t pcie_gadget_show_bar0_rw_offset(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_rw_offset_show(struct config_item *item,
char *buf)
{
- return sprintf(buf, "%lx", config->bar0_rw_offset);
+ return sprintf(buf, "%lx", to_target(item)->bar0_rw_offset);
}
-static ssize_t pcie_gadget_store_bar0_rw_offset(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_rw_offset_store(struct config_item *item,
const char *buf, size_t count)
{
ulong offset;
@@ -545,15 +534,14 @@ static ssize_t pcie_gadget_store_bar0_rw_offset(
if (offset % 4)
return -EINVAL;
- config->bar0_rw_offset = offset;
+ to_target(item)->bar0_rw_offset = offset;
return count;
}
-static ssize_t pcie_gadget_show_bar0_data(
- struct spear_pcie_gadget_config *config,
- char *buf)
+static ssize_t pcie_gadget_bar0_data_show(struct config_item *item, char *buf)
{
+ struct spear_pcie_gadget_config *config = to_target(item)
ulong data;
if (!config->va_bar0_address)
@@ -564,10 +552,10 @@ static ssize_t pcie_gadget_show_bar0_data(
return sprintf(buf, "%lx", data);
}
-static ssize_t pcie_gadget_store_bar0_data(
- struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_data_store(struct config_item *item,
const char *buf, size_t count)
{
+ struct spear_pcie_gadget_config *config = to_target(item)
ulong data;
int ret;
@@ -583,97 +571,35 @@ static ssize_t pcie_gadget_store_bar0_data(
return count;
}
-/*
- * Attribute definitions.
- */
-
-#define PCIE_GADGET_TARGET_ATTR_RO(_name) \
-static struct pcie_gadget_target_attr pcie_gadget_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IRUGO, pcie_gadget_show_##_name, NULL)
-
-#define PCIE_GADGET_TARGET_ATTR_WO(_name) \
-static struct pcie_gadget_target_attr pcie_gadget_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IWUSR, NULL, pcie_gadget_store_##_name)
-
-#define PCIE_GADGET_TARGET_ATTR_RW(_name) \
-static struct pcie_gadget_target_attr pcie_gadget_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, pcie_gadget_show_##_name, \
- pcie_gadget_store_##_name)
-PCIE_GADGET_TARGET_ATTR_RW(link);
-PCIE_GADGET_TARGET_ATTR_RW(int_type);
-PCIE_GADGET_TARGET_ATTR_RW(no_of_msi);
-PCIE_GADGET_TARGET_ATTR_WO(inta);
-PCIE_GADGET_TARGET_ATTR_WO(send_msi);
-PCIE_GADGET_TARGET_ATTR_RW(vendor_id);
-PCIE_GADGET_TARGET_ATTR_RW(device_id);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_size);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_address);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_rw_offset);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_data);
+CONFIGFS_ATTR(pcie_gadget_, link);
+CONFIGFS_ATTR(pcie_gadget_, int_type);
+CONFIGFS_ATTR(pcie_gadget_, no_of_msi);
+CONFIGFS_ATTR_WO(pcie_gadget_, inta);
+CONFIGFS_ATTR_WO(pcie_gadget_, send_msi);
+CONFIGFS_ATTR(pcie_gadget_, vendor_id);
+CONFIGFS_ATTR(pcie_gadget_, device_id);
+CONFIGFS_ATTR(pcie_gadget_, bar0_size);
+CONFIGFS_ATTR(pcie_gadget_, bar0_address);
+CONFIGFS_ATTR(pcie_gadget_, bar0_rw_offset);
+CONFIGFS_ATTR(pcie_gadget_, bar0_data);
static struct configfs_attribute *pcie_gadget_target_attrs[] = {
- &pcie_gadget_target_link.attr,
- &pcie_gadget_target_int_type.attr,
- &pcie_gadget_target_no_of_msi.attr,
- &pcie_gadget_target_inta.attr,
- &pcie_gadget_target_send_msi.attr,
- &pcie_gadget_target_vendor_id.attr,
- &pcie_gadget_target_device_id.attr,
- &pcie_gadget_target_bar0_size.attr,
- &pcie_gadget_target_bar0_address.attr,
- &pcie_gadget_target_bar0_rw_offset.attr,
- &pcie_gadget_target_bar0_data.attr,
+ &pcie_gadget_attr_link,
+ &pcie_gadget_attr_int_type,
+ &pcie_gadget_attr_no_of_msi,
+ &pcie_gadget_attr_inta,
+ &pcie_gadget_attr_send_msi,
+ &pcie_gadget_attr_vendor_id,
+ &pcie_gadget_attr_device_id,
+ &pcie_gadget_attr_bar0_size,
+ &pcie_gadget_attr_bar0_address,
+ &pcie_gadget_attr_bar0_rw_offset,
+ &pcie_gadget_attr_bar0_data,
NULL,
};
-static struct pcie_gadget_target *to_target(struct config_item *item)
-{
- return item ?
- container_of(to_configfs_subsystem(to_config_group(item)),
- struct pcie_gadget_target, subsys) : NULL;
-}
-
-/*
- * Item operations and type for pcie_gadget_target.
- */
-
-static ssize_t pcie_gadget_target_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *buf)
-{
- ssize_t ret = -EINVAL;
- struct pcie_gadget_target *target = to_target(item);
- struct pcie_gadget_target_attr *t_attr =
- container_of(attr, struct pcie_gadget_target_attr, attr);
-
- if (t_attr->show)
- ret = t_attr->show(&target->config, buf);
- return ret;
-}
-
-static ssize_t pcie_gadget_target_attr_store(struct config_item *item,
- struct configfs_attribute *attr,
- const char *buf,
- size_t count)
-{
- ssize_t ret = -EINVAL;
- struct pcie_gadget_target *target = to_target(item);
- struct pcie_gadget_target_attr *t_attr =
- container_of(attr, struct pcie_gadget_target_attr, attr);
-
- if (t_attr->store)
- ret = t_attr->store(&target->config, buf, count);
- return ret;
-}
-
-static struct configfs_item_operations pcie_gadget_target_item_ops = {
- .show_attribute = pcie_gadget_target_attr_show,
- .store_attribute = pcie_gadget_target_attr_store,
-};
-
static struct config_item_type pcie_gadget_target_type = {
.ct_attrs = pcie_gadget_target_attrs,
- .ct_item_ops = &pcie_gadget_target_item_ops,
.ct_owner = THIS_MODULE,
};
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 431e1dd528bc..736dae715dbf 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -28,20 +28,144 @@
#define SRAM_GRANULARITY 32
+struct sram_partition {
+ void __iomem *base;
+
+ struct gen_pool *pool;
+ struct bin_attribute battr;
+ struct mutex lock;
+};
+
struct sram_dev {
struct device *dev;
void __iomem *virt_base;
struct gen_pool *pool;
struct clk *clk;
+
+ struct sram_partition *partition;
+ u32 partitions;
};
struct sram_reserve {
struct list_head list;
u32 start;
u32 size;
+ bool export;
+ bool pool;
+ const char *label;
};
+static ssize_t sram_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct sram_partition *part;
+
+ part = container_of(attr, struct sram_partition, battr);
+
+ mutex_lock(&part->lock);
+ memcpy_fromio(buf, part->base + pos, count);
+ mutex_unlock(&part->lock);
+
+ return count;
+}
+
+static ssize_t sram_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct sram_partition *part;
+
+ part = container_of(attr, struct sram_partition, battr);
+
+ mutex_lock(&part->lock);
+ memcpy_toio(part->base + pos, buf, count);
+ mutex_unlock(&part->lock);
+
+ return count;
+}
+
+static int sram_add_pool(struct sram_dev *sram, struct sram_reserve *block,
+ phys_addr_t start, struct sram_partition *part)
+{
+ int ret;
+
+ part->pool = devm_gen_pool_create(sram->dev, ilog2(SRAM_GRANULARITY),
+ NUMA_NO_NODE, block->label);
+ if (IS_ERR(part->pool))
+ return PTR_ERR(part->pool);
+
+ ret = gen_pool_add_virt(part->pool, (unsigned long)part->base, start,
+ block->size, NUMA_NO_NODE);
+ if (ret < 0) {
+ dev_err(sram->dev, "failed to register subpool: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sram_add_export(struct sram_dev *sram, struct sram_reserve *block,
+ phys_addr_t start, struct sram_partition *part)
+{
+ sysfs_bin_attr_init(&part->battr);
+ part->battr.attr.name = devm_kasprintf(sram->dev, GFP_KERNEL,
+ "%llx.sram",
+ (unsigned long long)start);
+ if (!part->battr.attr.name)
+ return -ENOMEM;
+
+ part->battr.attr.mode = S_IRUSR | S_IWUSR;
+ part->battr.read = sram_read;
+ part->battr.write = sram_write;
+ part->battr.size = block->size;
+
+ return device_create_bin_file(sram->dev, &part->battr);
+}
+
+static int sram_add_partition(struct sram_dev *sram, struct sram_reserve *block,
+ phys_addr_t start)
+{
+ int ret;
+ struct sram_partition *part = &sram->partition[sram->partitions];
+
+ mutex_init(&part->lock);
+ part->base = sram->virt_base + block->start;
+
+ if (block->pool) {
+ ret = sram_add_pool(sram, block, start, part);
+ if (ret)
+ return ret;
+ }
+ if (block->export) {
+ ret = sram_add_export(sram, block, start, part);
+ if (ret)
+ return ret;
+ }
+ sram->partitions++;
+
+ return 0;
+}
+
+static void sram_free_partitions(struct sram_dev *sram)
+{
+ struct sram_partition *part;
+
+ if (!sram->partitions)
+ return;
+
+ part = &sram->partition[sram->partitions - 1];
+ for (; sram->partitions; sram->partitions--, part--) {
+ if (part->battr.size)
+ device_remove_bin_file(sram->dev, &part->battr);
+
+ if (part->pool &&
+ gen_pool_avail(part->pool) < gen_pool_size(part->pool))
+ dev_err(sram->dev, "removed pool while SRAM allocated\n");
+ }
+}
+
static int sram_reserve_cmp(void *priv, struct list_head *a,
struct list_head *b)
{
@@ -57,7 +181,8 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
unsigned long size, cur_start, cur_size;
struct sram_reserve *rblocks, *block;
struct list_head reserve_list;
- unsigned int nblocks;
+ unsigned int nblocks, exports = 0;
+ const char *label;
int ret = 0;
INIT_LIST_HEAD(&reserve_list);
@@ -69,7 +194,7 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
* after the reserved blocks from the dt are processed.
*/
nblocks = (np) ? of_get_available_child_count(np) + 1 : 1;
- rblocks = kmalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL);
+ rblocks = kzalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL);
if (!rblocks)
return -ENOMEM;
@@ -82,7 +207,6 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
dev_err(sram->dev,
"could not get address for node %s\n",
child->full_name);
- of_node_put(child);
goto err_chunks;
}
@@ -91,7 +215,6 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
"reserved block %s outside the sram area\n",
child->full_name);
ret = -EINVAL;
- of_node_put(child);
goto err_chunks;
}
@@ -99,11 +222,42 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
block->size = resource_size(&child_res);
list_add_tail(&block->list, &reserve_list);
- dev_dbg(sram->dev, "found reserved block 0x%x-0x%x\n",
- block->start, block->start + block->size);
+ if (of_find_property(child, "export", NULL))
+ block->export = true;
+
+ if (of_find_property(child, "pool", NULL))
+ block->pool = true;
+
+ if ((block->export || block->pool) && block->size) {
+ exports++;
+
+ label = NULL;
+ ret = of_property_read_string(child, "label", &label);
+ if (ret && ret != -EINVAL) {
+ dev_err(sram->dev,
+ "%s has invalid label name\n",
+ child->full_name);
+ goto err_chunks;
+ }
+ if (!label)
+ label = child->name;
+
+ block->label = devm_kstrdup(sram->dev,
+ label, GFP_KERNEL);
+ if (!block->label)
+ goto err_chunks;
+
+ dev_dbg(sram->dev, "found %sblock '%s' 0x%x-0x%x\n",
+ block->export ? "exported " : "", block->label,
+ block->start, block->start + block->size);
+ } else {
+ dev_dbg(sram->dev, "found reserved block 0x%x-0x%x\n",
+ block->start, block->start + block->size);
+ }
block++;
}
+ child = NULL;
/* the last chunk marks the end of the region */
rblocks[nblocks - 1].start = size;
@@ -112,8 +266,17 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
list_sort(NULL, &reserve_list, sram_reserve_cmp);
- cur_start = 0;
+ if (exports) {
+ sram->partition = devm_kzalloc(sram->dev,
+ exports * sizeof(*sram->partition),
+ GFP_KERNEL);
+ if (!sram->partition) {
+ ret = -ENOMEM;
+ goto err_chunks;
+ }
+ }
+ cur_start = 0;
list_for_each_entry(block, &reserve_list, list) {
/* can only happen if sections overlap */
if (block->start < cur_start) {
@@ -121,9 +284,19 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
"block at 0x%x starts after current offset 0x%lx\n",
block->start, cur_start);
ret = -EINVAL;
+ sram_free_partitions(sram);
goto err_chunks;
}
+ if ((block->export || block->pool) && block->size) {
+ ret = sram_add_partition(sram, block,
+ res->start + block->start);
+ if (ret) {
+ sram_free_partitions(sram);
+ goto err_chunks;
+ }
+ }
+
/* current start is in a reserved block, so continue after it */
if (block->start == cur_start) {
cur_start = block->start + block->size;
@@ -143,14 +316,19 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
ret = gen_pool_add_virt(sram->pool,
(unsigned long)sram->virt_base + cur_start,
res->start + cur_start, cur_size, -1);
- if (ret < 0)
+ if (ret < 0) {
+ sram_free_partitions(sram);
goto err_chunks;
+ }
/* next allocation after this reserved block */
cur_start = block->start + block->size;
}
err_chunks:
+ if (child)
+ of_node_put(child);
+
kfree(rblocks);
return ret;
@@ -213,6 +391,8 @@ static int sram_remove(struct platform_device *pdev)
{
struct sram_dev *sram = platform_get_drvdata(pdev);
+ sram_free_partitions(sram);
+
if (gen_pool_avail(sram->pool) < gen_pool_size(sram->pool))
dev_err(sram->dev, "removed while SRAM allocated\n");
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index c8c6a363069c..6e3af8b42cdd 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -460,6 +460,13 @@ static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
* - TTY layer when write's finished
* - st_write (in context of the protocol stack)
*/
+static void work_fn_write_wakeup(struct work_struct *work)
+{
+ struct st_data_s *st_gdata = container_of(work, struct st_data_s,
+ work_write_wakeup);
+
+ st_tx_wakeup((void *)st_gdata);
+}
void st_tx_wakeup(struct st_data_s *st_data)
{
struct sk_buff *skb;
@@ -812,8 +819,12 @@ static void st_tty_wakeup(struct tty_struct *tty)
/* don't do an wakeup for now */
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- /* call our internal wakeup */
- st_tx_wakeup((void *)st_gdata);
+ /*
+ * schedule the internal wakeup instead of calling directly to
+ * avoid lockup (port->lock needed in tty->ops->write is
+ * already taken here
+ */
+ schedule_work(&st_gdata->work_write_wakeup);
}
static void st_tty_flush_buffer(struct tty_struct *tty)
@@ -881,6 +892,9 @@ int st_core_init(struct st_data_s **core_data)
pr_err("unable to un-register ldisc");
return err;
}
+
+ INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup);
+
*core_data = st_gdata;
return 0;
}
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
index cb0289b44a17..f5456fb7d773 100644
--- a/drivers/misc/ti_dac7512.c
+++ b/drivers/misc/ti_dac7512.c
@@ -89,7 +89,6 @@ MODULE_DEVICE_TABLE(of, dac7512_of_match);
static struct spi_driver dac7512_driver = {
.driver = {
.name = "dac7512",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(dac7512_of_match),
},
.probe = dac7512_probe,
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index ffb56340d0c7..1e688bfec567 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -1,7 +1,7 @@
/*
* VMware Balloon driver.
*
- * Copyright (C) 2000-2010, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2000-2014, VMware, 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
@@ -37,16 +37,19 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/vmw_vmci_defs.h>
+#include <linux/vmw_vmci_api.h>
#include <asm/hypervisor.h>
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.3.0.0-k");
+MODULE_VERSION("1.5.0.0-k");
MODULE_ALIAS("dmi:*:svnVMware*:*");
MODULE_ALIAS("vmware_vmmemctl");
MODULE_LICENSE("GPL");
@@ -57,12 +60,6 @@ MODULE_LICENSE("GPL");
*/
/*
- * Rate of allocating memory when there is no memory pressure
- * (driver performs non-sleeping allocations).
- */
-#define VMW_BALLOON_NOSLEEP_ALLOC_MAX 16384U
-
-/*
* Rates of memory allocaton when guest experiences memory pressure
* (driver performs sleeping allocations).
*/
@@ -71,13 +68,6 @@ MODULE_LICENSE("GPL");
#define VMW_BALLOON_RATE_ALLOC_INC 16U
/*
- * Rates for releasing pages while deflating balloon.
- */
-#define VMW_BALLOON_RATE_FREE_MIN 512U
-#define VMW_BALLOON_RATE_FREE_MAX 16384U
-#define VMW_BALLOON_RATE_FREE_INC 16U
-
-/*
* When guest is under memory pressure, use a reduced page allocation
* rate for next several cycles.
*/
@@ -85,7 +75,7 @@ MODULE_LICENSE("GPL");
/*
* Use __GFP_HIGHMEM to allow pages from HIGHMEM zone. We don't
- * allow wait (__GFP_WAIT) for NOSLEEP page allocations. Use
+ * allow wait (__GFP_RECLAIM) for NOSLEEP page allocations. Use
* __GFP_NOWARN, to suppress page allocation failure warnings.
*/
#define VMW_PAGE_ALLOC_NOSLEEP (__GFP_HIGHMEM|__GFP_NOWARN)
@@ -99,9 +89,6 @@ MODULE_LICENSE("GPL");
*/
#define VMW_PAGE_ALLOC_CANSLEEP (GFP_HIGHUSER)
-/* Maximum number of page allocations without yielding processor */
-#define VMW_BALLOON_YIELD_THRESHOLD 1024
-
/* Maximum number of refused pages we accumulate during inflation cycle */
#define VMW_BALLOON_MAX_REFUSED 16
@@ -116,17 +103,45 @@ enum vmwballoon_capabilities {
/*
* Bit 0 is reserved and not associated to any capability.
*/
- VMW_BALLOON_BASIC_CMDS = (1 << 1),
- VMW_BALLOON_BATCHED_CMDS = (1 << 2)
+ VMW_BALLOON_BASIC_CMDS = (1 << 1),
+ VMW_BALLOON_BATCHED_CMDS = (1 << 2),
+ VMW_BALLOON_BATCHED_2M_CMDS = (1 << 3),
+ VMW_BALLOON_SIGNALLED_WAKEUP_CMD = (1 << 4),
};
-#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS)
+#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS \
+ | VMW_BALLOON_BATCHED_CMDS \
+ | VMW_BALLOON_BATCHED_2M_CMDS \
+ | VMW_BALLOON_SIGNALLED_WAKEUP_CMD)
+
+#define VMW_BALLOON_2M_SHIFT (9)
+#define VMW_BALLOON_NUM_PAGE_SIZES (2)
+
+/*
+ * Backdoor commands availability:
+ *
+ * START, GET_TARGET and GUEST_ID are always available,
+ *
+ * VMW_BALLOON_BASIC_CMDS:
+ * LOCK and UNLOCK commands,
+ * VMW_BALLOON_BATCHED_CMDS:
+ * BATCHED_LOCK and BATCHED_UNLOCK commands.
+ * VMW BALLOON_BATCHED_2M_CMDS:
+ * BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands,
+ * VMW VMW_BALLOON_SIGNALLED_WAKEUP_CMD:
+ * VMW_BALLOON_CMD_VMCI_DOORBELL_SET command.
+ */
+#define VMW_BALLOON_CMD_START 0
+#define VMW_BALLOON_CMD_GET_TARGET 1
+#define VMW_BALLOON_CMD_LOCK 2
+#define VMW_BALLOON_CMD_UNLOCK 3
+#define VMW_BALLOON_CMD_GUEST_ID 4
+#define VMW_BALLOON_CMD_BATCHED_LOCK 6
+#define VMW_BALLOON_CMD_BATCHED_UNLOCK 7
+#define VMW_BALLOON_CMD_BATCHED_2M_LOCK 8
+#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK 9
+#define VMW_BALLOON_CMD_VMCI_DOORBELL_SET 10
-#define VMW_BALLOON_CMD_START 0
-#define VMW_BALLOON_CMD_GET_TARGET 1
-#define VMW_BALLOON_CMD_LOCK 2
-#define VMW_BALLOON_CMD_UNLOCK 3
-#define VMW_BALLOON_CMD_GUEST_ID 4
/* error codes */
#define VMW_BALLOON_SUCCESS 0
@@ -142,18 +157,60 @@ enum vmwballoon_capabilities {
#define VMW_BALLOON_SUCCESS_WITH_CAPABILITIES (0x03000000)
-#define VMWARE_BALLOON_CMD(cmd, data, result) \
+/* Batch page description */
+
+/*
+ * Layout of a page in the batch page:
+ *
+ * +-------------+----------+--------+
+ * | | | |
+ * | Page number | Reserved | Status |
+ * | | | |
+ * +-------------+----------+--------+
+ * 64 PAGE_SHIFT 6 0
+ *
+ * The reserved field should be set to 0.
+ */
+#define VMW_BALLOON_BATCH_MAX_PAGES (PAGE_SIZE / sizeof(u64))
+#define VMW_BALLOON_BATCH_STATUS_MASK ((1UL << 5) - 1)
+#define VMW_BALLOON_BATCH_PAGE_MASK (~((1UL << PAGE_SHIFT) - 1))
+
+struct vmballoon_batch_page {
+ u64 pages[VMW_BALLOON_BATCH_MAX_PAGES];
+};
+
+static u64 vmballoon_batch_get_pa(struct vmballoon_batch_page *batch, int idx)
+{
+ return batch->pages[idx] & VMW_BALLOON_BATCH_PAGE_MASK;
+}
+
+static int vmballoon_batch_get_status(struct vmballoon_batch_page *batch,
+ int idx)
+{
+ return (int)(batch->pages[idx] & VMW_BALLOON_BATCH_STATUS_MASK);
+}
+
+static void vmballoon_batch_set_pa(struct vmballoon_batch_page *batch, int idx,
+ u64 pa)
+{
+ batch->pages[idx] = pa;
+}
+
+
+#define VMWARE_BALLOON_CMD(cmd, arg1, arg2, result) \
({ \
- unsigned long __status, __dummy1, __dummy2; \
+ unsigned long __status, __dummy1, __dummy2, __dummy3; \
__asm__ __volatile__ ("inl %%dx" : \
"=a"(__status), \
"=c"(__dummy1), \
"=d"(__dummy2), \
- "=b"(result) : \
+ "=b"(result), \
+ "=S" (__dummy3) : \
"0"(VMW_BALLOON_HV_MAGIC), \
"1"(VMW_BALLOON_CMD_##cmd), \
"2"(VMW_BALLOON_HV_PORT), \
- "3"(data) : \
+ "3"(arg1), \
+ "4" (arg2) : \
"memory"); \
if (VMW_BALLOON_CMD_##cmd == VMW_BALLOON_CMD_START) \
result = __dummy1; \
@@ -164,27 +221,30 @@ enum vmwballoon_capabilities {
#ifdef CONFIG_DEBUG_FS
struct vmballoon_stats {
unsigned int timer;
+ unsigned int doorbell;
/* allocation statistics */
- unsigned int alloc;
- unsigned int alloc_fail;
+ unsigned int alloc[VMW_BALLOON_NUM_PAGE_SIZES];
+ unsigned int alloc_fail[VMW_BALLOON_NUM_PAGE_SIZES];
unsigned int sleep_alloc;
unsigned int sleep_alloc_fail;
- unsigned int refused_alloc;
- unsigned int refused_free;
- unsigned int free;
+ unsigned int refused_alloc[VMW_BALLOON_NUM_PAGE_SIZES];
+ unsigned int refused_free[VMW_BALLOON_NUM_PAGE_SIZES];
+ unsigned int free[VMW_BALLOON_NUM_PAGE_SIZES];
/* monitor operations */
- unsigned int lock;
- unsigned int lock_fail;
- unsigned int unlock;
- unsigned int unlock_fail;
+ unsigned int lock[VMW_BALLOON_NUM_PAGE_SIZES];
+ unsigned int lock_fail[VMW_BALLOON_NUM_PAGE_SIZES];
+ unsigned int unlock[VMW_BALLOON_NUM_PAGE_SIZES];
+ unsigned int unlock_fail[VMW_BALLOON_NUM_PAGE_SIZES];
unsigned int target;
unsigned int target_fail;
unsigned int start;
unsigned int start_fail;
unsigned int guest_type;
unsigned int guest_type_fail;
+ unsigned int doorbell_set;
+ unsigned int doorbell_unset;
};
#define STATS_INC(stat) (stat)++
@@ -192,14 +252,30 @@ struct vmballoon_stats {
#define STATS_INC(stat)
#endif
-struct vmballoon {
+struct vmballoon;
+struct vmballoon_ops {
+ void (*add_page)(struct vmballoon *b, int idx, struct page *p);
+ int (*lock)(struct vmballoon *b, unsigned int num_pages,
+ bool is_2m_pages, unsigned int *target);
+ int (*unlock)(struct vmballoon *b, unsigned int num_pages,
+ bool is_2m_pages, unsigned int *target);
+};
+
+struct vmballoon_page_size {
/* list of reserved physical pages */
struct list_head pages;
/* transient list of non-balloonable pages */
struct list_head refused_pages;
unsigned int n_refused_pages;
+};
+
+struct vmballoon {
+ struct vmballoon_page_size page_sizes[VMW_BALLOON_NUM_PAGE_SIZES];
+
+ /* supported page sizes. 1 == 4k pages only, 2 == 4k and 2m pages */
+ unsigned supported_page_sizes;
/* balloon size in pages */
unsigned int size;
@@ -210,11 +286,18 @@ struct vmballoon {
/* adjustment rates (pages per second) */
unsigned int rate_alloc;
- unsigned int rate_free;
/* slowdown page allocations for next few cycles */
unsigned int slow_allocation_cycles;
+ unsigned long capabilities;
+
+ struct vmballoon_batch_page *batch_page;
+ unsigned int batch_max_pages;
+ struct page *page;
+
+ const struct vmballoon_ops *ops;
+
#ifdef CONFIG_DEBUG_FS
/* statistics */
struct vmballoon_stats stats;
@@ -226,6 +309,8 @@ struct vmballoon {
struct sysinfo sysinfo;
struct delayed_work dwork;
+
+ struct vmci_handle vmci_doorbell;
};
static struct vmballoon balloon;
@@ -234,20 +319,38 @@ static struct vmballoon balloon;
* Send "start" command to the host, communicating supported version
* of the protocol.
*/
-static bool vmballoon_send_start(struct vmballoon *b)
+static bool vmballoon_send_start(struct vmballoon *b, unsigned long req_caps)
{
- unsigned long status, capabilities;
+ unsigned long status, capabilities, dummy = 0;
+ bool success;
STATS_INC(b->stats.start);
- status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_CAPABILITIES,
- capabilities);
- if (status == VMW_BALLOON_SUCCESS)
- return true;
+ status = VMWARE_BALLOON_CMD(START, req_caps, dummy, capabilities);
- pr_debug("%s - failed, hv returns %ld\n", __func__, status);
- STATS_INC(b->stats.start_fail);
- return false;
+ switch (status) {
+ case VMW_BALLOON_SUCCESS_WITH_CAPABILITIES:
+ b->capabilities = capabilities;
+ success = true;
+ break;
+ case VMW_BALLOON_SUCCESS:
+ b->capabilities = VMW_BALLOON_BASIC_CMDS;
+ success = true;
+ break;
+ default:
+ success = false;
+ }
+
+ if (b->capabilities & VMW_BALLOON_BATCHED_2M_CMDS)
+ b->supported_page_sizes = 2;
+ else
+ b->supported_page_sizes = 1;
+
+ if (!success) {
+ pr_debug("%s - failed, hv returns %ld\n", __func__, status);
+ STATS_INC(b->stats.start_fail);
+ }
+ return success;
}
static bool vmballoon_check_status(struct vmballoon *b, unsigned long status)
@@ -273,9 +376,10 @@ static bool vmballoon_check_status(struct vmballoon *b, unsigned long status)
*/
static bool vmballoon_send_guest_id(struct vmballoon *b)
{
- unsigned long status, dummy;
+ unsigned long status, dummy = 0;
- status = VMWARE_BALLOON_CMD(GUEST_ID, VMW_BALLOON_GUEST_ID, dummy);
+ status = VMWARE_BALLOON_CMD(GUEST_ID, VMW_BALLOON_GUEST_ID, dummy,
+ dummy);
STATS_INC(b->stats.guest_type);
@@ -287,6 +391,14 @@ static bool vmballoon_send_guest_id(struct vmballoon *b)
return false;
}
+static u16 vmballoon_page_size(bool is_2m_page)
+{
+ if (is_2m_page)
+ return 1 << VMW_BALLOON_2M_SHIFT;
+
+ return 1;
+}
+
/*
* Retrieve desired balloon size from the host.
*/
@@ -295,6 +407,7 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)
unsigned long status;
unsigned long target;
unsigned long limit;
+ unsigned long dummy = 0;
u32 limit32;
/*
@@ -313,7 +426,7 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)
/* update stats */
STATS_INC(b->stats.target);
- status = VMWARE_BALLOON_CMD(GET_TARGET, limit, target);
+ status = VMWARE_BALLOON_CMD(GET_TARGET, limit, dummy, target);
if (vmballoon_check_status(b, status)) {
*new_target = target;
return true;
@@ -330,23 +443,46 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)
* check the return value and maybe submit a different page.
*/
static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
- unsigned int *hv_status)
+ unsigned int *hv_status, unsigned int *target)
{
- unsigned long status, dummy;
+ unsigned long status, dummy = 0;
u32 pfn32;
pfn32 = (u32)pfn;
if (pfn32 != pfn)
return -1;
- STATS_INC(b->stats.lock);
+ STATS_INC(b->stats.lock[false]);
- *hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy);
+ *hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy, *target);
if (vmballoon_check_status(b, status))
return 0;
pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
- STATS_INC(b->stats.lock_fail);
+ STATS_INC(b->stats.lock_fail[false]);
+ return 1;
+}
+
+static int vmballoon_send_batched_lock(struct vmballoon *b,
+ unsigned int num_pages, bool is_2m_pages, unsigned int *target)
+{
+ unsigned long status;
+ unsigned long pfn = page_to_pfn(b->page);
+
+ STATS_INC(b->stats.lock[is_2m_pages]);
+
+ if (is_2m_pages)
+ status = VMWARE_BALLOON_CMD(BATCHED_2M_LOCK, pfn, num_pages,
+ *target);
+ else
+ status = VMWARE_BALLOON_CMD(BATCHED_LOCK, pfn, num_pages,
+ *target);
+
+ if (vmballoon_check_status(b, status))
+ return 0;
+
+ pr_debug("%s - batch ppn %lx, hv returns %ld\n", __func__, pfn, status);
+ STATS_INC(b->stats.lock_fail[is_2m_pages]);
return 1;
}
@@ -354,26 +490,66 @@ static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
* Notify the host that guest intends to release given page back into
* the pool of available (to the guest) pages.
*/
-static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn)
+static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn,
+ unsigned int *target)
{
- unsigned long status, dummy;
+ unsigned long status, dummy = 0;
u32 pfn32;
pfn32 = (u32)pfn;
if (pfn32 != pfn)
return false;
- STATS_INC(b->stats.unlock);
+ STATS_INC(b->stats.unlock[false]);
- status = VMWARE_BALLOON_CMD(UNLOCK, pfn, dummy);
+ status = VMWARE_BALLOON_CMD(UNLOCK, pfn, dummy, *target);
if (vmballoon_check_status(b, status))
return true;
pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
- STATS_INC(b->stats.unlock_fail);
+ STATS_INC(b->stats.unlock_fail[false]);
+ return false;
+}
+
+static bool vmballoon_send_batched_unlock(struct vmballoon *b,
+ unsigned int num_pages, bool is_2m_pages, unsigned int *target)
+{
+ unsigned long status;
+ unsigned long pfn = page_to_pfn(b->page);
+
+ STATS_INC(b->stats.unlock[is_2m_pages]);
+
+ if (is_2m_pages)
+ status = VMWARE_BALLOON_CMD(BATCHED_2M_UNLOCK, pfn, num_pages,
+ *target);
+ else
+ status = VMWARE_BALLOON_CMD(BATCHED_UNLOCK, pfn, num_pages,
+ *target);
+
+ if (vmballoon_check_status(b, status))
+ return true;
+
+ pr_debug("%s - batch ppn %lx, hv returns %ld\n", __func__, pfn, status);
+ STATS_INC(b->stats.unlock_fail[is_2m_pages]);
return false;
}
+static struct page *vmballoon_alloc_page(gfp_t flags, bool is_2m_page)
+{
+ if (is_2m_page)
+ return alloc_pages(flags, VMW_BALLOON_2M_SHIFT);
+
+ return alloc_page(flags);
+}
+
+static void vmballoon_free_page(struct page *page, bool is_2m_page)
+{
+ if (is_2m_page)
+ __free_pages(page, VMW_BALLOON_2M_SHIFT);
+ else
+ __free_page(page);
+}
+
/*
* Quickly release all pages allocated for the balloon. This function is
* called when host decides to "reset" balloon for one reason or another.
@@ -383,35 +559,31 @@ static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn)
static void vmballoon_pop(struct vmballoon *b)
{
struct page *page, *next;
- unsigned int count = 0;
-
- list_for_each_entry_safe(page, next, &b->pages, lru) {
- list_del(&page->lru);
- __free_page(page);
- STATS_INC(b->stats.free);
- b->size--;
-
- if (++count >= b->rate_free) {
- count = 0;
+ unsigned is_2m_pages;
+
+ for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
+ is_2m_pages++) {
+ struct vmballoon_page_size *page_size =
+ &b->page_sizes[is_2m_pages];
+ u16 size_per_page = vmballoon_page_size(is_2m_pages);
+
+ list_for_each_entry_safe(page, next, &page_size->pages, lru) {
+ list_del(&page->lru);
+ vmballoon_free_page(page, is_2m_pages);
+ STATS_INC(b->stats.free[is_2m_pages]);
+ b->size -= size_per_page;
cond_resched();
}
}
-}
-/*
- * Perform standard reset sequence by popping the balloon (in case it
- * is not empty) and then restarting protocol. This operation normally
- * happens when host responds with VMW_BALLOON_ERROR_RESET to a command.
- */
-static void vmballoon_reset(struct vmballoon *b)
-{
- /* free all pages, skipping monitor unlock */
- vmballoon_pop(b);
+ if (b->batch_page) {
+ vunmap(b->batch_page);
+ b->batch_page = NULL;
+ }
- if (vmballoon_send_start(b)) {
- b->reset_required = false;
- if (!vmballoon_send_guest_id(b))
- pr_err("failed to send guest ID to the host\n");
+ if (b->page) {
+ __free_page(b->page);
+ b->page = NULL;
}
}
@@ -420,17 +592,23 @@ static void vmballoon_reset(struct vmballoon *b)
* refuse list, those refused page are then released at the end of the
* inflation cycle.
*/
-static int vmballoon_lock_page(struct vmballoon *b, struct page *page)
+static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages,
+ bool is_2m_pages, unsigned int *target)
{
int locked, hv_status;
+ struct page *page = b->page;
+ struct vmballoon_page_size *page_size = &b->page_sizes[false];
+
+ /* is_2m_pages can never happen as 2m pages support implies batching */
- locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
+ locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status,
+ target);
if (locked > 0) {
- STATS_INC(b->stats.refused_alloc);
+ STATS_INC(b->stats.refused_alloc[false]);
if (hv_status == VMW_BALLOON_ERROR_RESET ||
hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
- __free_page(page);
+ vmballoon_free_page(page, false);
return -EIO;
}
@@ -439,17 +617,17 @@ static int vmballoon_lock_page(struct vmballoon *b, struct page *page)
* and retry allocation, unless we already accumulated
* too many of them, in which case take a breather.
*/
- if (b->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
- b->n_refused_pages++;
- list_add(&page->lru, &b->refused_pages);
+ if (page_size->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
+ page_size->n_refused_pages++;
+ list_add(&page->lru, &page_size->refused_pages);
} else {
- __free_page(page);
+ vmballoon_free_page(page, false);
}
return -EIO;
}
/* track allocated page */
- list_add(&page->lru, &b->pages);
+ list_add(&page->lru, &page_size->pages);
/* update balloon size */
b->size++;
@@ -457,21 +635,81 @@ static int vmballoon_lock_page(struct vmballoon *b, struct page *page)
return 0;
}
+static int vmballoon_lock_batched_page(struct vmballoon *b,
+ unsigned int num_pages, bool is_2m_pages, unsigned int *target)
+{
+ int locked, i;
+ u16 size_per_page = vmballoon_page_size(is_2m_pages);
+
+ locked = vmballoon_send_batched_lock(b, num_pages, is_2m_pages,
+ target);
+ if (locked > 0) {
+ for (i = 0; i < num_pages; i++) {
+ u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
+ struct page *p = pfn_to_page(pa >> PAGE_SHIFT);
+
+ vmballoon_free_page(p, is_2m_pages);
+ }
+
+ return -EIO;
+ }
+
+ for (i = 0; i < num_pages; i++) {
+ u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
+ struct page *p = pfn_to_page(pa >> PAGE_SHIFT);
+ struct vmballoon_page_size *page_size =
+ &b->page_sizes[is_2m_pages];
+
+ locked = vmballoon_batch_get_status(b->batch_page, i);
+
+ switch (locked) {
+ case VMW_BALLOON_SUCCESS:
+ list_add(&p->lru, &page_size->pages);
+ b->size += size_per_page;
+ break;
+ case VMW_BALLOON_ERROR_PPN_PINNED:
+ case VMW_BALLOON_ERROR_PPN_INVALID:
+ if (page_size->n_refused_pages
+ < VMW_BALLOON_MAX_REFUSED) {
+ list_add(&p->lru, &page_size->refused_pages);
+ page_size->n_refused_pages++;
+ break;
+ }
+ /* Fallthrough */
+ case VMW_BALLOON_ERROR_RESET:
+ case VMW_BALLOON_ERROR_PPN_NOTNEEDED:
+ vmballoon_free_page(p, is_2m_pages);
+ break;
+ default:
+ /* This should never happen */
+ WARN_ON_ONCE(true);
+ }
+ }
+
+ return 0;
+}
+
/*
* Release the page allocated for the balloon. Note that we first notify
* the host so it can make sure the page will be available for the guest
* to use, if needed.
*/
-static int vmballoon_release_page(struct vmballoon *b, struct page *page)
+static int vmballoon_unlock_page(struct vmballoon *b, unsigned int num_pages,
+ bool is_2m_pages, unsigned int *target)
{
- if (!vmballoon_send_unlock_page(b, page_to_pfn(page)))
- return -EIO;
+ struct page *page = b->page;
+ struct vmballoon_page_size *page_size = &b->page_sizes[false];
+
+ /* is_2m_pages can never happen as 2m pages support implies batching */
- list_del(&page->lru);
+ if (!vmballoon_send_unlock_page(b, page_to_pfn(page), target)) {
+ list_add(&page->lru, &page_size->pages);
+ return -EIO;
+ }
/* deallocate page */
- __free_page(page);
- STATS_INC(b->stats.free);
+ vmballoon_free_page(page, false);
+ STATS_INC(b->stats.free[false]);
/* update balloon size */
b->size--;
@@ -479,21 +717,76 @@ static int vmballoon_release_page(struct vmballoon *b, struct page *page)
return 0;
}
+static int vmballoon_unlock_batched_page(struct vmballoon *b,
+ unsigned int num_pages, bool is_2m_pages,
+ unsigned int *target)
+{
+ int locked, i, ret = 0;
+ bool hv_success;
+ u16 size_per_page = vmballoon_page_size(is_2m_pages);
+
+ hv_success = vmballoon_send_batched_unlock(b, num_pages, is_2m_pages,
+ target);
+ if (!hv_success)
+ ret = -EIO;
+
+ for (i = 0; i < num_pages; i++) {
+ u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
+ struct page *p = pfn_to_page(pa >> PAGE_SHIFT);
+ struct vmballoon_page_size *page_size =
+ &b->page_sizes[is_2m_pages];
+
+ locked = vmballoon_batch_get_status(b->batch_page, i);
+ if (!hv_success || locked != VMW_BALLOON_SUCCESS) {
+ /*
+ * That page wasn't successfully unlocked by the
+ * hypervisor, re-add it to the list of pages owned by
+ * the balloon driver.
+ */
+ list_add(&p->lru, &page_size->pages);
+ } else {
+ /* deallocate page */
+ vmballoon_free_page(p, is_2m_pages);
+ STATS_INC(b->stats.free[is_2m_pages]);
+
+ /* update balloon size */
+ b->size -= size_per_page;
+ }
+ }
+
+ return ret;
+}
+
/*
* Release pages that were allocated while attempting to inflate the
* balloon but were refused by the host for one reason or another.
*/
-static void vmballoon_release_refused_pages(struct vmballoon *b)
+static void vmballoon_release_refused_pages(struct vmballoon *b,
+ bool is_2m_pages)
{
struct page *page, *next;
+ struct vmballoon_page_size *page_size =
+ &b->page_sizes[is_2m_pages];
- list_for_each_entry_safe(page, next, &b->refused_pages, lru) {
+ list_for_each_entry_safe(page, next, &page_size->refused_pages, lru) {
list_del(&page->lru);
- __free_page(page);
- STATS_INC(b->stats.refused_free);
+ vmballoon_free_page(page, is_2m_pages);
+ STATS_INC(b->stats.refused_free[is_2m_pages]);
}
- b->n_refused_pages = 0;
+ page_size->n_refused_pages = 0;
+}
+
+static void vmballoon_add_page(struct vmballoon *b, int idx, struct page *p)
+{
+ b->page = p;
+}
+
+static void vmballoon_add_batched_page(struct vmballoon *b, int idx,
+ struct page *p)
+{
+ vmballoon_batch_set_pa(b->batch_page, idx,
+ (u64)page_to_pfn(p) << PAGE_SHIFT);
}
/*
@@ -503,12 +796,12 @@ static void vmballoon_release_refused_pages(struct vmballoon *b)
*/
static void vmballoon_inflate(struct vmballoon *b)
{
- unsigned int goal;
- unsigned int rate;
- unsigned int i;
+ unsigned rate;
unsigned int allocations = 0;
+ unsigned int num_pages = 0;
int error = 0;
gfp_t flags = VMW_PAGE_ALLOC_NOSLEEP;
+ bool is_2m_pages;
pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
@@ -527,27 +820,50 @@ static void vmballoon_inflate(struct vmballoon *b)
* slowdown page allocations considerably.
*/
- goal = b->target - b->size;
/*
* Start with no sleep allocation rate which may be higher
* than sleeping allocation rate.
*/
- rate = b->slow_allocation_cycles ?
- b->rate_alloc : VMW_BALLOON_NOSLEEP_ALLOC_MAX;
+ if (b->slow_allocation_cycles) {
+ rate = b->rate_alloc;
+ is_2m_pages = false;
+ } else {
+ rate = UINT_MAX;
+ is_2m_pages =
+ b->supported_page_sizes == VMW_BALLOON_NUM_PAGE_SIZES;
+ }
- pr_debug("%s - goal: %d, no-sleep rate: %d, sleep rate: %d\n",
- __func__, goal, rate, b->rate_alloc);
+ pr_debug("%s - goal: %d, no-sleep rate: %u, sleep rate: %d\n",
+ __func__, b->target - b->size, rate, b->rate_alloc);
- for (i = 0; i < goal; i++) {
+ while (!b->reset_required &&
+ b->size + num_pages * vmballoon_page_size(is_2m_pages)
+ < b->target) {
struct page *page;
if (flags == VMW_PAGE_ALLOC_NOSLEEP)
- STATS_INC(b->stats.alloc);
+ STATS_INC(b->stats.alloc[is_2m_pages]);
else
STATS_INC(b->stats.sleep_alloc);
- page = alloc_page(flags);
+ page = vmballoon_alloc_page(flags, is_2m_pages);
if (!page) {
+ STATS_INC(b->stats.alloc_fail[is_2m_pages]);
+
+ if (is_2m_pages) {
+ b->ops->lock(b, num_pages, true, &b->target);
+
+ /*
+ * ignore errors from locking as we now switch
+ * to 4k pages and we might get different
+ * errors.
+ */
+
+ num_pages = 0;
+ is_2m_pages = false;
+ continue;
+ }
+
if (flags == VMW_PAGE_ALLOC_CANSLEEP) {
/*
* CANSLEEP page allocation failed, so guest
@@ -559,7 +875,6 @@ static void vmballoon_inflate(struct vmballoon *b)
STATS_INC(b->stats.sleep_alloc_fail);
break;
}
- STATS_INC(b->stats.alloc_fail);
/*
* NOSLEEP page allocation failed, so the guest is
@@ -571,7 +886,7 @@ static void vmballoon_inflate(struct vmballoon *b)
*/
b->slow_allocation_cycles = VMW_BALLOON_SLOW_CYCLES;
- if (i >= b->rate_alloc)
+ if (allocations >= b->rate_alloc)
break;
flags = VMW_PAGE_ALLOC_CANSLEEP;
@@ -580,34 +895,40 @@ static void vmballoon_inflate(struct vmballoon *b)
continue;
}
- error = vmballoon_lock_page(b, page);
- if (error)
- break;
-
- if (++allocations > VMW_BALLOON_YIELD_THRESHOLD) {
- cond_resched();
- allocations = 0;
+ b->ops->add_page(b, num_pages++, page);
+ if (num_pages == b->batch_max_pages) {
+ error = b->ops->lock(b, num_pages, is_2m_pages,
+ &b->target);
+ num_pages = 0;
+ if (error)
+ break;
}
- if (i >= rate) {
+ cond_resched();
+
+ if (allocations >= rate) {
/* We allocated enough pages, let's take a break. */
break;
}
}
+ if (num_pages > 0)
+ b->ops->lock(b, num_pages, is_2m_pages, &b->target);
+
/*
* We reached our goal without failures so try increasing
* allocation rate.
*/
- if (error == 0 && i >= b->rate_alloc) {
- unsigned int mult = i / b->rate_alloc;
+ if (error == 0 && allocations >= b->rate_alloc) {
+ unsigned int mult = allocations / b->rate_alloc;
b->rate_alloc =
min(b->rate_alloc + mult * VMW_BALLOON_RATE_ALLOC_INC,
VMW_BALLOON_RATE_ALLOC_MAX);
}
- vmballoon_release_refused_pages(b);
+ vmballoon_release_refused_pages(b, true);
+ vmballoon_release_refused_pages(b, false);
}
/*
@@ -615,35 +936,176 @@ static void vmballoon_inflate(struct vmballoon *b)
*/
static void vmballoon_deflate(struct vmballoon *b)
{
- struct page *page, *next;
- unsigned int i = 0;
- unsigned int goal;
- int error;
+ unsigned is_2m_pages;
pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
- /* limit deallocation rate */
- goal = min(b->size - b->target, b->rate_free);
+ /* free pages to reach target */
+ for (is_2m_pages = 0; is_2m_pages < b->supported_page_sizes;
+ is_2m_pages++) {
+ struct page *page, *next;
+ unsigned int num_pages = 0;
+ struct vmballoon_page_size *page_size =
+ &b->page_sizes[is_2m_pages];
+
+ list_for_each_entry_safe(page, next, &page_size->pages, lru) {
+ if (b->reset_required ||
+ (b->target > 0 &&
+ b->size - num_pages
+ * vmballoon_page_size(is_2m_pages)
+ < b->target + vmballoon_page_size(true)))
+ break;
+
+ list_del(&page->lru);
+ b->ops->add_page(b, num_pages++, page);
- pr_debug("%s - goal: %d, rate: %d\n", __func__, goal, b->rate_free);
+ if (num_pages == b->batch_max_pages) {
+ int error;
- /* free pages to reach target */
- list_for_each_entry_safe(page, next, &b->pages, lru) {
- error = vmballoon_release_page(b, page);
- if (error) {
- /* quickly decrease rate in case of error */
- b->rate_free = max(b->rate_free / 2,
- VMW_BALLOON_RATE_FREE_MIN);
- return;
+ error = b->ops->unlock(b, num_pages,
+ is_2m_pages, &b->target);
+ num_pages = 0;
+ if (error)
+ return;
+ }
+
+ cond_resched();
}
- if (++i >= goal)
- break;
+ if (num_pages > 0)
+ b->ops->unlock(b, num_pages, is_2m_pages, &b->target);
+ }
+}
+
+static const struct vmballoon_ops vmballoon_basic_ops = {
+ .add_page = vmballoon_add_page,
+ .lock = vmballoon_lock_page,
+ .unlock = vmballoon_unlock_page
+};
+
+static const struct vmballoon_ops vmballoon_batched_ops = {
+ .add_page = vmballoon_add_batched_page,
+ .lock = vmballoon_lock_batched_page,
+ .unlock = vmballoon_unlock_batched_page
+};
+
+static bool vmballoon_init_batching(struct vmballoon *b)
+{
+ b->page = alloc_page(VMW_PAGE_ALLOC_NOSLEEP);
+ if (!b->page)
+ return false;
+
+ b->batch_page = vmap(&b->page, 1, VM_MAP, PAGE_KERNEL);
+ if (!b->batch_page) {
+ __free_page(b->page);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Receive notification and resize balloon
+ */
+static void vmballoon_doorbell(void *client_data)
+{
+ struct vmballoon *b = client_data;
+
+ STATS_INC(b->stats.doorbell);
+
+ mod_delayed_work(system_freezable_wq, &b->dwork, 0);
+}
+
+/*
+ * Clean up vmci doorbell
+ */
+static void vmballoon_vmci_cleanup(struct vmballoon *b)
+{
+ int error;
+
+ VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET, VMCI_INVALID_ID,
+ VMCI_INVALID_ID, error);
+ STATS_INC(b->stats.doorbell_unset);
+
+ if (!vmci_handle_is_invalid(b->vmci_doorbell)) {
+ vmci_doorbell_destroy(b->vmci_doorbell);
+ b->vmci_doorbell = VMCI_INVALID_HANDLE;
+ }
+}
+
+/*
+ * Initialize vmci doorbell, to get notified as soon as balloon changes
+ */
+static int vmballoon_vmci_init(struct vmballoon *b)
+{
+ int error = 0;
+
+ if ((b->capabilities & VMW_BALLOON_SIGNALLED_WAKEUP_CMD) != 0) {
+ error = vmci_doorbell_create(&b->vmci_doorbell,
+ VMCI_FLAG_DELAYED_CB,
+ VMCI_PRIVILEGE_FLAG_RESTRICTED,
+ vmballoon_doorbell, b);
+
+ if (error == VMCI_SUCCESS) {
+ VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET,
+ b->vmci_doorbell.context,
+ b->vmci_doorbell.resource, error);
+ STATS_INC(b->stats.doorbell_set);
+ }
+ }
+
+ if (error != 0) {
+ vmballoon_vmci_cleanup(b);
+
+ return -EIO;
}
- /* slowly increase rate if there were no errors */
- b->rate_free = min(b->rate_free + VMW_BALLOON_RATE_FREE_INC,
- VMW_BALLOON_RATE_FREE_MAX);
+ return 0;
+}
+
+/*
+ * Perform standard reset sequence by popping the balloon (in case it
+ * is not empty) and then restarting protocol. This operation normally
+ * happens when host responds with VMW_BALLOON_ERROR_RESET to a command.
+ */
+static void vmballoon_reset(struct vmballoon *b)
+{
+ int error;
+
+ vmballoon_vmci_cleanup(b);
+
+ /* free all pages, skipping monitor unlock */
+ vmballoon_pop(b);
+
+ if (!vmballoon_send_start(b, VMW_BALLOON_CAPABILITIES))
+ return;
+
+ if ((b->capabilities & VMW_BALLOON_BATCHED_CMDS) != 0) {
+ b->ops = &vmballoon_batched_ops;
+ b->batch_max_pages = VMW_BALLOON_BATCH_MAX_PAGES;
+ if (!vmballoon_init_batching(b)) {
+ /*
+ * We failed to initialize batching, inform the monitor
+ * about it by sending a null capability.
+ *
+ * The guest will retry in one second.
+ */
+ vmballoon_send_start(b, 0);
+ return;
+ }
+ } else if ((b->capabilities & VMW_BALLOON_BASIC_CMDS) != 0) {
+ b->ops = &vmballoon_basic_ops;
+ b->batch_max_pages = 1;
+ }
+
+ b->reset_required = false;
+
+ error = vmballoon_vmci_init(b);
+ if (error)
+ pr_err("failed to initialize vmci doorbell\n");
+
+ if (!vmballoon_send_guest_id(b))
+ pr_err("failed to send guest ID to the host\n");
}
/*
@@ -664,13 +1126,14 @@ static void vmballoon_work(struct work_struct *work)
if (b->slow_allocation_cycles > 0)
b->slow_allocation_cycles--;
- if (vmballoon_send_get_target(b, &target)) {
+ if (!b->reset_required && vmballoon_send_get_target(b, &target)) {
/* update target, adjust size */
b->target = target;
if (b->size < target)
vmballoon_inflate(b);
- else if (b->size > target)
+ else if (target == 0 ||
+ b->size > target + vmballoon_page_size(true))
vmballoon_deflate(b);
}
@@ -692,6 +1155,14 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
struct vmballoon *b = f->private;
struct vmballoon_stats *stats = &b->stats;
+ /* format capabilities info */
+ seq_printf(f,
+ "balloon capabilities: %#4x\n"
+ "used capabilities: %#4lx\n"
+ "is resetting: %c\n",
+ VMW_BALLOON_CAPABILITIES, b->capabilities,
+ b->reset_required ? 'y' : 'n');
+
/* format size info */
seq_printf(f,
"target: %8d pages\n"
@@ -700,35 +1171,48 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
/* format rate info */
seq_printf(f,
- "rateNoSleepAlloc: %8d pages/sec\n"
- "rateSleepAlloc: %8d pages/sec\n"
- "rateFree: %8d pages/sec\n",
- VMW_BALLOON_NOSLEEP_ALLOC_MAX,
- b->rate_alloc, b->rate_free);
+ "rateSleepAlloc: %8d pages/sec\n",
+ b->rate_alloc);
seq_printf(f,
"\n"
"timer: %8u\n"
+ "doorbell: %8u\n"
"start: %8u (%4u failed)\n"
"guestType: %8u (%4u failed)\n"
+ "2m-lock: %8u (%4u failed)\n"
"lock: %8u (%4u failed)\n"
+ "2m-unlock: %8u (%4u failed)\n"
"unlock: %8u (%4u failed)\n"
"target: %8u (%4u failed)\n"
+ "prim2mAlloc: %8u (%4u failed)\n"
"primNoSleepAlloc: %8u (%4u failed)\n"
"primCanSleepAlloc: %8u (%4u failed)\n"
+ "prim2mFree: %8u\n"
"primFree: %8u\n"
+ "err2mAlloc: %8u\n"
"errAlloc: %8u\n"
- "errFree: %8u\n",
+ "err2mFree: %8u\n"
+ "errFree: %8u\n"
+ "doorbellSet: %8u\n"
+ "doorbellUnset: %8u\n",
stats->timer,
+ stats->doorbell,
stats->start, stats->start_fail,
stats->guest_type, stats->guest_type_fail,
- stats->lock, stats->lock_fail,
- stats->unlock, stats->unlock_fail,
+ stats->lock[true], stats->lock_fail[true],
+ stats->lock[false], stats->lock_fail[false],
+ stats->unlock[true], stats->unlock_fail[true],
+ stats->unlock[false], stats->unlock_fail[false],
stats->target, stats->target_fail,
- stats->alloc, stats->alloc_fail,
+ stats->alloc[true], stats->alloc_fail[true],
+ stats->alloc[false], stats->alloc_fail[false],
stats->sleep_alloc, stats->sleep_alloc_fail,
- stats->free,
- stats->refused_alloc, stats->refused_free);
+ stats->free[true],
+ stats->free[false],
+ stats->refused_alloc[true], stats->refused_alloc[false],
+ stats->refused_free[true], stats->refused_free[false],
+ stats->doorbell_set, stats->doorbell_unset);
return 0;
}
@@ -782,7 +1266,7 @@ static inline void vmballoon_debugfs_exit(struct vmballoon *b)
static int __init vmballoon_init(void)
{
int error;
-
+ unsigned is_2m_pages;
/*
* Check if we are running on VMware's hypervisor and bail out
* if we are not.
@@ -790,32 +1274,26 @@ static int __init vmballoon_init(void)
if (x86_hyper != &x86_hyper_vmware)
return -ENODEV;
- INIT_LIST_HEAD(&balloon.pages);
- INIT_LIST_HEAD(&balloon.refused_pages);
+ for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
+ is_2m_pages++) {
+ INIT_LIST_HEAD(&balloon.page_sizes[is_2m_pages].pages);
+ INIT_LIST_HEAD(&balloon.page_sizes[is_2m_pages].refused_pages);
+ }
/* initialize rates */
balloon.rate_alloc = VMW_BALLOON_RATE_ALLOC_MAX;
- balloon.rate_free = VMW_BALLOON_RATE_FREE_MAX;
INIT_DELAYED_WORK(&balloon.dwork, vmballoon_work);
- /*
- * Start balloon.
- */
- if (!vmballoon_send_start(&balloon)) {
- pr_err("failed to send start command to the host\n");
- return -EIO;
- }
-
- if (!vmballoon_send_guest_id(&balloon)) {
- pr_err("failed to send guest ID to the host\n");
- return -EIO;
- }
-
error = vmballoon_debugfs_init(&balloon);
if (error)
return error;
+ balloon.vmci_doorbell = VMCI_INVALID_HANDLE;
+ balloon.batch_page = NULL;
+ balloon.page = NULL;
+ balloon.reset_required = true;
+
queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
return 0;
@@ -824,6 +1302,7 @@ module_init(vmballoon_init);
static void __exit vmballoon_exit(void)
{
+ vmballoon_vmci_cleanup(&balloon);
cancel_delayed_work_sync(&balloon.dwork);
vmballoon_debugfs_exit(&balloon);
@@ -833,7 +1312,7 @@ static void __exit vmballoon_exit(void)
* Reset connection before deallocating memory to avoid potential for
* additional spurious resets from guest touching deallocated pages.
*/
- vmballoon_send_start(&balloon);
+ vmballoon_send_start(&balloon, 0);
vmballoon_pop(&balloon);
}
module_exit(vmballoon_exit);
diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c b/drivers/misc/vmw_vmci/vmci_datagram.c
index 822665245588..8a4b6bbe1bee 100644
--- a/drivers/misc/vmw_vmci/vmci_datagram.c
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -276,11 +276,10 @@ static int dg_dispatch_as_host(u32 context_id, struct vmci_datagram *dg)
}
/* We make a copy to enqueue. */
- new_dg = kmalloc(dg_size, GFP_KERNEL);
+ new_dg = kmemdup(dg, dg_size, GFP_KERNEL);
if (new_dg == NULL)
return VMCI_ERROR_NO_MEM;
- memcpy(new_dg, dg, dg_size);
retval = vmci_ctx_enqueue_datagram(dg->dst.context, new_dg);
if (retval < VMCI_SUCCESS) {
kfree(new_dg);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c742cfd7674e..d8486168415a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -65,8 +65,7 @@ MODULE_ALIAS("mmc:block");
#define MMC_SANITIZE_REQ_TIMEOUT 240000
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
-#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \
- (req->cmd_flags & REQ_META)) && \
+#define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \
(rq_data_dir(req) == WRITE))
#define PACKED_CMD_VER 0x01
#define PACKED_CMD_WR 0x02
@@ -387,6 +386,24 @@ out:
return ERR_PTR(err);
}
+static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
+ struct mmc_blk_ioc_data *idata)
+{
+ struct mmc_ioc_cmd *ic = &idata->ic;
+
+ if (copy_to_user(&(ic_ptr->response), ic->response,
+ sizeof(ic->response)))
+ return -EFAULT;
+
+ if (!idata->ic.write_flag) {
+ if (copy_to_user((void __user *)(unsigned long)ic->data_ptr,
+ idata->buf, idata->buf_bytes))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
u32 retries_max)
{
@@ -447,12 +464,9 @@ out:
return err;
}
-static int mmc_blk_ioctl_cmd(struct block_device *bdev,
- struct mmc_ioc_cmd __user *ic_ptr)
+static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
+ struct mmc_blk_ioc_data *idata)
{
- struct mmc_blk_ioc_data *idata;
- struct mmc_blk_data *md;
- struct mmc_card *card;
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct mmc_request mrq = {NULL};
@@ -461,33 +475,12 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
int is_rpmb = false;
u32 status = 0;
- /*
- * The caller must have CAP_SYS_RAWIO, and must be calling this on the
- * whole block device, not on a partition. This prevents overspray
- * between sibling partitions.
- */
- if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
- return -EPERM;
-
- idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
- if (IS_ERR(idata))
- return PTR_ERR(idata);
-
- md = mmc_blk_get(bdev->bd_disk);
- if (!md) {
- err = -EINVAL;
- goto cmd_err;
- }
+ if (!card || !md || !idata)
+ return -EINVAL;
if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
is_rpmb = true;
- card = md->queue.card;
- if (IS_ERR(card)) {
- err = PTR_ERR(card);
- goto cmd_done;
- }
-
cmd.opcode = idata->ic.opcode;
cmd.arg = idata->ic.arg;
cmd.flags = idata->ic.flags;
@@ -530,23 +523,21 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
mrq.cmd = &cmd;
- mmc_get_card(card);
-
err = mmc_blk_part_switch(card, md);
if (err)
- goto cmd_rel_host;
+ return err;
if (idata->ic.is_acmd) {
err = mmc_app_cmd(card->host, card);
if (err)
- goto cmd_rel_host;
+ return err;
}
if (is_rpmb) {
err = mmc_set_blockcount(card, data.blocks,
idata->ic.write_flag & (1 << 31));
if (err)
- goto cmd_rel_host;
+ return err;
}
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
@@ -557,7 +548,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
pr_err("%s: ioctl_do_sanitize() failed. err = %d",
__func__, err);
- goto cmd_rel_host;
+ return err;
}
mmc_wait_for_req(card->host, &mrq);
@@ -565,14 +556,12 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
if (cmd.error) {
dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
__func__, cmd.error);
- err = cmd.error;
- goto cmd_rel_host;
+ return cmd.error;
}
if (data.error) {
dev_err(mmc_dev(card->host), "%s: data error %d\n",
__func__, data.error);
- err = data.error;
- goto cmd_rel_host;
+ return data.error;
}
/*
@@ -582,18 +571,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
if (idata->ic.postsleep_min_us)
usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
- if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) {
- err = -EFAULT;
- goto cmd_rel_host;
- }
-
- if (!idata->ic.write_flag) {
- if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr,
- idata->buf, idata->buf_bytes)) {
- err = -EFAULT;
- goto cmd_rel_host;
- }
- }
+ memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
if (is_rpmb) {
/*
@@ -607,24 +585,132 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
__func__, status, err);
}
-cmd_rel_host:
+ return err;
+}
+
+static int mmc_blk_ioctl_cmd(struct block_device *bdev,
+ struct mmc_ioc_cmd __user *ic_ptr)
+{
+ struct mmc_blk_ioc_data *idata;
+ struct mmc_blk_data *md;
+ struct mmc_card *card;
+ int err = 0, ioc_err = 0;
+
+ idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
+ if (IS_ERR(idata))
+ return PTR_ERR(idata);
+
+ md = mmc_blk_get(bdev->bd_disk);
+ if (!md) {
+ err = -EINVAL;
+ goto cmd_err;
+ }
+
+ card = md->queue.card;
+ if (IS_ERR(card)) {
+ err = PTR_ERR(card);
+ goto cmd_done;
+ }
+
+ mmc_get_card(card);
+
+ ioc_err = __mmc_blk_ioctl_cmd(card, md, idata);
+
mmc_put_card(card);
+ err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
+
cmd_done:
mmc_blk_put(md);
cmd_err:
kfree(idata->buf);
kfree(idata);
- return err;
+ return ioc_err ? ioc_err : err;
+}
+
+static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
+ struct mmc_ioc_multi_cmd __user *user)
+{
+ struct mmc_blk_ioc_data **idata = NULL;
+ struct mmc_ioc_cmd __user *cmds = user->cmds;
+ struct mmc_card *card;
+ struct mmc_blk_data *md;
+ int i, err = 0, ioc_err = 0;
+ __u64 num_of_cmds;
+
+ if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
+ sizeof(num_of_cmds)))
+ return -EFAULT;
+
+ if (num_of_cmds > MMC_IOC_MAX_CMDS)
+ return -EINVAL;
+
+ idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
+ if (!idata)
+ return -ENOMEM;
+
+ for (i = 0; i < num_of_cmds; i++) {
+ idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
+ if (IS_ERR(idata[i])) {
+ err = PTR_ERR(idata[i]);
+ num_of_cmds = i;
+ goto cmd_err;
+ }
+ }
+
+ md = mmc_blk_get(bdev->bd_disk);
+ if (!md)
+ goto cmd_err;
+
+ card = md->queue.card;
+ if (IS_ERR(card)) {
+ err = PTR_ERR(card);
+ goto cmd_done;
+ }
+
+ mmc_get_card(card);
+
+ for (i = 0; i < num_of_cmds && !ioc_err; i++)
+ ioc_err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
+
+ mmc_put_card(card);
+
+ /* copy to user if data and response */
+ for (i = 0; i < num_of_cmds && !err; i++)
+ err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
+
+cmd_done:
+ mmc_blk_put(md);
+cmd_err:
+ for (i = 0; i < num_of_cmds; i++) {
+ kfree(idata[i]->buf);
+ kfree(idata[i]);
+ }
+ kfree(idata);
+ return ioc_err ? ioc_err : err;
}
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- int ret = -EINVAL;
- if (cmd == MMC_IOC_CMD)
- ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg);
- return ret;
+ /*
+ * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+ * whole block device, not on a partition. This prevents overspray
+ * between sibling partitions.
+ */
+ if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+ return -EPERM;
+
+ switch (cmd) {
+ case MMC_IOC_CMD:
+ return mmc_blk_ioctl_cmd(bdev,
+ (struct mmc_ioc_cmd __user *)arg);
+ case MMC_IOC_MULTI_CMD:
+ return mmc_blk_ioctl_multi_cmd(bdev,
+ (struct mmc_ioc_multi_cmd __user *)arg);
+ default:
+ return -EINVAL;
+ }
}
#ifdef CONFIG_COMPAT
@@ -1380,13 +1466,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
/*
* Reliable writes are used to implement Forced Unit Access and
- * REQ_META accesses, and are supported only on MMCs.
- *
- * XXX: this really needs a good explanation of why REQ_META
- * is treated special.
+ * are supported only on MMCs.
*/
- bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
- (req->cmd_flags & REQ_META)) &&
+ bool do_rel_wr = (req->cmd_flags & REQ_FUA) &&
(rq_data_dir(req) == WRITE) &&
(md->flags & MMC_BLK_REL_WR);
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index b78cf5d403a3..7fc9174d4619 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -2263,15 +2263,12 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
/*
* eMMC hardware reset.
*/
-static int mmc_test_hw_reset(struct mmc_test_card *test)
+static int mmc_test_reset(struct mmc_test_card *test)
{
struct mmc_card *card = test->card;
struct mmc_host *host = card->host;
int err;
- if (!mmc_card_mmc(card) || !mmc_can_reset(card))
- return RESULT_UNSUP_CARD;
-
err = mmc_hw_reset(host);
if (!err)
return RESULT_OK;
@@ -2605,8 +2602,8 @@ static const struct mmc_test_case mmc_test_cases[] = {
},
{
- .name = "eMMC hardware reset",
- .run = mmc_test_hw_reset,
+ .name = "Reset test",
+ .run = mmc_test_reset,
},
};
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index 9ebee72d9c3f..4c33d7690f2f 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -1,13 +1,3 @@
#
# MMC core configuration
#
-
-config MMC_CLKGATE
- bool "MMC host clock gating"
- help
- This will attempt to aggressively gate the clock to the MMC card.
- This is done to save power due to gating off the logic and bus
- noise when the MMC card is not in use. Your host driver has to
- support handling this in order for it to be of any use.
-
- If unsure, say N.
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a3eb20bdcd97..5ae89e48fd85 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -187,8 +187,6 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
if (mrq->done)
mrq->done(mrq);
-
- mmc_host_clk_release(host);
}
}
@@ -206,6 +204,23 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
return;
}
+ /*
+ * For sdio rw commands we must wait for card busy otherwise some
+ * sdio devices won't work properly.
+ */
+ if (mmc_is_io_op(mrq->cmd->opcode) && host->ops->card_busy) {
+ int tries = 500; /* Wait aprox 500ms at maximum */
+
+ while (host->ops->card_busy(host) && --tries)
+ mmc_delay(1);
+
+ if (tries == 0) {
+ mrq->cmd->error = -EBUSY;
+ mmc_request_done(host, mrq);
+ return;
+ }
+ }
+
host->ops->request(host, mrq);
}
@@ -275,7 +290,6 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
mrq->stop->mrq = mrq;
}
}
- mmc_host_clk_hold(host);
led_trigger_event(host->led, LED_FULL);
__mmc_start_request(host, mrq);
@@ -525,11 +539,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
bool is_first_req)
{
- if (host->ops->pre_req) {
- mmc_host_clk_hold(host);
+ if (host->ops->pre_req)
host->ops->pre_req(host, mrq, is_first_req);
- mmc_host_clk_release(host);
- }
}
/**
@@ -544,11 +555,8 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
int err)
{
- if (host->ops->post_req) {
- mmc_host_clk_hold(host);
+ if (host->ops->post_req)
host->ops->post_req(host, mrq, err);
- mmc_host_clk_release(host);
- }
}
/**
@@ -833,9 +841,9 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
unsigned int timeout_us, limit_us;
timeout_us = data->timeout_ns / 1000;
- if (mmc_host_clk_rate(card->host))
+ if (card->host->ios.clock)
timeout_us += data->timeout_clks * 1000 /
- (mmc_host_clk_rate(card->host) / 1000);
+ (card->host->ios.clock / 1000);
if (data->flags & MMC_DATA_WRITE)
/*
@@ -1033,8 +1041,6 @@ static inline void mmc_set_ios(struct mmc_host *host)
ios->power_mode, ios->chip_select, ios->vdd,
ios->bus_width, ios->timing);
- if (ios->clock > 0)
- mmc_set_ungated(host);
host->ops->set_ios(host, ios);
}
@@ -1043,17 +1049,15 @@ static inline void mmc_set_ios(struct mmc_host *host)
*/
void mmc_set_chip_select(struct mmc_host *host, int mode)
{
- mmc_host_clk_hold(host);
host->ios.chip_select = mode;
mmc_set_ios(host);
- mmc_host_clk_release(host);
}
/*
* Sets the host clock to the highest possible frequency that
* is below "hz".
*/
-static void __mmc_set_clock(struct mmc_host *host, unsigned int hz)
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
{
WARN_ON(hz && hz < host->f_min);
@@ -1064,68 +1068,6 @@ static void __mmc_set_clock(struct mmc_host *host, unsigned int hz)
mmc_set_ios(host);
}
-void mmc_set_clock(struct mmc_host *host, unsigned int hz)
-{
- mmc_host_clk_hold(host);
- __mmc_set_clock(host, hz);
- mmc_host_clk_release(host);
-}
-
-#ifdef CONFIG_MMC_CLKGATE
-/*
- * This gates the clock by setting it to 0 Hz.
- */
-void mmc_gate_clock(struct mmc_host *host)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&host->clk_lock, flags);
- host->clk_old = host->ios.clock;
- host->ios.clock = 0;
- host->clk_gated = true;
- spin_unlock_irqrestore(&host->clk_lock, flags);
- mmc_set_ios(host);
-}
-
-/*
- * This restores the clock from gating by using the cached
- * clock value.
- */
-void mmc_ungate_clock(struct mmc_host *host)
-{
- /*
- * We should previously have gated the clock, so the clock shall
- * be 0 here! The clock may however be 0 during initialization,
- * when some request operations are performed before setting
- * the frequency. When ungate is requested in that situation
- * we just ignore the call.
- */
- if (host->clk_old) {
- BUG_ON(host->ios.clock);
- /* This call will also set host->clk_gated to false */
- __mmc_set_clock(host, host->clk_old);
- }
-}
-
-void mmc_set_ungated(struct mmc_host *host)
-{
- unsigned long flags;
-
- /*
- * We've been given a new frequency while the clock is gated,
- * so make sure we regard this as ungating it.
- */
- spin_lock_irqsave(&host->clk_lock, flags);
- host->clk_gated = false;
- spin_unlock_irqrestore(&host->clk_lock, flags);
-}
-
-#else
-void mmc_set_ungated(struct mmc_host *host)
-{
-}
-#endif
-
int mmc_execute_tuning(struct mmc_card *card)
{
struct mmc_host *host = card->host;
@@ -1140,9 +1082,7 @@ int mmc_execute_tuning(struct mmc_card *card)
else
opcode = MMC_SEND_TUNING_BLOCK;
- mmc_host_clk_hold(host);
err = host->ops->execute_tuning(host, opcode);
- mmc_host_clk_release(host);
if (err)
pr_err("%s: tuning execution failed\n", mmc_hostname(host));
@@ -1157,10 +1097,8 @@ int mmc_execute_tuning(struct mmc_card *card)
*/
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
{
- mmc_host_clk_hold(host);
host->ios.bus_mode = mode;
mmc_set_ios(host);
- mmc_host_clk_release(host);
}
/*
@@ -1168,10 +1106,8 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
*/
void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
{
- mmc_host_clk_hold(host);
host->ios.bus_width = width;
mmc_set_ios(host);
- mmc_host_clk_release(host);
}
/*
@@ -1341,6 +1277,40 @@ struct device_node *mmc_of_find_child_device(struct mmc_host *host,
#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
*
@@ -1403,22 +1373,7 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
int min_uV, max_uV;
if (vdd_bit) {
- int tmp;
-
- /*
- * 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;
- }
+ 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) {
@@ -1439,6 +1394,84 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
}
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 */
int mmc_regulator_get_supply(struct mmc_host *mmc)
@@ -1515,11 +1548,8 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
int old_signal_voltage = host->ios.signal_voltage;
host->ios.signal_voltage = signal_voltage;
- if (host->ops->start_signal_voltage_switch) {
- mmc_host_clk_hold(host);
+ if (host->ops->start_signal_voltage_switch)
err = host->ops->start_signal_voltage_switch(host, &host->ios);
- mmc_host_clk_release(host);
- }
if (err)
host->ios.signal_voltage = old_signal_voltage;
@@ -1553,20 +1583,17 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
pr_warn("%s: cannot verify signal voltage switch\n",
mmc_hostname(host));
- mmc_host_clk_hold(host);
-
cmd.opcode = SD_SWITCH_VOLTAGE;
cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
- goto err_command;
+ return err;
+
+ if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
+ return -EIO;
- if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) {
- err = -EIO;
- goto err_command;
- }
/*
* The card should drive cmd and dat[0:3] low immediately
* after the response of cmd11, but wait 1 ms to be sure
@@ -1615,9 +1642,6 @@ power_cycle:
mmc_power_cycle(host, ocr);
}
-err_command:
- mmc_host_clk_release(host);
-
return err;
}
@@ -1626,10 +1650,8 @@ err_command:
*/
void mmc_set_timing(struct mmc_host *host, unsigned int timing)
{
- mmc_host_clk_hold(host);
host->ios.timing = timing;
mmc_set_ios(host);
- mmc_host_clk_release(host);
}
/*
@@ -1637,10 +1659,8 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing)
*/
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
{
- mmc_host_clk_hold(host);
host->ios.drv_type = drv_type;
mmc_set_ios(host);
- mmc_host_clk_release(host);
}
int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
@@ -1648,7 +1668,6 @@ int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
{
struct mmc_host *host = card->host;
int host_drv_type = SD_DRIVER_TYPE_B;
- int drive_strength;
*drv_type = 0;
@@ -1671,14 +1690,10 @@ int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
* information and let the hardware specific code
* return what is possible given the options
*/
- mmc_host_clk_hold(host);
- drive_strength = host->ops->select_drive_strength(card, max_dtr,
- host_drv_type,
- card_drv_type,
- drv_type);
- mmc_host_clk_release(host);
-
- return drive_strength;
+ return host->ops->select_drive_strength(card, max_dtr,
+ host_drv_type,
+ card_drv_type,
+ drv_type);
}
/*
@@ -1697,8 +1712,6 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
if (host->ios.power_mode == MMC_POWER_ON)
return;
- mmc_host_clk_hold(host);
-
mmc_pwrseq_pre_power_on(host);
host->ios.vdd = fls(ocr) - 1;
@@ -1732,8 +1745,6 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
* time required to reach a stable voltage.
*/
mmc_delay(10);
-
- mmc_host_clk_release(host);
}
void mmc_power_off(struct mmc_host *host)
@@ -1741,8 +1752,6 @@ void mmc_power_off(struct mmc_host *host)
if (host->ios.power_mode == MMC_POWER_OFF)
return;
- mmc_host_clk_hold(host);
-
mmc_pwrseq_power_off(host);
host->ios.clock = 0;
@@ -1758,8 +1767,6 @@ void mmc_power_off(struct mmc_host *host)
* can be successfully turned on again.
*/
mmc_delay(1);
-
- mmc_host_clk_release(host);
}
void mmc_power_cycle(struct mmc_host *host, u32 ocr)
@@ -1975,7 +1982,7 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
*/
timeout_clks <<= 1;
timeout_us += (timeout_clks * 1000) /
- (mmc_host_clk_rate(card->host) / 1000);
+ (card->host->ios.clock / 1000);
erase_timeout = timeout_us / 1000;
@@ -2423,9 +2430,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
{
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
return;
- mmc_host_clk_hold(host);
host->ops->hw_reset(host);
- mmc_host_clk_release(host);
}
int mmc_hw_reset(struct mmc_host *host)
@@ -2633,10 +2638,14 @@ void mmc_start_host(struct mmc_host *host)
host->f_init = max(freqs[0], host->f_min);
host->rescan_disable = 0;
host->ios.power_mode = MMC_POWER_UNDEFINED;
+
+ mmc_claim_host(host);
if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
mmc_power_off(host);
else
mmc_power_up(host, host->ocr_avail);
+ mmc_release_host(host);
+
mmc_gpiod_request_cd_irq(host);
_mmc_detect_change(host, 0, false);
}
@@ -2674,7 +2683,9 @@ void mmc_stop_host(struct mmc_host *host)
BUG_ON(host->card);
+ mmc_claim_host(host);
mmc_power_off(host);
+ mmc_release_host(host);
}
int mmc_power_save_host(struct mmc_host *host)
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 1a22a82209b2..09241e56d628 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -40,9 +40,6 @@ void mmc_init_erase(struct mmc_card *card);
void mmc_set_chip_select(struct mmc_host *host, int mode);
void mmc_set_clock(struct mmc_host *host, unsigned int hz);
-void mmc_gate_clock(struct mmc_host *host);
-void mmc_ungate_clock(struct mmc_host *host);
-void mmc_set_ungated(struct mmc_host *host);
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index e9142108a6c6..154aced0b91b 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -126,6 +126,12 @@ static int mmc_ios_show(struct seq_file *s, void *data)
case MMC_TIMING_SD_HS:
str = "sd high-speed";
break;
+ case MMC_TIMING_UHS_SDR12:
+ str = "sd uhs SDR12";
+ break;
+ case MMC_TIMING_UHS_SDR25:
+ str = "sd uhs SDR25";
+ break;
case MMC_TIMING_UHS_SDR50:
str = "sd uhs SDR50";
break;
@@ -166,6 +172,25 @@ static int mmc_ios_show(struct seq_file *s, void *data)
}
seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str);
+ switch (ios->drv_type) {
+ case MMC_SET_DRIVER_TYPE_A:
+ str = "driver type A";
+ break;
+ case MMC_SET_DRIVER_TYPE_B:
+ str = "driver type B";
+ break;
+ case MMC_SET_DRIVER_TYPE_C:
+ str = "driver type C";
+ break;
+ case MMC_SET_DRIVER_TYPE_D:
+ str = "driver type D";
+ break;
+ default:
+ str = "invalid";
+ break;
+ }
+ seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str);
+
return 0;
}
@@ -230,11 +255,6 @@ void mmc_add_host_debugfs(struct mmc_host *host)
&mmc_clock_fops))
goto err_node;
-#ifdef CONFIG_MMC_CLKGATE
- if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
- root, &host->clk_delay))
- goto err_node;
-#endif
#ifdef CONFIG_FAIL_MMC_REQUEST
if (fail_request)
setup_fault_attr(&fail_default_attr, fail_request);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 5466f25f0281..da950c44204d 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -61,246 +61,6 @@ void mmc_unregister_host_class(void)
class_unregister(&mmc_host_class);
}
-#ifdef CONFIG_MMC_CLKGATE
-static ssize_t clkgate_delay_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct mmc_host *host = cls_dev_to_mmc_host(dev);
- return snprintf(buf, PAGE_SIZE, "%lu\n", host->clkgate_delay);
-}
-
-static ssize_t clkgate_delay_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct mmc_host *host = cls_dev_to_mmc_host(dev);
- unsigned long flags, value;
-
- if (kstrtoul(buf, 0, &value))
- return -EINVAL;
-
- spin_lock_irqsave(&host->clk_lock, flags);
- host->clkgate_delay = value;
- spin_unlock_irqrestore(&host->clk_lock, flags);
- return count;
-}
-
-/*
- * Enabling clock gating will make the core call out to the host
- * once up and once down when it performs a request or card operation
- * intermingled in any fashion. The driver will see this through
- * set_ios() operations with ios.clock field set to 0 to gate (disable)
- * the block clock, and to the old frequency to enable it again.
- */
-static void mmc_host_clk_gate_delayed(struct mmc_host *host)
-{
- unsigned long tick_ns;
- unsigned long freq = host->ios.clock;
- unsigned long flags;
-
- if (!freq) {
- pr_debug("%s: frequency set to 0 in disable function, "
- "this means the clock is already disabled.\n",
- mmc_hostname(host));
- return;
- }
- /*
- * New requests may have appeared while we were scheduling,
- * then there is no reason to delay the check before
- * clk_disable().
- */
- spin_lock_irqsave(&host->clk_lock, flags);
-
- /*
- * Delay n bus cycles (at least 8 from MMC spec) before attempting
- * to disable the MCI block clock. The reference count may have
- * gone up again after this delay due to rescheduling!
- */
- if (!host->clk_requests) {
- spin_unlock_irqrestore(&host->clk_lock, flags);
- tick_ns = DIV_ROUND_UP(1000000000, freq);
- ndelay(host->clk_delay * tick_ns);
- } else {
- /* New users appeared while waiting for this work */
- spin_unlock_irqrestore(&host->clk_lock, flags);
- return;
- }
- mutex_lock(&host->clk_gate_mutex);
- spin_lock_irqsave(&host->clk_lock, flags);
- if (!host->clk_requests) {
- spin_unlock_irqrestore(&host->clk_lock, flags);
- /* This will set host->ios.clock to 0 */
- mmc_gate_clock(host);
- spin_lock_irqsave(&host->clk_lock, flags);
- pr_debug("%s: gated MCI clock\n", mmc_hostname(host));
- }
- spin_unlock_irqrestore(&host->clk_lock, flags);
- mutex_unlock(&host->clk_gate_mutex);
-}
-
-/*
- * Internal work. Work to disable the clock at some later point.
- */
-static void mmc_host_clk_gate_work(struct work_struct *work)
-{
- struct mmc_host *host = container_of(work, struct mmc_host,
- clk_gate_work.work);
-
- mmc_host_clk_gate_delayed(host);
-}
-
-/**
- * mmc_host_clk_hold - ungate hardware MCI clocks
- * @host: host to ungate.
- *
- * Makes sure the host ios.clock is restored to a non-zero value
- * past this call. Increase clock reference count and ungate clock
- * if we're the first user.
- */
-void mmc_host_clk_hold(struct mmc_host *host)
-{
- unsigned long flags;
-
- /* cancel any clock gating work scheduled by mmc_host_clk_release() */
- cancel_delayed_work_sync(&host->clk_gate_work);
- mutex_lock(&host->clk_gate_mutex);
- spin_lock_irqsave(&host->clk_lock, flags);
- if (host->clk_gated) {
- spin_unlock_irqrestore(&host->clk_lock, flags);
- mmc_ungate_clock(host);
- spin_lock_irqsave(&host->clk_lock, flags);
- pr_debug("%s: ungated MCI clock\n", mmc_hostname(host));
- }
- host->clk_requests++;
- spin_unlock_irqrestore(&host->clk_lock, flags);
- mutex_unlock(&host->clk_gate_mutex);
-}
-
-/**
- * mmc_host_may_gate_card - check if this card may be gated
- * @card: card to check.
- */
-static bool mmc_host_may_gate_card(struct mmc_card *card)
-{
- /* If there is no card we may gate it */
- if (!card)
- return true;
- /*
- * Don't gate SDIO cards! These need to be clocked at all times
- * since they may be independent systems generating interrupts
- * and other events. The clock requests counter from the core will
- * go down to zero since the core does not need it, but we will not
- * gate the clock, because there is somebody out there that may still
- * be using it.
- */
- return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING);
-}
-
-/**
- * mmc_host_clk_release - gate off hardware MCI clocks
- * @host: host to gate.
- *
- * Calls the host driver with ios.clock set to zero as often as possible
- * in order to gate off hardware MCI clocks. Decrease clock reference
- * count and schedule disabling of clock.
- */
-void mmc_host_clk_release(struct mmc_host *host)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&host->clk_lock, flags);
- host->clk_requests--;
- if (mmc_host_may_gate_card(host->card) &&
- !host->clk_requests)
- schedule_delayed_work(&host->clk_gate_work,
- msecs_to_jiffies(host->clkgate_delay));
- spin_unlock_irqrestore(&host->clk_lock, flags);
-}
-
-/**
- * mmc_host_clk_rate - get current clock frequency setting
- * @host: host to get the clock frequency for.
- *
- * Returns current clock frequency regardless of gating.
- */
-unsigned int mmc_host_clk_rate(struct mmc_host *host)
-{
- unsigned long freq;
- unsigned long flags;
-
- spin_lock_irqsave(&host->clk_lock, flags);
- if (host->clk_gated)
- freq = host->clk_old;
- else
- freq = host->ios.clock;
- spin_unlock_irqrestore(&host->clk_lock, flags);
- return freq;
-}
-
-/**
- * mmc_host_clk_init - set up clock gating code
- * @host: host with potential clock to control
- */
-static inline void mmc_host_clk_init(struct mmc_host *host)
-{
- host->clk_requests = 0;
- /* Hold MCI clock for 8 cycles by default */
- host->clk_delay = 8;
- /*
- * Default clock gating delay is 0ms to avoid wasting power.
- * This value can be tuned by writing into sysfs entry.
- */
- host->clkgate_delay = 0;
- host->clk_gated = false;
- INIT_DELAYED_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
- spin_lock_init(&host->clk_lock);
- mutex_init(&host->clk_gate_mutex);
-}
-
-/**
- * mmc_host_clk_exit - shut down clock gating code
- * @host: host with potential clock to control
- */
-static inline void mmc_host_clk_exit(struct mmc_host *host)
-{
- /*
- * Wait for any outstanding gate and then make sure we're
- * ungated before exiting.
- */
- if (cancel_delayed_work_sync(&host->clk_gate_work))
- mmc_host_clk_gate_delayed(host);
- if (host->clk_gated)
- mmc_host_clk_hold(host);
- /* There should be only one user now */
- WARN_ON(host->clk_requests > 1);
-}
-
-static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)
-{
- host->clkgate_delay_attr.show = clkgate_delay_show;
- host->clkgate_delay_attr.store = clkgate_delay_store;
- sysfs_attr_init(&host->clkgate_delay_attr.attr);
- host->clkgate_delay_attr.attr.name = "clkgate_delay";
- host->clkgate_delay_attr.attr.mode = S_IRUGO | S_IWUSR;
- if (device_create_file(&host->class_dev, &host->clkgate_delay_attr))
- pr_err("%s: Failed to create clkgate_delay sysfs entry\n",
- mmc_hostname(host));
-}
-#else
-
-static inline void mmc_host_clk_init(struct mmc_host *host)
-{
-}
-
-static inline void mmc_host_clk_exit(struct mmc_host *host)
-{
-}
-
-static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)
-{
-}
-
-#endif
-
void mmc_retune_enable(struct mmc_host *host)
{
host->can_retune = 1;
@@ -507,6 +267,8 @@ int mmc_of_parse(struct mmc_host *host)
host->caps |= MMC_CAP_UHS_DDR50;
if (of_property_read_bool(np, "cap-power-off-card"))
host->caps |= MMC_CAP_POWER_OFF_CARD;
+ if (of_property_read_bool(np, "cap-mmc-hw-reset"))
+ host->caps |= MMC_CAP_HW_RESET;
if (of_property_read_bool(np, "cap-sdio-irq"))
host->caps |= MMC_CAP_SDIO_IRQ;
if (of_property_read_bool(np, "full-pwr-cycle"))
@@ -583,8 +345,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
return NULL;
}
- mmc_host_clk_init(host);
-
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
@@ -633,7 +393,6 @@ int mmc_add_host(struct mmc_host *host)
#ifdef CONFIG_DEBUG_FS
mmc_add_host_debugfs(host);
#endif
- mmc_host_clk_sysfs_init(host);
mmc_start_host(host);
register_pm_notifier(&host->pm_notify);
@@ -663,8 +422,6 @@ void mmc_remove_host(struct mmc_host *host)
device_del(&host->class_dev);
led_trigger_unregister_simple(host->led);
-
- mmc_host_clk_exit(host);
}
EXPORT_SYMBOL(mmc_remove_host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index e726903170a8..3a9a79ec4343 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1040,9 +1040,24 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
return err;
}
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+ u32 status;
+ int err;
+
+ err = mmc_send_status(card, &status);
+ if (err)
+ return err;
+
+ return mmc_switch_status_error(card->host, status);
+}
+
static int mmc_select_hs400(struct mmc_card *card)
{
struct mmc_host *host = card->host;
+ bool send_status = true;
+ unsigned int max_dtr;
int err = 0;
u8 val;
@@ -1053,25 +1068,36 @@ static int mmc_select_hs400(struct mmc_card *card)
host->ios.bus_width == MMC_BUS_WIDTH_8))
return 0;
- /*
- * Before switching to dual data rate operation for HS400,
- * it is required to convert from HS200 mode to HS mode.
- */
- mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- mmc_set_bus_speed(card);
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ send_status = false;
+ /* Reduce frequency to HS frequency */
+ max_dtr = card->ext_csd.hs_max_dtr;
+ mmc_set_clock(host, max_dtr);
+
+ /* Switch card to HS mode */
val = EXT_CSD_TIMING_HS |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, true, true);
+ true, send_status, true);
if (err) {
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
mmc_hostname(host), err);
return err;
}
+ /* Set host controller to HS timing */
+ mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
+
+ /* Switch card to DDR */
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
EXT_CSD_DDR_BUS_WIDTH_8,
@@ -1082,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card)
return err;
}
+ /* Switch card to HS400 */
val = EXT_CSD_TIMING_HS400 |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, true, true);
+ true, send_status, true);
if (err) {
pr_err("%s: switch to hs400 failed, err:%d\n",
mmc_hostname(host), err);
return err;
}
+ /* Set host controller to HS400 timing and frequency */
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
mmc_set_bus_speed(card);
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
+
return 0;
+
+out_err:
+ pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
+ __func__, err);
+ return err;
}
int mmc_hs200_to_hs400(struct mmc_card *card)
@@ -1105,19 +1144,6 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
return mmc_select_hs400(card);
}
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
- u32 status;
- int err;
-
- err = mmc_send_status(card, &status);
- if (err)
- return err;
-
- return mmc_switch_status_error(card->host, status);
-}
-
int mmc_hs400_to_hs200(struct mmc_card *card)
{
struct mmc_host *host = card->host;
@@ -1219,6 +1245,8 @@ static void mmc_select_driver_type(struct mmc_card *card)
static int mmc_select_hs200(struct mmc_card *card)
{
struct mmc_host *host = card->host;
+ bool send_status = true;
+ unsigned int old_timing;
int err = -EINVAL;
u8 val;
@@ -1234,6 +1262,9 @@ static int mmc_select_hs200(struct mmc_card *card)
mmc_select_driver_type(card);
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ send_status = false;
+
/*
* Set the bus width(4 or 8) with host's support and
* switch to HS200 mode if bus width is set successfully.
@@ -1245,11 +1276,25 @@ static int mmc_select_hs200(struct mmc_card *card)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, true, true);
- if (!err)
- mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+ true, send_status, true);
+ if (err)
+ goto err;
+ old_timing = host->ios.timing;
+ mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ /*
+ * mmc_select_timing() assumes timing has not changed if
+ * it is a switch error.
+ */
+ if (err == -EBADMSG)
+ mmc_set_timing(host, old_timing);
+ }
}
err:
+ if (err)
+ pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
+ __func__, err);
return err;
}
@@ -1924,7 +1969,6 @@ EXPORT_SYMBOL(mmc_can_reset);
static int mmc_reset(struct mmc_host *host)
{
struct mmc_card *card = host->card;
- u32 status;
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
return -EOPNOTSUPP;
@@ -1932,20 +1976,12 @@ static int mmc_reset(struct mmc_host *host)
if (!mmc_can_reset(card))
return -EOPNOTSUPP;
- mmc_host_clk_hold(host);
mmc_set_clock(host, host->f_init);
host->ops->hw_reset(host);
- /* If the reset has happened, then a status command will fail */
- if (!mmc_send_status(card, &status)) {
- mmc_host_clk_release(host);
- return -ENOSYS;
- }
-
/* Set initial state and call mmc_set_ios */
mmc_set_initial_state(host);
- mmc_host_clk_release(host);
return mmc_init_card(host, card->ocr, card);
}
@@ -2013,14 +2049,13 @@ int mmc_attach_mmc(struct mmc_host *host)
mmc_release_host(host);
err = mmc_add_card(host->card);
- mmc_claim_host(host);
if (err)
goto remove_card;
+ mmc_claim_host(host);
return 0;
remove_card:
- mmc_release_host(host);
mmc_remove_card(host->card);
mmc_claim_host(host);
host->card = NULL;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 0e9ae1c276c8..1f444269ebbe 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -579,7 +579,6 @@ out:
return err;
}
-EXPORT_SYMBOL_GPL(__mmc_switch);
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms)
@@ -589,7 +588,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
}
EXPORT_SYMBOL_GPL(mmc_switch);
-int mmc_send_tuning(struct mmc_host *host)
+int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error)
{
struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
@@ -599,16 +598,13 @@ int mmc_send_tuning(struct mmc_host *host)
const u8 *tuning_block_pattern;
int size, err = 0;
u8 *data_buf;
- u32 opcode;
if (ios->bus_width == MMC_BUS_WIDTH_8) {
tuning_block_pattern = tuning_blk_pattern_8bit;
size = sizeof(tuning_blk_pattern_8bit);
- opcode = MMC_SEND_TUNING_BLOCK_HS200;
} else if (ios->bus_width == MMC_BUS_WIDTH_4) {
tuning_block_pattern = tuning_blk_pattern_4bit;
size = sizeof(tuning_blk_pattern_4bit);
- opcode = MMC_SEND_TUNING_BLOCK;
} else
return -EINVAL;
@@ -639,6 +635,9 @@ int mmc_send_tuning(struct mmc_host *host)
mmc_wait_for_req(host, &mrq);
+ if (cmd_error)
+ *cmd_error = cmd.error;
+
if (cmd.error) {
err = cmd.error;
goto out;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index f498f9ae21f0..f1b8e81aaa28 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -28,6 +28,9 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width);
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
int mmc_can_ext_csd(struct mmc_card *card);
int mmc_switch_status_error(struct mmc_host *host, u32 status);
+int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+ unsigned int timeout_ms, bool use_busy_signal, bool send_status,
+ bool ignore_crc);
#endif
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c
index 9d6d2fb21796..ad4f94ec7e8d 100644
--- a/drivers/mmc/core/pwrseq_emmc.c
+++ b/drivers/mmc/core/pwrseq_emmc.c
@@ -76,7 +76,7 @@ struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host,
if (!pwrseq)
return ERR_PTR(-ENOMEM);
- pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_LOW);
+ pwrseq->reset_gpio = gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(pwrseq->reset_gpio)) {
ret = PTR_ERR(pwrseq->reset_gpio);
goto free;
@@ -84,11 +84,11 @@ struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host,
/*
* register reset handler to ensure emmc reset also from
- * emergency_reboot(), priority 129 schedules it just before
- * system reboot
+ * emergency_reboot(), priority 255 is the highest priority
+ * so it will be executed before any system reboot handler.
*/
pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb;
- pwrseq->reset_nb.priority = 129;
+ pwrseq->reset_nb.priority = 255;
register_restart_handler(&pwrseq->reset_nb);
pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops;
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 0b14b83a53d6..d10538bb5e07 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -23,18 +23,21 @@ struct mmc_pwrseq_simple {
struct mmc_pwrseq pwrseq;
bool clk_enabled;
struct clk *ext_clk;
- int nr_gpios;
- struct gpio_desc *reset_gpios[0];
+ struct gpio_descs *reset_gpios;
};
static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
int value)
{
int i;
+ struct gpio_descs *reset_gpios = pwrseq->reset_gpios;
+ int values[reset_gpios->ndescs];
- for (i = 0; i < pwrseq->nr_gpios; i++)
- if (!IS_ERR(pwrseq->reset_gpios[i]))
- gpiod_set_value_cansleep(pwrseq->reset_gpios[i], value);
+ for (i = 0; i < reset_gpios->ndescs; i++)
+ values[i] = value;
+
+ gpiod_set_array_value_cansleep(reset_gpios->ndescs, reset_gpios->desc,
+ values);
}
static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
@@ -75,11 +78,8 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq,
struct mmc_pwrseq_simple, pwrseq);
- int i;
- for (i = 0; i < pwrseq->nr_gpios; i++)
- if (!IS_ERR(pwrseq->reset_gpios[i]))
- gpiod_put(pwrseq->reset_gpios[i]);
+ gpiod_put_array(pwrseq->reset_gpios);
if (!IS_ERR(pwrseq->ext_clk))
clk_put(pwrseq->ext_clk);
@@ -98,14 +98,9 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host,
struct device *dev)
{
struct mmc_pwrseq_simple *pwrseq;
- int i, nr_gpios, ret = 0;
-
- nr_gpios = of_gpio_named_count(dev->of_node, "reset-gpios");
- if (nr_gpios < 0)
- nr_gpios = 0;
+ int ret = 0;
- pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple) + nr_gpios *
- sizeof(struct gpio_desc *), GFP_KERNEL);
+ pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
if (!pwrseq)
return ERR_PTR(-ENOMEM);
@@ -116,22 +111,12 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host,
goto free;
}
- for (i = 0; i < nr_gpios; i++) {
- pwrseq->reset_gpios[i] = gpiod_get_index(dev, "reset", i,
- GPIOD_OUT_HIGH);
- if (IS_ERR(pwrseq->reset_gpios[i]) &&
- PTR_ERR(pwrseq->reset_gpios[i]) != -ENOENT &&
- PTR_ERR(pwrseq->reset_gpios[i]) != -ENOSYS) {
- ret = PTR_ERR(pwrseq->reset_gpios[i]);
-
- while (i--)
- gpiod_put(pwrseq->reset_gpios[i]);
-
- goto clk_put;
- }
+ pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(pwrseq->reset_gpios)) {
+ ret = PTR_ERR(pwrseq->reset_gpios);
+ goto clk_put;
}
- pwrseq->nr_gpios = nr_gpios;
pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
return &pwrseq->pwrseq;
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index dd1d1e0fe322..fad660b95809 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -35,25 +35,7 @@
#define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128
#endif
-/*
- * This hook just adds a quirk for all sdio devices
- */
-static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
-{
- if (mmc_card_sdio(card))
- card->quirks |= data;
-}
-
static const struct mmc_fixup mmc_fixup_methods[] = {
- /* by default sdio devices are considered CLK_GATING broken */
- /* good cards will be whitelisted as they are tested */
- SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID,
- add_quirk_for_sdio_devices,
- MMC_QUIRK_BROKEN_CLK_GATING),
-
- SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
- remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),
-
SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 4e7366ab187f..141eaa923e18 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -357,8 +357,6 @@ int mmc_sd_switch_hs(struct mmc_card *card)
if (card->sw_caps.hs_max_dtr == 0)
return 0;
- err = -EIO;
-
status = kmalloc(64, GFP_KERNEL);
if (!status) {
pr_err("%s: could not allocate a buffer for "
@@ -628,9 +626,25 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
* SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
*/
if (!mmc_host_is_spi(card->host) &&
- (card->sd_bus_speed == UHS_SDR50_BUS_SPEED ||
- card->sd_bus_speed == UHS_SDR104_BUS_SPEED))
+ (card->sd_bus_speed == UHS_SDR50_BUS_SPEED ||
+ card->sd_bus_speed == UHS_DDR50_BUS_SPEED ||
+ card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) {
err = mmc_execute_tuning(card);
+
+ /*
+ * As SD Specifications Part1 Physical Layer Specification
+ * Version 3.01 says, CMD19 tuning is available for unlocked
+ * cards in transfer state of 1.8V signaling mode. The small
+ * difference between v3.00 and 3.01 spec means that CMD19
+ * tuning is also available for DDR50 mode.
+ */
+ if (err && card->sd_bus_speed == UHS_DDR50_BUS_SPEED) {
+ pr_warn("%s: ddr50 tuning failed\n",
+ mmc_hostname(card->host));
+ err = 0;
+ }
+ }
+
out:
kfree(status);
@@ -786,9 +800,7 @@ static int mmc_sd_get_ro(struct mmc_host *host)
if (!host->ops->get_ro)
return -1;
- mmc_host_clk_hold(host);
ro = host->ops->get_ro(host);
- mmc_host_clk_release(host);
return ro;
}
@@ -1231,14 +1243,13 @@ int mmc_attach_sd(struct mmc_host *host)
mmc_release_host(host);
err = mmc_add_card(host->card);
- mmc_claim_host(host);
if (err)
goto remove_card;
+ mmc_claim_host(host);
return 0;
remove_card:
- mmc_release_host(host);
mmc_remove_card(host->card);
host->card = NULL;
mmc_claim_host(host);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index b91abedcfdca..16d838e6d623 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -897,11 +897,10 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
*/
static int mmc_sdio_suspend(struct mmc_host *host)
{
- if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
- mmc_claim_host(host);
+ mmc_claim_host(host);
+
+ if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host))
sdio_disable_wide(host->card);
- mmc_release_host(host);
- }
if (!mmc_card_keep_power(host)) {
mmc_power_off(host);
@@ -910,6 +909,8 @@ static int mmc_sdio_suspend(struct mmc_host *host)
mmc_retune_needed(host);
}
+ mmc_release_host(host);
+
return 0;
}
@@ -955,13 +956,10 @@ static int mmc_sdio_resume(struct mmc_host *host)
}
if (!err && host->sdio_irqs) {
- if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
+ if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread);
- } else if (host->caps & MMC_CAP_SDIO_IRQ) {
- mmc_host_clk_hold(host);
+ else if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 1);
- mmc_host_clk_release(host);
- }
}
mmc_release_host(host);
@@ -1018,15 +1016,24 @@ out:
static int mmc_sdio_runtime_suspend(struct mmc_host *host)
{
/* No references to the card, cut the power to it. */
+ mmc_claim_host(host);
mmc_power_off(host);
+ mmc_release_host(host);
+
return 0;
}
static int mmc_sdio_runtime_resume(struct mmc_host *host)
{
+ int ret;
+
/* Restore power and re-initialize. */
+ mmc_claim_host(host);
mmc_power_up(host, host->card->ocr);
- return mmc_sdio_power_restore(host);
+ ret = mmc_sdio_power_restore(host);
+ mmc_release_host(host);
+
+ return ret;
}
static int mmc_sdio_reset(struct mmc_host *host)
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 09cc67d028f0..91bbbfb29f3f 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -168,21 +168,15 @@ static int sdio_irq_thread(void *_host)
}
set_current_state(TASK_INTERRUPTIBLE);
- if (host->caps & MMC_CAP_SDIO_IRQ) {
- mmc_host_clk_hold(host);
+ if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 1);
- mmc_host_clk_release(host);
- }
if (!kthread_should_stop())
schedule_timeout(period);
set_current_state(TASK_RUNNING);
} while (!kthread_should_stop());
- if (host->caps & MMC_CAP_SDIO_IRQ) {
- mmc_host_clk_hold(host);
+ if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 0);
- mmc_host_clk_release(host);
- }
pr_debug("%s: IRQ thread exiting with code %d\n",
mmc_hostname(host), ret);
@@ -208,9 +202,7 @@ static int sdio_card_irq_get(struct mmc_card *card)
return err;
}
} else if (host->caps & MMC_CAP_SDIO_IRQ) {
- mmc_host_clk_hold(host);
host->ops->enable_sdio_irq(host, 1);
- mmc_host_clk_release(host);
}
}
@@ -229,9 +221,7 @@ static int sdio_card_irq_put(struct mmc_card *card)
atomic_set(&host->sdio_irq_thread_abort, 1);
kthread_stop(host->sdio_irq_thread);
} else if (host->caps & MMC_CAP_SDIO_IRQ) {
- mmc_host_clk_hold(host);
host->ops->enable_sdio_irq(host, 0);
- mmc_host_clk_release(host);
}
}
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index 12a4d3ab174c..5660c7f459e9 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -12,6 +12,8 @@
#ifndef _MMC_SDIO_OPS_H
#define _MMC_SDIO_OPS_H
+#include <linux/mmc/sdio.h>
+
int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8* out);
@@ -19,5 +21,10 @@ 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);
+static inline bool mmc_is_io_op(u32 opcode)
+{
+ return opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED;
+}
+
#endif
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 8a1e3498261e..1dee533634c9 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -67,7 +67,7 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
has the effect of scrambling the addresses and formats of data
accessed in sizes other than the datum size.
- This is the case for the Freescale eSDHC and Nintendo Wii SDHCI.
+ This is the case for the Nintendo Wii SDHCI.
config MMC_SDHCI_PCI
tristate "SDHCI support on PCI bus"
@@ -140,8 +140,8 @@ config MMC_SDHCI_OF_AT91
config MMC_SDHCI_OF_ESDHC
tristate "SDHCI OF support for the Freescale eSDHC controller"
depends on MMC_SDHCI_PLTFM
- depends on PPC
- select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+ depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
+ select MMC_SDHCI_IO_ACCESSORS
help
This selects the Freescale eSDHC controller support.
@@ -366,7 +366,7 @@ config MMC_OMAP
config MMC_OMAP_HS
tristate "TI OMAP High Speed Multimedia Card Interface support"
depends on HAS_DMA
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
+ depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST
help
This selects the TI OMAP High Speed Multimedia card Interface.
If you have an omap2plus board with a Multimedia Card slot,
@@ -473,7 +473,8 @@ config MMC_DAVINCI
config MMC_GOLDFISH
tristate "goldfish qemu Multimedia Card Interface support"
- depends on GOLDFISH
+ depends on HAS_DMA
+ depends on GOLDFISH || COMPILE_TEST
help
This selects the Goldfish Multimedia card Interface emulation
found on the Goldfish Android virtual device emulation.
@@ -615,15 +616,7 @@ config MMC_DW
help
This selects support for the Synopsys DesignWare Mobile Storage IP
block, this provides host support for SD and MMC interfaces, in both
- PIO and external DMA modes.
-
-config MMC_DW_IDMAC
- bool "Internal DMAC interface"
- depends on MMC_DW
- help
- This selects support for the internal DMAC block within the Synopsys
- Designware Mobile Storage IP block. This disables the external DMA
- interface.
+ PIO, internal DMA mode and external DMA mode.
config MMC_DW_PLTFM
tristate "Synopsys Designware MCI Support as platform device"
@@ -652,7 +645,6 @@ config MMC_DW_K3
tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
depends on MMC_DW
select MMC_DW_PLTFM
- select MMC_DW_IDMAC
help
This selects support for Hisilicon K3 SoC specific extensions to the
Synopsys DesignWare Memory Card Interface driver. Select this option
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 4f3452afa6ca..3595f83e89dd 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,8 +9,8 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o
obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o
-obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-o2micro.o
obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o
obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 1e75309898b7..3a7e835a0033 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -446,7 +446,7 @@ out:
return loc;
}
-static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
+static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
{
struct dw_mci *host = slot->host;
struct dw_mci_exynos_priv_data *priv = host->priv;
@@ -461,7 +461,7 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
mci_writel(host, TMOUT, ~0);
smpl = dw_mci_exynos_move_next_clksmpl(host);
- if (!mmc_send_tuning(mmc))
+ if (!mmc_send_tuning(mmc, opcode, NULL))
candiates |= (1 << smpl);
} while (start_smpl != smpl);
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index ec6dbcdec693..7e1d13b68b06 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -59,6 +59,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
host->pdata = pdev->dev.platform_data;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ /* Get registers' physical base address */
+ host->phy_regs = (void *)(regs->start);
host->regs = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(host->regs))
return PTR_ERR(host->regs);
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index bc76aa22473e..9becebeeccd1 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -13,12 +13,19 @@
#include <linux/mmc/host.h>
#include <linux/mmc/dw_mmc.h>
#include <linux/of_address.h>
+#include <linux/slab.h>
#include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
#define RK3288_CLKGEN_DIV 2
+struct dw_mci_rockchip_priv_data {
+ struct clk *drv_clk;
+ struct clk *sample_clk;
+ int default_sample_phase;
+};
+
static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
{
*cmdr |= SDMMC_CMD_USE_HOLD_REG;
@@ -33,6 +40,7 @@ static int dw_mci_rk3288_setup_clock(struct dw_mci *host)
static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
+ struct dw_mci_rockchip_priv_data *priv = host->priv;
int ret;
unsigned int cclkin;
u32 bus_hz;
@@ -66,6 +74,158 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
/* force dw_mci_setup_bus() */
host->current_speed = 0;
}
+
+ /* Make sure we use phases which we can enumerate with */
+ if (!IS_ERR(priv->sample_clk))
+ clk_set_phase(priv->sample_clk, priv->default_sample_phase);
+}
+
+#define NUM_PHASES 360
+#define TUNING_ITERATION_TO_PHASE(i) (DIV_ROUND_UP((i) * 360, NUM_PHASES))
+
+static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
+{
+ struct dw_mci *host = slot->host;
+ struct dw_mci_rockchip_priv_data *priv = host->priv;
+ struct mmc_host *mmc = slot->mmc;
+ int ret = 0;
+ int i;
+ bool v, prev_v = 0, first_v;
+ struct range_t {
+ int start;
+ int end; /* inclusive */
+ };
+ struct range_t *ranges;
+ unsigned int range_count = 0;
+ int longest_range_len = -1;
+ int longest_range = -1;
+ int middle_phase;
+
+ if (IS_ERR(priv->sample_clk)) {
+ dev_err(host->dev, "Tuning clock (sample_clk) not defined.\n");
+ return -EIO;
+ }
+
+ ranges = kmalloc_array(NUM_PHASES / 2 + 1, sizeof(*ranges), GFP_KERNEL);
+ if (!ranges)
+ return -ENOMEM;
+
+ /* Try each phase and extract good ranges */
+ for (i = 0; i < NUM_PHASES; ) {
+ clk_set_phase(priv->sample_clk, TUNING_ITERATION_TO_PHASE(i));
+
+ v = !mmc_send_tuning(mmc, opcode, NULL);
+
+ if (i == 0)
+ first_v = v;
+
+ if ((!prev_v) && v) {
+ range_count++;
+ ranges[range_count-1].start = i;
+ }
+ if (v) {
+ ranges[range_count-1].end = i;
+ i++;
+ } else if (i == NUM_PHASES - 1) {
+ /* No extra skipping rules if we're at the end */
+ i++;
+ } else {
+ /*
+ * No need to check too close to an invalid
+ * one since testing bad phases is slow. Skip
+ * 20 degrees.
+ */
+ i += DIV_ROUND_UP(20 * NUM_PHASES, 360);
+
+ /* Always test the last one */
+ if (i >= NUM_PHASES)
+ i = NUM_PHASES - 1;
+ }
+
+ prev_v = v;
+ }
+
+ if (range_count == 0) {
+ dev_warn(host->dev, "All phases bad!");
+ ret = -EIO;
+ goto free;
+ }
+
+ /* wrap around case, merge the end points */
+ if ((range_count > 1) && first_v && v) {
+ ranges[0].start = ranges[range_count-1].start;
+ range_count--;
+ }
+
+ if (ranges[0].start == 0 && ranges[0].end == NUM_PHASES - 1) {
+ clk_set_phase(priv->sample_clk, priv->default_sample_phase);
+ dev_info(host->dev, "All phases work, using default phase %d.",
+ priv->default_sample_phase);
+ goto free;
+ }
+
+ /* Find the longest range */
+ for (i = 0; i < range_count; i++) {
+ int len = (ranges[i].end - ranges[i].start + 1);
+
+ if (len < 0)
+ len += NUM_PHASES;
+
+ if (longest_range_len < len) {
+ longest_range_len = len;
+ longest_range = i;
+ }
+
+ dev_dbg(host->dev, "Good phase range %d-%d (%d len)\n",
+ TUNING_ITERATION_TO_PHASE(ranges[i].start),
+ TUNING_ITERATION_TO_PHASE(ranges[i].end),
+ len
+ );
+ }
+
+ dev_dbg(host->dev, "Best phase range %d-%d (%d len)\n",
+ TUNING_ITERATION_TO_PHASE(ranges[longest_range].start),
+ TUNING_ITERATION_TO_PHASE(ranges[longest_range].end),
+ longest_range_len
+ );
+
+ middle_phase = ranges[longest_range].start + longest_range_len / 2;
+ middle_phase %= NUM_PHASES;
+ dev_info(host->dev, "Successfully tuned phase to %d\n",
+ TUNING_ITERATION_TO_PHASE(middle_phase));
+
+ clk_set_phase(priv->sample_clk,
+ TUNING_ITERATION_TO_PHASE(middle_phase));
+
+free:
+ kfree(ranges);
+ return ret;
+}
+
+static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
+{
+ struct device_node *np = host->dev->of_node;
+ struct dw_mci_rockchip_priv_data *priv;
+
+ priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ if (of_property_read_u32(np, "rockchip,default-sample-phase",
+ &priv->default_sample_phase))
+ priv->default_sample_phase = 0;
+
+ priv->drv_clk = devm_clk_get(host->dev, "ciu-drive");
+ if (IS_ERR(priv->drv_clk))
+ dev_dbg(host->dev, "ciu_drv not available\n");
+
+ priv->sample_clk = devm_clk_get(host->dev, "ciu-sample");
+ if (IS_ERR(priv->sample_clk))
+ dev_dbg(host->dev, "ciu_sample not available\n");
+
+ host->priv = priv;
+
+ return 0;
}
static int dw_mci_rockchip_init(struct dw_mci *host)
@@ -95,6 +255,8 @@ static const struct dw_mci_drv_data rk3288_drv_data = {
.caps = dw_mci_rk3288_dwmmc_caps,
.prepare_command = dw_mci_rockchip_prepare_command,
.set_ios = dw_mci_rk3288_set_ios,
+ .execute_tuning = dw_mci_rk3288_execute_tuning,
+ .parse_dt = dw_mci_rk3288_parse_dt,
.setup_clock = dw_mci_rk3288_setup_clock,
.init = dw_mci_rockchip_init,
};
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index fcbf5524fd31..7a6cedbe48a8 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -56,7 +56,6 @@
#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */
#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */
-#ifdef CONFIG_MMC_DW_IDMAC
#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
@@ -102,7 +101,6 @@ struct idmac_desc {
/* Each descriptor can transfer up to 4KB of data in chained mode */
#define DW_MCI_DESC_DATA_LENGTH 0x1000
-#endif /* CONFIG_MMC_DW_IDMAC */
static bool dw_mci_reset(struct dw_mci *host);
static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset);
@@ -407,7 +405,6 @@ static int dw_mci_get_dma_dir(struct mmc_data *data)
return DMA_FROM_DEVICE;
}
-#ifdef CONFIG_MMC_DW_IDMAC
static void dw_mci_dma_cleanup(struct dw_mci *host)
{
struct mmc_data *data = host->data;
@@ -445,12 +442,21 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
mci_writel(host, BMOD, temp);
}
-static void dw_mci_idmac_complete_dma(struct dw_mci *host)
+static void dw_mci_dmac_complete_dma(void *arg)
{
+ struct dw_mci *host = arg;
struct mmc_data *data = host->data;
dev_vdbg(host->dev, "DMA complete\n");
+ if ((host->use_dma == TRANS_MODE_EDMAC) &&
+ data && (data->flags & MMC_DATA_READ))
+ /* Invalidate cache after read */
+ dma_sync_sg_for_cpu(mmc_dev(host->cur_slot->mmc),
+ data->sg,
+ data->sg_len,
+ DMA_FROM_DEVICE);
+
host->dma_ops->cleanup(host);
/*
@@ -564,7 +570,7 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
wmb(); /* drain writebuffer */
}
-static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
+static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
{
u32 temp;
@@ -589,6 +595,8 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
/* Start it running */
mci_writel(host, PLDMND, 1);
+
+ return 0;
}
static int dw_mci_idmac_init(struct dw_mci *host)
@@ -669,10 +677,110 @@ static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
.init = dw_mci_idmac_init,
.start = dw_mci_idmac_start_dma,
.stop = dw_mci_idmac_stop_dma,
- .complete = dw_mci_idmac_complete_dma,
+ .complete = dw_mci_dmac_complete_dma,
+ .cleanup = dw_mci_dma_cleanup,
+};
+
+static void dw_mci_edmac_stop_dma(struct dw_mci *host)
+{
+ dmaengine_terminate_all(host->dms->ch);
+}
+
+static int dw_mci_edmac_start_dma(struct dw_mci *host,
+ unsigned int sg_len)
+{
+ struct dma_slave_config cfg;
+ struct dma_async_tx_descriptor *desc = NULL;
+ struct scatterlist *sgl = host->data->sg;
+ const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256};
+ u32 sg_elems = host->data->sg_len;
+ u32 fifoth_val;
+ u32 fifo_offset = host->fifo_reg - host->regs;
+ int ret = 0;
+
+ /* Set external dma config: burst size, burst width */
+ cfg.dst_addr = (dma_addr_t)(host->phy_regs + fifo_offset);
+ cfg.src_addr = cfg.dst_addr;
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+ /* Match burst msize with external dma config */
+ fifoth_val = mci_readl(host, FIFOTH);
+ cfg.dst_maxburst = mszs[(fifoth_val >> 28) & 0x7];
+ cfg.src_maxburst = cfg.dst_maxburst;
+
+ if (host->data->flags & MMC_DATA_WRITE)
+ cfg.direction = DMA_MEM_TO_DEV;
+ else
+ cfg.direction = DMA_DEV_TO_MEM;
+
+ ret = dmaengine_slave_config(host->dms->ch, &cfg);
+ if (ret) {
+ dev_err(host->dev, "Failed to config edmac.\n");
+ return -EBUSY;
+ }
+
+ desc = dmaengine_prep_slave_sg(host->dms->ch, sgl,
+ sg_len, cfg.direction,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(host->dev, "Can't prepare slave sg.\n");
+ return -EBUSY;
+ }
+
+ /* Set dw_mci_dmac_complete_dma as callback */
+ desc->callback = dw_mci_dmac_complete_dma;
+ desc->callback_param = (void *)host;
+ dmaengine_submit(desc);
+
+ /* Flush cache before write */
+ if (host->data->flags & MMC_DATA_WRITE)
+ dma_sync_sg_for_device(mmc_dev(host->cur_slot->mmc), sgl,
+ sg_elems, DMA_TO_DEVICE);
+
+ dma_async_issue_pending(host->dms->ch);
+
+ return 0;
+}
+
+static int dw_mci_edmac_init(struct dw_mci *host)
+{
+ /* Request external dma channel */
+ host->dms = kzalloc(sizeof(struct dw_mci_dma_slave), GFP_KERNEL);
+ if (!host->dms)
+ return -ENOMEM;
+
+ host->dms->ch = dma_request_slave_channel(host->dev, "rx-tx");
+ if (!host->dms->ch) {
+ dev_err(host->dev, "Failed to get external DMA channel.\n");
+ kfree(host->dms);
+ host->dms = NULL;
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void dw_mci_edmac_exit(struct dw_mci *host)
+{
+ if (host->dms) {
+ if (host->dms->ch) {
+ dma_release_channel(host->dms->ch);
+ host->dms->ch = NULL;
+ }
+ kfree(host->dms);
+ host->dms = NULL;
+ }
+}
+
+static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
+ .init = dw_mci_edmac_init,
+ .exit = dw_mci_edmac_exit,
+ .start = dw_mci_edmac_start_dma,
+ .stop = dw_mci_edmac_stop_dma,
+ .complete = dw_mci_dmac_complete_dma,
.cleanup = dw_mci_dma_cleanup,
};
-#endif /* CONFIG_MMC_DW_IDMAC */
static int dw_mci_pre_dma_transfer(struct dw_mci *host,
struct mmc_data *data,
@@ -752,7 +860,6 @@ static void dw_mci_post_req(struct mmc_host *mmc,
static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
{
-#ifdef CONFIG_MMC_DW_IDMAC
unsigned int blksz = data->blksz;
const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256};
u32 fifo_width = 1 << host->data_shift;
@@ -760,6 +867,10 @@ static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers;
int idx = ARRAY_SIZE(mszs) - 1;
+ /* pio should ship this scenario */
+ if (!host->use_dma)
+ return;
+
tx_wmark = (host->fifo_depth) / 2;
tx_wmark_invers = host->fifo_depth - tx_wmark;
@@ -788,7 +899,6 @@ static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
done:
fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark);
mci_writel(host, FIFOTH, fifoth_val);
-#endif
}
static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
@@ -850,10 +960,12 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
host->using_dma = 1;
- dev_vdbg(host->dev,
- "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
- (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
- sg_len);
+ if (host->use_dma == TRANS_MODE_IDMAC)
+ dev_vdbg(host->dev,
+ "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
+ (unsigned long)host->sg_cpu,
+ (unsigned long)host->sg_dma,
+ sg_len);
/*
* Decide the MSIZE and RX/TX Watermark.
@@ -875,7 +987,11 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
mci_writel(host, INTMASK, temp);
spin_unlock_irqrestore(&host->irq_lock, irqflags);
- host->dma_ops->start(host, sg_len);
+ if (host->dma_ops->start(host, sg_len)) {
+ /* We can't do DMA */
+ dev_err(host->dev, "%s: failed to start DMA.\n", __func__);
+ return -ENODEV;
+ }
return 0;
}
@@ -1177,6 +1293,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* DDR mode set */
if (ios->timing == MMC_TIMING_MMC_DDR52 ||
+ ios->timing == MMC_TIMING_UHS_DDR50 ||
ios->timing == MMC_TIMING_MMC_HS400)
regs |= ((0x1 << slot->id) << 16);
else
@@ -1279,7 +1396,6 @@ static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
const struct dw_mci_drv_data *drv_data = host->drv_data;
u32 uhs;
u32 v18 = SDMMC_UHS_18V << slot->id;
- int min_uv, max_uv;
int ret;
if (drv_data && drv_data->switch_voltage)
@@ -1291,22 +1407,18 @@ static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
* does no harm but you need to set the regulator directly. Try both.
*/
uhs = mci_readl(host, UHS_REG);
- if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
- min_uv = 2700000;
- max_uv = 3600000;
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
uhs &= ~v18;
- } else {
- min_uv = 1700000;
- max_uv = 1950000;
+ else
uhs |= v18;
- }
+
if (!IS_ERR(mmc->supply.vqmmc)) {
- ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv);
+ ret = mmc_regulator_set_vqmmc(mmc, ios);
if (ret) {
dev_dbg(&mmc->class_dev,
- "Regulator set error %d: %d - %d\n",
- ret, min_uv, max_uv);
+ "Regulator set error %d - %s V\n",
+ ret, uhs & v18 ? "1.8" : "3.3");
return ret;
}
}
@@ -1427,7 +1539,7 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
int err = -EINVAL;
if (drv_data && drv_data->execute_tuning)
- err = drv_data->execute_tuning(slot);
+ err = drv_data->execute_tuning(slot, opcode);
return err;
}
@@ -2343,15 +2455,17 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
}
-#ifdef CONFIG_MMC_DW_IDMAC
- /* Handle DMA interrupts */
+ if (host->use_dma != TRANS_MODE_IDMAC)
+ return IRQ_HANDLED;
+
+ /* Handle IDMA interrupts */
if (host->dma_64bit_address == 1) {
pending = mci_readl(host, IDSTS64);
if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI |
SDMMC_IDMAC_INT_RI);
mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI);
- host->dma_ops->complete(host);
+ host->dma_ops->complete((void *)host);
}
} else {
pending = mci_readl(host, IDSTS);
@@ -2359,10 +2473,9 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI |
SDMMC_IDMAC_INT_RI);
mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
- host->dma_ops->complete(host);
+ host->dma_ops->complete((void *)host);
}
}
-#endif
return IRQ_HANDLED;
}
@@ -2471,13 +2584,21 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
goto err_host_allocated;
/* Useful defaults if platform data is unset. */
- if (host->use_dma) {
+ if (host->use_dma == TRANS_MODE_IDMAC) {
mmc->max_segs = host->ring_size;
mmc->max_blk_size = 65536;
mmc->max_seg_size = 0x1000;
mmc->max_req_size = mmc->max_seg_size * host->ring_size;
mmc->max_blk_count = mmc->max_req_size / 512;
+ } else if (host->use_dma == TRANS_MODE_EDMAC) {
+ mmc->max_segs = 64;
+ mmc->max_blk_size = 65536;
+ mmc->max_blk_count = 65535;
+ mmc->max_req_size =
+ mmc->max_blk_size * mmc->max_blk_count;
+ mmc->max_seg_size = mmc->max_req_size;
} else {
+ /* TRANS_MODE_PIO */
mmc->max_segs = 64;
mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
mmc->max_blk_count = 512;
@@ -2517,38 +2638,74 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
static void dw_mci_init_dma(struct dw_mci *host)
{
int addr_config;
- /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus width */
- addr_config = (mci_readl(host, HCON) >> 27) & 0x01;
-
- if (addr_config == 1) {
- /* host supports IDMAC in 64-bit address mode */
- host->dma_64bit_address = 1;
- dev_info(host->dev, "IDMAC supports 64-bit address mode.\n");
- if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
- dma_set_coherent_mask(host->dev, DMA_BIT_MASK(64));
- } else {
- /* host supports IDMAC in 32-bit address mode */
- host->dma_64bit_address = 0;
- dev_info(host->dev, "IDMAC supports 32-bit address mode.\n");
- }
+ struct device *dev = host->dev;
+ struct device_node *np = dev->of_node;
- /* Alloc memory for sg translation */
- host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
- &host->sg_dma, GFP_KERNEL);
- if (!host->sg_cpu) {
- dev_err(host->dev, "%s: could not alloc DMA memory\n",
- __func__);
+ /*
+ * Check tansfer mode from HCON[17:16]
+ * Clear the ambiguous description of dw_mmc databook:
+ * 2b'00: No DMA Interface -> Actually means using Internal DMA block
+ * 2b'01: DesignWare DMA Interface -> Synopsys DW-DMA block
+ * 2b'10: Generic DMA Interface -> non-Synopsys generic DMA block
+ * 2b'11: Non DW DMA Interface -> pio only
+ * Compared to DesignWare DMA Interface, Generic DMA Interface has a
+ * simpler request/acknowledge handshake mechanism and both of them
+ * are regarded as external dma master for dw_mmc.
+ */
+ host->use_dma = SDMMC_GET_TRANS_MODE(mci_readl(host, HCON));
+ if (host->use_dma == DMA_INTERFACE_IDMA) {
+ host->use_dma = TRANS_MODE_IDMAC;
+ } else if (host->use_dma == DMA_INTERFACE_DWDMA ||
+ host->use_dma == DMA_INTERFACE_GDMA) {
+ host->use_dma = TRANS_MODE_EDMAC;
+ } else {
goto no_dma;
}
/* Determine which DMA interface to use */
-#ifdef CONFIG_MMC_DW_IDMAC
- host->dma_ops = &dw_mci_idmac_ops;
- dev_info(host->dev, "Using internal DMA controller.\n");
-#endif
+ if (host->use_dma == TRANS_MODE_IDMAC) {
+ /*
+ * Check ADDR_CONFIG bit in HCON to find
+ * IDMAC address bus width
+ */
+ addr_config = SDMMC_GET_ADDR_CONFIG(mci_readl(host, HCON));
+
+ if (addr_config == 1) {
+ /* host supports IDMAC in 64-bit address mode */
+ host->dma_64bit_address = 1;
+ dev_info(host->dev,
+ "IDMAC supports 64-bit address mode.\n");
+ if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
+ dma_set_coherent_mask(host->dev,
+ DMA_BIT_MASK(64));
+ } else {
+ /* host supports IDMAC in 32-bit address mode */
+ host->dma_64bit_address = 0;
+ dev_info(host->dev,
+ "IDMAC supports 32-bit address mode.\n");
+ }
- if (!host->dma_ops)
- goto no_dma;
+ /* Alloc memory for sg translation */
+ host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
+ &host->sg_dma, GFP_KERNEL);
+ if (!host->sg_cpu) {
+ dev_err(host->dev,
+ "%s: could not alloc DMA memory\n",
+ __func__);
+ goto no_dma;
+ }
+
+ host->dma_ops = &dw_mci_idmac_ops;
+ dev_info(host->dev, "Using internal DMA controller.\n");
+ } else {
+ /* TRANS_MODE_EDMAC: check dma bindings again */
+ if ((of_property_count_strings(np, "dma-names") < 0) ||
+ (!of_find_property(np, "dmas", NULL))) {
+ goto no_dma;
+ }
+ host->dma_ops = &dw_mci_edmac_ops;
+ dev_info(host->dev, "Using external DMA controller.\n");
+ }
if (host->dma_ops->init && host->dma_ops->start &&
host->dma_ops->stop && host->dma_ops->cleanup) {
@@ -2562,12 +2719,11 @@ static void dw_mci_init_dma(struct dw_mci *host)
goto no_dma;
}
- host->use_dma = 1;
return;
no_dma:
dev_info(host->dev, "Using PIO mode.\n");
- host->use_dma = 0;
+ host->use_dma = TRANS_MODE_PIO;
}
static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
@@ -2650,10 +2806,9 @@ static bool dw_mci_reset(struct dw_mci *host)
}
}
-#if IS_ENABLED(CONFIG_MMC_DW_IDMAC)
- /* It is also recommended that we reset and reprogram idmac */
- dw_mci_idmac_reset(host);
-#endif
+ if (host->use_dma == TRANS_MODE_IDMAC)
+ /* It is also recommended that we reset and reprogram idmac */
+ dw_mci_idmac_reset(host);
ret = true;
@@ -2890,7 +3045,7 @@ int dw_mci_probe(struct dw_mci *host)
* Get the host data width - this assumes that HCON has been set with
* the correct values.
*/
- i = (mci_readl(host, HCON) >> 7) & 0x7;
+ i = SDMMC_GET_HDATA_WIDTH(mci_readl(host, HCON));
if (!i) {
host->push_data = dw_mci_push_data16;
host->pull_data = dw_mci_pull_data16;
@@ -2972,7 +3127,7 @@ int dw_mci_probe(struct dw_mci *host)
if (host->pdata->num_slots)
host->num_slots = host->pdata->num_slots;
else
- host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
+ host->num_slots = SDMMC_GET_SLOT_NUM(mci_readl(host, HCON));
/*
* Enable interrupts for command done, data over, data empty,
@@ -3067,6 +3222,9 @@ EXPORT_SYMBOL(dw_mci_remove);
*/
int dw_mci_suspend(struct dw_mci *host)
{
+ if (host->use_dma && host->dma_ops->exit)
+ host->dma_ops->exit(host);
+
return 0;
}
EXPORT_SYMBOL(dw_mci_suspend);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 8ce4674730a6..f695b58f0613 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -148,6 +148,15 @@
#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \
((r) & 0xFFF) << 16 | \
((t) & 0xFFF))
+/* HCON register defines */
+#define DMA_INTERFACE_IDMA (0x0)
+#define DMA_INTERFACE_DWDMA (0x1)
+#define DMA_INTERFACE_GDMA (0x2)
+#define DMA_INTERFACE_NODMA (0x3)
+#define SDMMC_GET_TRANS_MODE(x) (((x)>>16) & 0x3)
+#define SDMMC_GET_SLOT_NUM(x) ((((x)>>1) & 0x1F) + 1)
+#define SDMMC_GET_HDATA_WIDTH(x) (((x)>>7) & 0x7)
+#define SDMMC_GET_ADDR_CONFIG(x) (((x)>>27) & 0x1)
/* Internal DMAC interrupt defines */
#define SDMMC_IDMAC_INT_AI BIT(9)
#define SDMMC_IDMAC_INT_NI BIT(8)
@@ -163,7 +172,7 @@
/* Version ID register define */
#define SDMMC_GET_VERID(x) ((x) & 0xFFFF)
/* Card read threshold */
-#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x))
+#define SDMMC_SET_RD_THLD(v, x) (((v) & 0xFFF) << 16 | (x))
#define SDMMC_UHS_18V BIT(0)
/* All ctrl reset bits */
#define SDMMC_CTRL_ALL_RESET_FLAGS \
@@ -281,7 +290,7 @@ struct dw_mci_drv_data {
void (*prepare_command)(struct dw_mci *host, u32 *cmdr);
void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);
- int (*execute_tuning)(struct dw_mci_slot *slot);
+ int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode);
int (*prepare_hs400_tuning)(struct dw_mci *host,
struct mmc_ios *ios);
int (*switch_voltage)(struct mmc_host *mmc,
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index ae19d83bb9de..1c1b45ef3faf 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1511,11 +1511,11 @@ static const struct of_device_id mmc_spi_of_match_table[] = {
{ .compatible = "mmc-spi-slot", },
{},
};
+MODULE_DEVICE_TABLE(of, mmc_spi_of_match_table);
static struct spi_driver mmc_spi_driver = {
.driver = {
.name = "mmc_spi",
- .owner = THIS_MODULE,
.of_match_table = mmc_spi_of_match_table,
},
.probe = mmc_spi_probe,
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
index 006f1862444b..79905ce895ad 100644
--- a/drivers/mmc/host/moxart-mmc.c
+++ b/drivers/mmc/host/moxart-mmc.c
@@ -711,6 +711,7 @@ static const struct of_device_id moxart_mmc_match[] = {
{ .compatible = "faraday,ftsdc010" },
{ }
};
+MODULE_DEVICE_TABLE(of, moxart_mmc_match);
static struct platform_driver moxart_mmc_driver = {
.probe = moxart_probe,
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 7153500dd007..33dfd7e72516 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -26,6 +26,7 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/mmc/card.h>
@@ -64,6 +65,7 @@
#define SDC_RESP2 0x48
#define SDC_RESP3 0x4c
#define SDC_BLK_NUM 0x50
+#define EMMC_IOCON 0x7c
#define SDC_ACMD_RESP 0x80
#define MSDC_DMA_SA 0x90
#define MSDC_DMA_CTRL 0x98
@@ -71,6 +73,8 @@
#define MSDC_PATCH_BIT 0xb0
#define MSDC_PATCH_BIT1 0xb4
#define MSDC_PAD_TUNE 0xec
+#define PAD_DS_TUNE 0x188
+#define EMMC50_CFG0 0x208
/*--------------------------------------------------------------------------*/
/* Register Mask */
@@ -87,6 +91,7 @@
#define MSDC_CFG_CKSTB (0x1 << 7) /* R */
#define MSDC_CFG_CKDIV (0xff << 8) /* RW */
#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */
+#define MSDC_CFG_HS400_CK_MODE (0x1 << 18) /* RW */
/* MSDC_IOCON mask */
#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */
@@ -204,6 +209,17 @@
#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */
#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
+#define MSDC_PAD_TUNE_DATRRDLY (0x1f << 8) /* RW */
+#define MSDC_PAD_TUNE_CMDRDLY (0x1f << 16) /* RW */
+
+#define PAD_DS_TUNE_DLY1 (0x1f << 2) /* RW */
+#define PAD_DS_TUNE_DLY2 (0x1f << 7) /* RW */
+#define PAD_DS_TUNE_DLY3 (0x1f << 12) /* RW */
+
+#define EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) /* RW */
+#define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */
+#define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */
+
#define REQ_CMD_EIO (0x1 << 0)
#define REQ_CMD_TMO (0x1 << 1)
#define REQ_DAT_ERR (0x1 << 2)
@@ -219,6 +235,7 @@
#define CMD_TIMEOUT (HZ/10 * 5) /* 100ms x5 */
#define DAT_TIMEOUT (HZ * 5) /* 1000ms x5 */
+#define PAD_DELAY_MAX 32 /* PAD delay cells */
/*--------------------------------------------------------------------------*/
/* Descriptor Structure */
/*--------------------------------------------------------------------------*/
@@ -265,6 +282,14 @@ struct msdc_save_para {
u32 pad_tune;
u32 patch_bit0;
u32 patch_bit1;
+ u32 pad_ds_tune;
+ u32 emmc50_cfg0;
+};
+
+struct msdc_delay_phase {
+ u8 maxlen;
+ u8 start;
+ u8 final_phase;
};
struct msdc_host {
@@ -297,8 +322,9 @@ struct msdc_host {
u32 mclk; /* mmc subsystem clock frequency */
u32 src_clk_freq; /* source clock frequency */
u32 sclk; /* SD/MS bus clock frequency */
- bool ddr;
+ unsigned char timing;
bool vqmmc_enabled;
+ u32 hs400_ds_delay;
struct msdc_save_para save_para; /* used when gate HCLK */
};
@@ -353,7 +379,10 @@ static void msdc_reset_hw(struct msdc_host *host)
static void msdc_cmd_next(struct msdc_host *host,
struct mmc_request *mrq, struct mmc_command *cmd);
-static u32 data_ints_mask = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO |
+static const u32 cmd_ints_mask = MSDC_INTEN_CMDRDY | MSDC_INTEN_RSPCRCERR |
+ MSDC_INTEN_CMDTMO | MSDC_INTEN_ACMDRDY |
+ MSDC_INTEN_ACMDCRCERR | MSDC_INTEN_ACMDTMO;
+static const u32 data_ints_mask = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO |
MSDC_INTEN_DATCRCERR | MSDC_INTEN_DMA_BDCSERR |
MSDC_INTEN_DMA_GPDCSERR | MSDC_INTEN_DMA_PROTECT;
@@ -485,7 +514,7 @@ static void msdc_ungate_clock(struct msdc_host *host)
cpu_relax();
}
-static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
+static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
{
u32 mode;
u32 flags;
@@ -501,8 +530,15 @@ static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
flags = readl(host->base + MSDC_INTEN);
sdr_clr_bits(host->base + MSDC_INTEN, flags);
- if (ddr) { /* may need to modify later */
- mode = 0x2; /* ddr mode and use divisor */
+ sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_HS400_CK_MODE);
+ if (timing == MMC_TIMING_UHS_DDR50 ||
+ timing == MMC_TIMING_MMC_DDR52 ||
+ timing == MMC_TIMING_MMC_HS400) {
+ if (timing == MMC_TIMING_MMC_HS400)
+ mode = 0x3;
+ else
+ mode = 0x2; /* ddr mode and use divisor */
+
if (hz >= (host->src_clk_freq >> 2)) {
div = 0; /* mean div = 1/4 */
sclk = host->src_clk_freq >> 2; /* sclk = clk / 4 */
@@ -511,6 +547,14 @@ static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
sclk = (host->src_clk_freq >> 2) / div;
div = (div >> 1);
}
+
+ if (timing == MMC_TIMING_MMC_HS400 &&
+ hz >= (host->src_clk_freq >> 1)) {
+ sdr_set_bits(host->base + MSDC_CFG,
+ MSDC_CFG_HS400_CK_MODE);
+ sclk = host->src_clk_freq >> 1;
+ div = 0; /* div is ignore when bit18 is set */
+ }
} else if (hz >= host->src_clk_freq) {
mode = 0x1; /* no divisor */
div = 0;
@@ -532,12 +576,12 @@ static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
cpu_relax();
host->sclk = sclk;
host->mclk = hz;
- host->ddr = ddr;
+ host->timing = timing;
/* need because clk changed. */
msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
sdr_set_bits(host->base + MSDC_INTEN, flags);
- dev_dbg(host->dev, "sclk: %d, ddr: %d\n", host->sclk, ddr);
+ dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->sclk, timing);
}
static inline u32 msdc_cmd_find_resp(struct msdc_host *host,
@@ -725,11 +769,7 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
if (done)
return true;
- sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
- MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
- MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
- MSDC_INTEN_ACMDTMO);
- writel(cmd->arg, host->base + SDC_ARG);
+ sdr_clr_bits(host->base + MSDC_INTEN, cmd_ints_mask);
if (cmd->flags & MMC_RSP_PRESENT) {
if (cmd->flags & MMC_RSP_136) {
@@ -819,10 +859,7 @@ static void msdc_start_command(struct msdc_host *host,
rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
- sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
- MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
- MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
- MSDC_INTEN_ACMDTMO);
+ sdr_set_bits(host->base + MSDC_INTEN, cmd_ints_mask);
writel(cmd->arg, host->base + SDC_ARG);
writel(rawcmd, host->base + SDC_CMD);
}
@@ -896,7 +933,7 @@ static void msdc_data_xfer_next(struct msdc_host *host,
struct mmc_request *mrq, struct mmc_data *data)
{
if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error &&
- (!data->bytes_xfered || !mrq->sbc))
+ !mrq->sbc)
msdc_start_command(host, mrq, mrq->stop);
else
msdc_request_done(host, mrq);
@@ -942,6 +979,8 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
if (events & MSDC_INT_DATTMO)
data->error = -ETIMEDOUT;
+ else if (events & MSDC_INT_DATCRCERR)
+ data->error = -EILSEQ;
dev_err(host->dev, "%s: cmd=%d; blocks=%d",
__func__, mrq->cmd->opcode, data->blocks);
@@ -1113,10 +1152,12 @@ static void msdc_init_hw(struct msdc_host *host)
writel(0, host->base + MSDC_PAD_TUNE);
writel(0, host->base + MSDC_IOCON);
- sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
- writel(0x403c004f, host->base + MSDC_PATCH_BIT);
+ sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0);
+ writel(0x403c0046, host->base + MSDC_PATCH_BIT);
sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
+ sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
+
/* Configure to enable SDIO mode.
* it's must otherwise sdio cmd5 failed
*/
@@ -1148,11 +1189,14 @@ static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma)
struct mt_bdma_desc *bd = dma->bd;
int i;
- memset(gpd, 0, sizeof(struct mt_gpdma_desc));
+ memset(gpd, 0, sizeof(struct mt_gpdma_desc) * 2);
gpd->gpd_info = GPDMA_DESC_BDP; /* hwo, cs, bd pointer */
gpd->ptr = (u32)dma->bd_addr; /* physical address */
-
+ /* gpd->next is must set for desc DMA
+ * That's why must alloc 2 gpd structure.
+ */
+ gpd->next = (u32)dma->gpd_addr + sizeof(struct mt_gpdma_desc);
memset(bd, 0, sizeof(struct mt_bdma_desc) * MAX_BD_NUM);
for (i = 0; i < (MAX_BD_NUM - 1); i++)
bd[i].next = (u32)dma->bd_addr + sizeof(*bd) * (i + 1);
@@ -1162,20 +1206,16 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct msdc_host *host = mmc_priv(mmc);
int ret;
- u32 ddr = 0;
pm_runtime_get_sync(host->dev);
- if (ios->timing == MMC_TIMING_UHS_DDR50 ||
- ios->timing == MMC_TIMING_MMC_DDR52)
- ddr = 1;
-
msdc_set_buswidth(host, ios->bus_width);
/* Suspend/Resume will do power off/on */
switch (ios->power_mode) {
case MMC_POWER_UP:
if (!IS_ERR(mmc->supply.vmmc)) {
+ msdc_init_hw(host);
ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
ios->vdd);
if (ret) {
@@ -1206,14 +1246,207 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
}
- if (host->mclk != ios->clock || host->ddr != ddr)
- msdc_set_mclk(host, ddr, ios->clock);
+ if (host->mclk != ios->clock || host->timing != ios->timing)
+ msdc_set_mclk(host, ios->timing, ios->clock);
end:
pm_runtime_mark_last_busy(host->dev);
pm_runtime_put_autosuspend(host->dev);
}
+static u32 test_delay_bit(u32 delay, u32 bit)
+{
+ bit %= PAD_DELAY_MAX;
+ return delay & (1 << bit);
+}
+
+static int get_delay_len(u32 delay, u32 start_bit)
+{
+ int i;
+
+ for (i = 0; i < (PAD_DELAY_MAX - start_bit); i++) {
+ if (test_delay_bit(delay, start_bit + i) == 0)
+ return i;
+ }
+ return PAD_DELAY_MAX - start_bit;
+}
+
+static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)
+{
+ int start = 0, len = 0;
+ int start_final = 0, len_final = 0;
+ u8 final_phase = 0xff;
+ struct msdc_delay_phase delay_phase = { 0, };
+
+ if (delay == 0) {
+ dev_err(host->dev, "phase error: [map:%x]\n", delay);
+ delay_phase.final_phase = final_phase;
+ return delay_phase;
+ }
+
+ while (start < PAD_DELAY_MAX) {
+ len = get_delay_len(delay, start);
+ if (len_final < len) {
+ start_final = start;
+ len_final = len;
+ }
+ start += len ? len : 1;
+ if (len >= 8 && start_final < 4)
+ break;
+ }
+
+ /* The rule is that to find the smallest delay cell */
+ if (start_final == 0)
+ final_phase = (start_final + len_final / 3) % PAD_DELAY_MAX;
+ else
+ final_phase = (start_final + len_final / 2) % PAD_DELAY_MAX;
+ dev_info(host->dev, "phase: [map:%x] [maxlen:%d] [final:%d]\n",
+ delay, len_final, final_phase);
+
+ delay_phase.maxlen = len_final;
+ delay_phase.start = start_final;
+ delay_phase.final_phase = final_phase;
+ return delay_phase;
+}
+
+static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+ u32 rise_delay = 0, fall_delay = 0;
+ struct msdc_delay_phase final_rise_delay, final_fall_delay;
+ u8 final_delay, final_maxlen;
+ int cmd_err;
+ int i;
+
+ sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+ for (i = 0 ; i < PAD_DELAY_MAX; i++) {
+ sdr_set_field(host->base + MSDC_PAD_TUNE,
+ MSDC_PAD_TUNE_CMDRDLY, i);
+ mmc_send_tuning(mmc, opcode, &cmd_err);
+ if (!cmd_err)
+ rise_delay |= (1 << i);
+ }
+
+ sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+ for (i = 0; i < PAD_DELAY_MAX; i++) {
+ sdr_set_field(host->base + MSDC_PAD_TUNE,
+ MSDC_PAD_TUNE_CMDRDLY, i);
+ mmc_send_tuning(mmc, opcode, &cmd_err);
+ if (!cmd_err)
+ fall_delay |= (1 << i);
+ }
+
+ final_rise_delay = get_best_delay(host, rise_delay);
+ final_fall_delay = get_best_delay(host, fall_delay);
+
+ final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
+ if (final_maxlen == final_rise_delay.maxlen) {
+ sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+ sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY,
+ final_rise_delay.final_phase);
+ final_delay = final_rise_delay.final_phase;
+ } else {
+ sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
+ sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY,
+ final_fall_delay.final_phase);
+ final_delay = final_fall_delay.final_phase;
+ }
+
+ return final_delay == 0xff ? -EIO : 0;
+}
+
+static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+ u32 rise_delay = 0, fall_delay = 0;
+ struct msdc_delay_phase final_rise_delay, final_fall_delay;
+ u8 final_delay, final_maxlen;
+ int i, ret;
+
+ sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+ sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ for (i = 0 ; i < PAD_DELAY_MAX; i++) {
+ sdr_set_field(host->base + MSDC_PAD_TUNE,
+ MSDC_PAD_TUNE_DATRRDLY, i);
+ ret = mmc_send_tuning(mmc, opcode, NULL);
+ if (!ret)
+ rise_delay |= (1 << i);
+ }
+
+ sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+ sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ for (i = 0; i < PAD_DELAY_MAX; i++) {
+ sdr_set_field(host->base + MSDC_PAD_TUNE,
+ MSDC_PAD_TUNE_DATRRDLY, i);
+ ret = mmc_send_tuning(mmc, opcode, NULL);
+ if (!ret)
+ fall_delay |= (1 << i);
+ }
+
+ final_rise_delay = get_best_delay(host, rise_delay);
+ final_fall_delay = get_best_delay(host, fall_delay);
+
+ final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
+ /* Rising edge is more stable, prefer to use it */
+ if (final_rise_delay.maxlen >= 10)
+ final_maxlen = final_rise_delay.maxlen;
+ if (final_maxlen == final_rise_delay.maxlen) {
+ sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+ sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ sdr_set_field(host->base + MSDC_PAD_TUNE,
+ MSDC_PAD_TUNE_DATRRDLY,
+ final_rise_delay.final_phase);
+ final_delay = final_rise_delay.final_phase;
+ } else {
+ sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
+ sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ sdr_set_field(host->base + MSDC_PAD_TUNE,
+ MSDC_PAD_TUNE_DATRRDLY,
+ final_fall_delay.final_phase);
+ final_delay = final_fall_delay.final_phase;
+ }
+
+ return final_delay == 0xff ? -EIO : 0;
+}
+
+static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+ int ret;
+
+ pm_runtime_get_sync(host->dev);
+ ret = msdc_tune_response(mmc, opcode);
+ if (ret == -EIO) {
+ dev_err(host->dev, "Tune response fail!\n");
+ goto out;
+ }
+ ret = msdc_tune_data(mmc, opcode);
+ if (ret == -EIO)
+ dev_err(host->dev, "Tune data fail!\n");
+
+out:
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
+ return ret;
+}
+
+static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+
+ writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE);
+ return 0;
+}
+
+static void msdc_hw_reset(struct mmc_host *mmc)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+
+ sdr_set_bits(host->base + EMMC_IOCON, 1);
+ udelay(10); /* 10us is enough */
+ sdr_clr_bits(host->base + EMMC_IOCON, 1);
+}
+
static struct mmc_host_ops mt_msdc_ops = {
.post_req = msdc_post_req,
.pre_req = msdc_pre_req,
@@ -1221,6 +1454,9 @@ static struct mmc_host_ops mt_msdc_ops = {
.set_ios = msdc_ops_set_ios,
.start_signal_voltage_switch = msdc_ops_switch_volt,
.card_busy = msdc_card_busy,
+ .execute_tuning = msdc_execute_tuning,
+ .prepare_hs400_tuning = msdc_prepare_hs400_tuning,
+ .hw_reset = msdc_hw_reset,
};
static int msdc_drv_probe(struct platform_device *pdev)
@@ -1294,6 +1530,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
goto host_free;
}
+ if (!of_property_read_u32(pdev->dev.of_node, "hs400-ds-delay",
+ &host->hs400_ds_delay))
+ dev_dbg(&pdev->dev, "hs400-ds-delay: %x\n",
+ host->hs400_ds_delay);
+
host->dev = &pdev->dev;
host->mmc = mmc;
host->src_clk_freq = clk_get_rate(host->src_clk);
@@ -1302,6 +1543,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
mmc->f_min = host->src_clk_freq / (4 * 255);
mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
+ mmc->caps |= MMC_CAP_RUNTIME_RESUME;
/* MMC core transfer sizes tunable parameters */
mmc->max_segs = MAX_BD_NUM;
mmc->max_seg_size = BDMA_DESC_BUFLEN;
@@ -1313,7 +1555,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
host->timeout_clks = 3 * 1048576;
host->dma.gpd = dma_alloc_coherent(&pdev->dev,
- sizeof(struct mt_gpdma_desc),
+ 2 * sizeof(struct mt_gpdma_desc),
&host->dma.gpd_addr, GFP_KERNEL);
host->dma.bd = dma_alloc_coherent(&pdev->dev,
MAX_BD_NUM * sizeof(struct mt_bdma_desc),
@@ -1354,7 +1596,7 @@ release:
release_mem:
if (host->dma.gpd)
dma_free_coherent(&pdev->dev,
- sizeof(struct mt_gpdma_desc),
+ 2 * sizeof(struct mt_gpdma_desc),
host->dma.gpd, host->dma.gpd_addr);
if (host->dma.bd)
dma_free_coherent(&pdev->dev,
@@ -1403,6 +1645,8 @@ static void msdc_save_reg(struct msdc_host *host)
host->save_para.pad_tune = readl(host->base + MSDC_PAD_TUNE);
host->save_para.patch_bit0 = readl(host->base + MSDC_PATCH_BIT);
host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1);
+ host->save_para.pad_ds_tune = readl(host->base + PAD_DS_TUNE);
+ host->save_para.emmc50_cfg0 = readl(host->base + EMMC50_CFG0);
}
static void msdc_restore_reg(struct msdc_host *host)
@@ -1413,6 +1657,8 @@ static void msdc_restore_reg(struct msdc_host *host)
writel(host->save_para.pad_tune, host->base + MSDC_PAD_TUNE);
writel(host->save_para.patch_bit0, host->base + MSDC_PATCH_BIT);
writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1);
+ writel(host->save_para.pad_ds_tune, host->base + PAD_DS_TUNE);
+ writel(host->save_para.emmc50_cfg0, host->base + EMMC50_CFG0);
}
static int msdc_runtime_suspend(struct device *dev)
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index b763b11ed9e1..b9958a123594 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1490,6 +1490,7 @@ static const struct of_device_id mmc_omap_match[] = {
{ .compatible = "ti,omap2420-mmc", },
{ },
};
+MODULE_DEVICE_TABLE(of, mmc_omap_match);
#endif
static struct platform_driver mmc_omap_driver = {
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 8cadd74e8407..ce08896b9d69 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -805,7 +805,7 @@ static int pxamci_probe(struct platform_device *pdev)
goto out;
} else {
mmc->caps |= host->pdata->gpio_card_ro_invert ?
- MMC_CAP2_RO_ACTIVE_HIGH : 0;
+ 0 : MMC_CAP2_RO_ACTIVE_HIGH;
}
if (gpio_is_valid(gpio_cd))
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 22d929fa3371..f6047fc94062 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -207,7 +207,9 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
.caps2 = MMC_CAP2_HC_ERASE_SZ,
.flags = SDHCI_ACPI_RUNTIME_PM,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | SDHCI_QUIRK2_STOP_WITH_TC,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+ SDHCI_QUIRK2_STOP_WITH_TC |
+ SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400,
.probe_slot = sdhci_acpi_emmc_probe_slot,
};
@@ -239,6 +241,9 @@ struct sdhci_acpi_uid_slot {
};
static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {
+ { "80865ACA", NULL, &sdhci_acpi_slot_int_sd },
+ { "80865ACC", NULL, &sdhci_acpi_slot_int_emmc },
+ { "80865AD0", NULL, &sdhci_acpi_slot_int_sdio },
{ "80860F14" , "1" , &sdhci_acpi_slot_int_emmc },
{ "80860F14" , "3" , &sdhci_acpi_slot_int_sd },
{ "80860F16" , NULL, &sdhci_acpi_slot_int_sd },
@@ -247,11 +252,15 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {
{ "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio },
{ "INT3436" , NULL, &sdhci_acpi_slot_int_sdio },
{ "INT344D" , NULL, &sdhci_acpi_slot_int_sdio },
+ { "PNP0FFF" , "3" , &sdhci_acpi_slot_int_sd },
{ "PNP0D40" },
{ },
};
static const struct acpi_device_id sdhci_acpi_ids[] = {
+ { "80865ACA" },
+ { "80865ACC" },
+ { "80865AD0" },
{ "80860F14" },
{ "80860F16" },
{ "INT33BB" },
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index 2bd90fb35c75..00a8a40a3729 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -273,7 +273,7 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev)
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
dev_dbg(dev, "is_8bit=%c\n",
- (host->mmc->caps | MMC_CAP_8_BIT_DATA) ? 'Y' : 'N');
+ (host->mmc->caps & MMC_CAP_8_BIT_DATA) ? 'Y' : 'N');
ret = sdhci_bcm_kona_sd_reset(host);
if (ret)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 886d230f41d0..1f1582f6cccb 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -759,7 +759,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
min = ESDHC_TUNE_CTRL_MIN;
while (min < ESDHC_TUNE_CTRL_MAX) {
esdhc_prepare_tuning(host, min);
- if (!mmc_send_tuning(host->mmc))
+ if (!mmc_send_tuning(host->mmc, opcode, NULL))
break;
min += ESDHC_TUNE_CTRL_STEP;
}
@@ -768,7 +768,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
max = min + ESDHC_TUNE_CTRL_STEP;
while (max < ESDHC_TUNE_CTRL_MAX) {
esdhc_prepare_tuning(host, max);
- if (mmc_send_tuning(host->mmc)) {
+ if (mmc_send_tuning(host->mmc, opcode, NULL)) {
max -= ESDHC_TUNE_CTRL_STEP;
break;
}
@@ -778,7 +778,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
/* use average delay to get the best timing */
avg = (min + max) / 2;
esdhc_prepare_tuning(host, avg);
- ret = mmc_send_tuning(host->mmc);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
esdhc_post_tuning(host);
dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 163ac9974d91..de132e281753 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -24,6 +24,8 @@
SDHCI_QUIRK_PIO_NEEDS_DELAY | \
SDHCI_QUIRK_NO_HISPD_BIT)
+#define ESDHC_PROCTL 0x28
+
#define ESDHC_SYSTEM_CONTROL 0x2c
#define ESDHC_CLOCK_MASK 0x0000fff0
#define ESDHC_PREDIV_SHIFT 8
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4bcee033feda..4695bee203ea 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -373,7 +373,7 @@ retry:
if (rc)
return rc;
- rc = mmc_send_tuning(mmc);
+ rc = mmc_send_tuning(mmc, opcode, NULL);
if (!rc) {
/* Tuning is successful at this tuning point */
tuned_phases[tuned_phase_cnt++] = phase;
diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c
index a0f05de5409f..06d0b50dfe71 100644
--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -111,7 +111,6 @@ static int sdhci_at91_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev, "failed to set gck");
goto hclock_disable_unprepare;
- return -EINVAL;
}
/*
* We need to check if we have the requested rate for gck because in
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 653f335bef15..90e94a028a49 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -24,122 +24,324 @@
#define VENDOR_V_22 0x12
#define VENDOR_V_23 0x13
-static u32 esdhc_readl(struct sdhci_host *host, int reg)
+
+struct sdhci_esdhc {
+ u8 vendor_ver;
+ u8 spec_ver;
+};
+
+/**
+ * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register
+ * to make it compatible with SD spec.
+ *
+ * @host: pointer to sdhci_host
+ * @spec_reg: SD spec register address
+ * @value: 32bit eSDHC register value on spec_reg address
+ *
+ * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC
+ * registers are 32 bits. There are differences in register size, register
+ * address, register function, bit position and function between eSDHC spec
+ * and SD spec.
+ *
+ * Return a fixed up register value
+ */
+static u32 esdhc_readl_fixup(struct sdhci_host *host,
+ int spec_reg, u32 value)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = pltfm_host->priv;
u32 ret;
- ret = in_be32(host->ioaddr + reg);
/*
* The bit of ADMA flag in eSDHC is not compatible with standard
* SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
* supported by eSDHC.
* And for many FSL eSDHC controller, the reset value of field
- * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA,
+ * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA,
* only these vendor version is greater than 2.2/0x12 support ADMA.
- * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
- * the verdor version number, oxFE is SDHCI_HOST_VERSION.
*/
- if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
- u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
- tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
- if (tmp > VENDOR_V_22)
- ret |= SDHCI_CAN_DO_ADMA2;
+ if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) {
+ if (esdhc->vendor_ver > VENDOR_V_22) {
+ ret = value | SDHCI_CAN_DO_ADMA2;
+ return ret;
+ }
}
-
+ ret = value;
return ret;
}
-static u16 esdhc_readw(struct sdhci_host *host, int reg)
+static u16 esdhc_readw_fixup(struct sdhci_host *host,
+ int spec_reg, u32 value)
{
u16 ret;
- int base = reg & ~0x3;
- int shift = (reg & 0x2) * 8;
+ int shift = (spec_reg & 0x2) * 8;
- if (unlikely(reg == SDHCI_HOST_VERSION))
- ret = in_be32(host->ioaddr + base) & 0xffff;
+ if (spec_reg == SDHCI_HOST_VERSION)
+ ret = value & 0xffff;
else
- ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
+ ret = (value >> shift) & 0xffff;
return ret;
}
-static u8 esdhc_readb(struct sdhci_host *host, int reg)
+static u8 esdhc_readb_fixup(struct sdhci_host *host,
+ int spec_reg, u32 value)
{
- int base = reg & ~0x3;
- int shift = (reg & 0x3) * 8;
- u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
+ u8 ret;
+ u8 dma_bits;
+ int shift = (spec_reg & 0x3) * 8;
+
+ ret = (value >> shift) & 0xff;
/*
* "DMA select" locates at offset 0x28 in SD specification, but on
* P5020 or P3041, it locates at 0x29.
*/
- if (reg == SDHCI_HOST_CONTROL) {
- u32 dma_bits;
-
- dma_bits = in_be32(host->ioaddr + reg);
+ if (spec_reg == SDHCI_HOST_CONTROL) {
/* DMA select is 22,23 bits in Protocol Control Register */
- dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK;
-
+ dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK;
/* fixup the result */
ret &= ~SDHCI_CTRL_DMA_MASK;
ret |= dma_bits;
}
-
return ret;
}
-static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+/**
+ * esdhc_write*_fixup - Fixup the SD spec register value so that it could be
+ * written into eSDHC register.
+ *
+ * @host: pointer to sdhci_host
+ * @spec_reg: SD spec register address
+ * @value: 8/16/32bit SD spec register value that would be written
+ * @old_value: 32bit eSDHC register value on spec_reg address
+ *
+ * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC
+ * registers are 32 bits. There are differences in register size, register
+ * address, register function, bit position and function between eSDHC spec
+ * and SD spec.
+ *
+ * Return a fixed up register value
+ */
+static u32 esdhc_writel_fixup(struct sdhci_host *host,
+ int spec_reg, u32 value, u32 old_value)
{
+ u32 ret;
+
/*
- * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
- * when SYSCTL[RSTD]) is set for some special operations.
- * No any impact other operation.
+ * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+ * when SYSCTL[RSTD] is set for some special operations.
+ * No any impact on other operation.
*/
- if (reg == SDHCI_INT_ENABLE)
- val |= SDHCI_INT_BLK_GAP;
- sdhci_be32bs_writel(host, val, reg);
+ if (spec_reg == SDHCI_INT_ENABLE)
+ ret = value | SDHCI_INT_BLK_GAP;
+ else
+ ret = value;
+
+ return ret;
}
-static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
+static u32 esdhc_writew_fixup(struct sdhci_host *host,
+ int spec_reg, u16 value, u32 old_value)
{
- if (reg == SDHCI_BLOCK_SIZE) {
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ int shift = (spec_reg & 0x2) * 8;
+ u32 ret;
+
+ switch (spec_reg) {
+ case SDHCI_TRANSFER_MODE:
+ /*
+ * Postpone this write, we must do it together with a
+ * command write that is down below. Return old value.
+ */
+ pltfm_host->xfer_mode_shadow = value;
+ return old_value;
+ case SDHCI_COMMAND:
+ ret = (value << 16) | pltfm_host->xfer_mode_shadow;
+ return ret;
+ }
+
+ ret = old_value & (~(0xffff << shift));
+ ret |= (value << shift);
+
+ if (spec_reg == SDHCI_BLOCK_SIZE) {
/*
* Two last DMA bits are reserved, and first one is used for
* non-standard blksz of 4096 bytes that we don't support
* yet. So clear the DMA boundary bits.
*/
- val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
+ ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0));
}
- sdhci_be32bs_writew(host, val, reg);
+ return ret;
}
-static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
+static u32 esdhc_writeb_fixup(struct sdhci_host *host,
+ int spec_reg, u8 value, u32 old_value)
{
+ u32 ret;
+ u32 dma_bits;
+ u8 tmp;
+ int shift = (spec_reg & 0x3) * 8;
+
+ /*
+ * eSDHC doesn't have a standard power control register, so we do
+ * nothing here to avoid incorrect operation.
+ */
+ if (spec_reg == SDHCI_POWER_CONTROL)
+ return old_value;
/*
* "DMA select" location is offset 0x28 in SD specification, but on
* P5020 or P3041, it's located at 0x29.
*/
- if (reg == SDHCI_HOST_CONTROL) {
- u32 dma_bits;
-
+ if (spec_reg == SDHCI_HOST_CONTROL) {
/*
* If host control register is not standard, exit
* this function
*/
if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL)
- return;
+ return old_value;
/* DMA select is 22,23 bits in Protocol Control Register */
- dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5;
- clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5,
- dma_bits);
- val &= ~SDHCI_CTRL_DMA_MASK;
- val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK;
+ dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5;
+ ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits;
+ tmp = (value & (~SDHCI_CTRL_DMA_MASK)) |
+ (old_value & SDHCI_CTRL_DMA_MASK);
+ ret = (ret & (~0xff)) | tmp;
+
+ /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */
+ ret &= ~ESDHC_HOST_CONTROL_RES;
+ return ret;
}
- /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
- if (reg == SDHCI_HOST_CONTROL)
- val &= ~ESDHC_HOST_CONTROL_RES;
- sdhci_be32bs_writeb(host, val, reg);
+ ret = (old_value & (~(0xff << shift))) | (value << shift);
+ return ret;
+}
+
+static u32 esdhc_be_readl(struct sdhci_host *host, int reg)
+{
+ u32 ret;
+ u32 value;
+
+ value = ioread32be(host->ioaddr + reg);
+ ret = esdhc_readl_fixup(host, reg, value);
+
+ return ret;
+}
+
+static u32 esdhc_le_readl(struct sdhci_host *host, int reg)
+{
+ u32 ret;
+ u32 value;
+
+ value = ioread32(host->ioaddr + reg);
+ ret = esdhc_readl_fixup(host, reg, value);
+
+ return ret;
+}
+
+static u16 esdhc_be_readw(struct sdhci_host *host, int reg)
+{
+ u16 ret;
+ u32 value;
+ int base = reg & ~0x3;
+
+ value = ioread32be(host->ioaddr + base);
+ ret = esdhc_readw_fixup(host, reg, value);
+ return ret;
+}
+
+static u16 esdhc_le_readw(struct sdhci_host *host, int reg)
+{
+ u16 ret;
+ u32 value;
+ int base = reg & ~0x3;
+
+ value = ioread32(host->ioaddr + base);
+ ret = esdhc_readw_fixup(host, reg, value);
+ return ret;
+}
+
+static u8 esdhc_be_readb(struct sdhci_host *host, int reg)
+{
+ u8 ret;
+ u32 value;
+ int base = reg & ~0x3;
+
+ value = ioread32be(host->ioaddr + base);
+ ret = esdhc_readb_fixup(host, reg, value);
+ return ret;
+}
+
+static u8 esdhc_le_readb(struct sdhci_host *host, int reg)
+{
+ u8 ret;
+ u32 value;
+ int base = reg & ~0x3;
+
+ value = ioread32(host->ioaddr + base);
+ ret = esdhc_readb_fixup(host, reg, value);
+ return ret;
+}
+
+static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ u32 value;
+
+ value = esdhc_writel_fixup(host, reg, val, 0);
+ iowrite32be(value, host->ioaddr + reg);
+}
+
+static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ u32 value;
+
+ value = esdhc_writel_fixup(host, reg, val, 0);
+ iowrite32(value, host->ioaddr + reg);
+}
+
+static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg)
+{
+ int base = reg & ~0x3;
+ u32 value;
+ u32 ret;
+
+ value = ioread32be(host->ioaddr + base);
+ ret = esdhc_writew_fixup(host, reg, val, value);
+ if (reg != SDHCI_TRANSFER_MODE)
+ iowrite32be(ret, host->ioaddr + base);
+}
+
+static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg)
+{
+ int base = reg & ~0x3;
+ u32 value;
+ u32 ret;
+
+ value = ioread32(host->ioaddr + base);
+ ret = esdhc_writew_fixup(host, reg, val, value);
+ if (reg != SDHCI_TRANSFER_MODE)
+ iowrite32(ret, host->ioaddr + base);
+}
+
+static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+ int base = reg & ~0x3;
+ u32 value;
+ u32 ret;
+
+ value = ioread32be(host->ioaddr + base);
+ ret = esdhc_writeb_fixup(host, reg, val, value);
+ iowrite32be(ret, host->ioaddr + base);
+}
+
+static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+ int base = reg & ~0x3;
+ u32 value;
+ u32 ret;
+
+ value = ioread32(host->ioaddr + base);
+ ret = esdhc_writeb_fixup(host, reg, val, value);
+ iowrite32(ret, host->ioaddr + base);
}
/*
@@ -149,19 +351,17 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
* For Continue, apply soft reset for data(SYSCTL[RSTD]);
* and re-issue the entire read transaction from beginning.
*/
-static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
+static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask)
{
- u32 tmp;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = pltfm_host->priv;
bool applicable;
dma_addr_t dmastart;
dma_addr_t dmanow;
- tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
- tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
-
applicable = (intmask & SDHCI_INT_DATA_END) &&
- (intmask & SDHCI_INT_BLK_GAP) &&
- (tmp == VENDOR_V_23);
+ (intmask & SDHCI_INT_BLK_GAP) &&
+ (esdhc->vendor_ver == VENDOR_V_23);
if (!applicable)
return;
@@ -179,7 +379,11 @@ static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
static int esdhc_of_enable_dma(struct sdhci_host *host)
{
- setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
+ u32 value;
+
+ value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
+ value |= ESDHC_DMA_SNOOP;
+ sdhci_writel(host, value, ESDHC_DMA_SYSCTL);
return 0;
}
@@ -199,6 +403,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = pltfm_host->priv;
int pre_div = 1;
int div = 1;
u32 temp;
@@ -209,9 +415,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
return;
/* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */
- temp = esdhc_readw(host, SDHCI_HOST_VERSION);
- temp = (temp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
- if (temp < VENDOR_V_23)
+ if (esdhc->vendor_ver < VENDOR_V_23)
pre_div = 2;
/* Workaround to reduce the clock frequency for p1010 esdhc */
@@ -247,39 +451,26 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
mdelay(1);
}
-static void esdhc_of_platform_init(struct sdhci_host *host)
-{
- u32 vvn;
-
- vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
- vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
- if (vvn == VENDOR_V_22)
- host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
-
- if (vvn > VENDOR_V_22)
- host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
-}
-
static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
{
u32 ctrl;
+ ctrl = sdhci_readl(host, ESDHC_PROCTL);
+ ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK);
switch (width) {
case MMC_BUS_WIDTH_8:
- ctrl = ESDHC_CTRL_8BITBUS;
+ ctrl |= ESDHC_CTRL_8BITBUS;
break;
case MMC_BUS_WIDTH_4:
- ctrl = ESDHC_CTRL_4BITBUS;
+ ctrl |= ESDHC_CTRL_4BITBUS;
break;
default:
- ctrl = 0;
break;
}
- clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
- ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
+ sdhci_writel(host, ctrl, ESDHC_PROCTL);
}
static void esdhc_reset(struct sdhci_host *host, u8 mask)
@@ -290,32 +481,13 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
}
-static const struct sdhci_ops sdhci_esdhc_ops = {
- .read_l = esdhc_readl,
- .read_w = esdhc_readw,
- .read_b = esdhc_readb,
- .write_l = esdhc_writel,
- .write_w = esdhc_writew,
- .write_b = esdhc_writeb,
- .set_clock = esdhc_of_set_clock,
- .enable_dma = esdhc_of_enable_dma,
- .get_max_clock = esdhc_of_get_max_clock,
- .get_min_clock = esdhc_of_get_min_clock,
- .platform_init = esdhc_of_platform_init,
- .adma_workaround = esdhci_of_adma_workaround,
- .set_bus_width = esdhc_pltfm_set_bus_width,
- .reset = esdhc_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
-};
-
#ifdef CONFIG_PM
-
static u32 esdhc_proctl;
static int esdhc_of_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
- esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+ esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL);
return sdhci_suspend_host(host);
}
@@ -328,9 +500,8 @@ static int esdhc_of_resume(struct device *dev)
if (ret == 0) {
/* Isn't this already done by sdhci_resume_host() ? --rmk */
esdhc_of_enable_dma(host);
- sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+ sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
}
-
return ret;
}
@@ -343,37 +514,103 @@ static const struct dev_pm_ops esdhc_pmops = {
#define ESDHC_PMOPS NULL
#endif
-static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
- /*
- * card detection could be handled via GPIO
- * eSDHC cannot support End Attribute in NOP ADMA descriptor
- */
+static const struct sdhci_ops sdhci_esdhc_be_ops = {
+ .read_l = esdhc_be_readl,
+ .read_w = esdhc_be_readw,
+ .read_b = esdhc_be_readb,
+ .write_l = esdhc_be_writel,
+ .write_w = esdhc_be_writew,
+ .write_b = esdhc_be_writeb,
+ .set_clock = esdhc_of_set_clock,
+ .enable_dma = esdhc_of_enable_dma,
+ .get_max_clock = esdhc_of_get_max_clock,
+ .get_min_clock = esdhc_of_get_min_clock,
+ .adma_workaround = esdhc_of_adma_workaround,
+ .set_bus_width = esdhc_pltfm_set_bus_width,
+ .reset = esdhc_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_ops sdhci_esdhc_le_ops = {
+ .read_l = esdhc_le_readl,
+ .read_w = esdhc_le_readw,
+ .read_b = esdhc_le_readb,
+ .write_l = esdhc_le_writel,
+ .write_w = esdhc_le_writew,
+ .write_b = esdhc_le_writeb,
+ .set_clock = esdhc_of_set_clock,
+ .enable_dma = esdhc_of_enable_dma,
+ .get_max_clock = esdhc_of_get_max_clock,
+ .get_min_clock = esdhc_of_get_min_clock,
+ .adma_workaround = esdhc_of_adma_workaround,
+ .set_bus_width = esdhc_pltfm_set_bus_width,
+ .reset = esdhc_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
| SDHCI_QUIRK_NO_CARD_NO_RESET
| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
- .ops = &sdhci_esdhc_ops,
+ .ops = &sdhci_esdhc_be_ops,
};
+static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+ | SDHCI_QUIRK_NO_CARD_NO_RESET
+ | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .ops = &sdhci_esdhc_le_ops,
+};
+
+static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_esdhc *esdhc;
+ u16 host_ver;
+
+ pltfm_host = sdhci_priv(host);
+ esdhc = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_esdhc),
+ GFP_KERNEL);
+
+ host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
+ esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
+ SDHCI_VENDOR_VER_SHIFT;
+ esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
+
+ pltfm_host->priv = esdhc;
+}
+
static int sdhci_esdhc_probe(struct platform_device *pdev)
{
struct sdhci_host *host;
struct device_node *np;
int ret;
- host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
+ np = pdev->dev.of_node;
+
+ if (of_get_property(np, "little-endian", NULL))
+ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 0);
+ else
+ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 0);
+
if (IS_ERR(host))
return PTR_ERR(host);
+ esdhc_init(pdev, host);
+
sdhci_get_of_property(pdev);
- np = pdev->dev.of_node;
if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
of_device_is_compatible(np, "fsl,p5020-esdhc") ||
of_device_is_compatible(np, "fsl,p4080-esdhc") ||
of_device_is_compatible(np, "fsl,p1020-esdhc") ||
- of_device_is_compatible(np, "fsl,t1040-esdhc"))
+ of_device_is_compatible(np, "fsl,t1040-esdhc") ||
+ of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ if (of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
if (of_device_is_compatible(np, "fsl,p2020-esdhc")) {
/*
* Freescale messed up with P2020 as it has a non-standard
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci-core.c
index b3b0a3e4fca1..cf7ad458b4f4 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -444,11 +444,7 @@ static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
else
scratch &= ~0x47;
- ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
- if (ret)
- return ret;
-
- return 0;
+ return pci_write_config_byte(chip->pdev, 0xAE, scratch);
}
static int jmicron_probe(struct sdhci_pci_chip *chip)
@@ -1113,6 +1109,62 @@ static const struct pci_device_id pci_ids[] = {
},
{
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_DNV_EMMC,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BXT_EMMC,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BXT_SDIO,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sdio,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BXT_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_APL_EMMC,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_APL_SDIO,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sdio,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_APL_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd,
+ },
+
+ {
.vendor = PCI_VENDOR_ID_O2,
.device = PCI_DEVICE_ID_O2_8120,
.subvendor = PCI_ANY_ID,
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index e2ec108dba0e..d48f03104b5b 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -60,7 +60,7 @@ static void o2_pci_led_enable(struct sdhci_pci_chip *chip)
}
-void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
+static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
{
u32 scratch_32;
int ret;
@@ -145,7 +145,6 @@ void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
scratch_32 |= 0x00080000;
pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32);
}
-EXPORT_SYMBOL_GPL(sdhci_pci_o2_fujin2_pci_init);
int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
{
@@ -179,7 +178,6 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
return 0;
}
-EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe_slot);
int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
{
@@ -385,11 +383,9 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
return 0;
}
-EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe);
int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
{
sdhci_pci_o2_probe(chip);
return 0;
}
-EXPORT_SYMBOL_GPL(sdhci_pci_o2_resume);
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.h b/drivers/mmc/host/sdhci-pci-o2micro.h
index f7ffc908d9a0..770f53857211 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.h
+++ b/drivers/mmc/host/sdhci-pci-o2micro.h
@@ -64,8 +64,6 @@
#define O2_SD_VENDOR_SETTING 0x110
#define O2_SD_VENDOR_SETTING2 0x1C8
-extern void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip);
-
extern int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot);
extern int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip);
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 541f1cad5247..d1a0b4db60db 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -24,6 +24,13 @@
#define PCI_DEVICE_ID_INTEL_SPT_EMMC 0x9d2b
#define PCI_DEVICE_ID_INTEL_SPT_SDIO 0x9d2c
#define PCI_DEVICE_ID_INTEL_SPT_SD 0x9d2d
+#define PCI_DEVICE_ID_INTEL_DNV_EMMC 0x19db
+#define PCI_DEVICE_ID_INTEL_BXT_SD 0x0aca
+#define PCI_DEVICE_ID_INTEL_BXT_EMMC 0x0acc
+#define PCI_DEVICE_ID_INTEL_BXT_SDIO 0x0ad0
+#define PCI_DEVICE_ID_INTEL_APL_SD 0x5aca
+#define PCI_DEVICE_ID_INTEL_APL_EMMC 0x5acc
+#define PCI_DEVICE_ID_INTEL_APL_SDIO 0x5ad0
/*
* PCI registers
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index a207f5aaf62f..87fb5ea8ebe7 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -71,9 +71,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- const __be32 *clk;
u32 bus_width;
- int size;
if (of_get_property(np, "sdhci,auto-cmd12", NULL))
host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
@@ -101,9 +99,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- clk = of_get_property(np, "clock-frequency", &size);
- if (clk && size == sizeof(*clk) && *clk)
- pltfm_host->clock = be32_to_cpup(clk);
+ of_property_read_u32(np, "clock-frequency", &pltfm_host->clock);
if (of_find_property(np, "keep-power-in-suspend", NULL))
host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c
index 884294576356..34866f668dd7 100644
--- a/drivers/mmc/host/sdhci-sirf.c
+++ b/drivers/mmc/host/sdhci-sirf.c
@@ -50,7 +50,8 @@ static u32 sdhci_sirf_readl_le(struct sdhci_host *host, int reg)
if (unlikely((reg == SDHCI_CAPABILITIES_1) &&
(host->mmc->caps & MMC_CAP_UHS_SDR50))) {
/* fake CAP_1 register */
- val = SDHCI_SUPPORT_SDR50 | SDHCI_USE_SDR50_TUNING;
+ val = SDHCI_SUPPORT_DDR50 |
+ SDHCI_SUPPORT_SDR50 | SDHCI_USE_SDR50_TUNING;
}
if (unlikely(reg == SDHCI_SLOT_INT_STATUS)) {
@@ -97,7 +98,7 @@ retry:
clock_setting | phase,
SDHCI_CLK_DELAY_SETTING);
- if (!mmc_send_tuning(mmc)) {
+ if (!mmc_send_tuning(mmc, opcode, NULL)) {
/* Tuning is successful at this tuning point */
tuned_phase_cnt++;
dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n",
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index fbc7efdddcb5..b48565ed5616 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1895,9 +1895,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
tuning_count = host->tuning_count;
/*
- * The Host Controller needs tuning only in case of SDR104 mode
- * and for SDR50 mode when Use Tuning for SDR50 is set in the
- * Capabilities register.
+ * The Host Controller needs tuning in case of SDR104 and DDR50
+ * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
+ * the Capabilities register.
* If the Host Controller supports the HS200 mode then the
* tuning function has to be executed.
*/
@@ -1917,6 +1917,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
break;
case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_UHS_DDR50:
break;
case MMC_TIMING_UHS_SDR50:
@@ -2716,17 +2717,6 @@ int sdhci_resume_host(struct sdhci_host *host)
host->ops->enable_dma(host);
}
- if (!device_may_wakeup(mmc_dev(host->mmc))) {
- ret = request_threaded_irq(host->irq, sdhci_irq,
- sdhci_thread_irq, IRQF_SHARED,
- mmc_hostname(host->mmc), host);
- if (ret)
- return ret;
- } else {
- sdhci_disable_irq_wakeups(host);
- disable_irq_wake(host->irq);
- }
-
if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) &&
(host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
/* Card keeps power but host controller does not */
@@ -2739,6 +2729,17 @@ int sdhci_resume_host(struct sdhci_host *host)
mmiowb();
}
+ if (!device_may_wakeup(mmc_dev(host->mmc))) {
+ ret = request_threaded_irq(host->irq, sdhci_irq,
+ sdhci_thread_irq, IRQF_SHARED,
+ mmc_hostname(host->mmc), host);
+ if (ret)
+ return ret;
+ } else {
+ sdhci_disable_irq_wakeups(host);
+ disable_irq_wake(host->irq);
+ }
+
sdhci_enable_card_detection(host);
return ret;
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index b981b8552e43..83de82bceafc 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -873,6 +873,13 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
spin_unlock_irqrestore(&host->lock, iflags);
}
+static int sunxi_mmc_card_busy(struct mmc_host *mmc)
+{
+ struct sunxi_mmc_host *host = mmc_priv(mmc);
+
+ return !!(mmc_readl(host, REG_STAS) & SDXC_CARD_DATA_BUSY);
+}
+
static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-mmc", },
{ .compatible = "allwinner,sun5i-a13-mmc", },
@@ -888,6 +895,7 @@ static struct mmc_host_ops sunxi_mmc_ops = {
.get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
.hw_reset = sunxi_mmc_hw_reset,
+ .card_busy = sunxi_mmc_card_busy,
};
static const struct sunxi_mmc_clk_delay sunxi_mmc_clk_delays[] = {
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index fbabbb82b354..1e819f98b94f 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -563,7 +563,7 @@ static void add_offloaded_reg(struct vub300_mmc_host *vub300,
i += 1;
continue;
}
- };
+ }
__add_offloaded_reg_to_fifo(vub300, register_access, func);
}
@@ -1372,7 +1372,7 @@ static void download_offload_pseudocode(struct vub300_mmc_host *vub300)
l += snprintf(vub300->vub_name + l,
sizeof(vub300->vub_name) - l, "_%04X%04X",
sf->vendor, sf->device);
- };
+ }
snprintf(vub300->vub_name + l, sizeof(vub300->vub_name) - l, ".bin");
dev_info(&vub300->udev->dev, "requesting offload firmware %s\n",
vub300->vub_name);
@@ -1893,7 +1893,7 @@ static int satisfy_request_from_offloaded_data(struct vub300_mmc_host *vub300,
i += 1;
continue;
}
- };
+ }
if (vub300->total_offload_count == 0)
return 0;
else if (vub300->fn[func].offload_count == 0)
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index ca183ea767b3..c3fd16d997ca 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -809,7 +809,7 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
cmd->error = -EINVAL;
goto done;
- };
+ }
}
/*
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index c8503006f17a..08f62987cc37 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -48,6 +48,8 @@
* edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
*/
+#define pr_fmt(fmt) "mtd: " fmt
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
@@ -55,9 +57,6 @@
#include <linux/module.h>
#include <linux/err.h>
-/* error message prefix */
-#define ERRP "mtd: "
-
/* debug macro */
#if 0
#define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
@@ -115,9 +114,8 @@ static struct mtd_partition * newpart(char *s,
s++;
} else {
size = memparse(s, &s);
- if (size < PAGE_SIZE) {
- printk(KERN_ERR ERRP "partition size too small (%llx)\n",
- size);
+ if (!size) {
+ pr_err("partition has size 0\n");
return ERR_PTR(-EINVAL);
}
}
@@ -142,7 +140,7 @@ static struct mtd_partition * newpart(char *s,
name = ++s;
p = strchr(name, delim);
if (!p) {
- printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
+ pr_err("no closing %c found in partition name\n", delim);
return ERR_PTR(-EINVAL);
}
name_len = p - name;
@@ -170,7 +168,7 @@ static struct mtd_partition * newpart(char *s,
/* test if more partitions are following */
if (*s == ',') {
if (size == SIZE_REMAINING) {
- printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
+ pr_err("no partitions allowed after a fill-up partition\n");
return ERR_PTR(-EINVAL);
}
/* more partitions follow, parse them */
@@ -237,7 +235,7 @@ static int mtdpart_setup_real(char *s)
/* fetch <mtd-id> */
p = strchr(s, ':');
if (!p) {
- printk(KERN_ERR ERRP "no mtd-id\n");
+ pr_err("no mtd-id\n");
return -EINVAL;
}
mtd_id_len = p - mtd_id;
@@ -289,7 +287,7 @@ static int mtdpart_setup_real(char *s)
/* does another spec follow? */
if (*s != ';') {
- printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s);
+ pr_err("bad character after partition (%c)\n", *s);
return -EINVAL;
}
s++;
@@ -343,17 +341,15 @@ static int parse_cmdline_partitions(struct mtd_info *master,
part->parts[i].size = master->size - offset;
if (offset + part->parts[i].size > master->size) {
- printk(KERN_WARNING ERRP
- "%s: partitioning exceeds flash size, truncating\n",
- part->mtd_id);
+ pr_warn("%s: partitioning exceeds flash size, truncating\n",
+ part->mtd_id);
part->parts[i].size = master->size - offset;
}
offset += part->parts[i].size;
if (part->parts[i].size == 0) {
- printk(KERN_WARNING ERRP
- "%s: skipping zero sized partition\n",
- part->mtd_id);
+ pr_warn("%s: skipping zero sized partition\n",
+ part->mtd_id);
part->num_parts--;
memmove(&part->parts[i], &part->parts[i + 1],
sizeof(*part->parts) * (part->num_parts - i));
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
index 3d008a9410be..347bb83db864 100644
--- a/drivers/mtd/devices/bcm47xxsflash.c
+++ b/drivers/mtd/devices/bcm47xxsflash.c
@@ -237,13 +237,14 @@ static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len,
return 0;
}
-static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s)
+static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s,
+ struct device *dev)
{
struct mtd_info *mtd = &b47s->mtd;
mtd->priv = b47s;
+ mtd->dev.parent = dev;
mtd->name = "bcm47xxsflash";
- mtd->owner = THIS_MODULE;
mtd->type = MTD_NORFLASH;
mtd->flags = MTD_CAP_NORFLASH;
@@ -300,7 +301,7 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
b47s->blocksize = sflash->blocksize;
b47s->numblocks = sflash->numblocks;
b47s->size = sflash->size;
- bcm47xxsflash_fill_mtd(b47s);
+ bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
if (err) {
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 5e67b4acde78..c3a2695a4420 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1620,20 +1620,30 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
static int doc_register_sysfs(struct platform_device *pdev,
struct docg3_cascade *cascade)
{
- int ret = 0, floor, i = 0;
struct device *dev = &pdev->dev;
+ int floor;
+ int ret;
+ int i;
- for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS &&
- cascade->floors[floor]; floor++)
- for (i = 0; !ret && i < 4; i++)
+ for (floor = 0;
+ floor < DOC_MAX_NBFLOORS && cascade->floors[floor];
+ floor++) {
+ for (i = 0; i < 4; i++) {
ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
- if (!ret)
- return 0;
+ if (ret)
+ goto remove_files;
+ }
+ }
+
+ return 0;
+
+remove_files:
do {
while (--i >= 0)
device_remove_file(dev, &doc_sys_attrs[floor][i]);
i = 4;
} while (--floor >= 0);
+
return ret;
}
@@ -1843,7 +1853,6 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
mtd->erasesize /= 2;
mtd->writebufsize = mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
- mtd->owner = THIS_MODULE;
mtd->_erase = doc_erase;
mtd->_read = doc_read;
mtd->_write = doc_write;
@@ -1885,6 +1894,7 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev)
if (!mtd)
goto nomem2;
mtd->priv = docg3;
+ mtd->dev.parent = dev;
bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
8 * DOC_LAYOUT_PAGE_SIZE);
docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 9cd3631170ef..fe9ceb7b5405 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -31,7 +31,6 @@
struct m25p {
struct spi_device *spi;
struct spi_nor spi_nor;
- struct mtd_info mtd;
u8 command[MAX_CMD_SIZE];
};
@@ -62,8 +61,7 @@ static int m25p_cmdsz(struct spi_nor *nor)
return 1 + nor->addr_width;
}
-static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
- int wr_en)
+static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
{
struct m25p *flash = nor->priv;
struct spi_device *spi = flash->spi;
@@ -159,7 +157,7 @@ static int m25p80_erase(struct spi_nor *nor, loff_t offset)
struct m25p *flash = nor->priv;
dev_dbg(nor->dev, "%dKiB at 0x%08x\n",
- flash->mtd.erasesize / 1024, (u32)offset);
+ flash->spi_nor.mtd.erasesize / 1024, (u32)offset);
/* Set up command buffer. */
flash->command[0] = nor->erase_opcode;
@@ -201,11 +199,10 @@ static int m25p_probe(struct spi_device *spi)
nor->read_reg = m25p80_read_reg;
nor->dev = &spi->dev;
- nor->mtd = &flash->mtd;
+ nor->flash_node = spi->dev.of_node;
nor->priv = flash;
spi_set_drvdata(spi, flash);
- flash->mtd.priv = nor;
flash->spi = spi;
if (spi->mode & SPI_RX_QUAD)
@@ -214,7 +211,7 @@ static int m25p_probe(struct spi_device *spi)
mode = SPI_NOR_DUAL;
if (data && data->name)
- flash->mtd.name = data->name;
+ nor->mtd.name = data->name;
/* For some (historical?) reason many platforms provide two different
* names in flash_platform_data: "name" and "type". Quite often name is
@@ -232,7 +229,7 @@ static int m25p_probe(struct spi_device *spi)
ppdata.of_node = spi->dev.of_node;
- return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+ return mtd_device_parse_register(&nor->mtd, NULL, &ppdata,
data ? data->parts : NULL,
data ? data->nr_parts : 0);
}
@@ -243,7 +240,7 @@ static int m25p_remove(struct spi_device *spi)
struct m25p *flash = spi_get_drvdata(spi);
/* Clean up MTD stuff. */
- return mtd_device_unregister(&flash->mtd);
+ return mtd_device_unregister(&flash->spi_nor.mtd);
}
/*
@@ -304,7 +301,6 @@ MODULE_DEVICE_TABLE(of, m25p_of_table);
static struct spi_driver m25p80_driver = {
.driver = {
.name = "m25p80",
- .owner = THIS_MODULE,
.of_match_table = m25p_of_table,
},
.id_table = m25p_ids,
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index df6f61137376..e4a88715a844 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -648,7 +648,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
device->size = nr_pages * pagesize;
device->erasesize = pagesize;
device->writesize = pagesize;
- device->owner = THIS_MODULE;
device->type = MTD_DATAFLASH;
device->flags = MTD_WRITEABLE;
device->_erase = dataflash_erase;
@@ -911,7 +910,6 @@ static int dataflash_remove(struct spi_device *spi)
static struct spi_driver dataflash_driver = {
.driver = {
.name = "mtd_dataflash",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(dataflash_dt_ids),
},
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index 8e285089229c..627a9bc37679 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -32,8 +32,29 @@ MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
// We could store these in the mtd structure, but we only support 1 device..
static struct mtd_info *mtd_info;
+static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ int ret = 0;
+
+ /* Start address must align on block boundary */
+ if (mtd_mod_by_eb(ofs, mtd)) {
+ pr_debug("%s: unaligned address\n", __func__);
+ ret = -EINVAL;
+ }
+
+ /* Length must align on block boundary */
+ if (mtd_mod_by_eb(len, mtd)) {
+ pr_debug("%s: length not block aligned\n", __func__);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
+ if (check_offs_len(mtd, instr->addr, instr->len))
+ return -EINVAL;
memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
index 04b24d2b03f2..64c7458344d4 100644
--- a/drivers/mtd/devices/spear_smi.c
+++ b/drivers/mtd/devices/spear_smi.c
@@ -854,6 +854,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
else
flash->mtd.name = flash_devices[flash_index].name;
+ flash->mtd.dev.parent = &pdev->dev;
flash->mtd.type = MTD_NORFLASH;
flash->mtd.writesize = 1;
flash->mtd.flags = MTD_CAP_NORFLASH;
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index c63ecbcad0b7..5b84d71efb36 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -374,9 +374,8 @@ static int sst25l_probe(struct spi_device *spi)
data = dev_get_platdata(&spi->dev);
if (data && data->name)
flash->mtd.name = data->name;
- else
- flash->mtd.name = dev_name(&spi->dev);
+ flash->mtd.dev.parent = &spi->dev;
flash->mtd.type = MTD_NORFLASH;
flash->mtd.flags = MTD_CAP_NORFLASH;
flash->mtd.erasesize = flash_info->erase_size;
@@ -417,7 +416,6 @@ static int sst25l_remove(struct spi_device *spi)
static struct spi_driver sst25l_driver = {
.driver = {
.name = "sst25l",
- .owner = THIS_MODULE,
},
.probe = sst25l_probe,
.remove = sst25l_remove,
diff --git a/drivers/mtd/lpddr/lpddr2_nvm.c b/drivers/mtd/lpddr/lpddr2_nvm.c
index 063cec40d0ae..2342277c9bcb 100644
--- a/drivers/mtd/lpddr/lpddr2_nvm.c
+++ b/drivers/mtd/lpddr/lpddr2_nvm.c
@@ -460,6 +460,7 @@ static int lpddr2_nvm_probe(struct platform_device *pdev)
/* Populate mtd_info data structure */
*mtd = (struct mtd_info) {
+ .dev = { .parent = &pdev->dev },
.name = pdev->dev.init_name,
.type = MTD_RAM,
.priv = map,
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 2fb346091af2..385305e66fd1 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -266,7 +266,7 @@ static int gpio_flash_probe(struct platform_device *pdev)
kfree(state);
return -ENXIO;
}
-
+ state->mtd->dev.parent = &pdev->dev;
mtd_device_parse_register(state->mtd, part_probe_types, NULL,
pdata->parts, pdata->nr_parts);
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index 5ab71f0e1bcd..8bf79775e7c1 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -90,7 +90,7 @@ static int vr_nor_mtd_setup(struct vr_nor_mtd *p)
if (!p->info)
return -ENODEV;
- p->info->owner = THIS_MODULE;
+ p->info->dev.parent = &p->dev->dev;
return 0;
}
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index b4430741024e..e3180d5aa06a 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -226,7 +226,7 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
err = -ENXIO;
goto Error;
}
- info->mtd->owner = THIS_MODULE;
+ info->mtd->dev.parent = &dev->dev;
/* Use the fast version */
info->map.write = ixp4xx_write16;
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index e2f878216048..93852054977e 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -160,7 +160,7 @@ ltq_mtd_probe(struct platform_device *pdev)
return -ENXIO;
}
- ltq_mtd->mtd->owner = THIS_MODULE;
+ ltq_mtd->mtd->dev.parent = &pdev->dev;
cfi = ltq_mtd->map->fldrv_priv;
cfi->addr_unlock1 ^= 1;
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index cadfbe051873..6dc97aa667dc 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -195,7 +195,7 @@ static int latch_addr_flash_probe(struct platform_device *dev)
err = -ENODEV;
goto iounmap;
}
- info->mtd->owner = THIS_MODULE;
+ info->mtd->dev.parent = &dev->dev;
mtd_device_parse_register(info->mtd, NULL, NULL,
latch_addr_data->parts,
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index af747af5eee9..3dad2111b7e3 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -700,6 +700,7 @@ static const struct pcmcia_device_id pcmciamtd_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0),
PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965),
PCMCIA_DEVICE_PROD_ID12("PRETEC", " 2MB SRAM CARD", 0xebf91155, 0x805360ca),
+ PCMCIA_DEVICE_PROD_ID12("PRETEC", " 4MB SRAM CARD", 0xebf91155, 0x20b6bf17),
PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b),
PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad),
PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05),
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 4305fd607015..cc2adbbcd60f 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -167,7 +167,6 @@ static int physmap_flash_probe(struct platform_device *dev)
} else {
devices_found++;
}
- info->mtd[i]->owner = THIS_MODULE;
info->mtd[i]->dev.parent = &dev->dev;
}
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 3e614e9119d5..e46b4e983666 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -290,7 +290,6 @@ static int of_flash_probe(struct platform_device *dev)
} else {
info->list_size++;
}
- info->list[i].mtd->owner = THIS_MODULE;
info->list[i].mtd->dev.parent = &dev->dev;
}
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 4b65c08d15f6..51572895c02c 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -210,7 +210,6 @@ static int platram_probe(struct platform_device *pdev)
goto exit_free;
}
- info->mtd->owner = THIS_MODULE;
info->mtd->dev.parent = &pdev->dev;
platram_setrw(info, PLATRAM_RW);
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 12fa75df5008..7497090e9900 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -71,8 +71,8 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
info->map.name);
return -ENOMEM;
}
- info->map.cached =
- ioremap_cache(info->map.phys, info->map.size);
+ info->map.cached = memremap(info->map.phys, info->map.size,
+ MEMREMAP_WB);
if (!info->map.cached)
printk(KERN_WARNING "Failed to ioremap cached %s\n",
info->map.name);
@@ -93,7 +93,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
iounmap(info->map.cached);
return -EIO;
}
- info->mtd->owner = THIS_MODULE;
+ info->mtd->dev.parent = &pdev->dev;
mtd_device_parse_register(info->mtd, probes, NULL, flash->parts,
flash->nr_parts);
@@ -111,7 +111,7 @@ static int pxa2xx_flash_remove(struct platform_device *dev)
map_destroy(info->mtd);
iounmap(info->map.virt);
if (info->map.cached)
- iounmap(info->map.cached);
+ memunmap(info->map.cached);
kfree(info);
return 0;
}
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 5a7551aa2d89..3a06ecfc55ff 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -96,7 +96,7 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
err = -ENXIO;
goto err_out;
}
- info->mtd->owner = THIS_MODULE;
+ info->mtd->dev.parent = &dev->dev;
err = mtd_device_parse_register(info->mtd, NULL, NULL, pdata->parts,
pdata->nr_parts);
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 892ad6ac63f2..142fc3d79463 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -117,7 +117,6 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
ret = -ENXIO;
goto err;
}
- subdev->mtd->owner = THIS_MODULE;
printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %uMiB, %d-bit\n",
phys, (unsigned)(subdev->mtd->size >> 20),
@@ -234,6 +233,7 @@ static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev,
if (info->mtd == NULL)
ret = -ENXIO;
}
+ info->mtd->dev.parent = &pdev->dev;
if (ret == 0)
return info;
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 44dc965a2f7c..f4701182b558 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -192,8 +192,8 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
if (!dev)
return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
- mutex_lock(&dev->lock);
mutex_lock(&mtd_table_mutex);
+ mutex_lock(&dev->lock);
if (dev->open)
goto unlock;
@@ -217,8 +217,8 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
unlock:
dev->open++;
- mutex_unlock(&mtd_table_mutex);
mutex_unlock(&dev->lock);
+ mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
return ret;
@@ -228,8 +228,8 @@ error_release:
error_put:
module_put(dev->tr->owner);
kref_put(&dev->ref, blktrans_dev_release);
- mutex_unlock(&mtd_table_mutex);
mutex_unlock(&dev->lock);
+ mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
return ret;
}
@@ -241,8 +241,8 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode)
if (!dev)
return;
- mutex_lock(&dev->lock);
mutex_lock(&mtd_table_mutex);
+ mutex_lock(&dev->lock);
if (--dev->open)
goto unlock;
@@ -256,8 +256,8 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode)
__put_mtd_device(dev->mtd);
}
unlock:
- mutex_unlock(&mtd_table_mutex);
mutex_unlock(&dev->lock);
+ mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
}
@@ -399,7 +399,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
snprintf(gd->disk_name, sizeof(gd->disk_name),
"%s%d", tr->name, new->devnum);
- set_capacity(gd, (new->size * tr->blksize) >> 9);
+ set_capacity(gd, ((u64)new->size * tr->blksize) >> 9);
/* Create the request queue */
spin_lock_init(&new->queue_lock);
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 55fa27ecf4e1..6d19835b80a9 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -498,21 +498,17 @@ static int shrink_ecclayout(const struct nand_ecclayout *from,
}
static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
- struct blkpg_ioctl_arg __user *arg)
+ struct blkpg_ioctl_arg *arg)
{
- struct blkpg_ioctl_arg a;
struct blkpg_partition p;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
+ if (copy_from_user(&p, arg->data, sizeof(p)))
return -EFAULT;
- if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
- return -EFAULT;
-
- switch (a.op) {
+ switch (arg->op) {
case BLKPG_ADD_PARTITION:
/* Only master mtd device must be used to add partitions */
@@ -966,8 +962,13 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
case BLKPG:
{
- ret = mtdchar_blkpg_ioctl(mtd,
- (struct blkpg_ioctl_arg __user *)arg);
+ struct blkpg_ioctl_arg __user *blk_arg = argp;
+ struct blkpg_ioctl_arg a;
+
+ if (copy_from_user(&a, blk_arg, sizeof(a)))
+ ret = -EFAULT;
+ else
+ ret = mtdchar_blkpg_ioctl(mtd, &a);
break;
}
@@ -1046,6 +1047,29 @@ static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
&buf_user->start);
break;
}
+
+ case BLKPG:
+ {
+ /* Convert from blkpg_compat_ioctl_arg to blkpg_ioctl_arg */
+ struct blkpg_compat_ioctl_arg __user *uarg = argp;
+ struct blkpg_compat_ioctl_arg compat_arg;
+ struct blkpg_ioctl_arg a;
+
+ if (copy_from_user(&compat_arg, uarg, sizeof(compat_arg))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ memset(&a, 0, sizeof(a));
+ a.op = compat_arg.op;
+ a.flags = compat_arg.flags;
+ a.datalen = compat_arg.datalen;
+ a.data = compat_ptr(compat_arg.data);
+
+ ret = mtdchar_blkpg_ioctl(mtd, &a);
+ break;
+ }
+
default:
ret = mtdchar_ioctl(file, cmd, (unsigned long)argp);
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 8bbbb751bf45..95c13b2ffa79 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -387,6 +387,14 @@ int add_mtd_device(struct mtd_info *mtd)
struct mtd_notifier *not;
int i, error;
+ /*
+ * May occur, for instance, on buggy drivers which call
+ * mtd_device_parse_register() multiple times on the same master MTD,
+ * especially with CONFIG_MTD_PARTITIONED_MASTER=y.
+ */
+ if (WARN_ONCE(mtd->backing_dev_info, "MTD already registered\n"))
+ return -EEXIST;
+
mtd->backing_dev_info = &mtd_bdi;
BUG_ON(mtd->writesize == 0);
@@ -418,6 +426,15 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
+ if (mtd->dev.parent) {
+ if (!mtd->owner && mtd->dev.parent->driver)
+ mtd->owner = mtd->dev.parent->driver->owner;
+ if (!mtd->name)
+ mtd->name = dev_name(mtd->dev.parent);
+ } else {
+ pr_debug("mtd device won't show a device symlink in sysfs\n");
+ }
+
/* Some chips always power up locked. Unlock them now */
if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) {
error = mtd_unlock(mtd, 0, mtd->size);
@@ -430,7 +447,7 @@ int add_mtd_device(struct mtd_info *mtd)
}
/* Caller should have set dev.parent to match the
- * physical device.
+ * physical device, if appropriate.
*/
mtd->dev.type = &mtd_devtype;
mtd->dev.class = &mtd_class;
@@ -579,9 +596,17 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
else
ret = nr_parts;
}
+ /* Didn't come up with either parsed OR fallback partitions */
+ if (ret < 0) {
+ pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n",
+ ret);
+ /* Don't abort on errors; we can still use unpartitioned MTD */
+ ret = 0;
+ }
- if (ret >= 0)
- ret = mtd_add_device_partitions(mtd, real_parts, ret);
+ ret = mtd_add_device_partitions(mtd, real_parts, ret);
+ if (ret)
+ goto out;
/*
* FIXME: some drivers unfortunately call this function more than once.
@@ -591,11 +616,14 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
* does cause problems with parse_mtd_partitions() above (e.g.,
* cmdlineparts will register partitions more than once).
*/
+ WARN_ONCE(mtd->_reboot && mtd->reboot_notifier.notifier_call,
+ "MTD already registered\n");
if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) {
mtd->reboot_notifier.notifier_call = mtd_reboot_notifier;
register_reboot_notifier(&mtd->reboot_notifier);
}
+out:
kfree(real_parts);
return ret;
}
@@ -1188,8 +1216,7 @@ EXPORT_SYMBOL_GPL(mtd_writev);
*/
void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
{
- gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
- __GFP_NORETRY | __GFP_NO_KSWAPD;
+ gfp_t flags = __GFP_NOWARN | __GFP_DIRECT_RECLAIM | __GFP_NORETRY;
size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
void *kbuf;
@@ -1301,6 +1328,7 @@ static void __exit cleanup_mtd(void)
remove_proc_entry("mtd", NULL);
class_unregister(&mtd_class);
bdi_destroy(&mtd_bdi);
+ idr_destroy(&mtd_idr);
}
module_init(init_mtd);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index cafdb8855a79..f8ba153f63bf 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -664,8 +664,10 @@ int add_mtd_partitions(struct mtd_info *master,
for (i = 0; i < nbparts; i++) {
slave = allocate_partition(master, parts + i, i, cur_offset);
- if (IS_ERR(slave))
+ if (IS_ERR(slave)) {
+ del_mtd_partitions(master);
return PTR_ERR(slave);
+ }
mutex_lock(&mtd_partitions_mutex);
list_add(&slave->list, &mtd_partitions);
@@ -753,26 +755,37 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
struct mtd_part_parser_data *data)
{
struct mtd_part_parser *parser;
- int ret = 0;
+ int ret, err = 0;
if (!types)
types = default_mtd_part_types;
- for ( ; ret <= 0 && *types; types++) {
+ for ( ; *types; types++) {
+ pr_debug("%s: parsing partitions %s\n", master->name, *types);
parser = get_partition_parser(*types);
if (!parser && !request_module("%s", *types))
parser = get_partition_parser(*types);
+ pr_debug("%s: got parser %s\n", master->name,
+ parser ? parser->name : NULL);
if (!parser)
continue;
ret = (*parser->parse_fn)(master, pparts, data);
+ pr_debug("%s: parser %s: %i\n",
+ master->name, parser->name, ret);
put_partition_parser(parser);
if (ret > 0) {
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
ret, parser->name, master->name);
- break;
+ return ret;
}
+ /*
+ * Stash the first error we see; only report it if no parser
+ * succeeds
+ */
+ if (ret < 0 && !err)
+ err = ret;
}
- return ret;
+ return err;
}
int mtd_is_partition(const struct mtd_info *mtd)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 3324281d1f53..289664089cf3 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -393,7 +393,7 @@ config MTD_NAND_GPMI_NAND
config MTD_NAND_BRCMNAND
tristate "Broadcom STB NAND controller"
- depends on ARM || MIPS
+ depends on ARM || ARM64 || MIPS
help
Enables the Broadcom NAND controller driver. The controller was
originally designed for Set-Top Box but is used on various BCM7xxx,
@@ -460,6 +460,17 @@ config MTD_NAND_MPC5121_NFC
This enables the driver for the NAND flash controller on the
MPC5121 SoC.
+config MTD_NAND_VF610_NFC
+ tristate "Support for Freescale NFC for VF610/MPC5125"
+ depends on (SOC_VF610 || COMPILE_TEST)
+ help
+ Enables support for NAND Flash Controller on some Freescale
+ processors like the VF610, MPC5125, MCF54418 or Kinetis K70.
+ The driver supports a maximum 2k page size. With 2k pages and
+ 64 bytes or more of OOB, hardware ECC with up to 32-bit error
+ correction is supported. Hardware ECC is only enabled through
+ device tree.
+
config MTD_NAND_MXC
tristate "MXC NAND support"
depends on ARCH_MXC
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 075a027632b5..2c7f014b349e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o
obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o
obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o
obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
+obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o
obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 46010bd895b1..583cdd9bb971 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -954,7 +954,8 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
}
static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
struct atmel_nand_host *host = chip->priv;
uint32_t *eccpos = chip->ecc.layout->eccpos;
@@ -2005,7 +2006,8 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
if (likely(!raw))
/* Need to write ecc into oob */
- status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+ status = chip->ecc.write_page(mtd, chip, buf, oob_required,
+ page);
if (status < 0)
return status;
@@ -2126,7 +2128,7 @@ static int atmel_nand_probe(struct platform_device *pdev)
nand_chip->priv = host; /* link the private data structures */
mtd->priv = nand_chip;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
/* Set address of NAND IO lines */
nand_chip->IO_ADDR_R = host->io_base;
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index c0c3be180012..08a130f63faf 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -439,7 +439,7 @@ static int au1550nd_probe(struct platform_device *pdev)
this = &ctx->chip;
ctx->info.priv = this;
- ctx->info.owner = THIS_MODULE;
+ ctx->info.dev.parent = &pdev->dev;
/* figure out which CS# r->start belongs to */
cs = find_nand_cs(r->start);
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c
index 461577cfb5bc..9ba0c0f2cd9b 100644
--- a/drivers/mtd/nand/bcm47xxnflash/main.c
+++ b/drivers/mtd/nand/bcm47xxnflash/main.c
@@ -34,7 +34,7 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
return -ENOMEM;
b47n->nand_chip.priv = b47n;
- b47n->mtd.owner = THIS_MODULE;
+ b47n->mtd.dev.parent = &pdev->dev;
b47n->mtd.priv = &b47n->nand_chip; /* Required */
b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 4d8d4ba4b9c1..61bd2160717c 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -566,7 +566,8 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip
}
static int bf5xx_nand_write_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -782,7 +783,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
/* initialise mtd info data struct */
mtd = &info->mtd;
mtd->priv = chip;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
/* initialise the hardware */
err = bf5xx_nand_hw_init(info);
diff --git a/drivers/mtd/nand/brcmnand/bcm63138_nand.c b/drivers/mtd/nand/brcmnand/bcm63138_nand.c
index 3f4c44c24e14..59444b3a697d 100644
--- a/drivers/mtd/nand/brcmnand/bcm63138_nand.c
+++ b/drivers/mtd/nand/brcmnand/bcm63138_nand.c
@@ -22,7 +22,8 @@
#include "brcmnand.h"
-struct bcm63138_nand_soc_priv {
+struct bcm63138_nand_soc {
+ struct brcmnand_soc soc;
void __iomem *base;
};
@@ -35,7 +36,8 @@ enum {
static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc)
{
- struct bcm63138_nand_soc_priv *priv = soc->priv;
+ struct bcm63138_nand_soc *priv =
+ container_of(soc, struct bcm63138_nand_soc, soc);
void __iomem *mmio = priv->base + BCM63138_NAND_INT_STATUS;
u32 val = brcmnand_readl(mmio);
@@ -49,7 +51,8 @@ static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc)
static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en)
{
- struct bcm63138_nand_soc_priv *priv = soc->priv;
+ struct bcm63138_nand_soc *priv =
+ container_of(soc, struct bcm63138_nand_soc, soc);
void __iomem *mmio = priv->base + BCM63138_NAND_INT_EN;
u32 val = brcmnand_readl(mmio);
@@ -64,25 +67,20 @@ static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en)
static int bcm63138_nand_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct bcm63138_nand_soc_priv *priv;
+ struct bcm63138_nand_soc *priv;
struct brcmnand_soc *soc;
struct resource *res;
- soc = devm_kzalloc(dev, sizeof(*soc), GFP_KERNEL);
- if (!soc)
- return -ENOMEM;
-
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ soc = &priv->soc;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-int-base");
priv->base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- soc->pdev = pdev;
- soc->priv = priv;
soc->ctlrdy_ack = bcm63138_nand_intc_ack;
soc->ctlrdy_set_enabled = bcm63138_nand_intc_set;
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index fddb795eeb71..12c6190c6e33 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -344,6 +344,28 @@ static const u8 brcmnand_cs_offsets_cs0[] = {
[BRCMNAND_CS_TIMING2] = 0x14,
};
+/*
+ * Bitfields for the CFG and CFG_EXT registers. Pre-v7.1 controllers only had
+ * one config register, but once the bitfields overflowed, newer controllers
+ * (v7.1 and newer) added a CFG_EXT register and shuffled a few fields around.
+ */
+enum {
+ CFG_BLK_ADR_BYTES_SHIFT = 8,
+ CFG_COL_ADR_BYTES_SHIFT = 12,
+ CFG_FUL_ADR_BYTES_SHIFT = 16,
+ CFG_BUS_WIDTH_SHIFT = 23,
+ CFG_BUS_WIDTH = BIT(CFG_BUS_WIDTH_SHIFT),
+ CFG_DEVICE_SIZE_SHIFT = 24,
+
+ /* Only for pre-v7.1 (with no CFG_EXT register) */
+ CFG_PAGE_SIZE_SHIFT = 20,
+ CFG_BLK_SIZE_SHIFT = 28,
+
+ /* Only for v7.1+ (with CFG_EXT register) */
+ CFG_EXT_PAGE_SIZE_SHIFT = 0,
+ CFG_EXT_BLK_SIZE_SHIFT = 4,
+};
+
/* BRCMNAND_INTFC_STATUS */
enum {
INTFC_FLASH_STATUS = GENMASK(7, 0),
@@ -1544,9 +1566,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
dev_dbg(ctrl->dev, "write %llx <- %p\n", (unsigned long long)addr, buf);
- if (unlikely((u32)buf & 0x03)) {
+ if (unlikely((unsigned long)buf & 0x03)) {
dev_warn(ctrl->dev, "unaligned buffer: %p\n", buf);
- buf = (u32 *)((u32)buf & ~0x03);
+ buf = (u32 *)((unsigned long)buf & ~0x03);
}
brcmnand_wp(mtd, 0);
@@ -1606,7 +1628,7 @@ out:
}
static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
struct brcmnand_host *host = chip->priv;
void *oob = oob_required ? chip->oob_poi : NULL;
@@ -1617,7 +1639,7 @@ static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
static int brcmnand_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
struct brcmnand_host *host = chip->priv;
void *oob = oob_required ? chip->oob_poi : NULL;
@@ -1720,17 +1742,19 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
}
device_size = fls64(cfg->device_size) - fls64(BRCMNAND_MIN_DEVSIZE);
- tmp = (cfg->blk_adr_bytes << 8) |
- (cfg->col_adr_bytes << 12) |
- (cfg->ful_adr_bytes << 16) |
- (!!(cfg->device_width == 16) << 23) |
- (device_size << 24);
+ tmp = (cfg->blk_adr_bytes << CFG_BLK_ADR_BYTES_SHIFT) |
+ (cfg->col_adr_bytes << CFG_COL_ADR_BYTES_SHIFT) |
+ (cfg->ful_adr_bytes << CFG_FUL_ADR_BYTES_SHIFT) |
+ (!!(cfg->device_width == 16) << CFG_BUS_WIDTH_SHIFT) |
+ (device_size << CFG_DEVICE_SIZE_SHIFT);
if (cfg_offs == cfg_ext_offs) {
- tmp |= (page_size << 20) | (block_size << 28);
+ tmp |= (page_size << CFG_PAGE_SIZE_SHIFT) |
+ (block_size << CFG_BLK_SIZE_SHIFT);
nand_writereg(ctrl, cfg_offs, tmp);
} else {
nand_writereg(ctrl, cfg_offs, tmp);
- tmp = page_size | (block_size << 4);
+ tmp = (page_size << CFG_EXT_PAGE_SIZE_SHIFT) |
+ (block_size << CFG_EXT_BLK_SIZE_SHIFT);
nand_writereg(ctrl, cfg_ext_offs, tmp);
}
@@ -1792,7 +1816,8 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
memset(cfg, 0, sizeof(*cfg));
- ret = of_property_read_u32(chip->dn, "brcm,nand-oob-sector-size",
+ ret = of_property_read_u32(chip->flash_node,
+ "brcm,nand-oob-sector-size",
&oob_sector);
if (ret) {
/* Use detected size */
@@ -1888,6 +1913,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host)
struct mtd_info *mtd;
struct nand_chip *chip;
int ret;
+ u16 cfg_offs;
struct mtd_part_parser_data ppdata = { .of_node = dn };
ret = of_property_read_u32(dn, "reg", &host->cs);
@@ -1899,7 +1925,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host)
mtd = &host->mtd;
chip = &host->chip;
- chip->dn = dn;
+ chip->flash_node = dn;
chip->priv = host;
mtd->priv = chip;
mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d",
@@ -1930,6 +1956,15 @@ static int brcmnand_init_cs(struct brcmnand_host *host)
chip->controller = &ctrl->controller;
+ /*
+ * The bootloader might have configured 16bit mode but
+ * NAND READID command only works in 8bit mode. We force
+ * 8bit mode here to ensure that NAND READID commands works.
+ */
+ cfg_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_CFG);
+ nand_writereg(ctrl, cfg_offs,
+ nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH);
+
if (nand_scan_ident(mtd, 1, NULL))
return -ENXIO;
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
index 169f99e38a26..ef5eabba88e5 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.h
+++ b/drivers/mtd/nand/brcmnand/brcmnand.h
@@ -21,8 +21,6 @@ struct platform_device;
struct dev_pm_ops;
struct brcmnand_soc {
- struct platform_device *pdev;
- void *priv;
bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare);
diff --git a/drivers/mtd/nand/brcmnand/iproc_nand.c b/drivers/mtd/nand/brcmnand/iproc_nand.c
index 683495c74620..585596c549b2 100644
--- a/drivers/mtd/nand/brcmnand/iproc_nand.c
+++ b/drivers/mtd/nand/brcmnand/iproc_nand.c
@@ -22,7 +22,9 @@
#include "brcmnand.h"
-struct iproc_nand_soc_priv {
+struct iproc_nand_soc {
+ struct brcmnand_soc soc;
+
void __iomem *idm_base;
void __iomem *ext_base;
spinlock_t idm_lock;
@@ -37,7 +39,8 @@ struct iproc_nand_soc_priv {
static bool iproc_nand_intc_ack(struct brcmnand_soc *soc)
{
- struct iproc_nand_soc_priv *priv = soc->priv;
+ struct iproc_nand_soc *priv =
+ container_of(soc, struct iproc_nand_soc, soc);
void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET;
u32 val = brcmnand_readl(mmio);
@@ -51,7 +54,8 @@ static bool iproc_nand_intc_ack(struct brcmnand_soc *soc)
static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
{
- struct iproc_nand_soc_priv *priv = soc->priv;
+ struct iproc_nand_soc *priv =
+ container_of(soc, struct iproc_nand_soc, soc);
void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
u32 val;
unsigned long flags;
@@ -72,7 +76,8 @@ static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare)
{
- struct iproc_nand_soc_priv *priv = soc->priv;
+ struct iproc_nand_soc *priv =
+ container_of(soc, struct iproc_nand_soc, soc);
void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
u32 val;
unsigned long flags;
@@ -94,17 +99,14 @@ static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare)
static int iproc_nand_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct iproc_nand_soc_priv *priv;
+ struct iproc_nand_soc *priv;
struct brcmnand_soc *soc;
struct resource *res;
- soc = devm_kzalloc(dev, sizeof(*soc), GFP_KERNEL);
- if (!soc)
- return -ENOMEM;
-
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ soc = &priv->soc;
spin_lock_init(&priv->idm_lock);
@@ -118,8 +120,6 @@ static int iproc_nand_probe(struct platform_device *pdev)
if (IS_ERR(priv->ext_base))
return PTR_ERR(priv->ext_base);
- soc->pdev = pdev;
- soc->priv = priv;
soc->ctlrdy_ack = iproc_nand_intc_ack;
soc->ctlrdy_set_enabled = iproc_nand_intc_set;
soc->prepare_data_bus = iproc_nand_apb_access;
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 9a0f45f1d932..9de78d2a2eb1 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -516,7 +516,8 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
struct cafe_priv *cafe = mtd->priv;
@@ -604,7 +605,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
mtd->dev.parent = &pdev->dev;
mtd->priv = cafe;
- mtd->owner = THIS_MODULE;
cafe->pdev = pdev;
cafe->mmio = pci_iomap(pdev, 0, 0);
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index b90801302df4..c72313d66cf6 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -683,9 +683,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
info->vaddr = vaddr;
info->mtd.priv = &info->chip;
- info->mtd.name = dev_name(&pdev->dev);
- info->mtd.owner = THIS_MODULE;
-
info->mtd.dev.parent = &pdev->dev;
info->chip.IO_ADDR_R = vaddr;
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 870c7fc0f759..67eb2be0db87 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -458,8 +458,17 @@ static void find_valid_banks(struct denali_nand_info *denali)
static void detect_max_banks(struct denali_nand_info *denali)
{
uint32_t features = ioread32(denali->flash_reg + FEATURES);
+ /*
+ * Read the revision register, so we can calculate the max_banks
+ * properly: the encoding changed from rev 5.0 to 5.1
+ */
+ u32 revision = MAKE_COMPARABLE_REVISION(
+ ioread32(denali->flash_reg + REVISION));
- denali->max_banks = 2 << (features & FEATURES__N_BANKS);
+ if (revision < REVISION_5_1)
+ denali->max_banks = 2 << (features & FEATURES__N_BANKS);
+ else
+ denali->max_banks = 1 << (features & FEATURES__N_BANKS);
}
static void detect_partition_feature(struct denali_nand_info *denali)
@@ -1105,7 +1114,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip,
* by write_page above.
*/
static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
/*
* for regular page writes, we let HW handle all the ECC
@@ -1120,7 +1129,8 @@ static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
* write_page() function above.
*/
static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
/*
* for raw page writes, we want to disable ECC and simply write
@@ -1304,7 +1314,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
*/
addr = MODE_11 | BANK(denali->flash_bank);
index_addr(denali, addr | 0, 0x90);
- index_addr(denali, addr | 1, 0);
+ index_addr(denali, addr | 1, col);
for (i = 0; i < 8; i++) {
index_addr_read_data(denali, addr | 2, &id);
write_byte_to_buf(denali, id);
@@ -1454,7 +1464,6 @@ int denali_init(struct denali_nand_info *denali)
/* now that our ISR is registered, we can enable interrupts */
denali_set_intr_modes(denali, true);
denali->mtd.name = "denali-nand";
- denali->mtd.owner = THIS_MODULE;
denali->mtd.priv = &denali->nand;
/* register the driver with the NAND core subsystem */
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 145bf88930e8..4b12cd302819 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -178,6 +178,8 @@
#define REVISION 0x370
#define REVISION__VALUE 0xffff
+#define MAKE_COMPARABLE_REVISION(x) swab16((x) & REVISION__VALUE)
+#define REVISION_5_1 0x00000501
#define ONFI_DEVICE_FEATURES 0x380
#define ONFI_DEVICE_FEATURES__VALUE 0x003f
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index e5d7bcaafa7d..408cf69b854b 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -977,13 +977,13 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
}
static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
return write_page(mtd, nand, buf, false);
}
static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
return write_page(mtd, nand, buf, true);
}
@@ -1113,7 +1113,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
/* write first page of block */
write_page_prologue(mtd, g4_addr);
- docg4_write_page(mtd, nand, buf, 1);
+ docg4_write_page(mtd, nand, buf, 1, page);
ret = pageprog(mtd);
kfree(buf);
@@ -1316,7 +1316,7 @@ static int __init probe_docg4(struct platform_device *pdev)
doc = (struct docg4_priv *) (nand + 1);
mtd->priv = nand;
nand->priv = doc;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
doc->virtadr = virtadr;
doc->dev = dev;
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 04b22fd3732d..dcb1f7f4873f 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -715,7 +715,7 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
* waitfunc.
*/
static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -728,7 +728,7 @@ static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
*/
static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offset, uint32_t data_len,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -747,7 +747,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
/* Fill in fsl_elbc_mtd structure */
priv->mtd.priv = chip;
- priv->mtd.owner = THIS_MODULE;
+ priv->mtd.dev.parent = priv->dev;
/* set timeout to maximum */
priv->fmr = 15 << FMR_CWTO_SHIFT;
@@ -946,6 +946,7 @@ static const struct of_device_id fsl_elbc_nand_match[] = {
{ .compatible = "fsl,elbc-fcm-nand", },
{}
};
+MODULE_DEVICE_TABLE(of, fsl_elbc_nand_match);
static struct platform_driver fsl_elbc_nand_driver = {
.driver = {
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index a4e27e891153..7f4ac8c19001 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -772,7 +772,7 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
* waitfunc.
*/
static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
fsl_ifc_write_buf(mtd, buf, mtd->writesize);
fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -882,7 +882,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
/* Fill in fsl_ifc_mtd structure */
priv->mtd.priv = chip;
- priv->mtd.owner = THIS_MODULE;
+ priv->mtd.dev.parent = priv->dev;
/* fill in nand_chip structure */
/* set up function call table */
@@ -1163,6 +1163,7 @@ static const struct of_device_id fsl_ifc_nand_match[] = {
},
{}
};
+MODULE_DEVICE_TABLE(of, fsl_ifc_nand_match);
static struct platform_driver fsl_ifc_nand_driver = {
.driver = {
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 72755d7ec25d..d326369980c4 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -176,7 +176,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
fun->chip.dev_ready = fun_chip_ready;
fun->mtd.priv = &fun->chip;
- fun->mtd.owner = THIS_MODULE;
+ fun->mtd.dev.parent = fun->dev;
flash_np = of_get_next_child(upm_np, NULL);
if (!flash_np)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 793872f18065..07af3dc7a4d2 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -348,7 +348,7 @@ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
break;
default:
- BUG();
+ dev_err(host->dev, "unsupported chip-select %d\n", chipnr);
}
}
@@ -960,7 +960,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
host->data_va = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(host->data_va))
return PTR_ERR(host->data_va);
-
+
host->data_pa = (dma_addr_t)res->start;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
@@ -1017,18 +1017,23 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
mtd->priv = nand;
nand->priv = host;
- host->mtd.owner = THIS_MODULE;
+ host->mtd.dev.parent = &pdev->dev;
nand->IO_ADDR_R = host->data_va;
nand->IO_ADDR_W = host->data_va;
nand->cmd_ctrl = fsmc_cmd_ctrl;
nand->chip_delay = 30;
+ /*
+ * Setup default ECC mode. nand_dt_init() called from nand_scan_ident()
+ * can overwrite this value if the DT provides a different value.
+ */
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.hwctl = fsmc_enable_hwecc;
nand->ecc.size = 512;
nand->options = pdata->options;
nand->select_chip = fsmc_select_chip;
nand->badblockbits = 7;
+ nand->flash_node = np;
if (pdata->width == FSMC_NAND_BW16)
nand->options |= NAND_BUSWIDTH_16;
@@ -1070,11 +1075,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->ecc.correct = fsmc_bch8_correct_data;
nand->ecc.bytes = 13;
nand->ecc.strength = 8;
- } else {
- nand->ecc.calculate = fsmc_read_hwecc_ecc1;
- nand->ecc.correct = nand_correct_data;
- nand->ecc.bytes = 3;
- nand->ecc.strength = 1;
}
/*
@@ -1111,23 +1111,50 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
default:
dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
mtd->oobsize);
- BUG();
+ ret = -EINVAL;
+ goto err_probe;
}
} else {
- switch (host->mtd.oobsize) {
- case 16:
- nand->ecc.layout = &fsmc_ecc1_16_layout;
- break;
- case 64:
- nand->ecc.layout = &fsmc_ecc1_64_layout;
+ switch (nand->ecc.mode) {
+ case NAND_ECC_HW:
+ dev_info(&pdev->dev, "Using 1-bit HW ECC scheme\n");
+ nand->ecc.calculate = fsmc_read_hwecc_ecc1;
+ nand->ecc.correct = nand_correct_data;
+ nand->ecc.bytes = 3;
+ nand->ecc.strength = 1;
break;
- case 128:
- nand->ecc.layout = &fsmc_ecc1_128_layout;
+
+ case NAND_ECC_SOFT_BCH:
+ dev_info(&pdev->dev, "Using 4-bit SW BCH ECC scheme\n");
break;
+
default:
- dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
- mtd->oobsize);
- BUG();
+ dev_err(&pdev->dev, "Unsupported ECC mode!\n");
+ goto err_probe;
+ }
+
+ /*
+ * Don't set layout for BCH4 SW ECC. This will be
+ * generated later in nand_bch_init() later.
+ */
+ if (nand->ecc.mode != NAND_ECC_SOFT_BCH) {
+ switch (host->mtd.oobsize) {
+ case 16:
+ nand->ecc.layout = &fsmc_ecc1_16_layout;
+ break;
+ case 64:
+ nand->ecc.layout = &fsmc_ecc1_64_layout;
+ break;
+ case 128:
+ nand->ecc.layout = &fsmc_ecc1_128_layout;
+ break;
+ default:
+ dev_warn(&pdev->dev,
+ "No oob scheme defined for oobsize %d\n",
+ mtd->oobsize);
+ ret = -EINVAL;
+ goto err_probe;
+ }
}
}
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 73c4048c3a56..9ab97f934c37 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -275,7 +275,7 @@ static int gpio_nand_probe(struct platform_device *pdev)
chip->cmd_ctrl = gpio_nand_cmd_ctrl;
gpiomtd->mtd_info.priv = chip;
- gpiomtd->mtd_info.owner = THIS_MODULE;
+ gpiomtd->mtd_info.dev.parent = &pdev->dev;
platform_set_drvdata(pdev, gpiomtd);
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 1b8f3500e6d2..2064adac1d17 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -1160,7 +1160,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
}
static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry;
@@ -1446,7 +1446,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry;
@@ -1533,7 +1533,7 @@ static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
{
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
- return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1);
+ return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
}
static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
@@ -1717,7 +1717,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
/* Write the first page of the current stride. */
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
- chip->ecc.write_page_raw(mtd, chip, buffer, 0);
+ chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
/* Wait for the write to finish. */
@@ -1897,7 +1897,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
/* init the MTD data structures */
mtd->priv = chip;
mtd->name = "gpmi-nand";
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = this->dev;
/* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
chip->priv = this;
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c
index 8dcc7b8fee40..0cb2e886937d 100644
--- a/drivers/mtd/nand/hisi504_nand.c
+++ b/drivers/mtd/nand/hisi504_nand.c
@@ -590,7 +590,8 @@ static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
}
static int hisi_nand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
if (oob_required)
@@ -737,7 +738,6 @@ static int hisi_nfc_probe(struct platform_device *pdev)
}
mtd->priv = chip;
- mtd->owner = THIS_MODULE;
mtd->name = "hisi_nand";
mtd->dev.parent = &pdev->dev;
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index ebf2cce04cba..5a99a93ed025 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -25,6 +25,7 @@
#include <linux/gpio.h>
+#include <asm/mach-jz4740/gpio.h>
#include <asm/mach-jz4740/jz4740_nand.h>
#define JZ_REG_NAND_CTRL 0x50
@@ -434,7 +435,7 @@ static int jz_nand_probe(struct platform_device *pdev)
mtd = &nand->mtd;
chip = &nand->chip;
mtd->priv = chip;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
mtd->name = "jz4740-nand";
chip->ecc.hwctl = jz_nand_hwctl;
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index 79c3b7801e1f..347510978484 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -495,7 +495,8 @@ static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
struct lpc32xx_nand_host *host = chip->priv;
const uint8_t *oobbuf = chip->oob_poi;
@@ -682,7 +683,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
nand_chip->priv = host; /* link the private data structures */
mtd->priv = nand_chip;
- mtd->owner = THIS_MODULE;
mtd->dev.parent = &pdev->dev;
/* Get NAND clock */
@@ -692,7 +692,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
res = -ENOENT;
goto err_exit1;
}
- clk_enable(host->clk);
+ clk_prepare_enable(host->clk);
nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
nand_chip->dev_ready = lpc32xx_nand_device_ready;
@@ -800,7 +800,7 @@ err_exit3:
if (use_dma)
dma_release_channel(host->dma_chan);
err_exit2:
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
clk_put(host->clk);
err_exit1:
lpc32xx_wp_enable(host);
@@ -822,7 +822,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
if (use_dma)
dma_release_channel(host->dma_chan);
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
clk_put(host->clk);
lpc32xx_wp_enable(host);
@@ -837,7 +837,7 @@ static int lpc32xx_nand_resume(struct platform_device *pdev)
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
/* Re-enable NAND clock */
- clk_enable(host->clk);
+ clk_prepare_enable(host->clk);
/* Fresh init of NAND controller */
lpc32xx_nand_setup(host);
@@ -856,7 +856,7 @@ static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
lpc32xx_wp_enable(host);
/* Disable clock */
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
return 0;
}
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index abfec13868e5..4f3d4eb17da0 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -94,22 +94,25 @@
/**********************************************************************
* slc_tac register definitions
**********************************************************************/
+/* Computation of clock cycles on basis of controller and device clock rates */
+#define SLCTAC_CLOCKS(c, n, s) (min_t(u32, DIV_ROUND_UP(c, n) - 1, 0xF) << s)
+
/* Clock setting for RDY write sample wait time in 2*n clocks */
#define SLCTAC_WDR(n) (((n) & 0xF) << 28)
/* Write pulse width in clock cycles, 1 to 16 clocks */
-#define SLCTAC_WWIDTH(n) (((n) & 0xF) << 24)
+#define SLCTAC_WWIDTH(c, n) (SLCTAC_CLOCKS(c, n, 24))
/* Write hold time of control and data signals, 1 to 16 clocks */
-#define SLCTAC_WHOLD(n) (((n) & 0xF) << 20)
+#define SLCTAC_WHOLD(c, n) (SLCTAC_CLOCKS(c, n, 20))
/* Write setup time of control and data signals, 1 to 16 clocks */
-#define SLCTAC_WSETUP(n) (((n) & 0xF) << 16)
+#define SLCTAC_WSETUP(c, n) (SLCTAC_CLOCKS(c, n, 16))
/* Clock setting for RDY read sample wait time in 2*n clocks */
#define SLCTAC_RDR(n) (((n) & 0xF) << 12)
/* Read pulse width in clock cycles, 1 to 16 clocks */
-#define SLCTAC_RWIDTH(n) (((n) & 0xF) << 8)
+#define SLCTAC_RWIDTH(c, n) (SLCTAC_CLOCKS(c, n, 8))
/* Read hold time of control and data signals, 1 to 16 clocks */
-#define SLCTAC_RHOLD(n) (((n) & 0xF) << 4)
+#define SLCTAC_RHOLD(c, n) (SLCTAC_CLOCKS(c, n, 4))
/* Read setup time of control and data signals, 1 to 16 clocks */
-#define SLCTAC_RSETUP(n) (((n) & 0xF) << 0)
+#define SLCTAC_RSETUP(c, n) (SLCTAC_CLOCKS(c, n, 0))
/**********************************************************************
* slc_ecc register definitions
@@ -240,13 +243,13 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
/* Compute clock setup values */
tmp = SLCTAC_WDR(host->ncfg->wdr_clks) |
- SLCTAC_WWIDTH(1 + (clkrate / host->ncfg->wwidth)) |
- SLCTAC_WHOLD(1 + (clkrate / host->ncfg->whold)) |
- SLCTAC_WSETUP(1 + (clkrate / host->ncfg->wsetup)) |
+ SLCTAC_WWIDTH(clkrate, host->ncfg->wwidth) |
+ SLCTAC_WHOLD(clkrate, host->ncfg->whold) |
+ SLCTAC_WSETUP(clkrate, host->ncfg->wsetup) |
SLCTAC_RDR(host->ncfg->rdr_clks) |
- SLCTAC_RWIDTH(1 + (clkrate / host->ncfg->rwidth)) |
- SLCTAC_RHOLD(1 + (clkrate / host->ncfg->rhold)) |
- SLCTAC_RSETUP(1 + (clkrate / host->ncfg->rsetup));
+ SLCTAC_RWIDTH(clkrate, host->ncfg->rwidth) |
+ SLCTAC_RHOLD(clkrate, host->ncfg->rhold) |
+ SLCTAC_RSETUP(clkrate, host->ncfg->rsetup);
writel(tmp, SLC_TAC(host->io_base));
}
@@ -660,7 +663,8 @@ static int lpc32xx_nand_read_page_raw_syndrome(struct mtd_info *mtd,
*/
static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf,
+ int oob_required, int page)
{
struct lpc32xx_nand_host *host = chip->priv;
uint8_t *pb = chip->oob_poi + chip->ecc.layout->eccpos[0];
@@ -689,7 +693,7 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
/* Raw writes can just use the FIFO interface */
chip->write_buf(mtd, buf, chip->ecc.size * chip->ecc.steps);
@@ -810,7 +814,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
res = -ENOENT;
goto err_exit1;
}
- clk_enable(host->clk);
+ clk_prepare_enable(host->clk);
/* Set NAND IO addresses and command/ready functions */
chip->IO_ADDR_R = SLC_DATA(host->io_base);
@@ -915,7 +919,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
err_exit3:
dma_release_channel(host->dma_chan);
err_exit2:
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
err_exit1:
lpc32xx_wp_enable(host);
@@ -939,7 +943,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
tmp &= ~SLCCFG_CE_LOW;
writel(tmp, SLC_CTRL(host->io_base));
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
lpc32xx_wp_enable(host);
return 0;
@@ -951,7 +955,7 @@ static int lpc32xx_nand_resume(struct platform_device *pdev)
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
/* Re-enable NAND clock */
- clk_enable(host->clk);
+ clk_prepare_enable(host->clk);
/* Fresh init of NAND controller */
lpc32xx_nand_setup(host);
@@ -976,7 +980,7 @@ static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
lpc32xx_wp_enable(host);
/* Disable clock */
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
return 0;
}
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 2a49b53c8db9..d6bbde4a5331 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -659,6 +659,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
chip = &prv->chip;
mtd->priv = chip;
+ mtd->dev.parent = dev;
chip->priv = prv;
prv->dev = dev;
@@ -841,6 +842,7 @@ static const struct of_device_id mpc5121_nfc_match[] = {
{ .compatible = "fsl,mpc5121-nfc", },
{},
};
+MODULE_DEVICE_TABLE(of, mpc5121_nfc_match);
static struct platform_driver mpc5121_nfc_driver = {
.probe = mpc5121_nfc_probe,
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index f04445b992f5..136e73a3e07e 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -1458,6 +1458,7 @@ static const struct of_device_id mxcnd_dt_ids[] = {
},
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, mxcnd_dt_ids);
static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
{
@@ -1516,7 +1517,6 @@ static int mxcnd_probe(struct platform_device *pdev)
this = &host->nand;
mtd = &host->mtd;
mtd->priv = this;
- mtd->owner = THIS_MODULE;
mtd->dev.parent = &pdev->dev;
mtd->name = DRIVER_NAME;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ceb68ca8277a..ece544efccc3 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -543,23 +543,32 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
}
}
-/* Wait for the ready pin, after a command. The timeout is caught later. */
+/**
+ * nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
+ * @mtd: MTD device structure
+ *
+ * Wait for the ready pin after a command, and warn if a timeout occurs.
+ */
void nand_wait_ready(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
- unsigned long timeo = jiffies + msecs_to_jiffies(20);
+ unsigned long timeo = 400;
- /* 400ms timeout */
if (in_interrupt() || oops_in_progress)
- return panic_nand_wait_ready(mtd, 400);
+ return panic_nand_wait_ready(mtd, timeo);
led_trigger_event(nand_led_trigger, LED_FULL);
/* Wait until command is processed or timeout occurs */
+ timeo = jiffies + msecs_to_jiffies(timeo);
do {
if (chip->dev_ready(mtd))
- break;
- touch_softlockup_watchdog();
+ goto out;
+ cond_resched();
} while (time_before(jiffies, timeo));
+
+ pr_warn_ratelimited(
+ "timeout while waiting for chip to become ready\n");
+out:
led_trigger_event(nand_led_trigger, LED_OFF);
}
EXPORT_SYMBOL_GPL(nand_wait_ready);
@@ -885,15 +894,13 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: MTD device structure
* @chip: NAND chip structure
*
- * Wait for command done. This applies to erase and program only. Erase can
- * take up to 400ms and program up to 20ms according to general NAND and
- * SmartMedia specs.
+ * Wait for command done. This applies to erase and program only.
*/
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
- int status, state = chip->state;
- unsigned long timeo = (state == FL_ERASING ? 400 : 20);
+ int status;
+ unsigned long timeo = 400;
led_trigger_event(nand_led_trigger, LED_FULL);
@@ -909,7 +916,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
panic_nand_wait(mtd, chip, timeo);
else {
timeo = jiffies + msecs_to_jiffies(timeo);
- while (time_before(jiffies, timeo)) {
+ do {
if (chip->dev_ready) {
if (chip->dev_ready(mtd))
break;
@@ -918,7 +925,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
break;
}
cond_resched();
- }
+ } while (time_before(jiffies, timeo));
}
led_trigger_event(nand_led_trigger, LED_OFF);
@@ -1101,6 +1108,134 @@ out:
EXPORT_SYMBOL(nand_lock);
/**
+ * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
+ * @buf: buffer to test
+ * @len: buffer length
+ * @bitflips_threshold: maximum number of bitflips
+ *
+ * Check if a buffer contains only 0xff, which means the underlying region
+ * has been erased and is ready to be programmed.
+ * The bitflips_threshold specify the maximum number of bitflips before
+ * considering the region is not erased.
+ * Note: The logic of this function has been extracted from the memweight
+ * implementation, except that nand_check_erased_buf function exit before
+ * testing the whole buffer if the number of bitflips exceed the
+ * bitflips_threshold value.
+ *
+ * Returns a positive number of bitflips less than or equal to
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
+ * threshold.
+ */
+static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold)
+{
+ const unsigned char *bitmap = buf;
+ int bitflips = 0;
+ int weight;
+
+ for (; len && ((uintptr_t)bitmap) % sizeof(long);
+ len--, bitmap++) {
+ weight = hweight8(*bitmap);
+ bitflips += BITS_PER_BYTE - weight;
+ if (unlikely(bitflips > bitflips_threshold))
+ return -EBADMSG;
+ }
+
+ for (; len >= sizeof(long);
+ len -= sizeof(long), bitmap += sizeof(long)) {
+ weight = hweight_long(*((unsigned long *)bitmap));
+ bitflips += BITS_PER_LONG - weight;
+ if (unlikely(bitflips > bitflips_threshold))
+ return -EBADMSG;
+ }
+
+ for (; len > 0; len--, bitmap++) {
+ weight = hweight8(*bitmap);
+ bitflips += BITS_PER_BYTE - weight;
+ if (unlikely(bitflips > bitflips_threshold))
+ return -EBADMSG;
+ }
+
+ return bitflips;
+}
+
+/**
+ * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only
+ * 0xff data
+ * @data: data buffer to test
+ * @datalen: data length
+ * @ecc: ECC buffer
+ * @ecclen: ECC length
+ * @extraoob: extra OOB buffer
+ * @extraooblen: extra OOB length
+ * @bitflips_threshold: maximum number of bitflips
+ *
+ * Check if a data buffer and its associated ECC and OOB data contains only
+ * 0xff pattern, which means the underlying region has been erased and is
+ * ready to be programmed.
+ * The bitflips_threshold specify the maximum number of bitflips before
+ * considering the region as not erased.
+ *
+ * Note:
+ * 1/ ECC algorithms are working on pre-defined block sizes which are usually
+ * different from the NAND page size. When fixing bitflips, ECC engines will
+ * report the number of errors per chunk, and the NAND core infrastructure
+ * expect you to return the maximum number of bitflips for the whole page.
+ * This is why you should always use this function on a single chunk and
+ * not on the whole page. After checking each chunk you should update your
+ * max_bitflips value accordingly.
+ * 2/ When checking for bitflips in erased pages you should not only check
+ * the payload data but also their associated ECC data, because a user might
+ * have programmed almost all bits to 1 but a few. In this case, we
+ * shouldn't consider the chunk as erased, and checking ECC bytes prevent
+ * this case.
+ * 3/ The extraoob argument is optional, and should be used if some of your OOB
+ * data are protected by the ECC engine.
+ * It could also be used if you support subpages and want to attach some
+ * extra OOB data to an ECC chunk.
+ *
+ * Returns a positive number of bitflips less than or equal to
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
+ * threshold. In case of success, the passed buffers are filled with 0xff.
+ */
+int nand_check_erased_ecc_chunk(void *data, int datalen,
+ void *ecc, int ecclen,
+ void *extraoob, int extraooblen,
+ int bitflips_threshold)
+{
+ int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0;
+
+ data_bitflips = nand_check_erased_buf(data, datalen,
+ bitflips_threshold);
+ if (data_bitflips < 0)
+ return data_bitflips;
+
+ bitflips_threshold -= data_bitflips;
+
+ ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold);
+ if (ecc_bitflips < 0)
+ return ecc_bitflips;
+
+ bitflips_threshold -= ecc_bitflips;
+
+ extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen,
+ bitflips_threshold);
+ if (extraoob_bitflips < 0)
+ return extraoob_bitflips;
+
+ if (data_bitflips)
+ memset(data, 0xff, datalen);
+
+ if (ecc_bitflips)
+ memset(ecc, 0xff, ecclen);
+
+ if (extraoob_bitflips)
+ memset(extraoob, 0xff, extraooblen);
+
+ return data_bitflips + ecc_bitflips + extraoob_bitflips;
+}
+EXPORT_SYMBOL(nand_check_erased_ecc_chunk);
+
+/**
* nand_read_page_raw - [INTERN] read raw page data without ecc
* @mtd: mtd info structure
* @chip: nand chip info structure
@@ -2027,11 +2162,12 @@ out:
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*
* Not for syndrome calculating ECC controllers, which use a special oob layout.
*/
static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
if (oob_required)
@@ -2046,12 +2182,14 @@ static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*
* We need a special oob layout and handling even when ECC isn't checked.
*/
static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2088,9 +2226,11 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*/
static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2106,7 +2246,7 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
for (i = 0; i < chip->ecc.total; i++)
chip->oob_poi[eccpos[i]] = ecc_calc[i];
- return chip->ecc.write_page_raw(mtd, chip, buf, 1);
+ return chip->ecc.write_page_raw(mtd, chip, buf, 1, page);
}
/**
@@ -2115,9 +2255,11 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*/
static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2149,11 +2291,12 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @data_len: data length
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*/
static int nand_write_subpage_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint32_t offset,
uint32_t data_len, const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
uint8_t *oob_buf = chip->oob_poi;
uint8_t *ecc_calc = chip->buffers->ecccalc;
@@ -2208,13 +2351,15 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*
* The hw generator calculates the error syndrome automatically. Therefore we
* need a special oob layout and handling.
*/
static int nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2278,12 +2423,13 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
if (unlikely(raw))
status = chip->ecc.write_page_raw(mtd, chip, buf,
- oob_required);
+ oob_required, page);
else if (subpage)
status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
- buf, oob_required);
+ buf, oob_required, page);
else
- status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+ status = chip->ecc.write_page(mtd, chip, buf, oob_required,
+ page);
if (status < 0)
return status;
@@ -2964,7 +3110,7 @@ static void nand_resume(struct mtd_info *mtd)
*/
static void nand_shutdown(struct mtd_info *mtd)
{
- nand_get_device(mtd, FL_SHUTDOWN);
+ nand_get_device(mtd, FL_PM_SUSPENDED);
}
/* Set default functions */
@@ -3708,10 +3854,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->chipsize = (uint64_t)type->chipsize << 20;
- if (!type->pagesize && chip->init_size) {
- /* Set the pagesize, oobsize, erasesize by the driver */
- busw = chip->init_size(mtd, chip, id_data);
- } else if (!type->pagesize) {
+ if (!type->pagesize) {
/* Decode parameters from extended ID */
nand_decode_ext_id(mtd, chip, id_data, &busw);
} else {
@@ -3846,8 +3989,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
struct nand_flash_dev *type;
int ret;
- if (chip->dn) {
- ret = nand_dt_init(mtd, chip, chip->dn);
+ if (chip->flash_node) {
+ ret = nand_dt_init(mtd, chip, chip->flash_node);
if (ret)
return ret;
}
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 63a1a36a3f4b..b1d4f813aedc 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1080,7 +1080,7 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
struct nand_bbt_descr *td = this->bbt_td;
struct nand_bbt_descr *md = this->bbt_md;
- len = mtd->size >> (this->bbt_erase_shift + 2);
+ len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1;
/*
* Allocate memory (2bit per block) and clear the memory bad block
* table.
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 95d0cc49cfc2..b16d70aafd9e 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -649,8 +649,7 @@ static void free_device(struct nandsim *ns)
kmem_cache_free(ns->nand_pages_slab,
ns->pages[i].byte);
}
- if (ns->nand_pages_slab)
- kmem_cache_destroy(ns->nand_pages_slab);
+ kmem_cache_destroy(ns->nand_pages_slab);
vfree(ns->pages);
}
}
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 67a1b3f911cf..4f0d62f9d22c 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -169,7 +169,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
chip->priv = ndfc;
ndfc->mtd.priv = chip;
- ndfc->mtd.owner = THIS_MODULE;
+ ndfc->mtd.dev.parent = &ndfc->ofdev->dev;
flash_np = of_get_next_child(node, NULL);
if (!flash_np)
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index e58c644dd220..f0687f71fbd8 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -250,7 +250,7 @@ static int nuc900_nand_probe(struct platform_device *pdev)
chip = &(nuc900_nand->chip);
nuc900_nand->mtd.priv = chip;
- nuc900_nand->mtd.owner = THIS_MODULE;
+ nuc900_nand->mtd.dev.parent = &pdev->dev;
spin_lock_init(&nuc900_nand->lock);
nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 60fa89939c24..93f664cd1c90 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1500,11 +1500,12 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page
*
* Custom write page method evolved to support multi sector writing in one shot
*/
static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
int i;
uint8_t *ecc_calc = chip->buffers->ecccalc;
@@ -1684,8 +1685,7 @@ static int omap_nand_probe(struct platform_device *pdev)
info->ecc_opt = pdata->ecc_opt;
mtd = &info->mtd;
mtd->priv = &info->nand;
- mtd->name = dev_name(&pdev->dev);
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
nand_chip = &info->nand;
nand_chip->ecc.priv = NULL;
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index c3c6d305caa7..ee83749fb1d3 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -124,7 +124,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
}
mtd->priv = nc;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
nc->priv = board;
nc->IO_ADDR_R = nc->IO_ADDR_W = io_base;
@@ -201,6 +201,7 @@ static const struct of_device_id orion_nand_of_match_table[] = {
{ .compatible = "marvell,orion-nand", },
{},
};
+MODULE_DEVICE_TABLE(of, orion_nand_of_match_table);
#endif
static struct platform_driver orion_nand_driver = {
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 66c345b42097..83cf021b9651 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -124,7 +124,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
/* Link the private data with the MTD structure */
pasemi_nand_mtd->priv = chip;
- pasemi_nand_mtd->owner = THIS_MODULE;
+ pasemi_nand_mtd->dev.parent = &ofdev->dev;
chip->IO_ADDR_R = of_iomap(np, 0);
chip->IO_ADDR_W = chip->IO_ADDR_R;
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 717cf623fcde..65b9dbbe6d6a 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -59,8 +59,7 @@ static int plat_nand_probe(struct platform_device *pdev)
data->chip.priv = &data;
data->mtd.priv = &data->chip;
- data->mtd.owner = THIS_MODULE;
- data->mtd.name = dev_name(&pdev->dev);
+ data->mtd.dev.parent = &pdev->dev;
data->chip.IO_ADDR_R = data->io_base;
data->chip.IO_ADDR_W = data->io_base;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 740983a34626..e453ae9a17fa 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -15,7 +15,9 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
+#include <linux/dma/pxa-dma.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/mtd/mtd.h>
@@ -33,10 +35,6 @@
#define ARCH_HAS_DMA
#endif
-#ifdef ARCH_HAS_DMA
-#include <mach/dma.h>
-#endif
-
#include <linux/platform_data/mtd-nand-pxa3xx.h>
#define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200)
@@ -78,7 +76,8 @@
#define NDCR_ND_MODE (0x3 << 21)
#define NDCR_NAND_MODE (0x0)
#define NDCR_CLR_PG_CNT (0x1 << 20)
-#define NDCR_STOP_ON_UNCOR (0x1 << 19)
+#define NFCV1_NDCR_ARB_CNTL (0x1 << 19)
+#define NFCV2_NDCR_STOP_ON_UNCOR (0x1 << 19)
#define NDCR_RD_ID_CNT_MASK (0x7 << 16)
#define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK)
@@ -201,6 +200,10 @@ struct pxa3xx_nand_info {
unsigned int oob_buff_pos;
/* DMA information */
+ struct scatterlist sg;
+ enum dma_data_direction dma_dir;
+ struct dma_chan *dma_chan;
+ dma_cookie_t dma_cookie;
int drcmr_dat;
int drcmr_cmd;
@@ -208,8 +211,6 @@ struct pxa3xx_nand_info {
unsigned char *oob_buff;
dma_addr_t data_buff_phys;
int data_dma_ch;
- struct pxa_dma_desc *data_desc;
- dma_addr_t data_desc_addr;
struct pxa3xx_nand_host *host[NUM_CHIP_SELECT];
unsigned int state;
@@ -252,6 +253,25 @@ static bool use_dma = 1;
module_param(use_dma, bool, 0444);
MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW");
+struct pxa3xx_nand_timing {
+ unsigned int tCH; /* Enable signal hold time */
+ unsigned int tCS; /* Enable signal setup time */
+ unsigned int tWH; /* ND_nWE high duration */
+ unsigned int tWP; /* ND_nWE pulse time */
+ unsigned int tRH; /* ND_nRE high duration */
+ unsigned int tRP; /* ND_nRE pulse width */
+ unsigned int tR; /* ND_nWE high to ND_nRE low for read */
+ unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */
+ unsigned int tAR; /* ND_ALE low to ND_nRE low delay */
+};
+
+struct pxa3xx_nand_flash {
+ uint32_t chip_id;
+ unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */
+ unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */
+ struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
+};
+
static struct pxa3xx_nand_timing timing[] = {
{ 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
{ 10, 0, 20, 40, 30, 40, 11123, 110, 10, },
@@ -260,15 +280,14 @@ static struct pxa3xx_nand_timing timing[] = {
};
static struct pxa3xx_nand_flash builtin_flash_types[] = {
-{ "DEFAULT FLASH", 0, 0, 2048, 8, 8, 0, &timing[0] },
-{ "64MiB 16-bit", 0x46ec, 32, 512, 16, 16, 4096, &timing[1] },
-{ "256MiB 8-bit", 0xdaec, 64, 2048, 8, 8, 2048, &timing[1] },
-{ "4GiB 8-bit", 0xd7ec, 128, 4096, 8, 8, 8192, &timing[1] },
-{ "128MiB 8-bit", 0xa12c, 64, 2048, 8, 8, 1024, &timing[2] },
-{ "128MiB 16-bit", 0xb12c, 64, 2048, 16, 16, 1024, &timing[2] },
-{ "512MiB 8-bit", 0xdc2c, 64, 2048, 8, 8, 4096, &timing[2] },
-{ "512MiB 16-bit", 0xcc2c, 64, 2048, 16, 16, 4096, &timing[2] },
-{ "256MiB 16-bit", 0xba20, 64, 2048, 16, 16, 2048, &timing[3] },
+ { 0x46ec, 16, 16, &timing[1] },
+ { 0xdaec, 8, 8, &timing[1] },
+ { 0xd7ec, 8, 8, &timing[1] },
+ { 0xa12c, 8, 8, &timing[2] },
+ { 0xb12c, 16, 16, &timing[2] },
+ { 0xdc2c, 8, 8, &timing[2] },
+ { 0xcc2c, 16, 16, &timing[2] },
+ { 0xba20, 16, 16, &timing[3] },
};
static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
@@ -329,9 +348,6 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
.oobfree = { }
};
-/* Define a default flash type setting serve as flash detecting only */
-#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
-
#define NDTR0_tCH(c) (min((c), 7) << 19)
#define NDTR0_tCS(c) (min((c), 7) << 16)
#define NDTR0_tWH(c) (min((c), 7) << 11)
@@ -393,6 +409,128 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
nand_writel(info, NDTR1CS0, ndtr1);
}
+static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
+ const struct nand_sdr_timings *t)
+{
+ struct pxa3xx_nand_info *info = host->info_data;
+ struct nand_chip *chip = &host->chip;
+ unsigned long nand_clk = clk_get_rate(info->clk);
+ uint32_t ndtr0, ndtr1;
+
+ u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
+ u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
+ u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
+ u32 tWP_min = DIV_ROUND_UP(t->tWC_min - t->tWH_min, 1000);
+ u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
+ u32 tRP_min = DIV_ROUND_UP(t->tRC_min - t->tREH_min, 1000);
+ u32 tR = chip->chip_delay * 1000;
+ u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
+ u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
+
+ /* fallback to a default value if tR = 0 */
+ if (!tR)
+ tR = 20000;
+
+ ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
+ NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
+ NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
+ NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
+ NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
+ NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
+
+ ndtr1 = NDTR1_tR(ns2cycle(tR, nand_clk)) |
+ NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
+ NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
+
+ info->ndtr0cs0 = ndtr0;
+ info->ndtr1cs0 = ndtr1;
+ nand_writel(info, NDTR0CS0, ndtr0);
+ nand_writel(info, NDTR1CS0, ndtr1);
+}
+
+static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host,
+ unsigned int *flash_width,
+ unsigned int *dfc_width)
+{
+ struct nand_chip *chip = &host->chip;
+ struct pxa3xx_nand_info *info = host->info_data;
+ const struct pxa3xx_nand_flash *f = NULL;
+ int i, id, ntypes;
+
+ ntypes = ARRAY_SIZE(builtin_flash_types);
+
+ chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
+
+ id = chip->read_byte(host->mtd);
+ id |= chip->read_byte(host->mtd) << 0x8;
+
+ for (i = 0; i < ntypes; i++) {
+ f = &builtin_flash_types[i];
+
+ if (f->chip_id == id)
+ break;
+ }
+
+ if (i == ntypes) {
+ dev_err(&info->pdev->dev, "Error: timings not found\n");
+ return -EINVAL;
+ }
+
+ pxa3xx_nand_set_timing(host, f->timing);
+
+ *flash_width = f->flash_width;
+ *dfc_width = f->dfc_width;
+
+ return 0;
+}
+
+static int pxa3xx_nand_init_timings_onfi(struct pxa3xx_nand_host *host,
+ int mode)
+{
+ const struct nand_sdr_timings *timings;
+
+ mode = fls(mode) - 1;
+ if (mode < 0)
+ mode = 0;
+
+ timings = onfi_async_timing_mode_to_sdr_timings(mode);
+ if (IS_ERR(timings))
+ return PTR_ERR(timings);
+
+ pxa3xx_nand_set_sdr_timing(host, timings);
+
+ return 0;
+}
+
+static int pxa3xx_nand_init(struct pxa3xx_nand_host *host)
+{
+ struct nand_chip *chip = &host->chip;
+ struct pxa3xx_nand_info *info = host->info_data;
+ unsigned int flash_width = 0, dfc_width = 0;
+ int mode, err;
+
+ mode = onfi_get_async_timing_mode(chip);
+ if (mode == ONFI_TIMING_MODE_UNKNOWN) {
+ err = pxa3xx_nand_init_timings_compat(host, &flash_width,
+ &dfc_width);
+ if (err)
+ return err;
+
+ if (flash_width == 16) {
+ info->reg_ndcr |= NDCR_DWIDTH_M;
+ chip->options |= NAND_BUSWIDTH_16;
+ }
+
+ info->reg_ndcr |= (dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+ } else {
+ err = pxa3xx_nand_init_timings_onfi(host, mode);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
/*
* Set the data and OOB size, depending on the selected
* spare and ECC configuration.
@@ -468,6 +606,9 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
ndcr &= ~NDCR_ND_RUN;
nand_writel(info, NDCR, ndcr);
}
+ if (info->dma_chan)
+ dmaengine_terminate_all(info->dma_chan);
+
/* clear status bits */
nand_writel(info, NDSR, NDSR_MASK);
}
@@ -504,7 +645,7 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
* the polling on the last read.
*/
while (len > 8) {
- readsl(info->mmio_base + NDDB, data, 8);
+ ioread32_rep(info->mmio_base + NDDB, data, 8);
ret = readl_relaxed_poll_timeout(info->mmio_base + NDSR, val,
val & NDSR_RDDREQ, 1000, 5000);
@@ -519,7 +660,7 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
}
}
- readsl(info->mmio_base + NDDB, data, len);
+ ioread32_rep(info->mmio_base + NDDB, data, len);
}
static void handle_data_pio(struct pxa3xx_nand_info *info)
@@ -559,57 +700,61 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
info->data_size -= do_bytes;
}
-#ifdef ARCH_HAS_DMA
-static void start_data_dma(struct pxa3xx_nand_info *info)
+static void pxa3xx_nand_data_dma_irq(void *data)
{
- struct pxa_dma_desc *desc = info->data_desc;
- int dma_len = ALIGN(info->data_size + info->oob_size, 32);
+ struct pxa3xx_nand_info *info = data;
+ struct dma_tx_state state;
+ enum dma_status status;
- desc->ddadr = DDADR_STOP;
- desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
+ status = dmaengine_tx_status(info->dma_chan, info->dma_cookie, &state);
+ if (likely(status == DMA_COMPLETE)) {
+ info->state = STATE_DMA_DONE;
+ } else {
+ dev_err(&info->pdev->dev, "DMA error on data channel\n");
+ info->retcode = ERR_DMABUSERR;
+ }
+ dma_unmap_sg(info->dma_chan->device->dev, &info->sg, 1, info->dma_dir);
+
+ nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+ enable_int(info, NDCR_INT_MASK);
+}
+
+static void start_data_dma(struct pxa3xx_nand_info *info)
+{
+ enum dma_transfer_direction direction;
+ struct dma_async_tx_descriptor *tx;
switch (info->state) {
case STATE_DMA_WRITING:
- desc->dsadr = info->data_buff_phys;
- desc->dtadr = info->mmio_phys + NDDB;
- desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
+ info->dma_dir = DMA_TO_DEVICE;
+ direction = DMA_MEM_TO_DEV;
break;
case STATE_DMA_READING:
- desc->dtadr = info->data_buff_phys;
- desc->dsadr = info->mmio_phys + NDDB;
- desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+ info->dma_dir = DMA_FROM_DEVICE;
+ direction = DMA_DEV_TO_MEM;
break;
default:
dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
info->state);
BUG();
}
-
- DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
- DDADR(info->data_dma_ch) = info->data_desc_addr;
- DCSR(info->data_dma_ch) |= DCSR_RUN;
-}
-
-static void pxa3xx_nand_data_dma_irq(int channel, void *data)
-{
- struct pxa3xx_nand_info *info = data;
- uint32_t dcsr;
-
- dcsr = DCSR(channel);
- DCSR(channel) = dcsr;
-
- if (dcsr & DCSR_BUSERR) {
- info->retcode = ERR_DMABUSERR;
+ info->sg.length = info->data_size +
+ (info->oob_size ? info->spare_size + info->ecc_size : 0);
+ dma_map_sg(info->dma_chan->device->dev, &info->sg, 1, info->dma_dir);
+
+ tx = dmaengine_prep_slave_sg(info->dma_chan, &info->sg, 1, direction,
+ DMA_PREP_INTERRUPT);
+ if (!tx) {
+ dev_err(&info->pdev->dev, "prep_slave_sg() failed\n");
+ return;
}
-
- info->state = STATE_DMA_DONE;
- enable_int(info, NDCR_INT_MASK);
- nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+ tx->callback = pxa3xx_nand_data_dma_irq;
+ tx->callback_param = info;
+ info->dma_cookie = dmaengine_submit(tx);
+ dma_async_issue_pending(info->dma_chan);
+ dev_dbg(&info->pdev->dev, "%s(dir=%d cookie=%x size=%u)\n",
+ __func__, direction, info->dma_cookie, info->sg.length);
}
-#else
-static void start_data_dma(struct pxa3xx_nand_info *info)
-{}
-#endif
static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data)
{
@@ -1128,7 +1273,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
}
static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1241,45 +1387,23 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
return NAND_STATUS_READY;
}
-static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
- const struct pxa3xx_nand_flash *f)
+static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
{
struct platform_device *pdev = info->pdev;
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct pxa3xx_nand_host *host = info->host[info->cs];
- uint32_t ndcr = 0x0; /* enable all interrupts */
-
- if (f->page_size != 2048 && f->page_size != 512) {
- dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
- return -EINVAL;
- }
-
- if (f->flash_width != 16 && f->flash_width != 8) {
- dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
- return -EINVAL;
- }
-
- /* calculate addressing information */
- host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
-
- if (f->num_blocks * f->page_per_block > 65536)
- host->row_addr_cycles = 3;
- else
- host->row_addr_cycles = 2;
-
- ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
- ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
- ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
- ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
- ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
- ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
-
- ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
- ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+ struct mtd_info *mtd = host->mtd;
+ struct nand_chip *chip = mtd->priv;
- info->reg_ndcr = ndcr;
+ /* configure default flash values */
+ info->reg_ndcr = 0x0; /* enable all interrupts */
+ info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
+ info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
+ info->reg_ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+ info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+ info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
+ info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
- pxa3xx_nand_set_timing(host, f->timing);
return 0;
}
@@ -1289,42 +1413,57 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
/* Set an initial chunk size */
info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
- info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+ info->reg_ndcr = ndcr &
+ ~(NDCR_INT_MASK | NDCR_ND_ARB_EN | NFCV1_NDCR_ARB_CNTL);
info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
return 0;
}
-#ifdef ARCH_HAS_DMA
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{
struct platform_device *pdev = info->pdev;
- int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
+ struct dma_slave_config config;
+ dma_cap_mask_t mask;
+ struct pxad_param param;
+ int ret;
- if (use_dma == 0) {
- info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
- if (info->data_buff == NULL)
- return -ENOMEM;
+ info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
+ if (info->data_buff == NULL)
+ return -ENOMEM;
+ if (use_dma == 0)
return 0;
- }
- info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
- &info->data_buff_phys, GFP_KERNEL);
- if (info->data_buff == NULL) {
- dev_err(&pdev->dev, "failed to allocate dma buffer\n");
- return -ENOMEM;
- }
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
- info->data_desc = (void *)info->data_buff + data_desc_offset;
- info->data_desc_addr = info->data_buff_phys + data_desc_offset;
+ sg_init_one(&info->sg, info->data_buff, info->buf_size);
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ param.prio = PXAD_PRIO_LOWEST;
+ param.drcmr = info->drcmr_dat;
+ info->dma_chan = dma_request_slave_channel_compat(mask, pxad_filter_fn,
+ &param, &pdev->dev,
+ "data");
+ if (!info->dma_chan) {
+ dev_err(&pdev->dev, "unable to request data dma channel\n");
+ return -ENODEV;
+ }
- info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
- pxa3xx_nand_data_dma_irq, info);
- if (info->data_dma_ch < 0) {
- dev_err(&pdev->dev, "failed to request data dma\n");
- dma_free_coherent(&pdev->dev, info->buf_size,
- info->data_buff, info->data_buff_phys);
- return info->data_dma_ch;
+ memset(&config, 0, sizeof(config));
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ config.src_addr = info->mmio_phys + NDDB;
+ config.dst_addr = info->mmio_phys + NDDB;
+ config.src_maxburst = 32;
+ config.dst_maxburst = 32;
+ ret = dmaengine_slave_config(info->dma_chan, &config);
+ if (ret < 0) {
+ dev_err(&info->pdev->dev,
+ "dma channel configuration failed: %d\n",
+ ret);
+ return ret;
}
/*
@@ -1337,43 +1476,30 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
{
- struct platform_device *pdev = info->pdev;
if (info->use_dma) {
- pxa_free_dma(info->data_dma_ch);
- dma_free_coherent(&pdev->dev, info->buf_size,
- info->data_buff, info->data_buff_phys);
- } else {
- kfree(info->data_buff);
+ dmaengine_terminate_all(info->dma_chan);
+ dma_release_channel(info->dma_chan);
}
-}
-#else
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
-{
- info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
- if (info->data_buff == NULL)
- return -ENOMEM;
- return 0;
-}
-
-static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
-{
kfree(info->data_buff);
}
-#endif
-static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
{
+ struct pxa3xx_nand_info *info = host->info_data;
struct mtd_info *mtd;
struct nand_chip *chip;
+ const struct nand_sdr_timings *timings;
int ret;
mtd = info->host[info->cs]->mtd;
chip = mtd->priv;
/* use the common timing to make a try */
- ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
- if (ret)
- return ret;
+ timings = onfi_async_timing_mode_to_sdr_timings(0);
+ if (IS_ERR(timings))
+ return PTR_ERR(timings);
+
+ pxa3xx_nand_set_sdr_timing(host, timings);
chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
ret = chip->waitfunc(mtd, chip);
@@ -1458,12 +1584,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
struct pxa3xx_nand_info *info = host->info_data;
struct platform_device *pdev = info->pdev;
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
- const struct pxa3xx_nand_flash *f = NULL;
struct nand_chip *chip = mtd->priv;
- uint32_t id = -1;
- uint64_t chipsize;
- int i, ret, num;
+ int ret;
uint16_t ecc_strength, ecc_step;
if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
@@ -1472,7 +1594,11 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
/* Set a default chunk size */
info->chunk_size = 512;
- ret = pxa3xx_nand_sensing(info);
+ ret = pxa3xx_nand_config_flash(info);
+ if (ret)
+ return ret;
+
+ ret = pxa3xx_nand_sensing(host);
if (ret) {
dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
info->cs);
@@ -1480,54 +1606,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
return ret;
}
- chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
- id = *((uint16_t *)(info->data_buff));
- if (id != 0)
- dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
- else {
- dev_warn(&info->pdev->dev,
- "Read out ID 0, potential timing set wrong!!\n");
-
- return -EINVAL;
- }
-
- num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
- for (i = 0; i < num; i++) {
- if (i < pdata->num_flash)
- f = pdata->flash + i;
- else
- f = &builtin_flash_types[i - pdata->num_flash + 1];
-
- /* find the chip in default list */
- if (f->chip_id == id)
- break;
- }
-
- if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
- dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
-
- return -EINVAL;
- }
-
- ret = pxa3xx_nand_config_flash(info, f);
- if (ret) {
- dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
- return ret;
- }
-
- memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids));
-
- pxa3xx_flash_ids[0].name = f->name;
- pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
- pxa3xx_flash_ids[0].pagesize = f->page_size;
- chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
- pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
- pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
- if (f->flash_width == 16)
- pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
- pxa3xx_flash_ids[1].name = NULL;
- def = pxa3xx_flash_ids;
KEEP_CONFIG:
+ info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
if (info->reg_ndcr & NDCR_DWIDTH_M)
chip->options |= NAND_BUSWIDTH_16;
@@ -1535,9 +1615,18 @@ KEEP_CONFIG:
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
nand_writel(info, NDECCCTRL, 0x0);
- if (nand_scan_ident(mtd, 1, def))
+ if (nand_scan_ident(mtd, 1, NULL))
return -ENODEV;
+ if (!pdata->keep_config) {
+ ret = pxa3xx_nand_init(host);
+ if (ret) {
+ dev_err(&info->pdev->dev, "Failed to init nand: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
if (pdata->flash_bbt) {
/*
* We'll use a bad block table stored in-flash and don't
@@ -1635,7 +1724,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
host->cs = cs;
host->info_data = info;
mtd->priv = host;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &pdev->dev;
chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
chip->ecc.write_page = pxa3xx_nand_write_page_hwecc;
@@ -1662,34 +1751,23 @@ static int alloc_nand_resource(struct platform_device *pdev)
return ret;
if (use_dma) {
- /*
- * This is a dirty hack to make this driver work from
- * devicetree bindings. It can be removed once we have
- * a prober DMA controller framework for DT.
- */
- if (pdev->dev.of_node &&
- of_machine_is_compatible("marvell,pxa3xx")) {
- info->drcmr_dat = 97;
- info->drcmr_cmd = 99;
- } else {
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (r == NULL) {
- dev_err(&pdev->dev,
- "no resource defined for data DMA\n");
- ret = -ENXIO;
- goto fail_disable_clk;
- }
- info->drcmr_dat = r->start;
-
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (r == NULL) {
- dev_err(&pdev->dev,
- "no resource defined for cmd DMA\n");
- ret = -ENXIO;
- goto fail_disable_clk;
- }
- info->drcmr_cmd = r->start;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (r == NULL) {
+ dev_err(&pdev->dev,
+ "no resource defined for data DMA\n");
+ ret = -ENXIO;
+ goto fail_disable_clk;
+ }
+ info->drcmr_dat = r->start;
+
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (r == NULL) {
+ dev_err(&pdev->dev,
+ "no resource defined for cmd DMA\n");
+ ret = -ENXIO;
+ goto fail_disable_clk;
}
+ info->drcmr_cmd = r->start;
}
irq = platform_get_irq(pdev, 0);
@@ -1754,6 +1832,16 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
free_irq(irq, info);
pxa3xx_nand_free_buff(info);
+ /*
+ * In the pxa3xx case, the DFI bus is shared between the SMC and NFC.
+ * In order to prevent a lockup of the system bus, the DFI bus
+ * arbitration is granted to SMC upon driver removal. This is done by
+ * setting the x_ARB_CNTL bit, which also prevents the NAND to have
+ * access to the bus anymore.
+ */
+ nand_writel(info, NDCR,
+ (nand_readl(info, NDCR) & ~NDCR_ND_ARB_EN) |
+ NFCV1_NDCR_ARB_CNTL);
clk_disable_unprepare(info->clk);
for (cs = 0; cs < pdata->num_cs; cs++)
@@ -1800,15 +1888,16 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
struct pxa3xx_nand_platform_data *pdata;
struct mtd_part_parser_data ppdata = {};
struct pxa3xx_nand_info *info;
- int ret, cs, probe_success;
+ int ret, cs, probe_success, dma_available;
-#ifndef ARCH_HAS_DMA
- if (use_dma) {
+ dma_available = IS_ENABLED(CONFIG_ARM) &&
+ (IS_ENABLED(CONFIG_ARCH_PXA) || IS_ENABLED(CONFIG_ARCH_MMP));
+ if (use_dma && !dma_available) {
use_dma = 0;
dev_warn(&pdev->dev,
"This platform can't do DMA on this device\n");
}
-#endif
+
ret = pxa3xx_nand_probe_dt(pdev);
if (ret)
return ret;
@@ -1861,35 +1950,22 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
+static int pxa3xx_nand_suspend(struct device *dev)
{
- struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
- struct pxa3xx_nand_platform_data *pdata;
- struct mtd_info *mtd;
- int cs;
+ struct pxa3xx_nand_info *info = dev_get_drvdata(dev);
- pdata = dev_get_platdata(&pdev->dev);
if (info->state) {
- dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
+ dev_err(dev, "driver busy, state = %d\n", info->state);
return -EAGAIN;
}
- for (cs = 0; cs < pdata->num_cs; cs++) {
- mtd = info->host[cs]->mtd;
- mtd_suspend(mtd);
- }
-
return 0;
}
-static int pxa3xx_nand_resume(struct platform_device *pdev)
+static int pxa3xx_nand_resume(struct device *dev)
{
- struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
- struct pxa3xx_nand_platform_data *pdata;
- struct mtd_info *mtd;
- int cs;
+ struct pxa3xx_nand_info *info = dev_get_drvdata(dev);
- pdata = dev_get_platdata(&pdev->dev);
/* We don't want to handle interrupt without calling mtd routine */
disable_int(info, NDCR_INT_MASK);
@@ -1907,10 +1983,6 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
* all status before resume
*/
nand_writel(info, NDSR, NDSR_MASK);
- for (cs = 0; cs < pdata->num_cs; cs++) {
- mtd = info->host[cs]->mtd;
- mtd_resume(mtd);
- }
return 0;
}
@@ -1919,15 +1991,19 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
#define pxa3xx_nand_resume NULL
#endif
+static const struct dev_pm_ops pxa3xx_nand_pm_ops = {
+ .suspend = pxa3xx_nand_suspend,
+ .resume = pxa3xx_nand_resume,
+};
+
static struct platform_driver pxa3xx_nand_driver = {
.driver = {
.name = "pxa3xx-nand",
.of_match_table = pxa3xx_nand_dt_ids,
+ .pm = &pxa3xx_nand_pm_ops,
},
.probe = pxa3xx_nand_probe,
.remove = pxa3xx_nand_remove,
- .suspend = pxa3xx_nand_suspend,
- .resume = pxa3xx_nand_resume,
};
module_platform_driver(pxa3xx_nand_driver);
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index cc6bac537f5a..d8bb2be327f1 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -641,7 +641,6 @@ static int r852_register_nand_device(struct r852_device *dev)
WARN_ON(dev->card_registred);
- dev->mtd->owner = THIS_MODULE;
dev->mtd->priv = dev->chip;
dev->mtd->dev.parent = &dev->pci_dev->dev;
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 381f67ac6b5a..05105cadd0db 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -832,7 +832,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
nmtd->info = info;
nmtd->mtd.priv = chip;
- nmtd->mtd.owner = THIS_MODULE;
nmtd->set = set;
#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
@@ -1016,6 +1015,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
pr_debug("initialising set %d (%p, info %p)\n",
setno, nmtd, info);
+ nmtd->mtd.dev.parent = &pdev->dev;
s3c2410_nand_init_chip(info, nmtd, sets);
nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index c3ce81c1a716..bcba1a924c75 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -569,7 +569,8 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
}
static int flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1123,6 +1124,7 @@ static int flctl_probe(struct platform_device *pdev)
flctl_mtd = &flctl->mtd;
nand = &flctl->chip;
flctl_mtd->priv = nand;
+ flctl_mtd->dev.parent = &pdev->dev;
flctl->pdev = pdev;
flctl->hwecc = pdata->has_hwecc;
flctl->holden = pdata->use_holden;
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 842c47a451a0..082b6009736d 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -144,7 +144,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
/* Link the private data with the MTD structure */
sharpsl->mtd.priv = this;
- sharpsl->mtd.owner = THIS_MODULE;
+ sharpsl->mtd.dev.parent = &pdev->dev;
platform_set_drvdata(pdev, sharpsl);
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index d71062273f55..b94f53427f0f 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -167,7 +167,6 @@ static int socrates_nand_probe(struct platform_device *ofdev)
nand_chip->priv = host; /* link the private data structures */
mtd->priv = nand_chip;
mtd->name = "socrates_nand";
- mtd->owner = THIS_MODULE;
mtd->dev.parent = &ofdev->dev;
ppdata.of_node = ofdev->dev.of_node;
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index e7d333c162be..824711845c44 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -57,11 +57,8 @@
#define NFC_REG_ECC_CTL 0x0034
#define NFC_REG_ECC_ST 0x0038
#define NFC_REG_DEBUG 0x003C
-#define NFC_REG_ECC_CNT0 0x0040
-#define NFC_REG_ECC_CNT1 0x0044
-#define NFC_REG_ECC_CNT2 0x0048
-#define NFC_REG_ECC_CNT3 0x004c
-#define NFC_REG_USER_DATA_BASE 0x0050
+#define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3)
+#define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4))
#define NFC_REG_SPARE_AREA 0x00A0
#define NFC_RAM0_BASE 0x0400
#define NFC_RAM1_BASE 0x0800
@@ -69,12 +66,16 @@
/* define bit use in NFC_CTL */
#define NFC_EN BIT(0)
#define NFC_RESET BIT(1)
-#define NFC_BUS_WIDYH BIT(2)
-#define NFC_RB_SEL BIT(3)
-#define NFC_CE_SEL GENMASK(26, 24)
+#define NFC_BUS_WIDTH_MSK BIT(2)
+#define NFC_BUS_WIDTH_8 (0 << 2)
+#define NFC_BUS_WIDTH_16 (1 << 2)
+#define NFC_RB_SEL_MSK BIT(3)
+#define NFC_RB_SEL(x) ((x) << 3)
+#define NFC_CE_SEL_MSK GENMASK(26, 24)
+#define NFC_CE_SEL(x) ((x) << 24)
#define NFC_CE_CTL BIT(6)
-#define NFC_CE_CTL1 BIT(7)
-#define NFC_PAGE_SIZE GENMASK(11, 8)
+#define NFC_PAGE_SHIFT_MSK GENMASK(11, 8)
+#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
#define NFC_SAM BIT(12)
#define NFC_RAM_METHOD BIT(14)
#define NFC_DEBUG_CTL BIT(31)
@@ -86,10 +87,7 @@
#define NFC_CMD_FIFO_STATUS BIT(3)
#define NFC_STA BIT(4)
#define NFC_NATCH_INT_FLAG BIT(5)
-#define NFC_RB_STATE0 BIT(8)
-#define NFC_RB_STATE1 BIT(9)
-#define NFC_RB_STATE2 BIT(10)
-#define NFC_RB_STATE3 BIT(11)
+#define NFC_RB_STATE(x) BIT(x + 8)
/* define bit use in NFC_INT */
#define NFC_B2R_INT_ENABLE BIT(0)
@@ -109,9 +107,11 @@
(((tCAD) & 0x7) << 8))
/* define bit use in NFC_CMD */
-#define NFC_CMD_LOW_BYTE GENMASK(7, 0)
-#define NFC_CMD_HIGH_BYTE GENMASK(15, 8)
-#define NFC_ADR_NUM GENMASK(18, 16)
+#define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0)
+#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8)
+#define NFC_CMD(x) (x)
+#define NFC_ADR_NUM_MSK GENMASK(18, 16)
+#define NFC_ADR_NUM(x) (((x) - 1) << 16)
#define NFC_SEND_ADR BIT(19)
#define NFC_ACCESS_DIR BIT(20)
#define NFC_DATA_TRANS BIT(21)
@@ -123,33 +123,38 @@
#define NFC_ROW_AUTO_INC BIT(27)
#define NFC_SEND_CMD3 BIT(28)
#define NFC_SEND_CMD4 BIT(29)
-#define NFC_CMD_TYPE GENMASK(31, 30)
+#define NFC_CMD_TYPE_MSK GENMASK(31, 30)
+#define NFC_NORMAL_OP (0 << 30)
+#define NFC_ECC_OP (1 << 30)
+#define NFC_PAGE_OP (2 << 30)
/* define bit use in NFC_RCMD_SET */
-#define NFC_READ_CMD GENMASK(7, 0)
-#define NFC_RANDOM_READ_CMD0 GENMASK(15, 8)
-#define NFC_RANDOM_READ_CMD1 GENMASK(23, 16)
+#define NFC_READ_CMD_MSK GENMASK(7, 0)
+#define NFC_RND_READ_CMD0_MSK GENMASK(15, 8)
+#define NFC_RND_READ_CMD1_MSK GENMASK(23, 16)
/* define bit use in NFC_WCMD_SET */
-#define NFC_PROGRAM_CMD GENMASK(7, 0)
-#define NFC_RANDOM_WRITE_CMD GENMASK(15, 8)
-#define NFC_READ_CMD0 GENMASK(23, 16)
-#define NFC_READ_CMD1 GENMASK(31, 24)
+#define NFC_PROGRAM_CMD_MSK GENMASK(7, 0)
+#define NFC_RND_WRITE_CMD_MSK GENMASK(15, 8)
+#define NFC_READ_CMD0_MSK GENMASK(23, 16)
+#define NFC_READ_CMD1_MSK GENMASK(31, 24)
/* define bit use in NFC_ECC_CTL */
#define NFC_ECC_EN BIT(0)
#define NFC_ECC_PIPELINE BIT(3)
#define NFC_ECC_EXCEPTION BIT(4)
-#define NFC_ECC_BLOCK_SIZE BIT(5)
+#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
#define NFC_RANDOM_EN BIT(9)
#define NFC_RANDOM_DIRECTION BIT(10)
-#define NFC_ECC_MODE_SHIFT 12
-#define NFC_ECC_MODE GENMASK(15, 12)
-#define NFC_RANDOM_SEED GENMASK(30, 16)
+#define NFC_ECC_MODE_MSK GENMASK(15, 12)
+#define NFC_ECC_MODE(x) ((x) << 12)
+#define NFC_RANDOM_SEED_MSK GENMASK(30, 16)
+#define NFC_RANDOM_SEED(x) ((x) << 16)
-/* NFC_USER_DATA helper macros */
-#define NFC_BUF_TO_USER_DATA(buf) ((buf)[0] | ((buf)[1] << 8) | \
- ((buf)[2] << 16) | ((buf)[3] << 24))
+/* define bit use in NFC_ECC_ST */
+#define NFC_ECC_ERR(x) BIT(x)
+#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
+#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
#define NFC_DEFAULT_TIMEOUT_MS 1000
@@ -360,13 +365,13 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
switch (rb->type) {
case RB_NATIVE:
ret = !!(readl(nfc->regs + NFC_REG_ST) &
- (NFC_RB_STATE0 << rb->info.nativeid));
+ NFC_RB_STATE(rb->info.nativeid));
if (ret)
break;
sunxi_nfc_wait_int(nfc, NFC_RB_B2R, timeo);
ret = !!(readl(nfc->regs + NFC_REG_ST) &
- (NFC_RB_STATE0 << rb->info.nativeid));
+ NFC_RB_STATE(rb->info.nativeid));
break;
case RB_GPIO:
ret = gpio_get_value(rb->info.gpio);
@@ -396,19 +401,19 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
return;
ctl = readl(nfc->regs + NFC_REG_CTL) &
- ~(NFC_CE_SEL | NFC_RB_SEL | NFC_EN);
+ ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
if (chip >= 0) {
sel = &sunxi_nand->sels[chip];
- ctl |= (sel->cs << 24) | NFC_EN |
- (((nand->page_shift - 10) & 0xf) << 8);
+ ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
+ NFC_PAGE_SHIFT(nand->page_shift - 10);
if (sel->rb.type == RB_NONE) {
nand->dev_ready = NULL;
} else {
nand->dev_ready = sunxi_nfc_dev_ready;
if (sel->rb.type == RB_NATIVE)
- ctl |= (sel->rb.info.nativeid << 3);
+ ctl |= NFC_RB_SEL(sel->rb.info.nativeid);
}
writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
@@ -534,155 +539,244 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
}
-static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf,
- int oob_required, int page)
+static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
{
- struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
- struct nand_ecclayout *layout = ecc->layout;
- struct sunxi_nand_hw_ecc *data = ecc->priv;
- unsigned int max_bitflips = 0;
- int offset;
- int ret;
- u32 tmp;
- int i;
- int cnt;
+ struct nand_chip *nand = mtd->priv;
+ struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
+ u32 ecc_ctl;
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE);
- tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) |
- NFC_ECC_EXCEPTION;
+ ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
+ ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
+ NFC_ECC_BLOCK_SIZE_MSK);
+ ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION;
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
+}
- for (i = 0; i < ecc->steps; i++) {
- if (i)
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, i * ecc->size, -1);
+static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
+{
+ struct nand_chip *nand = mtd->priv;
+ struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
- offset = mtd->writesize + layout->eccpos[i * ecc->bytes] - 4;
+ writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
+ nfc->regs + NFC_REG_ECC_CTL);
+}
- chip->read_buf(mtd, NULL, ecc->size);
+static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
+{
+ buf[0] = user_data;
+ buf[1] = user_data >> 8;
+ buf[2] = user_data >> 16;
+ buf[3] = user_data >> 24;
+}
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
+static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
+ u8 *data, int data_off,
+ u8 *oob, int oob_off,
+ int *cur_off,
+ unsigned int *max_bitflips)
+{
+ struct nand_chip *nand = mtd->priv;
+ struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
+ u32 status;
+ int ret;
- ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
- if (ret)
- return ret;
+ if (*cur_off != data_off)
+ nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
- tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | (1 << 30);
- writel(tmp, nfc->regs + NFC_REG_CMD);
+ sunxi_nfc_read_buf(mtd, NULL, ecc->size);
- ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
- if (ret)
- return ret;
+ if (data_off + ecc->size != oob_off)
+ nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
- memcpy_fromio(buf + (i * ecc->size),
- nfc->regs + NFC_RAM0_BASE, ecc->size);
+ ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+ if (ret)
+ return ret;
- if (readl(nfc->regs + NFC_REG_ECC_ST) & 0x1) {
- mtd->ecc_stats.failed++;
- } else {
- tmp = readl(nfc->regs + NFC_REG_ECC_CNT0) & 0xff;
- mtd->ecc_stats.corrected += tmp;
- max_bitflips = max_t(unsigned int, max_bitflips, tmp);
- }
+ writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
+ nfc->regs + NFC_REG_CMD);
- if (oob_required) {
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
+ ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+ if (ret)
+ return ret;
- ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
- if (ret)
- return ret;
+ status = readl(nfc->regs + NFC_REG_ECC_ST);
+ ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
- offset -= mtd->writesize;
- chip->read_buf(mtd, chip->oob_poi + offset,
- ecc->bytes + 4);
- }
+ memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
+
+ nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
+ sunxi_nfc_read_buf(mtd, oob, ecc->bytes + 4);
+
+ if (status & NFC_ECC_ERR(0)) {
+ ret = nand_check_erased_ecc_chunk(data, ecc->size,
+ oob, ecc->bytes + 4,
+ NULL, 0, ecc->strength);
+ } else {
+ /*
+ * The engine protects 4 bytes of OOB data per chunk.
+ * Retrieve the corrected OOB bytes.
+ */
+ sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)),
+ oob);
}
- if (oob_required) {
- cnt = ecc->layout->oobfree[ecc->steps].length;
- if (cnt > 0) {
- offset = mtd->writesize +
- ecc->layout->oobfree[ecc->steps].offset;
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
- offset -= mtd->writesize;
- chip->read_buf(mtd, chip->oob_poi + offset, cnt);
- }
+ if (ret < 0) {
+ mtd->ecc_stats.failed++;
+ } else {
+ mtd->ecc_stats.corrected += ret;
+ *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
}
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~NFC_ECC_EN;
+ *cur_off = oob_off + ecc->bytes + 4;
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ return 0;
+}
- return max_bitflips;
+static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
+ u8 *oob, int *cur_off)
+{
+ struct nand_chip *nand = mtd->priv;
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
+ int offset = ((ecc->bytes + 4) * ecc->steps);
+ int len = mtd->oobsize - offset;
+
+ if (len <= 0)
+ return;
+
+ if (*cur_off != offset)
+ nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
+ offset + mtd->writesize, -1);
+
+ sunxi_nfc_read_buf(mtd, oob + offset, len);
+
+ *cur_off = mtd->oobsize + mtd->writesize;
}
-static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
{
- struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
- struct nand_ecclayout *layout = ecc->layout;
- struct sunxi_nand_hw_ecc *data = ecc->priv;
- int offset;
+ return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+}
+
+static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
+ const u8 *data, int data_off,
+ const u8 *oob, int oob_off,
+ int *cur_off)
+{
+ struct nand_chip *nand = mtd->priv;
+ struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret;
- u32 tmp;
- int i;
- int cnt;
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE);
- tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) |
- NFC_ECC_EXCEPTION;
+ if (data_off != *cur_off)
+ nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ sunxi_nfc_write_buf(mtd, data, ecc->size);
- for (i = 0; i < ecc->steps; i++) {
- if (i)
- chip->cmdfunc(mtd, NAND_CMD_RNDIN, i * ecc->size, -1);
+ /* Fill OOB data in */
+ writel(sunxi_nfc_buf_to_user_data(oob),
+ nfc->regs + NFC_REG_USER_DATA(0));
- chip->write_buf(mtd, buf + (i * ecc->size), ecc->size);
+ if (data_off + ecc->size != oob_off)
+ nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
- offset = layout->eccpos[i * ecc->bytes] - 4 + mtd->writesize;
+ ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+ if (ret)
+ return ret;
- /* Fill OOB data in */
- writel(NFC_BUF_TO_USER_DATA(chip->oob_poi +
- layout->oobfree[i].offset),
- nfc->regs + NFC_REG_USER_DATA_BASE);
+ writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
+ NFC_ACCESS_DIR | NFC_ECC_OP,
+ nfc->regs + NFC_REG_CMD);
- chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1);
+ ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+ if (ret)
+ return ret;
- ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
- if (ret)
- return ret;
+ *cur_off = oob_off + ecc->bytes + 4;
- tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR |
- (1 << 30);
- writel(tmp, nfc->regs + NFC_REG_CMD);
- ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+ return 0;
+}
+
+static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
+ u8 *oob, int *cur_off)
+{
+ struct nand_chip *nand = mtd->priv;
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
+ int offset = ((ecc->bytes + 4) * ecc->steps);
+ int len = mtd->oobsize - offset;
+
+ if (len <= 0)
+ return;
+
+ if (*cur_off != offset)
+ nand->cmdfunc(mtd, NAND_CMD_RNDIN,
+ offset + mtd->writesize, -1);
+
+ sunxi_nfc_write_buf(mtd, oob + offset, len);
+
+ *cur_off = mtd->oobsize + mtd->writesize;
+}
+
+static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
+ struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
+{
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
+ unsigned int max_bitflips = 0;
+ int ret, i, cur_off = 0;
+
+ sunxi_nfc_hw_ecc_enable(mtd);
+
+ 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;
+
+ ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
+ oob_off + mtd->writesize,
+ &cur_off, &max_bitflips);
if (ret)
return ret;
}
- if (oob_required) {
- cnt = ecc->layout->oobfree[i].length;
- if (cnt > 0) {
- offset = mtd->writesize +
- ecc->layout->oobfree[i].offset;
- chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1);
- offset -= mtd->writesize;
- chip->write_buf(mtd, chip->oob_poi + offset, cnt);
- }
+ if (oob_required)
+ sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off);
+
+ sunxi_nfc_hw_ecc_disable(mtd);
+
+ return max_bitflips;
+}
+
+static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ const uint8_t *buf, int oob_required,
+ int page)
+{
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
+ int ret, i, cur_off = 0;
+
+ sunxi_nfc_hw_ecc_enable(mtd);
+
+ 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;
+
+ ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
+ oob_off + mtd->writesize,
+ &cur_off);
+ if (ret)
+ return ret;
}
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~NFC_ECC_EN;
+ if (oob_required)
+ sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, &cur_off);
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ sunxi_nfc_hw_ecc_disable(mtd);
return 0;
}
@@ -692,65 +786,29 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
uint8_t *buf, int oob_required,
int page)
{
- struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
struct nand_ecc_ctrl *ecc = &chip->ecc;
- struct sunxi_nand_hw_ecc *data = ecc->priv;
unsigned int max_bitflips = 0;
- uint8_t *oob = chip->oob_poi;
- int offset = 0;
- int ret;
- int cnt;
- u32 tmp;
- int i;
+ int ret, i, cur_off = 0;
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE);
- tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) |
- NFC_ECC_EXCEPTION;
-
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ sunxi_nfc_hw_ecc_enable(mtd);
for (i = 0; i < ecc->steps; i++) {
- chip->read_buf(mtd, NULL, ecc->size);
-
- tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | (1 << 30);
- writel(tmp, nfc->regs + NFC_REG_CMD);
-
- ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+ int data_off = i * (ecc->size + ecc->bytes + 4);
+ int oob_off = data_off + ecc->size;
+ u8 *data = buf + (i * ecc->size);
+ u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
+
+ ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
+ oob_off, &cur_off,
+ &max_bitflips);
if (ret)
return ret;
-
- memcpy_fromio(buf, nfc->regs + NFC_RAM0_BASE, ecc->size);
- buf += ecc->size;
- offset += ecc->size;
-
- if (readl(nfc->regs + NFC_REG_ECC_ST) & 0x1) {
- mtd->ecc_stats.failed++;
- } else {
- tmp = readl(nfc->regs + NFC_REG_ECC_CNT0) & 0xff;
- mtd->ecc_stats.corrected += tmp;
- max_bitflips = max_t(unsigned int, max_bitflips, tmp);
- }
-
- if (oob_required) {
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
- chip->read_buf(mtd, oob, ecc->bytes + ecc->prepad);
- oob += ecc->bytes + ecc->prepad;
- }
-
- offset += ecc->bytes + ecc->prepad;
}
- if (oob_required) {
- cnt = mtd->oobsize - (oob - chip->oob_poi);
- if (cnt > 0) {
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
- chip->read_buf(mtd, oob, cnt);
- }
- }
+ if (oob_required)
+ sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off);
- writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
- nfc->regs + NFC_REG_ECC_CTL);
+ sunxi_nfc_hw_ecc_disable(mtd);
return max_bitflips;
}
@@ -758,57 +816,29 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
- struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
struct nand_ecc_ctrl *ecc = &chip->ecc;
- struct sunxi_nand_hw_ecc *data = ecc->priv;
- uint8_t *oob = chip->oob_poi;
- int offset = 0;
- int ret;
- int cnt;
- u32 tmp;
- int i;
+ int ret, i, cur_off = 0;
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE);
- tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) |
- NFC_ECC_EXCEPTION;
-
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ sunxi_nfc_hw_ecc_enable(mtd);
for (i = 0; i < ecc->steps; i++) {
- chip->write_buf(mtd, buf + (i * ecc->size), ecc->size);
- offset += ecc->size;
-
- /* Fill OOB data in */
- writel(NFC_BUF_TO_USER_DATA(oob),
- nfc->regs + NFC_REG_USER_DATA_BASE);
+ int data_off = i * (ecc->size + ecc->bytes + 4);
+ int oob_off = data_off + ecc->size;
+ const u8 *data = buf + (i * ecc->size);
+ const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
- tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR |
- (1 << 30);
- writel(tmp, nfc->regs + NFC_REG_CMD);
-
- ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+ ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off,
+ oob, oob_off, &cur_off);
if (ret)
return ret;
-
- offset += ecc->bytes + ecc->prepad;
- oob += ecc->bytes + ecc->prepad;
- }
-
- if (oob_required) {
- cnt = mtd->oobsize - (oob - chip->oob_poi);
- if (cnt > 0) {
- chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1);
- chip->write_buf(mtd, oob, cnt);
- }
}
- tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
- tmp &= ~NFC_ECC_EN;
+ if (oob_required)
+ sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, &cur_off);
- writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
+ sunxi_nfc_hw_ecc_disable(mtd);
return 0;
}
@@ -970,17 +1000,23 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip,
mode = chip->nand.onfi_timing_mode_default;
} else {
uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
+ int i;
mode = fls(mode) - 1;
if (mode < 0)
mode = 0;
feature[0] = mode;
- ret = chip->nand.onfi_set_features(&chip->mtd, &chip->nand,
+ for (i = 0; i < chip->nsels; i++) {
+ chip->nand.select_chip(&chip->mtd, i);
+ ret = chip->nand.onfi_set_features(&chip->mtd,
+ &chip->nand,
ONFI_FEATURE_ADDR_TIMING_MODE,
feature);
- if (ret)
- return ret;
+ chip->nand.select_chip(&chip->mtd, -1);
+ if (ret)
+ return ret;
+ }
}
timings = onfi_async_timing_mode_to_sdr_timings(mode);
@@ -1154,16 +1190,9 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
struct device_node *np)
{
struct nand_chip *nand = mtd->priv;
- int strength;
- int blk_size;
int ret;
- blk_size = of_get_nand_ecc_step_size(np);
- strength = of_get_nand_ecc_strength(np);
- if (blk_size > 0 && strength > 0) {
- ecc->size = blk_size;
- ecc->strength = strength;
- } else {
+ if (!ecc->size) {
ecc->size = nand->ecc_step_ds;
ecc->strength = nand->ecc_strength_ds;
}
@@ -1171,12 +1200,6 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
if (!ecc->size || !ecc->strength)
return -EINVAL;
- ecc->mode = NAND_ECC_HW;
-
- ret = of_get_nand_ecc_mode(np);
- if (ret >= 0)
- ecc->mode = ret;
-
switch (ecc->mode) {
case NAND_ECC_SOFT_BCH:
break;
@@ -1302,24 +1325,29 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
/* Default tR value specified in the ONFI spec (chapter 4.15.1) */
nand->chip_delay = 200;
nand->controller = &nfc->controller;
+ /*
+ * Set the ECC mode to the default value in case nothing is specified
+ * in the DT.
+ */
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->flash_node = np;
nand->select_chip = sunxi_nfc_select_chip;
nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
nand->read_buf = sunxi_nfc_read_buf;
nand->write_buf = sunxi_nfc_write_buf;
nand->read_byte = sunxi_nfc_read_byte;
- if (of_get_nand_on_flash_bbt(np))
- nand->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
-
mtd = &chip->mtd;
mtd->dev.parent = dev;
mtd->priv = nand;
- mtd->owner = THIS_MODULE;
ret = nand_scan_ident(mtd, nsels, NULL);
if (ret)
return ret;
+ if (nand->bbt_options & NAND_BBT_USE_FLASH)
+ nand->bbt_options |= NAND_BBT_NO_OOB;
+
ret = sunxi_nand_chip_init_timings(chip, np);
if (ret) {
dev_err(dev, "could not configure chip timings: %d\n", ret);
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index fb8fd35fa668..befddf0776e4 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -382,6 +382,7 @@ static int tmio_probe(struct platform_device *dev)
nand_chip = &tmio->chip;
mtd->priv = nand_chip;
mtd->name = "tmio-nand";
+ mtd->dev.parent = &dev->dev;
tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr));
if (!tmio->ccr)
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 9c0bc45e28a9..8572519b8441 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -323,7 +323,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
continue;
chip = &txx9_priv->chip;
mtd = &txx9_priv->mtd;
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &dev->dev;
mtd->priv = chip;
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
new file mode 100644
index 000000000000..8805d6325579
--- /dev/null
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -0,0 +1,878 @@
+/*
+ * Copyright 2009-2015 Freescale Semiconductor, Inc. and others
+ *
+ * Description: MPC5125, VF610, MCF54418 and Kinetis K70 Nand driver.
+ * Jason ported to M54418TWR and MVFA5 (VF610).
+ * Authors: Stefan Agner <stefan.agner@toradex.com>
+ * Bill Pringlemeir <bpringlemeir@nbsps.com>
+ * Shaohui Xie <b21989@freescale.com>
+ * Jason Jin <Jason.jin@freescale.com>
+ *
+ * Based on original driver mpc5121_nfc.c.
+ *
+ * This 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.
+ *
+ * Limitations:
+ * - Untested on MPC5125 and M54418.
+ * - DMA and pipelining not used.
+ * - 2K pages or less.
+ * - HW ECC: Only 2K page with 64+ OOB.
+ * - HW ECC: Only 24 and 32-bit error correction implemented.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_mtd.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define DRV_NAME "vf610_nfc"
+
+/* Register Offsets */
+#define NFC_FLASH_CMD1 0x3F00
+#define NFC_FLASH_CMD2 0x3F04
+#define NFC_COL_ADDR 0x3F08
+#define NFC_ROW_ADDR 0x3F0c
+#define NFC_ROW_ADDR_INC 0x3F14
+#define NFC_FLASH_STATUS1 0x3F18
+#define NFC_FLASH_STATUS2 0x3F1c
+#define NFC_CACHE_SWAP 0x3F28
+#define NFC_SECTOR_SIZE 0x3F2c
+#define NFC_FLASH_CONFIG 0x3F30
+#define NFC_IRQ_STATUS 0x3F38
+
+/* Addresses for NFC MAIN RAM BUFFER areas */
+#define NFC_MAIN_AREA(n) ((n) * 0x1000)
+
+#define PAGE_2K 0x0800
+#define OOB_64 0x0040
+#define OOB_MAX 0x0100
+
+/*
+ * NFC_CMD2[CODE] values. See section:
+ * - 31.4.7 Flash Command Code Description, Vybrid manual
+ * - 23.8.6 Flash Command Sequencer, MPC5125 manual
+ *
+ * Briefly these are bitmasks of controller cycles.
+ */
+#define READ_PAGE_CMD_CODE 0x7EE0
+#define READ_ONFI_PARAM_CMD_CODE 0x4860
+#define PROGRAM_PAGE_CMD_CODE 0x7FC0
+#define ERASE_CMD_CODE 0x4EC0
+#define READ_ID_CMD_CODE 0x4804
+#define RESET_CMD_CODE 0x4040
+#define STATUS_READ_CMD_CODE 0x4068
+
+/* NFC ECC mode define */
+#define ECC_BYPASS 0
+#define ECC_45_BYTE 6
+#define ECC_60_BYTE 7
+
+/*** Register Mask and bit definitions */
+
+/* NFC_FLASH_CMD1 Field */
+#define CMD_BYTE2_MASK 0xFF000000
+#define CMD_BYTE2_SHIFT 24
+
+/* NFC_FLASH_CM2 Field */
+#define CMD_BYTE1_MASK 0xFF000000
+#define CMD_BYTE1_SHIFT 24
+#define CMD_CODE_MASK 0x00FFFF00
+#define CMD_CODE_SHIFT 8
+#define BUFNO_MASK 0x00000006
+#define BUFNO_SHIFT 1
+#define START_BIT BIT(0)
+
+/* NFC_COL_ADDR Field */
+#define COL_ADDR_MASK 0x0000FFFF
+#define COL_ADDR_SHIFT 0
+
+/* NFC_ROW_ADDR Field */
+#define ROW_ADDR_MASK 0x00FFFFFF
+#define ROW_ADDR_SHIFT 0
+#define ROW_ADDR_CHIP_SEL_RB_MASK 0xF0000000
+#define ROW_ADDR_CHIP_SEL_RB_SHIFT 28
+#define ROW_ADDR_CHIP_SEL_MASK 0x0F000000
+#define ROW_ADDR_CHIP_SEL_SHIFT 24
+
+/* NFC_FLASH_STATUS2 Field */
+#define STATUS_BYTE1_MASK 0x000000FF
+
+/* NFC_FLASH_CONFIG Field */
+#define CONFIG_ECC_SRAM_ADDR_MASK 0x7FC00000
+#define CONFIG_ECC_SRAM_ADDR_SHIFT 22
+#define CONFIG_ECC_SRAM_REQ_BIT BIT(21)
+#define CONFIG_DMA_REQ_BIT BIT(20)
+#define CONFIG_ECC_MODE_MASK 0x000E0000
+#define CONFIG_ECC_MODE_SHIFT 17
+#define CONFIG_FAST_FLASH_BIT BIT(16)
+#define CONFIG_16BIT BIT(7)
+#define CONFIG_BOOT_MODE_BIT BIT(6)
+#define CONFIG_ADDR_AUTO_INCR_BIT BIT(5)
+#define CONFIG_BUFNO_AUTO_INCR_BIT BIT(4)
+#define CONFIG_PAGE_CNT_MASK 0xF
+#define CONFIG_PAGE_CNT_SHIFT 0
+
+/* NFC_IRQ_STATUS Field */
+#define IDLE_IRQ_BIT BIT(29)
+#define IDLE_EN_BIT BIT(20)
+#define CMD_DONE_CLEAR_BIT BIT(18)
+#define IDLE_CLEAR_BIT BIT(17)
+
+/*
+ * ECC status - seems to consume 8 bytes (double word). The documented
+ * status byte is located in the lowest byte of the second word (which is
+ * the 4th or 7th byte depending on endianness).
+ * Calculate an offset to store the ECC status at the end of the buffer.
+ */
+#define ECC_SRAM_ADDR (PAGE_2K + OOB_MAX - 8)
+
+#define ECC_STATUS 0x4
+#define ECC_STATUS_MASK 0x80
+#define ECC_STATUS_ERR_COUNT 0x3F
+
+enum vf610_nfc_alt_buf {
+ ALT_BUF_DATA = 0,
+ ALT_BUF_ID = 1,
+ ALT_BUF_STAT = 2,
+ ALT_BUF_ONFI = 3,
+};
+
+enum vf610_nfc_variant {
+ NFC_VFC610 = 1,
+};
+
+struct vf610_nfc {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ struct device *dev;
+ void __iomem *regs;
+ struct completion cmd_done;
+ uint buf_offset;
+ int write_sz;
+ /* Status and ID are in alternate locations. */
+ enum vf610_nfc_alt_buf alt_buf;
+ enum vf610_nfc_variant variant;
+ struct clk *clk;
+ bool use_hw_ecc;
+ u32 ecc_mode;
+};
+
+#define mtd_to_nfc(_mtd) container_of(_mtd, struct vf610_nfc, mtd)
+
+static struct nand_ecclayout vf610_nfc_ecc45 = {
+ .eccbytes = 45,
+ .eccpos = {19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63},
+ .oobfree = {
+ {.offset = 2,
+ .length = 17} }
+};
+
+static struct nand_ecclayout vf610_nfc_ecc60 = {
+ .eccbytes = 60,
+ .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63 },
+ .oobfree = {
+ {.offset = 2,
+ .length = 2} }
+};
+
+static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg)
+{
+ return readl(nfc->regs + reg);
+}
+
+static inline void vf610_nfc_write(struct vf610_nfc *nfc, uint reg, u32 val)
+{
+ writel(val, nfc->regs + reg);
+}
+
+static inline void vf610_nfc_set(struct vf610_nfc *nfc, uint reg, u32 bits)
+{
+ vf610_nfc_write(nfc, reg, vf610_nfc_read(nfc, reg) | bits);
+}
+
+static inline void vf610_nfc_clear(struct vf610_nfc *nfc, uint reg, u32 bits)
+{
+ vf610_nfc_write(nfc, reg, vf610_nfc_read(nfc, reg) & ~bits);
+}
+
+static inline void vf610_nfc_set_field(struct vf610_nfc *nfc, u32 reg,
+ u32 mask, u32 shift, u32 val)
+{
+ vf610_nfc_write(nfc, reg,
+ (vf610_nfc_read(nfc, reg) & (~mask)) | val << shift);
+}
+
+static inline void vf610_nfc_memcpy(void *dst, const void __iomem *src,
+ size_t n)
+{
+ /*
+ * Use this accessor for the internal SRAM buffers. On the ARM
+ * Freescale Vybrid SoC it's known that the driver can treat
+ * the SRAM buffer as if it's memory. Other platform might need
+ * to treat the buffers differently.
+ *
+ * For the time being, use memcpy
+ */
+ memcpy(dst, src, n);
+}
+
+/* Clear flags for upcoming command */
+static inline void vf610_nfc_clear_status(struct vf610_nfc *nfc)
+{
+ u32 tmp = vf610_nfc_read(nfc, NFC_IRQ_STATUS);
+
+ tmp |= CMD_DONE_CLEAR_BIT | IDLE_CLEAR_BIT;
+ vf610_nfc_write(nfc, NFC_IRQ_STATUS, tmp);
+}
+
+static void vf610_nfc_done(struct vf610_nfc *nfc)
+{
+ unsigned long timeout = msecs_to_jiffies(100);
+
+ /*
+ * Barrier is needed after this write. This write need
+ * to be done before reading the next register the first
+ * time.
+ * vf610_nfc_set implicates such a barrier by using writel
+ * to write to the register.
+ */
+ vf610_nfc_set(nfc, NFC_IRQ_STATUS, IDLE_EN_BIT);
+ vf610_nfc_set(nfc, NFC_FLASH_CMD2, START_BIT);
+
+ if (!wait_for_completion_timeout(&nfc->cmd_done, timeout))
+ dev_warn(nfc->dev, "Timeout while waiting for BUSY.\n");
+
+ vf610_nfc_clear_status(nfc);
+}
+
+static u8 vf610_nfc_get_id(struct vf610_nfc *nfc, int col)
+{
+ u32 flash_id;
+
+ if (col < 4) {
+ flash_id = vf610_nfc_read(nfc, NFC_FLASH_STATUS1);
+ flash_id >>= (3 - col) * 8;
+ } else {
+ flash_id = vf610_nfc_read(nfc, NFC_FLASH_STATUS2);
+ flash_id >>= 24;
+ }
+
+ return flash_id & 0xff;
+}
+
+static u8 vf610_nfc_get_status(struct vf610_nfc *nfc)
+{
+ return vf610_nfc_read(nfc, NFC_FLASH_STATUS2) & STATUS_BYTE1_MASK;
+}
+
+static void vf610_nfc_send_command(struct vf610_nfc *nfc, u32 cmd_byte1,
+ u32 cmd_code)
+{
+ u32 tmp;
+
+ vf610_nfc_clear_status(nfc);
+
+ tmp = vf610_nfc_read(nfc, NFC_FLASH_CMD2);
+ tmp &= ~(CMD_BYTE1_MASK | CMD_CODE_MASK | BUFNO_MASK);
+ tmp |= cmd_byte1 << CMD_BYTE1_SHIFT;
+ tmp |= cmd_code << CMD_CODE_SHIFT;
+ vf610_nfc_write(nfc, NFC_FLASH_CMD2, tmp);
+}
+
+static void vf610_nfc_send_commands(struct vf610_nfc *nfc, u32 cmd_byte1,
+ u32 cmd_byte2, u32 cmd_code)
+{
+ u32 tmp;
+
+ vf610_nfc_send_command(nfc, cmd_byte1, cmd_code);
+
+ tmp = vf610_nfc_read(nfc, NFC_FLASH_CMD1);
+ tmp &= ~CMD_BYTE2_MASK;
+ tmp |= cmd_byte2 << CMD_BYTE2_SHIFT;
+ vf610_nfc_write(nfc, NFC_FLASH_CMD1, tmp);
+}
+
+static irqreturn_t vf610_nfc_irq(int irq, void *data)
+{
+ struct mtd_info *mtd = data;
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+ vf610_nfc_clear(nfc, NFC_IRQ_STATUS, IDLE_EN_BIT);
+ complete(&nfc->cmd_done);
+
+ return IRQ_HANDLED;
+}
+
+static void vf610_nfc_addr_cycle(struct vf610_nfc *nfc, int column, int page)
+{
+ if (column != -1) {
+ if (nfc->chip.options & NAND_BUSWIDTH_16)
+ column = column / 2;
+ vf610_nfc_set_field(nfc, NFC_COL_ADDR, COL_ADDR_MASK,
+ COL_ADDR_SHIFT, column);
+ }
+ if (page != -1)
+ vf610_nfc_set_field(nfc, NFC_ROW_ADDR, ROW_ADDR_MASK,
+ ROW_ADDR_SHIFT, page);
+}
+
+static inline void vf610_nfc_ecc_mode(struct vf610_nfc *nfc, int ecc_mode)
+{
+ vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG,
+ CONFIG_ECC_MODE_MASK,
+ CONFIG_ECC_MODE_SHIFT, ecc_mode);
+}
+
+static inline void vf610_nfc_transfer_size(struct vf610_nfc *nfc, int size)
+{
+ vf610_nfc_write(nfc, NFC_SECTOR_SIZE, size);
+}
+
+static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
+ int column, int page)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ int trfr_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0;
+
+ nfc->buf_offset = max(column, 0);
+ nfc->alt_buf = ALT_BUF_DATA;
+
+ switch (command) {
+ case NAND_CMD_SEQIN:
+ /* Use valid column/page from preread... */
+ vf610_nfc_addr_cycle(nfc, column, page);
+ nfc->buf_offset = 0;
+
+ /*
+ * SEQIN => data => PAGEPROG sequence is done by the controller
+ * hence we do not need to issue the command here...
+ */
+ return;
+ case NAND_CMD_PAGEPROG:
+ trfr_sz += nfc->write_sz;
+ vf610_nfc_transfer_size(nfc, trfr_sz);
+ vf610_nfc_send_commands(nfc, NAND_CMD_SEQIN,
+ command, PROGRAM_PAGE_CMD_CODE);
+ if (nfc->use_hw_ecc)
+ vf610_nfc_ecc_mode(nfc, nfc->ecc_mode);
+ else
+ vf610_nfc_ecc_mode(nfc, ECC_BYPASS);
+ break;
+
+ case NAND_CMD_RESET:
+ vf610_nfc_transfer_size(nfc, 0);
+ vf610_nfc_send_command(nfc, command, RESET_CMD_CODE);
+ break;
+
+ case NAND_CMD_READOOB:
+ trfr_sz += mtd->oobsize;
+ column = mtd->writesize;
+ vf610_nfc_transfer_size(nfc, trfr_sz);
+ vf610_nfc_send_commands(nfc, NAND_CMD_READ0,
+ NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
+ vf610_nfc_addr_cycle(nfc, column, page);
+ vf610_nfc_ecc_mode(nfc, ECC_BYPASS);
+ break;
+
+ case NAND_CMD_READ0:
+ trfr_sz += mtd->writesize + mtd->oobsize;
+ vf610_nfc_transfer_size(nfc, trfr_sz);
+ vf610_nfc_send_commands(nfc, NAND_CMD_READ0,
+ NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
+ vf610_nfc_addr_cycle(nfc, column, page);
+ vf610_nfc_ecc_mode(nfc, nfc->ecc_mode);
+ break;
+
+ case NAND_CMD_PARAM:
+ nfc->alt_buf = ALT_BUF_ONFI;
+ trfr_sz = 3 * sizeof(struct nand_onfi_params);
+ vf610_nfc_transfer_size(nfc, trfr_sz);
+ vf610_nfc_send_command(nfc, command, READ_ONFI_PARAM_CMD_CODE);
+ vf610_nfc_addr_cycle(nfc, -1, column);
+ vf610_nfc_ecc_mode(nfc, ECC_BYPASS);
+ break;
+
+ case NAND_CMD_ERASE1:
+ vf610_nfc_transfer_size(nfc, 0);
+ vf610_nfc_send_commands(nfc, command,
+ NAND_CMD_ERASE2, ERASE_CMD_CODE);
+ vf610_nfc_addr_cycle(nfc, column, page);
+ break;
+
+ case NAND_CMD_READID:
+ nfc->alt_buf = ALT_BUF_ID;
+ nfc->buf_offset = 0;
+ vf610_nfc_transfer_size(nfc, 0);
+ vf610_nfc_send_command(nfc, command, READ_ID_CMD_CODE);
+ vf610_nfc_addr_cycle(nfc, -1, column);
+ break;
+
+ case NAND_CMD_STATUS:
+ nfc->alt_buf = ALT_BUF_STAT;
+ vf610_nfc_transfer_size(nfc, 0);
+ vf610_nfc_send_command(nfc, command, STATUS_READ_CMD_CODE);
+ break;
+ default:
+ return;
+ }
+
+ vf610_nfc_done(nfc);
+
+ nfc->use_hw_ecc = false;
+ nfc->write_sz = 0;
+}
+
+static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ uint c = nfc->buf_offset;
+
+ /* Alternate buffers are only supported through read_byte */
+ WARN_ON(nfc->alt_buf);
+
+ vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
+
+ nfc->buf_offset += len;
+}
+
+static void vf610_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+ int len)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ uint c = nfc->buf_offset;
+ uint l;
+
+ l = min_t(uint, len, mtd->writesize + mtd->oobsize - c);
+ vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l);
+
+ nfc->write_sz += l;
+ nfc->buf_offset += l;
+}
+
+static uint8_t vf610_nfc_read_byte(struct mtd_info *mtd)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ u8 tmp;
+ uint c = nfc->buf_offset;
+
+ switch (nfc->alt_buf) {
+ case ALT_BUF_ID:
+ tmp = vf610_nfc_get_id(nfc, c);
+ break;
+ case ALT_BUF_STAT:
+ tmp = vf610_nfc_get_status(nfc);
+ break;
+#ifdef __LITTLE_ENDIAN
+ case ALT_BUF_ONFI:
+ /* Reverse byte since the controller uses big endianness */
+ c = nfc->buf_offset ^ 0x3;
+ /* fall-through */
+#endif
+ default:
+ tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c));
+ break;
+ }
+ nfc->buf_offset++;
+ return tmp;
+}
+
+static u16 vf610_nfc_read_word(struct mtd_info *mtd)
+{
+ u16 tmp;
+
+ vf610_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
+ return tmp;
+}
+
+/* If not provided, upper layers apply a fixed delay. */
+static int vf610_nfc_dev_ready(struct mtd_info *mtd)
+{
+ /* NFC handles R/B internally; always ready. */
+ return 1;
+}
+
+/*
+ * This function supports Vybrid only (MPC5125 would have full RB and four CS)
+ */
+static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ u32 tmp = vf610_nfc_read(nfc, NFC_ROW_ADDR);
+
+ /* Vybrid only (MPC5125 would have full RB and four CS) */
+ if (nfc->variant != NFC_VFC610)
+ return;
+
+ tmp &= ~(ROW_ADDR_CHIP_SEL_RB_MASK | ROW_ADDR_CHIP_SEL_MASK);
+
+ if (chip >= 0) {
+ tmp |= 1 << ROW_ADDR_CHIP_SEL_RB_SHIFT;
+ tmp |= BIT(chip) << ROW_ADDR_CHIP_SEL_SHIFT;
+ }
+
+ vf610_nfc_write(nfc, NFC_ROW_ADDR, tmp);
+}
+
+/* Count the number of 0's in buff up to max_bits */
+static inline int count_written_bits(uint8_t *buff, int size, int max_bits)
+{
+ uint32_t *buff32 = (uint32_t *)buff;
+ int k, written_bits = 0;
+
+ for (k = 0; k < (size / 4); k++) {
+ written_bits += hweight32(~buff32[k]);
+ if (unlikely(written_bits > max_bits))
+ break;
+ }
+
+ return written_bits;
+}
+
+static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat,
+ uint8_t *oob, int page)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ u32 ecc_status_off = NFC_MAIN_AREA(0) + ECC_SRAM_ADDR + ECC_STATUS;
+ u8 ecc_status;
+ u8 ecc_count;
+ int flips_threshold = nfc->chip.ecc.strength / 2;
+
+ ecc_status = vf610_nfc_read(nfc, ecc_status_off) & 0xff;
+ ecc_count = ecc_status & ECC_STATUS_ERR_COUNT;
+
+ if (!(ecc_status & ECC_STATUS_MASK))
+ return ecc_count;
+
+ /* Read OOB without ECC unit enabled */
+ vf610_nfc_command(mtd, NAND_CMD_READOOB, 0, page);
+ vf610_nfc_read_buf(mtd, oob, mtd->oobsize);
+
+ /*
+ * On an erased page, bit count (including OOB) should be zero or
+ * at least less then half of the ECC strength.
+ */
+ return nand_check_erased_ecc_chunk(dat, nfc->chip.ecc.size, oob,
+ mtd->oobsize, NULL, 0,
+ flips_threshold);
+}
+
+static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ int eccsize = chip->ecc.size;
+ int stat;
+
+ vf610_nfc_read_buf(mtd, buf, eccsize);
+ if (oob_required)
+ vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ stat = vf610_nfc_correct_data(mtd, buf, chip->oob_poi, page);
+
+ if (stat < 0) {
+ mtd->ecc_stats.failed++;
+ return 0;
+ } else {
+ mtd->ecc_stats.corrected += stat;
+ return stat;
+ }
+}
+
+static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required, int page)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+ vf610_nfc_write_buf(mtd, buf, mtd->writesize);
+ if (oob_required)
+ vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ /* Always write whole page including OOB due to HW ECC */
+ nfc->use_hw_ecc = true;
+ nfc->write_sz = mtd->writesize + mtd->oobsize;
+
+ return 0;
+}
+
+static const struct of_device_id vf610_nfc_dt_ids[] = {
+ { .compatible = "fsl,vf610-nfc", .data = (void *)NFC_VFC610 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vf610_nfc_dt_ids);
+
+static void vf610_nfc_preinit_controller(struct vf610_nfc *nfc)
+{
+ vf610_nfc_clear(nfc, NFC_FLASH_CONFIG, CONFIG_16BIT);
+ vf610_nfc_clear(nfc, NFC_FLASH_CONFIG, CONFIG_ADDR_AUTO_INCR_BIT);
+ vf610_nfc_clear(nfc, NFC_FLASH_CONFIG, CONFIG_BUFNO_AUTO_INCR_BIT);
+ vf610_nfc_clear(nfc, NFC_FLASH_CONFIG, CONFIG_BOOT_MODE_BIT);
+ vf610_nfc_clear(nfc, NFC_FLASH_CONFIG, CONFIG_DMA_REQ_BIT);
+ vf610_nfc_set(nfc, NFC_FLASH_CONFIG, CONFIG_FAST_FLASH_BIT);
+
+ /* Disable virtual pages, only one elementary transfer unit */
+ vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG, CONFIG_PAGE_CNT_MASK,
+ CONFIG_PAGE_CNT_SHIFT, 1);
+}
+
+static void vf610_nfc_init_controller(struct vf610_nfc *nfc)
+{
+ if (nfc->chip.options & NAND_BUSWIDTH_16)
+ vf610_nfc_set(nfc, NFC_FLASH_CONFIG, CONFIG_16BIT);
+ else
+ vf610_nfc_clear(nfc, NFC_FLASH_CONFIG, CONFIG_16BIT);
+
+ if (nfc->chip.ecc.mode == NAND_ECC_HW) {
+ /* Set ECC status offset in SRAM */
+ vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG,
+ CONFIG_ECC_SRAM_ADDR_MASK,
+ CONFIG_ECC_SRAM_ADDR_SHIFT,
+ ECC_SRAM_ADDR >> 3);
+
+ /* Enable ECC status in SRAM */
+ vf610_nfc_set(nfc, NFC_FLASH_CONFIG, CONFIG_ECC_SRAM_REQ_BIT);
+ }
+}
+
+static int vf610_nfc_probe(struct platform_device *pdev)
+{
+ struct vf610_nfc *nfc;
+ struct resource *res;
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ struct device_node *child;
+ const struct of_device_id *of_id;
+ int err;
+ int irq;
+
+ nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+ if (!nfc)
+ return -ENOMEM;
+
+ nfc->dev = &pdev->dev;
+ mtd = &nfc->mtd;
+ chip = &nfc->chip;
+
+ mtd->priv = chip;
+ mtd->owner = THIS_MODULE;
+ mtd->dev.parent = nfc->dev;
+ mtd->name = DRV_NAME;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ nfc->regs = devm_ioremap_resource(nfc->dev, res);
+ if (IS_ERR(nfc->regs))
+ return PTR_ERR(nfc->regs);
+
+ nfc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(nfc->clk))
+ return PTR_ERR(nfc->clk);
+
+ err = clk_prepare_enable(nfc->clk);
+ if (err) {
+ dev_err(nfc->dev, "Unable to enable clock!\n");
+ return err;
+ }
+
+ of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev);
+ nfc->variant = (enum vf610_nfc_variant)of_id->data;
+
+ for_each_available_child_of_node(nfc->dev->of_node, child) {
+ if (of_device_is_compatible(child, "fsl,vf610-nfc-nandcs")) {
+
+ if (chip->flash_node) {
+ dev_err(nfc->dev,
+ "Only one NAND chip supported!\n");
+ err = -EINVAL;
+ goto error;
+ }
+
+ chip->flash_node = child;
+ }
+ }
+
+ if (!chip->flash_node) {
+ dev_err(nfc->dev, "NAND chip sub-node missing!\n");
+ err = -ENODEV;
+ goto err_clk;
+ }
+
+ chip->dev_ready = vf610_nfc_dev_ready;
+ chip->cmdfunc = vf610_nfc_command;
+ chip->read_byte = vf610_nfc_read_byte;
+ chip->read_word = vf610_nfc_read_word;
+ chip->read_buf = vf610_nfc_read_buf;
+ chip->write_buf = vf610_nfc_write_buf;
+ chip->select_chip = vf610_nfc_select_chip;
+
+ chip->options |= NAND_NO_SUBPAGE_WRITE;
+
+ init_completion(&nfc->cmd_done);
+
+ err = devm_request_irq(nfc->dev, irq, vf610_nfc_irq, 0, DRV_NAME, mtd);
+ if (err) {
+ dev_err(nfc->dev, "Error requesting IRQ!\n");
+ goto error;
+ }
+
+ vf610_nfc_preinit_controller(nfc);
+
+ /* first scan to find the device and get the page size */
+ if (nand_scan_ident(mtd, 1, NULL)) {
+ err = -ENXIO;
+ goto error;
+ }
+
+ vf610_nfc_init_controller(nfc);
+
+ /* Bad block options. */
+ if (chip->bbt_options & NAND_BBT_USE_FLASH)
+ chip->bbt_options |= NAND_BBT_NO_OOB;
+
+ /* Single buffer only, max 256 OOB minus ECC status */
+ if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
+ dev_err(nfc->dev, "Unsupported flash page size\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ if (chip->ecc.mode == NAND_ECC_HW) {
+ if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
+ dev_err(nfc->dev, "Unsupported flash with hwecc\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ if (chip->ecc.size != mtd->writesize) {
+ dev_err(nfc->dev, "Step size needs to be page size\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ /* Only 64 byte ECC layouts known */
+ if (mtd->oobsize > 64)
+ mtd->oobsize = 64;
+
+ if (chip->ecc.strength == 32) {
+ nfc->ecc_mode = ECC_60_BYTE;
+ chip->ecc.bytes = 60;
+ chip->ecc.layout = &vf610_nfc_ecc60;
+ } else if (chip->ecc.strength == 24) {
+ nfc->ecc_mode = ECC_45_BYTE;
+ chip->ecc.bytes = 45;
+ chip->ecc.layout = &vf610_nfc_ecc45;
+ } else {
+ dev_err(nfc->dev, "Unsupported ECC strength\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ /* propagate ecc.layout to mtd_info */
+ mtd->ecclayout = chip->ecc.layout;
+ chip->ecc.read_page = vf610_nfc_read_page;
+ chip->ecc.write_page = vf610_nfc_write_page;
+
+ chip->ecc.size = PAGE_2K;
+ }
+
+ /* second phase scan */
+ if (nand_scan_tail(mtd)) {
+ err = -ENXIO;
+ goto error;
+ }
+
+ platform_set_drvdata(pdev, mtd);
+
+ /* Register device in MTD */
+ return mtd_device_parse_register(mtd, NULL,
+ &(struct mtd_part_parser_data){
+ .of_node = chip->flash_node,
+ },
+ NULL, 0);
+
+error:
+ of_node_put(chip->flash_node);
+err_clk:
+ clk_disable_unprepare(nfc->clk);
+ return err;
+}
+
+static int vf610_nfc_remove(struct platform_device *pdev)
+{
+ struct mtd_info *mtd = platform_get_drvdata(pdev);
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+ nand_release(mtd);
+ clk_disable_unprepare(nfc->clk);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int vf610_nfc_suspend(struct device *dev)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+ clk_disable_unprepare(nfc->clk);
+ return 0;
+}
+
+static int vf610_nfc_resume(struct device *dev)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+ pinctrl_pm_select_default_state(dev);
+
+ clk_prepare_enable(nfc->clk);
+
+ vf610_nfc_preinit_controller(nfc);
+ vf610_nfc_init_controller(nfc);
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(vf610_nfc_pm_ops, vf610_nfc_suspend, vf610_nfc_resume);
+
+static struct platform_driver vf610_nfc_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = vf610_nfc_dt_ids,
+ .pm = &vf610_nfc_pm_ops,
+ },
+ .probe = vf610_nfc_probe,
+ .remove = vf610_nfc_remove,
+};
+
+module_platform_driver(vf610_nfc_driver);
+
+MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>");
+MODULE_DESCRIPTION("Freescale VF610/MPC5125 NFC MTD NAND driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index aa26c32e1bc2..669c3452f278 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -29,23 +29,33 @@ static int parse_ofpart_partitions(struct mtd_info *master,
struct mtd_partition **pparts,
struct mtd_part_parser_data *data)
{
- struct device_node *node;
+ struct device_node *mtd_node;
+ struct device_node *ofpart_node;
const char *partname;
struct device_node *pp;
- int nr_parts, i;
+ int nr_parts, i, ret = 0;
+ bool dedicated = true;
if (!data)
return 0;
- node = data->of_node;
- if (!node)
+ mtd_node = data->of_node;
+ if (!mtd_node)
return 0;
+ ofpart_node = of_get_child_by_name(mtd_node, "partitions");
+ if (!ofpart_node) {
+ pr_warn("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n",
+ master->name, mtd_node->full_name);
+ ofpart_node = mtd_node;
+ dedicated = false;
+ }
+
/* First count the subnodes */
nr_parts = 0;
- for_each_child_of_node(node, pp) {
- if (node_has_compatible(pp))
+ for_each_child_of_node(ofpart_node, pp) {
+ if (!dedicated && node_has_compatible(pp))
continue;
nr_parts++;
@@ -59,22 +69,36 @@ static int parse_ofpart_partitions(struct mtd_info *master,
return -ENOMEM;
i = 0;
- for_each_child_of_node(node, pp) {
+ for_each_child_of_node(ofpart_node, pp) {
const __be32 *reg;
int len;
int a_cells, s_cells;
- if (node_has_compatible(pp))
+ if (!dedicated && node_has_compatible(pp))
continue;
reg = of_get_property(pp, "reg", &len);
if (!reg) {
- nr_parts--;
- continue;
+ if (dedicated) {
+ pr_debug("%s: ofpart partition %s (%s) missing reg property.\n",
+ master->name, pp->full_name,
+ mtd_node->full_name);
+ goto ofpart_fail;
+ } else {
+ nr_parts--;
+ continue;
+ }
}
a_cells = of_n_addr_cells(pp);
s_cells = of_n_size_cells(pp);
+ if (len / 4 != a_cells + s_cells) {
+ pr_debug("%s: ofpart partition %s (%s) error parsing reg property.\n",
+ master->name, pp->full_name,
+ mtd_node->full_name);
+ goto ofpart_fail;
+ }
+
(*pparts)[i].offset = of_read_number(reg, a_cells);
(*pparts)[i].size = of_read_number(reg + a_cells, s_cells);
@@ -92,15 +116,20 @@ static int parse_ofpart_partitions(struct mtd_info *master,
i++;
}
- if (!i) {
- of_node_put(pp);
- pr_err("No valid partition found on %s\n", node->full_name);
- kfree(*pparts);
- *pparts = NULL;
- return -EINVAL;
- }
+ if (!nr_parts)
+ goto ofpart_none;
return nr_parts;
+
+ofpart_fail:
+ pr_err("%s: error parsing ofpart partition %s (%s)\n",
+ master->name, pp->full_name, mtd_node->full_name);
+ ret = -EINVAL;
+ofpart_none:
+ of_node_put(pp);
+ kfree(*pparts);
+ *pparts = NULL;
+ return ret;
}
static struct mtd_part_parser ofpart_parser = {
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index ab7bda0bb245..125da34d8ff9 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -60,9 +60,8 @@ static int generic_onenand_probe(struct platform_device *pdev)
info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL;
info->onenand.irq = platform_get_irq(pdev, 0);
- info->mtd.name = dev_name(&pdev->dev);
+ info->mtd.dev.parent = &pdev->dev;
info->mtd.priv = &info->onenand;
- info->mtd.owner = THIS_MODULE;
if (onenand_scan(&info->mtd, 1)) {
err = -ENXIO;
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 646ddd6db1b4..3e0285696227 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -710,9 +710,7 @@ static int omap2_onenand_probe(struct platform_device *pdev)
c->onenand.base, c->freq);
c->pdev = pdev;
- c->mtd.name = dev_name(&pdev->dev);
c->mtd.priv = &c->onenand;
- c->mtd.owner = THIS_MODULE;
c->mtd.dev.parent = &pdev->dev;
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 739259513055..af0ac1a7bf8f 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -864,7 +864,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
this = (struct onenand_chip *) &mtd[1];
mtd->priv = this;
mtd->dev.parent = &pdev->dev;
- mtd->owner = THIS_MODULE;
onenand->pdev = pdev;
onenand->type = platform_get_device_id(pdev)->driver_data;
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89bf4c1faa2b..2fe2a7e90fa9 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -23,7 +23,8 @@ config MTD_SPI_NOR_USE_4K_SECTORS
config SPI_FSL_QUADSPI
tristate "Freescale Quad SPI controller"
- depends on ARCH_MXC
+ depends on ARCH_MXC || 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
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
index d32b7e04ccca..7b10ed413983 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -28,6 +28,7 @@
#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)
@@ -154,15 +155,15 @@
#define LUT_MODE 4
#define LUT_MODE2 5
#define LUT_MODE4 6
-#define LUT_READ 7
-#define LUT_WRITE 8
+#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_READ_DDR 14
-#define LUT_WRITE_DDR 15
+#define LUT_FSL_READ_DDR 14
+#define LUT_FSL_WRITE_DDR 15
#define LUT_DATA_LEARN 16
/*
@@ -259,7 +260,6 @@ static struct fsl_qspi_devtype_data imx6ul_data = {
#define FSL_QSPI_MAX_CHIP 4
struct fsl_qspi {
- struct mtd_info mtd[FSL_QSPI_MAX_CHIP];
struct spi_nor nor[FSL_QSPI_MAX_CHIP];
void __iomem *iobase;
void __iomem *ahb_addr;
@@ -366,7 +366,7 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
- writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD4, rxfifo),
+ writel(LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo),
base + QUADSPI_LUT(lut_base + 1));
/* Write enable */
@@ -387,11 +387,11 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
- writel(LUT0(WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1));
+ writel(LUT0(FSL_WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1));
/* Read Status */
lut_base = SEQID_RDSR * 4;
- writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(READ, PAD1, 0x1),
+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(FSL_READ, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
/* Erase a sector */
@@ -410,17 +410,17 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
/* READ ID */
lut_base = SEQID_RDID * 4;
- writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(READ, PAD1, 0x8),
+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(FSL_READ, PAD1, 0x8),
base + QUADSPI_LUT(lut_base));
/* Write Register */
lut_base = SEQID_WRSR * 4;
- writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(WRITE, PAD1, 0x2),
+ writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(FSL_WRITE, PAD1, 0x2),
base + QUADSPI_LUT(lut_base));
/* Read Configuration Register */
lut_base = SEQID_RDCR * 4;
- writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(READ, PAD1, 0x1),
+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(FSL_READ, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
/* Write disable */
@@ -798,8 +798,7 @@ static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
return 0;
}
-static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
- int write_enable)
+static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
{
struct fsl_qspi *q = nor->priv;
int ret;
@@ -870,7 +869,7 @@ static int fsl_qspi_read(struct spi_nor *nor, loff_t from,
}
}
- dev_dbg(q->dev, "cmd [%x],read from 0x%p, len:%d\n",
+ 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);
@@ -888,7 +887,7 @@ static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs)
int ret;
dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n",
- nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs);
+ nor->mtd.erasesize / 1024, q->chip_base_addr, (u32)offs);
ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0);
if (ret)
@@ -1006,19 +1005,16 @@ static int fsl_qspi_probe(struct platform_device *pdev)
/* iterate the subnodes. */
for_each_available_child_of_node(dev->of_node, np) {
- char modalias[40];
-
/* skip the holes */
if (!q->has_second_chip)
i *= 2;
nor = &q->nor[i];
- mtd = &q->mtd[i];
+ mtd = &nor->mtd;
- nor->mtd = mtd;
nor->dev = dev;
+ nor->flash_node = np;
nor->priv = q;
- mtd->priv = nor;
/* fill the hooks */
nor->read_reg = fsl_qspi_read_reg;
@@ -1030,10 +1026,6 @@ static int fsl_qspi_probe(struct platform_device *pdev)
nor->prepare = fsl_qspi_prep;
nor->unprepare = fsl_qspi_unprep;
- ret = of_modalias_node(np, modalias, sizeof(modalias));
- if (ret < 0)
- goto mutex_failed;
-
ret = of_property_read_u32(np, "spi-max-frequency",
&q->clk_rate);
if (ret < 0)
@@ -1042,7 +1034,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
/* set the chip address for READID */
fsl_qspi_set_base_addr(q, nor);
- ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD);
+ ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
if (ret)
goto mutex_failed;
@@ -1087,7 +1079,7 @@ last_init_failed:
/* skip the holes */
if (!q->has_second_chip)
i *= 2;
- mtd_device_unregister(&q->mtd[i]);
+ mtd_device_unregister(&q->nor[i].mtd);
}
mutex_failed:
mutex_destroy(&q->lock);
@@ -1107,7 +1099,7 @@ static int fsl_qspi_remove(struct platform_device *pdev)
/* skip the holes */
if (!q->has_second_chip)
i *= 2;
- mtd_device_unregister(&q->mtd[i]);
+ mtd_device_unregister(&q->nor[i].mtd);
}
/* disable the hardware */
diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c
index 9ad1dd0896c0..9e82098ae644 100644
--- a/drivers/mtd/spi-nor/nxp-spifi.c
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
@@ -60,7 +60,6 @@ struct nxp_spifi {
struct clk *clk_reg;
void __iomem *io_base;
void __iomem *flash_base;
- struct mtd_info mtd;
struct spi_nor nor;
bool memory_mode;
u32 mcmd;
@@ -150,8 +149,7 @@ static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
return nxp_spifi_wait_for_cmd(spifi);
}
-static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
- int len, int write_enable)
+static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
{
struct nxp_spifi *spifi = nor->priv;
u32 cmd;
@@ -331,9 +329,8 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
writel(ctrl, spifi->io_base + SPIFI_CTRL);
- spifi->mtd.priv = &spifi->nor;
- spifi->nor.mtd = &spifi->mtd;
spifi->nor.dev = spifi->dev;
+ spifi->nor.flash_node = np;
spifi->nor.priv = spifi;
spifi->nor.read = nxp_spifi_read;
spifi->nor.write = nxp_spifi_write;
@@ -365,7 +362,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
}
ppdata.of_node = np;
- ret = mtd_device_parse_register(&spifi->mtd, NULL, &ppdata, NULL, 0);
+ ret = mtd_device_parse_register(&spifi->nor.mtd, NULL, &ppdata, NULL, 0);
if (ret) {
dev_err(spifi->dev, "mtd device parse failed\n");
return ret;
@@ -454,7 +451,7 @@ static int nxp_spifi_remove(struct platform_device *pdev)
{
struct nxp_spifi *spifi = platform_get_drvdata(pdev);
- mtd_device_unregister(&spifi->mtd);
+ mtd_device_unregister(&spifi->nor.mtd);
clk_disable_unprepare(spifi->clk_spifi);
clk_disable_unprepare(spifi->clk_reg);
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index f59aedfe1462..49883905a434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -16,15 +16,26 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/math64.h>
+#include <linux/sizes.h>
-#include <linux/mtd/cfi.h>
#include <linux/mtd/mtd.h>
#include <linux/of_platform.h>
#include <linux/spi/flash.h>
#include <linux/mtd/spi-nor.h>
/* Define max times to check status register before we give up. */
-#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
+
+/*
+ * For everything but full-chip erase; probably could be much smaller, but kept
+ * around for safety for now
+ */
+#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ)
+
+/*
+ * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up
+ * for larger flash
+ */
+#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ)
#define SPI_NOR_MAX_ID_LEN 6
@@ -145,7 +156,7 @@ static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
static inline int write_sr(struct spi_nor *nor, u8 val)
{
nor->cmd_buf[0] = val;
- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0);
+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1);
}
/*
@@ -154,7 +165,7 @@ static inline int write_sr(struct spi_nor *nor, u8 val)
*/
static inline int write_enable(struct spi_nor *nor)
{
- return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0);
+ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
}
/*
@@ -162,7 +173,7 @@ static inline int write_enable(struct spi_nor *nor)
*/
static inline int write_disable(struct spi_nor *nor)
{
- return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
+ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0);
}
static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
@@ -179,16 +190,16 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
u8 cmd;
switch (JEDEC_MFR(info)) {
- case CFI_MFR_ST: /* Micron, actually */
+ case SNOR_MFR_MICRON:
/* Some Micron need WREN command; all will accept it */
need_wren = true;
- case CFI_MFR_MACRONIX:
- case 0xEF /* winbond */:
+ case SNOR_MFR_MACRONIX:
+ case SNOR_MFR_WINBOND:
if (need_wren)
write_enable(nor);
cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
- status = nor->write_reg(nor, cmd, NULL, 0, 0);
+ status = nor->write_reg(nor, cmd, NULL, 0);
if (need_wren)
write_disable(nor);
@@ -196,7 +207,7 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
default:
/* Spansion style */
nor->cmd_buf[0] = enable << 7;
- return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0);
+ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1);
}
}
static inline int spi_nor_sr_ready(struct spi_nor *nor)
@@ -233,12 +244,13 @@ static int spi_nor_ready(struct spi_nor *nor)
* Service routine to read status register until ready, or timeout occurs.
* Returns non-zero if error.
*/
-static int spi_nor_wait_till_ready(struct spi_nor *nor)
+static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
+ unsigned long timeout_jiffies)
{
unsigned long deadline;
int timeout = 0, ret;
- deadline = jiffies + MAX_READY_WAIT_JIFFIES;
+ deadline = jiffies + timeout_jiffies;
while (!timeout) {
if (time_after_eq(jiffies, deadline))
@@ -258,6 +270,12 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
return -ETIMEDOUT;
}
+static int spi_nor_wait_till_ready(struct spi_nor *nor)
+{
+ return spi_nor_wait_till_ready_with_timeout(nor,
+ DEFAULT_READY_WAIT_JIFFIES);
+}
+
/*
* Erase the whole flash memory
*
@@ -265,9 +283,9 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
*/
static int erase_chip(struct spi_nor *nor)
{
- dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10));
+ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
- return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0);
+ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
}
static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops)
@@ -321,6 +339,8 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
/* whole-chip erase? */
if (len == mtd->size) {
+ unsigned long timeout;
+
write_enable(nor);
if (erase_chip(nor)) {
@@ -328,7 +348,16 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
goto erase_err;
}
- ret = spi_nor_wait_till_ready(nor);
+ /*
+ * Scale the timeout linearly with the size of the flash, with
+ * a minimum calibrated to an old 2MB flash. We could try to
+ * pull these from CFI/SFDP, but these values should be good
+ * enough for now.
+ */
+ timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES,
+ CHIP_ERASE_2MB_READY_WAIT_JIFFIES *
+ (unsigned long)(mtd->size / SZ_2M));
+ ret = spi_nor_wait_till_ready_with_timeout(nor, timeout);
if (ret)
goto erase_err;
@@ -371,72 +400,171 @@ erase_err:
return ret;
}
+static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
+ uint64_t *len)
+{
+ struct mtd_info *mtd = &nor->mtd;
+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+ int shift = ffs(mask) - 1;
+ int pow;
+
+ if (!(sr & mask)) {
+ /* No protection */
+ *ofs = 0;
+ *len = 0;
+ } else {
+ pow = ((sr & mask) ^ mask) >> shift;
+ *len = mtd->size >> pow;
+ *ofs = mtd->size - *len;
+ }
+}
+
+/*
+ * Return 1 if the entire region is locked, 0 otherwise
+ */
+static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
+ u8 sr)
+{
+ loff_t lock_offs;
+ uint64_t lock_len;
+
+ stm_get_locked_range(nor, sr, &lock_offs, &lock_len);
+
+ return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs);
+}
+
+/*
+ * Lock a region of the flash. Compatible with ST Micro and similar flash.
+ * Supports only the block protection bits BP{0,1,2} in the status register
+ * (SR). Does not support these features found in newer SR bitfields:
+ * - TB: top/bottom protect - only handle TB=0 (top protect)
+ * - SEC: sector/block protect - only handle SEC=0 (block protect)
+ * - CMP: complement protect - only support CMP=0 (range is not complemented)
+ *
+ * Sample table portion for 8MB flash (Winbond w25q64fw):
+ *
+ * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion
+ * --------------------------------------------------------------------------
+ * X | X | 0 | 0 | 0 | NONE | NONE
+ * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64
+ * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32
+ * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16
+ * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8
+ * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4
+ * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2
+ * X | X | 1 | 1 | 1 | 8 MB | ALL
+ *
+ * Returns negative on errors, 0 on success.
+ */
static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
- struct mtd_info *mtd = nor->mtd;
- uint32_t offset = ofs;
- uint8_t status_old, status_new;
- int ret = 0;
+ struct mtd_info *mtd = &nor->mtd;
+ u8 status_old, status_new;
+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+ u8 shift = ffs(mask) - 1, pow, val;
status_old = read_sr(nor);
- if (offset < mtd->size - (mtd->size / 2))
- status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0;
- else if (offset < mtd->size - (mtd->size / 4))
- status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
- else if (offset < mtd->size - (mtd->size / 8))
- status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
- else if (offset < mtd->size - (mtd->size / 16))
- status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
- else if (offset < mtd->size - (mtd->size / 32))
- status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
- else if (offset < mtd->size - (mtd->size / 64))
- status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
- else
- status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
+ /* SPI NOR always locks to the end */
+ if (ofs + len != mtd->size) {
+ /* Does combined region extend to end? */
+ if (!stm_is_locked_sr(nor, ofs + len, mtd->size - ofs - len,
+ status_old))
+ return -EINVAL;
+ len = mtd->size - ofs;
+ }
+
+ /*
+ * Need smallest pow such that:
+ *
+ * 1 / (2^pow) <= (len / size)
+ *
+ * so (assuming power-of-2 size) we do:
+ *
+ * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len))
+ */
+ pow = ilog2(mtd->size) - ilog2(len);
+ val = mask - (pow << shift);
+ if (val & ~mask)
+ return -EINVAL;
+ /* Don't "lock" with no region! */
+ if (!(val & mask))
+ return -EINVAL;
+
+ status_new = (status_old & ~mask) | val;
/* Only modify protection if it will not unlock other areas */
- if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) >
- (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
- write_enable(nor);
- ret = write_sr(nor, status_new);
- }
+ if ((status_new & mask) <= (status_old & mask))
+ return -EINVAL;
- return ret;
+ write_enable(nor);
+ return write_sr(nor, status_new);
}
+/*
+ * Unlock a region of the flash. See stm_lock() for more info
+ *
+ * Returns negative on errors, 0 on success.
+ */
static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
- struct mtd_info *mtd = nor->mtd;
- uint32_t offset = ofs;
+ struct mtd_info *mtd = &nor->mtd;
uint8_t status_old, status_new;
- int ret = 0;
+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+ u8 shift = ffs(mask) - 1, pow, val;
status_old = read_sr(nor);
- if (offset+len > mtd->size - (mtd->size / 64))
- status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0);
- else if (offset+len > mtd->size - (mtd->size / 32))
- status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
- else if (offset+len > mtd->size - (mtd->size / 16))
- status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
- else if (offset+len > mtd->size - (mtd->size / 8))
- status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
- else if (offset+len > mtd->size - (mtd->size / 4))
- status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
- else if (offset+len > mtd->size - (mtd->size / 2))
- status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
- else
- status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
+ /* Cannot unlock; would unlock larger region than requested */
+ if (stm_is_locked_sr(nor, status_old, ofs - mtd->erasesize,
+ mtd->erasesize))
+ return -EINVAL;
- /* Only modify protection if it will not lock other areas */
- if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) <
- (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
- write_enable(nor);
- ret = write_sr(nor, status_new);
+ /*
+ * Need largest pow such that:
+ *
+ * 1 / (2^pow) >= (len / size)
+ *
+ * so (assuming power-of-2 size) we do:
+ *
+ * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len))
+ */
+ pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len));
+ if (ofs + len == mtd->size) {
+ val = 0; /* fully unlocked */
+ } else {
+ val = mask - (pow << shift);
+ /* Some power-of-two sizes are not supported */
+ if (val & ~mask)
+ return -EINVAL;
}
- return ret;
+ status_new = (status_old & ~mask) | val;
+
+ /* Only modify protection if it will not lock other areas */
+ if ((status_new & mask) >= (status_old & mask))
+ return -EINVAL;
+
+ write_enable(nor);
+ return write_sr(nor, status_new);
+}
+
+/*
+ * Check if a region of the flash is (completely) locked. See stm_lock() for
+ * more info.
+ *
+ * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
+ * negative on errors.
+ */
+static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ int status;
+
+ status = read_sr(nor);
+ if (status < 0)
+ return status;
+
+ return stm_is_locked_sr(nor, ofs, len, status);
}
static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
@@ -469,6 +597,21 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
return ret;
}
+static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ int ret;
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
+ if (ret)
+ return ret;
+
+ ret = nor->flash_is_locked(nor, ofs, len);
+
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
+ return ret;
+}
+
/* Used when the "_ext_id" is two bytes at most */
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
.id = { \
@@ -585,6 +728,7 @@ static const struct flash_info spi_nor_ids[] = {
/* Micron */
{ "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
+ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
{ "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
{ "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
{ "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) },
@@ -618,12 +762,13 @@ static const struct flash_info spi_nor_ids[] = {
{ "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
{ "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
{ "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
- { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) },
+ { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
{ "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
{ "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K) },
+ { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) },
/* SST -- large erase sizes are "overlays", "sectors" are 4K */
{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
@@ -635,6 +780,7 @@ static const struct flash_info spi_nor_ids[] = {
{ "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) },
{ "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) },
{ "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) },
+ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
{ "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
{ "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
@@ -683,10 +829,11 @@ static const struct flash_info spi_nor_ids[] = {
{ "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
{ "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
{ "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) },
+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K) },
+ { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
@@ -868,8 +1015,7 @@ static int macronix_quad_enable(struct spi_nor *nor)
val = read_sr(nor);
write_enable(nor);
- nor->cmd_buf[0] = val | SR_QUAD_EN_MX;
- nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0);
+ write_sr(nor, val | SR_QUAD_EN_MX);
if (spi_nor_wait_till_ready(nor))
return 1;
@@ -894,7 +1040,7 @@ static int write_sr_cr(struct spi_nor *nor, u16 val)
nor->cmd_buf[0] = val & 0xff;
nor->cmd_buf[1] = (val >> 8);
- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0);
+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
}
static int spansion_quad_enable(struct spi_nor *nor)
@@ -936,7 +1082,7 @@ static int micron_quad_enable(struct spi_nor *nor)
/* set EVCR, enable quad I/O */
nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON;
- ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0);
+ ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1);
if (ret < 0) {
dev_err(nor->dev, "error while writing EVCR register\n");
return ret;
@@ -965,14 +1111,14 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
int status;
switch (JEDEC_MFR(info)) {
- case CFI_MFR_MACRONIX:
+ case SNOR_MFR_MACRONIX:
status = macronix_quad_enable(nor);
if (status) {
dev_err(nor->dev, "Macronix quad-read not enabled\n");
return -EINVAL;
}
return status;
- case CFI_MFR_ST:
+ case SNOR_MFR_MICRON:
status = micron_quad_enable(nor);
if (status) {
dev_err(nor->dev, "Micron quad-read not enabled\n");
@@ -1004,8 +1150,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
{
const struct flash_info *info = NULL;
struct device *dev = nor->dev;
- struct mtd_info *mtd = nor->mtd;
- struct device_node *np = dev->of_node;
+ struct mtd_info *mtd = &nor->mtd;
+ struct device_node *np = nor->flash_node;
int ret;
int i;
@@ -1048,19 +1194,21 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
mutex_init(&nor->lock);
/*
- * Atmel, SST and Intel/Numonyx serial nor tend to power
- * up with the software protection bits set
+ * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
+ * with the software protection bits set
*/
- if (JEDEC_MFR(info) == CFI_MFR_ATMEL ||
- JEDEC_MFR(info) == CFI_MFR_INTEL ||
- JEDEC_MFR(info) == CFI_MFR_SST) {
+ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
+ JEDEC_MFR(info) == SNOR_MFR_INTEL ||
+ JEDEC_MFR(info) == SNOR_MFR_SST ||
+ JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
write_enable(nor);
write_sr(nor, 0);
}
if (!mtd->name)
mtd->name = dev_name(dev);
+ mtd->priv = nor;
mtd->type = MTD_NORFLASH;
mtd->writesize = 1;
mtd->flags = MTD_CAP_NORFLASH;
@@ -1068,15 +1216,18 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
mtd->_erase = spi_nor_erase;
mtd->_read = spi_nor_read;
- /* nor protection support for STmicro chips */
- if (JEDEC_MFR(info) == CFI_MFR_ST) {
+ /* NOR protection support for STmicro/Micron chips and similar */
+ if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
+ JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
nor->flash_lock = stm_lock;
nor->flash_unlock = stm_unlock;
+ nor->flash_is_locked = stm_is_locked;
}
- if (nor->flash_lock && nor->flash_unlock) {
+ if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) {
mtd->_lock = spi_nor_lock;
mtd->_unlock = spi_nor_unlock;
+ mtd->_is_locked = spi_nor_is_locked;
}
/* sst nor chips use AAI word program */
@@ -1163,7 +1314,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
else if (mtd->size > 0x1000000) {
/* enable 4-byte addressing if the device exceeds 16MiB */
nor->addr_width = 4;
- if (JEDEC_MFR(info) == CFI_MFR_AMD) {
+ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
/* Dedicated 4-byte command set */
switch (nor->flash_read) {
case SPI_NOR_QUAD:
diff --git a/drivers/mtd/tests/speedtest.c b/drivers/mtd/tests/speedtest.c
index 5a6f31af06f9..0b89418a0888 100644
--- a/drivers/mtd/tests/speedtest.c
+++ b/drivers/mtd/tests/speedtest.c
@@ -22,6 +22,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/err.h>
@@ -49,7 +50,7 @@ static int pgsize;
static int ebcnt;
static int pgcnt;
static int goodebcnt;
-static struct timeval start, finish;
+static ktime_t start, finish;
static int multiblock_erase(int ebnum, int blocks)
{
@@ -168,12 +169,12 @@ static int read_eraseblock_by_2pages(int ebnum)
static inline void start_timing(void)
{
- do_gettimeofday(&start);
+ start = ktime_get();
}
static inline void stop_timing(void)
{
- do_gettimeofday(&finish);
+ finish = ktime_get();
}
static long calc_speed(void)
@@ -181,8 +182,7 @@ static long calc_speed(void)
uint64_t k;
long ms;
- ms = (finish.tv_sec - start.tv_sec) * 1000 +
- (finish.tv_usec - start.tv_usec) / 1000;
+ ms = ktime_ms_delta(finish, start);
if (ms == 0)
return 0;
k = (uint64_t)goodebcnt * (mtd->erasesize / 1024) * 1000;
diff --git a/drivers/mtd/tests/torturetest.c b/drivers/mtd/tests/torturetest.c
index e5d6e6d9532f..93c2729c47b8 100644
--- a/drivers/mtd/tests/torturetest.c
+++ b/drivers/mtd/tests/torturetest.c
@@ -26,6 +26,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/err.h>
@@ -79,18 +80,18 @@ static unsigned char *check_buf;
static unsigned int erase_cycles;
static int pgsize;
-static struct timeval start, finish;
+static ktime_t start, finish;
static void report_corrupt(unsigned char *read, unsigned char *written);
static inline void start_timing(void)
{
- do_gettimeofday(&start);
+ start = ktime_get();
}
static inline void stop_timing(void)
{
- do_gettimeofday(&finish);
+ finish = ktime_get();
}
/*
@@ -333,8 +334,7 @@ static int __init tort_init(void)
long ms;
stop_timing();
- ms = (finish.tv_sec - start.tv_sec) * 1000 +
- (finish.tv_usec - start.tv_usec) / 1000;
+ ms = ktime_ms_delta(finish, start);
pr_info("%08u erase cycles done, took %lu "
"milliseconds (%lu seconds)\n",
erase_cycles, ms, ms / 1000);
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 68eea5befaf1..c1aaf0336cf2 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1209,9 +1209,7 @@ static void destroy_ai(struct ubi_attach_info *ai)
}
}
- if (ai->aeb_slab_cache)
- kmem_cache_destroy(ai->aeb_slab_cache);
-
+ kmem_cache_destroy(ai->aeb_slab_cache);
kfree(ai);
}
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index d16fccf79179..54e056d3be02 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -949,7 +949,7 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
if (!req) {
err = -ENOMEM;
break;
- };
+ }
err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req));
if (err) {
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 51bca035cd83..5b9834cf2820 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1358,7 +1358,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
continue;
ubi_err(ubi, "LEB:%i:%i is PEB:%i instead of %i!",
- vol->vol_id, i, fm_eba[i][j],
+ vol->vol_id, j, fm_eba[i][j],
scan_eba[i][j]);
ubi_assert(0);
}
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index b2a665398bca..30d3999dddba 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -172,6 +172,30 @@ void ubi_refill_pools(struct ubi_device *ubi)
}
/**
+ * produce_free_peb - produce a free physical eraseblock.
+ * @ubi: UBI device description object
+ *
+ * This function tries to make a free PEB by means of synchronous execution of
+ * pending works. This may be needed if, for example the background thread is
+ * disabled. Returns zero in case of success and a negative error code in case
+ * of failure.
+ */
+static int produce_free_peb(struct ubi_device *ubi)
+{
+ int err;
+
+ while (!ubi->free.rb_node && ubi->works_count) {
+ dbg_wl("do one work synchronously");
+ err = do_work(ubi);
+
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/**
* ubi_wl_get_peb - get a physical eraseblock.
* @ubi: UBI device description object
*
@@ -213,6 +237,11 @@ again:
}
retried = 1;
up_read(&ubi->fm_eba_sem);
+ ret = produce_free_peb(ubi);
+ if (ret < 0) {
+ down_read(&ubi->fm_eba_sem);
+ goto out;
+ }
goto again;
}
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 4aa2fd8633e7..263b439e21a8 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -450,7 +450,7 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum)
* < 0 indicates an internal error.
*/
static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
- int *pebs, int pool_size, unsigned long long *max_sqnum,
+ __be32 *pebs, int pool_size, unsigned long long *max_sqnum,
struct list_head *free)
{
struct ubi_vid_hdr *vh;
@@ -775,7 +775,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
for (j = 0; j < be32_to_cpu(fm_eba->reserved_pebs); j++) {
int pnum = be32_to_cpu(fm_eba->pnum[j]);
- if ((int)be32_to_cpu(fm_eba->pnum[j]) < 0)
+ if (pnum < 0)
continue;
aeb = NULL;
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index b93807b4c459..cb7c075f2144 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -112,8 +112,8 @@ static int gluebi_get_device(struct mtd_info *mtd)
* The MTD device is already referenced and this is just one
* more reference. MTD allows many users to open the same
* volume simultaneously and do not distinguish between
- * readers/writers/exclusive openers as UBI does. So we do not
- * open the UBI volume again - just increase the reference
+ * readers/writers/exclusive/meta openers as UBI does. So we do
+ * not open the UBI volume again - just increase the reference
* counter and return.
*/
gluebi->refcnt += 1;
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index d0d072e7ccd2..22ed3f627506 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -500,7 +500,7 @@ struct ubi_fm_volhdr {
/* struct ubi_fm_volhdr is followed by one struct ubi_fm_eba records */
/**
- * struct ubi_fm_eba - denotes an association beween a PEB and LEB
+ * struct ubi_fm_eba - denotes an association between a PEB and LEB
* @magic: EBA table magic number
* @reserved_pebs: number of table entries
* @pnum: PEB number of LEB (LEB is the index)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d18eb607bee6..f184fb5bd110 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -298,7 +298,10 @@ config NLMON
config NET_VRF
tristate "Virtual Routing and Forwarding (Lite)"
- depends on IP_MULTIPLE_TABLES && IPV6_MULTIPLE_TABLES
+ depends on IP_MULTIPLE_TABLES
+ depends on NET_L3_MASTER_DEV
+ depends on IPV6 || IPV6=n
+ depends on IPV6_MULTIPLE_TABLES || IPV6=n
---help---
This option enables the support for mapping interfaces into VRF's. The
support enables VRF devices.
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 2a9c3c3abe9b..39bd16f3f86d 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -103,6 +103,7 @@ config ARCNET_RIM_I
config ARCNET_COM20020
tristate "ARCnet COM20020 chipset driver"
+ depends on LEDS_CLASS
help
This is the driver for the new COM20020 chipset. It supports such
things as promiscuous mode, so packet sniffing is possible, and
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
index 705e6ce2eb90..d78f30186642 100644
--- a/drivers/net/arcnet/arc-rawmode.c
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - "raw mode" packet encapsulation (no soft headers)
- *
+ *
* Written 1994-1999 by Avery Pennarun.
* Derived from skeleton.c by Donald Becker.
*
@@ -24,6 +24,8 @@
* **********************
*/
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/init.h>
@@ -31,58 +33,7 @@
#include <net/arp.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
-#include <linux/arcdevice.h>
-
-#define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n"
-
-
-static void rx(struct net_device *dev, int bufnum,
- struct archdr *pkthdr, int length);
-static int build_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, uint8_t daddr);
-static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
- int bufnum);
-
-static struct ArcProto rawmode_proto =
-{
- .suffix = 'r',
- .mtu = XMTU,
- .rx = rx,
- .build_header = build_header,
- .prepare_tx = prepare_tx,
- .continue_tx = NULL,
- .ack_tx = NULL
-};
-
-
-static int __init arcnet_raw_init(void)
-{
- int count;
-
- printk(VERSION);
-
- for (count = 0; count < 256; count++)
- if (arc_proto_map[count] == arc_proto_default)
- arc_proto_map[count] = &rawmode_proto;
-
- /* for raw mode, we only set the bcast proto if there's no better one */
- if (arc_bcast_proto == arc_proto_default)
- arc_bcast_proto = &rawmode_proto;
-
- arc_proto_default = &rawmode_proto;
- return 0;
-}
-
-static void __exit arcnet_raw_exit(void)
-{
- arcnet_unregister_proto(&rawmode_proto);
-}
-
-module_init(arcnet_raw_init);
-module_exit(arcnet_raw_exit);
-
-MODULE_LICENSE("GPL");
-
+#include "arcdevice.h"
/* packet receiver */
static void rx(struct net_device *dev, int bufnum,
@@ -93,7 +44,7 @@ static void rx(struct net_device *dev, int bufnum,
struct archdr *pkt = pkthdr;
int ofs;
- BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
+ arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length);
if (length > MTU)
ofs = 512 - length;
@@ -101,15 +52,14 @@ static void rx(struct net_device *dev, int bufnum,
ofs = 256 - length;
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ if (!skb) {
dev->stats.rx_dropped++;
return;
}
skb_put(skb, length + ARC_HDR_SIZE);
skb->dev = dev;
- pkt = (struct archdr *) skb->data;
+ pkt = (struct archdr *)skb->data;
skb_reset_mac_header(skb);
skb_pull(skb, ARC_HDR_SIZE);
@@ -121,38 +71,35 @@ static void rx(struct net_device *dev, int bufnum,
pkt->soft.raw + sizeof(pkt->soft),
length - sizeof(pkt->soft));
- BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, skb, "rx");
skb->protocol = cpu_to_be16(ETH_P_ARCNET);
netif_rx(skb);
}
-
-/*
- * Create the ARCnet hard/soft headers for raw mode.
+/* Create the ARCnet hard/soft headers for raw mode.
* There aren't any soft headers in raw mode - not even the protocol id.
*/
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
int hdr_size = ARC_HDR_SIZE;
- struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
+ struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
- /*
- * Set the source hardware address.
+ /* Set the source hardware address.
*
* This is pretty pointless for most purposes, but it can help in
- * debugging. ARCnet does not allow us to change the source address in
- * the actual packet sent)
+ * debugging. ARCnet does not allow us to change the source address
+ * in the actual packet sent.
*/
pkt->hard.source = *dev->dev_addr;
/* see linux/net/ethernet/eth.c to see where I got the following */
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
- /*
- * FIXME: fill in the last byte of the dest ipaddr here to better
- * comply with RFC1051 in "noarp" mode.
+ /* FIXME: fill in the last byte of the dest ipaddr here
+ * to better comply with RFC1051 in "noarp" mode.
*/
pkt->hard.dest = 0;
return hdr_size;
@@ -163,7 +110,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
return hdr_size; /* success */
}
-
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
@@ -171,15 +117,16 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
struct arc_hardware *hard = &pkt->hard;
int ofs;
- BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
- lp->next_tx, lp->cur_tx, bufnum);
+ arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
+ lp->next_tx, lp->cur_tx, bufnum);
- length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
+ /* hard header is not included in packet length */
+ length -= ARC_HDR_SIZE;
if (length > XMTU) {
/* should never happen! other people already check for this. */
- BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
- length, XMTU);
+ arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n",
+ length, XMTU);
length = XMTU;
}
if (length >= MinTU) {
@@ -188,11 +135,12 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
} else if (length > MTU) {
hard->offset[0] = 0;
hard->offset[1] = ofs = 512 - length - 3;
- } else
+ } else {
hard->offset[0] = ofs = 256 - length;
+ }
- BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n",
- length,ofs);
+ arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n",
+ length, ofs);
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
@@ -201,3 +149,41 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
return 1; /* done */
}
+
+static struct ArcProto rawmode_proto = {
+ .suffix = 'r',
+ .mtu = XMTU,
+ .rx = rx,
+ .build_header = build_header,
+ .prepare_tx = prepare_tx,
+ .continue_tx = NULL,
+ .ack_tx = NULL
+};
+
+static int __init arcnet_raw_init(void)
+{
+ int count;
+
+ pr_info("raw mode (`r') encapsulation support loaded\n");
+
+ for (count = 0; count < 256; count++)
+ if (arc_proto_map[count] == arc_proto_default)
+ arc_proto_map[count] = &rawmode_proto;
+
+ /* for raw mode, we only set the bcast proto if there's no better one */
+ if (arc_bcast_proto == arc_proto_default)
+ arc_bcast_proto = &rawmode_proto;
+
+ arc_proto_default = &rawmode_proto;
+ return 0;
+}
+
+static void __exit arcnet_raw_exit(void)
+{
+ arcnet_unregister_proto(&rawmode_proto);
+}
+
+module_init(arcnet_raw_init);
+module_exit(arcnet_raw_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index b8b4c7ba884f..a07e24970be4 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards
- *
+ *
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
* Derived from skeleton.c by Donald Becker.
@@ -24,6 +24,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -33,12 +36,10 @@
#include <linux/bootmem.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <linux/arcdevice.h>
-
-
-#define VERSION "arcnet: RIM I (entirely mem-mapped) support\n"
+#include <linux/io.h>
+#include "arcdevice.h"
+#include "com9026.h"
/* Internal function declarations */
@@ -50,66 +51,46 @@ static void arcrimi_setmask(struct net_device *dev, int mask);
static int arcrimi_reset(struct net_device *dev, int really_reset);
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count);
-static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count);
+static void arcrimi_copy_from_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count);
/* Handy defines for ARCnet specific stuff */
/* Amount of I/O memory used by the card */
-#define BUFFER_SIZE (512)
-#define MIRROR_SIZE (BUFFER_SIZE*4)
+#define BUFFER_SIZE (512)
+#define MIRROR_SIZE (BUFFER_SIZE * 4)
-/* COM 9026 controller chip --> ARCnet register addresses */
-#define _INTMASK (ioaddr+0) /* writable */
-#define _STATUS (ioaddr+0) /* readable */
-#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
-#define _RESET (ioaddr+8) /* software reset (on read) */
-#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */
-#define _ADDR_HI (ioaddr+15) /* Control registers for said */
-#define _ADDR_LO (ioaddr+14)
-#define _CONFIG (ioaddr+2) /* Configuration register */
-
-#undef ASTATUS
-#undef ACOMMAND
-#undef AINTMASK
-
-#define ASTATUS() readb(_STATUS)
-#define ACOMMAND(cmd) writeb((cmd),_COMMAND)
-#define AINTMASK(msk) writeb((msk),_INTMASK)
-#define SETCONF() writeb(lp->config,_CONFIG)
-
-
-/*
- * We cannot probe for a RIM I card; one reason is I don't know how to reset
+/* We cannot probe for a RIM I card; one reason is I don't know how to reset
* them. In fact, we can't even get their node ID automatically. So, we
* need to be passed a specific shmem address, IRQ, and node ID.
*/
static int __init arcrimi_probe(struct net_device *dev)
{
- BUGLVL(D_NORMAL) printk(VERSION);
- BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n");
-
- BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n",
- dev->dev_addr[0], dev->mem_start, dev->irq);
+ if (BUGLVL(D_NORMAL)) {
+ pr_info("%s\n", "RIM I (entirely mem-mapped) support");
+ pr_info("E-mail me if you actually test the RIM I driver, please!\n");
+ pr_info("Given: node %02Xh, shmem %lXh, irq %d\n",
+ dev->dev_addr[0], dev->mem_start, dev->irq);
+ }
if (dev->mem_start <= 0 || dev->irq <= 0) {
- BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you "
- "must specify the shmem and irq!\n");
+ if (BUGLVL(D_NORMAL))
+ pr_err("No autoprobe for RIM I; you must specify the shmem and irq!\n");
return -ENODEV;
}
if (dev->dev_addr[0] == 0) {
- BUGLVL(D_NORMAL) printk("You need to specify your card's station "
- "ID!\n");
+ if (BUGLVL(D_NORMAL))
+ pr_err("You need to specify your card's station ID!\n");
return -ENODEV;
}
- /*
- * Grab the memory region at mem_start for MIRROR_SIZE bytes.
+ /* Grab the memory region at mem_start for MIRROR_SIZE bytes.
* Later in arcrimi_found() the real size will be determined
* and this reserve will be released and the correct size
* will be taken.
*/
if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
- BUGLVL(D_NORMAL) printk("Card memory already allocated\n");
+ if (BUGLVL(D_NORMAL))
+ pr_notice("Card memory already allocated\n");
return -ENODEV;
}
return arcrimi_found(dev);
@@ -125,7 +106,7 @@ static int check_mirror(unsigned long addr, size_t size)
p = ioremap(addr, size);
if (p) {
- if (readb(p) == TESTvalue)
+ if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
res = 1;
else
res = 0;
@@ -136,9 +117,8 @@ static int check_mirror(unsigned long addr, size_t size)
return res;
}
-/*
- * Set up the struct net_device associated with this card. Called after
- * probing succeeds.
+/* Set up the struct net_device associated with this card.
+ * Called after probing succeeds.
*/
static int __init arcrimi_found(struct net_device *dev)
{
@@ -151,7 +131,7 @@ static int __init arcrimi_found(struct net_device *dev)
p = ioremap(dev->mem_start, MIRROR_SIZE);
if (!p) {
release_mem_region(dev->mem_start, MIRROR_SIZE);
- BUGMSG(D_NORMAL, "Can't ioremap\n");
+ arc_printk(D_NORMAL, dev, "Can't ioremap\n");
return -ENODEV;
}
@@ -159,13 +139,14 @@ static int __init arcrimi_found(struct net_device *dev)
if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
iounmap(p);
release_mem_region(dev->mem_start, MIRROR_SIZE);
- BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
+ arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
shmem = dev->mem_start;
- writeb(TESTvalue, p);
- writeb(dev->dev_addr[0], p + 1); /* actually the node ID */
+ arcnet_writeb(TESTvalue, p, COM9026_REG_W_INTMASK);
+ arcnet_writeb(TESTvalue, p, COM9026_REG_W_COMMAND);
+ /* actually the station/node ID */
/* find the real shared memory start/end points, including mirrors */
@@ -174,7 +155,7 @@ static int __init arcrimi_found(struct net_device *dev)
* 2k (or there are no mirrors at all) but on some, it's 4k.
*/
mirror_size = MIRROR_SIZE;
- if (readb(p) == TESTvalue &&
+ if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue &&
check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
mirror_size = 2 * MIRROR_SIZE;
@@ -204,8 +185,7 @@ static int __init arcrimi_found(struct net_device *dev)
lp->hw.copy_to_card = arcrimi_copy_to_card;
lp->hw.copy_from_card = arcrimi_copy_from_card;
- /*
- * re-reserve the memory region - arcrimi_probe() alloced this reqion
+ /* re-reserve the memory region - arcrimi_probe() alloced this reqion
* but didn't know the real size. Free that region and then re-get
* with the correct size. There is a VERY slim chance this could
* fail.
@@ -215,24 +195,25 @@ static int __init arcrimi_found(struct net_device *dev)
if (!request_mem_region(dev->mem_start,
dev->mem_end - dev->mem_start + 1,
"arcnet (90xx)")) {
- BUGMSG(D_NORMAL, "Card memory already allocated\n");
+ arc_printk(D_NORMAL, dev, "Card memory already allocated\n");
goto err_free_irq;
}
- lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1);
+ lp->mem_start = ioremap(dev->mem_start,
+ dev->mem_end - dev->mem_start + 1);
if (!lp->mem_start) {
- BUGMSG(D_NORMAL, "Can't remap device memory!\n");
+ arc_printk(D_NORMAL, dev, "Can't remap device memory!\n");
goto err_release_mem;
}
/* get and check the station ID from offset 1 in shmem */
- dev->dev_addr[0] = readb(lp->mem_start + 1);
+ dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
- BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, "
- "ShMem %lXh (%ld*%d bytes).\n",
- dev->dev_addr[0],
- dev->irq, dev->mem_start,
- (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size);
+ arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n",
+ dev->dev_addr[0],
+ dev->irq, dev->mem_start,
+ (dev->mem_end - dev->mem_start + 1) / mirror_size,
+ mirror_size);
err = register_netdev(dev);
if (err)
@@ -249,9 +230,7 @@ err_free_irq:
return -EIO;
}
-
-/*
- * Do a hardware reset on the card, and set up necessary registers.
+/* Do a hardware reset on the card, and set up necessary registers.
*
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
@@ -263,17 +242,19 @@ static int arcrimi_reset(struct net_device *dev, int really_reset)
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
- BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
+ arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
+ dev->name, arcnet_readb(ioaddr, COM9026_REG_R_STATUS));
if (really_reset) {
- writeb(TESTvalue, ioaddr - 0x800); /* fake reset */
+ arcnet_writeb(TESTvalue, ioaddr, -0x800); /* fake reset */
return 0;
}
- ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
- ACOMMAND(CFLAGScmd | CONFIGclear);
+ /* clear flags & end reset */
+ arcnet_writeb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
+ arcnet_writeb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
/* enable extended (512-byte) packets */
- ACOMMAND(CONFIGcmd | EXTconf);
+ arcnet_writeb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
/* done! return success. */
return 0;
@@ -284,7 +265,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask)
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
- AINTMASK(mask);
+ arcnet_writeb(mask, ioaddr, COM9026_REG_W_INTMASK);
}
static int arcrimi_status(struct net_device *dev)
@@ -292,7 +273,7 @@ static int arcrimi_status(struct net_device *dev)
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
- return ASTATUS();
+ return arcnet_readb(ioaddr, COM9026_REG_R_STATUS);
}
static void arcrimi_command(struct net_device *dev, int cmd)
@@ -300,7 +281,7 @@ static void arcrimi_command(struct net_device *dev, int cmd)
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
- ACOMMAND(cmd);
+ arcnet_writeb(cmd, ioaddr, COM9026_REG_W_COMMAND);
}
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
@@ -308,16 +289,17 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
- TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
-}
+ TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count));
+}
-static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count)
+static void arcrimi_copy_from_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
- TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
+
+ TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
static int node;
@@ -374,12 +356,13 @@ static void __exit arc_rimi_exit(void)
static int __init arcrimi_setup(char *s)
{
int ints[8];
+
s = get_options(s, 8, ints);
if (!ints[0])
return 1;
switch (ints[0]) {
default: /* ERROR */
- printk("arcrimi: Too many arguments.\n");
+ pr_err("Too many arguments\n");
case 3: /* Node ID */
node = ints[3];
case 2: /* IRQ */
diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h
new file mode 100644
index 000000000000..20bfb9ba83ea
--- /dev/null
+++ b/drivers/net/arcnet/arcdevice.h
@@ -0,0 +1,389 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. NET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions used by the ARCnet driver.
+ *
+ * Authors: Avery Pennarun and David Woodhouse
+ *
+ * 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.
+ *
+ */
+#ifndef _LINUX_ARCDEVICE_H
+#define _LINUX_ARCDEVICE_H
+
+#include <asm/timex.h>
+#include <linux/if_arcnet.h>
+
+#ifdef __KERNEL__
+#include <linux/irqreturn.h>
+
+/*
+ * RECON_THRESHOLD is the maximum number of RECON messages to receive
+ * within one minute before printing a "cabling problem" warning. The
+ * default value should be fine.
+ *
+ * After that, a "cabling restored" message will be printed on the next IRQ
+ * if no RECON messages have been received for 10 seconds.
+ *
+ * Do not define RECON_THRESHOLD at all if you want to disable this feature.
+ */
+#define RECON_THRESHOLD 30
+
+/*
+ * Define this to the minimum "timeout" value. If a transmit takes longer
+ * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large
+ * network, or one with heavy network traffic, this timeout may need to be
+ * increased. The larger it is, though, the longer it will be between
+ * necessary transmits - don't set this too high.
+ */
+#define TX_TIMEOUT (HZ * 200 / 1000)
+
+/* Display warnings about the driver being an ALPHA version. */
+#undef ALPHA_WARNING
+
+/*
+ * Debugging bitflags: each option can be enabled individually.
+ *
+ * Note: only debug flags included in the ARCNET_DEBUG_MAX define will
+ * actually be available. GCC will (at least, GCC 2.7.0 will) notice
+ * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
+ * them out.
+ */
+#define D_NORMAL 1 /* important operational info */
+#define D_EXTRA 2 /* useful, but non-vital information */
+#define D_INIT 4 /* show init/probe messages */
+#define D_INIT_REASONS 8 /* show reasons for discarding probes */
+#define D_RECON 32 /* print a message whenever token is lost */
+#define D_PROTO 64 /* debug auto-protocol support */
+/* debug levels below give LOTS of output during normal operation! */
+#define D_DURING 128 /* trace operations (including irq's) */
+#define D_TX 256 /* show tx packets */
+#define D_RX 512 /* show rx packets */
+#define D_SKB 1024 /* show skb's */
+#define D_SKB_SIZE 2048 /* show skb sizes */
+#define D_TIMING 4096 /* show time needed to copy buffers to card */
+#define D_DEBUG 8192 /* Very detailed debug line for line */
+
+#ifndef ARCNET_DEBUG_MAX
+#define ARCNET_DEBUG_MAX (127) /* change to ~0 if you want detailed debugging */
+#endif
+
+#ifndef ARCNET_DEBUG
+#define ARCNET_DEBUG (D_NORMAL | D_EXTRA)
+#endif
+extern int arcnet_debug;
+
+#define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug)
+
+/* macros to simplify debug checking */
+#define arc_printk(x, dev, fmt, ...) \
+do { \
+ if (BUGLVL(x)) { \
+ if ((x) == D_NORMAL) \
+ netdev_warn(dev, fmt, ##__VA_ARGS__); \
+ else if ((x) < D_DURING) \
+ netdev_info(dev, fmt, ##__VA_ARGS__); \
+ else \
+ netdev_dbg(dev, fmt, ##__VA_ARGS__); \
+ } \
+} while (0)
+
+#define arc_cont(x, fmt, ...) \
+do { \
+ if (BUGLVL(x)) \
+ pr_cont(fmt, ##__VA_ARGS__); \
+} while (0)
+
+/* see how long a function call takes to run, expressed in CPU cycles */
+#define TIME(dev, name, bytes, call) \
+do { \
+ if (BUGLVL(D_TIMING)) { \
+ unsigned long _x, _y; \
+ _x = get_cycles(); \
+ call; \
+ _y = get_cycles(); \
+ arc_printk(D_TIMING, dev, \
+ "%s: %d bytes in %lu cycles == %lu Kbytes/100Mcycle\n", \
+ name, bytes, _y - _x, \
+ 100000000 / 1024 * bytes / (_y - _x + 1)); \
+ } else { \
+ call; \
+ } \
+} while (0)
+
+/*
+ * Time needed to reset the card - in ms (milliseconds). This works on my
+ * SMC PC100. I can't find a reference that tells me just how long I
+ * should wait.
+ */
+#define RESETtime (300)
+
+/*
+ * These are the max/min lengths of packet payload, not including the
+ * arc_hardware header, but definitely including the soft header.
+ *
+ * Note: packet sizes 254, 255, 256 are impossible because of the way
+ * ARCnet registers work That's why RFC1201 defines "exception" packets.
+ * In non-RFC1201 protocols, we have to just tack some extra bytes on the
+ * end.
+ */
+#define MTU 253 /* normal packet max size */
+#define MinTU 257 /* extended packet min size */
+#define XMTU 508 /* extended packet max size */
+
+/* status/interrupt mask bit fields */
+#define TXFREEflag 0x01 /* transmitter available */
+#define TXACKflag 0x02 /* transmitted msg. ackd */
+#define RECONflag 0x04 /* network reconfigured */
+#define TESTflag 0x08 /* test flag */
+#define EXCNAKflag 0x08 /* excesive nak flag */
+#define RESETflag 0x10 /* power-on-reset */
+#define RES1flag 0x20 /* reserved - usually set by jumper */
+#define RES2flag 0x40 /* reserved - usually set by jumper */
+#define NORXflag 0x80 /* receiver inhibited */
+
+/* Flags used for IO-mapped memory operations */
+#define AUTOINCflag 0x40 /* Increase location with each access */
+#define IOMAPflag 0x02 /* (for 90xx) Use IO mapped memory, not mmap */
+#define ENABLE16flag 0x80 /* (for 90xx) Enable 16-bit mode */
+
+/* in the command register, the following bits have these meanings:
+ * 0-2 command
+ * 3-4 page number (for enable rcv/xmt command)
+ * 7 receive broadcasts
+ */
+#define NOTXcmd 0x01 /* disable transmitter */
+#define NORXcmd 0x02 /* disable receiver */
+#define TXcmd 0x03 /* enable transmitter */
+#define RXcmd 0x04 /* enable receiver */
+#define CONFIGcmd 0x05 /* define configuration */
+#define CFLAGScmd 0x06 /* clear flags */
+#define TESTcmd 0x07 /* load test flags */
+#define STARTIOcmd 0x18 /* start internal operation */
+
+/* flags for "clear flags" command */
+#define RESETclear 0x08 /* power-on-reset */
+#define CONFIGclear 0x10 /* system reconfigured */
+
+#define EXCNAKclear 0x0E /* Clear and acknowledge the excive nak bit */
+
+/* flags for "load test flags" command */
+#define TESTload 0x08 /* test flag (diagnostic) */
+
+/* byte deposited into first address of buffers on reset */
+#define TESTvalue 0321 /* that's octal for 0xD1 :) */
+
+/* for "enable receiver" command */
+#define RXbcasts 0x80 /* receive broadcasts */
+
+/* flags for "define configuration" command */
+#define NORMALconf 0x00 /* 1-249 byte packets */
+#define EXTconf 0x08 /* 250-504 byte packets */
+
+/* card feature flags, set during auto-detection.
+ * (currently only used by com20020pci)
+ */
+#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */
+#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit,
+ but default is 2.5MBit. */
+
+/* information needed to define an encapsulation driver */
+struct ArcProto {
+ char suffix; /* a for RFC1201, e for ether-encap, etc. */
+ int mtu; /* largest possible packet */
+ int is_ip; /* This is a ip plugin - not a raw thing */
+
+ void (*rx)(struct net_device *dev, int bufnum,
+ struct archdr *pkthdr, int length);
+ int (*build_header)(struct sk_buff *skb, struct net_device *dev,
+ unsigned short ethproto, uint8_t daddr);
+
+ /* these functions return '1' if the skb can now be freed */
+ int (*prepare_tx)(struct net_device *dev, struct archdr *pkt,
+ int length, int bufnum);
+ int (*continue_tx)(struct net_device *dev, int bufnum);
+ int (*ack_tx)(struct net_device *dev, int acked);
+};
+
+extern struct ArcProto *arc_proto_map[256], *arc_proto_default,
+ *arc_bcast_proto, *arc_raw_proto;
+
+/*
+ * "Incoming" is information needed for each address that could be sending
+ * to us. Mostly for partially-received split packets.
+ */
+struct Incoming {
+ struct sk_buff *skb; /* packet data buffer */
+ __be16 sequence; /* sequence number of assembly */
+ uint8_t lastpacket, /* number of last packet (from 1) */
+ numpackets; /* number of packets in split */
+};
+
+/* only needed for RFC1201 */
+struct Outgoing {
+ struct ArcProto *proto; /* protocol driver that owns this:
+ * if NULL, no packet is pending.
+ */
+ struct sk_buff *skb; /* buffer from upper levels */
+ struct archdr *pkt; /* a pointer into the skb */
+ uint16_t length, /* bytes total */
+ dataleft, /* bytes left */
+ segnum, /* segment being sent */
+ numsegs; /* number of segments */
+};
+
+#define ARCNET_LED_NAME_SZ (IFNAMSIZ + 6)
+
+struct arcnet_local {
+ uint8_t config, /* current value of CONFIG register */
+ timeout, /* Extended timeout for COM20020 */
+ backplane, /* Backplane flag for COM20020 */
+ clockp, /* COM20020 clock divider */
+ clockm, /* COM20020 clock multiplier flag */
+ setup, /* Contents of setup1 register */
+ setup2, /* Contents of setup2 register */
+ intmask; /* current value of INTMASK register */
+ uint8_t default_proto[256]; /* default encap to use for each host */
+ int cur_tx, /* buffer used by current transmit, or -1 */
+ next_tx, /* buffer where a packet is ready to send */
+ cur_rx; /* current receive buffer */
+ int lastload_dest, /* can last loaded packet be acked? */
+ lasttrans_dest; /* can last TX'd packet be acked? */
+ int timed_out; /* need to process TX timeout and drop packet */
+ unsigned long last_timeout; /* time of last reported timeout */
+ char *card_name; /* card ident string */
+ int card_flags; /* special card features */
+
+ /* On preemtive and SMB a lock is needed */
+ spinlock_t lock;
+
+ struct led_trigger *tx_led_trig;
+ char tx_led_trig_name[ARCNET_LED_NAME_SZ];
+ struct led_trigger *recon_led_trig;
+ char recon_led_trig_name[ARCNET_LED_NAME_SZ];
+
+ struct timer_list timer;
+
+ /*
+ * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of
+ * which can be used for either sending or receiving. The new dynamic
+ * buffer management routines use a simple circular queue of available
+ * buffers, and take them as they're needed. This way, we simplify
+ * situations in which we (for example) want to pre-load a transmit
+ * buffer, or start receiving while we copy a received packet to
+ * memory.
+ *
+ * The rules: only the interrupt handler is allowed to _add_ buffers to
+ * the queue; thus, this doesn't require a lock. Both the interrupt
+ * handler and the transmit function will want to _remove_ buffers, so
+ * we need to handle the situation where they try to do it at the same
+ * time.
+ *
+ * If next_buf == first_free_buf, the queue is empty. Since there are
+ * only four possible buffers, the queue should never be full.
+ */
+ atomic_t buf_lock;
+ int buf_queue[5];
+ int next_buf, first_free_buf;
+
+ /* network "reconfiguration" handling */
+ unsigned long first_recon; /* time of "first" RECON message to count */
+ unsigned long last_recon; /* time of most recent RECON */
+ int num_recons; /* number of RECONs between first and last. */
+ int network_down; /* do we think the network is down? */
+
+ int excnak_pending; /* We just got an excesive nak interrupt */
+
+ struct {
+ uint16_t sequence; /* sequence number (incs with each packet) */
+ __be16 aborted_seq;
+
+ struct Incoming incoming[256]; /* one from each address */
+ } rfc1201;
+
+ /* really only used by rfc1201, but we'll pretend it's not */
+ struct Outgoing outgoing; /* packet currently being sent */
+
+ /* hardware-specific functions */
+ struct {
+ struct module *owner;
+ void (*command)(struct net_device *dev, int cmd);
+ int (*status)(struct net_device *dev);
+ void (*intmask)(struct net_device *dev, int mask);
+ int (*reset)(struct net_device *dev, int really_reset);
+ void (*open)(struct net_device *dev);
+ void (*close)(struct net_device *dev);
+ void (*datatrigger) (struct net_device * dev, int enable);
+ void (*recontrigger) (struct net_device * dev, int enable);
+
+ void (*copy_to_card)(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count);
+ void (*copy_from_card)(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count);
+ } hw;
+
+ void __iomem *mem_start; /* pointer to ioremap'ed MMIO */
+};
+
+enum arcnet_led_event {
+ ARCNET_LED_EVENT_RECON,
+ ARCNET_LED_EVENT_OPEN,
+ ARCNET_LED_EVENT_STOP,
+ ARCNET_LED_EVENT_TX,
+};
+
+void arcnet_led_event(struct net_device *netdev, enum arcnet_led_event event);
+void devm_arcnet_led_init(struct net_device *netdev, int index, int subid);
+
+#if ARCNET_DEBUG_MAX & D_SKB
+void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
+#else
+static inline
+void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
+{
+}
+#endif
+
+void arcnet_unregister_proto(struct ArcProto *proto);
+irqreturn_t arcnet_interrupt(int irq, void *dev_id);
+struct net_device *alloc_arcdev(const char *name);
+
+int arcnet_open(struct net_device *dev);
+int arcnet_close(struct net_device *dev);
+netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
+ struct net_device *dev);
+void arcnet_timeout(struct net_device *dev);
+
+/* I/O equivalents */
+
+#ifdef CONFIG_SA1100_CT6001
+#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */
+#else
+#define BUS_ALIGN 1
+#endif
+
+/* addr and offset allow register like names to define the actual IO address.
+ * A configuration option multiplies the offset for alignment.
+ */
+#define arcnet_inb(addr, offset) \
+ inb((addr) + BUS_ALIGN * (offset))
+#define arcnet_outb(value, addr, offset) \
+ outb(value, (addr) + BUS_ALIGN * (offset))
+
+#define arcnet_insb(addr, offset, buffer, count) \
+ insb((addr) + BUS_ALIGN * (offset), buffer, count)
+#define arcnet_outsb(addr, offset, buffer, count) \
+ outsb((addr) + BUS_ALIGN * (offset), buffer, count)
+
+#define arcnet_readb(addr, offset) \
+ readb((addr) + (offset))
+#define arcnet_writeb(value, addr, offset) \
+ writeb(value, (addr) + (offset))
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ARCDEVICE_H */
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 816d0e94961c..6ea963e3b89a 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - device-independent routines
- *
+ *
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
@@ -20,12 +20,12 @@
* modified by SRC, incorporated herein by reference.
*
* **********************
- *
+ *
* The change log is now in a file called ChangeLog in this directory.
*
* Sources:
* - Crynwr arcnet.com/arcether.com packet drivers.
- * - arcnet.c v0.00 dated 1/1/94 and apparently by
+ * - arcnet.c v0.00 dated 1/1/94 and apparently by
* Donald Becker - it didn't work :)
* - skeleton.c v0.05 dated 11/16/93 by Donald Becker
* (from Linux Kernel 1.1.45)
@@ -41,7 +41,7 @@
* <jojo@repas.de>
*/
-#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/types.h>
@@ -50,9 +50,13 @@
#include <linux/if_arp.h>
#include <net/arp.h>
#include <linux/init.h>
-#include <linux/arcdevice.h>
#include <linux/jiffies.h>
+#include <linux/leds.h>
+
+#include "arcdevice.h"
+#include "com9026.h"
+
/* "do nothing" functions for protocol drivers */
static void null_rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length);
@@ -63,17 +67,24 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
static void arcnet_rx(struct net_device *dev, int bufnum);
-/*
- * one ArcProto per possible proto ID. None of the elements of
+/* one ArcProto per possible proto ID. None of the elements of
* arc_proto_map are allowed to be NULL; they will get set to
* arc_proto_default instead. It also must not be NULL; if you would like
* to set it to NULL, set it to &arc_proto_null instead.
*/
- struct ArcProto *arc_proto_map[256], *arc_proto_default,
- *arc_bcast_proto, *arc_raw_proto;
+struct ArcProto *arc_proto_map[256];
+EXPORT_SYMBOL(arc_proto_map);
-static struct ArcProto arc_proto_null =
-{
+struct ArcProto *arc_proto_default;
+EXPORT_SYMBOL(arc_proto_default);
+
+struct ArcProto *arc_bcast_proto;
+EXPORT_SYMBOL(arc_bcast_proto);
+
+struct ArcProto *arc_raw_proto;
+EXPORT_SYMBOL(arc_raw_proto);
+
+static struct ArcProto arc_proto_null = {
.suffix = '?',
.mtu = XMTU,
.is_ip = 0,
@@ -86,19 +97,7 @@ static struct ArcProto arc_proto_null =
/* Exported function prototypes */
int arcnet_debug = ARCNET_DEBUG;
-
-EXPORT_SYMBOL(arc_proto_map);
-EXPORT_SYMBOL(arc_proto_default);
-EXPORT_SYMBOL(arc_bcast_proto);
-EXPORT_SYMBOL(arc_raw_proto);
-EXPORT_SYMBOL(arcnet_unregister_proto);
EXPORT_SYMBOL(arcnet_debug);
-EXPORT_SYMBOL(alloc_arcdev);
-EXPORT_SYMBOL(arcnet_interrupt);
-EXPORT_SYMBOL(arcnet_open);
-EXPORT_SYMBOL(arcnet_close);
-EXPORT_SYMBOL(arcnet_send_packet);
-EXPORT_SYMBOL(arcnet_timeout);
/* Internal function prototypes */
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
@@ -116,29 +115,20 @@ static int __init arcnet_init(void)
arcnet_debug = debug;
- printk("arcnet loaded.\n");
-
-#ifdef ALPHA_WARNING
- BUGLVL(D_EXTRA) {
- printk("arcnet: ***\n"
- "arcnet: * Read arcnet.txt for important release notes!\n"
- "arcnet: *\n"
- "arcnet: * This is an ALPHA version! (Last stable release: v3.02) E-mail\n"
- "arcnet: * me if you have any questions, comments, or bug reports.\n"
- "arcnet: ***\n");
- }
-#endif
+ pr_info("arcnet loaded\n");
/* initialize the protocol map */
arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null;
for (count = 0; count < 256; count++)
arc_proto_map[count] = arc_proto_default;
- BUGLVL(D_DURING)
- printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n",
- sizeof(struct arc_hardware), sizeof(struct arc_rfc1201),
- sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap),
- sizeof(struct archdr));
+ if (BUGLVL(D_DURING))
+ pr_info("struct sizes: %Zd %Zd %Zd %Zd %Zd\n",
+ sizeof(struct arc_hardware),
+ sizeof(struct arc_rfc1201),
+ sizeof(struct arc_rfc1051),
+ sizeof(struct arc_eth_encap),
+ sizeof(struct archdr));
return 0;
}
@@ -150,9 +140,7 @@ static void __exit arcnet_exit(void)
module_init(arcnet_init);
module_exit(arcnet_exit);
-/*
- * Dump the contents of an sk_buff
- */
+/* Dump the contents of an sk_buff */
#if ARCNET_DEBUG_MAX & D_SKB
void arcnet_dump_skb(struct net_device *dev,
struct sk_buff *skb, char *desc)
@@ -164,14 +152,10 @@ void arcnet_dump_skb(struct net_device *dev,
print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
16, 1, skb->data, skb->len, true);
}
-
EXPORT_SYMBOL(arcnet_dump_skb);
#endif
-
-/*
- * Dump the contents of an ARCnet buffer
- */
+/* Dump the contents of an ARCnet buffer */
#if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
static void arcnet_dump_packet(struct net_device *dev, int bufnum,
char *desc, int take_arcnet_lock)
@@ -183,12 +167,13 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
char hdr[32];
/* hw.copy_from_card expects IRQ context so take the IRQ lock
- to keep it single threaded */
- if(take_arcnet_lock)
+ * to keep it single threaded
+ */
+ if (take_arcnet_lock)
spin_lock_irqsave(&lp->lock, flags);
lp->hw.copy_from_card(dev, bufnum, 0, buf, 512);
- if(take_arcnet_lock)
+ if (take_arcnet_lock)
spin_unlock_irqrestore(&lp->lock, flags);
/* if the offset[0] byte is nonzero, this is a 256-byte packet */
@@ -202,13 +187,76 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
#else
-#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) do { } while (0)
+#define arcnet_dump_packet(dev, bufnum, desc, take_arcnet_lock) do { } while (0)
#endif
+/* Trigger a LED event in response to a ARCNET device event */
+void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
+{
+ struct arcnet_local *lp = netdev_priv(dev);
+ unsigned long led_delay = 350;
+ unsigned long tx_delay = 50;
+
+ switch (event) {
+ case ARCNET_LED_EVENT_RECON:
+ led_trigger_blink_oneshot(lp->recon_led_trig,
+ &led_delay, &led_delay, 0);
+ break;
+ case ARCNET_LED_EVENT_OPEN:
+ led_trigger_event(lp->tx_led_trig, LED_OFF);
+ led_trigger_event(lp->recon_led_trig, LED_OFF);
+ break;
+ case ARCNET_LED_EVENT_STOP:
+ led_trigger_event(lp->tx_led_trig, LED_OFF);
+ led_trigger_event(lp->recon_led_trig, LED_OFF);
+ break;
+ case ARCNET_LED_EVENT_TX:
+ led_trigger_blink_oneshot(lp->tx_led_trig,
+ &tx_delay, &tx_delay, 0);
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(arcnet_led_event);
-/*
- * Unregister a protocol driver from the arc_proto_map. Protocol drivers
+static void arcnet_led_release(struct device *gendev, void *res)
+{
+ struct arcnet_local *lp = netdev_priv(to_net_dev(gendev));
+
+ led_trigger_unregister_simple(lp->tx_led_trig);
+ led_trigger_unregister_simple(lp->recon_led_trig);
+}
+
+/* Register ARCNET LED triggers for a arcnet device
+ *
+ * This is normally called from a driver's probe function
+ */
+void devm_arcnet_led_init(struct net_device *netdev, int index, int subid)
+{
+ struct arcnet_local *lp = netdev_priv(netdev);
+ void *res;
+
+ res = devres_alloc(arcnet_led_release, 0, GFP_KERNEL);
+ if (!res) {
+ netdev_err(netdev, "cannot register LED triggers\n");
+ return;
+ }
+
+ snprintf(lp->tx_led_trig_name, sizeof(lp->tx_led_trig_name),
+ "arc%d-%d-tx", index, subid);
+ snprintf(lp->recon_led_trig_name, sizeof(lp->recon_led_trig_name),
+ "arc%d-%d-recon", index, subid);
+
+ led_trigger_register_simple(lp->tx_led_trig_name,
+ &lp->tx_led_trig);
+ led_trigger_register_simple(lp->recon_led_trig_name,
+ &lp->recon_led_trig);
+
+ devres_add(&netdev->dev, res);
+}
+EXPORT_SYMBOL_GPL(devm_arcnet_led_init);
+
+/* Unregister a protocol driver from the arc_proto_map. Protocol drivers
* are responsible for registering themselves, but the unregister routine
* is pretty generic so we'll do it here.
*/
@@ -228,12 +276,11 @@ void arcnet_unregister_proto(struct ArcProto *proto)
arc_proto_map[count] = arc_proto_default;
}
}
+EXPORT_SYMBOL(arcnet_unregister_proto);
-
-/*
- * Add a buffer to the queue. Only the interrupt handler is allowed to do
+/* Add a buffer to the queue. Only the interrupt handler is allowed to do
* this, unless interrupts are disabled.
- *
+ *
* Note: we don't check for a full queue, since there aren't enough buffers
* to more than fill it.
*/
@@ -245,19 +292,17 @@ static void release_arcbuf(struct net_device *dev, int bufnum)
lp->buf_queue[lp->first_free_buf++] = bufnum;
lp->first_free_buf %= 5;
- BUGLVL(D_DURING) {
- BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ",
- bufnum);
- for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
- BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
- BUGMSG2(D_DURING, "\n");
+ if (BUGLVL(D_DURING)) {
+ arc_printk(D_DURING, dev, "release_arcbuf: freed #%d; buffer queue is now: ",
+ bufnum);
+ for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5)
+ arc_cont(D_DURING, "#%d ", lp->buf_queue[i]);
+ arc_cont(D_DURING, "\n");
}
}
-
-/*
- * Get a buffer from the queue. If this returns -1, there are no buffers
- * available.
+/* Get a buffer from the queue.
+ * If this returns -1, there are no buffers available.
*/
static int get_arcbuf(struct net_device *dev)
{
@@ -266,34 +311,32 @@ static int get_arcbuf(struct net_device *dev)
if (!atomic_dec_and_test(&lp->buf_lock)) {
/* already in this function */
- BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n",
- lp->buf_lock.counter);
- }
- else { /* we can continue */
+ arc_printk(D_NORMAL, dev, "get_arcbuf: overlap (%d)!\n",
+ lp->buf_lock.counter);
+ } else { /* we can continue */
if (lp->next_buf >= 5)
lp->next_buf -= 5;
- if (lp->next_buf == lp->first_free_buf)
- BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n");
- else {
+ if (lp->next_buf == lp->first_free_buf) {
+ arc_printk(D_NORMAL, dev, "get_arcbuf: BUG: no buffers are available??\n");
+ } else {
buf = lp->buf_queue[lp->next_buf++];
lp->next_buf %= 5;
}
}
-
- BUGLVL(D_DURING) {
- BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf);
- for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
- BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
- BUGMSG2(D_DURING, "\n");
+ if (BUGLVL(D_DURING)) {
+ arc_printk(D_DURING, dev, "get_arcbuf: got #%d; buffer queue is now: ",
+ buf);
+ for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5)
+ arc_cont(D_DURING, "#%d ", lp->buf_queue[i]);
+ arc_cont(D_DURING, "\n");
}
atomic_inc(&lp->buf_lock);
return buf;
}
-
static int choose_mtu(void)
{
int count, mtu = 65535;
@@ -336,7 +379,16 @@ static void arcdev_setup(struct net_device *dev)
/* New-style flags. */
dev->flags = IFF_BROADCAST;
+}
+static void arcnet_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+
+ if (!netif_carrier_ok(dev)) {
+ netif_carrier_on(dev);
+ netdev_info(dev, "link up\n");
+ }
}
struct net_device *alloc_arcdev(const char *name)
@@ -346,16 +398,20 @@ struct net_device *alloc_arcdev(const char *name)
dev = alloc_netdev(sizeof(struct arcnet_local),
name && *name ? name : "arc%d", NET_NAME_UNKNOWN,
arcdev_setup);
- if(dev) {
+ if (dev) {
struct arcnet_local *lp = netdev_priv(dev);
+
spin_lock_init(&lp->lock);
+ init_timer(&lp->timer);
+ lp->timer.data = (unsigned long) dev;
+ lp->timer.function = arcnet_timer;
}
return dev;
}
+EXPORT_SYMBOL(alloc_arcdev);
-/*
- * Open/initialize the board. This is called sometime after booting when
+/* Open/initialize the board. This is called sometime after booting when
* the 'ifconfig' program is run.
*
* This routine should set everything up anew at each open, even registers
@@ -367,34 +423,33 @@ int arcnet_open(struct net_device *dev)
struct arcnet_local *lp = netdev_priv(dev);
int count, newmtu, error;
- BUGMSG(D_INIT,"opened.");
+ arc_printk(D_INIT, dev, "opened.");
if (!try_module_get(lp->hw.owner))
return -ENODEV;
- BUGLVL(D_PROTO) {
- BUGMSG(D_PROTO, "protocol map (default is '%c'): ",
- arc_proto_default->suffix);
+ if (BUGLVL(D_PROTO)) {
+ arc_printk(D_PROTO, dev, "protocol map (default is '%c'): ",
+ arc_proto_default->suffix);
for (count = 0; count < 256; count++)
- BUGMSG2(D_PROTO, "%c", arc_proto_map[count]->suffix);
- BUGMSG2(D_PROTO, "\n");
+ arc_cont(D_PROTO, "%c", arc_proto_map[count]->suffix);
+ arc_cont(D_PROTO, "\n");
}
-
- BUGMSG(D_INIT, "arcnet_open: resetting card.\n");
+ arc_printk(D_INIT, dev, "arcnet_open: resetting card.\n");
/* try to put the card in a defined state - if it fails the first
* time, actually reset it.
*/
error = -ENODEV;
- if (ARCRESET(0) && ARCRESET(1))
+ if (lp->hw.reset(dev, 0) && lp->hw.reset(dev, 1))
goto out_module_put;
newmtu = choose_mtu();
if (newmtu < dev->mtu)
dev->mtu = newmtu;
- BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu);
+ arc_printk(D_INIT, dev, "arcnet_open: mtu: %d.\n", dev->mtu);
/* autodetect the encapsulation for each host. */
memset(lp->default_proto, 0, sizeof(lp->default_proto));
@@ -425,52 +480,57 @@ int arcnet_open(struct net_device *dev)
lp->hw.open(dev);
if (dev->dev_addr[0] == 0)
- BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved "
- "for broadcasts!\n");
+ arc_printk(D_NORMAL, dev, "WARNING! Station address 00 is reserved for broadcasts!\n");
else if (dev->dev_addr[0] == 255)
- BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse "
- "DOS networking programs!\n");
+ arc_printk(D_NORMAL, dev, "WARNING! Station address FF may confuse DOS networking programs!\n");
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
- if (ASTATUS() & RESETflag) {
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
- ACOMMAND(CFLAGScmd | RESETclear);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
+ if (lp->hw.status(dev) & RESETflag) {
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n",
+ __FILE__, __LINE__, __func__);
+ lp->hw.command(dev, CFLAGScmd | RESETclear);
}
-
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
/* make sure we're ready to receive IRQ's. */
- AINTMASK(0);
+ lp->hw.intmask(dev, 0);
udelay(1); /* give it time to set the mask before
* we reset it again. (may not even be
* necessary)
*/
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
lp->intmask = NORXflag | RECONflag;
- AINTMASK(lp->intmask);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ lp->hw.intmask(dev, lp->intmask);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
+ netif_carrier_off(dev);
netif_start_queue(dev);
+ mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));
+ arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN);
return 0;
out_module_put:
module_put(lp->hw.owner);
return error;
}
-
+EXPORT_SYMBOL(arcnet_open);
/* The inverse routine to arcnet_open - shuts down the card. */
int arcnet_close(struct net_device *dev)
{
struct arcnet_local *lp = netdev_priv(dev);
+ arcnet_led_event(dev, ARCNET_LED_EVENT_STOP);
+ del_timer_sync(&lp->timer);
+
netif_stop_queue(dev);
+ netif_carrier_off(dev);
/* flush TX and disable RX */
- AINTMASK(0);
- ACOMMAND(NOTXcmd); /* stop transmit */
- ACOMMAND(NORXcmd); /* disable receive */
+ lp->hw.intmask(dev, 0);
+ lp->hw.command(dev, NOTXcmd); /* stop transmit */
+ lp->hw.command(dev, NORXcmd); /* disable receive */
mdelay(1);
/* shut down the card */
@@ -478,7 +538,7 @@ int arcnet_close(struct net_device *dev)
module_put(lp->hw.owner);
return 0;
}
-
+EXPORT_SYMBOL(arcnet_close);
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
@@ -488,48 +548,44 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
uint8_t _daddr, proto_num;
struct ArcProto *proto;
- BUGMSG(D_DURING,
- "create header from %d to %d; protocol %d (%Xh); size %u.\n",
- saddr ? *(uint8_t *) saddr : -1,
- daddr ? *(uint8_t *) daddr : -1,
- type, type, len);
-
- if (skb->len!=0 && len != skb->len)
- BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n",
- skb->len, len);
-
-
- /* Type is host order - ? */
- if(type == ETH_P_ARCNET) {
- proto = arc_raw_proto;
- BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix);
- _daddr = daddr ? *(uint8_t *) daddr : 0;
- }
- else if (!daddr) {
- /*
- * if the dest addr isn't provided, we can't choose an encapsulation!
- * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a
- * real header when we do rebuild_header.
- */
- *(uint16_t *) skb_push(skb, 2) = type;
- /*
- * XXX: Why not use skb->mac_len?
+ arc_printk(D_DURING, dev,
+ "create header from %d to %d; protocol %d (%Xh); size %u.\n",
+ saddr ? *(uint8_t *)saddr : -1,
+ daddr ? *(uint8_t *)daddr : -1,
+ type, type, len);
+
+ if (skb->len != 0 && len != skb->len)
+ arc_printk(D_NORMAL, dev, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n",
+ skb->len, len);
+
+ /* Type is host order - ? */
+ if (type == ETH_P_ARCNET) {
+ proto = arc_raw_proto;
+ arc_printk(D_DEBUG, dev, "arc_raw_proto used. proto='%c'\n",
+ proto->suffix);
+ _daddr = daddr ? *(uint8_t *)daddr : 0;
+ } else if (!daddr) {
+ /* if the dest addr isn't provided, we can't choose an
+ * encapsulation! Store the packet type (eg. ETH_P_IP)
+ * for now, and we'll push on a real header when we do
+ * rebuild_header.
*/
+ *(uint16_t *)skb_push(skb, 2) = type;
+ /* XXX: Why not use skb->mac_len? */
if (skb->network_header - skb->mac_header != 2)
- BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n",
- (int)(skb->network_header - skb->mac_header));
+ arc_printk(D_NORMAL, dev, "arcnet_header: Yikes! diff (%u) is not 2!\n",
+ skb->network_header - skb->mac_header);
return -2; /* return error -- can't transmit yet! */
- }
- else {
+ } else {
/* otherwise, we can just add the header as usual. */
- _daddr = *(uint8_t *) daddr;
+ _daddr = *(uint8_t *)daddr;
proto_num = lp->default_proto[_daddr];
proto = arc_proto_map[proto_num];
- BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n",
- proto_num, proto->suffix);
+ arc_printk(D_DURING, dev, "building header for %02Xh using protocol '%c'\n",
+ proto_num, proto->suffix);
if (proto == &arc_proto_null && arc_bcast_proto != proto) {
- BUGMSG(D_DURING, "actually, let's use '%c' instead.\n",
- arc_bcast_proto->suffix);
+ arc_printk(D_DURING, dev, "actually, let's use '%c' instead.\n",
+ arc_bcast_proto->suffix);
proto = arc_bcast_proto;
}
}
@@ -538,7 +594,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
/* Called by the kernel in order to transmit a packet. */
netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
- struct net_device *dev)
+ struct net_device *dev)
{
struct arcnet_local *lp = netdev_priv(dev);
struct archdr *pkt;
@@ -546,23 +602,24 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
struct ArcProto *proto;
int txbuf;
unsigned long flags;
- int freeskb, retval;
+ int retval;
- BUGMSG(D_DURING,
- "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
- ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol);
+ arc_printk(D_DURING, dev,
+ "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
+ lp->hw.status(dev), lp->cur_tx, lp->next_tx, skb->len, skb->protocol);
- pkt = (struct archdr *) skb->data;
+ pkt = (struct archdr *)skb->data;
soft = &pkt->soft.rfc1201;
proto = arc_proto_map[soft->proto];
- BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n",
- skb->len, pkt->hard.dest);
- BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");
+ arc_printk(D_SKB_SIZE, dev, "skb: transmitting %d bytes to %02X\n",
+ skb->len, pkt->hard.dest);
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, skb, "tx");
/* fits in one packet? */
if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {
- BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");
+ arc_printk(D_NORMAL, dev, "fixme: packet too large: compensating badly!\n");
dev_kfree_skb(skb);
return NETDEV_TX_OK; /* don't try again */
}
@@ -571,96 +628,94 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
netif_stop_queue(dev);
spin_lock_irqsave(&lp->lock, flags);
- AINTMASK(0);
- if(lp->next_tx == -1)
+ lp->hw.intmask(dev, 0);
+ if (lp->next_tx == -1)
txbuf = get_arcbuf(dev);
- else {
+ else
txbuf = -1;
- }
+
if (txbuf != -1) {
if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
!proto->ack_tx) {
/* done right away and we don't want to acknowledge
- the package later - forget about it now */
+ * the package later - forget about it now
+ */
dev->stats.tx_bytes += skb->len;
- freeskb = 1;
+ dev_kfree_skb(skb);
} else {
/* do it the 'split' way */
lp->outgoing.proto = proto;
lp->outgoing.skb = skb;
lp->outgoing.pkt = pkt;
- freeskb = 0;
-
if (proto->continue_tx &&
proto->continue_tx(dev, txbuf)) {
- BUGMSG(D_NORMAL,
- "bug! continue_tx finished the first time! "
- "(proto='%c')\n", proto->suffix);
+ arc_printk(D_NORMAL, dev,
+ "bug! continue_tx finished the first time! (proto='%c')\n",
+ proto->suffix);
}
}
retval = NETDEV_TX_OK;
lp->next_tx = txbuf;
} else {
retval = NETDEV_TX_BUSY;
- freeskb = 0;
}
- BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS());
+ arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n",
+ __FILE__, __LINE__, __func__, lp->hw.status(dev));
/* make sure we didn't ignore a TX IRQ while we were in here */
- AINTMASK(0);
+ lp->hw.intmask(dev, 0);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
- lp->intmask |= TXFREEflag|EXCNAKflag;
- AINTMASK(lp->intmask);
- BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS());
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
+ lp->intmask |= TXFREEflag | EXCNAKflag;
+ lp->hw.intmask(dev, lp->intmask);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n",
+ __FILE__, __LINE__, __func__, lp->hw.status(dev));
+
+ arcnet_led_event(dev, ARCNET_LED_EVENT_TX);
spin_unlock_irqrestore(&lp->lock, flags);
- if (freeskb) {
- dev_kfree_skb(skb);
- }
return retval; /* no need to try again */
}
+EXPORT_SYMBOL(arcnet_send_packet);
-
-/*
- * Actually start transmitting a packet that was loaded into a buffer
+/* Actually start transmitting a packet that was loaded into a buffer
* by prepare_tx. This should _only_ be called by the interrupt handler.
*/
static int go_tx(struct net_device *dev)
{
struct arcnet_local *lp = netdev_priv(dev);
- BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",
- ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx);
+ arc_printk(D_DURING, dev, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",
+ lp->hw.status(dev), lp->intmask, lp->next_tx, lp->cur_tx);
if (lp->cur_tx != -1 || lp->next_tx == -1)
return 0;
- BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0);
+ if (BUGLVL(D_TX))
+ arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0);
lp->cur_tx = lp->next_tx;
lp->next_tx = -1;
/* start sending */
- ACOMMAND(TXcmd | (lp->cur_tx << 3));
+ lp->hw.command(dev, TXcmd | (lp->cur_tx << 3));
dev->stats.tx_packets++;
lp->lasttrans_dest = lp->lastload_dest;
lp->lastload_dest = 0;
lp->excnak_pending = 0;
- lp->intmask |= TXFREEflag|EXCNAKflag;
+ lp->intmask |= TXFREEflag | EXCNAKflag;
return 1;
}
-
/* Called by the kernel when transmit times out */
void arcnet_timeout(struct net_device *dev)
{
unsigned long flags;
struct arcnet_local *lp = netdev_priv(dev);
- int status = ASTATUS();
+ int status = lp->hw.status(dev);
char *msg;
spin_lock_irqsave(&lp->lock, flags);
@@ -670,30 +725,29 @@ void arcnet_timeout(struct net_device *dev)
msg = "";
dev->stats.tx_aborted_errors++;
lp->timed_out = 1;
- ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
+ lp->hw.command(dev, NOTXcmd | (lp->cur_tx << 3));
}
dev->stats.tx_errors++;
/* make sure we didn't miss a TX or a EXC NAK IRQ */
- AINTMASK(0);
- lp->intmask |= TXFREEflag|EXCNAKflag;
- AINTMASK(lp->intmask);
-
+ lp->hw.intmask(dev, 0);
+ lp->intmask |= TXFREEflag | EXCNAKflag;
+ lp->hw.intmask(dev, lp->intmask);
+
spin_unlock_irqrestore(&lp->lock, flags);
- if (time_after(jiffies, lp->last_timeout + 10*HZ)) {
- BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
- msg, status, lp->intmask, lp->lasttrans_dest);
+ if (time_after(jiffies, lp->last_timeout + 10 * HZ)) {
+ arc_printk(D_EXTRA, dev, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
+ msg, status, lp->intmask, lp->lasttrans_dest);
lp->last_timeout = jiffies;
}
if (lp->cur_tx == -1)
netif_wake_queue(dev);
}
+EXPORT_SYMBOL(arcnet_timeout);
-
-/*
- * The typical workload of the driver: Handle the network interface
+/* The typical workload of the driver: Handle the network interface
* interrupts. Establish which device needs attention, and call the correct
* chipset interrupt handler.
*/
@@ -704,125 +758,125 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
int recbuf, status, diagstatus, didsomething, boguscount;
int retval = IRQ_NONE;
- BUGMSG(D_DURING, "\n");
+ arc_printk(D_DURING, dev, "\n");
- BUGMSG(D_DURING, "in arcnet_interrupt\n");
+ arc_printk(D_DURING, dev, "in arcnet_interrupt\n");
lp = netdev_priv(dev);
BUG_ON(!lp);
-
+
spin_lock(&lp->lock);
- /*
- * RESET flag was enabled - if device is not running, we must clear it right
- * away (but nothing else).
+ /* RESET flag was enabled - if device is not running, we must
+ * clear it right away (but nothing else).
*/
if (!netif_running(dev)) {
- if (ASTATUS() & RESETflag)
- ACOMMAND(CFLAGScmd | RESETclear);
- AINTMASK(0);
+ if (lp->hw.status(dev) & RESETflag)
+ lp->hw.command(dev, CFLAGScmd | RESETclear);
+ lp->hw.intmask(dev, 0);
spin_unlock(&lp->lock);
return retval;
}
- BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
- ASTATUS(), lp->intmask);
+ arc_printk(D_DURING, dev, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
+ lp->hw.status(dev), lp->intmask);
boguscount = 5;
do {
- status = ASTATUS();
- diagstatus = (status >> 8) & 0xFF;
+ status = lp->hw.status(dev);
+ diagstatus = (status >> 8) & 0xFF;
- BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n",
- __FILE__,__LINE__,__func__,status);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s: status=%x\n",
+ __FILE__, __LINE__, __func__, status);
didsomething = 0;
- /*
- * RESET flag was enabled - card is resetting and if RX is
+ /* RESET flag was enabled - card is resetting and if RX is
* disabled, it's NOT because we just got a packet.
- *
- * The card is in an undefined state. Clear it out and start over.
+ *
+ * The card is in an undefined state.
+ * Clear it out and start over.
*/
if (status & RESETflag) {
- BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status);
+ arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n",
+ status);
arcnet_close(dev);
arcnet_open(dev);
/* get out of the interrupt handler! */
break;
}
- /*
- * RX is inhibited - we must have received something. Prepare to
- * receive into the next buffer.
- *
- * We don't actually copy the received packet from the card until
- * after the transmit handler runs (and possibly launches the next
- * tx); this should improve latency slightly if we get both types
- * of interrupts at once.
+ /* RX is inhibited - we must have received something.
+ * Prepare to receive into the next buffer.
+ *
+ * We don't actually copy the received packet from the card
+ * until after the transmit handler runs (and possibly
+ * launches the next tx); this should improve latency slightly
+ * if we get both types of interrupts at once.
*/
recbuf = -1;
if (status & lp->intmask & NORXflag) {
recbuf = lp->cur_rx;
- BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n",
- recbuf, status);
+ arc_printk(D_DURING, dev, "Buffer #%d: receive irq (status=%Xh)\n",
+ recbuf, status);
lp->cur_rx = get_arcbuf(dev);
if (lp->cur_rx != -1) {
- BUGMSG(D_DURING, "enabling receive to buffer #%d\n",
- lp->cur_rx);
- ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts);
+ arc_printk(D_DURING, dev, "enabling receive to buffer #%d\n",
+ lp->cur_rx);
+ lp->hw.command(dev, RXcmd | (lp->cur_rx << 3) | RXbcasts);
}
didsomething++;
}
- if((diagstatus & EXCNAKflag)) {
- BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n",
- diagstatus);
+ if ((diagstatus & EXCNAKflag)) {
+ arc_printk(D_DURING, dev, "EXCNAK IRQ (diagstat=%Xh)\n",
+ diagstatus);
- ACOMMAND(NOTXcmd); /* disable transmit */
- lp->excnak_pending = 1;
+ lp->hw.command(dev, NOTXcmd); /* disable transmit */
+ lp->excnak_pending = 1;
- ACOMMAND(EXCNAKclear);
+ lp->hw.command(dev, EXCNAKclear);
lp->intmask &= ~(EXCNAKflag);
- didsomething++;
- }
-
+ didsomething++;
+ }
/* a transmit finished, and we're interested in it. */
if ((status & lp->intmask & TXFREEflag) || lp->timed_out) {
- lp->intmask &= ~(TXFREEflag|EXCNAKflag);
+ lp->intmask &= ~(TXFREEflag | EXCNAKflag);
- BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status);
+ arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n",
+ status);
if (lp->cur_tx != -1 && !lp->timed_out) {
- if(!(status & TXACKflag)) {
+ if (!(status & TXACKflag)) {
if (lp->lasttrans_dest != 0) {
- BUGMSG(D_EXTRA,
- "transmit was not acknowledged! "
- "(status=%Xh, dest=%02Xh)\n",
- status, lp->lasttrans_dest);
+ arc_printk(D_EXTRA, dev,
+ "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
+ status,
+ lp->lasttrans_dest);
dev->stats.tx_errors++;
dev->stats.tx_carrier_errors++;
} else {
- BUGMSG(D_DURING,
- "broadcast was not acknowledged; that's normal "
- "(status=%Xh, dest=%02Xh)\n",
- status, lp->lasttrans_dest);
+ arc_printk(D_DURING, dev,
+ "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
+ status,
+ lp->lasttrans_dest);
}
}
if (lp->outgoing.proto &&
lp->outgoing.proto->ack_tx) {
- int ackstatus;
- if(status & TXACKflag)
- ackstatus=2;
- else if(lp->excnak_pending)
- ackstatus=1;
- else
- ackstatus=0;
-
- lp->outgoing.proto
- ->ack_tx(dev, ackstatus);
+ int ackstatus;
+
+ if (status & TXACKflag)
+ ackstatus = 2;
+ else if (lp->excnak_pending)
+ ackstatus = 1;
+ else
+ ackstatus = 0;
+
+ lp->outgoing.proto
+ ->ack_tx(dev, ackstatus);
}
}
if (lp->cur_tx != -1)
@@ -836,17 +890,18 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
go_tx(dev);
/* continue a split packet, if any */
- if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) {
+ if (lp->outgoing.proto &&
+ lp->outgoing.proto->continue_tx) {
int txbuf = get_arcbuf(dev);
+
if (txbuf != -1) {
if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
/* that was the last segment */
dev->stats.tx_bytes += lp->outgoing.skb->len;
- if(!lp->outgoing.proto->ack_tx)
- {
- dev_kfree_skb_irq(lp->outgoing.skb);
- lp->outgoing.proto = NULL;
- }
+ if (!lp->outgoing.proto->ack_tx) {
+ dev_kfree_skb_irq(lp->outgoing.skb);
+ lp->outgoing.proto = NULL;
+ }
}
lp->next_tx = txbuf;
}
@@ -857,7 +912,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
}
/* now process the received packet, if any */
if (recbuf != -1) {
- BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0);
+ if (BUGLVL(D_RX))
+ arcnet_dump_packet(dev, recbuf, "rx irq", 0);
arcnet_rx(dev, recbuf);
release_arcbuf(dev, recbuf);
@@ -865,32 +921,39 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
didsomething++;
}
if (status & lp->intmask & RECONflag) {
- ACOMMAND(CFLAGScmd | CONFIGclear);
+ lp->hw.command(dev, CFLAGScmd | CONFIGclear);
dev->stats.tx_carrier_errors++;
- BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
- status);
+ arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n",
+ status);
+ if (netif_carrier_ok(dev)) {
+ netif_carrier_off(dev);
+ netdev_info(dev, "link down\n");
+ }
+ mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));
+
+ arcnet_led_event(dev, ARCNET_LED_EVENT_RECON);
/* MYRECON bit is at bit 7 of diagstatus */
- if(diagstatus & 0x80)
- BUGMSG(D_RECON,"Put out that recon myself\n");
+ if (diagstatus & 0x80)
+ arc_printk(D_RECON, dev, "Put out that recon myself\n");
/* is the RECON info empty or old? */
if (!lp->first_recon || !lp->last_recon ||
time_after(jiffies, lp->last_recon + HZ * 10)) {
if (lp->network_down)
- BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");
+ arc_printk(D_NORMAL, dev, "reconfiguration detected: cabling restored?\n");
lp->first_recon = lp->last_recon = jiffies;
lp->num_recons = lp->network_down = 0;
- BUGMSG(D_DURING, "recon: clearing counters.\n");
+ arc_printk(D_DURING, dev, "recon: clearing counters.\n");
} else { /* add to current RECON counter */
lp->last_recon = jiffies;
lp->num_recons++;
- BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n",
- lp->num_recons,
- (lp->last_recon - lp->first_recon) / HZ,
- lp->network_down);
+ arc_printk(D_DURING, dev, "recon: counter=%d, time=%lds, net=%d\n",
+ lp->num_recons,
+ (lp->last_recon - lp->first_recon) / HZ,
+ lp->network_down);
/* if network is marked up;
* and first_recon and last_recon are 60+ apart;
@@ -902,46 +965,45 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
(lp->last_recon - lp->first_recon) <= HZ * 60 &&
lp->num_recons >= RECON_THRESHOLD) {
lp->network_down = 1;
- BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n");
+ arc_printk(D_NORMAL, dev, "many reconfigurations detected: cabling problem?\n");
} else if (!lp->network_down &&
lp->last_recon - lp->first_recon > HZ * 60) {
- /* reset counters if we've gone for over a minute. */
+ /* reset counters if we've gone for
+ * over a minute.
+ */
lp->first_recon = lp->last_recon;
lp->num_recons = 1;
}
}
} else if (lp->network_down &&
- time_after(jiffies, lp->last_recon + HZ * 10)) {
+ time_after(jiffies, lp->last_recon + HZ * 10)) {
if (lp->network_down)
- BUGMSG(D_NORMAL, "cabling restored?\n");
+ arc_printk(D_NORMAL, dev, "cabling restored?\n");
lp->first_recon = lp->last_recon = 0;
lp->num_recons = lp->network_down = 0;
- BUGMSG(D_DURING, "not recon: clearing counters anyway.\n");
+ arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n");
+ netif_carrier_on(dev);
}
- if(didsomething) {
+ if (didsomething)
retval |= IRQ_HANDLED;
- }
- }
- while (--boguscount && didsomething);
-
- BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n",
- ASTATUS(), boguscount);
- BUGMSG(D_DURING, "\n");
+ } while (--boguscount && didsomething);
+ arc_printk(D_DURING, dev, "arcnet_interrupt complete (status=%Xh, count=%d)\n",
+ lp->hw.status(dev), boguscount);
+ arc_printk(D_DURING, dev, "\n");
- AINTMASK(0);
+ lp->hw.intmask(dev, 0);
udelay(1);
- AINTMASK(lp->intmask);
-
+ lp->hw.intmask(dev, lp->intmask);
+
spin_unlock(&lp->lock);
return retval;
}
+EXPORT_SYMBOL(arcnet_interrupt);
-
-/*
- * This is a generic packet receiver that calls arcnet??_rx depending on the
+/* This is a generic packet receiver that calls arcnet??_rx depending on the
* protocol ID found.
*/
static void arcnet_rx(struct net_device *dev, int bufnum)
@@ -963,32 +1025,31 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
}
/* get the full header, if possible */
- if (sizeof(pkt.soft) <= length)
+ if (sizeof(pkt.soft) <= length) {
lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft));
- else {
+ } else {
memset(&pkt.soft, 0, sizeof(pkt.soft));
lp->hw.copy_from_card(dev, bufnum, ofs, soft, length);
}
- BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh "
- "(%d+4 bytes)\n",
- bufnum, pkt.hard.source, pkt.hard.dest, length);
+ arc_printk(D_DURING, dev, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n",
+ bufnum, pkt.hard.source, pkt.hard.dest, length);
dev->stats.rx_packets++;
dev->stats.rx_bytes += length + ARC_HDR_SIZE;
/* call the right receiver for the protocol */
if (arc_proto_map[soft->proto]->is_ip) {
- BUGLVL(D_PROTO) {
+ if (BUGLVL(D_PROTO)) {
struct ArcProto
*oldp = arc_proto_map[lp->default_proto[pkt.hard.source]],
*newp = arc_proto_map[soft->proto];
if (oldp != newp) {
- BUGMSG(D_PROTO,
- "got protocol %02Xh; encap for host %02Xh is now '%c'"
- " (was '%c')\n", soft->proto, pkt.hard.source,
- newp->suffix, oldp->suffix);
+ arc_printk(D_PROTO, dev,
+ "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n",
+ soft->proto, pkt.hard.source,
+ newp->suffix, oldp->suffix);
}
}
@@ -1002,30 +1063,27 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length);
}
-
static void null_rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- BUGMSG(D_PROTO,
- "rx: don't know how to deal with proto %02Xh from host %02Xh.\n",
- pkthdr->soft.rfc1201.proto, pkthdr->hard.source);
+ arc_printk(D_PROTO, dev,
+ "rx: don't know how to deal with proto %02Xh from host %02Xh.\n",
+ pkthdr->soft.rfc1201.proto, pkthdr->hard.source);
}
-
static int null_build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
struct arcnet_local *lp = netdev_priv(dev);
- BUGMSG(D_PROTO,
- "tx: can't build header for encap %02Xh; load a protocol driver.\n",
- lp->default_proto[daddr]);
+ arc_printk(D_PROTO, dev,
+ "tx: can't build header for encap %02Xh; load a protocol driver.\n",
+ lp->default_proto[daddr]);
/* always fails */
return 0;
}
-
/* the "do nothing" prepare_tx function warns that there's nothing to do. */
static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
int length, int bufnum)
@@ -1033,7 +1091,7 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
struct arcnet_local *lp = netdev_priv(dev);
struct arc_hardware newpkt;
- BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n");
+ arc_printk(D_PROTO, dev, "tx: no encap for this host; load a protocol driver.\n");
/* send a packet to myself -- will never get received, of course */
newpkt.source = newpkt.dest = dev->dev_addr[0];
diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c
index 42fce91b71fc..2056878fb087 100644
--- a/drivers/net/arcnet/capmode.c
+++ b/drivers/net/arcnet/capmode.c
@@ -26,6 +26,8 @@
* **********************
*/
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/init.h>
@@ -33,9 +35,8 @@
#include <net/arp.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
-#include <linux/arcdevice.h>
-#define VERSION "arcnet: cap mode (`c') encapsulation support loaded.\n"
+#include "arcdevice.h"
/* packet receiver */
static void rx(struct net_device *dev, int bufnum,
@@ -47,7 +48,8 @@ static void rx(struct net_device *dev, int bufnum,
char *pktbuf, *pkthdrbuf;
int ofs;
- BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length);
+ arc_printk(D_DURING, dev, "it's a raw(cap) packet (length=%d)\n",
+ length);
if (length >= MinTU)
ofs = 512 - length;
@@ -55,8 +57,7 @@ static void rx(struct net_device *dev, int bufnum,
ofs = 256 - length;
skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ if (!skb) {
dev->stats.rx_dropped++;
return;
}
@@ -66,17 +67,17 @@ static void rx(struct net_device *dev, int bufnum,
pkt = (struct archdr *)skb_mac_header(skb);
skb_pull(skb, ARC_HDR_SIZE);
- /* up to sizeof(pkt->soft) has already been copied from the card */
- /* squeeze in an int for the cap encapsulation */
-
- /* use these variables to be sure we count in bytes, not in
- sizeof(struct archdr) */
- pktbuf=(char*)pkt;
- pkthdrbuf=(char*)pkthdr;
- memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto));
- memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int),
- pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto),
- sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto));
+ /* up to sizeof(pkt->soft) has already been copied from the card
+ * squeeze in an int for the cap encapsulation
+ * use these variables to be sure we count in bytes, not in
+ * sizeof(struct archdr)
+ */
+ pktbuf = (char *)pkt;
+ pkthdrbuf = (char *)pkthdr;
+ memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto));
+ memcpy(pktbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto) + sizeof(int),
+ pkthdrbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto),
+ sizeof(struct archdr) - ARC_HDR_SIZE - sizeof(pkt->soft.cap.proto));
if (length > sizeof(pkt->soft))
lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
@@ -84,15 +85,14 @@ static void rx(struct net_device *dev, int bufnum,
+ sizeof(int),
length - sizeof(pkt->soft));
- BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, skb, "rx");
skb->protocol = cpu_to_be16(ETH_P_ARCNET);
netif_rx(skb);
}
-
-/*
- * Create the ARCnet hard/soft headers for cap mode.
+/* Create the ARCnet hard/soft headers for cap mode.
* There aren't any soft headers in cap mode - not even the protocol id.
*/
static int build_header(struct sk_buff *skb,
@@ -101,12 +101,12 @@ static int build_header(struct sk_buff *skb,
uint8_t daddr)
{
int hdr_size = ARC_HDR_SIZE;
- struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
+ struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
- BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n",
- *((int*)&pkt->soft.cap.cookie[0]));
- /*
- * Set the source hardware address.
+ arc_printk(D_PROTO, dev, "Preparing header for cap packet %x.\n",
+ *((int *)&pkt->soft.cap.cookie[0]));
+
+ /* Set the source hardware address.
*
* This is pretty pointless for most purposes, but it can help in
* debugging. ARCnet does not allow us to change the source address in
@@ -117,9 +117,8 @@ static int build_header(struct sk_buff *skb,
/* see linux/net/ethernet/eth.c to see where I got the following */
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
- /*
- * FIXME: fill in the last byte of the dest ipaddr here to better
- * comply with RFC1051 in "noarp" mode.
+ /* FIXME: fill in the last byte of the dest ipaddr here to
+ * better comply with RFC1051 in "noarp" mode.
*/
pkt->hard.dest = 0;
return hdr_size;
@@ -130,7 +129,6 @@ static int build_header(struct sk_buff *skb,
return hdr_size; /* success */
}
-
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
@@ -138,22 +136,21 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
struct arc_hardware *hard = &pkt->hard;
int ofs;
-
/* hard header is not included in packet length */
length -= ARC_HDR_SIZE;
/* And neither is the cookie field */
length -= sizeof(int);
- BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
- lp->next_tx, lp->cur_tx, bufnum);
+ arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
+ lp->next_tx, lp->cur_tx, bufnum);
- BUGMSG(D_PROTO, "Sending for cap packet %x.\n",
- *((int*)&pkt->soft.cap.cookie[0]));
+ arc_printk(D_PROTO, dev, "Sending for cap packet %x.\n",
+ *((int *)&pkt->soft.cap.cookie[0]));
if (length > XMTU) {
/* should never happen! other people already check for this. */
- BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
- length, XMTU);
+ arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n",
+ length, XMTU);
length = XMTU;
}
if (length > MinTU) {
@@ -162,11 +159,12 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
} else if (length > MTU) {
hard->offset[0] = 0;
hard->offset[1] = ofs = 512 - length - 3;
- } else
+ } else {
hard->offset[0] = ofs = 256 - length;
+ }
- BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n",
- length,ofs);
+ arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n",
+ length, ofs);
/* Copy the arcnet-header + the protocol byte down: */
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
@@ -174,9 +172,10 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
sizeof(pkt->soft.cap.proto));
/* Skip the extra integer we have written into it as a cookie
- but write the rest of the message: */
- lp->hw.copy_to_card(dev, bufnum, ofs+1,
- ((unsigned char*)&pkt->soft.cap.mes),length-1);
+ * but write the rest of the message:
+ */
+ lp->hw.copy_to_card(dev, bufnum, ofs + 1,
+ ((unsigned char *)&pkt->soft.cap.mes), length - 1);
lp->lastload_dest = hard->dest;
@@ -188,21 +187,20 @@ static int ack_tx(struct net_device *dev, int acked)
struct arcnet_local *lp = netdev_priv(dev);
struct sk_buff *ackskb;
struct archdr *ackpkt;
- int length=sizeof(struct arc_cap);
+ int length = sizeof(struct arc_cap);
- BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n",
- lp->outgoing.skb->protocol, acked);
+ arc_printk(D_DURING, dev, "capmode: ack_tx: protocol: %x: result: %d\n",
+ lp->outgoing.skb->protocol, acked);
- BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx");
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx");
/* Now alloc a skb to send back up through the layers: */
- ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC);
- if (ackskb == NULL) {
- BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n");
+ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
+ if (!ackskb)
goto free_outskb;
- }
- skb_put(ackskb, length + ARC_HDR_SIZE );
+ skb_put(ackskb, length + ARC_HDR_SIZE);
ackskb->dev = dev;
skb_reset_mac_header(ackskb);
@@ -212,39 +210,40 @@ static int ack_tx(struct net_device *dev, int acked)
skb_copy_from_linear_data(lp->outgoing.skb, ackpkt,
ARC_HDR_SIZE + sizeof(struct arc_cap));
ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */
- ackpkt->soft.cap.mes.ack=acked;
+ ackpkt->soft.cap.mes.ack = acked;
- BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n",
- *((int*)&ackpkt->soft.cap.cookie[0]));
+ arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n",
+ *((int *)&ackpkt->soft.cap.cookie[0]));
ackskb->protocol = cpu_to_be16(ETH_P_ARCNET);
- BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv");
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, ackskb, "ack_tx_recv");
netif_rx(ackskb);
free_outskb:
dev_kfree_skb_irq(lp->outgoing.skb);
- lp->outgoing.proto = NULL; /* We are always finished when in this protocol */
+ lp->outgoing.proto = NULL;
+ /* We are always finished when in this protocol */
return 0;
}
-static struct ArcProto capmode_proto =
-{
- 'r',
- XMTU,
- 0,
- rx,
- build_header,
- prepare_tx,
- NULL,
- ack_tx
+static struct ArcProto capmode_proto = {
+ .suffix = 'r',
+ .mtu = XMTU,
+ .rx = rx,
+ .build_header = build_header,
+ .prepare_tx = prepare_tx,
+ .ack_tx = ack_tx
};
-static void arcnet_cap_init(void)
+static int __init capmode_module_init(void)
{
int count;
+ pr_info("cap mode (`c') encapsulation support loaded\n");
+
for (count = 1; count <= 8; count++)
if (arc_proto_map[count] == arc_proto_default)
arc_proto_map[count] = &capmode_proto;
@@ -255,12 +254,7 @@ static void arcnet_cap_init(void)
arc_proto_default = &capmode_proto;
arc_raw_proto = &capmode_proto;
-}
-static int __init capmode_module_init(void)
-{
- printk(VERSION);
- arcnet_cap_init();
return 0;
}
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 45c61a2c5fbd..b9e9931353b2 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - COM20020 chipset support
- *
+ *
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
@@ -25,6 +25,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -36,16 +39,12 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/bootmem.h>
-#include <linux/arcdevice.h>
-#include <linux/com20020.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
-#define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n"
+#include "arcdevice.h"
+#include "com20020.h"
-
-/*
- * We cannot (yet) probe for an IO mapped card, although we can check that
+/* We cannot (yet) probe for an IO mapped card, although we can check that
* it's where we were told it was, and even do autoirq.
*/
static int __init com20020isa_probe(struct net_device *dev)
@@ -55,21 +54,21 @@ static int __init com20020isa_probe(struct net_device *dev)
struct arcnet_local *lp = netdev_priv(dev);
int err;
- BUGLVL(D_NORMAL) printk(VERSION);
+ if (BUGLVL(D_NORMAL))
+ pr_info("%s\n", "COM20020 ISA support (by David Woodhouse et al.)");
ioaddr = dev->base_addr;
if (!ioaddr) {
- BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you "
- "must specify the base address!\n");
+ arc_printk(D_NORMAL, dev, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n");
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
- BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n",
- ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
+ arc_printk(D_NORMAL, dev, "IO region %xh-%xh already allocated.\n",
+ ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
- if (ASTATUS() == 0xFF) {
- BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr);
+ if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
+ arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr);
err = -ENODEV;
goto out;
}
@@ -83,23 +82,24 @@ static int __init com20020isa_probe(struct net_device *dev)
* card has just reset and the NORXflag is on until
* we tell it to start receiving.
*/
- BUGMSG(D_INIT_REASONS, "intmask was %02Xh\n", inb(_INTMASK));
- outb(0, _INTMASK);
+ arc_printk(D_INIT_REASONS, dev, "intmask was %02Xh\n",
+ arcnet_inb(ioaddr, COM20020_REG_R_STATUS));
+ arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
airqmask = probe_irq_on();
- outb(NORXflag, _INTMASK);
+ arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK);
udelay(1);
- outb(0, _INTMASK);
+ arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
dev->irq = probe_irq_off(airqmask);
if ((int)dev->irq <= 0) {
- BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed first time\n");
+ arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n");
airqmask = probe_irq_on();
- outb(NORXflag, _INTMASK);
+ arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK);
udelay(5);
- outb(0, _INTMASK);
+ arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
dev->irq = probe_irq_off(airqmask);
if ((int)dev->irq <= 0) {
- BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n");
+ arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n");
err = -ENODEV;
goto out;
}
@@ -107,7 +107,9 @@ static int __init com20020isa_probe(struct net_device *dev)
}
lp->card_name = "ISA COM20020";
- if ((err = com20020_found(dev, 0)) != 0)
+
+ err = com20020_found(dev, 0);
+ if (err != 0)
goto out;
return 0;
@@ -194,7 +196,7 @@ static int __init com20020isa_setup(char *s)
switch (ints[0]) {
default: /* ERROR */
- printk("com90xx: Too many arguments.\n");
+ pr_info("Too many arguments\n");
case 6: /* Timeout */
timeout = ints[6];
case 5: /* CKP value */
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 96edc1346124..239de38fbd6a 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -1,7 +1,7 @@
/*
* Linux ARCnet driver - COM20020 PCI support
* Contemporary Controls PCI20 and SOHARD SH-ARC PCI
- *
+ *
* Written 1994-1999 by Avery Pennarun,
* based on an ISA version by David Woodhouse.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
@@ -26,6 +26,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -36,14 +39,12 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/arcdevice.h>
-#include <linux/com20020.h>
#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/leds.h>
-#include <asm/io.h>
-
-
-#define VERSION "arcnet: COM20020 PCI support\n"
+#include "arcdevice.h"
+#include "com20020.h"
/* Module parameters */
@@ -62,11 +63,43 @@ module_param(clockp, int, 0);
module_param(clockm, int, 0);
MODULE_LICENSE("GPL");
+static void led_tx_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct com20020_dev *card;
+ struct com20020_priv *priv;
+ struct com20020_pci_card_info *ci;
+
+ card = container_of(led_cdev, struct com20020_dev, tx_led);
+
+ priv = card->pci_priv;
+ ci = priv->ci;
+
+ outb(!!value, priv->misc + ci->leds[card->index].green);
+}
+
+static void led_recon_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct com20020_dev *card;
+ struct com20020_priv *priv;
+ struct com20020_pci_card_info *ci;
+
+ card = container_of(led_cdev, struct com20020_dev, recon_led);
+
+ priv = card->pci_priv;
+ ci = priv->ci;
+
+ outb(!!value, priv->misc + ci->leds[card->index].red);
+}
+
static void com20020pci_remove(struct pci_dev *pdev);
-static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int com20020pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct com20020_pci_card_info *ci;
+ struct com20020_pci_channel_map *mm;
struct net_device *dev;
struct arcnet_local *lp;
struct com20020_priv *priv;
@@ -83,9 +116,21 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
ci = (struct com20020_pci_card_info *)id->driver_data;
priv->ci = ci;
+ mm = &ci->misc_map;
INIT_LIST_HEAD(&priv->list_dev);
+ if (mm->size) {
+ ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
+ r = devm_request_region(&pdev->dev, ioaddr, mm->size,
+ "com20020-pci");
+ if (!r) {
+ pr_err("IO region %xh-%xh already allocated.\n",
+ ioaddr, ioaddr + mm->size - 1);
+ return -EBUSY;
+ }
+ priv->misc = ioaddr;
+ }
for (i = 0; i < ci->devcount; i++) {
struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
@@ -96,18 +141,19 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
ret = -ENOMEM;
goto out_port;
}
+ dev->dev_port = i;
dev->netdev_ops = &com20020_netdev_ops;
lp = netdev_priv(dev);
- BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
+ arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
r = devm_request_region(&pdev->dev, ioaddr, cm->size,
"com20020-pci");
if (!r) {
- pr_err("IO region %xh-%xh already allocated.\n",
+ pr_err("IO region %xh-%xh already allocated\n",
ioaddr, ioaddr + cm->size - 1);
ret = -EBUSY;
goto out_port;
@@ -117,8 +163,8 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
* ARCNET controller needs
* this access to detect bustype
*/
- outb(0x00, ioaddr + 1);
- inb(ioaddr + 1);
+ arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
+ arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
dev->base_addr = ioaddr;
dev->dev_addr[0] = node;
@@ -131,7 +177,14 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
lp->timeout = timeout;
lp->hw.owner = THIS_MODULE;
- if (ASTATUS() == 0xFF) {
+ /* Get the dev_id from the PLX rotary coder */
+ if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
+ dev->dev_id = 0xc;
+ dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4;
+
+ snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
+
+ if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
pr_err("IO address %Xh is empty!\n", ioaddr);
ret = -EIO;
goto out_port;
@@ -143,21 +196,46 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
GFP_KERNEL);
- if (!card) {
- pr_err("%s out of memory!\n", __func__);
+ if (!card)
return -ENOMEM;
- }
card->index = i;
card->pci_priv = priv;
+ card->tx_led.brightness_set = led_tx_set;
+ card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
+ GFP_KERNEL, "arc%d-%d-tx",
+ dev->dev_id, i);
+ card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "pci:green:tx:%d-%d",
+ dev->dev_id, i);
+
+ card->tx_led.dev = &dev->dev;
+ card->recon_led.brightness_set = led_recon_set;
+ card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
+ GFP_KERNEL, "arc%d-%d-recon",
+ dev->dev_id, i);
+ card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "pci:red:recon:%d-%d",
+ dev->dev_id, i);
+ card->recon_led.dev = &dev->dev;
card->dev = dev;
+ ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
+ if (ret)
+ goto out_port;
+
+ ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
+ if (ret)
+ goto out_port;
+
dev_set_drvdata(&dev->dev, card);
ret = com20020_found(dev, IRQF_SHARED);
if (ret)
goto out_port;
+ devm_arcnet_led_init(dev, dev->dev_id, i);
+
list_add(&card->list, &priv->list_dev);
}
@@ -190,7 +268,11 @@ static struct com20020_pci_card_info card_info_10mbit = {
.name = "ARC-PCI",
.devcount = 1,
.chan_map_tbl = {
- { 2, 0x00, 0x08 },
+ {
+ .bar = 2,
+ .offset = 0x00,
+ .size = 0x08,
+ },
},
.flags = ARC_CAN_10MBIT,
};
@@ -199,7 +281,11 @@ static struct com20020_pci_card_info card_info_5mbit = {
.name = "ARC-PCI",
.devcount = 1,
.chan_map_tbl = {
- { 2, 0x00, 0x08 },
+ {
+ .bar = 2,
+ .offset = 0x00,
+ .size = 0x08,
+ },
},
.flags = ARC_IS_5MBIT,
};
@@ -209,7 +295,11 @@ static struct com20020_pci_card_info card_info_sohard = {
.devcount = 1,
/* SOHARD needs PCI base addr 4 */
.chan_map_tbl = {
- {4, 0x00, 0x08},
+ {
+ .bar = 4,
+ .offset = 0x00,
+ .size = 0x08
+ },
},
.flags = ARC_CAN_10MBIT,
};
@@ -218,8 +308,24 @@ static struct com20020_pci_card_info card_info_eae_arc1 = {
.name = "EAE PLX-PCI ARC1",
.devcount = 1,
.chan_map_tbl = {
- { 2, 0x00, 0x08 },
+ {
+ .bar = 2,
+ .offset = 0x00,
+ .size = 0x08,
+ },
},
+ .misc_map = {
+ .bar = 2,
+ .offset = 0x10,
+ .size = 0x04,
+ },
+ .leds = {
+ {
+ .green = 0x0,
+ .red = 0x1,
+ },
+ },
+ .rotary = 0x0,
.flags = ARC_CAN_10MBIT,
};
@@ -227,9 +333,31 @@ static struct com20020_pci_card_info card_info_eae_ma1 = {
.name = "EAE PLX-PCI MA1",
.devcount = 2,
.chan_map_tbl = {
- { 2, 0x00, 0x08 },
- { 2, 0x08, 0x08 }
+ {
+ .bar = 2,
+ .offset = 0x00,
+ .size = 0x08,
+ }, {
+ .bar = 2,
+ .offset = 0x08,
+ .size = 0x08,
+ }
+ },
+ .misc_map = {
+ .bar = 2,
+ .offset = 0x10,
+ .size = 0x04,
+ },
+ .leds = {
+ {
+ .green = 0x0,
+ .red = 0x1,
+ }, {
+ .green = 0x2,
+ .red = 0x3,
+ },
},
+ .rotary = 0x0,
.flags = ARC_CAN_10MBIT,
};
@@ -404,7 +532,8 @@ static struct pci_driver com20020pci_driver = {
static int __init com20020pci_init(void)
{
- BUGLVL(D_NORMAL) printk(VERSION);
+ if (BUGLVL(D_NORMAL))
+ pr_info("%s\n", "COM20020 PCI support");
return pci_register_driver(&com20020pci_driver);
}
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 1a8437842fbc..13d9ad4b3f5c 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - COM20020 chipset support
- *
+ *
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
* Written 1999 by Martin Mares <mj@ucw.cz>.
@@ -25,6 +25,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -34,17 +37,16 @@
#include <linux/netdevice.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/arcdevice.h>
-#include <linux/com20020.h>
+#include <linux/io.h>
-#include <asm/io.h>
+#include "arcdevice.h"
+#include "com20020.h"
-#define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n"
-
-static char *clockrates[] =
-{"10 Mb/s", "Reserved", "5 Mb/s",
- "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s",
- "156.25 Kb/s", "Reserved", "Reserved", "Reserved"};
+static const char * const clockrates[] = {
+ "XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s",
+ "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", "156.25 Kb/s",
+ "Reserved", "Reserved", "Reserved"
+};
static void com20020_command(struct net_device *dev, int command);
static int com20020_status(struct net_device *dev);
@@ -63,35 +65,38 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum,
int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
/* set up the address register */
- outb((ofs >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
- outb(ofs & 0xff, _ADDR_LO);
+ arcnet_outb((ofs >> 8) | RDDATAflag | AUTOINCflag,
+ ioaddr, COM20020_REG_W_ADDR_HI);
+ arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
/* copy the data */
- TIME("insb", count, insb(_MEMDATA, buf, count));
+ TIME(dev, "insb", count,
+ arcnet_insb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count));
}
-
static void com20020_copy_to_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count)
{
int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
/* set up the address register */
- outb((ofs >> 8) | AUTOINCflag, _ADDR_HI);
- outb(ofs & 0xff, _ADDR_LO);
+ arcnet_outb((ofs >> 8) | AUTOINCflag, ioaddr, COM20020_REG_W_ADDR_HI);
+ arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
/* copy the data */
- TIME("outsb", count, outsb(_MEMDATA, buf, count));
+ TIME(dev, "outsb", count,
+ arcnet_outsb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count));
}
-
/* Reset the card and check some basic stuff during the detection stage. */
int com20020_check(struct net_device *dev)
{
int ioaddr = dev->base_addr, status;
struct arcnet_local *lp = netdev_priv(dev);
- ARCRESET0;
+ arcnet_outb(XTOcfg(3) | RESETcfg, ioaddr, COM20020_REG_W_CONFIG);
+ udelay(5);
+ arcnet_outb(XTOcfg(3), ioaddr, COM20020_REG_W_CONFIG);
mdelay(RESETtime);
lp->setup = lp->clockm ? 0 : (lp->clockp << 1);
@@ -101,49 +106,46 @@ int com20020_check(struct net_device *dev)
/* Enable P1Mode for backplane mode */
lp->setup = lp->setup | P1MODE;
- SET_SUBADR(SUB_SETUP1);
- outb(lp->setup, _XREG);
+ com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
+ arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
+
+ if (lp->clockm != 0) {
+ com20020_set_subaddress(lp, ioaddr, SUB_SETUP2);
+ arcnet_outb(lp->setup2, ioaddr, COM20020_REG_W_XREG);
- if (lp->clockm != 0)
- {
- SET_SUBADR(SUB_SETUP2);
- outb(lp->setup2, _XREG);
-
/* must now write the magic "restart operation" command */
mdelay(1);
- outb(0x18, _COMMAND);
+ arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
}
- lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2);
+ lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
/* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
- SETCONF;
- outb(0x42, ioaddr + BUS_ALIGN*7);
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
+ arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG);
- status = ASTATUS();
+ status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) {
- BUGMSG(D_NORMAL, "status invalid (%Xh).\n", status);
+ arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status);
return -ENODEV;
}
- BUGMSG(D_INIT_REASONS, "status after reset: %X\n", status);
-
- /* Enable TX */
- outb(0x39, _CONFIG);
- outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7);
-
- ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
+ arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status);
- status = ASTATUS();
- BUGMSG(D_INIT_REASONS, "status after reset acknowledged: %X\n",
- status);
+ arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
+ ioaddr, COM20020_REG_W_COMMAND);
+ status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
+ arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n",
+ status);
/* Read first location of memory */
- outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI);
- outb(0, _ADDR_LO);
-
- if ((status = inb(_MEMDATA)) != TESTvalue) {
- BUGMSG(D_NORMAL, "Signature byte not found (%02Xh != D1h).\n",
- status);
+ arcnet_outb(0 | RDDATAflag | AUTOINCflag,
+ ioaddr, COM20020_REG_W_ADDR_HI);
+ arcnet_outb(0, ioaddr, COM20020_REG_W_ADDR_LO);
+
+ status = arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA);
+ if (status != TESTvalue) {
+ arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n",
+ status);
return -ENODEV;
}
return 0;
@@ -156,15 +158,39 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr)
struct sockaddr *hwaddr = addr;
memcpy(dev->dev_addr, hwaddr->sa_data, 1);
- SET_SUBADR(SUB_NODE);
- outb(dev->dev_addr[0], _XREG);
+ com20020_set_subaddress(lp, ioaddr, SUB_NODE);
+ arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
+
+ return 0;
+}
+
+static int com20020_netdev_open(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ struct arcnet_local *lp = netdev_priv(dev);
+
+ lp->config |= TXENcfg;
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
+ return arcnet_open(dev);
+}
+
+static int com20020_netdev_close(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ struct arcnet_local *lp = netdev_priv(dev);
+
+ arcnet_close(dev);
+
+ /* disable transmitter */
+ lp->config &= ~TXENcfg;
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
return 0;
}
const struct net_device_ops com20020_netdev_ops = {
- .ndo_open = arcnet_open,
- .ndo_stop = arcnet_close,
+ .ndo_open = com20020_netdev_open,
+ .ndo_stop = com20020_netdev_close,
.ndo_start_xmit = arcnet_send_packet,
.ndo_tx_timeout = arcnet_timeout,
.ndo_set_mac_address = com20020_set_hwaddr,
@@ -192,48 +218,54 @@ int com20020_found(struct net_device *dev, int shared)
lp->hw.copy_from_card = com20020_copy_from_card;
lp->hw.close = com20020_close;
+ /* FIXME: do this some other way! */
if (!dev->dev_addr[0])
- dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */
+ dev->dev_addr[0] = arcnet_inb(ioaddr, 8);
+
+ com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
+ arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
- SET_SUBADR(SUB_SETUP1);
- outb(lp->setup, _XREG);
+ if (lp->card_flags & ARC_CAN_10MBIT) {
+ com20020_set_subaddress(lp, ioaddr, SUB_SETUP2);
+ arcnet_outb(lp->setup2, ioaddr, COM20020_REG_W_XREG);
- if (lp->card_flags & ARC_CAN_10MBIT)
- {
- SET_SUBADR(SUB_SETUP2);
- outb(lp->setup2, _XREG);
-
/* must now write the magic "restart operation" command */
mdelay(1);
- outb(0x18, _COMMAND);
+ arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
}
- lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1;
+ lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
/* Default 0x38 + register: Node ID */
- SETCONF;
- outb(dev->dev_addr[0], _XREG);
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
+ arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
/* reserve the irq */
if (request_irq(dev->irq, arcnet_interrupt, shared,
"arcnet (COM20020)", dev)) {
- BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
+ arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
dev->base_addr = ioaddr;
- BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
- lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
+ arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
+ lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
if (lp->backplane)
- BUGMSG(D_NORMAL, "Using backplane mode.\n");
+ arc_printk(D_NORMAL, dev, "Using backplane mode.\n");
if (lp->timeout != 3)
- BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout);
-
- BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n",
- lp->setup >> 1,
- clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]);
+ arc_printk(D_NORMAL, dev, "Using extended timeout value of %d\n",
+ lp->timeout);
+
+ arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n",
+ lp->setup >> 1,
+ clockrates[3 -
+ ((lp->setup2 & 0xF0) >> 4) +
+ ((lp->setup & 0x0F) >> 1)]);
+ /* The clockrates array index looks very fragile.
+ * It seems like it could have negative indexing.
+ */
if (register_netdev(dev)) {
free_irq(dev->irq, dev);
@@ -242,10 +274,8 @@ int com20020_found(struct net_device *dev, int shared)
return 0;
}
-
-/*
- * Do a hardware reset on the card, and set up necessary registers.
- *
+/* Do a hardware reset on the card, and set up necessary registers.
+ *
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
*
@@ -257,65 +287,71 @@ static int com20020_reset(struct net_device *dev, int really_reset)
u_int ioaddr = dev->base_addr;
u_char inbyte;
- BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n",
- __FILE__,__LINE__,__func__,dev,lp,dev->name);
- BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
- dev->name, ASTATUS());
+ arc_printk(D_DEBUG, dev, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n",
+ __FILE__, __LINE__, __func__, dev, lp, dev->name);
+ arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
+ dev->name, arcnet_inb(ioaddr, COM20020_REG_R_STATUS));
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
- lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
+ lp->config |= (lp->timeout << 3) | (lp->backplane << 2);
/* power-up defaults */
- SETCONF;
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
if (really_reset) {
/* reset the card */
- ARCRESET;
- mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */
+ arcnet_outb(lp->config | RESETcfg, ioaddr, COM20020_REG_W_CONFIG);
+ udelay(5);
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
+ mdelay(RESETtime * 2);
+ /* COM20020 seems to be slower sometimes */
}
/* clear flags & end reset */
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
- ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
+ arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
+ ioaddr, COM20020_REG_W_COMMAND);
/* verify that the ARCnet signature byte is present */
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
com20020_copy_from_card(dev, 0, 0, &inbyte, 1);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
if (inbyte != TESTvalue) {
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
- BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n",
+ __FILE__, __LINE__, __func__);
+ arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
return 1;
}
/* enable extended (512-byte) packets */
- ACOMMAND(CONFIGcmd | EXTconf);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
+ arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM20020_REG_W_COMMAND);
+
+ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
/* done! return success. */
return 0;
}
-
static void com20020_setmask(struct net_device *dev, int mask)
{
u_int ioaddr = dev->base_addr;
- BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr);
- AINTMASK(mask);
-}
+ arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr);
+ arcnet_outb(mask, ioaddr, COM20020_REG_W_INTMASK);
+}
static void com20020_command(struct net_device *dev, int cmd)
{
u_int ioaddr = dev->base_addr;
- ACOMMAND(cmd);
-}
+ arcnet_outb(cmd, ioaddr, COM20020_REG_W_COMMAND);
+}
static int com20020_status(struct net_device *dev)
{
u_int ioaddr = dev->base_addr;
- return ASTATUS() + (ADIAGSTATUS()<<8);
+ return arcnet_inb(ioaddr, COM20020_REG_R_STATUS) +
+ (arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT) << 8);
}
static void com20020_close(struct net_device *dev)
@@ -325,7 +361,7 @@ static void com20020_close(struct net_device *dev)
/* disable transmitter */
lp->config &= ~TXENcfg;
- SETCONF;
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
}
/* Set or clear the multicast filter for this adaptor.
@@ -340,20 +376,20 @@ static void com20020_set_mc_list(struct net_device *dev)
struct arcnet_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
- if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */
+ if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) {
+ /* Enable promiscuous mode */
if (!(lp->setup & PROMISCset))
- BUGMSG(D_NORMAL, "Setting promiscuous flag...\n");
- SET_SUBADR(SUB_SETUP1);
+ arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n");
+ com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
lp->setup |= PROMISCset;
- outb(lp->setup, _XREG);
- } else
+ arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
+ } else {
/* Disable promiscuous mode, use normal mode */
- {
if ((lp->setup & PROMISCset))
- BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n");
- SET_SUBADR(SUB_SETUP1);
+ arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n");
+ com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
lp->setup &= ~PROMISCset;
- outb(lp->setup, _XREG);
+ arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
}
}
@@ -371,7 +407,8 @@ MODULE_LICENSE("GPL");
static int __init com20020_module_init(void)
{
- BUGLVL(D_NORMAL) printk(VERSION);
+ if (BUGLVL(D_NORMAL))
+ pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)");
return 0;
}
diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h
new file mode 100644
index 000000000000..0bcc5d0a6903
--- /dev/null
+++ b/drivers/net/arcnet/com20020.h
@@ -0,0 +1,132 @@
+/*
+ * Linux ARCnet driver - COM20020 chipset support - function declarations
+ *
+ * Written 1997 by David Woodhouse.
+ * Written 1994-1999 by Avery Pennarun.
+ * Derived from skeleton.c by Donald Becker.
+ *
+ * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
+ * for sponsoring the further development of this driver.
+ *
+ * **********************
+ *
+ * The original copyright of skeleton.c was as follows:
+ *
+ * skeleton.c Written 1993 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency. This software may only be used
+ * and distributed according to the terms of the GNU General Public License as
+ * modified by SRC, incorporated herein by reference.
+ *
+ * **********************
+ *
+ * For more details, see drivers/net/arcnet.c
+ *
+ * **********************
+ */
+#ifndef __COM20020_H
+#define __COM20020_H
+#include <linux/leds.h>
+
+int com20020_check(struct net_device *dev);
+int com20020_found(struct net_device *dev, int shared);
+extern const struct net_device_ops com20020_netdev_ops;
+
+/* The number of low I/O ports used by the card. */
+#define ARCNET_TOTAL_SIZE 8
+
+#define PLX_PCI_MAX_CARDS 2
+
+struct ledoffsets {
+ int green;
+ int red;
+};
+
+struct com20020_pci_channel_map {
+ u32 bar;
+ u32 offset;
+ u32 size; /* 0x00 - auto, e.g. length of entire bar */
+};
+
+struct com20020_pci_card_info {
+ const char *name;
+ int devcount;
+
+ struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS];
+ struct com20020_pci_channel_map misc_map;
+
+ struct ledoffsets leds[PLX_PCI_MAX_CARDS];
+ int rotary;
+
+ unsigned int flags;
+};
+
+struct com20020_priv {
+ struct com20020_pci_card_info *ci;
+ struct list_head list_dev;
+ resource_size_t misc;
+};
+
+struct com20020_dev {
+ struct list_head list;
+ struct net_device *dev;
+
+ struct led_classdev tx_led;
+ struct led_classdev recon_led;
+
+ struct com20020_priv *pci_priv;
+ int index;
+};
+
+#define COM20020_REG_W_INTMASK 0 /* writable */
+#define COM20020_REG_R_STATUS 0 /* readable */
+#define COM20020_REG_W_COMMAND 1 /* standard arcnet commands */
+#define COM20020_REG_R_DIAGSTAT 1 /* diagnostic status */
+#define COM20020_REG_W_ADDR_HI 2 /* control for IO-mapped memory */
+#define COM20020_REG_W_ADDR_LO 3
+#define COM20020_REG_RW_MEMDATA 4 /* data port for IO-mapped memory */
+#define COM20020_REG_W_SUBADR 5 /* the extended port _XREG refers to */
+#define COM20020_REG_W_CONFIG 6 /* configuration */
+#define COM20020_REG_W_XREG 7 /* extra
+ * (indexed by _CONFIG or _SUBADDR)
+ */
+
+/* in the ADDR_HI register */
+#define RDDATAflag 0x80 /* next access is a read (not a write) */
+
+/* in the DIAGSTAT register */
+#define NEWNXTIDflag 0x02 /* ID to which token is passed has changed */
+
+/* in the CONFIG register */
+#define RESETcfg 0x80 /* put card in reset state */
+#define TXENcfg 0x20 /* enable TX */
+#define XTOcfg(x) ((x) << 3) /* extended timeout */
+
+/* in SETUP register */
+#define PROMISCset 0x10 /* enable RCV_ALL */
+#define P1MODE 0x80 /* enable P1-MODE for Backplane */
+#define SLOWARB 0x01 /* enable Slow Arbitration for >=5Mbps */
+
+/* COM2002x */
+#define SUB_TENTATIVE 0 /* tentative node ID */
+#define SUB_NODE 1 /* node ID */
+#define SUB_SETUP1 2 /* various options */
+#define SUB_TEST 3 /* test/diag register */
+
+/* COM20022 only */
+#define SUB_SETUP2 4 /* sundry options */
+#define SUB_BUSCTL 5 /* bus control options */
+#define SUB_DMACOUNT 6 /* DMA count options */
+
+static inline void com20020_set_subaddress(struct arcnet_local *lp,
+ int ioaddr, int val)
+{
+ if (val < 4) {
+ lp->config = (lp->config & ~0x03) | val;
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
+ } else {
+ arcnet_outb(val, ioaddr, COM20020_REG_W_SUBADR);
+ }
+}
+
+#endif /* __COM20020_H */
diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
index 057d9582132a..cf607ffcf358 100644
--- a/drivers/net/arcnet/com20020_cs.c
+++ b/drivers/net/arcnet/com20020_cs.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - COM20020 PCMCIA support
- *
+ *
* Written 1994-1999 by Avery Pennarun,
* based on an ISA version by David Woodhouse.
* Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
@@ -19,18 +19,21 @@
* Director, National Security Agency. This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC, incorporated herein by reference.
- *
+ *
* **********************
* Changes:
* Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
* - reorganize kmallocs in com20020_attach, checking all for failure
* and releasing the previous allocations if one fails
* **********************
- *
+ *
* For more details, see drivers/net/arcnet.c
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
@@ -39,51 +42,44 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/arcdevice.h>
-#include <linux/com20020.h>
-
+#include <linux/io.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
-#include <asm/io.h>
-
-#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
-
+#include "arcdevice.h"
+#include "com20020.h"
static void regdump(struct net_device *dev)
{
#ifdef DEBUG
- int ioaddr = dev->base_addr;
- int count;
-
- netdev_dbg(dev, "register dump:\n");
- for (count = ioaddr; count < ioaddr + 16; count++)
- {
- if (!(count % 16))
- pr_cont("%04X:", count);
- pr_cont(" %02X", inb(count));
- }
- pr_cont("\n");
-
- netdev_dbg(dev, "buffer0 dump:\n");
+ int ioaddr = dev->base_addr;
+ int count;
+
+ netdev_dbg(dev, "register dump:\n");
+ for (count = 0; count < 16; count++) {
+ if (!(count % 16))
+ pr_cont("%04X:", ioaddr + count);
+ pr_cont(" %02X", arcnet_inb(ioaddr, count));
+ }
+ pr_cont("\n");
+
+ netdev_dbg(dev, "buffer0 dump:\n");
/* set up the address register */
- count = 0;
- outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
- outb(count & 0xff, _ADDR_LO);
-
- for (count = 0; count < 256+32; count++)
- {
- if (!(count % 16))
- pr_cont("%04X:", count);
-
- /* copy the data */
- pr_cont(" %02X", inb(_MEMDATA));
- }
- pr_cont("\n");
-#endif
-}
+ count = 0;
+ arcnet_outb((count >> 8) | RDDATAflag | AUTOINCflag,
+ ioaddr, com20020_REG_W_ADDR_HI);
+ arcnet_outb(count & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
+ for (count = 0; count < 256 + 32; count++) {
+ if (!(count % 16))
+ pr_cont("%04X:", count);
+ /* copy the data */
+ pr_cont(" %02X", arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA));
+ }
+ pr_cont("\n");
+#endif
+}
/*====================================================================*/
@@ -114,169 +110,161 @@ static void com20020_detach(struct pcmcia_device *p_dev);
static int com20020_probe(struct pcmcia_device *p_dev)
{
- struct com20020_dev *info;
- struct net_device *dev;
- struct arcnet_local *lp;
+ struct com20020_dev *info;
+ struct net_device *dev;
+ struct arcnet_local *lp;
- dev_dbg(&p_dev->dev, "com20020_attach()\n");
+ dev_dbg(&p_dev->dev, "com20020_attach()\n");
- /* Create new network device */
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- goto fail_alloc_info;
+ /* Create new network device */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ goto fail_alloc_info;
- dev = alloc_arcdev("");
- if (!dev)
- goto fail_alloc_dev;
+ dev = alloc_arcdev("");
+ if (!dev)
+ goto fail_alloc_dev;
- lp = netdev_priv(dev);
- lp->timeout = timeout;
- lp->backplane = backplane;
- lp->clockp = clockp;
- lp->clockm = clockm & 3;
- lp->hw.owner = THIS_MODULE;
+ lp = netdev_priv(dev);
+ lp->timeout = timeout;
+ lp->backplane = backplane;
+ lp->clockp = clockp;
+ lp->clockm = clockm & 3;
+ lp->hw.owner = THIS_MODULE;
- /* fill in our module parameters as defaults */
- dev->dev_addr[0] = node;
+ /* fill in our module parameters as defaults */
+ dev->dev_addr[0] = node;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[0]->end = 16;
- p_dev->config_flags |= CONF_ENABLE_IRQ;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = 16;
+ p_dev->config_flags |= CONF_ENABLE_IRQ;
- info->dev = dev;
- p_dev->priv = info;
+ info->dev = dev;
+ p_dev->priv = info;
- return com20020_config(p_dev);
+ return com20020_config(p_dev);
fail_alloc_dev:
- kfree(info);
+ kfree(info);
fail_alloc_info:
- return -ENOMEM;
+ return -ENOMEM;
} /* com20020_attach */
static void com20020_detach(struct pcmcia_device *link)
{
- struct com20020_dev *info = link->priv;
- struct net_device *dev = info->dev;
+ struct com20020_dev *info = link->priv;
+ struct net_device *dev = info->dev;
- dev_dbg(&link->dev, "detach...\n");
+ dev_dbg(&link->dev, "detach...\n");
- dev_dbg(&link->dev, "com20020_detach\n");
+ dev_dbg(&link->dev, "com20020_detach\n");
- dev_dbg(&link->dev, "unregister...\n");
+ dev_dbg(&link->dev, "unregister...\n");
- unregister_netdev(dev);
+ unregister_netdev(dev);
- /*
- * this is necessary because we register our IRQ separately
- * from card services.
- */
- if (dev->irq)
- free_irq(dev->irq, dev);
+ /* this is necessary because we register our IRQ separately
+ * from card services.
+ */
+ if (dev->irq)
+ free_irq(dev->irq, dev);
- com20020_release(link);
+ com20020_release(link);
- /* Unlink device structure, free bits */
- dev_dbg(&link->dev, "unlinking...\n");
- if (link->priv)
- {
- dev = info->dev;
- if (dev)
- {
- dev_dbg(&link->dev, "kfree...\n");
- free_netdev(dev);
+ /* Unlink device structure, free bits */
+ dev_dbg(&link->dev, "unlinking...\n");
+ if (link->priv) {
+ dev = info->dev;
+ if (dev) {
+ dev_dbg(&link->dev, "kfree...\n");
+ free_netdev(dev);
+ }
+ dev_dbg(&link->dev, "kfree2...\n");
+ kfree(info);
}
- dev_dbg(&link->dev, "kfree2...\n");
- kfree(info);
- }
} /* com20020_detach */
static int com20020_config(struct pcmcia_device *link)
{
- struct arcnet_local *lp;
- struct com20020_dev *info;
- struct net_device *dev;
- int i, ret;
- int ioaddr;
+ struct arcnet_local *lp;
+ struct com20020_dev *info;
+ struct net_device *dev;
+ int i, ret;
+ int ioaddr;
+
+ info = link->priv;
+ dev = info->dev;
+
+ dev_dbg(&link->dev, "config...\n");
+
+ dev_dbg(&link->dev, "com20020_config\n");
- info = link->priv;
- dev = info->dev;
+ dev_dbg(&link->dev, "baseport1 is %Xh\n",
+ (unsigned int)link->resource[0]->start);
- dev_dbg(&link->dev, "config...\n");
+ i = -ENODEV;
+ link->io_lines = 16;
- dev_dbg(&link->dev, "com20020_config\n");
+ if (!link->resource[0]->start) {
+ for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) {
+ link->resource[0]->start = ioaddr;
+ i = pcmcia_request_io(link);
+ if (i == 0)
+ break;
+ }
+ } else {
+ i = pcmcia_request_io(link);
+ }
- dev_dbg(&link->dev, "baseport1 is %Xh\n",
- (unsigned int) link->resource[0]->start);
+ if (i != 0) {
+ dev_dbg(&link->dev, "requestIO failed totally!\n");
+ goto failed;
+ }
- i = -ENODEV;
- link->io_lines = 16;
+ ioaddr = dev->base_addr = link->resource[0]->start;
+ dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
- if (!link->resource[0]->start)
- {
- for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
- {
- link->resource[0]->start = ioaddr;
- i = pcmcia_request_io(link);
- if (i == 0)
- break;
+ dev_dbg(&link->dev, "request IRQ %d\n",
+ link->irq);
+ if (!link->irq) {
+ dev_dbg(&link->dev, "requestIRQ failed totally!\n");
+ goto failed;
}
- }
- else
- i = pcmcia_request_io(link);
-
- if (i != 0)
- {
- dev_dbg(&link->dev, "requestIO failed totally!\n");
- goto failed;
- }
-
- ioaddr = dev->base_addr = link->resource[0]->start;
- dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
-
- dev_dbg(&link->dev, "request IRQ %d\n",
- link->irq);
- if (!link->irq)
- {
- dev_dbg(&link->dev, "requestIRQ failed totally!\n");
- goto failed;
- }
-
- dev->irq = link->irq;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- if (com20020_check(dev))
- {
- regdump(dev);
- goto failed;
- }
-
- lp = netdev_priv(dev);
- lp->card_name = "PCMCIA COM20020";
- lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
-
- SET_NETDEV_DEV(dev, &link->dev);
-
- i = com20020_found(dev, 0); /* calls register_netdev */
-
- if (i != 0) {
- dev_notice(&link->dev,
- "com20020_found() failed\n");
- goto failed;
- }
-
- netdev_dbg(dev, "port %#3lx, irq %d\n",
- dev->base_addr, dev->irq);
- return 0;
+
+ dev->irq = link->irq;
+
+ ret = pcmcia_enable_device(link);
+ if (ret)
+ goto failed;
+
+ if (com20020_check(dev)) {
+ regdump(dev);
+ goto failed;
+ }
+
+ lp = netdev_priv(dev);
+ lp->card_name = "PCMCIA COM20020";
+ lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
+
+ SET_NETDEV_DEV(dev, &link->dev);
+
+ i = com20020_found(dev, 0); /* calls register_netdev */
+
+ if (i != 0) {
+ dev_notice(&link->dev,
+ "com20020_found() failed\n");
+ goto failed;
+ }
+
+ netdev_dbg(dev, "port %#3lx, irq %d\n",
+ dev->base_addr, dev->irq);
+ return 0;
failed:
- dev_dbg(&link->dev, "com20020_config failed...\n");
- com20020_release(link);
- return -ENODEV;
+ dev_dbg(&link->dev, "com20020_config failed...\n");
+ com20020_release(link);
+ return -ENODEV;
} /* com20020_config */
static void com20020_release(struct pcmcia_device *link)
@@ -304,7 +292,10 @@ static int com20020_resume(struct pcmcia_device *link)
if (link->open) {
int ioaddr = dev->base_addr;
struct arcnet_local *lp = netdev_priv(dev);
- ARCRESET;
+
+ arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG);
+ udelay(5);
+ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
}
return 0;
@@ -312,9 +303,9 @@ static int com20020_resume(struct pcmcia_device *link)
static const struct pcmcia_device_id com20020_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
- "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
+ "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
PCMCIA_DEVICE_PROD_ID12("SoHard AG",
- "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
+ "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
diff --git a/drivers/net/arcnet/com9026.h b/drivers/net/arcnet/com9026.h
new file mode 100644
index 000000000000..efcaf6707214
--- /dev/null
+++ b/drivers/net/arcnet/com9026.h
@@ -0,0 +1,17 @@
+#ifndef __COM9026_H
+#define __COM9026_H
+
+/* COM 9026 controller chip --> ARCnet register addresses */
+
+#define COM9026_REG_W_INTMASK 0 /* writable */
+#define COM9026_REG_R_STATUS 0 /* readable */
+#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */
+#define COM9026_REG_RW_CONFIG 2 /* Configuration register */
+#define COM9026_REG_R_RESET 8 /* software reset (on read) */
+#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */
+#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */
+#define COM9026_REG_W_ADDR_HI 15
+
+#define COM9026_REG_R_STATION 1 /* Station ID */
+
+#endif
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 487d780ebbdf..b57863df5bf5 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - COM90xx chipset (IO-mapped buffers)
- *
+ *
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
@@ -25,6 +25,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -34,12 +37,10 @@
#include <linux/bootmem.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <linux/arcdevice.h>
-
-
-#define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n"
+#include <linux/io.h>
+#include "arcdevice.h"
+#include "com9026.h"
/* Internal function declarations */
@@ -50,35 +51,14 @@ static void com90io_setmask(struct net_device *dev, int mask);
static int com90io_reset(struct net_device *dev, int really_reset);
static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count);
-static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count);
-
+static void com90io_copy_from_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count);
/* Handy defines for ARCnet specific stuff */
/* The number of low I/O ports used by the card. */
#define ARCNET_TOTAL_SIZE 16
-/* COM 9026 controller chip --> ARCnet register addresses */
-#define _INTMASK (ioaddr+0) /* writable */
-#define _STATUS (ioaddr+0) /* readable */
-#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
-#define _RESET (ioaddr+8) /* software reset (on read) */
-#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */
-#define _ADDR_HI (ioaddr+15) /* Control registers for said */
-#define _ADDR_LO (ioaddr+14)
-#define _CONFIG (ioaddr+2) /* Configuration register */
-
-#undef ASTATUS
-#undef ACOMMAND
-#undef AINTMASK
-
-#define ASTATUS() inb(_STATUS)
-#define ACOMMAND(cmd) outb((cmd),_COMMAND)
-#define AINTMASK(msk) outb((msk),_INTMASK)
-#define SETCONF() outb((lp->config),_CONFIG)
-
-
/****************************************************************************
* *
* IO-mapped operation routines *
@@ -92,58 +72,59 @@ static u_char get_buffer_byte(struct net_device *dev, unsigned offset)
{
int ioaddr = dev->base_addr;
- outb(offset >> 8, _ADDR_HI);
- outb(offset & 0xff, _ADDR_LO);
+ arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
+ arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
- return inb(_MEMDATA);
+ return arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
}
#ifdef ONE_AT_A_TIME_TX
-static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datum)
+static void put_buffer_byte(struct net_device *dev, unsigned offset,
+ u_char datum)
{
int ioaddr = dev->base_addr;
- outb(offset >> 8, _ADDR_HI);
- outb(offset & 0xff, _ADDR_LO);
+ arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
+ arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
- outb(datum, _MEMDATA);
+ arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA);
}
#endif
-
-static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest)
+static void get_whole_buffer(struct net_device *dev, unsigned offset,
+ unsigned length, char *dest)
{
int ioaddr = dev->base_addr;
- outb((offset >> 8) | AUTOINCflag, _ADDR_HI);
- outb(offset & 0xff, _ADDR_LO);
+ arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
+ arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
while (length--)
#ifdef ONE_AT_A_TIME_RX
*(dest++) = get_buffer_byte(dev, offset++);
#else
- *(dest++) = inb(_MEMDATA);
+ *(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
#endif
}
-static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest)
+static void put_whole_buffer(struct net_device *dev, unsigned offset,
+ unsigned length, char *dest)
{
int ioaddr = dev->base_addr;
- outb((offset >> 8) | AUTOINCflag, _ADDR_HI);
- outb(offset & 0xff, _ADDR_LO);
+ arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
+ arcnet_outb(offset & 0xff, ioaddr,COM9026_REG_W_ADDR_LO);
while (length--)
#ifdef ONE_AT_A_TIME_TX
put_buffer_byte(dev, offset++, *(dest++));
#else
- outb(*(dest++), _MEMDATA);
+ arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA);
#endif
}
-/*
- * We cannot probe for an IO mapped card either, although we can check that
+/* We cannot probe for an IO mapped card either, although we can check that
* it's where we were told it was, and even autoirq
*/
static int __init com90io_probe(struct net_device *dev)
@@ -151,71 +132,78 @@ static int __init com90io_probe(struct net_device *dev)
int ioaddr = dev->base_addr, status;
unsigned long airqmask;
- BUGLVL(D_NORMAL) printk(VERSION);
- BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n");
+ if (BUGLVL(D_NORMAL)) {
+ pr_info("%s\n", "COM90xx IO-mapped mode support (by David Woodhouse et el.)");
+ pr_info("E-mail me if you actually test this driver, please!\n");
+ }
if (!ioaddr) {
- BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you "
- "must specify the base address!\n");
+ arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n");
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
- BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
- ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
+ arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n",
+ ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
- if (ASTATUS() == 0xFF) {
- BUGMSG(D_INIT_REASONS, "IO address %x empty\n", ioaddr);
+ if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
+ arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n",
+ ioaddr);
goto err_out;
}
- inb(_RESET);
+ arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
- status = ASTATUS();
+ status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
- BUGMSG(D_INIT_REASONS, "Status invalid (%Xh).\n", status);
+ arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n",
+ status);
goto err_out;
}
- BUGMSG(D_INIT_REASONS, "Status after reset: %X\n", status);
+ arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status);
- ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
+ arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
+ ioaddr, COM9026_REG_W_COMMAND);
- BUGMSG(D_INIT_REASONS, "Status after reset acknowledged: %X\n", status);
+ arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n",
+ status);
- status = ASTATUS();
+ status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if (status & RESETflag) {
- BUGMSG(D_INIT_REASONS, "Eternal reset (status=%Xh)\n", status);
+ arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n",
+ status);
goto err_out;
}
- outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG);
+ arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag,
+ ioaddr, COM9026_REG_RW_CONFIG);
/* Read first loc'n of memory */
- outb(AUTOINCflag, _ADDR_HI);
- outb(0, _ADDR_LO);
+ arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
+ arcnet_outb(0, ioaddr, COM9026_REG_W_ADDR_LO);
- if ((status = inb(_MEMDATA)) != 0xd1) {
- BUGMSG(D_INIT_REASONS, "Signature byte not found"
- " (%Xh instead).\n", status);
+ status = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
+ if (status != 0xd1) {
+ arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n",
+ status);
goto err_out;
}
if (!dev->irq) {
- /*
- * if we do this, we're sure to get an IRQ since the
+ /* if we do this, we're sure to get an IRQ since the
* card has just reset and the NORXflag is on until
* we tell it to start receiving.
*/
airqmask = probe_irq_on();
- outb(NORXflag, _INTMASK);
+ arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
udelay(1);
- outb(0, _INTMASK);
+ arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
dev->irq = probe_irq_off(airqmask);
if ((int)dev->irq <= 0) {
- BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed\n");
+ arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n");
goto err_out;
}
}
@@ -227,7 +215,6 @@ err_out:
return -ENODEV;
}
-
/* Set up the struct net_device associated with this card. Called after
* probing succeeds.
*/
@@ -238,12 +225,14 @@ static int __init com90io_found(struct net_device *dev)
int err;
/* Reserve the irq */
- if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) {
- BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
+ if (request_irq(dev->irq, arcnet_interrupt, 0,
+ "arcnet (COM90xx-IO)", dev)) {
+ arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
/* Reserve the I/O region */
- if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
+ if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE,
+ "arcnet (COM90xx-IO)")) {
free_irq(dev->irq, dev);
return -EBUSY;
}
@@ -259,7 +248,7 @@ static int __init com90io_found(struct net_device *dev)
lp->hw.copy_from_card = com90io_copy_from_card;
lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
- SETCONF();
+ arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
/* get and check the station ID from offset 1 in shmem */
@@ -267,21 +256,20 @@ static int __init com90io_found(struct net_device *dev)
err = register_netdev(dev);
if (err) {
- outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
+ arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
+ ioaddr, COM9026_REG_RW_CONFIG);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
return err;
}
- BUGMSG(D_NORMAL, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
- dev->dev_addr[0], dev->base_addr, dev->irq);
+ arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
+ dev->dev_addr[0], dev->base_addr, dev->irq);
return 0;
}
-
-/*
- * Do a hardware reset on the card, and set up necessary registers.
+/* Do a hardware reset on the card, and set up necessary registers.
*
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
@@ -293,67 +281,66 @@ static int com90io_reset(struct net_device *dev, int really_reset)
struct arcnet_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
- BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
+ arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
+ dev->name, arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
if (really_reset) {
/* reset the card */
- inb(_RESET);
+ arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
}
/* Set the thing to IO-mapped, 8-bit mode */
lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag;
- SETCONF();
+ arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
- ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
- ACOMMAND(CFLAGScmd | CONFIGclear);
+ arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
+ /* clear flags & end reset */
+ arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
/* verify that the ARCnet signature byte is present */
if (get_buffer_byte(dev, 0) != TESTvalue) {
- BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
+ arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
return 1;
}
/* enable extended (512-byte) packets */
- ACOMMAND(CONFIGcmd | EXTconf);
-
+ arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
/* done! return success. */
return 0;
}
-
static void com90io_command(struct net_device *dev, int cmd)
{
short ioaddr = dev->base_addr;
- ACOMMAND(cmd);
+ arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
}
-
static int com90io_status(struct net_device *dev)
{
short ioaddr = dev->base_addr;
- return ASTATUS();
+ return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
}
-
static void com90io_setmask(struct net_device *dev, int mask)
{
short ioaddr = dev->base_addr;
- AINTMASK(mask);
+ arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
}
-static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count)
+static void com90io_copy_to_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count)
{
- TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
+ TIME(dev, "put_whole_buffer", count,
+ put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
}
-
-static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count)
+static void com90io_copy_from_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count)
{
- TIME("get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
+ TIME(dev, "get_whole_buffer", count,
+ get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
}
static int io; /* use the insmod io= irq= shmem= options */
@@ -369,12 +356,13 @@ MODULE_LICENSE("GPL");
static int __init com90io_setup(char *s)
{
int ints[4];
+
s = get_options(s, 4, ints);
if (!ints[0])
return 0;
switch (ints[0]) {
default: /* ERROR */
- printk("com90io: Too many arguments.\n");
+ pr_err("Too many arguments\n");
case 2: /* IRQ */
irq = ints[2];
case 1: /* IO address */
@@ -421,8 +409,11 @@ static void __exit com90io_exit(void)
unregister_netdev(dev);
- /* Set the thing back to MMAP mode, in case the old driver is loaded later */
- outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
+ /* In case the old driver is loaded later,
+ * set the thing back to MMAP mode
+ */
+ arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
+ ioaddr, COM9026_REG_RW_CONFIG);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index b80fbe40aa0e..0d9b45ff1bb2 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - COM90xx chipset (memory-mapped buffers)
- *
+ *
* Written 1994-1999 by Avery Pennarun.
* Written 1999 by Martin Mares <mj@ucw.cz>.
* Derived from skeleton.c by Donald Becker.
@@ -24,6 +24,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -32,12 +35,10 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/arcdevice.h>
-
-
-#define VERSION "arcnet: COM90xx chipset support\n"
+#include <linux/io.h>
+#include "arcdevice.h"
+#include "com9026.h"
/* Define this to speed up the autoprobe by assuming if only one io port and
* shmem are left in the list at Stage 5, they must correspond to each
@@ -53,7 +54,6 @@
*/
#undef FAST_PROBE
-
/* Internal function declarations */
static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *);
static void com90xx_command(struct net_device *dev, int command);
@@ -62,8 +62,8 @@ static void com90xx_setmask(struct net_device *dev, int mask);
static int com90xx_reset(struct net_device *dev, int really_reset);
static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count);
-static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count);
+static void com90xx_copy_from_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count);
/* Known ARCnet cards */
@@ -77,26 +77,7 @@ static int numcards;
/* Amount of I/O memory used by the card */
#define BUFFER_SIZE (512)
-#define MIRROR_SIZE (BUFFER_SIZE*4)
-
-/* COM 9026 controller chip --> ARCnet register addresses */
-#define _INTMASK (ioaddr+0) /* writable */
-#define _STATUS (ioaddr+0) /* readable */
-#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
-#define _CONFIG (ioaddr+2) /* Configuration register */
-#define _RESET (ioaddr+8) /* software reset (on read) */
-#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */
-#define _ADDR_HI (ioaddr+15) /* Control registers for said */
-#define _ADDR_LO (ioaddr+14)
-
-#undef ASTATUS
-#undef ACOMMAND
-#undef AINTMASK
-
-#define ASTATUS() inb(_STATUS)
-#define ACOMMAND(cmd) outb((cmd),_COMMAND)
-#define AINTMASK(msk) outb((msk),_INTMASK)
-
+#define MIRROR_SIZE (BUFFER_SIZE * 4)
static int com90xx_skip_probe __initdata = 0;
@@ -116,8 +97,7 @@ static void __init com90xx_probe(void)
{
int count, status, ioaddr, numprint, airq, openparen = 0;
unsigned long airqmask;
- int ports[(0x3f0 - 0x200) / 16 + 1] =
- {0};
+ int ports[(0x3f0 - 0x200) / 16 + 1] = { 0 };
unsigned long *shmems;
void __iomem **iomem;
int numports, numshmems, *port;
@@ -127,18 +107,19 @@ static void __init com90xx_probe(void)
if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
return;
- shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long),
+ shmems = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(unsigned long),
GFP_KERNEL);
if (!shmems)
return;
- iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *),
- GFP_KERNEL);
+ iomem = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(void __iomem *),
+ GFP_KERNEL);
if (!iomem) {
kfree(shmems);
return;
}
- BUGLVL(D_NORMAL) printk(VERSION);
+ if (BUGLVL(D_NORMAL))
+ pr_info("%s\n", "COM90xx chipset support");
/* set up the arrays where we'll store the possible probe addresses */
numports = numshmems = 0;
@@ -161,38 +142,43 @@ static void __init com90xx_probe(void)
numprint++;
numprint %= 8;
if (!numprint) {
- BUGMSG2(D_INIT, "\n");
- BUGMSG2(D_INIT, "S1: ");
+ arc_cont(D_INIT, "\n");
+ arc_cont(D_INIT, "S1: ");
}
- BUGMSG2(D_INIT, "%Xh ", *port);
+ arc_cont(D_INIT, "%Xh ", *port);
ioaddr = *port;
- if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) {
- BUGMSG2(D_INIT_REASONS, "(request_region)\n");
- BUGMSG2(D_INIT_REASONS, "S1: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ if (!request_region(*port, ARCNET_TOTAL_SIZE,
+ "arcnet (90xx)")) {
+ arc_cont(D_INIT_REASONS, "(request_region)\n");
+ arc_cont(D_INIT_REASONS, "S1: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
*port-- = ports[--numports];
continue;
}
- if (ASTATUS() == 0xFF) {
- BUGMSG2(D_INIT_REASONS, "(empty)\n");
- BUGMSG2(D_INIT_REASONS, "S1: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
+ arc_cont(D_INIT_REASONS, "(empty)\n");
+ arc_cont(D_INIT_REASONS, "S1: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
}
- inb(_RESET); /* begin resetting card */
+ /* begin resetting card */
+ arcnet_inb(ioaddr, COM9026_REG_R_RESET);
- BUGMSG2(D_INIT_REASONS, "\n");
- BUGMSG2(D_INIT_REASONS, "S1: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, "\n");
+ arc_cont(D_INIT_REASONS, "S1: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
}
- BUGMSG2(D_INIT, "\n");
+ arc_cont(D_INIT, "\n");
if (!numports) {
- BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");
+ arc_cont(D_NORMAL, "S1: No ARCnet cards found.\n");
kfree(shmems);
kfree(iomem);
return;
@@ -206,12 +192,12 @@ static void __init com90xx_probe(void)
numprint++;
numprint %= 8;
if (!numprint) {
- BUGMSG2(D_INIT, "\n");
- BUGMSG2(D_INIT, "S2: ");
+ arc_cont(D_INIT, "\n");
+ arc_cont(D_INIT, "S2: ");
}
- BUGMSG2(D_INIT, "%Xh ", *port);
+ arc_cont(D_INIT, "%Xh ", *port);
}
- BUGMSG2(D_INIT, "\n");
+ arc_cont(D_INIT, "\n");
mdelay(RESETtime);
/* Stage 3: abandon any shmem addresses that don't have the signature
@@ -224,29 +210,33 @@ static void __init com90xx_probe(void)
numprint++;
numprint %= 8;
if (!numprint) {
- BUGMSG2(D_INIT, "\n");
- BUGMSG2(D_INIT, "S3: ");
+ arc_cont(D_INIT, "\n");
+ arc_cont(D_INIT, "S3: ");
}
- BUGMSG2(D_INIT, "%lXh ", *p);
+ arc_cont(D_INIT, "%lXh ", *p);
if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) {
- BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n");
- BUGMSG2(D_INIT_REASONS, "Stage 3: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, "(request_mem_region)\n");
+ arc_cont(D_INIT_REASONS, "Stage 3: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
goto out;
}
base = ioremap(*p, MIRROR_SIZE);
if (!base) {
- BUGMSG2(D_INIT_REASONS, "(ioremap)\n");
- BUGMSG2(D_INIT_REASONS, "Stage 3: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, "(ioremap)\n");
+ arc_cont(D_INIT_REASONS, "Stage 3: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
goto out1;
}
- if (readb(base) != TESTvalue) {
- BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
- readb(base), TESTvalue);
- BUGMSG2(D_INIT_REASONS, "S3: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ if (arcnet_readb(base, COM9026_REG_R_STATUS) != TESTvalue) {
+ arc_cont(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
+ arcnet_readb(base, COM9026_REG_R_STATUS),
+ TESTvalue);
+ arc_cont(D_INIT_REASONS, "S3: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
goto out2;
}
/* By writing 0x42 to the TESTvalue location, we also make
@@ -254,15 +244,16 @@ static void __init com90xx_probe(void)
* in another pass through this loop, they will be discarded
* because *cptr != TESTvalue.
*/
- writeb(0x42, base);
- if (readb(base) != 0x42) {
- BUGMSG2(D_INIT_REASONS, "(read only)\n");
- BUGMSG2(D_INIT_REASONS, "S3: ");
+ arcnet_writeb(0x42, base, COM9026_REG_W_INTMASK);
+ if (arcnet_readb(base, COM9026_REG_R_STATUS) != 0x42) {
+ arc_cont(D_INIT_REASONS, "(read only)\n");
+ arc_cont(D_INIT_REASONS, "S3: ");
goto out2;
}
- BUGMSG2(D_INIT_REASONS, "\n");
- BUGMSG2(D_INIT_REASONS, "S3: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, "\n");
+ arc_cont(D_INIT_REASONS, "S3: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
iomem[index] = base;
continue;
out2:
@@ -273,10 +264,10 @@ static void __init com90xx_probe(void)
*p-- = shmems[--numshmems];
index--;
}
- BUGMSG2(D_INIT, "\n");
+ arc_cont(D_INIT, "\n");
if (!numshmems) {
- BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");
+ arc_cont(D_NORMAL, "S3: No ARCnet cards found.\n");
for (port = &ports[0]; port < ports + numports; port++)
release_region(*port, ARCNET_TOTAL_SIZE);
kfree(shmems);
@@ -291,12 +282,12 @@ static void __init com90xx_probe(void)
numprint++;
numprint %= 8;
if (!numprint) {
- BUGMSG2(D_INIT, "\n");
- BUGMSG2(D_INIT, "S4: ");
+ arc_cont(D_INIT, "\n");
+ arc_cont(D_INIT, "S4: ");
}
- BUGMSG2(D_INIT, "%lXh ", *p);
+ arc_cont(D_INIT, "%lXh ", *p);
}
- BUGMSG2(D_INIT, "\n");
+ arc_cont(D_INIT, "\n");
/* Stage 5: for any ports that have the correct status, can disable
* the RESET flag, and (if no irq is given) generate an autoirq,
@@ -308,33 +299,37 @@ static void __init com90xx_probe(void)
numprint = -1;
for (port = &ports[0]; port < ports + numports; port++) {
int found = 0;
+
numprint++;
numprint %= 8;
if (!numprint) {
- BUGMSG2(D_INIT, "\n");
- BUGMSG2(D_INIT, "S5: ");
+ arc_cont(D_INIT, "\n");
+ arc_cont(D_INIT, "S5: ");
}
- BUGMSG2(D_INIT, "%Xh ", *port);
+ arc_cont(D_INIT, "%Xh ", *port);
ioaddr = *port;
- status = ASTATUS();
+ status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if ((status & 0x9D)
!= (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
- BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);
- BUGMSG2(D_INIT_REASONS, "S5: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, "(status=%Xh)\n", status);
+ arc_cont(D_INIT_REASONS, "S5: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
}
- ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
- status = ASTATUS();
+ arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
+ ioaddr, COM9026_REG_W_COMMAND);
+ status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if (status & RESETflag) {
- BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
- status);
- BUGMSG2(D_INIT_REASONS, "S5: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
+ status);
+ arc_cont(D_INIT_REASONS, "S5: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
@@ -348,15 +343,16 @@ static void __init com90xx_probe(void)
* we tell it to start receiving.
*/
airqmask = probe_irq_on();
- AINTMASK(NORXflag);
+ arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
udelay(1);
- AINTMASK(0);
+ arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
airq = probe_irq_off(airqmask);
if (airq <= 0) {
- BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq);
- BUGMSG2(D_INIT_REASONS, "S5: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ arc_cont(D_INIT_REASONS, "(airq=%d)\n", airq);
+ arc_cont(D_INIT_REASONS, "S5: ");
+ if (BUGLVL(D_INIT_REASONS))
+ numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
@@ -365,7 +361,7 @@ static void __init com90xx_probe(void)
airq = irq;
}
- BUGMSG2(D_INIT, "(%d,", airq);
+ arc_cont(D_INIT, "(%d,", airq);
openparen = 1;
/* Everything seems okay. But which shmem, if any, puts
@@ -376,14 +372,15 @@ static void __init com90xx_probe(void)
*/
#ifdef FAST_PROBE
if (numports > 1 || numshmems > 1) {
- inb(_RESET);
+ arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
} else {
/* just one shmem and port, assume they match */
- writeb(TESTvalue, iomem[0]);
+ arcnet_writeb(TESTvalue, iomem[0],
+ COM9026_REG_W_INTMASK);
}
#else
- inb(_RESET);
+ arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
#endif
@@ -391,8 +388,8 @@ static void __init com90xx_probe(void)
u_long ptr = shmems[index];
void __iomem *base = iomem[index];
- if (readb(base) == TESTvalue) { /* found one */
- BUGMSG2(D_INIT, "%lXh)\n", *p);
+ if (arcnet_readb(base, COM9026_REG_R_STATUS) == TESTvalue) { /* found one */
+ arc_cont(D_INIT, "%lXh)\n", *p);
openparen = 0;
/* register the card */
@@ -405,25 +402,30 @@ static void __init com90xx_probe(void)
iomem[index] = iomem[numshmems];
break; /* go to the next I/O port */
} else {
- BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base));
+ arc_cont(D_INIT_REASONS, "%Xh-",
+ arcnet_readb(base, COM9026_REG_R_STATUS));
}
}
if (openparen) {
- BUGLVL(D_INIT) printk("no matching shmem)\n");
- BUGLVL(D_INIT_REASONS) printk("S5: ");
- BUGLVL(D_INIT_REASONS) numprint = 0;
+ if (BUGLVL(D_INIT))
+ pr_cont("no matching shmem)\n");
+ if (BUGLVL(D_INIT_REASONS)) {
+ pr_cont("S5: ");
+ numprint = 0;
+ }
}
if (!found)
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
}
- BUGLVL(D_INIT_REASONS) printk("\n");
+ if (BUGLVL(D_INIT_REASONS))
+ pr_cont("\n");
/* Now put back TESTvalue on all leftover shmems. */
for (index = 0; index < numshmems; index++) {
- writeb(TESTvalue, iomem[index]);
+ arcnet_writeb(TESTvalue, iomem[index], COM9026_REG_W_INTMASK);
iounmap(iomem[index]);
release_mem_region(shmems[index], MIRROR_SIZE);
}
@@ -441,7 +443,7 @@ static int check_mirror(unsigned long addr, size_t size)
p = ioremap(addr, size);
if (p) {
- if (readb(p) == TESTvalue)
+ if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
res = 1;
else
res = 0;
@@ -455,7 +457,8 @@ static int check_mirror(unsigned long addr, size_t size)
/* Set up the struct net_device associated with this card. Called after
* probing succeeds.
*/
-static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p)
+static int __init com90xx_found(int ioaddr, int airq, u_long shmem,
+ void __iomem *p)
{
struct net_device *dev = NULL;
struct arcnet_local *lp;
@@ -465,7 +468,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
/* allocate struct net_device */
dev = alloc_arcdev(device);
if (!dev) {
- BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n");
+ arc_cont(D_NORMAL, "com90xx: Can't allocate device!\n");
iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
return -ENOMEM;
@@ -478,7 +481,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
* 2k (or there are no mirrors at all) but on some, it's 4k.
*/
mirror_size = MIRROR_SIZE;
- if (readb(p) == TESTvalue &&
+ if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue &&
check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
mirror_size = 2 * MIRROR_SIZE;
@@ -499,12 +502,14 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
- if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)"))
+ if (!request_mem_region(dev->mem_start,
+ dev->mem_end - dev->mem_start + 1,
+ "arcnet (90xx)"))
goto err_free_dev;
/* reserve the irq */
if (request_irq(airq, arcnet_interrupt, 0, "arcnet (90xx)", dev)) {
- BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq);
+ arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", airq);
goto err_release_mem;
}
dev->irq = airq;
@@ -518,22 +523,23 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
lp->hw.owner = THIS_MODULE;
lp->hw.copy_to_card = com90xx_copy_to_card;
lp->hw.copy_from_card = com90xx_copy_from_card;
- lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1);
+ lp->mem_start = ioremap(dev->mem_start,
+ dev->mem_end - dev->mem_start + 1);
if (!lp->mem_start) {
- BUGMSG(D_NORMAL, "Can't remap device memory!\n");
+ arc_printk(D_NORMAL, dev, "Can't remap device memory!\n");
goto err_free_irq;
}
/* get and check the station ID from offset 1 in shmem */
- dev->dev_addr[0] = readb(lp->mem_start + 1);
+ dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
dev->base_addr = ioaddr;
- BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, "
- "ShMem %lXh (%ld*%xh).\n",
- dev->dev_addr[0],
- dev->base_addr, dev->irq, dev->mem_start,
- (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size);
+ arc_printk(D_NORMAL, dev, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n",
+ dev->dev_addr[0],
+ dev->base_addr, dev->irq, dev->mem_start,
+ (dev->mem_end - dev->mem_start + 1) / mirror_size,
+ mirror_size);
if (register_netdev(dev))
goto err_unmap;
@@ -552,34 +558,29 @@ err_free_dev:
return -EIO;
}
-
static void com90xx_command(struct net_device *dev, int cmd)
{
short ioaddr = dev->base_addr;
- ACOMMAND(cmd);
+ arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
}
-
static int com90xx_status(struct net_device *dev)
{
short ioaddr = dev->base_addr;
- return ASTATUS();
+ return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
}
-
static void com90xx_setmask(struct net_device *dev, int mask)
{
short ioaddr = dev->base_addr;
- AINTMASK(mask);
+ arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
}
-
-/*
- * Do a hardware reset on the card, and set up necessary registers.
- *
+/* Do a hardware reset on the card, and set up necessary registers.
+ *
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
*
@@ -590,53 +591,58 @@ static int com90xx_reset(struct net_device *dev, int really_reset)
struct arcnet_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
- BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
+ arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n",
+ arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
if (really_reset) {
/* reset the card */
- inb(_RESET);
+ arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
}
- ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
- ACOMMAND(CFLAGScmd | CONFIGclear);
+ /* clear flags & end reset */
+ arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
+ arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
+#if 0
/* don't do this until we verify that it doesn't hurt older cards! */
- /* outb(inb(_CONFIG) | ENABLE16flag, _CONFIG); */
+ arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) | ENABLE16flag,
+ ioaddr, COM9026_REG_RW_CONFIG);
+#endif
/* verify that the ARCnet signature byte is present */
- if (readb(lp->mem_start) != TESTvalue) {
+ if (arcnet_readb(lp->mem_start, COM9026_REG_R_STATUS) != TESTvalue) {
if (really_reset)
- BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
+ arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
return 1;
}
/* enable extended (512-byte) packets */
- ACOMMAND(CONFIGcmd | EXTconf);
+ arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
/* clean out all the memory to make debugging make more sense :) */
- BUGLVL(D_DURING)
- memset_io(lp->mem_start, 0x42, 2048);
+ if (BUGLVL(D_DURING))
+ memset_io(lp->mem_start, 0x42, 2048);
/* done! return success. */
return 0;
}
-static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count)
+static void com90xx_copy_to_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
- TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
-}
+ TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count));
+}
-static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset,
- void *buf, int count)
+static void com90xx_copy_from_card(struct net_device *dev, int bufnum,
+ int offset, void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
- TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
-}
+ TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
+}
MODULE_LICENSE("GPL");
@@ -664,7 +670,8 @@ static void __exit com90xx_exit(void)
free_irq(dev->irq, dev);
iounmap(lp->mem_start);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
+ release_mem_region(dev->mem_start,
+ dev->mem_end - dev->mem_start + 1);
free_netdev(dev);
}
}
@@ -679,13 +686,13 @@ static int __init com90xx_setup(char *s)
s = get_options(s, 8, ints);
if (!ints[0] && !*s) {
- printk("com90xx: Disabled.\n");
+ pr_notice("Disabled\n");
return 1;
}
switch (ints[0]) {
default: /* ERROR */
- printk("com90xx: Too many arguments.\n");
+ pr_err("Too many arguments\n");
case 3: /* Mem address */
shmem = ints[3];
case 2: /* IRQ */
diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c
index f81db4070a57..4b1a75469cb1 100644
--- a/drivers/net/arcnet/rfc1051.c
+++ b/drivers/net/arcnet/rfc1051.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - RFC1051 ("simple" standard) packet encapsulation
- *
+ *
* Written 1994-1999 by Avery Pennarun.
* Derived from skeleton.c by Donald Becker.
*
@@ -23,6 +23,9 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/init.h>
@@ -30,10 +33,8 @@
#include <net/arp.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
-#include <linux/arcdevice.h>
-
-#define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n"
+#include "arcdevice.h"
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev);
static void rx(struct net_device *dev, int bufnum,
@@ -43,9 +44,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum);
-
-static struct ArcProto rfc1051_proto =
-{
+static struct ArcProto rfc1051_proto = {
.suffix = 's',
.mtu = XMTU - RFC1051_HDR_SIZE,
.is_ip = 1,
@@ -56,10 +55,9 @@ static struct ArcProto rfc1051_proto =
.ack_tx = NULL
};
-
static int __init arcnet_rfc1051_init(void)
{
- printk(VERSION);
+ pr_info("%s\n", "RFC1051 \"simple standard\" (`s') encapsulation support loaded");
arc_proto_map[ARC_P_IP_RFC1051]
= arc_proto_map[ARC_P_ARP_RFC1051]
@@ -82,14 +80,13 @@ module_exit(arcnet_rfc1051_exit);
MODULE_LICENSE("GPL");
-/*
- * Determine a packet's protocol ID.
- *
+/* Determine a packet's protocol ID.
+ *
* With ARCnet we have to convert everything to Ethernet-style stuff.
*/
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
{
- struct archdr *pkt = (struct archdr *) skb->data;
+ struct archdr *pkt = (struct archdr *)skb->data;
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
@@ -97,9 +94,9 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
skb_reset_mac_header(skb);
skb_pull(skb, hdr_size);
- if (pkt->hard.dest == 0)
+ if (pkt->hard.dest == 0) {
skb->pkt_type = PACKET_BROADCAST;
- else if (dev->flags & IFF_PROMISC) {
+ } else if (dev->flags & IFF_PROMISC) {
/* if we're not sending to ourselves :) */
if (pkt->hard.dest != dev->dev_addr[0])
skb->pkt_type = PACKET_OTHERHOST;
@@ -120,7 +117,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
return htons(ETH_P_IP);
}
-
/* packet receiver */
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
@@ -130,7 +126,7 @@ static void rx(struct net_device *dev, int bufnum,
struct archdr *pkt = pkthdr;
int ofs;
- BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
+ arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length);
if (length >= MinTU)
ofs = 512 - length;
@@ -138,15 +134,14 @@ static void rx(struct net_device *dev, int bufnum,
ofs = 256 - length;
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ if (!skb) {
dev->stats.rx_dropped++;
return;
}
skb_put(skb, length + ARC_HDR_SIZE);
skb->dev = dev;
- pkt = (struct archdr *) skb->data;
+ pkt = (struct archdr *)skb->data;
/* up to sizeof(pkt->soft) has already been copied from the card */
memcpy(pkt, pkthdr, sizeof(struct archdr));
@@ -155,21 +150,19 @@ static void rx(struct net_device *dev, int bufnum,
pkt->soft.raw + sizeof(pkt->soft),
length - sizeof(pkt->soft));
- BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, skb, "rx");
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
}
-
-/*
- * Create the ARCnet hard/soft headers for RFC1051.
- */
+/* Create the ARCnet hard/soft headers for RFC1051 */
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
- struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
+ struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
/* set the protocol ID according to RFC1051 */
@@ -181,29 +174,26 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
soft->proto = ARC_P_ARP_RFC1051;
break;
default:
- BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n",
- type, type);
+ arc_printk(D_NORMAL, dev, "RFC1051: I don't understand protocol %d (%Xh)\n",
+ type, type);
dev->stats.tx_errors++;
dev->stats.tx_aborted_errors++;
return 0;
}
-
- /*
- * Set the source hardware address.
+ /* Set the source hardware address.
*
* This is pretty pointless for most purposes, but it can help in
- * debugging. ARCnet does not allow us to change the source address in
- * the actual packet sent)
+ * debugging. ARCnet does not allow us to change the source address
+ * in the actual packet sent.
*/
pkt->hard.source = *dev->dev_addr;
/* see linux/net/ethernet/eth.c to see where I got the following */
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
- /*
- * FIXME: fill in the last byte of the dest ipaddr here to better
- * comply with RFC1051 in "noarp" mode.
+ /* FIXME: fill in the last byte of the dest ipaddr here to
+ * better comply with RFC1051 in "noarp" mode.
*/
pkt->hard.dest = 0;
return hdr_size;
@@ -214,7 +204,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
return hdr_size; /* success */
}
-
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
@@ -222,15 +211,16 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
struct arc_hardware *hard = &pkt->hard;
int ofs;
- BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
- lp->next_tx, lp->cur_tx, bufnum);
+ arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
+ lp->next_tx, lp->cur_tx, bufnum);
- length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
+ /* hard header is not included in packet length */
+ length -= ARC_HDR_SIZE;
if (length > XMTU) {
/* should never happen! other people already check for this. */
- BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
- length, XMTU);
+ arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n",
+ length, XMTU);
length = XMTU;
}
if (length > MinTU) {
@@ -239,8 +229,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
} else if (length > MTU) {
hard->offset[0] = 0;
hard->offset[1] = ofs = 512 - length - 3;
- } else
+ } else {
hard->offset[0] = ofs = 256 - length;
+ }
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
index b71431aae084..566da5ecdc9d 100644
--- a/drivers/net/arcnet/rfc1201.c
+++ b/drivers/net/arcnet/rfc1201.c
@@ -1,6 +1,6 @@
/*
* Linux ARCnet driver - RFC1201 (standard) packet encapsulation
- *
+ *
* Written 1994-1999 by Avery Pennarun.
* Derived from skeleton.c by Donald Becker.
*
@@ -23,17 +23,19 @@
*
* **********************
*/
+
+#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
+
#include <linux/gfp.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
-#include <linux/arcdevice.h>
-MODULE_LICENSE("GPL");
-#define VERSION "arcnet: RFC1201 \"standard\" (`a') encapsulation support loaded.\n"
+#include "arcdevice.h"
+MODULE_LICENSE("GPL");
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev);
static void rx(struct net_device *dev, int bufnum,
@@ -44,8 +46,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum);
static int continue_tx(struct net_device *dev, int bufnum);
-static struct ArcProto rfc1201_proto =
-{
+static struct ArcProto rfc1201_proto = {
.suffix = 'a',
.mtu = 1500, /* could be more, but some receivers can't handle it... */
.is_ip = 1, /* This is for sending IP and ARP packages */
@@ -56,10 +57,9 @@ static struct ArcProto rfc1201_proto =
.ack_tx = NULL
};
-
static int __init arcnet_rfc1201_init(void)
{
- printk(VERSION);
+ pr_info("%s\n", "RFC1201 \"standard\" (`a') encapsulation support loaded");
arc_proto_map[ARC_P_IP]
= arc_proto_map[ARC_P_IPV6]
@@ -84,14 +84,13 @@ static void __exit arcnet_rfc1201_exit(void)
module_init(arcnet_rfc1201_init);
module_exit(arcnet_rfc1201_exit);
-/*
- * Determine a packet's protocol ID.
- *
+/* Determine a packet's protocol ID.
+ *
* With ARCnet we have to convert everything to Ethernet-style stuff.
*/
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
{
- struct archdr *pkt = (struct archdr *) skb->data;
+ struct archdr *pkt = (struct archdr *)skb->data;
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
@@ -99,9 +98,9 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
skb_reset_mac_header(skb);
skb_pull(skb, hdr_size);
- if (pkt->hard.dest == 0)
+ if (pkt->hard.dest == 0) {
skb->pkt_type = PACKET_BROADCAST;
- else if (dev->flags & IFF_PROMISC) {
+ } else if (dev->flags & IFF_PROMISC) {
/* if we're not sending to ourselves :) */
if (pkt->hard.dest != dev->dev_addr[0])
skb->pkt_type = PACKET_OTHERHOST;
@@ -129,7 +128,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
return htons(ETH_P_IP);
}
-
/* packet receiver */
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
@@ -141,7 +139,8 @@ static void rx(struct net_device *dev, int bufnum,
int saddr = pkt->hard.source, ofs;
struct Incoming *in = &lp->rfc1201.incoming[saddr];
- BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n", length);
+ arc_printk(D_DURING, dev, "it's an RFC1201 packet (length=%d)\n",
+ length);
if (length >= MinTU)
ofs = 512 - length;
@@ -149,11 +148,11 @@ static void rx(struct net_device *dev, int bufnum,
ofs = 256 - length;
if (soft->split_flag == 0xFF) { /* Exception Packet */
- if (length >= 4 + RFC1201_HDR_SIZE)
- BUGMSG(D_DURING, "compensating for exception packet\n");
- else {
- BUGMSG(D_EXTRA, "short RFC1201 exception packet from %02Xh",
- saddr);
+ if (length >= 4 + RFC1201_HDR_SIZE) {
+ arc_printk(D_DURING, dev, "compensating for exception packet\n");
+ } else {
+ arc_printk(D_EXTRA, dev, "short RFC1201 exception packet from %02Xh",
+ saddr);
return;
}
@@ -164,12 +163,13 @@ static void rx(struct net_device *dev, int bufnum,
soft, sizeof(pkt->soft));
}
if (!soft->split_flag) { /* not split */
- BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n",
- soft->split_flag);
+ arc_printk(D_RX, dev, "incoming is not split (splitflag=%d)\n",
+ soft->split_flag);
if (in->skb) { /* already assembling one! */
- BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
- in->sequence, soft->split_flag, soft->sequence);
+ arc_printk(D_EXTRA, dev, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+ in->sequence, soft->split_flag,
+ soft->sequence);
lp->rfc1201.aborted_seq = soft->sequence;
dev_kfree_skb_irq(in->skb);
dev->stats.rx_errors++;
@@ -179,82 +179,86 @@ static void rx(struct net_device *dev, int bufnum,
in->sequence = soft->sequence;
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ if (!skb) {
dev->stats.rx_dropped++;
return;
}
skb_put(skb, length + ARC_HDR_SIZE);
skb->dev = dev;
- pkt = (struct archdr *) skb->data;
+ pkt = (struct archdr *)skb->data;
soft = &pkt->soft.rfc1201;
- /* up to sizeof(pkt->soft) has already been copied from the card */
+ /* up to sizeof(pkt->soft) has already
+ * been copied from the card
+ */
memcpy(pkt, pkthdr, sizeof(struct archdr));
if (length > sizeof(pkt->soft))
- lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
- pkt->soft.raw + sizeof(pkt->soft),
+ lp->hw.copy_from_card(dev, bufnum,
+ ofs + sizeof(pkt->soft),
+ pkt->soft.raw + sizeof(pkt->soft),
length - sizeof(pkt->soft));
- /*
- * ARP packets have problems when sent from some DOS systems: the
- * source address is always 0! So we take the hardware source addr
- * (which is impossible to fumble) and insert it ourselves.
+ /* ARP packets have problems when sent from some DOS systems:
+ * the source address is always 0!
+ * So we take the hardware source addr (which is impossible
+ * to fumble) and insert it ourselves.
*/
if (soft->proto == ARC_P_ARP) {
- struct arphdr *arp = (struct arphdr *) soft->payload;
+ struct arphdr *arp = (struct arphdr *)soft->payload;
/* make sure addresses are the right length */
if (arp->ar_hln == 1 && arp->ar_pln == 4) {
- uint8_t *cptr = (uint8_t *) arp + sizeof(struct arphdr);
+ uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr);
if (!*cptr) { /* is saddr = 00? */
- BUGMSG(D_EXTRA,
- "ARP source address was 00h, set to %02Xh.\n",
- saddr);
+ arc_printk(D_EXTRA, dev,
+ "ARP source address was 00h, set to %02Xh\n",
+ saddr);
dev->stats.rx_crc_errors++;
*cptr = saddr;
} else {
- BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n",
- *cptr);
+ arc_printk(D_DURING, dev, "ARP source address (%Xh) is fine.\n",
+ *cptr);
}
} else {
- BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n",
- arp->ar_hln, arp->ar_pln);
+ arc_printk(D_NORMAL, dev, "funny-shaped ARP packet. (%Xh, %Xh)\n",
+ arp->ar_hln, arp->ar_pln);
dev->stats.rx_errors++;
dev->stats.rx_crc_errors++;
}
}
- BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, skb, "rx");
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
} else { /* split packet */
- /*
- * NOTE: MSDOS ARP packet correction should only need to apply to
- * unsplit packets, since ARP packets are so short.
+ /* NOTE: MSDOS ARP packet correction should only need to
+ * apply to unsplit packets, since ARP packets are so short.
*
- * My interpretation of the RFC1201 document is that if a packet is
- * received out of order, the entire assembly process should be
- * aborted.
+ * My interpretation of the RFC1201 document is that if a
+ * packet is received out of order, the entire assembly
+ * process should be aborted.
*
- * The RFC also mentions "it is possible for successfully received
- * packets to be retransmitted." As of 0.40 all previously received
- * packets are allowed, not just the most recent one.
+ * The RFC also mentions "it is possible for successfully
+ * received packets to be retransmitted." As of 0.40 all
+ * previously received packets are allowed, not just the
+ * most recent one.
*
- * We allow multiple assembly processes, one for each ARCnet card
- * possible on the network. Seems rather like a waste of memory,
- * but there's no other way to be reliable.
+ * We allow multiple assembly processes, one for each
+ * ARCnet card possible on the network.
+ * Seems rather like a waste of memory, but there's no
+ * other way to be reliable.
*/
- BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n",
- soft->split_flag, in->sequence);
+ arc_printk(D_RX, dev, "packet is split (splitflag=%d, seq=%d)\n",
+ soft->split_flag, in->sequence);
if (in->skb && in->sequence != soft->sequence) {
- BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
- saddr, in->sequence, soft->sequence,
- soft->split_flag);
+ arc_printk(D_EXTRA, dev, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+ saddr, in->sequence, soft->sequence,
+ soft->split_flag);
dev_kfree_skb_irq(in->skb);
in->skb = NULL;
dev->stats.rx_errors++;
@@ -262,24 +266,23 @@ static void rx(struct net_device *dev, int bufnum,
in->lastpacket = in->numpackets = 0;
}
if (soft->split_flag & 1) { /* first packet in split */
- BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n",
- soft->split_flag);
+ arc_printk(D_RX, dev, "brand new splitpacket (splitflag=%d)\n",
+ soft->split_flag);
if (in->skb) { /* already assembling one! */
- BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly "
- "(splitflag=%d, seq=%d)\n",
- in->sequence, soft->split_flag,
- soft->sequence);
+ arc_printk(D_EXTRA, dev, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+ in->sequence, soft->split_flag,
+ soft->sequence);
dev->stats.rx_errors++;
dev->stats.rx_missed_errors++;
dev_kfree_skb_irq(in->skb);
}
in->sequence = soft->sequence;
- in->numpackets = ((unsigned) soft->split_flag >> 1) + 2;
+ in->numpackets = ((unsigned)soft->split_flag >> 1) + 2;
in->lastpacket = 1;
if (in->numpackets > 16) {
- BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
- soft->split_flag);
+ arc_printk(D_EXTRA, dev, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+ soft->split_flag);
lp->rfc1201.aborted_seq = soft->sequence;
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
@@ -287,14 +290,14 @@ static void rx(struct net_device *dev, int bufnum,
}
in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE,
GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");
+ if (!skb) {
+ arc_printk(D_NORMAL, dev, "(split) memory squeeze, dropping packet.\n");
lp->rfc1201.aborted_seq = soft->sequence;
dev->stats.rx_dropped++;
return;
}
skb->dev = dev;
- pkt = (struct archdr *) skb->data;
+ pkt = (struct archdr *)skb->data;
soft = &pkt->soft.rfc1201;
memcpy(pkt, pkthdr, ARC_HDR_SIZE + RFC1201_HDR_SIZE);
@@ -302,37 +305,37 @@ static void rx(struct net_device *dev, int bufnum,
soft->split_flag = 0; /* end result won't be split */
} else { /* not first packet */
- int packetnum = ((unsigned) soft->split_flag >> 1) + 1;
+ int packetnum = ((unsigned)soft->split_flag >> 1) + 1;
- /*
- * if we're not assembling, there's no point trying to
+ /* if we're not assembling, there's no point trying to
* continue.
*/
if (!in->skb) {
if (lp->rfc1201.aborted_seq != soft->sequence) {
- BUGMSG(D_EXTRA, "can't continue split without starting "
- "first! (splitflag=%d, seq=%d, aborted=%d)\n",
- soft->split_flag, soft->sequence,
- lp->rfc1201.aborted_seq);
+ arc_printk(D_EXTRA, dev, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
+ soft->split_flag,
+ soft->sequence,
+ lp->rfc1201.aborted_seq);
dev->stats.rx_errors++;
dev->stats.rx_missed_errors++;
}
return;
}
in->lastpacket++;
- if (packetnum != in->lastpacket) { /* not the right flag! */
+ /* if not the right flag */
+ if (packetnum != in->lastpacket) {
/* harmless duplicate? ignore. */
if (packetnum <= in->lastpacket - 1) {
- BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n",
- soft->split_flag);
+ arc_printk(D_EXTRA, dev, "duplicate splitpacket ignored! (splitflag=%d)\n",
+ soft->split_flag);
dev->stats.rx_errors++;
dev->stats.rx_frame_errors++;
return;
}
/* "bad" duplicate, kill reassembly */
- BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly "
- "(seq=%d) aborted (splitflag=%d, seq=%d)\n",
- in->sequence, soft->split_flag, soft->sequence);
+ arc_printk(D_EXTRA, dev, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
+ in->sequence, soft->split_flag,
+ soft->sequence);
lp->rfc1201.aborted_seq = soft->sequence;
dev_kfree_skb_irq(in->skb);
in->skb = NULL;
@@ -341,7 +344,7 @@ static void rx(struct net_device *dev, int bufnum,
in->lastpacket = in->numpackets = 0;
return;
}
- pkt = (struct archdr *) in->skb->data;
+ pkt = (struct archdr *)in->skb->data;
soft = &pkt->soft.rfc1201;
}
@@ -357,11 +360,12 @@ static void rx(struct net_device *dev, int bufnum,
in->skb = NULL;
in->lastpacket = in->numpackets = 0;
- BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n",
- skb->len, pkt->hard.source);
- BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n",
- skb->len, pkt->hard.source);
- BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+ arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (unsplit)\n",
+ skb->len, pkt->hard.source);
+ arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (split)\n",
+ skb->len, pkt->hard.source);
+ if (BUGLVL(D_SKB))
+ arcnet_dump_skb(dev, skb, "rx");
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
@@ -369,14 +373,13 @@ static void rx(struct net_device *dev, int bufnum,
}
}
-
/* Create the ARCnet hard/soft headers for RFC1201. */
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
struct arcnet_local *lp = netdev_priv(dev);
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
- struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
+ struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
/* set the protocol ID according to RFC1201 */
@@ -402,19 +405,18 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
soft->proto = ARC_P_ATALK;
break;
default:
- BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n",
- type, type);
+ arc_printk(D_NORMAL, dev, "RFC1201: I don't understand protocol %d (%Xh)\n",
+ type, type);
dev->stats.tx_errors++;
dev->stats.tx_aborted_errors++;
return 0;
}
- /*
- * Set the source hardware address.
+ /* Set the source hardware address.
*
* This is pretty pointless for most purposes, but it can help in
- * debugging. ARCnet does not allow us to change the source address in
- * the actual packet sent)
+ * debugging. ARCnet does not allow us to change the source address
+ * in the actual packet sent.
*/
pkt->hard.source = *dev->dev_addr;
@@ -424,10 +426,10 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
/* see linux/net/ethernet/eth.c to see where I got the following */
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
- /*
- * FIXME: fill in the last byte of the dest ipaddr here to better
- * comply with RFC1051 in "noarp" mode. For now, always broadcasting
- * will probably at least get packets sent out :)
+ /* FIXME: fill in the last byte of the dest ipaddr here
+ * to better comply with RFC1051 in "noarp" mode.
+ * For now, always broadcasting will probably at least get
+ * packets sent out :)
*/
pkt->hard.dest = 0;
return hdr_size;
@@ -437,7 +439,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
return hdr_size;
}
-
static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
struct arc_rfc1201 *soft, int softlen, int bufnum)
{
@@ -461,8 +462,9 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
hard->offset[1] = ofs - RFC1201_HDR_SIZE;
lp->hw.copy_to_card(dev, bufnum, ofs - RFC1201_HDR_SIZE,
&excsoft, RFC1201_HDR_SIZE);
- } else
+ } else {
hard->offset[0] = ofs = 256 - softlen;
+ }
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
lp->hw.copy_to_card(dev, bufnum, ofs, soft, softlen);
@@ -470,7 +472,6 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
lp->lastload_dest = hard->dest;
}
-
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
@@ -478,11 +479,11 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
const int maxsegsize = XMTU - RFC1201_HDR_SIZE;
struct Outgoing *out;
+ arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
+ lp->next_tx, lp->cur_tx, bufnum);
- BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
- lp->next_tx, lp->cur_tx, bufnum);
-
- length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
+ /* hard header is not included in packet length */
+ length -= ARC_HDR_SIZE;
pkt->soft.rfc1201.split_flag = 0;
/* need to do a split packet? */
@@ -494,9 +495,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize;
out->segnum = 0;
- BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split "
- "(%d bytes, seq=%d)\n", out->numsegs, out->length,
- pkt->soft.rfc1201.sequence);
+ arc_printk(D_DURING, dev, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n",
+ out->numsegs, out->length,
+ pkt->soft.rfc1201.sequence);
return 0; /* not done */
}
@@ -506,7 +507,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
return 1; /* done */
}
-
static int continue_tx(struct net_device *dev, int bufnum)
{
struct arcnet_local *lp = netdev_priv(dev);
@@ -516,9 +516,9 @@ static int continue_tx(struct net_device *dev, int bufnum)
int maxsegsize = XMTU - RFC1201_HDR_SIZE;
int seglen;
- BUGMSG(D_DURING,
- "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n",
- out->segnum, out->numsegs, soft->sequence);
+ arc_printk(D_DURING, dev,
+ "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n",
+ out->segnum, out->numsegs, soft->sequence);
/* the "new" soft header comes right before the data chunk */
newsoft = (struct arc_rfc1201 *)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 3c45358844eb..940e2ebbdea8 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -127,6 +127,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
struct port *port);
static void ad_marker_response_received(struct bond_marker *marker,
struct port *port);
+static void ad_update_actor_keys(struct port *port, bool reset);
/* ================= api to bonding and kernel code ================== */
@@ -327,14 +328,12 @@ static u16 __get_link_speed(struct port *port)
static u8 __get_duplex(struct port *port)
{
struct slave *slave = port->slave;
- u8 retval;
+ u8 retval = 0x0;
/* handling a special case: when the configuration starts with
* link down, it sets the duplex to 0.
*/
- if (slave->link != BOND_LINK_UP) {
- retval = 0x0;
- } else {
+ if (slave->link == BOND_LINK_UP) {
switch (slave->duplex) {
case DUPLEX_FULL:
retval = 0x1;
@@ -1953,14 +1952,7 @@ void bond_3ad_bind_slave(struct slave *slave)
* user key
*/
port->actor_admin_port_key = bond->params.ad_user_port_key << 6;
- port->actor_admin_port_key |= __get_duplex(port);
- port->actor_admin_port_key |= (__get_link_speed(port) << 1);
- port->actor_oper_port_key = port->actor_admin_port_key;
- /* if the port is not full duplex, then the port should be not
- * lacp Enabled
- */
- if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS))
- port->sm_vars &= ~AD_PORT_LACP_ENABLED;
+ ad_update_actor_keys(port, false);
/* actor system is the bond's system */
port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
port->actor_system_priority =
@@ -2310,45 +2302,60 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
}
/**
- * bond_3ad_adapter_speed_changed - handle a slave's speed change indication
- * @slave: slave struct to work on
+ * ad_update_actor_keys - Update the oper / admin keys for a port based on
+ * its current speed and duplex settings.
*
- * Handle reselection of aggregator (if needed) for this port.
+ * @port: the port we'are looking at
+ * @reset: Boolean to just reset the speed and the duplex part of the key
+ *
+ * The logic to change the oper / admin keys is:
+ * (a) A full duplex port can participate in LACP with partner.
+ * (b) When the speed is changed, LACP need to be reinitiated.
*/
-void bond_3ad_adapter_speed_changed(struct slave *slave)
+static void ad_update_actor_keys(struct port *port, bool reset)
{
- struct port *port;
-
- port = &(SLAVE_AD_INFO(slave)->port);
-
- /* if slave is null, the whole port is not initialized */
- if (!port->slave) {
- netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n",
- slave->dev->name);
- return;
+ u8 duplex = 0;
+ u16 ospeed = 0, speed = 0;
+ u16 old_oper_key = port->actor_oper_port_key;
+
+ port->actor_admin_port_key &= ~(AD_SPEED_KEY_MASKS|AD_DUPLEX_KEY_MASKS);
+ if (!reset) {
+ speed = __get_link_speed(port);
+ ospeed = (old_oper_key & AD_SPEED_KEY_MASKS) >> 1;
+ duplex = __get_duplex(port);
+ port->actor_admin_port_key |= (speed << 1) | duplex;
}
-
- spin_lock_bh(&slave->bond->mode_lock);
-
- port->actor_admin_port_key &= ~AD_SPEED_KEY_MASKS;
- port->actor_admin_port_key |= __get_link_speed(port) << 1;
port->actor_oper_port_key = port->actor_admin_port_key;
- netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number);
- /* there is no need to reselect a new aggregator, just signal the
- * state machines to reinitialize
- */
- port->sm_vars |= AD_PORT_BEGIN;
- spin_unlock_bh(&slave->bond->mode_lock);
+ if (old_oper_key != port->actor_oper_port_key) {
+ /* Only 'duplex' port participates in LACP */
+ if (duplex)
+ port->sm_vars |= AD_PORT_LACP_ENABLED;
+ else
+ port->sm_vars &= ~AD_PORT_LACP_ENABLED;
+
+ if (!reset) {
+ if (!speed) {
+ netdev_err(port->slave->dev,
+ "speed changed to 0 for port %s",
+ port->slave->dev->name);
+ } else if (duplex && ospeed != speed) {
+ /* Speed change restarts LACP state-machine */
+ port->sm_vars |= AD_PORT_BEGIN;
+ }
+ }
+ }
}
/**
- * bond_3ad_adapter_duplex_changed - handle a slave's duplex change indication
+ * bond_3ad_adapter_speed_duplex_changed - handle a slave's speed / duplex
+ * change indication
+ *
* @slave: slave struct to work on
*
* Handle reselection of aggregator (if needed) for this port.
*/
-void bond_3ad_adapter_duplex_changed(struct slave *slave)
+void bond_3ad_adapter_speed_duplex_changed(struct slave *slave)
{
struct port *port;
@@ -2356,25 +2363,16 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
/* if slave is null, the whole port is not initialized */
if (!port->slave) {
- netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n",
+ netdev_warn(slave->bond->dev,
+ "speed/duplex changed for uninitialized port %s\n",
slave->dev->name);
return;
}
spin_lock_bh(&slave->bond->mode_lock);
-
- port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS;
- port->actor_admin_port_key |= __get_duplex(port);
- port->actor_oper_port_key = port->actor_admin_port_key;
- netdev_dbg(slave->bond->dev, "Port %d slave %s changed duplex\n",
+ ad_update_actor_keys(port, false);
+ netdev_dbg(slave->bond->dev, "Port %d slave %s changed speed/duplex\n",
port->actor_port_number, slave->dev->name);
- if (port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)
- port->sm_vars |= AD_PORT_LACP_ENABLED;
- /* there is no need to reselect a new aggregator, just signal the
- * state machines to reinitialize
- */
- port->sm_vars |= AD_PORT_BEGIN;
-
spin_unlock_bh(&slave->bond->mode_lock);
}
@@ -2406,26 +2404,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
* on link up we are forcing recheck on the duplex and speed since
* some of he adaptors(ce1000.lan) report.
*/
- port->actor_admin_port_key &= ~(AD_DUPLEX_KEY_MASKS|AD_SPEED_KEY_MASKS);
if (link == BOND_LINK_UP) {
port->is_enabled = true;
- port->actor_admin_port_key |=
- (__get_link_speed(port) << 1) | __get_duplex(port);
- if (port->actor_admin_port_key & AD_DUPLEX_KEY_MASKS)
- port->sm_vars |= AD_PORT_LACP_ENABLED;
+ ad_update_actor_keys(port, false);
} else {
/* link has failed */
port->is_enabled = false;
- port->sm_vars &= ~AD_PORT_LACP_ENABLED;
+ ad_update_actor_keys(port, true);
}
- port->actor_oper_port_key = port->actor_admin_port_key;
netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
port->actor_port_number,
link == BOND_LINK_UP ? "UP" : "DOWN");
- /* there is no need to reselect a new aggregator, just signal the
- * state machines to reinitialize
- */
- port->sm_vars |= AD_PORT_BEGIN;
spin_unlock_bh(&slave->bond->mode_lock);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 771a449d2f56..9e0f8a7ef8b1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1071,7 +1071,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
NETIF_F_HIGHDMA | NETIF_F_LRO)
#define BOND_ENC_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | NETIF_F_RXCSUM |\
- NETIF_F_TSO)
+ NETIF_F_ALL_TSO)
static void bond_compute_features(struct bonding *bond)
{
@@ -1749,6 +1749,7 @@ err_undo_flags:
slave_dev->dev_addr))
eth_hw_addr_random(bond_dev);
if (bond_dev->type != ARPHRD_ETHER) {
+ dev_close(bond_dev);
ether_setup(bond_dev);
bond_dev->flags |= IFF_MASTER;
bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
@@ -2943,8 +2944,6 @@ static int bond_slave_netdev_event(unsigned long event,
struct slave *slave = bond_slave_get_rtnl(slave_dev), *primary;
struct bonding *bond;
struct net_device *bond_dev;
- u32 old_speed;
- u8 old_duplex;
/* A netdev event can be generated while enslaving a device
* before netdev_rx_handler_register is called in which case
@@ -2965,17 +2964,9 @@ static int bond_slave_netdev_event(unsigned long event,
break;
case NETDEV_UP:
case NETDEV_CHANGE:
- old_speed = slave->speed;
- old_duplex = slave->duplex;
-
bond_update_speed_duplex(slave);
-
- if (BOND_MODE(bond) == BOND_MODE_8023AD) {
- if (old_speed != slave->speed)
- bond_3ad_adapter_speed_changed(slave);
- if (old_duplex != slave->duplex)
- bond_3ad_adapter_duplex_changed(slave);
- }
+ if (BOND_MODE(bond) == BOND_MODE_8023AD)
+ bond_3ad_adapter_speed_duplex_changed(slave);
/* Fallthrough */
case NETDEV_DOWN:
/* Refresh slave-array if applicable!
@@ -3136,6 +3127,10 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
struct flow_keys flow;
u32 hash;
+ if (bond->params.xmit_policy == BOND_XMIT_POLICY_ENCAP34 &&
+ skb->l4_hash)
+ return skb->hash;
+
if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER2 ||
!bond_flow_dissect(bond, skb, &flow))
return bond_eth_hash(skb);
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index de3962014af7..4721948a92f6 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -730,11 +730,14 @@ int cfspi_spi_probe(struct platform_device *pdev)
int res;
dev = (struct cfspi_dev *)pdev->dev.platform_data;
- ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d",
- NET_NAME_UNKNOWN, cfspi_setup);
if (!dev)
return -ENODEV;
+ ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d",
+ NET_NAME_UNKNOWN, cfspi_setup);
+ if (!ndev)
+ return -ENOMEM;
+
cfspi = netdev_priv(ndev);
netif_stop_queue(ndev);
cfspi->ndev = ndev;
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index e8c96b8e86f4..6d04183ed955 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -129,6 +129,16 @@ config CAN_RCAR
To compile this driver as a module, choose M here: the module will
be called rcar_can.
+config CAN_SUN4I
+ tristate "Allwinner A10 CAN controller"
+ depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
+ ---help---
+ Say Y here if you want to use CAN controller found on Allwinner
+ A10/A20 SoCs.
+
+ To compile this driver as a module, choose M here: the module will
+ be called sun4i_can.
+
config CAN_XILINXCAN
tristate "Xilinx CAN"
depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index c533c62b0f5e..1f21cef1d458 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
obj-$(CONFIG_PCH_CAN) += pch_can.o
obj-$(CONFIG_CAN_GRCAN) += grcan.o
obj-$(CONFIG_CAN_RCAR) += rcar_can.o
+obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o
obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o
subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 945c0955a967..8b3275d7792a 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -8,15 +8,6 @@
* Public License ("GPL") version 2 as distributed in the 'COPYING'
* file from the main directory of the linux kernel source.
*
- *
- * Your platform definition file should specify something like:
- *
- * static struct at91_can_data ek_can_data = {
- * transceiver_switch = sam9263ek_transceiver_switch,
- * };
- *
- * at91_add_device_can(&ek_can_data);
- *
*/
#include <linux/clk.h>
@@ -33,7 +24,6 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
-#include <linux/platform_data/atmel.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
@@ -324,15 +314,6 @@ static inline u32 at91_can_id_to_reg_mid(canid_t can_id)
return reg_mid;
}
-/*
- * Swtich transceiver on or off
- */
-static void at91_transceiver_switch(const struct at91_priv *priv, int on)
-{
- if (priv->pdata && priv->pdata->transceiver_switch)
- priv->pdata->transceiver_switch(on);
-}
-
static void at91_setup_mailboxes(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
@@ -416,7 +397,6 @@ static void at91_chip_start(struct net_device *dev)
at91_set_bittiming(dev);
at91_setup_mailboxes(dev);
- at91_transceiver_switch(priv, 1);
/* enable chip */
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
@@ -444,7 +424,6 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
reg_mr = at91_read(priv, AT91_MR);
at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN);
- at91_transceiver_switch(priv, 0);
priv->can.state = state;
}
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index aede704605c6..141c2a42d7ed 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -915,7 +915,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put(skb, IFLA_CAN_BITTIMING_CONST,
sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
- nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) ||
+ nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
nla_put_u32(skb, IFLA_CAN_STATE, state) ||
nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index c83f0f03482b..868fe945e35a 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -26,12 +26,8 @@
#include <linux/can/led.h>
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -63,10 +59,10 @@
#define FLEXCAN_MCR_LPRIO_EN BIT(13)
#define FLEXCAN_MCR_AEN BIT(12)
#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f)
-#define FLEXCAN_MCR_IDAM_A (0 << 8)
-#define FLEXCAN_MCR_IDAM_B (1 << 8)
-#define FLEXCAN_MCR_IDAM_C (2 << 8)
-#define FLEXCAN_MCR_IDAM_D (3 << 8)
+#define FLEXCAN_MCR_IDAM_A (0x0 << 8)
+#define FLEXCAN_MCR_IDAM_B (0x1 << 8)
+#define FLEXCAN_MCR_IDAM_C (0x2 << 8)
+#define FLEXCAN_MCR_IDAM_D (0x3 << 8)
/* FLEXCAN control register (CANCTRL) bits */
#define FLEXCAN_CTRL_PRESDIV(x) (((x) & 0xff) << 24)
@@ -161,7 +157,7 @@
#define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24)
#define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24)
#define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24)
-#define FLEXCAN_MB_CODE_RX_OVERRRUN (0x6 << 24)
+#define FLEXCAN_MB_CODE_RX_OVERRUN (0x6 << 24)
#define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24)
#define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24)
@@ -175,12 +171,9 @@
#define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16)
#define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff)
-#define FLEXCAN_MB_CODE_MASK (0xf0ffffff)
+#define FLEXCAN_TIMEOUT_US (50)
-#define FLEXCAN_TIMEOUT_US (50)
-
-/*
- * FLEXCAN hardware feature flags
+/* FLEXCAN hardware feature flags
*
* Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re-
@@ -194,9 +187,9 @@
*
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/
-#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */
-#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */
-#define FLEXCAN_HAS_MECR_FEATURES BIT(3) /* Memory error detection */
+#define FLEXCAN_QUIRK_BROKEN_ERR_STATE BIT(1) /* [TR]WRN_INT not connected */
+#define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */
+#define FLEXCAN_QUIRK_DISABLE_MECR BIT(3) /* Disble Memory error detection */
/* Structure of the message buffer */
struct flexcan_mb {
@@ -228,7 +221,7 @@ struct flexcan_regs {
u32 rxfgmask; /* 0x48 */
u32 rxfir; /* 0x4c */
u32 _reserved3[12]; /* 0x50 */
- struct flexcan_mb cantxfg[64]; /* 0x80 */
+ struct flexcan_mb mb[64]; /* 0x80 */
/* FIFO-mode:
* MB
* 0x080...0x08f 0 RX message buffer
@@ -236,7 +229,7 @@ struct flexcan_regs {
* 0x0e0...0x0ff 6-7 8 entry ID table
* (mx25, mx28, mx35, mx53)
* 0x0e0...0x2df 6-7..37 8..128 entry ID table
- * size conf'ed via ctrl2::RFFN
+ * size conf'ed via ctrl2::RFFN
* (mx6, vf610)
*/
u32 _reserved4[408];
@@ -251,14 +244,14 @@ struct flexcan_regs {
};
struct flexcan_devtype_data {
- u32 features; /* hardware controller features */
+ u32 quirks; /* quirks needed for different IP cores */
};
struct flexcan_priv {
struct can_priv can;
struct napi_struct napi;
- void __iomem *base;
+ struct flexcan_regs __iomem *regs;
u32 reg_esr;
u32 reg_ctrl_default;
@@ -270,14 +263,17 @@ struct flexcan_priv {
};
static struct flexcan_devtype_data fsl_p1010_devtype_data = {
- .features = FLEXCAN_HAS_BROKEN_ERR_STATE,
+ .quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE,
};
+
static struct flexcan_devtype_data fsl_imx28_devtype_data;
+
static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
- .features = FLEXCAN_HAS_V10_FEATURES,
+ .quirks = FLEXCAN_QUIRK_DISABLE_RXFG,
};
+
static struct flexcan_devtype_data fsl_vf610_devtype_data = {
- .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES,
+ .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
};
static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -292,11 +288,10 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
.brp_inc = 1,
};
-/*
- * Abstract off the read/write for arm versus ppc. This
+/* Abstract off the read/write for arm versus ppc. This
* assumes that PPC uses big-endian registers and everything
* else uses little-endian registers, independent of CPU
- * endianess.
+ * endianness.
*/
#if defined(CONFIG_PPC)
static inline u32 flexcan_read(void __iomem *addr)
@@ -345,7 +340,7 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
static int flexcan_chip_enable(struct flexcan_priv *priv)
{
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg;
@@ -364,7 +359,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
static int flexcan_chip_disable(struct flexcan_priv *priv)
{
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg;
@@ -383,7 +378,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
static int flexcan_chip_freeze(struct flexcan_priv *priv)
{
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
u32 reg;
@@ -402,7 +397,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
{
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg;
@@ -421,7 +416,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
static int flexcan_chip_softreset(struct flexcan_priv *priv)
{
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
@@ -434,12 +429,11 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)
return 0;
}
-
static int __flexcan_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec)
{
const struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
u32 reg = flexcan_read(&regs->ecr);
bec->txerr = (reg >> 0) & 0xff;
@@ -474,9 +468,10 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
const struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
struct can_frame *cf = (struct can_frame *)skb->data;
u32 can_id;
+ u32 data;
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16);
if (can_dropped_invalid_skb(dev, skb))
@@ -495,26 +490,26 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
ctrl |= FLEXCAN_MB_CNT_RTR;
if (cf->can_dlc > 0) {
- u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
- flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
+ data = be32_to_cpup((__be32 *)&cf->data[0]);
+ flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[0]);
}
if (cf->can_dlc > 3) {
- u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
- flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
+ data = be32_to_cpup((__be32 *)&cf->data[4]);
+ flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[1]);
}
can_put_echo_skb(skb, dev, 0);
- flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
- flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+ flexcan_write(can_id, &regs->mb[FLEXCAN_TX_BUF_ID].can_id);
+ flexcan_write(ctrl, &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
/* Errata ERR005829 step8:
* Write twice INACTIVE(0x8) code to first MB.
*/
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
- &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+ &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
- &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+ &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
return NETDEV_TX_OK;
}
@@ -597,14 +592,14 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
tx_state = unlikely(reg_esr & FLEXCAN_ESR_TX_WRN) ?
- CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
+ CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ?
- CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
+ CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
new_state = max(tx_state, rx_state);
} else {
__flexcan_get_berr_counter(dev, &bec);
new_state = flt == FLEXCAN_ESR_FLT_CONF_PASSIVE ?
- CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF;
+ CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF;
rx_state = bec.rxerr >= bec.txerr ? new_state : 0;
tx_state = bec.rxerr <= bec.txerr ? new_state : 0;
}
@@ -633,8 +628,8 @@ static void flexcan_read_fifo(const struct net_device *dev,
struct can_frame *cf)
{
const struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
- struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
+ struct flexcan_regs __iomem *regs = priv->regs;
+ struct flexcan_mb __iomem *mb = &regs->mb[0];
u32 reg_ctrl, reg_id;
reg_ctrl = flexcan_read(&mb->can_ctrl);
@@ -683,12 +678,11 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
{
struct net_device *dev = napi->dev;
const struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_iflag1, reg_esr;
int work_done = 0;
- /*
- * The error bits are cleared on read,
+ /* The error bits are cleared on read,
* use saved value from irq handler.
*/
reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
@@ -723,17 +717,17 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
struct net_device *dev = dev_id;
struct net_device_stats *stats = &dev->stats;
struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_iflag1, reg_esr;
reg_iflag1 = flexcan_read(&regs->iflag1);
reg_esr = flexcan_read(&regs->esr);
+
/* ACK all bus error and state change IRQ sources */
if (reg_esr & FLEXCAN_ESR_ALL_INT)
flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
- /*
- * schedule NAPI in case of:
+ /* schedule NAPI in case of:
* - rx IRQ
* - state change IRQ
* - bus error IRQ and bus error reporting is activated
@@ -741,15 +735,14 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) ||
(reg_esr & FLEXCAN_ESR_ERR_STATE) ||
flexcan_has_and_handle_berr(priv, reg_esr)) {
- /*
- * The error bits are cleared on read,
+ /* The error bits are cleared on read,
* save them for later use.
*/
priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
flexcan_write(FLEXCAN_IFLAG_DEFAULT &
- ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
+ ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
- &regs->ctrl);
+ &regs->ctrl);
napi_schedule(&priv->napi);
}
@@ -765,9 +758,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
stats->tx_bytes += can_get_echo_skb(dev, 0);
stats->tx_packets++;
can_led_event(dev, CAN_LED_EVENT_TX);
- /* after sending a RTR frame mailbox is in RX mode */
+
+ /* after sending a RTR frame MB is in RX mode */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
- &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+ &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
netif_wake_queue(dev);
}
@@ -779,7 +773,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
{
const struct flexcan_priv *priv = netdev_priv(dev);
const struct can_bittiming *bt = &priv->can.bittiming;
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
u32 reg;
reg = flexcan_read(&regs->ctrl);
@@ -813,8 +807,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
}
-/*
- * flexcan_chip_start
+/* flexcan_chip_start
*
* this functions is entered with clocks enabled
*
@@ -822,7 +815,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
static int flexcan_chip_start(struct net_device *dev)
{
struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr;
int err, i;
@@ -838,29 +831,26 @@ static int flexcan_chip_start(struct net_device *dev)
flexcan_set_bittiming(dev);
- /*
- * MCR
+ /* MCR
*
* enable freeze
* enable fifo
* halt now
* only supervisor access
* enable warning int
- * choose format C
* disable local echo
- *
+ * choose format C
+ * set max mailbox number
*/
reg_mcr = flexcan_read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
- FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
- FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS |
- FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
+ FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS |
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, &regs->mcr);
- /*
- * CTRL
+ /* CTRL
*
* disable timer sync feature
*
@@ -875,12 +865,12 @@ static int flexcan_chip_start(struct net_device *dev)
reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
FLEXCAN_CTRL_ERR_STATE;
- /*
- * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
+
+ /* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
* on most Flexcan cores, too. Otherwise we don't get
* any error warning or passive interrupts.
*/
- if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE ||
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE ||
priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
else
@@ -888,41 +878,41 @@ static int flexcan_chip_start(struct net_device *dev)
/* save for later use */
priv->reg_ctrl_default = reg_ctrl;
+ /* leave interrupts disabled for now */
+ reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL;
netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
flexcan_write(reg_ctrl, &regs->ctrl);
/* clear and invalidate all mailboxes first */
- for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) {
+ for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) {
flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
- &regs->cantxfg[i].can_ctrl);
+ &regs->mb[i].can_ctrl);
}
/* Errata ERR005829: mark first TX mailbox as INACTIVE */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
- &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+ &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
/* mark TX mailbox as INACTIVE */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
- &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+ &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
/* acceptance mask/acceptance code (accept everything) */
flexcan_write(0x0, &regs->rxgmask);
flexcan_write(0x0, &regs->rx14mask);
flexcan_write(0x0, &regs->rx15mask);
- if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
flexcan_write(0x0, &regs->rxfgmask);
- /*
- * On Vybrid, disable memory error detection interrupts
+ /* On Vybrid, disable memory error detection interrupts
* and freeze mode.
* This also works around errata e5295 which generates
* false positive memory errors and put the device in
* freeze mode.
*/
- if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) {
- /*
- * Follow the protocol as described in "Detection
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) {
+ /* Follow the protocol as described in "Detection
* and Correction of Memory Errors" to write to
* MECR register
*/
@@ -934,7 +924,7 @@ static int flexcan_chip_start(struct net_device *dev)
reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
flexcan_write(reg_mecr, &regs->mecr);
reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
- FLEXCAN_MECR_FANCEI_MSK);
+ FLEXCAN_MECR_FANCEI_MSK);
flexcan_write(reg_mecr, &regs->mecr);
}
@@ -949,8 +939,11 @@ static int flexcan_chip_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
- /* enable FIFO interrupts */
+ /* enable interrupts atomically */
+ disable_irq(dev->irq);
+ flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+ enable_irq(dev->irq);
/* print chip status */
netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__,
@@ -965,16 +958,14 @@ static int flexcan_chip_start(struct net_device *dev)
return err;
}
-/*
- * flexcan_chip_stop
+/* flexcan_chip_stop
*
* this functions is entered with clocks enabled
- *
*/
static void flexcan_chip_stop(struct net_device *dev)
{
struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
/* freeze + disable module */
flexcan_chip_freeze(priv);
@@ -987,8 +978,6 @@ static void flexcan_chip_stop(struct net_device *dev)
flexcan_transceiver_disable(priv);
priv->can.state = CAN_STATE_STOPPED;
-
- return;
}
static int flexcan_open(struct net_device *dev)
@@ -1085,7 +1074,7 @@ static const struct net_device_ops flexcan_netdev_ops = {
static int register_flexcandev(struct net_device *dev)
{
struct flexcan_priv *priv = netdev_priv(dev);
- struct flexcan_regs __iomem *regs = priv->base;
+ struct flexcan_regs __iomem *regs = priv->regs;
u32 reg, err;
err = clk_prepare_enable(priv->clk_ipg);
@@ -1114,8 +1103,7 @@ static int register_flexcandev(struct net_device *dev)
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
flexcan_write(reg, &regs->mcr);
- /*
- * Currently we only support newer versions of this core
+ /* Currently we only support newer versions of this core
* featuring a RX FIFO. Older cores found on some Coldfire
* derivates are not yet supported.
*/
@@ -1168,7 +1156,7 @@ static int flexcan_probe(struct platform_device *pdev)
struct regulator *reg_xceiver;
struct resource *mem;
struct clk *clk_ipg = NULL, *clk_per = NULL;
- void __iomem *base;
+ struct flexcan_regs __iomem *regs;
int err, irq;
u32 clock_freq = 0;
@@ -1180,7 +1168,7 @@ static int flexcan_probe(struct platform_device *pdev)
if (pdev->dev.of_node)
of_property_read_u32(pdev->dev.of_node,
- "clock-frequency", &clock_freq);
+ "clock-frequency", &clock_freq);
if (!clock_freq) {
clk_ipg = devm_clk_get(&pdev->dev, "ipg");
@@ -1202,9 +1190,9 @@ static int flexcan_probe(struct platform_device *pdev)
if (irq <= 0)
return -ENODEV;
- base = devm_ioremap_resource(&pdev->dev, mem);
- if (IS_ERR(base))
- return PTR_ERR(base);
+ regs = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
of_id = of_match_device(flexcan_of_match, &pdev->dev);
if (of_id) {
@@ -1232,12 +1220,11 @@ static int flexcan_probe(struct platform_device *pdev)
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_BERR_REPORTING;
- priv->base = base;
+ priv->regs = regs;
priv->clk_ipg = clk_ipg;
priv->clk_per = clk_per;
priv->pdata = dev_get_platdata(&pdev->dev);
priv->devtype_data = devtype_data;
-
priv->reg_xceiver = reg_xceiver;
netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
@@ -1254,7 +1241,7 @@ static int flexcan_probe(struct platform_device *pdev)
devm_can_led_init(dev);
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
- priv->base, dev->irq);
+ priv->regs, dev->irq);
return 0;
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index e5fac368068a..131026fbc2d7 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -87,6 +87,7 @@ static const struct pci_device_id peak_pci_tbl[] = {
{PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,},
#ifdef CONFIG_CAN_PEAK_PCIEC
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index b7e83c212023..575790e8a75a 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1243,7 +1243,6 @@ static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
static struct spi_driver mcp251x_can_driver = {
.driver = {
.name = DEVICE_NAME,
- .owner = THIS_MODULE,
.of_match_table = mcp251x_of_match,
.pm = &mcp251x_can_pm_ops,
},
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
new file mode 100644
index 000000000000..d9a42c646783
--- /dev/null
+++ b/drivers/net/can/sun4i_can.c
@@ -0,0 +1,857 @@
+/*
+ * sun4i_can.c - CAN bus controller driver for Allwinner SUN4I&SUN7I based SoCs
+ *
+ * Copyright (C) 2013 Peter Chen
+ * Copyright (C) 2015 Gerhard Bertelsmann
+ * All rights reserved.
+ *
+ * Parts of this software are based on (derived from) the SJA1000 code by:
+ * Copyright (C) 2014 Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
+ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
+ * Copyright (C) 2002-2007 Volkswagen Group Electronic Research
+ * Copyright (C) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
+ * 38106 Braunschweig, GERMANY
+ *
+ * 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 name of Volkswagen nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * 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/netdevice.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <linux/can/led.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#define DRV_NAME "sun4i_can"
+
+/* Registers address (physical base address 0x01C2BC00) */
+#define SUN4I_REG_MSEL_ADDR 0x0000 /* CAN Mode Select */
+#define SUN4I_REG_CMD_ADDR 0x0004 /* CAN Command */
+#define SUN4I_REG_STA_ADDR 0x0008 /* CAN Status */
+#define SUN4I_REG_INT_ADDR 0x000c /* CAN Interrupt Flag */
+#define SUN4I_REG_INTEN_ADDR 0x0010 /* CAN Interrupt Enable */
+#define SUN4I_REG_BTIME_ADDR 0x0014 /* CAN Bus Timing 0 */
+#define SUN4I_REG_TEWL_ADDR 0x0018 /* CAN Tx Error Warning Limit */
+#define SUN4I_REG_ERRC_ADDR 0x001c /* CAN Error Counter */
+#define SUN4I_REG_RMCNT_ADDR 0x0020 /* CAN Receive Message Counter */
+#define SUN4I_REG_RBUFSA_ADDR 0x0024 /* CAN Receive Buffer Start Address */
+#define SUN4I_REG_BUF0_ADDR 0x0040 /* CAN Tx/Rx Buffer 0 */
+#define SUN4I_REG_BUF1_ADDR 0x0044 /* CAN Tx/Rx Buffer 1 */
+#define SUN4I_REG_BUF2_ADDR 0x0048 /* CAN Tx/Rx Buffer 2 */
+#define SUN4I_REG_BUF3_ADDR 0x004c /* CAN Tx/Rx Buffer 3 */
+#define SUN4I_REG_BUF4_ADDR 0x0050 /* CAN Tx/Rx Buffer 4 */
+#define SUN4I_REG_BUF5_ADDR 0x0054 /* CAN Tx/Rx Buffer 5 */
+#define SUN4I_REG_BUF6_ADDR 0x0058 /* CAN Tx/Rx Buffer 6 */
+#define SUN4I_REG_BUF7_ADDR 0x005c /* CAN Tx/Rx Buffer 7 */
+#define SUN4I_REG_BUF8_ADDR 0x0060 /* CAN Tx/Rx Buffer 8 */
+#define SUN4I_REG_BUF9_ADDR 0x0064 /* CAN Tx/Rx Buffer 9 */
+#define SUN4I_REG_BUF10_ADDR 0x0068 /* CAN Tx/Rx Buffer 10 */
+#define SUN4I_REG_BUF11_ADDR 0x006c /* CAN Tx/Rx Buffer 11 */
+#define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */
+#define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */
+#define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */
+#define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */
+#define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */
+
+/* Controller Register Description */
+
+/* mode select register (r/w)
+ * offset:0x0000 default:0x0000_0001
+ */
+#define SUN4I_MSEL_SLEEP_MODE (0x01 << 4) /* write in reset mode */
+#define SUN4I_MSEL_WAKE_UP (0x00 << 4)
+#define SUN4I_MSEL_SINGLE_FILTER (0x01 << 3) /* write in reset mode */
+#define SUN4I_MSEL_DUAL_FILTERS (0x00 << 3)
+#define SUN4I_MSEL_LOOPBACK_MODE BIT(2)
+#define SUN4I_MSEL_LISTEN_ONLY_MODE BIT(1)
+#define SUN4I_MSEL_RESET_MODE BIT(0)
+
+/* command register (w)
+ * offset:0x0004 default:0x0000_0000
+ */
+#define SUN4I_CMD_BUS_OFF_REQ BIT(5)
+#define SUN4I_CMD_SELF_RCV_REQ BIT(4)
+#define SUN4I_CMD_CLEAR_OR_FLAG BIT(3)
+#define SUN4I_CMD_RELEASE_RBUF BIT(2)
+#define SUN4I_CMD_ABORT_REQ BIT(1)
+#define SUN4I_CMD_TRANS_REQ BIT(0)
+
+/* status register (r)
+ * offset:0x0008 default:0x0000_003c
+ */
+#define SUN4I_STA_BIT_ERR (0x00 << 22)
+#define SUN4I_STA_FORM_ERR (0x01 << 22)
+#define SUN4I_STA_STUFF_ERR (0x02 << 22)
+#define SUN4I_STA_OTHER_ERR (0x03 << 22)
+#define SUN4I_STA_MASK_ERR (0x03 << 22)
+#define SUN4I_STA_ERR_DIR BIT(21)
+#define SUN4I_STA_ERR_SEG_CODE (0x1f << 16)
+#define SUN4I_STA_START (0x03 << 16)
+#define SUN4I_STA_ID28_21 (0x02 << 16)
+#define SUN4I_STA_ID20_18 (0x06 << 16)
+#define SUN4I_STA_SRTR (0x04 << 16)
+#define SUN4I_STA_IDE (0x05 << 16)
+#define SUN4I_STA_ID17_13 (0x07 << 16)
+#define SUN4I_STA_ID12_5 (0x0f << 16)
+#define SUN4I_STA_ID4_0 (0x0e << 16)
+#define SUN4I_STA_RTR (0x0c << 16)
+#define SUN4I_STA_RB1 (0x0d << 16)
+#define SUN4I_STA_RB0 (0x09 << 16)
+#define SUN4I_STA_DLEN (0x0b << 16)
+#define SUN4I_STA_DATA_FIELD (0x0a << 16)
+#define SUN4I_STA_CRC_SEQUENCE (0x08 << 16)
+#define SUN4I_STA_CRC_DELIMITER (0x18 << 16)
+#define SUN4I_STA_ACK (0x19 << 16)
+#define SUN4I_STA_ACK_DELIMITER (0x1b << 16)
+#define SUN4I_STA_END (0x1a << 16)
+#define SUN4I_STA_INTERMISSION (0x12 << 16)
+#define SUN4I_STA_ACTIVE_ERROR (0x11 << 16)
+#define SUN4I_STA_PASSIVE_ERROR (0x16 << 16)
+#define SUN4I_STA_TOLERATE_DOMINANT_BITS (0x13 << 16)
+#define SUN4I_STA_ERROR_DELIMITER (0x17 << 16)
+#define SUN4I_STA_OVERLOAD (0x1c << 16)
+#define SUN4I_STA_BUS_OFF BIT(7)
+#define SUN4I_STA_ERR_STA BIT(6)
+#define SUN4I_STA_TRANS_BUSY BIT(5)
+#define SUN4I_STA_RCV_BUSY BIT(4)
+#define SUN4I_STA_TRANS_OVER BIT(3)
+#define SUN4I_STA_TBUF_RDY BIT(2)
+#define SUN4I_STA_DATA_ORUN BIT(1)
+#define SUN4I_STA_RBUF_RDY BIT(0)
+
+/* interrupt register (r)
+ * offset:0x000c default:0x0000_0000
+ */
+#define SUN4I_INT_BUS_ERR BIT(7)
+#define SUN4I_INT_ARB_LOST BIT(6)
+#define SUN4I_INT_ERR_PASSIVE BIT(5)
+#define SUN4I_INT_WAKEUP BIT(4)
+#define SUN4I_INT_DATA_OR BIT(3)
+#define SUN4I_INT_ERR_WRN BIT(2)
+#define SUN4I_INT_TBUF_VLD BIT(1)
+#define SUN4I_INT_RBUF_VLD BIT(0)
+
+/* interrupt enable register (r/w)
+ * offset:0x0010 default:0x0000_0000
+ */
+#define SUN4I_INTEN_BERR BIT(7)
+#define SUN4I_INTEN_ARB_LOST BIT(6)
+#define SUN4I_INTEN_ERR_PASSIVE BIT(5)
+#define SUN4I_INTEN_WAKEUP BIT(4)
+#define SUN4I_INTEN_OR BIT(3)
+#define SUN4I_INTEN_ERR_WRN BIT(2)
+#define SUN4I_INTEN_TX BIT(1)
+#define SUN4I_INTEN_RX BIT(0)
+
+/* error code */
+#define SUN4I_ERR_INRCV (0x1 << 5)
+#define SUN4I_ERR_INTRANS (0x0 << 5)
+
+/* filter mode */
+#define SUN4I_FILTER_CLOSE 0
+#define SUN4I_SINGLE_FLTER_MODE 1
+#define SUN4I_DUAL_FILTER_MODE 2
+
+/* message buffer flags */
+#define SUN4I_MSG_EFF_FLAG BIT(7)
+#define SUN4I_MSG_RTR_FLAG BIT(6)
+
+/* max. number of interrupts handled in ISR */
+#define SUN4I_CAN_MAX_IRQ 20
+#define SUN4I_MODE_MAX_RETRIES 100
+
+struct sun4ican_priv {
+ struct can_priv can;
+ void __iomem *base;
+ struct clk *clk;
+ spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
+};
+
+static const struct can_bittiming_const sun4ican_bittiming_const = {
+ .name = DRV_NAME,
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 64,
+ .brp_inc = 1,
+};
+
+static void sun4i_can_write_cmdreg(struct sun4ican_priv *priv, u8 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->cmdreg_lock, flags);
+ writel(val, priv->base + SUN4I_REG_CMD_ADDR);
+ spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
+}
+
+static int set_normal_mode(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ int retry = SUN4I_MODE_MAX_RETRIES;
+ u32 mod_reg_val = 0;
+
+ do {
+ mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
+ mod_reg_val &= ~SUN4I_MSEL_RESET_MODE;
+ writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR);
+ } while (retry-- && (mod_reg_val & SUN4I_MSEL_RESET_MODE));
+
+ if (readl(priv->base + SUN4I_REG_MSEL_ADDR) & SUN4I_MSEL_RESET_MODE) {
+ netdev_err(dev,
+ "setting controller into normal mode failed!\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int set_reset_mode(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ int retry = SUN4I_MODE_MAX_RETRIES;
+ u32 mod_reg_val = 0;
+
+ do {
+ mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
+ mod_reg_val |= SUN4I_MSEL_RESET_MODE;
+ writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR);
+ } while (retry-- && !(mod_reg_val & SUN4I_MSEL_RESET_MODE));
+
+ if (!(readl(priv->base + SUN4I_REG_MSEL_ADDR) &
+ SUN4I_MSEL_RESET_MODE)) {
+ netdev_err(dev, "setting controller into reset mode failed!\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+/* bittiming is called in reset_mode only */
+static int sun4ican_set_bittiming(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ u32 cfg;
+
+ cfg = ((bt->brp - 1) & 0x3FF) |
+ (((bt->sjw - 1) & 0x3) << 14) |
+ (((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) << 16) |
+ (((bt->phase_seg2 - 1) & 0x7) << 20);
+ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ cfg |= 0x800000;
+
+ netdev_dbg(dev, "setting BITTIMING=0x%08x\n", cfg);
+ writel(cfg, priv->base + SUN4I_REG_BTIME_ADDR);
+
+ return 0;
+}
+
+static int sun4ican_get_berr_counter(const struct net_device *dev,
+ struct can_berr_counter *bec)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ u32 errors;
+ int err;
+
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+ netdev_err(dev, "could not enable clock\n");
+ return err;
+ }
+
+ errors = readl(priv->base + SUN4I_REG_ERRC_ADDR);
+
+ bec->txerr = errors & 0xFF;
+ bec->rxerr = (errors >> 16) & 0xFF;
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static int sun4i_can_start(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ int err;
+ u32 mod_reg_val;
+
+ /* we need to enter the reset mode */
+ err = set_reset_mode(dev);
+ if (err) {
+ netdev_err(dev, "could not enter reset mode\n");
+ return err;
+ }
+
+ /* set filters - we accept all */
+ writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR);
+ writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR);
+
+ /* clear error counters and error code capture */
+ writel(0, priv->base + SUN4I_REG_ERRC_ADDR);
+
+ /* enable interrupts */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
+ writel(0xFF, priv->base + SUN4I_REG_INTEN_ADDR);
+ else
+ writel(0xFF & ~SUN4I_INTEN_BERR,
+ priv->base + SUN4I_REG_INTEN_ADDR);
+
+ /* enter the selected mode */
+ mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
+ if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
+ mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE;
+ else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE;
+ writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR);
+
+ err = sun4ican_set_bittiming(dev);
+ if (err)
+ return err;
+
+ /* we are ready to enter the normal mode */
+ err = set_normal_mode(dev);
+ if (err) {
+ netdev_err(dev, "could not enter normal mode\n");
+ return err;
+ }
+
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ return 0;
+}
+
+static int sun4i_can_stop(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ int err;
+
+ priv->can.state = CAN_STATE_STOPPED;
+ /* we need to enter reset mode */
+ err = set_reset_mode(dev);
+ if (err) {
+ netdev_err(dev, "could not enter reset mode\n");
+ return err;
+ }
+
+ /* disable all interrupts */
+ writel(0, priv->base + SUN4I_REG_INTEN_ADDR);
+
+ return 0;
+}
+
+static int sun4ican_set_mode(struct net_device *dev, enum can_mode mode)
+{
+ int err;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ err = sun4i_can_start(dev);
+ if (err) {
+ netdev_err(dev, "starting CAN controller failed!\n");
+ return err;
+ }
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+/* transmit a CAN message
+ * message layout in the sk_buff should be like this:
+ * xx xx xx xx ff ll 00 11 22 33 44 55 66 77
+ * [ can_id ] [flags] [len] [can data (up to 8 bytes]
+ */
+static int sun4ican_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ u8 dlc;
+ u32 dreg, msg_flag_n;
+ canid_t id;
+ int i;
+
+ if (can_dropped_invalid_skb(dev, skb))
+ return NETDEV_TX_OK;
+
+ netif_stop_queue(dev);
+
+ id = cf->can_id;
+ dlc = cf->can_dlc;
+ msg_flag_n = dlc;
+
+ if (id & CAN_RTR_FLAG)
+ msg_flag_n |= SUN4I_MSG_RTR_FLAG;
+
+ if (id & CAN_EFF_FLAG) {
+ msg_flag_n |= SUN4I_MSG_EFF_FLAG;
+ dreg = SUN4I_REG_BUF5_ADDR;
+ writel((id >> 21) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR);
+ writel((id >> 13) & 0xFF, priv->base + SUN4I_REG_BUF2_ADDR);
+ writel((id >> 5) & 0xFF, priv->base + SUN4I_REG_BUF3_ADDR);
+ writel((id << 3) & 0xF8, priv->base + SUN4I_REG_BUF4_ADDR);
+ } else {
+ dreg = SUN4I_REG_BUF3_ADDR;
+ writel((id >> 3) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR);
+ writel((id << 5) & 0xE0, priv->base + SUN4I_REG_BUF2_ADDR);
+ }
+
+ for (i = 0; i < dlc; i++)
+ writel(cf->data[i], priv->base + (dreg + i * 4));
+
+ writel(msg_flag_n, priv->base + SUN4I_REG_BUF0_ADDR);
+
+ can_put_echo_skb(skb, dev, 0);
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
+ sun4i_can_write_cmdreg(priv, SUN4I_CMD_SELF_RCV_REQ);
+ else
+ sun4i_can_write_cmdreg(priv, SUN4I_CMD_TRANS_REQ);
+
+ return NETDEV_TX_OK;
+}
+
+static void sun4i_can_rx(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ u8 fi;
+ u32 dreg;
+ canid_t id;
+ int i;
+
+ /* create zero'ed CAN frame buffer */
+ skb = alloc_can_skb(dev, &cf);
+ if (!skb)
+ return;
+
+ fi = readl(priv->base + SUN4I_REG_BUF0_ADDR);
+ cf->can_dlc = get_can_dlc(fi & 0x0F);
+ if (fi & SUN4I_MSG_EFF_FLAG) {
+ dreg = SUN4I_REG_BUF5_ADDR;
+ id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 21) |
+ (readl(priv->base + SUN4I_REG_BUF2_ADDR) << 13) |
+ (readl(priv->base + SUN4I_REG_BUF3_ADDR) << 5) |
+ ((readl(priv->base + SUN4I_REG_BUF4_ADDR) >> 3) & 0x1f);
+ id |= CAN_EFF_FLAG;
+ } else {
+ dreg = SUN4I_REG_BUF3_ADDR;
+ id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 3) |
+ ((readl(priv->base + SUN4I_REG_BUF2_ADDR) >> 5) & 0x7);
+ }
+
+ /* remote frame ? */
+ if (fi & SUN4I_MSG_RTR_FLAG)
+ id |= CAN_RTR_FLAG;
+ else
+ for (i = 0; i < cf->can_dlc; i++)
+ cf->data[i] = readl(priv->base + dreg + i * 4);
+
+ cf->can_id = id;
+
+ sun4i_can_write_cmdreg(priv, SUN4I_CMD_RELEASE_RBUF);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
+
+ can_led_event(dev, CAN_LED_EVENT_RX);
+}
+
+static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ enum can_state state = priv->can.state;
+ enum can_state rx_state, tx_state;
+ unsigned int rxerr, txerr, errc;
+ u32 ecc, alc;
+
+ /* we don't skip if alloc fails because we want the stats anyhow */
+ skb = alloc_can_err_skb(dev, &cf);
+
+ errc = readl(priv->base + SUN4I_REG_ERRC_ADDR);
+ rxerr = (errc >> 16) & 0xFF;
+ txerr = errc & 0xFF;
+
+ if (skb) {
+ cf->data[6] = txerr;
+ cf->data[7] = rxerr;
+ }
+
+ if (isrc & SUN4I_INT_DATA_OR) {
+ /* data overrun interrupt */
+ netdev_dbg(dev, "data overrun interrupt\n");
+ if (likely(skb)) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+ /* clear bit */
+ sun4i_can_write_cmdreg(priv, SUN4I_CMD_CLEAR_OR_FLAG);
+ }
+ if (isrc & SUN4I_INT_ERR_WRN) {
+ /* error warning interrupt */
+ netdev_dbg(dev, "error warning interrupt\n");
+
+ if (status & SUN4I_STA_BUS_OFF)
+ state = CAN_STATE_BUS_OFF;
+ else if (status & SUN4I_STA_ERR_STA)
+ state = CAN_STATE_ERROR_WARNING;
+ else
+ state = CAN_STATE_ERROR_ACTIVE;
+ }
+ if (isrc & SUN4I_INT_BUS_ERR) {
+ /* bus error interrupt */
+ netdev_dbg(dev, "bus error interrupt\n");
+ priv->can.can_stats.bus_error++;
+ stats->rx_errors++;
+
+ if (likely(skb)) {
+ ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
+
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ switch (ecc & SUN4I_STA_MASK_ERR) {
+ case SUN4I_STA_BIT_ERR:
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ break;
+ case SUN4I_STA_FORM_ERR:
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case SUN4I_STA_STUFF_ERR:
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ default:
+ cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+ cf->data[3] = (ecc & SUN4I_STA_ERR_SEG_CODE)
+ >> 16;
+ break;
+ }
+ /* error occurred during transmission? */
+ if ((ecc & SUN4I_STA_ERR_DIR) == 0)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ }
+ }
+ if (isrc & SUN4I_INT_ERR_PASSIVE) {
+ /* error passive interrupt */
+ netdev_dbg(dev, "error passive interrupt\n");
+ if (state == CAN_STATE_ERROR_PASSIVE)
+ state = CAN_STATE_ERROR_WARNING;
+ else
+ state = CAN_STATE_ERROR_PASSIVE;
+ }
+ if (isrc & SUN4I_INT_ARB_LOST) {
+ /* arbitration lost interrupt */
+ netdev_dbg(dev, "arbitration lost interrupt\n");
+ alc = readl(priv->base + SUN4I_REG_STA_ADDR);
+ priv->can.can_stats.arbitration_lost++;
+ stats->tx_errors++;
+ if (likely(skb)) {
+ cf->can_id |= CAN_ERR_LOSTARB;
+ cf->data[0] = (alc >> 8) & 0x1f;
+ }
+ }
+
+ if (state != priv->can.state) {
+ tx_state = txerr >= rxerr ? state : 0;
+ rx_state = txerr <= rxerr ? state : 0;
+
+ if (likely(skb))
+ can_change_state(dev, cf, tx_state, rx_state);
+ else
+ priv->can.state = state;
+ if (state == CAN_STATE_BUS_OFF)
+ can_bus_off(dev);
+ }
+
+ if (likely(skb)) {
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
+ } else {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ u8 isrc, status;
+ int n = 0;
+
+ while ((isrc = readl(priv->base + SUN4I_REG_INT_ADDR)) &&
+ (n < SUN4I_CAN_MAX_IRQ)) {
+ n++;
+ status = readl(priv->base + SUN4I_REG_STA_ADDR);
+
+ if (isrc & SUN4I_INT_WAKEUP)
+ netdev_warn(dev, "wakeup interrupt\n");
+
+ if (isrc & SUN4I_INT_TBUF_VLD) {
+ /* transmission complete interrupt */
+ stats->tx_bytes +=
+ readl(priv->base +
+ SUN4I_REG_RBUF_RBACK_START_ADDR) & 0xf;
+ stats->tx_packets++;
+ can_get_echo_skb(dev, 0);
+ netif_wake_queue(dev);
+ can_led_event(dev, CAN_LED_EVENT_TX);
+ }
+ if (isrc & SUN4I_INT_RBUF_VLD) {
+ /* receive interrupt */
+ while (status & SUN4I_STA_RBUF_RDY) {
+ /* RX buffer is not empty */
+ sun4i_can_rx(dev);
+ status = readl(priv->base + SUN4I_REG_STA_ADDR);
+ }
+ }
+ if (isrc &
+ (SUN4I_INT_DATA_OR | SUN4I_INT_ERR_WRN | SUN4I_INT_BUS_ERR |
+ SUN4I_INT_ERR_PASSIVE | SUN4I_INT_ARB_LOST)) {
+ /* error interrupt */
+ if (sun4i_can_err(dev, isrc, status))
+ netdev_err(dev, "can't allocate buffer - clearing pending interrupts\n");
+ }
+ /* clear interrupts */
+ writel(isrc, priv->base + SUN4I_REG_INT_ADDR);
+ readl(priv->base + SUN4I_REG_INT_ADDR);
+ }
+ if (n >= SUN4I_CAN_MAX_IRQ)
+ netdev_dbg(dev, "%d messages handled in ISR", n);
+
+ return (n) ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int sun4ican_open(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+ int err;
+
+ /* common open */
+ err = open_candev(dev);
+ if (err)
+ return err;
+
+ /* register interrupt handler */
+ err = request_irq(dev->irq, sun4i_can_interrupt, 0, dev->name, dev);
+ if (err) {
+ netdev_err(dev, "request_irq err: %d\n", err);
+ goto exit_irq;
+ }
+
+ /* turn on clocking for CAN peripheral block */
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+ netdev_err(dev, "could not enable CAN peripheral clock\n");
+ goto exit_clock;
+ }
+
+ err = sun4i_can_start(dev);
+ if (err) {
+ netdev_err(dev, "could not start CAN peripheral\n");
+ goto exit_can_start;
+ }
+
+ can_led_event(dev, CAN_LED_EVENT_OPEN);
+ netif_start_queue(dev);
+
+ return 0;
+
+exit_can_start:
+ clk_disable_unprepare(priv->clk);
+exit_clock:
+ free_irq(dev->irq, dev);
+exit_irq:
+ close_candev(dev);
+ return err;
+}
+
+static int sun4ican_close(struct net_device *dev)
+{
+ struct sun4ican_priv *priv = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+ sun4i_can_stop(dev);
+ clk_disable_unprepare(priv->clk);
+
+ free_irq(dev->irq, dev);
+ close_candev(dev);
+ can_led_event(dev, CAN_LED_EVENT_STOP);
+
+ return 0;
+}
+
+static const struct net_device_ops sun4ican_netdev_ops = {
+ .ndo_open = sun4ican_open,
+ .ndo_stop = sun4ican_close,
+ .ndo_start_xmit = sun4ican_start_xmit,
+};
+
+static const struct of_device_id sun4ican_of_match[] = {
+ {.compatible = "allwinner,sun4i-a10-can"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, sun4ican_of_match);
+
+static int sun4ican_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+
+ unregister_netdev(dev);
+ free_candev(dev);
+
+ return 0;
+}
+
+static int sun4ican_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *mem;
+ struct clk *clk;
+ void __iomem *addr;
+ int err, irq;
+ struct net_device *dev;
+ struct sun4ican_priv *priv;
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to request clock\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "could not get a valid irq\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ addr = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(addr)) {
+ err = -EBUSY;
+ goto exit;
+ }
+
+ dev = alloc_candev(sizeof(struct sun4ican_priv), 1);
+ if (!dev) {
+ dev_err(&pdev->dev,
+ "could not allocate memory for CAN device\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ dev->netdev_ops = &sun4ican_netdev_ops;
+ dev->irq = irq;
+ dev->flags |= IFF_ECHO;
+
+ priv = netdev_priv(dev);
+ priv->can.clock.freq = clk_get_rate(clk);
+ priv->can.bittiming_const = &sun4ican_bittiming_const;
+ priv->can.do_set_mode = sun4ican_set_mode;
+ priv->can.do_get_berr_counter = sun4ican_get_berr_counter;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING |
+ CAN_CTRLMODE_LISTENONLY |
+ CAN_CTRLMODE_LOOPBACK |
+ CAN_CTRLMODE_PRESUME_ACK |
+ CAN_CTRLMODE_3_SAMPLES;
+ priv->base = addr;
+ priv->clk = clk;
+ spin_lock_init(&priv->cmdreg_lock);
+
+ platform_set_drvdata(pdev, dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ err = register_candev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
+ DRV_NAME, err);
+ goto exit_free;
+ }
+ devm_can_led_init(dev);
+
+ dev_info(&pdev->dev, "device registered (base=%p, irq=%d)\n",
+ priv->base, dev->irq);
+
+ return 0;
+
+exit_free:
+ free_candev(dev);
+exit:
+ return err;
+}
+
+static struct platform_driver sun4i_can_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = sun4ican_of_match,
+ },
+ .probe = sun4ican_probe,
+ .remove = sun4ican_remove,
+};
+
+module_platform_driver(sun4i_can_driver);
+
+MODULE_AUTHOR("Peter Chen <xingkongcp@gmail.com>");
+MODULE_AUTHOR("Gerhard Bertelsmann <info@gerhard-bertelsmann.de>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)");
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 9d56515f4c4d..6f946fedbb77 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -21,10 +21,13 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
+#include <linux/of_net.h>
#include <net/dsa.h>
#include <linux/ethtool.h>
#include <linux/if_bridge.h>
#include <linux/brcmphy.h>
+#include <linux/etherdevice.h>
+#include <net/switchdev.h>
#include "bcm_sf2.h"
#include "bcm_sf2_regs.h"
@@ -264,6 +267,50 @@ static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
}
}
+static inline void bcm_sf2_port_intr_enable(struct bcm_sf2_priv *priv,
+ int port)
+{
+ unsigned int off;
+
+ switch (port) {
+ case 7:
+ off = P7_IRQ_OFF;
+ break;
+ case 0:
+ /* Port 0 interrupts are located on the first bank */
+ intrl2_0_mask_clear(priv, P_IRQ_MASK(P0_IRQ_OFF));
+ return;
+ default:
+ off = P_IRQ_OFF(port);
+ break;
+ }
+
+ intrl2_1_mask_clear(priv, P_IRQ_MASK(off));
+}
+
+static inline void bcm_sf2_port_intr_disable(struct bcm_sf2_priv *priv,
+ int port)
+{
+ unsigned int off;
+
+ switch (port) {
+ case 7:
+ off = P7_IRQ_OFF;
+ break;
+ case 0:
+ /* Port 0 interrupts are located on the first bank */
+ intrl2_0_mask_set(priv, P_IRQ_MASK(P0_IRQ_OFF));
+ intrl2_0_writel(priv, P_IRQ_MASK(P0_IRQ_OFF), INTRL2_CPU_CLEAR);
+ return;
+ default:
+ off = P_IRQ_OFF(port);
+ break;
+ }
+
+ intrl2_1_mask_set(priv, P_IRQ_MASK(off));
+ intrl2_1_writel(priv, P_IRQ_MASK(off), INTRL2_CPU_CLEAR);
+}
+
static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
struct phy_device *phy)
{
@@ -280,7 +327,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
core_writel(priv, 0, CORE_G_PCTL_PORT(port));
/* Re-enable the GPHY and re-apply workarounds */
- if (port == 0 && priv->hw_params.num_gphy == 1) {
+ if (priv->int_phy_mask & 1 << port && priv->hw_params.num_gphy == 1) {
bcm_sf2_gphy_enable_set(ds, true);
if (phy) {
/* if phy_stop() has been called before, phy
@@ -297,9 +344,9 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
}
}
- /* Enable port 7 interrupts to get notified */
- if (port == 7)
- intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF));
+ /* Enable MoCA port interrupts to get notified */
+ if (port == priv->moca_port)
+ bcm_sf2_port_intr_enable(priv, port);
/* Set this port, and only this one to be in the default VLAN,
* if member of a bridge, restore its membership prior to
@@ -329,12 +376,10 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
if (priv->wol_ports_mask & (1 << port))
return;
- if (port == 7) {
- intrl2_1_mask_set(priv, P_IRQ_MASK(P7_IRQ_OFF));
- intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR);
- }
+ if (port == priv->moca_port)
+ bcm_sf2_port_intr_disable(priv, port);
- if (port == 0 && priv->hw_params.num_gphy == 1)
+ if (priv->int_phy_mask & 1 << port && priv->hw_params.num_gphy == 1)
bcm_sf2_gphy_enable_set(ds, false);
if (dsa_is_cpu_port(ds, port))
@@ -555,6 +600,236 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port,
return 0;
}
+/* Address Resolution Logic routines */
+static int bcm_sf2_arl_op_wait(struct bcm_sf2_priv *priv)
+{
+ unsigned int timeout = 10;
+ u32 reg;
+
+ do {
+ reg = core_readl(priv, CORE_ARLA_RWCTL);
+ if (!(reg & ARL_STRTDN))
+ return 0;
+
+ usleep_range(1000, 2000);
+ } while (timeout--);
+
+ return -ETIMEDOUT;
+}
+
+static int bcm_sf2_arl_rw_op(struct bcm_sf2_priv *priv, unsigned int op)
+{
+ u32 cmd;
+
+ if (op > ARL_RW)
+ return -EINVAL;
+
+ cmd = core_readl(priv, CORE_ARLA_RWCTL);
+ cmd &= ~IVL_SVL_SELECT;
+ cmd |= ARL_STRTDN;
+ if (op)
+ cmd |= ARL_RW;
+ else
+ cmd &= ~ARL_RW;
+ core_writel(priv, cmd, CORE_ARLA_RWCTL);
+
+ return bcm_sf2_arl_op_wait(priv);
+}
+
+static int bcm_sf2_arl_read(struct bcm_sf2_priv *priv, u64 mac,
+ u16 vid, struct bcm_sf2_arl_entry *ent, u8 *idx,
+ bool is_valid)
+{
+ unsigned int i;
+ int ret;
+
+ ret = bcm_sf2_arl_op_wait(priv);
+ if (ret)
+ return ret;
+
+ /* Read the 4 bins */
+ for (i = 0; i < 4; i++) {
+ u64 mac_vid;
+ u32 fwd_entry;
+
+ mac_vid = core_readq(priv, CORE_ARLA_MACVID_ENTRY(i));
+ fwd_entry = core_readl(priv, CORE_ARLA_FWD_ENTRY(i));
+ bcm_sf2_arl_to_entry(ent, mac_vid, fwd_entry);
+
+ if (ent->is_valid && is_valid) {
+ *idx = i;
+ return 0;
+ }
+
+ /* This is the MAC we just deleted */
+ if (!is_valid && (mac_vid & mac))
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int bcm_sf2_arl_op(struct bcm_sf2_priv *priv, int op, int port,
+ const unsigned char *addr, u16 vid, bool is_valid)
+{
+ struct bcm_sf2_arl_entry ent;
+ u32 fwd_entry;
+ u64 mac, mac_vid = 0;
+ u8 idx = 0;
+ int ret;
+
+ /* Convert the array into a 64-bit MAC */
+ mac = bcm_sf2_mac_to_u64(addr);
+
+ /* Perform a read for the given MAC and VID */
+ core_writeq(priv, mac, CORE_ARLA_MAC);
+ core_writel(priv, vid, CORE_ARLA_VID);
+
+ /* Issue a read operation for this MAC */
+ ret = bcm_sf2_arl_rw_op(priv, 1);
+ if (ret)
+ return ret;
+
+ ret = bcm_sf2_arl_read(priv, mac, vid, &ent, &idx, is_valid);
+ /* If this is a read, just finish now */
+ if (op)
+ return ret;
+
+ /* We could not find a matching MAC, so reset to a new entry */
+ if (ret) {
+ fwd_entry = 0;
+ idx = 0;
+ }
+
+ memset(&ent, 0, sizeof(ent));
+ ent.port = port;
+ ent.is_valid = is_valid;
+ ent.vid = vid;
+ ent.is_static = true;
+ memcpy(ent.mac, addr, ETH_ALEN);
+ bcm_sf2_arl_from_entry(&mac_vid, &fwd_entry, &ent);
+
+ core_writeq(priv, mac_vid, CORE_ARLA_MACVID_ENTRY(idx));
+ core_writel(priv, fwd_entry, CORE_ARLA_FWD_ENTRY(idx));
+
+ ret = bcm_sf2_arl_rw_op(priv, 0);
+ if (ret)
+ return ret;
+
+ /* Re-read the entry to check */
+ return bcm_sf2_arl_read(priv, mac, vid, &ent, &idx, is_valid);
+}
+
+static int bcm_sf2_sw_fdb_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
+{
+ /* We do not need to do anything specific here yet */
+ return 0;
+}
+
+static int bcm_sf2_sw_fdb_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
+{
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+
+ return bcm_sf2_arl_op(priv, 0, port, fdb->addr, fdb->vid, true);
+}
+
+static int bcm_sf2_sw_fdb_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb)
+{
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+
+ return bcm_sf2_arl_op(priv, 0, port, fdb->addr, fdb->vid, false);
+}
+
+static int bcm_sf2_arl_search_wait(struct bcm_sf2_priv *priv)
+{
+ unsigned timeout = 1000;
+ u32 reg;
+
+ do {
+ reg = core_readl(priv, CORE_ARLA_SRCH_CTL);
+ if (!(reg & ARLA_SRCH_STDN))
+ return 0;
+
+ if (reg & ARLA_SRCH_VLID)
+ return 0;
+
+ usleep_range(1000, 2000);
+ } while (timeout--);
+
+ return -ETIMEDOUT;
+}
+
+static void bcm_sf2_arl_search_rd(struct bcm_sf2_priv *priv, u8 idx,
+ struct bcm_sf2_arl_entry *ent)
+{
+ u64 mac_vid;
+ u32 fwd_entry;
+
+ mac_vid = core_readq(priv, CORE_ARLA_SRCH_RSLT_MACVID(idx));
+ fwd_entry = core_readl(priv, CORE_ARLA_SRCH_RSLT(idx));
+ bcm_sf2_arl_to_entry(ent, mac_vid, fwd_entry);
+}
+
+static int bcm_sf2_sw_fdb_copy(struct net_device *dev, int port,
+ const struct bcm_sf2_arl_entry *ent,
+ struct switchdev_obj_port_fdb *fdb,
+ int (*cb)(struct switchdev_obj *obj))
+{
+ if (!ent->is_valid)
+ return 0;
+
+ if (port != ent->port)
+ return 0;
+
+ ether_addr_copy(fdb->addr, ent->mac);
+ fdb->vid = ent->vid;
+ fdb->ndm_state = ent->is_static ? NUD_NOARP : NUD_REACHABLE;
+
+ return cb(&fdb->obj);
+}
+
+static int bcm_sf2_sw_fdb_dump(struct dsa_switch *ds, int port,
+ struct switchdev_obj_port_fdb *fdb,
+ int (*cb)(struct switchdev_obj *obj))
+{
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ struct net_device *dev = ds->ports[port];
+ struct bcm_sf2_arl_entry results[2];
+ unsigned int count = 0;
+ int ret;
+
+ /* Start search operation */
+ core_writel(priv, ARLA_SRCH_STDN, CORE_ARLA_SRCH_CTL);
+
+ do {
+ ret = bcm_sf2_arl_search_wait(priv);
+ if (ret)
+ return ret;
+
+ /* Read both entries, then return their values back */
+ bcm_sf2_arl_search_rd(priv, 0, &results[0]);
+ ret = bcm_sf2_sw_fdb_copy(dev, port, &results[0], fdb, cb);
+ if (ret)
+ return ret;
+
+ bcm_sf2_arl_search_rd(priv, 1, &results[1]);
+ ret = bcm_sf2_sw_fdb_copy(dev, port, &results[1], fdb, cb);
+ if (ret)
+ return ret;
+
+ if (!results[0].is_valid && !results[1].is_valid)
+ break;
+
+ } while (count++ < CORE_ARLA_NUM_ENTRIES);
+
+ return 0;
+}
+
static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
{
struct bcm_sf2_priv *priv = dev_id;
@@ -615,6 +890,42 @@ static void bcm_sf2_intr_disable(struct bcm_sf2_priv *priv)
intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
}
+static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
+ struct device_node *dn)
+{
+ struct device_node *port;
+ const char *phy_mode_str;
+ int mode;
+ unsigned int port_num;
+ int ret;
+
+ priv->moca_port = -1;
+
+ for_each_available_child_of_node(dn, port) {
+ if (of_property_read_u32(port, "reg", &port_num))
+ continue;
+
+ /* Internal PHYs get assigned a specific 'phy-mode' property
+ * value: "internal" to help flag them before MDIO probing
+ * has completed, since they might be turned off at that
+ * time
+ */
+ mode = of_get_phy_mode(port);
+ if (mode < 0) {
+ ret = of_property_read_string(port, "phy-mode",
+ &phy_mode_str);
+ if (ret < 0)
+ continue;
+
+ if (!strcasecmp(phy_mode_str, "internal"))
+ priv->int_phy_mask |= 1 << port_num;
+ }
+
+ if (mode == PHY_INTERFACE_MODE_MOCA)
+ priv->moca_port = port_num;
+ }
+}
+
static int bcm_sf2_sw_setup(struct dsa_switch *ds)
{
const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
@@ -633,6 +944,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
* level
*/
dn = ds->pd->of_node->parent;
+ bcm_sf2_identify_ports(priv, ds->pd->of_node);
priv->irq0 = irq_of_parse_and_map(dn, 0);
priv->irq1 = irq_of_parse_and_map(dn, 1);
@@ -913,7 +1225,7 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
status->link = 0;
- /* Port 7 is special as we do not get link status from CORE_LNKSTS,
+ /* MoCA port is special as we do not get link status from CORE_LNKSTS,
* which means that we need to force the link at the port override
* level to get the data to flow. We do use what the interrupt handler
* did determine before.
@@ -921,7 +1233,7 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
* For the other ports, we just force the link status, since this is
* a fixed PHY device.
*/
- if (port == 7) {
+ if (port == priv->moca_port) {
status->link = priv->port_sts[port].link;
/* For MoCA interfaces, also force a link down notification
* since some version of the user-space daemon (mocad) use
@@ -1076,6 +1388,10 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
.port_join_bridge = bcm_sf2_sw_br_join,
.port_leave_bridge = bcm_sf2_sw_br_leave,
.port_stp_update = bcm_sf2_sw_br_set_stp_state,
+ .port_fdb_prepare = bcm_sf2_sw_fdb_prepare,
+ .port_fdb_add = bcm_sf2_sw_fdb_add,
+ .port_fdb_del = bcm_sf2_sw_fdb_del,
+ .port_fdb_dump = bcm_sf2_sw_fdb_dump,
};
static int __init bcm_sf2_init(void)
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index 789d7b7737da..6bba1c98d764 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -19,6 +19,8 @@
#include <linux/mutex.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
#include <net/dsa.h>
@@ -50,6 +52,60 @@ struct bcm_sf2_port_status {
u32 vlan_ctl_mask;
};
+struct bcm_sf2_arl_entry {
+ u8 port;
+ u8 mac[ETH_ALEN];
+ u16 vid;
+ u8 is_valid:1;
+ u8 is_age:1;
+ u8 is_static:1;
+};
+
+static inline void bcm_sf2_mac_from_u64(u64 src, u8 *dst)
+{
+ unsigned int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ dst[ETH_ALEN - 1 - i] = (src >> (8 * i)) & 0xff;
+}
+
+static inline u64 bcm_sf2_mac_to_u64(const u8 *src)
+{
+ unsigned int i;
+ u64 dst = 0;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ dst |= (u64)src[ETH_ALEN - 1 - i] << (8 * i);
+
+ return dst;
+}
+
+static inline void bcm_sf2_arl_to_entry(struct bcm_sf2_arl_entry *ent,
+ u64 mac_vid, u32 fwd_entry)
+{
+ memset(ent, 0, sizeof(*ent));
+ ent->port = fwd_entry & PORTID_MASK;
+ ent->is_valid = !!(fwd_entry & ARL_VALID);
+ ent->is_age = !!(fwd_entry & ARL_AGE);
+ ent->is_static = !!(fwd_entry & ARL_STATIC);
+ bcm_sf2_mac_from_u64(mac_vid, ent->mac);
+ ent->vid = mac_vid >> VID_SHIFT;
+}
+
+static inline void bcm_sf2_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
+ const struct bcm_sf2_arl_entry *ent)
+{
+ *mac_vid = bcm_sf2_mac_to_u64(ent->mac);
+ *mac_vid |= (u64)(ent->vid & VID_MASK) << VID_SHIFT;
+ *fwd_entry = ent->port & PORTID_MASK;
+ if (ent->is_valid)
+ *fwd_entry |= ARL_VALID;
+ if (ent->is_static)
+ *fwd_entry |= ARL_STATIC;
+ if (ent->is_age)
+ *fwd_entry |= ARL_AGE;
+}
+
struct bcm_sf2_priv {
/* Base registers, keep those in order with BCM_SF2_REGS_NAME */
void __iomem *core;
@@ -78,6 +134,12 @@ struct bcm_sf2_priv {
/* Mask of ports enabled for Wake-on-LAN */
u32 wol_ports_mask;
+
+ /* MoCA port location */
+ int moca_port;
+
+ /* Bitmask of ports having an integrated PHY */
+ unsigned int int_phy_mask;
};
struct bcm_sf2_hw_stats {
diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index fa4e6e78c9ea..97780d43b5c0 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -231,6 +231,49 @@
#define CORE_BRCM_HDR_RX_DIS 0x0980
#define CORE_BRCM_HDR_TX_DIS 0x0988
+#define CORE_ARLA_NUM_ENTRIES 1024
+
+#define CORE_ARLA_RWCTL 0x1400
+#define ARL_RW (1 << 0)
+#define IVL_SVL_SELECT (1 << 6)
+#define ARL_STRTDN (1 << 7)
+
+#define CORE_ARLA_MAC 0x1408
+#define CORE_ARLA_VID 0x1420
+#define ARLA_VIDTAB_INDX_MASK 0x1fff
+
+#define CORE_ARLA_MACVID0 0x1440
+#define MAC_MASK 0xffffffffff
+#define VID_SHIFT 48
+#define VID_MASK 0xfff
+
+#define CORE_ARLA_FWD_ENTRY0 0x1460
+#define PORTID_MASK 0x1ff
+#define ARL_CON_SHIFT 9
+#define ARL_CON_MASK 0x3
+#define ARL_PRI_SHIFT 11
+#define ARL_PRI_MASK 0x7
+#define ARL_AGE (1 << 14)
+#define ARL_STATIC (1 << 15)
+#define ARL_VALID (1 << 16)
+
+#define CORE_ARLA_MACVID_ENTRY(x) (CORE_ARLA_MACVID0 + ((x) * 0x40))
+#define CORE_ARLA_FWD_ENTRY(x) (CORE_ARLA_FWD_ENTRY0 + ((x) * 0x40))
+
+#define CORE_ARLA_SRCH_CTL 0x1540
+#define ARLA_SRCH_VLID (1 << 0)
+#define IVL_SVL_SELECT (1 << 6)
+#define ARLA_SRCH_STDN (1 << 7)
+
+#define CORE_ARLA_SRCH_ADR 0x1544
+#define ARLA_SRCH_ADR_VALID (1 << 15)
+
+#define CORE_ARLA_SRCH_RSLT_0_MACVID 0x1580
+#define CORE_ARLA_SRCH_RSLT_0 0x15a0
+
+#define CORE_ARLA_SRCH_RSLT_MACVID(x) (CORE_ARLA_SRCH_RSLT_0_MACVID + ((x) * 0x40))
+#define CORE_ARLA_SRCH_RSLT(x) (CORE_ARLA_SRCH_RSLT_0 + ((x) * 0x40))
+
#define CORE_MEM_PSM_VDD_CTRL 0x2380
#define P_TXQ_PSM_VDD_SHIFT 2
#define P_TXQ_PSM_VDD_MASK 0x3
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index c29aebe1e62b..0527f485c3dc 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -15,9 +15,7 @@
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
-
-#define REG_PORT(p) (8 + (p))
-#define REG_GLOBAL 0x0f
+#include "mv88e6060.h"
static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
@@ -26,7 +24,7 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
if (bus == NULL)
return -EINVAL;
- return mdiobus_read(bus, ds->pd->sw_addr + addr, reg);
+ return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg);
}
#define REG_READ(addr, reg) \
@@ -47,7 +45,7 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
if (bus == NULL)
return -EINVAL;
- return mdiobus_write(bus, ds->pd->sw_addr + addr, reg, val);
+ return mdiobus_write_nested(bus, ds->pd->sw_addr + addr, reg, val);
}
#define REG_WRITE(addr, reg, val) \
@@ -67,13 +65,14 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
if (bus == NULL)
return NULL;
- ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03);
+ ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID);
if (ret >= 0) {
- if (ret == 0x0600)
+ if (ret == PORT_SWITCH_ID_6060)
return "Marvell 88E6060 (A0)";
- if (ret == 0x0601 || ret == 0x0602)
+ if (ret == PORT_SWITCH_ID_6060_R1 ||
+ ret == PORT_SWITCH_ID_6060_R2)
return "Marvell 88E6060 (B0)";
- if ((ret & 0xfff0) == 0x0600)
+ if ((ret & PORT_SWITCH_ID_6060_MASK) == PORT_SWITCH_ID_6060)
return "Marvell 88E6060";
}
@@ -87,22 +86,26 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds)
unsigned long timeout;
/* Set all ports to the disabled state. */
- for (i = 0; i < 6; i++) {
- ret = REG_READ(REG_PORT(i), 0x04);
- REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
+ for (i = 0; i < MV88E6060_PORTS; i++) {
+ ret = REG_READ(REG_PORT(i), PORT_CONTROL);
+ REG_WRITE(REG_PORT(i), PORT_CONTROL,
+ ret & ~PORT_CONTROL_STATE_MASK);
}
/* Wait for transmit queues to drain. */
usleep_range(2000, 4000);
/* Reset the switch. */
- REG_WRITE(REG_GLOBAL, 0x0a, 0xa130);
+ REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
+ GLOBAL_ATU_CONTROL_SWRESET |
+ GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
+ GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
/* Wait up to one second for reset to complete. */
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
- ret = REG_READ(REG_GLOBAL, 0x00);
- if ((ret & 0x8000) == 0x0000)
+ ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS);
+ if (ret & GLOBAL_STATUS_INIT_READY)
break;
usleep_range(1000, 2000);
@@ -119,13 +122,15 @@ static int mv88e6060_setup_global(struct dsa_switch *ds)
* set the maximum frame size to 1536 bytes, and mask all
* interrupt sources.
*/
- REG_WRITE(REG_GLOBAL, 0x04, 0x0800);
+ REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, GLOBAL_CONTROL_MAX_FRAME_1536);
/* Enable automatic address learning, set the address
* database size to 1024 entries, and set the default aging
* time to 5 minutes.
*/
- REG_WRITE(REG_GLOBAL, 0x0a, 0x2130);
+ REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
+ GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
+ GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
return 0;
}
@@ -139,25 +144,30 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
* state to Forwarding. Additionally, if this is the CPU
* port, enable Ingress and Egress Trailer tagging mode.
*/
- REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003);
+ REG_WRITE(addr, PORT_CONTROL,
+ dsa_is_cpu_port(ds, p) ?
+ PORT_CONTROL_TRAILER |
+ PORT_CONTROL_INGRESS_MODE |
+ PORT_CONTROL_STATE_FORWARDING :
+ PORT_CONTROL_STATE_FORWARDING);
/* Port based VLAN map: give each port its own address
* database, allow the CPU port to talk to each of the 'real'
* ports, and allow each of the 'real' ports to only talk to
* the CPU port.
*/
- REG_WRITE(addr, 0x06,
- ((p & 0xf) << 12) |
- (dsa_is_cpu_port(ds, p) ?
- ds->phys_port_mask :
- (1 << ds->dst->cpu_port)));
+ REG_WRITE(addr, PORT_VLAN_MAP,
+ ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
+ (dsa_is_cpu_port(ds, p) ?
+ ds->phys_port_mask :
+ BIT(ds->dst->cpu_port)));
/* Port Association Vector: when learning source addresses
* of packets, add the address to the address database using
* a port bitmap that has only the bit for this port set and
* the other bits clear.
*/
- REG_WRITE(addr, 0x0b, 1 << p);
+ REG_WRITE(addr, PORT_ASSOC_VECTOR, BIT(p));
return 0;
}
@@ -177,7 +187,7 @@ static int mv88e6060_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < MV88E6060_PORTS; i++) {
ret = mv88e6060_setup_port(ds, i);
if (ret < 0)
return ret;
@@ -188,16 +198,17 @@ static int mv88e6060_setup(struct dsa_switch *ds)
static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr)
{
- REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
- REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
- REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
+ /* Use the same MAC Address as FD Pause frames for all ports */
+ REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 9) | addr[1]);
+ REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]);
+ REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]);
return 0;
}
static int mv88e6060_port_to_phy_addr(int port)
{
- if (port >= 0 && port <= 5)
+ if (port >= 0 && port < MV88E6060_PORTS)
return port;
return -1;
}
@@ -225,54 +236,6 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
return reg_write(ds, addr, regnum, val);
}
-static void mv88e6060_poll_link(struct dsa_switch *ds)
-{
- int i;
-
- for (i = 0; i < DSA_MAX_PORTS; i++) {
- struct net_device *dev;
- int uninitialized_var(port_status);
- int link;
- int speed;
- int duplex;
- int fc;
-
- dev = ds->ports[i];
- if (dev == NULL)
- continue;
-
- link = 0;
- if (dev->flags & IFF_UP) {
- port_status = reg_read(ds, REG_PORT(i), 0x00);
- if (port_status < 0)
- continue;
-
- link = !!(port_status & 0x1000);
- }
-
- if (!link) {
- if (netif_carrier_ok(dev)) {
- netdev_info(dev, "link down\n");
- netif_carrier_off(dev);
- }
- continue;
- }
-
- speed = (port_status & 0x0100) ? 100 : 10;
- duplex = (port_status & 0x0200) ? 1 : 0;
- fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0;
-
- if (!netif_carrier_ok(dev)) {
- netdev_info(dev,
- "link up, %d Mb/s, %s duplex, flow control %sabled\n",
- speed,
- duplex ? "full" : "half",
- fc ? "en" : "dis");
- netif_carrier_on(dev);
- }
- }
-}
-
static struct dsa_switch_driver mv88e6060_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_TRAILER,
.probe = mv88e6060_probe,
@@ -280,7 +243,6 @@ static struct dsa_switch_driver mv88e6060_switch_driver = {
.set_addr = mv88e6060_set_addr,
.phy_read = mv88e6060_phy_read,
.phy_write = mv88e6060_phy_write,
- .poll_link = mv88e6060_poll_link,
};
static int __init mv88e6060_init(void)
diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h
new file mode 100644
index 000000000000..cc9b2ed4aff4
--- /dev/null
+++ b/drivers/net/dsa/mv88e6060.h
@@ -0,0 +1,111 @@
+/*
+ * drivers/net/dsa/mv88e6060.h - Marvell 88e6060 switch chip support
+ * Copyright (c) 2015 Neil Armstrong
+ *
+ * Based on mv88e6xxx.h
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * 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.
+ */
+
+#ifndef __MV88E6060_H
+#define __MV88E6060_H
+
+#define MV88E6060_PORTS 6
+
+#define REG_PORT(p) (0x8 + (p))
+#define PORT_STATUS 0x00
+#define PORT_STATUS_PAUSE_EN BIT(15)
+#define PORT_STATUS_MY_PAUSE BIT(14)
+#define PORT_STATUS_FC (PORT_STATUS_MY_PAUSE | PORT_STATUS_PAUSE_EN)
+#define PORT_STATUS_RESOLVED BIT(13)
+#define PORT_STATUS_LINK BIT(12)
+#define PORT_STATUS_PORTMODE BIT(11)
+#define PORT_STATUS_PHYMODE BIT(10)
+#define PORT_STATUS_DUPLEX BIT(9)
+#define PORT_STATUS_SPEED BIT(8)
+#define PORT_SWITCH_ID 0x03
+#define PORT_SWITCH_ID_6060 0x0600
+#define PORT_SWITCH_ID_6060_MASK 0xfff0
+#define PORT_SWITCH_ID_6060_R1 0x0601
+#define PORT_SWITCH_ID_6060_R2 0x0602
+#define PORT_CONTROL 0x04
+#define PORT_CONTROL_FORCE_FLOW_CTRL BIT(15)
+#define PORT_CONTROL_TRAILER BIT(14)
+#define PORT_CONTROL_HEADER BIT(11)
+#define PORT_CONTROL_INGRESS_MODE BIT(8)
+#define PORT_CONTROL_VLAN_TUNNEL BIT(7)
+#define PORT_CONTROL_STATE_MASK 0x03
+#define PORT_CONTROL_STATE_DISABLED 0x00
+#define PORT_CONTROL_STATE_BLOCKING 0x01
+#define PORT_CONTROL_STATE_LEARNING 0x02
+#define PORT_CONTROL_STATE_FORWARDING 0x03
+#define PORT_VLAN_MAP 0x06
+#define PORT_VLAN_MAP_DBNUM_SHIFT 12
+#define PORT_VLAN_MAP_TABLE_MASK 0x1f
+#define PORT_ASSOC_VECTOR 0x0b
+#define PORT_ASSOC_VECTOR_MONITOR BIT(15)
+#define PORT_ASSOC_VECTOR_PAV_MASK 0x1f
+#define PORT_RX_CNTR 0x10
+#define PORT_TX_CNTR 0x11
+
+#define REG_GLOBAL 0x0f
+#define GLOBAL_STATUS 0x00
+#define GLOBAL_STATUS_SW_MODE_MASK (0x3 << 12)
+#define GLOBAL_STATUS_SW_MODE_0 (0x0 << 12)
+#define GLOBAL_STATUS_SW_MODE_1 (0x1 << 12)
+#define GLOBAL_STATUS_SW_MODE_2 (0x2 << 12)
+#define GLOBAL_STATUS_SW_MODE_3 (0x3 << 12)
+#define GLOBAL_STATUS_INIT_READY BIT(11)
+#define GLOBAL_STATUS_ATU_FULL BIT(3)
+#define GLOBAL_STATUS_ATU_DONE BIT(2)
+#define GLOBAL_STATUS_PHY_INT BIT(1)
+#define GLOBAL_STATUS_EEINT BIT(0)
+#define GLOBAL_MAC_01 0x01
+#define GLOBAL_MAC_01_DIFF_ADDR BIT(8)
+#define GLOBAL_MAC_23 0x02
+#define GLOBAL_MAC_45 0x03
+#define GLOBAL_CONTROL 0x04
+#define GLOBAL_CONTROL_DISCARD_EXCESS BIT(13)
+#define GLOBAL_CONTROL_MAX_FRAME_1536 BIT(10)
+#define GLOBAL_CONTROL_RELOAD_EEPROM BIT(9)
+#define GLOBAL_CONTROL_CTRMODE BIT(8)
+#define GLOBAL_CONTROL_ATU_FULL_EN BIT(3)
+#define GLOBAL_CONTROL_ATU_DONE_EN BIT(2)
+#define GLOBAL_CONTROL_PHYINT_EN BIT(1)
+#define GLOBAL_CONTROL_EEPROM_DONE_EN BIT(0)
+#define GLOBAL_ATU_CONTROL 0x0a
+#define GLOBAL_ATU_CONTROL_SWRESET BIT(15)
+#define GLOBAL_ATU_CONTROL_LEARNDIS BIT(14)
+#define GLOBAL_ATU_CONTROL_ATUSIZE_256 (0x0 << 12)
+#define GLOBAL_ATU_CONTROL_ATUSIZE_512 (0x1 << 12)
+#define GLOBAL_ATU_CONTROL_ATUSIZE_1024 (0x2 << 12)
+#define GLOBAL_ATU_CONTROL_ATE_AGE_SHIFT 4
+#define GLOBAL_ATU_CONTROL_ATE_AGE_MASK (0xff << 4)
+#define GLOBAL_ATU_CONTROL_ATE_AGE_5MIN (0x13 << 4)
+#define GLOBAL_ATU_OP 0x0b
+#define GLOBAL_ATU_OP_BUSY BIT(15)
+#define GLOBAL_ATU_OP_NOP (0 << 12)
+#define GLOBAL_ATU_OP_FLUSH_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_UNLOCKED ((2 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_LOAD_DB ((3 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_GET_NEXT_DB ((4 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_UNLOCKED_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_DATA 0x0c
+#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3f0
+#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4
+#define GLOBAL_ATU_DATA_STATE_MASK 0x0f
+#define GLOBAL_ATU_DATA_STATE_UNUSED 0x00
+#define GLOBAL_ATU_DATA_STATE_UC_STATIC 0x0e
+#define GLOBAL_ATU_DATA_STATE_UC_LOCKED 0x0f
+#define GLOBAL_ATU_DATA_STATE_MC_STATIC 0x07
+#define GLOBAL_ATU_DATA_STATE_MC_LOCKED 0x0e
+#define GLOBAL_ATU_MAC_01 0x0d
+#define GLOBAL_ATU_MAC_23 0x0e
+#define GLOBAL_ATU_MAC_45 0x0f
+
+#endif
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index 3de2a6d73fdc..d4fcf4570d95 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -17,39 +17,22 @@
#include <net/dsa.h>
#include "mv88e6xxx.h"
+static const struct mv88e6xxx_switch_id mv88e6123_61_65_table[] = {
+ { PORT_SWITCH_ID_6123, "Marvell 88E6123" },
+ { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" },
+ { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" },
+ { PORT_SWITCH_ID_6161, "Marvell 88E6161" },
+ { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" },
+ { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" },
+ { PORT_SWITCH_ID_6165, "Marvell 88E6165" },
+ { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" },
+ { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
+};
+
static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
- int ret;
-
- if (bus == NULL)
- return NULL;
-
- ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
- if (ret >= 0) {
- if (ret == PORT_SWITCH_ID_6123_A1)
- return "Marvell 88E6123 (A1)";
- if (ret == PORT_SWITCH_ID_6123_A2)
- return "Marvell 88E6123 (A2)";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6123)
- return "Marvell 88E6123";
-
- if (ret == PORT_SWITCH_ID_6161_A1)
- return "Marvell 88E6161 (A1)";
- if (ret == PORT_SWITCH_ID_6161_A2)
- return "Marvell 88E6161 (A2)";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6161)
- return "Marvell 88E6161";
-
- if (ret == PORT_SWITCH_ID_6165_A1)
- return "Marvell 88E6165 (A1)";
- if (ret == PORT_SWITCH_ID_6165_A2)
- return "Marvell 88e6165 (A2)";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6165)
- return "Marvell 88E6165";
- }
-
- return NULL;
+ return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_61_65_table,
+ ARRAY_SIZE(mv88e6123_61_65_table));
}
static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
@@ -125,7 +108,6 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
- .poll_link = mv88e6xxx_poll_link,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 3e8386529965..a92ca651c399 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -17,31 +17,18 @@
#include <net/dsa.h>
#include "mv88e6xxx.h"
+static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
+ { PORT_SWITCH_ID_6085, "Marvell 88E6085" },
+ { PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" },
+ { PORT_SWITCH_ID_6131, "Marvell 88E6131" },
+ { PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)" },
+ { PORT_SWITCH_ID_6185, "Marvell 88E6185" },
+};
+
static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
- int ret;
-
- if (bus == NULL)
- return NULL;
-
- ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
- if (ret >= 0) {
- int ret_masked = ret & 0xfff0;
-
- if (ret_masked == PORT_SWITCH_ID_6085)
- return "Marvell 88E6085";
- if (ret_masked == PORT_SWITCH_ID_6095)
- return "Marvell 88E6095/88E6095F";
- if (ret == PORT_SWITCH_ID_6131_B2)
- return "Marvell 88E6131 (B2)";
- if (ret_masked == PORT_SWITCH_ID_6131)
- return "Marvell 88E6131";
- if (ret_masked == PORT_SWITCH_ID_6185)
- return "Marvell 88E6185";
- }
-
- return NULL;
+ return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
+ ARRAY_SIZE(mv88e6131_table));
}
static int mv88e6131_setup_global(struct dsa_switch *ds)
@@ -178,7 +165,6 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.set_addr = mv88e6xxx_set_addr_direct,
.phy_read = mv88e6131_phy_read,
.phy_write = mv88e6131_phy_write,
- .poll_link = mv88e6xxx_poll_link,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index c2daaf087761..6e18213b9c04 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -17,27 +17,17 @@
#include <net/dsa.h>
#include "mv88e6xxx.h"
+static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
+ { PORT_SWITCH_ID_6171, "Marvell 88E6171" },
+ { PORT_SWITCH_ID_6175, "Marvell 88E6175" },
+ { PORT_SWITCH_ID_6350, "Marvell 88E6350" },
+ { PORT_SWITCH_ID_6351, "Marvell 88E6351" },
+};
+
static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
- int ret;
-
- if (bus == NULL)
- return NULL;
-
- ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
- if (ret >= 0) {
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6171)
- return "Marvell 88E6171";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6175)
- return "Marvell 88E6175";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6350)
- return "Marvell 88E6350";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6351)
- return "Marvell 88E6351";
- }
-
- return NULL;
+ return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
+ ARRAY_SIZE(mv88e6171_table));
}
static int mv88e6171_setup_global(struct dsa_switch *ds)
@@ -104,7 +94,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect,
.phy_write = mv88e6xxx_phy_write_indirect,
- .poll_link = mv88e6xxx_poll_link,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
@@ -114,17 +103,18 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
#endif
.get_regs_len = mv88e6xxx_get_regs_len,
.get_regs = mv88e6xxx_get_regs,
- .port_join_bridge = mv88e6xxx_join_bridge,
- .port_leave_bridge = mv88e6xxx_leave_bridge,
+ .port_join_bridge = mv88e6xxx_port_bridge_join,
+ .port_leave_bridge = mv88e6xxx_port_bridge_leave,
.port_stp_update = mv88e6xxx_port_stp_update,
.port_pvid_get = mv88e6xxx_port_pvid_get,
- .port_pvid_set = mv88e6xxx_port_pvid_set,
+ .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
.port_vlan_add = mv88e6xxx_port_vlan_add,
.port_vlan_del = mv88e6xxx_port_vlan_del,
.vlan_getnext = mv88e6xxx_vlan_getnext,
+ .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
.port_fdb_add = mv88e6xxx_port_fdb_add,
.port_fdb_del = mv88e6xxx_port_fdb_del,
- .port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
+ .port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
MODULE_ALIAS("platform:mv88e6171");
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 1f5129c105fb..cc6c54553418 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -22,41 +22,24 @@
#include <net/dsa.h>
#include "mv88e6xxx.h"
+static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
+ { PORT_SWITCH_ID_6172, "Marvell 88E6172" },
+ { PORT_SWITCH_ID_6176, "Marvell 88E6176" },
+ { PORT_SWITCH_ID_6320, "Marvell 88E6320" },
+ { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" },
+ { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" },
+ { PORT_SWITCH_ID_6321, "Marvell 88E6321" },
+ { PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)" },
+ { PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)" },
+ { PORT_SWITCH_ID_6352, "Marvell 88E6352" },
+ { PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)" },
+ { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
+};
+
static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
- int ret;
-
- if (bus == NULL)
- return NULL;
-
- ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
- if (ret >= 0) {
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6172)
- return "Marvell 88E6172";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6176)
- return "Marvell 88E6176";
- if (ret == PORT_SWITCH_ID_6320_A1)
- return "Marvell 88E6320 (A1)";
- if (ret == PORT_SWITCH_ID_6320_A2)
- return "Marvell 88e6320 (A2)";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6320)
- return "Marvell 88E6320";
- if (ret == PORT_SWITCH_ID_6321_A1)
- return "Marvell 88E6321 (A1)";
- if (ret == PORT_SWITCH_ID_6321_A2)
- return "Marvell 88e6321 (A2)";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6321)
- return "Marvell 88E6321";
- if (ret == PORT_SWITCH_ID_6352_A0)
- return "Marvell 88E6352 (A0)";
- if (ret == PORT_SWITCH_ID_6352_A1)
- return "Marvell 88E6352 (A1)";
- if ((ret & 0xfff0) == PORT_SWITCH_ID_6352)
- return "Marvell 88E6352";
- }
-
- return NULL;
+ return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
+ ARRAY_SIZE(mv88e6352_table));
}
static int mv88e6352_setup_global(struct dsa_switch *ds)
@@ -324,7 +307,6 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect,
.phy_write = mv88e6xxx_phy_write_indirect,
- .poll_link = mv88e6xxx_poll_link,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
@@ -341,17 +323,18 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.set_eeprom = mv88e6352_set_eeprom,
.get_regs_len = mv88e6xxx_get_regs_len,
.get_regs = mv88e6xxx_get_regs,
- .port_join_bridge = mv88e6xxx_join_bridge,
- .port_leave_bridge = mv88e6xxx_leave_bridge,
+ .port_join_bridge = mv88e6xxx_port_bridge_join,
+ .port_leave_bridge = mv88e6xxx_port_bridge_leave,
.port_stp_update = mv88e6xxx_port_stp_update,
.port_pvid_get = mv88e6xxx_port_pvid_get,
- .port_pvid_set = mv88e6xxx_port_pvid_set,
+ .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
.port_vlan_add = mv88e6xxx_port_vlan_add,
.port_vlan_del = mv88e6xxx_port_vlan_del,
.vlan_getnext = mv88e6xxx_vlan_getnext,
+ .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
.port_fdb_add = mv88e6xxx_port_fdb_add,
.port_fdb_del = mv88e6xxx_port_fdb_del,
- .port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
+ .port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
MODULE_ALIAS("platform:mv88e6172");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 1f7dd927cc5e..b06dba05594a 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -11,7 +11,6 @@
* (at your option) any later version.
*/
-#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -21,36 +20,18 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
-#include <linux/seq_file.h>
#include <net/dsa.h>
+#include <net/switchdev.h>
#include "mv88e6xxx.h"
-/* MDIO bus access can be nested in the case of PHYs connected to the
- * internal MDIO bus of the switch, which is accessed via MDIO bus of
- * the Ethernet interface. Avoid lockdep false positives by using
- * mutex_lock_nested().
- */
-static int mv88e6xxx_mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
-{
- int ret;
-
- mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
- ret = bus->read(bus, addr, regnum);
- mutex_unlock(&bus->mdio_lock);
-
- return ret;
-}
-
-static int mv88e6xxx_mdiobus_write(struct mii_bus *bus, int addr, u32 regnum,
- u16 val)
+static void assert_smi_lock(struct dsa_switch *ds)
{
- int ret;
-
- mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
- ret = bus->write(bus, addr, regnum, val);
- mutex_unlock(&bus->mdio_lock);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- return ret;
+ if (unlikely(!mutex_is_locked(&ps->smi_mutex))) {
+ dev_err(ds->master_dev, "SMI lock not held!\n");
+ dump_stack();
+ }
}
/* If the switch's ADDR[4:0] strap pins are strapped to zero, it will
@@ -67,7 +48,7 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
int i;
for (i = 0; i < 16; i++) {
- ret = mv88e6xxx_mdiobus_read(bus, sw_addr, SMI_CMD);
+ ret = mdiobus_read_nested(bus, sw_addr, SMI_CMD);
if (ret < 0)
return ret;
@@ -78,12 +59,13 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
return -ETIMEDOUT;
}
-int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
+static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
+ int reg)
{
int ret;
if (sw_addr == 0)
- return mv88e6xxx_mdiobus_read(bus, addr, reg);
+ return mdiobus_read_nested(bus, addr, reg);
/* Wait for the bus to become free. */
ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
@@ -91,8 +73,8 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
return ret;
/* Transmit the read command. */
- ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_CMD,
- SMI_CMD_OP_22_READ | (addr << 5) | reg);
+ ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
+ SMI_CMD_OP_22_READ | (addr << 5) | reg);
if (ret < 0)
return ret;
@@ -102,19 +84,20 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
return ret;
/* Read the data. */
- ret = mv88e6xxx_mdiobus_read(bus, sw_addr, SMI_DATA);
+ ret = mdiobus_read_nested(bus, sw_addr, SMI_DATA);
if (ret < 0)
return ret;
return ret & 0xffff;
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
int ret;
+ assert_smi_lock(ds);
+
if (bus == NULL)
return -EINVAL;
@@ -140,13 +123,13 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
return ret;
}
-int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
- int reg, u16 val)
+static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
+ int reg, u16 val)
{
int ret;
if (sw_addr == 0)
- return mv88e6xxx_mdiobus_write(bus, addr, reg, val);
+ return mdiobus_write_nested(bus, addr, reg, val);
/* Wait for the bus to become free. */
ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
@@ -154,13 +137,13 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
return ret;
/* Transmit the data to write. */
- ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_DATA, val);
+ ret = mdiobus_write_nested(bus, sw_addr, SMI_DATA, val);
if (ret < 0)
return ret;
/* Transmit the write command. */
- ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_CMD,
- SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
+ ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
+ SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
if (ret < 0)
return ret;
@@ -172,12 +155,13 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
return 0;
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
u16 val)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ assert_smi_lock(ds);
+
if (bus == NULL)
return -EINVAL;
@@ -233,7 +217,6 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
return 0;
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
{
if (addr >= 0)
@@ -241,7 +224,6 @@ static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
return 0xffff;
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum,
u16 val)
{
@@ -388,73 +370,6 @@ int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
}
#endif
-void mv88e6xxx_poll_link(struct dsa_switch *ds)
-{
- int i;
-
- for (i = 0; i < DSA_MAX_PORTS; i++) {
- struct net_device *dev;
- int uninitialized_var(port_status);
- int pcs_ctrl;
- int link;
- int speed;
- int duplex;
- int fc;
-
- dev = ds->ports[i];
- if (dev == NULL)
- continue;
-
- pcs_ctrl = mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_PCS_CTRL);
- if (pcs_ctrl < 0 || pcs_ctrl & PORT_PCS_CTRL_FORCE_LINK)
- continue;
-
- link = 0;
- if (dev->flags & IFF_UP) {
- port_status = mv88e6xxx_reg_read(ds, REG_PORT(i),
- PORT_STATUS);
- if (port_status < 0)
- continue;
-
- link = !!(port_status & PORT_STATUS_LINK);
- }
-
- if (!link) {
- if (netif_carrier_ok(dev)) {
- netdev_info(dev, "link down\n");
- netif_carrier_off(dev);
- }
- continue;
- }
-
- switch (port_status & PORT_STATUS_SPEED_MASK) {
- case PORT_STATUS_SPEED_10:
- speed = 10;
- break;
- case PORT_STATUS_SPEED_100:
- speed = 100;
- break;
- case PORT_STATUS_SPEED_1000:
- speed = 1000;
- break;
- default:
- speed = -1;
- break;
- }
- duplex = (port_status & PORT_STATUS_DUPLEX) ? 1 : 0;
- fc = (port_status & PORT_STATUS_PAUSE_EN) ? 1 : 0;
-
- if (!netif_carrier_ok(dev)) {
- netdev_info(dev,
- "link up, %d Mb/s, %s duplex, flow control %sabled\n",
- speed,
- duplex ? "full" : "half",
- fc ? "en" : "dis");
- netif_carrier_on(dev);
- }
- }
-}
-
static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -574,7 +489,8 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u32 ret, reg;
+ u32 reg;
+ int ret;
if (!phy_is_pseudo_fixed_link(phydev))
return;
@@ -633,7 +549,6 @@ out:
mutex_unlock(&ps->smi_mutex);
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
{
int ret;
@@ -648,7 +563,6 @@ static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
return -ETIMEDOUT;
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
{
int ret;
@@ -671,7 +585,6 @@ static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
return 0;
}
-/* Must be called with SMI mutex held */
static void _mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
{
u32 _val;
@@ -884,7 +797,6 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
}
}
-/* Must be called with SMI lock held */
static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
u16 mask)
{
@@ -934,21 +846,12 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
GLOBAL2_EEPROM_OP_BUSY);
}
-/* Must be called with SMI lock held */
static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
{
return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_ATU_OP,
GLOBAL_ATU_OP_BUSY);
}
-/* Must be called with SMI lock held */
-static int _mv88e6xxx_scratch_wait(struct dsa_switch *ds)
-{
- return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC,
- GLOBAL2_SCRATCH_BUSY);
-}
-
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
int regnum)
{
@@ -967,7 +870,6 @@ static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
return _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA);
}
-/* Must be called with SMI mutex held */
static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr,
int regnum, u16 val)
{
@@ -1036,14 +938,10 @@ out:
return ret;
}
-static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
+static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 cmd)
{
int ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
- if (ret < 0)
- return ret;
-
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd);
if (ret < 0)
return ret;
@@ -1051,15 +949,93 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
return _mv88e6xxx_atu_wait(ds);
}
-static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid)
+static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds,
+ struct mv88e6xxx_atu_entry *entry)
{
- int ret;
+ u16 data = entry->state & GLOBAL_ATU_DATA_STATE_MASK;
- ret = _mv88e6xxx_atu_wait(ds);
- if (ret < 0)
- return ret;
+ if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
+ unsigned int mask, shift;
+
+ if (entry->trunk) {
+ data |= GLOBAL_ATU_DATA_TRUNK;
+ mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK;
+ shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT;
+ } else {
+ mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK;
+ shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT;
+ }
+
+ data |= (entry->portv_trunkid << shift) & mask;
+ }
+
+ return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, data);
+}
+
+static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
+ struct mv88e6xxx_atu_entry *entry,
+ bool static_too)
+{
+ int op;
+ int err;
+
+ err = _mv88e6xxx_atu_wait(ds);
+ if (err)
+ return err;
+
+ err = _mv88e6xxx_atu_data_write(ds, entry);
+ if (err)
+ return err;
+
+ if (entry->fid) {
+ err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID,
+ entry->fid);
+ if (err)
+ return err;
+
+ op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB :
+ GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
+ } else {
+ op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL :
+ GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
+ }
+
+ return _mv88e6xxx_atu_cmd(ds, op);
+}
+
+static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too)
+{
+ struct mv88e6xxx_atu_entry entry = {
+ .fid = fid,
+ .state = 0, /* EntryState bits must be 0 */
+ };
+
+ return _mv88e6xxx_atu_flush_move(ds, &entry, static_too);
+}
+
+static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port,
+ int to_port, bool static_too)
+{
+ struct mv88e6xxx_atu_entry entry = {
+ .trunk = false,
+ .fid = fid,
+ };
+
+ /* EntryState bits must be 0xF */
+ entry.state = GLOBAL_ATU_DATA_STATE_MASK;
+
+ /* ToPort and FromPort are respectively in PortVec bits 7:4 and 3:0 */
+ entry.portv_trunkid = (to_port & 0x0f) << 4;
+ entry.portv_trunkid |= from_port & 0x0f;
- return _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB);
+ return _mv88e6xxx_atu_flush_move(ds, &entry, static_too);
+}
+
+static int _mv88e6xxx_atu_remove(struct dsa_switch *ds, u16 fid, int port,
+ bool static_too)
+{
+ /* Destination port 0xF means remove the entries */
+ return _mv88e6xxx_atu_move(ds, fid, port, 0x0f, static_too);
}
static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
@@ -1084,7 +1060,7 @@ static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
*/
if (oldstate >= PORT_CONTROL_STATE_LEARNING &&
state <= PORT_CONTROL_STATE_BLOCKING) {
- ret = _mv88e6xxx_flush_fid(ds, ps->fid[port]);
+ ret = _mv88e6xxx_atu_remove(ds, 0, port, false);
if (ret)
goto abort;
}
@@ -1098,130 +1074,21 @@ abort:
return ret;
}
-/* Must be called with smi lock held */
-static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u8 fid = ps->fid[port];
- u16 reg = fid << 12;
-
- if (dsa_is_cpu_port(ds, port))
- reg |= ds->phys_port_mask;
- else
- reg |= (ps->bridge_mask[fid] |
- (1 << dsa_upstream_port(ds))) & ~(1 << port);
-
- return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg);
-}
-
-/* Must be called with smi lock held */
-static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int port;
- u32 mask;
- int ret;
-
- mask = ds->phys_port_mask;
- while (mask) {
- port = __ffs(mask);
- mask &= ~(1 << port);
- if (ps->fid[port] != fid)
- continue;
-
- ret = _mv88e6xxx_update_port_config(ds, port);
- if (ret)
- return ret;
- }
-
- return _mv88e6xxx_flush_fid(ds, fid);
-}
-
-/* Bridge handling functions */
-
-int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
+static int _mv88e6xxx_port_vlan_map_set(struct dsa_switch *ds, int port,
+ u16 output_ports)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret = 0;
- u32 nmask;
- int fid;
-
- /* If the bridge group is not empty, join that group.
- * Otherwise create a new group.
- */
- fid = ps->fid[port];
- nmask = br_port_mask & ~(1 << port);
- if (nmask)
- fid = ps->fid[__ffs(nmask)];
-
- nmask = ps->bridge_mask[fid] | (1 << port);
- if (nmask != br_port_mask) {
- netdev_err(ds->ports[port],
- "join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
- fid, br_port_mask, nmask);
- return -EINVAL;
- }
-
- mutex_lock(&ps->smi_mutex);
-
- ps->bridge_mask[fid] = br_port_mask;
-
- if (fid != ps->fid[port]) {
- clear_bit(ps->fid[port], ps->fid_bitmap);
- ps->fid[port] = fid;
- ret = _mv88e6xxx_update_bridge_config(ds, fid);
- }
-
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u8 fid, newfid;
- int ret;
-
- fid = ps->fid[port];
-
- if (ps->bridge_mask[fid] != br_port_mask) {
- netdev_err(ds->ports[port],
- "leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
- fid, br_port_mask, ps->bridge_mask[fid]);
- return -EINVAL;
- }
-
- /* If the port was the last port of a bridge, we are done.
- * Otherwise assign a new fid to the port, and fix up
- * the bridge configuration.
- */
- if (br_port_mask == (1 << port))
- return 0;
-
- mutex_lock(&ps->smi_mutex);
-
- newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1);
- if (unlikely(newfid > ps->num_ports)) {
- netdev_err(ds->ports[port], "all first %d FIDs are used\n",
- ps->num_ports);
- ret = -ENOSPC;
- goto unlock;
- }
-
- ps->fid[port] = newfid;
- set_bit(newfid, ps->fid_bitmap);
- ps->bridge_mask[fid] &= ~(1 << port);
- ps->bridge_mask[newfid] = 1 << port;
+ const u16 mask = (1 << ps->num_ports) - 1;
+ int reg;
- ret = _mv88e6xxx_update_bridge_config(ds, fid);
- if (!ret)
- ret = _mv88e6xxx_update_bridge_config(ds, newfid);
+ reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
+ if (reg < 0)
+ return reg;
-unlock:
- mutex_unlock(&ps->smi_mutex);
+ reg &= ~mask;
+ reg |= output_ports & mask;
- return ret;
+ return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg);
}
int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
@@ -1258,6 +1125,19 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
return 0;
}
+static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid)
+{
+ int ret;
+
+ ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN);
+ if (ret < 0)
+ return ret;
+
+ *pvid = ret & PORT_DEFAULT_VLAN_MASK;
+
+ return 0;
+}
+
int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid)
{
int ret;
@@ -1271,9 +1151,9 @@ int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid)
return 0;
}
-int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid)
+static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid)
{
- return mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN,
+ return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN,
pvid & PORT_DEFAULT_VLAN_MASK);
}
@@ -1359,7 +1239,13 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
return 0;
}
-static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, u16 vid,
+static int _mv88e6xxx_vtu_vid_write(struct dsa_switch *ds, u16 vid)
+{
+ return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID,
+ vid & GLOBAL_VTU_VID_MASK);
+}
+
+static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds,
struct mv88e6xxx_vtu_stu_entry *entry)
{
struct mv88e6xxx_vtu_stu_entry next = { 0 };
@@ -1369,11 +1255,6 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, u16 vid,
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID,
- vid & GLOBAL_VTU_VID_MASK);
- if (ret < 0)
- return ret;
-
ret = _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_GET_NEXT);
if (ret < 0)
return ret;
@@ -1533,14 +1414,15 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid,
struct mv88e6xxx_vtu_stu_entry vlan = {
.valid = true,
.vid = vid,
+ .fid = vid, /* We use one FID per VLAN */
};
int i;
- /* exclude all ports except the CPU */
+ /* exclude all ports except the CPU and DSA ports */
for (i = 0; i < ps->num_ports; ++i)
- vlan.data[i] = dsa_is_cpu_port(ds, i) ?
- GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED :
- GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
+ vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)
+ ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
+ : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) {
@@ -1566,123 +1448,152 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid,
return err;
}
- /* Non-bridged ports and bridge groups use FIDs from 1 to
- * num_ports; VLANs use FIDs from num_ports+1 to 4095.
- */
- vlan.fid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID,
- ps->num_ports + 1);
- if (unlikely(vlan.fid == VLAN_N_VID)) {
- pr_err("no more FID available for VLAN %d\n", vid);
- return -ENOSPC;
- }
-
- err = _mv88e6xxx_flush_fid(ds, vlan.fid);
+ /* Clear all MAC addresses from the new database */
+ err = _mv88e6xxx_atu_flush(ds, vlan.fid, true);
if (err)
return err;
-
- set_bit(vlan.fid, ps->fid_bitmap);
}
*entry = vlan;
return 0;
}
-int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
- bool untagged)
+int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans)
+{
+ /* We reserve a few VLANs to isolate unbridged ports */
+ if (vlan->vid_end >= 4000)
+ return -EOPNOTSUPP;
+
+ /* We don't need any dynamic resource from the kernel (yet),
+ * so skip the prepare phase.
+ */
+ return 0;
+}
+
+static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
+ bool untagged)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
struct mv88e6xxx_vtu_stu_entry vlan;
int err;
- mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_vtu_getnext(ds, vid - 1, &vlan);
+ err = _mv88e6xxx_vtu_vid_write(ds, vid - 1);
if (err)
- goto unlock;
+ return err;
+
+ err = _mv88e6xxx_vtu_getnext(ds, &vlan);
+ if (err)
+ return err;
if (vlan.vid != vid || !vlan.valid) {
err = _mv88e6xxx_vlan_init(ds, vid, &vlan);
if (err)
- goto unlock;
+ return err;
}
vlan.data[port] = untagged ?
GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
- err = _mv88e6xxx_vtu_loadpurge(ds, &vlan);
+ return _mv88e6xxx_vtu_loadpurge(ds, &vlan);
+}
+
+int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+ bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+ u16 vid;
+ int err = 0;
+
+ mutex_lock(&ps->smi_mutex);
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ err = _mv88e6xxx_port_vlan_add(ds, port, vid, untagged);
+ if (err)
+ goto unlock;
+ }
+
+ /* no PVID with ranges, otherwise it's a bug */
+ if (pvid)
+ err = _mv88e6xxx_port_pvid_set(ds, port, vid);
unlock:
mutex_unlock(&ps->smi_mutex);
return err;
}
-int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
+static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
struct mv88e6xxx_vtu_stu_entry vlan;
- bool keep = false;
int i, err;
- mutex_lock(&ps->smi_mutex);
+ err = _mv88e6xxx_vtu_vid_write(ds, vid - 1);
+ if (err)
+ return err;
- err = _mv88e6xxx_vtu_getnext(ds, vid - 1, &vlan);
+ err = _mv88e6xxx_vtu_getnext(ds, &vlan);
if (err)
- goto unlock;
+ return err;
if (vlan.vid != vid || !vlan.valid ||
- vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
- err = -ENOENT;
- goto unlock;
- }
+ vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
+ return -ENOENT;
vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
/* keep the VLAN unless all ports are excluded */
+ vlan.valid = false;
for (i = 0; i < ps->num_ports; ++i) {
- if (dsa_is_cpu_port(ds, i))
+ if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
continue;
if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
- keep = true;
+ vlan.valid = true;
break;
}
}
- vlan.valid = keep;
err = _mv88e6xxx_vtu_loadpurge(ds, &vlan);
if (err)
- goto unlock;
-
- if (!keep)
- clear_bit(vlan.fid, ps->fid_bitmap);
-
-unlock:
- mutex_unlock(&ps->smi_mutex);
+ return err;
- return err;
+ return _mv88e6xxx_atu_remove(ds, vlan.fid, port, false);
}
-static int _mv88e6xxx_port_vtu_getnext(struct dsa_switch *ds, int port, u16 vid,
- struct mv88e6xxx_vtu_stu_entry *entry)
+int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan)
{
- int err;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ u16 pvid, vid;
+ int err = 0;
- do {
- if (vid == 4095)
- return -ENOENT;
+ mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_vtu_getnext(ds, vid, entry);
+ err = _mv88e6xxx_port_pvid_get(ds, port, &pvid);
+ if (err)
+ goto unlock;
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ err = _mv88e6xxx_port_vlan_del(ds, port, vid);
if (err)
- return err;
+ goto unlock;
- if (!entry->valid)
- return -ENOENT;
+ if (vid == pvid) {
+ err = _mv88e6xxx_port_pvid_set(ds, port, 0);
+ if (err)
+ goto unlock;
+ }
+ }
- vid = entry->vid;
- } while (entry->data[port] != GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED &&
- entry->data[port] != GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED);
+unlock:
+ mutex_unlock(&ps->smi_mutex);
- return 0;
+ return err;
}
int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
@@ -1697,7 +1608,12 @@ int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
return -ENOENT;
mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_vtu_getnext(ds, *vid, &next);
+ err = _mv88e6xxx_vtu_vid_write(ds, *vid);
+ if (err)
+ goto unlock;
+
+ err = _mv88e6xxx_vtu_getnext(ds, &next);
+unlock:
mutex_unlock(&ps->smi_mutex);
if (err)
@@ -1712,7 +1628,7 @@ int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
clear_bit(port, ports);
clear_bit(port, untagged);
- if (dsa_is_cpu_port(ds, port))
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
continue;
if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED ||
@@ -1761,7 +1677,6 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr)
static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
struct mv88e6xxx_atu_entry *entry)
{
- u16 reg = 0;
int ret;
ret = _mv88e6xxx_atu_wait(ds);
@@ -1772,47 +1687,15 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
if (ret < 0)
return ret;
- if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
- unsigned int mask, shift;
-
- if (entry->trunk) {
- reg |= GLOBAL_ATU_DATA_TRUNK;
- mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK;
- shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT;
- } else {
- mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK;
- shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT;
- }
-
- reg |= (entry->portv_trunkid << shift) & mask;
- }
-
- reg |= entry->state & GLOBAL_ATU_DATA_STATE_MASK;
-
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, reg);
+ ret = _mv88e6xxx_atu_data_write(ds, entry);
if (ret < 0)
return ret;
- return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
-}
-
-static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_vtu_stu_entry vlan;
- int err;
-
- if (vid == 0)
- return ps->fid[port];
-
- err = _mv88e6xxx_port_vtu_getnext(ds, port, vid - 1, &vlan);
- if (err)
- return err;
-
- if (vlan.vid == vid)
- return vlan.fid;
+ ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, entry->fid);
+ if (ret < 0)
+ return ret;
- return -ENOENT;
+ return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_LOAD_DB);
}
static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
@@ -1820,13 +1703,8 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
u8 state)
{
struct mv88e6xxx_atu_entry entry = { 0 };
- int ret;
- ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid);
- if (ret < 0)
- return ret;
-
- entry.fid = ret;
+ entry.fid = vid; /* We use one FID per VLAN */
entry.state = state;
ether_addr_copy(entry.mac, addr);
if (state != GLOBAL_ATU_DATA_STATE_UNUSED) {
@@ -1837,30 +1715,45 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
return _mv88e6xxx_atu_load(ds, &entry);
}
+int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
+{
+ /* We don't use per-port FDB */
+ if (fdb->vid == 0)
+ return -EOPNOTSUPP;
+
+ /* We don't need any dynamic resource from the kernel (yet),
+ * so skip the prepare phase.
+ */
+ return 0;
+}
+
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid)
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
{
- int state = is_multicast_ether_addr(addr) ?
+ int state = is_multicast_ether_addr(fdb->addr) ?
GLOBAL_ATU_DATA_STATE_MC_STATIC :
GLOBAL_ATU_DATA_STATE_UC_STATIC;
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, state);
+ ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state);
mutex_unlock(&ps->smi_mutex);
return ret;
}
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid)
+ const struct switchdev_obj_port_fdb *fdb)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid,
+ ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid,
GLOBAL_ATU_DATA_STATE_UNUSED);
mutex_unlock(&ps->smi_mutex);
@@ -1868,7 +1761,6 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
}
static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
- const unsigned char *addr,
struct mv88e6xxx_atu_entry *entry)
{
struct mv88e6xxx_atu_entry next = { 0 };
@@ -1880,11 +1772,11 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
if (ret < 0)
return ret;
- ret = _mv88e6xxx_atu_mac_write(ds, addr);
+ ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
+ ret = _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_GET_NEXT_DB);
if (ret < 0)
return ret;
@@ -1917,51 +1809,99 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
return 0;
}
-/* get next entry for port */
-int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
- unsigned char *addr, u16 *vid, bool *is_static)
+int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
+ struct switchdev_obj_port_fdb *fdb,
+ int (*cb)(struct switchdev_obj *obj))
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_atu_entry next;
- u16 fid;
- int ret;
+ struct mv88e6xxx_vtu_stu_entry vlan = {
+ .vid = GLOBAL_VTU_VID_MASK, /* all ones */
+ };
+ int err;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid);
- if (ret < 0)
+ err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid);
+ if (err)
goto unlock;
- fid = ret;
do {
- if (is_broadcast_ether_addr(addr)) {
- struct mv88e6xxx_vtu_stu_entry vtu;
+ struct mv88e6xxx_atu_entry addr = {
+ .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ };
- ret = _mv88e6xxx_port_vtu_getnext(ds, port, *vid, &vtu);
- if (ret < 0)
- goto unlock;
+ err = _mv88e6xxx_vtu_getnext(ds, &vlan);
+ if (err)
+ goto unlock;
- *vid = vtu.vid;
- fid = vtu.fid;
- }
+ if (!vlan.valid)
+ break;
- ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next);
- if (ret < 0)
+ err = _mv88e6xxx_atu_mac_write(ds, addr.mac);
+ if (err)
goto unlock;
- ether_addr_copy(addr, next.mac);
+ do {
+ err = _mv88e6xxx_atu_getnext(ds, vlan.fid, &addr);
+ if (err)
+ goto unlock;
+
+ if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED)
+ break;
+
+ if (!addr.trunk && addr.portv_trunkid & BIT(port)) {
+ bool is_static = addr.state ==
+ (is_multicast_ether_addr(addr.mac) ?
+ GLOBAL_ATU_DATA_STATE_MC_STATIC :
+ GLOBAL_ATU_DATA_STATE_UC_STATIC);
- if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED)
- continue;
- } while (next.trunk || (next.portv_trunkid & BIT(port)) == 0);
+ fdb->vid = vlan.vid;
+ ether_addr_copy(fdb->addr, addr.mac);
+ fdb->ndm_state = is_static ? NUD_NOARP :
+ NUD_REACHABLE;
+
+ err = cb(&fdb->obj);
+ if (err)
+ goto unlock;
+ }
+ } while (!is_broadcast_ether_addr(addr.mac));
+
+ } while (vlan.vid < GLOBAL_VTU_VID_MASK);
- *is_static = next.state == (is_multicast_ether_addr(addr) ?
- GLOBAL_ATU_DATA_STATE_MC_STATIC :
- GLOBAL_ATU_DATA_STATE_UC_STATIC);
unlock:
mutex_unlock(&ps->smi_mutex);
- return ret;
+ return err;
+}
+
+int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
+ int err;
+
+ /* The port joined a bridge, so leave its reserved VLAN */
+ mutex_lock(&ps->smi_mutex);
+ err = _mv88e6xxx_port_vlan_del(ds, port, pvid);
+ if (!err)
+ err = _mv88e6xxx_port_pvid_set(ds, port, 0);
+ mutex_unlock(&ps->smi_mutex);
+ return err;
+}
+
+int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
+ int err;
+
+ /* The port left the bridge, so join its reserved VLAN */
+ mutex_lock(&ps->smi_mutex);
+ err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true);
+ if (!err)
+ err = _mv88e6xxx_port_pvid_set(ds, port, pvid);
+ mutex_unlock(&ps->smi_mutex);
+ return err;
}
static void mv88e6xxx_bridge_work(struct work_struct *work)
@@ -1983,7 +1923,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret, fid;
+ int ret;
u16 reg;
mutex_lock(&ps->smi_mutex);
@@ -2109,7 +2049,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
}
- reg |= PORT_CONTROL_2_8021Q_FALLBACK;
+ reg |= PORT_CONTROL_2_8021Q_SECURE;
if (reg) {
ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
@@ -2123,8 +2063,12 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* a port bitmap that has only the bit for this port set and
* the other bits clear.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR,
- 1 << port);
+ reg = 1 << port;
+ /* Disable learning for DSA and CPU ports */
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+ reg = PORT_ASSOC_VECTOR_LOCKED_PORT;
+
+ ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
if (ret)
goto abort;
@@ -2202,19 +2146,11 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
if (ret)
goto abort;
- /* Port based VLAN map: give each port its own address
- * database, allow the CPU port to talk to each of the 'real'
- * ports, and allow each of the 'real' ports to only talk to
- * the upstream port.
+ /* Port based VLAN map: do not give each port its own address
+ * database, and allow every port to egress frames on all other ports.
*/
- fid = port + 1;
- ps->fid[port] = fid;
- set_bit(fid, ps->fid_bitmap);
-
- if (!dsa_is_cpu_port(ds, port))
- ps->bridge_mask[fid] = 1 << port;
-
- ret = _mv88e6xxx_update_port_config(ds, port);
+ reg = BIT(ps->num_ports) - 1; /* all ports */
+ ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg & ~port);
if (ret)
goto abort;
@@ -2238,271 +2174,21 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
ret = mv88e6xxx_setup_port(ds, i);
if (ret < 0)
return ret;
- }
- return 0;
-}
-
-static int mv88e6xxx_regs_show(struct seq_file *s, void *p)
-{
- struct dsa_switch *ds = s->private;
-
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int reg, port;
-
- seq_puts(s, " GLOBAL GLOBAL2 ");
- for (port = 0 ; port < ps->num_ports; port++)
- seq_printf(s, " %2d ", port);
- seq_puts(s, "\n");
-
- for (reg = 0; reg < 32; reg++) {
- seq_printf(s, "%2x: ", reg);
- seq_printf(s, " %4x %4x ",
- mv88e6xxx_reg_read(ds, REG_GLOBAL, reg),
- mv88e6xxx_reg_read(ds, REG_GLOBAL2, reg));
- for (port = 0 ; port < ps->num_ports; port++)
- seq_printf(s, "%4x ",
- mv88e6xxx_reg_read(ds, REG_PORT(port), reg));
- seq_puts(s, "\n");
- }
-
- return 0;
-}
-
-static int mv88e6xxx_regs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mv88e6xxx_regs_show, inode->i_private);
-}
-
-static const struct file_operations mv88e6xxx_regs_fops = {
- .open = mv88e6xxx_regs_open,
- .read = seq_read,
- .llseek = no_llseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static void mv88e6xxx_atu_show_header(struct seq_file *s)
-{
- seq_puts(s, "DB T/P Vec State Addr\n");
-}
-
-static void mv88e6xxx_atu_show_entry(struct seq_file *s, int dbnum,
- unsigned char *addr, int data)
-{
- bool trunk = !!(data & GLOBAL_ATU_DATA_TRUNK);
- int portvec = ((data & GLOBAL_ATU_DATA_PORT_VECTOR_MASK) >>
- GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT);
- int state = data & GLOBAL_ATU_DATA_STATE_MASK;
-
- seq_printf(s, "%03x %5s %10pb %x %pM\n",
- dbnum, (trunk ? "Trunk" : "Port"), &portvec, state, addr);
-}
-
-static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds,
- int dbnum)
-{
- unsigned char bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- unsigned char addr[6];
- int ret, data, state;
-
- ret = _mv88e6xxx_atu_mac_write(ds, bcast);
- if (ret < 0)
- return ret;
-
- do {
- ret = _mv88e6xxx_atu_cmd(ds, dbnum, GLOBAL_ATU_OP_GET_NEXT_DB);
- if (ret < 0)
- return ret;
- data = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA);
- if (data < 0)
- return data;
+ if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
+ continue;
- state = data & GLOBAL_ATU_DATA_STATE_MASK;
- if (state == GLOBAL_ATU_DATA_STATE_UNUSED)
- break;
- ret = _mv88e6xxx_atu_mac_read(ds, addr);
+ /* setup the unbridged state */
+ ret = mv88e6xxx_port_bridge_leave(ds, i, 0);
if (ret < 0)
return ret;
- mv88e6xxx_atu_show_entry(s, dbnum, addr, data);
- } while (state != GLOBAL_ATU_DATA_STATE_UNUSED);
-
- return 0;
-}
-
-static int mv88e6xxx_atu_show(struct seq_file *s, void *p)
-{
- struct dsa_switch *ds = s->private;
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int dbnum;
-
- mv88e6xxx_atu_show_header(s);
-
- for (dbnum = 0; dbnum < 255; dbnum++) {
- mutex_lock(&ps->smi_mutex);
- mv88e6xxx_atu_show_db(s, ds, dbnum);
- mutex_unlock(&ps->smi_mutex);
- }
-
- return 0;
-}
-
-static int mv88e6xxx_atu_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mv88e6xxx_atu_show, inode->i_private);
-}
-
-static const struct file_operations mv88e6xxx_atu_fops = {
- .open = mv88e6xxx_atu_open,
- .read = seq_read,
- .llseek = no_llseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static void mv88e6xxx_stats_show_header(struct seq_file *s,
- struct mv88e6xxx_priv_state *ps)
-{
- int port;
-
- seq_puts(s, " Statistic ");
- for (port = 0 ; port < ps->num_ports; port++)
- seq_printf(s, "Port %2d ", port);
- seq_puts(s, "\n");
-}
-
-static int mv88e6xxx_stats_show(struct seq_file *s, void *p)
-{
- struct dsa_switch *ds = s->private;
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_hw_stat *stats = mv88e6xxx_hw_stats;
- int port, stat, max_stats;
- uint64_t value;
-
- if (have_sw_in_discards(ds))
- max_stats = ARRAY_SIZE(mv88e6xxx_hw_stats);
- else
- max_stats = ARRAY_SIZE(mv88e6xxx_hw_stats) - 3;
-
- mv88e6xxx_stats_show_header(s, ps);
-
- mutex_lock(&ps->smi_mutex);
-
- for (stat = 0; stat < max_stats; stat++) {
- seq_printf(s, "%19s: ", stats[stat].string);
- for (port = 0 ; port < ps->num_ports; port++) {
- _mv88e6xxx_stats_snapshot(ds, port);
- value = _mv88e6xxx_get_ethtool_stat(ds, stat, stats,
- port);
- seq_printf(s, "%8llu ", value);
- }
- seq_puts(s, "\n");
}
- mutex_unlock(&ps->smi_mutex);
-
return 0;
}
-static int mv88e6xxx_stats_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mv88e6xxx_stats_show, inode->i_private);
-}
-
-static const struct file_operations mv88e6xxx_stats_fops = {
- .open = mv88e6xxx_stats_open,
- .read = seq_read,
- .llseek = no_llseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int mv88e6xxx_device_map_show(struct seq_file *s, void *p)
-{
- struct dsa_switch *ds = s->private;
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int target, ret;
-
- seq_puts(s, "Target Port\n");
-
- mutex_lock(&ps->smi_mutex);
- for (target = 0; target < 32; target++) {
- ret = _mv88e6xxx_reg_write(
- ds, REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING,
- target << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT);
- if (ret < 0)
- goto out;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2,
- GLOBAL2_DEVICE_MAPPING);
- seq_printf(s, " %2d %2d\n", target,
- ret & GLOBAL2_DEVICE_MAPPING_PORT_MASK);
- }
-out:
- mutex_unlock(&ps->smi_mutex);
-
- return 0;
-}
-
-static int mv88e6xxx_device_map_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mv88e6xxx_device_map_show, inode->i_private);
-}
-
-static const struct file_operations mv88e6xxx_device_map_fops = {
- .open = mv88e6xxx_device_map_open,
- .read = seq_read,
- .llseek = no_llseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int mv88e6xxx_scratch_show(struct seq_file *s, void *p)
-{
- struct dsa_switch *ds = s->private;
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int reg, ret;
-
- seq_puts(s, "Register Value\n");
-
- mutex_lock(&ps->smi_mutex);
- for (reg = 0; reg < 0x80; reg++) {
- ret = _mv88e6xxx_reg_write(
- ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC,
- reg << GLOBAL2_SCRATCH_REGISTER_SHIFT);
- if (ret < 0)
- goto out;
-
- ret = _mv88e6xxx_scratch_wait(ds);
- if (ret < 0)
- goto out;
-
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2,
- GLOBAL2_SCRATCH_MISC);
- seq_printf(s, " %2x %2x\n", reg,
- ret & GLOBAL2_SCRATCH_VALUE_MASK);
- }
-out:
- mutex_unlock(&ps->smi_mutex);
-
- return 0;
-}
-
-static int mv88e6xxx_scratch_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mv88e6xxx_scratch_show, inode->i_private);
-}
-
-static const struct file_operations mv88e6xxx_scratch_fops = {
- .open = mv88e6xxx_scratch_open,
- .read = seq_read,
- .llseek = no_llseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- char *name;
mutex_init(&ps->smi_mutex);
@@ -2510,24 +2196,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
- name = kasprintf(GFP_KERNEL, "dsa%d", ds->index);
- ps->dbgfs = debugfs_create_dir(name, NULL);
- kfree(name);
-
- debugfs_create_file("regs", S_IRUGO, ps->dbgfs, ds,
- &mv88e6xxx_regs_fops);
-
- debugfs_create_file("atu", S_IRUGO, ps->dbgfs, ds,
- &mv88e6xxx_atu_fops);
-
- debugfs_create_file("stats", S_IRUGO, ps->dbgfs, ds,
- &mv88e6xxx_stats_fops);
-
- debugfs_create_file("device_map", S_IRUGO, ps->dbgfs, ds,
- &mv88e6xxx_device_map_fops);
-
- debugfs_create_file("scratch", S_IRUGO, ps->dbgfs, ds,
- &mv88e6xxx_scratch_fops);
return 0;
}
@@ -2638,6 +2306,11 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
if (ret < 0)
goto unlock;
+ /* Clear all ATU entries */
+ ret = _mv88e6xxx_atu_flush(ds, 0, true);
+ if (ret < 0)
+ goto unlock;
+
/* Clear all the VTU and STU entries */
ret = _mv88e6xxx_vtu_stu_flush(ds);
unlock:
@@ -2920,6 +2593,38 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
}
#endif /* CONFIG_NET_DSA_HWMON */
+char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int num)
+{
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+ int i, ret;
+
+ if (!bus)
+ return NULL;
+
+ ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
+ if (ret < 0)
+ return NULL;
+
+ /* Look up the exact switch ID */
+ for (i = 0; i < num; ++i)
+ if (table[i].id == ret)
+ return table[i].name;
+
+ /* Look up only the product number */
+ for (i = 0; i < num; ++i) {
+ if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
+ dev_warn(host_dev, "unknown revision %d, using base switch 0x%x\n",
+ ret & PORT_SWITCH_ID_REV_MASK,
+ ret & PORT_SWITCH_ID_PROD_NUM_MASK);
+ return table[i].name;
+ }
+ }
+
+ return NULL;
+}
+
static int __init mv88e6xxx_init(void)
{
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 9b6f3d9d5ae1..21c8daa03f78 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -60,6 +60,8 @@
#define PORT_PCS_CTRL_UNFORCED 0x03
#define PORT_PAUSE_CTRL 0x02
#define PORT_SWITCH_ID 0x03
+#define PORT_SWITCH_ID_PROD_NUM_MASK 0xfff0
+#define PORT_SWITCH_ID_REV_MASK 0x000f
#define PORT_SWITCH_ID_6031 0x0310
#define PORT_SWITCH_ID_6035 0x0350
#define PORT_SWITCH_ID_6046 0x0480
@@ -157,6 +159,11 @@
#define PORT_RATE_CONTROL 0x09
#define PORT_RATE_CONTROL_2 0x0a
#define PORT_ASSOC_VECTOR 0x0b
+#define PORT_ASSOC_VECTOR_HOLD_AT_1 BIT(15)
+#define PORT_ASSOC_VECTOR_INT_AGE_OUT BIT(14)
+#define PORT_ASSOC_VECTOR_LOCKED_PORT BIT(13)
+#define PORT_ASSOC_VECTOR_IGNORE_WRONG BIT(12)
+#define PORT_ASSOC_VECTOR_REFRESH_LOCKED BIT(11)
#define PORT_ATU_CONTROL 0x0c
#define PORT_PRI_OVERRIDE 0x0d
#define PORT_ETH_TYPE 0x0f
@@ -226,12 +233,12 @@
#define GLOBAL_ATU_OP 0x0b
#define GLOBAL_ATU_OP_BUSY BIT(15)
#define GLOBAL_ATU_OP_NOP (0 << 12)
-#define GLOBAL_ATU_OP_FLUSH_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_FLUSH_NON_STATIC ((2 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_MOVE_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC ((2 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_LOAD_DB ((3 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_GET_NEXT_DB ((4 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_FLUSH_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_DATA 0x0c
#define GLOBAL_ATU_DATA_TRUNK BIT(15)
@@ -347,6 +354,11 @@
#define GLOBAL2_QOS_WEIGHT 0x1c
#define GLOBAL2_MISC 0x1d
+struct mv88e6xxx_switch_id {
+ u16 id;
+ char *name;
+};
+
struct mv88e6xxx_atu_entry {
u16 fid;
u8 state;
@@ -402,18 +414,10 @@ struct mv88e6xxx_priv_state {
int id; /* switch product id */
int num_ports; /* number of switch ports */
- /* hw bridging */
-
- DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */
- u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */
- u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */
-
unsigned long port_state_update_mask;
u8 port_state[DSA_MAX_PORTS];
struct work_struct bridge_work;
-
- struct dentry *dbgfs;
};
struct mv88e6xxx_hw_stat {
@@ -423,13 +427,13 @@ struct mv88e6xxx_hw_stat {
};
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
+char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int num);
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
int mv88e6xxx_setup_common(struct dsa_switch *ds);
int mv88e6xxx_setup_global(struct dsa_switch *ds);
-int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
-int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
- int reg, u16 val);
int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
@@ -442,7 +446,6 @@ void mv88e6xxx_ppu_state_init(struct dsa_switch *ds);
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
int regnum, u16 val);
-void mv88e6xxx_poll_link(struct dsa_switch *ds);
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data);
@@ -465,22 +468,31 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e);
-int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
-int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
+int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members);
+int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members);
int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
+int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans);
+int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans);
+int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan);
int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *vid);
-int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 vid);
-int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
- bool untagged);
-int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid);
int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
unsigned long *ports, unsigned long *untagged);
+int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans);
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid);
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans);
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid);
-int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
- unsigned char *addr, u16 *vid, bool *is_static);
+ const struct switchdev_obj_port_fdb *fdb);
+int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
+ struct switchdev_obj_port_fdb *fdb,
+ int (*cb)(struct switchdev_obj *obj));
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
int reg, int val);
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 815eb94990f5..69fc8409a973 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -147,8 +147,12 @@ static void dummy_setup(struct net_device *dev)
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
- dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
+ dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST;
+ dev->features |= NETIF_F_ALL_TSO | NETIF_F_UFO;
dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
+ dev->features |= NETIF_F_GSO_ENCAP_ALL;
+ dev->hw_features |= dev->features;
+ dev->hw_enc_features |= dev->features;
eth_hw_addr_random(dev);
}
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index edf72258ab1d..29c3075bfb05 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -64,7 +64,7 @@ config ARM_ETHERH
should say Y to this option if you wish to use it with Linux.
config MAC8390
- bool "Macintosh NS 8390 based ethernet cards"
+ tristate "Macintosh NS 8390 based ethernet cards"
depends on MAC
select CRC32
---help---
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 65cf60f6718c..b9283901136e 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -454,34 +454,22 @@ MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
MODULE_LICENSE("GPL");
-/* overkill, of course */
-static struct net_device *dev_mac8390[15];
-int init_module(void)
+static struct net_device *dev_mac8390;
+
+int __init init_module(void)
{
- int i;
- for (i = 0; i < 15; i++) {
- struct net_device *dev = mac8390_probe(-1);
- if (IS_ERR(dev))
- break;
- dev_mac890[i] = dev;
- }
- if (!i) {
- pr_notice("No useable cards found, driver NOT installed.\n");
- return -ENODEV;
+ dev_mac8390 = mac8390_probe(-1);
+ if (IS_ERR(dev_mac8390)) {
+ pr_warn("mac8390: No card found\n");
+ return PTR_ERR(dev_mac8390);
}
return 0;
}
-void cleanup_module(void)
+void __exit cleanup_module(void)
{
- int i;
- for (i = 0; i < 15; i++) {
- struct net_device *dev = dev_mac890[i];
- if (dev) {
- unregister_netdev(dev);
- free_netdev(dev);
- }
- }
+ unregister_netdev(dev_mac8390);
+ free_netdev(dev_mac8390);
}
#endif /* MODULE */
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 05aa7597dab9..955d06b9cdba 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -78,7 +78,6 @@ source "drivers/net/ethernet/ibm/Kconfig"
source "drivers/net/ethernet/intel/Kconfig"
source "drivers/net/ethernet/i825xx/Kconfig"
source "drivers/net/ethernet/xscale/Kconfig"
-source "drivers/net/ethernet/icplus/Kconfig"
config JME
tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index ddfc808110a1..4a2ee98738f0 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/
obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/
-obj-$(CONFIG_IP1000) += icplus/
obj-$(CONFIG_JME) += jme.o
obj-$(CONFIG_KORINA) += korina.o
obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index ae89de7deb13..20bf55dbd76f 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1141,8 +1141,6 @@ static void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *in
strlcpy(info->version, "revision: 1.0", sizeof(info->version));
strlcpy(info->bus_info, greth->dev->bus->name, sizeof(info->bus_info));
strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
- info->eedump_len = 0;
- info->regdump_len = sizeof(struct greth_regs);
}
static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index 48ce83e443c2..8d50314ac3eb 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -847,21 +847,25 @@ static int emac_probe(struct platform_device *pdev)
if (ndev->irq == -ENXIO) {
netdev_err(ndev, "No irq resource\n");
ret = ndev->irq;
- goto out;
+ goto out_iounmap;
}
db->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(db->clk)) {
ret = PTR_ERR(db->clk);
- goto out;
+ goto out_iounmap;
}
- clk_prepare_enable(db->clk);
+ ret = clk_prepare_enable(db->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
+ goto out_iounmap;
+ }
ret = sunxi_sram_claim(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
- goto out;
+ goto out_clk_disable_unprepare;
}
db->phy_node = of_parse_phandle(np, "phy", 0);
@@ -910,6 +914,10 @@ static int emac_probe(struct platform_device *pdev)
out_release_sram:
sunxi_sram_release(&pdev->dev);
+out_clk_disable_unprepare:
+ clk_disable_unprepare(db->clk);
+out_iounmap:
+ iounmap(db->membase);
out:
dev_err(db->dev, "not found (%d).\n", ret);
@@ -921,8 +929,12 @@ out:
static int emac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
+ struct emac_board_info *db = netdev_priv(ndev);
unregister_netdev(ndev);
+ sunxi_sram_release(&pdev->dev);
+ clk_disable_unprepare(db->clk);
+ iounmap(db->membase);
free_netdev(ndev);
dev_dbg(&pdev->dev, "released and freed device\n");
diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c
index 98a10d555b79..66d0b73c39c0 100644
--- a/drivers/net/ethernet/amd/7990.c
+++ b/drivers/net/ethernet/amd/7990.c
@@ -661,6 +661,7 @@ void lance_poll(struct net_device *dev)
spin_unlock(&lp->devlock);
lance_interrupt(dev->irq, dev);
}
+EXPORT_SYMBOL_GPL(lance_poll);
#endif
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index afc62ea804fc..0038709fd317 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -100,7 +100,7 @@ config DECLANCE
DEPCA series. (This chipset is better known via the NE2100 cards.)
config HPLANCE
- bool "HP on-board LANCE support"
+ tristate "HP on-board LANCE support"
depends on DIO
select CRC32
---help---
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index cb367cc59e0b..5330bcb8a944 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -714,7 +714,6 @@ au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
snprintf(info->bus_info, sizeof(info->bus_info), "%s %d", DRV_NAME,
aup->mac_id);
- info->regdump_len = 0;
}
static void au1000_set_msglevel(struct net_device *dev, u32 value)
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index bc8b04f42882..7ccebae9cb48 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -1500,10 +1500,11 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}
- if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) {
+ err = pci_set_dma_mask(pdev, PCNET32_DMA_MASK);
+ if (err) {
if (pcnet32_debug & NETIF_MSG_PROBE)
pr_err("architecture does not support 32bit PCI busmaster DMA\n");
- return -ENODEV;
+ return err;
}
if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) {
if (pcnet32_debug & NETIF_MSG_PROBE)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 2c063b60db4b..96f485ab612e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -327,9 +327,13 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
pdata->debugfs_xpcs_reg = 0;
buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
+ if (!buf)
+ return;
+
pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL);
if (!pdata->xgbe_debugfs) {
netdev_err(pdata->netdev, "debugfs_create_dir failed\n");
+ kfree(buf);
return;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index a4473d8ff4fa..970781a9e677 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
packet->rdesc_count, 1);
/* Make sure ownership is written to the descriptor */
- dma_wmb();
+ smp_wmb();
ring->cur = cur_index + 1;
if (!packet->skb->xmit_more ||
@@ -1940,84 +1940,31 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size,
unsigned int queue_count)
{
- unsigned int q_fifo_size = 0;
- enum xgbe_mtl_fifo_size p_fifo = XGMAC_MTL_FIFO_SIZE_256;
+ unsigned int q_fifo_size;
+ unsigned int p_fifo;
- /* Calculate Tx/Rx fifo share per queue */
- switch (fifo_size) {
- case 0:
- q_fifo_size = XGBE_FIFO_SIZE_B(128);
- break;
- case 1:
- q_fifo_size = XGBE_FIFO_SIZE_B(256);
- break;
- case 2:
- q_fifo_size = XGBE_FIFO_SIZE_B(512);
- break;
- case 3:
- q_fifo_size = XGBE_FIFO_SIZE_KB(1);
- break;
- case 4:
- q_fifo_size = XGBE_FIFO_SIZE_KB(2);
- break;
- case 5:
- q_fifo_size = XGBE_FIFO_SIZE_KB(4);
- break;
- case 6:
- q_fifo_size = XGBE_FIFO_SIZE_KB(8);
- break;
- case 7:
- q_fifo_size = XGBE_FIFO_SIZE_KB(16);
- break;
- case 8:
- q_fifo_size = XGBE_FIFO_SIZE_KB(32);
- break;
- case 9:
- q_fifo_size = XGBE_FIFO_SIZE_KB(64);
- break;
- case 10:
- q_fifo_size = XGBE_FIFO_SIZE_KB(128);
- break;
- case 11:
- q_fifo_size = XGBE_FIFO_SIZE_KB(256);
- break;
- }
+ /* Calculate the configured fifo size */
+ q_fifo_size = 1 << (fifo_size + 7);
- /* The configured value is not the actual amount of fifo RAM */
+ /* The configured value may not be the actual amount of fifo RAM */
q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size);
q_fifo_size = q_fifo_size / queue_count;
- /* Set the queue fifo size programmable value */
- if (q_fifo_size >= XGBE_FIFO_SIZE_KB(256))
- p_fifo = XGMAC_MTL_FIFO_SIZE_256K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(128))
- p_fifo = XGMAC_MTL_FIFO_SIZE_128K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(64))
- p_fifo = XGMAC_MTL_FIFO_SIZE_64K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(32))
- p_fifo = XGMAC_MTL_FIFO_SIZE_32K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(16))
- p_fifo = XGMAC_MTL_FIFO_SIZE_16K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(8))
- p_fifo = XGMAC_MTL_FIFO_SIZE_8K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(4))
- p_fifo = XGMAC_MTL_FIFO_SIZE_4K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(2))
- p_fifo = XGMAC_MTL_FIFO_SIZE_2K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(1))
- p_fifo = XGMAC_MTL_FIFO_SIZE_1K;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_B(512))
- p_fifo = XGMAC_MTL_FIFO_SIZE_512;
- else if (q_fifo_size >= XGBE_FIFO_SIZE_B(256))
- p_fifo = XGMAC_MTL_FIFO_SIZE_256;
+ /* Each increment in the queue fifo size represents 256 bytes of
+ * fifo, with 0 representing 256 bytes. Distribute the fifo equally
+ * between the queues.
+ */
+ p_fifo = q_fifo_size / 256;
+ if (p_fifo)
+ p_fifo--;
return p_fifo;
}
static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
{
- enum xgbe_mtl_fifo_size fifo_size;
+ unsigned int fifo_size;
unsigned int i;
fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size,
@@ -2033,7 +1980,7 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
{
- enum xgbe_mtl_fifo_size fifo_size;
+ unsigned int fifo_size;
unsigned int i;
fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size,
@@ -2224,7 +2171,7 @@ static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo)
default:
read_hi = false;
- };
+ }
val = XGMAC_IOREAD(pdata, reg_lo);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index aae9d5ecd182..53ce1222b11d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -360,6 +360,9 @@ static irqreturn_t xgbe_isr(int irq, void *data)
}
}
+ if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU))
+ pdata->ext_stats.rx_buffer_unavailable++;
+
/* Restart the device on a Fatal Bus Error */
if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE))
schedule_work(&pdata->restart_work);
@@ -384,7 +387,8 @@ static irqreturn_t xgbe_isr(int irq, void *data)
/* Read Tx Timestamp to clear interrupt */
pdata->tx_tstamp =
hw_if->get_tx_tstamp(pdata);
- schedule_work(&pdata->tx_tstamp_work);
+ queue_work(pdata->dev_workqueue,
+ &pdata->tx_tstamp_work);
}
}
}
@@ -450,7 +454,7 @@ static void xgbe_service_timer(unsigned long data)
{
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
- schedule_work(&pdata->service_work);
+ queue_work(pdata->dev_workqueue, &pdata->service_work);
mod_timer(&pdata->service_timer, jiffies + HZ);
}
@@ -891,7 +895,7 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
netif_tx_start_all_queues(netdev);
xgbe_start_timers(pdata);
- schedule_work(&pdata->service_work);
+ queue_work(pdata->dev_workqueue, &pdata->service_work);
DBGPR("<--xgbe_start\n");
@@ -1807,6 +1811,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
struct netdev_queue *txq;
int processed = 0;
unsigned int tx_packets = 0, tx_bytes = 0;
+ unsigned int cur;
DBGPR("-->xgbe_tx_poll\n");
@@ -1814,10 +1819,15 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
if (!ring)
return 0;
+ cur = ring->cur;
+
+ /* Be sure we get ring->cur before accessing descriptor data */
+ smp_rmb();
+
txq = netdev_get_tx_queue(netdev, channel->queue_index);
while ((processed < XGBE_TX_DESC_MAX_PROC) &&
- (ring->dirty != ring->cur)) {
+ (ring->dirty != cur)) {
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
rdesc = rdata->rdesc;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 59e090e95c0e..6040293db9c1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -179,6 +179,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = {
XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets),
+ XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
};
#define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats)
@@ -187,8 +188,6 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
int i;
- DBGPR("-->%s\n", __func__);
-
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < XGBE_STATS_COUNT; i++) {
@@ -198,8 +197,6 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
}
break;
}
-
- DBGPR("<--%s\n", __func__);
}
static void xgbe_get_ethtool_stats(struct net_device *netdev,
@@ -209,23 +206,17 @@ static void xgbe_get_ethtool_stats(struct net_device *netdev,
u8 *stat;
int i;
- DBGPR("-->%s\n", __func__);
-
pdata->hw_if.read_mmc_stats(pdata);
for (i = 0; i < XGBE_STATS_COUNT; i++) {
stat = (u8 *)pdata + xgbe_gstring_stats[i].stat_offset;
*data++ = *(u64 *)stat;
}
-
- DBGPR("<--%s\n", __func__);
}
static int xgbe_get_sset_count(struct net_device *netdev, int stringset)
{
int ret;
- DBGPR("-->%s\n", __func__);
-
switch (stringset) {
case ETH_SS_STATS:
ret = XGBE_STATS_COUNT;
@@ -235,8 +226,6 @@ static int xgbe_get_sset_count(struct net_device *netdev, int stringset)
ret = -EOPNOTSUPP;
}
- DBGPR("<--%s\n", __func__);
-
return ret;
}
@@ -245,13 +234,9 @@ static void xgbe_get_pauseparam(struct net_device *netdev,
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
- DBGPR("-->xgbe_get_pauseparam\n");
-
pause->autoneg = pdata->phy.pause_autoneg;
pause->tx_pause = pdata->phy.tx_pause;
pause->rx_pause = pdata->phy.rx_pause;
-
- DBGPR("<--xgbe_get_pauseparam\n");
}
static int xgbe_set_pauseparam(struct net_device *netdev,
@@ -260,13 +245,11 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
struct xgbe_prv_data *pdata = netdev_priv(netdev);
int ret = 0;
- DBGPR("-->xgbe_set_pauseparam\n");
-
- DBGPR(" autoneg = %d, tx_pause = %d, rx_pause = %d\n",
- pause->autoneg, pause->tx_pause, pause->rx_pause);
-
- if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE))
+ if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
+ netdev_err(netdev,
+ "autoneg disabled, pause autoneg not avialable\n");
return -EINVAL;
+ }
pdata->phy.pause_autoneg = pause->autoneg;
pdata->phy.tx_pause = pause->tx_pause;
@@ -286,8 +269,6 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
if (netif_running(netdev))
ret = pdata->phy_if.phy_config_aneg(pdata);
- DBGPR("<--xgbe_set_pauseparam\n");
-
return ret;
}
@@ -296,8 +277,6 @@ static int xgbe_get_settings(struct net_device *netdev,
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
- DBGPR("-->xgbe_get_settings\n");
-
cmd->phy_address = pdata->phy.address;
cmd->supported = pdata->phy.supported;
@@ -311,8 +290,6 @@ static int xgbe_get_settings(struct net_device *netdev,
cmd->port = PORT_NONE;
cmd->transceiver = XCVR_INTERNAL;
- DBGPR("<--xgbe_get_settings\n");
-
return 0;
}
@@ -323,16 +300,20 @@ static int xgbe_set_settings(struct net_device *netdev,
u32 speed;
int ret;
- DBGPR("-->xgbe_set_settings\n");
-
speed = ethtool_cmd_speed(cmd);
- if (cmd->phy_address != pdata->phy.address)
+ if (cmd->phy_address != pdata->phy.address) {
+ netdev_err(netdev, "invalid phy address %hhu\n",
+ cmd->phy_address);
return -EINVAL;
+ }
if ((cmd->autoneg != AUTONEG_ENABLE) &&
- (cmd->autoneg != AUTONEG_DISABLE))
+ (cmd->autoneg != AUTONEG_DISABLE)) {
+ netdev_err(netdev, "unsupported autoneg %hhu\n",
+ cmd->autoneg);
return -EINVAL;
+ }
if (cmd->autoneg == AUTONEG_DISABLE) {
switch (speed) {
@@ -341,16 +322,27 @@ static int xgbe_set_settings(struct net_device *netdev,
case SPEED_1000:
break;
default:
+ netdev_err(netdev, "unsupported speed %u\n", speed);
return -EINVAL;
}
- if (cmd->duplex != DUPLEX_FULL)
+ if (cmd->duplex != DUPLEX_FULL) {
+ netdev_err(netdev, "unsupported duplex %hhu\n",
+ cmd->duplex);
return -EINVAL;
+ }
}
+ netif_dbg(pdata, link, netdev,
+ "requested advertisement %#x, phy supported %#x\n",
+ cmd->advertising, pdata->phy.supported);
+
cmd->advertising &= pdata->phy.supported;
- if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising)
+ if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) {
+ netdev_err(netdev,
+ "unsupported requested advertisement\n");
return -EINVAL;
+ }
ret = 0;
pdata->phy.autoneg = cmd->autoneg;
@@ -366,8 +358,6 @@ static int xgbe_set_settings(struct net_device *netdev,
if (netif_running(netdev))
ret = pdata->phy_if.phy_config_aneg(pdata);
- DBGPR("<--xgbe_set_settings\n");
-
return ret;
}
@@ -385,7 +375,20 @@ static void xgbe_get_drvinfo(struct net_device *netdev,
XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
- drvinfo->n_stats = XGBE_STATS_COUNT;
+}
+
+static u32 xgbe_get_msglevel(struct net_device *netdev)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+ return pdata->msg_enable;
+}
+
+static void xgbe_set_msglevel(struct net_device *netdev, u32 msglevel)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+ pdata->msg_enable = msglevel;
}
static int xgbe_get_coalesce(struct net_device *netdev,
@@ -393,8 +396,6 @@ static int xgbe_get_coalesce(struct net_device *netdev,
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
- DBGPR("-->xgbe_get_coalesce\n");
-
memset(ec, 0, sizeof(struct ethtool_coalesce));
ec->rx_coalesce_usecs = pdata->rx_usecs;
@@ -402,8 +403,6 @@ static int xgbe_get_coalesce(struct net_device *netdev,
ec->tx_max_coalesced_frames = pdata->tx_frames;
- DBGPR("<--xgbe_get_coalesce\n");
-
return 0;
}
@@ -415,8 +414,6 @@ static int xgbe_set_coalesce(struct net_device *netdev,
unsigned int rx_frames, rx_riwt, rx_usecs;
unsigned int tx_frames;
- DBGPR("-->xgbe_set_coalesce\n");
-
/* Check for not supported parameters */
if ((ec->rx_coalesce_usecs_irq) ||
(ec->rx_max_coalesced_frames_irq) ||
@@ -436,8 +433,10 @@ static int xgbe_set_coalesce(struct net_device *netdev,
(ec->rx_max_coalesced_frames_high) ||
(ec->tx_coalesce_usecs_high) ||
(ec->tx_max_coalesced_frames_high) ||
- (ec->rate_sample_interval))
+ (ec->rate_sample_interval)) {
+ netdev_err(netdev, "unsupported coalescing parameter\n");
return -EOPNOTSUPP;
+ }
rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs);
rx_usecs = ec->rx_coalesce_usecs;
@@ -449,13 +448,13 @@ static int xgbe_set_coalesce(struct net_device *netdev,
/* Check the bounds of values for Rx */
if (rx_riwt > XGMAC_MAX_DMA_RIWT) {
- netdev_alert(netdev, "rx-usec is limited to %d usecs\n",
- hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT));
+ netdev_err(netdev, "rx-usec is limited to %d usecs\n",
+ hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT));
return -EINVAL;
}
if (rx_frames > pdata->rx_desc_count) {
- netdev_alert(netdev, "rx-frames is limited to %d frames\n",
- pdata->rx_desc_count);
+ netdev_err(netdev, "rx-frames is limited to %d frames\n",
+ pdata->rx_desc_count);
return -EINVAL;
}
@@ -463,8 +462,8 @@ static int xgbe_set_coalesce(struct net_device *netdev,
/* Check the bounds of values for Tx */
if (tx_frames > pdata->tx_desc_count) {
- netdev_alert(netdev, "tx-frames is limited to %d frames\n",
- pdata->tx_desc_count);
+ netdev_err(netdev, "tx-frames is limited to %d frames\n",
+ pdata->tx_desc_count);
return -EINVAL;
}
@@ -476,8 +475,6 @@ static int xgbe_set_coalesce(struct net_device *netdev,
pdata->tx_frames = tx_frames;
hw_if->config_tx_coalesce(pdata);
- DBGPR("<--xgbe_set_coalesce\n");
-
return 0;
}
@@ -539,8 +536,10 @@ static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
struct xgbe_hw_if *hw_if = &pdata->hw_if;
unsigned int ret;
- if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
+ if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
+ netdev_err(netdev, "unsupported hash function\n");
return -EOPNOTSUPP;
+ }
if (indir) {
ret = hw_if->set_rss_lookup_table(pdata, indir);
@@ -594,6 +593,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = {
.get_settings = xgbe_get_settings,
.set_settings = xgbe_set_settings,
.get_drvinfo = xgbe_get_drvinfo,
+ .get_msglevel = xgbe_get_msglevel,
+ .set_msglevel = xgbe_set_msglevel,
.get_link = ethtool_op_get_link,
.get_coalesce = xgbe_get_coalesce,
.set_coalesce = xgbe_set_coalesce,
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index e83bd76abce6..618d952c2984 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -342,6 +342,7 @@ static int xgbe_probe(struct platform_device *pdev)
struct resource *res;
const char *phy_mode;
unsigned int i, phy_memnum, phy_irqnum;
+ enum dev_dma_attr attr;
int ret;
DBGPR("--> xgbe_probe\n");
@@ -371,7 +372,7 @@ static int xgbe_probe(struct platform_device *pdev)
set_bit(XGBE_DOWN, &pdata->dev_state);
/* Check if we should use ACPI or DT */
- pdata->use_acpi = (!pdata->adev || acpi_disabled) ? 0 : 1;
+ pdata->use_acpi = dev->of_node ? 0 : 1;
phy_pdev = xgbe_get_phy_pdev(pdata);
if (!phy_pdev) {
@@ -609,7 +610,12 @@ static int xgbe_probe(struct platform_device *pdev)
goto err_io;
/* Set the DMA coherency values */
- pdata->coherent = device_dma_is_coherent(pdata->dev);
+ attr = device_get_dma_attr(dev);
+ if (attr == DEV_DMA_NOT_SUPPORTED) {
+ dev_err(dev, "DMA is not supported");
+ goto err_io;
+ }
+ pdata->coherent = (attr == DEV_DMA_COHERENT);
if (pdata->coherent) {
pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
pdata->arcache = XGBE_DMA_OS_ARCACHE;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 9088c3a35a20..446058081866 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -1115,8 +1115,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
unsigned int reg, link_aneg;
if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
- if (test_and_clear_bit(XGBE_LINK, &pdata->dev_state))
- netif_carrier_off(pdata->netdev);
+ netif_carrier_off(pdata->netdev);
pdata->phy.link = 0;
goto adjust_link;
@@ -1142,10 +1141,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
- if (!test_bit(XGBE_LINK, &pdata->dev_state)) {
- set_bit(XGBE_LINK, &pdata->dev_state);
- netif_carrier_on(pdata->netdev);
- }
+ netif_carrier_on(pdata->netdev);
} else {
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
xgbe_check_link_timeout(pdata);
@@ -1156,10 +1152,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
xgbe_phy_status_aneg(pdata);
- if (test_bit(XGBE_LINK, &pdata->dev_state)) {
- clear_bit(XGBE_LINK, &pdata->dev_state);
- netif_carrier_off(pdata->netdev);
- }
+ netif_carrier_off(pdata->netdev);
}
adjust_link:
@@ -1179,8 +1172,7 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
devm_free_irq(pdata->dev, pdata->an_irq, pdata);
pdata->phy.link = 0;
- if (test_and_clear_bit(XGBE_LINK, &pdata->dev_state))
- netif_carrier_off(pdata->netdev);
+ netif_carrier_off(pdata->netdev);
xgbe_phy_adjust_link(pdata);
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 8c9d01ef730d..e234b9970318 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -209,8 +209,6 @@
#define XGMAC_IOCTL_CONTEXT 2
#define XGBE_FIFO_MAX 81920
-#define XGBE_FIFO_SIZE_B(x) (x)
-#define XGBE_FIFO_SIZE_KB(x) (x * 1024)
#define XGBE_TC_MIN_QUANTUM 10
@@ -461,7 +459,6 @@ struct xgbe_channel {
enum xgbe_state {
XGBE_DOWN,
- XGBE_LINK,
XGBE_LINK_INIT,
XGBE_LINK_ERR,
};
@@ -483,20 +480,6 @@ enum xgbe_int_state {
XGMAC_INT_STATE_RESTORE,
};
-enum xgbe_mtl_fifo_size {
- XGMAC_MTL_FIFO_SIZE_256 = 0x00,
- XGMAC_MTL_FIFO_SIZE_512 = 0x01,
- XGMAC_MTL_FIFO_SIZE_1K = 0x03,
- XGMAC_MTL_FIFO_SIZE_2K = 0x07,
- XGMAC_MTL_FIFO_SIZE_4K = 0x0f,
- XGMAC_MTL_FIFO_SIZE_8K = 0x1f,
- XGMAC_MTL_FIFO_SIZE_16K = 0x3f,
- XGMAC_MTL_FIFO_SIZE_32K = 0x7f,
- XGMAC_MTL_FIFO_SIZE_64K = 0xff,
- XGMAC_MTL_FIFO_SIZE_128K = 0x1ff,
- XGMAC_MTL_FIFO_SIZE_256K = 0x3ff,
-};
-
enum xgbe_speed {
XGBE_SPEED_1000 = 0,
XGBE_SPEED_2500,
@@ -598,6 +581,7 @@ struct xgbe_mmc_stats {
struct xgbe_ext_stats {
u64 tx_tso_packets;
u64 rx_split_header_packets;
+ u64 rx_buffer_unavailable;
};
struct xgbe_hw_if {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index c4bb8027b3fb..c31e691d11fc 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -107,7 +107,8 @@ static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
{
xgene_enet_ring_set_type(ring);
- if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0)
+ if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0 ||
+ xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH1)
xgene_enet_ring_set_recombbuf(ring);
xgene_enet_ring_init(ring);
@@ -458,8 +459,48 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
}
+static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
+{
+ struct device *dev = &pdata->pdev->dev;
+
+ if (dev->of_node) {
+ struct clk *parent = clk_get_parent(pdata->clk);
+
+ switch (pdata->phy_speed) {
+ case SPEED_10:
+ clk_set_rate(parent, 2500000);
+ break;
+ case SPEED_100:
+ clk_set_rate(parent, 25000000);
+ break;
+ default:
+ clk_set_rate(parent, 125000000);
+ break;
+ }
+ }
+#ifdef CONFIG_ACPI
+ else {
+ switch (pdata->phy_speed) {
+ case SPEED_10:
+ acpi_evaluate_object(ACPI_HANDLE(dev),
+ "S10", NULL, NULL);
+ break;
+ case SPEED_100:
+ acpi_evaluate_object(ACPI_HANDLE(dev),
+ "S100", NULL, NULL);
+ break;
+ default:
+ acpi_evaluate_object(ACPI_HANDLE(dev),
+ "S1G", NULL, NULL);
+ break;
+ }
+ }
+#endif
+}
+
static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
{
+ struct device *dev = &pdata->pdev->dev;
u32 value, mc2;
u32 intf_ctl, rgmii;
u32 icm0, icm2;
@@ -475,12 +516,14 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
switch (pdata->phy_speed) {
case SPEED_10:
ENET_INTERFACE_MODE2_SET(&mc2, 1);
+ intf_ctl &= ~(ENET_LHD_MODE | ENET_GHD_MODE);
CFG_MACMODE_SET(&icm0, 0);
CFG_WAITASYNCRD_SET(&icm2, 500);
rgmii &= ~CFG_SPEED_1250;
break;
case SPEED_100:
ENET_INTERFACE_MODE2_SET(&mc2, 1);
+ intf_ctl &= ~ENET_GHD_MODE;
intf_ctl |= ENET_LHD_MODE;
CFG_MACMODE_SET(&icm0, 1);
CFG_WAITASYNCRD_SET(&icm2, 80);
@@ -488,15 +531,23 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
break;
default:
ENET_INTERFACE_MODE2_SET(&mc2, 2);
+ intf_ctl &= ~ENET_LHD_MODE;
intf_ctl |= ENET_GHD_MODE;
- CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
+ CFG_MACMODE_SET(&icm0, 2);
+ CFG_WAITASYNCRD_SET(&icm2, 0);
+ if (dev->of_node) {
+ CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay);
+ CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay);
+ }
+ rgmii |= CFG_SPEED_1250;
+
xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
break;
}
- mc2 |= FULL_DUPLEX2;
+ mc2 |= FULL_DUPLEX2 | PAD_CRC;
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
@@ -515,6 +566,7 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
/* Rtype should be copied from FP */
xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+ xgene_enet_configure_clock(pdata);
/* Rx-Tx traffic resume */
xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index ff05bbcff26d..c153a1dc5ff7 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -144,6 +144,7 @@ enum xgene_enet_rm {
#define CFG_BYPASS_UNISEC_RX BIT(1)
#define CFG_CLE_BYPASS_EN0 BIT(31)
#define CFG_TXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 29, 3)
+#define CFG_RXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 26, 3)
#define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2)
#define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12)
@@ -180,6 +181,7 @@ enum xgene_enet_rm {
#define ENET_LHD_MODE BIT(25)
#define ENET_GHD_MODE BIT(26)
#define FULL_DUPLEX2 BIT(0)
+#define PAD_CRC BIT(2)
#define SCAN_AUTO_INCR BIT(5)
#define TBYT_ADDR 0x38
#define TPKT_ADDR 0x39
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e47298faf78d..991412ce6f48 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -698,7 +698,6 @@ static int xgene_enet_open(struct net_device *ndev)
else
schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
- netif_carrier_off(ndev);
netif_start_queue(ndev);
return ret;
@@ -1118,6 +1117,47 @@ static int xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pda
return ret;
}
+static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata)
+{
+ struct device *dev = &pdata->pdev->dev;
+ int delay, ret;
+
+ ret = of_property_read_u32(dev->of_node, "tx-delay", &delay);
+ if (ret) {
+ pdata->tx_delay = 4;
+ return 0;
+ }
+
+ if (delay < 0 || delay > 7) {
+ dev_err(dev, "Invalid tx-delay specified\n");
+ return -EINVAL;
+ }
+
+ pdata->tx_delay = delay;
+
+ return 0;
+}
+
+static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata)
+{
+ struct device *dev = &pdata->pdev->dev;
+ int delay, ret;
+
+ ret = of_property_read_u32(dev->of_node, "rx-delay", &delay);
+ if (ret) {
+ pdata->rx_delay = 2;
+ return 0;
+ }
+
+ if (delay < 0 || delay > 7) {
+ dev_err(dev, "Invalid rx-delay specified\n");
+ return -EINVAL;
+ }
+
+ pdata->rx_delay = delay;
+
+ return 0;
+}
static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
{
@@ -1194,6 +1234,14 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
return -ENODEV;
}
+ ret = xgene_get_tx_delay(pdata);
+ if (ret)
+ return ret;
+
+ ret = xgene_get_rx_delay(pdata);
+ if (ret)
+ return ret;
+
ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
dev_err(dev, "Unable to get ENET Rx IRQ\n");
@@ -1305,10 +1353,17 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
pdata->ring_num = START_RING_NUM_0;
break;
case 1:
- pdata->cpu_bufnum = START_CPU_BUFNUM_1;
- pdata->eth_bufnum = START_ETH_BUFNUM_1;
- pdata->bp_bufnum = START_BP_BUFNUM_1;
- pdata->ring_num = START_RING_NUM_1;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+ pdata->cpu_bufnum = XG_START_CPU_BUFNUM_1;
+ pdata->eth_bufnum = XG_START_ETH_BUFNUM_1;
+ pdata->bp_bufnum = XG_START_BP_BUFNUM_1;
+ pdata->ring_num = XG_START_RING_NUM_1;
+ } else {
+ pdata->cpu_bufnum = START_CPU_BUFNUM_1;
+ pdata->eth_bufnum = START_ETH_BUFNUM_1;
+ pdata->bp_bufnum = START_BP_BUFNUM_1;
+ pdata->ring_num = START_RING_NUM_1;
+ }
break;
default:
break;
@@ -1478,6 +1533,7 @@ static const struct acpi_device_id xgene_enet_acpi_match[] = {
{ "APMC0D05", XGENE_ENET1},
{ "APMC0D30", XGENE_ENET1},
{ "APMC0D31", XGENE_ENET1},
+ { "APMC0D3F", XGENE_ENET1},
{ "APMC0D26", XGENE_ENET2},
{ "APMC0D25", XGENE_ENET2},
{ }
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 50f92c39ed2a..a6e56b88c0a0 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -56,6 +56,11 @@
#define START_BP_BUFNUM_1 0x2A
#define START_RING_NUM_1 264
+#define XG_START_CPU_BUFNUM_1 12
+#define XG_START_ETH_BUFNUM_1 2
+#define XG_START_BP_BUFNUM_1 0x22
+#define XG_START_RING_NUM_1 264
+
#define X2_START_CPU_BUFNUM_0 0
#define X2_START_ETH_BUFNUM_0 0
#define X2_START_BP_BUFNUM_0 0x20
@@ -179,6 +184,8 @@ struct xgene_enet_pdata {
u8 bp_bufnum;
u16 ring_num;
u32 mss;
+ u8 tx_delay;
+ u8 rx_delay;
};
struct xgene_indirect_ctl {
diff --git a/drivers/net/ethernet/apple/Kconfig b/drivers/net/ethernet/apple/Kconfig
index d19a41b0c6d2..31071297896c 100644
--- a/drivers/net/ethernet/apple/Kconfig
+++ b/drivers/net/ethernet/apple/Kconfig
@@ -51,7 +51,7 @@ config BMAC
will be called bmac.
config MACMACE
- bool "Macintosh (AV) onboard MACE ethernet"
+ tristate "Macintosh (AV) onboard MACE ethernet"
depends on MAC
select CRC32
---help---
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 48694c239d5c..872b7abb0196 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -233,10 +233,6 @@ static void atl1c_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = 0;
- drvinfo->testinfo_len = 0;
- drvinfo->regdump_len = atl1c_get_regs_len(netdev);
- drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
}
static void atl1c_get_wol(struct net_device *netdev,
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
index 1be072f4afc2..8e3dbd4d9f79 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
@@ -316,10 +316,6 @@ static void atl1e_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = 0;
- drvinfo->testinfo_len = 0;
- drvinfo->regdump_len = atl1e_get_regs_len(netdev);
- drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
}
static void atl1e_get_wol(struct net_device *netdev,
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index eca1d113fee1..529bca718334 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -3388,7 +3388,6 @@ static void atl1_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->eedump_len = ATL1_EEDUMP_LEN;
}
static void atl1_get_wol(struct net_device *netdev,
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 46a535318c7a..8f76f4558a88 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -2030,10 +2030,6 @@ static void atl2_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->fw_version, "L2", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = 0;
- drvinfo->testinfo_len = 0;
- drvinfo->regdump_len = atl2_get_regs_len(netdev);
- drvinfo->eedump_len = atl2_get_eeprom_len(netdev);
}
static void atl2_get_wol(struct net_device *netdev,
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index e930aa9a3cfb..8550df189ceb 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -170,4 +170,24 @@ config SYSTEMPORT
Broadcom BCM7xxx Set Top Box family chipset using an internal
Ethernet switch.
+config BNXT
+ tristate "Broadcom NetXtreme-C/E support"
+ depends on PCI
+ depends on VXLAN || VXLAN=n
+ select FW_LOADER
+ select LIBCRC32C
+ ---help---
+ This driver supports Broadcom NetXtreme-C/E 10/25/40/50 gigabit
+ Ethernet cards. To compile this driver as a module, choose M here:
+ the module will be called bnxt_en. This is recommended.
+
+config BNXT_SRIOV
+ bool "Broadcom NetXtreme-C/E SR-IOV support"
+ depends on BNXT && PCI_IOV
+ default y
+ ---help---
+ This configuration parameter enables Single Root Input Output
+ Virtualization support in the NetXtreme-C/E products. This
+ allows for virtual function acceleration in virtual environments.
+
endif # NET_VENDOR_BROADCOM
diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile
index e2a958a657e0..00584d78b3e0 100644
--- a/drivers/net/ethernet/broadcom/Makefile
+++ b/drivers/net/ethernet/broadcom/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
obj-$(CONFIG_TIGON3) += tg3.o
obj-$(CONFIG_BGMAC) += bgmac.o
obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
+obj-$(CONFIG_BNXT) += bnxt/
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index a7f2cc3e485e..8b1929e9f698 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1333,7 +1333,6 @@ static void bcm_enet_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->version));
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, "bcm63xx", sizeof(drvinfo->bus_info));
- drvinfo->n_stats = BCM_ENET_STATS_LEN;
}
static int bcm_enet_get_sset_count(struct net_device *netdev,
@@ -2049,7 +2048,7 @@ static void swphy_poll_timer(unsigned long data)
for (i = 0; i < priv->num_ports; i++) {
struct bcm63xx_enetsw_port *port;
- int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
+ int val, j, up, advertise, lpa, speed, duplex, media;
int external_phy = bcm_enet_port_is_rgmii(i);
u8 override;
@@ -2092,22 +2091,27 @@ static void swphy_poll_timer(unsigned long data)
lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
MII_LPA);
- lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
- MII_STAT1000);
-
/* figure out media and duplex from advertise and LPA values */
media = mii_nway_result(lpa & advertise);
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
- if (lpa2 & LPA_1000FULL)
- duplex = 1;
-
- if (lpa2 & (LPA_1000FULL | LPA_1000HALF))
- speed = 1000;
- else {
- if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
- speed = 100;
- else
- speed = 10;
+
+ if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+ speed = 100;
+ else
+ speed = 10;
+
+ if (val & BMSR_ESTATEN) {
+ advertise = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_CTRL1000);
+
+ lpa = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_STAT1000);
+
+ if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+ && lpa & (LPA_1000FULL | LPA_1000HALF)) {
+ speed = 1000;
+ duplex = (lpa & LPA_1000FULL);
+ }
}
dev_info(&priv->pdev->dev,
@@ -2597,7 +2601,6 @@ static void bcm_enetsw_get_drvinfo(struct net_device *netdev,
strncpy(drvinfo->version, bcm_enet_driver_version, 32);
strncpy(drvinfo->fw_version, "N/A", 32);
strncpy(drvinfo->bus_info, "bcm63xx", 32);
- drvinfo->n_stats = BCM_ENETSW_STATS_LEN;
}
static void bcm_enetsw_get_ethtool_stats(struct net_device *netdev,
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index f1b5364f3521..858106352ce9 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -287,7 +287,6 @@ static void bcm_sysport_get_drvinfo(struct net_device *dev,
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
strlcpy(info->version, "0.1", sizeof(info->version));
strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
- info->n_stats = BCM_SYSPORT_STATS_LEN;
}
static u32 bcm_sysport_get_msglvl(struct net_device *dev)
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 2b66ef3d8217..8fc3f3c137f8 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -813,6 +813,46 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
}
static void
+bnx2_free_stats_blk(struct net_device *dev)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+
+ if (bp->status_blk) {
+ dma_free_coherent(&bp->pdev->dev, bp->status_stats_size,
+ bp->status_blk,
+ bp->status_blk_mapping);
+ bp->status_blk = NULL;
+ bp->stats_blk = NULL;
+ }
+}
+
+static int
+bnx2_alloc_stats_blk(struct net_device *dev)
+{
+ int status_blk_size;
+ void *status_blk;
+ struct bnx2 *bp = netdev_priv(dev);
+
+ /* Combine status and statistics blocks into one allocation. */
+ status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
+ if (bp->flags & BNX2_FLAG_MSIX_CAP)
+ status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC *
+ 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);
+ if (status_blk == NULL)
+ return -ENOMEM;
+
+ bp->status_blk = status_blk;
+ bp->stats_blk = status_blk + status_blk_size;
+ bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
+
+ return 0;
+}
+
+static void
bnx2_free_mem(struct bnx2 *bp)
{
int i;
@@ -829,37 +869,19 @@ bnx2_free_mem(struct bnx2 *bp)
bp->ctx_blk[i] = NULL;
}
}
- if (bnapi->status_blk.msi) {
- dma_free_coherent(&bp->pdev->dev, bp->status_stats_size,
- bnapi->status_blk.msi,
- bp->status_blk_mapping);
+
+ if (bnapi->status_blk.msi)
bnapi->status_blk.msi = NULL;
- bp->stats_blk = NULL;
- }
}
static int
bnx2_alloc_mem(struct bnx2 *bp)
{
- int i, status_blk_size, err;
+ int i, err;
struct bnx2_napi *bnapi;
- void *status_blk;
-
- /* Combine status and statistics blocks into one allocation. */
- status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
- if (bp->flags & BNX2_FLAG_MSIX_CAP)
- status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC *
- 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);
- if (status_blk == NULL)
- goto alloc_mem_err;
bnapi = &bp->bnx2_napi[0];
- bnapi->status_blk.msi = status_blk;
+ bnapi->status_blk.msi = bp->status_blk;
bnapi->hw_tx_cons_ptr =
&bnapi->status_blk.msi->status_tx_quick_consumer_index0;
bnapi->hw_rx_cons_ptr =
@@ -870,7 +892,7 @@ bnx2_alloc_mem(struct bnx2 *bp)
bnapi = &bp->bnx2_napi[i];
- sblk = (status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i);
+ sblk = (bp->status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i);
bnapi->status_blk.msix = sblk;
bnapi->hw_tx_cons_ptr =
&sblk->status_tx_quick_consumer_index;
@@ -880,10 +902,6 @@ bnx2_alloc_mem(struct bnx2 *bp)
}
}
- bp->stats_blk = status_blk + status_blk_size;
-
- bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
-
if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE;
if (bp->ctx_pages == 0)
@@ -8330,6 +8348,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->phy_addr = 1;
+ /* allocate stats_blk */
+ rc = bnx2_alloc_stats_blk(dev);
+ if (rc)
+ goto err_out_unmap;
+
/* Disable WOL support if we are running on a SERDES chip. */
if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_get_5709_media(bp);
@@ -8453,6 +8476,8 @@ err_out_disable:
pci_disable_device(pdev);
err_out:
+ kfree(bp->temp_stats_blk);
+
return rc;
}
@@ -8586,6 +8611,7 @@ error:
pci_release_regions(pdev);
pci_disable_device(pdev);
err_free:
+ bnx2_free_stats_blk(dev);
free_netdev(dev);
return rc;
}
@@ -8603,6 +8629,7 @@ bnx2_remove_one(struct pci_dev *pdev)
pci_iounmap(bp->pdev, bp->regview);
+ bnx2_free_stats_blk(dev);
kfree(bp->temp_stats_blk);
if (bp->flags & BNX2_FLAG_AER_ENABLED) {
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index f92f76c44756..380234d72b95 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -6928,6 +6928,7 @@ struct bnx2 {
dma_addr_t status_blk_mapping;
+ void *status_blk;
struct statistics_block *stats_blk;
struct statistics_block *temp_stats_blk;
dma_addr_t stats_blk_mapping;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 44173be5cbf0..f8d7a2f06950 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -691,7 +691,7 @@ static void *bnx2x_frag_alloc(const struct bnx2x_fastpath *fp, gfp_t gfp_mask)
{
if (fp->rx_frag_size) {
/* GFP_KERNEL allocations are used only during initialization */
- if (unlikely(gfp_mask & __GFP_WAIT))
+ if (unlikely(gfpflags_allow_blocking(gfp_mask)))
return (void *)__get_free_page(gfp_mask);
return netdev_alloc_frag(fp->rx_frag_size);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index aeb7ce64452e..d84efcd34fac 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1090,10 +1090,6 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
bnx2x_fill_fw_str(bp, info->fw_version, sizeof(info->fw_version));
strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
- info->n_stats = BNX2X_NUM_STATS;
- info->testinfo_len = BNX2X_NUM_TESTS(bp);
- info->eedump_len = bp->common.flash_size;
- info->regdump_len = bnx2x_get_regs_len(dev);
}
static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -3351,6 +3347,13 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
udp_rss_requested = 0;
else
return -EINVAL;
+
+ if (CHIP_IS_E1x(bp) && udp_rss_requested) {
+ DP(BNX2X_MSG_ETHTOOL,
+ "57710, 57711 boards don't support RSS according to UDP 4-tuple\n");
+ return -EINVAL;
+ }
+
if ((info->flow_type == UDP_V4_FLOW) &&
(bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) {
bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index f1d62d5dbaff..c9b036789184 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13207,7 +13207,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
/* VF with OLD Hypervisor or old PF do not support filtering */
if (IS_PF(bp)) {
- if (CHIP_IS_E1x(bp))
+ if (chip_is_e1x)
bp->accept_any_vlan = true;
else
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile
new file mode 100644
index 000000000000..97e78e217928
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_BNXT) += bnxt_en.o
+
+bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
new file mode 100644
index 000000000000..db15c5ee09c5
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -0,0 +1,5742 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#include <linux/module.h>
+
+#include <linux/stringify.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <asm/page.h>
+#include <linux/time.h>
+#include <linux/mii.h>
+#include <linux/if.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+#if defined(CONFIG_VXLAN) || defined(CONFIG_VXLAN_MODULE)
+#include <net/vxlan.h>
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#include <net/busy_poll.h>
+#endif
+#include <linux/workqueue.h>
+#include <linux/prefetch.h>
+#include <linux/cache.h>
+#include <linux/log2.h>
+#include <linux/aer.h>
+#include <linux/bitmap.h>
+#include <linux/cpu_rmap.h>
+
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_sriov.h"
+#include "bnxt_ethtool.h"
+
+#define BNXT_TX_TIMEOUT (5 * HZ)
+
+static const char version[] =
+ "Broadcom NetXtreme-C/E driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION "\n";
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Broadcom BCM573xx network driver");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define BNXT_RX_OFFSET (NET_SKB_PAD + NET_IP_ALIGN)
+#define BNXT_RX_DMA_OFFSET NET_SKB_PAD
+#define BNXT_RX_COPY_THRESH 256
+
+#define BNXT_TX_PUSH_THRESH 92
+
+enum board_idx {
+ BCM57302,
+ BCM57304,
+ BCM57404,
+ BCM57406,
+ BCM57304_VF,
+ BCM57404_VF,
+};
+
+/* indexed by enum above */
+static const struct {
+ char *name;
+} board_info[] = {
+ { "Broadcom BCM57302 NetXtreme-C Single-port 10Gb/25Gb/40Gb/50Gb Ethernet" },
+ { "Broadcom BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet" },
+ { "Broadcom BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet" },
+ { "Broadcom BCM57406 NetXtreme-E Dual-port 10Gb Ethernet" },
+ { "Broadcom BCM57304 NetXtreme-C Ethernet Virtual Function" },
+ { "Broadcom BCM57404 NetXtreme-E Ethernet Virtual Function" },
+};
+
+static const struct pci_device_id bnxt_pci_tbl[] = {
+ { PCI_VDEVICE(BROADCOM, 0x16c9), .driver_data = BCM57302 },
+ { PCI_VDEVICE(BROADCOM, 0x16ca), .driver_data = BCM57304 },
+ { PCI_VDEVICE(BROADCOM, 0x16d1), .driver_data = BCM57404 },
+ { PCI_VDEVICE(BROADCOM, 0x16d2), .driver_data = BCM57406 },
+#ifdef CONFIG_BNXT_SRIOV
+ { PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = BCM57304_VF },
+ { PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = BCM57404_VF },
+#endif
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, bnxt_pci_tbl);
+
+static const u16 bnxt_vf_req_snif[] = {
+ HWRM_FUNC_CFG,
+ HWRM_PORT_PHY_QCFG,
+ HWRM_CFA_L2_FILTER_ALLOC,
+};
+
+static bool bnxt_vf_pciid(enum board_idx idx)
+{
+ return (idx == BCM57304_VF || idx == BCM57404_VF);
+}
+
+#define DB_CP_REARM_FLAGS (DB_KEY_CP | DB_IDX_VALID)
+#define DB_CP_FLAGS (DB_KEY_CP | DB_IDX_VALID | DB_IRQ_DIS)
+#define DB_CP_IRQ_DIS_FLAGS (DB_KEY_CP | DB_IRQ_DIS)
+
+#define BNXT_CP_DB_REARM(db, raw_cons) \
+ writel(DB_CP_REARM_FLAGS | RING_CMP(raw_cons), db)
+
+#define BNXT_CP_DB(db, raw_cons) \
+ writel(DB_CP_FLAGS | RING_CMP(raw_cons), db)
+
+#define BNXT_CP_DB_IRQ_DIS(db) \
+ writel(DB_CP_IRQ_DIS_FLAGS, db)
+
+static inline u32 bnxt_tx_avail(struct bnxt *bp, struct bnxt_tx_ring_info *txr)
+{
+ /* Tell compiler to fetch tx indices from memory. */
+ barrier();
+
+ return bp->tx_ring_size -
+ ((txr->tx_prod - txr->tx_cons) & bp->tx_ring_mask);
+}
+
+static const u16 bnxt_lhint_arr[] = {
+ TX_BD_FLAGS_LHINT_512_AND_SMALLER,
+ TX_BD_FLAGS_LHINT_512_TO_1023,
+ TX_BD_FLAGS_LHINT_1024_TO_2047,
+ TX_BD_FLAGS_LHINT_1024_TO_2047,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+ TX_BD_FLAGS_LHINT_2048_AND_LARGER,
+};
+
+static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct tx_bd *txbd;
+ struct tx_bd_ext *txbd1;
+ struct netdev_queue *txq;
+ int i;
+ dma_addr_t mapping;
+ unsigned int length, pad = 0;
+ u32 len, free_size, vlan_tag_flags, cfa_action, flags;
+ u16 prod, last_frag;
+ struct pci_dev *pdev = bp->pdev;
+ struct bnxt_napi *bnapi;
+ struct bnxt_tx_ring_info *txr;
+ struct bnxt_sw_tx_bd *tx_buf;
+
+ i = skb_get_queue_mapping(skb);
+ if (unlikely(i >= bp->tx_nr_rings)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ bnapi = bp->bnapi[i];
+ txr = &bnapi->tx_ring;
+ txq = netdev_get_tx_queue(dev, i);
+ prod = txr->tx_prod;
+
+ free_size = bnxt_tx_avail(bp, txr);
+ if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) {
+ netif_tx_stop_queue(txq);
+ return NETDEV_TX_BUSY;
+ }
+
+ length = skb->len;
+ len = skb_headlen(skb);
+ last_frag = skb_shinfo(skb)->nr_frags;
+
+ txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
+
+ txbd->tx_bd_opaque = prod;
+
+ tx_buf = &txr->tx_buf_ring[prod];
+ tx_buf->skb = skb;
+ tx_buf->nr_frags = last_frag;
+
+ vlan_tag_flags = 0;
+ cfa_action = 0;
+ if (skb_vlan_tag_present(skb)) {
+ vlan_tag_flags = TX_BD_CFA_META_KEY_VLAN |
+ skb_vlan_tag_get(skb);
+ /* Currently supports 8021Q, 8021AD vlan offloads
+ * QINQ1, QINQ2, QINQ3 vlan headers are deprecated
+ */
+ if (skb->vlan_proto == htons(ETH_P_8021Q))
+ vlan_tag_flags |= 1 << TX_BD_CFA_META_TPID_SHIFT;
+ }
+
+ if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) {
+ struct tx_push_bd *push = txr->tx_push;
+ struct tx_bd *tx_push = &push->txbd1;
+ struct tx_bd_ext *tx_push1 = &push->txbd2;
+ void *pdata = tx_push1 + 1;
+ int j;
+
+ /* Set COAL_NOW to be ready quickly for the next push */
+ tx_push->tx_bd_len_flags_type =
+ cpu_to_le32((length << TX_BD_LEN_SHIFT) |
+ TX_BD_TYPE_LONG_TX_BD |
+ TX_BD_FLAGS_LHINT_512_AND_SMALLER |
+ TX_BD_FLAGS_COAL_NOW |
+ TX_BD_FLAGS_PACKET_END |
+ (2 << TX_BD_FLAGS_BD_CNT_SHIFT));
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ tx_push1->tx_bd_hsize_lflags =
+ cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM);
+ else
+ tx_push1->tx_bd_hsize_lflags = 0;
+
+ tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags);
+ tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action);
+
+ skb_copy_from_linear_data(skb, pdata, len);
+ pdata += len;
+ for (j = 0; j < last_frag; j++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
+ void *fptr;
+
+ fptr = skb_frag_address_safe(frag);
+ if (!fptr)
+ goto normal_tx;
+
+ memcpy(pdata, fptr, skb_frag_size(frag));
+ pdata += skb_frag_size(frag);
+ }
+
+ memcpy(txbd, tx_push, sizeof(*txbd));
+ prod = NEXT_TX(prod);
+ txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
+ memcpy(txbd, tx_push1, sizeof(*txbd));
+ prod = NEXT_TX(prod);
+ push->doorbell =
+ cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod);
+ txr->tx_prod = prod;
+
+ netdev_tx_sent_queue(txq, skb->len);
+
+ __iowrite64_copy(txr->tx_doorbell, push,
+ (length + sizeof(*push) + 8) / 8);
+
+ tx_buf->is_push = 1;
+
+ goto tx_done;
+ }
+
+normal_tx:
+ if (length < BNXT_MIN_PKT_SIZE) {
+ pad = BNXT_MIN_PKT_SIZE - length;
+ if (skb_pad(skb, pad)) {
+ /* SKB already freed. */
+ tx_buf->skb = NULL;
+ return NETDEV_TX_OK;
+ }
+ length = BNXT_MIN_PKT_SIZE;
+ }
+
+ mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE);
+
+ if (unlikely(dma_mapping_error(&pdev->dev, mapping))) {
+ dev_kfree_skb_any(skb);
+ tx_buf->skb = NULL;
+ return NETDEV_TX_OK;
+ }
+
+ dma_unmap_addr_set(tx_buf, mapping, mapping);
+ flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD |
+ ((last_frag + 2) << TX_BD_FLAGS_BD_CNT_SHIFT);
+
+ txbd->tx_bd_haddr = cpu_to_le64(mapping);
+
+ prod = NEXT_TX(prod);
+ txbd1 = (struct tx_bd_ext *)
+ &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
+
+ txbd1->tx_bd_hsize_lflags = 0;
+ if (skb_is_gso(skb)) {
+ u32 hdr_len;
+
+ if (skb->encapsulation)
+ hdr_len = skb_inner_network_offset(skb) +
+ skb_inner_network_header_len(skb) +
+ inner_tcp_hdrlen(skb);
+ else
+ hdr_len = skb_transport_offset(skb) +
+ tcp_hdrlen(skb);
+
+ txbd1->tx_bd_hsize_lflags = cpu_to_le32(TX_BD_FLAGS_LSO |
+ TX_BD_FLAGS_T_IPID |
+ (hdr_len << (TX_BD_HSIZE_SHIFT - 1)));
+ length = skb_shinfo(skb)->gso_size;
+ txbd1->tx_bd_mss = cpu_to_le32(length);
+ length += hdr_len;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ txbd1->tx_bd_hsize_lflags =
+ cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM);
+ txbd1->tx_bd_mss = 0;
+ }
+
+ length >>= 9;
+ flags |= bnxt_lhint_arr[length];
+ txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
+
+ txbd1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags);
+ txbd1->tx_bd_cfa_action = cpu_to_le32(cfa_action);
+ for (i = 0; i < last_frag; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ prod = NEXT_TX(prod);
+ txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
+
+ len = skb_frag_size(frag);
+ mapping = skb_frag_dma_map(&pdev->dev, frag, 0, len,
+ DMA_TO_DEVICE);
+
+ if (unlikely(dma_mapping_error(&pdev->dev, mapping)))
+ goto tx_dma_error;
+
+ tx_buf = &txr->tx_buf_ring[prod];
+ dma_unmap_addr_set(tx_buf, mapping, mapping);
+
+ txbd->tx_bd_haddr = cpu_to_le64(mapping);
+
+ flags = len << TX_BD_LEN_SHIFT;
+ txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
+ }
+
+ flags &= ~TX_BD_LEN;
+ txbd->tx_bd_len_flags_type =
+ cpu_to_le32(((len + pad) << TX_BD_LEN_SHIFT) | flags |
+ TX_BD_FLAGS_PACKET_END);
+
+ netdev_tx_sent_queue(txq, skb->len);
+
+ /* Sync BD data before updating doorbell */
+ wmb();
+
+ prod = NEXT_TX(prod);
+ txr->tx_prod = prod;
+
+ writel(DB_KEY_TX | prod, txr->tx_doorbell);
+ writel(DB_KEY_TX | prod, txr->tx_doorbell);
+
+tx_done:
+
+ mmiowb();
+
+ if (unlikely(bnxt_tx_avail(bp, txr) <= MAX_SKB_FRAGS + 1)) {
+ netif_tx_stop_queue(txq);
+
+ /* netif_tx_stop_queue() must be done before checking
+ * tx index in bnxt_tx_avail() below, because in
+ * bnxt_tx_int(), we update tx index before checking for
+ * netif_tx_queue_stopped().
+ */
+ smp_mb();
+ if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)
+ netif_tx_wake_queue(txq);
+ }
+ return NETDEV_TX_OK;
+
+tx_dma_error:
+ last_frag = i;
+
+ /* start back at beginning and unmap skb */
+ prod = txr->tx_prod;
+ tx_buf = &txr->tx_buf_ring[prod];
+ tx_buf->skb = NULL;
+ dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
+ skb_headlen(skb), PCI_DMA_TODEVICE);
+ prod = NEXT_TX(prod);
+
+ /* unmap remaining mapped pages */
+ for (i = 0; i < last_frag; i++) {
+ prod = NEXT_TX(prod);
+ tx_buf = &txr->tx_buf_ring[prod];
+ dma_unmap_page(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
+ PCI_DMA_TODEVICE);
+ }
+
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+{
+ struct bnxt_tx_ring_info *txr = &bnapi->tx_ring;
+ int index = bnapi->index;
+ struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, index);
+ u16 cons = txr->tx_cons;
+ struct pci_dev *pdev = bp->pdev;
+ int i;
+ unsigned int tx_bytes = 0;
+
+ for (i = 0; i < nr_pkts; i++) {
+ struct bnxt_sw_tx_bd *tx_buf;
+ struct sk_buff *skb;
+ int j, last;
+
+ tx_buf = &txr->tx_buf_ring[cons];
+ cons = NEXT_TX(cons);
+ skb = tx_buf->skb;
+ tx_buf->skb = NULL;
+
+ if (tx_buf->is_push) {
+ tx_buf->is_push = 0;
+ goto next_tx_int;
+ }
+
+ dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
+ skb_headlen(skb), PCI_DMA_TODEVICE);
+ last = tx_buf->nr_frags;
+
+ for (j = 0; j < last; j++) {
+ cons = NEXT_TX(cons);
+ tx_buf = &txr->tx_buf_ring[cons];
+ dma_unmap_page(
+ &pdev->dev,
+ dma_unmap_addr(tx_buf, mapping),
+ skb_frag_size(&skb_shinfo(skb)->frags[j]),
+ PCI_DMA_TODEVICE);
+ }
+
+next_tx_int:
+ cons = NEXT_TX(cons);
+
+ tx_bytes += skb->len;
+ dev_kfree_skb_any(skb);
+ }
+
+ netdev_tx_completed_queue(txq, nr_pkts, tx_bytes);
+ txr->tx_cons = cons;
+
+ /* Need to make the tx_cons update visible to bnxt_start_xmit()
+ * before checking for netif_tx_queue_stopped(). Without the
+ * memory barrier, there is a small possibility that bnxt_start_xmit()
+ * will miss it and cause the queue to be stopped forever.
+ */
+ smp_mb();
+
+ if (unlikely(netif_tx_queue_stopped(txq)) &&
+ (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
+ __netif_tx_lock(txq, smp_processor_id());
+ if (netif_tx_queue_stopped(txq) &&
+ bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
+ txr->dev_state != BNXT_DEV_STATE_CLOSING)
+ netif_tx_wake_queue(txq);
+ __netif_tx_unlock(txq);
+ }
+}
+
+static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, dma_addr_t *mapping,
+ gfp_t gfp)
+{
+ u8 *data;
+ struct pci_dev *pdev = bp->pdev;
+
+ data = kmalloc(bp->rx_buf_size, gfp);
+ if (!data)
+ return NULL;
+
+ *mapping = dma_map_single(&pdev->dev, data + BNXT_RX_DMA_OFFSET,
+ bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+
+ if (dma_mapping_error(&pdev->dev, *mapping)) {
+ kfree(data);
+ data = NULL;
+ }
+ return data;
+}
+
+static inline int bnxt_alloc_rx_data(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr,
+ u16 prod, gfp_t gfp)
+{
+ struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[prod];
+ u8 *data;
+ dma_addr_t mapping;
+
+ data = __bnxt_alloc_rx_data(bp, &mapping, gfp);
+ if (!data)
+ return -ENOMEM;
+
+ rx_buf->data = data;
+ dma_unmap_addr_set(rx_buf, mapping, mapping);
+
+ rxbd->rx_bd_haddr = cpu_to_le64(mapping);
+
+ return 0;
+}
+
+static void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons,
+ u8 *data)
+{
+ u16 prod = rxr->rx_prod;
+ struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf;
+ struct rx_bd *cons_bd, *prod_bd;
+
+ prod_rx_buf = &rxr->rx_buf_ring[prod];
+ cons_rx_buf = &rxr->rx_buf_ring[cons];
+
+ prod_rx_buf->data = data;
+
+ dma_unmap_addr_set(prod_rx_buf, mapping,
+ dma_unmap_addr(cons_rx_buf, mapping));
+
+ prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
+
+ prod_bd->rx_bd_haddr = cons_bd->rx_bd_haddr;
+}
+
+static inline u16 bnxt_find_next_agg_idx(struct bnxt_rx_ring_info *rxr, u16 idx)
+{
+ u16 next, max = rxr->rx_agg_bmap_size;
+
+ next = find_next_zero_bit(rxr->rx_agg_bmap, max, idx);
+ if (next >= max)
+ next = find_first_zero_bit(rxr->rx_agg_bmap, max);
+ return next;
+}
+
+static inline int bnxt_alloc_rx_page(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr,
+ u16 prod, gfp_t gfp)
+{
+ struct rx_bd *rxbd =
+ &rxr->rx_agg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ struct bnxt_sw_rx_agg_bd *rx_agg_buf;
+ struct pci_dev *pdev = bp->pdev;
+ struct page *page;
+ dma_addr_t mapping;
+ u16 sw_prod = rxr->rx_sw_agg_prod;
+
+ page = alloc_page(gfp);
+ if (!page)
+ return -ENOMEM;
+
+ mapping = dma_map_page(&pdev->dev, page, 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (dma_mapping_error(&pdev->dev, mapping)) {
+ __free_page(page);
+ return -EIO;
+ }
+
+ if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap)))
+ sw_prod = bnxt_find_next_agg_idx(rxr, sw_prod);
+
+ __set_bit(sw_prod, rxr->rx_agg_bmap);
+ rx_agg_buf = &rxr->rx_agg_ring[sw_prod];
+ rxr->rx_sw_agg_prod = NEXT_RX_AGG(sw_prod);
+
+ rx_agg_buf->page = page;
+ rx_agg_buf->mapping = mapping;
+ rxbd->rx_bd_haddr = cpu_to_le64(mapping);
+ rxbd->rx_bd_opaque = sw_prod;
+ return 0;
+}
+
+static void bnxt_reuse_rx_agg_bufs(struct bnxt_napi *bnapi, u16 cp_cons,
+ u32 agg_bufs)
+{
+ struct bnxt *bp = bnapi->bp;
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ u16 prod = rxr->rx_agg_prod;
+ u16 sw_prod = rxr->rx_sw_agg_prod;
+ u32 i;
+
+ for (i = 0; i < agg_bufs; i++) {
+ u16 cons;
+ struct rx_agg_cmp *agg;
+ struct bnxt_sw_rx_agg_bd *cons_rx_buf, *prod_rx_buf;
+ struct rx_bd *prod_bd;
+ struct page *page;
+
+ agg = (struct rx_agg_cmp *)
+ &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+ cons = agg->rx_agg_cmp_opaque;
+ __clear_bit(cons, rxr->rx_agg_bmap);
+
+ if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap)))
+ sw_prod = bnxt_find_next_agg_idx(rxr, sw_prod);
+
+ __set_bit(sw_prod, rxr->rx_agg_bmap);
+ prod_rx_buf = &rxr->rx_agg_ring[sw_prod];
+ cons_rx_buf = &rxr->rx_agg_ring[cons];
+
+ /* It is possible for sw_prod to be equal to cons, so
+ * set cons_rx_buf->page to NULL first.
+ */
+ page = cons_rx_buf->page;
+ cons_rx_buf->page = NULL;
+ prod_rx_buf->page = page;
+
+ prod_rx_buf->mapping = cons_rx_buf->mapping;
+
+ prod_bd = &rxr->rx_agg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+
+ prod_bd->rx_bd_haddr = cpu_to_le64(cons_rx_buf->mapping);
+ prod_bd->rx_bd_opaque = sw_prod;
+
+ prod = NEXT_RX_AGG(prod);
+ sw_prod = NEXT_RX_AGG(sw_prod);
+ cp_cons = NEXT_CMP(cp_cons);
+ }
+ rxr->rx_agg_prod = prod;
+ rxr->rx_sw_agg_prod = sw_prod;
+}
+
+static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr, u16 cons,
+ u16 prod, u8 *data, dma_addr_t dma_addr,
+ unsigned int len)
+{
+ int err;
+ struct sk_buff *skb;
+
+ err = bnxt_alloc_rx_data(bp, rxr, prod, GFP_ATOMIC);
+ if (unlikely(err)) {
+ bnxt_reuse_rx_data(rxr, cons, data);
+ return NULL;
+ }
+
+ skb = build_skb(data, 0);
+ dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
+ PCI_DMA_FROMDEVICE);
+ if (!skb) {
+ kfree(data);
+ return NULL;
+ }
+
+ skb_reserve(skb, BNXT_RX_OFFSET);
+ skb_put(skb, len);
+ return skb;
+}
+
+static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct bnxt_napi *bnapi,
+ struct sk_buff *skb, u16 cp_cons,
+ u32 agg_bufs)
+{
+ struct pci_dev *pdev = bp->pdev;
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ u16 prod = rxr->rx_agg_prod;
+ u32 i;
+
+ for (i = 0; i < agg_bufs; i++) {
+ u16 cons, frag_len;
+ struct rx_agg_cmp *agg;
+ struct bnxt_sw_rx_agg_bd *cons_rx_buf;
+ struct page *page;
+ dma_addr_t mapping;
+
+ agg = (struct rx_agg_cmp *)
+ &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+ cons = agg->rx_agg_cmp_opaque;
+ frag_len = (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) &
+ RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT;
+
+ cons_rx_buf = &rxr->rx_agg_ring[cons];
+ skb_fill_page_desc(skb, i, cons_rx_buf->page, 0, frag_len);
+ __clear_bit(cons, rxr->rx_agg_bmap);
+
+ /* It is possible for bnxt_alloc_rx_page() to allocate
+ * a sw_prod index that equals the cons index, so we
+ * need to clear the cons entry now.
+ */
+ mapping = dma_unmap_addr(cons_rx_buf, mapping);
+ page = cons_rx_buf->page;
+ cons_rx_buf->page = NULL;
+
+ if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_ATOMIC) != 0) {
+ struct skb_shared_info *shinfo;
+ unsigned int nr_frags;
+
+ shinfo = skb_shinfo(skb);
+ nr_frags = --shinfo->nr_frags;
+ __skb_frag_set_page(&shinfo->frags[nr_frags], NULL);
+
+ dev_kfree_skb(skb);
+
+ cons_rx_buf->page = page;
+
+ /* Update prod since possibly some pages have been
+ * allocated already.
+ */
+ rxr->rx_agg_prod = prod;
+ bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs - i);
+ return NULL;
+ }
+
+ dma_unmap_page(&pdev->dev, mapping, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ skb->data_len += frag_len;
+ skb->len += frag_len;
+ skb->truesize += PAGE_SIZE;
+
+ prod = NEXT_RX_AGG(prod);
+ cp_cons = NEXT_CMP(cp_cons);
+ }
+ rxr->rx_agg_prod = prod;
+ return skb;
+}
+
+static int bnxt_agg_bufs_valid(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ u8 agg_bufs, u32 *raw_cons)
+{
+ u16 last;
+ struct rx_agg_cmp *agg;
+
+ *raw_cons = ADV_RAW_CMP(*raw_cons, agg_bufs);
+ last = RING_CMP(*raw_cons);
+ agg = (struct rx_agg_cmp *)
+ &cpr->cp_desc_ring[CP_RING(last)][CP_IDX(last)];
+ return RX_AGG_CMP_VALID(agg, *raw_cons);
+}
+
+static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
+ unsigned int len,
+ dma_addr_t mapping)
+{
+ struct bnxt *bp = bnapi->bp;
+ struct pci_dev *pdev = bp->pdev;
+ struct sk_buff *skb;
+
+ skb = napi_alloc_skb(&bnapi->napi, len);
+ if (!skb)
+ return NULL;
+
+ dma_sync_single_for_cpu(&pdev->dev, mapping,
+ bp->rx_copy_thresh, PCI_DMA_FROMDEVICE);
+
+ memcpy(skb->data - BNXT_RX_OFFSET, data, len + BNXT_RX_OFFSET);
+
+ dma_sync_single_for_device(&pdev->dev, mapping,
+ bp->rx_copy_thresh,
+ PCI_DMA_FROMDEVICE);
+
+ skb_put(skb, len);
+ return skb;
+}
+
+static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
+ struct rx_tpa_start_cmp *tpa_start,
+ struct rx_tpa_start_cmp_ext *tpa_start1)
+{
+ u8 agg_id = TPA_START_AGG_ID(tpa_start);
+ u16 cons, prod;
+ struct bnxt_tpa_info *tpa_info;
+ struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf;
+ struct rx_bd *prod_bd;
+ dma_addr_t mapping;
+
+ cons = tpa_start->rx_tpa_start_cmp_opaque;
+ prod = rxr->rx_prod;
+ cons_rx_buf = &rxr->rx_buf_ring[cons];
+ prod_rx_buf = &rxr->rx_buf_ring[prod];
+ tpa_info = &rxr->rx_tpa[agg_id];
+
+ prod_rx_buf->data = tpa_info->data;
+
+ mapping = tpa_info->mapping;
+ dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
+
+ prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+
+ prod_bd->rx_bd_haddr = cpu_to_le64(mapping);
+
+ tpa_info->data = cons_rx_buf->data;
+ cons_rx_buf->data = NULL;
+ tpa_info->mapping = dma_unmap_addr(cons_rx_buf, mapping);
+
+ tpa_info->len =
+ le32_to_cpu(tpa_start->rx_tpa_start_cmp_len_flags_type) >>
+ RX_TPA_START_CMP_LEN_SHIFT;
+ if (likely(TPA_START_HASH_VALID(tpa_start))) {
+ u32 hash_type = TPA_START_HASH_TYPE(tpa_start);
+
+ tpa_info->hash_type = PKT_HASH_TYPE_L4;
+ tpa_info->gso_type = SKB_GSO_TCPV4;
+ /* RSS profiles 1 and 3 with extract code 0 for inner 4-tuple */
+ if (hash_type == 3)
+ tpa_info->gso_type = SKB_GSO_TCPV6;
+ tpa_info->rss_hash =
+ le32_to_cpu(tpa_start->rx_tpa_start_cmp_rss_hash);
+ } else {
+ tpa_info->hash_type = PKT_HASH_TYPE_NONE;
+ tpa_info->gso_type = 0;
+ if (netif_msg_rx_err(bp))
+ netdev_warn(bp->dev, "TPA packet without valid hash\n");
+ }
+ tpa_info->flags2 = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2);
+ tpa_info->metadata = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata);
+
+ rxr->rx_prod = NEXT_RX(prod);
+ cons = NEXT_RX(cons);
+ cons_rx_buf = &rxr->rx_buf_ring[cons];
+
+ bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data);
+ rxr->rx_prod = NEXT_RX(rxr->rx_prod);
+ cons_rx_buf->data = NULL;
+}
+
+static void bnxt_abort_tpa(struct bnxt *bp, struct bnxt_napi *bnapi,
+ u16 cp_cons, u32 agg_bufs)
+{
+ if (agg_bufs)
+ bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs);
+}
+
+#define BNXT_IPV4_HDR_SIZE (sizeof(struct iphdr) + sizeof(struct tcphdr))
+#define BNXT_IPV6_HDR_SIZE (sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
+
+static inline struct sk_buff *bnxt_gro_skb(struct bnxt_tpa_info *tpa_info,
+ struct rx_tpa_end_cmp *tpa_end,
+ struct rx_tpa_end_cmp_ext *tpa_end1,
+ struct sk_buff *skb)
+{
+#ifdef CONFIG_INET
+ struct tcphdr *th;
+ int payload_off, tcp_opt_len = 0;
+ int len, nw_off;
+
+ NAPI_GRO_CB(skb)->count = TPA_END_TPA_SEGS(tpa_end);
+ skb_shinfo(skb)->gso_size =
+ le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len);
+ skb_shinfo(skb)->gso_type = tpa_info->gso_type;
+ payload_off = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
+ RX_TPA_END_CMP_PAYLOAD_OFFSET) >>
+ RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT;
+ if (TPA_END_GRO_TS(tpa_end))
+ tcp_opt_len = 12;
+
+ if (tpa_info->gso_type == SKB_GSO_TCPV4) {
+ struct iphdr *iph;
+
+ nw_off = payload_off - BNXT_IPV4_HDR_SIZE - tcp_opt_len -
+ ETH_HLEN;
+ skb_set_network_header(skb, nw_off);
+ iph = ip_hdr(skb);
+ skb_set_transport_header(skb, nw_off + sizeof(struct iphdr));
+ len = skb->len - skb_transport_offset(skb);
+ th = tcp_hdr(skb);
+ th->check = ~tcp_v4_check(len, iph->saddr, iph->daddr, 0);
+ } else if (tpa_info->gso_type == SKB_GSO_TCPV6) {
+ struct ipv6hdr *iph;
+
+ nw_off = payload_off - BNXT_IPV6_HDR_SIZE - tcp_opt_len -
+ ETH_HLEN;
+ skb_set_network_header(skb, nw_off);
+ iph = ipv6_hdr(skb);
+ skb_set_transport_header(skb, nw_off + sizeof(struct ipv6hdr));
+ len = skb->len - skb_transport_offset(skb);
+ th = tcp_hdr(skb);
+ th->check = ~tcp_v6_check(len, &iph->saddr, &iph->daddr, 0);
+ } else {
+ dev_kfree_skb_any(skb);
+ return NULL;
+ }
+ tcp_gro_complete(skb);
+
+ if (nw_off) { /* tunnel */
+ struct udphdr *uh = NULL;
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph = (struct iphdr *)skb->data;
+
+ if (iph->protocol == IPPROTO_UDP)
+ uh = (struct udphdr *)(iph + 1);
+ } else {
+ struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
+
+ if (iph->nexthdr == IPPROTO_UDP)
+ uh = (struct udphdr *)(iph + 1);
+ }
+ if (uh) {
+ if (uh->check)
+ skb_shinfo(skb)->gso_type |=
+ SKB_GSO_UDP_TUNNEL_CSUM;
+ else
+ skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
+ }
+ }
+#endif
+ return skb;
+}
+
+static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
+ struct bnxt_napi *bnapi,
+ u32 *raw_cons,
+ struct rx_tpa_end_cmp *tpa_end,
+ struct rx_tpa_end_cmp_ext *tpa_end1,
+ bool *agg_event)
+{
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ u8 agg_id = TPA_END_AGG_ID(tpa_end);
+ u8 *data, agg_bufs;
+ u16 cp_cons = RING_CMP(*raw_cons);
+ unsigned int len;
+ struct bnxt_tpa_info *tpa_info;
+ dma_addr_t mapping;
+ struct sk_buff *skb;
+
+ tpa_info = &rxr->rx_tpa[agg_id];
+ data = tpa_info->data;
+ prefetch(data);
+ len = tpa_info->len;
+ mapping = tpa_info->mapping;
+
+ agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
+ RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT;
+
+ if (agg_bufs) {
+ if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons))
+ return ERR_PTR(-EBUSY);
+
+ *agg_event = true;
+ cp_cons = NEXT_CMP(cp_cons);
+ }
+
+ if (unlikely(agg_bufs > MAX_SKB_FRAGS)) {
+ bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
+ netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
+ agg_bufs, (int)MAX_SKB_FRAGS);
+ return NULL;
+ }
+
+ if (len <= bp->rx_copy_thresh) {
+ skb = bnxt_copy_skb(bnapi, data, len, mapping);
+ if (!skb) {
+ bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
+ return NULL;
+ }
+ } else {
+ u8 *new_data;
+ dma_addr_t new_mapping;
+
+ new_data = __bnxt_alloc_rx_data(bp, &new_mapping, GFP_ATOMIC);
+ if (!new_data) {
+ bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
+ return NULL;
+ }
+
+ tpa_info->data = new_data;
+ tpa_info->mapping = new_mapping;
+
+ skb = build_skb(data, 0);
+ dma_unmap_single(&bp->pdev->dev, mapping, bp->rx_buf_use_size,
+ PCI_DMA_FROMDEVICE);
+
+ if (!skb) {
+ kfree(data);
+ bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
+ return NULL;
+ }
+ skb_reserve(skb, BNXT_RX_OFFSET);
+ skb_put(skb, len);
+ }
+
+ if (agg_bufs) {
+ skb = bnxt_rx_pages(bp, bnapi, skb, cp_cons, agg_bufs);
+ if (!skb) {
+ /* Page reuse already handled by bnxt_rx_pages(). */
+ return NULL;
+ }
+ }
+ skb->protocol = eth_type_trans(skb, bp->dev);
+
+ if (tpa_info->hash_type != PKT_HASH_TYPE_NONE)
+ skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type);
+
+ if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) {
+ netdev_features_t features = skb->dev->features;
+ u16 vlan_proto = tpa_info->metadata >>
+ RX_CMP_FLAGS2_METADATA_TPID_SFT;
+
+ if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
+ vlan_proto == ETH_P_8021Q) ||
+ ((features & NETIF_F_HW_VLAN_STAG_RX) &&
+ vlan_proto == ETH_P_8021AD)) {
+ __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
+ tpa_info->metadata &
+ RX_CMP_FLAGS2_METADATA_VID_MASK);
+ }
+ }
+
+ skb_checksum_none_assert(skb);
+ if (likely(tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_L4_CS_CALC)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->csum_level =
+ (tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3;
+ }
+
+ if (TPA_END_GRO(tpa_end))
+ skb = bnxt_gro_skb(tpa_info, tpa_end, tpa_end1, skb);
+
+ return skb;
+}
+
+/* returns the following:
+ * 1 - 1 packet successfully received
+ * 0 - successful TPA_START, packet not completed yet
+ * -EBUSY - completion ring does not have all the agg buffers yet
+ * -ENOMEM - packet aborted due to out of memory
+ * -EIO - packet aborted due to hw error indicated in BD
+ */
+static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
+ bool *agg_event)
+{
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ struct net_device *dev = bp->dev;
+ struct rx_cmp *rxcmp;
+ struct rx_cmp_ext *rxcmp1;
+ u32 tmp_raw_cons = *raw_cons;
+ u16 cons, prod, cp_cons = RING_CMP(tmp_raw_cons);
+ struct bnxt_sw_rx_bd *rx_buf;
+ unsigned int len;
+ u8 *data, agg_bufs, cmp_type;
+ dma_addr_t dma_addr;
+ struct sk_buff *skb;
+ int rc = 0;
+
+ rxcmp = (struct rx_cmp *)
+ &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+
+ tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons);
+ cp_cons = RING_CMP(tmp_raw_cons);
+ rxcmp1 = (struct rx_cmp_ext *)
+ &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+
+ if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
+ return -EBUSY;
+
+ cmp_type = RX_CMP_TYPE(rxcmp);
+
+ prod = rxr->rx_prod;
+
+ if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) {
+ bnxt_tpa_start(bp, rxr, (struct rx_tpa_start_cmp *)rxcmp,
+ (struct rx_tpa_start_cmp_ext *)rxcmp1);
+
+ goto next_rx_no_prod;
+
+ } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
+ skb = bnxt_tpa_end(bp, bnapi, &tmp_raw_cons,
+ (struct rx_tpa_end_cmp *)rxcmp,
+ (struct rx_tpa_end_cmp_ext *)rxcmp1,
+ agg_event);
+
+ if (unlikely(IS_ERR(skb)))
+ return -EBUSY;
+
+ rc = -ENOMEM;
+ if (likely(skb)) {
+ skb_record_rx_queue(skb, bnapi->index);
+ skb_mark_napi_id(skb, &bnapi->napi);
+ if (bnxt_busy_polling(bnapi))
+ netif_receive_skb(skb);
+ else
+ napi_gro_receive(&bnapi->napi, skb);
+ rc = 1;
+ }
+ goto next_rx_no_prod;
+ }
+
+ cons = rxcmp->rx_cmp_opaque;
+ rx_buf = &rxr->rx_buf_ring[cons];
+ data = rx_buf->data;
+ prefetch(data);
+
+ agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >>
+ RX_CMP_AGG_BUFS_SHIFT;
+
+ if (agg_bufs) {
+ if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, &tmp_raw_cons))
+ return -EBUSY;
+
+ cp_cons = NEXT_CMP(cp_cons);
+ *agg_event = true;
+ }
+
+ rx_buf->data = NULL;
+ if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) {
+ bnxt_reuse_rx_data(rxr, cons, data);
+ if (agg_bufs)
+ bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs);
+
+ rc = -EIO;
+ goto next_rx;
+ }
+
+ len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT;
+ dma_addr = dma_unmap_addr(rx_buf, mapping);
+
+ if (len <= bp->rx_copy_thresh) {
+ skb = bnxt_copy_skb(bnapi, data, len, dma_addr);
+ bnxt_reuse_rx_data(rxr, cons, data);
+ if (!skb) {
+ rc = -ENOMEM;
+ goto next_rx;
+ }
+ } else {
+ skb = bnxt_rx_skb(bp, rxr, cons, prod, data, dma_addr, len);
+ if (!skb) {
+ rc = -ENOMEM;
+ goto next_rx;
+ }
+ }
+
+ if (agg_bufs) {
+ skb = bnxt_rx_pages(bp, bnapi, skb, cp_cons, agg_bufs);
+ if (!skb) {
+ rc = -ENOMEM;
+ goto next_rx;
+ }
+ }
+
+ if (RX_CMP_HASH_VALID(rxcmp)) {
+ u32 hash_type = RX_CMP_HASH_TYPE(rxcmp);
+ enum pkt_hash_types type = PKT_HASH_TYPE_L4;
+
+ /* RSS profiles 1 and 3 with extract code 0 for inner 4-tuple */
+ if (hash_type != 1 && hash_type != 3)
+ type = PKT_HASH_TYPE_L3;
+ skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type);
+ }
+
+ skb->protocol = eth_type_trans(skb, dev);
+
+ if (rxcmp1->rx_cmp_flags2 &
+ cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) {
+ netdev_features_t features = skb->dev->features;
+ u32 meta_data = le32_to_cpu(rxcmp1->rx_cmp_meta_data);
+ u16 vlan_proto = meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT;
+
+ if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
+ vlan_proto == ETH_P_8021Q) ||
+ ((features & NETIF_F_HW_VLAN_STAG_RX) &&
+ vlan_proto == ETH_P_8021AD))
+ __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
+ meta_data &
+ RX_CMP_FLAGS2_METADATA_VID_MASK);
+ }
+
+ skb_checksum_none_assert(skb);
+ if (RX_CMP_L4_CS_OK(rxcmp1)) {
+ if (dev->features & NETIF_F_RXCSUM) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->csum_level = RX_CMP_ENCAP(rxcmp1);
+ }
+ } else {
+ if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS)
+ cpr->rx_l4_csum_errors++;
+ }
+
+ skb_record_rx_queue(skb, bnapi->index);
+ skb_mark_napi_id(skb, &bnapi->napi);
+ if (bnxt_busy_polling(bnapi))
+ netif_receive_skb(skb);
+ else
+ napi_gro_receive(&bnapi->napi, skb);
+ rc = 1;
+
+next_rx:
+ rxr->rx_prod = NEXT_RX(prod);
+
+next_rx_no_prod:
+ *raw_cons = tmp_raw_cons;
+
+ return rc;
+}
+
+static int bnxt_async_event_process(struct bnxt *bp,
+ struct hwrm_async_event_cmpl *cmpl)
+{
+ u16 event_id = le16_to_cpu(cmpl->event_id);
+
+ /* TODO CHIMP_FW: Define event id's for link change, error etc */
+ switch (event_id) {
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
+ set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+ break;
+ default:
+ netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n",
+ event_id);
+ break;
+ }
+ return 0;
+}
+
+static int bnxt_hwrm_handler(struct bnxt *bp, struct tx_cmp *txcmp)
+{
+ u16 cmpl_type = TX_CMP_TYPE(txcmp), vf_id, seq_id;
+ struct hwrm_cmpl *h_cmpl = (struct hwrm_cmpl *)txcmp;
+ struct hwrm_fwd_req_cmpl *fwd_req_cmpl =
+ (struct hwrm_fwd_req_cmpl *)txcmp;
+
+ switch (cmpl_type) {
+ case CMPL_BASE_TYPE_HWRM_DONE:
+ seq_id = le16_to_cpu(h_cmpl->sequence_id);
+ if (seq_id == bp->hwrm_intr_seq_id)
+ bp->hwrm_intr_seq_id = HWRM_SEQ_ID_INVALID;
+ else
+ netdev_err(bp->dev, "Invalid hwrm seq id %d\n", seq_id);
+ break;
+
+ case CMPL_BASE_TYPE_HWRM_FWD_REQ:
+ vf_id = le16_to_cpu(fwd_req_cmpl->source_id);
+
+ if ((vf_id < bp->pf.first_vf_id) ||
+ (vf_id >= bp->pf.first_vf_id + bp->pf.active_vfs)) {
+ netdev_err(bp->dev, "Msg contains invalid VF id %x\n",
+ vf_id);
+ return -EINVAL;
+ }
+
+ set_bit(vf_id - bp->pf.first_vf_id, bp->pf.vf_event_bmap);
+ set_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+ break;
+
+ case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT:
+ bnxt_async_event_process(bp,
+ (struct hwrm_async_event_cmpl *)txcmp);
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static irqreturn_t bnxt_msix(int irq, void *dev_instance)
+{
+ struct bnxt_napi *bnapi = dev_instance;
+ struct bnxt *bp = bnapi->bp;
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ u32 cons = RING_CMP(cpr->cp_raw_cons);
+
+ prefetch(&cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]);
+ napi_schedule(&bnapi->napi);
+ return IRQ_HANDLED;
+}
+
+static inline int bnxt_has_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
+{
+ u32 raw_cons = cpr->cp_raw_cons;
+ u16 cons = RING_CMP(raw_cons);
+ struct tx_cmp *txcmp;
+
+ txcmp = &cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)];
+
+ return TX_CMP_VALID(txcmp, raw_cons);
+}
+
+static irqreturn_t bnxt_inta(int irq, void *dev_instance)
+{
+ struct bnxt_napi *bnapi = dev_instance;
+ struct bnxt *bp = bnapi->bp;
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ u32 cons = RING_CMP(cpr->cp_raw_cons);
+ u32 int_status;
+
+ prefetch(&cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]);
+
+ if (!bnxt_has_work(bp, cpr)) {
+ int_status = readl(bp->bar0 + BNXT_CAG_REG_LEGACY_INT_STATUS);
+ /* return if erroneous interrupt */
+ if (!(int_status & (0x10000 << cpr->cp_ring_struct.fw_ring_id)))
+ return IRQ_NONE;
+ }
+
+ /* disable ring IRQ */
+ BNXT_CP_DB_IRQ_DIS(cpr->cp_doorbell);
+
+ /* Return here if interrupt is shared and is disabled. */
+ if (unlikely(atomic_read(&bp->intr_sem) != 0))
+ return IRQ_HANDLED;
+
+ napi_schedule(&bnapi->napi);
+ return IRQ_HANDLED;
+}
+
+static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
+{
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ u32 raw_cons = cpr->cp_raw_cons;
+ u32 cons;
+ int tx_pkts = 0;
+ int rx_pkts = 0;
+ bool rx_event = false;
+ bool agg_event = false;
+ struct tx_cmp *txcmp;
+
+ while (1) {
+ int rc;
+
+ cons = RING_CMP(raw_cons);
+ txcmp = &cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)];
+
+ if (!TX_CMP_VALID(txcmp, raw_cons))
+ break;
+
+ if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
+ tx_pkts++;
+ /* return full budget so NAPI will complete. */
+ if (unlikely(tx_pkts > bp->tx_wake_thresh))
+ rx_pkts = budget;
+ } else if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
+ rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &agg_event);
+ if (likely(rc >= 0))
+ rx_pkts += rc;
+ else if (rc == -EBUSY) /* partial completion */
+ break;
+ rx_event = true;
+ } else if (unlikely((TX_CMP_TYPE(txcmp) ==
+ CMPL_BASE_TYPE_HWRM_DONE) ||
+ (TX_CMP_TYPE(txcmp) ==
+ CMPL_BASE_TYPE_HWRM_FWD_REQ) ||
+ (TX_CMP_TYPE(txcmp) ==
+ CMPL_BASE_TYPE_HWRM_ASYNC_EVENT))) {
+ bnxt_hwrm_handler(bp, txcmp);
+ }
+ raw_cons = NEXT_RAW_CMP(raw_cons);
+
+ if (rx_pkts == budget)
+ break;
+ }
+
+ cpr->cp_raw_cons = raw_cons;
+ /* ACK completion ring before freeing tx ring and producing new
+ * buffers in rx/agg rings to prevent overflowing the completion
+ * ring.
+ */
+ BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons);
+
+ if (tx_pkts)
+ bnxt_tx_int(bp, bnapi, tx_pkts);
+
+ if (rx_event) {
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+
+ writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell);
+ writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell);
+ if (agg_event) {
+ writel(DB_KEY_RX | rxr->rx_agg_prod,
+ rxr->rx_agg_doorbell);
+ writel(DB_KEY_RX | rxr->rx_agg_prod,
+ rxr->rx_agg_doorbell);
+ }
+ }
+ return rx_pkts;
+}
+
+static int bnxt_poll(struct napi_struct *napi, int budget)
+{
+ struct bnxt_napi *bnapi = container_of(napi, struct bnxt_napi, napi);
+ struct bnxt *bp = bnapi->bp;
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ int work_done = 0;
+
+ if (!bnxt_lock_napi(bnapi))
+ return budget;
+
+ while (1) {
+ work_done += bnxt_poll_work(bp, bnapi, budget - work_done);
+
+ if (work_done >= budget)
+ break;
+
+ if (!bnxt_has_work(bp, cpr)) {
+ napi_complete(napi);
+ BNXT_CP_DB_REARM(cpr->cp_doorbell, cpr->cp_raw_cons);
+ break;
+ }
+ }
+ mmiowb();
+ bnxt_unlock_napi(bnapi);
+ return work_done;
+}
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static int bnxt_busy_poll(struct napi_struct *napi)
+{
+ struct bnxt_napi *bnapi = container_of(napi, struct bnxt_napi, napi);
+ struct bnxt *bp = bnapi->bp;
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ int rx_work, budget = 4;
+
+ if (atomic_read(&bp->intr_sem) != 0)
+ return LL_FLUSH_FAILED;
+
+ if (!bnxt_lock_poll(bnapi))
+ return LL_FLUSH_BUSY;
+
+ rx_work = bnxt_poll_work(bp, bnapi, budget);
+
+ BNXT_CP_DB_REARM(cpr->cp_doorbell, cpr->cp_raw_cons);
+
+ bnxt_unlock_poll(bnapi);
+ return rx_work;
+}
+#endif
+
+static void bnxt_free_tx_skbs(struct bnxt *bp)
+{
+ int i, max_idx;
+ struct pci_dev *pdev = bp->pdev;
+
+ if (!bp->bnapi)
+ return;
+
+ max_idx = bp->tx_nr_pages * TX_DESC_CNT;
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_tx_ring_info *txr;
+ int j;
+
+ if (!bnapi)
+ continue;
+
+ txr = &bnapi->tx_ring;
+ for (j = 0; j < max_idx;) {
+ struct bnxt_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
+ struct sk_buff *skb = tx_buf->skb;
+ int k, last;
+
+ if (!skb) {
+ j++;
+ continue;
+ }
+
+ tx_buf->skb = NULL;
+
+ if (tx_buf->is_push) {
+ dev_kfree_skb(skb);
+ j += 2;
+ continue;
+ }
+
+ dma_unmap_single(&pdev->dev,
+ dma_unmap_addr(tx_buf, mapping),
+ skb_headlen(skb),
+ PCI_DMA_TODEVICE);
+
+ last = tx_buf->nr_frags;
+ j += 2;
+ for (k = 0; k < last; k++, j = NEXT_TX(j)) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[k];
+
+ tx_buf = &txr->tx_buf_ring[j];
+ dma_unmap_page(
+ &pdev->dev,
+ dma_unmap_addr(tx_buf, mapping),
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
+ }
+ dev_kfree_skb(skb);
+ }
+ netdev_tx_reset_queue(netdev_get_tx_queue(bp->dev, i));
+ }
+}
+
+static void bnxt_free_rx_skbs(struct bnxt *bp)
+{
+ int i, max_idx, max_agg_idx;
+ struct pci_dev *pdev = bp->pdev;
+
+ if (!bp->bnapi)
+ return;
+
+ max_idx = bp->rx_nr_pages * RX_DESC_CNT;
+ max_agg_idx = bp->rx_agg_nr_pages * RX_DESC_CNT;
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr;
+ int j;
+
+ if (!bnapi)
+ continue;
+
+ rxr = &bnapi->rx_ring;
+
+ if (rxr->rx_tpa) {
+ for (j = 0; j < MAX_TPA; j++) {
+ struct bnxt_tpa_info *tpa_info =
+ &rxr->rx_tpa[j];
+ u8 *data = tpa_info->data;
+
+ if (!data)
+ continue;
+
+ dma_unmap_single(
+ &pdev->dev,
+ dma_unmap_addr(tpa_info, mapping),
+ bp->rx_buf_use_size,
+ PCI_DMA_FROMDEVICE);
+
+ tpa_info->data = NULL;
+
+ kfree(data);
+ }
+ }
+
+ for (j = 0; j < max_idx; j++) {
+ struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[j];
+ u8 *data = rx_buf->data;
+
+ if (!data)
+ continue;
+
+ dma_unmap_single(&pdev->dev,
+ dma_unmap_addr(rx_buf, mapping),
+ bp->rx_buf_use_size,
+ PCI_DMA_FROMDEVICE);
+
+ rx_buf->data = NULL;
+
+ kfree(data);
+ }
+
+ for (j = 0; j < max_agg_idx; j++) {
+ struct bnxt_sw_rx_agg_bd *rx_agg_buf =
+ &rxr->rx_agg_ring[j];
+ struct page *page = rx_agg_buf->page;
+
+ if (!page)
+ continue;
+
+ dma_unmap_page(&pdev->dev,
+ dma_unmap_addr(rx_agg_buf, mapping),
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+
+ rx_agg_buf->page = NULL;
+ __clear_bit(j, rxr->rx_agg_bmap);
+
+ __free_page(page);
+ }
+ }
+}
+
+static void bnxt_free_skbs(struct bnxt *bp)
+{
+ bnxt_free_tx_skbs(bp);
+ bnxt_free_rx_skbs(bp);
+}
+
+static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_struct *ring)
+{
+ struct pci_dev *pdev = bp->pdev;
+ int i;
+
+ for (i = 0; i < ring->nr_pages; i++) {
+ if (!ring->pg_arr[i])
+ continue;
+
+ dma_free_coherent(&pdev->dev, ring->page_size,
+ ring->pg_arr[i], ring->dma_arr[i]);
+
+ ring->pg_arr[i] = NULL;
+ }
+ if (ring->pg_tbl) {
+ dma_free_coherent(&pdev->dev, ring->nr_pages * 8,
+ ring->pg_tbl, ring->pg_tbl_map);
+ ring->pg_tbl = NULL;
+ }
+ if (ring->vmem_size && *ring->vmem) {
+ vfree(*ring->vmem);
+ *ring->vmem = NULL;
+ }
+}
+
+static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_struct *ring)
+{
+ int i;
+ struct pci_dev *pdev = bp->pdev;
+
+ if (ring->nr_pages > 1) {
+ ring->pg_tbl = dma_alloc_coherent(&pdev->dev,
+ ring->nr_pages * 8,
+ &ring->pg_tbl_map,
+ GFP_KERNEL);
+ if (!ring->pg_tbl)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ring->nr_pages; i++) {
+ ring->pg_arr[i] = dma_alloc_coherent(&pdev->dev,
+ ring->page_size,
+ &ring->dma_arr[i],
+ GFP_KERNEL);
+ if (!ring->pg_arr[i])
+ return -ENOMEM;
+
+ if (ring->nr_pages > 1)
+ ring->pg_tbl[i] = cpu_to_le64(ring->dma_arr[i]);
+ }
+
+ if (ring->vmem_size) {
+ *ring->vmem = vzalloc(ring->vmem_size);
+ if (!(*ring->vmem))
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void bnxt_free_rx_rings(struct bnxt *bp)
+{
+ int i;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ rxr = &bnapi->rx_ring;
+
+ kfree(rxr->rx_tpa);
+ rxr->rx_tpa = NULL;
+
+ kfree(rxr->rx_agg_bmap);
+ rxr->rx_agg_bmap = NULL;
+
+ ring = &rxr->rx_ring_struct;
+ bnxt_free_ring(bp, ring);
+
+ ring = &rxr->rx_agg_ring_struct;
+ bnxt_free_ring(bp, ring);
+ }
+}
+
+static int bnxt_alloc_rx_rings(struct bnxt *bp)
+{
+ int i, rc, agg_rings = 0, tpa_rings = 0;
+
+ if (bp->flags & BNXT_FLAG_AGG_RINGS)
+ agg_rings = 1;
+
+ if (bp->flags & BNXT_FLAG_TPA)
+ tpa_rings = 1;
+
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ rxr = &bnapi->rx_ring;
+ ring = &rxr->rx_ring_struct;
+
+ rc = bnxt_alloc_ring(bp, ring);
+ if (rc)
+ return rc;
+
+ if (agg_rings) {
+ u16 mem_size;
+
+ ring = &rxr->rx_agg_ring_struct;
+ rc = bnxt_alloc_ring(bp, ring);
+ if (rc)
+ return rc;
+
+ rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
+ mem_size = rxr->rx_agg_bmap_size / 8;
+ rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
+ if (!rxr->rx_agg_bmap)
+ return -ENOMEM;
+
+ if (tpa_rings) {
+ rxr->rx_tpa = kcalloc(MAX_TPA,
+ sizeof(struct bnxt_tpa_info),
+ GFP_KERNEL);
+ if (!rxr->rx_tpa)
+ return -ENOMEM;
+ }
+ }
+ }
+ return 0;
+}
+
+static void bnxt_free_tx_rings(struct bnxt *bp)
+{
+ int i;
+ struct pci_dev *pdev = bp->pdev;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_tx_ring_info *txr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ txr = &bnapi->tx_ring;
+
+ if (txr->tx_push) {
+ dma_free_coherent(&pdev->dev, bp->tx_push_size,
+ txr->tx_push, txr->tx_push_mapping);
+ txr->tx_push = NULL;
+ }
+
+ ring = &txr->tx_ring_struct;
+
+ bnxt_free_ring(bp, ring);
+ }
+}
+
+static int bnxt_alloc_tx_rings(struct bnxt *bp)
+{
+ int i, j, rc;
+ struct pci_dev *pdev = bp->pdev;
+
+ bp->tx_push_size = 0;
+ if (bp->tx_push_thresh) {
+ int push_size;
+
+ push_size = L1_CACHE_ALIGN(sizeof(struct tx_push_bd) +
+ bp->tx_push_thresh);
+
+ if (push_size > 128) {
+ push_size = 0;
+ bp->tx_push_thresh = 0;
+ }
+
+ bp->tx_push_size = push_size;
+ }
+
+ for (i = 0, j = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_tx_ring_info *txr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ txr = &bnapi->tx_ring;
+ ring = &txr->tx_ring_struct;
+
+ rc = bnxt_alloc_ring(bp, ring);
+ if (rc)
+ return rc;
+
+ if (bp->tx_push_size) {
+ struct tx_bd *txbd;
+ dma_addr_t mapping;
+
+ /* One pre-allocated DMA buffer to backup
+ * TX push operation
+ */
+ txr->tx_push = dma_alloc_coherent(&pdev->dev,
+ bp->tx_push_size,
+ &txr->tx_push_mapping,
+ GFP_KERNEL);
+
+ if (!txr->tx_push)
+ return -ENOMEM;
+
+ txbd = &txr->tx_push->txbd1;
+
+ mapping = txr->tx_push_mapping +
+ sizeof(struct tx_push_bd);
+ txbd->tx_bd_haddr = cpu_to_le64(mapping);
+
+ memset(txbd + 1, 0, sizeof(struct tx_bd_ext));
+ }
+ ring->queue_id = bp->q_info[j].queue_id;
+ if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
+ j++;
+ }
+ return 0;
+}
+
+static void bnxt_free_cp_rings(struct bnxt *bp)
+{
+ int i;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ cpr = &bnapi->cp_ring;
+ ring = &cpr->cp_ring_struct;
+
+ bnxt_free_ring(bp, ring);
+ }
+}
+
+static int bnxt_alloc_cp_rings(struct bnxt *bp)
+{
+ int i, rc;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ cpr = &bnapi->cp_ring;
+ ring = &cpr->cp_ring_struct;
+
+ rc = bnxt_alloc_ring(bp, ring);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+static void bnxt_init_ring_struct(struct bnxt *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr;
+ struct bnxt_rx_ring_info *rxr;
+ struct bnxt_tx_ring_info *txr;
+ struct bnxt_ring_struct *ring;
+
+ if (!bnapi)
+ continue;
+
+ cpr = &bnapi->cp_ring;
+ ring = &cpr->cp_ring_struct;
+ ring->nr_pages = bp->cp_nr_pages;
+ ring->page_size = HW_CMPD_RING_SIZE;
+ ring->pg_arr = (void **)cpr->cp_desc_ring;
+ ring->dma_arr = cpr->cp_desc_mapping;
+ ring->vmem_size = 0;
+
+ rxr = &bnapi->rx_ring;
+ ring = &rxr->rx_ring_struct;
+ ring->nr_pages = bp->rx_nr_pages;
+ ring->page_size = HW_RXBD_RING_SIZE;
+ ring->pg_arr = (void **)rxr->rx_desc_ring;
+ ring->dma_arr = rxr->rx_desc_mapping;
+ ring->vmem_size = SW_RXBD_RING_SIZE * bp->rx_nr_pages;
+ ring->vmem = (void **)&rxr->rx_buf_ring;
+
+ ring = &rxr->rx_agg_ring_struct;
+ ring->nr_pages = bp->rx_agg_nr_pages;
+ ring->page_size = HW_RXBD_RING_SIZE;
+ ring->pg_arr = (void **)rxr->rx_agg_desc_ring;
+ ring->dma_arr = rxr->rx_agg_desc_mapping;
+ ring->vmem_size = SW_RXBD_AGG_RING_SIZE * bp->rx_agg_nr_pages;
+ ring->vmem = (void **)&rxr->rx_agg_ring;
+
+ txr = &bnapi->tx_ring;
+ ring = &txr->tx_ring_struct;
+ ring->nr_pages = bp->tx_nr_pages;
+ ring->page_size = HW_RXBD_RING_SIZE;
+ ring->pg_arr = (void **)txr->tx_desc_ring;
+ ring->dma_arr = txr->tx_desc_mapping;
+ ring->vmem_size = SW_TXBD_RING_SIZE * bp->tx_nr_pages;
+ ring->vmem = (void **)&txr->tx_buf_ring;
+ }
+}
+
+static void bnxt_init_rxbd_pages(struct bnxt_ring_struct *ring, u32 type)
+{
+ int i;
+ u32 prod;
+ struct rx_bd **rx_buf_ring;
+
+ rx_buf_ring = (struct rx_bd **)ring->pg_arr;
+ for (i = 0, prod = 0; i < ring->nr_pages; i++) {
+ int j;
+ struct rx_bd *rxbd;
+
+ rxbd = rx_buf_ring[i];
+ if (!rxbd)
+ continue;
+
+ for (j = 0; j < RX_DESC_CNT; j++, rxbd++, prod++) {
+ rxbd->rx_bd_len_flags_type = cpu_to_le32(type);
+ rxbd->rx_bd_opaque = prod;
+ }
+ }
+}
+
+static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
+{
+ struct net_device *dev = bp->dev;
+ struct bnxt_napi *bnapi = bp->bnapi[ring_nr];
+ struct bnxt_rx_ring_info *rxr;
+ struct bnxt_ring_struct *ring;
+ u32 prod, type;
+ int i;
+
+ if (!bnapi)
+ return -EINVAL;
+
+ type = (bp->rx_buf_use_size << RX_BD_LEN_SHIFT) |
+ RX_BD_TYPE_RX_PACKET_BD | RX_BD_FLAGS_EOP;
+
+ if (NET_IP_ALIGN == 2)
+ type |= RX_BD_FLAGS_SOP;
+
+ rxr = &bnapi->rx_ring;
+ ring = &rxr->rx_ring_struct;
+ bnxt_init_rxbd_pages(ring, type);
+
+ prod = rxr->rx_prod;
+ for (i = 0; i < bp->rx_ring_size; i++) {
+ if (bnxt_alloc_rx_data(bp, rxr, prod, GFP_KERNEL) != 0) {
+ netdev_warn(dev, "init'ed rx ring %d with %d/%d skbs only\n",
+ ring_nr, i, bp->rx_ring_size);
+ break;
+ }
+ prod = NEXT_RX(prod);
+ }
+ rxr->rx_prod = prod;
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+
+ if (!(bp->flags & BNXT_FLAG_AGG_RINGS))
+ return 0;
+
+ ring = &rxr->rx_agg_ring_struct;
+
+ type = ((u32)PAGE_SIZE << RX_BD_LEN_SHIFT) |
+ RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
+
+ bnxt_init_rxbd_pages(ring, type);
+
+ prod = rxr->rx_agg_prod;
+ for (i = 0; i < bp->rx_agg_ring_size; i++) {
+ if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_KERNEL) != 0) {
+ netdev_warn(dev, "init'ed rx ring %d with %d/%d pages only\n",
+ ring_nr, i, bp->rx_ring_size);
+ break;
+ }
+ prod = NEXT_RX_AGG(prod);
+ }
+ rxr->rx_agg_prod = prod;
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+
+ if (bp->flags & BNXT_FLAG_TPA) {
+ if (rxr->rx_tpa) {
+ u8 *data;
+ dma_addr_t mapping;
+
+ for (i = 0; i < MAX_TPA; i++) {
+ data = __bnxt_alloc_rx_data(bp, &mapping,
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ rxr->rx_tpa[i].data = data;
+ rxr->rx_tpa[i].mapping = mapping;
+ }
+ } else {
+ netdev_err(bp->dev, "No resource allocated for LRO/GRO\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static int bnxt_init_rx_rings(struct bnxt *bp)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ rc = bnxt_init_one_rx_ring(bp, i);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
+static int bnxt_init_tx_rings(struct bnxt *bp)
+{
+ u16 i;
+
+ bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2,
+ MAX_SKB_FRAGS + 1);
+
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_tx_ring_info *txr = &bnapi->tx_ring;
+ struct bnxt_ring_struct *ring = &txr->tx_ring_struct;
+
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ }
+
+ return 0;
+}
+
+static void bnxt_free_ring_grps(struct bnxt *bp)
+{
+ kfree(bp->grp_info);
+ bp->grp_info = NULL;
+}
+
+static int bnxt_init_ring_grps(struct bnxt *bp, bool irq_re_init)
+{
+ int i;
+
+ if (irq_re_init) {
+ bp->grp_info = kcalloc(bp->cp_nr_rings,
+ sizeof(struct bnxt_ring_grp_info),
+ GFP_KERNEL);
+ if (!bp->grp_info)
+ return -ENOMEM;
+ }
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ if (irq_re_init)
+ bp->grp_info[i].fw_stats_ctx = INVALID_HW_RING_ID;
+ bp->grp_info[i].fw_grp_id = INVALID_HW_RING_ID;
+ bp->grp_info[i].rx_fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[i].agg_fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[i].cp_fw_ring_id = INVALID_HW_RING_ID;
+ }
+ return 0;
+}
+
+static void bnxt_free_vnics(struct bnxt *bp)
+{
+ kfree(bp->vnic_info);
+ bp->vnic_info = NULL;
+ bp->nr_vnics = 0;
+}
+
+static int bnxt_alloc_vnics(struct bnxt *bp)
+{
+ int num_vnics = 1;
+
+#ifdef CONFIG_RFS_ACCEL
+ if (bp->flags & BNXT_FLAG_RFS)
+ num_vnics += bp->rx_nr_rings;
+#endif
+
+ bp->vnic_info = kcalloc(num_vnics, sizeof(struct bnxt_vnic_info),
+ GFP_KERNEL);
+ if (!bp->vnic_info)
+ return -ENOMEM;
+
+ bp->nr_vnics = num_vnics;
+ return 0;
+}
+
+static void bnxt_init_vnics(struct bnxt *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->nr_vnics; i++) {
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
+
+ vnic->fw_vnic_id = INVALID_HW_RING_ID;
+ vnic->fw_rss_cos_lb_ctx = INVALID_HW_RING_ID;
+ vnic->fw_l2_ctx_id = INVALID_HW_RING_ID;
+
+ if (bp->vnic_info[i].rss_hash_key) {
+ if (i == 0)
+ prandom_bytes(vnic->rss_hash_key,
+ HW_HASH_KEY_SIZE);
+ else
+ memcpy(vnic->rss_hash_key,
+ bp->vnic_info[0].rss_hash_key,
+ HW_HASH_KEY_SIZE);
+ }
+ }
+}
+
+static int bnxt_calc_nr_ring_pages(u32 ring_size, int desc_per_pg)
+{
+ int pages;
+
+ pages = ring_size / desc_per_pg;
+
+ if (!pages)
+ return 1;
+
+ pages++;
+
+ while (pages & (pages - 1))
+ pages++;
+
+ return pages;
+}
+
+static void bnxt_set_tpa_flags(struct bnxt *bp)
+{
+ bp->flags &= ~BNXT_FLAG_TPA;
+ if (bp->dev->features & NETIF_F_LRO)
+ bp->flags |= BNXT_FLAG_LRO;
+ if ((bp->dev->features & NETIF_F_GRO) && (bp->pdev->revision > 0))
+ bp->flags |= BNXT_FLAG_GRO;
+}
+
+/* bp->rx_ring_size, bp->tx_ring_size, dev->mtu, BNXT_FLAG_{G|L}RO flags must
+ * be set on entry.
+ */
+void bnxt_set_ring_params(struct bnxt *bp)
+{
+ u32 ring_size, rx_size, rx_space;
+ u32 agg_factor = 0, agg_ring_size = 0;
+
+ /* 8 for CRC and VLAN */
+ rx_size = SKB_DATA_ALIGN(bp->dev->mtu + ETH_HLEN + NET_IP_ALIGN + 8);
+
+ rx_space = rx_size + NET_SKB_PAD +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ bp->rx_copy_thresh = BNXT_RX_COPY_THRESH;
+ ring_size = bp->rx_ring_size;
+ bp->rx_agg_ring_size = 0;
+ bp->rx_agg_nr_pages = 0;
+
+ if (bp->flags & BNXT_FLAG_TPA)
+ agg_factor = 4;
+
+ bp->flags &= ~BNXT_FLAG_JUMBO;
+ if (rx_space > PAGE_SIZE) {
+ u32 jumbo_factor;
+
+ bp->flags |= BNXT_FLAG_JUMBO;
+ jumbo_factor = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT;
+ if (jumbo_factor > agg_factor)
+ agg_factor = jumbo_factor;
+ }
+ agg_ring_size = ring_size * agg_factor;
+
+ if (agg_ring_size) {
+ bp->rx_agg_nr_pages = bnxt_calc_nr_ring_pages(agg_ring_size,
+ RX_DESC_CNT);
+ if (bp->rx_agg_nr_pages > MAX_RX_AGG_PAGES) {
+ u32 tmp = agg_ring_size;
+
+ bp->rx_agg_nr_pages = MAX_RX_AGG_PAGES;
+ agg_ring_size = MAX_RX_AGG_PAGES * RX_DESC_CNT - 1;
+ netdev_warn(bp->dev, "rx agg ring size %d reduced to %d.\n",
+ tmp, agg_ring_size);
+ }
+ bp->rx_agg_ring_size = agg_ring_size;
+ bp->rx_agg_ring_mask = (bp->rx_agg_nr_pages * RX_DESC_CNT) - 1;
+ rx_size = SKB_DATA_ALIGN(BNXT_RX_COPY_THRESH + NET_IP_ALIGN);
+ rx_space = rx_size + NET_SKB_PAD +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ }
+
+ bp->rx_buf_use_size = rx_size;
+ bp->rx_buf_size = rx_space;
+
+ bp->rx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, RX_DESC_CNT);
+ bp->rx_ring_mask = (bp->rx_nr_pages * RX_DESC_CNT) - 1;
+
+ ring_size = bp->tx_ring_size;
+ bp->tx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, TX_DESC_CNT);
+ bp->tx_ring_mask = (bp->tx_nr_pages * TX_DESC_CNT) - 1;
+
+ ring_size = bp->rx_ring_size * (2 + agg_factor) + bp->tx_ring_size;
+ bp->cp_ring_size = ring_size;
+
+ bp->cp_nr_pages = bnxt_calc_nr_ring_pages(ring_size, CP_DESC_CNT);
+ if (bp->cp_nr_pages > MAX_CP_PAGES) {
+ bp->cp_nr_pages = MAX_CP_PAGES;
+ bp->cp_ring_size = MAX_CP_PAGES * CP_DESC_CNT - 1;
+ netdev_warn(bp->dev, "completion ring size %d reduced to %d.\n",
+ ring_size, bp->cp_ring_size);
+ }
+ bp->cp_bit = bp->cp_nr_pages * CP_DESC_CNT;
+ bp->cp_ring_mask = bp->cp_bit - 1;
+}
+
+static void bnxt_free_vnic_attributes(struct bnxt *bp)
+{
+ int i;
+ struct bnxt_vnic_info *vnic;
+ struct pci_dev *pdev = bp->pdev;
+
+ if (!bp->vnic_info)
+ return;
+
+ for (i = 0; i < bp->nr_vnics; i++) {
+ vnic = &bp->vnic_info[i];
+
+ kfree(vnic->fw_grp_ids);
+ vnic->fw_grp_ids = NULL;
+
+ kfree(vnic->uc_list);
+ vnic->uc_list = NULL;
+
+ if (vnic->mc_list) {
+ dma_free_coherent(&pdev->dev, vnic->mc_list_size,
+ vnic->mc_list, vnic->mc_list_mapping);
+ vnic->mc_list = NULL;
+ }
+
+ if (vnic->rss_table) {
+ dma_free_coherent(&pdev->dev, PAGE_SIZE,
+ vnic->rss_table,
+ vnic->rss_table_dma_addr);
+ vnic->rss_table = NULL;
+ }
+
+ vnic->rss_hash_key = NULL;
+ vnic->flags = 0;
+ }
+}
+
+static int bnxt_alloc_vnic_attributes(struct bnxt *bp)
+{
+ int i, rc = 0, size;
+ struct bnxt_vnic_info *vnic;
+ struct pci_dev *pdev = bp->pdev;
+ int max_rings;
+
+ for (i = 0; i < bp->nr_vnics; i++) {
+ vnic = &bp->vnic_info[i];
+
+ if (vnic->flags & BNXT_VNIC_UCAST_FLAG) {
+ int mem_size = (BNXT_MAX_UC_ADDRS - 1) * ETH_ALEN;
+
+ if (mem_size > 0) {
+ vnic->uc_list = kmalloc(mem_size, GFP_KERNEL);
+ if (!vnic->uc_list) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ }
+ }
+
+ if (vnic->flags & BNXT_VNIC_MCAST_FLAG) {
+ vnic->mc_list_size = BNXT_MAX_MC_ADDRS * ETH_ALEN;
+ vnic->mc_list =
+ dma_alloc_coherent(&pdev->dev,
+ vnic->mc_list_size,
+ &vnic->mc_list_mapping,
+ GFP_KERNEL);
+ if (!vnic->mc_list) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (vnic->flags & BNXT_VNIC_RSS_FLAG)
+ max_rings = bp->rx_nr_rings;
+ else
+ max_rings = 1;
+
+ vnic->fw_grp_ids = kcalloc(max_rings, sizeof(u16), GFP_KERNEL);
+ if (!vnic->fw_grp_ids) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Allocate rss table and hash key */
+ vnic->rss_table = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+ &vnic->rss_table_dma_addr,
+ GFP_KERNEL);
+ if (!vnic->rss_table) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ size = L1_CACHE_ALIGN(HW_HASH_INDEX_SIZE * sizeof(u16));
+
+ vnic->rss_hash_key = ((void *)vnic->rss_table) + size;
+ vnic->rss_hash_key_dma_addr = vnic->rss_table_dma_addr + size;
+ }
+ return 0;
+
+out:
+ return rc;
+}
+
+static void bnxt_free_hwrm_resources(struct bnxt *bp)
+{
+ struct pci_dev *pdev = bp->pdev;
+
+ dma_free_coherent(&pdev->dev, PAGE_SIZE, bp->hwrm_cmd_resp_addr,
+ bp->hwrm_cmd_resp_dma_addr);
+
+ bp->hwrm_cmd_resp_addr = NULL;
+ if (bp->hwrm_dbg_resp_addr) {
+ dma_free_coherent(&pdev->dev, HWRM_DBG_REG_BUF_SIZE,
+ bp->hwrm_dbg_resp_addr,
+ bp->hwrm_dbg_resp_dma_addr);
+
+ bp->hwrm_dbg_resp_addr = NULL;
+ }
+}
+
+static int bnxt_alloc_hwrm_resources(struct bnxt *bp)
+{
+ struct pci_dev *pdev = bp->pdev;
+
+ bp->hwrm_cmd_resp_addr = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+ &bp->hwrm_cmd_resp_dma_addr,
+ GFP_KERNEL);
+ if (!bp->hwrm_cmd_resp_addr)
+ return -ENOMEM;
+ bp->hwrm_dbg_resp_addr = dma_alloc_coherent(&pdev->dev,
+ HWRM_DBG_REG_BUF_SIZE,
+ &bp->hwrm_dbg_resp_dma_addr,
+ GFP_KERNEL);
+ if (!bp->hwrm_dbg_resp_addr)
+ netdev_warn(bp->dev, "fail to alloc debug register dma mem\n");
+
+ return 0;
+}
+
+static void bnxt_free_stats(struct bnxt *bp)
+{
+ u32 size, i;
+ struct pci_dev *pdev = bp->pdev;
+
+ if (!bp->bnapi)
+ return;
+
+ size = sizeof(struct ctx_hw_stats);
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+
+ if (cpr->hw_stats) {
+ dma_free_coherent(&pdev->dev, size, cpr->hw_stats,
+ cpr->hw_stats_map);
+ cpr->hw_stats = NULL;
+ }
+ }
+}
+
+static int bnxt_alloc_stats(struct bnxt *bp)
+{
+ u32 size, i;
+ struct pci_dev *pdev = bp->pdev;
+
+ size = sizeof(struct ctx_hw_stats);
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+
+ cpr->hw_stats = dma_alloc_coherent(&pdev->dev, size,
+ &cpr->hw_stats_map,
+ GFP_KERNEL);
+ if (!cpr->hw_stats)
+ return -ENOMEM;
+
+ cpr->hw_stats_ctx_id = INVALID_STATS_CTX_ID;
+ }
+ return 0;
+}
+
+static void bnxt_clear_ring_indices(struct bnxt *bp)
+{
+ int i;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr;
+ struct bnxt_rx_ring_info *rxr;
+ struct bnxt_tx_ring_info *txr;
+
+ if (!bnapi)
+ continue;
+
+ cpr = &bnapi->cp_ring;
+ cpr->cp_raw_cons = 0;
+
+ txr = &bnapi->tx_ring;
+ txr->tx_prod = 0;
+ txr->tx_cons = 0;
+
+ rxr = &bnapi->rx_ring;
+ rxr->rx_prod = 0;
+ rxr->rx_agg_prod = 0;
+ rxr->rx_sw_agg_prod = 0;
+ }
+}
+
+static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool irq_reinit)
+{
+#ifdef CONFIG_RFS_ACCEL
+ int i;
+
+ /* Under rtnl_lock and all our NAPIs have been disabled. It's
+ * safe to delete the hash table.
+ */
+ for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
+ struct hlist_head *head;
+ struct hlist_node *tmp;
+ struct bnxt_ntuple_filter *fltr;
+
+ head = &bp->ntp_fltr_hash_tbl[i];
+ hlist_for_each_entry_safe(fltr, tmp, head, hash) {
+ hlist_del(&fltr->hash);
+ kfree(fltr);
+ }
+ }
+ if (irq_reinit) {
+ kfree(bp->ntp_fltr_bmap);
+ bp->ntp_fltr_bmap = NULL;
+ }
+ bp->ntp_fltr_count = 0;
+#endif
+}
+
+static int bnxt_alloc_ntp_fltrs(struct bnxt *bp)
+{
+#ifdef CONFIG_RFS_ACCEL
+ int i, rc = 0;
+
+ if (!(bp->flags & BNXT_FLAG_RFS))
+ return 0;
+
+ for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++)
+ INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]);
+
+ bp->ntp_fltr_count = 0;
+ bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+ GFP_KERNEL);
+
+ if (!bp->ntp_fltr_bmap)
+ rc = -ENOMEM;
+
+ return rc;
+#else
+ return 0;
+#endif
+}
+
+static void bnxt_free_mem(struct bnxt *bp, bool irq_re_init)
+{
+ bnxt_free_vnic_attributes(bp);
+ bnxt_free_tx_rings(bp);
+ bnxt_free_rx_rings(bp);
+ bnxt_free_cp_rings(bp);
+ bnxt_free_ntp_fltrs(bp, irq_re_init);
+ if (irq_re_init) {
+ bnxt_free_stats(bp);
+ bnxt_free_ring_grps(bp);
+ bnxt_free_vnics(bp);
+ kfree(bp->bnapi);
+ bp->bnapi = NULL;
+ } else {
+ bnxt_clear_ring_indices(bp);
+ }
+}
+
+static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
+{
+ int i, rc, size, arr_size;
+ void *bnapi;
+
+ if (irq_re_init) {
+ /* Allocate bnapi mem pointer array and mem block for
+ * all queues
+ */
+ arr_size = L1_CACHE_ALIGN(sizeof(struct bnxt_napi *) *
+ bp->cp_nr_rings);
+ size = L1_CACHE_ALIGN(sizeof(struct bnxt_napi));
+ bnapi = kzalloc(arr_size + size * bp->cp_nr_rings, GFP_KERNEL);
+ if (!bnapi)
+ return -ENOMEM;
+
+ bp->bnapi = bnapi;
+ bnapi += arr_size;
+ for (i = 0; i < bp->cp_nr_rings; i++, bnapi += size) {
+ bp->bnapi[i] = bnapi;
+ bp->bnapi[i]->index = i;
+ bp->bnapi[i]->bp = bp;
+ }
+
+ rc = bnxt_alloc_stats(bp);
+ if (rc)
+ goto alloc_mem_err;
+
+ rc = bnxt_alloc_ntp_fltrs(bp);
+ if (rc)
+ goto alloc_mem_err;
+
+ rc = bnxt_alloc_vnics(bp);
+ if (rc)
+ goto alloc_mem_err;
+ }
+
+ bnxt_init_ring_struct(bp);
+
+ rc = bnxt_alloc_rx_rings(bp);
+ if (rc)
+ goto alloc_mem_err;
+
+ rc = bnxt_alloc_tx_rings(bp);
+ if (rc)
+ goto alloc_mem_err;
+
+ rc = bnxt_alloc_cp_rings(bp);
+ if (rc)
+ goto alloc_mem_err;
+
+ bp->vnic_info[0].flags |= BNXT_VNIC_RSS_FLAG | BNXT_VNIC_MCAST_FLAG |
+ BNXT_VNIC_UCAST_FLAG;
+ rc = bnxt_alloc_vnic_attributes(bp);
+ if (rc)
+ goto alloc_mem_err;
+ return 0;
+
+alloc_mem_err:
+ bnxt_free_mem(bp, true);
+ return rc;
+}
+
+void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type,
+ u16 cmpl_ring, u16 target_id)
+{
+ struct hwrm_cmd_req_hdr *req = request;
+
+ req->cmpl_ring_req_type =
+ cpu_to_le32(req_type | (cmpl_ring << HWRM_CMPL_RING_SFT));
+ req->target_id_seq_id = cpu_to_le32(target_id << HWRM_TARGET_FID_SFT);
+ req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
+}
+
+int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout)
+{
+ int i, intr_process, rc;
+ struct hwrm_cmd_req_hdr *req = msg;
+ u32 *data = msg;
+ __le32 *resp_len, *valid;
+ u16 cp_ring_id, len = 0;
+ struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr;
+
+ req->target_id_seq_id |= cpu_to_le32(bp->hwrm_cmd_seq++);
+ memset(resp, 0, PAGE_SIZE);
+ cp_ring_id = (le32_to_cpu(req->cmpl_ring_req_type) &
+ HWRM_CMPL_RING_MASK) >>
+ HWRM_CMPL_RING_SFT;
+ intr_process = (cp_ring_id == INVALID_HW_RING_ID) ? 0 : 1;
+
+ /* Write request msg to hwrm channel */
+ __iowrite32_copy(bp->bar0, data, msg_len / 4);
+
+ /* currently supports only one outstanding message */
+ if (intr_process)
+ bp->hwrm_intr_seq_id = le32_to_cpu(req->target_id_seq_id) &
+ HWRM_SEQ_ID_MASK;
+
+ /* Ring channel doorbell */
+ writel(1, bp->bar0 + 0x100);
+
+ i = 0;
+ if (intr_process) {
+ /* Wait until hwrm response cmpl interrupt is processed */
+ while (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID &&
+ i++ < timeout) {
+ usleep_range(600, 800);
+ }
+
+ if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) {
+ netdev_err(bp->dev, "Resp cmpl intr err msg: 0x%x\n",
+ req->cmpl_ring_req_type);
+ return -1;
+ }
+ } else {
+ /* Check if response len is updated */
+ resp_len = bp->hwrm_cmd_resp_addr + HWRM_RESP_LEN_OFFSET;
+ for (i = 0; i < timeout; i++) {
+ len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >>
+ HWRM_RESP_LEN_SFT;
+ if (len)
+ break;
+ usleep_range(600, 800);
+ }
+
+ if (i >= timeout) {
+ netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n",
+ timeout, req->cmpl_ring_req_type,
+ req->target_id_seq_id, *resp_len);
+ return -1;
+ }
+
+ /* Last word of resp contains valid bit */
+ valid = bp->hwrm_cmd_resp_addr + len - 4;
+ for (i = 0; i < timeout; i++) {
+ if (le32_to_cpu(*valid) & HWRM_RESP_VALID_MASK)
+ break;
+ usleep_range(600, 800);
+ }
+
+ if (i >= timeout) {
+ netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n",
+ timeout, req->cmpl_ring_req_type,
+ req->target_id_seq_id, len, *valid);
+ return -1;
+ }
+ }
+
+ rc = le16_to_cpu(resp->error_code);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n",
+ le16_to_cpu(resp->req_type),
+ le16_to_cpu(resp->seq_id), rc);
+ return rc;
+ }
+ return 0;
+}
+
+int hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout)
+{
+ int rc;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, msg, msg_len, timeout);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
+{
+ struct hwrm_func_drv_rgtr_input req = {0};
+ int i;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR, -1, -1);
+
+ req.enables =
+ cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
+ FUNC_DRV_RGTR_REQ_ENABLES_VER |
+ FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
+
+ /* TODO: current async event fwd bits are not defined and the firmware
+ * only checks if it is non-zero to enable async event forwarding
+ */
+ req.async_event_fwd[0] |= cpu_to_le32(1);
+ req.os_type = cpu_to_le16(1);
+ req.ver_maj = DRV_VER_MAJ;
+ req.ver_min = DRV_VER_MIN;
+ req.ver_upd = DRV_VER_UPD;
+
+ if (BNXT_PF(bp)) {
+ unsigned long vf_req_snif_bmap[4];
+ u32 *data = (u32 *)vf_req_snif_bmap;
+
+ memset(vf_req_snif_bmap, 0, 32);
+ for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++)
+ __set_bit(bnxt_vf_req_snif[i], vf_req_snif_bmap);
+
+ for (i = 0; i < 8; i++) {
+ req.vf_req_fwd[i] = cpu_to_le32(*data);
+ data++;
+ }
+ req.enables |=
+ cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD);
+ }
+
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_hwrm_tunnel_dst_port_free(struct bnxt *bp, u8 tunnel_type)
+{
+ u32 rc = 0;
+ struct hwrm_tunnel_dst_port_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TUNNEL_DST_PORT_FREE, -1, -1);
+ req.tunnel_type = tunnel_type;
+
+ switch (tunnel_type) {
+ case TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN:
+ req.tunnel_dst_port_id = bp->vxlan_fw_dst_port_id;
+ break;
+ case TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE:
+ req.tunnel_dst_port_id = bp->nge_fw_dst_port_id;
+ break;
+ default:
+ break;
+ }
+
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ netdev_err(bp->dev, "hwrm_tunnel_dst_port_free failed. rc:%d\n",
+ rc);
+ return rc;
+}
+
+static int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, __be16 port,
+ u8 tunnel_type)
+{
+ u32 rc = 0;
+ struct hwrm_tunnel_dst_port_alloc_input req = {0};
+ struct hwrm_tunnel_dst_port_alloc_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TUNNEL_DST_PORT_ALLOC, -1, -1);
+
+ req.tunnel_type = tunnel_type;
+ req.tunnel_dst_port_val = port;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm_tunnel_dst_port_alloc failed. rc:%d\n",
+ rc);
+ goto err_out;
+ }
+
+ if (tunnel_type & TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_VXLAN)
+ bp->vxlan_fw_dst_port_id = resp->tunnel_dst_port_id;
+
+ else if (tunnel_type & TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_GENEVE)
+ bp->nge_fw_dst_port_id = resp->tunnel_dst_port_id;
+err_out:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id)
+{
+ struct hwrm_cfa_l2_set_rx_mask_input req = {0};
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_L2_SET_RX_MASK, -1, -1);
+ req.dflt_vnic_id = cpu_to_le32(vnic->fw_vnic_id);
+
+ req.num_mc_entries = cpu_to_le32(vnic->mc_list_count);
+ req.mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping);
+ req.mask = cpu_to_le32(vnic->rx_mask);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+#ifdef CONFIG_RFS_ACCEL
+static int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
+ struct bnxt_ntuple_filter *fltr)
+{
+ struct hwrm_cfa_ntuple_filter_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_NTUPLE_FILTER_FREE, -1, -1);
+ req.ntuple_filter_id = fltr->filter_id;
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+#define BNXT_NTP_FLTR_FLAGS \
+ (CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_MACADDR | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IPADDR_TYPE | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR_MASK | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR_MASK | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IP_PROTOCOL | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT_MASK | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT_MASK | \
+ CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID)
+
+static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
+ struct bnxt_ntuple_filter *fltr)
+{
+ int rc = 0;
+ struct hwrm_cfa_ntuple_filter_alloc_input req = {0};
+ struct hwrm_cfa_ntuple_filter_alloc_output *resp =
+ bp->hwrm_cmd_resp_addr;
+ struct flow_keys *keys = &fltr->fkeys;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[fltr->rxq + 1];
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_NTUPLE_FILTER_ALLOC, -1, -1);
+ req.l2_filter_id = bp->vnic_info[0].fw_l2_filter_id[0];
+
+ req.enables = cpu_to_le32(BNXT_NTP_FLTR_FLAGS);
+
+ req.ethertype = htons(ETH_P_IP);
+ memcpy(req.src_macaddr, fltr->src_mac_addr, ETH_ALEN);
+ req.ipaddr_type = 4;
+ req.ip_protocol = keys->basic.ip_proto;
+
+ req.src_ipaddr[0] = keys->addrs.v4addrs.src;
+ req.src_ipaddr_mask[0] = cpu_to_be32(0xffffffff);
+ req.dst_ipaddr[0] = keys->addrs.v4addrs.dst;
+ req.dst_ipaddr_mask[0] = cpu_to_be32(0xffffffff);
+
+ req.src_port = keys->ports.src;
+ req.src_port_mask = cpu_to_be16(0xffff);
+ req.dst_port = keys->ports.dst;
+ req.dst_port_mask = cpu_to_be16(0xffff);
+
+ req.dst_vnic_id = cpu_to_le16(vnic->fw_vnic_id);
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc)
+ fltr->filter_id = resp->ntuple_filter_id;
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+#endif
+
+static int bnxt_hwrm_set_vnic_filter(struct bnxt *bp, u16 vnic_id, u16 idx,
+ u8 *mac_addr)
+{
+ u32 rc = 0;
+ struct hwrm_cfa_l2_filter_alloc_input req = {0};
+ struct hwrm_cfa_l2_filter_alloc_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_L2_FILTER_ALLOC, -1, -1);
+ req.flags = cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX |
+ CFA_L2_FILTER_ALLOC_REQ_FLAGS_OUTERMOST);
+ req.dst_vnic_id = cpu_to_le16(bp->vnic_info[vnic_id].fw_vnic_id);
+ req.enables =
+ cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR |
+ CFA_L2_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID |
+ CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR_MASK);
+ memcpy(req.l2_addr, mac_addr, ETH_ALEN);
+ req.l2_addr_mask[0] = 0xff;
+ req.l2_addr_mask[1] = 0xff;
+ req.l2_addr_mask[2] = 0xff;
+ req.l2_addr_mask[3] = 0xff;
+ req.l2_addr_mask[4] = 0xff;
+ req.l2_addr_mask[5] = 0xff;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc)
+ bp->vnic_info[vnic_id].fw_l2_filter_id[idx] =
+ resp->l2_filter_id;
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_clear_vnic_filter(struct bnxt *bp)
+{
+ u16 i, j, num_of_vnics = 1; /* only vnic 0 supported */
+ int rc = 0;
+
+ /* Any associated ntuple filters will also be cleared by firmware. */
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < num_of_vnics; i++) {
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
+
+ for (j = 0; j < vnic->uc_filter_count; j++) {
+ struct hwrm_cfa_l2_filter_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req,
+ HWRM_CFA_L2_FILTER_FREE, -1, -1);
+
+ req.l2_filter_id = vnic->fw_l2_filter_id[j];
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ }
+ vnic->uc_filter_count = 0;
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+
+ return rc;
+}
+
+static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags)
+{
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+ struct hwrm_vnic_tpa_cfg_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_TPA_CFG, -1, -1);
+
+ if (tpa_flags) {
+ u16 mss = bp->dev->mtu - 40;
+ u32 nsegs, n, segs = 0, flags;
+
+ flags = VNIC_TPA_CFG_REQ_FLAGS_TPA |
+ VNIC_TPA_CFG_REQ_FLAGS_ENCAP_TPA |
+ VNIC_TPA_CFG_REQ_FLAGS_RSC_WND_UPDATE |
+ VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_ECN |
+ VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_SAME_GRE_SEQ;
+ if (tpa_flags & BNXT_FLAG_GRO)
+ flags |= VNIC_TPA_CFG_REQ_FLAGS_GRO;
+
+ req.flags = cpu_to_le32(flags);
+
+ req.enables =
+ cpu_to_le32(VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_SEGS |
+ VNIC_TPA_CFG_REQ_ENABLES_MAX_AGGS);
+
+ /* Number of segs are log2 units, and first packet is not
+ * included as part of this units.
+ */
+ if (mss <= PAGE_SIZE) {
+ n = PAGE_SIZE / mss;
+ nsegs = (MAX_SKB_FRAGS - 1) * n;
+ } else {
+ n = mss / PAGE_SIZE;
+ if (mss & (PAGE_SIZE - 1))
+ n++;
+ nsegs = (MAX_SKB_FRAGS - n) / n;
+ }
+
+ segs = ilog2(nsegs);
+ req.max_agg_segs = cpu_to_le16(segs);
+ req.max_aggs = cpu_to_le16(VNIC_TPA_CFG_REQ_MAX_AGGS_MAX);
+ }
+ req.vnic_id = cpu_to_le16(vnic->fw_vnic_id);
+
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss)
+{
+ u32 i, j, max_rings;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+ struct hwrm_vnic_rss_cfg_input req = {0};
+
+ if (vnic->fw_rss_cos_lb_ctx == INVALID_HW_RING_ID)
+ return 0;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_CFG, -1, -1);
+ if (set_rss) {
+ vnic->hash_type = BNXT_RSS_HASH_TYPE_FLAG_IPV4 |
+ BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV4 |
+ BNXT_RSS_HASH_TYPE_FLAG_IPV6 |
+ BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV6;
+
+ req.hash_type = cpu_to_le32(vnic->hash_type);
+
+ if (vnic->flags & BNXT_VNIC_RSS_FLAG)
+ max_rings = bp->rx_nr_rings;
+ else
+ max_rings = 1;
+
+ /* Fill the RSS indirection table with ring group ids */
+ for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++, j++) {
+ if (j == max_rings)
+ j = 0;
+ vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]);
+ }
+
+ req.ring_grp_tbl_addr = cpu_to_le64(vnic->rss_table_dma_addr);
+ req.hash_key_tbl_addr =
+ cpu_to_le64(vnic->rss_hash_key_dma_addr);
+ }
+ req.rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id)
+{
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+ struct hwrm_vnic_plcmodes_cfg_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_PLCMODES_CFG, -1, -1);
+ req.flags = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT |
+ VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 |
+ VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6);
+ req.enables =
+ cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID |
+ VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID);
+ /* thresholds not implemented in firmware yet */
+ req.jumbo_thresh = cpu_to_le16(bp->rx_copy_thresh);
+ req.hds_threshold = cpu_to_le16(bp->rx_copy_thresh);
+ req.vnic_id = cpu_to_le32(vnic->fw_vnic_id);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static void bnxt_hwrm_vnic_ctx_free_one(struct bnxt *bp, u16 vnic_id)
+{
+ struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE, -1, -1);
+ req.rss_cos_lb_ctx_id =
+ cpu_to_le16(bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx);
+
+ hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx = INVALID_HW_RING_ID;
+}
+
+static void bnxt_hwrm_vnic_ctx_free(struct bnxt *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->nr_vnics; i++) {
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
+
+ if (vnic->fw_rss_cos_lb_ctx != INVALID_HW_RING_ID)
+ bnxt_hwrm_vnic_ctx_free_one(bp, i);
+ }
+ bp->rsscos_nr_ctxs = 0;
+}
+
+static int bnxt_hwrm_vnic_ctx_alloc(struct bnxt *bp, u16 vnic_id)
+{
+ int rc;
+ struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
+ struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
+ bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC, -1,
+ -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc)
+ bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx =
+ le16_to_cpu(resp->rss_cos_lb_ctx_id);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+
+ return rc;
+}
+
+static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
+{
+ int grp_idx = 0;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+ struct hwrm_vnic_cfg_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_CFG, -1, -1);
+ /* Only RSS support for now TBD: COS & LB */
+ req.enables = cpu_to_le32(VNIC_CFG_REQ_ENABLES_DFLT_RING_GRP |
+ VNIC_CFG_REQ_ENABLES_RSS_RULE);
+ req.rss_rule = cpu_to_le16(vnic->fw_rss_cos_lb_ctx);
+ req.cos_rule = cpu_to_le16(0xffff);
+ if (vnic->flags & BNXT_VNIC_RSS_FLAG)
+ grp_idx = 0;
+ else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
+ grp_idx = vnic_id - 1;
+
+ req.vnic_id = cpu_to_le16(vnic->fw_vnic_id);
+ req.dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id);
+
+ req.lb_rule = cpu_to_le16(0xffff);
+ req.mru = cpu_to_le16(bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN +
+ VLAN_HLEN);
+
+ if (bp->flags & BNXT_FLAG_STRIP_VLAN)
+ req.flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
+
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_hwrm_vnic_free_one(struct bnxt *bp, u16 vnic_id)
+{
+ u32 rc = 0;
+
+ if (bp->vnic_info[vnic_id].fw_vnic_id != INVALID_HW_RING_ID) {
+ struct hwrm_vnic_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_FREE, -1, -1);
+ req.vnic_id =
+ cpu_to_le32(bp->vnic_info[vnic_id].fw_vnic_id);
+
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ return rc;
+ bp->vnic_info[vnic_id].fw_vnic_id = INVALID_HW_RING_ID;
+ }
+ return rc;
+}
+
+static void bnxt_hwrm_vnic_free(struct bnxt *bp)
+{
+ u16 i;
+
+ for (i = 0; i < bp->nr_vnics; i++)
+ bnxt_hwrm_vnic_free_one(bp, i);
+}
+
+static int bnxt_hwrm_vnic_alloc(struct bnxt *bp, u16 vnic_id, u16 start_grp_id,
+ u16 end_grp_id)
+{
+ u32 rc = 0, i, j;
+ struct hwrm_vnic_alloc_input req = {0};
+ struct hwrm_vnic_alloc_output *resp = bp->hwrm_cmd_resp_addr;
+
+ /* map ring groups to this vnic */
+ for (i = start_grp_id, j = 0; i < end_grp_id; i++, j++) {
+ if (bp->grp_info[i].fw_grp_id == INVALID_HW_RING_ID) {
+ netdev_err(bp->dev, "Not enough ring groups avail:%x req:%x\n",
+ j, (end_grp_id - start_grp_id));
+ break;
+ }
+ bp->vnic_info[vnic_id].fw_grp_ids[j] =
+ bp->grp_info[i].fw_grp_id;
+ }
+
+ bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx = INVALID_HW_RING_ID;
+ if (vnic_id == 0)
+ req.flags = cpu_to_le32(VNIC_ALLOC_REQ_FLAGS_DEFAULT);
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_ALLOC, -1, -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc)
+ bp->vnic_info[vnic_id].fw_vnic_id = le32_to_cpu(resp->vnic_id);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_ring_grp_alloc(struct bnxt *bp)
+{
+ u16 i;
+ u32 rc = 0;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct hwrm_ring_grp_alloc_input req = {0};
+ struct hwrm_ring_grp_alloc_output *resp =
+ bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_GRP_ALLOC, -1, -1);
+
+ req.cr = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id);
+ req.rr = cpu_to_le16(bp->grp_info[i].rx_fw_ring_id);
+ req.ar = cpu_to_le16(bp->grp_info[i].agg_fw_ring_id);
+ req.sc = cpu_to_le16(bp->grp_info[i].fw_stats_ctx);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+
+ bp->grp_info[i].fw_grp_id = le32_to_cpu(resp->ring_group_id);
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_ring_grp_free(struct bnxt *bp)
+{
+ u16 i;
+ u32 rc = 0;
+ struct hwrm_ring_grp_free_input req = {0};
+
+ if (!bp->grp_info)
+ return 0;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_GRP_FREE, -1, -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ if (bp->grp_info[i].fw_grp_id == INVALID_HW_RING_ID)
+ continue;
+ req.ring_group_id =
+ cpu_to_le32(bp->grp_info[i].fw_grp_id);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+ bp->grp_info[i].fw_grp_id = INVALID_HW_RING_ID;
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int hwrm_ring_alloc_send_msg(struct bnxt *bp,
+ struct bnxt_ring_struct *ring,
+ u32 ring_type, u32 map_index,
+ u32 stats_ctx_id)
+{
+ int rc = 0, err = 0;
+ struct hwrm_ring_alloc_input req = {0};
+ struct hwrm_ring_alloc_output *resp = bp->hwrm_cmd_resp_addr;
+ u16 ring_id;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_ALLOC, -1, -1);
+
+ req.enables = 0;
+ if (ring->nr_pages > 1) {
+ req.page_tbl_addr = cpu_to_le64(ring->pg_tbl_map);
+ /* Page size is in log2 units */
+ req.page_size = BNXT_PAGE_SHIFT;
+ req.page_tbl_depth = 1;
+ } else {
+ req.page_tbl_addr = cpu_to_le64(ring->dma_arr[0]);
+ }
+ req.fbo = 0;
+ /* Association of ring index with doorbell index and MSIX number */
+ req.logical_id = cpu_to_le16(map_index);
+
+ switch (ring_type) {
+ case HWRM_RING_ALLOC_TX:
+ req.ring_type = RING_ALLOC_REQ_RING_TYPE_TX;
+ /* Association of transmit ring with completion ring */
+ req.cmpl_ring_id =
+ cpu_to_le16(bp->grp_info[map_index].cp_fw_ring_id);
+ req.length = cpu_to_le32(bp->tx_ring_mask + 1);
+ req.stat_ctx_id = cpu_to_le32(stats_ctx_id);
+ req.queue_id = cpu_to_le16(ring->queue_id);
+ break;
+ case HWRM_RING_ALLOC_RX:
+ req.ring_type = RING_ALLOC_REQ_RING_TYPE_RX;
+ req.length = cpu_to_le32(bp->rx_ring_mask + 1);
+ break;
+ case HWRM_RING_ALLOC_AGG:
+ req.ring_type = RING_ALLOC_REQ_RING_TYPE_RX;
+ req.length = cpu_to_le32(bp->rx_agg_ring_mask + 1);
+ break;
+ case HWRM_RING_ALLOC_CMPL:
+ req.ring_type = RING_ALLOC_REQ_RING_TYPE_CMPL;
+ req.length = cpu_to_le32(bp->cp_ring_mask + 1);
+ if (bp->flags & BNXT_FLAG_USING_MSIX)
+ req.int_mode = RING_ALLOC_REQ_INT_MODE_MSIX;
+ break;
+ default:
+ netdev_err(bp->dev, "hwrm alloc invalid ring type %d\n",
+ ring_type);
+ return -1;
+ }
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ err = le16_to_cpu(resp->error_code);
+ ring_id = le16_to_cpu(resp->ring_id);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+
+ if (rc || err) {
+ switch (ring_type) {
+ case RING_FREE_REQ_RING_TYPE_CMPL:
+ netdev_err(bp->dev, "hwrm_ring_alloc cp failed. rc:%x err:%x\n",
+ rc, err);
+ return -1;
+
+ case RING_FREE_REQ_RING_TYPE_RX:
+ netdev_err(bp->dev, "hwrm_ring_alloc rx failed. rc:%x err:%x\n",
+ rc, err);
+ return -1;
+
+ case RING_FREE_REQ_RING_TYPE_TX:
+ netdev_err(bp->dev, "hwrm_ring_alloc tx failed. rc:%x err:%x\n",
+ rc, err);
+ return -1;
+
+ default:
+ netdev_err(bp->dev, "Invalid ring\n");
+ return -1;
+ }
+ }
+ ring->fw_ring_id = ring_id;
+ return rc;
+}
+
+static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
+{
+ int i, rc = 0;
+
+ if (bp->cp_nr_rings) {
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
+
+ rc = hwrm_ring_alloc_send_msg(bp, ring,
+ HWRM_RING_ALLOC_CMPL, i,
+ INVALID_STATS_CTX_ID);
+ if (rc)
+ goto err_out;
+ cpr->cp_doorbell = bp->bar1 + i * 0x80;
+ BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons);
+ bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id;
+ }
+ }
+
+ if (bp->tx_nr_rings) {
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_tx_ring_info *txr = &bnapi->tx_ring;
+ struct bnxt_ring_struct *ring = &txr->tx_ring_struct;
+ u16 fw_stats_ctx = bp->grp_info[i].fw_stats_ctx;
+
+ rc = hwrm_ring_alloc_send_msg(bp, ring,
+ HWRM_RING_ALLOC_TX, i,
+ fw_stats_ctx);
+ if (rc)
+ goto err_out;
+ txr->tx_doorbell = bp->bar1 + i * 0x80;
+ }
+ }
+
+ if (bp->rx_nr_rings) {
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ struct bnxt_ring_struct *ring = &rxr->rx_ring_struct;
+
+ rc = hwrm_ring_alloc_send_msg(bp, ring,
+ HWRM_RING_ALLOC_RX, i,
+ INVALID_STATS_CTX_ID);
+ if (rc)
+ goto err_out;
+ rxr->rx_doorbell = bp->bar1 + i * 0x80;
+ writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell);
+ bp->grp_info[i].rx_fw_ring_id = ring->fw_ring_id;
+ }
+ }
+
+ if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ struct bnxt_ring_struct *ring =
+ &rxr->rx_agg_ring_struct;
+
+ rc = hwrm_ring_alloc_send_msg(bp, ring,
+ HWRM_RING_ALLOC_AGG,
+ bp->rx_nr_rings + i,
+ INVALID_STATS_CTX_ID);
+ if (rc)
+ goto err_out;
+
+ rxr->rx_agg_doorbell =
+ bp->bar1 + (bp->rx_nr_rings + i) * 0x80;
+ writel(DB_KEY_RX | rxr->rx_agg_prod,
+ rxr->rx_agg_doorbell);
+ bp->grp_info[i].agg_fw_ring_id = ring->fw_ring_id;
+ }
+ }
+err_out:
+ return rc;
+}
+
+static int hwrm_ring_free_send_msg(struct bnxt *bp,
+ struct bnxt_ring_struct *ring,
+ u32 ring_type, int cmpl_ring_id)
+{
+ int rc;
+ struct hwrm_ring_free_input req = {0};
+ struct hwrm_ring_free_output *resp = bp->hwrm_cmd_resp_addr;
+ u16 error_code;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, -1, -1);
+ req.ring_type = ring_type;
+ req.ring_id = cpu_to_le16(ring->fw_ring_id);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ error_code = le16_to_cpu(resp->error_code);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+
+ if (rc || error_code) {
+ switch (ring_type) {
+ case RING_FREE_REQ_RING_TYPE_CMPL:
+ netdev_err(bp->dev, "hwrm_ring_free cp failed. rc:%d\n",
+ rc);
+ return rc;
+ case RING_FREE_REQ_RING_TYPE_RX:
+ netdev_err(bp->dev, "hwrm_ring_free rx failed. rc:%d\n",
+ rc);
+ return rc;
+ case RING_FREE_REQ_RING_TYPE_TX:
+ netdev_err(bp->dev, "hwrm_ring_free tx failed. rc:%d\n",
+ rc);
+ return rc;
+ default:
+ netdev_err(bp->dev, "Invalid ring\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path)
+{
+ int i, rc = 0;
+
+ if (!bp->bnapi)
+ return 0;
+
+ if (bp->tx_nr_rings) {
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_tx_ring_info *txr = &bnapi->tx_ring;
+ struct bnxt_ring_struct *ring = &txr->tx_ring_struct;
+ u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id;
+
+ if (ring->fw_ring_id != INVALID_HW_RING_ID) {
+ hwrm_ring_free_send_msg(
+ bp, ring,
+ RING_FREE_REQ_RING_TYPE_TX,
+ close_path ? cmpl_ring_id :
+ INVALID_HW_RING_ID);
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ }
+ }
+ }
+
+ if (bp->rx_nr_rings) {
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ struct bnxt_ring_struct *ring = &rxr->rx_ring_struct;
+ u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id;
+
+ if (ring->fw_ring_id != INVALID_HW_RING_ID) {
+ hwrm_ring_free_send_msg(
+ bp, ring,
+ RING_FREE_REQ_RING_TYPE_RX,
+ close_path ? cmpl_ring_id :
+ INVALID_HW_RING_ID);
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[i].rx_fw_ring_id =
+ INVALID_HW_RING_ID;
+ }
+ }
+ }
+
+ if (bp->rx_agg_nr_pages) {
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring;
+ struct bnxt_ring_struct *ring =
+ &rxr->rx_agg_ring_struct;
+ u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id;
+
+ if (ring->fw_ring_id != INVALID_HW_RING_ID) {
+ hwrm_ring_free_send_msg(
+ bp, ring,
+ RING_FREE_REQ_RING_TYPE_RX,
+ close_path ? cmpl_ring_id :
+ INVALID_HW_RING_ID);
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[i].agg_fw_ring_id =
+ INVALID_HW_RING_ID;
+ }
+ }
+ }
+
+ if (bp->cp_nr_rings) {
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
+
+ if (ring->fw_ring_id != INVALID_HW_RING_ID) {
+ hwrm_ring_free_send_msg(
+ bp, ring,
+ RING_FREE_REQ_RING_TYPE_CMPL,
+ INVALID_HW_RING_ID);
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[i].cp_fw_ring_id =
+ INVALID_HW_RING_ID;
+ }
+ }
+ }
+
+ return rc;
+}
+
+int bnxt_hwrm_set_coal(struct bnxt *bp)
+{
+ int i, rc = 0;
+ struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req = {0};
+ u16 max_buf, max_buf_irq;
+ u16 buf_tmr, buf_tmr_irq;
+ u32 flags;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS,
+ -1, -1);
+
+ /* Each rx completion (2 records) should be DMAed immediately */
+ max_buf = min_t(u16, bp->coal_bufs / 4, 2);
+ /* max_buf must not be zero */
+ max_buf = clamp_t(u16, max_buf, 1, 63);
+ max_buf_irq = clamp_t(u16, bp->coal_bufs_irq, 1, 63);
+ buf_tmr = max_t(u16, bp->coal_ticks / 4, 1);
+ buf_tmr_irq = max_t(u16, bp->coal_ticks_irq, 1);
+
+ flags = RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_TIMER_RESET;
+
+ /* RING_IDLE generates more IRQs for lower latency. Enable it only
+ * if coal_ticks is less than 25 us.
+ */
+ if (BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks) < 25)
+ flags |= RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_RING_IDLE;
+
+ req.flags = cpu_to_le16(flags);
+ req.num_cmpl_dma_aggr = cpu_to_le16(max_buf);
+ req.num_cmpl_dma_aggr_during_int = cpu_to_le16(max_buf_irq);
+ req.cmpl_aggr_dma_tmr = cpu_to_le16(buf_tmr);
+ req.cmpl_aggr_dma_tmr_during_int = cpu_to_le16(buf_tmr_irq);
+ req.int_lat_tmr_min = cpu_to_le16(buf_tmr);
+ req.int_lat_tmr_max = cpu_to_le16(bp->coal_ticks);
+ req.num_cmpl_aggr_int = cpu_to_le16(bp->coal_bufs);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ req.ring_id = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_stat_ctx_free(struct bnxt *bp)
+{
+ int rc = 0, i;
+ struct hwrm_stat_ctx_free_input req = {0};
+
+ if (!bp->bnapi)
+ return 0;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_FREE, -1, -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+
+ if (cpr->hw_stats_ctx_id != INVALID_STATS_CTX_ID) {
+ req.stat_ctx_id = cpu_to_le32(cpr->hw_stats_ctx_id);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+
+ cpr->hw_stats_ctx_id = INVALID_STATS_CTX_ID;
+ }
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp)
+{
+ int rc = 0, i;
+ struct hwrm_stat_ctx_alloc_input req = {0};
+ struct hwrm_stat_ctx_alloc_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_ALLOC, -1, -1);
+
+ req.update_period_ms = cpu_to_le32(1000);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+
+ req.stats_dma_addr = cpu_to_le64(cpr->hw_stats_map);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+
+ cpr->hw_stats_ctx_id = le32_to_cpu(resp->stat_ctx_id);
+
+ bp->grp_info[i].fw_stats_ctx = cpr->hw_stats_ctx_id;
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return 0;
+}
+
+static int bnxt_hwrm_func_qcaps(struct bnxt *bp)
+{
+ int rc = 0;
+ struct hwrm_func_qcaps_input req = {0};
+ struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1);
+ req.fid = cpu_to_le16(0xffff);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ goto hwrm_func_qcaps_exit;
+
+ if (BNXT_PF(bp)) {
+ struct bnxt_pf_info *pf = &bp->pf;
+
+ pf->fw_fid = le16_to_cpu(resp->fid);
+ pf->port_id = le16_to_cpu(resp->port_id);
+ memcpy(pf->mac_addr, resp->perm_mac_address, ETH_ALEN);
+ pf->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx);
+ pf->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings);
+ pf->max_tx_rings = le16_to_cpu(resp->max_tx_rings);
+ pf->max_pf_tx_rings = pf->max_tx_rings;
+ pf->max_rx_rings = le16_to_cpu(resp->max_rx_rings);
+ pf->max_pf_rx_rings = pf->max_rx_rings;
+ pf->max_l2_ctxs = le16_to_cpu(resp->max_l2_ctxs);
+ pf->max_vnics = le16_to_cpu(resp->max_vnics);
+ pf->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx);
+ pf->first_vf_id = le16_to_cpu(resp->first_vf_id);
+ pf->max_vfs = le16_to_cpu(resp->max_vfs);
+ pf->max_encap_records = le32_to_cpu(resp->max_encap_records);
+ pf->max_decap_records = le32_to_cpu(resp->max_decap_records);
+ pf->max_tx_em_flows = le32_to_cpu(resp->max_tx_em_flows);
+ pf->max_tx_wm_flows = le32_to_cpu(resp->max_tx_wm_flows);
+ pf->max_rx_em_flows = le32_to_cpu(resp->max_rx_em_flows);
+ pf->max_rx_wm_flows = le32_to_cpu(resp->max_rx_wm_flows);
+ } else {
+#ifdef CONFIG_BNXT_SRIOV
+ struct bnxt_vf_info *vf = &bp->vf;
+
+ vf->fw_fid = le16_to_cpu(resp->fid);
+ memcpy(vf->mac_addr, resp->perm_mac_address, ETH_ALEN);
+ if (!is_valid_ether_addr(vf->mac_addr))
+ random_ether_addr(vf->mac_addr);
+
+ vf->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx);
+ vf->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings);
+ vf->max_tx_rings = le16_to_cpu(resp->max_tx_rings);
+ vf->max_rx_rings = le16_to_cpu(resp->max_rx_rings);
+ vf->max_l2_ctxs = le16_to_cpu(resp->max_l2_ctxs);
+ vf->max_vnics = le16_to_cpu(resp->max_vnics);
+ vf->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx);
+#endif
+ }
+
+ bp->tx_push_thresh = 0;
+ if (resp->flags &
+ cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED))
+ bp->tx_push_thresh = BNXT_TX_PUSH_THRESH;
+
+hwrm_func_qcaps_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_func_reset(struct bnxt *bp)
+{
+ struct hwrm_func_reset_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_RESET, -1, -1);
+ req.enables = 0;
+
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_RESET_TIMEOUT);
+}
+
+static int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
+{
+ int rc = 0;
+ struct hwrm_queue_qportcfg_input req = {0};
+ struct hwrm_queue_qportcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ u8 i, *qptr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_QPORTCFG, -1, -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ goto qportcfg_exit;
+
+ if (!resp->max_configurable_queues) {
+ rc = -EINVAL;
+ goto qportcfg_exit;
+ }
+ bp->max_tc = resp->max_configurable_queues;
+ if (bp->max_tc > BNXT_MAX_QUEUE)
+ bp->max_tc = BNXT_MAX_QUEUE;
+
+ qptr = &resp->queue_id0;
+ for (i = 0; i < bp->max_tc; i++) {
+ bp->q_info[i].queue_id = *qptr++;
+ bp->q_info[i].queue_profile = *qptr++;
+ }
+
+qportcfg_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_ver_get(struct bnxt *bp)
+{
+ int rc;
+ struct hwrm_ver_get_input req = {0};
+ struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET, -1, -1);
+ req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
+ req.hwrm_intf_min = HWRM_VERSION_MINOR;
+ req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ goto hwrm_ver_get_exit;
+
+ memcpy(&bp->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
+
+ if (req.hwrm_intf_maj != resp->hwrm_intf_maj ||
+ req.hwrm_intf_min != resp->hwrm_intf_min ||
+ req.hwrm_intf_upd != resp->hwrm_intf_upd) {
+ netdev_warn(bp->dev, "HWRM interface %d.%d.%d does not match driver interface %d.%d.%d.\n",
+ resp->hwrm_intf_maj, resp->hwrm_intf_min,
+ resp->hwrm_intf_upd, req.hwrm_intf_maj,
+ req.hwrm_intf_min, req.hwrm_intf_upd);
+ netdev_warn(bp->dev, "Please update driver or firmware with matching interface versions.\n");
+ }
+ snprintf(bp->fw_ver_str, BC_HWRM_STR_LEN, "bc %d.%d.%d rm %d.%d.%d",
+ resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld,
+ resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
+
+hwrm_ver_get_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static void bnxt_hwrm_free_tunnel_ports(struct bnxt *bp)
+{
+ if (bp->vxlan_port_cnt) {
+ bnxt_hwrm_tunnel_dst_port_free(
+ bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
+ }
+ bp->vxlan_port_cnt = 0;
+ if (bp->nge_port_cnt) {
+ bnxt_hwrm_tunnel_dst_port_free(
+ bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
+ }
+ bp->nge_port_cnt = 0;
+}
+
+static int bnxt_set_tpa(struct bnxt *bp, bool set_tpa)
+{
+ int rc, i;
+ u32 tpa_flags = 0;
+
+ if (set_tpa)
+ tpa_flags = bp->flags & BNXT_FLAG_TPA;
+ for (i = 0; i < bp->nr_vnics; i++) {
+ rc = bnxt_hwrm_vnic_set_tpa(bp, i, tpa_flags);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic set tpa failure rc for vnic %d: %x\n",
+ rc, i);
+ return rc;
+ }
+ }
+ return 0;
+}
+
+static void bnxt_hwrm_clear_vnic_rss(struct bnxt *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->nr_vnics; i++)
+ bnxt_hwrm_vnic_set_rss(bp, i, false);
+}
+
+static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
+ bool irq_re_init)
+{
+ if (bp->vnic_info) {
+ bnxt_hwrm_clear_vnic_filter(bp);
+ /* clear all RSS setting before free vnic ctx */
+ bnxt_hwrm_clear_vnic_rss(bp);
+ bnxt_hwrm_vnic_ctx_free(bp);
+ /* before free the vnic, undo the vnic tpa settings */
+ if (bp->flags & BNXT_FLAG_TPA)
+ bnxt_set_tpa(bp, false);
+ bnxt_hwrm_vnic_free(bp);
+ }
+ bnxt_hwrm_ring_free(bp, close_path);
+ bnxt_hwrm_ring_grp_free(bp);
+ if (irq_re_init) {
+ bnxt_hwrm_stat_ctx_free(bp);
+ bnxt_hwrm_free_tunnel_ports(bp);
+ }
+}
+
+static int bnxt_setup_vnic(struct bnxt *bp, u16 vnic_id)
+{
+ int rc;
+
+ /* allocate context for vnic */
+ rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic_id);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d alloc failure rc: %x\n",
+ vnic_id, rc);
+ goto vnic_setup_err;
+ }
+ bp->rsscos_nr_ctxs++;
+
+ /* configure default vnic, ring grp */
+ rc = bnxt_hwrm_vnic_cfg(bp, vnic_id);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d cfg failure rc: %x\n",
+ vnic_id, rc);
+ goto vnic_setup_err;
+ }
+
+ /* Enable RSS hashing on vnic */
+ rc = bnxt_hwrm_vnic_set_rss(bp, vnic_id, true);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %x\n",
+ vnic_id, rc);
+ goto vnic_setup_err;
+ }
+
+ if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+ rc = bnxt_hwrm_vnic_set_hds(bp, vnic_id);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d set hds failure rc: %x\n",
+ vnic_id, rc);
+ }
+ }
+
+vnic_setup_err:
+ return rc;
+}
+
+static int bnxt_alloc_rfs_vnics(struct bnxt *bp)
+{
+#ifdef CONFIG_RFS_ACCEL
+ int i, rc = 0;
+
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ u16 vnic_id = i + 1;
+ u16 ring_id = i;
+
+ if (vnic_id >= bp->nr_vnics)
+ break;
+
+ bp->vnic_info[vnic_id].flags |= BNXT_VNIC_RFS_FLAG;
+ rc = bnxt_hwrm_vnic_alloc(bp, vnic_id, ring_id, ring_id + 1);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d alloc failure rc: %x\n",
+ vnic_id, rc);
+ break;
+ }
+ rc = bnxt_setup_vnic(bp, vnic_id);
+ if (rc)
+ break;
+ }
+ return rc;
+#else
+ return 0;
+#endif
+}
+
+static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
+{
+ int rc = 0;
+
+ if (irq_re_init) {
+ rc = bnxt_hwrm_stat_ctx_alloc(bp);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm stat ctx alloc failure rc: %x\n",
+ rc);
+ goto err_out;
+ }
+ }
+
+ rc = bnxt_hwrm_ring_alloc(bp);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm ring alloc failure rc: %x\n", rc);
+ goto err_out;
+ }
+
+ rc = bnxt_hwrm_ring_grp_alloc(bp);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm_ring_grp alloc failure: %x\n", rc);
+ goto err_out;
+ }
+
+ /* default vnic 0 */
+ rc = bnxt_hwrm_vnic_alloc(bp, 0, 0, bp->rx_nr_rings);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic alloc failure rc: %x\n", rc);
+ goto err_out;
+ }
+
+ rc = bnxt_setup_vnic(bp, 0);
+ if (rc)
+ goto err_out;
+
+ if (bp->flags & BNXT_FLAG_RFS) {
+ rc = bnxt_alloc_rfs_vnics(bp);
+ if (rc)
+ goto err_out;
+ }
+
+ if (bp->flags & BNXT_FLAG_TPA) {
+ rc = bnxt_set_tpa(bp, true);
+ if (rc)
+ goto err_out;
+ }
+
+ if (BNXT_VF(bp))
+ bnxt_update_vf_mac(bp);
+
+ /* Filter for default vnic 0 */
+ rc = bnxt_hwrm_set_vnic_filter(bp, 0, 0, bp->dev->dev_addr);
+ if (rc) {
+ netdev_err(bp->dev, "HWRM vnic filter failure rc: %x\n", rc);
+ goto err_out;
+ }
+ bp->vnic_info[0].uc_filter_count = 1;
+
+ bp->vnic_info[0].rx_mask = CFA_L2_SET_RX_MASK_REQ_MASK_UNICAST |
+ CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
+
+ if ((bp->dev->flags & IFF_PROMISC) && BNXT_PF(bp))
+ bp->vnic_info[0].rx_mask |=
+ CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
+
+ rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
+ if (rc) {
+ netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %x\n", rc);
+ goto err_out;
+ }
+
+ rc = bnxt_hwrm_set_coal(bp);
+ if (rc)
+ netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n",
+ rc);
+
+ return 0;
+
+err_out:
+ bnxt_hwrm_resource_free(bp, 0, true);
+
+ return rc;
+}
+
+static int bnxt_shutdown_nic(struct bnxt *bp, bool irq_re_init)
+{
+ bnxt_hwrm_resource_free(bp, 1, irq_re_init);
+ return 0;
+}
+
+static int bnxt_init_nic(struct bnxt *bp, bool irq_re_init)
+{
+ bnxt_init_rx_rings(bp);
+ bnxt_init_tx_rings(bp);
+ bnxt_init_ring_grps(bp, irq_re_init);
+ bnxt_init_vnics(bp);
+
+ return bnxt_init_chip(bp, irq_re_init);
+}
+
+static void bnxt_disable_int(struct bnxt *bp)
+{
+ int i;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+
+ BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons);
+ }
+}
+
+static void bnxt_enable_int(struct bnxt *bp)
+{
+ int i;
+
+ atomic_set(&bp->intr_sem, 0);
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+
+ BNXT_CP_DB_REARM(cpr->cp_doorbell, cpr->cp_raw_cons);
+ }
+}
+
+static int bnxt_set_real_num_queues(struct bnxt *bp)
+{
+ int rc;
+ struct net_device *dev = bp->dev;
+
+ rc = netif_set_real_num_tx_queues(dev, bp->tx_nr_rings);
+ if (rc)
+ return rc;
+
+ rc = netif_set_real_num_rx_queues(dev, bp->rx_nr_rings);
+ if (rc)
+ return rc;
+
+#ifdef CONFIG_RFS_ACCEL
+ if (bp->rx_nr_rings)
+ dev->rx_cpu_rmap = alloc_irq_cpu_rmap(bp->rx_nr_rings);
+ if (!dev->rx_cpu_rmap)
+ rc = -ENOMEM;
+#endif
+
+ return rc;
+}
+
+static int bnxt_setup_msix(struct bnxt *bp)
+{
+ struct msix_entry *msix_ent;
+ struct net_device *dev = bp->dev;
+ int i, total_vecs, rc = 0;
+ const int len = sizeof(bp->irq_tbl[0].name);
+
+ bp->flags &= ~BNXT_FLAG_USING_MSIX;
+ total_vecs = bp->cp_nr_rings;
+
+ msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL);
+ if (!msix_ent)
+ return -ENOMEM;
+
+ for (i = 0; i < total_vecs; i++) {
+ msix_ent[i].entry = i;
+ msix_ent[i].vector = 0;
+ }
+
+ total_vecs = pci_enable_msix_range(bp->pdev, msix_ent, 1, total_vecs);
+ if (total_vecs < 0) {
+ rc = -ENODEV;
+ goto msix_setup_exit;
+ }
+
+ bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL);
+ if (bp->irq_tbl) {
+ int tcs;
+
+ /* Trim rings based upon num of vectors allocated */
+ bp->rx_nr_rings = min_t(int, total_vecs, bp->rx_nr_rings);
+ bp->tx_nr_rings = min_t(int, total_vecs, bp->tx_nr_rings);
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+ tcs = netdev_get_num_tc(dev);
+ if (tcs > 1) {
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
+ if (bp->tx_nr_rings_per_tc == 0) {
+ netdev_reset_tc(dev);
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+ } else {
+ int i, off, count;
+
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
+ for (i = 0; i < tcs; i++) {
+ count = bp->tx_nr_rings_per_tc;
+ off = i * count;
+ netdev_set_tc_queue(dev, i, count, off);
+ }
+ }
+ }
+ bp->cp_nr_rings = max_t(int, bp->rx_nr_rings, bp->tx_nr_rings);
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ bp->irq_tbl[i].vector = msix_ent[i].vector;
+ snprintf(bp->irq_tbl[i].name, len,
+ "%s-%s-%d", dev->name, "TxRx", i);
+ bp->irq_tbl[i].handler = bnxt_msix;
+ }
+ rc = bnxt_set_real_num_queues(bp);
+ if (rc)
+ goto msix_setup_exit;
+ } else {
+ rc = -ENOMEM;
+ goto msix_setup_exit;
+ }
+ bp->flags |= BNXT_FLAG_USING_MSIX;
+ kfree(msix_ent);
+ return 0;
+
+msix_setup_exit:
+ netdev_err(bp->dev, "bnxt_setup_msix err: %x\n", rc);
+ pci_disable_msix(bp->pdev);
+ kfree(msix_ent);
+ return rc;
+}
+
+static int bnxt_setup_inta(struct bnxt *bp)
+{
+ int rc;
+ const int len = sizeof(bp->irq_tbl[0].name);
+
+ if (netdev_get_num_tc(bp->dev))
+ netdev_reset_tc(bp->dev);
+
+ bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL);
+ if (!bp->irq_tbl) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ bp->rx_nr_rings = 1;
+ bp->tx_nr_rings = 1;
+ bp->cp_nr_rings = 1;
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+ bp->irq_tbl[0].vector = bp->pdev->irq;
+ snprintf(bp->irq_tbl[0].name, len,
+ "%s-%s-%d", bp->dev->name, "TxRx", 0);
+ bp->irq_tbl[0].handler = bnxt_inta;
+ rc = bnxt_set_real_num_queues(bp);
+ return rc;
+}
+
+static int bnxt_setup_int_mode(struct bnxt *bp)
+{
+ int rc = 0;
+
+ if (bp->flags & BNXT_FLAG_MSIX_CAP)
+ rc = bnxt_setup_msix(bp);
+
+ if (!(bp->flags & BNXT_FLAG_USING_MSIX)) {
+ /* fallback to INTA */
+ rc = bnxt_setup_inta(bp);
+ }
+ return rc;
+}
+
+static void bnxt_free_irq(struct bnxt *bp)
+{
+ struct bnxt_irq *irq;
+ int i;
+
+#ifdef CONFIG_RFS_ACCEL
+ free_irq_cpu_rmap(bp->dev->rx_cpu_rmap);
+ bp->dev->rx_cpu_rmap = NULL;
+#endif
+ if (!bp->irq_tbl)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ irq = &bp->irq_tbl[i];
+ if (irq->requested)
+ free_irq(irq->vector, bp->bnapi[i]);
+ irq->requested = 0;
+ }
+ if (bp->flags & BNXT_FLAG_USING_MSIX)
+ pci_disable_msix(bp->pdev);
+ kfree(bp->irq_tbl);
+ bp->irq_tbl = NULL;
+}
+
+static int bnxt_request_irq(struct bnxt *bp)
+{
+ int i, rc = 0;
+ unsigned long flags = 0;
+#ifdef CONFIG_RFS_ACCEL
+ struct cpu_rmap *rmap = bp->dev->rx_cpu_rmap;
+#endif
+
+ if (!(bp->flags & BNXT_FLAG_USING_MSIX))
+ flags = IRQF_SHARED;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_irq *irq = &bp->irq_tbl[i];
+#ifdef CONFIG_RFS_ACCEL
+ if (rmap && (i < bp->rx_nr_rings)) {
+ rc = irq_cpu_rmap_add(rmap, irq->vector);
+ if (rc)
+ netdev_warn(bp->dev, "failed adding irq rmap for ring %d\n",
+ i);
+ }
+#endif
+ rc = request_irq(irq->vector, irq->handler, flags, irq->name,
+ bp->bnapi[i]);
+ if (rc)
+ break;
+
+ irq->requested = 1;
+ }
+ return rc;
+}
+
+static void bnxt_del_napi(struct bnxt *bp)
+{
+ int i;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+
+ napi_hash_del(&bnapi->napi);
+ netif_napi_del(&bnapi->napi);
+ }
+}
+
+static void bnxt_init_napi(struct bnxt *bp)
+{
+ int i;
+ struct bnxt_napi *bnapi;
+
+ if (bp->flags & BNXT_FLAG_USING_MSIX) {
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ bnapi = bp->bnapi[i];
+ netif_napi_add(bp->dev, &bnapi->napi,
+ bnxt_poll, 64);
+ napi_hash_add(&bnapi->napi);
+ }
+ } else {
+ bnapi = bp->bnapi[0];
+ netif_napi_add(bp->dev, &bnapi->napi, bnxt_poll, 64);
+ napi_hash_add(&bnapi->napi);
+ }
+}
+
+static void bnxt_disable_napi(struct bnxt *bp)
+{
+ int i;
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ napi_disable(&bp->bnapi[i]->napi);
+ bnxt_disable_poll(bp->bnapi[i]);
+ }
+}
+
+static void bnxt_enable_napi(struct bnxt *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ bnxt_enable_poll(bp->bnapi[i]);
+ napi_enable(&bp->bnapi[i]->napi);
+ }
+}
+
+static void bnxt_tx_disable(struct bnxt *bp)
+{
+ int i;
+ struct bnxt_napi *bnapi;
+ struct bnxt_tx_ring_info *txr;
+ struct netdev_queue *txq;
+
+ if (bp->bnapi) {
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ bnapi = bp->bnapi[i];
+ txr = &bnapi->tx_ring;
+ txq = netdev_get_tx_queue(bp->dev, i);
+ __netif_tx_lock(txq, smp_processor_id());
+ txr->dev_state = BNXT_DEV_STATE_CLOSING;
+ __netif_tx_unlock(txq);
+ }
+ }
+ /* Stop all TX queues */
+ netif_tx_disable(bp->dev);
+ netif_carrier_off(bp->dev);
+}
+
+static void bnxt_tx_enable(struct bnxt *bp)
+{
+ int i;
+ struct bnxt_napi *bnapi;
+ struct bnxt_tx_ring_info *txr;
+ struct netdev_queue *txq;
+
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ bnapi = bp->bnapi[i];
+ txr = &bnapi->tx_ring;
+ txq = netdev_get_tx_queue(bp->dev, i);
+ txr->dev_state = 0;
+ }
+ netif_tx_wake_all_queues(bp->dev);
+ if (bp->link_info.link_up)
+ netif_carrier_on(bp->dev);
+}
+
+static void bnxt_report_link(struct bnxt *bp)
+{
+ if (bp->link_info.link_up) {
+ const char *duplex;
+ const char *flow_ctrl;
+ u16 speed;
+
+ netif_carrier_on(bp->dev);
+ if (bp->link_info.duplex == BNXT_LINK_DUPLEX_FULL)
+ duplex = "full";
+ else
+ duplex = "half";
+ if (bp->link_info.pause == BNXT_LINK_PAUSE_BOTH)
+ flow_ctrl = "ON - receive & transmit";
+ else if (bp->link_info.pause == BNXT_LINK_PAUSE_TX)
+ flow_ctrl = "ON - transmit";
+ else if (bp->link_info.pause == BNXT_LINK_PAUSE_RX)
+ flow_ctrl = "ON - receive";
+ else
+ flow_ctrl = "none";
+ speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed);
+ netdev_info(bp->dev, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s\n",
+ speed, duplex, flow_ctrl);
+ } else {
+ netif_carrier_off(bp->dev);
+ netdev_err(bp->dev, "NIC Link is Down\n");
+ }
+}
+
+static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
+{
+ int rc = 0;
+ struct bnxt_link_info *link_info = &bp->link_info;
+ struct hwrm_port_phy_qcfg_input req = {0};
+ struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ u8 link_up = link_info->link_up;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
+
+ 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 rc;
+ }
+
+ memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp));
+ link_info->phy_link_status = resp->link;
+ link_info->duplex = resp->duplex;
+ link_info->pause = resp->pause;
+ link_info->auto_mode = resp->auto_mode;
+ link_info->auto_pause_setting = resp->auto_pause;
+ link_info->force_pause_setting = resp->force_pause;
+ link_info->duplex_setting = resp->duplex_setting;
+ if (link_info->phy_link_status == BNXT_LINK_LINK)
+ link_info->link_speed = le16_to_cpu(resp->link_speed);
+ else
+ link_info->link_speed = 0;
+ link_info->force_link_speed = le16_to_cpu(resp->force_link_speed);
+ link_info->auto_link_speed = le16_to_cpu(resp->auto_link_speed);
+ link_info->support_speeds = le16_to_cpu(resp->support_speeds);
+ link_info->auto_link_speeds = le16_to_cpu(resp->auto_link_speed_mask);
+ link_info->preemphasis = le32_to_cpu(resp->preemphasis);
+ link_info->phy_ver[0] = resp->phy_maj;
+ link_info->phy_ver[1] = resp->phy_min;
+ link_info->phy_ver[2] = resp->phy_bld;
+ link_info->media_type = resp->media_type;
+ link_info->transceiver = resp->transceiver_type;
+ link_info->phy_addr = resp->phy_addr;
+
+ /* TODO: need to add more logic to report VF link */
+ if (chng_link_state) {
+ if (link_info->phy_link_status == BNXT_LINK_LINK)
+ link_info->link_up = 1;
+ else
+ link_info->link_up = 0;
+ if (link_up != link_info->link_up)
+ bnxt_report_link(bp);
+ } else {
+ /* alwasy link down if not require to update link state */
+ link_info->link_up = 0;
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return 0;
+}
+
+static void
+bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
+{
+ if (bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) {
+ if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX)
+ req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX;
+ if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX)
+ req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX;
+ req->enables |=
+ cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE);
+ } else {
+ if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX)
+ req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_RX;
+ if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX)
+ req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_TX;
+ req->enables |=
+ cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE);
+ }
+}
+
+static void bnxt_hwrm_set_link_common(struct bnxt *bp,
+ struct hwrm_port_phy_cfg_input *req)
+{
+ u8 autoneg = bp->link_info.autoneg;
+ u16 fw_link_speed = bp->link_info.req_link_speed;
+ u32 advertising = bp->link_info.advertising;
+
+ if (autoneg & BNXT_AUTONEG_SPEED) {
+ req->auto_mode |=
+ PORT_PHY_CFG_REQ_AUTO_MODE_MASK;
+
+ req->enables |= cpu_to_le32(
+ PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK);
+ req->auto_link_speed_mask = cpu_to_le16(advertising);
+
+ req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE);
+ req->flags |=
+ cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG);
+ } else {
+ req->force_link_speed = cpu_to_le16(fw_link_speed);
+ req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE);
+ }
+
+ /* currently don't support half duplex */
+ req->auto_duplex = PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL;
+ req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX);
+ /* tell chimp that the setting takes effect immediately */
+ req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY);
+}
+
+int bnxt_hwrm_set_pause(struct bnxt *bp)
+{
+ struct hwrm_port_phy_cfg_input req = {0};
+ int rc;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
+ bnxt_hwrm_set_pause_common(bp, &req);
+
+ if ((bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) ||
+ bp->link_info.force_link_chng)
+ bnxt_hwrm_set_link_common(bp, &req);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc && !(bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
+ /* since changing of pause setting doesn't trigger any link
+ * change event, the driver needs to update the current pause
+ * result upon successfully return of the phy_cfg command
+ */
+ bp->link_info.pause =
+ bp->link_info.force_pause_setting = bp->link_info.req_flow_ctrl;
+ bp->link_info.auto_pause_setting = 0;
+ if (!bp->link_info.force_link_chng)
+ bnxt_report_link(bp);
+ }
+ bp->link_info.force_link_chng = false;
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+int bnxt_hwrm_set_link_setting(struct bnxt *bp, bool set_pause)
+{
+ struct hwrm_port_phy_cfg_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
+ if (set_pause)
+ bnxt_hwrm_set_pause_common(bp, &req);
+
+ bnxt_hwrm_set_link_common(bp, &req);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_update_phy_setting(struct bnxt *bp)
+{
+ int rc;
+ bool update_link = false;
+ bool update_pause = false;
+ struct bnxt_link_info *link_info = &bp->link_info;
+
+ rc = bnxt_update_link(bp, true);
+ if (rc) {
+ netdev_err(bp->dev, "failed to update link (rc: %x)\n",
+ rc);
+ return rc;
+ }
+ if ((link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) &&
+ link_info->auto_pause_setting != link_info->req_flow_ctrl)
+ update_pause = true;
+ if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) &&
+ link_info->force_pause_setting != link_info->req_flow_ctrl)
+ update_pause = true;
+ if (link_info->req_duplex != link_info->duplex_setting)
+ update_link = true;
+ if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
+ if (BNXT_AUTO_MODE(link_info->auto_mode))
+ update_link = true;
+ if (link_info->req_link_speed != link_info->force_link_speed)
+ update_link = true;
+ } else {
+ if (link_info->auto_mode == BNXT_LINK_AUTO_NONE)
+ update_link = true;
+ if (link_info->advertising != link_info->auto_link_speeds)
+ update_link = true;
+ if (link_info->req_link_speed != link_info->auto_link_speed)
+ update_link = true;
+ }
+
+ if (update_link)
+ rc = bnxt_hwrm_set_link_setting(bp, update_pause);
+ else if (update_pause)
+ rc = bnxt_hwrm_set_pause(bp);
+ if (rc) {
+ netdev_err(bp->dev, "failed to update phy setting (rc: %x)\n",
+ rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+/* Common routine to pre-map certain register block to different GRC window.
+ * A PF has 16 4K windows and a VF has 4 4K windows. However, only 15 windows
+ * in PF and 3 windows in VF that can be customized to map in different
+ * register blocks.
+ */
+static void bnxt_preset_reg_win(struct bnxt *bp)
+{
+ if (BNXT_PF(bp)) {
+ /* CAG registers map to GRC window #4 */
+ writel(BNXT_CAG_REG_BASE,
+ bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 12);
+ }
+}
+
+static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+{
+ int rc = 0;
+
+ bnxt_preset_reg_win(bp);
+ netif_carrier_off(bp->dev);
+ if (irq_re_init) {
+ rc = bnxt_setup_int_mode(bp);
+ if (rc) {
+ netdev_err(bp->dev, "bnxt_setup_int_mode err: %x\n",
+ rc);
+ return rc;
+ }
+ }
+ if ((bp->flags & BNXT_FLAG_RFS) &&
+ !(bp->flags & BNXT_FLAG_USING_MSIX)) {
+ /* disable RFS if falling back to INTA */
+ bp->dev->hw_features &= ~NETIF_F_NTUPLE;
+ bp->flags &= ~BNXT_FLAG_RFS;
+ }
+
+ rc = bnxt_alloc_mem(bp, irq_re_init);
+ if (rc) {
+ netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc);
+ goto open_err_free_mem;
+ }
+
+ if (irq_re_init) {
+ bnxt_init_napi(bp);
+ rc = bnxt_request_irq(bp);
+ if (rc) {
+ netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc);
+ goto open_err;
+ }
+ }
+
+ bnxt_enable_napi(bp);
+
+ rc = bnxt_init_nic(bp, irq_re_init);
+ if (rc) {
+ netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
+ goto open_err;
+ }
+
+ if (link_re_init) {
+ rc = bnxt_update_phy_setting(bp);
+ if (rc)
+ goto open_err;
+ }
+
+ if (irq_re_init) {
+#if defined(CONFIG_VXLAN) || defined(CONFIG_VXLAN_MODULE)
+ vxlan_get_rx_port(bp->dev);
+#endif
+ if (!bnxt_hwrm_tunnel_dst_port_alloc(
+ bp, htons(0x17c1),
+ TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE))
+ bp->nge_port_cnt = 1;
+ }
+
+ bp->state = BNXT_STATE_OPEN;
+ bnxt_enable_int(bp);
+ /* Enable TX queues */
+ bnxt_tx_enable(bp);
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
+
+ return 0;
+
+open_err:
+ bnxt_disable_napi(bp);
+ bnxt_del_napi(bp);
+
+open_err_free_mem:
+ bnxt_free_skbs(bp);
+ bnxt_free_irq(bp);
+ bnxt_free_mem(bp, true);
+ return rc;
+}
+
+/* rtnl_lock held */
+int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+{
+ int rc = 0;
+
+ rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
+ if (rc) {
+ netdev_err(bp->dev, "nic open fail (rc: %x)\n", rc);
+ dev_close(bp->dev);
+ }
+ return rc;
+}
+
+static int bnxt_open(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc = 0;
+
+ rc = bnxt_hwrm_func_reset(bp);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm chip reset failure rc: %x\n",
+ rc);
+ rc = -1;
+ return rc;
+ }
+ return __bnxt_open_nic(bp, true, true);
+}
+
+static void bnxt_disable_int_sync(struct bnxt *bp)
+{
+ int i;
+
+ atomic_inc(&bp->intr_sem);
+ if (!netif_running(bp->dev))
+ return;
+
+ bnxt_disable_int(bp);
+ for (i = 0; i < bp->cp_nr_rings; i++)
+ synchronize_irq(bp->irq_tbl[i].vector);
+}
+
+int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+{
+ int rc = 0;
+
+#ifdef CONFIG_BNXT_SRIOV
+ if (bp->sriov_cfg) {
+ rc = wait_event_interruptible_timeout(bp->sriov_cfg_wait,
+ !bp->sriov_cfg,
+ BNXT_SRIOV_CFG_WAIT_TMO);
+ if (rc)
+ netdev_warn(bp->dev, "timeout waiting for SRIOV config operation to complete!\n");
+ }
+#endif
+ /* Change device state to avoid TX queue wake up's */
+ bnxt_tx_disable(bp);
+
+ bp->state = BNXT_STATE_CLOSED;
+ cancel_work_sync(&bp->sp_task);
+
+ /* Flush rings before disabling interrupts */
+ bnxt_shutdown_nic(bp, irq_re_init);
+
+ /* TODO CHIMP_FW: Link/PHY related cleanup if (link_re_init) */
+
+ bnxt_disable_napi(bp);
+ bnxt_disable_int_sync(bp);
+ del_timer_sync(&bp->timer);
+ bnxt_free_skbs(bp);
+
+ if (irq_re_init) {
+ bnxt_free_irq(bp);
+ bnxt_del_napi(bp);
+ }
+ bnxt_free_mem(bp, irq_re_init);
+ return rc;
+}
+
+static int bnxt_close(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ bnxt_close_nic(bp, true, true);
+ return 0;
+}
+
+/* rtnl_lock held */
+static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ /* fallthru */
+ case SIOCGMIIREG: {
+ if (!netif_running(dev))
+ return -EAGAIN;
+
+ return 0;
+ }
+
+ case SIOCSMIIREG:
+ if (!netif_running(dev))
+ return -EAGAIN;
+
+ return 0;
+
+ default:
+ /* do nothing */
+ break;
+ }
+ return -EOPNOTSUPP;
+}
+
+static struct rtnl_link_stats64 *
+bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+ u32 i;
+ struct bnxt *bp = netdev_priv(dev);
+
+ memset(stats, 0, sizeof(struct rtnl_link_stats64));
+
+ if (!bp->bnapi)
+ return stats;
+
+ /* TODO check if we need to synchronize with bnxt_close path */
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct ctx_hw_stats *hw_stats = cpr->hw_stats;
+
+ stats->rx_packets += le64_to_cpu(hw_stats->rx_ucast_pkts);
+ stats->rx_packets += le64_to_cpu(hw_stats->rx_mcast_pkts);
+ stats->rx_packets += le64_to_cpu(hw_stats->rx_bcast_pkts);
+
+ stats->tx_packets += le64_to_cpu(hw_stats->tx_ucast_pkts);
+ stats->tx_packets += le64_to_cpu(hw_stats->tx_mcast_pkts);
+ stats->tx_packets += le64_to_cpu(hw_stats->tx_bcast_pkts);
+
+ stats->rx_bytes += le64_to_cpu(hw_stats->rx_ucast_bytes);
+ stats->rx_bytes += le64_to_cpu(hw_stats->rx_mcast_bytes);
+ stats->rx_bytes += le64_to_cpu(hw_stats->rx_bcast_bytes);
+
+ stats->tx_bytes += le64_to_cpu(hw_stats->tx_ucast_bytes);
+ stats->tx_bytes += le64_to_cpu(hw_stats->tx_mcast_bytes);
+ stats->tx_bytes += le64_to_cpu(hw_stats->tx_bcast_bytes);
+
+ stats->rx_missed_errors +=
+ le64_to_cpu(hw_stats->rx_discard_pkts);
+
+ stats->multicast += le64_to_cpu(hw_stats->rx_mcast_pkts);
+
+ stats->rx_dropped += le64_to_cpu(hw_stats->rx_drop_pkts);
+
+ stats->tx_dropped += le64_to_cpu(hw_stats->tx_drop_pkts);
+ }
+
+ return stats;
+}
+
+static bool bnxt_mc_list_updated(struct bnxt *bp, u32 *rx_mask)
+{
+ struct net_device *dev = bp->dev;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ struct netdev_hw_addr *ha;
+ u8 *haddr;
+ int mc_count = 0;
+ bool update = false;
+ int off = 0;
+
+ netdev_for_each_mc_addr(ha, dev) {
+ if (mc_count >= BNXT_MAX_MC_ADDRS) {
+ *rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
+ vnic->mc_list_count = 0;
+ return false;
+ }
+ haddr = ha->addr;
+ if (!ether_addr_equal(haddr, vnic->mc_list + off)) {
+ memcpy(vnic->mc_list + off, haddr, ETH_ALEN);
+ update = true;
+ }
+ off += ETH_ALEN;
+ mc_count++;
+ }
+ if (mc_count)
+ *rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_MCAST;
+
+ if (mc_count != vnic->mc_list_count) {
+ vnic->mc_list_count = mc_count;
+ update = true;
+ }
+ return update;
+}
+
+static bool bnxt_uc_list_updated(struct bnxt *bp)
+{
+ struct net_device *dev = bp->dev;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ struct netdev_hw_addr *ha;
+ int off = 0;
+
+ if (netdev_uc_count(dev) != (vnic->uc_filter_count - 1))
+ return true;
+
+ netdev_for_each_uc_addr(ha, dev) {
+ if (!ether_addr_equal(ha->addr, vnic->uc_list + off))
+ return true;
+
+ off += ETH_ALEN;
+ }
+ return false;
+}
+
+static void bnxt_set_rx_mode(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ u32 mask = vnic->rx_mask;
+ bool mc_update = false;
+ bool uc_update;
+
+ if (!netif_running(dev))
+ return;
+
+ mask &= ~(CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS |
+ CFA_L2_SET_RX_MASK_REQ_MASK_MCAST |
+ CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST);
+
+ /* Only allow PF to be in promiscuous mode */
+ if ((dev->flags & IFF_PROMISC) && BNXT_PF(bp))
+ mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
+
+ uc_update = bnxt_uc_list_updated(bp);
+
+ if (dev->flags & IFF_ALLMULTI) {
+ mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
+ vnic->mc_list_count = 0;
+ } else {
+ mc_update = bnxt_mc_list_updated(bp, &mask);
+ }
+
+ if (mask != vnic->rx_mask || uc_update || mc_update) {
+ vnic->rx_mask = mask;
+
+ set_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+ }
+}
+
+static void bnxt_cfg_rx_mode(struct bnxt *bp)
+{
+ struct net_device *dev = bp->dev;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ struct netdev_hw_addr *ha;
+ int i, off = 0, rc;
+ bool uc_update;
+
+ netif_addr_lock_bh(dev);
+ uc_update = bnxt_uc_list_updated(bp);
+ netif_addr_unlock_bh(dev);
+
+ if (!uc_update)
+ goto skip_uc;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 1; i < vnic->uc_filter_count; i++) {
+ struct hwrm_cfa_l2_filter_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_L2_FILTER_FREE, -1,
+ -1);
+
+ req.l2_filter_id = vnic->fw_l2_filter_id[i];
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+
+ vnic->uc_filter_count = 1;
+
+ netif_addr_lock_bh(dev);
+ if (netdev_uc_count(dev) > (BNXT_MAX_UC_ADDRS - 1)) {
+ vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
+ } else {
+ netdev_for_each_uc_addr(ha, dev) {
+ memcpy(vnic->uc_list + off, ha->addr, ETH_ALEN);
+ off += ETH_ALEN;
+ vnic->uc_filter_count++;
+ }
+ }
+ netif_addr_unlock_bh(dev);
+
+ for (i = 1, off = 0; i < vnic->uc_filter_count; i++, off += ETH_ALEN) {
+ rc = bnxt_hwrm_set_vnic_filter(bp, 0, i, vnic->uc_list + off);
+ if (rc) {
+ netdev_err(bp->dev, "HWRM vnic filter failure rc: %x\n",
+ rc);
+ vnic->uc_filter_count = i;
+ }
+ }
+
+skip_uc:
+ rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
+ if (rc)
+ netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %x\n",
+ rc);
+}
+
+static netdev_features_t bnxt_fix_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ return features;
+}
+
+static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ u32 flags = bp->flags;
+ u32 changes;
+ int rc = 0;
+ bool re_init = false;
+ bool update_tpa = false;
+
+ flags &= ~BNXT_FLAG_ALL_CONFIG_FEATS;
+ if ((features & NETIF_F_GRO) && (bp->pdev->revision > 0))
+ flags |= BNXT_FLAG_GRO;
+ if (features & NETIF_F_LRO)
+ flags |= BNXT_FLAG_LRO;
+
+ if (features & NETIF_F_HW_VLAN_CTAG_RX)
+ flags |= BNXT_FLAG_STRIP_VLAN;
+
+ if (features & NETIF_F_NTUPLE)
+ flags |= BNXT_FLAG_RFS;
+
+ changes = flags ^ bp->flags;
+ if (changes & BNXT_FLAG_TPA) {
+ update_tpa = true;
+ if ((bp->flags & BNXT_FLAG_TPA) == 0 ||
+ (flags & BNXT_FLAG_TPA) == 0)
+ re_init = true;
+ }
+
+ if (changes & ~BNXT_FLAG_TPA)
+ re_init = true;
+
+ if (flags != bp->flags) {
+ u32 old_flags = bp->flags;
+
+ bp->flags = flags;
+
+ if (!netif_running(dev)) {
+ if (update_tpa)
+ bnxt_set_ring_params(bp);
+ return rc;
+ }
+
+ if (re_init) {
+ bnxt_close_nic(bp, false, false);
+ if (update_tpa)
+ bnxt_set_ring_params(bp);
+
+ return bnxt_open_nic(bp, false, false);
+ }
+ if (update_tpa) {
+ rc = bnxt_set_tpa(bp,
+ (flags & BNXT_FLAG_TPA) ?
+ true : false);
+ if (rc)
+ bp->flags = old_flags;
+ }
+ }
+ return rc;
+}
+
+static void bnxt_dbg_dump_states(struct bnxt *bp)
+{
+ int i;
+ struct bnxt_napi *bnapi;
+ struct bnxt_tx_ring_info *txr;
+ struct bnxt_rx_ring_info *rxr;
+ struct bnxt_cp_ring_info *cpr;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ bnapi = bp->bnapi[i];
+ txr = &bnapi->tx_ring;
+ rxr = &bnapi->rx_ring;
+ cpr = &bnapi->cp_ring;
+ if (netif_msg_drv(bp)) {
+ netdev_info(bp->dev, "[%d]: tx{fw_ring: %d prod: %x cons: %x}\n",
+ i, txr->tx_ring_struct.fw_ring_id,
+ txr->tx_prod, txr->tx_cons);
+ netdev_info(bp->dev, "[%d]: rx{fw_ring: %d prod: %x} rx_agg{fw_ring: %d agg_prod: %x sw_agg_prod: %x}\n",
+ i, rxr->rx_ring_struct.fw_ring_id,
+ rxr->rx_prod,
+ rxr->rx_agg_ring_struct.fw_ring_id,
+ rxr->rx_agg_prod, rxr->rx_sw_agg_prod);
+ netdev_info(bp->dev, "[%d]: cp{fw_ring: %d raw_cons: %x}\n",
+ i, cpr->cp_ring_struct.fw_ring_id,
+ cpr->cp_raw_cons);
+ }
+ }
+}
+
+static void bnxt_reset_task(struct bnxt *bp)
+{
+ bnxt_dbg_dump_states(bp);
+ if (netif_running(bp->dev))
+ bnxt_tx_disable(bp); /* prevent tx timout again */
+}
+
+static void bnxt_tx_timeout(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ netdev_err(bp->dev, "TX timeout detected, starting reset task!\n");
+ set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void bnxt_poll_controller(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int i;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_irq *irq = &bp->irq_tbl[i];
+
+ disable_irq(irq->vector);
+ irq->handler(irq->vector, bp->bnapi[i]);
+ enable_irq(irq->vector);
+ }
+}
+#endif
+
+static void bnxt_timer(unsigned long data)
+{
+ struct bnxt *bp = (struct bnxt *)data;
+ struct net_device *dev = bp->dev;
+
+ if (!netif_running(dev))
+ return;
+
+ if (atomic_read(&bp->intr_sem) != 0)
+ goto bnxt_restart_timer;
+
+bnxt_restart_timer:
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
+}
+
+static void bnxt_cfg_ntp_filters(struct bnxt *);
+
+static void bnxt_sp_task(struct work_struct *work)
+{
+ struct bnxt *bp = container_of(work, struct bnxt, sp_task);
+ int rc;
+
+ if (bp->state != BNXT_STATE_OPEN)
+ return;
+
+ if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event))
+ bnxt_cfg_rx_mode(bp);
+
+ if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
+ bnxt_cfg_ntp_filters(bp);
+ if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
+ rc = bnxt_update_link(bp, true);
+ if (rc)
+ netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
+ rc);
+ }
+ if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
+ bnxt_hwrm_exec_fwd_req(bp);
+ if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
+ bnxt_hwrm_tunnel_dst_port_alloc(
+ bp, bp->vxlan_port,
+ TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
+ }
+ if (test_and_clear_bit(BNXT_VXLAN_DEL_PORT_SP_EVENT, &bp->sp_event)) {
+ bnxt_hwrm_tunnel_dst_port_free(
+ bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
+ }
+ if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+ bnxt_reset_task(bp);
+}
+
+static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
+{
+ int rc;
+ struct bnxt *bp = netdev_priv(dev);
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ /* enable device (incl. PCI PM wakeup), and bus-mastering */
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
+ goto init_err;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ dev_err(&pdev->dev,
+ "Cannot find PCI device base address, aborting\n");
+ rc = -ENODEV;
+ goto init_err_disable;
+ }
+
+ rc = pci_request_regions(pdev, DRV_MODULE_NAME);
+ if (rc) {
+ dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
+ goto init_err_disable;
+ }
+
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 &&
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
+ dev_err(&pdev->dev, "System does not support DMA, aborting\n");
+ goto init_err_disable;
+ }
+
+ pci_set_master(pdev);
+
+ bp->dev = dev;
+ bp->pdev = pdev;
+
+ bp->bar0 = pci_ioremap_bar(pdev, 0);
+ if (!bp->bar0) {
+ dev_err(&pdev->dev, "Cannot map device registers, aborting\n");
+ rc = -ENOMEM;
+ goto init_err_release;
+ }
+
+ bp->bar1 = pci_ioremap_bar(pdev, 2);
+ if (!bp->bar1) {
+ dev_err(&pdev->dev, "Cannot map doorbell registers, aborting\n");
+ rc = -ENOMEM;
+ goto init_err_release;
+ }
+
+ bp->bar2 = pci_ioremap_bar(pdev, 4);
+ if (!bp->bar2) {
+ dev_err(&pdev->dev, "Cannot map bar4 registers, aborting\n");
+ rc = -ENOMEM;
+ goto init_err_release;
+ }
+
+ INIT_WORK(&bp->sp_task, bnxt_sp_task);
+
+ spin_lock_init(&bp->ntp_fltr_lock);
+
+ bp->rx_ring_size = BNXT_DEFAULT_RX_RING_SIZE;
+ bp->tx_ring_size = BNXT_DEFAULT_TX_RING_SIZE;
+
+ bp->coal_ticks = BNXT_USEC_TO_COAL_TIMER(4);
+ bp->coal_bufs = 20;
+ bp->coal_ticks_irq = BNXT_USEC_TO_COAL_TIMER(1);
+ bp->coal_bufs_irq = 2;
+
+ init_timer(&bp->timer);
+ bp->timer.data = (unsigned long)bp;
+ bp->timer.function = bnxt_timer;
+ bp->current_interval = BNXT_TIMER_INTERVAL;
+
+ bp->state = BNXT_STATE_CLOSED;
+
+ return 0;
+
+init_err_release:
+ if (bp->bar2) {
+ pci_iounmap(pdev, bp->bar2);
+ bp->bar2 = NULL;
+ }
+
+ if (bp->bar1) {
+ pci_iounmap(pdev, bp->bar1);
+ bp->bar1 = NULL;
+ }
+
+ if (bp->bar0) {
+ pci_iounmap(pdev, bp->bar0);
+ bp->bar0 = NULL;
+ }
+
+ pci_release_regions(pdev);
+
+init_err_disable:
+ pci_disable_device(pdev);
+
+init_err:
+ return rc;
+}
+
+/* rtnl_lock held */
+static int bnxt_change_mac_addr(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ return 0;
+}
+
+/* rtnl_lock held */
+static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (new_mtu < 60 || new_mtu > 9000)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ bnxt_close_nic(bp, false, false);
+
+ dev->mtu = new_mtu;
+ bnxt_set_ring_params(bp);
+
+ if (netif_running(dev))
+ return bnxt_open_nic(bp, false, false);
+
+ return 0;
+}
+
+static int bnxt_setup_tc(struct net_device *dev, u8 tc)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (tc > bp->max_tc) {
+ netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n",
+ tc, bp->max_tc);
+ return -EINVAL;
+ }
+
+ if (netdev_get_num_tc(dev) == tc)
+ return 0;
+
+ if (tc) {
+ int max_rx_rings, max_tx_rings;
+
+ bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings);
+ if (bp->tx_nr_rings_per_tc * tc > max_tx_rings)
+ return -ENOMEM;
+ }
+
+ /* Needs to close the device and do hw resource re-allocations */
+ if (netif_running(bp->dev))
+ bnxt_close_nic(bp, true, false);
+
+ if (tc) {
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc;
+ netdev_set_num_tc(dev, tc);
+ } else {
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc;
+ netdev_reset_tc(dev);
+ }
+ bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings);
+ bp->num_stat_ctxs = bp->cp_nr_rings;
+
+ if (netif_running(bp->dev))
+ return bnxt_open_nic(bp, true, false);
+
+ return 0;
+}
+
+#ifdef CONFIG_RFS_ACCEL
+static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1,
+ struct bnxt_ntuple_filter *f2)
+{
+ struct flow_keys *keys1 = &f1->fkeys;
+ struct flow_keys *keys2 = &f2->fkeys;
+
+ if (keys1->addrs.v4addrs.src == keys2->addrs.v4addrs.src &&
+ keys1->addrs.v4addrs.dst == keys2->addrs.v4addrs.dst &&
+ keys1->ports.ports == keys2->ports.ports &&
+ keys1->basic.ip_proto == keys2->basic.ip_proto &&
+ keys1->basic.n_proto == keys2->basic.n_proto &&
+ ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr))
+ return true;
+
+ return false;
+}
+
+static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_ntuple_filter *fltr, *new_fltr;
+ struct flow_keys *fkeys;
+ struct ethhdr *eth = (struct ethhdr *)skb_mac_header(skb);
+ int rc = 0, idx, bit_id;
+ struct hlist_head *head;
+
+ if (skb->encapsulation)
+ return -EPROTONOSUPPORT;
+
+ new_fltr = kzalloc(sizeof(*new_fltr), GFP_ATOMIC);
+ if (!new_fltr)
+ return -ENOMEM;
+
+ fkeys = &new_fltr->fkeys;
+ if (!skb_flow_dissect_flow_keys(skb, fkeys, 0)) {
+ rc = -EPROTONOSUPPORT;
+ goto err_free;
+ }
+
+ if ((fkeys->basic.n_proto != htons(ETH_P_IP)) ||
+ ((fkeys->basic.ip_proto != IPPROTO_TCP) &&
+ (fkeys->basic.ip_proto != IPPROTO_UDP))) {
+ rc = -EPROTONOSUPPORT;
+ goto err_free;
+ }
+
+ memcpy(new_fltr->src_mac_addr, eth->h_source, ETH_ALEN);
+
+ idx = skb_get_hash_raw(skb) & BNXT_NTP_FLTR_HASH_MASK;
+ head = &bp->ntp_fltr_hash_tbl[idx];
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(fltr, head, hash) {
+ if (bnxt_fltr_match(fltr, new_fltr)) {
+ rcu_read_unlock();
+ rc = 0;
+ goto err_free;
+ }
+ }
+ rcu_read_unlock();
+
+ spin_lock_bh(&bp->ntp_fltr_lock);
+ bit_id = bitmap_find_free_region(bp->ntp_fltr_bmap,
+ BNXT_NTP_FLTR_MAX_FLTR, 0);
+ if (bit_id < 0) {
+ spin_unlock_bh(&bp->ntp_fltr_lock);
+ rc = -ENOMEM;
+ goto err_free;
+ }
+
+ new_fltr->sw_id = (u16)bit_id;
+ new_fltr->flow_id = flow_id;
+ new_fltr->rxq = rxq_index;
+ hlist_add_head_rcu(&new_fltr->hash, head);
+ bp->ntp_fltr_count++;
+ spin_unlock_bh(&bp->ntp_fltr_lock);
+
+ set_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+
+ return new_fltr->sw_id;
+
+err_free:
+ kfree(new_fltr);
+ return rc;
+}
+
+static void bnxt_cfg_ntp_filters(struct bnxt *bp)
+{
+ int i;
+
+ for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
+ struct hlist_head *head;
+ struct hlist_node *tmp;
+ struct bnxt_ntuple_filter *fltr;
+ int rc;
+
+ head = &bp->ntp_fltr_hash_tbl[i];
+ hlist_for_each_entry_safe(fltr, tmp, head, hash) {
+ bool del = false;
+
+ if (test_bit(BNXT_FLTR_VALID, &fltr->state)) {
+ if (rps_may_expire_flow(bp->dev, fltr->rxq,
+ fltr->flow_id,
+ fltr->sw_id)) {
+ bnxt_hwrm_cfa_ntuple_filter_free(bp,
+ fltr);
+ del = true;
+ }
+ } else {
+ rc = bnxt_hwrm_cfa_ntuple_filter_alloc(bp,
+ fltr);
+ if (rc)
+ del = true;
+ else
+ set_bit(BNXT_FLTR_VALID, &fltr->state);
+ }
+
+ if (del) {
+ spin_lock_bh(&bp->ntp_fltr_lock);
+ hlist_del_rcu(&fltr->hash);
+ bp->ntp_fltr_count--;
+ spin_unlock_bh(&bp->ntp_fltr_lock);
+ synchronize_rcu();
+ clear_bit(fltr->sw_id, bp->ntp_fltr_bmap);
+ kfree(fltr);
+ }
+ }
+ }
+}
+
+#else
+
+static void bnxt_cfg_ntp_filters(struct bnxt *bp)
+{
+}
+
+#endif /* CONFIG_RFS_ACCEL */
+
+static void bnxt_add_vxlan_port(struct net_device *dev, sa_family_t sa_family,
+ __be16 port)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return;
+
+ if (sa_family != AF_INET6 && sa_family != AF_INET)
+ return;
+
+ if (bp->vxlan_port_cnt && bp->vxlan_port != port)
+ return;
+
+ bp->vxlan_port_cnt++;
+ if (bp->vxlan_port_cnt == 1) {
+ bp->vxlan_port = port;
+ set_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+ }
+}
+
+static void bnxt_del_vxlan_port(struct net_device *dev, sa_family_t sa_family,
+ __be16 port)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return;
+
+ if (sa_family != AF_INET6 && sa_family != AF_INET)
+ return;
+
+ if (bp->vxlan_port_cnt && bp->vxlan_port == port) {
+ bp->vxlan_port_cnt--;
+
+ if (bp->vxlan_port_cnt == 0) {
+ set_bit(BNXT_VXLAN_DEL_PORT_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+ }
+ }
+}
+
+static const struct net_device_ops bnxt_netdev_ops = {
+ .ndo_open = bnxt_open,
+ .ndo_start_xmit = bnxt_start_xmit,
+ .ndo_stop = bnxt_close,
+ .ndo_get_stats64 = bnxt_get_stats64,
+ .ndo_set_rx_mode = bnxt_set_rx_mode,
+ .ndo_do_ioctl = bnxt_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = bnxt_change_mac_addr,
+ .ndo_change_mtu = bnxt_change_mtu,
+ .ndo_fix_features = bnxt_fix_features,
+ .ndo_set_features = bnxt_set_features,
+ .ndo_tx_timeout = bnxt_tx_timeout,
+#ifdef CONFIG_BNXT_SRIOV
+ .ndo_get_vf_config = bnxt_get_vf_config,
+ .ndo_set_vf_mac = bnxt_set_vf_mac,
+ .ndo_set_vf_vlan = bnxt_set_vf_vlan,
+ .ndo_set_vf_rate = bnxt_set_vf_bw,
+ .ndo_set_vf_link_state = bnxt_set_vf_link_state,
+ .ndo_set_vf_spoofchk = bnxt_set_vf_spoofchk,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = bnxt_poll_controller,
+#endif
+ .ndo_setup_tc = bnxt_setup_tc,
+#ifdef CONFIG_RFS_ACCEL
+ .ndo_rx_flow_steer = bnxt_rx_flow_steer,
+#endif
+ .ndo_add_vxlan_port = bnxt_add_vxlan_port,
+ .ndo_del_vxlan_port = bnxt_del_vxlan_port,
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = bnxt_busy_poll,
+#endif
+};
+
+static void bnxt_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (BNXT_PF(bp))
+ bnxt_sriov_disable(bp);
+
+ unregister_netdev(dev);
+ cancel_work_sync(&bp->sp_task);
+ bp->sp_event = 0;
+
+ bnxt_free_hwrm_resources(bp);
+ pci_iounmap(pdev, bp->bar2);
+ pci_iounmap(pdev, bp->bar1);
+ pci_iounmap(pdev, bp->bar0);
+ free_netdev(dev);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static int bnxt_probe_phy(struct bnxt *bp)
+{
+ int rc = 0;
+ struct bnxt_link_info *link_info = &bp->link_info;
+ char phy_ver[PHY_VER_STR_LEN];
+
+ rc = bnxt_update_link(bp, false);
+ if (rc) {
+ netdev_err(bp->dev, "Probe phy can't update link (rc: %x)\n",
+ rc);
+ return rc;
+ }
+
+ /*initialize the ethool setting copy with NVM settings */
+ if (BNXT_AUTO_MODE(link_info->auto_mode))
+ link_info->autoneg |= BNXT_AUTONEG_SPEED;
+
+ if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) {
+ if (link_info->auto_pause_setting == BNXT_LINK_PAUSE_BOTH)
+ link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ link_info->req_flow_ctrl = link_info->auto_pause_setting;
+ } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) {
+ link_info->req_flow_ctrl = link_info->force_pause_setting;
+ }
+ link_info->req_duplex = link_info->duplex_setting;
+ if (link_info->autoneg & BNXT_AUTONEG_SPEED)
+ link_info->req_link_speed = link_info->auto_link_speed;
+ else
+ link_info->req_link_speed = link_info->force_link_speed;
+ link_info->advertising = link_info->auto_link_speeds;
+ snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d",
+ link_info->phy_ver[0],
+ link_info->phy_ver[1],
+ link_info->phy_ver[2]);
+ strcat(bp->fw_ver_str, phy_ver);
+ return rc;
+}
+
+static int bnxt_get_max_irq(struct pci_dev *pdev)
+{
+ u16 ctrl;
+
+ if (!pdev->msix_cap)
+ return 1;
+
+ pci_read_config_word(pdev, pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
+ return (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1;
+}
+
+void bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx)
+{
+ int max_rings = 0;
+
+ if (BNXT_PF(bp)) {
+ *max_tx = bp->pf.max_pf_tx_rings;
+ *max_rx = bp->pf.max_pf_rx_rings;
+ max_rings = min_t(int, bp->pf.max_irqs, bp->pf.max_cp_rings);
+ max_rings = min_t(int, max_rings, bp->pf.max_stat_ctxs);
+ } else {
+#ifdef CONFIG_BNXT_SRIOV
+ *max_tx = bp->vf.max_tx_rings;
+ *max_rx = bp->vf.max_rx_rings;
+ max_rings = min_t(int, bp->vf.max_irqs, bp->vf.max_cp_rings);
+ max_rings = min_t(int, max_rings, bp->vf.max_stat_ctxs);
+#endif
+ }
+ if (bp->flags & BNXT_FLAG_AGG_RINGS)
+ *max_rx >>= 1;
+
+ *max_rx = min_t(int, *max_rx, max_rings);
+ *max_tx = min_t(int, *max_tx, max_rings);
+}
+
+static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int version_printed;
+ struct net_device *dev;
+ struct bnxt *bp;
+ int rc, max_rx_rings, max_tx_rings, max_irqs, dflt_rings;
+
+ if (version_printed++ == 0)
+ pr_info("%s", version);
+
+ max_irqs = bnxt_get_max_irq(pdev);
+ dev = alloc_etherdev_mq(sizeof(*bp), max_irqs);
+ if (!dev)
+ return -ENOMEM;
+
+ bp = netdev_priv(dev);
+
+ if (bnxt_vf_pciid(ent->driver_data))
+ bp->flags |= BNXT_FLAG_VF;
+
+ if (pdev->msix_cap) {
+ bp->flags |= BNXT_FLAG_MSIX_CAP;
+ if (BNXT_PF(bp))
+ bp->flags |= BNXT_FLAG_RFS;
+ }
+
+ rc = bnxt_init_board(pdev, dev);
+ if (rc < 0)
+ goto init_err_free;
+
+ dev->netdev_ops = &bnxt_netdev_ops;
+ dev->watchdog_timeo = BNXT_TX_TIMEOUT;
+ dev->ethtool_ops = &bnxt_ethtool_ops;
+
+ pci_set_drvdata(pdev, dev);
+
+ dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
+ NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
+ NETIF_F_RXHASH |
+ NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO;
+
+ if (bp->flags & BNXT_FLAG_RFS)
+ dev->hw_features |= NETIF_F_NTUPLE;
+
+ dev->hw_enc_features =
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
+ NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT;
+ dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA;
+ dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX;
+ dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
+ dev->priv_flags |= IFF_UNICAST_FLT;
+
+#ifdef CONFIG_BNXT_SRIOV
+ init_waitqueue_head(&bp->sriov_cfg_wait);
+#endif
+ rc = bnxt_alloc_hwrm_resources(bp);
+ if (rc)
+ goto init_err;
+
+ mutex_init(&bp->hwrm_cmd_lock);
+ bnxt_hwrm_ver_get(bp);
+
+ rc = bnxt_hwrm_func_drv_rgtr(bp);
+ if (rc)
+ goto init_err;
+
+ /* Get the MAX capabilities for this function */
+ rc = bnxt_hwrm_func_qcaps(bp);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm query capability failure rc: %x\n",
+ rc);
+ rc = -1;
+ goto init_err;
+ }
+
+ rc = bnxt_hwrm_queue_qportcfg(bp);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm query qportcfg failure rc: %x\n",
+ rc);
+ rc = -1;
+ goto init_err;
+ }
+
+ bnxt_set_tpa_flags(bp);
+ bnxt_set_ring_params(bp);
+ dflt_rings = netif_get_num_default_rss_queues();
+ if (BNXT_PF(bp)) {
+ memcpy(dev->dev_addr, bp->pf.mac_addr, ETH_ALEN);
+ bp->pf.max_irqs = max_irqs;
+ } else {
+#if defined(CONFIG_BNXT_SRIOV)
+ memcpy(dev->dev_addr, bp->vf.mac_addr, ETH_ALEN);
+ bp->vf.max_irqs = max_irqs;
+#endif
+ }
+ bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings);
+ bp->rx_nr_rings = min_t(int, dflt_rings, max_rx_rings);
+ bp->tx_nr_rings_per_tc = min_t(int, dflt_rings, max_tx_rings);
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc;
+ bp->cp_nr_rings = max_t(int, bp->rx_nr_rings, bp->tx_nr_rings);
+ bp->num_stat_ctxs = bp->cp_nr_rings;
+
+ if (dev->hw_features & NETIF_F_HW_VLAN_CTAG_RX)
+ bp->flags |= BNXT_FLAG_STRIP_VLAN;
+
+ rc = bnxt_probe_phy(bp);
+ if (rc)
+ goto init_err;
+
+ rc = register_netdev(dev);
+ if (rc)
+ goto init_err;
+
+ netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
+ board_info[ent->driver_data].name,
+ (long)pci_resource_start(pdev, 0), dev->dev_addr);
+
+ return 0;
+
+init_err:
+ pci_iounmap(pdev, bp->bar0);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+init_err_free:
+ free_netdev(dev);
+ return rc;
+}
+
+static struct pci_driver bnxt_pci_driver = {
+ .name = DRV_MODULE_NAME,
+ .id_table = bnxt_pci_tbl,
+ .probe = bnxt_init_one,
+ .remove = bnxt_remove_one,
+#if defined(CONFIG_BNXT_SRIOV)
+ .sriov_configure = bnxt_sriov_configure,
+#endif
+};
+
+module_pci_driver(bnxt_pci_driver);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
new file mode 100644
index 000000000000..674bc5159b91
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -0,0 +1,1092 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#ifndef BNXT_H
+#define BNXT_H
+
+#define DRV_MODULE_NAME "bnxt_en"
+#define DRV_MODULE_VERSION "0.1.24"
+
+#define DRV_VER_MAJ 0
+#define DRV_VER_MIN 1
+#define DRV_VER_UPD 24
+
+struct tx_bd {
+ __le32 tx_bd_len_flags_type;
+ #define TX_BD_TYPE (0x3f << 0)
+ #define TX_BD_TYPE_SHORT_TX_BD (0x00 << 0)
+ #define TX_BD_TYPE_LONG_TX_BD (0x10 << 0)
+ #define TX_BD_FLAGS_PACKET_END (1 << 6)
+ #define TX_BD_FLAGS_NO_CMPL (1 << 7)
+ #define TX_BD_FLAGS_BD_CNT (0x1f << 8)
+ #define TX_BD_FLAGS_BD_CNT_SHIFT 8
+ #define TX_BD_FLAGS_LHINT (3 << 13)
+ #define TX_BD_FLAGS_LHINT_SHIFT 13
+ #define TX_BD_FLAGS_LHINT_512_AND_SMALLER (0 << 13)
+ #define TX_BD_FLAGS_LHINT_512_TO_1023 (1 << 13)
+ #define TX_BD_FLAGS_LHINT_1024_TO_2047 (2 << 13)
+ #define TX_BD_FLAGS_LHINT_2048_AND_LARGER (3 << 13)
+ #define TX_BD_FLAGS_COAL_NOW (1 << 15)
+ #define TX_BD_LEN (0xffff << 16)
+ #define TX_BD_LEN_SHIFT 16
+
+ u32 tx_bd_opaque;
+ __le64 tx_bd_haddr;
+} __packed;
+
+struct tx_bd_ext {
+ __le32 tx_bd_hsize_lflags;
+ #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0)
+ #define TX_BD_FLAGS_IP_CKSUM (1 << 1)
+ #define TX_BD_FLAGS_NO_CRC (1 << 2)
+ #define TX_BD_FLAGS_STAMP (1 << 3)
+ #define TX_BD_FLAGS_T_IP_CHKSUM (1 << 4)
+ #define TX_BD_FLAGS_LSO (1 << 5)
+ #define TX_BD_FLAGS_IPID_FMT (1 << 6)
+ #define TX_BD_FLAGS_T_IPID (1 << 7)
+ #define TX_BD_HSIZE (0xff << 16)
+ #define TX_BD_HSIZE_SHIFT 16
+
+ __le32 tx_bd_mss;
+ __le32 tx_bd_cfa_action;
+ #define TX_BD_CFA_ACTION (0xffff << 16)
+ #define TX_BD_CFA_ACTION_SHIFT 16
+
+ __le32 tx_bd_cfa_meta;
+ #define TX_BD_CFA_META_MASK 0xfffffff
+ #define TX_BD_CFA_META_VID_MASK 0xfff
+ #define TX_BD_CFA_META_PRI_MASK (0xf << 12)
+ #define TX_BD_CFA_META_PRI_SHIFT 12
+ #define TX_BD_CFA_META_TPID_MASK (3 << 16)
+ #define TX_BD_CFA_META_TPID_SHIFT 16
+ #define TX_BD_CFA_META_KEY (0xf << 28)
+ #define TX_BD_CFA_META_KEY_SHIFT 28
+ #define TX_BD_CFA_META_KEY_VLAN (1 << 28)
+};
+
+struct rx_bd {
+ __le32 rx_bd_len_flags_type;
+ #define RX_BD_TYPE (0x3f << 0)
+ #define RX_BD_TYPE_RX_PACKET_BD 0x4
+ #define RX_BD_TYPE_RX_BUFFER_BD 0x5
+ #define RX_BD_TYPE_RX_AGG_BD 0x6
+ #define RX_BD_TYPE_16B_BD_SIZE (0 << 4)
+ #define RX_BD_TYPE_32B_BD_SIZE (1 << 4)
+ #define RX_BD_TYPE_48B_BD_SIZE (2 << 4)
+ #define RX_BD_TYPE_64B_BD_SIZE (3 << 4)
+ #define RX_BD_FLAGS_SOP (1 << 6)
+ #define RX_BD_FLAGS_EOP (1 << 7)
+ #define RX_BD_FLAGS_BUFFERS (3 << 8)
+ #define RX_BD_FLAGS_1_BUFFER_PACKET (0 << 8)
+ #define RX_BD_FLAGS_2_BUFFER_PACKET (1 << 8)
+ #define RX_BD_FLAGS_3_BUFFER_PACKET (2 << 8)
+ #define RX_BD_FLAGS_4_BUFFER_PACKET (3 << 8)
+ #define RX_BD_LEN (0xffff << 16)
+ #define RX_BD_LEN_SHIFT 16
+
+ u32 rx_bd_opaque;
+ __le64 rx_bd_haddr;
+};
+
+struct tx_cmp {
+ __le32 tx_cmp_flags_type;
+ #define CMP_TYPE (0x3f << 0)
+ #define CMP_TYPE_TX_L2_CMP 0
+ #define CMP_TYPE_RX_L2_CMP 17
+ #define CMP_TYPE_RX_AGG_CMP 18
+ #define CMP_TYPE_RX_L2_TPA_START_CMP 19
+ #define CMP_TYPE_RX_L2_TPA_END_CMP 21
+ #define CMP_TYPE_STATUS_CMP 32
+ #define CMP_TYPE_REMOTE_DRIVER_REQ 34
+ #define CMP_TYPE_REMOTE_DRIVER_RESP 36
+ #define CMP_TYPE_ERROR_STATUS 48
+ #define CMPL_BASE_TYPE_STAT_EJECT (0x1aUL << 0)
+ #define CMPL_BASE_TYPE_HWRM_DONE (0x20UL << 0)
+ #define CMPL_BASE_TYPE_HWRM_FWD_REQ (0x22UL << 0)
+ #define CMPL_BASE_TYPE_HWRM_FWD_RESP (0x24UL << 0)
+ #define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+
+ #define TX_CMP_FLAGS_ERROR (1 << 6)
+ #define TX_CMP_FLAGS_PUSH (1 << 7)
+
+ u32 tx_cmp_opaque;
+ __le32 tx_cmp_errors_v;
+ #define TX_CMP_V (1 << 0)
+ #define TX_CMP_ERRORS_BUFFER_ERROR (7 << 1)
+ #define TX_CMP_ERRORS_BUFFER_ERROR_NO_ERROR 0
+ #define TX_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT 2
+ #define TX_CMP_ERRORS_BUFFER_ERROR_INVALID_STAG 4
+ #define TX_CMP_ERRORS_BUFFER_ERROR_STAG_BOUNDS 5
+ #define TX_CMP_ERRORS_ZERO_LENGTH_PKT (1 << 4)
+ #define TX_CMP_ERRORS_EXCESSIVE_BD_LEN (1 << 5)
+ #define TX_CMP_ERRORS_DMA_ERROR (1 << 6)
+ #define TX_CMP_ERRORS_HINT_TOO_SHORT (1 << 7)
+
+ __le32 tx_cmp_unsed_3;
+};
+
+struct rx_cmp {
+ __le32 rx_cmp_len_flags_type;
+ #define RX_CMP_CMP_TYPE (0x3f << 0)
+ #define RX_CMP_FLAGS_ERROR (1 << 6)
+ #define RX_CMP_FLAGS_PLACEMENT (7 << 7)
+ #define RX_CMP_FLAGS_RSS_VALID (1 << 10)
+ #define RX_CMP_FLAGS_UNUSED (1 << 11)
+ #define RX_CMP_FLAGS_ITYPES_SHIFT 12
+ #define RX_CMP_FLAGS_ITYPE_UNKNOWN (0 << 12)
+ #define RX_CMP_FLAGS_ITYPE_IP (1 << 12)
+ #define RX_CMP_FLAGS_ITYPE_TCP (2 << 12)
+ #define RX_CMP_FLAGS_ITYPE_UDP (3 << 12)
+ #define RX_CMP_FLAGS_ITYPE_FCOE (4 << 12)
+ #define RX_CMP_FLAGS_ITYPE_ROCE (5 << 12)
+ #define RX_CMP_FLAGS_ITYPE_PTP_WO_TS (8 << 12)
+ #define RX_CMP_FLAGS_ITYPE_PTP_W_TS (9 << 12)
+ #define RX_CMP_LEN (0xffff << 16)
+ #define RX_CMP_LEN_SHIFT 16
+
+ u32 rx_cmp_opaque;
+ __le32 rx_cmp_misc_v1;
+ #define RX_CMP_V1 (1 << 0)
+ #define RX_CMP_AGG_BUFS (0x1f << 1)
+ #define RX_CMP_AGG_BUFS_SHIFT 1
+ #define RX_CMP_RSS_HASH_TYPE (0x7f << 9)
+ #define RX_CMP_RSS_HASH_TYPE_SHIFT 9
+ #define RX_CMP_PAYLOAD_OFFSET (0xff << 16)
+ #define RX_CMP_PAYLOAD_OFFSET_SHIFT 16
+
+ __le32 rx_cmp_rss_hash;
+};
+
+#define RX_CMP_HASH_VALID(rxcmp) \
+ ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID))
+
+#define RSS_PROFILE_ID_MASK 0x1f
+
+#define RX_CMP_HASH_TYPE(rxcmp) \
+ (((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\
+ RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK)
+
+struct rx_cmp_ext {
+ __le32 rx_cmp_flags2;
+ #define RX_CMP_FLAGS2_IP_CS_CALC 0x1
+ #define RX_CMP_FLAGS2_L4_CS_CALC (0x1 << 1)
+ #define RX_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2)
+ #define RX_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3)
+ #define RX_CMP_FLAGS2_META_FORMAT_VLAN (0x1 << 4)
+ __le32 rx_cmp_meta_data;
+ #define RX_CMP_FLAGS2_METADATA_VID_MASK 0xfff
+ #define RX_CMP_FLAGS2_METADATA_TPID_MASK 0xffff0000
+ #define RX_CMP_FLAGS2_METADATA_TPID_SFT 16
+ __le32 rx_cmp_cfa_code_errors_v2;
+ #define RX_CMP_V (1 << 0)
+ #define RX_CMPL_ERRORS_MASK (0x7fff << 1)
+ #define RX_CMPL_ERRORS_SFT 1
+ #define RX_CMPL_ERRORS_BUFFER_ERROR_MASK (0x7 << 1)
+ #define RX_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1)
+ #define RX_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT (0x1 << 1)
+ #define RX_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1)
+ #define RX_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1)
+ #define RX_CMPL_ERRORS_IP_CS_ERROR (0x1 << 4)
+ #define RX_CMPL_ERRORS_L4_CS_ERROR (0x1 << 5)
+ #define RX_CMPL_ERRORS_T_IP_CS_ERROR (0x1 << 6)
+ #define RX_CMPL_ERRORS_T_L4_CS_ERROR (0x1 << 7)
+ #define RX_CMPL_ERRORS_CRC_ERROR (0x1 << 8)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_MASK (0x7 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR (0x0 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (0x1 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (0x2 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR (0x3 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (0x4 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (0x5 << 9)
+ #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (0x6 << 9)
+ #define RX_CMPL_ERRORS_PKT_ERROR_MASK (0xf << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_NO_ERROR (0x0 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION (0x1 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (0x2 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL (0x3 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (0x4 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (0x5 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (0x6 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (0x7 << 12)
+ #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (0x8 << 12)
+
+ #define RX_CMPL_CFA_CODE_MASK (0xffff << 16)
+ #define RX_CMPL_CFA_CODE_SFT 16
+
+ __le32 rx_cmp_unused3;
+};
+
+#define RX_CMP_L2_ERRORS \
+ cpu_to_le32(RX_CMPL_ERRORS_BUFFER_ERROR_MASK | RX_CMPL_ERRORS_CRC_ERROR)
+
+#define RX_CMP_L4_CS_BITS \
+ (cpu_to_le32(RX_CMP_FLAGS2_L4_CS_CALC | RX_CMP_FLAGS2_T_L4_CS_CALC))
+
+#define RX_CMP_L4_CS_ERR_BITS \
+ (cpu_to_le32(RX_CMPL_ERRORS_L4_CS_ERROR | RX_CMPL_ERRORS_T_L4_CS_ERROR))
+
+#define RX_CMP_L4_CS_OK(rxcmp1) \
+ (((rxcmp1)->rx_cmp_flags2 & RX_CMP_L4_CS_BITS) && \
+ !((rxcmp1)->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS))
+
+#define RX_CMP_ENCAP(rxcmp1) \
+ ((le32_to_cpu((rxcmp1)->rx_cmp_flags2) & \
+ RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3)
+
+struct rx_agg_cmp {
+ __le32 rx_agg_cmp_len_flags_type;
+ #define RX_AGG_CMP_TYPE (0x3f << 0)
+ #define RX_AGG_CMP_LEN (0xffff << 16)
+ #define RX_AGG_CMP_LEN_SHIFT 16
+ u32 rx_agg_cmp_opaque;
+ __le32 rx_agg_cmp_v;
+ #define RX_AGG_CMP_V (1 << 0)
+ __le32 rx_agg_cmp_unused;
+};
+
+struct rx_tpa_start_cmp {
+ __le32 rx_tpa_start_cmp_len_flags_type;
+ #define RX_TPA_START_CMP_TYPE (0x3f << 0)
+ #define RX_TPA_START_CMP_FLAGS (0x3ff << 6)
+ #define RX_TPA_START_CMP_FLAGS_SHIFT 6
+ #define RX_TPA_START_CMP_FLAGS_PLACEMENT (0x7 << 7)
+ #define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7
+ #define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7)
+ #define RX_TPA_START_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7)
+ #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7)
+ #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7)
+ #define RX_TPA_START_CMP_FLAGS_RSS_VALID (0x1 << 10)
+ #define RX_TPA_START_CMP_FLAGS_ITYPES (0xf << 12)
+ #define RX_TPA_START_CMP_FLAGS_ITYPES_SHIFT 12
+ #define RX_TPA_START_CMP_FLAGS_ITYPE_TCP (0x2 << 12)
+ #define RX_TPA_START_CMP_LEN (0xffff << 16)
+ #define RX_TPA_START_CMP_LEN_SHIFT 16
+
+ u32 rx_tpa_start_cmp_opaque;
+ __le32 rx_tpa_start_cmp_misc_v1;
+ #define RX_TPA_START_CMP_V1 (0x1 << 0)
+ #define RX_TPA_START_CMP_RSS_HASH_TYPE (0x7f << 9)
+ #define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9
+ #define RX_TPA_START_CMP_AGG_ID (0x7f << 25)
+ #define RX_TPA_START_CMP_AGG_ID_SHIFT 25
+
+ __le32 rx_tpa_start_cmp_rss_hash;
+};
+
+#define TPA_START_HASH_VALID(rx_tpa_start) \
+ ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \
+ cpu_to_le32(RX_TPA_START_CMP_FLAGS_RSS_VALID))
+
+#define TPA_START_HASH_TYPE(rx_tpa_start) \
+ (((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \
+ RX_TPA_START_CMP_RSS_HASH_TYPE) >> \
+ RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK)
+
+#define TPA_START_AGG_ID(rx_tpa_start) \
+ ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \
+ RX_TPA_START_CMP_AGG_ID) >> RX_TPA_START_CMP_AGG_ID_SHIFT)
+
+struct rx_tpa_start_cmp_ext {
+ __le32 rx_tpa_start_cmp_flags2;
+ #define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC (0x1 << 0)
+ #define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC (0x1 << 1)
+ #define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2)
+ #define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3)
+
+ __le32 rx_tpa_start_cmp_metadata;
+ __le32 rx_tpa_start_cmp_cfa_code_v2;
+ #define RX_TPA_START_CMP_V2 (0x1 << 0)
+ #define RX_TPA_START_CMP_CFA_CODE (0xffff << 16)
+ #define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16
+ __le32 rx_tpa_start_cmp_unused5;
+};
+
+struct rx_tpa_end_cmp {
+ __le32 rx_tpa_end_cmp_len_flags_type;
+ #define RX_TPA_END_CMP_TYPE (0x3f << 0)
+ #define RX_TPA_END_CMP_FLAGS (0x3ff << 6)
+ #define RX_TPA_END_CMP_FLAGS_SHIFT 6
+ #define RX_TPA_END_CMP_FLAGS_PLACEMENT (0x7 << 7)
+ #define RX_TPA_END_CMP_FLAGS_PLACEMENT_SHIFT 7
+ #define RX_TPA_END_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7)
+ #define RX_TPA_END_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7)
+ #define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7)
+ #define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7)
+ #define RX_TPA_END_CMP_FLAGS_RSS_VALID (0x1 << 10)
+ #define RX_TPA_END_CMP_FLAGS_ITYPES (0xf << 12)
+ #define RX_TPA_END_CMP_FLAGS_ITYPES_SHIFT 12
+ #define RX_TPA_END_CMP_FLAGS_ITYPE_TCP (0x2 << 12)
+ #define RX_TPA_END_CMP_LEN (0xffff << 16)
+ #define RX_TPA_END_CMP_LEN_SHIFT 16
+
+ u32 rx_tpa_end_cmp_opaque;
+ __le32 rx_tpa_end_cmp_misc_v1;
+ #define RX_TPA_END_CMP_V1 (0x1 << 0)
+ #define RX_TPA_END_CMP_AGG_BUFS (0x3f << 1)
+ #define RX_TPA_END_CMP_AGG_BUFS_SHIFT 1
+ #define RX_TPA_END_CMP_TPA_SEGS (0xff << 8)
+ #define RX_TPA_END_CMP_TPA_SEGS_SHIFT 8
+ #define RX_TPA_END_CMP_PAYLOAD_OFFSET (0xff << 16)
+ #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16
+ #define RX_TPA_END_CMP_AGG_ID (0x7f << 25)
+ #define RX_TPA_END_CMP_AGG_ID_SHIFT 25
+
+ __le32 rx_tpa_end_cmp_tsdelta;
+ #define RX_TPA_END_GRO_TS (0x1 << 31)
+};
+
+#define TPA_END_AGG_ID(rx_tpa_end) \
+ ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \
+ RX_TPA_END_CMP_AGG_ID) >> RX_TPA_END_CMP_AGG_ID_SHIFT)
+
+#define TPA_END_TPA_SEGS(rx_tpa_end) \
+ ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \
+ RX_TPA_END_CMP_TPA_SEGS) >> RX_TPA_END_CMP_TPA_SEGS_SHIFT)
+
+#define RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO \
+ cpu_to_le32(RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO & \
+ RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS)
+
+#define TPA_END_GRO(rx_tpa_end) \
+ ((rx_tpa_end)->rx_tpa_end_cmp_len_flags_type & \
+ RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO)
+
+#define TPA_END_GRO_TS(rx_tpa_end) \
+ ((rx_tpa_end)->rx_tpa_end_cmp_tsdelta & cpu_to_le32(RX_TPA_END_GRO_TS))
+
+struct rx_tpa_end_cmp_ext {
+ __le32 rx_tpa_end_cmp_dup_acks;
+ #define RX_TPA_END_CMP_TPA_DUP_ACKS (0xf << 0)
+
+ __le32 rx_tpa_end_cmp_seg_len;
+ #define RX_TPA_END_CMP_TPA_SEG_LEN (0xffff << 0)
+
+ __le32 rx_tpa_end_cmp_errors_v2;
+ #define RX_TPA_END_CMP_V2 (0x1 << 0)
+ #define RX_TPA_END_CMP_ERRORS (0x7fff << 1)
+ #define RX_TPA_END_CMPL_ERRORS_SHIFT 1
+
+ u32 rx_tpa_end_cmp_start_opaque;
+};
+
+#define DB_IDX_MASK 0xffffff
+#define DB_IDX_VALID (0x1 << 26)
+#define DB_IRQ_DIS (0x1 << 27)
+#define DB_KEY_TX (0x0 << 28)
+#define DB_KEY_RX (0x1 << 28)
+#define DB_KEY_CP (0x2 << 28)
+#define DB_KEY_ST (0x3 << 28)
+#define DB_KEY_TX_PUSH (0x4 << 28)
+#define DB_LONG_TX_PUSH (0x2 << 24)
+
+#define INVALID_HW_RING_ID ((u16)-1)
+
+#define BNXT_RSS_HASH_TYPE_FLAG_IPV4 0x01
+#define BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV4 0x02
+#define BNXT_RSS_HASH_TYPE_FLAG_IPV6 0x04
+#define BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV6 0x08
+
+/* The hardware supports certain page sizes. Use the supported page sizes
+ * to allocate the rings.
+ */
+#if (PAGE_SHIFT < 12)
+#define BNXT_PAGE_SHIFT 12
+#elif (PAGE_SHIFT <= 13)
+#define BNXT_PAGE_SHIFT PAGE_SHIFT
+#elif (PAGE_SHIFT < 16)
+#define BNXT_PAGE_SHIFT 13
+#else
+#define BNXT_PAGE_SHIFT 16
+#endif
+
+#define BNXT_PAGE_SIZE (1 << BNXT_PAGE_SHIFT)
+
+#define BNXT_MIN_PKT_SIZE 45
+
+#define BNXT_NUM_TESTS(bp) 0
+
+#define BNXT_DEFAULT_RX_RING_SIZE 1023
+#define BNXT_DEFAULT_TX_RING_SIZE 512
+
+#define MAX_TPA 64
+
+#define MAX_RX_PAGES 8
+#define MAX_RX_AGG_PAGES 32
+#define MAX_TX_PAGES 8
+#define MAX_CP_PAGES 64
+
+#define RX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct rx_bd))
+#define TX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct tx_bd))
+#define CP_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct tx_cmp))
+
+#define SW_RXBD_RING_SIZE (sizeof(struct bnxt_sw_rx_bd) * RX_DESC_CNT)
+#define HW_RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
+
+#define SW_RXBD_AGG_RING_SIZE (sizeof(struct bnxt_sw_rx_agg_bd) * RX_DESC_CNT)
+
+#define SW_TXBD_RING_SIZE (sizeof(struct bnxt_sw_tx_bd) * TX_DESC_CNT)
+#define HW_TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
+
+#define HW_CMPD_RING_SIZE (sizeof(struct tx_cmp) * CP_DESC_CNT)
+
+#define BNXT_MAX_RX_DESC_CNT (RX_DESC_CNT * MAX_RX_PAGES - 1)
+#define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1)
+#define BNXT_MAX_TX_DESC_CNT (TX_DESC_CNT * MAX_TX_PAGES - 1)
+
+#define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4))
+#define RX_IDX(x) ((x) & (RX_DESC_CNT - 1))
+
+#define TX_RING(x) (((x) & ~(TX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4))
+#define TX_IDX(x) ((x) & (TX_DESC_CNT - 1))
+
+#define CP_RING(x) (((x) & ~(CP_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4))
+#define CP_IDX(x) ((x) & (CP_DESC_CNT - 1))
+
+#define TX_CMP_VALID(txcmp, raw_cons) \
+ (!!((txcmp)->tx_cmp_errors_v & cpu_to_le32(TX_CMP_V)) == \
+ !((raw_cons) & bp->cp_bit))
+
+#define RX_CMP_VALID(rxcmp1, raw_cons) \
+ (!!((rxcmp1)->rx_cmp_cfa_code_errors_v2 & cpu_to_le32(RX_CMP_V)) ==\
+ !((raw_cons) & bp->cp_bit))
+
+#define RX_AGG_CMP_VALID(agg, raw_cons) \
+ (!!((agg)->rx_agg_cmp_v & cpu_to_le32(RX_AGG_CMP_V)) == \
+ !((raw_cons) & bp->cp_bit))
+
+#define TX_CMP_TYPE(txcmp) \
+ (le32_to_cpu((txcmp)->tx_cmp_flags_type) & CMP_TYPE)
+
+#define RX_CMP_TYPE(rxcmp) \
+ (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_CMP_TYPE)
+
+#define NEXT_RX(idx) (((idx) + 1) & bp->rx_ring_mask)
+
+#define NEXT_RX_AGG(idx) (((idx) + 1) & bp->rx_agg_ring_mask)
+
+#define NEXT_TX(idx) (((idx) + 1) & bp->tx_ring_mask)
+
+#define ADV_RAW_CMP(idx, n) ((idx) + (n))
+#define NEXT_RAW_CMP(idx) ADV_RAW_CMP(idx, 1)
+#define RING_CMP(idx) ((idx) & bp->cp_ring_mask)
+#define NEXT_CMP(idx) RING_CMP(ADV_RAW_CMP(idx, 1))
+
+#define HWRM_CMD_TIMEOUT 500
+#define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4)
+#define HWRM_RESP_ERR_CODE_MASK 0xffff
+#define HWRM_RESP_LEN_MASK 0xffff0000
+#define HWRM_RESP_LEN_SFT 16
+#define HWRM_RESP_VALID_MASK 0xff000000
+#define BNXT_HWRM_REQ_MAX_SIZE 128
+#define BNXT_HWRM_REQS_PER_PAGE (BNXT_PAGE_SIZE / \
+ BNXT_HWRM_REQ_MAX_SIZE)
+
+struct bnxt_sw_tx_bd {
+ struct sk_buff *skb;
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+ u8 is_gso;
+ u8 is_push;
+ unsigned short nr_frags;
+};
+
+struct bnxt_sw_rx_bd {
+ u8 *data;
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+};
+
+struct bnxt_sw_rx_agg_bd {
+ struct page *page;
+ dma_addr_t mapping;
+};
+
+struct bnxt_ring_struct {
+ int nr_pages;
+ int page_size;
+ void **pg_arr;
+ dma_addr_t *dma_arr;
+
+ __le64 *pg_tbl;
+ dma_addr_t pg_tbl_map;
+
+ int vmem_size;
+ void **vmem;
+
+ u16 fw_ring_id; /* Ring id filled by Chimp FW */
+ u8 queue_id;
+};
+
+struct tx_push_bd {
+ __le32 doorbell;
+ struct tx_bd txbd1;
+ struct tx_bd_ext txbd2;
+};
+
+struct bnxt_tx_ring_info {
+ u16 tx_prod;
+ u16 tx_cons;
+ void __iomem *tx_doorbell;
+
+ struct tx_bd *tx_desc_ring[MAX_TX_PAGES];
+ struct bnxt_sw_tx_bd *tx_buf_ring;
+
+ dma_addr_t tx_desc_mapping[MAX_TX_PAGES];
+
+ struct tx_push_bd *tx_push;
+ dma_addr_t tx_push_mapping;
+
+#define BNXT_DEV_STATE_CLOSING 0x1
+ u32 dev_state;
+
+ struct bnxt_ring_struct tx_ring_struct;
+};
+
+struct bnxt_tpa_info {
+ u8 *data;
+ dma_addr_t mapping;
+ u16 len;
+ unsigned short gso_type;
+ u32 flags2;
+ u32 metadata;
+ enum pkt_hash_types hash_type;
+ u32 rss_hash;
+};
+
+struct bnxt_rx_ring_info {
+ u16 rx_prod;
+ u16 rx_agg_prod;
+ u16 rx_sw_agg_prod;
+ void __iomem *rx_doorbell;
+ void __iomem *rx_agg_doorbell;
+
+ struct rx_bd *rx_desc_ring[MAX_RX_PAGES];
+ struct bnxt_sw_rx_bd *rx_buf_ring;
+
+ struct rx_bd *rx_agg_desc_ring[MAX_RX_AGG_PAGES];
+ struct bnxt_sw_rx_agg_bd *rx_agg_ring;
+
+ unsigned long *rx_agg_bmap;
+ u16 rx_agg_bmap_size;
+
+ dma_addr_t rx_desc_mapping[MAX_RX_PAGES];
+ dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES];
+
+ struct bnxt_tpa_info *rx_tpa;
+
+ struct bnxt_ring_struct rx_ring_struct;
+ struct bnxt_ring_struct rx_agg_ring_struct;
+};
+
+struct bnxt_cp_ring_info {
+ u32 cp_raw_cons;
+ void __iomem *cp_doorbell;
+
+ struct tx_cmp *cp_desc_ring[MAX_CP_PAGES];
+
+ dma_addr_t cp_desc_mapping[MAX_CP_PAGES];
+
+ struct ctx_hw_stats *hw_stats;
+ dma_addr_t hw_stats_map;
+ u32 hw_stats_ctx_id;
+ u64 rx_l4_csum_errors;
+
+ struct bnxt_ring_struct cp_ring_struct;
+};
+
+struct bnxt_napi {
+ struct napi_struct napi;
+ struct bnxt *bp;
+
+ int index;
+ struct bnxt_cp_ring_info cp_ring;
+ struct bnxt_rx_ring_info rx_ring;
+ struct bnxt_tx_ring_info tx_ring;
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ atomic_t poll_state;
+#endif
+};
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+enum bnxt_poll_state_t {
+ BNXT_STATE_IDLE = 0,
+ BNXT_STATE_NAPI,
+ BNXT_STATE_POLL,
+ BNXT_STATE_DISABLE,
+};
+#endif
+
+struct bnxt_irq {
+ irq_handler_t handler;
+ unsigned int vector;
+ u8 requested;
+ char name[IFNAMSIZ + 2];
+};
+
+#define HWRM_RING_ALLOC_TX 0x1
+#define HWRM_RING_ALLOC_RX 0x2
+#define HWRM_RING_ALLOC_AGG 0x4
+#define HWRM_RING_ALLOC_CMPL 0x8
+
+#define INVALID_STATS_CTX_ID -1
+
+struct hwrm_cmd_req_hdr {
+#define HWRM_CMPL_RING_MASK 0xffff0000
+#define HWRM_CMPL_RING_SFT 16
+ __le32 cmpl_ring_req_type;
+#define HWRM_SEQ_ID_MASK 0xffff
+#define HWRM_SEQ_ID_INVALID -1
+#define HWRM_RESP_LEN_OFFSET 4
+#define HWRM_TARGET_FID_MASK 0xffff0000
+#define HWRM_TARGET_FID_SFT 16
+ __le32 target_id_seq_id;
+ __le64 resp_addr;
+};
+
+struct bnxt_ring_grp_info {
+ u16 fw_stats_ctx;
+ u16 fw_grp_id;
+ u16 rx_fw_ring_id;
+ u16 agg_fw_ring_id;
+ u16 cp_fw_ring_id;
+};
+
+struct bnxt_vnic_info {
+ u16 fw_vnic_id; /* returned by Chimp during alloc */
+ u16 fw_rss_cos_lb_ctx;
+ u16 fw_l2_ctx_id;
+#define BNXT_MAX_UC_ADDRS 4
+ __le64 fw_l2_filter_id[BNXT_MAX_UC_ADDRS];
+ /* index 0 always dev_addr */
+ u16 uc_filter_count;
+ u8 *uc_list;
+
+ u16 *fw_grp_ids;
+ u16 hash_type;
+ dma_addr_t rss_table_dma_addr;
+ __le16 *rss_table;
+ dma_addr_t rss_hash_key_dma_addr;
+ u64 *rss_hash_key;
+ u32 rx_mask;
+
+ u8 *mc_list;
+ int mc_list_size;
+ int mc_list_count;
+ dma_addr_t mc_list_mapping;
+#define BNXT_MAX_MC_ADDRS 16
+
+ u32 flags;
+#define BNXT_VNIC_RSS_FLAG 1
+#define BNXT_VNIC_RFS_FLAG 2
+#define BNXT_VNIC_MCAST_FLAG 4
+#define BNXT_VNIC_UCAST_FLAG 8
+};
+
+#if defined(CONFIG_BNXT_SRIOV)
+struct bnxt_vf_info {
+ u16 fw_fid;
+ u8 mac_addr[ETH_ALEN];
+ u16 max_rsscos_ctxs;
+ u16 max_cp_rings;
+ u16 max_tx_rings;
+ u16 max_rx_rings;
+ u16 max_l2_ctxs;
+ u16 max_irqs;
+ u16 max_vnics;
+ u16 max_stat_ctxs;
+ u16 vlan;
+ u32 flags;
+#define BNXT_VF_QOS 0x1
+#define BNXT_VF_SPOOFCHK 0x2
+#define BNXT_VF_LINK_FORCED 0x4
+#define BNXT_VF_LINK_UP 0x8
+ u32 func_flags; /* func cfg flags */
+ u32 min_tx_rate;
+ u32 max_tx_rate;
+ void *hwrm_cmd_req_addr;
+ dma_addr_t hwrm_cmd_req_dma_addr;
+};
+#endif
+
+struct bnxt_pf_info {
+#define BNXT_FIRST_PF_FID 1
+#define BNXT_FIRST_VF_FID 128
+ u32 fw_fid;
+ u8 port_id;
+ u8 mac_addr[ETH_ALEN];
+ u16 max_rsscos_ctxs;
+ u16 max_cp_rings;
+ u16 max_tx_rings; /* HW assigned max tx rings for this PF */
+ u16 max_pf_tx_rings; /* runtime max tx rings owned by PF */
+ u16 max_rx_rings; /* HW assigned max rx rings for this PF */
+ u16 max_pf_rx_rings; /* runtime max rx rings owned by PF */
+ u16 max_irqs;
+ u16 max_l2_ctxs;
+ u16 max_vnics;
+ u16 max_stat_ctxs;
+ u32 first_vf_id;
+ u16 active_vfs;
+ u16 max_vfs;
+ u32 max_encap_records;
+ u32 max_decap_records;
+ u32 max_tx_em_flows;
+ u32 max_tx_wm_flows;
+ u32 max_rx_em_flows;
+ u32 max_rx_wm_flows;
+ unsigned long *vf_event_bmap;
+ u16 hwrm_cmd_req_pages;
+ void *hwrm_cmd_req_addr[4];
+ dma_addr_t hwrm_cmd_req_dma_addr[4];
+ struct bnxt_vf_info *vf;
+};
+
+struct bnxt_ntuple_filter {
+ struct hlist_node hash;
+ u8 src_mac_addr[ETH_ALEN];
+ struct flow_keys fkeys;
+ __le64 filter_id;
+ u16 sw_id;
+ u16 rxq;
+ u32 flow_id;
+ unsigned long state;
+#define BNXT_FLTR_VALID 0
+#define BNXT_FLTR_UPDATE 1
+};
+
+#define BNXT_ALL_COPPER_ETHTOOL_SPEED \
+ (ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full | \
+ ADVERTISED_10000baseT_Full)
+
+struct bnxt_link_info {
+ u8 media_type;
+ u8 transceiver;
+ u8 phy_addr;
+ u8 phy_link_status;
+#define BNXT_LINK_NO_LINK PORT_PHY_QCFG_RESP_LINK_NO_LINK
+#define BNXT_LINK_SIGNAL PORT_PHY_QCFG_RESP_LINK_SIGNAL
+#define BNXT_LINK_LINK PORT_PHY_QCFG_RESP_LINK_LINK
+ u8 wire_speed;
+ u8 loop_back;
+ u8 link_up;
+ u8 duplex;
+#define BNXT_LINK_DUPLEX_HALF PORT_PHY_QCFG_RESP_DUPLEX_HALF
+#define BNXT_LINK_DUPLEX_FULL PORT_PHY_QCFG_RESP_DUPLEX_FULL
+ u8 pause;
+#define BNXT_LINK_PAUSE_TX PORT_PHY_QCFG_RESP_PAUSE_TX
+#define BNXT_LINK_PAUSE_RX PORT_PHY_QCFG_RESP_PAUSE_RX
+#define BNXT_LINK_PAUSE_BOTH (PORT_PHY_QCFG_RESP_PAUSE_RX | \
+ PORT_PHY_QCFG_RESP_PAUSE_TX)
+ u8 auto_pause_setting;
+ u8 force_pause_setting;
+ u8 duplex_setting;
+ u8 auto_mode;
+#define BNXT_AUTO_MODE(mode) ((mode) > BNXT_LINK_AUTO_NONE && \
+ (mode) <= BNXT_LINK_AUTO_MSK)
+#define BNXT_LINK_AUTO_NONE PORT_PHY_QCFG_RESP_AUTO_MODE_NONE
+#define BNXT_LINK_AUTO_ALLSPDS PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS
+#define BNXT_LINK_AUTO_ONESPD PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED
+#define BNXT_LINK_AUTO_ONEORBELOW PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW
+#define BNXT_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_MASK
+#define PHY_VER_LEN 3
+ u8 phy_ver[PHY_VER_LEN];
+ u16 link_speed;
+#define BNXT_LINK_SPEED_100MB PORT_PHY_QCFG_RESP_LINK_SPEED_100MB
+#define BNXT_LINK_SPEED_1GB PORT_PHY_QCFG_RESP_LINK_SPEED_1GB
+#define BNXT_LINK_SPEED_2GB PORT_PHY_QCFG_RESP_LINK_SPEED_2GB
+#define BNXT_LINK_SPEED_2_5GB PORT_PHY_QCFG_RESP_LINK_SPEED_2_5GB
+#define BNXT_LINK_SPEED_10GB PORT_PHY_QCFG_RESP_LINK_SPEED_10GB
+#define BNXT_LINK_SPEED_20GB PORT_PHY_QCFG_RESP_LINK_SPEED_20GB
+#define BNXT_LINK_SPEED_25GB PORT_PHY_QCFG_RESP_LINK_SPEED_25GB
+#define BNXT_LINK_SPEED_40GB PORT_PHY_QCFG_RESP_LINK_SPEED_40GB
+#define BNXT_LINK_SPEED_50GB PORT_PHY_QCFG_RESP_LINK_SPEED_50GB
+ u16 support_speeds;
+ u16 auto_link_speeds;
+#define BNXT_LINK_SPEED_MSK_100MB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MB
+#define BNXT_LINK_SPEED_MSK_1GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GB
+#define BNXT_LINK_SPEED_MSK_2GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2GB
+#define BNXT_LINK_SPEED_MSK_10GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_10GB
+#define BNXT_LINK_SPEED_MSK_2_5GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2_5GB
+#define BNXT_LINK_SPEED_MSK_20GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_20GB
+#define BNXT_LINK_SPEED_MSK_25GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB
+#define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB
+#define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB
+ u16 auto_link_speed;
+ u16 force_link_speed;
+ u32 preemphasis;
+
+ /* copy of requested setting from ethtool cmd */
+ u8 autoneg;
+#define BNXT_AUTONEG_SPEED 1
+#define BNXT_AUTONEG_FLOW_CTRL 2
+ u8 req_duplex;
+ u8 req_flow_ctrl;
+ u16 req_link_speed;
+ u32 advertising;
+ bool force_link_chng;
+ /* a copy of phy_qcfg output used to report link
+ * info to VF
+ */
+ struct hwrm_port_phy_qcfg_output phy_qcfg_resp;
+};
+
+#define BNXT_MAX_QUEUE 8
+
+struct bnxt_queue_info {
+ u8 queue_id;
+ u8 queue_profile;
+};
+
+#define BNXT_GRCPF_REG_WINDOW_BASE_OUT 0x400
+#define BNXT_CAG_REG_LEGACY_INT_STATUS 0x4014
+#define BNXT_CAG_REG_BASE 0x300000
+
+struct bnxt {
+ void __iomem *bar0;
+ void __iomem *bar1;
+ void __iomem *bar2;
+
+ u32 reg_base;
+
+ struct net_device *dev;
+ struct pci_dev *pdev;
+
+ atomic_t intr_sem;
+
+ u32 flags;
+ #define BNXT_FLAG_DCB_ENABLED 0x1
+ #define BNXT_FLAG_VF 0x2
+ #define BNXT_FLAG_LRO 0x4
+#ifdef CONFIG_INET
+ #define BNXT_FLAG_GRO 0x8
+#else
+ /* Cannot support hardware GRO if CONFIG_INET is not set */
+ #define BNXT_FLAG_GRO 0x0
+#endif
+ #define BNXT_FLAG_TPA (BNXT_FLAG_LRO | BNXT_FLAG_GRO)
+ #define BNXT_FLAG_JUMBO 0x10
+ #define BNXT_FLAG_STRIP_VLAN 0x20
+ #define BNXT_FLAG_AGG_RINGS (BNXT_FLAG_JUMBO | BNXT_FLAG_GRO | \
+ BNXT_FLAG_LRO)
+ #define BNXT_FLAG_USING_MSIX 0x40
+ #define BNXT_FLAG_MSIX_CAP 0x80
+ #define BNXT_FLAG_RFS 0x100
+ #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \
+ BNXT_FLAG_RFS | \
+ BNXT_FLAG_STRIP_VLAN)
+
+#define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF))
+#define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF)
+
+ struct bnxt_napi **bnapi;
+
+ u32 rx_buf_size;
+ u32 rx_buf_use_size; /* useable size */
+ u32 rx_ring_size;
+ u32 rx_agg_ring_size;
+ u32 rx_copy_thresh;
+ u32 rx_ring_mask;
+ u32 rx_agg_ring_mask;
+ int rx_nr_pages;
+ int rx_agg_nr_pages;
+ int rx_nr_rings;
+ int rsscos_nr_ctxs;
+
+ u32 tx_ring_size;
+ u32 tx_ring_mask;
+ int tx_nr_pages;
+ int tx_nr_rings;
+ int tx_nr_rings_per_tc;
+
+ int tx_wake_thresh;
+ int tx_push_thresh;
+ int tx_push_size;
+
+ u32 cp_ring_size;
+ u32 cp_ring_mask;
+ u32 cp_bit;
+ int cp_nr_pages;
+ int cp_nr_rings;
+
+ int num_stat_ctxs;
+ struct bnxt_ring_grp_info *grp_info;
+ struct bnxt_vnic_info *vnic_info;
+ int nr_vnics;
+
+ u8 max_tc;
+ struct bnxt_queue_info q_info[BNXT_MAX_QUEUE];
+
+ unsigned int current_interval;
+#define BNXT_TIMER_INTERVAL (HZ / 2)
+
+ struct timer_list timer;
+
+ int state;
+#define BNXT_STATE_CLOSED 0
+#define BNXT_STATE_OPEN 1
+
+ struct bnxt_irq *irq_tbl;
+ u8 mac_addr[ETH_ALEN];
+
+ u32 msg_enable;
+
+ u16 hwrm_cmd_seq;
+ u32 hwrm_intr_seq_id;
+ void *hwrm_cmd_resp_addr;
+ dma_addr_t hwrm_cmd_resp_dma_addr;
+ void *hwrm_dbg_resp_addr;
+ dma_addr_t hwrm_dbg_resp_dma_addr;
+#define HWRM_DBG_REG_BUF_SIZE 128
+ struct mutex hwrm_cmd_lock; /* serialize hwrm messages */
+ struct hwrm_ver_get_output ver_resp;
+#define FW_VER_STR_LEN 32
+#define BC_HWRM_STR_LEN 21
+#define PHY_VER_STR_LEN (FW_VER_STR_LEN - BC_HWRM_STR_LEN)
+ char fw_ver_str[FW_VER_STR_LEN];
+ __be16 vxlan_port;
+ u8 vxlan_port_cnt;
+ __le16 vxlan_fw_dst_port_id;
+ u8 nge_port_cnt;
+ __le16 nge_fw_dst_port_id;
+ u16 coal_ticks;
+ u16 coal_ticks_irq;
+ u16 coal_bufs;
+ u16 coal_bufs_irq;
+
+#define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2)
+#define BNXT_COAL_TIMER_TO_USEC(x) ((x) * 2 / 25)
+
+ struct work_struct sp_task;
+ unsigned long sp_event;
+#define BNXT_RX_MASK_SP_EVENT 0
+#define BNXT_RX_NTP_FLTR_SP_EVENT 1
+#define BNXT_LINK_CHNG_SP_EVENT 2
+#define BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT 3
+#define BNXT_VXLAN_ADD_PORT_SP_EVENT 4
+#define BNXT_VXLAN_DEL_PORT_SP_EVENT 5
+#define BNXT_RESET_TASK_SP_EVENT 6
+#define BNXT_RST_RING_SP_EVENT 7
+
+ struct bnxt_pf_info pf;
+#ifdef CONFIG_BNXT_SRIOV
+ int nr_vfs;
+ struct bnxt_vf_info vf;
+ wait_queue_head_t sriov_cfg_wait;
+ bool sriov_cfg;
+#define BNXT_SRIOV_CFG_WAIT_TMO msecs_to_jiffies(10000)
+#endif
+
+#define BNXT_NTP_FLTR_MAX_FLTR 4096
+#define BNXT_NTP_FLTR_HASH_SIZE 512
+#define BNXT_NTP_FLTR_HASH_MASK (BNXT_NTP_FLTR_HASH_SIZE - 1)
+ struct hlist_head ntp_fltr_hash_tbl[BNXT_NTP_FLTR_HASH_SIZE];
+ spinlock_t ntp_fltr_lock; /* for hash table add, del */
+
+ unsigned long *ntp_fltr_bmap;
+ int ntp_fltr_count;
+
+ struct bnxt_link_info link_info;
+};
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void bnxt_enable_poll(struct bnxt_napi *bnapi)
+{
+ atomic_set(&bnapi->poll_state, BNXT_STATE_IDLE);
+}
+
+/* called from the NAPI poll routine to get ownership of a bnapi */
+static inline bool bnxt_lock_napi(struct bnxt_napi *bnapi)
+{
+ int rc = atomic_cmpxchg(&bnapi->poll_state, BNXT_STATE_IDLE,
+ BNXT_STATE_NAPI);
+
+ return rc == BNXT_STATE_IDLE;
+}
+
+static inline void bnxt_unlock_napi(struct bnxt_napi *bnapi)
+{
+ atomic_set(&bnapi->poll_state, BNXT_STATE_IDLE);
+}
+
+/* called from the busy poll routine to get ownership of a bnapi */
+static inline bool bnxt_lock_poll(struct bnxt_napi *bnapi)
+{
+ int rc = atomic_cmpxchg(&bnapi->poll_state, BNXT_STATE_IDLE,
+ BNXT_STATE_POLL);
+
+ return rc == BNXT_STATE_IDLE;
+}
+
+static inline void bnxt_unlock_poll(struct bnxt_napi *bnapi)
+{
+ atomic_set(&bnapi->poll_state, BNXT_STATE_IDLE);
+}
+
+static inline bool bnxt_busy_polling(struct bnxt_napi *bnapi)
+{
+ return atomic_read(&bnapi->poll_state) == BNXT_STATE_POLL;
+}
+
+static inline void bnxt_disable_poll(struct bnxt_napi *bnapi)
+{
+ int old;
+
+ while (1) {
+ old = atomic_cmpxchg(&bnapi->poll_state, BNXT_STATE_IDLE,
+ BNXT_STATE_DISABLE);
+ if (old == BNXT_STATE_IDLE)
+ break;
+ usleep_range(500, 5000);
+ }
+}
+
+#else
+
+static inline void bnxt_enable_poll(struct bnxt_napi *bnapi)
+{
+}
+
+static inline bool bnxt_lock_napi(struct bnxt_napi *bnapi)
+{
+ return true;
+}
+
+static inline void bnxt_unlock_napi(struct bnxt_napi *bnapi)
+{
+}
+
+static inline bool bnxt_lock_poll(struct bnxt_napi *bnapi)
+{
+ return false;
+}
+
+static inline void bnxt_unlock_poll(struct bnxt_napi *bnapi)
+{
+}
+
+static inline bool bnxt_busy_polling(struct bnxt_napi *bnapi)
+{
+ return false;
+}
+
+static inline void bnxt_disable_poll(struct bnxt_napi *bnapi)
+{
+}
+
+#endif
+
+void bnxt_set_ring_params(struct bnxt *);
+void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
+int _hwrm_send_message(struct bnxt *, void *, u32, int);
+int hwrm_send_message(struct bnxt *, void *, u32, int);
+int bnxt_hwrm_set_coal(struct bnxt *);
+int bnxt_hwrm_set_pause(struct bnxt *);
+int bnxt_hwrm_set_link_setting(struct bnxt *, bool);
+int bnxt_open_nic(struct bnxt *, bool, bool);
+int bnxt_close_nic(struct bnxt *, bool, bool);
+void bnxt_get_max_rings(struct bnxt *, int *, int *);
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
new file mode 100644
index 000000000000..45bd628eaf3a
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -0,0 +1,1149 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#include <linux/ethtool.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <linux/firmware.h>
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_ethtool.h"
+#include "bnxt_nvm_defs.h" /* NVRAM content constant and structure defs */
+#include "bnxt_fw_hdr.h" /* Firmware hdr constant and structure defs */
+#define FLASH_NVRAM_TIMEOUT ((HWRM_CMD_TIMEOUT) * 100)
+
+static u32 bnxt_get_msglevel(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ return bp->msg_enable;
+}
+
+static void bnxt_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ bp->msg_enable = value;
+}
+
+static int bnxt_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coal)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ memset(coal, 0, sizeof(*coal));
+
+ coal->rx_coalesce_usecs =
+ max_t(u16, BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks), 1);
+ coal->rx_max_coalesced_frames = bp->coal_bufs / 2;
+ coal->rx_coalesce_usecs_irq =
+ max_t(u16, BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks_irq), 1);
+ coal->rx_max_coalesced_frames_irq = bp->coal_bufs_irq / 2;
+
+ return 0;
+}
+
+static int bnxt_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coal)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc = 0;
+
+ bp->coal_ticks = BNXT_USEC_TO_COAL_TIMER(coal->rx_coalesce_usecs);
+ bp->coal_bufs = coal->rx_max_coalesced_frames * 2;
+ bp->coal_ticks_irq =
+ BNXT_USEC_TO_COAL_TIMER(coal->rx_coalesce_usecs_irq);
+ bp->coal_bufs_irq = coal->rx_max_coalesced_frames_irq * 2;
+
+ if (netif_running(dev))
+ rc = bnxt_hwrm_set_coal(bp);
+
+ return rc;
+}
+
+#define BNXT_NUM_STATS 21
+
+static int bnxt_get_sset_count(struct net_device *dev, int sset)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ switch (sset) {
+ case ETH_SS_STATS:
+ return BNXT_NUM_STATS * bp->cp_nr_rings;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void bnxt_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *buf)
+{
+ u32 i, j = 0;
+ struct bnxt *bp = netdev_priv(dev);
+ u32 buf_size = sizeof(struct ctx_hw_stats) * bp->cp_nr_rings;
+ u32 stat_fields = sizeof(struct ctx_hw_stats) / 8;
+
+ memset(buf, 0, buf_size);
+
+ if (!bp->bnapi)
+ return;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_napi *bnapi = bp->bnapi[i];
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ __le64 *hw_stats = (__le64 *)cpr->hw_stats;
+ int k;
+
+ for (k = 0; k < stat_fields; j++, k++)
+ buf[j] = le64_to_cpu(hw_stats[k]);
+ buf[j++] = cpr->rx_l4_csum_errors;
+ }
+}
+
+static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ u32 i;
+
+ switch (stringset) {
+ /* The number of strings must match BNXT_NUM_STATS defined above. */
+ case ETH_SS_STATS:
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ sprintf(buf, "[%d]: rx_ucast_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_mcast_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_bcast_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_discards", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_drops", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_ucast_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_mcast_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_bcast_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_ucast_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_mcast_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_bcast_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_discards", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_drops", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_ucast_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_mcast_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tx_bcast_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tpa_packets", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tpa_bytes", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tpa_events", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: tpa_aborts", i);
+ buf += ETH_GSTRING_LEN;
+ sprintf(buf, "[%d]: rx_l4_csum_errors", i);
+ buf += ETH_GSTRING_LEN;
+ }
+ break;
+ default:
+ netdev_err(bp->dev, "bnxt_get_strings invalid request %x\n",
+ stringset);
+ break;
+ }
+}
+
+static void bnxt_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ering)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT;
+ ering->rx_jumbo_max_pending = BNXT_MAX_RX_JUM_DESC_CNT;
+ ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
+
+ ering->rx_pending = bp->rx_ring_size;
+ ering->rx_jumbo_pending = bp->rx_agg_ring_size;
+ ering->tx_pending = bp->tx_ring_size;
+}
+
+static int bnxt_set_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ering)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) ||
+ (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) ||
+ (ering->tx_pending <= MAX_SKB_FRAGS))
+ return -EINVAL;
+
+ if (netif_running(dev))
+ bnxt_close_nic(bp, false, false);
+
+ bp->rx_ring_size = ering->rx_pending;
+ bp->tx_ring_size = ering->tx_pending;
+ bnxt_set_ring_params(bp);
+
+ if (netif_running(dev))
+ return bnxt_open_nic(bp, false, false);
+
+ return 0;
+}
+
+static void bnxt_get_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int max_rx_rings, max_tx_rings, tcs;
+
+ bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings);
+ tcs = netdev_get_num_tc(dev);
+ if (tcs > 1)
+ max_tx_rings /= tcs;
+
+ channel->max_rx = max_rx_rings;
+ channel->max_tx = max_tx_rings;
+ channel->max_other = 0;
+ channel->max_combined = 0;
+ channel->rx_count = bp->rx_nr_rings;
+ channel->tx_count = bp->tx_nr_rings_per_tc;
+}
+
+static int bnxt_set_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int max_rx_rings, max_tx_rings, tcs;
+ u32 rc = 0;
+
+ if (channel->other_count || channel->combined_count ||
+ !channel->rx_count || !channel->tx_count)
+ return -EINVAL;
+
+ bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings);
+ tcs = netdev_get_num_tc(dev);
+ if (tcs > 1)
+ max_tx_rings /= tcs;
+
+ if (channel->rx_count > max_rx_rings ||
+ channel->tx_count > max_tx_rings)
+ return -EINVAL;
+
+ if (netif_running(dev)) {
+ if (BNXT_PF(bp)) {
+ /* TODO CHIMP_FW: Send message to all VF's
+ * before PF unload
+ */
+ }
+ rc = bnxt_close_nic(bp, true, false);
+ if (rc) {
+ netdev_err(bp->dev, "Set channel failure rc :%x\n",
+ rc);
+ return rc;
+ }
+ }
+
+ bp->rx_nr_rings = channel->rx_count;
+ bp->tx_nr_rings_per_tc = channel->tx_count;
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc;
+ if (tcs > 1)
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
+ bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings);
+ bp->num_stat_ctxs = bp->cp_nr_rings;
+
+ if (netif_running(dev)) {
+ rc = bnxt_open_nic(bp, true, false);
+ if ((!rc) && BNXT_PF(bp)) {
+ /* TODO CHIMP_FW: Send message to all VF's
+ * to renable
+ */
+ }
+ }
+
+ return rc;
+}
+
+#ifdef CONFIG_RFS_ACCEL
+static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ int i, j = 0;
+
+ cmd->data = bp->ntp_fltr_count;
+ for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
+ struct hlist_head *head;
+ struct bnxt_ntuple_filter *fltr;
+
+ head = &bp->ntp_fltr_hash_tbl[i];
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(fltr, head, hash) {
+ if (j == cmd->rule_cnt)
+ break;
+ rule_locs[j++] = fltr->sw_id;
+ }
+ rcu_read_unlock();
+ if (j == cmd->rule_cnt)
+ break;
+ }
+ cmd->rule_cnt = j;
+ return 0;
+}
+
+static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fs =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct bnxt_ntuple_filter *fltr;
+ struct flow_keys *fkeys;
+ int i, rc = -EINVAL;
+
+ if (fs->location < 0 || fs->location >= BNXT_NTP_FLTR_MAX_FLTR)
+ return rc;
+
+ for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
+ struct hlist_head *head;
+
+ head = &bp->ntp_fltr_hash_tbl[i];
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(fltr, head, hash) {
+ if (fltr->sw_id == fs->location)
+ goto fltr_found;
+ }
+ rcu_read_unlock();
+ }
+ return rc;
+
+fltr_found:
+ fkeys = &fltr->fkeys;
+ if (fkeys->basic.ip_proto == IPPROTO_TCP)
+ fs->flow_type = TCP_V4_FLOW;
+ else if (fkeys->basic.ip_proto == IPPROTO_UDP)
+ fs->flow_type = UDP_V4_FLOW;
+ else
+ goto fltr_err;
+
+ fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src;
+ fs->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0);
+
+ fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst;
+ fs->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0);
+
+ fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src;
+ fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0);
+
+ fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst;
+ fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0);
+
+ fs->ring_cookie = fltr->rxq;
+ rc = 0;
+
+fltr_err:
+ rcu_read_unlock();
+
+ return rc;
+}
+
+static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = bp->rx_nr_rings;
+ break;
+
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = bp->ntp_fltr_count;
+ cmd->data = BNXT_NTP_FLTR_MAX_FLTR;
+ break;
+
+ case ETHTOOL_GRXCLSRLALL:
+ rc = bnxt_grxclsrlall(bp, cmd, (u32 *)rule_locs);
+ break;
+
+ case ETHTOOL_GRXCLSRULE:
+ rc = bnxt_grxclsrule(bp, cmd);
+ break;
+
+ default:
+ rc = -EOPNOTSUPP;
+ break;
+ }
+
+ return rc;
+}
+#endif
+
+static u32 bnxt_get_rxfh_indir_size(struct net_device *dev)
+{
+ return HW_HASH_INDEX_SIZE;
+}
+
+static u32 bnxt_get_rxfh_key_size(struct net_device *dev)
+{
+ return HW_HASH_KEY_SIZE;
+}
+
+static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ int i = 0;
+
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP;
+
+ if (indir)
+ for (i = 0; i < HW_HASH_INDEX_SIZE; i++)
+ indir[i] = le16_to_cpu(vnic->rss_table[i]);
+
+ if (key)
+ memcpy(key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);
+
+ return 0;
+}
+
+static void bnxt_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
+ strlcpy(info->fw_version, bp->fw_ver_str, sizeof(info->fw_version));
+ strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
+ info->n_stats = BNXT_NUM_STATS * bp->cp_nr_rings;
+ info->testinfo_len = BNXT_NUM_TESTS(bp);
+ /* TODO CHIMP_FW: eeprom dump details */
+ info->eedump_len = 0;
+ /* TODO CHIMP FW: reg dump details */
+ info->regdump_len = 0;
+}
+
+static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info)
+{
+ u16 fw_speeds = link_info->support_speeds;
+ u32 speed_mask = 0;
+
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_100MB)
+ speed_mask |= SUPPORTED_100baseT_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_1GB)
+ speed_mask |= SUPPORTED_1000baseT_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_2_5GB)
+ speed_mask |= SUPPORTED_2500baseX_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB)
+ speed_mask |= SUPPORTED_10000baseT_Full;
+ /* TODO: support 25GB, 50GB with different cable type */
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB)
+ speed_mask |= SUPPORTED_20000baseMLD2_Full |
+ SUPPORTED_20000baseKR2_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB)
+ speed_mask |= SUPPORTED_40000baseKR4_Full |
+ SUPPORTED_40000baseCR4_Full |
+ SUPPORTED_40000baseSR4_Full |
+ SUPPORTED_40000baseLR4_Full;
+
+ return speed_mask;
+}
+
+static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
+{
+ u16 fw_speeds = link_info->auto_link_speeds;
+ u32 speed_mask = 0;
+
+ /* TODO: support 25GB, 40GB, 50GB with different cable type */
+ /* set the advertised speeds */
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_100MB)
+ speed_mask |= ADVERTISED_100baseT_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_1GB)
+ speed_mask |= ADVERTISED_1000baseT_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_2_5GB)
+ speed_mask |= ADVERTISED_2500baseX_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB)
+ speed_mask |= ADVERTISED_10000baseT_Full;
+ /* TODO: how to advertise 20, 25, 40, 50GB with different cable type ?*/
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB)
+ speed_mask |= ADVERTISED_20000baseMLD2_Full |
+ ADVERTISED_20000baseKR2_Full;
+ if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB)
+ speed_mask |= ADVERTISED_40000baseKR4_Full |
+ ADVERTISED_40000baseCR4_Full |
+ ADVERTISED_40000baseSR4_Full |
+ ADVERTISED_40000baseLR4_Full;
+ return speed_mask;
+}
+
+u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
+{
+ switch (fw_link_speed) {
+ case BNXT_LINK_SPEED_100MB:
+ return SPEED_100;
+ case BNXT_LINK_SPEED_1GB:
+ return SPEED_1000;
+ case BNXT_LINK_SPEED_2_5GB:
+ return SPEED_2500;
+ case BNXT_LINK_SPEED_10GB:
+ return SPEED_10000;
+ case BNXT_LINK_SPEED_20GB:
+ return SPEED_20000;
+ case BNXT_LINK_SPEED_25GB:
+ return SPEED_25000;
+ case BNXT_LINK_SPEED_40GB:
+ return SPEED_40000;
+ case BNXT_LINK_SPEED_50GB:
+ return SPEED_50000;
+ default:
+ return SPEED_UNKNOWN;
+ }
+}
+
+static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_link_info *link_info = &bp->link_info;
+ u16 ethtool_speed;
+
+ cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info);
+
+ if (link_info->auto_link_speeds)
+ cmd->supported |= SUPPORTED_Autoneg;
+
+ if (BNXT_AUTO_MODE(link_info->auto_mode)) {
+ cmd->advertising =
+ bnxt_fw_to_ethtool_advertised_spds(link_info);
+ cmd->advertising |= ADVERTISED_Autoneg;
+ cmd->autoneg = AUTONEG_ENABLE;
+ } else {
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->advertising = 0;
+ }
+ if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) {
+ if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) ==
+ BNXT_LINK_PAUSE_BOTH) {
+ cmd->advertising |= ADVERTISED_Pause;
+ cmd->supported |= SUPPORTED_Pause;
+ } else {
+ cmd->advertising |= ADVERTISED_Asym_Pause;
+ cmd->supported |= SUPPORTED_Asym_Pause;
+ if (link_info->auto_pause_setting &
+ BNXT_LINK_PAUSE_RX)
+ cmd->advertising |= ADVERTISED_Pause;
+ }
+ } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) {
+ if ((link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) ==
+ BNXT_LINK_PAUSE_BOTH) {
+ cmd->supported |= SUPPORTED_Pause;
+ } else {
+ cmd->supported |= SUPPORTED_Asym_Pause;
+ if (link_info->force_pause_setting &
+ BNXT_LINK_PAUSE_RX)
+ cmd->supported |= SUPPORTED_Pause;
+ }
+ }
+
+ cmd->port = PORT_NONE;
+ if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
+ cmd->port = PORT_TP;
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_TP;
+ } else {
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_FIBRE;
+
+ if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
+ cmd->port = PORT_DA;
+ else if (link_info->media_type ==
+ PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE)
+ cmd->port = PORT_FIBRE;
+ }
+
+ if (link_info->phy_link_status == BNXT_LINK_LINK) {
+ if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
+ cmd->duplex = DUPLEX_FULL;
+ } else {
+ cmd->duplex = DUPLEX_UNKNOWN;
+ }
+ ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
+ ethtool_cmd_speed_set(cmd, ethtool_speed);
+ if (link_info->transceiver ==
+ PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL)
+ cmd->transceiver = XCVR_INTERNAL;
+ else
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->phy_address = link_info->phy_addr;
+
+ return 0;
+}
+
+static u32 bnxt_get_fw_speed(struct net_device *dev, u16 ethtool_speed)
+{
+ switch (ethtool_speed) {
+ case SPEED_100:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB;
+ case SPEED_1000:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB;
+ case SPEED_2500:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB;
+ case SPEED_10000:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB;
+ case SPEED_20000:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB;
+ case SPEED_25000:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB;
+ case SPEED_40000:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB;
+ case SPEED_50000:
+ return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB;
+ default:
+ netdev_err(dev, "unsupported speed!\n");
+ break;
+ }
+ return 0;
+}
+
+static u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
+{
+ u16 fw_speed_mask = 0;
+
+ /* only support autoneg at speed 100, 1000, and 10000 */
+ if (advertising & (ADVERTISED_100baseT_Full |
+ ADVERTISED_100baseT_Half)) {
+ fw_speed_mask |= BNXT_LINK_SPEED_MSK_100MB;
+ }
+ if (advertising & (ADVERTISED_1000baseT_Full |
+ ADVERTISED_1000baseT_Half)) {
+ fw_speed_mask |= BNXT_LINK_SPEED_MSK_1GB;
+ }
+ if (advertising & ADVERTISED_10000baseT_Full)
+ fw_speed_mask |= BNXT_LINK_SPEED_MSK_10GB;
+
+ return fw_speed_mask;
+}
+
+static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ int rc = 0;
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_link_info *link_info = &bp->link_info;
+ u32 speed, fw_advertising = 0;
+ bool set_pause = false;
+
+ if (BNXT_VF(bp))
+ return rc;
+
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ if (link_info->media_type != PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
+ netdev_err(dev, "Media type doesn't support autoneg\n");
+ rc = -EINVAL;
+ goto set_setting_exit;
+ }
+ if (cmd->advertising & ~(BNXT_ALL_COPPER_ETHTOOL_SPEED |
+ ADVERTISED_Autoneg |
+ ADVERTISED_TP |
+ ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause)) {
+ netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n",
+ cmd->advertising);
+ rc = -EINVAL;
+ goto set_setting_exit;
+ }
+ fw_advertising = bnxt_get_fw_auto_link_speeds(cmd->advertising);
+ if (fw_advertising & ~link_info->support_speeds) {
+ netdev_err(dev, "Advertising parameters are not supported! (adv: 0x%x)\n",
+ cmd->advertising);
+ rc = -EINVAL;
+ goto set_setting_exit;
+ }
+ link_info->autoneg |= BNXT_AUTONEG_SPEED;
+ if (!fw_advertising)
+ link_info->advertising = link_info->support_speeds;
+ else
+ link_info->advertising = fw_advertising;
+ /* any change to autoneg will cause link change, therefore the
+ * driver should put back the original pause setting in autoneg
+ */
+ set_pause = true;
+ } else {
+ /* TODO: currently don't support half duplex */
+ if (cmd->duplex == DUPLEX_HALF) {
+ netdev_err(dev, "HALF DUPLEX is not supported!\n");
+ rc = -EINVAL;
+ goto set_setting_exit;
+ }
+ /* If received a request for an unknown duplex, assume full*/
+ if (cmd->duplex == DUPLEX_UNKNOWN)
+ cmd->duplex = DUPLEX_FULL;
+ speed = ethtool_cmd_speed(cmd);
+ link_info->req_link_speed = bnxt_get_fw_speed(dev, speed);
+ link_info->req_duplex = BNXT_LINK_DUPLEX_FULL;
+ link_info->autoneg &= ~BNXT_AUTONEG_SPEED;
+ link_info->advertising = 0;
+ }
+
+ if (netif_running(dev))
+ rc = bnxt_hwrm_set_link_setting(bp, set_pause);
+
+set_setting_exit:
+ return rc;
+}
+
+static void bnxt_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_link_info *link_info = &bp->link_info;
+
+ if (BNXT_VF(bp))
+ return;
+ epause->autoneg = !!(link_info->auto_pause_setting &
+ BNXT_LINK_PAUSE_BOTH);
+ epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0);
+ epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0);
+}
+
+static int bnxt_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+{
+ int rc = 0;
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_link_info *link_info = &bp->link_info;
+
+ if (BNXT_VF(bp))
+ return rc;
+
+ if (epause->autoneg) {
+ link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH;
+ } else {
+ /* when transition from auto pause to force pause,
+ * force a link change
+ */
+ if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
+ link_info->force_link_chng = true;
+ link_info->autoneg &= ~BNXT_AUTONEG_FLOW_CTRL;
+ link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_BOTH;
+ }
+ if (epause->rx_pause)
+ link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_RX;
+ else
+ link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_RX;
+
+ if (epause->tx_pause)
+ link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX;
+ else
+ link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_TX;
+
+ if (netif_running(dev))
+ rc = bnxt_hwrm_set_pause(bp);
+ return rc;
+}
+
+static u32 bnxt_get_link(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ /* TODO: handle MF, VF, driver close case */
+ return bp->link_info.link_up;
+}
+
+static int bnxt_flash_nvram(struct net_device *dev,
+ u16 dir_type,
+ u16 dir_ordinal,
+ u16 dir_ext,
+ u16 dir_attr,
+ const u8 *data,
+ size_t data_len)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+ struct hwrm_nvm_write_input req = {0};
+ dma_addr_t dma_handle;
+ u8 *kmem;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_WRITE, -1, -1);
+
+ req.dir_type = cpu_to_le16(dir_type);
+ req.dir_ordinal = cpu_to_le16(dir_ordinal);
+ req.dir_ext = cpu_to_le16(dir_ext);
+ req.dir_attr = cpu_to_le16(dir_attr);
+ req.dir_data_length = cpu_to_le32(data_len);
+
+ kmem = dma_alloc_coherent(&bp->pdev->dev, data_len, &dma_handle,
+ GFP_KERNEL);
+ if (!kmem) {
+ netdev_err(dev, "dma_alloc_coherent failure, length = %u\n",
+ (unsigned)data_len);
+ return -ENOMEM;
+ }
+ memcpy(kmem, data, data_len);
+ req.host_src_addr = cpu_to_le64(dma_handle);
+
+ rc = hwrm_send_message(bp, &req, sizeof(req), FLASH_NVRAM_TIMEOUT);
+ dma_free_coherent(&bp->pdev->dev, data_len, kmem, dma_handle);
+
+ return rc;
+}
+
+static int bnxt_flash_firmware(struct net_device *dev,
+ u16 dir_type,
+ const u8 *fw_data,
+ size_t fw_size)
+{
+ int rc = 0;
+ u16 code_type;
+ u32 stored_crc;
+ u32 calculated_crc;
+ struct bnxt_fw_header *header = (struct bnxt_fw_header *)fw_data;
+
+ switch (dir_type) {
+ case BNX_DIR_TYPE_BOOTCODE:
+ case BNX_DIR_TYPE_BOOTCODE_2:
+ code_type = CODE_BOOT;
+ break;
+ default:
+ netdev_err(dev, "Unsupported directory entry type: %u\n",
+ dir_type);
+ return -EINVAL;
+ }
+ if (fw_size < sizeof(struct bnxt_fw_header)) {
+ netdev_err(dev, "Invalid firmware file size: %u\n",
+ (unsigned int)fw_size);
+ return -EINVAL;
+ }
+ if (header->signature != cpu_to_le32(BNXT_FIRMWARE_BIN_SIGNATURE)) {
+ netdev_err(dev, "Invalid firmware signature: %08X\n",
+ le32_to_cpu(header->signature));
+ return -EINVAL;
+ }
+ if (header->code_type != code_type) {
+ netdev_err(dev, "Expected firmware type: %d, read: %d\n",
+ code_type, header->code_type);
+ return -EINVAL;
+ }
+ if (header->device != DEVICE_CUMULUS_FAMILY) {
+ netdev_err(dev, "Expected firmware device family %d, read: %d\n",
+ DEVICE_CUMULUS_FAMILY, header->device);
+ return -EINVAL;
+ }
+ /* Confirm the CRC32 checksum of the file: */
+ stored_crc = le32_to_cpu(*(__le32 *)(fw_data + fw_size -
+ sizeof(stored_crc)));
+ calculated_crc = ~crc32(~0, fw_data, fw_size - sizeof(stored_crc));
+ if (calculated_crc != stored_crc) {
+ netdev_err(dev, "Firmware file CRC32 checksum (%08lX) does not match calculated checksum (%08lX)\n",
+ (unsigned long)stored_crc,
+ (unsigned long)calculated_crc);
+ return -EINVAL;
+ }
+ /* TODO: Validate digital signature (RSA-encrypted SHA-256 hash) here */
+ rc = bnxt_flash_nvram(dev, dir_type, BNX_DIR_ORDINAL_FIRST,
+ 0, 0, fw_data, fw_size);
+ if (rc == 0) { /* Firmware update successful */
+ /* TODO: Notify processor it needs to reset itself
+ */
+ }
+ return rc;
+}
+
+static bool bnxt_dir_type_is_ape_bin_format(u16 dir_type)
+{
+ switch (dir_type) {
+ case BNX_DIR_TYPE_CHIMP_PATCH:
+ case BNX_DIR_TYPE_BOOTCODE:
+ case BNX_DIR_TYPE_BOOTCODE_2:
+ case BNX_DIR_TYPE_APE_FW:
+ case BNX_DIR_TYPE_APE_PATCH:
+ case BNX_DIR_TYPE_KONG_FW:
+ case BNX_DIR_TYPE_KONG_PATCH:
+ return true;
+ }
+
+ return false;
+}
+
+static bool bnxt_dir_type_is_unprotected_exec_format(u16 dir_type)
+{
+ switch (dir_type) {
+ case BNX_DIR_TYPE_AVS:
+ case BNX_DIR_TYPE_EXP_ROM_MBA:
+ case BNX_DIR_TYPE_PCIE:
+ case BNX_DIR_TYPE_TSCF_UCODE:
+ case BNX_DIR_TYPE_EXT_PHY:
+ case BNX_DIR_TYPE_CCM:
+ case BNX_DIR_TYPE_ISCSI_BOOT:
+ case BNX_DIR_TYPE_ISCSI_BOOT_IPV6:
+ case BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6:
+ return true;
+ }
+
+ return false;
+}
+
+static bool bnxt_dir_type_is_executable(u16 dir_type)
+{
+ return bnxt_dir_type_is_ape_bin_format(dir_type) ||
+ bnxt_dir_type_is_unprotected_exec_format(dir_type);
+}
+
+static int bnxt_flash_firmware_from_file(struct net_device *dev,
+ u16 dir_type,
+ const char *filename)
+{
+ const struct firmware *fw;
+ int rc;
+
+ if (bnxt_dir_type_is_executable(dir_type) == false)
+ return -EINVAL;
+
+ rc = request_firmware(&fw, filename, &dev->dev);
+ if (rc != 0) {
+ netdev_err(dev, "Error %d requesting firmware file: %s\n",
+ rc, filename);
+ return rc;
+ }
+ if (bnxt_dir_type_is_ape_bin_format(dir_type) == true)
+ rc = bnxt_flash_firmware(dev, dir_type, fw->data, fw->size);
+ else
+ rc = bnxt_flash_nvram(dev, dir_type, BNX_DIR_ORDINAL_FIRST,
+ 0, 0, fw->data, fw->size);
+ release_firmware(fw);
+ return rc;
+}
+
+static int bnxt_flash_package_from_file(struct net_device *dev,
+ char *filename)
+{
+ netdev_err(dev, "packages are not yet supported\n");
+ return -EINVAL;
+}
+
+static int bnxt_flash_device(struct net_device *dev,
+ struct ethtool_flash *flash)
+{
+ if (!BNXT_PF((struct bnxt *)netdev_priv(dev))) {
+ netdev_err(dev, "flashdev not supported from a virtual function\n");
+ return -EINVAL;
+ }
+
+ if (flash->region == ETHTOOL_FLASH_ALL_REGIONS)
+ return bnxt_flash_package_from_file(dev, flash->data);
+
+ return bnxt_flash_firmware_from_file(dev, flash->region, flash->data);
+}
+
+static int nvm_get_dir_info(struct net_device *dev, u32 *entries, u32 *length)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+ struct hwrm_nvm_get_dir_info_input req = {0};
+ struct hwrm_nvm_get_dir_info_output *output = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_DIR_INFO, -1, -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc) {
+ *entries = le32_to_cpu(output->entries);
+ *length = le32_to_cpu(output->entry_length);
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_get_eeprom_len(struct net_device *dev)
+{
+ /* The -1 return value allows the entire 32-bit range of offsets to be
+ * passed via the ethtool command-line utility.
+ */
+ return -1;
+}
+
+static int bnxt_get_nvram_directory(struct net_device *dev, u32 len, u8 *data)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+ u32 dir_entries;
+ u32 entry_length;
+ u8 *buf;
+ size_t buflen;
+ dma_addr_t dma_handle;
+ struct hwrm_nvm_get_dir_entries_input req = {0};
+
+ rc = nvm_get_dir_info(dev, &dir_entries, &entry_length);
+ if (rc != 0)
+ return rc;
+
+ /* Insert 2 bytes of directory info (count and size of entries) */
+ if (len < 2)
+ return -EINVAL;
+
+ *data++ = dir_entries;
+ *data++ = entry_length;
+ len -= 2;
+ memset(data, 0xff, len);
+
+ buflen = dir_entries * entry_length;
+ buf = dma_alloc_coherent(&bp->pdev->dev, buflen, &dma_handle,
+ GFP_KERNEL);
+ if (!buf) {
+ netdev_err(dev, "dma_alloc_coherent failure, length = %u\n",
+ (unsigned)buflen);
+ return -ENOMEM;
+ }
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_DIR_ENTRIES, -1, -1);
+ req.host_dest_addr = cpu_to_le64(dma_handle);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc == 0)
+ memcpy(data, buf, len > buflen ? buflen : len);
+ dma_free_coherent(&bp->pdev->dev, buflen, buf, dma_handle);
+ return rc;
+}
+
+static int bnxt_get_nvram_item(struct net_device *dev, u32 index, u32 offset,
+ u32 length, u8 *data)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+ u8 *buf;
+ dma_addr_t dma_handle;
+ struct hwrm_nvm_read_input req = {0};
+
+ buf = dma_alloc_coherent(&bp->pdev->dev, length, &dma_handle,
+ GFP_KERNEL);
+ if (!buf) {
+ netdev_err(dev, "dma_alloc_coherent failure, length = %u\n",
+ (unsigned)length);
+ return -ENOMEM;
+ }
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_READ, -1, -1);
+ req.host_dest_addr = cpu_to_le64(dma_handle);
+ req.dir_idx = cpu_to_le16(index);
+ req.offset = cpu_to_le32(offset);
+ req.len = cpu_to_le32(length);
+
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc == 0)
+ memcpy(data, buf, length);
+ dma_free_coherent(&bp->pdev->dev, length, buf, dma_handle);
+ return rc;
+}
+
+static int bnxt_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ u32 index;
+ u32 offset;
+
+ if (eeprom->offset == 0) /* special offset value to get directory */
+ return bnxt_get_nvram_directory(dev, eeprom->len, data);
+
+ index = eeprom->offset >> 24;
+ offset = eeprom->offset & 0xffffff;
+
+ if (index == 0) {
+ netdev_err(dev, "unsupported index value: %d\n", index);
+ return -EINVAL;
+ }
+
+ return bnxt_get_nvram_item(dev, index - 1, offset, eeprom->len, data);
+}
+
+static int bnxt_erase_nvram_directory(struct net_device *dev, u8 index)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct hwrm_nvm_erase_dir_entry_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_ERASE_DIR_ENTRY, -1, -1);
+ req.dir_idx = cpu_to_le16(index);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ u8 index, dir_op;
+ u16 type, ext, ordinal, attr;
+
+ if (!BNXT_PF(bp)) {
+ netdev_err(dev, "NVM write not supported from a virtual function\n");
+ return -EINVAL;
+ }
+
+ type = eeprom->magic >> 16;
+
+ if (type == 0xffff) { /* special value for directory operations */
+ index = eeprom->magic & 0xff;
+ dir_op = eeprom->magic >> 8;
+ if (index == 0)
+ return -EINVAL;
+ switch (dir_op) {
+ case 0x0e: /* erase */
+ if (eeprom->offset != ~eeprom->magic)
+ return -EINVAL;
+ return bnxt_erase_nvram_directory(dev, index - 1);
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* Create or re-write an NVM item: */
+ if (bnxt_dir_type_is_executable(type) == true)
+ return -EINVAL;
+ ext = eeprom->magic & 0xffff;
+ ordinal = eeprom->offset >> 16;
+ attr = eeprom->offset & 0xffff;
+
+ return bnxt_flash_nvram(dev, type, ordinal, ext, attr, data,
+ eeprom->len);
+}
+
+const struct ethtool_ops bnxt_ethtool_ops = {
+ .get_settings = bnxt_get_settings,
+ .set_settings = bnxt_set_settings,
+ .get_pauseparam = bnxt_get_pauseparam,
+ .set_pauseparam = bnxt_set_pauseparam,
+ .get_drvinfo = bnxt_get_drvinfo,
+ .get_coalesce = bnxt_get_coalesce,
+ .set_coalesce = bnxt_set_coalesce,
+ .get_msglevel = bnxt_get_msglevel,
+ .set_msglevel = bnxt_set_msglevel,
+ .get_sset_count = bnxt_get_sset_count,
+ .get_strings = bnxt_get_strings,
+ .get_ethtool_stats = bnxt_get_ethtool_stats,
+ .set_ringparam = bnxt_set_ringparam,
+ .get_ringparam = bnxt_get_ringparam,
+ .get_channels = bnxt_get_channels,
+ .set_channels = bnxt_set_channels,
+#ifdef CONFIG_RFS_ACCEL
+ .get_rxnfc = bnxt_get_rxnfc,
+#endif
+ .get_rxfh_indir_size = bnxt_get_rxfh_indir_size,
+ .get_rxfh_key_size = bnxt_get_rxfh_key_size,
+ .get_rxfh = bnxt_get_rxfh,
+ .flash_device = bnxt_flash_device,
+ .get_eeprom_len = bnxt_get_eeprom_len,
+ .get_eeprom = bnxt_get_eeprom,
+ .set_eeprom = bnxt_set_eeprom,
+ .get_link = bnxt_get_link,
+};
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
new file mode 100644
index 000000000000..98fa81e08b58
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
@@ -0,0 +1,17 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#ifndef BNXT_ETHTOOL_H
+#define BNXT_ETHTOOL_H
+
+extern const struct ethtool_ops bnxt_ethtool_ops;
+
+u32 bnxt_fw_to_ethtool_speed(u16);
+
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h
new file mode 100644
index 000000000000..e0aac65c6d82
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h
@@ -0,0 +1,104 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#ifndef __BNXT_FW_HDR_H__
+#define __BNXT_FW_HDR_H__
+
+#define BNXT_FIRMWARE_BIN_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */
+
+enum SUPPORTED_FAMILY {
+ DEVICE_5702_3_4_FAMILY, /* 0 - Denali, Vinson, K2 */
+ DEVICE_5705_FAMILY, /* 1 - Bachelor */
+ DEVICE_SHASTA_FAMILY, /* 2 - 5751 */
+ DEVICE_5706_FAMILY, /* 3 - Teton */
+ DEVICE_5714_FAMILY, /* 4 - Hamilton */
+ DEVICE_STANFORD_FAMILY, /* 5 - 5755 */
+ DEVICE_STANFORD_ME_FAMILY, /* 6 - 5756 */
+ DEVICE_SOLEDAD_FAMILY, /* 7 - 5761[E] */
+ DEVICE_CILAI_FAMILY, /* 8 - 57780/60/90/91 */
+ DEVICE_ASPEN_FAMILY, /* 9 - 57781/85/61/65/91/95 */
+ DEVICE_ASPEN_PLUS_FAMILY, /* 10 - 57786 */
+ DEVICE_LOGAN_FAMILY, /* 11 - Any device in the Logan family
+ */
+ DEVICE_LOGAN_5762, /* 12 - Logan Enterprise (aka Columbia)
+ */
+ DEVICE_LOGAN_57767, /* 13 - Logan Client */
+ DEVICE_LOGAN_57787, /* 14 - Logan Consumer */
+ DEVICE_LOGAN_5725, /* 15 - Logan Server (TruManage-enabled)
+ */
+ DEVICE_SAWTOOTH_FAMILY, /* 16 - 5717/18 */
+ DEVICE_COTOPAXI_FAMILY, /* 17 - 5719 */
+ DEVICE_SNAGGLETOOTH_FAMILY, /* 18 - 5720 */
+ DEVICE_CUMULUS_FAMILY, /* 19 - Cumulus/Whitney */
+ MAX_DEVICE_FAMILY
+};
+
+enum SUPPORTED_CODE {
+ CODE_ASF1, /* 0 - ASF VERSION 1.03 <deprecated> */
+ CODE_ASF2, /* 1 - ASF VERSION 2.00 <deprecated> */
+ CODE_PASSTHRU, /* 2 - PassThru <deprecated> */
+ CODE_PT_SEC, /* 3 - PassThru with security <deprecated> */
+ CODE_UMP, /* 4 - UMP <deprecated> */
+ CODE_BOOT, /* 5 - Bootcode */
+ CODE_DASH, /* 6 - TruManage (DASH + ASF + PMCI)
+ * Management firmwares
+ */
+ CODE_MCTP_PASSTHRU, /* 7 - NCSI / MCTP Passt-hrough firmware */
+ CODE_PM_OFFLOAD, /* 8 - Power-Management Proxy Offload firmwares
+ */
+ CODE_MDNS_SD_OFFLOAD, /* 9 - Multicast DNS Service Discovery Proxys
+ * Offload firmware
+ */
+ CODE_DISC_OFFLOAD, /* 10 - Discovery Offload firmware */
+ CODE_MUSTANG, /* 11 - I2C Error reporting APE firmwares
+ * <deprecated>
+ */
+ CODE_ARP_BATCH, /* 12 - ARP Batch firmware */
+ CODE_SMASH, /* 13 - TruManage (SMASH + DCMI/IPMI + PMCI)
+ * Management firmware
+ */
+ CODE_APE_DIAG, /* 14 - APE Test Diag firmware */
+ CODE_APE_PATCH, /* 15 - APE Patch firmware */
+ CODE_TANG_PATCH, /* 16 - TANG Patch firmware */
+ CODE_KONG_FW, /* 17 - KONG firmware */
+ CODE_KONG_PATCH, /* 18 - KONG Patch firmware */
+ CODE_BONO_FW, /* 19 - BONO firmware */
+ CODE_BONO_PATCH, /* 20 - BONO Patch firmware */
+
+ MAX_CODE_TYPE,
+};
+
+enum SUPPORTED_MEDIA {
+ MEDIA_COPPER, /* 0 */
+ MEDIA_FIBER, /* 1 */
+ MEDIA_NONE, /* 2 */
+ MEDIA_COPPER_FIBER, /* 3 */
+ MAX_MEDIA_TYPE,
+};
+
+struct bnxt_fw_header {
+ __le32 signature; /* constains the constant value of
+ * BNXT_Firmware_Bin_Signatures
+ */
+ u8 flags; /* reserved for ChiMP use */
+ u8 code_type; /* enum SUPPORTED_CODE */
+ u8 device; /* enum SUPPORTED_FAMILY */
+ u8 media; /* enum SUPPORTED_MEDIA */
+ u8 version[16]; /* the null terminated version string to
+ * indicate the version of the
+ * file, this will be copied from the binary
+ * file version string
+ */
+ u8 build;
+ u8 revision;
+ u8 minor_ver;
+ u8 major_ver;
+};
+
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
new file mode 100644
index 000000000000..70fc8253c07f
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
@@ -0,0 +1,4046 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#ifndef BNXT_HSI_H
+#define BNXT_HSI_H
+
+/* per-context HW statistics -- chip view */
+struct ctx_hw_stats {
+ __le64 rx_ucast_pkts;
+ __le64 rx_mcast_pkts;
+ __le64 rx_bcast_pkts;
+ __le64 rx_discard_pkts;
+ __le64 rx_drop_pkts;
+ __le64 rx_ucast_bytes;
+ __le64 rx_mcast_bytes;
+ __le64 rx_bcast_bytes;
+ __le64 tx_ucast_pkts;
+ __le64 tx_mcast_pkts;
+ __le64 tx_bcast_pkts;
+ __le64 tx_discard_pkts;
+ __le64 tx_drop_pkts;
+ __le64 tx_ucast_bytes;
+ __le64 tx_mcast_bytes;
+ __le64 tx_bcast_bytes;
+ __le64 tpa_pkts;
+ __le64 tpa_bytes;
+ __le64 tpa_events;
+ __le64 tpa_aborts;
+};
+
+/* Statistics Ejection Buffer Completion Record (16 bytes) */
+struct eject_cmpl {
+ __le16 type;
+ #define EJECT_CMPL_TYPE_MASK 0x3fUL
+ #define EJECT_CMPL_TYPE_SFT 0
+ #define EJECT_CMPL_TYPE_STAT_EJECT (0x1aUL << 0)
+ __le16 len;
+ __le32 opaque;
+ __le32 v;
+ #define EJECT_CMPL_V 0x1UL
+ __le32 unused_2;
+};
+
+/* HWRM Completion Record (16 bytes) */
+struct hwrm_cmpl {
+ __le16 type;
+ #define HWRM_CMPL_TYPE_MASK 0x3fUL
+ #define HWRM_CMPL_TYPE_SFT 0
+ #define HWRM_CMPL_TYPE_HWRM_DONE (0x20UL << 0)
+ __le16 sequence_id;
+ __le32 unused_1;
+ __le32 v;
+ #define HWRM_CMPL_V 0x1UL
+ __le32 unused_3;
+};
+
+/* HWRM Forwarded Request (16 bytes) */
+struct hwrm_fwd_req_cmpl {
+ __le16 req_len_type;
+ #define HWRM_FWD_REQ_CMPL_TYPE_MASK 0x3fUL
+ #define HWRM_FWD_REQ_CMPL_TYPE_SFT 0
+ #define HWRM_FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ (0x22UL << 0)
+ #define HWRM_FWD_REQ_CMPL_REQ_LEN_MASK 0xffc0UL
+ #define HWRM_FWD_REQ_CMPL_REQ_LEN_SFT 6
+ __le16 source_id;
+ __le32 unused_0;
+ __le32 req_buf_addr_v[2];
+ #define HWRM_FWD_REQ_CMPL_V 0x1UL
+ #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_MASK 0xfffffffeUL
+ #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_SFT 1
+};
+
+/* HWRM Forwarded Response (16 bytes) */
+struct hwrm_fwd_resp_cmpl {
+ __le16 type;
+ #define HWRM_FWD_RESP_CMPL_TYPE_MASK 0x3fUL
+ #define HWRM_FWD_RESP_CMPL_TYPE_SFT 0
+ #define HWRM_FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP (0x24UL << 0)
+ __le16 source_id;
+ __le16 resp_len;
+ __le16 unused_1;
+ __le32 resp_buf_addr_v[2];
+ #define HWRM_FWD_RESP_CMPL_V 0x1UL
+ #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_MASK 0xfffffffeUL
+ #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_SFT 1
+};
+
+/* HWRM Asynchronous Event Completion Record (16 bytes) */
+struct hwrm_async_event_cmpl {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE (0x0UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE (0x1UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE (0x2UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE (0x3UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED (0x4UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD (0x10UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD (0x11UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD (0x20UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD (0x20UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR (0x30UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE (0x31UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR (0xffUL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+};
+
+/* HWRM Asynchronous Event Completion Record for link status change (16 bytes) */
+struct hwrm_async_event_cmpl_link_status_change {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE (0x0UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_UP 0x1UL
+};
+
+/* HWRM Asynchronous Event Completion Record for link MTU change (16 bytes) */
+struct hwrm_async_event_cmpl_link_mtu_change {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE (0x1UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for link speed change (16 bytes) */
+struct hwrm_async_event_cmpl_link_speed_change {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE (0x2UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK 0xfffeUL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (0x1UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (0xaUL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (0x14UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (0x19UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (0x64UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (0xc8UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (0xfaUL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (0x190UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (0x1f4UL << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0000UL
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16
+};
+
+/* HWRM Asynchronous Event Completion Record for DCB Config change (16 bytes) */
+struct hwrm_async_event_cmpl_dcb_config_change {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE (0x3UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for port connection not allowed (16 bytes) */
+struct hwrm_async_event_cmpl_port_conn_not_allowed {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED (0x4UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for Function Driver Unload (16 bytes) */
+struct hwrm_async_event_cmpl_func_drvr_unload {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD (0x10UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for Function Driver load (16 bytes) */
+struct hwrm_async_event_cmpl_func_drvr_load {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD (0x11UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for PF Driver Unload (16 bytes) */
+struct hwrm_async_event_cmpl_pf_drvr_unload {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD (0x20UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for PF Driver load (16 bytes) */
+struct hwrm_async_event_cmpl_pf_drvr_load {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD (0x20UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for VF FLR (16 bytes) */
+struct hwrm_async_event_cmpl_vf_flr {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR (0x30UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for VF MAC Addr change (16 bytes) */
+struct hwrm_async_event_cmpl_vf_mac_addr_change {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE (0x31UL << 0)
+ __le32 event_data2;
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK 0xffffUL
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record for HWRM Error (16 bytes) */
+struct hwrm_async_event_cmpl_hwrm_error {
+ __le16 type;
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK 0x3fUL
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0)
+ __le16 event_id;
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR (0xffUL << 0)
+ __le32 event_data2;
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK 0xffUL
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING (0x0UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL (0x1UL << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL (0x2UL << 0)
+ u8 opaque_v;
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_V 0x1UL
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK 0xfeUL
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT 1
+ u8 unused_1[3];
+ __le32 event_data1;
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP 0x1UL
+};
+
+/* HW Resource Manager Specification 0.7.8 */
+#define HWRM_VERSION_MAJOR 0
+#define HWRM_VERSION_MINOR 7
+#define HWRM_VERSION_UPDATE 8
+
+#define HWRM_VERSION_STR "0.7.8"
+/* Following is the signature for HWRM message field that indicates not
+ * applicable (All F's). Need to cast it the size of the field if needed.
+ */
+#define HWRM_NA_SIGNATURE ((__le32)(-1))
+#define HWRM_MAX_REQ_LEN (128) /* hwrm_func_buf_rgtr */
+#define HWRM_MAX_RESP_LEN (176) /* hwrm_func_qstats */
+#define HW_HASH_INDEX_SIZE 0x80 /* 7 bit indirection table index. */
+#define HW_HASH_KEY_SIZE 40
+#define HWRM_RESP_VALID_KEY 1 /* valid key for HWRM response */
+/* Input (16 bytes) */
+struct input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (8 bytes) */
+struct output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+};
+
+/* Command numbering (8 bytes) */
+struct cmd_nums {
+ __le16 req_type;
+ #define HWRM_VER_GET (0x0UL)
+ #define HWRM_FUNC_DISABLE (0x10UL)
+ #define HWRM_FUNC_RESET (0x11UL)
+ #define HWRM_FUNC_GETFID (0x12UL)
+ #define HWRM_FUNC_VF_ALLOC (0x13UL)
+ #define HWRM_FUNC_VF_FREE (0x14UL)
+ #define HWRM_FUNC_QCAPS (0x15UL)
+ #define HWRM_FUNC_QCFG (0x16UL)
+ #define HWRM_FUNC_CFG (0x17UL)
+ #define HWRM_FUNC_QSTATS (0x18UL)
+ #define HWRM_FUNC_CLR_STATS (0x19UL)
+ #define HWRM_FUNC_DRV_UNRGTR (0x1aUL)
+ #define HWRM_FUNC_VF_RESC_FREE (0x1bUL)
+ #define HWRM_FUNC_VF_VNIC_IDS_QUERY (0x1cUL)
+ #define HWRM_FUNC_DRV_RGTR (0x1dUL)
+ #define HWRM_FUNC_DRV_QVER (0x1eUL)
+ #define HWRM_FUNC_BUF_RGTR (0x1fUL)
+ #define HWRM_FUNC_VF_CFG (0x20UL)
+ #define HWRM_PORT_PHY_CFG (0x20UL)
+ #define HWRM_PORT_MAC_CFG (0x21UL)
+ #define HWRM_PORT_ENABLE (0x22UL)
+ #define HWRM_PORT_QSTATS (0x23UL)
+ #define HWRM_PORT_LPBK_QSTATS (0x24UL)
+ #define HWRM_PORT_CLR_STATS (0x25UL)
+ #define HWRM_PORT_LPBK_CLR_STATS (0x26UL)
+ #define HWRM_PORT_PHY_QCFG (0x27UL)
+ #define HWRM_PORT_MAC_QCFG (0x28UL)
+ #define HWRM_PORT_BLINK_LED (0x29UL)
+ #define HWRM_QUEUE_QPORTCFG (0x30UL)
+ #define HWRM_QUEUE_QCFG (0x31UL)
+ #define HWRM_QUEUE_CFG (0x32UL)
+ #define HWRM_QUEUE_BUFFERS_QCFG (0x33UL)
+ #define HWRM_QUEUE_BUFFERS_CFG (0x34UL)
+ #define HWRM_QUEUE_PFCENABLE_QCFG (0x35UL)
+ #define HWRM_QUEUE_PFCENABLE_CFG (0x36UL)
+ #define HWRM_QUEUE_PRI2COS_QCFG (0x37UL)
+ #define HWRM_QUEUE_PRI2COS_CFG (0x38UL)
+ #define HWRM_QUEUE_COS2BW_QCFG (0x39UL)
+ #define HWRM_QUEUE_COS2BW_CFG (0x3aUL)
+ #define HWRM_VNIC_ALLOC (0x40UL)
+ #define HWRM_VNIC_FREE (0x41UL)
+ #define HWRM_VNIC_CFG (0x42UL)
+ #define HWRM_VNIC_QCFG (0x43UL)
+ #define HWRM_VNIC_TPA_CFG (0x44UL)
+ #define HWRM_VNIC_TPA_QCFG (0x45UL)
+ #define HWRM_VNIC_RSS_CFG (0x46UL)
+ #define HWRM_VNIC_RSS_QCFG (0x47UL)
+ #define HWRM_VNIC_PLCMODES_CFG (0x48UL)
+ #define HWRM_VNIC_PLCMODES_QCFG (0x49UL)
+ #define HWRM_RING_ALLOC (0x50UL)
+ #define HWRM_RING_FREE (0x51UL)
+ #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS (0x52UL)
+ #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS (0x53UL)
+ #define HWRM_RING_RESET (0x5eUL)
+ #define HWRM_RING_GRP_ALLOC (0x60UL)
+ #define HWRM_RING_GRP_FREE (0x61UL)
+ #define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC (0x70UL)
+ #define HWRM_VNIC_RSS_COS_LB_CTX_FREE (0x71UL)
+ #define HWRM_ARB_GRP_ALLOC (0x80UL)
+ #define HWRM_ARB_GRP_CFG (0x81UL)
+ #define HWRM_CFA_L2_FILTER_ALLOC (0x90UL)
+ #define HWRM_CFA_L2_FILTER_FREE (0x91UL)
+ #define HWRM_CFA_L2_FILTER_CFG (0x92UL)
+ #define HWRM_CFA_L2_SET_RX_MASK (0x93UL)
+ #define HWRM_CFA_L2_SET_BCASTMCAST_MIRRORING (0x94UL)
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC (0x95UL)
+ #define HWRM_CFA_TUNNEL_FILTER_FREE (0x96UL)
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC (0x97UL)
+ #define HWRM_CFA_ENCAP_RECORD_FREE (0x98UL)
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC (0x99UL)
+ #define HWRM_CFA_NTUPLE_FILTER_FREE (0x9aUL)
+ #define HWRM_CFA_NTUPLE_FILTER_CFG (0x9bUL)
+ #define HWRM_TUNNEL_DST_PORT_QUERY (0xa0UL)
+ #define HWRM_TUNNEL_DST_PORT_ALLOC (0xa1UL)
+ #define HWRM_TUNNEL_DST_PORT_FREE (0xa2UL)
+ #define HWRM_STAT_CTX_ALLOC (0xb0UL)
+ #define HWRM_STAT_CTX_FREE (0xb1UL)
+ #define HWRM_STAT_CTX_QUERY (0xb2UL)
+ #define HWRM_STAT_CTX_CLR_STATS (0xb3UL)
+ #define HWRM_FW_RESET (0xc0UL)
+ #define HWRM_FW_QSTATUS (0xc1UL)
+ #define HWRM_EXEC_FWD_RESP (0xd0UL)
+ #define HWRM_REJECT_FWD_RESP (0xd1UL)
+ #define HWRM_FWD_RESP (0xd2UL)
+ #define HWRM_FWD_ASYNC_EVENT_CMPL (0xd3UL)
+ #define HWRM_TEMP_MONITOR_QUERY (0xe0UL)
+ #define HWRM_MGMT_L2_FILTER_ALLOC (0x100UL)
+ #define HWRM_MGMT_L2_FILTER_FREE (0x101UL)
+ #define HWRM_DBG_READ_DIRECT (0xff10UL)
+ #define HWRM_DBG_READ_INDIRECT (0xff11UL)
+ #define HWRM_DBG_WRITE_DIRECT (0xff12UL)
+ #define HWRM_DBG_WRITE_INDIRECT (0xff13UL)
+ #define HWRM_DBG_DUMP (0xff14UL)
+ #define HWRM_NVM_MODIFY (0xfff4UL)
+ #define HWRM_NVM_VERIFY_UPDATE (0xfff5UL)
+ #define HWRM_NVM_GET_DEV_INFO (0xfff6UL)
+ #define HWRM_NVM_ERASE_DIR_ENTRY (0xfff7UL)
+ #define HWRM_NVM_MOD_DIR_ENTRY (0xfff8UL)
+ #define HWRM_NVM_FIND_DIR_ENTRY (0xfff9UL)
+ #define HWRM_NVM_GET_DIR_ENTRIES (0xfffaUL)
+ #define HWRM_NVM_GET_DIR_INFO (0xfffbUL)
+ #define HWRM_NVM_RAW_DUMP (0xfffcUL)
+ #define HWRM_NVM_READ (0xfffdUL)
+ #define HWRM_NVM_WRITE (0xfffeUL)
+ #define HWRM_NVM_RAW_WRITE_BLK (0xffffUL)
+ __le16 unused_0[3];
+};
+
+/* Return Codes (8 bytes) */
+struct ret_codes {
+ __le16 error_code;
+ #define HWRM_ERR_CODE_SUCCESS (0x0UL)
+ #define HWRM_ERR_CODE_FAIL (0x1UL)
+ #define HWRM_ERR_CODE_INVALID_PARAMS (0x2UL)
+ #define HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED (0x3UL)
+ #define HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR (0x4UL)
+ #define HWRM_ERR_CODE_INVALID_FLAGS (0x5UL)
+ #define HWRM_ERR_CODE_INVALID_ENABLES (0x6UL)
+ #define HWRM_ERR_CODE_HWRM_ERROR (0xfUL)
+ #define HWRM_ERR_CODE_UNKNOWN_ERR (0xfffeUL)
+ #define HWRM_ERR_CODE_CMD_NOT_SUPPORTED (0xffffUL)
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_err_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 opaque_0;
+ __le16 opaque_1;
+ u8 opaque_2;
+ u8 valid;
+};
+
+/* Port Tx Statistics Formats (408 bytes) */
+struct tx_port_stats {
+ __le64 tx_64b_frames;
+ __le64 tx_65b_127b_frames;
+ __le64 tx_128b_255b_frames;
+ __le64 tx_256b_511b_frames;
+ __le64 tx_512b_1023b_frames;
+ __le64 tx_1024b_1518_frames;
+ __le64 tx_good_vlan_frames;
+ __le64 tx_1519b_2047_frames;
+ __le64 tx_2048b_4095b_frames;
+ __le64 tx_4096b_9216b_frames;
+ __le64 tx_9217b_16383b_frames;
+ __le64 tx_good_frames;
+ __le64 tx_total_frames;
+ __le64 tx_ucast_frames;
+ __le64 tx_mcast_frames;
+ __le64 tx_bcast_frames;
+ __le64 tx_pause_frames;
+ __le64 tx_pfc_frames;
+ __le64 tx_jabber_frames;
+ __le64 tx_fcs_err_frames;
+ __le64 tx_control_frames;
+ __le64 tx_oversz_frames;
+ __le64 tx_single_dfrl_frames;
+ __le64 tx_multi_dfrl_frames;
+ __le64 tx_single_coll_frames;
+ __le64 tx_multi_coll_frames;
+ __le64 tx_late_coll_frames;
+ __le64 tx_excessive_coll_frames;
+ __le64 tx_frag_frames;
+ __le64 tx_err;
+ __le64 tx_tagged_frames;
+ __le64 tx_dbl_tagged_frames;
+ __le64 tx_runt_frames;
+ __le64 tx_fifo_underruns;
+ __le64 tx_pfc_ena_frames_pri0;
+ __le64 tx_pfc_ena_frames_pri1;
+ __le64 tx_pfc_ena_frames_pri2;
+ __le64 tx_pfc_ena_frames_pri3;
+ __le64 tx_pfc_ena_frames_pri4;
+ __le64 tx_pfc_ena_frames_pri5;
+ __le64 tx_pfc_ena_frames_pri6;
+ __le64 tx_pfc_ena_frames_pri7;
+ __le64 tx_eee_lpi_events;
+ __le64 tx_eee_lpi_duration;
+ __le64 tx_llfc_logical_msgs;
+ __le64 tx_hcfc_msgs;
+ __le64 tx_total_collisions;
+ __le64 tx_bytes;
+ __le64 tx_xthol_frames;
+ __le64 tx_stat_discard;
+ __le64 tx_stat_error;
+};
+
+/* Port Rx Statistics Formats (528 bytes) */
+struct rx_port_stats {
+ __le64 rx_64b_frames;
+ __le64 rx_65b_127b_frames;
+ __le64 rx_128b_255b_frames;
+ __le64 rx_256b_511b_frames;
+ __le64 rx_512b_1023b_frames;
+ __le64 rx_1024b_1518_frames;
+ __le64 rx_good_vlan_frames;
+ __le64 rx_1519b_2047b_frames;
+ __le64 rx_2048b_4095b_frames;
+ __le64 rx_4096b_9216b_frames;
+ __le64 rx_9217b_16383b_frames;
+ __le64 rx_total_frames;
+ __le64 rx_ucast_frames;
+ __le64 rx_mcast_frames;
+ __le64 rx_bcast_frames;
+ __le64 rx_fcs_err_frames;
+ __le64 rx_ctrl_frames;
+ __le64 rx_pause_frames;
+ __le64 rx_pfc_frames;
+ __le64 rx_unsupported_opcode_frames;
+ __le64 rx_unsupported_da_pausepfc_frames;
+ __le64 rx_wrong_sa_frames;
+ __le64 rx_align_err_frames;
+ __le64 rx_oor_len_frames;
+ __le64 rx_code_err_frames;
+ __le64 rx_false_carrier_frames;
+ __le64 rx_ovrsz_frames;
+ __le64 rx_jbr_frames;
+ __le64 rx_mtu_err_frames;
+ __le64 rx_match_crc_frames;
+ __le64 rx_promiscuous_frames;
+ __le64 rx_tagged_frames;
+ __le64 rx_double_tagged_frames;
+ __le64 rx_trunc_frames;
+ __le64 rx_good_frames;
+ __le64 rx_pfc_xon2xoff_frames_pri0;
+ __le64 rx_pfc_xon2xoff_frames_pri1;
+ __le64 rx_pfc_xon2xoff_frames_pri2;
+ __le64 rx_pfc_xon2xoff_frames_pri3;
+ __le64 rx_pfc_xon2xoff_frames_pri4;
+ __le64 rx_pfc_xon2xoff_frames_pri5;
+ __le64 rx_pfc_xon2xoff_frames_pri6;
+ __le64 rx_pfc_xon2xoff_frames_pri7;
+ __le64 rx_pfc_ena_frames_pri0;
+ __le64 rx_pfc_ena_frames_pri1;
+ __le64 rx_pfc_ena_frames_pri2;
+ __le64 rx_pfc_ena_frames_pri3;
+ __le64 rx_pfc_ena_frames_pri4;
+ __le64 rx_pfc_ena_frames_pri5;
+ __le64 rx_pfc_ena_frames_pri6;
+ __le64 rx_pfc_ena_frames_pri7;
+ __le64 rx_sch_crc_err_frames;
+ __le64 rx_undrsz_frames;
+ __le64 rx_frag_frames;
+ __le64 rx_eee_lpi_events;
+ __le64 rx_eee_lpi_duration;
+ __le64 rx_llfc_physical_msgs;
+ __le64 rx_llfc_logical_msgs;
+ __le64 rx_llfc_msgs_with_crc_err;
+ __le64 rx_hcfc_msgs;
+ __le64 rx_hcfc_msgs_with_crc_err;
+ __le64 rx_bytes;
+ __le64 rx_runt_bytes;
+ __le64 rx_runt_frames;
+ __le64 rx_stat_discard;
+ __le64 rx_stat_err;
+};
+
+/* hwrm_ver_get */
+/* Input (24 bytes) */
+struct hwrm_ver_get_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 hwrm_intf_maj;
+ u8 hwrm_intf_min;
+ u8 hwrm_intf_upd;
+ u8 unused_0[5];
+};
+
+/* Output (128 bytes) */
+struct hwrm_ver_get_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 hwrm_intf_maj;
+ u8 hwrm_intf_min;
+ u8 hwrm_intf_upd;
+ u8 hwrm_intf_rsvd;
+ u8 hwrm_fw_maj;
+ u8 hwrm_fw_min;
+ u8 hwrm_fw_bld;
+ u8 hwrm_fw_rsvd;
+ u8 ape_fw_maj;
+ u8 ape_fw_min;
+ u8 ape_fw_bld;
+ u8 ape_fw_rsvd;
+ u8 kong_fw_maj;
+ u8 kong_fw_min;
+ u8 kong_fw_bld;
+ u8 kong_fw_rsvd;
+ u8 tang_fw_maj;
+ u8 tang_fw_min;
+ u8 tang_fw_bld;
+ u8 tang_fw_rsvd;
+ u8 bono_fw_maj;
+ u8 bono_fw_min;
+ u8 bono_fw_bld;
+ u8 bono_fw_rsvd;
+ char hwrm_fw_name[16];
+ char ape_fw_name[16];
+ char kong_fw_name[16];
+ char tang_fw_name[16];
+ char bono_fw_name[16];
+ __le16 chip_num;
+ u8 chip_rev;
+ u8 chip_metal;
+ u8 chip_bond_id;
+ u8 unused_0;
+ __le16 max_req_win_len;
+ __le16 max_resp_len;
+ __le16 def_req_timeout;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_disable */
+/* Input (24 bytes) */
+struct hwrm_func_disable_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_DISABLE_REQ_ENABLES_VF_ID_VALID 0x1UL
+ __le16 vf_id;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_disable_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_reset */
+/* Input (24 bytes) */
+struct hwrm_func_reset_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_RESET_REQ_ENABLES_VF_ID_VALID 0x1UL
+ __le16 vf_id;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_reset_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_getfid */
+/* Input (24 bytes) */
+struct hwrm_func_getfid_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_GETFID_REQ_ENABLES_PCI_ID 0x1UL
+ __le16 pci_id;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_getfid_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 fid;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_func_vf_alloc */
+/* Input (24 bytes) */
+struct hwrm_func_vf_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_VF_ALLOC_REQ_ENABLES_FIRST_VF_ID 0x1UL
+ __le16 first_vf_id;
+ __le16 num_vfs;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_vf_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 first_vf_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_func_vf_free */
+/* Input (24 bytes) */
+struct hwrm_func_vf_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_VF_FREE_REQ_ENABLES_FIRST_VF_ID 0x1UL
+ __le16 first_vf_id;
+ __le16 num_vfs;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_vf_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_vf_cfg */
+/* Input (24 bytes) */
+struct hwrm_func_vf_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_VF_CFG_REQ_ENABLES_MTU 0x1UL
+ #define FUNC_VF_CFG_REQ_ENABLES_GUEST_VLAN 0x2UL
+ __le16 mtu;
+ __le16 guest_vlan;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_vf_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_qcaps */
+/* Input (24 bytes) */
+struct hwrm_func_qcaps_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 fid;
+ __le16 unused_0[3];
+};
+
+/* Output (80 bytes) */
+struct hwrm_func_qcaps_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 fid;
+ __le16 port_id;
+ __le32 flags;
+ #define FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED 0x1UL
+ #define FUNC_QCAPS_RESP_FLAGS_GLOBAL_MSIX_AUTOMASKING 0x2UL
+ u8 perm_mac_address[6];
+ __le16 max_rsscos_ctx;
+ __le16 max_cmpl_rings;
+ __le16 max_tx_rings;
+ __le16 max_rx_rings;
+ __le16 max_l2_ctxs;
+ __le16 max_vnics;
+ __le16 first_vf_id;
+ __le16 max_vfs;
+ __le16 max_stat_ctx;
+ __le32 max_encap_records;
+ __le32 max_decap_records;
+ __le32 max_tx_em_flows;
+ __le32 max_tx_wm_flows;
+ __le32 max_rx_em_flows;
+ __le32 max_rx_wm_flows;
+ __le32 max_mcast_filters;
+ __le32 max_flow_id;
+ __le32 max_hw_ring_grps;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_func_cfg */
+/* Input (88 bytes) */
+struct hwrm_func_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 vf_id;
+ u8 unused_0;
+ u8 unused_1;
+ __le32 flags;
+ #define FUNC_CFG_REQ_FLAGS_PROM_MODE 0x1UL
+ #define FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK 0x2UL
+ #define FUNC_CFG_REQ_FLAGS_SRC_IP_ADDR_CHECK 0x4UL
+ #define FUNC_CFG_REQ_FLAGS_VLAN_PRI_MATCH 0x8UL
+ #define FUNC_CFG_REQ_FLAGS_DFLT_PRI_NOMATCH 0x10UL
+ #define FUNC_CFG_REQ_FLAGS_DISABLE_PAUSE 0x20UL
+ #define FUNC_CFG_REQ_FLAGS_DISABLE_STP 0x40UL
+ #define FUNC_CFG_REQ_FLAGS_DISABLE_LLDP 0x80UL
+ #define FUNC_CFG_REQ_FLAGS_DISABLE_PTPV2 0x100UL
+ __le32 enables;
+ #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL
+ #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS 0x4UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS 0x8UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_TX_RINGS 0x10UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS 0x20UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_L2_CTXS 0x40UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_VNICS 0x80UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS 0x100UL
+ #define FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR 0x200UL
+ #define FUNC_CFG_REQ_ENABLES_DFLT_VLAN 0x400UL
+ #define FUNC_CFG_REQ_ENABLES_DFLT_IP_ADDR 0x800UL
+ #define FUNC_CFG_REQ_ENABLES_MIN_BW 0x1000UL
+ #define FUNC_CFG_REQ_ENABLES_MAX_BW 0x2000UL
+ #define FUNC_CFG_REQ_ENABLES_ASYNC_EVENT_CR 0x4000UL
+ #define FUNC_CFG_REQ_ENABLES_VLAN_ANTISPOOF_MODE 0x8000UL
+ #define FUNC_CFG_REQ_ENABLES_ALLOWED_VLAN_PRIS 0x10000UL
+ #define FUNC_CFG_REQ_ENABLES_EVB_MODE 0x20000UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_MCAST_FILTERS 0x40000UL
+ #define FUNC_CFG_REQ_ENABLES_NUM_HW_RING_GRPS 0x80000UL
+ __le16 mtu;
+ __le16 mru;
+ __le16 num_rsscos_ctxs;
+ __le16 num_cmpl_rings;
+ __le16 num_tx_rings;
+ __le16 num_rx_rings;
+ __le16 num_l2_ctxs;
+ __le16 num_vnics;
+ __le16 num_stat_ctxs;
+ __le16 num_hw_ring_grps;
+ u8 dflt_mac_addr[6];
+ __le16 dflt_vlan;
+ __be32 dflt_ip_addr[4];
+ __le32 min_bw;
+ __le32 max_bw;
+ __le16 async_event_cr;
+ u8 vlan_antispoof_mode;
+ #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_NOCHECK (0x0UL << 0)
+ #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_VALIDATE_VLAN (0x1UL << 0)
+ #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_INSERT_IF_VLANDNE (0x2UL << 0)
+ #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_INSERT_OR_OVERRIDE_VLAN (0x3UL << 0)
+ u8 allowed_vlan_pris;
+ #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_NOCHECK (0x0UL << 0)
+ #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_VALIDATE_VLAN (0x1UL << 0)
+ #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_INSERT_IF_VLANDNE (0x2UL << 0)
+ #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_INSERT_OR_OVERRIDE_VLAN (0x3UL << 0)
+ u8 evb_mode;
+ #define FUNC_CFG_REQ_EVB_MODE_NO_EVB (0x0UL << 0)
+ #define FUNC_CFG_REQ_EVB_MODE_VEB (0x1UL << 0)
+ #define FUNC_CFG_REQ_EVB_MODE_VEPA (0x2UL << 0)
+ u8 unused_2;
+ __le16 num_mcast_filters;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_qstats */
+/* Input (24 bytes) */
+struct hwrm_func_qstats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 fid;
+ __le16 unused_0[3];
+};
+
+/* Output (176 bytes) */
+struct hwrm_func_qstats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 tx_ucast_pkts;
+ __le64 tx_mcast_pkts;
+ __le64 tx_bcast_pkts;
+ __le64 tx_err_pkts;
+ __le64 tx_drop_pkts;
+ __le64 tx_ucast_bytes;
+ __le64 tx_mcast_bytes;
+ __le64 tx_bcast_bytes;
+ __le64 rx_ucast_pkts;
+ __le64 rx_mcast_pkts;
+ __le64 rx_bcast_pkts;
+ __le64 rx_err_pkts;
+ __le64 rx_drop_pkts;
+ __le64 rx_ucast_bytes;
+ __le64 rx_mcast_bytes;
+ __le64 rx_bcast_bytes;
+ __le64 rx_agg_pkts;
+ __le64 rx_agg_bytes;
+ __le64 rx_agg_events;
+ __le64 rx_agg_aborts;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_clr_stats */
+/* Input (24 bytes) */
+struct hwrm_func_clr_stats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 fid;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_clr_stats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_vf_resc_free */
+/* Input (24 bytes) */
+struct hwrm_func_vf_resc_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 vf_id;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_vf_resc_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_vf_vnic_ids_query */
+/* Input (32 bytes) */
+struct hwrm_func_vf_vnic_ids_query_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 vf_id;
+ u8 unused_0;
+ u8 unused_1;
+ __le32 max_vnic_id_cnt;
+ __le64 vnic_id_tbl_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_vf_vnic_ids_query_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 vnic_id_cnt;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_func_drv_rgtr */
+/* Input (80 bytes) */
+struct hwrm_func_drv_rgtr_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define FUNC_DRV_RGTR_REQ_FLAGS_FWD_ALL_MODE 0x1UL
+ #define FUNC_DRV_RGTR_REQ_FLAGS_FWD_NONE_MODE 0x2UL
+ __le32 enables;
+ #define FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE 0x1UL
+ #define FUNC_DRV_RGTR_REQ_ENABLES_VER 0x2UL
+ #define FUNC_DRV_RGTR_REQ_ENABLES_TIMESTAMP 0x4UL
+ #define FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD 0x8UL
+ #define FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD 0x10UL
+ __le16 os_type;
+ u8 ver_maj;
+ u8 ver_min;
+ u8 ver_upd;
+ u8 unused_0;
+ __le16 unused_1;
+ __le32 timestamp;
+ __le32 unused_2;
+ __le32 vf_req_fwd[8];
+ __le32 async_event_fwd[8];
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_drv_rgtr_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_drv_unrgtr */
+/* Input (24 bytes) */
+struct hwrm_func_drv_unrgtr_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define FUNC_DRV_UNRGTR_REQ_FLAGS_PREPARE_FOR_SHUTDOWN 0x1UL
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_drv_unrgtr_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_buf_rgtr */
+/* Input (128 bytes) */
+struct hwrm_func_buf_rgtr_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_BUF_RGTR_REQ_ENABLES_VF_ID 0x1UL
+ #define FUNC_BUF_RGTR_REQ_ENABLES_ERR_BUF_ADDR 0x2UL
+ __le16 vf_id;
+ __le16 req_buf_num_pages;
+ __le16 req_buf_page_size;
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_16B (0x4UL << 0)
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_4K (0xcUL << 0)
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_8K (0xdUL << 0)
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_64K (0x10UL << 0)
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_2M (0x16UL << 0)
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_4M (0x17UL << 0)
+ #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_1G (0x1eUL << 0)
+ __le16 req_buf_len;
+ __le16 resp_buf_len;
+ u8 unused_0;
+ u8 unused_1;
+ __le64 req_buf_page_addr0;
+ __le64 req_buf_page_addr1;
+ __le64 req_buf_page_addr2;
+ __le64 req_buf_page_addr3;
+ __le64 req_buf_page_addr4;
+ __le64 req_buf_page_addr5;
+ __le64 req_buf_page_addr6;
+ __le64 req_buf_page_addr7;
+ __le64 req_buf_page_addr8;
+ __le64 req_buf_page_addr9;
+ __le64 error_buf_addr;
+ __le64 resp_buf_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_buf_rgtr_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_func_drv_qver */
+/* Input (24 bytes) */
+struct hwrm_func_drv_qver_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define FUNC_DRV_QVER_REQ_ENABLES_OS_TYPE_VALID 0x1UL
+ #define FUNC_DRV_QVER_REQ_ENABLES_VER_VALID 0x2UL
+ __le16 fid;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_func_drv_qver_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 os_type;
+ u8 ver_maj;
+ u8 ver_min;
+ u8 ver_upd;
+ u8 unused_0;
+ u8 unused_1;
+ u8 valid;
+};
+
+/* hwrm_port_phy_cfg */
+/* Input (48 bytes) */
+struct hwrm_port_phy_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define PORT_PHY_CFG_REQ_FLAGS_RESET_PHY 0x1UL
+ #define PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN 0x2UL
+ #define PORT_PHY_CFG_REQ_FLAGS_FORCE 0x4UL
+ #define PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG 0x8UL
+ __le32 enables;
+ #define PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE 0x1UL
+ #define PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX 0x2UL
+ #define PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE 0x4UL
+ #define PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED 0x8UL
+ #define PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK 0x10UL
+ #define PORT_PHY_CFG_REQ_ENABLES_WIRESPEED 0x20UL
+ #define PORT_PHY_CFG_REQ_ENABLES_LPBK 0x40UL
+ #define PORT_PHY_CFG_REQ_ENABLES_PREEMPHASIS 0x80UL
+ #define PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE 0x100UL
+ __le16 port_id;
+ __le16 force_link_speed;
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100MB (0x1UL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_1GB (0xaUL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_2GB (0x14UL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_2_5GB (0x19UL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_10GB (0x64UL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_20GB (0xc8UL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_25GB (0xfaUL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_40GB (0x190UL << 0)
+ #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_50GB (0x1f4UL << 0)
+ u8 auto_mode;
+ #define PORT_PHY_CFG_REQ_AUTO_MODE_NONE (0x0UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_MODE_ALL_SPEEDS (0x1UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_MODE_ONE_SPEED (0x2UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_MODE_MASK (0x4UL << 0)
+ u8 auto_duplex;
+ #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_HALF (0x0UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL (0x1UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_BOTH (0x2UL << 0)
+ u8 auto_pause;
+ #define PORT_PHY_CFG_REQ_AUTO_PAUSE_TX 0x1UL
+ #define PORT_PHY_CFG_REQ_AUTO_PAUSE_RX 0x2UL
+ u8 unused_0;
+ __le16 auto_link_speed;
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB (0x1UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB (0xaUL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2GB (0x14UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB (0x19UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB (0x64UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB (0xc8UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB (0xfaUL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB (0x190UL << 0)
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB (0x1f4UL << 0)
+ __le16 auto_link_speed_mask;
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100MBHD 0x1UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100MB 0x2UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_1GBHD 0x4UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_1GB 0x8UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_2GB 0x10UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_2_5GB 0x20UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_10GB 0x40UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_20GB 0x80UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_25GB 0x100UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_40GB 0x200UL
+ #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_50GB 0x400UL
+ u8 wirespeed;
+ #define PORT_PHY_CFG_REQ_WIRESPEED_OFF (0x0UL << 0)
+ #define PORT_PHY_CFG_REQ_WIRESPEED_ON (0x1UL << 0)
+ u8 lpbk;
+ #define PORT_PHY_CFG_REQ_LPBK_NONE (0x0UL << 0)
+ #define PORT_PHY_CFG_REQ_LPBK_LOCAL (0x1UL << 0)
+ #define PORT_PHY_CFG_REQ_LPBK_REMOTE (0x2UL << 0)
+ u8 force_pause;
+ #define PORT_PHY_CFG_REQ_FORCE_PAUSE_TX 0x1UL
+ #define PORT_PHY_CFG_REQ_FORCE_PAUSE_RX 0x2UL
+ u8 unused_1;
+ __le32 preemphasis;
+ __le32 unused_2;
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_phy_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_port_phy_qcfg */
+/* Input (24 bytes) */
+struct hwrm_port_phy_qcfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 port_id;
+ __le16 unused_0[3];
+};
+
+/* Output (48 bytes) */
+struct hwrm_port_phy_qcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 link;
+ #define PORT_PHY_QCFG_RESP_LINK_NO_LINK (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SIGNAL (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_LINK (0x2UL << 0)
+ u8 unused_0;
+ __le16 link_speed;
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_100MB (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_1GB (0xaUL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_2GB (0x14UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_2_5GB (0x19UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_10GB (0x64UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_20GB (0xc8UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_25GB (0xfaUL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_40GB (0x190UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_SPEED_50GB (0x1f4UL << 0)
+ u8 duplex;
+ #define PORT_PHY_QCFG_RESP_DUPLEX_HALF (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_DUPLEX_FULL (0x1UL << 0)
+ u8 pause;
+ #define PORT_PHY_QCFG_RESP_PAUSE_TX 0x1UL
+ #define PORT_PHY_QCFG_RESP_PAUSE_RX 0x2UL
+ __le16 support_speeds;
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MBHD 0x1UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MB 0x2UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GBHD 0x4UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GB 0x8UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2GB 0x10UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2_5GB 0x20UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_10GB 0x40UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_20GB 0x80UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB 0x100UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB 0x200UL
+ #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB 0x400UL
+ __le16 force_link_speed;
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_100MB (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_1GB (0xaUL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_2GB (0x14UL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_2_5GB (0x19UL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_10GB (0x64UL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_20GB (0xc8UL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_25GB (0xfaUL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_40GB (0x190UL << 0)
+ #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_50GB (0x1f4UL << 0)
+ u8 auto_mode;
+ #define PORT_PHY_QCFG_RESP_AUTO_MODE_NONE (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED (0x2UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_MODE_MASK (0x4UL << 0)
+ u8 auto_pause;
+ #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_TX 0x1UL
+ #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_RX 0x2UL
+ __le16 auto_link_speed;
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_100MB (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_1GB (0xaUL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_2GB (0x14UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_2_5GB (0x19UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_10GB (0x64UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_20GB (0xc8UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_25GB (0xfaUL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_40GB (0x190UL << 0)
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_50GB (0x1f4UL << 0)
+ __le16 auto_link_speed_mask;
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100MBHD 0x1UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100MB 0x2UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_1GBHD 0x4UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_1GB 0x8UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_2GB 0x10UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_2_5GB 0x20UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_10GB 0x40UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_20GB 0x80UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_25GB 0x100UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_40GB 0x200UL
+ #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_50GB 0x400UL
+ u8 wirespeed;
+ #define PORT_PHY_QCFG_RESP_WIRESPEED_OFF (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_WIRESPEED_ON (0x1UL << 0)
+ u8 lpbk;
+ #define PORT_PHY_QCFG_RESP_LPBK_NONE (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_LPBK_LOCAL (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_LPBK_REMOTE (0x2UL << 0)
+ u8 force_pause;
+ #define PORT_PHY_QCFG_RESP_FORCE_PAUSE_TX 0x1UL
+ #define PORT_PHY_QCFG_RESP_FORCE_PAUSE_RX 0x2UL
+ u8 duplex_setting;
+ #define PORT_PHY_QCFG_RESP_DUPLEX_SETTING_HALF (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_DUPLEX_SETTING_FULL (0x1UL << 0)
+ __le32 preemphasis;
+ u8 phy_maj;
+ u8 phy_min;
+ u8 phy_bld;
+ u8 phy_type;
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASECR4 (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR4 (0x2UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASELR4 (0x3UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASESR4 (0x4UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR2 (0x5UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKX4 (0x6UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR (0x7UL << 0)
+ #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASET (0x8UL << 0)
+ u8 media_type;
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC (0x2UL << 0)
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE (0x3UL << 0)
+ u8 transceiver_type;
+ #define PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_EXTERNAL (0x2UL << 0)
+ u8 phy_addr;
+ #define PORT_PHY_QCFG_RESP_PHY_ADDR_MASK 0x1fUL
+ #define PORT_PHY_QCFG_RESP_PHY_ADDR_SFT 0
+ u8 unused_2;
+ __le16 link_partner_adv_speeds;
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100MBHD 0x1UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100MB 0x2UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_1GBHD 0x4UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_1GB 0x8UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_2GB 0x10UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_2_5GB 0x20UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_10GB 0x40UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_20GB 0x80UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_25GB 0x100UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_40GB 0x200UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_50GB 0x400UL
+ u8 link_partner_adv_auto_mode;
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_NONE (0x0UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ALL_SPEEDS (0x1UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ONE_SPEED (0x2UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0)
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_MASK (0x4UL << 0)
+ u8 link_partner_adv_pause;
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_PAUSE_TX 0x1UL
+ #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_PAUSE_RX 0x2UL
+ u8 unused_3;
+ u8 unused_4;
+ u8 unused_5;
+ u8 valid;
+};
+
+/* hwrm_port_mac_cfg */
+/* Input (32 bytes) */
+struct hwrm_port_mac_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define PORT_MAC_CFG_REQ_FLAGS_MATCH_LINK 0x1UL
+ #define PORT_MAC_CFG_REQ_FLAGS_COS_ASSIGNMENT_ENABLE 0x2UL
+ #define PORT_MAC_CFG_REQ_FLAGS_TUNNEL_PRI2COS_ENABLE 0x4UL
+ #define PORT_MAC_CFG_REQ_FLAGS_IP_DSCP2COS_ENABLE 0x8UL
+ __le32 enables;
+ #define PORT_MAC_CFG_REQ_ENABLES_IPG 0x1UL
+ #define PORT_MAC_CFG_REQ_ENABLES_LPBK 0x2UL
+ #define PORT_MAC_CFG_REQ_ENABLES_IVLAN_PRI2COS_MAP_PRI 0x4UL
+ #define PORT_MAC_CFG_REQ_ENABLES_LCOS_MAP_PRI 0x8UL
+ #define PORT_MAC_CFG_REQ_ENABLES_TUNNEL_PRI2COS_MAP_PRI 0x10UL
+ #define PORT_MAC_CFG_REQ_ENABLES_DSCP2COS_MAP_PRI 0x20UL
+ __le16 port_id;
+ u8 ipg;
+ u8 lpbk;
+ #define PORT_MAC_CFG_REQ_LPBK_NONE (0x0UL << 0)
+ #define PORT_MAC_CFG_REQ_LPBK_LOCAL (0x1UL << 0)
+ #define PORT_MAC_CFG_REQ_LPBK_REMOTE (0x2UL << 0)
+ u8 ivlan_pri2cos_map_pri;
+ u8 lcos_map_pri;
+ u8 tunnel_pri2cos_map_pri;
+ u8 dscp2pri_map_pri;
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_mac_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 mru;
+ __le16 mtu;
+ u8 ipg;
+ u8 lpbk;
+ #define PORT_MAC_CFG_RESP_LPBK_NONE (0x0UL << 0)
+ #define PORT_MAC_CFG_RESP_LPBK_LOCAL (0x1UL << 0)
+ #define PORT_MAC_CFG_RESP_LPBK_REMOTE (0x2UL << 0)
+ u8 unused_0;
+ u8 valid;
+};
+
+/* hwrm_port_enable */
+/* Input (24 bytes) */
+struct hwrm_port_enable_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define PORT_ENABLE_REQ_FLAGS_FORWARD_TRAFFIC 0x1UL
+ __le16 port_id;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_enable_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_port_qstats */
+/* Input (40 bytes) */
+struct hwrm_port_qstats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 port_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2[3];
+ u8 unused_3;
+ __le64 tx_stat_host_addr;
+ __le64 rx_stat_host_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_qstats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_port_lpbk_qstats */
+/* Input (16 bytes) */
+struct hwrm_port_lpbk_qstats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (64 bytes) */
+struct hwrm_port_lpbk_qstats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 lpbk_ucast_frames;
+ __le64 lpbk_mcast_frames;
+ __le64 lpbk_bcast_frames;
+ __le64 lpbk_ucast_bytes;
+ __le64 lpbk_mcast_bytes;
+ __le64 lpbk_bcast_bytes;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_port_clr_stats */
+/* Input (24 bytes) */
+struct hwrm_port_clr_stats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 port_id;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_clr_stats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_port_lpbk_clr_stats */
+/* Input (16 bytes) */
+struct hwrm_port_lpbk_clr_stats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_lpbk_clr_stats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_port_blink_led */
+/* Input (24 bytes) */
+struct hwrm_port_blink_led_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 num_blinks;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_port_blink_led_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_queue_qportcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_qportcfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define QUEUE_QPORTCFG_REQ_FLAGS_PATH 0x1UL
+ #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ __le16 port_id;
+ __le16 unused_0;
+};
+
+/* Output (32 bytes) */
+struct hwrm_queue_qportcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 max_configurable_queues;
+ u8 max_configurable_lossless_queues;
+ u8 queue_cfg_allowed;
+ u8 queue_buffers_cfg_allowed;
+ u8 queue_pfcenable_cfg_allowed;
+ u8 queue_pri2cos_cfg_allowed;
+ u8 queue_cos2bw_cfg_allowed;
+ u8 queue_id0;
+ u8 queue_id0_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id1;
+ u8 queue_id1_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID1_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID1_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID1_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id2;
+ u8 queue_id2_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID2_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID2_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID2_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id3;
+ u8 queue_id3_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID3_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID3_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID3_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id4;
+ u8 queue_id4_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID4_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID4_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID4_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id5;
+ u8 queue_id5_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID5_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID5_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID5_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id6;
+ u8 queue_id6_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID6_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID6_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID6_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 queue_id7;
+ u8 queue_id7_service_profile;
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID7_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID7_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_QPORTCFG_RESP_QUEUE_ID7_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 valid;
+};
+
+/* hwrm_queue_cfg */
+/* Input (40 bytes) */
+struct hwrm_queue_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define QUEUE_CFG_REQ_FLAGS_PATH 0x1UL
+ #define QUEUE_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define QUEUE_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ __le32 enables;
+ #define QUEUE_CFG_REQ_ENABLES_DFLT_LEN 0x1UL
+ #define QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE 0x2UL
+ __le32 queue_id;
+ __le32 dflt_len;
+ u8 service_profile;
+ #define QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY (0x0UL << 0)
+ #define QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS (0x1UL << 0)
+ #define QUEUE_CFG_REQ_SERVICE_PROFILE_UNKNOWN (0xffUL << 0)
+ u8 unused_0[7];
+};
+
+/* Output (16 bytes) */
+struct hwrm_queue_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_queue_buffers_cfg */
+/* Input (56 bytes) */
+struct hwrm_queue_buffers_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH 0x1UL
+ #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ __le32 enables;
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_RESERVED 0x1UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_SHARED 0x2UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_GROUP 0x4UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_XOFF 0x8UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_XON 0x10UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_FULL 0x20UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_NOTFULL 0x40UL
+ #define QUEUE_BUFFERS_CFG_REQ_ENABLES_MAX 0x80UL
+ __le32 queue_id;
+ __le32 reserved;
+ __le32 shared;
+ __le32 xoff;
+ __le32 xon;
+ __le32 full;
+ __le32 notfull;
+ __le32 max;
+};
+
+/* Output (16 bytes) */
+struct hwrm_queue_buffers_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_queue_pfcenable_cfg */
+/* Input (24 bytes) */
+struct hwrm_queue_pfcenable_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI0_PFC_ENABLED 0x1UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI1_PFC_ENABLED 0x2UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI2_PFC_ENABLED 0x4UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI3_PFC_ENABLED 0x8UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI4_PFC_ENABLED 0x10UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI5_PFC_ENABLED 0x20UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI6_PFC_ENABLED 0x40UL
+ #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI7_PFC_ENABLED 0x80UL
+ __le16 port_id;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_queue_pfcenable_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_queue_pri2cos_cfg */
+/* Input (40 bytes) */
+struct hwrm_queue_pri2cos_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH 0x1UL
+ #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ #define QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN 0x2UL
+ __le32 enables;
+ u8 port_id;
+ u8 pri0_cos;
+ u8 pri1_cos;
+ u8 pri2_cos;
+ u8 pri3_cos;
+ u8 pri4_cos;
+ u8 pri5_cos;
+ u8 pri6_cos;
+ u8 pri7_cos;
+ u8 unused_0[7];
+};
+
+/* Output (16 bytes) */
+struct hwrm_queue_pri2cos_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_queue_cos2bw_cfg */
+/* Input (128 bytes) */
+struct hwrm_queue_cos2bw_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ __le32 enables;
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID 0x1UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID1_VALID 0x2UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID2_VALID 0x4UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID3_VALID 0x8UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID4_VALID 0x10UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID5_VALID 0x20UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID6_VALID 0x40UL
+ #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID7_VALID 0x80UL
+ __le16 port_id;
+ u8 queue_id0;
+ u8 unused_0;
+ __le32 queue_id0_min_bw;
+ __le32 queue_id0_max_bw;
+ u8 queue_id0_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id0_pri_lvl;
+ u8 queue_id0_bw_weight;
+ u8 queue_id1;
+ __le32 queue_id1_min_bw;
+ __le32 queue_id1_max_bw;
+ u8 queue_id1_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id1_pri_lvl;
+ u8 queue_id1_bw_weight;
+ u8 queue_id2;
+ __le32 queue_id2_min_bw;
+ __le32 queue_id2_max_bw;
+ u8 queue_id2_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id2_pri_lvl;
+ u8 queue_id2_bw_weight;
+ u8 queue_id3;
+ __le32 queue_id3_min_bw;
+ __le32 queue_id3_max_bw;
+ u8 queue_id3_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id3_pri_lvl;
+ u8 queue_id3_bw_weight;
+ u8 queue_id4;
+ __le32 queue_id4_min_bw;
+ __le32 queue_id4_max_bw;
+ u8 queue_id4_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id4_pri_lvl;
+ u8 queue_id4_bw_weight;
+ u8 queue_id5;
+ __le32 queue_id5_min_bw;
+ __le32 queue_id5_max_bw;
+ u8 queue_id5_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id5_pri_lvl;
+ u8 queue_id5_bw_weight;
+ u8 queue_id6;
+ __le32 queue_id6_min_bw;
+ __le32 queue_id6_max_bw;
+ u8 queue_id6_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id6_pri_lvl;
+ u8 queue_id6_bw_weight;
+ u8 queue_id7;
+ __le32 queue_id7_min_bw;
+ __le32 queue_id7_max_bw;
+ u8 queue_id7_tsa_assign;
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_SP (0x0UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_ETS (0x1UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0)
+ #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0)
+ u8 queue_id7_pri_lvl;
+ u8 queue_id7_bw_weight;
+ u8 unused_1[5];
+};
+
+/* Output (16 bytes) */
+struct hwrm_queue_cos2bw_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_vnic_alloc */
+/* Input (24 bytes) */
+struct hwrm_vnic_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define VNIC_ALLOC_REQ_FLAGS_DEFAULT 0x1UL
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 vnic_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_vnic_free */
+/* Input (24 bytes) */
+struct hwrm_vnic_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 vnic_id;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_vnic_cfg */
+/* Input (40 bytes) */
+struct hwrm_vnic_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define VNIC_CFG_REQ_FLAGS_DEFAULT 0x1UL
+ #define VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE 0x2UL
+ __le32 enables;
+ #define VNIC_CFG_REQ_ENABLES_DFLT_RING_GRP 0x1UL
+ #define VNIC_CFG_REQ_ENABLES_RSS_RULE 0x2UL
+ #define VNIC_CFG_REQ_ENABLES_COS_RULE 0x4UL
+ #define VNIC_CFG_REQ_ENABLES_LB_RULE 0x8UL
+ #define VNIC_CFG_REQ_ENABLES_MRU 0x10UL
+ __le16 vnic_id;
+ __le16 dflt_ring_grp;
+ __le16 rss_rule;
+ __le16 cos_rule;
+ __le16 lb_rule;
+ __le16 mru;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_vnic_tpa_cfg */
+/* Input (40 bytes) */
+struct hwrm_vnic_tpa_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define VNIC_TPA_CFG_REQ_FLAGS_TPA 0x1UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_ENCAP_TPA 0x2UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_RSC_WND_UPDATE 0x4UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_GRO 0x8UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_ECN 0x10UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_SAME_GRE_SEQ 0x20UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_GRO_IPID_CHECK 0x40UL
+ #define VNIC_TPA_CFG_REQ_FLAGS_GRO_TTL_CHECK 0x80UL
+ __le32 enables;
+ #define VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_SEGS 0x1UL
+ #define VNIC_TPA_CFG_REQ_ENABLES_MAX_AGGS 0x2UL
+ #define VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_TIMER 0x4UL
+ #define VNIC_TPA_CFG_REQ_ENABLES_MIN_AGG_LEN 0x8UL
+ __le16 vnic_id;
+ __le16 max_agg_segs;
+ #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_1 (0x0UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_2 (0x1UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_4 (0x2UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_8 (0x3UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_MAX (0x1fUL << 0)
+ __le16 max_aggs;
+ #define VNIC_TPA_CFG_REQ_MAX_AGGS_1 (0x0UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGGS_2 (0x1UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGGS_4 (0x2UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGGS_8 (0x3UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGGS_16 (0x4UL << 0)
+ #define VNIC_TPA_CFG_REQ_MAX_AGGS_MAX (0x7UL << 0)
+ u8 unused_0;
+ u8 unused_1;
+ __le32 max_agg_timer;
+ __le32 min_agg_len;
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_tpa_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_vnic_rss_cfg */
+/* Input (48 bytes) */
+struct hwrm_vnic_rss_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 hash_type;
+ #define VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 0x1UL
+ #define VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 0x2UL
+ #define VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 0x4UL
+ #define VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 0x8UL
+ #define VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6 0x10UL
+ #define VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6 0x20UL
+ __le32 unused_0;
+ __le64 ring_grp_tbl_addr;
+ __le64 hash_key_tbl_addr;
+ __le16 rss_ctx_idx;
+ __le16 unused_1[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_rss_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_vnic_plcmodes_cfg */
+/* Input (40 bytes) */
+struct hwrm_vnic_plcmodes_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define VNIC_PLCMODES_CFG_REQ_FLAGS_REGULAR_PLACEMENT 0x1UL
+ #define VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT 0x2UL
+ #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 0x4UL
+ #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6 0x8UL
+ #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_FCOE 0x10UL
+ #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_ROCE 0x20UL
+ __le32 enables;
+ #define VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID 0x1UL
+ #define VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_OFFSET_VALID 0x2UL
+ #define VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID 0x4UL
+ __le32 vnic_id;
+ __le16 jumbo_thresh;
+ __le16 hds_offset;
+ __le16 hds_threshold;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_plcmodes_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_vnic_rss_cos_lb_ctx_alloc */
+/* Input (16 bytes) */
+struct hwrm_vnic_rss_cos_lb_ctx_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_rss_cos_lb_ctx_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 rss_cos_lb_ctx_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_vnic_rss_cos_lb_ctx_free */
+/* Input (24 bytes) */
+struct hwrm_vnic_rss_cos_lb_ctx_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 rss_cos_lb_ctx_id;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_vnic_rss_cos_lb_ctx_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_ring_alloc */
+/* Input (80 bytes) */
+struct hwrm_ring_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define RING_ALLOC_REQ_ENABLES_ARB_GRP_ID_VALID 0x1UL
+ #define RING_ALLOC_REQ_ENABLES_INPUT_NUM_VALID 0x2UL
+ #define RING_ALLOC_REQ_ENABLES_WEIGHT_VALID 0x4UL
+ #define RING_ALLOC_REQ_ENABLES_STAT_CTX_ID_VALID 0x8UL
+ #define RING_ALLOC_REQ_ENABLES_MIN_BW_VALID 0x10UL
+ #define RING_ALLOC_REQ_ENABLES_MAX_BW_VALID 0x20UL
+ u8 ring_type;
+ #define RING_ALLOC_REQ_RING_TYPE_CMPL (0x0UL << 0)
+ #define RING_ALLOC_REQ_RING_TYPE_TX (0x1UL << 0)
+ #define RING_ALLOC_REQ_RING_TYPE_RX (0x2UL << 0)
+ #define RING_ALLOC_REQ_RING_TYPE_STATUS (0x3UL << 0)
+ #define RING_ALLOC_REQ_RING_TYPE_CMD (0x4UL << 0)
+ u8 unused_0;
+ __le16 unused_1;
+ __le64 page_tbl_addr;
+ __le32 fbo;
+ u8 page_size;
+ u8 page_tbl_depth;
+ u8 unused_2;
+ u8 unused_3;
+ __le32 length;
+ __le16 logical_id;
+ __le16 cmpl_ring_id;
+ __le16 queue_id;
+ u8 unused_4;
+ u8 unused_5;
+ __le32 arb_grp_id;
+ __le16 input_number;
+ u8 unused_6;
+ u8 unused_7;
+ __le32 weight;
+ __le32 stat_ctx_id;
+ __le32 min_bw;
+ __le32 max_bw;
+ u8 int_mode;
+ #define RING_ALLOC_REQ_INT_MODE_LEGACY (0x0UL << 0)
+ #define RING_ALLOC_REQ_INT_MODE_MSI (0x1UL << 0)
+ #define RING_ALLOC_REQ_INT_MODE_MSIX (0x2UL << 0)
+ #define RING_ALLOC_REQ_INT_MODE_POLL (0x3UL << 0)
+ u8 unused_8[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_ring_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 ring_id;
+ __le16 logical_ring_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_ring_free */
+/* Input (24 bytes) */
+struct hwrm_ring_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 ring_type;
+ #define RING_FREE_REQ_RING_TYPE_CMPL (0x0UL << 0)
+ #define RING_FREE_REQ_RING_TYPE_TX (0x1UL << 0)
+ #define RING_FREE_REQ_RING_TYPE_RX (0x2UL << 0)
+ #define RING_FREE_REQ_RING_TYPE_STATUS (0x3UL << 0)
+ #define RING_FREE_REQ_RING_TYPE_CMD (0x4UL << 0)
+ u8 unused_0;
+ __le16 ring_id;
+ __le32 unused_1;
+};
+
+/* Output (16 bytes) */
+struct hwrm_ring_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_ring_cmpl_ring_qaggint_params */
+/* Input (24 bytes) */
+struct hwrm_ring_cmpl_ring_qaggint_params_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 ring_id;
+ __le16 unused_0[3];
+};
+
+/* Output (32 bytes) */
+struct hwrm_ring_cmpl_ring_qaggint_params_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 flags;
+ #define RING_CMPL_RING_QAGGINT_PARAMS_RESP_FLAGS_TIMER_RESET 0x1UL
+ #define RING_CMPL_RING_QAGGINT_PARAMS_RESP_FLAGS_RING_IDLE 0x2UL
+ __le16 num_cmpl_dma_aggr;
+ __le16 num_cmpl_dma_aggr_during_int;
+ __le16 cmpl_aggr_dma_tmr;
+ __le16 cmpl_aggr_dma_tmr_during_int;
+ __le16 int_lat_tmr_min;
+ __le16 int_lat_tmr_max;
+ __le16 num_cmpl_aggr_int;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_ring_cmpl_ring_cfg_aggint_params */
+/* Input (40 bytes) */
+struct hwrm_ring_cmpl_ring_cfg_aggint_params_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 ring_id;
+ __le16 flags;
+ #define RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_TIMER_RESET 0x1UL
+ #define RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_RING_IDLE 0x2UL
+ __le16 num_cmpl_dma_aggr;
+ __le16 num_cmpl_dma_aggr_during_int;
+ __le16 cmpl_aggr_dma_tmr;
+ __le16 cmpl_aggr_dma_tmr_during_int;
+ __le16 int_lat_tmr_min;
+ __le16 int_lat_tmr_max;
+ __le16 num_cmpl_aggr_int;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_ring_cmpl_ring_cfg_aggint_params_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_ring_reset */
+/* Input (24 bytes) */
+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_CMPL (0x0UL << 0)
+ #define RING_RESET_REQ_RING_TYPE_TX (0x1UL << 0)
+ #define RING_RESET_REQ_RING_TYPE_RX (0x2UL << 0)
+ #define RING_RESET_REQ_RING_TYPE_STATUS (0x3UL << 0)
+ #define RING_RESET_REQ_RING_TYPE_CMD (0x4UL << 0)
+ u8 unused_0;
+ __le16 ring_id;
+ __le32 unused_1;
+};
+
+/* Output (16 bytes) */
+struct hwrm_ring_reset_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_ring_grp_alloc */
+/* Input (24 bytes) */
+struct hwrm_ring_grp_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 cr;
+ __le16 rr;
+ __le16 ar;
+ __le16 sc;
+};
+
+/* Output (16 bytes) */
+struct hwrm_ring_grp_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 ring_group_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_ring_grp_free */
+/* Input (24 bytes) */
+struct hwrm_ring_grp_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 ring_group_id;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_ring_grp_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_arb_grp_alloc */
+/* Input (24 bytes) */
+struct hwrm_arb_grp_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 input_number;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_arb_grp_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 arb_grp_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_arb_grp_cfg */
+/* Input (32 bytes) */
+struct hwrm_arb_grp_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 arb_grp_id;
+ __le16 input_number;
+ __le16 tx_ring;
+ __le32 weight;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_arb_grp_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_l2_filter_alloc */
+/* Input (96 bytes) */
+struct hwrm_cfa_l2_filter_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH 0x1UL
+ #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x2UL
+ #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_DROP 0x4UL
+ #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_OUTERMOST 0x8UL
+ __le32 enables;
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR 0x1UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR_MASK 0x2UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_OVLAN 0x4UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_OVLAN_MASK 0x8UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN 0x10UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN_MASK 0x20UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_ADDR 0x40UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_ADDR_MASK 0x80UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_OVLAN 0x100UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_OVLAN_MASK 0x200UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_IVLAN 0x400UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_IVLAN_MASK 0x800UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_SRC_TYPE 0x1000UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_SRC_ID 0x2000UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x4000UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID 0x8000UL
+ #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x10000UL
+ u8 l2_addr[6];
+ u8 unused_0;
+ u8 unused_1;
+ u8 l2_addr_mask[6];
+ __le16 l2_ovlan;
+ __le16 l2_ovlan_mask;
+ __le16 l2_ivlan;
+ __le16 l2_ivlan_mask;
+ u8 unused_2;
+ u8 unused_3;
+ u8 t_l2_addr[6];
+ u8 unused_4;
+ u8 unused_5;
+ u8 t_l2_addr_mask[6];
+ __le16 t_l2_ovlan;
+ __le16 t_l2_ovlan_mask;
+ __le16 t_l2_ivlan;
+ __le16 t_l2_ivlan_mask;
+ u8 src_type;
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_NPORT (0x0UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_PF (0x1UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_VF (0x2UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_VNIC (0x3UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_KONG (0x4UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_APE (0x5UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_BONO (0x6UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_TANG (0x7UL << 0)
+ u8 unused_6;
+ __le32 src_id;
+ u8 tunnel_type;
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0)
+ u8 unused_7;
+ __le16 dst_vnic_id;
+ __le16 mirror_vnic_id;
+ u8 pri_hint;
+ #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_NO_PREFER (0x0UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_ABOVE_FILTER (0x1UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_BELOW_FILTER (0x2UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_MAX (0x3UL << 0)
+ #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_MIN (0x4UL << 0)
+ u8 unused_8;
+ __le32 unused_9;
+ __le64 l2_filter_id_hint;
+};
+
+/* Output (24 bytes) */
+struct hwrm_cfa_l2_filter_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 l2_filter_id;
+ __le32 flow_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_cfa_l2_filter_free */
+/* Input (24 bytes) */
+struct hwrm_cfa_l2_filter_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 l2_filter_id;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_l2_filter_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_l2_filter_cfg */
+/* Input (40 bytes) */
+struct hwrm_cfa_l2_filter_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH 0x1UL
+ #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ #define CFA_L2_FILTER_CFG_REQ_FLAGS_DROP 0x2UL
+ __le32 enables;
+ #define CFA_L2_FILTER_CFG_REQ_ENABLES_DST_VNIC_ID_VALID 0x1UL
+ __le64 l2_filter_id;
+ __le32 dst_vnic_id;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_l2_filter_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_l2_set_rx_mask */
+/* Input (40 bytes) */
+struct hwrm_cfa_l2_set_rx_mask_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 dflt_vnic_id;
+ __le32 mask;
+ #define CFA_L2_SET_RX_MASK_REQ_MASK_UNICAST 0x1UL
+ #define CFA_L2_SET_RX_MASK_REQ_MASK_MCAST 0x2UL
+ #define CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST 0x4UL
+ #define CFA_L2_SET_RX_MASK_REQ_MASK_BCAST 0x8UL
+ #define CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS 0x10UL
+ #define CFA_L2_SET_RX_MASK_REQ_MASK_OUTERMOST 0x20UL
+ __le64 mc_tbl_addr;
+ __le32 num_mc_entries;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_l2_set_rx_mask_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_l2_set_bcastmcast_mirroring */
+/* Input (32 bytes) */
+struct hwrm_cfa_l2_set_bcastmcast_mirroring_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 dflt_vnic_id;
+ __le32 mirroring_flags;
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_BCAST_MIRRORING 0x1UL
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_MCAST_MIRRORING 0x2UL
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_BCAST_SRC_KNOCKOUT 0x4UL
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_MCAST_SRC_KNOCKOUT 0x8UL
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_VLAN_ID_VALID 0x10UL
+ __le16 vlan_id;
+ u8 bcast_domain;
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_BCAST_DOMAIN_PFONLY (0x0UL << 0)
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_BCAST_DOMAIN_ALLPFS (0x1UL << 0)
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_BCAST_DOMAIN_ALLPFSVFS (0x2UL << 0)
+ u8 mcast_domain;
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MCAST_DOMAIN_PFONLY (0x0UL << 0)
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MCAST_DOMAIN_ALLPFS (0x1UL << 0)
+ #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MCAST_DOMAIN_ALLPFSVFS (0x2UL << 0)
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_l2_set_bcastmcast_mirroring_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_tunnel_filter_alloc */
+/* Input (88 bytes) */
+struct hwrm_cfa_tunnel_filter_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL
+ __le32 enables;
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L2_ADDR 0x2UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN 0x4UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L3_ADDR 0x8UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L3_ADDR_TYPE 0x10UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_T_L3_ADDR_TYPE 0x20UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_T_L3_ADDR 0x40UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x80UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_VNI 0x100UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID 0x200UL
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x400UL
+ __le64 l2_filter_id;
+ u8 l2_addr[6];
+ __le16 l2_ivlan;
+ __le32 l3_addr[4];
+ __le32 t_l3_addr[4];
+ u8 l3_addr_type;
+ u8 t_l3_addr_type;
+ u8 tunnel_type;
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0)
+ #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0)
+ u8 unused_0;
+ __le32 vni;
+ __le32 dst_vnic_id;
+ __le32 mirror_vnic_id;
+};
+
+/* Output (24 bytes) */
+struct hwrm_cfa_tunnel_filter_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 tunnel_filter_id;
+ __le32 flow_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_cfa_tunnel_filter_free */
+/* Input (24 bytes) */
+struct hwrm_cfa_tunnel_filter_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 tunnel_filter_id;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_tunnel_filter_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_encap_record_alloc */
+/* Input (32 bytes) */
+struct hwrm_cfa_encap_record_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL
+ u8 encap_type;
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN (0x1UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_NVGRE (0x2UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2GRE (0x3UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPIP (0x4UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_GENEVE (0x5UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_MPLS (0x6UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VLAN (0x7UL << 0)
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE (0x8UL << 0)
+ u8 unused_0;
+ __le16 unused_1;
+ __le32 encap_data[16];
+};
+
+/* Output (24 bytes) */
+struct hwrm_cfa_encap_record_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 encap_record_id;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_encap_record_free */
+/* Input (24 bytes) */
+struct hwrm_cfa_encap_record_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 encap_record_id;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_encap_record_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_ntuple_filter_alloc */
+/* Input (128 bytes) */
+struct hwrm_cfa_ntuple_filter_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DROP 0x2UL
+ __le32 enables;
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE 0x2UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x4UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_MACADDR 0x8UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IPADDR_TYPE 0x10UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR 0x20UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR_MASK 0x40UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR 0x80UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR_MASK 0x100UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IP_PROTOCOL 0x200UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT 0x400UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT_MASK 0x800UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT 0x1000UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT_MASK 0x2000UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_PRI_HINT 0x4000UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_NTUPLE_FILTER_ID 0x8000UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID 0x10000UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x20000UL
+ __le64 l2_filter_id;
+ u8 src_macaddr[6];
+ __be16 ethertype;
+ u8 ipaddr_type;
+ u8 ip_protocol;
+ __le16 dst_vnic_id;
+ __le16 mirror_vnic_id;
+ u8 tunnel_type;
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0)
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0)
+ u8 pri_hint;
+ __be32 src_ipaddr[4];
+ __be32 src_ipaddr_mask[4];
+ __be32 dst_ipaddr[4];
+ __be32 dst_ipaddr_mask[4];
+ __be16 src_port;
+ __be16 src_port_mask;
+ __be16 dst_port;
+ __be16 dst_port_mask;
+ __le64 ntuple_filter_id_hint;
+};
+
+/* Output (24 bytes) */
+struct hwrm_cfa_ntuple_filter_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 ntuple_filter_id;
+ __le32 flow_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_cfa_ntuple_filter_free */
+/* Input (24 bytes) */
+struct hwrm_cfa_ntuple_filter_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 ntuple_filter_id;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_ntuple_filter_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_cfa_ntuple_filter_cfg */
+/* Input (40 bytes) */
+struct hwrm_cfa_ntuple_filter_cfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_DST_VNIC_ID_VALID 0x1UL
+ #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_MIRROR_VNIC_ID_VALID 0x2UL
+ __le32 unused_0;
+ __le64 ntuple_filter_id;
+ __le32 new_dst_vnic_id;
+ __le32 new_mirror_vnic_id;
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_ntuple_filter_cfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_tunnel_dst_port_query */
+/* Input (24 bytes) */
+struct hwrm_tunnel_dst_port_query_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 tunnel_type;
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_STT (0x7UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0)
+ #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0)
+ u8 unused_0[7];
+};
+
+/* Output (16 bytes) */
+struct hwrm_tunnel_dst_port_query_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 tunnel_dst_port_id;
+ __be16 tunnel_dst_port_val;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_tunnel_dst_port_alloc */
+/* Input (24 bytes) */
+struct hwrm_tunnel_dst_port_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 tunnel_type;
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0)
+ #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0)
+ u8 unused_0;
+ __be16 tunnel_dst_port_val;
+ __le32 unused_1;
+};
+
+/* Output (16 bytes) */
+struct hwrm_tunnel_dst_port_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 tunnel_dst_port_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_tunnel_dst_port_free */
+/* Input (24 bytes) */
+struct hwrm_tunnel_dst_port_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 tunnel_type;
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_STT (0x7UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0)
+ #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0)
+ u8 unused_0;
+ __le16 tunnel_dst_port_id;
+ __le32 unused_1;
+};
+
+/* Output (16 bytes) */
+struct hwrm_tunnel_dst_port_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_stat_ctx_alloc */
+/* Input (32 bytes) */
+struct hwrm_stat_ctx_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 stats_dma_addr;
+ __le32 update_period_ms;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_stat_ctx_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 stat_ctx_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_stat_ctx_free */
+/* Input (24 bytes) */
+struct hwrm_stat_ctx_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 stat_ctx_id;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_stat_ctx_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 stat_ctx_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_stat_ctx_query */
+/* Input (24 bytes) */
+struct hwrm_stat_ctx_query_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 stat_ctx_id;
+ __le32 unused_0;
+};
+
+/* Output (176 bytes) */
+struct hwrm_stat_ctx_query_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le64 tx_ucast_pkts;
+ __le64 tx_mcast_pkts;
+ __le64 tx_bcast_pkts;
+ __le64 tx_err_pkts;
+ __le64 tx_drop_pkts;
+ __le64 tx_ucast_bytes;
+ __le64 tx_mcast_bytes;
+ __le64 tx_bcast_bytes;
+ __le64 rx_ucast_pkts;
+ __le64 rx_mcast_pkts;
+ __le64 rx_bcast_pkts;
+ __le64 rx_err_pkts;
+ __le64 rx_drop_pkts;
+ __le64 rx_ucast_bytes;
+ __le64 rx_mcast_bytes;
+ __le64 rx_bcast_bytes;
+ __le64 rx_agg_pkts;
+ __le64 rx_agg_bytes;
+ __le64 rx_agg_events;
+ __le64 rx_agg_aborts;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_stat_ctx_clr_stats */
+/* Input (24 bytes) */
+struct hwrm_stat_ctx_clr_stats_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 stat_ctx_id;
+ __le32 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_stat_ctx_clr_stats_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_mgmt_l2_filter_alloc */
+/* Input (56 bytes) */
+struct hwrm_mgmt_l2_filter_alloc_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define MGMT_L2_FILTER_ALLOC_REQ_FLAGS_PATH 0x1UL
+ #define MGMT_L2_FILTER_ALLOC_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define MGMT_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ __le32 enables;
+ #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDRESS 0x1UL
+ #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_OVLAN 0x2UL
+ #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_IVLAN 0x4UL
+ #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_ACTION_ID 0x8UL
+ u8 l2_address[6];
+ u8 unused_0;
+ u8 unused_1;
+ u8 l2_address_mask[6];
+ __le16 ovlan;
+ __le16 ovlan_mask;
+ __le16 ivlan;
+ __le16 ivlan_mask;
+ u8 unused_2;
+ u8 unused_3;
+ __le32 action_id;
+ u8 action_bypass;
+ #define MGMT_L2_FILTER_ALLOC_REQ_ACTION_BYPASS 0x1UL
+ u8 unused_5[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_mgmt_l2_filter_alloc_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 mgmt_l2_filter_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_mgmt_l2_filter_free */
+/* Input (24 bytes) */
+struct hwrm_mgmt_l2_filter_free_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 mgmt_l2_filter_id;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_mgmt_l2_filter_free_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_raw_write_blk */
+/* Input (32 bytes) */
+struct hwrm_nvm_raw_write_blk_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 host_src_addr;
+ __le32 dest_addr;
+ __le32 len;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_raw_write_blk_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_read */
+/* Input (40 bytes) */
+struct hwrm_nvm_read_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 host_dest_addr;
+ __le16 dir_idx;
+ u8 unused_0;
+ u8 unused_1;
+ __le32 offset;
+ __le32 len;
+ __le32 unused_2;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_read_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_raw_dump */
+/* Input (32 bytes) */
+struct hwrm_nvm_raw_dump_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 host_dest_addr;
+ __le32 offset;
+ __le32 len;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_raw_dump_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_get_dir_entries */
+/* Input (24 bytes) */
+struct hwrm_nvm_get_dir_entries_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 host_dest_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_get_dir_entries_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_get_dir_info */
+/* Input (16 bytes) */
+struct hwrm_nvm_get_dir_info_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (24 bytes) */
+struct hwrm_nvm_get_dir_info_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 entries;
+ __le32 entry_length;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_write */
+/* Input (40 bytes) */
+struct hwrm_nvm_write_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 host_src_addr;
+ __le16 dir_type;
+ __le16 dir_ordinal;
+ __le16 dir_ext;
+ __le16 dir_attr;
+ __le32 dir_data_length;
+ __le16 option;
+ __le16 flags;
+ #define NVM_WRITE_REQ_FLAGS_KEEP_ORIG_ACTIVE_IMG 0x1UL
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_write_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_modify */
+/* Input (40 bytes) */
+struct hwrm_nvm_modify_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 host_src_addr;
+ __le16 dir_idx;
+ u8 unused_0;
+ u8 unused_1;
+ __le32 offset;
+ __le32 len;
+ __le32 unused_2;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_modify_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_find_dir_entry */
+/* Input (32 bytes) */
+struct hwrm_nvm_find_dir_entry_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define NVM_FIND_DIR_ENTRY_REQ_ENABLES_DIR_IDX_VALID 0x1UL
+ __le16 dir_idx;
+ __le16 dir_type;
+ __le16 dir_ordinal;
+ __le16 dir_ext;
+ u8 opt_ordinal;
+ #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_MASK 0x3UL
+ #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_SFT 0
+ #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_EQ (0x0UL << 0)
+ #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_GE (0x1UL << 0)
+ #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_GT (0x2UL << 0)
+ u8 unused_1[3];
+};
+
+/* Output (32 bytes) */
+struct hwrm_nvm_find_dir_entry_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 dir_item_length;
+ __le32 dir_data_length;
+ __le32 fw_ver;
+ __le16 dir_ordinal;
+ __le16 dir_idx;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_erase_dir_entry */
+/* Input (24 bytes) */
+struct hwrm_nvm_erase_dir_entry_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 dir_idx;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_erase_dir_entry_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_get_dev_info */
+/* Input (16 bytes) */
+struct hwrm_nvm_get_dev_info_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (32 bytes) */
+struct hwrm_nvm_get_dev_info_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 manufacturer_id;
+ __le16 device_id;
+ __le32 sector_size;
+ __le32 nvram_size;
+ __le32 reserved_size;
+ __le32 available_size;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* hwrm_nvm_mod_dir_entry */
+/* Input (32 bytes) */
+struct hwrm_nvm_mod_dir_entry_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 enables;
+ #define NVM_MOD_DIR_ENTRY_REQ_ENABLES_CHECKSUM 0x1UL
+ __le16 dir_idx;
+ __le16 dir_ordinal;
+ __le16 dir_ext;
+ __le16 dir_attr;
+ __le32 checksum;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_mod_dir_entry_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_nvm_verify_update */
+/* Input (24 bytes) */
+struct hwrm_nvm_verify_update_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 dir_type;
+ __le16 dir_ordinal;
+ __le16 dir_ext;
+ __le16 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_verify_update_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_exec_fwd_resp */
+/* Input (120 bytes) */
+struct hwrm_exec_fwd_resp_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 encap_request[24];
+ __le16 encap_resp_target_id;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_exec_fwd_resp_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_reject_fwd_resp */
+/* Input (120 bytes) */
+struct hwrm_reject_fwd_resp_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 encap_request[24];
+ __le16 encap_resp_target_id;
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_reject_fwd_resp_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_fwd_resp */
+/* Input (40 bytes) */
+struct hwrm_fwd_resp_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 encap_resp_target_id;
+ __le16 encap_resp_cmpl_ring;
+ __le16 encap_resp_len;
+ u8 unused_0;
+ u8 unused_1;
+ __le64 encap_resp_addr;
+ __le32 encap_resp[24];
+};
+
+/* Output (16 bytes) */
+struct hwrm_fwd_resp_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_fwd_async_event_cmpl */
+/* Input (32 bytes) */
+struct hwrm_fwd_async_event_cmpl_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 encap_async_event_target_id;
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2[3];
+ u8 unused_3;
+ __le32 encap_async_event_cmpl[4];
+};
+
+/* Output (16 bytes) */
+struct hwrm_fwd_async_event_cmpl_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* hwrm_fw_reset */
+/* Input (24 bytes) */
+struct hwrm_fw_reset_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 embedded_proc_type;
+ #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIMP (0x0UL << 0)
+ #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_APE (0x1UL << 0)
+ #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_KONG (0x2UL << 0)
+ #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_BONO (0x3UL << 0)
+ #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_TANG (0x4UL << 0)
+ u8 selfrst_status;
+ #define FW_RESET_REQ_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0)
+ #define FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0)
+ #define FW_RESET_REQ_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0)
+ __le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_fw_reset_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 selfrst_status;
+ #define FW_RESET_RESP_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0)
+ #define FW_RESET_RESP_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0)
+ #define FW_RESET_RESP_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0)
+ u8 unused_0;
+ __le16 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_fw_qstatus */
+/* Input (24 bytes) */
+struct hwrm_fw_qstatus_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 embedded_proc_type;
+ #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_CHIMP (0x0UL << 0)
+ #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_APE (0x1UL << 0)
+ #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_KONG (0x2UL << 0)
+ #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_BONO (0x3UL << 0)
+ #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_TANG (0x4UL << 0)
+ u8 unused_0[7];
+};
+
+/* Output (16 bytes) */
+struct hwrm_fw_qstatus_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 selfrst_status;
+ #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0)
+ #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0)
+ #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0)
+ u8 unused_0;
+ __le16 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+/* hwrm_temp_monitor_query */
+/* Input (16 bytes) */
+struct hwrm_temp_monitor_query_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* Output (16 bytes) */
+struct hwrm_temp_monitor_query_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 temp;
+ u8 unused_0;
+ __le16 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h
new file mode 100644
index 000000000000..3cf3e1b70b64
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h
@@ -0,0 +1,59 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#ifndef _BNXT_NVM_DEFS_H_
+#define _BNXT_NVM_DEFS_H_
+
+enum bnxt_nvm_directory_type {
+ BNX_DIR_TYPE_UNUSED = 0,
+ BNX_DIR_TYPE_PKG_LOG = 1,
+ BNX_DIR_TYPE_CHIMP_PATCH = 3,
+ BNX_DIR_TYPE_BOOTCODE = 4,
+ BNX_DIR_TYPE_VPD = 5,
+ BNX_DIR_TYPE_EXP_ROM_MBA = 6,
+ BNX_DIR_TYPE_AVS = 7,
+ BNX_DIR_TYPE_PCIE = 8,
+ BNX_DIR_TYPE_PORT_MACRO = 9,
+ BNX_DIR_TYPE_APE_FW = 10,
+ BNX_DIR_TYPE_APE_PATCH = 11,
+ BNX_DIR_TYPE_KONG_FW = 12,
+ BNX_DIR_TYPE_KONG_PATCH = 13,
+ BNX_DIR_TYPE_BONO_FW = 14,
+ BNX_DIR_TYPE_BONO_PATCH = 15,
+ BNX_DIR_TYPE_TANG_FW = 16,
+ BNX_DIR_TYPE_TANG_PATCH = 17,
+ BNX_DIR_TYPE_BOOTCODE_2 = 18,
+ BNX_DIR_TYPE_CCM = 19,
+ BNX_DIR_TYPE_PCI_CFG = 20,
+ BNX_DIR_TYPE_TSCF_UCODE = 21,
+ BNX_DIR_TYPE_ISCSI_BOOT = 22,
+ BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24,
+ BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25,
+ BNX_DIR_TYPE_ISCSI_BOOT_CFG6 = 26,
+ BNX_DIR_TYPE_EXT_PHY = 27,
+ BNX_DIR_TYPE_SHARED_CFG = 40,
+ BNX_DIR_TYPE_PORT_CFG = 41,
+ BNX_DIR_TYPE_FUNC_CFG = 42,
+ BNX_DIR_TYPE_MGMT_CFG = 48,
+ BNX_DIR_TYPE_MGMT_DATA = 49,
+ BNX_DIR_TYPE_MGMT_WEB_DATA = 50,
+ BNX_DIR_TYPE_MGMT_WEB_META = 51,
+ BNX_DIR_TYPE_MGMT_EVENT_LOG = 52,
+ BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53
+};
+
+#define BNX_DIR_ORDINAL_FIRST 0
+
+#define BNX_DIR_EXT_INACTIVE (1 << 0)
+#define BNX_DIR_EXT_UPDATE (1 << 1)
+
+#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0)
+#define BNX_DIR_ATTR_PROP_STREAM (1 << 1)
+
+#endif /* Don't add anything after this line */
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
new file mode 100644
index 000000000000..f4cf68861069
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -0,0 +1,830 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
+#include <linux/etherdevice.h>
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_sriov.h"
+#include "bnxt_ethtool.h"
+
+#ifdef CONFIG_BNXT_SRIOV
+static int bnxt_vf_ndo_prep(struct bnxt *bp, int vf_id)
+{
+ if (bp->state != BNXT_STATE_OPEN) {
+ netdev_err(bp->dev, "vf ndo called though PF is down\n");
+ return -EINVAL;
+ }
+ if (!bp->pf.active_vfs) {
+ netdev_err(bp->dev, "vf ndo called though sriov is disabled\n");
+ return -EINVAL;
+ }
+ if (vf_id >= bp->pf.max_vfs) {
+ netdev_err(bp->dev, "Invalid VF id %d\n", vf_id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
+{
+ struct hwrm_func_cfg_input req = {0};
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vf_info *vf;
+ bool old_setting = false;
+ u32 func_flags;
+ int rc;
+
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+
+ vf = &bp->pf.vf[vf_id];
+ if (vf->flags & BNXT_VF_SPOOFCHK)
+ old_setting = true;
+ if (old_setting == setting)
+ return 0;
+
+ func_flags = vf->func_flags;
+ if (setting)
+ func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK;
+ else
+ func_flags &= ~FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK;
+ /*TODO: if the driver supports VLAN filter on guest VLAN,
+ * the spoof check should also include vlan anti-spoofing
+ */
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+ req.vf_id = cpu_to_le16(vf->fw_fid);
+ req.flags = cpu_to_le32(func_flags);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc) {
+ vf->func_flags = func_flags;
+ if (setting)
+ vf->flags |= BNXT_VF_SPOOFCHK;
+ else
+ vf->flags &= ~BNXT_VF_SPOOFCHK;
+ }
+ return rc;
+}
+
+int bnxt_get_vf_config(struct net_device *dev, int vf_id,
+ struct ifla_vf_info *ivi)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vf_info *vf;
+ int rc;
+
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+
+ ivi->vf = vf_id;
+ vf = &bp->pf.vf[vf_id];
+
+ memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN);
+ ivi->max_tx_rate = vf->max_tx_rate;
+ ivi->min_tx_rate = vf->min_tx_rate;
+ ivi->vlan = vf->vlan;
+ ivi->qos = vf->flags & BNXT_VF_QOS;
+ ivi->spoofchk = vf->flags & BNXT_VF_SPOOFCHK;
+ if (!(vf->flags & BNXT_VF_LINK_FORCED))
+ ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;
+ else if (vf->flags & BNXT_VF_LINK_UP)
+ ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE;
+ else
+ ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE;
+
+ return 0;
+}
+
+int bnxt_set_vf_mac(struct net_device *dev, int vf_id, u8 *mac)
+{
+ struct hwrm_func_cfg_input req = {0};
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vf_info *vf;
+ int rc;
+
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+ /* reject bc or mc mac addr, zero mac addr means allow
+ * VF to use its own mac addr
+ */
+ if (is_multicast_ether_addr(mac)) {
+ netdev_err(dev, "Invalid VF ethernet address\n");
+ return -EINVAL;
+ }
+ vf = &bp->pf.vf[vf_id];
+
+ memcpy(vf->mac_addr, mac, ETH_ALEN);
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+ req.vf_id = cpu_to_le16(vf->fw_fid);
+ req.flags = cpu_to_le32(vf->func_flags);
+ req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR);
+ memcpy(req.dflt_mac_addr, mac, ETH_ALEN);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos)
+{
+ struct hwrm_func_cfg_input req = {0};
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vf_info *vf;
+ u16 vlan_tag;
+ int rc;
+
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+
+ /* TODO: needed to implement proper handling of user priority,
+ * currently fail the command if there is valid priority
+ */
+ if (vlan_id > 4095 || qos)
+ return -EINVAL;
+
+ vf = &bp->pf.vf[vf_id];
+ vlan_tag = vlan_id;
+ if (vlan_tag == vf->vlan)
+ return 0;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+ req.vf_id = cpu_to_le16(vf->fw_fid);
+ req.flags = cpu_to_le32(vf->func_flags);
+ req.dflt_vlan = cpu_to_le16(vlan_tag);
+ req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc)
+ vf->vlan = vlan_tag;
+ return rc;
+}
+
+int bnxt_set_vf_bw(struct net_device *dev, int vf_id, int min_tx_rate,
+ int max_tx_rate)
+{
+ struct hwrm_func_cfg_input req = {0};
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vf_info *vf;
+ u32 pf_link_speed;
+ int rc;
+
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+
+ vf = &bp->pf.vf[vf_id];
+ pf_link_speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed);
+ if (max_tx_rate > pf_link_speed) {
+ netdev_info(bp->dev, "max tx rate %d exceed PF link speed for VF %d\n",
+ max_tx_rate, vf_id);
+ return -EINVAL;
+ }
+
+ if (min_tx_rate > pf_link_speed || min_tx_rate > max_tx_rate) {
+ netdev_info(bp->dev, "min tx rate %d is invalid for VF %d\n",
+ min_tx_rate, vf_id);
+ return -EINVAL;
+ }
+ if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate)
+ return 0;
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+ req.vf_id = cpu_to_le16(vf->fw_fid);
+ req.flags = cpu_to_le32(vf->func_flags);
+ req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW);
+ req.max_bw = cpu_to_le32(max_tx_rate);
+ req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MIN_BW);
+ req.min_bw = cpu_to_le32(min_tx_rate);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc) {
+ vf->min_tx_rate = min_tx_rate;
+ vf->max_tx_rate = max_tx_rate;
+ }
+ return rc;
+}
+
+int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_vf_info *vf;
+ int rc;
+
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+
+ vf = &bp->pf.vf[vf_id];
+
+ vf->flags &= ~(BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED);
+ switch (link) {
+ case IFLA_VF_LINK_STATE_AUTO:
+ vf->flags |= BNXT_VF_LINK_UP;
+ break;
+ case IFLA_VF_LINK_STATE_DISABLE:
+ vf->flags |= BNXT_VF_LINK_FORCED;
+ break;
+ case IFLA_VF_LINK_STATE_ENABLE:
+ vf->flags |= BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED;
+ break;
+ default:
+ netdev_err(bp->dev, "Invalid link option\n");
+ rc = -EINVAL;
+ break;
+ }
+ /* CHIMP TODO: send msg to VF to update new link state */
+
+ return rc;
+}
+
+static int bnxt_set_vf_attr(struct bnxt *bp, int num_vfs)
+{
+ int i;
+ struct bnxt_vf_info *vf;
+
+ for (i = 0; i < num_vfs; i++) {
+ vf = &bp->pf.vf[i];
+ memset(vf, 0, sizeof(*vf));
+ vf->flags = BNXT_VF_QOS | BNXT_VF_LINK_UP;
+ }
+ return 0;
+}
+
+static int bnxt_hwrm_func_vf_resource_free(struct bnxt *bp, int num_vfs)
+{
+ int i, rc = 0;
+ struct bnxt_pf_info *pf = &bp->pf;
+ struct hwrm_func_vf_resc_free_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_VF_RESC_FREE, -1, -1);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = pf->first_vf_id; i < pf->first_vf_id + num_vfs; i++) {
+ req.vf_id = cpu_to_le16(i);
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static void bnxt_free_vf_resources(struct bnxt *bp)
+{
+ struct pci_dev *pdev = bp->pdev;
+ int i;
+
+ kfree(bp->pf.vf_event_bmap);
+ bp->pf.vf_event_bmap = NULL;
+
+ for (i = 0; i < 4; i++) {
+ if (bp->pf.hwrm_cmd_req_addr[i]) {
+ dma_free_coherent(&pdev->dev, BNXT_PAGE_SIZE,
+ bp->pf.hwrm_cmd_req_addr[i],
+ bp->pf.hwrm_cmd_req_dma_addr[i]);
+ bp->pf.hwrm_cmd_req_addr[i] = NULL;
+ }
+ }
+
+ kfree(bp->pf.vf);
+ bp->pf.vf = NULL;
+}
+
+static int bnxt_alloc_vf_resources(struct bnxt *bp, int num_vfs)
+{
+ struct pci_dev *pdev = bp->pdev;
+ u32 nr_pages, size, i, j, k = 0;
+
+ bp->pf.vf = kcalloc(num_vfs, sizeof(struct bnxt_vf_info), GFP_KERNEL);
+ if (!bp->pf.vf)
+ return -ENOMEM;
+
+ bnxt_set_vf_attr(bp, num_vfs);
+
+ size = num_vfs * BNXT_HWRM_REQ_MAX_SIZE;
+ nr_pages = size / BNXT_PAGE_SIZE;
+ if (size & (BNXT_PAGE_SIZE - 1))
+ nr_pages++;
+
+ for (i = 0; i < nr_pages; i++) {
+ bp->pf.hwrm_cmd_req_addr[i] =
+ dma_alloc_coherent(&pdev->dev, BNXT_PAGE_SIZE,
+ &bp->pf.hwrm_cmd_req_dma_addr[i],
+ GFP_KERNEL);
+
+ if (!bp->pf.hwrm_cmd_req_addr[i])
+ return -ENOMEM;
+
+ for (j = 0; j < BNXT_HWRM_REQS_PER_PAGE && k < num_vfs; j++) {
+ struct bnxt_vf_info *vf = &bp->pf.vf[k];
+
+ vf->hwrm_cmd_req_addr = bp->pf.hwrm_cmd_req_addr[i] +
+ j * BNXT_HWRM_REQ_MAX_SIZE;
+ vf->hwrm_cmd_req_dma_addr =
+ bp->pf.hwrm_cmd_req_dma_addr[i] + j *
+ BNXT_HWRM_REQ_MAX_SIZE;
+ k++;
+ }
+ }
+
+ /* Max 128 VF's */
+ bp->pf.vf_event_bmap = kzalloc(16, GFP_KERNEL);
+ if (!bp->pf.vf_event_bmap)
+ return -ENOMEM;
+
+ bp->pf.hwrm_cmd_req_pages = nr_pages;
+ return 0;
+}
+
+static int bnxt_hwrm_func_buf_rgtr(struct bnxt *bp)
+{
+ struct hwrm_func_buf_rgtr_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_BUF_RGTR, -1, -1);
+
+ req.req_buf_num_pages = cpu_to_le16(bp->pf.hwrm_cmd_req_pages);
+ req.req_buf_page_size = cpu_to_le16(BNXT_PAGE_SHIFT);
+ req.req_buf_len = cpu_to_le16(BNXT_HWRM_REQ_MAX_SIZE);
+ req.req_buf_page_addr0 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[0]);
+ req.req_buf_page_addr1 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[1]);
+ req.req_buf_page_addr2 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[2]);
+ req.req_buf_page_addr3 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[3]);
+
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+/* only call by PF to reserve resources for VF */
+static int bnxt_hwrm_func_cfg(struct bnxt *bp, int *num_vfs)
+{
+ u32 rc = 0, mtu, i;
+ u16 vf_tx_rings, vf_rx_rings, vf_cp_rings, vf_stat_ctx, vf_vnics;
+ struct hwrm_func_cfg_input req = {0};
+ struct bnxt_pf_info *pf = &bp->pf;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+
+ /* Remaining rings are distributed equally amongs VF's for now */
+ /* TODO: the following workaroud is needed to restrict total number
+ * of vf_cp_rings not exceed number of HW ring groups. This WA should
+ * be removed once new HWRM provides HW ring groups capability in
+ * hwrm_func_qcap.
+ */
+ vf_cp_rings = min_t(u16, bp->pf.max_cp_rings, bp->pf.max_stat_ctxs);
+ vf_cp_rings = (vf_cp_rings - bp->cp_nr_rings) / *num_vfs;
+ /* TODO: restore this logic below once the WA above is removed */
+ /* vf_cp_rings = (bp->pf.max_cp_rings - bp->cp_nr_rings) / *num_vfs; */
+ vf_stat_ctx = (bp->pf.max_stat_ctxs - bp->num_stat_ctxs) / *num_vfs;
+ if (bp->flags & BNXT_FLAG_AGG_RINGS)
+ vf_rx_rings = (bp->pf.max_rx_rings - bp->rx_nr_rings * 2) /
+ *num_vfs;
+ else
+ vf_rx_rings = (bp->pf.max_rx_rings - bp->rx_nr_rings) /
+ *num_vfs;
+ vf_tx_rings = (bp->pf.max_tx_rings - bp->tx_nr_rings) / *num_vfs;
+
+ req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MTU |
+ FUNC_CFG_REQ_ENABLES_MRU |
+ FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS |
+ FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS |
+ FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS |
+ FUNC_CFG_REQ_ENABLES_NUM_TX_RINGS |
+ FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS |
+ FUNC_CFG_REQ_ENABLES_NUM_L2_CTXS |
+ FUNC_CFG_REQ_ENABLES_NUM_VNICS);
+
+ mtu = bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+ req.mru = cpu_to_le16(mtu);
+ req.mtu = cpu_to_le16(mtu);
+
+ req.num_rsscos_ctxs = cpu_to_le16(1);
+ req.num_cmpl_rings = cpu_to_le16(vf_cp_rings);
+ req.num_tx_rings = cpu_to_le16(vf_tx_rings);
+ req.num_rx_rings = cpu_to_le16(vf_rx_rings);
+ req.num_l2_ctxs = cpu_to_le16(4);
+ vf_vnics = 1;
+
+ req.num_vnics = cpu_to_le16(vf_vnics);
+ /* FIXME spec currently uses 1 bit for stats ctx */
+ req.num_stat_ctxs = cpu_to_le16(vf_stat_ctx);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ for (i = 0; i < *num_vfs; i++) {
+ req.vf_id = cpu_to_le16(pf->first_vf_id + i);
+ rc = _hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ if (rc)
+ break;
+ bp->pf.active_vfs = i + 1;
+ bp->pf.vf[i].fw_fid = le16_to_cpu(req.vf_id);
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ if (!rc) {
+ bp->pf.max_pf_tx_rings = bp->tx_nr_rings;
+ if (bp->flags & BNXT_FLAG_AGG_RINGS)
+ bp->pf.max_pf_rx_rings = bp->rx_nr_rings * 2;
+ else
+ bp->pf.max_pf_rx_rings = bp->rx_nr_rings;
+ }
+ return rc;
+}
+
+static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs)
+{
+ int rc = 0, vfs_supported;
+ int min_rx_rings, min_tx_rings, min_rss_ctxs;
+ int tx_ok = 0, rx_ok = 0, rss_ok = 0;
+
+ /* Check if we can enable requested num of vf's. At a mininum
+ * we require 1 RX 1 TX rings for each VF. In this minimum conf
+ * features like TPA will not be available.
+ */
+ vfs_supported = *num_vfs;
+
+ while (vfs_supported) {
+ min_rx_rings = vfs_supported;
+ min_tx_rings = vfs_supported;
+ min_rss_ctxs = vfs_supported;
+
+ if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+ if (bp->pf.max_rx_rings - bp->rx_nr_rings * 2 >=
+ min_rx_rings)
+ rx_ok = 1;
+ } else {
+ if (bp->pf.max_rx_rings - bp->rx_nr_rings >=
+ min_rx_rings)
+ rx_ok = 1;
+ }
+
+ if (bp->pf.max_tx_rings - bp->tx_nr_rings >= min_tx_rings)
+ tx_ok = 1;
+
+ if (bp->pf.max_rsscos_ctxs - bp->rsscos_nr_ctxs >= min_rss_ctxs)
+ rss_ok = 1;
+
+ if (tx_ok && rx_ok && rss_ok)
+ break;
+
+ vfs_supported--;
+ }
+
+ if (!vfs_supported) {
+ netdev_err(bp->dev, "Cannot enable VF's as all resources are used by PF\n");
+ return -EINVAL;
+ }
+
+ if (vfs_supported != *num_vfs) {
+ netdev_info(bp->dev, "Requested VFs %d, can enable %d\n",
+ *num_vfs, vfs_supported);
+ *num_vfs = vfs_supported;
+ }
+
+ rc = bnxt_alloc_vf_resources(bp, *num_vfs);
+ if (rc)
+ goto err_out1;
+
+ /* Reserve resources for VFs */
+ rc = bnxt_hwrm_func_cfg(bp, num_vfs);
+ if (rc)
+ goto err_out2;
+
+ /* Register buffers for VFs */
+ rc = bnxt_hwrm_func_buf_rgtr(bp);
+ if (rc)
+ goto err_out2;
+
+ rc = pci_enable_sriov(bp->pdev, *num_vfs);
+ if (rc)
+ goto err_out2;
+
+ return 0;
+
+err_out2:
+ /* Free the resources reserved for various VF's */
+ bnxt_hwrm_func_vf_resource_free(bp, *num_vfs);
+
+err_out1:
+ bnxt_free_vf_resources(bp);
+
+ return rc;
+}
+
+void bnxt_sriov_disable(struct bnxt *bp)
+{
+ u16 num_vfs = pci_num_vf(bp->pdev);
+
+ if (!num_vfs)
+ return;
+
+ if (pci_vfs_assigned(bp->pdev)) {
+ netdev_warn(bp->dev, "Unable to free %d VFs because some are assigned to VMs.\n",
+ num_vfs);
+ } else {
+ pci_disable_sriov(bp->pdev);
+ /* Free the HW resources reserved for various VF's */
+ bnxt_hwrm_func_vf_resource_free(bp, num_vfs);
+ }
+
+ bnxt_free_vf_resources(bp);
+
+ bp->pf.active_vfs = 0;
+ bp->pf.max_pf_rx_rings = bp->pf.max_rx_rings;
+ bp->pf.max_pf_tx_rings = bp->pf.max_tx_rings;
+}
+
+int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (!(bp->flags & BNXT_FLAG_USING_MSIX)) {
+ netdev_warn(dev, "Not allow SRIOV if the irq mode is not MSIX\n");
+ return 0;
+ }
+
+ rtnl_lock();
+ if (!netif_running(dev)) {
+ netdev_warn(dev, "Reject SRIOV config request since if is down!\n");
+ rtnl_unlock();
+ return 0;
+ }
+ bp->sriov_cfg = true;
+ rtnl_unlock();
+
+ if (pci_vfs_assigned(bp->pdev)) {
+ netdev_warn(dev, "Unable to configure SRIOV since some VFs are assigned to VMs.\n");
+ num_vfs = 0;
+ goto sriov_cfg_exit;
+ }
+
+ /* Check if enabled VFs is same as requested */
+ if (num_vfs && num_vfs == bp->pf.active_vfs)
+ goto sriov_cfg_exit;
+
+ /* if there are previous existing VFs, clean them up */
+ bnxt_sriov_disable(bp);
+ if (!num_vfs)
+ goto sriov_cfg_exit;
+
+ bnxt_sriov_enable(bp, &num_vfs);
+
+sriov_cfg_exit:
+ bp->sriov_cfg = false;
+ wake_up(&bp->sriov_cfg_wait);
+
+ return num_vfs;
+}
+
+static int bnxt_hwrm_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf,
+ void *encap_resp, __le64 encap_resp_addr,
+ __le16 encap_resp_cpr, u32 msg_size)
+{
+ int rc = 0;
+ struct hwrm_fwd_resp_input req = {0};
+ struct hwrm_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FWD_RESP, -1, -1);
+
+ /* Set the new target id */
+ req.target_id = cpu_to_le16(vf->fw_fid);
+ req.encap_resp_len = cpu_to_le16(msg_size);
+ req.encap_resp_addr = encap_resp_addr;
+ req.encap_resp_cmpl_ring = encap_resp_cpr;
+ memcpy(req.encap_resp, encap_resp, msg_size);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+
+ if (rc) {
+ netdev_err(bp->dev, "hwrm_fwd_resp failed. rc:%d\n", rc);
+ goto fwd_resp_exit;
+ }
+
+ if (resp->error_code) {
+ netdev_err(bp->dev, "hwrm_fwd_resp error %d\n",
+ resp->error_code);
+ rc = -1;
+ }
+
+fwd_resp_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_fwd_err_resp(struct bnxt *bp, struct bnxt_vf_info *vf,
+ u32 msg_size)
+{
+ int rc = 0;
+ struct hwrm_reject_fwd_resp_input req = {0};
+ struct hwrm_reject_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_REJECT_FWD_RESP, -1, -1);
+ /* Set the new target id */
+ req.target_id = cpu_to_le16(vf->fw_fid);
+ memcpy(req.encap_request, vf->hwrm_cmd_req_addr, msg_size);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+
+ if (rc) {
+ netdev_err(bp->dev, "hwrm_fwd_err_resp failed. rc:%d\n", rc);
+ goto fwd_err_resp_exit;
+ }
+
+ if (resp->error_code) {
+ netdev_err(bp->dev, "hwrm_fwd_err_resp error %d\n",
+ resp->error_code);
+ rc = -1;
+ }
+
+fwd_err_resp_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_exec_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf,
+ u32 msg_size)
+{
+ int rc = 0;
+ struct hwrm_exec_fwd_resp_input req = {0};
+ struct hwrm_exec_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_EXEC_FWD_RESP, -1, -1);
+ /* Set the new target id */
+ req.target_id = cpu_to_le16(vf->fw_fid);
+ memcpy(req.encap_request, vf->hwrm_cmd_req_addr, msg_size);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+
+ if (rc) {
+ netdev_err(bp->dev, "hwrm_exec_fw_resp failed. rc:%d\n", rc);
+ goto exec_fwd_resp_exit;
+ }
+
+ if (resp->error_code) {
+ netdev_err(bp->dev, "hwrm_exec_fw_resp error %d\n",
+ resp->error_code);
+ rc = -1;
+ }
+
+exec_fwd_resp_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf)
+{
+ u32 msg_size = sizeof(struct hwrm_cfa_l2_filter_alloc_input);
+ struct hwrm_cfa_l2_filter_alloc_input *req =
+ (struct hwrm_cfa_l2_filter_alloc_input *)vf->hwrm_cmd_req_addr;
+
+ if (!is_valid_ether_addr(vf->mac_addr) ||
+ ether_addr_equal((const u8 *)req->l2_addr, vf->mac_addr))
+ return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size);
+ else
+ return bnxt_hwrm_fwd_err_resp(bp, vf, msg_size);
+}
+
+static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf)
+{
+ int rc = 0;
+
+ if (!(vf->flags & BNXT_VF_LINK_FORCED)) {
+ /* real link */
+ rc = bnxt_hwrm_exec_fwd_resp(
+ bp, vf, sizeof(struct hwrm_port_phy_qcfg_input));
+ } else {
+ struct hwrm_port_phy_qcfg_output phy_qcfg_resp;
+ struct hwrm_port_phy_qcfg_input *phy_qcfg_req;
+
+ phy_qcfg_req =
+ (struct hwrm_port_phy_qcfg_input *)vf->hwrm_cmd_req_addr;
+ mutex_lock(&bp->hwrm_cmd_lock);
+ memcpy(&phy_qcfg_resp, &bp->link_info.phy_qcfg_resp,
+ sizeof(phy_qcfg_resp));
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ phy_qcfg_resp.seq_id = phy_qcfg_req->seq_id;
+
+ if (vf->flags & BNXT_VF_LINK_UP) {
+ /* if physical link is down, force link up on VF */
+ if (phy_qcfg_resp.link ==
+ PORT_PHY_QCFG_RESP_LINK_NO_LINK) {
+ phy_qcfg_resp.link =
+ PORT_PHY_QCFG_RESP_LINK_LINK;
+ if (phy_qcfg_resp.auto_link_speed)
+ phy_qcfg_resp.link_speed =
+ phy_qcfg_resp.auto_link_speed;
+ else
+ phy_qcfg_resp.link_speed =
+ phy_qcfg_resp.force_link_speed;
+ phy_qcfg_resp.duplex =
+ PORT_PHY_QCFG_RESP_DUPLEX_FULL;
+ phy_qcfg_resp.pause =
+ (PORT_PHY_QCFG_RESP_PAUSE_TX |
+ PORT_PHY_QCFG_RESP_PAUSE_RX);
+ }
+ } else {
+ /* force link down */
+ phy_qcfg_resp.link = PORT_PHY_QCFG_RESP_LINK_NO_LINK;
+ phy_qcfg_resp.link_speed = 0;
+ phy_qcfg_resp.duplex = PORT_PHY_QCFG_RESP_DUPLEX_HALF;
+ phy_qcfg_resp.pause = 0;
+ }
+ rc = bnxt_hwrm_fwd_resp(bp, vf, &phy_qcfg_resp,
+ phy_qcfg_req->resp_addr,
+ phy_qcfg_req->cmpl_ring,
+ sizeof(phy_qcfg_resp));
+ }
+ return rc;
+}
+
+static int bnxt_vf_req_validate_snd(struct bnxt *bp, struct bnxt_vf_info *vf)
+{
+ int rc = 0;
+ struct hwrm_cmd_req_hdr *encap_req = vf->hwrm_cmd_req_addr;
+ u32 req_type = le32_to_cpu(encap_req->cmpl_ring_req_type) & 0xffff;
+
+ switch (req_type) {
+ case HWRM_CFA_L2_FILTER_ALLOC:
+ rc = bnxt_vf_validate_set_mac(bp, vf);
+ break;
+ case HWRM_FUNC_CFG:
+ /* TODO Validate if VF is allowed to change mac address,
+ * mtu, num of rings etc
+ */
+ rc = bnxt_hwrm_exec_fwd_resp(
+ bp, vf, sizeof(struct hwrm_func_cfg_input));
+ break;
+ case HWRM_PORT_PHY_QCFG:
+ rc = bnxt_vf_set_link(bp, vf);
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
+void bnxt_hwrm_exec_fwd_req(struct bnxt *bp)
+{
+ u32 i = 0, active_vfs = bp->pf.active_vfs, vf_id;
+
+ /* Scan through VF's and process commands */
+ while (1) {
+ vf_id = find_next_bit(bp->pf.vf_event_bmap, active_vfs, i);
+ if (vf_id >= active_vfs)
+ break;
+
+ clear_bit(vf_id, bp->pf.vf_event_bmap);
+ bnxt_vf_req_validate_snd(bp, &bp->pf.vf[vf_id]);
+ i = vf_id + 1;
+ }
+}
+
+void bnxt_update_vf_mac(struct bnxt *bp)
+{
+ struct hwrm_func_qcaps_input req = {0};
+ struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1);
+ req.fid = cpu_to_le16(0xffff);
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ if (_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT))
+ goto update_vf_mac_exit;
+
+ if (!is_valid_ether_addr(resp->perm_mac_address))
+ goto update_vf_mac_exit;
+
+ if (ether_addr_equal(resp->perm_mac_address, bp->vf.mac_addr))
+ goto update_vf_mac_exit;
+
+ memcpy(bp->vf.mac_addr, resp->perm_mac_address, ETH_ALEN);
+ memcpy(bp->dev->dev_addr, bp->vf.mac_addr, ETH_ALEN);
+update_vf_mac_exit:
+ mutex_unlock(&bp->hwrm_cmd_lock);
+}
+
+#else
+
+void bnxt_sriov_disable(struct bnxt *bp)
+{
+}
+
+void bnxt_hwrm_exec_fwd_req(struct bnxt *bp)
+{
+ netdev_err(bp->dev, "Invalid VF message received when SRIOV is not enable\n");
+}
+
+void bnxt_update_vf_mac(struct bnxt *bp)
+{
+}
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h
new file mode 100644
index 000000000000..c151280e3980
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h
@@ -0,0 +1,23 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-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.
+ */
+
+#ifndef BNXT_SRIOV_H
+#define BNXT_SRIOV_H
+
+int bnxt_get_vf_config(struct net_device *, int, struct ifla_vf_info *);
+int bnxt_set_vf_mac(struct net_device *, int, u8 *);
+int bnxt_set_vf_vlan(struct net_device *, int, u16, u8);
+int bnxt_set_vf_bw(struct net_device *, int, int, int);
+int bnxt_set_vf_link_state(struct net_device *, int, int);
+int bnxt_set_vf_spoofchk(struct net_device *, int, bool);
+int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs);
+void bnxt_sriov_disable(struct bnxt *);
+void bnxt_hwrm_exec_fwd_req(struct bnxt *);
+void bnxt_update_vf_mac(struct bnxt *);
+#endif
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 3bc701e4c59e..17f017ab4dac 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -205,6 +205,23 @@ enum dma_reg {
DMA_INDEX2RING_5,
DMA_INDEX2RING_6,
DMA_INDEX2RING_7,
+ DMA_RING0_TIMEOUT,
+ DMA_RING1_TIMEOUT,
+ DMA_RING2_TIMEOUT,
+ DMA_RING3_TIMEOUT,
+ DMA_RING4_TIMEOUT,
+ DMA_RING5_TIMEOUT,
+ DMA_RING6_TIMEOUT,
+ DMA_RING7_TIMEOUT,
+ DMA_RING8_TIMEOUT,
+ DMA_RING9_TIMEOUT,
+ DMA_RING10_TIMEOUT,
+ DMA_RING11_TIMEOUT,
+ DMA_RING12_TIMEOUT,
+ DMA_RING13_TIMEOUT,
+ DMA_RING14_TIMEOUT,
+ DMA_RING15_TIMEOUT,
+ DMA_RING16_TIMEOUT,
};
static const u8 bcmgenet_dma_regs_v3plus[] = {
@@ -216,6 +233,23 @@ static const u8 bcmgenet_dma_regs_v3plus[] = {
[DMA_PRIORITY_0] = 0x30,
[DMA_PRIORITY_1] = 0x34,
[DMA_PRIORITY_2] = 0x38,
+ [DMA_RING0_TIMEOUT] = 0x2C,
+ [DMA_RING1_TIMEOUT] = 0x30,
+ [DMA_RING2_TIMEOUT] = 0x34,
+ [DMA_RING3_TIMEOUT] = 0x38,
+ [DMA_RING4_TIMEOUT] = 0x3c,
+ [DMA_RING5_TIMEOUT] = 0x40,
+ [DMA_RING6_TIMEOUT] = 0x44,
+ [DMA_RING7_TIMEOUT] = 0x48,
+ [DMA_RING8_TIMEOUT] = 0x4c,
+ [DMA_RING9_TIMEOUT] = 0x50,
+ [DMA_RING10_TIMEOUT] = 0x54,
+ [DMA_RING11_TIMEOUT] = 0x58,
+ [DMA_RING12_TIMEOUT] = 0x5c,
+ [DMA_RING13_TIMEOUT] = 0x60,
+ [DMA_RING14_TIMEOUT] = 0x64,
+ [DMA_RING15_TIMEOUT] = 0x68,
+ [DMA_RING16_TIMEOUT] = 0x6C,
[DMA_INDEX2RING_0] = 0x70,
[DMA_INDEX2RING_1] = 0x74,
[DMA_INDEX2RING_2] = 0x78,
@@ -235,6 +269,23 @@ static const u8 bcmgenet_dma_regs_v2[] = {
[DMA_PRIORITY_0] = 0x34,
[DMA_PRIORITY_1] = 0x38,
[DMA_PRIORITY_2] = 0x3C,
+ [DMA_RING0_TIMEOUT] = 0x2C,
+ [DMA_RING1_TIMEOUT] = 0x30,
+ [DMA_RING2_TIMEOUT] = 0x34,
+ [DMA_RING3_TIMEOUT] = 0x38,
+ [DMA_RING4_TIMEOUT] = 0x3c,
+ [DMA_RING5_TIMEOUT] = 0x40,
+ [DMA_RING6_TIMEOUT] = 0x44,
+ [DMA_RING7_TIMEOUT] = 0x48,
+ [DMA_RING8_TIMEOUT] = 0x4c,
+ [DMA_RING9_TIMEOUT] = 0x50,
+ [DMA_RING10_TIMEOUT] = 0x54,
+ [DMA_RING11_TIMEOUT] = 0x58,
+ [DMA_RING12_TIMEOUT] = 0x5c,
+ [DMA_RING13_TIMEOUT] = 0x60,
+ [DMA_RING14_TIMEOUT] = 0x64,
+ [DMA_RING15_TIMEOUT] = 0x68,
+ [DMA_RING16_TIMEOUT] = 0x6C,
};
static const u8 bcmgenet_dma_regs_v1[] = {
@@ -245,6 +296,23 @@ static const u8 bcmgenet_dma_regs_v1[] = {
[DMA_PRIORITY_0] = 0x34,
[DMA_PRIORITY_1] = 0x38,
[DMA_PRIORITY_2] = 0x3C,
+ [DMA_RING0_TIMEOUT] = 0x2C,
+ [DMA_RING1_TIMEOUT] = 0x30,
+ [DMA_RING2_TIMEOUT] = 0x34,
+ [DMA_RING3_TIMEOUT] = 0x38,
+ [DMA_RING4_TIMEOUT] = 0x3c,
+ [DMA_RING5_TIMEOUT] = 0x40,
+ [DMA_RING6_TIMEOUT] = 0x44,
+ [DMA_RING7_TIMEOUT] = 0x48,
+ [DMA_RING8_TIMEOUT] = 0x4c,
+ [DMA_RING9_TIMEOUT] = 0x50,
+ [DMA_RING10_TIMEOUT] = 0x54,
+ [DMA_RING11_TIMEOUT] = 0x58,
+ [DMA_RING12_TIMEOUT] = 0x5c,
+ [DMA_RING13_TIMEOUT] = 0x60,
+ [DMA_RING14_TIMEOUT] = 0x64,
+ [DMA_RING15_TIMEOUT] = 0x68,
+ [DMA_RING16_TIMEOUT] = 0x6C,
};
/* Set at runtime once bcmgenet version is known */
@@ -498,6 +566,85 @@ static void bcmgenet_set_msglevel(struct net_device *dev, u32 level)
priv->msg_enable = level;
}
+static int bcmgenet_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ec)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+
+ ec->tx_max_coalesced_frames =
+ bcmgenet_tdma_ring_readl(priv, DESC_INDEX,
+ DMA_MBUF_DONE_THRESH);
+ ec->rx_max_coalesced_frames =
+ bcmgenet_rdma_ring_readl(priv, DESC_INDEX,
+ DMA_MBUF_DONE_THRESH);
+ ec->rx_coalesce_usecs =
+ bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT) * 8192 / 1000;
+
+ return 0;
+}
+
+static int bcmgenet_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ec)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ unsigned int i;
+ u32 reg;
+
+ /* Base system clock is 125Mhz, DMA timeout is this reference clock
+ * divided by 1024, which yields roughly 8.192us, our maximum value
+ * has to fit in the DMA_TIMEOUT_MASK (16 bits)
+ */
+ if (ec->tx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK ||
+ ec->tx_max_coalesced_frames == 0 ||
+ ec->rx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK ||
+ ec->rx_coalesce_usecs > (DMA_TIMEOUT_MASK * 8) + 1)
+ return -EINVAL;
+
+ if (ec->rx_coalesce_usecs == 0 && ec->rx_max_coalesced_frames == 0)
+ return -EINVAL;
+
+ /* GENET TDMA hardware does not support a configurable timeout, but will
+ * always generate an interrupt either after MBDONE packets have been
+ * transmitted, or when the ring is emtpy.
+ */
+ if (ec->tx_coalesce_usecs || ec->tx_coalesce_usecs_high ||
+ ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_low)
+ return -EOPNOTSUPP;
+
+ /* Program all TX queues with the same values, as there is no
+ * ethtool knob to do coalescing on a per-queue basis
+ */
+ for (i = 0; i < priv->hw_params->tx_queues; i++)
+ bcmgenet_tdma_ring_writel(priv, i,
+ ec->tx_max_coalesced_frames,
+ DMA_MBUF_DONE_THRESH);
+ bcmgenet_tdma_ring_writel(priv, DESC_INDEX,
+ ec->tx_max_coalesced_frames,
+ DMA_MBUF_DONE_THRESH);
+
+ for (i = 0; i < priv->hw_params->rx_queues; i++) {
+ bcmgenet_rdma_ring_writel(priv, i,
+ ec->rx_max_coalesced_frames,
+ DMA_MBUF_DONE_THRESH);
+
+ reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
+ reg &= ~DMA_TIMEOUT_MASK;
+ reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192);
+ bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
+ }
+
+ bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
+ ec->rx_max_coalesced_frames,
+ DMA_MBUF_DONE_THRESH);
+
+ reg = bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT);
+ reg &= ~DMA_TIMEOUT_MASK;
+ reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192);
+ bcmgenet_rdma_writel(priv, reg, DMA_RING16_TIMEOUT);
+
+ return 0;
+}
+
/* standard ethtool support functions. */
enum bcmgenet_stat_type {
BCMGENET_STAT_NETDEV = -1,
@@ -646,7 +793,6 @@ static void bcmgenet_get_drvinfo(struct net_device *dev,
{
strlcpy(info->driver, "bcmgenet", sizeof(info->driver));
strlcpy(info->version, "v2.0", sizeof(info->version));
- info->n_stats = BCMGENET_STATS_LEN;
}
static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
@@ -844,6 +990,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
.get_eee = bcmgenet_get_eee,
.set_eee = bcmgenet_set_eee,
.nway_reset = bcmgenet_nway_reset,
+ .get_coalesce = bcmgenet_get_coalesce,
+ .set_coalesce = bcmgenet_set_coalesce,
};
/* Power down the unimac, based on mode. */
@@ -907,8 +1055,10 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
}
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
- if (mode == GENET_POWER_PASSIVE)
+ if (mode == GENET_POWER_PASSIVE) {
bcmgenet_phy_power_set(priv->dev, true);
+ bcmgenet_mii_reset(priv->dev);
+ }
}
/* ioctl handle special commands that are not present in ethtool. */
@@ -1683,6 +1833,24 @@ static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
}
+static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
+{
+ u32 int0_enable = 0;
+
+ /* Monitor cable plug/unplugged event for internal PHY, external PHY
+ * and MoCA PHY
+ */
+ if (priv->internal_phy) {
+ int0_enable |= UMAC_IRQ_LINK_EVENT;
+ } else if (priv->ext_phy) {
+ int0_enable |= UMAC_IRQ_LINK_EVENT;
+ } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+ if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
+ int0_enable |= UMAC_IRQ_LINK_EVENT;
+ }
+ bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
+}
+
static int init_umac(struct bcmgenet_priv *priv)
{
struct device *kdev = &priv->pdev->dev;
@@ -1723,15 +1891,8 @@ static int init_umac(struct bcmgenet_priv *priv)
/* Enable Tx default queue 16 interrupts */
int0_enable |= UMAC_IRQ_TXDMA_DONE;
- /* Monitor cable plug/unplugged event for internal PHY */
- if (priv->internal_phy) {
- int0_enable |= UMAC_IRQ_LINK_EVENT;
- } else if (priv->ext_phy) {
- int0_enable |= UMAC_IRQ_LINK_EVENT;
- } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
- if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
- int0_enable |= UMAC_IRQ_LINK_EVENT;
-
+ /* Configure backpressure vectors for MoCA */
+ if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
reg = bcmgenet_bp_mc_get(priv);
reg |= BIT(priv->hw_params->bp_in_en_shift);
@@ -2645,6 +2806,9 @@ static void bcmgenet_netif_start(struct net_device *dev)
netif_tx_start_all_queues(dev);
+ /* Monitor link interrupts now */
+ bcmgenet_link_intr_enable(priv);
+
phy_start(priv->phydev);
}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 7299d1075422..967367557309 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -304,13 +304,12 @@ struct bcmgenet_mib_counters {
#define UMAC_IRQ_RXDMA_MBDONE (1 << 13)
#define UMAC_IRQ_RXDMA_PDONE (1 << 14)
#define UMAC_IRQ_RXDMA_BDONE (1 << 15)
-#define UMAC_IRQ_RXDMA_DONE (UMAC_IRQ_RXDMA_PDONE | \
- UMAC_IRQ_RXDMA_BDONE)
+#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
#define UMAC_IRQ_TXDMA_MBDONE (1 << 16)
#define UMAC_IRQ_TXDMA_PDONE (1 << 17)
#define UMAC_IRQ_TXDMA_BDONE (1 << 18)
-#define UMAC_IRQ_TXDMA_DONE (UMAC_IRQ_TXDMA_PDONE | \
- UMAC_IRQ_TXDMA_BDONE)
+#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
+
/* Only valid for GENETv3+ */
#define UMAC_IRQ_MDIO_DONE (1 << 23)
#define UMAC_IRQ_MDIO_ERROR (1 << 24)
@@ -386,7 +385,7 @@ struct bcmgenet_mib_counters {
#define DMA_RING_BUFFER_SIZE_MASK 0xFFFF
/* DMA interrupt threshold register */
-#define DMA_INTR_THRESHOLD_MASK 0x00FF
+#define DMA_INTR_THRESHOLD_MASK 0x01FF
/* DMA XON/XOFF register */
#define DMA_XON_THREHOLD_MASK 0xFFFF
@@ -674,6 +673,7 @@ int bcmgenet_mii_init(struct net_device *dev);
int bcmgenet_mii_config(struct net_device *dev);
int bcmgenet_mii_probe(struct net_device *dev);
void bcmgenet_mii_exit(struct net_device *dev);
+void bcmgenet_mii_reset(struct net_device *dev);
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
void bcmgenet_mii_setup(struct net_device *dev);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index c8affad76f36..8bdfe53754ba 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -163,6 +163,7 @@ void bcmgenet_mii_setup(struct net_device *dev)
phy_print_status(phydev);
}
+
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
struct fixed_phy_status *status)
{
@@ -172,6 +173,22 @@ static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
return 0;
}
+/* Perform a voluntary PHY software reset, since the EPHY is very finicky about
+ * not doing it and will start corrupting packets
+ */
+void bcmgenet_mii_reset(struct net_device *dev)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+
+ if (GENET_IS_V4(priv))
+ return;
+
+ if (priv->phydev) {
+ phy_init_hw(priv->phydev);
+ phy_start_aneg(priv->phydev);
+ }
+}
+
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -214,6 +231,7 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= EXT_PWR_DN_EN_LD;
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+ bcmgenet_mii_reset(dev);
}
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 9b35d142f47a..8fb84e69c30e 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -3,7 +3,7 @@
#
config NET_VENDOR_CAVIUM
- tristate "Cavium ethernet drivers"
+ bool "Cavium ethernet drivers"
depends on PCI
default y
---help---
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index 29f330831784..245c063ed4db 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -153,7 +153,6 @@ lio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version,
ETHTOOL_FWVERS_LEN);
strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
- drvinfo->regdump_len = OCT_ETHTOOL_REGDUMP_LEN;
}
static void
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index f683d97d7614..b89504405b72 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -560,7 +560,7 @@ static int liquidio_resume(struct pci_dev *pdev)
#endif
/* For PCI-E Advanced Error Recovery (AER) Interface */
-static struct pci_error_handlers liquidio_err_handler = {
+static const struct pci_error_handlers liquidio_err_handler = {
.error_detected = liquidio_pcie_error_detected,
.mmio_enabled = liquidio_pcie_mmio_enabled,
.slot_reset = liquidio_pcie_slot_reset,
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index b3a5947a2cc0..c561fdcb79a7 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -22,7 +22,6 @@
struct nicpf {
struct pci_dev *pdev;
- u8 rev_id;
u8 node;
unsigned int flags;
u8 num_vf_en; /* No of VF enabled */
@@ -44,6 +43,7 @@ struct nicpf {
u8 duplex[MAX_LMAC];
u32 speed[MAX_LMAC];
u16 cpi_base[MAX_NUM_VFS_SUPPORTED];
+ u16 rssi_base[MAX_NUM_VFS_SUPPORTED];
u16 rss_ind_tbl_size;
bool mbx_lock[MAX_NUM_VFS_SUPPORTED];
@@ -54,6 +54,11 @@ struct nicpf {
bool irq_allocated[NIC_PF_MSIX_VECTORS];
};
+static inline bool pass1_silicon(struct nicpf *nic)
+{
+ return nic->pdev->revision < 8;
+}
+
/* Supported devices */
static const struct pci_device_id nic_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) },
@@ -117,7 +122,7 @@ static void nic_send_msg_to_vf(struct nicpf *nic, int vf, union nic_mbx *mbx)
* when PF writes to MBOX(1), in next revisions when
* PF writes to MBOX(0)
*/
- if (nic->rev_id == 0) {
+ if (pass1_silicon(nic)) {
/* see the comment for nic_reg_write()/nic_reg_read()
* functions above
*/
@@ -305,9 +310,6 @@ static void nic_init_hw(struct nicpf *nic)
{
int i;
- /* Reset NIC, in case the driver is repeatedly inserted and removed */
- nic_reg_write(nic, NIC_PF_SOFT_RESET, 1);
-
/* Enable NIC HW block */
nic_reg_write(nic, NIC_PF_CFG, 0x3);
@@ -395,8 +397,18 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */
/* Leave RSS_SIZE as '0' to disable RSS */
- nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
- (vnic << 24) | (padd << 16) | (rssi_base + rssi));
+ if (pass1_silicon(nic)) {
+ nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+ (vnic << 24) | (padd << 16) |
+ (rssi_base + rssi));
+ } else {
+ /* Set MPI_ALG to '0' to disable MCAM parsing */
+ nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+ (padd << 16));
+ /* MPI index is same as CPI if MPI_ALG is not enabled */
+ nic_reg_write(nic, NIC_PF_MPI_0_2047_CFG | (cpi << 3),
+ (vnic << 24) | (rssi_base + rssi));
+ }
if ((rssi + 1) >= cfg->rq_cnt)
continue;
@@ -409,6 +421,7 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
rssi = ((cpi - cpi_base) & 0x38) >> 3;
}
nic->cpi_base[cfg->vf_id] = cpi_base;
+ nic->rssi_base[cfg->vf_id] = rssi_base;
}
/* Responsds to VF with its RSS indirection table size */
@@ -434,10 +447,9 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
{
u8 qset, idx = 0;
u64 cpi_cfg, cpi_base, rssi_base, rssi;
+ u64 idx_addr;
- cpi_base = nic->cpi_base[cfg->vf_id];
- cpi_cfg = nic_reg_read(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3));
- rssi_base = (cpi_cfg & 0x0FFF) + cfg->tbl_offset;
+ rssi_base = nic->rssi_base[cfg->vf_id] + cfg->tbl_offset;
rssi = rssi_base;
qset = cfg->vf_id;
@@ -454,9 +466,15 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
idx++;
}
+ cpi_base = nic->cpi_base[cfg->vf_id];
+ if (pass1_silicon(nic))
+ idx_addr = NIC_PF_CPI_0_2047_CFG;
+ else
+ idx_addr = NIC_PF_MPI_0_2047_CFG;
+ cpi_cfg = nic_reg_read(nic, idx_addr | (cpi_base << 3));
cpi_cfg &= ~(0xFULL << 20);
cpi_cfg |= (cfg->hash_bits << 20);
- nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3), cpi_cfg);
+ nic_reg_write(nic, idx_addr | (cpi_base << 3), cpi_cfg);
}
/* 4 level transmit side scheduler configutation
@@ -1001,8 +1019,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_release_regions;
}
- pci_read_config_byte(pdev, PCI_REVISION_ID, &nic->rev_id);
-
nic->node = nic_get_node_id(pdev);
nic_set_lmac_vf_mapping(nic);
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index 58197bb2f805..dd536be20193 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -85,7 +85,11 @@
#define NIC_PF_ECC3_DBE_INT_W1S (0x2708)
#define NIC_PF_ECC3_DBE_ENA_W1C (0x2710)
#define NIC_PF_ECC3_DBE_ENA_W1S (0x2718)
+#define NIC_PF_MCAM_0_191_ENA (0x100000)
+#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000)
+#define NIC_PF_MCAM_CTRL (0x120000)
#define NIC_PF_CPI_0_2047_CFG (0x200000)
+#define NIC_PF_MPI_0_2047_CFG (0x210000)
#define NIC_PF_RSSI_0_4097_RQ (0x220000)
#define NIC_PF_LMAC_0_7_CFG (0x240000)
#define NIC_PF_LMAC_0_7_SW_XOFF (0x242000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index b63e579aeb12..7f709cbdcd87 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -29,7 +29,7 @@
static const struct pci_device_id nicvf_id_table[] = {
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
PCI_DEVICE_ID_THUNDER_NIC_VF,
- PCI_VENDOR_ID_CAVIUM, 0xA11E) },
+ PCI_VENDOR_ID_CAVIUM, 0xA134) },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
PCI_DEVICE_ID_THUNDER_PASS1_NIC_VF,
PCI_VENDOR_ID_CAVIUM, 0xA11E) },
@@ -1583,8 +1583,14 @@ err_disable_device:
static void nicvf_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct nicvf *nic = netdev_priv(netdev);
- struct net_device *pnetdev = nic->pnicvf->netdev;
+ struct nicvf *nic;
+ struct net_device *pnetdev;
+
+ if (!netdev)
+ return;
+
+ nic = netdev_priv(netdev);
+ pnetdev = nic->pnicvf->netdev;
/* Check if this Qset is assigned to different VF.
* If yes, clean primary and all secondary Qsets.
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 574c49278900..180aa9fabf48 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -977,8 +977,10 @@ static int bgx_init_of_phy(struct bgx *bgx)
SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev);
bgx->lmac[lmac].lmacid = lmac;
lmac++;
- if (lmac == MAX_LMAC_PER_BGX)
+ if (lmac == MAX_LMAC_PER_BGX) {
+ of_node_put(np_child);
break;
+ }
}
return 0;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index fa0c7b54ec7a..55a47de544ea 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -47,7 +47,9 @@
#include <linux/timer.h>
#include <linux/vmalloc.h>
#include <linux/etherdevice.h>
+#include <linux/net_tstamp.h>
#include <asm/io.h>
+#include "t4_chip_type.h"
#include "cxgb4_uld.h"
#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
@@ -290,31 +292,6 @@ struct pci_params {
unsigned char width;
};
-#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_FPGA 0x100
-#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
-#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
-
-#define CHELSIO_T4 0x4
-#define CHELSIO_T5 0x5
-#define CHELSIO_T6 0x6
-
-enum chip_type {
- T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
- T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
- T4_FIRST_REV = T4_A1,
- T4_LAST_REV = T4_A2,
-
- T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
- T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
- T5_FIRST_REV = T5_A0,
- T5_LAST_REV = T5_A1,
-
- T6_A0 = CHELSIO_CHIP_CODE(CHELSIO_T6, 0),
- T6_FIRST_REV = T6_A0,
- T6_LAST_REV = T6_A0,
-};
-
struct devlog_params {
u32 memtype; /* which memory (EDC0, EDC1, MC) */
u32 start; /* start of log in firmware memory */
@@ -478,6 +455,8 @@ struct port_info {
#ifdef CONFIG_CHELSIO_T4_FCOE
struct cxgb_fcoe fcoe;
#endif /* CONFIG_CHELSIO_T4_FCOE */
+ bool rxtstamp; /* Enable TS */
+ struct hwtstamp_config tstamp_config;
};
struct dentry;
@@ -517,6 +496,7 @@ struct sge_fl { /* SGE free-buffer queue state */
/* A packet gather list */
struct pkt_gl {
+ u64 sgetstamp; /* SGE Time Stamp for Ingress Packet */
struct page_frag frags[MAX_SKB_FRAGS];
void *va; /* virtual address of first byte */
unsigned int nfrags; /* # of fragments */
@@ -767,8 +747,8 @@ struct adapter {
bool tid_release_task_busy;
struct dentry *debugfs_root;
- u32 use_bd; /* Use SGE Back Door intfc for reading SGE Contexts */
- u32 trace_rss; /* 1 implies that different RSS flit per filter is
+ bool use_bd; /* Use SGE Back Door intfc for reading SGE Contexts */
+ bool trace_rss; /* 1 implies that different RSS flit per filter is
* used per filter else if 0 default RSS flit is
* used for all 4 filters.
*/
@@ -905,21 +885,6 @@ static inline int is_offload(const struct adapter *adap)
return adap->params.offload;
}
-static inline int is_t6(enum chip_type chip)
-{
- return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T6;
-}
-
-static inline int is_t5(enum chip_type chip)
-{
- return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5;
-}
-
-static inline int is_t4(enum chip_type chip)
-{
- return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
-}
-
static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
{
return readl(adap->regs + reg_addr);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 0a87a3247464..4269944c5db5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -940,6 +940,7 @@ static const char * const devlog_level_strings[] = {
static const char * const devlog_facility_strings[] = {
[FW_DEVLOG_FACILITY_CORE] = "CORE",
+ [FW_DEVLOG_FACILITY_CF] = "CF",
[FW_DEVLOG_FACILITY_SCHED] = "SCHED",
[FW_DEVLOG_FACILITY_TIMER] = "TIMER",
[FW_DEVLOG_FACILITY_RES] = "RES",
@@ -1128,18 +1129,26 @@ static const struct file_operations devlog_fops = {
static int mbox_show(struct seq_file *seq, void *v)
{
static const char * const owner[] = { "none", "FW", "driver",
- "unknown" };
+ "unknown", "<unread>" };
int i;
unsigned int mbox = (uintptr_t)seq->private & 7;
struct adapter *adap = seq->private - mbox;
void __iomem *addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
- unsigned int ctrl_reg = (is_t4(adap->params.chip)
- ? CIM_PF_MAILBOX_CTRL_A
- : CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A);
- void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg);
- i = MBOWNER_G(readl(ctrl));
+ /* For T4 we don't have a shadow copy of the Mailbox Control register.
+ * And since reading that real register causes a side effect of
+ * granting ownership, we're best of simply not reading it at all.
+ */
+ if (is_t4(adap->params.chip)) {
+ i = 4; /* index of "<unread>" */
+ } else {
+ unsigned int ctrl_reg = CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A;
+ void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg);
+
+ i = MBOWNER_G(readl(ctrl));
+ }
+
seq_printf(seq, "mailbox owned by %s\n\n", owner[i]);
for (i = 0; i < MBOX_LEN; i += 8)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
index 5eedb98ff581..a077f9476daf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
@@ -35,79 +35,79 @@ static void set_msglevel(struct net_device *dev, u32 val)
}
static const char stats_strings[][ETH_GSTRING_LEN] = {
- "TxOctetsOK ",
- "TxFramesOK ",
- "TxBroadcastFrames ",
- "TxMulticastFrames ",
- "TxUnicastFrames ",
- "TxErrorFrames ",
-
- "TxFrames64 ",
- "TxFrames65To127 ",
- "TxFrames128To255 ",
- "TxFrames256To511 ",
- "TxFrames512To1023 ",
- "TxFrames1024To1518 ",
- "TxFrames1519ToMax ",
-
- "TxFramesDropped ",
- "TxPauseFrames ",
- "TxPPP0Frames ",
- "TxPPP1Frames ",
- "TxPPP2Frames ",
- "TxPPP3Frames ",
- "TxPPP4Frames ",
- "TxPPP5Frames ",
- "TxPPP6Frames ",
- "TxPPP7Frames ",
-
- "RxOctetsOK ",
- "RxFramesOK ",
- "RxBroadcastFrames ",
- "RxMulticastFrames ",
- "RxUnicastFrames ",
-
- "RxFramesTooLong ",
- "RxJabberErrors ",
- "RxFCSErrors ",
- "RxLengthErrors ",
- "RxSymbolErrors ",
- "RxRuntFrames ",
-
- "RxFrames64 ",
- "RxFrames65To127 ",
- "RxFrames128To255 ",
- "RxFrames256To511 ",
- "RxFrames512To1023 ",
- "RxFrames1024To1518 ",
- "RxFrames1519ToMax ",
-
- "RxPauseFrames ",
- "RxPPP0Frames ",
- "RxPPP1Frames ",
- "RxPPP2Frames ",
- "RxPPP3Frames ",
- "RxPPP4Frames ",
- "RxPPP5Frames ",
- "RxPPP6Frames ",
- "RxPPP7Frames ",
-
- "RxBG0FramesDropped ",
- "RxBG1FramesDropped ",
- "RxBG2FramesDropped ",
- "RxBG3FramesDropped ",
- "RxBG0FramesTrunc ",
- "RxBG1FramesTrunc ",
- "RxBG2FramesTrunc ",
- "RxBG3FramesTrunc ",
-
- "TSO ",
- "TxCsumOffload ",
- "RxCsumGood ",
- "VLANextractions ",
- "VLANinsertions ",
- "GROpackets ",
- "GROmerged ",
+ "tx_octets_ok ",
+ "tx_frames_ok ",
+ "tx_broadcast_frames ",
+ "tx_multicast_frames ",
+ "tx_unicast_frames ",
+ "tx_error_frames ",
+
+ "tx_frames_64 ",
+ "tx_frames_65_to_127 ",
+ "tx_frames_128_to_255 ",
+ "tx_frames_256_to_511 ",
+ "tx_frames_512_to_1023 ",
+ "tx_frames_1024_to_1518 ",
+ "tx_frames_1519_to_max ",
+
+ "tx_frames_dropped ",
+ "tx_pause_frames ",
+ "tx_ppp0_frames ",
+ "tx_ppp1_frames ",
+ "tx_ppp2_frames ",
+ "tx_ppp3_frames ",
+ "tx_ppp4_frames ",
+ "tx_ppp5_frames ",
+ "tx_ppp6_frames ",
+ "tx_ppp7_frames ",
+
+ "rx_octets_ok ",
+ "rx_frames_ok ",
+ "rx_broadcast_frames ",
+ "rx_multicast_frames ",
+ "rx_unicast_frames ",
+
+ "rx_frames_too_long ",
+ "rx_jabber_errors ",
+ "rx_fcs_errors ",
+ "rx_length_errors ",
+ "rx_symbol_errors ",
+ "rx_runt_frames ",
+
+ "rx_frames_64 ",
+ "rx_frames_65_to_127 ",
+ "rx_frames_128_to_255 ",
+ "rx_frames_256_to_511 ",
+ "rx_frames_512_to_1023 ",
+ "rx_frames_1024_to_1518 ",
+ "rx_frames_1519_to_max ",
+
+ "rx_pause_frames ",
+ "rx_ppp0_frames ",
+ "rx_ppp1_frames ",
+ "rx_ppp2_frames ",
+ "rx_ppp3_frames ",
+ "rx_ppp4_frames ",
+ "rx_ppp5_frames ",
+ "rx_ppp6_frames ",
+ "rx_ppp7_frames ",
+
+ "rx_bg0_frames_dropped ",
+ "rx_bg1_frames_dropped ",
+ "rx_bg2_frames_dropped ",
+ "rx_bg3_frames_dropped ",
+ "rx_bg0_frames_trunc ",
+ "rx_bg1_frames_trunc ",
+ "rx_bg2_frames_trunc ",
+ "rx_bg3_frames_trunc ",
+
+ "tso ",
+ "tx_csum_offload ",
+ "rx_csum_good ",
+ "vlan_extractions ",
+ "vlan_insertions ",
+ "gro_packets ",
+ "gro_merged ",
};
static char adapter_stats_strings[][ETH_GSTRING_LEN] = {
@@ -211,8 +211,11 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
sizeof(info->version));
strlcpy(info->bus_info, pci_name(adapter->pdev),
sizeof(info->bus_info));
+ info->regdump_len = get_regs_len(dev);
- if (adapter->params.fw_vers)
+ if (!adapter->params.fw_vers)
+ strcpy(info->fw_version, "N/A");
+ else
snprintf(info->fw_version, sizeof(info->fw_version),
"%u.%u.%u.%u, TP %u.%u.%u.%u",
FW_HDR_FW_VER_MAJOR_G(adapter->params.fw_vers),
@@ -612,6 +615,8 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct port_info *p = netdev_priv(dev);
struct link_config *lc = &p->link_cfg;
u32 speed = ethtool_cmd_speed(cmd);
+ struct link_config old_lc;
+ int ret;
if (cmd->duplex != DUPLEX_FULL) /* only full-duplex supported */
return -EINVAL;
@@ -626,13 +631,11 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
+ old_lc = *lc;
if (cmd->autoneg == AUTONEG_DISABLE) {
cap = speed_to_caps(speed);
- if (!(lc->supported & cap) ||
- (speed == 1000) ||
- (speed == 10000) ||
- (speed == 40000))
+ if (!(lc->supported & cap))
return -EINVAL;
lc->requested_speed = cap;
lc->advertising = 0;
@@ -645,10 +648,14 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
}
lc->autoneg = cmd->autoneg;
- if (netif_running(dev))
- return t4_link_l1cfg(p->adapter, p->adapter->pf, p->tx_chan,
- lc);
- return 0;
+ /* If the firmware rejects the Link Configuration request, back out
+ * the changes and report the error.
+ */
+ ret = t4_link_l1cfg(p->adapter, p->adapter->mbox, p->tx_chan, lc);
+ if (ret)
+ *lc = old_lc;
+
+ return ret;
}
static void get_pauseparam(struct net_device *dev,
@@ -847,7 +854,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
{
int i, err = 0;
struct adapter *adapter = netdev2adap(dev);
- u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL);
+ u8 *buf = t4_alloc_mem(EEPROMSIZE);
if (!buf)
return -ENOMEM;
@@ -858,7 +865,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
if (!err)
memcpy(data, buf + e->offset, e->len);
- kfree(buf);
+ t4_free_mem(buf);
return err;
}
@@ -887,7 +894,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
/* RMW possibly needed for first or last words.
*/
- buf = kmalloc(aligned_len, GFP_KERNEL);
+ buf = t4_alloc_mem(aligned_len);
if (!buf)
return -ENOMEM;
err = eeprom_rd_phys(adapter, aligned_offset, (u32 *)buf);
@@ -915,7 +922,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
err = t4_seeprom_wp(adapter, true);
out:
if (buf != data)
- kfree(buf);
+ t4_free_mem(buf);
return err;
}
@@ -961,6 +968,20 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
return ret;
}
+static int get_ts_info(struct net_device *dev, struct ethtool_ts_info *ts_info)
+{
+ ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+
+ ts_info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ ts_info->phc_index = -1;
+
+ return 0;
+}
+
static u32 get_rss_table_size(struct net_device *dev)
{
const struct port_info *pi = netdev_priv(dev);
@@ -997,11 +1018,15 @@ static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
if (!p)
return 0;
- for (i = 0; i < pi->rss_size; i++)
- pi->rss[i] = p[i];
- if (pi->adapter->flags & FULL_INIT_DONE)
+ /* Interface must be brought up atleast once */
+ if (pi->adapter->flags & FULL_INIT_DONE) {
+ for (i = 0; i < pi->rss_size; i++)
+ pi->rss[i] = p[i];
+
return cxgb4_write_rss(pi, pi->rss);
- return 0;
+ }
+
+ return -EPERM;
}
static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
@@ -1095,6 +1120,7 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
.get_rxfh = get_rss_table,
.set_rxfh = set_rss_table,
.flash_device = set_flash,
+ .get_ts_info = get_ts_info
};
void cxgb4_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index f5dcde27e402..0d147610a06f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -83,7 +83,7 @@ char cxgb4_driver_name[] = KBUILD_MODNAME;
#endif
#define DRV_VERSION "2.0.0-ko"
const char cxgb4_driver_version[] = DRV_VERSION;
-#define DRV_DESC "Chelsio T4/T5 Network Driver"
+#define DRV_DESC "Chelsio T4/T5/T6 Network Driver"
/* Host shadow copy of ingress filter entry. This is in host native format
* and doesn't match the ordering or bit order, etc. of the hardware of the
@@ -151,6 +151,7 @@ MODULE_VERSION(DRV_VERSION);
MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
MODULE_FIRMWARE(FW4_FNAME);
MODULE_FIRMWARE(FW5_FNAME);
+MODULE_FIRMWARE(FW6_FNAME);
/*
* Normally we're willing to become the firmware's Master PF but will be happy
@@ -275,7 +276,7 @@ static void link_report(struct net_device *dev)
else {
static const char *fc[] = { "no", "Rx", "Tx", "Tx/Rx" };
- const char *s = "10Mbps";
+ const char *s;
const struct port_info *p = netdev_priv(dev);
switch (p->link_cfg.speed) {
@@ -291,6 +292,10 @@ static void link_report(struct net_device *dev)
case 40000:
s = "40Gbps";
break;
+ default:
+ pr_info("%s: unsupported speed: %d\n",
+ dev->name, p->link_cfg.speed);
+ return;
}
netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
@@ -1936,6 +1941,28 @@ unsigned int cxgb4_best_aligned_mtu(const unsigned short *mtus,
EXPORT_SYMBOL(cxgb4_best_aligned_mtu);
/**
+ * cxgb4_tp_smt_idx - Get the Source Mac Table index for this VI
+ * @chip: chip type
+ * @viid: VI id of the given port
+ *
+ * Return the SMT index for this VI.
+ */
+unsigned int cxgb4_tp_smt_idx(enum chip_type chip, unsigned int viid)
+{
+ /* In T4/T5, SMT contains 256 SMAC entries organized in
+ * 128 rows of 2 entries each.
+ * In T6, SMT contains 256 SMAC entries in 256 rows.
+ * TODO: The below code needs to be updated when we add support
+ * for 256 VFs.
+ */
+ if (CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5)
+ return ((viid & 0x7f) << 1);
+ else
+ return (viid & 0x7f);
+}
+EXPORT_SYMBOL(cxgb4_tp_smt_idx);
+
+/**
* cxgb4_port_chan - get the HW channel of a port
* @dev: the net device for the port
*
@@ -2959,6 +2986,30 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
ret = t4_mdio_wr(pi->adapter, mbox, prtad, devad,
data->reg_num, data->val_in);
break;
+ case SIOCGHWTSTAMP:
+ return copy_to_user(req->ifr_data, &pi->tstamp_config,
+ sizeof(pi->tstamp_config)) ?
+ -EFAULT : 0;
+ case SIOCSHWTSTAMP:
+ if (copy_from_user(&pi->tstamp_config, req->ifr_data,
+ sizeof(pi->tstamp_config)))
+ return -EFAULT;
+
+ switch (pi->tstamp_config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ pi->rxtstamp = false;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ pi->rxtstamp = true;
+ break;
+ default:
+ pi->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+ return -ERANGE;
+ }
+
+ return copy_to_user(req->ifr_data, &pi->tstamp_config,
+ sizeof(pi->tstamp_config)) ?
+ -EFAULT : 0;
default:
return -EOPNOTSUPP;
}
@@ -3670,7 +3721,7 @@ static int adap_init0(struct adapter *adap)
t4_get_tp_version(adap, &adap->params.tp_vers);
ret = t4_check_fw_version(adap);
/* If firmware is too old (not supported by driver) force an update. */
- if (ret == -EFAULT)
+ if (ret)
state = DEV_STATE_UNINIT;
if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
struct fw_info *fw_info;
@@ -4457,6 +4508,10 @@ static int enable_msix(struct adapter *adap)
}
for (i = 0; i < allocated; ++i)
adap->msix_info[i].vec = entries[i].vector;
+ dev_info(adap->pdev_dev, "%d MSI-X vectors allocated, "
+ "nic %d iscsi %d rdma cpl %d rdma ciq %d\n",
+ allocated, s->max_ethqsets, s->ofldqsets, s->rdmaqs,
+ s->rdmaciqs);
kfree(entries);
return 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index c3a8be5541e7..cf711d5f15be 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -40,6 +40,7 @@
#include <linux/skbuff.h>
#include <linux/inetdevice.h>
#include <linux/atomic.h>
+#include "cxgb4.h"
/* CPL message priority levels */
enum {
@@ -290,6 +291,7 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
unsigned int cxgb4_port_chan(const struct net_device *dev);
unsigned int cxgb4_port_viid(const struct net_device *dev);
+unsigned int cxgb4_tp_smt_idx(enum chip_type chip, unsigned int viid);
unsigned int cxgb4_port_idx(const struct net_device *dev);
unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu,
unsigned int *idx);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 9162746d7729..b7b93e7a643d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1820,11 +1820,34 @@ static noinline int handle_trace_pkt(struct adapter *adap,
return 0;
}
+/**
+ * cxgb4_sgetim_to_hwtstamp - convert sge time stamp to hw time stamp
+ * @adap: the adapter
+ * @hwtstamps: time stamp structure to update
+ * @sgetstamp: 60bit iqe timestamp
+ *
+ * Every ingress queue entry has the 60-bit timestamp, convert that timestamp
+ * which is in Core Clock ticks into ktime_t and assign it
+ **/
+static void cxgb4_sgetim_to_hwtstamp(struct adapter *adap,
+ struct skb_shared_hwtstamps *hwtstamps,
+ u64 sgetstamp)
+{
+ u64 ns;
+ u64 tmp = (sgetstamp * 1000 * 1000 + adap->params.vpd.cclk / 2);
+
+ ns = div_u64(tmp, adap->params.vpd.cclk);
+
+ memset(hwtstamps, 0, sizeof(*hwtstamps));
+ hwtstamps->hwtstamp = ns_to_ktime(ns);
+}
+
static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
const struct cpl_rx_pkt *pkt)
{
struct adapter *adapter = rxq->rspq.adap;
struct sge *s = &adapter->sge;
+ struct port_info *pi;
int ret;
struct sk_buff *skb;
@@ -1842,6 +1865,10 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(skb, rxq->rspq.idx);
skb_mark_napi_id(skb, &rxq->rspq.napi);
+ pi = netdev_priv(skb->dev);
+ if (pi->rxtstamp)
+ cxgb4_sgetim_to_hwtstamp(adapter, skb_hwtstamps(skb),
+ gl->sgetstamp);
if (rxq->rspq.netdev->features & NETIF_F_RXHASH)
skb_set_hash(skb, (__force u32)pkt->rsshdr.hash_val,
PKT_HASH_TYPE_L3);
@@ -1877,9 +1904,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
struct sge *s = &q->adap->sge;
int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
-#ifdef CONFIG_CHELSIO_T4_FCOE
struct port_info *pi;
-#endif
if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
return handle_trace_pkt(q->adap, si);
@@ -1910,6 +1935,10 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
rxq->stats.pkts++;
+ pi = netdev_priv(skb->dev);
+ if (pi->rxtstamp)
+ cxgb4_sgetim_to_hwtstamp(q->adap, skb_hwtstamps(skb),
+ si->sgetstamp);
if (csum_ok && (pkt->l2info & htonl(RXF_UDP_F | RXF_TCP_F))) {
if (!pkt->ip_frag) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1926,7 +1955,6 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
#define CPL_RX_PKT_FLAGS (RXF_PSH_F | RXF_SYN_F | RXF_UDP_F | \
RXF_TCP_F | RXF_IP_F | RXF_IP6_F | RXF_LRO_F)
- pi = netdev_priv(skb->dev);
if (!(pkt->l2info & cpu_to_be32(CPL_RX_PKT_FLAGS))) {
if ((pkt->l2info & cpu_to_be32(RXF_FCOE_F)) &&
(pi->fcoe.flags & CXGB_FCOE_ENABLED)) {
@@ -2067,6 +2095,8 @@ static int process_responses(struct sge_rspq *q, int budget)
unmap_rx_buf(q->adap, &rxq->fl);
}
+ si.sgetstamp = SGE_TIMESTAMP_G(
+ be64_to_cpu(rc->last_flit));
/*
* Last buffer remains mapped so explicitly make it
* coherent for CPU access.
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h b/drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h
new file mode 100644
index 000000000000..54b718111e3f
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the Chelsio T4 Ethernet driver for Linux.
+ *
+ * Copyright (c) 2003-2015 Chelsio Communications, Inc. 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.
+ */
+#ifndef __T4_CHIP_TYPE_H__
+#define __T4_CHIP_TYPE_H__
+
+#define CHELSIO_T4 0x4
+#define CHELSIO_T5 0x5
+#define CHELSIO_T6 0x6
+
+/* We code the Chelsio T4 Family "Chip Code" as a tuple:
+ *
+ * (Chip Version, Chip Revision)
+ *
+ * where:
+ *
+ * Chip Version: is T4, T5, etc.
+ * Chip Revision: is the FAB "spin" of the Chip Version.
+ */
+#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
+#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+
+enum chip_type {
+ T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+ T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+ T4_FIRST_REV = T4_A1,
+ T4_LAST_REV = T4_A2,
+
+ T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+ T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+ T5_FIRST_REV = T5_A0,
+ T5_LAST_REV = T5_A1,
+
+ T6_A0 = CHELSIO_CHIP_CODE(CHELSIO_T6, 0),
+ T6_FIRST_REV = T6_A0,
+ T6_LAST_REV = T6_A0,
+};
+
+static inline int is_t4(enum chip_type chip)
+{
+ return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4);
+}
+
+static inline int is_t5(enum chip_type chip)
+{
+ return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5);
+}
+
+static inline int is_t6(enum chip_type chip)
+{
+ return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T6);
+}
+
+#endif /* __T4_CHIP_TYPE_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 44806253c178..cf61a5869c6e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -699,50 +699,107 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
{
static const unsigned int t4_reg_ranges[] = {
0x1008, 0x1108,
- 0x1180, 0x11b4,
+ 0x1180, 0x1184,
+ 0x1190, 0x1194,
+ 0x11a0, 0x11a4,
+ 0x11b0, 0x11b4,
0x11fc, 0x123c,
0x1300, 0x173c,
0x1800, 0x18fc,
- 0x3000, 0x305c,
- 0x3068, 0x30d8,
- 0x30e0, 0x5924,
- 0x5960, 0x59d4,
- 0x5a00, 0x5af8,
+ 0x3000, 0x30d8,
+ 0x30e0, 0x30e4,
+ 0x30ec, 0x5910,
+ 0x5920, 0x5924,
+ 0x5960, 0x5960,
+ 0x5968, 0x5968,
+ 0x5970, 0x5970,
+ 0x5978, 0x5978,
+ 0x5980, 0x5980,
+ 0x5988, 0x5988,
+ 0x5990, 0x5990,
+ 0x5998, 0x5998,
+ 0x59a0, 0x59d4,
+ 0x5a00, 0x5ae0,
+ 0x5ae8, 0x5ae8,
+ 0x5af0, 0x5af0,
+ 0x5af8, 0x5af8,
0x6000, 0x6098,
0x6100, 0x6150,
0x6200, 0x6208,
0x6240, 0x6248,
- 0x6280, 0x6338,
+ 0x6280, 0x62b0,
+ 0x62c0, 0x6338,
0x6370, 0x638c,
0x6400, 0x643c,
0x6500, 0x6524,
- 0x6a00, 0x6a38,
- 0x6a60, 0x6a78,
- 0x6b00, 0x6b84,
- 0x6bf0, 0x6c84,
- 0x6cf0, 0x6d84,
- 0x6df0, 0x6e84,
- 0x6ef0, 0x6f84,
- 0x6ff0, 0x7084,
- 0x70f0, 0x7184,
- 0x71f0, 0x7284,
- 0x72f0, 0x7384,
- 0x73f0, 0x7450,
+ 0x6a00, 0x6a04,
+ 0x6a14, 0x6a38,
+ 0x6a60, 0x6a70,
+ 0x6a78, 0x6a78,
+ 0x6b00, 0x6b0c,
+ 0x6b1c, 0x6b84,
+ 0x6bf0, 0x6bf8,
+ 0x6c00, 0x6c0c,
+ 0x6c1c, 0x6c84,
+ 0x6cf0, 0x6cf8,
+ 0x6d00, 0x6d0c,
+ 0x6d1c, 0x6d84,
+ 0x6df0, 0x6df8,
+ 0x6e00, 0x6e0c,
+ 0x6e1c, 0x6e84,
+ 0x6ef0, 0x6ef8,
+ 0x6f00, 0x6f0c,
+ 0x6f1c, 0x6f84,
+ 0x6ff0, 0x6ff8,
+ 0x7000, 0x700c,
+ 0x701c, 0x7084,
+ 0x70f0, 0x70f8,
+ 0x7100, 0x710c,
+ 0x711c, 0x7184,
+ 0x71f0, 0x71f8,
+ 0x7200, 0x720c,
+ 0x721c, 0x7284,
+ 0x72f0, 0x72f8,
+ 0x7300, 0x730c,
+ 0x731c, 0x7384,
+ 0x73f0, 0x73f8,
+ 0x7400, 0x7450,
0x7500, 0x7530,
- 0x7600, 0x761c,
+ 0x7600, 0x760c,
+ 0x7614, 0x761c,
0x7680, 0x76cc,
0x7700, 0x7798,
0x77c0, 0x77fc,
0x7900, 0x79fc,
- 0x7b00, 0x7c38,
- 0x7d00, 0x7efc,
- 0x8dc0, 0x8e1c,
+ 0x7b00, 0x7b58,
+ 0x7b60, 0x7b84,
+ 0x7b8c, 0x7c38,
+ 0x7d00, 0x7d38,
+ 0x7d40, 0x7d80,
+ 0x7d8c, 0x7ddc,
+ 0x7de4, 0x7e04,
+ 0x7e10, 0x7e1c,
+ 0x7e24, 0x7e38,
+ 0x7e40, 0x7e44,
+ 0x7e4c, 0x7e78,
+ 0x7e80, 0x7ea4,
+ 0x7eac, 0x7edc,
+ 0x7ee8, 0x7efc,
+ 0x8dc0, 0x8e04,
+ 0x8e10, 0x8e1c,
0x8e30, 0x8e78,
- 0x8ea0, 0x8f6c,
- 0x8fc0, 0x9074,
+ 0x8ea0, 0x8eb8,
+ 0x8ec0, 0x8f6c,
+ 0x8fc0, 0x9008,
+ 0x9010, 0x9058,
+ 0x9060, 0x9060,
+ 0x9068, 0x9074,
0x90fc, 0x90fc,
- 0x9400, 0x9458,
- 0x9600, 0x96bc,
+ 0x9400, 0x9408,
+ 0x9410, 0x9458,
+ 0x9600, 0x9600,
+ 0x9608, 0x9638,
+ 0x9640, 0x96bc,
0x9800, 0x9808,
0x9820, 0x983c,
0x9850, 0x9864,
@@ -754,23 +811,42 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x9e80, 0x9eec,
0x9f00, 0x9f6c,
0x9f80, 0x9fec,
- 0xd004, 0xd03c,
+ 0xd004, 0xd004,
+ 0xd010, 0xd03c,
0xdfc0, 0xdfe0,
0xe000, 0xea7c,
- 0xf000, 0x11110,
- 0x11118, 0x11190,
+ 0xf000, 0x11190,
0x19040, 0x1906c,
0x19078, 0x19080,
- 0x1908c, 0x19124,
- 0x19150, 0x191b0,
+ 0x1908c, 0x190e4,
+ 0x190f0, 0x190f8,
+ 0x19100, 0x19110,
+ 0x19120, 0x19124,
+ 0x19150, 0x19194,
+ 0x1919c, 0x191b0,
0x191d0, 0x191e8,
0x19238, 0x1924c,
- 0x193f8, 0x19474,
- 0x19490, 0x194f8,
- 0x19800, 0x19f4c,
- 0x1a000, 0x1a06c,
- 0x1a0b0, 0x1a120,
- 0x1a128, 0x1a138,
+ 0x193f8, 0x1943c,
+ 0x1944c, 0x19474,
+ 0x19490, 0x194e0,
+ 0x194f0, 0x194f8,
+ 0x19800, 0x19c08,
+ 0x19c10, 0x19c90,
+ 0x19ca0, 0x19ce4,
+ 0x19cf0, 0x19d40,
+ 0x19d50, 0x19d94,
+ 0x19da0, 0x19de8,
+ 0x19df0, 0x19e40,
+ 0x19e50, 0x19e90,
+ 0x19ea0, 0x19f4c,
+ 0x1a000, 0x1a004,
+ 0x1a010, 0x1a06c,
+ 0x1a0b0, 0x1a0e4,
+ 0x1a0ec, 0x1a0f4,
+ 0x1a100, 0x1a108,
+ 0x1a114, 0x1a120,
+ 0x1a128, 0x1a130,
+ 0x1a138, 0x1a138,
0x1a190, 0x1a1c4,
0x1a1fc, 0x1a1fc,
0x1e040, 0x1e04c,
@@ -823,9 +899,12 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x1ffc0, 0x1ffc8,
0x20000, 0x2002c,
0x20100, 0x2013c,
- 0x20190, 0x201c8,
+ 0x20190, 0x201a0,
+ 0x201a8, 0x201b8,
+ 0x201c4, 0x201c8,
0x20200, 0x20318,
- 0x20400, 0x20528,
+ 0x20400, 0x204b4,
+ 0x204c0, 0x20528,
0x20540, 0x20614,
0x21000, 0x21040,
0x2104c, 0x21060,
@@ -834,22 +913,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x21270, 0x21284,
0x212fc, 0x21388,
0x21400, 0x21404,
- 0x21500, 0x21518,
- 0x2152c, 0x2153c,
+ 0x21500, 0x21500,
+ 0x21510, 0x21518,
+ 0x2152c, 0x21530,
+ 0x2153c, 0x2153c,
0x21550, 0x21554,
0x21600, 0x21600,
- 0x21608, 0x21628,
- 0x21630, 0x2163c,
+ 0x21608, 0x2161c,
+ 0x21624, 0x21628,
+ 0x21630, 0x21634,
+ 0x2163c, 0x2163c,
0x21700, 0x2171c,
0x21780, 0x2178c,
- 0x21800, 0x21c38,
- 0x21c80, 0x21d7c,
+ 0x21800, 0x21818,
+ 0x21820, 0x21828,
+ 0x21830, 0x21848,
+ 0x21850, 0x21854,
+ 0x21860, 0x21868,
+ 0x21870, 0x21870,
+ 0x21878, 0x21898,
+ 0x218a0, 0x218a8,
+ 0x218b0, 0x218c8,
+ 0x218d0, 0x218d4,
+ 0x218e0, 0x218e8,
+ 0x218f0, 0x218f0,
+ 0x218f8, 0x21a18,
+ 0x21a20, 0x21a28,
+ 0x21a30, 0x21a48,
+ 0x21a50, 0x21a54,
+ 0x21a60, 0x21a68,
+ 0x21a70, 0x21a70,
+ 0x21a78, 0x21a98,
+ 0x21aa0, 0x21aa8,
+ 0x21ab0, 0x21ac8,
+ 0x21ad0, 0x21ad4,
+ 0x21ae0, 0x21ae8,
+ 0x21af0, 0x21af0,
+ 0x21af8, 0x21c18,
+ 0x21c20, 0x21c20,
+ 0x21c28, 0x21c30,
+ 0x21c38, 0x21c38,
+ 0x21c80, 0x21c98,
+ 0x21ca0, 0x21ca8,
+ 0x21cb0, 0x21cc8,
+ 0x21cd0, 0x21cd4,
+ 0x21ce0, 0x21ce8,
+ 0x21cf0, 0x21cf0,
+ 0x21cf8, 0x21d7c,
0x21e00, 0x21e04,
0x22000, 0x2202c,
0x22100, 0x2213c,
- 0x22190, 0x221c8,
+ 0x22190, 0x221a0,
+ 0x221a8, 0x221b8,
+ 0x221c4, 0x221c8,
0x22200, 0x22318,
- 0x22400, 0x22528,
+ 0x22400, 0x224b4,
+ 0x224c0, 0x22528,
0x22540, 0x22614,
0x23000, 0x23040,
0x2304c, 0x23060,
@@ -858,22 +977,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x23270, 0x23284,
0x232fc, 0x23388,
0x23400, 0x23404,
- 0x23500, 0x23518,
- 0x2352c, 0x2353c,
+ 0x23500, 0x23500,
+ 0x23510, 0x23518,
+ 0x2352c, 0x23530,
+ 0x2353c, 0x2353c,
0x23550, 0x23554,
0x23600, 0x23600,
- 0x23608, 0x23628,
- 0x23630, 0x2363c,
+ 0x23608, 0x2361c,
+ 0x23624, 0x23628,
+ 0x23630, 0x23634,
+ 0x2363c, 0x2363c,
0x23700, 0x2371c,
0x23780, 0x2378c,
- 0x23800, 0x23c38,
- 0x23c80, 0x23d7c,
+ 0x23800, 0x23818,
+ 0x23820, 0x23828,
+ 0x23830, 0x23848,
+ 0x23850, 0x23854,
+ 0x23860, 0x23868,
+ 0x23870, 0x23870,
+ 0x23878, 0x23898,
+ 0x238a0, 0x238a8,
+ 0x238b0, 0x238c8,
+ 0x238d0, 0x238d4,
+ 0x238e0, 0x238e8,
+ 0x238f0, 0x238f0,
+ 0x238f8, 0x23a18,
+ 0x23a20, 0x23a28,
+ 0x23a30, 0x23a48,
+ 0x23a50, 0x23a54,
+ 0x23a60, 0x23a68,
+ 0x23a70, 0x23a70,
+ 0x23a78, 0x23a98,
+ 0x23aa0, 0x23aa8,
+ 0x23ab0, 0x23ac8,
+ 0x23ad0, 0x23ad4,
+ 0x23ae0, 0x23ae8,
+ 0x23af0, 0x23af0,
+ 0x23af8, 0x23c18,
+ 0x23c20, 0x23c20,
+ 0x23c28, 0x23c30,
+ 0x23c38, 0x23c38,
+ 0x23c80, 0x23c98,
+ 0x23ca0, 0x23ca8,
+ 0x23cb0, 0x23cc8,
+ 0x23cd0, 0x23cd4,
+ 0x23ce0, 0x23ce8,
+ 0x23cf0, 0x23cf0,
+ 0x23cf8, 0x23d7c,
0x23e00, 0x23e04,
0x24000, 0x2402c,
0x24100, 0x2413c,
- 0x24190, 0x241c8,
+ 0x24190, 0x241a0,
+ 0x241a8, 0x241b8,
+ 0x241c4, 0x241c8,
0x24200, 0x24318,
- 0x24400, 0x24528,
+ 0x24400, 0x244b4,
+ 0x244c0, 0x24528,
0x24540, 0x24614,
0x25000, 0x25040,
0x2504c, 0x25060,
@@ -882,22 +1041,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x25270, 0x25284,
0x252fc, 0x25388,
0x25400, 0x25404,
- 0x25500, 0x25518,
- 0x2552c, 0x2553c,
+ 0x25500, 0x25500,
+ 0x25510, 0x25518,
+ 0x2552c, 0x25530,
+ 0x2553c, 0x2553c,
0x25550, 0x25554,
0x25600, 0x25600,
- 0x25608, 0x25628,
- 0x25630, 0x2563c,
+ 0x25608, 0x2561c,
+ 0x25624, 0x25628,
+ 0x25630, 0x25634,
+ 0x2563c, 0x2563c,
0x25700, 0x2571c,
0x25780, 0x2578c,
- 0x25800, 0x25c38,
- 0x25c80, 0x25d7c,
+ 0x25800, 0x25818,
+ 0x25820, 0x25828,
+ 0x25830, 0x25848,
+ 0x25850, 0x25854,
+ 0x25860, 0x25868,
+ 0x25870, 0x25870,
+ 0x25878, 0x25898,
+ 0x258a0, 0x258a8,
+ 0x258b0, 0x258c8,
+ 0x258d0, 0x258d4,
+ 0x258e0, 0x258e8,
+ 0x258f0, 0x258f0,
+ 0x258f8, 0x25a18,
+ 0x25a20, 0x25a28,
+ 0x25a30, 0x25a48,
+ 0x25a50, 0x25a54,
+ 0x25a60, 0x25a68,
+ 0x25a70, 0x25a70,
+ 0x25a78, 0x25a98,
+ 0x25aa0, 0x25aa8,
+ 0x25ab0, 0x25ac8,
+ 0x25ad0, 0x25ad4,
+ 0x25ae0, 0x25ae8,
+ 0x25af0, 0x25af0,
+ 0x25af8, 0x25c18,
+ 0x25c20, 0x25c20,
+ 0x25c28, 0x25c30,
+ 0x25c38, 0x25c38,
+ 0x25c80, 0x25c98,
+ 0x25ca0, 0x25ca8,
+ 0x25cb0, 0x25cc8,
+ 0x25cd0, 0x25cd4,
+ 0x25ce0, 0x25ce8,
+ 0x25cf0, 0x25cf0,
+ 0x25cf8, 0x25d7c,
0x25e00, 0x25e04,
0x26000, 0x2602c,
0x26100, 0x2613c,
- 0x26190, 0x261c8,
+ 0x26190, 0x261a0,
+ 0x261a8, 0x261b8,
+ 0x261c4, 0x261c8,
0x26200, 0x26318,
- 0x26400, 0x26528,
+ 0x26400, 0x264b4,
+ 0x264c0, 0x26528,
0x26540, 0x26614,
0x27000, 0x27040,
0x2704c, 0x27060,
@@ -906,51 +1105,120 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x27270, 0x27284,
0x272fc, 0x27388,
0x27400, 0x27404,
- 0x27500, 0x27518,
- 0x2752c, 0x2753c,
+ 0x27500, 0x27500,
+ 0x27510, 0x27518,
+ 0x2752c, 0x27530,
+ 0x2753c, 0x2753c,
0x27550, 0x27554,
0x27600, 0x27600,
- 0x27608, 0x27628,
- 0x27630, 0x2763c,
+ 0x27608, 0x2761c,
+ 0x27624, 0x27628,
+ 0x27630, 0x27634,
+ 0x2763c, 0x2763c,
0x27700, 0x2771c,
0x27780, 0x2778c,
- 0x27800, 0x27c38,
- 0x27c80, 0x27d7c,
+ 0x27800, 0x27818,
+ 0x27820, 0x27828,
+ 0x27830, 0x27848,
+ 0x27850, 0x27854,
+ 0x27860, 0x27868,
+ 0x27870, 0x27870,
+ 0x27878, 0x27898,
+ 0x278a0, 0x278a8,
+ 0x278b0, 0x278c8,
+ 0x278d0, 0x278d4,
+ 0x278e0, 0x278e8,
+ 0x278f0, 0x278f0,
+ 0x278f8, 0x27a18,
+ 0x27a20, 0x27a28,
+ 0x27a30, 0x27a48,
+ 0x27a50, 0x27a54,
+ 0x27a60, 0x27a68,
+ 0x27a70, 0x27a70,
+ 0x27a78, 0x27a98,
+ 0x27aa0, 0x27aa8,
+ 0x27ab0, 0x27ac8,
+ 0x27ad0, 0x27ad4,
+ 0x27ae0, 0x27ae8,
+ 0x27af0, 0x27af0,
+ 0x27af8, 0x27c18,
+ 0x27c20, 0x27c20,
+ 0x27c28, 0x27c30,
+ 0x27c38, 0x27c38,
+ 0x27c80, 0x27c98,
+ 0x27ca0, 0x27ca8,
+ 0x27cb0, 0x27cc8,
+ 0x27cd0, 0x27cd4,
+ 0x27ce0, 0x27ce8,
+ 0x27cf0, 0x27cf0,
+ 0x27cf8, 0x27d7c,
0x27e00, 0x27e04,
};
static const unsigned int t5_reg_ranges[] = {
- 0x1008, 0x1148,
- 0x1180, 0x11b4,
+ 0x1008, 0x10c0,
+ 0x10cc, 0x10f8,
+ 0x1100, 0x1100,
+ 0x110c, 0x1148,
+ 0x1180, 0x1184,
+ 0x1190, 0x1194,
+ 0x11a0, 0x11a4,
+ 0x11b0, 0x11b4,
0x11fc, 0x123c,
0x1280, 0x173c,
0x1800, 0x18fc,
0x3000, 0x3028,
- 0x3068, 0x30d8,
+ 0x3060, 0x30b0,
+ 0x30b8, 0x30d8,
0x30e0, 0x30fc,
0x3140, 0x357c,
0x35a8, 0x35cc,
0x35ec, 0x35ec,
0x3600, 0x5624,
- 0x56cc, 0x575c,
+ 0x56cc, 0x56ec,
+ 0x56f4, 0x5720,
+ 0x5728, 0x575c,
0x580c, 0x5814,
- 0x5890, 0x58bc,
- 0x5940, 0x59dc,
+ 0x5890, 0x589c,
+ 0x58a4, 0x58ac,
+ 0x58b8, 0x58bc,
+ 0x5940, 0x59c8,
+ 0x59d0, 0x59dc,
0x59fc, 0x5a18,
- 0x5a60, 0x5a9c,
+ 0x5a60, 0x5a70,
+ 0x5a80, 0x5a9c,
0x5b94, 0x5bfc,
- 0x6000, 0x6040,
- 0x6058, 0x614c,
+ 0x6000, 0x6020,
+ 0x6028, 0x6040,
+ 0x6058, 0x609c,
+ 0x60a8, 0x614c,
0x7700, 0x7798,
0x77c0, 0x78fc,
- 0x7b00, 0x7c54,
- 0x7d00, 0x7efc,
+ 0x7b00, 0x7b58,
+ 0x7b60, 0x7b84,
+ 0x7b8c, 0x7c54,
+ 0x7d00, 0x7d38,
+ 0x7d40, 0x7d80,
+ 0x7d8c, 0x7ddc,
+ 0x7de4, 0x7e04,
+ 0x7e10, 0x7e1c,
+ 0x7e24, 0x7e38,
+ 0x7e40, 0x7e44,
+ 0x7e4c, 0x7e78,
+ 0x7e80, 0x7edc,
+ 0x7ee8, 0x7efc,
0x8dc0, 0x8de0,
- 0x8df8, 0x8e84,
+ 0x8df8, 0x8e04,
+ 0x8e10, 0x8e84,
0x8ea0, 0x8f84,
- 0x8fc0, 0x90f8,
- 0x9400, 0x9470,
- 0x9600, 0x96f4,
+ 0x8fc0, 0x9058,
+ 0x9060, 0x9060,
+ 0x9068, 0x90f8,
+ 0x9400, 0x9408,
+ 0x9410, 0x9470,
+ 0x9600, 0x9600,
+ 0x9608, 0x9638,
+ 0x9640, 0x96f4,
0x9800, 0x9808,
0x9820, 0x983c,
0x9850, 0x9864,
@@ -962,103 +1230,143 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x9e80, 0x9eec,
0x9f00, 0x9f6c,
0x9f80, 0xa020,
- 0xd004, 0xd03c,
+ 0xd004, 0xd004,
+ 0xd010, 0xd03c,
0xdfc0, 0xdfe0,
- 0xe000, 0x11088,
- 0x1109c, 0x11110,
- 0x11118, 0x1117c,
+ 0xe000, 0x1106c,
+ 0x11074, 0x11088,
+ 0x1109c, 0x1117c,
0x11190, 0x11204,
0x19040, 0x1906c,
0x19078, 0x19080,
- 0x1908c, 0x19124,
- 0x19150, 0x191b0,
+ 0x1908c, 0x190e8,
+ 0x190f0, 0x190f8,
+ 0x19100, 0x19110,
+ 0x19120, 0x19124,
+ 0x19150, 0x19194,
+ 0x1919c, 0x191b0,
0x191d0, 0x191e8,
0x19238, 0x19290,
- 0x193f8, 0x19474,
+ 0x193f8, 0x19428,
+ 0x19430, 0x19444,
+ 0x1944c, 0x1946c,
+ 0x19474, 0x19474,
0x19490, 0x194cc,
0x194f0, 0x194f8,
- 0x19c00, 0x19c60,
- 0x19c94, 0x19e10,
- 0x19e50, 0x19f34,
+ 0x19c00, 0x19c08,
+ 0x19c10, 0x19c60,
+ 0x19c94, 0x19ce4,
+ 0x19cf0, 0x19d40,
+ 0x19d50, 0x19d94,
+ 0x19da0, 0x19de8,
+ 0x19df0, 0x19e10,
+ 0x19e50, 0x19e90,
+ 0x19ea0, 0x19f24,
+ 0x19f34, 0x19f34,
0x19f40, 0x19f50,
- 0x19f90, 0x19fe4,
- 0x1a000, 0x1a06c,
- 0x1a0b0, 0x1a120,
- 0x1a128, 0x1a138,
+ 0x19f90, 0x19fb4,
+ 0x19fc4, 0x19fe4,
+ 0x1a000, 0x1a004,
+ 0x1a010, 0x1a06c,
+ 0x1a0b0, 0x1a0e4,
+ 0x1a0ec, 0x1a0f8,
+ 0x1a100, 0x1a108,
+ 0x1a114, 0x1a120,
+ 0x1a128, 0x1a130,
+ 0x1a138, 0x1a138,
0x1a190, 0x1a1c4,
0x1a1fc, 0x1a1fc,
0x1e008, 0x1e00c,
- 0x1e040, 0x1e04c,
+ 0x1e040, 0x1e044,
+ 0x1e04c, 0x1e04c,
0x1e284, 0x1e290,
0x1e2c0, 0x1e2c0,
0x1e2e0, 0x1e2e0,
0x1e300, 0x1e384,
0x1e3c0, 0x1e3c8,
0x1e408, 0x1e40c,
- 0x1e440, 0x1e44c,
+ 0x1e440, 0x1e444,
+ 0x1e44c, 0x1e44c,
0x1e684, 0x1e690,
0x1e6c0, 0x1e6c0,
0x1e6e0, 0x1e6e0,
0x1e700, 0x1e784,
0x1e7c0, 0x1e7c8,
0x1e808, 0x1e80c,
- 0x1e840, 0x1e84c,
+ 0x1e840, 0x1e844,
+ 0x1e84c, 0x1e84c,
0x1ea84, 0x1ea90,
0x1eac0, 0x1eac0,
0x1eae0, 0x1eae0,
0x1eb00, 0x1eb84,
0x1ebc0, 0x1ebc8,
0x1ec08, 0x1ec0c,
- 0x1ec40, 0x1ec4c,
+ 0x1ec40, 0x1ec44,
+ 0x1ec4c, 0x1ec4c,
0x1ee84, 0x1ee90,
0x1eec0, 0x1eec0,
0x1eee0, 0x1eee0,
0x1ef00, 0x1ef84,
0x1efc0, 0x1efc8,
0x1f008, 0x1f00c,
- 0x1f040, 0x1f04c,
+ 0x1f040, 0x1f044,
+ 0x1f04c, 0x1f04c,
0x1f284, 0x1f290,
0x1f2c0, 0x1f2c0,
0x1f2e0, 0x1f2e0,
0x1f300, 0x1f384,
0x1f3c0, 0x1f3c8,
0x1f408, 0x1f40c,
- 0x1f440, 0x1f44c,
+ 0x1f440, 0x1f444,
+ 0x1f44c, 0x1f44c,
0x1f684, 0x1f690,
0x1f6c0, 0x1f6c0,
0x1f6e0, 0x1f6e0,
0x1f700, 0x1f784,
0x1f7c0, 0x1f7c8,
0x1f808, 0x1f80c,
- 0x1f840, 0x1f84c,
+ 0x1f840, 0x1f844,
+ 0x1f84c, 0x1f84c,
0x1fa84, 0x1fa90,
0x1fac0, 0x1fac0,
0x1fae0, 0x1fae0,
0x1fb00, 0x1fb84,
0x1fbc0, 0x1fbc8,
0x1fc08, 0x1fc0c,
- 0x1fc40, 0x1fc4c,
+ 0x1fc40, 0x1fc44,
+ 0x1fc4c, 0x1fc4c,
0x1fe84, 0x1fe90,
0x1fec0, 0x1fec0,
0x1fee0, 0x1fee0,
0x1ff00, 0x1ff84,
0x1ffc0, 0x1ffc8,
0x30000, 0x30030,
+ 0x30038, 0x30038,
+ 0x30040, 0x30040,
0x30100, 0x30144,
- 0x30190, 0x301d0,
+ 0x30190, 0x301a0,
+ 0x301a8, 0x301b8,
+ 0x301c4, 0x301c8,
+ 0x301d0, 0x301d0,
0x30200, 0x30318,
- 0x30400, 0x3052c,
+ 0x30400, 0x304b4,
+ 0x304c0, 0x3052c,
0x30540, 0x3061c,
- 0x30800, 0x30834,
+ 0x30800, 0x30828,
+ 0x30834, 0x30834,
0x308c0, 0x30908,
0x30910, 0x309ac,
- 0x30a00, 0x30a2c,
+ 0x30a00, 0x30a14,
+ 0x30a1c, 0x30a2c,
0x30a44, 0x30a50,
- 0x30a74, 0x30c24,
+ 0x30a74, 0x30a74,
+ 0x30a7c, 0x30afc,
+ 0x30b08, 0x30c24,
0x30d00, 0x30d00,
0x30d08, 0x30d14,
0x30d1c, 0x30d20,
- 0x30d3c, 0x30d50,
+ 0x30d3c, 0x30d3c,
+ 0x30d48, 0x30d50,
0x31200, 0x3120c,
0x31220, 0x31220,
0x31240, 0x31240,
@@ -1078,27 +1386,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x322c8, 0x322fc,
0x32600, 0x32630,
0x32a00, 0x32abc,
- 0x32b00, 0x32b70,
- 0x33000, 0x33048,
- 0x33060, 0x3309c,
- 0x330f0, 0x33148,
- 0x33160, 0x3319c,
- 0x331f0, 0x332e4,
- 0x332f8, 0x333e4,
- 0x333f8, 0x33448,
- 0x33460, 0x3349c,
- 0x334f0, 0x33548,
- 0x33560, 0x3359c,
- 0x335f0, 0x336e4,
- 0x336f8, 0x337e4,
+ 0x32b00, 0x32b10,
+ 0x32b20, 0x32b30,
+ 0x32b40, 0x32b50,
+ 0x32b60, 0x32b70,
+ 0x33000, 0x33028,
+ 0x33030, 0x33048,
+ 0x33060, 0x33068,
+ 0x33070, 0x3309c,
+ 0x330f0, 0x33128,
+ 0x33130, 0x33148,
+ 0x33160, 0x33168,
+ 0x33170, 0x3319c,
+ 0x331f0, 0x33238,
+ 0x33240, 0x33240,
+ 0x33248, 0x33250,
+ 0x3325c, 0x33264,
+ 0x33270, 0x332b8,
+ 0x332c0, 0x332e4,
+ 0x332f8, 0x33338,
+ 0x33340, 0x33340,
+ 0x33348, 0x33350,
+ 0x3335c, 0x33364,
+ 0x33370, 0x333b8,
+ 0x333c0, 0x333e4,
+ 0x333f8, 0x33428,
+ 0x33430, 0x33448,
+ 0x33460, 0x33468,
+ 0x33470, 0x3349c,
+ 0x334f0, 0x33528,
+ 0x33530, 0x33548,
+ 0x33560, 0x33568,
+ 0x33570, 0x3359c,
+ 0x335f0, 0x33638,
+ 0x33640, 0x33640,
+ 0x33648, 0x33650,
+ 0x3365c, 0x33664,
+ 0x33670, 0x336b8,
+ 0x336c0, 0x336e4,
+ 0x336f8, 0x33738,
+ 0x33740, 0x33740,
+ 0x33748, 0x33750,
+ 0x3375c, 0x33764,
+ 0x33770, 0x337b8,
+ 0x337c0, 0x337e4,
0x337f8, 0x337fc,
0x33814, 0x33814,
0x3382c, 0x3382c,
0x33880, 0x3388c,
0x338e8, 0x338ec,
- 0x33900, 0x33948,
- 0x33960, 0x3399c,
- 0x339f0, 0x33ae4,
+ 0x33900, 0x33928,
+ 0x33930, 0x33948,
+ 0x33960, 0x33968,
+ 0x33970, 0x3399c,
+ 0x339f0, 0x33a38,
+ 0x33a40, 0x33a40,
+ 0x33a48, 0x33a50,
+ 0x33a5c, 0x33a64,
+ 0x33a70, 0x33ab8,
+ 0x33ac0, 0x33ae4,
0x33af8, 0x33b10,
0x33b28, 0x33b28,
0x33b3c, 0x33b50,
@@ -1107,21 +1453,32 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x33c3c, 0x33c50,
0x33cf0, 0x33cfc,
0x34000, 0x34030,
+ 0x34038, 0x34038,
+ 0x34040, 0x34040,
0x34100, 0x34144,
- 0x34190, 0x341d0,
+ 0x34190, 0x341a0,
+ 0x341a8, 0x341b8,
+ 0x341c4, 0x341c8,
+ 0x341d0, 0x341d0,
0x34200, 0x34318,
- 0x34400, 0x3452c,
+ 0x34400, 0x344b4,
+ 0x344c0, 0x3452c,
0x34540, 0x3461c,
- 0x34800, 0x34834,
+ 0x34800, 0x34828,
+ 0x34834, 0x34834,
0x348c0, 0x34908,
0x34910, 0x349ac,
- 0x34a00, 0x34a2c,
+ 0x34a00, 0x34a14,
+ 0x34a1c, 0x34a2c,
0x34a44, 0x34a50,
- 0x34a74, 0x34c24,
+ 0x34a74, 0x34a74,
+ 0x34a7c, 0x34afc,
+ 0x34b08, 0x34c24,
0x34d00, 0x34d00,
0x34d08, 0x34d14,
0x34d1c, 0x34d20,
- 0x34d3c, 0x34d50,
+ 0x34d3c, 0x34d3c,
+ 0x34d48, 0x34d50,
0x35200, 0x3520c,
0x35220, 0x35220,
0x35240, 0x35240,
@@ -1141,27 +1498,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x362c8, 0x362fc,
0x36600, 0x36630,
0x36a00, 0x36abc,
- 0x36b00, 0x36b70,
- 0x37000, 0x37048,
- 0x37060, 0x3709c,
- 0x370f0, 0x37148,
- 0x37160, 0x3719c,
- 0x371f0, 0x372e4,
- 0x372f8, 0x373e4,
- 0x373f8, 0x37448,
- 0x37460, 0x3749c,
- 0x374f0, 0x37548,
- 0x37560, 0x3759c,
- 0x375f0, 0x376e4,
- 0x376f8, 0x377e4,
+ 0x36b00, 0x36b10,
+ 0x36b20, 0x36b30,
+ 0x36b40, 0x36b50,
+ 0x36b60, 0x36b70,
+ 0x37000, 0x37028,
+ 0x37030, 0x37048,
+ 0x37060, 0x37068,
+ 0x37070, 0x3709c,
+ 0x370f0, 0x37128,
+ 0x37130, 0x37148,
+ 0x37160, 0x37168,
+ 0x37170, 0x3719c,
+ 0x371f0, 0x37238,
+ 0x37240, 0x37240,
+ 0x37248, 0x37250,
+ 0x3725c, 0x37264,
+ 0x37270, 0x372b8,
+ 0x372c0, 0x372e4,
+ 0x372f8, 0x37338,
+ 0x37340, 0x37340,
+ 0x37348, 0x37350,
+ 0x3735c, 0x37364,
+ 0x37370, 0x373b8,
+ 0x373c0, 0x373e4,
+ 0x373f8, 0x37428,
+ 0x37430, 0x37448,
+ 0x37460, 0x37468,
+ 0x37470, 0x3749c,
+ 0x374f0, 0x37528,
+ 0x37530, 0x37548,
+ 0x37560, 0x37568,
+ 0x37570, 0x3759c,
+ 0x375f0, 0x37638,
+ 0x37640, 0x37640,
+ 0x37648, 0x37650,
+ 0x3765c, 0x37664,
+ 0x37670, 0x376b8,
+ 0x376c0, 0x376e4,
+ 0x376f8, 0x37738,
+ 0x37740, 0x37740,
+ 0x37748, 0x37750,
+ 0x3775c, 0x37764,
+ 0x37770, 0x377b8,
+ 0x377c0, 0x377e4,
0x377f8, 0x377fc,
0x37814, 0x37814,
0x3782c, 0x3782c,
0x37880, 0x3788c,
0x378e8, 0x378ec,
- 0x37900, 0x37948,
- 0x37960, 0x3799c,
- 0x379f0, 0x37ae4,
+ 0x37900, 0x37928,
+ 0x37930, 0x37948,
+ 0x37960, 0x37968,
+ 0x37970, 0x3799c,
+ 0x379f0, 0x37a38,
+ 0x37a40, 0x37a40,
+ 0x37a48, 0x37a50,
+ 0x37a5c, 0x37a64,
+ 0x37a70, 0x37ab8,
+ 0x37ac0, 0x37ae4,
0x37af8, 0x37b10,
0x37b28, 0x37b28,
0x37b3c, 0x37b50,
@@ -1170,21 +1565,32 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x37c3c, 0x37c50,
0x37cf0, 0x37cfc,
0x38000, 0x38030,
+ 0x38038, 0x38038,
+ 0x38040, 0x38040,
0x38100, 0x38144,
- 0x38190, 0x381d0,
+ 0x38190, 0x381a0,
+ 0x381a8, 0x381b8,
+ 0x381c4, 0x381c8,
+ 0x381d0, 0x381d0,
0x38200, 0x38318,
- 0x38400, 0x3852c,
+ 0x38400, 0x384b4,
+ 0x384c0, 0x3852c,
0x38540, 0x3861c,
- 0x38800, 0x38834,
+ 0x38800, 0x38828,
+ 0x38834, 0x38834,
0x388c0, 0x38908,
0x38910, 0x389ac,
- 0x38a00, 0x38a2c,
+ 0x38a00, 0x38a14,
+ 0x38a1c, 0x38a2c,
0x38a44, 0x38a50,
- 0x38a74, 0x38c24,
+ 0x38a74, 0x38a74,
+ 0x38a7c, 0x38afc,
+ 0x38b08, 0x38c24,
0x38d00, 0x38d00,
0x38d08, 0x38d14,
0x38d1c, 0x38d20,
- 0x38d3c, 0x38d50,
+ 0x38d3c, 0x38d3c,
+ 0x38d48, 0x38d50,
0x39200, 0x3920c,
0x39220, 0x39220,
0x39240, 0x39240,
@@ -1204,27 +1610,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x3a2c8, 0x3a2fc,
0x3a600, 0x3a630,
0x3aa00, 0x3aabc,
- 0x3ab00, 0x3ab70,
- 0x3b000, 0x3b048,
- 0x3b060, 0x3b09c,
- 0x3b0f0, 0x3b148,
- 0x3b160, 0x3b19c,
- 0x3b1f0, 0x3b2e4,
- 0x3b2f8, 0x3b3e4,
- 0x3b3f8, 0x3b448,
- 0x3b460, 0x3b49c,
- 0x3b4f0, 0x3b548,
- 0x3b560, 0x3b59c,
- 0x3b5f0, 0x3b6e4,
- 0x3b6f8, 0x3b7e4,
+ 0x3ab00, 0x3ab10,
+ 0x3ab20, 0x3ab30,
+ 0x3ab40, 0x3ab50,
+ 0x3ab60, 0x3ab70,
+ 0x3b000, 0x3b028,
+ 0x3b030, 0x3b048,
+ 0x3b060, 0x3b068,
+ 0x3b070, 0x3b09c,
+ 0x3b0f0, 0x3b128,
+ 0x3b130, 0x3b148,
+ 0x3b160, 0x3b168,
+ 0x3b170, 0x3b19c,
+ 0x3b1f0, 0x3b238,
+ 0x3b240, 0x3b240,
+ 0x3b248, 0x3b250,
+ 0x3b25c, 0x3b264,
+ 0x3b270, 0x3b2b8,
+ 0x3b2c0, 0x3b2e4,
+ 0x3b2f8, 0x3b338,
+ 0x3b340, 0x3b340,
+ 0x3b348, 0x3b350,
+ 0x3b35c, 0x3b364,
+ 0x3b370, 0x3b3b8,
+ 0x3b3c0, 0x3b3e4,
+ 0x3b3f8, 0x3b428,
+ 0x3b430, 0x3b448,
+ 0x3b460, 0x3b468,
+ 0x3b470, 0x3b49c,
+ 0x3b4f0, 0x3b528,
+ 0x3b530, 0x3b548,
+ 0x3b560, 0x3b568,
+ 0x3b570, 0x3b59c,
+ 0x3b5f0, 0x3b638,
+ 0x3b640, 0x3b640,
+ 0x3b648, 0x3b650,
+ 0x3b65c, 0x3b664,
+ 0x3b670, 0x3b6b8,
+ 0x3b6c0, 0x3b6e4,
+ 0x3b6f8, 0x3b738,
+ 0x3b740, 0x3b740,
+ 0x3b748, 0x3b750,
+ 0x3b75c, 0x3b764,
+ 0x3b770, 0x3b7b8,
+ 0x3b7c0, 0x3b7e4,
0x3b7f8, 0x3b7fc,
0x3b814, 0x3b814,
0x3b82c, 0x3b82c,
0x3b880, 0x3b88c,
0x3b8e8, 0x3b8ec,
- 0x3b900, 0x3b948,
- 0x3b960, 0x3b99c,
- 0x3b9f0, 0x3bae4,
+ 0x3b900, 0x3b928,
+ 0x3b930, 0x3b948,
+ 0x3b960, 0x3b968,
+ 0x3b970, 0x3b99c,
+ 0x3b9f0, 0x3ba38,
+ 0x3ba40, 0x3ba40,
+ 0x3ba48, 0x3ba50,
+ 0x3ba5c, 0x3ba64,
+ 0x3ba70, 0x3bab8,
+ 0x3bac0, 0x3bae4,
0x3baf8, 0x3bb10,
0x3bb28, 0x3bb28,
0x3bb3c, 0x3bb50,
@@ -1233,21 +1677,32 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x3bc3c, 0x3bc50,
0x3bcf0, 0x3bcfc,
0x3c000, 0x3c030,
+ 0x3c038, 0x3c038,
+ 0x3c040, 0x3c040,
0x3c100, 0x3c144,
- 0x3c190, 0x3c1d0,
+ 0x3c190, 0x3c1a0,
+ 0x3c1a8, 0x3c1b8,
+ 0x3c1c4, 0x3c1c8,
+ 0x3c1d0, 0x3c1d0,
0x3c200, 0x3c318,
- 0x3c400, 0x3c52c,
+ 0x3c400, 0x3c4b4,
+ 0x3c4c0, 0x3c52c,
0x3c540, 0x3c61c,
- 0x3c800, 0x3c834,
+ 0x3c800, 0x3c828,
+ 0x3c834, 0x3c834,
0x3c8c0, 0x3c908,
0x3c910, 0x3c9ac,
- 0x3ca00, 0x3ca2c,
+ 0x3ca00, 0x3ca14,
+ 0x3ca1c, 0x3ca2c,
0x3ca44, 0x3ca50,
- 0x3ca74, 0x3cc24,
+ 0x3ca74, 0x3ca74,
+ 0x3ca7c, 0x3cafc,
+ 0x3cb08, 0x3cc24,
0x3cd00, 0x3cd00,
0x3cd08, 0x3cd14,
0x3cd1c, 0x3cd20,
- 0x3cd3c, 0x3cd50,
+ 0x3cd3c, 0x3cd3c,
+ 0x3cd48, 0x3cd50,
0x3d200, 0x3d20c,
0x3d220, 0x3d220,
0x3d240, 0x3d240,
@@ -1267,27 +1722,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x3e2c8, 0x3e2fc,
0x3e600, 0x3e630,
0x3ea00, 0x3eabc,
- 0x3eb00, 0x3eb70,
- 0x3f000, 0x3f048,
- 0x3f060, 0x3f09c,
- 0x3f0f0, 0x3f148,
- 0x3f160, 0x3f19c,
- 0x3f1f0, 0x3f2e4,
- 0x3f2f8, 0x3f3e4,
- 0x3f3f8, 0x3f448,
- 0x3f460, 0x3f49c,
- 0x3f4f0, 0x3f548,
- 0x3f560, 0x3f59c,
- 0x3f5f0, 0x3f6e4,
- 0x3f6f8, 0x3f7e4,
+ 0x3eb00, 0x3eb10,
+ 0x3eb20, 0x3eb30,
+ 0x3eb40, 0x3eb50,
+ 0x3eb60, 0x3eb70,
+ 0x3f000, 0x3f028,
+ 0x3f030, 0x3f048,
+ 0x3f060, 0x3f068,
+ 0x3f070, 0x3f09c,
+ 0x3f0f0, 0x3f128,
+ 0x3f130, 0x3f148,
+ 0x3f160, 0x3f168,
+ 0x3f170, 0x3f19c,
+ 0x3f1f0, 0x3f238,
+ 0x3f240, 0x3f240,
+ 0x3f248, 0x3f250,
+ 0x3f25c, 0x3f264,
+ 0x3f270, 0x3f2b8,
+ 0x3f2c0, 0x3f2e4,
+ 0x3f2f8, 0x3f338,
+ 0x3f340, 0x3f340,
+ 0x3f348, 0x3f350,
+ 0x3f35c, 0x3f364,
+ 0x3f370, 0x3f3b8,
+ 0x3f3c0, 0x3f3e4,
+ 0x3f3f8, 0x3f428,
+ 0x3f430, 0x3f448,
+ 0x3f460, 0x3f468,
+ 0x3f470, 0x3f49c,
+ 0x3f4f0, 0x3f528,
+ 0x3f530, 0x3f548,
+ 0x3f560, 0x3f568,
+ 0x3f570, 0x3f59c,
+ 0x3f5f0, 0x3f638,
+ 0x3f640, 0x3f640,
+ 0x3f648, 0x3f650,
+ 0x3f65c, 0x3f664,
+ 0x3f670, 0x3f6b8,
+ 0x3f6c0, 0x3f6e4,
+ 0x3f6f8, 0x3f738,
+ 0x3f740, 0x3f740,
+ 0x3f748, 0x3f750,
+ 0x3f75c, 0x3f764,
+ 0x3f770, 0x3f7b8,
+ 0x3f7c0, 0x3f7e4,
0x3f7f8, 0x3f7fc,
0x3f814, 0x3f814,
0x3f82c, 0x3f82c,
0x3f880, 0x3f88c,
0x3f8e8, 0x3f8ec,
- 0x3f900, 0x3f948,
- 0x3f960, 0x3f99c,
- 0x3f9f0, 0x3fae4,
+ 0x3f900, 0x3f928,
+ 0x3f930, 0x3f948,
+ 0x3f960, 0x3f968,
+ 0x3f970, 0x3f99c,
+ 0x3f9f0, 0x3fa38,
+ 0x3fa40, 0x3fa40,
+ 0x3fa48, 0x3fa50,
+ 0x3fa5c, 0x3fa64,
+ 0x3fa70, 0x3fab8,
+ 0x3fac0, 0x3fae4,
0x3faf8, 0x3fb10,
0x3fb28, 0x3fb28,
0x3fb3c, 0x3fb50,
@@ -1296,108 +1789,224 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x3fc3c, 0x3fc50,
0x3fcf0, 0x3fcfc,
0x40000, 0x4000c,
- 0x40040, 0x40068,
- 0x4007c, 0x40144,
+ 0x40040, 0x40050,
+ 0x40060, 0x40068,
+ 0x4007c, 0x4008c,
+ 0x40094, 0x400b0,
+ 0x400c0, 0x40144,
0x40180, 0x4018c,
- 0x40200, 0x40298,
- 0x402ac, 0x4033c,
+ 0x40200, 0x40254,
+ 0x40260, 0x40264,
+ 0x40270, 0x40288,
+ 0x40290, 0x40298,
+ 0x402ac, 0x402c8,
+ 0x402d0, 0x402e0,
+ 0x402f0, 0x402f0,
+ 0x40300, 0x4033c,
0x403f8, 0x403fc,
0x41304, 0x413c4,
- 0x41400, 0x4141c,
+ 0x41400, 0x4140c,
+ 0x41414, 0x4141c,
0x41480, 0x414d0,
- 0x44000, 0x44078,
- 0x440c0, 0x44278,
- 0x442c0, 0x44478,
- 0x444c0, 0x44678,
- 0x446c0, 0x44878,
- 0x448c0, 0x449fc,
- 0x45000, 0x45068,
+ 0x44000, 0x44054,
+ 0x4405c, 0x44078,
+ 0x440c0, 0x44174,
+ 0x44180, 0x441ac,
+ 0x441b4, 0x441b8,
+ 0x441c0, 0x44254,
+ 0x4425c, 0x44278,
+ 0x442c0, 0x44374,
+ 0x44380, 0x443ac,
+ 0x443b4, 0x443b8,
+ 0x443c0, 0x44454,
+ 0x4445c, 0x44478,
+ 0x444c0, 0x44574,
+ 0x44580, 0x445ac,
+ 0x445b4, 0x445b8,
+ 0x445c0, 0x44654,
+ 0x4465c, 0x44678,
+ 0x446c0, 0x44774,
+ 0x44780, 0x447ac,
+ 0x447b4, 0x447b8,
+ 0x447c0, 0x44854,
+ 0x4485c, 0x44878,
+ 0x448c0, 0x44974,
+ 0x44980, 0x449ac,
+ 0x449b4, 0x449b8,
+ 0x449c0, 0x449fc,
+ 0x45000, 0x45004,
+ 0x45010, 0x45030,
+ 0x45040, 0x45060,
+ 0x45068, 0x45068,
0x45080, 0x45084,
0x450a0, 0x450b0,
- 0x45200, 0x45268,
+ 0x45200, 0x45204,
+ 0x45210, 0x45230,
+ 0x45240, 0x45260,
+ 0x45268, 0x45268,
0x45280, 0x45284,
0x452a0, 0x452b0,
0x460c0, 0x460e4,
- 0x47000, 0x4708c,
+ 0x47000, 0x4703c,
+ 0x47044, 0x4708c,
0x47200, 0x47250,
- 0x47400, 0x47420,
+ 0x47400, 0x47408,
+ 0x47414, 0x47420,
0x47600, 0x47618,
0x47800, 0x47814,
0x48000, 0x4800c,
- 0x48040, 0x48068,
- 0x4807c, 0x48144,
+ 0x48040, 0x48050,
+ 0x48060, 0x48068,
+ 0x4807c, 0x4808c,
+ 0x48094, 0x480b0,
+ 0x480c0, 0x48144,
0x48180, 0x4818c,
- 0x48200, 0x48298,
- 0x482ac, 0x4833c,
+ 0x48200, 0x48254,
+ 0x48260, 0x48264,
+ 0x48270, 0x48288,
+ 0x48290, 0x48298,
+ 0x482ac, 0x482c8,
+ 0x482d0, 0x482e0,
+ 0x482f0, 0x482f0,
+ 0x48300, 0x4833c,
0x483f8, 0x483fc,
0x49304, 0x493c4,
- 0x49400, 0x4941c,
+ 0x49400, 0x4940c,
+ 0x49414, 0x4941c,
0x49480, 0x494d0,
- 0x4c000, 0x4c078,
- 0x4c0c0, 0x4c278,
- 0x4c2c0, 0x4c478,
- 0x4c4c0, 0x4c678,
- 0x4c6c0, 0x4c878,
- 0x4c8c0, 0x4c9fc,
- 0x4d000, 0x4d068,
+ 0x4c000, 0x4c054,
+ 0x4c05c, 0x4c078,
+ 0x4c0c0, 0x4c174,
+ 0x4c180, 0x4c1ac,
+ 0x4c1b4, 0x4c1b8,
+ 0x4c1c0, 0x4c254,
+ 0x4c25c, 0x4c278,
+ 0x4c2c0, 0x4c374,
+ 0x4c380, 0x4c3ac,
+ 0x4c3b4, 0x4c3b8,
+ 0x4c3c0, 0x4c454,
+ 0x4c45c, 0x4c478,
+ 0x4c4c0, 0x4c574,
+ 0x4c580, 0x4c5ac,
+ 0x4c5b4, 0x4c5b8,
+ 0x4c5c0, 0x4c654,
+ 0x4c65c, 0x4c678,
+ 0x4c6c0, 0x4c774,
+ 0x4c780, 0x4c7ac,
+ 0x4c7b4, 0x4c7b8,
+ 0x4c7c0, 0x4c854,
+ 0x4c85c, 0x4c878,
+ 0x4c8c0, 0x4c974,
+ 0x4c980, 0x4c9ac,
+ 0x4c9b4, 0x4c9b8,
+ 0x4c9c0, 0x4c9fc,
+ 0x4d000, 0x4d004,
+ 0x4d010, 0x4d030,
+ 0x4d040, 0x4d060,
+ 0x4d068, 0x4d068,
0x4d080, 0x4d084,
0x4d0a0, 0x4d0b0,
- 0x4d200, 0x4d268,
+ 0x4d200, 0x4d204,
+ 0x4d210, 0x4d230,
+ 0x4d240, 0x4d260,
+ 0x4d268, 0x4d268,
0x4d280, 0x4d284,
0x4d2a0, 0x4d2b0,
0x4e0c0, 0x4e0e4,
- 0x4f000, 0x4f08c,
+ 0x4f000, 0x4f03c,
+ 0x4f044, 0x4f08c,
0x4f200, 0x4f250,
- 0x4f400, 0x4f420,
+ 0x4f400, 0x4f408,
+ 0x4f414, 0x4f420,
0x4f600, 0x4f618,
0x4f800, 0x4f814,
- 0x50000, 0x500cc,
+ 0x50000, 0x50084,
+ 0x50090, 0x500cc,
0x50400, 0x50400,
- 0x50800, 0x508cc,
+ 0x50800, 0x50884,
+ 0x50890, 0x508cc,
0x50c00, 0x50c00,
0x51000, 0x5101c,
0x51300, 0x51308,
};
static const unsigned int t6_reg_ranges[] = {
- 0x1008, 0x1124,
- 0x1138, 0x114c,
- 0x1180, 0x11b4,
+ 0x1008, 0x101c,
+ 0x1024, 0x10a8,
+ 0x10b4, 0x10f8,
+ 0x1100, 0x1114,
+ 0x111c, 0x112c,
+ 0x1138, 0x113c,
+ 0x1144, 0x114c,
+ 0x1180, 0x1184,
+ 0x1190, 0x1194,
+ 0x11a0, 0x11a4,
+ 0x11b0, 0x11b4,
0x11fc, 0x1254,
0x1280, 0x133c,
0x1800, 0x18fc,
0x3000, 0x302c,
- 0x3060, 0x30d8,
+ 0x3060, 0x30b0,
+ 0x30b8, 0x30d8,
0x30e0, 0x30fc,
0x3140, 0x357c,
0x35a8, 0x35cc,
0x35ec, 0x35ec,
0x3600, 0x5624,
- 0x56cc, 0x575c,
+ 0x56cc, 0x56ec,
+ 0x56f4, 0x5720,
+ 0x5728, 0x575c,
0x580c, 0x5814,
- 0x5890, 0x58bc,
+ 0x5890, 0x589c,
+ 0x58a4, 0x58ac,
+ 0x58b8, 0x58bc,
0x5940, 0x595c,
0x5980, 0x598c,
- 0x59b0, 0x59dc,
+ 0x59b0, 0x59c8,
+ 0x59d0, 0x59dc,
0x59fc, 0x5a18,
0x5a60, 0x5a6c,
- 0x5a80, 0x5a9c,
+ 0x5a80, 0x5a8c,
+ 0x5a94, 0x5a9c,
0x5b94, 0x5bfc,
- 0x5c10, 0x5ec0,
+ 0x5c10, 0x5e48,
+ 0x5e50, 0x5e94,
+ 0x5ea0, 0x5eb0,
+ 0x5ec0, 0x5ec0,
0x5ec8, 0x5ecc,
- 0x6000, 0x6040,
- 0x6058, 0x619c,
+ 0x6000, 0x6020,
+ 0x6028, 0x6040,
+ 0x6058, 0x609c,
+ 0x60a8, 0x619c,
0x7700, 0x7798,
0x77c0, 0x7880,
0x78cc, 0x78fc,
- 0x7b00, 0x7c54,
- 0x7d00, 0x7efc,
+ 0x7b00, 0x7b58,
+ 0x7b60, 0x7b84,
+ 0x7b8c, 0x7c54,
+ 0x7d00, 0x7d38,
+ 0x7d40, 0x7d84,
+ 0x7d8c, 0x7ddc,
+ 0x7de4, 0x7e04,
+ 0x7e10, 0x7e1c,
+ 0x7e24, 0x7e38,
+ 0x7e40, 0x7e44,
+ 0x7e4c, 0x7e78,
+ 0x7e80, 0x7edc,
+ 0x7ee8, 0x7efc,
0x8dc0, 0x8de4,
- 0x8df8, 0x8e84,
+ 0x8df8, 0x8e04,
+ 0x8e10, 0x8e84,
0x8ea0, 0x8f88,
- 0x8fb8, 0x9124,
+ 0x8fb8, 0x9058,
+ 0x9060, 0x9060,
+ 0x9068, 0x90f8,
+ 0x9100, 0x9124,
0x9400, 0x9470,
- 0x9600, 0x971c,
+ 0x9600, 0x9600,
+ 0x9608, 0x9638,
+ 0x9640, 0x9704,
+ 0x9710, 0x971c,
0x9800, 0x9808,
0x9820, 0x983c,
0x9850, 0x9864,
@@ -1411,109 +2020,170 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x9f80, 0xa020,
0xd004, 0xd03c,
0xd100, 0xd118,
- 0xd200, 0xd31c,
+ 0xd200, 0xd214,
+ 0xd220, 0xd234,
+ 0xd240, 0xd254,
+ 0xd260, 0xd274,
+ 0xd280, 0xd294,
+ 0xd2a0, 0xd2b4,
+ 0xd2c0, 0xd2d4,
+ 0xd2e0, 0xd2f4,
+ 0xd300, 0xd31c,
0xdfc0, 0xdfe0,
0xe000, 0xf008,
0x11000, 0x11014,
- 0x11048, 0x1117c,
- 0x11190, 0x11270,
+ 0x11048, 0x1106c,
+ 0x11074, 0x11088,
+ 0x11098, 0x11120,
+ 0x1112c, 0x1117c,
+ 0x11190, 0x112e0,
0x11300, 0x1130c,
0x12000, 0x1206c,
0x19040, 0x1906c,
0x19078, 0x19080,
- 0x1908c, 0x19124,
- 0x19150, 0x191b0,
+ 0x1908c, 0x190e8,
+ 0x190f0, 0x190f8,
+ 0x19100, 0x19110,
+ 0x19120, 0x19124,
+ 0x19150, 0x19194,
+ 0x1919c, 0x191b0,
0x191d0, 0x191e8,
- 0x19238, 0x192bc,
- 0x193f8, 0x19474,
+ 0x19238, 0x192b0,
+ 0x192bc, 0x192bc,
+ 0x19348, 0x1934c,
+ 0x193f8, 0x19418,
+ 0x19420, 0x19428,
+ 0x19430, 0x19444,
+ 0x1944c, 0x1946c,
+ 0x19474, 0x19474,
0x19490, 0x194cc,
0x194f0, 0x194f8,
- 0x19c00, 0x19c80,
- 0x19c94, 0x19cbc,
- 0x19ce4, 0x19d28,
+ 0x19c00, 0x19c48,
+ 0x19c50, 0x19c80,
+ 0x19c94, 0x19c98,
+ 0x19ca0, 0x19cbc,
+ 0x19ce4, 0x19ce4,
+ 0x19cf0, 0x19cf8,
+ 0x19d00, 0x19d28,
0x19d50, 0x19d78,
- 0x19d94, 0x19dc8,
+ 0x19d94, 0x19d98,
+ 0x19da0, 0x19dc8,
0x19df0, 0x19e10,
0x19e50, 0x19e6c,
- 0x19ea0, 0x19f34,
+ 0x19ea0, 0x19ebc,
+ 0x19ec4, 0x19ef4,
+ 0x19f04, 0x19f2c,
+ 0x19f34, 0x19f34,
0x19f40, 0x19f50,
0x19f90, 0x19fac,
- 0x19fc4, 0x19fe4,
- 0x1a000, 0x1a06c,
- 0x1a0b0, 0x1a120,
- 0x1a128, 0x1a138,
+ 0x19fc4, 0x19fc8,
+ 0x19fd0, 0x19fe4,
+ 0x1a000, 0x1a004,
+ 0x1a010, 0x1a06c,
+ 0x1a0b0, 0x1a0e4,
+ 0x1a0ec, 0x1a0f8,
+ 0x1a100, 0x1a108,
+ 0x1a114, 0x1a120,
+ 0x1a128, 0x1a130,
+ 0x1a138, 0x1a138,
0x1a190, 0x1a1c4,
0x1a1fc, 0x1a1fc,
0x1e008, 0x1e00c,
- 0x1e040, 0x1e04c,
+ 0x1e040, 0x1e044,
+ 0x1e04c, 0x1e04c,
0x1e284, 0x1e290,
0x1e2c0, 0x1e2c0,
0x1e2e0, 0x1e2e0,
0x1e300, 0x1e384,
0x1e3c0, 0x1e3c8,
0x1e408, 0x1e40c,
- 0x1e440, 0x1e44c,
+ 0x1e440, 0x1e444,
+ 0x1e44c, 0x1e44c,
0x1e684, 0x1e690,
0x1e6c0, 0x1e6c0,
0x1e6e0, 0x1e6e0,
0x1e700, 0x1e784,
0x1e7c0, 0x1e7c8,
0x1e808, 0x1e80c,
- 0x1e840, 0x1e84c,
+ 0x1e840, 0x1e844,
+ 0x1e84c, 0x1e84c,
0x1ea84, 0x1ea90,
0x1eac0, 0x1eac0,
0x1eae0, 0x1eae0,
0x1eb00, 0x1eb84,
0x1ebc0, 0x1ebc8,
0x1ec08, 0x1ec0c,
- 0x1ec40, 0x1ec4c,
+ 0x1ec40, 0x1ec44,
+ 0x1ec4c, 0x1ec4c,
0x1ee84, 0x1ee90,
0x1eec0, 0x1eec0,
0x1eee0, 0x1eee0,
0x1ef00, 0x1ef84,
0x1efc0, 0x1efc8,
0x1f008, 0x1f00c,
- 0x1f040, 0x1f04c,
+ 0x1f040, 0x1f044,
+ 0x1f04c, 0x1f04c,
0x1f284, 0x1f290,
0x1f2c0, 0x1f2c0,
0x1f2e0, 0x1f2e0,
0x1f300, 0x1f384,
0x1f3c0, 0x1f3c8,
0x1f408, 0x1f40c,
- 0x1f440, 0x1f44c,
+ 0x1f440, 0x1f444,
+ 0x1f44c, 0x1f44c,
0x1f684, 0x1f690,
0x1f6c0, 0x1f6c0,
0x1f6e0, 0x1f6e0,
0x1f700, 0x1f784,
0x1f7c0, 0x1f7c8,
0x1f808, 0x1f80c,
- 0x1f840, 0x1f84c,
+ 0x1f840, 0x1f844,
+ 0x1f84c, 0x1f84c,
0x1fa84, 0x1fa90,
0x1fac0, 0x1fac0,
0x1fae0, 0x1fae0,
0x1fb00, 0x1fb84,
0x1fbc0, 0x1fbc8,
0x1fc08, 0x1fc0c,
- 0x1fc40, 0x1fc4c,
+ 0x1fc40, 0x1fc44,
+ 0x1fc4c, 0x1fc4c,
0x1fe84, 0x1fe90,
0x1fec0, 0x1fec0,
0x1fee0, 0x1fee0,
0x1ff00, 0x1ff84,
0x1ffc0, 0x1ffc8,
- 0x30000, 0x30070,
- 0x30100, 0x301d0,
+ 0x30000, 0x30030,
+ 0x30038, 0x30038,
+ 0x30040, 0x30040,
+ 0x30048, 0x30048,
+ 0x30050, 0x30050,
+ 0x3005c, 0x30060,
+ 0x30068, 0x30068,
+ 0x30070, 0x30070,
+ 0x30100, 0x30168,
+ 0x30190, 0x301a0,
+ 0x301a8, 0x301b8,
+ 0x301c4, 0x301c8,
+ 0x301d0, 0x301d0,
0x30200, 0x30320,
- 0x30400, 0x3052c,
+ 0x30400, 0x304b4,
+ 0x304c0, 0x3052c,
0x30540, 0x3061c,
- 0x30800, 0x30890,
+ 0x30800, 0x308a0,
0x308c0, 0x30908,
0x30910, 0x309b8,
0x30a00, 0x30a04,
- 0x30a0c, 0x30a2c,
+ 0x30a0c, 0x30a14,
+ 0x30a1c, 0x30a2c,
0x30a44, 0x30a50,
- 0x30a74, 0x30c24,
- 0x30d00, 0x30d3c,
- 0x30d44, 0x30d7c,
+ 0x30a74, 0x30a74,
+ 0x30a7c, 0x30afc,
+ 0x30b08, 0x30c24,
+ 0x30d00, 0x30d14,
+ 0x30d1c, 0x30d3c,
+ 0x30d44, 0x30d4c,
+ 0x30d54, 0x30d74,
+ 0x30d7c, 0x30d7c,
0x30de0, 0x30de0,
0x30e00, 0x30ed4,
0x30f00, 0x30fa4,
@@ -1542,7 +2212,8 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x31bb0, 0x31bb4,
0x31bc8, 0x31bd4,
0x32140, 0x3218c,
- 0x321f0, 0x32200,
+ 0x321f0, 0x321f4,
+ 0x32200, 0x32200,
0x32218, 0x32218,
0x32400, 0x32400,
0x32408, 0x3241c,
@@ -1551,46 +2222,108 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x326a8, 0x326a8,
0x326ec, 0x326ec,
0x32a00, 0x32abc,
- 0x32b00, 0x32b78,
+ 0x32b00, 0x32b38,
+ 0x32b40, 0x32b58,
+ 0x32b60, 0x32b78,
0x32c00, 0x32c00,
0x32c08, 0x32c3c,
0x32e00, 0x32e2c,
0x32f00, 0x32f2c,
- 0x33000, 0x330ac,
- 0x330c0, 0x331ac,
- 0x331c0, 0x332c4,
- 0x332e4, 0x333c4,
- 0x333e4, 0x334ac,
- 0x334c0, 0x335ac,
- 0x335c0, 0x336c4,
- 0x336e4, 0x337c4,
+ 0x33000, 0x3302c,
+ 0x33034, 0x33050,
+ 0x33058, 0x33058,
+ 0x33060, 0x3308c,
+ 0x3309c, 0x330ac,
+ 0x330c0, 0x330c0,
+ 0x330c8, 0x330d0,
+ 0x330d8, 0x330e0,
+ 0x330ec, 0x3312c,
+ 0x33134, 0x33150,
+ 0x33158, 0x33158,
+ 0x33160, 0x3318c,
+ 0x3319c, 0x331ac,
+ 0x331c0, 0x331c0,
+ 0x331c8, 0x331d0,
+ 0x331d8, 0x331e0,
+ 0x331ec, 0x33290,
+ 0x33298, 0x332c4,
+ 0x332e4, 0x33390,
+ 0x33398, 0x333c4,
+ 0x333e4, 0x3342c,
+ 0x33434, 0x33450,
+ 0x33458, 0x33458,
+ 0x33460, 0x3348c,
+ 0x3349c, 0x334ac,
+ 0x334c0, 0x334c0,
+ 0x334c8, 0x334d0,
+ 0x334d8, 0x334e0,
+ 0x334ec, 0x3352c,
+ 0x33534, 0x33550,
+ 0x33558, 0x33558,
+ 0x33560, 0x3358c,
+ 0x3359c, 0x335ac,
+ 0x335c0, 0x335c0,
+ 0x335c8, 0x335d0,
+ 0x335d8, 0x335e0,
+ 0x335ec, 0x33690,
+ 0x33698, 0x336c4,
+ 0x336e4, 0x33790,
+ 0x33798, 0x337c4,
0x337e4, 0x337fc,
0x33814, 0x33814,
0x33854, 0x33868,
0x33880, 0x3388c,
0x338c0, 0x338d0,
0x338e8, 0x338ec,
- 0x33900, 0x339ac,
- 0x339c0, 0x33ac4,
+ 0x33900, 0x3392c,
+ 0x33934, 0x33950,
+ 0x33958, 0x33958,
+ 0x33960, 0x3398c,
+ 0x3399c, 0x339ac,
+ 0x339c0, 0x339c0,
+ 0x339c8, 0x339d0,
+ 0x339d8, 0x339e0,
+ 0x339ec, 0x33a90,
+ 0x33a98, 0x33ac4,
0x33ae4, 0x33b10,
- 0x33b24, 0x33b50,
+ 0x33b24, 0x33b28,
+ 0x33b38, 0x33b50,
0x33bf0, 0x33c10,
- 0x33c24, 0x33c50,
+ 0x33c24, 0x33c28,
+ 0x33c38, 0x33c50,
0x33cf0, 0x33cfc,
- 0x34000, 0x34070,
- 0x34100, 0x341d0,
+ 0x34000, 0x34030,
+ 0x34038, 0x34038,
+ 0x34040, 0x34040,
+ 0x34048, 0x34048,
+ 0x34050, 0x34050,
+ 0x3405c, 0x34060,
+ 0x34068, 0x34068,
+ 0x34070, 0x34070,
+ 0x34100, 0x34168,
+ 0x34190, 0x341a0,
+ 0x341a8, 0x341b8,
+ 0x341c4, 0x341c8,
+ 0x341d0, 0x341d0,
0x34200, 0x34320,
- 0x34400, 0x3452c,
+ 0x34400, 0x344b4,
+ 0x344c0, 0x3452c,
0x34540, 0x3461c,
- 0x34800, 0x34890,
+ 0x34800, 0x348a0,
0x348c0, 0x34908,
0x34910, 0x349b8,
0x34a00, 0x34a04,
- 0x34a0c, 0x34a2c,
+ 0x34a0c, 0x34a14,
+ 0x34a1c, 0x34a2c,
0x34a44, 0x34a50,
- 0x34a74, 0x34c24,
- 0x34d00, 0x34d3c,
- 0x34d44, 0x34d7c,
+ 0x34a74, 0x34a74,
+ 0x34a7c, 0x34afc,
+ 0x34b08, 0x34c24,
+ 0x34d00, 0x34d14,
+ 0x34d1c, 0x34d3c,
+ 0x34d44, 0x34d4c,
+ 0x34d54, 0x34d74,
+ 0x34d7c, 0x34d7c,
0x34de0, 0x34de0,
0x34e00, 0x34ed4,
0x34f00, 0x34fa4,
@@ -1619,7 +2352,8 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x35bb0, 0x35bb4,
0x35bc8, 0x35bd4,
0x36140, 0x3618c,
- 0x361f0, 0x36200,
+ 0x361f0, 0x361f4,
+ 0x36200, 0x36200,
0x36218, 0x36218,
0x36400, 0x36400,
0x36408, 0x3641c,
@@ -1628,31 +2362,75 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x366a8, 0x366a8,
0x366ec, 0x366ec,
0x36a00, 0x36abc,
- 0x36b00, 0x36b78,
+ 0x36b00, 0x36b38,
+ 0x36b40, 0x36b58,
+ 0x36b60, 0x36b78,
0x36c00, 0x36c00,
0x36c08, 0x36c3c,
0x36e00, 0x36e2c,
0x36f00, 0x36f2c,
- 0x37000, 0x370ac,
- 0x370c0, 0x371ac,
- 0x371c0, 0x372c4,
- 0x372e4, 0x373c4,
- 0x373e4, 0x374ac,
- 0x374c0, 0x375ac,
- 0x375c0, 0x376c4,
- 0x376e4, 0x377c4,
+ 0x37000, 0x3702c,
+ 0x37034, 0x37050,
+ 0x37058, 0x37058,
+ 0x37060, 0x3708c,
+ 0x3709c, 0x370ac,
+ 0x370c0, 0x370c0,
+ 0x370c8, 0x370d0,
+ 0x370d8, 0x370e0,
+ 0x370ec, 0x3712c,
+ 0x37134, 0x37150,
+ 0x37158, 0x37158,
+ 0x37160, 0x3718c,
+ 0x3719c, 0x371ac,
+ 0x371c0, 0x371c0,
+ 0x371c8, 0x371d0,
+ 0x371d8, 0x371e0,
+ 0x371ec, 0x37290,
+ 0x37298, 0x372c4,
+ 0x372e4, 0x37390,
+ 0x37398, 0x373c4,
+ 0x373e4, 0x3742c,
+ 0x37434, 0x37450,
+ 0x37458, 0x37458,
+ 0x37460, 0x3748c,
+ 0x3749c, 0x374ac,
+ 0x374c0, 0x374c0,
+ 0x374c8, 0x374d0,
+ 0x374d8, 0x374e0,
+ 0x374ec, 0x3752c,
+ 0x37534, 0x37550,
+ 0x37558, 0x37558,
+ 0x37560, 0x3758c,
+ 0x3759c, 0x375ac,
+ 0x375c0, 0x375c0,
+ 0x375c8, 0x375d0,
+ 0x375d8, 0x375e0,
+ 0x375ec, 0x37690,
+ 0x37698, 0x376c4,
+ 0x376e4, 0x37790,
+ 0x37798, 0x377c4,
0x377e4, 0x377fc,
0x37814, 0x37814,
0x37854, 0x37868,
0x37880, 0x3788c,
0x378c0, 0x378d0,
0x378e8, 0x378ec,
- 0x37900, 0x379ac,
- 0x379c0, 0x37ac4,
+ 0x37900, 0x3792c,
+ 0x37934, 0x37950,
+ 0x37958, 0x37958,
+ 0x37960, 0x3798c,
+ 0x3799c, 0x379ac,
+ 0x379c0, 0x379c0,
+ 0x379c8, 0x379d0,
+ 0x379d8, 0x379e0,
+ 0x379ec, 0x37a90,
+ 0x37a98, 0x37ac4,
0x37ae4, 0x37b10,
- 0x37b24, 0x37b50,
+ 0x37b24, 0x37b28,
+ 0x37b38, 0x37b50,
0x37bf0, 0x37c10,
- 0x37c24, 0x37c50,
+ 0x37c24, 0x37c28,
+ 0x37c38, 0x37c50,
0x37cf0, 0x37cfc,
0x40040, 0x40040,
0x40080, 0x40084,
@@ -1664,36 +2442,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
0x40280, 0x40280,
0x40304, 0x40304,
0x40330, 0x4033c,
- 0x41304, 0x413dc,
- 0x41400, 0x4141c,
+ 0x41304, 0x413c8,
+ 0x413d0, 0x413dc,
+ 0x413f0, 0x413f0,
+ 0x41400, 0x4140c,
+ 0x41414, 0x4141c,
0x41480, 0x414d0,
0x44000, 0x4407c,
- 0x440c0, 0x4427c,
- 0x442c0, 0x4447c,
- 0x444c0, 0x4467c,
- 0x446c0, 0x4487c,
- 0x448c0, 0x44a7c,
- 0x44ac0, 0x44c7c,
- 0x44cc0, 0x44e7c,
- 0x44ec0, 0x4507c,
- 0x450c0, 0x451fc,
- 0x45800, 0x45868,
+ 0x440c0, 0x441ac,
+ 0x441b4, 0x4427c,
+ 0x442c0, 0x443ac,
+ 0x443b4, 0x4447c,
+ 0x444c0, 0x445ac,
+ 0x445b4, 0x4467c,
+ 0x446c0, 0x447ac,
+ 0x447b4, 0x4487c,
+ 0x448c0, 0x449ac,
+ 0x449b4, 0x44a7c,
+ 0x44ac0, 0x44bac,
+ 0x44bb4, 0x44c7c,
+ 0x44cc0, 0x44dac,
+ 0x44db4, 0x44e7c,
+ 0x44ec0, 0x44fac,
+ 0x44fb4, 0x4507c,
+ 0x450c0, 0x451ac,
+ 0x451b4, 0x451fc,
+ 0x45800, 0x45804,
+ 0x45810, 0x45830,
+ 0x45840, 0x45860,
+ 0x45868, 0x45868,
0x45880, 0x45884,
0x458a0, 0x458b0,
- 0x45a00, 0x45a68,
+ 0x45a00, 0x45a04,
+ 0x45a10, 0x45a30,
+ 0x45a40, 0x45a60,
+ 0x45a68, 0x45a68,
0x45a80, 0x45a84,
0x45aa0, 0x45ab0,
0x460c0, 0x460e4,
- 0x47000, 0x4708c,
+ 0x47000, 0x4703c,
+ 0x47044, 0x4708c,
0x47200, 0x47250,
- 0x47400, 0x47420,
+ 0x47400, 0x47408,
+ 0x47414, 0x47420,
0x47600, 0x47618,
- 0x47800, 0x4782c,
- 0x50000, 0x500cc,
+ 0x47800, 0x47814,
+ 0x47820, 0x4782c,
+ 0x50000, 0x50084,
+ 0x50090, 0x500cc,
+ 0x50300, 0x50384,
0x50400, 0x50400,
- 0x50800, 0x508cc,
+ 0x50800, 0x50884,
+ 0x50890, 0x508cc,
+ 0x50b00, 0x50b84,
0x50c00, 0x50c00,
- 0x51000, 0x510b0,
+ 0x51000, 0x51020,
+ 0x51028, 0x510b0,
0x51300, 0x51324,
};
@@ -2177,11 +2981,15 @@ int t4_get_exprom_version(struct adapter *adap, u32 *vers)
*/
int t4_check_fw_version(struct adapter *adap)
{
- int ret, major, minor, micro;
+ int i, ret, major, minor, micro;
int exp_major, exp_minor, exp_micro;
unsigned int chip_version = CHELSIO_CHIP_VERSION(adap->params.chip);
ret = t4_get_fw_version(adap, &adap->params.fw_vers);
+ /* Try multiple times before returning error */
+ for (i = 0; (ret == -EBUSY || ret == -EAGAIN) && i < 3; i++)
+ ret = t4_get_fw_version(adap, &adap->params.fw_vers);
+
if (ret)
return ret;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index 640369df8b3a..13708fde1668 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -263,4 +263,9 @@ enum {
#undef FLASH_START
#undef FLASH_MAX_SIZE
+#define SGE_TIMESTAMP_S 0
+#define SGE_TIMESTAMP_M 0xfffffffffffffffULL
+#define SGE_TIMESTAMP_V(x) ((__u64)(x) << SGE_TIMESTAMP_S)
+#define SGE_TIMESTAMP_G(x) (((__u64)(x) >> SGE_TIMESTAMP_S) & SGE_TIMESTAMP_M)
+
#endif /* __T4_HW_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index b99144afd4ec..a072d341e205 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -417,6 +417,21 @@ struct cpl_t5_act_open_req {
__be64 params;
};
+struct cpl_t6_act_open_req {
+ WR_HDR;
+ union opcode_tid ot;
+ __be16 local_port;
+ __be16 peer_port;
+ __be32 local_ip;
+ __be32 peer_ip;
+ __be64 opt0;
+ __be32 rsvd;
+ __be32 opt2;
+ __be64 params;
+ __be32 rsvd2;
+ __be32 opt3;
+};
+
struct cpl_act_open_req6 {
WR_HDR;
union opcode_tid ot;
@@ -446,6 +461,23 @@ struct cpl_t5_act_open_req6 {
__be64 params;
};
+struct cpl_t6_act_open_req6 {
+ WR_HDR;
+ union opcode_tid ot;
+ __be16 local_port;
+ __be16 peer_port;
+ __be64 local_ip_hi;
+ __be64 local_ip_lo;
+ __be64 peer_ip_hi;
+ __be64 peer_ip_lo;
+ __be64 opt0;
+ __be32 rsvd;
+ __be32 opt2;
+ __be64 params;
+ __be32 rsvd2;
+ __be32 opt3;
+};
+
struct cpl_act_open_rpl {
union opcode_tid ot;
__be32 atid_status;
@@ -504,6 +536,19 @@ struct cpl_pass_establish {
#define TCPOPT_MSS_M 0xF
#define TCPOPT_MSS_G(x) (((x) >> TCPOPT_MSS_S) & TCPOPT_MSS_M)
+#define T6_TCP_HDR_LEN_S 8
+#define T6_TCP_HDR_LEN_V(x) ((x) << T6_TCP_HDR_LEN_S)
+#define T6_TCP_HDR_LEN_G(x) (((x) >> T6_TCP_HDR_LEN_S) & TCP_HDR_LEN_M)
+
+#define T6_IP_HDR_LEN_S 14
+#define T6_IP_HDR_LEN_V(x) ((x) << T6_IP_HDR_LEN_S)
+#define T6_IP_HDR_LEN_G(x) (((x) >> T6_IP_HDR_LEN_S) & IP_HDR_LEN_M)
+
+#define T6_ETH_HDR_LEN_S 24
+#define T6_ETH_HDR_LEN_M 0xFF
+#define T6_ETH_HDR_LEN_V(x) ((x) << T6_ETH_HDR_LEN_S)
+#define T6_ETH_HDR_LEN_G(x) (((x) >> T6_ETH_HDR_LEN_S) & T6_ETH_HDR_LEN_M)
+
struct cpl_act_establish {
union opcode_tid ot;
__be32 rsvd;
@@ -833,6 +878,9 @@ struct cpl_rx_pkt {
__be16 err_vec;
};
+#define RX_T6_ETHHDR_LEN_M 0xFF
+#define RX_T6_ETHHDR_LEN_G(x) (((x) >> RX_ETHHDR_LEN_S) & RX_T6_ETHHDR_LEN_M)
+
#define RXF_PSH_S 20
#define RXF_PSH_V(x) ((x) << RXF_PSH_S)
#define RXF_PSH_F RXF_PSH_V(1U)
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index b2b5e5bbe04c..0cfa5d72cafd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -56,7 +56,7 @@
* Generic information about the driver.
*/
#define DRV_VERSION "2.0.0-ko"
-#define DRV_DESC "Chelsio T4/T5 Virtual Function (VF) Network Driver"
+#define DRV_DESC "Chelsio T4/T5/T6 Virtual Function (VF) Network Driver"
/*
* Module Parameters.
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 8b53f7d4bebf..1671fa3332c2 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -50,6 +50,7 @@ struct enic_msix_entry {
char devname[IFNAMSIZ];
irqreturn_t (*isr)(int, void *);
void *devid;
+ cpumask_var_t affinity_mask;
};
/* Store only the lower range. Higher range is given by fw. */
@@ -143,6 +144,7 @@ struct enic {
struct vnic_dev *vdev;
struct timer_list notify_timer;
struct work_struct reset;
+ struct work_struct tx_hang_reset;
struct work_struct change_mtu_work;
struct msix_entry msix_entry[ENIC_INTR_MAX];
struct enic_msix_entry msix[ENIC_INTR_MAX];
@@ -262,6 +264,32 @@ static inline unsigned int enic_msix_notify_intr(struct enic *enic)
return enic->rq_count + enic->wq_count + 1;
}
+static inline bool enic_is_err_intr(struct enic *enic, int intr)
+{
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ return intr == enic_legacy_err_intr();
+ case VNIC_DEV_INTR_MODE_MSIX:
+ return intr == enic_msix_err_intr(enic);
+ case VNIC_DEV_INTR_MODE_MSI:
+ default:
+ return false;
+ }
+}
+
+static inline bool enic_is_notify_intr(struct enic *enic, int intr)
+{
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ return intr == enic_legacy_notify_intr();
+ case VNIC_DEV_INTR_MODE_MSIX:
+ return intr == enic_msix_notify_intr(enic);
+ case VNIC_DEV_INTR_MODE_MSI:
+ default:
+ return false;
+ }
+}
+
static inline int enic_dma_map_check(struct enic *enic, dma_addr_t dma_addr)
{
if (unlikely(pci_dma_mapping_error(enic->pdev, dma_addr))) {
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 3352d027ab89..b36643ef0593 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -39,6 +39,7 @@
#include <linux/prefetch.h>
#include <net/ip6_checksum.h>
#include <linux/ktime.h>
+#include <linux/numa.h>
#ifdef CONFIG_RFS_ACCEL
#include <linux/cpu_rmap.h>
#endif
@@ -112,6 +113,71 @@ static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
{3, 6}, /* 10 - 40 Gbps */
};
+static void enic_init_affinity_hint(struct enic *enic)
+{
+ int numa_node = dev_to_node(&enic->pdev->dev);
+ int i;
+
+ for (i = 0; i < enic->intr_count; i++) {
+ if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i) ||
+ (enic->msix[i].affinity_mask &&
+ !cpumask_empty(enic->msix[i].affinity_mask)))
+ continue;
+ if (zalloc_cpumask_var(&enic->msix[i].affinity_mask,
+ GFP_KERNEL))
+ cpumask_set_cpu(cpumask_local_spread(i, numa_node),
+ enic->msix[i].affinity_mask);
+ }
+}
+
+static void enic_free_affinity_hint(struct enic *enic)
+{
+ int i;
+
+ for (i = 0; i < enic->intr_count; i++) {
+ if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i))
+ continue;
+ free_cpumask_var(enic->msix[i].affinity_mask);
+ }
+}
+
+static void enic_set_affinity_hint(struct enic *enic)
+{
+ int i;
+ int err;
+
+ for (i = 0; i < enic->intr_count; i++) {
+ if (enic_is_err_intr(enic, i) ||
+ enic_is_notify_intr(enic, i) ||
+ !enic->msix[i].affinity_mask ||
+ cpumask_empty(enic->msix[i].affinity_mask))
+ continue;
+ err = irq_set_affinity_hint(enic->msix_entry[i].vector,
+ enic->msix[i].affinity_mask);
+ if (err)
+ netdev_warn(enic->netdev, "irq_set_affinity_hint failed, err %d\n",
+ err);
+ }
+
+ for (i = 0; i < enic->wq_count; i++) {
+ int wq_intr = enic_msix_wq_intr(enic, i);
+
+ if (enic->msix[wq_intr].affinity_mask &&
+ !cpumask_empty(enic->msix[wq_intr].affinity_mask))
+ netif_set_xps_queue(enic->netdev,
+ enic->msix[wq_intr].affinity_mask,
+ i);
+ }
+}
+
+static void enic_unset_affinity_hint(struct enic *enic)
+{
+ int i;
+
+ for (i = 0; i < enic->intr_count; i++)
+ irq_set_affinity_hint(enic->msix_entry[i].vector, NULL);
+}
+
int enic_is_dynamic(struct enic *enic)
{
return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
@@ -178,13 +244,15 @@ static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
return 0;
}
-static void enic_log_q_error(struct enic *enic)
+static bool enic_log_q_error(struct enic *enic)
{
unsigned int i;
u32 error_status;
+ bool err = false;
for (i = 0; i < enic->wq_count; i++) {
error_status = vnic_wq_error_status(&enic->wq[i]);
+ err |= error_status;
if (error_status)
netdev_err(enic->netdev, "WQ[%d] error_status %d\n",
i, error_status);
@@ -192,10 +260,13 @@ static void enic_log_q_error(struct enic *enic)
for (i = 0; i < enic->rq_count; i++) {
error_status = vnic_rq_error_status(&enic->rq[i]);
+ err |= error_status;
if (error_status)
netdev_err(enic->netdev, "RQ[%d] error_status %d\n",
i, error_status);
}
+
+ return err;
}
static void enic_msglvl_check(struct enic *enic)
@@ -333,10 +404,9 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data)
vnic_intr_return_all_credits(&enic->intr[intr]);
- enic_log_q_error(enic);
-
- /* schedule recovery from WQ/RQ error */
- schedule_work(&enic->reset);
+ if (enic_log_q_error(enic))
+ /* schedule recovery from WQ/RQ error */
+ schedule_work(&enic->reset);
return IRQ_HANDLED;
}
@@ -804,7 +874,7 @@ static void enic_set_rx_mode(struct net_device *netdev)
static void enic_tx_timeout(struct net_device *netdev)
{
struct enic *enic = netdev_priv(netdev);
- schedule_work(&enic->reset);
+ schedule_work(&enic->tx_hang_reset);
}
static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
@@ -1645,6 +1715,8 @@ static int enic_open(struct net_device *netdev)
netdev_err(netdev, "Unable to request irq.\n");
return err;
}
+ enic_init_affinity_hint(enic);
+ enic_set_affinity_hint(enic);
err = enic_dev_notify_set(enic);
if (err) {
@@ -1697,6 +1769,7 @@ err_out_free_rq:
vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
enic_dev_notify_unset(enic);
err_out_free_intr:
+ enic_unset_affinity_hint(enic);
enic_free_intr(enic);
return err;
@@ -1750,6 +1823,7 @@ static int enic_stop(struct net_device *netdev)
}
enic_dev_notify_unset(enic);
+ enic_unset_affinity_hint(enic);
enic_free_intr(enic);
for (i = 0; i < enic->wq_count; i++)
@@ -1924,6 +1998,19 @@ static int enic_dev_open(struct enic *enic)
return err;
}
+static int enic_dev_soft_reset(struct enic *enic)
+{
+ int err;
+
+ err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset,
+ vnic_dev_soft_reset_done, 0);
+ if (err)
+ netdev_err(enic->netdev, "vNIC soft reset failed, err %d\n",
+ err);
+
+ return err;
+}
+
static int enic_dev_hang_reset(struct enic *enic)
{
int err;
@@ -2060,6 +2147,26 @@ static void enic_reset(struct work_struct *work)
rtnl_lock();
spin_lock(&enic->enic_api_lock);
+ enic_stop(enic->netdev);
+ enic_dev_soft_reset(enic);
+ enic_reset_addr_lists(enic);
+ enic_init_vnic_resources(enic);
+ enic_set_rss_nic_cfg(enic);
+ enic_dev_set_ig_vlan_rewrite_mode(enic);
+ enic_open(enic->netdev);
+ spin_unlock(&enic->enic_api_lock);
+ call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
+
+ rtnl_unlock();
+}
+
+static void enic_tx_hang_reset(struct work_struct *work)
+{
+ struct enic *enic = container_of(work, struct enic, tx_hang_reset);
+
+ rtnl_lock();
+
+ spin_lock(&enic->enic_api_lock);
enic_dev_hang_notify(enic);
enic_stop(enic->netdev);
enic_dev_hang_reset(enic);
@@ -2272,6 +2379,7 @@ static void enic_dev_deinit(struct enic *enic)
enic_free_vnic_resources(enic);
enic_clear_intr_mode(enic);
+ enic_free_affinity_hint(enic);
}
static void enic_kdump_kernel_config(struct enic *enic)
@@ -2367,6 +2475,7 @@ static int enic_dev_init(struct enic *enic)
return 0;
err_out_free_vnic_resources:
+ enic_free_affinity_hint(enic);
enic_clear_intr_mode(enic);
enic_free_vnic_resources(enic);
@@ -2583,6 +2692,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
enic_set_rx_coal_setting(enic);
INIT_WORK(&enic->reset, enic_reset);
+ INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
for (i = 0; i < enic->wq_count; i++)
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index a3badefaf360..1ffd1050860b 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -659,14 +659,14 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
return 0;
}
-static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
+int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
{
u64 a0 = (u32)arg, a1 = 0;
int wait = 1000;
return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
}
-static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
+int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index b013b6a78e87..54156c484424 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -155,7 +155,9 @@ int vnic_dev_deinit(struct vnic_dev *vdev);
void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev);
int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev);
int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
+int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
+int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
enum vnic_dev_intr_mode intr_mode);
enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index a02ecc4f9002..cadcee645f74 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -1597,7 +1597,6 @@ static void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info)
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->bus_info, pci_name(de->pdev), sizeof(info->bus_info));
- info->eedump_len = DE_EEPROM_SIZE;
}
static int de_get_regs_len(struct net_device *dev)
diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig
index f6e858d0b9d4..ebdc83247bb6 100644
--- a/drivers/net/ethernet/dlink/Kconfig
+++ b/drivers/net/ethernet/dlink/Kconfig
@@ -17,15 +17,16 @@ config NET_VENDOR_DLINK
if NET_VENDOR_DLINK
config DL2K
- tristate "DL2000/TC902x-based Gigabit Ethernet support"
+ tristate "DL2000/TC902x/IP1000A-based Gigabit Ethernet support"
depends on PCI
select CRC32
---help---
- This driver supports DL2000/TC902x-based Gigabit ethernet cards,
+ This driver supports DL2000/TC902x/IP1000A-based Gigabit ethernet cards,
which includes
D-Link DGE-550T Gigabit Ethernet Adapter.
D-Link DL2000-based Gigabit Ethernet Adapter.
Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
+ ICPlus IP1000A-based cards
To compile this driver as a module, choose M here: the
module will be called dl2k.
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index cf0a5fcdaaaf..ccca4799c27b 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -253,6 +253,19 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_out_unmap_rx;
+ if (np->chip_id == CHIP_IP1000A &&
+ (np->pdev->revision == 0x40 || np->pdev->revision == 0x41)) {
+ /* PHY magic taken from ipg driver, undocumented registers */
+ mii_write(dev, np->phy_addr, 31, 0x0001);
+ mii_write(dev, np->phy_addr, 27, 0x01e0);
+ mii_write(dev, np->phy_addr, 31, 0x0002);
+ mii_write(dev, np->phy_addr, 27, 0xeb8e);
+ mii_write(dev, np->phy_addr, 31, 0x0000);
+ mii_write(dev, np->phy_addr, 30, 0x005e);
+ /* advertise 1000BASE-T half & full duplex, prefer MASTER */
+ mii_write(dev, np->phy_addr, MII_CTRL1000, 0x0700);
+ }
+
/* Fiber device? */
np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0;
np->link_status = 0;
@@ -361,6 +374,11 @@ parse_eeprom (struct net_device *dev)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = psrom->mac_addr[i];
+ if (np->chip_id == CHIP_IP1000A) {
+ np->led_mode = psrom->led_mode;
+ return 0;
+ }
+
if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) {
return 0;
}
@@ -406,6 +424,28 @@ parse_eeprom (struct net_device *dev)
return 0;
}
+static void rio_set_led_mode(struct net_device *dev)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
+ u32 mode;
+
+ if (np->chip_id != CHIP_IP1000A)
+ return;
+
+ mode = dr32(ASICCtrl);
+ mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED);
+
+ if (np->led_mode & 0x01)
+ mode |= IPG_AC_LED_MODE;
+ if (np->led_mode & 0x02)
+ mode |= IPG_AC_LED_MODE_BIT_1;
+ if (np->led_mode & 0x08)
+ mode |= IPG_AC_LED_SPEED;
+
+ dw32(ASICCtrl, mode);
+}
+
static int
rio_open (struct net_device *dev)
{
@@ -424,6 +464,8 @@ rio_open (struct net_device *dev)
GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset);
mdelay(10);
+ rio_set_led_mode(dev);
+
/* DebugCtrl bit 4, 5, 9 must set */
dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230);
@@ -433,9 +475,13 @@ rio_open (struct net_device *dev)
alloc_list (dev);
- /* Get station address */
- for (i = 0; i < 6; i++)
- dw8(StationAddr0 + i, dev->dev_addr[i]);
+ /* Set station address */
+ /* 16 or 32-bit access is required by TC9020 datasheet but 8-bit works
+ * too. However, it doesn't work on IP1000A so we use 16-bit access.
+ */
+ for (i = 0; i < 3; i++)
+ dw16(StationAddr0 + 2 * i,
+ cpu_to_le16(((u16 *)dev->dev_addr)[i]));
set_multicast (dev);
if (np->coalesce) {
@@ -780,6 +826,7 @@ tx_error (struct net_device *dev, int tx_status)
break;
mdelay (1);
}
+ rio_set_led_mode(dev);
rio_free_tx (dev, 1);
/* Reset TFDListPtr */
dw32(TFDListPtr0, np->tx_ring_dma +
@@ -799,6 +846,7 @@ tx_error (struct net_device *dev, int tx_status)
break;
mdelay (1);
}
+ rio_set_led_mode(dev);
/* Let TxStartThresh stay default value */
}
/* Maximum Collisions */
@@ -965,6 +1013,7 @@ rio_error (struct net_device *dev, int int_status)
dev->name, int_status);
dw16(ASICCtrl + 2, GlobalReset | HostReset);
mdelay (500);
+ rio_set_led_mode(dev);
}
}
diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h
index 23c07b007069..8f4f61262d5c 100644
--- a/drivers/net/ethernet/dlink/dl2k.h
+++ b/drivers/net/ethernet/dlink/dl2k.h
@@ -211,6 +211,10 @@ enum ASICCtrl_HiWord_bits {
ResetBusy = 0x0400,
};
+#define IPG_AC_LED_MODE BIT(14)
+#define IPG_AC_LED_SPEED BIT(27)
+#define IPG_AC_LED_MODE_BIT_1 BIT(29)
+
/* Transmit Frame Control bits */
enum TFC_bits {
DwordAlign = 0x00000000,
@@ -332,7 +336,10 @@ typedef struct t_SROM {
u16 asic_ctrl; /* 0x02 */
u16 sub_vendor_id; /* 0x04 */
u16 sub_system_id; /* 0x06 */
- u16 reserved1[12]; /* 0x08-0x1f */
+ u16 pci_base_1; /* 0x08 (IP1000A only) */
+ u16 pci_base_2; /* 0x0a (IP1000A only) */
+ u16 led_mode; /* 0x0c (IP1000A only) */
+ u16 reserved1[9]; /* 0x0e-0x1f */
u8 mac_addr[6]; /* 0x20-0x25 */
u8 reserved2[10]; /* 0x26-0x2f */
u8 sib[204]; /* 0x30-0xfb */
@@ -397,6 +404,7 @@ struct netdev_private {
u16 advertising; /* NWay media advertisement */
u16 negotiate; /* Negotiated media */
int phy_addr; /* PHY addresses. */
+ u16 led_mode; /* LED mode read from EEPROM (IP1000A only) */
};
/* The station address location in the EEPROM. */
@@ -407,10 +415,15 @@ struct netdev_private {
class_mask of the class are honored during the comparison.
driver_data Data private to the driver.
*/
+#define CHIP_IP1000A 1
static const struct pci_device_id rio_pci_tbl[] = {
{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, },
{0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VDEVICE(SUNDANCE, 0x1023), CHIP_IP1000A },
+ { PCI_VDEVICE(SUNDANCE, 0x2021), CHIP_IP1000A },
+ { PCI_VDEVICE(DLINK, 0x9021), CHIP_IP1000A },
+ { PCI_VDEVICE(DLINK, 0x4020), CHIP_IP1000A },
{ }
};
MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 821540913343..d463563e1f70 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -592,6 +592,7 @@ struct be_adapter {
int be_get_temp_freq;
struct be_hwmon hwmon_info;
u8 pf_number;
+ u8 pci_func_num;
struct rss_info rss_info;
/* Filters for packets that need to be sent to BMC */
u32 bmc_filt_mask;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index eb323913cd39..1795c935ff02 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -851,8 +851,10 @@ static int be_cmd_notify_wait(struct be_adapter *adapter,
return status;
dest_wrb = be_cmd_copy(adapter, wrb);
- if (!dest_wrb)
- return -EBUSY;
+ if (!dest_wrb) {
+ status = -EBUSY;
+ goto unlock;
+ }
if (use_mcc(adapter))
status = be_mcc_notify_wait(adapter);
@@ -862,6 +864,7 @@ static int be_cmd_notify_wait(struct be_adapter *adapter,
if (!status)
memcpy(wrb, dest_wrb, sizeof(*wrb));
+unlock:
be_cmd_unlock(adapter);
return status;
}
@@ -1984,6 +1987,8 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
be_if_cap_flags(adapter));
}
flags &= be_if_cap_flags(adapter);
+ if (!flags)
+ return -ENOTSUPP;
return __be_cmd_rx_filter(adapter, flags, value);
}
@@ -2887,6 +2892,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
if (!status) {
attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
adapter->hba_port_num = attribs->hba_attribs.phy_port;
+ adapter->pci_func_num = attribs->pci_func_num;
serial_num = attribs->hba_attribs.controller_serial_number;
for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
@@ -3709,7 +3715,6 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
status = -EINVAL;
goto err;
}
-
adapter->pf_number = desc->pf_num;
be_copy_nic_desc(res, desc);
}
@@ -3721,7 +3726,10 @@ err:
return status;
}
-/* Will use MBOX only if MCCQ has not been created */
+/* Will use MBOX only if MCCQ has not been created
+ * non-zero domain => a PF is querying this on behalf of a VF
+ * zero domain => a PF or a VF is querying this for itself
+ */
int be_cmd_get_profile_config(struct be_adapter *adapter,
struct be_resources *res, u8 query, u8 domain)
{
@@ -3748,10 +3756,15 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
OPCODE_COMMON_GET_PROFILE_CONFIG,
cmd.size, &wrb, &cmd);
- req->hdr.domain = domain;
if (!lancer_chip(adapter))
req->hdr.version = 1;
req->type = ACTIVE_PROFILE_TYPE;
+ /* When a function is querying profile information relating to
+ * itself hdr.pf_number must be set to it's pci_func_num + 1
+ */
+ req->hdr.domain = domain;
+ if (domain == 0)
+ req->hdr.pf_num = adapter->pci_func_num + 1;
/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
* descriptors with all bits set to "1" for the fields which can be
@@ -3921,12 +3934,16 @@ static void be_fill_vf_res_template(struct be_adapter *adapter,
vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
BE_IF_FLAGS_DEFQ_RSS);
}
-
- nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
} else {
num_vf_qs = 1;
}
+ if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
+ nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
+ vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
+ }
+
+ nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
nic_vft->rq_count = cpu_to_le16(num_vf_qs);
nic_vft->txq_count = cpu_to_le16(num_vf_qs);
nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 7d178bdb112e..91155ea74f34 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -289,7 +289,9 @@ struct be_cmd_req_hdr {
u32 timeout; /* dword 1 */
u32 request_length; /* dword 2 */
u8 version; /* dword 3 */
- u8 rsvd[3]; /* dword 3 */
+ u8 rsvd1; /* dword 3 */
+ u8 pf_num; /* dword 3 */
+ u8 rsvd2; /* dword 3 */
};
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
@@ -1652,7 +1654,11 @@ struct mgmt_hba_attribs {
struct mgmt_controller_attrib {
struct mgmt_hba_attribs hba_attribs;
- u32 rsvd0[10];
+ u32 rsvd0[2];
+ u16 rsvd1;
+ u8 pci_func_num;
+ u8 rsvd2;
+ u32 rsvd3[7];
} __packed;
struct be_cmd_req_cntl_attribs {
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 2c9ed1710ba6..734f655c99c1 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -234,9 +234,6 @@ static void be_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->testinfo_len = 0;
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
}
static u32 lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name)
@@ -1065,9 +1062,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
static int be_set_rss_hash_opts(struct be_adapter *adapter,
struct ethtool_rxnfc *cmd)
{
- struct be_rx_obj *rxo;
- int status = 0, i, j;
- u8 rsstable[128];
+ int status;
u32 rss_flags = adapter->rss_info.rss_flags;
if (cmd->data != L3_RSS_FLAGS &&
@@ -1116,20 +1111,11 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter,
}
if (rss_flags == adapter->rss_info.rss_flags)
- return status;
-
- if (be_multi_rxq(adapter)) {
- for (j = 0; j < 128; j += adapter->num_rss_qs) {
- for_all_rss_queues(adapter, rxo, i) {
- if ((j + i) >= 128)
- break;
- rsstable[j + i] = rxo->rss_id;
- }
- }
- }
+ return 0;
status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable,
- rss_flags, 128, adapter->rss_info.rss_hkey);
+ rss_flags, RSS_INDIR_TABLE_LEN,
+ adapter->rss_info.rss_hkey);
if (!status)
adapter->rss_info.rss_flags = rss_flags;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 7bf51a1a0a77..b6ad02909d6b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1123,11 +1123,12 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
struct sk_buff *skb,
struct be_wrb_params *wrb_params)
{
- /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
- * less may cause a transmit stall on that port. So the work-around is
- * to pad short packets (<= 32 bytes) to a 36-byte length.
+ /* Lancer, SH and BE3 in SRIOV mode have a bug wherein
+ * packets that are 32b or less may cause a transmit stall
+ * on that port. The workaround is to pad such packets
+ * (len <= 32 bytes) to a minimum length of 36b.
*/
- if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
+ if (skb->len <= 32) {
if (skb_put_padto(skb, 36))
return NULL;
}
@@ -3517,7 +3518,7 @@ static int be_rx_qs_create(struct be_adapter *adapter)
netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN);
rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
- 128, rss_key);
+ RSS_INDIR_TABLE_LEN, rss_key);
if (rc) {
rss->rss_flags = RSS_ENABLE_NONE;
return rc;
@@ -4205,10 +4206,6 @@ static int be_get_config(struct be_adapter *adapter)
int status, level;
u16 profile_id;
- status = be_cmd_get_cntl_attributes(adapter);
- if (status)
- return status;
-
status = be_cmd_query_fw_cfg(adapter);
if (status)
return status;
@@ -4407,6 +4404,11 @@ static int be_setup(struct be_adapter *adapter)
if (!lancer_chip(adapter))
be_cmd_req_native_mode(adapter);
+ /* Need to invoke this cmd first to get the PCI Function Number */
+ status = be_cmd_get_cntl_attributes(adapter);
+ if (status)
+ return status;
+
if (!BE2_chip(adapter) && be_physfn(adapter))
be_alloc_sriov_res(adapter);
@@ -4999,7 +5001,15 @@ static bool be_check_ufi_compatibility(struct be_adapter *adapter,
return false;
}
- return (fhdr->asic_type_rev >= adapter->asic_rev);
+ /* In BE3 FW images the "asic_type_rev" field doesn't track the
+ * asic_rev of the chips it is compatible with.
+ * When asic_type_rev is 0 the image is compatible only with
+ * pre-BE3-R chips (asic_rev < 0x10)
+ */
+ if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
+ return adapter->asic_rev < 0x10;
+ else
+ return (fhdr->asic_type_rev >= adapter->asic_rev);
}
static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index a2c96fd88393..ff665493ca97 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -201,6 +201,7 @@ struct ethoc {
void __iomem *membase;
int dma_alloc;
resource_size_t io_region_size;
+ bool big_endian;
unsigned int num_bd;
unsigned int num_tx;
@@ -236,12 +237,18 @@ struct ethoc_bd {
static inline u32 ethoc_read(struct ethoc *dev, loff_t offset)
{
- return ioread32(dev->iobase + offset);
+ if (dev->big_endian)
+ return ioread32be(dev->iobase + offset);
+ else
+ return ioread32(dev->iobase + offset);
}
static inline void ethoc_write(struct ethoc *dev, loff_t offset, u32 data)
{
- iowrite32(data, dev->iobase + offset);
+ if (dev->big_endian)
+ iowrite32be(data, dev->iobase + offset);
+ else
+ iowrite32(data, dev->iobase + offset);
}
static inline void ethoc_read_bd(struct ethoc *dev, int index,
@@ -1106,6 +1113,9 @@ static int ethoc_probe(struct platform_device *pdev)
priv->dma_alloc = buffer_size;
}
+ priv->big_endian = pdata ? pdata->big_endian :
+ of_device_is_big_endian(pdev->dev.of_node);
+
/* calculate the number of TX/RX buffers, maximum 128 supported */
num_bd = min_t(unsigned int,
128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ);
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index dd4ca39d5d8f..b2a32209ffbf 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3070,7 +3070,6 @@ static void fec_poll_controller(struct net_device *dev)
}
#endif
-#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM
static inline void fec_enet_set_netdev_features(struct net_device *netdev,
netdev_features_t features)
{
@@ -3094,7 +3093,7 @@ static int fec_set_features(struct net_device *netdev,
struct fec_enet_private *fep = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
- if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
+ if (netif_running(netdev) && changed & NETIF_F_RXCSUM) {
napi_disable(&fep->napi);
netif_tx_lock_bh(netdev);
fec_stop(netdev);
@@ -3262,7 +3261,7 @@ static void fec_reset_phy(struct platform_device *pdev)
return;
}
msleep(msec);
- gpio_set_value(phy_reset, 1);
+ gpio_set_value_cansleep(phy_reset, 1);
}
#else /* CONFIG_OF */
static void fec_reset_phy(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 1543cf0e8ef6..f9e74461bdc0 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -112,9 +112,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
unsigned long flags;
u32 val, tempval;
int inc;
- struct timespec ts;
+ struct timespec64 ts;
u64 ns;
- u32 remainder;
val = 0;
if (!(fep->hwts_tx_en || fep->hwts_rx_en)) {
@@ -163,8 +162,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
tempval = readl(fep->hwp + FEC_ATIME);
/* Convert the ptp local counter to 1588 timestamp */
ns = timecounter_cyc2time(&fep->tc, tempval);
- ts.tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
- ts.tv_nsec = remainder;
+ ts = ns_to_timespec64(ns);
/* The tempval is less than 3 seconds, and so val is less than
* 4 seconds. No overflow for 32bit calculation.
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 3c40f6b99224..55c36230e176 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -198,11 +198,13 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
/*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MDIO registers (struct gfar)
* This is mildly evil, but so is our hardware for doing this.
* Also, we have to cast back to struct gfar because of
* definition weirdness done in gianfar.h.
*/
-static uint32_t __iomem *get_gfar_tbipa(void __iomem *p)
+static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p)
{
struct gfar __iomem *enet_regs = p;
@@ -210,6 +212,15 @@ static uint32_t __iomem *get_gfar_tbipa(void __iomem *p)
}
/*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MII registers (gfar_mii_regs[] within struct gfar)
+ */
+static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p)
+{
+ return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs));
+}
+
+/*
* Return the TBIPAR address for an eTSEC2 node
*/
static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
@@ -220,11 +231,12 @@ static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
/*
- * Return the TBIPAR address for a QE MDIO node
+ * Return the TBIPAR address for a QE MDIO node, starting from the address
+ * of the mapped MII registers (struct fsl_pq_mii)
*/
static uint32_t __iomem *get_ucc_tbipa(void __iomem *p)
{
- struct fsl_pq_mdio __iomem *mdio = p;
+ struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii);
return &mdio->utbipar;
}
@@ -300,14 +312,14 @@ static const struct of_device_id fsl_pq_mdio_match[] = {
.compatible = "fsl,gianfar-tbi",
.data = &(struct fsl_pq_mdio_data) {
.mii_offset = 0,
- .get_tbipa = get_gfar_tbipa,
+ .get_tbipa = get_gfar_tbipa_from_mii,
},
},
{
.compatible = "fsl,gianfar-mdio",
.data = &(struct fsl_pq_mdio_data) {
.mii_offset = 0,
- .get_tbipa = get_gfar_tbipa,
+ .get_tbipa = get_gfar_tbipa_from_mii,
},
},
{
@@ -315,7 +327,7 @@ static const struct of_device_id fsl_pq_mdio_match[] = {
.compatible = "gianfar",
.data = &(struct fsl_pq_mdio_data) {
.mii_offset = offsetof(struct fsl_pq_mdio, mii),
- .get_tbipa = get_gfar_tbipa,
+ .get_tbipa = get_gfar_tbipa_from_mdio,
},
},
{
@@ -445,6 +457,16 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
tbipa = data->get_tbipa(priv->map);
+ /*
+ * Add consistency check to make sure TBI is contained
+ * within the mapped range (not because we would get a
+ * segfault, rather to catch bugs in computing TBI
+ * address). Print error message but continue anyway.
+ */
+ if ((void *)tbipa > priv->map + resource_size(&res) - 4)
+ dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n",
+ ((void *)tbipa - priv->map) + 4);
+
iowrite32be(be32_to_cpup(prop), tbipa);
}
}
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 710715fcb23d..3e6b9b437497 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -107,7 +107,7 @@
#include "gianfar.h"
-#define TX_TIMEOUT (1*HZ)
+#define TX_TIMEOUT (5*HZ)
const char gfar_driver_version[] = "2.0";
@@ -341,7 +341,7 @@ static void gfar_rx_offload_en(struct gfar_private *priv)
if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
priv->uses_rxfcb = 1;
- if (priv->hwts_rx_en)
+ if (priv->hwts_rx_en || priv->rx_filer_enable)
priv->uses_rxfcb = 1;
}
@@ -351,7 +351,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv)
u32 rctrl = 0;
if (priv->rx_filer_enable) {
- rctrl |= RCTRL_FILREN;
+ rctrl |= RCTRL_FILREN | RCTRL_PRSDEP_INIT;
/* Program the RIR0 reg with the required distribution */
if (priv->poll_mode == GFAR_SQ_POLLING)
gfar_write(&regs->rir0, DEFAULT_2RXQ_RIR0);
@@ -907,6 +907,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
if (of_find_property(np, "fsl,magic-packet", NULL))
priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+ if (of_get_property(np, "fsl,wake-on-filer", NULL))
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER;
+
priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
/* In the case of a fixed PHY, the DT node associated
@@ -1415,8 +1418,14 @@ static int gfar_probe(struct platform_device *ofdev)
goto register_fail;
}
- device_set_wakeup_capable(&dev->dev, priv->device_flags &
- FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET)
+ priv->wol_supported |= GFAR_WOL_MAGIC;
+
+ if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER) &&
+ priv->rx_filer_enable)
+ priv->wol_supported |= GFAR_WOL_FILER_UCAST;
+
+ device_set_wakeup_capable(&ofdev->dev, priv->wol_supported);
/* fill out IRQ number and name fields */
for (i = 0; i < priv->num_grps; i++) {
@@ -1479,15 +1488,122 @@ static int gfar_remove(struct platform_device *ofdev)
#ifdef CONFIG_PM
+static void __gfar_filer_disable(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 temp;
+
+ temp = gfar_read(&regs->rctrl);
+ temp &= ~(RCTRL_FILREN | RCTRL_PRSDEP_INIT);
+ gfar_write(&regs->rctrl, temp);
+}
+
+static void __gfar_filer_enable(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 temp;
+
+ temp = gfar_read(&regs->rctrl);
+ temp |= RCTRL_FILREN | RCTRL_PRSDEP_INIT;
+ gfar_write(&regs->rctrl, temp);
+}
+
+/* Filer rules implementing wol capabilities */
+static void gfar_filer_config_wol(struct gfar_private *priv)
+{
+ unsigned int i;
+ u32 rqfcr;
+
+ __gfar_filer_disable(priv);
+
+ /* clear the filer table, reject any packet by default */
+ rqfcr = RQFCR_RJE | RQFCR_CMP_MATCH;
+ for (i = 0; i <= MAX_FILER_IDX; i++)
+ gfar_write_filer(priv, i, rqfcr, 0);
+
+ i = 0;
+ if (priv->wol_opts & GFAR_WOL_FILER_UCAST) {
+ /* unicast packet, accept it */
+ struct net_device *ndev = priv->ndev;
+ /* get the default rx queue index */
+ u8 qindex = (u8)priv->gfargrp[0].rx_queue->qindex;
+ u32 dest_mac_addr = (ndev->dev_addr[0] << 16) |
+ (ndev->dev_addr[1] << 8) |
+ ndev->dev_addr[2];
+
+ rqfcr = (qindex << 10) | RQFCR_AND |
+ RQFCR_CMP_EXACT | RQFCR_PID_DAH;
+
+ gfar_write_filer(priv, i++, rqfcr, dest_mac_addr);
+
+ dest_mac_addr = (ndev->dev_addr[3] << 16) |
+ (ndev->dev_addr[4] << 8) |
+ ndev->dev_addr[5];
+ rqfcr = (qindex << 10) | RQFCR_GPI |
+ RQFCR_CMP_EXACT | RQFCR_PID_DAL;
+ gfar_write_filer(priv, i++, rqfcr, dest_mac_addr);
+ }
+
+ __gfar_filer_enable(priv);
+}
+
+static void gfar_filer_restore_table(struct gfar_private *priv)
+{
+ u32 rqfcr, rqfpr;
+ unsigned int i;
+
+ __gfar_filer_disable(priv);
+
+ for (i = 0; i <= MAX_FILER_IDX; i++) {
+ rqfcr = priv->ftp_rqfcr[i];
+ rqfpr = priv->ftp_rqfpr[i];
+ gfar_write_filer(priv, i, rqfcr, rqfpr);
+ }
+
+ __gfar_filer_enable(priv);
+}
+
+/* gfar_start() for Rx only and with the FGPI filer interrupt enabled */
+static void gfar_start_wol_filer(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 tempval;
+ int i = 0;
+
+ /* Enable Rx hw queues */
+ gfar_write(&regs->rqueue, priv->rqueue);
+
+ /* Initialize DMACTRL to have WWR and WOP */
+ tempval = gfar_read(&regs->dmactrl);
+ tempval |= DMACTRL_INIT_SETTINGS;
+ gfar_write(&regs->dmactrl, tempval);
+
+ /* Make sure we aren't stopped */
+ tempval = gfar_read(&regs->dmactrl);
+ tempval &= ~DMACTRL_GRS;
+ gfar_write(&regs->dmactrl, tempval);
+
+ for (i = 0; i < priv->num_grps; i++) {
+ regs = priv->gfargrp[i].regs;
+ /* Clear RHLT, so that the DMA starts polling now */
+ gfar_write(&regs->rstat, priv->gfargrp[i].rstat);
+ /* enable the Filer General Purpose Interrupt */
+ gfar_write(&regs->imask, IMASK_FGPI);
+ }
+
+ /* Enable Rx DMA */
+ tempval = gfar_read(&regs->maccfg1);
+ tempval |= MACCFG1_RX_EN;
+ gfar_write(&regs->maccfg1, tempval);
+}
+
static int gfar_suspend(struct device *dev)
{
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
- int magic_packet = priv->wol_en &&
- (priv->device_flags &
- FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ u16 wol = priv->wol_opts;
if (!netif_running(ndev))
return 0;
@@ -1499,7 +1615,7 @@ static int gfar_suspend(struct device *dev)
gfar_halt(priv);
- if (magic_packet) {
+ if (wol & GFAR_WOL_MAGIC) {
/* Enable interrupt on Magic Packet */
gfar_write(&regs->imask, IMASK_MAG);
@@ -1513,6 +1629,10 @@ static int gfar_suspend(struct device *dev)
tempval |= MACCFG1_RX_EN;
gfar_write(&regs->maccfg1, tempval);
+ } else if (wol & GFAR_WOL_FILER_UCAST) {
+ gfar_filer_config_wol(priv);
+ gfar_start_wol_filer(priv);
+
} else {
phy_stop(priv->phydev);
}
@@ -1526,18 +1646,22 @@ static int gfar_resume(struct device *dev)
struct net_device *ndev = priv->ndev;
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
- int magic_packet = priv->wol_en &&
- (priv->device_flags &
- FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ u16 wol = priv->wol_opts;
if (!netif_running(ndev))
return 0;
- if (magic_packet) {
+ if (wol & GFAR_WOL_MAGIC) {
/* Disable Magic Packet mode */
tempval = gfar_read(&regs->maccfg2);
tempval &= ~MACCFG2_MPEN;
gfar_write(&regs->maccfg2, tempval);
+
+ } else if (wol & GFAR_WOL_FILER_UCAST) {
+ /* need to stop rx only, tx is already down */
+ gfar_halt(priv);
+ gfar_filer_restore_table(priv);
+
} else {
phy_start(priv->phydev);
}
@@ -1998,6 +2122,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
gfar_irq(grp, RX)->irq);
goto rx_irq_fail;
}
+ enable_irq_wake(gfar_irq(grp, RX)->irq);
+
} else {
err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0,
gfar_irq(grp, TX)->name, grp);
@@ -2743,7 +2869,14 @@ irqreturn_t gfar_receive(int irq, void *grp_id)
{
struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
unsigned long flags;
- u32 imask;
+ u32 imask, ievent;
+
+ ievent = gfar_read(&grp->regs->ievent);
+
+ if (unlikely(ievent & IEVENT_FGPI)) {
+ gfar_write(&grp->regs->ievent, IEVENT_FGPI);
+ return IRQ_HANDLED;
+ }
if (likely(napi_schedule_prep(&grp->napi_rx))) {
spin_lock_irqsave(&grp->grplock, flags);
@@ -3462,11 +3595,9 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
if (events & IEVENT_BSY) {
- dev->stats.rx_errors++;
+ dev->stats.rx_over_errors++;
atomic64_inc(&priv->extra_stats.rx_bsy);
- gfar_receive(irq, grp_id);
-
netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
gfar_read(&regs->rstat));
}
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 8c1994856e93..f266b20f9ef5 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -340,6 +340,7 @@ extern const char gfar_driver_version[];
#define IEVENT_MAG 0x00000800
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
+#define IEVENT_FGPI 0x00000010
#define IEVENT_FIR 0x00000008
#define IEVENT_FIQ 0x00000004
#define IEVENT_DPE 0x00000002
@@ -372,6 +373,7 @@ extern const char gfar_driver_version[];
#define IMASK_MAG 0x00000800
#define IMASK_GRSC 0x00000100
#define IMASK_RXFEN0 0x00000080
+#define IMASK_FGPI 0x00000010
#define IMASK_FIR 0x00000008
#define IMASK_FIQ 0x00000004
#define IMASK_DPE 0x00000002
@@ -540,6 +542,9 @@ extern const char gfar_driver_version[];
#define GFAR_INT_NAME_MAX (IFNAMSIZ + 6) /* '_g#_xx' */
+#define GFAR_WOL_MAGIC 0x00000001
+#define GFAR_WOL_FILER_UCAST 0x00000002
+
struct txbd8
{
union {
@@ -917,6 +922,7 @@ struct gfar {
#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
#define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800
+#define FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER 0x00001000
#if (MAXGROUPS == 2)
#define DEFAULT_MAPPING 0xAA
@@ -1161,8 +1167,6 @@ struct gfar_private {
extended_hash:1,
bd_stash_en:1,
rx_filer_enable:1,
- /* Wake-on-LAN enabled */
- wol_en:1,
/* Enable priorty based Tx scheduling in Hw */
prio_sched_en:1,
/* Flow control flags */
@@ -1191,6 +1195,10 @@ struct gfar_private {
u32 __iomem *hash_regs[16];
int hash_width;
+ /* wake-on-lan settings */
+ u16 wol_opts;
+ u16 wol_supported;
+
/*Filer table*/
unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 6bdc89179b72..4b0ee855edd7 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -182,8 +182,6 @@ static void gfar_gdrvinfo(struct net_device *dev,
sizeof(drvinfo->version));
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
}
@@ -644,28 +642,49 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct gfar_private *priv = netdev_priv(dev);
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
- wol->supported = WAKE_MAGIC;
- wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
- } else {
- wol->supported = wol->wolopts = 0;
- }
+ wol->supported = 0;
+ wol->wolopts = 0;
+
+ if (priv->wol_supported & GFAR_WOL_MAGIC)
+ wol->supported |= WAKE_MAGIC;
+
+ if (priv->wol_supported & GFAR_WOL_FILER_UCAST)
+ wol->supported |= WAKE_UCAST;
+
+ if (priv->wol_opts & GFAR_WOL_MAGIC)
+ wol->wolopts |= WAKE_MAGIC;
+
+ if (priv->wol_opts & GFAR_WOL_FILER_UCAST)
+ wol->wolopts |= WAKE_UCAST;
}
static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct gfar_private *priv = netdev_priv(dev);
+ u16 wol_opts = 0;
+ int err;
- if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
- wol->wolopts != 0)
+ if (!priv->wol_supported && wol->wolopts)
return -EINVAL;
- if (wol->wolopts & ~WAKE_MAGIC)
+ if (wol->wolopts & ~(WAKE_MAGIC | WAKE_UCAST))
return -EINVAL;
- device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC);
+ if (wol->wolopts & WAKE_MAGIC) {
+ wol_opts |= GFAR_WOL_MAGIC;
+ } else {
+ if (wol->wolopts & WAKE_UCAST)
+ wol_opts |= GFAR_WOL_FILER_UCAST;
+ }
+
+ wol_opts &= priv->wol_supported;
+ priv->wol_opts = 0;
+
+ err = device_set_wakeup_enable(priv->dev, wol_opts);
+ if (err)
+ return err;
- priv->wol_en = !!device_may_wakeup(&dev->dev);
+ priv->wol_opts = wol_opts;
return 0;
}
@@ -676,14 +695,14 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow)
u32 fcr = 0x0, fpr = FPR_FILER_MASK;
if (ethflow & RXH_L2DA) {
- fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH |
+ fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH |
RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
priv->cur_filer_idx = priv->cur_filer_idx - 1;
- fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH |
+ fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH |
RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index cc83350d56ba..89714f5e0dfc 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -351,8 +351,6 @@ uec_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, "QUICC ENGINE", sizeof(drvinfo->bus_info));
- drvinfo->eedump_len = 0;
- drvinfo->regdump_len = uec_get_regs_len(netdev);
}
#ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index dead17b5d769..74beb1867230 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -5,7 +5,8 @@
config NET_VENDOR_HISILICON
bool "Hisilicon devices"
default y
- depends on ARM
+ depends on OF && HAS_DMA
+ depends on ARM || ARM64 || COMPILE_TEST
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
@@ -24,11 +25,42 @@ config HIX5HD2_GMAC
config HIP04_ETH
tristate "HISILICON P04 Ethernet support"
- select PHYLIB
select MARVELL_PHY
select MFD_SYSCON
+ select HNS_MDIO
---help---
If you wish to compile a kernel for a hardware with hisilicon p04 SoC and
want to use the internal ethernet then you should answer Y to this.
+config HNS_MDIO
+ tristate
+ select PHYLIB
+ ---help---
+ This selects the HNS MDIO support. It is needed by HNS_DSAF to access
+ the PHY
+
+config HNS
+ tristate "Hisilicon Network Subsystem Support (Framework)"
+ ---help---
+ This selects the framework support for Hisilicon Network Subsystem. It
+ is needed by any driver which provides HNS acceleration engine or make
+ use of the engine
+
+config HNS_DSAF
+ tristate "Hisilicon HNS DSAF device Support"
+ select HNS
+ select HNS_MDIO
+ ---help---
+ This selects the DSAF (Distributed System Area Frabric) network
+ acceleration engine support. The engine is used in Hisilicon hip05,
+ Hi1610 and further ICT SoC
+
+config HNS_ENET
+ tristate "Hisilicon HNS Ethernet Device Support"
+ select PHYLIB
+ select HNS
+ ---help---
+ This selects the general ethernet driver for HNS. This module make
+ use of any HNS AE driver, such as HNS_DSAF
+
endif # NET_VENDOR_HISILICON
diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile
index 6c14540a4dc5..390b71fb3000 100644
--- a/drivers/net/ethernet/hisilicon/Makefile
+++ b/drivers/net/ethernet/hisilicon/Makefile
@@ -3,4 +3,6 @@
#
obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o
-obj-$(CONFIG_HIP04_ETH) += hip04_mdio.o hip04_eth.o
+obj-$(CONFIG_HIP04_ETH) += hip04_eth.o
+obj-$(CONFIG_HNS_MDIO) += hns_mdio.o
+obj-$(CONFIG_HNS) += hns/
diff --git a/drivers/net/ethernet/hisilicon/hip04_mdio.c b/drivers/net/ethernet/hisilicon/hip04_mdio.c
deleted file mode 100644
index fca0a5be1f0f..000000000000
--- a/drivers/net/ethernet/hisilicon/hip04_mdio.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Copyright (c) 2014 Linaro Ltd.
- * Copyright (c) 2014 Hisilicon 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>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/of_mdio.h>
-#include <linux/delay.h>
-
-#define MDIO_CMD_REG 0x0
-#define MDIO_ADDR_REG 0x4
-#define MDIO_WDATA_REG 0x8
-#define MDIO_RDATA_REG 0xc
-#define MDIO_STA_REG 0x10
-
-#define MDIO_START BIT(14)
-#define MDIO_R_VALID BIT(1)
-#define MDIO_READ (BIT(12) | BIT(11) | MDIO_START)
-#define MDIO_WRITE (BIT(12) | BIT(10) | MDIO_START)
-
-struct hip04_mdio_priv {
- void __iomem *base;
-};
-
-#define WAIT_TIMEOUT 10
-static int hip04_mdio_wait_ready(struct mii_bus *bus)
-{
- struct hip04_mdio_priv *priv = bus->priv;
- int i;
-
- for (i = 0; readl_relaxed(priv->base + MDIO_CMD_REG) & MDIO_START; i++) {
- if (i == WAIT_TIMEOUT)
- return -ETIMEDOUT;
- msleep(20);
- }
-
- return 0;
-}
-
-static int hip04_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-{
- struct hip04_mdio_priv *priv = bus->priv;
- u32 val;
- int ret;
-
- ret = hip04_mdio_wait_ready(bus);
- if (ret < 0)
- goto out;
-
- val = regnum | (mii_id << 5) | MDIO_READ;
- writel_relaxed(val, priv->base + MDIO_CMD_REG);
-
- ret = hip04_mdio_wait_ready(bus);
- if (ret < 0)
- goto out;
-
- val = readl_relaxed(priv->base + MDIO_STA_REG);
- if (val & MDIO_R_VALID) {
- dev_err(bus->parent, "SMI bus read not valid\n");
- ret = -ENODEV;
- goto out;
- }
-
- val = readl_relaxed(priv->base + MDIO_RDATA_REG);
- ret = val & 0xFFFF;
-out:
- return ret;
-}
-
-static int hip04_mdio_write(struct mii_bus *bus, int mii_id,
- int regnum, u16 value)
-{
- struct hip04_mdio_priv *priv = bus->priv;
- u32 val;
- int ret;
-
- ret = hip04_mdio_wait_ready(bus);
- if (ret < 0)
- goto out;
-
- writel_relaxed(value, priv->base + MDIO_WDATA_REG);
- val = regnum | (mii_id << 5) | MDIO_WRITE;
- writel_relaxed(val, priv->base + MDIO_CMD_REG);
-out:
- return ret;
-}
-
-static int hip04_mdio_reset(struct mii_bus *bus)
-{
- int temp, i;
-
- for (i = 0; i < PHY_MAX_ADDR; i++) {
- hip04_mdio_write(bus, i, 22, 0);
- temp = hip04_mdio_read(bus, i, MII_BMCR);
- if (temp < 0)
- continue;
-
- temp |= BMCR_RESET;
- if (hip04_mdio_write(bus, i, MII_BMCR, temp) < 0)
- continue;
- }
-
- mdelay(500);
- return 0;
-}
-
-static int hip04_mdio_probe(struct platform_device *pdev)
-{
- struct resource *r;
- struct mii_bus *bus;
- struct hip04_mdio_priv *priv;
- int ret;
-
- bus = mdiobus_alloc_size(sizeof(struct hip04_mdio_priv));
- if (!bus) {
- dev_err(&pdev->dev, "Cannot allocate MDIO bus\n");
- return -ENOMEM;
- }
-
- bus->name = "hip04_mdio_bus";
- bus->read = hip04_mdio_read;
- bus->write = hip04_mdio_write;
- bus->reset = hip04_mdio_reset;
- snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev));
- bus->parent = &pdev->dev;
- priv = bus->priv;
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(priv->base)) {
- ret = PTR_ERR(priv->base);
- goto out_mdio;
- }
-
- ret = of_mdiobus_register(bus, pdev->dev.of_node);
- if (ret < 0) {
- dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
- goto out_mdio;
- }
-
- platform_set_drvdata(pdev, bus);
-
- return 0;
-
-out_mdio:
- mdiobus_free(bus);
- return ret;
-}
-
-static int hip04_mdio_remove(struct platform_device *pdev)
-{
- struct mii_bus *bus = platform_get_drvdata(pdev);
-
- mdiobus_unregister(bus);
- mdiobus_free(bus);
-
- return 0;
-}
-
-static const struct of_device_id hip04_mdio_match[] = {
- { .compatible = "hisilicon,hip04-mdio" },
- { }
-};
-MODULE_DEVICE_TABLE(of, hip04_mdio_match);
-
-static struct platform_driver hip04_mdio_driver = {
- .probe = hip04_mdio_probe,
- .remove = hip04_mdio_remove,
- .driver = {
- .name = "hip04-mdio",
- .of_match_table = hip04_mdio_match,
- },
-};
-
-module_platform_driver(hip04_mdio_driver);
-
-MODULE_DESCRIPTION("HISILICON P04 MDIO interface driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:hip04-mdio");
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index a5e077eac99a..e51892d518ff 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -371,7 +371,7 @@ static void hix5hd2_port_enable(struct hix5hd2_priv *priv)
static void hix5hd2_port_disable(struct hix5hd2_priv *priv)
{
- writel_relaxed(~(BITS_RX_EN | BITS_TX_EN), priv->base + PORT_EN);
+ writel_relaxed(~(u32)(BITS_RX_EN | BITS_TX_EN), priv->base + PORT_EN);
writel_relaxed(0, priv->base + DESC_WR_RD_ENA);
}
diff --git a/drivers/net/ethernet/hisilicon/hns/Makefile b/drivers/net/ethernet/hisilicon/hns/Makefile
new file mode 100644
index 000000000000..6010c83e38d8
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the HISILICON network device drivers.
+#
+
+obj-$(CONFIG_HNS) += hnae.o
+
+obj-$(CONFIG_HNS_DSAF) += hns_dsaf.o
+hns_dsaf-objs = hns_ae_adapt.o hns_dsaf_gmac.o hns_dsaf_mac.o hns_dsaf_misc.o \
+ hns_dsaf_main.o hns_dsaf_ppe.o hns_dsaf_rcb.o hns_dsaf_xgmac.o
+
+obj-$(CONFIG_HNS_ENET) += hns_enet_drv.o
+hns_enet_drv-objs = hns_enet.o hns_ethtool.o
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c
new file mode 100644
index 000000000000..b3645297477e
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+
+#include "hnae.h"
+
+#define cls_to_ae_dev(dev) container_of(dev, struct hnae_ae_dev, cls_dev)
+
+static struct class *hnae_class;
+
+static void
+hnae_list_add(spinlock_t *lock, struct list_head *node, struct list_head *head)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(lock, flags);
+ list_add_tail_rcu(node, head);
+ spin_unlock_irqrestore(lock, flags);
+}
+
+static void hnae_list_del(spinlock_t *lock, struct list_head *node)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(lock, flags);
+ list_del_rcu(node);
+ spin_unlock_irqrestore(lock, flags);
+}
+
+static int hnae_alloc_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
+{
+ unsigned int order = hnae_page_order(ring);
+ struct page *p = dev_alloc_pages(order);
+
+ if (!p)
+ return -ENOMEM;
+
+ cb->priv = p;
+ cb->page_offset = 0;
+ cb->reuse_flag = 0;
+ cb->buf = page_address(p);
+ cb->length = hnae_page_size(ring);
+ cb->type = DESC_TYPE_PAGE;
+
+ return 0;
+}
+
+static void hnae_free_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
+{
+ if (cb->type == DESC_TYPE_SKB)
+ dev_kfree_skb_any((struct sk_buff *)cb->priv);
+ else if (unlikely(is_rx_ring(ring)))
+ put_page((struct page *)cb->priv);
+ memset(cb, 0, sizeof(*cb));
+}
+
+static int hnae_map_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
+{
+ cb->dma = dma_map_page(ring_to_dev(ring), cb->priv, 0,
+ cb->length, ring_to_dma_dir(ring));
+
+ if (dma_mapping_error(ring_to_dev(ring), cb->dma))
+ return -EIO;
+
+ return 0;
+}
+
+static void hnae_unmap_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
+{
+ if (cb->type == DESC_TYPE_SKB)
+ dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length,
+ ring_to_dma_dir(ring));
+ else
+ dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length,
+ ring_to_dma_dir(ring));
+}
+
+static struct hnae_buf_ops hnae_bops = {
+ .alloc_buffer = hnae_alloc_buffer,
+ .free_buffer = hnae_free_buffer,
+ .map_buffer = hnae_map_buffer,
+ .unmap_buffer = hnae_unmap_buffer,
+};
+
+static int __ae_match(struct device *dev, const void *data)
+{
+ struct hnae_ae_dev *hdev = cls_to_ae_dev(dev);
+ const char *ae_id = data;
+
+ if (!strncmp(ae_id, hdev->name, AE_NAME_SIZE))
+ return 1;
+
+ return 0;
+}
+
+static struct hnae_ae_dev *find_ae(const char *ae_id)
+{
+ struct device *dev;
+
+ WARN_ON(!ae_id);
+
+ dev = class_find_device(hnae_class, NULL, ae_id, __ae_match);
+
+ return dev ? cls_to_ae_dev(dev) : NULL;
+}
+
+static void hnae_free_buffers(struct hnae_ring *ring)
+{
+ int i;
+
+ for (i = 0; i < ring->desc_num; i++)
+ hnae_free_buffer_detach(ring, i);
+}
+
+/* Allocate memory for raw pkg, and map with dma */
+static int hnae_alloc_buffers(struct hnae_ring *ring)
+{
+ int i, j, ret;
+
+ for (i = 0; i < ring->desc_num; i++) {
+ ret = hnae_alloc_buffer_attach(ring, i);
+ if (ret)
+ goto out_buffer_fail;
+ }
+
+ return 0;
+
+out_buffer_fail:
+ for (j = i - 1; j >= 0; j--)
+ hnae_free_buffer_detach(ring, j);
+ return ret;
+}
+
+/* free desc along with its attached buffer */
+static void hnae_free_desc(struct hnae_ring *ring)
+{
+ hnae_free_buffers(ring);
+ dma_unmap_single(ring_to_dev(ring), ring->desc_dma_addr,
+ ring->desc_num * sizeof(ring->desc[0]),
+ ring_to_dma_dir(ring));
+ ring->desc_dma_addr = 0;
+ kfree(ring->desc);
+ ring->desc = NULL;
+}
+
+/* alloc desc, without buffer attached */
+static int hnae_alloc_desc(struct hnae_ring *ring)
+{
+ int size = ring->desc_num * sizeof(ring->desc[0]);
+
+ ring->desc = kzalloc(size, GFP_KERNEL);
+ if (!ring->desc)
+ return -ENOMEM;
+
+ ring->desc_dma_addr = dma_map_single(ring_to_dev(ring),
+ ring->desc, size, ring_to_dma_dir(ring));
+ if (dma_mapping_error(ring_to_dev(ring), ring->desc_dma_addr)) {
+ ring->desc_dma_addr = 0;
+ kfree(ring->desc);
+ ring->desc = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/* fini ring, also free the buffer for the ring */
+static void hnae_fini_ring(struct hnae_ring *ring)
+{
+ hnae_free_desc(ring);
+ kfree(ring->desc_cb);
+ ring->desc_cb = NULL;
+ ring->next_to_clean = 0;
+ ring->next_to_use = 0;
+}
+
+/* init ring, and with buffer for rx ring */
+static int
+hnae_init_ring(struct hnae_queue *q, struct hnae_ring *ring, int flags)
+{
+ int ret;
+
+ if (ring->desc_num <= 0 || ring->buf_size <= 0)
+ return -EINVAL;
+
+ ring->q = q;
+ ring->flags = flags;
+ assert(!ring->desc && !ring->desc_cb && !ring->desc_dma_addr);
+
+ /* not matter for tx or rx ring, the ntc and ntc start from 0 */
+ assert(ring->next_to_use == 0);
+ assert(ring->next_to_clean == 0);
+
+ ring->desc_cb = kcalloc(ring->desc_num, sizeof(ring->desc_cb[0]),
+ GFP_KERNEL);
+ if (!ring->desc_cb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = hnae_alloc_desc(ring);
+ if (ret)
+ goto out_with_desc_cb;
+
+ if (is_rx_ring(ring)) {
+ ret = hnae_alloc_buffers(ring);
+ if (ret)
+ goto out_with_desc;
+ }
+
+ return 0;
+
+out_with_desc:
+ hnae_free_desc(ring);
+out_with_desc_cb:
+ kfree(ring->desc_cb);
+ ring->desc_cb = NULL;
+out:
+ return ret;
+}
+
+static int hnae_init_queue(struct hnae_handle *h, struct hnae_queue *q,
+ struct hnae_ae_dev *dev)
+{
+ int ret;
+
+ q->dev = dev;
+ q->handle = h;
+
+ ret = hnae_init_ring(q, &q->tx_ring, q->tx_ring.flags | RINGF_DIR);
+ if (ret)
+ goto out;
+
+ ret = hnae_init_ring(q, &q->rx_ring, q->rx_ring.flags & ~RINGF_DIR);
+ if (ret)
+ goto out_with_tx_ring;
+
+ if (dev->ops->init_queue)
+ dev->ops->init_queue(q);
+
+ return 0;
+
+out_with_tx_ring:
+ hnae_fini_ring(&q->tx_ring);
+out:
+ return ret;
+}
+
+static void hnae_fini_queue(struct hnae_queue *q)
+{
+ if (q->dev->ops->fini_queue)
+ q->dev->ops->fini_queue(q);
+
+ hnae_fini_ring(&q->tx_ring);
+ hnae_fini_ring(&q->rx_ring);
+}
+
+/**
+ * ae_chain - define ae chain head
+ */
+static RAW_NOTIFIER_HEAD(ae_chain);
+
+int hnae_register_notifier(struct notifier_block *nb)
+{
+ return raw_notifier_chain_register(&ae_chain, nb);
+}
+EXPORT_SYMBOL(hnae_register_notifier);
+
+void hnae_unregister_notifier(struct notifier_block *nb)
+{
+ if (raw_notifier_chain_unregister(&ae_chain, nb))
+ dev_err(NULL, "notifier chain unregister fail\n");
+}
+EXPORT_SYMBOL(hnae_unregister_notifier);
+
+int hnae_reinit_handle(struct hnae_handle *handle)
+{
+ int i, j;
+ int ret;
+
+ for (i = 0; i < handle->q_num; i++) /* free ring*/
+ hnae_fini_queue(handle->qs[i]);
+
+ if (handle->dev->ops->reset)
+ handle->dev->ops->reset(handle);
+
+ for (i = 0; i < handle->q_num; i++) {/* reinit ring*/
+ ret = hnae_init_queue(handle, handle->qs[i], handle->dev);
+ if (ret)
+ goto out_when_init_queue;
+ }
+ return 0;
+out_when_init_queue:
+ for (j = i - 1; j >= 0; j--)
+ hnae_fini_queue(handle->qs[j]);
+ return ret;
+}
+EXPORT_SYMBOL(hnae_reinit_handle);
+
+/* hnae_get_handle - get a handle from the AE
+ * @owner_dev: the dev use this handle
+ * @ae_id: the id of the ae to be used
+ * @ae_opts: the options set for the handle
+ * @bops: the callbacks for buffer management
+ *
+ * return handle ptr or ERR_PTR
+ */
+struct hnae_handle *hnae_get_handle(struct device *owner_dev,
+ const char *ae_id, u32 port_id,
+ struct hnae_buf_ops *bops)
+{
+ struct hnae_ae_dev *dev;
+ struct hnae_handle *handle;
+ int i, j;
+ int ret;
+
+ dev = find_ae(ae_id);
+ if (!dev)
+ return ERR_PTR(-ENODEV);
+
+ handle = dev->ops->get_handle(dev, port_id);
+ if (IS_ERR(handle))
+ return handle;
+
+ handle->dev = dev;
+ handle->owner_dev = owner_dev;
+ handle->bops = bops ? bops : &hnae_bops;
+ handle->eport_id = port_id;
+
+ for (i = 0; i < handle->q_num; i++) {
+ ret = hnae_init_queue(handle, handle->qs[i], dev);
+ if (ret)
+ goto out_when_init_queue;
+ }
+
+ __module_get(dev->owner);
+
+ hnae_list_add(&dev->lock, &handle->node, &dev->handle_list);
+
+ return handle;
+
+out_when_init_queue:
+ for (j = i - 1; j >= 0; j--)
+ hnae_fini_queue(handle->qs[j]);
+
+ return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL(hnae_get_handle);
+
+void hnae_put_handle(struct hnae_handle *h)
+{
+ struct hnae_ae_dev *dev = h->dev;
+ int i;
+
+ for (i = 0; i < h->q_num; i++)
+ hnae_fini_queue(h->qs[i]);
+
+ if (h->dev->ops->reset)
+ h->dev->ops->reset(h);
+
+ hnae_list_del(&dev->lock, &h->node);
+
+ if (dev->ops->put_handle)
+ dev->ops->put_handle(h);
+
+ module_put(dev->owner);
+}
+EXPORT_SYMBOL(hnae_put_handle);
+
+static void hnae_release(struct device *dev)
+{
+}
+
+/**
+ * hnae_ae_register - register a AE engine to hnae framework
+ * @hdev: the hnae ae engine device
+ * @owner: the module who provides this dev
+ * NOTE: the duplicated name will not be checked
+ */
+int hnae_ae_register(struct hnae_ae_dev *hdev, struct module *owner)
+{
+ static atomic_t id = ATOMIC_INIT(-1);
+ int ret;
+
+ if (!hdev->dev)
+ return -ENODEV;
+
+ if (!hdev->ops || !hdev->ops->get_handle ||
+ !hdev->ops->toggle_ring_irq ||
+ !hdev->ops->toggle_queue_status ||
+ !hdev->ops->get_status || !hdev->ops->adjust_link)
+ return -EINVAL;
+
+ hdev->owner = owner;
+ hdev->id = (int)atomic_inc_return(&id);
+ hdev->cls_dev.parent = hdev->dev;
+ hdev->cls_dev.class = hnae_class;
+ hdev->cls_dev.release = hnae_release;
+ (void)dev_set_name(&hdev->cls_dev, "hnae%d", hdev->id);
+ ret = device_register(&hdev->cls_dev);
+ if (ret)
+ return ret;
+
+ __module_get(THIS_MODULE);
+
+ INIT_LIST_HEAD(&hdev->handle_list);
+ spin_lock_init(&hdev->lock);
+
+ ret = raw_notifier_call_chain(&ae_chain, HNAE_AE_REGISTER, NULL);
+ if (ret)
+ dev_dbg(hdev->dev,
+ "has not notifier for AE: %s\n", hdev->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(hnae_ae_register);
+
+/**
+ * hnae_ae_unregister - unregisters a HNAE AE engine
+ * @cdev: the device to unregister
+ */
+void hnae_ae_unregister(struct hnae_ae_dev *hdev)
+{
+ device_unregister(&hdev->cls_dev);
+ module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL(hnae_ae_unregister);
+
+static int __init hnae_init(void)
+{
+ hnae_class = class_create(THIS_MODULE, "hnae");
+ return PTR_ERR_OR_ZERO(hnae_class);
+}
+
+static void __exit hnae_exit(void)
+{
+ class_destroy(hnae_class);
+}
+
+subsys_initcall(hnae_init);
+module_exit(hnae_exit);
+
+MODULE_AUTHOR("Hisilicon, Inc.");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Hisilicon Network Acceleration Engine Framework");
+
+/* vi: set tw=78 noet: */
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h
new file mode 100644
index 000000000000..cec95ac8687d
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef __HNAE_H
+#define __HNAE_H
+
+/* Names used in this framework:
+ * ae handle (handle):
+ * a set of queues provided by AE
+ * ring buffer queue (rbq):
+ * the channel between upper layer and the AE, can do tx and rx
+ * ring:
+ * a tx or rx channel within a rbq
+ * ring description (desc):
+ * an element in the ring with packet information
+ * buffer:
+ * a memory region referred by desc with the full packet payload
+ *
+ * "num" means a static number set as a parameter, "count" mean a dynamic
+ * number set while running
+ * "cb" means control block
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/notifier.h>
+#include <linux/phy.h>
+#include <linux/types.h>
+
+#define HNAE_DRIVER_VERSION "1.3.0"
+#define HNAE_DRIVER_NAME "hns"
+#define HNAE_COPYRIGHT "Copyright(c) 2015 Huawei Corporation."
+#define HNAE_DRIVER_STRING "Hisilicon Network Subsystem Driver"
+#define HNAE_DEFAULT_DEVICE_DESCR "Hisilicon Network Subsystem"
+
+#ifdef DEBUG
+
+#ifndef assert
+#define assert(expr) \
+do { \
+ if (!(expr)) { \
+ pr_err("Assertion failed! %s, %s, %s, line %d\n", \
+ #expr, __FILE__, __func__, __LINE__); \
+ } \
+} while (0)
+#endif
+
+#else
+
+#ifndef assert
+#define assert(expr)
+#endif
+
+#endif
+
+#define AE_VERSION_1 ('6' << 16 | '6' << 8 | '0')
+#define AE_VERSION_2 ('1' << 24 | '6' << 16 | '1' << 8 | '0')
+#define AE_NAME_SIZE 16
+
+/* some said the RX and TX RCB format should not be the same in the future. But
+ * it is the same now...
+ */
+#define RCB_REG_BASEADDR_L 0x00 /* P660 support only 32bit accessing */
+#define RCB_REG_BASEADDR_H 0x04
+#define RCB_REG_BD_NUM 0x08
+#define RCB_REG_BD_LEN 0x0C
+#define RCB_REG_PKTLINE 0x10
+#define RCB_REG_TAIL 0x18
+#define RCB_REG_HEAD 0x1C
+#define RCB_REG_FBDNUM 0x20
+#define RCB_REG_OFFSET 0x24 /* pkt num to be handled */
+#define RCB_REG_PKTNUM_RECORD 0x2C /* total pkt received */
+
+#define HNS_RX_HEAD_SIZE 256
+
+#define HNAE_AE_REGISTER 0x1
+
+#define RCB_RING_NAME_LEN 16
+
+enum hnae_led_state {
+ HNAE_LED_INACTIVE,
+ HNAE_LED_ACTIVE,
+ HNAE_LED_ON,
+ HNAE_LED_OFF
+};
+
+#define HNS_RX_FLAG_VLAN_PRESENT 0x1
+#define HNS_RX_FLAG_L3ID_IPV4 0x0
+#define HNS_RX_FLAG_L3ID_IPV6 0x1
+#define HNS_RX_FLAG_L4ID_UDP 0x0
+#define HNS_RX_FLAG_L4ID_TCP 0x1
+
+#define HNS_TXD_ASID_S 0
+#define HNS_TXD_ASID_M (0xff << HNS_TXD_ASID_S)
+#define HNS_TXD_BUFNUM_S 8
+#define HNS_TXD_BUFNUM_M (0x3 << HNS_TXD_BUFNUM_S)
+#define HNS_TXD_PORTID_S 10
+#define HNS_TXD_PORTID_M (0x7 << HNS_TXD_PORTID_S)
+
+#define HNS_TXD_RA_B 8
+#define HNS_TXD_RI_B 9
+#define HNS_TXD_L4CS_B 10
+#define HNS_TXD_L3CS_B 11
+#define HNS_TXD_FE_B 12
+#define HNS_TXD_VLD_B 13
+#define HNS_TXD_IPOFFSET_S 14
+#define HNS_TXD_IPOFFSET_M (0xff << HNS_TXD_IPOFFSET_S)
+
+#define HNS_RXD_IPOFFSET_S 0
+#define HNS_RXD_IPOFFSET_M (0xff << HNS_TXD_IPOFFSET_S)
+#define HNS_RXD_BUFNUM_S 8
+#define HNS_RXD_BUFNUM_M (0x3 << HNS_RXD_BUFNUM_S)
+#define HNS_RXD_PORTID_S 10
+#define HNS_RXD_PORTID_M (0x7 << HNS_RXD_PORTID_S)
+#define HNS_RXD_DMAC_S 13
+#define HNS_RXD_DMAC_M (0x3 << HNS_RXD_DMAC_S)
+#define HNS_RXD_VLAN_S 15
+#define HNS_RXD_VLAN_M (0x3 << HNS_RXD_VLAN_S)
+#define HNS_RXD_L3ID_S 17
+#define HNS_RXD_L3ID_M (0xf << HNS_RXD_L3ID_S)
+#define HNS_RXD_L4ID_S 21
+#define HNS_RXD_L4ID_M (0xf << HNS_RXD_L4ID_S)
+#define HNS_RXD_FE_B 25
+#define HNS_RXD_FRAG_B 26
+#define HNS_RXD_VLD_B 27
+#define HNS_RXD_L2E_B 28
+#define HNS_RXD_L3E_B 29
+#define HNS_RXD_L4E_B 30
+#define HNS_RXD_DROP_B 31
+
+#define HNS_RXD_VLANID_S 8
+#define HNS_RXD_VLANID_M (0xfff << HNS_RXD_VLANID_S)
+#define HNS_RXD_CFI_B 20
+#define HNS_RXD_PRI_S 21
+#define HNS_RXD_PRI_M (0x7 << HNS_RXD_PRI_S)
+#define HNS_RXD_ASID_S 24
+#define HNS_RXD_ASID_M (0xff << HNS_RXD_ASID_S)
+
+/* hardware spec ring buffer format */
+struct __packed hnae_desc {
+ __le64 addr;
+ union {
+ struct {
+ __le16 asid_bufnum_pid;
+ __le16 send_size;
+ __le32 flag_ipoffset;
+ __le32 reserved_3[4];
+ } tx;
+
+ struct {
+ __le32 ipoff_bnum_pid_flag;
+ __le16 pkt_len;
+ __le16 size;
+ __le32 vlan_pri_asid;
+ __le32 reserved_2[3];
+ } rx;
+ };
+};
+
+struct hnae_desc_cb {
+ dma_addr_t dma; /* dma address of this desc */
+ void *buf; /* cpu addr for a desc */
+
+ /* priv data for the desc, e.g. skb when use with ip stack*/
+ void *priv;
+ u16 page_offset;
+ u16 reuse_flag;
+
+ u16 length; /* length of the buffer */
+
+ /* desc type, used by the ring user to mark the type of the priv data */
+ u16 type;
+};
+
+#define setflags(flags, bits) ((flags) |= (bits))
+#define unsetflags(flags, bits) ((flags) &= ~(bits))
+
+/* hnae_ring->flags fields */
+#define RINGF_DIR 0x1 /* TX or RX ring, set if TX */
+#define is_tx_ring(ring) ((ring)->flags & RINGF_DIR)
+#define is_rx_ring(ring) (!is_tx_ring(ring))
+#define ring_to_dma_dir(ring) (is_tx_ring(ring) ? \
+ DMA_TO_DEVICE : DMA_FROM_DEVICE)
+
+struct ring_stats {
+ u64 io_err_cnt;
+ u64 sw_err_cnt;
+ u64 seg_pkt_cnt;
+ union {
+ struct {
+ u64 tx_pkts;
+ u64 tx_bytes;
+ u64 tx_err_cnt;
+ u64 restart_queue;
+ u64 tx_busy;
+ };
+ struct {
+ u64 rx_pkts;
+ u64 rx_bytes;
+ u64 rx_err_cnt;
+ u64 reuse_pg_cnt;
+ u64 err_pkt_len;
+ u64 non_vld_descs;
+ u64 err_bd_num;
+ u64 l2_err;
+ u64 l3l4_csum_err;
+ };
+ };
+};
+
+struct hnae_queue;
+
+struct hnae_ring {
+ u8 __iomem *io_base; /* base io address for the ring */
+ struct hnae_desc *desc; /* dma map address space */
+ struct hnae_desc_cb *desc_cb;
+ struct hnae_queue *q;
+ int irq;
+ char ring_name[RCB_RING_NAME_LEN];
+
+ /* statistic */
+ struct ring_stats stats;
+
+ dma_addr_t desc_dma_addr;
+ u32 buf_size; /* size for hnae_desc->addr, preset by AE */
+ u16 desc_num; /* total number of desc */
+ u16 max_desc_num_per_pkt;
+ u16 max_raw_data_sz_per_desc;
+ u16 max_pkt_size;
+ int next_to_use; /* idx of next spare desc */
+
+ /* idx of lastest sent desc, the ring is empty when equal to
+ * next_to_use
+ */
+ int next_to_clean;
+
+ int flags; /* ring attribute */
+ int irq_init_flag;
+};
+
+#define ring_ptr_move_fw(ring, p) \
+ ((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
+#define ring_ptr_move_bw(ring, p) \
+ ((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
+
+enum hns_desc_type {
+ DESC_TYPE_SKB,
+ DESC_TYPE_PAGE,
+};
+
+#define assert_is_ring_idx(ring, idx) \
+ assert((idx) >= 0 && (idx) < (ring)->desc_num)
+
+/* the distance between [begin, end) in a ring buffer
+ * note: there is a unuse slot between the begin and the end
+ */
+static inline int ring_dist(struct hnae_ring *ring, int begin, int end)
+{
+ assert_is_ring_idx(ring, begin);
+ assert_is_ring_idx(ring, end);
+
+ return (end - begin + ring->desc_num) % ring->desc_num;
+}
+
+static inline int ring_space(struct hnae_ring *ring)
+{
+ return ring->desc_num -
+ ring_dist(ring, ring->next_to_clean, ring->next_to_use) - 1;
+}
+
+static inline int is_ring_empty(struct hnae_ring *ring)
+{
+ assert_is_ring_idx(ring, ring->next_to_use);
+ assert_is_ring_idx(ring, ring->next_to_clean);
+
+ return ring->next_to_use == ring->next_to_clean;
+}
+
+#define hnae_buf_size(_ring) ((_ring)->buf_size)
+#define hnae_page_order(_ring) (get_order(hnae_buf_size(_ring)))
+#define hnae_page_size(_ring) (PAGE_SIZE << hnae_page_order(_ring))
+
+struct hnae_handle;
+
+/* allocate and dma map space for hnae desc */
+struct hnae_buf_ops {
+ int (*alloc_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb);
+ void (*free_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb);
+ int (*map_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb);
+ void (*unmap_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb);
+};
+
+struct hnae_queue {
+ void __iomem *io_base;
+ phys_addr_t phy_base;
+ struct hnae_ae_dev *dev; /* the device who use this queue */
+ struct hnae_ring rx_ring, tx_ring;
+ struct hnae_handle *handle;
+};
+
+/*hnae loop mode*/
+enum hnae_loop {
+ MAC_INTERNALLOOP_MAC = 0,
+ MAC_INTERNALLOOP_SERDES,
+ MAC_INTERNALLOOP_PHY,
+ MAC_LOOP_NONE,
+};
+
+/*hnae port type*/
+enum hnae_port_type {
+ HNAE_PORT_SERVICE = 0,
+ HNAE_PORT_DEBUG
+};
+
+/* This struct defines the operation on the handle.
+ *
+ * get_handle(): (mandatory)
+ * Get a handle from AE according to its name and options.
+ * the AE driver should manage the space used by handle and its queues while
+ * the HNAE framework will allocate desc and desc_cb for all rings in the
+ * queues.
+ * put_handle():
+ * Release the handle.
+ * start():
+ * Enable the hardware, include all queues
+ * stop():
+ * Disable the hardware
+ * set_opts(): (mandatory)
+ * Set options to the AE
+ * get_opts(): (mandatory)
+ * Get options from the AE
+ * get_status():
+ * Get the carrier state of the back channel of the handle, 1 for ok, 0 for
+ * non-ok
+ * toggle_ring_irq(): (mandatory)
+ * Set the ring irq to be enabled(0) or disable(1)
+ * toggle_queue_status(): (mandatory)
+ * Set the queue to be enabled(1) or disable(0), this will not change the
+ * ring irq state
+ * adjust_link()
+ * adjust link status
+ * set_loopback()
+ * set loopback
+ * get_ring_bdnum_limit()
+ * get ring bd number limit
+ * get_pauseparam()
+ * get tx and rx of pause frame use
+ * set_autoneg()
+ * set auto autonegotiation of pause frame use
+ * get_autoneg()
+ * get auto autonegotiation of pause frame use
+ * set_pauseparam()
+ * set tx and rx of pause frame use
+ * get_coalesce_usecs()
+ * get usecs to delay a TX interrupt after a packet is sent
+ * get_rx_max_coalesced_frames()
+ * get Maximum number of packets to be sent before a TX interrupt.
+ * set_coalesce_usecs()
+ * set usecs to delay a TX interrupt after a packet is sent
+ * set_coalesce_frames()
+ * set Maximum number of packets to be sent before a TX interrupt.
+ * get_ringnum()
+ * get RX/TX ring number
+ * get_max_ringnum()
+ * get RX/TX ring maximum number
+ * get_mac_addr()
+ * get mac address
+ * set_mac_addr()
+ * set mac address
+ * set_mc_addr()
+ * set multicast mode
+ * set_mtu()
+ * set mtu
+ * update_stats()
+ * update Old network device statistics
+ * get_ethtool_stats()
+ * get ethtool network device statistics
+ * get_strings()
+ * get a set of strings that describe the requested objects
+ * get_sset_count()
+ * get number of strings that @get_strings will write
+ * update_led_status()
+ * update the led status
+ * set_led_id()
+ * set led id
+ * get_regs()
+ * get regs dump
+ * get_regs_len()
+ * get the len of the regs dump
+ */
+struct hnae_ae_ops {
+ struct hnae_handle *(*get_handle)(struct hnae_ae_dev *dev,
+ u32 port_id);
+ void (*put_handle)(struct hnae_handle *handle);
+ void (*init_queue)(struct hnae_queue *q);
+ void (*fini_queue)(struct hnae_queue *q);
+ int (*start)(struct hnae_handle *handle);
+ void (*stop)(struct hnae_handle *handle);
+ void (*reset)(struct hnae_handle *handle);
+ int (*set_opts)(struct hnae_handle *handle, int type, void *opts);
+ int (*get_opts)(struct hnae_handle *handle, int type, void **opts);
+ int (*get_status)(struct hnae_handle *handle);
+ int (*get_info)(struct hnae_handle *handle,
+ u8 *auto_neg, u16 *speed, u8 *duplex);
+ void (*toggle_ring_irq)(struct hnae_ring *ring, u32 val);
+ void (*toggle_queue_status)(struct hnae_queue *queue, u32 val);
+ void (*adjust_link)(struct hnae_handle *handle, int speed, int duplex);
+ int (*set_loopback)(struct hnae_handle *handle,
+ enum hnae_loop loop_mode, int en);
+ void (*get_ring_bdnum_limit)(struct hnae_queue *queue,
+ u32 *uplimit);
+ void (*get_pauseparam)(struct hnae_handle *handle,
+ u32 *auto_neg, u32 *rx_en, u32 *tx_en);
+ int (*set_autoneg)(struct hnae_handle *handle, u8 enable);
+ int (*get_autoneg)(struct hnae_handle *handle);
+ int (*set_pauseparam)(struct hnae_handle *handle,
+ u32 auto_neg, u32 rx_en, u32 tx_en);
+ void (*get_coalesce_usecs)(struct hnae_handle *handle,
+ u32 *tx_usecs, u32 *rx_usecs);
+ void (*get_rx_max_coalesced_frames)(struct hnae_handle *handle,
+ u32 *tx_frames, u32 *rx_frames);
+ void (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout);
+ int (*set_coalesce_frames)(struct hnae_handle *handle,
+ u32 coalesce_frames);
+ void (*set_promisc_mode)(struct hnae_handle *handle, u32 en);
+ int (*get_mac_addr)(struct hnae_handle *handle, void **p);
+ int (*set_mac_addr)(struct hnae_handle *handle, void *p);
+ int (*set_mc_addr)(struct hnae_handle *handle, void *addr);
+ int (*set_mtu)(struct hnae_handle *handle, int new_mtu);
+ void (*update_stats)(struct hnae_handle *handle,
+ struct net_device_stats *net_stats);
+ void (*get_stats)(struct hnae_handle *handle, u64 *data);
+ void (*get_strings)(struct hnae_handle *handle,
+ u32 stringset, u8 *data);
+ int (*get_sset_count)(struct hnae_handle *handle, int stringset);
+ void (*update_led_status)(struct hnae_handle *handle);
+ int (*set_led_id)(struct hnae_handle *handle,
+ enum hnae_led_state status);
+ void (*get_regs)(struct hnae_handle *handle, void *data);
+ int (*get_regs_len)(struct hnae_handle *handle);
+};
+
+struct hnae_ae_dev {
+ struct device cls_dev; /* the class dev */
+ struct device *dev; /* the presented dev */
+ struct hnae_ae_ops *ops;
+ struct list_head node;
+ struct module *owner; /* the module who provides this dev */
+ int id;
+ char name[AE_NAME_SIZE];
+ struct list_head handle_list;
+ spinlock_t lock; /* lock to protect the handle_list */
+};
+
+struct hnae_handle {
+ struct device *owner_dev; /* the device which make use of this handle */
+ struct hnae_ae_dev *dev; /* the device who provides this handle */
+ struct device_node *phy_node;
+ phy_interface_t phy_if;
+ u32 if_support;
+ int q_num;
+ int vf_id;
+ u32 eport_id;
+ enum hnae_port_type port_type;
+ struct list_head node; /* list to hnae_ae_dev->handle_list */
+ struct hnae_buf_ops *bops; /* operation for the buffer */
+ struct hnae_queue **qs; /* array base of all queues */
+};
+
+#define ring_to_dev(ring) ((ring)->q->dev->dev)
+
+struct hnae_handle *hnae_get_handle(struct device *owner_dev, const char *ae_id,
+ u32 port_id, struct hnae_buf_ops *bops);
+void hnae_put_handle(struct hnae_handle *handle);
+int hnae_ae_register(struct hnae_ae_dev *dev, struct module *owner);
+void hnae_ae_unregister(struct hnae_ae_dev *dev);
+
+int hnae_register_notifier(struct notifier_block *nb);
+void hnae_unregister_notifier(struct notifier_block *nb);
+int hnae_reinit_handle(struct hnae_handle *handle);
+
+#define hnae_queue_xmit(q, buf_num) writel_relaxed(buf_num, \
+ (q)->tx_ring.io_base + RCB_REG_TAIL)
+
+#ifndef assert
+#define assert(cond)
+#endif
+
+static inline int hnae_reserve_buffer_map(struct hnae_ring *ring,
+ struct hnae_desc_cb *cb)
+{
+ struct hnae_buf_ops *bops = ring->q->handle->bops;
+ int ret;
+
+ ret = bops->alloc_buffer(ring, cb);
+ if (ret)
+ goto out;
+
+ ret = bops->map_buffer(ring, cb);
+ if (ret)
+ goto out_with_buf;
+
+ return 0;
+
+out_with_buf:
+ bops->free_buffer(ring, cb);
+out:
+ return ret;
+}
+
+static inline int hnae_alloc_buffer_attach(struct hnae_ring *ring, int i)
+{
+ int ret = hnae_reserve_buffer_map(ring, &ring->desc_cb[i]);
+
+ if (ret)
+ return ret;
+
+ ring->desc[i].addr = (__le64)ring->desc_cb[i].dma;
+
+ return 0;
+}
+
+static inline void hnae_buffer_detach(struct hnae_ring *ring, int i)
+{
+ ring->q->handle->bops->unmap_buffer(ring, &ring->desc_cb[i]);
+ ring->desc[i].addr = 0;
+}
+
+static inline void hnae_free_buffer_detach(struct hnae_ring *ring, int i)
+{
+ struct hnae_buf_ops *bops = ring->q->handle->bops;
+ struct hnae_desc_cb *cb = &ring->desc_cb[i];
+
+ if (!ring->desc_cb[i].dma)
+ return;
+
+ hnae_buffer_detach(ring, i);
+ bops->free_buffer(ring, cb);
+}
+
+/* detach a in-used buffer and replace with a reserved one */
+static inline void hnae_replace_buffer(struct hnae_ring *ring, int i,
+ struct hnae_desc_cb *res_cb)
+{
+ struct hnae_buf_ops *bops = ring->q->handle->bops;
+ struct hnae_desc_cb tmp_cb = ring->desc_cb[i];
+
+ bops->unmap_buffer(ring, &ring->desc_cb[i]);
+ ring->desc_cb[i] = *res_cb;
+ *res_cb = tmp_cb;
+ ring->desc[i].addr = (__le64)ring->desc_cb[i].dma;
+ ring->desc[i].rx.ipoff_bnum_pid_flag = 0;
+}
+
+static inline void hnae_reuse_buffer(struct hnae_ring *ring, int i)
+{
+ ring->desc_cb[i].reuse_flag = 0;
+ ring->desc[i].addr = (__le64)(ring->desc_cb[i].dma
+ + ring->desc_cb[i].page_offset);
+ ring->desc[i].rx.ipoff_bnum_pid_flag = 0;
+}
+
+#define hnae_set_field(origin, mask, shift, val) \
+ do { \
+ (origin) &= (~(mask)); \
+ (origin) |= ((val) << (shift)) & (mask); \
+ } while (0)
+
+#define hnae_set_bit(origin, shift, val) \
+ hnae_set_field((origin), (0x1 << (shift)), (shift), (val))
+
+#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift))
+
+#define hnae_get_bit(origin, shift) \
+ hnae_get_field((origin), (0x1 << (shift)), (shift))
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
new file mode 100644
index 000000000000..1a16c0307b47
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+
+#include "hnae.h"
+#include "hns_dsaf_mac.h"
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_ppe.h"
+#include "hns_dsaf_rcb.h"
+
+#define AE_NAME_PORT_ID_IDX 6
+#define ETH_STATIC_REG 1
+#define ETH_DUMP_REG 5
+#define ETH_GSTRING_LEN 32
+
+static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle)
+{
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+
+ return vf_cb->mac_cb;
+}
+
+/**
+ * hns_ae_map_eport_to_dport - translate enet port id to dsaf port id
+ * @port_id: enet port id
+ *: debug port 0-1, service port 2 -7 (dsaf mode only 2)
+ * return: dsaf port id
+ *: service ports 0 - 5, debug port 6-7
+ **/
+static int hns_ae_map_eport_to_dport(u32 port_id)
+{
+ int port_index;
+
+ if (port_id < DSAF_DEBUG_NW_NUM)
+ port_index = port_id + DSAF_SERVICE_PORT_NUM_PER_DSAF;
+ else
+ port_index = port_id - DSAF_DEBUG_NW_NUM;
+
+ return port_index;
+}
+
+static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev)
+{
+ return container_of(dev, struct dsaf_device, ae_dev);
+}
+
+static struct hns_ppe_cb *hns_get_ppe_cb(struct hnae_handle *handle)
+{
+ int ppe_index;
+ int ppe_common_index;
+ struct ppe_common_cb *ppe_comm;
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+
+ if (vf_cb->port_index < DSAF_SERVICE_PORT_NUM_PER_DSAF) {
+ ppe_index = vf_cb->port_index;
+ ppe_common_index = 0;
+ } else {
+ ppe_index = 0;
+ ppe_common_index =
+ vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1;
+ }
+ ppe_comm = vf_cb->dsaf_dev->ppe_common[ppe_common_index];
+ return &ppe_comm->ppe_cb[ppe_index];
+}
+
+static int hns_ae_get_q_num_per_vf(
+ struct dsaf_device *dsaf_dev, int port)
+{
+ int common_idx = hns_dsaf_get_comm_idx_by_port(port);
+
+ return dsaf_dev->rcb_common[common_idx]->max_q_per_vf;
+}
+
+static int hns_ae_get_vf_num_per_port(
+ struct dsaf_device *dsaf_dev, int port)
+{
+ int common_idx = hns_dsaf_get_comm_idx_by_port(port);
+
+ return dsaf_dev->rcb_common[common_idx]->max_vfn;
+}
+
+static struct ring_pair_cb *hns_ae_get_base_ring_pair(
+ struct dsaf_device *dsaf_dev, int port)
+{
+ int common_idx = hns_dsaf_get_comm_idx_by_port(port);
+ struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[common_idx];
+ int q_num = rcb_comm->max_q_per_vf;
+ int vf_num = rcb_comm->max_vfn;
+
+ if (common_idx == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ return &rcb_comm->ring_pair_cb[port * q_num * vf_num];
+ else
+ return &rcb_comm->ring_pair_cb[0];
+}
+
+static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q)
+{
+ return container_of(q, struct ring_pair_cb, q);
+}
+
+struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev,
+ u32 port_id)
+{
+ int port_idx;
+ int vfnum_per_port;
+ int qnum_per_vf;
+ int i;
+ struct dsaf_device *dsaf_dev;
+ struct hnae_handle *ae_handle;
+ struct ring_pair_cb *ring_pair_cb;
+ struct hnae_vf_cb *vf_cb;
+
+ dsaf_dev = hns_ae_get_dsaf_dev(dev);
+ port_idx = hns_ae_map_eport_to_dport(port_id);
+
+ ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port_idx);
+ vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port_idx);
+ qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port_idx);
+
+ vf_cb = kzalloc(sizeof(*vf_cb) +
+ qnum_per_vf * sizeof(struct hnae_queue *), GFP_KERNEL);
+ if (unlikely(!vf_cb)) {
+ dev_err(dsaf_dev->dev, "malloc vf_cb fail!\n");
+ ae_handle = ERR_PTR(-ENOMEM);
+ goto handle_err;
+ }
+ ae_handle = &vf_cb->ae_handle;
+ /* ae_handle Init */
+ ae_handle->owner_dev = dsaf_dev->dev;
+ ae_handle->dev = dev;
+ ae_handle->q_num = qnum_per_vf;
+
+ /* find ring pair, and set vf id*/
+ for (ae_handle->vf_id = 0;
+ ae_handle->vf_id < vfnum_per_port; ae_handle->vf_id++) {
+ if (!ring_pair_cb->used_by_vf)
+ break;
+ ring_pair_cb += qnum_per_vf;
+ }
+ if (ae_handle->vf_id >= vfnum_per_port) {
+ dev_err(dsaf_dev->dev, "malloc queue fail!\n");
+ ae_handle = ERR_PTR(-EINVAL);
+ goto vf_id_err;
+ }
+
+ ae_handle->qs = (struct hnae_queue **)(&ae_handle->qs + 1);
+ for (i = 0; i < qnum_per_vf; i++) {
+ ae_handle->qs[i] = &ring_pair_cb->q;
+ ae_handle->qs[i]->rx_ring.q = ae_handle->qs[i];
+ ae_handle->qs[i]->tx_ring.q = ae_handle->qs[i];
+
+ ring_pair_cb->used_by_vf = 1;
+ if (port_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF)
+ ring_pair_cb->port_id_in_dsa = port_idx;
+ else
+ ring_pair_cb->port_id_in_dsa = 0;
+
+ ring_pair_cb++;
+ }
+
+ vf_cb->dsaf_dev = dsaf_dev;
+ vf_cb->port_index = port_idx;
+ vf_cb->mac_cb = &dsaf_dev->mac_cb[port_idx];
+
+ ae_handle->phy_if = vf_cb->mac_cb->phy_if;
+ ae_handle->phy_node = vf_cb->mac_cb->phy_node;
+ ae_handle->if_support = vf_cb->mac_cb->if_support;
+ ae_handle->port_type = vf_cb->mac_cb->mac_type;
+
+ return ae_handle;
+vf_id_err:
+ kfree(vf_cb);
+handle_err:
+ return ae_handle;
+}
+
+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;
+}
+
+static void hns_ae_ring_enable_all(struct hnae_handle *handle, int val)
+{
+ int q_num = handle->q_num;
+ int i;
+
+ for (i = 0; i < q_num; i++)
+ hns_rcb_ring_enable_hw(handle->qs[i], val);
+}
+
+static void hns_ae_init_queue(struct hnae_queue *q)
+{
+ struct ring_pair_cb *ring =
+ container_of(q, struct ring_pair_cb, q);
+
+ hns_rcb_init_hw(ring);
+}
+
+static void hns_ae_fini_queue(struct hnae_queue *q)
+{
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(q->handle);
+
+ if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE)
+ hns_rcb_reset_ring_hw(q);
+}
+
+static int hns_ae_set_mac_address(struct hnae_handle *handle, void *p)
+{
+ int ret;
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ if (!p || !is_valid_ether_addr((const u8 *)p)) {
+ dev_err(handle->owner_dev, "is not valid ether addr !\n");
+ return -EADDRNOTAVAIL;
+ }
+
+ ret = hns_mac_change_vf_addr(mac_cb, handle->vf_id, p);
+ if (ret != 0) {
+ dev_err(handle->owner_dev,
+ "set_mac_address fail, ret=%d!\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr)
+{
+ int ret;
+ char *mac_addr = (char *)addr;
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ assert(mac_cb);
+
+ if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+ return 0;
+
+ ret = hns_mac_set_multi(mac_cb, mac_cb->mac_id, mac_addr, ENABLE);
+ if (ret) {
+ dev_err(handle->owner_dev,
+ "mac add mul_mac:%pM port%d fail, ret = %#x!\n",
+ mac_addr, mac_cb->mac_id, ret);
+ return ret;
+ }
+
+ ret = hns_mac_set_multi(mac_cb, DSAF_BASE_INNER_PORT_NUM,
+ mac_addr, ENABLE);
+ if (ret)
+ dev_err(handle->owner_dev,
+ "mac add mul_mac:%pM port%d fail, ret = %#x!\n",
+ mac_addr, DSAF_BASE_INNER_PORT_NUM, ret);
+
+ return ret;
+}
+
+static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ return hns_mac_set_mtu(mac_cb, new_mtu);
+}
+
+static int hns_ae_start(struct hnae_handle *handle)
+{
+ int ret;
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ ret = hns_mac_vm_config_bc_en(mac_cb, 0, ENABLE);
+ if (ret)
+ return ret;
+
+ hns_ae_ring_enable_all(handle, 1);
+ msleep(100);
+
+ hns_mac_start(mac_cb);
+
+ return 0;
+}
+
+void hns_ae_stop(struct hnae_handle *handle)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ /* just clean tx fbd, neednot rx fbd*/
+ hns_rcb_wait_fbd_clean(handle->qs, handle->q_num, RCB_INT_FLAG_TX);
+
+ msleep(20);
+
+ hns_mac_stop(mac_cb);
+
+ usleep_range(10000, 20000);
+
+ hns_ae_ring_enable_all(handle, 0);
+
+ (void)hns_mac_vm_config_bc_en(mac_cb, 0, DISABLE);
+}
+
+static void hns_ae_reset(struct hnae_handle *handle)
+{
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+
+ if (vf_cb->mac_cb->mac_type == HNAE_PORT_DEBUG) {
+ u8 ppe_common_index =
+ vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1;
+
+ hns_mac_reset(vf_cb->mac_cb);
+ hns_ppe_reset_common(vf_cb->dsaf_dev, ppe_common_index);
+ }
+}
+
+void hns_ae_toggle_ring_irq(struct hnae_ring *ring, u32 mask)
+{
+ u32 flag;
+
+ if (is_tx_ring(ring))
+ flag = RCB_INT_FLAG_TX;
+ else
+ flag = RCB_INT_FLAG_RX;
+
+ hns_rcb_int_clr_hw(ring->q, flag);
+ hns_rcb_int_ctrl_hw(ring->q, flag, mask);
+}
+
+static void hns_ae_toggle_queue_status(struct hnae_queue *queue, u32 val)
+{
+ hns_rcb_start(queue, val);
+}
+
+static int hns_ae_get_link_status(struct hnae_handle *handle)
+{
+ u32 link_status;
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ hns_mac_get_link_status(mac_cb, &link_status);
+
+ return !!link_status;
+}
+
+static int hns_ae_get_mac_info(struct hnae_handle *handle,
+ u8 *auto_neg, u16 *speed, u8 *duplex)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ return hns_mac_get_port_info(mac_cb, auto_neg, speed, duplex);
+}
+
+static void hns_ae_adjust_link(struct hnae_handle *handle, int speed,
+ int duplex)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ hns_mac_adjust_link(mac_cb, speed, duplex);
+}
+
+static void hns_ae_get_ring_bdnum_limit(struct hnae_queue *queue,
+ u32 *uplimit)
+{
+ *uplimit = HNS_RCB_RING_MAX_PENDING_BD;
+}
+
+static void hns_ae_get_pauseparam(struct hnae_handle *handle,
+ u32 *auto_neg, u32 *rx_en, u32 *tx_en)
+{
+ assert(handle);
+
+ hns_mac_get_autoneg(hns_get_mac_cb(handle), auto_neg);
+
+ hns_mac_get_pauseparam(hns_get_mac_cb(handle), rx_en, tx_en);
+}
+
+static int hns_ae_set_autoneg(struct hnae_handle *handle, u8 enable)
+{
+ assert(handle);
+
+ return hns_mac_set_autoneg(hns_get_mac_cb(handle), enable);
+}
+
+static void hns_ae_set_promisc_mode(struct hnae_handle *handle, u32 en)
+{
+ hns_dsaf_set_promisc_mode(hns_ae_get_dsaf_dev(handle->dev), en);
+}
+
+static int hns_ae_get_autoneg(struct hnae_handle *handle)
+{
+ u32 auto_neg;
+
+ assert(handle);
+
+ hns_mac_get_autoneg(hns_get_mac_cb(handle), &auto_neg);
+
+ return auto_neg;
+}
+
+static int hns_ae_set_pauseparam(struct hnae_handle *handle,
+ u32 autoneg, u32 rx_en, u32 tx_en)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+ int ret;
+
+ ret = hns_mac_set_autoneg(mac_cb, autoneg);
+ if (ret)
+ return ret;
+
+ return hns_mac_set_pauseparam(mac_cb, rx_en, tx_en);
+}
+
+static void hns_ae_get_coalesce_usecs(struct hnae_handle *handle,
+ u32 *tx_usecs, u32 *rx_usecs)
+{
+ int port;
+
+ port = hns_ae_map_eport_to_dport(handle->eport_id);
+
+ *tx_usecs = hns_rcb_get_coalesce_usecs(
+ hns_ae_get_dsaf_dev(handle->dev),
+ hns_dsaf_get_comm_idx_by_port(port));
+ *rx_usecs = hns_rcb_get_coalesce_usecs(
+ hns_ae_get_dsaf_dev(handle->dev),
+ hns_dsaf_get_comm_idx_by_port(port));
+}
+
+static void hns_ae_get_rx_max_coalesced_frames(struct hnae_handle *handle,
+ u32 *tx_frames, u32 *rx_frames)
+{
+ int port;
+
+ assert(handle);
+
+ port = hns_ae_map_eport_to_dport(handle->eport_id);
+
+ *tx_frames = hns_rcb_get_coalesced_frames(
+ hns_ae_get_dsaf_dev(handle->dev), port);
+ *rx_frames = hns_rcb_get_coalesced_frames(
+ hns_ae_get_dsaf_dev(handle->dev), port);
+}
+
+static void hns_ae_set_coalesce_usecs(struct hnae_handle *handle,
+ u32 timeout)
+{
+ int port;
+
+ assert(handle);
+
+ port = hns_ae_map_eport_to_dport(handle->eport_id);
+
+ hns_rcb_set_coalesce_usecs(hns_ae_get_dsaf_dev(handle->dev),
+ port, timeout);
+}
+
+static int hns_ae_set_coalesce_frames(struct hnae_handle *handle,
+ u32 coalesce_frames)
+{
+ int port;
+ int ret;
+
+ assert(handle);
+
+ port = hns_ae_map_eport_to_dport(handle->eport_id);
+
+ ret = hns_rcb_set_coalesced_frames(hns_ae_get_dsaf_dev(handle->dev),
+ port, coalesce_frames);
+ return ret;
+}
+
+void hns_ae_update_stats(struct hnae_handle *handle,
+ struct net_device_stats *net_stats)
+{
+ int port;
+ int idx;
+ struct dsaf_device *dsaf_dev;
+ struct hns_mac_cb *mac_cb;
+ struct hns_ppe_cb *ppe_cb;
+ struct hnae_queue *queue;
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+ u64 tx_bytes = 0, rx_bytes = 0, tx_packets = 0, rx_packets = 0;
+ u64 rx_errors = 0, tx_errors = 0, tx_dropped = 0;
+ u64 rx_missed_errors = 0;
+
+ dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
+ if (!dsaf_dev)
+ return;
+ port = vf_cb->port_index;
+ ppe_cb = hns_get_ppe_cb(handle);
+ mac_cb = hns_get_mac_cb(handle);
+
+ for (idx = 0; idx < handle->q_num; idx++) {
+ queue = handle->qs[idx];
+ hns_rcb_update_stats(queue);
+
+ tx_bytes += queue->tx_ring.stats.tx_bytes;
+ tx_packets += queue->tx_ring.stats.tx_pkts;
+ rx_bytes += queue->rx_ring.stats.rx_bytes;
+ rx_packets += queue->rx_ring.stats.rx_pkts;
+
+ rx_errors += queue->rx_ring.stats.err_pkt_len
+ + queue->rx_ring.stats.l2_err
+ + queue->rx_ring.stats.l3l4_csum_err;
+ }
+
+ hns_ppe_update_stats(ppe_cb);
+ rx_missed_errors = ppe_cb->hw_stats.rx_drop_no_buf;
+ tx_errors += ppe_cb->hw_stats.tx_err_checksum
+ + ppe_cb->hw_stats.tx_err_fifo_empty;
+
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE) {
+ hns_dsaf_update_stats(dsaf_dev, port);
+ /* for port upline direction, i.e., rx. */
+ rx_missed_errors += dsaf_dev->hw_stats[port].bp_drop;
+ rx_missed_errors += dsaf_dev->hw_stats[port].pad_drop;
+ rx_missed_errors += dsaf_dev->hw_stats[port].crc_false;
+
+ /* for port downline direction, i.e., tx. */
+ port = port + DSAF_PPE_INODE_BASE;
+ hns_dsaf_update_stats(dsaf_dev, port);
+ tx_dropped += dsaf_dev->hw_stats[port].bp_drop;
+ tx_dropped += dsaf_dev->hw_stats[port].pad_drop;
+ tx_dropped += dsaf_dev->hw_stats[port].crc_false;
+ tx_dropped += dsaf_dev->hw_stats[port].rslt_drop;
+ tx_dropped += dsaf_dev->hw_stats[port].vlan_drop;
+ tx_dropped += dsaf_dev->hw_stats[port].stp_drop;
+ }
+
+ hns_mac_update_stats(mac_cb);
+ rx_errors += mac_cb->hw_stats.rx_fifo_overrun_err;
+
+ tx_errors += mac_cb->hw_stats.tx_bad_pkts
+ + mac_cb->hw_stats.tx_fragment_err
+ + mac_cb->hw_stats.tx_jabber_err
+ + mac_cb->hw_stats.tx_underrun_err
+ + mac_cb->hw_stats.tx_crc_err;
+
+ net_stats->tx_bytes = tx_bytes;
+ net_stats->tx_packets = tx_packets;
+ net_stats->rx_bytes = rx_bytes;
+ net_stats->rx_dropped = 0;
+ net_stats->rx_packets = rx_packets;
+ net_stats->rx_errors = rx_errors;
+ net_stats->tx_errors = tx_errors;
+ net_stats->tx_dropped = tx_dropped;
+ net_stats->rx_missed_errors = rx_missed_errors;
+ net_stats->rx_crc_errors = mac_cb->hw_stats.rx_fcs_err;
+ net_stats->rx_frame_errors = mac_cb->hw_stats.rx_align_err;
+ net_stats->rx_fifo_errors = mac_cb->hw_stats.rx_fifo_overrun_err;
+ net_stats->rx_length_errors = mac_cb->hw_stats.rx_len_err;
+ net_stats->multicast = mac_cb->hw_stats.rx_mc_pkts;
+}
+
+void hns_ae_get_stats(struct hnae_handle *handle, u64 *data)
+{
+ int idx;
+ struct hns_mac_cb *mac_cb;
+ struct hns_ppe_cb *ppe_cb;
+ u64 *p = data;
+ struct hnae_vf_cb *vf_cb;
+
+ if (!handle || !data) {
+ pr_err("hns_ae_get_stats NULL handle or data pointer!\n");
+ return;
+ }
+
+ vf_cb = hns_ae_get_vf_cb(handle);
+ mac_cb = hns_get_mac_cb(handle);
+ ppe_cb = hns_get_ppe_cb(handle);
+
+ for (idx = 0; idx < handle->q_num; idx++) {
+ hns_rcb_get_stats(handle->qs[idx], p);
+ p += hns_rcb_get_ring_sset_count((int)ETH_SS_STATS);
+ }
+
+ hns_ppe_get_stats(ppe_cb, p);
+ p += hns_ppe_get_sset_count((int)ETH_SS_STATS);
+
+ hns_mac_get_stats(mac_cb, p);
+ p += hns_mac_get_sset_count(mac_cb, (int)ETH_SS_STATS);
+
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE)
+ hns_dsaf_get_stats(vf_cb->dsaf_dev, p, vf_cb->port_index);
+}
+
+void hns_ae_get_strings(struct hnae_handle *handle,
+ u32 stringset, u8 *data)
+{
+ int port;
+ int idx;
+ struct hns_mac_cb *mac_cb;
+ struct hns_ppe_cb *ppe_cb;
+ u8 *p = data;
+ struct hnae_vf_cb *vf_cb;
+
+ assert(handle);
+
+ vf_cb = hns_ae_get_vf_cb(handle);
+ port = vf_cb->port_index;
+ mac_cb = hns_get_mac_cb(handle);
+ ppe_cb = hns_get_ppe_cb(handle);
+
+ for (idx = 0; idx < handle->q_num; idx++) {
+ hns_rcb_get_strings(stringset, p, idx);
+ p += ETH_GSTRING_LEN * hns_rcb_get_ring_sset_count(stringset);
+ }
+
+ hns_ppe_get_strings(ppe_cb, stringset, p);
+ p += ETH_GSTRING_LEN * hns_ppe_get_sset_count(stringset);
+
+ hns_mac_get_strings(mac_cb, stringset, p);
+ p += ETH_GSTRING_LEN * hns_mac_get_sset_count(mac_cb, stringset);
+
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE)
+ hns_dsaf_get_strings(stringset, p, port);
+}
+
+int hns_ae_get_sset_count(struct hnae_handle *handle, int stringset)
+{
+ u32 sset_count = 0;
+ struct hns_mac_cb *mac_cb;
+
+ assert(handle);
+
+ mac_cb = hns_get_mac_cb(handle);
+
+ sset_count += hns_rcb_get_ring_sset_count(stringset) * handle->q_num;
+ sset_count += hns_ppe_get_sset_count(stringset);
+ sset_count += hns_mac_get_sset_count(mac_cb, stringset);
+
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE)
+ sset_count += hns_dsaf_get_sset_count(stringset);
+
+ return sset_count;
+}
+
+static int hns_ae_config_loopback(struct hnae_handle *handle,
+ enum hnae_loop loop, int en)
+{
+ int ret;
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+
+ switch (loop) {
+ case MAC_INTERNALLOOP_SERDES:
+ ret = hns_mac_config_sds_loopback(vf_cb->mac_cb, en);
+ break;
+ case MAC_INTERNALLOOP_MAC:
+ ret = hns_mac_config_mac_loopback(vf_cb->mac_cb, loop, en);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+void hns_ae_update_led_status(struct hnae_handle *handle)
+{
+ struct hns_mac_cb *mac_cb;
+
+ assert(handle);
+ mac_cb = hns_get_mac_cb(handle);
+ if (!mac_cb->cpld_vaddr)
+ return;
+ hns_set_led_opt(mac_cb);
+}
+
+int hns_ae_cpld_set_led_id(struct hnae_handle *handle,
+ enum hnae_led_state status)
+{
+ struct hns_mac_cb *mac_cb;
+
+ assert(handle);
+
+ mac_cb = hns_get_mac_cb(handle);
+
+ return hns_cpld_led_set_id(mac_cb, status);
+}
+
+void hns_ae_get_regs(struct hnae_handle *handle, void *data)
+{
+ u32 *p = data;
+ u32 rcb_com_idx;
+ int i;
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+ struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle);
+
+ hns_ppe_get_regs(ppe_cb, p);
+ p += hns_ppe_get_regs_count();
+
+ rcb_com_idx = hns_dsaf_get_comm_idx_by_port(vf_cb->port_index);
+ hns_rcb_get_common_regs(vf_cb->dsaf_dev->rcb_common[rcb_com_idx], p);
+ p += hns_rcb_get_common_regs_count();
+
+ for (i = 0; i < handle->q_num; i++) {
+ hns_rcb_get_ring_regs(handle->qs[i], p);
+ p += hns_rcb_get_ring_regs_count();
+ }
+
+ hns_mac_get_regs(vf_cb->mac_cb, p);
+ p += hns_mac_get_regs_count(vf_cb->mac_cb);
+
+ if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE)
+ hns_dsaf_get_regs(vf_cb->dsaf_dev, vf_cb->port_index, p);
+}
+
+int hns_ae_get_regs_len(struct hnae_handle *handle)
+{
+ u32 total_num;
+ struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+
+ total_num = hns_ppe_get_regs_count();
+ total_num += hns_rcb_get_common_regs_count();
+ total_num += hns_rcb_get_ring_regs_count() * handle->q_num;
+ total_num += hns_mac_get_regs_count(vf_cb->mac_cb);
+
+ if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE)
+ total_num += hns_dsaf_get_regs_count();
+
+ return total_num;
+}
+
+static struct hnae_ae_ops hns_dsaf_ops = {
+ .get_handle = hns_ae_get_handle,
+ .put_handle = hns_ae_put_handle,
+ .init_queue = hns_ae_init_queue,
+ .fini_queue = hns_ae_fini_queue,
+ .start = hns_ae_start,
+ .stop = hns_ae_stop,
+ .reset = hns_ae_reset,
+ .toggle_ring_irq = hns_ae_toggle_ring_irq,
+ .toggle_queue_status = hns_ae_toggle_queue_status,
+ .get_status = hns_ae_get_link_status,
+ .get_info = hns_ae_get_mac_info,
+ .adjust_link = hns_ae_adjust_link,
+ .set_loopback = hns_ae_config_loopback,
+ .get_ring_bdnum_limit = hns_ae_get_ring_bdnum_limit,
+ .get_pauseparam = hns_ae_get_pauseparam,
+ .set_autoneg = hns_ae_set_autoneg,
+ .get_autoneg = hns_ae_get_autoneg,
+ .set_pauseparam = hns_ae_set_pauseparam,
+ .get_coalesce_usecs = hns_ae_get_coalesce_usecs,
+ .get_rx_max_coalesced_frames = hns_ae_get_rx_max_coalesced_frames,
+ .set_coalesce_usecs = hns_ae_set_coalesce_usecs,
+ .set_coalesce_frames = hns_ae_set_coalesce_frames,
+ .set_promisc_mode = hns_ae_set_promisc_mode,
+ .set_mac_addr = hns_ae_set_mac_address,
+ .set_mc_addr = hns_ae_set_multicast_one,
+ .set_mtu = hns_ae_set_mtu,
+ .update_stats = hns_ae_update_stats,
+ .get_stats = hns_ae_get_stats,
+ .get_strings = hns_ae_get_strings,
+ .get_sset_count = hns_ae_get_sset_count,
+ .update_led_status = hns_ae_update_led_status,
+ .set_led_id = hns_ae_cpld_set_led_id,
+ .get_regs = hns_ae_get_regs,
+ .get_regs_len = hns_ae_get_regs_len
+};
+
+int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev)
+{
+ struct hnae_ae_dev *ae_dev = &dsaf_dev->ae_dev;
+
+ ae_dev->ops = &hns_dsaf_ops;
+ ae_dev->dev = dsaf_dev->dev;
+
+ return hnae_ae_register(ae_dev, THIS_MODULE);
+}
+
+void hns_dsaf_ae_uninit(struct dsaf_device *dsaf_dev)
+{
+ hnae_ae_unregister(&dsaf_dev->ae_dev);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
new file mode 100644
index 000000000000..b8517b00e706
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/delay.h>
+#include <linux/of_mdio.h>
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_mac.h"
+#include "hns_dsaf_gmac.h"
+
+static const struct mac_stats_string g_gmac_stats_string[] = {
+ {"gmac_rx_octets_total_ok", MAC_STATS_FIELD_OFF(rx_good_bytes)},
+ {"gmac_rx_octets_bad", MAC_STATS_FIELD_OFF(rx_bad_bytes)},
+ {"gmac_rx_uc_pkts", MAC_STATS_FIELD_OFF(rx_uc_pkts)},
+ {"gamc_rx_mc_pkts", MAC_STATS_FIELD_OFF(rx_mc_pkts)},
+ {"gmac_rx_bc_pkts", MAC_STATS_FIELD_OFF(rx_bc_pkts)},
+ {"gmac_rx_pkts_64octets", MAC_STATS_FIELD_OFF(rx_64bytes)},
+ {"gmac_rx_pkts_65to127", MAC_STATS_FIELD_OFF(rx_65to127)},
+ {"gmac_rx_pkts_128to255", MAC_STATS_FIELD_OFF(rx_128to255)},
+ {"gmac_rx_pkts_256to511", MAC_STATS_FIELD_OFF(rx_256to511)},
+ {"gmac_rx_pkts_512to1023", MAC_STATS_FIELD_OFF(rx_512to1023)},
+ {"gmac_rx_pkts_1024to1518", MAC_STATS_FIELD_OFF(rx_1024to1518)},
+ {"gmac_rx_pkts_1519tomax", MAC_STATS_FIELD_OFF(rx_1519tomax)},
+ {"gmac_rx_fcs_errors", MAC_STATS_FIELD_OFF(rx_fcs_err)},
+ {"gmac_rx_tagged", MAC_STATS_FIELD_OFF(rx_vlan_pkts)},
+ {"gmac_rx_data_err", MAC_STATS_FIELD_OFF(rx_data_err)},
+ {"gmac_rx_align_errors", MAC_STATS_FIELD_OFF(rx_align_err)},
+ {"gmac_rx_long_errors", MAC_STATS_FIELD_OFF(rx_oversize)},
+ {"gmac_rx_jabber_errors", MAC_STATS_FIELD_OFF(rx_jabber_err)},
+ {"gmac_rx_pause_maccontrol", MAC_STATS_FIELD_OFF(rx_pfc_tc0)},
+ {"gmac_rx_unknown_maccontrol", MAC_STATS_FIELD_OFF(rx_unknown_ctrl)},
+ {"gmac_rx_very_long_err", MAC_STATS_FIELD_OFF(rx_long_err)},
+ {"gmac_rx_runt_err", MAC_STATS_FIELD_OFF(rx_minto64)},
+ {"gmac_rx_short_err", MAC_STATS_FIELD_OFF(rx_under_min)},
+ {"gmac_rx_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_bytes)},
+ {"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_pkts)},
+ {"gmac_rx_overrun_cnt", MAC_STATS_FIELD_OFF(rx_fifo_overrun_err)},
+ {"gmac_rx_length_err", MAC_STATS_FIELD_OFF(rx_len_err)},
+ {"gmac_rx_fail_comma", MAC_STATS_FIELD_OFF(rx_comma_err)},
+
+ {"gmac_tx_octets_ok", MAC_STATS_FIELD_OFF(tx_good_bytes)},
+ {"gmac_tx_octets_bad", MAC_STATS_FIELD_OFF(tx_bad_bytes)},
+ {"gmac_tx_uc_pkts", MAC_STATS_FIELD_OFF(tx_uc_pkts)},
+ {"gmac_tx_mc_pkts", MAC_STATS_FIELD_OFF(tx_mc_pkts)},
+ {"gmac_tx_bc_pkts", MAC_STATS_FIELD_OFF(tx_bc_pkts)},
+ {"gmac_tx_pkts_64octets", MAC_STATS_FIELD_OFF(tx_64bytes)},
+ {"gmac_tx_pkts_65to127", MAC_STATS_FIELD_OFF(tx_65to127)},
+ {"gmac_tx_pkts_128to255", MAC_STATS_FIELD_OFF(tx_128to255)},
+ {"gmac_tx_pkts_256to511", MAC_STATS_FIELD_OFF(tx_256to511)},
+ {"gmac_tx_pkts_512to1023", MAC_STATS_FIELD_OFF(tx_512to1023)},
+ {"gmac_tx_pkts_1024to1518", MAC_STATS_FIELD_OFF(tx_1024to1518)},
+ {"gmac_tx_pkts_1519tomax", MAC_STATS_FIELD_OFF(tx_1519tomax)},
+ {"gmac_tx_excessive_length_drop", MAC_STATS_FIELD_OFF(tx_jabber_err)},
+ {"gmac_tx_underrun", MAC_STATS_FIELD_OFF(tx_underrun_err)},
+ {"gmac_tx_tagged", MAC_STATS_FIELD_OFF(tx_vlan)},
+ {"gmac_tx_crc_error", MAC_STATS_FIELD_OFF(tx_crc_err)},
+ {"gmac_tx_pause_frames", MAC_STATS_FIELD_OFF(tx_pfc_tc0)}
+};
+
+static void hns_gmac_enable(void *mac_drv, enum mac_commom_mode mode)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ /*enable GE rX/tX */
+ if ((mode == MAC_COMM_MODE_TX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+ dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_TX_EN_B, 1);
+
+ if ((mode == MAC_COMM_MODE_RX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+ dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 1);
+}
+
+static void hns_gmac_disable(void *mac_drv, enum mac_commom_mode mode)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ /*disable GE rX/tX */
+ if ((mode == MAC_COMM_MODE_TX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+ dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_TX_EN_B, 0);
+
+ if ((mode == MAC_COMM_MODE_RX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+ dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 0);
+}
+
+/**
+*hns_gmac_get_en - get port enable
+*@mac_drv:mac device
+*@rx:rx enable
+*@tx:tx enable
+*/
+static void hns_gmac_get_en(void *mac_drv, u32 *rx, u32 *tx)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ u32 porten;
+
+ porten = dsaf_read_dev(drv, GMAC_PORT_EN_REG);
+ *tx = dsaf_get_bit(porten, GMAC_PORT_TX_EN_B);
+ *rx = dsaf_get_bit(porten, GMAC_PORT_RX_EN_B);
+}
+
+static void hns_gmac_free(void *mac_drv)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct dsaf_device *dsaf_dev
+ = (struct dsaf_device *)dev_get_drvdata(drv->dev);
+
+ u32 mac_id = drv->mac_id;
+
+ hns_dsaf_ge_srst_by_port(dsaf_dev, mac_id, 0);
+}
+
+static void hns_gmac_set_tx_auto_pause_frames(void *mac_drv, u16 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_field(drv, GMAC_FC_TX_TIMER_REG, GMAC_FC_TX_TIMER_M,
+ GMAC_FC_TX_TIMER_S, newval);
+}
+
+static void hns_gmac_get_tx_auto_pause_frames(void *mac_drv, u16 *newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *newval = dsaf_get_dev_field(drv, GMAC_FC_TX_TIMER_REG,
+ GMAC_FC_TX_TIMER_M, GMAC_FC_TX_TIMER_S);
+}
+
+static void hns_gmac_set_rx_auto_pause_frames(void *mac_drv, u32 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_bit(drv, GMAC_PAUSE_EN_REG,
+ GMAC_PAUSE_EN_RX_FDFC_B, !!newval);
+}
+
+static void hns_gmac_config_max_frame_length(void *mac_drv, u16 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_field(drv, GMAC_MAX_FRM_SIZE_REG, GMAC_MAX_FRM_SIZE_M,
+ GMAC_MAX_FRM_SIZE_S, newval);
+
+ dsaf_set_dev_field(drv, GAMC_RX_MAX_FRAME, GMAC_MAX_FRM_SIZE_M,
+ GMAC_MAX_FRM_SIZE_S, newval);
+}
+
+static void hns_gmac_config_an_mode(void *mac_drv, u8 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_bit(drv, GMAC_TRANSMIT_CONTROL_REG,
+ GMAC_TX_AN_EN_B, !!newval);
+}
+
+static void hns_gmac_tx_loop_pkt_dis(void *mac_drv)
+{
+ u32 tx_loop_pkt_pri;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ tx_loop_pkt_pri = dsaf_read_dev(drv, GMAC_TX_LOOP_PKT_PRI_REG);
+ dsaf_set_bit(tx_loop_pkt_pri, GMAC_TX_LOOP_PKT_EN_B, 1);
+ dsaf_set_bit(tx_loop_pkt_pri, GMAC_TX_LOOP_PKT_HIG_PRI_B, 0);
+ dsaf_write_dev(drv, GMAC_TX_LOOP_PKT_PRI_REG, tx_loop_pkt_pri);
+}
+
+static void hns_gmac_set_duplex_type(void *mac_drv, u8 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_bit(drv, GMAC_DUPLEX_TYPE_REG,
+ GMAC_DUPLEX_TYPE_B, !!newval);
+}
+
+static void hns_gmac_get_duplex_type(void *mac_drv,
+ enum hns_gmac_duplex_mdoe *duplex_mode)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *duplex_mode = (enum hns_gmac_duplex_mdoe)dsaf_get_dev_bit(
+ drv, GMAC_DUPLEX_TYPE_REG, GMAC_DUPLEX_TYPE_B);
+}
+
+static void hns_gmac_get_port_mode(void *mac_drv, enum hns_port_mode *port_mode)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *port_mode = (enum hns_port_mode)dsaf_get_dev_field(
+ drv, GMAC_PORT_MODE_REG, GMAC_PORT_MODE_M, GMAC_PORT_MODE_S);
+}
+
+static void hns_gmac_port_mode_get(void *mac_drv,
+ struct hns_gmac_port_mode_cfg *port_mode)
+{
+ u32 tx_ctrl;
+ u32 recv_ctrl;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ port_mode->port_mode = (enum hns_port_mode)dsaf_get_dev_field(
+ drv, GMAC_PORT_MODE_REG, GMAC_PORT_MODE_M, GMAC_PORT_MODE_S);
+
+ tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
+ recv_ctrl = dsaf_read_dev(drv, GMAC_RECV_CONTROL_REG);
+
+ port_mode->max_frm_size =
+ dsaf_get_dev_field(drv, GMAC_MAX_FRM_SIZE_REG,
+ GMAC_MAX_FRM_SIZE_M, GMAC_MAX_FRM_SIZE_S);
+ port_mode->short_runts_thr =
+ dsaf_get_dev_field(drv, GMAC_SHORT_RUNTS_THR_REG,
+ GMAC_SHORT_RUNTS_THR_M,
+ GMAC_SHORT_RUNTS_THR_S);
+
+ port_mode->pad_enable = dsaf_get_bit(tx_ctrl, GMAC_TX_PAD_EN_B);
+ port_mode->crc_add = dsaf_get_bit(tx_ctrl, GMAC_TX_CRC_ADD_B);
+ port_mode->an_enable = dsaf_get_bit(tx_ctrl, GMAC_TX_AN_EN_B);
+
+ port_mode->runt_pkt_en =
+ dsaf_get_bit(recv_ctrl, GMAC_RECV_CTRL_RUNT_PKT_EN_B);
+ port_mode->strip_pad_en =
+ dsaf_get_bit(recv_ctrl, GMAC_RECV_CTRL_STRIP_PAD_EN_B);
+}
+
+static void hns_gmac_pause_frm_cfg(void *mac_drv, u32 rx_pause_en,
+ u32 tx_pause_en)
+{
+ u32 pause_en;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ pause_en = dsaf_read_dev(drv, GMAC_PAUSE_EN_REG);
+ dsaf_set_bit(pause_en, GMAC_PAUSE_EN_RX_FDFC_B, !!rx_pause_en);
+ dsaf_set_bit(pause_en, GMAC_PAUSE_EN_TX_FDFC_B, !!tx_pause_en);
+ dsaf_write_dev(drv, GMAC_PAUSE_EN_REG, pause_en);
+}
+
+static void hns_gmac_get_pausefrm_cfg(void *mac_drv, u32 *rx_pause_en,
+ u32 *tx_pause_en)
+{
+ u32 pause_en;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ pause_en = dsaf_read_dev(drv, GMAC_PAUSE_EN_REG);
+
+ *rx_pause_en = dsaf_get_bit(pause_en, GMAC_PAUSE_EN_RX_FDFC_B);
+ *tx_pause_en = dsaf_get_bit(pause_en, GMAC_PAUSE_EN_TX_FDFC_B);
+}
+
+static int hns_gmac_adjust_link(void *mac_drv, enum mac_speed speed,
+ u32 full_duplex)
+{
+ u32 tx_ctrl;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_bit(drv, GMAC_DUPLEX_TYPE_REG,
+ GMAC_DUPLEX_TYPE_B, !!full_duplex);
+
+ switch (speed) {
+ case MAC_SPEED_10:
+ dsaf_set_dev_field(
+ drv, GMAC_PORT_MODE_REG,
+ GMAC_PORT_MODE_M, GMAC_PORT_MODE_S, 0x6);
+ break;
+ case MAC_SPEED_100:
+ dsaf_set_dev_field(
+ drv, GMAC_PORT_MODE_REG,
+ GMAC_PORT_MODE_M, GMAC_PORT_MODE_S, 0x7);
+ break;
+ case MAC_SPEED_1000:
+ dsaf_set_dev_field(
+ drv, GMAC_PORT_MODE_REG,
+ GMAC_PORT_MODE_M, GMAC_PORT_MODE_S, 0x8);
+ break;
+ default:
+ dev_err(drv->dev,
+ "hns_gmac_adjust_link fail, speed%d mac%d\n",
+ speed, drv->mac_id);
+ return -EINVAL;
+ }
+
+ tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
+ dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, 1);
+ dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, 1);
+ dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl);
+
+ dsaf_set_dev_bit(drv, GMAC_MODE_CHANGE_EN_REG,
+ GMAC_MODE_CHANGE_EB_B, 1);
+
+ return 0;
+}
+
+static void hns_gmac_init(void *mac_drv)
+{
+ u32 port;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct dsaf_device *dsaf_dev
+ = (struct dsaf_device *)dev_get_drvdata(drv->dev);
+
+ port = drv->mac_id;
+
+ hns_dsaf_ge_srst_by_port(dsaf_dev, port, 0);
+ mdelay(10);
+ hns_dsaf_ge_srst_by_port(dsaf_dev, port, 1);
+ mdelay(10);
+ hns_gmac_disable(mac_drv, MAC_COMM_MODE_RX_AND_TX);
+ hns_gmac_tx_loop_pkt_dis(mac_drv);
+}
+
+void hns_gmac_update_stats(void *mac_drv)
+{
+ struct mac_hw_stats *hw_stats = NULL;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ hw_stats = &drv->mac_cb->hw_stats;
+
+ /* RX */
+ hw_stats->rx_good_bytes
+ += dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_OK_REG);
+ hw_stats->rx_bad_bytes
+ += dsaf_read_dev(drv, GMAC_RX_OCTETS_BAD_REG);
+ hw_stats->rx_uc_pkts += dsaf_read_dev(drv, GMAC_RX_UC_PKTS_REG);
+ hw_stats->rx_mc_pkts += dsaf_read_dev(drv, GMAC_RX_MC_PKTS_REG);
+ hw_stats->rx_bc_pkts += dsaf_read_dev(drv, GMAC_RX_BC_PKTS_REG);
+ hw_stats->rx_64bytes
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_64OCTETS_REG);
+ hw_stats->rx_65to127
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_65TO127OCTETS_REG);
+ hw_stats->rx_128to255
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_128TO255OCTETS_REG);
+ hw_stats->rx_256to511
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_255TO511OCTETS_REG);
+ hw_stats->rx_512to1023
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_512TO1023OCTETS_REG);
+ hw_stats->rx_1024to1518
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_1024TO1518OCTETS_REG);
+ hw_stats->rx_1519tomax
+ += dsaf_read_dev(drv, GMAC_RX_PKTS_1519TOMAXOCTETS_REG);
+ hw_stats->rx_fcs_err += dsaf_read_dev(drv, GMAC_RX_FCS_ERRORS_REG);
+ hw_stats->rx_vlan_pkts += dsaf_read_dev(drv, GMAC_RX_TAGGED_REG);
+ hw_stats->rx_data_err += dsaf_read_dev(drv, GMAC_RX_DATA_ERR_REG);
+ hw_stats->rx_align_err
+ += dsaf_read_dev(drv, GMAC_RX_ALIGN_ERRORS_REG);
+ hw_stats->rx_oversize
+ += dsaf_read_dev(drv, GMAC_RX_LONG_ERRORS_REG);
+ hw_stats->rx_jabber_err
+ += dsaf_read_dev(drv, GMAC_RX_JABBER_ERRORS_REG);
+ hw_stats->rx_pfc_tc0
+ += dsaf_read_dev(drv, GMAC_RX_PAUSE_MACCTRL_FRAM_REG);
+ hw_stats->rx_unknown_ctrl
+ += dsaf_read_dev(drv, GMAC_RX_UNKNOWN_MACCTRL_FRAM_REG);
+ hw_stats->rx_long_err
+ += dsaf_read_dev(drv, GMAC_RX_VERY_LONG_ERR_CNT_REG);
+ hw_stats->rx_minto64
+ += dsaf_read_dev(drv, GMAC_RX_RUNT_ERR_CNT_REG);
+ hw_stats->rx_under_min
+ += dsaf_read_dev(drv, GMAC_RX_SHORT_ERR_CNT_REG);
+ hw_stats->rx_filter_pkts
+ += dsaf_read_dev(drv, GMAC_RX_FILT_PKT_CNT_REG);
+ hw_stats->rx_filter_bytes
+ += dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_FILT_REG);
+ hw_stats->rx_fifo_overrun_err
+ += dsaf_read_dev(drv, GMAC_RX_OVERRUN_CNT_REG);
+ hw_stats->rx_len_err
+ += dsaf_read_dev(drv, GMAC_RX_LENGTHFIELD_ERR_CNT_REG);
+ hw_stats->rx_comma_err
+ += dsaf_read_dev(drv, GMAC_RX_FAIL_COMMA_CNT_REG);
+
+ /* TX */
+ hw_stats->tx_good_bytes
+ += dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_OK_REG);
+ hw_stats->tx_bad_bytes
+ += dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_BAD_REG);
+ hw_stats->tx_uc_pkts += dsaf_read_dev(drv, GMAC_TX_UC_PKTS_REG);
+ hw_stats->tx_mc_pkts += dsaf_read_dev(drv, GMAC_TX_MC_PKTS_REG);
+ hw_stats->tx_bc_pkts += dsaf_read_dev(drv, GMAC_TX_BC_PKTS_REG);
+ hw_stats->tx_64bytes
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_64OCTETS_REG);
+ hw_stats->tx_65to127
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_65TO127OCTETS_REG);
+ hw_stats->tx_128to255
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_128TO255OCTETS_REG);
+ hw_stats->tx_256to511
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_255TO511OCTETS_REG);
+ hw_stats->tx_512to1023
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_512TO1023OCTETS_REG);
+ hw_stats->tx_1024to1518
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_1024TO1518OCTETS_REG);
+ hw_stats->tx_1519tomax
+ += dsaf_read_dev(drv, GMAC_TX_PKTS_1519TOMAXOCTETS_REG);
+ hw_stats->tx_jabber_err
+ += dsaf_read_dev(drv, GMAC_TX_EXCESSIVE_LENGTH_DROP_REG);
+ hw_stats->tx_underrun_err
+ += dsaf_read_dev(drv, GMAC_TX_UNDERRUN_REG);
+ hw_stats->tx_vlan += dsaf_read_dev(drv, GMAC_TX_TAGGED_REG);
+ hw_stats->tx_crc_err += dsaf_read_dev(drv, GMAC_TX_CRC_ERROR_REG);
+ hw_stats->tx_pfc_tc0
+ += dsaf_read_dev(drv, GMAC_TX_PAUSE_FRAMES_REG);
+}
+
+static void hns_gmac_set_mac_addr(void *mac_drv, char *mac_addr)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ if (drv->mac_id >= DSAF_SERVICE_NW_NUM) {
+ u32 high_val = mac_addr[1] | (mac_addr[0] << 8);
+
+ u32 low_val = mac_addr[5] | (mac_addr[4] << 8)
+ | (mac_addr[3] << 16) | (mac_addr[2] << 24);
+ dsaf_write_dev(drv, GMAC_STATION_ADDR_LOW_2_REG, low_val);
+ dsaf_write_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG, high_val);
+ }
+}
+
+static int hns_gmac_config_loopback(void *mac_drv, enum hnae_loop loop_mode,
+ u8 enable)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ switch (loop_mode) {
+ case MAC_INTERNALLOOP_MAC:
+ dsaf_set_dev_bit(drv, GMAC_LOOP_REG, GMAC_LP_REG_CF2MI_LP_EN_B,
+ !!enable);
+ break;
+ default:
+ dev_err(drv->dev, "loop_mode error\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void hns_gmac_config_pad_and_crc(void *mac_drv, u8 newval)
+{
+ u32 tx_ctrl;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
+ dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, !!newval);
+ dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, !!newval);
+ dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl);
+}
+
+static void hns_gmac_get_id(void *mac_drv, u8 *mac_id)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *mac_id = drv->mac_id;
+}
+
+static void hns_gmac_get_info(void *mac_drv, struct mac_info *mac_info)
+{
+ enum hns_gmac_duplex_mdoe duplex;
+ enum hns_port_mode speed;
+ u32 rx_pause;
+ u32 tx_pause;
+ u32 rx;
+ u32 tx;
+ u16 fc_tx_timer;
+ struct hns_gmac_port_mode_cfg port_mode = { GMAC_10M_MII, 0 };
+
+ hns_gmac_port_mode_get(mac_drv, &port_mode);
+ mac_info->pad_and_crc_en = port_mode.crc_add && port_mode.pad_enable;
+ mac_info->auto_neg = port_mode.an_enable;
+
+ hns_gmac_get_tx_auto_pause_frames(mac_drv, &fc_tx_timer);
+ mac_info->tx_pause_time = fc_tx_timer;
+
+ hns_gmac_get_en(mac_drv, &rx, &tx);
+ mac_info->port_en = rx && tx;
+
+ hns_gmac_get_duplex_type(mac_drv, &duplex);
+ mac_info->duplex = duplex;
+
+ hns_gmac_get_port_mode(mac_drv, &speed);
+ switch (speed) {
+ case GMAC_10M_SGMII:
+ mac_info->speed = MAC_SPEED_10;
+ break;
+ case GMAC_100M_SGMII:
+ mac_info->speed = MAC_SPEED_100;
+ break;
+ case GMAC_1000M_SGMII:
+ mac_info->speed = MAC_SPEED_1000;
+ break;
+ default:
+ mac_info->speed = 0;
+ break;
+ }
+
+ hns_gmac_get_pausefrm_cfg(mac_drv, &rx_pause, &tx_pause);
+ mac_info->rx_pause_en = rx_pause;
+ mac_info->tx_pause_en = tx_pause;
+}
+
+static void hns_gmac_autoneg_stat(void *mac_drv, u32 *enable)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *enable = dsaf_get_dev_bit(drv, GMAC_TRANSMIT_CONTROL_REG,
+ GMAC_TX_AN_EN_B);
+}
+
+static void hns_gmac_get_link_status(void *mac_drv, u32 *link_stat)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *link_stat = dsaf_get_dev_bit(drv, GMAC_AN_NEG_STATE_REG,
+ GMAC_AN_NEG_STAT_RX_SYNC_OK_B);
+}
+
+static void hns_gmac_get_regs(void *mac_drv, void *data)
+{
+ u32 *regs = data;
+ int i;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ /* base config registers */
+ regs[0] = dsaf_read_dev(drv, GMAC_DUPLEX_TYPE_REG);
+ regs[1] = dsaf_read_dev(drv, GMAC_FD_FC_TYPE_REG);
+ regs[2] = dsaf_read_dev(drv, GMAC_FC_TX_TIMER_REG);
+ regs[3] = dsaf_read_dev(drv, GMAC_FD_FC_ADDR_LOW_REG);
+ regs[4] = dsaf_read_dev(drv, GMAC_FD_FC_ADDR_HIGH_REG);
+ regs[5] = dsaf_read_dev(drv, GMAC_IPG_TX_TIMER_REG);
+ regs[6] = dsaf_read_dev(drv, GMAC_PAUSE_THR_REG);
+ regs[7] = dsaf_read_dev(drv, GMAC_MAX_FRM_SIZE_REG);
+ regs[8] = dsaf_read_dev(drv, GMAC_PORT_MODE_REG);
+ regs[9] = dsaf_read_dev(drv, GMAC_PORT_EN_REG);
+ regs[10] = dsaf_read_dev(drv, GMAC_PAUSE_EN_REG);
+ regs[11] = dsaf_read_dev(drv, GMAC_SHORT_RUNTS_THR_REG);
+ regs[12] = dsaf_read_dev(drv, GMAC_AN_NEG_STATE_REG);
+ regs[13] = dsaf_read_dev(drv, GMAC_TX_LOCAL_PAGE_REG);
+ regs[14] = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
+ regs[15] = dsaf_read_dev(drv, GMAC_REC_FILT_CONTROL_REG);
+ regs[16] = dsaf_read_dev(drv, GMAC_PTP_CONFIG_REG);
+
+ /* rx static registers */
+ regs[17] = dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_OK_REG);
+ regs[18] = dsaf_read_dev(drv, GMAC_RX_OCTETS_BAD_REG);
+ regs[19] = dsaf_read_dev(drv, GMAC_RX_UC_PKTS_REG);
+ regs[20] = dsaf_read_dev(drv, GMAC_RX_MC_PKTS_REG);
+ regs[21] = dsaf_read_dev(drv, GMAC_RX_BC_PKTS_REG);
+ regs[22] = dsaf_read_dev(drv, GMAC_RX_PKTS_64OCTETS_REG);
+ regs[23] = dsaf_read_dev(drv, GMAC_RX_PKTS_65TO127OCTETS_REG);
+ regs[24] = dsaf_read_dev(drv, GMAC_RX_PKTS_128TO255OCTETS_REG);
+ regs[25] = dsaf_read_dev(drv, GMAC_RX_PKTS_255TO511OCTETS_REG);
+ regs[26] = dsaf_read_dev(drv, GMAC_RX_PKTS_512TO1023OCTETS_REG);
+ regs[27] = dsaf_read_dev(drv, GMAC_RX_PKTS_1024TO1518OCTETS_REG);
+ regs[28] = dsaf_read_dev(drv, GMAC_RX_PKTS_1519TOMAXOCTETS_REG);
+ regs[29] = dsaf_read_dev(drv, GMAC_RX_FCS_ERRORS_REG);
+ regs[30] = dsaf_read_dev(drv, GMAC_RX_TAGGED_REG);
+ regs[31] = dsaf_read_dev(drv, GMAC_RX_DATA_ERR_REG);
+ regs[32] = dsaf_read_dev(drv, GMAC_RX_ALIGN_ERRORS_REG);
+ regs[33] = dsaf_read_dev(drv, GMAC_RX_LONG_ERRORS_REG);
+ regs[34] = dsaf_read_dev(drv, GMAC_RX_JABBER_ERRORS_REG);
+ regs[35] = dsaf_read_dev(drv, GMAC_RX_PAUSE_MACCTRL_FRAM_REG);
+ regs[36] = dsaf_read_dev(drv, GMAC_RX_UNKNOWN_MACCTRL_FRAM_REG);
+ regs[37] = dsaf_read_dev(drv, GMAC_RX_VERY_LONG_ERR_CNT_REG);
+ regs[38] = dsaf_read_dev(drv, GMAC_RX_RUNT_ERR_CNT_REG);
+ regs[39] = dsaf_read_dev(drv, GMAC_RX_SHORT_ERR_CNT_REG);
+ regs[40] = dsaf_read_dev(drv, GMAC_RX_FILT_PKT_CNT_REG);
+ regs[41] = dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_FILT_REG);
+
+ /* tx static registers */
+ regs[42] = dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_OK_REG);
+ regs[43] = dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_BAD_REG);
+ regs[44] = dsaf_read_dev(drv, GMAC_TX_UC_PKTS_REG);
+ regs[45] = dsaf_read_dev(drv, GMAC_TX_MC_PKTS_REG);
+ regs[46] = dsaf_read_dev(drv, GMAC_TX_BC_PKTS_REG);
+ regs[47] = dsaf_read_dev(drv, GMAC_TX_PKTS_64OCTETS_REG);
+ regs[48] = dsaf_read_dev(drv, GMAC_TX_PKTS_65TO127OCTETS_REG);
+ regs[49] = dsaf_read_dev(drv, GMAC_TX_PKTS_128TO255OCTETS_REG);
+ regs[50] = dsaf_read_dev(drv, GMAC_TX_PKTS_255TO511OCTETS_REG);
+ regs[51] = dsaf_read_dev(drv, GMAC_TX_PKTS_512TO1023OCTETS_REG);
+ regs[52] = dsaf_read_dev(drv, GMAC_TX_PKTS_1024TO1518OCTETS_REG);
+ regs[53] = dsaf_read_dev(drv, GMAC_TX_PKTS_1519TOMAXOCTETS_REG);
+ regs[54] = dsaf_read_dev(drv, GMAC_TX_EXCESSIVE_LENGTH_DROP_REG);
+ regs[55] = dsaf_read_dev(drv, GMAC_TX_UNDERRUN_REG);
+ regs[56] = dsaf_read_dev(drv, GMAC_TX_TAGGED_REG);
+ regs[57] = dsaf_read_dev(drv, GMAC_TX_CRC_ERROR_REG);
+ regs[58] = dsaf_read_dev(drv, GMAC_TX_PAUSE_FRAMES_REG);
+
+ regs[59] = dsaf_read_dev(drv, GAMC_RX_MAX_FRAME);
+ regs[60] = dsaf_read_dev(drv, GMAC_LINE_LOOP_BACK_REG);
+ regs[61] = dsaf_read_dev(drv, GMAC_CF_CRC_STRIP_REG);
+ regs[62] = dsaf_read_dev(drv, GMAC_MODE_CHANGE_EN_REG);
+ regs[63] = dsaf_read_dev(drv, GMAC_SIXTEEN_BIT_CNTR_REG);
+ regs[64] = dsaf_read_dev(drv, GMAC_LD_LINK_COUNTER_REG);
+ regs[65] = dsaf_read_dev(drv, GMAC_LOOP_REG);
+ regs[66] = dsaf_read_dev(drv, GMAC_RECV_CONTROL_REG);
+ regs[67] = dsaf_read_dev(drv, GMAC_VLAN_CODE_REG);
+ regs[68] = dsaf_read_dev(drv, GMAC_RX_OVERRUN_CNT_REG);
+ regs[69] = dsaf_read_dev(drv, GMAC_RX_LENGTHFIELD_ERR_CNT_REG);
+ regs[70] = dsaf_read_dev(drv, GMAC_RX_FAIL_COMMA_CNT_REG);
+
+ regs[71] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_0_REG);
+ regs[72] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_0_REG);
+ regs[73] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_1_REG);
+ regs[74] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_1_REG);
+ regs[75] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_2_REG);
+ regs[76] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG);
+ regs[77] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_3_REG);
+ regs[78] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_3_REG);
+ regs[79] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_4_REG);
+ regs[80] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_4_REG);
+ regs[81] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_5_REG);
+ regs[82] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_5_REG);
+ regs[83] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_MSK_0_REG);
+ regs[84] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_MSK_0_REG);
+ regs[85] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_MSK_1_REG);
+ regs[86] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_MSK_1_REG);
+ regs[87] = dsaf_read_dev(drv, GMAC_MAC_SKIP_LEN_REG);
+ regs[88] = dsaf_read_dev(drv, GMAC_TX_LOOP_PKT_PRI_REG);
+
+ /* mark end of mac regs */
+ for (i = 89; i < 96; i++)
+ regs[i] = 0xaaaaaaaa;
+}
+
+static void hns_gmac_get_stats(void *mac_drv, u64 *data)
+{
+ u32 i;
+ u64 *buf = data;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct mac_hw_stats *hw_stats = NULL;
+
+ hw_stats = &drv->mac_cb->hw_stats;
+
+ for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++) {
+ buf[i] = DSAF_STATS_READ(hw_stats,
+ g_gmac_stats_string[i].offset);
+ }
+}
+
+static void hns_gmac_get_strings(u32 stringset, u8 *data)
+{
+ char *buff = (char *)data;
+ u32 i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++) {
+ snprintf(buff, ETH_GSTRING_LEN, g_gmac_stats_string[i].desc);
+ buff = buff + ETH_GSTRING_LEN;
+ }
+}
+
+static int hns_gmac_get_sset_count(int stringset)
+{
+ if (stringset == ETH_SS_STATS)
+ return ARRAY_SIZE(g_gmac_stats_string);
+
+ return 0;
+}
+
+static int hns_gmac_get_regs_count(void)
+{
+ return ETH_GMAC_DUMP_NUM;
+}
+
+void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
+{
+ struct mac_driver *mac_drv;
+
+ mac_drv = devm_kzalloc(mac_cb->dev, sizeof(*mac_drv), GFP_KERNEL);
+ if (!mac_drv)
+ return NULL;
+
+ mac_drv->mac_init = hns_gmac_init;
+ mac_drv->mac_enable = hns_gmac_enable;
+ mac_drv->mac_disable = hns_gmac_disable;
+ mac_drv->mac_free = hns_gmac_free;
+ mac_drv->adjust_link = hns_gmac_adjust_link;
+ mac_drv->set_tx_auto_pause_frames = hns_gmac_set_tx_auto_pause_frames;
+ mac_drv->config_max_frame_length = hns_gmac_config_max_frame_length;
+ mac_drv->mac_pausefrm_cfg = hns_gmac_pause_frm_cfg;
+
+ mac_drv->mac_id = mac_param->mac_id;
+ mac_drv->mac_mode = mac_param->mac_mode;
+ mac_drv->io_base = mac_param->vaddr;
+ mac_drv->dev = mac_param->dev;
+ mac_drv->mac_cb = mac_cb;
+
+ mac_drv->set_mac_addr = hns_gmac_set_mac_addr;
+ mac_drv->set_an_mode = hns_gmac_config_an_mode;
+ mac_drv->config_loopback = hns_gmac_config_loopback;
+ mac_drv->config_pad_and_crc = hns_gmac_config_pad_and_crc;
+ mac_drv->config_half_duplex = hns_gmac_set_duplex_type;
+ mac_drv->set_rx_ignore_pause_frames = hns_gmac_set_rx_auto_pause_frames;
+ mac_drv->mac_get_id = hns_gmac_get_id;
+ mac_drv->get_info = hns_gmac_get_info;
+ mac_drv->autoneg_stat = hns_gmac_autoneg_stat;
+ mac_drv->get_pause_enable = hns_gmac_get_pausefrm_cfg;
+ mac_drv->get_link_status = hns_gmac_get_link_status;
+ mac_drv->get_regs = hns_gmac_get_regs;
+ mac_drv->get_regs_count = hns_gmac_get_regs_count;
+ mac_drv->get_ethtool_stats = hns_gmac_get_stats;
+ mac_drv->get_sset_count = hns_gmac_get_sset_count;
+ mac_drv->get_strings = hns_gmac_get_strings;
+ mac_drv->update_stats = hns_gmac_update_stats;
+
+ return (void *)mac_drv;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h
new file mode 100644
index 000000000000..44fe3010dc6d
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _HNS_GMAC_H
+#define _HNS_GMAC_H
+
+#include "hns_dsaf_mac.h"
+
+enum hns_port_mode {
+ GMAC_10M_MII = 0,
+ GMAC_100M_MII,
+ GMAC_1000M_GMII,
+ GMAC_10M_RGMII,
+ GMAC_100M_RGMII,
+ GMAC_1000M_RGMII,
+ GMAC_10M_SGMII,
+ GMAC_100M_SGMII,
+ GMAC_1000M_SGMII,
+ GMAC_10000M_SGMII /* 10GE */
+};
+
+enum hns_gmac_duplex_mdoe {
+ GMAC_HALF_DUPLEX_MODE = 0,
+ GMAC_FULL_DUPLEX_MODE
+};
+
+struct hns_gmac_port_mode_cfg {
+ enum hns_port_mode port_mode;
+ u32 max_frm_size;
+ u32 short_runts_thr;
+ u32 pad_enable;
+ u32 crc_add;
+ u32 an_enable; /*auto-nego enable */
+ u32 runt_pkt_en;
+ u32 strip_pad_en;
+};
+
+#define ETH_GMAC_DUMP_NUM 96
+#endif /* __HNS_GMAC_H__ */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
new file mode 100644
index 000000000000..026b38676cba
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/phy_fixed.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "hns_dsaf_misc.h"
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_rcb.h"
+
+#define MAC_EN_FLAG_V 0xada0328
+
+static const u16 mac_phy_to_speed[] = {
+ [PHY_INTERFACE_MODE_MII] = MAC_SPEED_100,
+ [PHY_INTERFACE_MODE_GMII] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_SGMII] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_TBI] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_RMII] = MAC_SPEED_100,
+ [PHY_INTERFACE_MODE_RGMII] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_RGMII_ID] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_RGMII_RXID] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_RGMII_TXID] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_RTBI] = MAC_SPEED_1000,
+ [PHY_INTERFACE_MODE_XGMII] = MAC_SPEED_10000
+};
+
+static const enum mac_mode g_mac_mode_100[] = {
+ [PHY_INTERFACE_MODE_MII] = MAC_MODE_MII_100,
+ [PHY_INTERFACE_MODE_RMII] = MAC_MODE_RMII_100
+};
+
+static const enum mac_mode g_mac_mode_1000[] = {
+ [PHY_INTERFACE_MODE_GMII] = MAC_MODE_GMII_1000,
+ [PHY_INTERFACE_MODE_SGMII] = MAC_MODE_SGMII_1000,
+ [PHY_INTERFACE_MODE_TBI] = MAC_MODE_TBI_1000,
+ [PHY_INTERFACE_MODE_RGMII] = MAC_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RGMII_ID] = MAC_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RGMII_RXID] = MAC_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RGMII_TXID] = MAC_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RTBI] = MAC_MODE_RTBI_1000
+};
+
+static enum mac_mode hns_mac_dev_to_enet_if(const struct hns_mac_cb *mac_cb)
+{
+ switch (mac_cb->max_speed) {
+ case MAC_SPEED_100:
+ return g_mac_mode_100[mac_cb->phy_if];
+ case MAC_SPEED_1000:
+ return g_mac_mode_1000[mac_cb->phy_if];
+ case MAC_SPEED_10000:
+ return MAC_MODE_XGMII_10000;
+ default:
+ return MAC_MODE_MII_100;
+ }
+}
+
+static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb)
+{
+ switch (mac_cb->max_speed) {
+ case MAC_SPEED_100:
+ return g_mac_mode_100[mac_cb->phy_if];
+ case MAC_SPEED_1000:
+ return g_mac_mode_1000[mac_cb->phy_if];
+ case MAC_SPEED_10000:
+ return MAC_MODE_XGMII_10000;
+ default:
+ return MAC_MODE_MII_100;
+ }
+}
+
+int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt)
+{
+ if (!mac_cb->cpld_vaddr)
+ return -ENODEV;
+
+ *sfp_prsnt = !dsaf_read_b((u8 *)mac_cb->cpld_vaddr
+ + MAC_SFP_PORT_OFFSET);
+
+ return 0;
+}
+
+void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
+{
+ struct mac_driver *mac_ctrl_drv;
+ int ret, sfp_prsnt;
+
+ mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ if (mac_ctrl_drv->get_link_status)
+ mac_ctrl_drv->get_link_status(mac_ctrl_drv, link_status);
+ else
+ *link_status = 0;
+
+ ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt);
+ if (!ret)
+ *link_status = *link_status && sfp_prsnt;
+
+ mac_cb->link = *link_status;
+}
+
+int hns_mac_get_port_info(struct hns_mac_cb *mac_cb,
+ u8 *auto_neg, u16 *speed, u8 *duplex)
+{
+ struct mac_driver *mac_ctrl_drv;
+ struct mac_info info;
+
+ mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ if (!mac_ctrl_drv->get_info)
+ return -ENODEV;
+
+ mac_ctrl_drv->get_info(mac_ctrl_drv, &info);
+ if (auto_neg)
+ *auto_neg = info.auto_neg;
+ if (speed)
+ *speed = info.speed;
+ if (duplex)
+ *duplex = info.duplex;
+
+ return 0;
+}
+
+void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex)
+{
+ int ret;
+ struct mac_driver *mac_ctrl_drv;
+
+ mac_ctrl_drv = (struct mac_driver *)(mac_cb->priv.mac);
+
+ mac_cb->speed = speed;
+ mac_cb->half_duplex = !duplex;
+ mac_ctrl_drv->mac_mode = hns_mac_dev_to_enet_if(mac_cb);
+
+ if (mac_ctrl_drv->adjust_link) {
+ ret = mac_ctrl_drv->adjust_link(mac_ctrl_drv,
+ (enum mac_speed)speed, duplex);
+ if (ret) {
+ dev_err(mac_cb->dev,
+ "adjust_link failed,%s mac%d ret = %#x!\n",
+ mac_cb->dsaf_dev->ae_dev.name,
+ mac_cb->mac_id, ret);
+ return;
+ }
+ }
+}
+
+/**
+ *hns_mac_get_inner_port_num - get mac table inner port number
+ *@mac_cb: mac device
+ *@vmid: vm id
+ *@port_num:port number
+ *
+ */
+static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
+ u8 vmid, u8 *port_num)
+{
+ u8 tmp_port;
+ u32 comm_idx;
+
+ if (mac_cb->dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) {
+ if (mac_cb->mac_id != DSAF_MAX_PORT_NUM_PER_CHIP) {
+ dev_err(mac_cb->dev,
+ "input invalid,%s mac%d vmid%d !\n",
+ mac_cb->dsaf_dev->ae_dev.name,
+ mac_cb->mac_id, vmid);
+ return -EINVAL;
+ }
+ } else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) {
+ if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM_PER_CHIP) {
+ dev_err(mac_cb->dev,
+ "input invalid,%s mac%d vmid%d!\n",
+ mac_cb->dsaf_dev->ae_dev.name,
+ mac_cb->mac_id, vmid);
+ return -EINVAL;
+ }
+ } else {
+ dev_err(mac_cb->dev, "dsaf mode invalid,%s mac%d!\n",
+ mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id);
+ return -EINVAL;
+ }
+
+ comm_idx = hns_dsaf_get_comm_idx_by_port(mac_cb->mac_id);
+
+ if (vmid >= mac_cb->dsaf_dev->rcb_common[comm_idx]->max_vfn) {
+ dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d !\n",
+ mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vmid);
+ return -EINVAL;
+ }
+
+ switch (mac_cb->dsaf_dev->dsaf_mode) {
+ case DSAF_MODE_ENABLE_FIX:
+ tmp_port = 0;
+ break;
+ case DSAF_MODE_DISABLE_FIX:
+ tmp_port = 0;
+ break;
+ case DSAF_MODE_ENABLE_0VM:
+ case DSAF_MODE_ENABLE_8VM:
+ case DSAF_MODE_ENABLE_16VM:
+ case DSAF_MODE_ENABLE_32VM:
+ case DSAF_MODE_ENABLE_128VM:
+ case DSAF_MODE_DISABLE_2PORT_8VM:
+ case DSAF_MODE_DISABLE_2PORT_16VM:
+ case DSAF_MODE_DISABLE_2PORT_64VM:
+ case DSAF_MODE_DISABLE_6PORT_0VM:
+ case DSAF_MODE_DISABLE_6PORT_2VM:
+ case DSAF_MODE_DISABLE_6PORT_4VM:
+ case DSAF_MODE_DISABLE_6PORT_16VM:
+ tmp_port = vmid;
+ break;
+ default:
+ dev_err(mac_cb->dev, "dsaf mode invalid,%s mac%d!\n",
+ mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id);
+ return -EINVAL;
+ }
+ tmp_port += DSAF_BASE_INNER_PORT_NUM;
+
+ *port_num = tmp_port;
+
+ return 0;
+}
+
+/**
+ *hns_mac_get_inner_port_num - change vf mac address
+ *@mac_cb: mac device
+ *@vmid: vmid
+ *@addr:mac address
+ */
+int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb,
+ u32 vmid, char *addr)
+{
+ int ret;
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+ struct mac_entry_idx *old_entry;
+
+ old_entry = &mac_cb->addr_entry_idx[vmid];
+ if (dsaf_dev) {
+ memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+ mac_entry.in_vlan_id = old_entry->vlan_id;
+ mac_entry.in_port_num = mac_cb->mac_id;
+ ret = hns_mac_get_inner_port_num(mac_cb, (u8)vmid,
+ &mac_entry.port_num);
+ if (ret)
+ return ret;
+
+ if ((old_entry->valid != 0) &&
+ (memcmp(old_entry->addr,
+ addr, sizeof(mac_entry.addr)) != 0)) {
+ ret = hns_dsaf_del_mac_entry(dsaf_dev,
+ old_entry->vlan_id,
+ mac_cb->mac_id,
+ old_entry->addr);
+ if (ret)
+ return ret;
+ }
+
+ ret = hns_dsaf_set_mac_uc_entry(dsaf_dev, &mac_entry);
+ if (ret)
+ return ret;
+ }
+
+ if ((mac_ctrl_drv->set_mac_addr) && (vmid == 0))
+ mac_ctrl_drv->set_mac_addr(mac_cb->priv.mac, addr);
+
+ memcpy(old_entry->addr, addr, sizeof(old_entry->addr));
+ old_entry->valid = 1;
+ return 0;
+}
+
+int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
+ u32 port_num, char *addr, u8 en)
+{
+ int ret;
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+
+ if (dsaf_dev && addr) {
+ memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+ mac_entry.in_vlan_id = 0;/*vlan_id;*/
+ mac_entry.in_port_num = mac_cb->mac_id;
+ mac_entry.port_num = port_num;
+
+ if (en == DISABLE)
+ ret = hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry);
+ else
+ ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry);
+ if (ret) {
+ dev_err(dsaf_dev->dev,
+ "set mac mc port failed,%s mac%d ret = %#x!\n",
+ mac_cb->dsaf_dev->ae_dev.name,
+ mac_cb->mac_id, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ *hns_mac_del_mac - delete mac address into dsaf table,can't delete the same
+ * address twice
+ *@net_dev: net device
+ *@vfn : vf lan
+ *@mac : mac address
+ *return status
+ */
+int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac)
+{
+ struct mac_entry_idx *old_mac;
+ struct dsaf_device *dsaf_dev;
+ u32 ret;
+
+ dsaf_dev = mac_cb->dsaf_dev;
+
+ if (vfn < DSAF_MAX_VM_NUM) {
+ old_mac = &mac_cb->addr_entry_idx[vfn];
+ } else {
+ dev_err(mac_cb->dev,
+ "vf queue is too large,%s mac%d queue = %#x!\n",
+ mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vfn);
+ return -EINVAL;
+ }
+
+ if (dsaf_dev) {
+ ret = hns_dsaf_del_mac_entry(dsaf_dev, old_mac->vlan_id,
+ mac_cb->mac_id, old_mac->addr);
+ if (ret)
+ return ret;
+
+ if (memcmp(old_mac->addr, mac, sizeof(old_mac->addr)) == 0)
+ old_mac->valid = 0;
+ }
+
+ return 0;
+}
+
+static void hns_mac_param_get(struct mac_params *param,
+ struct hns_mac_cb *mac_cb)
+{
+ param->vaddr = (void *)mac_cb->vaddr;
+ param->mac_mode = hns_get_enet_interface(mac_cb);
+ memcpy(param->addr, mac_cb->addr_entry_idx[0].addr,
+ MAC_NUM_OCTETS_PER_ADDR);
+ param->mac_id = mac_cb->mac_id;
+ param->dev = mac_cb->dev;
+}
+
+/**
+ *hns_mac_queue_config_bc_en - set broadcast rx&tx enable
+ *@mac_cb: mac device
+ *@queue: queue number
+ *@en:enable
+ *retuen 0 - success , negative --fail
+ */
+static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb,
+ u32 port_num, u16 vlan_id, u8 en)
+{
+ int ret;
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ u8 addr[MAC_NUM_OCTETS_PER_ADDR]
+ = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+
+ /* directy return ok in debug network mode */
+ if (mac_cb->mac_type == HNAE_PORT_DEBUG)
+ return 0;
+
+ if (dsaf_dev) {
+ memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+ mac_entry.in_vlan_id = vlan_id;
+ mac_entry.in_port_num = mac_cb->mac_id;
+ mac_entry.port_num = port_num;
+
+ if (en == DISABLE)
+ ret = hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry);
+ else
+ ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ *hns_mac_vm_config_bc_en - set broadcast rx&tx enable
+ *@mac_cb: mac device
+ *@vmid: vm id
+ *@en:enable
+ *retuen 0 - success , negative --fail
+ */
+int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, u8 en)
+{
+ int ret;
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ u8 port_num;
+ u8 addr[MAC_NUM_OCTETS_PER_ADDR]
+ = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ struct mac_entry_idx *uc_mac_entry;
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+
+ if (mac_cb->mac_type == HNAE_PORT_DEBUG)
+ return 0;
+
+ uc_mac_entry = &mac_cb->addr_entry_idx[vmid];
+
+ if (dsaf_dev) {
+ memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+ mac_entry.in_vlan_id = uc_mac_entry->vlan_id;
+ mac_entry.in_port_num = mac_cb->mac_id;
+ ret = hns_mac_get_inner_port_num(mac_cb, vmid, &port_num);
+ if (ret)
+ return ret;
+ mac_entry.port_num = port_num;
+
+ if (en == DISABLE)
+ ret = hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry);
+ else
+ ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry);
+ return ret;
+ }
+
+ return 0;
+}
+
+void hns_mac_reset(struct hns_mac_cb *mac_cb)
+{
+ struct mac_driver *drv;
+
+ drv = hns_mac_get_drv(mac_cb);
+
+ drv->mac_init(drv);
+
+ if (drv->config_max_frame_length)
+ drv->config_max_frame_length(drv, mac_cb->max_frm);
+
+ if (drv->set_tx_auto_pause_frames)
+ drv->set_tx_auto_pause_frames(drv, mac_cb->tx_pause_frm_time);
+
+ if (drv->set_an_mode)
+ drv->set_an_mode(drv, 1);
+
+ if (drv->mac_pausefrm_cfg) {
+ if (mac_cb->mac_type == HNAE_PORT_DEBUG)
+ drv->mac_pausefrm_cfg(drv, 0, 0);
+ else /* mac rx must disable, dsaf pfc close instead of it*/
+ drv->mac_pausefrm_cfg(drv, 0, 1);
+ }
+}
+
+int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu)
+{
+ struct mac_driver *drv = hns_mac_get_drv(mac_cb);
+ u32 buf_size = mac_cb->dsaf_dev->buf_size;
+ u32 new_frm = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+ if ((new_mtu < MAC_MIN_MTU) || (new_frm > MAC_MAX_MTU) ||
+ (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size))
+ return -EINVAL;
+
+ if (!drv->config_max_frame_length)
+ return -ECHILD;
+
+ /* adjust max frame to be at least the size of a standard frame */
+ if (new_frm < (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN))
+ new_frm = (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN);
+
+ drv->config_max_frame_length(drv, new_frm);
+
+ mac_cb->max_frm = new_frm;
+
+ return 0;
+}
+
+void hns_mac_start(struct hns_mac_cb *mac_cb)
+{
+ struct mac_driver *mac_drv = hns_mac_get_drv(mac_cb);
+
+ /* for virt */
+ if (mac_drv->mac_en_flg == MAC_EN_FLAG_V) {
+ /*plus 1 when the virtual mac has been enabled */
+ mac_drv->virt_dev_num += 1;
+ return;
+ }
+
+ if (mac_drv->mac_enable) {
+ mac_drv->mac_enable(mac_cb->priv.mac, MAC_COMM_MODE_RX_AND_TX);
+ mac_drv->mac_en_flg = MAC_EN_FLAG_V;
+ }
+}
+
+void hns_mac_stop(struct hns_mac_cb *mac_cb)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ /*modified for virtualization */
+ if (mac_ctrl_drv->virt_dev_num > 0) {
+ mac_ctrl_drv->virt_dev_num -= 1;
+ if (mac_ctrl_drv->virt_dev_num > 0)
+ return;
+ }
+
+ if (mac_ctrl_drv->mac_disable)
+ mac_ctrl_drv->mac_disable(mac_cb->priv.mac,
+ MAC_COMM_MODE_RX_AND_TX);
+
+ mac_ctrl_drv->mac_en_flg = 0;
+ mac_cb->link = 0;
+ cpld_led_reset(mac_cb);
+}
+
+/**
+ * hns_mac_get_autoneg - get auto autonegotiation
+ * @mac_cb: mac control block
+ * @enable: enable or not
+ * retuen 0 - success , negative --fail
+ */
+void hns_mac_get_autoneg(struct hns_mac_cb *mac_cb, u32 *auto_neg)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ if (mac_ctrl_drv->autoneg_stat)
+ mac_ctrl_drv->autoneg_stat(mac_ctrl_drv, auto_neg);
+ else
+ *auto_neg = 0;
+}
+
+/**
+ * hns_mac_get_pauseparam - set rx & tx pause parameter
+ * @mac_cb: mac control block
+ * @rx_en: rx enable status
+ * @tx_en: tx enable status
+ * retuen 0 - success , negative --fail
+ */
+void hns_mac_get_pauseparam(struct hns_mac_cb *mac_cb, u32 *rx_en, u32 *tx_en)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ if (mac_ctrl_drv->get_pause_enable) {
+ mac_ctrl_drv->get_pause_enable(mac_ctrl_drv, rx_en, tx_en);
+ } else {
+ *rx_en = 0;
+ *tx_en = 0;
+ }
+
+ /* Due to the chip defect, the service mac's rx pause CAN'T be enabled.
+ * We set the rx pause frm always be true (1), because DSAF deals with
+ * the rx pause frm instead of service mac. After all, we still support
+ * rx pause frm.
+ */
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE)
+ *rx_en = 1;
+}
+
+/**
+ * hns_mac_set_autoneg - set auto autonegotiation
+ * @mac_cb: mac control block
+ * @enable: enable or not
+ * retuen 0 - success , negative --fail
+ */
+int hns_mac_set_autoneg(struct hns_mac_cb *mac_cb, u8 enable)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII && enable) {
+ dev_err(mac_cb->dev, "enable autoneg is not allowed!");
+ return -ENOTSUPP;
+ }
+
+ if (mac_ctrl_drv->set_an_mode)
+ mac_ctrl_drv->set_an_mode(mac_ctrl_drv, enable);
+
+ return 0;
+}
+
+/**
+ * hns_mac_set_autoneg - set rx & tx pause parameter
+ * @mac_cb: mac control block
+ * @rx_en: rx enable or not
+ * @tx_en: tx enable or not
+ * return 0 - success , negative --fail
+ */
+int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE) {
+ if (!rx_en) {
+ dev_err(mac_cb->dev, "disable rx_pause is not allowed!");
+ return -EINVAL;
+ }
+ } else if (mac_cb->mac_type == HNAE_PORT_DEBUG) {
+ if (tx_en || rx_en) {
+ dev_err(mac_cb->dev, "enable tx_pause or enable rx_pause are not allowed!");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(mac_cb->dev, "Unsupport this operation!");
+ return -EINVAL;
+ }
+
+ if (mac_ctrl_drv->mac_pausefrm_cfg)
+ mac_ctrl_drv->mac_pausefrm_cfg(mac_ctrl_drv, rx_en, tx_en);
+
+ return 0;
+}
+
+/**
+ * hns_mac_init_ex - mac init
+ * @mac_cb: mac control block
+ * retuen 0 - success , negative --fail
+ */
+static int hns_mac_init_ex(struct hns_mac_cb *mac_cb)
+{
+ int ret;
+ struct mac_params param;
+ struct mac_driver *drv;
+
+ hns_dsaf_fix_mac_mode(mac_cb);
+
+ memset(&param, 0, sizeof(struct mac_params));
+ hns_mac_param_get(&param, mac_cb);
+
+ if (MAC_SPEED_FROM_MODE(param.mac_mode) < MAC_SPEED_10000)
+ drv = (struct mac_driver *)hns_gmac_config(mac_cb, &param);
+ else
+ drv = (struct mac_driver *)hns_xgmac_config(mac_cb, &param);
+
+ if (!drv)
+ return -ENOMEM;
+
+ mac_cb->priv.mac = (void *)drv;
+ hns_mac_reset(mac_cb);
+
+ hns_mac_adjust_link(mac_cb, mac_cb->speed, !mac_cb->half_duplex);
+
+ ret = hns_mac_port_config_bc_en(mac_cb, mac_cb->mac_id, 0, ENABLE);
+ if (ret)
+ goto free_mac_drv;
+
+ return 0;
+
+free_mac_drv:
+ drv->mac_free(mac_cb->priv.mac);
+ mac_cb->priv.mac = NULL;
+
+ return ret;
+}
+
+/**
+ *mac_free_dev - get mac information from device node
+ *@mac_cb: mac device
+ *@np:device node
+ *@mac_mode_idx:mac mode index
+ */
+static void hns_mac_get_info(struct hns_mac_cb *mac_cb,
+ struct device_node *np, u32 mac_mode_idx)
+{
+ mac_cb->link = false;
+ mac_cb->half_duplex = false;
+ mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if];
+ mac_cb->max_speed = mac_cb->speed;
+
+ if (mac_cb->phy_if == PHY_INTERFACE_MODE_SGMII) {
+ mac_cb->if_support = MAC_GMAC_SUPPORTED;
+ mac_cb->if_support |= SUPPORTED_1000baseT_Full;
+ } else if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII) {
+ mac_cb->if_support = SUPPORTED_10000baseR_FEC;
+ mac_cb->if_support |= SUPPORTED_10000baseKR_Full;
+ }
+
+ mac_cb->max_frm = MAC_DEFAULT_MTU;
+ mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME;
+
+ /* Get the rest of the PHY information */
+ mac_cb->phy_node = of_parse_phandle(np, "phy-handle", mac_cb->mac_id);
+ if (mac_cb->phy_node)
+ dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n",
+ mac_cb->mac_id, mac_cb->phy_node->name);
+}
+
+/**
+ * hns_mac_get_mode - get mac mode
+ * @phy_if: phy interface
+ * retuen 0 - gmac, 1 - xgmac , negative --fail
+ */
+static int hns_mac_get_mode(phy_interface_t phy_if)
+{
+ switch (phy_if) {
+ case PHY_INTERFACE_MODE_SGMII:
+ return MAC_GMAC_IDX;
+ case PHY_INTERFACE_MODE_XGMII:
+ return MAC_XGMAC_IDX;
+ default:
+ return -EINVAL;
+ }
+}
+
+u8 __iomem *hns_mac_get_vaddr(struct dsaf_device *dsaf_dev,
+ struct hns_mac_cb *mac_cb, u32 mac_mode_idx)
+{
+ u8 __iomem *base = dsaf_dev->io_base;
+ int mac_id = mac_cb->mac_id;
+
+ if (mac_cb->mac_type == HNAE_PORT_SERVICE)
+ return base + 0x40000 + mac_id * 0x4000 -
+ mac_mode_idx * 0x20000;
+ else
+ return mac_cb->serdes_vaddr + 0x1000
+ + (mac_id - DSAF_SERVICE_PORT_NUM_PER_DSAF) * 0x100000;
+}
+
+/**
+ * hns_mac_get_cfg - get mac cfg from dtb or acpi table
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_idx: mac index
+ * retuen 0 - success , negative --fail
+ */
+int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx)
+{
+ int ret;
+ u32 mac_mode_idx;
+ struct hns_mac_cb *mac_cb = &dsaf_dev->mac_cb[mac_idx];
+
+ mac_cb->dsaf_dev = dsaf_dev;
+ mac_cb->dev = dsaf_dev->dev;
+ mac_cb->mac_id = mac_idx;
+
+ mac_cb->sys_ctl_vaddr = dsaf_dev->sc_base;
+ mac_cb->serdes_vaddr = dsaf_dev->sds_base;
+
+ if (dsaf_dev->cpld_base &&
+ mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) {
+ mac_cb->cpld_vaddr = dsaf_dev->cpld_base +
+ mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET;
+ cpld_led_reset(mac_cb);
+ }
+ mac_cb->sfp_prsnt = 0;
+ mac_cb->txpkt_for_led = 0;
+ mac_cb->rxpkt_for_led = 0;
+
+ if (mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF)
+ mac_cb->mac_type = HNAE_PORT_SERVICE;
+ else
+ mac_cb->mac_type = HNAE_PORT_DEBUG;
+
+ mac_cb->phy_if = hns_mac_get_phy_if(mac_cb);
+
+ ret = hns_mac_get_mode(mac_cb->phy_if);
+ if (ret < 0) {
+ dev_err(dsaf_dev->dev,
+ "hns_mac_get_mode failed,mac%d ret = %#x!\n",
+ mac_cb->mac_id, ret);
+ return ret;
+ }
+ mac_mode_idx = (u32)ret;
+
+ hns_mac_get_info(mac_cb, mac_cb->dev->of_node, mac_mode_idx);
+
+ mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx);
+
+ return 0;
+}
+
+/**
+ * hns_mac_init - init mac
+ * @dsaf_dev: dsa fabric device struct pointer
+ * retuen 0 - success , negative --fail
+ */
+int hns_mac_init(struct dsaf_device *dsaf_dev)
+{
+ int i;
+ int ret;
+ size_t size;
+ struct hns_mac_cb *mac_cb;
+
+ size = sizeof(struct hns_mac_cb) * DSAF_MAX_PORT_NUM_PER_CHIP;
+ dsaf_dev->mac_cb = devm_kzalloc(dsaf_dev->dev, size, GFP_KERNEL);
+ if (!dsaf_dev->mac_cb)
+ return -ENOMEM;
+
+ for (i = 0; i < DSAF_MAX_PORT_NUM_PER_CHIP; i++) {
+ ret = hns_mac_get_cfg(dsaf_dev, i);
+ if (ret)
+ goto free_mac_cb;
+
+ mac_cb = &dsaf_dev->mac_cb[i];
+ ret = hns_mac_init_ex(mac_cb);
+ if (ret)
+ goto free_mac_cb;
+ }
+
+ return 0;
+
+free_mac_cb:
+ dsaf_dev->mac_cb = NULL;
+
+ return ret;
+}
+
+void hns_mac_uninit(struct dsaf_device *dsaf_dev)
+{
+ cpld_led_reset(dsaf_dev->mac_cb);
+ dsaf_dev->mac_cb = NULL;
+}
+
+int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb,
+ enum hnae_loop loop, int en)
+{
+ int ret;
+ struct mac_driver *drv = hns_mac_get_drv(mac_cb);
+
+ if (drv->config_loopback)
+ ret = drv->config_loopback(drv, loop, en);
+ else
+ ret = -ENOTSUPP;
+
+ return ret;
+}
+
+void hns_mac_update_stats(struct hns_mac_cb *mac_cb)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ mac_ctrl_drv->update_stats(mac_ctrl_drv);
+}
+
+void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ mac_ctrl_drv->get_ethtool_stats(mac_ctrl_drv, data);
+}
+
+void hns_mac_get_strings(struct hns_mac_cb *mac_cb,
+ int stringset, u8 *data)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ mac_ctrl_drv->get_strings(stringset, data);
+}
+
+int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ return mac_ctrl_drv->get_sset_count(stringset);
+}
+
+int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ return mac_ctrl_drv->get_regs_count();
+}
+
+void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ mac_ctrl_drv->get_regs(mac_ctrl_drv, data);
+}
+
+void hns_set_led_opt(struct hns_mac_cb *mac_cb)
+{
+ int nic_data = 0;
+ int txpkts, rxpkts;
+
+ txpkts = mac_cb->txpkt_for_led - mac_cb->hw_stats.tx_good_pkts;
+ rxpkts = mac_cb->rxpkt_for_led - mac_cb->hw_stats.rx_good_pkts;
+ if (txpkts || rxpkts)
+ nic_data = 1;
+ else
+ nic_data = 0;
+ mac_cb->txpkt_for_led = mac_cb->hw_stats.tx_good_pkts;
+ mac_cb->rxpkt_for_led = mac_cb->hw_stats.rx_good_pkts;
+ hns_cpld_set_led(mac_cb, (int)mac_cb->link,
+ mac_cb->speed, nic_data);
+}
+
+int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
+ enum hnae_led_state status)
+{
+ if (!mac_cb || !mac_cb->cpld_vaddr)
+ return 0;
+
+ return cpld_set_led_id(mac_cb, status);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
new file mode 100644
index 000000000000..7da95a7581f9
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _HNS_DSAF_MAC_H
+#define _HNS_DSAF_MAC_H
+
+#include <linux/phy.h>
+#include <linux/kernel.h>
+#include <linux/if_vlan.h>
+#include "hns_dsaf_main.h"
+
+struct dsaf_device;
+
+#define MAC_GMAC_SUPPORTED \
+ (SUPPORTED_10baseT_Half \
+ | SUPPORTED_10baseT_Full \
+ | SUPPORTED_100baseT_Half \
+ | SUPPORTED_100baseT_Full \
+ | SUPPORTED_Autoneg)
+
+#define MAC_DEFAULT_MTU (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN + ETH_DATA_LEN)
+#define MAC_MAX_MTU 9600
+#define MAC_MIN_MTU 68
+
+#define MAC_DEFAULT_PAUSE_TIME 0xff
+
+#define MAC_GMAC_IDX 0
+#define MAC_XGMAC_IDX 1
+
+#define ETH_STATIC_REG 1
+#define ETH_DUMP_REG 5
+/* check mac addr broadcast */
+#define MAC_IS_BROADCAST(p) ((*(p) == 0xff) && (*((p) + 1) == 0xff) && \
+ (*((p) + 2) == 0xff) && (*((p) + 3) == 0xff) && \
+ (*((p) + 4) == 0xff) && (*((p) + 5) == 0xff))
+
+/* check mac addr is 01-00-5e-xx-xx-xx*/
+#define MAC_IS_L3_MULTICAST(p) ((*((p) + 0) == 0x01) && \
+ (*((p) + 1) == 0x00) && \
+ (*((p) + 2) == 0x5e))
+
+/*check the mac addr is 0 in all bit*/
+#define MAC_IS_ALL_ZEROS(p) ((*(p) == 0) && (*((p) + 1) == 0) && \
+ (*((p) + 2) == 0) && (*((p) + 3) == 0) && \
+ (*((p) + 4) == 0) && (*((p) + 5) == 0))
+
+/*check mac addr multicast*/
+#define MAC_IS_MULTICAST(p) ((*((u8 *)((p) + 0)) & 0x01) ? (1) : (0))
+
+/**< Number of octets (8-bit bytes) in an ethernet address */
+#define MAC_NUM_OCTETS_PER_ADDR 6
+
+struct mac_priv {
+ void *mac;
+};
+
+/* net speed */
+enum mac_speed {
+ MAC_SPEED_10 = 10, /**< 10 Mbps */
+ MAC_SPEED_100 = 100, /**< 100 Mbps */
+ MAC_SPEED_1000 = 1000, /**< 1000 Mbps = 1 Gbps */
+ MAC_SPEED_10000 = 10000 /**< 10000 Mbps = 10 Gbps */
+};
+
+/*mac interface keyword */
+enum mac_intf {
+ MAC_IF_NONE = 0x00000000, /**< interface not invalid */
+ MAC_IF_MII = 0x00010000, /**< MII interface */
+ MAC_IF_RMII = 0x00020000, /**< RMII interface */
+ MAC_IF_SMII = 0x00030000, /**< SMII interface */
+ MAC_IF_GMII = 0x00040000, /**< GMII interface */
+ MAC_IF_RGMII = 0x00050000, /**< RGMII interface */
+ MAC_IF_TBI = 0x00060000, /**< TBI interface */
+ MAC_IF_RTBI = 0x00070000, /**< RTBI interface */
+ MAC_IF_SGMII = 0x00080000, /**< SGMII interface */
+ MAC_IF_XGMII = 0x00090000, /**< XGMII interface */
+ MAC_IF_QSGMII = 0x000a0000 /**< QSGMII interface */
+};
+
+/*mac mode */
+enum mac_mode {
+ /**< Invalid Ethernet mode */
+ MAC_MODE_INVALID = 0,
+ /**< 10 Mbps MII */
+ MAC_MODE_MII_10 = (MAC_IF_MII | MAC_SPEED_10),
+ /**< 100 Mbps MII */
+ MAC_MODE_MII_100 = (MAC_IF_MII | MAC_SPEED_100),
+ /**< 10 Mbps RMII */
+ MAC_MODE_RMII_10 = (MAC_IF_RMII | MAC_SPEED_10),
+ /**< 100 Mbps RMII */
+ MAC_MODE_RMII_100 = (MAC_IF_RMII | MAC_SPEED_100),
+ /**< 10 Mbps SMII */
+ MAC_MODE_SMII_10 = (MAC_IF_SMII | MAC_SPEED_10),
+ /**< 100 Mbps SMII */
+ MAC_MODE_SMII_100 = (MAC_IF_SMII | MAC_SPEED_100),
+ /**< 1000 Mbps GMII */
+ MAC_MODE_GMII_1000 = (MAC_IF_GMII | MAC_SPEED_1000),
+ /**< 10 Mbps RGMII */
+ MAC_MODE_RGMII_10 = (MAC_IF_RGMII | MAC_SPEED_10),
+ /**< 100 Mbps RGMII */
+ MAC_MODE_RGMII_100 = (MAC_IF_RGMII | MAC_SPEED_100),
+ /**< 1000 Mbps RGMII */
+ MAC_MODE_RGMII_1000 = (MAC_IF_RGMII | MAC_SPEED_1000),
+ /**< 1000 Mbps TBI */
+ MAC_MODE_TBI_1000 = (MAC_IF_TBI | MAC_SPEED_1000),
+ /**< 1000 Mbps RTBI */
+ MAC_MODE_RTBI_1000 = (MAC_IF_RTBI | MAC_SPEED_1000),
+ /**< 10 Mbps SGMII */
+ MAC_MODE_SGMII_10 = (MAC_IF_SGMII | MAC_SPEED_10),
+ /**< 100 Mbps SGMII */
+ MAC_MODE_SGMII_100 = (MAC_IF_SGMII | MAC_SPEED_100),
+ /**< 1000 Mbps SGMII */
+ MAC_MODE_SGMII_1000 = (MAC_IF_SGMII | MAC_SPEED_1000),
+ /**< 10000 Mbps XGMII */
+ MAC_MODE_XGMII_10000 = (MAC_IF_XGMII | MAC_SPEED_10000),
+ /**< 1000 Mbps QSGMII */
+ MAC_MODE_QSGMII_1000 = (MAC_IF_QSGMII | MAC_SPEED_1000)
+};
+
+/*mac communicate mode*/
+enum mac_commom_mode {
+ MAC_COMM_MODE_NONE = 0, /**< No transmit/receive communication */
+ MAC_COMM_MODE_RX = 1, /**< Only receive communication */
+ MAC_COMM_MODE_TX = 2, /**< Only transmit communication */
+ MAC_COMM_MODE_RX_AND_TX = 3 /**< Both tx and rx communication */
+};
+
+/*mac statistics */
+struct mac_statistics {
+ u64 stat_pkts64; /* r-10G tr-DT 64 byte frame counter */
+ u64 stat_pkts65to127; /* r-10G 65 to 127 byte frame counter */
+ u64 stat_pkts128to255; /* r-10G 128 to 255 byte frame counter */
+ u64 stat_pkts256to511; /*r-10G 256 to 511 byte frame counter */
+ u64 stat_pkts512to1023;/* r-10G 512 to 1023 byte frame counter */
+ u64 stat_pkts1024to1518; /* r-10G 1024 to 1518 byte frame counter */
+ u64 stat_pkts1519to1522; /* r-10G 1519 to 1522 byte good frame count*/
+ /* Total number of packets that were less than 64 octets */
+ /* long with a wrong CRC.*/
+ u64 stat_fragments;
+ /* Total number of packets longer than valid maximum length octets */
+ u64 stat_jabbers;
+ /* number of dropped packets due to internal errors of */
+ /* the MAC Client. */
+ u64 stat_drop_events;
+ /* Incremented when frames of correct length but with */
+ /* CRC error are received.*/
+ u64 stat_crc_align_errors;
+ /* Total number of packets that were less than 64 octets */
+ /* long with a good CRC.*/
+ u64 stat_undersize_pkts;
+ u64 stat_oversize_pkts; /**< T,B.D*/
+
+ u64 stat_rx_pause; /**< Pause MAC Control received */
+ u64 stat_tx_pause; /**< Pause MAC Control sent */
+
+ u64 in_octets; /**< Total number of byte received. */
+ u64 in_pkts; /* Total number of packets received.*/
+ u64 in_mcast_pkts; /* Total number of multicast frame received */
+ u64 in_bcast_pkts; /* Total number of broadcast frame received */
+ /* Frames received, but discarded due to */
+ /* problems within the MAC RX. */
+ u64 in_discards;
+ u64 in_errors; /* Number of frames received with error: */
+ /* - FIFO Overflow Error */
+ /* - CRC Error */
+ /* - Frame Too Long Error */
+ /* - Alignment Error */
+ u64 out_octets; /*Total number of byte sent. */
+ u64 out_pkts; /**< Total number of packets sent .*/
+ u64 out_mcast_pkts; /* Total number of multicast frame sent */
+ u64 out_bcast_pkts; /* Total number of multicast frame sent */
+ /* Frames received, but discarded due to problems within */
+ /* the MAC TX N/A!.*/
+ u64 out_discards;
+ u64 out_errors; /*Number of frames transmitted with error: */
+ /* - FIFO Overflow Error */
+ /* - FIFO Underflow Error */
+ /* - Other */
+};
+
+/*mac para struct ,mac get param from nic or dsaf when initialize*/
+struct mac_params {
+ char addr[MAC_NUM_OCTETS_PER_ADDR];
+ void *vaddr; /*virtual address*/
+ struct device *dev;
+ u8 mac_id;
+ /**< Ethernet operation mode (MAC-PHY interface and speed) */
+ enum mac_mode mac_mode;
+};
+
+struct mac_info {
+ u16 speed;/* The forced speed (lower bits) in */
+ /* *mbps. Please use */
+ /* * ethtool_cmd_speed()/_set() to */
+ /* * access it */
+ u8 duplex; /* Duplex, half or full */
+ u8 auto_neg; /* Enable or disable autonegotiation */
+ enum hnae_loop loop_mode;
+ u8 tx_pause_en;
+ u8 tx_pause_time;
+ u8 rx_pause_en;
+ u8 pad_and_crc_en;
+ u8 promiscuous_en;
+ u8 port_en; /*port enable*/
+};
+
+struct mac_entry_idx {
+ u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+ u16 vlan_id:12;
+ u16 valid:1;
+ u16 qos:3;
+};
+
+struct mac_hw_stats {
+ u64 rx_good_pkts; /* only for xgmac */
+ u64 rx_good_bytes;
+ u64 rx_total_pkts; /* only for xgmac */
+ u64 rx_total_bytes; /* only for xgmac */
+ u64 rx_bad_bytes; /* only for gmac */
+ u64 rx_uc_pkts;
+ u64 rx_mc_pkts;
+ u64 rx_bc_pkts;
+ u64 rx_fragment_err; /* only for xgmac */
+ u64 rx_undersize; /* only for xgmac */
+ u64 rx_under_min;
+ u64 rx_minto64; /* only for gmac */
+ u64 rx_64bytes;
+ u64 rx_65to127;
+ u64 rx_128to255;
+ u64 rx_256to511;
+ u64 rx_512to1023;
+ u64 rx_1024to1518;
+ u64 rx_1519tomax;
+ u64 rx_1519tomax_good; /* only for xgmac */
+ u64 rx_oversize;
+ u64 rx_jabber_err;
+ u64 rx_fcs_err;
+ u64 rx_vlan_pkts; /* only for gmac */
+ u64 rx_data_err; /* only for gmac */
+ u64 rx_align_err; /* only for gmac */
+ u64 rx_long_err; /* only for gmac */
+ u64 rx_pfc_tc0;
+ u64 rx_pfc_tc1; /* only for xgmac */
+ u64 rx_pfc_tc2; /* only for xgmac */
+ u64 rx_pfc_tc3; /* only for xgmac */
+ u64 rx_pfc_tc4; /* only for xgmac */
+ u64 rx_pfc_tc5; /* only for xgmac */
+ u64 rx_pfc_tc6; /* only for xgmac */
+ u64 rx_pfc_tc7; /* only for xgmac */
+ u64 rx_unknown_ctrl;
+ u64 rx_filter_pkts; /* only for gmac */
+ u64 rx_filter_bytes; /* only for gmac */
+ u64 rx_fifo_overrun_err;/* only for gmac */
+ u64 rx_len_err; /* only for gmac */
+ u64 rx_comma_err; /* only for gmac */
+ u64 rx_symbol_err; /* only for xgmac */
+ u64 tx_good_to_sw; /* only for xgmac */
+ u64 tx_bad_to_sw; /* only for xgmac */
+ u64 rx_1731_pkts; /* only for xgmac */
+
+ u64 tx_good_bytes;
+ u64 tx_good_pkts; /* only for xgmac */
+ u64 tx_total_bytes; /* only for xgmac */
+ u64 tx_total_pkts; /* only for xgmac */
+ u64 tx_bad_bytes; /* only for gmac */
+ u64 tx_bad_pkts; /* only for xgmac */
+ u64 tx_uc_pkts;
+ u64 tx_mc_pkts;
+ u64 tx_bc_pkts;
+ u64 tx_undersize; /* only for xgmac */
+ u64 tx_fragment_err; /* only for xgmac */
+ u64 tx_under_min_pkts; /* only for gmac */
+ u64 tx_64bytes;
+ u64 tx_65to127;
+ u64 tx_128to255;
+ u64 tx_256to511;
+ u64 tx_512to1023;
+ u64 tx_1024to1518;
+ u64 tx_1519tomax;
+ u64 tx_1519tomax_good; /* only for xgmac */
+ u64 tx_oversize; /* only for xgmac */
+ u64 tx_jabber_err;
+ u64 tx_underrun_err; /* only for gmac */
+ u64 tx_vlan; /* only for gmac */
+ u64 tx_crc_err; /* only for gmac */
+ u64 tx_pfc_tc0;
+ u64 tx_pfc_tc1; /* only for xgmac */
+ u64 tx_pfc_tc2; /* only for xgmac */
+ u64 tx_pfc_tc3; /* only for xgmac */
+ u64 tx_pfc_tc4; /* only for xgmac */
+ u64 tx_pfc_tc5; /* only for xgmac */
+ u64 tx_pfc_tc6; /* only for xgmac */
+ u64 tx_pfc_tc7; /* only for xgmac */
+ u64 tx_ctrl; /* only for xgmac */
+ u64 tx_1731_pkts; /* only for xgmac */
+ u64 tx_1588_pkts; /* only for xgmac */
+ u64 rx_good_from_sw; /* only for xgmac */
+ u64 rx_bad_from_sw; /* only for xgmac */
+};
+
+struct hns_mac_cb {
+ struct device *dev;
+ struct dsaf_device *dsaf_dev;
+ struct mac_priv priv;
+ u8 __iomem *vaddr;
+ u8 __iomem *cpld_vaddr;
+ u8 __iomem *sys_ctl_vaddr;
+ u8 __iomem *serdes_vaddr;
+ struct mac_entry_idx addr_entry_idx[DSAF_MAX_VM_NUM];
+ u8 sfp_prsnt;
+ u8 cpld_led_value;
+ u8 mac_id;
+
+ u8 link;
+ u8 half_duplex;
+ u16 speed;
+ u16 max_speed;
+ u16 max_frm;
+ u16 tx_pause_frm_time;
+ u32 if_support;
+ u64 txpkt_for_led;
+ u64 rxpkt_for_led;
+ enum hnae_port_type mac_type;
+ phy_interface_t phy_if;
+ enum hnae_loop loop_mode;
+
+ struct device_node *phy_node;
+
+ struct mac_hw_stats hw_stats;
+};
+
+struct mac_driver {
+ /*init Mac when init nic or dsaf*/
+ void (*mac_init)(void *mac_drv);
+ /*remove mac when remove nic or dsaf*/
+ void (*mac_free)(void *mac_drv);
+ /*enable mac when enable nic or dsaf*/
+ void (*mac_enable)(void *mac_drv, enum mac_commom_mode mode);
+ /*disable mac when disable nic or dsaf*/
+ void (*mac_disable)(void *mac_drv, enum mac_commom_mode mode);
+ /* config mac address*/
+ void (*set_mac_addr)(void *mac_drv, char *mac_addr);
+ /*adjust mac mode of port,include speed and duplex*/
+ int (*adjust_link)(void *mac_drv, enum mac_speed speed,
+ u32 full_duplex);
+ /* config autoegotaite mode of port*/
+ void (*set_an_mode)(void *mac_drv, u8 enable);
+ /* config loopbank mode */
+ int (*config_loopback)(void *mac_drv, enum hnae_loop loop_mode,
+ u8 enable);
+ /* config mtu*/
+ void (*config_max_frame_length)(void *mac_drv, u16 newval);
+ /*config PAD and CRC enable */
+ void (*config_pad_and_crc)(void *mac_drv, u8 newval);
+ /* config duplex mode*/
+ void (*config_half_duplex)(void *mac_drv, u8 newval);
+ /*config tx pause time,if pause_time is zero,disable tx pause enable*/
+ void (*set_tx_auto_pause_frames)(void *mac_drv, u16 pause_time);
+ /*config rx pause enable*/
+ void (*set_rx_ignore_pause_frames)(void *mac_drv, u32 enable);
+ /* config rx mode for promiscuous*/
+ int (*set_promiscuous)(void *mac_drv, u8 enable);
+ /* get mac id */
+ void (*mac_get_id)(void *mac_drv, u8 *mac_id);
+ void (*mac_pausefrm_cfg)(void *mac_drv, u32 rx_en, u32 tx_en);
+
+ void (*autoneg_stat)(void *mac_drv, u32 *enable);
+ int (*set_pause_enable)(void *mac_drv, u32 rx_en, u32 tx_en);
+ void (*get_pause_enable)(void *mac_drv, u32 *rx_en, u32 *tx_en);
+ void (*get_link_status)(void *mac_drv, u32 *link_stat);
+ /* get the imporant regs*/
+ void (*get_regs)(void *mac_drv, void *data);
+ int (*get_regs_count)(void);
+ /* get strings name for ethtool statistic */
+ void (*get_strings)(u32 stringset, u8 *data);
+ /* get the number of strings*/
+ int (*get_sset_count)(int stringset);
+
+ /* get the statistic by ethtools*/
+ void (*get_ethtool_stats)(void *mac_drv, u64 *data);
+
+ /* get mac information */
+ void (*get_info)(void *mac_drv, struct mac_info *mac_info);
+
+ void (*update_stats)(void *mac_drv);
+
+ enum mac_mode mac_mode;
+ u8 mac_id;
+ struct hns_mac_cb *mac_cb;
+ void __iomem *io_base;
+ unsigned int mac_en_flg;/*you'd better don't enable mac twice*/
+ unsigned int virt_dev_num;
+ struct device *dev;
+};
+
+struct mac_stats_string {
+ char desc[64];
+ unsigned long offset;
+};
+
+#define MAC_MAKE_MODE(interface, speed) (enum mac_mode)((interface) | (speed))
+#define MAC_INTERFACE_FROM_MODE(mode) (enum mac_intf)((mode) & 0xFFFF0000)
+#define MAC_SPEED_FROM_MODE(mode) (enum mac_speed)((mode) & 0x0000FFFF)
+#define MAC_STATS_FIELD_OFF(field) (offsetof(struct mac_hw_stats, field))
+
+static inline struct mac_driver *hns_mac_get_drv(
+ const struct hns_mac_cb *mac_cb)
+{
+ return (struct mac_driver *)(mac_cb->priv.mac);
+}
+
+void *hns_gmac_config(struct hns_mac_cb *mac_cb,
+ struct mac_params *mac_param);
+void *hns_xgmac_config(struct hns_mac_cb *mac_cb,
+ struct mac_params *mac_param);
+
+int hns_mac_init(struct dsaf_device *dsaf_dev);
+void mac_adjust_link(struct net_device *net_dev);
+void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status);
+int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, char *addr);
+int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
+ u32 port_num, char *addr, u8 en);
+int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vm, u8 en);
+void hns_mac_start(struct hns_mac_cb *mac_cb);
+void hns_mac_stop(struct hns_mac_cb *mac_cb);
+int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac);
+void hns_mac_uninit(struct dsaf_device *dsaf_dev);
+void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex);
+void hns_mac_reset(struct hns_mac_cb *mac_cb);
+void hns_mac_get_autoneg(struct hns_mac_cb *mac_cb, u32 *auto_neg);
+void hns_mac_get_pauseparam(struct hns_mac_cb *mac_cb, u32 *rx_en, u32 *tx_en);
+int hns_mac_set_autoneg(struct hns_mac_cb *mac_cb, u8 enable);
+int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en);
+int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu);
+int hns_mac_get_port_info(struct hns_mac_cb *mac_cb,
+ u8 *auto_neg, u16 *speed, u8 *duplex);
+phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb);
+int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en);
+int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb,
+ enum hnae_loop loop, int en);
+void hns_mac_update_stats(struct hns_mac_cb *mac_cb);
+void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data);
+void hns_mac_get_strings(struct hns_mac_cb *mac_cb, int stringset, u8 *data);
+int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset);
+void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data);
+int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb);
+void hns_set_led_opt(struct hns_mac_cb *mac_cb);
+int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
+ enum hnae_led_state status);
+#endif /* _HNS_DSAF_MAC_H */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
new file mode 100644
index 000000000000..2a98eba660c0
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -0,0 +1,2474 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_rcb.h"
+#include "hns_dsaf_ppe.h"
+#include "hns_dsaf_mac.h"
+
+const char *g_dsaf_mode_match[DSAF_MODE_MAX] = {
+ [DSAF_MODE_DISABLE_2PORT_64VM] = "2port-64vf",
+ [DSAF_MODE_DISABLE_6PORT_0VM] = "6port-16rss",
+ [DSAF_MODE_DISABLE_6PORT_16VM] = "6port-16vf",
+};
+
+int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
+{
+ int ret, i;
+ u32 desc_num;
+ u32 buf_size;
+ const char *name, *mode_str;
+ struct device_node *np = dsaf_dev->dev->of_node;
+
+ if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v2"))
+ dsaf_dev->dsaf_ver = AE_VERSION_2;
+ else
+ dsaf_dev->dsaf_ver = AE_VERSION_1;
+
+ ret = of_property_read_string(np, "dsa_name", &name);
+ if (ret) {
+ dev_err(dsaf_dev->dev, "get dsaf name fail, ret=%d!\n", ret);
+ return ret;
+ }
+ strncpy(dsaf_dev->ae_dev.name, name, AE_NAME_SIZE);
+ dsaf_dev->ae_dev.name[AE_NAME_SIZE - 1] = '\0';
+
+ ret = of_property_read_string(np, "mode", &mode_str);
+ if (ret) {
+ dev_err(dsaf_dev->dev, "get dsaf mode fail, ret=%d!\n", ret);
+ return ret;
+ }
+ for (i = 0; i < DSAF_MODE_MAX; i++) {
+ if (g_dsaf_mode_match[i] &&
+ !strcmp(mode_str, g_dsaf_mode_match[i]))
+ break;
+ }
+ if (i >= DSAF_MODE_MAX ||
+ i == DSAF_MODE_INVALID || i == DSAF_MODE_ENABLE) {
+ dev_err(dsaf_dev->dev,
+ "%s prs mode str fail!\n", dsaf_dev->ae_dev.name);
+ return -EINVAL;
+ }
+ dsaf_dev->dsaf_mode = (enum dsaf_mode)i;
+
+ if (dsaf_dev->dsaf_mode > DSAF_MODE_ENABLE)
+ dsaf_dev->dsaf_en = HRD_DSAF_NO_DSAF_MODE;
+ else
+ dsaf_dev->dsaf_en = HRD_DSAF_MODE;
+
+ if ((i == DSAF_MODE_ENABLE_16VM) ||
+ (i == DSAF_MODE_DISABLE_2PORT_8VM) ||
+ (i == DSAF_MODE_DISABLE_6PORT_2VM))
+ dsaf_dev->dsaf_tc_mode = HRD_DSAF_8TC_MODE;
+ else
+ dsaf_dev->dsaf_tc_mode = HRD_DSAF_4TC_MODE;
+
+ dsaf_dev->sc_base = of_iomap(np, 0);
+ if (!dsaf_dev->sc_base) {
+ dev_err(dsaf_dev->dev,
+ "%s of_iomap 0 fail!\n", dsaf_dev->ae_dev.name);
+ ret = -ENOMEM;
+ goto unmap_base_addr;
+ }
+
+ dsaf_dev->sds_base = of_iomap(np, 1);
+ if (!dsaf_dev->sds_base) {
+ dev_err(dsaf_dev->dev,
+ "%s of_iomap 1 fail!\n", dsaf_dev->ae_dev.name);
+ ret = -ENOMEM;
+ goto unmap_base_addr;
+ }
+
+ dsaf_dev->ppe_base = of_iomap(np, 2);
+ if (!dsaf_dev->ppe_base) {
+ dev_err(dsaf_dev->dev,
+ "%s of_iomap 2 fail!\n", dsaf_dev->ae_dev.name);
+ ret = -ENOMEM;
+ goto unmap_base_addr;
+ }
+
+ dsaf_dev->io_base = of_iomap(np, 3);
+ if (!dsaf_dev->io_base) {
+ dev_err(dsaf_dev->dev,
+ "%s of_iomap 3 fail!\n", dsaf_dev->ae_dev.name);
+ ret = -ENOMEM;
+ goto unmap_base_addr;
+ }
+
+ dsaf_dev->cpld_base = of_iomap(np, 4);
+ if (!dsaf_dev->cpld_base)
+ dev_dbg(dsaf_dev->dev, "NO CPLD ADDR");
+
+ ret = of_property_read_u32(np, "desc-num", &desc_num);
+ if (ret < 0 || desc_num < HNS_DSAF_MIN_DESC_CNT ||
+ desc_num > HNS_DSAF_MAX_DESC_CNT) {
+ dev_err(dsaf_dev->dev, "get desc-num(%d) fail, ret=%d!\n",
+ desc_num, ret);
+ goto unmap_base_addr;
+ }
+ dsaf_dev->desc_num = desc_num;
+
+ ret = of_property_read_u32(np, "buf-size", &buf_size);
+ if (ret < 0) {
+ dev_err(dsaf_dev->dev,
+ "get buf-size fail, ret=%d!\r\n", ret);
+ goto unmap_base_addr;
+ }
+ dsaf_dev->buf_size = buf_size;
+
+ dsaf_dev->buf_size_type = hns_rcb_buf_size2type(buf_size);
+ if (dsaf_dev->buf_size_type < 0) {
+ dev_err(dsaf_dev->dev,
+ "buf_size(%d) is wrong!\n", buf_size);
+ goto unmap_base_addr;
+ }
+
+ if (!dma_set_mask_and_coherent(dsaf_dev->dev, DMA_BIT_MASK(64ULL)))
+ dev_dbg(dsaf_dev->dev, "set mask to 64bit\n");
+ else
+ dev_err(dsaf_dev->dev, "set mask to 64bit fail!\n");
+
+ return 0;
+
+unmap_base_addr:
+ if (dsaf_dev->io_base)
+ iounmap(dsaf_dev->io_base);
+ if (dsaf_dev->ppe_base)
+ iounmap(dsaf_dev->ppe_base);
+ if (dsaf_dev->sds_base)
+ iounmap(dsaf_dev->sds_base);
+ if (dsaf_dev->sc_base)
+ iounmap(dsaf_dev->sc_base);
+ if (dsaf_dev->cpld_base)
+ iounmap(dsaf_dev->cpld_base);
+ return ret;
+}
+
+static void hns_dsaf_free_cfg(struct dsaf_device *dsaf_dev)
+{
+ if (dsaf_dev->io_base)
+ iounmap(dsaf_dev->io_base);
+
+ if (dsaf_dev->ppe_base)
+ iounmap(dsaf_dev->ppe_base);
+
+ if (dsaf_dev->sds_base)
+ iounmap(dsaf_dev->sds_base);
+
+ if (dsaf_dev->sc_base)
+ iounmap(dsaf_dev->sc_base);
+
+ if (dsaf_dev->cpld_base)
+ iounmap(dsaf_dev->cpld_base);
+}
+
+/**
+ * hns_dsaf_sbm_link_sram_init_en - config dsaf_sbm_init_en
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_sbm_link_sram_init_en(struct dsaf_device *dsaf_dev)
+{
+ dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_SBM_INIT_S, 1);
+}
+
+/**
+ * hns_dsaf_reg_cnt_clr_ce - config hns_dsaf_reg_cnt_clr_ce
+ * @dsaf_id: dsa fabric id
+ * @hns_dsaf_reg_cnt_clr_ce: config value
+ */
+static void
+hns_dsaf_reg_cnt_clr_ce(struct dsaf_device *dsaf_dev, u32 reg_cnt_clr_ce)
+{
+ dsaf_set_dev_bit(dsaf_dev, DSAF_DSA_REG_CNT_CLR_CE_REG,
+ DSAF_CNT_CLR_CE_S, reg_cnt_clr_ce);
+}
+
+/**
+ * hns_ppe_qid_cfg - config ppe qid
+ * @dsaf_id: dsa fabric id
+ * @pppe_qid_cfg: value array
+ */
+static void
+hns_dsaf_ppe_qid_cfg(struct dsaf_device *dsaf_dev, u32 qid_cfg)
+{
+ u32 i;
+
+ for (i = 0; i < DSAF_COMM_CHN; i++) {
+ dsaf_set_dev_field(dsaf_dev,
+ DSAF_PPE_QID_CFG_0_REG + 0x0004 * i,
+ DSAF_PPE_QID_CFG_M, DSAF_PPE_QID_CFG_S,
+ qid_cfg);
+ }
+}
+
+static void hns_dsaf_mix_def_qid_cfg(struct dsaf_device *dsaf_dev)
+{
+ u16 max_q_per_vf, max_vfn;
+ u32 q_id, q_num_per_port;
+ u32 i;
+
+ hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode,
+ HNS_DSAF_COMM_SERVICE_NW_IDX,
+ &max_vfn, &max_q_per_vf);
+ q_num_per_port = max_vfn * max_q_per_vf;
+
+ for (i = 0, q_id = 0; i < DSAF_SERVICE_NW_NUM; i++) {
+ dsaf_set_dev_field(dsaf_dev,
+ DSAF_MIX_DEF_QID_0_REG + 0x0004 * i,
+ 0xff, 0, q_id);
+ q_id += q_num_per_port;
+ }
+}
+
+/**
+ * hns_dsaf_sw_port_type_cfg - cfg sw type
+ * @dsaf_id: dsa fabric id
+ * @psw_port_type: array
+ */
+static void hns_dsaf_sw_port_type_cfg(struct dsaf_device *dsaf_dev,
+ enum dsaf_sw_port_type port_type)
+{
+ u32 i;
+
+ for (i = 0; i < DSAF_SW_PORT_NUM; i++) {
+ dsaf_set_dev_field(dsaf_dev,
+ DSAF_SW_PORT_TYPE_0_REG + 0x0004 * i,
+ DSAF_SW_PORT_TYPE_M, DSAF_SW_PORT_TYPE_S,
+ port_type);
+ }
+}
+
+/**
+ * hns_dsaf_stp_port_type_cfg - cfg stp type
+ * @dsaf_id: dsa fabric id
+ * @pstp_port_type: array
+ */
+static void hns_dsaf_stp_port_type_cfg(struct dsaf_device *dsaf_dev,
+ enum dsaf_stp_port_type port_type)
+{
+ u32 i;
+
+ for (i = 0; i < DSAF_COMM_CHN; i++) {
+ dsaf_set_dev_field(dsaf_dev,
+ DSAF_STP_PORT_TYPE_0_REG + 0x0004 * i,
+ DSAF_STP_PORT_TYPE_M, DSAF_STP_PORT_TYPE_S,
+ port_type);
+ }
+}
+
+/**
+ * hns_dsaf_sbm_cfg - config sbm
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_sbm_cfg(struct dsaf_device *dsaf_dev)
+{
+ u32 o_sbm_cfg;
+ u32 i;
+
+ for (i = 0; i < DSAF_SBM_NUM; i++) {
+ o_sbm_cfg = dsaf_read_dev(dsaf_dev,
+ DSAF_SBM_CFG_REG_0_REG + 0x80 * i);
+ dsaf_set_bit(o_sbm_cfg, DSAF_SBM_CFG_EN_S, 1);
+ dsaf_set_bit(o_sbm_cfg, DSAF_SBM_CFG_SHCUT_EN_S, 0);
+ dsaf_write_dev(dsaf_dev,
+ DSAF_SBM_CFG_REG_0_REG + 0x80 * i, o_sbm_cfg);
+ }
+}
+
+/**
+ * hns_dsaf_sbm_cfg_mib_en - config sbm
+ * @dsaf_id: dsa fabric id
+ */
+static int hns_dsaf_sbm_cfg_mib_en(struct dsaf_device *dsaf_dev)
+{
+ u32 sbm_cfg_mib_en;
+ u32 i;
+ u32 reg;
+ u32 read_cnt;
+
+ for (i = 0; i < DSAF_SBM_NUM; i++) {
+ reg = DSAF_SBM_CFG_REG_0_REG + 0x80 * i;
+ dsaf_set_dev_bit(dsaf_dev, reg, DSAF_SBM_CFG_MIB_EN_S, 1);
+ }
+
+ /* waitint for all sbm enable finished */
+ for (i = 0; i < DSAF_SBM_NUM; i++) {
+ read_cnt = 0;
+ reg = DSAF_SBM_CFG_REG_0_REG + 0x80 * i;
+ do {
+ udelay(1);
+ sbm_cfg_mib_en = dsaf_get_dev_bit(
+ dsaf_dev, reg, DSAF_SBM_CFG_MIB_EN_S);
+ read_cnt++;
+ } while (sbm_cfg_mib_en == 0 &&
+ read_cnt < DSAF_CFG_READ_CNT);
+
+ if (sbm_cfg_mib_en == 0) {
+ dev_err(dsaf_dev->dev,
+ "sbm_cfg_mib_en fail,%s,sbm_num=%d\n",
+ dsaf_dev->ae_dev.name, i);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_sbm_bp_wl_cfg - config sbm
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_sbm_bp_wl_cfg(struct dsaf_device *dsaf_dev)
+{
+ u32 o_sbm_bp_cfg0;
+ u32 o_sbm_bp_cfg1;
+ u32 o_sbm_bp_cfg2;
+ u32 o_sbm_bp_cfg3;
+ u32 reg;
+ u32 i;
+
+ /* XGE */
+ for (i = 0; i < DSAF_XGE_NUM; i++) {
+ reg = DSAF_SBM_BP_CFG_0_XGE_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg0 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg0, DSAF_SBM_CFG0_COM_MAX_BUF_NUM_M,
+ DSAF_SBM_CFG0_COM_MAX_BUF_NUM_S, 512);
+ dsaf_set_field(o_sbm_bp_cfg0, DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_M,
+ DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_S, 0);
+ dsaf_set_field(o_sbm_bp_cfg0, DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_M,
+ DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_S, 0);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg0);
+
+ reg = DSAF_SBM_BP_CFG_1_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg1 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg1, DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_M,
+ DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_S, 0);
+ dsaf_set_field(o_sbm_bp_cfg1, DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_M,
+ DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_S, 0);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg1);
+
+ reg = DSAF_SBM_BP_CFG_2_XGE_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg2 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_SET_BUF_NUM_M,
+ DSAF_SBM_CFG2_SET_BUF_NUM_S, 104);
+ dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_RESET_BUF_NUM_M,
+ DSAF_SBM_CFG2_RESET_BUF_NUM_S, 128);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg2);
+
+ reg = DSAF_SBM_BP_CFG_3_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg3 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg3,
+ DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_M,
+ DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 110);
+ dsaf_set_field(o_sbm_bp_cfg3,
+ DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M,
+ DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 160);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg3);
+
+ /* for no enable pfc mode */
+ reg = DSAF_SBM_BP_CFG_4_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg3 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg3,
+ DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_M,
+ DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 128);
+ dsaf_set_field(o_sbm_bp_cfg3,
+ DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M,
+ DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 192);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg3);
+ }
+
+ /* PPE */
+ for (i = 0; i < DSAF_COMM_CHN; i++) {
+ reg = DSAF_SBM_BP_CFG_2_PPE_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg2 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_SET_BUF_NUM_M,
+ DSAF_SBM_CFG2_SET_BUF_NUM_S, 10);
+ dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_RESET_BUF_NUM_M,
+ DSAF_SBM_CFG2_RESET_BUF_NUM_S, 12);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg2);
+ }
+
+ /* RoCEE */
+ for (i = 0; i < DSAF_COMM_CHN; i++) {
+ reg = DSAF_SBM_BP_CFG_2_ROCEE_REG_0_REG + 0x80 * i;
+ o_sbm_bp_cfg2 = dsaf_read_dev(dsaf_dev, reg);
+ dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_SET_BUF_NUM_M,
+ DSAF_SBM_CFG2_SET_BUF_NUM_S, 2);
+ dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_RESET_BUF_NUM_M,
+ DSAF_SBM_CFG2_RESET_BUF_NUM_S, 4);
+ dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg2);
+ }
+}
+
+/**
+ * hns_dsaf_voq_bp_all_thrd_cfg - voq
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_voq_bp_all_thrd_cfg(struct dsaf_device *dsaf_dev)
+{
+ u32 voq_bp_all_thrd;
+ u32 i;
+
+ for (i = 0; i < DSAF_VOQ_NUM; i++) {
+ voq_bp_all_thrd = dsaf_read_dev(
+ dsaf_dev, DSAF_VOQ_BP_ALL_THRD_0_REG + 0x40 * i);
+ if (i < DSAF_XGE_NUM) {
+ dsaf_set_field(voq_bp_all_thrd,
+ DSAF_VOQ_BP_ALL_DOWNTHRD_M,
+ DSAF_VOQ_BP_ALL_DOWNTHRD_S, 930);
+ dsaf_set_field(voq_bp_all_thrd,
+ DSAF_VOQ_BP_ALL_UPTHRD_M,
+ DSAF_VOQ_BP_ALL_UPTHRD_S, 950);
+ } else {
+ dsaf_set_field(voq_bp_all_thrd,
+ DSAF_VOQ_BP_ALL_DOWNTHRD_M,
+ DSAF_VOQ_BP_ALL_DOWNTHRD_S, 220);
+ dsaf_set_field(voq_bp_all_thrd,
+ DSAF_VOQ_BP_ALL_UPTHRD_M,
+ DSAF_VOQ_BP_ALL_UPTHRD_S, 230);
+ }
+ dsaf_write_dev(
+ dsaf_dev, DSAF_VOQ_BP_ALL_THRD_0_REG + 0x40 * i,
+ voq_bp_all_thrd);
+ }
+}
+
+/**
+ * hns_dsaf_tbl_tcam_data_cfg - tbl
+ * @dsaf_id: dsa fabric id
+ * @ptbl_tcam_data: addr
+ */
+static void hns_dsaf_tbl_tcam_data_cfg(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_tbl_tcam_data *ptbl_tcam_data)
+{
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_LOW_0_REG,
+ ptbl_tcam_data->tbl_tcam_data_low);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_HIGH_0_REG,
+ ptbl_tcam_data->tbl_tcam_data_high);
+}
+
+/**
+ * dsaf_tbl_tcam_mcast_cfg - tbl
+ * @dsaf_id: dsa fabric id
+ * @ptbl_tcam_mcast: addr
+ */
+static void hns_dsaf_tbl_tcam_mcast_cfg(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_tbl_tcam_mcast_cfg *mcast)
+{
+ u32 mcast_cfg4;
+
+ mcast_cfg4 = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG);
+ dsaf_set_bit(mcast_cfg4, DSAF_TBL_MCAST_CFG4_ITEM_VLD_S,
+ mcast->tbl_mcast_item_vld);
+ dsaf_set_bit(mcast_cfg4, DSAF_TBL_MCAST_CFG4_OLD_EN_S,
+ mcast->tbl_mcast_old_en);
+ dsaf_set_field(mcast_cfg4, DSAF_TBL_MCAST_CFG4_VM128_112_M,
+ DSAF_TBL_MCAST_CFG4_VM128_112_S,
+ mcast->tbl_mcast_port_msk[4]);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG, mcast_cfg4);
+
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG,
+ mcast->tbl_mcast_port_msk[3]);
+
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG,
+ mcast->tbl_mcast_port_msk[2]);
+
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG,
+ mcast->tbl_mcast_port_msk[1]);
+
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG,
+ mcast->tbl_mcast_port_msk[0]);
+}
+
+/**
+ * hns_dsaf_tbl_tcam_ucast_cfg - tbl
+ * @dsaf_id: dsa fabric id
+ * @ptbl_tcam_ucast: addr
+ */
+static void hns_dsaf_tbl_tcam_ucast_cfg(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_tbl_tcam_ucast_cfg *tbl_tcam_ucast)
+{
+ u32 ucast_cfg1;
+
+ ucast_cfg1 = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_UCAST_CFG_0_REG);
+ dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_MAC_DISCARD_S,
+ tbl_tcam_ucast->tbl_ucast_mac_discard);
+ dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_ITEM_VLD_S,
+ tbl_tcam_ucast->tbl_ucast_item_vld);
+ dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_OLD_EN_S,
+ tbl_tcam_ucast->tbl_ucast_old_en);
+ dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_DVC_S,
+ tbl_tcam_ucast->tbl_ucast_dvc);
+ dsaf_set_field(ucast_cfg1, DSAF_TBL_UCAST_CFG1_OUT_PORT_M,
+ DSAF_TBL_UCAST_CFG1_OUT_PORT_S,
+ tbl_tcam_ucast->tbl_ucast_out_port);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_UCAST_CFG_0_REG, ucast_cfg1);
+}
+
+/**
+ * hns_dsaf_tbl_line_cfg - tbl
+ * @dsaf_id: dsa fabric id
+ * @ptbl_lin: addr
+ */
+static void hns_dsaf_tbl_line_cfg(struct dsaf_device *dsaf_dev,
+ struct dsaf_tbl_line_cfg *tbl_lin)
+{
+ u32 tbl_line;
+
+ tbl_line = dsaf_read_dev(dsaf_dev, DSAF_TBL_LIN_CFG_0_REG);
+ dsaf_set_bit(tbl_line, DSAF_TBL_LINE_CFG_MAC_DISCARD_S,
+ tbl_lin->tbl_line_mac_discard);
+ dsaf_set_bit(tbl_line, DSAF_TBL_LINE_CFG_DVC_S,
+ tbl_lin->tbl_line_dvc);
+ dsaf_set_field(tbl_line, DSAF_TBL_LINE_CFG_OUT_PORT_M,
+ DSAF_TBL_LINE_CFG_OUT_PORT_S,
+ tbl_lin->tbl_line_out_port);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_LIN_CFG_0_REG, tbl_line);
+}
+
+/**
+ * hns_dsaf_tbl_tcam_mcast_pul - tbl
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_tcam_mcast_pul(struct dsaf_device *dsaf_dev)
+{
+ u32 o_tbl_pul;
+
+ o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 1);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+}
+
+/**
+ * hns_dsaf_tbl_line_pul - tbl
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_line_pul(struct dsaf_device *dsaf_dev)
+{
+ u32 tbl_pul;
+
+ tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG);
+ dsaf_set_bit(tbl_pul, DSAF_TBL_PUL_LINE_VLD_S, 1);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, tbl_pul);
+ dsaf_set_bit(tbl_pul, DSAF_TBL_PUL_LINE_VLD_S, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, tbl_pul);
+}
+
+/**
+ * hns_dsaf_tbl_tcam_data_mcast_pul - tbl
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_tcam_data_mcast_pul(
+ struct dsaf_device *dsaf_dev)
+{
+ u32 o_tbl_pul;
+
+ o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 1);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 1);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 0);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+}
+
+/**
+ * hns_dsaf_tbl_tcam_data_ucast_pul - tbl
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_tcam_data_ucast_pul(
+ struct dsaf_device *dsaf_dev)
+{
+ u32 o_tbl_pul;
+
+ o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 1);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_UCAST_VLD_S, 1);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 0);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_UCAST_VLD_S, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+}
+
+void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en)
+{
+ dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_MIX_MODE_S, !!en);
+}
+
+/**
+ * hns_dsaf_tbl_stat_en - tbl
+ * @dsaf_id: dsa fabric id
+ * @ptbl_stat_en: addr
+ */
+static void hns_dsaf_tbl_stat_en(struct dsaf_device *dsaf_dev)
+{
+ u32 o_tbl_ctrl;
+
+ o_tbl_ctrl = dsaf_read_dev(dsaf_dev, DSAF_TBL_DFX_CTRL_0_REG);
+ dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_LINE_LKUP_NUM_EN_S, 1);
+ dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_UC_LKUP_NUM_EN_S, 1);
+ dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_MC_LKUP_NUM_EN_S, 1);
+ dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_BC_LKUP_NUM_EN_S, 1);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_DFX_CTRL_0_REG, o_tbl_ctrl);
+}
+
+/**
+ * hns_dsaf_rocee_bp_en - rocee back press enable
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_rocee_bp_en(struct dsaf_device *dsaf_dev)
+{
+ dsaf_set_dev_bit(dsaf_dev, DSAF_XGE_CTRL_SIG_CFG_0_REG,
+ DSAF_FC_XGE_TX_PAUSE_S, 1);
+}
+
+/* set msk for dsaf exception irq*/
+static void hns_dsaf_int_xge_msk_set(struct dsaf_device *dsaf_dev,
+ u32 chnn_num, u32 mask_set)
+{
+ dsaf_write_dev(dsaf_dev,
+ DSAF_XGE_INT_MSK_0_REG + 0x4 * chnn_num, mask_set);
+}
+
+static void hns_dsaf_int_ppe_msk_set(struct dsaf_device *dsaf_dev,
+ u32 chnn_num, u32 msk_set)
+{
+ dsaf_write_dev(dsaf_dev,
+ DSAF_PPE_INT_MSK_0_REG + 0x4 * chnn_num, msk_set);
+}
+
+static void hns_dsaf_int_rocee_msk_set(struct dsaf_device *dsaf_dev,
+ u32 chnn, u32 msk_set)
+{
+ dsaf_write_dev(dsaf_dev,
+ DSAF_ROCEE_INT_MSK_0_REG + 0x4 * chnn, msk_set);
+}
+
+static void
+hns_dsaf_int_tbl_msk_set(struct dsaf_device *dsaf_dev, u32 msk_set)
+{
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_INT_MSK_0_REG, msk_set);
+}
+
+/* clr dsaf exception irq*/
+static void hns_dsaf_int_xge_src_clr(struct dsaf_device *dsaf_dev,
+ u32 chnn_num, u32 int_src)
+{
+ dsaf_write_dev(dsaf_dev,
+ DSAF_XGE_INT_SRC_0_REG + 0x4 * chnn_num, int_src);
+}
+
+static void hns_dsaf_int_ppe_src_clr(struct dsaf_device *dsaf_dev,
+ u32 chnn, u32 int_src)
+{
+ dsaf_write_dev(dsaf_dev,
+ DSAF_PPE_INT_SRC_0_REG + 0x4 * chnn, int_src);
+}
+
+static void hns_dsaf_int_rocee_src_clr(struct dsaf_device *dsaf_dev,
+ u32 chnn, u32 int_src)
+{
+ dsaf_write_dev(dsaf_dev,
+ DSAF_ROCEE_INT_SRC_0_REG + 0x4 * chnn, int_src);
+}
+
+static void hns_dsaf_int_tbl_src_clr(struct dsaf_device *dsaf_dev,
+ u32 int_src)
+{
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_INT_SRC_0_REG, int_src);
+}
+
+/**
+ * hns_dsaf_single_line_tbl_cfg - INT
+ * @dsaf_id: dsa fabric id
+ * @address:
+ * @ptbl_line:
+ */
+static void hns_dsaf_single_line_tbl_cfg(
+ struct dsaf_device *dsaf_dev,
+ u32 address, struct dsaf_tbl_line_cfg *ptbl_line)
+{
+ /*Write Addr*/
+ hns_dsaf_tbl_line_addr_cfg(dsaf_dev, address);
+
+ /*Write Line*/
+ hns_dsaf_tbl_line_cfg(dsaf_dev, ptbl_line);
+
+ /*Write Plus*/
+ hns_dsaf_tbl_line_pul(dsaf_dev);
+}
+
+/**
+ * hns_dsaf_tcam_uc_cfg - INT
+ * @dsaf_id: dsa fabric id
+ * @address,
+ * @ptbl_tcam_data,
+ */
+static void hns_dsaf_tcam_uc_cfg(
+ struct dsaf_device *dsaf_dev, u32 address,
+ struct dsaf_tbl_tcam_data *ptbl_tcam_data,
+ struct dsaf_tbl_tcam_ucast_cfg *ptbl_tcam_ucast)
+{
+ /*Write Addr*/
+ hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+ /*Write Tcam Data*/
+ hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, ptbl_tcam_data);
+ /*Write Tcam Ucast*/
+ hns_dsaf_tbl_tcam_ucast_cfg(dsaf_dev, ptbl_tcam_ucast);
+ /*Write Plus*/
+ hns_dsaf_tbl_tcam_data_ucast_pul(dsaf_dev);
+}
+
+/**
+ * hns_dsaf_tcam_mc_cfg - INT
+ * @dsaf_id: dsa fabric id
+ * @address,
+ * @ptbl_tcam_data,
+ * @ptbl_tcam_mcast,
+ */
+static void hns_dsaf_tcam_mc_cfg(
+ struct dsaf_device *dsaf_dev, u32 address,
+ struct dsaf_tbl_tcam_data *ptbl_tcam_data,
+ struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast)
+{
+ /*Write Addr*/
+ hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+ /*Write Tcam Data*/
+ hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, ptbl_tcam_data);
+ /*Write Tcam Mcast*/
+ hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, ptbl_tcam_mcast);
+ /*Write Plus*/
+ hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev);
+}
+
+/**
+ * hns_dsaf_tcam_mc_invld - INT
+ * @dsaf_id: dsa fabric id
+ * @address
+ */
+static void hns_dsaf_tcam_mc_invld(struct dsaf_device *dsaf_dev, u32 address)
+{
+ /*Write Addr*/
+ hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+
+ /*write tcam mcast*/
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG, 0);
+
+ /*Write Plus*/
+ hns_dsaf_tbl_tcam_mcast_pul(dsaf_dev);
+}
+
+/**
+ * hns_dsaf_tcam_uc_get - INT
+ * @dsaf_id: dsa fabric id
+ * @address
+ * @ptbl_tcam_data
+ * @ptbl_tcam_ucast
+ */
+static void hns_dsaf_tcam_uc_get(
+ struct dsaf_device *dsaf_dev, u32 address,
+ struct dsaf_tbl_tcam_data *ptbl_tcam_data,
+ struct dsaf_tbl_tcam_ucast_cfg *ptbl_tcam_ucast)
+{
+ u32 tcam_read_data0;
+ u32 tcam_read_data4;
+
+ /*Write Addr*/
+ hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+
+ /*read tcam item puls*/
+ hns_dsaf_tbl_tcam_load_pul(dsaf_dev);
+
+ /*read tcam data*/
+ ptbl_tcam_data->tbl_tcam_data_high
+ = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
+ ptbl_tcam_data->tbl_tcam_data_low
+ = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
+
+ /*read tcam mcast*/
+ tcam_read_data0 = dsaf_read_dev(dsaf_dev,
+ DSAF_TBL_TCAM_RAM_RDATA0_0_REG);
+ tcam_read_data4 = dsaf_read_dev(dsaf_dev,
+ DSAF_TBL_TCAM_RAM_RDATA4_0_REG);
+
+ ptbl_tcam_ucast->tbl_ucast_item_vld
+ = dsaf_get_bit(tcam_read_data4,
+ DSAF_TBL_MCAST_CFG4_ITEM_VLD_S);
+ ptbl_tcam_ucast->tbl_ucast_old_en
+ = dsaf_get_bit(tcam_read_data4, DSAF_TBL_MCAST_CFG4_OLD_EN_S);
+ ptbl_tcam_ucast->tbl_ucast_mac_discard
+ = dsaf_get_bit(tcam_read_data0,
+ DSAF_TBL_UCAST_CFG1_MAC_DISCARD_S);
+ ptbl_tcam_ucast->tbl_ucast_out_port
+ = dsaf_get_field(tcam_read_data0,
+ DSAF_TBL_UCAST_CFG1_OUT_PORT_M,
+ DSAF_TBL_UCAST_CFG1_OUT_PORT_S);
+ ptbl_tcam_ucast->tbl_ucast_dvc
+ = dsaf_get_bit(tcam_read_data0, DSAF_TBL_UCAST_CFG1_DVC_S);
+}
+
+/**
+ * hns_dsaf_tcam_mc_get - INT
+ * @dsaf_id: dsa fabric id
+ * @address
+ * @ptbl_tcam_data
+ * @ptbl_tcam_ucast
+ */
+static void hns_dsaf_tcam_mc_get(
+ struct dsaf_device *dsaf_dev, u32 address,
+ struct dsaf_tbl_tcam_data *ptbl_tcam_data,
+ struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast)
+{
+ u32 data_tmp;
+
+ /*Write Addr*/
+ hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+
+ /*read tcam item puls*/
+ hns_dsaf_tbl_tcam_load_pul(dsaf_dev);
+
+ /*read tcam data*/
+ ptbl_tcam_data->tbl_tcam_data_high =
+ dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
+ ptbl_tcam_data->tbl_tcam_data_low =
+ dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
+
+ /*read tcam mcast*/
+ ptbl_tcam_mcast->tbl_mcast_port_msk[0] =
+ dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA0_0_REG);
+ ptbl_tcam_mcast->tbl_mcast_port_msk[1] =
+ dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA1_0_REG);
+ ptbl_tcam_mcast->tbl_mcast_port_msk[2] =
+ dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA2_0_REG);
+ ptbl_tcam_mcast->tbl_mcast_port_msk[3] =
+ dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA3_0_REG);
+
+ data_tmp = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA4_0_REG);
+ ptbl_tcam_mcast->tbl_mcast_item_vld =
+ dsaf_get_bit(data_tmp, DSAF_TBL_MCAST_CFG4_ITEM_VLD_S);
+ ptbl_tcam_mcast->tbl_mcast_old_en =
+ dsaf_get_bit(data_tmp, DSAF_TBL_MCAST_CFG4_OLD_EN_S);
+ ptbl_tcam_mcast->tbl_mcast_port_msk[4] =
+ dsaf_get_field(data_tmp, DSAF_TBL_MCAST_CFG4_VM128_112_M,
+ DSAF_TBL_MCAST_CFG4_VM128_112_S);
+}
+
+/**
+ * hns_dsaf_tbl_line_init - INT
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_line_init(struct dsaf_device *dsaf_dev)
+{
+ u32 i;
+ /* defaultly set all lineal mac table entry resulting discard */
+ struct dsaf_tbl_line_cfg tbl_line[] = {{1, 0, 0} };
+
+ for (i = 0; i < DSAF_LINE_SUM; i++)
+ hns_dsaf_single_line_tbl_cfg(dsaf_dev, i, tbl_line);
+}
+
+/**
+ * hns_dsaf_tbl_tcam_init - INT
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_tcam_init(struct dsaf_device *dsaf_dev)
+{
+ u32 i;
+ struct dsaf_tbl_tcam_data tcam_data[] = {{0, 0} };
+ struct dsaf_tbl_tcam_ucast_cfg tcam_ucast[] = {{0, 0, 0, 0, 0} };
+
+ /*tcam tbl*/
+ for (i = 0; i < DSAF_TCAM_SUM; i++)
+ hns_dsaf_tcam_uc_cfg(dsaf_dev, i, tcam_data, tcam_ucast);
+}
+
+/**
+ * hns_dsaf_pfc_en_cfg - dsaf pfc pause cfg
+ * @mac_cb: mac contrl block
+ */
+static void hns_dsaf_pfc_en_cfg(struct dsaf_device *dsaf_dev,
+ int mac_id, int en)
+{
+ if (!en)
+ dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, 0);
+ else
+ dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, 0xff);
+}
+
+/**
+ * hns_dsaf_tbl_tcam_init - INT
+ * @dsaf_id: dsa fabric id
+ * @dsaf_mode
+ */
+static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev)
+{
+ u32 i;
+ u32 o_dsaf_cfg;
+
+ o_dsaf_cfg = dsaf_read_dev(dsaf_dev, DSAF_CFG_0_REG);
+ dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_EN_S, dsaf_dev->dsaf_en);
+ dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_TC_MODE_S, dsaf_dev->dsaf_tc_mode);
+ dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_CRC_EN_S, 0);
+ dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_MIX_MODE_S, 0);
+ dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_LOCA_ADDR_EN_S, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_CFG_0_REG, o_dsaf_cfg);
+
+ hns_dsaf_reg_cnt_clr_ce(dsaf_dev, 1);
+ hns_dsaf_stp_port_type_cfg(dsaf_dev, DSAF_STP_PORT_TYPE_FORWARD);
+
+ /* set 22 queue per tx ppe engine, only used in switch mode */
+ hns_dsaf_ppe_qid_cfg(dsaf_dev, DSAF_DEFAUTL_QUEUE_NUM_PER_PPE);
+
+ /* set promisc def queue id */
+ hns_dsaf_mix_def_qid_cfg(dsaf_dev);
+
+ /* in non switch mode, set all port to access mode */
+ hns_dsaf_sw_port_type_cfg(dsaf_dev, DSAF_SW_PORT_TYPE_NON_VLAN);
+
+ /*set dsaf pfc to 0 for parseing rx pause*/
+ for (i = 0; i < DSAF_COMM_CHN; i++)
+ hns_dsaf_pfc_en_cfg(dsaf_dev, i, 0);
+
+ /*msk and clr exception irqs */
+ for (i = 0; i < DSAF_COMM_CHN; i++) {
+ hns_dsaf_int_xge_src_clr(dsaf_dev, i, 0xfffffffful);
+ hns_dsaf_int_ppe_src_clr(dsaf_dev, i, 0xfffffffful);
+ hns_dsaf_int_rocee_src_clr(dsaf_dev, i, 0xfffffffful);
+
+ hns_dsaf_int_xge_msk_set(dsaf_dev, i, 0xfffffffful);
+ hns_dsaf_int_ppe_msk_set(dsaf_dev, i, 0xfffffffful);
+ hns_dsaf_int_rocee_msk_set(dsaf_dev, i, 0xfffffffful);
+ }
+ hns_dsaf_int_tbl_src_clr(dsaf_dev, 0xfffffffful);
+ hns_dsaf_int_tbl_msk_set(dsaf_dev, 0xfffffffful);
+}
+
+/**
+ * hns_dsaf_inode_init - INT
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_inode_init(struct dsaf_device *dsaf_dev)
+{
+ u32 reg;
+ u32 tc_cfg;
+ u32 i;
+
+ if (dsaf_dev->dsaf_tc_mode == HRD_DSAF_4TC_MODE)
+ tc_cfg = HNS_DSAF_I4TC_CFG;
+ else
+ tc_cfg = HNS_DSAF_I8TC_CFG;
+
+ for (i = 0; i < DSAF_INODE_NUM; i++) {
+ reg = DSAF_INODE_IN_PORT_NUM_0_REG + 0x80 * i;
+ dsaf_set_dev_field(dsaf_dev, reg, DSAF_INODE_IN_PORT_NUM_M,
+ DSAF_INODE_IN_PORT_NUM_S, i % DSAF_XGE_NUM);
+
+ reg = DSAF_INODE_PRI_TC_CFG_0_REG + 0x80 * i;
+ dsaf_write_dev(dsaf_dev, reg, tc_cfg);
+ }
+}
+
+/**
+ * hns_dsaf_sbm_init - INT
+ * @dsaf_id: dsa fabric id
+ */
+static int hns_dsaf_sbm_init(struct dsaf_device *dsaf_dev)
+{
+ u32 flag;
+ u32 cnt = 0;
+ int ret;
+
+ hns_dsaf_sbm_bp_wl_cfg(dsaf_dev);
+
+ /* enable sbm chanel, disable sbm chanel shcut function*/
+ hns_dsaf_sbm_cfg(dsaf_dev);
+
+ /* enable sbm mib */
+ ret = hns_dsaf_sbm_cfg_mib_en(dsaf_dev);
+ if (ret) {
+ dev_err(dsaf_dev->dev,
+ "hns_dsaf_sbm_cfg_mib_en fail,%s, ret=%d\n",
+ dsaf_dev->ae_dev.name, ret);
+ return ret;
+ }
+
+ /* enable sbm initial link sram */
+ hns_dsaf_sbm_link_sram_init_en(dsaf_dev);
+
+ do {
+ usleep_range(200, 210);/*udelay(200);*/
+ flag = dsaf_read_dev(dsaf_dev, DSAF_SRAM_INIT_OVER_0_REG);
+ cnt++;
+ } while (flag != DSAF_SRAM_INIT_FINISH_FLAG && cnt < DSAF_CFG_READ_CNT);
+
+ if (flag != DSAF_SRAM_INIT_FINISH_FLAG) {
+ dev_err(dsaf_dev->dev,
+ "hns_dsaf_sbm_init fail %s, flag=%d, cnt=%d\n",
+ dsaf_dev->ae_dev.name, flag, cnt);
+ return -ENODEV;
+ }
+
+ hns_dsaf_rocee_bp_en(dsaf_dev);
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_tbl_init - INT
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_tbl_init(struct dsaf_device *dsaf_dev)
+{
+ hns_dsaf_tbl_stat_en(dsaf_dev);
+
+ hns_dsaf_tbl_tcam_init(dsaf_dev);
+ hns_dsaf_tbl_line_init(dsaf_dev);
+}
+
+/**
+ * hns_dsaf_voq_init - INT
+ * @dsaf_id: dsa fabric id
+ */
+static void hns_dsaf_voq_init(struct dsaf_device *dsaf_dev)
+{
+ hns_dsaf_voq_bp_all_thrd_cfg(dsaf_dev);
+}
+
+/**
+ * hns_dsaf_init_hw - init dsa fabric hardware
+ * @dsaf_dev: dsa fabric device struct pointer
+ */
+static int hns_dsaf_init_hw(struct dsaf_device *dsaf_dev)
+{
+ int ret;
+
+ dev_dbg(dsaf_dev->dev,
+ "hns_dsaf_init_hw begin %s !\n", dsaf_dev->ae_dev.name);
+
+ hns_dsaf_rst(dsaf_dev, 0);
+ mdelay(10);
+ hns_dsaf_rst(dsaf_dev, 1);
+
+ hns_dsaf_comm_init(dsaf_dev);
+
+ /*init XBAR_INODE*/
+ hns_dsaf_inode_init(dsaf_dev);
+
+ /*init SBM*/
+ ret = hns_dsaf_sbm_init(dsaf_dev);
+ if (ret)
+ return ret;
+
+ /*init TBL*/
+ hns_dsaf_tbl_init(dsaf_dev);
+
+ /*init VOQ*/
+ hns_dsaf_voq_init(dsaf_dev);
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_remove_hw - uninit dsa fabric hardware
+ * @dsaf_dev: dsa fabric device struct pointer
+ */
+static void hns_dsaf_remove_hw(struct dsaf_device *dsaf_dev)
+{
+ /*reset*/
+ hns_dsaf_rst(dsaf_dev, 0);
+}
+
+/**
+ * hns_dsaf_init - init dsa fabric
+ * @dsaf_dev: dsa fabric device struct pointer
+ * retuen 0 - success , negative --fail
+ */
+static int hns_dsaf_init(struct dsaf_device *dsaf_dev)
+{
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ u32 i;
+ int ret;
+
+ ret = hns_dsaf_init_hw(dsaf_dev);
+ if (ret)
+ return ret;
+
+ /* malloc mem for tcam mac key(vlan+mac) */
+ priv->soft_mac_tbl = vzalloc(sizeof(*priv->soft_mac_tbl)
+ * DSAF_TCAM_SUM);
+ if (!priv->soft_mac_tbl) {
+ ret = -ENOMEM;
+ goto remove_hw;
+ }
+
+ /*all entry invall */
+ for (i = 0; i < DSAF_TCAM_SUM; i++)
+ (priv->soft_mac_tbl + i)->index = DSAF_INVALID_ENTRY_IDX;
+
+ return 0;
+
+remove_hw:
+ hns_dsaf_remove_hw(dsaf_dev);
+ return ret;
+}
+
+/**
+ * hns_dsaf_free - free dsa fabric
+ * @dsaf_dev: dsa fabric device struct pointer
+ */
+static void hns_dsaf_free(struct dsaf_device *dsaf_dev)
+{
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+
+ hns_dsaf_remove_hw(dsaf_dev);
+
+ /* free all mac mem */
+ vfree(priv->soft_mac_tbl);
+ priv->soft_mac_tbl = NULL;
+}
+
+/**
+ * hns_dsaf_find_soft_mac_entry - find dsa fabric soft entry
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_key: mac entry struct pointer
+ */
+static u16 hns_dsaf_find_soft_mac_entry(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_tbl_tcam_key *mac_key)
+{
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+ u32 i;
+
+ soft_mac_entry = priv->soft_mac_tbl;
+ for (i = 0; i < DSAF_TCAM_SUM; i++) {
+ /* invall tab entry */
+ if ((soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX) &&
+ (soft_mac_entry->tcam_key.high.val == mac_key->high.val) &&
+ (soft_mac_entry->tcam_key.low.val == mac_key->low.val))
+ /* return find result --soft index */
+ return soft_mac_entry->index;
+
+ soft_mac_entry++;
+ }
+ return DSAF_INVALID_ENTRY_IDX;
+}
+
+/**
+ * hns_dsaf_find_empty_mac_entry - search dsa fabric soft empty-entry
+ * @dsaf_dev: dsa fabric device struct pointer
+ */
+static u16 hns_dsaf_find_empty_mac_entry(struct dsaf_device *dsaf_dev)
+{
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+ u32 i;
+
+ soft_mac_entry = priv->soft_mac_tbl;
+ for (i = 0; i < DSAF_TCAM_SUM; i++) {
+ /* inv all entry */
+ if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX)
+ /* return find result --soft index */
+ return i;
+
+ soft_mac_entry++;
+ }
+ return DSAF_INVALID_ENTRY_IDX;
+}
+
+/**
+ * hns_dsaf_set_mac_key - set mac key
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_key: tcam key pointer
+ * @vlan_id: vlan id
+ * @in_port_num: input port num
+ * @addr: mac addr
+ */
+static void hns_dsaf_set_mac_key(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_tbl_tcam_key *mac_key, u16 vlan_id, u8 in_port_num,
+ u8 *addr)
+{
+ u8 port;
+
+ if (dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE)
+ /*DSAF mode : in port id fixed 0*/
+ port = 0;
+ else
+ /*non-dsaf mode*/
+ port = in_port_num;
+
+ mac_key->high.bits.mac_0 = addr[0];
+ mac_key->high.bits.mac_1 = addr[1];
+ mac_key->high.bits.mac_2 = addr[2];
+ mac_key->high.bits.mac_3 = addr[3];
+ mac_key->low.bits.mac_4 = addr[4];
+ mac_key->low.bits.mac_5 = addr[5];
+ mac_key->low.bits.vlan = vlan_id;
+ mac_key->low.bits.port = port;
+}
+
+/**
+ * hns_dsaf_set_mac_uc_entry - set mac uc-entry
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_entry: uc-mac entry
+ */
+int hns_dsaf_set_mac_uc_entry(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+ struct dsaf_tbl_tcam_ucast_cfg mac_data;
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+
+ /* mac addr check */
+ if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
+ MAC_IS_BROADCAST(mac_entry->addr) ||
+ MAC_IS_MULTICAST(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev,
+ "set_uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n",
+ dsaf_dev->ae_dev.name, mac_entry->addr[0],
+ mac_entry->addr[1], mac_entry->addr[2],
+ mac_entry->addr[3], mac_entry->addr[4],
+ mac_entry->addr[5]);
+ return -EINVAL;
+ }
+
+ /* config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id,
+ mac_entry->in_port_num, mac_entry->addr);
+
+ /* entry ie exist? */
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*if has not inv entry,find a empty entry */
+ entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /* has not empty,return error */
+ dev_err(dsaf_dev->dev,
+ "set_uc_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+ }
+
+ dev_dbg(dsaf_dev->dev,
+ "set_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ /* config hardware entry */
+ mac_data.tbl_ucast_item_vld = 1;
+ mac_data.tbl_ucast_mac_discard = 0;
+ mac_data.tbl_ucast_old_en = 0;
+ /* default config dvc to 0 */
+ mac_data.tbl_ucast_dvc = 0;
+ mac_data.tbl_ucast_out_port = mac_entry->port_num;
+ hns_dsaf_tcam_uc_cfg(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+
+ /* config software entry */
+ soft_mac_entry += entry_index;
+ soft_mac_entry->index = entry_index;
+ soft_mac_entry->tcam_key.high.val = mac_key.high.val;
+ soft_mac_entry->tcam_key.low.val = mac_key.low.val;
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_set_mac_mc_entry - set mac mc-entry
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_entry: mc-mac entry
+ */
+int hns_dsaf_set_mac_mc_entry(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_multi_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+ struct dsaf_tbl_tcam_mcast_cfg mac_data;
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+ struct dsaf_drv_tbl_tcam_key tmp_mac_key;
+
+ /* mac addr check */
+ if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev,
+ "set uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n",
+ dsaf_dev->ae_dev.name, mac_entry->addr[0],
+ mac_entry->addr[1], mac_entry->addr[2],
+ mac_entry->addr[3],
+ mac_entry->addr[4], mac_entry->addr[5]);
+ return -EINVAL;
+ }
+
+ /*config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key,
+ mac_entry->in_vlan_id,
+ mac_entry->in_port_num, mac_entry->addr);
+
+ /* entry ie exist? */
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*if hasnot, find enpty entry*/
+ entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*if hasnot empty, error*/
+ dev_err(dsaf_dev->dev,
+ "set_uc_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+
+ /* config hardware entry */
+ memset(mac_data.tbl_mcast_port_msk,
+ 0, sizeof(mac_data.tbl_mcast_port_msk));
+ } else {
+ /* config hardware entry */
+ hns_dsaf_tcam_mc_get(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data);
+ }
+ mac_data.tbl_mcast_old_en = 0;
+ mac_data.tbl_mcast_item_vld = 1;
+ dsaf_set_field(mac_data.tbl_mcast_port_msk[0],
+ 0x3F, 0, mac_entry->port_mask[0]);
+
+ dev_dbg(dsaf_dev->dev,
+ "set_uc_entry, %s key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ hns_dsaf_tcam_mc_cfg(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+
+ /* config software entry */
+ soft_mac_entry += entry_index;
+ soft_mac_entry->index = entry_index;
+ soft_mac_entry->tcam_key.high.val = mac_key.high.val;
+ soft_mac_entry->tcam_key.low.val = mac_key.low.val;
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_add_mac_mc_port - add mac mc-port
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_entry: mc-mac entry
+ */
+int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+ struct dsaf_tbl_tcam_mcast_cfg mac_data;
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+ struct dsaf_drv_tbl_tcam_key tmp_mac_key;
+ int mskid;
+
+ /*chechk mac addr */
+ if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev,
+ "set_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
+ mac_entry->addr[0], mac_entry->addr[1],
+ mac_entry->addr[2], mac_entry->addr[3],
+ mac_entry->addr[4], mac_entry->addr[5]);
+ return -EINVAL;
+ }
+
+ /*config key */
+ hns_dsaf_set_mac_key(
+ dsaf_dev, &mac_key, mac_entry->in_vlan_id,
+ mac_entry->in_port_num, mac_entry->addr);
+
+ memset(&mac_data, 0, sizeof(struct dsaf_tbl_tcam_mcast_cfg));
+
+ /*check exist? */
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*if hasnot , find a empty*/
+ entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*if hasnot empty, error*/
+ dev_err(dsaf_dev->dev,
+ "set_uc_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val);
+ return -EINVAL;
+ }
+ } else {
+ /*if exist, add in */
+ hns_dsaf_tcam_mc_get(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data);
+ }
+ /* config hardware entry */
+ if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) {
+ mskid = mac_entry->port_num;
+ } else if (mac_entry->port_num >= DSAF_BASE_INNER_PORT_NUM) {
+ mskid = mac_entry->port_num -
+ DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM;
+ } else {
+ dev_err(dsaf_dev->dev,
+ "%s,pnum(%d)error,key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name, mac_entry->port_num,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+ dsaf_set_bit(mac_data.tbl_mcast_port_msk[mskid / 32], mskid % 32, 1);
+ mac_data.tbl_mcast_old_en = 0;
+ mac_data.tbl_mcast_item_vld = 1;
+
+ dev_dbg(dsaf_dev->dev,
+ "set_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ hns_dsaf_tcam_mc_cfg(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+
+ /*config software entry */
+ soft_mac_entry += entry_index;
+ soft_mac_entry->index = entry_index;
+ soft_mac_entry->tcam_key.high.val = mac_key.high.val;
+ soft_mac_entry->tcam_key.low.val = mac_key.low.val;
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_del_mac_entry - del mac mc-port
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @vlan_id: vlian id
+ * @in_port_num: input port num
+ * @addr : mac addr
+ */
+int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id,
+ u8 in_port_num, u8 *addr)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+
+ /*check mac addr */
+ if (MAC_IS_ALL_ZEROS(addr) || MAC_IS_BROADCAST(addr)) {
+ dev_err(dsaf_dev->dev,
+ "del_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+ return -EINVAL;
+ }
+
+ /*config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, addr);
+
+ /*exist ?*/
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*not exist, error */
+ dev_err(dsaf_dev->dev,
+ "del_mac_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+ dev_dbg(dsaf_dev->dev,
+ "del_mac_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ /*do del opt*/
+ hns_dsaf_tcam_mc_invld(dsaf_dev, entry_index);
+
+ /*del soft emtry */
+ soft_mac_entry += entry_index;
+ soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_del_mac_mc_port - del mac mc- port
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_entry: mac entry
+ */
+int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+ struct dsaf_drv_priv *priv =
+ (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+ u16 vlan_id;
+ u8 in_port_num;
+ struct dsaf_tbl_tcam_mcast_cfg mac_data;
+ struct dsaf_drv_tbl_tcam_key tmp_mac_key;
+ int mskid;
+ const u8 empty_msk[sizeof(mac_data.tbl_mcast_port_msk)] = {0};
+
+ if (!(void *)mac_entry) {
+ dev_err(dsaf_dev->dev,
+ "hns_dsaf_del_mac_mc_port mac_entry is NULL\n");
+ return -EINVAL;
+ }
+
+ /*get key info*/
+ vlan_id = mac_entry->in_vlan_id;
+ in_port_num = mac_entry->in_port_num;
+
+ /*check mac addr */
+ if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev,
+ "del_port failed, addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
+ mac_entry->addr[0], mac_entry->addr[1],
+ mac_entry->addr[2], mac_entry->addr[3],
+ mac_entry->addr[4], mac_entry->addr[5]);
+ return -EINVAL;
+ }
+
+ /*config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num,
+ mac_entry->addr);
+
+ /*check is exist? */
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*find none */
+ dev_err(dsaf_dev->dev,
+ "find_soft_mac_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+
+ dev_dbg(dsaf_dev->dev,
+ "del_mac_mc_port, %s key(%#x:%#x) index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ /*read entry*/
+ hns_dsaf_tcam_mc_get(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data);
+
+ /*del the port*/
+ if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) {
+ mskid = mac_entry->port_num;
+ } else if (mac_entry->port_num >= DSAF_BASE_INNER_PORT_NUM) {
+ mskid = mac_entry->port_num -
+ DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM;
+ } else {
+ dev_err(dsaf_dev->dev,
+ "%s,pnum(%d)error,key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name, mac_entry->port_num,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+ dsaf_set_bit(mac_data.tbl_mcast_port_msk[mskid / 32], mskid % 32, 0);
+
+ /*check non port, do del entry */
+ if (!memcmp(mac_data.tbl_mcast_port_msk, empty_msk,
+ sizeof(mac_data.tbl_mcast_port_msk))) {
+ hns_dsaf_tcam_mc_invld(dsaf_dev, entry_index);
+
+ /* del soft entry */
+ soft_mac_entry += entry_index;
+ soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
+ } else { /* not zer, just del port, updata*/
+ hns_dsaf_tcam_mc_cfg(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+ }
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_get_mac_uc_entry - get mac uc entry
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_entry: mac entry
+ */
+int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+
+ struct dsaf_tbl_tcam_ucast_cfg mac_data;
+
+ /* check macaddr */
+ if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
+ MAC_IS_BROADCAST(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev,
+ "get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac_entry->addr[0], mac_entry->addr[1],
+ mac_entry->addr[2], mac_entry->addr[3],
+ mac_entry->addr[4], mac_entry->addr[5]);
+ return -EINVAL;
+ }
+
+ /*config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id,
+ mac_entry->in_port_num, mac_entry->addr);
+
+ /*check exist? */
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /*find none, error */
+ dev_err(dsaf_dev->dev,
+ "get_uc_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name,
+ mac_key.high.val, mac_key.low.val);
+ return -EINVAL;
+ }
+ dev_dbg(dsaf_dev->dev,
+ "get_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ /*read entry*/
+ hns_dsaf_tcam_uc_get(dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+ mac_entry->port_num = mac_data.tbl_ucast_out_port;
+
+ return 0;
+}
+
+/**
+ * hns_dsaf_get_mac_mc_entry - get mac mc entry
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @mac_entry: mac entry
+ */
+int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_multi_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+
+ struct dsaf_tbl_tcam_mcast_cfg mac_data;
+
+ /*check mac addr */
+ if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
+ MAC_IS_BROADCAST(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev,
+ "get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac_entry->addr[0], mac_entry->addr[1],
+ mac_entry->addr[2], mac_entry->addr[3],
+ mac_entry->addr[4], mac_entry->addr[5]);
+ return -EINVAL;
+ }
+
+ /*config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id,
+ mac_entry->in_port_num, mac_entry->addr);
+
+ /*check exist? */
+ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /* find none, error */
+ dev_err(dsaf_dev->dev,
+ "get_mac_uc_entry failed, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val);
+ return -EINVAL;
+ }
+ dev_dbg(dsaf_dev->dev,
+ "get_mac_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, mac_key.high.val,
+ mac_key.low.val, entry_index);
+
+ /*read entry */
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+
+ mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
+ return 0;
+}
+
+/**
+ * hns_dsaf_get_mac_entry_by_index - get mac entry by tab index
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @entry_index: tab entry index
+ * @mac_entry: mac entry
+ */
+int hns_dsaf_get_mac_entry_by_index(
+ struct dsaf_device *dsaf_dev,
+ u16 entry_index, struct dsaf_drv_mac_multi_dest_entry *mac_entry)
+{
+ struct dsaf_drv_tbl_tcam_key mac_key;
+
+ struct dsaf_tbl_tcam_mcast_cfg mac_data;
+ struct dsaf_tbl_tcam_ucast_cfg mac_uc_data;
+ char mac_addr[MAC_NUM_OCTETS_PER_ADDR] = {0};
+
+ if (entry_index >= DSAF_TCAM_SUM) {
+ /* find none, del error */
+ dev_err(dsaf_dev->dev, "get_uc_entry failed, %s\n",
+ dsaf_dev->ae_dev.name);
+ return -EINVAL;
+ }
+
+ /* mc entry, do read opt */
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+
+ mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
+
+ /***get mac addr*/
+ mac_addr[0] = mac_key.high.bits.mac_0;
+ mac_addr[1] = mac_key.high.bits.mac_1;
+ mac_addr[2] = mac_key.high.bits.mac_2;
+ mac_addr[3] = mac_key.high.bits.mac_3;
+ mac_addr[4] = mac_key.low.bits.mac_4;
+ mac_addr[5] = mac_key.low.bits.mac_5;
+ /**is mc or uc*/
+ if (MAC_IS_MULTICAST((u8 *)mac_addr) ||
+ MAC_IS_L3_MULTICAST((u8 *)mac_addr)) {
+ /**mc donot do*/
+ } else {
+ /*is not mc, just uc... */
+ hns_dsaf_tcam_uc_get(dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)&mac_key,
+ &mac_uc_data);
+ mac_entry->port_mask[0] = (1 << mac_uc_data.tbl_ucast_out_port);
+ }
+
+ return 0;
+}
+
+static struct dsaf_device *hns_dsaf_alloc_dev(struct device *dev,
+ size_t sizeof_priv)
+{
+ struct dsaf_device *dsaf_dev;
+
+ dsaf_dev = devm_kzalloc(dev,
+ sizeof(*dsaf_dev) + sizeof_priv, GFP_KERNEL);
+ if (unlikely(!dsaf_dev)) {
+ dsaf_dev = ERR_PTR(-ENOMEM);
+ } else {
+ dsaf_dev->dev = dev;
+ dev_set_drvdata(dev, dsaf_dev);
+ }
+
+ return dsaf_dev;
+}
+
+/**
+ * hns_dsaf_free_dev - free dev mem
+ * @dev: struct device pointer
+ */
+static void hns_dsaf_free_dev(struct dsaf_device *dsaf_dev)
+{
+ (void)dev_set_drvdata(dsaf_dev->dev, NULL);
+}
+
+/**
+ * dsaf_pfc_unit_cnt - set pfc unit count
+ * @dsaf_id: dsa fabric id
+ * @pport_rate: value array
+ * @pdsaf_pfc_unit_cnt: value array
+ */
+static void hns_dsaf_pfc_unit_cnt(struct dsaf_device *dsaf_dev, int mac_id,
+ enum dsaf_port_rate_mode rate)
+{
+ u32 unit_cnt;
+
+ switch (rate) {
+ case DSAF_PORT_RATE_10000:
+ unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_XGE;
+ break;
+ case DSAF_PORT_RATE_1000:
+ unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_GE_1000;
+ break;
+ case DSAF_PORT_RATE_2500:
+ unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_GE_1000;
+ break;
+ default:
+ unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_XGE;
+ }
+
+ dsaf_set_dev_field(dsaf_dev,
+ (DSAF_PFC_UNIT_CNT_0_REG + 0x4 * (u64)mac_id),
+ DSAF_PFC_UNINT_CNT_M, DSAF_PFC_UNINT_CNT_S,
+ unit_cnt);
+}
+
+/**
+ * dsaf_port_work_rate_cfg - fifo
+ * @dsaf_id: dsa fabric id
+ * @xge_ge_work_mode
+ */
+void hns_dsaf_port_work_rate_cfg(struct dsaf_device *dsaf_dev, int mac_id,
+ enum dsaf_port_rate_mode rate_mode)
+{
+ u32 port_work_mode;
+
+ port_work_mode = dsaf_read_dev(
+ dsaf_dev, DSAF_XGE_GE_WORK_MODE_0_REG + 0x4 * (u64)mac_id);
+
+ if (rate_mode == DSAF_PORT_RATE_10000)
+ dsaf_set_bit(port_work_mode, DSAF_XGE_GE_WORK_MODE_S, 1);
+ else
+ dsaf_set_bit(port_work_mode, DSAF_XGE_GE_WORK_MODE_S, 0);
+
+ dsaf_write_dev(dsaf_dev,
+ DSAF_XGE_GE_WORK_MODE_0_REG + 0x4 * (u64)mac_id,
+ port_work_mode);
+
+ hns_dsaf_pfc_unit_cnt(dsaf_dev, mac_id, rate_mode);
+}
+
+/**
+ * hns_dsaf_fix_mac_mode - dsaf modify mac mode
+ * @mac_cb: mac contrl block
+ */
+void hns_dsaf_fix_mac_mode(struct hns_mac_cb *mac_cb)
+{
+ enum dsaf_port_rate_mode mode;
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ int mac_id = mac_cb->mac_id;
+
+ if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+ return;
+ if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII)
+ mode = DSAF_PORT_RATE_10000;
+ else
+ mode = DSAF_PORT_RATE_1000;
+
+ hns_dsaf_port_work_rate_cfg(dsaf_dev, mac_id, mode);
+}
+
+void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num)
+{
+ struct dsaf_hw_stats *hw_stats
+ = &dsaf_dev->hw_stats[node_num];
+
+ hw_stats->pad_drop += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_PAD_DISCARD_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->man_pkts += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_FINAL_IN_MAN_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->rx_pkts += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_FINAL_IN_PKT_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->rx_pkt_id += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_SBM_PID_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->rx_pause_frame += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->release_buf_num += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_SBM_RELS_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->sbm_drop += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_SBM_DROP_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->crc_false += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_CRC_FALSE_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->bp_drop += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_BP_DISCARD_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->rslt_drop += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_RSLT_DISCARD_NUM_0_REG + 0x80 * (u64)node_num);
+ hw_stats->local_addr_false += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG + 0x80 * (u64)node_num);
+
+ hw_stats->vlan_drop += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + 0x80 * (u64)node_num);
+ hw_stats->stp_drop += dsaf_read_dev(dsaf_dev,
+ DSAF_INODE_IN_DATA_STP_DISC_0_REG + 0x80 * (u64)node_num);
+
+ hw_stats->tx_pkts += dsaf_read_dev(dsaf_dev,
+ DSAF_XOD_RCVPKT_CNT_0_REG + 0x90 * (u64)node_num);
+}
+
+/**
+ *hns_dsaf_get_regs - dump dsaf regs
+ *@dsaf_dev: dsaf device
+ *@data:data for value of regs
+ */
+void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data)
+{
+ u32 i = 0;
+ u32 j;
+ u32 *p = data;
+
+ /* dsaf common registers */
+ p[0] = dsaf_read_dev(ddev, DSAF_SRAM_INIT_OVER_0_REG);
+ p[1] = dsaf_read_dev(ddev, DSAF_CFG_0_REG);
+ p[2] = dsaf_read_dev(ddev, DSAF_ECC_ERR_INVERT_0_REG);
+ p[3] = dsaf_read_dev(ddev, DSAF_ABNORMAL_TIMEOUT_0_REG);
+ p[4] = dsaf_read_dev(ddev, DSAF_FSM_TIMEOUT_0_REG);
+ p[5] = dsaf_read_dev(ddev, DSAF_DSA_REG_CNT_CLR_CE_REG);
+ p[6] = dsaf_read_dev(ddev, DSAF_DSA_SBM_INF_FIFO_THRD_REG);
+ p[7] = dsaf_read_dev(ddev, DSAF_DSA_SRAM_1BIT_ECC_SEL_REG);
+ p[8] = dsaf_read_dev(ddev, DSAF_DSA_SRAM_1BIT_ECC_CNT_REG);
+
+ p[9] = dsaf_read_dev(ddev, DSAF_PFC_EN_0_REG + port * 4);
+ p[10] = dsaf_read_dev(ddev, DSAF_PFC_UNIT_CNT_0_REG + port * 4);
+ p[11] = dsaf_read_dev(ddev, DSAF_XGE_INT_MSK_0_REG + port * 4);
+ p[12] = dsaf_read_dev(ddev, DSAF_XGE_INT_SRC_0_REG + port * 4);
+ p[13] = dsaf_read_dev(ddev, DSAF_XGE_INT_STS_0_REG + port * 4);
+ p[14] = dsaf_read_dev(ddev, DSAF_XGE_INT_MSK_0_REG + port * 4);
+ p[15] = dsaf_read_dev(ddev, DSAF_PPE_INT_MSK_0_REG + port * 4);
+ p[16] = dsaf_read_dev(ddev, DSAF_ROCEE_INT_MSK_0_REG + port * 4);
+ p[17] = dsaf_read_dev(ddev, DSAF_XGE_INT_SRC_0_REG + port * 4);
+ p[18] = dsaf_read_dev(ddev, DSAF_PPE_INT_SRC_0_REG + port * 4);
+ p[19] = dsaf_read_dev(ddev, DSAF_ROCEE_INT_SRC_0_REG + port * 4);
+ p[20] = dsaf_read_dev(ddev, DSAF_XGE_INT_STS_0_REG + port * 4);
+ p[21] = dsaf_read_dev(ddev, DSAF_PPE_INT_STS_0_REG + port * 4);
+ p[22] = dsaf_read_dev(ddev, DSAF_ROCEE_INT_STS_0_REG + port * 4);
+ p[23] = dsaf_read_dev(ddev, DSAF_PPE_QID_CFG_0_REG + port * 4);
+
+ for (i = 0; i < DSAF_SW_PORT_NUM; i++)
+ p[24 + i] = dsaf_read_dev(ddev,
+ DSAF_SW_PORT_TYPE_0_REG + i * 4);
+
+ p[32] = dsaf_read_dev(ddev, DSAF_MIX_DEF_QID_0_REG + port * 4);
+
+ for (i = 0; i < DSAF_SW_PORT_NUM; i++)
+ p[33 + i] = dsaf_read_dev(ddev,
+ DSAF_PORT_DEF_VLAN_0_REG + i * 4);
+
+ for (i = 0; i < DSAF_TOTAL_QUEUE_NUM; i++)
+ p[41 + i] = dsaf_read_dev(ddev,
+ DSAF_VM_DEF_VLAN_0_REG + i * 4);
+
+ /* dsaf inode registers */
+ p[170] = dsaf_read_dev(ddev, DSAF_INODE_CUT_THROUGH_CFG_0_REG);
+
+ p[171] = dsaf_read_dev(ddev,
+ DSAF_INODE_ECC_ERR_ADDR_0_REG + port * 0x80);
+
+ for (i = 0; i < DSAF_INODE_NUM / DSAF_COMM_CHN; i++) {
+ j = i * DSAF_COMM_CHN + port;
+ p[172 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_IN_PORT_NUM_0_REG + j * 0x80);
+ p[175 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_PRI_TC_CFG_0_REG + j * 0x80);
+ p[178 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_BP_STATUS_0_REG + j * 0x80);
+ p[181 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_PAD_DISCARD_NUM_0_REG + j * 0x80);
+ p[184 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_FINAL_IN_MAN_NUM_0_REG + j * 0x80);
+ p[187 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_FINAL_IN_PKT_NUM_0_REG + j * 0x80);
+ p[190 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_SBM_PID_NUM_0_REG + j * 0x80);
+ p[193 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG + j * 0x80);
+ p[196 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_SBM_RELS_NUM_0_REG + j * 0x80);
+ p[199 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_SBM_DROP_NUM_0_REG + j * 0x80);
+ p[202 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_CRC_FALSE_NUM_0_REG + j * 0x80);
+ p[205 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_BP_DISCARD_NUM_0_REG + j * 0x80);
+ p[208 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_RSLT_DISCARD_NUM_0_REG + j * 0x80);
+ p[211 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG + j * 0x80);
+ p[214 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_VOQ_OVER_NUM_0_REG + j * 0x80);
+ p[217 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_BD_SAVE_STATUS_0_REG + j * 4);
+ p[220 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_BD_ORDER_STATUS_0_REG + j * 4);
+ p[223 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + j * 4);
+ p[224 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_IN_DATA_STP_DISC_0_REG + j * 4);
+ }
+
+ p[227] = dsaf_read_dev(ddev, DSAF_INODE_GE_FC_EN_0_REG + port * 4);
+
+ for (i = 0; i < DSAF_INODE_NUM / DSAF_COMM_CHN; i++) {
+ j = i * DSAF_COMM_CHN + port;
+ p[228 + i] = dsaf_read_dev(ddev,
+ DSAF_INODE_VC0_IN_PKT_NUM_0_REG + j * 4);
+ }
+
+ p[231] = dsaf_read_dev(ddev,
+ DSAF_INODE_VC1_IN_PKT_NUM_0_REG + port * 4);
+
+ /* dsaf inode registers */
+ for (i = 0; i < DSAF_SBM_NUM / DSAF_COMM_CHN; i++) {
+ j = i * DSAF_COMM_CHN + port;
+ p[232 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_CFG_REG_0_REG + j * 0x80);
+ p[235 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CFG_0_XGE_REG_0_REG + j * 0x80);
+ p[238 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CFG_1_REG_0_REG + j * 0x80);
+ p[241 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CFG_2_XGE_REG_0_REG + j * 0x80);
+ p[244 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_FREE_CNT_0_0_REG + j * 0x80);
+ p[245 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_FREE_CNT_1_0_REG + j * 0x80);
+ p[248 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CNT_0_0_REG + j * 0x80);
+ p[251 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CNT_1_0_REG + j * 0x80);
+ p[254 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CNT_2_0_REG + j * 0x80);
+ p[257 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CNT_3_0_REG + j * 0x80);
+ p[260 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_INER_ST_0_REG + j * 0x80);
+ p[263 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_MIB_REQ_FAILED_TC_0_REG + j * 0x80);
+ p[266 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_CNT_0_REG + j * 0x80);
+ p[269 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_DROP_CNT_0_REG + j * 0x80);
+ p[272 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_INF_OUTPORT_CNT_0_REG + j * 0x80);
+ p[275 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC0_CNT_0_REG + j * 0x80);
+ p[278 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC1_CNT_0_REG + j * 0x80);
+ p[281 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC2_CNT_0_REG + j * 0x80);
+ p[284 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC3_CNT_0_REG + j * 0x80);
+ p[287 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC4_CNT_0_REG + j * 0x80);
+ p[290 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC5_CNT_0_REG + j * 0x80);
+ p[293 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC6_CNT_0_REG + j * 0x80);
+ p[296 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_INPORT_TC7_CNT_0_REG + j * 0x80);
+ p[299 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_REQ_CNT_0_REG + j * 0x80);
+ p[302 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_LNK_RELS_CNT_0_REG + j * 0x80);
+ p[305 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CFG_3_REG_0_REG + j * 0x80);
+ p[308 + i] = dsaf_read_dev(ddev,
+ DSAF_SBM_BP_CFG_4_REG_0_REG + j * 0x80);
+ }
+
+ /* dsaf onode registers */
+ for (i = 0; i < DSAF_XOD_NUM; i++) {
+ p[311 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + j * 0x90);
+ p[319 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + j * 0x90);
+ p[327 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + j * 0x90);
+ p[335 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + j * 0x90);
+ p[343 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + j * 0x90);
+ p[351 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_ETS_TOKEN_CFG_0_REG + j * 0x90);
+ }
+
+ p[359] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_0_0_REG + port * 0x90);
+ p[360] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_1_0_REG + port * 0x90);
+ p[361] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_2_0_REG + port * 0x90);
+
+ for (i = 0; i < DSAF_XOD_BIG_NUM / DSAF_COMM_CHN; i++) {
+ j = i * DSAF_COMM_CHN + port;
+ p[362 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_GNT_L_0_REG + j * 0x90);
+ p[365 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_GNT_H_0_REG + j * 0x90);
+ p[368 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_CONNECT_STATE_0_REG + j * 0x90);
+ p[371 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVPKT_CNT_0_REG + j * 0x90);
+ p[374 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVTC0_CNT_0_REG + j * 0x90);
+ p[377 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVTC1_CNT_0_REG + j * 0x90);
+ p[380 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVTC2_CNT_0_REG + j * 0x90);
+ p[383 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVTC3_CNT_0_REG + j * 0x90);
+ p[386 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVVC0_CNT_0_REG + j * 0x90);
+ p[389 + i] = dsaf_read_dev(ddev,
+ DSAF_XOD_RCVVC1_CNT_0_REG + j * 0x90);
+ }
+
+ p[392] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN0_CNT_0_REG + port * 0x90);
+ p[393] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN1_CNT_0_REG + port * 0x90);
+ p[394] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN2_CNT_0_REG + port * 0x90);
+ p[395] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN3_CNT_0_REG + port * 0x90);
+ p[396] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN4_CNT_0_REG + port * 0x90);
+ p[397] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN5_CNT_0_REG + port * 0x90);
+ p[398] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN6_CNT_0_REG + port * 0x90);
+ p[399] = dsaf_read_dev(ddev,
+ DSAF_XOD_XGE_RCVIN7_CNT_0_REG + port * 0x90);
+ p[400] = dsaf_read_dev(ddev,
+ DSAF_XOD_PPE_RCVIN0_CNT_0_REG + port * 0x90);
+ p[401] = dsaf_read_dev(ddev,
+ DSAF_XOD_PPE_RCVIN1_CNT_0_REG + port * 0x90);
+ p[402] = dsaf_read_dev(ddev,
+ DSAF_XOD_ROCEE_RCVIN0_CNT_0_REG + port * 0x90);
+ p[403] = dsaf_read_dev(ddev,
+ DSAF_XOD_ROCEE_RCVIN1_CNT_0_REG + port * 0x90);
+ p[404] = dsaf_read_dev(ddev,
+ DSAF_XOD_FIFO_STATUS_0_REG + port * 0x90);
+
+ /* dsaf voq registers */
+ for (i = 0; i < DSAF_VOQ_NUM / DSAF_COMM_CHN; i++) {
+ j = (i * DSAF_COMM_CHN + port) * 0x90;
+ p[405 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_ECC_INVERT_EN_0_REG + j);
+ p[408 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_SRAM_PKT_NUM_0_REG + j);
+ p[411 + i] = dsaf_read_dev(ddev, DSAF_VOQ_IN_PKT_NUM_0_REG + j);
+ p[414 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_OUT_PKT_NUM_0_REG + j);
+ p[417 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_ECC_ERR_ADDR_0_REG + j);
+ p[420 + i] = dsaf_read_dev(ddev, DSAF_VOQ_BP_STATUS_0_REG + j);
+ p[423 + i] = dsaf_read_dev(ddev, DSAF_VOQ_SPUP_IDLE_0_REG + j);
+ p[426 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_XGE_XOD_REQ_0_0_REG + j);
+ p[429 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_XGE_XOD_REQ_1_0_REG + j);
+ p[432 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_PPE_XOD_REQ_0_REG + j);
+ p[435 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_ROCEE_XOD_REQ_0_REG + j);
+ p[438 + i] = dsaf_read_dev(ddev,
+ DSAF_VOQ_BP_ALL_THRD_0_REG + j);
+ }
+
+ /* dsaf tbl registers */
+ p[441] = dsaf_read_dev(ddev, DSAF_TBL_CTRL_0_REG);
+ p[442] = dsaf_read_dev(ddev, DSAF_TBL_INT_MSK_0_REG);
+ p[443] = dsaf_read_dev(ddev, DSAF_TBL_INT_SRC_0_REG);
+ p[444] = dsaf_read_dev(ddev, DSAF_TBL_INT_STS_0_REG);
+ p[445] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_ADDR_0_REG);
+ p[446] = dsaf_read_dev(ddev, DSAF_TBL_LINE_ADDR_0_REG);
+ p[447] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_HIGH_0_REG);
+ p[448] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_LOW_0_REG);
+ p[449] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG);
+ p[450] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG);
+ p[451] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG);
+ p[452] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG);
+ p[453] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG);
+ p[454] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_UCAST_CFG_0_REG);
+ p[455] = dsaf_read_dev(ddev, DSAF_TBL_LIN_CFG_0_REG);
+ p[456] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
+ p[457] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
+ p[458] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA4_0_REG);
+ p[459] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA3_0_REG);
+ p[460] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA2_0_REG);
+ p[461] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA1_0_REG);
+ p[462] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA0_0_REG);
+ p[463] = dsaf_read_dev(ddev, DSAF_TBL_LIN_RDATA_0_REG);
+
+ for (i = 0; i < DSAF_SW_PORT_NUM; i++) {
+ j = i * 0x8;
+ p[464 + 2 * i] = dsaf_read_dev(ddev,
+ DSAF_TBL_DA0_MIS_INFO1_0_REG + j);
+ p[465 + 2 * i] = dsaf_read_dev(ddev,
+ DSAF_TBL_DA0_MIS_INFO0_0_REG + j);
+ }
+
+ p[480] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO2_0_REG);
+ p[481] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO1_0_REG);
+ p[482] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO0_0_REG);
+ p[483] = dsaf_read_dev(ddev, DSAF_TBL_PUL_0_REG);
+ p[484] = dsaf_read_dev(ddev, DSAF_TBL_OLD_RSLT_0_REG);
+ p[485] = dsaf_read_dev(ddev, DSAF_TBL_OLD_SCAN_VAL_0_REG);
+ p[486] = dsaf_read_dev(ddev, DSAF_TBL_DFX_CTRL_0_REG);
+ p[487] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_0_REG);
+ p[488] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_2_0_REG);
+ p[489] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_I_0_REG);
+ p[490] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_O_0_REG);
+ p[491] = dsaf_read_dev(ddev, DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG);
+
+ /* dsaf other registers */
+ p[492] = dsaf_read_dev(ddev, DSAF_INODE_FIFO_WL_0_REG + port * 0x4);
+ p[493] = dsaf_read_dev(ddev, DSAF_ONODE_FIFO_WL_0_REG + port * 0x4);
+ p[494] = dsaf_read_dev(ddev, DSAF_XGE_GE_WORK_MODE_0_REG + port * 0x4);
+ p[495] = dsaf_read_dev(ddev,
+ DSAF_XGE_APP_RX_LINK_UP_0_REG + port * 0x4);
+ p[496] = dsaf_read_dev(ddev, DSAF_NETPORT_CTRL_SIG_0_REG + port * 0x4);
+ p[497] = dsaf_read_dev(ddev, DSAF_XGE_CTRL_SIG_CFG_0_REG + port * 0x4);
+
+ /* mark end of dsaf regs */
+ for (i = 498; i < 504; i++)
+ p[i] = 0xdddddddd;
+}
+
+static char *hns_dsaf_get_node_stats_strings(char *data, int node)
+{
+ char *buff = data;
+
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_pad_drop_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_manage_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pkt_id", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pause_frame", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_release_buf_num", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_sbm_drop_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_crc_false_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_bp_drop_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_lookup_rslt_drop_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_local_rslt_fail_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_vlan_drop_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "innod%d_stp_drop_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "onnod%d_tx_pkts", node);
+ buff = buff + ETH_GSTRING_LEN;
+
+ return buff;
+}
+
+static u64 *hns_dsaf_get_node_stats(struct dsaf_device *ddev, u64 *data,
+ int node_num)
+{
+ u64 *p = data;
+ struct dsaf_hw_stats *hw_stats = &ddev->hw_stats[node_num];
+
+ p[0] = hw_stats->pad_drop;
+ p[1] = hw_stats->man_pkts;
+ p[2] = hw_stats->rx_pkts;
+ p[3] = hw_stats->rx_pkt_id;
+ p[4] = hw_stats->rx_pause_frame;
+ p[5] = hw_stats->release_buf_num;
+ p[6] = hw_stats->sbm_drop;
+ p[7] = hw_stats->crc_false;
+ p[8] = hw_stats->bp_drop;
+ p[9] = hw_stats->rslt_drop;
+ p[10] = hw_stats->local_addr_false;
+ p[11] = hw_stats->vlan_drop;
+ p[12] = hw_stats->stp_drop;
+ p[13] = hw_stats->tx_pkts;
+
+ return &p[14];
+}
+
+/**
+ *hns_dsaf_get_stats - get dsaf statistic
+ *@ddev: dsaf device
+ *@data:statistic value
+ *@port: port num
+ */
+void hns_dsaf_get_stats(struct dsaf_device *ddev, u64 *data, int port)
+{
+ u64 *p = data;
+ int node_num = port;
+
+ /* for ge/xge node info */
+ p = hns_dsaf_get_node_stats(ddev, p, node_num);
+
+ /* for ppe node info */
+ node_num = port + DSAF_PPE_INODE_BASE;
+ (void)hns_dsaf_get_node_stats(ddev, p, node_num);
+}
+
+/**
+ *hns_dsaf_get_sset_count - get dsaf string set count
+ *@stringset: type of values in data
+ *return dsaf string name count
+ */
+int hns_dsaf_get_sset_count(int stringset)
+{
+ if (stringset == ETH_SS_STATS)
+ return DSAF_STATIC_NUM;
+
+ return 0;
+}
+
+/**
+ *hns_dsaf_get_strings - get dsaf string set
+ *@stringset:srting set index
+ *@data:strings name value
+ *@port:port index
+ */
+void hns_dsaf_get_strings(int stringset, u8 *data, int port)
+{
+ char *buff = (char *)data;
+ int node = port;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ /* for ge/xge node info */
+ buff = hns_dsaf_get_node_stats_strings(buff, node);
+
+ /* for ppe node info */
+ node = port + DSAF_PPE_INODE_BASE;
+ (void)hns_dsaf_get_node_stats_strings(buff, node);
+}
+
+/**
+ *hns_dsaf_get_sset_count - get dsaf regs count
+ *return dsaf regs count
+ */
+int hns_dsaf_get_regs_count(void)
+{
+ return DSAF_DUMP_REGS_NUM;
+}
+
+/**
+ * dsaf_probe - probo dsaf dev
+ * @pdev: dasf platform device
+ * retuen 0 - success , negative --fail
+ */
+static int hns_dsaf_probe(struct platform_device *pdev)
+{
+ struct dsaf_device *dsaf_dev;
+ int ret;
+
+ dsaf_dev = hns_dsaf_alloc_dev(&pdev->dev, sizeof(struct dsaf_drv_priv));
+ if (IS_ERR(dsaf_dev)) {
+ ret = PTR_ERR(dsaf_dev);
+ dev_err(&pdev->dev,
+ "dsaf_probe dsaf_alloc_dev failed, ret = %#x!\n", ret);
+ return ret;
+ }
+
+ ret = hns_dsaf_get_cfg(dsaf_dev);
+ if (ret)
+ goto free_dev;
+
+ ret = hns_dsaf_init(dsaf_dev);
+ if (ret)
+ goto free_cfg;
+
+ ret = hns_mac_init(dsaf_dev);
+ if (ret)
+ goto uninit_dsaf;
+
+ ret = hns_ppe_init(dsaf_dev);
+ if (ret)
+ goto uninit_mac;
+
+ ret = hns_dsaf_ae_init(dsaf_dev);
+ if (ret)
+ goto uninit_ppe;
+
+ return 0;
+
+uninit_ppe:
+ hns_ppe_uninit(dsaf_dev);
+
+uninit_mac:
+ hns_mac_uninit(dsaf_dev);
+
+uninit_dsaf:
+ hns_dsaf_free(dsaf_dev);
+
+free_cfg:
+ hns_dsaf_free_cfg(dsaf_dev);
+
+free_dev:
+ hns_dsaf_free_dev(dsaf_dev);
+
+ return ret;
+}
+
+/**
+ * dsaf_remove - remove dsaf dev
+ * @pdev: dasf platform device
+ */
+static int hns_dsaf_remove(struct platform_device *pdev)
+{
+ struct dsaf_device *dsaf_dev = dev_get_drvdata(&pdev->dev);
+
+ hns_dsaf_ae_uninit(dsaf_dev);
+
+ hns_ppe_uninit(dsaf_dev);
+
+ hns_mac_uninit(dsaf_dev);
+
+ hns_dsaf_free(dsaf_dev);
+
+ hns_dsaf_free_cfg(dsaf_dev);
+
+ hns_dsaf_free_dev(dsaf_dev);
+
+ return 0;
+}
+
+static const struct of_device_id g_dsaf_match[] = {
+ {.compatible = "hisilicon,hns-dsaf-v1"},
+ {.compatible = "hisilicon,hns-dsaf-v2"},
+ {}
+};
+
+static struct platform_driver g_dsaf_driver = {
+ .probe = hns_dsaf_probe,
+ .remove = hns_dsaf_remove,
+ .driver = {
+ .name = DSAF_DRV_NAME,
+ .of_match_table = g_dsaf_match,
+ },
+};
+
+module_platform_driver(g_dsaf_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
+MODULE_DESCRIPTION("HNS DSAF driver");
+MODULE_VERSION(DSAF_MOD_VERSION);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
new file mode 100644
index 000000000000..b2b93484995c
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef __HNS_DSAF_MAIN_H
+#define __HNS_DSAF_MAIN_H
+#include "hnae.h"
+
+#include "hns_dsaf_reg.h"
+#include "hns_dsaf_mac.h"
+
+struct hns_mac_cb;
+
+#define DSAF_DRV_NAME "hns_dsaf"
+#define DSAF_MOD_VERSION "v1.0"
+
+#define ENABLE (0x1)
+#define DISABLE (0x0)
+
+#define HNS_DSAF_DEBUG_NW_REG_OFFSET (0x100000)
+
+#define DSAF_BASE_INNER_PORT_NUM (127) /* mac tbl qid*/
+
+#define DSAF_MAX_CHIP_NUM (2) /*max 2 chips */
+
+#define DSAF_DEFAUTL_QUEUE_NUM_PER_PPE (22)
+
+#define HNS_DSAF_MAX_DESC_CNT (1024)
+#define HNS_DSAF_MIN_DESC_CNT (16)
+
+#define DSAF_INVALID_ENTRY_IDX (0xffff)
+
+#define DSAF_CFG_READ_CNT (30)
+#define DSAF_SRAM_INIT_FINISH_FLAG (0xff)
+
+#define MAC_NUM_OCTETS_PER_ADDR 6
+
+#define DSAF_DUMP_REGS_NUM 504
+#define DSAF_STATIC_NUM 28
+
+#define DSAF_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset))))
+
+enum hal_dsaf_mode {
+ HRD_DSAF_NO_DSAF_MODE = 0x0,
+ HRD_DSAF_MODE = 0x1,
+};
+
+enum hal_dsaf_tc_mode {
+ HRD_DSAF_4TC_MODE = 0X0,
+ HRD_DSAF_8TC_MODE = 0X1,
+};
+
+struct dsaf_vm_def_vlan {
+ u32 vm_def_vlan_id;
+ u32 vm_def_vlan_cfi;
+ u32 vm_def_vlan_pri;
+};
+
+struct dsaf_tbl_tcam_data {
+ u32 tbl_tcam_data_high;
+ u32 tbl_tcam_data_low;
+};
+
+#define DSAF_PORT_MSK_NUM \
+ ((DSAF_TOTAL_QUEUE_NUM + DSAF_SERVICE_NW_NUM - 1) / 32 + 1)
+struct dsaf_tbl_tcam_mcast_cfg {
+ u8 tbl_mcast_old_en;
+ u8 tbl_mcast_item_vld;
+ u32 tbl_mcast_port_msk[DSAF_PORT_MSK_NUM];
+};
+
+struct dsaf_tbl_tcam_ucast_cfg {
+ u32 tbl_ucast_old_en;
+ u32 tbl_ucast_item_vld;
+ u32 tbl_ucast_mac_discard;
+ u32 tbl_ucast_dvc;
+ u32 tbl_ucast_out_port;
+};
+
+struct dsaf_tbl_line_cfg {
+ u32 tbl_line_mac_discard;
+ u32 tbl_line_dvc;
+ u32 tbl_line_out_port;
+};
+
+enum dsaf_port_rate_mode {
+ DSAF_PORT_RATE_1000 = 0,
+ DSAF_PORT_RATE_2500,
+ DSAF_PORT_RATE_10000
+};
+
+enum dsaf_stp_port_type {
+ DSAF_STP_PORT_TYPE_DISCARD = 0,
+ DSAF_STP_PORT_TYPE_BLOCK = 1,
+ DSAF_STP_PORT_TYPE_LISTEN = 2,
+ DSAF_STP_PORT_TYPE_LEARN = 3,
+ DSAF_STP_PORT_TYPE_FORWARD = 4
+};
+
+enum dsaf_sw_port_type {
+ DSAF_SW_PORT_TYPE_NON_VLAN = 0,
+ DSAF_SW_PORT_TYPE_ACCESS = 1,
+ DSAF_SW_PORT_TYPE_TRUNK = 2,
+};
+
+#define DSAF_SUB_BASE_SIZE (0x10000)
+
+/* dsaf mode define */
+enum dsaf_mode {
+ DSAF_MODE_INVALID = 0, /**< Invalid dsaf mode */
+ DSAF_MODE_ENABLE_FIX, /**< en DSAF-mode, fixed to queue*/
+ DSAF_MODE_ENABLE_0VM, /**< en DSAF-mode, support 0 VM */
+ DSAF_MODE_ENABLE_8VM, /**< en DSAF-mode, support 8 VM */
+ DSAF_MODE_ENABLE_16VM, /**< en DSAF-mode, support 16 VM */
+ DSAF_MODE_ENABLE_32VM, /**< en DSAF-mode, support 32 VM */
+ DSAF_MODE_ENABLE_128VM, /**< en DSAF-mode, support 128 VM */
+ DSAF_MODE_ENABLE, /**< before is enable DSAF mode*/
+ DSAF_MODE_DISABLE_FIX, /**< non-dasf, fixed to queue*/
+ DSAF_MODE_DISABLE_2PORT_8VM, /**< non-dasf, 2port 8VM */
+ DSAF_MODE_DISABLE_2PORT_16VM, /**< non-dasf, 2port 16VM */
+ DSAF_MODE_DISABLE_2PORT_64VM, /**< non-dasf, 2port 64VM */
+ DSAF_MODE_DISABLE_6PORT_0VM, /**< non-dasf, 6port 0VM */
+ DSAF_MODE_DISABLE_6PORT_2VM, /**< non-dasf, 6port 2VM */
+ DSAF_MODE_DISABLE_6PORT_4VM, /**< non-dasf, 6port 4VM */
+ DSAF_MODE_DISABLE_6PORT_16VM, /**< non-dasf, 6port 16VM */
+ DSAF_MODE_MAX /**< the last one, use as the num */
+};
+
+#define DSAF_DEST_PORT_NUM 256 /* DSAF max port num */
+#define DSAF_WORD_BIT_CNT 32 /* the num bit of word */
+
+/*mac entry, mc or uc entry*/
+struct dsaf_drv_mac_single_dest_entry {
+ /* mac addr, match the entry*/
+ u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+ u16 in_vlan_id; /* value of VlanId */
+
+ /* the vld input port num, dsaf-mode fix 0, */
+ /* non-dasf is the entry whitch port vld*/
+ u8 in_port_num;
+
+ u8 port_num; /*output port num*/
+ u8 rsv[6];
+};
+
+/*only mc entry*/
+struct dsaf_drv_mac_multi_dest_entry {
+ /* mac addr, match the entry*/
+ u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+ u16 in_vlan_id;
+ /* this mac addr output port,*/
+ /* bit0-bit5 means Port0-Port5(1bit is vld)**/
+ u32 port_mask[DSAF_DEST_PORT_NUM / DSAF_WORD_BIT_CNT];
+
+ /* the vld input port num, dsaf-mode fix 0,*/
+ /* non-dasf is the entry whitch port vld*/
+ u8 in_port_num;
+ u8 rsv[7];
+};
+
+struct dsaf_hw_stats {
+ u64 pad_drop;
+ u64 man_pkts;
+ u64 rx_pkts;
+ u64 rx_pkt_id;
+ u64 rx_pause_frame;
+ u64 release_buf_num;
+ u64 sbm_drop;
+ u64 crc_false;
+ u64 bp_drop;
+ u64 rslt_drop;
+ u64 local_addr_false;
+ u64 vlan_drop;
+ u64 stp_drop;
+ u64 tx_pkts;
+};
+
+struct hnae_vf_cb {
+ u8 port_index;
+ struct hns_mac_cb *mac_cb;
+ struct dsaf_device *dsaf_dev;
+ struct hnae_handle ae_handle; /* must be the last number */
+};
+
+struct dsaf_int_xge_src {
+ u32 xid_xge_ecc_err_int_src;
+ u32 xid_xge_fsm_timout_int_src;
+ u32 sbm_xge_lnk_fsm_timout_int_src;
+ u32 sbm_xge_lnk_ecc_2bit_int_src;
+ u32 sbm_xge_mib_req_failed_int_src;
+ u32 sbm_xge_mib_req_fsm_timout_int_src;
+ u32 sbm_xge_mib_rels_fsm_timout_int_src;
+ u32 sbm_xge_sram_ecc_2bit_int_src;
+ u32 sbm_xge_mib_buf_sum_err_int_src;
+ u32 sbm_xge_mib_req_extra_int_src;
+ u32 sbm_xge_mib_rels_extra_int_src;
+ u32 voq_xge_start_to_over_0_int_src;
+ u32 voq_xge_start_to_over_1_int_src;
+ u32 voq_xge_ecc_err_int_src;
+};
+
+struct dsaf_int_ppe_src {
+ u32 xid_ppe_fsm_timout_int_src;
+ u32 sbm_ppe_lnk_fsm_timout_int_src;
+ u32 sbm_ppe_lnk_ecc_2bit_int_src;
+ u32 sbm_ppe_mib_req_failed_int_src;
+ u32 sbm_ppe_mib_req_fsm_timout_int_src;
+ u32 sbm_ppe_mib_rels_fsm_timout_int_src;
+ u32 sbm_ppe_sram_ecc_2bit_int_src;
+ u32 sbm_ppe_mib_buf_sum_err_int_src;
+ u32 sbm_ppe_mib_req_extra_int_src;
+ u32 sbm_ppe_mib_rels_extra_int_src;
+ u32 voq_ppe_start_to_over_0_int_src;
+ u32 voq_ppe_ecc_err_int_src;
+ u32 xod_ppe_fifo_rd_empty_int_src;
+ u32 xod_ppe_fifo_wr_full_int_src;
+};
+
+struct dsaf_int_rocee_src {
+ u32 xid_rocee_fsm_timout_int_src;
+ u32 sbm_rocee_lnk_fsm_timout_int_src;
+ u32 sbm_rocee_lnk_ecc_2bit_int_src;
+ u32 sbm_rocee_mib_req_failed_int_src;
+ u32 sbm_rocee_mib_req_fsm_timout_int_src;
+ u32 sbm_rocee_mib_rels_fsm_timout_int_src;
+ u32 sbm_rocee_sram_ecc_2bit_int_src;
+ u32 sbm_rocee_mib_buf_sum_err_int_src;
+ u32 sbm_rocee_mib_req_extra_int_src;
+ u32 sbm_rocee_mib_rels_extra_int_src;
+ u32 voq_rocee_start_to_over_0_int_src;
+ u32 voq_rocee_ecc_err_int_src;
+};
+
+struct dsaf_int_tbl_src {
+ u32 tbl_da0_mis_src;
+ u32 tbl_da1_mis_src;
+ u32 tbl_da2_mis_src;
+ u32 tbl_da3_mis_src;
+ u32 tbl_da4_mis_src;
+ u32 tbl_da5_mis_src;
+ u32 tbl_da6_mis_src;
+ u32 tbl_da7_mis_src;
+ u32 tbl_sa_mis_src;
+ u32 tbl_old_sech_end_src;
+ u32 lram_ecc_err1_src;
+ u32 lram_ecc_err2_src;
+ u32 tram_ecc_err1_src;
+ u32 tram_ecc_err2_src;
+ u32 tbl_ucast_bcast_xge0_src;
+ u32 tbl_ucast_bcast_xge1_src;
+ u32 tbl_ucast_bcast_xge2_src;
+ u32 tbl_ucast_bcast_xge3_src;
+ u32 tbl_ucast_bcast_xge4_src;
+ u32 tbl_ucast_bcast_xge5_src;
+ u32 tbl_ucast_bcast_ppe_src;
+ u32 tbl_ucast_bcast_rocee_src;
+};
+
+struct dsaf_int_stat {
+ struct dsaf_int_xge_src dsaf_int_xge_stat[DSAF_COMM_CHN];
+ struct dsaf_int_ppe_src dsaf_int_ppe_stat[DSAF_COMM_CHN];
+ struct dsaf_int_rocee_src dsaf_int_rocee_stat[DSAF_COMM_CHN];
+ struct dsaf_int_tbl_src dsaf_int_tbl_stat[1];
+
+};
+
+/* Dsaf device struct define ,and mac -> dsaf */
+struct dsaf_device {
+ struct device *dev;
+ struct hnae_ae_dev ae_dev;
+
+ void *priv;
+
+ int virq[DSAF_IRQ_NUM];
+
+ u8 __iomem *sc_base;
+ u8 __iomem *sds_base;
+ u8 __iomem *ppe_base;
+ u8 __iomem *io_base;
+ u8 __iomem *cpld_base;
+
+ u32 desc_num; /* desc num per queue*/
+ u32 buf_size; /* ring buffer size */
+ int buf_size_type; /* ring buffer size-type */
+ enum dsaf_mode dsaf_mode; /* dsaf mode */
+ enum hal_dsaf_mode dsaf_en;
+ enum hal_dsaf_tc_mode dsaf_tc_mode;
+ u32 dsaf_ver;
+
+ struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM];
+ struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM];
+ struct hns_mac_cb *mac_cb;
+
+ struct dsaf_hw_stats hw_stats[DSAF_NODE_NUM];
+ struct dsaf_int_stat int_stat;
+};
+
+static inline void *hns_dsaf_dev_priv(const struct dsaf_device *dsaf_dev)
+{
+ return (void *)((u8 *)dsaf_dev + sizeof(*dsaf_dev));
+}
+
+struct dsaf_drv_tbl_tcam_key {
+ union {
+ struct {
+ u8 mac_3;
+ u8 mac_2;
+ u8 mac_1;
+ u8 mac_0;
+ } bits;
+
+ u32 val;
+ } high;
+ union {
+ struct {
+ u32 port:4; /* port id, */
+ /* dsaf-mode fixed 0, non-dsaf-mode port id*/
+ u32 vlan:12; /* vlan id */
+ u32 mac_5:8;
+ u32 mac_4:8;
+ } bits;
+
+ u32 val;
+ } low;
+};
+
+struct dsaf_drv_soft_mac_tbl {
+ struct dsaf_drv_tbl_tcam_key tcam_key;
+ u16 index; /*the entry's index in tcam tab*/
+};
+
+struct dsaf_drv_priv {
+ /* soft tab Mac key, for hardware tab*/
+ struct dsaf_drv_soft_mac_tbl *soft_mac_tbl;
+};
+
+static inline void hns_dsaf_tbl_tcam_addr_cfg(struct dsaf_device *dsaf_dev,
+ u32 tab_tcam_addr)
+{
+ dsaf_set_dev_field(dsaf_dev, DSAF_TBL_TCAM_ADDR_0_REG,
+ DSAF_TBL_TCAM_ADDR_M, DSAF_TBL_TCAM_ADDR_S,
+ tab_tcam_addr);
+}
+
+static inline void hns_dsaf_tbl_tcam_load_pul(struct dsaf_device *dsaf_dev)
+{
+ u32 o_tbl_pul;
+
+ o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_LOAD_S, 1);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+ dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_LOAD_S, 0);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
+}
+
+static inline void hns_dsaf_tbl_line_addr_cfg(struct dsaf_device *dsaf_dev,
+ u32 tab_line_addr)
+{
+ dsaf_set_dev_field(dsaf_dev, DSAF_TBL_LINE_ADDR_0_REG,
+ DSAF_TBL_LINE_ADDR_M, DSAF_TBL_LINE_ADDR_S,
+ tab_line_addr);
+}
+
+static inline int hns_dsaf_get_comm_idx_by_port(int port)
+{
+ if ((port < DSAF_COMM_CHN) || (port == DSAF_MAX_PORT_NUM_PER_CHIP))
+ return 0;
+ else
+ return (port - DSAF_COMM_CHN + 1);
+}
+
+static inline struct hnae_vf_cb *hns_ae_get_vf_cb(
+ struct hnae_handle *handle)
+{
+ return container_of(handle, struct hnae_vf_cb, ae_handle);
+}
+
+int hns_dsaf_set_mac_uc_entry(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry);
+int hns_dsaf_set_mac_mc_entry(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_multi_dest_entry *mac_entry);
+int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry);
+int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id,
+ u8 in_port_num, u8 *addr);
+int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry);
+int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry);
+int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_multi_dest_entry *mac_entry);
+int hns_dsaf_get_mac_entry_by_index(
+ struct dsaf_device *dsaf_dev,
+ u16 entry_index,
+ struct dsaf_drv_mac_multi_dest_entry *mac_entry);
+
+void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val);
+
+void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val);
+
+void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val);
+
+void hns_dsaf_fix_mac_mode(struct hns_mac_cb *mac_cb);
+
+int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev);
+void hns_dsaf_ae_uninit(struct dsaf_device *dsaf_dev);
+
+void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val);
+void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val);
+void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev,
+ u32 port, u32 val);
+
+void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 inode_num);
+
+int hns_dsaf_get_sset_count(int stringset);
+void hns_dsaf_get_stats(struct dsaf_device *ddev, u64 *data, int port);
+void hns_dsaf_get_strings(int stringset, u8 *data, int port);
+
+void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data);
+int hns_dsaf_get_regs_count(void);
+void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en);
+
+#endif /* __HNS_DSAF_MAIN_H__ */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
new file mode 100644
index 000000000000..523e9b83d304
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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 "hns_dsaf_misc.h"
+#include "hns_dsaf_mac.h"
+#include "hns_dsaf_reg.h"
+#include "hns_dsaf_ppe.h"
+
+void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status,
+ u16 speed, int data)
+{
+ int speed_reg = 0;
+ u8 value;
+
+ if (!mac_cb) {
+ pr_err("sfp_led_opt mac_dev is null!\n");
+ return;
+ }
+ if (!mac_cb->cpld_vaddr) {
+ dev_err(mac_cb->dev, "mac_id=%d, cpld_vaddr is null !\n",
+ mac_cb->mac_id);
+ return;
+ }
+
+ if (speed == MAC_SPEED_10000)
+ speed_reg = 1;
+
+ value = mac_cb->cpld_led_value;
+
+ if (link_status) {
+ dsaf_set_bit(value, DSAF_LED_LINK_B, link_status);
+ dsaf_set_field(value, DSAF_LED_SPEED_M,
+ DSAF_LED_SPEED_S, speed_reg);
+ dsaf_set_bit(value, DSAF_LED_DATA_B, data);
+
+ if (value != mac_cb->cpld_led_value) {
+ dsaf_write_b(mac_cb->cpld_vaddr, value);
+ mac_cb->cpld_led_value = value;
+ }
+ } else {
+ dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE);
+ mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE;
+ }
+}
+
+void cpld_led_reset(struct hns_mac_cb *mac_cb)
+{
+ if (!mac_cb || !mac_cb->cpld_vaddr)
+ return;
+
+ dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE);
+ mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE;
+}
+
+int cpld_set_led_id(struct hns_mac_cb *mac_cb,
+ enum hnae_led_state status)
+{
+ switch (status) {
+ case HNAE_LED_ACTIVE:
+ mac_cb->cpld_led_value = dsaf_read_b(mac_cb->cpld_vaddr);
+ dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B,
+ CPLD_LED_ON_VALUE);
+ dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value);
+ return 2;
+ case HNAE_LED_INACTIVE:
+ dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B,
+ CPLD_LED_DEFAULT_VALUE);
+ dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+#define RESET_REQ_OR_DREQ 1
+
+void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val)
+{
+ u32 xbar_reg_addr;
+ u32 nt_reg_addr;
+
+ if (!val) {
+ xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_REQ_REG;
+ nt_reg_addr = DSAF_SUB_SC_NT_RESET_REQ_REG;
+ } else {
+ xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_DREQ_REG;
+ nt_reg_addr = DSAF_SUB_SC_NT_RESET_DREQ_REG;
+ }
+
+ dsaf_write_reg(dsaf_dev->sc_base, xbar_reg_addr,
+ RESET_REQ_OR_DREQ);
+ dsaf_write_reg(dsaf_dev->sc_base, nt_reg_addr,
+ RESET_REQ_OR_DREQ);
+}
+
+void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val)
+{
+ u32 reg_val = 0;
+ u32 reg_addr;
+
+ if (port >= DSAF_XGE_NUM)
+ return;
+
+ reg_val |= RESET_REQ_OR_DREQ;
+ reg_val |= 0x2082082 << port;
+
+ if (val == 0)
+ reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG;
+ else
+ reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG;
+
+ dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val);
+}
+
+void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev,
+ u32 port, u32 val)
+{
+ u32 reg_val = 0;
+ u32 reg_addr;
+
+ if (port >= DSAF_XGE_NUM)
+ return;
+
+ reg_val |= XGMAC_TRX_CORE_SRST_M << port;
+
+ if (val == 0)
+ reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG;
+ else
+ reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG;
+
+ dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val);
+}
+
+void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val)
+{
+ u32 reg_val_1;
+ u32 reg_val_2;
+
+ if (port >= DSAF_GE_NUM)
+ return;
+
+ if (port < DSAF_SERVICE_NW_NUM) {
+ reg_val_1 = 0x1 << port;
+ reg_val_2 = 0x1041041 << port;
+
+ if (val == 0) {
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_GE_RESET_REQ1_REG,
+ reg_val_1);
+
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_GE_RESET_REQ0_REG,
+ reg_val_2);
+ } else {
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_GE_RESET_DREQ0_REG,
+ reg_val_2);
+
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_GE_RESET_DREQ1_REG,
+ reg_val_1);
+ }
+ } else {
+ reg_val_1 = 0x15540 << (port - 6);
+ reg_val_2 = 0x100 << (port - 6);
+
+ if (val == 0) {
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_GE_RESET_REQ1_REG,
+ reg_val_1);
+
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_PPE_RESET_REQ_REG,
+ reg_val_2);
+ } else {
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_GE_RESET_DREQ1_REG,
+ reg_val_1);
+
+ dsaf_write_reg(dsaf_dev->sc_base,
+ DSAF_SUB_SC_PPE_RESET_DREQ_REG,
+ reg_val_2);
+ }
+ }
+}
+
+void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val)
+{
+ u32 reg_val = 0;
+ u32 reg_addr;
+
+ reg_val |= RESET_REQ_OR_DREQ << port;
+
+ if (val == 0)
+ reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG;
+ else
+ reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG;
+
+ dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val);
+}
+
+void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val)
+{
+ int comm_index = ppe_common->comm_index;
+ struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev;
+ u32 reg_val;
+ u32 reg_addr;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
+ reg_val = RESET_REQ_OR_DREQ;
+ if (val == 0)
+ reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG;
+ else
+ reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG;
+
+ } else {
+ reg_val = 0x100 << (comm_index - 1);
+
+ if (val == 0)
+ reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG;
+ else
+ reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG;
+ }
+
+ dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val);
+}
+
+/**
+ * hns_mac_get_sds_mode - get phy ifterface form serdes mode
+ * @mac_cb: mac control block
+ * retuen phy interface
+ */
+phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb)
+{
+ u32 hilink3_mode;
+ u32 hilink4_mode;
+ void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr;
+ int dev_id = mac_cb->mac_id;
+ phy_interface_t phy_if = PHY_INTERFACE_MODE_NA;
+
+ hilink3_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK3_REG);
+ hilink4_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK4_REG);
+ if (dev_id >= 0 && dev_id <= 3) {
+ if (hilink4_mode == 0)
+ phy_if = PHY_INTERFACE_MODE_SGMII;
+ else
+ phy_if = PHY_INTERFACE_MODE_XGMII;
+ } else if (dev_id >= 4 && dev_id <= 5) {
+ if (hilink3_mode == 0)
+ phy_if = PHY_INTERFACE_MODE_SGMII;
+ else
+ phy_if = PHY_INTERFACE_MODE_XGMII;
+ } else {
+ phy_if = PHY_INTERFACE_MODE_SGMII;
+ }
+
+ dev_dbg(mac_cb->dev,
+ "hilink3_mode=%d, hilink4_mode=%d dev_id=%d, phy_if=%d\n",
+ hilink3_mode, hilink4_mode, dev_id, phy_if);
+ return phy_if;
+}
+
+/**
+ * hns_mac_config_sds_loopback - set loop back for serdes
+ * @mac_cb: mac control block
+ * retuen 0 == success
+ */
+int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en)
+{
+ /* port 0-3 hilink4 base is serdes_vaddr + 0x00280000
+ * port 4-7 hilink3 base is serdes_vaddr + 0x00200000
+ */
+ u8 *base_addr = (u8 *)mac_cb->serdes_vaddr +
+ (mac_cb->mac_id <= 3 ? 0x00280000 : 0x00200000);
+ const u8 lane_id[] = {
+ 0, /* mac 0 -> lane 0 */
+ 1, /* mac 1 -> lane 1 */
+ 2, /* mac 2 -> lane 2 */
+ 3, /* mac 3 -> lane 3 */
+ 2, /* mac 4 -> lane 2 */
+ 3, /* mac 5 -> lane 3 */
+ 0, /* mac 6 -> lane 0 */
+ 1 /* mac 7 -> lane 1 */
+ };
+#define RX_CSR(lane, reg) ((0x4080 + (reg) * 0x0002 + (lane) * 0x0200) * 2)
+ u64 reg_offset = RX_CSR(lane_id[mac_cb->mac_id], 0);
+
+ int sfp_prsnt;
+ int ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt);
+
+ if (!mac_cb->phy_node) {
+ if (ret)
+ pr_info("please confirm sfp is present or not\n");
+ else
+ if (!sfp_prsnt)
+ pr_info("no sfp in this eth\n");
+ }
+
+ dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h
new file mode 100644
index 000000000000..419f07aa9734
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _HNS_DSAF_MISC_H
+#define _HNS_DSAF_MISC_H
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "hns_dsaf_mac.h"
+
+#define CPLD_ADDR_PORT_OFFSET 0x4
+
+#define HS_LED_ON 0xE
+#define HS_LED_OFF 0xF
+
+#define CPLD_LED_ON_VALUE 1
+#define CPLD_LED_DEFAULT_VALUE 0
+
+#define MAC_SFP_PORT_OFFSET 0x2
+
+#define DSAF_LED_SPEED_S 0
+#define DSAF_LED_SPEED_M (0x3 << DSAF_LED_SPEED_S)
+
+#define DSAF_LED_LINK_B 2
+#define DSAF_LED_DATA_B 4
+#define DSAF_LED_ANCHOR_B 5
+
+void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status,
+ u16 speed, int data);
+void cpld_led_reset(struct hns_mac_cb *mac_cb);
+int cpld_set_led_id(struct hns_mac_cb *mac_cb,
+ enum hnae_led_state status);
+int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
new file mode 100644
index 000000000000..67f33f185a44
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include "hns_dsaf_ppe.h"
+
+static void __iomem *hns_ppe_common_get_ioaddr(
+ struct ppe_common_cb *ppe_common)
+{
+ void __iomem *base_addr;
+
+ int idx = ppe_common->comm_index;
+
+ if (idx == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ base_addr = ppe_common->dsaf_dev->ppe_base
+ + PPE_COMMON_REG_OFFSET;
+ else
+ base_addr = ppe_common->dsaf_dev->sds_base
+ + (idx - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET
+ + PPE_COMMON_REG_OFFSET;
+
+ return base_addr;
+}
+
+/**
+ * hns_ppe_common_get_cfg - get ppe common config
+ * @dsaf_dev: dasf device
+ * comm_index: common index
+ * retuen 0 - success , negative --fail
+ */
+int hns_ppe_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index)
+{
+ struct ppe_common_cb *ppe_common;
+ int ppe_num;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ ppe_num = HNS_PPE_SERVICE_NW_ENGINE_NUM;
+ 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);
+ if (!ppe_common)
+ return -ENOMEM;
+
+ ppe_common->ppe_num = ppe_num;
+ ppe_common->dsaf_dev = dsaf_dev;
+ ppe_common->comm_index = comm_index;
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ ppe_common->ppe_mode = PPE_COMMON_MODE_SERVICE;
+ else
+ ppe_common->ppe_mode = PPE_COMMON_MODE_DEBUG;
+ ppe_common->dev = dsaf_dev->dev;
+
+ ppe_common->io_base = hns_ppe_common_get_ioaddr(ppe_common);
+
+ dsaf_dev->ppe_common[comm_index] = ppe_common;
+
+ return 0;
+}
+
+void hns_ppe_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index)
+{
+ dsaf_dev->ppe_common[comm_index] = NULL;
+}
+
+static void __iomem *hns_ppe_get_iobase(struct ppe_common_cb *ppe_common,
+ int ppe_idx)
+{
+ void __iomem *base_addr;
+ int common_idx = ppe_common->comm_index;
+
+ if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) {
+ base_addr = ppe_common->dsaf_dev->ppe_base +
+ ppe_idx * PPE_REG_OFFSET;
+
+ } else {
+ base_addr = ppe_common->dsaf_dev->sds_base +
+ (common_idx - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET;
+ }
+
+ return base_addr;
+}
+
+static int hns_ppe_get_port(struct ppe_common_cb *ppe_common, int idx)
+{
+ int port;
+
+ if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE)
+ port = idx;
+ else
+ port = HNS_PPE_SERVICE_NW_ENGINE_NUM
+ + ppe_common->comm_index - 1;
+
+ return port;
+}
+
+static void hns_ppe_get_cfg(struct ppe_common_cb *ppe_common)
+{
+ u32 i;
+ struct hns_ppe_cb *ppe_cb;
+ u32 ppe_num = ppe_common->ppe_num;
+
+ for (i = 0; i < ppe_num; i++) {
+ ppe_cb = &ppe_common->ppe_cb[i];
+ ppe_cb->dev = ppe_common->dev;
+ ppe_cb->next = NULL;
+ ppe_cb->ppe_common_cb = ppe_common;
+ ppe_cb->index = i;
+ ppe_cb->port = hns_ppe_get_port(ppe_common, i);
+ ppe_cb->io_base = hns_ppe_get_iobase(ppe_common, i);
+ ppe_cb->virq = 0;
+ }
+}
+
+static void hns_ppe_cnt_clr_ce(struct hns_ppe_cb *ppe_cb)
+{
+ dsaf_set_dev_bit(ppe_cb, PPE_TNL_0_5_CNT_CLR_CE_REG,
+ PPE_CNT_CLR_CE_B, 1);
+}
+
+/**
+ * hns_ppe_checksum_hw - set ppe checksum caculate
+ * @ppe_device: ppe device
+ * @value: value
+ */
+static void hns_ppe_checksum_hw(struct hns_ppe_cb *ppe_cb, u32 value)
+{
+ dsaf_set_dev_field(ppe_cb, PPE_CFG_PRO_CHECK_EN_REG,
+ 0xfffffff, 0, value);
+}
+
+static void hns_ppe_set_qid_mode(struct ppe_common_cb *ppe_common,
+ enum ppe_qid_mode qid_mdoe)
+{
+ dsaf_set_dev_field(ppe_common, PPE_COM_CFG_QID_MODE_REG,
+ PPE_CFG_QID_MODE_CF_QID_MODE_M,
+ PPE_CFG_QID_MODE_CF_QID_MODE_S, qid_mdoe);
+}
+
+/**
+ * hns_ppe_set_qid - set ppe qid
+ * @ppe_common: ppe common device
+ * @qid: queue id
+ */
+static void hns_ppe_set_qid(struct ppe_common_cb *ppe_common, u32 qid)
+{
+ u32 qid_mod = dsaf_read_dev(ppe_common, PPE_COM_CFG_QID_MODE_REG);
+
+ if (!dsaf_get_field(qid_mod, PPE_CFG_QID_MODE_DEF_QID_M,
+ PPE_CFG_QID_MODE_DEF_QID_S)) {
+ dsaf_set_field(qid_mod, PPE_CFG_QID_MODE_DEF_QID_M,
+ PPE_CFG_QID_MODE_DEF_QID_S, qid);
+ dsaf_write_dev(ppe_common, PPE_COM_CFG_QID_MODE_REG, qid_mod);
+ }
+}
+
+/**
+ * hns_ppe_set_port_mode - set port mode
+ * @ppe_device: ppe device
+ * @mode: port mode
+ */
+static void hns_ppe_set_port_mode(struct hns_ppe_cb *ppe_cb,
+ enum ppe_port_mode mode)
+{
+ dsaf_write_dev(ppe_cb, PPE_CFG_XGE_MODE_REG, mode);
+}
+
+/**
+ * hns_ppe_common_init_hw - init ppe common device
+ * @ppe_common: ppe common device
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_ppe_common_init_hw(struct ppe_common_cb *ppe_common)
+{
+ enum ppe_qid_mode qid_mode;
+ enum dsaf_mode dsaf_mode = ppe_common->dsaf_dev->dsaf_mode;
+
+ hns_ppe_com_srst(ppe_common, 0);
+ mdelay(100);
+ hns_ppe_com_srst(ppe_common, 1);
+ mdelay(100);
+
+ if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) {
+ switch (dsaf_mode) {
+ case DSAF_MODE_ENABLE_FIX:
+ case DSAF_MODE_DISABLE_FIX:
+ qid_mode = PPE_QID_MODE0;
+ hns_ppe_set_qid(ppe_common, 0);
+ break;
+ case DSAF_MODE_ENABLE_0VM:
+ case DSAF_MODE_DISABLE_2PORT_64VM:
+ qid_mode = PPE_QID_MODE3;
+ break;
+ case DSAF_MODE_ENABLE_8VM:
+ case DSAF_MODE_DISABLE_2PORT_16VM:
+ qid_mode = PPE_QID_MODE4;
+ break;
+ case DSAF_MODE_ENABLE_16VM:
+ case DSAF_MODE_DISABLE_6PORT_0VM:
+ qid_mode = PPE_QID_MODE5;
+ break;
+ case DSAF_MODE_ENABLE_32VM:
+ case DSAF_MODE_DISABLE_6PORT_16VM:
+ qid_mode = PPE_QID_MODE2;
+ break;
+ case DSAF_MODE_ENABLE_128VM:
+ case DSAF_MODE_DISABLE_6PORT_4VM:
+ qid_mode = PPE_QID_MODE1;
+ break;
+ case DSAF_MODE_DISABLE_2PORT_8VM:
+ qid_mode = PPE_QID_MODE7;
+ break;
+ case DSAF_MODE_DISABLE_6PORT_2VM:
+ qid_mode = PPE_QID_MODE6;
+ break;
+ default:
+ dev_err(ppe_common->dev,
+ "get ppe queue mode failed! dsaf_mode=%d\n",
+ dsaf_mode);
+ return -EINVAL;
+ }
+ hns_ppe_set_qid_mode(ppe_common, qid_mode);
+ }
+
+ dsaf_set_dev_bit(ppe_common, PPE_COM_COMMON_CNT_CLR_CE_REG,
+ PPE_COMMON_CNT_CLR_CE_B, 1);
+
+ return 0;
+}
+
+/*clr ppe exception irq*/
+static void hns_ppe_exc_irq_en(struct hns_ppe_cb *ppe_cb, int en)
+{
+ u32 clr_vlue = 0xfffffffful;
+ u32 msk_vlue = en ? 0xfffffffful : 0; /*1 is en, 0 is dis*/
+ u32 vld_msk = 0;
+
+ /*only care bit 0,1,7*/
+ dsaf_set_bit(vld_msk, 0, 1);
+ dsaf_set_bit(vld_msk, 1, 1);
+ dsaf_set_bit(vld_msk, 7, 1);
+
+ /*clr sts**/
+ dsaf_write_dev(ppe_cb, PPE_RINT_REG, clr_vlue);
+
+ /*for some reserved bits, so set 0**/
+ dsaf_write_dev(ppe_cb, PPE_INTEN_REG, msk_vlue & vld_msk);
+}
+
+/**
+ * ppe_init_hw - init ppe
+ * @ppe_device: ppe device
+ */
+static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb)
+{
+ struct ppe_common_cb *ppe_common_cb = ppe_cb->ppe_common_cb;
+ u32 port = ppe_cb->port;
+ struct dsaf_device *dsaf_dev = ppe_common_cb->dsaf_dev;
+
+ hns_ppe_srst_by_port(dsaf_dev, port, 0);
+ mdelay(10);
+ hns_ppe_srst_by_port(dsaf_dev, port, 1);
+
+ /* clr and msk except irq*/
+ hns_ppe_exc_irq_en(ppe_cb, 0);
+
+ if (ppe_common_cb->ppe_mode == PPE_COMMON_MODE_DEBUG)
+ hns_ppe_set_port_mode(ppe_cb, PPE_MODE_GE);
+ else
+ hns_ppe_set_port_mode(ppe_cb, PPE_MODE_XGE);
+ hns_ppe_checksum_hw(ppe_cb, 0xffffffff);
+ hns_ppe_cnt_clr_ce(ppe_cb);
+}
+
+/**
+ * ppe_uninit_hw - uninit ppe
+ * @ppe_device: ppe device
+ */
+static void hns_ppe_uninit_hw(struct hns_ppe_cb *ppe_cb)
+{
+ u32 port;
+
+ if (ppe_cb->ppe_common_cb) {
+ port = ppe_cb->index;
+ hns_ppe_srst_by_port(ppe_cb->ppe_common_cb->dsaf_dev, port, 0);
+ }
+}
+
+void hns_ppe_uninit_ex(struct ppe_common_cb *ppe_common)
+{
+ u32 i;
+
+ for (i = 0; i < ppe_common->ppe_num; i++) {
+ hns_ppe_uninit_hw(&ppe_common->ppe_cb[i]);
+ memset(&ppe_common->ppe_cb[i], 0, sizeof(struct hns_ppe_cb));
+ }
+}
+
+void hns_ppe_uninit(struct dsaf_device *dsaf_dev)
+{
+ u32 i;
+
+ for (i = 0; i < HNS_PPE_COM_NUM; i++) {
+ if (dsaf_dev->ppe_common[i])
+ hns_ppe_uninit_ex(dsaf_dev->ppe_common[i]);
+ hns_rcb_common_free_cfg(dsaf_dev, i);
+ hns_ppe_common_free_cfg(dsaf_dev, i);
+ }
+}
+
+/**
+ * hns_ppe_reset - reinit ppe/rcb hw
+ * @dsaf_dev: dasf device
+ * retuen void
+ */
+void hns_ppe_reset_common(struct dsaf_device *dsaf_dev, u8 ppe_common_index)
+{
+ u32 i;
+ int ret;
+ struct ppe_common_cb *ppe_common;
+
+ ppe_common = dsaf_dev->ppe_common[ppe_common_index];
+ ret = hns_ppe_common_init_hw(ppe_common);
+ if (ret)
+ return;
+
+ ret = hns_rcb_common_init_hw(dsaf_dev->rcb_common[ppe_common_index]);
+ if (ret)
+ return;
+
+ for (i = 0; i < ppe_common->ppe_num; i++)
+ hns_ppe_init_hw(&ppe_common->ppe_cb[i]);
+
+ hns_rcb_common_init_commit_hw(dsaf_dev->rcb_common[ppe_common_index]);
+}
+
+void hns_ppe_update_stats(struct hns_ppe_cb *ppe_cb)
+{
+ struct hns_ppe_hw_stats *hw_stats = &ppe_cb->hw_stats;
+
+ hw_stats->rx_pkts_from_sw
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_SW_PKT_CNT_REG);
+ hw_stats->rx_pkts
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_WR_BD_OK_PKT_CNT_REG);
+ hw_stats->rx_drop_no_bd
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_NO_BUF_CNT_REG);
+ hw_stats->rx_alloc_buf_fail
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_FAIL_CNT_REG);
+ hw_stats->rx_alloc_buf_wait
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_WAIT_CNT_REG);
+ hw_stats->rx_drop_no_buf
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_FUL_CNT_REG);
+ hw_stats->rx_err_fifo_full
+ += dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_PRT_CNT_REG);
+
+ hw_stats->tx_bd_form_rcb
+ += dsaf_read_dev(ppe_cb, PPE_HIS_TX_BD_CNT_REG);
+ hw_stats->tx_pkts_from_rcb
+ += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CNT_REG);
+ hw_stats->tx_pkts
+ += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_OK_CNT_REG);
+ hw_stats->tx_err_fifo_empty
+ += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_EPT_CNT_REG);
+ hw_stats->tx_err_checksum
+ += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CS_FAIL_CNT_REG);
+}
+
+int hns_ppe_get_sset_count(int stringset)
+{
+ if (stringset == ETH_SS_STATS)
+ return ETH_PPE_STATIC_NUM;
+ return 0;
+}
+
+int hns_ppe_get_regs_count(void)
+{
+ return ETH_PPE_DUMP_NUM;
+}
+
+/**
+ * ppe_get_strings - get ppe srting
+ * @ppe_device: ppe device
+ * @stringset: string set type
+ * @data: output string
+ */
+void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 *data)
+{
+ char *buff = (char *)data;
+ int index = ppe_cb->index;
+
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_sw_pkt", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_pkt_ok", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_drop_pkt_no_bd", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_alloc_buf_fail", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_alloc_buf_wait", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_pkt_drop_no_buf", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_pkt_err_fifo_full", index);
+ buff = buff + ETH_GSTRING_LEN;
+
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_bd", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt_ok", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt_err_fifo_empty", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt_err_csum_fail", index);
+}
+
+void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 *data)
+{
+ u64 *regs_buff = data;
+ struct hns_ppe_hw_stats *hw_stats = &ppe_cb->hw_stats;
+
+ regs_buff[0] = hw_stats->rx_pkts_from_sw;
+ regs_buff[1] = hw_stats->rx_pkts;
+ regs_buff[2] = hw_stats->rx_drop_no_bd;
+ regs_buff[3] = hw_stats->rx_alloc_buf_fail;
+ regs_buff[4] = hw_stats->rx_alloc_buf_wait;
+ regs_buff[5] = hw_stats->rx_drop_no_buf;
+ regs_buff[6] = hw_stats->rx_err_fifo_full;
+
+ regs_buff[7] = hw_stats->tx_bd_form_rcb;
+ regs_buff[8] = hw_stats->tx_pkts_from_rcb;
+ regs_buff[9] = hw_stats->tx_pkts;
+ regs_buff[10] = hw_stats->tx_err_fifo_empty;
+ regs_buff[11] = hw_stats->tx_err_checksum;
+}
+
+/**
+ * hns_ppe_init - init ppe device
+ * @dsaf_dev: dasf device
+ * retuen 0 - success , negative --fail
+ */
+int hns_ppe_init(struct dsaf_device *dsaf_dev)
+{
+ int i, k;
+ int ret;
+
+ for (i = 0; i < HNS_PPE_COM_NUM; i++) {
+ ret = hns_ppe_common_get_cfg(dsaf_dev, i);
+ if (ret)
+ goto get_ppe_cfg_fail;
+
+ ret = hns_rcb_common_get_cfg(dsaf_dev, i);
+ if (ret)
+ goto get_rcb_cfg_fail;
+
+ hns_ppe_get_cfg(dsaf_dev->ppe_common[i]);
+
+ hns_rcb_get_cfg(dsaf_dev->rcb_common[i]);
+ }
+
+ for (i = 0; i < HNS_PPE_COM_NUM; i++)
+ hns_ppe_reset_common(dsaf_dev, i);
+
+ return 0;
+
+get_rcb_cfg_fail:
+ hns_ppe_common_free_cfg(dsaf_dev, i);
+get_ppe_cfg_fail:
+ for (k = i - 1; k >= 0; k--) {
+ hns_rcb_common_free_cfg(dsaf_dev, k);
+ hns_ppe_common_free_cfg(dsaf_dev, k);
+ }
+ return ret;
+}
+
+void hns_ppe_get_regs(struct hns_ppe_cb *ppe_cb, void *data)
+{
+ struct ppe_common_cb *ppe_common = ppe_cb->ppe_common_cb;
+ u32 *regs = data;
+ u32 i;
+ u32 offset;
+
+ /* ppe common registers */
+ regs[0] = dsaf_read_dev(ppe_common, PPE_COM_CFG_QID_MODE_REG);
+ regs[1] = dsaf_read_dev(ppe_common, PPE_COM_INTEN_REG);
+ regs[2] = dsaf_read_dev(ppe_common, PPE_COM_RINT_REG);
+ regs[3] = dsaf_read_dev(ppe_common, PPE_COM_INTSTS_REG);
+ regs[4] = dsaf_read_dev(ppe_common, PPE_COM_COMMON_CNT_CLR_CE_REG);
+
+ for (i = 0; i < DSAF_TOTAL_QUEUE_NUM; i++) {
+ offset = PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG + 0x4 * i;
+ regs[5 + i] = dsaf_read_dev(ppe_common, offset);
+ offset = PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG + 0x4 * i;
+ regs[5 + i + DSAF_TOTAL_QUEUE_NUM]
+ = dsaf_read_dev(ppe_common, offset);
+ offset = PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG + 0x4 * i;
+ regs[5 + i + DSAF_TOTAL_QUEUE_NUM * 2]
+ = dsaf_read_dev(ppe_common, offset);
+ offset = PPE_COM_HIS_TX_PKT_QID_OK_CNT_REG + 0x4 * i;
+ regs[5 + i + DSAF_TOTAL_QUEUE_NUM * 3]
+ = dsaf_read_dev(ppe_common, offset);
+ }
+
+ /* mark end of ppe regs */
+ for (i = 521; i < 524; i++)
+ regs[i] = 0xeeeeeeee;
+
+ /* ppe channel registers */
+ regs[525] = dsaf_read_dev(ppe_cb, PPE_CFG_TX_FIFO_THRSLD_REG);
+ regs[526] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_FIFO_THRSLD_REG);
+ regs[527] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_FIFO_PAUSE_THRSLD_REG);
+ regs[528] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_FIFO_SW_BP_THRSLD_REG);
+ regs[529] = dsaf_read_dev(ppe_cb, PPE_CFG_PAUSE_IDLE_CNT_REG);
+ regs[530] = dsaf_read_dev(ppe_cb, PPE_CFG_BUS_CTRL_REG);
+ regs[531] = dsaf_read_dev(ppe_cb, PPE_CFG_TNL_TO_BE_RST_REG);
+ regs[532] = dsaf_read_dev(ppe_cb, PPE_CURR_TNL_CAN_RST_REG);
+
+ regs[533] = dsaf_read_dev(ppe_cb, PPE_CFG_XGE_MODE_REG);
+ regs[534] = dsaf_read_dev(ppe_cb, PPE_CFG_MAX_FRAME_LEN_REG);
+ regs[535] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_PKT_MODE_REG);
+ regs[536] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_VLAN_TAG_REG);
+ regs[537] = dsaf_read_dev(ppe_cb, PPE_CFG_TAG_GEN_REG);
+ regs[538] = dsaf_read_dev(ppe_cb, PPE_CFG_PARSE_TAG_REG);
+ regs[539] = dsaf_read_dev(ppe_cb, PPE_CFG_PRO_CHECK_EN_REG);
+
+ regs[540] = dsaf_read_dev(ppe_cb, PPE_INTEN_REG);
+ regs[541] = dsaf_read_dev(ppe_cb, PPE_RINT_REG);
+ regs[542] = dsaf_read_dev(ppe_cb, PPE_INTSTS_REG);
+ regs[543] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_PKT_INT_REG);
+
+ regs[544] = dsaf_read_dev(ppe_cb, PPE_CFG_HEAT_DECT_TIME0_REG);
+ regs[545] = dsaf_read_dev(ppe_cb, PPE_CFG_HEAT_DECT_TIME1_REG);
+
+ /* ppe static */
+ regs[546] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_SW_PKT_CNT_REG);
+ regs[547] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_WR_BD_OK_PKT_CNT_REG);
+ regs[548] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_NO_BUF_CNT_REG);
+ regs[549] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_BD_CNT_REG);
+ regs[550] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CNT_REG);
+ regs[551] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_OK_CNT_REG);
+ regs[552] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_EPT_CNT_REG);
+ regs[553] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CS_FAIL_CNT_REG);
+ regs[554] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_FAIL_CNT_REG);
+ regs[555] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_WAIT_CNT_REG);
+ regs[556] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_FUL_CNT_REG);
+ regs[557] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_PRT_CNT_REG);
+
+ regs[558] = dsaf_read_dev(ppe_cb, PPE_TNL_0_5_CNT_CLR_CE_REG);
+ regs[559] = dsaf_read_dev(ppe_cb, PPE_CFG_AXI_DBG_REG);
+ regs[560] = dsaf_read_dev(ppe_cb, PPE_HIS_PRO_ERR_REG);
+ regs[561] = dsaf_read_dev(ppe_cb, PPE_HIS_TNL_FIFO_ERR_REG);
+ regs[562] = dsaf_read_dev(ppe_cb, PPE_CURR_CFF_DATA_NUM_REG);
+ regs[563] = dsaf_read_dev(ppe_cb, PPE_CURR_RX_ST_REG);
+ regs[564] = dsaf_read_dev(ppe_cb, PPE_CURR_TX_ST_REG);
+ regs[565] = dsaf_read_dev(ppe_cb, PPE_CURR_RX_FIFO0_REG);
+ regs[566] = dsaf_read_dev(ppe_cb, PPE_CURR_RX_FIFO1_REG);
+ regs[567] = dsaf_read_dev(ppe_cb, PPE_CURR_TX_FIFO0_REG);
+ regs[568] = dsaf_read_dev(ppe_cb, PPE_CURR_TX_FIFO1_REG);
+ regs[569] = dsaf_read_dev(ppe_cb, PPE_ECO0_REG);
+ regs[570] = dsaf_read_dev(ppe_cb, PPE_ECO1_REG);
+ regs[571] = dsaf_read_dev(ppe_cb, PPE_ECO2_REG);
+
+ /* mark end of ppe regs */
+ for (i = 572; i < 576; i++)
+ regs[i] = 0xeeeeeeee;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
new file mode 100644
index 000000000000..4894f9a0d39f
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _HNS_DSAF_PPE_H
+#define _HNS_DSAF_PPE_H
+
+#include <linux/platform_device.h>
+
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_mac.h"
+#include "hns_dsaf_rcb.h"
+
+#define HNS_PPE_SERVICE_NW_ENGINE_NUM DSAF_COMM_CHN
+#define HNS_PPE_DEBUG_NW_ENGINE_NUM 1
+#define HNS_PPE_COM_NUM DSAF_COMM_DEV_NUM
+
+#define PPE_COMMON_REG_OFFSET 0x70000
+#define PPE_REG_OFFSET 0x10000
+
+#define ETH_PPE_DUMP_NUM 576
+#define ETH_PPE_STATIC_NUM 12
+enum ppe_qid_mode {
+ PPE_QID_MODE0 = 0, /* fixed queue id mode */
+ PPE_QID_MODE1, /* switch:128VM non switch:6Port/4VM/4TC */
+ PPE_QID_MODE2, /* switch:32VM/4TC non switch:6Port/16VM */
+ PPE_QID_MODE3, /* switch:4TC/8TAG non switch:2Port/64VM */
+ PPE_QID_MODE4, /* switch:8VM/16TAG non switch:2Port/16VM/4TC */
+ PPE_QID_MODE5, /* non switch:6Port/16TAG */
+ PPE_QID_MODE6, /* non switch:6Port/2VM/8TC */
+ PPE_QID_MODE7, /* non switch:2Port/8VM/8TC */
+};
+
+enum ppe_port_mode {
+ PPE_MODE_GE = 0,
+ PPE_MODE_XGE,
+};
+
+enum ppe_common_mode {
+ PPE_COMMON_MODE_DEBUG = 0,
+ PPE_COMMON_MODE_SERVICE,
+ PPE_COMMON_MODE_MAX
+};
+
+struct hns_ppe_hw_stats {
+ u64 rx_pkts_from_sw;
+ u64 rx_pkts;
+ u64 rx_drop_no_bd;
+ u64 rx_alloc_buf_fail;
+ u64 rx_alloc_buf_wait;
+ u64 rx_drop_no_buf;
+ u64 rx_err_fifo_full;
+ u64 tx_bd_form_rcb;
+ u64 tx_pkts_from_rcb;
+ u64 tx_pkts;
+ u64 tx_err_fifo_empty;
+ u64 tx_err_checksum;
+};
+
+struct hns_ppe_cb {
+ struct device *dev;
+ struct hns_ppe_cb *next; /* pointer to next ppe device */
+ struct ppe_common_cb *ppe_common_cb; /* belong to */
+ struct hns_ppe_hw_stats hw_stats;
+
+ u8 index; /* index in a ppe common device */
+ u8 port; /* port id in dsaf */
+ void __iomem *io_base;
+ int virq;
+};
+
+struct ppe_common_cb {
+ struct device *dev;
+ struct dsaf_device *dsaf_dev;
+ void __iomem *io_base;
+
+ enum ppe_common_mode ppe_mode;
+
+ u8 comm_index; /*ppe_common index*/
+
+ u32 ppe_num;
+ struct hns_ppe_cb ppe_cb[0];
+
+};
+
+int hns_ppe_init(struct dsaf_device *dsaf_dev);
+
+void hns_ppe_uninit(struct dsaf_device *dsaf_dev);
+
+void hns_ppe_reset_common(struct dsaf_device *dsaf_dev, u8 ppe_common_index);
+
+void hns_ppe_update_stats(struct hns_ppe_cb *ppe_cb);
+
+int hns_ppe_get_sset_count(int stringset);
+int hns_ppe_get_regs_count(void);
+void hns_ppe_get_regs(struct hns_ppe_cb *ppe_cb, void *data);
+
+void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 *data);
+void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 *data);
+#endif /* _HNS_DSAF_PPE_H */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
new file mode 100644
index 000000000000..4db32c62f062
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -0,0 +1,1021 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/cdev.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <asm/cacheflush.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_ppe.h"
+#include "hns_dsaf_rcb.h"
+
+#define RCB_COMMON_REG_OFFSET 0x80000
+#define TX_RING 0
+#define RX_RING 1
+
+#define RCB_RESET_WAIT_TIMES 30
+#define RCB_RESET_TRY_TIMES 10
+
+/**
+ *hns_rcb_wait_fbd_clean - clean fbd
+ *@qs: ring struct pointer array
+ *@qnum: num of array
+ *@flag: tx or rx flag
+ */
+void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag)
+{
+ int i, wait_cnt;
+ u32 fbd_num;
+
+ for (wait_cnt = i = 0; i < q_num; wait_cnt++) {
+ usleep_range(200, 300);
+ fbd_num = 0;
+ if (flag & RCB_INT_FLAG_TX)
+ fbd_num += dsaf_read_dev(qs[i],
+ RCB_RING_TX_RING_FBDNUM_REG);
+ if (flag & RCB_INT_FLAG_RX)
+ fbd_num += dsaf_read_dev(qs[i],
+ RCB_RING_RX_RING_FBDNUM_REG);
+ if (!fbd_num)
+ i++;
+ if (wait_cnt >= 10000)
+ break;
+ }
+
+ if (i < q_num)
+ dev_err(qs[i]->handle->owner_dev,
+ "queue(%d) wait fbd(%d) clean fail!!\n", i, fbd_num);
+}
+
+/**
+ *hns_rcb_reset_ring_hw - ring reset
+ *@q: ring struct pointer
+ */
+void hns_rcb_reset_ring_hw(struct hnae_queue *q)
+{
+ u32 wait_cnt;
+ u32 try_cnt = 0;
+ u32 could_ret;
+
+ u32 tx_fbd_num;
+
+ while (try_cnt++ < RCB_RESET_TRY_TIMES) {
+ usleep_range(100, 200);
+ tx_fbd_num = dsaf_read_dev(q, RCB_RING_TX_RING_FBDNUM_REG);
+ if (tx_fbd_num)
+ continue;
+
+ dsaf_write_dev(q, RCB_RING_PREFETCH_EN_REG, 0);
+
+ dsaf_write_dev(q, RCB_RING_T0_BE_RST, 1);
+
+ msleep(20);
+ could_ret = dsaf_read_dev(q, RCB_RING_COULD_BE_RST);
+
+ wait_cnt = 0;
+ while (!could_ret && (wait_cnt < RCB_RESET_WAIT_TIMES)) {
+ dsaf_write_dev(q, RCB_RING_T0_BE_RST, 0);
+
+ dsaf_write_dev(q, RCB_RING_T0_BE_RST, 1);
+
+ msleep(20);
+ could_ret = dsaf_read_dev(q, RCB_RING_COULD_BE_RST);
+
+ wait_cnt++;
+ }
+
+ dsaf_write_dev(q, RCB_RING_T0_BE_RST, 0);
+
+ if (could_ret)
+ break;
+ }
+
+ if (try_cnt >= RCB_RESET_TRY_TIMES)
+ dev_err(q->dev->dev, "port%d reset ring fail\n",
+ hns_ae_get_vf_cb(q->handle)->port_index);
+}
+
+/**
+ *hns_rcb_int_ctrl_hw - rcb irq enable control
+ *@q: hnae queue struct pointer
+ *@flag:ring flag tx or rx
+ *@mask:mask
+ */
+void hns_rcb_int_ctrl_hw(struct hnae_queue *q, u32 flag, u32 mask)
+{
+ u32 int_mask_en = !!mask;
+
+ if (flag & RCB_INT_FLAG_TX) {
+ dsaf_write_dev(q, RCB_RING_INTMSK_TXWL_REG, int_mask_en);
+ dsaf_write_dev(q, RCB_RING_INTMSK_TX_OVERTIME_REG,
+ int_mask_en);
+ }
+
+ if (flag & RCB_INT_FLAG_RX) {
+ dsaf_write_dev(q, RCB_RING_INTMSK_RXWL_REG, int_mask_en);
+ dsaf_write_dev(q, RCB_RING_INTMSK_RX_OVERTIME_REG,
+ int_mask_en);
+ }
+}
+
+void hns_rcb_int_clr_hw(struct hnae_queue *q, u32 flag)
+{
+ u32 clr = 1;
+
+ if (flag & RCB_INT_FLAG_TX) {
+ dsaf_write_dev(q, RCB_RING_INTSTS_TX_RING_REG, clr);
+ dsaf_write_dev(q, RCB_RING_INTSTS_TX_OVERTIME_REG, clr);
+ }
+
+ if (flag & RCB_INT_FLAG_RX) {
+ dsaf_write_dev(q, RCB_RING_INTSTS_RX_RING_REG, clr);
+ dsaf_write_dev(q, RCB_RING_INTSTS_RX_OVERTIME_REG, clr);
+ }
+}
+
+/**
+ *hns_rcb_ring_enable_hw - enable ring
+ *@ring: rcb ring
+ */
+void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val)
+{
+ dsaf_write_dev(q, RCB_RING_PREFETCH_EN_REG, !!val);
+}
+
+void hns_rcb_start(struct hnae_queue *q, u32 val)
+{
+ hns_rcb_ring_enable_hw(q, val);
+}
+
+/**
+ *hns_rcb_common_init_commit_hw - make rcb common init completed
+ *@rcb_common: rcb common device
+ */
+void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common)
+{
+ wmb(); /* Sync point before breakpoint */
+ dsaf_write_dev(rcb_common, RCB_COM_CFG_SYS_FSH_REG, 1);
+ wmb(); /* Sync point after breakpoint */
+}
+
+/**
+ *hns_rcb_ring_init - init rcb ring
+ *@ring_pair: ring pair control block
+ *@ring_type: ring type, RX_RING or TX_RING
+ */
+static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type)
+{
+ struct hnae_queue *q = &ring_pair->q;
+ struct rcb_common_cb *rcb_common = ring_pair->rcb_common;
+ u32 bd_size_type = rcb_common->dsaf_dev->buf_size_type;
+ struct hnae_ring *ring =
+ (ring_type == RX_RING) ? &q->rx_ring : &q->tx_ring;
+ dma_addr_t dma = ring->desc_dma_addr;
+
+ if (ring_type == RX_RING) {
+ dsaf_write_dev(q, RCB_RING_RX_RING_BASEADDR_L_REG,
+ (u32)dma);
+ dsaf_write_dev(q, RCB_RING_RX_RING_BASEADDR_H_REG,
+ (u32)((dma >> 31) >> 1));
+ dsaf_write_dev(q, RCB_RING_RX_RING_BD_LEN_REG,
+ bd_size_type);
+ dsaf_write_dev(q, RCB_RING_RX_RING_BD_NUM_REG,
+ ring_pair->port_id_in_dsa);
+ dsaf_write_dev(q, RCB_RING_RX_RING_PKTLINE_REG,
+ ring_pair->port_id_in_dsa);
+ } else {
+ dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_L_REG,
+ (u32)dma);
+ dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_H_REG,
+ (u32)((dma >> 31) >> 1));
+ dsaf_write_dev(q, RCB_RING_TX_RING_BD_LEN_REG,
+ bd_size_type);
+ dsaf_write_dev(q, RCB_RING_TX_RING_BD_NUM_REG,
+ ring_pair->port_id_in_dsa);
+ dsaf_write_dev(q, RCB_RING_TX_RING_PKTLINE_REG,
+ ring_pair->port_id_in_dsa);
+ }
+}
+
+/**
+ *hns_rcb_init_hw - init rcb hardware
+ *@ring: rcb ring
+ */
+void hns_rcb_init_hw(struct ring_pair_cb *ring)
+{
+ hns_rcb_ring_init(ring, RX_RING);
+ hns_rcb_ring_init(ring, TX_RING);
+}
+
+/**
+ *hns_rcb_set_port_desc_cnt - set rcb port description num
+ *@rcb_common: rcb_common device
+ *@port_idx:port index
+ *@desc_cnt:BD num
+ */
+static void hns_rcb_set_port_desc_cnt(struct rcb_common_cb *rcb_common,
+ u32 port_idx, u32 desc_cnt)
+{
+ if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM)
+ port_idx = 0;
+
+ dsaf_write_dev(rcb_common, RCB_CFG_BD_NUM_REG + port_idx * 4,
+ desc_cnt);
+}
+
+/**
+ *hns_rcb_set_port_coalesced_frames - set rcb port coalesced frames
+ *@rcb_common: rcb_common device
+ *@port_idx:port index
+ *@coalesced_frames:BD num for coalesced frames
+ */
+static int hns_rcb_set_port_coalesced_frames(struct rcb_common_cb *rcb_common,
+ u32 port_idx,
+ u32 coalesced_frames)
+{
+ if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM)
+ port_idx = 0;
+ if (coalesced_frames >= rcb_common->desc_num ||
+ coalesced_frames > HNS_RCB_MAX_COALESCED_FRAMES)
+ return -EINVAL;
+
+ dsaf_write_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4,
+ coalesced_frames);
+ return 0;
+}
+
+/**
+ *hns_rcb_get_port_coalesced_frames - set rcb port coalesced frames
+ *@rcb_common: rcb_common device
+ *@port_idx:port index
+ * return coaleseced frames value
+ */
+static u32 hns_rcb_get_port_coalesced_frames(struct rcb_common_cb *rcb_common,
+ u32 port_idx)
+{
+ if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM)
+ port_idx = 0;
+
+ return dsaf_read_dev(rcb_common,
+ RCB_CFG_PKTLINE_REG + port_idx * 4);
+}
+
+/**
+ *hns_rcb_set_timeout - set rcb port coalesced time_out
+ *@rcb_common: rcb_common device
+ *@time_out:time for coalesced time_out
+ */
+static void hns_rcb_set_timeout(struct rcb_common_cb *rcb_common,
+ u32 timeout)
+{
+ dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, timeout);
+}
+
+static int hns_rcb_common_get_port_num(struct rcb_common_cb *rcb_common)
+{
+ if (rcb_common->comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ return HNS_RCB_SERVICE_NW_ENGINE_NUM;
+ else
+ return HNS_RCB_DEBUG_NW_ENGINE_NUM;
+}
+
+/*clr rcb comm exception irq**/
+static void hns_rcb_comm_exc_irq_en(
+ struct rcb_common_cb *rcb_common, int en)
+{
+ u32 clr_vlue = 0xfffffffful;
+ u32 msk_vlue = en ? 0 : 0xfffffffful;
+
+ /* clr int*/
+ dsaf_write_dev(rcb_common, RCB_COM_INTSTS_ECC_ERR_REG, clr_vlue);
+
+ dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_RING_STS, clr_vlue);
+
+ dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_BD_RINT_STS, clr_vlue);
+
+ dsaf_write_dev(rcb_common, RCB_COM_RINT_TX_PKT_REG, clr_vlue);
+ dsaf_write_dev(rcb_common, RCB_COM_AXI_ERR_STS, clr_vlue);
+
+ /*en msk*/
+ dsaf_write_dev(rcb_common, RCB_COM_INTMASK_ECC_ERR_REG, msk_vlue);
+
+ dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_INTMASK_RING, msk_vlue);
+
+ /*for tx bd neednot cacheline, so msk sf_txring_fbd_intmask (bit 1)**/
+ dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_INTMASK_BD, msk_vlue | 2);
+
+ dsaf_write_dev(rcb_common, RCB_COM_INTMSK_TX_PKT_REG, msk_vlue);
+ dsaf_write_dev(rcb_common, RCB_COM_AXI_WR_ERR_INTMASK, msk_vlue);
+}
+
+/**
+ *hns_rcb_common_init_hw - init rcb common hardware
+ *@rcb_common: rcb_common device
+ *retuen 0 - success , negative --fail
+ */
+int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common)
+{
+ u32 reg_val;
+ int i;
+ int port_num = hns_rcb_common_get_port_num(rcb_common);
+
+ hns_rcb_comm_exc_irq_en(rcb_common, 0);
+
+ reg_val = dsaf_read_dev(rcb_common, RCB_COM_CFG_INIT_FLAG_REG);
+ if (0x1 != (reg_val & 0x1)) {
+ dev_err(rcb_common->dsaf_dev->dev,
+ "RCB_COM_CFG_INIT_FLAG_REG reg = 0x%x\n", reg_val);
+ return -EBUSY;
+ }
+
+ for (i = 0; i < port_num; i++) {
+ hns_rcb_set_port_desc_cnt(rcb_common, i, rcb_common->desc_num);
+ (void)hns_rcb_set_port_coalesced_frames(
+ rcb_common, i, rcb_common->coalesced_frames);
+ }
+ hns_rcb_set_timeout(rcb_common, rcb_common->timeout);
+
+ dsaf_write_dev(rcb_common, RCB_COM_CFG_ENDIAN_REG,
+ HNS_RCB_COMMON_ENDIAN);
+
+ return 0;
+}
+
+int hns_rcb_buf_size2type(u32 buf_size)
+{
+ int bd_size_type;
+
+ switch (buf_size) {
+ case 512:
+ bd_size_type = HNS_BD_SIZE_512_TYPE;
+ break;
+ case 1024:
+ bd_size_type = HNS_BD_SIZE_1024_TYPE;
+ break;
+ case 2048:
+ bd_size_type = HNS_BD_SIZE_2048_TYPE;
+ break;
+ case 4096:
+ bd_size_type = HNS_BD_SIZE_4096_TYPE;
+ break;
+ default:
+ bd_size_type = -EINVAL;
+ }
+
+ return bd_size_type;
+}
+
+static void hns_rcb_ring_get_cfg(struct hnae_queue *q, int ring_type)
+{
+ struct hnae_ring *ring;
+ struct rcb_common_cb *rcb_common;
+ struct ring_pair_cb *ring_pair_cb;
+ u32 buf_size;
+ u16 desc_num;
+ int irq_idx;
+
+ ring_pair_cb = container_of(q, struct ring_pair_cb, q);
+ if (ring_type == RX_RING) {
+ ring = &q->rx_ring;
+ ring->io_base = ring_pair_cb->q.io_base;
+ irq_idx = HNS_RCB_IRQ_IDX_RX;
+ } else {
+ ring = &q->tx_ring;
+ ring->io_base = (u8 __iomem *)ring_pair_cb->q.io_base +
+ HNS_RCB_TX_REG_OFFSET;
+ irq_idx = HNS_RCB_IRQ_IDX_TX;
+ }
+
+ rcb_common = ring_pair_cb->rcb_common;
+ buf_size = rcb_common->dsaf_dev->buf_size;
+ desc_num = rcb_common->dsaf_dev->desc_num;
+
+ ring->desc = NULL;
+ ring->desc_cb = NULL;
+
+ ring->irq = ring_pair_cb->virq[irq_idx];
+ ring->desc_dma_addr = 0;
+
+ ring->buf_size = buf_size;
+ ring->desc_num = desc_num;
+ ring->max_desc_num_per_pkt = HNS_RCB_RING_MAX_BD_PER_PKT;
+ ring->max_raw_data_sz_per_desc = HNS_RCB_MAX_PKT_SIZE;
+ ring->max_pkt_size = HNS_RCB_MAX_PKT_SIZE;
+ ring->next_to_use = 0;
+ ring->next_to_clean = 0;
+}
+
+static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb *ring_pair_cb)
+{
+ ring_pair_cb->q.handle = NULL;
+
+ hns_rcb_ring_get_cfg(&ring_pair_cb->q, RX_RING);
+ hns_rcb_ring_get_cfg(&ring_pair_cb->q, TX_RING);
+}
+
+static int hns_rcb_get_port(struct rcb_common_cb *rcb_common, int ring_idx)
+{
+ int comm_index = rcb_common->comm_index;
+ int port;
+ int q_num;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
+ q_num = (int)rcb_common->max_q_per_vf * rcb_common->max_vfn;
+ port = ring_idx / q_num;
+ } else {
+ port = HNS_RCB_SERVICE_NW_ENGINE_NUM + comm_index - 1;
+ }
+
+ return port;
+}
+
+static int hns_rcb_get_base_irq_idx(struct rcb_common_cb *rcb_common)
+{
+ int comm_index = rcb_common->comm_index;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ return HNS_SERVICE_RING_IRQ_IDX;
+ else
+ return HNS_DEBUG_RING_IRQ_IDX + (comm_index - 1) * 2;
+}
+
+#define RCB_COMM_BASE_TO_RING_BASE(base, ringid)\
+ ((base) + 0x10000 + HNS_RCB_REG_OFFSET * (ringid))
+/**
+ *hns_rcb_get_cfg - get rcb config
+ *@rcb_common: rcb common device
+ */
+void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common)
+{
+ struct ring_pair_cb *ring_pair_cb;
+ u32 i;
+ u32 ring_num = rcb_common->ring_num;
+ int base_irq_idx = hns_rcb_get_base_irq_idx(rcb_common);
+ struct device_node *np = rcb_common->dsaf_dev->dev->of_node;
+
+ for (i = 0; i < ring_num; i++) {
+ ring_pair_cb = &rcb_common->ring_pair_cb[i];
+ ring_pair_cb->rcb_common = rcb_common;
+ ring_pair_cb->dev = rcb_common->dsaf_dev->dev;
+ ring_pair_cb->index = i;
+ ring_pair_cb->q.io_base =
+ RCB_COMM_BASE_TO_RING_BASE(rcb_common->io_base, i);
+ ring_pair_cb->port_id_in_dsa = hns_rcb_get_port(rcb_common, i);
+ ring_pair_cb->virq[HNS_RCB_IRQ_IDX_TX]
+ = irq_of_parse_and_map(np, base_irq_idx + i * 2);
+ ring_pair_cb->virq[HNS_RCB_IRQ_IDX_RX]
+ = irq_of_parse_and_map(np, base_irq_idx + i * 2 + 1);
+ ring_pair_cb->q.phy_base =
+ RCB_COMM_BASE_TO_RING_BASE(rcb_common->phy_base, i);
+ hns_rcb_ring_pair_get_cfg(ring_pair_cb);
+ }
+}
+
+/**
+ *hns_rcb_get_coalesced_frames - get rcb port coalesced frames
+ *@rcb_common: rcb_common device
+ *@comm_index:port index
+ *return coalesced_frames
+ */
+u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int port)
+{
+ int comm_index = hns_dsaf_get_comm_idx_by_port(port);
+ struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index];
+
+ return hns_rcb_get_port_coalesced_frames(rcb_comm, port);
+}
+
+/**
+ *hns_rcb_get_coalesce_usecs - get rcb port coalesced time_out
+ *@rcb_common: rcb_common device
+ *@comm_index:port index
+ *return time_out
+ */
+u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index)
+{
+ struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index];
+
+ return rcb_comm->timeout;
+}
+
+/**
+ *hns_rcb_set_coalesce_usecs - set rcb port coalesced time_out
+ *@rcb_common: rcb_common device
+ *@comm_index: comm :index
+ *@etx_usecs:tx time for coalesced time_out
+ *@rx_usecs:rx time for coalesced time_out
+ */
+void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev,
+ int port, u32 timeout)
+{
+ int comm_index = hns_dsaf_get_comm_idx_by_port(port);
+ struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index];
+
+ if (rcb_comm->timeout == timeout)
+ return;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
+ dev_err(dsaf_dev->dev,
+ "error: not support coalesce_usecs setting!\n");
+ return;
+ }
+ rcb_comm->timeout = timeout;
+ hns_rcb_set_timeout(rcb_comm, rcb_comm->timeout);
+}
+
+/**
+ *hns_rcb_set_coalesced_frames - set rcb coalesced frames
+ *@rcb_common: rcb_common device
+ *@tx_frames:tx BD num for coalesced frames
+ *@rx_frames:rx BD num for coalesced frames
+ *Return 0 on success, negative on failure
+ */
+int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev,
+ int port, u32 coalesced_frames)
+{
+ int comm_index = hns_dsaf_get_comm_idx_by_port(port);
+ struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index];
+ u32 coalesced_reg_val;
+ int ret;
+
+ coalesced_reg_val = hns_rcb_get_port_coalesced_frames(rcb_comm, port);
+
+ if (coalesced_reg_val == coalesced_frames)
+ return 0;
+
+ if (coalesced_frames >= HNS_RCB_MIN_COALESCED_FRAMES) {
+ ret = hns_rcb_set_port_coalesced_frames(rcb_comm, port,
+ coalesced_frames);
+ return ret;
+ } else {
+ return -EINVAL;
+ }
+}
+
+/**
+ *hns_rcb_get_queue_mode - get max VM number and max ring number per VM
+ * accordding to dsaf mode
+ *@dsaf_mode: dsaf mode
+ *@max_vfn : max vfn number
+ *@max_q_per_vf:max ring number per vm
+ */
+void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index,
+ u16 *max_vfn, u16 *max_q_per_vf)
+{
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
+ switch (dsaf_mode) {
+ case DSAF_MODE_DISABLE_6PORT_0VM:
+ *max_vfn = 1;
+ *max_q_per_vf = 16;
+ break;
+ case DSAF_MODE_DISABLE_FIX:
+ *max_vfn = 1;
+ *max_q_per_vf = 1;
+ break;
+ case DSAF_MODE_DISABLE_2PORT_64VM:
+ *max_vfn = 64;
+ *max_q_per_vf = 1;
+ break;
+ case DSAF_MODE_DISABLE_6PORT_16VM:
+ *max_vfn = 16;
+ *max_q_per_vf = 1;
+ break;
+ default:
+ *max_vfn = 1;
+ *max_q_per_vf = 16;
+ break;
+ }
+ } else {
+ *max_vfn = 1;
+ *max_q_per_vf = 1;
+ }
+}
+
+int hns_rcb_get_ring_num(struct dsaf_device *dsaf_dev, int comm_index)
+{
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
+ switch (dsaf_dev->dsaf_mode) {
+ case DSAF_MODE_ENABLE_FIX:
+ return 1;
+
+ case DSAF_MODE_DISABLE_FIX:
+ return 6;
+
+ case DSAF_MODE_ENABLE_0VM:
+ return 32;
+
+ case DSAF_MODE_DISABLE_6PORT_0VM:
+ case DSAF_MODE_ENABLE_16VM:
+ case DSAF_MODE_DISABLE_6PORT_2VM:
+ case DSAF_MODE_DISABLE_6PORT_16VM:
+ case DSAF_MODE_DISABLE_6PORT_4VM:
+ case DSAF_MODE_ENABLE_8VM:
+ return 96;
+
+ case DSAF_MODE_DISABLE_2PORT_16VM:
+ case DSAF_MODE_DISABLE_2PORT_8VM:
+ case DSAF_MODE_ENABLE_32VM:
+ case DSAF_MODE_DISABLE_2PORT_64VM:
+ case DSAF_MODE_ENABLE_128VM:
+ return 128;
+
+ default:
+ dev_warn(dsaf_dev->dev,
+ "get ring num fail,use default!dsaf_mode=%d\n",
+ dsaf_dev->dsaf_mode);
+ return 128;
+ }
+ } else {
+ return 1;
+ }
+}
+
+void __iomem *hns_rcb_common_get_vaddr(struct dsaf_device *dsaf_dev,
+ int comm_index)
+{
+ void __iomem *base_addr;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX)
+ base_addr = dsaf_dev->ppe_base + RCB_COMMON_REG_OFFSET;
+ else
+ base_addr = dsaf_dev->sds_base
+ + (comm_index - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET
+ + RCB_COMMON_REG_OFFSET;
+
+ return base_addr;
+}
+
+static phys_addr_t hns_rcb_common_get_paddr(struct dsaf_device *dsaf_dev,
+ int comm_index)
+{
+ struct device_node *np = dsaf_dev->dev->of_node;
+ phys_addr_t phy_addr;
+ const __be32 *tmp_addr;
+ u64 addr_offset = 0;
+ u64 size = 0;
+ int index = 0;
+
+ if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
+ index = 2;
+ addr_offset = RCB_COMMON_REG_OFFSET;
+ } else {
+ index = 1;
+ addr_offset = (comm_index - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET +
+ RCB_COMMON_REG_OFFSET;
+ }
+ tmp_addr = of_get_address(np, index, &size, NULL);
+ phy_addr = of_translate_address(np, tmp_addr);
+ return phy_addr + addr_offset;
+}
+
+int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev,
+ int comm_index)
+{
+ struct rcb_common_cb *rcb_common;
+ enum dsaf_mode dsaf_mode = dsaf_dev->dsaf_mode;
+ u16 max_vfn;
+ u16 max_q_per_vf;
+ int ring_num = hns_rcb_get_ring_num(dsaf_dev, comm_index);
+
+ rcb_common =
+ devm_kzalloc(dsaf_dev->dev, sizeof(*rcb_common) +
+ ring_num * sizeof(struct ring_pair_cb), GFP_KERNEL);
+ if (!rcb_common) {
+ dev_err(dsaf_dev->dev, "rcb common devm_kzalloc fail!\n");
+ return -ENOMEM;
+ }
+ rcb_common->comm_index = comm_index;
+ rcb_common->ring_num = ring_num;
+ rcb_common->dsaf_dev = dsaf_dev;
+
+ rcb_common->desc_num = dsaf_dev->desc_num;
+ rcb_common->coalesced_frames = HNS_RCB_DEF_COALESCED_FRAMES;
+ rcb_common->timeout = HNS_RCB_MAX_TIME_OUT;
+
+ hns_rcb_get_queue_mode(dsaf_mode, comm_index, &max_vfn, &max_q_per_vf);
+ rcb_common->max_vfn = max_vfn;
+ rcb_common->max_q_per_vf = max_q_per_vf;
+
+ rcb_common->io_base = hns_rcb_common_get_vaddr(dsaf_dev, comm_index);
+ rcb_common->phy_base = hns_rcb_common_get_paddr(dsaf_dev, comm_index);
+
+ dsaf_dev->rcb_common[comm_index] = rcb_common;
+ return 0;
+}
+
+void hns_rcb_common_free_cfg(struct dsaf_device *dsaf_dev,
+ u32 comm_index)
+{
+ dsaf_dev->rcb_common[comm_index] = NULL;
+}
+
+void hns_rcb_update_stats(struct hnae_queue *queue)
+{
+ struct ring_pair_cb *ring =
+ container_of(queue, struct ring_pair_cb, q);
+ struct dsaf_device *dsaf_dev = ring->rcb_common->dsaf_dev;
+ struct ppe_common_cb *ppe_common
+ = dsaf_dev->ppe_common[ring->rcb_common->comm_index];
+ struct hns_ring_hw_stats *hw_stats = &ring->hw_stats;
+
+ hw_stats->rx_pkts += dsaf_read_dev(queue,
+ RCB_RING_RX_RING_PKTNUM_RECORD_REG);
+ dsaf_write_dev(queue, RCB_RING_RX_RING_PKTNUM_RECORD_REG, 0x1);
+
+ hw_stats->ppe_rx_ok_pkts += dsaf_read_dev(ppe_common,
+ PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG + 4 * ring->index);
+ hw_stats->ppe_rx_drop_pkts += dsaf_read_dev(ppe_common,
+ PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG + 4 * ring->index);
+
+ hw_stats->tx_pkts += dsaf_read_dev(queue,
+ RCB_RING_TX_RING_PKTNUM_RECORD_REG);
+ dsaf_write_dev(queue, RCB_RING_TX_RING_PKTNUM_RECORD_REG, 0x1);
+
+ hw_stats->ppe_tx_ok_pkts += dsaf_read_dev(ppe_common,
+ PPE_COM_HIS_TX_PKT_QID_OK_CNT_REG + 4 * ring->index);
+ hw_stats->ppe_tx_drop_pkts += dsaf_read_dev(ppe_common,
+ PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG + 4 * ring->index);
+}
+
+/**
+ *hns_rcb_get_stats - get rcb statistic
+ *@ring: rcb ring
+ *@data:statistic value
+ */
+void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data)
+{
+ u64 *regs_buff = data;
+ struct ring_pair_cb *ring =
+ container_of(queue, struct ring_pair_cb, q);
+ struct hns_ring_hw_stats *hw_stats = &ring->hw_stats;
+
+ regs_buff[0] = hw_stats->tx_pkts;
+ regs_buff[1] = hw_stats->ppe_tx_ok_pkts;
+ regs_buff[2] = hw_stats->ppe_tx_drop_pkts;
+ regs_buff[3] =
+ dsaf_read_dev(queue, RCB_RING_TX_RING_FBDNUM_REG);
+
+ regs_buff[4] = queue->tx_ring.stats.tx_pkts;
+ regs_buff[5] = queue->tx_ring.stats.tx_bytes;
+ regs_buff[6] = queue->tx_ring.stats.tx_err_cnt;
+ regs_buff[7] = queue->tx_ring.stats.io_err_cnt;
+ regs_buff[8] = queue->tx_ring.stats.sw_err_cnt;
+ regs_buff[9] = queue->tx_ring.stats.seg_pkt_cnt;
+ regs_buff[10] = queue->tx_ring.stats.restart_queue;
+ regs_buff[11] = queue->tx_ring.stats.tx_busy;
+
+ regs_buff[12] = hw_stats->rx_pkts;
+ regs_buff[13] = hw_stats->ppe_rx_ok_pkts;
+ regs_buff[14] = hw_stats->ppe_rx_drop_pkts;
+ regs_buff[15] =
+ dsaf_read_dev(queue, RCB_RING_RX_RING_FBDNUM_REG);
+
+ regs_buff[16] = queue->rx_ring.stats.rx_pkts;
+ regs_buff[17] = queue->rx_ring.stats.rx_bytes;
+ regs_buff[18] = queue->rx_ring.stats.rx_err_cnt;
+ regs_buff[19] = queue->rx_ring.stats.io_err_cnt;
+ regs_buff[20] = queue->rx_ring.stats.sw_err_cnt;
+ regs_buff[21] = queue->rx_ring.stats.seg_pkt_cnt;
+ regs_buff[22] = queue->rx_ring.stats.reuse_pg_cnt;
+ regs_buff[23] = queue->rx_ring.stats.err_pkt_len;
+ regs_buff[24] = queue->rx_ring.stats.non_vld_descs;
+ regs_buff[25] = queue->rx_ring.stats.err_bd_num;
+ regs_buff[26] = queue->rx_ring.stats.l2_err;
+ regs_buff[27] = queue->rx_ring.stats.l3l4_csum_err;
+}
+
+/**
+ *hns_rcb_get_ring_sset_count - rcb string set count
+ *@stringset:ethtool cmd
+ *return rcb ring string set count
+ */
+int hns_rcb_get_ring_sset_count(int stringset)
+{
+ if (stringset == ETH_SS_STATS)
+ return HNS_RING_STATIC_REG_NUM;
+
+ return 0;
+}
+
+/**
+ *hns_rcb_get_common_regs_count - rcb common regs count
+ *return regs count
+ */
+int hns_rcb_get_common_regs_count(void)
+{
+ return HNS_RCB_COMMON_DUMP_REG_NUM;
+}
+
+/**
+ *rcb_get_sset_count - rcb ring regs count
+ *return regs count
+ */
+int hns_rcb_get_ring_regs_count(void)
+{
+ return HNS_RCB_RING_DUMP_REG_NUM;
+}
+
+/**
+ *hns_rcb_get_strings - get rcb string set
+ *@stringset:string set index
+ *@data:strings name value
+ *@index:queue index
+ */
+void hns_rcb_get_strings(int stringset, u8 *data, int index)
+{
+ char *buff = (char *)data;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_rcb_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_ppe_tx_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_ppe_drop_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_fbd_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_bytes", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_err_cnt", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_io_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_sw_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_seg_pkt", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_restart_queue", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_tx_busy", index);
+ buff = buff + ETH_GSTRING_LEN;
+
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_rcb_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_ppe_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_ppe_drop_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_fbd_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_pkt_num", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_bytes", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_err_cnt", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_io_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_sw_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_seg_pkt", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_reuse_pg", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_len_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_non_vld_desc_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_bd_num_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_l2_err", index);
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_l3l4csum_err", index);
+}
+
+void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data)
+{
+ u32 *regs = data;
+ u32 i = 0;
+
+ /*rcb common registers */
+ regs[0] = dsaf_read_dev(rcb_com, RCB_COM_CFG_ENDIAN_REG);
+ regs[1] = dsaf_read_dev(rcb_com, RCB_COM_CFG_SYS_FSH_REG);
+ regs[2] = dsaf_read_dev(rcb_com, RCB_COM_CFG_INIT_FLAG_REG);
+
+ regs[3] = dsaf_read_dev(rcb_com, RCB_COM_CFG_PKT_REG);
+ regs[4] = dsaf_read_dev(rcb_com, RCB_COM_CFG_RINVLD_REG);
+ regs[5] = dsaf_read_dev(rcb_com, RCB_COM_CFG_FNA_REG);
+ regs[6] = dsaf_read_dev(rcb_com, RCB_COM_CFG_FA_REG);
+ regs[7] = dsaf_read_dev(rcb_com, RCB_COM_CFG_PKT_TC_BP_REG);
+ regs[8] = dsaf_read_dev(rcb_com, RCB_COM_CFG_PPE_TNL_CLKEN_REG);
+
+ regs[9] = dsaf_read_dev(rcb_com, RCB_COM_INTMSK_TX_PKT_REG);
+ regs[10] = dsaf_read_dev(rcb_com, RCB_COM_RINT_TX_PKT_REG);
+ regs[11] = dsaf_read_dev(rcb_com, RCB_COM_INTMASK_ECC_ERR_REG);
+ regs[12] = dsaf_read_dev(rcb_com, RCB_COM_INTSTS_ECC_ERR_REG);
+ regs[13] = dsaf_read_dev(rcb_com, RCB_COM_EBD_SRAM_ERR_REG);
+ regs[14] = dsaf_read_dev(rcb_com, RCB_COM_RXRING_ERR_REG);
+ regs[15] = dsaf_read_dev(rcb_com, RCB_COM_TXRING_ERR_REG);
+ regs[16] = dsaf_read_dev(rcb_com, RCB_COM_TX_FBD_ERR_REG);
+ regs[17] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK_EN_REG);
+ regs[18] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK0_REG);
+ regs[19] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK1_REG);
+ regs[20] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK2_REG);
+ regs[21] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK3_REG);
+ regs[22] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK4_REG);
+ regs[23] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK5_REG);
+ regs[24] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR0_REG);
+ regs[25] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR3_REG);
+ regs[26] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR4_REG);
+ regs[27] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR5_REG);
+
+ regs[28] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_INTMASK_RING);
+ regs[29] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_RING_STS);
+ regs[30] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_RING);
+ regs[31] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_INTMASK_BD);
+ regs[32] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_BD_RINT_STS);
+ regs[33] = dsaf_read_dev(rcb_com, RCB_COM_RCB_RD_BD_BUSY);
+ regs[34] = dsaf_read_dev(rcb_com, RCB_COM_RCB_FBD_CRT_EN);
+ regs[35] = dsaf_read_dev(rcb_com, RCB_COM_AXI_WR_ERR_INTMASK);
+ regs[36] = dsaf_read_dev(rcb_com, RCB_COM_AXI_ERR_STS);
+ regs[37] = dsaf_read_dev(rcb_com, RCB_COM_CHK_TX_FBD_NUM_REG);
+
+ /* rcb common entry registers */
+ for (i = 0; i < 16; i++) { /* total 16 model registers */
+ regs[38 + i]
+ = dsaf_read_dev(rcb_com, RCB_CFG_BD_NUM_REG + 4 * i);
+ regs[54 + i]
+ = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_REG + 4 * i);
+ }
+
+ regs[70] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_REG);
+ regs[71] = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_INT_NUM_REG);
+ regs[72] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_INT_NUM_REG);
+
+ /* mark end of rcb common regs */
+ for (i = 73; i < 80; i++)
+ regs[i] = 0xcccccccc;
+}
+
+void hns_rcb_get_ring_regs(struct hnae_queue *queue, void *data)
+{
+ u32 *regs = data;
+ struct ring_pair_cb *ring_pair
+ = container_of(queue, struct ring_pair_cb, q);
+ u32 i = 0;
+
+ /*rcb ring registers */
+ regs[0] = dsaf_read_dev(queue, RCB_RING_RX_RING_BASEADDR_L_REG);
+ regs[1] = dsaf_read_dev(queue, RCB_RING_RX_RING_BASEADDR_H_REG);
+ regs[2] = dsaf_read_dev(queue, RCB_RING_RX_RING_BD_NUM_REG);
+ regs[3] = dsaf_read_dev(queue, RCB_RING_RX_RING_BD_LEN_REG);
+ regs[4] = dsaf_read_dev(queue, RCB_RING_RX_RING_PKTLINE_REG);
+ regs[5] = dsaf_read_dev(queue, RCB_RING_RX_RING_TAIL_REG);
+ regs[6] = dsaf_read_dev(queue, RCB_RING_RX_RING_HEAD_REG);
+ regs[7] = dsaf_read_dev(queue, RCB_RING_RX_RING_FBDNUM_REG);
+ regs[8] = dsaf_read_dev(queue, RCB_RING_RX_RING_PKTNUM_RECORD_REG);
+
+ regs[9] = dsaf_read_dev(queue, RCB_RING_TX_RING_BASEADDR_L_REG);
+ regs[10] = dsaf_read_dev(queue, RCB_RING_TX_RING_BASEADDR_H_REG);
+ regs[11] = dsaf_read_dev(queue, RCB_RING_TX_RING_BD_NUM_REG);
+ regs[12] = dsaf_read_dev(queue, RCB_RING_TX_RING_BD_LEN_REG);
+ regs[13] = dsaf_read_dev(queue, RCB_RING_TX_RING_PKTLINE_REG);
+ regs[15] = dsaf_read_dev(queue, RCB_RING_TX_RING_TAIL_REG);
+ regs[16] = dsaf_read_dev(queue, RCB_RING_TX_RING_HEAD_REG);
+ regs[17] = dsaf_read_dev(queue, RCB_RING_TX_RING_FBDNUM_REG);
+ regs[18] = dsaf_read_dev(queue, RCB_RING_TX_RING_OFFSET_REG);
+ regs[19] = dsaf_read_dev(queue, RCB_RING_TX_RING_PKTNUM_RECORD_REG);
+
+ regs[20] = dsaf_read_dev(queue, RCB_RING_PREFETCH_EN_REG);
+ regs[21] = dsaf_read_dev(queue, RCB_RING_CFG_VF_NUM_REG);
+ regs[22] = dsaf_read_dev(queue, RCB_RING_ASID_REG);
+ regs[23] = dsaf_read_dev(queue, RCB_RING_RX_VM_REG);
+ regs[24] = dsaf_read_dev(queue, RCB_RING_T0_BE_RST);
+ regs[25] = dsaf_read_dev(queue, RCB_RING_COULD_BE_RST);
+ regs[26] = dsaf_read_dev(queue, RCB_RING_WRR_WEIGHT_REG);
+
+ regs[27] = dsaf_read_dev(queue, RCB_RING_INTMSK_RXWL_REG);
+ regs[28] = dsaf_read_dev(queue, RCB_RING_INTSTS_RX_RING_REG);
+ regs[29] = dsaf_read_dev(queue, RCB_RING_INTMSK_TXWL_REG);
+ regs[30] = dsaf_read_dev(queue, RCB_RING_INTSTS_TX_RING_REG);
+ regs[31] = dsaf_read_dev(queue, RCB_RING_INTMSK_RX_OVERTIME_REG);
+ regs[32] = dsaf_read_dev(queue, RCB_RING_INTSTS_RX_OVERTIME_REG);
+ regs[33] = dsaf_read_dev(queue, RCB_RING_INTMSK_TX_OVERTIME_REG);
+ regs[34] = dsaf_read_dev(queue, RCB_RING_INTSTS_TX_OVERTIME_REG);
+
+ /* mark end of ring regs */
+ for (i = 35; i < 40; i++)
+ regs[i] = 0xcccccc00 + ring_pair->index;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
new file mode 100644
index 000000000000..3a2afe2dd8bb
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _HNS_DSAF_RCB_H
+#define _HNS_DSAF_RCB_H
+
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#include "hnae.h"
+#include "hns_dsaf_main.h"
+
+struct rcb_common_cb;
+
+#define HNS_RCB_IRQ_NUM_PER_QUEUE 2
+#define HNS_RCB_IRQ_IDX_TX 0
+#define HNS_RCB_IRQ_IDX_RX 1
+#define HNS_RCB_TX_REG_OFFSET 0x40
+
+#define HNS_RCB_SERVICE_NW_ENGINE_NUM DSAF_COMM_CHN
+#define HNS_RCB_DEBUG_NW_ENGINE_NUM 1
+#define HNS_RCB_RING_MAX_BD_PER_PKT 3
+#define HNS_RCB_MAX_PKT_SIZE MAC_MAX_MTU
+
+#define HNS_RCB_RING_MAX_PENDING_BD 1024
+#define HNS_RCB_RING_MIN_PENDING_BD 16
+
+#define HNS_RCB_REG_OFFSET 0x10000
+
+#define HNS_RCB_MAX_COALESCED_FRAMES 1023
+#define HNS_RCB_MIN_COALESCED_FRAMES 1
+#define HNS_RCB_DEF_COALESCED_FRAMES 50
+#define HNS_RCB_MAX_TIME_OUT 0x500
+
+#define HNS_RCB_COMMON_ENDIAN 1
+
+#define HNS_BD_SIZE_512_TYPE 0
+#define HNS_BD_SIZE_1024_TYPE 1
+#define HNS_BD_SIZE_2048_TYPE 2
+#define HNS_BD_SIZE_4096_TYPE 3
+
+#define HNS_RCB_COMMON_DUMP_REG_NUM 80
+#define HNS_RCB_RING_DUMP_REG_NUM 40
+#define HNS_RING_STATIC_REG_NUM 28
+
+#define HNS_DUMP_REG_NUM 500
+#define HNS_STATIC_REG_NUM 12
+
+enum rcb_int_flag {
+ RCB_INT_FLAG_TX = 0x1,
+ RCB_INT_FLAG_RX = (0x1 << 1),
+ RCB_INT_FLAG_MAX = (0x1 << 2), /*must be the last element */
+};
+
+struct hns_ring_hw_stats {
+ u64 tx_pkts;
+ u64 ppe_tx_ok_pkts;
+ u64 ppe_tx_drop_pkts;
+ u64 rx_pkts;
+ u64 ppe_rx_ok_pkts;
+ u64 ppe_rx_drop_pkts;
+};
+
+struct ring_pair_cb {
+ struct rcb_common_cb *rcb_common; /* ring belongs to */
+ struct device *dev; /*device for DMA mapping */
+ struct hnae_queue q;
+
+ u16 index; /* global index in a rcb common device */
+ u16 buf_size;
+
+ int virq[HNS_RCB_IRQ_NUM_PER_QUEUE];
+
+ u8 port_id_in_dsa;
+ u8 used_by_vf;
+
+ struct hns_ring_hw_stats hw_stats;
+};
+
+struct rcb_common_cb {
+ u8 __iomem *io_base;
+ phys_addr_t phy_base;
+ struct dsaf_device *dsaf_dev;
+ u16 max_vfn;
+ u16 max_q_per_vf;
+
+ u8 comm_index;
+ u32 ring_num;
+ u32 coalesced_frames; /* frames threshold of rx interrupt */
+ u32 timeout; /* time threshold of rx interrupt */
+ u32 desc_num; /* desc num per queue*/
+
+ struct ring_pair_cb ring_pair_cb[0];
+};
+
+int hns_rcb_buf_size2type(u32 buf_size);
+
+int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index);
+void hns_rcb_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index);
+int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common);
+void hns_rcb_start(struct hnae_queue *q, u32 val);
+void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common);
+void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common);
+void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index,
+ u16 *max_vfn, u16 *max_q_per_vf);
+
+void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val);
+void hns_rcb_int_clr_hw(struct hnae_queue *q, u32 flag);
+void hns_rcb_int_ctrl_hw(struct hnae_queue *q, u32 flag, u32 enable);
+void hns_rcb_init_hw(struct ring_pair_cb *ring);
+void hns_rcb_reset_ring_hw(struct hnae_queue *q);
+void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag);
+
+u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int comm_index);
+u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index);
+void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev,
+ int comm_index, u32 timeout);
+int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev,
+ int comm_index, u32 coalesce_frames);
+void hns_rcb_update_stats(struct hnae_queue *queue);
+
+void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data);
+
+void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_common, void *data);
+
+int hns_rcb_get_ring_sset_count(int stringset);
+int hns_rcb_get_common_regs_count(void);
+int hns_rcb_get_ring_regs_count(void);
+
+void hns_rcb_get_ring_regs(struct hnae_queue *queue, void *data);
+
+void hns_rcb_get_strings(int stringset, u8 *data, int index);
+#endif /* _HNS_DSAF_RCB_H */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
new file mode 100644
index 000000000000..b475e1bf2e6f
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -0,0 +1,972 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _DSAF_REG_H_
+#define _DSAF_REG_H_
+
+#define HNS_GE_FIFO_ERR_INTNUM 8
+#define HNS_XGE_ERR_INTNUM 6
+#define HNS_RCB_COMM_ERR_INTNUM 12
+#define HNS_PPE_TNL_ERR_INTNUM 8
+#define HNS_DSAF_EVENT_INTNUM 21
+#define HNS_DEBUG_RING_INTNUM 4
+#define HNS_SERVICE_RING_INTNUM 256
+
+#define HNS_DEBUG_RING_IRQ_IDX (HNS_GE_FIFO_ERR_INTNUM + HNS_XGE_ERR_INTNUM +\
+ HNS_RCB_COMM_ERR_INTNUM + HNS_PPE_TNL_ERR_INTNUM +\
+ HNS_DSAF_EVENT_INTNUM)
+#define HNS_SERVICE_RING_IRQ_IDX (HNS_DEBUG_RING_IRQ_IDX +\
+ HNS_DEBUG_RING_INTNUM)
+
+#define DSAF_IRQ_NUM 18
+
+#define DSAF_MAX_PORT_NUM_PER_CHIP 8
+#define DSAF_SERVICE_PORT_NUM_PER_DSAF 6
+#define DSAF_MAX_VM_NUM 128
+
+#define DSAF_COMM_DEV_NUM 3
+#define DSAF_PPE_INODE_BASE 6
+#define HNS_DSAF_COMM_SERVICE_NW_IDX 0
+#define DSAF_DEBUG_NW_NUM 2
+#define DSAF_SERVICE_NW_NUM 6
+#define DSAF_COMM_CHN DSAF_SERVICE_NW_NUM
+#define DSAF_GE_NUM ((DSAF_SERVICE_NW_NUM) + (DSAF_DEBUG_NW_NUM))
+#define DSAF_PORT_NUM ((DSAF_SERVICE_NW_NUM) + (DSAF_DEBUG_NW_NUM))
+#define DSAF_XGE_NUM DSAF_SERVICE_NW_NUM
+#define DSAF_NODE_NUM 18
+#define DSAF_XOD_BIG_NUM DSAF_NODE_NUM
+#define DSAF_SBM_NUM DSAF_NODE_NUM
+#define DSAF_VOQ_NUM DSAF_NODE_NUM
+#define DSAF_INODE_NUM DSAF_NODE_NUM
+#define DSAF_XOD_NUM 8
+#define DSAF_TBL_NUM 8
+#define DSAF_SW_PORT_NUM 8
+#define DSAF_TOTAL_QUEUE_NUM 129
+
+#define DSAF_TCAM_SUM 512
+#define DSAF_LINE_SUM (2048 * 14)
+
+#define DSAF_SUB_SC_NT_SRAM_CLK_SEL_REG 0x100
+#define DSAF_SUB_SC_HILINK3_CRG_CTRL0_REG 0x180
+#define DSAF_SUB_SC_HILINK3_CRG_CTRL1_REG 0x184
+#define DSAF_SUB_SC_HILINK3_CRG_CTRL2_REG 0x188
+#define DSAF_SUB_SC_HILINK3_CRG_CTRL3_REG 0x18C
+#define DSAF_SUB_SC_HILINK4_CRG_CTRL0_REG 0x190
+#define DSAF_SUB_SC_HILINK4_CRG_CTRL1_REG 0x194
+#define DSAF_SUB_SC_DSAF_CLK_EN_REG 0x300
+#define DSAF_SUB_SC_DSAF_CLK_DIS_REG 0x304
+#define DSAF_SUB_SC_NT_CLK_EN_REG 0x308
+#define DSAF_SUB_SC_NT_CLK_DIS_REG 0x30C
+#define DSAF_SUB_SC_XGE_CLK_EN_REG 0x310
+#define DSAF_SUB_SC_XGE_CLK_DIS_REG 0x314
+#define DSAF_SUB_SC_GE_CLK_EN_REG 0x318
+#define DSAF_SUB_SC_GE_CLK_DIS_REG 0x31C
+#define DSAF_SUB_SC_PPE_CLK_EN_REG 0x320
+#define DSAF_SUB_SC_PPE_CLK_DIS_REG 0x324
+#define DSAF_SUB_SC_RCB_PPE_COM_CLK_EN_REG 0x350
+#define DSAF_SUB_SC_RCB_PPE_COM_CLK_DIS_REG 0x354
+#define DSAF_SUB_SC_XBAR_RESET_REQ_REG 0xA00
+#define DSAF_SUB_SC_XBAR_RESET_DREQ_REG 0xA04
+#define DSAF_SUB_SC_NT_RESET_REQ_REG 0xA08
+#define DSAF_SUB_SC_NT_RESET_DREQ_REG 0xA0C
+#define DSAF_SUB_SC_XGE_RESET_REQ_REG 0xA10
+#define DSAF_SUB_SC_XGE_RESET_DREQ_REG 0xA14
+#define DSAF_SUB_SC_GE_RESET_REQ0_REG 0xA18
+#define DSAF_SUB_SC_GE_RESET_DREQ0_REG 0xA1C
+#define DSAF_SUB_SC_GE_RESET_REQ1_REG 0xA20
+#define DSAF_SUB_SC_GE_RESET_DREQ1_REG 0xA24
+#define DSAF_SUB_SC_PPE_RESET_REQ_REG 0xA48
+#define DSAF_SUB_SC_PPE_RESET_DREQ_REG 0xA4C
+#define DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG 0xA88
+#define DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG 0xA8C
+#define DSAF_SUB_SC_LIGHT_MODULE_DETECT_EN_REG 0x2060
+#define DSAF_SUB_SC_TCAM_MBIST_EN_REG 0x2300
+#define DSAF_SUB_SC_DSAF_CLK_ST_REG 0x5300
+#define DSAF_SUB_SC_NT_CLK_ST_REG 0x5304
+#define DSAF_SUB_SC_XGE_CLK_ST_REG 0x5308
+#define DSAF_SUB_SC_GE_CLK_ST_REG 0x530C
+#define DSAF_SUB_SC_PPE_CLK_ST_REG 0x5310
+#define DSAF_SUB_SC_ROCEE_CLK_ST_REG 0x5314
+#define DSAF_SUB_SC_CPU_CLK_ST_REG 0x5318
+#define DSAF_SUB_SC_RCB_PPE_COM_CLK_ST_REG 0x5328
+#define DSAF_SUB_SC_XBAR_RESET_ST_REG 0x5A00
+#define DSAF_SUB_SC_NT_RESET_ST_REG 0x5A04
+#define DSAF_SUB_SC_XGE_RESET_ST_REG 0x5A08
+#define DSAF_SUB_SC_GE_RESET_ST0_REG 0x5A0C
+#define DSAF_SUB_SC_GE_RESET_ST1_REG 0x5A10
+#define DSAF_SUB_SC_PPE_RESET_ST_REG 0x5A24
+#define DSAF_SUB_SC_RCB_PPE_COM_RESET_ST_REG 0x5A44
+
+/*serdes offset**/
+#define HNS_MAC_HILINK3_REG DSAF_SUB_SC_HILINK3_CRG_CTRL0_REG
+#define HNS_MAC_HILINK4_REG DSAF_SUB_SC_HILINK4_CRG_CTRL0_REG
+#define HNS_MAC_LANE0_CTLEDFE_REG 0x000BFFCCULL
+#define HNS_MAC_LANE1_CTLEDFE_REG 0x000BFFBCULL
+#define HNS_MAC_LANE2_CTLEDFE_REG 0x000BFFACULL
+#define HNS_MAC_LANE3_CTLEDFE_REG 0x000BFF9CULL
+#define HNS_MAC_LANE0_STATE_REG 0x000BFFD4ULL
+#define HNS_MAC_LANE1_STATE_REG 0x000BFFC4ULL
+#define HNS_MAC_LANE2_STATE_REG 0x000BFFB4ULL
+#define HNS_MAC_LANE3_STATE_REG 0x000BFFA4ULL
+
+#define HILINK_RESET_TIMOUT 10000
+
+#define DSAF_SRAM_INIT_OVER_0_REG 0x0
+#define DSAF_CFG_0_REG 0x4
+#define DSAF_ECC_ERR_INVERT_0_REG 0x8
+#define DSAF_ABNORMAL_TIMEOUT_0_REG 0x1C
+#define DSAF_FSM_TIMEOUT_0_REG 0x20
+#define DSAF_DSA_REG_CNT_CLR_CE_REG 0x2C
+#define DSAF_DSA_SBM_INF_FIFO_THRD_REG 0x30
+#define DSAF_DSA_SRAM_1BIT_ECC_SEL_REG 0x34
+#define DSAF_DSA_SRAM_1BIT_ECC_CNT_REG 0x38
+#define DSAF_PFC_EN_0_REG 0x50
+#define DSAF_PFC_UNIT_CNT_0_REG 0x70
+#define DSAF_XGE_INT_MSK_0_REG 0x100
+#define DSAF_PPE_INT_MSK_0_REG 0x120
+#define DSAF_ROCEE_INT_MSK_0_REG 0x140
+#define DSAF_XGE_INT_SRC_0_REG 0x160
+#define DSAF_PPE_INT_SRC_0_REG 0x180
+#define DSAF_ROCEE_INT_SRC_0_REG 0x1A0
+#define DSAF_XGE_INT_STS_0_REG 0x1C0
+#define DSAF_PPE_INT_STS_0_REG 0x1E0
+#define DSAF_ROCEE_INT_STS_0_REG 0x200
+#define DSAF_PPE_QID_CFG_0_REG 0x300
+#define DSAF_SW_PORT_TYPE_0_REG 0x320
+#define DSAF_STP_PORT_TYPE_0_REG 0x340
+#define DSAF_MIX_DEF_QID_0_REG 0x360
+#define DSAF_PORT_DEF_VLAN_0_REG 0x380
+#define DSAF_VM_DEF_VLAN_0_REG 0x400
+
+#define DSAF_INODE_CUT_THROUGH_CFG_0_REG 0x1000
+#define DSAF_INODE_ECC_INVERT_EN_0_REG 0x1008
+#define DSAF_INODE_ECC_ERR_ADDR_0_REG 0x100C
+#define DSAF_INODE_IN_PORT_NUM_0_REG 0x1018
+#define DSAF_INODE_PRI_TC_CFG_0_REG 0x101C
+#define DSAF_INODE_BP_STATUS_0_REG 0x1020
+#define DSAF_INODE_PAD_DISCARD_NUM_0_REG 0x1028
+#define DSAF_INODE_FINAL_IN_MAN_NUM_0_REG 0x102C
+#define DSAF_INODE_FINAL_IN_PKT_NUM_0_REG 0x1030
+#define DSAF_INODE_SBM_PID_NUM_0_REG 0x1038
+#define DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG 0x103C
+#define DSAF_INODE_SBM_RELS_NUM_0_REG 0x104C
+#define DSAF_INODE_SBM_DROP_NUM_0_REG 0x1050
+#define DSAF_INODE_CRC_FALSE_NUM_0_REG 0x1054
+#define DSAF_INODE_BP_DISCARD_NUM_0_REG 0x1058
+#define DSAF_INODE_RSLT_DISCARD_NUM_0_REG 0x105C
+#define DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG 0x1060
+#define DSAF_INODE_VOQ_OVER_NUM_0_REG 0x1068
+#define DSAF_INODE_BD_SAVE_STATUS_0_REG 0x1900
+#define DSAF_INODE_BD_ORDER_STATUS_0_REG 0x1950
+#define DSAF_INODE_SW_VLAN_TAG_DISC_0_REG 0x1A00
+#define DSAF_INODE_IN_DATA_STP_DISC_0_REG 0x1A50
+#define DSAF_INODE_GE_FC_EN_0_REG 0x1B00
+#define DSAF_INODE_VC0_IN_PKT_NUM_0_REG 0x1B50
+#define DSAF_INODE_VC1_IN_PKT_NUM_0_REG 0x1C00
+
+#define DSAF_SBM_CFG_REG_0_REG 0x2000
+#define DSAF_SBM_BP_CFG_0_XGE_REG_0_REG 0x2004
+#define DSAF_SBM_BP_CFG_0_PPE_REG_0_REG 0x2304
+#define DSAF_SBM_BP_CFG_0_ROCEE_REG_0_REG 0x2604
+#define DSAF_SBM_BP_CFG_1_REG_0_REG 0x2008
+#define DSAF_SBM_BP_CFG_2_XGE_REG_0_REG 0x200C
+#define DSAF_SBM_BP_CFG_2_PPE_REG_0_REG 0x230C
+#define DSAF_SBM_BP_CFG_2_ROCEE_REG_0_REG 0x260C
+#define DSAF_SBM_FREE_CNT_0_0_REG 0x2010
+#define DSAF_SBM_FREE_CNT_1_0_REG 0x2014
+#define DSAF_SBM_BP_CNT_0_0_REG 0x2018
+#define DSAF_SBM_BP_CNT_1_0_REG 0x201C
+#define DSAF_SBM_BP_CNT_2_0_REG 0x2020
+#define DSAF_SBM_BP_CNT_3_0_REG 0x2024
+#define DSAF_SBM_INER_ST_0_REG 0x2028
+#define DSAF_SBM_MIB_REQ_FAILED_TC_0_REG 0x202C
+#define DSAF_SBM_LNK_INPORT_CNT_0_REG 0x2030
+#define DSAF_SBM_LNK_DROP_CNT_0_REG 0x2034
+#define DSAF_SBM_INF_OUTPORT_CNT_0_REG 0x2038
+#define DSAF_SBM_LNK_INPORT_TC0_CNT_0_REG 0x203C
+#define DSAF_SBM_LNK_INPORT_TC1_CNT_0_REG 0x2040
+#define DSAF_SBM_LNK_INPORT_TC2_CNT_0_REG 0x2044
+#define DSAF_SBM_LNK_INPORT_TC3_CNT_0_REG 0x2048
+#define DSAF_SBM_LNK_INPORT_TC4_CNT_0_REG 0x204C
+#define DSAF_SBM_LNK_INPORT_TC5_CNT_0_REG 0x2050
+#define DSAF_SBM_LNK_INPORT_TC6_CNT_0_REG 0x2054
+#define DSAF_SBM_LNK_INPORT_TC7_CNT_0_REG 0x2058
+#define DSAF_SBM_LNK_REQ_CNT_0_REG 0x205C
+#define DSAF_SBM_LNK_RELS_CNT_0_REG 0x2060
+#define DSAF_SBM_BP_CFG_3_REG_0_REG 0x2068
+#define DSAF_SBM_BP_CFG_4_REG_0_REG 0x206C
+
+#define DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG 0x3000
+#define DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG 0x3004
+#define DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG 0x3008
+#define DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG 0x300C
+#define DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG 0x3010
+#define DSAF_XOD_ETS_TOKEN_CFG_0_REG 0x3014
+#define DSAF_XOD_PFS_CFG_0_0_REG 0x3018
+#define DSAF_XOD_PFS_CFG_1_0_REG 0x301C
+#define DSAF_XOD_PFS_CFG_2_0_REG 0x3020
+#define DSAF_XOD_GNT_L_0_REG 0x3024
+#define DSAF_XOD_GNT_H_0_REG 0x3028
+#define DSAF_XOD_CONNECT_STATE_0_REG 0x302C
+#define DSAF_XOD_RCVPKT_CNT_0_REG 0x3030
+#define DSAF_XOD_RCVTC0_CNT_0_REG 0x3034
+#define DSAF_XOD_RCVTC1_CNT_0_REG 0x3038
+#define DSAF_XOD_RCVTC2_CNT_0_REG 0x303C
+#define DSAF_XOD_RCVTC3_CNT_0_REG 0x3040
+#define DSAF_XOD_RCVVC0_CNT_0_REG 0x3044
+#define DSAF_XOD_RCVVC1_CNT_0_REG 0x3048
+#define DSAF_XOD_XGE_RCVIN0_CNT_0_REG 0x304C
+#define DSAF_XOD_XGE_RCVIN1_CNT_0_REG 0x3050
+#define DSAF_XOD_XGE_RCVIN2_CNT_0_REG 0x3054
+#define DSAF_XOD_XGE_RCVIN3_CNT_0_REG 0x3058
+#define DSAF_XOD_XGE_RCVIN4_CNT_0_REG 0x305C
+#define DSAF_XOD_XGE_RCVIN5_CNT_0_REG 0x3060
+#define DSAF_XOD_XGE_RCVIN6_CNT_0_REG 0x3064
+#define DSAF_XOD_XGE_RCVIN7_CNT_0_REG 0x3068
+#define DSAF_XOD_PPE_RCVIN0_CNT_0_REG 0x306C
+#define DSAF_XOD_PPE_RCVIN1_CNT_0_REG 0x3070
+#define DSAF_XOD_ROCEE_RCVIN0_CNT_0_REG 0x3074
+#define DSAF_XOD_ROCEE_RCVIN1_CNT_0_REG 0x3078
+#define DSAF_XOD_FIFO_STATUS_0_REG 0x307C
+
+#define DSAF_VOQ_ECC_INVERT_EN_0_REG 0x4004
+#define DSAF_VOQ_SRAM_PKT_NUM_0_REG 0x4008
+#define DSAF_VOQ_IN_PKT_NUM_0_REG 0x400C
+#define DSAF_VOQ_OUT_PKT_NUM_0_REG 0x4010
+#define DSAF_VOQ_ECC_ERR_ADDR_0_REG 0x4014
+#define DSAF_VOQ_BP_STATUS_0_REG 0x4018
+#define DSAF_VOQ_SPUP_IDLE_0_REG 0x401C
+#define DSAF_VOQ_XGE_XOD_REQ_0_0_REG 0x4024
+#define DSAF_VOQ_XGE_XOD_REQ_1_0_REG 0x4028
+#define DSAF_VOQ_PPE_XOD_REQ_0_REG 0x402C
+#define DSAF_VOQ_ROCEE_XOD_REQ_0_REG 0x4030
+#define DSAF_VOQ_BP_ALL_THRD_0_REG 0x4034
+
+#define DSAF_TBL_CTRL_0_REG 0x5000
+#define DSAF_TBL_INT_MSK_0_REG 0x5004
+#define DSAF_TBL_INT_SRC_0_REG 0x5008
+#define DSAF_TBL_INT_STS_0_REG 0x5100
+#define DSAF_TBL_TCAM_ADDR_0_REG 0x500C
+#define DSAF_TBL_LINE_ADDR_0_REG 0x5010
+#define DSAF_TBL_TCAM_HIGH_0_REG 0x5014
+#define DSAF_TBL_TCAM_LOW_0_REG 0x5018
+#define DSAF_TBL_TCAM_MCAST_CFG_4_0_REG 0x501C
+#define DSAF_TBL_TCAM_MCAST_CFG_3_0_REG 0x5020
+#define DSAF_TBL_TCAM_MCAST_CFG_2_0_REG 0x5024
+#define DSAF_TBL_TCAM_MCAST_CFG_1_0_REG 0x5028
+#define DSAF_TBL_TCAM_MCAST_CFG_0_0_REG 0x502C
+#define DSAF_TBL_TCAM_UCAST_CFG_0_REG 0x5030
+#define DSAF_TBL_LIN_CFG_0_REG 0x5034
+#define DSAF_TBL_TCAM_RDATA_HIGH_0_REG 0x5038
+#define DSAF_TBL_TCAM_RDATA_LOW_0_REG 0x503C
+#define DSAF_TBL_TCAM_RAM_RDATA4_0_REG 0x5040
+#define DSAF_TBL_TCAM_RAM_RDATA3_0_REG 0x5044
+#define DSAF_TBL_TCAM_RAM_RDATA2_0_REG 0x5048
+#define DSAF_TBL_TCAM_RAM_RDATA1_0_REG 0x504C
+#define DSAF_TBL_TCAM_RAM_RDATA0_0_REG 0x5050
+#define DSAF_TBL_LIN_RDATA_0_REG 0x5054
+#define DSAF_TBL_DA0_MIS_INFO1_0_REG 0x5058
+#define DSAF_TBL_DA0_MIS_INFO0_0_REG 0x505C
+#define DSAF_TBL_SA_MIS_INFO2_0_REG 0x5104
+#define DSAF_TBL_SA_MIS_INFO1_0_REG 0x5098
+#define DSAF_TBL_SA_MIS_INFO0_0_REG 0x509C
+#define DSAF_TBL_PUL_0_REG 0x50A0
+#define DSAF_TBL_OLD_RSLT_0_REG 0x50A4
+#define DSAF_TBL_OLD_SCAN_VAL_0_REG 0x50A8
+#define DSAF_TBL_DFX_CTRL_0_REG 0x50AC
+#define DSAF_TBL_DFX_STAT_0_REG 0x50B0
+#define DSAF_TBL_DFX_STAT_2_0_REG 0x5108
+#define DSAF_TBL_LKUP_NUM_I_0_REG 0x50C0
+#define DSAF_TBL_LKUP_NUM_O_0_REG 0x50E0
+#define DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG 0x510C
+
+#define DSAF_INODE_FIFO_WL_0_REG 0x6000
+#define DSAF_ONODE_FIFO_WL_0_REG 0x6020
+#define DSAF_XGE_GE_WORK_MODE_0_REG 0x6040
+#define DSAF_XGE_APP_RX_LINK_UP_0_REG 0x6080
+#define DSAF_NETPORT_CTRL_SIG_0_REG 0x60A0
+#define DSAF_XGE_CTRL_SIG_CFG_0_REG 0x60C0
+
+#define PPE_COM_CFG_QID_MODE_REG 0x0
+#define PPE_COM_INTEN_REG 0x110
+#define PPE_COM_RINT_REG 0x114
+#define PPE_COM_INTSTS_REG 0x118
+#define PPE_COM_COMMON_CNT_CLR_CE_REG 0x1120
+#define PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG 0x300
+#define PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG 0x600
+#define PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG 0x900
+#define PPE_COM_HIS_TX_PKT_QID_OK_CNT_REG 0xC00
+#define PPE_COM_COMMON_CNT_CLR_CE_REG 0x1120
+
+#define PPE_CFG_TX_FIFO_THRSLD_REG 0x0
+#define PPE_CFG_RX_FIFO_THRSLD_REG 0x4
+#define PPE_CFG_RX_FIFO_PAUSE_THRSLD_REG 0x8
+#define PPE_CFG_RX_FIFO_SW_BP_THRSLD_REG 0xC
+#define PPE_CFG_PAUSE_IDLE_CNT_REG 0x10
+#define PPE_CFG_BUS_CTRL_REG 0x40
+#define PPE_CFG_TNL_TO_BE_RST_REG 0x48
+#define PPE_CURR_TNL_CAN_RST_REG 0x4C
+#define PPE_CFG_XGE_MODE_REG 0x80
+#define PPE_CFG_MAX_FRAME_LEN_REG 0x84
+#define PPE_CFG_RX_PKT_MODE_REG 0x88
+#define PPE_CFG_RX_VLAN_TAG_REG 0x8C
+#define PPE_CFG_TAG_GEN_REG 0x90
+#define PPE_CFG_PARSE_TAG_REG 0x94
+#define PPE_CFG_PRO_CHECK_EN_REG 0x98
+#define PPE_INTEN_REG 0x100
+#define PPE_RINT_REG 0x104
+#define PPE_INTSTS_REG 0x108
+#define PPE_CFG_RX_PKT_INT_REG 0x140
+#define PPE_CFG_HEAT_DECT_TIME0_REG 0x144
+#define PPE_CFG_HEAT_DECT_TIME1_REG 0x148
+#define PPE_HIS_RX_SW_PKT_CNT_REG 0x200
+#define PPE_HIS_RX_WR_BD_OK_PKT_CNT_REG 0x204
+#define PPE_HIS_RX_PKT_NO_BUF_CNT_REG 0x208
+#define PPE_HIS_TX_BD_CNT_REG 0x20C
+#define PPE_HIS_TX_PKT_CNT_REG 0x210
+#define PPE_HIS_TX_PKT_OK_CNT_REG 0x214
+#define PPE_HIS_TX_PKT_EPT_CNT_REG 0x218
+#define PPE_HIS_TX_PKT_CS_FAIL_CNT_REG 0x21C
+#define PPE_HIS_RX_APP_BUF_FAIL_CNT_REG 0x220
+#define PPE_HIS_RX_APP_BUF_WAIT_CNT_REG 0x224
+#define PPE_HIS_RX_PKT_DROP_FUL_CNT_REG 0x228
+#define PPE_HIS_RX_PKT_DROP_PRT_CNT_REG 0x22C
+#define PPE_TNL_0_5_CNT_CLR_CE_REG 0x300
+#define PPE_CFG_AXI_DBG_REG 0x304
+#define PPE_HIS_PRO_ERR_REG 0x308
+#define PPE_HIS_TNL_FIFO_ERR_REG 0x30C
+#define PPE_CURR_CFF_DATA_NUM_REG 0x310
+#define PPE_CURR_RX_ST_REG 0x314
+#define PPE_CURR_TX_ST_REG 0x318
+#define PPE_CURR_RX_FIFO0_REG 0x31C
+#define PPE_CURR_RX_FIFO1_REG 0x320
+#define PPE_CURR_TX_FIFO0_REG 0x324
+#define PPE_CURR_TX_FIFO1_REG 0x328
+#define PPE_ECO0_REG 0x32C
+#define PPE_ECO1_REG 0x330
+#define PPE_ECO2_REG 0x334
+
+#define RCB_COM_CFG_ENDIAN_REG 0x0
+#define RCB_COM_CFG_SYS_FSH_REG 0xC
+#define RCB_COM_CFG_INIT_FLAG_REG 0x10
+#define RCB_COM_CFG_PKT_REG 0x30
+#define RCB_COM_CFG_RINVLD_REG 0x34
+#define RCB_COM_CFG_FNA_REG 0x38
+#define RCB_COM_CFG_FA_REG 0x3C
+#define RCB_COM_CFG_PKT_TC_BP_REG 0x40
+#define RCB_COM_CFG_PPE_TNL_CLKEN_REG 0x44
+
+#define RCB_COM_INTMSK_TX_PKT_REG 0x3A0
+#define RCB_COM_RINT_TX_PKT_REG 0x3A8
+#define RCB_COM_INTMASK_ECC_ERR_REG 0x400
+#define RCB_COM_INTSTS_ECC_ERR_REG 0x408
+#define RCB_COM_EBD_SRAM_ERR_REG 0x410
+#define RCB_COM_RXRING_ERR_REG 0x41C
+#define RCB_COM_TXRING_ERR_REG 0x420
+#define RCB_COM_TX_FBD_ERR_REG 0x424
+#define RCB_SRAM_ECC_CHK_EN_REG 0x428
+#define RCB_SRAM_ECC_CHK0_REG 0x42C
+#define RCB_SRAM_ECC_CHK1_REG 0x430
+#define RCB_SRAM_ECC_CHK2_REG 0x434
+#define RCB_SRAM_ECC_CHK3_REG 0x438
+#define RCB_SRAM_ECC_CHK4_REG 0x43c
+#define RCB_SRAM_ECC_CHK5_REG 0x440
+#define RCB_ECC_ERR_ADDR0_REG 0x450
+#define RCB_ECC_ERR_ADDR3_REG 0x45C
+#define RCB_ECC_ERR_ADDR4_REG 0x460
+#define RCB_ECC_ERR_ADDR5_REG 0x464
+
+#define RCB_COM_SF_CFG_INTMASK_RING 0x480
+#define RCB_COM_SF_CFG_RING_STS 0x484
+#define RCB_COM_SF_CFG_RING 0x488
+#define RCB_COM_SF_CFG_INTMASK_BD 0x48C
+#define RCB_COM_SF_CFG_BD_RINT_STS 0x470
+#define RCB_COM_RCB_RD_BD_BUSY 0x490
+#define RCB_COM_RCB_FBD_CRT_EN 0x494
+#define RCB_COM_AXI_WR_ERR_INTMASK 0x498
+#define RCB_COM_AXI_ERR_STS 0x49C
+#define RCB_COM_CHK_TX_FBD_NUM_REG 0x4a0
+
+#define RCB_CFG_BD_NUM_REG 0x9000
+#define RCB_CFG_PKTLINE_REG 0x9050
+
+#define RCB_CFG_OVERTIME_REG 0x9300
+#define RCB_CFG_PKTLINE_INT_NUM_REG 0x9304
+#define RCB_CFG_OVERTIME_INT_NUM_REG 0x9308
+
+#define RCB_RING_RX_RING_BASEADDR_L_REG 0x00000
+#define RCB_RING_RX_RING_BASEADDR_H_REG 0x00004
+#define RCB_RING_RX_RING_BD_NUM_REG 0x00008
+#define RCB_RING_RX_RING_BD_LEN_REG 0x0000C
+#define RCB_RING_RX_RING_PKTLINE_REG 0x00010
+#define RCB_RING_RX_RING_TAIL_REG 0x00018
+#define RCB_RING_RX_RING_HEAD_REG 0x0001C
+#define RCB_RING_RX_RING_FBDNUM_REG 0x00020
+#define RCB_RING_RX_RING_PKTNUM_RECORD_REG 0x0002C
+
+#define RCB_RING_TX_RING_BASEADDR_L_REG 0x00040
+#define RCB_RING_TX_RING_BASEADDR_H_REG 0x00044
+#define RCB_RING_TX_RING_BD_NUM_REG 0x00048
+#define RCB_RING_TX_RING_BD_LEN_REG 0x0004C
+#define RCB_RING_TX_RING_PKTLINE_REG 0x00050
+#define RCB_RING_TX_RING_TAIL_REG 0x00058
+#define RCB_RING_TX_RING_HEAD_REG 0x0005C
+#define RCB_RING_TX_RING_FBDNUM_REG 0x00060
+#define RCB_RING_TX_RING_OFFSET_REG 0x00064
+#define RCB_RING_TX_RING_PKTNUM_RECORD_REG 0x0006C
+
+#define RCB_RING_PREFETCH_EN_REG 0x0007C
+#define RCB_RING_CFG_VF_NUM_REG 0x00080
+#define RCB_RING_ASID_REG 0x0008C
+#define RCB_RING_RX_VM_REG 0x00090
+#define RCB_RING_T0_BE_RST 0x00094
+#define RCB_RING_COULD_BE_RST 0x00098
+#define RCB_RING_WRR_WEIGHT_REG 0x0009c
+
+#define RCB_RING_INTMSK_RXWL_REG 0x000A0
+#define RCB_RING_INTSTS_RX_RING_REG 0x000A4
+#define RCB_RING_INTMSK_TXWL_REG 0x000AC
+#define RCB_RING_INTSTS_TX_RING_REG 0x000B0
+#define RCB_RING_INTMSK_RX_OVERTIME_REG 0x000B8
+#define RCB_RING_INTSTS_RX_OVERTIME_REG 0x000BC
+#define RCB_RING_INTMSK_TX_OVERTIME_REG 0x000C4
+#define RCB_RING_INTSTS_TX_OVERTIME_REG 0x000C8
+
+#define GMAC_DUPLEX_TYPE_REG 0x0008UL
+#define GMAC_FD_FC_TYPE_REG 0x000CUL
+#define GMAC_FC_TX_TIMER_REG 0x001CUL
+#define GMAC_FD_FC_ADDR_LOW_REG 0x0020UL
+#define GMAC_FD_FC_ADDR_HIGH_REG 0x0024UL
+#define GMAC_IPG_TX_TIMER_REG 0x0030UL
+#define GMAC_PAUSE_THR_REG 0x0038UL
+#define GMAC_MAX_FRM_SIZE_REG 0x003CUL
+#define GMAC_PORT_MODE_REG 0x0040UL
+#define GMAC_PORT_EN_REG 0x0044UL
+#define GMAC_PAUSE_EN_REG 0x0048UL
+#define GMAC_SHORT_RUNTS_THR_REG 0x0050UL
+#define GMAC_AN_NEG_STATE_REG 0x0058UL
+#define GMAC_TX_LOCAL_PAGE_REG 0x005CUL
+#define GMAC_TRANSMIT_CONTROL_REG 0x0060UL
+#define GMAC_REC_FILT_CONTROL_REG 0x0064UL
+#define GMAC_PTP_CONFIG_REG 0x0074UL
+
+#define GMAC_RX_OCTETS_TOTAL_OK_REG 0x0080UL
+#define GMAC_RX_OCTETS_BAD_REG 0x0084UL
+#define GMAC_RX_UC_PKTS_REG 0x0088UL
+#define GMAC_RX_MC_PKTS_REG 0x008CUL
+#define GMAC_RX_BC_PKTS_REG 0x0090UL
+#define GMAC_RX_PKTS_64OCTETS_REG 0x0094UL
+#define GMAC_RX_PKTS_65TO127OCTETS_REG 0x0098UL
+#define GMAC_RX_PKTS_128TO255OCTETS_REG 0x009CUL
+#define GMAC_RX_PKTS_255TO511OCTETS_REG 0x00A0UL
+#define GMAC_RX_PKTS_512TO1023OCTETS_REG 0x00A4UL
+#define GMAC_RX_PKTS_1024TO1518OCTETS_REG 0x00A8UL
+#define GMAC_RX_PKTS_1519TOMAXOCTETS_REG 0x00ACUL
+#define GMAC_RX_FCS_ERRORS_REG 0x00B0UL
+#define GMAC_RX_TAGGED_REG 0x00B4UL
+#define GMAC_RX_DATA_ERR_REG 0x00B8UL
+#define GMAC_RX_ALIGN_ERRORS_REG 0x00BCUL
+#define GMAC_RX_LONG_ERRORS_REG 0x00C0UL
+#define GMAC_RX_JABBER_ERRORS_REG 0x00C4UL
+#define GMAC_RX_PAUSE_MACCTRL_FRAM_REG 0x00C8UL
+#define GMAC_RX_UNKNOWN_MACCTRL_FRAM_REG 0x00CCUL
+#define GMAC_RX_VERY_LONG_ERR_CNT_REG 0x00D0UL
+#define GMAC_RX_RUNT_ERR_CNT_REG 0x00D4UL
+#define GMAC_RX_SHORT_ERR_CNT_REG 0x00D8UL
+#define GMAC_RX_FILT_PKT_CNT_REG 0x00E8UL
+#define GMAC_RX_OCTETS_TOTAL_FILT_REG 0x00ECUL
+#define GMAC_OCTETS_TRANSMITTED_OK_REG 0x0100UL
+#define GMAC_OCTETS_TRANSMITTED_BAD_REG 0x0104UL
+#define GMAC_TX_UC_PKTS_REG 0x0108UL
+#define GMAC_TX_MC_PKTS_REG 0x010CUL
+#define GMAC_TX_BC_PKTS_REG 0x0110UL
+#define GMAC_TX_PKTS_64OCTETS_REG 0x0114UL
+#define GMAC_TX_PKTS_65TO127OCTETS_REG 0x0118UL
+#define GMAC_TX_PKTS_128TO255OCTETS_REG 0x011CUL
+#define GMAC_TX_PKTS_255TO511OCTETS_REG 0x0120UL
+#define GMAC_TX_PKTS_512TO1023OCTETS_REG 0x0124UL
+#define GMAC_TX_PKTS_1024TO1518OCTETS_REG 0x0128UL
+#define GMAC_TX_PKTS_1519TOMAXOCTETS_REG 0x012CUL
+#define GMAC_TX_EXCESSIVE_LENGTH_DROP_REG 0x014CUL
+#define GMAC_TX_UNDERRUN_REG 0x0150UL
+#define GMAC_TX_TAGGED_REG 0x0154UL
+#define GMAC_TX_CRC_ERROR_REG 0x0158UL
+#define GMAC_TX_PAUSE_FRAMES_REG 0x015CUL
+#define GAMC_RX_MAX_FRAME 0x0170UL
+#define GMAC_LINE_LOOP_BACK_REG 0x01A8UL
+#define GMAC_CF_CRC_STRIP_REG 0x01B0UL
+#define GMAC_MODE_CHANGE_EN_REG 0x01B4UL
+#define GMAC_SIXTEEN_BIT_CNTR_REG 0x01CCUL
+#define GMAC_LD_LINK_COUNTER_REG 0x01D0UL
+#define GMAC_LOOP_REG 0x01DCUL
+#define GMAC_RECV_CONTROL_REG 0x01E0UL
+#define GMAC_VLAN_CODE_REG 0x01E8UL
+#define GMAC_RX_OVERRUN_CNT_REG 0x01ECUL
+#define GMAC_RX_LENGTHFIELD_ERR_CNT_REG 0x01F4UL
+#define GMAC_RX_FAIL_COMMA_CNT_REG 0x01F8UL
+#define GMAC_STATION_ADDR_LOW_0_REG 0x0200UL
+#define GMAC_STATION_ADDR_HIGH_0_REG 0x0204UL
+#define GMAC_STATION_ADDR_LOW_1_REG 0x0208UL
+#define GMAC_STATION_ADDR_HIGH_1_REG 0x020CUL
+#define GMAC_STATION_ADDR_LOW_2_REG 0x0210UL
+#define GMAC_STATION_ADDR_HIGH_2_REG 0x0214UL
+#define GMAC_STATION_ADDR_LOW_3_REG 0x0218UL
+#define GMAC_STATION_ADDR_HIGH_3_REG 0x021CUL
+#define GMAC_STATION_ADDR_LOW_4_REG 0x0220UL
+#define GMAC_STATION_ADDR_HIGH_4_REG 0x0224UL
+#define GMAC_STATION_ADDR_LOW_5_REG 0x0228UL
+#define GMAC_STATION_ADDR_HIGH_5_REG 0x022CUL
+#define GMAC_STATION_ADDR_LOW_MSK_0_REG 0x0230UL
+#define GMAC_STATION_ADDR_HIGH_MSK_0_REG 0x0234UL
+#define GMAC_STATION_ADDR_LOW_MSK_1_REG 0x0238UL
+#define GMAC_STATION_ADDR_HIGH_MSK_1_REG 0x023CUL
+#define GMAC_MAC_SKIP_LEN_REG 0x0240UL
+#define GMAC_TX_LOOP_PKT_PRI_REG 0x0378UL
+
+#define XGMAC_INT_STATUS_REG 0x0
+#define XGMAC_INT_ENABLE_REG 0x4
+#define XGMAC_INT_SET_REG 0x8
+#define XGMAC_IERR_U_INFO_REG 0xC
+#define XGMAC_OVF_INFO_REG 0x10
+#define XGMAC_OVF_CNT_REG 0x14
+#define XGMAC_PORT_MODE_REG 0x40
+#define XGMAC_CLK_ENABLE_REG 0x44
+#define XGMAC_RESET_REG 0x48
+#define XGMAC_LINK_CONTROL_REG 0x50
+#define XGMAC_LINK_STATUS_REG 0x54
+#define XGMAC_SPARE_REG 0xC0
+#define XGMAC_SPARE_CNT_REG 0xC4
+
+#define XGMAC_MAC_ENABLE_REG 0x100
+#define XGMAC_MAC_CONTROL_REG 0x104
+#define XGMAC_MAC_IPG_REG 0x120
+#define XGMAC_MAC_MSG_CRC_EN_REG 0x124
+#define XGMAC_MAC_MSG_IMG_REG 0x128
+#define XGMAC_MAC_MSG_FC_CFG_REG 0x12C
+#define XGMAC_MAC_MSG_TC_CFG_REG 0x130
+#define XGMAC_MAC_PAD_SIZE_REG 0x134
+#define XGMAC_MAC_MIN_PKT_SIZE_REG 0x138
+#define XGMAC_MAC_MAX_PKT_SIZE_REG 0x13C
+#define XGMAC_MAC_PAUSE_CTRL_REG 0x160
+#define XGMAC_MAC_PAUSE_TIME_REG 0x164
+#define XGMAC_MAC_PAUSE_GAP_REG 0x168
+#define XGMAC_MAC_PAUSE_LOCAL_MAC_H_REG 0x16C
+#define XGMAC_MAC_PAUSE_LOCAL_MAC_L_REG 0x170
+#define XGMAC_MAC_PAUSE_PEER_MAC_H_REG 0x174
+#define XGMAC_MAC_PAUSE_PEER_MAC_L_REG 0x178
+#define XGMAC_MAC_PFC_PRI_EN_REG 0x17C
+#define XGMAC_MAC_1588_CTRL_REG 0x180
+#define XGMAC_MAC_1588_TX_PORT_DLY_REG 0x184
+#define XGMAC_MAC_1588_RX_PORT_DLY_REG 0x188
+#define XGMAC_MAC_1588_ASYM_DLY_REG 0x18C
+#define XGMAC_MAC_1588_ADJUST_CFG_REG 0x190
+#define XGMAC_MAC_Y1731_ETH_TYPE_REG 0x194
+#define XGMAC_MAC_MIB_CONTROL_REG 0x198
+#define XGMAC_MAC_WAN_RATE_ADJUST_REG 0x19C
+#define XGMAC_MAC_TX_ERR_MARK_REG 0x1A0
+#define XGMAC_MAC_TX_LF_RF_CONTROL_REG 0x1A4
+#define XGMAC_MAC_RX_LF_RF_STATUS_REG 0x1A8
+#define XGMAC_MAC_TX_RUNT_PKT_CNT_REG 0x1C0
+#define XGMAC_MAC_RX_RUNT_PKT_CNT_REG 0x1C4
+#define XGMAC_MAC_RX_PREAM_ERR_PKT_CNT_REG 0x1C8
+#define XGMAC_MAC_TX_LF_RF_TERM_PKT_CNT_REG 0x1CC
+#define XGMAC_MAC_TX_SN_MISMATCH_PKT_CNT_REG 0x1D0
+#define XGMAC_MAC_RX_ERR_MSG_CNT_REG 0x1D4
+#define XGMAC_MAC_RX_ERR_EFD_CNT_REG 0x1D8
+#define XGMAC_MAC_ERR_INFO_REG 0x1DC
+#define XGMAC_MAC_DBG_INFO_REG 0x1E0
+
+#define XGMAC_PCS_BASER_SYNC_THD_REG 0x330
+#define XGMAC_PCS_STATUS1_REG 0x404
+#define XGMAC_PCS_BASER_STATUS1_REG 0x410
+#define XGMAC_PCS_BASER_STATUS2_REG 0x414
+#define XGMAC_PCS_BASER_SEEDA_0_REG 0x420
+#define XGMAC_PCS_BASER_SEEDA_1_REG 0x424
+#define XGMAC_PCS_BASER_SEEDB_0_REG 0x428
+#define XGMAC_PCS_BASER_SEEDB_1_REG 0x42C
+#define XGMAC_PCS_BASER_TEST_CONTROL_REG 0x430
+#define XGMAC_PCS_BASER_TEST_ERR_CNT_REG 0x434
+#define XGMAC_PCS_DBG_INFO_REG 0x4C0
+#define XGMAC_PCS_DBG_INFO1_REG 0x4C4
+#define XGMAC_PCS_DBG_INFO2_REG 0x4C8
+#define XGMAC_PCS_DBG_INFO3_REG 0x4CC
+
+#define XGMAC_PMA_ENABLE_REG 0x700
+#define XGMAC_PMA_CONTROL_REG 0x704
+#define XGMAC_PMA_SIGNAL_STATUS_REG 0x708
+#define XGMAC_PMA_DBG_INFO_REG 0x70C
+#define XGMAC_PMA_FEC_ABILITY_REG 0x740
+#define XGMAC_PMA_FEC_CONTROL_REG 0x744
+#define XGMAC_PMA_FEC_CORR_BLOCK_CNT__REG 0x750
+#define XGMAC_PMA_FEC_UNCORR_BLOCK_CNT__REG 0x760
+
+#define XGMAC_TX_PKTS_FRAGMENT 0x0000
+#define XGMAC_TX_PKTS_UNDERSIZE 0x0008
+#define XGMAC_TX_PKTS_UNDERMIN 0x0010
+#define XGMAC_TX_PKTS_64OCTETS 0x0018
+#define XGMAC_TX_PKTS_65TO127OCTETS 0x0020
+#define XGMAC_TX_PKTS_128TO255OCTETS 0x0028
+#define XGMAC_TX_PKTS_256TO511OCTETS 0x0030
+#define XGMAC_TX_PKTS_512TO1023OCTETS 0x0038
+#define XGMAC_TX_PKTS_1024TO1518OCTETS 0x0040
+#define XGMAC_TX_PKTS_1519TOMAXOCTETS 0x0048
+#define XGMAC_TX_PKTS_1519TOMAXOCTETSOK 0x0050
+#define XGMAC_TX_PKTS_OVERSIZE 0x0058
+#define XGMAC_TX_PKTS_JABBER 0x0060
+#define XGMAC_TX_GOODPKTS 0x0068
+#define XGMAC_TX_GOODOCTETS 0x0070
+#define XGMAC_TX_TOTAL_PKTS 0x0078
+#define XGMAC_TX_TOTALOCTETS 0x0080
+#define XGMAC_TX_UNICASTPKTS 0x0088
+#define XGMAC_TX_MULTICASTPKTS 0x0090
+#define XGMAC_TX_BROADCASTPKTS 0x0098
+#define XGMAC_TX_PRI0PAUSEPKTS 0x00a0
+#define XGMAC_TX_PRI1PAUSEPKTS 0x00a8
+#define XGMAC_TX_PRI2PAUSEPKTS 0x00b0
+#define XGMAC_TX_PRI3PAUSEPKTS 0x00b8
+#define XGMAC_TX_PRI4PAUSEPKTS 0x00c0
+#define XGMAC_TX_PRI5PAUSEPKTS 0x00c8
+#define XGMAC_TX_PRI6PAUSEPKTS 0x00d0
+#define XGMAC_TX_PRI7PAUSEPKTS 0x00d8
+#define XGMAC_TX_MACCTRLPKTS 0x00e0
+#define XGMAC_TX_1731PKTS 0x00e8
+#define XGMAC_TX_1588PKTS 0x00f0
+#define XGMAC_RX_FROMAPPGOODPKTS 0x00f8
+#define XGMAC_RX_FROMAPPBADPKTS 0x0100
+#define XGMAC_TX_ERRALLPKTS 0x0108
+
+#define XGMAC_RX_PKTS_FRAGMENT 0x0110
+#define XGMAC_RX_PKTSUNDERSIZE 0x0118
+#define XGMAC_RX_PKTS_UNDERMIN 0x0120
+#define XGMAC_RX_PKTS_64OCTETS 0x0128
+#define XGMAC_RX_PKTS_65TO127OCTETS 0x0130
+#define XGMAC_RX_PKTS_128TO255OCTETS 0x0138
+#define XGMAC_RX_PKTS_256TO511OCTETS 0x0140
+#define XGMAC_RX_PKTS_512TO1023OCTETS 0x0148
+#define XGMAC_RX_PKTS_1024TO1518OCTETS 0x0150
+#define XGMAC_RX_PKTS_1519TOMAXOCTETS 0x0158
+#define XGMAC_RX_PKTS_1519TOMAXOCTETSOK 0x0160
+#define XGMAC_RX_PKTS_OVERSIZE 0x0168
+#define XGMAC_RX_PKTS_JABBER 0x0170
+#define XGMAC_RX_GOODPKTS 0x0178
+#define XGMAC_RX_GOODOCTETS 0x0180
+#define XGMAC_RX_TOTAL_PKTS 0x0188
+#define XGMAC_RX_TOTALOCTETS 0x0190
+#define XGMAC_RX_UNICASTPKTS 0x0198
+#define XGMAC_RX_MULTICASTPKTS 0x01a0
+#define XGMAC_RX_BROADCASTPKTS 0x01a8
+#define XGMAC_RX_PRI0PAUSEPKTS 0x01b0
+#define XGMAC_RX_PRI1PAUSEPKTS 0x01b8
+#define XGMAC_RX_PRI2PAUSEPKTS 0x01c0
+#define XGMAC_RX_PRI3PAUSEPKTS 0x01c8
+#define XGMAC_RX_PRI4PAUSEPKTS 0x01d0
+#define XGMAC_RX_PRI5PAUSEPKTS 0x01d8
+#define XGMAC_RX_PRI6PAUSEPKTS 0x01e0
+#define XGMAC_RX_PRI7PAUSEPKTS 0x01e8
+#define XGMAC_RX_MACCTRLPKTS 0x01f0
+#define XGMAC_TX_SENDAPPGOODPKTS 0x01f8
+#define XGMAC_TX_SENDAPPBADPKTS 0x0200
+#define XGMAC_RX_1731PKTS 0x0208
+#define XGMAC_RX_SYMBOLERRPKTS 0x0210
+#define XGMAC_RX_FCSERRPKTS 0x0218
+
+#define XGMAC_TRX_CORE_SRST_M 0x2080
+
+#define DSAF_CFG_EN_S 0
+#define DSAF_CFG_TC_MODE_S 1
+#define DSAF_CFG_CRC_EN_S 2
+#define DSAF_CFG_SBM_INIT_S 3
+#define DSAF_CFG_MIX_MODE_S 4
+#define DSAF_CFG_STP_MODE_S 5
+#define DSAF_CFG_LOCA_ADDR_EN_S 6
+
+#define DSAF_CNT_CLR_CE_S 0
+#define DSAF_SNAP_EN_S 1
+
+#define HNS_DSAF_PFC_UNIT_CNT_FOR_XGE 41
+#define HNS_DSAF_PFC_UNIT_CNT_FOR_GE_1000 410
+#define HNS_DSAF_PFC_UNIT_CNT_FOR_GE_2500 103
+
+#define DSAF_PFC_UNINT_CNT_M ((1ULL << 9) - 1)
+#define DSAF_PFC_UNINT_CNT_S 0
+
+#define DSAF_PPE_QID_CFG_M 0xFF
+#define DSAF_PPE_QID_CFG_S 0
+
+#define DSAF_SW_PORT_TYPE_M 3
+#define DSAF_SW_PORT_TYPE_S 0
+
+#define DSAF_STP_PORT_TYPE_M 7
+#define DSAF_STP_PORT_TYPE_S 0
+
+#define DSAF_INODE_IN_PORT_NUM_M 7
+#define DSAF_INODE_IN_PORT_NUM_S 0
+
+#define HNS_DSAF_I4TC_CFG 0x18688688
+#define HNS_DSAF_I8TC_CFG 0x18FAC688
+
+#define DSAF_SBM_CFG_SHCUT_EN_S 0
+#define DSAF_SBM_CFG_EN_S 1
+#define DSAF_SBM_CFG_MIB_EN_S 2
+#define DSAF_SBM_CFG_ECC_INVERT_EN_S 3
+
+#define DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_S 0
+#define DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 0)
+#define DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_S 10
+#define DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 10)
+#define DSAF_SBM_CFG0_COM_MAX_BUF_NUM_S 20
+#define DSAF_SBM_CFG0_COM_MAX_BUF_NUM_M (((1ULL << 11) - 1) << 20)
+
+#define DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_S 0
+#define DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 0)
+#define DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_S 10
+#define DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 10)
+
+#define DSAF_SBM_CFG2_SET_BUF_NUM_S 0
+#define DSAF_SBM_CFG2_SET_BUF_NUM_M (((1ULL << 10) - 1) << 0)
+#define DSAF_SBM_CFG2_RESET_BUF_NUM_S 10
+#define DSAF_SBM_CFG2_RESET_BUF_NUM_M (((1ULL << 10) - 1) << 10)
+
+#define DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_S 0
+#define DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_M (((1ULL << 10) - 1) << 0)
+#define DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S 10
+#define DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M (((1ULL << 10) - 1) << 10)
+
+#define DSAF_TBL_TCAM_ADDR_S 0
+#define DSAF_TBL_TCAM_ADDR_M ((1ULL << 9) - 1)
+
+#define DSAF_TBL_LINE_ADDR_S 0
+#define DSAF_TBL_LINE_ADDR_M ((1ULL << 15) - 1)
+
+#define DSAF_TBL_MCAST_CFG4_VM128_112_S 0
+#define DSAF_TBL_MCAST_CFG4_VM128_112_M (((1ULL << 7) - 1) << 0)
+#define DSAF_TBL_MCAST_CFG4_ITEM_VLD_S 7
+#define DSAF_TBL_MCAST_CFG4_OLD_EN_S 8
+
+#define DSAF_TBL_MCAST_CFG0_XGE5_0_S 0
+#define DSAF_TBL_MCAST_CFG0_XGE5_0_M (((1ULL << 6) - 1) << 0)
+#define DSAF_TBL_MCAST_CFG0_VM25_0_S 6
+#define DSAF_TBL_MCAST_CFG0_VM25_0_M (((1ULL << 26) - 1) << 6)
+
+#define DSAF_TBL_UCAST_CFG1_OUT_PORT_S 0
+#define DSAF_TBL_UCAST_CFG1_OUT_PORT_M (((1ULL << 8) - 1) << 0)
+#define DSAF_TBL_UCAST_CFG1_DVC_S 8
+#define DSAF_TBL_UCAST_CFG1_MAC_DISCARD_S 9
+#define DSAF_TBL_UCAST_CFG1_ITEM_VLD_S 10
+#define DSAF_TBL_UCAST_CFG1_OLD_EN_S 11
+
+#define DSAF_TBL_LINE_CFG_OUT_PORT_S 0
+#define DSAF_TBL_LINE_CFG_OUT_PORT_M (((1ULL << 8) - 1) << 0)
+#define DSAF_TBL_LINE_CFG_DVC_S 8
+#define DSAF_TBL_LINE_CFG_MAC_DISCARD_S 9
+
+#define DSAF_TBL_PUL_OLD_RSLT_RE_S 0
+#define DSAF_TBL_PUL_MCAST_VLD_S 1
+#define DSAF_TBL_PUL_TCAM_DATA_VLD_S 2
+#define DSAF_TBL_PUL_UCAST_VLD_S 3
+#define DSAF_TBL_PUL_LINE_VLD_S 4
+#define DSAF_TBL_PUL_TCAM_LOAD_S 5
+#define DSAF_TBL_PUL_LINE_LOAD_S 6
+
+#define DSAF_TBL_DFX_LINE_LKUP_NUM_EN_S 0
+#define DSAF_TBL_DFX_UC_LKUP_NUM_EN_S 1
+#define DSAF_TBL_DFX_MC_LKUP_NUM_EN_S 2
+#define DSAF_TBL_DFX_BC_LKUP_NUM_EN_S 3
+#define DSAF_TBL_DFX_RAM_ERR_INJECT_EN_S 4
+
+#define DSAF_VOQ_BP_ALL_DOWNTHRD_S 0
+#define DSAF_VOQ_BP_ALL_DOWNTHRD_M (((1ULL << 10) - 1) << 0)
+#define DSAF_VOQ_BP_ALL_UPTHRD_S 10
+#define DSAF_VOQ_BP_ALL_UPTHRD_M (((1ULL << 10) - 1) << 10)
+
+#define DSAF_XGE_GE_WORK_MODE_S 0
+#define DSAF_XGE_GE_LOOPBACK_S 1
+
+#define DSAF_FC_XGE_TX_PAUSE_S 0
+#define DSAF_REGS_XGE_CNT_CAR_S 1
+
+#define PPE_CFG_QID_MODE_DEF_QID_S 0
+#define PPE_CFG_QID_MODE_DEF_QID_M (0xff << PPE_CFG_QID_MODE_DEF_QID_S)
+
+#define PPE_CFG_QID_MODE_CF_QID_MODE_S 8
+#define PPE_CFG_QID_MODE_CF_QID_MODE_M (0x7 << PPE_CFG_QID_MODE_CF_QID_MODE_S)
+
+#define PPE_CNT_CLR_CE_B 0
+#define PPE_CNT_CLR_SNAP_EN_B 1
+
+#define PPE_COMMON_CNT_CLR_CE_B 0
+#define PPE_COMMON_CNT_CLR_SNAP_EN_B 1
+
+#define GMAC_DUPLEX_TYPE_B 0
+
+#define GMAC_FC_TX_TIMER_S 0
+#define GMAC_FC_TX_TIMER_M 0xffff
+
+#define GMAC_MAX_FRM_SIZE_S 0
+#define GMAC_MAX_FRM_SIZE_M 0xffff
+
+#define GMAC_PORT_MODE_S 0
+#define GMAC_PORT_MODE_M 0xf
+
+#define GMAC_RGMII_1000M_DELAY_B 4
+#define GMAC_MII_TX_EDGE_SEL_B 5
+#define GMAC_FIFO_ERR_AUTO_RST_B 6
+#define GMAC_DBG_CLK_LOS_MSK_B 7
+
+#define GMAC_PORT_RX_EN_B 1
+#define GMAC_PORT_TX_EN_B 2
+
+#define GMAC_PAUSE_EN_RX_FDFC_B 0
+#define GMAC_PAUSE_EN_TX_FDFC_B 1
+#define GMAC_PAUSE_EN_TX_HDFC_B 2
+
+#define GMAC_SHORT_RUNTS_THR_S 0
+#define GMAC_SHORT_RUNTS_THR_M 0x1f
+
+#define GMAC_AN_NEG_STAT_FD_B 5
+#define GMAC_AN_NEG_STAT_HD_B 6
+#define GMAC_AN_NEG_STAT_RF1_DUPLIEX_B 12
+#define GMAC_AN_NEG_STAT_RF2_B 13
+
+#define GMAC_AN_NEG_STAT_NP_LNK_OK_B 15
+#define GMAC_AN_NEG_STAT_RX_SYNC_OK_B 20
+#define GMAC_AN_NEG_STAT_AN_DONE_B 21
+
+#define GMAC_AN_NEG_STAT_PS_S 7
+#define GMAC_AN_NEG_STAT_PS_M (0x3 << GMAC_AN_NEG_STAT_PS_S)
+
+#define GMAC_AN_NEG_STAT_SPEED_S 10
+#define GMAC_AN_NEG_STAT_SPEED_M (0x3 << GMAC_AN_NEG_STAT_SPEED_S)
+
+#define GMAC_TX_AN_EN_B 5
+#define GMAC_TX_CRC_ADD_B 6
+#define GMAC_TX_PAD_EN_B 7
+
+#define GMAC_LINE_LOOPBACK_B 0
+
+#define GMAC_LP_REG_CF_EXT_DRV_LP_B 1
+#define GMAC_LP_REG_CF2MI_LP_EN_B 2
+
+#define GMAC_MODE_CHANGE_EB_B 0
+
+#define GMAC_RECV_CTRL_STRIP_PAD_EN_B 3
+#define GMAC_RECV_CTRL_RUNT_PKT_EN_B 4
+
+#define GMAC_TX_LOOP_PKT_HIG_PRI_B 0
+#define GMAC_TX_LOOP_PKT_EN_B 1
+
+#define XGMAC_PORT_MODE_TX_S 0x0
+#define XGMAC_PORT_MODE_TX_M (0x3 << XGMAC_PORT_MODE_TX_S)
+#define XGMAC_PORT_MODE_TX_40G_B 0x3
+#define XGMAC_PORT_MODE_RX_S 0x4
+#define XGMAC_PORT_MODE_RX_M (0x3 << XGMAC_PORT_MODE_RX_S)
+#define XGMAC_PORT_MODE_RX_40G_B 0x7
+
+#define XGMAC_ENABLE_TX_B 0
+#define XGMAC_ENABLE_RX_B 1
+
+#define XGMAC_CTL_TX_FCS_B 0
+#define XGMAC_CTL_TX_PAD_B 1
+#define XGMAC_CTL_TX_PREAMBLE_TRANS_B 3
+#define XGMAC_CTL_TX_UNDER_MIN_ERR_B 4
+#define XGMAC_CTL_TX_TRUNCATE_B 5
+#define XGMAC_CTL_TX_1588_B 8
+#define XGMAC_CTL_TX_1731_B 9
+#define XGMAC_CTL_TX_PFC_B 10
+#define XGMAC_CTL_RX_FCS_B 16
+#define XGMAC_CTL_RX_FCS_STRIP_B 17
+#define XGMAC_CTL_RX_PREAMBLE_TRANS_B 19
+#define XGMAC_CTL_RX_UNDER_MIN_ERR_B 20
+#define XGMAC_CTL_RX_TRUNCATE_B 21
+#define XGMAC_CTL_RX_1588_B 24
+#define XGMAC_CTL_RX_1731_B 25
+#define XGMAC_CTL_RX_PFC_B 26
+
+#define XGMAC_PMA_FEC_CTL_TX_B 0
+#define XGMAC_PMA_FEC_CTL_RX_B 1
+#define XGMAC_PMA_FEC_CTL_ERR_EN 2
+#define XGMAC_PMA_FEC_CTL_ERR_SH 3
+
+#define XGMAC_PAUSE_CTL_TX_B 0
+#define XGMAC_PAUSE_CTL_RX_B 1
+#define XGMAC_PAUSE_CTL_RSP_MODE_B 2
+#define XGMAC_PAUSE_CTL_TX_XOFF_B 3
+
+static inline void dsaf_write_reg(void *base, u32 reg, u32 value)
+{
+ u8 __iomem *reg_addr = ACCESS_ONCE(base);
+
+ writel(value, reg_addr + reg);
+}
+
+#define dsaf_write_dev(a, reg, value) \
+ dsaf_write_reg((a)->io_base, (reg), (value))
+
+static inline u32 dsaf_read_reg(u8 *base, u32 reg)
+{
+ u8 __iomem *reg_addr = ACCESS_ONCE(base);
+
+ return readl(reg_addr + reg);
+}
+
+#define dsaf_read_dev(a, reg) \
+ dsaf_read_reg((a)->io_base, (reg))
+
+#define dsaf_set_field(origin, mask, shift, val) \
+ do { \
+ (origin) &= (~(mask)); \
+ (origin) |= (((val) << (shift)) & (mask)); \
+ } while (0)
+
+#define dsaf_set_bit(origin, shift, val) \
+ dsaf_set_field((origin), (1ull << (shift)), (shift), (val))
+
+static inline void dsaf_set_reg_field(void *base, u32 reg, u32 mask, u32 shift,
+ u32 val)
+{
+ u32 origin = dsaf_read_reg(base, reg);
+
+ dsaf_set_field(origin, mask, shift, val);
+ dsaf_write_reg(base, reg, origin);
+}
+
+#define dsaf_set_dev_field(dev, reg, mask, shift, val) \
+ dsaf_set_reg_field((dev)->io_base, (reg), (mask), (shift), (val))
+
+#define dsaf_set_dev_bit(dev, reg, bit, val) \
+ dsaf_set_reg_field((dev)->io_base, (reg), (1ull << (bit)), (bit), (val))
+
+#define dsaf_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift))
+
+#define dsaf_get_bit(origin, shift) \
+ dsaf_get_field((origin), (1ull << (shift)), (shift))
+
+static inline u32 dsaf_get_reg_field(void *base, u32 reg, u32 mask, u32 shift)
+{
+ u32 origin;
+
+ origin = dsaf_read_reg(base, reg);
+ return dsaf_get_field(origin, mask, shift);
+}
+
+#define dsaf_get_dev_field(dev, reg, mask, shift) \
+ dsaf_get_reg_field((dev)->io_base, (reg), (mask), (shift))
+
+#define dsaf_get_dev_bit(dev, reg, bit) \
+ dsaf_get_reg_field((dev)->io_base, (reg), (1ull << (bit)), (bit))
+
+#define dsaf_write_b(addr, data)\
+ writeb((data), (__iomem unsigned char *)(addr))
+#define dsaf_read_b(addr)\
+ readb((__iomem unsigned char *)(addr))
+
+#define hns_mac_reg_read64(drv, offset) \
+ readq((__iomem void *)(((u8 *)(drv)->io_base + 0xc00 + (offset))))
+
+#endif /* _DSAF_REG_H */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
new file mode 100644
index 000000000000..802d55457f19
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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 <asm-generic/io-64-nonatomic-hi-lo.h>
+#include <linux/of_mdio.h>
+#include "hns_dsaf_main.h"
+#include "hns_dsaf_mac.h"
+#include "hns_dsaf_xgmac.h"
+#include "hns_dsaf_reg.h"
+
+static const struct mac_stats_string g_xgmac_stats_string[] = {
+ {"xgmac_tx_bad_pkts_minto64", MAC_STATS_FIELD_OFF(tx_fragment_err)},
+ {"xgmac_tx_good_pkts_minto64", MAC_STATS_FIELD_OFF(tx_undersize)},
+ {"xgmac_tx_total_pkts_minto64", MAC_STATS_FIELD_OFF(tx_under_min_pkts)},
+ {"xgmac_tx_pkts_64", MAC_STATS_FIELD_OFF(tx_64bytes)},
+ {"xgmac_tx_pkts_65to127", MAC_STATS_FIELD_OFF(tx_65to127)},
+ {"xgmac_tx_pkts_128to255", MAC_STATS_FIELD_OFF(tx_128to255)},
+ {"xgmac_tx_pkts_256to511", MAC_STATS_FIELD_OFF(tx_256to511)},
+ {"xgmac_tx_pkts_512to1023", MAC_STATS_FIELD_OFF(tx_512to1023)},
+ {"xgmac_tx_pkts_1024to1518", MAC_STATS_FIELD_OFF(tx_1024to1518)},
+ {"xgmac_tx_pkts_1519tomax", MAC_STATS_FIELD_OFF(tx_1519tomax)},
+ {"xgmac_tx_good_pkts_1519tomax",
+ MAC_STATS_FIELD_OFF(tx_1519tomax_good)},
+ {"xgmac_tx_good_pkts_untralmax", MAC_STATS_FIELD_OFF(tx_oversize)},
+ {"xgmac_tx_bad_pkts_untralmax", MAC_STATS_FIELD_OFF(tx_jabber_err)},
+ {"xgmac_tx_good_pkts_all", MAC_STATS_FIELD_OFF(tx_good_pkts)},
+ {"xgmac_tx_good_byte_all", MAC_STATS_FIELD_OFF(tx_good_bytes)},
+ {"xgmac_tx_total_pkt", MAC_STATS_FIELD_OFF(tx_total_pkts)},
+ {"xgmac_tx_total_byt", MAC_STATS_FIELD_OFF(tx_total_bytes)},
+ {"xgmac_tx_uc_pkt", MAC_STATS_FIELD_OFF(tx_uc_pkts)},
+ {"xgmac_tx_mc_pkt", MAC_STATS_FIELD_OFF(tx_mc_pkts)},
+ {"xgmac_tx_bc_pkt", MAC_STATS_FIELD_OFF(tx_bc_pkts)},
+ {"xgmac_tx_pause_frame_num", MAC_STATS_FIELD_OFF(tx_pfc_tc0)},
+ {"xgmac_tx_pfc_per_1pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc1)},
+ {"xgmac_tx_pfc_per_2pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc2)},
+ {"xgmac_tx_pfc_per_3pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc3)},
+ {"xgmac_tx_pfc_per_4pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc4)},
+ {"xgmac_tx_pfc_per_5pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc5)},
+ {"xgmac_tx_pfc_per_6pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc6)},
+ {"xgmac_tx_pfc_per_7pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc7)},
+ {"xgmac_tx_mac_ctrol_frame", MAC_STATS_FIELD_OFF(tx_ctrl)},
+ {"xgmac_tx_1731_pkts", MAC_STATS_FIELD_OFF(tx_1731_pkts)},
+ {"xgmac_tx_1588_pkts", MAC_STATS_FIELD_OFF(tx_1588_pkts)},
+ {"xgmac_rx_good_pkt_from_dsaf", MAC_STATS_FIELD_OFF(rx_good_from_sw)},
+ {"xgmac_rx_bad_pkt_from_dsaf", MAC_STATS_FIELD_OFF(rx_bad_from_sw)},
+ {"xgmac_tx_bad_pkt_64tomax", MAC_STATS_FIELD_OFF(tx_bad_pkts)},
+
+ {"xgmac_rx_bad_pkts_minto64", MAC_STATS_FIELD_OFF(rx_fragment_err)},
+ {"xgmac_rx_good_pkts_minto64", MAC_STATS_FIELD_OFF(rx_undersize)},
+ {"xgmac_rx_total_pkts_minto64", MAC_STATS_FIELD_OFF(rx_under_min)},
+ {"xgmac_rx_pkt_64", MAC_STATS_FIELD_OFF(rx_64bytes)},
+ {"xgmac_rx_pkt_65to127", MAC_STATS_FIELD_OFF(rx_65to127)},
+ {"xgmac_rx_pkt_128to255", MAC_STATS_FIELD_OFF(rx_128to255)},
+ {"xgmac_rx_pkt_256to511", MAC_STATS_FIELD_OFF(rx_256to511)},
+ {"xgmac_rx_pkt_512to1023", MAC_STATS_FIELD_OFF(rx_512to1023)},
+ {"xgmac_rx_pkt_1024to1518", MAC_STATS_FIELD_OFF(rx_1024to1518)},
+ {"xgmac_rx_pkt_1519tomax", MAC_STATS_FIELD_OFF(rx_1519tomax)},
+ {"xgmac_rx_good_pkt_1519tomax", MAC_STATS_FIELD_OFF(rx_1519tomax_good)},
+ {"xgmac_rx_good_pkt_untramax", MAC_STATS_FIELD_OFF(rx_oversize)},
+ {"xgmac_rx_bad_pkt_untramax", MAC_STATS_FIELD_OFF(rx_jabber_err)},
+ {"xgmac_rx_good_pkt", MAC_STATS_FIELD_OFF(rx_good_pkts)},
+ {"xgmac_rx_good_byt", MAC_STATS_FIELD_OFF(rx_good_bytes)},
+ {"xgmac_rx_pkt", MAC_STATS_FIELD_OFF(rx_total_pkts)},
+ {"xgmac_rx_byt", MAC_STATS_FIELD_OFF(rx_total_bytes)},
+ {"xgmac_rx_uc_pkt", MAC_STATS_FIELD_OFF(rx_uc_pkts)},
+ {"xgmac_rx_mc_pkt", MAC_STATS_FIELD_OFF(rx_mc_pkts)},
+ {"xgmac_rx_bc_pkt", MAC_STATS_FIELD_OFF(rx_bc_pkts)},
+ {"xgmac_rx_pause_frame_num", MAC_STATS_FIELD_OFF(rx_pfc_tc0)},
+ {"xgmac_rx_pfc_per_1pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc1)},
+ {"xgmac_rx_pfc_per_2pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc2)},
+ {"xgmac_rx_pfc_per_3pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc3)},
+ {"xgmac_rx_pfc_per_4pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc4)},
+ {"xgmac_rx_pfc_per_5pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc5)},
+ {"xgmac_rx_pfc_per_6pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc6)},
+ {"xgmac_rx_pfc_per_7pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc7)},
+ {"xgmac_rx_mac_control", MAC_STATS_FIELD_OFF(rx_unknown_ctrl)},
+ {"xgmac_tx_good_pkt_todsaf", MAC_STATS_FIELD_OFF(tx_good_to_sw)},
+ {"xgmac_tx_bad_pkt_todsaf", MAC_STATS_FIELD_OFF(tx_bad_to_sw)},
+ {"xgmac_rx_1731_pkt", MAC_STATS_FIELD_OFF(rx_1731_pkts)},
+ {"xgmac_rx_symbol_err_pkt", MAC_STATS_FIELD_OFF(rx_symbol_err)},
+ {"xgmac_rx_fcs_pkt", MAC_STATS_FIELD_OFF(rx_fcs_err)}
+};
+
+/**
+ *hns_xgmac_tx_enable - xgmac port tx enable
+ *@drv: mac driver
+ *@value: value of enable
+ */
+static void hns_xgmac_tx_enable(struct mac_driver *drv, u32 value)
+{
+ dsaf_set_dev_bit(drv, XGMAC_MAC_ENABLE_REG, XGMAC_ENABLE_TX_B, !!value);
+}
+
+/**
+ *hns_xgmac_rx_enable - xgmac port rx enable
+ *@drv: mac driver
+ *@value: value of enable
+ */
+static void hns_xgmac_rx_enable(struct mac_driver *drv, u32 value)
+{
+ dsaf_set_dev_bit(drv, XGMAC_MAC_ENABLE_REG, XGMAC_ENABLE_RX_B, !!value);
+}
+
+/**
+ *hns_xgmac_enable - enable xgmac port
+ *@drv: mac driver
+ *@mode: mode of mac port
+ */
+static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct dsaf_device *dsaf_dev
+ = (struct dsaf_device *)dev_get_drvdata(drv->dev);
+ u32 port = drv->mac_id;
+
+ hns_dsaf_xge_core_srst_by_port(dsaf_dev, port, 1);
+ mdelay(10);
+
+ /*enable XGE rX/tX */
+ if (mode == MAC_COMM_MODE_TX) {
+ hns_xgmac_tx_enable(drv, 1);
+ } else if (mode == MAC_COMM_MODE_RX) {
+ hns_xgmac_rx_enable(drv, 1);
+ } else if (mode == MAC_COMM_MODE_RX_AND_TX) {
+ hns_xgmac_tx_enable(drv, 1);
+ hns_xgmac_rx_enable(drv, 1);
+ } else {
+ dev_err(drv->dev, "error mac mode:%d\n", mode);
+ }
+}
+
+/**
+ *hns_xgmac_disable - disable xgmac port
+ *@mac_drv: mac driver
+ *@mode: mode of mac port
+ */
+static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct dsaf_device *dsaf_dev
+ = (struct dsaf_device *)dev_get_drvdata(drv->dev);
+ u32 port = drv->mac_id;
+
+ if (mode == MAC_COMM_MODE_TX) {
+ hns_xgmac_tx_enable(drv, 0);
+ } else if (mode == MAC_COMM_MODE_RX) {
+ hns_xgmac_rx_enable(drv, 0);
+ } else if (mode == MAC_COMM_MODE_RX_AND_TX) {
+ hns_xgmac_tx_enable(drv, 0);
+ hns_xgmac_rx_enable(drv, 0);
+ }
+
+ mdelay(10);
+ hns_dsaf_xge_core_srst_by_port(dsaf_dev, port, 0);
+}
+
+/**
+ *hns_xgmac_pma_fec_enable - xgmac PMA FEC enable
+ *@drv: mac driver
+ *@tx_value: tx value
+ *@rx_value: rx value
+ *return status
+ */
+static void hns_xgmac_pma_fec_enable(struct mac_driver *drv, u32 tx_value,
+ u32 rx_value)
+{
+ u32 origin = dsaf_read_dev(drv, XGMAC_PMA_FEC_CONTROL_REG);
+
+ dsaf_set_bit(origin, XGMAC_PMA_FEC_CTL_TX_B, !!tx_value);
+ dsaf_set_bit(origin, XGMAC_PMA_FEC_CTL_RX_B, !!rx_value);
+ dsaf_write_dev(drv, XGMAC_PMA_FEC_CONTROL_REG, origin);
+}
+
+/* clr exc irq for xge*/
+static void hns_xgmac_exc_irq_en(struct mac_driver *drv, u32 en)
+{
+ u32 clr_vlue = 0xfffffffful;
+ u32 msk_vlue = en ? 0xfffffffful : 0; /*1 is en, 0 is dis*/
+
+ dsaf_write_dev(drv, XGMAC_INT_STATUS_REG, clr_vlue);
+ dsaf_write_dev(drv, XGMAC_INT_ENABLE_REG, msk_vlue);
+}
+
+/**
+ *hns_xgmac_init - initialize XGE
+ *@mac_drv: mac driver
+ */
+static void hns_xgmac_init(void *mac_drv)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct dsaf_device *dsaf_dev
+ = (struct dsaf_device *)dev_get_drvdata(drv->dev);
+ u32 port = drv->mac_id;
+
+ hns_dsaf_xge_srst_by_port(dsaf_dev, port, 0);
+ mdelay(100);
+ hns_dsaf_xge_srst_by_port(dsaf_dev, port, 1);
+
+ mdelay(100);
+ hns_xgmac_exc_irq_en(drv, 0);
+
+ hns_xgmac_pma_fec_enable(drv, 0x0, 0x0);
+
+ hns_xgmac_disable(mac_drv, MAC_COMM_MODE_RX_AND_TX);
+}
+
+/**
+ *hns_xgmac_config_pad_and_crc - set xgmac pad and crc enable the same time
+ *@mac_drv: mac driver
+ *@newval:enable of pad and crc
+ */
+static void hns_xgmac_config_pad_and_crc(void *mac_drv, u8 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ u32 origin = dsaf_read_dev(drv, XGMAC_MAC_CONTROL_REG);
+
+ dsaf_set_bit(origin, XGMAC_CTL_TX_PAD_B, !!newval);
+ dsaf_set_bit(origin, XGMAC_CTL_TX_FCS_B, !!newval);
+ dsaf_set_bit(origin, XGMAC_CTL_RX_FCS_B, !!newval);
+ dsaf_write_dev(drv, XGMAC_MAC_CONTROL_REG, origin);
+}
+
+/**
+ *hns_xgmac_pausefrm_cfg - set pause param about xgmac
+ *@mac_drv: mac driver
+ *@newval:enable of pad and crc
+ */
+static void hns_xgmac_pausefrm_cfg(void *mac_drv, u32 rx_en, u32 tx_en)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ u32 origin = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG);
+
+ dsaf_set_bit(origin, XGMAC_PAUSE_CTL_TX_B, !!tx_en);
+ dsaf_set_bit(origin, XGMAC_PAUSE_CTL_RX_B, !!rx_en);
+ dsaf_write_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG, origin);
+}
+
+static void hns_xgmac_set_pausefrm_mac_addr(void *mac_drv, char *mac_addr)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ u32 high_val = mac_addr[1] | (mac_addr[0] << 8);
+ u32 low_val = mac_addr[5] | (mac_addr[4] << 8)
+ | (mac_addr[3] << 16) | (mac_addr[2] << 24);
+ dsaf_write_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_L_REG, low_val);
+ dsaf_write_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_H_REG, high_val);
+}
+
+/**
+ *hns_xgmac_set_rx_ignore_pause_frames - set rx pause param about xgmac
+ *@mac_drv: mac driver
+ *@enable:enable rx pause param
+ */
+static void hns_xgmac_set_rx_ignore_pause_frames(void *mac_drv, u32 enable)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_bit(drv, XGMAC_MAC_PAUSE_CTRL_REG,
+ XGMAC_PAUSE_CTL_RX_B, !!enable);
+}
+
+/**
+ *hns_xgmac_set_tx_auto_pause_frames - set tx pause param about xgmac
+ *@mac_drv: mac driver
+ *@enable:enable tx pause param
+ */
+static void hns_xgmac_set_tx_auto_pause_frames(void *mac_drv, u16 enable)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_set_dev_bit(drv, XGMAC_MAC_PAUSE_CTRL_REG,
+ XGMAC_PAUSE_CTL_TX_B, !!enable);
+
+ /*if enable is not zero ,set tx pause time */
+ if (enable)
+ dsaf_write_dev(drv, XGMAC_MAC_PAUSE_TIME_REG, enable);
+}
+
+/**
+ *hns_xgmac_get_id - get xgmac port id
+ *@mac_drv: mac driver
+ *@newval:xgmac max frame length
+ */
+static void hns_xgmac_get_id(void *mac_drv, u8 *mac_id)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *mac_id = drv->mac_id;
+}
+
+/**
+ *hns_xgmac_config_max_frame_length - set xgmac max frame length
+ *@mac_drv: mac driver
+ *@newval:xgmac max frame length
+ */
+static void hns_xgmac_config_max_frame_length(void *mac_drv, u16 newval)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ dsaf_write_dev(drv, XGMAC_MAC_MAX_PKT_SIZE_REG, newval);
+}
+
+void hns_xgmac_update_stats(void *mac_drv)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct mac_hw_stats *hw_stats = &drv->mac_cb->hw_stats;
+
+ /* TX */
+ hw_stats->tx_fragment_err
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_FRAGMENT);
+ hw_stats->tx_undersize
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERSIZE);
+ hw_stats->tx_under_min_pkts
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERMIN);
+ hw_stats->tx_64bytes = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_64OCTETS);
+ hw_stats->tx_65to127
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_65TO127OCTETS);
+ hw_stats->tx_128to255
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_128TO255OCTETS);
+ hw_stats->tx_256to511
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_256TO511OCTETS);
+ hw_stats->tx_512to1023
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_512TO1023OCTETS);
+ hw_stats->tx_1024to1518
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1024TO1518OCTETS);
+ hw_stats->tx_1519tomax
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETS);
+ hw_stats->tx_1519tomax_good
+ = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETSOK);
+ hw_stats->tx_oversize = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_OVERSIZE);
+ hw_stats->tx_jabber_err = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_JABBER);
+ hw_stats->tx_good_pkts = hns_mac_reg_read64(drv, XGMAC_TX_GOODPKTS);
+ hw_stats->tx_good_bytes = hns_mac_reg_read64(drv, XGMAC_TX_GOODOCTETS);
+ hw_stats->tx_total_pkts = hns_mac_reg_read64(drv, XGMAC_TX_TOTAL_PKTS);
+ hw_stats->tx_total_bytes
+ = hns_mac_reg_read64(drv, XGMAC_TX_TOTALOCTETS);
+ hw_stats->tx_uc_pkts = hns_mac_reg_read64(drv, XGMAC_TX_UNICASTPKTS);
+ hw_stats->tx_mc_pkts = hns_mac_reg_read64(drv, XGMAC_TX_MULTICASTPKTS);
+ hw_stats->tx_bc_pkts = hns_mac_reg_read64(drv, XGMAC_TX_BROADCASTPKTS);
+ hw_stats->tx_pfc_tc0 = hns_mac_reg_read64(drv, XGMAC_TX_PRI0PAUSEPKTS);
+ hw_stats->tx_pfc_tc1 = hns_mac_reg_read64(drv, XGMAC_TX_PRI1PAUSEPKTS);
+ hw_stats->tx_pfc_tc2 = hns_mac_reg_read64(drv, XGMAC_TX_PRI2PAUSEPKTS);
+ hw_stats->tx_pfc_tc3 = hns_mac_reg_read64(drv, XGMAC_TX_PRI3PAUSEPKTS);
+ hw_stats->tx_pfc_tc4 = hns_mac_reg_read64(drv, XGMAC_TX_PRI4PAUSEPKTS);
+ hw_stats->tx_pfc_tc5 = hns_mac_reg_read64(drv, XGMAC_TX_PRI5PAUSEPKTS);
+ hw_stats->tx_pfc_tc6 = hns_mac_reg_read64(drv, XGMAC_TX_PRI6PAUSEPKTS);
+ hw_stats->tx_pfc_tc7 = hns_mac_reg_read64(drv, XGMAC_TX_PRI7PAUSEPKTS);
+ hw_stats->tx_ctrl = hns_mac_reg_read64(drv, XGMAC_TX_MACCTRLPKTS);
+ hw_stats->tx_1731_pkts = hns_mac_reg_read64(drv, XGMAC_TX_1731PKTS);
+ hw_stats->tx_1588_pkts = hns_mac_reg_read64(drv, XGMAC_TX_1588PKTS);
+ hw_stats->rx_good_from_sw
+ = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPGOODPKTS);
+ hw_stats->rx_bad_from_sw
+ = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPBADPKTS);
+ hw_stats->tx_bad_pkts = hns_mac_reg_read64(drv, XGMAC_TX_ERRALLPKTS);
+
+ /* RX */
+ hw_stats->rx_fragment_err
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_FRAGMENT);
+ hw_stats->rx_undersize
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTSUNDERSIZE);
+ hw_stats->rx_under_min
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_UNDERMIN);
+ hw_stats->rx_64bytes = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_64OCTETS);
+ hw_stats->rx_65to127
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_65TO127OCTETS);
+ hw_stats->rx_128to255
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_128TO255OCTETS);
+ hw_stats->rx_256to511
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_256TO511OCTETS);
+ hw_stats->rx_512to1023
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_512TO1023OCTETS);
+ hw_stats->rx_1024to1518
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1024TO1518OCTETS);
+ hw_stats->rx_1519tomax
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETS);
+ hw_stats->rx_1519tomax_good
+ = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETSOK);
+ hw_stats->rx_oversize = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_OVERSIZE);
+ hw_stats->rx_jabber_err = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_JABBER);
+ hw_stats->rx_good_pkts = hns_mac_reg_read64(drv, XGMAC_RX_GOODPKTS);
+ hw_stats->rx_good_bytes = hns_mac_reg_read64(drv, XGMAC_RX_GOODOCTETS);
+ hw_stats->rx_total_pkts = hns_mac_reg_read64(drv, XGMAC_RX_TOTAL_PKTS);
+ hw_stats->rx_total_bytes
+ = hns_mac_reg_read64(drv, XGMAC_RX_TOTALOCTETS);
+ hw_stats->rx_uc_pkts = hns_mac_reg_read64(drv, XGMAC_RX_UNICASTPKTS);
+ hw_stats->rx_mc_pkts = hns_mac_reg_read64(drv, XGMAC_RX_MULTICASTPKTS);
+ hw_stats->rx_bc_pkts = hns_mac_reg_read64(drv, XGMAC_RX_BROADCASTPKTS);
+ hw_stats->rx_pfc_tc0 = hns_mac_reg_read64(drv, XGMAC_RX_PRI0PAUSEPKTS);
+ hw_stats->rx_pfc_tc1 = hns_mac_reg_read64(drv, XGMAC_RX_PRI1PAUSEPKTS);
+ hw_stats->rx_pfc_tc2 = hns_mac_reg_read64(drv, XGMAC_RX_PRI2PAUSEPKTS);
+ hw_stats->rx_pfc_tc3 = hns_mac_reg_read64(drv, XGMAC_RX_PRI3PAUSEPKTS);
+ hw_stats->rx_pfc_tc4 = hns_mac_reg_read64(drv, XGMAC_RX_PRI4PAUSEPKTS);
+ hw_stats->rx_pfc_tc5 = hns_mac_reg_read64(drv, XGMAC_RX_PRI5PAUSEPKTS);
+ hw_stats->rx_pfc_tc6 = hns_mac_reg_read64(drv, XGMAC_RX_PRI6PAUSEPKTS);
+ hw_stats->rx_pfc_tc7 = hns_mac_reg_read64(drv, XGMAC_RX_PRI7PAUSEPKTS);
+
+ hw_stats->rx_unknown_ctrl
+ = hns_mac_reg_read64(drv, XGMAC_RX_MACCTRLPKTS);
+ hw_stats->tx_good_to_sw
+ = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPGOODPKTS);
+ hw_stats->tx_bad_to_sw
+ = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPBADPKTS);
+ hw_stats->rx_1731_pkts = hns_mac_reg_read64(drv, XGMAC_RX_1731PKTS);
+ hw_stats->rx_symbol_err
+ = hns_mac_reg_read64(drv, XGMAC_RX_SYMBOLERRPKTS);
+ hw_stats->rx_fcs_err = hns_mac_reg_read64(drv, XGMAC_RX_FCSERRPKTS);
+}
+
+/**
+ *hns_xgmac_free - free xgmac driver
+ *@mac_drv: mac driver
+ */
+static void hns_xgmac_free(void *mac_drv)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct dsaf_device *dsaf_dev
+ = (struct dsaf_device *)dev_get_drvdata(drv->dev);
+
+ u32 mac_id = drv->mac_id;
+
+ hns_dsaf_xge_srst_by_port(dsaf_dev, mac_id, 0);
+}
+
+/**
+ *hns_xgmac_get_info - get xgmac information
+ *@mac_drv: mac driver
+ *@mac_info:mac information
+ */
+static void hns_xgmac_get_info(void *mac_drv, struct mac_info *mac_info)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ u32 pause_time, pause_ctrl, port_mode, ctrl_val;
+
+ ctrl_val = dsaf_read_dev(drv, XGMAC_MAC_CONTROL_REG);
+ mac_info->pad_and_crc_en = dsaf_get_bit(ctrl_val, XGMAC_CTL_TX_PAD_B);
+ mac_info->auto_neg = 0;
+
+ pause_time = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_TIME_REG);
+ mac_info->tx_pause_time = pause_time;
+
+ port_mode = dsaf_read_dev(drv, XGMAC_PORT_MODE_REG);
+ mac_info->port_en = dsaf_get_field(port_mode, XGMAC_PORT_MODE_TX_M,
+ XGMAC_PORT_MODE_TX_S) &&
+ dsaf_get_field(port_mode, XGMAC_PORT_MODE_RX_M,
+ XGMAC_PORT_MODE_RX_S);
+ mac_info->duplex = 1;
+ mac_info->speed = MAC_SPEED_10000;
+
+ pause_ctrl = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG);
+ mac_info->rx_pause_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_RX_B);
+ mac_info->tx_pause_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_TX_B);
+}
+
+/**
+ *hns_xgmac_get_pausefrm_cfg - get xgmac pause param
+ *@mac_drv: mac driver
+ *@rx_en:xgmac rx pause enable
+ *@tx_en:xgmac tx pause enable
+ */
+static void hns_xgmac_get_pausefrm_cfg(void *mac_drv, u32 *rx_en, u32 *tx_en)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ u32 pause_ctrl;
+
+ pause_ctrl = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG);
+ *rx_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_RX_B);
+ *tx_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_TX_B);
+}
+
+/**
+ *hns_xgmac_get_link_status - get xgmac link status
+ *@mac_drv: mac driver
+ *@link_stat: xgmac link stat
+ */
+static void hns_xgmac_get_link_status(void *mac_drv, u32 *link_stat)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+ *link_stat = dsaf_read_dev(drv, XGMAC_LINK_STATUS_REG);
+}
+
+/**
+ *hns_xgmac_get_regs - dump xgmac regs
+ *@mac_drv: mac driver
+ *@cmd:ethtool cmd
+ *@data:data for value of regs
+ */
+static void hns_xgmac_get_regs(void *mac_drv, void *data)
+{
+ u32 i = 0;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ u32 *regs = data;
+ u64 qtmp;
+
+ /* base config registers */
+ regs[0] = dsaf_read_dev(drv, XGMAC_INT_STATUS_REG);
+ regs[1] = dsaf_read_dev(drv, XGMAC_INT_ENABLE_REG);
+ regs[2] = dsaf_read_dev(drv, XGMAC_INT_SET_REG);
+ regs[3] = dsaf_read_dev(drv, XGMAC_IERR_U_INFO_REG);
+ regs[4] = dsaf_read_dev(drv, XGMAC_OVF_INFO_REG);
+ regs[5] = dsaf_read_dev(drv, XGMAC_OVF_CNT_REG);
+ regs[6] = dsaf_read_dev(drv, XGMAC_PORT_MODE_REG);
+ regs[7] = dsaf_read_dev(drv, XGMAC_CLK_ENABLE_REG);
+ regs[8] = dsaf_read_dev(drv, XGMAC_RESET_REG);
+ regs[9] = dsaf_read_dev(drv, XGMAC_LINK_CONTROL_REG);
+ regs[10] = dsaf_read_dev(drv, XGMAC_LINK_STATUS_REG);
+
+ regs[11] = dsaf_read_dev(drv, XGMAC_SPARE_REG);
+ regs[12] = dsaf_read_dev(drv, XGMAC_SPARE_CNT_REG);
+ regs[13] = dsaf_read_dev(drv, XGMAC_MAC_ENABLE_REG);
+ regs[14] = dsaf_read_dev(drv, XGMAC_MAC_CONTROL_REG);
+ regs[15] = dsaf_read_dev(drv, XGMAC_MAC_IPG_REG);
+ regs[16] = dsaf_read_dev(drv, XGMAC_MAC_MSG_CRC_EN_REG);
+ regs[17] = dsaf_read_dev(drv, XGMAC_MAC_MSG_IMG_REG);
+ regs[18] = dsaf_read_dev(drv, XGMAC_MAC_MSG_FC_CFG_REG);
+ regs[19] = dsaf_read_dev(drv, XGMAC_MAC_MSG_TC_CFG_REG);
+ regs[20] = dsaf_read_dev(drv, XGMAC_MAC_PAD_SIZE_REG);
+ regs[21] = dsaf_read_dev(drv, XGMAC_MAC_MIN_PKT_SIZE_REG);
+ regs[22] = dsaf_read_dev(drv, XGMAC_MAC_MAX_PKT_SIZE_REG);
+ regs[23] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG);
+ regs[24] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_TIME_REG);
+ regs[25] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_GAP_REG);
+ regs[26] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_H_REG);
+ regs[27] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_L_REG);
+ regs[28] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_PEER_MAC_H_REG);
+ regs[29] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_PEER_MAC_L_REG);
+ regs[30] = dsaf_read_dev(drv, XGMAC_MAC_PFC_PRI_EN_REG);
+ regs[31] = dsaf_read_dev(drv, XGMAC_MAC_1588_CTRL_REG);
+ regs[32] = dsaf_read_dev(drv, XGMAC_MAC_1588_TX_PORT_DLY_REG);
+ regs[33] = dsaf_read_dev(drv, XGMAC_MAC_1588_RX_PORT_DLY_REG);
+ regs[34] = dsaf_read_dev(drv, XGMAC_MAC_1588_ASYM_DLY_REG);
+ regs[35] = dsaf_read_dev(drv, XGMAC_MAC_1588_ADJUST_CFG_REG);
+
+ regs[36] = dsaf_read_dev(drv, XGMAC_MAC_Y1731_ETH_TYPE_REG);
+ regs[37] = dsaf_read_dev(drv, XGMAC_MAC_MIB_CONTROL_REG);
+ regs[38] = dsaf_read_dev(drv, XGMAC_MAC_WAN_RATE_ADJUST_REG);
+ regs[39] = dsaf_read_dev(drv, XGMAC_MAC_TX_ERR_MARK_REG);
+ regs[40] = dsaf_read_dev(drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG);
+ regs[41] = dsaf_read_dev(drv, XGMAC_MAC_RX_LF_RF_STATUS_REG);
+ regs[42] = dsaf_read_dev(drv, XGMAC_MAC_TX_RUNT_PKT_CNT_REG);
+ regs[43] = dsaf_read_dev(drv, XGMAC_MAC_RX_RUNT_PKT_CNT_REG);
+ regs[44] = dsaf_read_dev(drv, XGMAC_MAC_RX_PREAM_ERR_PKT_CNT_REG);
+ regs[45] = dsaf_read_dev(drv, XGMAC_MAC_TX_LF_RF_TERM_PKT_CNT_REG);
+ regs[46] = dsaf_read_dev(drv, XGMAC_MAC_TX_SN_MISMATCH_PKT_CNT_REG);
+ regs[47] = dsaf_read_dev(drv, XGMAC_MAC_RX_ERR_MSG_CNT_REG);
+ regs[48] = dsaf_read_dev(drv, XGMAC_MAC_RX_ERR_EFD_CNT_REG);
+ regs[49] = dsaf_read_dev(drv, XGMAC_MAC_ERR_INFO_REG);
+ regs[50] = dsaf_read_dev(drv, XGMAC_MAC_DBG_INFO_REG);
+
+ regs[51] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SYNC_THD_REG);
+ regs[52] = dsaf_read_dev(drv, XGMAC_PCS_STATUS1_REG);
+ regs[53] = dsaf_read_dev(drv, XGMAC_PCS_BASER_STATUS1_REG);
+ regs[54] = dsaf_read_dev(drv, XGMAC_PCS_BASER_STATUS2_REG);
+ regs[55] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDA_0_REG);
+ regs[56] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDA_1_REG);
+ regs[57] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDB_0_REG);
+ regs[58] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDB_1_REG);
+ regs[59] = dsaf_read_dev(drv, XGMAC_PCS_BASER_TEST_CONTROL_REG);
+ regs[60] = dsaf_read_dev(drv, XGMAC_PCS_BASER_TEST_ERR_CNT_REG);
+ regs[61] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO_REG);
+ regs[62] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO1_REG);
+ regs[63] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO2_REG);
+ regs[64] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO3_REG);
+
+ regs[65] = dsaf_read_dev(drv, XGMAC_PMA_ENABLE_REG);
+ regs[66] = dsaf_read_dev(drv, XGMAC_PMA_CONTROL_REG);
+ regs[67] = dsaf_read_dev(drv, XGMAC_PMA_SIGNAL_STATUS_REG);
+ regs[68] = dsaf_read_dev(drv, XGMAC_PMA_DBG_INFO_REG);
+ regs[69] = dsaf_read_dev(drv, XGMAC_PMA_FEC_ABILITY_REG);
+ regs[70] = dsaf_read_dev(drv, XGMAC_PMA_FEC_CONTROL_REG);
+ regs[71] = dsaf_read_dev(drv, XGMAC_PMA_FEC_CORR_BLOCK_CNT__REG);
+ regs[72] = dsaf_read_dev(drv, XGMAC_PMA_FEC_UNCORR_BLOCK_CNT__REG);
+
+ /* status registers */
+#define hns_xgmac_cpy_q(p, q) \
+ do {\
+ *(p) = (u32)(q);\
+ *((p) + 1) = (u32)((q) >> 32);\
+ } while (0)
+
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_FRAGMENT);
+ hns_xgmac_cpy_q(&regs[73], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERSIZE);
+ hns_xgmac_cpy_q(&regs[75], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERMIN);
+ hns_xgmac_cpy_q(&regs[77], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_64OCTETS);
+ hns_xgmac_cpy_q(&regs[79], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_65TO127OCTETS);
+ hns_xgmac_cpy_q(&regs[81], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_128TO255OCTETS);
+ hns_xgmac_cpy_q(&regs[83], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_256TO511OCTETS);
+ hns_xgmac_cpy_q(&regs[85], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_512TO1023OCTETS);
+ hns_xgmac_cpy_q(&regs[87], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1024TO1518OCTETS);
+ hns_xgmac_cpy_q(&regs[89], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETS);
+ hns_xgmac_cpy_q(&regs[91], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETSOK);
+ hns_xgmac_cpy_q(&regs[93], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_OVERSIZE);
+ hns_xgmac_cpy_q(&regs[95], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_JABBER);
+ hns_xgmac_cpy_q(&regs[97], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_GOODPKTS);
+ hns_xgmac_cpy_q(&regs[99], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_GOODOCTETS);
+ hns_xgmac_cpy_q(&regs[101], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_TOTAL_PKTS);
+ hns_xgmac_cpy_q(&regs[103], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_TOTALOCTETS);
+ hns_xgmac_cpy_q(&regs[105], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_UNICASTPKTS);
+ hns_xgmac_cpy_q(&regs[107], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_MULTICASTPKTS);
+ hns_xgmac_cpy_q(&regs[109], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_BROADCASTPKTS);
+ hns_xgmac_cpy_q(&regs[111], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI0PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[113], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI1PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[115], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI2PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[117], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI3PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[119], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI4PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[121], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI5PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[123], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI6PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[125], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI7PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[127], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_MACCTRLPKTS);
+ hns_xgmac_cpy_q(&regs[129], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_1731PKTS);
+ hns_xgmac_cpy_q(&regs[131], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_1588PKTS);
+ hns_xgmac_cpy_q(&regs[133], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPGOODPKTS);
+ hns_xgmac_cpy_q(&regs[135], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPBADPKTS);
+ hns_xgmac_cpy_q(&regs[137], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_ERRALLPKTS);
+ hns_xgmac_cpy_q(&regs[139], qtmp);
+
+ /* RX */
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_FRAGMENT);
+ hns_xgmac_cpy_q(&regs[141], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTSUNDERSIZE);
+ hns_xgmac_cpy_q(&regs[143], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_UNDERMIN);
+ hns_xgmac_cpy_q(&regs[145], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_64OCTETS);
+ hns_xgmac_cpy_q(&regs[147], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_65TO127OCTETS);
+ hns_xgmac_cpy_q(&regs[149], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_128TO255OCTETS);
+ hns_xgmac_cpy_q(&regs[151], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_256TO511OCTETS);
+ hns_xgmac_cpy_q(&regs[153], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_512TO1023OCTETS);
+ hns_xgmac_cpy_q(&regs[155], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1024TO1518OCTETS);
+ hns_xgmac_cpy_q(&regs[157], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETS);
+ hns_xgmac_cpy_q(&regs[159], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETSOK);
+ hns_xgmac_cpy_q(&regs[161], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_OVERSIZE);
+ hns_xgmac_cpy_q(&regs[163], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_JABBER);
+ hns_xgmac_cpy_q(&regs[165], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_GOODPKTS);
+ hns_xgmac_cpy_q(&regs[167], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_GOODOCTETS);
+ hns_xgmac_cpy_q(&regs[169], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_TOTAL_PKTS);
+ hns_xgmac_cpy_q(&regs[171], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_TOTALOCTETS);
+ hns_xgmac_cpy_q(&regs[173], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_UNICASTPKTS);
+ hns_xgmac_cpy_q(&regs[175], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_MULTICASTPKTS);
+ hns_xgmac_cpy_q(&regs[177], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_BROADCASTPKTS);
+ hns_xgmac_cpy_q(&regs[179], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI0PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[181], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI1PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[183], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI2PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[185], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI3PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[187], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI4PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[189], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI5PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[191], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI6PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[193], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI7PAUSEPKTS);
+ hns_xgmac_cpy_q(&regs[195], qtmp);
+
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_MACCTRLPKTS);
+ hns_xgmac_cpy_q(&regs[197], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPGOODPKTS);
+ hns_xgmac_cpy_q(&regs[199], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPBADPKTS);
+ hns_xgmac_cpy_q(&regs[201], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_1731PKTS);
+ hns_xgmac_cpy_q(&regs[203], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_SYMBOLERRPKTS);
+ hns_xgmac_cpy_q(&regs[205], qtmp);
+ qtmp = hns_mac_reg_read64(drv, XGMAC_RX_FCSERRPKTS);
+ hns_xgmac_cpy_q(&regs[207], qtmp);
+
+ /* mark end of mac regs */
+ for (i = 208; i < 214; i++)
+ regs[i] = 0xaaaaaaaa;
+}
+
+/**
+ *hns_xgmac_get_stats - get xgmac statistic
+ *@mac_drv: mac driver
+ *@data:data for value of stats regs
+ */
+static void hns_xgmac_get_stats(void *mac_drv, u64 *data)
+{
+ u32 i;
+ u64 *buf = data;
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct mac_hw_stats *hw_stats = NULL;
+
+ hw_stats = &drv->mac_cb->hw_stats;
+
+ for (i = 0; i < ARRAY_SIZE(g_xgmac_stats_string); i++) {
+ buf[i] = DSAF_STATS_READ(hw_stats,
+ g_xgmac_stats_string[i].offset);
+ }
+}
+
+/**
+ *hns_xgmac_get_strings - get xgmac strings name
+ *@stringset: type of values in data
+ *@data:data for value of string name
+ */
+static void hns_xgmac_get_strings(u32 stringset, u8 *data)
+{
+ char *buff = (char *)data;
+ u32 i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(g_xgmac_stats_string); i++) {
+ snprintf(buff, ETH_GSTRING_LEN, g_xgmac_stats_string[i].desc);
+ buff = buff + ETH_GSTRING_LEN;
+ }
+}
+
+/**
+ *hns_xgmac_get_sset_count - get xgmac string set count
+ *@stringset: type of values in data
+ *return xgmac string set count
+ */
+static int hns_xgmac_get_sset_count(int stringset)
+{
+ if (stringset == ETH_SS_STATS)
+ return ARRAY_SIZE(g_xgmac_stats_string);
+
+ return 0;
+}
+
+/**
+ *hns_xgmac_get_regs_count - get xgmac regs count
+ *return xgmac regs count
+ */
+static int hns_xgmac_get_regs_count(void)
+{
+ return ETH_XGMAC_DUMP_NUM;
+}
+
+void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
+{
+ struct mac_driver *mac_drv;
+
+ mac_drv = devm_kzalloc(mac_cb->dev, sizeof(*mac_drv), GFP_KERNEL);
+ if (!mac_drv)
+ return NULL;
+
+ mac_drv->mac_init = hns_xgmac_init;
+ mac_drv->mac_enable = hns_xgmac_enable;
+ mac_drv->mac_disable = hns_xgmac_disable;
+
+ mac_drv->mac_id = mac_param->mac_id;
+ mac_drv->mac_mode = mac_param->mac_mode;
+ mac_drv->io_base = mac_param->vaddr;
+ mac_drv->dev = mac_param->dev;
+ mac_drv->mac_cb = mac_cb;
+
+ mac_drv->set_mac_addr = hns_xgmac_set_pausefrm_mac_addr;
+ mac_drv->set_an_mode = NULL;
+ mac_drv->config_loopback = NULL;
+ mac_drv->config_pad_and_crc = hns_xgmac_config_pad_and_crc;
+ mac_drv->config_half_duplex = NULL;
+ mac_drv->set_rx_ignore_pause_frames =
+ hns_xgmac_set_rx_ignore_pause_frames;
+ mac_drv->mac_get_id = hns_xgmac_get_id;
+ mac_drv->mac_free = hns_xgmac_free;
+ mac_drv->adjust_link = NULL;
+ mac_drv->set_tx_auto_pause_frames = hns_xgmac_set_tx_auto_pause_frames;
+ mac_drv->config_max_frame_length = hns_xgmac_config_max_frame_length;
+ mac_drv->mac_pausefrm_cfg = hns_xgmac_pausefrm_cfg;
+ mac_drv->autoneg_stat = NULL;
+ mac_drv->get_info = hns_xgmac_get_info;
+ mac_drv->get_pause_enable = hns_xgmac_get_pausefrm_cfg;
+ mac_drv->get_link_status = hns_xgmac_get_link_status;
+ mac_drv->get_regs = hns_xgmac_get_regs;
+ mac_drv->get_ethtool_stats = hns_xgmac_get_stats;
+ mac_drv->get_sset_count = hns_xgmac_get_sset_count;
+ mac_drv->get_regs_count = hns_xgmac_get_regs_count;
+ mac_drv->get_strings = hns_xgmac_get_strings;
+ mac_drv->update_stats = hns_xgmac_update_stats;
+
+ return (void *)mac_drv;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h
new file mode 100644
index 000000000000..139f7297c7b4
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef _HNS_XGMAC_H
+#define _HNS_XGMAC_H
+
+#define ETH_XGMAC_DUMP_NUM (214)
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
new file mode 100644
index 000000000000..08cef0dfb5db
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -0,0 +1,1642 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/clk.h>
+#include <linux/cpumask.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+
+#include "hnae.h"
+#include "hns_enet.h"
+
+#define NIC_MAX_Q_PER_VF 16
+#define HNS_NIC_TX_TIMEOUT (5 * HZ)
+
+#define SERVICE_TIMER_HZ (1 * HZ)
+
+#define NIC_TX_CLEAN_MAX_NUM 256
+#define NIC_RX_CLEAN_MAX_NUM 64
+
+#define RCB_IRQ_NOT_INITED 0
+#define RCB_IRQ_INITED 1
+
+static void fill_desc(struct hnae_ring *ring, void *priv,
+ int size, dma_addr_t dma, int frag_end,
+ int buf_num, enum hns_desc_type type)
+{
+ struct hnae_desc *desc = &ring->desc[ring->next_to_use];
+ struct hnae_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
+ struct sk_buff *skb;
+ __be16 protocol;
+ u32 ip_offset;
+ u32 asid_bufnum_pid = 0;
+ u32 flag_ipoffset = 0;
+
+ desc_cb->priv = priv;
+ desc_cb->length = size;
+ desc_cb->dma = dma;
+ desc_cb->type = type;
+
+ desc->addr = cpu_to_le64(dma);
+ desc->tx.send_size = cpu_to_le16((u16)size);
+
+ /*config bd buffer end */
+ flag_ipoffset |= 1 << HNS_TXD_VLD_B;
+
+ asid_bufnum_pid |= buf_num << HNS_TXD_BUFNUM_S;
+
+ if (type == DESC_TYPE_SKB) {
+ skb = (struct sk_buff *)priv;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ protocol = skb->protocol;
+ ip_offset = ETH_HLEN;
+
+ /*if it is a SW VLAN check the next protocol*/
+ if (protocol == htons(ETH_P_8021Q)) {
+ ip_offset += VLAN_HLEN;
+ protocol = vlan_get_protocol(skb);
+ skb->protocol = protocol;
+ }
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ flag_ipoffset |= 1 << HNS_TXD_L3CS_B;
+ /* check for tcp/udp header */
+ flag_ipoffset |= 1 << HNS_TXD_L4CS_B;
+
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ /* ipv6 has not l3 cs, check for L4 header */
+ flag_ipoffset |= 1 << HNS_TXD_L4CS_B;
+ }
+
+ flag_ipoffset |= ip_offset << HNS_TXD_IPOFFSET_S;
+ }
+ }
+
+ flag_ipoffset |= frag_end << HNS_TXD_FE_B;
+
+ desc->tx.asid_bufnum_pid = cpu_to_le16(asid_bufnum_pid);
+ desc->tx.flag_ipoffset = cpu_to_le32(flag_ipoffset);
+
+ ring_ptr_move_fw(ring, next_to_use);
+}
+
+static void unfill_desc(struct hnae_ring *ring)
+{
+ ring_ptr_move_bw(ring, next_to_use);
+}
+
+int hns_nic_net_xmit_hw(struct net_device *ndev,
+ struct sk_buff *skb,
+ struct hns_nic_ring_data *ring_data)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct device *dev = priv->dev;
+ struct hnae_ring *ring = ring_data->ring;
+ struct netdev_queue *dev_queue;
+ struct skb_frag_struct *frag;
+ int buf_num;
+ dma_addr_t dma;
+ int size, next_to_use;
+ int i, j;
+ struct sk_buff *new_skb;
+
+ assert(ring->max_desc_num_per_pkt <= ring->desc_num);
+
+ /* no. of segments (plus a header) */
+ buf_num = skb_shinfo(skb)->nr_frags + 1;
+
+ if (unlikely(buf_num > ring->max_desc_num_per_pkt)) {
+ if (ring_space(ring) < 1) {
+ ring->stats.tx_busy++;
+ goto out_net_tx_busy;
+ }
+
+ new_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!new_skb) {
+ ring->stats.sw_err_cnt++;
+ netdev_err(ndev, "no memory to xmit!\n");
+ goto out_err_tx_ok;
+ }
+
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+ buf_num = 1;
+ assert(skb_shinfo(skb)->nr_frags == 1);
+ } else if (buf_num > ring_space(ring)) {
+ ring->stats.tx_busy++;
+ goto out_net_tx_busy;
+ }
+ next_to_use = ring->next_to_use;
+
+ /* fill the first part */
+ size = skb_headlen(skb);
+ dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma)) {
+ netdev_err(ndev, "TX head DMA map failed\n");
+ ring->stats.sw_err_cnt++;
+ goto out_err_tx_ok;
+ }
+ fill_desc(ring, skb, size, dma, buf_num == 1 ? 1 : 0, buf_num,
+ DESC_TYPE_SKB);
+
+ /* fill the fragments */
+ for (i = 1; i < buf_num; i++) {
+ frag = &skb_shinfo(skb)->frags[i - 1];
+ size = skb_frag_size(frag);
+ dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma)) {
+ netdev_err(ndev, "TX frag(%d) DMA map failed\n", i);
+ ring->stats.sw_err_cnt++;
+ goto out_map_frag_fail;
+ }
+ fill_desc(ring, skb_frag_page(frag), size, dma,
+ buf_num - 1 == i ? 1 : 0, buf_num, DESC_TYPE_PAGE);
+ }
+
+ /*complete translate all packets*/
+ dev_queue = netdev_get_tx_queue(ndev, skb->queue_mapping);
+ netdev_tx_sent_queue(dev_queue, skb->len);
+
+ wmb(); /* commit all data before submit */
+ assert(skb->queue_mapping < priv->ae_handle->q_num);
+ hnae_queue_xmit(priv->ae_handle->qs[skb->queue_mapping], buf_num);
+ ring->stats.tx_pkts++;
+ ring->stats.tx_bytes += skb->len;
+
+ return NETDEV_TX_OK;
+
+out_map_frag_fail:
+
+ for (j = i - 1; j > 0; j--) {
+ unfill_desc(ring);
+ next_to_use = ring->next_to_use;
+ dma_unmap_page(dev, ring->desc_cb[next_to_use].dma,
+ ring->desc_cb[next_to_use].length,
+ DMA_TO_DEVICE);
+ }
+
+ unfill_desc(ring);
+ next_to_use = ring->next_to_use;
+ dma_unmap_single(dev, ring->desc_cb[next_to_use].dma,
+ ring->desc_cb[next_to_use].length, DMA_TO_DEVICE);
+
+out_err_tx_ok:
+
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+
+out_net_tx_busy:
+
+ netif_stop_subqueue(ndev, skb->queue_mapping);
+
+ /* Herbert's original patch had:
+ * smp_mb__after_netif_stop_queue();
+ * but since that doesn't exist yet, just open code it.
+ */
+ smp_mb();
+ return NETDEV_TX_BUSY;
+}
+
+/**
+ * hns_nic_get_headlen - determine size of header for RSC/LRO/GRO/FCOE
+ * @data: pointer to the start of the headers
+ * @max: total length of section to find headers in
+ *
+ * This function is meant to determine the length of headers that will
+ * be recognized by hardware for LRO, GRO, and RSC offloads. The main
+ * motivation of doing this is to only perform one pull for IPv4 TCP
+ * packets so that we can do basic things like calculating the gso_size
+ * based on the average data per packet.
+ **/
+static unsigned int hns_nic_get_headlen(unsigned char *data, u32 flag,
+ unsigned int max_size)
+{
+ unsigned char *network;
+ u8 hlen;
+
+ /* this should never happen, but better safe than sorry */
+ if (max_size < ETH_HLEN)
+ return max_size;
+
+ /* initialize network frame pointer */
+ network = data;
+
+ /* set first protocol and move network header forward */
+ network += ETH_HLEN;
+
+ /* handle any vlan tag if present */
+ if (hnae_get_field(flag, HNS_RXD_VLAN_M, HNS_RXD_VLAN_S)
+ == HNS_RX_FLAG_VLAN_PRESENT) {
+ if ((typeof(max_size))(network - data) > (max_size - VLAN_HLEN))
+ return max_size;
+
+ network += VLAN_HLEN;
+ }
+
+ /* handle L3 protocols */
+ if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S)
+ == HNS_RX_FLAG_L3ID_IPV4) {
+ if ((typeof(max_size))(network - data) >
+ (max_size - sizeof(struct iphdr)))
+ return max_size;
+
+ /* access ihl as a u8 to avoid unaligned access on ia64 */
+ hlen = (network[0] & 0x0F) << 2;
+
+ /* verify hlen meets minimum size requirements */
+ if (hlen < sizeof(struct iphdr))
+ return network - data;
+
+ /* record next protocol if header is present */
+ } else if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S)
+ == HNS_RX_FLAG_L3ID_IPV6) {
+ if ((typeof(max_size))(network - data) >
+ (max_size - sizeof(struct ipv6hdr)))
+ return max_size;
+
+ /* record next protocol */
+ hlen = sizeof(struct ipv6hdr);
+ } else {
+ return network - data;
+ }
+
+ /* relocate pointer to start of L4 header */
+ network += hlen;
+
+ /* finally sort out TCP/UDP */
+ if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S)
+ == HNS_RX_FLAG_L4ID_TCP) {
+ if ((typeof(max_size))(network - data) >
+ (max_size - sizeof(struct tcphdr)))
+ return max_size;
+
+ /* access doff as a u8 to avoid unaligned access on ia64 */
+ hlen = (network[12] & 0xF0) >> 2;
+
+ /* verify hlen meets minimum size requirements */
+ if (hlen < sizeof(struct tcphdr))
+ return network - data;
+
+ network += hlen;
+ } else if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S)
+ == HNS_RX_FLAG_L4ID_UDP) {
+ if ((typeof(max_size))(network - data) >
+ (max_size - sizeof(struct udphdr)))
+ return max_size;
+
+ network += sizeof(struct udphdr);
+ }
+
+ /* If everything has gone correctly network should be the
+ * data section of the packet and will be the end of the header.
+ * If not then it probably represents the end of the last recognized
+ * header.
+ */
+ if ((typeof(max_size))(network - data) < max_size)
+ return network - data;
+ else
+ return max_size;
+}
+
+static void
+hns_nic_reuse_page(struct hnae_desc_cb *desc_cb, int tsize, int last_offset)
+{
+ /* avoid re-using remote pages,flag default unreuse */
+ if (likely(page_to_nid(desc_cb->priv) == numa_node_id())) {
+ /* move offset up to the next cache line */
+ desc_cb->page_offset += tsize;
+
+ if (desc_cb->page_offset <= last_offset) {
+ desc_cb->reuse_flag = 1;
+ /* bump ref count on page before it is given*/
+ get_page(desc_cb->priv);
+ }
+ }
+}
+
+static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data,
+ struct sk_buff **out_skb, int *out_bnum)
+{
+ struct hnae_ring *ring = ring_data->ring;
+ struct net_device *ndev = ring_data->napi.dev;
+ struct sk_buff *skb;
+ struct hnae_desc *desc;
+ struct hnae_desc_cb *desc_cb;
+ unsigned char *va;
+ int bnum, length, size, i, truesize, last_offset;
+ int pull_len;
+ u32 bnum_flag;
+
+ last_offset = hnae_page_size(ring) - hnae_buf_size(ring);
+ desc = &ring->desc[ring->next_to_clean];
+ desc_cb = &ring->desc_cb[ring->next_to_clean];
+ length = le16_to_cpu(desc->rx.pkt_len);
+ bnum_flag = le32_to_cpu(desc->rx.ipoff_bnum_pid_flag);
+ bnum = hnae_get_field(bnum_flag, HNS_RXD_BUFNUM_M, HNS_RXD_BUFNUM_S);
+ *out_bnum = bnum;
+ va = (unsigned char *)desc_cb->buf + desc_cb->page_offset;
+
+ skb = *out_skb = napi_alloc_skb(&ring_data->napi, HNS_RX_HEAD_SIZE);
+ if (unlikely(!skb)) {
+ netdev_err(ndev, "alloc rx skb fail\n");
+ ring->stats.sw_err_cnt++;
+ return -ENOMEM;
+ }
+
+ if (length <= HNS_RX_HEAD_SIZE) {
+ memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
+
+ /* we can reuse buffer as-is, just make sure it is local */
+ if (likely(page_to_nid(desc_cb->priv) == numa_node_id()))
+ desc_cb->reuse_flag = 1;
+ else /* this page cannot be reused so discard it */
+ put_page(desc_cb->priv);
+
+ ring_ptr_move_fw(ring, next_to_clean);
+
+ if (unlikely(bnum != 1)) { /* check err*/
+ *out_bnum = 1;
+ goto out_bnum_err;
+ }
+ } else {
+ ring->stats.seg_pkt_cnt++;
+
+ pull_len = hns_nic_get_headlen(va, bnum_flag, HNS_RX_HEAD_SIZE);
+ memcpy(__skb_put(skb, pull_len), va,
+ ALIGN(pull_len, sizeof(long)));
+
+ size = le16_to_cpu(desc->rx.size);
+ truesize = ALIGN(size, L1_CACHE_BYTES);
+ skb_add_rx_frag(skb, 0, desc_cb->priv,
+ desc_cb->page_offset + pull_len,
+ size - pull_len, truesize - pull_len);
+
+ hns_nic_reuse_page(desc_cb, truesize, last_offset);
+ ring_ptr_move_fw(ring, next_to_clean);
+
+ if (unlikely(bnum >= (int)MAX_SKB_FRAGS)) { /* check err*/
+ *out_bnum = 1;
+ goto out_bnum_err;
+ }
+ for (i = 1; i < bnum; i++) {
+ desc = &ring->desc[ring->next_to_clean];
+ desc_cb = &ring->desc_cb[ring->next_to_clean];
+ size = le16_to_cpu(desc->rx.size);
+ truesize = ALIGN(size, L1_CACHE_BYTES);
+ skb_add_rx_frag(skb, i, desc_cb->priv,
+ desc_cb->page_offset,
+ size, truesize);
+
+ hns_nic_reuse_page(desc_cb, truesize, last_offset);
+ ring_ptr_move_fw(ring, next_to_clean);
+ }
+ }
+
+ /* check except process, free skb and jump the desc */
+ if (unlikely((!bnum) || (bnum > ring->max_desc_num_per_pkt))) {
+out_bnum_err:
+ *out_bnum = *out_bnum ? *out_bnum : 1; /* ntc moved,cannot 0*/
+ netdev_err(ndev, "invalid bnum(%d,%d,%d,%d),%016llx,%016llx\n",
+ bnum, ring->max_desc_num_per_pkt,
+ length, (int)MAX_SKB_FRAGS,
+ ((u64 *)desc)[0], ((u64 *)desc)[1]);
+ ring->stats.err_bd_num++;
+ dev_kfree_skb_any(skb);
+ return -EDOM;
+ }
+
+ bnum_flag = le32_to_cpu(desc->rx.ipoff_bnum_pid_flag);
+
+ if (unlikely(!hnae_get_bit(bnum_flag, HNS_RXD_VLD_B))) {
+ netdev_err(ndev, "no valid bd,%016llx,%016llx\n",
+ ((u64 *)desc)[0], ((u64 *)desc)[1]);
+ ring->stats.non_vld_descs++;
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+
+ if (unlikely((!desc->rx.pkt_len) ||
+ hnae_get_bit(bnum_flag, HNS_RXD_DROP_B))) {
+ ring->stats.err_pkt_len++;
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
+ }
+
+ if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L2E_B))) {
+ ring->stats.l2_err++;
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
+ }
+
+ ring->stats.rx_pkts++;
+ ring->stats.rx_bytes += skb->len;
+
+ if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L3E_B) ||
+ hnae_get_bit(bnum_flag, HNS_RXD_L4E_B))) {
+ ring->stats.l3l4_csum_err++;
+ return 0;
+ }
+
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ return 0;
+}
+
+static void
+hns_nic_alloc_rx_buffers(struct hns_nic_ring_data *ring_data, int cleand_count)
+{
+ int i, ret;
+ struct hnae_desc_cb res_cbs;
+ struct hnae_desc_cb *desc_cb;
+ struct hnae_ring *ring = ring_data->ring;
+ struct net_device *ndev = ring_data->napi.dev;
+
+ for (i = 0; i < cleand_count; i++) {
+ desc_cb = &ring->desc_cb[ring->next_to_use];
+ if (desc_cb->reuse_flag) {
+ ring->stats.reuse_pg_cnt++;
+ hnae_reuse_buffer(ring, ring->next_to_use);
+ } else {
+ ret = hnae_reserve_buffer_map(ring, &res_cbs);
+ if (ret) {
+ ring->stats.sw_err_cnt++;
+ netdev_err(ndev, "hnae reserve buffer map failed.\n");
+ break;
+ }
+ hnae_replace_buffer(ring, ring->next_to_use, &res_cbs);
+ }
+
+ ring_ptr_move_fw(ring, next_to_use);
+ }
+
+ wmb(); /* make all data has been write before submit */
+ writel_relaxed(i, ring->io_base + RCB_REG_HEAD);
+}
+
+/* return error number for error or number of desc left to take
+ */
+static void hns_nic_rx_up_pro(struct hns_nic_ring_data *ring_data,
+ struct sk_buff *skb)
+{
+ struct net_device *ndev = ring_data->napi.dev;
+
+ skb->protocol = eth_type_trans(skb, ndev);
+ (void)napi_gro_receive(&ring_data->napi, skb);
+ ndev->last_rx = jiffies;
+}
+
+static int hns_nic_rx_poll_one(struct hns_nic_ring_data *ring_data,
+ int budget, void *v)
+{
+ struct hnae_ring *ring = ring_data->ring;
+ struct sk_buff *skb;
+ int num, bnum, ex_num;
+#define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
+ int recv_pkts, recv_bds, clean_count, err;
+
+ num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
+ rmb(); /* make sure num taken effect before the other data is touched */
+
+ recv_pkts = 0, recv_bds = 0, clean_count = 0;
+recv:
+ while (recv_pkts < budget && recv_bds < num) {
+ /* reuse or realloc buffers*/
+ if (clean_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
+ hns_nic_alloc_rx_buffers(ring_data, clean_count);
+ clean_count = 0;
+ }
+
+ /* poll one pkg*/
+ err = hns_nic_poll_rx_skb(ring_data, &skb, &bnum);
+ if (unlikely(!skb)) /* this fault cannot be repaired */
+ break;
+
+ recv_bds += bnum;
+ clean_count += bnum;
+ if (unlikely(err)) { /* do jump the err */
+ recv_pkts++;
+ continue;
+ }
+
+ /* do update ip stack process*/
+ ((void (*)(struct hns_nic_ring_data *, struct sk_buff *))v)(
+ ring_data, skb);
+ recv_pkts++;
+ }
+
+ /* make all data has been write before submit */
+ if (clean_count > 0) {
+ hns_nic_alloc_rx_buffers(ring_data, clean_count);
+ clean_count = 0;
+ }
+
+ if (recv_pkts < budget) {
+ ex_num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
+ rmb(); /*complete read rx ring bd number*/
+ if (ex_num > 0) {
+ num += ex_num;
+ goto recv;
+ }
+ }
+
+ return recv_pkts;
+}
+
+static void hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data)
+{
+ struct hnae_ring *ring = ring_data->ring;
+ int num = 0;
+
+ /* for hardware bug fixed */
+ num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
+
+ if (num > 0) {
+ ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
+ ring_data->ring, 1);
+
+ napi_schedule(&ring_data->napi);
+ }
+}
+
+static inline void hns_nic_reclaim_one_desc(struct hnae_ring *ring,
+ int *bytes, int *pkts)
+{
+ struct hnae_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean];
+
+ (*pkts) += (desc_cb->type == DESC_TYPE_SKB);
+ (*bytes) += desc_cb->length;
+ /* desc_cb will be cleaned, after hnae_free_buffer_detach*/
+ hnae_free_buffer_detach(ring, ring->next_to_clean);
+
+ ring_ptr_move_fw(ring, next_to_clean);
+}
+
+static int is_valid_clean_head(struct hnae_ring *ring, int h)
+{
+ int u = ring->next_to_use;
+ int c = ring->next_to_clean;
+
+ if (unlikely(h > ring->desc_num))
+ return 0;
+
+ assert(u > 0 && u < ring->desc_num);
+ assert(c > 0 && c < ring->desc_num);
+ assert(u != c && h != c); /* must be checked before call this func */
+
+ return u > c ? (h > c && h <= u) : (h > c || h <= u);
+}
+
+/* netif_tx_lock will turn down the performance, set only when necessary */
+#ifdef CONFIG_NET_POLL_CONTROLLER
+#define NETIF_TX_LOCK(ndev) netif_tx_lock(ndev)
+#define NETIF_TX_UNLOCK(ndev) netif_tx_unlock(ndev)
+#else
+#define NETIF_TX_LOCK(ndev)
+#define NETIF_TX_UNLOCK(ndev)
+#endif
+/* reclaim all desc in one budget
+ * return error or number of desc left
+ */
+static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data,
+ int budget, void *v)
+{
+ struct hnae_ring *ring = ring_data->ring;
+ struct net_device *ndev = ring_data->napi.dev;
+ struct netdev_queue *dev_queue;
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ int head;
+ int bytes, pkts;
+
+ NETIF_TX_LOCK(ndev);
+
+ head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
+ rmb(); /* make sure head is ready before touch any data */
+
+ if (is_ring_empty(ring) || head == ring->next_to_clean) {
+ NETIF_TX_UNLOCK(ndev);
+ return 0; /* no data to poll */
+ }
+
+ if (!is_valid_clean_head(ring, head)) {
+ netdev_err(ndev, "wrong head (%d, %d-%d)\n", head,
+ ring->next_to_use, ring->next_to_clean);
+ ring->stats.io_err_cnt++;
+ NETIF_TX_UNLOCK(ndev);
+ return -EIO;
+ }
+
+ bytes = 0;
+ pkts = 0;
+ while (head != ring->next_to_clean)
+ hns_nic_reclaim_one_desc(ring, &bytes, &pkts);
+
+ NETIF_TX_UNLOCK(ndev);
+
+ dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
+ netdev_tx_completed_queue(dev_queue, pkts, bytes);
+
+ if (unlikely(pkts && netif_carrier_ok(ndev) &&
+ (ring_space(ring) >= ring->max_desc_num_per_pkt * 2))) {
+ /* Make sure that anybody stopping the queue after this
+ * sees the new next_to_clean.
+ */
+ smp_mb();
+ if (netif_tx_queue_stopped(dev_queue) &&
+ !test_bit(NIC_STATE_DOWN, &priv->state)) {
+ netif_tx_wake_queue(dev_queue);
+ ring->stats.restart_queue++;
+ }
+ }
+ return 0;
+}
+
+static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data)
+{
+ struct hnae_ring *ring = ring_data->ring;
+ int head = ring->next_to_clean;
+
+ /* for hardware bug fixed */
+ head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
+
+ if (head != ring->next_to_clean) {
+ ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
+ ring_data->ring, 1);
+
+ napi_schedule(&ring_data->napi);
+ }
+}
+
+static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data)
+{
+ struct hnae_ring *ring = ring_data->ring;
+ struct net_device *ndev = ring_data->napi.dev;
+ struct netdev_queue *dev_queue;
+ int head;
+ int bytes, pkts;
+
+ NETIF_TX_LOCK(ndev);
+
+ head = ring->next_to_use; /* ntu :soft setted ring position*/
+ bytes = 0;
+ pkts = 0;
+ while (head != ring->next_to_clean)
+ hns_nic_reclaim_one_desc(ring, &bytes, &pkts);
+
+ NETIF_TX_UNLOCK(ndev);
+
+ dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
+ netdev_tx_reset_queue(dev_queue);
+}
+
+static int hns_nic_common_poll(struct napi_struct *napi, int budget)
+{
+ struct hns_nic_ring_data *ring_data =
+ container_of(napi, struct hns_nic_ring_data, napi);
+ int clean_complete = ring_data->poll_one(
+ ring_data, budget, ring_data->ex_process);
+
+ if (clean_complete >= 0 && clean_complete < budget) {
+ napi_complete(napi);
+ ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
+ ring_data->ring, 0);
+
+ ring_data->fini_process(ring_data);
+ }
+
+ return clean_complete;
+}
+
+static irqreturn_t hns_irq_handle(int irq, void *dev)
+{
+ struct hns_nic_ring_data *ring_data = (struct hns_nic_ring_data *)dev;
+
+ ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
+ ring_data->ring, 1);
+ napi_schedule(&ring_data->napi);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ *hns_nic_adjust_link - adjust net work mode by the phy stat or new param
+ *@ndev: net device
+ */
+static void hns_nic_adjust_link(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ h->dev->ops->adjust_link(h, ndev->phydev->speed, ndev->phydev->duplex);
+}
+
+/**
+ *hns_nic_init_phy - init phy
+ *@ndev: net device
+ *@h: ae handle
+ * Return 0 on success, negative on failure
+ */
+int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct phy_device *phy_dev = NULL;
+
+ if (!h->phy_node)
+ return 0;
+
+ if (h->phy_if != PHY_INTERFACE_MODE_XGMII)
+ phy_dev = of_phy_connect(ndev, h->phy_node,
+ hns_nic_adjust_link, 0, h->phy_if);
+ else
+ phy_dev = of_phy_attach(ndev, h->phy_node, 0, h->phy_if);
+
+ if (unlikely(!phy_dev) || IS_ERR(phy_dev))
+ return !phy_dev ? -ENODEV : PTR_ERR(phy_dev);
+
+ phy_dev->supported &= h->if_support;
+ phy_dev->advertising = phy_dev->supported;
+
+ if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
+ phy_dev->autoneg = false;
+
+ priv->phy = phy_dev;
+
+ return 0;
+}
+
+static int hns_nic_ring_open(struct net_device *netdev, int idx)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ napi_enable(&priv->ring_data[idx].napi);
+
+ enable_irq(priv->ring_data[idx].ring->irq);
+ h->dev->ops->toggle_ring_irq(priv->ring_data[idx].ring, 0);
+
+ return 0;
+}
+
+static int hns_nic_net_set_mac_address(struct net_device *ndev, void *p)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ struct sockaddr *mac_addr = p;
+ int ret;
+
+ if (!mac_addr || !is_valid_ether_addr((const u8 *)mac_addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ ret = h->dev->ops->set_mac_addr(h, mac_addr->sa_data);
+ if (ret) {
+ netdev_err(ndev, "set_mac_address fail, ret=%d!\n", ret);
+ return ret;
+ }
+
+ memcpy(ndev->dev_addr, mac_addr->sa_data, ndev->addr_len);
+
+ return 0;
+}
+
+void hns_nic_update_stats(struct net_device *netdev)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ h->dev->ops->update_stats(h, &netdev->stats);
+}
+
+/* set mac addr if it is configed. or leave it to the AE driver */
+static void hns_init_mac_addr(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct device_node *node = priv->dev->of_node;
+ const void *mac_addr_temp;
+
+ mac_addr_temp = of_get_mac_address(node);
+ if (mac_addr_temp && is_valid_ether_addr(mac_addr_temp)) {
+ memcpy(ndev->dev_addr, mac_addr_temp, ndev->addr_len);
+ } else {
+ eth_hw_addr_random(ndev);
+ dev_warn(priv->dev, "No valid mac, use random mac %pM",
+ ndev->dev_addr);
+ }
+}
+
+static void hns_nic_ring_close(struct net_device *netdev, int idx)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ h->dev->ops->toggle_ring_irq(priv->ring_data[idx].ring, 1);
+ disable_irq(priv->ring_data[idx].ring->irq);
+
+ napi_disable(&priv->ring_data[idx].napi);
+}
+
+static int hns_nic_init_irq(struct hns_nic_priv *priv)
+{
+ struct hnae_handle *h = priv->ae_handle;
+ struct hns_nic_ring_data *rd;
+ int i;
+ int ret;
+ int cpu;
+ cpumask_t mask;
+
+ for (i = 0; i < h->q_num * 2; i++) {
+ rd = &priv->ring_data[i];
+
+ if (rd->ring->irq_init_flag == RCB_IRQ_INITED)
+ break;
+
+ snprintf(rd->ring->ring_name, RCB_RING_NAME_LEN,
+ "%s-%s%d", priv->netdev->name,
+ (i < h->q_num ? "tx" : "rx"), rd->queue_index);
+
+ rd->ring->ring_name[RCB_RING_NAME_LEN - 1] = '\0';
+
+ ret = request_irq(rd->ring->irq,
+ hns_irq_handle, 0, rd->ring->ring_name, rd);
+ if (ret) {
+ netdev_err(priv->netdev, "request irq(%d) fail\n",
+ rd->ring->irq);
+ return ret;
+ }
+ disable_irq(rd->ring->irq);
+ rd->ring->irq_init_flag = RCB_IRQ_INITED;
+
+ /*set cpu affinity*/
+ if (cpu_online(rd->queue_index)) {
+ cpumask_clear(&mask);
+ cpu = rd->queue_index;
+ cpumask_set_cpu(cpu, &mask);
+ irq_set_affinity_hint(rd->ring->irq, &mask);
+ }
+ }
+
+ return 0;
+}
+
+static int hns_nic_net_up(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ int i, j, k;
+ int ret;
+
+ ret = hns_nic_init_irq(priv);
+ if (ret != 0) {
+ netdev_err(ndev, "hns init irq failed! ret=%d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < h->q_num * 2; i++) {
+ ret = hns_nic_ring_open(ndev, i);
+ if (ret)
+ goto out_has_some_queues;
+ }
+
+ for (k = 0; k < h->q_num; k++)
+ h->dev->ops->toggle_queue_status(h->qs[k], 1);
+
+ ret = h->dev->ops->set_mac_addr(h, ndev->dev_addr);
+ if (ret)
+ goto out_set_mac_addr_err;
+
+ ret = h->dev->ops->start ? h->dev->ops->start(h) : 0;
+ if (ret)
+ goto out_start_err;
+
+ if (priv->phy)
+ phy_start(priv->phy);
+
+ clear_bit(NIC_STATE_DOWN, &priv->state);
+ (void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ);
+
+ return 0;
+
+out_start_err:
+ netif_stop_queue(ndev);
+out_set_mac_addr_err:
+ for (k = 0; k < h->q_num; k++)
+ h->dev->ops->toggle_queue_status(h->qs[k], 0);
+out_has_some_queues:
+ for (j = i - 1; j >= 0; j--)
+ hns_nic_ring_close(ndev, j);
+
+ set_bit(NIC_STATE_DOWN, &priv->state);
+
+ return ret;
+}
+
+static void hns_nic_net_down(struct net_device *ndev)
+{
+ int i;
+ struct hnae_ae_ops *ops;
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+
+ if (test_and_set_bit(NIC_STATE_DOWN, &priv->state))
+ return;
+
+ (void)del_timer_sync(&priv->service_timer);
+ netif_tx_stop_all_queues(ndev);
+ netif_carrier_off(ndev);
+ netif_tx_disable(ndev);
+ priv->link = 0;
+
+ if (priv->phy)
+ phy_stop(priv->phy);
+
+ ops = priv->ae_handle->dev->ops;
+
+ if (ops->stop)
+ ops->stop(priv->ae_handle);
+
+ netif_tx_stop_all_queues(ndev);
+
+ for (i = priv->ae_handle->q_num - 1; i >= 0; i--) {
+ hns_nic_ring_close(ndev, i);
+ hns_nic_ring_close(ndev, i + priv->ae_handle->q_num);
+
+ /* clean tx buffers*/
+ hns_nic_tx_clr_all_bufs(priv->ring_data + i);
+ }
+}
+
+void hns_nic_net_reset(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *handle = priv->ae_handle;
+
+ while (test_and_set_bit(NIC_STATE_RESETTING, &priv->state))
+ usleep_range(1000, 2000);
+
+ (void)hnae_reinit_handle(handle);
+
+ clear_bit(NIC_STATE_RESETTING, &priv->state);
+}
+
+void hns_nic_net_reinit(struct net_device *netdev)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+
+ priv->netdev->trans_start = jiffies;
+ while (test_and_set_bit(NIC_STATE_REINITING, &priv->state))
+ usleep_range(1000, 2000);
+
+ hns_nic_net_down(netdev);
+ hns_nic_net_reset(netdev);
+ (void)hns_nic_net_up(netdev);
+ clear_bit(NIC_STATE_REINITING, &priv->state);
+}
+
+static int hns_nic_net_open(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ int ret;
+
+ if (test_bit(NIC_STATE_TESTING, &priv->state))
+ return -EBUSY;
+
+ priv->link = 0;
+ netif_carrier_off(ndev);
+
+ ret = netif_set_real_num_tx_queues(ndev, h->q_num);
+ if (ret < 0) {
+ netdev_err(ndev, "netif_set_real_num_tx_queues fail, ret=%d!\n",
+ ret);
+ return ret;
+ }
+
+ ret = netif_set_real_num_rx_queues(ndev, h->q_num);
+ if (ret < 0) {
+ netdev_err(ndev,
+ "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
+ return ret;
+ }
+
+ ret = hns_nic_net_up(ndev);
+ if (ret) {
+ netdev_err(ndev,
+ "hns net up fail, ret=%d!\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hns_nic_net_stop(struct net_device *ndev)
+{
+ hns_nic_net_down(ndev);
+
+ return 0;
+}
+
+static void hns_tx_timeout_reset(struct hns_nic_priv *priv);
+static void hns_nic_net_timeout(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+
+ hns_tx_timeout_reset(priv);
+}
+
+static int hns_nic_do_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ int cmd)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct phy_device *phy_dev = priv->phy;
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ if (!phy_dev)
+ return -ENOTSUPP;
+
+ return phy_mii_ioctl(phy_dev, ifr, cmd);
+}
+
+/* use only for netconsole to poll with the device without interrupt */
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void hns_nic_poll_controller(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ unsigned long flags;
+ int i;
+
+ local_irq_save(flags);
+ for (i = 0; i < priv->ae_handle->q_num * 2; i++)
+ napi_schedule(&priv->ring_data[i].napi);
+ local_irq_restore(flags);
+}
+#endif
+
+static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb,
+ struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ assert(skb->queue_mapping < ndev->ae_handle->q_num);
+ ret = hns_nic_net_xmit_hw(ndev, skb,
+ &tx_ring_data(priv, skb->queue_mapping));
+ if (ret == NETDEV_TX_OK) {
+ ndev->trans_start = jiffies;
+ ndev->stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ }
+ return (netdev_tx_t)ret;
+}
+
+static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ int ret;
+
+ /* MTU < 68 is an error and causes problems on some kernels */
+ if (new_mtu < 68)
+ return -EINVAL;
+
+ if (!h->dev->ops->set_mtu)
+ return -ENOTSUPP;
+
+ if (netif_running(ndev)) {
+ (void)hns_nic_net_stop(ndev);
+ msleep(100);
+
+ ret = h->dev->ops->set_mtu(h, new_mtu);
+ if (ret)
+ netdev_err(ndev, "set mtu fail, return value %d\n",
+ ret);
+
+ if (hns_nic_net_open(ndev))
+ netdev_err(ndev, "hns net open fail\n");
+ } else {
+ ret = h->dev->ops->set_mtu(h, new_mtu);
+ }
+
+ if (!ret)
+ ndev->mtu = new_mtu;
+
+ return ret;
+}
+
+/**
+ * nic_set_multicast_list - set mutl mac address
+ * @netdev: net device
+ * @p: mac address
+ *
+ * return void
+ */
+void hns_set_multicast_list(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ struct netdev_hw_addr *ha = NULL;
+
+ if (!h) {
+ netdev_err(ndev, "hnae handle is null\n");
+ return;
+ }
+
+ if (h->dev->ops->set_mc_addr) {
+ netdev_for_each_mc_addr(ha, ndev)
+ if (h->dev->ops->set_mc_addr(h, ha->addr))
+ netdev_err(ndev, "set multicast fail\n");
+ }
+}
+
+void hns_nic_set_rx_mode(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ if (h->dev->ops->set_promisc_mode) {
+ if (ndev->flags & IFF_PROMISC)
+ h->dev->ops->set_promisc_mode(h, 1);
+ else
+ h->dev->ops->set_promisc_mode(h, 0);
+ }
+
+ hns_set_multicast_list(ndev);
+}
+
+struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev,
+ struct rtnl_link_stats64 *stats)
+{
+ int idx = 0;
+ u64 tx_bytes = 0;
+ u64 rx_bytes = 0;
+ u64 tx_pkts = 0;
+ u64 rx_pkts = 0;
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ for (idx = 0; idx < h->q_num; idx++) {
+ tx_bytes += h->qs[idx]->tx_ring.stats.tx_bytes;
+ tx_pkts += h->qs[idx]->tx_ring.stats.tx_pkts;
+ rx_bytes += h->qs[idx]->rx_ring.stats.rx_bytes;
+ rx_pkts += h->qs[idx]->rx_ring.stats.rx_pkts;
+ }
+
+ stats->tx_bytes = tx_bytes;
+ stats->tx_packets = tx_pkts;
+ stats->rx_bytes = rx_bytes;
+ stats->rx_packets = rx_pkts;
+
+ stats->rx_errors = ndev->stats.rx_errors;
+ stats->multicast = ndev->stats.multicast;
+ stats->rx_length_errors = ndev->stats.rx_length_errors;
+ stats->rx_crc_errors = ndev->stats.rx_crc_errors;
+ stats->rx_missed_errors = ndev->stats.rx_missed_errors;
+
+ stats->tx_errors = ndev->stats.tx_errors;
+ stats->rx_dropped = ndev->stats.rx_dropped;
+ stats->tx_dropped = ndev->stats.tx_dropped;
+ stats->collisions = ndev->stats.collisions;
+ stats->rx_over_errors = ndev->stats.rx_over_errors;
+ stats->rx_frame_errors = ndev->stats.rx_frame_errors;
+ stats->rx_fifo_errors = ndev->stats.rx_fifo_errors;
+ stats->tx_aborted_errors = ndev->stats.tx_aborted_errors;
+ stats->tx_carrier_errors = ndev->stats.tx_carrier_errors;
+ stats->tx_fifo_errors = ndev->stats.tx_fifo_errors;
+ stats->tx_heartbeat_errors = ndev->stats.tx_heartbeat_errors;
+ stats->tx_window_errors = ndev->stats.tx_window_errors;
+ stats->rx_compressed = ndev->stats.rx_compressed;
+ stats->tx_compressed = ndev->stats.tx_compressed;
+
+ return stats;
+}
+
+static const struct net_device_ops hns_nic_netdev_ops = {
+ .ndo_open = hns_nic_net_open,
+ .ndo_stop = hns_nic_net_stop,
+ .ndo_start_xmit = hns_nic_net_xmit,
+ .ndo_tx_timeout = hns_nic_net_timeout,
+ .ndo_set_mac_address = hns_nic_net_set_mac_address,
+ .ndo_change_mtu = hns_nic_change_mtu,
+ .ndo_do_ioctl = hns_nic_do_ioctl,
+ .ndo_get_stats64 = hns_nic_get_stats64,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = hns_nic_poll_controller,
+#endif
+ .ndo_set_rx_mode = hns_nic_set_rx_mode,
+};
+
+static void hns_nic_update_link_status(struct net_device *netdev)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+
+ struct hnae_handle *h = priv->ae_handle;
+ int state = 1;
+
+ if (priv->phy) {
+ if (!genphy_update_link(priv->phy))
+ state = priv->phy->link;
+ else
+ state = 0;
+ }
+ state = state && h->dev->ops->get_status(h);
+
+ if (state != priv->link) {
+ if (state) {
+ netif_carrier_on(netdev);
+ netif_tx_wake_all_queues(netdev);
+ netdev_info(netdev, "link up\n");
+ } else {
+ netif_carrier_off(netdev);
+ netdev_info(netdev, "link down\n");
+ }
+ priv->link = state;
+ }
+}
+
+/* for dumping key regs*/
+static void hns_nic_dump(struct hns_nic_priv *priv)
+{
+ struct hnae_handle *h = priv->ae_handle;
+ struct hnae_ae_ops *ops = h->dev->ops;
+ u32 *data, reg_num, i;
+
+ if (ops->get_regs_len && ops->get_regs) {
+ reg_num = ops->get_regs_len(priv->ae_handle);
+ reg_num = (reg_num + 3ul) & ~3ul;
+ data = kcalloc(reg_num, sizeof(u32), GFP_KERNEL);
+ if (data) {
+ ops->get_regs(priv->ae_handle, data);
+ for (i = 0; i < reg_num; i += 4)
+ pr_info("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ i, data[i], data[i + 1],
+ data[i + 2], data[i + 3]);
+ kfree(data);
+ }
+ }
+
+ for (i = 0; i < h->q_num; i++) {
+ pr_info("tx_queue%d_next_to_clean:%d\n",
+ i, h->qs[i]->tx_ring.next_to_clean);
+ pr_info("tx_queue%d_next_to_use:%d\n",
+ i, h->qs[i]->tx_ring.next_to_use);
+ pr_info("rx_queue%d_next_to_clean:%d\n",
+ i, h->qs[i]->rx_ring.next_to_clean);
+ pr_info("rx_queue%d_next_to_use:%d\n",
+ i, h->qs[i]->rx_ring.next_to_use);
+ }
+}
+
+/* for resetting suntask*/
+static void hns_nic_reset_subtask(struct hns_nic_priv *priv)
+{
+ enum hnae_port_type type = priv->ae_handle->port_type;
+
+ if (!test_bit(NIC_STATE2_RESET_REQUESTED, &priv->state))
+ return;
+ clear_bit(NIC_STATE2_RESET_REQUESTED, &priv->state);
+
+ /* If we're already down, removing or resetting, just bail */
+ if (test_bit(NIC_STATE_DOWN, &priv->state) ||
+ test_bit(NIC_STATE_REMOVING, &priv->state) ||
+ test_bit(NIC_STATE_RESETTING, &priv->state))
+ return;
+
+ hns_nic_dump(priv);
+ netdev_info(priv->netdev, "Reset %s port\n",
+ (type == HNAE_PORT_DEBUG ? "debug" : "business"));
+
+ rtnl_lock();
+ /* put off any impending NetWatchDogTimeout */
+ priv->netdev->trans_start = jiffies;
+
+ if (type == HNAE_PORT_DEBUG)
+ hns_nic_net_reinit(priv->netdev);
+ rtnl_unlock();
+}
+
+/* for doing service complete*/
+static void hns_nic_service_event_complete(struct hns_nic_priv *priv)
+{
+ assert(!test_bit(NIC_STATE_SERVICE_SCHED, &priv->state));
+
+ smp_mb__before_atomic();
+ clear_bit(NIC_STATE_SERVICE_SCHED, &priv->state);
+}
+
+static void hns_nic_service_task(struct work_struct *work)
+{
+ struct hns_nic_priv *priv
+ = container_of(work, struct hns_nic_priv, service_task);
+ struct hnae_handle *h = priv->ae_handle;
+
+ hns_nic_update_link_status(priv->netdev);
+ h->dev->ops->update_led_status(h);
+ hns_nic_update_stats(priv->netdev);
+
+ hns_nic_reset_subtask(priv);
+ hns_nic_service_event_complete(priv);
+}
+
+static void hns_nic_task_schedule(struct hns_nic_priv *priv)
+{
+ if (!test_bit(NIC_STATE_DOWN, &priv->state) &&
+ !test_bit(NIC_STATE_REMOVING, &priv->state) &&
+ !test_and_set_bit(NIC_STATE_SERVICE_SCHED, &priv->state))
+ (void)schedule_work(&priv->service_task);
+}
+
+static void hns_nic_service_timer(unsigned long data)
+{
+ struct hns_nic_priv *priv = (struct hns_nic_priv *)data;
+
+ (void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ);
+
+ hns_nic_task_schedule(priv);
+}
+
+/**
+ * hns_tx_timeout_reset - initiate reset due to Tx timeout
+ * @priv: driver private struct
+ **/
+static void hns_tx_timeout_reset(struct hns_nic_priv *priv)
+{
+ /* Do the reset outside of interrupt context */
+ if (!test_bit(NIC_STATE_DOWN, &priv->state)) {
+ set_bit(NIC_STATE2_RESET_REQUESTED, &priv->state);
+ netdev_warn(priv->netdev,
+ "initiating reset due to tx timeout(%llu,0x%lx)\n",
+ priv->tx_timeout_count, priv->state);
+ priv->tx_timeout_count++;
+ hns_nic_task_schedule(priv);
+ }
+}
+
+static int hns_nic_init_ring_data(struct hns_nic_priv *priv)
+{
+ struct hnae_handle *h = priv->ae_handle;
+ struct hns_nic_ring_data *rd;
+ int i;
+
+ if (h->q_num > NIC_MAX_Q_PER_VF) {
+ netdev_err(priv->netdev, "too much queue (%d)\n", h->q_num);
+ return -EINVAL;
+ }
+
+ priv->ring_data = kzalloc(h->q_num * sizeof(*priv->ring_data) * 2,
+ GFP_KERNEL);
+ if (!priv->ring_data)
+ return -ENOMEM;
+
+ for (i = 0; i < h->q_num; i++) {
+ rd = &priv->ring_data[i];
+ rd->queue_index = i;
+ rd->ring = &h->qs[i]->tx_ring;
+ rd->poll_one = hns_nic_tx_poll_one;
+ rd->fini_process = hns_nic_tx_fini_pro;
+
+ netif_napi_add(priv->netdev, &rd->napi,
+ hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM);
+ rd->ring->irq_init_flag = RCB_IRQ_NOT_INITED;
+ }
+ for (i = h->q_num; i < h->q_num * 2; i++) {
+ rd = &priv->ring_data[i];
+ rd->queue_index = i - h->q_num;
+ rd->ring = &h->qs[i - h->q_num]->rx_ring;
+ rd->poll_one = hns_nic_rx_poll_one;
+ rd->ex_process = hns_nic_rx_up_pro;
+ rd->fini_process = hns_nic_rx_fini_pro;
+
+ netif_napi_add(priv->netdev, &rd->napi,
+ hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM);
+ rd->ring->irq_init_flag = RCB_IRQ_NOT_INITED;
+ }
+
+ return 0;
+}
+
+static void hns_nic_uninit_ring_data(struct hns_nic_priv *priv)
+{
+ struct hnae_handle *h = priv->ae_handle;
+ int i;
+
+ for (i = 0; i < h->q_num * 2; i++) {
+ netif_napi_del(&priv->ring_data[i].napi);
+ if (priv->ring_data[i].ring->irq_init_flag == RCB_IRQ_INITED) {
+ irq_set_affinity_hint(priv->ring_data[i].ring->irq,
+ NULL);
+ free_irq(priv->ring_data[i].ring->irq,
+ &priv->ring_data[i]);
+ }
+
+ priv->ring_data[i].ring->irq_init_flag = RCB_IRQ_NOT_INITED;
+ }
+ kfree(priv->ring_data);
+}
+
+static int hns_nic_try_get_ae(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h;
+ int ret;
+
+ h = hnae_get_handle(&priv->netdev->dev,
+ priv->ae_name, priv->port_id, NULL);
+ if (IS_ERR_OR_NULL(h)) {
+ ret = PTR_ERR(h);
+ dev_dbg(priv->dev, "has not handle, register notifier!\n");
+ goto out;
+ }
+ priv->ae_handle = h;
+
+ ret = hns_nic_init_phy(ndev, h);
+ if (ret) {
+ dev_err(priv->dev, "probe phy device fail!\n");
+ goto out_init_phy;
+ }
+
+ ret = hns_nic_init_ring_data(priv);
+ if (ret) {
+ ret = -ENOMEM;
+ goto out_init_ring_data;
+ }
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ dev_err(priv->dev, "probe register netdev fail!\n");
+ goto out_reg_ndev_fail;
+ }
+ return 0;
+
+out_reg_ndev_fail:
+ hns_nic_uninit_ring_data(priv);
+ priv->ring_data = NULL;
+out_init_phy:
+out_init_ring_data:
+ hnae_put_handle(priv->ae_handle);
+ priv->ae_handle = NULL;
+out:
+ return ret;
+}
+
+static int hns_nic_notifier_action(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct hns_nic_priv *priv =
+ container_of(nb, struct hns_nic_priv, notifier_block);
+
+ assert(action == HNAE_AE_REGISTER);
+
+ if (!hns_nic_try_get_ae(priv->netdev)) {
+ hnae_unregister_notifier(&priv->notifier_block);
+ priv->notifier_block.notifier_call = NULL;
+ }
+ return 0;
+}
+
+static int hns_nic_dev_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct net_device *ndev;
+ struct hns_nic_priv *priv;
+ struct device_node *node = dev->of_node;
+ int ret;
+
+ ndev = alloc_etherdev_mq(sizeof(struct hns_nic_priv), NIC_MAX_Q_PER_VF);
+ if (!ndev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ndev);
+
+ priv = netdev_priv(ndev);
+ priv->dev = dev;
+ priv->netdev = ndev;
+
+ if (of_device_is_compatible(node, "hisilicon,hns-nic-v2"))
+ priv->enet_ver = AE_VERSION_2;
+ else
+ priv->enet_ver = AE_VERSION_1;
+
+ ret = of_property_read_string(node, "ae-name", &priv->ae_name);
+ if (ret)
+ goto out_read_string_fail;
+
+ ret = of_property_read_u32(node, "port-id", &priv->port_id);
+ if (ret)
+ goto out_read_string_fail;
+
+ hns_init_mac_addr(ndev);
+
+ ndev->watchdog_timeo = HNS_NIC_TX_TIMEOUT;
+ ndev->priv_flags |= IFF_UNICAST_FLT;
+ ndev->netdev_ops = &hns_nic_netdev_ops;
+ hns_ethtool_set_ops(ndev);
+ ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
+ NETIF_F_GRO;
+ ndev->vlan_features |=
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
+ ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO;
+
+ SET_NETDEV_DEV(ndev, dev);
+
+ if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
+ dev_dbg(dev, "set mask to 64bit\n");
+ else
+ dev_err(dev, "set mask to 32bit fail!\n");
+
+ /* carrier off reporting is important to ethtool even BEFORE open */
+ netif_carrier_off(ndev);
+
+ setup_timer(&priv->service_timer, hns_nic_service_timer,
+ (unsigned long)priv);
+ INIT_WORK(&priv->service_task, hns_nic_service_task);
+
+ set_bit(NIC_STATE_SERVICE_INITED, &priv->state);
+ clear_bit(NIC_STATE_SERVICE_SCHED, &priv->state);
+ set_bit(NIC_STATE_DOWN, &priv->state);
+
+ if (hns_nic_try_get_ae(priv->netdev)) {
+ priv->notifier_block.notifier_call = hns_nic_notifier_action;
+ ret = hnae_register_notifier(&priv->notifier_block);
+ if (ret) {
+ dev_err(dev, "register notifier fail!\n");
+ goto out_notify_fail;
+ }
+ dev_dbg(dev, "has not handle, register notifier!\n");
+ }
+
+ return 0;
+
+out_notify_fail:
+ (void)cancel_work_sync(&priv->service_task);
+out_read_string_fail:
+ free_netdev(ndev);
+ return ret;
+}
+
+static int hns_nic_dev_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+
+ if (ndev->reg_state != NETREG_UNINITIALIZED)
+ unregister_netdev(ndev);
+
+ if (priv->ring_data)
+ hns_nic_uninit_ring_data(priv);
+ priv->ring_data = NULL;
+
+ if (priv->phy)
+ phy_disconnect(priv->phy);
+ priv->phy = NULL;
+
+ if (!IS_ERR_OR_NULL(priv->ae_handle))
+ hnae_put_handle(priv->ae_handle);
+ priv->ae_handle = NULL;
+ if (priv->notifier_block.notifier_call)
+ hnae_unregister_notifier(&priv->notifier_block);
+ priv->notifier_block.notifier_call = NULL;
+
+ set_bit(NIC_STATE_REMOVING, &priv->state);
+ (void)cancel_work_sync(&priv->service_task);
+
+ free_netdev(ndev);
+ return 0;
+}
+
+static const struct of_device_id hns_enet_of_match[] = {
+ {.compatible = "hisilicon,hns-nic-v1",},
+ {.compatible = "hisilicon,hns-nic-v2",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, hns_enet_of_match);
+
+static struct platform_driver hns_nic_dev_driver = {
+ .driver = {
+ .name = "hns-nic",
+ .of_match_table = hns_enet_of_match,
+ },
+ .probe = hns_nic_dev_probe,
+ .remove = hns_nic_dev_remove,
+};
+
+module_platform_driver(hns_nic_dev_driver);
+
+MODULE_DESCRIPTION("HISILICON HNS Ethernet driver");
+MODULE_AUTHOR("Hisilicon, Inc.");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hns-nic");
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h
new file mode 100644
index 000000000000..dae0ed19ac6d
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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.
+ */
+
+#ifndef __HNS_ENET_H
+#define __HNS_ENET_H
+
+#include <linux/netdevice.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+#include "hnae.h"
+
+enum hns_nic_state {
+ NIC_STATE_TESTING = 0,
+ NIC_STATE_RESETTING,
+ NIC_STATE_REINITING,
+ NIC_STATE_DOWN,
+ NIC_STATE_DISABLED,
+ NIC_STATE_REMOVING,
+ NIC_STATE_SERVICE_INITED,
+ NIC_STATE_SERVICE_SCHED,
+ NIC_STATE2_RESET_REQUESTED,
+ NIC_STATE_MAX
+};
+
+struct hns_nic_ring_data {
+ struct hnae_ring *ring;
+ struct napi_struct napi;
+ int queue_index;
+ int (*poll_one)(struct hns_nic_ring_data *, int, void *);
+ void (*ex_process)(struct hns_nic_ring_data *, struct sk_buff *);
+ void (*fini_process)(struct hns_nic_ring_data *);
+};
+
+struct hns_nic_priv {
+ const char *ae_name;
+ u32 enet_ver;
+ u32 port_id;
+ int phy_mode;
+ int phy_led_val;
+ struct phy_device *phy;
+ struct net_device *netdev;
+ struct device *dev;
+ struct hnae_handle *ae_handle;
+
+ /* the cb for nic to manage the ring buffer, the first half of the
+ * array is for tx_ring and vice versa for the second half
+ */
+ struct hns_nic_ring_data *ring_data;
+
+ /* The most recently read link state */
+ int link;
+ u64 tx_timeout_count;
+
+ unsigned long state;
+
+ struct timer_list service_timer;
+
+ struct work_struct service_task;
+
+ struct notifier_block notifier_block;
+};
+
+#define tx_ring_data(priv, idx) ((priv)->ring_data[idx])
+#define rx_ring_data(priv, idx) \
+ ((priv)->ring_data[(priv)->ae_handle->q_num + (idx)])
+
+void hns_ethtool_set_ops(struct net_device *ndev);
+void hns_nic_net_reset(struct net_device *ndev);
+void hns_nic_net_reinit(struct net_device *netdev);
+int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h);
+int hns_nic_net_xmit_hw(struct net_device *ndev,
+ struct sk_buff *skb,
+ struct hns_nic_ring_data *ring_data);
+
+#endif /**__HNS_ENET_H */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
new file mode 100644
index 000000000000..a0332129970b
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -0,0 +1,1214 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "hns_enet.h"
+
+#define HNS_PHY_PAGE_MDIX 0
+#define HNS_PHY_PAGE_LED 3
+#define HNS_PHY_PAGE_COPPER 0
+
+#define HNS_PHY_PAGE_REG 22 /* Page Selection Reg. */
+#define HNS_PHY_CSC_REG 16 /* Copper Specific Control Register */
+#define HNS_PHY_CSS_REG 17 /* Copper Specific Status Register */
+#define HNS_LED_FC_REG 16 /* LED Function Control Reg. */
+#define HNS_LED_PC_REG 17 /* LED Polarity Control Reg. */
+
+#define HNS_LED_FORCE_ON 9
+#define HNS_LED_FORCE_OFF 8
+
+#define HNS_CHIP_VERSION 660
+#define HNS_NET_STATS_CNT 26
+
+#define PHY_MDIX_CTRL_S (5)
+#define PHY_MDIX_CTRL_M (3 << PHY_MDIX_CTRL_S)
+
+#define PHY_MDIX_STATUS_B (6)
+#define PHY_SPEED_DUP_RESOLVE_B (11)
+
+/**
+ *hns_nic_get_link - get current link status
+ *@net_dev: net_device
+ *retuen 0 - success , negative --fail
+ */
+static u32 hns_nic_get_link(struct net_device *net_dev)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ u32 link_stat = priv->link;
+ struct hnae_handle *h;
+
+ assert(priv && priv->ae_handle);
+ h = priv->ae_handle;
+
+ if (priv->phy) {
+ if (!genphy_update_link(priv->phy))
+ link_stat = priv->phy->link;
+ else
+ link_stat = 0;
+ }
+
+ if (h->dev && h->dev->ops && h->dev->ops->get_status)
+ link_stat = link_stat && h->dev->ops->get_status(h);
+ else
+ link_stat = 0;
+
+ return link_stat;
+}
+
+static void hns_get_mdix_mode(struct net_device *net_dev,
+ struct ethtool_cmd *cmd)
+{
+ int mdix_ctrl, mdix, retval, is_resolved;
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct phy_device *phy_dev = priv->phy;
+
+ if (!phy_dev || !phy_dev->bus) {
+ cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
+ cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
+ return;
+ }
+
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_PHY_PAGE_REG,
+ HNS_PHY_PAGE_MDIX);
+
+ retval = mdiobus_read(phy_dev->bus, phy_dev->addr, HNS_PHY_CSC_REG);
+ mdix_ctrl = hnae_get_field(retval, PHY_MDIX_CTRL_M, PHY_MDIX_CTRL_S);
+
+ retval = mdiobus_read(phy_dev->bus, phy_dev->addr, HNS_PHY_CSS_REG);
+ mdix = hnae_get_bit(retval, PHY_MDIX_STATUS_B);
+ is_resolved = hnae_get_bit(retval, PHY_SPEED_DUP_RESOLVE_B);
+
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_PHY_PAGE_REG,
+ HNS_PHY_PAGE_COPPER);
+
+ switch (mdix_ctrl) {
+ case 0x0:
+ cmd->eth_tp_mdix_ctrl = ETH_TP_MDI;
+ break;
+ case 0x1:
+ cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X;
+ break;
+ case 0x3:
+ cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
+ break;
+ default:
+ cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
+ break;
+ }
+
+ if (!is_resolved)
+ cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
+ else if (mdix)
+ cmd->eth_tp_mdix = ETH_TP_MDI_X;
+ else
+ cmd->eth_tp_mdix = ETH_TP_MDI;
+}
+
+/**
+ *hns_nic_get_settings - implement ethtool get settings
+ *@net_dev: net_device
+ *@cmd: ethtool_cmd
+ *retuen 0 - success , negative --fail
+ */
+static int hns_nic_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *cmd)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_handle *h;
+ u32 link_stat;
+ int ret;
+ u8 duplex;
+ u16 speed;
+
+ if (!priv || !priv->ae_handle)
+ return -ESRCH;
+
+ h = priv->ae_handle;
+ if (!h->dev || !h->dev->ops || !h->dev->ops->get_info)
+ return -ESRCH;
+
+ ret = h->dev->ops->get_info(h, NULL, &speed, &duplex);
+ if (ret < 0) {
+ netdev_err(net_dev, "%s get_info error!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* When there is no phy, autoneg is off. */
+ cmd->autoneg = false;
+ ethtool_cmd_speed_set(cmd, speed);
+ cmd->duplex = duplex;
+
+ if (priv->phy)
+ (void)phy_ethtool_gset(priv->phy, cmd);
+
+ link_stat = hns_nic_get_link(net_dev);
+ if (!link_stat) {
+ ethtool_cmd_speed_set(cmd, (u32)SPEED_UNKNOWN);
+ cmd->duplex = DUPLEX_UNKNOWN;
+ }
+
+ if (cmd->autoneg)
+ cmd->advertising |= ADVERTISED_Autoneg;
+
+ cmd->supported |= h->if_support;
+ if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_1000baseT_Full;
+ } else if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_10000baseKR_Full;
+ }
+
+ if (h->port_type == HNAE_PORT_SERVICE) {
+ cmd->port = PORT_FIBRE;
+ cmd->supported |= SUPPORTED_Pause;
+ } else {
+ cmd->port = PORT_TP;
+ }
+
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->mdio_support = (ETH_MDIO_SUPPORTS_C45 | ETH_MDIO_SUPPORTS_C22);
+ hns_get_mdix_mode(net_dev, cmd);
+
+ return 0;
+}
+
+/**
+ *hns_nic_set_settings - implement ethtool set settings
+ *@net_dev: net_device
+ *@cmd: ethtool_cmd
+ *retuen 0 - success , negative --fail
+ */
+static int hns_nic_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *cmd)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_handle *h;
+ u32 speed;
+
+ if (!netif_running(net_dev))
+ return -ESRCH;
+
+ if (!priv || !priv->ae_handle || !priv->ae_handle->dev ||
+ !priv->ae_handle->dev->ops)
+ return -ENODEV;
+
+ h = priv->ae_handle;
+ speed = ethtool_cmd_speed(cmd);
+
+ if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
+ if (cmd->autoneg == AUTONEG_ENABLE || speed != SPEED_10000 ||
+ cmd->duplex != DUPLEX_FULL)
+ return -EINVAL;
+ } else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
+ if (!priv->phy && cmd->autoneg == AUTONEG_ENABLE)
+ return -EINVAL;
+
+ if (speed == SPEED_1000 && cmd->duplex == DUPLEX_HALF)
+ return -EINVAL;
+ if (priv->phy)
+ return phy_ethtool_sset(priv->phy, cmd);
+
+ if ((speed != SPEED_10 && speed != SPEED_100 &&
+ speed != SPEED_1000) || (cmd->duplex != DUPLEX_HALF &&
+ cmd->duplex != DUPLEX_FULL))
+ return -EINVAL;
+ } else {
+ netdev_err(net_dev, "Not supported!");
+ return -ENOTSUPP;
+ }
+
+ if (h->dev->ops->adjust_link) {
+ h->dev->ops->adjust_link(h, (int)speed, cmd->duplex);
+ return 0;
+ }
+
+ netdev_err(net_dev, "Not supported!");
+ return -ENOTSUPP;
+}
+
+static const char hns_nic_test_strs[][ETH_GSTRING_LEN] = {
+ "Mac Loopback test",
+ "Serdes Loopback test",
+ "Phy Loopback test"
+};
+
+static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
+{
+#define COPPER_CONTROL_REG 0
+#define PHY_LOOP_BACK BIT(14)
+ u16 val = 0;
+
+ if (phy_dev->is_c45) /* c45 branch adding for XGE PHY */
+ return -ENOTSUPP;
+
+ if (en) {
+ /* speed : 1000M */
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG, 2);
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 21, 0x1046);
+ /* Force Master */
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 9, 0x1F00);
+ /* Soft-reset */
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 0, 0x9140);
+ /* If autoneg disabled,two soft-reset operations */
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 0, 0x9140);
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 22, 0xFA);
+
+ /* Default is 0x0400 */
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 1, 0x418);
+
+ /* Force 1000M Link, Default is 0x0200 */
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 7, 0x20C);
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 22, 0);
+
+ /* Enable MAC loop-back */
+ val = (u16)mdiobus_read(phy_dev->bus, phy_dev->addr,
+ COPPER_CONTROL_REG);
+ val |= PHY_LOOP_BACK;
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ COPPER_CONTROL_REG, val);
+ } else {
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 22, 0xFA);
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 1, 0x400);
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 7, 0x200);
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ 22, 0);
+
+ val = (u16)mdiobus_read(phy_dev->bus, phy_dev->addr,
+ COPPER_CONTROL_REG);
+ val &= ~PHY_LOOP_BACK;
+ (void)mdiobus_write(phy_dev->bus, phy_dev->addr,
+ COPPER_CONTROL_REG, val);
+ }
+ return 0;
+}
+
+static int __lb_setup(struct net_device *ndev,
+ enum hnae_loop loop)
+{
+ int ret = 0;
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct phy_device *phy_dev = priv->phy;
+ struct hnae_handle *h = priv->ae_handle;
+
+ switch (loop) {
+ case MAC_INTERNALLOOP_PHY:
+ if ((phy_dev) && (!phy_dev->is_c45))
+ ret = hns_nic_config_phy_loopback(phy_dev, 0x1);
+ break;
+ case MAC_INTERNALLOOP_MAC:
+ if ((h->dev->ops->set_loopback) &&
+ (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII))
+ ret = h->dev->ops->set_loopback(h, loop, 0x1);
+ break;
+ case MAC_INTERNALLOOP_SERDES:
+ if (h->dev->ops->set_loopback)
+ ret = h->dev->ops->set_loopback(h, loop, 0x1);
+ break;
+ case MAC_LOOP_NONE:
+ if ((phy_dev) && (!phy_dev->is_c45))
+ ret |= hns_nic_config_phy_loopback(phy_dev, 0x0);
+
+ if (h->dev->ops->set_loopback) {
+ if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
+ ret |= h->dev->ops->set_loopback(h,
+ MAC_INTERNALLOOP_MAC, 0x0);
+
+ ret |= h->dev->ops->set_loopback(h,
+ MAC_INTERNALLOOP_SERDES, 0x0);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int __lb_up(struct net_device *ndev,
+ enum hnae_loop loop_mode)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ int speed, duplex;
+ int ret;
+
+ hns_nic_net_reset(ndev);
+
+ if (priv->phy) {
+ phy_disconnect(priv->phy);
+ msleep(100);
+
+ ret = hns_nic_init_phy(ndev, h);
+ if (ret)
+ return ret;
+ }
+
+ ret = __lb_setup(ndev, loop_mode);
+ if (ret)
+ return ret;
+
+ msleep(100);
+
+ ret = h->dev->ops->start ? h->dev->ops->start(h) : 0;
+ if (ret)
+ return ret;
+
+ if (priv->phy)
+ phy_start(priv->phy);
+
+ /* link adjust duplex*/
+ if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
+ speed = 1000;
+ else
+ speed = 10000;
+ duplex = 1;
+
+ h->dev->ops->adjust_link(h, speed, duplex);
+
+ return 0;
+}
+
+static void __lb_other_process(struct hns_nic_ring_data *ring_data,
+ struct sk_buff *skb)
+{
+ struct net_device *ndev;
+ struct hnae_ring *ring;
+ struct netdev_queue *dev_queue;
+ struct sk_buff *new_skb;
+ unsigned int frame_size;
+ int check_ok;
+ u32 i;
+ char buff[33]; /* 32B data and the last character '\0' */
+
+ if (!ring_data) { /* Just for doing create frame*/
+ frame_size = skb->len;
+ memset(skb->data, 0xFF, frame_size);
+ frame_size &= ~1ul;
+ memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
+ memset(&skb->data[frame_size / 2 + 10], 0xBE,
+ frame_size / 2 - 11);
+ memset(&skb->data[frame_size / 2 + 12], 0xAF,
+ frame_size / 2 - 13);
+ return;
+ }
+
+ ring = ring_data->ring;
+ ndev = ring_data->napi.dev;
+ if (is_tx_ring(ring)) { /* for tx queue reset*/
+ dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
+ netdev_tx_reset_queue(dev_queue);
+ return;
+ }
+
+ frame_size = skb->len;
+ frame_size &= ~1ul;
+ /* for mutl buffer*/
+ new_skb = skb_copy(skb, GFP_ATOMIC);
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+
+ check_ok = 0;
+ if (*(skb->data + 10) == 0xFF) { /* for rx check frame*/
+ if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+ (*(skb->data + frame_size / 2 + 12) == 0xAF))
+ check_ok = 1;
+ }
+
+ if (check_ok) {
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += skb->len;
+ } else {
+ ndev->stats.rx_frame_errors++;
+ for (i = 0; i < skb->len; i++) {
+ snprintf(buff + i % 16 * 2, 3, /* tailing \0*/
+ "%02x", *(skb->data + i));
+ if ((i % 16 == 15) || (i == skb->len - 1))
+ pr_info("%s\n", buff);
+ }
+ }
+ dev_kfree_skb_any(skb);
+}
+
+static int __lb_clean_rings(struct hns_nic_priv *priv,
+ int ringid0, int ringid1, int budget)
+{
+ int i, ret;
+ struct hns_nic_ring_data *ring_data;
+ struct net_device *ndev = priv->netdev;
+ unsigned long rx_packets = ndev->stats.rx_packets;
+ unsigned long rx_bytes = ndev->stats.rx_bytes;
+ unsigned long rx_frame_errors = ndev->stats.rx_frame_errors;
+
+ for (i = ringid0; i <= ringid1; i++) {
+ ring_data = &priv->ring_data[i];
+ (void)ring_data->poll_one(ring_data,
+ budget, __lb_other_process);
+ }
+ ret = (int)(ndev->stats.rx_packets - rx_packets);
+ ndev->stats.rx_packets = rx_packets;
+ ndev->stats.rx_bytes = rx_bytes;
+ ndev->stats.rx_frame_errors = rx_frame_errors;
+ return ret;
+}
+
+/**
+ * nic_run_loopback_test - run loopback test
+ * @nic_dev: net device
+ * @loopback_type: loopback type
+ */
+static int __lb_run_test(struct net_device *ndev,
+ enum hnae_loop loop_mode)
+{
+#define NIC_LB_TEST_PKT_NUM_PER_CYCLE 1
+#define NIC_LB_TEST_RING_ID 0
+#define NIC_LB_TEST_FRAME_SIZE 128
+/* nic loopback test err */
+#define NIC_LB_TEST_NO_MEM_ERR 1
+#define NIC_LB_TEST_TX_CNT_ERR 2
+#define NIC_LB_TEST_RX_CNT_ERR 3
+#define NIC_LB_TEST_RX_PKG_ERR 4
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ int i, j, lc, good_cnt, ret_val = 0;
+ unsigned int size;
+ netdev_tx_t tx_ret_val;
+ struct sk_buff *skb;
+
+ size = NIC_LB_TEST_FRAME_SIZE;
+ /* allocate test skb */
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return NIC_LB_TEST_NO_MEM_ERR;
+
+ /* place data into test skb */
+ (void)skb_put(skb, size);
+ __lb_other_process(NULL, skb);
+ skb->queue_mapping = NIC_LB_TEST_RING_ID;
+
+ lc = 1;
+ for (j = 0; j < lc; j++) {
+ /* reset count of good packets */
+ good_cnt = 0;
+ /* place 64 packets on the transmit queue*/
+ for (i = 0; i < NIC_LB_TEST_PKT_NUM_PER_CYCLE; i++) {
+ (void)skb_get(skb);
+
+ tx_ret_val = (netdev_tx_t)hns_nic_net_xmit_hw(
+ ndev, skb,
+ &tx_ring_data(priv, skb->queue_mapping));
+ if (tx_ret_val == NETDEV_TX_OK)
+ good_cnt++;
+ else
+ break;
+ }
+ if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) {
+ ret_val = NIC_LB_TEST_TX_CNT_ERR;
+ dev_err(priv->dev, "%s sent fail, cnt=0x%x, budget=0x%x\n",
+ hns_nic_test_strs[loop_mode], good_cnt,
+ NIC_LB_TEST_PKT_NUM_PER_CYCLE);
+ break;
+ }
+
+ /* allow 100 milliseconds for packets to go from Tx to Rx */
+ msleep(100);
+
+ good_cnt = __lb_clean_rings(priv,
+ h->q_num, h->q_num * 2 - 1,
+ NIC_LB_TEST_PKT_NUM_PER_CYCLE);
+ if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) {
+ ret_val = NIC_LB_TEST_RX_CNT_ERR;
+ dev_err(priv->dev, "%s recv fail, cnt=0x%x, budget=0x%x\n",
+ hns_nic_test_strs[loop_mode], good_cnt,
+ NIC_LB_TEST_PKT_NUM_PER_CYCLE);
+ break;
+ }
+ (void)__lb_clean_rings(priv,
+ NIC_LB_TEST_RING_ID, NIC_LB_TEST_RING_ID,
+ NIC_LB_TEST_PKT_NUM_PER_CYCLE);
+ }
+
+ /* free the original skb */
+ kfree_skb(skb);
+
+ return ret_val;
+}
+
+static int __lb_down(struct net_device *ndev)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ struct hnae_handle *h = priv->ae_handle;
+ int ret;
+
+ ret = __lb_setup(ndev, MAC_LOOP_NONE);
+ if (ret)
+ netdev_err(ndev, "%s: __lb_setup return error(%d)!\n",
+ __func__,
+ ret);
+
+ if (priv->phy)
+ phy_stop(priv->phy);
+
+ if (h->dev->ops->stop)
+ h->dev->ops->stop(h);
+
+ usleep_range(10000, 20000);
+ (void)__lb_clean_rings(priv, 0, h->q_num - 1, 256);
+
+ hns_nic_net_reset(ndev);
+
+ return 0;
+}
+
+/**
+ * hns_nic_self_test - self test
+ * @dev: net device
+ * @eth_test: test cmd
+ * @data: test result
+ */
+static void hns_nic_self_test(struct net_device *ndev,
+ struct ethtool_test *eth_test, u64 *data)
+{
+ struct hns_nic_priv *priv = netdev_priv(ndev);
+ bool if_running = netif_running(ndev);
+#define SELF_TEST_TPYE_NUM 3
+ int st_param[SELF_TEST_TPYE_NUM][2];
+ int i;
+ int test_index = 0;
+
+ st_param[0][0] = MAC_INTERNALLOOP_MAC; /* XGE not supported lb */
+ st_param[0][1] = (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII);
+ st_param[1][0] = MAC_INTERNALLOOP_SERDES;
+ st_param[1][1] = 1; /*serdes must exist*/
+ st_param[2][0] = MAC_INTERNALLOOP_PHY; /* only supporte phy node*/
+ st_param[2][1] = ((!!(priv->ae_handle->phy_node)) &&
+ (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII));
+
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ set_bit(NIC_STATE_TESTING, &priv->state);
+
+ if (if_running)
+ (void)dev_close(ndev);
+
+ for (i = 0; i < SELF_TEST_TPYE_NUM; i++) {
+ if (!st_param[i][1])
+ continue; /* NEXT testing */
+
+ data[test_index] = __lb_up(ndev,
+ (enum hnae_loop)st_param[i][0]);
+ if (!data[test_index]) {
+ data[test_index] = __lb_run_test(
+ ndev, (enum hnae_loop)st_param[i][0]);
+ (void)__lb_down(ndev);
+ }
+
+ if (data[test_index])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+ test_index++;
+ }
+
+ hns_nic_net_reset(priv->netdev);
+
+ clear_bit(NIC_STATE_TESTING, &priv->state);
+
+ if (if_running)
+ (void)dev_open(ndev);
+ }
+ /* Online tests aren't run; pass by default */
+
+ (void)msleep_interruptible(4 * 1000);
+}
+
+/**
+ * hns_nic_get_drvinfo - get net driver info
+ * @dev: net device
+ * @drvinfo: driver info
+ */
+static void hns_nic_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+
+ assert(priv);
+
+ strncpy(drvinfo->version, HNAE_DRIVER_VERSION,
+ sizeof(drvinfo->version));
+ drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
+
+ strncpy(drvinfo->driver, HNAE_DRIVER_NAME, sizeof(drvinfo->driver));
+ drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
+
+ strncpy(drvinfo->bus_info, priv->dev->bus->name,
+ sizeof(drvinfo->bus_info));
+ drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0';
+
+ strncpy(drvinfo->fw_version, "N/A", ETHTOOL_FWVERS_LEN);
+}
+
+/**
+ * hns_get_ringparam - get ring parameter
+ * @dev: net device
+ * @param: ethtool parameter
+ */
+void hns_get_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *param)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_ae_ops *ops;
+ struct hnae_queue *queue;
+ u32 uplimit = 0;
+
+ queue = priv->ae_handle->qs[0];
+ ops = priv->ae_handle->dev->ops;
+
+ if (ops->get_ring_bdnum_limit)
+ ops->get_ring_bdnum_limit(queue, &uplimit);
+
+ param->rx_max_pending = uplimit;
+ param->tx_max_pending = uplimit;
+ param->rx_pending = queue->rx_ring.desc_num;
+ param->tx_pending = queue->tx_ring.desc_num;
+}
+
+/**
+ * hns_get_pauseparam - get pause parameter
+ * @dev: net device
+ * @param: pause parameter
+ */
+static void hns_get_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *param)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_ae_ops *ops;
+
+ ops = priv->ae_handle->dev->ops;
+
+ if (ops->get_pauseparam)
+ ops->get_pauseparam(priv->ae_handle, &param->autoneg,
+ &param->rx_pause, &param->tx_pause);
+}
+
+/**
+ * hns_set_pauseparam - set pause parameter
+ * @dev: net device
+ * @param: pause parameter
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_set_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *param)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_handle *h;
+ struct hnae_ae_ops *ops;
+
+ assert(priv || priv->ae_handle);
+
+ h = priv->ae_handle;
+ ops = h->dev->ops;
+
+ if (!ops->set_pauseparam)
+ return -ESRCH;
+
+ return ops->set_pauseparam(priv->ae_handle, param->autoneg,
+ param->rx_pause, param->tx_pause);
+}
+
+/**
+ * hns_get_coalesce - get coalesce info.
+ * @dev: net device
+ * @ec: coalesce info.
+ *
+ * Return 0 on success, negative on failure.
+ */
+static int hns_get_coalesce(struct net_device *net_dev,
+ struct ethtool_coalesce *ec)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_ae_ops *ops;
+
+ ops = priv->ae_handle->dev->ops;
+
+ ec->use_adaptive_rx_coalesce = 1;
+ ec->use_adaptive_tx_coalesce = 1;
+
+ if ((!ops->get_coalesce_usecs) ||
+ (!ops->get_rx_max_coalesced_frames))
+ return -ESRCH;
+
+ ops->get_coalesce_usecs(priv->ae_handle,
+ &ec->tx_coalesce_usecs,
+ &ec->rx_coalesce_usecs);
+
+ ops->get_rx_max_coalesced_frames(
+ priv->ae_handle,
+ &ec->tx_max_coalesced_frames,
+ &ec->rx_max_coalesced_frames);
+
+ return 0;
+}
+
+/**
+ * hns_set_coalesce - set coalesce info.
+ * @dev: net device
+ * @ec: coalesce info.
+ *
+ * Return 0 on success, negative on failure.
+ */
+static int hns_set_coalesce(struct net_device *net_dev,
+ struct ethtool_coalesce *ec)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_ae_ops *ops;
+ int ret;
+
+ assert(priv || priv->ae_handle);
+
+ ops = priv->ae_handle->dev->ops;
+
+ if (ec->tx_coalesce_usecs != ec->rx_coalesce_usecs)
+ return -EINVAL;
+
+ if (ec->rx_max_coalesced_frames != ec->tx_max_coalesced_frames)
+ return -EINVAL;
+
+ if ((!ops->set_coalesce_usecs) ||
+ (!ops->set_coalesce_frames))
+ return -ESRCH;
+
+ ops->set_coalesce_usecs(priv->ae_handle,
+ ec->rx_coalesce_usecs);
+
+ ret = ops->set_coalesce_frames(
+ priv->ae_handle,
+ ec->rx_max_coalesced_frames);
+
+ return ret;
+}
+
+/**
+ * hns_get_channels - get channel info.
+ * @dev: net device
+ * @ch: channel info.
+ */
+void hns_get_channels(struct net_device *net_dev, struct ethtool_channels *ch)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+
+ ch->max_rx = priv->ae_handle->q_num;
+ ch->max_tx = priv->ae_handle->q_num;
+
+ ch->rx_count = priv->ae_handle->q_num;
+ ch->tx_count = priv->ae_handle->q_num;
+}
+
+/**
+ * get_ethtool_stats - get detail statistics.
+ * @dev: net device
+ * @stats: statistics info.
+ * @data: statistics data.
+ */
+void hns_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ u64 *p = data;
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+ const struct rtnl_link_stats64 *net_stats;
+ struct rtnl_link_stats64 temp;
+
+ if (!h->dev->ops->get_stats || !h->dev->ops->update_stats) {
+ netdev_err(netdev, "get_stats or update_stats is null!\n");
+ return;
+ }
+
+ h->dev->ops->update_stats(h, &netdev->stats);
+
+ net_stats = dev_get_stats(netdev, &temp);
+
+ /* get netdev statistics */
+ p[0] = net_stats->rx_packets;
+ p[1] = net_stats->tx_packets;
+ p[2] = net_stats->rx_bytes;
+ p[3] = net_stats->tx_bytes;
+ p[4] = net_stats->rx_errors;
+ p[5] = net_stats->tx_errors;
+ p[6] = net_stats->rx_dropped;
+ p[7] = net_stats->tx_dropped;
+ p[8] = net_stats->multicast;
+ p[9] = net_stats->collisions;
+ p[10] = net_stats->rx_over_errors;
+ p[11] = net_stats->rx_crc_errors;
+ p[12] = net_stats->rx_frame_errors;
+ p[13] = net_stats->rx_fifo_errors;
+ p[14] = net_stats->rx_missed_errors;
+ p[15] = net_stats->tx_aborted_errors;
+ p[16] = net_stats->tx_carrier_errors;
+ p[17] = net_stats->tx_fifo_errors;
+ p[18] = net_stats->tx_heartbeat_errors;
+ p[19] = net_stats->rx_length_errors;
+ p[20] = net_stats->tx_window_errors;
+ p[21] = net_stats->rx_compressed;
+ p[22] = net_stats->tx_compressed;
+
+ p[23] = netdev->rx_dropped.counter;
+ p[24] = netdev->tx_dropped.counter;
+
+ p[25] = priv->tx_timeout_count;
+
+ /* get driver statistics */
+ h->dev->ops->get_stats(h, &p[26]);
+}
+
+/**
+ * get_strings: Return a set of strings that describe the requested objects
+ * @dev: net device
+ * @stats: string set ID.
+ * @data: objects data.
+ */
+void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+ char *buff = (char *)data;
+
+ if (!h->dev->ops->get_strings) {
+ netdev_err(netdev, "h->dev->ops->get_strings is null!\n");
+ return;
+ }
+
+ if (stringset == ETH_SS_TEST) {
+ if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) {
+ memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_MAC],
+ ETH_GSTRING_LEN);
+ buff += ETH_GSTRING_LEN;
+ }
+ memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES],
+ ETH_GSTRING_LEN);
+ buff += ETH_GSTRING_LEN;
+ if ((priv->phy) && (!priv->phy->is_c45))
+ memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_PHY],
+ ETH_GSTRING_LEN);
+
+ } else {
+ snprintf(buff, ETH_GSTRING_LEN, "rx_packets");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_packets");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_bytes");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_bytes");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_dropped");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_dropped");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "multicast");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "collisions");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_over_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_crc_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_frame_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_fifo_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_missed_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_aborted_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_carrier_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_fifo_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_heartbeat_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_length_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_window_errors");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "rx_compressed");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "tx_compressed");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "netdev_rx_dropped");
+ buff = buff + ETH_GSTRING_LEN;
+ snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_dropped");
+ buff = buff + ETH_GSTRING_LEN;
+
+ snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_timeout");
+ buff = buff + ETH_GSTRING_LEN;
+
+ h->dev->ops->get_strings(h, stringset, (u8 *)buff);
+ }
+}
+
+/**
+ * nic_get_sset_count - get string set count witch returned by nic_get_strings.
+ * @dev: net device
+ * @stringset: string set index, 0: self test string; 1: statistics string.
+ *
+ * Return string set count.
+ */
+int hns_get_sset_count(struct net_device *netdev, int stringset)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+ struct hnae_ae_ops *ops = h->dev->ops;
+
+ if (!ops->get_sset_count) {
+ netdev_err(netdev, "get_sset_count is null!\n");
+ return -EOPNOTSUPP;
+ }
+ if (stringset == ETH_SS_TEST) {
+ u32 cnt = (sizeof(hns_nic_test_strs) / ETH_GSTRING_LEN);
+
+ if (priv->ae_handle->phy_if == PHY_INTERFACE_MODE_XGMII)
+ cnt--;
+
+ if ((!priv->phy) || (priv->phy->is_c45))
+ cnt--;
+
+ return cnt;
+ } else {
+ return (HNS_NET_STATS_CNT + ops->get_sset_count(h, stringset));
+ }
+}
+
+/**
+ * hns_phy_led_set - set phy LED status.
+ * @dev: net device
+ * @value: LED state.
+ *
+ * Return 0 on success, negative on failure.
+ */
+int hns_phy_led_set(struct net_device *netdev, int value)
+{
+ int retval;
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct phy_device *phy_dev = priv->phy;
+
+ if (!phy_dev->bus) {
+ netdev_err(netdev, "phy_dev->bus is null!\n");
+ return -EINVAL;
+ }
+ retval = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED);
+ retval = mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_LED_FC_REG,
+ value);
+ retval = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER);
+ if (retval) {
+ netdev_err(netdev, "mdiobus_write fail !\n");
+ return retval;
+ }
+ return 0;
+}
+
+/**
+ * nic_set_phys_id - set phy identify LED.
+ * @dev: net device
+ * @state: LED state.
+ *
+ * Return 0 on success, negative on failure.
+ */
+int hns_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+ struct phy_device *phy_dev = priv->phy;
+ int ret;
+
+ if (phy_dev)
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ ret = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG,
+ HNS_PHY_PAGE_LED);
+ if (ret)
+ return ret;
+
+ priv->phy_led_val = (u16)mdiobus_read(phy_dev->bus,
+ phy_dev->addr,
+ HNS_LED_FC_REG);
+
+ ret = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG,
+ HNS_PHY_PAGE_COPPER);
+ if (ret)
+ return ret;
+ return 2;
+ case ETHTOOL_ID_ON:
+ ret = hns_phy_led_set(netdev, HNS_LED_FORCE_ON);
+ if (ret)
+ return ret;
+ break;
+ case ETHTOOL_ID_OFF:
+ ret = hns_phy_led_set(netdev, HNS_LED_FORCE_OFF);
+ if (ret)
+ return ret;
+ break;
+ case ETHTOOL_ID_INACTIVE:
+ ret = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG,
+ HNS_PHY_PAGE_LED);
+ if (ret)
+ return ret;
+
+ ret = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_LED_FC_REG, priv->phy_led_val);
+ if (ret)
+ return ret;
+
+ ret = mdiobus_write(phy_dev->bus, phy_dev->addr,
+ HNS_PHY_PAGE_REG,
+ HNS_PHY_PAGE_COPPER);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+ else
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ return h->dev->ops->set_led_id(h, HNAE_LED_ACTIVE);
+ case ETHTOOL_ID_ON:
+ return h->dev->ops->set_led_id(h, HNAE_LED_ON);
+ case ETHTOOL_ID_OFF:
+ return h->dev->ops->set_led_id(h, HNAE_LED_OFF);
+ case ETHTOOL_ID_INACTIVE:
+ return h->dev->ops->set_led_id(h, HNAE_LED_INACTIVE);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * hns_get_regs - get net device register
+ * @dev: net device
+ * @cmd: ethtool cmd
+ * @date: register data
+ */
+void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd,
+ void *data)
+{
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_ae_ops *ops;
+
+ assert(priv || priv->ae_handle);
+
+ ops = priv->ae_handle->dev->ops;
+
+ cmd->version = HNS_CHIP_VERSION;
+ if (!ops->get_regs) {
+ netdev_err(net_dev, "ops->get_regs is null!\n");
+ return;
+ }
+ ops->get_regs(priv->ae_handle, data);
+}
+
+/**
+ * nic_get_regs_len - get total register len.
+ * @dev: net device
+ *
+ * Return total register len.
+ */
+static int hns_get_regs_len(struct net_device *net_dev)
+{
+ u32 reg_num;
+ struct hns_nic_priv *priv = netdev_priv(net_dev);
+ struct hnae_ae_ops *ops;
+
+ assert(priv || priv->ae_handle);
+
+ ops = priv->ae_handle->dev->ops;
+ if (!ops->get_regs_len) {
+ netdev_err(net_dev, "ops->get_regs_len is null!\n");
+ return -EOPNOTSUPP;
+ }
+
+ reg_num = ops->get_regs_len(priv->ae_handle);
+ if (reg_num > 0)
+ return reg_num * sizeof(u32);
+ else
+ return reg_num; /* error code */
+}
+
+/**
+ * hns_nic_nway_reset - nway reset
+ * @dev: net device
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_nic_nway_reset(struct net_device *netdev)
+{
+ int ret = 0;
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct phy_device *phy = priv->phy;
+
+ if (netif_running(netdev)) {
+ if (phy)
+ ret = genphy_restart_aneg(phy);
+ }
+
+ return ret;
+}
+
+static struct ethtool_ops hns_ethtool_ops = {
+ .get_drvinfo = hns_nic_get_drvinfo,
+ .get_link = hns_nic_get_link,
+ .get_settings = hns_nic_get_settings,
+ .set_settings = hns_nic_set_settings,
+ .get_ringparam = hns_get_ringparam,
+ .get_pauseparam = hns_get_pauseparam,
+ .set_pauseparam = hns_set_pauseparam,
+ .get_coalesce = hns_get_coalesce,
+ .set_coalesce = hns_set_coalesce,
+ .get_channels = hns_get_channels,
+ .self_test = hns_nic_self_test,
+ .get_strings = hns_get_strings,
+ .get_sset_count = hns_get_sset_count,
+ .get_ethtool_stats = hns_get_ethtool_stats,
+ .set_phys_id = hns_set_phys_id,
+ .get_regs_len = hns_get_regs_len,
+ .get_regs = hns_get_regs,
+ .nway_reset = hns_nic_nway_reset,
+};
+
+void hns_ethtool_set_ops(struct net_device *ndev)
+{
+ ndev->ethtool_ops = &hns_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c
new file mode 100644
index 000000000000..37491c85bc42
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2014-2015 Hisilicon 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/errno.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/spinlock_types.h>
+
+#define MDIO_DRV_NAME "Hi-HNS_MDIO"
+#define MDIO_BUS_NAME "Hisilicon MII Bus"
+#define MDIO_DRV_VERSION "1.3.0"
+#define MDIO_COPYRIGHT "Copyright(c) 2015 Huawei Corporation."
+#define MDIO_DRV_STRING MDIO_BUS_NAME
+#define MDIO_DEFAULT_DEVICE_DESCR MDIO_BUS_NAME
+
+#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5)
+
+#define MDIO_TIMEOUT 1000000
+
+struct hns_mdio_device {
+ void *vbase; /* mdio reg base address */
+ struct regmap *subctrl_vbase;
+};
+
+/* mdio reg */
+#define MDIO_COMMAND_REG 0x0
+#define MDIO_ADDR_REG 0x4
+#define MDIO_WDATA_REG 0x8
+#define MDIO_RDATA_REG 0xc
+#define MDIO_STA_REG 0x10
+
+/* cfg phy bit map */
+#define MDIO_CMD_DEVAD_M 0x1f
+#define MDIO_CMD_DEVAD_S 0
+#define MDIO_CMD_PRTAD_M 0x1f
+#define MDIO_CMD_PRTAD_S 5
+#define MDIO_CMD_OP_M 0x3
+#define MDIO_CMD_OP_S 10
+#define MDIO_CMD_ST_M 0x3
+#define MDIO_CMD_ST_S 12
+#define MDIO_CMD_START_B 14
+
+#define MDIO_ADDR_DATA_M 0xffff
+#define MDIO_ADDR_DATA_S 0
+
+#define MDIO_WDATA_DATA_M 0xffff
+#define MDIO_WDATA_DATA_S 0
+
+#define MDIO_RDATA_DATA_M 0xffff
+#define MDIO_RDATA_DATA_S 0
+
+#define MDIO_STATE_STA_B 0
+
+enum mdio_st_clause {
+ MDIO_ST_CLAUSE_45 = 0,
+ MDIO_ST_CLAUSE_22
+};
+
+enum mdio_c22_op_seq {
+ MDIO_C22_WRITE = 1,
+ MDIO_C22_READ = 2
+};
+
+enum mdio_c45_op_seq {
+ MDIO_C45_WRITE_ADDR = 0,
+ MDIO_C45_WRITE_DATA,
+ MDIO_C45_READ_INCREMENT,
+ MDIO_C45_READ
+};
+
+/* peri subctrl reg */
+#define MDIO_SC_CLK_EN 0x338
+#define MDIO_SC_CLK_DIS 0x33C
+#define MDIO_SC_RESET_REQ 0xA38
+#define MDIO_SC_RESET_DREQ 0xA3C
+#define MDIO_SC_CTRL 0x2010
+#define MDIO_SC_CLK_ST 0x531C
+#define MDIO_SC_RESET_ST 0x5A1C
+
+static void mdio_write_reg(void *base, u32 reg, u32 value)
+{
+ u8 __iomem *reg_addr = (u8 __iomem *)base;
+
+ writel_relaxed(value, reg_addr + reg);
+}
+
+#define MDIO_WRITE_REG(a, reg, value) \
+ mdio_write_reg((a)->vbase, (reg), (value))
+
+static u32 mdio_read_reg(void *base, u32 reg)
+{
+ u8 __iomem *reg_addr = (u8 __iomem *)base;
+
+ return readl_relaxed(reg_addr + reg);
+}
+
+#define mdio_set_field(origin, mask, shift, val) \
+ do { \
+ (origin) &= (~((mask) << (shift))); \
+ (origin) |= (((val) & (mask)) << (shift)); \
+ } while (0)
+
+#define mdio_get_field(origin, mask, shift) (((origin) >> (shift)) & (mask))
+
+static void mdio_set_reg_field(void *base, u32 reg, u32 mask, u32 shift,
+ u32 val)
+{
+ u32 origin = mdio_read_reg(base, reg);
+
+ mdio_set_field(origin, mask, shift, val);
+ mdio_write_reg(base, reg, origin);
+}
+
+#define MDIO_SET_REG_FIELD(dev, reg, mask, shift, val) \
+ mdio_set_reg_field((dev)->vbase, (reg), (mask), (shift), (val))
+
+static u32 mdio_get_reg_field(void *base, u32 reg, u32 mask, u32 shift)
+{
+ u32 origin;
+
+ origin = mdio_read_reg(base, reg);
+ return mdio_get_field(origin, mask, shift);
+}
+
+#define MDIO_GET_REG_FIELD(dev, reg, mask, shift) \
+ mdio_get_reg_field((dev)->vbase, (reg), (mask), (shift))
+
+#define MDIO_GET_REG_BIT(dev, reg, bit) \
+ mdio_get_reg_field((dev)->vbase, (reg), 0x1ull, (bit))
+
+#define MDIO_CHECK_SET_ST 1
+#define MDIO_CHECK_CLR_ST 0
+
+static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,
+ u32 cfg_reg, u32 set_val,
+ u32 st_reg, u32 st_msk, u8 check_st)
+{
+ u32 time_cnt;
+ u32 reg_value;
+
+ regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);
+
+ for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {
+ regmap_read(mdio_dev->subctrl_vbase, st_reg, &reg_value);
+ reg_value &= st_msk;
+ if ((!!check_st) == (!!reg_value))
+ break;
+ }
+
+ if ((!!check_st) != (!!reg_value))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int hns_mdio_wait_ready(struct mii_bus *bus)
+{
+ struct hns_mdio_device *mdio_dev = bus->priv;
+ int i;
+ u32 cmd_reg_value = 1;
+
+ /* waitting for MDIO_COMMAND_REG 's mdio_start==0 */
+ /* after that can do read or write*/
+ for (i = 0; cmd_reg_value; i++) {
+ cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,
+ MDIO_COMMAND_REG,
+ MDIO_CMD_START_B);
+ if (i == MDIO_TIMEOUT)
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
+ u8 is_c45, u8 op, u8 phy_id, u16 cmd)
+{
+ u32 cmd_reg_value;
+ u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22;
+
+ cmd_reg_value = st << MDIO_CMD_ST_S;
+ cmd_reg_value |= op << MDIO_CMD_OP_S;
+ cmd_reg_value |=
+ (phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S;
+ cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S;
+ cmd_reg_value |= 1 << MDIO_CMD_START_B;
+
+ MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value);
+}
+
+/**
+ * hns_mdio_write - access phy register
+ * @bus: mdio bus
+ * @phy_id: phy id
+ * @regnum: register num
+ * @value: register value
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_mdio_write(struct mii_bus *bus,
+ int phy_id, int regnum, u16 data)
+{
+ int ret;
+ struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
+ u8 devad = ((regnum >> 16) & 0x1f);
+ u8 is_c45 = !!(regnum & MII_ADDR_C45);
+ u16 reg = (u16)(regnum & 0xffff);
+ u8 op;
+ u16 cmd_reg_cfg;
+
+ dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
+ bus->id, mdio_dev->vbase);
+ dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n",
+ phy_id, is_c45, devad, reg, data);
+
+ /* wait for ready */
+ ret = hns_mdio_wait_ready(bus);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO bus is busy\n");
+ return ret;
+ }
+
+ if (!is_c45) {
+ cmd_reg_cfg = reg;
+ op = MDIO_C22_WRITE;
+ } else {
+ /* config the cmd-reg to write addr*/
+ MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
+ MDIO_ADDR_DATA_S, reg);
+
+ hns_mdio_cmd_write(mdio_dev, is_c45,
+ MDIO_C45_WRITE_ADDR, phy_id, devad);
+
+ /* check for read or write opt is finished */
+ ret = hns_mdio_wait_ready(bus);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO bus is busy\n");
+ return ret;
+ }
+
+ /* config the data needed writing */
+ cmd_reg_cfg = devad;
+ op = MDIO_C45_WRITE_ADDR;
+ }
+
+ MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
+ MDIO_WDATA_DATA_S, data);
+
+ hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg);
+
+ return 0;
+}
+
+/**
+ * hns_mdio_read - access phy register
+ * @bus: mdio bus
+ * @phy_id: phy id
+ * @regnum: register num
+ * @value: register value
+ *
+ * Return phy register value
+ */
+static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+ int ret;
+ u16 reg_val = 0;
+ u8 devad = ((regnum >> 16) & 0x1f);
+ u8 is_c45 = !!(regnum & MII_ADDR_C45);
+ u16 reg = (u16)(regnum & 0xffff);
+ struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
+
+ dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
+ bus->id, mdio_dev->vbase);
+ dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n",
+ phy_id, is_c45, devad, reg);
+
+ /* Step 1: wait for ready */
+ ret = hns_mdio_wait_ready(bus);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO bus is busy\n");
+ return ret;
+ }
+
+ if (!is_c45) {
+ hns_mdio_cmd_write(mdio_dev, is_c45,
+ MDIO_C22_READ, phy_id, reg);
+ } else {
+ MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
+ MDIO_ADDR_DATA_S, reg);
+
+ /* Step 2; config the cmd-reg to write addr*/
+ hns_mdio_cmd_write(mdio_dev, is_c45,
+ MDIO_C45_WRITE_ADDR, phy_id, devad);
+
+ /* Step 3: check for read or write opt is finished */
+ ret = hns_mdio_wait_ready(bus);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO bus is busy\n");
+ return ret;
+ }
+
+ hns_mdio_cmd_write(mdio_dev, is_c45,
+ MDIO_C45_WRITE_ADDR, phy_id, devad);
+ }
+
+ /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
+ /* check for read or write opt is finished */
+ ret = hns_mdio_wait_ready(bus);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO bus is busy\n");
+ return ret;
+ }
+
+ reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);
+ if (reg_val) {
+ dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");
+ return -EBUSY;
+ }
+
+ /* Step 6; get out data*/
+ reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,
+ MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);
+
+ return reg_val;
+}
+
+/**
+ * hns_mdio_reset - reset mdio bus
+ * @bus: mdio bus
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_mdio_reset(struct mii_bus *bus)
+{
+ struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
+ int ret;
+
+ if (!mdio_dev->subctrl_vbase) {
+ dev_err(&bus->dev, "mdio sys ctl reg has not maped\n");
+ return -ENODEV;
+ }
+
+ /*1. reset req, and read reset st check*/
+ ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_REQ, 0x1,
+ MDIO_SC_RESET_ST, 0x1,
+ MDIO_CHECK_SET_ST);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO reset fail\n");
+ return ret;
+ }
+
+ /*2. dis clk, and read clk st check*/
+ ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_DIS,
+ 0x1, MDIO_SC_CLK_ST, 0x1,
+ MDIO_CHECK_CLR_ST);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO dis clk fail\n");
+ return ret;
+ }
+
+ /*3. reset dreq, and read reset st check*/
+ ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_DREQ, 0x1,
+ MDIO_SC_RESET_ST, 0x1,
+ MDIO_CHECK_CLR_ST);
+ if (ret) {
+ dev_err(&bus->dev, "MDIO dis clk fail\n");
+ return ret;
+ }
+
+ /*4. en clk, and read clk st check*/
+ ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_EN,
+ 0x1, MDIO_SC_CLK_ST, 0x1,
+ MDIO_CHECK_SET_ST);
+ if (ret)
+ dev_err(&bus->dev, "MDIO en clk fail\n");
+
+ return ret;
+}
+
+/**
+ * hns_mdio_bus_name - get mdio bus name
+ * @name: mdio bus name
+ * @np: mdio device node pointer
+ */
+static void hns_mdio_bus_name(char *name, struct device_node *np)
+{
+ const u32 *addr;
+ u64 taddr = OF_BAD_ADDR;
+
+ addr = of_get_address(np, 0, NULL, NULL);
+ if (addr)
+ taddr = of_translate_address(np, addr);
+
+ snprintf(name, MII_BUS_ID_SIZE, "%s@%llx", np->name,
+ (unsigned long long)taddr);
+}
+
+/**
+ * hns_mdio_probe - probe mdio device
+ * @pdev: mdio platform device
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_mdio_probe(struct platform_device *pdev)
+{
+ struct device_node *np;
+ struct hns_mdio_device *mdio_dev;
+ struct mii_bus *new_bus;
+ struct resource *res;
+ int ret;
+
+ if (!pdev) {
+ dev_err(NULL, "pdev is NULL!\r\n");
+ return -ENODEV;
+ }
+ np = pdev->dev.of_node;
+ mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL);
+ if (!mdio_dev)
+ return -ENOMEM;
+
+ new_bus = devm_mdiobus_alloc(&pdev->dev);
+ if (!new_bus) {
+ dev_err(&pdev->dev, "mdiobus_alloc fail!\n");
+ return -ENOMEM;
+ }
+
+ new_bus->name = MDIO_BUS_NAME;
+ new_bus->read = hns_mdio_read;
+ new_bus->write = hns_mdio_write;
+ new_bus->reset = hns_mdio_reset;
+ new_bus->priv = mdio_dev;
+ hns_mdio_bus_name(new_bus->id, np);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mdio_dev->vbase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mdio_dev->vbase)) {
+ ret = PTR_ERR(mdio_dev->vbase);
+ return ret;
+ }
+
+ mdio_dev->subctrl_vbase =
+ syscon_node_to_regmap(of_parse_phandle(np, "subctrl_vbase", 0));
+ if (IS_ERR(mdio_dev->subctrl_vbase)) {
+ dev_warn(&pdev->dev, "no syscon hisilicon,peri-c-subctrl\n");
+ mdio_dev->subctrl_vbase = NULL;
+ }
+ new_bus->irq = devm_kcalloc(&pdev->dev, PHY_MAX_ADDR,
+ sizeof(int), GFP_KERNEL);
+ if (!new_bus->irq)
+ return -ENOMEM;
+
+ new_bus->parent = &pdev->dev;
+ platform_set_drvdata(pdev, new_bus);
+
+ ret = of_mdiobus_register(new_bus, np);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot register as MDIO bus!\n");
+ platform_set_drvdata(pdev, NULL);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * hns_mdio_remove - remove mdio device
+ * @pdev: mdio platform device
+ *
+ * Return 0 on success, negative on failure
+ */
+static int hns_mdio_remove(struct platform_device *pdev)
+{
+ struct mii_bus *bus;
+
+ bus = platform_get_drvdata(pdev);
+
+ mdiobus_unregister(bus);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static const struct of_device_id hns_mdio_match[] = {
+ {.compatible = "hisilicon,mdio"},
+ {.compatible = "hisilicon,hns-mdio"},
+ {}
+};
+
+static struct platform_driver hns_mdio_driver = {
+ .probe = hns_mdio_probe,
+ .remove = hns_mdio_remove,
+ .driver = {
+ .name = MDIO_DRV_NAME,
+ .of_match_table = hns_mdio_match,
+ },
+};
+
+module_platform_driver(hns_mdio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
+MODULE_DESCRIPTION("Hisilicon HNS MDIO driver");
+MODULE_ALIAS("platform:" MDIO_DRV_NAME);
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index b60a34d982a9..5d7db6c01c46 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -2204,7 +2204,6 @@ static void emac_ethtool_get_drvinfo(struct net_device *ndev,
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
snprintf(info->bus_info, sizeof(info->bus_info), "PPC 4xx EMAC-%d %s",
dev->cell_index, dev->ofdev->dev.of_node->full_name);
- info->regdump_len = emac_ethtool_get_regs_len(ndev);
}
static const struct ethtool_ops emac_ethtool_ops = {
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index ac02c675c59c..93ae11494810 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -181,7 +181,7 @@ struct emac_instance {
struct mal_commac commac;
/* PHY infos */
- u32 phy_mode;
+ int phy_mode;
u32 phy_map;
u32 phy_address;
u32 phy_feat_exc;
diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig
deleted file mode 100644
index 14a66e9d2e26..000000000000
--- a/drivers/net/ethernet/icplus/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# IC Plus device configuration
-#
-
-config IP1000
- tristate "IP1000 Gigabit Ethernet support"
- depends on PCI
- select MII
- ---help---
- This driver supports IP1000 gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called ipg. This is recommended.
diff --git a/drivers/net/ethernet/icplus/Makefile b/drivers/net/ethernet/icplus/Makefile
deleted file mode 100644
index 5bc87c1f36aa..000000000000
--- a/drivers/net/ethernet/icplus/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the IC Plus device drivers
-#
-
-obj-$(CONFIG_IP1000) += ipg.o
diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
deleted file mode 100644
index c3b6af83f070..000000000000
--- a/drivers/net/ethernet/icplus/ipg.c
+++ /dev/null
@@ -1,2300 +0,0 @@
-/*
- * ipg.c: Device Driver for the IP1000 Gigabit Ethernet Adapter
- *
- * Copyright (C) 2003, 2007 IC Plus Corp
- *
- * Original Author:
- *
- * Craig Rich
- * Sundance Technology, Inc.
- * www.sundanceti.com
- * craig_rich@sundanceti.com
- *
- * Current Maintainer:
- *
- * Sorbica Shieh.
- * http://www.icplus.com.tw
- * sorbica@icplus.com.tw
- *
- * Jesse Huang
- * http://www.icplus.com.tw
- * jesse@icplus.com.tw
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/interrupt.h>
-#include <linux/gfp.h>
-#include <linux/mii.h>
-#include <linux/mutex.h>
-
-#include <asm/div64.h>
-
-#define IPG_RX_RING_BYTES (sizeof(struct ipg_rx) * IPG_RFDLIST_LENGTH)
-#define IPG_TX_RING_BYTES (sizeof(struct ipg_tx) * IPG_TFDLIST_LENGTH)
-#define IPG_RESET_MASK \
- (IPG_AC_GLOBAL_RESET | IPG_AC_RX_RESET | IPG_AC_TX_RESET | \
- IPG_AC_DMA | IPG_AC_FIFO | IPG_AC_NETWORK | IPG_AC_HOST | \
- IPG_AC_AUTO_INIT)
-
-#define ipg_w32(val32, reg) iowrite32((val32), ioaddr + (reg))
-#define ipg_w16(val16, reg) iowrite16((val16), ioaddr + (reg))
-#define ipg_w8(val8, reg) iowrite8((val8), ioaddr + (reg))
-
-#define ipg_r32(reg) ioread32(ioaddr + (reg))
-#define ipg_r16(reg) ioread16(ioaddr + (reg))
-#define ipg_r8(reg) ioread8(ioaddr + (reg))
-
-enum {
- netdev_io_size = 128
-};
-
-#include "ipg.h"
-#define DRV_NAME "ipg"
-
-MODULE_AUTHOR("IC Plus Corp. 2003");
-MODULE_DESCRIPTION("IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Defaults
- */
-#define IPG_MAX_RXFRAME_SIZE 0x0600
-#define IPG_RXFRAG_SIZE 0x0600
-#define IPG_RXSUPPORT_SIZE 0x0600
-#define IPG_IS_JUMBO false
-
-/*
- * Variable record -- index by leading revision/length
- * Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
- */
-static const unsigned short DefaultPhyParam[] = {
- /* 11/12/03 IP1000A v1-3 rev=0x40 */
- /*--------------------------------------------------------------------------
- (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2,
- 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6,
- 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700,
- --------------------------------------------------------------------------*/
- /* 12/17/03 IP1000A v1-4 rev=0x40 */
- (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
- 0x0000,
- 30, 0x005e, 9, 0x0700,
- /* 01/09/04 IP1000A v1-5 rev=0x41 */
- (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
- 0x0000,
- 30, 0x005e, 9, 0x0700,
- 0x0000
-};
-
-static const char * const ipg_brand_name[] = {
- "IC PLUS IP1000 1000/100/10 based NIC",
- "Sundance Technology ST2021 based NIC",
- "Tamarack Microelectronics TC9020/9021 based NIC",
- "D-Link NIC IP1000A"
-};
-
-static const struct pci_device_id ipg_pci_tbl[] = {
- { PCI_VDEVICE(SUNDANCE, 0x1023), 0 },
- { PCI_VDEVICE(SUNDANCE, 0x2021), 1 },
- { PCI_VDEVICE(DLINK, 0x9021), 2 },
- { PCI_VDEVICE(DLINK, 0x4020), 3 },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, ipg_pci_tbl);
-
-static inline void __iomem *ipg_ioaddr(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- return sp->ioaddr;
-}
-
-#ifdef IPG_DEBUG
-static void ipg_dump_rfdlist(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
- u32 offset;
-
- IPG_DEBUG_MSG("_dump_rfdlist\n");
-
- netdev_info(dev, "rx_current = %02x\n", sp->rx_current);
- netdev_info(dev, "rx_dirty = %02x\n", sp->rx_dirty);
- netdev_info(dev, "RFDList start address = %016lx\n",
- (unsigned long)sp->rxd_map);
- netdev_info(dev, "RFDListPtr register = %08x%08x\n",
- ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0));
-
- for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
- offset = (u32) &sp->rxd[i].next_desc - (u32) sp->rxd;
- netdev_info(dev, "%02x %04x RFDNextPtr = %016lx\n",
- i, offset, (unsigned long)sp->rxd[i].next_desc);
- offset = (u32) &sp->rxd[i].rfs - (u32) sp->rxd;
- netdev_info(dev, "%02x %04x RFS = %016lx\n",
- i, offset, (unsigned long)sp->rxd[i].rfs);
- offset = (u32) &sp->rxd[i].frag_info - (u32) sp->rxd;
- netdev_info(dev, "%02x %04x frag_info = %016lx\n",
- i, offset, (unsigned long)sp->rxd[i].frag_info);
- }
-}
-
-static void ipg_dump_tfdlist(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
- u32 offset;
-
- IPG_DEBUG_MSG("_dump_tfdlist\n");
-
- netdev_info(dev, "tx_current = %02x\n", sp->tx_current);
- netdev_info(dev, "tx_dirty = %02x\n", sp->tx_dirty);
- netdev_info(dev, "TFDList start address = %016lx\n",
- (unsigned long) sp->txd_map);
- netdev_info(dev, "TFDListPtr register = %08x%08x\n",
- ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0));
-
- for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
- offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd;
- netdev_info(dev, "%02x %04x TFDNextPtr = %016lx\n",
- i, offset, (unsigned long)sp->txd[i].next_desc);
-
- offset = (u32) &sp->txd[i].tfc - (u32) sp->txd;
- netdev_info(dev, "%02x %04x TFC = %016lx\n",
- i, offset, (unsigned long) sp->txd[i].tfc);
- offset = (u32) &sp->txd[i].frag_info - (u32) sp->txd;
- netdev_info(dev, "%02x %04x frag_info = %016lx\n",
- i, offset, (unsigned long) sp->txd[i].frag_info);
- }
-}
-#endif
-
-static void ipg_write_phy_ctl(void __iomem *ioaddr, u8 data)
-{
- ipg_w8(IPG_PC_RSVD_MASK & data, PHY_CTRL);
- ndelay(IPG_PC_PHYCTRLWAIT_NS);
-}
-
-static void ipg_drive_phy_ctl_low_high(void __iomem *ioaddr, u8 data)
-{
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | data);
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | data);
-}
-
-static void send_three_state(void __iomem *ioaddr, u8 phyctrlpolarity)
-{
- phyctrlpolarity |= (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR;
-
- ipg_drive_phy_ctl_low_high(ioaddr, phyctrlpolarity);
-}
-
-static void send_end(void __iomem *ioaddr, u8 phyctrlpolarity)
-{
- ipg_w8((IPG_PC_MGMTCLK_LO | (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR |
- phyctrlpolarity) & IPG_PC_RSVD_MASK, PHY_CTRL);
-}
-
-static u16 read_phy_bit(void __iomem *ioaddr, u8 phyctrlpolarity)
-{
- u16 bit_data;
-
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | phyctrlpolarity);
-
- bit_data = ((ipg_r8(PHY_CTRL) & IPG_PC_MGMTDATA) >> 1) & 1;
-
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | phyctrlpolarity);
-
- return bit_data;
-}
-
-/*
- * Read a register from the Physical Layer device located
- * on the IPG NIC, using the IPG PHYCTRL register.
- */
-static int mdio_read(struct net_device *dev, int phy_id, int phy_reg)
-{
- void __iomem *ioaddr = ipg_ioaddr(dev);
- /*
- * The GMII mangement frame structure for a read is as follows:
- *
- * |Preamble|st|op|phyad|regad|ta| data |idle|
- * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z |
- *
- * <32 1s> = 32 consecutive logic 1 values
- * A = bit of Physical Layer device address (MSB first)
- * R = bit of register address (MSB first)
- * z = High impedance state
- * D = bit of read data (MSB first)
- *
- * Transmission order is 'Preamble' field first, bits transmitted
- * left to right (first to last).
- */
- struct {
- u32 field;
- unsigned int len;
- } p[] = {
- { GMII_PREAMBLE, 32 }, /* Preamble */
- { GMII_ST, 2 }, /* ST */
- { GMII_READ, 2 }, /* OP */
- { phy_id, 5 }, /* PHYAD */
- { phy_reg, 5 }, /* REGAD */
- { 0x0000, 2 }, /* TA */
- { 0x0000, 16 }, /* DATA */
- { 0x0000, 1 } /* IDLE */
- };
- unsigned int i, j;
- u8 polarity, data;
-
- polarity = ipg_r8(PHY_CTRL);
- polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
- /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
- for (j = 0; j < 5; j++) {
- for (i = 0; i < p[j].len; i++) {
- /* For each variable length field, the MSB must be
- * transmitted first. Rotate through the field bits,
- * starting with the MSB, and move each bit into the
- * the 1st (2^1) bit position (this is the bit position
- * corresponding to the MgmtData bit of the PhyCtrl
- * register for the IPG).
- *
- * Example: ST = 01;
- *
- * First write a '0' to bit 1 of the PhyCtrl
- * register, then write a '1' to bit 1 of the
- * PhyCtrl register.
- *
- * To do this, right shift the MSB of ST by the value:
- * [field length - 1 - #ST bits already written]
- * then left shift this result by 1.
- */
- data = (p[j].field >> (p[j].len - 1 - i)) << 1;
- data &= IPG_PC_MGMTDATA;
- data |= polarity | IPG_PC_MGMTDIR;
-
- ipg_drive_phy_ctl_low_high(ioaddr, data);
- }
- }
-
- send_three_state(ioaddr, polarity);
-
- read_phy_bit(ioaddr, polarity);
-
- /*
- * For a read cycle, the bits for the next two fields (TA and
- * DATA) are driven by the PHY (the IPG reads these bits).
- */
- for (i = 0; i < p[6].len; i++) {
- p[6].field |=
- (read_phy_bit(ioaddr, polarity) << (p[6].len - 1 - i));
- }
-
- send_three_state(ioaddr, polarity);
- send_three_state(ioaddr, polarity);
- send_three_state(ioaddr, polarity);
- send_end(ioaddr, polarity);
-
- /* Return the value of the DATA field. */
- return p[6].field;
-}
-
-/*
- * Write to a register from the Physical Layer device located
- * on the IPG NIC, using the IPG PHYCTRL register.
- */
-static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val)
-{
- void __iomem *ioaddr = ipg_ioaddr(dev);
- /*
- * The GMII mangement frame structure for a read is as follows:
- *
- * |Preamble|st|op|phyad|regad|ta| data |idle|
- * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z |
- *
- * <32 1s> = 32 consecutive logic 1 values
- * A = bit of Physical Layer device address (MSB first)
- * R = bit of register address (MSB first)
- * z = High impedance state
- * D = bit of write data (MSB first)
- *
- * Transmission order is 'Preamble' field first, bits transmitted
- * left to right (first to last).
- */
- struct {
- u32 field;
- unsigned int len;
- } p[] = {
- { GMII_PREAMBLE, 32 }, /* Preamble */
- { GMII_ST, 2 }, /* ST */
- { GMII_WRITE, 2 }, /* OP */
- { phy_id, 5 }, /* PHYAD */
- { phy_reg, 5 }, /* REGAD */
- { 0x0002, 2 }, /* TA */
- { val & 0xffff, 16 }, /* DATA */
- { 0x0000, 1 } /* IDLE */
- };
- unsigned int i, j;
- u8 polarity, data;
-
- polarity = ipg_r8(PHY_CTRL);
- polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
- /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
- for (j = 0; j < 7; j++) {
- for (i = 0; i < p[j].len; i++) {
- /* For each variable length field, the MSB must be
- * transmitted first. Rotate through the field bits,
- * starting with the MSB, and move each bit into the
- * the 1st (2^1) bit position (this is the bit position
- * corresponding to the MgmtData bit of the PhyCtrl
- * register for the IPG).
- *
- * Example: ST = 01;
- *
- * First write a '0' to bit 1 of the PhyCtrl
- * register, then write a '1' to bit 1 of the
- * PhyCtrl register.
- *
- * To do this, right shift the MSB of ST by the value:
- * [field length - 1 - #ST bits already written]
- * then left shift this result by 1.
- */
- data = (p[j].field >> (p[j].len - 1 - i)) << 1;
- data &= IPG_PC_MGMTDATA;
- data |= polarity | IPG_PC_MGMTDIR;
-
- ipg_drive_phy_ctl_low_high(ioaddr, data);
- }
- }
-
- /* The last cycle is a tri-state, so read from the PHY. */
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity);
- ipg_r8(PHY_CTRL);
- ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity);
-}
-
-static void ipg_set_led_mode(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- u32 mode;
-
- mode = ipg_r32(ASIC_CTRL);
- mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED);
-
- if ((sp->led_mode & 0x03) > 1)
- mode |= IPG_AC_LED_MODE_BIT_1; /* Write Asic Control Bit 29 */
-
- if ((sp->led_mode & 0x01) == 1)
- mode |= IPG_AC_LED_MODE; /* Write Asic Control Bit 14 */
-
- if ((sp->led_mode & 0x08) == 8)
- mode |= IPG_AC_LED_SPEED; /* Write Asic Control Bit 27 */
-
- ipg_w32(mode, ASIC_CTRL);
-}
-
-static void ipg_set_phy_set(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- int physet;
-
- physet = ipg_r8(PHY_SET);
- physet &= ~(IPG_PS_MEM_LENB9B | IPG_PS_MEM_LEN9 | IPG_PS_NON_COMPDET);
- physet |= ((sp->led_mode & 0x70) >> 4);
- ipg_w8(physet, PHY_SET);
-}
-
-static int ipg_reset(struct net_device *dev, u32 resetflags)
-{
- /* Assert functional resets via the IPG AsicCtrl
- * register as specified by the 'resetflags' input
- * parameter.
- */
- void __iomem *ioaddr = ipg_ioaddr(dev);
- unsigned int timeout_count = 0;
-
- IPG_DEBUG_MSG("_reset\n");
-
- ipg_w32(ipg_r32(ASIC_CTRL) | resetflags, ASIC_CTRL);
-
- /* Delay added to account for problem with 10Mbps reset. */
- mdelay(IPG_AC_RESETWAIT);
-
- while (IPG_AC_RESET_BUSY & ipg_r32(ASIC_CTRL)) {
- mdelay(IPG_AC_RESETWAIT);
- if (++timeout_count > IPG_AC_RESET_TIMEOUT)
- return -ETIME;
- }
- /* Set LED Mode in Asic Control */
- ipg_set_led_mode(dev);
-
- /* Set PHYSet Register Value */
- ipg_set_phy_set(dev);
- return 0;
-}
-
-/* Find the GMII PHY address. */
-static int ipg_find_phyaddr(struct net_device *dev)
-{
- unsigned int phyaddr, i;
-
- for (i = 0; i < 32; i++) {
- u32 status;
-
- /* Search for the correct PHY address among 32 possible. */
- phyaddr = (IPG_NIC_PHY_ADDRESS + i) % 32;
-
- /* 10/22/03 Grace change verify from GMII_PHY_STATUS to
- GMII_PHY_ID1
- */
-
- status = mdio_read(dev, phyaddr, MII_BMSR);
-
- if ((status != 0xFFFF) && (status != 0))
- return phyaddr;
- }
-
- return 0x1f;
-}
-
-/*
- * Configure IPG based on result of IEEE 802.3 PHY
- * auto-negotiation.
- */
-static int ipg_config_autoneg(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int txflowcontrol;
- unsigned int rxflowcontrol;
- unsigned int fullduplex;
- u32 mac_ctrl_val;
- u32 asicctrl;
- u8 phyctrl;
- const char *speed;
- const char *duplex;
- const char *tx_desc;
- const char *rx_desc;
-
- IPG_DEBUG_MSG("_config_autoneg\n");
-
- asicctrl = ipg_r32(ASIC_CTRL);
- phyctrl = ipg_r8(PHY_CTRL);
- mac_ctrl_val = ipg_r32(MAC_CTRL);
-
- /* Set flags for use in resolving auto-negotiation, assuming
- * non-1000Mbps, half duplex, no flow control.
- */
- fullduplex = 0;
- txflowcontrol = 0;
- rxflowcontrol = 0;
-
- /* To accommodate a problem in 10Mbps operation,
- * set a global flag if PHY running in 10Mbps mode.
- */
- sp->tenmbpsmode = 0;
-
- /* Determine actual speed of operation. */
- switch (phyctrl & IPG_PC_LINK_SPEED) {
- case IPG_PC_LINK_SPEED_10MBPS:
- speed = "10Mbps";
- sp->tenmbpsmode = 1;
- break;
- case IPG_PC_LINK_SPEED_100MBPS:
- speed = "100Mbps";
- break;
- case IPG_PC_LINK_SPEED_1000MBPS:
- speed = "1000Mbps";
- break;
- default:
- speed = "undefined!";
- return 0;
- }
-
- netdev_info(dev, "Link speed = %s\n", speed);
- if (sp->tenmbpsmode == 1)
- netdev_info(dev, "10Mbps operational mode enabled\n");
-
- if (phyctrl & IPG_PC_DUPLEX_STATUS) {
- fullduplex = 1;
- txflowcontrol = 1;
- rxflowcontrol = 1;
- }
-
- /* Configure full duplex, and flow control. */
- if (fullduplex == 1) {
-
- /* Configure IPG for full duplex operation. */
-
- duplex = "full";
-
- mac_ctrl_val |= IPG_MC_DUPLEX_SELECT_FD;
-
- if (txflowcontrol == 1) {
- tx_desc = "";
- mac_ctrl_val |= IPG_MC_TX_FLOW_CONTROL_ENABLE;
- } else {
- tx_desc = "no ";
- mac_ctrl_val &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE;
- }
-
- if (rxflowcontrol == 1) {
- rx_desc = "";
- mac_ctrl_val |= IPG_MC_RX_FLOW_CONTROL_ENABLE;
- } else {
- rx_desc = "no ";
- mac_ctrl_val &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
- }
- } else {
- duplex = "half";
- tx_desc = "no ";
- rx_desc = "no ";
- mac_ctrl_val &= (~IPG_MC_DUPLEX_SELECT_FD &
- ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
- ~IPG_MC_RX_FLOW_CONTROL_ENABLE);
- }
-
- netdev_info(dev, "setting %s duplex, %sTX, %sRX flow control\n",
- duplex, tx_desc, rx_desc);
- ipg_w32(mac_ctrl_val, MAC_CTRL);
-
- return 0;
-}
-
-/* Determine and configure multicast operation and set
- * receive mode for IPG.
- */
-static void ipg_nic_set_multicast_list(struct net_device *dev)
-{
- void __iomem *ioaddr = ipg_ioaddr(dev);
- struct netdev_hw_addr *ha;
- unsigned int hashindex;
- u32 hashtable[2];
- u8 receivemode;
-
- IPG_DEBUG_MSG("_nic_set_multicast_list\n");
-
- receivemode = IPG_RM_RECEIVEUNICAST | IPG_RM_RECEIVEBROADCAST;
-
- if (dev->flags & IFF_PROMISC) {
- /* NIC to be configured in promiscuous mode. */
- receivemode = IPG_RM_RECEIVEALLFRAMES;
- } else if ((dev->flags & IFF_ALLMULTI) ||
- ((dev->flags & IFF_MULTICAST) &&
- (netdev_mc_count(dev) > IPG_MULTICAST_HASHTABLE_SIZE))) {
- /* NIC to be configured to receive all multicast
- * frames. */
- receivemode |= IPG_RM_RECEIVEMULTICAST;
- } else if ((dev->flags & IFF_MULTICAST) && !netdev_mc_empty(dev)) {
- /* NIC to be configured to receive selected
- * multicast addresses. */
- receivemode |= IPG_RM_RECEIVEMULTICASTHASH;
- }
-
- /* Calculate the bits to set for the 64 bit, IPG HASHTABLE.
- * The IPG applies a cyclic-redundancy-check (the same CRC
- * used to calculate the frame data FCS) to the destination
- * address all incoming multicast frames whose destination
- * address has the multicast bit set. The least significant
- * 6 bits of the CRC result are used as an addressing index
- * into the hash table. If the value of the bit addressed by
- * this index is a 1, the frame is passed to the host system.
- */
-
- /* Clear hashtable. */
- hashtable[0] = 0x00000000;
- hashtable[1] = 0x00000000;
-
- /* Cycle through all multicast addresses to filter. */
- netdev_for_each_mc_addr(ha, dev) {
- /* Calculate CRC result for each multicast address. */
- hashindex = crc32_le(0xffffffff, ha->addr,
- ETH_ALEN);
-
- /* Use only the least significant 6 bits. */
- hashindex = hashindex & 0x3F;
-
- /* Within "hashtable", set bit number "hashindex"
- * to a logic 1.
- */
- set_bit(hashindex, (void *)hashtable);
- }
-
- /* Write the value of the hashtable, to the 4, 16 bit
- * HASHTABLE IPG registers.
- */
- ipg_w32(hashtable[0], HASHTABLE_0);
- ipg_w32(hashtable[1], HASHTABLE_1);
-
- ipg_w8(IPG_RM_RSVD_MASK & receivemode, RECEIVE_MODE);
-
- IPG_DEBUG_MSG("ReceiveMode = %x\n", ipg_r8(RECEIVE_MODE));
-}
-
-static int ipg_io_config(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = ipg_ioaddr(dev);
- u32 origmacctrl;
- u32 restoremacctrl;
-
- IPG_DEBUG_MSG("_io_config\n");
-
- origmacctrl = ipg_r32(MAC_CTRL);
-
- restoremacctrl = origmacctrl | IPG_MC_STATISTICS_ENABLE;
-
- /* Based on compilation option, determine if FCS is to be
- * stripped on receive frames by IPG.
- */
- if (!IPG_STRIP_FCS_ON_RX)
- restoremacctrl |= IPG_MC_RCV_FCS;
-
- /* Determine if transmitter and/or receiver are
- * enabled so we may restore MACCTRL correctly.
- */
- if (origmacctrl & IPG_MC_TX_ENABLED)
- restoremacctrl |= IPG_MC_TX_ENABLE;
-
- if (origmacctrl & IPG_MC_RX_ENABLED)
- restoremacctrl |= IPG_MC_RX_ENABLE;
-
- /* Transmitter and receiver must be disabled before setting
- * IFSSelect.
- */
- ipg_w32((origmacctrl & (IPG_MC_RX_DISABLE | IPG_MC_TX_DISABLE)) &
- IPG_MC_RSVD_MASK, MAC_CTRL);
-
- /* Now that transmitter and receiver are disabled, write
- * to IFSSelect.
- */
- ipg_w32((origmacctrl & IPG_MC_IFS_96BIT) & IPG_MC_RSVD_MASK, MAC_CTRL);
-
- /* Set RECEIVEMODE register. */
- ipg_nic_set_multicast_list(dev);
-
- ipg_w16(sp->max_rxframe_size, MAX_FRAME_SIZE);
-
- ipg_w8(IPG_RXDMAPOLLPERIOD_VALUE, RX_DMA_POLL_PERIOD);
- ipg_w8(IPG_RXDMAURGENTTHRESH_VALUE, RX_DMA_URGENT_THRESH);
- ipg_w8(IPG_RXDMABURSTTHRESH_VALUE, RX_DMA_BURST_THRESH);
- ipg_w8(IPG_TXDMAPOLLPERIOD_VALUE, TX_DMA_POLL_PERIOD);
- ipg_w8(IPG_TXDMAURGENTTHRESH_VALUE, TX_DMA_URGENT_THRESH);
- ipg_w8(IPG_TXDMABURSTTHRESH_VALUE, TX_DMA_BURST_THRESH);
- ipg_w16((IPG_IE_HOST_ERROR | IPG_IE_TX_DMA_COMPLETE |
- IPG_IE_TX_COMPLETE | IPG_IE_INT_REQUESTED |
- IPG_IE_UPDATE_STATS | IPG_IE_LINK_EVENT |
- IPG_IE_RX_DMA_COMPLETE | IPG_IE_RX_DMA_PRIORITY), INT_ENABLE);
- ipg_w16(IPG_FLOWONTHRESH_VALUE, FLOW_ON_THRESH);
- ipg_w16(IPG_FLOWOFFTHRESH_VALUE, FLOW_OFF_THRESH);
-
- /* IPG multi-frag frame bug workaround.
- * Per silicon revision B3 eratta.
- */
- ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0200, DEBUG_CTRL);
-
- /* IPG TX poll now bug workaround.
- * Per silicon revision B3 eratta.
- */
- ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0010, DEBUG_CTRL);
-
- /* IPG RX poll now bug workaround.
- * Per silicon revision B3 eratta.
- */
- ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0020, DEBUG_CTRL);
-
- /* Now restore MACCTRL to original setting. */
- ipg_w32(IPG_MC_RSVD_MASK & restoremacctrl, MAC_CTRL);
-
- /* Disable unused RMON statistics. */
- ipg_w32(IPG_RZ_ALL, RMON_STATISTICS_MASK);
-
- /* Disable unused MIB statistics. */
- ipg_w32(IPG_SM_MACCONTROLFRAMESXMTD | IPG_SM_MACCONTROLFRAMESRCVD |
- IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK | IPG_SM_TXJUMBOFRAMES |
- IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK | IPG_SM_RXJUMBOFRAMES |
- IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK |
- IPG_SM_UDPCHECKSUMERRORS | IPG_SM_TCPCHECKSUMERRORS |
- IPG_SM_IPCHECKSUMERRORS, STATISTICS_MASK);
-
- return 0;
-}
-
-/*
- * Create a receive buffer within system memory and update
- * NIC private structure appropriately.
- */
-static int ipg_get_rxbuff(struct net_device *dev, int entry)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- struct ipg_rx *rxfd = sp->rxd + entry;
- struct sk_buff *skb;
- u64 rxfragsize;
-
- IPG_DEBUG_MSG("_get_rxbuff\n");
-
- skb = netdev_alloc_skb_ip_align(dev, sp->rxsupport_size);
- if (!skb) {
- sp->rx_buff[entry] = NULL;
- return -ENOMEM;
- }
-
- /* Save the address of the sk_buff structure. */
- sp->rx_buff[entry] = skb;
-
- rxfd->frag_info = cpu_to_le64(pci_map_single(sp->pdev, skb->data,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE));
-
- /* Set the RFD fragment length. */
- rxfragsize = sp->rxfrag_size;
- rxfd->frag_info |= cpu_to_le64((rxfragsize << 48) & IPG_RFI_FRAGLEN);
-
- return 0;
-}
-
-static int init_rfdlist(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
-
- IPG_DEBUG_MSG("_init_rfdlist\n");
-
- for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
- struct ipg_rx *rxfd = sp->rxd + i;
-
- if (sp->rx_buff[i]) {
- pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
- dev_kfree_skb_irq(sp->rx_buff[i]);
- sp->rx_buff[i] = NULL;
- }
-
- /* Clear out the RFS field. */
- rxfd->rfs = 0x0000000000000000;
-
- if (ipg_get_rxbuff(dev, i) < 0) {
- /*
- * A receive buffer was not ready, break the
- * RFD list here.
- */
- IPG_DEBUG_MSG("Cannot allocate Rx buffer\n");
-
- /* Just in case we cannot allocate a single RFD.
- * Should not occur.
- */
- if (i == 0) {
- netdev_err(dev, "No memory available for RFD list\n");
- return -ENOMEM;
- }
- }
-
- rxfd->next_desc = cpu_to_le64(sp->rxd_map +
- sizeof(struct ipg_rx)*(i + 1));
- }
- sp->rxd[i - 1].next_desc = cpu_to_le64(sp->rxd_map);
-
- sp->rx_current = 0;
- sp->rx_dirty = 0;
-
- /* Write the location of the RFDList to the IPG. */
- ipg_w32((u32) sp->rxd_map, RFD_LIST_PTR_0);
- ipg_w32(0x00000000, RFD_LIST_PTR_1);
-
- return 0;
-}
-
-static void init_tfdlist(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
-
- IPG_DEBUG_MSG("_init_tfdlist\n");
-
- for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
- struct ipg_tx *txfd = sp->txd + i;
-
- txfd->tfc = cpu_to_le64(IPG_TFC_TFDDONE);
-
- if (sp->tx_buff[i]) {
- dev_kfree_skb_irq(sp->tx_buff[i]);
- sp->tx_buff[i] = NULL;
- }
-
- txfd->next_desc = cpu_to_le64(sp->txd_map +
- sizeof(struct ipg_tx)*(i + 1));
- }
- sp->txd[i - 1].next_desc = cpu_to_le64(sp->txd_map);
-
- sp->tx_current = 0;
- sp->tx_dirty = 0;
-
- /* Write the location of the TFDList to the IPG. */
- IPG_DDEBUG_MSG("Starting TFDListPtr = %08x\n",
- (u32) sp->txd_map);
- ipg_w32((u32) sp->txd_map, TFD_LIST_PTR_0);
- ipg_w32(0x00000000, TFD_LIST_PTR_1);
-
- sp->reset_current_tfd = 1;
-}
-
-/*
- * Free all transmit buffers which have already been transferred
- * via DMA to the IPG.
- */
-static void ipg_nic_txfree(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- unsigned int released, pending, dirty;
-
- IPG_DEBUG_MSG("_nic_txfree\n");
-
- pending = sp->tx_current - sp->tx_dirty;
- dirty = sp->tx_dirty % IPG_TFDLIST_LENGTH;
-
- for (released = 0; released < pending; released++) {
- struct sk_buff *skb = sp->tx_buff[dirty];
- struct ipg_tx *txfd = sp->txd + dirty;
-
- IPG_DEBUG_MSG("TFC = %016lx\n", (unsigned long) txfd->tfc);
-
- /* Look at each TFD's TFC field beginning
- * at the last freed TFD up to the current TFD.
- * If the TFDDone bit is set, free the associated
- * buffer.
- */
- if (!(txfd->tfc & cpu_to_le64(IPG_TFC_TFDDONE)))
- break;
-
- /* Free the transmit buffer. */
- if (skb) {
- pci_unmap_single(sp->pdev,
- le64_to_cpu(txfd->frag_info) & ~IPG_TFI_FRAGLEN,
- skb->len, PCI_DMA_TODEVICE);
-
- dev_kfree_skb_irq(skb);
-
- sp->tx_buff[dirty] = NULL;
- }
- dirty = (dirty + 1) % IPG_TFDLIST_LENGTH;
- }
-
- sp->tx_dirty += released;
-
- if (netif_queue_stopped(dev) &&
- (sp->tx_current != (sp->tx_dirty + IPG_TFDLIST_LENGTH))) {
- netif_wake_queue(dev);
- }
-}
-
-static void ipg_tx_timeout(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
-
- ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA | IPG_AC_NETWORK |
- IPG_AC_FIFO);
-
- spin_lock_irq(&sp->lock);
-
- /* Re-configure after DMA reset. */
- if (ipg_io_config(dev) < 0)
- netdev_info(dev, "Error during re-configuration\n");
-
- init_tfdlist(dev);
-
- spin_unlock_irq(&sp->lock);
-
- ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) & IPG_MC_RSVD_MASK,
- MAC_CTRL);
-}
-
-/*
- * For TxComplete interrupts, free all transmit
- * buffers which have already been transferred via DMA
- * to the IPG.
- */
-static void ipg_nic_txcleanup(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
-
- IPG_DEBUG_MSG("_nic_txcleanup\n");
-
- for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
- /* Reading the TXSTATUS register clears the
- * TX_COMPLETE interrupt.
- */
- u32 txstatusdword = ipg_r32(TX_STATUS);
-
- IPG_DEBUG_MSG("TxStatus = %08x\n", txstatusdword);
-
- /* Check for Transmit errors. Error bits only valid if
- * TX_COMPLETE bit in the TXSTATUS register is a 1.
- */
- if (!(txstatusdword & IPG_TS_TX_COMPLETE))
- break;
-
- /* If in 10Mbps mode, indicate transmit is ready. */
- if (sp->tenmbpsmode) {
- netif_wake_queue(dev);
- }
-
- /* Transmit error, increment stat counters. */
- if (txstatusdword & IPG_TS_TX_ERROR) {
- IPG_DEBUG_MSG("Transmit error\n");
- sp->stats.tx_errors++;
- }
-
- /* Late collision, re-enable transmitter. */
- if (txstatusdword & IPG_TS_LATE_COLLISION) {
- IPG_DEBUG_MSG("Late collision on transmit\n");
- ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
- IPG_MC_RSVD_MASK, MAC_CTRL);
- }
-
- /* Maximum collisions, re-enable transmitter. */
- if (txstatusdword & IPG_TS_TX_MAX_COLL) {
- IPG_DEBUG_MSG("Maximum collisions on transmit\n");
- ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
- IPG_MC_RSVD_MASK, MAC_CTRL);
- }
-
- /* Transmit underrun, reset and re-enable
- * transmitter.
- */
- if (txstatusdword & IPG_TS_TX_UNDERRUN) {
- IPG_DEBUG_MSG("Transmitter underrun\n");
- sp->stats.tx_fifo_errors++;
- ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA |
- IPG_AC_NETWORK | IPG_AC_FIFO);
-
- /* Re-configure after DMA reset. */
- if (ipg_io_config(dev) < 0) {
- netdev_info(dev, "Error during re-configuration\n");
- }
- init_tfdlist(dev);
-
- ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
- IPG_MC_RSVD_MASK, MAC_CTRL);
- }
- }
-
- ipg_nic_txfree(dev);
-}
-
-/* Provides statistical information about the IPG NIC. */
-static struct net_device_stats *ipg_nic_get_stats(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- u16 temp1;
- u16 temp2;
-
- IPG_DEBUG_MSG("_nic_get_stats\n");
-
- /* Check to see if the NIC has been initialized via nic_open,
- * before trying to read statistic registers.
- */
- if (!netif_running(dev))
- return &sp->stats;
-
- sp->stats.rx_packets += ipg_r32(IPG_FRAMESRCVDOK);
- sp->stats.tx_packets += ipg_r32(IPG_FRAMESXMTDOK);
- sp->stats.rx_bytes += ipg_r32(IPG_OCTETRCVOK);
- sp->stats.tx_bytes += ipg_r32(IPG_OCTETXMTOK);
- temp1 = ipg_r16(IPG_FRAMESLOSTRXERRORS);
- sp->stats.rx_errors += temp1;
- sp->stats.rx_missed_errors += temp1;
- temp1 = ipg_r32(IPG_SINGLECOLFRAMES) + ipg_r32(IPG_MULTICOLFRAMES) +
- ipg_r32(IPG_LATECOLLISIONS);
- temp2 = ipg_r16(IPG_CARRIERSENSEERRORS);
- sp->stats.collisions += temp1;
- sp->stats.tx_dropped += ipg_r16(IPG_FRAMESABORTXSCOLLS);
- sp->stats.tx_errors += ipg_r16(IPG_FRAMESWEXDEFERRAL) +
- ipg_r32(IPG_FRAMESWDEFERREDXMT) + temp1 + temp2;
- sp->stats.multicast += ipg_r32(IPG_MCSTOCTETRCVDOK);
-
- /* detailed tx_errors */
- sp->stats.tx_carrier_errors += temp2;
-
- /* detailed rx_errors */
- sp->stats.rx_length_errors += ipg_r16(IPG_INRANGELENGTHERRORS) +
- ipg_r16(IPG_FRAMETOOLONGERRORS);
- sp->stats.rx_crc_errors += ipg_r16(IPG_FRAMECHECKSEQERRORS);
-
- /* Unutilized IPG statistic registers. */
- ipg_r32(IPG_MCSTFRAMESRCVDOK);
-
- return &sp->stats;
-}
-
-/* Restore used receive buffers. */
-static int ipg_nic_rxrestore(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- const unsigned int curr = sp->rx_current;
- unsigned int dirty = sp->rx_dirty;
-
- IPG_DEBUG_MSG("_nic_rxrestore\n");
-
- for (dirty = sp->rx_dirty; curr - dirty > 0; dirty++) {
- unsigned int entry = dirty % IPG_RFDLIST_LENGTH;
-
- /* rx_copybreak may poke hole here and there. */
- if (sp->rx_buff[entry])
- continue;
-
- /* Generate a new receive buffer to replace the
- * current buffer (which will be released by the
- * Linux system).
- */
- if (ipg_get_rxbuff(dev, entry) < 0) {
- IPG_DEBUG_MSG("Cannot allocate new Rx buffer\n");
-
- break;
- }
-
- /* Reset the RFS field. */
- sp->rxd[entry].rfs = 0x0000000000000000;
- }
- sp->rx_dirty = dirty;
-
- return 0;
-}
-
-/* use jumboindex and jumbosize to control jumbo frame status
- * initial status is jumboindex=-1 and jumbosize=0
- * 1. jumboindex = -1 and jumbosize=0 : previous jumbo frame has been done.
- * 2. jumboindex != -1 and jumbosize != 0 : jumbo frame is not over size and receiving
- * 3. jumboindex = -1 and jumbosize != 0 : jumbo frame is over size, already dump
- * previous receiving and need to continue dumping the current one
- */
-enum {
- NORMAL_PACKET,
- ERROR_PACKET
-};
-
-enum {
- FRAME_NO_START_NO_END = 0,
- FRAME_WITH_START = 1,
- FRAME_WITH_END = 10,
- FRAME_WITH_START_WITH_END = 11
-};
-
-static void ipg_nic_rx_free_skb(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- unsigned int entry = sp->rx_current % IPG_RFDLIST_LENGTH;
-
- if (sp->rx_buff[entry]) {
- struct ipg_rx *rxfd = sp->rxd + entry;
-
- pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
- dev_kfree_skb_irq(sp->rx_buff[entry]);
- sp->rx_buff[entry] = NULL;
- }
-}
-
-static int ipg_nic_rx_check_frame_type(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- struct ipg_rx *rxfd = sp->rxd + (sp->rx_current % IPG_RFDLIST_LENGTH);
- int type = FRAME_NO_START_NO_END;
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMESTART)
- type += FRAME_WITH_START;
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMEEND)
- type += FRAME_WITH_END;
- return type;
-}
-
-static int ipg_nic_rx_check_error(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- unsigned int entry = sp->rx_current % IPG_RFDLIST_LENGTH;
- struct ipg_rx *rxfd = sp->rxd + entry;
-
- if (IPG_DROP_ON_RX_ETH_ERRORS && (le64_to_cpu(rxfd->rfs) &
- (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME |
- IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
- IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR))) {
- IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
- (unsigned long) rxfd->rfs);
-
- /* Increment general receive error statistic. */
- sp->stats.rx_errors++;
-
- /* Increment detailed receive error statistics. */
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
- IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
-
- sp->stats.rx_fifo_errors++;
- }
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
- IPG_DEBUG_MSG("RX runt occurred\n");
- sp->stats.rx_length_errors++;
- }
-
- /* Do nothing for IPG_RFS_RXOVERSIZEDFRAME,
- * error count handled by a IPG statistic register.
- */
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
- IPG_DEBUG_MSG("RX alignment error occurred\n");
- sp->stats.rx_frame_errors++;
- }
-
- /* Do nothing for IPG_RFS_RXFCSERROR, error count
- * handled by a IPG statistic register.
- */
-
- /* Free the memory associated with the RX
- * buffer since it is erroneous and we will
- * not pass it to higher layer processes.
- */
- if (sp->rx_buff[entry]) {
- pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
- dev_kfree_skb_irq(sp->rx_buff[entry]);
- sp->rx_buff[entry] = NULL;
- }
- return ERROR_PACKET;
- }
- return NORMAL_PACKET;
-}
-
-static void ipg_nic_rx_with_start_and_end(struct net_device *dev,
- struct ipg_nic_private *sp,
- struct ipg_rx *rxfd, unsigned entry)
-{
- struct ipg_jumbo *jumbo = &sp->jumbo;
- struct sk_buff *skb;
- int framelen;
-
- if (jumbo->found_start) {
- dev_kfree_skb_irq(jumbo->skb);
- jumbo->found_start = 0;
- jumbo->current_size = 0;
- jumbo->skb = NULL;
- }
-
- /* 1: found error, 0 no error */
- if (ipg_nic_rx_check_error(dev) != NORMAL_PACKET)
- return;
-
- skb = sp->rx_buff[entry];
- if (!skb)
- return;
-
- /* accept this frame and send to upper layer */
- framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
- if (framelen > sp->rxfrag_size)
- framelen = sp->rxfrag_size;
-
- skb_put(skb, framelen);
- skb->protocol = eth_type_trans(skb, dev);
- skb_checksum_none_assert(skb);
- netif_rx(skb);
- sp->rx_buff[entry] = NULL;
-}
-
-static void ipg_nic_rx_with_start(struct net_device *dev,
- struct ipg_nic_private *sp,
- struct ipg_rx *rxfd, unsigned entry)
-{
- struct ipg_jumbo *jumbo = &sp->jumbo;
- struct pci_dev *pdev = sp->pdev;
- struct sk_buff *skb;
-
- /* 1: found error, 0 no error */
- if (ipg_nic_rx_check_error(dev) != NORMAL_PACKET)
- return;
-
- /* accept this frame and send to upper layer */
- skb = sp->rx_buff[entry];
- if (!skb)
- return;
-
- if (jumbo->found_start)
- dev_kfree_skb_irq(jumbo->skb);
-
- pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
- skb_put(skb, sp->rxfrag_size);
-
- jumbo->found_start = 1;
- jumbo->current_size = sp->rxfrag_size;
- jumbo->skb = skb;
-
- sp->rx_buff[entry] = NULL;
-}
-
-static void ipg_nic_rx_with_end(struct net_device *dev,
- struct ipg_nic_private *sp,
- struct ipg_rx *rxfd, unsigned entry)
-{
- struct ipg_jumbo *jumbo = &sp->jumbo;
-
- /* 1: found error, 0 no error */
- if (ipg_nic_rx_check_error(dev) == NORMAL_PACKET) {
- struct sk_buff *skb = sp->rx_buff[entry];
-
- if (!skb)
- return;
-
- if (jumbo->found_start) {
- int framelen, endframelen;
-
- framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
-
- endframelen = framelen - jumbo->current_size;
- if (framelen > sp->rxsupport_size)
- dev_kfree_skb_irq(jumbo->skb);
- else {
- memcpy(skb_put(jumbo->skb, endframelen),
- skb->data, endframelen);
-
- jumbo->skb->protocol =
- eth_type_trans(jumbo->skb, dev);
-
- skb_checksum_none_assert(jumbo->skb);
- netif_rx(jumbo->skb);
- }
- }
-
- jumbo->found_start = 0;
- jumbo->current_size = 0;
- jumbo->skb = NULL;
-
- ipg_nic_rx_free_skb(dev);
- } else {
- dev_kfree_skb_irq(jumbo->skb);
- jumbo->found_start = 0;
- jumbo->current_size = 0;
- jumbo->skb = NULL;
- }
-}
-
-static void ipg_nic_rx_no_start_no_end(struct net_device *dev,
- struct ipg_nic_private *sp,
- struct ipg_rx *rxfd, unsigned entry)
-{
- struct ipg_jumbo *jumbo = &sp->jumbo;
-
- /* 1: found error, 0 no error */
- if (ipg_nic_rx_check_error(dev) == NORMAL_PACKET) {
- struct sk_buff *skb = sp->rx_buff[entry];
-
- if (skb) {
- if (jumbo->found_start) {
- jumbo->current_size += sp->rxfrag_size;
- if (jumbo->current_size <= sp->rxsupport_size) {
- memcpy(skb_put(jumbo->skb,
- sp->rxfrag_size),
- skb->data, sp->rxfrag_size);
- }
- }
- ipg_nic_rx_free_skb(dev);
- }
- } else {
- dev_kfree_skb_irq(jumbo->skb);
- jumbo->found_start = 0;
- jumbo->current_size = 0;
- jumbo->skb = NULL;
- }
-}
-
-static int ipg_nic_rx_jumbo(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- unsigned int curr = sp->rx_current;
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
-
- IPG_DEBUG_MSG("_nic_rx\n");
-
- for (i = 0; i < IPG_MAXRFDPROCESS_COUNT; i++, curr++) {
- unsigned int entry = curr % IPG_RFDLIST_LENGTH;
- struct ipg_rx *rxfd = sp->rxd + entry;
-
- if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE)))
- break;
-
- switch (ipg_nic_rx_check_frame_type(dev)) {
- case FRAME_WITH_START_WITH_END:
- ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry);
- break;
- case FRAME_WITH_START:
- ipg_nic_rx_with_start(dev, sp, rxfd, entry);
- break;
- case FRAME_WITH_END:
- ipg_nic_rx_with_end(dev, sp, rxfd, entry);
- break;
- case FRAME_NO_START_NO_END:
- ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry);
- break;
- }
- }
-
- sp->rx_current = curr;
-
- if (i == IPG_MAXRFDPROCESS_COUNT) {
- /* There are more RFDs to process, however the
- * allocated amount of RFD processing time has
- * expired. Assert Interrupt Requested to make
- * sure we come back to process the remaining RFDs.
- */
- ipg_w32(ipg_r32(ASIC_CTRL) | IPG_AC_INT_REQUEST, ASIC_CTRL);
- }
-
- ipg_nic_rxrestore(dev);
-
- return 0;
-}
-
-static int ipg_nic_rx(struct net_device *dev)
-{
- /* Transfer received Ethernet frames to higher network layers. */
- struct ipg_nic_private *sp = netdev_priv(dev);
- unsigned int curr = sp->rx_current;
- void __iomem *ioaddr = sp->ioaddr;
- struct ipg_rx *rxfd;
- unsigned int i;
-
- IPG_DEBUG_MSG("_nic_rx\n");
-
-#define __RFS_MASK \
- cpu_to_le64(IPG_RFS_RFDDONE | IPG_RFS_FRAMESTART | IPG_RFS_FRAMEEND)
-
- for (i = 0; i < IPG_MAXRFDPROCESS_COUNT; i++, curr++) {
- unsigned int entry = curr % IPG_RFDLIST_LENGTH;
- struct sk_buff *skb = sp->rx_buff[entry];
- unsigned int framelen;
-
- rxfd = sp->rxd + entry;
-
- if (((rxfd->rfs & __RFS_MASK) != __RFS_MASK) || !skb)
- break;
-
- /* Get received frame length. */
- framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
-
- /* Check for jumbo frame arrival with too small
- * RXFRAG_SIZE.
- */
- if (framelen > sp->rxfrag_size) {
- IPG_DEBUG_MSG
- ("RFS FrameLen > allocated fragment size\n");
-
- framelen = sp->rxfrag_size;
- }
-
- if ((IPG_DROP_ON_RX_ETH_ERRORS && (le64_to_cpu(rxfd->rfs) &
- (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME |
- IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
- IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR)))) {
-
- IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
- (unsigned long int) rxfd->rfs);
-
- /* Increment general receive error statistic. */
- sp->stats.rx_errors++;
-
- /* Increment detailed receive error statistics. */
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
- IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
- sp->stats.rx_fifo_errors++;
- }
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
- IPG_DEBUG_MSG("RX runt occurred\n");
- sp->stats.rx_length_errors++;
- }
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXOVERSIZEDFRAME) ;
- /* Do nothing, error count handled by a IPG
- * statistic register.
- */
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
- IPG_DEBUG_MSG("RX alignment error occurred\n");
- sp->stats.rx_frame_errors++;
- }
-
- if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFCSERROR) ;
- /* Do nothing, error count handled by a IPG
- * statistic register.
- */
-
- /* Free the memory associated with the RX
- * buffer since it is erroneous and we will
- * not pass it to higher layer processes.
- */
- if (skb) {
- __le64 info = rxfd->frag_info;
-
- pci_unmap_single(sp->pdev,
- le64_to_cpu(info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
- dev_kfree_skb_irq(skb);
- }
- } else {
-
- /* Adjust the new buffer length to accommodate the size
- * of the received frame.
- */
- skb_put(skb, framelen);
-
- /* Set the buffer's protocol field to Ethernet. */
- skb->protocol = eth_type_trans(skb, dev);
-
- /* The IPG encountered an error with (or
- * there were no) IP/TCP/UDP checksums.
- * This may or may not indicate an invalid
- * IP/TCP/UDP frame was received. Let the
- * upper layer decide.
- */
- skb_checksum_none_assert(skb);
-
- /* Hand off frame for higher layer processing.
- * The function netif_rx() releases the sk_buff
- * when processing completes.
- */
- netif_rx(skb);
- }
-
- /* Assure RX buffer is not reused by IPG. */
- sp->rx_buff[entry] = NULL;
- }
-
- /*
- * If there are more RFDs to process and the allocated amount of RFD
- * processing time has expired, assert Interrupt Requested to make
- * sure we come back to process the remaining RFDs.
- */
- if (i == IPG_MAXRFDPROCESS_COUNT)
- ipg_w32(ipg_r32(ASIC_CTRL) | IPG_AC_INT_REQUEST, ASIC_CTRL);
-
-#ifdef IPG_DEBUG
- /* Check if the RFD list contained no receive frame data. */
- if (!i)
- sp->EmptyRFDListCount++;
-#endif
- while ((le64_to_cpu(rxfd->rfs) & IPG_RFS_RFDDONE) &&
- !((le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMESTART) &&
- (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMEEND))) {
- unsigned int entry = curr++ % IPG_RFDLIST_LENGTH;
-
- rxfd = sp->rxd + entry;
-
- IPG_DEBUG_MSG("Frame requires multiple RFDs\n");
-
- /* An unexpected event, additional code needed to handle
- * properly. So for the time being, just disregard the
- * frame.
- */
-
- /* Free the memory associated with the RX
- * buffer since it is erroneous and we will
- * not pass it to higher layer processes.
- */
- if (sp->rx_buff[entry]) {
- pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
- dev_kfree_skb_irq(sp->rx_buff[entry]);
- }
-
- /* Assure RX buffer is not reused by IPG. */
- sp->rx_buff[entry] = NULL;
- }
-
- sp->rx_current = curr;
-
- /* Check to see if there are a minimum number of used
- * RFDs before restoring any (should improve performance.)
- */
- if ((curr - sp->rx_dirty) >= IPG_MINUSEDRFDSTOFREE)
- ipg_nic_rxrestore(dev);
-
- return 0;
-}
-
-static void ipg_reset_after_host_error(struct work_struct *work)
-{
- struct ipg_nic_private *sp =
- container_of(work, struct ipg_nic_private, task.work);
- struct net_device *dev = sp->dev;
-
- /*
- * Acknowledge HostError interrupt by resetting
- * IPG DMA and HOST.
- */
- ipg_reset(dev, IPG_AC_GLOBAL_RESET | IPG_AC_HOST | IPG_AC_DMA);
-
- init_rfdlist(dev);
- init_tfdlist(dev);
-
- if (ipg_io_config(dev) < 0) {
- netdev_info(dev, "Cannot recover from PCI error\n");
- schedule_delayed_work(&sp->task, HZ);
- }
-}
-
-static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
-{
- struct net_device *dev = dev_inst;
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int handled = 0;
- u16 status;
-
- IPG_DEBUG_MSG("_interrupt_handler\n");
-
- if (sp->is_jumbo)
- ipg_nic_rxrestore(dev);
-
- spin_lock(&sp->lock);
-
- /* Get interrupt source information, and acknowledge
- * some (i.e. TxDMAComplete, RxDMAComplete, RxEarly,
- * IntRequested, MacControlFrame, LinkEvent) interrupts
- * if issued. Also, all IPG interrupts are disabled by
- * reading IntStatusAck.
- */
- status = ipg_r16(INT_STATUS_ACK);
-
- IPG_DEBUG_MSG("IntStatusAck = %04x\n", status);
-
- /* Shared IRQ of remove event. */
- if (!(status & IPG_IS_RSVD_MASK))
- goto out_enable;
-
- handled = 1;
-
- if (unlikely(!netif_running(dev)))
- goto out_unlock;
-
- /* If RFDListEnd interrupt, restore all used RFDs. */
- if (status & IPG_IS_RFD_LIST_END) {
- IPG_DEBUG_MSG("RFDListEnd Interrupt\n");
-
- /* The RFD list end indicates an RFD was encountered
- * with a 0 NextPtr, or with an RFDDone bit set to 1
- * (indicating the RFD is not read for use by the
- * IPG.) Try to restore all RFDs.
- */
- ipg_nic_rxrestore(dev);
-
-#ifdef IPG_DEBUG
- /* Increment the RFDlistendCount counter. */
- sp->RFDlistendCount++;
-#endif
- }
-
- /* If RFDListEnd, RxDMAPriority, RxDMAComplete, or
- * IntRequested interrupt, process received frames. */
- if ((status & IPG_IS_RX_DMA_PRIORITY) ||
- (status & IPG_IS_RFD_LIST_END) ||
- (status & IPG_IS_RX_DMA_COMPLETE) ||
- (status & IPG_IS_INT_REQUESTED)) {
-#ifdef IPG_DEBUG
- /* Increment the RFD list checked counter if interrupted
- * only to check the RFD list. */
- if (status & (~(IPG_IS_RX_DMA_PRIORITY | IPG_IS_RFD_LIST_END |
- IPG_IS_RX_DMA_COMPLETE | IPG_IS_INT_REQUESTED) &
- (IPG_IS_HOST_ERROR | IPG_IS_TX_DMA_COMPLETE |
- IPG_IS_LINK_EVENT | IPG_IS_TX_COMPLETE |
- IPG_IS_UPDATE_STATS)))
- sp->RFDListCheckedCount++;
-#endif
-
- if (sp->is_jumbo)
- ipg_nic_rx_jumbo(dev);
- else
- ipg_nic_rx(dev);
- }
-
- /* If TxDMAComplete interrupt, free used TFDs. */
- if (status & IPG_IS_TX_DMA_COMPLETE)
- ipg_nic_txfree(dev);
-
- /* TxComplete interrupts indicate one of numerous actions.
- * Determine what action to take based on TXSTATUS register.
- */
- if (status & IPG_IS_TX_COMPLETE)
- ipg_nic_txcleanup(dev);
-
- /* If UpdateStats interrupt, update Linux Ethernet statistics */
- if (status & IPG_IS_UPDATE_STATS)
- ipg_nic_get_stats(dev);
-
- /* If HostError interrupt, reset IPG. */
- if (status & IPG_IS_HOST_ERROR) {
- IPG_DDEBUG_MSG("HostError Interrupt\n");
-
- schedule_delayed_work(&sp->task, 0);
- }
-
- /* If LinkEvent interrupt, resolve autonegotiation. */
- if (status & IPG_IS_LINK_EVENT) {
- if (ipg_config_autoneg(dev) < 0)
- netdev_info(dev, "Auto-negotiation error\n");
- }
-
- /* If MACCtrlFrame interrupt, do nothing. */
- if (status & IPG_IS_MAC_CTRL_FRAME)
- IPG_DEBUG_MSG("MACCtrlFrame interrupt\n");
-
- /* If RxComplete interrupt, do nothing. */
- if (status & IPG_IS_RX_COMPLETE)
- IPG_DEBUG_MSG("RxComplete interrupt\n");
-
- /* If RxEarly interrupt, do nothing. */
- if (status & IPG_IS_RX_EARLY)
- IPG_DEBUG_MSG("RxEarly interrupt\n");
-
-out_enable:
- /* Re-enable IPG interrupts. */
- ipg_w16(IPG_IE_TX_DMA_COMPLETE | IPG_IE_RX_DMA_COMPLETE |
- IPG_IE_HOST_ERROR | IPG_IE_INT_REQUESTED | IPG_IE_TX_COMPLETE |
- IPG_IE_LINK_EVENT | IPG_IE_UPDATE_STATS, INT_ENABLE);
-out_unlock:
- spin_unlock(&sp->lock);
-
- return IRQ_RETVAL(handled);
-}
-
-static void ipg_rx_clear(struct ipg_nic_private *sp)
-{
- unsigned int i;
-
- for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
- if (sp->rx_buff[i]) {
- struct ipg_rx *rxfd = sp->rxd + i;
-
- dev_kfree_skb_irq(sp->rx_buff[i]);
- sp->rx_buff[i] = NULL;
- pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
- sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
- }
- }
-}
-
-static void ipg_tx_clear(struct ipg_nic_private *sp)
-{
- unsigned int i;
-
- for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
- if (sp->tx_buff[i]) {
- struct ipg_tx *txfd = sp->txd + i;
-
- pci_unmap_single(sp->pdev,
- le64_to_cpu(txfd->frag_info) & ~IPG_TFI_FRAGLEN,
- sp->tx_buff[i]->len, PCI_DMA_TODEVICE);
-
- dev_kfree_skb_irq(sp->tx_buff[i]);
-
- sp->tx_buff[i] = NULL;
- }
- }
-}
-
-static int ipg_nic_open(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- struct pci_dev *pdev = sp->pdev;
- int rc;
-
- IPG_DEBUG_MSG("_nic_open\n");
-
- sp->rx_buf_sz = sp->rxsupport_size;
-
- /* Check for interrupt line conflicts, and request interrupt
- * line for IPG.
- *
- * IMPORTANT: Disable IPG interrupts prior to registering
- * IRQ.
- */
- ipg_w16(0x0000, INT_ENABLE);
-
- /* Register the interrupt line to be used by the IPG within
- * the Linux system.
- */
- rc = request_irq(pdev->irq, ipg_interrupt_handler, IRQF_SHARED,
- dev->name, dev);
- if (rc < 0) {
- netdev_info(dev, "Error when requesting interrupt\n");
- goto out;
- }
-
- dev->irq = pdev->irq;
-
- rc = -ENOMEM;
-
- sp->rxd = dma_alloc_coherent(&pdev->dev, IPG_RX_RING_BYTES,
- &sp->rxd_map, GFP_KERNEL);
- if (!sp->rxd)
- goto err_free_irq_0;
-
- sp->txd = dma_alloc_coherent(&pdev->dev, IPG_TX_RING_BYTES,
- &sp->txd_map, GFP_KERNEL);
- if (!sp->txd)
- goto err_free_rx_1;
-
- rc = init_rfdlist(dev);
- if (rc < 0) {
- netdev_info(dev, "Error during configuration\n");
- goto err_free_tx_2;
- }
-
- init_tfdlist(dev);
-
- rc = ipg_io_config(dev);
- if (rc < 0) {
- netdev_info(dev, "Error during configuration\n");
- goto err_release_tfdlist_3;
- }
-
- /* Resolve autonegotiation. */
- if (ipg_config_autoneg(dev) < 0)
- netdev_info(dev, "Auto-negotiation error\n");
-
- /* initialize JUMBO Frame control variable */
- sp->jumbo.found_start = 0;
- sp->jumbo.current_size = 0;
- sp->jumbo.skb = NULL;
-
- /* Enable transmit and receive operation of the IPG. */
- ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_RX_ENABLE | IPG_MC_TX_ENABLE) &
- IPG_MC_RSVD_MASK, MAC_CTRL);
-
- netif_start_queue(dev);
-out:
- return rc;
-
-err_release_tfdlist_3:
- ipg_tx_clear(sp);
- ipg_rx_clear(sp);
-err_free_tx_2:
- dma_free_coherent(&pdev->dev, IPG_TX_RING_BYTES, sp->txd, sp->txd_map);
-err_free_rx_1:
- dma_free_coherent(&pdev->dev, IPG_RX_RING_BYTES, sp->rxd, sp->rxd_map);
-err_free_irq_0:
- free_irq(pdev->irq, dev);
- goto out;
-}
-
-static int ipg_nic_stop(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- struct pci_dev *pdev = sp->pdev;
-
- IPG_DEBUG_MSG("_nic_stop\n");
-
- netif_stop_queue(dev);
-
- IPG_DUMPTFDLIST(dev);
-
- do {
- (void) ipg_r16(INT_STATUS_ACK);
-
- ipg_reset(dev, IPG_AC_GLOBAL_RESET | IPG_AC_HOST | IPG_AC_DMA);
-
- synchronize_irq(pdev->irq);
- } while (ipg_r16(INT_ENABLE) & IPG_IE_RSVD_MASK);
-
- ipg_rx_clear(sp);
-
- ipg_tx_clear(sp);
-
- pci_free_consistent(pdev, IPG_RX_RING_BYTES, sp->rxd, sp->rxd_map);
- pci_free_consistent(pdev, IPG_TX_RING_BYTES, sp->txd, sp->txd_map);
-
- free_irq(pdev->irq, dev);
-
- return 0;
-}
-
-static netdev_tx_t ipg_nic_hard_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int entry = sp->tx_current % IPG_TFDLIST_LENGTH;
- unsigned long flags;
- struct ipg_tx *txfd;
-
- IPG_DDEBUG_MSG("_nic_hard_start_xmit\n");
-
- /* If in 10Mbps mode, stop the transmit queue so
- * no more transmit frames are accepted.
- */
- if (sp->tenmbpsmode)
- netif_stop_queue(dev);
-
- if (sp->reset_current_tfd) {
- sp->reset_current_tfd = 0;
- entry = 0;
- }
-
- txfd = sp->txd + entry;
-
- sp->tx_buff[entry] = skb;
-
- /* Clear all TFC fields, except TFDDONE. */
- txfd->tfc = cpu_to_le64(IPG_TFC_TFDDONE);
-
- /* Specify the TFC field within the TFD. */
- txfd->tfc |= cpu_to_le64(IPG_TFC_WORDALIGNDISABLED |
- (IPG_TFC_FRAMEID & sp->tx_current) |
- (IPG_TFC_FRAGCOUNT & (1 << 24)));
- /*
- * 16--17 (WordAlign) <- 3 (disable),
- * 0--15 (FrameId) <- sp->tx_current,
- * 24--27 (FragCount) <- 1
- */
-
- /* Request TxComplete interrupts at an interval defined
- * by the constant IPG_FRAMESBETWEENTXCOMPLETES.
- * Request TxComplete interrupt for every frame
- * if in 10Mbps mode to accommodate problem with 10Mbps
- * processing.
- */
- if (sp->tenmbpsmode)
- txfd->tfc |= cpu_to_le64(IPG_TFC_TXINDICATE);
- txfd->tfc |= cpu_to_le64(IPG_TFC_TXDMAINDICATE);
- /* Based on compilation option, determine if FCS is to be
- * appended to transmit frame by IPG.
- */
- if (!(IPG_APPEND_FCS_ON_TX))
- txfd->tfc |= cpu_to_le64(IPG_TFC_FCSAPPENDDISABLE);
-
- /* Based on compilation option, determine if IP, TCP and/or
- * UDP checksums are to be added to transmit frame by IPG.
- */
- if (IPG_ADD_IPCHECKSUM_ON_TX)
- txfd->tfc |= cpu_to_le64(IPG_TFC_IPCHECKSUMENABLE);
-
- if (IPG_ADD_TCPCHECKSUM_ON_TX)
- txfd->tfc |= cpu_to_le64(IPG_TFC_TCPCHECKSUMENABLE);
-
- if (IPG_ADD_UDPCHECKSUM_ON_TX)
- txfd->tfc |= cpu_to_le64(IPG_TFC_UDPCHECKSUMENABLE);
-
- /* Based on compilation option, determine if VLAN tag info is to be
- * inserted into transmit frame by IPG.
- */
- if (IPG_INSERT_MANUAL_VLAN_TAG) {
- txfd->tfc |= cpu_to_le64(IPG_TFC_VLANTAGINSERT |
- ((u64) IPG_MANUAL_VLAN_VID << 32) |
- ((u64) IPG_MANUAL_VLAN_CFI << 44) |
- ((u64) IPG_MANUAL_VLAN_USERPRIORITY << 45));
- }
-
- /* The fragment start location within system memory is defined
- * by the sk_buff structure's data field. The physical address
- * of this location within the system's virtual memory space
- * is determined using the IPG_HOST2BUS_MAP function.
- */
- txfd->frag_info = cpu_to_le64(pci_map_single(sp->pdev, skb->data,
- skb->len, PCI_DMA_TODEVICE));
-
- /* The length of the fragment within system memory is defined by
- * the sk_buff structure's len field.
- */
- txfd->frag_info |= cpu_to_le64(IPG_TFI_FRAGLEN &
- ((u64) (skb->len & 0xffff) << 48));
-
- /* Clear the TFDDone bit last to indicate the TFD is ready
- * for transfer to the IPG.
- */
- txfd->tfc &= cpu_to_le64(~IPG_TFC_TFDDONE);
-
- spin_lock_irqsave(&sp->lock, flags);
-
- sp->tx_current++;
-
- mmiowb();
-
- ipg_w32(IPG_DC_TX_DMA_POLL_NOW, DMA_CTRL);
-
- if (sp->tx_current == (sp->tx_dirty + IPG_TFDLIST_LENGTH))
- netif_stop_queue(dev);
-
- spin_unlock_irqrestore(&sp->lock, flags);
-
- return NETDEV_TX_OK;
-}
-
-static void ipg_set_phy_default_param(unsigned char rev,
- struct net_device *dev, int phy_address)
-{
- unsigned short length;
- unsigned char revision;
- const unsigned short *phy_param;
- unsigned short address, value;
-
- phy_param = &DefaultPhyParam[0];
- length = *phy_param & 0x00FF;
- revision = (unsigned char)((*phy_param) >> 8);
- phy_param++;
- while (length != 0) {
- if (rev == revision) {
- while (length > 1) {
- address = *phy_param;
- value = *(phy_param + 1);
- phy_param += 2;
- mdio_write(dev, phy_address, address, value);
- length -= 4;
- }
- break;
- } else {
- phy_param += length / 2;
- length = *phy_param & 0x00FF;
- revision = (unsigned char)((*phy_param) >> 8);
- phy_param++;
- }
- }
-}
-
-static int read_eeprom(struct net_device *dev, int eep_addr)
-{
- void __iomem *ioaddr = ipg_ioaddr(dev);
- unsigned int i;
- int ret = 0;
- u16 value;
-
- value = IPG_EC_EEPROM_READOPCODE | (eep_addr & 0xff);
- ipg_w16(value, EEPROM_CTRL);
-
- for (i = 0; i < 1000; i++) {
- u16 data;
-
- mdelay(10);
- data = ipg_r16(EEPROM_CTRL);
- if (!(data & IPG_EC_EEPROM_BUSY)) {
- ret = ipg_r16(EEPROM_DATA);
- break;
- }
- }
- return ret;
-}
-
-static void ipg_init_mii(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- struct mii_if_info *mii_if = &sp->mii_if;
- int phyaddr;
-
- mii_if->dev = dev;
- mii_if->mdio_read = mdio_read;
- mii_if->mdio_write = mdio_write;
- mii_if->phy_id_mask = 0x1f;
- mii_if->reg_num_mask = 0x1f;
-
- mii_if->phy_id = phyaddr = ipg_find_phyaddr(dev);
-
- if (phyaddr != 0x1f) {
- u16 mii_phyctrl, mii_1000cr;
-
- mii_1000cr = mdio_read(dev, phyaddr, MII_CTRL1000);
- mii_1000cr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF |
- GMII_PHY_1000BASETCONTROL_PreferMaster;
- mdio_write(dev, phyaddr, MII_CTRL1000, mii_1000cr);
-
- mii_phyctrl = mdio_read(dev, phyaddr, MII_BMCR);
-
- /* Set default phyparam */
- ipg_set_phy_default_param(sp->pdev->revision, dev, phyaddr);
-
- /* Reset PHY */
- mii_phyctrl |= BMCR_RESET | BMCR_ANRESTART;
- mdio_write(dev, phyaddr, MII_BMCR, mii_phyctrl);
-
- }
-}
-
-static int ipg_hw_init(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->ioaddr;
- unsigned int i;
- int rc;
-
- /* Read/Write and Reset EEPROM Value */
- /* Read LED Mode Configuration from EEPROM */
- sp->led_mode = read_eeprom(dev, 6);
-
- /* Reset all functions within the IPG. Do not assert
- * RST_OUT as not compatible with some PHYs.
- */
- rc = ipg_reset(dev, IPG_RESET_MASK);
- if (rc < 0)
- goto out;
-
- ipg_init_mii(dev);
-
- /* Read MAC Address from EEPROM */
- for (i = 0; i < 3; i++)
- sp->station_addr[i] = read_eeprom(dev, 16 + i);
-
- for (i = 0; i < 3; i++)
- ipg_w16(sp->station_addr[i], STATION_ADDRESS_0 + 2*i);
-
- /* Set station address in ethernet_device structure. */
- dev->dev_addr[0] = ipg_r16(STATION_ADDRESS_0) & 0x00ff;
- dev->dev_addr[1] = (ipg_r16(STATION_ADDRESS_0) & 0xff00) >> 8;
- dev->dev_addr[2] = ipg_r16(STATION_ADDRESS_1) & 0x00ff;
- dev->dev_addr[3] = (ipg_r16(STATION_ADDRESS_1) & 0xff00) >> 8;
- dev->dev_addr[4] = ipg_r16(STATION_ADDRESS_2) & 0x00ff;
- dev->dev_addr[5] = (ipg_r16(STATION_ADDRESS_2) & 0xff00) >> 8;
-out:
- return rc;
-}
-
-static int ipg_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- int rc;
-
- mutex_lock(&sp->mii_mutex);
- rc = generic_mii_ioctl(&sp->mii_if, if_mii(ifr), cmd, NULL);
- mutex_unlock(&sp->mii_mutex);
-
- return rc;
-}
-
-static int ipg_nic_change_mtu(struct net_device *dev, int new_mtu)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- int err;
-
- /* Function to accommodate changes to Maximum Transfer Unit
- * (or MTU) of IPG NIC. Cannot use default function since
- * the default will not allow for MTU > 1500 bytes.
- */
-
- IPG_DEBUG_MSG("_nic_change_mtu\n");
-
- /*
- * Check that the new MTU value is between 68 (14 byte header, 46 byte
- * payload, 4 byte FCS) and 10 KB, which is the largest supported MTU.
- */
- if (new_mtu < 68 || new_mtu > 10240)
- return -EINVAL;
-
- err = ipg_nic_stop(dev);
- if (err)
- return err;
-
- dev->mtu = new_mtu;
-
- sp->max_rxframe_size = new_mtu;
-
- sp->rxfrag_size = new_mtu;
- if (sp->rxfrag_size > 4088)
- sp->rxfrag_size = 4088;
-
- sp->rxsupport_size = sp->max_rxframe_size;
-
- if (new_mtu > 0x0600)
- sp->is_jumbo = true;
- else
- sp->is_jumbo = false;
-
- return ipg_nic_open(dev);
-}
-
-static int ipg_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- int rc;
-
- mutex_lock(&sp->mii_mutex);
- rc = mii_ethtool_gset(&sp->mii_if, cmd);
- mutex_unlock(&sp->mii_mutex);
-
- return rc;
-}
-
-static int ipg_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- int rc;
-
- mutex_lock(&sp->mii_mutex);
- rc = mii_ethtool_sset(&sp->mii_if, cmd);
- mutex_unlock(&sp->mii_mutex);
-
- return rc;
-}
-
-static int ipg_nway_reset(struct net_device *dev)
-{
- struct ipg_nic_private *sp = netdev_priv(dev);
- int rc;
-
- mutex_lock(&sp->mii_mutex);
- rc = mii_nway_restart(&sp->mii_if);
- mutex_unlock(&sp->mii_mutex);
-
- return rc;
-}
-
-static const struct ethtool_ops ipg_ethtool_ops = {
- .get_settings = ipg_get_settings,
- .set_settings = ipg_set_settings,
- .nway_reset = ipg_nway_reset,
-};
-
-static void ipg_remove(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct ipg_nic_private *sp = netdev_priv(dev);
-
- IPG_DEBUG_MSG("_remove\n");
-
- /* Un-register Ethernet device. */
- unregister_netdev(dev);
-
- pci_iounmap(pdev, sp->ioaddr);
-
- pci_release_regions(pdev);
-
- free_netdev(dev);
- pci_disable_device(pdev);
-}
-
-static const struct net_device_ops ipg_netdev_ops = {
- .ndo_open = ipg_nic_open,
- .ndo_stop = ipg_nic_stop,
- .ndo_start_xmit = ipg_nic_hard_start_xmit,
- .ndo_get_stats = ipg_nic_get_stats,
- .ndo_set_rx_mode = ipg_nic_set_multicast_list,
- .ndo_do_ioctl = ipg_ioctl,
- .ndo_tx_timeout = ipg_tx_timeout,
- .ndo_change_mtu = ipg_nic_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- unsigned int i = id->driver_data;
- struct ipg_nic_private *sp;
- struct net_device *dev;
- void __iomem *ioaddr;
- int rc;
-
- rc = pci_enable_device(pdev);
- if (rc < 0)
- goto out;
-
- pr_info("%s: %s\n", pci_name(pdev), ipg_brand_name[i]);
-
- pci_set_master(pdev);
-
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
- if (rc < 0) {
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc < 0) {
- pr_err("%s: DMA config failed\n", pci_name(pdev));
- goto err_disable_0;
- }
- }
-
- /*
- * Initialize net device.
- */
- dev = alloc_etherdev(sizeof(struct ipg_nic_private));
- if (!dev) {
- rc = -ENOMEM;
- goto err_disable_0;
- }
-
- sp = netdev_priv(dev);
- spin_lock_init(&sp->lock);
- mutex_init(&sp->mii_mutex);
-
- sp->is_jumbo = IPG_IS_JUMBO;
- sp->rxfrag_size = IPG_RXFRAG_SIZE;
- sp->rxsupport_size = IPG_RXSUPPORT_SIZE;
- sp->max_rxframe_size = IPG_MAX_RXFRAME_SIZE;
-
- /* Declare IPG NIC functions for Ethernet device methods.
- */
- dev->netdev_ops = &ipg_netdev_ops;
- SET_NETDEV_DEV(dev, &pdev->dev);
- dev->ethtool_ops = &ipg_ethtool_ops;
-
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
- goto err_free_dev_1;
-
- ioaddr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
- if (!ioaddr) {
- pr_err("%s: cannot map MMIO\n", pci_name(pdev));
- rc = -EIO;
- goto err_release_regions_2;
- }
-
- /* Save the pointer to the PCI device information. */
- sp->ioaddr = ioaddr;
- sp->pdev = pdev;
- sp->dev = dev;
-
- INIT_DELAYED_WORK(&sp->task, ipg_reset_after_host_error);
-
- pci_set_drvdata(pdev, dev);
-
- rc = ipg_hw_init(dev);
- if (rc < 0)
- goto err_unmap_3;
-
- rc = register_netdev(dev);
- if (rc < 0)
- goto err_unmap_3;
-
- netdev_info(dev, "Ethernet device registered\n");
-out:
- return rc;
-
-err_unmap_3:
- pci_iounmap(pdev, ioaddr);
-err_release_regions_2:
- pci_release_regions(pdev);
-err_free_dev_1:
- free_netdev(dev);
-err_disable_0:
- pci_disable_device(pdev);
- goto out;
-}
-
-static struct pci_driver ipg_pci_driver = {
- .name = IPG_DRIVER_NAME,
- .id_table = ipg_pci_tbl,
- .probe = ipg_probe,
- .remove = ipg_remove,
-};
-
-module_pci_driver(ipg_pci_driver);
diff --git a/drivers/net/ethernet/icplus/ipg.h b/drivers/net/ethernet/icplus/ipg.h
deleted file mode 100644
index de606281f97b..000000000000
--- a/drivers/net/ethernet/icplus/ipg.h
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- * Include file for Gigabit Ethernet device driver for Network
- * Interface Cards (NICs) utilizing the Tamarack Microelectronics
- * Inc. IPG Gigabit or Triple Speed Ethernet Media Access
- * Controller.
- */
-#ifndef __LINUX_IPG_H
-#define __LINUX_IPG_H
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <asm/bitops.h>
-
-/*
- * Constants
- */
-
-/* GMII based PHY IDs */
-#define NS 0x2000
-#define MARVELL 0x0141
-#define ICPLUS_PHY 0x243
-
-/* NIC Physical Layer Device MII register fields. */
-#define MII_PHY_SELECTOR_IEEE8023 0x0001
-#define MII_PHY_TECHABILITYFIELD 0x1FE0
-
-/* GMII_PHY_1000 need to set to prefer master */
-#define GMII_PHY_1000BASETCONTROL_PreferMaster 0x0400
-
-/* NIC Physical Layer Device GMII constants. */
-#define GMII_PREAMBLE 0xFFFFFFFF
-#define GMII_ST 0x1
-#define GMII_READ 0x2
-#define GMII_WRITE 0x1
-#define GMII_TA_READ_MASK 0x1
-#define GMII_TA_WRITE 0x2
-
-/* I/O register offsets. */
-enum ipg_regs {
- DMA_CTRL = 0x00,
- RX_DMA_STATUS = 0x08, /* Unused + reserved */
- TFD_LIST_PTR_0 = 0x10,
- TFD_LIST_PTR_1 = 0x14,
- TX_DMA_BURST_THRESH = 0x18,
- TX_DMA_URGENT_THRESH = 0x19,
- TX_DMA_POLL_PERIOD = 0x1a,
- RFD_LIST_PTR_0 = 0x1c,
- RFD_LIST_PTR_1 = 0x20,
- RX_DMA_BURST_THRESH = 0x24,
- RX_DMA_URGENT_THRESH = 0x25,
- RX_DMA_POLL_PERIOD = 0x26,
- DEBUG_CTRL = 0x2c,
- ASIC_CTRL = 0x30,
- FIFO_CTRL = 0x38, /* Unused */
- FLOW_OFF_THRESH = 0x3c,
- FLOW_ON_THRESH = 0x3e,
- EEPROM_DATA = 0x48,
- EEPROM_CTRL = 0x4a,
- EXPROM_ADDR = 0x4c, /* Unused */
- EXPROM_DATA = 0x50, /* Unused */
- WAKE_EVENT = 0x51, /* Unused */
- COUNTDOWN = 0x54, /* Unused */
- INT_STATUS_ACK = 0x5a,
- INT_ENABLE = 0x5c,
- INT_STATUS = 0x5e, /* Unused */
- TX_STATUS = 0x60,
- MAC_CTRL = 0x6c,
- VLAN_TAG = 0x70, /* Unused */
- PHY_SET = 0x75,
- PHY_CTRL = 0x76,
- STATION_ADDRESS_0 = 0x78,
- STATION_ADDRESS_1 = 0x7a,
- STATION_ADDRESS_2 = 0x7c,
- MAX_FRAME_SIZE = 0x86,
- RECEIVE_MODE = 0x88,
- HASHTABLE_0 = 0x8c,
- HASHTABLE_1 = 0x90,
- RMON_STATISTICS_MASK = 0x98,
- STATISTICS_MASK = 0x9c,
- RX_JUMBO_FRAMES = 0xbc, /* Unused */
- TCP_CHECKSUM_ERRORS = 0xc0, /* Unused */
- IP_CHECKSUM_ERRORS = 0xc2, /* Unused */
- UDP_CHECKSUM_ERRORS = 0xc4, /* Unused */
- TX_JUMBO_FRAMES = 0xf4 /* Unused */
-};
-
-/* Ethernet MIB statistic register offsets. */
-#define IPG_OCTETRCVOK 0xA8
-#define IPG_MCSTOCTETRCVDOK 0xAC
-#define IPG_BCSTOCTETRCVOK 0xB0
-#define IPG_FRAMESRCVDOK 0xB4
-#define IPG_MCSTFRAMESRCVDOK 0xB8
-#define IPG_BCSTFRAMESRCVDOK 0xBE
-#define IPG_MACCONTROLFRAMESRCVD 0xC6
-#define IPG_FRAMETOOLONGERRORS 0xC8
-#define IPG_INRANGELENGTHERRORS 0xCA
-#define IPG_FRAMECHECKSEQERRORS 0xCC
-#define IPG_FRAMESLOSTRXERRORS 0xCE
-#define IPG_OCTETXMTOK 0xD0
-#define IPG_MCSTOCTETXMTOK 0xD4
-#define IPG_BCSTOCTETXMTOK 0xD8
-#define IPG_FRAMESXMTDOK 0xDC
-#define IPG_MCSTFRAMESXMTDOK 0xE0
-#define IPG_FRAMESWDEFERREDXMT 0xE4
-#define IPG_LATECOLLISIONS 0xE8
-#define IPG_MULTICOLFRAMES 0xEC
-#define IPG_SINGLECOLFRAMES 0xF0
-#define IPG_BCSTFRAMESXMTDOK 0xF6
-#define IPG_CARRIERSENSEERRORS 0xF8
-#define IPG_MACCONTROLFRAMESXMTDOK 0xFA
-#define IPG_FRAMESABORTXSCOLLS 0xFC
-#define IPG_FRAMESWEXDEFERRAL 0xFE
-
-/* RMON statistic register offsets. */
-#define IPG_ETHERSTATSCOLLISIONS 0x100
-#define IPG_ETHERSTATSOCTETSTRANSMIT 0x104
-#define IPG_ETHERSTATSPKTSTRANSMIT 0x108
-#define IPG_ETHERSTATSPKTS64OCTESTSTRANSMIT 0x10C
-#define IPG_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT 0x110
-#define IPG_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT 0x114
-#define IPG_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT 0x118
-#define IPG_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT 0x11C
-#define IPG_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT 0x120
-#define IPG_ETHERSTATSCRCALIGNERRORS 0x124
-#define IPG_ETHERSTATSUNDERSIZEPKTS 0x128
-#define IPG_ETHERSTATSFRAGMENTS 0x12C
-#define IPG_ETHERSTATSJABBERS 0x130
-#define IPG_ETHERSTATSOCTETS 0x134
-#define IPG_ETHERSTATSPKTS 0x138
-#define IPG_ETHERSTATSPKTS64OCTESTS 0x13C
-#define IPG_ETHERSTATSPKTS65TO127OCTESTS 0x140
-#define IPG_ETHERSTATSPKTS128TO255OCTESTS 0x144
-#define IPG_ETHERSTATSPKTS256TO511OCTESTS 0x148
-#define IPG_ETHERSTATSPKTS512TO1023OCTESTS 0x14C
-#define IPG_ETHERSTATSPKTS1024TO1518OCTESTS 0x150
-
-/* RMON statistic register equivalents. */
-#define IPG_ETHERSTATSMULTICASTPKTSTRANSMIT 0xE0
-#define IPG_ETHERSTATSBROADCASTPKTSTRANSMIT 0xF6
-#define IPG_ETHERSTATSMULTICASTPKTS 0xB8
-#define IPG_ETHERSTATSBROADCASTPKTS 0xBE
-#define IPG_ETHERSTATSOVERSIZEPKTS 0xC8
-#define IPG_ETHERSTATSDROPEVENTS 0xCE
-
-/* Serial EEPROM offsets */
-#define IPG_EEPROM_CONFIGPARAM 0x00
-#define IPG_EEPROM_ASICCTRL 0x01
-#define IPG_EEPROM_SUBSYSTEMVENDORID 0x02
-#define IPG_EEPROM_SUBSYSTEMID 0x03
-#define IPG_EEPROM_STATIONADDRESS0 0x10
-#define IPG_EEPROM_STATIONADDRESS1 0x11
-#define IPG_EEPROM_STATIONADDRESS2 0x12
-
-/* Register & data structure bit masks */
-
-/* PCI register masks. */
-
-/* IOBaseAddress */
-#define IPG_PIB_RSVD_MASK 0xFFFFFE01
-#define IPG_PIB_IOBASEADDRESS 0xFFFFFF00
-#define IPG_PIB_IOBASEADDRIND 0x00000001
-
-/* MemBaseAddress */
-#define IPG_PMB_RSVD_MASK 0xFFFFFE07
-#define IPG_PMB_MEMBASEADDRIND 0x00000001
-#define IPG_PMB_MEMMAPTYPE 0x00000006
-#define IPG_PMB_MEMMAPTYPE0 0x00000002
-#define IPG_PMB_MEMMAPTYPE1 0x00000004
-#define IPG_PMB_MEMBASEADDRESS 0xFFFFFE00
-
-/* ConfigStatus */
-#define IPG_CS_RSVD_MASK 0xFFB0
-#define IPG_CS_CAPABILITIES 0x0010
-#define IPG_CS_66MHZCAPABLE 0x0020
-#define IPG_CS_FASTBACK2BACK 0x0080
-#define IPG_CS_DATAPARITYREPORTED 0x0100
-#define IPG_CS_DEVSELTIMING 0x0600
-#define IPG_CS_SIGNALEDTARGETABORT 0x0800
-#define IPG_CS_RECEIVEDTARGETABORT 0x1000
-#define IPG_CS_RECEIVEDMASTERABORT 0x2000
-#define IPG_CS_SIGNALEDSYSTEMERROR 0x4000
-#define IPG_CS_DETECTEDPARITYERROR 0x8000
-
-/* TFD data structure masks. */
-
-/* TFDList, TFC */
-#define IPG_TFC_RSVD_MASK 0x0000FFFF9FFFFFFFULL
-#define IPG_TFC_FRAMEID 0x000000000000FFFFULL
-#define IPG_TFC_WORDALIGN 0x0000000000030000ULL
-#define IPG_TFC_WORDALIGNTODWORD 0x0000000000000000ULL
-#define IPG_TFC_WORDALIGNTOWORD 0x0000000000020000ULL
-#define IPG_TFC_WORDALIGNDISABLED 0x0000000000030000ULL
-#define IPG_TFC_TCPCHECKSUMENABLE 0x0000000000040000ULL
-#define IPG_TFC_UDPCHECKSUMENABLE 0x0000000000080000ULL
-#define IPG_TFC_IPCHECKSUMENABLE 0x0000000000100000ULL
-#define IPG_TFC_FCSAPPENDDISABLE 0x0000000000200000ULL
-#define IPG_TFC_TXINDICATE 0x0000000000400000ULL
-#define IPG_TFC_TXDMAINDICATE 0x0000000000800000ULL
-#define IPG_TFC_FRAGCOUNT 0x000000000F000000ULL
-#define IPG_TFC_VLANTAGINSERT 0x0000000010000000ULL
-#define IPG_TFC_TFDDONE 0x0000000080000000ULL
-#define IPG_TFC_VID 0x00000FFF00000000ULL
-#define IPG_TFC_CFI 0x0000100000000000ULL
-#define IPG_TFC_USERPRIORITY 0x0000E00000000000ULL
-
-/* TFDList, FragInfo */
-#define IPG_TFI_RSVD_MASK 0xFFFF00FFFFFFFFFFULL
-#define IPG_TFI_FRAGADDR 0x000000FFFFFFFFFFULL
-#define IPG_TFI_FRAGLEN 0xFFFF000000000000ULL
-
-/* RFD data structure masks. */
-
-/* RFDList, RFS */
-#define IPG_RFS_RSVD_MASK 0x0000FFFFFFFFFFFFULL
-#define IPG_RFS_RXFRAMELEN 0x000000000000FFFFULL
-#define IPG_RFS_RXFIFOOVERRUN 0x0000000000010000ULL
-#define IPG_RFS_RXRUNTFRAME 0x0000000000020000ULL
-#define IPG_RFS_RXALIGNMENTERROR 0x0000000000040000ULL
-#define IPG_RFS_RXFCSERROR 0x0000000000080000ULL
-#define IPG_RFS_RXOVERSIZEDFRAME 0x0000000000100000ULL
-#define IPG_RFS_RXLENGTHERROR 0x0000000000200000ULL
-#define IPG_RFS_VLANDETECTED 0x0000000000400000ULL
-#define IPG_RFS_TCPDETECTED 0x0000000000800000ULL
-#define IPG_RFS_TCPERROR 0x0000000001000000ULL
-#define IPG_RFS_UDPDETECTED 0x0000000002000000ULL
-#define IPG_RFS_UDPERROR 0x0000000004000000ULL
-#define IPG_RFS_IPDETECTED 0x0000000008000000ULL
-#define IPG_RFS_IPERROR 0x0000000010000000ULL
-#define IPG_RFS_FRAMESTART 0x0000000020000000ULL
-#define IPG_RFS_FRAMEEND 0x0000000040000000ULL
-#define IPG_RFS_RFDDONE 0x0000000080000000ULL
-#define IPG_RFS_TCI 0x0000FFFF00000000ULL
-
-/* RFDList, FragInfo */
-#define IPG_RFI_RSVD_MASK 0xFFFF00FFFFFFFFFFULL
-#define IPG_RFI_FRAGADDR 0x000000FFFFFFFFFFULL
-#define IPG_RFI_FRAGLEN 0xFFFF000000000000ULL
-
-/* I/O Register masks. */
-
-/* RMON Statistics Mask */
-#define IPG_RZ_ALL 0x0FFFFFFF
-
-/* Statistics Mask */
-#define IPG_SM_ALL 0x0FFFFFFF
-#define IPG_SM_OCTETRCVOK_FRAMESRCVDOK 0x00000001
-#define IPG_SM_MCSTOCTETRCVDOK_MCSTFRAMESRCVDOK 0x00000002
-#define IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK 0x00000004
-#define IPG_SM_RXJUMBOFRAMES 0x00000008
-#define IPG_SM_TCPCHECKSUMERRORS 0x00000010
-#define IPG_SM_IPCHECKSUMERRORS 0x00000020
-#define IPG_SM_UDPCHECKSUMERRORS 0x00000040
-#define IPG_SM_MACCONTROLFRAMESRCVD 0x00000080
-#define IPG_SM_FRAMESTOOLONGERRORS 0x00000100
-#define IPG_SM_INRANGELENGTHERRORS 0x00000200
-#define IPG_SM_FRAMECHECKSEQERRORS 0x00000400
-#define IPG_SM_FRAMESLOSTRXERRORS 0x00000800
-#define IPG_SM_OCTETXMTOK_FRAMESXMTOK 0x00001000
-#define IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK 0x00002000
-#define IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK 0x00004000
-#define IPG_SM_FRAMESWDEFERREDXMT 0x00008000
-#define IPG_SM_LATECOLLISIONS 0x00010000
-#define IPG_SM_MULTICOLFRAMES 0x00020000
-#define IPG_SM_SINGLECOLFRAMES 0x00040000
-#define IPG_SM_TXJUMBOFRAMES 0x00080000
-#define IPG_SM_CARRIERSENSEERRORS 0x00100000
-#define IPG_SM_MACCONTROLFRAMESXMTD 0x00200000
-#define IPG_SM_FRAMESABORTXSCOLLS 0x00400000
-#define IPG_SM_FRAMESWEXDEFERAL 0x00800000
-
-/* Countdown */
-#define IPG_CD_RSVD_MASK 0x0700FFFF
-#define IPG_CD_COUNT 0x0000FFFF
-#define IPG_CD_COUNTDOWNSPEED 0x01000000
-#define IPG_CD_COUNTDOWNMODE 0x02000000
-#define IPG_CD_COUNTINTENABLED 0x04000000
-
-/* TxDMABurstThresh */
-#define IPG_TB_RSVD_MASK 0xFF
-
-/* TxDMAUrgentThresh */
-#define IPG_TU_RSVD_MASK 0xFF
-
-/* TxDMAPollPeriod */
-#define IPG_TP_RSVD_MASK 0xFF
-
-/* RxDMAUrgentThresh */
-#define IPG_RU_RSVD_MASK 0xFF
-
-/* RxDMAPollPeriod */
-#define IPG_RP_RSVD_MASK 0xFF
-
-/* ReceiveMode */
-#define IPG_RM_RSVD_MASK 0x3F
-#define IPG_RM_RECEIVEUNICAST 0x01
-#define IPG_RM_RECEIVEMULTICAST 0x02
-#define IPG_RM_RECEIVEBROADCAST 0x04
-#define IPG_RM_RECEIVEALLFRAMES 0x08
-#define IPG_RM_RECEIVEMULTICASTHASH 0x10
-#define IPG_RM_RECEIVEIPMULTICAST 0x20
-
-/* PhySet */
-#define IPG_PS_MEM_LENB9B 0x01
-#define IPG_PS_MEM_LEN9 0x02
-#define IPG_PS_NON_COMPDET 0x04
-
-/* PhyCtrl */
-#define IPG_PC_RSVD_MASK 0xFF
-#define IPG_PC_MGMTCLK_LO 0x00
-#define IPG_PC_MGMTCLK_HI 0x01
-#define IPG_PC_MGMTCLK 0x01
-#define IPG_PC_MGMTDATA 0x02
-#define IPG_PC_MGMTDIR 0x04
-#define IPG_PC_DUPLEX_POLARITY 0x08
-#define IPG_PC_DUPLEX_STATUS 0x10
-#define IPG_PC_LINK_POLARITY 0x20
-#define IPG_PC_LINK_SPEED 0xC0
-#define IPG_PC_LINK_SPEED_10MBPS 0x40
-#define IPG_PC_LINK_SPEED_100MBPS 0x80
-#define IPG_PC_LINK_SPEED_1000MBPS 0xC0
-
-/* DMACtrl */
-#define IPG_DC_RSVD_MASK 0xC07D9818
-#define IPG_DC_RX_DMA_COMPLETE 0x00000008
-#define IPG_DC_RX_DMA_POLL_NOW 0x00000010
-#define IPG_DC_TX_DMA_COMPLETE 0x00000800
-#define IPG_DC_TX_DMA_POLL_NOW 0x00001000
-#define IPG_DC_TX_DMA_IN_PROG 0x00008000
-#define IPG_DC_RX_EARLY_DISABLE 0x00010000
-#define IPG_DC_MWI_DISABLE 0x00040000
-#define IPG_DC_TX_WRITE_BACK_DISABLE 0x00080000
-#define IPG_DC_TX_BURST_LIMIT 0x00700000
-#define IPG_DC_TARGET_ABORT 0x40000000
-#define IPG_DC_MASTER_ABORT 0x80000000
-
-/* ASICCtrl */
-#define IPG_AC_RSVD_MASK 0x07FFEFF2
-#define IPG_AC_EXP_ROM_SIZE 0x00000002
-#define IPG_AC_PHY_SPEED10 0x00000010
-#define IPG_AC_PHY_SPEED100 0x00000020
-#define IPG_AC_PHY_SPEED1000 0x00000040
-#define IPG_AC_PHY_MEDIA 0x00000080
-#define IPG_AC_FORCED_CFG 0x00000700
-#define IPG_AC_D3RESETDISABLE 0x00000800
-#define IPG_AC_SPEED_UP_MODE 0x00002000
-#define IPG_AC_LED_MODE 0x00004000
-#define IPG_AC_RST_OUT_POLARITY 0x00008000
-#define IPG_AC_GLOBAL_RESET 0x00010000
-#define IPG_AC_RX_RESET 0x00020000
-#define IPG_AC_TX_RESET 0x00040000
-#define IPG_AC_DMA 0x00080000
-#define IPG_AC_FIFO 0x00100000
-#define IPG_AC_NETWORK 0x00200000
-#define IPG_AC_HOST 0x00400000
-#define IPG_AC_AUTO_INIT 0x00800000
-#define IPG_AC_RST_OUT 0x01000000
-#define IPG_AC_INT_REQUEST 0x02000000
-#define IPG_AC_RESET_BUSY 0x04000000
-#define IPG_AC_LED_SPEED 0x08000000
-#define IPG_AC_LED_MODE_BIT_1 0x20000000
-
-/* EepromCtrl */
-#define IPG_EC_RSVD_MASK 0x83FF
-#define IPG_EC_EEPROM_ADDR 0x00FF
-#define IPG_EC_EEPROM_OPCODE 0x0300
-#define IPG_EC_EEPROM_SUBCOMMAD 0x0000
-#define IPG_EC_EEPROM_WRITEOPCODE 0x0100
-#define IPG_EC_EEPROM_READOPCODE 0x0200
-#define IPG_EC_EEPROM_ERASEOPCODE 0x0300
-#define IPG_EC_EEPROM_BUSY 0x8000
-
-/* FIFOCtrl */
-#define IPG_FC_RSVD_MASK 0xC001
-#define IPG_FC_RAM_TEST_MODE 0x0001
-#define IPG_FC_TRANSMITTING 0x4000
-#define IPG_FC_RECEIVING 0x8000
-
-/* TxStatus */
-#define IPG_TS_RSVD_MASK 0xFFFF00DD
-#define IPG_TS_TX_ERROR 0x00000001
-#define IPG_TS_LATE_COLLISION 0x00000004
-#define IPG_TS_TX_MAX_COLL 0x00000008
-#define IPG_TS_TX_UNDERRUN 0x00000010
-#define IPG_TS_TX_IND_REQD 0x00000040
-#define IPG_TS_TX_COMPLETE 0x00000080
-#define IPG_TS_TX_FRAMEID 0xFFFF0000
-
-/* WakeEvent */
-#define IPG_WE_WAKE_PKT_ENABLE 0x01
-#define IPG_WE_MAGIC_PKT_ENABLE 0x02
-#define IPG_WE_LINK_EVT_ENABLE 0x04
-#define IPG_WE_WAKE_POLARITY 0x08
-#define IPG_WE_WAKE_PKT_EVT 0x10
-#define IPG_WE_MAGIC_PKT_EVT 0x20
-#define IPG_WE_LINK_EVT 0x40
-#define IPG_WE_WOL_ENABLE 0x80
-
-/* IntEnable */
-#define IPG_IE_RSVD_MASK 0x1FFE
-#define IPG_IE_HOST_ERROR 0x0002
-#define IPG_IE_TX_COMPLETE 0x0004
-#define IPG_IE_MAC_CTRL_FRAME 0x0008
-#define IPG_IE_RX_COMPLETE 0x0010
-#define IPG_IE_RX_EARLY 0x0020
-#define IPG_IE_INT_REQUESTED 0x0040
-#define IPG_IE_UPDATE_STATS 0x0080
-#define IPG_IE_LINK_EVENT 0x0100
-#define IPG_IE_TX_DMA_COMPLETE 0x0200
-#define IPG_IE_RX_DMA_COMPLETE 0x0400
-#define IPG_IE_RFD_LIST_END 0x0800
-#define IPG_IE_RX_DMA_PRIORITY 0x1000
-
-/* IntStatus */
-#define IPG_IS_RSVD_MASK 0x1FFF
-#define IPG_IS_INTERRUPT_STATUS 0x0001
-#define IPG_IS_HOST_ERROR 0x0002
-#define IPG_IS_TX_COMPLETE 0x0004
-#define IPG_IS_MAC_CTRL_FRAME 0x0008
-#define IPG_IS_RX_COMPLETE 0x0010
-#define IPG_IS_RX_EARLY 0x0020
-#define IPG_IS_INT_REQUESTED 0x0040
-#define IPG_IS_UPDATE_STATS 0x0080
-#define IPG_IS_LINK_EVENT 0x0100
-#define IPG_IS_TX_DMA_COMPLETE 0x0200
-#define IPG_IS_RX_DMA_COMPLETE 0x0400
-#define IPG_IS_RFD_LIST_END 0x0800
-#define IPG_IS_RX_DMA_PRIORITY 0x1000
-
-/* MACCtrl */
-#define IPG_MC_RSVD_MASK 0x7FE33FA3
-#define IPG_MC_IFS_SELECT 0x00000003
-#define IPG_MC_IFS_4352BIT 0x00000003
-#define IPG_MC_IFS_1792BIT 0x00000002
-#define IPG_MC_IFS_1024BIT 0x00000001
-#define IPG_MC_IFS_96BIT 0x00000000
-#define IPG_MC_DUPLEX_SELECT 0x00000020
-#define IPG_MC_DUPLEX_SELECT_FD 0x00000020
-#define IPG_MC_DUPLEX_SELECT_HD 0x00000000
-#define IPG_MC_TX_FLOW_CONTROL_ENABLE 0x00000080
-#define IPG_MC_RX_FLOW_CONTROL_ENABLE 0x00000100
-#define IPG_MC_RCV_FCS 0x00000200
-#define IPG_MC_FIFO_LOOPBACK 0x00000400
-#define IPG_MC_MAC_LOOPBACK 0x00000800
-#define IPG_MC_AUTO_VLAN_TAGGING 0x00001000
-#define IPG_MC_AUTO_VLAN_UNTAGGING 0x00002000
-#define IPG_MC_COLLISION_DETECT 0x00010000
-#define IPG_MC_CARRIER_SENSE 0x00020000
-#define IPG_MC_STATISTICS_ENABLE 0x00200000
-#define IPG_MC_STATISTICS_DISABLE 0x00400000
-#define IPG_MC_STATISTICS_ENABLED 0x00800000
-#define IPG_MC_TX_ENABLE 0x01000000
-#define IPG_MC_TX_DISABLE 0x02000000
-#define IPG_MC_TX_ENABLED 0x04000000
-#define IPG_MC_RX_ENABLE 0x08000000
-#define IPG_MC_RX_DISABLE 0x10000000
-#define IPG_MC_RX_ENABLED 0x20000000
-#define IPG_MC_PAUSED 0x40000000
-
-/*
- * Tune
- */
-
-/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS append on TX. */
-#define IPG_APPEND_FCS_ON_TX 1
-
-/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS strip on RX. */
-#define IPG_STRIP_FCS_ON_RX 1
-
-/* Assign IPG_DROP_ON_RX_ETH_ERRORS > 0 to drop RX frames with
- * Ethernet errors.
- */
-#define IPG_DROP_ON_RX_ETH_ERRORS 1
-
-/* Assign IPG_INSERT_MANUAL_VLAN_TAG > 0 to insert VLAN tags manually
- * (via TFC).
- */
-#define IPG_INSERT_MANUAL_VLAN_TAG 0
-
-/* Assign IPG_ADD_IPCHECKSUM_ON_TX > 0 for auto IP checksum on TX. */
-#define IPG_ADD_IPCHECKSUM_ON_TX 0
-
-/* Assign IPG_ADD_TCPCHECKSUM_ON_TX > 0 for auto TCP checksum on TX.
- * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER.
- */
-#define IPG_ADD_TCPCHECKSUM_ON_TX 0
-
-/* Assign IPG_ADD_UDPCHECKSUM_ON_TX > 0 for auto UDP checksum on TX.
- * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER.
- */
-#define IPG_ADD_UDPCHECKSUM_ON_TX 0
-
-/* If inserting VLAN tags manually, assign the IPG_MANUAL_VLAN_xx
- * constants as desired.
- */
-#define IPG_MANUAL_VLAN_VID 0xABC
-#define IPG_MANUAL_VLAN_CFI 0x1
-#define IPG_MANUAL_VLAN_USERPRIORITY 0x5
-
-#define IPG_IO_REG_RANGE 0xFF
-#define IPG_MEM_REG_RANGE 0x154
-#define IPG_DRIVER_NAME "Sundance Technology IPG Triple-Speed Ethernet"
-#define IPG_NIC_PHY_ADDRESS 0x01
-#define IPG_DMALIST_ALIGN_PAD 0x07
-#define IPG_MULTICAST_HASHTABLE_SIZE 0x40
-
-/* Number of milliseconds to wait after issuing a software reset.
- * 0x05 <= IPG_AC_RESETWAIT to account for proper 10Mbps operation.
- */
-#define IPG_AC_RESETWAIT 0x05
-
-/* Number of IPG_AC_RESETWAIT timeperiods before declaring timeout. */
-#define IPG_AC_RESET_TIMEOUT 0x0A
-
-/* Minimum number of nanoseconds used to toggle MDC clock during
- * MII/GMII register access.
- */
-#define IPG_PC_PHYCTRLWAIT_NS 200
-
-#define IPG_TFDLIST_LENGTH 0x100
-
-/* Number of frames between TxDMAComplete interrupt.
- * 0 < IPG_FRAMESBETWEENTXDMACOMPLETES <= IPG_TFDLIST_LENGTH
- */
-#define IPG_FRAMESBETWEENTXDMACOMPLETES 0x1
-
-#define IPG_RFDLIST_LENGTH 0x100
-
-/* Maximum number of RFDs to process per interrupt.
- * 1 < IPG_MAXRFDPROCESS_COUNT < IPG_RFDLIST_LENGTH
- */
-#define IPG_MAXRFDPROCESS_COUNT 0x80
-
-/* Minimum margin between last freed RFD, and current RFD.
- * 1 < IPG_MINUSEDRFDSTOFREE < IPG_RFDLIST_LENGTH
- */
-#define IPG_MINUSEDRFDSTOFREE 0x80
-
-/* specify the jumbo frame maximum size
- * per unit is 0x600 (the rx_buffer size that one RFD can carry)
- */
-#define MAX_JUMBOSIZE 0x8 /* max is 12K */
-
-/* Key register values loaded at driver start up. */
-
-/* TXDMAPollPeriod is specified in 320ns increments.
- *
- * Value Time
- * ---------------------
- * 0x00-0x01 320ns
- * 0x03 ~1us
- * 0x1F ~10us
- * 0xFF ~82us
- */
-#define IPG_TXDMAPOLLPERIOD_VALUE 0x26
-
-/* TxDMAUrgentThresh specifies the minimum amount of
- * data in the transmit FIFO before asserting an
- * urgent transmit DMA request.
- *
- * Value Min TxFIFO occupied space before urgent TX request
- * ---------------------------------------------------------------
- * 0x00-0x04 128 bytes (1024 bits)
- * 0x27 1248 bytes (~10000 bits)
- * 0x30 1536 bytes (12288 bits)
- * 0xFF 8192 bytes (65535 bits)
- */
-#define IPG_TXDMAURGENTTHRESH_VALUE 0x04
-
-/* TxDMABurstThresh specifies the minimum amount of
- * free space in the transmit FIFO before asserting an
- * transmit DMA request.
- *
- * Value Min TxFIFO free space before TX request
- * ----------------------------------------------------
- * 0x00-0x08 256 bytes
- * 0x30 1536 bytes
- * 0xFF 8192 bytes
- */
-#define IPG_TXDMABURSTTHRESH_VALUE 0x30
-
-/* RXDMAPollPeriod is specified in 320ns increments.
- *
- * Value Time
- * ---------------------
- * 0x00-0x01 320ns
- * 0x03 ~1us
- * 0x1F ~10us
- * 0xFF ~82us
- */
-#define IPG_RXDMAPOLLPERIOD_VALUE 0x01
-
-/* RxDMAUrgentThresh specifies the minimum amount of
- * free space within the receive FIFO before asserting
- * a urgent receive DMA request.
- *
- * Value Min RxFIFO free space before urgent RX request
- * ---------------------------------------------------------------
- * 0x00-0x04 128 bytes (1024 bits)
- * 0x27 1248 bytes (~10000 bits)
- * 0x30 1536 bytes (12288 bits)
- * 0xFF 8192 bytes (65535 bits)
- */
-#define IPG_RXDMAURGENTTHRESH_VALUE 0x30
-
-/* RxDMABurstThresh specifies the minimum amount of
- * occupied space within the receive FIFO before asserting
- * a receive DMA request.
- *
- * Value Min TxFIFO free space before TX request
- * ----------------------------------------------------
- * 0x00-0x08 256 bytes
- * 0x30 1536 bytes
- * 0xFF 8192 bytes
- */
-#define IPG_RXDMABURSTTHRESH_VALUE 0x30
-
-/* FlowOnThresh specifies the maximum amount of occupied
- * space in the receive FIFO before a PAUSE frame with
- * maximum pause time transmitted.
- *
- * Value Max RxFIFO occupied space before PAUSE
- * ---------------------------------------------------
- * 0x0000 0 bytes
- * 0x0740 29,696 bytes
- * 0x07FF 32,752 bytes
- */
-#define IPG_FLOWONTHRESH_VALUE 0x0740
-
-/* FlowOffThresh specifies the minimum amount of occupied
- * space in the receive FIFO before a PAUSE frame with
- * zero pause time is transmitted.
- *
- * Value Max RxFIFO occupied space before PAUSE
- * ---------------------------------------------------
- * 0x0000 0 bytes
- * 0x00BF 3056 bytes
- * 0x07FF 32,752 bytes
- */
-#define IPG_FLOWOFFTHRESH_VALUE 0x00BF
-
-/*
- * Miscellaneous macros.
- */
-
-/* Macros for printing debug statements. */
-#ifdef IPG_DEBUG
-# define IPG_DEBUG_MSG(fmt, args...) \
-do { \
- if (0) \
- printk(KERN_DEBUG "IPG: " fmt, ##args); \
-} while (0)
-# define IPG_DDEBUG_MSG(fmt, args...) \
- printk(KERN_DEBUG "IPG: " fmt, ##args)
-# define IPG_DUMPRFDLIST(args) ipg_dump_rfdlist(args)
-# define IPG_DUMPTFDLIST(args) ipg_dump_tfdlist(args)
-#else
-# define IPG_DEBUG_MSG(fmt, args...) \
-do { \
- if (0) \
- printk(KERN_DEBUG "IPG: " fmt, ##args); \
-} while (0)
-# define IPG_DDEBUG_MSG(fmt, args...) \
-do { \
- if (0) \
- printk(KERN_DEBUG "IPG: " fmt, ##args); \
-} while (0)
-# define IPG_DUMPRFDLIST(args)
-# define IPG_DUMPTFDLIST(args)
-#endif
-
-/*
- * End miscellaneous macros.
- */
-
-/* Transmit Frame Descriptor. The IPG supports 15 fragments,
- * however Linux requires only a single fragment. Note, each
- * TFD field is 64 bits wide.
- */
-struct ipg_tx {
- __le64 next_desc;
- __le64 tfc;
- __le64 frag_info;
-};
-
-/* Receive Frame Descriptor. Note, each RFD field is 64 bits wide.
- */
-struct ipg_rx {
- __le64 next_desc;
- __le64 rfs;
- __le64 frag_info;
-};
-
-struct ipg_jumbo {
- int found_start;
- int current_size;
- struct sk_buff *skb;
-};
-
-/* Structure of IPG NIC specific data. */
-struct ipg_nic_private {
- void __iomem *ioaddr;
- struct ipg_tx *txd;
- struct ipg_rx *rxd;
- dma_addr_t txd_map;
- dma_addr_t rxd_map;
- struct sk_buff *tx_buff[IPG_TFDLIST_LENGTH];
- struct sk_buff *rx_buff[IPG_RFDLIST_LENGTH];
- unsigned int tx_current;
- unsigned int tx_dirty;
- unsigned int rx_current;
- unsigned int rx_dirty;
- bool is_jumbo;
- struct ipg_jumbo jumbo;
- unsigned long rxfrag_size;
- unsigned long rxsupport_size;
- unsigned long max_rxframe_size;
- unsigned int rx_buf_sz;
- struct pci_dev *pdev;
- struct net_device *dev;
- struct net_device_stats stats;
- spinlock_t lock;
- int tenmbpsmode;
-
- u16 led_mode;
- u16 station_addr[3]; /* Station Address in EEPROM Reg 0x10..0x12 */
-
- struct mutex mii_mutex;
- struct mii_if_info mii_if;
- int reset_current_tfd;
-#ifdef IPG_DEBUG
- int RFDlistendCount;
- int RFDListCheckedCount;
- int EmptyRFDListCount;
-#endif
- struct delayed_work task;
-};
-
-#endif /* __LINUX_IPG_H */
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 4270ad2d4ddf..83e557c7f279 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -559,8 +559,6 @@ static void e1000_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = e1000_get_regs_len(netdev);
- drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
}
static void e1000_get_ringparam(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index 45c8c864104e..b1af0d613caa 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -3900,10 +3900,6 @@ static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
return E1000_SUCCESS;
}
- /* If eeprom is not yet detected, do so now */
- if (eeprom->word_size == 0)
- e1000_init_eeprom_params(hw);
-
/* A check for invalid values: offset too large, too many words, and
* not enough words.
*/
@@ -4074,10 +4070,6 @@ static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
return E1000_SUCCESS;
}
- /* If eeprom is not yet detected, do so now */
- if (eeprom->word_size == 0)
- e1000_init_eeprom_params(hw);
-
/* A check for invalid values: offset too large, too many words, and
* not enough words.
*/
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 74dc15055971..fd7be860c201 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -3820,7 +3820,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
if (work_done < budget) {
if (likely(adapter->itr_setting & 3))
e1000_set_itr(adapter);
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
}
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index ad6daa656d3e..6cab1f30d41e 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -648,8 +648,6 @@ static void e1000_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = e1000_get_regs_len(netdev);
- drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
}
static void e1000_get_ringparam(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index faf4b3f3d0b5..0a854a47d31a 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2693,7 +2693,7 @@ static int e1000e_poll(struct napi_struct *napi, int weight)
if (work_done < weight) {
if (adapter->itr_setting & 3)
e1000_set_itr(adapter);
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
if (!test_bit(__E1000_DOWN, &adapter->state)) {
if (adapter->msix_entries)
ew32(IMS, adapter->rx_ring->ims_val);
@@ -6952,6 +6952,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
#endif
.ndo_set_features = e1000_set_features,
.ndo_fix_features = e1000_fix_features,
+ .ndo_features_check = passthru_features_check,
};
/**
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
index c8c8c5baefda..14440200499b 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
@@ -101,12 +101,19 @@ struct fm10k_tx_queue_stats {
u64 csum_err;
u64 tx_busy;
u64 tx_done_old;
+ u64 csum_good;
};
struct fm10k_rx_queue_stats {
u64 alloc_failed;
u64 csum_err;
u64 errors;
+ u64 csum_good;
+ u64 switch_errors;
+ u64 drops;
+ u64 pp_errors;
+ u64 link_errors;
+ u64 length_errors;
};
struct fm10k_ring {
@@ -251,6 +258,7 @@ struct fm10k_intfc {
#define FM10K_FLAG_RSS_FIELD_IPV6_UDP (u32)(1 << 2)
#define FM10K_FLAG_RX_TS_ENABLED (u32)(1 << 3)
#define FM10K_FLAG_SWPRI_CONFIG (u32)(1 << 4)
+#define FM10K_FLAG_DEBUG_STATS (u32)(1 << 5)
int xcast_mode;
/* Tx fast path data */
@@ -277,6 +285,17 @@ struct fm10k_intfc {
u64 rx_drops_nic;
u64 rx_overrun_pf;
u64 rx_overrun_vf;
+
+ /* Debug Statistics */
+ u64 hw_sm_mbx_full;
+ u64 hw_csum_tx_good;
+ u64 hw_csum_rx_good;
+ u64 rx_switch_errors;
+ u64 rx_drops;
+ u64 rx_pp_errors;
+ u64 rx_link_errors;
+ u64 rx_length_errors;
+
u32 tx_timeout_count;
/* RX */
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
index f45b4d71adb8..5304bc1fbecd 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
@@ -37,7 +37,8 @@ static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos)
}
static void *fm10k_dbg_desc_seq_next(struct seq_file *s,
- void __always_unused *v, loff_t *pos)
+ void __always_unused *v,
+ loff_t *pos)
{
struct fm10k_ring *ring = s->private;
@@ -45,7 +46,7 @@ static void *fm10k_dbg_desc_seq_next(struct seq_file *s,
}
static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s,
- __always_unused void *v)
+ void __always_unused *v)
{
/* Do nothing. */
}
@@ -175,7 +176,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
return;
/* Generate a folder for each q_vector */
- sprintf(name, "q_vector.%03d", q_vector->v_idx);
+ snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx);
q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc);
if (!q_vector->dbg_q_vector)
@@ -185,7 +186,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
for (i = 0; i < q_vector->tx.count; i++) {
struct fm10k_ring *ring = &q_vector->tx.ring[i];
- sprintf(name, "tx_ring.%03d", ring->queue_index);
+ snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index);
debugfs_create_file(name, 0600,
q_vector->dbg_q_vector, ring,
@@ -196,7 +197,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
for (i = 0; i < q_vector->rx.count; i++) {
struct fm10k_ring *ring = &q_vector->rx.ring[i];
- sprintf(name, "rx_ring.%03d", ring->queue_index);
+ snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index);
debugfs_create_file(name, 0600,
q_vector->dbg_q_vector, ring,
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
index c6dc9683429e..2ce0eba5e040 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
@@ -76,19 +76,22 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = {
FM10K_STAT("mac_rules_used", hw.swapi.mac.used),
FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail),
- FM10K_STAT("mbx_tx_busy", hw.mbx.tx_busy),
- FM10K_STAT("mbx_tx_oversized", hw.mbx.tx_dropped),
- FM10K_STAT("mbx_tx_messages", hw.mbx.tx_messages),
- FM10K_STAT("mbx_tx_dwords", hw.mbx.tx_dwords),
- FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages),
- FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords),
- FM10K_STAT("mbx_rx_parse_err", hw.mbx.rx_parse_err),
-
FM10K_STAT("tx_hang_count", tx_timeout_count),
FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
};
+static const struct fm10k_stats fm10k_gstrings_debug_stats[] = {
+ FM10K_STAT("hw_sm_mbx_full", hw_sm_mbx_full),
+ FM10K_STAT("hw_csum_tx_good", hw_csum_tx_good),
+ FM10K_STAT("hw_csum_rx_good", hw_csum_rx_good),
+ FM10K_STAT("rx_switch_errors", rx_switch_errors),
+ FM10K_STAT("rx_drops", rx_drops),
+ FM10K_STAT("rx_pp_errors", rx_pp_errors),
+ FM10K_STAT("rx_link_errors", rx_link_errors),
+ FM10K_STAT("rx_length_errors", rx_length_errors),
+};
+
static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {
FM10K_STAT("timeout", stats.timeout.count),
FM10K_STAT("ur", stats.ur.count),
@@ -100,14 +103,33 @@ static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {
FM10K_STAT("nodesc_drop", stats.nodesc_drop.count),
};
+#define FM10K_MBX_STAT(_name, _stat) { \
+ .stat_string = _name, \
+ .sizeof_stat = FIELD_SIZEOF(struct fm10k_mbx_info, _stat), \
+ .stat_offset = offsetof(struct fm10k_mbx_info, _stat) \
+}
+
+static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = {
+ FM10K_MBX_STAT("mbx_tx_busy", tx_busy),
+ FM10K_MBX_STAT("mbx_tx_oversized", tx_dropped),
+ FM10K_MBX_STAT("mbx_tx_messages", tx_messages),
+ FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords),
+ FM10K_MBX_STAT("mbx_rx_messages", rx_messages),
+ FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords),
+ FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err),
+};
+
#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats)
+#define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats)
#define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats)
+#define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats)
#define FM10K_QUEUE_STATS_LEN(_n) \
( (_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64)))
#define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \
- FM10K_NETDEV_STATS_LEN)
+ FM10K_NETDEV_STATS_LEN + \
+ FM10K_MBX_STATS_LEN)
static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = {
"Mailbox test (on/offline)"
@@ -120,47 +142,97 @@ enum fm10k_self_test_types {
FM10K_TEST_MAX = FM10K_TEST_LEN
};
-static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+enum {
+ FM10K_PRV_FLAG_DEBUG_STATS,
+ FM10K_PRV_FLAG_LEN,
+};
+
+static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = {
+ "debug-statistics",
+};
+
+static void fm10k_get_stat_strings(struct net_device *dev, u8 *data)
{
struct fm10k_intfc *interface = netdev_priv(dev);
+ struct fm10k_iov_data *iov_data = interface->iov_data;
char *p = (char *)data;
unsigned int i;
+ unsigned int j;
- switch (stringset) {
- case ETH_SS_TEST:
- memcpy(data, *fm10k_gstrings_test,
- FM10K_TEST_LEN * ETH_GSTRING_LEN);
- break;
- case ETH_SS_STATS:
- for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) {
- memcpy(p, fm10k_gstrings_net_stats[i].stat_string,
+ for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) {
+ memcpy(p, fm10k_gstrings_net_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+
+ for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) {
+ memcpy(p, fm10k_gstrings_global_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+
+ if (interface->flags & FM10K_FLAG_DEBUG_STATS) {
+ for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) {
+ memcpy(p, fm10k_gstrings_debug_stats[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
- for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) {
- memcpy(p, fm10k_gstrings_global_stats[i].stat_string,
+ }
+
+ for (i = 0; i < FM10K_MBX_STATS_LEN; i++) {
+ memcpy(p, fm10k_gstrings_mbx_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+
+ if (interface->hw.mac.type != fm10k_mac_vf) {
+ for (i = 0; i < FM10K_PF_STATS_LEN; i++) {
+ memcpy(p, fm10k_gstrings_pf_stats[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+ }
- if (interface->hw.mac.type != fm10k_mac_vf) {
- for (i = 0; i < FM10K_PF_STATS_LEN; i++) {
- memcpy(p, fm10k_gstrings_pf_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) {
+ for (i = 0; i < iov_data->num_vfs; i++) {
+ for (j = 0; j < FM10K_MBX_STATS_LEN; j++) {
+ snprintf(p,
+ ETH_GSTRING_LEN,
+ "vf_%u_%s", i,
+ fm10k_gstrings_mbx_stats[j].stat_string);
p += ETH_GSTRING_LEN;
}
}
+ }
- for (i = 0; i < interface->hw.mac.max_queues; i++) {
- sprintf(p, "tx_queue_%u_packets", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_queue_%u_bytes", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_queue_%u_packets", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_queue_%u_bytes", i);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < interface->hw.mac.max_queues; i++) {
+ snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+}
+
+static void fm10k_get_strings(struct net_device *dev,
+ u32 stringset, u8 *data)
+{
+ char *p = (char *)data;
+
+ switch (stringset) {
+ case ETH_SS_TEST:
+ memcpy(data, *fm10k_gstrings_test,
+ FM10K_TEST_LEN * ETH_GSTRING_LEN);
+ break;
+ case ETH_SS_STATS:
+ fm10k_get_stat_strings(dev, data);
+ break;
+ case ETH_SS_PRIV_FLAGS:
+ memcpy(p, fm10k_prv_flags,
+ FM10K_PRV_FLAG_LEN * ETH_GSTRING_LEN);
break;
}
}
@@ -168,6 +240,7 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data)
static int fm10k_get_sset_count(struct net_device *dev, int sset)
{
struct fm10k_intfc *interface = netdev_priv(dev);
+ struct fm10k_iov_data *iov_data = interface->iov_data;
struct fm10k_hw *hw = &interface->hw;
int stats_len = FM10K_STATIC_STATS_LEN;
@@ -180,7 +253,16 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset)
if (hw->mac.type != fm10k_mac_vf)
stats_len += FM10K_PF_STATS_LEN;
+ if (interface->flags & FM10K_FLAG_DEBUG_STATS) {
+ stats_len += FM10K_DEBUG_STATS_LEN;
+
+ if (iov_data)
+ stats_len += FM10K_MBX_STATS_LEN * iov_data->num_vfs;
+ }
+
return stats_len;
+ case ETH_SS_PRIV_FLAGS:
+ return FM10K_PRV_FLAG_LEN;
default:
return -EOPNOTSUPP;
}
@@ -192,6 +274,7 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
{
const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64);
struct fm10k_intfc *interface = netdev_priv(netdev);
+ struct fm10k_iov_data *iov_data = interface->iov_data;
struct net_device_stats *net_stats = &netdev->stats;
char *p;
int i, j;
@@ -211,13 +294,47 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
- if (interface->hw.mac.type != fm10k_mac_vf)
+ if (interface->flags & FM10K_FLAG_DEBUG_STATS) {
+ for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) {
+ p = (char *)interface + fm10k_gstrings_debug_stats[i].stat_offset;
+ *(data++) = (fm10k_gstrings_debug_stats[i].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+ }
+
+ for (i = 0; i < FM10K_MBX_STATS_LEN; i++) {
+ p = (char *)&interface->hw.mbx + fm10k_gstrings_mbx_stats[i].stat_offset;
+ *(data++) = (fm10k_gstrings_mbx_stats[i].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+
+ if (interface->hw.mac.type != fm10k_mac_vf) {
for (i = 0; i < FM10K_PF_STATS_LEN; i++) {
p = (char *)interface +
fm10k_gstrings_pf_stats[i].stat_offset;
*(data++) = (fm10k_gstrings_pf_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
+ }
+
+ if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) {
+ for (i = 0; i < iov_data->num_vfs; i++) {
+ struct fm10k_vf_info *vf_info;
+ vf_info = &iov_data->vf_info[i];
+
+ /* skip stats if we don't have a vf info */
+ if (!vf_info) {
+ data += FM10K_MBX_STATS_LEN;
+ continue;
+ }
+
+ for (j = 0; j < FM10K_MBX_STATS_LEN; j++) {
+ p = (char *)&vf_info->mbx + fm10k_gstrings_mbx_stats[j].stat_offset;
+ *(data++) = (fm10k_gstrings_mbx_stats[j].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+ }
+ }
for (i = 0; i < interface->hw.mac.max_queues; i++) {
struct fm10k_ring *ring;
@@ -398,10 +515,6 @@ static void fm10k_get_drvinfo(struct net_device *dev,
sizeof(info->version) - 1);
strncpy(info->bus_info, pci_name(interface->pdev),
sizeof(info->bus_info) - 1);
-
- info->n_stats = fm10k_get_sset_count(dev, ETH_SS_STATS);
-
- info->regdump_len = fm10k_get_regs_len(dev);
}
static void fm10k_get_pauseparam(struct net_device *dev,
@@ -881,6 +994,33 @@ static void fm10k_self_test(struct net_device *dev,
eth_test->flags |= ETH_TEST_FL_FAILED;
}
+static u32 fm10k_get_priv_flags(struct net_device *netdev)
+{
+ struct fm10k_intfc *interface = netdev_priv(netdev);
+ u32 priv_flags = 0;
+
+ if (interface->flags & FM10K_FLAG_DEBUG_STATS)
+ priv_flags |= 1 << FM10K_PRV_FLAG_DEBUG_STATS;
+
+ return priv_flags;
+}
+
+static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags)
+{
+ struct fm10k_intfc *interface = netdev_priv(netdev);
+
+ if (priv_flags >= (1 << FM10K_PRV_FLAG_LEN))
+ return -EINVAL;
+
+ if (priv_flags & (1 << FM10K_PRV_FLAG_DEBUG_STATS))
+ interface->flags |= FM10K_FLAG_DEBUG_STATS;
+ else
+ interface->flags &= ~FM10K_FLAG_DEBUG_STATS;
+
+ return 0;
+}
+
+
static u32 fm10k_get_reta_size(struct net_device __always_unused *netdev)
{
return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
@@ -1094,6 +1234,8 @@ static const struct ethtool_ops fm10k_ethtool_ops = {
.get_regs = fm10k_get_regs,
.get_regs_len = fm10k_get_regs_len,
.self_test = fm10k_self_test,
+ .get_priv_flags = fm10k_get_priv_flags,
+ .set_priv_flags = fm10k_set_priv_flags,
.get_rxfh_indir_size = fm10k_get_reta_size,
.get_rxfh_key_size = fm10k_get_rssrk_size,
.get_rxfh = fm10k_get_rssh,
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c
index 94571e6e790c..acfb8b1f88a7 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c
@@ -137,8 +137,11 @@ process_mbx:
}
/* guarantee we have free space in the SM mailbox */
- if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU))
+ if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) {
+ /* keep track of how many times this occurs */
+ interface->hw_sm_mbx_full++;
break;
+ }
/* cleanup mailbox and process received messages */
mbx->ops.process(hw, mbx);
@@ -228,9 +231,6 @@ int fm10k_iov_resume(struct pci_dev *pdev)
hw->iov.ops.set_lport(hw, vf_info, i,
FM10K_VF_FLAG_MULTI_CAPABLE);
- /* assign our default vid to the VF following reset */
- vf_info->sw_vid = hw->mac.default_vid;
-
/* mailbox is disconnected so we don't send a message */
hw->iov.ops.assign_default_mac_vlan(hw, vf_info);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index b5b2925103ec..e76a44cf330c 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -398,6 +398,8 @@ static inline void fm10k_rx_checksum(struct fm10k_ring *ring,
return;
skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ ring->rx_stats.csum_good++;
}
#define FM10K_RSS_L4_TYPES_MASK \
@@ -497,8 +499,11 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring,
if (rx_desc->w.vlan) {
u16 vid = le16_to_cpu(rx_desc->w.vlan);
- if (vid != rx_ring->vid)
+ if ((vid & VLAN_VID_MASK) != rx_ring->vid)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
+ else if (vid & VLAN_PRIO_MASK)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ vid & VLAN_PRIO_MASK);
}
fm10k_type_trans(rx_ring, rx_desc, skb);
@@ -553,6 +558,18 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring,
{
if (unlikely((fm10k_test_staterr(rx_desc,
FM10K_RXD_STATUS_RXE)))) {
+#define FM10K_TEST_RXD_BIT(rxd, bit) \
+ ((rxd)->w.csum_err & cpu_to_le16(bit))
+ if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_SWITCH_ERROR))
+ rx_ring->rx_stats.switch_errors++;
+ if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_NO_DESCRIPTOR))
+ rx_ring->rx_stats.drops++;
+ if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_PP_ERROR))
+ rx_ring->rx_stats.pp_errors++;
+ if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_SWITCH_READY))
+ rx_ring->rx_stats.link_errors++;
+ if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_TOO_BIG))
+ rx_ring->rx_stats.length_errors++;
dev_kfree_skb_any(skb);
rx_ring->rx_stats.errors++;
return true;
@@ -576,9 +593,9 @@ static void fm10k_receive_skb(struct fm10k_q_vector *q_vector,
napi_gro_receive(&q_vector->napi, skb);
}
-static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
- struct fm10k_ring *rx_ring,
- int budget)
+static int fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
+ struct fm10k_ring *rx_ring,
+ int budget)
{
struct sk_buff *skb = rx_ring->skb;
unsigned int total_bytes = 0, total_packets = 0;
@@ -645,7 +662,7 @@ static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
q_vector->rx.total_packets += total_packets;
q_vector->rx.total_bytes += total_bytes;
- return total_packets < budget;
+ return total_packets;
}
#define VXLAN_HLEN (sizeof(struct udphdr) + 8)
@@ -878,6 +895,7 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
/* update TX checksum flag */
first->tx_flags |= FM10K_TX_FLAGS_CSUM;
+ tx_ring->tx_stats.csum_good++;
no_csum:
/* populate Tx descriptor header size and mss */
@@ -1079,9 +1097,7 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
struct fm10k_tx_buffer *first;
int tso;
u32 tx_flags = 0;
-#if PAGE_SIZE > FM10K_MAX_DATA_PER_TXD
unsigned short f;
-#endif
u16 count = TXD_USE_COUNT(skb_headlen(skb));
/* need: 1 descriptor per page * PAGE_SIZE/FM10K_MAX_DATA_PER_TXD,
@@ -1089,12 +1105,9 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
* + 2 desc gap to keep tail from touching head
* otherwise try next time
*/
-#if PAGE_SIZE > FM10K_MAX_DATA_PER_TXD
for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
-#else
- count += skb_shinfo(skb)->nr_frags;
-#endif
+
if (fm10k_maybe_stop_tx(tx_ring, count + 3)) {
tx_ring->tx_stats.tx_busy++;
return NETDEV_TX_BUSY;
@@ -1409,7 +1422,7 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
struct fm10k_q_vector *q_vector =
container_of(napi, struct fm10k_q_vector, napi);
struct fm10k_ring *ring;
- int per_ring_budget;
+ int per_ring_budget, work_done = 0;
bool clean_complete = true;
fm10k_for_each_ring(ring, q_vector->tx)
@@ -1423,16 +1436,19 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
else
per_ring_budget = budget;
- fm10k_for_each_ring(ring, q_vector->rx)
- clean_complete &= fm10k_clean_rx_irq(q_vector, ring,
- per_ring_budget);
+ fm10k_for_each_ring(ring, q_vector->rx) {
+ int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget);
+
+ work_done += work;
+ clean_complete &= !!(work < per_ring_budget);
+ }
/* If all work not completed, return budget and keep polling */
if (!clean_complete)
return budget;
/* all work done, exit the polling mode */
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
/* re-enable the q_vector */
fm10k_qv_enable(q_vector);
@@ -1892,7 +1908,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface)
u32 reta, base;
/* If the netdev is initialized we have to maintain table if possible */
- if (interface->netdev->reg_state) {
+ if (interface->netdev->reg_state != NETREG_UNINITIALIZED) {
for (i = FM10K_RETA_SIZE; i--;) {
reta = interface->reta[i];
if ((((reta << 24) >> 24) < rss_i) &&
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
index 1a4b52637de9..af09a1b272e6 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
@@ -129,8 +129,8 @@ static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
* fm10k_fifo_drop_all - Drop all messages in FIFO
* @fifo: pointer to FIFO
*
- * This function resets the head pointer to drop all messages in the FIFO,
- * and ensure the FIFO is empty.
+ * This function resets the head pointer to drop all messages in the FIFO and
+ * ensure the FIFO is empty.
**/
static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
{
@@ -899,6 +899,27 @@ static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
}
/**
+ * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mailbox header
+ * @mbx: pointer to mailbox
+ *
+ * This function creates a fake disconnect header for loading into remote
+ * mailbox header. The primary purpose is to prevent errors on immediate
+ * start up after mbx->connect.
+ **/
+static void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
+{
+ u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
+ FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
+ FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
+ u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
+
+ mbx->mbx_lock |= FM10K_MBX_ACK;
+
+ /* load header to memory to be written */
+ mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
+}
+
+/**
* fm10k_mbx_create_error_msg - Generate a error message
* @mbx: pointer to mailbox
* @err: local error encountered
@@ -1046,9 +1067,26 @@ static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
**/
static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
{
+ u16 len, head, ack;
+
/* reset our outgoing max size back to Rx limits */
mbx->max_size = mbx->rx.size - 1;
+ /* update mbx->pulled to account for tail_len and ack */
+ head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
+ ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
+ mbx->pulled += mbx->tail_len - ack;
+
+ /* now drop any messages which have started or finished transmitting */
+ while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
+ len = fm10k_fifo_head_drop(&mbx->tx);
+ mbx->tx_dropped++;
+ if (mbx->pulled >= len)
+ mbx->pulled -= len;
+ else
+ mbx->pulled = 0;
+ }
+
/* just do a quick resysnc to start of message */
mbx->pushed = 0;
mbx->pulled = 0;
@@ -1418,8 +1456,10 @@ static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
/* Place mbx in ready to connect state */
mbx->state = FM10K_STATE_CONNECT;
+ fm10k_mbx_reset_work(mbx);
+
/* initialize header of remote mailbox */
- fm10k_mbx_create_disconnect_hdr(mbx);
+ fm10k_mbx_create_fake_disconnect_hdr(mbx);
fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
/* enable interrupt and notify other party of new message */
@@ -1725,7 +1765,7 @@ static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
mbx->state = FM10K_STATE_CLOSED;
mbx->remote = 0;
fm10k_mbx_reset_work(mbx);
- fm10k_mbx_update_max_size(mbx, 0);
+ fm10k_fifo_drop_all(&mbx->tx);
fm10k_write_reg(hw, mbx->mbmem_reg, 0);
}
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 99228bf46c12..639263d5e833 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -758,6 +758,7 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set)
struct fm10k_intfc *interface = netdev_priv(netdev);
struct fm10k_hw *hw = &interface->hw;
s32 err;
+ int i;
/* updates do not apply to VLAN 0 */
if (!vid)
@@ -775,8 +776,25 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set)
if (!set)
clear_bit(vid, interface->active_vlans);
- /* if default VLAN is already present do nothing */
- if (vid == hw->mac.default_vid)
+ /* disable the default VID on ring if we have an active VLAN */
+ for (i = 0; i < interface->num_rx_queues; i++) {
+ struct fm10k_ring *rx_ring = interface->rx_ring[i];
+ u16 rx_vid = rx_ring->vid & (VLAN_N_VID - 1);
+
+ if (test_bit(rx_vid, interface->active_vlans))
+ rx_ring->vid |= FM10K_VLAN_CLEAR;
+ else
+ rx_ring->vid &= ~FM10K_VLAN_CLEAR;
+ }
+
+ /* Do not remove default VID related entries from VLAN and MAC tables */
+ if (!set && vid == hw->mac.default_vid)
+ return 0;
+
+ /* Do not throw an error if the interface is down. We will sync once
+ * we come up
+ */
+ if (test_bit(__FM10K_DOWN, &interface->state))
return 0;
fm10k_mbx_lock(interface);
@@ -996,21 +1014,6 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
int xcast_mode;
u16 vid, glort;
- /* restore our address if perm_addr is set */
- if (hw->mac.type == fm10k_mac_vf) {
- if (is_valid_ether_addr(hw->mac.perm_addr)) {
- ether_addr_copy(hw->mac.addr, hw->mac.perm_addr);
- ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr);
- ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr);
- netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
- }
-
- if (hw->mac.vlan_override)
- netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
- else
- netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
- }
-
/* record glort for this interface */
glort = interface->glort;
@@ -1045,7 +1048,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
vid, true, 0);
}
- /* update xcast mode before syncronizing addresses */
+ /* update xcast mode before synchronizing addresses */
hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode);
/* synchronize all of the addresses */
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index ce53ff25f88d..74be792f3f1b 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -170,6 +170,21 @@ static void fm10k_reinit(struct fm10k_intfc *interface)
/* reassociate interrupts */
fm10k_mbx_request_irq(interface);
+ /* update hardware address for VFs if perm_addr has changed */
+ if (hw->mac.type == fm10k_mac_vf) {
+ if (is_valid_ether_addr(hw->mac.perm_addr)) {
+ ether_addr_copy(hw->mac.addr, hw->mac.perm_addr);
+ ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr);
+ ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr);
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
+ }
+
+ if (hw->mac.vlan_override)
+ netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+ else
+ netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+ }
+
/* reset clock */
fm10k_ts_reset(interface);
@@ -259,8 +274,6 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface)
* @interface: board private structure
*
* This function will process both the upstream and downstream mailboxes.
- * It is necessary for us to hold the rtnl_lock while doing this as the
- * mailbox accesses are protected by this lock.
**/
static void fm10k_mbx_subtask(struct fm10k_intfc *interface)
{
@@ -315,6 +328,9 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
{
struct net_device_stats *net_stats = &interface->netdev->stats;
struct fm10k_hw *hw = &interface->hw;
+ u64 hw_csum_tx_good = 0, hw_csum_rx_good = 0, rx_length_errors = 0;
+ u64 rx_switch_errors = 0, rx_drops = 0, rx_pp_errors = 0;
+ u64 rx_link_errors = 0;
u64 rx_errors = 0, rx_csum_errors = 0, tx_csum_errors = 0;
u64 restart_queue = 0, tx_busy = 0, alloc_failed = 0;
u64 rx_bytes_nic = 0, rx_pkts_nic = 0, rx_drops_nic = 0;
@@ -334,6 +350,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
tx_csum_errors += tx_ring->tx_stats.csum_err;
bytes += tx_ring->stats.bytes;
pkts += tx_ring->stats.packets;
+ hw_csum_tx_good += tx_ring->tx_stats.csum_good;
}
interface->restart_queue = restart_queue;
@@ -341,6 +358,8 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
net_stats->tx_bytes = bytes;
net_stats->tx_packets = pkts;
interface->tx_csum_errors = tx_csum_errors;
+ interface->hw_csum_tx_good = hw_csum_tx_good;
+
/* gather some stats to the interface struct that are per queue */
for (bytes = 0, pkts = 0, i = 0; i < interface->num_rx_queues; i++) {
struct fm10k_ring *rx_ring = interface->rx_ring[i];
@@ -350,12 +369,24 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
alloc_failed += rx_ring->rx_stats.alloc_failed;
rx_csum_errors += rx_ring->rx_stats.csum_err;
rx_errors += rx_ring->rx_stats.errors;
+ hw_csum_rx_good += rx_ring->rx_stats.csum_good;
+ rx_switch_errors += rx_ring->rx_stats.switch_errors;
+ rx_drops += rx_ring->rx_stats.drops;
+ rx_pp_errors += rx_ring->rx_stats.pp_errors;
+ rx_link_errors += rx_ring->rx_stats.link_errors;
+ rx_length_errors += rx_ring->rx_stats.length_errors;
}
net_stats->rx_bytes = bytes;
net_stats->rx_packets = pkts;
interface->alloc_failed = alloc_failed;
interface->rx_csum_errors = rx_csum_errors;
+ interface->hw_csum_rx_good = hw_csum_rx_good;
+ interface->rx_switch_errors = rx_switch_errors;
+ interface->rx_drops = rx_drops;
+ interface->rx_pp_errors = rx_pp_errors;
+ interface->rx_link_errors = rx_link_errors;
+ interface->rx_length_errors = rx_length_errors;
hw->mac.ops.update_hw_stats(hw, &interface->stats);
@@ -483,7 +514,7 @@ static void fm10k_service_task(struct work_struct *work)
interface = container_of(work, struct fm10k_intfc, service_task);
- /* tasks always capable of running, but must be rtnl protected */
+ /* tasks run even when interface is down */
fm10k_mbx_subtask(interface);
fm10k_detach_subtask(interface);
fm10k_reset_subtask(interface);
@@ -663,6 +694,10 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface,
/* assign default VLAN to queue */
ring->vid = hw->mac.default_vid;
+ /* if we have an active VLAN, disable default VID */
+ if (test_bit(hw->mac.default_vid, interface->active_vlans))
+ ring->vid |= FM10K_VLAN_CLEAR;
+
/* Map interrupt */
if (ring->q_vector) {
rxint = ring->q_vector->v_idx + NON_Q_VECTORS(hw);
@@ -861,10 +896,12 @@ void fm10k_netpoll(struct net_device *netdev)
#endif
#define FM10K_ERR_MSG(type) case (type): error = #type; break
-static void fm10k_print_fault(struct fm10k_intfc *interface, int type,
+static void fm10k_handle_fault(struct fm10k_intfc *interface, int type,
struct fm10k_fault *fault)
{
struct pci_dev *pdev = interface->pdev;
+ struct fm10k_hw *hw = &interface->hw;
+ struct fm10k_iov_data *iov_data = interface->iov_data;
char *error;
switch (type) {
@@ -918,6 +955,30 @@ static void fm10k_print_fault(struct fm10k_intfc *interface, int type,
"%s Address: 0x%llx SpecInfo: 0x%x Func: %02x.%0x\n",
error, fault->address, fault->specinfo,
PCI_SLOT(fault->func), PCI_FUNC(fault->func));
+
+ /* For VF faults, clear out the respective LPORT, reset the queue
+ * resources, and then reconnect to the mailbox. This allows the
+ * VF in question to resume behavior. For transient faults that are
+ * the result of non-malicious behavior this will log the fault and
+ * allow the VF to resume functionality. Obviously for malicious VFs
+ * they will be able to attempt malicious behavior again. In this
+ * case, the system administrator will need to step in and manually
+ * remove or disable the VF in question.
+ */
+ if (fault->func && iov_data) {
+ int vf = fault->func - 1;
+ struct fm10k_vf_info *vf_info = &iov_data->vf_info[vf];
+
+ hw->iov.ops.reset_lport(hw, vf_info);
+ hw->iov.ops.reset_resources(hw, vf_info);
+
+ /* reset_lport disables the VF, so re-enable it */
+ hw->iov.ops.set_lport(hw, vf_info, vf,
+ FM10K_VF_FLAG_MULTI_CAPABLE);
+
+ /* reset_resources will disconnect from the mbx */
+ vf_info->mbx.ops.connect(hw, &vf_info->mbx);
+ }
}
static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr)
@@ -941,7 +1002,7 @@ static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr)
continue;
}
- fm10k_print_fault(interface, type, &fault);
+ fm10k_handle_fault(interface, type, &fault);
}
}
@@ -1705,22 +1766,86 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
static void fm10k_slot_warn(struct fm10k_intfc *interface)
{
- struct device *dev = &interface->pdev->dev;
+ enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
+ enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
struct fm10k_hw *hw = &interface->hw;
+ int max_gts = 0, expected_gts = 0;
+
+ if (pcie_get_minimum_link(interface->pdev, &speed, &width) ||
+ speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) {
+ dev_warn(&interface->pdev->dev,
+ "Unable to determine PCI Express bandwidth.\n");
+ return;
+ }
+
+ switch (speed) {
+ case PCIE_SPEED_2_5GT:
+ /* 8b/10b encoding reduces max throughput by 20% */
+ max_gts = 2 * width;
+ break;
+ case PCIE_SPEED_5_0GT:
+ /* 8b/10b encoding reduces max throughput by 20% */
+ max_gts = 4 * width;
+ break;
+ case PCIE_SPEED_8_0GT:
+ /* 128b/130b encoding has less than 2% impact on throughput */
+ max_gts = 8 * width;
+ break;
+ default:
+ dev_warn(&interface->pdev->dev,
+ "Unable to determine PCI Express bandwidth.\n");
+ return;
+ }
+
+ dev_info(&interface->pdev->dev,
+ "PCI Express bandwidth of %dGT/s available\n",
+ max_gts);
+ dev_info(&interface->pdev->dev,
+ "(Speed:%s, Width: x%d, Encoding Loss:%s, Payload:%s)\n",
+ (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" :
+ speed == PCIE_SPEED_5_0GT ? "5.0GT/s" :
+ speed == PCIE_SPEED_2_5GT ? "2.5GT/s" :
+ "Unknown"),
+ hw->bus.width,
+ (speed == PCIE_SPEED_2_5GT ? "20%" :
+ speed == PCIE_SPEED_5_0GT ? "20%" :
+ speed == PCIE_SPEED_8_0GT ? "<2%" :
+ "Unknown"),
+ (hw->bus.payload == fm10k_bus_payload_128 ? "128B" :
+ hw->bus.payload == fm10k_bus_payload_256 ? "256B" :
+ hw->bus.payload == fm10k_bus_payload_512 ? "512B" :
+ "Unknown"));
- if (hw->mac.ops.is_slot_appropriate(hw))
+ switch (hw->bus_caps.speed) {
+ case fm10k_bus_speed_2500:
+ /* 8b/10b encoding reduces max throughput by 20% */
+ expected_gts = 2 * hw->bus_caps.width;
+ break;
+ case fm10k_bus_speed_5000:
+ /* 8b/10b encoding reduces max throughput by 20% */
+ expected_gts = 4 * hw->bus_caps.width;
+ break;
+ case fm10k_bus_speed_8000:
+ /* 128b/130b encoding has less than 2% impact on throughput */
+ expected_gts = 8 * hw->bus_caps.width;
+ break;
+ default:
+ dev_warn(&interface->pdev->dev,
+ "Unable to determine expected PCI Express bandwidth.\n");
return;
+ }
- dev_warn(dev,
- "For optimal performance, a %s %s slot is recommended.\n",
- (hw->bus_caps.width == fm10k_bus_width_pcie_x1 ? "x1" :
- hw->bus_caps.width == fm10k_bus_width_pcie_x4 ? "x4" :
- "x8"),
- (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s" :
- hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s" :
- "8.0GT/s"));
- dev_warn(dev,
- "A slot with more lanes and/or higher speed is suggested.\n");
+ if (max_gts < expected_gts) {
+ dev_warn(&interface->pdev->dev,
+ "This device requires %dGT/s of bandwidth for optimal performance.\n",
+ expected_gts);
+ dev_warn(&interface->pdev->dev,
+ "A %sslot with x%d lanes is suggested.\n",
+ (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s " :
+ hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s " :
+ hw->bus_caps.speed == fm10k_bus_speed_8000 ? "8.0GT/s " : ""),
+ hw->bus_caps.width);
+ }
}
/**
@@ -1739,7 +1864,6 @@ static int fm10k_probe(struct pci_dev *pdev,
{
struct net_device *netdev;
struct fm10k_intfc *interface;
- struct fm10k_hw *hw;
int err;
err = pci_enable_device_mem(pdev);
@@ -1783,7 +1907,6 @@ static int fm10k_probe(struct pci_dev *pdev,
interface->netdev = netdev;
interface->pdev = pdev;
- hw = &interface->hw;
interface->uc_addr = ioremap(pci_resource_start(pdev, 0),
FM10K_UC_ADDR_SIZE);
@@ -1825,24 +1948,12 @@ static int fm10k_probe(struct pci_dev *pdev,
/* Register PTP interface */
fm10k_ptp_register(interface);
- /* print bus type/speed/width info */
- dev_info(&pdev->dev, "(PCI Express:%s Width: %s Payload: %s)\n",
- (hw->bus.speed == fm10k_bus_speed_8000 ? "8.0GT/s" :
- hw->bus.speed == fm10k_bus_speed_5000 ? "5.0GT/s" :
- hw->bus.speed == fm10k_bus_speed_2500 ? "2.5GT/s" :
- "Unknown"),
- (hw->bus.width == fm10k_bus_width_pcie_x8 ? "x8" :
- hw->bus.width == fm10k_bus_width_pcie_x4 ? "x4" :
- hw->bus.width == fm10k_bus_width_pcie_x1 ? "x1" :
- "Unknown"),
- (hw->bus.payload == fm10k_bus_payload_128 ? "128B" :
- hw->bus.payload == fm10k_bus_payload_256 ? "256B" :
- hw->bus.payload == fm10k_bus_payload_512 ? "512B" :
- "Unknown"));
-
/* print warning for non-optimal configurations */
fm10k_slot_warn(interface);
+ /* report MAC address for logging */
+ dev_info(&pdev->dev, "%pM\n", netdev->dev_addr);
+
/* enable SR-IOV after registering netdev to enforce PF/VF ordering */
fm10k_iov_configure(pdev, 0);
@@ -1983,6 +2094,16 @@ static int fm10k_resume(struct pci_dev *pdev)
if (err)
return err;
+ /* assume host is not ready, to prevent race with watchdog in case we
+ * actually don't have connection to the switch
+ */
+ interface->host_ready = false;
+ fm10k_watchdog_host_not_ready(interface);
+
+ /* clear the service task disable bit to allow service task to start */
+ clear_bit(__FM10K_SERVICE_DISABLE, &interface->state);
+ fm10k_service_event_schedule(interface);
+
/* restore SR-IOV interface */
fm10k_iov_resume(pdev);
@@ -2010,6 +2131,15 @@ static int fm10k_suspend(struct pci_dev *pdev,
fm10k_iov_suspend(pdev);
+ /* the watchdog tasks may read registers, which will appear like a
+ * surprise-remove event once the PCI device is disabled. This will
+ * cause us to close the netdevice, so we don't retain the open/closed
+ * state post-resume. Prevent this by disabling the service task while
+ * suspended, until we actually resume.
+ */
+ set_bit(__FM10K_SERVICE_DISABLE, &interface->state);
+ cancel_work_sync(&interface->service_task);
+
rtnl_lock();
if (netif_running(netdev))
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
index 3ca0233b3ea2..8c0bdc4e4edd 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
@@ -59,6 +59,11 @@ static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw)
if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE))
return FM10K_ERR_DMA_PENDING;
+ /* verify the switch is ready for reset */
+ reg = fm10k_read_reg(hw, FM10K_DMA_CTRL2);
+ if (!(reg & FM10K_DMA_CTRL2_SWITCH_READY))
+ goto out;
+
/* Inititate data path reset */
reg |= FM10K_DMA_CTRL_DATAPATH_RESET;
fm10k_write_reg(hw, FM10K_DMA_CTRL, reg);
@@ -72,6 +77,7 @@ static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw)
if (!(reg & FM10K_IP_NOTINRESET))
err = FM10K_ERR_RESET_FAILED;
+out:
return err;
}
@@ -185,19 +191,6 @@ static s32 fm10k_init_hw_pf(struct fm10k_hw *hw)
}
/**
- * fm10k_is_slot_appropriate_pf - Indicate appropriate slot for this SKU
- * @hw: pointer to hardware structure
- *
- * Looks at the PCIe bus info to confirm whether or not this slot can support
- * the necessary bandwidth for this device.
- **/
-static bool fm10k_is_slot_appropriate_pf(struct fm10k_hw *hw)
-{
- return (hw->bus.speed == hw->bus_caps.speed) &&
- (hw->bus.width == hw->bus_caps.width);
-}
-
-/**
* fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table
* @hw: pointer to hardware structure
* @vid: VLAN ID to add to table
@@ -1162,6 +1155,24 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results,
}
/**
+ * fm10k_iov_select_vid - Select correct default VID
+ * @hw: Pointer to hardware structure
+ * @vid: VID to correct
+ *
+ * Will report an error if VID is out of range. For VID = 0, it will return
+ * either the pf_vid or sw_vid depending on which one is set.
+ */
+static inline s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid)
+{
+ if (!vid)
+ return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid;
+ else if (vf_info->pf_vid && vid != vf_info->pf_vid)
+ return FM10K_ERR_PARAM;
+ else
+ return vid;
+}
+
+/**
* fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF
* @hw: Pointer to hardware structure
* @results: Pointer array to message, results[0] is pointer to message
@@ -1175,9 +1186,10 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info *mbx)
{
struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
- int err = 0;
u8 mac[ETH_ALEN];
u32 *result;
+ int err = 0;
+ bool set;
u16 vlan;
u32 vid;
@@ -1193,19 +1205,21 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
if (err)
return err;
- /* if VLAN ID is 0, set the default VLAN ID instead of 0 */
- if (!vid || (vid == FM10K_VLAN_CLEAR)) {
- if (vf_info->pf_vid)
- vid |= vf_info->pf_vid;
- else
- vid |= vf_info->sw_vid;
- } else if (vid != vf_info->pf_vid) {
+ /* verify upper 16 bits are zero */
+ if (vid >> 16)
return FM10K_ERR_PARAM;
- }
+
+ set = !(vid & FM10K_VLAN_CLEAR);
+ vid &= ~FM10K_VLAN_CLEAR;
+
+ err = fm10k_iov_select_vid(vf_info, vid);
+ if (err < 0)
+ return err;
+ else
+ vid = err;
/* update VSI info for VF in regards to VLAN table */
- err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi,
- !(vid & FM10K_VLAN_CLEAR));
+ err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
}
if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) {
@@ -1221,19 +1235,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
memcmp(mac, vf_info->mac, ETH_ALEN))
return FM10K_ERR_PARAM;
- /* if VLAN ID is 0, set the default VLAN ID instead of 0 */
- if (!vlan || (vlan == FM10K_VLAN_CLEAR)) {
- if (vf_info->pf_vid)
- vlan |= vf_info->pf_vid;
- else
- vlan |= vf_info->sw_vid;
- } else if (vf_info->pf_vid) {
- return FM10K_ERR_PARAM;
- }
+ set = !(vlan & FM10K_VLAN_CLEAR);
+ vlan &= ~FM10K_VLAN_CLEAR;
+
+ err = fm10k_iov_select_vid(vf_info, vlan);
+ if (err < 0)
+ return err;
+ else
+ vlan = err;
/* notify switch of request for new unicast address */
- err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, mac, vlan,
- !(vlan & FM10K_VLAN_CLEAR), 0);
+ err = hw->mac.ops.update_uc_addr(hw, vf_info->glort,
+ mac, vlan, set, 0);
}
if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) {
@@ -1248,19 +1261,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED))
return FM10K_ERR_PARAM;
- /* if VLAN ID is 0, set the default VLAN ID instead of 0 */
- if (!vlan || (vlan == FM10K_VLAN_CLEAR)) {
- if (vf_info->pf_vid)
- vlan |= vf_info->pf_vid;
- else
- vlan |= vf_info->sw_vid;
- } else if (vf_info->pf_vid) {
- return FM10K_ERR_PARAM;
- }
+ set = !(vlan & FM10K_VLAN_CLEAR);
+ vlan &= ~FM10K_VLAN_CLEAR;
+
+ err = fm10k_iov_select_vid(vf_info, vlan);
+ if (err < 0)
+ return err;
+ else
+ vlan = err;
/* notify switch of request for new multicast address */
- err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, vlan,
- !(vlan & FM10K_VLAN_CLEAR));
+ err = hw->mac.ops.update_mc_addr(hw, vf_info->glort,
+ mac, vlan, set);
}
return err;
@@ -1849,7 +1861,6 @@ static struct fm10k_mac_ops mac_ops_pf = {
.init_hw = &fm10k_init_hw_pf,
.start_hw = &fm10k_start_hw_generic,
.stop_hw = &fm10k_stop_hw_generic,
- .is_slot_appropriate = &fm10k_is_slot_appropriate_pf,
.update_vlan = &fm10k_update_vlan_pf,
.read_mac_addr = &fm10k_read_mac_addr_pf,
.update_uc_addr = &fm10k_update_uc_addr_pf,
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
index 2a17d82fa37d..318a212f0a78 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
@@ -521,7 +521,6 @@ struct fm10k_mac_ops {
s32 (*stop_hw)(struct fm10k_hw *);
s32 (*get_bus_info)(struct fm10k_hw *);
s32 (*get_host_state)(struct fm10k_hw *, bool *);
- bool (*is_slot_appropriate)(struct fm10k_hw *);
s32 (*update_vlan)(struct fm10k_hw *, u32, u8, bool);
s32 (*read_mac_addr)(struct fm10k_hw *);
s32 (*update_uc_addr)(struct fm10k_hw *, u16, const u8 *,
@@ -763,6 +762,12 @@ enum fm10k_rxdesc_xc {
#define FM10K_RXD_STATUS_L4E 0x4000 /* L4 csum error */
#define FM10K_RXD_STATUS_IPE 0x8000 /* IPv4 csum error */
+#define FM10K_RXD_ERR_SWITCH_ERROR 0x0001 /* Switch found bad packet */
+#define FM10K_RXD_ERR_NO_DESCRIPTOR 0x0002 /* No descriptor available */
+#define FM10K_RXD_ERR_PP_ERROR 0x0004 /* RAM error during processing */
+#define FM10K_RXD_ERR_SWITCH_READY 0x0008 /* Link transition mid-packet */
+#define FM10K_RXD_ERR_TOO_BIG 0x0010 /* Pkt too big for single buf */
+
struct fm10k_ftag {
__be16 swpri_type_user;
__be16 vlan;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
index 94f0f6a146d9..36c8b0aa08fd 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
@@ -131,19 +131,6 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw)
return 0;
}
-/**
- * fm10k_is_slot_appropriate_vf - Indicate appropriate slot for this SKU
- * @hw: pointer to hardware structure
- *
- * Looks at the PCIe bus info to confirm whether or not this slot can support
- * the necessary bandwidth for this device. Since the VF has no control over
- * the "slot" it is in, always indicate that the slot is appropriate.
- **/
-static bool fm10k_is_slot_appropriate_vf(struct fm10k_hw *hw)
-{
- return true;
-}
-
/* This structure defines the attibutes to be parsed below */
const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[] = {
FM10K_TLV_ATTR_U32(FM10K_MAC_VLAN_MSG_VLAN),
@@ -552,7 +539,6 @@ static struct fm10k_mac_ops mac_ops_vf = {
.init_hw = &fm10k_init_hw_vf,
.start_hw = &fm10k_start_hw_generic,
.stop_hw = &fm10k_stop_hw_vf,
- .is_slot_appropriate = &fm10k_is_slot_appropriate_vf,
.update_vlan = &fm10k_update_vlan_vf,
.read_mac_addr = &fm10k_read_mac_addr_vf,
.update_uc_addr = &fm10k_update_uc_addr_vf,
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index e7462793d48d..4dd3e26129b4 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -71,7 +71,6 @@
#define I40E_MAX_VEB 16
#define I40E_MAX_NUM_DESCRIPTORS 4096
-#define I40E_MAX_REGISTER 0x800000
#define I40E_MAX_CSR_SPACE (4 * 1024 * 1024 - 64 * 1024)
#define I40E_DEFAULT_NUM_DESCRIPTORS 512
#define I40E_REQ_DESCRIPTOR_MULTIPLE 32
@@ -94,19 +93,26 @@
#endif /* I40E_FCOE */
#define I40E_MAX_AQ_BUF_SIZE 4096
#define I40E_AQ_LEN 256
-#define I40E_AQ_WORK_LIMIT 32
+#define I40E_AQ_WORK_LIMIT 66 /* max number of VFs + a little */
#define I40E_MAX_USER_PRIORITY 8
#define I40E_DEFAULT_MSG_ENABLE 4
#define I40E_QUEUE_WAIT_RETRY_LIMIT 10
-#define I40E_INT_NAME_STR_LEN (IFNAMSIZ + 9)
+#define I40E_INT_NAME_STR_LEN (IFNAMSIZ + 16)
/* Ethtool Private Flags */
#define I40E_PRIV_FLAGS_NPAR_FLAG BIT(0)
+#define I40E_PRIV_FLAGS_LINKPOLL_FLAG BIT(1)
+#define I40E_PRIV_FLAGS_FD_ATR BIT(2)
+#define I40E_PRIV_FLAGS_VEB_STATS BIT(3)
#define I40E_NVM_VERSION_LO_SHIFT 0
#define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT)
#define I40E_NVM_VERSION_HI_SHIFT 12
#define I40E_NVM_VERSION_HI_MASK (0xf << I40E_NVM_VERSION_HI_SHIFT)
+#define I40E_OEM_VER_BUILD_MASK 0xffff
+#define I40E_OEM_VER_PATCH_MASK 0xff
+#define I40E_OEM_VER_BUILD_SHIFT 8
+#define I40E_OEM_VER_SHIFT 24
/* The values in here are decimal coded as hex as is the case in the NVM map*/
#define I40E_CURRENT_NVM_VERSION_HI 0x2
@@ -243,7 +249,6 @@ struct i40e_pf {
struct pci_dev *pdev;
struct i40e_hw hw;
unsigned long state;
- unsigned long link_check_timeout;
struct msix_entry *msix_entries;
bool fc_autoneg_status;
@@ -305,7 +310,6 @@ struct i40e_pf {
#ifdef I40E_FCOE
#define I40E_FLAG_FCOE_ENABLED BIT_ULL(11)
#endif /* I40E_FCOE */
-#define I40E_FLAG_IN_NETPOLL BIT_ULL(12)
#define I40E_FLAG_16BYTE_RX_DESC_ENABLED BIT_ULL(13)
#define I40E_FLAG_CLEAN_ADMINQ BIT_ULL(14)
#define I40E_FLAG_FILTER_SYNC BIT_ULL(15)
@@ -327,8 +331,11 @@ struct i40e_pf {
#define I40E_FLAG_OUTER_UDP_CSUM_CAPABLE BIT_ULL(33)
#define I40E_FLAG_128_QP_RSS_CAPABLE BIT_ULL(34)
#define I40E_FLAG_WB_ON_ITR_CAPABLE BIT_ULL(35)
+#define I40E_FLAG_VEB_STATS_ENABLED BIT_ULL(37)
#define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE BIT_ULL(38)
+#define I40E_FLAG_LINK_POLLING_ENABLED BIT_ULL(39)
#define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40)
+#define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42)
/* tracks features that get auto disabled by errors */
u64 auto_disable_flags;
@@ -409,6 +416,9 @@ struct i40e_pf {
/* These are only valid in NPAR modes */
u32 npar_max_bw;
u32 npar_min_bw;
+
+ u32 ioremap_len;
+ u32 fd_inv;
};
struct i40e_mac_filter {
@@ -460,6 +470,8 @@ struct i40e_vsi {
#define I40E_VSI_FLAG_VEB_OWNER BIT(1)
unsigned long flags;
+ /* Per VSI lock to protect elements/list (MAC filter) */
+ spinlock_t mac_filter_list_lock;
struct list_head mac_filter_list;
/* VSI stats */
@@ -474,6 +486,7 @@ struct i40e_vsi {
#endif
u32 tx_restart;
u32 tx_busy;
+ u64 tx_linearize;
u32 rx_buf_failed;
u32 rx_page_failed;
@@ -489,6 +502,7 @@ struct i40e_vsi {
*/
u16 rx_itr_setting;
u16 tx_itr_setting;
+ u16 int_rate_limit; /* value in usecs */
u16 rss_table_size;
u16 rss_size;
@@ -534,6 +548,7 @@ struct i40e_vsi {
u16 idx; /* index in pf->vsi[] */
u16 veb_idx; /* index of VEB parent */
struct kobject *kobj; /* sysfs object */
+ bool current_isup; /* Sync 'link up' logging */
/* VSI specific handlers */
irqreturn_t (*irq_handler)(int irq, void *data);
@@ -564,6 +579,8 @@ struct i40e_q_vector {
struct rcu_head rcu; /* to avoid race with update stats on free */
char name[I40E_INT_NAME_STR_LEN];
bool arm_wb_state;
+#define ITR_COUNTDOWN_START 100
+ u8 itr_countdown; /* when 0 should adjust ITR */
} ____cacheline_internodealigned_in_smp;
/* lan device */
@@ -573,22 +590,29 @@ struct i40e_device {
};
/**
- * i40e_fw_version_str - format the FW and NVM version strings
+ * i40e_nvm_version_str - format the NVM version strings
* @hw: ptr to the hardware info
**/
-static inline char *i40e_fw_version_str(struct i40e_hw *hw)
+static inline char *i40e_nvm_version_str(struct i40e_hw *hw)
{
static char buf[32];
+ u32 full_ver;
+ u8 ver, patch;
+ u16 build;
+
+ full_ver = hw->nvm.oem_ver;
+ ver = (u8)(full_ver >> I40E_OEM_VER_SHIFT);
+ build = (u16)((full_ver >> I40E_OEM_VER_BUILD_SHIFT)
+ & I40E_OEM_VER_BUILD_MASK);
+ patch = (u8)(full_ver & I40E_OEM_VER_PATCH_MASK);
snprintf(buf, sizeof(buf),
- "f%d.%d.%05d a%d.%d n%x.%02x e%x",
- hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build,
- hw->aq.api_maj_ver, hw->aq.api_min_ver,
+ "%x.%02x 0x%x %d.%d.%d",
(hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >>
I40E_NVM_VERSION_HI_SHIFT,
(hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >>
I40E_NVM_VERSION_LO_SHIFT,
- (hw->nvm.eetrack & 0xffffff));
+ hw->nvm.eetrack, ver, build, patch);
return buf;
}
@@ -667,7 +691,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
bool is_vf, bool is_netdev);
void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan,
bool is_vf, bool is_netdev);
-int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
+int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl);
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
u16 uplink, u32 param1);
int i40e_vsi_release(struct i40e_vsi *vsi);
@@ -700,7 +724,24 @@ static inline void i40e_dbg_pf_exit(struct i40e_pf *pf) {}
static inline void i40e_dbg_init(void) {}
static inline void i40e_dbg_exit(void) {}
#endif /* CONFIG_DEBUG_FS*/
-void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector);
+/**
+ * i40e_irq_dynamic_enable - Enable default interrupt generation settings
+ * @vsi: pointer to a vsi
+ * @vector: enable a particular Hw Interrupt vector, without base_vector
+ **/
+static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
+{
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ u32 val;
+
+ val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
+ I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+ (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
+ wr32(hw, I40E_PFINT_DYN_CTLN(vector + vsi->base_vector - 1), val);
+ /* skip the flush */
+}
+
void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector);
void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
@@ -739,7 +780,7 @@ int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt);
u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf);
void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi);
void i40e_fcoe_vsi_setup(struct i40e_pf *pf);
-int i40e_init_pf_fcoe(struct i40e_pf *pf);
+void i40e_init_pf_fcoe(struct i40e_pf *pf);
int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi);
void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi);
int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
@@ -771,4 +812,5 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi);
i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf);
i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf);
i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf);
+void i40e_print_link_message(struct i40e_vsi *vsi, bool isup);
#endif /* _I40E_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 62488a67149d..0ff8f01e57ee 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -386,7 +386,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
hw->aq.asq.next_to_use = 0;
hw->aq.asq.next_to_clean = 0;
- hw->aq.asq.count = hw->aq.num_asq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -404,6 +403,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
goto init_adminq_free_rings;
/* success! */
+ hw->aq.asq.count = hw->aq.num_asq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
@@ -445,7 +445,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
hw->aq.arq.next_to_use = 0;
hw->aq.arq.next_to_clean = 0;
- hw->aq.arq.count = hw->aq.num_arq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -463,6 +462,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
goto init_adminq_free_rings;
/* success! */
+ hw->aq.arq.count = hw->aq.num_arq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
@@ -482,8 +482,12 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
{
i40e_status ret_code = 0;
- if (hw->aq.asq.count == 0)
- return I40E_ERR_NOT_READY;
+ mutex_lock(&hw->aq.asq_mutex);
+
+ if (hw->aq.asq.count == 0) {
+ ret_code = I40E_ERR_NOT_READY;
+ goto shutdown_asq_out;
+ }
/* Stop firmware AdminQ processing */
wr32(hw, hw->aq.asq.head, 0);
@@ -492,16 +496,13 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
wr32(hw, hw->aq.asq.bal, 0);
wr32(hw, hw->aq.asq.bah, 0);
- /* make sure lock is available */
- mutex_lock(&hw->aq.asq_mutex);
-
hw->aq.asq.count = 0; /* to indicate uninitialized queue */
/* free ring buffers */
i40e_free_asq_bufs(hw);
+shutdown_asq_out:
mutex_unlock(&hw->aq.asq_mutex);
-
return ret_code;
}
@@ -515,8 +516,12 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
{
i40e_status ret_code = 0;
- if (hw->aq.arq.count == 0)
- return I40E_ERR_NOT_READY;
+ mutex_lock(&hw->aq.arq_mutex);
+
+ if (hw->aq.arq.count == 0) {
+ ret_code = I40E_ERR_NOT_READY;
+ goto shutdown_arq_out;
+ }
/* Stop firmware AdminQ processing */
wr32(hw, hw->aq.arq.head, 0);
@@ -525,16 +530,13 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
wr32(hw, hw->aq.arq.bal, 0);
wr32(hw, hw->aq.arq.bah, 0);
- /* make sure lock is available */
- mutex_lock(&hw->aq.arq_mutex);
-
hw->aq.arq.count = 0; /* to indicate uninitialized queue */
/* free ring buffers */
i40e_free_arq_bufs(hw);
+shutdown_arq_out:
mutex_unlock(&hw->aq.arq_mutex);
-
return ret_code;
}
@@ -551,8 +553,9 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
**/
i40e_status i40e_init_adminq(struct i40e_hw *hw)
{
- i40e_status ret_code;
+ u16 cfg_ptr, oem_hi, oem_lo;
u16 eetrack_lo, eetrack_hi;
+ i40e_status ret_code;
int retry = 0;
/* verify input for valid configuration */
@@ -611,6 +614,12 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_LO, &eetrack_lo);
i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_HI, &eetrack_hi);
hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo;
+ i40e_read_nvm_word(hw, I40E_SR_BOOT_CONFIG_PTR, &cfg_ptr);
+ i40e_read_nvm_word(hw, (cfg_ptr + I40E_NVM_OEM_VER_OFF),
+ &oem_hi);
+ i40e_read_nvm_word(hw, (cfg_ptr + (I40E_NVM_OEM_VER_OFF + 1)),
+ &oem_lo);
+ hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
ret_code = I40E_ERR_FIRMWARE_API_VERSION;
@@ -657,6 +666,9 @@ i40e_status i40e_shutdown_adminq(struct i40e_hw *hw)
/* destroy the locks */
+ if (hw->nvm_buff.va)
+ i40e_free_virt_mem(hw, &hw->nvm_buff);
+
return ret_code;
}
@@ -678,8 +690,7 @@ static u16 i40e_clean_asq(struct i40e_hw *hw)
details = I40E_ADMINQ_DETAILS(*asq, ntc);
while (rd32(hw, hw->aq.asq.head) != ntc) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "%s: ntc %d head %d.\n", __func__, ntc,
- rd32(hw, hw->aq.asq.head));
+ "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head));
if (details->callback) {
I40E_ADMINQ_CALLBACK cb_func =
@@ -742,19 +753,23 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
u16 retval = 0;
u32 val = 0;
- val = rd32(hw, hw->aq.asq.head);
- if (val >= hw->aq.num_asq_entries) {
+ mutex_lock(&hw->aq.asq_mutex);
+
+ if (hw->aq.asq.count == 0) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: head overrun at %d\n", val);
+ "AQTX: Admin queue not initialized.\n");
status = I40E_ERR_QUEUE_EMPTY;
- goto asq_send_command_exit;
+ goto asq_send_command_error;
}
- if (hw->aq.asq.count == 0) {
+ hw->aq.asq_last_status = I40E_AQ_RC_OK;
+
+ val = rd32(hw, hw->aq.asq.head);
+ if (val >= hw->aq.num_asq_entries) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Admin queue not initialized.\n");
+ "AQTX: head overrun at %d\n", val);
status = I40E_ERR_QUEUE_EMPTY;
- goto asq_send_command_exit;
+ goto asq_send_command_error;
}
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
@@ -779,8 +794,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
desc->flags &= ~cpu_to_le16(details->flags_dis);
desc->flags |= cpu_to_le16(details->flags_ena);
- mutex_lock(&hw->aq.asq_mutex);
-
if (buff_size > hw->aq.asq_buf_size) {
i40e_debug(hw,
I40E_DEBUG_AQ_MESSAGE,
@@ -889,6 +902,10 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
"AQTX: desc and buffer writeback:\n");
i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size);
+ /* save writeback aq if requested */
+ if (details->wb_desc)
+ *details->wb_desc = *desc_on_ring;
+
/* update the error if time out occurred */
if ((!cmd_completed) &&
(!details->async && !details->postpone)) {
@@ -900,7 +917,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
asq_send_command_error:
mutex_unlock(&hw->aq.asq_mutex);
-asq_send_command_exit:
return status;
}
@@ -1023,6 +1039,19 @@ clean_arq_element_err:
i40e_release_nvm(hw);
hw->aq.nvm_release_on_done = false;
}
+
+ switch (hw->nvmupd_state) {
+ case I40E_NVMUPD_STATE_INIT_WAIT:
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ break;
+
+ case I40E_NVMUPD_STATE_WRITE_WAIT:
+ hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
+ break;
+
+ default:
+ break;
+ }
}
return ret_code;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
index 28e519a50de4..12fbbddea299 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
@@ -69,6 +69,7 @@ struct i40e_asq_cmd_details {
u16 flags_dis;
bool async;
bool postpone;
+ struct i40e_aq_desc *wb_desc;
};
#define I40E_ADMINQ_DETAILS(R, i) \
@@ -108,9 +109,10 @@ struct i40e_adminq_info {
/**
* i40e_aq_rc_to_posix - convert errors to user-land codes
- * aq_rc: AdminQ error code to convert
+ * aq_ret: AdminQ handler error code can override aq_rc
+ * aq_rc: AdminQ firmware error code to convert
**/
-static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc)
+static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
{
int aq_to_posix[] = {
0, /* I40E_AQ_RC_OK */
@@ -142,8 +144,9 @@ static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc)
if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
return -EAGAIN;
- if (aq_rc >= ARRAY_SIZE(aq_to_posix))
+ if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
return -ERANGE;
+
return aq_to_posix[aq_rc];
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index 95d23bfbcbf1..6584b6cd73fd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -1722,11 +1722,13 @@ struct i40e_aqc_get_link_status {
u8 phy_type; /* i40e_aq_phy_type */
u8 link_speed; /* i40e_aq_link_speed */
u8 link_info;
-#define I40E_AQ_LINK_UP 0x01
+#define I40E_AQ_LINK_UP 0x01 /* obsolete */
+#define I40E_AQ_LINK_UP_FUNCTION 0x01
#define I40E_AQ_LINK_FAULT 0x02
#define I40E_AQ_LINK_FAULT_TX 0x04
#define I40E_AQ_LINK_FAULT_RX 0x08
#define I40E_AQ_LINK_FAULT_REMOTE 0x10
+#define I40E_AQ_LINK_UP_PORT 0x20
#define I40E_AQ_MEDIA_AVAILABLE 0x40
#define I40E_AQ_SIGNAL_DETECT 0x80
u8 an_info;
@@ -2062,6 +2064,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start);
#define I40E_AQC_CEE_APP_ISCSI_MASK (0x7 << I40E_AQC_CEE_APP_ISCSI_SHIFT)
#define I40E_AQC_CEE_APP_FIP_SHIFT 0x8
#define I40E_AQC_CEE_APP_FIP_MASK (0x7 << I40E_AQC_CEE_APP_FIP_SHIFT)
+
#define I40E_AQC_CEE_PG_STATUS_SHIFT 0x0
#define I40E_AQC_CEE_PG_STATUS_MASK (0x7 << I40E_AQC_CEE_PG_STATUS_SHIFT)
#define I40E_AQC_CEE_PFC_STATUS_SHIFT 0x3
@@ -2070,10 +2073,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start);
#define I40E_AQC_CEE_APP_STATUS_MASK (0x7 << I40E_AQC_CEE_APP_STATUS_SHIFT)
#define I40E_AQC_CEE_FCOE_STATUS_SHIFT 0x8
#define I40E_AQC_CEE_FCOE_STATUS_MASK (0x7 << I40E_AQC_CEE_FCOE_STATUS_SHIFT)
-#define I40E_AQC_CEE_ISCSI_STATUS_SHIFT 0xA
+#define I40E_AQC_CEE_ISCSI_STATUS_SHIFT 0xB
#define I40E_AQC_CEE_ISCSI_STATUS_MASK (0x7 << I40E_AQC_CEE_ISCSI_STATUS_SHIFT)
#define I40E_AQC_CEE_FIP_STATUS_SHIFT 0x10
#define I40E_AQC_CEE_FIP_STATUS_MASK (0x7 << I40E_AQC_CEE_FIP_STATUS_SHIFT)
+
+/* struct i40e_aqc_get_cee_dcb_cfg_v1_resp was originally defined with
+ * word boundary layout issues, which the Linux compilers silently deal
+ * with by adding padding, making the actual struct larger than designed.
+ * However, the FW compiler for the NIC is less lenient and complains
+ * about the struct. Hence, the struct defined here has an extra byte in
+ * fields reserved3 and reserved4 to directly acknowledge that padding,
+ * and the new length is used in the length check macro.
+ */
struct i40e_aqc_get_cee_dcb_cfg_v1_resp {
u8 reserved1;
u8 oper_num_tc;
@@ -2081,9 +2093,9 @@ struct i40e_aqc_get_cee_dcb_cfg_v1_resp {
u8 reserved2;
u8 oper_tc_bw[8];
u8 oper_pfc_en;
- u8 reserved3;
+ u8 reserved3[2];
__le16 oper_app_prio;
- u8 reserved4;
+ u8 reserved4[2];
__le16 tlv_status;
};
@@ -2120,6 +2132,13 @@ I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_get_cee_dcb_cfg_resp);
struct i40e_aqc_lldp_set_local_mib {
#define SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT 0
#define SET_LOCAL_MIB_AC_TYPE_DCBX_MASK (1 << SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT)
+#define SET_LOCAL_MIB_AC_TYPE_DCBX_MASK (1 << \
+ SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT)
+#define SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB 0x0
+#define SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT (1)
+#define SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_MASK (1 << \
+ SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT)
+#define SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS 0x1
u8 type;
u8 reserved0;
__le16 length;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 114dc6450183..2d74c6e4d7b6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -51,7 +51,9 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_QSFP_B:
case I40E_DEV_ID_QSFP_C:
case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_20G_KR2:
+ case I40E_DEV_ID_20G_KR2_A:
hw->mac.type = I40E_MAC_XL710;
break;
case I40E_DEV_ID_SFP_X722:
@@ -85,7 +87,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
* @hw: pointer to the HW structure
* @aq_err: the AQ error code to convert
**/
-char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
+const char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
{
switch (aq_err) {
case I40E_AQ_RC_OK:
@@ -145,7 +147,7 @@ char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
* @hw: pointer to the HW structure
* @stat_err: the status error code to convert
**/
-char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err)
+const char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err)
{
switch (stat_err) {
case 0:
@@ -329,25 +331,11 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
len = buf_len;
/* write the full 16-byte chunks */
for (i = 0; i < (len - 16); i += 16)
- i40e_debug(hw, mask,
- "\t0x%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
- i, buf[i], buf[i + 1], buf[i + 2],
- buf[i + 3], buf[i + 4], buf[i + 5],
- buf[i + 6], buf[i + 7], buf[i + 8],
- buf[i + 9], buf[i + 10], buf[i + 11],
- buf[i + 12], buf[i + 13], buf[i + 14],
- buf[i + 15]);
+ i40e_debug(hw, mask, "\t0x%04X %16ph\n", i, buf + i);
/* write whatever's left over without overrunning the buffer */
- if (i < len) {
- char d_buf[80];
- int j = 0;
-
- memset(d_buf, 0, sizeof(d_buf));
- j += sprintf(d_buf, "\t0x%04X ", i);
- while (i < len)
- j += sprintf(&d_buf[j], " %02X", buf[i++]);
- i40e_debug(hw, mask, "%s\n", d_buf);
- }
+ if (i < len)
+ i40e_debug(hw, mask, "\t0x%04X %*ph\n",
+ i, len - i, buf + i);
}
}
@@ -441,9 +429,6 @@ static i40e_status i40e_aq_get_set_rss_lut(struct i40e_hw *hw,
I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
- cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)lut));
- cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)lut));
-
status = i40e_asq_send_command(hw, &desc, lut, lut_size, NULL);
return status;
@@ -518,8 +503,6 @@ static i40e_status i40e_aq_get_set_rss_key(struct i40e_hw *hw,
I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) &
I40E_AQC_SET_RSS_KEY_VSI_ID_MASK));
cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID);
- cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)key));
- cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)key));
status = i40e_asq_send_command(hw, &desc, key, key_size, NULL);
@@ -961,6 +944,9 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)
else
hw->pf_id = (u8)(func_rid & 0x7);
+ if (hw->mac.type == I40E_MAC_X722)
+ hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE;
+
status = i40e_init_nvm(hw);
return status;
}
@@ -1038,7 +1024,7 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL);
if (flags & I40E_AQC_LAN_ADDR_VALID)
- memcpy(mac_addr, &addrs.pf_lan_mac, sizeof(addrs.pf_lan_mac));
+ ether_addr_copy(mac_addr, addrs.pf_lan_mac);
return status;
}
@@ -1061,7 +1047,7 @@ i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
return status;
if (flags & I40E_AQC_PORT_ADDR_VALID)
- memcpy(mac_addr, &addrs.port_mac, sizeof(addrs.port_mac));
+ ether_addr_copy(mac_addr, addrs.port_mac);
else
status = I40E_ERR_INVALID_MAC_ADDR;
@@ -1119,7 +1105,7 @@ i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
return status;
if (flags & I40E_AQC_SAN_ADDR_VALID)
- memcpy(mac_addr, &addrs.pf_san_mac, sizeof(addrs.pf_san_mac));
+ ether_addr_copy(mac_addr, addrs.pf_san_mac);
else
status = I40E_ERR_INVALID_MAC_ADDR;
@@ -1260,7 +1246,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
grst_del = (rd32(hw, I40E_GLGEN_RSTCTL) &
I40E_GLGEN_RSTCTL_GRSTDEL_MASK) >>
I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT;
- for (cnt = 0; cnt < grst_del + 2; cnt++) {
+ for (cnt = 0; cnt < grst_del + 10; cnt++) {
reg = rd32(hw, I40E_GLGEN_RSTAT);
if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK))
break;
@@ -1620,6 +1606,9 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)
status = I40E_ERR_UNKNOWN_PHY;
+ if (report_init)
+ hw->phy.phy_types = le32_to_cpu(abilities->phy_type);
+
return status;
}
@@ -1720,14 +1709,14 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
*aq_failures |= I40E_SET_FC_AQ_FAIL_SET;
}
/* Update the link info */
- status = i40e_aq_get_link_info(hw, true, NULL, NULL);
+ status = i40e_update_link_info(hw);
if (status) {
/* Wait a little bit (on 40G cards it sometimes takes a really
* long time for link to come back from the atomic reset)
* and try once more
*/
msleep(1000);
- status = i40e_aq_get_link_info(hw, true, NULL, NULL);
+ status = i40e_update_link_info(hw);
}
if (status)
*aq_failures |= I40E_SET_FC_AQ_FAIL_UPDATE;
@@ -2238,27 +2227,54 @@ i40e_status i40e_aq_send_driver_version(struct i40e_hw *hw,
/**
* i40e_get_link_status - get status of the HW network link
* @hw: pointer to the hw struct
+ * @link_up: pointer to bool (true/false = linkup/linkdown)
*
- * Returns true if link is up, false if link is down.
+ * Variable link_up true if link is up, false if link is down.
+ * The variable link_up is invalid if returned value of status != 0
*
* Side effect: LinkStatusEvent reporting becomes enabled
**/
-bool i40e_get_link_status(struct i40e_hw *hw)
+i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up)
{
i40e_status status = 0;
- bool link_status = false;
if (hw->phy.get_link_info) {
- status = i40e_aq_get_link_info(hw, true, NULL, NULL);
+ status = i40e_update_link_info(hw);
if (status)
- goto i40e_get_link_status_exit;
+ i40e_debug(hw, I40E_DEBUG_LINK, "get link failed: status %d\n",
+ status);
}
- link_status = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
+ *link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
+
+ return status;
+}
+
+/**
+ * i40e_updatelink_status - update status of the HW network link
+ * @hw: pointer to the hw struct
+ **/
+i40e_status i40e_update_link_info(struct i40e_hw *hw)
+{
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ i40e_status status = 0;
+
+ status = i40e_aq_get_link_info(hw, true, NULL, NULL);
+ if (status)
+ return status;
+
+ if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) {
+ status = i40e_aq_get_phy_capabilities(hw, false, false,
+ &abilities, NULL);
+ if (status)
+ return status;
-i40e_get_link_status_exit:
- return link_status;
+ memcpy(hw->phy.link_info.module_type, &abilities.module_type,
+ sizeof(hw->phy.link_info.module_type));
+ }
+
+ return status;
}
/**
@@ -2365,6 +2381,7 @@ i40e_status i40e_aq_get_veb_parameters(struct i40e_hw *hw,
*vebs_free = le16_to_cpu(cmd_resp->vebs_free);
if (floating) {
u16 flags = le16_to_cpu(cmd_resp->veb_flags);
+
if (flags & I40E_AQC_ADD_VEB_FLOATING)
*floating = true;
else
@@ -3779,7 +3796,7 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
}
if (mac_addr)
- memcpy(cmd->mac, mac_addr, ETH_ALEN);
+ ether_addr_copy(cmd->mac, mac_addr);
cmd->etype = cpu_to_le16(ethtype);
cmd->flags = cpu_to_le16(flags);
@@ -3798,6 +3815,28 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
}
/**
+ * i40e_add_filter_to_drop_tx_flow_control_frames- filter to drop flow control
+ * @hw: pointer to the hw struct
+ * @seid: VSI seid to add ethertype filter from
+ **/
+#define I40E_FLOW_CONTROL_ETHTYPE 0x8808
+void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
+ u16 seid)
+{
+ u16 flag = I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC |
+ I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP |
+ I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX;
+ u16 ethtype = I40E_FLOW_CONTROL_ETHTYPE;
+ i40e_status status;
+
+ status = i40e_aq_add_rem_control_packet_filter(hw, NULL, ethtype, flag,
+ seid, 0, true, NULL,
+ NULL);
+ if (status)
+ hw_dbg(hw, "Ethtype Filter Add failed: Error pruning Tx flow control frames\n");
+}
+
+/**
* i40e_aq_alternate_read
* @hw: pointer to the hardware structure
* @reg_addr0: address of first dword to be read
diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c
index 90de46aef557..2691277c0055 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c
@@ -292,6 +292,190 @@ static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
}
/**
+ * i40e_parse_cee_pgcfg_tlv
+ * @tlv: CEE DCBX PG CFG TLV
+ * @dcbcfg: Local store to update ETS CFG data
+ *
+ * Parses CEE DCBX PG CFG TLV
+ **/
+static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
+ struct i40e_dcbx_config *dcbcfg)
+{
+ struct i40e_dcb_ets_config *etscfg;
+ u8 *buf = tlv->tlvinfo;
+ u16 offset = 0;
+ u8 priority;
+ int i;
+
+ etscfg = &dcbcfg->etscfg;
+
+ if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
+ etscfg->willing = 1;
+
+ etscfg->cbs = 0;
+ /* Priority Group Table (4 octets)
+ * Octets:| 1 | 2 | 3 | 4 |
+ * -----------------------------------------
+ * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
+ * -----------------------------------------
+ * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
+ * -----------------------------------------
+ */
+ for (i = 0; i < 4; i++) {
+ priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
+ I40E_CEE_PGID_PRIO_1_SHIFT);
+ etscfg->prioritytable[i * 2] = priority;
+ priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
+ I40E_CEE_PGID_PRIO_0_SHIFT);
+ etscfg->prioritytable[i * 2 + 1] = priority;
+ offset++;
+ }
+
+ /* PG Percentage Table (8 octets)
+ * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+ * ---------------------------------
+ * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
+ * ---------------------------------
+ */
+ for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
+ etscfg->tcbwtable[i] = buf[offset++];
+
+ /* Number of TCs supported (1 octet) */
+ etscfg->maxtcs = buf[offset];
+}
+
+/**
+ * i40e_parse_cee_pfccfg_tlv
+ * @tlv: CEE DCBX PFC CFG TLV
+ * @dcbcfg: Local store to update PFC CFG data
+ *
+ * Parses CEE DCBX PFC CFG TLV
+ **/
+static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
+ struct i40e_dcbx_config *dcbcfg)
+{
+ u8 *buf = tlv->tlvinfo;
+
+ if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
+ dcbcfg->pfc.willing = 1;
+
+ /* ------------------------
+ * | PFC Enable | PFC TCs |
+ * ------------------------
+ * | 1 octet | 1 octet |
+ */
+ dcbcfg->pfc.pfcenable = buf[0];
+ dcbcfg->pfc.pfccap = buf[1];
+}
+
+/**
+ * i40e_parse_cee_app_tlv
+ * @tlv: CEE DCBX APP TLV
+ * @dcbcfg: Local store to update APP PRIO data
+ *
+ * Parses CEE DCBX APP PRIO TLV
+ **/
+static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
+ struct i40e_dcbx_config *dcbcfg)
+{
+ u16 length, typelength, offset = 0;
+ struct i40e_cee_app_prio *app;
+ u8 i, up, selector;
+
+ typelength = ntohs(tlv->hdr.typelen);
+ length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
+ I40E_LLDP_TLV_LEN_SHIFT);
+
+ dcbcfg->numapps = length / sizeof(*app);
+ if (!dcbcfg->numapps)
+ return;
+
+ for (i = 0; i < dcbcfg->numapps; i++) {
+ app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
+ for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
+ if (app->prio_map & BIT(up))
+ break;
+ }
+ dcbcfg->app[i].priority = up;
+
+ /* Get Selector from lower 2 bits, and convert to IEEE */
+ selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
+ if (selector == I40E_CEE_APP_SEL_ETHTYPE)
+ dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
+ else if (selector == I40E_CEE_APP_SEL_TCPIP)
+ dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
+ else
+ /* Keep selector as it is for unknown types */
+ dcbcfg->app[i].selector = selector;
+
+ dcbcfg->app[i].protocolid = ntohs(app->protocol);
+ /* Move to next app */
+ offset += sizeof(*app);
+ }
+}
+
+/**
+ * i40e_parse_cee_tlv
+ * @tlv: CEE DCBX TLV
+ * @dcbcfg: Local store to update DCBX config data
+ *
+ * Get the TLV subtype and send it to parsing function
+ * based on the subtype value
+ **/
+static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
+ struct i40e_dcbx_config *dcbcfg)
+{
+ u16 len, tlvlen, sublen, typelength;
+ struct i40e_cee_feat_tlv *sub_tlv;
+ u8 subtype, feat_tlv_count = 0;
+ u32 ouisubtype;
+
+ ouisubtype = ntohl(tlv->ouisubtype);
+ subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
+ I40E_LLDP_TLV_SUBTYPE_SHIFT);
+ /* Return if not CEE DCBX */
+ if (subtype != I40E_CEE_DCBX_TYPE)
+ return;
+
+ typelength = ntohs(tlv->typelength);
+ tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
+ I40E_LLDP_TLV_LEN_SHIFT);
+ len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
+ sizeof(struct i40e_cee_ctrl_tlv);
+ /* Return if no CEE DCBX Feature TLVs */
+ if (tlvlen <= len)
+ return;
+
+ sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
+ while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
+ typelength = ntohs(sub_tlv->hdr.typelen);
+ sublen = (u16)((typelength &
+ I40E_LLDP_TLV_LEN_MASK) >>
+ I40E_LLDP_TLV_LEN_SHIFT);
+ subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
+ I40E_LLDP_TLV_TYPE_SHIFT);
+ switch (subtype) {
+ case I40E_CEE_SUBTYPE_PG_CFG:
+ i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
+ break;
+ case I40E_CEE_SUBTYPE_PFC_CFG:
+ i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
+ break;
+ case I40E_CEE_SUBTYPE_APP_PRI:
+ i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
+ break;
+ default:
+ return; /* Invalid Sub-type return */
+ }
+ feat_tlv_count++;
+ /* Move to next sub TLV */
+ sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
+ sizeof(sub_tlv->hdr.typelen) +
+ sublen);
+ }
+}
+
+/**
* i40e_parse_org_tlv
* @tlv: Organization specific TLV
* @dcbcfg: Local store to update ETS REC data
@@ -312,6 +496,9 @@ static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
case I40E_IEEE_8021QAZ_OUI:
i40e_parse_ieee_tlv(tlv, dcbcfg);
break;
+ case I40E_CEE_DCBX_OUI:
+ i40e_parse_cee_tlv(tlv, dcbcfg);
+ break;
default:
break;
}
@@ -502,15 +689,18 @@ static void i40e_cee_to_dcb_config(
/* CEE PG data to ETS config */
dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
+ /* Note that the FW creates the oper_prio_tc nibbles reversed
+ * from those in the CEE Priority Group sub-TLV.
+ */
for (i = 0; i < 4; i++) {
tc = (u8)((cee_cfg->oper_prio_tc[i] &
- I40E_CEE_PGID_PRIO_1_MASK) >>
- I40E_CEE_PGID_PRIO_1_SHIFT);
- dcbcfg->etscfg.prioritytable[i*2] = tc;
- tc = (u8)((cee_cfg->oper_prio_tc[i] &
I40E_CEE_PGID_PRIO_0_MASK) >>
I40E_CEE_PGID_PRIO_0_SHIFT);
- dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
+ dcbcfg->etscfg.prioritytable[i * 2] = tc;
+ tc = (u8)((cee_cfg->oper_prio_tc[i] &
+ I40E_CEE_PGID_PRIO_1_MASK) >>
+ I40E_CEE_PGID_PRIO_1_SHIFT);
+ dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;
}
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
@@ -531,37 +721,85 @@ static void i40e_cee_to_dcb_config(
dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
- status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
- I40E_AQC_CEE_APP_STATUS_SHIFT;
+ i = 0;
+ status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
+ I40E_AQC_CEE_FCOE_STATUS_SHIFT;
err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
- /* Add APPs if Error is False and Oper/Sync is True */
+ /* Add FCoE APP if Error is False and Oper/Sync is True */
if (!err && sync && oper) {
- /* CEE operating configuration supports FCoE/iSCSI/FIP only */
- dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
-
/* FCoE APP */
- dcbcfg->app[0].priority =
+ dcbcfg->app[i].priority =
(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
I40E_AQC_CEE_APP_FCOE_SHIFT;
- dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
- dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+ dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
+ dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
+ i++;
+ }
+ status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
+ I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
+ err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
+ sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
+ oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
+ /* Add iSCSI APP if Error is False and Oper/Sync is True */
+ if (!err && sync && oper) {
/* iSCSI APP */
- dcbcfg->app[1].priority =
+ dcbcfg->app[i].priority =
(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
I40E_AQC_CEE_APP_ISCSI_SHIFT;
- dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
- dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
+ dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
+ dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
+ i++;
+ }
+ status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
+ I40E_AQC_CEE_FIP_STATUS_SHIFT;
+ err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
+ sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
+ oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
+ /* Add FIP APP if Error is False and Oper/Sync is True */
+ if (!err && sync && oper) {
/* FIP APP */
- dcbcfg->app[2].priority =
+ dcbcfg->app[i].priority =
(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
I40E_AQC_CEE_APP_FIP_SHIFT;
- dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
- dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
+ dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
+ dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
+ i++;
}
+ dcbcfg->numapps = i;
+}
+
+/**
+ * i40e_get_ieee_dcb_config
+ * @hw: pointer to the hw struct
+ *
+ * Get IEEE mode DCB configuration from the Firmware
+ **/
+static i40e_status i40e_get_ieee_dcb_config(struct i40e_hw *hw)
+{
+ i40e_status ret = 0;
+
+ /* IEEE mode */
+ hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
+ /* Get Local DCB Config */
+ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
+ &hw->local_dcbx_config);
+ if (ret)
+ goto out;
+
+ /* Get Remote DCB Config */
+ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
+ I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
+ &hw->remote_dcbx_config);
+ /* Don't treat ENOENT as an error for Remote MIBs */
+ if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
+ ret = 0;
+
+out:
+ return ret;
}
/**
@@ -579,7 +817,7 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw)
/* If Firmware version < v4.33 IEEE only */
if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
(hw->aq.fw_maj_ver < 4))
- goto ieee;
+ return i40e_get_ieee_dcb_config(hw);
/* If Firmware version == v4.33 use old CEE struct */
if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) {
@@ -608,16 +846,14 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw)
/* CEE mode not enabled try querying IEEE data */
if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
- goto ieee;
- else
+ return i40e_get_ieee_dcb_config(hw);
+
+ if (ret)
goto out;
-ieee:
- /* IEEE mode */
- hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
- /* Get Local DCB Config */
+ /* Get CEE DCB Desired Config */
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
- &hw->local_dcbx_config);
+ &hw->desired_dcbx_config);
if (ret)
goto out;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.h b/drivers/net/ethernet/intel/i40e/i40e_dcb.h
index 50fc894a4cde..92d01042c1f6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_dcb.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.h
@@ -44,6 +44,15 @@
#define I40E_IEEE_SUBTYPE_PFC_CFG 11
#define I40E_IEEE_SUBTYPE_APP_PRI 12
+#define I40E_CEE_DCBX_OUI 0x001b21
+#define I40E_CEE_DCBX_TYPE 2
+
+#define I40E_CEE_SUBTYPE_CTRL 1
+#define I40E_CEE_SUBTYPE_PG_CFG 2
+#define I40E_CEE_SUBTYPE_PFC_CFG 3
+#define I40E_CEE_SUBTYPE_APP_PRI 4
+
+#define I40E_CEE_MAX_FEAT_TYPE 3
/* Defines for LLDP TLV header */
#define I40E_LLDP_TLV_LEN_SHIFT 0
#define I40E_LLDP_TLV_LEN_MASK (0x01FF << I40E_LLDP_TLV_LEN_SHIFT)
@@ -98,6 +107,36 @@ struct i40e_lldp_org_tlv {
__be32 ouisubtype;
u8 tlvinfo[1];
};
+
+struct i40e_cee_tlv_hdr {
+ __be16 typelen;
+ u8 operver;
+ u8 maxver;
+};
+
+struct i40e_cee_ctrl_tlv {
+ struct i40e_cee_tlv_hdr hdr;
+ __be32 seqno;
+ __be32 ackno;
+};
+
+struct i40e_cee_feat_tlv {
+ struct i40e_cee_tlv_hdr hdr;
+ u8 en_will_err; /* Bits: |En|Will|Err|Reserved(5)| */
+#define I40E_CEE_FEAT_TLV_ENABLE_MASK 0x80
+#define I40E_CEE_FEAT_TLV_WILLING_MASK 0x40
+#define I40E_CEE_FEAT_TLV_ERR_MASK 0x20
+ u8 subtype;
+ u8 tlvinfo[1];
+};
+
+struct i40e_cee_app_prio {
+ __be16 protocol;
+ u8 upper_oui_sel; /* Bits: |Upper OUI(6)|Selector(2)| */
+#define I40E_CEE_APP_SELECTOR_MASK 0x03
+ __be16 lower_oui;
+ u8 prio_map;
+};
#pragma pack()
i40e_status i40e_get_dcbx_status(struct i40e_hw *hw,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c
index 1c51f736a8d0..886e667f2f1c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c
@@ -236,14 +236,13 @@ static void i40e_dcbnl_del_app(struct i40e_pf *pf,
struct i40e_dcb_app_priority_table *app)
{
int v, err;
+
for (v = 0; v < pf->num_alloc_vsi; v++) {
if (pf->vsi[v] && pf->vsi[v]->netdev) {
err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app);
- if (err)
- dev_info(&pf->pdev->dev, "%s: Failed deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n",
- __func__, pf->vsi[v]->seid,
- err, app->selector,
- app->protocolid, app->priority);
+ dev_dbg(&pf->pdev->dev, "Deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n",
+ pf->vsi[v]->seid, err, app->selector,
+ app->protocolid, app->priority);
}
}
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index d7c15d17faa6..d4b7af9a2fc8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -404,82 +404,82 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
nstat = i40e_get_vsi_stats_struct(vsi);
dev_info(&pf->pdev->dev,
" net_stats: rx_packets = %lu, rx_bytes = %lu, rx_errors = %lu, rx_dropped = %lu\n",
- (long unsigned int)nstat->rx_packets,
- (long unsigned int)nstat->rx_bytes,
- (long unsigned int)nstat->rx_errors,
- (long unsigned int)nstat->rx_dropped);
+ (unsigned long int)nstat->rx_packets,
+ (unsigned long int)nstat->rx_bytes,
+ (unsigned long int)nstat->rx_errors,
+ (unsigned long int)nstat->rx_dropped);
dev_info(&pf->pdev->dev,
" net_stats: tx_packets = %lu, tx_bytes = %lu, tx_errors = %lu, tx_dropped = %lu\n",
- (long unsigned int)nstat->tx_packets,
- (long unsigned int)nstat->tx_bytes,
- (long unsigned int)nstat->tx_errors,
- (long unsigned int)nstat->tx_dropped);
+ (unsigned long int)nstat->tx_packets,
+ (unsigned long int)nstat->tx_bytes,
+ (unsigned long int)nstat->tx_errors,
+ (unsigned long int)nstat->tx_dropped);
dev_info(&pf->pdev->dev,
" net_stats: multicast = %lu, collisions = %lu\n",
- (long unsigned int)nstat->multicast,
- (long unsigned int)nstat->collisions);
+ (unsigned long int)nstat->multicast,
+ (unsigned long int)nstat->collisions);
dev_info(&pf->pdev->dev,
" net_stats: rx_length_errors = %lu, rx_over_errors = %lu, rx_crc_errors = %lu\n",
- (long unsigned int)nstat->rx_length_errors,
- (long unsigned int)nstat->rx_over_errors,
- (long unsigned int)nstat->rx_crc_errors);
+ (unsigned long int)nstat->rx_length_errors,
+ (unsigned long int)nstat->rx_over_errors,
+ (unsigned long int)nstat->rx_crc_errors);
dev_info(&pf->pdev->dev,
" net_stats: rx_frame_errors = %lu, rx_fifo_errors = %lu, rx_missed_errors = %lu\n",
- (long unsigned int)nstat->rx_frame_errors,
- (long unsigned int)nstat->rx_fifo_errors,
- (long unsigned int)nstat->rx_missed_errors);
+ (unsigned long int)nstat->rx_frame_errors,
+ (unsigned long int)nstat->rx_fifo_errors,
+ (unsigned long int)nstat->rx_missed_errors);
dev_info(&pf->pdev->dev,
" net_stats: tx_aborted_errors = %lu, tx_carrier_errors = %lu, tx_fifo_errors = %lu\n",
- (long unsigned int)nstat->tx_aborted_errors,
- (long unsigned int)nstat->tx_carrier_errors,
- (long unsigned int)nstat->tx_fifo_errors);
+ (unsigned long int)nstat->tx_aborted_errors,
+ (unsigned long int)nstat->tx_carrier_errors,
+ (unsigned long int)nstat->tx_fifo_errors);
dev_info(&pf->pdev->dev,
" net_stats: tx_heartbeat_errors = %lu, tx_window_errors = %lu\n",
- (long unsigned int)nstat->tx_heartbeat_errors,
- (long unsigned int)nstat->tx_window_errors);
+ (unsigned long int)nstat->tx_heartbeat_errors,
+ (unsigned long int)nstat->tx_window_errors);
dev_info(&pf->pdev->dev,
" net_stats: rx_compressed = %lu, tx_compressed = %lu\n",
- (long unsigned int)nstat->rx_compressed,
- (long unsigned int)nstat->tx_compressed);
+ (unsigned long int)nstat->rx_compressed,
+ (unsigned long int)nstat->tx_compressed);
dev_info(&pf->pdev->dev,
" net_stats_offsets: rx_packets = %lu, rx_bytes = %lu, rx_errors = %lu, rx_dropped = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.rx_packets,
- (long unsigned int)vsi->net_stats_offsets.rx_bytes,
- (long unsigned int)vsi->net_stats_offsets.rx_errors,
- (long unsigned int)vsi->net_stats_offsets.rx_dropped);
+ (unsigned long int)vsi->net_stats_offsets.rx_packets,
+ (unsigned long int)vsi->net_stats_offsets.rx_bytes,
+ (unsigned long int)vsi->net_stats_offsets.rx_errors,
+ (unsigned long int)vsi->net_stats_offsets.rx_dropped);
dev_info(&pf->pdev->dev,
" net_stats_offsets: tx_packets = %lu, tx_bytes = %lu, tx_errors = %lu, tx_dropped = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.tx_packets,
- (long unsigned int)vsi->net_stats_offsets.tx_bytes,
- (long unsigned int)vsi->net_stats_offsets.tx_errors,
- (long unsigned int)vsi->net_stats_offsets.tx_dropped);
+ (unsigned long int)vsi->net_stats_offsets.tx_packets,
+ (unsigned long int)vsi->net_stats_offsets.tx_bytes,
+ (unsigned long int)vsi->net_stats_offsets.tx_errors,
+ (unsigned long int)vsi->net_stats_offsets.tx_dropped);
dev_info(&pf->pdev->dev,
" net_stats_offsets: multicast = %lu, collisions = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.multicast,
- (long unsigned int)vsi->net_stats_offsets.collisions);
+ (unsigned long int)vsi->net_stats_offsets.multicast,
+ (unsigned long int)vsi->net_stats_offsets.collisions);
dev_info(&pf->pdev->dev,
" net_stats_offsets: rx_length_errors = %lu, rx_over_errors = %lu, rx_crc_errors = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.rx_length_errors,
- (long unsigned int)vsi->net_stats_offsets.rx_over_errors,
- (long unsigned int)vsi->net_stats_offsets.rx_crc_errors);
+ (unsigned long int)vsi->net_stats_offsets.rx_length_errors,
+ (unsigned long int)vsi->net_stats_offsets.rx_over_errors,
+ (unsigned long int)vsi->net_stats_offsets.rx_crc_errors);
dev_info(&pf->pdev->dev,
" net_stats_offsets: rx_frame_errors = %lu, rx_fifo_errors = %lu, rx_missed_errors = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.rx_frame_errors,
- (long unsigned int)vsi->net_stats_offsets.rx_fifo_errors,
- (long unsigned int)vsi->net_stats_offsets.rx_missed_errors);
+ (unsigned long int)vsi->net_stats_offsets.rx_frame_errors,
+ (unsigned long int)vsi->net_stats_offsets.rx_fifo_errors,
+ (unsigned long int)vsi->net_stats_offsets.rx_missed_errors);
dev_info(&pf->pdev->dev,
" net_stats_offsets: tx_aborted_errors = %lu, tx_carrier_errors = %lu, tx_fifo_errors = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.tx_aborted_errors,
- (long unsigned int)vsi->net_stats_offsets.tx_carrier_errors,
- (long unsigned int)vsi->net_stats_offsets.tx_fifo_errors);
+ (unsigned long int)vsi->net_stats_offsets.tx_aborted_errors,
+ (unsigned long int)vsi->net_stats_offsets.tx_carrier_errors,
+ (unsigned long int)vsi->net_stats_offsets.tx_fifo_errors);
dev_info(&pf->pdev->dev,
" net_stats_offsets: tx_heartbeat_errors = %lu, tx_window_errors = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.tx_heartbeat_errors,
- (long unsigned int)vsi->net_stats_offsets.tx_window_errors);
+ (unsigned long int)vsi->net_stats_offsets.tx_heartbeat_errors,
+ (unsigned long int)vsi->net_stats_offsets.tx_window_errors);
dev_info(&pf->pdev->dev,
" net_stats_offsets: rx_compressed = %lu, tx_compressed = %lu\n",
- (long unsigned int)vsi->net_stats_offsets.rx_compressed,
- (long unsigned int)vsi->net_stats_offsets.tx_compressed);
+ (unsigned long int)vsi->net_stats_offsets.rx_compressed,
+ (unsigned long int)vsi->net_stats_offsets.tx_compressed);
dev_info(&pf->pdev->dev,
" tx_restart = %d, tx_busy = %d, rx_buf_failed = %d, rx_page_failed = %d\n",
vsi->tx_restart, vsi->tx_busy,
@@ -487,6 +487,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
rcu_read_lock();
for (i = 0; i < vsi->num_queue_pairs; i++) {
struct i40e_ring *rx_ring = ACCESS_ONCE(vsi->rx_rings[i]);
+
if (!rx_ring)
continue;
@@ -527,7 +528,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
dev_info(&pf->pdev->dev,
" rx_rings[%i]: size = %i, dma = 0x%08lx\n",
i, rx_ring->size,
- (long unsigned int)rx_ring->dma);
+ (unsigned long int)rx_ring->dma);
dev_info(&pf->pdev->dev,
" rx_rings[%i]: vsi = %p, q_vector = %p\n",
i, rx_ring->vsi,
@@ -535,6 +536,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
}
for (i = 0; i < vsi->num_queue_pairs; i++) {
struct i40e_ring *tx_ring = ACCESS_ONCE(vsi->tx_rings[i]);
+
if (!tx_ring)
continue;
@@ -573,7 +575,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
dev_info(&pf->pdev->dev,
" tx_rings[%i]: size = %i, dma = 0x%08lx\n",
i, tx_ring->size,
- (long unsigned int)tx_ring->dma);
+ (unsigned long int)tx_ring->dma);
dev_info(&pf->pdev->dev,
" tx_rings[%i]: vsi = %p, q_vector = %p\n",
i, tx_ring->vsi,
@@ -743,6 +745,7 @@ static void i40e_dbg_dump_aq_desc(struct i40e_pf *pf)
ring = &(hw->aq.asq);
for (i = 0; i < ring->count; i++) {
struct i40e_aq_desc *d = I40E_ADMINQ_DESC(*ring, i);
+
dev_info(&pf->pdev->dev,
" at[%02d] flags=0x%04x op=0x%04x dlen=0x%04x ret=0x%04x cookie_h=0x%08x cookie_l=0x%08x\n",
i, d->flags, d->opcode, d->datalen, d->retval,
@@ -755,6 +758,7 @@ static void i40e_dbg_dump_aq_desc(struct i40e_pf *pf)
ring = &(hw->aq.arq);
for (i = 0; i < ring->count; i++) {
struct i40e_aq_desc *d = I40E_ADMINQ_DESC(*ring, i);
+
dev_info(&pf->pdev->dev,
" ar[%02d] flags=0x%04x op=0x%04x dlen=0x%04x ret=0x%04x cookie_h=0x%08x cookie_l=0x%08x\n",
i, d->flags, d->opcode, d->datalen, d->retval,
@@ -949,24 +953,6 @@ static void i40e_dbg_dump_veb_all(struct i40e_pf *pf)
}
}
-/**
- * i40e_dbg_cmd_fd_ctrl - Enable/disable FD sideband/ATR
- * @pf: the PF that would be altered
- * @flag: flag that needs enabling or disabling
- * @enable: Enable/disable FD SD/ATR
- **/
-static void i40e_dbg_cmd_fd_ctrl(struct i40e_pf *pf, u64 flag, bool enable)
-{
- if (enable) {
- pf->flags |= flag;
- } else {
- pf->flags &= ~flag;
- pf->auto_disable_flags |= flag;
- }
- dev_info(&pf->pdev->dev, "requesting a PF reset\n");
- i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED));
-}
-
#define I40E_MAX_DEBUG_OUT_BUFFER (4096*4)
/**
* i40e_dbg_command_write - write into command datum
@@ -1038,7 +1024,13 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, "'%s' failed\n", cmd_buf);
} else if (strncmp(cmd_buf, "del vsi", 7) == 0) {
- sscanf(&cmd_buf[7], "%i", &vsi_seid);
+ cnt = sscanf(&cmd_buf[7], "%i", &vsi_seid);
+ if (cnt != 1) {
+ dev_info(&pf->pdev->dev,
+ "del vsi: bad command string, cnt=%d\n",
+ cnt);
+ goto command_write_done;
+ }
vsi = i40e_dbg_find_vsi(pf, vsi_seid);
if (!vsi) {
dev_info(&pf->pdev->dev, "del VSI %d: seid not found\n",
@@ -1145,8 +1137,10 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
goto command_write_done;
}
+ spin_lock_bh(&vsi->mac_filter_list_lock);
f = i40e_add_filter(vsi, ma, vlan, false, false);
- ret = i40e_sync_vsi_filters(vsi);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+ ret = i40e_sync_vsi_filters(vsi, true);
if (f && !ret)
dev_info(&pf->pdev->dev,
"add macaddr: %pM vlan=%d added to VSI %d\n",
@@ -1182,8 +1176,10 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
goto command_write_done;
}
+ spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_del_filter(vsi, ma, vlan, false, false);
- ret = i40e_sync_vsi_filters(vsi);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+ ret = i40e_sync_vsi_filters(vsi, true);
if (!ret)
dev_info(&pf->pdev->dev,
"del macaddr: %pM vlan=%d removed from VSI %d\n",
@@ -1488,6 +1484,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
} else if (strncmp(cmd_buf, "read", 4) == 0) {
u32 address;
u32 value;
+
cnt = sscanf(&cmd_buf[4], "%i", &address);
if (cnt != 1) {
dev_info(&pf->pdev->dev, "read <reg>\n");
@@ -1495,9 +1492,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
}
/* check the range on address */
- if (address >= I40E_MAX_REGISTER) {
- dev_info(&pf->pdev->dev, "read reg address 0x%08x too large\n",
- address);
+ if (address > (pf->ioremap_len - sizeof(u32))) {
+ dev_info(&pf->pdev->dev, "read reg address 0x%08x too large, max=0x%08lx\n",
+ address, (unsigned long int)(pf->ioremap_len - sizeof(u32)));
goto command_write_done;
}
@@ -1507,6 +1504,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
} else if (strncmp(cmd_buf, "write", 5) == 0) {
u32 address, value;
+
cnt = sscanf(&cmd_buf[5], "%i %i", &address, &value);
if (cnt != 2) {
dev_info(&pf->pdev->dev, "write <reg> <value>\n");
@@ -1514,9 +1512,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
}
/* check the range on address */
- if (address >= I40E_MAX_REGISTER) {
- dev_info(&pf->pdev->dev, "write reg address 0x%08x too large\n",
- address);
+ if (address > (pf->ioremap_len - sizeof(u32))) {
+ dev_info(&pf->pdev->dev, "write reg address 0x%08x too large, max=0x%08lx\n",
+ address, (unsigned long int)(pf->ioremap_len - sizeof(u32)));
goto command_write_done;
}
wr32(&pf->hw, address, value);
@@ -1528,6 +1526,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
cnt = sscanf(&cmd_buf[15], "%i", &vsi_seid);
if (cnt == 0) {
int i;
+
for (i = 0; i < pf->num_alloc_vsi; i++)
i40e_vsi_reset_stats(pf->vsi[i]);
dev_info(&pf->pdev->dev, "vsi clear stats called for all vsi's\n");
@@ -1726,8 +1725,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
packet_len, I40E_FDIR_MAX_RAW_PACKET_SIZE);
for (i = 0; i < packet_len; i++) {
- sscanf(&asc_packet[j], "%2hhx ",
- &raw_packet[i]);
+ cnt = sscanf(&asc_packet[j], "%2hhx ", &raw_packet[i]);
+ if (!cnt)
+ break;
j += 3;
}
dev_info(&pf->pdev->dev, "FD raw packet dump\n");
@@ -1745,16 +1745,13 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
raw_packet = NULL;
kfree(asc_packet);
asc_packet = NULL;
- } else if (strncmp(cmd_buf, "fd-atr off", 10) == 0) {
- i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false);
- } else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) {
- i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true);
} else if (strncmp(cmd_buf, "fd current cnt", 14) == 0) {
dev_info(&pf->pdev->dev, "FD current total filter count for this interface: %d\n",
i40e_get_current_fd_count(pf));
} else if (strncmp(cmd_buf, "lldp", 4) == 0) {
if (strncmp(&cmd_buf[5], "stop", 4) == 0) {
int ret;
+
ret = i40e_aq_stop_lldp(&pf->hw, false, NULL);
if (ret) {
dev_info(&pf->pdev->dev,
@@ -1779,6 +1776,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
#endif /* CONFIG_I40E_DCB */
} else if (strncmp(&cmd_buf[5], "start", 5) == 0) {
int ret;
+
ret = i40e_aq_add_rem_control_packet_filter(&pf->hw,
pf->hw.mac.addr,
I40E_ETH_P_LLDP, 0,
@@ -1807,6 +1805,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
u16 llen, rlen;
int ret;
u8 *buff;
+
buff = kzalloc(I40E_LLDPDU_SIZE, GFP_KERNEL);
if (!buff)
goto command_write_done;
@@ -1833,6 +1832,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
u16 llen, rlen;
int ret;
u8 *buff;
+
buff = kzalloc(I40E_LLDPDU_SIZE, GFP_KERNEL);
if (!buff)
goto command_write_done;
@@ -1858,6 +1858,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
buff = NULL;
} else if (strncmp(&cmd_buf[5], "event on", 8) == 0) {
int ret;
+
ret = i40e_aq_cfg_lldp_mib_change_event(&pf->hw,
true, NULL);
if (ret) {
@@ -1868,6 +1869,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
}
} else if (strncmp(&cmd_buf[5], "event off", 9) == 0) {
int ret;
+
ret = i40e_aq_cfg_lldp_mib_change_event(&pf->hw,
false, NULL);
if (ret) {
@@ -1969,8 +1971,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, " send indirect aq_cmd <flags> <opcode> <datalen> <retval> <cookie_h> <cookie_l> <param0> <param1> <param2> <param3> <buffer_len>\n");
dev_info(&pf->pdev->dev, " add fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
dev_info(&pf->pdev->dev, " rem fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
- dev_info(&pf->pdev->dev, " fd-atr off\n");
- dev_info(&pf->pdev->dev, " fd-atr on\n");
dev_info(&pf->pdev->dev, " fd current cnt");
dev_info(&pf->pdev->dev, " lldp start\n");
dev_info(&pf->pdev->dev, " lldp stop\n");
@@ -2105,6 +2105,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
}
} else if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) {
int mtu;
+
cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i %i",
&vsi_seid, &mtu);
if (cnt != 2) {
@@ -2220,7 +2221,6 @@ void i40e_dbg_pf_init(struct i40e_pf *pf)
create_failed:
dev_info(dev, "debugfs dir/file for %s failed\n", name);
debugfs_remove_recursive(pf->i40e_dbg_pf);
- return;
}
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h
new file mode 100644
index 000000000000..c601ca4a610c
--- /dev/null
+++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Driver
+ * Copyright(c) 2013 - 2015 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.
+ *
+ * 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".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_DEVIDS_H_
+#define _I40E_DEVIDS_H_
+
+/* Device IDs */
+#define I40E_DEV_ID_SFP_XL710 0x1572
+#define I40E_DEV_ID_QEMU 0x1574
+#define I40E_DEV_ID_KX_A 0x157F
+#define I40E_DEV_ID_KX_B 0x1580
+#define I40E_DEV_ID_KX_C 0x1581
+#define I40E_DEV_ID_QSFP_A 0x1583
+#define I40E_DEV_ID_QSFP_B 0x1584
+#define I40E_DEV_ID_QSFP_C 0x1585
+#define I40E_DEV_ID_10G_BASE_T 0x1586
+#define I40E_DEV_ID_20G_KR2 0x1587
+#define I40E_DEV_ID_20G_KR2_A 0x1588
+#define I40E_DEV_ID_10G_BASE_T4 0x1589
+#define I40E_DEV_ID_VF 0x154C
+#define I40E_DEV_ID_VF_HV 0x1571
+#define I40E_DEV_ID_SFP_X722 0x37D0
+#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
+#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
+#define I40E_DEV_ID_X722_VF 0x37CD
+#define I40E_DEV_ID_X722_VF_HV 0x37D9
+
+#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
+ (d) == I40E_DEV_ID_QSFP_B || \
+ (d) == I40E_DEV_ID_QSFP_C)
+
+#endif /* _I40E_DEVIDS_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index e972b5ecbf0b..3f385ffe420f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -87,11 +87,9 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {
I40E_VSI_STAT("rx_broadcast", eth_stats.rx_broadcast),
I40E_VSI_STAT("tx_broadcast", eth_stats.tx_broadcast),
I40E_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol),
+ I40E_VSI_STAT("tx_linearize", tx_linearize),
};
-static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
- struct ethtool_rxnfc *cmd);
-
/* These PF_STATs might look like duplicates of some NETDEV_STATs,
* but they are separate. This device supports Virtualization, and
* as such might have several netdevs supporting VMDq and FCoE going
@@ -229,10 +227,12 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = {
static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
"NPAR",
+ "LinkPolling",
+ "flow-director-atr",
+ "veb-stats",
};
-#define I40E_PRIV_FLAGS_STR_LEN \
- (sizeof(i40e_priv_flags_strings) / ETH_GSTRING_LEN)
+#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
/**
* i40e_partition_setting_complaint - generic complaint for MFP restriction
@@ -253,7 +253,8 @@ static void i40e_partition_setting_complaint(struct i40e_pf *pf)
**/
static void i40e_get_settings_link_up(struct i40e_hw *hw,
struct ethtool_cmd *ecmd,
- struct net_device *netdev)
+ struct net_device *netdev,
+ struct i40e_pf *pf)
{
struct i40e_link_status *hw_link_info = &hw->phy.link_info;
u32 link_speed = hw_link_info->link_speed;
@@ -272,65 +273,49 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
case I40E_PHY_TYPE_40GBASE_AOC:
ecmd->supported = SUPPORTED_40000baseCR4_Full;
break;
- case I40E_PHY_TYPE_40GBASE_KR4:
- ecmd->supported = SUPPORTED_Autoneg |
- SUPPORTED_40000baseKR4_Full;
- ecmd->advertising = ADVERTISED_Autoneg |
- ADVERTISED_40000baseKR4_Full;
- break;
case I40E_PHY_TYPE_40GBASE_SR4:
ecmd->supported = SUPPORTED_40000baseSR4_Full;
break;
case I40E_PHY_TYPE_40GBASE_LR4:
ecmd->supported = SUPPORTED_40000baseLR4_Full;
break;
- case I40E_PHY_TYPE_20GBASE_KR2:
- ecmd->supported = SUPPORTED_Autoneg |
- SUPPORTED_20000baseKR2_Full;
- ecmd->advertising = ADVERTISED_Autoneg |
- ADVERTISED_20000baseKR2_Full;
- break;
- case I40E_PHY_TYPE_10GBASE_KX4:
- ecmd->supported = SUPPORTED_Autoneg |
- SUPPORTED_10000baseKX4_Full;
- ecmd->advertising = ADVERTISED_Autoneg |
- ADVERTISED_10000baseKX4_Full;
- break;
- case I40E_PHY_TYPE_10GBASE_KR:
- ecmd->supported = SUPPORTED_Autoneg |
- SUPPORTED_10000baseKR_Full;
- ecmd->advertising = ADVERTISED_Autoneg |
- ADVERTISED_10000baseKR_Full;
- break;
case I40E_PHY_TYPE_10GBASE_SR:
case I40E_PHY_TYPE_10GBASE_LR:
case I40E_PHY_TYPE_1000BASE_SX:
case I40E_PHY_TYPE_1000BASE_LX:
- ecmd->supported = SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full;
+ ecmd->supported = SUPPORTED_10000baseT_Full;
+ if (hw_link_info->module_type[2] &
+ I40E_MODULE_TYPE_1000BASE_SX ||
+ hw_link_info->module_type[2] &
+ I40E_MODULE_TYPE_1000BASE_LX) {
+ ecmd->supported |= SUPPORTED_1000baseT_Full;
+ if (hw_link_info->requested_speeds &
+ I40E_LINK_SPEED_1GB)
+ ecmd->advertising |= ADVERTISED_1000baseT_Full;
+ }
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
ecmd->advertising |= ADVERTISED_10000baseT_Full;
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
- ecmd->advertising |= ADVERTISED_1000baseT_Full;
- break;
- case I40E_PHY_TYPE_1000BASE_KX:
- ecmd->supported = SUPPORTED_Autoneg |
- SUPPORTED_1000baseKX_Full;
- ecmd->advertising = ADVERTISED_Autoneg |
- ADVERTISED_1000baseKX_Full;
break;
case I40E_PHY_TYPE_10GBASE_T:
case I40E_PHY_TYPE_1000BASE_T:
- case I40E_PHY_TYPE_100BASE_TX:
ecmd->supported = SUPPORTED_Autoneg |
SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_100baseT_Full;
+ SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_Autoneg;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
ecmd->advertising |= ADVERTISED_10000baseT_Full;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
ecmd->advertising |= ADVERTISED_1000baseT_Full;
+ break;
+ case I40E_PHY_TYPE_1000BASE_T_OPTICAL:
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_1000baseT_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_1000baseT_Full;
+ break;
+ case I40E_PHY_TYPE_100BASE_TX:
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_100baseT_Full;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
ecmd->advertising |= ADVERTISED_100baseT_Full;
break;
@@ -350,12 +335,24 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
break;
case I40E_PHY_TYPE_SGMII:
ecmd->supported = SUPPORTED_Autoneg |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_100baseT_Full;
+ SUPPORTED_1000baseT_Full;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
ecmd->advertising |= ADVERTISED_1000baseT_Full;
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
- ecmd->advertising |= ADVERTISED_100baseT_Full;
+ if (pf->hw.mac.type == I40E_MAC_X722) {
+ ecmd->supported |= SUPPORTED_100baseT_Full;
+ if (hw_link_info->requested_speeds &
+ I40E_LINK_SPEED_100MB)
+ ecmd->advertising |= ADVERTISED_100baseT_Full;
+ }
+ break;
+ /* Backplane is set based on supported phy types in get_settings
+ * so don't set anything here but don't warn either
+ */
+ case I40E_PHY_TYPE_40GBASE_KR4:
+ case I40E_PHY_TYPE_20GBASE_KR2:
+ case I40E_PHY_TYPE_10GBASE_KR:
+ case I40E_PHY_TYPE_10GBASE_KX4:
+ case I40E_PHY_TYPE_1000BASE_KX:
break;
default:
/* if we got here and link is up something bad is afoot */
@@ -394,64 +391,73 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
* Reports link settings that can be determined when link is down
**/
static void i40e_get_settings_link_down(struct i40e_hw *hw,
- struct ethtool_cmd *ecmd)
+ struct ethtool_cmd *ecmd,
+ struct i40e_pf *pf)
{
- struct i40e_link_status *hw_link_info = &hw->phy.link_info;
+ enum i40e_aq_capabilities_phy_type phy_types = hw->phy.phy_types;
/* link is down and the driver needs to fall back on
- * device ID to determine what kinds of info to display,
- * it's mostly a guess that may change when link is up
+ * supported phy types to figure out what info to display
*/
- switch (hw->device_id) {
- case I40E_DEV_ID_QSFP_A:
- case I40E_DEV_ID_QSFP_B:
- case I40E_DEV_ID_QSFP_C:
- /* pluggable QSFP */
- ecmd->supported = SUPPORTED_40000baseSR4_Full |
- SUPPORTED_40000baseCR4_Full |
- SUPPORTED_40000baseLR4_Full;
- ecmd->advertising = ADVERTISED_40000baseSR4_Full |
- ADVERTISED_40000baseCR4_Full |
- ADVERTISED_40000baseLR4_Full;
- break;
- case I40E_DEV_ID_KX_B:
- /* backplane 40G */
- ecmd->supported = SUPPORTED_40000baseKR4_Full;
- ecmd->advertising = ADVERTISED_40000baseKR4_Full;
- break;
- case I40E_DEV_ID_KX_C:
- /* backplane 10G */
- ecmd->supported = SUPPORTED_10000baseKR_Full;
- ecmd->advertising = ADVERTISED_10000baseKR_Full;
- break;
- case I40E_DEV_ID_10G_BASE_T:
- ecmd->supported = SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_100baseT_Full;
- /* Figure out what has been requested */
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
- ecmd->advertising |= ADVERTISED_10000baseT_Full;
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
- ecmd->advertising |= ADVERTISED_1000baseT_Full;
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
+ ecmd->supported = 0x0;
+ ecmd->advertising = 0x0;
+ if (phy_types & I40E_CAP_PHY_TYPE_SGMII) {
+ ecmd->supported |= SUPPORTED_Autoneg |
+ SUPPORTED_1000baseT_Full;
+ ecmd->advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_1000baseT_Full;
+ if (pf->hw.mac.type == I40E_MAC_X722) {
+ ecmd->supported |= SUPPORTED_100baseT_Full;
ecmd->advertising |= ADVERTISED_100baseT_Full;
- break;
- case I40E_DEV_ID_20G_KR2:
- /* backplane 20G */
- ecmd->supported = SUPPORTED_20000baseKR2_Full;
- ecmd->advertising = ADVERTISED_20000baseKR2_Full;
- break;
- default:
- /* all the rest are 10G/1G */
- ecmd->supported = SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full;
- /* Figure out what has been requested */
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
- ecmd->advertising |= ADVERTISED_10000baseT_Full;
- if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
- ecmd->advertising |= ADVERTISED_1000baseT_Full;
- break;
+ }
}
+ if (phy_types & I40E_CAP_PHY_TYPE_XAUI ||
+ phy_types & I40E_CAP_PHY_TYPE_XFI ||
+ phy_types & I40E_CAP_PHY_TYPE_SFI ||
+ phy_types & I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU ||
+ phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC)
+ ecmd->supported |= SUPPORTED_10000baseT_Full;
+ if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU ||
+ phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
+ phy_types & I40E_CAP_PHY_TYPE_10GBASE_T ||
+ phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR ||
+ phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) {
+ ecmd->supported |= SUPPORTED_Autoneg |
+ SUPPORTED_10000baseT_Full;
+ ecmd->advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_10000baseT_Full;
+ }
+ if (phy_types & I40E_CAP_PHY_TYPE_XLAUI ||
+ phy_types & I40E_CAP_PHY_TYPE_XLPPI ||
+ phy_types & I40E_CAP_PHY_TYPE_40GBASE_AOC)
+ ecmd->supported |= SUPPORTED_40000baseCR4_Full;
+ if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4_CU ||
+ phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4) {
+ ecmd->supported |= SUPPORTED_Autoneg |
+ SUPPORTED_40000baseCR4_Full;
+ ecmd->advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_40000baseCR4_Full;
+ }
+ if ((phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) &&
+ !(phy_types & I40E_CAP_PHY_TYPE_1000BASE_T)) {
+ ecmd->supported |= SUPPORTED_Autoneg |
+ SUPPORTED_100baseT_Full;
+ ecmd->advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_100baseT_Full;
+ }
+ if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T ||
+ phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX ||
+ phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX ||
+ phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) {
+ ecmd->supported |= SUPPORTED_Autoneg |
+ SUPPORTED_1000baseT_Full;
+ ecmd->advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_1000baseT_Full;
+ }
+ if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4)
+ ecmd->supported |= SUPPORTED_40000baseSR4_Full;
+ if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4)
+ ecmd->supported |= SUPPORTED_40000baseLR4_Full;
/* With no link speed and duplex are unknown */
ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
@@ -475,12 +481,43 @@ static int i40e_get_settings(struct net_device *netdev,
bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP;
if (link_up)
- i40e_get_settings_link_up(hw, ecmd, netdev);
+ i40e_get_settings_link_up(hw, ecmd, netdev, pf);
else
- i40e_get_settings_link_down(hw, ecmd);
+ i40e_get_settings_link_down(hw, ecmd, pf);
/* Now set the settings that don't rely on link being up/down */
+ /* For backplane, supported and advertised are only reliant on the
+ * phy types the NVM specifies are supported.
+ */
+ if (hw->device_id == I40E_DEV_ID_KX_B ||
+ hw->device_id == I40E_DEV_ID_KX_C ||
+ hw->device_id == I40E_DEV_ID_20G_KR2 ||
+ hw->device_id == I40E_DEV_ID_20G_KR2_A) {
+ ecmd->supported = SUPPORTED_Autoneg;
+ ecmd->advertising = ADVERTISED_Autoneg;
+ if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) {
+ ecmd->supported |= SUPPORTED_40000baseKR4_Full;
+ ecmd->advertising |= ADVERTISED_40000baseKR4_Full;
+ }
+ if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2) {
+ ecmd->supported |= SUPPORTED_20000baseKR2_Full;
+ ecmd->advertising |= ADVERTISED_20000baseKR2_Full;
+ }
+ if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) {
+ ecmd->supported |= SUPPORTED_10000baseKR_Full;
+ ecmd->advertising |= ADVERTISED_10000baseKR_Full;
+ }
+ if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {
+ ecmd->supported |= SUPPORTED_10000baseKX4_Full;
+ ecmd->advertising |= ADVERTISED_10000baseKX4_Full;
+ }
+ if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) {
+ ecmd->supported |= SUPPORTED_1000baseKX_Full;
+ ecmd->advertising |= ADVERTISED_1000baseKX_Full;
+ }
+ }
+
/* Set autoneg settings */
ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ?
AUTONEG_ENABLE : AUTONEG_DISABLE);
@@ -580,6 +617,14 @@ static int i40e_set_settings(struct net_device *netdev,
hw->phy.link_info.link_info & I40E_AQ_LINK_UP)
return -EOPNOTSUPP;
+ if (hw->device_id == I40E_DEV_ID_KX_B ||
+ hw->device_id == I40E_DEV_ID_KX_C ||
+ hw->device_id == I40E_DEV_ID_20G_KR2 ||
+ hw->device_id == I40E_DEV_ID_20G_KR2_A) {
+ netdev_info(netdev, "Changing settings is not supported on backplane.\n");
+ return -EOPNOTSUPP;
+ }
+
/* get our own copy of the bits to check against */
memset(&safe_ecmd, 0, sizeof(struct ethtool_cmd));
i40e_get_settings(netdev, &safe_ecmd);
@@ -616,28 +661,31 @@ static int i40e_set_settings(struct net_device *netdev,
/* Check autoneg */
if (autoneg == AUTONEG_ENABLE) {
- /* If autoneg is not supported, return error */
- if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) {
- netdev_info(netdev, "Autoneg not supported on this phy\n");
- return -EINVAL;
- }
/* If autoneg was not already enabled */
if (!(hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED)) {
+ /* If autoneg is not supported, return error */
+ if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) {
+ netdev_info(netdev, "Autoneg not supported on this phy\n");
+ return -EINVAL;
+ }
+ /* Autoneg is allowed to change */
config.abilities = abilities.abilities |
I40E_AQ_PHY_ENABLE_AN;
change = true;
}
} else {
- /* If autoneg is supported 10GBASE_T is the only phy that
- * can disable it, so otherwise return error
- */
- if (safe_ecmd.supported & SUPPORTED_Autoneg &&
- hw->phy.link_info.phy_type != I40E_PHY_TYPE_10GBASE_T) {
- netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
- return -EINVAL;
- }
/* If autoneg is currently enabled */
if (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) {
+ /* If autoneg is supported 10GBASE_T is the only PHY
+ * that can disable it, so otherwise return error
+ */
+ if (safe_ecmd.supported & SUPPORTED_Autoneg &&
+ hw->phy.link_info.phy_type !=
+ I40E_PHY_TYPE_10GBASE_T) {
+ netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
+ return -EINVAL;
+ }
+ /* Autoneg is allowed to change */
config.abilities = abilities.abilities &
~I40E_AQ_PHY_ENABLE_AN;
change = true;
@@ -664,6 +712,13 @@ static int i40e_set_settings(struct net_device *netdev,
advertise & ADVERTISED_40000baseLR4_Full)
config.link_speed |= I40E_LINK_SPEED_40GB;
+ /* If speed didn't get set, set it to what it currently is.
+ * This is needed because if advertise is 0 (as it is when autoneg
+ * is disabled) then speed won't get set.
+ */
+ if (!config.link_speed)
+ config.link_speed = abilities.link_speed;
+
if (change || (abilities.link_speed != config.link_speed)) {
/* copy over the rest of the abilities */
config.phy_type = abilities.phy_type;
@@ -680,7 +735,7 @@ static int i40e_set_settings(struct net_device *netdev,
/* Tell the OS link is going down, the link will go
* back up when fw says it is ready asynchronously
*/
- netdev_info(netdev, "PHY settings change requested, NIC Link is going down.\n");
+ i40e_print_link_message(vsi, false);
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
}
@@ -694,11 +749,11 @@ static int i40e_set_settings(struct net_device *netdev,
return -EAGAIN;
}
- status = i40e_aq_get_link_info(hw, true, NULL, NULL);
+ status = i40e_update_link_info(hw);
if (status)
- netdev_info(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));
+ 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));
} else {
netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
@@ -824,7 +879,7 @@ static int i40e_set_pauseparam(struct net_device *netdev,
/* Tell the OS link is going down, the link will go back up when fw
* says it is ready asynchronously
*/
- netdev_info(netdev, "Flow control settings change requested, NIC Link is going down.\n");
+ i40e_print_link_message(vsi, false);
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
@@ -948,9 +1003,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
cmd = (struct i40e_nvm_access *)eeprom;
ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno);
- if (ret_val &&
- ((hw->aq.asq_last_status != I40E_AQ_RC_EACCES) ||
- (hw->debug_mask & I40E_DEBUG_NVM)))
+ if (ret_val && (hw->debug_mask & I40E_DEBUG_NVM))
dev_info(&pf->pdev->dev,
"NVMUpdate read failed err=%d status=0x%x errno=%d module=%d offset=0x%x size=%d\n",
ret_val, hw->aq.asq_last_status, errno,
@@ -1054,10 +1107,7 @@ static int i40e_set_eeprom(struct net_device *netdev,
cmd = (struct i40e_nvm_access *)eeprom;
ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno);
- if (ret_val &&
- ((hw->aq.asq_last_status != I40E_AQ_RC_EPERM &&
- hw->aq.asq_last_status != I40E_AQ_RC_EBUSY) ||
- (hw->debug_mask & I40E_DEBUG_NVM)))
+ if (ret_val && (hw->debug_mask & I40E_DEBUG_NVM))
dev_info(&pf->pdev->dev,
"NVMUpdate write failed err=%d status=0x%x errno=%d module=%d offset=0x%x size=%d\n",
ret_val, hw->aq.asq_last_status, errno,
@@ -1077,11 +1127,10 @@ static void i40e_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->driver, i40e_driver_name, sizeof(drvinfo->driver));
strlcpy(drvinfo->version, i40e_driver_version_str,
sizeof(drvinfo->version));
- strlcpy(drvinfo->fw_version, i40e_fw_version_str(&pf->hw),
+ strlcpy(drvinfo->fw_version, i40e_nvm_version_str(&pf->hw),
sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
}
static void i40e_get_ringparam(struct net_device *netdev,
@@ -1166,6 +1215,11 @@ static int i40e_set_ringparam(struct net_device *netdev,
/* clone ring and setup updated count */
tx_rings[i] = *vsi->tx_rings[i];
tx_rings[i].count = new_tx_count;
+ /* the desc and bi pointers will be reallocated in the
+ * setup call
+ */
+ tx_rings[i].desc = NULL;
+ tx_rings[i].rx_bi = NULL;
err = i40e_setup_tx_descriptors(&tx_rings[i]);
if (err) {
while (i) {
@@ -1196,6 +1250,11 @@ static int i40e_set_ringparam(struct net_device *netdev,
/* clone ring and setup updated count */
rx_rings[i] = *vsi->rx_rings[i];
rx_rings[i].count = new_rx_count;
+ /* the desc and bi pointers will be reallocated in the
+ * setup call
+ */
+ rx_rings[i].desc = NULL;
+ rx_rings[i].rx_bi = NULL;
err = i40e_setup_rx_descriptors(&rx_rings[i]);
if (err) {
while (i) {
@@ -1263,7 +1322,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)
if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id == 1) {
int len = I40E_PF_STATS_LEN(netdev);
- if (pf->lan_veb != I40E_NO_VEB)
+ if ((pf->lan_veb != I40E_NO_VEB) &&
+ (pf->flags & I40E_FLAG_VEB_STATS_ENABLED))
len += I40E_VEB_STATS_TOTAL;
return len;
} else {
@@ -1336,14 +1396,22 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1)
return;
- if (pf->lan_veb != I40E_NO_VEB) {
+ if ((pf->lan_veb != I40E_NO_VEB) &&
+ (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) {
struct i40e_veb *veb = pf->veb[pf->lan_veb];
+
for (j = 0; j < I40E_VEB_STATS_LEN; j++) {
p = (char *)veb;
p += i40e_gstrings_veb_stats[j].stat_offset;
data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
+ for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) {
+ data[i++] = veb->tc_stats.tc_tx_packets[j];
+ data[i++] = veb->tc_stats.tc_tx_bytes[j];
+ data[i++] = veb->tc_stats.tc_rx_packets[j];
+ data[i++] = veb->tc_stats.tc_rx_bytes[j];
+ }
}
for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) {
p = (char *)pf + i40e_gstrings_stats[j].stat_offset;
@@ -1409,7 +1477,8 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1)
return;
- if (pf->lan_veb != I40E_NO_VEB) {
+ if ((pf->lan_veb != I40E_NO_VEB) &&
+ (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) {
for (i = 0; i < I40E_VEB_STATS_LEN; i++) {
snprintf(p, ETH_GSTRING_LEN, "veb.%s",
i40e_gstrings_veb_stats[i].stat_string);
@@ -1504,9 +1573,18 @@ static int i40e_link_test(struct net_device *netdev, u64 *data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
+ i40e_status status;
+ bool link_up = false;
netif_info(pf, hw, netdev, "link test\n");
- if (i40e_get_link_status(&pf->hw))
+ status = i40e_get_link_status(&pf->hw, &link_up);
+ if (status) {
+ netif_err(pf, drv, netdev, "link query timed out, please retry test\n");
+ *data = 1;
+ return *data;
+ }
+
+ if (link_up)
*data = 0;
else
*data = 1;
@@ -1575,7 +1653,7 @@ static inline bool i40e_active_vfs(struct i40e_pf *pf)
int i;
for (i = 0; i < pf->num_alloc_vfs; i++)
- if (vfs[i].vf_states & I40E_VF_STAT_ACTIVE)
+ if (test_bit(I40E_VF_STAT_ACTIVE, &vfs[i].vf_states))
return true;
return false;
}
@@ -1782,6 +1860,14 @@ static int i40e_get_coalesce(struct net_device *netdev,
ec->rx_coalesce_usecs = vsi->rx_itr_setting & ~I40E_ITR_DYNAMIC;
ec->tx_coalesce_usecs = vsi->tx_itr_setting & ~I40E_ITR_DYNAMIC;
+ /* we use the _usecs_high to store/set the interrupt rate limit
+ * that the hardware supports, that almost but not quite
+ * fits the original intent of the ethtool variable,
+ * the rx_coalesce_usecs_high limits total interrupts
+ * per second from both tx/rx sources.
+ */
+ ec->rx_coalesce_usecs_high = vsi->int_rate_limit;
+ ec->tx_coalesce_usecs_high = vsi->int_rate_limit;
return 0;
}
@@ -1800,6 +1886,17 @@ static int i40e_set_coalesce(struct net_device *netdev,
if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
vsi->work_limit = ec->tx_max_coalesced_frames_irq;
+ /* tx_coalesce_usecs_high is ignored, use rx-usecs-high instead */
+ if (ec->tx_coalesce_usecs_high != vsi->int_rate_limit) {
+ netif_info(pf, drv, netdev, "tx-usecs-high is not used, please program rx-usecs-high\n");
+ return -EINVAL;
+ }
+
+ if (ec->rx_coalesce_usecs_high >= INTRL_REG_TO_USEC(I40E_MAX_INTRL)) {
+ netif_info(pf, drv, netdev, "Invalid value, rx-usecs-high range is 0-235\n");
+ return -EINVAL;
+ }
+
vector = vsi->base_vector;
if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
(ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
@@ -1813,6 +1910,8 @@ static int i40e_set_coalesce(struct net_device *netdev,
return -EINVAL;
}
+ vsi->int_rate_limit = ec->rx_coalesce_usecs_high;
+
if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
(ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
vsi->tx_itr_setting = ec->tx_coalesce_usecs;
@@ -1837,11 +1936,14 @@ static int i40e_set_coalesce(struct net_device *netdev,
vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
+ u16 intrl = INTRL_USEC_TO_REG(vsi->int_rate_limit);
+
q_vector = vsi->q_vectors[i];
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
wr32(hw, I40E_PFINT_ITRN(0, vector - 1), q_vector->rx.itr);
q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);
wr32(hw, I40E_PFINT_ITRN(1, vector - 1), q_vector->tx.itr);
+ wr32(hw, I40E_PFINT_RATEN(vector - 1), intrl);
i40e_flush(hw);
}
@@ -2604,10 +2706,51 @@ static u32 i40e_get_priv_flags(struct net_device *dev)
ret_flags |= pf->hw.func_caps.npar_enable ?
I40E_PRIV_FLAGS_NPAR_FLAG : 0;
+ ret_flags |= pf->flags & I40E_FLAG_LINK_POLLING_ENABLED ?
+ I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0;
+ ret_flags |= pf->flags & I40E_FLAG_FD_ATR_ENABLED ?
+ I40E_PRIV_FLAGS_FD_ATR : 0;
+ ret_flags |= pf->flags & I40E_FLAG_VEB_STATS_ENABLED ?
+ I40E_PRIV_FLAGS_VEB_STATS : 0;
return ret_flags;
}
+/**
+ * i40e_set_priv_flags - set private flags
+ * @dev: network interface device structure
+ * @flags: bit flags to be set
+ **/
+static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
+{
+ struct i40e_netdev_priv *np = netdev_priv(dev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_pf *pf = vsi->back;
+
+ if (flags & I40E_PRIV_FLAGS_LINKPOLL_FLAG)
+ pf->flags |= I40E_FLAG_LINK_POLLING_ENABLED;
+ else
+ pf->flags &= ~I40E_FLAG_LINK_POLLING_ENABLED;
+
+ /* allow the user to control the state of the Flow
+ * Director ATR (Application Targeted Routing) feature
+ * of the driver
+ */
+ if (flags & I40E_PRIV_FLAGS_FD_ATR) {
+ pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
+ } else {
+ pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+ pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED;
+ }
+
+ if (flags & I40E_PRIV_FLAGS_VEB_STATS)
+ pf->flags |= I40E_FLAG_VEB_STATS_ENABLED;
+ else
+ pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED;
+
+ return 0;
+}
+
static const struct ethtool_ops i40e_ethtool_ops = {
.get_settings = i40e_get_settings,
.set_settings = i40e_set_settings,
@@ -2644,6 +2787,7 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.set_channels = i40e_set_channels,
.get_ts_info = i40e_get_ts_info,
.get_priv_flags = i40e_get_priv_flags,
+ .set_priv_flags = i40e_set_priv_flags,
};
void i40e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
index 5ea75dd537d6..fe5d9bf3ed6d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
@@ -272,10 +272,8 @@ out:
/**
* i40e_fcoe_sw_init - sets up the HW for FCoE
* @pf: pointer to PF
- *
- * Returns 0 if FCoE is supported otherwise the error code
**/
-int i40e_init_pf_fcoe(struct i40e_pf *pf)
+void i40e_init_pf_fcoe(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
u32 val;
@@ -286,14 +284,14 @@ int i40e_init_pf_fcoe(struct i40e_pf *pf)
pf->fcoe_hmc_filt_num = 0;
if (!pf->hw.func_caps.fcoe) {
- dev_info(&pf->pdev->dev, "FCoE capability is disabled\n");
- return 0;
+ dev_dbg(&pf->pdev->dev, "FCoE capability is disabled\n");
+ return;
}
if (!pf->hw.func_caps.dcb) {
dev_warn(&pf->pdev->dev,
"Hardware is not DCB capable not enabling FCoE.\n");
- return 0;
+ return;
}
/* enable FCoE hash filter */
@@ -326,7 +324,6 @@ int i40e_init_pf_fcoe(struct i40e_pf *pf)
wr32(hw, I40E_GLFCOE_RCTL, val);
dev_info(&pf->pdev->dev, "FCoE is supported.\n");
- return 0;
}
/**
@@ -1519,10 +1516,12 @@ void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)
* same PCI function.
*/
netdev->dev_port = 1;
+ spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false);
i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false);
i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false);
i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
/* use san mac */
ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
index fa371a2a40c6..79ae7beeafe5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
@@ -431,9 +431,8 @@ exit_sd_error:
pd_idx1 = max(pd_idx,
((j - 1) * I40E_HMC_MAX_BP_COUNT));
pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT));
- for (i = pd_idx1; i < pd_lmt1; i++) {
+ for (i = pd_idx1; i < pd_lmt1; i++)
i40e_remove_pd_bp(hw, info->hmc_info, i);
- }
i40e_remove_pd_page(hw, info->hmc_info, (j - 1));
break;
case I40E_SD_TYPE_DIRECT:
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 2fdf978ae6a5..b825f978d441 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -39,7 +39,7 @@ static const char i40e_driver_string[] =
#define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 3
-#define DRV_VERSION_BUILD 9
+#define DRV_VERSION_BUILD 46
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
@@ -75,10 +75,13 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_B), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_1G_BASE_T_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_X722), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0},
/* required last entry */
{0, }
};
@@ -213,10 +216,10 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile,
ret = i;
pile->search_hint = i + j;
break;
- } else {
- /* not enough, so skip over it and continue looking */
- i += j;
}
+
+ /* not enough, so skip over it and continue looking */
+ i += j;
}
return ret;
@@ -299,25 +302,69 @@ static void i40e_tx_timeout(struct net_device *netdev)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
+ struct i40e_ring *tx_ring = NULL;
+ unsigned int i, hung_queue = 0;
+ u32 head, val;
pf->tx_timeout_count++;
+ /* find the stopped queue the same way the stack does */
+ for (i = 0; i < netdev->num_tx_queues; i++) {
+ struct netdev_queue *q;
+ unsigned long trans_start;
+
+ q = netdev_get_tx_queue(netdev, i);
+ trans_start = q->trans_start ? : netdev->trans_start;
+ if (netif_xmit_stopped(q) &&
+ time_after(jiffies,
+ (trans_start + netdev->watchdog_timeo))) {
+ hung_queue = i;
+ break;
+ }
+ }
+
+ if (i == netdev->num_tx_queues) {
+ netdev_info(netdev, "tx_timeout: no netdev hung queue found\n");
+ } else {
+ /* now that we have an index, find the tx_ring struct */
+ for (i = 0; i < vsi->num_queue_pairs; i++) {
+ if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) {
+ if (hung_queue ==
+ vsi->tx_rings[i]->queue_index) {
+ tx_ring = vsi->tx_rings[i];
+ break;
+ }
+ }
+ }
+ }
+
if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20)))
- pf->tx_timeout_recovery_level = 1;
+ pf->tx_timeout_recovery_level = 1; /* reset after some time */
+ else if (time_before(jiffies,
+ (pf->tx_timeout_last_recovery + netdev->watchdog_timeo)))
+ return; /* don't do any new action before the next timeout */
+
+ if (tx_ring) {
+ head = i40e_get_head(tx_ring);
+ /* Read interrupt register */
+ if (pf->flags & I40E_FLAG_MSIX_ENABLED)
+ val = rd32(&pf->hw,
+ I40E_PFINT_DYN_CTLN(tx_ring->q_vector->v_idx +
+ tx_ring->vsi->base_vector - 1));
+ else
+ val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);
+
+ netdev_info(netdev, "tx_timeout: VSI_seid: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n",
+ vsi->seid, hung_queue, tx_ring->next_to_clean,
+ head, tx_ring->next_to_use,
+ readl(tx_ring->tail), val);
+ }
+
pf->tx_timeout_last_recovery = jiffies;
- netdev_info(netdev, "tx_timeout recovery level %d\n",
- pf->tx_timeout_recovery_level);
+ netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n",
+ pf->tx_timeout_recovery_level, hung_queue);
switch (pf->tx_timeout_recovery_level) {
- case 0:
- /* disable and re-enable queues for the VSI */
- if (in_interrupt()) {
- set_bit(__I40E_REINIT_REQUESTED, &pf->state);
- set_bit(__I40E_REINIT_REQUESTED, &vsi->state);
- } else {
- i40e_vsi_reinit_locked(vsi);
- }
- break;
case 1:
set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
break;
@@ -329,10 +376,9 @@ static void i40e_tx_timeout(struct net_device *netdev)
break;
default:
netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
- set_bit(__I40E_DOWN_REQUESTED, &pf->state);
- set_bit(__I40E_DOWN_REQUESTED, &vsi->state);
break;
}
+
i40e_service_event_schedule(pf);
pf->tx_timeout_recovery_level++;
}
@@ -431,6 +477,7 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
stats->tx_errors = vsi_stats->tx_errors;
stats->tx_dropped = vsi_stats->tx_dropped;
stats->rx_errors = vsi_stats->rx_errors;
+ stats->rx_dropped = vsi_stats->rx_dropped;
stats->rx_crc_errors = vsi_stats->rx_crc_errors;
stats->rx_length_errors = vsi_stats->rx_length_errors;
@@ -456,11 +503,11 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi)
memset(&vsi->eth_stats_offsets, 0, sizeof(vsi->eth_stats_offsets));
if (vsi->rx_rings && vsi->rx_rings[0]) {
for (i = 0; i < vsi->num_queue_pairs; i++) {
- memset(&vsi->rx_rings[i]->stats, 0 ,
+ memset(&vsi->rx_rings[i]->stats, 0,
sizeof(vsi->rx_rings[i]->stats));
- memset(&vsi->rx_rings[i]->rx_stats, 0 ,
+ memset(&vsi->rx_rings[i]->rx_stats, 0,
sizeof(vsi->rx_rings[i]->rx_stats));
- memset(&vsi->tx_rings[i]->stats, 0 ,
+ memset(&vsi->tx_rings[i]->stats, 0,
sizeof(vsi->tx_rings[i]->stats));
memset(&vsi->tx_rings[i]->tx_stats, 0,
sizeof(vsi->tx_rings[i]->tx_stats));
@@ -754,7 +801,6 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf)
struct i40e_hw_port_stats *nsd = &pf->stats;
struct i40e_hw *hw = &pf->hw;
u64 xoff = 0;
- u16 i, v;
if ((hw->fc.current_mode != I40E_FC_FULL) &&
(hw->fc.current_mode != I40E_FC_RX_PAUSE))
@@ -769,18 +815,6 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf)
if (!(nsd->link_xoff_rx - xoff))
return;
- /* Clear the __I40E_HANG_CHECK_ARMED bit for all Tx rings */
- for (v = 0; v < pf->num_alloc_vsi; v++) {
- struct i40e_vsi *vsi = pf->vsi[v];
-
- if (!vsi || !vsi->tx_rings[0])
- continue;
-
- for (i = 0; i < vsi->num_queue_pairs; i++) {
- struct i40e_ring *ring = vsi->tx_rings[i];
- clear_bit(__I40E_HANG_CHECK_ARMED, &ring->state);
- }
- }
}
/**
@@ -796,7 +830,7 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)
bool xoff[I40E_MAX_TRAFFIC_CLASS] = {false};
struct i40e_dcbx_config *dcb_cfg;
struct i40e_hw *hw = &pf->hw;
- u16 i, v;
+ u16 i;
u8 tc;
dcb_cfg = &hw->local_dcbx_config;
@@ -809,6 +843,7 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)
for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
u64 prio_xoff = nsd->priority_xoff_rx[i];
+
i40e_stat_update32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i),
pf->stat_offsets_loaded,
&osd->priority_xoff_rx[i],
@@ -821,23 +856,6 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)
tc = dcb_cfg->etscfg.prioritytable[i];
xoff[tc] = true;
}
-
- /* Clear the __I40E_HANG_CHECK_ARMED bit for Tx rings */
- for (v = 0; v < pf->num_alloc_vsi; v++) {
- struct i40e_vsi *vsi = pf->vsi[v];
-
- if (!vsi || !vsi->tx_rings[0])
- continue;
-
- for (i = 0; i < vsi->num_queue_pairs; i++) {
- struct i40e_ring *ring = vsi->tx_rings[i];
-
- tc = ring->dcb_tc;
- if (xoff[tc])
- clear_bit(__I40E_HANG_CHECK_ARMED,
- &ring->state);
- }
- }
}
/**
@@ -862,6 +880,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
u32 rx_page, rx_buf;
u64 bytes, packets;
unsigned int start;
+ u64 tx_linearize;
u64 rx_p, rx_b;
u64 tx_p, tx_b;
u16 q;
@@ -880,7 +899,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
*/
rx_b = rx_p = 0;
tx_b = tx_p = 0;
- tx_restart = tx_busy = 0;
+ tx_restart = tx_busy = tx_linearize = 0;
rx_page = 0;
rx_buf = 0;
rcu_read_lock();
@@ -897,6 +916,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
tx_p += packets;
tx_restart += p->tx_stats.restart_queue;
tx_busy += p->tx_stats.tx_busy;
+ tx_linearize += p->tx_stats.tx_linearize;
/* Rx queue is part of the same block as Tx queue */
p = &p[1];
@@ -913,6 +933,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
rcu_read_unlock();
vsi->tx_restart = tx_restart;
vsi->tx_busy = tx_busy;
+ vsi->tx_linearize = tx_linearize;
vsi->rx_page_failed = rx_page;
vsi->rx_buf_failed = rx_buf;
@@ -1256,7 +1277,7 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
* so we have to go through all the list in order to make sure
*/
list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if (f->vlan >= 0)
+ if (f->vlan >= 0 || vsi->info.pvid)
return true;
}
@@ -1334,6 +1355,9 @@ static int i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
* @is_netdev: make sure its a netdev filter, else doesn't matter
*
* Returns ptr to the filter object or NULL when no memory available.
+ *
+ * NOTE: This function is expected to be called with mac_filter_list_lock
+ * being held.
**/
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
u8 *macaddr, s16 vlan,
@@ -1392,6 +1416,9 @@ add_filter_out:
* @vlan: the vlan
* @is_vf: make sure it's a VF filter, else doesn't matter
* @is_netdev: make sure it's a netdev filter, else doesn't matter
+ *
+ * NOTE: This function is expected to be called with mac_filter_list_lock
+ * being held.
**/
void i40e_del_filter(struct i40e_vsi *vsi,
u8 *macaddr, s16 vlan,
@@ -1419,6 +1446,7 @@ void i40e_del_filter(struct i40e_vsi *vsi,
} else {
/* make sure we don't remove a filter in use by VF or netdev */
int min_f = 0;
+
min_f += (f->is_vf ? 1 : 0);
min_f += (f->is_netdev ? 1 : 0);
@@ -1477,6 +1505,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
if (vsi->type == I40E_VSI_MAIN) {
i40e_status ret;
+
ret = i40e_aq_mac_address_write(&vsi->back->hw,
I40E_AQC_WRITE_TYPE_LAA_WOL,
addr->sa_data, NULL);
@@ -1496,8 +1525,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
} else {
+ spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
false, false);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
}
if (ether_addr_equal(addr->sa_data, hw->mac.addr)) {
@@ -1508,13 +1539,15 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
element.flags = cpu_to_le16(I40E_AQC_MACVLAN_ADD_PERFECT_MATCH);
i40e_aq_add_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
} else {
+ spin_lock_bh(&vsi->mac_filter_list_lock);
f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY,
false, false);
if (f)
f->is_laa = true;
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
}
- i40e_sync_vsi_filters(vsi);
+ i40e_sync_vsi_filters(vsi, false);
ether_addr_copy(netdev->dev_addr, addr->sa_data);
return 0;
@@ -1684,6 +1717,8 @@ static void i40e_set_rx_mode(struct net_device *netdev)
struct netdev_hw_addr *mca;
struct netdev_hw_addr *ha;
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+
/* add addr if not already in the filter list */
netdev_for_each_uc_addr(uca, netdev) {
if (!i40e_find_mac(vsi, uca->addr, false, true)) {
@@ -1709,37 +1744,29 @@ static void i40e_set_rx_mode(struct net_device *netdev)
/* remove filter if not in netdev list */
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
- bool found = false;
if (!f->is_netdev)
continue;
- if (is_multicast_ether_addr(f->macaddr)) {
- netdev_for_each_mc_addr(mca, netdev) {
- if (ether_addr_equal(mca->addr, f->macaddr)) {
- found = true;
- break;
- }
- }
- } else {
- netdev_for_each_uc_addr(uca, netdev) {
- if (ether_addr_equal(uca->addr, f->macaddr)) {
- found = true;
- break;
- }
- }
+ netdev_for_each_mc_addr(mca, netdev)
+ if (ether_addr_equal(mca->addr, f->macaddr))
+ goto bottom_of_search_loop;
- for_each_dev_addr(netdev, ha) {
- if (ether_addr_equal(ha->addr, f->macaddr)) {
- found = true;
- break;
- }
- }
- }
- if (!found)
- i40e_del_filter(
- vsi, f->macaddr, I40E_VLAN_ANY, false, true);
+ netdev_for_each_uc_addr(uca, netdev)
+ if (ether_addr_equal(uca->addr, f->macaddr))
+ goto bottom_of_search_loop;
+
+ for_each_dev_addr(netdev, ha)
+ if (ether_addr_equal(ha->addr, f->macaddr))
+ goto bottom_of_search_loop;
+
+ /* f->macaddr wasn't found in uc, mc, or ha list so delete it */
+ i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, false, true);
+
+bottom_of_search_loop:
+ continue;
}
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
/* check for other flag changes */
if (vsi->current_netdev_flags != vsi->netdev->flags) {
@@ -1749,20 +1776,96 @@ static void i40e_set_rx_mode(struct net_device *netdev)
}
/**
+ * i40e_mac_filter_entry_clone - Clones a MAC filter entry
+ * @src: source MAC filter entry to be clones
+ *
+ * Returns the pointer to newly cloned MAC filter entry or NULL
+ * in case of error
+ **/
+static struct i40e_mac_filter *i40e_mac_filter_entry_clone(
+ struct i40e_mac_filter *src)
+{
+ struct i40e_mac_filter *f;
+
+ f = kzalloc(sizeof(*f), GFP_ATOMIC);
+ if (!f)
+ return NULL;
+ *f = *src;
+
+ INIT_LIST_HEAD(&f->list);
+
+ return f;
+}
+
+/**
+ * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries
+ * @vsi: pointer to vsi struct
+ * @from: Pointer to list which contains MAC filter entries - changes to
+ * those entries needs to be undone.
+ *
+ * MAC filter entries from list were slated to be removed from device.
+ **/
+static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
+ struct list_head *from)
+{
+ struct i40e_mac_filter *f, *ftmp;
+
+ list_for_each_entry_safe(f, ftmp, from, list) {
+ f->changed = true;
+ /* Move the element back into MAC filter list*/
+ list_move_tail(&f->list, &vsi->mac_filter_list);
+ }
+}
+
+/**
+ * i40e_undo_add_filter_entries - Undo the changes made to MAC filter entries
+ * @vsi: pointer to vsi struct
+ *
+ * MAC filter entries from list were slated to be added from device.
+ **/
+static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi)
+{
+ struct i40e_mac_filter *f, *ftmp;
+
+ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
+ if (!f->changed && f->counter)
+ f->changed = true;
+ }
+}
+
+/**
+ * i40e_cleanup_add_list - Deletes the element from add list and release
+ * memory
+ * @add_list: Pointer to list which contains MAC filter entries
+ **/
+static void i40e_cleanup_add_list(struct list_head *add_list)
+{
+ struct i40e_mac_filter *f, *ftmp;
+
+ list_for_each_entry_safe(f, ftmp, add_list, list) {
+ list_del(&f->list);
+ kfree(f);
+ }
+}
+
+/**
* i40e_sync_vsi_filters - Update the VSI filter list to the HW
* @vsi: ptr to the VSI
+ * @grab_rtnl: whether RTNL needs to be grabbed
*
* Push any outstanding VSI filter changes through the AdminQ.
*
* Returns 0 or error value
**/
-int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
+int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl)
{
- struct i40e_mac_filter *f, *ftmp;
+ struct list_head tmp_del_list, tmp_add_list;
+ struct i40e_mac_filter *f, *ftmp, *fclone;
bool promisc_forced_on = false;
bool add_happened = false;
int filter_list_len = 0;
u32 changed_flags = 0;
+ bool err_cond = false;
i40e_status ret = 0;
struct i40e_pf *pf;
int num_add = 0;
@@ -1783,17 +1886,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
vsi->current_netdev_flags = vsi->netdev->flags;
}
+ INIT_LIST_HEAD(&tmp_del_list);
+ INIT_LIST_HEAD(&tmp_add_list);
+
if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) {
vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED;
- filter_list_len = pf->hw.aq.asq_buf_size /
- sizeof(struct i40e_aqc_remove_macvlan_element_data);
- del_list = kcalloc(filter_list_len,
- sizeof(struct i40e_aqc_remove_macvlan_element_data),
- GFP_KERNEL);
- if (!del_list)
- return -ENOMEM;
-
+ spin_lock_bh(&vsi->mac_filter_list_lock);
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
if (!f->changed)
continue;
@@ -1801,6 +1900,58 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
if (f->counter != 0)
continue;
f->changed = false;
+
+ /* Move the element into temporary del_list */
+ list_move_tail(&f->list, &tmp_del_list);
+ }
+
+ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
+ if (!f->changed)
+ continue;
+
+ if (f->counter == 0)
+ continue;
+ f->changed = false;
+
+ /* Clone MAC filter entry and add into temporary list */
+ fclone = i40e_mac_filter_entry_clone(f);
+ if (!fclone) {
+ err_cond = true;
+ break;
+ }
+ list_add_tail(&fclone->list, &tmp_add_list);
+ }
+
+ /* if failed to clone MAC filter entry - undo */
+ if (err_cond) {
+ i40e_undo_del_filter_entries(vsi, &tmp_del_list);
+ i40e_undo_add_filter_entries(vsi);
+ }
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+
+ if (err_cond)
+ i40e_cleanup_add_list(&tmp_add_list);
+ }
+
+ /* Now process 'del_list' outside the lock */
+ if (!list_empty(&tmp_del_list)) {
+ filter_list_len = pf->hw.aq.asq_buf_size /
+ sizeof(struct i40e_aqc_remove_macvlan_element_data);
+ del_list = kcalloc(filter_list_len,
+ sizeof(struct i40e_aqc_remove_macvlan_element_data),
+ GFP_KERNEL);
+ if (!del_list) {
+ i40e_cleanup_add_list(&tmp_add_list);
+
+ /* Undo VSI's MAC filter entry element updates */
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+ i40e_undo_del_filter_entries(vsi, &tmp_del_list);
+ i40e_undo_add_filter_entries(vsi);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+ return -ENOMEM;
+ }
+
+ list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) {
cmd_flags = 0;
/* add to delete list */
@@ -1813,10 +1964,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
del_list[num_del].flags = cmd_flags;
num_del++;
- /* unlink from filter list */
- list_del(&f->list);
- kfree(f);
-
/* flush a full buffer */
if (num_del == filter_list_len) {
ret = i40e_aq_remove_macvlan(&pf->hw,
@@ -1827,12 +1974,18 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
memset(del_list, 0, sizeof(*del_list));
if (ret && aq_err != I40E_AQ_RC_ENOENT)
- dev_info(&pf->pdev->dev,
- "ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n",
- i40e_stat_str(&pf->hw, ret),
- i40e_aq_str(&pf->hw, aq_err));
+ dev_err(&pf->pdev->dev,
+ "ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n",
+ i40e_stat_str(&pf->hw, ret),
+ i40e_aq_str(&pf->hw, aq_err));
}
+ /* Release memory for MAC filter entries which were
+ * synced up with HW.
+ */
+ list_del(&f->list);
+ kfree(f);
}
+
if (num_del) {
ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,
del_list, num_del, NULL);
@@ -1848,6 +2001,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
kfree(del_list);
del_list = NULL;
+ }
+
+ if (!list_empty(&tmp_add_list)) {
/* do all the adds now */
filter_list_len = pf->hw.aq.asq_buf_size /
@@ -1855,16 +2011,19 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
add_list = kcalloc(filter_list_len,
sizeof(struct i40e_aqc_add_macvlan_element_data),
GFP_KERNEL);
- if (!add_list)
+ if (!add_list) {
+ /* Purge element from temporary lists */
+ i40e_cleanup_add_list(&tmp_add_list);
+
+ /* Undo add filter entries from VSI MAC filter list */
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+ i40e_undo_add_filter_entries(vsi);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
return -ENOMEM;
+ }
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
- if (!f->changed)
- continue;
+ list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {
- if (f->counter == 0)
- continue;
- f->changed = false;
add_happened = true;
cmd_flags = 0;
@@ -1891,7 +2050,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
break;
memset(add_list, 0, sizeof(*add_list));
}
+ /* Entries from tmp_add_list were cloned from MAC
+ * filter list, hence clean those cloned entries
+ */
+ list_del(&f->list);
+ kfree(f);
}
+
if (num_add) {
ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
add_list, num_add, NULL);
@@ -1920,6 +2085,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
/* check for changes in promiscuous modes */
if (changed_flags & IFF_ALLMULTI) {
bool cur_multipromisc;
+
cur_multipromisc = !!(vsi->current_netdev_flags & IFF_ALLMULTI);
ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw,
vsi->seid,
@@ -1934,6 +2100,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
}
if ((changed_flags & IFF_PROMISC) || promisc_forced_on) {
bool cur_promisc;
+
cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) ||
test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
&vsi->state));
@@ -1945,7 +2112,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
*/
if (pf->cur_promisc != cur_promisc) {
pf->cur_promisc = cur_promisc;
- i40e_do_reset_safe(pf,
+ if (grab_rtnl)
+ i40e_do_reset_safe(pf,
+ BIT(__I40E_PF_RESET_REQUESTED));
+ else
+ i40e_do_reset(pf,
BIT(__I40E_PF_RESET_REQUESTED));
}
} else {
@@ -1996,7 +2167,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
for (v = 0; v < pf->num_alloc_vsi; v++) {
if (pf->vsi[v] &&
(pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED))
- i40e_sync_vsi_filters(pf->vsi[v]);
+ i40e_sync_vsi_filters(pf->vsi[v], true);
}
}
@@ -2137,6 +2308,9 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
is_vf = (vsi->type == I40E_VSI_SRIOV);
is_netdev = !!(vsi->netdev);
+ /* Locked once because all functions invoked below iterates list*/
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+
if (is_netdev) {
add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid,
is_vf, is_netdev);
@@ -2144,6 +2318,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
dev_info(&vsi->back->pdev->dev,
"Could not add vlan filter %d for %pM\n",
vid, vsi->netdev->dev_addr);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
return -ENOMEM;
}
}
@@ -2154,6 +2329,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
dev_info(&vsi->back->pdev->dev,
"Could not add vlan filter %d for %pM\n",
vid, f->macaddr);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
return -ENOMEM;
}
}
@@ -2175,6 +2351,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
dev_info(&vsi->back->pdev->dev,
"Could not add filter 0 for %pM\n",
vsi->netdev->dev_addr);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
return -ENOMEM;
}
}
@@ -2183,27 +2360,33 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
/* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */
if (vid > 0 && !vsi->info.pvid) {
list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if (i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY,
- is_vf, is_netdev)) {
- i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY,
- is_vf, is_netdev);
- add_f = i40e_add_filter(vsi, f->macaddr,
- 0, is_vf, is_netdev);
- if (!add_f) {
- dev_info(&vsi->back->pdev->dev,
- "Could not add filter 0 for %pM\n",
- f->macaddr);
- return -ENOMEM;
- }
+ if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY,
+ is_vf, is_netdev))
+ continue;
+ i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY,
+ is_vf, is_netdev);
+ add_f = i40e_add_filter(vsi, f->macaddr,
+ 0, is_vf, is_netdev);
+ if (!add_f) {
+ dev_info(&vsi->back->pdev->dev,
+ "Could not add filter 0 for %pM\n",
+ f->macaddr);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+ return -ENOMEM;
}
}
}
+ /* Make sure to release before sync_vsi_filter because that
+ * function will lock/unlock as necessary
+ */
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+
if (test_bit(__I40E_DOWN, &vsi->back->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
return 0;
- return i40e_sync_vsi_filters(vsi);
+ return i40e_sync_vsi_filters(vsi, false);
}
/**
@@ -2223,6 +2406,9 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
is_vf = (vsi->type == I40E_VSI_SRIOV);
is_netdev = !!(netdev);
+ /* Locked once because all functions invoked below iterates list */
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+
if (is_netdev)
i40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev);
@@ -2253,6 +2439,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
dev_info(&vsi->back->pdev->dev,
"Could not add filter %d for %pM\n",
I40E_VLAN_ANY, netdev->dev_addr);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
return -ENOMEM;
}
}
@@ -2261,21 +2448,27 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
list_for_each_entry(f, &vsi->mac_filter_list, list) {
i40e_del_filter(vsi, f->macaddr, 0, is_vf, is_netdev);
add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY,
- is_vf, is_netdev);
+ is_vf, is_netdev);
if (!add_f) {
dev_info(&vsi->back->pdev->dev,
"Could not add filter %d for %pM\n",
I40E_VLAN_ANY, f->macaddr);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
return -ENOMEM;
}
}
}
+ /* Make sure to release before sync_vsi_filter because that
+ * function with lock/unlock as necessary
+ */
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+
if (test_bit(__I40E_DOWN, &vsi->back->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
return 0;
- return i40e_sync_vsi_filters(vsi);
+ return i40e_sync_vsi_filters(vsi, false);
}
/**
@@ -2609,8 +2802,6 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
wr32(hw, I40E_QTX_CTL(pf_q), qtx_ctl);
i40e_flush(hw);
- clear_bit(__I40E_HANG_CHECK_ARMED, &ring->state);
-
/* cache tail off for easier writes later */
ring->tail = hw->hw_addr + I40E_QTX_TAIL(pf_q);
@@ -2882,11 +3073,9 @@ static int i40e_vsi_configure(struct i40e_vsi *vsi)
static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
- struct i40e_q_vector *q_vector;
struct i40e_hw *hw = &pf->hw;
u16 vector;
int i, q;
- u32 val;
u32 qp;
/* The interrupt indexing is offset by 1 in the PFINT_ITRn
@@ -2896,7 +3085,9 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
qp = vsi->base_queue;
vector = vsi->base_vector;
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
- q_vector = vsi->q_vectors[i];
+ struct i40e_q_vector *q_vector = vsi->q_vectors[i];
+
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
q_vector->rx.latency_range = I40E_LOW_LATENCY;
wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1),
@@ -2905,10 +3096,14 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
q_vector->tx.latency_range = I40E_LOW_LATENCY;
wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, vector - 1),
q_vector->tx.itr);
+ wr32(hw, I40E_PFINT_RATEN(vector - 1),
+ INTRL_USEC_TO_REG(vsi->int_rate_limit));
/* Linked list for the queuepairs assigned to this vector */
wr32(hw, I40E_PFINT_LNKLSTN(vector - 1), qp);
for (q = 0; q < q_vector->num_ringpairs; q++) {
+ u32 val;
+
val = I40E_QINT_RQCTL_CAUSE_ENA_MASK |
(I40E_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) |
(vector << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
@@ -2988,6 +3183,7 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi)
u32 val;
/* set the ITR configuration */
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
q_vector->rx.latency_range = I40E_LOW_LATENCY;
wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.itr);
@@ -3046,24 +3242,6 @@ void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf)
}
/**
- * i40e_irq_dynamic_enable - Enable default interrupt generation settings
- * @vsi: pointer to a vsi
- * @vector: enable a particular Hw Interrupt vector
- **/
-void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
-{
- struct i40e_pf *pf = vsi->back;
- struct i40e_hw *hw = &pf->hw;
- u32 val;
-
- val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
- (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
- wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val);
- /* skip the flush */
-}
-
-/**
* i40e_irq_dynamic_disable - Disable default interrupt generation settings
* @vsi: pointer to a vsi
* @vector: disable a particular Hw Interrupt vector
@@ -3091,7 +3269,7 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data)
if (!q_vector->tx.ring && !q_vector->rx.ring)
return IRQ_HANDLED;
- napi_schedule(&q_vector->napi);
+ napi_schedule_irqoff(&q_vector->napi);
return IRQ_HANDLED;
}
@@ -3136,8 +3314,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
q_vector);
if (err) {
dev_info(&pf->pdev->dev,
- "%s: request_irq failed, error: %d\n",
- __func__, err);
+ "MSIX request_irq failed, error: %d\n", err);
goto free_queue_irqs;
}
/* assign the mask for this irq */
@@ -3202,8 +3379,7 @@ static int i40e_vsi_enable_irq(struct i40e_vsi *vsi)
int i;
if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
- for (i = vsi->base_vector;
- i < (vsi->num_q_vectors + vsi->base_vector); i++)
+ for (i = 0; i < vsi->num_q_vectors; i++)
i40e_irq_dynamic_enable(vsi, i);
} else {
i40e_irq_dynamic_enable_icr0(pf);
@@ -3262,9 +3438,12 @@ static irqreturn_t i40e_intr(int irq, void *data)
/* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK) {
+ struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+ struct i40e_q_vector *q_vector = vsi->q_vectors[0];
/* temporarily disable queue cause for NAPI processing */
u32 qval = rd32(hw, I40E_QINT_RQCTL(0));
+
qval &= ~I40E_QINT_RQCTL_CAUSE_ENA_MASK;
wr32(hw, I40E_QINT_RQCTL(0), qval);
@@ -3273,7 +3452,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
wr32(hw, I40E_QINT_TQCTL(0), qval);
if (!test_bit(__I40E_DOWN, &pf->state))
- napi_schedule(&pf->vsi[pf->lan_vsi]->q_vectors[0]->napi);
+ napi_schedule_irqoff(&q_vector->napi);
}
if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
@@ -3434,10 +3613,9 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget)
i += tx_ring->count;
tx_ring->next_to_clean = i;
- if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
- i40e_irq_dynamic_enable(vsi,
- tx_ring->q_vector->v_idx + vsi->base_vector);
- }
+ if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED)
+ i40e_irq_dynamic_enable(vsi, tx_ring->q_vector->v_idx);
+
return budget > 0;
}
@@ -3575,14 +3753,12 @@ static void i40e_netpoll(struct net_device *netdev)
if (test_bit(__I40E_DOWN, &vsi->state))
return;
- pf->flags |= I40E_FLAG_IN_NETPOLL;
if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
for (i = 0; i < vsi->num_q_vectors; i++)
i40e_msix_clean_rings(0, vsi->q_vectors[i]);
} else {
i40e_intr(pf->pdev->irq, netdev);
}
- pf->flags &= ~I40E_FLAG_IN_NETPOLL;
}
#endif
@@ -3663,9 +3839,8 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
ret = i40e_pf_txq_wait(pf, pf_q, enable);
if (ret) {
dev_info(&pf->pdev->dev,
- "%s: VSI seid %d Tx ring %d %sable timeout\n",
- __func__, vsi->seid, pf_q,
- (enable ? "en" : "dis"));
+ "VSI seid %d Tx ring %d %sable timeout\n",
+ vsi->seid, pf_q, (enable ? "en" : "dis"));
break;
}
}
@@ -3741,9 +3916,8 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
ret = i40e_pf_rxq_wait(pf, pf_q, enable);
if (ret) {
dev_info(&pf->pdev->dev,
- "%s: VSI seid %d Rx ring %d %sable timeout\n",
- __func__, vsi->seid, pf_q,
- (enable ? "en" : "dis"));
+ "VSI seid %d Rx ring %d %sable timeout\n",
+ vsi->seid, pf_q, (enable ? "en" : "dis"));
break;
}
}
@@ -4038,17 +4212,15 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi)
if ((test_bit(__I40E_PORT_TX_SUSPENDED, &vsi->back->state)) &&
vsi->type == I40E_VSI_FCOE) {
dev_dbg(&vsi->back->pdev->dev,
- "%s: VSI seid %d skipping FCoE VSI disable\n",
- __func__, vsi->seid);
+ "VSI seid %d skipping FCoE VSI disable\n", vsi->seid);
return;
}
set_bit(__I40E_NEEDS_RESTART, &vsi->state);
- if (vsi->netdev && netif_running(vsi->netdev)) {
+ if (vsi->netdev && netif_running(vsi->netdev))
vsi->netdev->netdev_ops->ndo_stop(vsi->netdev);
- } else {
+ else
i40e_vsi_close(vsi);
- }
}
/**
@@ -4113,8 +4285,8 @@ static int i40e_vsi_wait_txq_disabled(struct i40e_vsi *vsi)
ret = i40e_pf_txq_wait(pf, pf_q, false);
if (ret) {
dev_info(&pf->pdev->dev,
- "%s: VSI seid %d Tx ring %d disable timeout\n",
- __func__, vsi->seid, pf_q);
+ "VSI seid %d Tx ring %d disable timeout\n",
+ vsi->seid, pf_q);
return ret;
}
}
@@ -4146,6 +4318,108 @@ static int i40e_pf_wait_txq_disabled(struct i40e_pf *pf)
}
#endif
+
+/**
+ * i40e_detect_recover_hung_queue - Function to detect and recover hung_queue
+ * @q_idx: TX queue number
+ * @vsi: Pointer to VSI struct
+ *
+ * This function checks specified queue for given VSI. Detects hung condition.
+ * Sets hung bit since it is two step process. Before next run of service task
+ * if napi_poll runs, it reset 'hung' bit for respective q_vector. If not,
+ * hung condition remain unchanged and during subsequent run, this function
+ * issues SW interrupt to recover from hung condition.
+ **/
+static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)
+{
+ struct i40e_ring *tx_ring = NULL;
+ struct i40e_pf *pf;
+ u32 head, val, tx_pending;
+ int i;
+
+ pf = vsi->back;
+
+ /* now that we have an index, find the tx_ring struct */
+ for (i = 0; i < vsi->num_queue_pairs; i++) {
+ if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) {
+ if (q_idx == vsi->tx_rings[i]->queue_index) {
+ tx_ring = vsi->tx_rings[i];
+ break;
+ }
+ }
+ }
+
+ if (!tx_ring)
+ return;
+
+ /* Read interrupt register */
+ if (pf->flags & I40E_FLAG_MSIX_ENABLED)
+ val = rd32(&pf->hw,
+ I40E_PFINT_DYN_CTLN(tx_ring->q_vector->v_idx +
+ tx_ring->vsi->base_vector - 1));
+ else
+ val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);
+
+ head = i40e_get_head(tx_ring);
+
+ tx_pending = i40e_get_tx_pending(tx_ring);
+
+ /* Interrupts are disabled and TX pending is non-zero,
+ * trigger the SW interrupt (don't wait). Worst case
+ * there will be one extra interrupt which may result
+ * into not cleaning any queues because queues are cleaned.
+ */
+ if (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)))
+ i40e_force_wb(vsi, tx_ring->q_vector);
+}
+
+/**
+ * i40e_detect_recover_hung - Function to detect and recover hung_queues
+ * @pf: pointer to PF struct
+ *
+ * LAN VSI has netdev and netdev has TX queues. This function is to check
+ * each of those TX queues if they are hung, trigger recovery by issuing
+ * SW interrupt.
+ **/
+static void i40e_detect_recover_hung(struct i40e_pf *pf)
+{
+ struct net_device *netdev;
+ struct i40e_vsi *vsi;
+ int i;
+
+ /* Only for LAN VSI */
+ vsi = pf->vsi[pf->lan_vsi];
+
+ if (!vsi)
+ return;
+
+ /* Make sure, VSI state is not DOWN/RECOVERY_PENDING */
+ if (test_bit(__I40E_DOWN, &vsi->back->state) ||
+ test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+ return;
+
+ /* Make sure type is MAIN VSI */
+ if (vsi->type != I40E_VSI_MAIN)
+ return;
+
+ netdev = vsi->netdev;
+ if (!netdev)
+ return;
+
+ /* Bail out if netif_carrier is not OK */
+ if (!netif_carrier_ok(netdev))
+ return;
+
+ /* Go thru' TX queues for netdev */
+ for (i = 0; i < netdev->num_tx_queues; i++) {
+ struct netdev_queue *q;
+
+ q = netdev_get_tx_queue(netdev, i);
+ if (q)
+ i40e_detect_recover_hung_queue(i, vsi);
+ }
+}
+
/**
* i40e_get_iscsi_tc_map - Return TC map for iSCSI APP
* @pf: pointer to PF
@@ -4745,11 +5019,14 @@ out:
* i40e_print_link_message - print link up or down
* @vsi: the VSI for which link needs a message
*/
-static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
+void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
{
- char speed[SPEED_SIZE] = "Unknown";
- char fc[FC_SIZE] = "RX/TX";
+ char *speed = "Unknown";
+ char *fc = "Unknown";
+ if (vsi->current_isup == isup)
+ return;
+ vsi->current_isup = isup;
if (!isup) {
netdev_info(vsi->netdev, "NIC Link is Down\n");
return;
@@ -4766,19 +5043,19 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
switch (vsi->back->hw.phy.link_info.link_speed) {
case I40E_LINK_SPEED_40GB:
- strlcpy(speed, "40 Gbps", SPEED_SIZE);
+ speed = "40 G";
break;
case I40E_LINK_SPEED_20GB:
- strncpy(speed, "20 Gbps", SPEED_SIZE);
+ speed = "20 G";
break;
case I40E_LINK_SPEED_10GB:
- strlcpy(speed, "10 Gbps", SPEED_SIZE);
+ speed = "10 G";
break;
case I40E_LINK_SPEED_1GB:
- strlcpy(speed, "1000 Mbps", SPEED_SIZE);
+ speed = "1000 M";
break;
case I40E_LINK_SPEED_100MB:
- strncpy(speed, "100 Mbps", SPEED_SIZE);
+ speed = "100 M";
break;
default:
break;
@@ -4786,20 +5063,20 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
switch (vsi->back->hw.fc.current_mode) {
case I40E_FC_FULL:
- strlcpy(fc, "RX/TX", FC_SIZE);
+ fc = "RX/TX";
break;
case I40E_FC_TX_PAUSE:
- strlcpy(fc, "TX", FC_SIZE);
+ fc = "TX";
break;
case I40E_FC_RX_PAUSE:
- strlcpy(fc, "RX", FC_SIZE);
+ fc = "RX";
break;
default:
- strlcpy(fc, "None", FC_SIZE);
+ fc = "None";
break;
}
- netdev_info(vsi->netdev, "NIC Link is Up %s Full Duplex, Flow Control: %s\n",
+ netdev_info(vsi->netdev, "NIC Link is Up %sbps Full Duplex, Flow Control: %s\n",
speed, fc);
}
@@ -5218,15 +5495,13 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
"VSI reinit requested\n");
for (v = 0; v < pf->num_alloc_vsi; v++) {
struct i40e_vsi *vsi = pf->vsi[v];
+
if (vsi != NULL &&
test_bit(__I40E_REINIT_REQUESTED, &vsi->state)) {
i40e_vsi_reinit_locked(pf->vsi[v]);
clear_bit(__I40E_REINIT_REQUESTED, &vsi->state);
}
}
-
- /* no further action needed, so return now */
- return;
} else if (reset_flags & BIT_ULL(__I40E_DOWN_REQUESTED)) {
int v;
@@ -5234,6 +5509,7 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
dev_info(&pf->pdev->dev, "VSI down requested\n");
for (v = 0; v < pf->num_alloc_vsi; v++) {
struct i40e_vsi *vsi = pf->vsi[v];
+
if (vsi != NULL &&
test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) {
set_bit(__I40E_DOWN, &vsi->state);
@@ -5241,13 +5517,9 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
clear_bit(__I40E_DOWN_REQUESTED, &vsi->state);
}
}
-
- /* no further action needed, so return now */
- return;
} else {
dev_info(&pf->pdev->dev,
"bad reset request 0x%08x\n", reset_flags);
- return;
}
}
@@ -5303,8 +5575,7 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf,
dev_dbg(&pf->pdev->dev, "APP Table change detected.\n");
}
- dev_dbg(&pf->pdev->dev, "%s: need_reconfig=%d\n", __func__,
- need_reconfig);
+ dev_dbg(&pf->pdev->dev, "dcb need_reconfig=%d\n", need_reconfig);
return need_reconfig;
}
@@ -5331,16 +5602,14 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
/* Ignore if event is not for Nearest Bridge */
type = ((mib->type >> I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT)
& I40E_AQ_LLDP_BRIDGE_TYPE_MASK);
- dev_dbg(&pf->pdev->dev,
- "%s: LLDP event mib bridge type 0x%x\n", __func__, type);
+ dev_dbg(&pf->pdev->dev, "LLDP event mib bridge type 0x%x\n", type);
if (type != I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE)
return ret;
/* Check MIB Type and return if event for Remote MIB update */
type = mib->type & I40E_AQ_LLDP_MIB_TYPE_MASK;
dev_dbg(&pf->pdev->dev,
- "%s: LLDP event mib type %s\n", __func__,
- type ? "remote" : "local");
+ "LLDP event mib type %s\n", type ? "remote" : "local");
if (type == I40E_AQ_LLDP_MIB_REMOTE) {
/* Update the remote cached instance and return */
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
@@ -5525,7 +5794,9 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf)
**/
void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
{
+ struct i40e_fdir_filter *filter;
u32 fcnt_prog, fcnt_avail;
+ struct hlist_node *node;
if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
return;
@@ -5554,6 +5825,18 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table now\n");
}
}
+
+ /* if hw had a problem adding a filter, delete it */
+ if (pf->fd_inv > 0) {
+ hlist_for_each_entry_safe(filter, node,
+ &pf->fdir_filter_list, fdir_node) {
+ if (filter->fd_id == pf->fd_inv) {
+ hlist_del(&filter->fdir_node);
+ kfree(filter);
+ pf->fdir_pf_active_filters--;
+ }
+ }
+ }
}
#define I40E_MIN_FD_FLUSH_INTERVAL 10
@@ -5573,49 +5856,51 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
return;
- if (time_after(jiffies, pf->fd_flush_timestamp +
- (I40E_MIN_FD_FLUSH_INTERVAL * HZ))) {
- /* If the flush is happening too quick and we have mostly
- * SB rules we should not re-enable ATR for some time.
- */
- min_flush_time = pf->fd_flush_timestamp
- + (I40E_MIN_FD_FLUSH_SB_ATR_UNSTABLE * HZ);
- fd_room = pf->fdir_pf_filter_count - pf->fdir_pf_active_filters;
+ if (!time_after(jiffies, pf->fd_flush_timestamp +
+ (I40E_MIN_FD_FLUSH_INTERVAL * HZ)))
+ return;
- if (!(time_after(jiffies, min_flush_time)) &&
- (fd_room < I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) {
- if (I40E_DEBUG_FD & pf->hw.debug_mask)
- dev_info(&pf->pdev->dev, "ATR disabled, not enough FD filter space.\n");
- disable_atr = true;
- }
+ /* If the flush is happening too quick and we have mostly SB rules we
+ * should not re-enable ATR for some time.
+ */
+ min_flush_time = pf->fd_flush_timestamp +
+ (I40E_MIN_FD_FLUSH_SB_ATR_UNSTABLE * HZ);
+ fd_room = pf->fdir_pf_filter_count - pf->fdir_pf_active_filters;
- pf->fd_flush_timestamp = jiffies;
- pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
- /* flush all filters */
- wr32(&pf->hw, I40E_PFQF_CTL_1,
- I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
- i40e_flush(&pf->hw);
- pf->fd_flush_cnt++;
- pf->fd_add_err = 0;
- do {
- /* Check FD flush status every 5-6msec */
- usleep_range(5000, 6000);
- reg = rd32(&pf->hw, I40E_PFQF_CTL_1);
- if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK))
- break;
- } while (flush_wait_retry--);
- if (reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK) {
- dev_warn(&pf->pdev->dev, "FD table did not flush, needs more time\n");
- } else {
- /* replay sideband filters */
- i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]);
- if (!disable_atr)
- pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
- clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
- if (I40E_DEBUG_FD & pf->hw.debug_mask)
- dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
- }
+ if (!(time_after(jiffies, min_flush_time)) &&
+ (fd_room < I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) {
+ if (I40E_DEBUG_FD & pf->hw.debug_mask)
+ dev_info(&pf->pdev->dev, "ATR disabled, not enough FD filter space.\n");
+ disable_atr = true;
+ }
+
+ pf->fd_flush_timestamp = jiffies;
+ pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+ /* flush all filters */
+ wr32(&pf->hw, I40E_PFQF_CTL_1,
+ I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
+ i40e_flush(&pf->hw);
+ pf->fd_flush_cnt++;
+ pf->fd_add_err = 0;
+ do {
+ /* Check FD flush status every 5-6msec */
+ usleep_range(5000, 6000);
+ reg = rd32(&pf->hw, I40E_PFQF_CTL_1);
+ if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK))
+ break;
+ } while (flush_wait_retry--);
+ if (reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK) {
+ dev_warn(&pf->pdev->dev, "FD table did not flush, needs more time\n");
+ } else {
+ /* replay sideband filters */
+ i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]);
+ if (!disable_atr)
+ pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
+ clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
+ if (I40E_DEBUG_FD & pf->hw.debug_mask)
+ dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
}
+
}
/**
@@ -5723,15 +6008,23 @@ static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up)
**/
static void i40e_link_event(struct i40e_pf *pf)
{
- bool new_link, old_link;
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
u8 new_link_speed, old_link_speed;
+ i40e_status status;
+ bool new_link, old_link;
/* set this to force the get_link_status call to refresh state */
pf->hw.phy.get_link_info = true;
old_link = (pf->hw.phy.link_info_old.link_info & I40E_AQ_LINK_UP);
- new_link = i40e_get_link_status(&pf->hw);
+
+ status = i40e_get_link_status(&pf->hw, &new_link);
+ if (status) {
+ dev_dbg(&pf->pdev->dev, "couldn't get link state, status: %d\n",
+ status);
+ return;
+ }
+
old_link_speed = pf->hw.phy.link_info_old.link_speed;
new_link_speed = pf->hw.phy.link_info.link_speed;
@@ -5760,68 +6053,6 @@ static void i40e_link_event(struct i40e_pf *pf)
}
/**
- * i40e_check_hang_subtask - Check for hung queues and dropped interrupts
- * @pf: board private structure
- *
- * Set the per-queue flags to request a check for stuck queues in the irq
- * clean functions, then force interrupts to be sure the irq clean is called.
- **/
-static void i40e_check_hang_subtask(struct i40e_pf *pf)
-{
- int i, v;
-
- /* If we're down or resetting, just bail */
- if (test_bit(__I40E_DOWN, &pf->state) ||
- test_bit(__I40E_CONFIG_BUSY, &pf->state))
- return;
-
- /* for each VSI/netdev
- * for each Tx queue
- * set the check flag
- * for each q_vector
- * force an interrupt
- */
- for (v = 0; v < pf->num_alloc_vsi; v++) {
- struct i40e_vsi *vsi = pf->vsi[v];
- int armed = 0;
-
- if (!pf->vsi[v] ||
- test_bit(__I40E_DOWN, &vsi->state) ||
- (vsi->netdev && !netif_carrier_ok(vsi->netdev)))
- continue;
-
- for (i = 0; i < vsi->num_queue_pairs; i++) {
- set_check_for_tx_hang(vsi->tx_rings[i]);
- if (test_bit(__I40E_HANG_CHECK_ARMED,
- &vsi->tx_rings[i]->state))
- armed++;
- }
-
- if (armed) {
- if (!(pf->flags & I40E_FLAG_MSIX_ENABLED)) {
- wr32(&vsi->back->hw, I40E_PFINT_DYN_CTL0,
- (I40E_PFINT_DYN_CTL0_INTENA_MASK |
- I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK |
- I40E_PFINT_DYN_CTL0_ITR_INDX_MASK |
- I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK |
- I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK));
- } else {
- u16 vec = vsi->base_vector - 1;
- u32 val = (I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
- I40E_PFINT_DYN_CTLN_ITR_INDX_MASK |
- I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK |
- I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK);
- for (i = 0; i < vsi->num_q_vectors; i++, vec++)
- wr32(&vsi->back->hw,
- I40E_PFINT_DYN_CTLN(vec), val);
- }
- i40e_flush(&vsi->back->hw);
- }
- }
-}
-
-/**
* i40e_watchdog_subtask - periodic checks not using event driven response
* @pf: board private structure
**/
@@ -5840,8 +6071,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
return;
pf->service_timer_previous = jiffies;
- i40e_check_hang_subtask(pf);
- i40e_link_event(pf);
+ if (pf->flags & I40E_FLAG_LINK_POLLING_ENABLED)
+ i40e_link_event(pf);
/* Update the stats for active netdevs so the network stack
* can look at updated numbers whenever it cares to
@@ -5850,10 +6081,12 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
if (pf->vsi[i] && pf->vsi[i]->netdev)
i40e_update_stats(pf->vsi[i]);
- /* Update the stats for the active switching components */
- for (i = 0; i < I40E_MAX_VEB; i++)
- if (pf->veb[i])
- i40e_update_veb_stats(pf->veb[i]);
+ if (pf->flags & I40E_FLAG_VEB_STATS_ENABLED) {
+ /* Update the stats for the active switching components */
+ for (i = 0; i < I40E_MAX_VEB; i++)
+ if (pf->veb[i])
+ i40e_update_veb_stats(pf->veb[i]);
+ }
i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]);
}
@@ -6164,8 +6397,9 @@ static void i40e_config_bridge_mode(struct i40e_veb *veb)
{
struct i40e_pf *pf = veb->pf;
- dev_info(&pf->pdev->dev, "enabling bridge mode: %s\n",
- veb->bridge_mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+ if (pf->hw.debug_mask & I40E_DEBUG_LAN)
+ dev_info(&pf->pdev->dev, "enabling bridge mode: %s\n",
+ veb->bridge_mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
if (veb->bridge_mode & BRIDGE_MODE_VEPA)
i40e_disable_pf_switch_lb(pf);
else
@@ -6232,6 +6466,7 @@ static int i40e_reconstitute_veb(struct i40e_veb *veb)
if (pf->vsi[v]->veb_idx == veb->idx) {
struct i40e_vsi *vsi = pf->vsi[v];
+
vsi->uplink_seid = veb->seid;
ret = i40e_add_vsi(vsi);
if (ret) {
@@ -6296,12 +6531,6 @@ static int i40e_get_capabilities(struct i40e_pf *pf)
}
} while (err);
- if (((pf->hw.aq.fw_maj_ver == 2) && (pf->hw.aq.fw_min_ver < 22)) ||
- (pf->hw.aq.fw_maj_ver < 2)) {
- pf->hw.func_caps.num_msix_vectors++;
- pf->hw.func_caps.num_msix_vectors_vf++;
- }
-
if (pf->hw.debug_mask & I40E_DEBUG_USER)
dev_info(&pf->pdev->dev,
"pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n",
@@ -6514,9 +6743,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
}
#endif /* CONFIG_I40E_DCB */
#ifdef I40E_FCOE
- ret = i40e_init_pf_fcoe(pf);
- if (ret)
- dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", ret);
+ i40e_init_pf_fcoe(pf);
#endif
/* do basic switch setup */
@@ -6538,9 +6765,9 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
/* make sure our flow control settings are restored */
ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true);
if (ret)
- dev_info(&pf->pdev->dev, "set fc fail, err %s aq_err %s\n",
- i40e_stat_str(&pf->hw, ret),
- i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+ dev_dbg(&pf->pdev->dev, "setting flow control: ret = %s last_status = %s\n",
+ i40e_stat_str(&pf->hw, ret),
+ i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
/* Rebuild the VSIs and VEBs that existed before reset.
* They are still in our local switch element arrays, so only
@@ -6610,6 +6837,15 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
if (pf->flags & I40E_FLAG_MSIX_ENABLED)
ret = i40e_setup_misc_vector(pf);
+ /* Add a filter to drop all Flow control frames from any VSI from being
+ * transmitted. By doing so we stop a malicious VF from sending out
+ * PAUSE or PFC frames and potentially controlling traffic for other
+ * PF/VF VSIs.
+ * The FW can still send Flow control frames if enabled.
+ */
+ i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw,
+ pf->main_vsi_seid);
+
/* restart the VSIs that were rebuilt and running before the reset */
i40e_pf_unquiesce_all_vsi(pf);
@@ -6808,6 +7044,7 @@ static void i40e_service_task(struct work_struct *work)
return;
}
+ i40e_detect_recover_hung(pf);
i40e_reset_subtask(pf);
i40e_handle_mdd_event(pf);
i40e_vc_process_vflr_event(pf);
@@ -6991,6 +7228,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
vsi->idx = vsi_idx;
vsi->rx_itr_setting = pf->rx_itr_default;
vsi->tx_itr_setting = pf->tx_itr_default;
+ vsi->int_rate_limit = 0;
vsi->rss_table_size = (vsi->type == I40E_VSI_MAIN) ?
pf->rss_table_size : 64;
vsi->netdev_registered = false;
@@ -7009,6 +7247,8 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
/* Setup default MSIX irq handler for VSI */
i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);
+ /* Initialize VSI lock */
+ spin_lock_init(&vsi->mac_filter_list_lock);
pf->vsi[vsi_idx] = vsi;
ret = vsi_idx;
goto unlock_pf;
@@ -7566,7 +7806,7 @@ static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed)
"Cannot set RSS key, err %s aq_err %s\n",
i40e_stat_str(&pf->hw, ret),
i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
- return ret;
+ goto config_rss_aq_out;
}
if (vsi->type == I40E_VSI_MAIN)
@@ -7580,6 +7820,8 @@ static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed)
i40e_stat_str(&pf->hw, ret),
i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+config_rss_aq_out:
+ kfree(rss_lut);
return ret;
}
@@ -7854,6 +8096,7 @@ static int i40e_sw_init(struct i40e_pf *pf)
/* Set default capability flags */
pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
I40E_FLAG_MSI_ENABLED |
+ I40E_FLAG_LINK_POLLING_ENABLED |
I40E_FLAG_MSIX_ENABLED;
if (iommu_present(&pci_bus_type))
@@ -7896,12 +8139,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
(pf->hw.func_caps.fd_filters_best_effort > 0)) {
pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
pf->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE;
- if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) {
- pf->flags |= I40E_FLAG_FD_SB_ENABLED;
- } else {
+ if (pf->flags & I40E_FLAG_MFP_ENABLED &&
+ pf->hw.num_partitions > 1)
dev_info(&pf->pdev->dev,
"Flow Director Sideband mode Disabled in MFP mode\n");
- }
+ else
+ pf->flags |= I40E_FLAG_FD_SB_ENABLED;
pf->fdir_pf_filter_count =
pf->hw.func_caps.fd_filters_guaranteed;
pf->hw.fdir_shared_filter_count =
@@ -7911,12 +8154,11 @@ static int i40e_sw_init(struct i40e_pf *pf)
if (pf->hw.func_caps.vmdq) {
pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI;
pf->flags |= I40E_FLAG_VMDQ_ENABLED;
+ pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf);
}
#ifdef I40E_FCOE
- err = i40e_init_pf_fcoe(pf);
- if (err)
- dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", err);
+ i40e_init_pf_fcoe(pf);
#endif /* I40E_FCOE */
#ifdef CONFIG_PCI_IOV
@@ -7940,6 +8182,9 @@ static int i40e_sw_init(struct i40e_pf *pf)
pf->lan_veb = I40E_NO_VEB;
pf->lan_vsi = I40E_NO_VSI;
+ /* By default FW has this off for performance reasons */
+ pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED;
+
/* set up queue assignment tracking */
size = sizeof(struct i40e_lump_tracking)
+ (sizeof(u16) * pf->hw.func_caps.num_tx_qp);
@@ -8119,9 +8364,6 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
pf->vxlan_ports[idx] = 0;
pf->pending_vxlan_bitmap |= BIT_ULL(idx);
pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
-
- dev_info(&pf->pdev->dev, "deleting vxlan port %d\n",
- ntohs(port));
} else {
netdev_warn(netdev, "vxlan port %d was not found, not deleting\n",
ntohs(port));
@@ -8273,13 +8515,15 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
* @seq: RTNL message seq #
* @dev: the netdev being configured
* @filter_mask: unused
+ * @nlflags: netlink flags passed in
*
* Return the mode in which the hardware bridge is operating in
* i.e VEB or VEPA.
**/
static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev,
- u32 filter_mask, int nlflags)
+ u32 __always_unused filter_mask,
+ int nlflags)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
struct i40e_vsi *vsi = np->vsi;
@@ -8308,7 +8552,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
/**
* i40e_features_check - Validate encapsulated packet conforms to limits
* @skb: skb buff
- * @netdev: This physical port's netdev
+ * @dev: This physical port's netdev
* @features: Offload features that the stack believes apply
**/
static netdev_features_t i40e_features_check(struct sk_buff *skb,
@@ -8389,6 +8633,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
netdev->hw_enc_features |= NETIF_F_IP_CSUM |
NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_GRE |
NETIF_F_TSO;
netdev->features = NETIF_F_SG |
@@ -8396,6 +8641,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
NETIF_F_SCTP_CSUM |
NETIF_F_HIGHDMA |
NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_GRE |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER |
@@ -8421,17 +8667,26 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
* default a MAC-VLAN filter that accepts any tagged packet
* which must be replaced by a normal filter.
*/
- if (!i40e_rm_default_mac_filter(vsi, mac_addr))
+ if (!i40e_rm_default_mac_filter(vsi, mac_addr)) {
+ spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_add_filter(vsi, mac_addr,
I40E_VLAN_ANY, false, true);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+ }
} else {
/* relate the VSI_VMDQ name to the VSI_MAIN name */
snprintf(netdev->name, IFNAMSIZ, "%sv%%d",
pf->vsi[pf->lan_vsi]->netdev->name);
random_ether_addr(mac_addr);
+
+ spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
}
+
+ spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_add_filter(vsi, brdcast, I40E_VLAN_ANY, false, false);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
ether_addr_copy(netdev->dev_addr, mac_addr);
ether_addr_copy(netdev->perm_addr, mac_addr);
@@ -8487,12 +8742,22 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi)
return 1;
veb = pf->veb[vsi->veb_idx];
+ if (!veb) {
+ dev_info(&pf->pdev->dev,
+ "There is no veb associated with the bridge\n");
+ return -ENOENT;
+ }
+
/* Uplink is a bridge in VEPA mode */
- if (veb && (veb->bridge_mode & BRIDGE_MODE_VEPA))
+ if (veb->bridge_mode & BRIDGE_MODE_VEPA) {
return 0;
+ } else {
+ /* Uplink is a bridge in VEB mode */
+ return 1;
+ }
- /* Uplink is a bridge in VEB mode */
- return 1;
+ /* VEPA is now default bridge, so return 0 */
+ return 0;
}
/**
@@ -8505,10 +8770,13 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi)
static int i40e_add_vsi(struct i40e_vsi *vsi)
{
int ret = -ENODEV;
- struct i40e_mac_filter *f, *ftmp;
+ u8 laa_macaddr[ETH_ALEN];
+ bool found_laa_mac_filter = false;
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
struct i40e_vsi_context ctxt;
+ struct i40e_mac_filter *f, *ftmp;
+
u8 enabled_tc = 0x1; /* TC0 enabled */
int f_count = 0;
@@ -8680,32 +8948,41 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
vsi->id = ctxt.vsi_number;
}
+ spin_lock_bh(&vsi->mac_filter_list_lock);
/* If macvlan filters already exist, force them to get loaded */
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
f->changed = true;
f_count++;
+ /* Expected to have only one MAC filter entry for LAA in list */
if (f->is_laa && vsi->type == I40E_VSI_MAIN) {
- struct i40e_aqc_remove_macvlan_element_data element;
+ ether_addr_copy(laa_macaddr, f->macaddr);
+ found_laa_mac_filter = true;
+ }
+ }
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
- memset(&element, 0, sizeof(element));
- ether_addr_copy(element.mac_addr, f->macaddr);
- element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
- ret = i40e_aq_remove_macvlan(hw, vsi->seid,
- &element, 1, NULL);
- if (ret) {
- /* some older FW has a different default */
- element.flags |=
- I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
- i40e_aq_remove_macvlan(hw, vsi->seid,
- &element, 1, NULL);
- }
+ if (found_laa_mac_filter) {
+ struct i40e_aqc_remove_macvlan_element_data element;
- i40e_aq_mac_address_write(hw,
- I40E_AQC_WRITE_TYPE_LAA_WOL,
- f->macaddr, NULL);
+ memset(&element, 0, sizeof(element));
+ ether_addr_copy(element.mac_addr, laa_macaddr);
+ element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
+ ret = i40e_aq_remove_macvlan(hw, vsi->seid,
+ &element, 1, NULL);
+ if (ret) {
+ /* some older FW has a different default */
+ element.flags |=
+ I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
+ i40e_aq_remove_macvlan(hw, vsi->seid,
+ &element, 1, NULL);
}
+
+ i40e_aq_mac_address_write(hw,
+ I40E_AQC_WRITE_TYPE_LAA_WOL,
+ laa_macaddr, NULL);
}
+
if (f_count) {
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
pf->flags |= I40E_FLAG_FILTER_SYNC;
@@ -8768,10 +9045,13 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
i40e_vsi_disable_irq(vsi);
}
+ spin_lock_bh(&vsi->mac_filter_list_lock);
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
i40e_del_filter(vsi, f->macaddr, f->vlan,
f->is_vf, f->is_netdev);
- i40e_sync_vsi_filters(vsi);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+
+ i40e_sync_vsi_filters(vsi, false);
i40e_vsi_delete(vsi);
i40e_vsi_free_q_vectors(vsi);
@@ -8996,8 +9276,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
if (veb) {
if (vsi->seid != pf->vsi[pf->lan_vsi]->seid) {
dev_info(&vsi->back->pdev->dev,
- "%s: New VSI creation error, uplink seid of LAN VSI expected.\n",
- __func__);
+ "New VSI creation error, uplink seid of LAN VSI expected.\n");
return NULL;
}
/* We come up by default in VEPA mode if SRIOV is not
@@ -9647,6 +9926,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
} else {
/* force a reset of TC and queue layout configurations */
u8 enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc;
+
pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0;
pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid;
i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc);
@@ -9670,7 +9950,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
i40e_config_rss(pf);
/* fill in link information and enable LSE reporting */
- i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
+ i40e_update_link_info(&pf->hw);
i40e_link_event(pf);
/* Initialize user-specific link properties */
@@ -9788,8 +10068,14 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
}
pf->queues_left = queues_left;
+ dev_dbg(&pf->pdev->dev,
+ "qs_avail=%d FD SB=%d lan_qs=%d lan_tc0=%d vf=%d*%d vmdq=%d*%d, remaining=%d\n",
+ pf->hw.func_caps.num_tx_qp,
+ !!(pf->flags & I40E_FLAG_FD_SB_ENABLED),
+ pf->num_lan_qps, pf->rss_size, pf->num_req_vfs, pf->num_vf_qps,
+ pf->num_vmdq_vsis, pf->num_vmdq_qps, queues_left);
#ifdef I40E_FCOE
- dev_info(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps);
+ dev_dbg(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps);
#endif
}
@@ -9857,12 +10143,19 @@ static void i40e_print_features(struct i40e_pf *pf)
}
if (pf->flags & I40E_FLAG_DCB_CAPABLE)
buf += sprintf(buf, "DCB ");
+#if IS_ENABLED(CONFIG_VXLAN)
+ buf += sprintf(buf, "VxLAN ");
+#endif
if (pf->flags & I40E_FLAG_PTP)
buf += sprintf(buf, "PTP ");
#ifdef I40E_FCOE
if (pf->flags & I40E_FLAG_FCOE_ENABLED)
buf += sprintf(buf, "FCOE ");
#endif
+ if (pf->flags & I40E_FLAG_VEB_MODE_ENABLED)
+ buf += sprintf(buf, "VEB ");
+ else
+ buf += sprintf(buf, "VEPA ");
BUG_ON(buf > (string + INFO_STRING_LEN));
dev_info(&pf->pdev->dev, "%s\n", string);
@@ -9883,14 +10176,15 @@ static void i40e_print_features(struct i40e_pf *pf)
static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct i40e_aq_get_phy_abilities_resp abilities;
- unsigned long ioremap_len;
struct i40e_pf *pf;
struct i40e_hw *hw;
static u16 pfs_found;
+ u16 wol_nvm_bits;
u16 link_status;
- int err = 0;
+ int err;
u32 len;
u32 i;
+ u8 set_fc_aq_fail;
err = pci_enable_device_mem(pdev);
if (err)
@@ -9936,15 +10230,15 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw = &pf->hw;
hw->back = pf;
- ioremap_len = min_t(unsigned long, pci_resource_len(pdev, 0),
- I40E_MAX_CSR_SPACE);
+ pf->ioremap_len = min_t(int, pci_resource_len(pdev, 0),
+ I40E_MAX_CSR_SPACE);
- hw->hw_addr = ioremap(pci_resource_start(pdev, 0), ioremap_len);
+ hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pf->ioremap_len);
if (!hw->hw_addr) {
err = -EIO;
dev_info(&pdev->dev, "ioremap(0x%04x, 0x%04x) failed: 0x%x\n",
(unsigned int)pci_resource_start(pdev, 0),
- (unsigned int)pci_resource_len(pdev, 0), err);
+ pf->ioremap_len, err);
goto err_ioremap;
}
hw->vendor_id = pdev->vendor;
@@ -10002,7 +10296,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pf->hw.fc.requested_mode = I40E_FC_NONE;
err = i40e_init_adminq(hw);
- dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
+
+ /* provide nvm, fw, api versions */
+ dev_info(&pdev->dev, "fw %d.%d.%05d api %d.%d nvm %s\n",
+ hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build,
+ hw->aq.api_maj_ver, hw->aq.api_min_ver,
+ i40e_nvm_version_str(hw));
+
if (err) {
dev_info(&pdev->dev,
"The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n");
@@ -10102,10 +10402,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&pf->service_task, i40e_service_task);
clear_bit(__I40E_SERVICE_SCHED, &pf->state);
pf->flags |= I40E_FLAG_NEED_LINK_UPDATE;
- pf->link_check_timeout = jiffies;
- /* WoL defaults to disabled */
- pf->wol_en = false;
+ /* NVM bit on means WoL disabled for the port */
+ i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);
+ if ((1 << hw->port) & wol_nvm_bits || hw->partition_id != 1)
+ pf->wol_en = false;
+ else
+ pf->wol_en = true;
device_set_wakeup_enable(&pf->pdev->dev, pf->wol_en);
/* set up the main switch operations */
@@ -10146,6 +10449,25 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err);
goto err_vsis;
}
+
+ /* Make sure flow control is set according to current settings */
+ err = i40e_set_fc(hw, &set_fc_aq_fail, true);
+ if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_GET)
+ dev_dbg(&pf->pdev->dev,
+ "Set fc with err %s aq_err %s on get_phy_cap\n",
+ i40e_stat_str(hw, err),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_SET)
+ dev_dbg(&pf->pdev->dev,
+ "Set fc with err %s aq_err %s on set_phy_config\n",
+ i40e_stat_str(hw, err),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_UPDATE)
+ dev_dbg(&pf->pdev->dev,
+ "Set fc with err %s aq_err %s on get_link_info\n",
+ i40e_stat_str(hw, err),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+
/* if FDIR VSI was set up, start it now */
for (i = 0; i < pf->num_alloc_vsi; i++) {
if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
@@ -10236,37 +10558,82 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i40e_fcoe_vsi_setup(pf);
#endif
- /* Get the negotiated link width and speed from PCI config space */
- pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, &link_status);
+#define PCI_SPEED_SIZE 8
+#define PCI_WIDTH_SIZE 8
+ /* Devices on the IOSF bus do not have this information
+ * and will report PCI Gen 1 x 1 by default so don't bother
+ * checking them.
+ */
+ if (!(pf->flags & I40E_FLAG_NO_PCI_LINK_CHECK)) {
+ char speed[PCI_SPEED_SIZE] = "Unknown";
+ char width[PCI_WIDTH_SIZE] = "Unknown";
- i40e_set_pci_config_data(hw, link_status);
+ /* Get the negotiated link width and speed from PCI config
+ * space
+ */
+ pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA,
+ &link_status);
+
+ i40e_set_pci_config_data(hw, link_status);
+
+ switch (hw->bus.speed) {
+ case i40e_bus_speed_8000:
+ strncpy(speed, "8.0", PCI_SPEED_SIZE); break;
+ case i40e_bus_speed_5000:
+ strncpy(speed, "5.0", PCI_SPEED_SIZE); break;
+ case i40e_bus_speed_2500:
+ strncpy(speed, "2.5", PCI_SPEED_SIZE); break;
+ default:
+ break;
+ }
+ switch (hw->bus.width) {
+ case i40e_bus_width_pcie_x8:
+ strncpy(width, "8", PCI_WIDTH_SIZE); break;
+ case i40e_bus_width_pcie_x4:
+ strncpy(width, "4", PCI_WIDTH_SIZE); break;
+ case i40e_bus_width_pcie_x2:
+ strncpy(width, "2", PCI_WIDTH_SIZE); break;
+ case i40e_bus_width_pcie_x1:
+ strncpy(width, "1", PCI_WIDTH_SIZE); break;
+ default:
+ break;
+ }
- dev_info(&pdev->dev, "PCI-Express: %s %s\n",
- (hw->bus.speed == i40e_bus_speed_8000 ? "Speed 8.0GT/s" :
- hw->bus.speed == i40e_bus_speed_5000 ? "Speed 5.0GT/s" :
- hw->bus.speed == i40e_bus_speed_2500 ? "Speed 2.5GT/s" :
- "Unknown"),
- (hw->bus.width == i40e_bus_width_pcie_x8 ? "Width x8" :
- hw->bus.width == i40e_bus_width_pcie_x4 ? "Width x4" :
- hw->bus.width == i40e_bus_width_pcie_x2 ? "Width x2" :
- hw->bus.width == i40e_bus_width_pcie_x1 ? "Width x1" :
- "Unknown"));
+ dev_info(&pdev->dev, "PCI-Express: Speed %sGT/s Width x%s\n",
+ speed, width);
- if (hw->bus.width < i40e_bus_width_pcie_x8 ||
- hw->bus.speed < i40e_bus_speed_8000) {
- dev_warn(&pdev->dev, "PCI-Express bandwidth available for this device may be insufficient for optimal performance.\n");
- dev_warn(&pdev->dev, "Please move the device to a different PCI-e link with more lanes and/or higher transfer rate.\n");
+ if (hw->bus.width < i40e_bus_width_pcie_x8 ||
+ hw->bus.speed < i40e_bus_speed_8000) {
+ dev_warn(&pdev->dev, "PCI-Express bandwidth available for this device may be insufficient for optimal performance.\n");
+ dev_warn(&pdev->dev, "Please move the device to a different PCI-e link with more lanes and/or higher transfer rate.\n");
+ }
}
/* get the requested speeds from the fw */
err = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, NULL);
if (err)
- dev_info(&pf->pdev->dev,
- "get phy capabilities failed, err %s aq_err %s, advertised speed settings may not be correct\n",
- i40e_stat_str(&pf->hw, err),
- i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+ dev_dbg(&pf->pdev->dev, "get requested speeds ret = %s last_status = %s\n",
+ i40e_stat_str(&pf->hw, err),
+ i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
pf->hw.phy.link_info.requested_speeds = abilities.link_speed;
+ /* get the supported phy types from the fw */
+ err = i40e_aq_get_phy_capabilities(hw, false, true, &abilities, NULL);
+ if (err)
+ dev_dbg(&pf->pdev->dev, "get supported phy types ret = %s last_status = %s\n",
+ i40e_stat_str(&pf->hw, err),
+ i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+ pf->hw.phy.phy_types = le32_to_cpu(abilities.phy_type);
+
+ /* Add a filter to drop all Flow control frames from any VSI from being
+ * transmitted. By doing so we stop a malicious VF from sending out
+ * PAUSE or PFC frames and potentially controlling traffic for other
+ * PF/VF VSIs.
+ * The FW can still send Flow control frames if enabled.
+ */
+ i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw,
+ pf->main_vsi_seid);
+
/* print a string summarizing features */
i40e_print_features(pf);
@@ -10314,6 +10681,7 @@ err_dma:
static void i40e_remove(struct pci_dev *pdev)
{
struct i40e_pf *pf = pci_get_drvdata(pdev);
+ struct i40e_hw *hw = &pf->hw;
i40e_status ret_code;
int i;
@@ -10321,6 +10689,10 @@ static void i40e_remove(struct pci_dev *pdev)
i40e_ptp_stop(pf);
+ /* Disable RSS in hw */
+ wr32(hw, I40E_PFQF_HENA(0), 0);
+ wr32(hw, I40E_PFQF_HENA(1), 0);
+
/* no more scheduling of any task */
set_bit(__I40E_DOWN, &pf->state);
del_timer_sync(&pf->service_timer);
@@ -10437,7 +10809,7 @@ static pci_ers_result_t i40e_pci_error_slot_reset(struct pci_dev *pdev)
int err;
u32 reg;
- dev_info(&pdev->dev, "%s\n", __func__);
+ dev_dbg(&pdev->dev, "%s\n", __func__);
if (pci_enable_device_mem(pdev)) {
dev_info(&pdev->dev,
"Cannot re-enable PCI device after reset.\n");
@@ -10477,13 +10849,13 @@ static void i40e_pci_error_resume(struct pci_dev *pdev)
{
struct i40e_pf *pf = pci_get_drvdata(pdev);
- dev_info(&pdev->dev, "%s\n", __func__);
+ dev_dbg(&pdev->dev, "%s\n", __func__);
if (test_bit(__I40E_SUSPENDED, &pf->state))
return;
rtnl_lock();
i40e_handle_reset_warning(pf);
- rtnl_lock();
+ rtnl_unlock();
}
/**
@@ -10569,9 +10941,7 @@ static int i40e_resume(struct pci_dev *pdev)
err = pci_enable_device_mem(pdev);
if (err) {
- dev_err(&pdev->dev,
- "%s: Cannot enable PCI device from suspend\n",
- __func__);
+ dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n");
return err;
}
pci_set_master(pdev);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 9b83abc0e774..6100cdd9ad13 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -290,9 +290,18 @@ static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
u16 *data)
{
- if (hw->mac.type == I40E_MAC_X722)
- return i40e_read_nvm_word_aq(hw, offset, data);
- return i40e_read_nvm_word_srctl(hw, offset, data);
+ enum i40e_status_code ret_code = 0;
+
+ if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
+ ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+ if (!ret_code) {
+ ret_code = i40e_read_nvm_word_aq(hw, offset, data);
+ i40e_release_nvm(hw);
+ }
+ } else {
+ ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
+ }
+ return ret_code;
}
/**
@@ -397,9 +406,19 @@ read_nvm_buffer_aq_exit:
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
u16 *words, u16 *data)
{
- if (hw->mac.type == I40E_MAC_X722)
- return i40e_read_nvm_buffer_aq(hw, offset, words, data);
- return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
+ enum i40e_status_code ret_code = 0;
+
+ if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
+ ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+ if (!ret_code) {
+ ret_code = i40e_read_nvm_buffer_aq(hw, offset, words,
+ data);
+ i40e_release_nvm(hw);
+ }
+ } else {
+ ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
+ }
+ return ret_code;
}
/**
@@ -418,6 +437,10 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
bool last_command)
{
i40e_status ret_code = I40E_ERR_NVM;
+ struct i40e_asq_cmd_details cmd_details;
+
+ memset(&cmd_details, 0, sizeof(cmd_details));
+ cmd_details.wb_desc = &hw->nvm_wb_desc;
/* Here we are checking the SR limit only for the flat memory model.
* We cannot do it for the module-based model, as we did not acquire
@@ -443,7 +466,7 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
ret_code = i40e_aq_update_nvm(hw, module_pointer,
2 * offset, /*bytes*/
2 * words, /*bytes*/
- data, last_command, NULL);
+ data, last_command, &cmd_details);
return ret_code;
}
@@ -461,7 +484,7 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
u16 *checksum)
{
- i40e_status ret_code = 0;
+ i40e_status ret_code;
struct i40e_virt_mem vmem;
u16 pcie_alt_module = 0;
u16 checksum_local = 0;
@@ -541,13 +564,16 @@ i40e_calc_nvm_checksum_exit:
**/
i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
{
- i40e_status ret_code = 0;
+ i40e_status ret_code;
u16 checksum;
+ __le16 le_sum;
ret_code = i40e_calc_nvm_checksum(hw, &checksum);
- if (!ret_code)
+ if (!ret_code) {
+ le_sum = cpu_to_le16(checksum);
ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
- 1, &checksum, true);
+ 1, &le_sum, true);
+ }
return ret_code;
}
@@ -592,25 +618,31 @@ i40e_validate_nvm_checksum_exit:
static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno);
+ u8 *bytes, int *perrno);
static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno);
+ u8 *bytes, int *perrno);
static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
u8 *bytes, int *errno);
static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- int *errno);
+ int *perrno);
static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- int *errno);
+ int *perrno);
static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno);
+ u8 *bytes, int *perrno);
static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno);
+ u8 *bytes, int *perrno);
+static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *perrno);
+static i40e_status i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *perrno);
static inline u8 i40e_nvmupd_get_module(u32 val)
{
return (u8)(val & I40E_NVM_MOD_PNT_MASK);
@@ -620,7 +652,7 @@ static inline u8 i40e_nvmupd_get_transaction(u32 val)
return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
}
-static char *i40e_nvm_update_state_str[] = {
+static const char * const i40e_nvm_update_state_str[] = {
"I40E_NVMUPD_INVALID",
"I40E_NVMUPD_READ_CON",
"I40E_NVMUPD_READ_SNT",
@@ -634,6 +666,9 @@ static char *i40e_nvm_update_state_str[] = {
"I40E_NVMUPD_CSUM_CON",
"I40E_NVMUPD_CSUM_SA",
"I40E_NVMUPD_CSUM_LCB",
+ "I40E_NVMUPD_STATUS",
+ "I40E_NVMUPD_EXEC_AQ",
+ "I40E_NVMUPD_GET_AQ_RESULT",
};
/**
@@ -641,30 +676,60 @@ static char *i40e_nvm_update_state_str[] = {
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command
* @bytes: pointer to the data buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* Dispatches command depending on what update state is current
**/
i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno)
+ u8 *bytes, int *perrno)
{
i40e_status status;
+ enum i40e_nvmupd_cmd upd_cmd;
/* assume success */
- *errno = 0;
+ *perrno = 0;
+
+ /* early check for status command and debug msgs */
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
+
+ i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
+ i40e_nvm_update_state_str[upd_cmd],
+ hw->nvmupd_state,
+ hw->aq.nvm_release_on_done);
+
+ if (upd_cmd == I40E_NVMUPD_INVALID) {
+ *perrno = -EFAULT;
+ i40e_debug(hw, I40E_DEBUG_NVM,
+ "i40e_nvmupd_validate_command returns %d errno %d\n",
+ upd_cmd, *perrno);
+ }
+
+ /* a status request returns immediately rather than
+ * going into the state machine
+ */
+ if (upd_cmd == I40E_NVMUPD_STATUS) {
+ bytes[0] = hw->nvmupd_state;
+ return 0;
+ }
switch (hw->nvmupd_state) {
case I40E_NVMUPD_STATE_INIT:
- status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
break;
case I40E_NVMUPD_STATE_READING:
- status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
break;
case I40E_NVMUPD_STATE_WRITING:
- status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
+ break;
+
+ case I40E_NVMUPD_STATE_INIT_WAIT:
+ case I40E_NVMUPD_STATE_WRITE_WAIT:
+ status = I40E_ERR_NOT_READY;
+ *perrno = -EBUSY;
break;
default:
@@ -672,7 +737,7 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: no such state %d\n", hw->nvmupd_state);
status = I40E_NOT_SUPPORTED;
- *errno = -ESRCH;
+ *perrno = -ESRCH;
break;
}
return status;
@@ -683,28 +748,28 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
* @bytes: pointer to the data buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* Process legitimate commands of the Init state and conditionally set next
* state. Reject all other commands.
**/
static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno)
+ u8 *bytes, int *perrno)
{
i40e_status status = 0;
enum i40e_nvmupd_cmd upd_cmd;
- upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
switch (upd_cmd) {
case I40E_NVMUPD_READ_SA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
if (status) {
- *errno = i40e_aq_rc_to_posix(status,
+ *perrno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else {
- status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
i40e_release_nvm(hw);
}
break;
@@ -712,10 +777,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_READ_SNT:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
if (status) {
- *errno = i40e_aq_rc_to_posix(status,
+ *perrno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else {
- status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
if (status)
i40e_release_nvm(hw);
else
@@ -726,70 +791,83 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_WRITE_ERA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) {
- *errno = i40e_aq_rc_to_posix(status,
+ *perrno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else {
- status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
- if (status)
+ status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
+ if (status) {
i40e_release_nvm(hw);
- else
+ } else {
hw->aq.nvm_release_on_done = true;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+ }
}
break;
case I40E_NVMUPD_WRITE_SA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) {
- *errno = i40e_aq_rc_to_posix(status,
+ *perrno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else {
- status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
- if (status)
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+ if (status) {
i40e_release_nvm(hw);
- else
+ } else {
hw->aq.nvm_release_on_done = true;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+ }
}
break;
case I40E_NVMUPD_WRITE_SNT:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) {
- *errno = i40e_aq_rc_to_posix(status,
+ *perrno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else {
- status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
if (status)
i40e_release_nvm(hw);
else
- hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
}
break;
case I40E_NVMUPD_CSUM_SA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) {
- *errno = i40e_aq_rc_to_posix(status,
+ *perrno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else {
status = i40e_update_nvm_checksum(hw);
if (status) {
- *errno = hw->aq.asq_last_status ?
+ *perrno = hw->aq.asq_last_status ?
i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status) :
-EIO;
i40e_release_nvm(hw);
} else {
hw->aq.nvm_release_on_done = true;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
}
break;
+ case I40E_NVMUPD_EXEC_AQ:
+ status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
+ break;
+
+ case I40E_NVMUPD_GET_AQ_RESULT:
+ status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
+ break;
+
default:
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: bad cmd %s in init state\n",
i40e_nvm_update_state_str[upd_cmd]);
status = I40E_ERR_NVM;
- *errno = -ESRCH;
+ *perrno = -ESRCH;
break;
}
return status;
@@ -800,28 +878,28 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
* @bytes: pointer to the data buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* NVM ownership is already held. Process legitimate commands and set any
* change in state; reject all other commands.
**/
static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno)
+ u8 *bytes, int *perrno)
{
- i40e_status status;
+ i40e_status status = 0;
enum i40e_nvmupd_cmd upd_cmd;
- upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
switch (upd_cmd) {
case I40E_NVMUPD_READ_SA:
case I40E_NVMUPD_READ_CON:
- status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
break;
case I40E_NVMUPD_READ_LCB:
- status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
i40e_release_nvm(hw);
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
break;
@@ -831,7 +909,7 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
"NVMUPD: bad cmd %s in reading state.\n",
i40e_nvm_update_state_str[upd_cmd]);
status = I40E_NOT_SUPPORTED;
- *errno = -ESRCH;
+ *perrno = -ESRCH;
break;
}
return status;
@@ -842,55 +920,68 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
* @bytes: pointer to the data buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* NVM ownership is already held. Process legitimate commands and set any
* change in state; reject all other commands
**/
static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno)
+ u8 *bytes, int *perrno)
{
- i40e_status status;
+ i40e_status status = 0;
enum i40e_nvmupd_cmd upd_cmd;
bool retry_attempt = false;
- upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
retry:
switch (upd_cmd) {
case I40E_NVMUPD_WRITE_CON:
- status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+ if (!status)
+ hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
break;
case I40E_NVMUPD_WRITE_LCB:
- status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
- if (!status)
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+ if (status) {
+ *perrno = hw->aq.asq_last_status ?
+ i40e_aq_rc_to_posix(status,
+ hw->aq.asq_last_status) :
+ -EIO;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ } else {
hw->aq.nvm_release_on_done = true;
- hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+ }
break;
case I40E_NVMUPD_CSUM_CON:
status = i40e_update_nvm_checksum(hw);
if (status) {
- *errno = hw->aq.asq_last_status ?
+ *perrno = hw->aq.asq_last_status ?
i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status) :
-EIO;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ } else {
+ hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
}
break;
case I40E_NVMUPD_CSUM_LCB:
status = i40e_update_nvm_checksum(hw);
- if (status)
- *errno = hw->aq.asq_last_status ?
+ if (status) {
+ *perrno = hw->aq.asq_last_status ?
i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status) :
-EIO;
- else
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ } else {
hw->aq.nvm_release_on_done = true;
- hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+ }
break;
default:
@@ -898,7 +989,7 @@ retry:
"NVMUPD: bad cmd %s in writing state.\n",
i40e_nvm_update_state_str[upd_cmd]);
status = I40E_NOT_SUPPORTED;
- *errno = -ESRCH;
+ *perrno = -ESRCH;
break;
}
@@ -941,21 +1032,22 @@ retry:
* i40e_nvmupd_validate_command - Validate given command
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* Return one of the valid command types or I40E_NVMUPD_INVALID
**/
static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- int *errno)
+ int *perrno)
{
enum i40e_nvmupd_cmd upd_cmd;
- u8 transaction;
+ u8 module, transaction;
/* anything that doesn't match a recognized case is an error */
upd_cmd = I40E_NVMUPD_INVALID;
transaction = i40e_nvmupd_get_transaction(cmd->config);
+ module = i40e_nvmupd_get_module(cmd->config);
/* limits on data size */
if ((cmd->data_size < 1) ||
@@ -963,7 +1055,7 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_validate_command data_size %d\n",
cmd->data_size);
- *errno = -EFAULT;
+ *perrno = -EFAULT;
return I40E_NVMUPD_INVALID;
}
@@ -982,6 +1074,12 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
case I40E_NVM_SA:
upd_cmd = I40E_NVMUPD_READ_SA;
break;
+ case I40E_NVM_EXEC:
+ if (module == 0xf)
+ upd_cmd = I40E_NVMUPD_STATUS;
+ else if (module == 0)
+ upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
+ break;
}
break;
@@ -1011,21 +1109,155 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
case (I40E_NVM_CSUM|I40E_NVM_LCB):
upd_cmd = I40E_NVMUPD_CSUM_LCB;
break;
+ case I40E_NVM_EXEC:
+ if (module == 0)
+ upd_cmd = I40E_NVMUPD_EXEC_AQ;
+ break;
}
break;
}
- i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
- i40e_nvm_update_state_str[upd_cmd],
- hw->nvmupd_state,
- hw->aq.nvm_release_on_done);
- if (upd_cmd == I40E_NVMUPD_INVALID) {
- *errno = -EFAULT;
+ return upd_cmd;
+}
+
+/**
+ * i40e_nvmupd_exec_aq - Run an AQ command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *perrno)
+{
+ struct i40e_asq_cmd_details cmd_details;
+ i40e_status status;
+ struct i40e_aq_desc *aq_desc;
+ u32 buff_size = 0;
+ u8 *buff = NULL;
+ u32 aq_desc_len;
+ u32 aq_data_len;
+
+ i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+ memset(&cmd_details, 0, sizeof(cmd_details));
+ cmd_details.wb_desc = &hw->nvm_wb_desc;
+
+ aq_desc_len = sizeof(struct i40e_aq_desc);
+ memset(&hw->nvm_wb_desc, 0, aq_desc_len);
+
+ /* get the aq descriptor */
+ if (cmd->data_size < aq_desc_len) {
i40e_debug(hw, I40E_DEBUG_NVM,
- "i40e_nvmupd_validate_command returns %d errno %d\n",
- upd_cmd, *errno);
+ "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",
+ cmd->data_size, aq_desc_len);
+ *perrno = -EINVAL;
+ return I40E_ERR_PARAM;
}
- return upd_cmd;
+ aq_desc = (struct i40e_aq_desc *)bytes;
+
+ /* if data buffer needed, make sure it's ready */
+ aq_data_len = cmd->data_size - aq_desc_len;
+ buff_size = max_t(u32, aq_data_len, le16_to_cpu(aq_desc->datalen));
+ if (buff_size) {
+ if (!hw->nvm_buff.va) {
+ status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
+ hw->aq.asq_buf_size);
+ if (status)
+ i40e_debug(hw, I40E_DEBUG_NVM,
+ "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",
+ status);
+ }
+
+ if (hw->nvm_buff.va) {
+ buff = hw->nvm_buff.va;
+ memcpy(buff, &bytes[aq_desc_len], aq_data_len);
+ }
+ }
+
+ /* and away we go! */
+ status = i40e_asq_send_command(hw, aq_desc, buff,
+ buff_size, &cmd_details);
+ if (status) {
+ i40e_debug(hw, I40E_DEBUG_NVM,
+ "i40e_nvmupd_exec_aq err %s aq_err %s\n",
+ i40e_stat_str(hw, status),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+ }
+
+ return status;
+}
+
+/**
+ * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static i40e_status i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *perrno)
+{
+ u32 aq_total_len;
+ u32 aq_desc_len;
+ int remainder;
+ u8 *buff;
+
+ i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+
+ aq_desc_len = sizeof(struct i40e_aq_desc);
+ aq_total_len = aq_desc_len + le16_to_cpu(hw->nvm_wb_desc.datalen);
+
+ /* check offset range */
+ if (cmd->offset > aq_total_len) {
+ i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
+ __func__, cmd->offset, aq_total_len);
+ *perrno = -EINVAL;
+ return I40E_ERR_PARAM;
+ }
+
+ /* check copylength range */
+ if (cmd->data_size > (aq_total_len - cmd->offset)) {
+ int new_len = aq_total_len - cmd->offset;
+
+ i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",
+ __func__, cmd->data_size, new_len);
+ cmd->data_size = new_len;
+ }
+
+ remainder = cmd->data_size;
+ if (cmd->offset < aq_desc_len) {
+ u32 len = aq_desc_len - cmd->offset;
+
+ len = min(len, cmd->data_size);
+ i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
+ __func__, cmd->offset, cmd->offset + len);
+
+ buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
+ memcpy(bytes, buff, len);
+
+ bytes += len;
+ remainder -= len;
+ buff = hw->nvm_buff.va;
+ } else {
+ buff = hw->nvm_buff.va + (cmd->offset - aq_desc_len);
+ }
+
+ if (remainder > 0) {
+ int start_byte = buff - (u8 *)hw->nvm_buff.va;
+
+ i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
+ __func__, start_byte, start_byte + remainder);
+ memcpy(bytes, buff, remainder);
+ }
+
+ return 0;
}
/**
@@ -1033,14 +1265,15 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
* @bytes: pointer to the data buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* cmd structure contains identifiers and data buffer
**/
static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno)
+ u8 *bytes, int *perrno)
{
+ struct i40e_asq_cmd_details cmd_details;
i40e_status status;
u8 module, transaction;
bool last;
@@ -1049,8 +1282,11 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
module = i40e_nvmupd_get_module(cmd->config);
last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
+ memset(&cmd_details, 0, sizeof(cmd_details));
+ cmd_details.wb_desc = &hw->nvm_wb_desc;
+
status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
- bytes, last, NULL);
+ bytes, last, &cmd_details);
if (status) {
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
@@ -1058,7 +1294,7 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_read status %d aq %d\n",
status, hw->aq.asq_last_status);
- *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+ *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
return status;
@@ -1068,23 +1304,28 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
* i40e_nvmupd_nvm_erase - Erase an NVM module
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* module, offset, data_size and data are in cmd structure
**/
static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- int *errno)
+ int *perrno)
{
i40e_status status = 0;
+ struct i40e_asq_cmd_details cmd_details;
u8 module, transaction;
bool last;
transaction = i40e_nvmupd_get_transaction(cmd->config);
module = i40e_nvmupd_get_module(cmd->config);
last = (transaction & I40E_NVM_LCB);
+
+ memset(&cmd_details, 0, sizeof(cmd_details));
+ cmd_details.wb_desc = &hw->nvm_wb_desc;
+
status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
- last, NULL);
+ last, &cmd_details);
if (status) {
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
@@ -1092,7 +1333,7 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_erase status %d aq %d\n",
status, hw->aq.asq_last_status);
- *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+ *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
return status;
@@ -1103,15 +1344,16 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
* @hw: pointer to hardware structure
* @cmd: pointer to nvm update command buffer
* @bytes: pointer to the data buffer
- * @errno: pointer to return error code
+ * @perrno: pointer to return error code
*
* module, offset, data_size and data are in cmd structure
**/
static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
- u8 *bytes, int *errno)
+ u8 *bytes, int *perrno)
{
i40e_status status = 0;
+ struct i40e_asq_cmd_details cmd_details;
u8 module, transaction;
bool last;
@@ -1119,8 +1361,12 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
module = i40e_nvmupd_get_module(cmd->config);
last = (transaction & I40E_NVM_LCB);
+ memset(&cmd_details, 0, sizeof(cmd_details));
+ cmd_details.wb_desc = &hw->nvm_wb_desc;
+
status = i40e_aq_update_nvm(hw, module, cmd->offset,
- (u16)cmd->data_size, bytes, last, NULL);
+ (u16)cmd->data_size, bytes, last,
+ &cmd_details);
if (status) {
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
@@ -1128,7 +1374,7 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_write status %d aq %d\n",
status, hw->aq.asq_last_status);
- *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+ *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
return status;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h b/drivers/net/ethernet/intel/i40e/i40e_osdep.h
index ad802dd0f67a..5b6feb7edeb1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h
@@ -35,7 +35,7 @@
#include <linux/highuid.h>
/* get readq/writeq support for 32 bit kernels, use the low-first version */
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
/* File to be the magic between shared code and
* actual OS primitives
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index dcb72a8ee8e5..bb9d583e5416 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -58,8 +58,8 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,
void i40e_idle_aq(struct i40e_hw *hw);
bool i40e_check_asq_alive(struct i40e_hw *hw);
i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading);
-char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
-char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err);
+const char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
+const char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err);
i40e_status i40e_aq_get_rss_lut(struct i40e_hw *hw, u16 seid,
bool pf_lut, u8 *lut, u16 lut_size);
@@ -258,7 +258,8 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw);
i40e_status i40e_pf_reset(struct i40e_hw *hw);
void i40e_clear_hw(struct i40e_hw *hw);
void i40e_clear_pxe_mode(struct i40e_hw *hw);
-bool i40e_get_link_status(struct i40e_hw *hw);
+i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up);
+i40e_status i40e_update_link_info(struct i40e_hw *hw);
i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
i40e_status i40e_read_bw_from_alt_ram(struct i40e_hw *hw,
u32 *max_bw, u32 *min_bw, bool *min_valid,
@@ -321,4 +322,6 @@ i40e_status i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id,
void *buff, u16 *ret_buff_size,
u8 *ret_next_table, u32 *ret_next_index,
struct i40e_asq_cmd_details *cmd_details);
+void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
+ u16 vsi_seid);
#endif /* _I40E_PROTOTYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index 8c40d6ea15fd..565ca7c835bc 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -618,9 +618,8 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf)
/* Attempt to register the clock before enabling the hardware. */
pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
- if (IS_ERR(pf->ptp_clock)) {
+ if (IS_ERR(pf->ptp_clock))
return PTR_ERR(pf->ptp_clock);
- }
/* clear the hwtstamp settings here during clock create, instead of
* during regular init, so that we can maintain settings across a
@@ -675,8 +674,8 @@ void i40e_ptp_init(struct i40e_pf *pf)
struct timespec64 ts;
u32 regval;
- dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
- netdev->name);
+ if (pf->hw.debug_mask & I40E_DEBUG_LAN)
+ dev_info(&pf->pdev->dev, "PHC enabled\n");
pf->flags |= I40E_FLAG_PTP;
/* Ensure the clocks are running. */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 738aca68f665..635b3ac17877 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -465,10 +465,11 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
if (error == BIT(I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT)) {
+ pf->fd_inv = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fd_id);
if ((rx_desc->wb.qword0.hi_dword.fd_id != 0) ||
(I40E_DEBUG_FD & pf->hw.debug_mask))
dev_warn(&pdev->dev, "ntuple filter loc = %d, could not be added\n",
- rx_desc->wb.qword0.hi_dword.fd_id);
+ pf->fd_inv);
/* Check if the programming error is for ATR.
* If so, auto disable ATR and set a state for
@@ -601,27 +602,13 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring)
}
/**
- * i40e_get_head - Retrieve head from head writeback
- * @tx_ring: tx ring to fetch head of
- *
- * Returns value of Tx ring head based on value stored
- * in head write-back location
- **/
-static inline u32 i40e_get_head(struct i40e_ring *tx_ring)
-{
- void *head = (struct i40e_tx_desc *)tx_ring->desc + tx_ring->count;
-
- return le32_to_cpu(*(volatile __le32 *)head);
-}
-
-/**
* i40e_get_tx_pending - how many tx descriptors not processed
* @tx_ring: the ring of descriptors
*
* Since there is no access to the ring head register
* in XL710, we need to use our local copies
**/
-static u32 i40e_get_tx_pending(struct i40e_ring *ring)
+u32 i40e_get_tx_pending(struct i40e_ring *ring)
{
u32 head, tail;
@@ -635,50 +622,6 @@ static u32 i40e_get_tx_pending(struct i40e_ring *ring)
return 0;
}
-/**
- * i40e_check_tx_hang - Is there a hang in the Tx queue
- * @tx_ring: the ring of descriptors
- **/
-static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)
-{
- u32 tx_done = tx_ring->stats.packets;
- u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
- u32 tx_pending = i40e_get_tx_pending(tx_ring);
- struct i40e_pf *pf = tx_ring->vsi->back;
- bool ret = false;
-
- clear_check_for_tx_hang(tx_ring);
-
- /* Check for a hung queue, but be thorough. This verifies
- * that a transmit has been completed since the previous
- * check AND there is at least one packet pending. The
- * ARMED bit is set to indicate a potential hang. The
- * bit is cleared if a pause frame is received to remove
- * false hang detection due to PFC or 802.3x frames. By
- * requiring this to fail twice we avoid races with
- * PFC clearing the ARMED bit and conditions where we
- * run the check_tx_hang logic with a transmit completion
- * pending but without time to complete it yet.
- */
- if ((tx_done_old == tx_done) && tx_pending) {
- /* make sure it is true for two checks in a row */
- ret = test_and_set_bit(__I40E_HANG_CHECK_ARMED,
- &tx_ring->state);
- } else if (tx_done_old == tx_done &&
- (tx_pending < I40E_MIN_DESC_PENDING) && (tx_pending > 0)) {
- if (I40E_DEBUG_FLOW & pf->hw.debug_mask)
- dev_info(tx_ring->dev, "HW needs some more descs to do a cacheline flush. tx_pending %d, queue %d",
- tx_pending, tx_ring->queue_index);
- pf->tx_sluggish_count++;
- } else {
- /* update completed stats and disarm the hang check */
- tx_ring->tx_stats.tx_done_old = tx_done;
- clear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state);
- }
-
- return ret;
-}
-
#define WB_STRIDE 0x3
/**
@@ -784,42 +727,21 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
tx_ring->q_vector->tx.total_bytes += total_bytes;
tx_ring->q_vector->tx.total_packets += total_packets;
- /* check to see if there are any non-cache aligned descriptors
- * waiting to be written back, and kick the hardware to force
- * them to be written back in case of napi polling
- */
- if (budget &&
- !((i & WB_STRIDE) == WB_STRIDE) &&
- !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
- (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
- tx_ring->arm_wb = true;
- else
- tx_ring->arm_wb = false;
-
- if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {
- /* schedule immediate reset if we believe we hung */
- dev_info(tx_ring->dev, "Detected Tx Unit Hang\n"
- " VSI <%d>\n"
- " Tx Queue <%d>\n"
- " next_to_use <%x>\n"
- " next_to_clean <%x>\n",
- tx_ring->vsi->seid,
- tx_ring->queue_index,
- tx_ring->next_to_use, i);
-
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
-
- dev_info(tx_ring->dev,
- "tx hang detected on queue %d, reset requested\n",
- tx_ring->queue_index);
-
- /* do not fire the reset immediately, wait for the stack to
- * decide we are truly stuck, also prevents every queue from
- * simultaneously requesting a reset
+ if (tx_ring->flags & I40E_TXR_FLAGS_WB_ON_ITR) {
+ unsigned int j = 0;
+
+ /* check to see if there are < 4 descriptors
+ * waiting to be written back, then kick the hardware to force
+ * them to be written back in case we stay in NAPI.
+ * In this mode on X722 we do not enable Interrupt.
*/
+ j = i40e_get_tx_pending(tx_ring);
- /* the adapter is about to reset, no point in enabling polling */
- budget = 1;
+ if (budget &&
+ ((j / (WB_STRIDE + 1)) == 0) && (j != 0) &&
+ !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
+ (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
+ tx_ring->arm_wb = true;
}
netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,
@@ -851,7 +773,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
* @q_vector: the vector on which to force writeback
*
**/
-static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
+void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
{
u16 flags = q_vector->tx.ring[0].flags;
@@ -893,6 +815,8 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
* i40e_set_new_dynamic_itr - Find new ITR level
* @rc: structure containing ring performance data
*
+ * Returns true if ITR changed, false if not
+ *
* Stores a new ITR value based on packets and byte counts during
* the last interrupt. The advantage of per interrupt computation
* is faster updates and more accurate ITR for the current traffic
@@ -901,21 +825,32 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
* testing data as well as attempting to minimize response time
* while increasing bulk throughput.
**/
-static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
+static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
{
enum i40e_latency_range new_latency_range = rc->latency_range;
+ struct i40e_q_vector *qv = rc->ring->q_vector;
u32 new_itr = rc->itr;
int bytes_per_int;
+ int usecs;
if (rc->total_packets == 0 || !rc->itr)
- return;
+ return false;
/* simple throttlerate management
- * 0-10MB/s lowest (100000 ints/s)
+ * 0-10MB/s lowest (50000 ints/s)
* 10-20MB/s low (20000 ints/s)
- * 20-1249MB/s bulk (8000 ints/s)
+ * 20-1249MB/s bulk (18000 ints/s)
+ * > 40000 Rx packets per second (8000 ints/s)
+ *
+ * The math works out because the divisor is in 10^(-6) which
+ * turns the bytes/us input value into MB/s values, but
+ * make sure to use usecs, as the register values written
+ * are in 2 usec increments in the ITR registers, and make sure
+ * to use the smoothed values that the countdown timer gives us.
*/
- bytes_per_int = rc->total_bytes / rc->itr;
+ usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
+ bytes_per_int = rc->total_bytes / usecs;
+
switch (new_latency_range) {
case I40E_LOWEST_LATENCY:
if (bytes_per_int > 10)
@@ -928,35 +863,52 @@ static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
new_latency_range = I40E_LOWEST_LATENCY;
break;
case I40E_BULK_LATENCY:
- if (bytes_per_int <= 20)
- new_latency_range = I40E_LOW_LATENCY;
- break;
+ case I40E_ULTRA_LATENCY:
default:
if (bytes_per_int <= 20)
new_latency_range = I40E_LOW_LATENCY;
break;
}
+
+ /* this is to adjust RX more aggressively when streaming small
+ * packets. The value of 40000 was picked as it is just beyond
+ * what the hardware can receive per second if in low latency
+ * mode.
+ */
+#define RX_ULTRA_PACKET_RATE 40000
+
+ if ((((rc->total_packets * 1000000) / usecs) > RX_ULTRA_PACKET_RATE) &&
+ (&qv->rx == rc))
+ new_latency_range = I40E_ULTRA_LATENCY;
+
rc->latency_range = new_latency_range;
switch (new_latency_range) {
case I40E_LOWEST_LATENCY:
- new_itr = I40E_ITR_100K;
+ new_itr = I40E_ITR_50K;
break;
case I40E_LOW_LATENCY:
new_itr = I40E_ITR_20K;
break;
case I40E_BULK_LATENCY:
+ new_itr = I40E_ITR_18K;
+ break;
+ case I40E_ULTRA_LATENCY:
new_itr = I40E_ITR_8K;
break;
default:
break;
}
- if (new_itr != rc->itr)
- rc->itr = new_itr;
-
rc->total_bytes = 0;
rc->total_packets = 0;
+
+ if (new_itr != rc->itr) {
+ rc->itr = new_itr;
+ return true;
+ }
+
+ return false;
}
/**
@@ -1002,6 +954,8 @@ int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring)
if (!dev)
return -ENOMEM;
+ /* warn if we are about to overwrite the pointer */
+ WARN_ON(tx_ring->tx_bi);
bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
tx_ring->tx_bi = kzalloc(bi_size, GFP_KERNEL);
if (!tx_ring->tx_bi)
@@ -1162,6 +1116,8 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring)
struct device *dev = rx_ring->dev;
int bi_size;
+ /* warn if we are about to overwrite the pointer */
+ WARN_ON(rx_ring->rx_bi);
bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
rx_ring->rx_bi = kzalloc(bi_size, GFP_KERNEL);
if (!rx_ring->rx_bi)
@@ -1342,16 +1298,11 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
struct sk_buff *skb, u16 vlan_tag)
{
struct i40e_q_vector *q_vector = rx_ring->q_vector;
- struct i40e_vsi *vsi = rx_ring->vsi;
- u64 flags = vsi->back->flags;
if (vlan_tag & VLAN_VID_MASK)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
- if (flags & I40E_FLAG_IN_NETPOLL)
- netif_rx(skb);
- else
- napi_gro_receive(&q_vector->napi, skb);
+ napi_gro_receive(&q_vector->napi, skb);
}
/**
@@ -1518,7 +1469,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
u16 rx_packet_len, rx_header_len, rx_sph, rx_hbo;
u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
- const int current_node = numa_node_id();
+ const int current_node = numa_mem_id();
struct i40e_vsi *vsi = rx_ring->vsi;
u16 i = rx_ring->next_to_clean;
union i40e_rx_desc *rx_desc;
@@ -1596,6 +1547,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
cleaned_count++;
if (rx_hbo || rx_sph) {
int len;
+
if (rx_hbo)
len = I40E_RX_HDR_SIZE;
else
@@ -1781,9 +1733,6 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget)
/* ERR_MASK will only have valid bits if EOP set */
if (unlikely(rx_error & BIT(I40E_RX_DESC_ERROR_RXE_SHIFT))) {
dev_kfree_skb_any(skb);
- /* TODO: shouldn't we increment a counter indicating the
- * drop?
- */
continue;
}
@@ -1828,6 +1777,21 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget)
return total_rx_packets;
}
+static u32 i40e_buildreg_itr(const int type, const u16 itr)
+{
+ u32 val;
+
+ val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
+ I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+ (type << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+ (itr << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT);
+
+ return val;
+}
+
+/* a small macro to shorten up some long lines */
+#define INTREG I40E_PFINT_DYN_CTLN
+
/**
* i40e_update_enable_itr - Update itr and re-enable MSIX interrupt
* @vsi: the VSI we care about
@@ -1838,56 +1802,69 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
struct i40e_q_vector *q_vector)
{
struct i40e_hw *hw = &vsi->back->hw;
- u16 old_itr;
+ bool rx = false, tx = false;
+ u32 rxval, txval;
int vector;
- u32 val;
vector = (q_vector->v_idx + vsi->base_vector);
+
+ /* avoid dynamic calculation if in countdown mode OR if
+ * all dynamic is disabled
+ */
+ rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
+
+ if (q_vector->itr_countdown > 0 ||
+ (!ITR_IS_DYNAMIC(vsi->rx_itr_setting) &&
+ !ITR_IS_DYNAMIC(vsi->tx_itr_setting))) {
+ goto enable_int;
+ }
+
if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) {
- old_itr = q_vector->rx.itr;
- i40e_set_new_dynamic_itr(&q_vector->rx);
- if (old_itr != q_vector->rx.itr) {
- val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
- (I40E_RX_ITR <<
- I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
- (q_vector->rx.itr <<
- I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT);
- } else {
- val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
- (I40E_ITR_NONE <<
- I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
- }
- if (!test_bit(__I40E_DOWN, &vsi->state))
- wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val);
- } else {
- i40e_irq_dynamic_enable(vsi,
- q_vector->v_idx + vsi->base_vector);
+ rx = i40e_set_new_dynamic_itr(&q_vector->rx);
+ rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);
}
+
if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) {
- old_itr = q_vector->tx.itr;
- i40e_set_new_dynamic_itr(&q_vector->tx);
- if (old_itr != q_vector->tx.itr) {
- val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
- (I40E_TX_ITR <<
- I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
- (q_vector->tx.itr <<
- I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT);
- } else {
- val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
- (I40E_ITR_NONE <<
- I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
- }
- if (!test_bit(__I40E_DOWN, &vsi->state))
- wr32(hw, I40E_PFINT_DYN_CTLN(q_vector->v_idx +
- vsi->base_vector - 1), val);
- } else {
- i40e_irq_dynamic_enable(vsi,
- q_vector->v_idx + vsi->base_vector);
+ tx = i40e_set_new_dynamic_itr(&q_vector->tx);
+ txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr);
+ }
+
+ if (rx || tx) {
+ /* get the higher of the two ITR adjustments and
+ * use the same value for both ITR registers
+ * when in adaptive mode (Rx and/or Tx)
+ */
+ u16 itr = max(q_vector->tx.itr, q_vector->rx.itr);
+
+ q_vector->tx.itr = q_vector->rx.itr = itr;
+ txval = i40e_buildreg_itr(I40E_TX_ITR, itr);
+ tx = true;
+ rxval = i40e_buildreg_itr(I40E_RX_ITR, itr);
+ rx = true;
}
+
+ /* only need to enable the interrupt once, but need
+ * to possibly update both ITR values
+ */
+ if (rx) {
+ /* set the INTENA_MSK_MASK so that this first write
+ * won't actually enable the interrupt, instead just
+ * updating the ITR (it's bit 31 PF and VF)
+ */
+ rxval |= BIT(31);
+ /* don't check _DOWN because interrupt isn't being enabled */
+ wr32(hw, INTREG(vector - 1), rxval);
+ }
+
+enable_int:
+ if (!test_bit(__I40E_DOWN, &vsi->state))
+ wr32(hw, INTREG(vector - 1), txval);
+
+ if (q_vector->itr_countdown)
+ q_vector->itr_countdown--;
+ else
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+
}
/**
@@ -1908,7 +1885,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
bool clean_complete = true;
bool arm_wb = false;
int budget_per_ring;
- int cleaned;
+ int work_done = 0;
if (test_bit(__I40E_DOWN, &vsi->state)) {
napi_complete(napi);
@@ -1921,24 +1898,34 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
i40e_for_each_ring(ring, q_vector->tx) {
clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit);
arm_wb |= ring->arm_wb;
+ ring->arm_wb = false;
}
+ /* Handle case where we are called by netpoll with a budget of 0 */
+ if (budget <= 0)
+ goto tx_only;
+
/* We attempt to distribute budget to each Rx queue fairly, but don't
* allow the budget to go below 1 because that would exit polling early.
*/
budget_per_ring = max(budget/q_vector->num_ringpairs, 1);
i40e_for_each_ring(ring, q_vector->rx) {
+ int cleaned;
+
if (ring_is_ps_enabled(ring))
cleaned = i40e_clean_rx_irq_ps(ring, budget_per_ring);
else
cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring);
+
+ work_done += cleaned;
/* if we didn't clean as many as budgeted, we must be done */
clean_complete &= (budget_per_ring != cleaned);
}
/* If work not completed, return budget and polling will return */
if (!clean_complete) {
+tx_only:
if (arm_wb)
i40e_force_wb(vsi, q_vector);
return budget;
@@ -1948,7 +1935,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
q_vector->arm_wb_state = false;
/* Work is done so exit the polling mode and re-enable the interrupt */
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
i40e_update_enable_itr(vsi, q_vector);
} else { /* Legacy mode */
@@ -2156,6 +2143,7 @@ static inline int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
/* else if it is a SW VLAN, check the next protocol and store the tag */
} else if (protocol == htons(ETH_P_8021Q)) {
struct vlan_hdr *vhdr, _vhdr;
+
vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
if (!vhdr)
return -EINVAL;
@@ -2199,6 +2187,7 @@ out:
* @tx_ring: ptr to the ring to send
* @skb: ptr to the skb we're sending
* @hdr_len: ptr to the size of the packet header
+ * @cd_type_cmd_tso_mss: ptr to u64 object
* @cd_tunneling: ptr to context descriptor bits
*
* Returns 0 if no TSO can happen, 1 if tso is going, or error
@@ -2258,6 +2247,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_ring: ptr to the ring to send
* @skb: ptr to the skb we're sending
* @tx_flags: the collected send information
+ * @cd_type_cmd_tso_mss: ptr to u64 object
*
* Returns 0 if no Tx timestamp can happen and 1 if the timestamp will happen
**/
@@ -2300,6 +2290,7 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
* @tx_flags: pointer to Tx flags currently set
* @td_cmd: Tx descriptor command bits to set
* @td_offset: Tx descriptor header offsets to set
+ * @tx_ring: Tx descriptor ring
* @cd_tunneling: ptr to context desc bits
**/
static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
@@ -2324,6 +2315,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break;
+ case IPPROTO_GRE:
+ l4_tunnel = I40E_TXD_CTX_GRE_TUNNELING;
+ break;
default:
return;
}
@@ -2581,6 +2575,9 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
u32 td_tag = 0;
dma_addr_t dma;
u16 gso_segs;
+ u16 desc_count = 0;
+ bool tail_bump = true;
+ bool do_rs = false;
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2621,6 +2618,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_desc++;
i++;
+ desc_count++;
+
if (i == tx_ring->count) {
tx_desc = I40E_TX_DESC(tx_ring, 0);
i = 0;
@@ -2640,6 +2639,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_desc++;
i++;
+ desc_count++;
+
if (i == tx_ring->count) {
tx_desc = I40E_TX_DESC(tx_ring, 0);
i = 0;
@@ -2654,34 +2655,6 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_bi = &tx_ring->tx_bi[i];
}
- /* Place RS bit on last descriptor of any packet that spans across the
- * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline.
- */
- if (((i & WB_STRIDE) != WB_STRIDE) &&
- (first <= &tx_ring->tx_bi[i]) &&
- (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) {
- tx_desc->cmd_type_offset_bsz =
- build_ctob(td_cmd, td_offset, size, td_tag) |
- cpu_to_le64((u64)I40E_TX_DESC_CMD_EOP <<
- I40E_TXD_QW1_CMD_SHIFT);
- } else {
- tx_desc->cmd_type_offset_bsz =
- build_ctob(td_cmd, td_offset, size, td_tag) |
- cpu_to_le64((u64)I40E_TXD_CMD <<
- I40E_TXD_QW1_CMD_SHIFT);
- }
-
- netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
- tx_ring->queue_index),
- first->bytecount);
-
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64).
- */
- wmb();
-
/* set next_to_watch value indicating a packet is present */
first->next_to_watch = tx_desc;
@@ -2691,15 +2664,72 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_ring->next_to_use = i;
+ netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
+ tx_ring->queue_index),
+ first->bytecount);
i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+
+ /* Algorithm to optimize tail and RS bit setting:
+ * if xmit_more is supported
+ * if xmit_more is true
+ * do not update tail and do not mark RS bit.
+ * if xmit_more is false and last xmit_more was false
+ * if every packet spanned less than 4 desc
+ * then set RS bit on 4th packet and update tail
+ * on every packet
+ * else
+ * update tail and set RS bit on every packet.
+ * if xmit_more is false and last_xmit_more was true
+ * update tail and set RS bit.
+ *
+ * Optimization: wmb to be issued only in case of tail update.
+ * Also optimize the Descriptor WB path for RS bit with the same
+ * algorithm.
+ *
+ * Note: If there are less than 4 packets
+ * pending and interrupts were disabled the service task will
+ * trigger a force WB.
+ */
+ if (skb->xmit_more &&
+ !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
+ tx_ring->queue_index))) {
+ tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
+ tail_bump = false;
+ } else if (!skb->xmit_more &&
+ !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
+ tx_ring->queue_index)) &&
+ (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
+ (tx_ring->packet_stride < WB_STRIDE) &&
+ (desc_count < WB_STRIDE)) {
+ tx_ring->packet_stride++;
+ } else {
+ tx_ring->packet_stride = 0;
+ tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
+ do_rs = true;
+ }
+ if (do_rs)
+ tx_ring->packet_stride = 0;
+
+ tx_desc->cmd_type_offset_bsz =
+ build_ctob(td_cmd, td_offset, size, td_tag) |
+ cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
+ I40E_TX_DESC_CMD_EOP) <<
+ I40E_TXD_QW1_CMD_SHIFT);
+
/* notify HW of packet */
- if (!skb->xmit_more ||
- netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
- tx_ring->queue_index)))
- writel(i, tx_ring->tail);
- else
+ if (!tail_bump)
prefetchw(tx_desc + 1);
+ if (tail_bump) {
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+ writel(i, tx_ring->tail);
+ }
+
return;
dma_error:
@@ -2776,6 +2806,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
u8 hdr_len = 0;
int tsyn;
int tso;
+
if (0 == i40e_xmit_descriptor_count(skb, tx_ring))
return NETDEV_TX_BUSY;
@@ -2808,10 +2839,11 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
if (tsyn)
tx_flags |= I40E_TX_FLAGS_TSYN;
- if (i40e_chk_linearize(skb, tx_flags))
+ if (i40e_chk_linearize(skb, tx_flags)) {
if (skb_linearize(skb))
goto out_drop;
-
+ tx_ring->tx_stats.tx_linearize++;
+ }
skb_tx_timestamp(skb);
/* always enable CRC insertion offload */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index f1385a1989fa..6779fb771d6a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -32,11 +32,14 @@
#define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */
#define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */
#define I40E_ITR_100K 0x0005
+#define I40E_ITR_50K 0x000A
#define I40E_ITR_20K 0x0019
+#define I40E_ITR_18K 0x001B
#define I40E_ITR_8K 0x003E
#define I40E_ITR_4K 0x007A
-#define I40E_ITR_RX_DEF I40E_ITR_8K
-#define I40E_ITR_TX_DEF I40E_ITR_4K
+#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */
+#define I40E_ITR_RX_DEF I40E_ITR_20K
+#define I40E_ITR_TX_DEF I40E_ITR_20K
#define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
#define I40E_MIN_INT_RATE 250 /* ~= 1000000 / (I40E_MAX_ITR * 2) */
#define I40E_MAX_INT_RATE 500000 /* == 1000000 / (I40E_MIN_ITR * 2) */
@@ -44,6 +47,15 @@
#define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1)
#define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC))
#define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1)
+/* 0x40 is the enable bit for interrupt rate limiting, and must be set if
+ * the value of the rate limit is non-zero
+ */
+#define INTRL_ENA BIT(6)
+#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2)
+#define INTRL_USEC_TO_REG(set) ((set) ? ((set) >> 2) | INTRL_ENA : 0)
+#define I40E_INTRL_8K 125 /* 8000 ints/sec */
+#define I40E_INTRL_62K 16 /* 62500 ints/sec */
+#define I40E_INTRL_83K 12 /* 83333 ints/sec */
#define I40E_QUEUE_END_OF_LIST 0x7FF
@@ -79,12 +91,12 @@ enum i40e_dyn_idx_t {
BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD))
#define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \
- BIT(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
- BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
- BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
- BIT(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
- BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
- BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
#define i40e_pf_get_default_rss_hena(pf) \
(((pf)->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \
@@ -165,6 +177,7 @@ struct i40e_tx_buffer {
};
unsigned int bytecount;
unsigned short gso_segs;
+
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
u32 tx_flags;
@@ -188,6 +201,7 @@ struct i40e_tx_queue_stats {
u64 restart_queue;
u64 tx_busy;
u64 tx_done_old;
+ u64 tx_linearize;
};
struct i40e_rx_queue_stats {
@@ -199,8 +213,6 @@ struct i40e_rx_queue_stats {
enum i40e_ring_state_t {
__I40E_TX_FDIR_INIT_DONE,
__I40E_TX_XPS_INIT_DONE,
- __I40E_TX_DETECT_HANG,
- __I40E_HANG_CHECK_ARMED,
__I40E_RX_PS_ENABLED,
__I40E_RX_16BYTE_DESC_ENABLED,
};
@@ -211,12 +223,6 @@ enum i40e_ring_state_t {
set_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
#define clear_ring_ps_enabled(ring) \
clear_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
-#define check_for_tx_hang(ring) \
- test_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
-#define set_check_for_tx_hang(ring) \
- set_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
-#define clear_check_for_tx_hang(ring) \
- clear_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
#define ring_is_16byte_desc_enabled(ring) \
test_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)
#define set_ring_16byte_desc_enabled(ring) \
@@ -264,10 +270,12 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */
+ u8 packet_stride;
u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
#define I40E_TXR_FLAGS_OUTER_UDP_CSUM BIT(1)
+#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
/* stats structs */
struct i40e_queue_stats stats;
@@ -290,6 +298,7 @@ enum i40e_latency_range {
I40E_LOWEST_LATENCY = 0,
I40E_LOW_LATENCY = 1,
I40E_BULK_LATENCY = 2,
+ I40E_ULTRA_LATENCY = 3,
};
struct i40e_ring_container {
@@ -326,4 +335,20 @@ int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring);
int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
struct i40e_ring *tx_ring, u32 *flags);
#endif
+void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
+u32 i40e_get_tx_pending(struct i40e_ring *ring);
+
+/**
+ * i40e_get_head - Retrieve head from head writeback
+ * @tx_ring: tx ring to fetch head of
+ *
+ * Returns value of Tx ring head based on value stored
+ * in head write-back location
+ **/
+static inline u32 i40e_get_head(struct i40e_ring *tx_ring)
+{
+ void *head = (struct i40e_tx_desc *)tx_ring->desc + tx_ring->count;
+
+ return le32_to_cpu(*(volatile __le32 *)head);
+}
#endif /* _I40E_TXRX_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index 4842239ee777..dd2da356d9a1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -33,29 +33,7 @@
#include "i40e_adminq.h"
#include "i40e_hmc.h"
#include "i40e_lan_hmc.h"
-
-/* Device IDs */
-#define I40E_DEV_ID_SFP_XL710 0x1572
-#define I40E_DEV_ID_QEMU 0x1574
-#define I40E_DEV_ID_KX_A 0x157F
-#define I40E_DEV_ID_KX_B 0x1580
-#define I40E_DEV_ID_KX_C 0x1581
-#define I40E_DEV_ID_QSFP_A 0x1583
-#define I40E_DEV_ID_QSFP_B 0x1584
-#define I40E_DEV_ID_QSFP_C 0x1585
-#define I40E_DEV_ID_10G_BASE_T 0x1586
-#define I40E_DEV_ID_20G_KR2 0x1587
-#define I40E_DEV_ID_VF 0x154C
-#define I40E_DEV_ID_VF_HV 0x1571
-#define I40E_DEV_ID_SFP_X722 0x37D0
-#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
-#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
-#define I40E_DEV_ID_X722_VF 0x37CD
-#define I40E_DEV_ID_X722_VF_HV 0x37D9
-
-#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
- (d) == I40E_DEV_ID_QSFP_B || \
- (d) == I40E_DEV_ID_QSFP_C)
+#include "i40e_devids.h"
/* I40E_MASK is a macro used on 32 bit registers */
#define I40E_MASK(mask, shift) (mask << shift)
@@ -158,14 +136,14 @@ enum i40e_set_fc_aq_failures {
};
enum i40e_vsi_type {
- I40E_VSI_MAIN = 0,
- I40E_VSI_VMDQ1,
- I40E_VSI_VMDQ2,
- I40E_VSI_CTRL,
- I40E_VSI_FCOE,
- I40E_VSI_MIRROR,
- I40E_VSI_SRIOV,
- I40E_VSI_FDIR,
+ I40E_VSI_MAIN = 0,
+ I40E_VSI_VMDQ1 = 1,
+ I40E_VSI_VMDQ2 = 2,
+ I40E_VSI_CTRL = 3,
+ I40E_VSI_FCOE = 4,
+ I40E_VSI_MIRROR = 5,
+ I40E_VSI_SRIOV = 6,
+ I40E_VSI_FDIR = 7,
I40E_VSI_TYPE_UNKNOWN
};
@@ -189,16 +167,65 @@ struct i40e_link_status {
bool crc_enable;
u8 pacing;
u8 requested_speeds;
+ u8 module_type[3];
+ /* 1st byte: module identifier */
+#define I40E_MODULE_TYPE_SFP 0x03
+#define I40E_MODULE_TYPE_QSFP 0x0D
+ /* 2nd byte: ethernet compliance codes for 10/40G */
+#define I40E_MODULE_TYPE_40G_ACTIVE 0x01
+#define I40E_MODULE_TYPE_40G_LR4 0x02
+#define I40E_MODULE_TYPE_40G_SR4 0x04
+#define I40E_MODULE_TYPE_40G_CR4 0x08
+#define I40E_MODULE_TYPE_10G_BASE_SR 0x10
+#define I40E_MODULE_TYPE_10G_BASE_LR 0x20
+#define I40E_MODULE_TYPE_10G_BASE_LRM 0x40
+#define I40E_MODULE_TYPE_10G_BASE_ER 0x80
+ /* 3rd byte: ethernet compliance codes for 1G */
+#define I40E_MODULE_TYPE_1000BASE_SX 0x01
+#define I40E_MODULE_TYPE_1000BASE_LX 0x02
+#define I40E_MODULE_TYPE_1000BASE_CX 0x04
+#define I40E_MODULE_TYPE_1000BASE_T 0x08
+};
+
+enum i40e_aq_capabilities_phy_type {
+ I40E_CAP_PHY_TYPE_SGMII = BIT(I40E_PHY_TYPE_SGMII),
+ I40E_CAP_PHY_TYPE_1000BASE_KX = BIT(I40E_PHY_TYPE_1000BASE_KX),
+ I40E_CAP_PHY_TYPE_10GBASE_KX4 = BIT(I40E_PHY_TYPE_10GBASE_KX4),
+ I40E_CAP_PHY_TYPE_10GBASE_KR = BIT(I40E_PHY_TYPE_10GBASE_KR),
+ I40E_CAP_PHY_TYPE_40GBASE_KR4 = BIT(I40E_PHY_TYPE_40GBASE_KR4),
+ I40E_CAP_PHY_TYPE_XAUI = BIT(I40E_PHY_TYPE_XAUI),
+ I40E_CAP_PHY_TYPE_XFI = BIT(I40E_PHY_TYPE_XFI),
+ I40E_CAP_PHY_TYPE_SFI = BIT(I40E_PHY_TYPE_SFI),
+ I40E_CAP_PHY_TYPE_XLAUI = BIT(I40E_PHY_TYPE_XLAUI),
+ I40E_CAP_PHY_TYPE_XLPPI = BIT(I40E_PHY_TYPE_XLPPI),
+ I40E_CAP_PHY_TYPE_40GBASE_CR4_CU = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU),
+ I40E_CAP_PHY_TYPE_10GBASE_CR1_CU = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU),
+ I40E_CAP_PHY_TYPE_10GBASE_AOC = BIT(I40E_PHY_TYPE_10GBASE_AOC),
+ I40E_CAP_PHY_TYPE_40GBASE_AOC = BIT(I40E_PHY_TYPE_40GBASE_AOC),
+ I40E_CAP_PHY_TYPE_100BASE_TX = BIT(I40E_PHY_TYPE_100BASE_TX),
+ I40E_CAP_PHY_TYPE_1000BASE_T = BIT(I40E_PHY_TYPE_1000BASE_T),
+ I40E_CAP_PHY_TYPE_10GBASE_T = BIT(I40E_PHY_TYPE_10GBASE_T),
+ I40E_CAP_PHY_TYPE_10GBASE_SR = BIT(I40E_PHY_TYPE_10GBASE_SR),
+ I40E_CAP_PHY_TYPE_10GBASE_LR = BIT(I40E_PHY_TYPE_10GBASE_LR),
+ I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU),
+ I40E_CAP_PHY_TYPE_10GBASE_CR1 = BIT(I40E_PHY_TYPE_10GBASE_CR1),
+ I40E_CAP_PHY_TYPE_40GBASE_CR4 = BIT(I40E_PHY_TYPE_40GBASE_CR4),
+ I40E_CAP_PHY_TYPE_40GBASE_SR4 = BIT(I40E_PHY_TYPE_40GBASE_SR4),
+ I40E_CAP_PHY_TYPE_40GBASE_LR4 = BIT(I40E_PHY_TYPE_40GBASE_LR4),
+ I40E_CAP_PHY_TYPE_1000BASE_SX = BIT(I40E_PHY_TYPE_1000BASE_SX),
+ I40E_CAP_PHY_TYPE_1000BASE_LX = BIT(I40E_PHY_TYPE_1000BASE_LX),
+ I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL =
+ BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL),
+ I40E_CAP_PHY_TYPE_20GBASE_KR2 = BIT(I40E_PHY_TYPE_20GBASE_KR2)
};
struct i40e_phy_info {
struct i40e_link_status link_info;
struct i40e_link_status link_info_old;
- u32 autoneg_advertised;
- u32 phy_id;
- u32 module_type;
bool get_link_info;
enum i40e_media_type media_type;
+ /* all the phy types the NVM is capable of */
+ enum i40e_aq_capabilities_phy_type phy_types;
};
#define I40E_HW_CAP_MAX_GPIO 30
@@ -287,6 +314,7 @@ struct i40e_nvm_info {
bool blank_nvm_mode; /* is NVM empty (no FW present)*/
u16 version; /* NVM package version */
u32 eetrack; /* NVM data version */
+ u32 oem_ver; /* OEM version info */
};
/* definitions used in NVM update support */
@@ -305,12 +333,17 @@ enum i40e_nvmupd_cmd {
I40E_NVMUPD_CSUM_CON,
I40E_NVMUPD_CSUM_SA,
I40E_NVMUPD_CSUM_LCB,
+ I40E_NVMUPD_STATUS,
+ I40E_NVMUPD_EXEC_AQ,
+ I40E_NVMUPD_GET_AQ_RESULT,
};
enum i40e_nvmupd_state {
I40E_NVMUPD_STATE_INIT,
I40E_NVMUPD_STATE_READING,
- I40E_NVMUPD_STATE_WRITING
+ I40E_NVMUPD_STATE_WRITING,
+ I40E_NVMUPD_STATE_INIT_WAIT,
+ I40E_NVMUPD_STATE_WRITE_WAIT,
};
/* nvm_access definition and its masks/shifts need to be accessible to
@@ -329,6 +362,7 @@ enum i40e_nvmupd_state {
#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
#define I40E_NVM_ERA 0x4
#define I40E_NVM_CSUM 0x8
+#define I40E_NVM_EXEC 0xf
#define I40E_NVM_ADAPT_SHIFT 16
#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
@@ -409,6 +443,8 @@ struct i40e_fc_info {
#define I40E_APP_PROTOID_FIP 0x8914
#define I40E_APP_SEL_ETHTYPE 0x1
#define I40E_APP_SEL_TCPIP 0x2
+#define I40E_CEE_APP_SEL_ETHTYPE 0x0
+#define I40E_CEE_APP_SEL_TCPIP 0x1
/* CEE or IEEE 802.1Qaz ETS Configuration data */
struct i40e_dcb_ets_config {
@@ -439,6 +475,8 @@ struct i40e_dcbx_config {
u8 dcbx_mode;
#define I40E_DCBX_MODE_CEE 0x1
#define I40E_DCBX_MODE_IEEE 0x2
+ u8 app_mode;
+#define I40E_DCBX_APPS_NON_WILLING 0x1
u32 numapps;
u32 tlv_status; /* CEE mode TLV status */
struct i40e_dcb_ets_config etscfg;
@@ -492,6 +530,8 @@ struct i40e_hw {
/* state of nvm update process */
enum i40e_nvmupd_state nvmupd_state;
+ struct i40e_aq_desc nvm_wb_desc;
+ struct i40e_virt_mem nvm_buff;
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
@@ -500,8 +540,12 @@ struct i40e_hw {
u16 dcbx_status;
/* DCBX info */
- struct i40e_dcbx_config local_dcbx_config;
- struct i40e_dcbx_config remote_dcbx_config;
+ struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */
+ struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
+ struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
+
+#define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
+ u64 flags;
/* debug mask */
u32 debug_mask;
@@ -1024,8 +1068,8 @@ enum i40e_filter_program_desc_fd_status {
};
#define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT 23
-#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK \
- BIT_ULL(I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT)
+#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK (0x1FFUL << \
+ I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT)
#define I40E_TXD_FLTR_QW1_CMD_SHIFT 4
#define I40E_TXD_FLTR_QW1_CMD_MASK (0xFFFFULL << \
@@ -1193,6 +1237,8 @@ struct i40e_hw_port_stats {
#define I40E_SR_EMP_MODULE_PTR 0x0F
#define I40E_SR_PBA_FLAGS 0x15
#define I40E_SR_PBA_BLOCK_PTR 0x16
+#define I40E_SR_BOOT_CONFIG_PTR 0x17
+#define I40E_NVM_OEM_VER_OFF 0x83
#define I40E_SR_NVM_DEV_STARTER_VERSION 0x18
#define I40E_SR_NVM_WAKE_ON_LAN 0x19
#define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR 0x27
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
index 0f8d4156f8b1..ae879826084b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
@@ -81,7 +81,6 @@ enum i40e_virtchnl_ops {
I40E_VIRTCHNL_OP_GET_STATS = 15,
I40E_VIRTCHNL_OP_FCOE = 16,
I40E_VIRTCHNL_OP_EVENT = 17,
- I40E_VIRTCHNL_OP_CONFIG_RSS = 18,
};
/* Virtual channel message descriptor. This overlays the admin queue
@@ -151,6 +150,7 @@ struct i40e_virtchnl_vsi_resource {
#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010
+#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020
#define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000
#define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index d99c116032f3..44462b40f2d7 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -536,6 +536,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
}
if (type == I40E_VSI_SRIOV) {
u8 brdcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
vf->lan_vsi_idx = vsi->idx;
vf->lan_vsi_id = vsi->id;
/* If the port VLAN has been configured and then the
@@ -546,6 +547,8 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
*/
if (vf->port_vlan_id)
i40e_vsi_add_pvid(vsi, vf->port_vlan_id);
+
+ spin_lock_bh(&vsi->mac_filter_list_lock);
f = i40e_add_filter(vsi, vf->default_lan_addr.addr,
vf->port_vlan_id ? vf->port_vlan_id : -1,
true, false);
@@ -558,10 +561,11 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
if (!f)
dev_info(&pf->pdev->dev,
"Could not allocate VF broadcast filter\n");
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
}
/* program mac filter */
- ret = i40e_sync_vsi_filters(vsi);
+ ret = i40e_sync_vsi_filters(vsi, false);
if (ret)
dev_err(&pf->pdev->dev, "Unable to program ucast filters\n");
@@ -605,6 +609,7 @@ static void i40e_enable_vf_mappings(struct i40e_vf *vf)
/* map PF queues to VF queues */
for (j = 0; j < pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; j++) {
u16 qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_id, j);
+
reg = (qid & I40E_VPLAN_QTABLE_QINDEX_MASK);
wr32(hw, I40E_VPLAN_QTABLE(total_queue_pairs, vf->vf_id), reg);
total_queue_pairs++;
@@ -701,6 +706,7 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
*/
vf->num_queue_pairs = 0;
vf->vf_states = 0;
+ clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
}
/**
@@ -839,11 +845,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
complete_reset:
/* reallocate VF resources to reset the VSI state */
i40e_free_vf_res(vf);
- i40e_alloc_vf_res(vf);
- i40e_enable_vf_mappings(vf);
- set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
- clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
-
+ if (!i40e_alloc_vf_res(vf)) {
+ i40e_enable_vf_mappings(vf);
+ set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
+ clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
+ }
/* tell the VF the reset is done */
wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
i40e_flush(hw);
@@ -872,6 +878,11 @@ void i40e_free_vfs(struct i40e_pf *pf)
i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx],
false);
+ for (i = 0; i < pf->num_alloc_vfs; i++)
+ if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states))
+ i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx],
+ false);
+
/* Disable IOV before freeing resources. This lets any VF drivers
* running in the host get themselves cleaned up before we yank
* the carpet out from underneath their feet.
@@ -933,6 +944,7 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
if (pci_num_vf(pf->pdev) != num_alloc_vfs) {
ret = pci_enable_sriov(pf->pdev, num_alloc_vfs);
if (ret) {
+ pf->flags &= ~I40E_FLAG_VEB_MODE_ENABLED;
pf->num_alloc_vfs = 0;
goto err_iov;
}
@@ -957,8 +969,6 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
/* VF resources get allocated during reset */
i40e_reset_vf(&vfs[i], false);
- /* enable VF vplan_qtable mappings */
- i40e_enable_vf_mappings(&vfs[i]);
}
pf->num_alloc_vfs = num_alloc_vfs;
@@ -986,24 +996,26 @@ static int i40e_pci_sriov_enable(struct pci_dev *pdev, int num_vfs)
int pre_existing_vfs = pci_num_vf(pdev);
int err = 0;
- if (pf->state & __I40E_TESTING) {
+ if (test_bit(__I40E_TESTING, &pf->state)) {
dev_warn(&pdev->dev,
"Cannot enable SR-IOV virtual functions while the device is undergoing diagnostic testing\n");
err = -EPERM;
goto err_out;
}
- dev_info(&pdev->dev, "Allocating %d VFs.\n", num_vfs);
if (pre_existing_vfs && pre_existing_vfs != num_vfs)
i40e_free_vfs(pf);
else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
goto out;
if (num_vfs > pf->num_req_vfs) {
+ dev_warn(&pdev->dev, "Unable to enable %d VFs. Limited to %d VFs due to device resource constraints.\n",
+ num_vfs, pf->num_req_vfs);
err = -EPERM;
goto err_out;
}
+ dev_info(&pdev->dev, "Allocating %d VFs.\n", num_vfs);
err = i40e_alloc_vfs(pf, num_vfs);
if (err) {
dev_warn(&pdev->dev, "Failed to enable SR-IOV: %d\n", err);
@@ -1094,6 +1106,8 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
}
} else {
vf->num_valid_msgs++;
+ /* reset the invalid counter, if a valid message is received. */
+ vf->num_invalid_msgs = 0;
}
aq_ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval,
@@ -1195,16 +1209,22 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
} else {
vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG;
}
+
+ if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING)
+ vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING;
+
vfres->num_vsis = num_vsis;
vfres->num_queue_pairs = vf->num_queue_pairs;
vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf;
if (vf->lan_vsi_idx) {
vfres->vsi_res[i].vsi_id = vf->lan_vsi_id;
vfres->vsi_res[i].vsi_type = I40E_VSI_SRIOV;
- vfres->vsi_res[i].num_queue_pairs =
- pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs;
- memcpy(vfres->vsi_res[i].default_mac_addr,
- vf->default_lan_addr.addr, ETH_ALEN);
+ vfres->vsi_res[i].num_queue_pairs = vsi->alloc_queue_pairs;
+ /* VFs only use TC 0 */
+ vfres->vsi_res[i].qset_handle
+ = le16_to_cpu(vsi->info.qs_handle[0]);
+ ether_addr_copy(vfres->vsi_res[i].default_mac_addr,
+ vf->default_lan_addr.addr);
i++;
}
set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
@@ -1582,6 +1602,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
}
vsi = pf->vsi[vf->lan_vsi_idx];
+ /* Lock once, because all function inside for loop accesses VSI's
+ * MAC filter list which needs to be protected using same lock.
+ */
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+
/* add new addresses to the list */
for (i = 0; i < al->num_elements; i++) {
struct i40e_mac_filter *f;
@@ -1600,12 +1625,14 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
dev_err(&pf->pdev->dev,
"Unable to add VF MAC filter\n");
ret = I40E_ERR_PARAM;
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
goto error_param;
}
}
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
/* program the updated filter list */
- if (i40e_sync_vsi_filters(vsi))
+ if (i40e_sync_vsi_filters(vsi, false))
dev_err(&pf->pdev->dev, "Unable to program VF MAC filters\n");
error_param:
@@ -1650,13 +1677,15 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
}
vsi = pf->vsi[vf->lan_vsi_idx];
+ spin_lock_bh(&vsi->mac_filter_list_lock);
/* delete addresses from the list */
for (i = 0; i < al->num_elements; i++)
i40e_del_filter(vsi, al->list[i].addr,
I40E_VLAN_ANY, true, false);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
/* program the updated filter list */
- if (i40e_sync_vsi_filters(vsi))
+ if (i40e_sync_vsi_filters(vsi, false))
dev_err(&pf->pdev->dev, "Unable to program VF MAC filters\n");
error_param:
@@ -1708,6 +1737,7 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
for (i = 0; i < vfl->num_elements; i++) {
/* add new VLAN filter */
int ret = i40e_vsi_add_vlan(vsi, vfl->vlan_id[i]);
+
if (ret)
dev_err(&pf->pdev->dev,
"Unable to add VF vlan filter %d, error %d\n",
@@ -1759,6 +1789,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
for (i = 0; i < vfl->num_elements; i++) {
int ret = i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]);
+
if (ret)
dev_err(&pf->pdev->dev,
"Unable to delete VF vlan filter %d, error %d\n",
@@ -1870,7 +1901,6 @@ static int i40e_vc_validate_vf_msg(struct i40e_vf *vf, u32 v_opcode,
case I40E_VIRTCHNL_OP_UNKNOWN:
default:
return -EPERM;
- break;
}
/* few more checks */
if ((valid_len != msglen) || (err_msg_format)) {
@@ -2049,6 +2079,11 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
goto error_param;
}
+ /* Lock once because below invoked function add/del_filter requires
+ * mac_filter_list_lock to be held
+ */
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+
/* delete the temporary mac address */
i40e_del_filter(vsi, vf->default_lan_addr.addr,
vf->port_vlan_id ? vf->port_vlan_id : -1,
@@ -2060,9 +2095,11 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
list_for_each_entry(f, &vsi->mac_filter_list, list)
i40e_del_filter(vsi, f->macaddr, f->vlan, true, false);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+
dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id);
/* program mac filter */
- if (i40e_sync_vsi_filters(vsi)) {
+ if (i40e_sync_vsi_filters(vsi, false)) {
dev_err(&pf->pdev->dev, "Unable to program ucast filters\n");
ret = -EIO;
goto error_param;
@@ -2089,8 +2126,10 @@ error_param:
int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
int vf_id, u16 vlan_id, u8 qos)
{
+ u16 vlanprio = vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT);
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
+ bool is_vsi_in_vlan = false;
struct i40e_vsi *vsi;
struct i40e_vf *vf;
int ret = 0;
@@ -2116,12 +2155,15 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
goto error_pvid;
}
- if (le16_to_cpu(vsi->info.pvid) ==
- (vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT)))
+ if (le16_to_cpu(vsi->info.pvid) == vlanprio)
/* duplicate request, so just return success */
goto error_pvid;
- if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {
+ spin_lock_bh(&vsi->mac_filter_list_lock);
+ is_vsi_in_vlan = i40e_is_vsi_in_vlan(vsi);
+ spin_unlock_bh(&vsi->mac_filter_list_lock);
+
+ if (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) {
dev_err(&pf->pdev->dev,
"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
vf_id);
@@ -2141,7 +2183,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
* MAC addresses deleted.
*/
if ((!(vlan_id || qos) ||
- (vlan_id | qos) != le16_to_cpu(vsi->info.pvid)) &&
+ vlanprio != le16_to_cpu(vsi->info.pvid)) &&
vsi->info.pvid)
ret = i40e_vsi_add_vlan(vsi, I40E_VLAN_ANY);
@@ -2156,8 +2198,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
}
}
if (vlan_id || qos)
- ret = i40e_vsi_add_pvid(vsi,
- vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT));
+ ret = i40e_vsi_add_pvid(vsi, vlanprio);
else
i40e_vsi_remove_pvid(vsi);
@@ -2310,7 +2351,7 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
ivi->vf = vf_id;
- memcpy(&ivi->mac, vf->default_lan_addr.addr, ETH_ALEN);
+ ether_addr_copy(ivi->mac, vf->default_lan_addr.addr);
ivi->max_tx_rate = vf->tx_rate;
ivi->min_tx_rate = 0;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 736f6f08b4f2..da44995def42 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -29,8 +29,6 @@
#include "i40e.h"
-#define I40E_MAX_MACVLAN_FILTERS 256
-#define I40E_MAX_VLAN_FILTERS 256
#define I40E_MAX_VLANID 4095
#define I40E_VIRTCHNL_SUPPORTED_QTYPES 2
@@ -98,7 +96,8 @@ struct i40e_vf {
u8 num_queue_pairs; /* num of qps assigned to VF vsis */
u64 num_mdd_events; /* num of mdd events detected */
- u64 num_invalid_msgs; /* num of malformed or invalid msgs detected */
+ /* num of continuous malformed or invalid msgs detected */
+ u64 num_invalid_msgs;
u64 num_valid_msgs; /* num of valid msgs detected */
unsigned long vf_caps; /* vf's adv. capabilities */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
index 929d47152bf2..fd123ca60761 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
@@ -373,7 +373,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
hw->aq.asq.next_to_use = 0;
hw->aq.asq.next_to_clean = 0;
- hw->aq.asq.count = hw->aq.num_asq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -391,6 +390,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
goto init_adminq_free_rings;
/* success! */
+ hw->aq.asq.count = hw->aq.num_asq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
@@ -432,7 +432,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
hw->aq.arq.next_to_use = 0;
hw->aq.arq.next_to_clean = 0;
- hw->aq.arq.count = hw->aq.num_arq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -450,6 +449,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
goto init_adminq_free_rings;
/* success! */
+ hw->aq.arq.count = hw->aq.num_arq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
@@ -469,8 +469,12 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
{
i40e_status ret_code = 0;
- if (hw->aq.asq.count == 0)
- return I40E_ERR_NOT_READY;
+ mutex_lock(&hw->aq.asq_mutex);
+
+ if (hw->aq.asq.count == 0) {
+ ret_code = I40E_ERR_NOT_READY;
+ goto shutdown_asq_out;
+ }
/* Stop firmware AdminQ processing */
wr32(hw, hw->aq.asq.head, 0);
@@ -479,16 +483,13 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
wr32(hw, hw->aq.asq.bal, 0);
wr32(hw, hw->aq.asq.bah, 0);
- /* make sure lock is available */
- mutex_lock(&hw->aq.asq_mutex);
-
hw->aq.asq.count = 0; /* to indicate uninitialized queue */
/* free ring buffers */
i40e_free_asq_bufs(hw);
+shutdown_asq_out:
mutex_unlock(&hw->aq.asq_mutex);
-
return ret_code;
}
@@ -502,8 +503,12 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
{
i40e_status ret_code = 0;
- if (hw->aq.arq.count == 0)
- return I40E_ERR_NOT_READY;
+ mutex_lock(&hw->aq.arq_mutex);
+
+ if (hw->aq.arq.count == 0) {
+ ret_code = I40E_ERR_NOT_READY;
+ goto shutdown_arq_out;
+ }
/* Stop firmware AdminQ processing */
wr32(hw, hw->aq.arq.head, 0);
@@ -512,16 +517,13 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
wr32(hw, hw->aq.arq.bal, 0);
wr32(hw, hw->aq.arq.bah, 0);
- /* make sure lock is available */
- mutex_lock(&hw->aq.arq_mutex);
-
hw->aq.arq.count = 0; /* to indicate uninitialized queue */
/* free ring buffers */
i40e_free_arq_bufs(hw);
+shutdown_arq_out:
mutex_unlock(&hw->aq.arq_mutex);
-
return ret_code;
}
@@ -596,6 +598,9 @@ i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw)
/* destroy the locks */
+ if (hw->nvm_buff.va)
+ i40e_free_virt_mem(hw, &hw->nvm_buff);
+
return ret_code;
}
@@ -617,8 +622,7 @@ static u16 i40e_clean_asq(struct i40e_hw *hw)
details = I40E_ADMINQ_DETAILS(*asq, ntc);
while (rd32(hw, hw->aq.asq.head) != ntc) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "%s: ntc %d head %d.\n", __func__, ntc,
- rd32(hw, hw->aq.asq.head));
+ "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head));
if (details->callback) {
I40E_ADMINQ_CALLBACK cb_func =
@@ -682,19 +686,23 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
u16 retval = 0;
u32 val = 0;
- val = rd32(hw, hw->aq.asq.head);
- if (val >= hw->aq.num_asq_entries) {
+ mutex_lock(&hw->aq.asq_mutex);
+
+ if (hw->aq.asq.count == 0) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: head overrun at %d\n", val);
+ "AQTX: Admin queue not initialized.\n");
status = I40E_ERR_QUEUE_EMPTY;
- goto asq_send_command_exit;
+ goto asq_send_command_error;
}
- if (hw->aq.asq.count == 0) {
+ hw->aq.asq_last_status = I40E_AQ_RC_OK;
+
+ val = rd32(hw, hw->aq.asq.head);
+ if (val >= hw->aq.num_asq_entries) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Admin queue not initialized.\n");
+ "AQTX: head overrun at %d\n", val);
status = I40E_ERR_QUEUE_EMPTY;
- goto asq_send_command_exit;
+ goto asq_send_command_error;
}
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
@@ -719,8 +727,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
desc->flags &= ~cpu_to_le16(details->flags_dis);
desc->flags |= cpu_to_le16(details->flags_ena);
- mutex_lock(&hw->aq.asq_mutex);
-
if (buff_size > hw->aq.asq_buf_size) {
i40e_debug(hw,
I40E_DEBUG_AQ_MESSAGE,
@@ -830,6 +836,10 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff,
buff_size);
+ /* save writeback aq if requested */
+ if (details->wb_desc)
+ *details->wb_desc = *desc_on_ring;
+
/* update the error if time out occurred */
if ((!cmd_completed) &&
(!details->async && !details->postpone)) {
@@ -841,7 +851,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
asq_send_command_error:
mutex_unlock(&hw->aq.asq_mutex);
-asq_send_command_exit:
return status;
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
index ef43d68f67b3..a3eae5d9a2bd 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
@@ -69,6 +69,7 @@ struct i40e_asq_cmd_details {
u16 flags_dis;
bool async;
bool postpone;
+ struct i40e_aq_desc *wb_desc;
};
#define I40E_ADMINQ_DETAILS(R, i) \
@@ -108,9 +109,10 @@ struct i40e_adminq_info {
/**
* i40e_aq_rc_to_posix - convert errors to user-land codes
- * aq_rc: AdminQ error code to convert
+ * aq_ret: AdminQ handler error code can override aq_rc
+ * aq_rc: AdminQ firmware error code to convert
**/
-static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc)
+static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
{
int aq_to_posix[] = {
0, /* I40E_AQ_RC_OK */
@@ -142,8 +144,9 @@ static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc)
if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
return -EAGAIN;
- if (aq_rc >= ARRAY_SIZE(aq_to_posix))
+ if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
return -ERANGE;
+
return aq_to_posix[aq_rc];
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index c8022092d369..fcb9ef34cc7a 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -1719,11 +1719,13 @@ struct i40e_aqc_get_link_status {
u8 phy_type; /* i40e_aq_phy_type */
u8 link_speed; /* i40e_aq_link_speed */
u8 link_info;
-#define I40E_AQ_LINK_UP 0x01
+#define I40E_AQ_LINK_UP 0x01 /* obsolete */
+#define I40E_AQ_LINK_UP_FUNCTION 0x01
#define I40E_AQ_LINK_FAULT 0x02
#define I40E_AQ_LINK_FAULT_TX 0x04
#define I40E_AQ_LINK_FAULT_RX 0x08
#define I40E_AQ_LINK_FAULT_REMOTE 0x10
+#define I40E_AQ_LINK_UP_PORT 0x20
#define I40E_AQ_MEDIA_AVAILABLE 0x40
#define I40E_AQ_SIGNAL_DETECT 0x80
u8 an_info;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
index d45d0ae6bd3b..72b1942a94aa 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c
@@ -51,7 +51,9 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_QSFP_B:
case I40E_DEV_ID_QSFP_C:
case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_20G_KR2:
+ case I40E_DEV_ID_20G_KR2_A:
hw->mac.type = I40E_MAC_XL710;
break;
case I40E_DEV_ID_SFP_X722:
@@ -85,7 +87,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)
* @hw: pointer to the HW structure
* @aq_err: the AQ error code to convert
**/
-char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
+const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
{
switch (aq_err) {
case I40E_AQ_RC_OK:
@@ -145,7 +147,7 @@ char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
* @hw: pointer to the HW structure
* @stat_err: the status error code to convert
**/
-char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err)
+const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err)
{
switch (stat_err) {
case 0:
@@ -329,25 +331,11 @@ void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
len = buf_len;
/* write the full 16-byte chunks */
for (i = 0; i < (len - 16); i += 16)
- i40e_debug(hw, mask,
- "\t0x%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
- i, buf[i], buf[i + 1], buf[i + 2],
- buf[i + 3], buf[i + 4], buf[i + 5],
- buf[i + 6], buf[i + 7], buf[i + 8],
- buf[i + 9], buf[i + 10], buf[i + 11],
- buf[i + 12], buf[i + 13], buf[i + 14],
- buf[i + 15]);
+ i40e_debug(hw, mask, "\t0x%04X %16ph\n", i, buf + i);
/* write whatever's left over without overrunning the buffer */
- if (i < len) {
- char d_buf[80];
- int j = 0;
-
- memset(d_buf, 0, sizeof(d_buf));
- j += sprintf(d_buf, "\t0x%04X ", i);
- while (i < len)
- j += sprintf(&d_buf[j], " %02X", buf[i++]);
- i40e_debug(hw, mask, "%s\n", d_buf);
- }
+ if (i < len)
+ i40e_debug(hw, mask, "\t0x%04X %*ph\n",
+ i, len - i, buf + i);
}
}
@@ -441,9 +429,6 @@ static i40e_status i40e_aq_get_set_rss_lut(struct i40e_hw *hw,
I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
- cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)lut));
- cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)lut));
-
status = i40evf_asq_send_command(hw, &desc, lut, lut_size, NULL);
return status;
@@ -518,8 +503,6 @@ static i40e_status i40e_aq_get_set_rss_key(struct i40e_hw *hw,
I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) &
I40E_AQC_SET_RSS_KEY_VSI_ID_MASK));
cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID);
- cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)key));
- cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)key));
status = i40evf_asq_send_command(hw, &desc, key, key_size, NULL);
@@ -990,10 +973,10 @@ void i40e_vf_parse_hw_config(struct i40e_hw *hw,
I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0;
for (i = 0; i < msg->num_vsis; i++) {
if (vsi_res->vsi_type == I40E_VSI_SRIOV) {
- memcpy(hw->mac.perm_addr, vsi_res->default_mac_addr,
- ETH_ALEN);
- memcpy(hw->mac.addr, vsi_res->default_mac_addr,
- ETH_ALEN);
+ ether_addr_copy(hw->mac.perm_addr,
+ vsi_res->default_mac_addr);
+ ether_addr_copy(hw->mac.addr,
+ vsi_res->default_mac_addr);
}
vsi_res++;
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
new file mode 100644
index 000000000000..e6a39c9862e8
--- /dev/null
+++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 - 2015 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.
+ *
+ * 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".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_DEVIDS_H_
+#define _I40E_DEVIDS_H_
+
+/* Device IDs */
+#define I40E_DEV_ID_SFP_XL710 0x1572
+#define I40E_DEV_ID_QEMU 0x1574
+#define I40E_DEV_ID_KX_A 0x157F
+#define I40E_DEV_ID_KX_B 0x1580
+#define I40E_DEV_ID_KX_C 0x1581
+#define I40E_DEV_ID_QSFP_A 0x1583
+#define I40E_DEV_ID_QSFP_B 0x1584
+#define I40E_DEV_ID_QSFP_C 0x1585
+#define I40E_DEV_ID_10G_BASE_T 0x1586
+#define I40E_DEV_ID_20G_KR2 0x1587
+#define I40E_DEV_ID_20G_KR2_A 0x1588
+#define I40E_DEV_ID_10G_BASE_T4 0x1589
+#define I40E_DEV_ID_VF 0x154C
+#define I40E_DEV_ID_VF_HV 0x1571
+#define I40E_DEV_ID_SFP_X722 0x37D0
+#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
+#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
+#define I40E_DEV_ID_X722_VF 0x37CD
+#define I40E_DEV_ID_X722_VF_HV 0x37D9
+
+#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
+ (d) == I40E_DEV_ID_QSFP_B || \
+ (d) == I40E_DEV_ID_QSFP_C)
+
+#endif /* _I40E_DEVIDS_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
index 21a91b14bf81..5e314fd3c016 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
@@ -34,7 +34,7 @@
#include <linux/pci.h>
/* get readq/writeq support for 32 bit kernels, use the low-first version */
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
/* File to be the magic between shared code and
* actual OS primitives
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
index 55ae4b0f8192..cbd9a1b078ab 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
@@ -60,8 +60,8 @@ void i40e_idle_aq(struct i40e_hw *hw);
void i40evf_resume_aq(struct i40e_hw *hw);
bool i40evf_check_asq_alive(struct i40e_hw *hw);
i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw, bool unloading);
-char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
-char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err);
+const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
+const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err);
i40e_status i40evf_aq_get_rss_lut(struct i40e_hw *hw, u16 seid,
bool pf_lut, u8 *lut, u16 lut_size);
@@ -101,4 +101,6 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
u16 vsi_seid, u16 queue, bool is_add,
struct i40e_control_filter_stats *stats,
struct i40e_asq_cmd_details *cmd_details);
+void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
+ u16 vsi_seid);
#endif /* _I40E_PROTOTYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 7e91d825c760..47e9a90d6b10 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -140,65 +140,6 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring)
return le32_to_cpu(*(volatile __le32 *)head);
}
-/**
- * i40e_get_tx_pending - how many tx descriptors not processed
- * @tx_ring: the ring of descriptors
- *
- * Since there is no access to the ring head register
- * in XL710, we need to use our local copies
- **/
-static u32 i40e_get_tx_pending(struct i40e_ring *ring)
-{
- u32 head, tail;
-
- head = i40e_get_head(ring);
- tail = readl(ring->tail);
-
- if (head != tail)
- return (head < tail) ?
- tail - head : (tail + ring->count - head);
-
- return 0;
-}
-
-/**
- * i40e_check_tx_hang - Is there a hang in the Tx queue
- * @tx_ring: the ring of descriptors
- **/
-static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)
-{
- u32 tx_done = tx_ring->stats.packets;
- u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
- u32 tx_pending = i40e_get_tx_pending(tx_ring);
- bool ret = false;
-
- clear_check_for_tx_hang(tx_ring);
-
- /* Check for a hung queue, but be thorough. This verifies
- * that a transmit has been completed since the previous
- * check AND there is at least one packet pending. The
- * ARMED bit is set to indicate a potential hang. The
- * bit is cleared if a pause frame is received to remove
- * false hang detection due to PFC or 802.3x frames. By
- * requiring this to fail twice we avoid races with
- * PFC clearing the ARMED bit and conditions where we
- * run the check_tx_hang logic with a transmit completion
- * pending but without time to complete it yet.
- */
- if ((tx_done_old == tx_done) && tx_pending) {
- /* make sure it is true for two checks in a row */
- ret = test_and_set_bit(__I40E_HANG_CHECK_ARMED,
- &tx_ring->state);
- } else if (tx_done_old == tx_done &&
- (tx_pending < I40E_MIN_DESC_PENDING) && (tx_pending > 0)) {
- /* update completed stats and disarm the hang check */
- tx_ring->tx_stats.tx_done_old = tx_done;
- clear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state);
- }
-
- return ret;
-}
-
#define WB_STRIDE 0x3
/**
@@ -304,36 +245,15 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
tx_ring->q_vector->tx.total_bytes += total_bytes;
tx_ring->q_vector->tx.total_packets += total_packets;
+ /* check to see if there are any non-cache aligned descriptors
+ * waiting to be written back, and kick the hardware to force
+ * them to be written back in case of napi polling
+ */
if (budget &&
!((i & WB_STRIDE) == WB_STRIDE) &&
!test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
- else
- tx_ring->arm_wb = false;
-
- if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {
- /* schedule immediate reset if we believe we hung */
- dev_info(tx_ring->dev, "Detected Tx Unit Hang\n"
- " VSI <%d>\n"
- " Tx Queue <%d>\n"
- " next_to_use <%x>\n"
- " next_to_clean <%x>\n",
- tx_ring->vsi->seid,
- tx_ring->queue_index,
- tx_ring->next_to_use, i);
-
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
-
- dev_info(tx_ring->dev,
- "tx hang detected on queue %d, resetting adapter\n",
- tx_ring->queue_index);
-
- tx_ring->netdev->netdev_ops->ndo_tx_timeout(tx_ring->netdev);
-
- /* the adapter is about to reset, no point in enabling stuff */
- return true;
- }
netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index),
@@ -355,16 +275,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
}
}
- return budget > 0;
+ return !!budget;
}
/**
- * i40e_force_wb -Arm hardware to do a wb on noncache aligned descriptors
+ * i40evf_force_wb -Arm hardware to do a wb on noncache aligned descriptors
* @vsi: the VSI we care about
* @q_vector: the vector on which to force writeback
*
**/
-static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
+static void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
{
u16 flags = q_vector->tx.ring[0].flags;
@@ -398,6 +318,8 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
* i40e_set_new_dynamic_itr - Find new ITR level
* @rc: structure containing ring performance data
*
+ * Returns true if ITR changed, false if not
+ *
* Stores a new ITR value based on packets and byte counts during
* the last interrupt. The advantage of per interrupt computation
* is faster updates and more accurate ITR for the current traffic
@@ -406,21 +328,32 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
* testing data as well as attempting to minimize response time
* while increasing bulk throughput.
**/
-static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
+static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
{
enum i40e_latency_range new_latency_range = rc->latency_range;
+ struct i40e_q_vector *qv = rc->ring->q_vector;
u32 new_itr = rc->itr;
int bytes_per_int;
+ int usecs;
if (rc->total_packets == 0 || !rc->itr)
- return;
+ return false;
/* simple throttlerate management
- * 0-10MB/s lowest (100000 ints/s)
+ * 0-10MB/s lowest (50000 ints/s)
* 10-20MB/s low (20000 ints/s)
- * 20-1249MB/s bulk (8000 ints/s)
+ * 20-1249MB/s bulk (18000 ints/s)
+ * > 40000 Rx packets per second (8000 ints/s)
+ *
+ * The math works out because the divisor is in 10^(-6) which
+ * turns the bytes/us input value into MB/s values, but
+ * make sure to use usecs, as the register values written
+ * are in 2 usec increments in the ITR registers, and make sure
+ * to use the smoothed values that the countdown timer gives us.
*/
- bytes_per_int = rc->total_bytes / rc->itr;
+ usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
+ bytes_per_int = rc->total_bytes / usecs;
+
switch (new_latency_range) {
case I40E_LOWEST_LATENCY:
if (bytes_per_int > 10)
@@ -433,35 +366,52 @@ static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
new_latency_range = I40E_LOWEST_LATENCY;
break;
case I40E_BULK_LATENCY:
- if (bytes_per_int <= 20)
- new_latency_range = I40E_LOW_LATENCY;
- break;
+ case I40E_ULTRA_LATENCY:
default:
if (bytes_per_int <= 20)
new_latency_range = I40E_LOW_LATENCY;
break;
}
+
+ /* this is to adjust RX more aggressively when streaming small
+ * packets. The value of 40000 was picked as it is just beyond
+ * what the hardware can receive per second if in low latency
+ * mode.
+ */
+#define RX_ULTRA_PACKET_RATE 40000
+
+ if ((((rc->total_packets * 1000000) / usecs) > RX_ULTRA_PACKET_RATE) &&
+ (&qv->rx == rc))
+ new_latency_range = I40E_ULTRA_LATENCY;
+
rc->latency_range = new_latency_range;
switch (new_latency_range) {
case I40E_LOWEST_LATENCY:
- new_itr = I40E_ITR_100K;
+ new_itr = I40E_ITR_50K;
break;
case I40E_LOW_LATENCY:
new_itr = I40E_ITR_20K;
break;
case I40E_BULK_LATENCY:
+ new_itr = I40E_ITR_18K;
+ break;
+ case I40E_ULTRA_LATENCY:
new_itr = I40E_ITR_8K;
break;
default:
break;
}
- if (new_itr != rc->itr)
- rc->itr = new_itr;
-
rc->total_bytes = 0;
rc->total_packets = 0;
+
+ if (new_itr != rc->itr) {
+ rc->itr = new_itr;
+ return true;
+ }
+
+ return false;
}
/*
@@ -822,16 +772,11 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
struct sk_buff *skb, u16 vlan_tag)
{
struct i40e_q_vector *q_vector = rx_ring->q_vector;
- struct i40e_vsi *vsi = rx_ring->vsi;
- u64 flags = vsi->back->flags;
if (vlan_tag & VLAN_VID_MASK)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
- if (flags & I40E_FLAG_IN_NETPOLL)
- netif_rx(skb);
- else
- napi_gro_receive(&q_vector->napi, skb);
+ napi_gro_receive(&q_vector->napi, skb);
}
/**
@@ -997,7 +942,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
u16 rx_packet_len, rx_header_len, rx_sph, rx_hbo;
u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
- const int current_node = numa_node_id();
+ const int current_node = numa_mem_id();
struct i40e_vsi *vsi = rx_ring->vsi;
u16 i = rx_ring->next_to_clean;
union i40e_rx_desc *rx_desc;
@@ -1067,6 +1012,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
cleaned_count++;
if (rx_hbo || rx_sph) {
int len;
+
if (rx_hbo)
len = I40E_RX_HDR_SIZE;
else
@@ -1240,9 +1186,6 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget)
/* ERR_MASK will only have valid bits if EOP set */
if (unlikely(rx_error & BIT(I40E_RX_DESC_ERROR_RXE_SHIFT))) {
dev_kfree_skb_any(skb);
- /* TODO: shouldn't we increment a counter indicating the
- * drop?
- */
continue;
}
@@ -1274,6 +1217,21 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget)
return total_rx_packets;
}
+static u32 i40e_buildreg_itr(const int type, const u16 itr)
+{
+ u32 val;
+
+ val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+ I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
+ (type << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
+ (itr << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT);
+
+ return val;
+}
+
+/* a small macro to shorten up some long lines */
+#define INTREG I40E_VFINT_DYN_CTLN1
+
/**
* i40e_update_enable_itr - Update itr and re-enable MSIX interrupt
* @vsi: the VSI we care about
@@ -1284,55 +1242,67 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
struct i40e_q_vector *q_vector)
{
struct i40e_hw *hw = &vsi->back->hw;
- u16 old_itr;
+ bool rx = false, tx = false;
+ u32 rxval, txval;
int vector;
- u32 val;
vector = (q_vector->v_idx + vsi->base_vector);
+
+ /* avoid dynamic calculation if in countdown mode OR if
+ * all dynamic is disabled
+ */
+ rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
+
+ if (q_vector->itr_countdown > 0 ||
+ (!ITR_IS_DYNAMIC(vsi->rx_itr_setting) &&
+ !ITR_IS_DYNAMIC(vsi->tx_itr_setting))) {
+ goto enable_int;
+ }
+
if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) {
- old_itr = q_vector->rx.itr;
- i40e_set_new_dynamic_itr(&q_vector->rx);
- if (old_itr != q_vector->rx.itr) {
- val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
- (I40E_RX_ITR <<
- I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
- (q_vector->rx.itr <<
- I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT);
- } else {
- val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
- (I40E_ITR_NONE <<
- I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT);
- }
- if (!test_bit(__I40E_DOWN, &vsi->state))
- wr32(hw, I40E_VFINT_DYN_CTLN1(vector - 1), val);
- } else {
- i40evf_irq_enable_queues(vsi->back, 1
- << q_vector->v_idx);
+ rx = i40e_set_new_dynamic_itr(&q_vector->rx);
+ rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);
}
if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) {
- old_itr = q_vector->tx.itr;
- i40e_set_new_dynamic_itr(&q_vector->tx);
- if (old_itr != q_vector->tx.itr) {
- val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
- (I40E_TX_ITR <<
- I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
- (q_vector->tx.itr <<
- I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT);
+ tx = i40e_set_new_dynamic_itr(&q_vector->tx);
+ txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr);
+ }
+ if (rx || tx) {
+ /* get the higher of the two ITR adjustments and
+ * use the same value for both ITR registers
+ * when in adaptive mode (Rx and/or Tx)
+ */
+ u16 itr = max(q_vector->tx.itr, q_vector->rx.itr);
- } else {
- val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
- (I40E_ITR_NONE <<
- I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT);
- }
- if (!test_bit(__I40E_DOWN, &vsi->state))
- wr32(hw, I40E_VFINT_DYN_CTLN1(vector - 1), val);
- } else {
- i40evf_irq_enable_queues(vsi->back, BIT(q_vector->v_idx));
+ q_vector->tx.itr = q_vector->rx.itr = itr;
+ txval = i40e_buildreg_itr(I40E_TX_ITR, itr);
+ tx = true;
+ rxval = i40e_buildreg_itr(I40E_RX_ITR, itr);
+ rx = true;
}
+
+ /* only need to enable the interrupt once, but need
+ * to possibly update both ITR values
+ */
+ if (rx) {
+ /* set the INTENA_MSK_MASK so that this first write
+ * won't actually enable the interrupt, instead just
+ * updating the ITR (it's bit 31 PF and VF)
+ */
+ rxval |= BIT(31);
+ /* don't check _DOWN because interrupt isn't being enabled */
+ wr32(hw, INTREG(vector - 1), rxval);
+ }
+
+enable_int:
+ if (!test_bit(__I40E_DOWN, &vsi->state))
+ wr32(hw, INTREG(vector - 1), txval);
+
+ if (q_vector->itr_countdown)
+ q_vector->itr_countdown--;
+ else
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+
}
/**
@@ -1353,7 +1323,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
bool clean_complete = true;
bool arm_wb = false;
int budget_per_ring;
- int cleaned;
+ int work_done = 0;
if (test_bit(__I40E_DOWN, &vsi->state)) {
napi_complete(napi);
@@ -1366,26 +1336,36 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
i40e_for_each_ring(ring, q_vector->tx) {
clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit);
arm_wb |= ring->arm_wb;
+ ring->arm_wb = false;
}
+ /* Handle case where we are called by netpoll with a budget of 0 */
+ if (budget <= 0)
+ goto tx_only;
+
/* We attempt to distribute budget to each Rx queue fairly, but don't
* allow the budget to go below 1 because that would exit polling early.
*/
budget_per_ring = max(budget/q_vector->num_ringpairs, 1);
i40e_for_each_ring(ring, q_vector->rx) {
+ int cleaned;
+
if (ring_is_ps_enabled(ring))
cleaned = i40e_clean_rx_irq_ps(ring, budget_per_ring);
else
cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring);
+
+ work_done += cleaned;
/* if we didn't clean as many as budgeted, we must be done */
clean_complete &= (budget_per_ring != cleaned);
}
/* If work not completed, return budget and polling will return */
if (!clean_complete) {
+tx_only:
if (arm_wb)
- i40e_force_wb(vsi, q_vector);
+ i40evf_force_wb(vsi, q_vector);
return budget;
}
@@ -1393,7 +1373,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
q_vector->arm_wb_state = false;
/* Work is done so exit the polling mode and re-enable the interrupt */
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
i40e_update_enable_itr(vsi, q_vector);
return 0;
}
@@ -1437,6 +1417,7 @@ static inline int i40evf_tx_prepare_vlan_flags(struct sk_buff *skb,
/* else if it is a SW VLAN, check the next protocol and store the tag */
} else if (protocol == htons(ETH_P_8021Q)) {
struct vlan_hdr *vhdr, _vhdr;
+
vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
if (!vhdr)
return -EINVAL;
@@ -1979,6 +1960,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
u32 td_cmd = 0;
u8 hdr_len = 0;
int tso;
+
if (0 == i40evf_xmit_descriptor_count(skb, tx_ring))
return NETDEV_TX_BUSY;
@@ -2006,10 +1988,11 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
else if (tso)
tx_flags |= I40E_TX_FLAGS_TSO;
- if (i40e_chk_linearize(skb, tx_flags))
+ if (i40e_chk_linearize(skb, tx_flags)) {
if (skb_linearize(skb))
goto out_drop;
-
+ tx_ring->tx_stats.tx_linearize++;
+ }
skb_tx_timestamp(skb);
/* always enable CRC insertion offload */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
index 9a30f5d8c089..ebc1bf77f036 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
@@ -32,11 +32,14 @@
#define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */
#define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */
#define I40E_ITR_100K 0x0005
+#define I40E_ITR_50K 0x000A
#define I40E_ITR_20K 0x0019
+#define I40E_ITR_18K 0x001B
#define I40E_ITR_8K 0x003E
#define I40E_ITR_4K 0x007A
-#define I40E_ITR_RX_DEF I40E_ITR_8K
-#define I40E_ITR_TX_DEF I40E_ITR_4K
+#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */
+#define I40E_ITR_RX_DEF I40E_ITR_20K
+#define I40E_ITR_TX_DEF I40E_ITR_20K
#define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
#define I40E_MIN_INT_RATE 250 /* ~= 1000000 / (I40E_MAX_ITR * 2) */
#define I40E_MAX_INT_RATE 500000 /* == 1000000 / (I40E_MIN_ITR * 2) */
@@ -44,6 +47,15 @@
#define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1)
#define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC))
#define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1)
+/* 0x40 is the enable bit for interrupt rate limiting, and must be set if
+ * the value of the rate limit is non-zero
+ */
+#define INTRL_ENA BIT(6)
+#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2)
+#define INTRL_USEC_TO_REG(set) ((set) ? ((set) >> 2) | INTRL_ENA : 0)
+#define I40E_INTRL_8K 125 /* 8000 ints/sec */
+#define I40E_INTRL_62K 16 /* 62500 ints/sec */
+#define I40E_INTRL_83K 12 /* 83333 ints/sec */
#define I40E_QUEUE_END_OF_LIST 0x7FF
@@ -79,16 +91,16 @@ enum i40e_dyn_idx_t {
BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD))
#define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \
- BIT(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
- BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
- BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
- BIT(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
- BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
- BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
#define i40e_pf_get_default_rss_hena(pf) \
(((pf)->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \
- I40E_DEFAULT_RSS_HENA_EXPANDED : I40E_DEFAULT_RSS_HENA)
+ I40E_DEFAULT_RSS_HENA_EXPANDED : I40E_DEFAULT_RSS_HENA)
/* Supported Rx Buffer Sizes */
#define I40E_RXBUFFER_512 512 /* Used for packet split */
@@ -164,6 +176,7 @@ struct i40e_tx_buffer {
};
unsigned int bytecount;
unsigned short gso_segs;
+
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
u32 tx_flags;
@@ -187,6 +200,7 @@ struct i40e_tx_queue_stats {
u64 restart_queue;
u64 tx_busy;
u64 tx_done_old;
+ u64 tx_linearize;
};
struct i40e_rx_queue_stats {
@@ -198,8 +212,6 @@ struct i40e_rx_queue_stats {
enum i40e_ring_state_t {
__I40E_TX_FDIR_INIT_DONE,
__I40E_TX_XPS_INIT_DONE,
- __I40E_TX_DETECT_HANG,
- __I40E_HANG_CHECK_ARMED,
__I40E_RX_PS_ENABLED,
__I40E_RX_16BYTE_DESC_ENABLED,
};
@@ -210,12 +222,6 @@ enum i40e_ring_state_t {
set_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
#define clear_ring_ps_enabled(ring) \
clear_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
-#define check_for_tx_hang(ring) \
- test_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
-#define set_check_for_tx_hang(ring) \
- set_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
-#define clear_check_for_tx_hang(ring) \
- clear_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
#define ring_is_16byte_desc_enabled(ring) \
test_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)
#define set_ring_16byte_desc_enabled(ring) \
@@ -287,6 +293,7 @@ enum i40e_latency_range {
I40E_LOWEST_LATENCY = 0,
I40E_LOW_LATENCY = 1,
I40E_BULK_LATENCY = 2,
+ I40E_ULTRA_LATENCY = 3,
};
struct i40e_ring_container {
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 24a2693869a1..301fe2b6dd03 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -33,29 +33,7 @@
#include "i40e_adminq.h"
#include "i40e_hmc.h"
#include "i40e_lan_hmc.h"
-
-/* Device IDs */
-#define I40E_DEV_ID_SFP_XL710 0x1572
-#define I40E_DEV_ID_QEMU 0x1574
-#define I40E_DEV_ID_KX_A 0x157F
-#define I40E_DEV_ID_KX_B 0x1580
-#define I40E_DEV_ID_KX_C 0x1581
-#define I40E_DEV_ID_QSFP_A 0x1583
-#define I40E_DEV_ID_QSFP_B 0x1584
-#define I40E_DEV_ID_QSFP_C 0x1585
-#define I40E_DEV_ID_10G_BASE_T 0x1586
-#define I40E_DEV_ID_20G_KR2 0x1587
-#define I40E_DEV_ID_VF 0x154C
-#define I40E_DEV_ID_VF_HV 0x1571
-#define I40E_DEV_ID_SFP_X722 0x37D0
-#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
-#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
-#define I40E_DEV_ID_X722_VF 0x37CD
-#define I40E_DEV_ID_X722_VF_HV 0x37D9
-
-#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
- (d) == I40E_DEV_ID_QSFP_B || \
- (d) == I40E_DEV_ID_QSFP_C)
+#include "i40e_devids.h"
/* I40E_MASK is a macro used on 32 bit registers */
#define I40E_MASK(mask, shift) (mask << shift)
@@ -158,14 +136,14 @@ enum i40e_set_fc_aq_failures {
};
enum i40e_vsi_type {
- I40E_VSI_MAIN = 0,
- I40E_VSI_VMDQ1,
- I40E_VSI_VMDQ2,
- I40E_VSI_CTRL,
- I40E_VSI_FCOE,
- I40E_VSI_MIRROR,
- I40E_VSI_SRIOV,
- I40E_VSI_FDIR,
+ I40E_VSI_MAIN = 0,
+ I40E_VSI_VMDQ1 = 1,
+ I40E_VSI_VMDQ2 = 2,
+ I40E_VSI_CTRL = 3,
+ I40E_VSI_FCOE = 4,
+ I40E_VSI_MIRROR = 5,
+ I40E_VSI_SRIOV = 6,
+ I40E_VSI_FDIR = 7,
I40E_VSI_TYPE_UNKNOWN
};
@@ -189,16 +167,65 @@ struct i40e_link_status {
bool crc_enable;
u8 pacing;
u8 requested_speeds;
+ u8 module_type[3];
+ /* 1st byte: module identifier */
+#define I40E_MODULE_TYPE_SFP 0x03
+#define I40E_MODULE_TYPE_QSFP 0x0D
+ /* 2nd byte: ethernet compliance codes for 10/40G */
+#define I40E_MODULE_TYPE_40G_ACTIVE 0x01
+#define I40E_MODULE_TYPE_40G_LR4 0x02
+#define I40E_MODULE_TYPE_40G_SR4 0x04
+#define I40E_MODULE_TYPE_40G_CR4 0x08
+#define I40E_MODULE_TYPE_10G_BASE_SR 0x10
+#define I40E_MODULE_TYPE_10G_BASE_LR 0x20
+#define I40E_MODULE_TYPE_10G_BASE_LRM 0x40
+#define I40E_MODULE_TYPE_10G_BASE_ER 0x80
+ /* 3rd byte: ethernet compliance codes for 1G */
+#define I40E_MODULE_TYPE_1000BASE_SX 0x01
+#define I40E_MODULE_TYPE_1000BASE_LX 0x02
+#define I40E_MODULE_TYPE_1000BASE_CX 0x04
+#define I40E_MODULE_TYPE_1000BASE_T 0x08
+};
+
+enum i40e_aq_capabilities_phy_type {
+ I40E_CAP_PHY_TYPE_SGMII = BIT(I40E_PHY_TYPE_SGMII),
+ I40E_CAP_PHY_TYPE_1000BASE_KX = BIT(I40E_PHY_TYPE_1000BASE_KX),
+ I40E_CAP_PHY_TYPE_10GBASE_KX4 = BIT(I40E_PHY_TYPE_10GBASE_KX4),
+ I40E_CAP_PHY_TYPE_10GBASE_KR = BIT(I40E_PHY_TYPE_10GBASE_KR),
+ I40E_CAP_PHY_TYPE_40GBASE_KR4 = BIT(I40E_PHY_TYPE_40GBASE_KR4),
+ I40E_CAP_PHY_TYPE_XAUI = BIT(I40E_PHY_TYPE_XAUI),
+ I40E_CAP_PHY_TYPE_XFI = BIT(I40E_PHY_TYPE_XFI),
+ I40E_CAP_PHY_TYPE_SFI = BIT(I40E_PHY_TYPE_SFI),
+ I40E_CAP_PHY_TYPE_XLAUI = BIT(I40E_PHY_TYPE_XLAUI),
+ I40E_CAP_PHY_TYPE_XLPPI = BIT(I40E_PHY_TYPE_XLPPI),
+ I40E_CAP_PHY_TYPE_40GBASE_CR4_CU = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU),
+ I40E_CAP_PHY_TYPE_10GBASE_CR1_CU = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU),
+ I40E_CAP_PHY_TYPE_10GBASE_AOC = BIT(I40E_PHY_TYPE_10GBASE_AOC),
+ I40E_CAP_PHY_TYPE_40GBASE_AOC = BIT(I40E_PHY_TYPE_40GBASE_AOC),
+ I40E_CAP_PHY_TYPE_100BASE_TX = BIT(I40E_PHY_TYPE_100BASE_TX),
+ I40E_CAP_PHY_TYPE_1000BASE_T = BIT(I40E_PHY_TYPE_1000BASE_T),
+ I40E_CAP_PHY_TYPE_10GBASE_T = BIT(I40E_PHY_TYPE_10GBASE_T),
+ I40E_CAP_PHY_TYPE_10GBASE_SR = BIT(I40E_PHY_TYPE_10GBASE_SR),
+ I40E_CAP_PHY_TYPE_10GBASE_LR = BIT(I40E_PHY_TYPE_10GBASE_LR),
+ I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU),
+ I40E_CAP_PHY_TYPE_10GBASE_CR1 = BIT(I40E_PHY_TYPE_10GBASE_CR1),
+ I40E_CAP_PHY_TYPE_40GBASE_CR4 = BIT(I40E_PHY_TYPE_40GBASE_CR4),
+ I40E_CAP_PHY_TYPE_40GBASE_SR4 = BIT(I40E_PHY_TYPE_40GBASE_SR4),
+ I40E_CAP_PHY_TYPE_40GBASE_LR4 = BIT(I40E_PHY_TYPE_40GBASE_LR4),
+ I40E_CAP_PHY_TYPE_1000BASE_SX = BIT(I40E_PHY_TYPE_1000BASE_SX),
+ I40E_CAP_PHY_TYPE_1000BASE_LX = BIT(I40E_PHY_TYPE_1000BASE_LX),
+ I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL =
+ BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL),
+ I40E_CAP_PHY_TYPE_20GBASE_KR2 = BIT(I40E_PHY_TYPE_20GBASE_KR2)
};
struct i40e_phy_info {
struct i40e_link_status link_info;
struct i40e_link_status link_info_old;
- u32 autoneg_advertised;
- u32 phy_id;
- u32 module_type;
bool get_link_info;
enum i40e_media_type media_type;
+ /* all the phy types the NVM is capable of */
+ enum i40e_aq_capabilities_phy_type phy_types;
};
#define I40E_HW_CAP_MAX_GPIO 30
@@ -286,6 +313,7 @@ struct i40e_nvm_info {
bool blank_nvm_mode; /* is NVM empty (no FW present)*/
u16 version; /* NVM package version */
u32 eetrack; /* NVM data version */
+ u32 oem_ver; /* OEM version info */
};
/* definitions used in NVM update support */
@@ -304,12 +332,17 @@ enum i40e_nvmupd_cmd {
I40E_NVMUPD_CSUM_CON,
I40E_NVMUPD_CSUM_SA,
I40E_NVMUPD_CSUM_LCB,
+ I40E_NVMUPD_STATUS,
+ I40E_NVMUPD_EXEC_AQ,
+ I40E_NVMUPD_GET_AQ_RESULT,
};
enum i40e_nvmupd_state {
I40E_NVMUPD_STATE_INIT,
I40E_NVMUPD_STATE_READING,
- I40E_NVMUPD_STATE_WRITING
+ I40E_NVMUPD_STATE_WRITING,
+ I40E_NVMUPD_STATE_INIT_WAIT,
+ I40E_NVMUPD_STATE_WRITE_WAIT,
};
/* nvm_access definition and its masks/shifts need to be accessible to
@@ -328,6 +361,7 @@ enum i40e_nvmupd_state {
#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
#define I40E_NVM_ERA 0x4
#define I40E_NVM_CSUM 0x8
+#define I40E_NVM_EXEC 0xf
#define I40E_NVM_ADAPT_SHIFT 16
#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
@@ -486,6 +520,8 @@ struct i40e_hw {
/* state of nvm update process */
enum i40e_nvmupd_state nvmupd_state;
+ struct i40e_aq_desc nvm_wb_desc;
+ struct i40e_virt_mem nvm_buff;
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
@@ -494,8 +530,9 @@ struct i40e_hw {
u16 dcbx_status;
/* DCBX info */
- struct i40e_dcbx_config local_dcbx_config;
- struct i40e_dcbx_config remote_dcbx_config;
+ struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */
+ struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
+ struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
/* debug mask */
u32 debug_mask;
@@ -1018,8 +1055,8 @@ enum i40e_filter_program_desc_fd_status {
};
#define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT 23
-#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK \
- BIT_ULL(I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT)
+#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK (0x1FFUL << \
+ I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT)
#define I40E_TXD_FLTR_QW1_CMD_SHIFT 4
#define I40E_TXD_FLTR_QW1_CMD_MASK (0xFFFFULL << \
@@ -1162,6 +1199,7 @@ struct i40e_hw_port_stats {
/* Checksum and Shadow RAM pointers */
#define I40E_SR_NVM_CONTROL_WORD 0x00
#define I40E_SR_EMP_MODULE_PTR 0x0F
+#define I40E_NVM_OEM_VER_OFF 0x83
#define I40E_SR_NVM_DEV_STARTER_VERSION 0x18
#define I40E_SR_NVM_WAKE_ON_LAN 0x19
#define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR 0x27
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
index e6db20e8a395..9f7b279b9d9c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
@@ -81,7 +81,6 @@ enum i40e_virtchnl_ops {
I40E_VIRTCHNL_OP_GET_STATS = 15,
I40E_VIRTCHNL_OP_FCOE = 16,
I40E_VIRTCHNL_OP_EVENT = 17,
- I40E_VIRTCHNL_OP_CONFIG_RSS = 18,
};
/* Virtual channel message descriptor. This overlays the admin queue
@@ -151,6 +150,7 @@ struct i40e_virtchnl_vsi_resource {
#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010
+#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020
#define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000
#define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index 3817cbbf45e6..22fc3d49c4b9 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -48,10 +48,6 @@
#define DEFAULT_DEBUG_LEVEL_SHIFT 3
#define PFX "i40evf: "
-#define DPRINTK(nlevel, klevel, fmt, args...) \
- ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
- printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
- __func__ , ## args)))
/* dummy struct to make common code less painful */
struct i40e_vsi {
@@ -70,6 +66,7 @@ struct i40e_vsi {
*/
u16 rx_itr_setting;
u16 tx_itr_setting;
+ u16 qs_handle;
};
/* How many Rx Buffers do we bundle into one write to the hardware ? */
@@ -90,7 +87,7 @@ struct i40e_vsi {
#define I40EVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */
#define I40EVF_MAX_AQ_BUF_SIZE 4096
#define I40EVF_AQ_LEN 32
-#define I40EVF_AQ_MAX_ERR 10 /* times to try before resetting AQ */
+#define I40EVF_AQ_MAX_ERR 20 /* times to try before resetting AQ */
#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
@@ -115,6 +112,8 @@ struct i40e_q_vector {
struct i40e_ring_container tx;
u32 ring_mask;
u8 num_ringpairs; /* total number of ring pairs in vector */
+#define ITR_COUNTDOWN_START 100
+ u8 itr_countdown; /* when 0 or 1 update ITR */
int v_idx; /* vector index in list */
char name[IFNAMSIZ + 9];
bool arm_wb_state;
@@ -214,7 +213,6 @@ struct i40evf_adapter {
#define I40EVF_FLAG_RX_1BUF_CAPABLE BIT(1)
#define I40EVF_FLAG_RX_PS_CAPABLE BIT(2)
#define I40EVF_FLAG_RX_PS_ENABLED BIT(3)
-#define I40EVF_FLAG_IN_NETPOLL BIT(4)
#define I40EVF_FLAG_IMIR_ENABLED BIT(5)
#define I40EVF_FLAG_MQ_CAPABLE BIT(6)
#define I40EVF_FLAG_NEED_LINK_UPDATE BIT(7)
@@ -223,10 +221,10 @@ struct i40evf_adapter {
#define I40EVF_FLAG_RESET_NEEDED BIT(10)
#define I40EVF_FLAG_WB_ON_ITR_CAPABLE BIT(11)
#define I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE BIT(12)
+#define I40EVF_FLAG_ADDR_SET_BY_PF BIT(13)
/* duplicates for common code */
#define I40E_FLAG_FDIR_ATR_ENABLED 0
#define I40E_FLAG_DCB_ENABLED 0
-#define I40E_FLAG_IN_NETPOLL I40EVF_FLAG_IN_NETPOLL
#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
#define I40E_FLAG_WB_ON_ITR_CAPABLE I40EVF_FLAG_WB_ON_ITR_CAPABLE
#define I40E_FLAG_OUTER_UDP_CSUM_CAPABLE I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index e85849b9ff98..d962164dfb0f 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf";
static const char i40evf_driver_string[] =
"Intel(R) XL710/X710 Virtual Function Network Driver";
-#define DRV_VERSION "1.3.5"
+#define DRV_VERSION "1.3.33"
const char i40evf_driver_version[] = DRV_VERSION;
static const char i40evf_copyright[] =
"Copyright (c) 2013 - 2015 Intel Corporation.";
@@ -282,6 +282,7 @@ static void i40evf_fire_sw_int(struct i40evf_adapter *adapter, u32 mask)
/**
* i40evf_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
+ * @flush: boolean value whether to run rd32()
**/
void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush)
{
@@ -305,15 +306,14 @@ static irqreturn_t i40evf_msix_aq(int irq, void *data)
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw;
u32 val;
- u32 ena_mask;
/* handle non-queue interrupts */
- val = rd32(hw, I40E_VFINT_ICR01);
- ena_mask = rd32(hw, I40E_VFINT_ICR0_ENA1);
+ rd32(hw, I40E_VFINT_ICR01);
+ rd32(hw, I40E_VFINT_ICR0_ENA1);
- val = rd32(hw, I40E_VFINT_DYN_CTL01);
- val = val | I40E_VFINT_DYN_CTL01_CLEARPBA_MASK;
+ val = rd32(hw, I40E_VFINT_DYN_CTL01) |
+ I40E_VFINT_DYN_CTL01_CLEARPBA_MASK;
wr32(hw, I40E_VFINT_DYN_CTL01, val);
/* schedule work on the private workqueue */
@@ -334,7 +334,7 @@ static irqreturn_t i40evf_msix_clean_rings(int irq, void *data)
if (!q_vector->tx.ring && !q_vector->rx.ring)
return IRQ_HANDLED;
- napi_schedule(&q_vector->napi);
+ napi_schedule_irqoff(&q_vector->napi);
return IRQ_HANDLED;
}
@@ -357,6 +357,7 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
q_vector->rx.ring = rx_ring;
q_vector->rx.count++;
q_vector->rx.latency_range = I40E_LOW_LATENCY;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
}
/**
@@ -377,6 +378,7 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
q_vector->tx.ring = tx_ring;
q_vector->tx.count++;
q_vector->tx.latency_range = I40E_LOW_LATENCY;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
q_vector->num_ringpairs++;
q_vector->ring_mask |= BIT(t_idx);
}
@@ -444,6 +446,29 @@ out:
return err;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * i40evf_netpoll - A Polling 'interrupt' handler
+ * @netdev: network interface device structure
+ *
+ * This is used by netconsole to send skbs without having to re-enable
+ * interrupts. It's not called while the normal interrupt routine is executing.
+ **/
+static void i40evf_netpoll(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+ int i;
+
+ /* if interface is down do nothing */
+ if (test_bit(__I40E_DOWN, &adapter->vsi.state))
+ return;
+
+ for (i = 0; i < q_vectors; i++)
+ i40evf_msix_clean_rings(0, adapter->q_vector[i]);
+}
+
+#endif
/**
* i40evf_request_traffic_irqs - Initialize MSI-X interrupts
* @adapter: board private structure
@@ -489,8 +514,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
q_vector);
if (err) {
dev_info(&adapter->pdev->dev,
- "%s: request_irq failed, error: %d\n",
- __func__, err);
+ "Request_irq failed, error: %d\n", err);
goto free_queue_irqs;
}
/* assign the mask for this irq */
@@ -731,6 +755,8 @@ static int i40evf_vlan_rx_add_vid(struct net_device *netdev,
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
+ if (!VLAN_ALLOWED(adapter))
+ return -EIO;
if (i40evf_add_vlan(adapter, vid) == NULL)
return -ENOMEM;
return 0;
@@ -746,8 +772,11 @@ static int i40evf_vlan_rx_kill_vid(struct net_device *netdev,
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
- i40evf_del_vlan(adapter, vid);
- return 0;
+ if (VLAN_ALLOWED(adapter)) {
+ i40evf_del_vlan(adapter, vid);
+ return 0;
+ }
+ return -EIO;
}
/**
@@ -837,6 +866,15 @@ static int i40evf_set_mac(struct net_device *netdev, void *p)
if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
return 0;
+ if (adapter->flags & I40EVF_FLAG_ADDR_SET_BY_PF)
+ return -EPERM;
+
+ f = i40evf_find_filter(adapter, hw->mac.addr);
+ if (f) {
+ f->remove = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+ }
+
f = i40evf_add_filter(adapter, addr->sa_data);
if (f) {
ether_addr_copy(hw->mac.addr, addr->sa_data);
@@ -856,6 +894,7 @@ static void i40evf_set_rx_mode(struct net_device *netdev)
struct i40evf_mac_filter *f, *ftmp;
struct netdev_hw_addr *uca;
struct netdev_hw_addr *mca;
+ struct netdev_hw_addr *ha;
int count = 50;
/* add addr if not already in the filter list */
@@ -877,29 +916,27 @@ static void i40evf_set_rx_mode(struct net_device *netdev)
}
/* remove filter if not in netdev list */
list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
- bool found = false;
-
- if (is_multicast_ether_addr(f->macaddr)) {
- netdev_for_each_mc_addr(mca, netdev) {
- if (ether_addr_equal(mca->addr, f->macaddr)) {
- found = true;
- break;
- }
- }
- } else {
- netdev_for_each_uc_addr(uca, netdev) {
- if (ether_addr_equal(uca->addr, f->macaddr)) {
- found = true;
- break;
- }
- }
- if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr))
- found = true;
- }
- if (!found) {
- f->remove = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
- }
+ netdev_for_each_mc_addr(mca, netdev)
+ if (ether_addr_equal(mca->addr, f->macaddr))
+ goto bottom_of_search_loop;
+
+ netdev_for_each_uc_addr(uca, netdev)
+ if (ether_addr_equal(uca->addr, f->macaddr))
+ goto bottom_of_search_loop;
+
+ for_each_dev_addr(netdev, ha)
+ if (ether_addr_equal(ha->addr, f->macaddr))
+ goto bottom_of_search_loop;
+
+ if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr))
+ goto bottom_of_search_loop;
+
+ /* f->macaddr wasn't found in uc, mc, or ha list so delete it */
+ f->remove = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+
+bottom_of_search_loop:
+ continue;
}
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
}
@@ -1111,6 +1148,8 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
tx_ring->netdev = adapter->netdev;
tx_ring->dev = &adapter->pdev->dev;
tx_ring->count = adapter->tx_desc_count;
+ if (adapter->flags & I40E_FLAG_WB_ON_ITR_CAPABLE)
+ tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR;
adapter->tx_rings[i] = tx_ring;
rx_ring = &tx_ring[1];
@@ -1165,7 +1204,7 @@ static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter)
for (vector = 0; vector < v_budget; vector++)
adapter->msix_entries[vector].entry = vector;
- i40evf_acquire_msix_vectors(adapter, v_budget);
+ err = i40evf_acquire_msix_vectors(adapter, v_budget);
out:
adapter->netdev->real_num_tx_queues = pairs;
@@ -1421,16 +1460,16 @@ static void i40evf_watchdog_task(struct work_struct *work)
struct i40evf_adapter,
watchdog_task);
struct i40e_hw *hw = &adapter->hw;
- uint32_t rstat_val;
+ u32 reg_val;
if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
goto restart_watchdog;
if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
- rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if ((rstat_val == I40E_VFR_VFACTIVE) ||
- (rstat_val == I40E_VFR_COMPLETED)) {
+ reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if ((reg_val == I40E_VFR_VFACTIVE) ||
+ (reg_val == I40E_VFR_COMPLETED)) {
/* A chance for redemption! */
dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
adapter->state = __I40EVF_STARTUP;
@@ -1455,11 +1494,8 @@ static void i40evf_watchdog_task(struct work_struct *work)
goto watchdog_done;
/* check for reset */
- rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) &&
- (rstat_val != I40E_VFR_VFACTIVE) &&
- (rstat_val != I40E_VFR_COMPLETED)) {
+ reg_val = rd32(hw, I40E_VF_ARQLEN1) & I40E_VF_ARQLEN1_ARQENABLE_MASK;
+ if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && !reg_val) {
adapter->state = __I40EVF_RESETTING;
adapter->flags |= I40EVF_FLAG_RESET_PENDING;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
@@ -1573,8 +1609,9 @@ static void i40evf_reset_task(struct work_struct *work)
reset_task);
struct net_device *netdev = adapter->netdev;
struct i40e_hw *hw = &adapter->hw;
+ struct i40evf_vlan_filter *vlf;
struct i40evf_mac_filter *f;
- uint32_t rstat_val;
+ u32 reg_val;
int i = 0, err;
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
@@ -1595,12 +1632,11 @@ static void i40evf_reset_task(struct work_struct *work)
/* poll until we see the reset actually happen */
for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
- rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if ((rstat_val != I40E_VFR_VFACTIVE) &&
- (rstat_val != I40E_VFR_COMPLETED))
+ reg_val = rd32(hw, I40E_VF_ARQLEN1) &
+ I40E_VF_ARQLEN1_ARQENABLE_MASK;
+ if (!reg_val)
break;
- usleep_range(500, 1000);
+ usleep_range(5000, 10000);
}
if (i == I40EVF_RESET_WAIT_COUNT) {
dev_info(&adapter->pdev->dev, "Never saw reset\n");
@@ -1609,21 +1645,21 @@ static void i40evf_reset_task(struct work_struct *work)
/* wait until the reset is complete and the PF is responding to us */
for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
- rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if (rstat_val == I40E_VFR_VFACTIVE)
+ reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if (reg_val == I40E_VFR_VFACTIVE)
break;
msleep(I40EVF_RESET_WAIT_MS);
}
/* extra wait to make sure minimum wait is met */
msleep(I40EVF_RESET_WAIT_MS);
if (i == I40EVF_RESET_WAIT_COUNT) {
- struct i40evf_mac_filter *f, *ftmp;
+ struct i40evf_mac_filter *ftmp;
struct i40evf_vlan_filter *fv, *fvtmp;
/* reset never finished */
dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
- rstat_val);
+ reg_val);
adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
if (netif_running(adapter->netdev)) {
@@ -1697,8 +1733,8 @@ continue_reset:
f->add = true;
}
/* re-add all VLAN filters */
- list_for_each_entry(f, &adapter->vlan_filter_list, list) {
- f->add = true;
+ list_for_each_entry(vlf, &adapter->vlan_filter_list, list) {
+ vlf->add = true;
}
adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
@@ -1853,8 +1889,7 @@ static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter)
if (!err)
continue;
dev_err(&adapter->pdev->dev,
- "%s: Allocation for Tx Queue %u failed\n",
- __func__, i);
+ "Allocation for Tx Queue %u failed\n", i);
break;
}
@@ -1881,8 +1916,7 @@ static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter)
if (!err)
continue;
dev_err(&adapter->pdev->dev,
- "%s: Allocation for Rx Queue %u failed\n",
- __func__, i);
+ "Allocation for Rx Queue %u failed\n", i);
break;
}
return err;
@@ -2041,6 +2075,9 @@ static const struct net_device_ops i40evf_netdev_ops = {
.ndo_tx_timeout = i40evf_tx_timeout,
.ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = i40evf_netpoll,
+#endif
};
/**
@@ -2089,7 +2126,10 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
if (adapter->vf_res->vf_offload_flags
& I40E_VIRTCHNL_VF_OFFLOAD_VLAN) {
- netdev->vlan_features = netdev->features;
+ netdev->vlan_features = netdev->features &
+ ~(NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER);
netdev->features |= NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -2118,6 +2158,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
adapter->vsi.tx_itr_setting = (I40E_ITR_DYNAMIC |
ITR_REG_TO_USEC(I40E_ITR_TX_DEF));
adapter->vsi.netdev = adapter->netdev;
+ adapter->vsi.qs_handle = adapter->vsi_res->qset_handle;
return 0;
}
@@ -2246,10 +2287,13 @@ static void i40evf_init_task(struct work_struct *work)
if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
adapter->hw.mac.addr);
- random_ether_addr(adapter->hw.mac.addr);
+ eth_hw_addr_random(netdev);
+ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
+ } else {
+ adapter->flags |= I40EVF_FLAG_ADDR_SET_BY_PF;
+ ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
+ ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
}
- ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
- ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &i40evf_watchdog_timer;
@@ -2265,6 +2309,9 @@ static void i40evf_init_task(struct work_struct *work)
if (err)
goto err_sw_init;
i40evf_map_rings_to_vectors(adapter);
+ if (adapter->vf_res->vf_offload_flags &
+ I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
+ adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE;
if (!RSS_AQ(adapter))
i40evf_configure_rss(adapter);
err = i40evf_request_misc_irq(adapter);
@@ -2300,8 +2347,7 @@ static void i40evf_init_task(struct work_struct *work)
}
return;
restart:
- schedule_delayed_work(&adapter->init_task,
- msecs_to_jiffies(50));
+ schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30));
return;
err_register:
@@ -2314,11 +2360,14 @@ err_alloc:
err:
/* Things went into the weeds, so try again later */
if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) {
- dev_err(&pdev->dev, "Failed to communicate with PF; giving up\n");
+ dev_err(&pdev->dev, "Failed to communicate with PF; waiting before retry\n");
adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
- return; /* do not reschedule */
+ i40evf_shutdown_adminq(hw);
+ adapter->state = __I40EVF_STARTUP;
+ schedule_delayed_work(&adapter->init_task, HZ * 5);
+ return;
}
- schedule_delayed_work(&adapter->init_task, HZ * 3);
+ schedule_delayed_work(&adapter->init_task, HZ);
}
/**
@@ -2434,7 +2483,8 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->adminq_task, i40evf_adminq_task);
INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);
INIT_DELAYED_WORK(&adapter->init_task, i40evf_init_task);
- schedule_delayed_work(&adapter->init_task, 10);
+ schedule_delayed_work(&adapter->init_task,
+ msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
return 0;
@@ -2510,6 +2560,7 @@ static int i40evf_resume(struct pci_dev *pdev)
rtnl_lock();
err = i40evf_set_interrupt_capability(adapter);
if (err) {
+ rtnl_unlock();
dev_err(&pdev->dev, "Cannot enable MSI-X interrupts.\n");
return err;
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index d4eb1a5e7d42..32e620e1eb5c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -156,7 +156,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 |
I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ |
I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG |
- I40E_VIRTCHNL_VF_OFFLOAD_VLAN;
+ I40E_VIRTCHNL_VF_OFFLOAD_VLAN |
+ I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR;
adapter->current_op = I40E_VIRTCHNL_OP_GET_VF_RESOURCES;
adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
if (PF_IS_V11(adapter))
@@ -234,8 +235,8 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
+ adapter->current_op);
return;
}
adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES;
@@ -288,8 +289,8 @@ void i40evf_enable_queues(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot enable queues, command %d pending\n",
+ adapter->current_op);
return;
}
adapter->current_op = I40E_VIRTCHNL_OP_ENABLE_QUEUES;
@@ -313,8 +314,8 @@ void i40evf_disable_queues(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot disable queues, command %d pending\n",
+ adapter->current_op);
return;
}
adapter->current_op = I40E_VIRTCHNL_OP_DISABLE_QUEUES;
@@ -341,8 +342,8 @@ void i40evf_map_queues(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot map queues to vectors, command %d pending\n",
+ adapter->current_op);
return;
}
adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP;
@@ -393,8 +394,8 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot add filters, command %d pending\n",
+ adapter->current_op);
return;
}
list_for_each_entry(f, &adapter->mac_filter_list, list) {
@@ -410,8 +411,7 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
len = sizeof(struct i40e_virtchnl_ether_addr_list) +
(count * sizeof(struct i40e_virtchnl_ether_addr));
if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request\n",
- __func__);
+ dev_warn(&adapter->pdev->dev, "Too many add MAC changes in one request\n");
count = (I40EVF_MAX_AQ_BUF_SIZE -
sizeof(struct i40e_virtchnl_ether_addr_list)) /
sizeof(struct i40e_virtchnl_ether_addr);
@@ -453,8 +453,8 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot remove filters, command %d pending\n",
+ adapter->current_op);
return;
}
list_for_each_entry(f, &adapter->mac_filter_list, list) {
@@ -470,8 +470,7 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
len = sizeof(struct i40e_virtchnl_ether_addr_list) +
(count * sizeof(struct i40e_virtchnl_ether_addr));
if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request\n",
- __func__);
+ dev_warn(&adapter->pdev->dev, "Too many delete MAC changes in one request\n");
count = (I40EVF_MAX_AQ_BUF_SIZE -
sizeof(struct i40e_virtchnl_ether_addr_list)) /
sizeof(struct i40e_virtchnl_ether_addr);
@@ -513,8 +512,8 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot add VLANs, command %d pending\n",
+ adapter->current_op);
return;
}
@@ -531,8 +530,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter)
len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
(count * sizeof(u16));
if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request\n",
- __func__);
+ dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
count = (I40EVF_MAX_AQ_BUF_SIZE -
sizeof(struct i40e_virtchnl_vlan_filter_list)) /
sizeof(u16);
@@ -572,8 +570,8 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot remove VLANs, command %d pending\n",
+ adapter->current_op);
return;
}
@@ -590,8 +588,7 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter)
len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
(count * sizeof(u16));
if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request\n",
- __func__);
+ dev_warn(&adapter->pdev->dev, "Too many delete VLAN changes in one request\n");
count = (I40EVF_MAX_AQ_BUF_SIZE -
sizeof(struct i40e_virtchnl_vlan_filter_list)) /
sizeof(u16);
@@ -629,8 +626,8 @@ void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags)
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
- __func__, adapter->current_op);
+ dev_err(&adapter->pdev->dev, "Cannot set promiscuous mode, command %d pending\n",
+ adapter->current_op);
return;
}
adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
@@ -720,17 +717,16 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
}
break;
default:
- dev_err(&adapter->pdev->dev,
- "%s: Unknown event %d from pf\n",
- __func__, vpe->event);
+ dev_err(&adapter->pdev->dev, "Unknown event %d from PF\n",
+ vpe->event);
break;
}
return;
}
if (v_retval) {
- dev_err(&adapter->pdev->dev, "%s: PF returned error %d (%s) to our request %d\n",
- __func__, v_retval,
- i40evf_stat_str(&adapter->hw, v_retval), v_opcode);
+ dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
+ v_retval, i40evf_stat_str(&adapter->hw, v_retval),
+ v_opcode);
}
switch (v_opcode) {
case I40E_VIRTCHNL_OP_GET_STATS: {
@@ -756,6 +752,8 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
sizeof(struct i40e_virtchnl_vsi_resource);
memcpy(adapter->vf_res, msg, min(msglen, len));
i40e_vf_parse_hw_config(&adapter->hw, adapter->vf_res);
+ /* restore current mac address */
+ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
i40evf_process_config(adapter);
}
break;
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 212d668dabb3..1a2f1cc44b28 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -444,8 +444,8 @@ struct igb_adapter {
struct ptp_pin_desc sdp_config[IGB_N_SDP];
struct {
- struct timespec start;
- struct timespec period;
+ struct timespec64 start;
+ struct timespec64 period;
} perout[IGB_N_PEROUT];
char fw_version[32];
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 74262768b09b..2529bc625de4 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -842,10 +842,6 @@ static void igb_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = IGB_STATS_LEN;
- drvinfo->testinfo_len = IGB_TEST_LEN;
- drvinfo->regdump_len = igb_get_regs_len(netdev);
- drvinfo->eedump_len = igb_get_eeprom_len(netdev);
}
static void igb_get_ringparam(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index e174fbbdba40..ea7b09887245 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -151,7 +151,7 @@ static void igb_setup_dca(struct igb_adapter *);
#endif /* CONFIG_IGB_DCA */
static int igb_poll(struct napi_struct *, int);
static bool igb_clean_tx_irq(struct igb_q_vector *);
-static bool igb_clean_rx_irq(struct igb_q_vector *, int);
+static int igb_clean_rx_irq(struct igb_q_vector *, int);
static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
static void igb_tx_timeout(struct net_device *);
static void igb_reset_task(struct work_struct *);
@@ -2986,6 +2986,9 @@ static int igb_sw_init(struct igb_adapter *adapter)
}
#endif /* CONFIG_PCI_IOV */
+ /* Assume MSI-X interrupts, will be checked during IRQ allocation */
+ adapter->flags |= IGB_FLAG_HAS_MSIX;
+
igb_probe_vfs(adapter);
igb_init_queue_configuration(adapter);
@@ -5389,7 +5392,7 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct ptp_clock_event event;
- struct timespec ts;
+ struct timespec64 ts;
u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR);
if (tsicr & TSINTR_SYS_WRAP) {
@@ -5409,10 +5412,11 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter)
if (tsicr & TSINTR_TT0) {
spin_lock(&adapter->tmreg_lock);
- ts = timespec_add(adapter->perout[0].start,
- adapter->perout[0].period);
+ ts = timespec64_add(adapter->perout[0].start,
+ adapter->perout[0].period);
+ /* u32 conversion of tv_sec is safe until y2106 */
wr32(E1000_TRGTTIML0, ts.tv_nsec);
- wr32(E1000_TRGTTIMH0, ts.tv_sec);
+ wr32(E1000_TRGTTIMH0, (u32)ts.tv_sec);
tsauxc = rd32(E1000_TSAUXC);
tsauxc |= TSAUXC_EN_TT0;
wr32(E1000_TSAUXC, tsauxc);
@@ -5423,10 +5427,10 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter)
if (tsicr & TSINTR_TT1) {
spin_lock(&adapter->tmreg_lock);
- ts = timespec_add(adapter->perout[1].start,
- adapter->perout[1].period);
+ ts = timespec64_add(adapter->perout[1].start,
+ adapter->perout[1].period);
wr32(E1000_TRGTTIML1, ts.tv_nsec);
- wr32(E1000_TRGTTIMH1, ts.tv_sec);
+ wr32(E1000_TRGTTIMH1, (u32)ts.tv_sec);
tsauxc = rd32(E1000_TSAUXC);
tsauxc |= TSAUXC_EN_TT1;
wr32(E1000_TSAUXC, tsauxc);
@@ -6360,6 +6364,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
struct igb_q_vector,
napi);
bool clean_complete = true;
+ int work_done = 0;
#ifdef CONFIG_IGB_DCA
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
@@ -6368,15 +6373,19 @@ static int igb_poll(struct napi_struct *napi, int budget)
if (q_vector->tx.ring)
clean_complete = igb_clean_tx_irq(q_vector);
- if (q_vector->rx.ring)
- clean_complete &= igb_clean_rx_irq(q_vector, budget);
+ if (q_vector->rx.ring) {
+ int cleaned = igb_clean_rx_irq(q_vector, budget);
+
+ work_done += cleaned;
+ clean_complete &= (cleaned < budget);
+ }
/* If all work not completed, return budget and keep polling */
if (!clean_complete)
return budget;
/* If not enough Rx work done, exit the polling mode */
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
igb_ring_irq_enable(q_vector);
return 0;
@@ -6900,7 +6909,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring,
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
}
-static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
+static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
{
struct igb_ring *rx_ring = q_vector->rx.ring;
struct sk_buff *skb = rx_ring->skb;
@@ -6974,7 +6983,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
if (cleaned_count)
igb_alloc_rx_buffers(rx_ring, cleaned_count);
- return total_packets < budget;
+ return total_packets;
}
static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 5982f28d521a..c44df87c38de 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -143,7 +143,7 @@ static void igb_ptp_write_i210(struct igb_adapter *adapter,
* sub-nanosecond resolution.
*/
wr32(E1000_SYSTIML, ts->tv_nsec);
- wr32(E1000_SYSTIMH, ts->tv_sec);
+ wr32(E1000_SYSTIMH, (u32)ts->tv_sec);
}
/**
@@ -479,7 +479,7 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp,
struct e1000_hw *hw = &igb->hw;
u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout;
unsigned long flags;
- struct timespec ts;
+ struct timespec64 ts;
int use_freq = 0, pin = -1;
s64 ns;
@@ -523,14 +523,14 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp,
}
ts.tv_sec = rq->perout.period.sec;
ts.tv_nsec = rq->perout.period.nsec;
- ns = timespec_to_ns(&ts);
+ ns = timespec64_to_ns(&ts);
ns = ns >> 1;
if (on && ns <= 70000000LL) {
if (ns < 8LL)
return -EINVAL;
use_freq = 1;
}
- ts = ns_to_timespec(ns);
+ ts = ns_to_timespec64(ns);
if (rq->perout.index == 1) {
if (use_freq) {
tsauxc_mask = TSAUXC_EN_CLK1 | TSAUXC_ST1;
diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index c6996feb1cb4..b74ce53d7b52 100644
--- a/drivers/net/ethernet/intel/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -196,8 +196,6 @@ static void igbvf_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = igbvf_get_regs_len(netdev);
- drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
}
static void igbvf_get_ringparam(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 686fa7184179..297af801f051 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1211,7 +1211,7 @@ static int igbvf_poll(struct napi_struct *napi, int budget)
/* If not enough Rx work done, exit the polling mode */
if (work_done < budget) {
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
if (adapter->requested_itr & 3)
igbvf_set_itr(adapter);
@@ -2615,6 +2615,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
.ndo_poll_controller = igbvf_netpoll,
#endif
.ndo_set_features = igbvf_set_features,
+ .ndo_features_check = passthru_features_check,
};
/**
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
index b311e9e710d2..d2b29b490ae0 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
@@ -479,9 +479,6 @@ ixgb_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = IXGB_STATS_LEN;
- drvinfo->regdump_len = ixgb_get_regs_len(netdev);
- drvinfo->eedump_len = ixgb_get_eeprom_len(netdev);
}
static void
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index edf1fb913209..1d2174526a4c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -152,9 +152,17 @@ struct vf_data_storage {
u16 vlan_count;
u8 spoofchk_enabled;
bool rss_query_enabled;
+ u8 trusted;
+ int xcast_mode;
unsigned int vf_api;
};
+enum ixgbevf_xcast_modes {
+ IXGBEVF_XCAST_MODE_NONE = 0,
+ IXGBEVF_XCAST_MODE_MULTI,
+ IXGBEVF_XCAST_MODE_ALLMULTI,
+};
+
struct vf_macvlans {
struct list_head l;
int vf;
@@ -539,8 +547,7 @@ struct hwmon_buff {
#define IXGBE_MIN_RSC_ITR 24
#define IXGBE_100K_ITR 40
#define IXGBE_20K_ITR 200
-#define IXGBE_10K_ITR 400
-#define IXGBE_8K_ITR 500
+#define IXGBE_12K_ITR 336
/* ixgbe_test_staterr - tests bits in Rx descriptor status and error fields */
static inline __le32 ixgbe_test_staterr(union ixgbe_adv_rx_desc *rx_desc,
@@ -595,6 +602,7 @@ struct ixgbe_mac_addr {
/* default to trying for four seconds */
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
+#define IXGBE_SFP_POLL_JIFFIES (2 * HZ) /* SFP poll every 2 seconds */
/* board specific private data structure */
struct ixgbe_adapter {
@@ -708,6 +716,7 @@ struct ixgbe_adapter {
u32 link_speed;
bool link_up;
+ unsigned long sfp_poll_time;
unsigned long link_check_timeout;
struct timer_list service_timer;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index dd7062fed61a..a39afcf03e2c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -44,9 +44,8 @@
static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
- ixgbe_link_speed speed,
- bool autoneg_wait_to_complete);
+static void
+ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *, ixgbe_link_speed);
static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg_wait_to_complete);
@@ -109,6 +108,9 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
if (hw->phy.multispeed_fiber) {
/* Set up dual speed SFP+ support */
mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
+ mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
+ mac->ops.set_rate_select_speed =
+ ixgbe_set_hard_rate_select_speed;
} else {
if ((mac->ops.get_media_type(hw) ==
ixgbe_media_type_backplane) &&
@@ -646,176 +648,32 @@ static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
}
/**
- * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
- * @hw: pointer to hardware structure
- * @speed: new link speed
- * @autoneg_wait_to_complete: true when waiting for completion is needed
+ * ixgbe_set_hard_rate_select_speed - Set module link speed
+ * @hw: pointer to hardware structure
+ * @speed: link speed to set
*
- * Set the link speed in the AUTOC register and restarts link.
- **/
-static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
- ixgbe_link_speed speed,
- bool autoneg_wait_to_complete)
+ * Set module link speed via RS0/RS1 rate select pins.
+ */
+static void
+ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
{
- s32 status = 0;
- ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
- ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
- u32 speedcnt = 0;
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
- u32 i = 0;
- bool link_up = false;
- bool autoneg = false;
-
- /* Mask off requested but non-supported speeds */
- status = hw->mac.ops.get_link_capabilities(hw, &link_speed,
- &autoneg);
- if (status != 0)
- return status;
-
- speed &= link_speed;
-
- /*
- * Try each speed one by one, highest priority first. We do this in
- * software because 10gb fiber doesn't support speed autonegotiation.
- */
- if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
- speedcnt++;
- highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
-
- /* If we already have link at this speed, just jump out */
- status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
- false);
- if (status != 0)
- return status;
-
- if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
- goto out;
-
- /* Set the module link speed */
- switch (hw->phy.media_type) {
- case ixgbe_media_type_fiber:
- esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- IXGBE_WRITE_FLUSH(hw);
- break;
- case ixgbe_media_type_fiber_qsfp:
- /* QSFP module automatically detects MAC link speed */
- break;
- default:
- hw_dbg(hw, "Unexpected media type.\n");
- break;
- }
-
- /* Allow module to change analog characteristics (1G->10G) */
- msleep(40);
-
- status = ixgbe_setup_mac_link_82599(hw,
- IXGBE_LINK_SPEED_10GB_FULL,
- autoneg_wait_to_complete);
- if (status != 0)
- return status;
-
- /* Flap the tx laser if it has not already been done */
- if (hw->mac.ops.flap_tx_laser)
- hw->mac.ops.flap_tx_laser(hw);
-
- /*
- * Wait for the controller to acquire link. Per IEEE 802.3ap,
- * Section 73.10.2, we may have to wait up to 500ms if KR is
- * attempted. 82599 uses the same timing for 10g SFI.
- */
- for (i = 0; i < 5; i++) {
- /* Wait for the link partner to also set speed */
- msleep(100);
-
- /* If we have link, just jump out */
- status = hw->mac.ops.check_link(hw, &link_speed,
- &link_up, false);
- if (status != 0)
- return status;
-
- if (link_up)
- goto out;
- }
- }
-
- if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
- speedcnt++;
- if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
- highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
-
- /* If we already have link at this speed, just jump out */
- status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
- false);
- if (status != 0)
- return status;
-
- if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
- goto out;
-
- /* Set the module link speed */
- switch (hw->phy.media_type) {
- case ixgbe_media_type_fiber:
- esdp_reg &= ~IXGBE_ESDP_SDP5;
- esdp_reg |= IXGBE_ESDP_SDP5_DIR;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- IXGBE_WRITE_FLUSH(hw);
- break;
- case ixgbe_media_type_fiber_qsfp:
- /* QSFP module automatically detects MAC link speed */
- break;
- default:
- hw_dbg(hw, "Unexpected media type.\n");
- break;
- }
-
- /* Allow module to change analog characteristics (10G->1G) */
- msleep(40);
-
- status = ixgbe_setup_mac_link_82599(hw,
- IXGBE_LINK_SPEED_1GB_FULL,
- autoneg_wait_to_complete);
- if (status != 0)
- return status;
-
- /* Flap the tx laser if it has not already been done */
- if (hw->mac.ops.flap_tx_laser)
- hw->mac.ops.flap_tx_laser(hw);
- /* Wait for the link partner to also set speed */
- msleep(100);
-
- /* If we have link, just jump out */
- status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
- false);
- if (status != 0)
- return status;
-
- if (link_up)
- goto out;
+ switch (speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ esdp_reg &= ~IXGBE_ESDP_SDP5;
+ esdp_reg |= IXGBE_ESDP_SDP5_DIR;
+ break;
+ default:
+ hw_dbg(hw, "Invalid fixed module speed\n");
+ return;
}
- /*
- * We didn't get link. Configure back to the highest speed we tried,
- * (if there was more than one). We call ourselves back with just the
- * single highest speed that the user requested.
- */
- if (speedcnt > 1)
- status = ixgbe_setup_mac_link_multispeed_fiber(hw,
- highest_link_speed,
- autoneg_wait_to_complete);
-
-out:
- /* Set autoneg_advertised value based on input link speed */
- hw->phy.autoneg_advertised = 0;
-
- if (speed & IXGBE_LINK_SPEED_10GB_FULL)
- hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
-
- if (speed & IXGBE_LINK_SPEED_1GB_FULL)
- hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
-
- return status;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
}
/**
@@ -1766,6 +1624,16 @@ s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
+ /* also use it for SCTP */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
+ break;
+ default:
+ break;
+ }
+
/* store source and destination IP masks (big-enian) */
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
~input_mask->formatted.src_ip[0]);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 3f56a8080118..ce61b36b94f1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -297,13 +297,13 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
/* Setup flow control */
ret_val = ixgbe_setup_fc(hw);
- if (!ret_val)
- return 0;
+ if (ret_val)
+ return ret_val;
/* Clear adapter stopped flag */
hw->adapter_stopped = false;
- return ret_val;
+ return 0;
}
/**
@@ -2164,10 +2164,11 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
/*
* In order to prevent Tx hangs when the internal Tx
* switch is enabled we must set the high water mark
- * to the maximum FCRTH value. This allows the Tx
- * switch to function even under heavy Rx workloads.
+ * to the Rx packet buffer size - 24KB. This allows
+ * the Tx switch to function even under heavy Rx
+ * workloads.
*/
- fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+ fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
}
IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
@@ -2476,6 +2477,9 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n");
hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ if (hw->mac.type >= ixgbe_mac_X550)
+ return 0;
+
/*
* Before proceeding, make sure that the PCIe block does not have
* transactions pending.
@@ -3920,3 +3924,213 @@ bool ixgbe_mng_present(struct ixgbe_hw *hw)
fwsm &= IXGBE_FWSM_MODE_MASK;
return fwsm == IXGBE_FWSM_FW_MODE_PT;
}
+
+/**
+ * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait_to_complete: true when waiting for completion is needed
+ *
+ * Set the link speed in the MAC and/or PHY register and restarts link.
+ */
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg_wait_to_complete)
+{
+ ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+ ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+ s32 status = 0;
+ u32 speedcnt = 0;
+ u32 i = 0;
+ bool autoneg, link_up = false;
+
+ /* Mask off requested but non-supported speeds */
+ status = hw->mac.ops.get_link_capabilities(hw, &link_speed, &autoneg);
+ if (status)
+ return status;
+
+ speed &= link_speed;
+
+ /* Try each speed one by one, highest priority first. We do this in
+ * software because 10Gb fiber doesn't support speed autonegotiation.
+ */
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+ speedcnt++;
+ highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+ /* If we already have link at this speed, just jump out */
+ status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+ false);
+ if (status)
+ return status;
+
+ if (link_speed == IXGBE_LINK_SPEED_10GB_FULL && link_up)
+ goto out;
+
+ /* Set the module link speed */
+ switch (hw->phy.media_type) {
+ case ixgbe_media_type_fiber:
+ hw->mac.ops.set_rate_select_speed(hw,
+ IXGBE_LINK_SPEED_10GB_FULL);
+ break;
+ case ixgbe_media_type_fiber_qsfp:
+ /* QSFP module automatically detects MAC link speed */
+ break;
+ default:
+ hw_dbg(hw, "Unexpected media type\n");
+ break;
+ }
+
+ /* Allow module to change analog characteristics (1G->10G) */
+ msleep(40);
+
+ status = hw->mac.ops.setup_mac_link(hw,
+ IXGBE_LINK_SPEED_10GB_FULL,
+ autoneg_wait_to_complete);
+ if (status)
+ return status;
+
+ /* Flap the Tx laser if it has not already been done */
+ if (hw->mac.ops.flap_tx_laser)
+ hw->mac.ops.flap_tx_laser(hw);
+
+ /* Wait for the controller to acquire link. Per IEEE 802.3ap,
+ * Section 73.10.2, we may have to wait up to 500ms if KR is
+ * attempted. 82599 uses the same timing for 10g SFI.
+ */
+ for (i = 0; i < 5; i++) {
+ /* Wait for the link partner to also set speed */
+ msleep(100);
+
+ /* If we have link, just jump out */
+ status = hw->mac.ops.check_link(hw, &link_speed,
+ &link_up, false);
+ if (status)
+ return status;
+
+ if (link_up)
+ goto out;
+ }
+ }
+
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+ speedcnt++;
+ if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
+ highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
+
+ /* If we already have link at this speed, just jump out */
+ status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+ false);
+ if (status)
+ return status;
+
+ if (link_speed == IXGBE_LINK_SPEED_1GB_FULL && link_up)
+ goto out;
+
+ /* Set the module link speed */
+ switch (hw->phy.media_type) {
+ case ixgbe_media_type_fiber:
+ hw->mac.ops.set_rate_select_speed(hw,
+ IXGBE_LINK_SPEED_1GB_FULL);
+ break;
+ case ixgbe_media_type_fiber_qsfp:
+ /* QSFP module automatically detects link speed */
+ break;
+ default:
+ hw_dbg(hw, "Unexpected media type\n");
+ break;
+ }
+
+ /* Allow module to change analog characteristics (10G->1G) */
+ msleep(40);
+
+ status = hw->mac.ops.setup_mac_link(hw,
+ IXGBE_LINK_SPEED_1GB_FULL,
+ autoneg_wait_to_complete);
+ if (status)
+ return status;
+
+ /* Flap the Tx laser if it has not already been done */
+ if (hw->mac.ops.flap_tx_laser)
+ hw->mac.ops.flap_tx_laser(hw);
+
+ /* Wait for the link partner to also set speed */
+ msleep(100);
+
+ /* If we have link, just jump out */
+ status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+ false);
+ if (status)
+ return status;
+
+ if (link_up)
+ goto out;
+ }
+
+ /* We didn't get link. Configure back to the highest speed we tried,
+ * (if there was more than one). We call ourselves back with just the
+ * single highest speed that the user requested.
+ */
+ if (speedcnt > 1)
+ status = ixgbe_setup_mac_link_multispeed_fiber(hw,
+ highest_link_speed,
+ autoneg_wait_to_complete);
+
+out:
+ /* Set autoneg_advertised value based on input link speed */
+ hw->phy.autoneg_advertised = 0;
+
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+ return status;
+}
+
+/**
+ * ixgbe_set_soft_rate_select_speed - Set module link speed
+ * @hw: pointer to hardware structure
+ * @speed: link speed to set
+ *
+ * Set module link speed via the soft rate select.
+ */
+void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed)
+{
+ s32 status;
+ u8 rs, eeprom_data;
+
+ switch (speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ /* one bit mask same as setting on */
+ rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
+ break;
+ default:
+ hw_dbg(hw, "Invalid fixed module speed\n");
+ return;
+ }
+
+ /* Set RS0 */
+ status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+ IXGBE_I2C_EEPROM_DEV_ADDR2,
+ &eeprom_data);
+ if (status) {
+ hw_dbg(hw, "Failed to read Rx Rate Select RS0\n");
+ return;
+ }
+
+ eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
+
+ status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+ IXGBE_I2C_EEPROM_DEV_ADDR2,
+ eeprom_data);
+ if (status) {
+ hw_dbg(hw, "Failed to write Rx Rate Select RS0\n");
+ return;
+ }
+}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 2f779f35dc4f..a0044e4a8b90 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -135,6 +135,11 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
void ixgbe_disable_rx_generic(struct ixgbe_hw *hw);
void ixgbe_enable_rx_generic(struct ixgbe_hw *hw);
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg_wait_to_complete);
+void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed);
#define IXGBE_FAILED_READ_REG 0xffffffffU
#define IXGBE_FAILED_READ_CFG_DWORD 0xffffffffU
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index 3b932fe64ab6..23277ab153b6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
@@ -259,7 +259,13 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
} else {
- reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+ /* In order to prevent Tx hangs when the internal Tx
+ * switch is enabled we must set the high water mark
+ * to the Rx packet buffer size - 24KB. This allows
+ * the Tx switch to function even under heavy Rx
+ * workloads.
+ */
+ reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index ab2edc8e7703..d681273bd39d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -943,9 +943,6 @@ static void ixgbe_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = IXGBE_STATS_LEN;
- drvinfo->testinfo_len = IXGBE_TEST_LEN;
- drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
}
static void ixgbe_get_ringparam(struct net_device *netdev,
@@ -2286,7 +2283,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
adapter->tx_itr_setting = ec->tx_coalesce_usecs;
if (adapter->tx_itr_setting == 1)
- tx_itr_param = IXGBE_10K_ITR;
+ tx_itr_param = IXGBE_12K_ITR;
else
tx_itr_param = adapter->tx_itr_setting;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 68e1e757ecef..f3168bcc7d87 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -866,7 +866,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
if (txr_count && !rxr_count) {
/* tx only vector */
if (adapter->tx_itr_setting == 1)
- q_vector->itr = IXGBE_10K_ITR;
+ q_vector->itr = IXGBE_12K_ITR;
else
q_vector->itr = adapter->tx_itr_setting;
} else {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 63b2cfe9416b..47395ff5d908 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -79,7 +79,7 @@ char ixgbe_default_device_descr[] =
static char ixgbe_default_device_descr[] =
"Intel(R) 10 Gigabit Network Connection";
#endif
-#define DRV_VERSION "4.0.1-k"
+#define DRV_VERSION "4.2.1-k"
const char ixgbe_driver_version[] = DRV_VERSION;
static const char ixgbe_copyright[] =
"Copyright (c) 1999-2015 Intel Corporation.";
@@ -137,6 +137,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KX4), board_X550EM_x},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x},
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x},
/* required last entry */
{0, }
};
@@ -1244,9 +1245,12 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
int cpu)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 txctrl = dca3_get_tag(tx_ring->dev, cpu);
+ u32 txctrl = 0;
u16 reg_offset;
+ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+ txctrl = dca3_get_tag(tx_ring->dev, cpu);
+
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
reg_offset = IXGBE_DCA_TXCTRL(tx_ring->reg_idx);
@@ -1278,9 +1282,11 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
int cpu)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 rxctrl = dca3_get_tag(rx_ring->dev, cpu);
+ u32 rxctrl = 0;
u8 reg_idx = rx_ring->reg_idx;
+ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+ rxctrl = dca3_get_tag(rx_ring->dev, cpu);
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
@@ -1297,6 +1303,7 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
* which will cause the DCA tag to be cleared.
*/
rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN |
+ IXGBE_DCA_RXCTRL_DATA_DCA_EN |
IXGBE_DCA_RXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl);
@@ -1326,11 +1333,13 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
{
int i;
- if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
- return;
-
/* always use CB2 mode, difference is masked in the CB driver */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
+ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
+ IXGBE_DCA_CTRL_DCA_MODE_CB2);
+ else
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
+ IXGBE_DCA_CTRL_DCA_DISABLE);
for (i = 0; i < adapter->num_q_vectors; i++) {
adapter->q_vector[i]->cpu = -1;
@@ -1353,7 +1362,8 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
break;
if (dca_add_requester(dev) == 0) {
adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
- ixgbe_setup_dca(adapter);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
+ IXGBE_DCA_CTRL_DCA_MODE_CB2);
break;
}
/* Fall Through since DCA is disabled. */
@@ -1361,7 +1371,8 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
dca_remove_requester(dev);
adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
+ IXGBE_DCA_CTRL_DCA_DISABLE);
}
break;
}
@@ -2261,7 +2272,7 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector,
/* simple throttlerate management
* 0-10MB/s lowest (100000 ints/s)
* 10-20MB/s low (20000 ints/s)
- * 20-1249MB/s bulk (8000 ints/s)
+ * 20-1249MB/s bulk (12000 ints/s)
*/
/* what was last interrupt timeslice? */
timepassed_us = q_vector->itr >> 2;
@@ -2350,7 +2361,7 @@ static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector)
new_itr = IXGBE_20K_ITR;
break;
case bulk_latency:
- new_itr = IXGBE_8K_ITR;
+ new_itr = IXGBE_12K_ITR;
break;
default:
break;
@@ -2495,17 +2506,27 @@ static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
{
struct ixgbe_hw *hw = &adapter->hw;
+ u32 eicr_mask = IXGBE_EICR_GPI_SDP2(hw);
+
+ if (!ixgbe_is_sfp(hw))
+ return;
- if (eicr & IXGBE_EICR_GPI_SDP2(hw)) {
+ /* Later MAC's use different SDP */
+ if (hw->mac.type >= ixgbe_mac_X540)
+ eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
+
+ if (eicr & eicr_mask) {
/* Clear the interrupt */
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2(hw));
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
+ adapter->sfp_poll_time = 0;
ixgbe_service_event_schedule(adapter);
}
}
- if (eicr & IXGBE_EICR_GPI_SDP1(hw)) {
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB &&
+ (eicr & IXGBE_EICR_GPI_SDP1(hw))) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1(hw));
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
@@ -2622,6 +2643,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_SFP)
+ mask |= IXGBE_EIMS_GPI_SDP0(&adapter->hw);
if (adapter->hw.phy.type == ixgbe_phy_x550em_ext_t)
mask |= IXGBE_EICR_GPI_SDP0_X540;
mask |= IXGBE_EIMS_ECC;
@@ -2752,7 +2775,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_ring *ring;
- int per_ring_budget;
+ int per_ring_budget, work_done = 0;
bool clean_complete = true;
#ifdef CONFIG_IXGBE_DCA
@@ -2773,9 +2796,13 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
else
per_ring_budget = budget;
- ixgbe_for_each_ring(ring, q_vector->rx)
- clean_complete &= (ixgbe_clean_rx_irq(q_vector, ring,
- per_ring_budget) < per_ring_budget);
+ ixgbe_for_each_ring(ring, q_vector->rx) {
+ int cleaned = ixgbe_clean_rx_irq(q_vector, ring,
+ per_ring_budget);
+
+ work_done += cleaned;
+ clean_complete &= (cleaned < per_ring_budget);
+ }
ixgbe_qv_unlock_napi(q_vector);
/* If all work not completed, return budget and keep polling */
@@ -2783,7 +2810,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
return budget;
/* all work done, exit the polling mode */
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
if (adapter->rx_itr_setting & 1)
ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -3700,14 +3727,20 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0),
adapter->num_vfs);
- /* Ensure LLDP is set for Ethertype Antispoofing if we will be
+ /* Ensure LLDP and FC is set for Ethertype Antispoofing if we will be
* calling set_ethertype_anti_spoofing for each VF in loop below
*/
- if (hw->mac.ops.set_ethertype_anti_spoofing)
+ if (hw->mac.ops.set_ethertype_anti_spoofing) {
IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_LLDP),
- (IXGBE_ETQF_FILTER_EN | /* enable filter */
- IXGBE_ETQF_TX_ANTISPOOF | /* tx antispoof */
- IXGBE_ETH_P_LLDP)); /* LLDP eth type */
+ (IXGBE_ETQF_FILTER_EN |
+ IXGBE_ETQF_TX_ANTISPOOF |
+ IXGBE_ETH_P_LLDP));
+
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FC),
+ (IXGBE_ETQF_FILTER_EN |
+ IXGBE_ETQF_TX_ANTISPOOF |
+ ETH_P_PAUSE));
+ }
/* For VFs that have spoof checking turned off */
for (i = 0; i < adapter->num_vfs; i++) {
@@ -3777,8 +3810,6 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
switch (hw->mac.type) {
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
case ixgbe_mac_82598EB:
/*
* For VMDq support of different descriptor types or
@@ -3792,6 +3823,11 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
*/
rdrxctl |= IXGBE_RDRXCTL_MVMEN;
break;
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ if (adapter->num_vfs)
+ rdrxctl |= IXGBE_RDRXCTL_PSP;
+ /* fall through for older HW */
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
/* Disable RSC for ACK packets */
@@ -4767,6 +4803,12 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
break;
}
+#ifdef CONFIG_IXGBE_DCA
+ /* configure DCA */
+ if (adapter->flags & IXGBE_FLAG_DCA_CAPABLE)
+ ixgbe_setup_dca(adapter);
+#endif /* CONFIG_IXGBE_DCA */
+
#ifdef IXGBE_FCOE
/* configure FCoE L2 filters, redirection table, and Rx control */
ixgbe_configure_fcoe(adapter);
@@ -4793,6 +4835,7 @@ static void ixgbe_sfp_link_config(struct ixgbe_adapter *adapter)
adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
+ adapter->sfp_poll_time = 0;
}
/**
@@ -4883,9 +4926,6 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
case ixgbe_mac_82599EB:
gpie |= IXGBE_SDP0_GPIEN_8259X;
break;
- case ixgbe_mac_X540:
- gpie |= IXGBE_EIMS_TS;
- break;
default:
break;
}
@@ -4895,9 +4935,15 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
gpie |= IXGBE_SDP1_GPIEN(hw);
- if (hw->mac.type == ixgbe_mac_82599EB) {
- gpie |= IXGBE_SDP1_GPIEN_8259X;
- gpie |= IXGBE_SDP2_GPIEN_8259X;
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ gpie |= IXGBE_SDP1_GPIEN_8259X | IXGBE_SDP2_GPIEN_8259X;
+ break;
+ case ixgbe_mac_X550EM_x:
+ gpie |= IXGBE_SDP0_GPIEN_X540;
+ break;
+ default:
+ break;
}
IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
@@ -5220,11 +5266,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_clean_all_tx_rings(adapter);
ixgbe_clean_all_rx_rings(adapter);
-
-#ifdef CONFIG_IXGBE_DCA
- /* since we reset the hardware DCA settings were cleared */
- ixgbe_setup_dca(adapter);
-#endif
}
/**
@@ -5270,7 +5311,6 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());
adapter->ring_feature[RING_F_RSS].limit = rss;
adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
- adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
adapter->max_q_vectors = MAX_Q_VECTORS_82599;
adapter->atr_sample_rate = 20;
fdir = min_t(int, IXGBE_MAX_FDIR_INDICES, num_online_cpus());
@@ -5296,7 +5336,6 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
adapter->flags2 &= ~IXGBE_FLAG2_RSC_CAPABLE;
- adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
if (hw->device_id == IXGBE_DEV_ID_82598AT)
adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
@@ -6692,10 +6731,16 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter)
!(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
return;
+ if (adapter->sfp_poll_time &&
+ time_after(adapter->sfp_poll_time, jiffies))
+ return; /* If not yet time to poll for SFP */
+
/* someone else is in init, wait until next service event */
if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
return;
+ adapter->sfp_poll_time = jiffies + IXGBE_SFP_POLL_JIFFIES - 1;
+
err = hw->phy.ops.identify_sfp(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
goto sfp_out;
@@ -8362,6 +8407,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_rate = ixgbe_ndo_set_vf_bw,
.ndo_set_vf_spoofchk = ixgbe_ndo_set_vf_spoofchk,
.ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en,
+ .ndo_set_vf_trust = ixgbe_ndo_set_vf_trust,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
#ifdef CONFIG_IXGBE_DCB
@@ -8695,8 +8741,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->phy.reset_if_overtemp = true;
err = hw->mac.ops.reset_hw(hw);
hw->phy.reset_if_overtemp = false;
- if (err == IXGBE_ERR_SFP_NOT_PRESENT &&
- hw->mac.type == ixgbe_mac_82598EB) {
+ if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
err = 0;
} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
e_dev_err("failed to load because an unsupported SFP+ or QSFP module type was detected.\n");
@@ -9008,7 +9053,8 @@ static void ixgbe_remove(struct pci_dev *pdev)
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
dca_remove_requester(&pdev->dev);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
+ IXGBE_DCA_CTRL_DCA_DISABLE);
}
#endif
@@ -9019,12 +9065,12 @@ static void ixgbe_remove(struct pci_dev *pdev)
/* remove the added san mac */
ixgbe_del_sanmac_netdev(netdev);
- if (netdev->reg_state == NETREG_REGISTERED)
- unregister_netdev(netdev);
-
#ifdef CONFIG_PCI_IOV
ixgbe_disable_sriov(adapter);
#endif
+ if (netdev->reg_state == NETREG_REGISTERED)
+ unregister_netdev(netdev);
+
ixgbe_clear_interrupt_scheme(adapter);
ixgbe_release_hw_control(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index b1e4703ff2a5..8daa95f74548 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -102,6 +102,8 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_GET_RETA 0x0a /* VF request for RETA */
#define IXGBE_VF_GET_RSS_KEY 0x0b /* get RSS key */
+#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c
+
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 597d0b1c2370..fb8673d63806 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -100,16 +100,17 @@ static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2)
}
/**
- * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
+ * ixgbe_read_i2c_combined_generic_int - Perform I2C read combined operation
* @hw: pointer to the hardware structure
* @addr: I2C bus address to read from
* @reg: I2C device register to read from
* @val: pointer to location to receive read value
+ * @lock: true if to take and release semaphore
*
* Returns an error code on error.
- **/
-s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 *val)
+ */
+static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 *val, bool lock)
{
u32 swfw_mask = hw->phy.phy_semaphore_mask;
int max_retry = 10;
@@ -124,7 +125,7 @@ s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
csum = ~csum;
do {
- if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+ if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
return IXGBE_ERR_SWFW_SYNC;
ixgbe_i2c_start(hw);
/* Device Address and write indication */
@@ -157,13 +158,15 @@ s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
if (ixgbe_clock_out_i2c_bit(hw, false))
goto fail;
ixgbe_i2c_stop(hw);
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
*val = (high_bits << 8) | low_bits;
return 0;
fail:
ixgbe_i2c_bus_clear(hw);
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
retry++;
if (retry < max_retry)
hw_dbg(hw, "I2C byte read combined error - Retry.\n");
@@ -175,17 +178,49 @@ fail:
}
/**
- * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
+ * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ */
+s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 *val)
+{
+ return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
+}
+
+/**
+ * ixgbe_read_i2c_combined_generic_unlocked - Unlocked I2C read combined
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ */
+s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 *val)
+{
+ return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation
* @hw: pointer to the hardware structure
* @addr: I2C bus address to write to
* @reg: I2C device register to write to
* @val: value to write
+ * @lock: true if to take and release semaphore
*
* Returns an error code on error.
- **/
-s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
- u8 addr, u16 reg, u16 val)
+ */
+static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 val, bool lock)
{
+ u32 swfw_mask = hw->phy.phy_semaphore_mask;
int max_retry = 1;
int retry = 0;
u8 reg_high;
@@ -197,6 +232,8 @@ s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
csum = ixgbe_ones_comp_byte_add(csum, val & 0xFF);
csum = ~csum;
do {
+ if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+ return IXGBE_ERR_SWFW_SYNC;
ixgbe_i2c_start(hw);
/* Device Address and write indication */
if (ixgbe_out_i2c_byte_ack(hw, addr))
@@ -217,10 +254,14 @@ s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
if (ixgbe_out_i2c_byte_ack(hw, csum))
goto fail;
ixgbe_i2c_stop(hw);
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
return 0;
fail:
ixgbe_i2c_bus_clear(hw);
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
retry++;
if (retry < max_retry)
hw_dbg(hw, "I2C byte write combined error - Retry.\n");
@@ -232,6 +273,36 @@ fail:
}
/**
+ * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ */
+s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
+ u8 addr, u16 reg, u16 val)
+{
+ return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic_unlocked - Unlocked I2C write combined
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ */
+s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
+ u8 addr, u16 reg, u16 val)
+{
+ return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
+}
+
+/**
* ixgbe_identify_phy_generic - Get physical layer module
* @hw: pointer to hardware structure
*
@@ -1100,6 +1171,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
return IXGBE_ERR_SFP_NOT_PRESENT;
}
+ /* LAN ID is needed for sfp_type determination */
+ hw->mac.ops.set_lan_id(hw);
+
status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_IDENTIFIER,
&identifier);
@@ -1107,9 +1181,6 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
if (status)
goto err_read_i2c_eeprom;
- /* LAN ID is needed for sfp_type determination */
- hw->mac.ops.set_lan_id(hw);
-
if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
hw->phy.type = ixgbe_phy_sfp_unsupported;
return IXGBE_ERR_SFP_NOT_SUPPORTED;
@@ -1159,7 +1230,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
hw->phy.sfp_type = ixgbe_sfp_type_lr;
else
hw->phy.sfp_type = ixgbe_sfp_type_unknown;
- } else if (hw->mac.type == ixgbe_mac_82599EB) {
+ } else {
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
if (hw->bus.lan_id == 0)
hw->phy.sfp_type =
@@ -1660,26 +1731,46 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
}
/**
- * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C
+ * ixgbe_is_sfp_probe - Returns true if SFP is being detected
+ * @hw: pointer to hardware structure
+ * @offset: eeprom offset to be read
+ * @addr: I2C address to be read
+ */
+static bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, u8 offset, u8 addr)
+{
+ if (addr == IXGBE_I2C_EEPROM_DEV_ADDR &&
+ offset == IXGBE_SFF_IDENTIFIER &&
+ hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+ return true;
+ return false;
+}
+
+/**
+ * ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C
* @hw: pointer to hardware structure
* @byte_offset: byte offset to read
* @data: value read
+ * @lock: true if to take and release semaphore
*
* Performs byte read operation to SFP module's EEPROM over I2C interface at
* a specified device address.
- **/
-s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
- u8 dev_addr, u8 *data)
+ */
+static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data, bool lock)
{
s32 status;
u32 max_retry = 10;
u32 retry = 0;
u32 swfw_mask = hw->phy.phy_semaphore_mask;
bool nack = true;
+
+ if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr))
+ max_retry = IXGBE_SFP_DETECT_RETRIES;
+
*data = 0;
do {
- if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+ if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
return IXGBE_ERR_SWFW_SYNC;
ixgbe_i2c_start(hw);
@@ -1721,12 +1812,16 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
goto fail;
ixgbe_i2c_stop(hw);
- break;
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ return 0;
fail:
ixgbe_i2c_bus_clear(hw);
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
- msleep(100);
+ if (lock) {
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msleep(100);
+ }
retry++;
if (retry < max_retry)
hw_dbg(hw, "I2C byte read error - Retrying.\n");
@@ -1735,29 +1830,60 @@ fail:
} while (retry < max_retry);
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-
return status;
}
/**
- * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C
+ * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to read
+ * @data: value read
+ *
+ * Performs byte read operation to SFP module's EEPROM over I2C interface at
+ * a specified device address.
+ */
+s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data)
+{
+ return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+ data, true);
+}
+
+/**
+ * ixgbe_read_i2c_byte_generic_unlocked - Reads 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to read
+ * @data: value read
+ *
+ * Performs byte read operation to SFP module's EEPROM over I2C interface at
+ * a specified device address.
+ */
+s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data)
+{
+ return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+ data, false);
+}
+
+/**
+ * ixgbe_write_i2c_byte_generic_int - Writes 8 bit word over I2C
* @hw: pointer to hardware structure
* @byte_offset: byte offset to write
* @data: value to write
+ * @lock: true if to take and release semaphore
*
* Performs byte write operation to SFP module's EEPROM over I2C interface at
* a specified device address.
- **/
-s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
- u8 dev_addr, u8 data)
+ */
+static s32 ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data, bool lock)
{
s32 status;
u32 max_retry = 1;
u32 retry = 0;
u32 swfw_mask = hw->phy.phy_semaphore_mask;
- if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+ if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
return IXGBE_ERR_SWFW_SYNC;
do {
@@ -1788,7 +1914,9 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
goto fail;
ixgbe_i2c_stop(hw);
- break;
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ return 0;
fail:
ixgbe_i2c_bus_clear(hw);
@@ -1799,21 +1927,57 @@ fail:
hw_dbg(hw, "I2C byte write error.\n");
} while (retry < max_retry);
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ if (lock)
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
return status;
}
/**
+ * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @data: value to write
+ *
+ * Performs byte write operation to SFP module's EEPROM over I2C interface at
+ * a specified device address.
+ */
+s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data)
+{
+ return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+ data, true);
+}
+
+/**
+ * ixgbe_write_i2c_byte_generic_unlocked - Writes 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @data: value to write
+ *
+ * Performs byte write operation to SFP module's EEPROM over I2C interface at
+ * a specified device address.
+ */
+s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data)
+{
+ return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+ data, false);
+}
+
+/**
* ixgbe_i2c_start - Sets I2C start condition
* @hw: pointer to hardware structure
*
* Sets I2C start condition (High -> Low on SDA while SCL is High)
+ * Set bit-bang mode on X550 hardware.
**/
static void ixgbe_i2c_start(struct ixgbe_hw *hw)
{
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
+ i2cctl |= IXGBE_I2C_BB_EN(hw);
+
/* Start condition must begin with data and clock high */
ixgbe_set_i2c_data(hw, &i2cctl, 1);
ixgbe_raise_i2c_clk(hw, &i2cctl);
@@ -1838,10 +2002,15 @@ static void ixgbe_i2c_start(struct ixgbe_hw *hw)
* @hw: pointer to hardware structure
*
* Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ * Disables bit-bang mode and negates data output enable on X550
+ * hardware.
**/
static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
{
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
+ u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
+ u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN(hw);
+ u32 bb_en_bit = IXGBE_I2C_BB_EN(hw);
/* Stop condition must begin with data low and clock high */
ixgbe_set_i2c_data(hw, &i2cctl, 0);
@@ -1854,6 +2023,13 @@ static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
/* bus free time between stop and start (4.7us)*/
udelay(IXGBE_I2C_T_BUF);
+
+ if (bb_en_bit || data_oe_bit || clk_oe_bit) {
+ i2cctl &= ~bb_en_bit;
+ i2cctl |= data_oe_bit | clk_oe_bit;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
+ IXGBE_WRITE_FLUSH(hw);
+ }
}
/**
@@ -1868,6 +2044,7 @@ static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data)
s32 i;
bool bit = false;
+ *data = 0;
for (i = 7; i >= 0; i--) {
ixgbe_clock_in_i2c_bit(hw, &bit);
*data |= bit << i;
@@ -1901,6 +2078,7 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
/* Release SDA line (set high) */
i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
i2cctl |= IXGBE_I2C_DATA_OUT(hw);
+ i2cctl |= IXGBE_I2C_DATA_OE_N_EN(hw);
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
IXGBE_WRITE_FLUSH(hw);
@@ -1915,15 +2093,21 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
**/
static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
{
+ u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
s32 status = 0;
u32 i = 0;
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
u32 timeout = 10;
bool ack = true;
+ if (data_oe_bit) {
+ i2cctl |= IXGBE_I2C_DATA_OUT(hw);
+ i2cctl |= data_oe_bit;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
+ IXGBE_WRITE_FLUSH(hw);
+ }
ixgbe_raise_i2c_clk(hw, &i2cctl);
-
/* Minimum high period of clock is 4us */
udelay(IXGBE_I2C_T_HIGH);
@@ -1961,7 +2145,14 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
{
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
+ u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
+ if (data_oe_bit) {
+ i2cctl |= IXGBE_I2C_DATA_OUT(hw);
+ i2cctl |= data_oe_bit;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
+ IXGBE_WRITE_FLUSH(hw);
+ }
ixgbe_raise_i2c_clk(hw, &i2cctl);
/* Minimum high period of clock is 4us */
@@ -2016,13 +2207,20 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
* @i2cctl: Current value of I2CCTL register
*
* Raises the I2C clock line '0'->'1'
+ * Negates the I2C clock output enable on X550 hardware.
**/
static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
{
+ u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN(hw);
u32 i = 0;
u32 timeout = IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT;
u32 i2cctl_r = 0;
+ if (clk_oe_bit) {
+ *i2cctl |= clk_oe_bit;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
+ }
+
for (i = 0; i < timeout; i++) {
*i2cctl |= IXGBE_I2C_CLK_OUT(hw);
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
@@ -2042,11 +2240,13 @@ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
* @i2cctl: Current value of I2CCTL register
*
* Lowers the I2C clock line '1'->'0'
+ * Asserts the I2C clock output enable on X550 hardware.
**/
static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
{
*i2cctl &= ~IXGBE_I2C_CLK_OUT(hw);
+ *i2cctl &= ~IXGBE_I2C_CLK_OE_N_EN(hw);
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
IXGBE_WRITE_FLUSH(hw);
@@ -2062,13 +2262,17 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
* @data: I2C data value (0 or 1) to set
*
* Sets the I2C data bit
+ * Asserts the I2C data output enable on X550 hardware.
**/
static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
{
+ u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
+
if (data)
*i2cctl |= IXGBE_I2C_DATA_OUT(hw);
else
*i2cctl &= ~IXGBE_I2C_DATA_OUT(hw);
+ *i2cctl &= ~data_oe_bit;
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
IXGBE_WRITE_FLUSH(hw);
@@ -2076,6 +2280,14 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA);
+ if (!data) /* Can't verify data in this case */
+ return 0;
+ if (data_oe_bit) {
+ *i2cctl |= data_oe_bit;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
+ IXGBE_WRITE_FLUSH(hw);
+ }
+
/* Verify data was set correctly */
*i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
if (data != ixgbe_get_i2c_data(hw, i2cctl)) {
@@ -2092,9 +2304,19 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
* @i2cctl: Current value of I2CCTL register
*
* Returns the I2C data bit value
+ * Negates the I2C data output enable on X550 hardware.
**/
static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl)
{
+ u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
+
+ if (data_oe_bit) {
+ *i2cctl |= data_oe_bit;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(IXGBE_I2C_T_FALL);
+ }
+
if (*i2cctl & IXGBE_I2C_DATA_IN(hw))
return true;
return false;
@@ -2109,10 +2331,11 @@ static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl)
**/
static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
{
- u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
+ u32 i2cctl;
u32 i;
ixgbe_i2c_start(hw);
+ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
ixgbe_set_i2c_data(hw, &i2cctl, 1);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index e45988c4dad5..5abd66c84d00 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -66,6 +66,9 @@
#define IXGBE_SFF_1GBASET_CAPABLE 0x8
#define IXGBE_SFF_10GBASESR_CAPABLE 0x10
#define IXGBE_SFF_10GBASELR_CAPABLE 0x20
+#define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8
+#define IXGBE_SFF_SOFT_RS_SELECT_10G 0x8
+#define IXGBE_SFF_SOFT_RS_SELECT_1G 0x0
#define IXGBE_SFF_ADDRESSING_MODE 0x4
#define IXGBE_SFF_QSFP_DA_ACTIVE_CABLE 0x1
#define IXGBE_SFF_QSFP_DA_PASSIVE_CABLE 0x8
@@ -78,9 +81,29 @@
#define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2
#define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3
#define IXGBE_CS4227 0xBE /* CS4227 address */
-#define IXGBE_CS4227_SPARE24_LSB 0x12B0 /* Reg to program EDC */
+#define IXGBE_CS4227_SCRATCH 2
+#define IXGBE_CS4227_RESET_PENDING 0x1357
+#define IXGBE_CS4227_RESET_COMPLETE 0x5AA5
+#define IXGBE_CS4227_RETRIES 15
+#define IXGBE_CS4227_EFUSE_STATUS 0x0181
+#define IXGBE_CS4227_LINE_SPARE22_MSB 0x12AD /* Reg to set speed */
+#define IXGBE_CS4227_LINE_SPARE24_LSB 0x12B0 /* Reg to set EDC */
+#define IXGBE_CS4227_HOST_SPARE22_MSB 0x1AAD /* Reg to set speed */
+#define IXGBE_CS4227_HOST_SPARE24_LSB 0x1AB0 /* Reg to program EDC */
+#define IXGBE_CS4227_EEPROM_STATUS 0x5001
+#define IXGBE_CS4227_EEPROM_LOAD_OK 0x0001
+#define IXGBE_CS4227_SPEED_1G 0x8000
+#define IXGBE_CS4227_SPEED_10G 0
#define IXGBE_CS4227_EDC_MODE_CX1 0x0002
#define IXGBE_CS4227_EDC_MODE_SR 0x0004
+#define IXGBE_CS4227_EDC_MODE_DIAG 0x0008
+#define IXGBE_CS4227_RESET_HOLD 500 /* microseconds */
+#define IXGBE_CS4227_RESET_DELAY 500 /* milliseconds */
+#define IXGBE_CS4227_CHECK_DELAY 30 /* milliseconds */
+#define IXGBE_PE 0xE0 /* Port expander addr */
+#define IXGBE_PE_OUTPUT 1 /* Output reg offset */
+#define IXGBE_PE_CONFIG 3 /* Config reg offset */
+#define IXGBE_PE_BIT1 (1 << 1)
/* Flow control defines */
#define IXGBE_TAF_SYM_PAUSE 0x400
@@ -109,6 +132,8 @@
#define IXGBE_I2C_T_SU_STO 4
#define IXGBE_I2C_T_BUF 5
+#define IXGBE_SFP_DETECT_RETRIES 2
+
#define IXGBE_TN_LASI_STATUS_REG 0x9005
#define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008
@@ -154,8 +179,12 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
+s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data);
s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
+s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data);
s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);
s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset,
@@ -164,6 +193,10 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 eeprom_data);
s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
u16 reg, u16 *val);
+s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 *val);
s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
u16 reg, u16 val);
+s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 val);
#endif /* _IXGBE_PHY_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 1d17b5872dd1..fcd8b27a0ccb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -116,6 +116,12 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
* we want to disable the querying by default.
*/
adapter->vfinfo[i].rss_query_enabled = 0;
+
+ /* Untrust all VFs */
+ adapter->vfinfo[i].trusted = false;
+
+ /* set the default xcast mode */
+ adapter->vfinfo[i].xcast_mode = IXGBEVF_XCAST_MODE_NONE;
}
return 0;
@@ -1001,6 +1007,59 @@ static int ixgbe_get_vf_rss_key(struct ixgbe_adapter *adapter,
return 0;
}
+static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int xcast_mode = msgbuf[1];
+ u32 vmolr, disable, enable;
+
+ /* verify the PF is supporting the correct APIs */
+ switch (adapter->vfinfo[vf].vf_api) {
+ case ixgbe_mbox_api_12:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if (xcast_mode > IXGBEVF_XCAST_MODE_MULTI &&
+ !adapter->vfinfo[vf].trusted) {
+ xcast_mode = IXGBEVF_XCAST_MODE_MULTI;
+ }
+
+ if (adapter->vfinfo[vf].xcast_mode == xcast_mode)
+ goto out;
+
+ switch (xcast_mode) {
+ case IXGBEVF_XCAST_MODE_NONE:
+ disable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_MPE;
+ enable = 0;
+ break;
+ case IXGBEVF_XCAST_MODE_MULTI:
+ disable = IXGBE_VMOLR_MPE;
+ enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE;
+ break;
+ case IXGBEVF_XCAST_MODE_ALLMULTI:
+ disable = 0;
+ enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_MPE;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+ vmolr &= ~disable;
+ vmolr |= enable;
+ IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
+
+ adapter->vfinfo[vf].xcast_mode = xcast_mode;
+
+out:
+ msgbuf[1] = xcast_mode;
+
+ return 0;
+}
+
static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
{
u32 mbx_size = IXGBE_VFMAILBOX_SIZE;
@@ -1063,6 +1122,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
case IXGBE_VF_GET_RSS_KEY:
retval = ixgbe_get_vf_rss_key(adapter, msgbuf, vf);
break;
+ case IXGBE_VF_UPDATE_XCAST_MODE:
+ retval = ixgbe_update_vf_xcast_mode(adapter, msgbuf, vf);
+ break;
default:
e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
retval = IXGBE_ERR_MBX;
@@ -1124,6 +1186,17 @@ void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
}
+static inline void ixgbe_ping_vf(struct ixgbe_adapter *adapter, int vf)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 ping;
+
+ ping = IXGBE_PF_CONTROL_MSG;
+ if (adapter->vfinfo[vf].clear_to_send)
+ ping |= IXGBE_VT_MSGTYPE_CTS;
+ ixgbe_write_mbx(hw, &ping, 1, vf);
+}
+
void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
@@ -1416,6 +1489,28 @@ int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf,
return 0;
}
+int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ if (vf >= adapter->num_vfs)
+ return -EINVAL;
+
+ /* nothing to do */
+ if (adapter->vfinfo[vf].trusted == setting)
+ return 0;
+
+ adapter->vfinfo[vf].trusted = setting;
+
+ /* reset VF to reconfigure features */
+ adapter->vfinfo[vf].clear_to_send = false;
+ ixgbe_ping_vf(adapter, vf);
+
+ e_info(drv, "VF %u is %strusted\n", vf, setting ? "" : "not ");
+
+ return 0;
+}
+
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi)
{
@@ -1430,5 +1525,6 @@ int ixgbe_ndo_get_vf_config(struct net_device *netdev,
ivi->qos = adapter->vfinfo[vf].pf_qos;
ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled;
ivi->rss_query_en = adapter->vfinfo[vf].rss_query_enabled;
+ ivi->trusted = adapter->vfinfo[vf].trusted;
return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
index 2c197e6d1fe7..dad925706f4c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
@@ -49,6 +49,7 @@ int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate,
int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf,
bool setting);
+int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting);
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi);
void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 63689192b149..995f03107eac 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -402,6 +402,7 @@ struct ixgbe_thermal_sensor_data {
#define IXGBE_FDIRSIP4M 0x0EE40
#define IXGBE_FDIRTCPM 0x0EE44
#define IXGBE_FDIRUDPM 0x0EE48
+#define IXGBE_FDIRSCTPM 0x0EE78
#define IXGBE_FDIRIP6M 0x0EE74
#define IXGBE_FDIRM 0x0EE70
@@ -1192,6 +1193,7 @@ struct ixgbe_thermal_sensor_data {
/* RDRXCTL Bit Masks */
#define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min Threshold Size */
#define IXGBE_RDRXCTL_CRCSTRIP 0x00000002 /* CRC Strip */
+#define IXGBE_RDRXCTL_PSP 0x00000004 /* Pad small packet */
#define IXGBE_RDRXCTL_MVMEN 0x00000020
#define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */
#define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */
@@ -1750,6 +1752,9 @@ enum {
* FCoE (0x8906): Filter 2
* 1588 (0x88f7): Filter 3
* FIP (0x8914): Filter 4
+ * LLDP (0x88CC): Filter 5
+ * LACP (0x8809): Filter 6
+ * FC (0x8808): Filter 7
*/
#define IXGBE_ETQF_FILTER_EAPOL 0
#define IXGBE_ETQF_FILTER_FCOE 2
@@ -1757,6 +1762,7 @@ enum {
#define IXGBE_ETQF_FILTER_FIP 4
#define IXGBE_ETQF_FILTER_LLDP 5
#define IXGBE_ETQF_FILTER_LACP 6
+#define IXGBE_ETQF_FILTER_FC 7
/* VLAN Control Bit Masks */
#define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */
@@ -1948,6 +1954,7 @@ enum {
#define IXGBE_GSSR_SW_MNG_SM 0x0400
#define IXGBE_GSSR_SHARED_I2C_SM 0x1806 /* Wait for both phys & I2Cs */
#define IXGBE_GSSR_I2C_MASK 0x1800
+#define IXGBE_GSSR_NVM_PHY_MASK 0xF
/* FW Status register bitmask */
#define IXGBE_FWSTS_FWRI 0x00000200 /* Firmware Reset Indication */
@@ -3255,9 +3262,11 @@ struct ixgbe_mac_operations {
void (*flap_tx_laser)(struct ixgbe_hw *);
void (*stop_link_on_d3)(struct ixgbe_hw *);
s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool);
+ s32 (*setup_mac_link)(struct ixgbe_hw *, ixgbe_link_speed, bool);
s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
+ void (*set_rate_select_speed)(struct ixgbe_hw *, ixgbe_link_speed);
/* Packet Buffer Manipulation */
void (*set_rxpba)(struct ixgbe_hw *, int, u32, int);
@@ -3328,6 +3337,10 @@ struct ixgbe_phy_operations {
s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
s32 (*enter_lplu)(struct ixgbe_hw *);
s32 (*handle_lasi)(struct ixgbe_hw *hw);
+ s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 *value);
+ s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 value);
};
struct ixgbe_eeprom_info {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 4e758435ece8..c1d4584f6469 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -567,19 +567,25 @@ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
**/
s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
{
- u32 swfw_sync;
- u32 swmask = mask;
- u32 fwmask = mask << 5;
- u32 hwmask = 0;
+ u32 swmask = mask & IXGBE_GSSR_NVM_PHY_MASK;
+ u32 swi2c_mask = mask & IXGBE_GSSR_I2C_MASK;
+ u32 fwmask = swmask << 5;
u32 timeout = 200;
+ u32 hwmask = 0;
+ u32 swfw_sync;
u32 i;
- if (swmask == IXGBE_GSSR_EEP_SM)
+ if (swmask & IXGBE_GSSR_EEP_SM)
hwmask = IXGBE_GSSR_FLASH_SM;
+ /* SW only mask does not have FW bit pair */
+ if (mask & IXGBE_GSSR_SW_MNG_SM)
+ swmask |= IXGBE_GSSR_SW_MNG_SM;
+
+ swmask |= swi2c_mask;
+ fwmask |= swi2c_mask << 2;
for (i = 0; i < timeout; i++) {
- /*
- * SW NVM semaphore bit is used for access to all
+ /* SW NVM semaphore bit is used for access to all
* SW_FW_SYNC bits (not just NVM)
*/
if (ixgbe_get_swfw_sync_semaphore(hw))
@@ -590,39 +596,56 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
swfw_sync |= swmask;
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
- break;
- } else {
- /*
- * Firmware currently using resource (fwmask),
- * hardware currently using resource (hwmask),
- * or other software thread currently using
- * resource (swmask)
- */
- ixgbe_release_swfw_sync_semaphore(hw);
- usleep_range(5000, 10000);
+ usleep_range(5000, 6000);
+ return 0;
}
+ /* Firmware currently using resource (fwmask), hardware
+ * currently using resource (hwmask), or other software
+ * thread currently using resource (swmask)
+ */
+ ixgbe_release_swfw_sync_semaphore(hw);
+ usleep_range(5000, 10000);
}
- /*
- * If the resource is not released by the FW/HW the SW can assume that
- * the FW/HW malfunctions. In that case the SW should sets the
- * SW bit(s) of the requested resource(s) while ignoring the
- * corresponding FW/HW bits in the SW_FW_SYNC register.
- */
- if (i >= timeout) {
- swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
- if (swfw_sync & (fwmask | hwmask)) {
- if (ixgbe_get_swfw_sync_semaphore(hw))
- return IXGBE_ERR_SWFW_SYNC;
+ /* Failed to get SW only semaphore */
+ if (swmask == IXGBE_GSSR_SW_MNG_SM) {
+ hw_dbg(hw, "Failed to get SW only semaphore\n");
+ return IXGBE_ERR_SWFW_SYNC;
+ }
- swfw_sync |= swmask;
- IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
- ixgbe_release_swfw_sync_semaphore(hw);
- }
+ /* If the resource is not released by the FW/HW the SW can assume that
+ * the FW/HW malfunctions. In that case the SW should set the SW bit(s)
+ * of the requested resource(s) while ignoring the corresponding FW/HW
+ * bits in the SW_FW_SYNC register.
+ */
+ if (ixgbe_get_swfw_sync_semaphore(hw))
+ return IXGBE_ERR_SWFW_SYNC;
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
+ if (swfw_sync & (fwmask | hwmask)) {
+ swfw_sync |= swmask;
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
+ ixgbe_release_swfw_sync_semaphore(hw);
+ usleep_range(5000, 6000);
+ return 0;
}
+ /* If the resource is not released by other SW the SW can assume that
+ * the other SW malfunctions. In that case the SW should clear all SW
+ * flags that it does not own and then repeat the whole process once
+ * again.
+ */
+ if (swfw_sync & swmask) {
+ u32 rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM |
+ IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM;
+
+ if (swi2c_mask)
+ rmask |= IXGBE_GSSR_I2C_MASK;
+ ixgbe_release_swfw_sync_X540(hw, rmask);
+ ixgbe_release_swfw_sync_semaphore(hw);
+ return IXGBE_ERR_SWFW_SYNC;
+ }
+ ixgbe_release_swfw_sync_semaphore(hw);
- usleep_range(5000, 10000);
- return 0;
+ return IXGBE_ERR_SWFW_SYNC;
}
/**
@@ -635,9 +658,11 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
**/
void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
{
+ u32 swmask = mask & (IXGBE_GSSR_NVM_PHY_MASK | IXGBE_GSSR_SW_MNG_SM);
u32 swfw_sync;
- u32 swmask = mask;
+ if (mask & IXGBE_GSSR_I2C_MASK)
+ swmask |= mask & IXGBE_GSSR_I2C_MASK;
ixgbe_get_swfw_sync_semaphore(hw);
swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
@@ -645,7 +670,7 @@ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
- usleep_range(5000, 10000);
+ usleep_range(5000, 6000);
}
/**
@@ -686,6 +711,11 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
usleep_range(50, 100);
}
+ /* Release semaphores and return error if SW NVM semaphore
+ * was not granted because we do not have access to the EEPROM
+ */
+ hw_dbg(hw, "REGSMP Software NVM semaphore not granted\n");
+ ixgbe_release_swfw_sync_semaphore(hw);
return IXGBE_ERR_EEPROM;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
index 9fe9445cd73b..ebe0ac950b14 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
@@ -56,6 +56,292 @@ static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
IXGBE_WRITE_FLUSH(hw);
}
+/**
+ * ixgbe_read_cs4227 - Read CS4227 register
+ * @hw: pointer to hardware structure
+ * @reg: register number to write
+ * @value: pointer to receive value read
+ *
+ * Returns status code
+ */
+static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
+{
+ return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
+ value);
+}
+
+/**
+ * ixgbe_write_cs4227 - Write CS4227 register
+ * @hw: pointer to hardware structure
+ * @reg: register number to write
+ * @value: value to write to register
+ *
+ * Returns status code
+ */
+static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
+{
+ return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
+ value);
+}
+
+/**
+ * ixgbe_check_cs4227_reg - Perform diag on a CS4227 register
+ * @hw: pointer to hardware structure
+ * @reg: the register to check
+ *
+ * Performs a diagnostic on a register in the CS4227 chip. Returns an error
+ * if it is not operating correctly.
+ * This function assumes that the caller has acquired the proper semaphore.
+ */
+static s32 ixgbe_check_cs4227_reg(struct ixgbe_hw *hw, u16 reg)
+{
+ s32 status;
+ u32 retry;
+ u16 reg_val;
+
+ reg_val = (IXGBE_CS4227_EDC_MODE_DIAG << 1) | 1;
+ status = ixgbe_write_cs4227(hw, reg, reg_val);
+ if (status)
+ return status;
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
+ msleep(IXGBE_CS4227_CHECK_DELAY);
+ reg_val = 0xFFFF;
+ ixgbe_read_cs4227(hw, reg, &reg_val);
+ if (!reg_val)
+ break;
+ }
+ if (reg_val) {
+ hw_err(hw, "CS4227 reg 0x%04X failed diagnostic\n", reg);
+ return status;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_get_cs4227_status - Return CS4227 status
+ * @hw: pointer to hardware structure
+ *
+ * Performs a diagnostic on the CS4227 chip. Returns an error if it is
+ * not operating correctly.
+ * This function assumes that the caller has acquired the proper semaphore.
+ */
+static s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw)
+{
+ s32 status;
+ u16 value = 0;
+
+ /* Exit if the diagnostic has already been performed. */
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
+ if (status)
+ return status;
+ if (value == IXGBE_CS4227_RESET_COMPLETE)
+ return 0;
+
+ /* Check port 0. */
+ status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_LINE_SPARE24_LSB);
+ if (status)
+ return status;
+
+ status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_HOST_SPARE24_LSB);
+ if (status)
+ return status;
+
+ /* Check port 1. */
+ status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_LINE_SPARE24_LSB +
+ (1 << 12));
+ if (status)
+ return status;
+
+ return ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_HOST_SPARE24_LSB +
+ (1 << 12));
+}
+
+/**
+ * ixgbe_read_pe - Read register from port expander
+ * @hw: pointer to hardware structure
+ * @reg: register number to read
+ * @value: pointer to receive read value
+ *
+ * Returns status code
+ */
+static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
+{
+ s32 status;
+
+ status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value);
+ if (status)
+ hw_err(hw, "port expander access failed with %d\n", status);
+ return status;
+}
+
+/**
+ * ixgbe_write_pe - Write register to port expander
+ * @hw: pointer to hardware structure
+ * @reg: register number to write
+ * @value: value to write
+ *
+ * Returns status code
+ */
+static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
+{
+ s32 status;
+
+ status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE,
+ value);
+ if (status)
+ hw_err(hw, "port expander access failed with %d\n", status);
+ return status;
+}
+
+/**
+ * ixgbe_reset_cs4227 - Reset CS4227 using port expander
+ * @hw: pointer to hardware structure
+ *
+ * This function assumes that the caller has acquired the proper semaphore.
+ * Returns error code
+ */
+static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
+{
+ s32 status;
+ u32 retry;
+ u16 value;
+ u8 reg;
+
+ /* Trigger hard reset. */
+ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
+ if (status)
+ return status;
+ reg |= IXGBE_PE_BIT1;
+ status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
+ if (status)
+ return status;
+
+ status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
+ if (status)
+ return status;
+ reg &= ~IXGBE_PE_BIT1;
+ status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
+ if (status)
+ return status;
+
+ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
+ if (status)
+ return status;
+ reg &= ~IXGBE_PE_BIT1;
+ status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
+ if (status)
+ return status;
+
+ usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100);
+
+ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
+ if (status)
+ return status;
+ reg |= IXGBE_PE_BIT1;
+ status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
+ if (status)
+ return status;
+
+ /* Wait for the reset to complete. */
+ msleep(IXGBE_CS4227_RESET_DELAY);
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
+ &value);
+ if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK)
+ break;
+ msleep(IXGBE_CS4227_CHECK_DELAY);
+ }
+ if (retry == IXGBE_CS4227_RETRIES) {
+ hw_err(hw, "CS4227 reset did not complete\n");
+ return IXGBE_ERR_PHY;
+ }
+
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
+ if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
+ hw_err(hw, "CS4227 EEPROM did not load successfully\n");
+ return IXGBE_ERR_PHY;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_check_cs4227 - Check CS4227 and reset as needed
+ * @hw: pointer to hardware structure
+ */
+static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
+{
+ u32 swfw_mask = hw->phy.phy_semaphore_mask;
+ s32 status;
+ u16 value;
+ u8 retry;
+
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+ if (status) {
+ hw_err(hw, "semaphore failed with %d\n", status);
+ msleep(IXGBE_CS4227_CHECK_DELAY);
+ continue;
+ }
+
+ /* Get status of reset flow. */
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
+ if (!status && value == IXGBE_CS4227_RESET_COMPLETE)
+ goto out;
+
+ if (status || value != IXGBE_CS4227_RESET_PENDING)
+ break;
+
+ /* Reset is pending. Wait and check again. */
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msleep(IXGBE_CS4227_CHECK_DELAY);
+ }
+ /* If still pending, assume other instance failed. */
+ if (retry == IXGBE_CS4227_RETRIES) {
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+ if (status) {
+ hw_err(hw, "semaphore failed with %d\n", status);
+ return;
+ }
+ }
+
+ /* Reset the CS4227. */
+ status = ixgbe_reset_cs4227(hw);
+ if (status) {
+ hw_err(hw, "CS4227 reset failed: %d", status);
+ goto out;
+ }
+
+ /* Reset takes so long, temporarily release semaphore in case the
+ * other driver instance is waiting for the reset indication.
+ */
+ ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
+ IXGBE_CS4227_RESET_PENDING);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ usleep_range(10000, 12000);
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+ if (status) {
+ hw_err(hw, "semaphore failed with %d", status);
+ return;
+ }
+
+ /* Is the CS4227 working correctly? */
+ status = ixgbe_get_cs4227_status(hw);
+ if (status) {
+ hw_err(hw, "CS4227 status failed: %d", status);
+ goto out;
+ }
+
+ /* Record completion for next time. */
+ status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
+ IXGBE_CS4227_RESET_COMPLETE);
+
+out:
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msleep(hw->eeprom.semaphore_delay);
+}
+
/** ixgbe_identify_phy_x550em - Get PHY type based on device id
* @hw: pointer to hardware structure
*
@@ -68,7 +354,7 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
/* set up for CS4227 usage */
hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
ixgbe_setup_mux_ctl(hw);
-
+ ixgbe_check_cs4227(hw);
return ixgbe_identify_module_generic(hw);
case IXGBE_DEV_ID_X550EM_X_KX4:
hw->phy.type = ixgbe_phy_x550em_kx4;
@@ -910,6 +1196,96 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
}
/**
+ * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
+ * @hw: pointer to hardware structure
+ * @linear: true if SFP module is linear
+ */
+static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
+{
+ switch (hw->phy.sfp_type) {
+ case ixgbe_sfp_type_not_present:
+ return IXGBE_ERR_SFP_NOT_PRESENT;
+ case ixgbe_sfp_type_da_cu_core0:
+ case ixgbe_sfp_type_da_cu_core1:
+ *linear = true;
+ break;
+ case ixgbe_sfp_type_srlr_core0:
+ case ixgbe_sfp_type_srlr_core1:
+ case ixgbe_sfp_type_da_act_lmt_core0:
+ case ixgbe_sfp_type_da_act_lmt_core1:
+ case ixgbe_sfp_type_1g_sx_core0:
+ case ixgbe_sfp_type_1g_sx_core1:
+ case ixgbe_sfp_type_1g_lx_core0:
+ case ixgbe_sfp_type_1g_lx_core1:
+ *linear = false;
+ break;
+ case ixgbe_sfp_type_unknown:
+ case ixgbe_sfp_type_1g_cu_core0:
+ case ixgbe_sfp_type_1g_cu_core1:
+ default:
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP.
+ * @hw: pointer to hardware structure
+ *
+ * Configures the extern PHY and the integrated KR PHY for SFP support.
+ */
+static s32
+ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ __always_unused bool autoneg_wait_to_complete)
+{
+ s32 status;
+ u16 slice, value;
+ bool setup_linear = false;
+
+ /* Check if SFP module is supported and linear */
+ status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
+
+ /* If no SFP module present, then return success. Return success since
+ * there is no reason to configure CS4227 and SFP not present error is
+ * not accepted in the setup MAC link flow.
+ */
+ if (status == IXGBE_ERR_SFP_NOT_PRESENT)
+ return 0;
+
+ if (status)
+ return status;
+
+ /* Configure CS4227 LINE side to 10G SR. */
+ slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
+ value = IXGBE_CS4227_SPEED_10G;
+ status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice,
+ value);
+
+ /* Configure CS4227 for HOST connection rate then type. */
+ slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
+ value = speed & IXGBE_LINK_SPEED_10GB_FULL ?
+ IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
+ status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice,
+ value);
+
+ slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
+ if (setup_linear)
+ value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
+ else
+ value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
+ status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice,
+ value);
+
+ /* If internal link mode is XFI, then setup XFI internal link. */
+ if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))
+ status = ixgbe_setup_ixfi_x550em(hw, &speed);
+
+ return status;
+}
+
+/**
* ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
* @hw: pointer to hardware structure
* @speed: new link speed
@@ -1003,6 +1379,10 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
mac->ops.disable_tx_laser = NULL;
mac->ops.enable_tx_laser = NULL;
mac->ops.flap_tx_laser = NULL;
+ mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
+ mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em;
+ mac->ops.set_rate_select_speed =
+ ixgbe_set_soft_rate_select_speed;
break;
case ixgbe_media_type_copper:
mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
@@ -1018,53 +1398,18 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
*/
static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
{
- bool setup_linear;
- u16 reg_slice, edc_mode;
- s32 ret_val;
+ s32 status;
+ bool linear;
- switch (hw->phy.sfp_type) {
- case ixgbe_sfp_type_unknown:
- return 0;
- case ixgbe_sfp_type_not_present:
- return IXGBE_ERR_SFP_NOT_PRESENT;
- case ixgbe_sfp_type_da_cu_core0:
- case ixgbe_sfp_type_da_cu_core1:
- setup_linear = true;
- break;
- case ixgbe_sfp_type_srlr_core0:
- case ixgbe_sfp_type_srlr_core1:
- case ixgbe_sfp_type_da_act_lmt_core0:
- case ixgbe_sfp_type_da_act_lmt_core1:
- case ixgbe_sfp_type_1g_sx_core0:
- case ixgbe_sfp_type_1g_sx_core1:
- setup_linear = false;
- break;
- default:
- return IXGBE_ERR_SFP_NOT_SUPPORTED;
- }
+ /* Check if SFP module is supported */
+ status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
+ if (status)
+ return status;
ixgbe_init_mac_link_ops_X550em(hw);
hw->phy.ops.reset = NULL;
- /* The CS4227 slice address is the base address + the port-pair reg
- * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0.
- */
- reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12);
-
- if (setup_linear)
- edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- else
- edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-
- /* Configure CS4227 for connection type. */
- ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- edc_mode);
-
- if (ret_val)
- ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice,
- edc_mode);
-
- return ret_val;
+ return 0;
}
/** ixgbe_get_link_capabilities_x550em - Determines link capabilities
@@ -1272,7 +1617,7 @@ static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
if (status)
return status;
- if (lsc)
+ if (lsc && phy->ops.setup_internal_link)
return phy->ops.setup_internal_link(hw);
return 0;
@@ -1927,6 +2272,62 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
}
+/**
+ * ixgbe_set_mux - Set mux for port 1 access with CS4227
+ * @hw: pointer to hardware structure
+ * @state: set mux if 1, clear if 0
+ */
+static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
+{
+ u32 esdp;
+
+ if (!hw->bus.lan_id)
+ return;
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ if (state)
+ esdp |= IXGBE_ESDP_SDP1;
+ else
+ esdp &= ~IXGBE_ESDP_SDP1;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+}
+
+/**
+ * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to acquire
+ *
+ * Acquires the SWFW semaphore and sets the I2C MUX
+ */
+static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
+{
+ s32 status;
+
+ status = ixgbe_acquire_swfw_sync_X540(hw, mask);
+ if (status)
+ return status;
+
+ if (mask & IXGBE_GSSR_I2C_MASK)
+ ixgbe_set_mux(hw, 1);
+
+ return 0;
+}
+
+/**
+ * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to release
+ *
+ * Releases the SWFW semaphore and sets the I2C MUX
+ */
+static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
+{
+ if (mask & IXGBE_GSSR_I2C_MASK)
+ ixgbe_set_mux(hw, 0);
+
+ ixgbe_release_swfw_sync_X540(hw, mask);
+}
+
#define X550_COMMON_MAC \
.init_hw = &ixgbe_init_hw_generic, \
.start_hw = &ixgbe_start_hw_X540, \
@@ -1964,8 +2365,6 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
&ixgbe_set_source_address_pruning_X550, \
.set_ethertype_anti_spoofing = \
&ixgbe_set_ethertype_anti_spoofing_X550, \
- .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, \
- .release_swfw_sync = &ixgbe_release_swfw_sync_X540, \
.disable_rx_buff = &ixgbe_disable_rx_buff_generic, \
.enable_rx_buff = &ixgbe_enable_rx_buff_generic, \
.get_thermal_sensor_data = NULL, \
@@ -1985,6 +2384,8 @@ static struct ixgbe_mac_operations mac_ops_X550 = {
.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic,
.get_bus_info = &ixgbe_get_bus_info_generic,
.setup_sfp = NULL,
+ .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540,
+ .release_swfw_sync = &ixgbe_release_swfw_sync_X540,
};
static struct ixgbe_mac_operations mac_ops_X550EM_x = {
@@ -1997,7 +2398,8 @@ static struct ixgbe_mac_operations mac_ops_X550EM_x = {
.get_link_capabilities = &ixgbe_get_link_capabilities_X550em,
.get_bus_info = &ixgbe_get_bus_info_X550em,
.setup_sfp = ixgbe_setup_sfp_modules_X550em,
-
+ .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em,
+ .release_swfw_sync = &ixgbe_release_swfw_sync_X550em,
};
#define X550_COMMON_EEP \
@@ -2039,14 +2441,17 @@ static struct ixgbe_phy_operations phy_ops_X550 = {
X550_COMMON_PHY
.init = NULL,
.identify = &ixgbe_identify_phy_generic,
- .read_i2c_combined = &ixgbe_read_i2c_combined_generic,
- .write_i2c_combined = &ixgbe_write_i2c_combined_generic,
};
static struct ixgbe_phy_operations phy_ops_X550EM_x = {
X550_COMMON_PHY
.init = &ixgbe_init_phy_ops_X550em,
.identify = &ixgbe_identify_phy_x550em,
+ .read_i2c_combined = &ixgbe_read_i2c_combined_generic,
+ .write_i2c_combined = &ixgbe_write_i2c_combined_generic,
+ .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked,
+ .write_i2c_combined_unlocked =
+ &ixgbe_write_i2c_combined_generic_unlocked,
};
static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 04c7ec8446e0..ec3147279621 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -471,6 +471,12 @@ enum ixgbevf_boards {
board_X550EM_x_vf,
};
+enum ixgbevf_xcast_modes {
+ IXGBEVF_XCAST_MODE_NONE = 0,
+ IXGBEVF_XCAST_MODE_MULTI,
+ IXGBEVF_XCAST_MODE_ALLMULTI,
+};
+
extern const struct ixgbevf_info ixgbevf_82599_vf_info;
extern const struct ixgbevf_info ixgbevf_X540_vf_info;
extern const struct ixgbevf_info ixgbevf_X550_vf_info;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 149a0b4489be..592ff237d692 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1008,7 +1008,7 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
container_of(napi, struct ixgbevf_q_vector, napi);
struct ixgbevf_adapter *adapter = q_vector->adapter;
struct ixgbevf_ring *ring;
- int per_ring_budget;
+ int per_ring_budget, work_done = 0;
bool clean_complete = true;
ixgbevf_for_each_ring(ring, q_vector->tx)
@@ -1027,10 +1027,12 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
else
per_ring_budget = budget;
- ixgbevf_for_each_ring(ring, q_vector->rx)
- clean_complete &= (ixgbevf_clean_rx_irq(q_vector, ring,
- per_ring_budget)
- < per_ring_budget);
+ ixgbevf_for_each_ring(ring, q_vector->rx) {
+ int cleaned = ixgbevf_clean_rx_irq(q_vector, ring,
+ per_ring_budget);
+ work_done += cleaned;
+ clean_complete &= (cleaned < per_ring_budget);
+ }
#ifdef CONFIG_NET_RX_BUSY_POLL
ixgbevf_qv_unlock_napi(q_vector);
@@ -1040,7 +1042,7 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
if (!clean_complete)
return budget;
/* all work done, exit the polling mode */
- napi_complete(napi);
+ napi_complete_done(napi, work_done);
if (adapter->rx_itr_setting & 1)
ixgbevf_set_itr(q_vector);
if (!test_bit(__IXGBEVF_DOWN, &adapter->state) &&
@@ -1892,9 +1894,17 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev)
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
+ unsigned int flags = netdev->flags;
+ int xcast_mode;
+
+ xcast_mode = (flags & IFF_ALLMULTI) ? IXGBEVF_XCAST_MODE_ALLMULTI :
+ (flags & (IFF_BROADCAST | IFF_MULTICAST)) ?
+ IXGBEVF_XCAST_MODE_MULTI : IXGBEVF_XCAST_MODE_NONE;
spin_lock_bh(&adapter->mbx_lock);
+ hw->mac.ops.update_xcast_mode(hw, netdev, xcast_mode);
+
/* reprogram multicast list */
hw->mac.ops.update_mc_addr_list(hw, netdev);
@@ -3896,6 +3906,7 @@ static const struct net_device_ops ixgbevf_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgbevf_netpoll,
#endif
+ .ndo_features_check = passthru_features_check,
};
static void ixgbevf_assign_netdev_ops(struct net_device *dev)
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index 82f44e06e5fc..340cdd469455 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -112,6 +112,8 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_GET_RETA 0x0a /* VF request for RETA */
#define IXGBE_VF_GET_RSS_KEY 0x0b /* get RSS hash key */
+#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c
+
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index d1339b050627..427f3605cbfc 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -469,6 +469,46 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
}
/**
+ * ixgbevf_update_xcast_mode - Update Multicast mode
+ * @hw: pointer to the HW structure
+ * @netdev: pointer to net device structure
+ * @xcast_mode: new multicast mode
+ *
+ * Updates the Multicast Mode of VF.
+ **/
+static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw,
+ struct net_device *netdev, int xcast_mode)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf[2];
+ s32 err;
+
+ switch (hw->api_version) {
+ case ixgbe_mbox_api_12:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ msgbuf[0] = IXGBE_VF_UPDATE_XCAST_MODE;
+ msgbuf[1] = xcast_mode;
+
+ err = mbx->ops.write_posted(hw, msgbuf, 2);
+ if (err)
+ return err;
+
+ err = mbx->ops.read_posted(hw, msgbuf, 2);
+ if (err)
+ return err;
+
+ msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+ if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK))
+ return -EPERM;
+
+ return 0;
+}
+
+/**
* ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address
* @hw: pointer to the HW structure
* @vlan: 12 bit VLAN ID
@@ -727,6 +767,7 @@ static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
.check_link = ixgbevf_check_mac_link_vf,
.set_rar = ixgbevf_set_rar_vf,
.update_mc_addr_list = ixgbevf_update_mc_addr_list_vf,
+ .update_xcast_mode = ixgbevf_update_xcast_mode,
.set_uc_addr = ixgbevf_set_uc_addr_vf,
.set_vfta = ixgbevf_set_vfta_vf,
};
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index d40f036b6df0..ef9f7736b4dc 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -63,6 +63,7 @@ struct ixgbe_mac_operations {
s32 (*set_uc_addr)(struct ixgbe_hw *, u32, u8 *);
s32 (*init_rx_addrs)(struct ixgbe_hw *);
s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *);
+ s32 (*update_xcast_mode)(struct ixgbe_hw *, struct net_device *, int);
s32 (*enable_mc)(struct ixgbe_hw *);
s32 (*disable_mc)(struct ixgbe_hw *);
s32 (*clear_vfta)(struct ixgbe_hw *);
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index 80af9ffce5ea..a1c862b4664d 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -44,6 +44,7 @@ config MVNETA
tristate "Marvell Armada 370/38x/XP network interface support"
depends on PLAT_ORION
select MVMDIO
+ select FIXED_PHY
---help---
This driver supports the network interface units in the
Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 960169efe636..4182290fdbcf 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -759,11 +759,23 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
desc->l4i_chk = 0;
desc->byte_cnt = length;
- desc->buf_ptr = dma_map_single(dev->dev.parent, data,
- length, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) {
- WARN(1, "dma_map_single failed!\n");
- return -ENOMEM;
+
+ if (length <= 8 && (uintptr_t)data & 0x7) {
+ /* Copy unaligned small data fragment to TSO header data area */
+ memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE,
+ data, length);
+ desc->buf_ptr = txq->tso_hdrs_dma
+ + txq->tx_curr_desc * TSO_HEADER_SIZE;
+ } else {
+ /* Alignment is okay, map buffer and hand off to hardware */
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
+ desc->buf_ptr = dma_map_single(dev->dev.parent, data,
+ length, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev->dev.parent,
+ desc->buf_ptr))) {
+ WARN(1, "dma_map_single failed!\n");
+ return -ENOMEM;
+ }
}
cmd_sts = BUFFER_OWNED_BY_DMA;
@@ -779,7 +791,8 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
}
static inline void
-txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
+txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length,
+ u32 *first_cmd_sts, bool first_desc)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -788,6 +801,7 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
int ret;
u32 cmd_csum = 0;
u16 l4i_chk = 0;
+ u32 cmd_sts;
tx_index = txq->tx_curr_desc;
desc = &txq->tx_desc_area[tx_index];
@@ -803,9 +817,17 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
desc->byte_cnt = hdr_len;
desc->buf_ptr = txq->tso_hdrs_dma +
txq->tx_curr_desc * TSO_HEADER_SIZE;
- desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC |
+ cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC |
GEN_CRC;
+ /* Defer updating the first command descriptor until all
+ * following descriptors have been written.
+ */
+ if (first_desc)
+ *first_cmd_sts = cmd_sts;
+ else
+ desc->cmd_sts = cmd_sts;
+
txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
@@ -819,6 +841,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
int desc_count = 0;
struct tso_t tso;
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ struct tx_desc *first_tx_desc;
+ u32 first_cmd_sts = 0;
/* Count needed descriptors */
if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) {
@@ -826,11 +850,14 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
return -EBUSY;
}
+ first_tx_desc = &txq->tx_desc_area[txq->tx_curr_desc];
+
/* Initialize the TSO handler, and prepare the first payload */
tso_start(skb, &tso);
total_len = skb->len - hdr_len;
while (total_len > 0) {
+ bool first_desc = (desc_count == 0);
char *hdr;
data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
@@ -840,7 +867,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
/* prepare packet headers: MAC + IP + TCP */
hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE;
tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
- txq_put_hdr_tso(skb, txq, data_left);
+ txq_put_hdr_tso(skb, txq, data_left, &first_cmd_sts,
+ first_desc);
while (data_left > 0) {
int size;
@@ -860,6 +888,10 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
__skb_queue_tail(&txq->tx_skb, skb);
skb_tx_timestamp(skb);
+ /* ensure all other descriptors are written before first cmd_sts */
+ wmb();
+ first_tx_desc->cmd_sts = first_cmd_sts;
+
/* clear TX_END status */
mp->work_tx_end &= ~(1 << txq->index);
@@ -1586,7 +1618,6 @@ static void mv643xx_eth_get_drvinfo(struct net_device *dev,
sizeof(drvinfo->version));
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
- drvinfo->n_stats = ARRAY_SIZE(mv643xx_eth_stats);
}
static int mv643xx_eth_nway_reset(struct net_device *dev)
@@ -1845,29 +1876,19 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev)
struct netdev_hw_addr *ha;
int i;
- if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
- int port_num;
- u32 accept;
+ if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI))
+ goto promiscuous;
-oom:
- port_num = mp->port_num;
- accept = 0x01010101;
- for (i = 0; i < 0x100; i += 4) {
- wrl(mp, SPECIAL_MCAST_TABLE(port_num) + i, accept);
- wrl(mp, OTHER_MCAST_TABLE(port_num) + i, accept);
- }
- return;
- }
-
- mc_spec = kzalloc(0x200, GFP_ATOMIC);
- if (mc_spec == NULL)
- goto oom;
- mc_other = mc_spec + (0x100 >> 2);
+ /* Allocate both mc_spec and mc_other tables */
+ mc_spec = kcalloc(128, sizeof(u32), GFP_ATOMIC);
+ if (!mc_spec)
+ goto promiscuous;
+ mc_other = &mc_spec[64];
netdev_for_each_mc_addr(ha, dev) {
u8 *a = ha->addr;
u32 *table;
- int entry;
+ u8 entry;
if (memcmp(a, "\x01\x00\x5e\x00\x00", 5) == 0) {
table = mc_spec;
@@ -1880,12 +1901,23 @@ oom:
table[entry >> 2] |= 1 << (8 * (entry & 3));
}
- for (i = 0; i < 0x100; i += 4) {
- wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i, mc_spec[i >> 2]);
- wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i, mc_other[i >> 2]);
+ for (i = 0; i < 64; i++) {
+ wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i * sizeof(u32),
+ mc_spec[i]);
+ wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i * sizeof(u32),
+ mc_other[i]);
}
kfree(mc_spec);
+ return;
+
+promiscuous:
+ for (i = 0; i < 64; i++) {
+ wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i * sizeof(u32),
+ 0x01010101u);
+ wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i * sizeof(u32),
+ 0x01010101u);
+ }
}
static void mv643xx_eth_set_rx_mode(struct net_device *dev)
@@ -2785,8 +2817,10 @@ static int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
for_each_available_child_of_node(np, pnp) {
ret = mv643xx_eth_shared_of_add_port(pdev, pnp);
- if (ret)
+ if (ret) {
+ of_node_put(pnp);
return ret;
+ }
}
return 0;
}
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 514df76fc70f..e84c7f2634d3 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -32,6 +32,7 @@
#include <linux/of_address.h>
#include <linux/phy.h>
#include <linux/clk.h>
+#include <linux/cpu.h>
/* Registers */
#define MVNETA_RXQ_CONFIG_REG(q) (0x1400 + ((q) << 2))
@@ -100,6 +101,8 @@
#define MVNETA_TXQ_CMD 0x2448
#define MVNETA_TXQ_DISABLE_SHIFT 8
#define MVNETA_TXQ_ENABLE_MASK 0x000000ff
+#define MVNETA_RX_DISCARD_FRAME_COUNT 0x2484
+#define MVNETA_OVERRUN_FRAME_COUNT 0x2488
#define MVNETA_GMAC_CLOCK_DIVIDER 0x24f4
#define MVNETA_GMAC_1MS_CLOCK_ENABLE BIT(31)
#define MVNETA_ACC_MODE 0x2500
@@ -191,7 +194,7 @@
#define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11)
#define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVNETA_GMAC_AN_DUPLEX_EN BIT(13)
-#define MVNETA_MIB_COUNTERS_BASE 0x3080
+#define MVNETA_MIB_COUNTERS_BASE 0x3000
#define MVNETA_MIB_LATE_COLLISION 0x7c
#define MVNETA_DA_FILT_SPEC_MCAST 0x3400
#define MVNETA_DA_FILT_OTH_MCAST 0x3500
@@ -277,6 +280,50 @@
#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)
+struct mvneta_statistic {
+ unsigned short offset;
+ unsigned short type;
+ const char name[ETH_GSTRING_LEN];
+};
+
+#define T_REG_32 32
+#define T_REG_64 64
+
+static const struct mvneta_statistic mvneta_statistics[] = {
+ { 0x3000, T_REG_64, "good_octets_received", },
+ { 0x3010, T_REG_32, "good_frames_received", },
+ { 0x3008, T_REG_32, "bad_octets_received", },
+ { 0x3014, T_REG_32, "bad_frames_received", },
+ { 0x3018, T_REG_32, "broadcast_frames_received", },
+ { 0x301c, T_REG_32, "multicast_frames_received", },
+ { 0x3050, T_REG_32, "unrec_mac_control_received", },
+ { 0x3058, T_REG_32, "good_fc_received", },
+ { 0x305c, T_REG_32, "bad_fc_received", },
+ { 0x3060, T_REG_32, "undersize_received", },
+ { 0x3064, T_REG_32, "fragments_received", },
+ { 0x3068, T_REG_32, "oversize_received", },
+ { 0x306c, T_REG_32, "jabber_received", },
+ { 0x3070, T_REG_32, "mac_receive_error", },
+ { 0x3074, T_REG_32, "bad_crc_event", },
+ { 0x3078, T_REG_32, "collision", },
+ { 0x307c, T_REG_32, "late_collision", },
+ { 0x2484, T_REG_32, "rx_discard", },
+ { 0x2488, T_REG_32, "rx_overrun", },
+ { 0x3020, T_REG_32, "frames_64_octets", },
+ { 0x3024, T_REG_32, "frames_65_to_127_octets", },
+ { 0x3028, T_REG_32, "frames_128_to_255_octets", },
+ { 0x302c, T_REG_32, "frames_256_to_511_octets", },
+ { 0x3030, T_REG_32, "frames_512_to_1023_octets", },
+ { 0x3034, T_REG_32, "frames_1024_to_max_octets", },
+ { 0x3038, T_REG_64, "good_octets_sent", },
+ { 0x3040, T_REG_32, "good_frames_sent", },
+ { 0x3044, T_REG_32, "excessive_collision", },
+ { 0x3048, T_REG_32, "multicast_frames_sent", },
+ { 0x304c, T_REG_32, "broadcast_frames_sent", },
+ { 0x3054, T_REG_32, "fc_sent", },
+ { 0x300c, T_REG_32, "internal_mac_transmit_err", },
+};
+
struct mvneta_pcpu_stats {
struct u64_stats_sync syncp;
u64 rx_packets;
@@ -285,23 +332,34 @@ struct mvneta_pcpu_stats {
u64 tx_bytes;
};
+struct mvneta_pcpu_port {
+ /* Pointer to the shared port */
+ struct mvneta_port *pp;
+
+ /* Pointer to the CPU-local NAPI struct */
+ struct napi_struct napi;
+
+ /* Cause of the previous interrupt */
+ u32 cause_rx_tx;
+};
+
struct mvneta_port {
+ struct mvneta_pcpu_port __percpu *ports;
+ struct mvneta_pcpu_stats __percpu *stats;
+
int pkt_size;
unsigned int frag_size;
void __iomem *base;
struct mvneta_rx_queue *rxqs;
struct mvneta_tx_queue *txqs;
struct net_device *dev;
-
- u32 cause_rx_tx;
- struct napi_struct napi;
+ struct notifier_block cpu_notifier;
/* Core clock */
struct clk *clk;
u8 mcast_count[256];
u16 tx_ring_size;
u16 rx_ring_size;
- struct mvneta_pcpu_stats *stats;
struct mii_bus *mii_bus;
struct phy_device *phy_dev;
@@ -312,6 +370,8 @@ struct mvneta_port {
unsigned int speed;
unsigned int tx_csum_limit;
int use_inband_status:1;
+
+ u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
};
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -468,7 +528,7 @@ struct mvneta_rx_queue {
/* The hardware supports eight (8) rx queues, but we are only allowing
* the first one to be used. Therefore, let's just allocate one queue.
*/
-static int rxq_number = 1;
+static int rxq_number = 8;
static int txq_number = 8;
static int rxq_def;
@@ -518,6 +578,8 @@ static void mvneta_mib_counters_clear(struct mvneta_port *pp)
/* Perform dummy reads from MIB counters */
for (i = 0; i < MVNETA_MIB_LATE_COLLISION; i += 4)
dummy = mvreg_read(pp, (MVNETA_MIB_COUNTERS_BASE + i));
+ dummy = mvreg_read(pp, MVNETA_RX_DISCARD_FRAME_COUNT);
+ dummy = mvreg_read(pp, MVNETA_OVERRUN_FRAME_COUNT);
}
/* Get System Network Statistics */
@@ -746,7 +808,6 @@ static void mvneta_port_up(struct mvneta_port *pp)
u32 q_map;
/* Enable all initialized TXs. */
- mvneta_mib_counters_clear(pp);
q_map = 0;
for (queue = 0; queue < txq_number; queue++) {
struct mvneta_tx_queue *txq = &pp->txqs[queue];
@@ -756,14 +817,7 @@ static void mvneta_port_up(struct mvneta_port *pp)
mvreg_write(pp, MVNETA_TXQ_CMD, q_map);
/* Enable all initialized RXQs. */
- q_map = 0;
- for (queue = 0; queue < rxq_number; queue++) {
- struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
- if (rxq->descs != NULL)
- q_map |= (1 << queue);
- }
-
- mvreg_write(pp, MVNETA_RXQ_CMD, q_map);
+ mvreg_write(pp, MVNETA_RXQ_CMD, BIT(rxq_def));
}
/* Stop the Ethernet port activity */
@@ -949,7 +1003,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
/* Set CPU queue access map - all CPUs have access to all RX
* queues and to all TX queues
*/
- for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++)
+ for_each_present_cpu(cpu)
mvreg_write(pp, MVNETA_CPU_MAP(cpu),
(MVNETA_CPU_RXQ_ACCESS_ALL_MASK |
MVNETA_CPU_TXQ_ACCESS_ALL_MASK));
@@ -1030,6 +1084,8 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
mvreg_write(pp, MVNETA_INTR_ENABLE,
(MVNETA_RXQ_INTR_ENABLE_ALL_MASK
| MVNETA_TXQ_INTR_ENABLE_ALL_MASK));
+
+ mvneta_mib_counters_clear(pp);
}
/* Set max sizes for tx queues */
@@ -1426,17 +1482,6 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
return MVNETA_TX_L4_CSUM_NOT;
}
-/* Returns rx queue pointer (find last set bit) according to causeRxTx
- * value
- */
-static struct mvneta_rx_queue *mvneta_rx_policy(struct mvneta_port *pp,
- u32 cause)
-{
- int queue = fls(cause >> 8) - 1;
-
- return (queue < 0 || queue >= rxq_number) ? NULL : &pp->rxqs[queue];
-}
-
/* Drop packets received by the RXQ and free buffers */
static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
struct mvneta_rx_queue *rxq)
@@ -1448,9 +1493,9 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
struct mvneta_rx_desc *rx_desc = rxq->descs + i;
void *data = (void *)rx_desc->buf_cookie;
- mvneta_frag_free(pp, data);
dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
+ mvneta_frag_free(pp, data);
}
if (rx_done)
@@ -1461,6 +1506,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
struct mvneta_rx_queue *rxq)
{
+ struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
struct net_device *dev = pp->dev;
int rx_done;
u32 rcvd_pkts = 0;
@@ -1515,7 +1561,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
skb->protocol = eth_type_trans(skb, dev);
mvneta_rx_csum(pp, rx_status, skb);
- napi_gro_receive(&pp->napi, skb);
+ napi_gro_receive(&port->napi, skb);
rcvd_pkts++;
rcvd_bytes += rx_bytes;
@@ -1550,7 +1596,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
mvneta_rx_csum(pp, rx_status, skb);
- napi_gro_receive(&pp->napi, skb);
+ napi_gro_receive(&port->napi, skb);
}
if (rcvd_pkts) {
@@ -2061,12 +2107,10 @@ static void mvneta_set_rx_mode(struct net_device *dev)
/* Interrupt handling - the callback for request_irq() */
static irqreturn_t mvneta_isr(int irq, void *dev_id)
{
- struct mvneta_port *pp = (struct mvneta_port *)dev_id;
-
- /* Mask all interrupts */
- mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+ struct mvneta_pcpu_port *port = (struct mvneta_pcpu_port *)dev_id;
- napi_schedule(&pp->napi);
+ disable_percpu_irq(port->pp->dev->irq);
+ napi_schedule(&port->napi);
return IRQ_HANDLED;
}
@@ -2104,11 +2148,11 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
{
int rx_done = 0;
u32 cause_rx_tx;
- unsigned long flags;
struct mvneta_port *pp = netdev_priv(napi->dev);
+ struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
if (!netif_running(pp->dev)) {
- napi_complete(napi);
+ napi_complete(&port->napi);
return rx_done;
}
@@ -2135,47 +2179,17 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
/* For the case where the last mvneta_poll did not process all
* RX packets
*/
- cause_rx_tx |= pp->cause_rx_tx;
- if (rxq_number > 1) {
- while ((cause_rx_tx & MVNETA_RX_INTR_MASK_ALL) && (budget > 0)) {
- int count;
- struct mvneta_rx_queue *rxq;
- /* get rx queue number from cause_rx_tx */
- rxq = mvneta_rx_policy(pp, cause_rx_tx);
- if (!rxq)
- break;
-
- /* process the packet in that rx queue */
- count = mvneta_rx(pp, budget, rxq);
- rx_done += count;
- budget -= count;
- if (budget > 0) {
- /* set off the rx bit of the
- * corresponding bit in the cause rx
- * tx register, so that next iteration
- * will find the next rx queue where
- * packets are received on
- */
- cause_rx_tx &= ~((1 << rxq->id) << 8);
- }
- }
- } else {
- rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]);
- budget -= rx_done;
- }
+ cause_rx_tx |= port->cause_rx_tx;
+ rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]);
+ budget -= rx_done;
if (budget > 0) {
cause_rx_tx = 0;
- napi_complete(napi);
- local_irq_save(flags);
- mvreg_write(pp, MVNETA_INTR_NEW_MASK,
- MVNETA_RX_INTR_MASK(rxq_number) |
- MVNETA_TX_INTR_MASK(txq_number) |
- MVNETA_MISCINTR_INTR_MASK);
- local_irq_restore(flags);
+ napi_complete(&port->napi);
+ enable_percpu_irq(pp->dev->irq, 0);
}
- pp->cause_rx_tx = cause_rx_tx;
+ port->cause_rx_tx = cause_rx_tx;
return rx_done;
}
@@ -2379,26 +2393,19 @@ static void mvneta_cleanup_txqs(struct mvneta_port *pp)
/* Cleanup all Rx queues */
static void mvneta_cleanup_rxqs(struct mvneta_port *pp)
{
- int queue;
-
- for (queue = 0; queue < rxq_number; queue++)
- mvneta_rxq_deinit(pp, &pp->rxqs[queue]);
+ mvneta_rxq_deinit(pp, &pp->rxqs[rxq_def]);
}
/* Init all Rx queues */
static int mvneta_setup_rxqs(struct mvneta_port *pp)
{
- int queue;
-
- for (queue = 0; queue < rxq_number; queue++) {
- int err = mvneta_rxq_init(pp, &pp->rxqs[queue]);
- if (err) {
- netdev_err(pp->dev, "%s: can't create rxq=%d\n",
- __func__, queue);
- mvneta_cleanup_rxqs(pp);
- return err;
- }
+ int err = mvneta_rxq_init(pp, &pp->rxqs[rxq_def]);
+ if (err) {
+ netdev_err(pp->dev, "%s: can't create rxq=%d\n",
+ __func__, rxq_def);
+ mvneta_cleanup_rxqs(pp);
+ return err;
}
return 0;
@@ -2424,6 +2431,8 @@ static int mvneta_setup_txqs(struct mvneta_port *pp)
static void mvneta_start_dev(struct mvneta_port *pp)
{
+ unsigned int cpu;
+
mvneta_max_rx_size_set(pp, pp->pkt_size);
mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
@@ -2431,7 +2440,11 @@ static void mvneta_start_dev(struct mvneta_port *pp)
mvneta_port_enable(pp);
/* Enable polling on the port */
- napi_enable(&pp->napi);
+ for_each_present_cpu(cpu) {
+ struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+
+ napi_enable(&port->napi);
+ }
/* Unmask interrupts */
mvreg_write(pp, MVNETA_INTR_NEW_MASK,
@@ -2449,9 +2462,15 @@ static void mvneta_start_dev(struct mvneta_port *pp)
static void mvneta_stop_dev(struct mvneta_port *pp)
{
+ unsigned int cpu;
+
phy_stop(pp->phy_dev);
- napi_disable(&pp->napi);
+ for_each_present_cpu(cpu) {
+ struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+
+ napi_disable(&port->napi);
+ }
netif_carrier_off(pp->dev);
@@ -2691,6 +2710,125 @@ static void mvneta_mdio_remove(struct mvneta_port *pp)
pp->phy_dev = NULL;
}
+static void mvneta_percpu_enable(void *arg)
+{
+ struct mvneta_port *pp = arg;
+
+ enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE);
+}
+
+static void mvneta_percpu_disable(void *arg)
+{
+ struct mvneta_port *pp = arg;
+
+ disable_percpu_irq(pp->dev->irq);
+}
+
+static void mvneta_percpu_elect(struct mvneta_port *pp)
+{
+ int online_cpu_idx, cpu, i = 0;
+
+ online_cpu_idx = rxq_def % num_online_cpus();
+
+ for_each_online_cpu(cpu) {
+ if (i == online_cpu_idx)
+ /* Enable per-CPU interrupt on the one CPU we
+ * just elected
+ */
+ smp_call_function_single(cpu, mvneta_percpu_enable,
+ pp, true);
+ else
+ /* Disable per-CPU interrupt on all the other CPU */
+ smp_call_function_single(cpu, mvneta_percpu_disable,
+ pp, true);
+ i++;
+ }
+};
+
+static int mvneta_percpu_notifier(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ struct mvneta_port *pp = container_of(nfb, struct mvneta_port,
+ cpu_notifier);
+ int cpu = (unsigned long)hcpu, other_cpu;
+ struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ netif_tx_stop_all_queues(pp->dev);
+
+ /* We have to synchronise on tha napi of each CPU
+ * except the one just being waked up
+ */
+ for_each_online_cpu(other_cpu) {
+ if (other_cpu != cpu) {
+ struct mvneta_pcpu_port *other_port =
+ per_cpu_ptr(pp->ports, other_cpu);
+
+ napi_synchronize(&other_port->napi);
+ }
+ }
+
+ /* Mask all ethernet port interrupts */
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+ mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
+ mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+ napi_enable(&port->napi);
+
+ /* Enable per-CPU interrupt on the one CPU we care
+ * about.
+ */
+ mvneta_percpu_elect(pp);
+
+ /* Unmask all ethernet port interrupts */
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+ MVNETA_RX_INTR_MASK(rxq_number) |
+ MVNETA_TX_INTR_MASK(txq_number) |
+ MVNETA_MISCINTR_INTR_MASK);
+ mvreg_write(pp, MVNETA_INTR_MISC_MASK,
+ MVNETA_CAUSE_PHY_STATUS_CHANGE |
+ MVNETA_CAUSE_LINK_CHANGE |
+ MVNETA_CAUSE_PSC_SYNC_CHANGE);
+ netif_tx_start_all_queues(pp->dev);
+ break;
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ netif_tx_stop_all_queues(pp->dev);
+ /* Mask all ethernet port interrupts */
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+ mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
+ mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+
+ napi_synchronize(&port->napi);
+ napi_disable(&port->napi);
+ /* Disable per-CPU interrupts on the CPU that is
+ * brought down.
+ */
+ smp_call_function_single(cpu, mvneta_percpu_disable,
+ pp, true);
+
+ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ /* Check if a new CPU must be elected now this on is down */
+ mvneta_percpu_elect(pp);
+ /* Unmask all ethernet port interrupts */
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+ MVNETA_RX_INTR_MASK(rxq_number) |
+ MVNETA_TX_INTR_MASK(txq_number) |
+ MVNETA_MISCINTR_INTR_MASK);
+ mvreg_write(pp, MVNETA_INTR_MISC_MASK,
+ MVNETA_CAUSE_PHY_STATUS_CHANGE |
+ MVNETA_CAUSE_LINK_CHANGE |
+ MVNETA_CAUSE_PSC_SYNC_CHANGE);
+ netif_tx_start_all_queues(pp->dev);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
static int mvneta_open(struct net_device *dev)
{
struct mvneta_port *pp = netdev_priv(dev);
@@ -2709,13 +2847,29 @@ static int mvneta_open(struct net_device *dev)
goto err_cleanup_rxqs;
/* Connect to port interrupt line */
- ret = request_irq(pp->dev->irq, mvneta_isr, 0,
- MVNETA_DRIVER_NAME, pp);
+ ret = request_percpu_irq(pp->dev->irq, mvneta_isr,
+ MVNETA_DRIVER_NAME, pp->ports);
if (ret) {
netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq);
goto err_cleanup_txqs;
}
+ /* Even though the documentation says that request_percpu_irq
+ * doesn't enable the interrupts automatically, it actually
+ * does so on the local CPU.
+ *
+ * Make sure it's disabled.
+ */
+ mvneta_percpu_disable(pp);
+
+ /* Elect a CPU to handle our RX queue interrupt */
+ mvneta_percpu_elect(pp);
+
+ /* Register a CPU notifier to handle the case where our CPU
+ * might be taken offline.
+ */
+ register_cpu_notifier(&pp->cpu_notifier);
+
/* In default link is down */
netif_carrier_off(pp->dev);
@@ -2730,7 +2884,7 @@ static int mvneta_open(struct net_device *dev)
return 0;
err_free_irq:
- free_irq(pp->dev->irq, pp);
+ free_percpu_irq(pp->dev->irq, pp->ports);
err_cleanup_txqs:
mvneta_cleanup_txqs(pp);
err_cleanup_rxqs:
@@ -2742,10 +2896,14 @@ err_cleanup_rxqs:
static int mvneta_stop(struct net_device *dev)
{
struct mvneta_port *pp = netdev_priv(dev);
+ int cpu;
mvneta_stop_dev(pp);
mvneta_mdio_remove(pp);
- free_irq(dev->irq, pp);
+ unregister_cpu_notifier(&pp->cpu_notifier);
+ for_each_present_cpu(cpu)
+ smp_call_function_single(cpu, mvneta_percpu_disable, pp, true);
+ free_percpu_irq(dev->irq, pp->ports);
mvneta_cleanup_rxqs(pp);
mvneta_cleanup_txqs(pp);
@@ -2875,6 +3033,65 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev,
return 0;
}
+static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
+ u8 *data)
+{
+ if (sset == ETH_SS_STATS) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
+ memcpy(data + i * ETH_GSTRING_LEN,
+ mvneta_statistics[i].name, ETH_GSTRING_LEN);
+ }
+}
+
+static void mvneta_ethtool_update_stats(struct mvneta_port *pp)
+{
+ const struct mvneta_statistic *s;
+ void __iomem *base = pp->base;
+ u32 high, low, val;
+ int i;
+
+ for (i = 0, s = mvneta_statistics;
+ s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
+ s++, i++) {
+ val = 0;
+
+ switch (s->type) {
+ case T_REG_32:
+ val = readl_relaxed(base + s->offset);
+ break;
+ case T_REG_64:
+ /* Docs say to read low 32-bit then high */
+ low = readl_relaxed(base + s->offset);
+ high = readl_relaxed(base + s->offset + 4);
+ val = (u64)high << 32 | low;
+ break;
+ }
+
+ pp->ethtool_stats[i] += val;
+ }
+}
+
+static void mvneta_ethtool_get_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+ int i;
+
+ mvneta_ethtool_update_stats(pp);
+
+ for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
+ *data++ = pp->ethtool_stats[i];
+}
+
+static int mvneta_ethtool_get_sset_count(struct net_device *dev, int sset)
+{
+ if (sset == ETH_SS_STATS)
+ return ARRAY_SIZE(mvneta_statistics);
+ return -EOPNOTSUPP;
+}
+
static const struct net_device_ops mvneta_netdev_ops = {
.ndo_open = mvneta_open,
.ndo_stop = mvneta_stop,
@@ -2896,6 +3113,9 @@ const struct ethtool_ops mvneta_eth_tool_ops = {
.get_drvinfo = mvneta_ethtool_get_drvinfo,
.get_ringparam = mvneta_ethtool_get_ringparam,
.set_ringparam = mvneta_ethtool_set_ringparam,
+ .get_strings = mvneta_ethtool_get_strings,
+ .get_ethtool_stats = mvneta_ethtool_get_stats,
+ .get_sset_count = mvneta_ethtool_get_sset_count,
};
/* Initialize hw */
@@ -3032,14 +3252,7 @@ static int mvneta_probe(struct platform_device *pdev)
const char *managed;
int phy_mode;
int err;
-
- /* Our multiqueue support is not complete, so for now, only
- * allow the usage of the first RX queue
- */
- if (rxq_def != 0) {
- dev_err(&pdev->dev, "Invalid rxq_def argument: %d\n", rxq_def);
- return -EINVAL;
- }
+ int cpu;
dev = alloc_etherdev_mqs(sizeof(struct mvneta_port), txq_number, rxq_number);
if (!dev)
@@ -3091,6 +3304,7 @@ static int mvneta_probe(struct platform_device *pdev)
err = of_property_read_string(dn, "managed", &managed);
pp->use_inband_status = (err == 0 &&
strcmp(managed, "in-band-status") == 0);
+ pp->cpu_notifier.notifier_call = mvneta_percpu_notifier;
pp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pp->clk)) {
@@ -3107,11 +3321,18 @@ static int mvneta_probe(struct platform_device *pdev)
goto err_clk;
}
+ /* Alloc per-cpu port structure */
+ pp->ports = alloc_percpu(struct mvneta_pcpu_port);
+ if (!pp->ports) {
+ err = -ENOMEM;
+ goto err_clk;
+ }
+
/* Alloc per-cpu stats */
pp->stats = netdev_alloc_pcpu_stats(struct mvneta_pcpu_stats);
if (!pp->stats) {
err = -ENOMEM;
- goto err_clk;
+ goto err_free_ports;
}
dt_mac_addr = of_get_mac_address(dn);
@@ -3152,7 +3373,12 @@ static int mvneta_probe(struct platform_device *pdev)
if (dram_target_info)
mvneta_conf_mbus_windows(pp, dram_target_info);
- netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT);
+ for_each_present_cpu(cpu) {
+ struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+
+ netif_napi_add(dev, &port->napi, mvneta_poll, NAPI_POLL_WEIGHT);
+ port->pp = pp;
+ }
dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
dev->hw_features |= dev->features;
@@ -3183,6 +3409,8 @@ static int mvneta_probe(struct platform_device *pdev)
err_free_stats:
free_percpu(pp->stats);
+err_free_ports:
+ free_percpu(pp->ports);
err_clk:
clk_disable_unprepare(pp->clk);
err_put_phy_node:
@@ -3202,6 +3430,7 @@ static int mvneta_remove(struct platform_device *pdev)
unregister_netdev(dev);
clk_disable_unprepare(pp->clk);
+ free_percpu(pp->ports);
free_percpu(pp->stats);
irq_dispose_mapping(dev->irq);
of_node_put(pp->phy_node);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index d9f4498832a1..5606a043063e 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4819,6 +4819,18 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8,
ETH_ALEN);
+ /* if the address is invalid, use a random value */
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ struct sockaddr sa = { AF_UNSPEC };
+
+ netdev_warn(dev,
+ "Invalid MAC address, defaulting to random\n");
+ eth_hw_addr_random(dev);
+ memcpy(sa.sa_data, dev->dev_addr, ETH_ALEN);
+ if (sky2_set_mac_address(dev, &sa))
+ netdev_warn(dev, "Failed to set MAC address.\n");
+ }
+
return dev;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 0a3202047569..2177e56ed0be 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -2398,7 +2398,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
}
}
- memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
+ memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
INIT_WORK(&priv->mfunc.master.comm_work,
mlx4_master_comm_channel);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index f79d8124321e..ddb5541882f5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -95,9 +95,6 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
(u16) (mdev->dev->caps.fw_ver & 0xffff));
strlcpy(drvinfo->bus_info, pci_name(mdev->dev->persist->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = 0;
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
}
static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index a946e4bf71d2..005f910ec955 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -123,6 +123,28 @@ void mlx4_en_update_loopback_state(struct net_device *dev,
*/
if (mlx4_is_mfunc(priv->mdev->dev) || priv->validate_loopback)
priv->flags |= MLX4_EN_FLAG_ENABLE_HW_LOOPBACK;
+
+ mutex_lock(&priv->mdev->state_lock);
+ if (priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB &&
+ priv->rss_map.indir_qp.qpn) {
+ int i;
+ int err = 0;
+ int loopback = !!(features & NETIF_F_LOOPBACK);
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ int ret;
+
+ ret = mlx4_en_change_mcast_lb(priv,
+ &priv->rss_map.qps[i],
+ loopback);
+ if (!err)
+ err = ret;
+ }
+ if (err)
+ mlx4_warn(priv->mdev, "failed to change mcast loopback\n");
+ }
+ mutex_unlock(&priv->mdev->state_lock);
}
static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 4726122ea76b..886e1bc86374 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -573,10 +573,8 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
{
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_dev *dev = mdev->dev;
- struct mlx4_mac_entry *entry;
int index = 0;
int err = 0;
- u64 reg_id = 0;
int *qpn = &priv->base_qpn;
u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr);
@@ -600,44 +598,11 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
if (err) {
en_err(priv, "Failed to reserve qp for mac registration\n");
- goto qp_err;
- }
-
- err = mlx4_en_uc_steer_add(priv, priv->dev->dev_addr, qpn, &reg_id);
- if (err)
- goto steer_err;
-
- err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn,
- &priv->tunnel_reg_id);
- if (err)
- goto tunnel_err;
-
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- err = -ENOMEM;
- goto alloc_err;
+ mlx4_unregister_mac(dev, priv->port, mac);
+ return err;
}
- memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
- memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
- entry->reg_id = reg_id;
-
- hlist_add_head_rcu(&entry->hlist,
- &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
return 0;
-
-alloc_err:
- if (priv->tunnel_reg_id)
- mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
-tunnel_err:
- mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id);
-
-steer_err:
- mlx4_qp_release_range(dev, *qpn, 1);
-
-qp_err:
- mlx4_unregister_mac(dev, priv->port, mac);
- return err;
}
static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
@@ -645,39 +610,13 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_dev *dev = mdev->dev;
int qpn = priv->base_qpn;
- u64 mac;
if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
- mac = mlx4_mac_to_u64(priv->dev->dev_addr);
+ u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr);
en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
priv->dev->dev_addr);
mlx4_unregister_mac(dev, priv->port, mac);
} else {
- struct mlx4_mac_entry *entry;
- struct hlist_node *tmp;
- struct hlist_head *bucket;
- unsigned int i;
-
- for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
- bucket = &priv->mac_hash[i];
- hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
- mac = mlx4_mac_to_u64(entry->mac);
- en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
- entry->mac);
- mlx4_en_uc_steer_release(priv, entry->mac,
- qpn, entry->reg_id);
-
- mlx4_unregister_mac(dev, priv->port, mac);
- hlist_del_rcu(&entry->hlist);
- kfree_rcu(entry, rcu);
- }
- }
-
- if (priv->tunnel_reg_id) {
- mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
- priv->tunnel_reg_id = 0;
- }
-
en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
priv->port, qpn);
mlx4_qp_release_range(dev, qpn, 1);
@@ -1283,6 +1222,75 @@ static void mlx4_en_netpoll(struct net_device *dev)
}
#endif
+static int mlx4_en_set_rss_steer_rules(struct mlx4_en_priv *priv)
+{
+ u64 reg_id;
+ int err = 0;
+ int *qpn = &priv->base_qpn;
+ struct mlx4_mac_entry *entry;
+
+ err = mlx4_en_uc_steer_add(priv, priv->dev->dev_addr, qpn, &reg_id);
+ if (err)
+ return err;
+
+ err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn,
+ &priv->tunnel_reg_id);
+ if (err)
+ goto tunnel_err;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ err = -ENOMEM;
+ goto alloc_err;
+ }
+
+ memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
+ memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
+ entry->reg_id = reg_id;
+ hlist_add_head_rcu(&entry->hlist,
+ &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
+
+ return 0;
+
+alloc_err:
+ if (priv->tunnel_reg_id)
+ mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
+
+tunnel_err:
+ mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id);
+ return err;
+}
+
+static void mlx4_en_delete_rss_steer_rules(struct mlx4_en_priv *priv)
+{
+ u64 mac;
+ unsigned int i;
+ int qpn = priv->base_qpn;
+ struct hlist_head *bucket;
+ struct hlist_node *tmp;
+ struct mlx4_mac_entry *entry;
+
+ for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
+ bucket = &priv->mac_hash[i];
+ hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
+ mac = mlx4_mac_to_u64(entry->mac);
+ en_dbg(DRV, priv, "Registering MAC:%pM for deleting\n",
+ entry->mac);
+ mlx4_en_uc_steer_release(priv, entry->mac,
+ qpn, entry->reg_id);
+
+ mlx4_unregister_mac(priv->mdev->dev, priv->port, mac);
+ hlist_del_rcu(&entry->hlist);
+ kfree_rcu(entry, rcu);
+ }
+ }
+
+ if (priv->tunnel_reg_id) {
+ mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
+ priv->tunnel_reg_id = 0;
+ }
+}
+
static void mlx4_en_tx_timeout(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -1684,6 +1692,11 @@ int mlx4_en_start_port(struct net_device *dev)
goto tx_err;
}
+ /* Set Unicast and VXLAN steering rules */
+ if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0 &&
+ mlx4_en_set_rss_steer_rules(priv))
+ mlx4_warn(mdev, "Failed setting steering rules\n");
+
/* Attach rx QP to bradcast address */
eth_broadcast_addr(&mc_list[10]);
mc_list[5] = priv->port; /* needed for B0 steering support */
@@ -1831,6 +1844,9 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
for (i = 0; i < priv->tx_ring_num; i++)
mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
+ if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
+ mlx4_en_delete_rss_steer_rules(priv);
+
/* Free RSS qps */
mlx4_en_release_rss_steer(priv);
@@ -2800,7 +2816,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
struct mlx4_en_priv *priv;
int i;
int err;
- u64 mac_u64;
dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
MAX_TX_RINGS, MAX_RX_RINGS);
@@ -2892,17 +2907,17 @@ 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)) {
- if (mlx4_is_slave(priv->mdev->dev)) {
- eth_hw_addr_random(dev);
- en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr);
- mac_u64 = mlx4_mac_to_u64(dev->dev_addr);
- mdev->dev->caps.def_mac[priv->port] = mac_u64;
- } else {
- en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
- priv->port, dev->dev_addr);
- err = -EINVAL;
- goto out;
- }
+ en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
+ priv->port, dev->dev_addr);
+ err = -EINVAL;
+ goto out;
+ } else if (mlx4_is_slave(priv->mdev->dev) &&
+ (priv->mdev->dev->port_random_macs & 1 << priv->port)) {
+ /* Random MAC was assigned in mlx4_slave_cap
+ * in mlx4_core module
+ */
+ dev->addr_assign_type |= NET_ADDR_RANDOM;
+ en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr);
}
memcpy(priv->current_mac, dev->dev_addr, sizeof(priv->current_mac));
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index e482fa1bb741..12aab5a659d3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
@@ -69,6 +69,15 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
context->pri_path.counter_index = priv->counter_index;
context->cqn_send = cpu_to_be32(cqn);
context->cqn_recv = cpu_to_be32(cqn);
+ if (!rss &&
+ (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
+ context->pri_path.counter_index !=
+ MLX4_SINK_COUNTER_INDEX(mdev->dev)) {
+ /* disable multicast loopback to qp with same counter */
+ if (!(dev->features & NETIF_F_LOOPBACK))
+ context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
+ context->pri_path.control |= MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
+ }
context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
context->param3 |= cpu_to_be32(1 << 30);
@@ -80,6 +89,22 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
}
}
+int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
+ int loopback)
+{
+ int ret;
+ struct mlx4_update_qp_params qp_params;
+
+ memset(&qp_params, 0, sizeof(qp_params));
+ if (!loopback)
+ qp_params.flags = MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB;
+
+ ret = mlx4_update_qp(priv->mdev->dev, qp->qpn,
+ MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB,
+ &qp_params);
+
+ return ret;
+}
int mlx4_en_map_buffer(struct mlx4_buf *buf)
{
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 494e7762fdb1..4421bf5463f6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -964,6 +964,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_SVLAN;
else if (vlan_proto == ETH_P_8021Q)
tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_CVLAN;
+ else
+ tx_desc->ctrl.ins_vlan = 0;
tx_desc->ctrl.fence_size = real_size;
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 8e81e53c370e..603d1c3d3b2e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -196,7 +196,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
return;
}
- memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
+ memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
s_eqe->slave_id = slave;
/* ensure all information is written before setting the ownersip bit */
dma_wmb();
@@ -1364,6 +1364,10 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
* and performing a NOP command
*/
for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+ /* Make sure request_irq was called */
+ if (!priv->eq_table.eq[i].have_irq)
+ continue;
+
/* Temporary use polling for command completions */
mlx4_cmd_use_polling(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index e8ec1dec5789..90db94e83fde 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -155,6 +155,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
[27] = "Port beacon support",
[28] = "RX-ALL support",
[29] = "802.1ad offload support",
+ [31] = "Modifying loopback source checks using UPDATE_QP support",
+ [32] = "Loopback source checks support",
};
int i;
@@ -964,6 +966,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
if (field32 & (1 << 16))
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
+ if (field32 & (1 << 18))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB;
+ if (field32 & (1 << 19))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_LB_SRC_CHK;
if (field32 & (1 << 26))
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
if (field32 & (1 << 20))
@@ -2840,3 +2846,19 @@ int set_phv_bit(struct mlx4_dev *dev, u8 port, int new_val)
return -EOPNOTSUPP;
}
EXPORT_SYMBOL(set_phv_bit);
+
+void mlx4_replace_zero_macs(struct mlx4_dev *dev)
+{
+ int i;
+ u8 mac_addr[ETH_ALEN];
+
+ dev->port_random_macs = 0;
+ for (i = 1; i <= dev->caps.num_ports; ++i)
+ if (!dev->caps.def_mac[i] &&
+ dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH) {
+ eth_random_addr(mac_addr);
+ dev->port_random_macs |= 1 << i;
+ dev->caps.def_mac[i] = mlx4_mac_to_u64(mac_addr);
+ }
+}
+EXPORT_SYMBOL_GPL(mlx4_replace_zero_macs);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 006757f80988..31c491e02e69 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -863,6 +863,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
return -ENODEV;
}
+ mlx4_replace_zero_macs(dev);
+
dev->caps.qp0_qkey = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);
dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
@@ -890,9 +892,10 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
dev->caps.qp1_proxy[i - 1] = func_cap.qp1_proxy_qpn;
dev->caps.port_mask[i] = dev->caps.port_type[i];
dev->caps.phys_port_id[i] = func_cap.phys_port_id;
- if (mlx4_get_slave_pkey_gid_tbl_len(dev, i,
- &dev->caps.gid_table_len[i],
- &dev->caps.pkey_table_len[i]))
+ err = mlx4_get_slave_pkey_gid_tbl_len(dev, i,
+ &dev->caps.gid_table_len[i],
+ &dev->caps.pkey_table_len[i]);
+ if (err)
goto err_mem;
}
@@ -904,6 +907,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
dev->caps.uar_page_size * dev->caps.num_uars,
(unsigned long long)
pci_resource_len(dev->persist->pdev, 2));
+ err = -ENOMEM;
goto err_mem;
}
@@ -2669,14 +2673,11 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
if (msi_x) {
int nreq = dev->caps.num_ports * num_online_cpus() + 1;
- bool shared_ports = false;
nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
nreq);
- if (nreq > MAX_MSIX) {
+ if (nreq > MAX_MSIX)
nreq = MAX_MSIX;
- shared_ports = true;
- }
entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
if (!entries)
@@ -2699,9 +2700,6 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
bitmap_zero(priv->eq_table.eq[MLX4_EQ_ASYNC].actv_ports.ports,
dev->caps.num_ports);
- if (MLX4_IS_LEGACY_EQ_MODE(dev->caps))
- shared_ports = true;
-
for (i = 0; i < dev->caps.num_comp_vectors + 1; i++) {
if (i == MLX4_EQ_ASYNC)
continue;
@@ -2709,7 +2707,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
priv->eq_table.eq[i].irq =
entries[i + 1 - !!(i > MLX4_EQ_ASYNC)].vector;
- if (shared_ports) {
+ if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) {
bitmap_fill(priv->eq_table.eq[i].actv_ports.ports,
dev->caps.num_ports);
/* We don't set affinity hint when there
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 232b2b55f23b..e1cf9036af22 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -1378,6 +1378,8 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work);
void mlx4_init_quotas(struct mlx4_dev *dev);
+/* for VFs, replace zero MACs with randomly-generated MACs at driver start */
+void mlx4_replace_zero_macs(struct mlx4_dev *dev);
int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port);
/* Returns the VF index of slave */
int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index defcf8c395bf..c41f15102ae0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -798,7 +798,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
int mlx4_en_map_buffer(struct mlx4_buf *buf);
void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
-
+int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
+ int loopback);
void mlx4_en_calc_rx_buf(struct net_device *dev);
int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index 78f51e103880..93195191f45b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -318,7 +318,7 @@ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
key, NULL);
} else {
mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR_OR_NULL(mailbox))
+ if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
err = mlx4_cmd_box(dev, 0, mailbox->dma, key,
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 20268634a9ab..168823dde79f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -422,20 +422,37 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
u64 qp_mask = 0;
int err = 0;
+ if (!attr || (attr & ~MLX4_UPDATE_QP_SUPPORTED_ATTRS))
+ return -EINVAL;
+
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
cmd = (struct mlx4_update_qp_context *)mailbox->buf;
- if (!attr || (attr & ~MLX4_UPDATE_QP_SUPPORTED_ATTRS))
- return -EINVAL;
-
if (attr & MLX4_UPDATE_QP_SMAC) {
pri_addr_path_mask |= 1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX;
cmd->qp_context.pri_path.grh_mylmc = params->smac_index;
}
+ if (attr & MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB) {
+ if (!(dev->caps.flags2
+ & MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB)) {
+ mlx4_warn(dev,
+ "Trying to set src check LB, but it isn't supported\n");
+ err = -ENOTSUPP;
+ goto out;
+ }
+ pri_addr_path_mask |=
+ 1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB;
+ if (params->flags &
+ MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB) {
+ cmd->qp_context.pri_path.fl |=
+ MLX4_FL_ETH_SRC_CHECK_MC_LB;
+ }
+ }
+
if (attr & MLX4_UPDATE_QP_VSD) {
qp_mask |= 1ULL << MLX4_UPD_QP_MASK_VSD;
if (params->flags & MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE)
@@ -458,7 +475,7 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
err = mlx4_cmd(dev, mailbox->dma, qpn & 0xffffff, 0,
MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
-
+out:
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 731423ca575d..6fec3e993d02 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -770,9 +770,12 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
}
}
+ /* preserve IF_COUNTER flag */
+ qpc->pri_path.vlan_control &=
+ MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE &&
dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
- qpc->pri_path.vlan_control =
+ qpc->pri_path.vlan_control |=
MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |
MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED |
@@ -780,12 +783,12 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
} else if (0 != vp_oper->state.default_vlan) {
- qpc->pri_path.vlan_control =
+ qpc->pri_path.vlan_control |=
MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
} else { /* priority tagged */
- qpc->pri_path.vlan_control =
+ qpc->pri_path.vlan_control |=
MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
}
@@ -1238,8 +1241,10 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
return 0;
undo:
- for (--i; i >= base; --i)
+ for (--i; i >= 0; --i) {
rb_erase(&res_arr[i]->node, root);
+ list_del_init(&res_arr[i]->list);
+ }
spin_unlock_irq(mlx4_tlock(dev));
@@ -3762,9 +3767,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
update_gid(dev, inbox, (u8)slave);
adjust_proxy_tun_qkey(dev, vhcr, qpc);
orig_sched_queue = qpc->pri_path.sched_queue;
- err = update_vport_qp_param(dev, inbox, slave, qpn);
- if (err)
- return err;
err = get_res(dev, slave, qpn, RES_QP, &qp);
if (err)
@@ -3774,6 +3776,10 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
goto out;
}
+ err = update_vport_qp_param(dev, inbox, slave, qpn);
+ if (err)
+ goto out;
+
err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
out:
/* if no error, save sched queue value passed in by VF. This is
@@ -4208,7 +4214,9 @@ static int add_eth_header(struct mlx4_dev *dev, int slave,
}
-#define MLX4_UPD_QP_PATH_MASK_SUPPORTED (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)
+#define MLX4_UPD_QP_PATH_MASK_SUPPORTED ( \
+ 1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX |\
+ 1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB)
int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -4231,6 +4239,16 @@ int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
(pri_addr_path_mask & ~MLX4_UPD_QP_PATH_MASK_SUPPORTED))
return -EPERM;
+ if ((pri_addr_path_mask &
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB)) &&
+ !(dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB)) {
+ mlx4_warn(dev,
+ "Src check LB for slave %d isn't supported\n",
+ slave);
+ return -ENOTSUPP;
+ }
+
/* Just change the smac for the QP */
err = get_res(dev, slave, qpn, RES_QP, &rqp);
if (err) {
@@ -4934,26 +4952,41 @@ static void rem_slave_counters(struct mlx4_dev *dev, int slave)
struct res_counter *counter;
struct res_counter *tmp;
int err;
- int index;
+ int *counters_arr = NULL;
+ int i, j;
err = move_all_busy(dev, slave, RES_COUNTER);
if (err)
mlx4_warn(dev, "rem_slave_counters: Could not move all counters - too busy for slave %d\n",
slave);
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
- if (counter->com.owner == slave) {
- index = counter->com.res_id;
- rb_erase(&counter->com.node,
- &tracker->res_tree[RES_COUNTER]);
- list_del(&counter->com.list);
- kfree(counter);
- __mlx4_counter_free(dev, index);
+ counters_arr = kmalloc_array(dev->caps.max_counters,
+ sizeof(*counters_arr), GFP_KERNEL);
+ if (!counters_arr)
+ return;
+
+ do {
+ i = 0;
+ j = 0;
+ spin_lock_irq(mlx4_tlock(dev));
+ list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
+ if (counter->com.owner == slave) {
+ counters_arr[i++] = counter->com.res_id;
+ rb_erase(&counter->com.node,
+ &tracker->res_tree[RES_COUNTER]);
+ list_del(&counter->com.list);
+ kfree(counter);
+ }
+ }
+ spin_unlock_irq(mlx4_tlock(dev));
+
+ while (j < i) {
+ __mlx4_counter_free(dev, counters_arr[j++]);
mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
}
- }
- spin_unlock_irq(mlx4_tlock(dev));
+ } while (i);
+
+ kfree(counters_arr);
}
static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 75ff58dc1ff5..037fc4cdf5af 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -30,7 +30,7 @@
* SOFTWARE.
*/
-#include <asm-generic/kmap_types.h>
+#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -254,6 +254,156 @@ static void dump_buf(void *buf, int size, int data_only, int offset)
pr_debug("\n");
}
+enum {
+ MLX5_DRIVER_STATUS_ABORTED = 0xfe,
+ MLX5_DRIVER_SYND = 0xbadd00de,
+};
+
+static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
+ u32 *synd, u8 *status)
+{
+ *synd = 0;
+ *status = 0;
+
+ switch (op) {
+ case MLX5_CMD_OP_TEARDOWN_HCA:
+ case MLX5_CMD_OP_DISABLE_HCA:
+ case MLX5_CMD_OP_MANAGE_PAGES:
+ case MLX5_CMD_OP_DESTROY_MKEY:
+ case MLX5_CMD_OP_DESTROY_EQ:
+ case MLX5_CMD_OP_DESTROY_CQ:
+ case MLX5_CMD_OP_DESTROY_QP:
+ case MLX5_CMD_OP_DESTROY_PSV:
+ case MLX5_CMD_OP_DESTROY_SRQ:
+ case MLX5_CMD_OP_DESTROY_XRC_SRQ:
+ case MLX5_CMD_OP_DESTROY_DCT:
+ case MLX5_CMD_OP_DEALLOC_Q_COUNTER:
+ case MLX5_CMD_OP_DEALLOC_PD:
+ case MLX5_CMD_OP_DEALLOC_UAR:
+ case MLX5_CMD_OP_DETTACH_FROM_MCG:
+ case MLX5_CMD_OP_DEALLOC_XRCD:
+ case MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN:
+ case MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT:
+ case MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY:
+ case MLX5_CMD_OP_DESTROY_TIR:
+ case MLX5_CMD_OP_DESTROY_SQ:
+ case MLX5_CMD_OP_DESTROY_RQ:
+ case MLX5_CMD_OP_DESTROY_RMP:
+ case MLX5_CMD_OP_DESTROY_TIS:
+ case MLX5_CMD_OP_DESTROY_RQT:
+ case MLX5_CMD_OP_DESTROY_FLOW_TABLE:
+ case MLX5_CMD_OP_DESTROY_FLOW_GROUP:
+ case MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY:
+ return MLX5_CMD_STAT_OK;
+
+ case MLX5_CMD_OP_QUERY_HCA_CAP:
+ case MLX5_CMD_OP_QUERY_ADAPTER:
+ case MLX5_CMD_OP_INIT_HCA:
+ case MLX5_CMD_OP_ENABLE_HCA:
+ case MLX5_CMD_OP_QUERY_PAGES:
+ case MLX5_CMD_OP_SET_HCA_CAP:
+ case MLX5_CMD_OP_QUERY_ISSI:
+ case MLX5_CMD_OP_SET_ISSI:
+ case MLX5_CMD_OP_CREATE_MKEY:
+ case MLX5_CMD_OP_QUERY_MKEY:
+ case MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS:
+ case MLX5_CMD_OP_PAGE_FAULT_RESUME:
+ case MLX5_CMD_OP_CREATE_EQ:
+ case MLX5_CMD_OP_QUERY_EQ:
+ case MLX5_CMD_OP_GEN_EQE:
+ case MLX5_CMD_OP_CREATE_CQ:
+ case MLX5_CMD_OP_QUERY_CQ:
+ case MLX5_CMD_OP_MODIFY_CQ:
+ case MLX5_CMD_OP_CREATE_QP:
+ case MLX5_CMD_OP_RST2INIT_QP:
+ case MLX5_CMD_OP_INIT2RTR_QP:
+ case MLX5_CMD_OP_RTR2RTS_QP:
+ case MLX5_CMD_OP_RTS2RTS_QP:
+ case MLX5_CMD_OP_SQERR2RTS_QP:
+ case MLX5_CMD_OP_2ERR_QP:
+ case MLX5_CMD_OP_2RST_QP:
+ case MLX5_CMD_OP_QUERY_QP:
+ case MLX5_CMD_OP_SQD_RTS_QP:
+ case MLX5_CMD_OP_INIT2INIT_QP:
+ case MLX5_CMD_OP_CREATE_PSV:
+ case MLX5_CMD_OP_CREATE_SRQ:
+ case MLX5_CMD_OP_QUERY_SRQ:
+ case MLX5_CMD_OP_ARM_RQ:
+ case MLX5_CMD_OP_CREATE_XRC_SRQ:
+ case MLX5_CMD_OP_QUERY_XRC_SRQ:
+ case MLX5_CMD_OP_ARM_XRC_SRQ:
+ case MLX5_CMD_OP_CREATE_DCT:
+ case MLX5_CMD_OP_DRAIN_DCT:
+ case MLX5_CMD_OP_QUERY_DCT:
+ case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
+ case MLX5_CMD_OP_QUERY_VPORT_STATE:
+ case MLX5_CMD_OP_MODIFY_VPORT_STATE:
+ case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
+ case MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT:
+ case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
+ case MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT:
+ case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
+ case MLX5_CMD_OP_SET_ROCE_ADDRESS:
+ case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
+ case MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT:
+ case MLX5_CMD_OP_QUERY_HCA_VPORT_GID:
+ case MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY:
+ case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
+ case MLX5_CMD_OP_ALLOC_Q_COUNTER:
+ case MLX5_CMD_OP_QUERY_Q_COUNTER:
+ case MLX5_CMD_OP_ALLOC_PD:
+ case MLX5_CMD_OP_ALLOC_UAR:
+ case MLX5_CMD_OP_CONFIG_INT_MODERATION:
+ case MLX5_CMD_OP_ACCESS_REG:
+ case MLX5_CMD_OP_ATTACH_TO_MCG:
+ case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
+ case MLX5_CMD_OP_MAD_IFC:
+ case MLX5_CMD_OP_QUERY_MAD_DEMUX:
+ case MLX5_CMD_OP_SET_MAD_DEMUX:
+ case MLX5_CMD_OP_NOP:
+ case MLX5_CMD_OP_ALLOC_XRCD:
+ case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
+ case MLX5_CMD_OP_QUERY_CONG_STATUS:
+ case MLX5_CMD_OP_MODIFY_CONG_STATUS:
+ case MLX5_CMD_OP_QUERY_CONG_PARAMS:
+ case MLX5_CMD_OP_MODIFY_CONG_PARAMS:
+ case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
+ case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
+ case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
+ case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
+ case MLX5_CMD_OP_CREATE_TIR:
+ case MLX5_CMD_OP_MODIFY_TIR:
+ case MLX5_CMD_OP_QUERY_TIR:
+ case MLX5_CMD_OP_CREATE_SQ:
+ case MLX5_CMD_OP_MODIFY_SQ:
+ case MLX5_CMD_OP_QUERY_SQ:
+ case MLX5_CMD_OP_CREATE_RQ:
+ case MLX5_CMD_OP_MODIFY_RQ:
+ case MLX5_CMD_OP_QUERY_RQ:
+ case MLX5_CMD_OP_CREATE_RMP:
+ case MLX5_CMD_OP_MODIFY_RMP:
+ case MLX5_CMD_OP_QUERY_RMP:
+ case MLX5_CMD_OP_CREATE_TIS:
+ case MLX5_CMD_OP_MODIFY_TIS:
+ case MLX5_CMD_OP_QUERY_TIS:
+ case MLX5_CMD_OP_CREATE_RQT:
+ case MLX5_CMD_OP_MODIFY_RQT:
+ case MLX5_CMD_OP_QUERY_RQT:
+ case MLX5_CMD_OP_CREATE_FLOW_TABLE:
+ case MLX5_CMD_OP_QUERY_FLOW_TABLE:
+ case MLX5_CMD_OP_CREATE_FLOW_GROUP:
+ case MLX5_CMD_OP_QUERY_FLOW_GROUP:
+ case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
+ case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
+ *status = MLX5_DRIVER_STATUS_ABORTED;
+ *synd = MLX5_DRIVER_SYND;
+ return -EIO;
+ default:
+ mlx5_core_err(dev, "Unknown FW command (%d)\n", op);
+ return -EINVAL;
+ }
+}
+
const char *mlx5_command_str(int command)
{
switch (command) {
@@ -473,6 +623,7 @@ static void cmd_work_handler(struct work_struct *work)
struct mlx5_core_dev *dev = container_of(cmd, struct mlx5_core_dev, cmd);
struct mlx5_cmd_layout *lay;
struct semaphore *sem;
+ unsigned long flags;
sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
down(sem);
@@ -485,6 +636,9 @@ static void cmd_work_handler(struct work_struct *work)
}
} else {
ent->idx = cmd->max_reg_cmds;
+ spin_lock_irqsave(&cmd->alloc_lock, flags);
+ clear_bit(ent->idx, &cmd->bitmask);
+ spin_unlock_irqrestore(&cmd->alloc_lock, flags);
}
ent->token = alloc_token(cmd);
@@ -584,6 +738,16 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
return err;
}
+static __be32 *get_synd_ptr(struct mlx5_outbox_hdr *out)
+{
+ return &out->syndrome;
+}
+
+static u8 *get_status_ptr(struct mlx5_outbox_hdr *out)
+{
+ return &out->status;
+}
+
/* Notes:
* 1. Callback functions may not sleep
* 2. page queue commands do not support asynchrous completion
@@ -1081,7 +1245,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
}
}
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
{
struct mlx5_cmd *cmd = &dev->cmd;
struct mlx5_cmd_work_ent *ent;
@@ -1092,7 +1256,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
s64 ds;
struct mlx5_cmd_stats *stats;
unsigned long flags;
+ unsigned long vector;
+ /* there can be at most 32 command queues */
+ vector = vec & 0xffffffff;
for (i = 0; i < (1 << cmd->log_sz); i++) {
if (test_bit(i, &vector)) {
struct semaphore *sem;
@@ -1110,11 +1277,16 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
ent->ret = verify_signature(ent);
else
ent->ret = 0;
- ent->status = ent->lay->status_own >> 1;
+ if (vec & MLX5_TRIGGERED_CMD_COMP)
+ ent->status = MLX5_DRIVER_STATUS_ABORTED;
+ else
+ ent->status = ent->lay->status_own >> 1;
+
mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",
ent->ret, deliv_status_to_str(ent->status), ent->status);
}
free_ent(cmd, ent->idx);
+
if (ent->callback) {
ds = ent->ts2 - ent->ts1;
if (ent->op < ARRAY_SIZE(cmd->stats)) {
@@ -1136,6 +1308,7 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
mlx5_free_cmd_msg(dev, ent->out);
free_msg(dev, ent->in);
+ err = err ? err : ent->status;
free_cmd(ent);
callback(err, context);
} else {
@@ -1183,6 +1356,11 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size,
return msg;
}
+static u16 opcode_from_in(struct mlx5_inbox_hdr *in)
+{
+ return be16_to_cpu(in->opcode);
+}
+
static int is_manage_pages(struct mlx5_inbox_hdr *in)
{
return be16_to_cpu(in->opcode) == MLX5_CMD_OP_MANAGE_PAGES;
@@ -1197,6 +1375,15 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
gfp_t gfp;
int err;
u8 status = 0;
+ u32 drv_synd;
+
+ if (pci_channel_offline(dev->pdev) ||
+ dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ err = mlx5_internal_err_ret_value(dev, opcode_from_in(in), &drv_synd, &status);
+ *get_synd_ptr(out) = cpu_to_be32(drv_synd);
+ *get_status_ptr(out) = status;
+ return err;
+ }
pages_queue = is_manage_pages(in);
gfp = callback ? GFP_ATOMIC : GFP_KERNEL;
@@ -1363,6 +1550,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
int err;
int i;
+ memset(cmd, 0, sizeof(*cmd));
cmd_if_rev = cmdif_rev(dev);
if (cmd_if_rev != CMD_IF_REV) {
dev_err(&dev->pdev->dev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
index 04ab7e445eae..b51e42d6fbec 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
@@ -242,6 +242,7 @@ int mlx5_init_cq_table(struct mlx5_core_dev *dev)
struct mlx5_cq_table *table = &dev->priv.cq_table;
int err;
+ memset(table, 0, sizeof(*table));
spin_lock_init(&table->lock);
INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
err = mlx5_cq_debugfs_init(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 0983a208b299..22e72bf1ae48 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -334,9 +334,15 @@ struct mlx5e_tx_skb_cb {
#define MLX5E_TX_SKB_CB(__skb) ((struct mlx5e_tx_skb_cb *)__skb->cb)
+enum mlx5e_dma_map_type {
+ MLX5E_DMA_MAP_SINGLE,
+ MLX5E_DMA_MAP_PAGE
+};
+
struct mlx5e_sq_dma {
- dma_addr_t addr;
- u32 size;
+ dma_addr_t addr;
+ u32 size;
+ enum mlx5e_dma_map_type type;
};
enum {
@@ -617,5 +623,11 @@ static inline void mlx5e_cq_arm(struct mlx5e_cq *cq)
mlx5_cq_arm(mcq, MLX5_CQ_DB_REQ_NOT, mcq->uar->map, NULL, cq->wq.cc);
}
+static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
+{
+ return min_t(int, mdev->priv.eq_table.num_comp_vectors,
+ MLX5E_MAX_NUM_CHANNELS);
+}
+
extern const struct ethtool_ops mlx5e_ethtool_ops;
u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index bce912688ca8..2e022e900939 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -345,9 +345,8 @@ static void mlx5e_get_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
struct mlx5e_priv *priv = netdev_priv(dev);
- int ncv = priv->mdev->priv.eq_table.num_comp_vectors;
- ch->max_combined = ncv;
+ ch->max_combined = mlx5e_get_max_num_channels(priv->mdev);
ch->combined_count = priv->params.num_channels;
}
@@ -355,7 +354,7 @@ static int mlx5e_set_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
struct mlx5e_priv *priv = netdev_priv(dev);
- int ncv = priv->mdev->priv.eq_table.num_comp_vectors;
+ int ncv = mlx5e_get_max_num_channels(priv->mdev);
unsigned int count = ch->combined_count;
bool was_opened;
int err = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c b/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
index e71563ce05d1..22d603f78273 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
@@ -598,6 +598,8 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
return;
priv->vlan.filter_disabled = false;
+ if (priv->netdev->flags & IFF_PROMISC)
+ return;
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
}
@@ -607,6 +609,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
return;
priv->vlan.filter_disabled = true;
+ if (priv->netdev->flags & IFF_PROMISC)
+ return;
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
}
@@ -717,8 +721,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled;
bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled;
- if (enable_promisc)
+ if (enable_promisc) {
mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC);
+ if (!priv->vlan.filter_disabled)
+ mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+ 0);
+ }
if (enable_allmulti)
mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
if (enable_broadcast)
@@ -730,8 +738,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast);
if (disable_allmulti)
mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti);
- if (disable_promisc)
+ if (disable_promisc) {
+ if (!priv->vlan.filter_disabled)
+ mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+ 0);
mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc);
+ }
ea->promisc_enabled = promisc_enabled;
ea->allmulti_enabled = allmulti_enabled;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 59874d666cff..1e52db32c73d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -442,12 +442,12 @@ static void mlx5e_disable_rq(struct mlx5e_rq *rq)
static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq)
{
+ unsigned long exp_time = jiffies + msecs_to_jiffies(20000);
struct mlx5e_channel *c = rq->channel;
struct mlx5e_priv *priv = c->priv;
struct mlx5_wq_ll *wq = &rq->wq;
- int i;
- for (i = 0; i < 1000; i++) {
+ while (time_before(jiffies, exp_time)) {
if (wq->cur_sz >= priv->params.min_rx_wqes)
return 0;
@@ -1332,6 +1332,42 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
return err;
}
+static int mlx5e_refresh_tir_self_loopback_enable(struct mlx5_core_dev *mdev,
+ u32 tirn)
+{
+ void *in;
+ int inlen;
+ int err;
+
+ inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
+ in = mlx5_vzalloc(inlen);
+ if (!in)
+ return -ENOMEM;
+
+ MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
+
+ err = mlx5_core_modify_tir(mdev, tirn, in, inlen);
+
+ kvfree(in);
+
+ return err;
+}
+
+static int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5e_priv *priv)
+{
+ int err;
+ int i;
+
+ for (i = 0; i < MLX5E_NUM_TT; i++) {
+ err = mlx5e_refresh_tir_self_loopback_enable(priv->mdev,
+ priv->tirn[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int mlx5e_set_dev_port_mtu(struct net_device *netdev)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -1367,13 +1403,20 @@ int mlx5e_open_locked(struct net_device *netdev)
err = mlx5e_set_dev_port_mtu(netdev);
if (err)
- return err;
+ goto err_clear_state_opened_flag;
err = mlx5e_open_channels(priv);
if (err) {
netdev_err(netdev, "%s: mlx5e_open_channels failed, %d\n",
__func__, err);
- return err;
+ goto err_clear_state_opened_flag;
+ }
+
+ err = mlx5e_refresh_tirs_self_loopback_enable(priv);
+ if (err) {
+ netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
+ __func__, err);
+ goto err_close_channels;
}
mlx5e_update_carrier(priv);
@@ -1382,6 +1425,12 @@ int mlx5e_open_locked(struct net_device *netdev)
schedule_delayed_work(&priv->update_stats_work, 0);
return 0;
+
+err_close_channels:
+ mlx5e_close_channels(priv);
+err_clear_state_opened_flag:
+ clear_bit(MLX5E_STATE_OPENED, &priv->state);
+ return err;
}
static int mlx5e_open(struct net_device *netdev)
@@ -1400,6 +1449,12 @@ int mlx5e_close_locked(struct net_device *netdev)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
+ /* May already be CLOSED in case a previous configuration operation
+ * (e.g RX/TX queue size change) that involves close&open failed.
+ */
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
+ return 0;
+
clear_bit(MLX5E_STATE_OPENED, &priv->state);
mlx5e_redirect_rqts(priv);
@@ -1833,7 +1888,7 @@ static int mlx5e_set_features(struct net_device *netdev,
mlx5e_disable_vlan_filter(priv);
}
- return 0;
+ return err;
}
static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
@@ -1846,6 +1901,8 @@ static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
+ max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+
if (new_mtu > max_mtu) {
netdev_err(netdev,
"%s: Bad MTU (%d) > (%d) Max\n",
@@ -1899,6 +1956,9 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
"Not creating net device, some required device capabilities are missing\n");
return -ENOTSUPP;
}
+ if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
+ mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
+
return 0;
}
@@ -1994,6 +2054,7 @@ static void mlx5e_build_netdev(struct net_device *netdev)
netdev->vlan_features |= NETIF_F_LRO;
netdev->hw_features = netdev->vlan_features;
+ netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -2037,8 +2098,7 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
{
struct net_device *netdev;
struct mlx5e_priv *priv;
- int nch = min_t(int, mdev->priv.eq_table.num_comp_vectors,
- MLX5E_MAX_NUM_CHANNELS);
+ int nch = mlx5e_get_max_num_channels(mdev);
int err;
if (mlx5e_check_required_hca_cap(mdev))
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index b73672f32e2c..1341b1d3c421 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -61,39 +61,47 @@ void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw)
}
}
-static void mlx5e_dma_pop_last_pushed(struct mlx5e_sq *sq, dma_addr_t *addr,
- u32 *size)
+static inline void mlx5e_tx_dma_unmap(struct device *pdev,
+ struct mlx5e_sq_dma *dma)
{
- sq->dma_fifo_pc--;
- *addr = sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr;
- *size = sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size;
-}
-
-static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, struct sk_buff *skb)
-{
- dma_addr_t addr;
- u32 size;
- int i;
-
- for (i = 0; i < MLX5E_TX_SKB_CB(skb)->num_dma; i++) {
- mlx5e_dma_pop_last_pushed(sq, &addr, &size);
- dma_unmap_single(sq->pdev, addr, size, DMA_TO_DEVICE);
+ switch (dma->type) {
+ case MLX5E_DMA_MAP_SINGLE:
+ dma_unmap_single(pdev, dma->addr, dma->size, DMA_TO_DEVICE);
+ break;
+ case MLX5E_DMA_MAP_PAGE:
+ dma_unmap_page(pdev, dma->addr, dma->size, DMA_TO_DEVICE);
+ break;
+ default:
+ WARN_ONCE(true, "mlx5e_tx_dma_unmap unknown DMA type!\n");
}
}
-static inline void mlx5e_dma_push(struct mlx5e_sq *sq, dma_addr_t addr,
- u32 size)
+static inline void mlx5e_dma_push(struct mlx5e_sq *sq,
+ dma_addr_t addr,
+ u32 size,
+ enum mlx5e_dma_map_type map_type)
{
sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr = addr;
sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size = size;
+ sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].type = map_type;
sq->dma_fifo_pc++;
}
-static inline void mlx5e_dma_get(struct mlx5e_sq *sq, u32 i, dma_addr_t *addr,
- u32 *size)
+static inline struct mlx5e_sq_dma *mlx5e_dma_get(struct mlx5e_sq *sq, u32 i)
+{
+ return &sq->dma_fifo[i & sq->dma_fifo_mask];
+}
+
+static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, struct sk_buff *skb)
{
- *addr = sq->dma_fifo[i & sq->dma_fifo_mask].addr;
- *size = sq->dma_fifo[i & sq->dma_fifo_mask].size;
+ int i;
+
+ for (i = 0; i < MLX5E_TX_SKB_CB(skb)->num_dma; i++) {
+ struct mlx5e_sq_dma *last_pushed_dma =
+ mlx5e_dma_get(sq, --sq->dma_fifo_pc);
+
+ mlx5e_tx_dma_unmap(sq->pdev, last_pushed_dma);
+ }
}
u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
@@ -116,14 +124,36 @@ static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq,
* headers and occur before the data gather.
* Therefore these headers must be copied into the WQE
*/
-#define MLX5E_MIN_INLINE (ETH_HLEN + 2/*vlan tag*/)
+#define MLX5E_MIN_INLINE ETH_HLEN
+
+ if (bf) {
+ u16 ihs = skb_headlen(skb);
+
+ if (skb_vlan_tag_present(skb))
+ ihs += VLAN_HLEN;
- if (bf && (skb_headlen(skb) <= sq->max_inline))
- return skb_headlen(skb);
+ if (ihs <= sq->max_inline)
+ return skb_headlen(skb);
+ }
return MLX5E_MIN_INLINE;
}
+static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs)
+{
+ struct vlan_ethhdr *vhdr = (struct vlan_ethhdr *)start;
+ int cpy1_sz = 2 * ETH_ALEN;
+ int cpy2_sz = ihs - cpy1_sz;
+
+ skb_copy_from_linear_data(skb, vhdr, cpy1_sz);
+ skb_pull_inline(skb, cpy1_sz);
+ vhdr->h_vlan_proto = skb->vlan_proto;
+ vhdr->h_vlan_TCI = cpu_to_be16(skb_vlan_tag_get(skb));
+ skb_copy_from_linear_data(skb, &vhdr->h_vlan_encapsulated_proto,
+ cpy2_sz);
+ skb_pull_inline(skb, cpy2_sz);
+}
+
static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
{
struct mlx5_wq_cyc *wq = &sq->wq;
@@ -175,8 +205,13 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
ETH_ZLEN);
}
- skb_copy_from_linear_data(skb, eseg->inline_hdr_start, ihs);
- skb_pull_inline(skb, ihs);
+ if (skb_vlan_tag_present(skb)) {
+ mlx5e_insert_vlan(eseg->inline_hdr_start, skb, ihs);
+ ihs += VLAN_HLEN;
+ } else {
+ skb_copy_from_linear_data(skb, eseg->inline_hdr_start, ihs);
+ skb_pull_inline(skb, ihs);
+ }
eseg->inline_hdr_sz = cpu_to_be16(ihs);
@@ -198,7 +233,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
dseg->lkey = sq->mkey_be;
dseg->byte_count = cpu_to_be32(headlen);
- mlx5e_dma_push(sq, dma_addr, headlen);
+ mlx5e_dma_push(sq, dma_addr, headlen, MLX5E_DMA_MAP_SINGLE);
MLX5E_TX_SKB_CB(skb)->num_dma++;
dseg++;
@@ -217,7 +252,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
dseg->lkey = sq->mkey_be;
dseg->byte_count = cpu_to_be32(fsz);
- mlx5e_dma_push(sq, dma_addr, fsz);
+ mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE);
MLX5E_TX_SKB_CB(skb)->num_dma++;
dseg++;
@@ -333,13 +368,10 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq)
}
for (j = 0; j < MLX5E_TX_SKB_CB(skb)->num_dma; j++) {
- dma_addr_t addr;
- u32 size;
+ struct mlx5e_sq_dma *dma =
+ mlx5e_dma_get(sq, dma_fifo_cc++);
- mlx5e_dma_get(sq, dma_fifo_cc, &addr, &size);
- dma_fifo_cc++;
- dma_unmap_single(sq->pdev, addr, size,
- DMA_TO_DEVICE);
+ mlx5e_tx_dma_unmap(sq->pdev, dma);
}
npkts++;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index a40b96d4c662..713ead583347 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -346,6 +346,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
int inlen;
eq->nent = roundup_pow_of_two(nent + MLX5_NUM_SPARE_EQE);
+ eq->cons_index = 0;
err = mlx5_buf_alloc(dev, eq->nent * MLX5_EQE_SIZE, &eq->buf);
if (err)
return err;
@@ -381,10 +382,10 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
name, pci_name(dev->pdev));
eq->eqn = out.eq_number;
- eq->irqn = vecidx;
+ eq->irqn = priv->msix_arr[vecidx].vector;
eq->dev = dev;
eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET;
- err = request_irq(priv->msix_arr[vecidx].vector, mlx5_msix_handler, 0,
+ err = request_irq(eq->irqn, mlx5_msix_handler, 0,
priv->irq_info[vecidx].name, eq);
if (err)
goto err_eq;
@@ -420,12 +421,12 @@ int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
int err;
mlx5_debug_eq_remove(dev, eq);
- free_irq(dev->priv.msix_arr[eq->irqn].vector, eq);
+ free_irq(eq->irqn, eq);
err = mlx5_cmd_destroy_eq(dev, eq->eqn);
if (err)
mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n",
eq->eqn);
- synchronize_irq(dev->priv.msix_arr[eq->irqn].vector);
+ synchronize_irq(eq->irqn);
mlx5_buf_free(dev, &eq->buf);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 292d76f2a904..f5deb642d0d6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/random.h>
#include <linux/vmalloc.h>
+#include <linux/hardirq.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/cmd.h>
#include "mlx5_core.h"
@@ -46,39 +47,113 @@ enum {
enum {
MLX5_HEALTH_SYNDR_FW_ERR = 0x1,
MLX5_HEALTH_SYNDR_IRISC_ERR = 0x7,
+ MLX5_HEALTH_SYNDR_HW_UNRECOVERABLE_ERR = 0x8,
MLX5_HEALTH_SYNDR_CRC_ERR = 0x9,
MLX5_HEALTH_SYNDR_FETCH_PCI_ERR = 0xa,
MLX5_HEALTH_SYNDR_HW_FTL_ERR = 0xb,
MLX5_HEALTH_SYNDR_ASYNC_EQ_OVERRUN_ERR = 0xc,
MLX5_HEALTH_SYNDR_EQ_ERR = 0xd,
+ MLX5_HEALTH_SYNDR_EQ_INV = 0xe,
MLX5_HEALTH_SYNDR_FFSER_ERR = 0xf,
+ MLX5_HEALTH_SYNDR_HIGH_TEMP = 0x10
};
-static DEFINE_SPINLOCK(health_lock);
-static LIST_HEAD(health_list);
-static struct work_struct health_work;
+enum {
+ MLX5_NIC_IFC_FULL = 0,
+ MLX5_NIC_IFC_DISABLED = 1,
+ MLX5_NIC_IFC_NO_DRAM_NIC = 2
+};
-static void health_care(struct work_struct *work)
+static u8 get_nic_interface(struct mlx5_core_dev *dev)
{
- struct mlx5_core_health *health, *n;
- struct mlx5_core_dev *dev;
- struct mlx5_priv *priv;
- LIST_HEAD(tlist);
+ return (ioread32be(&dev->iseg->cmdq_addr_l_sz) >> 8) & 3;
+}
+
+static void trigger_cmd_completions(struct mlx5_core_dev *dev)
+{
+ unsigned long flags;
+ u64 vector;
- spin_lock_irq(&health_lock);
- list_splice_init(&health_list, &tlist);
+ /* wait for pending handlers to complete */
+ synchronize_irq(dev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector);
+ spin_lock_irqsave(&dev->cmd.alloc_lock, flags);
+ vector = ~dev->cmd.bitmask & ((1ul << (1 << dev->cmd.log_sz)) - 1);
+ if (!vector)
+ goto no_trig;
+
+ vector |= MLX5_TRIGGERED_CMD_COMP;
+ spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
+
+ mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
+ mlx5_cmd_comp_handler(dev, vector);
+ return;
+
+no_trig:
+ spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
+}
+
+static int in_fatal(struct mlx5_core_dev *dev)
+{
+ struct mlx5_core_health *health = &dev->priv.health;
+ struct health_buffer __iomem *h = health->health;
- spin_unlock_irq(&health_lock);
+ if (get_nic_interface(dev) == MLX5_NIC_IFC_DISABLED)
+ return 1;
- list_for_each_entry_safe(health, n, &tlist, list) {
- priv = container_of(health, struct mlx5_priv, health);
- dev = container_of(priv, struct mlx5_core_dev, priv);
- mlx5_core_warn(dev, "handling bad device here\n");
- /* nothing yet */
- spin_lock_irq(&health_lock);
- list_del_init(&health->list);
- spin_unlock_irq(&health_lock);
+ if (ioread32be(&h->fw_ver) == 0xffffffff)
+ return 1;
+
+ return 0;
+}
+
+void mlx5_enter_error_state(struct mlx5_core_dev *dev)
+{
+ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+ return;
+
+ mlx5_core_err(dev, "start\n");
+ if (pci_channel_offline(dev->pdev) || in_fatal(dev))
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+
+ mlx5_core_event(dev, MLX5_DEV_EVENT_SYS_ERROR, 0);
+ mlx5_core_err(dev, "end\n");
+}
+
+static void mlx5_handle_bad_state(struct mlx5_core_dev *dev)
+{
+ u8 nic_interface = get_nic_interface(dev);
+
+ switch (nic_interface) {
+ case MLX5_NIC_IFC_FULL:
+ mlx5_core_warn(dev, "Expected to see disabled NIC but it is full driver\n");
+ break;
+
+ case MLX5_NIC_IFC_DISABLED:
+ mlx5_core_warn(dev, "starting teardown\n");
+ break;
+
+ case MLX5_NIC_IFC_NO_DRAM_NIC:
+ mlx5_core_warn(dev, "Expected to see disabled NIC but it is no dram nic\n");
+ break;
+ default:
+ mlx5_core_warn(dev, "Expected to see disabled NIC but it is has invalid value %d\n",
+ nic_interface);
}
+
+ mlx5_disable_device(dev);
+}
+
+static void health_care(struct work_struct *work)
+{
+ struct mlx5_core_health *health;
+ struct mlx5_core_dev *dev;
+ struct mlx5_priv *priv;
+
+ health = container_of(work, struct mlx5_core_health, work);
+ priv = container_of(health, struct mlx5_priv, health);
+ dev = container_of(priv, struct mlx5_core_dev, priv);
+ mlx5_core_warn(dev, "handling bad device here\n");
+ mlx5_handle_bad_state(dev);
}
static const char *hsynd_str(u8 synd)
@@ -88,6 +163,8 @@ static const char *hsynd_str(u8 synd)
return "firmware internal error";
case MLX5_HEALTH_SYNDR_IRISC_ERR:
return "irisc not responding";
+ case MLX5_HEALTH_SYNDR_HW_UNRECOVERABLE_ERR:
+ return "unrecoverable hardware error";
case MLX5_HEALTH_SYNDR_CRC_ERR:
return "firmware CRC error";
case MLX5_HEALTH_SYNDR_FETCH_PCI_ERR:
@@ -98,48 +175,81 @@ static const char *hsynd_str(u8 synd)
return "async EQ buffer overrun";
case MLX5_HEALTH_SYNDR_EQ_ERR:
return "EQ error";
+ case MLX5_HEALTH_SYNDR_EQ_INV:
+ return "Invalid EQ refrenced";
case MLX5_HEALTH_SYNDR_FFSER_ERR:
return "FFSER error";
+ case MLX5_HEALTH_SYNDR_HIGH_TEMP:
+ return "High temprature";
default:
return "unrecognized error";
}
}
-static u16 read_be16(__be16 __iomem *p)
+static u16 get_maj(u32 fw)
{
- return swab16(readl((__force u16 __iomem *) p));
+ return fw >> 28;
}
-static u32 read_be32(__be32 __iomem *p)
+static u16 get_min(u32 fw)
{
- return swab32(readl((__force u32 __iomem *) p));
+ return fw >> 16 & 0xfff;
+}
+
+static u16 get_sub(u32 fw)
+{
+ return fw & 0xffff;
}
static void print_health_info(struct mlx5_core_dev *dev)
{
struct mlx5_core_health *health = &dev->priv.health;
struct health_buffer __iomem *h = health->health;
+ char fw_str[18];
+ u32 fw;
int i;
+ /* If the syndrom is 0, the device is OK and no need to print buffer */
+ if (!ioread8(&h->synd))
+ return;
+
for (i = 0; i < ARRAY_SIZE(h->assert_var); i++)
- pr_info("assert_var[%d] 0x%08x\n", i, read_be32(h->assert_var + i));
+ dev_err(&dev->pdev->dev, "assert_var[%d] 0x%08x\n", i, ioread32be(h->assert_var + i));
+
+ dev_err(&dev->pdev->dev, "assert_exit_ptr 0x%08x\n", ioread32be(&h->assert_exit_ptr));
+ dev_err(&dev->pdev->dev, "assert_callra 0x%08x\n", ioread32be(&h->assert_callra));
+ fw = ioread32be(&h->fw_ver);
+ sprintf(fw_str, "%d.%d.%d", get_maj(fw), get_min(fw), get_sub(fw));
+ dev_err(&dev->pdev->dev, "fw_ver %s\n", fw_str);
+ dev_err(&dev->pdev->dev, "hw_id 0x%08x\n", ioread32be(&h->hw_id));
+ dev_err(&dev->pdev->dev, "irisc_index %d\n", ioread8(&h->irisc_index));
+ dev_err(&dev->pdev->dev, "synd 0x%x: %s\n", ioread8(&h->synd), hsynd_str(ioread8(&h->synd)));
+ dev_err(&dev->pdev->dev, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd));
+}
+
+static unsigned long get_next_poll_jiffies(void)
+{
+ unsigned long next;
- pr_info("assert_exit_ptr 0x%08x\n", read_be32(&h->assert_exit_ptr));
- pr_info("assert_callra 0x%08x\n", read_be32(&h->assert_callra));
- pr_info("fw_ver 0x%08x\n", read_be32(&h->fw_ver));
- pr_info("hw_id 0x%08x\n", read_be32(&h->hw_id));
- pr_info("irisc_index %d\n", readb(&h->irisc_index));
- pr_info("synd 0x%x: %s\n", readb(&h->synd), hsynd_str(readb(&h->synd)));
- pr_info("ext_sync 0x%04x\n", read_be16(&h->ext_sync));
+ get_random_bytes(&next, sizeof(next));
+ next %= HZ;
+ next += jiffies + MLX5_HEALTH_POLL_INTERVAL;
+
+ return next;
}
static void poll_health(unsigned long data)
{
struct mlx5_core_dev *dev = (struct mlx5_core_dev *)data;
struct mlx5_core_health *health = &dev->priv.health;
- unsigned long next;
u32 count;
+ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ trigger_cmd_completions(dev);
+ mod_timer(&health->timer, get_next_poll_jiffies());
+ return;
+ }
+
count = ioread32be(health->health_counter);
if (count == health->prev)
++health->miss_counter;
@@ -148,18 +258,16 @@ static void poll_health(unsigned long data)
health->prev = count;
if (health->miss_counter == MAX_MISSES) {
- mlx5_core_err(dev, "device's health compromised\n");
+ dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n");
print_health_info(dev);
- spin_lock_irq(&health_lock);
- list_add_tail(&health->list, &health_list);
- spin_unlock_irq(&health_lock);
-
- queue_work(mlx5_core_wq, &health_work);
} else {
- get_random_bytes(&next, sizeof(next));
- next %= HZ;
- next += jiffies + MLX5_HEALTH_POLL_INTERVAL;
- mod_timer(&health->timer, next);
+ mod_timer(&health->timer, get_next_poll_jiffies());
+ }
+
+ if (in_fatal(dev) && !health->sick) {
+ health->sick = true;
+ print_health_info(dev);
+ queue_work(health->wq, &health->work);
}
}
@@ -167,7 +275,6 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev)
{
struct mlx5_core_health *health = &dev->priv.health;
- INIT_LIST_HEAD(&health->list);
init_timer(&health->timer);
health->health = &dev->iseg->health;
health->health_counter = &dev->iseg->health_counter;
@@ -183,18 +290,33 @@ void mlx5_stop_health_poll(struct mlx5_core_dev *dev)
struct mlx5_core_health *health = &dev->priv.health;
del_timer_sync(&health->timer);
-
- spin_lock_irq(&health_lock);
- if (!list_empty(&health->list))
- list_del_init(&health->list);
- spin_unlock_irq(&health_lock);
}
-void mlx5_health_cleanup(void)
+void mlx5_health_cleanup(struct mlx5_core_dev *dev)
{
+ struct mlx5_core_health *health = &dev->priv.health;
+
+ destroy_workqueue(health->wq);
}
-void __init mlx5_health_init(void)
+int mlx5_health_init(struct mlx5_core_dev *dev)
{
- INIT_WORK(&health_work, health_care);
+ struct mlx5_core_health *health;
+ char *name;
+
+ health = &dev->priv.health;
+ name = kmalloc(64, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ strcpy(name, "mlx5_health");
+ strcat(name, dev_name(&dev->pdev->dev));
+ health->wq = create_singlethread_workqueue(name);
+ kfree(name);
+ if (!health->wq)
+ return -ENOMEM;
+
+ INIT_WORK(&health->work, health_care);
+
+ return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 03aabdd79abe..4ac8d4cc4973 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -30,7 +30,7 @@
* SOFTWARE.
*/
-#include <asm-generic/kmap_types.h>
+#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -39,12 +39,14 @@
#include <linux/slab.h>
#include <linux/io-mapping.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/cq.h>
#include <linux/mlx5/qp.h>
#include <linux/mlx5/srq.h>
#include <linux/debugfs.h>
#include <linux/kmod.h>
+#include <linux/delay.h>
#include <linux/mlx5/mlx5_ifc.h>
#include "mlx5_core.h"
@@ -62,7 +64,6 @@ static int prof_sel = MLX5_DEFAULT_PROF;
module_param_named(prof_sel, prof_sel, int, 0444);
MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
-struct workqueue_struct *mlx5_core_wq;
static LIST_HEAD(intf_list);
static LIST_HEAD(dev_list);
static DEFINE_MUTEX(intf_mutex);
@@ -152,6 +153,25 @@ static struct mlx5_profile profile[] = {
},
};
+#define FW_INIT_TIMEOUT_MILI 2000
+#define FW_INIT_WAIT_MS 2
+
+static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
+{
+ unsigned long end = jiffies + msecs_to_jiffies(max_wait_mili);
+ int err = 0;
+
+ while (fw_initializing(dev)) {
+ if (time_after(jiffies, end)) {
+ err = -EBUSY;
+ break;
+ }
+ msleep(FW_INIT_WAIT_MS);
+ }
+
+ return err;
+}
+
static int set_dma_caps(struct pci_dev *pdev)
{
int err;
@@ -182,6 +202,34 @@ static int set_dma_caps(struct pci_dev *pdev)
return err;
}
+static int mlx5_pci_enable_device(struct mlx5_core_dev *dev)
+{
+ struct pci_dev *pdev = dev->pdev;
+ int err = 0;
+
+ mutex_lock(&dev->pci_status_mutex);
+ if (dev->pci_status == MLX5_PCI_STATUS_DISABLED) {
+ err = pci_enable_device(pdev);
+ if (!err)
+ dev->pci_status = MLX5_PCI_STATUS_ENABLED;
+ }
+ mutex_unlock(&dev->pci_status_mutex);
+
+ return err;
+}
+
+static void mlx5_pci_disable_device(struct mlx5_core_dev *dev)
+{
+ struct pci_dev *pdev = dev->pdev;
+
+ mutex_lock(&dev->pci_status_mutex);
+ if (dev->pci_status == MLX5_PCI_STATUS_ENABLED) {
+ pci_disable_device(pdev);
+ dev->pci_status = MLX5_PCI_STATUS_DISABLED;
+ }
+ mutex_unlock(&dev->pci_status_mutex);
+}
+
static int request_bar(struct pci_dev *pdev)
{
int err = 0;
@@ -672,12 +720,126 @@ static void unmap_bf_area(struct mlx5_core_dev *dev)
io_mapping_free(dev->priv.bf_mapping);
}
-static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
+static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+ struct mlx5_device_context *dev_ctx;
+ struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
+
+ dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
+ if (!dev_ctx)
+ return;
+
+ dev_ctx->intf = intf;
+ dev_ctx->context = intf->add(dev);
+
+ if (dev_ctx->context) {
+ spin_lock_irq(&priv->ctx_lock);
+ list_add_tail(&dev_ctx->list, &priv->ctx_list);
+ spin_unlock_irq(&priv->ctx_lock);
+ } else {
+ kfree(dev_ctx);
+ }
+}
+
+static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+ struct mlx5_device_context *dev_ctx;
+ struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
+
+ list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+ if (dev_ctx->intf == intf) {
+ spin_lock_irq(&priv->ctx_lock);
+ list_del(&dev_ctx->list);
+ spin_unlock_irq(&priv->ctx_lock);
+
+ intf->remove(dev, dev_ctx->context);
+ kfree(dev_ctx);
+ return;
+ }
+}
+
+static int mlx5_register_device(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
- int err;
+ struct mlx5_interface *intf;
+
+ mutex_lock(&intf_mutex);
+ list_add_tail(&priv->dev_list, &dev_list);
+ list_for_each_entry(intf, &intf_list, list)
+ mlx5_add_device(intf, priv);
+ mutex_unlock(&intf_mutex);
+
+ return 0;
+}
+
+static void mlx5_unregister_device(struct mlx5_core_dev *dev)
+{
+ struct mlx5_priv *priv = &dev->priv;
+ struct mlx5_interface *intf;
+
+ mutex_lock(&intf_mutex);
+ list_for_each_entry(intf, &intf_list, list)
+ mlx5_remove_device(intf, priv);
+ list_del(&priv->dev_list);
+ mutex_unlock(&intf_mutex);
+}
+
+int mlx5_register_interface(struct mlx5_interface *intf)
+{
+ struct mlx5_priv *priv;
+
+ if (!intf->add || !intf->remove)
+ return -EINVAL;
+
+ mutex_lock(&intf_mutex);
+ list_add_tail(&intf->list, &intf_list);
+ list_for_each_entry(priv, &dev_list, dev_list)
+ mlx5_add_device(intf, priv);
+ mutex_unlock(&intf_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(mlx5_register_interface);
+
+void mlx5_unregister_interface(struct mlx5_interface *intf)
+{
+ struct mlx5_priv *priv;
+
+ mutex_lock(&intf_mutex);
+ list_for_each_entry(priv, &dev_list, dev_list)
+ mlx5_remove_device(intf, priv);
+ list_del(&intf->list);
+ mutex_unlock(&intf_mutex);
+}
+EXPORT_SYMBOL(mlx5_unregister_interface);
+
+void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol)
+{
+ struct mlx5_priv *priv = &mdev->priv;
+ struct mlx5_device_context *dev_ctx;
+ unsigned long flags;
+ void *result = NULL;
+
+ spin_lock_irqsave(&priv->ctx_lock, flags);
+
+ list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list)
+ if ((dev_ctx->intf->protocol == protocol) &&
+ dev_ctx->intf->get_dev) {
+ result = dev_ctx->intf->get_dev(dev_ctx->context);
+ break;
+ }
+
+ spin_unlock_irqrestore(&priv->ctx_lock, flags);
+
+ return result;
+}
+EXPORT_SYMBOL(mlx5_get_protocol_dev);
+
+static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
+{
+ struct pci_dev *pdev = dev->pdev;
+ int err = 0;
- dev->pdev = pdev;
pci_set_drvdata(dev->pdev, dev);
strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN);
priv->name[MLX5_MAX_NAME_LEN - 1] = 0;
@@ -694,7 +856,7 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
if (!priv->dbg_root)
return -ENOMEM;
- err = pci_enable_device(pdev);
+ err = mlx5_pci_enable_device(dev);
if (err) {
dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
goto err_dbg;
@@ -721,13 +883,61 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
dev_err(&pdev->dev, "Failed mapping initialization segment, aborting\n");
goto err_clr_master;
}
+
+ return 0;
+
+err_clr_master:
+ pci_clear_master(dev->pdev);
+ release_bar(dev->pdev);
+err_disable:
+ mlx5_pci_disable_device(dev);
+
+err_dbg:
+ debugfs_remove(priv->dbg_root);
+ return err;
+}
+
+static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
+{
+ iounmap(dev->iseg);
+ pci_clear_master(dev->pdev);
+ release_bar(dev->pdev);
+ mlx5_pci_disable_device(dev);
+ debugfs_remove(priv->dbg_root);
+}
+
+#define MLX5_IB_MOD "mlx5_ib"
+static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
+{
+ struct pci_dev *pdev = dev->pdev;
+ int err;
+
+ mutex_lock(&dev->intf_state_mutex);
+ if (dev->interface_state == MLX5_INTERFACE_STATE_UP) {
+ dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n",
+ __func__);
+ goto out;
+ }
+
dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev),
fw_rev_min(dev), fw_rev_sub(dev));
+ /* on load removing any previous indication of internal error, device is
+ * up
+ */
+ dev->state = MLX5_DEVICE_STATE_UP;
+
err = mlx5_cmd_init(dev);
if (err) {
dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
- goto err_unmap;
+ goto out_err;
+ }
+
+ err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI);
+ if (err) {
+ dev_err(&dev->pdev->dev, "Firmware over %d MS in initializing state, aborting\n",
+ FW_INIT_TIMEOUT_MILI);
+ goto out_err;
}
mlx5_pagealloc_init(dev);
@@ -842,8 +1052,29 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
mlx5_init_srq_table(dev);
mlx5_init_mr_table(dev);
+ err = mlx5_register_device(dev);
+ if (err) {
+ dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
+ goto err_reg_dev;
+ }
+
+ err = request_module_nowait(MLX5_IB_MOD);
+ if (err)
+ pr_info("failed request module on %s\n", MLX5_IB_MOD);
+
+ dev->interface_state = MLX5_INTERFACE_STATE_UP;
+out:
+ mutex_unlock(&dev->intf_state_mutex);
+
return 0;
+err_reg_dev:
+ mlx5_cleanup_mr_table(dev);
+ mlx5_cleanup_srq_table(dev);
+ mlx5_cleanup_qp_table(dev);
+ mlx5_cleanup_cq_table(dev);
+ mlx5_irq_clear_affinity_hints(dev);
+
err_unmap_bf_area:
unmap_bf_area(dev);
@@ -865,7 +1096,7 @@ err_stop_poll:
mlx5_stop_health_poll(dev);
if (mlx5_cmd_teardown_hca(dev)) {
dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n");
- return err;
+ goto out_err;
}
err_pagealloc_stop:
@@ -881,25 +1112,25 @@ err_pagealloc_cleanup:
mlx5_pagealloc_cleanup(dev);
mlx5_cmd_cleanup(dev);
-err_unmap:
- iounmap(dev->iseg);
-
-err_clr_master:
- pci_clear_master(dev->pdev);
- release_bar(dev->pdev);
-
-err_disable:
- pci_disable_device(dev->pdev);
+out_err:
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+ mutex_unlock(&dev->intf_state_mutex);
-err_dbg:
- debugfs_remove(priv->dbg_root);
return err;
}
-static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
+static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
{
- struct mlx5_priv *priv = &dev->priv;
+ int err = 0;
+ mutex_lock(&dev->intf_state_mutex);
+ if (dev->interface_state == MLX5_INTERFACE_STATE_DOWN) {
+ dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
+ __func__);
+ goto out;
+ }
+ mlx5_unregister_device(dev);
+ mlx5_cleanup_mr_table(dev);
mlx5_cleanup_srq_table(dev);
mlx5_cleanup_qp_table(dev);
mlx5_cleanup_cq_table(dev);
@@ -911,139 +1142,25 @@ static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
mlx5_eq_cleanup(dev);
mlx5_disable_msix(dev);
mlx5_stop_health_poll(dev);
- if (mlx5_cmd_teardown_hca(dev)) {
+ err = mlx5_cmd_teardown_hca(dev);
+ if (err) {
dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n");
- return;
+ goto out;
}
mlx5_pagealloc_stop(dev);
mlx5_reclaim_startup_pages(dev);
mlx5_core_disable_hca(dev);
mlx5_pagealloc_cleanup(dev);
mlx5_cmd_cleanup(dev);
- iounmap(dev->iseg);
- pci_clear_master(dev->pdev);
- release_bar(dev->pdev);
- pci_disable_device(dev->pdev);
- debugfs_remove(priv->dbg_root);
-}
-
-static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
-{
- struct mlx5_device_context *dev_ctx;
- struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
-
- dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
- if (!dev_ctx) {
- pr_warn("mlx5_add_device: alloc context failed\n");
- return;
- }
-
- dev_ctx->intf = intf;
- dev_ctx->context = intf->add(dev);
-
- if (dev_ctx->context) {
- spin_lock_irq(&priv->ctx_lock);
- list_add_tail(&dev_ctx->list, &priv->ctx_list);
- spin_unlock_irq(&priv->ctx_lock);
- } else {
- kfree(dev_ctx);
- }
-}
-
-static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
-{
- struct mlx5_device_context *dev_ctx;
- struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
-
- list_for_each_entry(dev_ctx, &priv->ctx_list, list)
- if (dev_ctx->intf == intf) {
- spin_lock_irq(&priv->ctx_lock);
- list_del(&dev_ctx->list);
- spin_unlock_irq(&priv->ctx_lock);
-
- intf->remove(dev, dev_ctx->context);
- kfree(dev_ctx);
- return;
- }
-}
-static int mlx5_register_device(struct mlx5_core_dev *dev)
-{
- struct mlx5_priv *priv = &dev->priv;
- struct mlx5_interface *intf;
-
- mutex_lock(&intf_mutex);
- list_add_tail(&priv->dev_list, &dev_list);
- list_for_each_entry(intf, &intf_list, list)
- mlx5_add_device(intf, priv);
- mutex_unlock(&intf_mutex);
-
- return 0;
-}
-static void mlx5_unregister_device(struct mlx5_core_dev *dev)
-{
- struct mlx5_priv *priv = &dev->priv;
- struct mlx5_interface *intf;
-
- mutex_lock(&intf_mutex);
- list_for_each_entry(intf, &intf_list, list)
- mlx5_remove_device(intf, priv);
- list_del(&priv->dev_list);
- mutex_unlock(&intf_mutex);
-}
-
-int mlx5_register_interface(struct mlx5_interface *intf)
-{
- struct mlx5_priv *priv;
-
- if (!intf->add || !intf->remove)
- return -EINVAL;
-
- mutex_lock(&intf_mutex);
- list_add_tail(&intf->list, &intf_list);
- list_for_each_entry(priv, &dev_list, dev_list)
- mlx5_add_device(intf, priv);
- mutex_unlock(&intf_mutex);
-
- return 0;
-}
-EXPORT_SYMBOL(mlx5_register_interface);
-
-void mlx5_unregister_interface(struct mlx5_interface *intf)
-{
- struct mlx5_priv *priv;
-
- mutex_lock(&intf_mutex);
- list_for_each_entry(priv, &dev_list, dev_list)
- mlx5_remove_device(intf, priv);
- list_del(&intf->list);
- mutex_unlock(&intf_mutex);
-}
-EXPORT_SYMBOL(mlx5_unregister_interface);
-
-void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol)
-{
- struct mlx5_priv *priv = &mdev->priv;
- struct mlx5_device_context *dev_ctx;
- unsigned long flags;
- void *result = NULL;
-
- spin_lock_irqsave(&priv->ctx_lock, flags);
-
- list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list)
- if ((dev_ctx->intf->protocol == protocol) &&
- dev_ctx->intf->get_dev) {
- result = dev_ctx->intf->get_dev(dev_ctx->context);
- break;
- }
- spin_unlock_irqrestore(&priv->ctx_lock, flags);
-
- return result;
+out:
+ dev->interface_state = MLX5_INTERFACE_STATE_DOWN;
+ mutex_unlock(&dev->intf_state_mutex);
+ return err;
}
-EXPORT_SYMBOL(mlx5_get_protocol_dev);
-static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
- unsigned long param)
+void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
+ unsigned long param)
{
struct mlx5_priv *priv = &dev->priv;
struct mlx5_device_context *dev_ctx;
@@ -1064,7 +1181,6 @@ struct mlx5_core_event_handler {
void *data);
};
-#define MLX5_IB_MOD "mlx5_ib"
static int init_one(struct pci_dev *pdev,
const struct pci_device_id *id)
@@ -1088,43 +1204,166 @@ static int init_one(struct pci_dev *pdev,
prof_sel = MLX5_DEFAULT_PROF;
}
dev->profile = &profile[prof_sel];
+ dev->pdev = pdev;
dev->event = mlx5_core_event;
INIT_LIST_HEAD(&priv->ctx_list);
spin_lock_init(&priv->ctx_lock);
- err = mlx5_dev_init(dev, pdev);
+ mutex_init(&dev->pci_status_mutex);
+ mutex_init(&dev->intf_state_mutex);
+ err = mlx5_pci_init(dev, priv);
if (err) {
- dev_err(&pdev->dev, "mlx5_dev_init failed %d\n", err);
- goto out;
+ dev_err(&pdev->dev, "mlx5_pci_init failed with error code %d\n", err);
+ goto clean_dev;
}
- err = mlx5_register_device(dev);
+ err = mlx5_health_init(dev);
if (err) {
- dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
- goto out_init;
+ dev_err(&pdev->dev, "mlx5_health_init failed with error code %d\n", err);
+ goto close_pci;
}
- err = request_module_nowait(MLX5_IB_MOD);
- if (err)
- pr_info("failed request module on %s\n", MLX5_IB_MOD);
+ err = mlx5_load_one(dev, priv);
+ if (err) {
+ dev_err(&pdev->dev, "mlx5_load_one failed with error code %d\n", err);
+ goto clean_health;
+ }
return 0;
-out_init:
- mlx5_dev_cleanup(dev);
-out:
+clean_health:
+ mlx5_health_cleanup(dev);
+close_pci:
+ mlx5_pci_close(dev, priv);
+clean_dev:
+ pci_set_drvdata(pdev, NULL);
kfree(dev);
+
return err;
}
+
static void remove_one(struct pci_dev *pdev)
{
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+ struct mlx5_priv *priv = &dev->priv;
- mlx5_unregister_device(dev);
- mlx5_dev_cleanup(dev);
+ if (mlx5_unload_one(dev, priv)) {
+ dev_err(&dev->pdev->dev, "mlx5_unload_one failed\n");
+ mlx5_health_cleanup(dev);
+ return;
+ }
+ mlx5_health_cleanup(dev);
+ mlx5_pci_close(dev, priv);
+ pci_set_drvdata(pdev, NULL);
kfree(dev);
}
+static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+ struct mlx5_priv *priv = &dev->priv;
+
+ dev_info(&pdev->dev, "%s was called\n", __func__);
+ mlx5_enter_error_state(dev);
+ mlx5_unload_one(dev, priv);
+ mlx5_pci_disable_device(dev);
+ return state == pci_channel_io_perm_failure ?
+ PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
+{
+ struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+ int err = 0;
+
+ dev_info(&pdev->dev, "%s was called\n", __func__);
+
+ err = mlx5_pci_enable_device(dev);
+ if (err) {
+ dev_err(&pdev->dev, "%s: mlx5_pci_enable_device failed with error code: %d\n"
+ , __func__, err);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
+}
+
+void mlx5_disable_device(struct mlx5_core_dev *dev)
+{
+ mlx5_pci_err_detected(dev->pdev, 0);
+}
+
+/* wait for the device to show vital signs. For now we check
+ * that we can read the device ID and that the health buffer
+ * shows a non zero value which is different than 0xffffffff
+ */
+static void wait_vital(struct pci_dev *pdev)
+{
+ struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+ struct mlx5_core_health *health = &dev->priv.health;
+ const int niter = 100;
+ u32 count;
+ u16 did;
+ int i;
+
+ /* Wait for firmware to be ready after reset */
+ msleep(1000);
+ for (i = 0; i < niter; i++) {
+ if (pci_read_config_word(pdev, 2, &did)) {
+ dev_warn(&pdev->dev, "failed reading config word\n");
+ break;
+ }
+ if (did == pdev->device) {
+ dev_info(&pdev->dev, "device ID correctly read after %d iterations\n", i);
+ break;
+ }
+ msleep(50);
+ }
+ if (i == niter)
+ dev_warn(&pdev->dev, "%s-%d: could not read device ID\n", __func__, __LINE__);
+
+ for (i = 0; i < niter; i++) {
+ count = ioread32be(health->health_counter);
+ if (count && count != 0xffffffff) {
+ dev_info(&pdev->dev, "Counter value 0x%x after %d iterations\n", count, i);
+ break;
+ }
+ msleep(50);
+ }
+
+ if (i == niter)
+ dev_warn(&pdev->dev, "%s-%d: could not read device ID\n", __func__, __LINE__);
+}
+
+static void mlx5_pci_resume(struct pci_dev *pdev)
+{
+ struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+ struct mlx5_priv *priv = &dev->priv;
+ int err;
+
+ dev_info(&pdev->dev, "%s was called\n", __func__);
+
+ pci_save_state(pdev);
+ wait_vital(pdev);
+
+ err = mlx5_load_one(dev, priv);
+ if (err)
+ dev_err(&pdev->dev, "%s: mlx5_load_one failed with error code: %d\n"
+ , __func__, err);
+ else
+ dev_info(&pdev->dev, "%s: device recovered\n", __func__);
+}
+
+static const struct pci_error_handlers mlx5_err_handler = {
+ .error_detected = mlx5_pci_err_detected,
+ .slot_reset = mlx5_pci_slot_reset,
+ .resume = mlx5_pci_resume
+};
+
static const struct pci_device_id mlx5_core_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */
{ PCI_VDEVICE(MELLANOX, 0x1012) }, /* Connect-IB VF */
@@ -1141,7 +1380,8 @@ static struct pci_driver mlx5_core_driver = {
.name = DRIVER_NAME,
.id_table = mlx5_core_pci_table,
.probe = init_one,
- .remove = remove_one
+ .remove = remove_one,
+ .err_handler = &mlx5_err_handler
};
static int __init init(void)
@@ -1149,16 +1389,10 @@ static int __init init(void)
int err;
mlx5_register_debugfs();
- mlx5_core_wq = create_singlethread_workqueue("mlx5_core_wq");
- if (!mlx5_core_wq) {
- err = -ENOMEM;
- goto err_debug;
- }
- mlx5_health_init();
err = pci_register_driver(&mlx5_core_driver);
if (err)
- goto err_health;
+ goto err_debug;
#ifdef CONFIG_MLX5_CORE_EN
mlx5e_init();
@@ -1166,9 +1400,6 @@ static int __init init(void)
return 0;
-err_health:
- mlx5_health_cleanup();
- destroy_workqueue(mlx5_core_wq);
err_debug:
mlx5_unregister_debugfs();
return err;
@@ -1180,8 +1411,6 @@ static void __exit cleanup(void)
mlx5e_cleanup();
#endif
pci_unregister_driver(&mlx5_core_driver);
- mlx5_health_cleanup();
- destroy_workqueue(mlx5_core_wq);
mlx5_unregister_debugfs();
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 566a70488db1..cee5b7a839bc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -43,25 +43,25 @@
extern int mlx5_core_debug_mask;
-#define mlx5_core_dbg(dev, format, ...) \
- pr_debug("%s:%s:%d:(pid %d): " format, \
- (dev)->priv.name, __func__, __LINE__, current->pid, \
+#define mlx5_core_dbg(__dev, format, ...) \
+ dev_dbg(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format, \
+ (__dev)->priv.name, __func__, __LINE__, current->pid, \
##__VA_ARGS__)
-#define mlx5_core_dbg_mask(dev, mask, format, ...) \
+#define mlx5_core_dbg_mask(__dev, mask, format, ...) \
do { \
if ((mask) & mlx5_core_debug_mask) \
- mlx5_core_dbg(dev, format, ##__VA_ARGS__); \
+ mlx5_core_dbg(__dev, format, ##__VA_ARGS__); \
} while (0)
-#define mlx5_core_err(dev, format, ...) \
- pr_err("%s:%s:%d:(pid %d): " format, \
- (dev)->priv.name, __func__, __LINE__, current->pid, \
+#define mlx5_core_err(__dev, format, ...) \
+ dev_err(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format, \
+ (__dev)->priv.name, __func__, __LINE__, current->pid, \
##__VA_ARGS__)
-#define mlx5_core_warn(dev, format, ...) \
- pr_warn("%s:%s:%d:(pid %d): " format, \
- (dev)->priv.name, __func__, __LINE__, current->pid, \
+#define mlx5_core_warn(__dev, format, ...) \
+ dev_warn(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format, \
+ (__dev)->priv.name, __func__, __LINE__, current->pid, \
##__VA_ARGS__)
enum {
@@ -86,6 +86,10 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev);
int mlx5_query_board_id(struct mlx5_core_dev *dev);
int mlx5_cmd_init_hca(struct mlx5_core_dev *dev);
int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev);
+void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
+ unsigned long param);
+void mlx5_enter_error_state(struct mlx5_core_dev *dev);
+void mlx5_disable_device(struct mlx5_core_dev *dev);
void mlx5e_init(void);
void mlx5e_cleanup(void);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c
index 1adb300dd850..6fa22b51e460 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c
@@ -40,6 +40,7 @@ void mlx5_init_mr_table(struct mlx5_core_dev *dev)
{
struct mlx5_mr_table *table = &dev->priv.mr_table;
+ memset(table, 0, sizeof(*table));
rwlock_init(&table->lock);
INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index 8a64542abc16..4d3377b12657 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -30,7 +30,7 @@
* SOFTWARE.
*/
-#include <asm-generic/kmap_types.h>
+#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
@@ -275,12 +275,36 @@ out_alloc:
return err;
}
+
+static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id)
+{
+ struct mlx5_manage_pages_inbox *in;
+ struct mlx5_manage_pages_outbox out;
+ int err;
+
+ in = kzalloc(sizeof(*in), GFP_KERNEL);
+ if (!in)
+ return;
+
+ memset(&out, 0, sizeof(out));
+ in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
+ in->hdr.opmod = cpu_to_be16(MLX5_PAGES_CANT_GIVE);
+ in->func_id = cpu_to_be16(func_id);
+ err = mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out));
+ if (!err)
+ err = mlx5_cmd_status_to_err(&out.hdr);
+
+ if (err)
+ mlx5_core_warn(dev, "page notify failed\n");
+
+ kfree(in);
+}
+
static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
int notify_fail)
{
struct mlx5_manage_pages_inbox *in;
struct mlx5_manage_pages_outbox out;
- struct mlx5_manage_pages_inbox *nin;
int inlen;
u64 addr;
int err;
@@ -289,8 +313,9 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
inlen = sizeof(*in) + npages * sizeof(in->pas[0]);
in = mlx5_vzalloc(inlen);
if (!in) {
+ err = -ENOMEM;
mlx5_core_warn(dev, "vzalloc failed %d\n", inlen);
- return -ENOMEM;
+ goto out_free;
}
memset(&out, 0, sizeof(out));
@@ -316,43 +341,29 @@ retry:
if (err) {
mlx5_core_warn(dev, "func_id 0x%x, npages %d, err %d\n",
func_id, npages, err);
- goto out_alloc;
+ goto out_4k;
}
dev->priv.fw_pages += npages;
- if (out.hdr.status) {
- err = mlx5_cmd_status_to_err(&out.hdr);
- if (err) {
- mlx5_core_warn(dev, "func_id 0x%x, npages %d, status %d\n",
- func_id, npages, out.hdr.status);
- goto out_alloc;
- }
+ err = mlx5_cmd_status_to_err(&out.hdr);
+ if (err) {
+ mlx5_core_warn(dev, "func_id 0x%x, npages %d, status %d\n",
+ func_id, npages, out.hdr.status);
+ goto out_4k;
}
mlx5_core_dbg(dev, "err %d\n", err);
- goto out_free;
-
-out_alloc:
- if (notify_fail) {
- nin = kzalloc(sizeof(*nin), GFP_KERNEL);
- if (!nin) {
- mlx5_core_warn(dev, "allocation failed\n");
- goto out_4k;
- }
- memset(&out, 0, sizeof(out));
- nin->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
- nin->hdr.opmod = cpu_to_be16(MLX5_PAGES_CANT_GIVE);
- if (mlx5_cmd_exec(dev, nin, sizeof(*nin), &out, sizeof(out)))
- mlx5_core_warn(dev, "page notify failed\n");
- kfree(nin);
- }
+ kvfree(in);
+ return 0;
out_4k:
for (i--; i >= 0; i--)
free_4k(dev, be64_to_cpu(in->pas[i]));
out_free:
kvfree(in);
+ if (notify_fail)
+ page_notify_fail(dev, func_id);
return err;
}
@@ -482,15 +493,20 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
struct fw_page *fwp;
struct rb_node *p;
int nclaimed = 0;
- int err;
+ int err = 0;
do {
p = rb_first(&dev->priv.page_root);
if (p) {
fwp = rb_entry(p, struct fw_page, rb_node);
- err = reclaim_pages(dev, fwp->func_id,
- optimal_reclaimed_pages(),
- &nclaimed);
+ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ free_4k(dev, fwp->addr);
+ nclaimed = 1;
+ } else {
+ err = reclaim_pages(dev, fwp->func_id,
+ optimal_reclaimed_pages(),
+ &nclaimed);
+ }
if (err) {
mlx5_core_warn(dev, "failed reclaiming pages (%d)\n",
err);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 821caaab9bfb..a87e773e93f3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -90,16 +90,13 @@ int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
{
struct mlx5_reg_pcap in;
struct mlx5_reg_pcap out;
- int err;
memset(&in, 0, sizeof(in));
in.caps_127_96 = cpu_to_be32(caps);
in.port_num = port_num;
- err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
- sizeof(out), MLX5_REG_PCAP, 0, 1);
-
- return err;
+ return mlx5_core_access_reg(dev, &in, sizeof(in), &out,
+ sizeof(out), MLX5_REG_PCAP, 0, 1);
}
EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
@@ -107,16 +104,13 @@ int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
int ptys_size, int proto_mask, u8 local_port)
{
u32 in[MLX5_ST_SZ_DW(ptys_reg)];
- int err;
memset(in, 0, sizeof(in));
MLX5_SET(ptys_reg, in, local_port, local_port);
MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
- err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
- ptys_size, MLX5_REG_PTYS, 0, 0);
-
- return err;
+ return mlx5_core_access_reg(dev, in, sizeof(in), ptys,
+ ptys_size, MLX5_REG_PTYS, 0, 0);
}
EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
@@ -199,7 +193,6 @@ int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
{
u32 in[MLX5_ST_SZ_DW(ptys_reg)];
u32 out[MLX5_ST_SZ_DW(ptys_reg)];
- int err;
memset(in, 0, sizeof(in));
@@ -210,9 +203,8 @@ int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
else
MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
- err = mlx5_core_access_reg(dev, in, sizeof(in), out,
- sizeof(out), MLX5_REG_PTYS, 0, 1);
- return err;
+ return mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PTYS, 0, 1);
}
EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
@@ -250,7 +242,7 @@ int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
return err;
*status = MLX5_GET(paos_reg, out, admin_status);
- return err;
+ return 0;
}
EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
@@ -308,15 +300,12 @@ static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc,
int pvlc_size, u8 local_port)
{
u32 in[MLX5_ST_SZ_DW(pvlc_reg)];
- int err;
memset(in, 0, sizeof(in));
- MLX5_SET(ptys_reg, in, local_port, local_port);
-
- err = mlx5_core_access_reg(dev, in, sizeof(in), pvlc,
- pvlc_size, MLX5_REG_PVLC, 0, 0);
+ MLX5_SET(pvlc_reg, in, local_port, local_port);
- return err;
+ return mlx5_core_access_reg(dev, in, sizeof(in), pvlc,
+ pvlc_size, MLX5_REG_PVLC, 0, 0);
}
int mlx5_query_port_vl_hw_cap(struct mlx5_core_dev *dev,
@@ -339,16 +328,14 @@ int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 rx_pause, u32 tx_pause)
{
u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
- int err;
memset(in, 0, sizeof(in));
MLX5_SET(pfcc_reg, in, local_port, 1);
MLX5_SET(pfcc_reg, in, pptx, tx_pause);
MLX5_SET(pfcc_reg, in, pprx, rx_pause);
- err = mlx5_core_access_reg(dev, in, sizeof(in), out,
- sizeof(out), MLX5_REG_PFCC, 0, 1);
- return err;
+ return mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PFCC, 0, 1);
}
EXPORT_SYMBOL_GPL(mlx5_set_port_pause);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
index 8b494b562263..30e2ba3f5f16 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
@@ -345,6 +345,7 @@ void mlx5_init_qp_table(struct mlx5_core_dev *dev)
{
struct mlx5_qp_table *table = &dev->priv.qp_table;
+ memset(table, 0, sizeof(*table));
spin_lock_init(&table->lock);
INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
mlx5_qp_debugfs_init(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/srq.c b/drivers/net/ethernet/mellanox/mlx5/core/srq.c
index c48f504ccbeb..ffada801976b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/srq.c
@@ -531,6 +531,7 @@ void mlx5_init_srq_table(struct mlx5_core_dev *dev)
{
struct mlx5_srq_table *table = &dev->priv.srq_table;
+ memset(table, 0, sizeof(*table));
spin_lock_init(&table->lock);
INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
index b4c87c7b0cf0..d7068f54e800 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
@@ -177,7 +177,7 @@ int mlx5_core_modify_tir(struct mlx5_core_dev *dev, u32 tirn, u32 *in,
void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn)
{
- u32 in[MLX5_ST_SZ_DW(destroy_tir_out)];
+ u32 in[MLX5_ST_SZ_DW(destroy_tir_in)];
u32 out[MLX5_ST_SZ_DW(destroy_tir_out)];
memset(in, 0, sizeof(in));
@@ -206,7 +206,7 @@ int mlx5_core_create_tis(struct mlx5_core_dev *dev, u32 *in, int inlen,
void mlx5_core_destroy_tis(struct mlx5_core_dev *dev, u32 tisn)
{
- u32 in[MLX5_ST_SZ_DW(destroy_tis_out)];
+ u32 in[MLX5_ST_SZ_DW(destroy_tis_in)];
u32 out[MLX5_ST_SZ_DW(destroy_tis_out)];
memset(in, 0, sizeof(in));
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
index 2941d9c5ae48..e36e12219c9b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
@@ -30,3 +30,14 @@ config MLXSW_SWITCHX2
To compile this driver as a module, choose M here: the
module will be called mlxsw_switchx2.
+
+config MLXSW_SPECTRUM
+ tristate "Mellanox Technologies Spectrum support"
+ depends on MLXSW_CORE && NET_SWITCHDEV
+ default m
+ ---help---
+ This driver supports Mellanox Technologies Spectrum Ethernet
+ Switch ASICs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mlxsw_spectrum.
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile
index 0a05f65ee814..af015818fd19 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile
@@ -4,3 +4,6 @@ obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o
mlxsw_pci-objs := pci.o
obj-$(CONFIG_MLXSW_SWITCHX2) += mlxsw_switchx2.o
mlxsw_switchx2-objs := switchx2.o
+obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o
+mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
+ spectrum_switchdev.o
diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h
index 770db17eb03f..cd63b8263688 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h
@@ -464,6 +464,8 @@ MLXSW_ITEM32(cmd_mbox, query_aq_cap, max_sg_rq, 0x10, 0, 8);
* passed in this command must be pinned.
*/
+#define MLXSW_CMD_MAP_FA_VPM_ENTRIES_MAX 32
+
static inline int mlxsw_cmd_map_fa(struct mlxsw_core *mlxsw_core,
char *in_mbox, u32 vpm_entries_count)
{
@@ -568,7 +570,7 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_max_vlan_groups, 0x0C, 6, 1);
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_max_regions, 0x0C, 7, 1);
-/* cmd_mbox_config_profile_set_fid_based
+/* cmd_mbox_config_profile_set_flood_mode
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
@@ -649,12 +651,8 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vlan_groups, 0x28, 0, 12);
MLXSW_ITEM32(cmd_mbox, config_profile, max_regions, 0x2C, 0, 16);
/* cmd_mbox_config_profile_max_flood_tables
- * Maximum number of Flooding Tables. Flooding Tables are associated to
- * the different packet types for the different switch partitions.
- * Note that the table size depends on the fid_based mode.
- * In SwitchX silicon, tables are split equally between the switch
- * partitions. e.g. for 2 swids and 8 tables, the first 4 are associated
- * with swid-1 and the last 4 are associated with swid-2.
+ * Maximum number of single-entry flooding tables. Different flooding tables
+ * can be associated with different packet types.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, max_flood_tables, 0x30, 16, 4);
@@ -665,15 +663,42 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_flood_tables, 0x30, 16, 4);
*/
MLXSW_ITEM32(cmd_mbox, config_profile, max_vid_flood_tables, 0x30, 8, 4);
-/* cmd_mbox_config_profile_fid_based
- * FID Based Flood Mode
- * 00 Do not use FID to offset the index into the Port Group Table/Multicast ID
- * 01 Use FID to offset the index to the Port Group Table (pgi)
- * 10 Use FID to offset the index to the Port Group Table (pgi) and
- * the Multicast ID
+/* cmd_mbox_config_profile_flood_mode
+ * Flooding mode to use.
+ * 0-2 - Backward compatible modes for SwitchX devices.
+ * 3 - Mixed mode, where:
+ * max_flood_tables indicates the number of single-entry tables.
+ * max_vid_flood_tables indicates the number of per-VID tables.
+ * max_fid_offset_flood_tables indicates the number of FID-offset tables.
+ * max_fid_flood_tables indicates the number of per-FID tables.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 2);
+/* cmd_mbox_config_profile_max_fid_offset_flood_tables
+ * Maximum number of FID-offset flooding tables.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile,
+ max_fid_offset_flood_tables, 0x34, 24, 4);
+
+/* cmd_mbox_config_profile_fid_offset_flood_table_size
+ * The size (number of entries) of each FID-offset flood table.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile,
+ fid_offset_flood_table_size, 0x34, 0, 16);
+
+/* cmd_mbox_config_profile_max_fid_flood_tables
+ * Maximum number of per-FID flooding tables.
+ *
+ * Note: This flooding tables cover special FIDs only (vFIDs), starting at
+ * FID value 4K and higher.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile, max_fid_flood_tables, 0x38, 24, 4);
+
+/* cmd_mbox_config_profile_fid_flood_table_size
+ * The size (number of entries) of each per-FID table.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile, fid_flood_table_size, 0x38, 0, 16);
+
/* cmd_mbox_config_profile_max_ib_mc
* Maximum number of multicast FDB records for InfiniBand
* FDB (in 512 chunks) per InfiniBand switch partition.
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index dbcaf5df8967..97f0d93caf99 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -287,7 +287,7 @@ static void mlxsw_emad_pack_op_tlv(char *op_tlv,
mlxsw_emad_op_tlv_status_set(op_tlv, 0);
mlxsw_emad_op_tlv_register_id_set(op_tlv, reg->id);
mlxsw_emad_op_tlv_r_set(op_tlv, MLXSW_EMAD_OP_TLV_REQUEST);
- if (MLXSW_CORE_REG_ACCESS_TYPE_QUERY == type)
+ if (type == MLXSW_CORE_REG_ACCESS_TYPE_QUERY)
mlxsw_emad_op_tlv_method_set(op_tlv,
MLXSW_EMAD_OP_TLV_METHOD_QUERY);
else
@@ -362,7 +362,7 @@ static bool mlxsw_emad_is_resp(const struct sk_buff *skb)
char *op_tlv;
op_tlv = mlxsw_emad_op_tlv(skb);
- return (MLXSW_EMAD_OP_TLV_RESPONSE == mlxsw_emad_op_tlv_r_get(op_tlv));
+ return (mlxsw_emad_op_tlv_r_get(op_tlv) == MLXSW_EMAD_OP_TLV_RESPONSE);
}
#define MLXSW_EMAD_TIMEOUT_MS 200
@@ -374,26 +374,31 @@ static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
int err;
int ret;
+ mlxsw_core->emad.trans_active = true;
+
err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info);
if (err) {
dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n",
mlxsw_core->emad.tid);
dev_kfree_skb(skb);
- return err;
+ goto trans_inactive_out;
}
- mlxsw_core->emad.trans_active = true;
ret = wait_event_timeout(mlxsw_core->emad.wait,
!(mlxsw_core->emad.trans_active),
msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS));
if (!ret) {
dev_warn(mlxsw_core->bus_info->dev, "EMAD timed-out (tid=%llx)\n",
mlxsw_core->emad.tid);
- mlxsw_core->emad.trans_active = false;
- return -EIO;
+ err = -EIO;
+ goto trans_inactive_out;
}
return 0;
+
+trans_inactive_out:
+ mlxsw_core->emad.trans_active = false;
+ return err;
}
static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core,
@@ -506,7 +511,6 @@ static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core)
return err;
mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
- MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
MLXSW_TRAP_ID_ETHEMAD);
return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
}
@@ -551,8 +555,8 @@ static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core)
{
char hpkt_pl[MLXSW_REG_HPKT_LEN];
+ mlxsw_core->emad.use_emad = false;
mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD,
- MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
MLXSW_TRAP_ID_ETHEMAD);
mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 165808471188..807827350a89 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -54,6 +54,7 @@
MODULE_ALIAS(MLXSW_MODULE_ALIAS_PREFIX kind)
#define MLXSW_DEVICE_KIND_SWITCHX2 "switchx2"
+#define MLXSW_DEVICE_KIND_SPECTRUM "spectrum"
struct mlxsw_core;
struct mlxsw_driver;
@@ -153,6 +154,10 @@ struct mlxsw_config_profile {
u8 max_flood_tables;
u8 max_vid_flood_tables;
u8 flood_mode;
+ u8 max_fid_offset_flood_tables;
+ u16 fid_offset_flood_table_size;
+ u8 max_fid_flood_tables;
+ u16 fid_flood_table_size;
u16 max_ib_mc;
u16 max_pkey;
u8 ar_sec;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h
index ffd55d030ce2..a94dbda6590b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/item.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/item.h
@@ -171,15 +171,21 @@ static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
}
static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
- struct mlxsw_item *item)
+ struct mlxsw_item *item,
+ unsigned short index)
{
- memcpy(dst, &buf[item->offset], item->size.bytes);
+ unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
+
+ memcpy(dst, &buf[offset], item->size.bytes);
}
-static inline void __mlxsw_item_memcpy_to(char *buf, char *src,
- struct mlxsw_item *item)
+static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
+ struct mlxsw_item *item,
+ unsigned short index)
{
- memcpy(&buf[item->offset], src, item->size.bytes);
+ unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
+
+ memcpy(&buf[offset], src, item->size.bytes);
}
static inline u16
@@ -187,6 +193,7 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
{
u16 max_index, be_index;
u16 offset; /* byte offset inside the array */
+ u8 in_byte_index;
BUG_ON(index && !item->element_size);
if (item->offset % sizeof(u32) != 0 ||
@@ -199,7 +206,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
max_index = (item->size.bytes << 3) / item->element_size - 1;
be_index = max_index - index;
offset = be_index * item->element_size >> 3;
- *shift = index % (BITS_PER_BYTE / item->element_size) << 1;
+ in_byte_index = index % (BITS_PER_BYTE / item->element_size);
+ *shift = in_byte_index * item->element_size;
return item->offset + offset;
}
@@ -371,12 +379,40 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
static inline void \
mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst) \
{ \
- __mlxsw_item_memcpy_from(buf, dst, &__ITEM_NAME(_type, _cname, _iname));\
+ __mlxsw_item_memcpy_from(buf, dst, \
+ &__ITEM_NAME(_type, _cname, _iname), 0); \
+} \
+static inline void \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, const char *src) \
+{ \
+ __mlxsw_item_memcpy_to(buf, src, \
+ &__ITEM_NAME(_type, _cname, _iname), 0); \
+}
+
+#define MLXSW_ITEM_BUF_INDEXED(_type, _cname, _iname, _offset, _sizebytes, \
+ _step, _instepoffset) \
+static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
+ .offset = _offset, \
+ .step = _step, \
+ .in_step_offset = _instepoffset, \
+ .size = {.bytes = _sizebytes,}, \
+ .name = #_type "_" #_cname "_" #_iname, \
+}; \
+static inline void \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, \
+ unsigned short index, \
+ char *dst) \
+{ \
+ __mlxsw_item_memcpy_from(buf, dst, \
+ &__ITEM_NAME(_type, _cname, _iname), index); \
} \
static inline void \
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, char *src) \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, \
+ unsigned short index, \
+ const char *src) \
{ \
- __mlxsw_item_memcpy_to(buf, src, &__ITEM_NAME(_type, _cname, _iname)); \
+ __mlxsw_item_memcpy_to(buf, src, \
+ &__ITEM_NAME(_type, _cname, _iname), index); \
}
#define MLXSW_ITEM_BIT_ARRAY(_type, _cname, _iname, _offset, _sizebytes, \
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 462cea31ecbb..de69e719dc9d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -57,6 +57,7 @@ static const char mlxsw_pci_driver_name[] = "mlxsw_pci";
static const struct pci_device_id mlxsw_pci_id_table[] = {
{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0},
+ {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
{0, }
};
@@ -67,6 +68,8 @@ static const char *mlxsw_pci_device_kind_get(const struct pci_device_id *id)
switch (id->device) {
case PCI_DEVICE_ID_MELLANOX_SWITCHX2:
return MLXSW_DEVICE_KIND_SWITCHX2;
+ case PCI_DEVICE_ID_MELLANOX_SPECTRUM:
+ return MLXSW_DEVICE_KIND_SPECTRUM;
default:
BUG();
}
@@ -171,8 +174,8 @@ struct mlxsw_pci {
struct msix_entry msix_entry;
struct mlxsw_core *core;
struct {
- u16 num_pages;
struct mlxsw_pci_mem_item *items;
+ unsigned int count;
} fw_area;
struct {
struct mlxsw_pci_mem_item out_mbox;
@@ -431,8 +434,7 @@ static int mlxsw_pci_wqe_frag_map(struct mlxsw_pci *mlxsw_pci, char *wqe,
mapaddr = pci_map_single(pdev, frag_data, frag_len, direction);
if (unlikely(pci_dma_mapping_error(pdev, mapaddr))) {
- if (net_ratelimit())
- dev_err(&pdev->dev, "failed to dma map tx frag\n");
+ dev_err_ratelimited(&pdev->dev, "failed to dma map tx frag\n");
return -EIO;
}
mlxsw_pci_wqe_address_set(wqe, index, mapaddr);
@@ -497,6 +499,7 @@ static int mlxsw_pci_rdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
struct mlxsw_pci_queue *q)
{
struct mlxsw_pci_queue_elem_info *elem_info;
+ u8 sdq_count = mlxsw_pci_sdq_count(mlxsw_pci);
int i;
int err;
@@ -504,9 +507,9 @@ static int mlxsw_pci_rdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
q->consumer_counter = 0;
/* Set CQ of same number of this RDQ with base
- * above MLXSW_PCI_SDQS_MAX as the lower ones are assigned to SDQs.
+ * above SDQ count as the lower ones are assigned to SDQs.
*/
- mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, q->num + MLXSW_PCI_SDQS_COUNT);
+ mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, sdq_count + q->num);
mlxsw_cmd_mbox_sw2hw_dq_log2_dq_sz_set(mbox, 3); /* 8 pages */
for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) {
dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i);
@@ -699,8 +702,8 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
put_new_skb:
memset(wqe, 0, q->elem_size);
err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info);
- if (err && net_ratelimit())
- dev_dbg(&pdev->dev, "Failed to alloc skb for RDQ\n");
+ if (err)
+ dev_dbg_ratelimited(&pdev->dev, "Failed to alloc skb for RDQ\n");
/* Everything is set up, ring doorbell to pass elem to HW */
q->producer_counter++;
mlxsw_pci_queue_doorbell_producer_ring(mlxsw_pci, q);
@@ -830,7 +833,8 @@ static void mlxsw_pci_eq_tasklet(unsigned long data)
{
struct mlxsw_pci_queue *q = (struct mlxsw_pci_queue *) data;
struct mlxsw_pci *mlxsw_pci = q->pci;
- unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_COUNT)];
+ u8 cq_count = mlxsw_pci_cq_count(mlxsw_pci);
+ unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_MAX)];
char *eqe;
u8 cqn;
bool cq_handle = false;
@@ -866,7 +870,7 @@ static void mlxsw_pci_eq_tasklet(unsigned long data)
if (!cq_handle)
return;
- for_each_set_bit(cqn, active_cqns, MLXSW_PCI_CQS_COUNT) {
+ for_each_set_bit(cqn, active_cqns, cq_count) {
q = mlxsw_pci_cq_get(mlxsw_pci, cqn);
mlxsw_pci_queue_tasklet_schedule(q);
}
@@ -1067,10 +1071,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox)
num_eqs = mlxsw_cmd_mbox_query_aq_cap_max_num_eqs_get(mbox);
eq_log2sz = mlxsw_cmd_mbox_query_aq_cap_log_max_eq_sz_get(mbox);
- if ((num_sdqs != MLXSW_PCI_SDQS_COUNT) ||
- (num_rdqs != MLXSW_PCI_RDQS_COUNT) ||
- (num_cqs != MLXSW_PCI_CQS_COUNT) ||
- (num_eqs != MLXSW_PCI_EQS_COUNT)) {
+ if (num_sdqs + num_rdqs > num_cqs ||
+ num_cqs > MLXSW_PCI_CQS_MAX || num_eqs != MLXSW_PCI_EQS_COUNT) {
dev_err(&pdev->dev, "Unsupported number of queues\n");
return -EINVAL;
}
@@ -1215,6 +1217,14 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
mbox, profile->max_flood_tables);
mlxsw_cmd_mbox_config_profile_max_vid_flood_tables_set(
mbox, profile->max_vid_flood_tables);
+ mlxsw_cmd_mbox_config_profile_max_fid_offset_flood_tables_set(
+ mbox, profile->max_fid_offset_flood_tables);
+ mlxsw_cmd_mbox_config_profile_fid_offset_flood_table_size_set(
+ mbox, profile->fid_offset_flood_table_size);
+ mlxsw_cmd_mbox_config_profile_max_fid_flood_tables_set(
+ mbox, profile->max_fid_flood_tables);
+ mlxsw_cmd_mbox_config_profile_fid_flood_table_size_set(
+ mbox, profile->fid_flood_table_size);
}
if (profile->used_flood_mode) {
mlxsw_cmd_mbox_config_profile_set_flood_mode_set(
@@ -1272,6 +1282,7 @@ static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
u16 num_pages)
{
struct mlxsw_pci_mem_item *mem_item;
+ int nent = 0;
int i;
int err;
@@ -1279,7 +1290,7 @@ static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
GFP_KERNEL);
if (!mlxsw_pci->fw_area.items)
return -ENOMEM;
- mlxsw_pci->fw_area.num_pages = num_pages;
+ mlxsw_pci->fw_area.count = num_pages;
mlxsw_cmd_mbox_zero(mbox);
for (i = 0; i < num_pages; i++) {
@@ -1293,13 +1304,22 @@ static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
err = -ENOMEM;
goto err_alloc;
}
- mlxsw_cmd_mbox_map_fa_pa_set(mbox, i, mem_item->mapaddr);
- mlxsw_cmd_mbox_map_fa_log2size_set(mbox, i, 0); /* 1 page */
+ mlxsw_cmd_mbox_map_fa_pa_set(mbox, nent, mem_item->mapaddr);
+ mlxsw_cmd_mbox_map_fa_log2size_set(mbox, nent, 0); /* 1 page */
+ if (++nent == MLXSW_CMD_MAP_FA_VPM_ENTRIES_MAX) {
+ err = mlxsw_cmd_map_fa(mlxsw_pci->core, mbox, nent);
+ if (err)
+ goto err_cmd_map_fa;
+ nent = 0;
+ mlxsw_cmd_mbox_zero(mbox);
+ }
}
- err = mlxsw_cmd_map_fa(mlxsw_pci->core, mbox, num_pages);
- if (err)
- goto err_cmd_map_fa;
+ if (nent) {
+ err = mlxsw_cmd_map_fa(mlxsw_pci->core, mbox, nent);
+ if (err)
+ goto err_cmd_map_fa;
+ }
return 0;
@@ -1322,7 +1342,7 @@ static void mlxsw_pci_fw_area_fini(struct mlxsw_pci *mlxsw_pci)
mlxsw_cmd_unmap_fa(mlxsw_pci->core);
- for (i = 0; i < mlxsw_pci->fw_area.num_pages; i++) {
+ for (i = 0; i < mlxsw_pci->fw_area.count; i++) {
mem_item = &mlxsw_pci->fw_area.items[i];
pci_free_consistent(mlxsw_pci->pdev, mem_item->size,
@@ -1582,11 +1602,11 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
if (in_mbox)
memcpy(mlxsw_pci->cmd.in_mbox.buf, in_mbox, in_mbox_size);
- mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, in_mapaddr >> 32);
- mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, in_mapaddr);
+ mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, upper_32_bits(in_mapaddr));
+ mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, lower_32_bits(in_mapaddr));
- mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, out_mapaddr >> 32);
- mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, out_mapaddr);
+ mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, upper_32_bits(out_mapaddr));
+ mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, lower_32_bits(out_mapaddr));
mlxsw_pci_write32(mlxsw_pci, CIR_IN_MODIFIER, in_mod);
mlxsw_pci_write32(mlxsw_pci, CIR_TOKEN, 0);
@@ -1642,8 +1662,9 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
CIR_OUT_PARAM_LO));
memcpy(out_mbox + sizeof(tmp), &tmp, sizeof(tmp));
}
- } else if (!err && out_mbox)
+ } else if (!err && out_mbox) {
memcpy(out_mbox, mlxsw_pci->cmd.out_mbox.buf, out_mbox_size);
+ }
mutex_unlock(&mlxsw_pci->cmd.lock);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h
index 1ef9664b4512..142f33d978c5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h
@@ -40,6 +40,7 @@
#include "item.h"
#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738
+#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84
#define MLXSW_PCI_BAR0_SIZE (1024 * 1024) /* 1MB */
#define MLXSW_PCI_PAGE_SIZE 4096
@@ -71,9 +72,7 @@
#define MLXSW_PCI_DOORBELL(offset, type_offset, num) \
((offset) + (type_offset) + (num) * 4)
-#define MLXSW_PCI_RDQS_COUNT 24
-#define MLXSW_PCI_SDQS_COUNT 24
-#define MLXSW_PCI_CQS_COUNT (MLXSW_PCI_RDQS_COUNT + MLXSW_PCI_SDQS_COUNT)
+#define MLXSW_PCI_CQS_MAX 96
#define MLXSW_PCI_EQS_COUNT 2
#define MLXSW_PCI_EQ_ASYNC_NUM 0
#define MLXSW_PCI_EQ_COMP_NUM 1
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 096e1c12175a..236fb5d2ad69 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -99,57 +99,6 @@ static const struct mlxsw_reg_info mlxsw_reg_spad = {
*/
MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02, 6);
-/* SMID - Switch Multicast ID
- * --------------------------
- * In multi-chip configuration, each device should maintain mapping between
- * Multicast ID (MID) into a list of local ports. This mapping is used in all
- * the devices other than the ingress device, and is implemented as part of the
- * FDB. The MID record maps from a MID, which is a unique identi- fier of the
- * multicast group within the stacking domain, into a list of local ports into
- * which the packet is replicated.
- */
-#define MLXSW_REG_SMID_ID 0x2007
-#define MLXSW_REG_SMID_LEN 0x420
-
-static const struct mlxsw_reg_info mlxsw_reg_smid = {
- .id = MLXSW_REG_SMID_ID,
- .len = MLXSW_REG_SMID_LEN,
-};
-
-/* reg_smid_swid
- * Switch partition ID.
- * Access: Index
- */
-MLXSW_ITEM32(reg, smid, swid, 0x00, 24, 8);
-
-/* reg_smid_mid
- * Multicast identifier - global identifier that represents the multicast group
- * across all devices
- * Access: Index
- */
-MLXSW_ITEM32(reg, smid, mid, 0x00, 0, 16);
-
-/* reg_smid_port
- * Local port memebership (1 bit per port).
- * Access: RW
- */
-MLXSW_ITEM_BIT_ARRAY(reg, smid, port, 0x20, 0x20, 1);
-
-/* reg_smid_port_mask
- * Local port mask (1 bit per port).
- * Access: W
- */
-MLXSW_ITEM_BIT_ARRAY(reg, smid, port_mask, 0x220, 0x20, 1);
-
-static inline void mlxsw_reg_smid_pack(char *payload, u16 mid)
-{
- MLXSW_REG_ZERO(smid, payload);
- mlxsw_reg_smid_swid_set(payload, 0);
- mlxsw_reg_smid_mid_set(payload, mid);
- mlxsw_reg_smid_port_set(payload, MLXSW_PORT_CPU_PORT, 1);
- mlxsw_reg_smid_port_mask_set(payload, MLXSW_PORT_CPU_PORT, 1);
-}
-
/* SSPR - Switch System Port Record Register
* -----------------------------------------
* Configures the system port to local port mapping.
@@ -208,11 +157,359 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port)
mlxsw_reg_sspr_system_port_set(payload, local_port);
}
+/* SFDAT - Switch Filtering Database Aging Time
+ * --------------------------------------------
+ * Controls the Switch aging time. Aging time is able to be set per Switch
+ * Partition.
+ */
+#define MLXSW_REG_SFDAT_ID 0x2009
+#define MLXSW_REG_SFDAT_LEN 0x8
+
+static const struct mlxsw_reg_info mlxsw_reg_sfdat = {
+ .id = MLXSW_REG_SFDAT_ID,
+ .len = MLXSW_REG_SFDAT_LEN,
+};
+
+/* reg_sfdat_swid
+ * Switch partition ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sfdat, swid, 0x00, 24, 8);
+
+/* reg_sfdat_age_time
+ * Aging time in seconds
+ * Min - 10 seconds
+ * Max - 1,000,000 seconds
+ * Default is 300 seconds.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdat, age_time, 0x04, 0, 20);
+
+static inline void mlxsw_reg_sfdat_pack(char *payload, u32 age_time)
+{
+ MLXSW_REG_ZERO(sfdat, payload);
+ mlxsw_reg_sfdat_swid_set(payload, 0);
+ mlxsw_reg_sfdat_age_time_set(payload, age_time);
+}
+
+/* SFD - Switch Filtering Database
+ * -------------------------------
+ * The following register defines the access to the filtering database.
+ * The register supports querying, adding, removing and modifying the database.
+ * The access is optimized for bulk updates in which case more than one
+ * FDB record is present in the same command.
+ */
+#define MLXSW_REG_SFD_ID 0x200A
+#define MLXSW_REG_SFD_BASE_LEN 0x10 /* base length, without records */
+#define MLXSW_REG_SFD_REC_LEN 0x10 /* record length */
+#define MLXSW_REG_SFD_REC_MAX_COUNT 64
+#define MLXSW_REG_SFD_LEN (MLXSW_REG_SFD_BASE_LEN + \
+ MLXSW_REG_SFD_REC_LEN * MLXSW_REG_SFD_REC_MAX_COUNT)
+
+static const struct mlxsw_reg_info mlxsw_reg_sfd = {
+ .id = MLXSW_REG_SFD_ID,
+ .len = MLXSW_REG_SFD_LEN,
+};
+
+/* reg_sfd_swid
+ * Switch partition ID for queries. Reserved on Write.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sfd, swid, 0x00, 24, 8);
+
+enum mlxsw_reg_sfd_op {
+ /* Dump entire FDB a (process according to record_locator) */
+ MLXSW_REG_SFD_OP_QUERY_DUMP = 0,
+ /* Query records by {MAC, VID/FID} value */
+ MLXSW_REG_SFD_OP_QUERY_QUERY = 1,
+ /* Query and clear activity. Query records by {MAC, VID/FID} value */
+ MLXSW_REG_SFD_OP_QUERY_QUERY_AND_CLEAR_ACTIVITY = 2,
+ /* Test. Response indicates if each of the records could be
+ * added to the FDB.
+ */
+ MLXSW_REG_SFD_OP_WRITE_TEST = 0,
+ /* Add/modify. Aged-out records cannot be added. This command removes
+ * the learning notification of the {MAC, VID/FID}. Response includes
+ * the entries that were added to the FDB.
+ */
+ MLXSW_REG_SFD_OP_WRITE_EDIT = 1,
+ /* Remove record by {MAC, VID/FID}. This command also removes
+ * the learning notification and aged-out notifications
+ * of the {MAC, VID/FID}. The response provides current (pre-removal)
+ * entries as non-aged-out.
+ */
+ MLXSW_REG_SFD_OP_WRITE_REMOVE = 2,
+ /* Remove learned notification by {MAC, VID/FID}. The response provides
+ * the removed learning notification.
+ */
+ MLXSW_REG_SFD_OP_WRITE_REMOVE_NOTIFICATION = 2,
+};
+
+/* reg_sfd_op
+ * Operation.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, sfd, op, 0x04, 30, 2);
+
+/* reg_sfd_record_locator
+ * Used for querying the FDB. Use record_locator=0 to initiate the
+ * query. When a record is returned, a new record_locator is
+ * returned to be used in the subsequent query.
+ * Reserved for database update.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sfd, record_locator, 0x04, 0, 30);
+
+/* reg_sfd_num_rec
+ * Request: Number of records to read/add/modify/remove
+ * Response: Number of records read/added/replaced/removed
+ * See above description for more details.
+ * Ranges 0..64
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfd, num_rec, 0x08, 0, 8);
+
+static inline void mlxsw_reg_sfd_pack(char *payload, enum mlxsw_reg_sfd_op op,
+ u32 record_locator)
+{
+ MLXSW_REG_ZERO(sfd, payload);
+ mlxsw_reg_sfd_op_set(payload, op);
+ mlxsw_reg_sfd_record_locator_set(payload, record_locator);
+}
+
+/* reg_sfd_rec_swid
+ * Switch partition ID.
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, rec_swid, MLXSW_REG_SFD_BASE_LEN, 24, 8,
+ MLXSW_REG_SFD_REC_LEN, 0x00, false);
+
+enum mlxsw_reg_sfd_rec_type {
+ MLXSW_REG_SFD_REC_TYPE_UNICAST = 0x0,
+};
+
+/* reg_sfd_rec_type
+ * FDB record type.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, rec_type, MLXSW_REG_SFD_BASE_LEN, 20, 4,
+ MLXSW_REG_SFD_REC_LEN, 0x00, false);
+
+enum mlxsw_reg_sfd_rec_policy {
+ /* Replacement disabled, aging disabled. */
+ MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY = 0,
+ /* (mlag remote): Replacement enabled, aging disabled,
+ * learning notification enabled on this port.
+ */
+ MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG = 1,
+ /* (ingress device): Replacement enabled, aging enabled. */
+ MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS = 3,
+};
+
+/* reg_sfd_rec_policy
+ * Policy.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, rec_policy, MLXSW_REG_SFD_BASE_LEN, 18, 2,
+ MLXSW_REG_SFD_REC_LEN, 0x00, false);
+
+/* reg_sfd_rec_a
+ * Activity. Set for new static entries. Set for static entries if a frame SMAC
+ * lookup hits on the entry.
+ * To clear the a bit, use "query and clear activity" op.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, rec_a, MLXSW_REG_SFD_BASE_LEN, 16, 1,
+ MLXSW_REG_SFD_REC_LEN, 0x00, false);
+
+/* reg_sfd_rec_mac
+ * MAC address.
+ * Access: Index
+ */
+MLXSW_ITEM_BUF_INDEXED(reg, sfd, rec_mac, MLXSW_REG_SFD_BASE_LEN, 6,
+ MLXSW_REG_SFD_REC_LEN, 0x02);
+
+enum mlxsw_reg_sfd_rec_action {
+ /* forward */
+ MLXSW_REG_SFD_REC_ACTION_NOP = 0,
+ /* forward and trap, trap_id is FDB_TRAP */
+ MLXSW_REG_SFD_REC_ACTION_MIRROR_TO_CPU = 1,
+ /* trap and do not forward, trap_id is FDB_TRAP */
+ MLXSW_REG_SFD_REC_ACTION_TRAP = 3,
+ MLXSW_REG_SFD_REC_ACTION_DISCARD_ERROR = 15,
+};
+
+/* reg_sfd_rec_action
+ * Action to apply on the packet.
+ * Note: Dynamic entries can only be configured with NOP action.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, rec_action, MLXSW_REG_SFD_BASE_LEN, 28, 4,
+ MLXSW_REG_SFD_REC_LEN, 0x0C, false);
+
+/* reg_sfd_uc_sub_port
+ * VEPA channel on local port.
+ * Valid only if local port is a non-stacking port. Must be 0 if multichannel
+ * VEPA is not enabled.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, uc_sub_port, MLXSW_REG_SFD_BASE_LEN, 16, 8,
+ MLXSW_REG_SFD_REC_LEN, 0x08, false);
+
+/* reg_sfd_uc_fid_vid
+ * Filtering ID or VLAN ID
+ * For SwitchX and SwitchX-2:
+ * - Dynamic entries (policy 2,3) use FID
+ * - Static entries (policy 0) use VID
+ * - When independent learning is configured, VID=FID
+ * For Spectrum: use FID for both Dynamic and Static entries.
+ * VID should not be used.
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, uc_fid_vid, MLXSW_REG_SFD_BASE_LEN, 0, 16,
+ MLXSW_REG_SFD_REC_LEN, 0x08, false);
+
+/* reg_sfd_uc_system_port
+ * Unique port identifier for the final destination of the packet.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, sfd, uc_system_port, MLXSW_REG_SFD_BASE_LEN, 0, 16,
+ MLXSW_REG_SFD_REC_LEN, 0x0C, false);
+
+static inline void mlxsw_reg_sfd_uc_pack(char *payload, int rec_index,
+ enum mlxsw_reg_sfd_rec_policy policy,
+ const char *mac, u16 vid,
+ enum mlxsw_reg_sfd_rec_action action,
+ u8 local_port)
+{
+ u8 num_rec = mlxsw_reg_sfd_num_rec_get(payload);
+
+ if (rec_index >= num_rec)
+ mlxsw_reg_sfd_num_rec_set(payload, rec_index + 1);
+ mlxsw_reg_sfd_rec_swid_set(payload, rec_index, 0);
+ mlxsw_reg_sfd_rec_type_set(payload, rec_index,
+ MLXSW_REG_SFD_REC_TYPE_UNICAST);
+ mlxsw_reg_sfd_rec_policy_set(payload, rec_index, policy);
+ mlxsw_reg_sfd_rec_mac_memcpy_to(payload, rec_index, mac);
+ mlxsw_reg_sfd_uc_sub_port_set(payload, rec_index, 0);
+ mlxsw_reg_sfd_uc_fid_vid_set(payload, rec_index, vid);
+ mlxsw_reg_sfd_rec_action_set(payload, rec_index, action);
+ mlxsw_reg_sfd_uc_system_port_set(payload, rec_index, local_port);
+}
+
+static inline void mlxsw_reg_sfd_uc_unpack(char *payload, int rec_index,
+ char *mac, u16 *p_vid,
+ u8 *p_local_port)
+{
+ mlxsw_reg_sfd_rec_mac_memcpy_from(payload, rec_index, mac);
+ *p_vid = mlxsw_reg_sfd_uc_fid_vid_get(payload, rec_index);
+ *p_local_port = mlxsw_reg_sfd_uc_system_port_get(payload, rec_index);
+}
+
+/* SFN - Switch FDB Notification Register
+ * -------------------------------------------
+ * The switch provides notifications on newly learned FDB entries and
+ * aged out entries. The notifications can be polled by software.
+ */
+#define MLXSW_REG_SFN_ID 0x200B
+#define MLXSW_REG_SFN_BASE_LEN 0x10 /* base length, without records */
+#define MLXSW_REG_SFN_REC_LEN 0x10 /* record length */
+#define MLXSW_REG_SFN_REC_MAX_COUNT 64
+#define MLXSW_REG_SFN_LEN (MLXSW_REG_SFN_BASE_LEN + \
+ MLXSW_REG_SFN_REC_LEN * MLXSW_REG_SFN_REC_MAX_COUNT)
+
+static const struct mlxsw_reg_info mlxsw_reg_sfn = {
+ .id = MLXSW_REG_SFN_ID,
+ .len = MLXSW_REG_SFN_LEN,
+};
+
+/* reg_sfn_swid
+ * Switch partition ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sfn, swid, 0x00, 24, 8);
+
+/* reg_sfn_num_rec
+ * Request: Number of learned notifications and aged-out notification
+ * records requested.
+ * Response: Number of notification records returned (must be smaller
+ * than or equal to the value requested)
+ * Ranges 0..64
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, sfn, num_rec, 0x04, 0, 8);
+
+static inline void mlxsw_reg_sfn_pack(char *payload)
+{
+ MLXSW_REG_ZERO(sfn, payload);
+ mlxsw_reg_sfn_swid_set(payload, 0);
+ mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT);
+}
+
+/* reg_sfn_rec_swid
+ * Switch partition ID.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, sfn, rec_swid, MLXSW_REG_SFN_BASE_LEN, 24, 8,
+ MLXSW_REG_SFN_REC_LEN, 0x00, false);
+
+enum mlxsw_reg_sfn_rec_type {
+ /* MAC addresses learned on a regular port. */
+ MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC = 0x5,
+ /* Aged-out MAC address on a regular port */
+ MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC = 0x7,
+};
+
+/* reg_sfn_rec_type
+ * Notification record type.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, sfn, rec_type, MLXSW_REG_SFN_BASE_LEN, 20, 4,
+ MLXSW_REG_SFN_REC_LEN, 0x00, false);
+
+/* reg_sfn_rec_mac
+ * MAC address.
+ * Access: RO
+ */
+MLXSW_ITEM_BUF_INDEXED(reg, sfn, rec_mac, MLXSW_REG_SFN_BASE_LEN, 6,
+ MLXSW_REG_SFN_REC_LEN, 0x02);
+
+/* reg_sfn_mac_sub_port
+ * VEPA channel on the local port.
+ * 0 if multichannel VEPA is not enabled.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, sfn, mac_sub_port, MLXSW_REG_SFN_BASE_LEN, 16, 8,
+ MLXSW_REG_SFN_REC_LEN, 0x08, false);
+
+/* reg_sfn_mac_fid
+ * Filtering identifier.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, sfn, mac_fid, MLXSW_REG_SFN_BASE_LEN, 0, 16,
+ MLXSW_REG_SFN_REC_LEN, 0x08, false);
+
+/* reg_sfn_mac_system_port
+ * Unique port identifier for the final destination of the packet.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, sfn, mac_system_port, MLXSW_REG_SFN_BASE_LEN, 0, 16,
+ MLXSW_REG_SFN_REC_LEN, 0x0C, false);
+
+static inline void mlxsw_reg_sfn_mac_unpack(char *payload, int rec_index,
+ char *mac, u16 *p_vid,
+ u8 *p_local_port)
+{
+ mlxsw_reg_sfn_rec_mac_memcpy_from(payload, rec_index, mac);
+ *p_vid = mlxsw_reg_sfn_mac_fid_get(payload, rec_index);
+ *p_local_port = mlxsw_reg_sfn_mac_system_port_get(payload, rec_index);
+}
+
/* SPMS - Switch Port MSTP/RSTP State Register
* -------------------------------------------
* Configures the spanning tree state of a physical port.
*/
-#define MLXSW_REG_SPMS_ID 0x200d
+#define MLXSW_REG_SPMS_ID 0x200D
#define MLXSW_REG_SPMS_LEN 0x404
static const struct mlxsw_reg_info mlxsw_reg_spms = {
@@ -243,20 +540,166 @@ enum mlxsw_reg_spms_state {
*/
MLXSW_ITEM_BIT_ARRAY(reg, spms, state, 0x04, 0x400, 2);
-static inline void mlxsw_reg_spms_pack(char *payload, u8 local_port, u16 vid,
- enum mlxsw_reg_spms_state state)
+static inline void mlxsw_reg_spms_pack(char *payload, u8 local_port)
{
MLXSW_REG_ZERO(spms, payload);
mlxsw_reg_spms_local_port_set(payload, local_port);
+}
+
+static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid,
+ enum mlxsw_reg_spms_state state)
+{
mlxsw_reg_spms_state_set(payload, vid, state);
}
+/* SPVID - Switch Port VID
+ * -----------------------
+ * The switch port VID configures the default VID for a port.
+ */
+#define MLXSW_REG_SPVID_ID 0x200E
+#define MLXSW_REG_SPVID_LEN 0x08
+
+static const struct mlxsw_reg_info mlxsw_reg_spvid = {
+ .id = MLXSW_REG_SPVID_ID,
+ .len = MLXSW_REG_SPVID_LEN,
+};
+
+/* reg_spvid_local_port
+ * Local port number.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, spvid, local_port, 0x00, 16, 8);
+
+/* reg_spvid_sub_port
+ * Virtual port within the physical port.
+ * Should be set to 0 when virtual ports are not enabled on the port.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8);
+
+/* reg_spvid_pvid
+ * Port default VID
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spvid, pvid, 0x04, 0, 12);
+
+static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid)
+{
+ MLXSW_REG_ZERO(spvid, payload);
+ mlxsw_reg_spvid_local_port_set(payload, local_port);
+ mlxsw_reg_spvid_pvid_set(payload, pvid);
+}
+
+/* SPVM - Switch Port VLAN Membership
+ * ----------------------------------
+ * The Switch Port VLAN Membership register configures the VLAN membership
+ * of a port in a VLAN denoted by VID. VLAN membership is managed per
+ * virtual port. The register can be used to add and remove VID(s) from a port.
+ */
+#define MLXSW_REG_SPVM_ID 0x200F
+#define MLXSW_REG_SPVM_BASE_LEN 0x04 /* base length, without records */
+#define MLXSW_REG_SPVM_REC_LEN 0x04 /* record length */
+#define MLXSW_REG_SPVM_REC_MAX_COUNT 256
+#define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN + \
+ MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT)
+
+static const struct mlxsw_reg_info mlxsw_reg_spvm = {
+ .id = MLXSW_REG_SPVM_ID,
+ .len = MLXSW_REG_SPVM_LEN,
+};
+
+/* reg_spvm_pt
+ * Priority tagged. If this bit is set, packets forwarded to the port with
+ * untagged VLAN membership (u bit is set) will be tagged with priority tag
+ * (VID=0)
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spvm, pt, 0x00, 31, 1);
+
+/* reg_spvm_pte
+ * Priority Tagged Update Enable. On Write operations, if this bit is cleared,
+ * the pt bit will NOT be updated. To update the pt bit, pte must be set.
+ * Access: WO
+ */
+MLXSW_ITEM32(reg, spvm, pte, 0x00, 30, 1);
+
+/* reg_spvm_local_port
+ * Local port number.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, spvm, local_port, 0x00, 16, 8);
+
+/* reg_spvm_sub_port
+ * Virtual port within the physical port.
+ * Should be set to 0 when virtual ports are not enabled on the port.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, spvm, sub_port, 0x00, 8, 8);
+
+/* reg_spvm_num_rec
+ * Number of records to update. Each record contains: i, e, u, vid.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, spvm, num_rec, 0x00, 0, 8);
+
+/* reg_spvm_rec_i
+ * Ingress membership in VLAN ID.
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, spvm, rec_i,
+ MLXSW_REG_SPVM_BASE_LEN, 14, 1,
+ MLXSW_REG_SPVM_REC_LEN, 0, false);
+
+/* reg_spvm_rec_e
+ * Egress membership in VLAN ID.
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, spvm, rec_e,
+ MLXSW_REG_SPVM_BASE_LEN, 13, 1,
+ MLXSW_REG_SPVM_REC_LEN, 0, false);
+
+/* reg_spvm_rec_u
+ * Untagged - port is an untagged member - egress transmission uses untagged
+ * frames on VID<n>
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, spvm, rec_u,
+ MLXSW_REG_SPVM_BASE_LEN, 12, 1,
+ MLXSW_REG_SPVM_REC_LEN, 0, false);
+
+/* reg_spvm_rec_vid
+ * Egress membership in VLAN ID.
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, spvm, rec_vid,
+ MLXSW_REG_SPVM_BASE_LEN, 0, 12,
+ MLXSW_REG_SPVM_REC_LEN, 0, false);
+
+static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port,
+ u16 vid_begin, u16 vid_end,
+ bool is_member, bool untagged)
+{
+ int size = vid_end - vid_begin + 1;
+ int i;
+
+ MLXSW_REG_ZERO(spvm, payload);
+ mlxsw_reg_spvm_local_port_set(payload, local_port);
+ mlxsw_reg_spvm_num_rec_set(payload, size);
+
+ for (i = 0; i < size; i++) {
+ mlxsw_reg_spvm_rec_i_set(payload, i, is_member);
+ mlxsw_reg_spvm_rec_e_set(payload, i, is_member);
+ mlxsw_reg_spvm_rec_u_set(payload, i, untagged);
+ mlxsw_reg_spvm_rec_vid_set(payload, i, vid_begin + i);
+ }
+}
+
/* SFGC - Switch Flooding Group Configuration
* ------------------------------------------
* The following register controls the association of flooding tables and MIDs
* to packet types used for flooding.
*/
-#define MLXSW_REG_SFGC_ID 0x2011
+#define MLXSW_REG_SFGC_ID 0x2011
#define MLXSW_REG_SFGC_LEN 0x10
static const struct mlxsw_reg_info mlxsw_reg_sfgc = {
@@ -265,13 +708,15 @@ static const struct mlxsw_reg_info mlxsw_reg_sfgc = {
};
enum mlxsw_reg_sfgc_type {
- MLXSW_REG_SFGC_TYPE_BROADCAST = 0,
- MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST = 1,
- MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4 = 2,
- MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6 = 3,
- MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP = 5,
- MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL = 6,
- MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST = 7,
+ MLXSW_REG_SFGC_TYPE_BROADCAST,
+ MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST,
+ MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4,
+ MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6,
+ MLXSW_REG_SFGC_TYPE_RESERVED,
+ MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP,
+ MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL,
+ MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST,
+ MLXSW_REG_SFGC_TYPE_MAX,
};
/* reg_sfgc_type
@@ -408,7 +853,7 @@ static inline void mlxsw_reg_sftr_pack(char *payload,
unsigned int flood_table,
unsigned int index,
enum mlxsw_flood_table_type table_type,
- unsigned int range)
+ unsigned int range, u8 port, bool set)
{
MLXSW_REG_ZERO(sftr, payload);
mlxsw_reg_sftr_swid_set(payload, 0);
@@ -416,8 +861,8 @@ static inline void mlxsw_reg_sftr_pack(char *payload,
mlxsw_reg_sftr_index_set(payload, index);
mlxsw_reg_sftr_table_type_set(payload, table_type);
mlxsw_reg_sftr_range_set(payload, range);
- mlxsw_reg_sftr_port_set(payload, MLXSW_PORT_CPU_PORT, 1);
- mlxsw_reg_sftr_port_mask_set(payload, MLXSW_PORT_CPU_PORT, 1);
+ mlxsw_reg_sftr_port_set(payload, port, set);
+ mlxsw_reg_sftr_port_mask_set(payload, port, 1);
}
/* SPMLR - Switch Port MAC Learning Register
@@ -473,6 +918,285 @@ static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port,
mlxsw_reg_spmlr_learn_mode_set(payload, mode);
}
+/* SVFA - Switch VID to FID Allocation Register
+ * --------------------------------------------
+ * Controls the VID to FID mapping and {Port, VID} to FID mapping for
+ * virtualized ports.
+ */
+#define MLXSW_REG_SVFA_ID 0x201C
+#define MLXSW_REG_SVFA_LEN 0x10
+
+static const struct mlxsw_reg_info mlxsw_reg_svfa = {
+ .id = MLXSW_REG_SVFA_ID,
+ .len = MLXSW_REG_SVFA_LEN,
+};
+
+/* reg_svfa_swid
+ * Switch partition ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, svfa, swid, 0x00, 24, 8);
+
+/* reg_svfa_local_port
+ * Local port number.
+ * Access: Index
+ *
+ * Note: Reserved for 802.1Q FIDs.
+ */
+MLXSW_ITEM32(reg, svfa, local_port, 0x00, 16, 8);
+
+enum mlxsw_reg_svfa_mt {
+ MLXSW_REG_SVFA_MT_VID_TO_FID,
+ MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
+};
+
+/* reg_svfa_mapping_table
+ * Mapping table:
+ * 0 - VID to FID
+ * 1 - {Port, VID} to FID
+ * Access: Index
+ *
+ * Note: Reserved for SwitchX-2.
+ */
+MLXSW_ITEM32(reg, svfa, mapping_table, 0x00, 8, 3);
+
+/* reg_svfa_v
+ * Valid.
+ * Valid if set.
+ * Access: RW
+ *
+ * Note: Reserved for SwitchX-2.
+ */
+MLXSW_ITEM32(reg, svfa, v, 0x00, 0, 1);
+
+/* reg_svfa_fid
+ * Filtering ID.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, svfa, fid, 0x04, 16, 16);
+
+/* reg_svfa_vid
+ * VLAN ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, svfa, vid, 0x04, 0, 12);
+
+/* reg_svfa_counter_set_type
+ * Counter set type for flow counters.
+ * Access: RW
+ *
+ * Note: Reserved for SwitchX-2.
+ */
+MLXSW_ITEM32(reg, svfa, counter_set_type, 0x08, 24, 8);
+
+/* reg_svfa_counter_index
+ * Counter index for flow counters.
+ * Access: RW
+ *
+ * Note: Reserved for SwitchX-2.
+ */
+MLXSW_ITEM32(reg, svfa, counter_index, 0x08, 0, 24);
+
+static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port,
+ enum mlxsw_reg_svfa_mt mt, bool valid,
+ u16 fid, u16 vid)
+{
+ MLXSW_REG_ZERO(svfa, payload);
+ local_port = mt == MLXSW_REG_SVFA_MT_VID_TO_FID ? 0 : local_port;
+ mlxsw_reg_svfa_swid_set(payload, 0);
+ mlxsw_reg_svfa_local_port_set(payload, local_port);
+ mlxsw_reg_svfa_mapping_table_set(payload, mt);
+ mlxsw_reg_svfa_v_set(payload, valid);
+ mlxsw_reg_svfa_fid_set(payload, fid);
+ mlxsw_reg_svfa_vid_set(payload, vid);
+}
+
+/* SVPE - Switch Virtual-Port Enabling Register
+ * --------------------------------------------
+ * Enables port virtualization.
+ */
+#define MLXSW_REG_SVPE_ID 0x201E
+#define MLXSW_REG_SVPE_LEN 0x4
+
+static const struct mlxsw_reg_info mlxsw_reg_svpe = {
+ .id = MLXSW_REG_SVPE_ID,
+ .len = MLXSW_REG_SVPE_LEN,
+};
+
+/* reg_svpe_local_port
+ * Local port number
+ * Access: Index
+ *
+ * Note: CPU port is not supported (uses VLAN mode only).
+ */
+MLXSW_ITEM32(reg, svpe, local_port, 0x00, 16, 8);
+
+/* reg_svpe_vp_en
+ * Virtual port enable.
+ * 0 - Disable, VLAN mode (VID to FID).
+ * 1 - Enable, Virtual port mode ({Port, VID} to FID).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, svpe, vp_en, 0x00, 8, 1);
+
+static inline void mlxsw_reg_svpe_pack(char *payload, u8 local_port,
+ bool enable)
+{
+ MLXSW_REG_ZERO(svpe, payload);
+ mlxsw_reg_svpe_local_port_set(payload, local_port);
+ mlxsw_reg_svpe_vp_en_set(payload, enable);
+}
+
+/* SFMR - Switch FID Management Register
+ * -------------------------------------
+ * Creates and configures FIDs.
+ */
+#define MLXSW_REG_SFMR_ID 0x201F
+#define MLXSW_REG_SFMR_LEN 0x18
+
+static const struct mlxsw_reg_info mlxsw_reg_sfmr = {
+ .id = MLXSW_REG_SFMR_ID,
+ .len = MLXSW_REG_SFMR_LEN,
+};
+
+enum mlxsw_reg_sfmr_op {
+ MLXSW_REG_SFMR_OP_CREATE_FID,
+ MLXSW_REG_SFMR_OP_DESTROY_FID,
+};
+
+/* reg_sfmr_op
+ * Operation.
+ * 0 - Create or edit FID.
+ * 1 - Destroy FID.
+ * Access: WO
+ */
+MLXSW_ITEM32(reg, sfmr, op, 0x00, 24, 4);
+
+/* reg_sfmr_fid
+ * Filtering ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sfmr, fid, 0x00, 0, 16);
+
+/* reg_sfmr_fid_offset
+ * FID offset.
+ * Used to point into the flooding table selected by SFGC register if
+ * the table is of type FID-Offset. Otherwise, this field is reserved.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfmr, fid_offset, 0x08, 0, 16);
+
+/* reg_sfmr_vtfp
+ * Valid Tunnel Flood Pointer.
+ * If not set, then nve_tunnel_flood_ptr is reserved and considered NULL.
+ * Access: RW
+ *
+ * Note: Reserved for 802.1Q FIDs.
+ */
+MLXSW_ITEM32(reg, sfmr, vtfp, 0x0C, 31, 1);
+
+/* reg_sfmr_nve_tunnel_flood_ptr
+ * Underlay Flooding and BC Pointer.
+ * Used as a pointer to the first entry of the group based link lists of
+ * flooding or BC entries (for NVE tunnels).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfmr, nve_tunnel_flood_ptr, 0x0C, 0, 24);
+
+/* reg_sfmr_vv
+ * VNI Valid.
+ * If not set, then vni is reserved.
+ * Access: RW
+ *
+ * Note: Reserved for 802.1Q FIDs.
+ */
+MLXSW_ITEM32(reg, sfmr, vv, 0x10, 31, 1);
+
+/* reg_sfmr_vni
+ * Virtual Network Identifier.
+ * Access: RW
+ *
+ * Note: A given VNI can only be assigned to one FID.
+ */
+MLXSW_ITEM32(reg, sfmr, vni, 0x10, 0, 24);
+
+static inline void mlxsw_reg_sfmr_pack(char *payload,
+ enum mlxsw_reg_sfmr_op op, u16 fid,
+ u16 fid_offset)
+{
+ MLXSW_REG_ZERO(sfmr, payload);
+ mlxsw_reg_sfmr_op_set(payload, op);
+ mlxsw_reg_sfmr_fid_set(payload, fid);
+ mlxsw_reg_sfmr_fid_offset_set(payload, fid_offset);
+ mlxsw_reg_sfmr_vtfp_set(payload, false);
+ mlxsw_reg_sfmr_vv_set(payload, false);
+}
+
+/* SPVMLR - Switch Port VLAN MAC Learning Register
+ * -----------------------------------------------
+ * Controls the switch MAC learning policy per {Port, VID}.
+ */
+#define MLXSW_REG_SPVMLR_ID 0x2020
+#define MLXSW_REG_SPVMLR_BASE_LEN 0x04 /* base length, without records */
+#define MLXSW_REG_SPVMLR_REC_LEN 0x04 /* record length */
+#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 256
+#define MLXSW_REG_SPVMLR_LEN (MLXSW_REG_SPVMLR_BASE_LEN + \
+ MLXSW_REG_SPVMLR_REC_LEN * \
+ MLXSW_REG_SPVMLR_REC_MAX_COUNT)
+
+static const struct mlxsw_reg_info mlxsw_reg_spvmlr = {
+ .id = MLXSW_REG_SPVMLR_ID,
+ .len = MLXSW_REG_SPVMLR_LEN,
+};
+
+/* reg_spvmlr_local_port
+ * Local ingress port.
+ * Access: Index
+ *
+ * Note: CPU port is not supported.
+ */
+MLXSW_ITEM32(reg, spvmlr, local_port, 0x00, 16, 8);
+
+/* reg_spvmlr_num_rec
+ * Number of records to update.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, spvmlr, num_rec, 0x00, 0, 8);
+
+/* reg_spvmlr_rec_learn_enable
+ * 0 - Disable learning for {Port, VID}.
+ * 1 - Enable learning for {Port, VID}.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_learn_enable, MLXSW_REG_SPVMLR_BASE_LEN,
+ 31, 1, MLXSW_REG_SPVMLR_REC_LEN, 0x00, false);
+
+/* reg_spvmlr_rec_vid
+ * VLAN ID to be added/removed from port or for querying.
+ * Access: Index
+ */
+MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_vid, MLXSW_REG_SPVMLR_BASE_LEN, 0, 12,
+ MLXSW_REG_SPVMLR_REC_LEN, 0x00, false);
+
+static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port,
+ u16 vid_begin, u16 vid_end,
+ bool learn_enable)
+{
+ int num_rec = vid_end - vid_begin + 1;
+ int i;
+
+ WARN_ON(num_rec < 1 || num_rec > MLXSW_REG_SPVMLR_REC_MAX_COUNT);
+
+ MLXSW_REG_ZERO(spvmlr, payload);
+ mlxsw_reg_spvmlr_local_port_set(payload, local_port);
+ mlxsw_reg_spvmlr_num_rec_set(payload, num_rec);
+
+ for (i = 0; i < num_rec; i++) {
+ mlxsw_reg_spvmlr_rec_learn_enable_set(payload, i, learn_enable);
+ mlxsw_reg_spvmlr_rec_vid_set(payload, i, vid_begin + i);
+ }
+}
+
/* PMLP - Ports Module to Local Port Register
* ------------------------------------------
* Configures the assignment of modules to local ports.
@@ -1008,12 +1732,88 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port)
mlxsw_reg_ppcnt_prio_tc_set(payload, 0);
}
+/* PBMC - Port Buffer Management Control Register
+ * ----------------------------------------------
+ * The PBMC register configures and retrieves the port packet buffer
+ * allocation for different Prios, and the Pause threshold management.
+ */
+#define MLXSW_REG_PBMC_ID 0x500C
+#define MLXSW_REG_PBMC_LEN 0x68
+
+static const struct mlxsw_reg_info mlxsw_reg_pbmc = {
+ .id = MLXSW_REG_PBMC_ID,
+ .len = MLXSW_REG_PBMC_LEN,
+};
+
+/* reg_pbmc_local_port
+ * Local port number.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, pbmc, local_port, 0x00, 16, 8);
+
+/* reg_pbmc_xoff_timer_value
+ * When device generates a pause frame, it uses this value as the pause
+ * timer (time for the peer port to pause in quota-512 bit time).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, pbmc, xoff_timer_value, 0x04, 16, 16);
+
+/* reg_pbmc_xoff_refresh
+ * The time before a new pause frame should be sent to refresh the pause RW
+ * state. Using the same units as xoff_timer_value above (in quota-512 bit
+ * time).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, pbmc, xoff_refresh, 0x04, 0, 16);
+
+/* reg_pbmc_buf_lossy
+ * The field indicates if the buffer is lossy.
+ * 0 - Lossless
+ * 1 - Lossy
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, pbmc, buf_lossy, 0x0C, 25, 1, 0x08, 0x00, false);
+
+/* reg_pbmc_buf_epsb
+ * Eligible for Port Shared buffer.
+ * If epsb is set, packets assigned to buffer are allowed to insert the port
+ * shared buffer.
+ * When buf_lossy is MLXSW_REG_PBMC_LOSSY_LOSSY this field is reserved.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, pbmc, buf_epsb, 0x0C, 24, 1, 0x08, 0x00, false);
+
+/* reg_pbmc_buf_size
+ * The part of the packet buffer array is allocated for the specific buffer.
+ * Units are represented in cells.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, pbmc, buf_size, 0x0C, 0, 16, 0x08, 0x00, false);
+
+static inline void mlxsw_reg_pbmc_pack(char *payload, u8 local_port,
+ u16 xoff_timer_value, u16 xoff_refresh)
+{
+ MLXSW_REG_ZERO(pbmc, payload);
+ mlxsw_reg_pbmc_local_port_set(payload, local_port);
+ mlxsw_reg_pbmc_xoff_timer_value_set(payload, xoff_timer_value);
+ mlxsw_reg_pbmc_xoff_refresh_set(payload, xoff_refresh);
+}
+
+static inline void mlxsw_reg_pbmc_lossy_buffer_pack(char *payload,
+ int buf_index,
+ u16 size)
+{
+ mlxsw_reg_pbmc_buf_lossy_set(payload, buf_index, 1);
+ mlxsw_reg_pbmc_buf_epsb_set(payload, buf_index, 0);
+ mlxsw_reg_pbmc_buf_size_set(payload, buf_index, size);
+}
+
/* PSPA - Port Switch Partition Allocation
* ---------------------------------------
* Controls the association of a port with a switch partition and enables
* configuring ports as stacking ports.
*/
-#define MLXSW_REG_PSPA_ID 0x500d
+#define MLXSW_REG_PSPA_ID 0x500D
#define MLXSW_REG_PSPA_LEN 0x8
static const struct mlxsw_reg_info mlxsw_reg_pspa = {
@@ -1074,8 +1874,11 @@ MLXSW_ITEM32(reg, htgt, swid, 0x00, 24, 8);
*/
MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4);
-#define MLXSW_REG_HTGT_TRAP_GROUP_EMAD 0x0
-#define MLXSW_REG_HTGT_TRAP_GROUP_RX 0x1
+enum mlxsw_reg_htgt_trap_group {
+ MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
+ MLXSW_REG_HTGT_TRAP_GROUP_RX,
+ MLXSW_REG_HTGT_TRAP_GROUP_CTRL,
+};
/* reg_htgt_trap_group
* Trap group number. User defined number specifying which trap groups
@@ -1142,6 +1945,7 @@ MLXSW_ITEM32(reg, htgt, local_path_cpu_tclass, 0x10, 16, 6);
#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD 0x15
#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX 0x14
+#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL 0x13
/* reg_htgt_local_path_rdq
* Receive descriptor queue (RDQ) to use for the trap group.
@@ -1149,21 +1953,29 @@ MLXSW_ITEM32(reg, htgt, local_path_cpu_tclass, 0x10, 16, 6);
*/
MLXSW_ITEM32(reg, htgt, local_path_rdq, 0x10, 0, 6);
-static inline void mlxsw_reg_htgt_pack(char *payload, u8 trap_group)
+static inline void mlxsw_reg_htgt_pack(char *payload,
+ enum mlxsw_reg_htgt_trap_group group)
{
u8 swid, rdq;
MLXSW_REG_ZERO(htgt, payload);
- if (MLXSW_REG_HTGT_TRAP_GROUP_EMAD == trap_group) {
+ switch (group) {
+ case MLXSW_REG_HTGT_TRAP_GROUP_EMAD:
swid = MLXSW_PORT_SWID_ALL_SWIDS;
rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD;
- } else {
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_RX:
swid = 0;
rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_CTRL:
+ swid = 0;
+ rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL;
+ break;
}
mlxsw_reg_htgt_swid_set(payload, swid);
mlxsw_reg_htgt_type_set(payload, MLXSW_REG_HTGT_PATH_TYPE_LOCAL);
- mlxsw_reg_htgt_trap_group_set(payload, trap_group);
+ mlxsw_reg_htgt_trap_group_set(payload, group);
mlxsw_reg_htgt_pide_set(payload, MLXSW_REG_HTGT_POLICER_DISABLE);
mlxsw_reg_htgt_pid_set(payload, 0);
mlxsw_reg_htgt_mirror_action_set(payload, MLXSW_REG_HTGT_TRAP_TO_CPU);
@@ -1254,17 +2066,290 @@ enum {
*/
MLXSW_ITEM32(reg, hpkt, ctrl, 0x04, 16, 2);
-static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action,
- u8 trap_group, u16 trap_id)
+static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id)
{
+ enum mlxsw_reg_htgt_trap_group trap_group;
+
MLXSW_REG_ZERO(hpkt, payload);
mlxsw_reg_hpkt_ack_set(payload, MLXSW_REG_HPKT_ACK_NOT_REQUIRED);
mlxsw_reg_hpkt_action_set(payload, action);
+ switch (trap_id) {
+ case MLXSW_TRAP_ID_ETHEMAD:
+ case MLXSW_TRAP_ID_PUDE:
+ trap_group = MLXSW_REG_HTGT_TRAP_GROUP_EMAD;
+ break;
+ default:
+ trap_group = MLXSW_REG_HTGT_TRAP_GROUP_RX;
+ break;
+ }
mlxsw_reg_hpkt_trap_group_set(payload, trap_group);
mlxsw_reg_hpkt_trap_id_set(payload, trap_id);
mlxsw_reg_hpkt_ctrl_set(payload, MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT);
}
+/* SBPR - Shared Buffer Pools Register
+ * -----------------------------------
+ * The SBPR configures and retrieves the shared buffer pools and configuration.
+ */
+#define MLXSW_REG_SBPR_ID 0xB001
+#define MLXSW_REG_SBPR_LEN 0x14
+
+static const struct mlxsw_reg_info mlxsw_reg_sbpr = {
+ .id = MLXSW_REG_SBPR_ID,
+ .len = MLXSW_REG_SBPR_LEN,
+};
+
+enum mlxsw_reg_sbpr_dir {
+ MLXSW_REG_SBPR_DIR_INGRESS,
+ MLXSW_REG_SBPR_DIR_EGRESS,
+};
+
+/* reg_sbpr_dir
+ * Direction.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbpr, dir, 0x00, 24, 2);
+
+/* reg_sbpr_pool
+ * Pool index.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbpr, pool, 0x00, 0, 4);
+
+/* reg_sbpr_size
+ * Pool size in buffer cells.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbpr, size, 0x04, 0, 24);
+
+enum mlxsw_reg_sbpr_mode {
+ MLXSW_REG_SBPR_MODE_STATIC,
+ MLXSW_REG_SBPR_MODE_DYNAMIC,
+};
+
+/* reg_sbpr_mode
+ * Pool quota calculation mode.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbpr, mode, 0x08, 0, 4);
+
+static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool,
+ enum mlxsw_reg_sbpr_dir dir,
+ enum mlxsw_reg_sbpr_mode mode, u32 size)
+{
+ MLXSW_REG_ZERO(sbpr, payload);
+ mlxsw_reg_sbpr_pool_set(payload, pool);
+ mlxsw_reg_sbpr_dir_set(payload, dir);
+ mlxsw_reg_sbpr_mode_set(payload, mode);
+ mlxsw_reg_sbpr_size_set(payload, size);
+}
+
+/* SBCM - Shared Buffer Class Management Register
+ * ----------------------------------------------
+ * The SBCM register configures and retrieves the shared buffer allocation
+ * and configuration according to Port-PG, including the binding to pool
+ * and definition of the associated quota.
+ */
+#define MLXSW_REG_SBCM_ID 0xB002
+#define MLXSW_REG_SBCM_LEN 0x28
+
+static const struct mlxsw_reg_info mlxsw_reg_sbcm = {
+ .id = MLXSW_REG_SBCM_ID,
+ .len = MLXSW_REG_SBCM_LEN,
+};
+
+/* reg_sbcm_local_port
+ * Local port number.
+ * For Ingress: excludes CPU port and Router port
+ * For Egress: excludes IP Router
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbcm, local_port, 0x00, 16, 8);
+
+/* reg_sbcm_pg_buff
+ * PG buffer - Port PG (dir=ingress) / traffic class (dir=egress)
+ * For PG buffer: range is 0..cap_max_pg_buffers - 1
+ * For traffic class: range is 0..cap_max_tclass - 1
+ * Note that when traffic class is in MC aware mode then the traffic
+ * classes which are MC aware cannot be configured.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbcm, pg_buff, 0x00, 8, 6);
+
+enum mlxsw_reg_sbcm_dir {
+ MLXSW_REG_SBCM_DIR_INGRESS,
+ MLXSW_REG_SBCM_DIR_EGRESS,
+};
+
+/* reg_sbcm_dir
+ * Direction.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbcm, dir, 0x00, 0, 2);
+
+/* reg_sbcm_min_buff
+ * Minimum buffer size for the limiter, in cells.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbcm, min_buff, 0x18, 0, 24);
+
+/* reg_sbcm_max_buff
+ * When the pool associated to the port-pg/tclass is configured to
+ * static, Maximum buffer size for the limiter configured in cells.
+ * When the pool associated to the port-pg/tclass is configured to
+ * dynamic, the max_buff holds the "alpha" parameter, supporting
+ * the following values:
+ * 0: 0
+ * i: (1/128)*2^(i-1), for i=1..14
+ * 0xFF: Infinity
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbcm, max_buff, 0x1C, 0, 24);
+
+/* reg_sbcm_pool
+ * Association of the port-priority to a pool.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbcm, pool, 0x24, 0, 4);
+
+static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff,
+ enum mlxsw_reg_sbcm_dir dir,
+ u32 min_buff, u32 max_buff, u8 pool)
+{
+ MLXSW_REG_ZERO(sbcm, payload);
+ mlxsw_reg_sbcm_local_port_set(payload, local_port);
+ mlxsw_reg_sbcm_pg_buff_set(payload, pg_buff);
+ mlxsw_reg_sbcm_dir_set(payload, dir);
+ mlxsw_reg_sbcm_min_buff_set(payload, min_buff);
+ mlxsw_reg_sbcm_max_buff_set(payload, max_buff);
+ mlxsw_reg_sbcm_pool_set(payload, pool);
+}
+
+/* SBPM - Shared Buffer Class Management Register
+ * ----------------------------------------------
+ * The SBPM register configures and retrieves the shared buffer allocation
+ * and configuration according to Port-Pool, including the definition
+ * of the associated quota.
+ */
+#define MLXSW_REG_SBPM_ID 0xB003
+#define MLXSW_REG_SBPM_LEN 0x28
+
+static const struct mlxsw_reg_info mlxsw_reg_sbpm = {
+ .id = MLXSW_REG_SBPM_ID,
+ .len = MLXSW_REG_SBPM_LEN,
+};
+
+/* reg_sbpm_local_port
+ * Local port number.
+ * For Ingress: excludes CPU port and Router port
+ * For Egress: excludes IP Router
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbpm, local_port, 0x00, 16, 8);
+
+/* reg_sbpm_pool
+ * The pool associated to quota counting on the local_port.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbpm, pool, 0x00, 8, 4);
+
+enum mlxsw_reg_sbpm_dir {
+ MLXSW_REG_SBPM_DIR_INGRESS,
+ MLXSW_REG_SBPM_DIR_EGRESS,
+};
+
+/* reg_sbpm_dir
+ * Direction.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbpm, dir, 0x00, 0, 2);
+
+/* reg_sbpm_min_buff
+ * Minimum buffer size for the limiter, in cells.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbpm, min_buff, 0x18, 0, 24);
+
+/* reg_sbpm_max_buff
+ * When the pool associated to the port-pg/tclass is configured to
+ * static, Maximum buffer size for the limiter configured in cells.
+ * When the pool associated to the port-pg/tclass is configured to
+ * dynamic, the max_buff holds the "alpha" parameter, supporting
+ * the following values:
+ * 0: 0
+ * i: (1/128)*2^(i-1), for i=1..14
+ * 0xFF: Infinity
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbpm, max_buff, 0x1C, 0, 24);
+
+static inline void mlxsw_reg_sbpm_pack(char *payload, u8 local_port, u8 pool,
+ enum mlxsw_reg_sbpm_dir dir,
+ u32 min_buff, u32 max_buff)
+{
+ MLXSW_REG_ZERO(sbpm, payload);
+ mlxsw_reg_sbpm_local_port_set(payload, local_port);
+ mlxsw_reg_sbpm_pool_set(payload, pool);
+ mlxsw_reg_sbpm_dir_set(payload, dir);
+ mlxsw_reg_sbpm_min_buff_set(payload, min_buff);
+ mlxsw_reg_sbpm_max_buff_set(payload, max_buff);
+}
+
+/* SBMM - Shared Buffer Multicast Management Register
+ * --------------------------------------------------
+ * The SBMM register configures and retrieves the shared buffer allocation
+ * and configuration for MC packets according to Switch-Priority, including
+ * the binding to pool and definition of the associated quota.
+ */
+#define MLXSW_REG_SBMM_ID 0xB004
+#define MLXSW_REG_SBMM_LEN 0x28
+
+static const struct mlxsw_reg_info mlxsw_reg_sbmm = {
+ .id = MLXSW_REG_SBMM_ID,
+ .len = MLXSW_REG_SBMM_LEN,
+};
+
+/* reg_sbmm_prio
+ * Switch Priority.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sbmm, prio, 0x00, 8, 4);
+
+/* reg_sbmm_min_buff
+ * Minimum buffer size for the limiter, in cells.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbmm, min_buff, 0x18, 0, 24);
+
+/* reg_sbmm_max_buff
+ * When the pool associated to the port-pg/tclass is configured to
+ * static, Maximum buffer size for the limiter configured in cells.
+ * When the pool associated to the port-pg/tclass is configured to
+ * dynamic, the max_buff holds the "alpha" parameter, supporting
+ * the following values:
+ * 0: 0
+ * i: (1/128)*2^(i-1), for i=1..14
+ * 0xFF: Infinity
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbmm, max_buff, 0x1C, 0, 24);
+
+/* reg_sbmm_pool
+ * Association of the port-priority to a pool.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sbmm, pool, 0x24, 0, 4);
+
+static inline void mlxsw_reg_sbmm_pack(char *payload, u8 prio, u32 min_buff,
+ u32 max_buff, u8 pool)
+{
+ MLXSW_REG_ZERO(sbmm, payload);
+ mlxsw_reg_sbmm_prio_set(payload, prio);
+ mlxsw_reg_sbmm_min_buff_set(payload, min_buff);
+ mlxsw_reg_sbmm_max_buff_set(payload, max_buff);
+ mlxsw_reg_sbmm_pool_set(payload, pool);
+}
+
static inline const char *mlxsw_reg_id_str(u16 reg_id)
{
switch (reg_id) {
@@ -1272,18 +2357,34 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id)
return "SGCR";
case MLXSW_REG_SPAD_ID:
return "SPAD";
- case MLXSW_REG_SMID_ID:
- return "SMID";
case MLXSW_REG_SSPR_ID:
return "SSPR";
+ case MLXSW_REG_SFDAT_ID:
+ return "SFDAT";
+ case MLXSW_REG_SFD_ID:
+ return "SFD";
+ case MLXSW_REG_SFN_ID:
+ return "SFN";
case MLXSW_REG_SPMS_ID:
return "SPMS";
+ case MLXSW_REG_SPVID_ID:
+ return "SPVID";
+ case MLXSW_REG_SPVM_ID:
+ return "SPVM";
case MLXSW_REG_SFGC_ID:
return "SFGC";
case MLXSW_REG_SFTR_ID:
return "SFTR";
case MLXSW_REG_SPMLR_ID:
return "SPMLR";
+ case MLXSW_REG_SVFA_ID:
+ return "SVFA";
+ case MLXSW_REG_SVPE_ID:
+ return "SVPE";
+ case MLXSW_REG_SFMR_ID:
+ return "SFMR";
+ case MLXSW_REG_SPVMLR_ID:
+ return "SPVMLR";
case MLXSW_REG_PMLP_ID:
return "PMLP";
case MLXSW_REG_PMTU_ID:
@@ -1296,12 +2397,22 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id)
return "PAOS";
case MLXSW_REG_PPCNT_ID:
return "PPCNT";
+ case MLXSW_REG_PBMC_ID:
+ return "PBMC";
case MLXSW_REG_PSPA_ID:
return "PSPA";
case MLXSW_REG_HTGT_ID:
return "HTGT";
case MLXSW_REG_HPKT_ID:
return "HPKT";
+ case MLXSW_REG_SBPR_ID:
+ return "SBPR";
+ case MLXSW_REG_SBCM_ID:
+ return "SBCM";
+ case MLXSW_REG_SBPM_ID:
+ return "SBPM";
+ case MLXSW_REG_SBMM_ID:
+ return "SBMM";
default:
return "*UNKNOWN*";
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
new file mode 100644
index 000000000000..3be4a2355ead
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -0,0 +1,1949 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+ * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
+ * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
+ * Copyright (c) 2015 Elad Raz <eladr@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <net/switchdev.h>
+#include <generated/utsrelease.h>
+
+#include "spectrum.h"
+#include "core.h"
+#include "reg.h"
+#include "port.h"
+#include "trap.h"
+#include "txheader.h"
+
+static const char mlxsw_sp_driver_name[] = "mlxsw_spectrum";
+static const char mlxsw_sp_driver_version[] = "1.0";
+
+/* tx_hdr_version
+ * Tx header version.
+ * Must be set to 1.
+ */
+MLXSW_ITEM32(tx, hdr, version, 0x00, 28, 4);
+
+/* tx_hdr_ctl
+ * Packet control type.
+ * 0 - Ethernet control (e.g. EMADs, LACP)
+ * 1 - Ethernet data
+ */
+MLXSW_ITEM32(tx, hdr, ctl, 0x00, 26, 2);
+
+/* tx_hdr_proto
+ * Packet protocol type. Must be set to 1 (Ethernet).
+ */
+MLXSW_ITEM32(tx, hdr, proto, 0x00, 21, 3);
+
+/* tx_hdr_rx_is_router
+ * Packet is sent from the router. Valid for data packets only.
+ */
+MLXSW_ITEM32(tx, hdr, rx_is_router, 0x00, 19, 1);
+
+/* tx_hdr_fid_valid
+ * Indicates if the 'fid' field is valid and should be used for
+ * forwarding lookup. Valid for data packets only.
+ */
+MLXSW_ITEM32(tx, hdr, fid_valid, 0x00, 16, 1);
+
+/* tx_hdr_swid
+ * Switch partition ID. Must be set to 0.
+ */
+MLXSW_ITEM32(tx, hdr, swid, 0x00, 12, 3);
+
+/* tx_hdr_control_tclass
+ * Indicates if the packet should use the control TClass and not one
+ * of the data TClasses.
+ */
+MLXSW_ITEM32(tx, hdr, control_tclass, 0x00, 6, 1);
+
+/* tx_hdr_etclass
+ * Egress TClass to be used on the egress device on the egress port.
+ */
+MLXSW_ITEM32(tx, hdr, etclass, 0x00, 0, 4);
+
+/* tx_hdr_port_mid
+ * Destination local port for unicast packets.
+ * Destination multicast ID for multicast packets.
+ *
+ * Control packets are directed to a specific egress port, while data
+ * packets are transmitted through the CPU port (0) into the switch partition,
+ * where forwarding rules are applied.
+ */
+MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16);
+
+/* tx_hdr_fid
+ * Forwarding ID used for L2 forwarding lookup. Valid only if 'fid_valid' is
+ * set, otherwise calculated based on the packet's VID using VID to FID mapping.
+ * Valid for data packets only.
+ */
+MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16);
+
+/* tx_hdr_type
+ * 0 - Data packets
+ * 6 - Control packets
+ */
+MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
+
+static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
+ const struct mlxsw_tx_info *tx_info)
+{
+ char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
+
+ memset(txhdr, 0, MLXSW_TXHDR_LEN);
+
+ mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1);
+ mlxsw_tx_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
+ mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
+ mlxsw_tx_hdr_swid_set(txhdr, 0);
+ mlxsw_tx_hdr_control_tclass_set(txhdr, 1);
+ mlxsw_tx_hdr_port_mid_set(txhdr, tx_info->local_port);
+ mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
+}
+
+static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
+{
+ char spad_pl[MLXSW_REG_SPAD_LEN];
+ int err;
+
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(spad), spad_pl);
+ if (err)
+ return err;
+ mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sp->base_mac);
+ return 0;
+}
+
+static int mlxsw_sp_port_admin_status_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool is_up)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char paos_pl[MLXSW_REG_PAOS_LEN];
+
+ mlxsw_reg_paos_pack(paos_pl, mlxsw_sp_port->local_port,
+ is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
+ MLXSW_PORT_ADMIN_STATUS_DOWN);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(paos), paos_pl);
+}
+
+static int mlxsw_sp_port_oper_status_get(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool *p_is_up)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char paos_pl[MLXSW_REG_PAOS_LEN];
+ u8 oper_status;
+ int err;
+
+ mlxsw_reg_paos_pack(paos_pl, mlxsw_sp_port->local_port, 0);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(paos), paos_pl);
+ if (err)
+ return err;
+ oper_status = mlxsw_reg_paos_oper_status_get(paos_pl);
+ *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP ? true : false;
+ return 0;
+}
+
+static int mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp, u16 vfid)
+{
+ char sfmr_pl[MLXSW_REG_SFMR_LEN];
+ int err;
+
+ mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
+ MLXSW_SP_VFID_BASE + vfid, 0);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
+
+ if (err)
+ return err;
+
+ set_bit(vfid, mlxsw_sp->active_vfids);
+ return 0;
+}
+
+static void mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp, u16 vfid)
+{
+ char sfmr_pl[MLXSW_REG_SFMR_LEN];
+
+ clear_bit(vfid, mlxsw_sp->active_vfids);
+
+ mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_DESTROY_FID,
+ MLXSW_SP_VFID_BASE + vfid, 0);
+ mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
+}
+
+static int mlxsw_sp_port_dev_addr_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ unsigned char *addr)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char ppad_pl[MLXSW_REG_PPAD_LEN];
+
+ mlxsw_reg_ppad_pack(ppad_pl, true, mlxsw_sp_port->local_port);
+ mlxsw_reg_ppad_mac_memcpy_to(ppad_pl, addr);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ppad), ppad_pl);
+}
+
+static int mlxsw_sp_port_dev_addr_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ unsigned char *addr = mlxsw_sp_port->dev->dev_addr;
+
+ ether_addr_copy(addr, mlxsw_sp->base_mac);
+ addr[ETH_ALEN - 1] += mlxsw_sp_port->local_port;
+ return mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr);
+}
+
+static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 vid, enum mlxsw_reg_spms_state state)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char *spms_pl;
+ int err;
+
+ spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
+ if (!spms_pl)
+ return -ENOMEM;
+ mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
+ mlxsw_reg_spms_vid_pack(spms_pl, vid, state);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
+ kfree(spms_pl);
+ return err;
+}
+
+static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char pmtu_pl[MLXSW_REG_PMTU_LEN];
+ int max_mtu;
+ int err;
+
+ mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
+ mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, 0);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
+ if (err)
+ return err;
+ max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
+
+ if (mtu > max_mtu)
+ return -EINVAL;
+
+ mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, mtu);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
+}
+
+static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char pspa_pl[MLXSW_REG_PSPA_LEN];
+
+ mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl);
+}
+
+static int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool enable)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char svpe_pl[MLXSW_REG_SVPE_LEN];
+
+ mlxsw_reg_svpe_pack(svpe_pl, mlxsw_sp_port->local_port, enable);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svpe), svpe_pl);
+}
+
+int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ enum mlxsw_reg_svfa_mt mt, bool valid, u16 fid,
+ u16 vid)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char svfa_pl[MLXSW_REG_SVFA_LEN];
+
+ mlxsw_reg_svfa_pack(svfa_pl, mlxsw_sp_port->local_port, mt, valid,
+ fid, vid);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
+}
+
+static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 vid, bool learn_enable)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char *spvmlr_pl;
+ int err;
+
+ spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL);
+ if (!spvmlr_pl)
+ return -ENOMEM;
+ mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid, vid,
+ learn_enable);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl);
+ kfree(spvmlr_pl);
+ return err;
+}
+
+static int
+mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char sspr_pl[MLXSW_REG_SSPR_LEN];
+
+ mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sp_port->local_port);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl);
+}
+
+static int mlxsw_sp_port_module_check(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool *p_usable)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char pmlp_pl[MLXSW_REG_PMLP_LEN];
+ int err;
+
+ mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
+ if (err)
+ return err;
+ *p_usable = mlxsw_reg_pmlp_width_get(pmlp_pl) ? true : false;
+ return 0;
+}
+
+static int mlxsw_sp_port_open(struct net_device *dev)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err;
+
+ err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
+ if (err)
+ return err;
+ netif_start_queue(dev);
+ return 0;
+}
+
+static int mlxsw_sp_port_stop(struct net_device *dev)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+ return mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
+}
+
+static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
+ const struct mlxsw_tx_info tx_info = {
+ .local_port = mlxsw_sp_port->local_port,
+ .is_emad = false,
+ };
+ u64 len;
+ int err;
+
+ if (mlxsw_core_skb_transmit_busy(mlxsw_sp, &tx_info))
+ return NETDEV_TX_BUSY;
+
+ if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
+ struct sk_buff *skb_orig = skb;
+
+ skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
+ if (!skb) {
+ this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
+ dev_kfree_skb_any(skb_orig);
+ return NETDEV_TX_OK;
+ }
+ }
+
+ if (eth_skb_pad(skb)) {
+ this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
+ return NETDEV_TX_OK;
+ }
+
+ mlxsw_sp_txhdr_construct(skb, &tx_info);
+ len = skb->len;
+ /* Due to a race we might fail here because of a full queue. In that
+ * unlikely case we simply drop the packet.
+ */
+ err = mlxsw_core_skb_transmit(mlxsw_sp, skb, &tx_info);
+
+ if (!err) {
+ pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
+ u64_stats_update_begin(&pcpu_stats->syncp);
+ pcpu_stats->tx_packets++;
+ pcpu_stats->tx_bytes += len;
+ u64_stats_update_end(&pcpu_stats->syncp);
+ } else {
+ this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
+ dev_kfree_skb_any(skb);
+ }
+ return NETDEV_TX_OK;
+}
+
+static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct sockaddr *addr = p;
+ int err;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ err = mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr->sa_data);
+ if (err)
+ return err;
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ return 0;
+}
+
+static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err;
+
+ err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu);
+ if (err)
+ return err;
+ dev->mtu = mtu;
+ return 0;
+}
+
+static struct rtnl_link_stats64 *
+mlxsw_sp_port_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp_port_pcpu_stats *p;
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ u32 tx_dropped = 0;
+ unsigned int start;
+ int i;
+
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(mlxsw_sp_port->pcpu_stats, i);
+ do {
+ start = u64_stats_fetch_begin_irq(&p->syncp);
+ rx_packets = p->rx_packets;
+ rx_bytes = p->rx_bytes;
+ tx_packets = p->tx_packets;
+ tx_bytes = p->tx_bytes;
+ } while (u64_stats_fetch_retry_irq(&p->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+ stats->tx_packets += tx_packets;
+ stats->tx_bytes += tx_bytes;
+ /* tx_dropped is u32, updated without syncp protection. */
+ tx_dropped += p->tx_dropped;
+ }
+ stats->tx_dropped = tx_dropped;
+ return stats;
+}
+
+int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
+ u16 vid_end, bool is_member, bool untagged)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char *spvm_pl;
+ int err;
+
+ spvm_pl = kmalloc(MLXSW_REG_SPVM_LEN, GFP_KERNEL);
+ if (!spvm_pl)
+ return -ENOMEM;
+
+ mlxsw_reg_spvm_pack(spvm_pl, mlxsw_sp_port->local_port, vid_begin,
+ vid_end, is_member, untagged);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvm), spvm_pl);
+ kfree(spvm_pl);
+ return err;
+}
+
+static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
+ u16 vid, last_visited_vid;
+ int err;
+
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
+ err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, true, vid,
+ vid);
+ if (err) {
+ last_visited_vid = vid;
+ goto err_port_vid_to_fid_set;
+ }
+ }
+
+ err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
+ if (err) {
+ last_visited_vid = VLAN_N_VID;
+ goto err_port_vid_to_fid_set;
+ }
+
+ return 0;
+
+err_port_vid_to_fid_set:
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, last_visited_vid)
+ mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, vid,
+ vid);
+ return err;
+}
+
+static int mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
+ u16 vid;
+ int err;
+
+ err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
+ if (err)
+ return err;
+
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
+ err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false,
+ vid, vid);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
+ u16 vid)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char *sftr_pl;
+ int err;
+
+ /* VLAN 0 is added to HW filter when device goes up, but it is
+ * reserved in our case, so simply return.
+ */
+ if (!vid)
+ return 0;
+
+ if (test_bit(vid, mlxsw_sp_port->active_vfids)) {
+ netdev_warn(dev, "VID=%d already configured\n", vid);
+ return 0;
+ }
+
+ if (!test_bit(vid, mlxsw_sp->active_vfids)) {
+ err = mlxsw_sp_vfid_create(mlxsw_sp, vid);
+ if (err) {
+ netdev_err(dev, "Failed to create vFID=%d\n",
+ MLXSW_SP_VFID_BASE + vid);
+ return err;
+ }
+
+ sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
+ if (!sftr_pl) {
+ err = -ENOMEM;
+ goto err_flood_table_alloc;
+ }
+ mlxsw_reg_sftr_pack(sftr_pl, 0, vid,
+ MLXSW_REG_SFGC_TABLE_TYPE_FID, 0,
+ MLXSW_PORT_CPU_PORT, true);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
+ kfree(sftr_pl);
+ if (err) {
+ netdev_err(dev, "Failed to configure flood table\n");
+ goto err_flood_table_config;
+ }
+ }
+
+ /* In case we fail in the following steps, we intentionally do not
+ * destroy the associated vFID.
+ */
+
+ /* When adding the first VLAN interface on a bridged port we need to
+ * transition all the active 802.1Q bridge VLANs to use explicit
+ * {Port, VID} to FID mappings and set the port's mode to Virtual mode.
+ */
+ if (!mlxsw_sp_port->nr_vfids) {
+ err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
+ if (err) {
+ netdev_err(dev, "Failed to set to Virtual mode\n");
+ return err;
+ }
+ }
+
+ err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port,
+ MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
+ true, MLXSW_SP_VFID_BASE + vid, vid);
+ if (err) {
+ netdev_err(dev, "Failed to map {Port, VID=%d} to vFID=%d\n",
+ vid, MLXSW_SP_VFID_BASE + vid);
+ goto err_port_vid_to_fid_set;
+ }
+
+ err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
+ if (err) {
+ netdev_err(dev, "Failed to disable learning for VID=%d\n", vid);
+ goto err_port_vid_learning_set;
+ }
+
+ err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true, false);
+ if (err) {
+ netdev_err(dev, "Failed to set VLAN membership for VID=%d\n",
+ vid);
+ goto err_port_add_vid;
+ }
+
+ err = mlxsw_sp_port_stp_state_set(mlxsw_sp_port, vid,
+ MLXSW_REG_SPMS_STATE_FORWARDING);
+ if (err) {
+ netdev_err(dev, "Failed to set STP state for VID=%d\n", vid);
+ goto err_port_stp_state_set;
+ }
+
+ mlxsw_sp_port->nr_vfids++;
+ set_bit(vid, mlxsw_sp_port->active_vfids);
+
+ return 0;
+
+err_flood_table_config:
+err_flood_table_alloc:
+ mlxsw_sp_vfid_destroy(mlxsw_sp, vid);
+ return err;
+
+err_port_stp_state_set:
+ mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
+err_port_add_vid:
+ mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
+err_port_vid_learning_set:
+ mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port,
+ MLXSW_REG_SVFA_MT_PORT_VID_TO_FID, false,
+ MLXSW_SP_VFID_BASE + vid, vid);
+err_port_vid_to_fid_set:
+ mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
+ return err;
+}
+
+int mlxsw_sp_port_kill_vid(struct net_device *dev,
+ __be16 __always_unused proto, u16 vid)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err;
+
+ /* VLAN 0 is removed from HW filter when device goes down, but
+ * it is reserved in our case, so simply return.
+ */
+ if (!vid)
+ return 0;
+
+ if (!test_bit(vid, mlxsw_sp_port->active_vfids)) {
+ netdev_warn(dev, "VID=%d does not exist\n", vid);
+ return 0;
+ }
+
+ err = mlxsw_sp_port_stp_state_set(mlxsw_sp_port, vid,
+ MLXSW_REG_SPMS_STATE_DISCARDING);
+ if (err) {
+ netdev_err(dev, "Failed to set STP state for VID=%d\n", vid);
+ return err;
+ }
+
+ err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
+ if (err) {
+ netdev_err(dev, "Failed to set VLAN membership for VID=%d\n",
+ vid);
+ return err;
+ }
+
+ err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
+ if (err) {
+ netdev_err(dev, "Failed to enable learning for VID=%d\n", vid);
+ return err;
+ }
+
+ err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port,
+ MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
+ false, MLXSW_SP_VFID_BASE + vid,
+ vid);
+ if (err) {
+ netdev_err(dev, "Failed to invalidate {Port, VID=%d} to vFID=%d mapping\n",
+ vid, MLXSW_SP_VFID_BASE + vid);
+ return err;
+ }
+
+ /* When removing the last VLAN interface on a bridged port we need to
+ * transition all active 802.1Q bridge VLANs to use VID to FID
+ * mappings and set port's mode to VLAN mode.
+ */
+ if (mlxsw_sp_port->nr_vfids == 1) {
+ err = mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
+ if (err) {
+ netdev_err(dev, "Failed to set to VLAN mode\n");
+ return err;
+ }
+ }
+
+ mlxsw_sp_port->nr_vfids--;
+ clear_bit(vid, mlxsw_sp_port->active_vfids);
+
+ 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,
+ .ndo_start_xmit = mlxsw_sp_port_xmit,
+ .ndo_set_mac_address = mlxsw_sp_port_set_mac_address,
+ .ndo_change_mtu = mlxsw_sp_port_change_mtu,
+ .ndo_get_stats64 = mlxsw_sp_port_get_stats64,
+ .ndo_vlan_rx_add_vid = mlxsw_sp_port_add_vid,
+ .ndo_vlan_rx_kill_vid = mlxsw_sp_port_kill_vid,
+ .ndo_fdb_add = switchdev_port_fdb_add,
+ .ndo_fdb_del = switchdev_port_fdb_del,
+ .ndo_fdb_dump = switchdev_port_fdb_dump,
+ .ndo_bridge_setlink = switchdev_port_bridge_setlink,
+ .ndo_bridge_getlink = switchdev_port_bridge_getlink,
+ .ndo_bridge_dellink = switchdev_port_bridge_dellink,
+};
+
+static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+ strlcpy(drvinfo->driver, mlxsw_sp_driver_name, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, mlxsw_sp_driver_version,
+ sizeof(drvinfo->version));
+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+ "%d.%d.%d",
+ mlxsw_sp->bus_info->fw_rev.major,
+ mlxsw_sp->bus_info->fw_rev.minor,
+ mlxsw_sp->bus_info->fw_rev.subminor);
+ strlcpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name,
+ sizeof(drvinfo->bus_info));
+}
+
+struct mlxsw_sp_port_hw_stats {
+ char str[ETH_GSTRING_LEN];
+ u64 (*getter)(char *payload);
+};
+
+static const struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
+ {
+ .str = "a_frames_transmitted_ok",
+ .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get,
+ },
+ {
+ .str = "a_frames_received_ok",
+ .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get,
+ },
+ {
+ .str = "a_frame_check_sequence_errors",
+ .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get,
+ },
+ {
+ .str = "a_alignment_errors",
+ .getter = mlxsw_reg_ppcnt_a_alignment_errors_get,
+ },
+ {
+ .str = "a_octets_transmitted_ok",
+ .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get,
+ },
+ {
+ .str = "a_octets_received_ok",
+ .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get,
+ },
+ {
+ .str = "a_multicast_frames_xmitted_ok",
+ .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get,
+ },
+ {
+ .str = "a_broadcast_frames_xmitted_ok",
+ .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get,
+ },
+ {
+ .str = "a_multicast_frames_received_ok",
+ .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get,
+ },
+ {
+ .str = "a_broadcast_frames_received_ok",
+ .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get,
+ },
+ {
+ .str = "a_in_range_length_errors",
+ .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get,
+ },
+ {
+ .str = "a_out_of_range_length_field",
+ .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get,
+ },
+ {
+ .str = "a_frame_too_long_errors",
+ .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get,
+ },
+ {
+ .str = "a_symbol_error_during_carrier",
+ .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get,
+ },
+ {
+ .str = "a_mac_control_frames_transmitted",
+ .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get,
+ },
+ {
+ .str = "a_mac_control_frames_received",
+ .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get,
+ },
+ {
+ .str = "a_unsupported_opcodes_received",
+ .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get,
+ },
+ {
+ .str = "a_pause_mac_ctrl_frames_received",
+ .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get,
+ },
+ {
+ .str = "a_pause_mac_ctrl_frames_xmitted",
+ .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get,
+ },
+};
+
+#define MLXSW_SP_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_stats)
+
+static void mlxsw_sp_port_get_strings(struct net_device *dev,
+ u32 stringset, u8 *data)
+{
+ u8 *p = data;
+ int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) {
+ memcpy(p, mlxsw_sp_port_hw_stats[i].str,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
+ }
+}
+
+static void mlxsw_sp_port_get_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
+ int i;
+ int err;
+
+ mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl);
+ for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++)
+ data[i] = !err ? mlxsw_sp_port_hw_stats[i].getter(ppcnt_pl) : 0;
+}
+
+static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return MLXSW_SP_PORT_HW_STATS_LEN;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+struct mlxsw_sp_port_link_mode {
+ u32 mask;
+ u32 supported;
+ u32 advertised;
+ u32 speed;
+};
+
+static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = {
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
+ .supported = SUPPORTED_100baseT_Full,
+ .advertised = ADVERTISED_100baseT_Full,
+ .speed = 100,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX,
+ .speed = 100,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
+ MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
+ .supported = SUPPORTED_1000baseKX_Full,
+ .advertised = ADVERTISED_1000baseKX_Full,
+ .speed = 1000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
+ .supported = SUPPORTED_10000baseT_Full,
+ .advertised = ADVERTISED_10000baseT_Full,
+ .speed = 10000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
+ MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
+ .supported = SUPPORTED_10000baseKX4_Full,
+ .advertised = ADVERTISED_10000baseKX4_Full,
+ .speed = 10000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
+ MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
+ MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
+ MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
+ .supported = SUPPORTED_10000baseKR_Full,
+ .advertised = ADVERTISED_10000baseKR_Full,
+ .speed = 10000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
+ .supported = SUPPORTED_20000baseKR2_Full,
+ .advertised = ADVERTISED_20000baseKR2_Full,
+ .speed = 20000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
+ .supported = SUPPORTED_40000baseCR4_Full,
+ .advertised = ADVERTISED_40000baseCR4_Full,
+ .speed = 40000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
+ .supported = SUPPORTED_40000baseKR4_Full,
+ .advertised = ADVERTISED_40000baseKR4_Full,
+ .speed = 40000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
+ .supported = SUPPORTED_40000baseSR4_Full,
+ .advertised = ADVERTISED_40000baseSR4_Full,
+ .speed = 40000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
+ .supported = SUPPORTED_40000baseLR4_Full,
+ .advertised = ADVERTISED_40000baseLR4_Full,
+ .speed = 40000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR |
+ MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR |
+ MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
+ .speed = 25000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 |
+ MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
+ .speed = 50000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
+ .supported = SUPPORTED_56000baseKR4_Full,
+ .advertised = ADVERTISED_56000baseKR4_Full,
+ .speed = 56000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
+ .speed = 100000,
+ },
+};
+
+#define MLXSW_SP_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp_port_link_mode)
+
+static u32 mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto)
+{
+ if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
+ MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
+ MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_SGMII))
+ return SUPPORTED_FIBRE;
+
+ 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 |
+ MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
+ return SUPPORTED_Backplane;
+ return 0;
+}
+
+static u32 mlxsw_sp_from_ptys_supported_link(u32 ptys_eth_proto)
+{
+ u32 modes = 0;
+ int i;
+
+ for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
+ if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask)
+ modes |= mlxsw_sp_port_link_mode[i].supported;
+ }
+ return modes;
+}
+
+static u32 mlxsw_sp_from_ptys_advert_link(u32 ptys_eth_proto)
+{
+ u32 modes = 0;
+ int i;
+
+ for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
+ if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask)
+ modes |= mlxsw_sp_port_link_mode[i].advertised;
+ }
+ return modes;
+}
+
+static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
+ struct ethtool_cmd *cmd)
+{
+ u32 speed = SPEED_UNKNOWN;
+ u8 duplex = DUPLEX_UNKNOWN;
+ int i;
+
+ 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;
+ duplex = DUPLEX_FULL;
+ break;
+ }
+ }
+out:
+ ethtool_cmd_speed_set(cmd, speed);
+ cmd->duplex = duplex;
+}
+
+static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto)
+{
+ 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;
+
+ 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;
+
+ 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;
+
+ return PORT_OTHER;
+}
+
+static int mlxsw_sp_port_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char ptys_pl[MLXSW_REG_PTYS_LEN];
+ u32 eth_proto_cap;
+ u32 eth_proto_admin;
+ u32 eth_proto_oper;
+ int err;
+
+ mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
+ if (err) {
+ netdev_err(dev, "Failed to get proto");
+ return err;
+ }
+ mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap,
+ &eth_proto_admin, &eth_proto_oper);
+
+ cmd->supported = mlxsw_sp_from_ptys_supported_port(eth_proto_cap) |
+ mlxsw_sp_from_ptys_supported_link(eth_proto_cap) |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ cmd->advertising = mlxsw_sp_from_ptys_advert_link(eth_proto_admin);
+ mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev),
+ eth_proto_oper, cmd);
+
+ eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
+ cmd->port = mlxsw_sp_port_connector_port(eth_proto_oper);
+ cmd->lp_advertising = mlxsw_sp_from_ptys_advert_link(eth_proto_oper);
+
+ cmd->transceiver = XCVR_INTERNAL;
+ return 0;
+}
+
+static u32 mlxsw_sp_to_ptys_advert_link(u32 advertising)
+{
+ u32 ptys_proto = 0;
+ int i;
+
+ for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
+ if (advertising & mlxsw_sp_port_link_mode[i].advertised)
+ ptys_proto |= mlxsw_sp_port_link_mode[i].mask;
+ }
+ return ptys_proto;
+}
+
+static u32 mlxsw_sp_to_ptys_speed(u32 speed)
+{
+ 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;
+ }
+ return ptys_proto;
+}
+
+static int mlxsw_sp_port_set_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char ptys_pl[MLXSW_REG_PTYS_LEN];
+ u32 speed;
+ u32 eth_proto_new;
+ u32 eth_proto_cap;
+ u32 eth_proto_admin;
+ bool is_up;
+ int err;
+
+ speed = ethtool_cmd_speed(cmd);
+
+ eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ?
+ mlxsw_sp_to_ptys_advert_link(cmd->advertising) :
+ mlxsw_sp_to_ptys_speed(speed);
+
+ mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
+ if (err) {
+ netdev_err(dev, "Failed to get proto");
+ return err;
+ }
+ mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin, NULL);
+
+ eth_proto_new = eth_proto_new & eth_proto_cap;
+ if (!eth_proto_new) {
+ netdev_err(dev, "Not supported proto admin requested");
+ return -EINVAL;
+ }
+ if (eth_proto_new == eth_proto_admin)
+ return 0;
+
+ mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
+ if (err) {
+ netdev_err(dev, "Failed to set proto admin");
+ return err;
+ }
+
+ err = mlxsw_sp_port_oper_status_get(mlxsw_sp_port, &is_up);
+ if (err) {
+ netdev_err(dev, "Failed to get oper status");
+ return err;
+ }
+ if (!is_up)
+ return 0;
+
+ err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
+ if (err) {
+ netdev_err(dev, "Failed to set admin status");
+ return err;
+ }
+
+ err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
+ if (err) {
+ netdev_err(dev, "Failed to set admin status");
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
+ .get_drvinfo = mlxsw_sp_port_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_strings = mlxsw_sp_port_get_strings,
+ .get_ethtool_stats = mlxsw_sp_port_get_stats,
+ .get_sset_count = mlxsw_sp_port_get_sset_count,
+ .get_settings = mlxsw_sp_port_get_settings,
+ .set_settings = mlxsw_sp_port_set_settings,
+};
+
+static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port;
+ struct net_device *dev;
+ bool usable;
+ int err;
+
+ dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
+ if (!dev)
+ return -ENOMEM;
+ mlxsw_sp_port = netdev_priv(dev);
+ mlxsw_sp_port->dev = dev;
+ mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
+ mlxsw_sp_port->local_port = local_port;
+ mlxsw_sp_port->learning = 1;
+ mlxsw_sp_port->learning_sync = 1;
+ mlxsw_sp_port->uc_flood = 1;
+ mlxsw_sp_port->pvid = 1;
+
+ mlxsw_sp_port->pcpu_stats =
+ netdev_alloc_pcpu_stats(struct mlxsw_sp_port_pcpu_stats);
+ if (!mlxsw_sp_port->pcpu_stats) {
+ err = -ENOMEM;
+ goto err_alloc_stats;
+ }
+
+ dev->netdev_ops = &mlxsw_sp_port_netdev_ops;
+ dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops;
+
+ err = mlxsw_sp_port_dev_addr_init(mlxsw_sp_port);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unable to init port mac address\n",
+ mlxsw_sp_port->local_port);
+ goto err_dev_addr_init;
+ }
+
+ netif_carrier_off(dev);
+
+ dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
+ NETIF_F_HW_VLAN_CTAG_FILTER;
+
+ /* Each packet needs to have a Tx header (metadata) on top all other
+ * headers.
+ */
+ dev->hard_header_len += MLXSW_TXHDR_LEN;
+
+ err = mlxsw_sp_port_module_check(mlxsw_sp_port, &usable);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to check module\n",
+ mlxsw_sp_port->local_port);
+ goto err_port_module_check;
+ }
+
+ if (!usable) {
+ dev_dbg(mlxsw_sp->bus_info->dev, "Port %d: Not usable, skipping initialization\n",
+ mlxsw_sp_port->local_port);
+ goto port_not_usable;
+ }
+
+ err = mlxsw_sp_port_system_port_mapping_set(mlxsw_sp_port);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set system port mapping\n",
+ mlxsw_sp_port->local_port);
+ goto err_port_system_port_mapping_set;
+ }
+
+ err = mlxsw_sp_port_swid_set(mlxsw_sp_port, 0);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n",
+ mlxsw_sp_port->local_port);
+ goto err_port_swid_set;
+ }
+
+ err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, ETH_DATA_LEN);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set MTU\n",
+ mlxsw_sp_port->local_port);
+ goto err_port_mtu_set;
+ }
+
+ err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
+ if (err)
+ goto err_port_admin_status_set;
+
+ err = mlxsw_sp_port_buffers_init(mlxsw_sp_port);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize buffers\n",
+ mlxsw_sp_port->local_port);
+ goto err_port_buffers_init;
+ }
+
+ mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register netdev\n",
+ mlxsw_sp_port->local_port);
+ goto err_register_netdev;
+ }
+
+ err = mlxsw_sp_port_vlan_init(mlxsw_sp_port);
+ if (err)
+ goto err_port_vlan_init;
+
+ mlxsw_sp->ports[local_port] = mlxsw_sp_port;
+ return 0;
+
+err_port_vlan_init:
+ unregister_netdev(dev);
+err_register_netdev:
+err_port_buffers_init:
+err_port_admin_status_set:
+err_port_mtu_set:
+err_port_swid_set:
+err_port_system_port_mapping_set:
+port_not_usable:
+err_port_module_check:
+err_dev_addr_init:
+ free_percpu(mlxsw_sp_port->pcpu_stats);
+err_alloc_stats:
+ free_netdev(dev);
+ return err;
+}
+
+static void mlxsw_sp_vfids_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ u16 vfid;
+
+ for_each_set_bit(vfid, mlxsw_sp->active_vfids, VLAN_N_VID)
+ mlxsw_sp_vfid_destroy(mlxsw_sp, vfid);
+}
+
+static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
+
+ if (!mlxsw_sp_port)
+ return;
+ mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
+ unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
+ mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
+ free_percpu(mlxsw_sp_port->pcpu_stats);
+ free_netdev(mlxsw_sp_port->dev);
+}
+
+static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
+{
+ int i;
+
+ for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
+ mlxsw_sp_port_remove(mlxsw_sp, i);
+ kfree(mlxsw_sp->ports);
+}
+
+static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
+{
+ size_t alloc_size;
+ int i;
+ int err;
+
+ alloc_size = sizeof(struct mlxsw_sp_port *) * MLXSW_PORT_MAX_PORTS;
+ mlxsw_sp->ports = kzalloc(alloc_size, GFP_KERNEL);
+ if (!mlxsw_sp->ports)
+ return -ENOMEM;
+
+ for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
+ err = mlxsw_sp_port_create(mlxsw_sp, i);
+ if (err)
+ goto err_port_create;
+ }
+ return 0;
+
+err_port_create:
+ for (i--; i >= 1; i--)
+ mlxsw_sp_port_remove(mlxsw_sp, i);
+ kfree(mlxsw_sp->ports);
+ return err;
+}
+
+static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
+ char *pude_pl, void *priv)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+ struct mlxsw_sp_port *mlxsw_sp_port;
+ enum mlxsw_reg_pude_oper_status status;
+ u8 local_port;
+
+ local_port = mlxsw_reg_pude_local_port_get(pude_pl);
+ mlxsw_sp_port = mlxsw_sp->ports[local_port];
+ if (!mlxsw_sp_port) {
+ dev_warn(mlxsw_sp->bus_info->dev, "Port %d: Link event received for non-existent port\n",
+ local_port);
+ return;
+ }
+
+ status = mlxsw_reg_pude_oper_status_get(pude_pl);
+ if (status == MLXSW_PORT_OPER_STATUS_UP) {
+ netdev_info(mlxsw_sp_port->dev, "link up\n");
+ netif_carrier_on(mlxsw_sp_port->dev);
+ } else {
+ netdev_info(mlxsw_sp_port->dev, "link down\n");
+ netif_carrier_off(mlxsw_sp_port->dev);
+ }
+}
+
+static struct mlxsw_event_listener mlxsw_sp_pude_event = {
+ .func = mlxsw_sp_pude_event_func,
+ .trap_id = MLXSW_TRAP_ID_PUDE,
+};
+
+static int mlxsw_sp_event_register(struct mlxsw_sp *mlxsw_sp,
+ enum mlxsw_event_trap_id trap_id)
+{
+ struct mlxsw_event_listener *el;
+ char hpkt_pl[MLXSW_REG_HPKT_LEN];
+ int err;
+
+ switch (trap_id) {
+ case MLXSW_TRAP_ID_PUDE:
+ el = &mlxsw_sp_pude_event;
+ break;
+ }
+ err = mlxsw_core_event_listener_register(mlxsw_sp->core, el, mlxsw_sp);
+ if (err)
+ return err;
+
+ mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
+ if (err)
+ goto err_event_trap_set;
+
+ return 0;
+
+err_event_trap_set:
+ mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp);
+ return err;
+}
+
+static void mlxsw_sp_event_unregister(struct mlxsw_sp *mlxsw_sp,
+ enum mlxsw_event_trap_id trap_id)
+{
+ struct mlxsw_event_listener *el;
+
+ switch (trap_id) {
+ case MLXSW_TRAP_ID_PUDE:
+ el = &mlxsw_sp_pude_event;
+ break;
+ }
+ mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp);
+}
+
+static void mlxsw_sp_rx_listener_func(struct sk_buff *skb, u8 local_port,
+ void *priv)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+ struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
+ struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
+
+ if (unlikely(!mlxsw_sp_port)) {
+ dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
+ local_port);
+ return;
+ }
+
+ skb->dev = mlxsw_sp_port->dev;
+
+ pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
+ u64_stats_update_begin(&pcpu_stats->syncp);
+ pcpu_stats->rx_packets++;
+ pcpu_stats->rx_bytes += skb->len;
+ u64_stats_update_end(&pcpu_stats->syncp);
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ netif_receive_skb(skb);
+}
+
+static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = {
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_FDB_MC,
+ },
+ /* Traps for specific L2 packet types, not trapped as FDB MC */
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_STP,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_LACP,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_EAPOL,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_LLDP,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_MMRP,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_MVRP,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_RPVST,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_DHCP,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_IGMP_QUERY,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_IGMP_V1_REPORT,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_IGMP_V2_REPORT,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_IGMP_V2_LEAVE,
+ },
+ {
+ .func = mlxsw_sp_rx_listener_func,
+ .local_port = MLXSW_PORT_DONT_CARE,
+ .trap_id = MLXSW_TRAP_ID_IGMP_V3_REPORT,
+ },
+};
+
+static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
+{
+ char htgt_pl[MLXSW_REG_HTGT_LEN];
+ char hpkt_pl[MLXSW_REG_HPKT_LEN];
+ int i;
+ int err;
+
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
+ if (err)
+ return err;
+
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
+ if (err)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) {
+ err = mlxsw_core_rx_listener_register(mlxsw_sp->core,
+ &mlxsw_sp_rx_listener[i],
+ mlxsw_sp);
+ if (err)
+ goto err_rx_listener_register;
+
+ mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
+ mlxsw_sp_rx_listener[i].trap_id);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
+ if (err)
+ goto err_rx_trap_set;
+ }
+ return 0;
+
+err_rx_trap_set:
+ mlxsw_core_rx_listener_unregister(mlxsw_sp->core,
+ &mlxsw_sp_rx_listener[i],
+ mlxsw_sp);
+err_rx_listener_register:
+ for (i--; i >= 0; i--) {
+ mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
+ mlxsw_sp_rx_listener[i].trap_id);
+ mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
+
+ mlxsw_core_rx_listener_unregister(mlxsw_sp->core,
+ &mlxsw_sp_rx_listener[i],
+ mlxsw_sp);
+ }
+ return err;
+}
+
+static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ char hpkt_pl[MLXSW_REG_HPKT_LEN];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) {
+ mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
+ mlxsw_sp_rx_listener[i].trap_id);
+ mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
+
+ mlxsw_core_rx_listener_unregister(mlxsw_sp->core,
+ &mlxsw_sp_rx_listener[i],
+ mlxsw_sp);
+ }
+}
+
+static int __mlxsw_sp_flood_init(struct mlxsw_core *mlxsw_core,
+ enum mlxsw_reg_sfgc_type type,
+ enum mlxsw_reg_sfgc_bridge_type bridge_type)
+{
+ enum mlxsw_flood_table_type table_type;
+ enum mlxsw_sp_flood_table flood_table;
+ char sfgc_pl[MLXSW_REG_SFGC_LEN];
+
+ if (bridge_type == MLXSW_REG_SFGC_BRIDGE_TYPE_VFID) {
+ table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID;
+ flood_table = 0;
+ } else {
+ table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST;
+ if (type == MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST)
+ flood_table = MLXSW_SP_FLOOD_TABLE_UC;
+ else
+ flood_table = MLXSW_SP_FLOOD_TABLE_BM;
+ }
+
+ mlxsw_reg_sfgc_pack(sfgc_pl, type, bridge_type, table_type,
+ flood_table);
+ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(sfgc), sfgc_pl);
+}
+
+static int mlxsw_sp_flood_init(struct mlxsw_sp *mlxsw_sp)
+{
+ int type, err;
+
+ /* For non-offloaded netdevs, flood all traffic types to CPU
+ * port.
+ */
+ for (type = 0; type < MLXSW_REG_SFGC_TYPE_MAX; type++) {
+ if (type == MLXSW_REG_SFGC_TYPE_RESERVED)
+ continue;
+
+ err = __mlxsw_sp_flood_init(mlxsw_sp->core, type,
+ MLXSW_REG_SFGC_BRIDGE_TYPE_VFID);
+ if (err)
+ return err;
+ }
+
+ /* For bridged ports, use one flooding table for unknown unicast
+ * traffic and a second table for unregistered multicast and
+ * broadcast.
+ */
+ for (type = 0; type < MLXSW_REG_SFGC_TYPE_MAX; type++) {
+ if (type == MLXSW_REG_SFGC_TYPE_RESERVED)
+ continue;
+
+ err = __mlxsw_sp_flood_init(mlxsw_sp->core, type,
+ MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int mlxsw_sp_init(void *priv, struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_bus_info *mlxsw_bus_info)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+ int err;
+
+ mlxsw_sp->core = mlxsw_core;
+ mlxsw_sp->bus_info = mlxsw_bus_info;
+
+ err = mlxsw_sp_base_mac_get(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to get base mac\n");
+ return err;
+ }
+
+ err = mlxsw_sp_ports_create(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n");
+ goto err_ports_create;
+ }
+
+ err = mlxsw_sp_event_register(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to register for PUDE events\n");
+ goto err_event_register;
+ }
+
+ err = mlxsw_sp_traps_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps for RX\n");
+ goto err_rx_listener_register;
+ }
+
+ err = mlxsw_sp_flood_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize flood tables\n");
+ goto err_flood_init;
+ }
+
+ err = mlxsw_sp_buffers_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize buffers\n");
+ goto err_buffers_init;
+ }
+
+ err = mlxsw_sp_switchdev_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
+ goto err_switchdev_init;
+ }
+
+ return 0;
+
+err_switchdev_init:
+err_buffers_init:
+err_flood_init:
+ mlxsw_sp_traps_fini(mlxsw_sp);
+err_rx_listener_register:
+ mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
+err_event_register:
+ mlxsw_sp_ports_remove(mlxsw_sp);
+err_ports_create:
+ mlxsw_sp_vfids_fini(mlxsw_sp);
+ return err;
+}
+
+static void mlxsw_sp_fini(void *priv)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+
+ mlxsw_sp_switchdev_fini(mlxsw_sp);
+ mlxsw_sp_traps_fini(mlxsw_sp);
+ mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
+ mlxsw_sp_ports_remove(mlxsw_sp);
+ mlxsw_sp_vfids_fini(mlxsw_sp);
+}
+
+static struct mlxsw_config_profile mlxsw_sp_config_profile = {
+ .used_max_vepa_channels = 1,
+ .max_vepa_channels = 0,
+ .used_max_lag = 1,
+ .max_lag = 64,
+ .used_max_port_per_lag = 1,
+ .max_port_per_lag = 16,
+ .used_max_mid = 1,
+ .max_mid = 7000,
+ .used_max_pgt = 1,
+ .max_pgt = 0,
+ .used_max_system_port = 1,
+ .max_system_port = 64,
+ .used_max_vlan_groups = 1,
+ .max_vlan_groups = 127,
+ .used_max_regions = 1,
+ .max_regions = 400,
+ .used_flood_tables = 1,
+ .used_flood_mode = 1,
+ .flood_mode = 3,
+ .max_fid_offset_flood_tables = 2,
+ .fid_offset_flood_table_size = VLAN_N_VID - 1,
+ .max_fid_flood_tables = 1,
+ .fid_flood_table_size = VLAN_N_VID,
+ .used_max_ib_mc = 1,
+ .max_ib_mc = 0,
+ .used_max_pkey = 1,
+ .max_pkey = 0,
+ .swid_config = {
+ {
+ .used_type = 1,
+ .type = MLXSW_PORT_SWID_TYPE_ETH,
+ }
+ },
+};
+
+static struct mlxsw_driver mlxsw_sp_driver = {
+ .kind = MLXSW_DEVICE_KIND_SPECTRUM,
+ .owner = THIS_MODULE,
+ .priv_size = sizeof(struct mlxsw_sp),
+ .init = mlxsw_sp_init,
+ .fini = mlxsw_sp_fini,
+ .txhdr_construct = mlxsw_sp_txhdr_construct,
+ .txhdr_len = MLXSW_TXHDR_LEN,
+ .profile = &mlxsw_sp_config_profile,
+};
+
+static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
+{
+ return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
+}
+
+static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct net_device *dev = mlxsw_sp_port->dev;
+ int err;
+
+ /* When port is not bridged untagged packets are tagged with
+ * PVID=VID=1, thereby creating an implicit VLAN interface in
+ * the device. Remove it and let bridge code take care of its
+ * own VLANs.
+ */
+ err = mlxsw_sp_port_kill_vid(dev, 0, 1);
+ if (err)
+ netdev_err(dev, "Failed to remove VID 1\n");
+
+ return err;
+}
+
+static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct net_device *dev = mlxsw_sp_port->dev;
+ int err;
+
+ /* Add implicit VLAN interface in the device, so that untagged
+ * packets will be classified to the default vFID.
+ */
+ err = mlxsw_sp_port_add_vid(dev, 0, 1);
+ if (err)
+ netdev_err(dev, "Failed to add VID 1\n");
+
+ return err;
+}
+
+static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
+ struct net_device *br_dev)
+{
+ return !mlxsw_sp->master_bridge.dev ||
+ mlxsw_sp->master_bridge.dev == br_dev;
+}
+
+static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
+ struct net_device *br_dev)
+{
+ mlxsw_sp->master_bridge.dev = br_dev;
+ mlxsw_sp->master_bridge.ref_count++;
+}
+
+static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp,
+ struct net_device *br_dev)
+{
+ if (--mlxsw_sp->master_bridge.ref_count == 0)
+ mlxsw_sp->master_bridge.dev = NULL;
+}
+
+static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct netdev_notifier_changeupper_info *info;
+ struct mlxsw_sp_port *mlxsw_sp_port;
+ struct net_device *upper_dev;
+ struct mlxsw_sp *mlxsw_sp;
+ int err;
+
+ if (!mlxsw_sp_port_dev_check(dev))
+ return NOTIFY_DONE;
+
+ mlxsw_sp_port = netdev_priv(dev);
+ mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ info = ptr;
+
+ switch (event) {
+ case NETDEV_PRECHANGEUPPER:
+ upper_dev = info->upper_dev;
+ /* HW limitation forbids to put ports to multiple bridges. */
+ if (info->master && info->linking &&
+ netif_is_bridge_master(upper_dev) &&
+ !mlxsw_sp_master_bridge_check(mlxsw_sp, upper_dev))
+ return NOTIFY_BAD;
+ break;
+ case NETDEV_CHANGEUPPER:
+ upper_dev = info->upper_dev;
+ if (info->master &&
+ netif_is_bridge_master(upper_dev)) {
+ if (info->linking) {
+ err = mlxsw_sp_port_bridge_join(mlxsw_sp_port);
+ if (err)
+ netdev_err(dev, "Failed to join bridge\n");
+ mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev);
+ mlxsw_sp_port->bridged = 1;
+ } else {
+ err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port);
+ if (err)
+ netdev_err(dev, "Failed to leave bridge\n");
+ mlxsw_sp_port->bridged = 0;
+ mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev);
+ }
+ }
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mlxsw_sp_netdevice_nb __read_mostly = {
+ .notifier_call = mlxsw_sp_netdevice_event,
+};
+
+static int __init mlxsw_sp_module_init(void)
+{
+ int err;
+
+ register_netdevice_notifier(&mlxsw_sp_netdevice_nb);
+ err = mlxsw_core_driver_register(&mlxsw_sp_driver);
+ if (err)
+ goto err_core_driver_register;
+ return 0;
+
+err_core_driver_register:
+ unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb);
+ return err;
+}
+
+static void __exit mlxsw_sp_module_exit(void)
+{
+ mlxsw_core_driver_unregister(&mlxsw_sp_driver);
+ unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb);
+}
+
+module_init(mlxsw_sp_module_init);
+module_exit(mlxsw_sp_module_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox Spectrum driver");
+MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SPECTRUM);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
new file mode 100644
index 000000000000..4365c8bccc6d
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -0,0 +1,122 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+ * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
+ * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
+ * Copyright (c) 2015 Elad Raz <eladr@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.
+ */
+
+#ifndef _MLXSW_SPECTRUM_H
+#define _MLXSW_SPECTRUM_H
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
+#include <net/switchdev.h>
+
+#include "core.h"
+
+#define MLXSW_SP_VFID_BASE VLAN_N_VID
+
+struct mlxsw_sp_port;
+
+struct mlxsw_sp {
+ unsigned long active_vfids[BITS_TO_LONGS(VLAN_N_VID)];
+ unsigned long active_fids[BITS_TO_LONGS(VLAN_N_VID)];
+ struct mlxsw_sp_port **ports;
+ struct mlxsw_core *core;
+ const struct mlxsw_bus_info *bus_info;
+ unsigned char base_mac[ETH_ALEN];
+ struct {
+ struct delayed_work dw;
+#define MLXSW_SP_DEFAULT_LEARNING_INTERVAL 100
+ unsigned int interval; /* ms */
+ } fdb_notify;
+#define MLXSW_SP_DEFAULT_AGEING_TIME 300
+ u32 ageing_time;
+ struct {
+ struct net_device *dev;
+ unsigned int ref_count;
+ } master_bridge;
+};
+
+struct mlxsw_sp_port_pcpu_stats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+ u32 tx_dropped;
+};
+
+struct mlxsw_sp_port {
+ struct net_device *dev;
+ struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
+ struct mlxsw_sp *mlxsw_sp;
+ u8 local_port;
+ u8 stp_state;
+ u8 learning:1,
+ learning_sync:1,
+ uc_flood:1,
+ bridged:1;
+ u16 pvid;
+ /* 802.1Q bridge VLANs */
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ /* VLAN interfaces */
+ unsigned long active_vfids[BITS_TO_LONGS(VLAN_N_VID)];
+ u16 nr_vfids;
+};
+
+enum mlxsw_sp_flood_table {
+ MLXSW_SP_FLOOD_TABLE_UC,
+ MLXSW_SP_FLOOD_TABLE_BM,
+};
+
+int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp);
+int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port);
+
+int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp);
+int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port);
+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_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ enum mlxsw_reg_svfa_mt mt, bool valid, u16 fid,
+ u16 vid);
+int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
+ u16 vid_end, bool is_member, bool untagged);
+int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
+ u16 vid);
+int mlxsw_sp_port_kill_vid(struct net_device *dev,
+ __be16 __always_unused proto, u16 vid);
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
new file mode 100644
index 000000000000..d59195e3f7fb
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -0,0 +1,422 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+ * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015 Jiri Pirko <jiri@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "spectrum.h"
+#include "core.h"
+#include "port.h"
+#include "reg.h"
+
+struct mlxsw_sp_pb {
+ u8 index;
+ u16 size;
+};
+
+#define MLXSW_SP_PB(_index, _size) \
+ { \
+ .index = _index, \
+ .size = _size, \
+ }
+
+static const struct mlxsw_sp_pb mlxsw_sp_pbs[] = {
+ MLXSW_SP_PB(0, 208),
+ MLXSW_SP_PB(1, 208),
+ MLXSW_SP_PB(2, 208),
+ MLXSW_SP_PB(3, 208),
+ MLXSW_SP_PB(4, 208),
+ MLXSW_SP_PB(5, 208),
+ MLXSW_SP_PB(6, 208),
+ MLXSW_SP_PB(7, 208),
+ MLXSW_SP_PB(9, 208),
+};
+
+#define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs)
+
+static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ 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++) {
+ const struct mlxsw_sp_pb *pb;
+
+ pb = &mlxsw_sp_pbs[i];
+ mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pb->index, pb->size);
+ }
+ return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core,
+ MLXSW_REG(pbmc), pbmc_pl);
+}
+
+#define MLXSW_SP_SB_BYTES_PER_CELL 96
+
+struct mlxsw_sp_sb_pool {
+ u8 pool;
+ enum mlxsw_reg_sbpr_dir dir;
+ enum mlxsw_reg_sbpr_mode mode;
+ u32 size;
+};
+
+#define MLXSW_SP_SB_POOL_INGRESS_SIZE \
+ ((15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) / \
+ MLXSW_SP_SB_BYTES_PER_CELL)
+#define MLXSW_SP_SB_POOL_EGRESS_SIZE \
+ ((14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) / \
+ MLXSW_SP_SB_BYTES_PER_CELL)
+
+#define MLXSW_SP_SB_POOL(_pool, _dir, _mode, _size) \
+ { \
+ .pool = _pool, \
+ .dir = _dir, \
+ .mode = _mode, \
+ .size = _size, \
+ }
+
+#define MLXSW_SP_SB_POOL_INGRESS(_pool, _size) \
+ MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_INGRESS, \
+ MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
+
+#define MLXSW_SP_SB_POOL_EGRESS(_pool, _size) \
+ MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_EGRESS, \
+ MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
+
+static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = {
+ MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_SB_POOL_INGRESS_SIZE),
+ MLXSW_SP_SB_POOL_INGRESS(1, 0),
+ MLXSW_SP_SB_POOL_INGRESS(2, 0),
+ MLXSW_SP_SB_POOL_INGRESS(3, 0),
+ MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_SB_POOL_EGRESS_SIZE),
+ MLXSW_SP_SB_POOL_EGRESS(1, 0),
+ MLXSW_SP_SB_POOL_EGRESS(2, 0),
+ MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_SB_POOL_EGRESS_SIZE),
+};
+
+#define MLXSW_SP_SB_POOLS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools)
+
+static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
+{
+ char sbpr_pl[MLXSW_REG_SBPR_LEN];
+ int i;
+ int err;
+
+ for (i = 0; i < MLXSW_SP_SB_POOLS_LEN; i++) {
+ const struct mlxsw_sp_sb_pool *pool;
+
+ pool = &mlxsw_sp_sb_pools[i];
+ mlxsw_reg_sbpr_pack(sbpr_pl, pool->pool, pool->dir,
+ pool->mode, pool->size);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+struct mlxsw_sp_sb_cm {
+ union {
+ u8 pg;
+ u8 tc;
+ } u;
+ enum mlxsw_reg_sbcm_dir dir;
+ u32 min_buff;
+ u32 max_buff;
+ u8 pool;
+};
+
+#define MLXSW_SP_SB_CM(_pg_tc, _dir, _min_buff, _max_buff, _pool) \
+ { \
+ .u.pg = _pg_tc, \
+ .dir = _dir, \
+ .min_buff = _min_buff, \
+ .max_buff = _max_buff, \
+ .pool = _pool, \
+ }
+
+#define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff) \
+ MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBCM_DIR_INGRESS, \
+ _min_buff, _max_buff, 0)
+
+#define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff) \
+ MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, \
+ _min_buff, _max_buff, 0)
+
+#define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc) \
+ MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, 104, 2, 3)
+
+static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = {
+ MLXSW_SP_SB_CM_INGRESS(0, 10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8),
+ MLXSW_SP_SB_CM_INGRESS(1, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(2, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(3, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(4, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(5, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(6, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(7, 0, 0),
+ MLXSW_SP_SB_CM_INGRESS(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff),
+ MLXSW_SP_SB_CM_EGRESS(0, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(1, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(2, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(3, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(4, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(5, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(6, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(7, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
+ MLXSW_SP_SB_CM_EGRESS(8, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(9, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(10, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(11, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(12, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(13, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(14, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(15, 0, 0),
+ MLXSW_SP_SB_CM_EGRESS(16, 1, 0xff),
+};
+
+#define MLXSW_SP_SB_CMS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms)
+
+static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = {
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(0),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(1),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(2),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(3),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(4),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(5),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(6),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(7),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(8),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(9),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(10),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(11),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(12),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(13),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(14),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(15),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(16),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(17),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(18),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(19),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(20),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(21),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(22),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(23),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(24),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(25),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(26),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(27),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(28),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(29),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(30),
+ MLXSW_SP_CPU_PORT_SB_CM_EGRESS(31),
+};
+
+#define MLXSW_SP_CPU_PORT_SB_MCS_LEN \
+ ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms)
+
+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)
+{
+ char sbcm_pl[MLXSW_REG_SBCM_LEN];
+ int i;
+ int err;
+
+ for (i = 0; i < cms_len; i++) {
+ const struct mlxsw_sp_sb_cm *cm;
+
+ cm = &cms[i];
+ mlxsw_reg_sbcm_pack(sbcm_pl, local_port, cm->u.pg, cm->dir,
+ cm->min_buff, cm->max_buff, cm->pool);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ return mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
+ mlxsw_sp_port->local_port, mlxsw_sp_sb_cms,
+ MLXSW_SP_SB_CMS_LEN);
+}
+
+static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
+{
+ return mlxsw_sp_sb_cms_init(mlxsw_sp, 0, mlxsw_sp_cpu_port_sb_cms,
+ MLXSW_SP_CPU_PORT_SB_MCS_LEN);
+}
+
+struct mlxsw_sp_sb_pm {
+ u8 pool;
+ enum mlxsw_reg_sbpm_dir dir;
+ u32 min_buff;
+ u32 max_buff;
+};
+
+#define MLXSW_SP_SB_PM(_pool, _dir, _min_buff, _max_buff) \
+ { \
+ .pool = _pool, \
+ .dir = _dir, \
+ .min_buff = _min_buff, \
+ .max_buff = _max_buff, \
+ }
+
+#define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff) \
+ MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_INGRESS, \
+ _min_buff, _max_buff)
+
+#define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff) \
+ MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_EGRESS, \
+ _min_buff, _max_buff)
+
+static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
+ MLXSW_SP_SB_PM_INGRESS(0, 0, 0xff),
+ MLXSW_SP_SB_PM_INGRESS(1, 0, 0),
+ MLXSW_SP_SB_PM_INGRESS(2, 0, 0),
+ MLXSW_SP_SB_PM_INGRESS(3, 0, 0),
+ MLXSW_SP_SB_PM_EGRESS(0, 0, 7),
+ MLXSW_SP_SB_PM_EGRESS(1, 0, 0),
+ MLXSW_SP_SB_PM_EGRESS(2, 0, 0),
+ MLXSW_SP_SB_PM_EGRESS(3, 0, 0),
+};
+
+#define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms)
+
+static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ char sbpm_pl[MLXSW_REG_SBPM_LEN];
+ int i;
+ int err;
+
+ for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) {
+ const struct mlxsw_sp_sb_pm *pm;
+
+ pm = &mlxsw_sp_sb_pms[i];
+ mlxsw_reg_sbpm_pack(sbpm_pl, mlxsw_sp_port->local_port,
+ pm->pool, pm->dir,
+ pm->min_buff, pm->max_buff);
+ err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core,
+ MLXSW_REG(sbpm), sbpm_pl);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+struct mlxsw_sp_sb_mm {
+ u8 prio;
+ u32 min_buff;
+ u32 max_buff;
+ u8 pool;
+};
+
+#define MLXSW_SP_SB_MM(_prio, _min_buff, _max_buff, _pool) \
+ { \
+ .prio = _prio, \
+ .min_buff = _min_buff, \
+ .max_buff = _max_buff, \
+ .pool = _pool, \
+ }
+
+static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = {
+ MLXSW_SP_SB_MM(0, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(1, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(2, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(3, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(4, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(5, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(6, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(7, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(8, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(10, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(11, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(12, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(13, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+ MLXSW_SP_SB_MM(14, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+};
+
+#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++) {
+ const struct mlxsw_sp_sb_mm *mc;
+
+ mc = &mlxsw_sp_sb_mms[i];
+ mlxsw_reg_sbmm_pack(sbmm_pl, mc->prio, mc->min_buff,
+ mc->max_buff, mc->pool);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
+{
+ int err;
+
+ err = mlxsw_sp_sb_pools_init(mlxsw_sp);
+ if (err)
+ return err;
+ err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp);
+ if (err)
+ return err;
+ err = mlxsw_sp_sb_mms_init(mlxsw_sp);
+
+ return err;
+}
+
+int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ int err;
+
+ err = mlxsw_sp_port_pb_init(mlxsw_sp_port);
+ if (err)
+ return err;
+ err = mlxsw_sp_port_sb_cms_init(mlxsw_sp_port);
+ if (err)
+ return err;
+ err = mlxsw_sp_port_sb_pms_init(mlxsw_sp_port);
+
+ return err;
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
new file mode 100644
index 000000000000..617fb22b5d81
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -0,0 +1,903 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+ * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
+ * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
+ * Copyright (c) 2015 Elad Raz <eladr@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <net/switchdev.h>
+
+#include "spectrum.h"
+#include "core.h"
+#include "reg.h"
+
+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:
+ attr->u.brport_flags =
+ (mlxsw_sp_port->learning ? BR_LEARNING : 0) |
+ (mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0) |
+ (mlxsw_sp_port->uc_flood ? BR_FLOOD : 0);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ u8 state)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ enum mlxsw_reg_spms_state spms_state;
+ char *spms_pl;
+ u16 vid;
+ int err;
+
+ switch (state) {
+ case BR_STATE_DISABLED: /* fall-through */
+ case BR_STATE_FORWARDING:
+ spms_state = MLXSW_REG_SPMS_STATE_FORWARDING;
+ break;
+ case BR_STATE_LISTENING: /* fall-through */
+ case BR_STATE_LEARNING:
+ spms_state = MLXSW_REG_SPMS_STATE_LEARNING;
+ break;
+ case BR_STATE_BLOCKING:
+ spms_state = MLXSW_REG_SPMS_STATE_DISCARDING;
+ break;
+ default:
+ BUG();
+ }
+
+ spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
+ if (!spms_pl)
+ return -ENOMEM;
+ mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
+ mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
+
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
+ kfree(spms_pl);
+ return err;
+}
+
+static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct switchdev_trans *trans,
+ u8 state)
+{
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ mlxsw_sp_port->stp_state = state;
+ return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state);
+}
+
+static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 fid_begin, u16 fid_end, bool set,
+ bool only_uc)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ u16 range = fid_end - fid_begin + 1;
+ char *sftr_pl;
+ int err;
+
+ sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
+ if (!sftr_pl)
+ return -ENOMEM;
+
+ mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin,
+ MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
+ mlxsw_sp_port->local_port, set);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
+ if (err)
+ goto buffer_out;
+
+ /* Flooding control allows one to decide whether a given port will
+ * flood unicast traffic for which there is no FDB entry.
+ */
+ if (only_uc)
+ goto buffer_out;
+
+ mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin,
+ MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
+ mlxsw_sp_port->local_port, set);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
+
+buffer_out:
+ kfree(sftr_pl);
+ return err;
+}
+
+static int mlxsw_sp_port_uc_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool set)
+{
+ struct net_device *dev = mlxsw_sp_port->dev;
+ u16 vid, last_visited_vid;
+ int err;
+
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
+ err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, set,
+ true);
+ if (err) {
+ last_visited_vid = vid;
+ goto err_port_flood_set;
+ }
+ }
+
+ return 0;
+
+err_port_flood_set:
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, last_visited_vid)
+ __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, !set, true);
+ netdev_err(dev, "Failed to configure unicast flooding\n");
+ return err;
+}
+
+static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct switchdev_trans *trans,
+ unsigned long brport_flags)
+{
+ unsigned long uc_flood = mlxsw_sp_port->uc_flood ? BR_FLOOD : 0;
+ bool set;
+ int err;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ if ((uc_flood ^ brport_flags) & BR_FLOOD) {
+ set = mlxsw_sp_port->uc_flood ? false : true;
+ err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port, set);
+ if (err)
+ return err;
+ }
+
+ mlxsw_sp_port->uc_flood = brport_flags & BR_FLOOD ? 1 : 0;
+ mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0;
+ mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0;
+
+ return 0;
+}
+
+static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time)
+{
+ char sfdat_pl[MLXSW_REG_SFDAT_LEN];
+ int err;
+
+ mlxsw_reg_sfdat_pack(sfdat_pl, ageing_time);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdat), sfdat_pl);
+ if (err)
+ return err;
+ mlxsw_sp->ageing_time = ageing_time;
+ return 0;
+}
+
+static int mlxsw_sp_port_attr_br_ageing_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct switchdev_trans *trans,
+ unsigned long ageing_clock_t)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);
+ u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ return mlxsw_sp_ageing_set(mlxsw_sp, ageing_time);
+}
+
+static int mlxsw_sp_port_attr_set(struct net_device *dev,
+ const struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err = 0;
+
+ switch (attr->id) {
+ case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
+ err = mlxsw_sp_port_attr_stp_state_set(mlxsw_sp_port, trans,
+ attr->u.stp_state);
+ break;
+ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
+ err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, trans,
+ attr->u.brport_flags);
+ break;
+ case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
+ err = mlxsw_sp_port_attr_br_ageing_set(mlxsw_sp_port, trans,
+ attr->u.ageing_time);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char spvid_pl[MLXSW_REG_SPVID_LEN];
+
+ mlxsw_reg_spvid_pack(spvid_pl, mlxsw_sp_port->local_port, vid);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
+}
+
+static int mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp, u16 fid)
+{
+ char sfmr_pl[MLXSW_REG_SFMR_LEN];
+ int err;
+
+ mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid, fid);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
+
+ if (err)
+ return err;
+
+ set_bit(fid, mlxsw_sp->active_fids);
+ return 0;
+}
+
+static void mlxsw_sp_fid_destroy(struct mlxsw_sp *mlxsw_sp, u16 fid)
+{
+ char sfmr_pl[MLXSW_REG_SFMR_LEN];
+
+ clear_bit(fid, mlxsw_sp->active_fids);
+
+ mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_DESTROY_FID,
+ fid, fid);
+ mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
+}
+
+static int mlxsw_sp_port_fid_map(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
+{
+ enum mlxsw_reg_svfa_mt mt;
+
+ if (mlxsw_sp_port->nr_vfids)
+ mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
+ else
+ mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
+
+ return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, true, fid, fid);
+}
+
+static int mlxsw_sp_port_fid_unmap(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
+{
+ enum mlxsw_reg_svfa_mt mt;
+
+ if (!mlxsw_sp_port->nr_vfids)
+ return 0;
+
+ mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
+ return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, fid, fid);
+}
+
+static int mlxsw_sp_port_add_vids(struct net_device *dev, u16 vid_begin,
+ u16 vid_end)
+{
+ u16 vid;
+ int err;
+
+ for (vid = vid_begin; vid <= vid_end; vid++) {
+ err = mlxsw_sp_port_add_vid(dev, 0, vid);
+ if (err)
+ goto err_port_add_vid;
+ }
+ return 0;
+
+err_port_add_vid:
+ for (vid--; vid >= vid_begin; vid--)
+ mlxsw_sp_port_kill_vid(dev, 0, vid);
+ return err;
+}
+
+static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 vid_begin, u16 vid_end,
+ bool flag_untagged, bool flag_pvid)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct net_device *dev = mlxsw_sp_port->dev;
+ enum mlxsw_reg_svfa_mt mt;
+ u16 vid, vid_e;
+ int err;
+
+ /* In case this is invoked with BRIDGE_FLAGS_SELF and port is
+ * not bridged, then packets ingressing through the port with
+ * the specified VIDs will be directed to CPU.
+ */
+ if (!mlxsw_sp_port->bridged)
+ return mlxsw_sp_port_add_vids(dev, vid_begin, vid_end);
+
+ for (vid = vid_begin; vid <= vid_end; vid++) {
+ if (!test_bit(vid, mlxsw_sp->active_fids)) {
+ err = mlxsw_sp_fid_create(mlxsw_sp, vid);
+ if (err) {
+ netdev_err(dev, "Failed to create FID=%d\n",
+ vid);
+ return err;
+ }
+
+ /* When creating a FID, we set a VID to FID mapping
+ * regardless of the port's mode.
+ */
+ mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
+ err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt,
+ true, vid, vid);
+ if (err) {
+ netdev_err(dev, "Failed to create FID=VID=%d mapping\n",
+ vid);
+ return err;
+ }
+ }
+
+ /* Set FID mapping according to port's mode */
+ err = mlxsw_sp_port_fid_map(mlxsw_sp_port, vid);
+ if (err) {
+ netdev_err(dev, "Failed to map FID=%d", vid);
+ return err;
+ }
+ }
+
+ err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end,
+ true, false);
+ if (err) {
+ netdev_err(dev, "Failed to configure flooding\n");
+ return err;
+ }
+
+ for (vid = vid_begin; vid <= vid_end;
+ vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
+ vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
+ vid_end);
+
+ err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e, true,
+ flag_untagged);
+ if (err) {
+ netdev_err(mlxsw_sp_port->dev, "Unable to add VIDs %d-%d\n",
+ vid, vid_e);
+ return err;
+ }
+ }
+
+ vid = vid_begin;
+ if (flag_pvid && mlxsw_sp_port->pvid != vid) {
+ err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid);
+ if (err) {
+ netdev_err(mlxsw_sp_port->dev, "Unable to add PVID %d\n",
+ vid);
+ return err;
+ }
+ mlxsw_sp_port->pvid = vid;
+ }
+
+ /* Changing activity bits only if HW operation succeded */
+ for (vid = vid_begin; vid <= vid_end; vid++)
+ set_bit(vid, mlxsw_sp_port->active_vlans);
+
+ return mlxsw_sp_port_stp_state_set(mlxsw_sp_port,
+ mlxsw_sp_port->stp_state);
+}
+
+static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans)
+{
+ bool untagged_flag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+ bool pvid_flag = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ return __mlxsw_sp_port_vlans_add(mlxsw_sp_port,
+ vlan->vid_begin, vlan->vid_end,
+ untagged_flag, pvid_flag);
+}
+
+static int mlxsw_sp_port_fdb_op(struct mlxsw_sp_port *mlxsw_sp_port,
+ const char *mac, u16 vid, bool adding,
+ bool dynamic)
+{
+ enum mlxsw_reg_sfd_rec_policy policy;
+ enum mlxsw_reg_sfd_op op;
+ char *sfd_pl;
+ int err;
+
+ if (!vid)
+ vid = mlxsw_sp_port->pvid;
+
+ sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
+ if (!sfd_pl)
+ return -ENOMEM;
+
+ policy = dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
+ MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+ op = adding ? MLXSW_REG_SFD_OP_WRITE_EDIT :
+ MLXSW_REG_SFD_OP_WRITE_REMOVE;
+ mlxsw_reg_sfd_pack(sfd_pl, op, 0);
+ mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy,
+ mac, vid, MLXSW_REG_SFD_REC_ACTION_NOP,
+ mlxsw_sp_port->local_port);
+ err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(sfd),
+ sfd_pl);
+ kfree(sfd_pl);
+
+ return err;
+}
+
+static int
+mlxsw_sp_port_fdb_static_add(struct mlxsw_sp_port *mlxsw_sp_port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
+{
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ return mlxsw_sp_port_fdb_op(mlxsw_sp_port, fdb->addr, fdb->vid,
+ true, false);
+}
+
+static int mlxsw_sp_port_obj_add(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err = 0;
+
+ switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = mlxsw_sp_port_vlans_add(mlxsw_sp_port,
+ SWITCHDEV_OBJ_PORT_VLAN(obj),
+ trans);
+ break;
+ case SWITCHDEV_OBJ_ID_PORT_FDB:
+ err = mlxsw_sp_port_fdb_static_add(mlxsw_sp_port,
+ SWITCHDEV_OBJ_PORT_FDB(obj),
+ trans);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static int mlxsw_sp_port_kill_vids(struct net_device *dev, u16 vid_begin,
+ u16 vid_end)
+{
+ u16 vid;
+ int err;
+
+ for (vid = vid_begin; vid <= vid_end; vid++) {
+ err = mlxsw_sp_port_kill_vid(dev, 0, vid);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 vid_begin, u16 vid_end, bool init)
+{
+ struct net_device *dev = mlxsw_sp_port->dev;
+ u16 vid, vid_e;
+ int err;
+
+ /* In case this is invoked with BRIDGE_FLAGS_SELF and port is
+ * not bridged, then prevent packets ingressing through the
+ * port with the specified VIDs from being trapped to CPU.
+ */
+ if (!init && !mlxsw_sp_port->bridged)
+ return mlxsw_sp_port_kill_vids(dev, vid_begin, vid_end);
+
+ for (vid = vid_begin; vid <= vid_end;
+ vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
+ vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
+ vid_end);
+ err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e, false,
+ false);
+ if (err) {
+ netdev_err(mlxsw_sp_port->dev, "Unable to del VIDs %d-%d\n",
+ vid, vid_e);
+ return err;
+ }
+ }
+
+ if ((mlxsw_sp_port->pvid >= vid_begin) &&
+ (mlxsw_sp_port->pvid <= vid_end)) {
+ /* Default VLAN is always 1 */
+ mlxsw_sp_port->pvid = 1;
+ err = mlxsw_sp_port_pvid_set(mlxsw_sp_port,
+ mlxsw_sp_port->pvid);
+ if (err) {
+ netdev_err(mlxsw_sp_port->dev, "Unable to del PVID %d\n",
+ vid);
+ return err;
+ }
+ }
+
+ if (init)
+ goto out;
+
+ err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end,
+ false, false);
+ if (err) {
+ netdev_err(dev, "Failed to clear flooding\n");
+ return err;
+ }
+
+ for (vid = vid_begin; vid <= vid_end; vid++) {
+ /* Remove FID mapping in case of Virtual mode */
+ err = mlxsw_sp_port_fid_unmap(mlxsw_sp_port, vid);
+ if (err) {
+ netdev_err(dev, "Failed to unmap FID=%d", vid);
+ return err;
+ }
+ }
+
+out:
+ /* Changing activity bits only if HW operation succeded */
+ for (vid = vid_begin; vid <= vid_end; vid++)
+ clear_bit(vid, mlxsw_sp_port->active_vlans);
+
+ return 0;
+}
+
+static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
+ const struct switchdev_obj_port_vlan *vlan)
+{
+ return __mlxsw_sp_port_vlans_del(mlxsw_sp_port,
+ vlan->vid_begin, vlan->vid_end, false);
+}
+
+static int
+mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port,
+ const struct switchdev_obj_port_fdb *fdb)
+{
+ return mlxsw_sp_port_fdb_op(mlxsw_sp_port, fdb->addr, fdb->vid,
+ false, false);
+}
+
+static int mlxsw_sp_port_obj_del(struct net_device *dev,
+ const struct switchdev_obj *obj)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err = 0;
+
+ switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = mlxsw_sp_port_vlans_del(mlxsw_sp_port,
+ SWITCHDEV_OBJ_PORT_VLAN(obj));
+ break;
+ case SWITCHDEV_OBJ_ID_PORT_FDB:
+ err = mlxsw_sp_port_fdb_static_del(mlxsw_sp_port,
+ SWITCHDEV_OBJ_PORT_FDB(obj));
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct switchdev_obj_port_fdb *fdb,
+ switchdev_obj_dump_cb_t *cb)
+{
+ char *sfd_pl;
+ char mac[ETH_ALEN];
+ u16 vid;
+ u8 local_port;
+ u8 num_rec;
+ int stored_err = 0;
+ int i;
+ int err;
+
+ sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
+ if (!sfd_pl)
+ return -ENOMEM;
+
+ mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
+ do {
+ mlxsw_reg_sfd_num_rec_set(sfd_pl, MLXSW_REG_SFD_REC_MAX_COUNT);
+ err = mlxsw_reg_query(mlxsw_sp_port->mlxsw_sp->core,
+ MLXSW_REG(sfd), sfd_pl);
+ if (err)
+ goto out;
+
+ num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
+
+ /* Even in case of error, we have to run the dump to the end
+ * so the session in firmware is finished.
+ */
+ if (stored_err)
+ continue;
+
+ for (i = 0; i < num_rec; i++) {
+ switch (mlxsw_reg_sfd_rec_type_get(sfd_pl, i)) {
+ case MLXSW_REG_SFD_REC_TYPE_UNICAST:
+ mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &vid,
+ &local_port);
+ if (local_port == mlxsw_sp_port->local_port) {
+ ether_addr_copy(fdb->addr, mac);
+ fdb->ndm_state = NUD_REACHABLE;
+ fdb->vid = vid;
+ err = cb(&fdb->obj);
+ if (err)
+ stored_err = err;
+ }
+ }
+ }
+ } while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT);
+
+out:
+ kfree(sfd_pl);
+ return stored_err ? stored_err : err;
+}
+
+static int mlxsw_sp_port_vlan_dump(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct switchdev_obj_port_vlan *vlan,
+ switchdev_obj_dump_cb_t *cb)
+{
+ u16 vid;
+ int err = 0;
+
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
+ vlan->flags = 0;
+ if (vid == mlxsw_sp_port->pvid)
+ vlan->flags |= BRIDGE_VLAN_INFO_PVID;
+ vlan->vid_begin = vid;
+ vlan->vid_end = vid;
+ err = cb(&vlan->obj);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+static int mlxsw_sp_port_obj_dump(struct net_device *dev,
+ struct switchdev_obj *obj,
+ switchdev_obj_dump_cb_t *cb)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ int err = 0;
+
+ switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = mlxsw_sp_port_vlan_dump(mlxsw_sp_port,
+ SWITCHDEV_OBJ_PORT_VLAN(obj), cb);
+ break;
+ case SWITCHDEV_OBJ_ID_PORT_FDB:
+ err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port,
+ SWITCHDEV_OBJ_PORT_FDB(obj), cb);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+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,
+ .switchdev_port_obj_add = mlxsw_sp_port_obj_add,
+ .switchdev_port_obj_del = mlxsw_sp_port_obj_del,
+ .switchdev_port_obj_dump = mlxsw_sp_port_obj_dump,
+};
+
+static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
+ char *sfn_pl, int rec_index,
+ bool adding)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port;
+ char mac[ETH_ALEN];
+ u8 local_port;
+ u16 vid;
+ int err;
+
+ mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &vid, &local_port);
+ mlxsw_sp_port = mlxsw_sp->ports[local_port];
+ if (!mlxsw_sp_port) {
+ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");
+ return;
+ }
+
+ err = mlxsw_sp_port_fdb_op(mlxsw_sp_port, mac, vid,
+ adding && mlxsw_sp_port->learning, true);
+ if (err) {
+ if (net_ratelimit())
+ netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
+ return;
+ }
+
+ if (mlxsw_sp_port->learning && mlxsw_sp_port->learning_sync) {
+ struct switchdev_notifier_fdb_info info;
+ unsigned long notifier_type;
+
+ info.addr = mac;
+ info.vid = vid;
+ notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
+ call_switchdev_notifiers(notifier_type, mlxsw_sp_port->dev,
+ &info.info);
+ }
+}
+
+static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
+ char *sfn_pl, int rec_index)
+{
+ switch (mlxsw_reg_sfn_rec_type_get(sfn_pl, rec_index)) {
+ case MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC:
+ mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl,
+ rec_index, true);
+ break;
+ case MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC:
+ mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl,
+ rec_index, false);
+ break;
+ }
+}
+
+static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp)
+{
+ schedule_delayed_work(&mlxsw_sp->fdb_notify.dw,
+ msecs_to_jiffies(mlxsw_sp->fdb_notify.interval));
+}
+
+static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
+{
+ struct mlxsw_sp *mlxsw_sp;
+ char *sfn_pl;
+ u8 num_rec;
+ int i;
+ int err;
+
+ sfn_pl = kmalloc(MLXSW_REG_SFN_LEN, GFP_KERNEL);
+ if (!sfn_pl)
+ return;
+
+ mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
+
+ do {
+ mlxsw_reg_sfn_pack(sfn_pl);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
+ if (err) {
+ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
+ break;
+ }
+ num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
+ for (i = 0; i < num_rec; i++)
+ mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
+
+ } while (num_rec);
+
+ kfree(sfn_pl);
+ mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
+}
+
+static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
+{
+ int err;
+
+ err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
+ return err;
+ }
+ INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
+ mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
+ mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
+ return 0;
+}
+
+static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ cancel_delayed_work_sync(&mlxsw_sp->fdb_notify.dw);
+}
+
+static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ u16 fid;
+
+ for_each_set_bit(fid, mlxsw_sp->active_fids, VLAN_N_VID)
+ mlxsw_sp_fid_destroy(mlxsw_sp, fid);
+}
+
+int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
+{
+ return mlxsw_sp_fdb_init(mlxsw_sp);
+}
+
+void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ mlxsw_sp_fdb_fini(mlxsw_sp);
+ mlxsw_sp_fids_fini(mlxsw_sp);
+}
+
+int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct net_device *dev = mlxsw_sp_port->dev;
+ int err;
+
+ /* Allow only untagged packets to ingress and tag them internally
+ * with VID 1.
+ */
+ mlxsw_sp_port->pvid = 1;
+ err = __mlxsw_sp_port_vlans_del(mlxsw_sp_port, 0, VLAN_N_VID, true);
+ if (err) {
+ netdev_err(dev, "Unable to init VLANs\n");
+ return err;
+ }
+
+ /* Add implicit VLAN interface in the device, so that untagged
+ * packets will be classified to the default vFID.
+ */
+ err = mlxsw_sp_port_add_vid(dev, 0, 1);
+ if (err)
+ netdev_err(dev, "Failed to configure default vFID\n");
+
+ return err;
+}
+
+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 3e52ee93438c..d85960cfb694 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -57,13 +57,11 @@ static const char mlxsw_sx_driver_version[] = "1.0";
struct mlxsw_sx_port;
-#define MLXSW_SW_HW_ID_LEN 6
-
struct mlxsw_sx {
struct mlxsw_sx_port **ports;
struct mlxsw_core *core;
const struct mlxsw_bus_info *bus_info;
- u8 hw_id[MLXSW_SW_HW_ID_LEN];
+ u8 hw_id[ETH_ALEN];
};
struct mlxsw_sx_port_pcpu_stats {
@@ -868,7 +866,7 @@ static int mlxsw_sx_port_attr_get(struct net_device *dev,
struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
switch (attr->id) {
- case SWITCHDEV_ATTR_PORT_PARENT_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;
@@ -925,7 +923,8 @@ static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port,
spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
if (!spms_pl)
return -ENOMEM;
- mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port, vid, state);
+ mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port);
+ mlxsw_reg_spms_vid_pack(spms_pl, vid, state);
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spms), spms_pl);
kfree(spms_pl);
return err;
@@ -1069,9 +1068,9 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
return 0;
err_register_netdev:
-err_port_admin_status_set:
err_port_mac_learning_mode_set:
err_port_stp_state_set:
+err_port_admin_status_set:
err_port_mtu_set:
err_port_speed_set:
err_port_swid_set:
@@ -1148,7 +1147,7 @@ static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg,
}
status = mlxsw_reg_pude_oper_status_get(pude_pl);
- if (MLXSW_PORT_OPER_STATUS_UP == status) {
+ if (status == MLXSW_PORT_OPER_STATUS_UP) {
netdev_info(mlxsw_sx_port->dev, "link up\n");
netif_carrier_on(mlxsw_sx_port->dev);
} else {
@@ -1178,8 +1177,7 @@ static int mlxsw_sx_event_register(struct mlxsw_sx *mlxsw_sx,
if (err)
return err;
- mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
- MLXSW_REG_HTGT_TRAP_GROUP_EMAD, trap_id);
+ mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id);
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
if (err)
goto err_event_trap_set;
@@ -1212,9 +1210,8 @@ static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port,
struct mlxsw_sx_port_pcpu_stats *pcpu_stats;
if (unlikely(!mlxsw_sx_port)) {
- if (net_ratelimit())
- dev_warn(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n",
- local_port);
+ dev_warn_ratelimited(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n",
+ local_port);
return;
}
@@ -1316,6 +1313,11 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx)
if (err)
return err;
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL);
+ err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl);
+ if (err)
+ return err;
+
for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) {
err = mlxsw_core_rx_listener_register(mlxsw_sx->core,
&mlxsw_sx_rx_listener[i],
@@ -1324,7 +1326,6 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx)
goto err_rx_listener_register;
mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
- MLXSW_REG_HTGT_TRAP_GROUP_RX,
mlxsw_sx_rx_listener[i].trap_id);
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
if (err)
@@ -1339,7 +1340,6 @@ err_rx_trap_set:
err_rx_listener_register:
for (i--; i >= 0; i--) {
mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
- MLXSW_REG_HTGT_TRAP_GROUP_RX,
mlxsw_sx_rx_listener[i].trap_id);
mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
@@ -1357,7 +1357,6 @@ static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx)
for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) {
mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
- MLXSW_REG_HTGT_TRAP_GROUP_RX,
mlxsw_sx_rx_listener[i].trap_id);
mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
@@ -1371,25 +1370,15 @@ static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx)
{
char sfgc_pl[MLXSW_REG_SFGC_LEN];
char sgcr_pl[MLXSW_REG_SGCR_LEN];
- char *smid_pl;
char *sftr_pl;
int err;
- /* Due to FW bug, we must configure SMID. */
- smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL);
- if (!smid_pl)
- return -ENOMEM;
- mlxsw_reg_smid_pack(smid_pl, MLXSW_PORT_MID);
- err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(smid), smid_pl);
- kfree(smid_pl);
- if (err)
- return err;
-
/* Configure a flooding table, which includes only CPU port. */
sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
if (!sftr_pl)
return -ENOMEM;
- mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0);
+ mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0,
+ MLXSW_PORT_CPU_PORT, true);
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sftr), sftr_pl);
kfree(sftr_pl);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/txheader.h b/drivers/net/ethernet/mellanox/mlxsw/txheader.h
index 06fc46c78a0b..fdf94720ca62 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/txheader.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/txheader.h
@@ -38,6 +38,7 @@
#define MLXSW_TXHDR_LEN 0x10
#define MLXSW_TXHDR_VERSION_0 0
+#define MLXSW_TXHDR_VERSION_1 1
enum {
MLXSW_TXHDR_ETH_CTL,
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 60f43ec22175..1edc973df4c4 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1607,7 +1607,6 @@ static struct spi_driver ks8851_driver = {
.driver = {
.name = "ks8851",
.of_match_table = ks8851_match_table,
- .owner = THIS_MODULE,
.pm = &ks8851_pm_ops,
},
.probe = ks8851_probe,
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index 3fd8ca6d4e7c..36a09d94b368 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -33,4 +33,13 @@ config ENC28J60_WRITEVERIFY
Enable the verify after the buffer write useful for debugging purpose.
If unsure, say N.
+config ENCX24J600
+ tristate "ENCX24J600 support"
+ depends on SPI
+ ---help---
+ Support for the Microchip ENC424J600/624J600 ethernet chip.
+
+ To compile this driver as a module, choose M here. The module will be
+ called encx24j600.
+
endif # NET_VENDOR_MICROCHIP
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index 573d4292b9ea..ff78f621b59a 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_ENC28J60) += enc28j60.o
+obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index b1b5f66b8b69..86ea17e7ba7b 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1633,7 +1633,6 @@ static int enc28j60_remove(struct spi_device *spi)
static struct spi_driver enc28j60_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
},
.probe = enc28j60_probe,
.remove = enc28j60_remove,
diff --git a/drivers/net/ethernet/microchip/encx24j600-regmap.c b/drivers/net/ethernet/microchip/encx24j600-regmap.c
new file mode 100644
index 000000000000..f3bb9055a292
--- /dev/null
+++ b/drivers/net/ethernet/microchip/encx24j600-regmap.c
@@ -0,0 +1,513 @@
+/**
+ * Register map access API - ENCX24J600 support
+ *
+ * Copyright 2015 Gridpoint
+ *
+ * Author: Jon Ringle <jringle@gridpoint.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/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "encx24j600_hw.h"
+
+static inline bool is_bits_set(int value, int mask)
+{
+ return (value & mask) == mask;
+}
+
+static int encx24j600_switch_bank(struct encx24j600_context *ctx,
+ int bank)
+{
+ int ret = 0;
+
+ int bank_opcode = BANK_SELECT(bank);
+ ret = spi_write(ctx->spi, &bank_opcode, 1);
+ if (ret == 0)
+ ctx->bank = bank;
+
+ return ret;
+}
+
+static int encx24j600_cmdn(struct encx24j600_context *ctx, u8 opcode,
+ const void *buf, size_t len)
+{
+ struct spi_message m;
+ struct spi_transfer t[2] = { { .tx_buf = &opcode, .len = 1, },
+ { .tx_buf = buf, .len = len }, };
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+
+ return spi_sync(ctx->spi, &m);
+}
+
+static void regmap_lock_mutex(void *context)
+{
+ struct encx24j600_context *ctx = context;
+ mutex_lock(&ctx->mutex);
+}
+
+static void regmap_unlock_mutex(void *context)
+{
+ struct encx24j600_context *ctx = context;
+ mutex_unlock(&ctx->mutex);
+}
+
+static int regmap_encx24j600_sfr_read(void *context, u8 reg, u8 *val,
+ size_t len)
+{
+ struct encx24j600_context *ctx = context;
+ u8 banked_reg = reg & ADDR_MASK;
+ u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT);
+ u8 cmd = RCRU;
+ int ret = 0;
+ int i = 0;
+ u8 tx_buf[2];
+
+ if (reg < 0x80) {
+ cmd = RCRCODE | banked_reg;
+ if ((banked_reg < 0x16) && (ctx->bank != bank))
+ ret = encx24j600_switch_bank(ctx, bank);
+ if (unlikely(ret))
+ return ret;
+ } else {
+ /* Translate registers that are more effecient using
+ * 3-byte SPI commands
+ */
+ switch (reg) {
+ case EGPRDPT:
+ cmd = RGPRDPT; break;
+ case EGPWRPT:
+ cmd = RGPWRPT; break;
+ case ERXRDPT:
+ cmd = RRXRDPT; break;
+ case ERXWRPT:
+ cmd = RRXWRPT; break;
+ case EUDARDPT:
+ cmd = RUDARDPT; break;
+ case EUDAWRPT:
+ cmd = RUDAWRPT; break;
+ case EGPDATA:
+ case ERXDATA:
+ case EUDADATA:
+ default:
+ return -EINVAL;
+ }
+ }
+
+ tx_buf[i++] = cmd;
+ if (cmd == RCRU)
+ tx_buf[i++] = reg;
+
+ ret = spi_write_then_read(ctx->spi, tx_buf, i, val, len);
+
+ return ret;
+}
+
+static int regmap_encx24j600_sfr_update(struct encx24j600_context *ctx,
+ u8 reg, u8 *val, size_t len,
+ u8 unbanked_cmd, u8 banked_code)
+{
+ u8 banked_reg = reg & ADDR_MASK;
+ u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT);
+ u8 cmd = unbanked_cmd;
+ struct spi_message m;
+ struct spi_transfer t[3] = { { .tx_buf = &cmd, .len = sizeof(cmd), },
+ { .tx_buf = &reg, .len = sizeof(reg), },
+ { .tx_buf = val, .len = len }, };
+
+ if (reg < 0x80) {
+ int ret = 0;
+ cmd = banked_code | banked_reg;
+ if ((banked_reg < 0x16) && (ctx->bank != bank))
+ ret = encx24j600_switch_bank(ctx, bank);
+ if (unlikely(ret))
+ return ret;
+ } else {
+ /* Translate registers that are more effecient using
+ * 3-byte SPI commands
+ */
+ switch (reg) {
+ case EGPRDPT:
+ cmd = WGPRDPT; break;
+ case EGPWRPT:
+ cmd = WGPWRPT; break;
+ case ERXRDPT:
+ cmd = WRXRDPT; break;
+ case ERXWRPT:
+ cmd = WRXWRPT; break;
+ case EUDARDPT:
+ cmd = WUDARDPT; break;
+ case EUDAWRPT:
+ cmd = WUDAWRPT; break;
+ case EGPDATA:
+ case ERXDATA:
+ case EUDADATA:
+ default:
+ return -EINVAL;
+ }
+ }
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+
+ if (cmd == unbanked_cmd) {
+ t[1].tx_buf = &reg;
+ spi_message_add_tail(&t[1], &m);
+ }
+
+ spi_message_add_tail(&t[2], &m);
+ return spi_sync(ctx->spi, &m);
+}
+
+static int regmap_encx24j600_sfr_write(void *context, u8 reg, u8 *val,
+ size_t len)
+{
+ struct encx24j600_context *ctx = context;
+ return regmap_encx24j600_sfr_update(ctx, reg, val, len, WCRU, WCRCODE);
+}
+
+static int regmap_encx24j600_sfr_set_bits(struct encx24j600_context *ctx,
+ u8 reg, u8 val)
+{
+ return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFSU, BFSCODE);
+}
+
+static int regmap_encx24j600_sfr_clr_bits(struct encx24j600_context *ctx,
+ u8 reg, u8 val)
+{
+ return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFCU, BFCCODE);
+}
+
+static int regmap_encx24j600_reg_update_bits(void *context, unsigned int reg,
+ unsigned int mask,
+ unsigned int val)
+{
+ struct encx24j600_context *ctx = context;
+
+ int ret = 0;
+ unsigned int set_mask = mask & val;
+ unsigned int clr_mask = mask & ~val;
+
+ if ((reg >= 0x40 && reg < 0x6c) || reg >= 0x80)
+ return -EINVAL;
+
+ if (set_mask & 0xff)
+ ret = regmap_encx24j600_sfr_set_bits(ctx, reg, set_mask);
+
+ set_mask = (set_mask & 0xff00) >> 8;
+
+ if ((set_mask & 0xff) && (ret == 0))
+ ret = regmap_encx24j600_sfr_set_bits(ctx, reg + 1, set_mask);
+
+ if ((clr_mask & 0xff) && (ret == 0))
+ ret = regmap_encx24j600_sfr_clr_bits(ctx, reg, clr_mask);
+
+ clr_mask = (clr_mask & 0xff00) >> 8;
+
+ if ((clr_mask & 0xff) && (ret == 0))
+ ret = regmap_encx24j600_sfr_clr_bits(ctx, reg + 1, clr_mask);
+
+ return ret;
+}
+
+int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data,
+ size_t count)
+{
+ struct encx24j600_context *ctx = context;
+
+ if (reg < 0xc0)
+ return encx24j600_cmdn(ctx, reg, data, count);
+ else
+ /* SPI 1-byte command. Ignore data */
+ return spi_write(ctx->spi, &reg, 1);
+}
+EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_write);
+
+int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count)
+{
+ struct encx24j600_context *ctx = context;
+
+ if (reg == RBSEL && count > 1)
+ count = 1;
+
+ return spi_write_then_read(ctx->spi, &reg, sizeof(reg), data, count);
+}
+EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_read);
+
+static int regmap_encx24j600_write(void *context, const void *data,
+ size_t len)
+{
+ u8 *dout = (u8 *)data;
+ u8 reg = dout[0];
+ ++dout;
+ --len;
+
+ if (reg > 0xa0)
+ return regmap_encx24j600_spi_write(context, reg, dout, len);
+
+ if (len > 2)
+ return -EINVAL;
+
+ return regmap_encx24j600_sfr_write(context, reg, dout, len);
+}
+
+static int regmap_encx24j600_read(void *context,
+ const void *reg_buf, size_t reg_size,
+ void *val, size_t val_size)
+{
+ u8 reg = *(const u8 *)reg_buf;
+
+ if (reg_size != 1) {
+ pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size);
+ return -EINVAL;
+ }
+
+ if (reg > 0xa0)
+ return regmap_encx24j600_spi_read(context, reg, val, val_size);
+
+ if (val_size > 2) {
+ pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size);
+ return -EINVAL;
+ }
+
+ return regmap_encx24j600_sfr_read(context, reg, val, val_size);
+}
+
+static bool encx24j600_regmap_readable(struct device *dev, unsigned int reg)
+{
+ if ((reg < 0x36) ||
+ ((reg >= 0x40) && (reg < 0x4c)) ||
+ ((reg >= 0x52) && (reg < 0x56)) ||
+ ((reg >= 0x60) && (reg < 0x66)) ||
+ ((reg >= 0x68) && (reg < 0x80)) ||
+ ((reg >= 0x86) && (reg < 0x92)) ||
+ (reg == 0xc8))
+ return true;
+ else
+ return false;
+}
+
+static bool encx24j600_regmap_writeable(struct device *dev, unsigned int reg)
+{
+ if ((reg < 0x12) ||
+ ((reg >= 0x14) && (reg < 0x1a)) ||
+ ((reg >= 0x1c) && (reg < 0x36)) ||
+ ((reg >= 0x40) && (reg < 0x4c)) ||
+ ((reg >= 0x52) && (reg < 0x56)) ||
+ ((reg >= 0x60) && (reg < 0x68)) ||
+ ((reg >= 0x6c) && (reg < 0x80)) ||
+ ((reg >= 0x86) && (reg < 0x92)) ||
+ ((reg >= 0xc0) && (reg < 0xc8)) ||
+ ((reg >= 0xca) && (reg < 0xf0)))
+ return true;
+ else
+ return false;
+}
+
+static bool encx24j600_regmap_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ERXHEAD:
+ case EDMACS:
+ case ETXSTAT:
+ case ETXWIRE:
+ case ECON1: /* Can be modified via single byte cmds */
+ case ECON2: /* Can be modified via single byte cmds */
+ case ESTAT:
+ case EIR: /* Can be modified via single byte cmds */
+ case MIRD:
+ case MISTAT:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static bool encx24j600_regmap_precious(struct device *dev, unsigned int reg)
+{
+ /* single byte cmds are precious */
+ if (((reg >= 0xc0) && (reg < 0xc8)) ||
+ ((reg >= 0xca) && (reg < 0xf0)))
+ return true;
+ else
+ return false;
+}
+
+static int regmap_encx24j600_phy_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ struct encx24j600_context *ctx = context;
+ int ret;
+ unsigned int mistat;
+
+ reg = MIREGADR_VAL | (reg & PHREG_MASK);
+ ret = regmap_write(ctx->regmap, MIREGADR, reg);
+ if (unlikely(ret))
+ goto err_out;
+
+ ret = regmap_write(ctx->regmap, MICMD, MIIRD);
+ if (unlikely(ret))
+ goto err_out;
+
+ usleep_range(26, 100);
+ while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) &&
+ (mistat & BUSY))
+ cpu_relax();
+
+ if (unlikely(ret))
+ goto err_out;
+
+ ret = regmap_write(ctx->regmap, MICMD, 0);
+ if (unlikely(ret))
+ goto err_out;
+
+ ret = regmap_read(ctx->regmap, MIRD, val);
+
+err_out:
+ if (ret)
+ pr_err("%s: error %d reading reg %02x\n", __func__, ret,
+ reg & PHREG_MASK);
+
+ return ret;
+}
+
+static int regmap_encx24j600_phy_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ struct encx24j600_context *ctx = context;
+ int ret;
+ unsigned int mistat;
+
+ reg = MIREGADR_VAL | (reg & PHREG_MASK);
+ ret = regmap_write(ctx->regmap, MIREGADR, reg);
+ if (unlikely(ret))
+ goto err_out;
+
+ ret = regmap_write(ctx->regmap, MIWR, val);
+ if (unlikely(ret))
+ goto err_out;
+
+ usleep_range(26, 100);
+ while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) &&
+ (mistat & BUSY))
+ cpu_relax();
+
+err_out:
+ if (ret)
+ pr_err("%s: error %d writing reg %02x=%04x\n", __func__, ret,
+ reg & PHREG_MASK, val);
+
+ return ret;
+}
+
+static bool encx24j600_phymap_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case PHCON1:
+ case PHSTAT1:
+ case PHANA:
+ case PHANLPA:
+ case PHANE:
+ case PHCON2:
+ case PHSTAT2:
+ case PHSTAT3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool encx24j600_phymap_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case PHCON1:
+ case PHCON2:
+ case PHANA:
+ return true;
+ case PHSTAT1:
+ case PHSTAT2:
+ case PHSTAT3:
+ case PHANLPA:
+ case PHANE:
+ default:
+ return false;
+ }
+}
+
+static bool encx24j600_phymap_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case PHSTAT1:
+ case PHSTAT2:
+ case PHSTAT3:
+ case PHANLPA:
+ case PHANE:
+ case PHCON2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static struct regmap_config regcfg = {
+ .name = "reg",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0xee,
+ .reg_stride = 2,
+ .cache_type = REGCACHE_RBTREE,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+ .readable_reg = encx24j600_regmap_readable,
+ .writeable_reg = encx24j600_regmap_writeable,
+ .volatile_reg = encx24j600_regmap_volatile,
+ .precious_reg = encx24j600_regmap_precious,
+ .lock = regmap_lock_mutex,
+ .unlock = regmap_unlock_mutex,
+};
+
+static struct regmap_bus regmap_encx24j600 = {
+ .write = regmap_encx24j600_write,
+ .read = regmap_encx24j600_read,
+ .reg_update_bits = regmap_encx24j600_reg_update_bits,
+};
+
+static struct regmap_config phycfg = {
+ .name = "phy",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0x1f,
+ .cache_type = REGCACHE_RBTREE,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+ .readable_reg = encx24j600_phymap_readable,
+ .writeable_reg = encx24j600_phymap_writeable,
+ .volatile_reg = encx24j600_phymap_volatile,
+};
+static struct regmap_bus phymap_encx24j600 = {
+ .reg_write = regmap_encx24j600_phy_reg_write,
+ .reg_read = regmap_encx24j600_phy_reg_read,
+};
+
+void devm_regmap_init_encx24j600(struct device *dev,
+ struct encx24j600_context *ctx)
+{
+ mutex_init(&ctx->mutex);
+ regcfg.lock_arg = ctx;
+ ctx->regmap = devm_regmap_init(dev, &regmap_encx24j600, ctx, &regcfg);
+ ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c
new file mode 100644
index 000000000000..2056b719c262
--- /dev/null
+++ b/drivers/net/ethernet/microchip/encx24j600.c
@@ -0,0 +1,1129 @@
+/**
+ * Microchip ENCX24J600 ethernet driver
+ *
+ * Copyright (C) 2015 Gridpoint
+ * Author: Jon Ringle <jringle@gridpoint.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/device.h>
+#include <linux/errno.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/regmap.h>
+#include <linux/skbuff.h>
+#include <linux/spi/spi.h>
+
+#include "encx24j600_hw.h"
+
+#define DRV_NAME "encx24j600"
+#define DRV_VERSION "1.0"
+
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+/* SRAM memory layout:
+ *
+ * 0x0000-0x05ff TX buffers 1.5KB (1*1536) reside in the GP area in SRAM
+ * 0x0600-0x5fff RX buffers 22.5KB (15*1536) reside in the RX area in SRAM
+ */
+#define ENC_TX_BUF_START 0x0000U
+#define ENC_RX_BUF_START 0x0600U
+#define ENC_RX_BUF_END 0x5fffU
+#define ENC_SRAM_SIZE 0x6000U
+
+enum {
+ RXFILTER_NORMAL,
+ RXFILTER_MULTI,
+ RXFILTER_PROMISC
+};
+
+struct encx24j600_priv {
+ struct net_device *ndev;
+ struct mutex lock; /* device access lock */
+ struct encx24j600_context ctx;
+ struct sk_buff *tx_skb;
+ struct task_struct *kworker_task;
+ struct kthread_worker kworker;
+ struct kthread_work tx_work;
+ struct kthread_work setrx_work;
+ u16 next_packet;
+ bool hw_enabled;
+ bool full_duplex;
+ bool autoneg;
+ u16 speed;
+ int rxfilter;
+ u32 msg_enable;
+};
+
+static void dump_packet(const char *msg, int len, const char *data)
+{
+ pr_debug(DRV_NAME ": %s - packet len:%d\n", msg, len);
+ print_hex_dump_bytes("pk data: ", DUMP_PREFIX_OFFSET, data, len);
+}
+
+static void encx24j600_dump_rsv(struct encx24j600_priv *priv, const char *msg,
+ struct rsv *rsv)
+{
+ struct net_device *dev = priv->ndev;
+
+ netdev_info(dev, "RX packet Len:%d\n", rsv->len);
+ netdev_dbg(dev, "%s - NextPk: 0x%04x\n", msg,
+ rsv->next_packet);
+ netdev_dbg(dev, "RxOK: %d, DribbleNibble: %d\n",
+ RSV_GETBIT(rsv->rxstat, RSV_RXOK),
+ RSV_GETBIT(rsv->rxstat, RSV_DRIBBLENIBBLE));
+ netdev_dbg(dev, "CRCErr:%d, LenChkErr: %d, LenOutOfRange: %d\n",
+ RSV_GETBIT(rsv->rxstat, RSV_CRCERROR),
+ RSV_GETBIT(rsv->rxstat, RSV_LENCHECKERR),
+ RSV_GETBIT(rsv->rxstat, RSV_LENOUTOFRANGE));
+ netdev_dbg(dev, "Multicast: %d, Broadcast: %d, LongDropEvent: %d, CarrierEvent: %d\n",
+ RSV_GETBIT(rsv->rxstat, RSV_RXMULTICAST),
+ RSV_GETBIT(rsv->rxstat, RSV_RXBROADCAST),
+ RSV_GETBIT(rsv->rxstat, RSV_RXLONGEVDROPEV),
+ RSV_GETBIT(rsv->rxstat, RSV_CARRIEREV));
+ netdev_dbg(dev, "ControlFrame: %d, PauseFrame: %d, UnknownOp: %d, VLanTagFrame: %d\n",
+ RSV_GETBIT(rsv->rxstat, RSV_RXCONTROLFRAME),
+ RSV_GETBIT(rsv->rxstat, RSV_RXPAUSEFRAME),
+ RSV_GETBIT(rsv->rxstat, RSV_RXUNKNOWNOPCODE),
+ RSV_GETBIT(rsv->rxstat, RSV_RXTYPEVLAN));
+}
+
+static u16 encx24j600_read_reg(struct encx24j600_priv *priv, u8 reg)
+{
+ struct net_device *dev = priv->ndev;
+ unsigned int val = 0;
+ int ret = regmap_read(priv->ctx.regmap, reg, &val);
+ if (unlikely(ret))
+ netif_err(priv, drv, dev, "%s: error %d reading reg %02x\n",
+ __func__, ret, reg);
+ return val;
+}
+
+static void encx24j600_write_reg(struct encx24j600_priv *priv, u8 reg, u16 val)
+{
+ struct net_device *dev = priv->ndev;
+ int ret = regmap_write(priv->ctx.regmap, reg, val);
+ if (unlikely(ret))
+ netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n",
+ __func__, ret, reg, val);
+}
+
+static void encx24j600_update_reg(struct encx24j600_priv *priv, u8 reg,
+ u16 mask, u16 val)
+{
+ struct net_device *dev = priv->ndev;
+ int ret = regmap_update_bits(priv->ctx.regmap, reg, mask, val);
+ if (unlikely(ret))
+ netif_err(priv, drv, dev, "%s: error %d updating reg %02x=%04x~%04x\n",
+ __func__, ret, reg, val, mask);
+}
+
+static u16 encx24j600_read_phy(struct encx24j600_priv *priv, u8 reg)
+{
+ struct net_device *dev = priv->ndev;
+ unsigned int val = 0;
+ int ret = regmap_read(priv->ctx.phymap, reg, &val);
+ if (unlikely(ret))
+ netif_err(priv, drv, dev, "%s: error %d reading %02x\n",
+ __func__, ret, reg);
+ return val;
+}
+
+static void encx24j600_write_phy(struct encx24j600_priv *priv, u8 reg, u16 val)
+{
+ struct net_device *dev = priv->ndev;
+ int ret = regmap_write(priv->ctx.phymap, reg, val);
+ if (unlikely(ret))
+ netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n",
+ __func__, ret, reg, val);
+}
+
+static void encx24j600_clr_bits(struct encx24j600_priv *priv, u8 reg, u16 mask)
+{
+ encx24j600_update_reg(priv, reg, mask, 0);
+}
+
+static void encx24j600_set_bits(struct encx24j600_priv *priv, u8 reg, u16 mask)
+{
+ encx24j600_update_reg(priv, reg, mask, mask);
+}
+
+static void encx24j600_cmd(struct encx24j600_priv *priv, u8 cmd)
+{
+ struct net_device *dev = priv->ndev;
+ int ret = regmap_write(priv->ctx.regmap, cmd, 0);
+ if (unlikely(ret))
+ netif_err(priv, drv, dev, "%s: error %d with cmd %02x\n",
+ __func__, ret, cmd);
+}
+
+static int encx24j600_raw_read(struct encx24j600_priv *priv, u8 reg, u8 *data,
+ size_t count)
+{
+ int ret;
+ mutex_lock(&priv->ctx.mutex);
+ ret = regmap_encx24j600_spi_read(&priv->ctx, reg, data, count);
+ mutex_unlock(&priv->ctx.mutex);
+
+ return ret;
+}
+
+static int encx24j600_raw_write(struct encx24j600_priv *priv, u8 reg,
+ const u8 *data, size_t count)
+{
+ int ret;
+ mutex_lock(&priv->ctx.mutex);
+ ret = regmap_encx24j600_spi_write(&priv->ctx, reg, data, count);
+ mutex_unlock(&priv->ctx.mutex);
+
+ return ret;
+}
+
+static void encx24j600_update_phcon1(struct encx24j600_priv *priv)
+{
+ u16 phcon1 = encx24j600_read_phy(priv, PHCON1);
+ if (priv->autoneg == AUTONEG_ENABLE) {
+ phcon1 |= ANEN | RENEG;
+ } else {
+ phcon1 &= ~ANEN;
+ if (priv->speed == SPEED_100)
+ phcon1 |= SPD100;
+ else
+ phcon1 &= ~SPD100;
+
+ if (priv->full_duplex)
+ phcon1 |= PFULDPX;
+ else
+ phcon1 &= ~PFULDPX;
+ }
+ encx24j600_write_phy(priv, PHCON1, phcon1);
+}
+
+/* Waits for autonegotiation to complete. */
+static int encx24j600_wait_for_autoneg(struct encx24j600_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+ unsigned long timeout = jiffies + msecs_to_jiffies(2000);
+ u16 phstat1;
+ u16 estat;
+ int ret = 0;
+
+ phstat1 = encx24j600_read_phy(priv, PHSTAT1);
+ while ((phstat1 & ANDONE) == 0) {
+ if (time_after(jiffies, timeout)) {
+ u16 phstat3;
+
+ netif_notice(priv, drv, dev, "timeout waiting for autoneg done\n");
+
+ priv->autoneg = AUTONEG_DISABLE;
+ phstat3 = encx24j600_read_phy(priv, PHSTAT3);
+ priv->speed = (phstat3 & PHY3SPD100)
+ ? SPEED_100 : SPEED_10;
+ priv->full_duplex = (phstat3 & PHY3DPX) ? 1 : 0;
+ encx24j600_update_phcon1(priv);
+ netif_notice(priv, drv, dev, "Using parallel detection: %s/%s",
+ priv->speed == SPEED_100 ? "100" : "10",
+ priv->full_duplex ? "Full" : "Half");
+
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ phstat1 = encx24j600_read_phy(priv, PHSTAT1);
+ }
+
+ estat = encx24j600_read_reg(priv, ESTAT);
+ if (estat & PHYDPX) {
+ encx24j600_set_bits(priv, MACON2, FULDPX);
+ encx24j600_write_reg(priv, MABBIPG, 0x15);
+ } else {
+ encx24j600_clr_bits(priv, MACON2, FULDPX);
+ encx24j600_write_reg(priv, MABBIPG, 0x12);
+ /* Max retransmittions attempt */
+ encx24j600_write_reg(priv, MACLCON, 0x370f);
+ }
+
+ return ret;
+}
+
+/* Access the PHY to determine link status */
+static void encx24j600_check_link_status(struct encx24j600_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+ u16 estat;
+
+ estat = encx24j600_read_reg(priv, ESTAT);
+
+ if (estat & PHYLNK) {
+ if (priv->autoneg == AUTONEG_ENABLE)
+ encx24j600_wait_for_autoneg(priv);
+
+ netif_carrier_on(dev);
+ netif_info(priv, ifup, dev, "link up\n");
+ } else {
+ netif_info(priv, ifdown, dev, "link down\n");
+
+ /* Re-enable autoneg since we won't know what we might be
+ * connected to when the link is brought back up again.
+ */
+ priv->autoneg = AUTONEG_ENABLE;
+ priv->full_duplex = true;
+ priv->speed = SPEED_100;
+ netif_carrier_off(dev);
+ }
+}
+
+static void encx24j600_int_link_handler(struct encx24j600_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+
+ netif_dbg(priv, intr, dev, "%s", __func__);
+ encx24j600_check_link_status(priv);
+ encx24j600_clr_bits(priv, EIR, LINKIF);
+}
+
+static void encx24j600_tx_complete(struct encx24j600_priv *priv, bool err)
+{
+ struct net_device *dev = priv->ndev;
+
+ if (!priv->tx_skb) {
+ BUG();
+ return;
+ }
+
+ mutex_lock(&priv->lock);
+
+ if (err)
+ dev->stats.tx_errors++;
+ else
+ dev->stats.tx_packets++;
+
+ dev->stats.tx_bytes += priv->tx_skb->len;
+
+ encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF);
+
+ netif_dbg(priv, tx_done, dev, "TX Done%s\n", err ? ": Err" : "");
+
+ dev_kfree_skb(priv->tx_skb);
+ priv->tx_skb = NULL;
+
+ netif_wake_queue(dev);
+
+ mutex_unlock(&priv->lock);
+}
+
+static int encx24j600_receive_packet(struct encx24j600_priv *priv,
+ struct rsv *rsv)
+{
+ struct net_device *dev = priv->ndev;
+ struct sk_buff *skb = netdev_alloc_skb(dev, rsv->len + NET_IP_ALIGN);
+ if (!skb) {
+ pr_err_ratelimited("RX: OOM: packet dropped\n");
+ dev->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+ encx24j600_raw_read(priv, RRXDATA, skb_put(skb, rsv->len), rsv->len);
+
+ if (netif_msg_pktdata(priv))
+ dump_packet("RX", skb->len, skb->data);
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+
+ /* Maintain stats */
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += rsv->len;
+ priv->next_packet = rsv->next_packet;
+
+ netif_rx(skb);
+
+ return 0;
+}
+
+static void encx24j600_rx_packets(struct encx24j600_priv *priv, u8 packet_count)
+{
+ struct net_device *dev = priv->ndev;
+
+ while (packet_count--) {
+ struct rsv rsv;
+ u16 newrxtail;
+
+ encx24j600_write_reg(priv, ERXRDPT, priv->next_packet);
+ encx24j600_raw_read(priv, RRXDATA, (u8 *)&rsv, sizeof(rsv));
+
+ if (netif_msg_rx_status(priv))
+ encx24j600_dump_rsv(priv, __func__, &rsv);
+
+ if (!RSV_GETBIT(rsv.rxstat, RSV_RXOK) ||
+ (rsv.len > MAX_FRAMELEN)) {
+ netif_err(priv, rx_err, dev, "RX Error %04x\n",
+ rsv.rxstat);
+ dev->stats.rx_errors++;
+
+ if (RSV_GETBIT(rsv.rxstat, RSV_CRCERROR))
+ dev->stats.rx_crc_errors++;
+ if (RSV_GETBIT(rsv.rxstat, RSV_LENCHECKERR))
+ dev->stats.rx_frame_errors++;
+ if (rsv.len > MAX_FRAMELEN)
+ dev->stats.rx_over_errors++;
+ } else {
+ encx24j600_receive_packet(priv, &rsv);
+ }
+
+ newrxtail = priv->next_packet - 2;
+ if (newrxtail == ENC_RX_BUF_START)
+ newrxtail = SRAM_SIZE - 2;
+
+ encx24j600_cmd(priv, SETPKTDEC);
+ encx24j600_write_reg(priv, ERXTAIL, newrxtail);
+ }
+}
+
+static irqreturn_t encx24j600_isr(int irq, void *dev_id)
+{
+ struct encx24j600_priv *priv = dev_id;
+ struct net_device *dev = priv->ndev;
+ int eir;
+
+ /* Clear interrupts */
+ encx24j600_cmd(priv, CLREIE);
+
+ eir = encx24j600_read_reg(priv, EIR);
+
+ if (eir & LINKIF)
+ encx24j600_int_link_handler(priv);
+
+ if (eir & TXIF)
+ encx24j600_tx_complete(priv, false);
+
+ if (eir & TXABTIF)
+ encx24j600_tx_complete(priv, true);
+
+ if (eir & RXABTIF) {
+ if (eir & PCFULIF) {
+ /* Packet counter is full */
+ netif_err(priv, rx_err, dev, "Packet counter full\n");
+ }
+ dev->stats.rx_dropped++;
+ encx24j600_clr_bits(priv, EIR, RXABTIF);
+ }
+
+ if (eir & PKTIF) {
+ u8 packet_count;
+
+ mutex_lock(&priv->lock);
+
+ packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff;
+ while (packet_count) {
+ encx24j600_rx_packets(priv, packet_count);
+ packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff;
+ }
+
+ mutex_unlock(&priv->lock);
+ }
+
+ /* Enable interrupts */
+ encx24j600_cmd(priv, SETEIE);
+
+ return IRQ_HANDLED;
+}
+
+static int encx24j600_soft_reset(struct encx24j600_priv *priv)
+{
+ int ret = 0;
+ int timeout;
+ u16 eudast;
+
+ /* Write and verify a test value to EUDAST */
+ regcache_cache_bypass(priv->ctx.regmap, true);
+ timeout = 10;
+ do {
+ encx24j600_write_reg(priv, EUDAST, EUDAST_TEST_VAL);
+ eudast = encx24j600_read_reg(priv, EUDAST);
+ usleep_range(25, 100);
+ } while ((eudast != EUDAST_TEST_VAL) && --timeout);
+ regcache_cache_bypass(priv->ctx.regmap, false);
+
+ if (timeout == 0) {
+ ret = -ETIMEDOUT;
+ goto err_out;
+ }
+
+ /* Wait for CLKRDY to become set */
+ timeout = 10;
+ while (!(encx24j600_read_reg(priv, ESTAT) & CLKRDY) && --timeout)
+ usleep_range(25, 100);
+
+ if (timeout == 0) {
+ ret = -ETIMEDOUT;
+ goto err_out;
+ }
+
+ /* Issue a System Reset command */
+ encx24j600_cmd(priv, SETETHRST);
+ usleep_range(25, 100);
+
+ /* Confirm that EUDAST has 0000h after system reset */
+ if (encx24j600_read_reg(priv, EUDAST) != 0) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ /* Wait for PHY register and status bits to become available */
+ usleep_range(256, 1000);
+
+err_out:
+ return ret;
+}
+
+static int encx24j600_hw_reset(struct encx24j600_priv *priv)
+{
+ int ret;
+
+ mutex_lock(&priv->lock);
+ ret = encx24j600_soft_reset(priv);
+ mutex_unlock(&priv->lock);
+
+ return ret;
+}
+
+static void encx24j600_reset_hw_tx(struct encx24j600_priv *priv)
+{
+ encx24j600_set_bits(priv, ECON2, TXRST);
+ encx24j600_clr_bits(priv, ECON2, TXRST);
+}
+
+static void encx24j600_hw_init_tx(struct encx24j600_priv *priv)
+{
+ /* Reset TX */
+ encx24j600_reset_hw_tx(priv);
+
+ /* Clear the TXIF flag if were previously set */
+ encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF);
+
+ /* Write the Tx Buffer pointer */
+ encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START);
+}
+
+static void encx24j600_hw_init_rx(struct encx24j600_priv *priv)
+{
+ encx24j600_cmd(priv, DISABLERX);
+
+ /* Set up RX packet start address in the SRAM */
+ encx24j600_write_reg(priv, ERXST, ENC_RX_BUF_START);
+
+ /* Preload the RX Data pointer to the beginning of the RX area */
+ encx24j600_write_reg(priv, ERXRDPT, ENC_RX_BUF_START);
+
+ priv->next_packet = ENC_RX_BUF_START;
+
+ /* Set up RX end address in the SRAM */
+ encx24j600_write_reg(priv, ERXTAIL, ENC_SRAM_SIZE - 2);
+
+ /* Reset the user data pointers */
+ encx24j600_write_reg(priv, EUDAST, ENC_SRAM_SIZE);
+ encx24j600_write_reg(priv, EUDAND, ENC_SRAM_SIZE + 1);
+
+ /* Set Max Frame length */
+ encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN);
+}
+
+static void encx24j600_dump_config(struct encx24j600_priv *priv,
+ const char *msg)
+{
+ pr_info(DRV_NAME ": %s\n", msg);
+
+ /* CHIP configuration */
+ pr_info(DRV_NAME " ECON1: %04X\n", encx24j600_read_reg(priv, ECON1));
+ pr_info(DRV_NAME " ECON2: %04X\n", encx24j600_read_reg(priv, ECON2));
+ pr_info(DRV_NAME " ERXFCON: %04X\n", encx24j600_read_reg(priv,
+ ERXFCON));
+ pr_info(DRV_NAME " ESTAT: %04X\n", encx24j600_read_reg(priv, ESTAT));
+ pr_info(DRV_NAME " EIR: %04X\n", encx24j600_read_reg(priv, EIR));
+ pr_info(DRV_NAME " EIDLED: %04X\n", encx24j600_read_reg(priv, EIDLED));
+
+ /* MAC layer configuration */
+ pr_info(DRV_NAME " MACON1: %04X\n", encx24j600_read_reg(priv, MACON1));
+ pr_info(DRV_NAME " MACON2: %04X\n", encx24j600_read_reg(priv, MACON2));
+ pr_info(DRV_NAME " MAIPG: %04X\n", encx24j600_read_reg(priv, MAIPG));
+ pr_info(DRV_NAME " MACLCON: %04X\n", encx24j600_read_reg(priv,
+ MACLCON));
+ pr_info(DRV_NAME " MABBIPG: %04X\n", encx24j600_read_reg(priv,
+ MABBIPG));
+
+ /* PHY configuation */
+ pr_info(DRV_NAME " PHCON1: %04X\n", encx24j600_read_phy(priv, PHCON1));
+ pr_info(DRV_NAME " PHCON2: %04X\n", encx24j600_read_phy(priv, PHCON2));
+ pr_info(DRV_NAME " PHANA: %04X\n", encx24j600_read_phy(priv, PHANA));
+ pr_info(DRV_NAME " PHANLPA: %04X\n", encx24j600_read_phy(priv,
+ PHANLPA));
+ pr_info(DRV_NAME " PHANE: %04X\n", encx24j600_read_phy(priv, PHANE));
+ pr_info(DRV_NAME " PHSTAT1: %04X\n", encx24j600_read_phy(priv,
+ PHSTAT1));
+ pr_info(DRV_NAME " PHSTAT2: %04X\n", encx24j600_read_phy(priv,
+ PHSTAT2));
+ pr_info(DRV_NAME " PHSTAT3: %04X\n", encx24j600_read_phy(priv,
+ PHSTAT3));
+}
+
+static void encx24j600_set_rxfilter_mode(struct encx24j600_priv *priv)
+{
+ switch (priv->rxfilter) {
+ case RXFILTER_PROMISC:
+ encx24j600_set_bits(priv, MACON1, PASSALL);
+ encx24j600_write_reg(priv, ERXFCON, UCEN | MCEN | NOTMEEN);
+ break;
+ case RXFILTER_MULTI:
+ encx24j600_clr_bits(priv, MACON1, PASSALL);
+ encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN | MCEN);
+ break;
+ case RXFILTER_NORMAL:
+ default:
+ encx24j600_clr_bits(priv, MACON1, PASSALL);
+ encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN);
+ break;
+ }
+}
+
+static int encx24j600_hw_init(struct encx24j600_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+ int ret = 0;
+ u16 eidled;
+ u16 macon2;
+
+ priv->hw_enabled = false;
+
+ eidled = encx24j600_read_reg(priv, EIDLED);
+ if (((eidled & DEVID_MASK) >> DEVID_SHIFT) != ENCX24J600_DEV_ID) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ netif_info(priv, drv, dev, "Silicon rev ID: 0x%02x\n",
+ (eidled & REVID_MASK) >> REVID_SHIFT);
+
+ /* PHY Leds: link status,
+ * LEDA: Link State + collision events
+ * LEDB: Link State + transmit/receive events
+ */
+ encx24j600_update_reg(priv, EIDLED, 0xff00, 0xcb00);
+
+ /* Loopback disabled */
+ encx24j600_write_reg(priv, MACON1, 0x9);
+
+ /* interpacket gap value */
+ encx24j600_write_reg(priv, MAIPG, 0x0c12);
+
+ /* Write the auto negotiation pattern */
+ encx24j600_write_phy(priv, PHANA, PHANA_DEFAULT);
+
+ encx24j600_update_phcon1(priv);
+ encx24j600_check_link_status(priv);
+
+ macon2 = MACON2_RSV1 | TXCRCEN | PADCFG0 | PADCFG2 | MACON2_DEFER;
+ if ((priv->autoneg == AUTONEG_DISABLE) && priv->full_duplex)
+ macon2 |= FULDPX;
+
+ encx24j600_set_bits(priv, MACON2, macon2);
+
+ priv->rxfilter = RXFILTER_NORMAL;
+ encx24j600_set_rxfilter_mode(priv);
+
+ /* Program the Maximum frame length */
+ encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN);
+
+ /* Init Tx pointers */
+ encx24j600_hw_init_tx(priv);
+
+ /* Init Rx pointers */
+ encx24j600_hw_init_rx(priv);
+
+ if (netif_msg_hw(priv))
+ encx24j600_dump_config(priv, "Hw is initialized");
+
+err_out:
+ return ret;
+}
+
+static void encx24j600_hw_enable(struct encx24j600_priv *priv)
+{
+ /* Clear the interrupt flags in case was set */
+ encx24j600_clr_bits(priv, EIR, (PCFULIF | RXABTIF | TXABTIF | TXIF |
+ PKTIF | LINKIF));
+
+ /* Enable the interrupts */
+ encx24j600_write_reg(priv, EIE, (PCFULIE | RXABTIE | TXABTIE | TXIE |
+ PKTIE | LINKIE | INTIE));
+
+ /* Enable RX */
+ encx24j600_cmd(priv, ENABLERX);
+
+ priv->hw_enabled = true;
+}
+
+static void encx24j600_hw_disable(struct encx24j600_priv *priv)
+{
+ /* Disable all interrupts */
+ encx24j600_write_reg(priv, EIE, 0);
+
+ /* Disable RX */
+ encx24j600_cmd(priv, DISABLERX);
+
+ priv->hw_enabled = false;
+}
+
+static int encx24j600_setlink(struct net_device *dev, u8 autoneg, u16 speed,
+ u8 duplex)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+ int ret = 0;
+
+ if (!priv->hw_enabled) {
+ /* link is in low power mode now; duplex setting
+ * will take effect on next encx24j600_hw_init()
+ */
+ if (speed == SPEED_10 || speed == SPEED_100) {
+ priv->autoneg = (autoneg == AUTONEG_ENABLE);
+ priv->full_duplex = (duplex == DUPLEX_FULL);
+ priv->speed = (speed == SPEED_100);
+ } else {
+ netif_warn(priv, link, dev, "unsupported link speed setting\n");
+ /*speeds other than SPEED_10 and SPEED_100 */
+ /*are not supported by chip */
+ ret = -EOPNOTSUPP;
+ }
+ } else {
+ netif_warn(priv, link, dev, "Warning: hw must be disabled to set link mode\n");
+ ret = -EBUSY;
+ }
+ return ret;
+}
+
+static void encx24j600_hw_get_macaddr(struct encx24j600_priv *priv,
+ unsigned char *ethaddr)
+{
+ unsigned short val;
+
+ val = encx24j600_read_reg(priv, MAADR1);
+
+ ethaddr[0] = val & 0x00ff;
+ ethaddr[1] = (val & 0xff00) >> 8;
+
+ val = encx24j600_read_reg(priv, MAADR2);
+
+ ethaddr[2] = val & 0x00ffU;
+ ethaddr[3] = (val & 0xff00U) >> 8;
+
+ val = encx24j600_read_reg(priv, MAADR3);
+
+ ethaddr[4] = val & 0x00ffU;
+ ethaddr[5] = (val & 0xff00U) >> 8;
+}
+
+/* Program the hardware MAC address from dev->dev_addr.*/
+static int encx24j600_set_hw_macaddr(struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+
+ if (priv->hw_enabled) {
+ netif_info(priv, drv, dev, "Hardware must be disabled to set Mac address\n");
+ return -EBUSY;
+ }
+
+ mutex_lock(&priv->lock);
+
+ netif_info(priv, drv, dev, "%s: Setting MAC address to %pM\n",
+ dev->name, dev->dev_addr);
+
+ encx24j600_write_reg(priv, MAADR3, (dev->dev_addr[4] |
+ dev->dev_addr[5] << 8));
+ encx24j600_write_reg(priv, MAADR2, (dev->dev_addr[2] |
+ dev->dev_addr[3] << 8));
+ encx24j600_write_reg(priv, MAADR1, (dev->dev_addr[0] |
+ dev->dev_addr[1] << 8));
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+/* Store the new hardware address in dev->dev_addr, and update the MAC.*/
+static int encx24j600_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *address = addr;
+
+ if (netif_running(dev))
+ return -EBUSY;
+ if (!is_valid_ether_addr(address->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
+ return encx24j600_set_hw_macaddr(dev);
+}
+
+static int encx24j600_open(struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+
+ int ret = request_threaded_irq(priv->ctx.spi->irq, NULL, encx24j600_isr,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ DRV_NAME, priv);
+ if (unlikely(ret < 0)) {
+ netdev_err(dev, "request irq %d failed (ret = %d)\n",
+ priv->ctx.spi->irq, ret);
+ return ret;
+ }
+
+ encx24j600_hw_disable(priv);
+ encx24j600_hw_init(priv);
+ encx24j600_hw_enable(priv);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int encx24j600_stop(struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+ free_irq(priv->ctx.spi->irq, priv);
+ return 0;
+}
+
+static void encx24j600_setrx_proc(struct kthread_work *ws)
+{
+ struct encx24j600_priv *priv =
+ container_of(ws, struct encx24j600_priv, setrx_work);
+
+ mutex_lock(&priv->lock);
+ encx24j600_set_rxfilter_mode(priv);
+ mutex_unlock(&priv->lock);
+}
+
+static void encx24j600_set_multicast_list(struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+ int oldfilter = priv->rxfilter;
+
+ if (dev->flags & IFF_PROMISC) {
+ netif_dbg(priv, link, dev, "promiscuous mode\n");
+ priv->rxfilter = RXFILTER_PROMISC;
+ } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
+ netif_dbg(priv, link, dev, "%smulticast mode\n",
+ (dev->flags & IFF_ALLMULTI) ? "all-" : "");
+ priv->rxfilter = RXFILTER_MULTI;
+ } else {
+ netif_dbg(priv, link, dev, "normal mode\n");
+ priv->rxfilter = RXFILTER_NORMAL;
+ }
+
+ if (oldfilter != priv->rxfilter)
+ queue_kthread_work(&priv->kworker, &priv->setrx_work);
+}
+
+static void encx24j600_hw_tx(struct encx24j600_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+ netif_info(priv, tx_queued, dev, "TX Packet Len:%d\n",
+ priv->tx_skb->len);
+
+ if (netif_msg_pktdata(priv))
+ dump_packet("TX", priv->tx_skb->len, priv->tx_skb->data);
+
+ if (encx24j600_read_reg(priv, EIR) & TXABTIF)
+ /* Last transmition aborted due to error. Reset TX interface */
+ encx24j600_reset_hw_tx(priv);
+
+ /* Clear the TXIF flag if were previously set */
+ encx24j600_clr_bits(priv, EIR, TXIF);
+
+ /* Set the data pointer to the TX buffer address in the SRAM */
+ encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START);
+
+ /* Copy the packet into the SRAM */
+ encx24j600_raw_write(priv, WGPDATA, (u8 *)priv->tx_skb->data,
+ priv->tx_skb->len);
+
+ /* Program the Tx buffer start pointer */
+ encx24j600_write_reg(priv, ETXST, ENC_TX_BUF_START);
+
+ /* Program the packet length */
+ encx24j600_write_reg(priv, ETXLEN, priv->tx_skb->len);
+
+ /* Start the transmission */
+ encx24j600_cmd(priv, SETTXRTS);
+}
+
+static void encx24j600_tx_proc(struct kthread_work *ws)
+{
+ struct encx24j600_priv *priv =
+ container_of(ws, struct encx24j600_priv, tx_work);
+
+ mutex_lock(&priv->lock);
+ encx24j600_hw_tx(priv);
+ mutex_unlock(&priv->lock);
+}
+
+static netdev_tx_t encx24j600_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+
+ /* save the timestamp */
+ dev->trans_start = jiffies;
+
+ /* Remember the skb for deferred processing */
+ priv->tx_skb = skb;
+
+ queue_kthread_work(&priv->kworker, &priv->tx_work);
+
+ return NETDEV_TX_OK;
+}
+
+/* Deal with a transmit timeout */
+static void encx24j600_tx_timeout(struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+
+ netif_err(priv, tx_err, dev, "TX timeout at %ld, latency %ld\n",
+ jiffies, jiffies - dev->trans_start);
+
+ dev->stats.tx_errors++;
+ netif_wake_queue(dev);
+ return;
+}
+
+static int encx24j600_get_regs_len(struct net_device *dev)
+{
+ return SFR_REG_COUNT;
+}
+
+static void encx24j600_get_regs(struct net_device *dev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+ u16 *buff = p;
+ u8 reg;
+
+ regs->version = 1;
+ mutex_lock(&priv->lock);
+ for (reg = 0; reg < SFR_REG_COUNT; reg += 2) {
+ unsigned int val = 0;
+ /* ignore errors for unreadable registers */
+ regmap_read(priv->ctx.regmap, reg, &val);
+ buff[reg] = val & 0xffff;
+ }
+ mutex_unlock(&priv->lock);
+}
+
+static void encx24j600_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev_name(dev->dev.parent),
+ sizeof(info->bus_info));
+}
+
+static int encx24j600_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_TP;
+
+ ethtool_cmd_speed_set(cmd, priv->speed);
+ cmd->duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+ cmd->port = PORT_TP;
+ cmd->autoneg = priv->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+
+ return 0;
+}
+
+static int encx24j600_set_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ return encx24j600_setlink(dev, cmd->autoneg,
+ ethtool_cmd_speed(cmd), cmd->duplex);
+}
+
+static u32 encx24j600_get_msglevel(struct net_device *dev)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+ return priv->msg_enable;
+}
+
+static void encx24j600_set_msglevel(struct net_device *dev, u32 val)
+{
+ struct encx24j600_priv *priv = netdev_priv(dev);
+ priv->msg_enable = val;
+}
+
+static const struct ethtool_ops encx24j600_ethtool_ops = {
+ .get_settings = encx24j600_get_settings,
+ .set_settings = encx24j600_set_settings,
+ .get_drvinfo = encx24j600_get_drvinfo,
+ .get_msglevel = encx24j600_get_msglevel,
+ .set_msglevel = encx24j600_set_msglevel,
+ .get_regs_len = encx24j600_get_regs_len,
+ .get_regs = encx24j600_get_regs,
+};
+
+static const struct net_device_ops encx24j600_netdev_ops = {
+ .ndo_open = encx24j600_open,
+ .ndo_stop = encx24j600_stop,
+ .ndo_start_xmit = encx24j600_tx,
+ .ndo_set_rx_mode = encx24j600_set_multicast_list,
+ .ndo_set_mac_address = encx24j600_set_mac_address,
+ .ndo_tx_timeout = encx24j600_tx_timeout,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static int encx24j600_spi_probe(struct spi_device *spi)
+{
+ int ret;
+
+ struct net_device *ndev;
+ struct encx24j600_priv *priv;
+
+ ndev = alloc_etherdev(sizeof(struct encx24j600_priv));
+
+ if (!ndev) {
+ ret = -ENOMEM;
+ goto error_out;
+ }
+
+ priv = netdev_priv(ndev);
+ spi_set_drvdata(spi, priv);
+ dev_set_drvdata(&spi->dev, priv);
+ SET_NETDEV_DEV(ndev, &spi->dev);
+
+ priv->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
+ priv->ndev = ndev;
+
+ /* Default configuration PHY configuration */
+ priv->full_duplex = true;
+ priv->autoneg = AUTONEG_ENABLE;
+ priv->speed = SPEED_100;
+
+ priv->ctx.spi = spi;
+ devm_regmap_init_encx24j600(&spi->dev, &priv->ctx);
+ ndev->irq = spi->irq;
+ ndev->netdev_ops = &encx24j600_netdev_ops;
+
+ mutex_init(&priv->lock);
+
+ /* Reset device and check if it is connected */
+ if (encx24j600_hw_reset(priv)) {
+ netif_err(priv, probe, ndev,
+ DRV_NAME ": Chip is not detected\n");
+ ret = -EIO;
+ goto out_free;
+ }
+
+ /* Initialize the device HW to the consistent state */
+ if (encx24j600_hw_init(priv)) {
+ netif_err(priv, probe, ndev,
+ DRV_NAME ": HW initialization error\n");
+ ret = -EIO;
+ goto out_free;
+ }
+
+ init_kthread_worker(&priv->kworker);
+ init_kthread_work(&priv->tx_work, encx24j600_tx_proc);
+ init_kthread_work(&priv->setrx_work, encx24j600_setrx_proc);
+
+ priv->kworker_task = kthread_run(kthread_worker_fn, &priv->kworker,
+ "encx24j600");
+
+ if (IS_ERR(priv->kworker_task)) {
+ ret = PTR_ERR(priv->kworker_task);
+ goto out_free;
+ }
+
+ /* Get the MAC address from the chip */
+ encx24j600_hw_get_macaddr(priv, ndev->dev_addr);
+
+ ndev->ethtool_ops = &encx24j600_ethtool_ops;
+
+ ret = register_netdev(ndev);
+ if (unlikely(ret)) {
+ netif_err(priv, probe, ndev, "Error %d initializing card encx24j600 card\n",
+ ret);
+ goto out_free;
+ }
+
+ netif_info(priv, drv, priv->ndev, "MAC address %pM\n", ndev->dev_addr);
+
+ return ret;
+
+out_free:
+ free_netdev(ndev);
+
+error_out:
+ return ret;
+}
+
+static int encx24j600_spi_remove(struct spi_device *spi)
+{
+ struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev);
+
+ unregister_netdev(priv->ndev);
+
+ free_netdev(priv->ndev);
+
+ return 0;
+}
+
+static const struct spi_device_id encx24j600_spi_id_table[] = {
+ { .name = "encx24j600" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(spi, encx24j600_spi_id_table);
+
+static struct spi_driver encx24j600_spi_net_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .bus = &spi_bus_type,
+ },
+ .probe = encx24j600_spi_probe,
+ .remove = encx24j600_spi_remove,
+ .id_table = encx24j600_spi_id_table,
+};
+
+static int __init encx24j600_init(void)
+{
+ return spi_register_driver(&encx24j600_spi_net_driver);
+}
+module_init(encx24j600_init);
+
+static void encx24j600_exit(void)
+{
+ spi_unregister_driver(&encx24j600_spi_net_driver);
+}
+module_exit(encx24j600_exit);
+
+MODULE_DESCRIPTION(DRV_NAME " ethernet driver");
+MODULE_AUTHOR("Jon Ringle <jringle@gridpoint.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/net/ethernet/microchip/encx24j600_hw.h b/drivers/net/ethernet/microchip/encx24j600_hw.h
new file mode 100644
index 000000000000..4be73d5553f8
--- /dev/null
+++ b/drivers/net/ethernet/microchip/encx24j600_hw.h
@@ -0,0 +1,437 @@
+/**
+ * encx24j600_hw.h: Register definitions
+ *
+ */
+
+#ifndef _ENCX24J600_HW_H
+#define _ENCX24J600_HW_H
+
+struct encx24j600_context {
+ struct spi_device *spi;
+ struct regmap *regmap;
+ struct regmap *phymap;
+ struct mutex mutex; /* mutex to protect access to regmap */
+ int bank;
+};
+
+void devm_regmap_init_encx24j600(struct device *dev,
+ struct encx24j600_context *ctx);
+
+/* Single-byte instructions */
+#define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1))
+#define B0SEL 0xC0 /* Bank 0 Select */
+#define B1SEL 0xC2 /* Bank 1 Select */
+#define B2SEL 0xC4 /* Bank 2 Select */
+#define B3SEL 0xC6 /* Bank 3 Select */
+#define SETETHRST 0xCA /* System Reset */
+#define FCDISABLE 0xE0 /* Flow Control Disable */
+#define FCSINGLE 0xE2 /* Flow Control Single */
+#define FCMULTIPLE 0xE4 /* Flow Control Multiple */
+#define FCCLEAR 0xE6 /* Flow Control Clear */
+#define SETPKTDEC 0xCC /* Decrement Packet Counter */
+#define DMASTOP 0xD2 /* DMA Stop */
+#define DMACKSUM 0xD8 /* DMA Start Checksum */
+#define DMACKSUMS 0xDA /* DMA Start Checksum with Seed */
+#define DMACOPY 0xDC /* DMA Start Copy */
+#define DMACOPYS 0xDE /* DMA Start Copy and Checksum with Seed */
+#define SETTXRTS 0xD4 /* Request Packet Transmission */
+#define ENABLERX 0xE8 /* Enable RX */
+#define DISABLERX 0xEA /* Disable RX */
+#define SETEIE 0xEC /* Enable Interrupts */
+#define CLREIE 0xEE /* Disable Interrupts */
+
+/* Two byte instructions */
+#define RBSEL 0xC8 /* Read Bank Select */
+
+/* Three byte instructions */
+#define WGPRDPT 0x60 /* Write EGPRDPT */
+#define RGPRDPT 0x62 /* Read EGPRDPT */
+#define WRXRDPT 0x64 /* Write ERXRDPT */
+#define RRXRDPT 0x66 /* Read ERXRDPT */
+#define WUDARDPT 0x68 /* Write EUDARDPT */
+#define RUDARDPT 0x6A /* Read EUDARDPT */
+#define WGPWRPT 0x6C /* Write EGPWRPT */
+#define RGPWRPT 0x6E /* Read EGPWRPT */
+#define WRXWRPT 0x70 /* Write ERXWRPT */
+#define RRXWRPT 0x72 /* Read ERXWRPT */
+#define WUDAWRPT 0x74 /* Write EUDAWRPT */
+#define RUDAWRPT 0x76 /* Read EUDAWRPT */
+
+/* n byte instructions */
+#define RCRCODE 0x00
+#define WCRCODE 0x40
+#define BFSCODE 0x80
+#define BFCCODE 0xA0
+#define RCR(addr) (RCRCODE | (addr & ADDR_MASK)) /* Read Control Register */
+#define WCR(addr) (WCRCODE | (addr & ADDR_MASK)) /* Write Control Register */
+#define RCRU 0x20 /* Read Control Register Unbanked */
+#define WCRU 0x22 /* Write Control Register Unbanked */
+#define BFS(addr) (BFSCODE | (addr & ADDR_MASK)) /* Bit Field Set */
+#define BFC(addr) (BFCCODE | (addr & ADDR_MASK)) /* Bit Field Clear */
+#define BFSU 0x24 /* Bit Field Set Unbanked */
+#define BFCU 0x26 /* Bit Field Clear Unbanked */
+#define RGPDATA 0x28 /* Read EGPDATA */
+#define WGPDATA 0x2A /* Write EGPDATA */
+#define RRXDATA 0x2C /* Read ERXDATA */
+#define WRXDATA 0x2E /* Write ERXDATA */
+#define RUDADATA 0x30 /* Read EUDADATA */
+#define WUDADATA 0x32 /* Write EUDADATA */
+
+#define SFR_REG_COUNT 0xA0
+
+/* ENC424J600 Control Registers
+ * Control register definitions are a combination of address
+ * and bank number
+ * - Register address (bits 0-4)
+ * - Bank number (bits 5-6)
+ */
+#define ADDR_MASK 0x1F
+#define BANK_MASK 0x60
+#define BANK_SHIFT 5
+
+/* All-bank registers */
+#define EUDAST 0x16
+#define EUDAND 0x18
+#define ESTAT 0x1A
+#define EIR 0x1C
+#define ECON1 0x1E
+
+/* Bank 0 registers */
+#define ETXST (0x00 | 0x00)
+#define ETXLEN (0x02 | 0x00)
+#define ERXST (0x04 | 0x00)
+#define ERXTAIL (0x06 | 0x00)
+#define ERXHEAD (0x08 | 0x00)
+#define EDMAST (0x0A | 0x00)
+#define EDMALEN (0x0C | 0x00)
+#define EDMADST (0x0E | 0x00)
+#define EDMACS (0x10 | 0x00)
+#define ETXSTAT (0x12 | 0x00)
+#define ETXWIRE (0x14 | 0x00)
+
+/* Bank 1 registers */
+#define EHT1 (0x00 | 0x20)
+#define EHT2 (0x02 | 0x20)
+#define EHT3 (0x04 | 0x20)
+#define EHT4 (0x06 | 0x20)
+#define EPMM1 (0x08 | 0x20)
+#define EPMM2 (0x0A | 0x20)
+#define EPMM3 (0x0C | 0x20)
+#define EPMM4 (0x0E | 0x20)
+#define EPMCS (0x10 | 0x20)
+#define EPMO (0x12 | 0x20)
+#define ERXFCON (0x14 | 0x20)
+
+/* Bank 2 registers */
+#define MACON1 (0x00 | 0x40)
+#define MACON2 (0x02 | 0x40)
+#define MABBIPG (0x04 | 0x40)
+#define MAIPG (0x06 | 0x40)
+#define MACLCON (0x08 | 0x40)
+#define MAMXFL (0x0A | 0x40)
+#define MICMD (0x12 | 0x40)
+#define MIREGADR (0x14 | 0x40)
+
+/* Bank 3 registers */
+#define MAADR3 (0x00 | 0x60)
+#define MAADR2 (0x02 | 0x60)
+#define MAADR1 (0x04 | 0x60)
+#define MIWR (0x06 | 0x60)
+#define MIRD (0x08 | 0x60)
+#define MISTAT (0x0A | 0x60)
+#define EPAUS (0x0C | 0x60)
+#define ECON2 (0x0E | 0x60)
+#define ERXWM (0x10 | 0x60)
+#define EIE (0x12 | 0x60)
+#define EIDLED (0x14 | 0x60)
+
+/* Unbanked registers */
+#define EGPDATA (0x00 | 0x80)
+#define ERXDATA (0x02 | 0x80)
+#define EUDADATA (0x04 | 0x80)
+#define EGPRDPT (0x06 | 0x80)
+#define EGPWRPT (0x08 | 0x80)
+#define ERXRDPT (0x0A | 0x80)
+#define ERXWRPT (0x0C | 0x80)
+#define EUDARDPT (0x0E | 0x80)
+#define EUDAWRPT (0x10 | 0x80)
+
+
+/* Register bit definitions */
+/* ESTAT */
+#define INT (1 << 15)
+#define FCIDLE (1 << 14)
+#define RXBUSY (1 << 13)
+#define CLKRDY (1 << 12)
+#define PHYDPX (1 << 10)
+#define PHYLNK (1 << 8)
+
+/* EIR */
+#define CRYPTEN (1 << 15)
+#define MODEXIF (1 << 14)
+#define HASHIF (1 << 13)
+#define AESIF (1 << 12)
+#define LINKIF (1 << 11)
+#define PKTIF (1 << 6)
+#define DMAIF (1 << 5)
+#define TXIF (1 << 3)
+#define TXABTIF (1 << 2)
+#define RXABTIF (1 << 1)
+#define PCFULIF (1 << 0)
+
+/* ECON1 */
+#define MODEXST (1 << 15)
+#define HASHEN (1 << 14)
+#define HASHOP (1 << 13)
+#define HASHLST (1 << 12)
+#define AESST (1 << 11)
+#define AESOP1 (1 << 10)
+#define AESOP0 (1 << 9)
+#define PKTDEC (1 << 8)
+#define FCOP1 (1 << 7)
+#define FCOP0 (1 << 6)
+#define DMAST (1 << 5)
+#define DMACPY (1 << 4)
+#define DMACSSD (1 << 3)
+#define DMANOCS (1 << 2)
+#define TXRTS (1 << 1)
+#define RXEN (1 << 0)
+
+/* ETXSTAT */
+#define LATECOL (1 << 10)
+#define MAXCOL (1 << 9)
+#define EXDEFER (1 << 8)
+#define ETXSTATL_DEFER (1 << 7)
+#define CRCBAD (1 << 4)
+#define COLCNT_MASK 0xF
+
+/* ERXFCON */
+#define HTEN (1 << 15)
+#define MPEN (1 << 14)
+#define NOTPM (1 << 12)
+#define PMEN3 (1 << 11)
+#define PMEN2 (1 << 10)
+#define PMEN1 (1 << 9)
+#define PMEN0 (1 << 8)
+#define CRCEEN (1 << 7)
+#define CRCEN (1 << 6)
+#define RUNTEEN (1 << 5)
+#define RUNTEN (1 << 4)
+#define UCEN (1 << 3)
+#define NOTMEEN (1 << 2)
+#define MCEN (1 << 1)
+#define BCEN (1 << 0)
+
+/* MACON1 */
+#define LOOPBK (1 << 4)
+#define RXPAUS (1 << 2)
+#define PASSALL (1 << 1)
+
+/* MACON2 */
+#define MACON2_DEFER (1 << 14)
+#define BPEN (1 << 13)
+#define NOBKOFF (1 << 12)
+#define PADCFG2 (1 << 7)
+#define PADCFG1 (1 << 6)
+#define PADCFG0 (1 << 5)
+#define TXCRCEN (1 << 4)
+#define PHDREN (1 << 3)
+#define HFRMEN (1 << 2)
+#define MACON2_RSV1 (1 << 1)
+#define FULDPX (1 << 0)
+
+/* MAIPG */
+/* value of the high byte is given by the reserved bits,
+ * value of the low byte is recomended setting of the
+ * IPG parameter.
+ */
+#define MAIPGH_VAL 0x0C
+#define MAIPGL_VAL 0x12
+
+/* MIREGADRH */
+#define MIREGADR_VAL (1 << 8)
+
+/* MIREGADRL */
+#define PHREG_MASK 0x1F
+
+/* MICMD */
+#define MIISCAN (1 << 1)
+#define MIIRD (1 << 0)
+
+/* MISTAT */
+#define NVALID (1 << 2)
+#define SCAN (1 << 1)
+#define BUSY (1 << 0)
+
+/* ECON2 */
+#define ETHEN (1 << 15)
+#define STRCH (1 << 14)
+#define TXMAC (1 << 13)
+#define SHA1MD5 (1 << 12)
+#define COCON3 (1 << 11)
+#define COCON2 (1 << 10)
+#define COCON1 (1 << 9)
+#define COCON0 (1 << 8)
+#define AUTOFC (1 << 7)
+#define TXRST (1 << 6)
+#define RXRST (1 << 5)
+#define ETHRST (1 << 4)
+#define MODLEN1 (1 << 3)
+#define MODLEN0 (1 << 2)
+#define AESLEN1 (1 << 1)
+#define AESLEN0 (1 << 0)
+
+/* EIE */
+#define INTIE (1 << 15)
+#define MODEXIE (1 << 14)
+#define HASHIE (1 << 13)
+#define AESIE (1 << 12)
+#define LINKIE (1 << 11)
+#define PKTIE (1 << 6)
+#define DMAIE (1 << 5)
+#define TXIE (1 << 3)
+#define TXABTIE (1 << 2)
+#define RXABTIE (1 << 1)
+#define PCFULIE (1 << 0)
+
+/* EIDLED */
+#define LACFG3 (1 << 15)
+#define LACFG2 (1 << 14)
+#define LACFG1 (1 << 13)
+#define LACFG0 (1 << 12)
+#define LBCFG3 (1 << 11)
+#define LBCFG2 (1 << 10)
+#define LBCFG1 (1 << 9)
+#define LBCFG0 (1 << 8)
+#define DEVID_SHIFT 5
+#define DEVID_MASK (0x7 << DEVID_SHIFT)
+#define REVID_SHIFT 0
+#define REVID_MASK (0x1F << REVID_SHIFT)
+
+/* PHY registers */
+#define PHCON1 0x00
+#define PHSTAT1 0x01
+#define PHANA 0x04
+#define PHANLPA 0x05
+#define PHANE 0x06
+#define PHCON2 0x11
+#define PHSTAT2 0x1B
+#define PHSTAT3 0x1F
+
+/* PHCON1 */
+#define PRST (1 << 15)
+#define PLOOPBK (1 << 14)
+#define SPD100 (1 << 13)
+#define ANEN (1 << 12)
+#define PSLEEP (1 << 11)
+#define RENEG (1 << 9)
+#define PFULDPX (1 << 8)
+
+/* PHSTAT1 */
+#define FULL100 (1 << 14)
+#define HALF100 (1 << 13)
+#define FULL10 (1 << 12)
+#define HALF10 (1 << 11)
+#define ANDONE (1 << 5)
+#define LRFAULT (1 << 4)
+#define ANABLE (1 << 3)
+#define LLSTAT (1 << 2)
+#define EXTREGS (1 << 0)
+
+/* PHSTAT2 */
+#define PLRITY (1 << 4)
+
+/* PHSTAT3 */
+#define PHY3SPD100 (1 << 3)
+#define PHY3DPX (1 << 4)
+#define SPDDPX_SHIFT 2
+#define SPDDPX_MASK (0x7 << SPDDPX_SHIFT)
+
+/* PHANA */
+/* Default value for PHY initialization*/
+#define PHANA_DEFAULT 0x05E1
+
+/* PHANE */
+#define PDFLT (1 << 4)
+#define LPARCD (1 << 1)
+#define LPANABL (1 << 0)
+
+#define EUDAST_TEST_VAL 0x1234
+
+#define TSV_SIZE 7
+
+#define ENCX24J600_DEV_ID 0x1
+
+/* Configuration */
+
+/* Led is on when the link is present and driven low
+ * temporarily when packet is TX'd or RX'd
+ */
+#define LED_A_SETTINGS 0xC
+
+/* Led is on if the link is in 100 Mbps mode */
+#define LED_B_SETTINGS 0x8
+
+/* maximum ethernet frame length
+ * Currently not used as a limit anywhere
+ * (we're using the "huge frame enable" feature of
+ * enc424j600).
+ */
+#define MAX_FRAMELEN 1518
+
+/* Size in bytes of the receive buffer in enc424j600.
+ * Must be word aligned (even).
+ */
+#define RX_BUFFER_SIZE (15 * MAX_FRAMELEN)
+
+/* Start of the general purpose area in sram */
+#define SRAM_GP_START 0x0
+
+/* SRAM size */
+#define SRAM_SIZE 0x6000
+
+/* Start of the receive buffer */
+#define ERXST_VAL (SRAM_SIZE - RX_BUFFER_SIZE)
+
+#define RSV_RXLONGEVDROPEV 16
+#define RSV_CARRIEREV 18
+#define RSV_CRCERROR 20
+#define RSV_LENCHECKERR 21
+#define RSV_LENOUTOFRANGE 22
+#define RSV_RXOK 23
+#define RSV_RXMULTICAST 24
+#define RSV_RXBROADCAST 25
+#define RSV_DRIBBLENIBBLE 26
+#define RSV_RXCONTROLFRAME 27
+#define RSV_RXPAUSEFRAME 28
+#define RSV_RXUNKNOWNOPCODE 29
+#define RSV_RXTYPEVLAN 30
+
+#define RSV_RUNTFILTERMATCH 31
+#define RSV_NOTMEFILTERMATCH 32
+#define RSV_HASHFILTERMATCH 33
+#define RSV_MAGICPKTFILTERMATCH 34
+#define RSV_PTRNMTCHFILTERMATCH 35
+#define RSV_UNICASTFILTERMATCH 36
+
+#define RSV_SIZE 8
+#define RSV_BITMASK(x) (1 << ((x) - 16))
+#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0)
+
+struct rsv {
+ u16 next_packet;
+ u16 len;
+ u32 rxstat;
+};
+
+/* Put RX buffer at 0 as suggested by the Errata datasheet */
+
+#define RXSTART_INIT ERXST_VAL
+#define RXEND_INIT 0x5FFF
+
+int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data,
+ size_t count);
+int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count);
+
+
+#endif
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 2d1b94274079..9ba975853ec6 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -5389,8 +5389,6 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
strlcpy(info->driver, s2io_driver_name, sizeof(info->driver));
strlcpy(info->version, s2io_driver_version, sizeof(info->version));
strlcpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
- info->regdump_len = XENA_REG_SPACE;
- info->eedump_len = XENA_EEPROM_SPACE;
}
/**
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
index be916eb2f2e7..9a2967016c18 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
@@ -105,10 +105,6 @@ static void vxge_ethtool_gdrvinfo(struct net_device *dev,
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->fw_version, vdev->fw_version, sizeof(info->fw_version));
strlcpy(info->bus_info, pci_name(vdev->pdev), sizeof(info->bus_info));
- info->regdump_len = sizeof(struct vxge_hw_vpath_reg)
- * vdev->no_of_vpath;
-
- info->n_stats = STAT_LEN;
}
/**
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index a41bb5e6b954..75e88f4c1531 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4076,6 +4076,8 @@ static void nv_do_nic_poll(unsigned long data)
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 mask = 0;
+ unsigned long flags;
+ unsigned int irq = 0;
/*
* First disable irq(s) and then
@@ -4085,25 +4087,27 @@ static void nv_do_nic_poll(unsigned long data)
if (!using_multi_irqs(dev)) {
if (np->msi_flags & NV_MSI_X_ENABLED)
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector;
else
- disable_irq_lockdep(np->pci_dev->irq);
+ irq = np->pci_dev->irq;
mask = np->irqmask;
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector;
mask |= NVREG_IRQ_RX_ALL;
}
if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector;
mask |= NVREG_IRQ_TX_ALL;
}
if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector;
mask |= NVREG_IRQ_OTHER;
}
}
- /* disable_irq() contains synchronize_irq, thus no irq handler can run now */
+
+ disable_irq_nosync_lockdep_irqsave(irq, &flags);
+ synchronize_irq(irq);
if (np->recover_error) {
np->recover_error = 0;
@@ -4156,28 +4160,22 @@ static void nv_do_nic_poll(unsigned long data)
nv_nic_irq_optimized(0, dev);
else
nv_nic_irq(0, dev);
- if (np->msi_flags & NV_MSI_X_ENABLED)
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
- else
- enable_irq_lockdep(np->pci_dev->irq);
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
np->nic_poll_irq &= ~NVREG_IRQ_RX_ALL;
nv_nic_irq_rx(0, dev);
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
np->nic_poll_irq &= ~NVREG_IRQ_TX_ALL;
nv_nic_irq_tx(0, dev);
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
}
if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
np->nic_poll_irq &= ~NVREG_IRQ_OTHER;
nv_nic_irq_other(0, dev);
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
}
}
+ enable_irq_lockdep_irqrestore(irq, &flags);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 66fd868152e5..b159ef8303cc 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -476,13 +476,12 @@ static void __lpc_get_mac(struct netdata_local *pldat, u8 *mac)
mac[5] = tmp >> 8;
}
-static void __lpc_eth_clock_enable(struct netdata_local *pldat,
- bool enable)
+static void __lpc_eth_clock_enable(struct netdata_local *pldat, bool enable)
{
if (enable)
- clk_enable(pldat->clk);
+ clk_prepare_enable(pldat->clk);
else
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
}
static void __lpc_params_setup(struct netdata_local *pldat)
@@ -1494,7 +1493,7 @@ err_out_free_irq:
err_out_iounmap:
iounmap(pldat->net_base);
err_out_disable_clocks:
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
clk_put(pldat->clk);
err_out_free_dev:
free_netdev(ndev);
@@ -1519,7 +1518,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
iounmap(pldat->net_base);
mdiobus_unregister(pldat->mii_bus);
mdiobus_free(pldat->mii_bus);
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
clk_put(pldat->clk);
free_netdev(ndev);
@@ -1540,7 +1539,7 @@ static int lpc_eth_drv_suspend(struct platform_device *pdev,
if (netif_running(ndev)) {
netif_device_detach(ndev);
__lpc_eth_shutdown(pldat);
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
/*
* Reset again now clock is disable to be sure
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index 7bf9c028d8d7..c177c7cec13b 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -1344,10 +1344,6 @@ static void octeon_mgmt_get_drvinfo(struct net_device *netdev,
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
strlcpy(info->bus_info, "N/A", sizeof(info->bus_info));
- info->n_stats = 0;
- info->testinfo_len = 0;
- info->regdump_len = 0;
- info->eedump_len = 0;
}
static int octeon_mgmt_get_settings(struct net_device *netdev,
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
index f6fcf7450352..b19be7c6c1f4 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
@@ -164,7 +164,6 @@ static void pch_gbe_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = pch_gbe_get_regs_len(netdev);
}
/**
diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig
index f1f0108c275d..ddcfcab034c2 100644
--- a/drivers/net/ethernet/qlogic/Kconfig
+++ b/drivers/net/ethernet/qlogic/Kconfig
@@ -91,4 +91,16 @@ config NETXEN_NIC
---help---
This enables the support for NetXen's Gigabit Ethernet card.
+config QED
+ tristate "QLogic QED 25/40/100Gb core driver"
+ depends on PCI
+ select ZLIB_INFLATE
+ ---help---
+ This enables the support for ...
+
+config QEDE
+ tristate "QLogic QED 25/40/100Gb Ethernet NIC"
+ depends on QED
+ ---help---
+ This enables the support for ...
endif # NET_VENDOR_QLOGIC
diff --git a/drivers/net/ethernet/qlogic/Makefile b/drivers/net/ethernet/qlogic/Makefile
index b2a283d9ae60..cee90e05beb8 100644
--- a/drivers/net/ethernet/qlogic/Makefile
+++ b/drivers/net/ethernet/qlogic/Makefile
@@ -6,3 +6,5 @@ obj-$(CONFIG_QLA3XXX) += qla3xxx.o
obj-$(CONFIG_QLCNIC) += qlcnic/
obj-$(CONFIG_QLGE) += qlge/
obj-$(CONFIG_NETXEN_NIC) += netxen/
+obj-$(CONFIG_QED) += qed/
+obj-$(CONFIG_QEDE)+= qede/
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 87e073c6e291..f9034467736c 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -93,8 +93,6 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = NETXEN_NIC_REGS_LEN;
- drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev);
}
static int
diff --git a/drivers/net/ethernet/qlogic/qed/Makefile b/drivers/net/ethernet/qlogic/qed/Makefile
new file mode 100644
index 000000000000..5c2fd57236fe
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_QED) := qed.o
+
+qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
+ qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
new file mode 100644
index 000000000000..ac17d8669b1a
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -0,0 +1,496 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_H
+#define _QED_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/zlib.h>
+#include <linux/hashtable.h>
+#include <linux/qed/qed_if.h>
+#include "qed_hsi.h"
+
+extern const struct qed_common_ops qed_common_ops_pass;
+#define DRV_MODULE_VERSION "8.4.0.0"
+
+#define MAX_HWFNS_PER_DEVICE (4)
+#define NAME_SIZE 16
+#define VER_SIZE 16
+
+/* cau states */
+enum qed_coalescing_mode {
+ QED_COAL_MODE_DISABLE,
+ QED_COAL_MODE_ENABLE
+};
+
+struct qed_eth_cb_ops;
+struct qed_dev_info;
+
+/* helpers */
+static inline u32 qed_db_addr(u32 cid, u32 DEMS)
+{
+ u32 db_addr = FIELD_VALUE(DB_LEGACY_ADDR_DEMS, DEMS) |
+ FIELD_VALUE(DB_LEGACY_ADDR_ICID, cid);
+
+ return db_addr;
+}
+
+#define ALIGNED_TYPE_SIZE(type_name, p_hwfn) \
+ ((sizeof(type_name) + (u32)(1 << (p_hwfn->cdev->cache_shift)) - 1) & \
+ ~((1 << (p_hwfn->cdev->cache_shift)) - 1))
+
+#define for_each_hwfn(cdev, i) for (i = 0; i < cdev->num_hwfns; i++)
+
+#define D_TRINE(val, cond1, cond2, true1, true2, def) \
+ (val == (cond1) ? true1 : \
+ (val == (cond2) ? true2 : def))
+
+/* forward */
+struct qed_ptt_pool;
+struct qed_spq;
+struct qed_sb_info;
+struct qed_sb_attn_info;
+struct qed_cxt_mngr;
+struct qed_sb_sp_info;
+struct qed_mcp_info;
+
+struct qed_rt_data {
+ u32 init_val;
+ bool b_valid;
+};
+
+/* The PCI personality is not quite synonymous to protocol ID:
+ * 1. All personalities need CORE connections
+ * 2. The Ethernet personality may support also the RoCE protocol
+ */
+enum qed_pci_personality {
+ QED_PCI_ETH,
+ QED_PCI_DEFAULT /* default in shmem */
+};
+
+/* All VFs are symmetric, all counters are PF + all VFs */
+struct qed_qm_iids {
+ u32 cids;
+ u32 vf_cids;
+ u32 tids;
+};
+
+enum QED_RESOURCES {
+ QED_SB,
+ QED_L2_QUEUE,
+ QED_VPORT,
+ QED_RSS_ENG,
+ QED_PQ,
+ QED_RL,
+ QED_MAC,
+ QED_VLAN,
+ QED_ILT,
+ QED_MAX_RESC,
+};
+
+enum QED_FEATURE {
+ QED_PF_L2_QUE,
+ QED_MAX_FEATURES,
+};
+
+enum QED_PORT_MODE {
+ QED_PORT_MODE_DE_2X40G,
+ QED_PORT_MODE_DE_2X50G,
+ QED_PORT_MODE_DE_1X100G,
+ QED_PORT_MODE_DE_4X10G_F,
+ QED_PORT_MODE_DE_4X10G_E,
+ QED_PORT_MODE_DE_4X20G,
+ QED_PORT_MODE_DE_1X40G,
+ QED_PORT_MODE_DE_2X25G,
+ QED_PORT_MODE_DE_1X25G
+};
+
+struct qed_hw_info {
+ /* PCI personality */
+ enum qed_pci_personality personality;
+
+ /* Resource Allocation scheme results */
+ u32 resc_start[QED_MAX_RESC];
+ u32 resc_num[QED_MAX_RESC];
+ u32 feat_num[QED_MAX_FEATURES];
+
+#define RESC_START(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_start[resc])
+#define RESC_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_num[resc])
+#define FEAT_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.feat_num[resc])
+
+ u8 num_tc;
+ u8 offload_tc;
+ u8 non_offload_tc;
+
+ u32 concrete_fid;
+ u16 opaque_fid;
+ u16 ovlan;
+ u32 part_num[4];
+
+ u32 vendor_id;
+ u32 device_id;
+
+ unsigned char hw_mac_addr[ETH_ALEN];
+
+ struct qed_igu_info *p_igu_info;
+
+ u32 port_mode;
+ u32 hw_mode;
+};
+
+struct qed_hw_cid_data {
+ u32 cid;
+ bool b_cid_allocated;
+
+ /* Additional identifiers */
+ u16 opaque_fid;
+ u8 vport_id;
+};
+
+/* maximun size of read/write commands (HW limit) */
+#define DMAE_MAX_RW_SIZE 0x2000
+
+struct qed_dmae_info {
+ /* Mutex for synchronizing access to functions */
+ struct mutex mutex;
+
+ u8 channel;
+
+ dma_addr_t completion_word_phys_addr;
+
+ /* The memory location where the DMAE writes the completion
+ * value when an operation is finished on this context.
+ */
+ u32 *p_completion_word;
+
+ dma_addr_t intermediate_buffer_phys_addr;
+
+ /* An intermediate buffer for DMAE operations that use virtual
+ * addresses - data is DMA'd to/from this buffer and then
+ * memcpy'd to/from the virtual address
+ */
+ u32 *p_intermediate_buffer;
+
+ dma_addr_t dmae_cmd_phys_addr;
+ struct dmae_cmd *p_dmae_cmd;
+};
+
+struct qed_qm_info {
+ struct init_qm_pq_params *qm_pq_params;
+ struct init_qm_vport_params *qm_vport_params;
+ struct init_qm_port_params *qm_port_params;
+ u16 start_pq;
+ u8 start_vport;
+ u8 pure_lb_pq;
+ u8 offload_pq;
+ u8 pure_ack_pq;
+ u8 vf_queues_offset;
+ u16 num_pqs;
+ u16 num_vf_pqs;
+ u8 num_vports;
+ u8 max_phys_tcs_per_port;
+ bool pf_rl_en;
+ bool pf_wfq_en;
+ bool vport_rl_en;
+ bool vport_wfq_en;
+ u8 pf_wfq;
+ u32 pf_rl;
+};
+
+struct storm_stats {
+ u32 address;
+ u32 len;
+};
+
+struct qed_storm_stats {
+ struct storm_stats mstats;
+ struct storm_stats pstats;
+ struct storm_stats tstats;
+ struct storm_stats ustats;
+};
+
+struct qed_fw_data {
+ struct fw_ver_info *fw_ver_info;
+ const u8 *modes_tree_buf;
+ union init_op *init_ops;
+ const u32 *arr_data;
+ u32 init_ops_size;
+};
+
+struct qed_simd_fp_handler {
+ void *token;
+ void (*func)(void *);
+};
+
+struct qed_hwfn {
+ struct qed_dev *cdev;
+ u8 my_id; /* ID inside the PF */
+#define IS_LEAD_HWFN(edev) (!((edev)->my_id))
+ u8 rel_pf_id; /* Relative to engine*/
+ u8 abs_pf_id;
+#define QED_PATH_ID(_p_hwfn) ((_p_hwfn)->abs_pf_id & 1)
+ u8 port_id;
+ bool b_active;
+
+ u32 dp_module;
+ u8 dp_level;
+ char name[NAME_SIZE];
+
+ bool first_on_engine;
+ bool hw_init_done;
+
+ /* BAR access */
+ void __iomem *regview;
+ void __iomem *doorbells;
+ u64 db_phys_addr;
+ unsigned long db_size;
+
+ /* PTT pool */
+ struct qed_ptt_pool *p_ptt_pool;
+
+ /* HW info */
+ struct qed_hw_info hw_info;
+
+ /* rt_array (for init-tool) */
+ struct qed_rt_data *rt_data;
+
+ /* SPQ */
+ struct qed_spq *p_spq;
+
+ /* EQ */
+ struct qed_eq *p_eq;
+
+ /* Consolidate Q*/
+ struct qed_consq *p_consq;
+
+ /* Slow-Path definitions */
+ struct tasklet_struct *sp_dpc;
+ bool b_sp_dpc_enabled;
+
+ struct qed_ptt *p_main_ptt;
+ struct qed_ptt *p_dpc_ptt;
+
+ struct qed_sb_sp_info *p_sp_sb;
+ struct qed_sb_attn_info *p_sb_attn;
+
+ /* Protocol related */
+ struct qed_pf_params pf_params;
+
+ /* Array of sb_info of all status blocks */
+ struct qed_sb_info *sbs_info[MAX_SB_PER_PF_MIMD];
+ u16 num_sbs;
+
+ struct qed_cxt_mngr *p_cxt_mngr;
+
+ /* Flag indicating whether interrupts are enabled or not*/
+ bool b_int_enabled;
+
+ struct qed_mcp_info *mcp_info;
+
+ struct qed_hw_cid_data *p_tx_cids;
+ struct qed_hw_cid_data *p_rx_cids;
+
+ struct qed_dmae_info dmae_info;
+
+ /* QM init */
+ struct qed_qm_info qm_info;
+ struct qed_storm_stats storm_stats;
+
+ /* Buffer for unzipping firmware data */
+ void *unzip_buf;
+
+ struct qed_simd_fp_handler simd_proto_handler[64];
+
+ struct z_stream_s *stream;
+};
+
+struct pci_params {
+ int pm_cap;
+
+ unsigned long mem_start;
+ unsigned long mem_end;
+ unsigned int irq;
+ u8 pf_num;
+};
+
+struct qed_int_param {
+ u32 int_mode;
+ u8 num_vectors;
+ u8 min_msix_cnt; /* for minimal functionality */
+};
+
+struct qed_int_params {
+ struct qed_int_param in;
+ struct qed_int_param out;
+ struct msix_entry *msix_table;
+ bool fp_initialized;
+ u8 fp_msix_base;
+ u8 fp_msix_cnt;
+};
+
+struct qed_dev {
+ u32 dp_module;
+ u8 dp_level;
+ char name[NAME_SIZE];
+
+ u8 type;
+#define QED_DEV_TYPE_BB_A0 (0 << 0)
+#define QED_DEV_TYPE_MASK (0x3)
+#define QED_DEV_TYPE_SHIFT (0)
+
+ u16 chip_num;
+#define CHIP_NUM_MASK 0xffff
+#define CHIP_NUM_SHIFT 16
+
+ u16 chip_rev;
+#define CHIP_REV_MASK 0xf
+#define CHIP_REV_SHIFT 12
+
+ u16 chip_metal;
+#define CHIP_METAL_MASK 0xff
+#define CHIP_METAL_SHIFT 4
+
+ u16 chip_bond_id;
+#define CHIP_BOND_ID_MASK 0xf
+#define CHIP_BOND_ID_SHIFT 0
+
+ u8 num_engines;
+ u8 num_ports_in_engines;
+ u8 num_funcs_in_port;
+
+ u8 path_id;
+ enum mf_mode mf_mode;
+#define IS_MF(_p_hwfn) (((_p_hwfn)->cdev)->mf_mode != SF)
+#define IS_MF_SI(_p_hwfn) (((_p_hwfn)->cdev)->mf_mode == MF_NPAR)
+#define IS_MF_SD(_p_hwfn) (((_p_hwfn)->cdev)->mf_mode == MF_OVLAN)
+
+ int pcie_width;
+ int pcie_speed;
+ u8 ver_str[VER_SIZE];
+
+ /* Add MF related configuration */
+ u8 mcp_rev;
+ u8 boot_mode;
+
+ u8 wol;
+
+ u32 int_mode;
+ enum qed_coalescing_mode int_coalescing_mode;
+ u8 rx_coalesce_usecs;
+ u8 tx_coalesce_usecs;
+
+ /* Start Bar offset of first hwfn */
+ void __iomem *regview;
+ void __iomem *doorbells;
+ u64 db_phys_addr;
+ unsigned long db_size;
+
+ /* PCI */
+ u8 cache_shift;
+
+ /* Init */
+ const struct iro *iro_arr;
+#define IRO (p_hwfn->cdev->iro_arr)
+
+ /* HW functions */
+ u8 num_hwfns;
+ struct qed_hwfn hwfns[MAX_HWFNS_PER_DEVICE];
+
+ u32 drv_type;
+
+ struct qed_eth_stats *reset_stats;
+ struct qed_fw_data *fw_data;
+
+ u32 mcp_nvm_resp;
+
+ /* Linux specific here */
+ struct qede_dev *edev;
+ struct pci_dev *pdev;
+ int msg_enable;
+
+ struct pci_params pci_params;
+
+ struct qed_int_params int_params;
+
+ u8 protocol;
+#define IS_QED_ETH_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_ETH)
+
+ /* Callbacks to protocol driver */
+ union {
+ struct qed_common_cb_ops *common;
+ struct qed_eth_cb_ops *eth;
+ } protocol_ops;
+ void *ops_cookie;
+
+ const struct firmware *firmware;
+};
+
+#define QED_GET_TYPE(dev) (((dev)->type & QED_DEV_TYPE_MASK) >> \
+ QED_DEV_TYPE_SHIFT)
+#define QED_IS_BB_A0(dev) (QED_GET_TYPE(dev) == QED_DEV_TYPE_BB_A0)
+#define QED_IS_BB(dev) (QED_IS_BB_A0(dev))
+
+#define NUM_OF_SBS(dev) MAX_SB_PER_PATH_BB
+#define NUM_OF_ENG_PFS(dev) MAX_NUM_PFS_BB
+
+/**
+ * @brief qed_concrete_to_sw_fid - get the sw function id from
+ * the concrete value.
+ *
+ * @param concrete_fid
+ *
+ * @return inline u8
+ */
+static inline u8 qed_concrete_to_sw_fid(struct qed_dev *cdev,
+ u32 concrete_fid)
+{
+ u8 pfid = GET_FIELD(concrete_fid, PXP_CONCRETE_FID_PFID);
+
+ return pfid;
+}
+
+#define PURE_LB_TC 8
+
+#define QED_LEADING_HWFN(dev) (&dev->hwfns[0])
+
+/* Other Linux specific common definitions */
+#define DP_NAME(cdev) ((cdev)->name)
+
+#define REG_ADDR(cdev, offset) (void __iomem *)((u8 __iomem *)\
+ (cdev->regview) + \
+ (offset))
+
+#define REG_RD(cdev, offset) readl(REG_ADDR(cdev, offset))
+#define REG_WR(cdev, offset, val) writel((u32)val, REG_ADDR(cdev, offset))
+#define REG_WR16(cdev, offset, val) writew((u16)val, REG_ADDR(cdev, offset))
+
+#define DOORBELL(cdev, db_addr, val) \
+ writel((u32)val, (void __iomem *)((u8 __iomem *)\
+ (cdev->doorbells) + (db_addr)))
+
+/* Prototypes */
+int qed_fill_dev_info(struct qed_dev *cdev,
+ struct qed_dev_info *dev_info);
+void qed_link_update(struct qed_hwfn *hwfn);
+u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
+ u32 input_len, u8 *input_buf,
+ u32 max_size, u8 *unzip_buf);
+
+#define QED_ETH_INTERFACE_VERSION 300
+
+#endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
new file mode 100644
index 000000000000..7ccdb46c6764
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
@@ -0,0 +1,847 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/log2.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include "qed.h"
+#include "qed_cxt.h"
+#include "qed_dev_api.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_init_ops.h"
+#include "qed_reg_addr.h"
+
+/* Max number of connection types in HW (DQ/CDU etc.) */
+#define MAX_CONN_TYPES PROTOCOLID_COMMON
+#define NUM_TASK_TYPES 2
+#define NUM_TASK_PF_SEGMENTS 4
+
+/* QM constants */
+#define QM_PQ_ELEMENT_SIZE 4 /* in bytes */
+
+/* Doorbell-Queue constants */
+#define DQ_RANGE_SHIFT 4
+#define DQ_RANGE_ALIGN BIT(DQ_RANGE_SHIFT)
+
+/* ILT constants */
+#define ILT_DEFAULT_HW_P_SIZE 3
+#define ILT_PAGE_IN_BYTES(hw_p_size) (1U << ((hw_p_size) + 12))
+#define ILT_CFG_REG(cli, reg) PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET
+
+/* ILT entry structure */
+#define ILT_ENTRY_PHY_ADDR_MASK 0x000FFFFFFFFFFFULL
+#define ILT_ENTRY_PHY_ADDR_SHIFT 0
+#define ILT_ENTRY_VALID_MASK 0x1ULL
+#define ILT_ENTRY_VALID_SHIFT 52
+#define ILT_ENTRY_IN_REGS 2
+#define ILT_REG_SIZE_IN_BYTES 4
+
+/* connection context union */
+union conn_context {
+ struct core_conn_context core_ctx;
+ struct eth_conn_context eth_ctx;
+};
+
+#define CONN_CXT_SIZE(p_hwfn) \
+ ALIGNED_TYPE_SIZE(union conn_context, p_hwfn)
+
+/* PF per protocl configuration object */
+struct qed_conn_type_cfg {
+ u32 cid_count;
+ u32 cid_start;
+};
+
+/* ILT Client configuration, Per connection type (protocol) resources. */
+#define ILT_CLI_PF_BLOCKS (1 + NUM_TASK_PF_SEGMENTS * 2)
+#define CDUC_BLK (0)
+
+enum ilt_clients {
+ ILT_CLI_CDUC,
+ ILT_CLI_QM,
+ ILT_CLI_MAX
+};
+
+struct ilt_cfg_pair {
+ u32 reg;
+ u32 val;
+};
+
+struct qed_ilt_cli_blk {
+ u32 total_size; /* 0 means not active */
+ u32 real_size_in_page;
+ u32 start_line;
+};
+
+struct qed_ilt_client_cfg {
+ bool active;
+
+ /* ILT boundaries */
+ struct ilt_cfg_pair first;
+ struct ilt_cfg_pair last;
+ struct ilt_cfg_pair p_size;
+
+ /* ILT client blocks for PF */
+ struct qed_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
+ u32 pf_total_lines;
+};
+
+/* Per Path -
+ * ILT shadow table
+ * Protocol acquired CID lists
+ * PF start line in ILT
+ */
+struct qed_dma_mem {
+ dma_addr_t p_phys;
+ void *p_virt;
+ size_t size;
+};
+
+struct qed_cid_acquired_map {
+ u32 start_cid;
+ u32 max_count;
+ unsigned long *cid_map;
+};
+
+struct qed_cxt_mngr {
+ /* Per protocl configuration */
+ struct qed_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
+
+ /* computed ILT structure */
+ struct qed_ilt_client_cfg clients[ILT_CLI_MAX];
+
+ /* Acquired CIDs */
+ struct qed_cid_acquired_map acquired[MAX_CONN_TYPES];
+
+ /* ILT shadow table */
+ struct qed_dma_mem *ilt_shadow;
+ u32 pf_start_line;
+};
+
+static u32 qed_cxt_cdu_iids(struct qed_cxt_mngr *p_mngr)
+{
+ u32 type, pf_cids = 0;
+
+ for (type = 0; type < MAX_CONN_TYPES; type++)
+ pf_cids += p_mngr->conn_cfg[type].cid_count;
+
+ return pf_cids;
+}
+
+static void qed_cxt_qm_iids(struct qed_hwfn *p_hwfn,
+ struct qed_qm_iids *iids)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ int type;
+
+ for (type = 0; type < MAX_CONN_TYPES; type++)
+ iids->cids += p_mngr->conn_cfg[type].cid_count;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT, "iids: CIDS %08x\n", iids->cids);
+}
+
+/* set the iids count per protocol */
+static void qed_cxt_set_proto_cid_count(struct qed_hwfn *p_hwfn,
+ enum protocol_type type,
+ u32 cid_count)
+{
+ struct qed_cxt_mngr *p_mgr = p_hwfn->p_cxt_mngr;
+ struct qed_conn_type_cfg *p_conn = &p_mgr->conn_cfg[type];
+
+ p_conn->cid_count = roundup(cid_count, DQ_RANGE_ALIGN);
+}
+
+static void qed_ilt_cli_blk_fill(struct qed_ilt_client_cfg *p_cli,
+ struct qed_ilt_cli_blk *p_blk,
+ u32 start_line, u32 total_size,
+ u32 elem_size)
+{
+ u32 ilt_size = ILT_PAGE_IN_BYTES(p_cli->p_size.val);
+
+ /* verify thatits called only once for each block */
+ if (p_blk->total_size)
+ return;
+
+ p_blk->total_size = total_size;
+ p_blk->real_size_in_page = 0;
+ if (elem_size)
+ p_blk->real_size_in_page = (ilt_size / elem_size) * elem_size;
+ p_blk->start_line = start_line;
+}
+
+static void qed_ilt_cli_adv_line(struct qed_hwfn *p_hwfn,
+ struct qed_ilt_client_cfg *p_cli,
+ struct qed_ilt_cli_blk *p_blk,
+ u32 *p_line, enum ilt_clients client_id)
+{
+ if (!p_blk->total_size)
+ return;
+
+ if (!p_cli->active)
+ p_cli->first.val = *p_line;
+
+ p_cli->active = true;
+ *p_line += DIV_ROUND_UP(p_blk->total_size,
+ p_blk->real_size_in_page);
+ p_cli->last.val = *p_line - 1;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT,
+ "ILT[Client %d] - Lines: [%08x - %08x]. Block - Size %08x [Real %08x] Start line %d\n",
+ client_id, p_cli->first.val,
+ p_cli->last.val, p_blk->total_size,
+ p_blk->real_size_in_page, p_blk->start_line);
+}
+
+int qed_cxt_cfg_ilt_compute(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ struct qed_ilt_client_cfg *p_cli;
+ struct qed_ilt_cli_blk *p_blk;
+ u32 curr_line, total, pf_cids;
+ struct qed_qm_iids qm_iids;
+
+ memset(&qm_iids, 0, sizeof(qm_iids));
+
+ p_mngr->pf_start_line = RESC_START(p_hwfn, QED_ILT);
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT,
+ "hwfn [%d] - Set context manager starting line to be 0x%08x\n",
+ p_hwfn->my_id, p_hwfn->p_cxt_mngr->pf_start_line);
+
+ /* CDUC */
+ p_cli = &p_mngr->clients[ILT_CLI_CDUC];
+ curr_line = p_mngr->pf_start_line;
+ p_cli->pf_total_lines = 0;
+
+ /* get the counters for the CDUC and QM clients */
+ pf_cids = qed_cxt_cdu_iids(p_mngr);
+
+ p_blk = &p_cli->pf_blks[CDUC_BLK];
+
+ total = pf_cids * CONN_CXT_SIZE(p_hwfn);
+
+ qed_ilt_cli_blk_fill(p_cli, p_blk, curr_line,
+ total, CONN_CXT_SIZE(p_hwfn));
+
+ qed_ilt_cli_adv_line(p_hwfn, p_cli, p_blk, &curr_line, ILT_CLI_CDUC);
+ p_cli->pf_total_lines = curr_line - p_blk->start_line;
+
+ /* QM */
+ p_cli = &p_mngr->clients[ILT_CLI_QM];
+ p_blk = &p_cli->pf_blks[0];
+
+ qed_cxt_qm_iids(p_hwfn, &qm_iids);
+ total = qed_qm_pf_mem_size(p_hwfn->rel_pf_id, qm_iids.cids, 0, 0,
+ p_hwfn->qm_info.num_pqs, 0);
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT,
+ "QM ILT Info, (cids=%d, num_pqs=%d, memory_size=%d)\n",
+ qm_iids.cids, p_hwfn->qm_info.num_pqs, total);
+
+ qed_ilt_cli_blk_fill(p_cli, p_blk,
+ curr_line, total * 0x1000,
+ QM_PQ_ELEMENT_SIZE);
+
+ qed_ilt_cli_adv_line(p_hwfn, p_cli, p_blk, &curr_line, ILT_CLI_QM);
+ p_cli->pf_total_lines = curr_line - p_blk->start_line;
+
+ if (curr_line - p_hwfn->p_cxt_mngr->pf_start_line >
+ RESC_NUM(p_hwfn, QED_ILT)) {
+ DP_ERR(p_hwfn, "too many ilt lines...#lines=%d\n",
+ curr_line - p_hwfn->p_cxt_mngr->pf_start_line);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define for_each_ilt_valid_client(pos, clients) \
+ for (pos = 0; pos < ILT_CLI_MAX; pos++)
+
+/* Total number of ILT lines used by this PF */
+static u32 qed_cxt_ilt_shadow_size(struct qed_ilt_client_cfg *ilt_clients)
+{
+ u32 size = 0;
+ u32 i;
+
+ for_each_ilt_valid_client(i, ilt_clients) {
+ if (!ilt_clients[i].active)
+ continue;
+ size += (ilt_clients[i].last.val -
+ ilt_clients[i].first.val + 1);
+ }
+
+ return size;
+}
+
+static void qed_ilt_shadow_free(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ilt_client_cfg *p_cli = p_hwfn->p_cxt_mngr->clients;
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ u32 ilt_size, i;
+
+ ilt_size = qed_cxt_ilt_shadow_size(p_cli);
+
+ for (i = 0; p_mngr->ilt_shadow && i < ilt_size; i++) {
+ struct qed_dma_mem *p_dma = &p_mngr->ilt_shadow[i];
+
+ if (p_dma->p_virt)
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ p_dma->size, p_dma->p_virt,
+ p_dma->p_phys);
+ p_dma->p_virt = NULL;
+ }
+ kfree(p_mngr->ilt_shadow);
+}
+
+static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,
+ struct qed_ilt_cli_blk *p_blk,
+ enum ilt_clients ilt_client,
+ u32 start_line_offset)
+{
+ struct qed_dma_mem *ilt_shadow = p_hwfn->p_cxt_mngr->ilt_shadow;
+ u32 lines, line, sz_left;
+
+ if (!p_blk->total_size)
+ return 0;
+
+ sz_left = p_blk->total_size;
+ lines = DIV_ROUND_UP(sz_left, p_blk->real_size_in_page);
+ line = p_blk->start_line + start_line_offset -
+ p_hwfn->p_cxt_mngr->pf_start_line;
+
+ for (; lines; lines--) {
+ dma_addr_t p_phys;
+ void *p_virt;
+ u32 size;
+
+ size = min_t(u32, sz_left,
+ p_blk->real_size_in_page);
+ p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ size,
+ &p_phys,
+ GFP_KERNEL);
+ if (!p_virt)
+ return -ENOMEM;
+ memset(p_virt, 0, size);
+
+ ilt_shadow[line].p_phys = p_phys;
+ ilt_shadow[line].p_virt = p_virt;
+ ilt_shadow[line].size = size;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT,
+ "ILT shadow: Line [%d] Physical 0x%llx Virtual %p Size %d\n",
+ line, (u64)p_phys, p_virt, size);
+
+ sz_left -= size;
+ line++;
+ }
+
+ return 0;
+}
+
+static int qed_ilt_shadow_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ struct qed_ilt_client_cfg *clients = p_mngr->clients;
+ struct qed_ilt_cli_blk *p_blk;
+ u32 size, i, j;
+ int rc;
+
+ size = qed_cxt_ilt_shadow_size(clients);
+ p_mngr->ilt_shadow = kcalloc(size, sizeof(struct qed_dma_mem),
+ GFP_KERNEL);
+ if (!p_mngr->ilt_shadow) {
+ DP_NOTICE(p_hwfn, "Failed to allocate ilt shadow table\n");
+ rc = -ENOMEM;
+ goto ilt_shadow_fail;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT,
+ "Allocated 0x%x bytes for ilt shadow\n",
+ (u32)(size * sizeof(struct qed_dma_mem)));
+
+ for_each_ilt_valid_client(i, clients) {
+ if (!clients[i].active)
+ continue;
+ for (j = 0; j < ILT_CLI_PF_BLOCKS; j++) {
+ p_blk = &clients[i].pf_blks[j];
+ rc = qed_ilt_blk_alloc(p_hwfn, p_blk, i, 0);
+ if (rc != 0)
+ goto ilt_shadow_fail;
+ }
+ }
+
+ return 0;
+
+ilt_shadow_fail:
+ qed_ilt_shadow_free(p_hwfn);
+ return rc;
+}
+
+static void qed_cid_map_free(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ u32 type;
+
+ for (type = 0; type < MAX_CONN_TYPES; type++) {
+ kfree(p_mngr->acquired[type].cid_map);
+ p_mngr->acquired[type].max_count = 0;
+ p_mngr->acquired[type].start_cid = 0;
+ }
+}
+
+static int qed_cid_map_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ u32 start_cid = 0;
+ u32 type;
+
+ for (type = 0; type < MAX_CONN_TYPES; type++) {
+ u32 cid_cnt = p_hwfn->p_cxt_mngr->conn_cfg[type].cid_count;
+ u32 size;
+
+ if (cid_cnt == 0)
+ continue;
+
+ size = DIV_ROUND_UP(cid_cnt,
+ sizeof(unsigned long) * BITS_PER_BYTE) *
+ sizeof(unsigned long);
+ p_mngr->acquired[type].cid_map = kzalloc(size, GFP_KERNEL);
+ if (!p_mngr->acquired[type].cid_map)
+ goto cid_map_fail;
+
+ p_mngr->acquired[type].max_count = cid_cnt;
+ p_mngr->acquired[type].start_cid = start_cid;
+
+ p_hwfn->p_cxt_mngr->conn_cfg[type].cid_start = start_cid;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_CXT,
+ "Type %08x start: %08x count %08x\n",
+ type, p_mngr->acquired[type].start_cid,
+ p_mngr->acquired[type].max_count);
+ start_cid += cid_cnt;
+ }
+
+ return 0;
+
+cid_map_fail:
+ qed_cid_map_free(p_hwfn);
+ return -ENOMEM;
+}
+
+int qed_cxt_mngr_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr;
+ u32 i;
+
+ p_mngr = kzalloc(sizeof(*p_mngr), GFP_ATOMIC);
+ if (!p_mngr) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_cxt_mngr'\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize ILT client registers */
+ p_mngr->clients[ILT_CLI_CDUC].first.reg = ILT_CFG_REG(CDUC, FIRST_ILT);
+ p_mngr->clients[ILT_CLI_CDUC].last.reg = ILT_CFG_REG(CDUC, LAST_ILT);
+ p_mngr->clients[ILT_CLI_CDUC].p_size.reg = ILT_CFG_REG(CDUC, P_SIZE);
+
+ p_mngr->clients[ILT_CLI_QM].first.reg = ILT_CFG_REG(QM, FIRST_ILT);
+ p_mngr->clients[ILT_CLI_QM].last.reg = ILT_CFG_REG(QM, LAST_ILT);
+ p_mngr->clients[ILT_CLI_QM].p_size.reg = ILT_CFG_REG(QM, P_SIZE);
+
+ /* default ILT page size for all clients is 32K */
+ for (i = 0; i < ILT_CLI_MAX; i++)
+ p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
+
+ /* Set the cxt mangr pointer priori to further allocations */
+ p_hwfn->p_cxt_mngr = p_mngr;
+
+ return 0;
+}
+
+int qed_cxt_tables_alloc(struct qed_hwfn *p_hwfn)
+{
+ int rc;
+
+ /* Allocate the ILT shadow table */
+ rc = qed_ilt_shadow_alloc(p_hwfn);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to allocate ilt memory\n");
+ goto tables_alloc_fail;
+ }
+
+ /* Allocate and initialize the acquired cids bitmaps */
+ rc = qed_cid_map_alloc(p_hwfn);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to allocate cid maps\n");
+ goto tables_alloc_fail;
+ }
+
+ return 0;
+
+tables_alloc_fail:
+ qed_cxt_mngr_free(p_hwfn);
+ return rc;
+}
+
+void qed_cxt_mngr_free(struct qed_hwfn *p_hwfn)
+{
+ if (!p_hwfn->p_cxt_mngr)
+ return;
+
+ qed_cid_map_free(p_hwfn);
+ qed_ilt_shadow_free(p_hwfn);
+ kfree(p_hwfn->p_cxt_mngr);
+
+ p_hwfn->p_cxt_mngr = NULL;
+}
+
+void qed_cxt_mngr_setup(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ int type;
+
+ /* Reset acquired cids */
+ for (type = 0; type < MAX_CONN_TYPES; type++) {
+ u32 cid_cnt = p_hwfn->p_cxt_mngr->conn_cfg[type].cid_count;
+
+ if (cid_cnt == 0)
+ continue;
+
+ memset(p_mngr->acquired[type].cid_map, 0,
+ DIV_ROUND_UP(cid_cnt,
+ sizeof(unsigned long) * BITS_PER_BYTE) *
+ sizeof(unsigned long));
+ }
+}
+
+/* CDU Common */
+#define CDUC_CXT_SIZE_SHIFT \
+ CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE_SHIFT
+
+#define CDUC_CXT_SIZE_MASK \
+ (CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE >> CDUC_CXT_SIZE_SHIFT)
+
+#define CDUC_BLOCK_WASTE_SHIFT \
+ CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE_SHIFT
+
+#define CDUC_BLOCK_WASTE_MASK \
+ (CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE >> CDUC_BLOCK_WASTE_SHIFT)
+
+#define CDUC_NCIB_SHIFT \
+ CDU_REG_CID_ADDR_PARAMS_NCIB_SHIFT
+
+#define CDUC_NCIB_MASK \
+ (CDU_REG_CID_ADDR_PARAMS_NCIB >> CDUC_NCIB_SHIFT)
+
+static void qed_cdu_init_common(struct qed_hwfn *p_hwfn)
+{
+ u32 page_sz, elems_per_page, block_waste, cxt_size, cdu_params = 0;
+
+ /* CDUC - connection configuration */
+ page_sz = p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUC].p_size.val;
+ cxt_size = CONN_CXT_SIZE(p_hwfn);
+ elems_per_page = ILT_PAGE_IN_BYTES(page_sz) / cxt_size;
+ block_waste = ILT_PAGE_IN_BYTES(page_sz) - elems_per_page * cxt_size;
+
+ SET_FIELD(cdu_params, CDUC_CXT_SIZE, cxt_size);
+ SET_FIELD(cdu_params, CDUC_BLOCK_WASTE, block_waste);
+ SET_FIELD(cdu_params, CDUC_NCIB, elems_per_page);
+ STORE_RT_REG(p_hwfn, CDU_REG_CID_ADDR_PARAMS_RT_OFFSET, cdu_params);
+}
+
+void qed_qm_init_pf(struct qed_hwfn *p_hwfn)
+{
+ struct qed_qm_pf_rt_init_params params;
+ struct qed_qm_info *qm_info = &p_hwfn->qm_info;
+ struct qed_qm_iids iids;
+
+ memset(&iids, 0, sizeof(iids));
+ qed_cxt_qm_iids(p_hwfn, &iids);
+
+ memset(&params, 0, sizeof(params));
+ params.port_id = p_hwfn->port_id;
+ params.pf_id = p_hwfn->rel_pf_id;
+ params.max_phys_tcs_per_port = qm_info->max_phys_tcs_per_port;
+ params.is_first_pf = p_hwfn->first_on_engine;
+ params.num_pf_cids = iids.cids;
+ params.start_pq = qm_info->start_pq;
+ params.num_pf_pqs = qm_info->num_pqs;
+ params.start_vport = qm_info->num_vports;
+ params.pf_wfq = qm_info->pf_wfq;
+ params.pf_rl = qm_info->pf_rl;
+ params.pq_params = qm_info->qm_pq_params;
+ params.vport_params = qm_info->qm_vport_params;
+
+ qed_qm_pf_rt_init(p_hwfn, p_hwfn->p_main_ptt, &params);
+}
+
+/* CM PF */
+static int qed_cm_init_pf(struct qed_hwfn *p_hwfn)
+{
+ union qed_qm_pq_params pq_params;
+ u16 pq;
+
+ /* XCM pure-LB queue */
+ memset(&pq_params, 0, sizeof(pq_params));
+ pq_params.core.tc = LB_TC;
+ pq = qed_get_qm_pq(p_hwfn, PROTOCOLID_CORE, &pq_params);
+ STORE_RT_REG(p_hwfn, XCM_REG_CON_PHY_Q3_RT_OFFSET, pq);
+
+ return 0;
+}
+
+/* DQ PF */
+static void qed_dq_init_pf(struct qed_hwfn *p_hwfn)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ u32 dq_pf_max_cid = 0;
+
+ dq_pf_max_cid += (p_mngr->conn_cfg[0].cid_count >> DQ_RANGE_SHIFT);
+ STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_0_RT_OFFSET, dq_pf_max_cid);
+
+ dq_pf_max_cid += (p_mngr->conn_cfg[1].cid_count >> DQ_RANGE_SHIFT);
+ STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_1_RT_OFFSET, dq_pf_max_cid);
+
+ dq_pf_max_cid += (p_mngr->conn_cfg[2].cid_count >> DQ_RANGE_SHIFT);
+ STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_2_RT_OFFSET, dq_pf_max_cid);
+
+ dq_pf_max_cid += (p_mngr->conn_cfg[3].cid_count >> DQ_RANGE_SHIFT);
+ STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_3_RT_OFFSET, dq_pf_max_cid);
+
+ dq_pf_max_cid += (p_mngr->conn_cfg[4].cid_count >> DQ_RANGE_SHIFT);
+ STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_4_RT_OFFSET, dq_pf_max_cid);
+
+ /* 5 - PF */
+ dq_pf_max_cid += (p_mngr->conn_cfg[5].cid_count >> DQ_RANGE_SHIFT);
+ STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_5_RT_OFFSET, dq_pf_max_cid);
+}
+
+static void qed_ilt_bounds_init(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ilt_client_cfg *ilt_clients;
+ int i;
+
+ ilt_clients = p_hwfn->p_cxt_mngr->clients;
+ for_each_ilt_valid_client(i, ilt_clients) {
+ if (!ilt_clients[i].active)
+ continue;
+ STORE_RT_REG(p_hwfn,
+ ilt_clients[i].first.reg,
+ ilt_clients[i].first.val);
+ STORE_RT_REG(p_hwfn,
+ ilt_clients[i].last.reg,
+ ilt_clients[i].last.val);
+ STORE_RT_REG(p_hwfn,
+ ilt_clients[i].p_size.reg,
+ ilt_clients[i].p_size.val);
+ }
+}
+
+/* ILT (PSWRQ2) PF */
+static void qed_ilt_init_pf(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ilt_client_cfg *clients;
+ struct qed_cxt_mngr *p_mngr;
+ struct qed_dma_mem *p_shdw;
+ u32 line, rt_offst, i;
+
+ qed_ilt_bounds_init(p_hwfn);
+
+ p_mngr = p_hwfn->p_cxt_mngr;
+ p_shdw = p_mngr->ilt_shadow;
+ clients = p_hwfn->p_cxt_mngr->clients;
+
+ for_each_ilt_valid_client(i, clients) {
+ if (!clients[i].active)
+ continue;
+
+ /** Client's 1st val and RT array are absolute, ILT shadows'
+ * lines are relative.
+ */
+ line = clients[i].first.val - p_mngr->pf_start_line;
+ rt_offst = PSWRQ2_REG_ILT_MEMORY_RT_OFFSET +
+ clients[i].first.val * ILT_ENTRY_IN_REGS;
+
+ for (; line <= clients[i].last.val - p_mngr->pf_start_line;
+ line++, rt_offst += ILT_ENTRY_IN_REGS) {
+ u64 ilt_hw_entry = 0;
+
+ /** p_virt could be NULL incase of dynamic
+ * allocation
+ */
+ if (p_shdw[line].p_virt) {
+ SET_FIELD(ilt_hw_entry, ILT_ENTRY_VALID, 1ULL);
+ SET_FIELD(ilt_hw_entry, ILT_ENTRY_PHY_ADDR,
+ (p_shdw[line].p_phys >> 12));
+
+ DP_VERBOSE(p_hwfn, QED_MSG_ILT,
+ "Setting RT[0x%08x] from ILT[0x%08x] [Client is %d] to Physical addr: 0x%llx\n",
+ rt_offst, line, i,
+ (u64)(p_shdw[line].p_phys >> 12));
+ }
+
+ STORE_RT_REG_AGG(p_hwfn, rt_offst, ilt_hw_entry);
+ }
+ }
+}
+
+void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn)
+{
+ qed_cdu_init_common(p_hwfn);
+}
+
+void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn)
+{
+ qed_qm_init_pf(p_hwfn);
+ qed_cm_init_pf(p_hwfn);
+ qed_dq_init_pf(p_hwfn);
+ qed_ilt_init_pf(p_hwfn);
+}
+
+int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
+ enum protocol_type type,
+ u32 *p_cid)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ u32 rel_cid;
+
+ if (type >= MAX_CONN_TYPES || !p_mngr->acquired[type].cid_map) {
+ DP_NOTICE(p_hwfn, "Invalid protocol type %d", type);
+ return -EINVAL;
+ }
+
+ rel_cid = find_first_zero_bit(p_mngr->acquired[type].cid_map,
+ p_mngr->acquired[type].max_count);
+
+ if (rel_cid >= p_mngr->acquired[type].max_count) {
+ DP_NOTICE(p_hwfn, "no CID available for protocol %d\n",
+ type);
+ return -EINVAL;
+ }
+
+ __set_bit(rel_cid, p_mngr->acquired[type].cid_map);
+
+ *p_cid = rel_cid + p_mngr->acquired[type].start_cid;
+
+ return 0;
+}
+
+static bool qed_cxt_test_cid_acquired(struct qed_hwfn *p_hwfn,
+ u32 cid,
+ enum protocol_type *p_type)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ struct qed_cid_acquired_map *p_map;
+ enum protocol_type p;
+ u32 rel_cid;
+
+ /* Iterate over protocols and find matching cid range */
+ for (p = 0; p < MAX_CONN_TYPES; p++) {
+ p_map = &p_mngr->acquired[p];
+
+ if (!p_map->cid_map)
+ continue;
+ if (cid >= p_map->start_cid &&
+ cid < p_map->start_cid + p_map->max_count)
+ break;
+ }
+ *p_type = p;
+
+ if (p == MAX_CONN_TYPES) {
+ DP_NOTICE(p_hwfn, "Invalid CID %d", cid);
+ return false;
+ }
+
+ rel_cid = cid - p_map->start_cid;
+ if (!test_bit(rel_cid, p_map->cid_map)) {
+ DP_NOTICE(p_hwfn, "CID %d not acquired", cid);
+ return false;
+ }
+ return true;
+}
+
+void qed_cxt_release_cid(struct qed_hwfn *p_hwfn,
+ u32 cid)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ enum protocol_type type;
+ bool b_acquired;
+ u32 rel_cid;
+
+ /* Test acquired and find matching per-protocol map */
+ b_acquired = qed_cxt_test_cid_acquired(p_hwfn, cid, &type);
+
+ if (!b_acquired)
+ return;
+
+ rel_cid = cid - p_mngr->acquired[type].start_cid;
+ __clear_bit(rel_cid, p_mngr->acquired[type].cid_map);
+}
+
+int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn,
+ struct qed_cxt_info *p_info)
+{
+ struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
+ u32 conn_cxt_size, hw_p_size, cxts_per_p, line;
+ enum protocol_type type;
+ bool b_acquired;
+
+ /* Test acquired and find matching per-protocol map */
+ b_acquired = qed_cxt_test_cid_acquired(p_hwfn, p_info->iid, &type);
+
+ if (!b_acquired)
+ return -EINVAL;
+
+ /* set the protocl type */
+ p_info->type = type;
+
+ /* compute context virtual pointer */
+ hw_p_size = p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUC].p_size.val;
+
+ conn_cxt_size = CONN_CXT_SIZE(p_hwfn);
+ cxts_per_p = ILT_PAGE_IN_BYTES(hw_p_size) / conn_cxt_size;
+ line = p_info->iid / cxts_per_p;
+
+ /* Make sure context is allocated (dynamic allocation) */
+ if (!p_mngr->ilt_shadow[line].p_virt)
+ return -EINVAL;
+
+ p_info->p_cxt = p_mngr->ilt_shadow[line].p_virt +
+ p_info->iid % cxts_per_p * conn_cxt_size;
+
+ DP_VERBOSE(p_hwfn, (QED_MSG_ILT | QED_MSG_CXT),
+ "Accessing ILT shadow[%d]: CXT pointer is at %p (for iid %d)\n",
+ p_info->iid / cxts_per_p, p_info->p_cxt, p_info->iid);
+
+ return 0;
+}
+
+int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
+{
+ struct qed_eth_pf_params *p_params = &p_hwfn->pf_params.eth_pf_params;
+
+ /* Set the number of required CORE connections */
+ u32 core_cids = 1; /* SPQ */
+
+ qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_CORE, core_cids);
+
+ qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
+ p_params->num_cons);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.h b/drivers/net/ethernet/qlogic/qed/qed_cxt.h
new file mode 100644
index 000000000000..c8e1f5e5c42b
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.h
@@ -0,0 +1,139 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_CXT_H
+#define _QED_CXT_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/qed/qed_if.h>
+#include "qed_hsi.h"
+#include "qed.h"
+
+struct qed_cxt_info {
+ void *p_cxt;
+ u32 iid;
+ enum protocol_type type;
+};
+
+/**
+ * @brief qed_cxt_acquire - Acquire a new cid of a specific protocol type
+ *
+ * @param p_hwfn
+ * @param type
+ * @param p_cid
+ *
+ * @return int
+ */
+int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
+ enum protocol_type type,
+ u32 *p_cid);
+
+/**
+ * @brief qedo_cid_get_cxt_info - Returns the context info for a specific cid
+ *
+ *
+ * @param p_hwfn
+ * @param p_info in/out
+ *
+ * @return int
+ */
+int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn,
+ struct qed_cxt_info *p_info);
+
+enum qed_cxt_elem_type {
+ QED_ELEM_CXT,
+ QED_ELEM_TASK
+};
+
+/**
+ * @brief qed_cxt_set_pf_params - Set the PF params for cxt init
+ *
+ * @param p_hwfn
+ *
+ * @return int
+ */
+int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_cfg_ilt_compute - compute ILT init parameters
+ *
+ * @param p_hwfn
+ *
+ * @return int
+ */
+int qed_cxt_cfg_ilt_compute(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_mngr_alloc - Allocate and init the context manager struct
+ *
+ * @param p_hwfn
+ *
+ * @return int
+ */
+int qed_cxt_mngr_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_mngr_free
+ *
+ * @param p_hwfn
+ */
+void qed_cxt_mngr_free(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_tables_alloc - Allocate ILT shadow, Searcher T2, acquired map
+ *
+ * @param p_hwfn
+ *
+ * @return int
+ */
+int qed_cxt_tables_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_mngr_setup - Reset the acquired CIDs
+ *
+ * @param p_hwfn
+ */
+void qed_cxt_mngr_setup(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_hw_init_common - Initailze ILT and DQ, common phase, per path.
+ *
+ *
+ *
+ * @param p_hwfn
+ */
+void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_hw_init_pf - Initailze ILT and DQ, PF phase, per path.
+ *
+ *
+ *
+ * @param p_hwfn
+ */
+void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_qm_init_pf - Initailze the QM PF phase, per path
+ *
+ * @param p_hwfn
+ */
+
+void qed_qm_init_pf(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_cxt_release - Release a cid
+ *
+ * @param p_hwfn
+ * @param cid
+ */
+void qed_cxt_release_cid(struct qed_hwfn *p_hwfn,
+ u32 cid);
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
new file mode 100644
index 000000000000..803b190ccada
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -0,0 +1,1803 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+#include <linux/qed/qed_chain.h>
+#include <linux/qed/qed_if.h>
+#include "qed.h"
+#include "qed_cxt.h"
+#include "qed_dev_api.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_init_ops.h"
+#include "qed_int.h"
+#include "qed_mcp.h"
+#include "qed_reg_addr.h"
+#include "qed_sp.h"
+
+/* API common to all protocols */
+void qed_init_dp(struct qed_dev *cdev,
+ u32 dp_module, u8 dp_level)
+{
+ u32 i;
+
+ cdev->dp_level = dp_level;
+ cdev->dp_module = dp_module;
+ for (i = 0; i < MAX_HWFNS_PER_DEVICE; i++) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ p_hwfn->dp_level = dp_level;
+ p_hwfn->dp_module = dp_module;
+ }
+}
+
+void qed_init_struct(struct qed_dev *cdev)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_HWFNS_PER_DEVICE; i++) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ p_hwfn->cdev = cdev;
+ p_hwfn->my_id = i;
+ p_hwfn->b_active = false;
+
+ mutex_init(&p_hwfn->dmae_info.mutex);
+ }
+
+ /* hwfn 0 is always active */
+ cdev->hwfns[0].b_active = true;
+
+ /* set the default cache alignment to 128 */
+ cdev->cache_shift = 7;
+}
+
+static void qed_qm_info_free(struct qed_hwfn *p_hwfn)
+{
+ struct qed_qm_info *qm_info = &p_hwfn->qm_info;
+
+ kfree(qm_info->qm_pq_params);
+ qm_info->qm_pq_params = NULL;
+ kfree(qm_info->qm_vport_params);
+ qm_info->qm_vport_params = NULL;
+ kfree(qm_info->qm_port_params);
+ qm_info->qm_port_params = NULL;
+}
+
+void qed_resc_free(struct qed_dev *cdev)
+{
+ int i;
+
+ kfree(cdev->fw_data);
+ cdev->fw_data = NULL;
+
+ kfree(cdev->reset_stats);
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ kfree(p_hwfn->p_tx_cids);
+ p_hwfn->p_tx_cids = NULL;
+ kfree(p_hwfn->p_rx_cids);
+ p_hwfn->p_rx_cids = NULL;
+ }
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ qed_cxt_mngr_free(p_hwfn);
+ qed_qm_info_free(p_hwfn);
+ qed_spq_free(p_hwfn);
+ qed_eq_free(p_hwfn, p_hwfn->p_eq);
+ qed_consq_free(p_hwfn, p_hwfn->p_consq);
+ qed_int_free(p_hwfn);
+ qed_dmae_info_free(p_hwfn);
+ }
+}
+
+static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
+{
+ struct qed_qm_info *qm_info = &p_hwfn->qm_info;
+ struct init_qm_port_params *p_qm_port;
+ u8 num_vports, i, vport_id, num_ports;
+ u16 num_pqs, multi_cos_tcs = 1;
+
+ memset(qm_info, 0, sizeof(*qm_info));
+
+ num_pqs = multi_cos_tcs + 1; /* The '1' is for pure-LB */
+ num_vports = (u8)RESC_NUM(p_hwfn, QED_VPORT);
+
+ /* Sanity checking that setup requires legal number of resources */
+ if (num_pqs > RESC_NUM(p_hwfn, QED_PQ)) {
+ DP_ERR(p_hwfn,
+ "Need too many Physical queues - 0x%04x when only %04x are available\n",
+ num_pqs, RESC_NUM(p_hwfn, QED_PQ));
+ return -EINVAL;
+ }
+
+ /* PQs will be arranged as follows: First per-TC PQ then pure-LB quete.
+ */
+ qm_info->qm_pq_params = kzalloc(sizeof(*qm_info->qm_pq_params) *
+ num_pqs, GFP_ATOMIC);
+ if (!qm_info->qm_pq_params)
+ goto alloc_err;
+
+ qm_info->qm_vport_params = kzalloc(sizeof(*qm_info->qm_vport_params) *
+ num_vports, GFP_ATOMIC);
+ if (!qm_info->qm_vport_params)
+ goto alloc_err;
+
+ qm_info->qm_port_params = kzalloc(sizeof(*qm_info->qm_port_params) *
+ MAX_NUM_PORTS, GFP_ATOMIC);
+ if (!qm_info->qm_port_params)
+ goto alloc_err;
+
+ vport_id = (u8)RESC_START(p_hwfn, QED_VPORT);
+
+ /* First init per-TC PQs */
+ for (i = 0; i < multi_cos_tcs; i++) {
+ struct init_qm_pq_params *params = &qm_info->qm_pq_params[i];
+
+ params->vport_id = vport_id;
+ params->tc_id = p_hwfn->hw_info.non_offload_tc;
+ params->wrr_group = 1;
+ }
+
+ /* Then init pure-LB PQ */
+ qm_info->pure_lb_pq = i;
+ qm_info->qm_pq_params[i].vport_id = (u8)RESC_START(p_hwfn, QED_VPORT);
+ qm_info->qm_pq_params[i].tc_id = PURE_LB_TC;
+ qm_info->qm_pq_params[i].wrr_group = 1;
+ i++;
+
+ qm_info->offload_pq = 0;
+ qm_info->num_pqs = num_pqs;
+ qm_info->num_vports = num_vports;
+
+ /* Initialize qm port parameters */
+ num_ports = p_hwfn->cdev->num_ports_in_engines;
+ for (i = 0; i < num_ports; i++) {
+ p_qm_port = &qm_info->qm_port_params[i];
+ p_qm_port->active = 1;
+ p_qm_port->num_active_phys_tcs = 4;
+ p_qm_port->num_pbf_cmd_lines = PBF_MAX_CMD_LINES / num_ports;
+ p_qm_port->num_btb_blocks = BTB_MAX_BLOCKS / num_ports;
+ }
+
+ qm_info->max_phys_tcs_per_port = NUM_OF_PHYS_TCS;
+
+ qm_info->start_pq = (u16)RESC_START(p_hwfn, QED_PQ);
+
+ qm_info->start_vport = (u8)RESC_START(p_hwfn, QED_VPORT);
+
+ qm_info->pf_wfq = 0;
+ qm_info->pf_rl = 0;
+ qm_info->vport_rl_en = 1;
+
+ return 0;
+
+alloc_err:
+ DP_NOTICE(p_hwfn, "Failed to allocate memory for QM params\n");
+ kfree(qm_info->qm_pq_params);
+ kfree(qm_info->qm_vport_params);
+ kfree(qm_info->qm_port_params);
+
+ return -ENOMEM;
+}
+
+int qed_resc_alloc(struct qed_dev *cdev)
+{
+ struct qed_consq *p_consq;
+ struct qed_eq *p_eq;
+ int i, rc = 0;
+
+ cdev->fw_data = kzalloc(sizeof(*cdev->fw_data), GFP_KERNEL);
+ if (!cdev->fw_data)
+ return -ENOMEM;
+
+ /* Allocate Memory for the Queue->CID mapping */
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ int tx_size = sizeof(struct qed_hw_cid_data) *
+ RESC_NUM(p_hwfn, QED_L2_QUEUE);
+ int rx_size = sizeof(struct qed_hw_cid_data) *
+ RESC_NUM(p_hwfn, QED_L2_QUEUE);
+
+ p_hwfn->p_tx_cids = kzalloc(tx_size, GFP_KERNEL);
+ if (!p_hwfn->p_tx_cids) {
+ DP_NOTICE(p_hwfn,
+ "Failed to allocate memory for Tx Cids\n");
+ rc = -ENOMEM;
+ goto alloc_err;
+ }
+
+ p_hwfn->p_rx_cids = kzalloc(rx_size, GFP_KERNEL);
+ if (!p_hwfn->p_rx_cids) {
+ DP_NOTICE(p_hwfn,
+ "Failed to allocate memory for Rx Cids\n");
+ rc = -ENOMEM;
+ goto alloc_err;
+ }
+ }
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ /* First allocate the context manager structure */
+ rc = qed_cxt_mngr_alloc(p_hwfn);
+ if (rc)
+ goto alloc_err;
+
+ /* Set the HW cid/tid numbers (in the contest manager)
+ * Must be done prior to any further computations.
+ */
+ rc = qed_cxt_set_pf_params(p_hwfn);
+ if (rc)
+ goto alloc_err;
+
+ /* Prepare and process QM requirements */
+ rc = qed_init_qm_info(p_hwfn);
+ if (rc)
+ goto alloc_err;
+
+ /* Compute the ILT client partition */
+ rc = qed_cxt_cfg_ilt_compute(p_hwfn);
+ if (rc)
+ goto alloc_err;
+
+ /* CID map / ILT shadow table / T2
+ * The talbes sizes are determined by the computations above
+ */
+ rc = qed_cxt_tables_alloc(p_hwfn);
+ if (rc)
+ goto alloc_err;
+
+ /* SPQ, must follow ILT because initializes SPQ context */
+ rc = qed_spq_alloc(p_hwfn);
+ if (rc)
+ goto alloc_err;
+
+ /* SP status block allocation */
+ p_hwfn->p_dpc_ptt = qed_get_reserved_ptt(p_hwfn,
+ RESERVED_PTT_DPC);
+
+ rc = qed_int_alloc(p_hwfn, p_hwfn->p_main_ptt);
+ if (rc)
+ goto alloc_err;
+
+ /* EQ */
+ p_eq = qed_eq_alloc(p_hwfn, 256);
+ if (!p_eq) {
+ rc = -ENOMEM;
+ goto alloc_err;
+ }
+ p_hwfn->p_eq = p_eq;
+
+ p_consq = qed_consq_alloc(p_hwfn);
+ if (!p_consq) {
+ rc = -ENOMEM;
+ goto alloc_err;
+ }
+ p_hwfn->p_consq = p_consq;
+
+ /* DMA info initialization */
+ rc = qed_dmae_info_alloc(p_hwfn);
+ if (rc) {
+ DP_NOTICE(p_hwfn,
+ "Failed to allocate memory for dmae_info structure\n");
+ goto alloc_err;
+ }
+ }
+
+ cdev->reset_stats = kzalloc(sizeof(*cdev->reset_stats), GFP_KERNEL);
+ if (!cdev->reset_stats) {
+ DP_NOTICE(cdev, "Failed to allocate reset statistics\n");
+ rc = -ENOMEM;
+ goto alloc_err;
+ }
+
+ return 0;
+
+alloc_err:
+ qed_resc_free(cdev);
+ return rc;
+}
+
+void qed_resc_setup(struct qed_dev *cdev)
+{
+ int i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ qed_cxt_mngr_setup(p_hwfn);
+ qed_spq_setup(p_hwfn);
+ qed_eq_setup(p_hwfn, p_hwfn->p_eq);
+ qed_consq_setup(p_hwfn, p_hwfn->p_consq);
+
+ /* Read shadow of current MFW mailbox */
+ qed_mcp_read_mb(p_hwfn, p_hwfn->p_main_ptt);
+ memcpy(p_hwfn->mcp_info->mfw_mb_shadow,
+ p_hwfn->mcp_info->mfw_mb_cur,
+ p_hwfn->mcp_info->mfw_mb_length);
+
+ qed_int_setup(p_hwfn, p_hwfn->p_main_ptt);
+ }
+}
+
+#define FINAL_CLEANUP_CMD_OFFSET (0)
+#define FINAL_CLEANUP_CMD (0x1)
+#define FINAL_CLEANUP_VALID_OFFSET (6)
+#define FINAL_CLEANUP_VFPF_ID_SHIFT (7)
+#define FINAL_CLEANUP_COMP (0x2)
+#define FINAL_CLEANUP_POLL_CNT (100)
+#define FINAL_CLEANUP_POLL_TIME (10)
+int qed_final_cleanup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u16 id)
+{
+ u32 command = 0, addr, count = FINAL_CLEANUP_POLL_CNT;
+ int rc = -EBUSY;
+
+ addr = GTT_BAR0_MAP_REG_USDM_RAM + USTORM_FLR_FINAL_ACK_OFFSET;
+
+ command |= FINAL_CLEANUP_CMD << FINAL_CLEANUP_CMD_OFFSET;
+ command |= 1 << FINAL_CLEANUP_VALID_OFFSET;
+ command |= id << FINAL_CLEANUP_VFPF_ID_SHIFT;
+ command |= FINAL_CLEANUP_COMP << SDM_OP_GEN_COMP_TYPE_SHIFT;
+
+ /* Make sure notification is not set before initiating final cleanup */
+ if (REG_RD(p_hwfn, addr)) {
+ DP_NOTICE(
+ p_hwfn,
+ "Unexpected; Found final cleanup notification before initiating final cleanup\n");
+ REG_WR(p_hwfn, addr, 0);
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+ "Sending final cleanup for PFVF[%d] [Command %08x\n]",
+ id, command);
+
+ qed_wr(p_hwfn, p_ptt, XSDM_REG_OPERATION_GEN, command);
+
+ /* Poll until completion */
+ while (!REG_RD(p_hwfn, addr) && count--)
+ msleep(FINAL_CLEANUP_POLL_TIME);
+
+ if (REG_RD(p_hwfn, addr))
+ rc = 0;
+ else
+ DP_NOTICE(p_hwfn,
+ "Failed to receive FW final cleanup notification\n");
+
+ /* Cleanup afterwards */
+ REG_WR(p_hwfn, addr, 0);
+
+ return rc;
+}
+
+static void qed_calc_hw_mode(struct qed_hwfn *p_hwfn)
+{
+ int hw_mode = 0;
+
+ hw_mode = (1 << MODE_BB_A0);
+
+ switch (p_hwfn->cdev->num_ports_in_engines) {
+ case 1:
+ hw_mode |= 1 << MODE_PORTS_PER_ENG_1;
+ break;
+ case 2:
+ hw_mode |= 1 << MODE_PORTS_PER_ENG_2;
+ break;
+ case 4:
+ hw_mode |= 1 << MODE_PORTS_PER_ENG_4;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "num_ports_in_engine = %d not supported\n",
+ p_hwfn->cdev->num_ports_in_engines);
+ return;
+ }
+
+ switch (p_hwfn->cdev->mf_mode) {
+ case SF:
+ hw_mode |= 1 << MODE_SF;
+ break;
+ case MF_OVLAN:
+ hw_mode |= 1 << MODE_MF_SD;
+ break;
+ case MF_NPAR:
+ hw_mode |= 1 << MODE_MF_SI;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unsupported MF mode, init as SF\n");
+ hw_mode |= 1 << MODE_SF;
+ }
+
+ hw_mode |= 1 << MODE_ASIC;
+
+ p_hwfn->hw_info.hw_mode = hw_mode;
+}
+
+/* Init run time data for all PFs on an engine. */
+static void qed_init_cau_rt_data(struct qed_dev *cdev)
+{
+ u32 offset = CAU_REG_SB_VAR_MEMORY_RT_OFFSET;
+ int i, sb_id;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ struct qed_igu_info *p_igu_info;
+ struct qed_igu_block *p_block;
+ struct cau_sb_entry sb_entry;
+
+ p_igu_info = p_hwfn->hw_info.p_igu_info;
+
+ for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(cdev);
+ sb_id++) {
+ p_block = &p_igu_info->igu_map.igu_blocks[sb_id];
+ if (!p_block->is_pf)
+ continue;
+
+ qed_init_cau_sb_entry(p_hwfn, &sb_entry,
+ p_block->function_id,
+ 0, 0);
+ STORE_RT_REG_AGG(p_hwfn, offset + sb_id * 2,
+ sb_entry);
+ }
+ }
+}
+
+static int qed_hw_init_common(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ int hw_mode)
+{
+ struct qed_qm_info *qm_info = &p_hwfn->qm_info;
+ struct qed_qm_common_rt_init_params params;
+ struct qed_dev *cdev = p_hwfn->cdev;
+ int rc = 0;
+
+ qed_init_cau_rt_data(cdev);
+
+ /* Program GTT windows */
+ qed_gtt_init(p_hwfn);
+
+ if (p_hwfn->mcp_info) {
+ if (p_hwfn->mcp_info->func_info.bandwidth_max)
+ qm_info->pf_rl_en = 1;
+ if (p_hwfn->mcp_info->func_info.bandwidth_min)
+ qm_info->pf_wfq_en = 1;
+ }
+
+ memset(&params, 0, sizeof(params));
+ params.max_ports_per_engine = p_hwfn->cdev->num_ports_in_engines;
+ params.max_phys_tcs_per_port = qm_info->max_phys_tcs_per_port;
+ params.pf_rl_en = qm_info->pf_rl_en;
+ params.pf_wfq_en = qm_info->pf_wfq_en;
+ params.vport_rl_en = qm_info->vport_rl_en;
+ params.vport_wfq_en = qm_info->vport_wfq_en;
+ params.port_params = qm_info->qm_port_params;
+
+ qed_qm_common_rt_init(p_hwfn, &params);
+
+ qed_cxt_hw_init_common(p_hwfn);
+
+ /* Close gate from NIG to BRB/Storm; By default they are open, but
+ * we close them to prevent NIG from passing data to reset blocks.
+ * Should have been done in the ENGINE phase, but init-tool lacks
+ * proper port-pretend capabilities.
+ */
+ qed_wr(p_hwfn, p_ptt, NIG_REG_RX_BRB_OUT_EN, 0);
+ qed_wr(p_hwfn, p_ptt, NIG_REG_STORM_OUT_EN, 0);
+ qed_port_pretend(p_hwfn, p_ptt, p_hwfn->port_id ^ 1);
+ qed_wr(p_hwfn, p_ptt, NIG_REG_RX_BRB_OUT_EN, 0);
+ qed_wr(p_hwfn, p_ptt, NIG_REG_STORM_OUT_EN, 0);
+ qed_port_unpretend(p_hwfn, p_ptt);
+
+ rc = qed_init_run(p_hwfn, p_ptt, PHASE_ENGINE, ANY_PHASE_ID, hw_mode);
+ if (rc != 0)
+ return rc;
+
+ qed_wr(p_hwfn, p_ptt, PSWRQ2_REG_L2P_VALIDATE_VFID, 0);
+ qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_USE_CLIENTID_IN_TAG, 1);
+
+ /* Disable relaxed ordering in the PCI config space */
+ qed_wr(p_hwfn, p_ptt, 0x20b4,
+ qed_rd(p_hwfn, p_ptt, 0x20b4) & ~0x10);
+
+ return rc;
+}
+
+static int qed_hw_init_port(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ int hw_mode)
+{
+ int rc = 0;
+
+ rc = qed_init_run(p_hwfn, p_ptt, PHASE_PORT, p_hwfn->port_id,
+ hw_mode);
+ return rc;
+}
+
+static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ int hw_mode,
+ bool b_hw_start,
+ enum qed_int_mode int_mode,
+ bool allow_npar_tx_switch)
+{
+ u8 rel_pf_id = p_hwfn->rel_pf_id;
+ int rc = 0;
+
+ if (p_hwfn->mcp_info) {
+ struct qed_mcp_function_info *p_info;
+
+ p_info = &p_hwfn->mcp_info->func_info;
+ if (p_info->bandwidth_min)
+ p_hwfn->qm_info.pf_wfq = p_info->bandwidth_min;
+
+ /* Update rate limit once we'll actually have a link */
+ p_hwfn->qm_info.pf_rl = 100;
+ }
+
+ qed_cxt_hw_init_pf(p_hwfn);
+
+ qed_int_igu_init_rt(p_hwfn);
+
+ /* Set VLAN in NIG if needed */
+ if (hw_mode & (1 << MODE_MF_SD)) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW, "Configuring LLH_FUNC_TAG\n");
+ STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET, 1);
+ STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET,
+ p_hwfn->hw_info.ovlan);
+ }
+
+ /* Enable classification by MAC if needed */
+ if (hw_mode & (1 << MODE_MF_SI)) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "Configuring TAGMAC_CLS_TYPE\n");
+ STORE_RT_REG(p_hwfn,
+ NIG_REG_LLH_FUNC_TAGMAC_CLS_TYPE_RT_OFFSET, 1);
+ }
+
+ /* Protocl Configuration */
+ STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_TCP_RT_OFFSET, 0);
+ STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_FCOE_RT_OFFSET, 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);
+ if (rc != 0)
+ return rc;
+
+ /* PF Init sequence */
+ rc = qed_init_run(p_hwfn, p_ptt, PHASE_PF, rel_pf_id, hw_mode);
+ if (rc)
+ return rc;
+
+ /* QM_PF Init sequence (may be invoked separately e.g. for DCB) */
+ rc = qed_init_run(p_hwfn, p_ptt, PHASE_QM_PF, rel_pf_id, hw_mode);
+ if (rc)
+ return rc;
+
+ /* Pure runtime initializations - directly to the HW */
+ qed_int_igu_init_pure_rt(p_hwfn, p_ptt, true, true);
+
+ if (b_hw_start) {
+ /* enable interrupts */
+ qed_int_igu_enable(p_hwfn, p_ptt, int_mode);
+
+ /* send function start command */
+ rc = qed_sp_pf_start(p_hwfn, p_hwfn->cdev->mf_mode);
+ if (rc)
+ DP_NOTICE(p_hwfn, "Function start ramrod failed\n");
+ }
+ return rc;
+}
+
+static int qed_change_pci_hwfn(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 enable)
+{
+ u32 delay_idx = 0, val, set_val = enable ? 1 : 0;
+
+ /* Change PF in PXP */
+ 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 */
+ for (delay_idx = 0; delay_idx < 20000; delay_idx++) {
+ val = qed_rd(p_hwfn, p_ptt,
+ PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
+ if (val == set_val)
+ break;
+
+ usleep_range(50, 60);
+ }
+
+ if (val != set_val) {
+ DP_NOTICE(p_hwfn,
+ "PFID_ENABLE_MASTER wasn't changed after a second\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static void qed_reset_mb_shadow(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_main_ptt)
+{
+ /* Read shadow of current MFW mailbox */
+ qed_mcp_read_mb(p_hwfn, p_main_ptt);
+ memcpy(p_hwfn->mcp_info->mfw_mb_shadow,
+ p_hwfn->mcp_info->mfw_mb_cur,
+ p_hwfn->mcp_info->mfw_mb_length);
+}
+
+int qed_hw_init(struct qed_dev *cdev,
+ bool b_hw_start,
+ enum qed_int_mode int_mode,
+ bool allow_npar_tx_switch,
+ const u8 *bin_fw_data)
+{
+ struct qed_storm_stats *p_stat;
+ u32 load_code, param, *p_address;
+ int rc, mfw_rc, i;
+ u8 fw_vport = 0;
+
+ rc = qed_init_fw_data(cdev, bin_fw_data);
+ if (rc != 0)
+ return rc;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ rc = qed_fw_vport(p_hwfn, 0, &fw_vport);
+ if (rc != 0)
+ return rc;
+
+ /* Enable DMAE in PXP */
+ rc = qed_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true);
+
+ qed_calc_hw_mode(p_hwfn);
+
+ rc = qed_mcp_load_req(p_hwfn, p_hwfn->p_main_ptt,
+ &load_code);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed sending LOAD_REQ command\n");
+ return rc;
+ }
+
+ qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt);
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "Load request was sent. Resp:0x%x, Load code: 0x%x\n",
+ rc, load_code);
+
+ p_hwfn->first_on_engine = (load_code ==
+ FW_MSG_CODE_DRV_LOAD_ENGINE);
+
+ switch (load_code) {
+ case FW_MSG_CODE_DRV_LOAD_ENGINE:
+ rc = qed_hw_init_common(p_hwfn, p_hwfn->p_main_ptt,
+ p_hwfn->hw_info.hw_mode);
+ if (rc)
+ break;
+ /* Fall into */
+ case FW_MSG_CODE_DRV_LOAD_PORT:
+ rc = qed_hw_init_port(p_hwfn, p_hwfn->p_main_ptt,
+ p_hwfn->hw_info.hw_mode);
+ if (rc)
+ break;
+
+ /* Fall into */
+ case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+ rc = qed_hw_init_pf(p_hwfn, p_hwfn->p_main_ptt,
+ p_hwfn->hw_info.hw_mode,
+ b_hw_start, int_mode,
+ allow_npar_tx_switch);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc)
+ DP_NOTICE(p_hwfn,
+ "init phase failed for loadcode 0x%x (rc %d)\n",
+ load_code, rc);
+
+ /* 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);
+ if (rc)
+ return rc;
+ if (mfw_rc) {
+ DP_NOTICE(p_hwfn, "Failed sending LOAD_DONE command\n");
+ return mfw_rc;
+ }
+
+ p_hwfn->hw_init_done = true;
+
+ /* init PF stats */
+ p_stat = &p_hwfn->storm_stats;
+ p_stat->mstats.address = BAR0_MAP_REG_MSDM_RAM +
+ MSTORM_QUEUE_STAT_OFFSET(fw_vport);
+ p_stat->mstats.len = sizeof(struct eth_mstorm_per_queue_stat);
+
+ p_stat->ustats.address = BAR0_MAP_REG_USDM_RAM +
+ USTORM_QUEUE_STAT_OFFSET(fw_vport);
+ p_stat->ustats.len = sizeof(struct eth_ustorm_per_queue_stat);
+
+ p_stat->pstats.address = BAR0_MAP_REG_PSDM_RAM +
+ PSTORM_QUEUE_STAT_OFFSET(fw_vport);
+ p_stat->pstats.len = sizeof(struct eth_pstorm_per_queue_stat);
+
+ p_address = &p_stat->tstats.address;
+ *p_address = BAR0_MAP_REG_TSDM_RAM +
+ TSTORM_PORT_STAT_OFFSET(MFW_PORT(p_hwfn));
+ p_stat->tstats.len = sizeof(struct tstorm_per_port_stat);
+ }
+
+ return 0;
+}
+
+#define QED_HW_STOP_RETRY_LIMIT (10)
+int qed_hw_stop(struct qed_dev *cdev)
+{
+ int rc = 0, t_rc;
+ int i, j;
+
+ for_each_hwfn(cdev, j) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[j];
+ struct qed_ptt *p_ptt = p_hwfn->p_main_ptt;
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_IFDOWN, "Stopping hw/fw\n");
+
+ /* mark the hw as uninitialized... */
+ p_hwfn->hw_init_done = false;
+
+ rc = qed_sp_pf_stop(p_hwfn);
+ if (rc)
+ return rc;
+
+ qed_wr(p_hwfn, p_ptt,
+ NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x1);
+
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_OPENFLOW, 0x0);
+
+ qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0);
+ qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0);
+ for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) {
+ if ((!qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_CONN)) &&
+ (!qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_TASK)))
+ break;
+
+ usleep_range(1000, 2000);
+ }
+ if (i == QED_HW_STOP_RETRY_LIMIT)
+ DP_NOTICE(p_hwfn,
+ "Timers linear scans are not over [Connection %02x Tasks %02x]\n",
+ (u8)qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_CONN),
+ (u8)qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_TASK));
+
+ /* Disable Attention Generation */
+ qed_int_igu_disable_int(p_hwfn, p_ptt);
+
+ qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0);
+ qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0);
+
+ qed_int_igu_init_pure_rt(p_hwfn, p_ptt, false, true);
+
+ /* Need to wait 1ms to guarantee SBs are cleared */
+ usleep_range(1000, 2000);
+ }
+
+ /* 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.
+ */
+ t_rc = qed_change_pci_hwfn(&cdev->hwfns[0],
+ cdev->hwfns[0].p_main_ptt,
+ false);
+ if (t_rc != 0)
+ rc = t_rc;
+
+ return rc;
+}
+
+void qed_hw_stop_fastpath(struct qed_dev *cdev)
+{
+ int i, j;
+
+ for_each_hwfn(cdev, j) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[j];
+ struct qed_ptt *p_ptt = p_hwfn->p_main_ptt;
+
+ DP_VERBOSE(p_hwfn,
+ NETIF_MSG_IFDOWN,
+ "Shutting down the fastpath\n");
+
+ qed_wr(p_hwfn, p_ptt,
+ NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x1);
+
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0);
+ qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_OPENFLOW, 0x0);
+
+ qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0);
+ qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0);
+ for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) {
+ if ((!qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_CONN)) &&
+ (!qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_TASK)))
+ break;
+
+ usleep_range(1000, 2000);
+ }
+ if (i == QED_HW_STOP_RETRY_LIMIT)
+ DP_NOTICE(p_hwfn,
+ "Timers linear scans are not over [Connection %02x Tasks %02x]\n",
+ (u8)qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_CONN),
+ (u8)qed_rd(p_hwfn, p_ptt,
+ TM_REG_PF_SCAN_ACTIVE_TASK));
+
+ qed_int_igu_init_pure_rt(p_hwfn, p_ptt, false, false);
+
+ /* Need to wait 1ms to guarantee SBs are cleared */
+ usleep_range(1000, 2000);
+ }
+}
+
+void qed_hw_start_fastpath(struct qed_hwfn *p_hwfn)
+{
+ /* Re-open incoming traffic */
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt,
+ NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x0);
+}
+
+static int qed_reg_assert(struct qed_hwfn *hwfn,
+ struct qed_ptt *ptt, u32 reg,
+ bool expected)
+{
+ u32 assert_val = qed_rd(hwfn, ptt, reg);
+
+ if (assert_val != expected) {
+ DP_NOTICE(hwfn, "Value at address 0x%x != 0x%08x\n",
+ reg, expected);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int qed_hw_reset(struct qed_dev *cdev)
+{
+ int rc = 0;
+ u32 unload_resp, unload_param;
+ int i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_IFDOWN, "Resetting hw/fw\n");
+
+ /* Check for incorrect states */
+ qed_reg_assert(p_hwfn, p_hwfn->p_main_ptt,
+ QM_REG_USG_CNT_PF_TX, 0);
+ qed_reg_assert(p_hwfn, p_hwfn->p_main_ptt,
+ QM_REG_USG_CNT_PF_OTHER, 0);
+
+ /* Disable PF in HW blocks */
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt, DORQ_REG_PF_DB_ENABLE, 0);
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt, QM_REG_PF_EN, 0);
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt,
+ TCFC_REG_STRONG_ENABLE_PF, 0);
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt,
+ CCFC_REG_STRONG_ENABLE_PF, 0);
+
+ /* Send unload command to MCP */
+ rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
+ DRV_MSG_CODE_UNLOAD_REQ,
+ DRV_MB_PARAM_UNLOAD_WOL_MCP,
+ &unload_resp, &unload_param);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_REQ failed\n");
+ unload_resp = FW_MSG_CODE_DRV_UNLOAD_ENGINE;
+ }
+
+ rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
+ DRV_MSG_CODE_UNLOAD_DONE,
+ 0, &unload_resp, &unload_param);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_DONE failed\n");
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+/* Free hwfn memory and resources acquired in hw_hwfn_prepare */
+static void qed_hw_hwfn_free(struct qed_hwfn *p_hwfn)
+{
+ qed_ptt_pool_free(p_hwfn);
+ kfree(p_hwfn->hw_info.p_igu_info);
+}
+
+/* Setup bar access */
+static int qed_hw_hwfn_prepare(struct qed_hwfn *p_hwfn)
+{
+ int rc;
+
+ /* Allocate PTT pool */
+ rc = qed_ptt_pool_alloc(p_hwfn);
+ if (rc)
+ return rc;
+
+ /* Allocate the main PTT */
+ p_hwfn->p_main_ptt = qed_get_reserved_ptt(p_hwfn, RESERVED_PTT_MAIN);
+
+ /* clear indirect access */
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_88_F0, 0);
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_8C_F0, 0);
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_90_F0, 0);
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_94_F0, 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);
+
+ /* enable internal target-read */
+ qed_wr(p_hwfn, p_hwfn->p_main_ptt,
+ PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
+ return 0;
+}
+
+static void get_function_id(struct qed_hwfn *p_hwfn)
+{
+ /* ME Register */
+ p_hwfn->hw_info.opaque_fid = (u16)REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR);
+
+ p_hwfn->hw_info.concrete_fid = REG_RD(p_hwfn, PXP_PF_ME_CONCRETE_ADDR);
+
+ p_hwfn->abs_pf_id = (p_hwfn->hw_info.concrete_fid >> 16) & 0xf;
+ p_hwfn->rel_pf_id = GET_FIELD(p_hwfn->hw_info.concrete_fid,
+ PXP_CONCRETE_FID_PFID);
+ p_hwfn->port_id = GET_FIELD(p_hwfn->hw_info.concrete_fid,
+ PXP_CONCRETE_FID_PORT);
+}
+
+static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
+{
+ u32 *feat_num = p_hwfn->hw_info.feat_num;
+ int num_features = 1;
+
+ feat_num[QED_PF_L2_QUE] = min_t(u32, RESC_NUM(p_hwfn, QED_SB) /
+ num_features,
+ RESC_NUM(p_hwfn, QED_L2_QUEUE));
+ DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE,
+ "#PF_L2_QUEUES=%d #SBS=%d num_features=%d\n",
+ feat_num[QED_PF_L2_QUE], RESC_NUM(p_hwfn, QED_SB),
+ num_features);
+}
+
+static void qed_hw_get_resc(struct qed_hwfn *p_hwfn)
+{
+ u32 *resc_start = p_hwfn->hw_info.resc_start;
+ u32 *resc_num = p_hwfn->hw_info.resc_num;
+ int num_funcs, i;
+
+ num_funcs = IS_MF(p_hwfn) ? MAX_NUM_PFS_BB
+ : p_hwfn->cdev->num_ports_in_engines;
+
+ resc_num[QED_SB] = min_t(u32,
+ (MAX_SB_PER_PATH_BB / num_funcs),
+ qed_int_get_num_sbs(p_hwfn, NULL));
+ resc_num[QED_L2_QUEUE] = MAX_NUM_L2_QUEUES_BB / num_funcs;
+ resc_num[QED_VPORT] = MAX_NUM_VPORTS_BB / num_funcs;
+ resc_num[QED_RSS_ENG] = ETH_RSS_ENGINE_NUM_BB / num_funcs;
+ resc_num[QED_PQ] = MAX_QM_TX_QUEUES_BB / num_funcs;
+ resc_num[QED_RL] = 8;
+ resc_num[QED_MAC] = ETH_NUM_MAC_FILTERS / num_funcs;
+ resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) /
+ num_funcs;
+ resc_num[QED_ILT] = 950;
+
+ for (i = 0; i < QED_MAX_RESC; i++)
+ resc_start[i] = resc_num[i] * p_hwfn->rel_pf_id;
+
+ qed_hw_set_feat(p_hwfn);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE,
+ "The numbers for each resource are:\n"
+ "SB = %d start = %d\n"
+ "L2_QUEUE = %d start = %d\n"
+ "VPORT = %d start = %d\n"
+ "PQ = %d start = %d\n"
+ "RL = %d start = %d\n"
+ "MAC = %d start = %d\n"
+ "VLAN = %d start = %d\n"
+ "ILT = %d start = %d\n",
+ p_hwfn->hw_info.resc_num[QED_SB],
+ p_hwfn->hw_info.resc_start[QED_SB],
+ p_hwfn->hw_info.resc_num[QED_L2_QUEUE],
+ p_hwfn->hw_info.resc_start[QED_L2_QUEUE],
+ p_hwfn->hw_info.resc_num[QED_VPORT],
+ p_hwfn->hw_info.resc_start[QED_VPORT],
+ p_hwfn->hw_info.resc_num[QED_PQ],
+ p_hwfn->hw_info.resc_start[QED_PQ],
+ p_hwfn->hw_info.resc_num[QED_RL],
+ p_hwfn->hw_info.resc_start[QED_RL],
+ p_hwfn->hw_info.resc_num[QED_MAC],
+ p_hwfn->hw_info.resc_start[QED_MAC],
+ p_hwfn->hw_info.resc_num[QED_VLAN],
+ p_hwfn->hw_info.resc_start[QED_VLAN],
+ p_hwfn->hw_info.resc_num[QED_ILT],
+ p_hwfn->hw_info.resc_start[QED_ILT]);
+}
+
+static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
+ u32 port_cfg_addr, link_temp, val, nvm_cfg_addr;
+ struct qed_mcp_link_params *link;
+
+ /* Read global nvm_cfg address */
+ nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
+
+ /* Verify MCP has initialized it */
+ if (!nvm_cfg_addr) {
+ DP_NOTICE(p_hwfn, "Shared memory not initialized\n");
+ return -EINVAL;
+ }
+
+ /* Read nvm_cfg1 (Notice this is just offset, and not offsize (TBD) */
+ nvm_cfg1_offset = qed_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
+
+ /* Read Vendor Id / Device Id */
+ addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+ offsetof(struct nvm_cfg1, glob) +
+ offsetof(struct nvm_cfg1_glob, pci_id);
+ p_hwfn->hw_info.vendor_id = qed_rd(p_hwfn, p_ptt, addr) &
+ NVM_CFG1_GLOB_VENDOR_ID_MASK;
+
+ addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+ offsetof(struct nvm_cfg1, glob) +
+ offsetof(struct nvm_cfg1_glob, core_cfg);
+
+ core_cfg = qed_rd(p_hwfn, p_ptt, addr);
+
+ switch ((core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >>
+ NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET) {
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X40G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X40G;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X50G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X50G;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X100G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X100G;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_F:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_F;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_E:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_E;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X20G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X20G;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X40G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X40G;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X25G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X25G;
+ break;
+ case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X25G:
+ p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X25G;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unknown port mode in 0x%08x\n",
+ core_cfg);
+ break;
+ }
+
+ addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+ offsetof(struct nvm_cfg1, func[MCP_PF_ID(p_hwfn)]) +
+ offsetof(struct nvm_cfg1_func, device_id);
+ val = qed_rd(p_hwfn, p_ptt, addr);
+
+ if (IS_MF(p_hwfn)) {
+ p_hwfn->hw_info.device_id =
+ (val & NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_MASK) >>
+ NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_OFFSET;
+ } else {
+ p_hwfn->hw_info.device_id =
+ (val & NVM_CFG1_FUNC_VENDOR_DEVICE_ID_MASK) >>
+ NVM_CFG1_FUNC_VENDOR_DEVICE_ID_OFFSET;
+ }
+
+ /* Read default link configuration */
+ link = &p_hwfn->mcp_info->link_input;
+ port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+ offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
+ link_temp = qed_rd(p_hwfn, p_ptt,
+ port_cfg_addr +
+ offsetof(struct nvm_cfg1_port, speed_cap_mask));
+ link->speed.advertised_speeds =
+ link_temp & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK;
+
+ p_hwfn->mcp_info->link_capabilities.speed_capabilities =
+ link->speed.advertised_speeds;
+
+ link_temp = qed_rd(p_hwfn, p_ptt,
+ port_cfg_addr +
+ offsetof(struct nvm_cfg1_port, link_settings));
+ switch ((link_temp & NVM_CFG1_PORT_DRV_LINK_SPEED_MASK) >>
+ NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET) {
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG:
+ link->speed.autoneg = true;
+ break;
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_1G:
+ link->speed.forced_speed = 1000;
+ break;
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_10G:
+ link->speed.forced_speed = 10000;
+ break;
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_25G:
+ link->speed.forced_speed = 25000;
+ break;
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_40G:
+ link->speed.forced_speed = 40000;
+ break;
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_50G:
+ link->speed.forced_speed = 50000;
+ break;
+ case NVM_CFG1_PORT_DRV_LINK_SPEED_100G:
+ link->speed.forced_speed = 100000;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unknown Speed in 0x%08x\n",
+ link_temp);
+ }
+
+ link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK;
+ link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET;
+ link->pause.autoneg = !!(link_temp &
+ NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
+ link->pause.forced_rx = !!(link_temp &
+ NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
+ link->pause.forced_tx = !!(link_temp &
+ NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
+ link->loopback_mode = 0;
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+ "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x\n",
+ link->speed.forced_speed, link->speed.advertised_speeds,
+ link->speed.autoneg, link->pause.autoneg);
+
+ /* Read Multi-function information from shmem */
+ addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+ offsetof(struct nvm_cfg1, glob) +
+ offsetof(struct nvm_cfg1_glob, generic_cont0);
+
+ generic_cont0 = qed_rd(p_hwfn, p_ptt, addr);
+
+ mf_mode = (generic_cont0 & NVM_CFG1_GLOB_MF_MODE_MASK) >>
+ NVM_CFG1_GLOB_MF_MODE_OFFSET;
+
+ switch (mf_mode) {
+ case NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED:
+ p_hwfn->cdev->mf_mode = MF_OVLAN;
+ break;
+ case NVM_CFG1_GLOB_MF_MODE_NPAR1_0:
+ p_hwfn->cdev->mf_mode = MF_NPAR;
+ break;
+ case NVM_CFG1_GLOB_MF_MODE_FORCED_SF:
+ p_hwfn->cdev->mf_mode = SF;
+ break;
+ }
+ DP_INFO(p_hwfn, "Multi function mode is %08x\n",
+ p_hwfn->cdev->mf_mode);
+
+ return qed_mcp_fill_shmem_func_info(p_hwfn, p_ptt);
+}
+
+static int
+qed_get_hw_info(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_pci_personality personality)
+{
+ u32 port_mode;
+ int rc;
+
+ /* Read the port mode */
+ port_mode = qed_rd(p_hwfn, p_ptt,
+ CNIG_REG_NW_PORT_MODE_BB_B0);
+
+ if (port_mode < 3) {
+ p_hwfn->cdev->num_ports_in_engines = 1;
+ } else if (port_mode <= 5) {
+ p_hwfn->cdev->num_ports_in_engines = 2;
+ } else {
+ DP_NOTICE(p_hwfn, "PORT MODE: %d not supported\n",
+ p_hwfn->cdev->num_ports_in_engines);
+
+ /* Default num_ports_in_engines to something */
+ p_hwfn->cdev->num_ports_in_engines = 1;
+ }
+
+ qed_hw_get_nvm_info(p_hwfn, p_ptt);
+
+ rc = qed_int_igu_read_cam(p_hwfn, p_ptt);
+ if (rc)
+ return rc;
+
+ if (qed_mcp_is_init(p_hwfn))
+ ether_addr_copy(p_hwfn->hw_info.hw_mac_addr,
+ p_hwfn->mcp_info->func_info.mac);
+ else
+ eth_random_addr(p_hwfn->hw_info.hw_mac_addr);
+
+ if (qed_mcp_is_init(p_hwfn)) {
+ if (p_hwfn->mcp_info->func_info.ovlan != QED_MCP_VLAN_UNSET)
+ p_hwfn->hw_info.ovlan =
+ p_hwfn->mcp_info->func_info.ovlan;
+
+ qed_mcp_cmd_port_init(p_hwfn, p_ptt);
+ }
+
+ if (qed_mcp_is_init(p_hwfn)) {
+ enum qed_pci_personality protocol;
+
+ protocol = p_hwfn->mcp_info->func_info.protocol;
+ p_hwfn->hw_info.personality = protocol;
+ }
+
+ qed_hw_get_resc(p_hwfn);
+
+ return rc;
+}
+
+static void qed_get_dev_info(struct qed_dev *cdev)
+{
+ u32 tmp;
+
+ cdev->chip_num = (u16)qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt,
+ MISCS_REG_CHIP_NUM);
+ cdev->chip_rev = (u16)qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt,
+ MISCS_REG_CHIP_REV);
+ MASK_FIELD(CHIP_REV, cdev->chip_rev);
+
+ /* Learn number of HW-functions */
+ tmp = qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt,
+ MISCS_REG_CMT_ENABLED_FOR_PAIR);
+
+ if (tmp & (1 << cdev->hwfns[0].rel_pf_id)) {
+ DP_NOTICE(cdev->hwfns, "device in CMT mode\n");
+ cdev->num_hwfns = 2;
+ } else {
+ cdev->num_hwfns = 1;
+ }
+
+ cdev->chip_bond_id = qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt,
+ MISCS_REG_CHIP_TEST_REG) >> 4;
+ MASK_FIELD(CHIP_BOND_ID, cdev->chip_bond_id);
+ cdev->chip_metal = (u16)qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt,
+ MISCS_REG_CHIP_METAL);
+ MASK_FIELD(CHIP_METAL, cdev->chip_metal);
+
+ DP_INFO(cdev->hwfns,
+ "Chip details - Num: %04x Rev: %04x Bond id: %04x Metal: %04x\n",
+ cdev->chip_num, cdev->chip_rev,
+ cdev->chip_bond_id, cdev->chip_metal);
+}
+
+static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
+ void __iomem *p_regview,
+ void __iomem *p_doorbells,
+ enum qed_pci_personality personality)
+{
+ int rc = 0;
+
+ /* Split PCI bars evenly between hwfns */
+ p_hwfn->regview = p_regview;
+ p_hwfn->doorbells = p_doorbells;
+
+ /* Validate that chip access is feasible */
+ if (REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR) == 0xffffffff) {
+ DP_ERR(p_hwfn,
+ "Reading the ME register returns all Fs; Preventing further chip access\n");
+ return -EINVAL;
+ }
+
+ get_function_id(p_hwfn);
+
+ rc = qed_hw_hwfn_prepare(p_hwfn);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to prepare hwfn's hw\n");
+ goto err0;
+ }
+
+ /* First hwfn learns basic information, e.g., number of hwfns */
+ if (!p_hwfn->my_id)
+ qed_get_dev_info(p_hwfn->cdev);
+
+ /* Initialize MCP structure */
+ rc = qed_mcp_cmd_init(p_hwfn, p_hwfn->p_main_ptt);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed initializing mcp command\n");
+ goto err1;
+ }
+
+ /* Read the device configuration information from the HW and SHMEM */
+ rc = qed_get_hw_info(p_hwfn, p_hwfn->p_main_ptt, personality);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to get HW information\n");
+ goto err2;
+ }
+
+ /* Allocate the init RT array and initialize the init-ops engine */
+ rc = qed_init_alloc(p_hwfn);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to allocate the init array\n");
+ goto err2;
+ }
+
+ return rc;
+err2:
+ qed_mcp_free(p_hwfn);
+err1:
+ qed_hw_hwfn_free(p_hwfn);
+err0:
+ return rc;
+}
+
+static u32 qed_hw_bar_size(struct qed_dev *cdev,
+ u8 bar_id)
+{
+ u32 size = pci_resource_len(cdev->pdev, (bar_id > 0) ? 2 : 0);
+
+ return size / cdev->num_hwfns;
+}
+
+int qed_hw_prepare(struct qed_dev *cdev,
+ int personality)
+{
+ int rc, i;
+
+ /* Store the precompiled init data ptrs */
+ qed_init_iro_array(cdev);
+
+ /* Initialize the first hwfn - will learn number of hwfns */
+ rc = qed_hw_prepare_single(&cdev->hwfns[0], cdev->regview,
+ cdev->doorbells, personality);
+ if (rc)
+ return rc;
+
+ personality = cdev->hwfns[0].hw_info.personality;
+
+ /* Initialize the rest of the hwfns */
+ for (i = 1; i < cdev->num_hwfns; i++) {
+ void __iomem *p_regview, *p_doorbell;
+
+ p_regview = cdev->regview +
+ i * qed_hw_bar_size(cdev, 0);
+ p_doorbell = cdev->doorbells +
+ i * qed_hw_bar_size(cdev, 1);
+ rc = qed_hw_prepare_single(&cdev->hwfns[i], p_regview,
+ p_doorbell, personality);
+ if (rc) {
+ /* Cleanup previously initialized hwfns */
+ while (--i >= 0) {
+ qed_init_free(&cdev->hwfns[i]);
+ qed_mcp_free(&cdev->hwfns[i]);
+ qed_hw_hwfn_free(&cdev->hwfns[i]);
+ }
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+void qed_hw_remove(struct qed_dev *cdev)
+{
+ int i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ qed_init_free(p_hwfn);
+ qed_hw_hwfn_free(p_hwfn);
+ qed_mcp_free(p_hwfn);
+ }
+}
+
+int qed_chain_alloc(struct qed_dev *cdev,
+ enum qed_chain_use_mode intended_use,
+ enum qed_chain_mode mode,
+ u16 num_elems,
+ size_t elem_size,
+ struct qed_chain *p_chain)
+{
+ dma_addr_t p_pbl_phys = 0;
+ void *p_pbl_virt = NULL;
+ dma_addr_t p_phys = 0;
+ void *p_virt = NULL;
+ u16 page_cnt = 0;
+ size_t size;
+
+ if (mode == QED_CHAIN_MODE_SINGLE)
+ page_cnt = 1;
+ else
+ page_cnt = QED_CHAIN_PAGE_CNT(num_elems, elem_size, mode);
+
+ size = page_cnt * QED_CHAIN_PAGE_SIZE;
+ p_virt = dma_alloc_coherent(&cdev->pdev->dev,
+ size, &p_phys, GFP_KERNEL);
+ if (!p_virt) {
+ DP_NOTICE(cdev, "Failed to allocate chain mem\n");
+ goto nomem;
+ }
+
+ if (mode == QED_CHAIN_MODE_PBL) {
+ size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE;
+ p_pbl_virt = dma_alloc_coherent(&cdev->pdev->dev,
+ size, &p_pbl_phys,
+ GFP_KERNEL);
+ if (!p_pbl_virt) {
+ DP_NOTICE(cdev, "Failed to allocate chain pbl mem\n");
+ goto nomem;
+ }
+
+ qed_chain_pbl_init(p_chain, p_virt, p_phys, page_cnt,
+ (u8)elem_size, intended_use,
+ p_pbl_phys, p_pbl_virt);
+ } else {
+ qed_chain_init(p_chain, p_virt, p_phys, page_cnt,
+ (u8)elem_size, intended_use, mode);
+ }
+
+ return 0;
+
+nomem:
+ dma_free_coherent(&cdev->pdev->dev,
+ page_cnt * QED_CHAIN_PAGE_SIZE,
+ p_virt, p_phys);
+ dma_free_coherent(&cdev->pdev->dev,
+ page_cnt * QED_CHAIN_PBL_ENTRY_SIZE,
+ p_pbl_virt, p_pbl_phys);
+
+ return -ENOMEM;
+}
+
+void qed_chain_free(struct qed_dev *cdev,
+ struct qed_chain *p_chain)
+{
+ size_t size;
+
+ if (!p_chain->p_virt_addr)
+ return;
+
+ if (p_chain->mode == QED_CHAIN_MODE_PBL) {
+ size = p_chain->page_cnt * QED_CHAIN_PBL_ENTRY_SIZE;
+ dma_free_coherent(&cdev->pdev->dev, size,
+ p_chain->pbl.p_virt_table,
+ p_chain->pbl.p_phys_table);
+ }
+
+ size = p_chain->page_cnt * QED_CHAIN_PAGE_SIZE;
+ dma_free_coherent(&cdev->pdev->dev, size,
+ p_chain->p_virt_addr,
+ p_chain->p_phys_addr);
+}
+
+static void __qed_get_vport_stats(struct qed_dev *cdev,
+ struct qed_eth_stats *stats)
+{
+ int i, j;
+
+ memset(stats, 0, sizeof(*stats));
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ struct eth_mstorm_per_queue_stat mstats;
+ struct eth_ustorm_per_queue_stat ustats;
+ struct eth_pstorm_per_queue_stat pstats;
+ struct tstorm_per_port_stat tstats;
+ struct port_stats port_stats;
+ struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn);
+
+ if (!p_ptt) {
+ DP_ERR(p_hwfn, "Failed to acquire ptt\n");
+ continue;
+ }
+
+ memset(&mstats, 0, sizeof(mstats));
+ qed_memcpy_from(p_hwfn, p_ptt, &mstats,
+ p_hwfn->storm_stats.mstats.address,
+ p_hwfn->storm_stats.mstats.len);
+
+ memset(&ustats, 0, sizeof(ustats));
+ qed_memcpy_from(p_hwfn, p_ptt, &ustats,
+ p_hwfn->storm_stats.ustats.address,
+ p_hwfn->storm_stats.ustats.len);
+
+ memset(&pstats, 0, sizeof(pstats));
+ qed_memcpy_from(p_hwfn, p_ptt, &pstats,
+ p_hwfn->storm_stats.pstats.address,
+ p_hwfn->storm_stats.pstats.len);
+
+ memset(&tstats, 0, sizeof(tstats));
+ qed_memcpy_from(p_hwfn, p_ptt, &tstats,
+ p_hwfn->storm_stats.tstats.address,
+ p_hwfn->storm_stats.tstats.len);
+
+ memset(&port_stats, 0, sizeof(port_stats));
+
+ if (p_hwfn->mcp_info)
+ qed_memcpy_from(p_hwfn, p_ptt, &port_stats,
+ p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port, stats),
+ sizeof(port_stats));
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ stats->no_buff_discards +=
+ HILO_64_REGPAIR(mstats.no_buff_discard);
+ stats->packet_too_big_discard +=
+ HILO_64_REGPAIR(mstats.packet_too_big_discard);
+ stats->ttl0_discard +=
+ HILO_64_REGPAIR(mstats.ttl0_discard);
+ stats->tpa_coalesced_pkts +=
+ HILO_64_REGPAIR(mstats.tpa_coalesced_pkts);
+ stats->tpa_coalesced_events +=
+ HILO_64_REGPAIR(mstats.tpa_coalesced_events);
+ stats->tpa_aborts_num +=
+ HILO_64_REGPAIR(mstats.tpa_aborts_num);
+ stats->tpa_coalesced_bytes +=
+ HILO_64_REGPAIR(mstats.tpa_coalesced_bytes);
+
+ stats->rx_ucast_bytes +=
+ HILO_64_REGPAIR(ustats.rcv_ucast_bytes);
+ stats->rx_mcast_bytes +=
+ HILO_64_REGPAIR(ustats.rcv_mcast_bytes);
+ stats->rx_bcast_bytes +=
+ HILO_64_REGPAIR(ustats.rcv_bcast_bytes);
+ stats->rx_ucast_pkts +=
+ HILO_64_REGPAIR(ustats.rcv_ucast_pkts);
+ stats->rx_mcast_pkts +=
+ HILO_64_REGPAIR(ustats.rcv_mcast_pkts);
+ stats->rx_bcast_pkts +=
+ HILO_64_REGPAIR(ustats.rcv_bcast_pkts);
+
+ stats->mftag_filter_discards +=
+ HILO_64_REGPAIR(tstats.mftag_filter_discard);
+ stats->mac_filter_discards +=
+ HILO_64_REGPAIR(tstats.eth_mac_filter_discard);
+
+ stats->tx_ucast_bytes +=
+ HILO_64_REGPAIR(pstats.sent_ucast_bytes);
+ stats->tx_mcast_bytes +=
+ HILO_64_REGPAIR(pstats.sent_mcast_bytes);
+ stats->tx_bcast_bytes +=
+ HILO_64_REGPAIR(pstats.sent_bcast_bytes);
+ stats->tx_ucast_pkts +=
+ HILO_64_REGPAIR(pstats.sent_ucast_pkts);
+ stats->tx_mcast_pkts +=
+ HILO_64_REGPAIR(pstats.sent_mcast_pkts);
+ stats->tx_bcast_pkts +=
+ HILO_64_REGPAIR(pstats.sent_bcast_pkts);
+ stats->tx_err_drop_pkts +=
+ HILO_64_REGPAIR(pstats.error_drop_pkts);
+ stats->rx_64_byte_packets += port_stats.pmm.r64;
+ stats->rx_127_byte_packets += port_stats.pmm.r127;
+ stats->rx_255_byte_packets += port_stats.pmm.r255;
+ stats->rx_511_byte_packets += port_stats.pmm.r511;
+ stats->rx_1023_byte_packets += port_stats.pmm.r1023;
+ stats->rx_1518_byte_packets += port_stats.pmm.r1518;
+ stats->rx_1522_byte_packets += port_stats.pmm.r1522;
+ stats->rx_2047_byte_packets += port_stats.pmm.r2047;
+ stats->rx_4095_byte_packets += port_stats.pmm.r4095;
+ stats->rx_9216_byte_packets += port_stats.pmm.r9216;
+ stats->rx_16383_byte_packets += port_stats.pmm.r16383;
+ stats->rx_crc_errors += port_stats.pmm.rfcs;
+ stats->rx_mac_crtl_frames += port_stats.pmm.rxcf;
+ stats->rx_pause_frames += port_stats.pmm.rxpf;
+ stats->rx_pfc_frames += port_stats.pmm.rxpp;
+ stats->rx_align_errors += port_stats.pmm.raln;
+ stats->rx_carrier_errors += port_stats.pmm.rfcr;
+ stats->rx_oversize_packets += port_stats.pmm.rovr;
+ stats->rx_jabbers += port_stats.pmm.rjbr;
+ stats->rx_undersize_packets += port_stats.pmm.rund;
+ stats->rx_fragments += port_stats.pmm.rfrg;
+ stats->tx_64_byte_packets += port_stats.pmm.t64;
+ stats->tx_65_to_127_byte_packets += port_stats.pmm.t127;
+ stats->tx_128_to_255_byte_packets += port_stats.pmm.t255;
+ stats->tx_256_to_511_byte_packets += port_stats.pmm.t511;
+ stats->tx_512_to_1023_byte_packets += port_stats.pmm.t1023;
+ stats->tx_1024_to_1518_byte_packets += port_stats.pmm.t1518;
+ stats->tx_1519_to_2047_byte_packets += port_stats.pmm.t2047;
+ stats->tx_2048_to_4095_byte_packets += port_stats.pmm.t4095;
+ stats->tx_4096_to_9216_byte_packets += port_stats.pmm.t9216;
+ stats->tx_9217_to_16383_byte_packets += port_stats.pmm.t16383;
+ stats->tx_pause_frames += port_stats.pmm.txpf;
+ stats->tx_pfc_frames += port_stats.pmm.txpp;
+ stats->tx_lpi_entry_count += port_stats.pmm.tlpiec;
+ stats->tx_total_collisions += port_stats.pmm.tncl;
+ stats->rx_mac_bytes += port_stats.pmm.rbyte;
+ stats->rx_mac_uc_packets += port_stats.pmm.rxuca;
+ stats->rx_mac_mc_packets += port_stats.pmm.rxmca;
+ stats->rx_mac_bc_packets += port_stats.pmm.rxbca;
+ stats->rx_mac_frames_ok += port_stats.pmm.rxpok;
+ stats->tx_mac_bytes += port_stats.pmm.tbyte;
+ stats->tx_mac_uc_packets += port_stats.pmm.txuca;
+ stats->tx_mac_mc_packets += port_stats.pmm.txmca;
+ stats->tx_mac_bc_packets += port_stats.pmm.txbca;
+ stats->tx_mac_ctrl_frames += port_stats.pmm.txcf;
+
+ for (j = 0; j < 8; j++) {
+ stats->brb_truncates += port_stats.brb.brb_truncate[j];
+ stats->brb_discards += port_stats.brb.brb_discard[j];
+ }
+ }
+}
+
+void qed_get_vport_stats(struct qed_dev *cdev,
+ struct qed_eth_stats *stats)
+{
+ u32 i;
+
+ if (!cdev) {
+ memset(stats, 0, sizeof(*stats));
+ return;
+ }
+
+ __qed_get_vport_stats(cdev, stats);
+
+ if (!cdev->reset_stats)
+ return;
+
+ /* Reduce the statistics baseline */
+ for (i = 0; i < sizeof(struct qed_eth_stats) / sizeof(u64); i++)
+ ((u64 *)stats)[i] -= ((u64 *)cdev->reset_stats)[i];
+}
+
+/* zeroes V-PORT specific portion of stats (Port stats remains untouched) */
+void qed_reset_vport_stats(struct qed_dev *cdev)
+{
+ int i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ struct eth_mstorm_per_queue_stat mstats;
+ struct eth_ustorm_per_queue_stat ustats;
+ struct eth_pstorm_per_queue_stat pstats;
+ struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn);
+
+ if (!p_ptt) {
+ DP_ERR(p_hwfn, "Failed to acquire ptt\n");
+ continue;
+ }
+
+ memset(&mstats, 0, sizeof(mstats));
+ qed_memcpy_to(p_hwfn, p_ptt,
+ p_hwfn->storm_stats.mstats.address,
+ &mstats,
+ p_hwfn->storm_stats.mstats.len);
+
+ memset(&ustats, 0, sizeof(ustats));
+ qed_memcpy_to(p_hwfn, p_ptt,
+ p_hwfn->storm_stats.ustats.address,
+ &ustats,
+ p_hwfn->storm_stats.ustats.len);
+
+ memset(&pstats, 0, sizeof(pstats));
+ qed_memcpy_to(p_hwfn, p_ptt,
+ p_hwfn->storm_stats.pstats.address,
+ &pstats,
+ p_hwfn->storm_stats.pstats.len);
+
+ qed_ptt_release(p_hwfn, p_ptt);
+ }
+
+ /* PORT statistics are not necessarily reset, so we need to
+ * read and create a baseline for future statistics.
+ */
+ if (!cdev->reset_stats)
+ DP_INFO(cdev, "Reset stats not allocated\n");
+ else
+ __qed_get_vport_stats(cdev, cdev->reset_stats);
+}
+
+int qed_fw_l2_queue(struct qed_hwfn *p_hwfn,
+ u16 src_id, u16 *dst_id)
+{
+ if (src_id >= RESC_NUM(p_hwfn, QED_L2_QUEUE)) {
+ u16 min, max;
+
+ min = (u16)RESC_START(p_hwfn, QED_L2_QUEUE);
+ max = min + RESC_NUM(p_hwfn, QED_L2_QUEUE);
+ DP_NOTICE(p_hwfn,
+ "l2_queue id [%d] is not valid, available indices [%d - %d]\n",
+ src_id, min, max);
+
+ return -EINVAL;
+ }
+
+ *dst_id = RESC_START(p_hwfn, QED_L2_QUEUE) + src_id;
+
+ return 0;
+}
+
+int qed_fw_vport(struct qed_hwfn *p_hwfn,
+ u8 src_id, u8 *dst_id)
+{
+ if (src_id >= RESC_NUM(p_hwfn, QED_VPORT)) {
+ u8 min, max;
+
+ min = (u8)RESC_START(p_hwfn, QED_VPORT);
+ max = min + RESC_NUM(p_hwfn, QED_VPORT);
+ DP_NOTICE(p_hwfn,
+ "vport id [%d] is not valid, available indices [%d - %d]\n",
+ src_id, min, max);
+
+ return -EINVAL;
+ }
+
+ *dst_id = RESC_START(p_hwfn, QED_VPORT) + src_id;
+
+ return 0;
+}
+
+int qed_fw_rss_eng(struct qed_hwfn *p_hwfn,
+ u8 src_id, u8 *dst_id)
+{
+ if (src_id >= RESC_NUM(p_hwfn, QED_RSS_ENG)) {
+ u8 min, max;
+
+ min = (u8)RESC_START(p_hwfn, QED_RSS_ENG);
+ max = min + RESC_NUM(p_hwfn, QED_RSS_ENG);
+ DP_NOTICE(p_hwfn,
+ "rss_eng id [%d] is not valid, available indices [%d - %d]\n",
+ src_id, min, max);
+
+ return -EINVAL;
+ }
+
+ *dst_id = RESC_START(p_hwfn, QED_RSS_ENG) + src_id;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
new file mode 100644
index 000000000000..e29a3ba6c8b0
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
@@ -0,0 +1,283 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_DEV_API_H
+#define _QED_DEV_API_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/qed/qed_chain.h>
+#include <linux/qed/qed_if.h>
+#include "qed_int.h"
+
+/**
+ * @brief qed_init_dp - initialize the debug level
+ *
+ * @param cdev
+ * @param dp_module
+ * @param dp_level
+ */
+void qed_init_dp(struct qed_dev *cdev,
+ u32 dp_module,
+ u8 dp_level);
+
+/**
+ * @brief qed_init_struct - initialize the device structure to
+ * its defaults
+ *
+ * @param cdev
+ */
+void qed_init_struct(struct qed_dev *cdev);
+
+/**
+ * @brief qed_resc_free -
+ *
+ * @param cdev
+ */
+void qed_resc_free(struct qed_dev *cdev);
+
+/**
+ * @brief qed_resc_alloc -
+ *
+ * @param cdev
+ *
+ * @return int
+ */
+int qed_resc_alloc(struct qed_dev *cdev);
+
+/**
+ * @brief qed_resc_setup -
+ *
+ * @param cdev
+ */
+void qed_resc_setup(struct qed_dev *cdev);
+
+/**
+ * @brief qed_hw_init -
+ *
+ * @param cdev
+ * @param b_hw_start
+ * @param int_mode - interrupt mode [msix, inta, etc.] to use.
+ * @param allow_npar_tx_switch - npar tx switching to be used
+ * for vports configured for tx-switching.
+ * @param bin_fw_data - binary fw data pointer in binary fw file.
+ * Pass NULL if not using binary fw file.
+ *
+ * @return int
+ */
+int qed_hw_init(struct qed_dev *cdev,
+ bool b_hw_start,
+ enum qed_int_mode int_mode,
+ bool allow_npar_tx_switch,
+ const u8 *bin_fw_data);
+
+/**
+ * @brief qed_hw_stop -
+ *
+ * @param cdev
+ *
+ * @return int
+ */
+int qed_hw_stop(struct qed_dev *cdev);
+
+/**
+ * @brief qed_hw_stop_fastpath -should be called incase
+ * slowpath is still required for the device,
+ * but fastpath is not.
+ *
+ * @param cdev
+ *
+ */
+void qed_hw_stop_fastpath(struct qed_dev *cdev);
+
+/**
+ * @brief qed_hw_start_fastpath -restart fastpath traffic,
+ * only if hw_stop_fastpath was called
+ *
+ * @param cdev
+ *
+ */
+void qed_hw_start_fastpath(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_hw_reset -
+ *
+ * @param cdev
+ *
+ * @return int
+ */
+int qed_hw_reset(struct qed_dev *cdev);
+
+/**
+ * @brief qed_hw_prepare -
+ *
+ * @param cdev
+ * @param personality - personality to initialize
+ *
+ * @return int
+ */
+int qed_hw_prepare(struct qed_dev *cdev,
+ int personality);
+
+/**
+ * @brief qed_hw_remove -
+ *
+ * @param cdev
+ */
+void qed_hw_remove(struct qed_dev *cdev);
+
+/**
+ * @brief qed_ptt_acquire - Allocate a PTT window
+ *
+ * Should be called at the entry point to the driver (at the beginning of an
+ * exported function)
+ *
+ * @param p_hwfn
+ *
+ * @return struct qed_ptt
+ */
+struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_ptt_release - Release PTT Window
+ *
+ * Should be called at the end of a flow - at the end of the function that
+ * acquired the PTT.
+ *
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+void qed_ptt_release(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+void qed_get_vport_stats(struct qed_dev *cdev,
+ struct qed_eth_stats *stats);
+void qed_reset_vport_stats(struct qed_dev *cdev);
+
+enum qed_dmae_address_type_t {
+ QED_DMAE_ADDRESS_HOST_VIRT,
+ QED_DMAE_ADDRESS_HOST_PHYS,
+ QED_DMAE_ADDRESS_GRC
+};
+
+/* value of flags If QED_DMAE_FLAG_RW_REPL_SRC flag is set and the
+ * source is a block of length DMAE_MAX_RW_SIZE and the
+ * destination is larger, the source block will be duplicated as
+ * many times as required to fill the destination block. This is
+ * used mostly to write a zeroed buffer to destination address
+ * using DMA
+ */
+#define QED_DMAE_FLAG_RW_REPL_SRC 0x00000001
+#define QED_DMAE_FLAG_COMPLETION_DST 0x00000008
+
+struct qed_dmae_params {
+ u32 flags; /* consists of QED_DMAE_FLAG_* values */
+};
+
+/**
+ * @brief qed_dmae_host2grc - copy data from source addr to
+ * dmae registers using the given ptt
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param source_addr
+ * @param grc_addr (dmae_data_offset)
+ * @param size_in_dwords
+ * @param flags (one of the flags defined above)
+ */
+int
+qed_dmae_host2grc(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u64 source_addr,
+ u32 grc_addr,
+ u32 size_in_dwords,
+ u32 flags);
+
+/**
+ * @brief qed_chain_alloc - Allocate and initialize a chain
+ *
+ * @param p_hwfn
+ * @param intended_use
+ * @param mode
+ * @param num_elems
+ * @param elem_size
+ * @param p_chain
+ *
+ * @return int
+ */
+int
+qed_chain_alloc(struct qed_dev *cdev,
+ enum qed_chain_use_mode intended_use,
+ enum qed_chain_mode mode,
+ u16 num_elems,
+ size_t elem_size,
+ struct qed_chain *p_chain);
+
+/**
+ * @brief qed_chain_free - Free chain DMA memory
+ *
+ * @param p_hwfn
+ * @param p_chain
+ */
+void qed_chain_free(struct qed_dev *cdev,
+ struct qed_chain *p_chain);
+
+/**
+ * @@brief qed_fw_l2_queue - Get absolute L2 queue ID
+ *
+ * @param p_hwfn
+ * @param src_id - relative to p_hwfn
+ * @param dst_id - absolute per engine
+ *
+ * @return int
+ */
+int qed_fw_l2_queue(struct qed_hwfn *p_hwfn,
+ u16 src_id,
+ u16 *dst_id);
+
+/**
+ * @@brief qed_fw_vport - Get absolute vport ID
+ *
+ * @param p_hwfn
+ * @param src_id - relative to p_hwfn
+ * @param dst_id - absolute per engine
+ *
+ * @return int
+ */
+int qed_fw_vport(struct qed_hwfn *p_hwfn,
+ u8 src_id,
+ u8 *dst_id);
+
+/**
+ * @@brief qed_fw_rss_eng - Get absolute RSS engine ID
+ *
+ * @param p_hwfn
+ * @param src_id - relative to p_hwfn
+ * @param dst_id - absolute per engine
+ *
+ * @return int
+ */
+int qed_fw_rss_eng(struct qed_hwfn *p_hwfn,
+ u8 src_id,
+ u8 *dst_id);
+
+/**
+ * *@brief Cleanup of previous driver remains prior to load
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param id - For PF, engine-relative. For VF, PF-relative.
+ *
+ * @return int
+ */
+int qed_final_cleanup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u16 id);
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
new file mode 100644
index 000000000000..b2f8e854dfd1
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -0,0 +1,5291 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_HSI_H
+#define _QED_HSI_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/qed/common_hsi.h>
+#include <linux/qed/eth_common.h>
+
+struct qed_hwfn;
+struct qed_ptt;
+/********************************/
+/* Add include to common target */
+/********************************/
+
+/* opcodes for the event ring */
+enum common_event_opcode {
+ COMMON_EVENT_PF_START,
+ COMMON_EVENT_PF_STOP,
+ COMMON_EVENT_RESERVED,
+ COMMON_EVENT_RESERVED2,
+ COMMON_EVENT_RESERVED3,
+ COMMON_EVENT_RESERVED4,
+ COMMON_EVENT_RESERVED5,
+ MAX_COMMON_EVENT_OPCODE
+};
+
+/* Common Ramrod Command IDs */
+enum common_ramrod_cmd_id {
+ COMMON_RAMROD_UNUSED,
+ COMMON_RAMROD_PF_START /* PF Function Start Ramrod */,
+ COMMON_RAMROD_PF_STOP /* PF Function Stop Ramrod */,
+ COMMON_RAMROD_RESERVED,
+ COMMON_RAMROD_RESERVED2,
+ COMMON_RAMROD_RESERVED3,
+ MAX_COMMON_RAMROD_CMD_ID
+};
+
+/* The core storm context for the Ystorm */
+struct ystorm_core_conn_st_ctx {
+ __le32 reserved[4];
+};
+
+/* The core storm context for the Pstorm */
+struct pstorm_core_conn_st_ctx {
+ __le32 reserved[4];
+};
+
+/* Core Slowpath Connection storm context of Xstorm */
+struct xstorm_core_conn_st_ctx {
+ __le32 spq_base_lo /* SPQ Ring Base Address low dword */;
+ __le32 spq_base_hi /* SPQ Ring Base Address high dword */;
+ struct regpair consolid_base_addr;
+ __le16 spq_cons /* SPQ Ring Consumer */;
+ __le16 consolid_cons /* Consolidation Ring Consumer */;
+ __le32 reserved0[55] /* Pad to 15 cycles */;
+};
+
+struct xstorm_core_conn_ag_ctx {
+ u8 reserved0 /* cdu_validation */;
+ u8 core_state /* state */;
+ u8 flags0;
+#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED1_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED1_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED2_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED2_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM3_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM3_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED3_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED3_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED4_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED4_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED5_MASK 0x1 /* bit6 */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED5_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED6_MASK 0x1 /* bit7 */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED6_SHIFT 7
+ u8 flags1;
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED7_MASK 0x1 /* bit8 */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED7_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED8_MASK 0x1 /* bit9 */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED8_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED9_MASK 0x1 /* bit10 */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED9_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_BIT11_MASK 0x1 /* bit11 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT11_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_BIT12_MASK 0x1 /* bit12 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT12_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_BIT13_MASK 0x1 /* bit13 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT13_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_TX_RULE_ACTIVE_MASK 0x1 /* bit14 */
+#define XSTORM_CORE_CONN_AG_CTX_TX_RULE_ACTIVE_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE_MASK 0x1 /* bit15 */
+#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE_SHIFT 7
+ u8 flags2;
+#define XSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */
+#define XSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */
+#define XSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */
+#define XSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF3_MASK 0x3
+#define XSTORM_CORE_CONN_AG_CTX_CF3_SHIFT 6
+ u8 flags3;
+#define XSTORM_CORE_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */
+#define XSTORM_CORE_CONN_AG_CTX_CF4_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */
+#define XSTORM_CORE_CONN_AG_CTX_CF5_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */
+#define XSTORM_CORE_CONN_AG_CTX_CF6_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */
+#define XSTORM_CORE_CONN_AG_CTX_CF7_SHIFT 6
+ u8 flags4;
+#define XSTORM_CORE_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */
+#define XSTORM_CORE_CONN_AG_CTX_CF8_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */
+#define XSTORM_CORE_CONN_AG_CTX_CF9_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */
+#define XSTORM_CORE_CONN_AG_CTX_CF10_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF11_MASK 0x3 /* cf11 */
+#define XSTORM_CORE_CONN_AG_CTX_CF11_SHIFT 6
+ u8 flags5;
+#define XSTORM_CORE_CONN_AG_CTX_CF12_MASK 0x3 /* cf12 */
+#define XSTORM_CORE_CONN_AG_CTX_CF12_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF13_MASK 0x3 /* cf13 */
+#define XSTORM_CORE_CONN_AG_CTX_CF13_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_CF14_MASK 0x3 /* cf14 */
+#define XSTORM_CORE_CONN_AG_CTX_CF14_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF15_MASK 0x3 /* cf15 */
+#define XSTORM_CORE_CONN_AG_CTX_CF15_SHIFT 6
+ u8 flags6;
+#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_MASK 0x3 /* cf16 */
+#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF17_MASK 0x3
+#define XSTORM_CORE_CONN_AG_CTX_CF17_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_MASK 0x3 /* cf18 */
+#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_MASK 0x3 /* cf19 */
+#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_SHIFT 6
+ u8 flags7;
+#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_MASK 0x3 /* cf20 */
+#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED10_MASK 0x3 /* cf21 */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED10_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_MASK 0x3 /* cf22 */
+#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define XSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define XSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 7
+ u8 flags8;
+#define XSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define XSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */
+#define XSTORM_CORE_CONN_AG_CTX_CF3EN_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */
+#define XSTORM_CORE_CONN_AG_CTX_CF4EN_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */
+#define XSTORM_CORE_CONN_AG_CTX_CF5EN_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */
+#define XSTORM_CORE_CONN_AG_CTX_CF6EN_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */
+#define XSTORM_CORE_CONN_AG_CTX_CF7EN_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */
+#define XSTORM_CORE_CONN_AG_CTX_CF8EN_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */
+#define XSTORM_CORE_CONN_AG_CTX_CF9EN_SHIFT 7
+ u8 flags9;
+#define XSTORM_CORE_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */
+#define XSTORM_CORE_CONN_AG_CTX_CF10EN_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_CF11EN_MASK 0x1 /* cf11en */
+#define XSTORM_CORE_CONN_AG_CTX_CF11EN_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_CF12EN_MASK 0x1 /* cf12en */
+#define XSTORM_CORE_CONN_AG_CTX_CF12EN_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_CF13EN_MASK 0x1 /* cf13en */
+#define XSTORM_CORE_CONN_AG_CTX_CF13EN_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_CF14EN_MASK 0x1 /* cf14en */
+#define XSTORM_CORE_CONN_AG_CTX_CF14EN_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF15EN_MASK 0x1 /* cf15en */
+#define XSTORM_CORE_CONN_AG_CTX_CF15EN_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN_MASK 0x1 /* cf16en */
+#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_CF17EN_MASK 0x1
+#define XSTORM_CORE_CONN_AG_CTX_CF17EN_SHIFT 7
+ u8 flags10;
+#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN_MASK 0x1 /* cf18en */
+#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_EN_MASK 0x1 /* cf19en */
+#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_EN_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_EN_MASK 0x1 /* cf20en */
+#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_EN_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED11_MASK 0x1 /* cf21en */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED11_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_EN_MASK 0x1 /* cf22en */
+#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_EN_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_CF23EN_MASK 0x1 /* cf23en */
+#define XSTORM_CORE_CONN_AG_CTX_CF23EN_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED12_MASK 0x1 /* rule0en */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED12_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED13_MASK 0x1 /* rule1en */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED13_SHIFT 7
+ u8 flags11;
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED14_MASK 0x1 /* rule2en */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED14_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED15_MASK 0x1 /* rule3en */
+#define XSTORM_CORE_CONN_AG_CTX_RESERVED15_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_TX_DEC_RULE_EN_MASK 0x1 /* rule4en */
+#define XSTORM_CORE_CONN_AG_CTX_TX_DEC_RULE_EN_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE5EN_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE6EN_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE7EN_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED1_MASK 0x1 /* rule8en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED1_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_RULE9EN_MASK 0x1 /* rule9en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE9EN_SHIFT 7
+ u8 flags12;
+#define XSTORM_CORE_CONN_AG_CTX_RULE10EN_MASK 0x1 /* rule10en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE10EN_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_RULE11EN_MASK 0x1 /* rule11en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE11EN_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED2_MASK 0x1 /* rule12en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED2_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED3_MASK 0x1 /* rule13en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED3_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_RULE14EN_MASK 0x1 /* rule14en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE14EN_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_RULE15EN_MASK 0x1 /* rule15en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE15EN_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_RULE16EN_MASK 0x1 /* rule16en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE16EN_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_RULE17EN_MASK 0x1 /* rule17en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE17EN_SHIFT 7
+ u8 flags13;
+#define XSTORM_CORE_CONN_AG_CTX_RULE18EN_MASK 0x1 /* rule18en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE18EN_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_RULE19EN_MASK 0x1 /* rule19en */
+#define XSTORM_CORE_CONN_AG_CTX_RULE19EN_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED4_MASK 0x1 /* rule20en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED4_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED5_MASK 0x1 /* rule21en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED5_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED6_MASK 0x1 /* rule22en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED6_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED7_MASK 0x1 /* rule23en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED7_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED8_MASK 0x1 /* rule24en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED8_SHIFT 6
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED9_MASK 0x1 /* rule25en */
+#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED9_SHIFT 7
+ u8 flags14;
+#define XSTORM_CORE_CONN_AG_CTX_BIT16_MASK 0x1 /* bit16 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT16_SHIFT 0
+#define XSTORM_CORE_CONN_AG_CTX_BIT17_MASK 0x1 /* bit17 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT17_SHIFT 1
+#define XSTORM_CORE_CONN_AG_CTX_BIT18_MASK 0x1 /* bit18 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT18_SHIFT 2
+#define XSTORM_CORE_CONN_AG_CTX_BIT19_MASK 0x1 /* bit19 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT19_SHIFT 3
+#define XSTORM_CORE_CONN_AG_CTX_BIT20_MASK 0x1 /* bit20 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT20_SHIFT 4
+#define XSTORM_CORE_CONN_AG_CTX_BIT21_MASK 0x1 /* bit21 */
+#define XSTORM_CORE_CONN_AG_CTX_BIT21_SHIFT 5
+#define XSTORM_CORE_CONN_AG_CTX_CF23_MASK 0x3 /* cf23 */
+#define XSTORM_CORE_CONN_AG_CTX_CF23_SHIFT 6
+ u8 byte2 /* byte2 */;
+ __le16 physical_q0 /* physical_q0 */;
+ __le16 consolid_prod /* physical_q1 */;
+ __le16 reserved16 /* physical_q2 */;
+ __le16 tx_bd_cons /* word3 */;
+ __le16 tx_bd_or_spq_prod /* word4 */;
+ __le16 word5 /* word5 */;
+ __le16 conn_dpi /* conn_dpi */;
+ u8 byte3 /* byte3 */;
+ u8 byte4 /* byte4 */;
+ u8 byte5 /* byte5 */;
+ u8 byte6 /* byte6 */;
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+ __le32 reg4 /* reg4 */;
+ __le32 reg5 /* cf_array0 */;
+ __le32 reg6 /* cf_array1 */;
+ __le16 word7 /* word7 */;
+ __le16 word8 /* word8 */;
+ __le16 word9 /* word9 */;
+ __le16 word10 /* word10 */;
+ __le32 reg7 /* reg7 */;
+ __le32 reg8 /* reg8 */;
+ __le32 reg9 /* reg9 */;
+ u8 byte7 /* byte7 */;
+ u8 byte8 /* byte8 */;
+ u8 byte9 /* byte9 */;
+ u8 byte10 /* byte10 */;
+ u8 byte11 /* byte11 */;
+ u8 byte12 /* byte12 */;
+ u8 byte13 /* byte13 */;
+ u8 byte14 /* byte14 */;
+ u8 byte15 /* byte15 */;
+ u8 byte16 /* byte16 */;
+ __le16 word11 /* word11 */;
+ __le32 reg10 /* reg10 */;
+ __le32 reg11 /* reg11 */;
+ __le32 reg12 /* reg12 */;
+ __le32 reg13 /* reg13 */;
+ __le32 reg14 /* reg14 */;
+ __le32 reg15 /* reg15 */;
+ __le32 reg16 /* reg16 */;
+ __le32 reg17 /* reg17 */;
+ __le32 reg18 /* reg18 */;
+ __le32 reg19 /* reg19 */;
+ __le16 word12 /* word12 */;
+ __le16 word13 /* word13 */;
+ __le16 word14 /* word14 */;
+ __le16 word15 /* word15 */;
+};
+
+/* The core storm context for the Mstorm */
+struct mstorm_core_conn_st_ctx {
+ __le32 reserved[24];
+};
+
+/* The core storm context for the Ustorm */
+struct ustorm_core_conn_st_ctx {
+ __le32 reserved[4];
+};
+
+/* core connection context */
+struct core_conn_context {
+ struct ystorm_core_conn_st_ctx ystorm_st_context;
+ struct regpair ystorm_st_padding[2] /* padding */;
+ struct pstorm_core_conn_st_ctx pstorm_st_context;
+ struct regpair pstorm_st_padding[2];
+ struct xstorm_core_conn_st_ctx xstorm_st_context;
+ struct xstorm_core_conn_ag_ctx xstorm_ag_context;
+ struct mstorm_core_conn_st_ctx mstorm_st_context;
+ struct regpair mstorm_st_padding[2];
+ struct ustorm_core_conn_st_ctx ustorm_st_context;
+ struct regpair ustorm_st_padding[2] /* padding */;
+};
+
+struct eth_mstorm_per_queue_stat {
+ struct regpair ttl0_discard;
+ struct regpair packet_too_big_discard;
+ struct regpair no_buff_discard;
+ struct regpair not_active_discard;
+ struct regpair tpa_coalesced_pkts;
+ struct regpair tpa_coalesced_events;
+ struct regpair tpa_aborts_num;
+ struct regpair tpa_coalesced_bytes;
+};
+
+struct eth_pstorm_per_queue_stat {
+ struct regpair sent_ucast_bytes;
+ struct regpair sent_mcast_bytes;
+ struct regpair sent_bcast_bytes;
+ struct regpair sent_ucast_pkts;
+ struct regpair sent_mcast_pkts;
+ struct regpair sent_bcast_pkts;
+ struct regpair error_drop_pkts;
+};
+
+struct eth_ustorm_per_queue_stat {
+ struct regpair rcv_ucast_bytes;
+ struct regpair rcv_mcast_bytes;
+ struct regpair rcv_bcast_bytes;
+ struct regpair rcv_ucast_pkts;
+ struct regpair rcv_mcast_pkts;
+ struct regpair rcv_bcast_pkts;
+};
+
+/* Event Ring Next Page Address */
+struct event_ring_next_addr {
+ struct regpair addr /* Next Page Address */;
+ __le32 reserved[2] /* Reserved */;
+};
+
+union event_ring_element {
+ struct event_ring_entry entry /* Event Ring Entry */;
+ struct event_ring_next_addr next_addr;
+};
+
+enum personality_type {
+ PERSONALITY_RESERVED,
+ PERSONALITY_RESERVED2,
+ PERSONALITY_RDMA_AND_ETH /* Roce or Iwarp */,
+ PERSONALITY_RESERVED3,
+ PERSONALITY_ETH /* Ethernet */,
+ PERSONALITY_RESERVED4,
+ MAX_PERSONALITY_TYPE
+};
+
+struct pf_start_tunnel_config {
+ u8 set_vxlan_udp_port_flg;
+ u8 set_geneve_udp_port_flg;
+ u8 tx_enable_vxlan /* If set, enable VXLAN tunnel in TX path. */;
+ u8 tx_enable_l2geneve;
+ u8 tx_enable_ipgeneve;
+ u8 tx_enable_l2gre /* If set, enable l2 GRE tunnel in TX path. */;
+ u8 tx_enable_ipgre /* If set, enable IP GRE tunnel in TX path. */;
+ u8 tunnel_clss_vxlan /* Classification scheme for VXLAN tunnel. */;
+ u8 tunnel_clss_l2geneve;
+ u8 tunnel_clss_ipgeneve;
+ u8 tunnel_clss_l2gre;
+ u8 tunnel_clss_ipgre;
+ __le16 vxlan_udp_port /* VXLAN tunnel UDP destination port. */;
+ __le16 geneve_udp_port /* GENEVE tunnel UDP destination port. */;
+};
+
+/* Ramrod data for PF start ramrod */
+struct pf_start_ramrod_data {
+ struct regpair event_ring_pbl_addr;
+ struct regpair consolid_q_pbl_addr;
+ struct pf_start_tunnel_config tunnel_config;
+ __le16 event_ring_sb_id;
+ u8 base_vf_id;
+ u8 num_vfs;
+ u8 event_ring_num_pages;
+ u8 event_ring_sb_index;
+ u8 path_id;
+ u8 warning_as_error;
+ u8 dont_log_ramrods;
+ u8 personality;
+ __le16 log_type_mask;
+ u8 mf_mode /* Multi function mode */;
+ u8 integ_phase /* Integration phase */;
+ u8 allow_npar_tx_switching;
+ u8 inner_to_outer_pri_map[8];
+ u8 pri_map_valid;
+ u32 outer_tag;
+ u8 reserved0[4];
+};
+
+enum ports_mode {
+ ENGX2_PORTX1 /* 2 engines x 1 port */,
+ ENGX2_PORTX2 /* 2 engines x 2 ports */,
+ ENGX1_PORTX1 /* 1 engine x 1 port */,
+ ENGX1_PORTX2 /* 1 engine x 2 ports */,
+ ENGX1_PORTX4 /* 1 engine x 4 ports */,
+ MAX_PORTS_MODE
+};
+
+/* Ramrod Header of SPQE */
+struct ramrod_header {
+ __le32 cid /* Slowpath Connection CID */;
+ u8 cmd_id /* Ramrod Cmd (Per Protocol Type) */;
+ u8 protocol_id /* Ramrod Protocol ID */;
+ __le16 echo /* Ramrod echo */;
+};
+
+/* Slowpath Element (SPQE) */
+struct slow_path_element {
+ struct ramrod_header hdr /* Ramrod Header */;
+ struct regpair data_ptr;
+};
+
+struct tstorm_per_port_stat {
+ struct regpair trunc_error_discard;
+ struct regpair mac_error_discard;
+ struct regpair mftag_filter_discard;
+ struct regpair eth_mac_filter_discard;
+ struct regpair ll2_mac_filter_discard;
+ struct regpair ll2_conn_disabled_discard;
+ struct regpair iscsi_irregular_pkt;
+ struct regpair fcoe_irregular_pkt;
+ struct regpair roce_irregular_pkt;
+ struct regpair eth_irregular_pkt;
+ struct regpair toe_irregular_pkt;
+ struct regpair preroce_irregular_pkt;
+};
+
+struct atten_status_block {
+ __le32 atten_bits;
+ __le32 atten_ack;
+ __le16 reserved0;
+ __le16 sb_index /* status block running index */;
+ __le32 reserved1;
+};
+
+enum block_addr {
+ GRCBASE_GRC = 0x50000,
+ GRCBASE_MISCS = 0x9000,
+ GRCBASE_MISC = 0x8000,
+ GRCBASE_DBU = 0xa000,
+ GRCBASE_PGLUE_B = 0x2a8000,
+ GRCBASE_CNIG = 0x218000,
+ GRCBASE_CPMU = 0x30000,
+ GRCBASE_NCSI = 0x40000,
+ GRCBASE_OPTE = 0x53000,
+ GRCBASE_BMB = 0x540000,
+ GRCBASE_PCIE = 0x54000,
+ GRCBASE_MCP = 0xe00000,
+ GRCBASE_MCP2 = 0x52000,
+ GRCBASE_PSWHST = 0x2a0000,
+ GRCBASE_PSWHST2 = 0x29e000,
+ GRCBASE_PSWRD = 0x29c000,
+ GRCBASE_PSWRD2 = 0x29d000,
+ GRCBASE_PSWWR = 0x29a000,
+ GRCBASE_PSWWR2 = 0x29b000,
+ GRCBASE_PSWRQ = 0x280000,
+ GRCBASE_PSWRQ2 = 0x240000,
+ GRCBASE_PGLCS = 0x0,
+ GRCBASE_PTU = 0x560000,
+ GRCBASE_DMAE = 0xc000,
+ GRCBASE_TCM = 0x1180000,
+ GRCBASE_MCM = 0x1200000,
+ GRCBASE_UCM = 0x1280000,
+ GRCBASE_XCM = 0x1000000,
+ GRCBASE_YCM = 0x1080000,
+ GRCBASE_PCM = 0x1100000,
+ GRCBASE_QM = 0x2f0000,
+ GRCBASE_TM = 0x2c0000,
+ GRCBASE_DORQ = 0x100000,
+ GRCBASE_BRB = 0x340000,
+ GRCBASE_SRC = 0x238000,
+ GRCBASE_PRS = 0x1f0000,
+ GRCBASE_TSDM = 0xfb0000,
+ GRCBASE_MSDM = 0xfc0000,
+ GRCBASE_USDM = 0xfd0000,
+ GRCBASE_XSDM = 0xf80000,
+ GRCBASE_YSDM = 0xf90000,
+ GRCBASE_PSDM = 0xfa0000,
+ GRCBASE_TSEM = 0x1700000,
+ GRCBASE_MSEM = 0x1800000,
+ GRCBASE_USEM = 0x1900000,
+ GRCBASE_XSEM = 0x1400000,
+ GRCBASE_YSEM = 0x1500000,
+ GRCBASE_PSEM = 0x1600000,
+ GRCBASE_RSS = 0x238800,
+ GRCBASE_TMLD = 0x4d0000,
+ GRCBASE_MULD = 0x4e0000,
+ GRCBASE_YULD = 0x4c8000,
+ GRCBASE_XYLD = 0x4c0000,
+ GRCBASE_PRM = 0x230000,
+ GRCBASE_PBF_PB1 = 0xda0000,
+ GRCBASE_PBF_PB2 = 0xda4000,
+ GRCBASE_RPB = 0x23c000,
+ GRCBASE_BTB = 0xdb0000,
+ GRCBASE_PBF = 0xd80000,
+ GRCBASE_RDIF = 0x300000,
+ GRCBASE_TDIF = 0x310000,
+ GRCBASE_CDU = 0x580000,
+ GRCBASE_CCFC = 0x2e0000,
+ GRCBASE_TCFC = 0x2d0000,
+ GRCBASE_IGU = 0x180000,
+ GRCBASE_CAU = 0x1c0000,
+ GRCBASE_UMAC = 0x51000,
+ GRCBASE_XMAC = 0x210000,
+ GRCBASE_DBG = 0x10000,
+ GRCBASE_NIG = 0x500000,
+ GRCBASE_WOL = 0x600000,
+ GRCBASE_BMBN = 0x610000,
+ GRCBASE_IPC = 0x20000,
+ GRCBASE_NWM = 0x800000,
+ GRCBASE_NWS = 0x700000,
+ GRCBASE_MS = 0x6a0000,
+ GRCBASE_PHY_PCIE = 0x618000,
+ GRCBASE_MISC_AEU = 0x8000,
+ GRCBASE_BAR0_MAP = 0x1c00000,
+ MAX_BLOCK_ADDR
+};
+
+enum block_id {
+ BLOCK_GRC,
+ BLOCK_MISCS,
+ BLOCK_MISC,
+ BLOCK_DBU,
+ BLOCK_PGLUE_B,
+ BLOCK_CNIG,
+ BLOCK_CPMU,
+ BLOCK_NCSI,
+ BLOCK_OPTE,
+ BLOCK_BMB,
+ BLOCK_PCIE,
+ BLOCK_MCP,
+ BLOCK_MCP2,
+ BLOCK_PSWHST,
+ BLOCK_PSWHST2,
+ BLOCK_PSWRD,
+ BLOCK_PSWRD2,
+ BLOCK_PSWWR,
+ BLOCK_PSWWR2,
+ BLOCK_PSWRQ,
+ BLOCK_PSWRQ2,
+ BLOCK_PGLCS,
+ BLOCK_PTU,
+ BLOCK_DMAE,
+ BLOCK_TCM,
+ BLOCK_MCM,
+ BLOCK_UCM,
+ BLOCK_XCM,
+ BLOCK_YCM,
+ BLOCK_PCM,
+ BLOCK_QM,
+ BLOCK_TM,
+ BLOCK_DORQ,
+ BLOCK_BRB,
+ BLOCK_SRC,
+ BLOCK_PRS,
+ BLOCK_TSDM,
+ BLOCK_MSDM,
+ BLOCK_USDM,
+ BLOCK_XSDM,
+ BLOCK_YSDM,
+ BLOCK_PSDM,
+ BLOCK_TSEM,
+ BLOCK_MSEM,
+ BLOCK_USEM,
+ BLOCK_XSEM,
+ BLOCK_YSEM,
+ BLOCK_PSEM,
+ BLOCK_RSS,
+ BLOCK_TMLD,
+ BLOCK_MULD,
+ BLOCK_YULD,
+ BLOCK_XYLD,
+ BLOCK_PRM,
+ BLOCK_PBF_PB1,
+ BLOCK_PBF_PB2,
+ BLOCK_RPB,
+ BLOCK_BTB,
+ BLOCK_PBF,
+ BLOCK_RDIF,
+ BLOCK_TDIF,
+ BLOCK_CDU,
+ BLOCK_CCFC,
+ BLOCK_TCFC,
+ BLOCK_IGU,
+ BLOCK_CAU,
+ BLOCK_UMAC,
+ BLOCK_XMAC,
+ BLOCK_DBG,
+ BLOCK_NIG,
+ BLOCK_WOL,
+ BLOCK_BMBN,
+ BLOCK_IPC,
+ BLOCK_NWM,
+ BLOCK_NWS,
+ BLOCK_MS,
+ BLOCK_PHY_PCIE,
+ BLOCK_MISC_AEU,
+ BLOCK_BAR0_MAP,
+ MAX_BLOCK_ID
+};
+
+enum command_type_bit {
+ IGU_COMMAND_TYPE_NOP = 0,
+ IGU_COMMAND_TYPE_SET = 1,
+ MAX_COMMAND_TYPE_BIT
+};
+
+struct dmae_cmd {
+ __le32 opcode;
+#define DMAE_CMD_SRC_MASK 0x1
+#define DMAE_CMD_SRC_SHIFT 0
+#define DMAE_CMD_DST_MASK 0x3
+#define DMAE_CMD_DST_SHIFT 1
+#define DMAE_CMD_C_DST_MASK 0x1
+#define DMAE_CMD_C_DST_SHIFT 3
+#define DMAE_CMD_CRC_RESET_MASK 0x1
+#define DMAE_CMD_CRC_RESET_SHIFT 4
+#define DMAE_CMD_SRC_ADDR_RESET_MASK 0x1
+#define DMAE_CMD_SRC_ADDR_RESET_SHIFT 5
+#define DMAE_CMD_DST_ADDR_RESET_MASK 0x1
+#define DMAE_CMD_DST_ADDR_RESET_SHIFT 6
+#define DMAE_CMD_COMP_FUNC_MASK 0x1
+#define DMAE_CMD_COMP_FUNC_SHIFT 7
+#define DMAE_CMD_COMP_WORD_EN_MASK 0x1
+#define DMAE_CMD_COMP_WORD_EN_SHIFT 8
+#define DMAE_CMD_COMP_CRC_EN_MASK 0x1
+#define DMAE_CMD_COMP_CRC_EN_SHIFT 9
+#define DMAE_CMD_COMP_CRC_OFFSET_MASK 0x7
+#define DMAE_CMD_COMP_CRC_OFFSET_SHIFT 10
+#define DMAE_CMD_RESERVED1_MASK 0x1
+#define DMAE_CMD_RESERVED1_SHIFT 13
+#define DMAE_CMD_ENDIANITY_MODE_MASK 0x3
+#define DMAE_CMD_ENDIANITY_MODE_SHIFT 14
+#define DMAE_CMD_ERR_HANDLING_MASK 0x3
+#define DMAE_CMD_ERR_HANDLING_SHIFT 16
+#define DMAE_CMD_PORT_ID_MASK 0x3
+#define DMAE_CMD_PORT_ID_SHIFT 18
+#define DMAE_CMD_SRC_PF_ID_MASK 0xF
+#define DMAE_CMD_SRC_PF_ID_SHIFT 20
+#define DMAE_CMD_DST_PF_ID_MASK 0xF
+#define DMAE_CMD_DST_PF_ID_SHIFT 24
+#define DMAE_CMD_SRC_VF_ID_VALID_MASK 0x1
+#define DMAE_CMD_SRC_VF_ID_VALID_SHIFT 28
+#define DMAE_CMD_DST_VF_ID_VALID_MASK 0x1
+#define DMAE_CMD_DST_VF_ID_VALID_SHIFT 29
+#define DMAE_CMD_RESERVED2_MASK 0x3
+#define DMAE_CMD_RESERVED2_SHIFT 30
+ __le32 src_addr_lo;
+ __le32 src_addr_hi;
+ __le32 dst_addr_lo;
+ __le32 dst_addr_hi;
+ __le16 length /* Length in DW */;
+ __le16 opcode_b;
+#define DMAE_CMD_SRC_VF_ID_MASK 0xFF /* Source VF id */
+#define DMAE_CMD_SRC_VF_ID_SHIFT 0
+#define DMAE_CMD_DST_VF_ID_MASK 0xFF /* Destination VF id */
+#define DMAE_CMD_DST_VF_ID_SHIFT 8
+ __le32 comp_addr_lo /* PCIe completion address low or grc address */;
+ __le32 comp_addr_hi;
+ __le32 comp_val /* Value to write to copmletion address */;
+ __le32 crc32 /* crc16 result */;
+ __le32 crc_32_c /* crc32_c result */;
+ __le16 crc16 /* crc16 result */;
+ __le16 crc16_c /* crc16_c result */;
+ __le16 crc10 /* crc_t10 result */;
+ __le16 reserved;
+ __le16 xsum16 /* checksum16 result */;
+ __le16 xsum8 /* checksum8 result */;
+};
+
+struct igu_cleanup {
+ __le32 sb_id_and_flags;
+#define IGU_CLEANUP_RESERVED0_MASK 0x7FFFFFF
+#define IGU_CLEANUP_RESERVED0_SHIFT 0
+#define IGU_CLEANUP_CLEANUP_SET_MASK 0x1 /* cleanup clear - 0, set - 1 */
+#define IGU_CLEANUP_CLEANUP_SET_SHIFT 27
+#define IGU_CLEANUP_CLEANUP_TYPE_MASK 0x7
+#define IGU_CLEANUP_CLEANUP_TYPE_SHIFT 28
+#define IGU_CLEANUP_COMMAND_TYPE_MASK 0x1
+#define IGU_CLEANUP_COMMAND_TYPE_SHIFT 31
+ __le32 reserved1;
+};
+
+union igu_command {
+ struct igu_prod_cons_update prod_cons_update;
+ struct igu_cleanup cleanup;
+};
+
+struct igu_command_reg_ctrl {
+ __le16 opaque_fid;
+ __le16 igu_command_reg_ctrl_fields;
+#define IGU_COMMAND_REG_CTRL_PXP_BAR_ADDR_MASK 0xFFF
+#define IGU_COMMAND_REG_CTRL_PXP_BAR_ADDR_SHIFT 0
+#define IGU_COMMAND_REG_CTRL_RESERVED_MASK 0x7
+#define IGU_COMMAND_REG_CTRL_RESERVED_SHIFT 12
+#define IGU_COMMAND_REG_CTRL_COMMAND_TYPE_MASK 0x1
+#define IGU_COMMAND_REG_CTRL_COMMAND_TYPE_SHIFT 15
+};
+
+struct igu_mapping_line {
+ __le32 igu_mapping_line_fields;
+#define IGU_MAPPING_LINE_VALID_MASK 0x1
+#define IGU_MAPPING_LINE_VALID_SHIFT 0
+#define IGU_MAPPING_LINE_VECTOR_NUMBER_MASK 0xFF
+#define IGU_MAPPING_LINE_VECTOR_NUMBER_SHIFT 1
+#define IGU_MAPPING_LINE_FUNCTION_NUMBER_MASK 0xFF
+#define IGU_MAPPING_LINE_FUNCTION_NUMBER_SHIFT 9
+#define IGU_MAPPING_LINE_PF_VALID_MASK 0x1 /* PF-1, VF-0 */
+#define IGU_MAPPING_LINE_PF_VALID_SHIFT 17
+#define IGU_MAPPING_LINE_IPS_GROUP_MASK 0x3F
+#define IGU_MAPPING_LINE_IPS_GROUP_SHIFT 18
+#define IGU_MAPPING_LINE_RESERVED_MASK 0xFF
+#define IGU_MAPPING_LINE_RESERVED_SHIFT 24
+};
+
+struct igu_msix_vector {
+ struct regpair address;
+ __le32 data;
+ __le32 msix_vector_fields;
+#define IGU_MSIX_VECTOR_MASK_BIT_MASK 0x1
+#define IGU_MSIX_VECTOR_MASK_BIT_SHIFT 0
+#define IGU_MSIX_VECTOR_RESERVED0_MASK 0x7FFF
+#define IGU_MSIX_VECTOR_RESERVED0_SHIFT 1
+#define IGU_MSIX_VECTOR_STEERING_TAG_MASK 0xFF
+#define IGU_MSIX_VECTOR_STEERING_TAG_SHIFT 16
+#define IGU_MSIX_VECTOR_RESERVED1_MASK 0xFF
+#define IGU_MSIX_VECTOR_RESERVED1_SHIFT 24
+};
+
+enum init_modes {
+ MODE_BB_A0,
+ MODE_RESERVED,
+ MODE_RESERVED2,
+ MODE_ASIC,
+ MODE_RESERVED3,
+ MODE_RESERVED4,
+ MODE_RESERVED5,
+ MODE_SF,
+ MODE_MF_SD,
+ MODE_MF_SI,
+ MODE_PORTS_PER_ENG_1,
+ MODE_PORTS_PER_ENG_2,
+ MODE_PORTS_PER_ENG_4,
+ MODE_40G,
+ MODE_100G,
+ MODE_EAGLE_ENG1_WORKAROUND,
+ MAX_INIT_MODES
+};
+
+enum init_phases {
+ PHASE_ENGINE,
+ PHASE_PORT,
+ PHASE_PF,
+ PHASE_RESERVED,
+ PHASE_QM_PF,
+ MAX_INIT_PHASES
+};
+
+struct mstorm_core_conn_ag_ctx {
+ u8 byte0 /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define MSTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */
+#define MSTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0
+#define MSTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */
+#define MSTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1
+#define MSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* cf0 */
+#define MSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 2
+#define MSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* cf1 */
+#define MSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 4
+#define MSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* cf2 */
+#define MSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 6
+ u8 flags1;
+#define MSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define MSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 0
+#define MSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define MSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 1
+#define MSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define MSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 2
+#define MSTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define MSTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 3
+#define MSTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define MSTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 4
+#define MSTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define MSTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 5
+#define MSTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define MSTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 6
+#define MSTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define MSTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 7
+ __le16 word0 /* word0 */;
+ __le16 word1 /* word1 */;
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+};
+
+/* per encapsulation type enabling flags */
+struct prs_reg_encapsulation_type_en {
+ u8 flags;
+#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_MASK 0x1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_SHIFT 0
+#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_MASK 0x1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT 1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_MASK 0x1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT 2
+#define PRS_REG_ENCAPSULATION_TYPE_EN_T_TAG_ENABLE_MASK 0x1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_T_TAG_ENABLE_SHIFT 3
+#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_MASK 0x1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_SHIFT 4
+#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_MASK 0x1
+#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT 5
+#define PRS_REG_ENCAPSULATION_TYPE_EN_RESERVED_MASK 0x3
+#define PRS_REG_ENCAPSULATION_TYPE_EN_RESERVED_SHIFT 6
+};
+
+enum pxp_tph_st_hint {
+ TPH_ST_HINT_BIDIR /* Read/Write access by Host and Device */,
+ TPH_ST_HINT_REQUESTER /* Read/Write access by Device */,
+ TPH_ST_HINT_TARGET,
+ TPH_ST_HINT_TARGET_PRIO,
+ MAX_PXP_TPH_ST_HINT
+};
+
+/* QM hardware structure of enable bypass credit mask */
+struct qm_rf_bypass_mask {
+ u8 flags;
+#define QM_RF_BYPASS_MASK_LINEVOQ_MASK 0x1
+#define QM_RF_BYPASS_MASK_LINEVOQ_SHIFT 0
+#define QM_RF_BYPASS_MASK_RESERVED0_MASK 0x1
+#define QM_RF_BYPASS_MASK_RESERVED0_SHIFT 1
+#define QM_RF_BYPASS_MASK_PFWFQ_MASK 0x1
+#define QM_RF_BYPASS_MASK_PFWFQ_SHIFT 2
+#define QM_RF_BYPASS_MASK_VPWFQ_MASK 0x1
+#define QM_RF_BYPASS_MASK_VPWFQ_SHIFT 3
+#define QM_RF_BYPASS_MASK_PFRL_MASK 0x1
+#define QM_RF_BYPASS_MASK_PFRL_SHIFT 4
+#define QM_RF_BYPASS_MASK_VPQCNRL_MASK 0x1
+#define QM_RF_BYPASS_MASK_VPQCNRL_SHIFT 5
+#define QM_RF_BYPASS_MASK_FWPAUSE_MASK 0x1
+#define QM_RF_BYPASS_MASK_FWPAUSE_SHIFT 6
+#define QM_RF_BYPASS_MASK_RESERVED1_MASK 0x1
+#define QM_RF_BYPASS_MASK_RESERVED1_SHIFT 7
+};
+
+/* QM hardware structure of opportunistic credit mask */
+struct qm_rf_opportunistic_mask {
+ __le16 flags;
+#define QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT 0
+#define QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT 1
+#define QM_RF_OPPORTUNISTIC_MASK_PFWFQ_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT 2
+#define QM_RF_OPPORTUNISTIC_MASK_VPWFQ_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT 3
+#define QM_RF_OPPORTUNISTIC_MASK_PFRL_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT 4
+#define QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT 5
+#define QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT 6
+#define QM_RF_OPPORTUNISTIC_MASK_RESERVED0_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_RESERVED0_SHIFT 7
+#define QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_MASK 0x1
+#define QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT 8
+#define QM_RF_OPPORTUNISTIC_MASK_RESERVED1_MASK 0x7F
+#define QM_RF_OPPORTUNISTIC_MASK_RESERVED1_SHIFT 9
+};
+
+/* QM hardware structure of QM map memory */
+struct qm_rf_pq_map {
+ u32 reg;
+#define QM_RF_PQ_MAP_PQ_VALID_MASK 0x1 /* PQ active */
+#define QM_RF_PQ_MAP_PQ_VALID_SHIFT 0
+#define QM_RF_PQ_MAP_RL_ID_MASK 0xFF /* RL ID */
+#define QM_RF_PQ_MAP_RL_ID_SHIFT 1
+#define QM_RF_PQ_MAP_VP_PQ_ID_MASK 0x1FF
+#define QM_RF_PQ_MAP_VP_PQ_ID_SHIFT 9
+#define QM_RF_PQ_MAP_VOQ_MASK 0x1F /* VOQ */
+#define QM_RF_PQ_MAP_VOQ_SHIFT 18
+#define QM_RF_PQ_MAP_WRR_WEIGHT_GROUP_MASK 0x3 /* WRR weight */
+#define QM_RF_PQ_MAP_WRR_WEIGHT_GROUP_SHIFT 23
+#define QM_RF_PQ_MAP_RL_VALID_MASK 0x1 /* RL active */
+#define QM_RF_PQ_MAP_RL_VALID_SHIFT 25
+#define QM_RF_PQ_MAP_RESERVED_MASK 0x3F
+#define QM_RF_PQ_MAP_RESERVED_SHIFT 26
+};
+
+/* SDM operation gen command (generate aggregative interrupt) */
+struct sdm_op_gen {
+ __le32 command;
+#define SDM_OP_GEN_COMP_PARAM_MASK 0xFFFF /* completion parameters 0-15 */
+#define SDM_OP_GEN_COMP_PARAM_SHIFT 0
+#define SDM_OP_GEN_COMP_TYPE_MASK 0xF /* completion type 16-19 */
+#define SDM_OP_GEN_COMP_TYPE_SHIFT 16
+#define SDM_OP_GEN_RESERVED_MASK 0xFFF /* reserved 20-31 */
+#define SDM_OP_GEN_RESERVED_SHIFT 20
+};
+
+struct tstorm_core_conn_ag_ctx {
+ u8 byte0 /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define TSTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */
+#define TSTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0
+#define TSTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */
+#define TSTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1
+#define TSTORM_CORE_CONN_AG_CTX_BIT2_MASK 0x1 /* bit2 */
+#define TSTORM_CORE_CONN_AG_CTX_BIT2_SHIFT 2
+#define TSTORM_CORE_CONN_AG_CTX_BIT3_MASK 0x1 /* bit3 */
+#define TSTORM_CORE_CONN_AG_CTX_BIT3_SHIFT 3
+#define TSTORM_CORE_CONN_AG_CTX_BIT4_MASK 0x1 /* bit4 */
+#define TSTORM_CORE_CONN_AG_CTX_BIT4_SHIFT 4
+#define TSTORM_CORE_CONN_AG_CTX_BIT5_MASK 0x1 /* bit5 */
+#define TSTORM_CORE_CONN_AG_CTX_BIT5_SHIFT 5
+#define TSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */
+#define TSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 6
+ u8 flags1;
+#define TSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */
+#define TSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 0
+#define TSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */
+#define TSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 2
+#define TSTORM_CORE_CONN_AG_CTX_CF3_MASK 0x3 /* timer_stop_all */
+#define TSTORM_CORE_CONN_AG_CTX_CF3_SHIFT 4
+#define TSTORM_CORE_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */
+#define TSTORM_CORE_CONN_AG_CTX_CF4_SHIFT 6
+ u8 flags2;
+#define TSTORM_CORE_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */
+#define TSTORM_CORE_CONN_AG_CTX_CF5_SHIFT 0
+#define TSTORM_CORE_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */
+#define TSTORM_CORE_CONN_AG_CTX_CF6_SHIFT 2
+#define TSTORM_CORE_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */
+#define TSTORM_CORE_CONN_AG_CTX_CF7_SHIFT 4
+#define TSTORM_CORE_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */
+#define TSTORM_CORE_CONN_AG_CTX_CF8_SHIFT 6
+ u8 flags3;
+#define TSTORM_CORE_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */
+#define TSTORM_CORE_CONN_AG_CTX_CF9_SHIFT 0
+#define TSTORM_CORE_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */
+#define TSTORM_CORE_CONN_AG_CTX_CF10_SHIFT 2
+#define TSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define TSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 4
+#define TSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define TSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 5
+#define TSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define TSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 6
+#define TSTORM_CORE_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */
+#define TSTORM_CORE_CONN_AG_CTX_CF3EN_SHIFT 7
+ u8 flags4;
+#define TSTORM_CORE_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */
+#define TSTORM_CORE_CONN_AG_CTX_CF4EN_SHIFT 0
+#define TSTORM_CORE_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */
+#define TSTORM_CORE_CONN_AG_CTX_CF5EN_SHIFT 1
+#define TSTORM_CORE_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */
+#define TSTORM_CORE_CONN_AG_CTX_CF6EN_SHIFT 2
+#define TSTORM_CORE_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */
+#define TSTORM_CORE_CONN_AG_CTX_CF7EN_SHIFT 3
+#define TSTORM_CORE_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */
+#define TSTORM_CORE_CONN_AG_CTX_CF8EN_SHIFT 4
+#define TSTORM_CORE_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */
+#define TSTORM_CORE_CONN_AG_CTX_CF9EN_SHIFT 5
+#define TSTORM_CORE_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */
+#define TSTORM_CORE_CONN_AG_CTX_CF10EN_SHIFT 6
+#define TSTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 7
+ u8 flags5;
+#define TSTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 0
+#define TSTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 1
+#define TSTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 2
+#define TSTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 3
+#define TSTORM_CORE_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE5EN_SHIFT 4
+#define TSTORM_CORE_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE6EN_SHIFT 5
+#define TSTORM_CORE_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE7EN_SHIFT 6
+#define TSTORM_CORE_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */
+#define TSTORM_CORE_CONN_AG_CTX_RULE8EN_SHIFT 7
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+ __le32 reg4 /* reg4 */;
+ __le32 reg5 /* reg5 */;
+ __le32 reg6 /* reg6 */;
+ __le32 reg7 /* reg7 */;
+ __le32 reg8 /* reg8 */;
+ u8 byte2 /* byte2 */;
+ u8 byte3 /* byte3 */;
+ __le16 word0 /* word0 */;
+ u8 byte4 /* byte4 */;
+ u8 byte5 /* byte5 */;
+ __le16 word1 /* word1 */;
+ __le16 word2 /* conn_dpi */;
+ __le16 word3 /* word3 */;
+ __le32 reg9 /* reg9 */;
+ __le32 reg10 /* reg10 */;
+};
+
+struct ustorm_core_conn_ag_ctx {
+ u8 reserved /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define USTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */
+#define USTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0
+#define USTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */
+#define USTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1
+#define USTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */
+#define USTORM_CORE_CONN_AG_CTX_CF0_SHIFT 2
+#define USTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */
+#define USTORM_CORE_CONN_AG_CTX_CF1_SHIFT 4
+#define USTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */
+#define USTORM_CORE_CONN_AG_CTX_CF2_SHIFT 6
+ u8 flags1;
+#define USTORM_CORE_CONN_AG_CTX_CF3_MASK 0x3 /* timer_stop_all */
+#define USTORM_CORE_CONN_AG_CTX_CF3_SHIFT 0
+#define USTORM_CORE_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */
+#define USTORM_CORE_CONN_AG_CTX_CF4_SHIFT 2
+#define USTORM_CORE_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */
+#define USTORM_CORE_CONN_AG_CTX_CF5_SHIFT 4
+#define USTORM_CORE_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */
+#define USTORM_CORE_CONN_AG_CTX_CF6_SHIFT 6
+ u8 flags2;
+#define USTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define USTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 0
+#define USTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define USTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 1
+#define USTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define USTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 2
+#define USTORM_CORE_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */
+#define USTORM_CORE_CONN_AG_CTX_CF3EN_SHIFT 3
+#define USTORM_CORE_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */
+#define USTORM_CORE_CONN_AG_CTX_CF4EN_SHIFT 4
+#define USTORM_CORE_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */
+#define USTORM_CORE_CONN_AG_CTX_CF5EN_SHIFT 5
+#define USTORM_CORE_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */
+#define USTORM_CORE_CONN_AG_CTX_CF6EN_SHIFT 6
+#define USTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define USTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 7
+ u8 flags3;
+#define USTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define USTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 0
+#define USTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define USTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 1
+#define USTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define USTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 2
+#define USTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define USTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 3
+#define USTORM_CORE_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */
+#define USTORM_CORE_CONN_AG_CTX_RULE5EN_SHIFT 4
+#define USTORM_CORE_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */
+#define USTORM_CORE_CONN_AG_CTX_RULE6EN_SHIFT 5
+#define USTORM_CORE_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */
+#define USTORM_CORE_CONN_AG_CTX_RULE7EN_SHIFT 6
+#define USTORM_CORE_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */
+#define USTORM_CORE_CONN_AG_CTX_RULE8EN_SHIFT 7
+ u8 byte2 /* byte2 */;
+ u8 byte3 /* byte3 */;
+ __le16 word0 /* conn_dpi */;
+ __le16 word1 /* word1 */;
+ __le32 rx_producers /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+ __le16 word2 /* word2 */;
+ __le16 word3 /* word3 */;
+};
+
+struct ystorm_core_conn_ag_ctx {
+ u8 byte0 /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define YSTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */
+#define YSTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0
+#define YSTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */
+#define YSTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1
+#define YSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* cf0 */
+#define YSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 2
+#define YSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* cf1 */
+#define YSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 4
+#define YSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* cf2 */
+#define YSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 6
+ u8 flags1;
+#define YSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define YSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 0
+#define YSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define YSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 1
+#define YSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define YSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 2
+#define YSTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define YSTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 3
+#define YSTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define YSTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 4
+#define YSTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define YSTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 5
+#define YSTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define YSTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 6
+#define YSTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define YSTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 7
+ u8 byte2 /* byte2 */;
+ u8 byte3 /* byte3 */;
+ __le16 word0 /* word0 */;
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le16 word1 /* word1 */;
+ __le16 word2 /* word2 */;
+ __le16 word3 /* word3 */;
+ __le16 word4 /* word4 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+};
+
+/*********************************** Init ************************************/
+
+/* Width of GRC address in bits (addresses are specified in dwords) */
+#define GRC_ADDR_BITS 23
+#define MAX_GRC_ADDR ((1 << GRC_ADDR_BITS) - 1)
+
+/* indicates an init that should be applied to any phase ID */
+#define ANY_PHASE_ID 0xffff
+
+/* init pattern size in bytes */
+#define INIT_PATTERN_SIZE_BITS 4
+#define MAX_INIT_PATTERN_SIZE BIT(INIT_PATTERN_SIZE_BITS)
+
+/* Max size in dwords of a zipped array */
+#define MAX_ZIPPED_SIZE 8192
+
+/* Global PXP window */
+#define NUM_OF_PXP_WIN 19
+#define PXP_WIN_DWORD_SIZE_BITS 10
+#define PXP_WIN_DWORD_SIZE BIT(PXP_WIN_DWORD_SIZE_BITS)
+#define PXP_WIN_BYTE_SIZE_BITS (PXP_WIN_DWORD_SIZE_BITS + 2)
+#define PXP_WIN_BYTE_SIZE (PXP_WIN_DWORD_SIZE * 4)
+
+/********************************* GRC Dump **********************************/
+
+/* width of GRC dump register sequence length in bits */
+#define DUMP_SEQ_LEN_BITS 8
+#define DUMP_SEQ_LEN_MAX_VAL ((1 << DUMP_SEQ_LEN_BITS) - 1)
+
+/* width of GRC dump memory length in bits */
+#define DUMP_MEM_LEN_BITS 18
+#define DUMP_MEM_LEN_MAX_VAL ((1 << DUMP_MEM_LEN_BITS) - 1)
+
+/* width of register type ID in bits */
+#define REG_TYPE_ID_BITS 6
+#define REG_TYPE_ID_MAX_VAL ((1 << REG_TYPE_ID_BITS) - 1)
+
+/* width of block ID in bits */
+#define BLOCK_ID_BITS 8
+#define BLOCK_ID_MAX_VAL ((1 << BLOCK_ID_BITS) - 1)
+
+/******************************** Idle Check *********************************/
+
+/* max number of idle check predicate immediates */
+#define MAX_IDLE_CHK_PRED_IMM 3
+
+/* max number of idle check argument registers */
+#define MAX_IDLE_CHK_READ_REGS 3
+
+/* max number of idle check loops */
+#define MAX_IDLE_CHK_LOOPS 0x10000
+
+/* max idle check address increment */
+#define MAX_IDLE_CHK_INCREMENT 0x10000
+
+/* inicates an undefined idle check line index */
+#define IDLE_CHK_UNDEFINED_LINE_IDX 0xffffff
+
+/* max number of register values following the idle check header */
+#define IDLE_CHK_MAX_DUMP_REGS 2
+
+/* arguments for IDLE_CHK_MACRO_TYPE_QM_RD_WR */
+#define IDLE_CHK_QM_RD_WR_PTR 0
+#define IDLE_CHK_QM_RD_WR_BANK 1
+
+/**************************************/
+/* HSI Functions constants and macros */
+/**************************************/
+
+/* Number of VLAN priorities */
+#define NUM_OF_VLAN_PRIORITIES 8
+
+/* the MCP Trace meta data signautre is duplicated in the perl script that
+ * generats the NVRAM images.
+ */
+#define MCP_TRACE_META_IMAGE_SIGNATURE 0x669955aa
+
+/* Binary buffer header */
+struct bin_buffer_hdr {
+ u32 offset;
+ u32 length /* buffer length in bytes */;
+};
+
+/* binary buffer types */
+enum bin_buffer_type {
+ BIN_BUF_FW_VER_INFO /* fw_ver_info struct */,
+ BIN_BUF_INIT_CMD /* init commands */,
+ BIN_BUF_INIT_VAL /* init data */,
+ BIN_BUF_INIT_MODE_TREE /* init modes tree */,
+ BIN_BUF_IRO /* internal RAM offsets array */,
+ MAX_BIN_BUFFER_TYPE
+};
+
+/* Chip IDs */
+enum chip_ids {
+ CHIP_BB_A0 /* BB A0 chip ID */,
+ CHIP_BB_B0 /* BB B0 chip ID */,
+ CHIP_K2 /* AH chip ID */,
+ MAX_CHIP_IDS
+};
+
+enum idle_chk_severity_types {
+ IDLE_CHK_SEVERITY_ERROR /* idle check failure should cause an error */,
+ IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC,
+ IDLE_CHK_SEVERITY_WARNING,
+ MAX_IDLE_CHK_SEVERITY_TYPES
+};
+
+struct init_array_raw_hdr {
+ __le32 data;
+#define INIT_ARRAY_RAW_HDR_TYPE_MASK 0xF
+#define INIT_ARRAY_RAW_HDR_TYPE_SHIFT 0
+#define INIT_ARRAY_RAW_HDR_PARAMS_MASK 0xFFFFFFF /* init array params */
+#define INIT_ARRAY_RAW_HDR_PARAMS_SHIFT 4
+};
+
+struct init_array_standard_hdr {
+ __le32 data;
+#define INIT_ARRAY_STANDARD_HDR_TYPE_MASK 0xF
+#define INIT_ARRAY_STANDARD_HDR_TYPE_SHIFT 0
+#define INIT_ARRAY_STANDARD_HDR_SIZE_MASK 0xFFFFFFF
+#define INIT_ARRAY_STANDARD_HDR_SIZE_SHIFT 4
+};
+
+struct init_array_zipped_hdr {
+ __le32 data;
+#define INIT_ARRAY_ZIPPED_HDR_TYPE_MASK 0xF
+#define INIT_ARRAY_ZIPPED_HDR_TYPE_SHIFT 0
+#define INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE_MASK 0xFFFFFFF
+#define INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE_SHIFT 4
+};
+
+struct init_array_pattern_hdr {
+ __le32 data;
+#define INIT_ARRAY_PATTERN_HDR_TYPE_MASK 0xF
+#define INIT_ARRAY_PATTERN_HDR_TYPE_SHIFT 0
+#define INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE_MASK 0xF
+#define INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE_SHIFT 4
+#define INIT_ARRAY_PATTERN_HDR_REPETITIONS_MASK 0xFFFFFF
+#define INIT_ARRAY_PATTERN_HDR_REPETITIONS_SHIFT 8
+};
+
+union init_array_hdr {
+ struct init_array_raw_hdr raw /* raw init array header */;
+ struct init_array_standard_hdr standard;
+ struct init_array_zipped_hdr zipped /* zipped init array header */;
+ struct init_array_pattern_hdr pattern /* pattern init array header */;
+};
+
+enum init_array_types {
+ INIT_ARR_STANDARD /* standard init array */,
+ INIT_ARR_ZIPPED /* zipped init array */,
+ INIT_ARR_PATTERN /* a repeated pattern */,
+ MAX_INIT_ARRAY_TYPES
+};
+
+/* init operation: callback */
+struct init_callback_op {
+ __le32 op_data;
+#define INIT_CALLBACK_OP_OP_MASK 0xF
+#define INIT_CALLBACK_OP_OP_SHIFT 0
+#define INIT_CALLBACK_OP_RESERVED_MASK 0xFFFFFFF
+#define INIT_CALLBACK_OP_RESERVED_SHIFT 4
+ __le16 callback_id /* Callback ID */;
+ __le16 block_id /* Blocks ID */;
+};
+
+/* init comparison types */
+enum init_comparison_types {
+ INIT_COMPARISON_EQ /* init value is included in the init command */,
+ INIT_COMPARISON_OR /* init value is all zeros */,
+ INIT_COMPARISON_AND /* init value is an array of values */,
+ MAX_INIT_COMPARISON_TYPES
+};
+
+/* init operation: delay */
+struct init_delay_op {
+ __le32 op_data;
+#define INIT_DELAY_OP_OP_MASK 0xF
+#define INIT_DELAY_OP_OP_SHIFT 0
+#define INIT_DELAY_OP_RESERVED_MASK 0xFFFFFFF
+#define INIT_DELAY_OP_RESERVED_SHIFT 4
+ __le32 delay /* delay in us */;
+};
+
+/* init operation: if_mode */
+struct init_if_mode_op {
+ __le32 op_data;
+#define INIT_IF_MODE_OP_OP_MASK 0xF
+#define INIT_IF_MODE_OP_OP_SHIFT 0
+#define INIT_IF_MODE_OP_RESERVED1_MASK 0xFFF
+#define INIT_IF_MODE_OP_RESERVED1_SHIFT 4
+#define INIT_IF_MODE_OP_CMD_OFFSET_MASK 0xFFFF
+#define INIT_IF_MODE_OP_CMD_OFFSET_SHIFT 16
+ __le16 reserved2;
+ __le16 modes_buf_offset;
+};
+
+/* init operation: if_phase */
+struct init_if_phase_op {
+ __le32 op_data;
+#define INIT_IF_PHASE_OP_OP_MASK 0xF
+#define INIT_IF_PHASE_OP_OP_SHIFT 0
+#define INIT_IF_PHASE_OP_DMAE_ENABLE_MASK 0x1
+#define INIT_IF_PHASE_OP_DMAE_ENABLE_SHIFT 4
+#define INIT_IF_PHASE_OP_RESERVED1_MASK 0x7FF
+#define INIT_IF_PHASE_OP_RESERVED1_SHIFT 5
+#define INIT_IF_PHASE_OP_CMD_OFFSET_MASK 0xFFFF
+#define INIT_IF_PHASE_OP_CMD_OFFSET_SHIFT 16
+ __le32 phase_data;
+#define INIT_IF_PHASE_OP_PHASE_MASK 0xFF /* Init phase */
+#define INIT_IF_PHASE_OP_PHASE_SHIFT 0
+#define INIT_IF_PHASE_OP_RESERVED2_MASK 0xFF
+#define INIT_IF_PHASE_OP_RESERVED2_SHIFT 8
+#define INIT_IF_PHASE_OP_PHASE_ID_MASK 0xFFFF /* Init phase ID */
+#define INIT_IF_PHASE_OP_PHASE_ID_SHIFT 16
+};
+
+/* init mode operators */
+enum init_mode_ops {
+ INIT_MODE_OP_NOT /* init mode not operator */,
+ INIT_MODE_OP_OR /* init mode or operator */,
+ INIT_MODE_OP_AND /* init mode and operator */,
+ MAX_INIT_MODE_OPS
+};
+
+/* init operation: raw */
+struct init_raw_op {
+ __le32 op_data;
+#define INIT_RAW_OP_OP_MASK 0xF
+#define INIT_RAW_OP_OP_SHIFT 0
+#define INIT_RAW_OP_PARAM1_MASK 0xFFFFFFF /* init param 1 */
+#define INIT_RAW_OP_PARAM1_SHIFT 4
+ __le32 param2 /* Init param 2 */;
+};
+
+/* init array params */
+struct init_op_array_params {
+ __le16 size /* array size in dwords */;
+ __le16 offset /* array start offset in dwords */;
+};
+
+/* Write init operation arguments */
+union init_write_args {
+ __le32 inline_val;
+ __le32 zeros_count;
+ __le32 array_offset;
+ struct init_op_array_params runtime;
+};
+
+/* init operation: write */
+struct init_write_op {
+ __le32 data;
+#define INIT_WRITE_OP_OP_MASK 0xF
+#define INIT_WRITE_OP_OP_SHIFT 0
+#define INIT_WRITE_OP_SOURCE_MASK 0x7
+#define INIT_WRITE_OP_SOURCE_SHIFT 4
+#define INIT_WRITE_OP_RESERVED_MASK 0x1
+#define INIT_WRITE_OP_RESERVED_SHIFT 7
+#define INIT_WRITE_OP_WIDE_BUS_MASK 0x1
+#define INIT_WRITE_OP_WIDE_BUS_SHIFT 8
+#define INIT_WRITE_OP_ADDRESS_MASK 0x7FFFFF
+#define INIT_WRITE_OP_ADDRESS_SHIFT 9
+ union init_write_args args /* Write init operation arguments */;
+};
+
+/* init operation: read */
+struct init_read_op {
+ __le32 op_data;
+#define INIT_READ_OP_OP_MASK 0xF
+#define INIT_READ_OP_OP_SHIFT 0
+#define INIT_READ_OP_POLL_COMP_MASK 0x7
+#define INIT_READ_OP_POLL_COMP_SHIFT 4
+#define INIT_READ_OP_RESERVED_MASK 0x1
+#define INIT_READ_OP_RESERVED_SHIFT 7
+#define INIT_READ_OP_POLL_MASK 0x1
+#define INIT_READ_OP_POLL_SHIFT 8
+#define INIT_READ_OP_ADDRESS_MASK 0x7FFFFF
+#define INIT_READ_OP_ADDRESS_SHIFT 9
+ __le32 expected_val;
+};
+
+/* Init operations union */
+union init_op {
+ struct init_raw_op raw /* raw init operation */;
+ struct init_write_op write /* write init operation */;
+ struct init_read_op read /* read init operation */;
+ struct init_if_mode_op if_mode /* if_mode init operation */;
+ struct init_if_phase_op if_phase /* if_phase init operation */;
+ struct init_callback_op callback /* callback init operation */;
+ struct init_delay_op delay /* delay init operation */;
+};
+
+/* Init command operation types */
+enum init_op_types {
+ INIT_OP_READ /* GRC read init command */,
+ INIT_OP_WRITE /* GRC write init command */,
+ INIT_OP_IF_MODE,
+ INIT_OP_IF_PHASE,
+ INIT_OP_DELAY /* delay init command */,
+ INIT_OP_CALLBACK /* callback init command */,
+ MAX_INIT_OP_TYPES
+};
+
+/* init source types */
+enum init_source_types {
+ INIT_SRC_INLINE /* init value is included in the init command */,
+ INIT_SRC_ZEROS /* init value is all zeros */,
+ INIT_SRC_ARRAY /* init value is an array of values */,
+ INIT_SRC_RUNTIME /* init value is provided during runtime */,
+ MAX_INIT_SOURCE_TYPES
+};
+
+/* Internal RAM Offsets macro data */
+struct iro {
+ u32 base /* RAM field offset */;
+ u16 m1 /* multiplier 1 */;
+ u16 m2 /* multiplier 2 */;
+ u16 m3 /* multiplier 3 */;
+ u16 size /* RAM field size */;
+};
+
+/* QM per-port init parameters */
+struct init_qm_port_params {
+ u8 active /* Indicates if this port is active */;
+ u8 num_active_phys_tcs;
+ u16 num_pbf_cmd_lines;
+ u16 num_btb_blocks;
+ __le16 reserved;
+};
+
+/* QM per-PQ init parameters */
+struct init_qm_pq_params {
+ u8 vport_id /* VPORT ID */;
+ u8 tc_id /* TC ID */;
+ u8 wrr_group /* WRR group */;
+ u8 reserved;
+};
+
+/* QM per-vport init parameters */
+struct init_qm_vport_params {
+ u32 vport_rl;
+ u16 vport_wfq;
+ u16 first_tx_pq_id[NUM_OF_TCS];
+};
+
+/* Win 2 */
+#define GTT_BAR0_MAP_REG_IGU_CMD \
+ 0x00f000UL
+/* Win 3 */
+#define GTT_BAR0_MAP_REG_TSDM_RAM \
+ 0x010000UL
+/* Win 4 */
+#define GTT_BAR0_MAP_REG_MSDM_RAM \
+ 0x011000UL
+/* Win 5 */
+#define GTT_BAR0_MAP_REG_MSDM_RAM_1024 \
+ 0x012000UL
+/* Win 6 */
+#define GTT_BAR0_MAP_REG_USDM_RAM \
+ 0x013000UL
+/* Win 7 */
+#define GTT_BAR0_MAP_REG_USDM_RAM_1024 \
+ 0x014000UL
+/* Win 8 */
+#define GTT_BAR0_MAP_REG_USDM_RAM_2048 \
+ 0x015000UL
+/* Win 9 */
+#define GTT_BAR0_MAP_REG_XSDM_RAM \
+ 0x016000UL
+/* Win 10 */
+#define GTT_BAR0_MAP_REG_YSDM_RAM \
+ 0x017000UL
+/* Win 11 */
+#define GTT_BAR0_MAP_REG_PSDM_RAM \
+ 0x018000UL
+
+/**
+ * @brief qed_qm_pf_mem_size - prepare QM ILT sizes
+ *
+ * Returns the required host memory size in 4KB units.
+ * Must be called before all QM init HSI functions.
+ *
+ * @param pf_id - physical function ID
+ * @param num_pf_cids - number of connections used by this PF
+ * @param num_vf_cids - number of connections used by VFs of this PF
+ * @param num_tids - number of tasks used by this PF
+ * @param num_pf_pqs - number of PQs used by this PF
+ * @param num_vf_pqs - number of PQs used by VFs of this PF
+ *
+ * @return The required host memory size in 4KB units.
+ */
+u32 qed_qm_pf_mem_size(u8 pf_id,
+ u32 num_pf_cids,
+ u32 num_vf_cids,
+ u32 num_tids,
+ u16 num_pf_pqs,
+ u16 num_vf_pqs);
+
+struct qed_qm_common_rt_init_params {
+ u8 max_ports_per_engine;
+ u8 max_phys_tcs_per_port;
+ bool pf_rl_en;
+ bool pf_wfq_en;
+ bool vport_rl_en;
+ bool vport_wfq_en;
+ struct init_qm_port_params *port_params;
+};
+
+/**
+ * @brief qed_qm_common_rt_init - Prepare QM runtime init values for the
+ * engine phase.
+ *
+ * @param p_hwfn
+ * @param max_ports_per_engine - max number of ports per engine in HW
+ * @param max_phys_tcs_per_port - max number of physical TCs per port in HW
+ * @param pf_rl_en - enable per-PF rate limiters
+ * @param pf_wfq_en - enable per-PF WFQ
+ * @param vport_rl_en - enable per-VPORT rate limiters
+ * @param vport_wfq_en - enable per-VPORT WFQ
+ * @param port_params - array of size MAX_NUM_PORTS with
+ * arameters for each port
+ *
+ * @return 0 on success, -1 on error.
+ */
+int qed_qm_common_rt_init(
+ struct qed_hwfn *p_hwfn,
+ struct qed_qm_common_rt_init_params *p_params);
+
+struct qed_qm_pf_rt_init_params {
+ u8 port_id;
+ u8 pf_id;
+ u8 max_phys_tcs_per_port;
+ bool is_first_pf;
+ u32 num_pf_cids;
+ u32 num_vf_cids;
+ u32 num_tids;
+ u16 start_pq;
+ u16 num_pf_pqs;
+ u16 num_vf_pqs;
+ u8 start_vport;
+ u8 num_vports;
+ u8 pf_wfq;
+ u32 pf_rl;
+ struct init_qm_pq_params *pq_params;
+ struct init_qm_vport_params *vport_params;
+};
+
+int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_qm_pf_rt_init_params *p_params);
+
+/**
+ * @brief qed_init_pf_rl Initializes the rate limit of the specified PF
+ *
+ * @param p_hwfn
+ * @param p_ptt - ptt window used for writing the registers
+ * @param pf_id - PF ID
+ * @param pf_rl - rate limit in Mb/sec units
+ *
+ * @return 0 on success, -1 on error.
+ */
+int qed_init_pf_rl(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 pf_id,
+ u32 pf_rl);
+
+/**
+ * @brief qed_init_vport_rl Initializes the rate limit of the specified VPORT
+ *
+ * @param p_hwfn
+ * @param p_ptt - ptt window used for writing the registers
+ * @param vport_id - VPORT ID
+ * @param vport_rl - rate limit in Mb/sec units
+ *
+ * @return 0 on success, -1 on error.
+ */
+
+int qed_init_vport_rl(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 vport_id,
+ u32 vport_rl);
+/**
+ * @brief qed_send_qm_stop_cmd Sends a stop command to the QM
+ *
+ * @param p_hwfn
+ * @param p_ptt - ptt window used for writing the registers
+ * @param is_release_cmd - true for release, false for stop.
+ * @param is_tx_pq - true for Tx PQs, false for Other PQs.
+ * @param start_pq - first PQ ID to stop
+ * @param num_pqs - Number of PQs to stop, starting from start_pq.
+ *
+ * @return bool, true if successful, false if timeout occurred while waiting
+ * for QM command done.
+ */
+
+bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool is_release_cmd,
+ bool is_tx_pq,
+ u16 start_pq,
+ u16 num_pqs);
+
+/* Ystorm flow control mode. Use enum fw_flow_ctrl_mode */
+#define YSTORM_FLOW_CONTROL_MODE_OFFSET (IRO[0].base)
+#define YSTORM_FLOW_CONTROL_MODE_SIZE (IRO[0].size)
+/* Tstorm port statistics */
+#define TSTORM_PORT_STAT_OFFSET(port_id) (IRO[1].base + \
+ ((port_id) * \
+ IRO[1].m1))
+#define TSTORM_PORT_STAT_SIZE (IRO[1].size)
+/* Ustorm VF-PF Channel ready flag */
+#define USTORM_VF_PF_CHANNEL_READY_OFFSET(vf_id) (IRO[2].base + \
+ ((vf_id) * \
+ IRO[2].m1))
+#define USTORM_VF_PF_CHANNEL_READY_SIZE (IRO[2].size)
+/* Ustorm Final flr cleanup ack */
+#define USTORM_FLR_FINAL_ACK_OFFSET (IRO[3].base)
+#define USTORM_FLR_FINAL_ACK_SIZE (IRO[3].size)
+/* Ustorm Event ring consumer */
+#define USTORM_EQE_CONS_OFFSET(pf_id) (IRO[4].base + \
+ ((pf_id) * \
+ IRO[4].m1))
+#define USTORM_EQE_CONS_SIZE (IRO[4].size)
+/* Ustorm Completion ring consumer */
+#define USTORM_CQ_CONS_OFFSET(global_queue_id) (IRO[5].base + \
+ ((global_queue_id) * \
+ IRO[5].m1))
+#define USTORM_CQ_CONS_SIZE (IRO[5].size)
+/* Xstorm Integration Test Data */
+#define XSTORM_INTEG_TEST_DATA_OFFSET (IRO[6].base)
+#define XSTORM_INTEG_TEST_DATA_SIZE (IRO[6].size)
+/* Ystorm Integration Test Data */
+#define YSTORM_INTEG_TEST_DATA_OFFSET (IRO[7].base)
+#define YSTORM_INTEG_TEST_DATA_SIZE (IRO[7].size)
+/* Pstorm Integration Test Data */
+#define PSTORM_INTEG_TEST_DATA_OFFSET (IRO[8].base)
+#define PSTORM_INTEG_TEST_DATA_SIZE (IRO[8].size)
+/* Tstorm Integration Test Data */
+#define TSTORM_INTEG_TEST_DATA_OFFSET (IRO[9].base)
+#define TSTORM_INTEG_TEST_DATA_SIZE (IRO[9].size)
+/* Mstorm Integration Test Data */
+#define MSTORM_INTEG_TEST_DATA_OFFSET (IRO[10].base)
+#define MSTORM_INTEG_TEST_DATA_SIZE (IRO[10].size)
+/* Ustorm Integration Test Data */
+#define USTORM_INTEG_TEST_DATA_OFFSET (IRO[11].base)
+#define USTORM_INTEG_TEST_DATA_SIZE (IRO[11].size)
+/* Tstorm producers */
+#define TSTORM_LL2_RX_PRODS_OFFSET(core_rx_queue_id) (IRO[12].base + \
+ ((core_rx_queue_id) * \
+ IRO[12].m1))
+#define TSTORM_LL2_RX_PRODS_SIZE (IRO[12].size)
+/* Tstorm LiteL2 queue statistics */
+#define CORE_LL2_TSTORM_PER_QUEUE_STAT_OFFSET(core_rx_q_id) (IRO[13].base + \
+ ((core_rx_q_id) * \
+ IRO[13].m1))
+#define CORE_LL2_TSTORM_PER_QUEUE_STAT_SIZE (IRO[13].size)
+/* Ustorm LiteL2 queue statistics */
+#define CORE_LL2_USTORM_PER_QUEUE_STAT_OFFSET(core_rx_q_id) (IRO[14].base + \
+ ((core_rx_q_id) * \
+ IRO[14].m1))
+#define CORE_LL2_USTORM_PER_QUEUE_STAT_SIZE (IRO[14].size)
+/* Pstorm LiteL2 queue statistics */
+#define CORE_LL2_PSTORM_PER_QUEUE_STAT_OFFSET(core_txst_id) (IRO[15].base + \
+ ((core_txst_id) * \
+ IRO[15].m1))
+#define CORE_LL2_PSTORM_PER_QUEUE_STAT_SIZE (IRO[15].size)
+/* Mstorm queue statistics */
+#define MSTORM_QUEUE_STAT_OFFSET(stat_counter_id) (IRO[16].base + \
+ ((stat_counter_id) * \
+ IRO[16].m1))
+#define MSTORM_QUEUE_STAT_SIZE (IRO[16].size)
+/* Mstorm producers */
+#define MSTORM_PRODS_OFFSET(queue_id) (IRO[17].base + \
+ ((queue_id) * \
+ IRO[17].m1))
+#define MSTORM_PRODS_SIZE (IRO[17].size)
+/* TPA agregation timeout in us resolution (on ASIC) */
+#define MSTORM_TPA_TIMEOUT_US_OFFSET (IRO[18].base)
+#define MSTORM_TPA_TIMEOUT_US_SIZE (IRO[18].size)
+/* Ustorm queue statistics */
+#define USTORM_QUEUE_STAT_OFFSET(stat_counter_id) (IRO[19].base + \
+ ((stat_counter_id) * \
+ IRO[19].m1))
+#define USTORM_QUEUE_STAT_SIZE (IRO[19].size)
+/* Ustorm queue zone */
+#define USTORM_ETH_QUEUE_ZONE_OFFSET(queue_id) (IRO[20].base + \
+ ((queue_id) * \
+ IRO[20].m1))
+#define USTORM_ETH_QUEUE_ZONE_SIZE (IRO[20].size)
+/* Pstorm queue statistics */
+#define PSTORM_QUEUE_STAT_OFFSET(stat_counter_id) (IRO[21].base + \
+ ((stat_counter_id) * \
+ IRO[21].m1))
+#define PSTORM_QUEUE_STAT_SIZE (IRO[21].size)
+/* Tstorm last parser message */
+#define TSTORM_ETH_PRS_INPUT_OFFSET(pf_id) (IRO[22].base + \
+ ((pf_id) * \
+ IRO[22].m1))
+#define TSTORM_ETH_PRS_INPUT_SIZE (IRO[22].size)
+/* Ystorm queue zone */
+#define YSTORM_ETH_QUEUE_ZONE_OFFSET(queue_id) (IRO[23].base + \
+ ((queue_id) * \
+ IRO[23].m1))
+#define YSTORM_ETH_QUEUE_ZONE_SIZE (IRO[23].size)
+/* Ystorm cqe producer */
+#define YSTORM_TOE_CQ_PROD_OFFSET(rss_id) (IRO[24].base + \
+ ((rss_id) * \
+ IRO[24].m1))
+#define YSTORM_TOE_CQ_PROD_SIZE (IRO[24].size)
+/* Ustorm cqe producer */
+#define USTORM_TOE_CQ_PROD_OFFSET(rss_id) (IRO[25].base + \
+ ((rss_id) * \
+ IRO[25].m1))
+#define USTORM_TOE_CQ_PROD_SIZE (IRO[25].size)
+/* Ustorm grq producer */
+#define USTORM_TOE_GRQ_PROD_OFFSET(pf_id) (IRO[26].base + \
+ ((pf_id) * \
+ IRO[26].m1))
+#define USTORM_TOE_GRQ_PROD_SIZE (IRO[26].size)
+/* Tstorm cmdq-cons of given command queue-id */
+#define TSTORM_SCSI_CMDQ_CONS_OFFSET(cmdq_queue_id) (IRO[27].base + \
+ ((cmdq_queue_id) * \
+ IRO[27].m1))
+#define TSTORM_SCSI_CMDQ_CONS_SIZE (IRO[27].size)
+/* Mstorm rq-cons of given queue-id */
+#define MSTORM_SCSI_RQ_CONS_OFFSET(rq_queue_id) (IRO[28].base + \
+ ((rq_queue_id) * \
+ IRO[28].m1))
+#define MSTORM_SCSI_RQ_CONS_SIZE (IRO[28].size)
+/* Pstorm RoCE statistics */
+#define PSTORM_ROCE_STAT_OFFSET(stat_counter_id) (IRO[29].base + \
+ ((stat_counter_id) * \
+ IRO[29].m1))
+#define PSTORM_ROCE_STAT_SIZE (IRO[29].size)
+/* Tstorm RoCE statistics */
+#define TSTORM_ROCE_STAT_OFFSET(stat_counter_id) (IRO[30].base + \
+ ((stat_counter_id) * \
+ IRO[30].m1))
+#define TSTORM_ROCE_STAT_SIZE (IRO[30].size)
+
+static const struct iro iro_arr[31] = {
+ { 0x10, 0x0, 0x0, 0x0, 0x8 },
+ { 0x4448, 0x60, 0x0, 0x0, 0x60 },
+ { 0x498, 0x8, 0x0, 0x0, 0x4 },
+ { 0x494, 0x0, 0x0, 0x0, 0x4 },
+ { 0x10, 0x8, 0x0, 0x0, 0x2 },
+ { 0x90, 0x8, 0x0, 0x0, 0x2 },
+ { 0x4540, 0x0, 0x0, 0x0, 0xf8 },
+ { 0x39e0, 0x0, 0x0, 0x0, 0xf8 },
+ { 0x2598, 0x0, 0x0, 0x0, 0xf8 },
+ { 0x4350, 0x0, 0x0, 0x0, 0xf8 },
+ { 0x52d0, 0x0, 0x0, 0x0, 0xf8 },
+ { 0x7a48, 0x0, 0x0, 0x0, 0xf8 },
+ { 0x100, 0x8, 0x0, 0x0, 0x8 },
+ { 0x5808, 0x10, 0x0, 0x0, 0x10 },
+ { 0xb100, 0x30, 0x0, 0x0, 0x30 },
+ { 0x95c0, 0x30, 0x0, 0x0, 0x30 },
+ { 0x54f8, 0x40, 0x0, 0x0, 0x40 },
+ { 0x200, 0x10, 0x0, 0x0, 0x8 },
+ { 0x9e70, 0x0, 0x0, 0x0, 0x4 },
+ { 0x7ca0, 0x40, 0x0, 0x0, 0x30 },
+ { 0xd00, 0x8, 0x0, 0x0, 0x8 },
+ { 0x2790, 0x80, 0x0, 0x0, 0x38 },
+ { 0xa520, 0xf0, 0x0, 0x0, 0xf0 },
+ { 0x80, 0x8, 0x0, 0x0, 0x8 },
+ { 0xac0, 0x8, 0x0, 0x0, 0x8 },
+ { 0x2580, 0x8, 0x0, 0x0, 0x8 },
+ { 0x2500, 0x8, 0x0, 0x0, 0x8 },
+ { 0x440, 0x8, 0x0, 0x0, 0x2 },
+ { 0x1800, 0x8, 0x0, 0x0, 0x2 },
+ { 0x27c8, 0x80, 0x0, 0x0, 0x10 },
+ { 0x4710, 0x10, 0x0, 0x0, 0x10 },
+};
+
+/* Runtime array offsets */
+#define DORQ_REG_PF_MAX_ICID_0_RT_OFFSET 0
+#define DORQ_REG_PF_MAX_ICID_1_RT_OFFSET 1
+#define DORQ_REG_PF_MAX_ICID_2_RT_OFFSET 2
+#define DORQ_REG_PF_MAX_ICID_3_RT_OFFSET 3
+#define DORQ_REG_PF_MAX_ICID_4_RT_OFFSET 4
+#define DORQ_REG_PF_MAX_ICID_5_RT_OFFSET 5
+#define DORQ_REG_PF_MAX_ICID_6_RT_OFFSET 6
+#define DORQ_REG_PF_MAX_ICID_7_RT_OFFSET 7
+#define DORQ_REG_VF_MAX_ICID_0_RT_OFFSET 8
+#define DORQ_REG_VF_MAX_ICID_1_RT_OFFSET 9
+#define DORQ_REG_VF_MAX_ICID_2_RT_OFFSET 10
+#define DORQ_REG_VF_MAX_ICID_3_RT_OFFSET 11
+#define DORQ_REG_VF_MAX_ICID_4_RT_OFFSET 12
+#define DORQ_REG_VF_MAX_ICID_5_RT_OFFSET 13
+#define DORQ_REG_VF_MAX_ICID_6_RT_OFFSET 14
+#define DORQ_REG_VF_MAX_ICID_7_RT_OFFSET 15
+#define DORQ_REG_PF_WAKE_ALL_RT_OFFSET 16
+#define IGU_REG_PF_CONFIGURATION_RT_OFFSET 17
+#define IGU_REG_VF_CONFIGURATION_RT_OFFSET 18
+#define IGU_REG_ATTN_MSG_ADDR_L_RT_OFFSET 19
+#define IGU_REG_ATTN_MSG_ADDR_H_RT_OFFSET 20
+#define IGU_REG_LEADING_EDGE_LATCH_RT_OFFSET 21
+#define IGU_REG_TRAILING_EDGE_LATCH_RT_OFFSET 22
+#define CAU_REG_CQE_AGG_UNIT_SIZE_RT_OFFSET 23
+#define CAU_REG_SB_VAR_MEMORY_RT_OFFSET 760
+#define CAU_REG_SB_VAR_MEMORY_RT_SIZE 736
+#define CAU_REG_SB_VAR_MEMORY_RT_OFFSET 760
+#define CAU_REG_SB_VAR_MEMORY_RT_SIZE 736
+#define CAU_REG_SB_ADDR_MEMORY_RT_OFFSET 1496
+#define CAU_REG_SB_ADDR_MEMORY_RT_SIZE 736
+#define CAU_REG_PI_MEMORY_RT_OFFSET 2232
+#define CAU_REG_PI_MEMORY_RT_SIZE 4416
+#define PRS_REG_SEARCH_RESP_INITIATOR_TYPE_RT_OFFSET 6648
+#define PRS_REG_TASK_ID_MAX_INITIATOR_PF_RT_OFFSET 6649
+#define PRS_REG_TASK_ID_MAX_INITIATOR_VF_RT_OFFSET 6650
+#define PRS_REG_TASK_ID_MAX_TARGET_PF_RT_OFFSET 6651
+#define PRS_REG_TASK_ID_MAX_TARGET_VF_RT_OFFSET 6652
+#define PRS_REG_SEARCH_TCP_RT_OFFSET 6653
+#define PRS_REG_SEARCH_FCOE_RT_OFFSET 6654
+#define PRS_REG_SEARCH_ROCE_RT_OFFSET 6655
+#define PRS_REG_ROCE_DEST_QP_MAX_VF_RT_OFFSET 6656
+#define PRS_REG_ROCE_DEST_QP_MAX_PF_RT_OFFSET 6657
+#define PRS_REG_SEARCH_OPENFLOW_RT_OFFSET 6658
+#define PRS_REG_SEARCH_NON_IP_AS_OPENFLOW_RT_OFFSET 6659
+#define PRS_REG_OPENFLOW_SUPPORT_ONLY_KNOWN_OVER_IP_RT_OFFSET 6660
+#define PRS_REG_OPENFLOW_SEARCH_KEY_MASK_RT_OFFSET 6661
+#define PRS_REG_LIGHT_L2_ETHERTYPE_EN_RT_OFFSET 6662
+#define SRC_REG_FIRSTFREE_RT_OFFSET 6663
+#define SRC_REG_FIRSTFREE_RT_SIZE 2
+#define SRC_REG_LASTFREE_RT_OFFSET 6665
+#define SRC_REG_LASTFREE_RT_SIZE 2
+#define SRC_REG_COUNTFREE_RT_OFFSET 6667
+#define SRC_REG_NUMBER_HASH_BITS_RT_OFFSET 6668
+#define PSWRQ2_REG_CDUT_P_SIZE_RT_OFFSET 6669
+#define PSWRQ2_REG_CDUC_P_SIZE_RT_OFFSET 6670
+#define PSWRQ2_REG_TM_P_SIZE_RT_OFFSET 6671
+#define PSWRQ2_REG_QM_P_SIZE_RT_OFFSET 6672
+#define PSWRQ2_REG_SRC_P_SIZE_RT_OFFSET 6673
+#define PSWRQ2_REG_TM_FIRST_ILT_RT_OFFSET 6674
+#define PSWRQ2_REG_TM_LAST_ILT_RT_OFFSET 6675
+#define PSWRQ2_REG_QM_FIRST_ILT_RT_OFFSET 6676
+#define PSWRQ2_REG_QM_LAST_ILT_RT_OFFSET 6677
+#define PSWRQ2_REG_SRC_FIRST_ILT_RT_OFFSET 6678
+#define PSWRQ2_REG_SRC_LAST_ILT_RT_OFFSET 6679
+#define PSWRQ2_REG_CDUC_FIRST_ILT_RT_OFFSET 6680
+#define PSWRQ2_REG_CDUC_LAST_ILT_RT_OFFSET 6681
+#define PSWRQ2_REG_CDUT_FIRST_ILT_RT_OFFSET 6682
+#define PSWRQ2_REG_CDUT_LAST_ILT_RT_OFFSET 6683
+#define PSWRQ2_REG_TSDM_FIRST_ILT_RT_OFFSET 6684
+#define PSWRQ2_REG_TSDM_LAST_ILT_RT_OFFSET 6685
+#define PSWRQ2_REG_TM_NUMBER_OF_PF_BLOCKS_RT_OFFSET 6686
+#define PSWRQ2_REG_CDUT_NUMBER_OF_PF_BLOCKS_RT_OFFSET 6687
+#define PSWRQ2_REG_CDUC_NUMBER_OF_PF_BLOCKS_RT_OFFSET 6688
+#define PSWRQ2_REG_TM_VF_BLOCKS_RT_OFFSET 6689
+#define PSWRQ2_REG_CDUT_VF_BLOCKS_RT_OFFSET 6690
+#define PSWRQ2_REG_CDUC_VF_BLOCKS_RT_OFFSET 6691
+#define PSWRQ2_REG_TM_BLOCKS_FACTOR_RT_OFFSET 6692
+#define PSWRQ2_REG_CDUT_BLOCKS_FACTOR_RT_OFFSET 6693
+#define PSWRQ2_REG_CDUC_BLOCKS_FACTOR_RT_OFFSET 6694
+#define PSWRQ2_REG_VF_BASE_RT_OFFSET 6695
+#define PSWRQ2_REG_VF_LAST_ILT_RT_OFFSET 6696
+#define PSWRQ2_REG_WR_MBS0_RT_OFFSET 6697
+#define PSWRQ2_REG_RD_MBS0_RT_OFFSET 6698
+#define PSWRQ2_REG_DRAM_ALIGN_WR_RT_OFFSET 6699
+#define PSWRQ2_REG_DRAM_ALIGN_RD_RT_OFFSET 6700
+#define PSWRQ2_REG_ILT_MEMORY_RT_OFFSET 6701
+#define PSWRQ2_REG_ILT_MEMORY_RT_SIZE 22000
+#define PGLUE_REG_B_VF_BASE_RT_OFFSET 28701
+#define PGLUE_REG_B_CACHE_LINE_SIZE_RT_OFFSET 28702
+#define PGLUE_REG_B_PF_BAR0_SIZE_RT_OFFSET 28703
+#define PGLUE_REG_B_PF_BAR1_SIZE_RT_OFFSET 28704
+#define PGLUE_REG_B_VF_BAR1_SIZE_RT_OFFSET 28705
+#define TM_REG_VF_ENABLE_CONN_RT_OFFSET 28706
+#define TM_REG_PF_ENABLE_CONN_RT_OFFSET 28707
+#define TM_REG_PF_ENABLE_TASK_RT_OFFSET 28708
+#define TM_REG_GROUP_SIZE_RESOLUTION_CONN_RT_OFFSET 28709
+#define TM_REG_GROUP_SIZE_RESOLUTION_TASK_RT_OFFSET 28710
+#define TM_REG_CONFIG_CONN_MEM_RT_OFFSET 28711
+#define TM_REG_CONFIG_CONN_MEM_RT_SIZE 416
+#define TM_REG_CONFIG_TASK_MEM_RT_OFFSET 29127
+#define TM_REG_CONFIG_TASK_MEM_RT_SIZE 512
+#define QM_REG_MAXPQSIZE_0_RT_OFFSET 29639
+#define QM_REG_MAXPQSIZE_1_RT_OFFSET 29640
+#define QM_REG_MAXPQSIZE_2_RT_OFFSET 29641
+#define QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET 29642
+#define QM_REG_MAXPQSIZETXSEL_1_RT_OFFSET 29643
+#define QM_REG_MAXPQSIZETXSEL_2_RT_OFFSET 29644
+#define QM_REG_MAXPQSIZETXSEL_3_RT_OFFSET 29645
+#define QM_REG_MAXPQSIZETXSEL_4_RT_OFFSET 29646
+#define QM_REG_MAXPQSIZETXSEL_5_RT_OFFSET 29647
+#define QM_REG_MAXPQSIZETXSEL_6_RT_OFFSET 29648
+#define QM_REG_MAXPQSIZETXSEL_7_RT_OFFSET 29649
+#define QM_REG_MAXPQSIZETXSEL_8_RT_OFFSET 29650
+#define QM_REG_MAXPQSIZETXSEL_9_RT_OFFSET 29651
+#define QM_REG_MAXPQSIZETXSEL_10_RT_OFFSET 29652
+#define QM_REG_MAXPQSIZETXSEL_11_RT_OFFSET 29653
+#define QM_REG_MAXPQSIZETXSEL_12_RT_OFFSET 29654
+#define QM_REG_MAXPQSIZETXSEL_13_RT_OFFSET 29655
+#define QM_REG_MAXPQSIZETXSEL_14_RT_OFFSET 29656
+#define QM_REG_MAXPQSIZETXSEL_15_RT_OFFSET 29657
+#define QM_REG_MAXPQSIZETXSEL_16_RT_OFFSET 29658
+#define QM_REG_MAXPQSIZETXSEL_17_RT_OFFSET 29659
+#define QM_REG_MAXPQSIZETXSEL_18_RT_OFFSET 29660
+#define QM_REG_MAXPQSIZETXSEL_19_RT_OFFSET 29661
+#define QM_REG_MAXPQSIZETXSEL_20_RT_OFFSET 29662
+#define QM_REG_MAXPQSIZETXSEL_21_RT_OFFSET 29663
+#define QM_REG_MAXPQSIZETXSEL_22_RT_OFFSET 29664
+#define QM_REG_MAXPQSIZETXSEL_23_RT_OFFSET 29665
+#define QM_REG_MAXPQSIZETXSEL_24_RT_OFFSET 29666
+#define QM_REG_MAXPQSIZETXSEL_25_RT_OFFSET 29667
+#define QM_REG_MAXPQSIZETXSEL_26_RT_OFFSET 29668
+#define QM_REG_MAXPQSIZETXSEL_27_RT_OFFSET 29669
+#define QM_REG_MAXPQSIZETXSEL_28_RT_OFFSET 29670
+#define QM_REG_MAXPQSIZETXSEL_29_RT_OFFSET 29671
+#define QM_REG_MAXPQSIZETXSEL_30_RT_OFFSET 29672
+#define QM_REG_MAXPQSIZETXSEL_31_RT_OFFSET 29673
+#define QM_REG_MAXPQSIZETXSEL_32_RT_OFFSET 29674
+#define QM_REG_MAXPQSIZETXSEL_33_RT_OFFSET 29675
+#define QM_REG_MAXPQSIZETXSEL_34_RT_OFFSET 29676
+#define QM_REG_MAXPQSIZETXSEL_35_RT_OFFSET 29677
+#define QM_REG_MAXPQSIZETXSEL_36_RT_OFFSET 29678
+#define QM_REG_MAXPQSIZETXSEL_37_RT_OFFSET 29679
+#define QM_REG_MAXPQSIZETXSEL_38_RT_OFFSET 29680
+#define QM_REG_MAXPQSIZETXSEL_39_RT_OFFSET 29681
+#define QM_REG_MAXPQSIZETXSEL_40_RT_OFFSET 29682
+#define QM_REG_MAXPQSIZETXSEL_41_RT_OFFSET 29683
+#define QM_REG_MAXPQSIZETXSEL_42_RT_OFFSET 29684
+#define QM_REG_MAXPQSIZETXSEL_43_RT_OFFSET 29685
+#define QM_REG_MAXPQSIZETXSEL_44_RT_OFFSET 29686
+#define QM_REG_MAXPQSIZETXSEL_45_RT_OFFSET 29687
+#define QM_REG_MAXPQSIZETXSEL_46_RT_OFFSET 29688
+#define QM_REG_MAXPQSIZETXSEL_47_RT_OFFSET 29689
+#define QM_REG_MAXPQSIZETXSEL_48_RT_OFFSET 29690
+#define QM_REG_MAXPQSIZETXSEL_49_RT_OFFSET 29691
+#define QM_REG_MAXPQSIZETXSEL_50_RT_OFFSET 29692
+#define QM_REG_MAXPQSIZETXSEL_51_RT_OFFSET 29693
+#define QM_REG_MAXPQSIZETXSEL_52_RT_OFFSET 29694
+#define QM_REG_MAXPQSIZETXSEL_53_RT_OFFSET 29695
+#define QM_REG_MAXPQSIZETXSEL_54_RT_OFFSET 29696
+#define QM_REG_MAXPQSIZETXSEL_55_RT_OFFSET 29697
+#define QM_REG_MAXPQSIZETXSEL_56_RT_OFFSET 29698
+#define QM_REG_MAXPQSIZETXSEL_57_RT_OFFSET 29699
+#define QM_REG_MAXPQSIZETXSEL_58_RT_OFFSET 29700
+#define QM_REG_MAXPQSIZETXSEL_59_RT_OFFSET 29701
+#define QM_REG_MAXPQSIZETXSEL_60_RT_OFFSET 29702
+#define QM_REG_MAXPQSIZETXSEL_61_RT_OFFSET 29703
+#define QM_REG_MAXPQSIZETXSEL_62_RT_OFFSET 29704
+#define QM_REG_MAXPQSIZETXSEL_63_RT_OFFSET 29705
+#define QM_REG_BASEADDROTHERPQ_RT_OFFSET 29706
+#define QM_REG_BASEADDROTHERPQ_RT_SIZE 128
+#define QM_REG_VOQCRDLINE_RT_OFFSET 29834
+#define QM_REG_VOQCRDLINE_RT_SIZE 20
+#define QM_REG_VOQINITCRDLINE_RT_OFFSET 29854
+#define QM_REG_VOQINITCRDLINE_RT_SIZE 20
+#define QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET 29874
+#define QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET 29875
+#define QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET 29876
+#define QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET 29877
+#define QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET 29878
+#define QM_REG_WRROTHERPQGRP_0_RT_OFFSET 29879
+#define QM_REG_WRROTHERPQGRP_1_RT_OFFSET 29880
+#define QM_REG_WRROTHERPQGRP_2_RT_OFFSET 29881
+#define QM_REG_WRROTHERPQGRP_3_RT_OFFSET 29882
+#define QM_REG_WRROTHERPQGRP_4_RT_OFFSET 29883
+#define QM_REG_WRROTHERPQGRP_5_RT_OFFSET 29884
+#define QM_REG_WRROTHERPQGRP_6_RT_OFFSET 29885
+#define QM_REG_WRROTHERPQGRP_7_RT_OFFSET 29886
+#define QM_REG_WRROTHERPQGRP_8_RT_OFFSET 29887
+#define QM_REG_WRROTHERPQGRP_9_RT_OFFSET 29888
+#define QM_REG_WRROTHERPQGRP_10_RT_OFFSET 29889
+#define QM_REG_WRROTHERPQGRP_11_RT_OFFSET 29890
+#define QM_REG_WRROTHERPQGRP_12_RT_OFFSET 29891
+#define QM_REG_WRROTHERPQGRP_13_RT_OFFSET 29892
+#define QM_REG_WRROTHERPQGRP_14_RT_OFFSET 29893
+#define QM_REG_WRROTHERPQGRP_15_RT_OFFSET 29894
+#define QM_REG_WRROTHERGRPWEIGHT_0_RT_OFFSET 29895
+#define QM_REG_WRROTHERGRPWEIGHT_1_RT_OFFSET 29896
+#define QM_REG_WRROTHERGRPWEIGHT_2_RT_OFFSET 29897
+#define QM_REG_WRROTHERGRPWEIGHT_3_RT_OFFSET 29898
+#define QM_REG_WRRTXGRPWEIGHT_0_RT_OFFSET 29899
+#define QM_REG_WRRTXGRPWEIGHT_1_RT_OFFSET 29900
+#define QM_REG_PQTX2PF_0_RT_OFFSET 29901
+#define QM_REG_PQTX2PF_1_RT_OFFSET 29902
+#define QM_REG_PQTX2PF_2_RT_OFFSET 29903
+#define QM_REG_PQTX2PF_3_RT_OFFSET 29904
+#define QM_REG_PQTX2PF_4_RT_OFFSET 29905
+#define QM_REG_PQTX2PF_5_RT_OFFSET 29906
+#define QM_REG_PQTX2PF_6_RT_OFFSET 29907
+#define QM_REG_PQTX2PF_7_RT_OFFSET 29908
+#define QM_REG_PQTX2PF_8_RT_OFFSET 29909
+#define QM_REG_PQTX2PF_9_RT_OFFSET 29910
+#define QM_REG_PQTX2PF_10_RT_OFFSET 29911
+#define QM_REG_PQTX2PF_11_RT_OFFSET 29912
+#define QM_REG_PQTX2PF_12_RT_OFFSET 29913
+#define QM_REG_PQTX2PF_13_RT_OFFSET 29914
+#define QM_REG_PQTX2PF_14_RT_OFFSET 29915
+#define QM_REG_PQTX2PF_15_RT_OFFSET 29916
+#define QM_REG_PQTX2PF_16_RT_OFFSET 29917
+#define QM_REG_PQTX2PF_17_RT_OFFSET 29918
+#define QM_REG_PQTX2PF_18_RT_OFFSET 29919
+#define QM_REG_PQTX2PF_19_RT_OFFSET 29920
+#define QM_REG_PQTX2PF_20_RT_OFFSET 29921
+#define QM_REG_PQTX2PF_21_RT_OFFSET 29922
+#define QM_REG_PQTX2PF_22_RT_OFFSET 29923
+#define QM_REG_PQTX2PF_23_RT_OFFSET 29924
+#define QM_REG_PQTX2PF_24_RT_OFFSET 29925
+#define QM_REG_PQTX2PF_25_RT_OFFSET 29926
+#define QM_REG_PQTX2PF_26_RT_OFFSET 29927
+#define QM_REG_PQTX2PF_27_RT_OFFSET 29928
+#define QM_REG_PQTX2PF_28_RT_OFFSET 29929
+#define QM_REG_PQTX2PF_29_RT_OFFSET 29930
+#define QM_REG_PQTX2PF_30_RT_OFFSET 29931
+#define QM_REG_PQTX2PF_31_RT_OFFSET 29932
+#define QM_REG_PQTX2PF_32_RT_OFFSET 29933
+#define QM_REG_PQTX2PF_33_RT_OFFSET 29934
+#define QM_REG_PQTX2PF_34_RT_OFFSET 29935
+#define QM_REG_PQTX2PF_35_RT_OFFSET 29936
+#define QM_REG_PQTX2PF_36_RT_OFFSET 29937
+#define QM_REG_PQTX2PF_37_RT_OFFSET 29938
+#define QM_REG_PQTX2PF_38_RT_OFFSET 29939
+#define QM_REG_PQTX2PF_39_RT_OFFSET 29940
+#define QM_REG_PQTX2PF_40_RT_OFFSET 29941
+#define QM_REG_PQTX2PF_41_RT_OFFSET 29942
+#define QM_REG_PQTX2PF_42_RT_OFFSET 29943
+#define QM_REG_PQTX2PF_43_RT_OFFSET 29944
+#define QM_REG_PQTX2PF_44_RT_OFFSET 29945
+#define QM_REG_PQTX2PF_45_RT_OFFSET 29946
+#define QM_REG_PQTX2PF_46_RT_OFFSET 29947
+#define QM_REG_PQTX2PF_47_RT_OFFSET 29948
+#define QM_REG_PQTX2PF_48_RT_OFFSET 29949
+#define QM_REG_PQTX2PF_49_RT_OFFSET 29950
+#define QM_REG_PQTX2PF_50_RT_OFFSET 29951
+#define QM_REG_PQTX2PF_51_RT_OFFSET 29952
+#define QM_REG_PQTX2PF_52_RT_OFFSET 29953
+#define QM_REG_PQTX2PF_53_RT_OFFSET 29954
+#define QM_REG_PQTX2PF_54_RT_OFFSET 29955
+#define QM_REG_PQTX2PF_55_RT_OFFSET 29956
+#define QM_REG_PQTX2PF_56_RT_OFFSET 29957
+#define QM_REG_PQTX2PF_57_RT_OFFSET 29958
+#define QM_REG_PQTX2PF_58_RT_OFFSET 29959
+#define QM_REG_PQTX2PF_59_RT_OFFSET 29960
+#define QM_REG_PQTX2PF_60_RT_OFFSET 29961
+#define QM_REG_PQTX2PF_61_RT_OFFSET 29962
+#define QM_REG_PQTX2PF_62_RT_OFFSET 29963
+#define QM_REG_PQTX2PF_63_RT_OFFSET 29964
+#define QM_REG_PQOTHER2PF_0_RT_OFFSET 29965
+#define QM_REG_PQOTHER2PF_1_RT_OFFSET 29966
+#define QM_REG_PQOTHER2PF_2_RT_OFFSET 29967
+#define QM_REG_PQOTHER2PF_3_RT_OFFSET 29968
+#define QM_REG_PQOTHER2PF_4_RT_OFFSET 29969
+#define QM_REG_PQOTHER2PF_5_RT_OFFSET 29970
+#define QM_REG_PQOTHER2PF_6_RT_OFFSET 29971
+#define QM_REG_PQOTHER2PF_7_RT_OFFSET 29972
+#define QM_REG_PQOTHER2PF_8_RT_OFFSET 29973
+#define QM_REG_PQOTHER2PF_9_RT_OFFSET 29974
+#define QM_REG_PQOTHER2PF_10_RT_OFFSET 29975
+#define QM_REG_PQOTHER2PF_11_RT_OFFSET 29976
+#define QM_REG_PQOTHER2PF_12_RT_OFFSET 29977
+#define QM_REG_PQOTHER2PF_13_RT_OFFSET 29978
+#define QM_REG_PQOTHER2PF_14_RT_OFFSET 29979
+#define QM_REG_PQOTHER2PF_15_RT_OFFSET 29980
+#define QM_REG_RLGLBLPERIOD_0_RT_OFFSET 29981
+#define QM_REG_RLGLBLPERIOD_1_RT_OFFSET 29982
+#define QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET 29983
+#define QM_REG_RLGLBLPERIODTIMER_1_RT_OFFSET 29984
+#define QM_REG_RLGLBLPERIODSEL_0_RT_OFFSET 29985
+#define QM_REG_RLGLBLPERIODSEL_1_RT_OFFSET 29986
+#define QM_REG_RLGLBLPERIODSEL_2_RT_OFFSET 29987
+#define QM_REG_RLGLBLPERIODSEL_3_RT_OFFSET 29988
+#define QM_REG_RLGLBLPERIODSEL_4_RT_OFFSET 29989
+#define QM_REG_RLGLBLPERIODSEL_5_RT_OFFSET 29990
+#define QM_REG_RLGLBLPERIODSEL_6_RT_OFFSET 29991
+#define QM_REG_RLGLBLPERIODSEL_7_RT_OFFSET 29992
+#define QM_REG_RLGLBLINCVAL_RT_OFFSET 29993
+#define QM_REG_RLGLBLINCVAL_RT_SIZE 256
+#define QM_REG_RLGLBLUPPERBOUND_RT_OFFSET 30249
+#define QM_REG_RLGLBLUPPERBOUND_RT_SIZE 256
+#define QM_REG_RLGLBLCRD_RT_OFFSET 30505
+#define QM_REG_RLGLBLCRD_RT_SIZE 256
+#define QM_REG_RLGLBLENABLE_RT_OFFSET 30761
+#define QM_REG_RLPFPERIOD_RT_OFFSET 30762
+#define QM_REG_RLPFPERIODTIMER_RT_OFFSET 30763
+#define QM_REG_RLPFINCVAL_RT_OFFSET 30764
+#define QM_REG_RLPFINCVAL_RT_SIZE 16
+#define QM_REG_RLPFUPPERBOUND_RT_OFFSET 30780
+#define QM_REG_RLPFUPPERBOUND_RT_SIZE 16
+#define QM_REG_RLPFCRD_RT_OFFSET 30796
+#define QM_REG_RLPFCRD_RT_SIZE 16
+#define QM_REG_RLPFENABLE_RT_OFFSET 30812
+#define QM_REG_RLPFVOQENABLE_RT_OFFSET 30813
+#define QM_REG_WFQPFWEIGHT_RT_OFFSET 30814
+#define QM_REG_WFQPFWEIGHT_RT_SIZE 16
+#define QM_REG_WFQPFUPPERBOUND_RT_OFFSET 30830
+#define QM_REG_WFQPFUPPERBOUND_RT_SIZE 16
+#define QM_REG_WFQPFCRD_RT_OFFSET 30846
+#define QM_REG_WFQPFCRD_RT_SIZE 160
+#define QM_REG_WFQPFENABLE_RT_OFFSET 31006
+#define QM_REG_WFQVPENABLE_RT_OFFSET 31007
+#define QM_REG_BASEADDRTXPQ_RT_OFFSET 31008
+#define QM_REG_BASEADDRTXPQ_RT_SIZE 512
+#define QM_REG_TXPQMAP_RT_OFFSET 31520
+#define QM_REG_TXPQMAP_RT_SIZE 512
+#define QM_REG_WFQVPWEIGHT_RT_OFFSET 32032
+#define QM_REG_WFQVPWEIGHT_RT_SIZE 512
+#define QM_REG_WFQVPUPPERBOUND_RT_OFFSET 32544
+#define QM_REG_WFQVPUPPERBOUND_RT_SIZE 512
+#define QM_REG_WFQVPCRD_RT_OFFSET 33056
+#define QM_REG_WFQVPCRD_RT_SIZE 512
+#define QM_REG_WFQVPMAP_RT_OFFSET 33568
+#define QM_REG_WFQVPMAP_RT_SIZE 512
+#define QM_REG_WFQPFCRD_MSB_RT_OFFSET 34080
+#define QM_REG_WFQPFCRD_MSB_RT_SIZE 160
+#define NIG_REG_LLH_CLS_TYPE_DUALMODE_RT_OFFSET 34240
+#define NIG_REG_OUTER_TAG_VALUE_LIST0_RT_OFFSET 34241
+#define NIG_REG_OUTER_TAG_VALUE_LIST1_RT_OFFSET 34242
+#define NIG_REG_OUTER_TAG_VALUE_LIST2_RT_OFFSET 34243
+#define NIG_REG_OUTER_TAG_VALUE_LIST3_RT_OFFSET 34244
+#define NIG_REG_OUTER_TAG_VALUE_MASK_RT_OFFSET 34245
+#define NIG_REG_LLH_FUNC_TAGMAC_CLS_TYPE_RT_OFFSET 34246
+#define NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET 34247
+#define NIG_REG_LLH_FUNC_TAG_EN_RT_SIZE 4
+#define NIG_REG_LLH_FUNC_TAG_HDR_SEL_RT_OFFSET 34251
+#define NIG_REG_LLH_FUNC_TAG_HDR_SEL_RT_SIZE 4
+#define NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET 34255
+#define NIG_REG_LLH_FUNC_TAG_VALUE_RT_SIZE 4
+#define NIG_REG_LLH_FUNC_NO_TAG_RT_OFFSET 34259
+#define NIG_REG_LLH_FUNC_FILTER_VALUE_RT_OFFSET 34260
+#define NIG_REG_LLH_FUNC_FILTER_VALUE_RT_SIZE 32
+#define NIG_REG_LLH_FUNC_FILTER_EN_RT_OFFSET 34292
+#define NIG_REG_LLH_FUNC_FILTER_EN_RT_SIZE 16
+#define NIG_REG_LLH_FUNC_FILTER_MODE_RT_OFFSET 34308
+#define NIG_REG_LLH_FUNC_FILTER_MODE_RT_SIZE 16
+#define NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_RT_OFFSET 34324
+#define NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_RT_SIZE 16
+#define NIG_REG_LLH_FUNC_FILTER_HDR_SEL_RT_OFFSET 34340
+#define NIG_REG_LLH_FUNC_FILTER_HDR_SEL_RT_SIZE 16
+#define NIG_REG_TX_EDPM_CTRL_RT_OFFSET 34356
+#define CDU_REG_CID_ADDR_PARAMS_RT_OFFSET 34357
+#define CDU_REG_SEGMENT0_PARAMS_RT_OFFSET 34358
+#define CDU_REG_SEGMENT1_PARAMS_RT_OFFSET 34359
+#define CDU_REG_PF_SEG0_TYPE_OFFSET_RT_OFFSET 34360
+#define CDU_REG_PF_SEG1_TYPE_OFFSET_RT_OFFSET 34361
+#define CDU_REG_PF_SEG2_TYPE_OFFSET_RT_OFFSET 34362
+#define CDU_REG_PF_SEG3_TYPE_OFFSET_RT_OFFSET 34363
+#define CDU_REG_PF_FL_SEG0_TYPE_OFFSET_RT_OFFSET 34364
+#define CDU_REG_PF_FL_SEG1_TYPE_OFFSET_RT_OFFSET 34365
+#define CDU_REG_PF_FL_SEG2_TYPE_OFFSET_RT_OFFSET 34366
+#define CDU_REG_PF_FL_SEG3_TYPE_OFFSET_RT_OFFSET 34367
+#define CDU_REG_VF_SEG_TYPE_OFFSET_RT_OFFSET 34368
+#define CDU_REG_VF_FL_SEG_TYPE_OFFSET_RT_OFFSET 34369
+#define PBF_REG_BTB_SHARED_AREA_SIZE_RT_OFFSET 34370
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET 34371
+#define PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET 34372
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ0_RT_OFFSET 34373
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET 34374
+#define PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET 34375
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ1_RT_OFFSET 34376
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ2_RT_OFFSET 34377
+#define PBF_REG_BTB_GUARANTEED_VOQ2_RT_OFFSET 34378
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ2_RT_OFFSET 34379
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ3_RT_OFFSET 34380
+#define PBF_REG_BTB_GUARANTEED_VOQ3_RT_OFFSET 34381
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ3_RT_OFFSET 34382
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ4_RT_OFFSET 34383
+#define PBF_REG_BTB_GUARANTEED_VOQ4_RT_OFFSET 34384
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ4_RT_OFFSET 34385
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ5_RT_OFFSET 34386
+#define PBF_REG_BTB_GUARANTEED_VOQ5_RT_OFFSET 34387
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ5_RT_OFFSET 34388
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ6_RT_OFFSET 34389
+#define PBF_REG_BTB_GUARANTEED_VOQ6_RT_OFFSET 34390
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ6_RT_OFFSET 34391
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ7_RT_OFFSET 34392
+#define PBF_REG_BTB_GUARANTEED_VOQ7_RT_OFFSET 34393
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ7_RT_OFFSET 34394
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ8_RT_OFFSET 34395
+#define PBF_REG_BTB_GUARANTEED_VOQ8_RT_OFFSET 34396
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ8_RT_OFFSET 34397
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ9_RT_OFFSET 34398
+#define PBF_REG_BTB_GUARANTEED_VOQ9_RT_OFFSET 34399
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ9_RT_OFFSET 34400
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ10_RT_OFFSET 34401
+#define PBF_REG_BTB_GUARANTEED_VOQ10_RT_OFFSET 34402
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ10_RT_OFFSET 34403
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ11_RT_OFFSET 34404
+#define PBF_REG_BTB_GUARANTEED_VOQ11_RT_OFFSET 34405
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ11_RT_OFFSET 34406
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ12_RT_OFFSET 34407
+#define PBF_REG_BTB_GUARANTEED_VOQ12_RT_OFFSET 34408
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ12_RT_OFFSET 34409
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ13_RT_OFFSET 34410
+#define PBF_REG_BTB_GUARANTEED_VOQ13_RT_OFFSET 34411
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ13_RT_OFFSET 34412
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ14_RT_OFFSET 34413
+#define PBF_REG_BTB_GUARANTEED_VOQ14_RT_OFFSET 34414
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ14_RT_OFFSET 34415
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ15_RT_OFFSET 34416
+#define PBF_REG_BTB_GUARANTEED_VOQ15_RT_OFFSET 34417
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ15_RT_OFFSET 34418
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ16_RT_OFFSET 34419
+#define PBF_REG_BTB_GUARANTEED_VOQ16_RT_OFFSET 34420
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ16_RT_OFFSET 34421
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ17_RT_OFFSET 34422
+#define PBF_REG_BTB_GUARANTEED_VOQ17_RT_OFFSET 34423
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ17_RT_OFFSET 34424
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ18_RT_OFFSET 34425
+#define PBF_REG_BTB_GUARANTEED_VOQ18_RT_OFFSET 34426
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ18_RT_OFFSET 34427
+#define PBF_REG_YCMD_QS_NUM_LINES_VOQ19_RT_OFFSET 34428
+#define PBF_REG_BTB_GUARANTEED_VOQ19_RT_OFFSET 34429
+#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ19_RT_OFFSET 34430
+#define XCM_REG_CON_PHY_Q3_RT_OFFSET 34431
+
+#define RUNTIME_ARRAY_SIZE 34432
+
+/* The eth storm context for the Ystorm */
+struct ystorm_eth_conn_st_ctx {
+ __le32 reserved[4];
+};
+
+/* The eth storm context for the Pstorm */
+struct pstorm_eth_conn_st_ctx {
+ __le32 reserved[8];
+};
+
+/* The eth storm context for the Xstorm */
+struct xstorm_eth_conn_st_ctx {
+ __le32 reserved[60];
+};
+
+struct xstorm_eth_conn_ag_ctx {
+ u8 reserved0 /* cdu_validation */;
+ u8 eth_state /* state */;
+ u8 flags0;
+#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1
+#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED1_MASK 0x1
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED1_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED2_MASK 0x1
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED2_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM3_MASK 0x1
+#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM3_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED3_MASK 0x1 /* bit4 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED3_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED4_MASK 0x1
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED4_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED5_MASK 0x1 /* bit6 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED5_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED6_MASK 0x1 /* bit7 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED6_SHIFT 7
+ u8 flags1;
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED7_MASK 0x1 /* bit8 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED7_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED8_MASK 0x1 /* bit9 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED8_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED9_MASK 0x1 /* bit10 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED9_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_BIT11_MASK 0x1 /* bit11 */
+#define XSTORM_ETH_CONN_AG_CTX_BIT11_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_BIT12_MASK 0x1 /* bit12 */
+#define XSTORM_ETH_CONN_AG_CTX_BIT12_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_BIT13_MASK 0x1 /* bit13 */
+#define XSTORM_ETH_CONN_AG_CTX_BIT13_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_TX_RULE_ACTIVE_MASK 0x1 /* bit14 */
+#define XSTORM_ETH_CONN_AG_CTX_TX_RULE_ACTIVE_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_ACTIVE_MASK 0x1 /* bit15 */
+#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_ACTIVE_SHIFT 7
+ u8 flags2;
+#define XSTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */
+#define XSTORM_ETH_CONN_AG_CTX_CF0_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */
+#define XSTORM_ETH_CONN_AG_CTX_CF1_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */
+#define XSTORM_ETH_CONN_AG_CTX_CF2_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF3_MASK 0x3
+#define XSTORM_ETH_CONN_AG_CTX_CF3_SHIFT 6
+ u8 flags3;
+#define XSTORM_ETH_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */
+#define XSTORM_ETH_CONN_AG_CTX_CF4_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */
+#define XSTORM_ETH_CONN_AG_CTX_CF5_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */
+#define XSTORM_ETH_CONN_AG_CTX_CF6_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */
+#define XSTORM_ETH_CONN_AG_CTX_CF7_SHIFT 6
+ u8 flags4;
+#define XSTORM_ETH_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */
+#define XSTORM_ETH_CONN_AG_CTX_CF8_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */
+#define XSTORM_ETH_CONN_AG_CTX_CF9_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */
+#define XSTORM_ETH_CONN_AG_CTX_CF10_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF11_MASK 0x3 /* cf11 */
+#define XSTORM_ETH_CONN_AG_CTX_CF11_SHIFT 6
+ u8 flags5;
+#define XSTORM_ETH_CONN_AG_CTX_CF12_MASK 0x3 /* cf12 */
+#define XSTORM_ETH_CONN_AG_CTX_CF12_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_CF13_MASK 0x3 /* cf13 */
+#define XSTORM_ETH_CONN_AG_CTX_CF13_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_CF14_MASK 0x3 /* cf14 */
+#define XSTORM_ETH_CONN_AG_CTX_CF14_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF15_MASK 0x3 /* cf15 */
+#define XSTORM_ETH_CONN_AG_CTX_CF15_SHIFT 6
+ u8 flags6;
+#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_MASK 0x3 /* cf16 */
+#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_MASK 0x3
+#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_MASK 0x3 /* cf18 */
+#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_MASK 0x3 /* cf19 */
+#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_SHIFT 6
+ u8 flags7;
+#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_MASK 0x3 /* cf20 */
+#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED10_MASK 0x3 /* cf21 */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED10_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_MASK 0x3 /* cf22 */
+#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define XSTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define XSTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 7
+ u8 flags8;
+#define XSTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define XSTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */
+#define XSTORM_ETH_CONN_AG_CTX_CF3EN_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */
+#define XSTORM_ETH_CONN_AG_CTX_CF4EN_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */
+#define XSTORM_ETH_CONN_AG_CTX_CF5EN_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */
+#define XSTORM_ETH_CONN_AG_CTX_CF6EN_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */
+#define XSTORM_ETH_CONN_AG_CTX_CF7EN_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */
+#define XSTORM_ETH_CONN_AG_CTX_CF8EN_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */
+#define XSTORM_ETH_CONN_AG_CTX_CF9EN_SHIFT 7
+ u8 flags9;
+#define XSTORM_ETH_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */
+#define XSTORM_ETH_CONN_AG_CTX_CF10EN_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_CF11EN_MASK 0x1 /* cf11en */
+#define XSTORM_ETH_CONN_AG_CTX_CF11EN_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_CF12EN_MASK 0x1 /* cf12en */
+#define XSTORM_ETH_CONN_AG_CTX_CF12EN_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_CF13EN_MASK 0x1 /* cf13en */
+#define XSTORM_ETH_CONN_AG_CTX_CF13EN_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_CF14EN_MASK 0x1 /* cf14en */
+#define XSTORM_ETH_CONN_AG_CTX_CF14EN_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_CF15EN_MASK 0x1 /* cf15en */
+#define XSTORM_ETH_CONN_AG_CTX_CF15EN_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_MASK 0x1 /* cf16en */
+#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_EN_MASK 0x1
+#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_EN_SHIFT 7
+ u8 flags10;
+#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_EN_MASK 0x1 /* cf18en */
+#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_EN_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_EN_MASK 0x1 /* cf19en */
+#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_EN_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_EN_MASK 0x1 /* cf20en */
+#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_EN_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED11_MASK 0x1 /* cf21en */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED11_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_EN_MASK 0x1 /* cf22en */
+#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_EN_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_MASK 0x1 /* cf23en */
+#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED12_MASK 0x1 /* rule0en */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED12_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED13_MASK 0x1 /* rule1en */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED13_SHIFT 7
+ u8 flags11;
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED14_MASK 0x1 /* rule2en */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED14_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED15_MASK 0x1 /* rule3en */
+#define XSTORM_ETH_CONN_AG_CTX_RESERVED15_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_TX_DEC_RULE_EN_MASK 0x1 /* rule4en */
+#define XSTORM_ETH_CONN_AG_CTX_TX_DEC_RULE_EN_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE5EN_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE6EN_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE7EN_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED1_MASK 0x1 /* rule8en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED1_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_RULE9EN_MASK 0x1 /* rule9en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE9EN_SHIFT 7
+ u8 flags12;
+#define XSTORM_ETH_CONN_AG_CTX_RULE10EN_MASK 0x1 /* rule10en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE10EN_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_RULE11EN_MASK 0x1 /* rule11en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE11EN_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED2_MASK 0x1 /* rule12en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED2_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED3_MASK 0x1 /* rule13en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED3_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_RULE14EN_MASK 0x1 /* rule14en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE14EN_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_RULE15EN_MASK 0x1 /* rule15en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE15EN_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_RULE16EN_MASK 0x1 /* rule16en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE16EN_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_RULE17EN_MASK 0x1 /* rule17en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE17EN_SHIFT 7
+ u8 flags13;
+#define XSTORM_ETH_CONN_AG_CTX_RULE18EN_MASK 0x1 /* rule18en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE18EN_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_RULE19EN_MASK 0x1 /* rule19en */
+#define XSTORM_ETH_CONN_AG_CTX_RULE19EN_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED4_MASK 0x1 /* rule20en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED4_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED5_MASK 0x1 /* rule21en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED5_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED6_MASK 0x1 /* rule22en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED6_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED7_MASK 0x1 /* rule23en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED7_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED8_MASK 0x1 /* rule24en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED8_SHIFT 6
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED9_MASK 0x1 /* rule25en */
+#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED9_SHIFT 7
+ u8 flags14;
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_USE_EXT_HDR_MASK 0x1 /* bit16 */
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_USE_EXT_HDR_SHIFT 0
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_MASK 0x1 /* bit17 */
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_SHIFT 1
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_MASK 0x1 /* bit18 */
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_SHIFT 2
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_MASK 0x1 /* bit19 */
+#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_SHIFT 3
+#define XSTORM_ETH_CONN_AG_CTX_L2_EDPM_ENABLE_MASK 0x1 /* bit20 */
+#define XSTORM_ETH_CONN_AG_CTX_L2_EDPM_ENABLE_SHIFT 4
+#define XSTORM_ETH_CONN_AG_CTX_ROCE_EDPM_ENABLE_MASK 0x1 /* bit21 */
+#define XSTORM_ETH_CONN_AG_CTX_ROCE_EDPM_ENABLE_SHIFT 5
+#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_MASK 0x3 /* cf23 */
+#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_SHIFT 6
+ u8 edpm_event_id /* byte2 */;
+ __le16 physical_q0 /* physical_q0 */;
+ __le16 word1 /* physical_q1 */;
+ __le16 edpm_num_bds /* physical_q2 */;
+ __le16 tx_bd_cons /* word3 */;
+ __le16 tx_bd_prod /* word4 */;
+ __le16 go_to_bd_cons /* word5 */;
+ __le16 conn_dpi /* conn_dpi */;
+ u8 byte3 /* byte3 */;
+ u8 byte4 /* byte4 */;
+ u8 byte5 /* byte5 */;
+ u8 byte6 /* byte6 */;
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+ __le32 reg4 /* reg4 */;
+ __le32 reg5 /* cf_array0 */;
+ __le32 reg6 /* cf_array1 */;
+ __le16 word7 /* word7 */;
+ __le16 word8 /* word8 */;
+ __le16 word9 /* word9 */;
+ __le16 word10 /* word10 */;
+ __le32 reg7 /* reg7 */;
+ __le32 reg8 /* reg8 */;
+ __le32 reg9 /* reg9 */;
+ u8 byte7 /* byte7 */;
+ u8 byte8 /* byte8 */;
+ u8 byte9 /* byte9 */;
+ u8 byte10 /* byte10 */;
+ u8 byte11 /* byte11 */;
+ u8 byte12 /* byte12 */;
+ u8 byte13 /* byte13 */;
+ u8 byte14 /* byte14 */;
+ u8 byte15 /* byte15 */;
+ u8 byte16 /* byte16 */;
+ __le16 word11 /* word11 */;
+ __le32 reg10 /* reg10 */;
+ __le32 reg11 /* reg11 */;
+ __le32 reg12 /* reg12 */;
+ __le32 reg13 /* reg13 */;
+ __le32 reg14 /* reg14 */;
+ __le32 reg15 /* reg15 */;
+ __le32 reg16 /* reg16 */;
+ __le32 reg17 /* reg17 */;
+ __le32 reg18 /* reg18 */;
+ __le32 reg19 /* reg19 */;
+ __le16 word12 /* word12 */;
+ __le16 word13 /* word13 */;
+ __le16 word14 /* word14 */;
+ __le16 word15 /* word15 */;
+};
+
+/* The eth storm context for the Tstorm */
+struct tstorm_eth_conn_st_ctx {
+ __le32 reserved[4];
+};
+
+/* The eth storm context for the Mstorm */
+struct mstorm_eth_conn_st_ctx {
+ __le32 reserved[8];
+};
+
+/* The eth storm context for the Ustorm */
+struct ustorm_eth_conn_st_ctx {
+ __le32 reserved[40];
+};
+
+/* eth connection context */
+struct eth_conn_context {
+ struct ystorm_eth_conn_st_ctx ystorm_st_context;
+ struct regpair ystorm_st_padding[2] /* padding */;
+ struct pstorm_eth_conn_st_ctx pstorm_st_context;
+ struct regpair pstorm_st_padding[2] /* padding */;
+ struct xstorm_eth_conn_st_ctx xstorm_st_context;
+ struct xstorm_eth_conn_ag_ctx xstorm_ag_context;
+ struct tstorm_eth_conn_st_ctx tstorm_st_context;
+ struct regpair tstorm_st_padding[2] /* padding */;
+ struct mstorm_eth_conn_st_ctx mstorm_st_context;
+ struct ustorm_eth_conn_st_ctx ustorm_st_context;
+};
+
+enum eth_filter_action {
+ ETH_FILTER_ACTION_REMOVE,
+ ETH_FILTER_ACTION_ADD,
+ ETH_FILTER_ACTION_REPLACE,
+ MAX_ETH_FILTER_ACTION
+};
+
+struct eth_filter_cmd {
+ u8 type /* Filter Type (MAC/VLAN/Pair/VNI) */;
+ u8 vport_id /* the vport id */;
+ u8 action /* filter command action: add/remove/replace */;
+ u8 reserved0;
+ __le32 vni;
+ __le16 mac_lsb;
+ __le16 mac_mid;
+ __le16 mac_msb;
+ __le16 vlan_id;
+};
+
+struct eth_filter_cmd_header {
+ u8 rx;
+ u8 tx;
+ u8 cmd_cnt;
+ u8 assert_on_error;
+ u8 reserved1[4];
+};
+
+enum eth_filter_type {
+ ETH_FILTER_TYPE_MAC,
+ ETH_FILTER_TYPE_VLAN,
+ ETH_FILTER_TYPE_PAIR,
+ ETH_FILTER_TYPE_INNER_MAC,
+ ETH_FILTER_TYPE_INNER_VLAN,
+ ETH_FILTER_TYPE_INNER_PAIR,
+ ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR,
+ ETH_FILTER_TYPE_MAC_VNI_PAIR,
+ ETH_FILTER_TYPE_VNI,
+ MAX_ETH_FILTER_TYPE
+};
+
+enum eth_ramrod_cmd_id {
+ ETH_RAMROD_UNUSED,
+ ETH_RAMROD_VPORT_START /* VPort Start Ramrod */,
+ ETH_RAMROD_VPORT_UPDATE /* VPort Update Ramrod */,
+ ETH_RAMROD_VPORT_STOP /* VPort Stop Ramrod */,
+ ETH_RAMROD_RX_QUEUE_START /* RX Queue Start Ramrod */,
+ ETH_RAMROD_RX_QUEUE_STOP /* RX Queue Stop Ramrod */,
+ ETH_RAMROD_TX_QUEUE_START /* TX Queue Start Ramrod */,
+ ETH_RAMROD_TX_QUEUE_STOP /* TX Queue Stop Ramrod */,
+ ETH_RAMROD_FILTERS_UPDATE /* Add or Remove Mac/Vlan/Pair filters */,
+ ETH_RAMROD_RX_QUEUE_UPDATE /* RX Queue Update Ramrod */,
+ ETH_RAMROD_RESERVED,
+ ETH_RAMROD_RESERVED2,
+ ETH_RAMROD_RESERVED3,
+ ETH_RAMROD_RESERVED4,
+ ETH_RAMROD_RESERVED5,
+ ETH_RAMROD_RESERVED6,
+ ETH_RAMROD_RESERVED7,
+ ETH_RAMROD_RESERVED8,
+ MAX_ETH_RAMROD_CMD_ID
+};
+
+struct eth_vport_rss_config {
+ __le16 capabilities;
+#define ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY_SHIFT 0
+#define ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY_SHIFT 1
+#define ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY_SHIFT 2
+#define ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY_SHIFT 3
+#define ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY_SHIFT 4
+#define ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY_SHIFT 5
+#define ETH_VPORT_RSS_CONFIG_EN_5_TUPLE_CAPABILITY_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_EN_5_TUPLE_CAPABILITY_SHIFT 6
+#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_TCP_FRAG_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_TCP_FRAG_SHIFT 7
+#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_UDP_FRAG_MASK 0x1
+#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_UDP_FRAG_SHIFT 8
+#define ETH_VPORT_RSS_CONFIG_RESERVED0_MASK 0x7F
+#define ETH_VPORT_RSS_CONFIG_RESERVED0_SHIFT 9
+ u8 rss_id;
+ u8 rss_mode;
+ u8 update_rss_key;
+ u8 update_rss_ind_table;
+ u8 update_rss_capabilities;
+ u8 tbl_size;
+ __le32 reserved2[2];
+ __le16 indirection_table[ETH_RSS_IND_TABLE_ENTRIES_NUM];
+ __le32 rss_key[ETH_RSS_KEY_SIZE_REGS];
+ __le32 reserved3[2];
+};
+
+enum eth_vport_rss_mode {
+ ETH_VPORT_RSS_MODE_DISABLED,
+ ETH_VPORT_RSS_MODE_REGULAR,
+ MAX_ETH_VPORT_RSS_MODE
+};
+
+struct eth_vport_rx_mode {
+ __le16 state;
+#define ETH_VPORT_RX_MODE_UCAST_DROP_ALL_MASK 0x1
+#define ETH_VPORT_RX_MODE_UCAST_DROP_ALL_SHIFT 0
+#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_ALL_MASK 0x1
+#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_ALL_SHIFT 1
+#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED_MASK 0x1
+#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define ETH_VPORT_RX_MODE_MCAST_DROP_ALL_MASK 0x1
+#define ETH_VPORT_RX_MODE_MCAST_DROP_ALL_SHIFT 3
+#define ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL_MASK 0x1
+#define ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL_SHIFT 4
+#define ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL_MASK 0x1
+#define ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL_SHIFT 5
+#define ETH_VPORT_RX_MODE_RESERVED1_MASK 0x3FF
+#define ETH_VPORT_RX_MODE_RESERVED1_SHIFT 6
+ __le16 reserved2[3];
+};
+
+struct eth_vport_tpa_param {
+ u64 reserved[2];
+};
+
+struct eth_vport_tx_mode {
+ __le16 state;
+#define ETH_VPORT_TX_MODE_UCAST_DROP_ALL_MASK 0x1
+#define ETH_VPORT_TX_MODE_UCAST_DROP_ALL_SHIFT 0
+#define ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL_MASK 0x1
+#define ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL_SHIFT 1
+#define ETH_VPORT_TX_MODE_MCAST_DROP_ALL_MASK 0x1
+#define ETH_VPORT_TX_MODE_MCAST_DROP_ALL_SHIFT 2
+#define ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL_MASK 0x1
+#define ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL_SHIFT 3
+#define ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL_MASK 0x1
+#define ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL_SHIFT 4
+#define ETH_VPORT_TX_MODE_RESERVED1_MASK 0x7FF
+#define ETH_VPORT_TX_MODE_RESERVED1_SHIFT 5
+ __le16 reserved2[3];
+};
+
+struct rx_queue_start_ramrod_data {
+ __le16 rx_queue_id;
+ __le16 num_of_pbl_pages;
+ __le16 bd_max_bytes;
+ __le16 sb_id;
+ u8 sb_index;
+ u8 vport_id;
+ u8 default_rss_queue_flg;
+ u8 complete_cqe_flg;
+ u8 complete_event_flg;
+ u8 stats_counter_id;
+ u8 pin_context;
+ u8 pxp_tph_valid_bd;
+ u8 pxp_tph_valid_pkt;
+ u8 pxp_st_hint;
+ __le16 pxp_st_index;
+ u8 reserved[4];
+ struct regpair cqe_pbl_addr;
+ struct regpair bd_base;
+ struct regpair sge_base;
+};
+
+struct rx_queue_stop_ramrod_data {
+ __le16 rx_queue_id;
+ u8 complete_cqe_flg;
+ u8 complete_event_flg;
+ u8 vport_id;
+ u8 reserved[3];
+};
+
+struct rx_queue_update_ramrod_data {
+ __le16 rx_queue_id;
+ u8 complete_cqe_flg;
+ u8 complete_event_flg;
+ u8 init_sge_ring_flg;
+ u8 vport_id;
+ u8 pxp_tph_valid_sge;
+ u8 pxp_st_hint;
+ __le16 pxp_st_index;
+ u8 reserved[6];
+ struct regpair sge_base;
+};
+
+struct tx_queue_start_ramrod_data {
+ __le16 sb_id;
+ u8 sb_index;
+ u8 vport_id;
+ u8 tc;
+ u8 stats_counter_id;
+ __le16 qm_pq_id;
+ u8 flags;
+#define TX_QUEUE_START_RAMROD_DATA_DISABLE_OPPORTUNISTIC_MASK 0x1
+#define TX_QUEUE_START_RAMROD_DATA_DISABLE_OPPORTUNISTIC_SHIFT 0
+#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_PKT_DUP_MASK 0x1
+#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_PKT_DUP_SHIFT 1
+#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_TX_DEST_MASK 0x1
+#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_TX_DEST_SHIFT 2
+#define TX_QUEUE_START_RAMROD_DATA_RESERVED0_MASK 0x1F
+#define TX_QUEUE_START_RAMROD_DATA_RESERVED0_SHIFT 3
+ u8 pin_context;
+ u8 pxp_tph_valid_bd;
+ u8 pxp_tph_valid_pkt;
+ __le16 pxp_st_index;
+ u8 pxp_st_hint;
+ u8 reserved1[3];
+ __le16 queue_zone_id;
+ __le16 test_dup_count;
+ __le16 pbl_size;
+ struct regpair pbl_base_addr;
+};
+
+struct tx_queue_stop_ramrod_data {
+ __le16 reserved[4];
+};
+
+struct vport_filter_update_ramrod_data {
+ struct eth_filter_cmd_header filter_cmd_hdr;
+ struct eth_filter_cmd filter_cmds[ETH_FILTER_RULES_COUNT];
+};
+
+struct vport_start_ramrod_data {
+ u8 vport_id;
+ u8 sw_fid;
+ __le16 mtu;
+ u8 drop_ttl0_en;
+ u8 inner_vlan_removal_en;
+ struct eth_vport_rx_mode rx_mode;
+ struct eth_vport_tx_mode tx_mode;
+ struct eth_vport_tpa_param tpa_param;
+ __le16 sge_buff_size;
+ u8 max_sges_num;
+ u8 tx_switching_en;
+ u8 anti_spoofing_en;
+ u8 default_vlan_en;
+ u8 handle_ptp_pkts;
+ u8 silent_vlan_removal_en;
+ __le16 default_vlan;
+ u8 untagged;
+ u8 reserved[7];
+};
+
+struct vport_stop_ramrod_data {
+ u8 vport_id;
+ u8 reserved[7];
+};
+
+struct vport_update_ramrod_data_cmn {
+ u8 vport_id;
+ u8 update_rx_active_flg;
+ u8 rx_active_flg;
+ u8 update_tx_active_flg;
+ u8 tx_active_flg;
+ u8 update_rx_mode_flg;
+ u8 update_tx_mode_flg;
+ u8 update_approx_mcast_flg;
+ u8 update_rss_flg;
+ u8 update_inner_vlan_removal_en_flg;
+ u8 inner_vlan_removal_en;
+ u8 update_tpa_param_flg;
+ u8 update_tpa_en_flg;
+ u8 update_sge_param_flg;
+ __le16 sge_buff_size;
+ u8 max_sges_num;
+ u8 update_tx_switching_en_flg;
+ u8 tx_switching_en;
+ u8 update_anti_spoofing_en_flg;
+ u8 anti_spoofing_en;
+ u8 update_handle_ptp_pkts;
+ u8 handle_ptp_pkts;
+ u8 update_default_vlan_en_flg;
+ u8 default_vlan_en;
+ u8 update_default_vlan_flg;
+ __le16 default_vlan;
+ u8 update_accept_any_vlan_flg;
+ u8 accept_any_vlan;
+ u8 silent_vlan_removal_en;
+ u8 reserved;
+};
+
+struct vport_update_ramrod_mcast {
+ __le32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS];
+};
+
+struct vport_update_ramrod_data {
+ struct vport_update_ramrod_data_cmn common;
+ struct eth_vport_rx_mode rx_mode;
+ struct eth_vport_tx_mode tx_mode;
+ struct eth_vport_tpa_param tpa_param;
+ struct vport_update_ramrod_mcast approx_mcast;
+ struct eth_vport_rss_config rss_config;
+};
+
+struct mstorm_eth_conn_ag_ctx {
+ u8 byte0 /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define MSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1 /* exist_in_qm0 */
+#define MSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0
+#define MSTORM_ETH_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */
+#define MSTORM_ETH_CONN_AG_CTX_BIT1_SHIFT 1
+#define MSTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* cf0 */
+#define MSTORM_ETH_CONN_AG_CTX_CF0_SHIFT 2
+#define MSTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* cf1 */
+#define MSTORM_ETH_CONN_AG_CTX_CF1_SHIFT 4
+#define MSTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* cf2 */
+#define MSTORM_ETH_CONN_AG_CTX_CF2_SHIFT 6
+ u8 flags1;
+#define MSTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define MSTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 0
+#define MSTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define MSTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 1
+#define MSTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define MSTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 2
+#define MSTORM_ETH_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define MSTORM_ETH_CONN_AG_CTX_RULE0EN_SHIFT 3
+#define MSTORM_ETH_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define MSTORM_ETH_CONN_AG_CTX_RULE1EN_SHIFT 4
+#define MSTORM_ETH_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define MSTORM_ETH_CONN_AG_CTX_RULE2EN_SHIFT 5
+#define MSTORM_ETH_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define MSTORM_ETH_CONN_AG_CTX_RULE3EN_SHIFT 6
+#define MSTORM_ETH_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define MSTORM_ETH_CONN_AG_CTX_RULE4EN_SHIFT 7
+ __le16 word0 /* word0 */;
+ __le16 word1 /* word1 */;
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+};
+
+struct tstorm_eth_conn_ag_ctx {
+ u8 byte0 /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define TSTORM_ETH_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */
+#define TSTORM_ETH_CONN_AG_CTX_BIT0_SHIFT 0
+#define TSTORM_ETH_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */
+#define TSTORM_ETH_CONN_AG_CTX_BIT1_SHIFT 1
+#define TSTORM_ETH_CONN_AG_CTX_BIT2_MASK 0x1 /* bit2 */
+#define TSTORM_ETH_CONN_AG_CTX_BIT2_SHIFT 2
+#define TSTORM_ETH_CONN_AG_CTX_BIT3_MASK 0x1 /* bit3 */
+#define TSTORM_ETH_CONN_AG_CTX_BIT3_SHIFT 3
+#define TSTORM_ETH_CONN_AG_CTX_BIT4_MASK 0x1 /* bit4 */
+#define TSTORM_ETH_CONN_AG_CTX_BIT4_SHIFT 4
+#define TSTORM_ETH_CONN_AG_CTX_BIT5_MASK 0x1 /* bit5 */
+#define TSTORM_ETH_CONN_AG_CTX_BIT5_SHIFT 5
+#define TSTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */
+#define TSTORM_ETH_CONN_AG_CTX_CF0_SHIFT 6
+ u8 flags1;
+#define TSTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */
+#define TSTORM_ETH_CONN_AG_CTX_CF1_SHIFT 0
+#define TSTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */
+#define TSTORM_ETH_CONN_AG_CTX_CF2_SHIFT 2
+#define TSTORM_ETH_CONN_AG_CTX_CF3_MASK 0x3 /* timer_stop_all */
+#define TSTORM_ETH_CONN_AG_CTX_CF3_SHIFT 4
+#define TSTORM_ETH_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */
+#define TSTORM_ETH_CONN_AG_CTX_CF4_SHIFT 6
+ u8 flags2;
+#define TSTORM_ETH_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */
+#define TSTORM_ETH_CONN_AG_CTX_CF5_SHIFT 0
+#define TSTORM_ETH_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */
+#define TSTORM_ETH_CONN_AG_CTX_CF6_SHIFT 2
+#define TSTORM_ETH_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */
+#define TSTORM_ETH_CONN_AG_CTX_CF7_SHIFT 4
+#define TSTORM_ETH_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */
+#define TSTORM_ETH_CONN_AG_CTX_CF8_SHIFT 6
+ u8 flags3;
+#define TSTORM_ETH_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */
+#define TSTORM_ETH_CONN_AG_CTX_CF9_SHIFT 0
+#define TSTORM_ETH_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */
+#define TSTORM_ETH_CONN_AG_CTX_CF10_SHIFT 2
+#define TSTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define TSTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 4
+#define TSTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define TSTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 5
+#define TSTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define TSTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 6
+#define TSTORM_ETH_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */
+#define TSTORM_ETH_CONN_AG_CTX_CF3EN_SHIFT 7
+ u8 flags4;
+#define TSTORM_ETH_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */
+#define TSTORM_ETH_CONN_AG_CTX_CF4EN_SHIFT 0
+#define TSTORM_ETH_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */
+#define TSTORM_ETH_CONN_AG_CTX_CF5EN_SHIFT 1
+#define TSTORM_ETH_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */
+#define TSTORM_ETH_CONN_AG_CTX_CF6EN_SHIFT 2
+#define TSTORM_ETH_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */
+#define TSTORM_ETH_CONN_AG_CTX_CF7EN_SHIFT 3
+#define TSTORM_ETH_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */
+#define TSTORM_ETH_CONN_AG_CTX_CF8EN_SHIFT 4
+#define TSTORM_ETH_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */
+#define TSTORM_ETH_CONN_AG_CTX_CF9EN_SHIFT 5
+#define TSTORM_ETH_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */
+#define TSTORM_ETH_CONN_AG_CTX_CF10EN_SHIFT 6
+#define TSTORM_ETH_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE0EN_SHIFT 7
+ u8 flags5;
+#define TSTORM_ETH_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE1EN_SHIFT 0
+#define TSTORM_ETH_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE2EN_SHIFT 1
+#define TSTORM_ETH_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE3EN_SHIFT 2
+#define TSTORM_ETH_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE4EN_SHIFT 3
+#define TSTORM_ETH_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE5EN_SHIFT 4
+#define TSTORM_ETH_CONN_AG_CTX_RX_BD_EN_MASK 0x1 /* rule6en */
+#define TSTORM_ETH_CONN_AG_CTX_RX_BD_EN_SHIFT 5
+#define TSTORM_ETH_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE7EN_SHIFT 6
+#define TSTORM_ETH_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */
+#define TSTORM_ETH_CONN_AG_CTX_RULE8EN_SHIFT 7
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+ __le32 reg4 /* reg4 */;
+ __le32 reg5 /* reg5 */;
+ __le32 reg6 /* reg6 */;
+ __le32 reg7 /* reg7 */;
+ __le32 reg8 /* reg8 */;
+ u8 byte2 /* byte2 */;
+ u8 byte3 /* byte3 */;
+ __le16 rx_bd_cons /* word0 */;
+ u8 byte4 /* byte4 */;
+ u8 byte5 /* byte5 */;
+ __le16 rx_bd_prod /* word1 */;
+ __le16 word2 /* conn_dpi */;
+ __le16 word3 /* word3 */;
+ __le32 reg9 /* reg9 */;
+ __le32 reg10 /* reg10 */;
+};
+
+struct ustorm_eth_conn_ag_ctx {
+ u8 byte0 /* cdu_validation */;
+ u8 byte1 /* state */;
+ u8 flags0;
+#define USTORM_ETH_CONN_AG_CTX_BIT0_MASK 0x1
+#define USTORM_ETH_CONN_AG_CTX_BIT0_SHIFT 0
+#define USTORM_ETH_CONN_AG_CTX_BIT1_MASK 0x1
+#define USTORM_ETH_CONN_AG_CTX_BIT1_SHIFT 1
+#define USTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */
+#define USTORM_ETH_CONN_AG_CTX_CF0_SHIFT 2
+#define USTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */
+#define USTORM_ETH_CONN_AG_CTX_CF1_SHIFT 4
+#define USTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */
+#define USTORM_ETH_CONN_AG_CTX_CF2_SHIFT 6
+ u8 flags1;
+#define USTORM_ETH_CONN_AG_CTX_CF3_MASK 0x3
+#define USTORM_ETH_CONN_AG_CTX_CF3_SHIFT 0
+#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_MASK 0x3 /* cf4 */
+#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_SHIFT 2
+#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_MASK 0x3 /* cf5 */
+#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_SHIFT 4
+#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_MASK 0x3 /* cf6 */
+#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_SHIFT 6
+ u8 flags2;
+#define USTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */
+#define USTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 0
+#define USTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */
+#define USTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 1
+#define USTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */
+#define USTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 2
+#define USTORM_ETH_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */
+#define USTORM_ETH_CONN_AG_CTX_CF3EN_SHIFT 3
+#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_EN_MASK 0x1 /* cf4en */
+#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_EN_SHIFT 4
+#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_EN_MASK 0x1 /* cf5en */
+#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_EN_SHIFT 5
+#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_EN_MASK 0x1 /* cf6en */
+#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_EN_SHIFT 6
+#define USTORM_ETH_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */
+#define USTORM_ETH_CONN_AG_CTX_RULE0EN_SHIFT 7
+ u8 flags3;
+#define USTORM_ETH_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */
+#define USTORM_ETH_CONN_AG_CTX_RULE1EN_SHIFT 0
+#define USTORM_ETH_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */
+#define USTORM_ETH_CONN_AG_CTX_RULE2EN_SHIFT 1
+#define USTORM_ETH_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */
+#define USTORM_ETH_CONN_AG_CTX_RULE3EN_SHIFT 2
+#define USTORM_ETH_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */
+#define USTORM_ETH_CONN_AG_CTX_RULE4EN_SHIFT 3
+#define USTORM_ETH_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */
+#define USTORM_ETH_CONN_AG_CTX_RULE5EN_SHIFT 4
+#define USTORM_ETH_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */
+#define USTORM_ETH_CONN_AG_CTX_RULE6EN_SHIFT 5
+#define USTORM_ETH_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */
+#define USTORM_ETH_CONN_AG_CTX_RULE7EN_SHIFT 6
+#define USTORM_ETH_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */
+#define USTORM_ETH_CONN_AG_CTX_RULE8EN_SHIFT 7
+ u8 byte2 /* byte2 */;
+ u8 byte3 /* byte3 */;
+ __le16 word0 /* conn_dpi */;
+ __le16 tx_bd_cons /* word1 */;
+ __le32 reg0 /* reg0 */;
+ __le32 reg1 /* reg1 */;
+ __le32 reg2 /* reg2 */;
+ __le32 reg3 /* reg3 */;
+ __le16 tx_drv_bd_cons /* word2 */;
+ __le16 rx_drv_cqe_cons /* word3 */;
+};
+
+struct xstorm_eth_hw_conn_ag_ctx {
+ u8 reserved0 /* cdu_validation */;
+ u8 eth_state /* state */;
+ u8 flags0;
+#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED1_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED1_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED2_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED2_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM3_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM3_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED3_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED3_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED4_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED4_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED5_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED5_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED6_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED6_SHIFT 7
+ u8 flags1;
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED7_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED7_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED8_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED8_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED9_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED9_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_BIT11_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_BIT11_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_BIT12_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_BIT12_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_BIT13_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_BIT13_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_TX_RULE_ACTIVE_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_TX_RULE_ACTIVE_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_ACTIVE_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_ACTIVE_SHIFT 7
+ u8 flags2;
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF0_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF0_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF1_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF1_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF2_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF2_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF3_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF3_SHIFT 6
+ u8 flags3;
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF4_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF4_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF5_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF5_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF6_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF6_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF7_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF7_SHIFT 6
+ u8 flags4;
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF8_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF8_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF9_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF9_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF10_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF10_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF11_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF11_SHIFT 6
+ u8 flags5;
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF12_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF12_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF13_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF13_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF14_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF14_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF15_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF15_SHIFT 6
+ u8 flags6;
+#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_SHIFT 6
+ u8 flags7;
+#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED10_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED10_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF0EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF0EN_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF1EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF1EN_SHIFT 7
+ u8 flags8;
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF2EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF2EN_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF3EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF3EN_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF4EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF4EN_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF5EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF5EN_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF6EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF6EN_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF7EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF7EN_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF8EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF8EN_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF9EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF9EN_SHIFT 7
+ u8 flags9;
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF10EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF10EN_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF11EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF11EN_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF12EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF12EN_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF13EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF13EN_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF14EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF14EN_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF15EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_CF15EN_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_EN_SHIFT 7
+ u8 flags10;
+#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_EN_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_EN_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_EN_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED11_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED11_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_EN_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED12_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED12_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED13_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED13_SHIFT 7
+ u8 flags11;
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED14_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED14_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED15_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED15_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_TX_DEC_RULE_EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_TX_DEC_RULE_EN_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE5EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE5EN_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE6EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE6EN_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE7EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE7EN_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED1_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED1_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE9EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE9EN_SHIFT 7
+ u8 flags12;
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE10EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE10EN_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE11EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE11EN_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED2_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED2_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED3_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED3_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE14EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE14EN_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE15EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE15EN_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE16EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE16EN_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE17EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE17EN_SHIFT 7
+ u8 flags13;
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE18EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE18EN_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE19EN_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_RULE19EN_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED4_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED4_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED5_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED5_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED6_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED6_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED7_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED7_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED8_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED8_SHIFT 6
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED9_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED9_SHIFT 7
+ u8 flags14;
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_USE_EXT_HDR_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_USE_EXT_HDR_SHIFT 0
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_SHIFT 1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_SHIFT 2
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_SHIFT 3
+#define XSTORM_ETH_HW_CONN_AG_CTX_L2_EDPM_ENABLE_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_L2_EDPM_ENABLE_SHIFT 4
+#define XSTORM_ETH_HW_CONN_AG_CTX_ROCE_EDPM_ENABLE_MASK 0x1
+#define XSTORM_ETH_HW_CONN_AG_CTX_ROCE_EDPM_ENABLE_SHIFT 5
+#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_MASK 0x3
+#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_SHIFT 6
+ u8 edpm_event_id /* byte2 */;
+ __le16 physical_q0 /* physical_q0 */;
+ __le16 word1 /* physical_q1 */;
+ __le16 edpm_num_bds /* physical_q2 */;
+ __le16 tx_bd_cons /* word3 */;
+ __le16 tx_bd_prod /* word4 */;
+ __le16 go_to_bd_cons /* word5 */;
+ __le16 conn_dpi /* conn_dpi */;
+};
+
+#define VF_MAX_STATIC 192 /* In case of K2 */
+
+#define MCP_GLOB_PATH_MAX 2
+#define MCP_PORT_MAX 2 /* Global */
+#define MCP_GLOB_PORT_MAX 4 /* Global */
+#define MCP_GLOB_FUNC_MAX 16 /* Global */
+
+typedef u32 offsize_t; /* In DWORDS !!! */
+/* Offset from the beginning of the MCP scratchpad */
+#define OFFSIZE_OFFSET_SHIFT 0
+#define OFFSIZE_OFFSET_MASK 0x0000ffff
+/* Size of specific element (not the whole array if any) */
+#define OFFSIZE_SIZE_SHIFT 16
+#define OFFSIZE_SIZE_MASK 0xffff0000
+
+/* SECTION_OFFSET is calculating the offset in bytes out of offsize */
+#define SECTION_OFFSET(_offsize) ((((_offsize & \
+ OFFSIZE_OFFSET_MASK) >> \
+ OFFSIZE_OFFSET_SHIFT) << 2))
+
+/* QED_SECTION_SIZE is calculating the size in bytes out of offsize */
+#define QED_SECTION_SIZE(_offsize) (((_offsize & \
+ OFFSIZE_SIZE_MASK) >> \
+ OFFSIZE_SIZE_SHIFT) << 2)
+
+/* SECTION_ADDR returns the GRC addr of a section, given offsize and index
+ * within section.
+ */
+#define SECTION_ADDR(_offsize, idx) (MCP_REG_SCRATCH + \
+ SECTION_OFFSET(_offsize) + \
+ (QED_SECTION_SIZE(_offsize) * idx))
+
+/* SECTION_OFFSIZE_ADDR returns the GRC addr to the offsize address.
+ * Use offsetof, since the OFFSETUP collide with the firmware definition
+ */
+#define SECTION_OFFSIZE_ADDR(_pub_base, _section) (_pub_base + \
+ offsetof(struct \
+ mcp_public_data, \
+ sections[_section]))
+/* PHY configuration */
+struct pmm_phy_cfg {
+ u32 speed;
+#define PMM_SPEED_AUTONEG 0
+
+ u32 pause; /* bitmask */
+#define PMM_PAUSE_NONE 0x0
+#define PMM_PAUSE_AUTONEG 0x1
+#define PMM_PAUSE_RX 0x2
+#define PMM_PAUSE_TX 0x4
+
+ u32 adv_speed; /* Default should be the speed_cap_mask */
+ u32 loopback_mode;
+#define PMM_LOOPBACK_NONE 0
+#define PMM_LOOPBACK_INT_PHY 1
+#define PMM_LOOPBACK_EXT_PHY 2
+#define PMM_LOOPBACK_EXT 3
+#define PMM_LOOPBACK_MAC 4
+
+ /* features */
+ u32 feature_config_flags;
+};
+
+struct port_mf_cfg {
+ u32 dynamic_cfg; /* device control channel */
+#define PORT_MF_CFG_OV_TAG_MASK 0x0000ffff
+#define PORT_MF_CFG_OV_TAG_SHIFT 0
+#define PORT_MF_CFG_OV_TAG_DEFAULT PORT_MF_CFG_OV_TAG_MASK
+
+ u32 reserved[1];
+};
+
+/* DO NOT add new fields in the middle
+ * MUST be synced with struct pmm_stats_map
+ */
+struct pmm_stats {
+ u64 r64; /* 0x00 (Offset 0x00 ) RX 64-byte frame counter*/
+ u64 r127; /* 0x01 (Offset 0x08 ) RX 65 to 127 byte frame counter*/
+ u64 r255;
+ u64 r511;
+ u64 r1023;
+ u64 r1518;
+ u64 r1522;
+ u64 r2047;
+ u64 r4095;
+ u64 r9216;
+ u64 r16383;
+ u64 rfcs; /* 0x0F (Offset 0x58 ) RX FCS error frame counter*/
+ u64 rxcf; /* 0x10 (Offset 0x60 ) RX control frame counter*/
+ u64 rxpf; /* 0x11 (Offset 0x68 ) RX pause frame counter*/
+ u64 rxpp; /* 0x12 (Offset 0x70 ) RX PFC frame counter*/
+ u64 raln; /* 0x16 (Offset 0x78 ) RX alignment error counter*/
+ u64 rfcr; /* 0x19 (Offset 0x80 ) RX false carrier counter */
+ u64 rovr; /* 0x1A (Offset 0x88 ) RX oversized frame counter*/
+ u64 rjbr; /* 0x1B (Offset 0x90 ) RX jabber frame counter */
+ u64 rund; /* 0x34 (Offset 0x98 ) RX undersized frame counter */
+ u64 rfrg; /* 0x35 (Offset 0xa0 ) RX fragment counter */
+ u64 t64; /* 0x40 (Offset 0xa8 ) TX 64-byte frame counter */
+ u64 t127;
+ u64 t255;
+ u64 t511;
+ u64 t1023;
+ u64 t1518;
+ u64 t2047;
+ u64 t4095;
+ u64 t9216;
+ u64 t16383;
+ u64 txpf; /* 0x50 (Offset 0xf8 ) TX pause frame counter */
+ u64 txpp; /* 0x51 (Offset 0x100) TX PFC frame counter */
+ u64 tlpiec;
+ u64 tncl;
+ u64 rbyte; /* 0x3d (Offset 0x118) RX byte counter */
+ u64 rxuca; /* 0x0c (Offset 0x120) RX UC frame counter */
+ u64 rxmca; /* 0x0d (Offset 0x128) RX MC frame counter */
+ u64 rxbca; /* 0x0e (Offset 0x130) RX BC frame counter */
+ u64 rxpok;
+ u64 tbyte; /* 0x6f (Offset 0x140) TX byte counter */
+ u64 txuca; /* 0x4d (Offset 0x148) TX UC frame counter */
+ u64 txmca; /* 0x4e (Offset 0x150) TX MC frame counter */
+ u64 txbca; /* 0x4f (Offset 0x158) TX BC frame counter */
+ u64 txcf; /* 0x54 (Offset 0x160) TX control frame counter */
+};
+
+struct brb_stats {
+ u64 brb_truncate[8];
+ u64 brb_discard[8];
+};
+
+struct port_stats {
+ struct brb_stats brb;
+ struct pmm_stats pmm;
+};
+
+#define CMT_TEAM0 0
+#define CMT_TEAM1 1
+#define CMT_TEAM_MAX 2
+
+struct couple_mode_teaming {
+ u8 port_cmt[MCP_GLOB_PORT_MAX];
+#define PORT_CMT_IN_TEAM BIT(0)
+
+#define PORT_CMT_PORT_ROLE BIT(1)
+#define PORT_CMT_PORT_INACTIVE (0 << 1)
+#define PORT_CMT_PORT_ACTIVE BIT(1)
+
+#define PORT_CMT_TEAM_MASK BIT(2)
+#define PORT_CMT_TEAM0 (0 << 2)
+#define PORT_CMT_TEAM1 BIT(2)
+};
+
+/**************************************
+* LLDP and DCBX HSI structures
+**************************************/
+#define LLDP_CHASSIS_ID_STAT_LEN 4
+#define LLDP_PORT_ID_STAT_LEN 4
+#define DCBX_MAX_APP_PROTOCOL 32
+#define MAX_SYSTEM_LLDP_TLV_DATA 32
+
+enum lldp_agent_e {
+ LLDP_NEAREST_BRIDGE = 0,
+ LLDP_NEAREST_NON_TPMR_BRIDGE,
+ LLDP_NEAREST_CUSTOMER_BRIDGE,
+ LLDP_MAX_LLDP_AGENTS
+};
+
+struct lldp_config_params_s {
+ u32 config;
+#define LLDP_CONFIG_TX_INTERVAL_MASK 0x000000ff
+#define LLDP_CONFIG_TX_INTERVAL_SHIFT 0
+#define LLDP_CONFIG_HOLD_MASK 0x00000f00
+#define LLDP_CONFIG_HOLD_SHIFT 8
+#define LLDP_CONFIG_MAX_CREDIT_MASK 0x0000f000
+#define LLDP_CONFIG_MAX_CREDIT_SHIFT 12
+#define LLDP_CONFIG_ENABLE_RX_MASK 0x40000000
+#define LLDP_CONFIG_ENABLE_RX_SHIFT 30
+#define LLDP_CONFIG_ENABLE_TX_MASK 0x80000000
+#define LLDP_CONFIG_ENABLE_TX_SHIFT 31
+ u32 local_chassis_id[LLDP_CHASSIS_ID_STAT_LEN];
+ u32 local_port_id[LLDP_PORT_ID_STAT_LEN];
+};
+
+struct lldp_status_params_s {
+ u32 prefix_seq_num;
+ u32 status; /* TBD */
+
+ /* Holds remote Chassis ID TLV header, subtype and 9B of payload. */
+ u32 peer_chassis_id[LLDP_CHASSIS_ID_STAT_LEN];
+
+ /* Holds remote Port ID TLV header, subtype and 9B of payload. */
+ u32 peer_port_id[LLDP_PORT_ID_STAT_LEN];
+ u32 suffix_seq_num;
+};
+
+struct dcbx_ets_feature {
+ u32 flags;
+#define DCBX_ETS_ENABLED_MASK 0x00000001
+#define DCBX_ETS_ENABLED_SHIFT 0
+#define DCBX_ETS_WILLING_MASK 0x00000002
+#define DCBX_ETS_WILLING_SHIFT 1
+#define DCBX_ETS_ERROR_MASK 0x00000004
+#define DCBX_ETS_ERROR_SHIFT 2
+#define DCBX_ETS_CBS_MASK 0x00000008
+#define DCBX_ETS_CBS_SHIFT 3
+#define DCBX_ETS_MAX_TCS_MASK 0x000000f0
+#define DCBX_ETS_MAX_TCS_SHIFT 4
+ u32 pri_tc_tbl[1];
+#define DCBX_ISCSI_OOO_TC 4
+#define NIG_ETS_ISCSI_OOO_CLIENT_OFFSET (DCBX_ISCSI_OOO_TC + 1)
+ u32 tc_bw_tbl[2];
+ u32 tc_tsa_tbl[2];
+#define DCBX_ETS_TSA_STRICT 0
+#define DCBX_ETS_TSA_CBS 1
+#define DCBX_ETS_TSA_ETS 2
+};
+
+struct dcbx_app_priority_entry {
+ u32 entry;
+#define DCBX_APP_PRI_MAP_MASK 0x000000ff
+#define DCBX_APP_PRI_MAP_SHIFT 0
+#define DCBX_APP_PRI_0 0x01
+#define DCBX_APP_PRI_1 0x02
+#define DCBX_APP_PRI_2 0x04
+#define DCBX_APP_PRI_3 0x08
+#define DCBX_APP_PRI_4 0x10
+#define DCBX_APP_PRI_5 0x20
+#define DCBX_APP_PRI_6 0x40
+#define DCBX_APP_PRI_7 0x80
+#define DCBX_APP_SF_MASK 0x00000300
+#define DCBX_APP_SF_SHIFT 8
+#define DCBX_APP_SF_ETHTYPE 0
+#define DCBX_APP_SF_PORT 1
+#define DCBX_APP_PROTOCOL_ID_MASK 0xffff0000
+#define DCBX_APP_PROTOCOL_ID_SHIFT 16
+};
+
+/* FW structure in BE */
+struct dcbx_app_priority_feature {
+ u32 flags;
+#define DCBX_APP_ENABLED_MASK 0x00000001
+#define DCBX_APP_ENABLED_SHIFT 0
+#define DCBX_APP_WILLING_MASK 0x00000002
+#define DCBX_APP_WILLING_SHIFT 1
+#define DCBX_APP_ERROR_MASK 0x00000004
+#define DCBX_APP_ERROR_SHIFT 2
+/* Not in use
+ * #define DCBX_APP_DEFAULT_PRI_MASK 0x00000f00
+ * #define DCBX_APP_DEFAULT_PRI_SHIFT 8
+ */
+#define DCBX_APP_MAX_TCS_MASK 0x0000f000
+#define DCBX_APP_MAX_TCS_SHIFT 12
+#define DCBX_APP_NUM_ENTRIES_MASK 0x00ff0000
+#define DCBX_APP_NUM_ENTRIES_SHIFT 16
+ struct dcbx_app_priority_entry app_pri_tbl[DCBX_MAX_APP_PROTOCOL];
+};
+
+/* FW structure in BE */
+struct dcbx_features {
+ /* PG feature */
+ struct dcbx_ets_feature ets;
+
+ /* PFC feature */
+ u32 pfc;
+#define DCBX_PFC_PRI_EN_BITMAP_MASK 0x000000ff
+#define DCBX_PFC_PRI_EN_BITMAP_SHIFT 0
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_0 0x01
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_1 0x02
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_2 0x04
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_3 0x08
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_4 0x10
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_5 0x20
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_6 0x40
+#define DCBX_PFC_PRI_EN_BITMAP_PRI_7 0x80
+
+#define DCBX_PFC_FLAGS_MASK 0x0000ff00
+#define DCBX_PFC_FLAGS_SHIFT 8
+#define DCBX_PFC_CAPS_MASK 0x00000f00
+#define DCBX_PFC_CAPS_SHIFT 8
+#define DCBX_PFC_MBC_MASK 0x00004000
+#define DCBX_PFC_MBC_SHIFT 14
+#define DCBX_PFC_WILLING_MASK 0x00008000
+#define DCBX_PFC_WILLING_SHIFT 15
+#define DCBX_PFC_ENABLED_MASK 0x00010000
+#define DCBX_PFC_ENABLED_SHIFT 16
+#define DCBX_PFC_ERROR_MASK 0x00020000
+#define DCBX_PFC_ERROR_SHIFT 17
+
+ /* APP feature */
+ struct dcbx_app_priority_feature app;
+};
+
+struct dcbx_local_params {
+ u32 config;
+#define DCBX_CONFIG_VERSION_MASK 0x00000003
+#define DCBX_CONFIG_VERSION_SHIFT 0
+#define DCBX_CONFIG_VERSION_DISABLED 0
+#define DCBX_CONFIG_VERSION_IEEE 1
+#define DCBX_CONFIG_VERSION_CEE 2
+
+ u32 flags;
+ struct dcbx_features features;
+};
+
+struct dcbx_mib {
+ u32 prefix_seq_num;
+ u32 flags;
+ struct dcbx_features features;
+ u32 suffix_seq_num;
+};
+
+struct lldp_system_tlvs_buffer_s {
+ u16 valid;
+ u16 length;
+ u32 data[MAX_SYSTEM_LLDP_TLV_DATA];
+};
+
+/**************************************/
+/* */
+/* P U B L I C G L O B A L */
+/* */
+/**************************************/
+struct public_global {
+ u32 max_path;
+#define MAX_PATH_BIG_BEAR 2
+#define MAX_PATH_K2 1
+ u32 max_ports;
+#define MODE_1P 1
+#define MODE_2P 2
+#define MODE_3P 3
+#define MODE_4P 4
+ u32 debug_mb_offset;
+ u32 phymod_dbg_mb_offset;
+ struct couple_mode_teaming cmt;
+ s32 internal_temperature;
+ u32 mfw_ver;
+ u32 running_bundle_id;
+};
+
+/**************************************/
+/* */
+/* P U B L I C P A T H */
+/* */
+/**************************************/
+
+/****************************************************************************
+* Shared Memory 2 Region *
+****************************************************************************/
+/* The fw_flr_ack is actually built in the following way: */
+/* 8 bit: PF ack */
+/* 128 bit: VF ack */
+/* 8 bit: ios_dis_ack */
+/* In order to maintain endianity in the mailbox hsi, we want to keep using */
+/* u32. The fw must have the VF right after the PF since this is how it */
+/* access arrays(it expects always the VF to reside after the PF, and that */
+/* makes the calculation much easier for it. ) */
+/* In order to answer both limitations, and keep the struct small, the code */
+/* will abuse the structure defined here to achieve the actual partition */
+/* above */
+/****************************************************************************/
+struct fw_flr_mb {
+ u32 aggint;
+ u32 opgen_addr;
+ u32 accum_ack; /* 0..15:PF, 16..207:VF, 256..271:IOV_DIS */
+#define ACCUM_ACK_PF_BASE 0
+#define ACCUM_ACK_PF_SHIFT 0
+
+#define ACCUM_ACK_VF_BASE 8
+#define ACCUM_ACK_VF_SHIFT 3
+
+#define ACCUM_ACK_IOV_DIS_BASE 256
+#define ACCUM_ACK_IOV_DIS_SHIFT 8
+};
+
+struct public_path {
+ struct fw_flr_mb flr_mb;
+ u32 mcp_vf_disabled[VF_MAX_STATIC / 32];
+
+ u32 process_kill;
+#define PROCESS_KILL_COUNTER_MASK 0x0000ffff
+#define PROCESS_KILL_COUNTER_SHIFT 0
+#define PROCESS_KILL_GLOB_AEU_BIT_MASK 0xffff0000
+#define PROCESS_KILL_GLOB_AEU_BIT_SHIFT 16
+#define GLOBAL_AEU_BIT(aeu_reg_id, aeu_bit) (aeu_reg_id * 32 + aeu_bit)
+};
+
+/**************************************/
+/* */
+/* P U B L I C P O R T */
+/* */
+/**************************************/
+
+/****************************************************************************
+* Driver <-> FW Mailbox *
+****************************************************************************/
+
+struct public_port {
+ u32 validity_map; /* 0x0 (4*2 = 0x8) */
+
+ /* validity bits */
+#define MCP_VALIDITY_PCI_CFG 0x00100000
+#define MCP_VALIDITY_MB 0x00200000
+#define MCP_VALIDITY_DEV_INFO 0x00400000
+#define MCP_VALIDITY_RESERVED 0x00000007
+
+ /* One licensing bit should be set */
+#define MCP_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038
+#define MCP_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008
+#define MCP_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010
+#define MCP_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020
+
+ /* Active MFW */
+#define MCP_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000
+#define MCP_VALIDITY_ACTIVE_MFW_MASK 0x000001c0
+#define MCP_VALIDITY_ACTIVE_MFW_NCSI 0x00000040
+#define MCP_VALIDITY_ACTIVE_MFW_NONE 0x000001c0
+
+ u32 link_status;
+#define LINK_STATUS_LINK_UP \
+ 0x00000001
+#define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001e
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD BIT(1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (2 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_10G (3 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_20G (4 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_40G (5 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_50G (6 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_100G (7 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_25G (8 << 1)
+
+#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020
+
+#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040
+#define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080
+
+#define LINK_STATUS_PFC_ENABLED \
+ 0x00000100
+#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200
+#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400
+#define LINK_STATUS_LINK_PARTNER_10G_CAPABLE 0x00000800
+#define LINK_STATUS_LINK_PARTNER_20G_CAPABLE 0x00001000
+#define LINK_STATUS_LINK_PARTNER_40G_CAPABLE 0x00002000
+#define LINK_STATUS_LINK_PARTNER_50G_CAPABLE 0x00004000
+#define LINK_STATUS_LINK_PARTNER_100G_CAPABLE 0x00008000
+#define LINK_STATUS_LINK_PARTNER_25G_CAPABLE 0x00010000
+
+#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000
+#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0 << 18)
+#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE BIT(18)
+#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2 << 18)
+#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3 << 18)
+
+#define LINK_STATUS_SFP_TX_FAULT \
+ 0x00100000
+#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00200000
+#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00400000
+
+ u32 link_status1;
+ u32 ext_phy_fw_version;
+ u32 drv_phy_cfg_addr;
+
+ u32 port_stx;
+
+ u32 stat_nig_timer;
+
+ struct port_mf_cfg port_mf_config;
+ struct port_stats stats;
+
+ u32 media_type;
+#define MEDIA_UNSPECIFIED 0x0
+#define MEDIA_SFPP_10G_FIBER 0x1
+#define MEDIA_XFP_FIBER 0x2
+#define MEDIA_DA_TWINAX 0x3
+#define MEDIA_BASE_T 0x4
+#define MEDIA_SFP_1G_FIBER 0x5
+#define MEDIA_KR 0xf0
+#define MEDIA_NOT_PRESENT 0xff
+
+ u32 lfa_status;
+#define LFA_LINK_FLAP_REASON_OFFSET 0
+#define LFA_LINK_FLAP_REASON_MASK 0x000000ff
+#define LFA_NO_REASON (0 << 0)
+#define LFA_LINK_DOWN BIT(0)
+#define LFA_FORCE_INIT BIT(1)
+#define LFA_LOOPBACK_MISMATCH BIT(2)
+#define LFA_SPEED_MISMATCH BIT(3)
+#define LFA_FLOW_CTRL_MISMATCH BIT(4)
+#define LFA_ADV_SPEED_MISMATCH BIT(5)
+#define LINK_FLAP_AVOIDANCE_COUNT_OFFSET 8
+#define LINK_FLAP_AVOIDANCE_COUNT_MASK 0x0000ff00
+#define LINK_FLAP_COUNT_OFFSET 16
+#define LINK_FLAP_COUNT_MASK 0x00ff0000
+
+ u32 link_change_count;
+
+ /* LLDP params */
+ struct lldp_config_params_s lldp_config_params[
+ LLDP_MAX_LLDP_AGENTS];
+ struct lldp_status_params_s lldp_status_params[
+ LLDP_MAX_LLDP_AGENTS];
+ struct lldp_system_tlvs_buffer_s system_lldp_tlvs_buf;
+
+ /* DCBX related MIB */
+ struct dcbx_local_params local_admin_dcbx_mib;
+ struct dcbx_mib remote_dcbx_mib;
+ struct dcbx_mib operational_dcbx_mib;
+};
+
+/**************************************/
+/* */
+/* P U B L I C F U N C */
+/* */
+/**************************************/
+
+struct public_func {
+ u32 iscsi_boot_signature;
+ u32 iscsi_boot_block_offset;
+
+ u32 reserved[8];
+
+ u32 config;
+
+ /* E/R/I/D */
+ /* function 0 of each port cannot be hidden */
+#define FUNC_MF_CFG_FUNC_HIDE 0x00000001
+#define FUNC_MF_CFG_PAUSE_ON_HOST_RING 0x00000002
+#define FUNC_MF_CFG_PAUSE_ON_HOST_RING_SHIFT 0x00000001
+
+#define FUNC_MF_CFG_PROTOCOL_MASK 0x000000f0
+#define FUNC_MF_CFG_PROTOCOL_SHIFT 4
+#define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000000
+#define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000010
+#define FUNC_MF_CFG_PROTOCOL_FCOE 0x00000020
+#define FUNC_MF_CFG_PROTOCOL_ROCE 0x00000030
+#define FUNC_MF_CFG_PROTOCOL_MAX 0x00000030
+
+ /* MINBW, MAXBW */
+ /* value range - 0..100, increments in 1 % */
+#define FUNC_MF_CFG_MIN_BW_MASK 0x0000ff00
+#define FUNC_MF_CFG_MIN_BW_SHIFT 8
+#define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000
+#define FUNC_MF_CFG_MAX_BW_MASK 0x00ff0000
+#define FUNC_MF_CFG_MAX_BW_SHIFT 16
+#define FUNC_MF_CFG_MAX_BW_DEFAULT 0x00640000
+
+ u32 status;
+#define FUNC_STATUS_VLINK_DOWN 0x00000001
+
+ u32 mac_upper; /* MAC */
+#define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff
+#define FUNC_MF_CFG_UPPERMAC_SHIFT 0
+#define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK
+ u32 mac_lower;
+#define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff
+
+ u32 fcoe_wwn_port_name_upper;
+ u32 fcoe_wwn_port_name_lower;
+
+ u32 fcoe_wwn_node_name_upper;
+ u32 fcoe_wwn_node_name_lower;
+
+ u32 ovlan_stag; /* tags */
+#define FUNC_MF_CFG_OV_STAG_MASK 0x0000ffff
+#define FUNC_MF_CFG_OV_STAG_SHIFT 0
+#define FUNC_MF_CFG_OV_STAG_DEFAULT FUNC_MF_CFG_OV_STAG_MASK
+
+ u32 pf_allocation; /* vf per pf */
+
+ u32 preserve_data; /* Will be used bt CCM */
+
+ u32 driver_last_activity_ts;
+
+ u32 drv_ack_vf_disabled[VF_MAX_STATIC / 32]; /* 0x0044 */
+
+ u32 drv_id;
+#define DRV_ID_PDA_COMP_VER_MASK 0x0000ffff
+#define DRV_ID_PDA_COMP_VER_SHIFT 0
+
+#define DRV_ID_MCP_HSI_VER_MASK 0x00ff0000
+#define DRV_ID_MCP_HSI_VER_SHIFT 16
+#define DRV_ID_MCP_HSI_VER_CURRENT BIT(DRV_ID_MCP_HSI_VER_SHIFT)
+
+#define DRV_ID_DRV_TYPE_MASK 0xff000000
+#define DRV_ID_DRV_TYPE_SHIFT 24
+#define DRV_ID_DRV_TYPE_UNKNOWN (0 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_LINUX BIT(DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_WINDOWS (2 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_DIAG (3 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_PREBOOT (4 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_SOLARIS (5 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_VMWARE (6 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_FREEBSD (7 << DRV_ID_DRV_TYPE_SHIFT)
+#define DRV_ID_DRV_TYPE_AIX (8 << DRV_ID_DRV_TYPE_SHIFT)
+};
+
+/**************************************/
+/* */
+/* P U B L I C M B */
+/* */
+/**************************************/
+/* This is the only section that the driver can write to, and each */
+/* Basically each driver request to set feature parameters,
+ * will be done using a different command, which will be linked
+ * to a specific data structure from the union below.
+ * For huge strucuture, the common blank structure should be used.
+ */
+
+struct mcp_mac {
+ u32 mac_upper; /* Upper 16 bits are always zeroes */
+ u32 mac_lower;
+};
+
+struct mcp_val64 {
+ u32 lo;
+ u32 hi;
+};
+
+struct mcp_file_att {
+ u32 nvm_start_addr;
+ u32 len;
+};
+
+#define MCP_DRV_VER_STR_SIZE 16
+#define MCP_DRV_VER_STR_SIZE_DWORD (MCP_DRV_VER_STR_SIZE / sizeof(u32))
+#define MCP_DRV_NVM_BUF_LEN 32
+struct drv_version_stc {
+ u32 version;
+ u8 name[MCP_DRV_VER_STR_SIZE - 4];
+};
+
+union drv_union_data {
+ u32 ver_str[MCP_DRV_VER_STR_SIZE_DWORD];
+ struct mcp_mac wol_mac;
+
+ struct pmm_phy_cfg drv_phy_cfg;
+
+ struct mcp_val64 val64; /* For PHY / AVS commands */
+
+ u8 raw_data[MCP_DRV_NVM_BUF_LEN];
+
+ struct mcp_file_att file_att;
+
+ u32 ack_vf_disabled[VF_MAX_STATIC / 32];
+
+ struct drv_version_stc drv_version;
+};
+
+struct public_drv_mb {
+ u32 drv_mb_header;
+#define DRV_MSG_CODE_MASK 0xffff0000
+#define DRV_MSG_CODE_LOAD_REQ 0x10000000
+#define DRV_MSG_CODE_LOAD_DONE 0x11000000
+#define DRV_MSG_CODE_UNLOAD_REQ 0x20000000
+#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000
+#define DRV_MSG_CODE_INIT_PHY 0x22000000
+ /* Params - FORCE - Reinitialize the link regardless of LFA */
+ /* - DONT_CARE - Don't flap the link if up */
+#define DRV_MSG_CODE_LINK_RESET 0x23000000
+
+#define DRV_MSG_CODE_SET_LLDP 0x24000000
+#define DRV_MSG_CODE_SET_DCBX 0x25000000
+
+#define DRV_MSG_CODE_NIG_DRAIN 0x30000000
+
+#define DRV_MSG_CODE_INITIATE_FLR 0x02000000
+#define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
+#define DRV_MSG_CODE_CFG_VF_MSIX 0xc0010000
+#define DRV_MSG_CODE_NVM_PUT_FILE_BEGIN 0x00010000
+#define DRV_MSG_CODE_NVM_PUT_FILE_DATA 0x00020000
+#define DRV_MSG_CODE_NVM_GET_FILE_ATT 0x00030000
+#define DRV_MSG_CODE_NVM_READ_NVRAM 0x00050000
+#define DRV_MSG_CODE_NVM_WRITE_NVRAM 0x00060000
+#define DRV_MSG_CODE_NVM_DEL_FILE 0x00080000
+#define DRV_MSG_CODE_MCP_RESET 0x00090000
+#define DRV_MSG_CODE_SET_SECURE_MODE 0x000a0000
+#define DRV_MSG_CODE_PHY_RAW_READ 0x000b0000
+#define DRV_MSG_CODE_PHY_RAW_WRITE 0x000c0000
+#define DRV_MSG_CODE_PHY_CORE_READ 0x000d0000
+#define DRV_MSG_CODE_PHY_CORE_WRITE 0x000e0000
+#define DRV_MSG_CODE_SET_VERSION 0x000f0000
+
+#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
+
+ u32 drv_mb_param;
+
+ /* UNLOAD_REQ params */
+#define DRV_MB_PARAM_UNLOAD_WOL_UNKNOWN 0x00000000
+#define DRV_MB_PARAM_UNLOAD_WOL_MCP 0x00000001
+#define DRV_MB_PARAM_UNLOAD_WOL_DISABLED 0x00000002
+#define DRV_MB_PARAM_UNLOAD_WOL_ENABLED 0x00000003
+
+ /* UNLOAD_DONE_params */
+#define DRV_MB_PARAM_UNLOAD_NON_D3_POWER 0x00000001
+
+ /* INIT_PHY params */
+#define DRV_MB_PARAM_INIT_PHY_FORCE 0x00000001
+#define DRV_MB_PARAM_INIT_PHY_DONT_CARE 0x00000002
+
+ /* LLDP / DCBX params*/
+#define DRV_MB_PARAM_LLDP_SEND_MASK 0x00000001
+#define DRV_MB_PARAM_LLDP_SEND_SHIFT 0
+#define DRV_MB_PARAM_LLDP_AGENT_MASK 0x00000006
+#define DRV_MB_PARAM_LLDP_AGENT_SHIFT 1
+#define DRV_MB_PARAM_DCBX_NOTIFY_MASK 0x00000008
+#define DRV_MB_PARAM_DCBX_NOTIFY_SHIFT 3
+
+#define DRV_MB_PARAM_NIG_DRAIN_PERIOD_MS_MASK 0x000000FF
+#define DRV_MB_PARAM_NIG_DRAIN_PERIOD_MS_SHIFT 0
+
+#define DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MFW 0x1
+#define DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_IMAGE 0x2
+
+#define DRV_MB_PARAM_NVM_OFFSET_SHIFT 0
+#define DRV_MB_PARAM_NVM_OFFSET_MASK 0x00FFFFFF
+#define DRV_MB_PARAM_NVM_LEN_SHIFT 24
+#define DRV_MB_PARAM_NVM_LEN_MASK 0xFF000000
+
+#define DRV_MB_PARAM_PHY_ADDR_SHIFT 0
+#define DRV_MB_PARAM_PHY_ADDR_MASK 0x1FF0FFFF
+#define DRV_MB_PARAM_PHY_LANE_SHIFT 16
+#define DRV_MB_PARAM_PHY_LANE_MASK 0x000F0000
+#define DRV_MB_PARAM_PHY_SELECT_PORT_SHIFT 29
+#define DRV_MB_PARAM_PHY_SELECT_PORT_MASK 0x20000000
+#define DRV_MB_PARAM_PHY_PORT_SHIFT 30
+#define DRV_MB_PARAM_PHY_PORT_MASK 0xc0000000
+
+/* configure vf MSIX params*/
+#define DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT 0
+#define DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK 0x000000FF
+#define DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT 8
+#define DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK 0x0000FF00
+
+ u32 fw_mb_header;
+#define FW_MSG_CODE_MASK 0xffff0000
+#define FW_MSG_CODE_DRV_LOAD_ENGINE 0x10100000
+#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
+#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
+#define FW_MSG_CODE_DRV_LOAD_REFUSED_PDA 0x10200000
+#define FW_MSG_CODE_DRV_LOAD_REFUSED_HSI 0x10210000
+#define FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG 0x10220000
+#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
+#define FW_MSG_CODE_DRV_UNLOAD_ENGINE 0x20110000
+#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20120000
+#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20130000
+#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000
+#define FW_MSG_CODE_INIT_PHY_DONE 0x21200000
+#define FW_MSG_CODE_INIT_PHY_ERR_INVALID_ARGS 0x21300000
+#define FW_MSG_CODE_LINK_RESET_DONE 0x23000000
+#define FW_MSG_CODE_SET_LLDP_DONE 0x24000000
+#define FW_MSG_CODE_SET_LLDP_UNSUPPORTED_AGENT 0x24010000
+#define FW_MSG_CODE_SET_DCBX_DONE 0x25000000
+#define FW_MSG_CODE_NIG_DRAIN_DONE 0x30000000
+#define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000
+#define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE 0xb0010000
+#define FW_MSG_CODE_FLR_ACK 0x02000000
+#define FW_MSG_CODE_FLR_NACK 0x02100000
+
+#define FW_MSG_CODE_NVM_OK 0x00010000
+#define FW_MSG_CODE_NVM_INVALID_MODE 0x00020000
+#define FW_MSG_CODE_NVM_PREV_CMD_WAS_NOT_FINISHED 0x00030000
+#define FW_MSG_CODE_NVM_FAILED_TO_ALLOCATE_PAGE 0x00040000
+#define FW_MSG_CODE_NVM_INVALID_DIR_FOUND 0x00050000
+#define FW_MSG_CODE_NVM_PAGE_NOT_FOUND 0x00060000
+#define FW_MSG_CODE_NVM_FAILED_PARSING_BNDLE_HEADER 0x00070000
+#define FW_MSG_CODE_NVM_FAILED_PARSING_IMAGE_HEADER 0x00080000
+#define FW_MSG_CODE_NVM_PARSING_OUT_OF_SYNC 0x00090000
+#define FW_MSG_CODE_NVM_FAILED_UPDATING_DIR 0x000a0000
+#define FW_MSG_CODE_NVM_FAILED_TO_FREE_PAGE 0x000b0000
+#define FW_MSG_CODE_NVM_FILE_NOT_FOUND 0x000c0000
+#define FW_MSG_CODE_NVM_OPERATION_FAILED 0x000d0000
+#define FW_MSG_CODE_NVM_FAILED_UNALIGNED 0x000e0000
+#define FW_MSG_CODE_NVM_BAD_OFFSET 0x000f0000
+#define FW_MSG_CODE_NVM_BAD_SIGNATURE 0x00100000
+#define FW_MSG_CODE_NVM_FILE_READ_ONLY 0x00200000
+#define FW_MSG_CODE_NVM_UNKNOWN_FILE 0x00300000
+#define FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK 0x00400000
+#define FW_MSG_CODE_MCP_RESET_REJECT 0x00600000
+#define FW_MSG_CODE_PHY_OK 0x00110000
+#define FW_MSG_CODE_PHY_ERROR 0x00120000
+#define FW_MSG_CODE_SET_SECURE_MODE_ERROR 0x00130000
+#define FW_MSG_CODE_SET_SECURE_MODE_OK 0x00140000
+#define FW_MSG_MODE_PHY_PRIVILEGE_ERROR 0x00150000
+
+#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
+
+ u32 fw_mb_param;
+
+ u32 drv_pulse_mb;
+#define DRV_PULSE_SEQ_MASK 0x00007fff
+#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000
+#define DRV_PULSE_ALWAYS_ALIVE 0x00008000
+ u32 mcp_pulse_mb;
+#define MCP_PULSE_SEQ_MASK 0x00007fff
+#define MCP_PULSE_ALWAYS_ALIVE 0x00008000
+#define MCP_EVENT_MASK 0xffff0000
+#define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000
+
+ union drv_union_data union_data;
+};
+
+/* MFW - DRV MB */
+/**********************************************************************
+* Description
+* Incremental Aggregative
+* 8-bit MFW counter per message
+* 8-bit ack-counter per message
+* Capabilities
+* Provides up to 256 aggregative message per type
+* Provides 4 message types in dword
+* Message type pointers to byte offset
+* Backward Compatibility by using sizeof for the counters.
+* No lock requires for 32bit messages
+* Limitations:
+* In case of messages greater than 32bit, a dedicated mechanism(e.g lock)
+* is required to prevent data corruption.
+**********************************************************************/
+enum MFW_DRV_MSG_TYPE {
+ MFW_DRV_MSG_LINK_CHANGE,
+ MFW_DRV_MSG_FLR_FW_ACK_FAILED,
+ MFW_DRV_MSG_VF_DISABLED,
+ MFW_DRV_MSG_LLDP_DATA_UPDATED,
+ MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED,
+ MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED,
+ MFW_DRV_MSG_ERROR_RECOVERY,
+ MFW_DRV_MSG_MAX
+};
+
+#define MFW_DRV_MSG_MAX_DWORDS(msgs) (((msgs - 1) >> 2) + 1)
+#define MFW_DRV_MSG_DWORD(msg_id) (msg_id >> 2)
+#define MFW_DRV_MSG_OFFSET(msg_id) ((msg_id & 0x3) << 3)
+#define MFW_DRV_MSG_MASK(msg_id) (0xff << MFW_DRV_MSG_OFFSET(msg_id))
+
+struct public_mfw_mb {
+ u32 sup_msgs;
+ u32 msg[MFW_DRV_MSG_MAX_DWORDS(MFW_DRV_MSG_MAX)];
+ u32 ack[MFW_DRV_MSG_MAX_DWORDS(MFW_DRV_MSG_MAX)];
+};
+
+/**************************************/
+/* */
+/* P U B L I C D A T A */
+/* */
+/**************************************/
+enum public_sections {
+ PUBLIC_DRV_MB, /* Points to the first drv_mb of path0 */
+ PUBLIC_MFW_MB, /* Points to the first mfw_mb of path0 */
+ PUBLIC_GLOBAL,
+ PUBLIC_PATH,
+ PUBLIC_PORT,
+ PUBLIC_FUNC,
+ PUBLIC_MAX_SECTIONS
+};
+
+struct drv_ver_info_stc {
+ u32 ver;
+ u8 name[32];
+};
+
+struct mcp_public_data {
+ /* The sections fields is an array */
+ u32 num_sections;
+ offsize_t sections[PUBLIC_MAX_SECTIONS];
+ struct public_drv_mb drv_mb[MCP_GLOB_FUNC_MAX];
+ struct public_mfw_mb mfw_mb[MCP_GLOB_FUNC_MAX];
+ struct public_global global;
+ struct public_path path[MCP_GLOB_PATH_MAX];
+ struct public_port port[MCP_GLOB_PORT_MAX];
+ struct public_func func[MCP_GLOB_FUNC_MAX];
+ struct drv_ver_info_stc drv_info;
+};
+
+struct nvm_cfg_mac_address {
+ u32 mac_addr_hi;
+#define NVM_CFG_MAC_ADDRESS_HI_MASK 0x0000FFFF
+#define NVM_CFG_MAC_ADDRESS_HI_OFFSET 0
+
+ u32 mac_addr_lo;
+};
+
+/******************************************
+* nvm_cfg1 structs
+******************************************/
+
+struct nvm_cfg1_glob {
+ u32 generic_cont0; /* 0x0 */
+#define NVM_CFG1_GLOB_BOARD_SWAP_MASK 0x0000000F
+#define NVM_CFG1_GLOB_BOARD_SWAP_OFFSET 0
+#define NVM_CFG1_GLOB_BOARD_SWAP_NONE 0x0
+#define NVM_CFG1_GLOB_BOARD_SWAP_PATH 0x1
+#define NVM_CFG1_GLOB_BOARD_SWAP_PORT 0x2
+#define NVM_CFG1_GLOB_BOARD_SWAP_BOTH 0x3
+#define NVM_CFG1_GLOB_MF_MODE_MASK 0x00000FF0
+#define NVM_CFG1_GLOB_MF_MODE_OFFSET 4
+#define NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED 0x0
+#define NVM_CFG1_GLOB_MF_MODE_FORCED_SF 0x1
+#define NVM_CFG1_GLOB_MF_MODE_SPIO4 0x2
+#define NVM_CFG1_GLOB_MF_MODE_NPAR1_0 0x3
+#define NVM_CFG1_GLOB_MF_MODE_NPAR1_5 0x4
+#define NVM_CFG1_GLOB_MF_MODE_NPAR2_0 0x5
+#define NVM_CFG1_GLOB_MF_MODE_BD 0x6
+#define NVM_CFG1_GLOB_MF_MODE_UFP 0x7
+#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_MASK 0x00001000
+#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_OFFSET 12
+#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_DISABLED 0x0
+#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_ENABLED 0x1
+#define NVM_CFG1_GLOB_AVS_MARGIN_LOW_MASK 0x001FE000
+#define NVM_CFG1_GLOB_AVS_MARGIN_LOW_OFFSET 13
+#define NVM_CFG1_GLOB_AVS_MARGIN_HIGH_MASK 0x1FE00000
+#define NVM_CFG1_GLOB_AVS_MARGIN_HIGH_OFFSET 21
+#define NVM_CFG1_GLOB_ENABLE_SRIOV_MASK 0x20000000
+#define NVM_CFG1_GLOB_ENABLE_SRIOV_OFFSET 29
+#define NVM_CFG1_GLOB_ENABLE_SRIOV_DISABLED 0x0
+#define NVM_CFG1_GLOB_ENABLE_SRIOV_ENABLED 0x1
+#define NVM_CFG1_GLOB_ENABLE_ATC_MASK 0x40000000
+#define NVM_CFG1_GLOB_ENABLE_ATC_OFFSET 30
+#define NVM_CFG1_GLOB_ENABLE_ATC_DISABLED 0x0
+#define NVM_CFG1_GLOB_ENABLE_ATC_ENABLED 0x1
+#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_MASK 0x80000000
+#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_OFFSET 31
+#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_DISABLED 0x0
+#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_ENABLED 0x1
+
+ u32 engineering_change[3]; /* 0x4 */
+
+ u32 manufacturing_id; /* 0x10 */
+
+ u32 serial_number[4]; /* 0x14 */
+
+ u32 pcie_cfg; /* 0x24 */
+#define NVM_CFG1_GLOB_PCI_GEN_MASK 0x00000003
+#define NVM_CFG1_GLOB_PCI_GEN_OFFSET 0
+#define NVM_CFG1_GLOB_PCI_GEN_PCI_GEN1 0x0
+#define NVM_CFG1_GLOB_PCI_GEN_PCI_GEN2 0x1
+#define NVM_CFG1_GLOB_PCI_GEN_PCI_GEN3 0x2
+#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_MASK 0x00000004
+#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_OFFSET 2
+#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_DISABLED 0x0
+#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_ENABLED 0x1
+#define NVM_CFG1_GLOB_ASPM_SUPPORT_MASK 0x00000018
+#define NVM_CFG1_GLOB_ASPM_SUPPORT_OFFSET 3
+#define NVM_CFG1_GLOB_ASPM_SUPPORT_L0S_L1_ENABLED 0x0
+#define NVM_CFG1_GLOB_ASPM_SUPPORT_L0S_DISABLED 0x1
+#define NVM_CFG1_GLOB_ASPM_SUPPORT_L1_DISABLED 0x2
+#define NVM_CFG1_GLOB_ASPM_SUPPORT_L0S_L1_DISABLED 0x3
+#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_MASK 0x00000020
+#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_OFFSET 5
+#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_DISABLED 0x0
+#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_ENABLED 0x1
+#define NVM_CFG1_GLOB_PCIE_G2_TX_AMPLITUDE_MASK 0x000003C0
+#define NVM_CFG1_GLOB_PCIE_G2_TX_AMPLITUDE_OFFSET 6
+#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_MASK 0x00001C00
+#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_OFFSET 10
+#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_HW 0x0
+#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_0DB 0x1
+#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_3_5DB 0x2
+#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_6_0DB 0x3
+#define NVM_CFG1_GLOB_WWN_NODE_PREFIX0_MASK 0x001FE000
+#define NVM_CFG1_GLOB_WWN_NODE_PREFIX0_OFFSET 13
+#define NVM_CFG1_GLOB_WWN_NODE_PREFIX1_MASK 0x1FE00000
+#define NVM_CFG1_GLOB_WWN_NODE_PREFIX1_OFFSET 21
+#define NVM_CFG1_GLOB_NCSI_PACKAGE_ID_MASK 0x60000000
+#define NVM_CFG1_GLOB_NCSI_PACKAGE_ID_OFFSET 29
+
+ u32 mgmt_traffic; /* 0x28 */
+#define NVM_CFG1_GLOB_RESERVED60_MASK 0x00000001
+#define NVM_CFG1_GLOB_RESERVED60_OFFSET 0
+#define NVM_CFG1_GLOB_RESERVED60_100KHZ 0x0
+#define NVM_CFG1_GLOB_RESERVED60_400KHZ 0x1
+#define NVM_CFG1_GLOB_WWN_PORT_PREFIX0_MASK 0x000001FE
+#define NVM_CFG1_GLOB_WWN_PORT_PREFIX0_OFFSET 1
+#define NVM_CFG1_GLOB_WWN_PORT_PREFIX1_MASK 0x0001FE00
+#define NVM_CFG1_GLOB_WWN_PORT_PREFIX1_OFFSET 9
+#define NVM_CFG1_GLOB_SMBUS_ADDRESS_MASK 0x01FE0000
+#define NVM_CFG1_GLOB_SMBUS_ADDRESS_OFFSET 17
+#define NVM_CFG1_GLOB_SIDEBAND_MODE_MASK 0x06000000
+#define NVM_CFG1_GLOB_SIDEBAND_MODE_OFFSET 25
+#define NVM_CFG1_GLOB_SIDEBAND_MODE_DISABLED 0x0
+#define NVM_CFG1_GLOB_SIDEBAND_MODE_RMII 0x1
+#define NVM_CFG1_GLOB_SIDEBAND_MODE_SGMII 0x2
+
+ u32 core_cfg; /* 0x2C */
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK 0x000000FF
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET 0
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X40G 0x0
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X50G 0x1
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X100G 0x2
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_F 0x3
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_E 0x4
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X20G 0x5
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X40G 0xB
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X25G 0xC
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X25G 0xD
+#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_MASK 0x00000100
+#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_OFFSET 8
+#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_DISABLED 0x0
+#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_ENABLED 0x1
+#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_MASK 0x00000200
+#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_OFFSET 9
+#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_DISABLED 0x0
+#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_ENABLED 0x1
+#define NVM_CFG1_GLOB_EAGLE_CORE_ADDR_MASK 0x0003FC00
+#define NVM_CFG1_GLOB_EAGLE_CORE_ADDR_OFFSET 10
+#define NVM_CFG1_GLOB_FALCON_CORE_ADDR_MASK 0x03FC0000
+#define NVM_CFG1_GLOB_FALCON_CORE_ADDR_OFFSET 18
+#define NVM_CFG1_GLOB_AVS_MODE_MASK 0x1C000000
+#define NVM_CFG1_GLOB_AVS_MODE_OFFSET 26
+#define NVM_CFG1_GLOB_AVS_MODE_CLOSE_LOOP 0x0
+#define NVM_CFG1_GLOB_AVS_MODE_OPEN_LOOP 0x1
+#define NVM_CFG1_GLOB_AVS_MODE_DISABLED 0x3
+#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_MASK 0x60000000
+#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_OFFSET 29
+#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_DISABLED 0x0
+#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_ENABLED 0x1
+
+ u32 e_lane_cfg1; /* 0x30 */
+#define NVM_CFG1_GLOB_RX_LANE0_SWAP_MASK 0x0000000F
+#define NVM_CFG1_GLOB_RX_LANE0_SWAP_OFFSET 0
+#define NVM_CFG1_GLOB_RX_LANE1_SWAP_MASK 0x000000F0
+#define NVM_CFG1_GLOB_RX_LANE1_SWAP_OFFSET 4
+#define NVM_CFG1_GLOB_RX_LANE2_SWAP_MASK 0x00000F00
+#define NVM_CFG1_GLOB_RX_LANE2_SWAP_OFFSET 8
+#define NVM_CFG1_GLOB_RX_LANE3_SWAP_MASK 0x0000F000
+#define NVM_CFG1_GLOB_RX_LANE3_SWAP_OFFSET 12
+#define NVM_CFG1_GLOB_TX_LANE0_SWAP_MASK 0x000F0000
+#define NVM_CFG1_GLOB_TX_LANE0_SWAP_OFFSET 16
+#define NVM_CFG1_GLOB_TX_LANE1_SWAP_MASK 0x00F00000
+#define NVM_CFG1_GLOB_TX_LANE1_SWAP_OFFSET 20
+#define NVM_CFG1_GLOB_TX_LANE2_SWAP_MASK 0x0F000000
+#define NVM_CFG1_GLOB_TX_LANE2_SWAP_OFFSET 24
+#define NVM_CFG1_GLOB_TX_LANE3_SWAP_MASK 0xF0000000
+#define NVM_CFG1_GLOB_TX_LANE3_SWAP_OFFSET 28
+
+ u32 e_lane_cfg2; /* 0x34 */
+#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_MASK 0x00000001
+#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_OFFSET 0
+#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_MASK 0x00000002
+#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_OFFSET 1
+#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_MASK 0x00000004
+#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_OFFSET 2
+#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_MASK 0x00000008
+#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_OFFSET 3
+#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_MASK 0x00000010
+#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_OFFSET 4
+#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_MASK 0x00000020
+#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_OFFSET 5
+#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_MASK 0x00000040
+#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_OFFSET 6
+#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_MASK 0x00000080
+#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_OFFSET 7
+#define NVM_CFG1_GLOB_SMBUS_MODE_MASK 0x00000F00
+#define NVM_CFG1_GLOB_SMBUS_MODE_OFFSET 8
+#define NVM_CFG1_GLOB_SMBUS_MODE_DISABLED 0x0
+#define NVM_CFG1_GLOB_SMBUS_MODE_100KHZ 0x1
+#define NVM_CFG1_GLOB_SMBUS_MODE_400KHZ 0x2
+#define NVM_CFG1_GLOB_NCSI_MASK 0x0000F000
+#define NVM_CFG1_GLOB_NCSI_OFFSET 12
+#define NVM_CFG1_GLOB_NCSI_DISABLED 0x0
+#define NVM_CFG1_GLOB_NCSI_ENABLED 0x1
+
+ u32 f_lane_cfg1; /* 0x38 */
+#define NVM_CFG1_GLOB_RX_LANE0_SWAP_MASK 0x0000000F
+#define NVM_CFG1_GLOB_RX_LANE0_SWAP_OFFSET 0
+#define NVM_CFG1_GLOB_RX_LANE1_SWAP_MASK 0x000000F0
+#define NVM_CFG1_GLOB_RX_LANE1_SWAP_OFFSET 4
+#define NVM_CFG1_GLOB_RX_LANE2_SWAP_MASK 0x00000F00
+#define NVM_CFG1_GLOB_RX_LANE2_SWAP_OFFSET 8
+#define NVM_CFG1_GLOB_RX_LANE3_SWAP_MASK 0x0000F000
+#define NVM_CFG1_GLOB_RX_LANE3_SWAP_OFFSET 12
+#define NVM_CFG1_GLOB_TX_LANE0_SWAP_MASK 0x000F0000
+#define NVM_CFG1_GLOB_TX_LANE0_SWAP_OFFSET 16
+#define NVM_CFG1_GLOB_TX_LANE1_SWAP_MASK 0x00F00000
+#define NVM_CFG1_GLOB_TX_LANE1_SWAP_OFFSET 20
+#define NVM_CFG1_GLOB_TX_LANE2_SWAP_MASK 0x0F000000
+#define NVM_CFG1_GLOB_TX_LANE2_SWAP_OFFSET 24
+#define NVM_CFG1_GLOB_TX_LANE3_SWAP_MASK 0xF0000000
+#define NVM_CFG1_GLOB_TX_LANE3_SWAP_OFFSET 28
+
+ u32 f_lane_cfg2; /* 0x3C */
+#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_MASK 0x00000001
+#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_OFFSET 0
+#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_MASK 0x00000002
+#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_OFFSET 1
+#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_MASK 0x00000004
+#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_OFFSET 2
+#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_MASK 0x00000008
+#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_OFFSET 3
+#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_MASK 0x00000010
+#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_OFFSET 4
+#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_MASK 0x00000020
+#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_OFFSET 5
+#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_MASK 0x00000040
+#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_OFFSET 6
+#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_MASK 0x00000080
+#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_OFFSET 7
+
+ u32 eagle_preemphasis; /* 0x40 */
+#define NVM_CFG1_GLOB_LANE0_PREEMP_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_PREEMP_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_PREEMP_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_PREEMP_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_PREEMP_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_PREEMP_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_PREEMP_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_PREEMP_OFFSET 24
+
+ u32 eagle_driver_current; /* 0x44 */
+#define NVM_CFG1_GLOB_LANE0_AMP_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_AMP_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_AMP_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_AMP_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_AMP_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_AMP_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_AMP_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_AMP_OFFSET 24
+
+ u32 falcon_preemphasis; /* 0x48 */
+#define NVM_CFG1_GLOB_LANE0_PREEMP_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_PREEMP_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_PREEMP_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_PREEMP_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_PREEMP_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_PREEMP_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_PREEMP_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_PREEMP_OFFSET 24
+
+ u32 falcon_driver_current; /* 0x4C */
+#define NVM_CFG1_GLOB_LANE0_AMP_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_AMP_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_AMP_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_AMP_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_AMP_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_AMP_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_AMP_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_AMP_OFFSET 24
+
+ u32 pci_id; /* 0x50 */
+#define NVM_CFG1_GLOB_VENDOR_ID_MASK 0x0000FFFF
+#define NVM_CFG1_GLOB_VENDOR_ID_OFFSET 0
+
+ u32 pci_subsys_id; /* 0x54 */
+#define NVM_CFG1_GLOB_SUBSYSTEM_VENDOR_ID_MASK 0x0000FFFF
+#define NVM_CFG1_GLOB_SUBSYSTEM_VENDOR_ID_OFFSET 0
+#define NVM_CFG1_GLOB_SUBSYSTEM_DEVICE_ID_MASK 0xFFFF0000
+#define NVM_CFG1_GLOB_SUBSYSTEM_DEVICE_ID_OFFSET 16
+
+ u32 bar; /* 0x58 */
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_MASK 0x0000000F
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_OFFSET 0
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_DISABLED 0x0
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_2K 0x1
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_4K 0x2
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_8K 0x3
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_16K 0x4
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_32K 0x5
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_64K 0x6
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_128K 0x7
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_256K 0x8
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_512K 0x9
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_1M 0xA
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_2M 0xB
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_4M 0xC
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_8M 0xD
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_16M 0xE
+#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_32M 0xF
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_MASK 0x000000F0
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_OFFSET 4
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_DISABLED 0x0
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_4K 0x1
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_8K 0x2
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_16K 0x3
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_32K 0x4
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_64K 0x5
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_128K 0x6
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_256K 0x7
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_512K 0x8
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_1M 0x9
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_2M 0xA
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_4M 0xB
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_8M 0xC
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_16M 0xD
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_32M 0xE
+#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_64M 0xF
+#define NVM_CFG1_GLOB_BAR2_SIZE_MASK 0x00000F00
+#define NVM_CFG1_GLOB_BAR2_SIZE_OFFSET 8
+#define NVM_CFG1_GLOB_BAR2_SIZE_DISABLED 0x0
+#define NVM_CFG1_GLOB_BAR2_SIZE_64K 0x1
+#define NVM_CFG1_GLOB_BAR2_SIZE_128K 0x2
+#define NVM_CFG1_GLOB_BAR2_SIZE_256K 0x3
+#define NVM_CFG1_GLOB_BAR2_SIZE_512K 0x4
+#define NVM_CFG1_GLOB_BAR2_SIZE_1M 0x5
+#define NVM_CFG1_GLOB_BAR2_SIZE_2M 0x6
+#define NVM_CFG1_GLOB_BAR2_SIZE_4M 0x7
+#define NVM_CFG1_GLOB_BAR2_SIZE_8M 0x8
+#define NVM_CFG1_GLOB_BAR2_SIZE_16M 0x9
+#define NVM_CFG1_GLOB_BAR2_SIZE_32M 0xA
+#define NVM_CFG1_GLOB_BAR2_SIZE_64M 0xB
+#define NVM_CFG1_GLOB_BAR2_SIZE_128M 0xC
+#define NVM_CFG1_GLOB_BAR2_SIZE_256M 0xD
+#define NVM_CFG1_GLOB_BAR2_SIZE_512M 0xE
+#define NVM_CFG1_GLOB_BAR2_SIZE_1G 0xF
+
+ u32 eagle_txfir_main; /* 0x5C */
+#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_OFFSET 24
+
+ u32 eagle_txfir_post; /* 0x60 */
+#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_OFFSET 24
+
+ u32 falcon_txfir_main; /* 0x64 */
+#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_OFFSET 24
+
+ u32 falcon_txfir_post; /* 0x68 */
+#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_MASK 0x000000FF
+#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_OFFSET 0
+#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_OFFSET 8
+#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_OFFSET 16
+#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_MASK 0xFF000000
+#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_OFFSET 24
+
+ u32 manufacture_ver; /* 0x6C */
+#define NVM_CFG1_GLOB_MANUF0_VER_MASK 0x0000003F
+#define NVM_CFG1_GLOB_MANUF0_VER_OFFSET 0
+#define NVM_CFG1_GLOB_MANUF1_VER_MASK 0x00000FC0
+#define NVM_CFG1_GLOB_MANUF1_VER_OFFSET 6
+#define NVM_CFG1_GLOB_MANUF2_VER_MASK 0x0003F000
+#define NVM_CFG1_GLOB_MANUF2_VER_OFFSET 12
+#define NVM_CFG1_GLOB_MANUF3_VER_MASK 0x00FC0000
+#define NVM_CFG1_GLOB_MANUF3_VER_OFFSET 18
+#define NVM_CFG1_GLOB_MANUF4_VER_MASK 0x3F000000
+#define NVM_CFG1_GLOB_MANUF4_VER_OFFSET 24
+
+ u32 manufacture_time; /* 0x70 */
+#define NVM_CFG1_GLOB_MANUF0_TIME_MASK 0x0000003F
+#define NVM_CFG1_GLOB_MANUF0_TIME_OFFSET 0
+#define NVM_CFG1_GLOB_MANUF1_TIME_MASK 0x00000FC0
+#define NVM_CFG1_GLOB_MANUF1_TIME_OFFSET 6
+#define NVM_CFG1_GLOB_MANUF2_TIME_MASK 0x0003F000
+#define NVM_CFG1_GLOB_MANUF2_TIME_OFFSET 12
+
+ u32 led_global_settings; /* 0x74 */
+#define NVM_CFG1_GLOB_LED_SWAP_0_MASK 0x0000000F
+#define NVM_CFG1_GLOB_LED_SWAP_0_OFFSET 0
+#define NVM_CFG1_GLOB_LED_SWAP_1_MASK 0x000000F0
+#define NVM_CFG1_GLOB_LED_SWAP_1_OFFSET 4
+#define NVM_CFG1_GLOB_LED_SWAP_2_MASK 0x00000F00
+#define NVM_CFG1_GLOB_LED_SWAP_2_OFFSET 8
+#define NVM_CFG1_GLOB_LED_SWAP_3_MASK 0x0000F000
+#define NVM_CFG1_GLOB_LED_SWAP_3_OFFSET 12
+
+ u32 generic_cont1; /* 0x78 */
+#define NVM_CFG1_GLOB_AVS_DAC_CODE_MASK 0x000003FF
+#define NVM_CFG1_GLOB_AVS_DAC_CODE_OFFSET 0
+
+ u32 mbi_version; /* 0x7C */
+#define NVM_CFG1_GLOB_MBI_VERSION_0_MASK 0x000000FF
+#define NVM_CFG1_GLOB_MBI_VERSION_0_OFFSET 0
+#define NVM_CFG1_GLOB_MBI_VERSION_1_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_MBI_VERSION_1_OFFSET 8
+#define NVM_CFG1_GLOB_MBI_VERSION_2_MASK 0x00FF0000
+#define NVM_CFG1_GLOB_MBI_VERSION_2_OFFSET 16
+
+ u32 mbi_date; /* 0x80 */
+
+ u32 misc_sig; /* 0x84 */
+
+ /* Define the GPIO mapping to switch i2c mux */
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_0_MASK 0x000000FF
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_0_OFFSET 0
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_1_MASK 0x0000FF00
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_1_OFFSET 8
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__NA 0x0
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO0 0x1
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO1 0x2
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO2 0x3
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO3 0x4
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO4 0x5
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO5 0x6
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO6 0x7
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO7 0x8
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO8 0x9
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO9 0xA
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO10 0xB
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO11 0xC
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO12 0xD
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO13 0xE
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO14 0xF
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO15 0x10
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO16 0x11
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO17 0x12
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO18 0x13
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO19 0x14
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO20 0x15
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO21 0x16
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO22 0x17
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO23 0x18
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO24 0x19
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO25 0x1A
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO26 0x1B
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO27 0x1C
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO28 0x1D
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO29 0x1E
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO30 0x1F
+#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO31 0x20
+
+ u32 reserved[46]; /* 0x88 */
+};
+
+struct nvm_cfg1_path {
+ u32 reserved[30]; /* 0x0 */
+};
+
+struct nvm_cfg1_port {
+ u32 power_dissipated; /* 0x0 */
+#define NVM_CFG1_PORT_POWER_DIS_D0_MASK 0x000000FF
+#define NVM_CFG1_PORT_POWER_DIS_D0_OFFSET 0
+#define NVM_CFG1_PORT_POWER_DIS_D1_MASK 0x0000FF00
+#define NVM_CFG1_PORT_POWER_DIS_D1_OFFSET 8
+#define NVM_CFG1_PORT_POWER_DIS_D2_MASK 0x00FF0000
+#define NVM_CFG1_PORT_POWER_DIS_D2_OFFSET 16
+#define NVM_CFG1_PORT_POWER_DIS_D3_MASK 0xFF000000
+#define NVM_CFG1_PORT_POWER_DIS_D3_OFFSET 24
+
+ u32 power_consumed; /* 0x4 */
+#define NVM_CFG1_PORT_POWER_CONS_D0_MASK 0x000000FF
+#define NVM_CFG1_PORT_POWER_CONS_D0_OFFSET 0
+#define NVM_CFG1_PORT_POWER_CONS_D1_MASK 0x0000FF00
+#define NVM_CFG1_PORT_POWER_CONS_D1_OFFSET 8
+#define NVM_CFG1_PORT_POWER_CONS_D2_MASK 0x00FF0000
+#define NVM_CFG1_PORT_POWER_CONS_D2_OFFSET 16
+#define NVM_CFG1_PORT_POWER_CONS_D3_MASK 0xFF000000
+#define NVM_CFG1_PORT_POWER_CONS_D3_OFFSET 24
+
+ u32 generic_cont0; /* 0x8 */
+#define NVM_CFG1_PORT_LED_MODE_MASK 0x000000FF
+#define NVM_CFG1_PORT_LED_MODE_OFFSET 0
+#define NVM_CFG1_PORT_LED_MODE_MAC1 0x0
+#define NVM_CFG1_PORT_LED_MODE_PHY1 0x1
+#define NVM_CFG1_PORT_LED_MODE_PHY2 0x2
+#define NVM_CFG1_PORT_LED_MODE_PHY3 0x3
+#define NVM_CFG1_PORT_LED_MODE_MAC2 0x4
+#define NVM_CFG1_PORT_LED_MODE_PHY4 0x5
+#define NVM_CFG1_PORT_LED_MODE_PHY5 0x6
+#define NVM_CFG1_PORT_LED_MODE_PHY6 0x7
+#define NVM_CFG1_PORT_LED_MODE_MAC3 0x8
+#define NVM_CFG1_PORT_LED_MODE_PHY7 0x9
+#define NVM_CFG1_PORT_LED_MODE_PHY8 0xA
+#define NVM_CFG1_PORT_LED_MODE_PHY9 0xB
+#define NVM_CFG1_PORT_LED_MODE_MAC4 0xC
+#define NVM_CFG1_PORT_LED_MODE_PHY10 0xD
+#define NVM_CFG1_PORT_LED_MODE_PHY11 0xE
+#define NVM_CFG1_PORT_LED_MODE_PHY12 0xF
+#define NVM_CFG1_PORT_ROCE_PRIORITY_MASK 0x0000FF00
+#define NVM_CFG1_PORT_ROCE_PRIORITY_OFFSET 8
+#define NVM_CFG1_PORT_DCBX_MODE_MASK 0x000F0000
+#define NVM_CFG1_PORT_DCBX_MODE_OFFSET 16
+#define NVM_CFG1_PORT_DCBX_MODE_DISABLED 0x0
+#define NVM_CFG1_PORT_DCBX_MODE_IEEE 0x1
+#define NVM_CFG1_PORT_DCBX_MODE_CEE 0x2
+#define NVM_CFG1_PORT_DCBX_MODE_DYNAMIC 0x3
+
+ u32 pcie_cfg; /* 0xC */
+#define NVM_CFG1_PORT_RESERVED15_MASK 0x00000007
+#define NVM_CFG1_PORT_RESERVED15_OFFSET 0
+
+ u32 features; /* 0x10 */
+#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_MASK 0x00000001
+#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_OFFSET 0
+#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_DISABLED 0x0
+#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_ENABLED 0x1
+#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_MASK 0x00000002
+#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_OFFSET 1
+#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_DISABLED 0x0
+#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_ENABLED 0x1
+
+ u32 speed_cap_mask; /* 0x14 */
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK 0x0000FFFF
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_OFFSET 0
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G 0x1
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G 0x2
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G 0x8
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G 0x10
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G 0x20
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G 0x40
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_MASK 0xFFFF0000
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_OFFSET 16
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_1G 0x1
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_10G 0x2
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_25G 0x8
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_40G 0x10
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_50G 0x20
+#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_100G 0x40
+
+ u32 link_settings; /* 0x18 */
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_MASK 0x0000000F
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET 0
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG 0x0
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_1G 0x1
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_10G 0x2
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_25G 0x4
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_40G 0x5
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_50G 0x6
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_100G 0x7
+#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK 0x00000070
+#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET 4
+#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG 0x1
+#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX 0x2
+#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX 0x4
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_MASK 0x00000780
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_OFFSET 7
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_AUTONEG 0x0
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_1G 0x1
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_10G 0x2
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_25G 0x4
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_40G 0x5
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_50G 0x6
+#define NVM_CFG1_PORT_MFW_LINK_SPEED_100G 0x7
+#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_MASK 0x00003800
+#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_OFFSET 11
+#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_AUTONEG 0x1
+#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_RX 0x2
+#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_TX 0x4
+#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_MASK 0x00004000
+#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_OFFSET 14
+#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_DISABLED 0x0
+#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_ENABLED 0x1
+
+ u32 phy_cfg; /* 0x1C */
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_MASK 0x0000FFFF
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_OFFSET 0
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_HIGIG 0x1
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_SCRAMBLER 0x2
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_FIBER 0x4
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_DISABLE_CL72_AN 0x8
+#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_DISABLE_FEC_AN 0x10
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_MASK 0x00FF0000
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_OFFSET 16
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_BYPASS 0x0
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_KR 0x2
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_KR2 0x3
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_KR4 0x4
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_XFI 0x8
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_SFI 0x9
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_1000X 0xB
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_SGMII 0xC
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_XLAUI 0xD
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_CAUI 0xE
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_XLPPI 0xF
+#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_CPPI 0x10
+#define NVM_CFG1_PORT_AN_MODE_MASK 0xFF000000
+#define NVM_CFG1_PORT_AN_MODE_OFFSET 24
+#define NVM_CFG1_PORT_AN_MODE_NONE 0x0
+#define NVM_CFG1_PORT_AN_MODE_CL73 0x1
+#define NVM_CFG1_PORT_AN_MODE_CL37 0x2
+#define NVM_CFG1_PORT_AN_MODE_CL73_BAM 0x3
+#define NVM_CFG1_PORT_AN_MODE_CL37_BAM 0x4
+#define NVM_CFG1_PORT_AN_MODE_HPAM 0x5
+#define NVM_CFG1_PORT_AN_MODE_SGMII 0x6
+
+ u32 mgmt_traffic; /* 0x20 */
+#define NVM_CFG1_PORT_RESERVED61_MASK 0x0000000F
+#define NVM_CFG1_PORT_RESERVED61_OFFSET 0
+#define NVM_CFG1_PORT_RESERVED61_DISABLED 0x0
+#define NVM_CFG1_PORT_RESERVED61_NCSI_OVER_RMII 0x1
+#define NVM_CFG1_PORT_RESERVED61_NCSI_OVER_SMBUS 0x2
+
+ u32 ext_phy; /* 0x24 */
+#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_MASK 0x000000FF
+#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_OFFSET 0
+#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_NONE 0x0
+#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_BCM84844 0x1
+#define NVM_CFG1_PORT_EXTERNAL_PHY_ADDRESS_MASK 0x0000FF00
+#define NVM_CFG1_PORT_EXTERNAL_PHY_ADDRESS_OFFSET 8
+
+ u32 mba_cfg1; /* 0x28 */
+#define NVM_CFG1_PORT_MBA_MASK 0x00000001
+#define NVM_CFG1_PORT_MBA_OFFSET 0
+#define NVM_CFG1_PORT_MBA_DISABLED 0x0
+#define NVM_CFG1_PORT_MBA_ENABLED 0x1
+#define NVM_CFG1_PORT_MBA_BOOT_TYPE_MASK 0x00000006
+#define NVM_CFG1_PORT_MBA_BOOT_TYPE_OFFSET 1
+#define NVM_CFG1_PORT_MBA_BOOT_TYPE_AUTO 0x0
+#define NVM_CFG1_PORT_MBA_BOOT_TYPE_BBS 0x1
+#define NVM_CFG1_PORT_MBA_BOOT_TYPE_INT18H 0x2
+#define NVM_CFG1_PORT_MBA_BOOT_TYPE_INT19H 0x3
+#define NVM_CFG1_PORT_MBA_DELAY_TIME_MASK 0x00000078
+#define NVM_CFG1_PORT_MBA_DELAY_TIME_OFFSET 3
+#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_MASK 0x00000080
+#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_OFFSET 7
+#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_CTRL_S 0x0
+#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_CTRL_B 0x1
+#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_MASK 0x00000100
+#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_OFFSET 8
+#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_DISABLED 0x0
+#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_ENABLED 0x1
+#define NVM_CFG1_PORT_RESERVED5_MASK 0x0001FE00
+#define NVM_CFG1_PORT_RESERVED5_OFFSET 9
+#define NVM_CFG1_PORT_RESERVED5_DISABLED 0x0
+#define NVM_CFG1_PORT_RESERVED5_2K 0x1
+#define NVM_CFG1_PORT_RESERVED5_4K 0x2
+#define NVM_CFG1_PORT_RESERVED5_8K 0x3
+#define NVM_CFG1_PORT_RESERVED5_16K 0x4
+#define NVM_CFG1_PORT_RESERVED5_32K 0x5
+#define NVM_CFG1_PORT_RESERVED5_64K 0x6
+#define NVM_CFG1_PORT_RESERVED5_128K 0x7
+#define NVM_CFG1_PORT_RESERVED5_256K 0x8
+#define NVM_CFG1_PORT_RESERVED5_512K 0x9
+#define NVM_CFG1_PORT_RESERVED5_1M 0xA
+#define NVM_CFG1_PORT_RESERVED5_2M 0xB
+#define NVM_CFG1_PORT_RESERVED5_4M 0xC
+#define NVM_CFG1_PORT_RESERVED5_8M 0xD
+#define NVM_CFG1_PORT_RESERVED5_16M 0xE
+#define NVM_CFG1_PORT_RESERVED5_32M 0xF
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_MASK 0x001E0000
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_OFFSET 17
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_AUTONEG 0x0
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_1G 0x1
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_10G 0x2
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_25G 0x4
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_40G 0x5
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_50G 0x6
+#define NVM_CFG1_PORT_MBA_LINK_SPEED_100G 0x7
+#define NVM_CFG1_PORT_MBA_BOOT_RETRY_COUNT_MASK 0x00E00000
+#define NVM_CFG1_PORT_MBA_BOOT_RETRY_COUNT_OFFSET 21
+
+ u32 mba_cfg2; /* 0x2C */
+#define NVM_CFG1_PORT_MBA_VLAN_VALUE_MASK 0x0000FFFF
+#define NVM_CFG1_PORT_MBA_VLAN_VALUE_OFFSET 0
+#define NVM_CFG1_PORT_MBA_VLAN_MASK 0x00010000
+#define NVM_CFG1_PORT_MBA_VLAN_OFFSET 16
+
+ u32 vf_cfg; /* 0x30 */
+#define NVM_CFG1_PORT_RESERVED8_MASK 0x0000FFFF
+#define NVM_CFG1_PORT_RESERVED8_OFFSET 0
+#define NVM_CFG1_PORT_RESERVED6_MASK 0x000F0000
+#define NVM_CFG1_PORT_RESERVED6_OFFSET 16
+#define NVM_CFG1_PORT_RESERVED6_DISABLED 0x0
+#define NVM_CFG1_PORT_RESERVED6_4K 0x1
+#define NVM_CFG1_PORT_RESERVED6_8K 0x2
+#define NVM_CFG1_PORT_RESERVED6_16K 0x3
+#define NVM_CFG1_PORT_RESERVED6_32K 0x4
+#define NVM_CFG1_PORT_RESERVED6_64K 0x5
+#define NVM_CFG1_PORT_RESERVED6_128K 0x6
+#define NVM_CFG1_PORT_RESERVED6_256K 0x7
+#define NVM_CFG1_PORT_RESERVED6_512K 0x8
+#define NVM_CFG1_PORT_RESERVED6_1M 0x9
+#define NVM_CFG1_PORT_RESERVED6_2M 0xA
+#define NVM_CFG1_PORT_RESERVED6_4M 0xB
+#define NVM_CFG1_PORT_RESERVED6_8M 0xC
+#define NVM_CFG1_PORT_RESERVED6_16M 0xD
+#define NVM_CFG1_PORT_RESERVED6_32M 0xE
+#define NVM_CFG1_PORT_RESERVED6_64M 0xF
+
+ struct nvm_cfg_mac_address lldp_mac_address; /* 0x34 */
+
+ u32 led_port_settings; /* 0x3C */
+#define NVM_CFG1_PORT_LANE_LED_SPD_0_SEL_MASK 0x000000FF
+#define NVM_CFG1_PORT_LANE_LED_SPD_0_SEL_OFFSET 0
+#define NVM_CFG1_PORT_LANE_LED_SPD_1_SEL_MASK 0x0000FF00
+#define NVM_CFG1_PORT_LANE_LED_SPD_1_SEL_OFFSET 8
+#define NVM_CFG1_PORT_LANE_LED_SPD_2_SEL_MASK 0x00FF0000
+#define NVM_CFG1_PORT_LANE_LED_SPD_2_SEL_OFFSET 16
+#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_1G 0x1
+#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_10G 0x2
+#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_25G 0x8
+#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_40G 0x10
+#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_50G 0x20
+#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_100G 0x40
+
+ u32 transceiver_00; /* 0x40 */
+
+ /* Define for mapping of transceiver signal module absent */
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_MASK 0x000000FF
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_OFFSET 0
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_NA 0x0
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO0 0x1
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO1 0x2
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO2 0x3
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO3 0x4
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO4 0x5
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO5 0x6
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO6 0x7
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO7 0x8
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO8 0x9
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO9 0xA
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO10 0xB
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO11 0xC
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO12 0xD
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO13 0xE
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO14 0xF
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO15 0x10
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO16 0x11
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO17 0x12
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO18 0x13
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO19 0x14
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO20 0x15
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO21 0x16
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO22 0x17
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO23 0x18
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO24 0x19
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO25 0x1A
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO26 0x1B
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO27 0x1C
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO28 0x1D
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO29 0x1E
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO30 0x1F
+#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO31 0x20
+ /* Define the GPIO mux settings to switch i2c mux to this port */
+#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_0_MASK 0x00000F00
+#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_0_OFFSET 8
+#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_1_MASK 0x0000F000
+#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_1_OFFSET 12
+
+ u32 reserved[133]; /* 0x44 */
+};
+
+struct nvm_cfg1_func {
+ struct nvm_cfg_mac_address mac_address; /* 0x0 */
+
+ u32 rsrv1; /* 0x8 */
+#define NVM_CFG1_FUNC_RESERVED1_MASK 0x0000FFFF
+#define NVM_CFG1_FUNC_RESERVED1_OFFSET 0
+#define NVM_CFG1_FUNC_RESERVED2_MASK 0xFFFF0000
+#define NVM_CFG1_FUNC_RESERVED2_OFFSET 16
+
+ u32 rsrv2; /* 0xC */
+#define NVM_CFG1_FUNC_RESERVED3_MASK 0x0000FFFF
+#define NVM_CFG1_FUNC_RESERVED3_OFFSET 0
+#define NVM_CFG1_FUNC_RESERVED4_MASK 0xFFFF0000
+#define NVM_CFG1_FUNC_RESERVED4_OFFSET 16
+
+ u32 device_id; /* 0x10 */
+#define NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_MASK 0x0000FFFF
+#define NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_OFFSET 0
+#define NVM_CFG1_FUNC_VENDOR_DEVICE_ID_MASK 0xFFFF0000
+#define NVM_CFG1_FUNC_VENDOR_DEVICE_ID_OFFSET 16
+
+ u32 cmn_cfg; /* 0x14 */
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_MASK 0x00000007
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_OFFSET 0
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_PXE 0x0
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_RPL 0x1
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_BOOTP 0x2
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_ISCSI_BOOT 0x3
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_FCOE_BOOT 0x4
+#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_NONE 0x7
+#define NVM_CFG1_FUNC_VF_PCI_DEVICE_ID_MASK 0x0007FFF8
+#define NVM_CFG1_FUNC_VF_PCI_DEVICE_ID_OFFSET 3
+#define NVM_CFG1_FUNC_PERSONALITY_MASK 0x00780000
+#define NVM_CFG1_FUNC_PERSONALITY_OFFSET 19
+#define NVM_CFG1_FUNC_PERSONALITY_ETHERNET 0x0
+#define NVM_CFG1_FUNC_PERSONALITY_ISCSI 0x1
+#define NVM_CFG1_FUNC_PERSONALITY_FCOE 0x2
+#define NVM_CFG1_FUNC_PERSONALITY_ROCE 0x3
+#define NVM_CFG1_FUNC_BANDWIDTH_WEIGHT_MASK 0x7F800000
+#define NVM_CFG1_FUNC_BANDWIDTH_WEIGHT_OFFSET 23
+#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_MASK 0x80000000
+#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_OFFSET 31
+#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_DISABLED 0x0
+#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_ENABLED 0x1
+
+ u32 pci_cfg; /* 0x18 */
+#define NVM_CFG1_FUNC_NUMBER_OF_VFS_PER_PF_MASK 0x0000007F
+#define NVM_CFG1_FUNC_NUMBER_OF_VFS_PER_PF_OFFSET 0
+#define NVM_CFG1_FUNC_RESERVESD12_MASK 0x00003F80
+#define NVM_CFG1_FUNC_RESERVESD12_OFFSET 7
+#define NVM_CFG1_FUNC_BAR1_SIZE_MASK 0x0003C000
+#define NVM_CFG1_FUNC_BAR1_SIZE_OFFSET 14
+#define NVM_CFG1_FUNC_BAR1_SIZE_DISABLED 0x0
+#define NVM_CFG1_FUNC_BAR1_SIZE_64K 0x1
+#define NVM_CFG1_FUNC_BAR1_SIZE_128K 0x2
+#define NVM_CFG1_FUNC_BAR1_SIZE_256K 0x3
+#define NVM_CFG1_FUNC_BAR1_SIZE_512K 0x4
+#define NVM_CFG1_FUNC_BAR1_SIZE_1M 0x5
+#define NVM_CFG1_FUNC_BAR1_SIZE_2M 0x6
+#define NVM_CFG1_FUNC_BAR1_SIZE_4M 0x7
+#define NVM_CFG1_FUNC_BAR1_SIZE_8M 0x8
+#define NVM_CFG1_FUNC_BAR1_SIZE_16M 0x9
+#define NVM_CFG1_FUNC_BAR1_SIZE_32M 0xA
+#define NVM_CFG1_FUNC_BAR1_SIZE_64M 0xB
+#define NVM_CFG1_FUNC_BAR1_SIZE_128M 0xC
+#define NVM_CFG1_FUNC_BAR1_SIZE_256M 0xD
+#define NVM_CFG1_FUNC_BAR1_SIZE_512M 0xE
+#define NVM_CFG1_FUNC_BAR1_SIZE_1G 0xF
+#define NVM_CFG1_FUNC_MAX_BANDWIDTH_MASK 0x03FC0000
+#define NVM_CFG1_FUNC_MAX_BANDWIDTH_OFFSET 18
+
+ struct nvm_cfg_mac_address fcoe_node_wwn_mac_addr; /* 0x1C */
+
+ struct nvm_cfg_mac_address fcoe_port_wwn_mac_addr; /* 0x24 */
+
+ u32 reserved[9]; /* 0x2C */
+};
+
+struct nvm_cfg1 {
+ struct nvm_cfg1_glob glob; /* 0x0 */
+
+ struct nvm_cfg1_path path[MCP_GLOB_PATH_MAX]; /* 0x140 */
+
+ struct nvm_cfg1_port port[MCP_GLOB_PORT_MAX]; /* 0x230 */
+
+ struct nvm_cfg1_func func[MCP_GLOB_FUNC_MAX]; /* 0xB90 */
+};
+
+/******************************************
+* nvm_cfg structs
+******************************************/
+
+enum nvm_cfg_sections {
+ NVM_CFG_SECTION_NVM_CFG1,
+ NVM_CFG_SECTION_MAX
+};
+
+struct nvm_cfg {
+ u32 num_sections;
+ u32 sections_offset[NVM_CFG_SECTION_MAX];
+ struct nvm_cfg1 cfg1;
+};
+
+#define PORT_0 0
+#define PORT_1 1
+#define PORT_2 2
+#define PORT_3 3
+
+extern struct spad_layout g_spad;
+
+#define MCP_SPAD_SIZE 0x00028000 /* 160 KB */
+
+#define SPAD_OFFSET(addr) (((u32)addr - (u32)CPU_SPAD_BASE))
+
+#define TO_OFFSIZE(_offset, _size) \
+ (u32)((((u32)(_offset) >> 2) << OFFSIZE_OFFSET_SHIFT) | \
+ (((u32)(_size) >> 2) << OFFSIZE_SIZE_SHIFT))
+
+enum spad_sections {
+ SPAD_SECTION_TRACE,
+ SPAD_SECTION_NVM_CFG,
+ SPAD_SECTION_PUBLIC,
+ SPAD_SECTION_PRIVATE,
+ SPAD_SECTION_MAX
+};
+
+struct spad_layout {
+ struct nvm_cfg nvm_cfg;
+ struct mcp_public_data public_data;
+};
+
+#define CRC_MAGIC_VALUE 0xDEBB20E3
+#define CRC32_POLYNOMIAL 0xEDB88320
+#define NVM_CRC_SIZE (sizeof(u32))
+
+enum nvm_sw_arbitrator {
+ NVM_SW_ARB_HOST,
+ NVM_SW_ARB_MCP,
+ NVM_SW_ARB_UART,
+ NVM_SW_ARB_RESERVED
+};
+
+/****************************************************************************
+* Boot Strap Region *
+****************************************************************************/
+struct legacy_bootstrap_region {
+ u32 magic_value;
+#define NVM_MAGIC_VALUE 0x669955aa
+ u32 sram_start_addr;
+ u32 code_len; /* boot code length (in dwords) */
+ u32 code_start_addr;
+ u32 crc; /* 32-bit CRC */
+};
+
+/****************************************************************************
+* Directories Region *
+****************************************************************************/
+struct nvm_code_entry {
+ u32 image_type; /* Image type */
+ u32 nvm_start_addr; /* NVM address of the image */
+ u32 len; /* Include CRC */
+ u32 sram_start_addr;
+ u32 sram_run_addr; /* Relevant in case of MIM only */
+};
+
+enum nvm_image_type {
+ NVM_TYPE_TIM1 = 0x01,
+ NVM_TYPE_TIM2 = 0x02,
+ NVM_TYPE_MIM1 = 0x03,
+ NVM_TYPE_MIM2 = 0x04,
+ NVM_TYPE_MBA = 0x05,
+ NVM_TYPE_MODULES_PN = 0x06,
+ NVM_TYPE_VPD = 0x07,
+ NVM_TYPE_MFW_TRACE1 = 0x08,
+ NVM_TYPE_MFW_TRACE2 = 0x09,
+ NVM_TYPE_NVM_CFG1 = 0x0a,
+ NVM_TYPE_L2B = 0x0b,
+ NVM_TYPE_DIR1 = 0x0c,
+ NVM_TYPE_EAGLE_FW1 = 0x0d,
+ NVM_TYPE_FALCON_FW1 = 0x0e,
+ NVM_TYPE_PCIE_FW1 = 0x0f,
+ NVM_TYPE_HW_SET = 0x10,
+ NVM_TYPE_LIM = 0x11,
+ NVM_TYPE_AVS_FW1 = 0x12,
+ NVM_TYPE_DIR2 = 0x13,
+ NVM_TYPE_CCM = 0x14,
+ NVM_TYPE_EAGLE_FW2 = 0x15,
+ NVM_TYPE_FALCON_FW2 = 0x16,
+ NVM_TYPE_PCIE_FW2 = 0x17,
+ NVM_TYPE_AVS_FW2 = 0x18,
+
+ NVM_TYPE_MAX,
+};
+
+#define MAX_NVM_DIR_ENTRIES 200
+
+struct nvm_dir {
+ s32 seq;
+#define NVM_DIR_NEXT_MFW_MASK 0x00000001
+#define NVM_DIR_SEQ_MASK 0xfffffffe
+#define NVM_DIR_NEXT_MFW(seq) ((seq) & NVM_DIR_NEXT_MFW_MASK)
+
+#define IS_DIR_SEQ_VALID(seq) ((seq & NVM_DIR_SEQ_MASK) != NVM_DIR_SEQ_MASK)
+
+ u32 num_images;
+ u32 rsrv;
+ struct nvm_code_entry code[1]; /* Up to MAX_NVM_DIR_ENTRIES */
+};
+
+#define NVM_DIR_SIZE(_num_images) (sizeof(struct nvm_dir) + \
+ (_num_images - \
+ 1) * sizeof(struct nvm_code_entry) + \
+ NVM_CRC_SIZE)
+
+struct nvm_vpd_image {
+ u32 format_revision;
+#define VPD_IMAGE_VERSION 1
+
+ /* This array length depends on the number of VPD fields */
+ u8 vpd_data[1];
+};
+
+/****************************************************************************
+* NVRAM FULL MAP *
+****************************************************************************/
+#define DIR_ID_1 (0)
+#define DIR_ID_2 (1)
+#define MAX_DIR_IDS (2)
+
+#define MFW_BUNDLE_1 (0)
+#define MFW_BUNDLE_2 (1)
+#define MAX_MFW_BUNDLES (2)
+
+#define FLASH_PAGE_SIZE 0x1000
+#define NVM_DIR_MAX_SIZE (FLASH_PAGE_SIZE) /* 4Kb */
+#define ASIC_MIM_MAX_SIZE (300 * FLASH_PAGE_SIZE) /* 1.2Mb */
+#define FPGA_MIM_MAX_SIZE (25 * FLASH_PAGE_SIZE) /* 60Kb */
+
+#define LIM_MAX_SIZE ((2 * \
+ FLASH_PAGE_SIZE) - \
+ sizeof(struct legacy_bootstrap_region) - \
+ NVM_RSV_SIZE)
+#define LIM_OFFSET (NVM_OFFSET(lim_image))
+#define NVM_RSV_SIZE (44)
+#define MIM_MAX_SIZE(is_asic) ((is_asic) ? ASIC_MIM_MAX_SIZE : \
+ FPGA_MIM_MAX_SIZE)
+#define MIM_OFFSET(idx, is_asic) (NVM_OFFSET(dir[MAX_MFW_BUNDLES]) + \
+ ((idx == \
+ NVM_TYPE_MIM2) ? MIM_MAX_SIZE(is_asic) : 0))
+#define NVM_FIXED_AREA_SIZE(is_asic) (sizeof(struct nvm_image) + \
+ MIM_MAX_SIZE(is_asic) * 2)
+
+union nvm_dir_union {
+ struct nvm_dir dir;
+ u8 page[FLASH_PAGE_SIZE];
+};
+
+/* Address
+ * +-------------------+ 0x000000
+ * | Bootstrap: |
+ * | magic_number |
+ * | sram_start_addr |
+ * | code_len |
+ * | code_start_addr |
+ * | crc |
+ * +-------------------+ 0x000014
+ * | rsrv |
+ * +-------------------+ 0x000040
+ * | LIM |
+ * +-------------------+ 0x002000
+ * | Dir1 |
+ * +-------------------+ 0x003000
+ * | Dir2 |
+ * +-------------------+ 0x004000
+ * | MIM1 |
+ * +-------------------+ 0x130000
+ * | MIM2 |
+ * +-------------------+ 0x25C000
+ * | Rest Images: |
+ * | TIM1/2 |
+ * | MFW_TRACE1/2 |
+ * | Eagle/Falcon FW |
+ * | PCIE/AVS FW |
+ * | MBA/CCM/L2B |
+ * | VPD |
+ * | optic_modules |
+ * | ... |
+ * +-------------------+ 0x400000
+ */
+struct nvm_image {
+/*********** !!! FIXED SECTIONS !!! DO NOT MODIFY !!! **********************/
+ /* NVM Offset (size) */
+ struct legacy_bootstrap_region bootstrap;
+ u8 rsrv[NVM_RSV_SIZE];
+ u8 lim_image[LIM_MAX_SIZE];
+ union nvm_dir_union dir[MAX_MFW_BUNDLES];
+
+ /* MIM1_IMAGE 0x004000 (0x12c000) */
+ /* MIM2_IMAGE 0x130000 (0x12c000) */
+/*********** !!! FIXED SECTIONS !!! DO NOT MODIFY !!! **********************/
+}; /* 0x134 */
+
+#define NVM_OFFSET(f) ((u32_t)((int_ptr_t)(&(((struct nvm_image *)0)->f))))
+
+struct hw_set_info {
+ u32 reg_type;
+#define GRC_REG_TYPE 1
+#define PHY_REG_TYPE 2
+#define PCI_REG_TYPE 4
+
+ u32 bank_num;
+ u32 pf_num;
+ u32 operation;
+#define READ_OP 1
+#define WRITE_OP 2
+#define RMW_SET_OP 3
+#define RMW_CLR_OP 4
+
+ u32 reg_addr;
+ u32 reg_data;
+
+ u32 reset_type;
+#define POR_RESET_TYPE BIT(0)
+#define HARD_RESET_TYPE BIT(1)
+#define CORE_RESET_TYPE BIT(2)
+#define MCP_RESET_TYPE BIT(3)
+#define PERSET_ASSERT BIT(4)
+#define PERSET_DEASSERT BIT(5)
+};
+
+struct hw_set_image {
+ u32 format_version;
+#define HW_SET_IMAGE_VERSION 1
+ u32 no_hw_sets;
+
+ /* This array length depends on the no_hw_sets */
+ struct hw_set_info hw_sets[1];
+};
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c
new file mode 100644
index 000000000000..ffa99273b353
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c
@@ -0,0 +1,776 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/qed/qed_chain.h>
+#include "qed.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_reg_addr.h"
+
+#define QED_BAR_ACQUIRE_TIMEOUT 1000
+
+/* Invalid values */
+#define QED_BAR_INVALID_OFFSET (cpu_to_le32(-1))
+
+struct qed_ptt {
+ struct list_head list_entry;
+ unsigned int idx;
+ struct pxp_ptt_entry pxp;
+};
+
+struct qed_ptt_pool {
+ struct list_head free_list;
+ spinlock_t lock; /* ptt synchronized access */
+ struct qed_ptt ptts[PXP_EXTERNAL_BAR_PF_WINDOW_NUM];
+};
+
+int qed_ptt_pool_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ptt_pool *p_pool = kmalloc(sizeof(*p_pool),
+ GFP_ATOMIC);
+ int i;
+
+ if (!p_pool)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&p_pool->free_list);
+ for (i = 0; i < PXP_EXTERNAL_BAR_PF_WINDOW_NUM; i++) {
+ p_pool->ptts[i].idx = i;
+ p_pool->ptts[i].pxp.offset = QED_BAR_INVALID_OFFSET;
+ p_pool->ptts[i].pxp.pretend.control = 0;
+ if (i >= RESERVED_PTT_MAX)
+ list_add(&p_pool->ptts[i].list_entry,
+ &p_pool->free_list);
+ }
+
+ p_hwfn->p_ptt_pool = p_pool;
+ spin_lock_init(&p_pool->lock);
+
+ return 0;
+}
+
+void qed_ptt_invalidate(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ptt *p_ptt;
+ int i;
+
+ for (i = 0; i < PXP_EXTERNAL_BAR_PF_WINDOW_NUM; i++) {
+ p_ptt = &p_hwfn->p_ptt_pool->ptts[i];
+ p_ptt->pxp.offset = QED_BAR_INVALID_OFFSET;
+ }
+}
+
+void qed_ptt_pool_free(struct qed_hwfn *p_hwfn)
+{
+ kfree(p_hwfn->p_ptt_pool);
+ p_hwfn->p_ptt_pool = NULL;
+}
+
+struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ptt *p_ptt;
+ unsigned int i;
+
+ /* Take the free PTT from the list */
+ for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) {
+ spin_lock_bh(&p_hwfn->p_ptt_pool->lock);
+
+ if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) {
+ p_ptt = list_first_entry(&p_hwfn->p_ptt_pool->free_list,
+ struct qed_ptt, list_entry);
+ list_del(&p_ptt->list_entry);
+
+ spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "allocated ptt %d\n", p_ptt->idx);
+ return p_ptt;
+ }
+
+ spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
+ usleep_range(1000, 2000);
+ }
+
+ DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n");
+ return NULL;
+}
+
+void qed_ptt_release(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ spin_lock_bh(&p_hwfn->p_ptt_pool->lock);
+ list_add(&p_ptt->list_entry, &p_hwfn->p_ptt_pool->free_list);
+ spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
+}
+
+u32 qed_ptt_get_hw_addr(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ /* The HW is using DWORDS and we need to translate it to Bytes */
+ return le32_to_cpu(p_ptt->pxp.offset) << 2;
+}
+
+static u32 qed_ptt_config_addr(struct qed_ptt *p_ptt)
+{
+ return PXP_PF_WINDOW_ADMIN_PER_PF_START +
+ p_ptt->idx * sizeof(struct pxp_ptt_entry);
+}
+
+u32 qed_ptt_get_bar_addr(struct qed_ptt *p_ptt)
+{
+ return PXP_EXTERNAL_BAR_PF_WINDOW_START +
+ p_ptt->idx * PXP_EXTERNAL_BAR_PF_WINDOW_SINGLE_SIZE;
+}
+
+void qed_ptt_set_win(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 new_hw_addr)
+{
+ u32 prev_hw_addr;
+
+ prev_hw_addr = qed_ptt_get_hw_addr(p_hwfn, p_ptt);
+
+ if (new_hw_addr == prev_hw_addr)
+ return;
+
+ /* Update PTT entery in admin window */
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "Updating PTT entry %d to offset 0x%x\n",
+ p_ptt->idx, new_hw_addr);
+
+ /* The HW is using DWORDS and the address is in Bytes */
+ p_ptt->pxp.offset = cpu_to_le32(new_hw_addr >> 2);
+
+ REG_WR(p_hwfn,
+ qed_ptt_config_addr(p_ptt) +
+ offsetof(struct pxp_ptt_entry, offset),
+ le32_to_cpu(p_ptt->pxp.offset));
+}
+
+static u32 qed_set_ptt(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr)
+{
+ u32 win_hw_addr = qed_ptt_get_hw_addr(p_hwfn, p_ptt);
+ u32 offset;
+
+ offset = hw_addr - win_hw_addr;
+
+ /* Verify the address is within the window */
+ if (hw_addr < win_hw_addr ||
+ offset >= PXP_EXTERNAL_BAR_PF_WINDOW_SINGLE_SIZE) {
+ qed_ptt_set_win(p_hwfn, p_ptt, hw_addr);
+ offset = 0;
+ }
+
+ return qed_ptt_get_bar_addr(p_ptt) + offset;
+}
+
+struct qed_ptt *qed_get_reserved_ptt(struct qed_hwfn *p_hwfn,
+ enum reserved_ptts ptt_idx)
+{
+ if (ptt_idx >= RESERVED_PTT_MAX) {
+ DP_NOTICE(p_hwfn,
+ "Requested PTT %d is out of range\n", ptt_idx);
+ return NULL;
+ }
+
+ return &p_hwfn->p_ptt_pool->ptts[ptt_idx];
+}
+
+void qed_wr(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr, u32 val)
+{
+ u32 bar_addr = qed_set_ptt(p_hwfn, p_ptt, hw_addr);
+
+ REG_WR(p_hwfn, bar_addr, val);
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "bar_addr 0x%x, hw_addr 0x%x, val 0x%x\n",
+ bar_addr, hw_addr, val);
+}
+
+u32 qed_rd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr)
+{
+ u32 bar_addr = qed_set_ptt(p_hwfn, p_ptt, hw_addr);
+ u32 val = REG_RD(p_hwfn, bar_addr);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "bar_addr 0x%x, hw_addr 0x%x, val 0x%x\n",
+ bar_addr, hw_addr, val);
+
+ return val;
+}
+
+static void qed_memcpy_hw(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ void *addr,
+ u32 hw_addr,
+ size_t n,
+ bool to_device)
+{
+ u32 dw_count, *host_addr, hw_offset;
+ size_t quota, done = 0;
+ u32 __iomem *reg_addr;
+
+ while (done < n) {
+ quota = min_t(size_t, n - done,
+ PXP_EXTERNAL_BAR_PF_WINDOW_SINGLE_SIZE);
+
+ qed_ptt_set_win(p_hwfn, p_ptt, hw_addr + done);
+ hw_offset = qed_ptt_get_bar_addr(p_ptt);
+
+ dw_count = quota / 4;
+ host_addr = (u32 *)((u8 *)addr + done);
+ reg_addr = (u32 __iomem *)REG_ADDR(p_hwfn, hw_offset);
+ if (to_device)
+ while (dw_count--)
+ DIRECT_REG_WR(reg_addr++, *host_addr++);
+ else
+ while (dw_count--)
+ *host_addr++ = DIRECT_REG_RD(reg_addr++);
+
+ done += quota;
+ }
+}
+
+void qed_memcpy_from(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ void *dest, u32 hw_addr, size_t n)
+{
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "hw_addr 0x%x, dest %p hw_addr 0x%x, size %lu\n",
+ hw_addr, dest, hw_addr, (unsigned long)n);
+
+ qed_memcpy_hw(p_hwfn, p_ptt, dest, hw_addr, n, false);
+}
+
+void qed_memcpy_to(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr, void *src, size_t n)
+{
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "hw_addr 0x%x, hw_addr 0x%x, src %p size %lu\n",
+ hw_addr, hw_addr, src, (unsigned long)n);
+
+ qed_memcpy_hw(p_hwfn, p_ptt, src, hw_addr, n, true);
+}
+
+void qed_fid_pretend(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u16 fid)
+{
+ u16 control = 0;
+
+ SET_FIELD(control, PXP_PRETEND_CMD_IS_CONCRETE, 1);
+ SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_FUNCTION, 1);
+
+ /* Every pretend undos previous pretends, including
+ * previous port pretend.
+ */
+ SET_FIELD(control, PXP_PRETEND_CMD_PORT, 0);
+ SET_FIELD(control, PXP_PRETEND_CMD_USE_PORT, 0);
+ SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_PORT, 1);
+
+ if (!GET_FIELD(fid, PXP_CONCRETE_FID_VFVALID))
+ fid = GET_FIELD(fid, PXP_CONCRETE_FID_PFID);
+
+ p_ptt->pxp.pretend.control = cpu_to_le16(control);
+ p_ptt->pxp.pretend.fid.concrete_fid.fid = cpu_to_le16(fid);
+
+ REG_WR(p_hwfn,
+ qed_ptt_config_addr(p_ptt) +
+ offsetof(struct pxp_ptt_entry, pretend),
+ *(u32 *)&p_ptt->pxp.pretend);
+}
+
+void qed_port_pretend(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 port_id)
+{
+ u16 control = 0;
+
+ SET_FIELD(control, PXP_PRETEND_CMD_PORT, port_id);
+ SET_FIELD(control, PXP_PRETEND_CMD_USE_PORT, 1);
+ SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_PORT, 1);
+
+ p_ptt->pxp.pretend.control = cpu_to_le16(control);
+
+ REG_WR(p_hwfn,
+ qed_ptt_config_addr(p_ptt) +
+ offsetof(struct pxp_ptt_entry, pretend),
+ *(u32 *)&p_ptt->pxp.pretend);
+}
+
+void qed_port_unpretend(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u16 control = 0;
+
+ SET_FIELD(control, PXP_PRETEND_CMD_PORT, 0);
+ SET_FIELD(control, PXP_PRETEND_CMD_USE_PORT, 0);
+ SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_PORT, 1);
+
+ p_ptt->pxp.pretend.control = cpu_to_le16(control);
+
+ REG_WR(p_hwfn,
+ qed_ptt_config_addr(p_ptt) +
+ offsetof(struct pxp_ptt_entry, pretend),
+ *(u32 *)&p_ptt->pxp.pretend);
+}
+
+/* DMAE */
+static void qed_dmae_opcode(struct qed_hwfn *p_hwfn,
+ const u8 is_src_type_grc,
+ const u8 is_dst_type_grc,
+ struct qed_dmae_params *p_params)
+{
+ u32 opcode = 0;
+ u16 opcodeB = 0;
+
+ /* Whether the source is the PCIe or the GRC.
+ * 0- The source is the PCIe
+ * 1- The source is the GRC.
+ */
+ opcode |= (is_src_type_grc ? DMAE_CMD_SRC_MASK_GRC
+ : DMAE_CMD_SRC_MASK_PCIE) <<
+ DMAE_CMD_SRC_SHIFT;
+ opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_SRC_PF_ID_MASK) <<
+ DMAE_CMD_SRC_PF_ID_SHIFT);
+
+ /* The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */
+ opcode |= (is_dst_type_grc ? DMAE_CMD_DST_MASK_GRC
+ : DMAE_CMD_DST_MASK_PCIE) <<
+ DMAE_CMD_DST_SHIFT;
+ opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_DST_PF_ID_MASK) <<
+ DMAE_CMD_DST_PF_ID_SHIFT);
+
+ /* Whether to write a completion word to the completion destination:
+ * 0-Do not write a completion word
+ * 1-Write the completion word
+ */
+ opcode |= (DMAE_CMD_COMP_WORD_EN_MASK << DMAE_CMD_COMP_WORD_EN_SHIFT);
+ opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK <<
+ DMAE_CMD_SRC_ADDR_RESET_SHIFT);
+
+ if (p_params->flags & QED_DMAE_FLAG_COMPLETION_DST)
+ opcode |= (1 << DMAE_CMD_COMP_FUNC_SHIFT);
+
+ opcode |= (DMAE_CMD_ENDIANITY << DMAE_CMD_ENDIANITY_MODE_SHIFT);
+
+ opcode |= ((p_hwfn->port_id) << DMAE_CMD_PORT_ID_SHIFT);
+
+ /* reset source address in next go */
+ opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK <<
+ DMAE_CMD_SRC_ADDR_RESET_SHIFT);
+
+ /* reset dest address in next go */
+ opcode |= (DMAE_CMD_DST_ADDR_RESET_MASK <<
+ DMAE_CMD_DST_ADDR_RESET_SHIFT);
+
+ opcodeB |= (DMAE_CMD_SRC_VF_ID_MASK <<
+ DMAE_CMD_SRC_VF_ID_SHIFT);
+
+ opcodeB |= (DMAE_CMD_DST_VF_ID_MASK <<
+ DMAE_CMD_DST_VF_ID_SHIFT);
+
+ p_hwfn->dmae_info.p_dmae_cmd->opcode = cpu_to_le32(opcode);
+ p_hwfn->dmae_info.p_dmae_cmd->opcode_b = cpu_to_le16(opcodeB);
+}
+
+u32 qed_dmae_idx_to_go_cmd(u8 idx)
+{
+ /* All the DMAE 'go' registers form an array in internal memory */
+ return DMAE_REG_GO_C0 + (idx << 2);
+}
+
+static int
+qed_dmae_post_command(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct dmae_cmd *command = p_hwfn->dmae_info.p_dmae_cmd;
+ u8 idx_cmd = p_hwfn->dmae_info.channel, i;
+ int qed_status = 0;
+
+ /* verify address is not NULL */
+ if ((((command->dst_addr_lo == 0) && (command->dst_addr_hi == 0)) ||
+ ((command->src_addr_lo == 0) && (command->src_addr_hi == 0)))) {
+ DP_NOTICE(p_hwfn,
+ "source or destination address 0 idx_cmd=%d\n"
+ "opcode = [0x%08x,0x%04x] len=0x%x src=0x%x:%x dst=0x%x:%x\n",
+ idx_cmd,
+ le32_to_cpu(command->opcode),
+ le16_to_cpu(command->opcode_b),
+ le16_to_cpu(command->length),
+ le32_to_cpu(command->src_addr_hi),
+ le32_to_cpu(command->src_addr_lo),
+ le32_to_cpu(command->dst_addr_hi),
+ le32_to_cpu(command->dst_addr_lo));
+
+ return -EINVAL;
+ }
+
+ DP_VERBOSE(p_hwfn,
+ NETIF_MSG_HW,
+ "Posting DMAE command [idx %d]: opcode = [0x%08x,0x%04x] len=0x%x src=0x%x:%x dst=0x%x:%x\n",
+ idx_cmd,
+ le32_to_cpu(command->opcode),
+ le16_to_cpu(command->opcode_b),
+ le16_to_cpu(command->length),
+ le32_to_cpu(command->src_addr_hi),
+ le32_to_cpu(command->src_addr_lo),
+ le32_to_cpu(command->dst_addr_hi),
+ le32_to_cpu(command->dst_addr_lo));
+
+ /* Copy the command to DMAE - need to do it before every call
+ * for source/dest address no reset.
+ * The first 9 DWs are the command registers, the 10 DW is the
+ * GO register, and the rest are result registers
+ * (which are read only by the client).
+ */
+ for (i = 0; i < DMAE_CMD_SIZE; i++) {
+ u32 data = (i < DMAE_CMD_SIZE_TO_FILL) ?
+ *(((u32 *)command) + i) : 0;
+
+ qed_wr(p_hwfn, p_ptt,
+ DMAE_REG_CMD_MEM +
+ (idx_cmd * DMAE_CMD_SIZE * sizeof(u32)) +
+ (i * sizeof(u32)), data);
+ }
+
+ qed_wr(p_hwfn, p_ptt,
+ qed_dmae_idx_to_go_cmd(idx_cmd),
+ DMAE_GO_VALUE);
+
+ return qed_status;
+}
+
+int qed_dmae_info_alloc(struct qed_hwfn *p_hwfn)
+{
+ dma_addr_t *p_addr = &p_hwfn->dmae_info.completion_word_phys_addr;
+ struct dmae_cmd **p_cmd = &p_hwfn->dmae_info.p_dmae_cmd;
+ u32 **p_buff = &p_hwfn->dmae_info.p_intermediate_buffer;
+ u32 **p_comp = &p_hwfn->dmae_info.p_completion_word;
+
+ *p_comp = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(u32),
+ p_addr,
+ GFP_KERNEL);
+ if (!*p_comp) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `p_completion_word'\n");
+ goto err;
+ }
+
+ p_addr = &p_hwfn->dmae_info.dmae_cmd_phys_addr;
+ *p_cmd = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(struct dmae_cmd),
+ p_addr, GFP_KERNEL);
+ if (!*p_cmd) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `struct dmae_cmd'\n");
+ goto err;
+ }
+
+ p_addr = &p_hwfn->dmae_info.intermediate_buffer_phys_addr;
+ *p_buff = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(u32) * DMAE_MAX_RW_SIZE,
+ p_addr, GFP_KERNEL);
+ if (!*p_buff) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `intermediate_buffer'\n");
+ goto err;
+ }
+
+ p_hwfn->dmae_info.channel = p_hwfn->rel_pf_id;
+
+ return 0;
+err:
+ qed_dmae_info_free(p_hwfn);
+ return -ENOMEM;
+}
+
+void qed_dmae_info_free(struct qed_hwfn *p_hwfn)
+{
+ dma_addr_t p_phys;
+
+ /* Just make sure no one is in the middle */
+ mutex_lock(&p_hwfn->dmae_info.mutex);
+
+ if (p_hwfn->dmae_info.p_completion_word) {
+ p_phys = p_hwfn->dmae_info.completion_word_phys_addr;
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(u32),
+ p_hwfn->dmae_info.p_completion_word,
+ p_phys);
+ p_hwfn->dmae_info.p_completion_word = NULL;
+ }
+
+ if (p_hwfn->dmae_info.p_dmae_cmd) {
+ p_phys = p_hwfn->dmae_info.dmae_cmd_phys_addr;
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(struct dmae_cmd),
+ p_hwfn->dmae_info.p_dmae_cmd,
+ p_phys);
+ p_hwfn->dmae_info.p_dmae_cmd = NULL;
+ }
+
+ if (p_hwfn->dmae_info.p_intermediate_buffer) {
+ p_phys = p_hwfn->dmae_info.intermediate_buffer_phys_addr;
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(u32) * DMAE_MAX_RW_SIZE,
+ p_hwfn->dmae_info.p_intermediate_buffer,
+ p_phys);
+ p_hwfn->dmae_info.p_intermediate_buffer = NULL;
+ }
+
+ mutex_unlock(&p_hwfn->dmae_info.mutex);
+}
+
+static int qed_dmae_operation_wait(struct qed_hwfn *p_hwfn)
+{
+ u32 wait_cnt = 0;
+ u32 wait_cnt_limit = 10000;
+
+ int qed_status = 0;
+
+ barrier();
+ while (*p_hwfn->dmae_info.p_completion_word != DMAE_COMPLETION_VAL) {
+ udelay(DMAE_MIN_WAIT_TIME);
+ if (++wait_cnt > wait_cnt_limit) {
+ DP_NOTICE(p_hwfn->cdev,
+ "Timed-out waiting for operation to complete. Completion word is 0x%08x expected 0x%08x.\n",
+ *p_hwfn->dmae_info.p_completion_word,
+ DMAE_COMPLETION_VAL);
+ qed_status = -EBUSY;
+ break;
+ }
+
+ /* to sync the completion_word since we are not
+ * using the volatile keyword for p_completion_word
+ */
+ barrier();
+ }
+
+ if (qed_status == 0)
+ *p_hwfn->dmae_info.p_completion_word = 0;
+
+ return qed_status;
+}
+
+static int qed_dmae_execute_sub_operation(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u64 src_addr,
+ u64 dst_addr,
+ u8 src_type,
+ u8 dst_type,
+ u32 length)
+{
+ dma_addr_t phys = p_hwfn->dmae_info.intermediate_buffer_phys_addr;
+ struct dmae_cmd *cmd = p_hwfn->dmae_info.p_dmae_cmd;
+ int qed_status = 0;
+
+ switch (src_type) {
+ case QED_DMAE_ADDRESS_GRC:
+ case QED_DMAE_ADDRESS_HOST_PHYS:
+ cmd->src_addr_hi = cpu_to_le32(upper_32_bits(src_addr));
+ cmd->src_addr_lo = cpu_to_le32(lower_32_bits(src_addr));
+ break;
+ /* for virtual source addresses we use the intermediate buffer. */
+ case QED_DMAE_ADDRESS_HOST_VIRT:
+ cmd->src_addr_hi = cpu_to_le32(upper_32_bits(phys));
+ cmd->src_addr_lo = cpu_to_le32(lower_32_bits(phys));
+ memcpy(&p_hwfn->dmae_info.p_intermediate_buffer[0],
+ (void *)(uintptr_t)src_addr,
+ length * sizeof(u32));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dst_type) {
+ case QED_DMAE_ADDRESS_GRC:
+ case QED_DMAE_ADDRESS_HOST_PHYS:
+ cmd->dst_addr_hi = cpu_to_le32(upper_32_bits(dst_addr));
+ cmd->dst_addr_lo = cpu_to_le32(lower_32_bits(dst_addr));
+ break;
+ /* for virtual source addresses we use the intermediate buffer. */
+ case QED_DMAE_ADDRESS_HOST_VIRT:
+ cmd->dst_addr_hi = cpu_to_le32(upper_32_bits(phys));
+ cmd->dst_addr_lo = cpu_to_le32(lower_32_bits(phys));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cmd->length = cpu_to_le16((u16)length);
+
+ qed_dmae_post_command(p_hwfn, p_ptt);
+
+ qed_status = qed_dmae_operation_wait(p_hwfn);
+
+ if (qed_status) {
+ DP_NOTICE(p_hwfn,
+ "qed_dmae_host2grc: Wait Failed. source_addr 0x%llx, grc_addr 0x%llx, size_in_dwords 0x%x\n",
+ src_addr,
+ dst_addr,
+ length);
+ return qed_status;
+ }
+
+ if (dst_type == QED_DMAE_ADDRESS_HOST_VIRT)
+ memcpy((void *)(uintptr_t)(dst_addr),
+ &p_hwfn->dmae_info.p_intermediate_buffer[0],
+ length * sizeof(u32));
+
+ return 0;
+}
+
+static int qed_dmae_execute_command(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u64 src_addr, u64 dst_addr,
+ u8 src_type, u8 dst_type,
+ u32 size_in_dwords,
+ struct qed_dmae_params *p_params)
+{
+ dma_addr_t phys = p_hwfn->dmae_info.completion_word_phys_addr;
+ u16 length_cur = 0, i = 0, cnt_split = 0, length_mod = 0;
+ struct dmae_cmd *cmd = p_hwfn->dmae_info.p_dmae_cmd;
+ u64 src_addr_split = 0, dst_addr_split = 0;
+ u16 length_limit = DMAE_MAX_RW_SIZE;
+ int qed_status = 0;
+ u32 offset = 0;
+
+ qed_dmae_opcode(p_hwfn,
+ (src_type == QED_DMAE_ADDRESS_GRC),
+ (dst_type == QED_DMAE_ADDRESS_GRC),
+ p_params);
+
+ cmd->comp_addr_lo = cpu_to_le32(lower_32_bits(phys));
+ cmd->comp_addr_hi = cpu_to_le32(upper_32_bits(phys));
+ cmd->comp_val = cpu_to_le32(DMAE_COMPLETION_VAL);
+
+ /* Check if the grc_addr is valid like < MAX_GRC_OFFSET */
+ cnt_split = size_in_dwords / length_limit;
+ length_mod = size_in_dwords % length_limit;
+
+ src_addr_split = src_addr;
+ dst_addr_split = dst_addr;
+
+ for (i = 0; i <= cnt_split; i++) {
+ offset = length_limit * i;
+
+ if (!(p_params->flags & QED_DMAE_FLAG_RW_REPL_SRC)) {
+ if (src_type == QED_DMAE_ADDRESS_GRC)
+ src_addr_split = src_addr + offset;
+ else
+ src_addr_split = src_addr + (offset * 4);
+ }
+
+ if (dst_type == QED_DMAE_ADDRESS_GRC)
+ dst_addr_split = dst_addr + offset;
+ else
+ dst_addr_split = dst_addr + (offset * 4);
+
+ length_cur = (cnt_split == i) ? length_mod : length_limit;
+
+ /* might be zero on last iteration */
+ if (!length_cur)
+ continue;
+
+ qed_status = qed_dmae_execute_sub_operation(p_hwfn,
+ p_ptt,
+ src_addr_split,
+ dst_addr_split,
+ src_type,
+ dst_type,
+ length_cur);
+ if (qed_status) {
+ DP_NOTICE(p_hwfn,
+ "qed_dmae_execute_sub_operation Failed with error 0x%x. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n",
+ qed_status,
+ src_addr,
+ dst_addr,
+ length_cur);
+ break;
+ }
+ }
+
+ return qed_status;
+}
+
+int qed_dmae_host2grc(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u64 source_addr,
+ u32 grc_addr,
+ u32 size_in_dwords,
+ u32 flags)
+{
+ u32 grc_addr_in_dw = grc_addr / sizeof(u32);
+ struct qed_dmae_params params;
+ int rc;
+
+ memset(&params, 0, sizeof(struct qed_dmae_params));
+ params.flags = flags;
+
+ mutex_lock(&p_hwfn->dmae_info.mutex);
+
+ rc = qed_dmae_execute_command(p_hwfn, p_ptt, source_addr,
+ grc_addr_in_dw,
+ QED_DMAE_ADDRESS_HOST_VIRT,
+ QED_DMAE_ADDRESS_GRC,
+ size_in_dwords, &params);
+
+ mutex_unlock(&p_hwfn->dmae_info.mutex);
+
+ return rc;
+}
+
+u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn,
+ enum protocol_type proto,
+ union qed_qm_pq_params *p_params)
+{
+ u16 pq_id = 0;
+
+ if ((proto == PROTOCOLID_CORE || proto == PROTOCOLID_ETH) &&
+ !p_params) {
+ DP_NOTICE(p_hwfn,
+ "Protocol %d received NULL PQ params\n",
+ proto);
+ return 0;
+ }
+
+ switch (proto) {
+ case PROTOCOLID_CORE:
+ if (p_params->core.tc == LB_TC)
+ pq_id = p_hwfn->qm_info.pure_lb_pq;
+ else
+ pq_id = p_hwfn->qm_info.offload_pq;
+ break;
+ case PROTOCOLID_ETH:
+ pq_id = p_params->eth.tc;
+ break;
+ default:
+ pq_id = 0;
+ }
+
+ pq_id = CM_TX_PQ_BASE + pq_id + RESC_START(p_hwfn, QED_PQ);
+
+ return pq_id;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.h b/drivers/net/ethernet/qlogic/qed/qed_hw.h
new file mode 100644
index 000000000000..e56d433793be
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_hw.h
@@ -0,0 +1,263 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_HW_H
+#define _QED_HW_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "qed.h"
+#include "qed_dev_api.h"
+
+/* Forward decleration */
+struct qed_ptt;
+
+enum reserved_ptts {
+ RESERVED_PTT_EDIAG,
+ RESERVED_PTT_USER_SPACE,
+ RESERVED_PTT_MAIN,
+ RESERVED_PTT_DPC,
+ RESERVED_PTT_MAX
+};
+
+enum _dmae_cmd_dst_mask {
+ DMAE_CMD_DST_MASK_NONE = 0,
+ DMAE_CMD_DST_MASK_PCIE = 1,
+ DMAE_CMD_DST_MASK_GRC = 2
+};
+
+enum _dmae_cmd_src_mask {
+ DMAE_CMD_SRC_MASK_PCIE = 0,
+ DMAE_CMD_SRC_MASK_GRC = 1
+};
+
+enum _dmae_cmd_crc_mask {
+ DMAE_CMD_COMP_CRC_EN_MASK_NONE = 0,
+ DMAE_CMD_COMP_CRC_EN_MASK_SET = 1
+};
+
+/* definitions for DMA constants */
+#define DMAE_GO_VALUE 0x1
+
+#define DMAE_COMPLETION_VAL 0xD1AE
+#define DMAE_CMD_ENDIANITY 0x2
+
+#define DMAE_CMD_SIZE 14
+#define DMAE_CMD_SIZE_TO_FILL (DMAE_CMD_SIZE - 5)
+#define DMAE_MIN_WAIT_TIME 0x2
+#define DMAE_MAX_CLIENTS 32
+
+/**
+ * @brief qed_gtt_init - Initialize GTT windows
+ *
+ * @param p_hwfn
+ */
+void qed_gtt_init(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_ptt_invalidate - Forces all ptt entries to be re-configured
+ *
+ * @param p_hwfn
+ */
+void qed_ptt_invalidate(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_ptt_pool_alloc - Allocate and initialize PTT pool
+ *
+ * @param p_hwfn
+ *
+ * @return struct _qed_status - success (0), negative - error.
+ */
+int qed_ptt_pool_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_ptt_pool_free -
+ *
+ * @param p_hwfn
+ */
+void qed_ptt_pool_free(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_ptt_get_hw_addr - Get PTT's GRC/HW address
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return u32
+ */
+u32 qed_ptt_get_hw_addr(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief qed_ptt_get_bar_addr - Get PPT's external BAR address
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return u32
+ */
+u32 qed_ptt_get_bar_addr(struct qed_ptt *p_ptt);
+
+/**
+ * @brief qed_ptt_set_win - Set PTT Window's GRC BAR address
+ *
+ * @param p_hwfn
+ * @param new_hw_addr
+ * @param p_ptt
+ */
+void qed_ptt_set_win(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 new_hw_addr);
+
+/**
+ * @brief qed_get_reserved_ptt - Get a specific reserved PTT
+ *
+ * @param p_hwfn
+ * @param ptt_idx
+ *
+ * @return struct qed_ptt *
+ */
+struct qed_ptt *qed_get_reserved_ptt(struct qed_hwfn *p_hwfn,
+ enum reserved_ptts ptt_idx);
+
+/**
+ * @brief qed_wr - Write value to BAR using the given ptt
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param val
+ * @param hw_addr
+ */
+void qed_wr(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr,
+ u32 val);
+
+/**
+ * @brief qed_rd - Read value from BAR using the given ptt
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param val
+ * @param hw_addr
+ */
+u32 qed_rd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr);
+
+/**
+ * @brief qed_memcpy_from - copy n bytes from BAR using the given
+ * ptt
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param dest
+ * @param hw_addr
+ * @param n
+ */
+void qed_memcpy_from(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ void *dest,
+ u32 hw_addr,
+ size_t n);
+
+/**
+ * @brief qed_memcpy_to - copy n bytes to BAR using the given
+ * ptt
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param hw_addr
+ * @param src
+ * @param n
+ */
+void qed_memcpy_to(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 hw_addr,
+ void *src,
+ size_t n);
+/**
+ * @brief qed_fid_pretend - pretend to another function when
+ * accessing the ptt window. There is no way to unpretend
+ * a function. The only way to cancel a pretend is to
+ * pretend back to the original function.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param fid - fid field of pxp_pretend structure. Can contain
+ * either pf / vf, port/path fields are don't care.
+ */
+void qed_fid_pretend(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u16 fid);
+
+/**
+ * @brief qed_port_pretend - pretend to another port when
+ * accessing the ptt window
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param port_id - the port to pretend to
+ */
+void qed_port_pretend(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 port_id);
+
+/**
+ * @brief qed_port_unpretend - cancel any previously set port
+ * pretend
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+void qed_port_unpretend(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief qed_dmae_idx_to_go_cmd - map the idx to dmae cmd
+ * this is declared here since other files will require it.
+ * @param idx
+ */
+u32 qed_dmae_idx_to_go_cmd(u8 idx);
+
+/**
+ * @brief qed_dmae_info_alloc - Init the dmae_info structure
+ * which is part of p_hwfn.
+ * @param p_hwfn
+ */
+int qed_dmae_info_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_dmae_info_free - Free the dmae_info structure
+ * which is part of p_hwfn
+ *
+ * @param p_hwfn
+ */
+void qed_dmae_info_free(struct qed_hwfn *p_hwfn);
+
+union qed_qm_pq_params {
+ struct {
+ u8 tc;
+ } core;
+
+ struct {
+ u8 is_vf;
+ u8 vf_id;
+ u8 tc;
+ } eth;
+};
+
+u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn,
+ enum protocol_type proto,
+ union qed_qm_pq_params *params);
+
+int qed_init_fw_data(struct qed_dev *cdev,
+ const u8 *fw_data);
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c
new file mode 100644
index 000000000000..0b21a553cc7d
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c
@@ -0,0 +1,798 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_init_ops.h"
+#include "qed_reg_addr.h"
+
+enum cminterface {
+ MCM_SEC,
+ MCM_PRI,
+ UCM_SEC,
+ UCM_PRI,
+ TCM_SEC,
+ TCM_PRI,
+ YCM_SEC,
+ YCM_PRI,
+ XCM_SEC,
+ XCM_PRI,
+ NUM_OF_CM_INTERFACES
+};
+
+/* general constants */
+#define QM_PQ_ELEMENT_SIZE 4 /* in bytes */
+#define QM_PQ_MEM_4KB(pq_size) (pq_size ? DIV_ROUND_UP((pq_size + 1) * \
+ QM_PQ_ELEMENT_SIZE, \
+ 0x1000) : 0)
+#define QM_PQ_SIZE_256B(pq_size) (pq_size ? DIV_ROUND_UP(pq_size, \
+ 0x100) - 1 : 0)
+#define QM_INVALID_PQ_ID 0xffff
+/* feature enable */
+#define QM_BYPASS_EN 1
+#define QM_BYTE_CRD_EN 1
+/* other PQ constants */
+#define QM_OTHER_PQS_PER_PF 4
+/* WFQ constants */
+#define QM_WFQ_UPPER_BOUND 6250000
+#define QM_WFQ_VP_PQ_VOQ_SHIFT 0
+#define QM_WFQ_VP_PQ_PF_SHIFT 5
+#define QM_WFQ_INC_VAL(weight) ((weight) * 0x9000)
+#define QM_WFQ_MAX_INC_VAL 4375000
+#define QM_WFQ_INIT_CRD(inc_val) (2 * (inc_val))
+/* RL constants */
+#define QM_RL_UPPER_BOUND 6250000
+#define QM_RL_PERIOD 5 /* in us */
+#define QM_RL_PERIOD_CLK_25M (25 * QM_RL_PERIOD)
+#define QM_RL_INC_VAL(rate) max_t(u32, \
+ (((rate ? rate : 1000000) \
+ * QM_RL_PERIOD) / 8), 1)
+#define QM_RL_MAX_INC_VAL 4375000
+/* AFullOprtnstcCrdMask constants */
+#define QM_OPPOR_LINE_VOQ_DEF 1
+#define QM_OPPOR_FW_STOP_DEF 0
+#define QM_OPPOR_PQ_EMPTY_DEF 1
+#define EAGLE_WORKAROUND_TC 7
+/* Command Queue constants */
+#define PBF_CMDQ_PURE_LB_LINES 150
+#define PBF_CMDQ_EAGLE_WORKAROUND_LINES 8
+#define PBF_CMDQ_LINES_RT_OFFSET(voq) ( \
+ PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET + voq * \
+ (PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET - \
+ PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET))
+#define PBF_BTB_GUARANTEED_RT_OFFSET(voq) ( \
+ PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET + voq * \
+ (PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET - \
+ PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET))
+#define QM_VOQ_LINE_CRD(pbf_cmd_lines) ((((pbf_cmd_lines) - \
+ 4) * \
+ 2) | QM_LINE_CRD_REG_SIGN_BIT)
+/* BTB: blocks constants (block size = 256B) */
+#define BTB_JUMBO_PKT_BLOCKS 38
+#define BTB_HEADROOM_BLOCKS BTB_JUMBO_PKT_BLOCKS
+#define BTB_EAGLE_WORKAROUND_BLOCKS 4
+#define BTB_PURE_LB_FACTOR 10
+#define BTB_PURE_LB_RATIO 7
+/* QM stop command constants */
+#define QM_STOP_PQ_MASK_WIDTH 32
+#define QM_STOP_CMD_ADDR 0x2
+#define QM_STOP_CMD_STRUCT_SIZE 2
+#define QM_STOP_CMD_PAUSE_MASK_OFFSET 0
+#define QM_STOP_CMD_PAUSE_MASK_SHIFT 0
+#define QM_STOP_CMD_PAUSE_MASK_MASK -1
+#define QM_STOP_CMD_GROUP_ID_OFFSET 1
+#define QM_STOP_CMD_GROUP_ID_SHIFT 16
+#define QM_STOP_CMD_GROUP_ID_MASK 15
+#define QM_STOP_CMD_PQ_TYPE_OFFSET 1
+#define QM_STOP_CMD_PQ_TYPE_SHIFT 24
+#define QM_STOP_CMD_PQ_TYPE_MASK 1
+#define QM_STOP_CMD_MAX_POLL_COUNT 100
+#define QM_STOP_CMD_POLL_PERIOD_US 500
+/* QM command macros */
+#define QM_CMD_STRUCT_SIZE(cmd) cmd ## \
+ _STRUCT_SIZE
+#define QM_CMD_SET_FIELD(var, cmd, field, \
+ value) SET_FIELD(var[cmd ## _ ## field ## \
+ _OFFSET], \
+ cmd ## _ ## field, \
+ value)
+/* QM: VOQ macros */
+#define PHYS_VOQ(port, tc, max_phy_tcs_pr_port) ((port) * \
+ (max_phy_tcs_pr_port) \
+ + (tc))
+#define LB_VOQ(port) ( \
+ MAX_PHYS_VOQS + (port))
+#define VOQ(port, tc, max_phy_tcs_pr_port) \
+ ((tc) < \
+ LB_TC ? PHYS_VOQ(port, \
+ tc, \
+ max_phy_tcs_pr_port) \
+ : LB_VOQ(port))
+/******************** INTERNAL IMPLEMENTATION *********************/
+/* Prepare PF RL enable/disable runtime init values */
+static void qed_enable_pf_rl(struct qed_hwfn *p_hwfn,
+ bool pf_rl_en)
+{
+ STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0);
+ if (pf_rl_en) {
+ /* enable RLs for all VOQs */
+ STORE_RT_REG(p_hwfn, QM_REG_RLPFVOQENABLE_RT_OFFSET,
+ (1 << MAX_NUM_VOQS) - 1);
+ /* write RL period */
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLPFPERIOD_RT_OFFSET,
+ QM_RL_PERIOD_CLK_25M);
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLPFPERIODTIMER_RT_OFFSET,
+ QM_RL_PERIOD_CLK_25M);
+ /* set credit threshold for QM bypass flow */
+ if (QM_BYPASS_EN)
+ STORE_RT_REG(p_hwfn,
+ QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET,
+ QM_RL_UPPER_BOUND);
+ }
+}
+
+/* Prepare PF WFQ enable/disable runtime init values */
+static void qed_enable_pf_wfq(struct qed_hwfn *p_hwfn,
+ bool pf_wfq_en)
+{
+ STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0);
+ /* set credit threshold for QM bypass flow */
+ if (pf_wfq_en && QM_BYPASS_EN)
+ STORE_RT_REG(p_hwfn,
+ QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET,
+ QM_WFQ_UPPER_BOUND);
+}
+
+/* Prepare VPORT RL enable/disable runtime init values */
+static void qed_enable_vport_rl(struct qed_hwfn *p_hwfn,
+ bool vport_rl_en)
+{
+ STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET,
+ vport_rl_en ? 1 : 0);
+ if (vport_rl_en) {
+ /* write RL period (use timer 0 only) */
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLGLBLPERIOD_0_RT_OFFSET,
+ QM_RL_PERIOD_CLK_25M);
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET,
+ QM_RL_PERIOD_CLK_25M);
+ /* set credit threshold for QM bypass flow */
+ if (QM_BYPASS_EN)
+ STORE_RT_REG(p_hwfn,
+ QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET,
+ QM_RL_UPPER_BOUND);
+ }
+}
+
+/* Prepare VPORT WFQ enable/disable runtime init values */
+static void qed_enable_vport_wfq(struct qed_hwfn *p_hwfn,
+ bool vport_wfq_en)
+{
+ STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET,
+ vport_wfq_en ? 1 : 0);
+ /* set credit threshold for QM bypass flow */
+ if (vport_wfq_en && QM_BYPASS_EN)
+ STORE_RT_REG(p_hwfn,
+ QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET,
+ QM_WFQ_UPPER_BOUND);
+}
+
+/* Prepare runtime init values to allocate PBF command queue lines for
+ * the specified VOQ
+ */
+static void qed_cmdq_lines_voq_rt_init(struct qed_hwfn *p_hwfn,
+ u8 voq,
+ u16 cmdq_lines)
+{
+ u32 qm_line_crd;
+
+ /* In A0 - Limit the size of pbf queue so that only 511 commands with
+ * the minimum size of 4 (FCoE minimum size)
+ */
+ bool is_bb_a0 = QED_IS_BB_A0(p_hwfn->cdev);
+
+ if (is_bb_a0)
+ cmdq_lines = min_t(u32, cmdq_lines, 1022);
+ qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines);
+ OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq),
+ (u32)cmdq_lines);
+ STORE_RT_REG(p_hwfn, QM_REG_VOQCRDLINE_RT_OFFSET + voq, qm_line_crd);
+ STORE_RT_REG(p_hwfn, QM_REG_VOQINITCRDLINE_RT_OFFSET + voq,
+ qm_line_crd);
+}
+
+/* Prepare runtime init values to allocate PBF command queue lines. */
+static void qed_cmdq_lines_rt_init(
+ struct qed_hwfn *p_hwfn,
+ u8 max_ports_per_engine,
+ u8 max_phys_tcs_per_port,
+ struct init_qm_port_params port_params[MAX_NUM_PORTS])
+{
+ u8 tc, voq, port_id;
+
+ /* clear PBF lines for all VOQs */
+ for (voq = 0; voq < MAX_NUM_VOQS; voq++)
+ STORE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), 0);
+ for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
+ if (port_params[port_id].active) {
+ u16 phys_lines, phys_lines_per_tc;
+ u8 phys_tcs = port_params[port_id].num_active_phys_tcs;
+
+ /* find #lines to divide between the active
+ * physical TCs.
+ */
+ phys_lines = port_params[port_id].num_pbf_cmd_lines -
+ PBF_CMDQ_PURE_LB_LINES;
+ /* find #lines per active physical TC */
+ phys_lines_per_tc = phys_lines / phys_tcs;
+ /* init registers per active TC */
+ for (tc = 0; tc < phys_tcs; tc++) {
+ voq = PHYS_VOQ(port_id, tc,
+ max_phys_tcs_per_port);
+ qed_cmdq_lines_voq_rt_init(p_hwfn, voq,
+ phys_lines_per_tc);
+ }
+ /* init registers for pure LB TC */
+ qed_cmdq_lines_voq_rt_init(p_hwfn, LB_VOQ(port_id),
+ PBF_CMDQ_PURE_LB_LINES);
+ }
+ }
+}
+
+static void qed_btb_blocks_rt_init(
+ struct qed_hwfn *p_hwfn,
+ u8 max_ports_per_engine,
+ u8 max_phys_tcs_per_port,
+ struct init_qm_port_params port_params[MAX_NUM_PORTS])
+{
+ u32 usable_blocks, pure_lb_blocks, phys_blocks;
+ u8 tc, voq, port_id;
+
+ for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
+ u32 temp;
+ u8 phys_tcs;
+
+ if (!port_params[port_id].active)
+ continue;
+
+ phys_tcs = port_params[port_id].num_active_phys_tcs;
+
+ /* subtract headroom blocks */
+ usable_blocks = port_params[port_id].num_btb_blocks -
+ BTB_HEADROOM_BLOCKS;
+
+ /* find blocks per physical TC. use factor to avoid
+ * floating arithmethic.
+ */
+ pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) /
+ (phys_tcs * BTB_PURE_LB_FACTOR +
+ BTB_PURE_LB_RATIO);
+ pure_lb_blocks = max_t(u32, BTB_JUMBO_PKT_BLOCKS,
+ pure_lb_blocks / BTB_PURE_LB_FACTOR);
+ phys_blocks = (usable_blocks - pure_lb_blocks) / phys_tcs;
+
+ /* init physical TCs */
+ for (tc = 0; tc < phys_tcs; tc++) {
+ voq = PHYS_VOQ(port_id, tc, max_phys_tcs_per_port);
+ STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(voq),
+ phys_blocks);
+ }
+
+ /* init pure LB TC */
+ temp = LB_VOQ(port_id);
+ STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(temp),
+ pure_lb_blocks);
+ }
+}
+
+/* Prepare Tx PQ mapping runtime init values for the specified PF */
+static void qed_tx_pq_map_rt_init(
+ struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_qm_pf_rt_init_params *p_params,
+ u32 base_mem_addr_4kb)
+{
+ struct init_qm_vport_params *vport_params = p_params->vport_params;
+ u16 num_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
+ u16 first_pq_group = p_params->start_pq / QM_PF_QUEUE_GROUP_SIZE;
+ u16 last_pq_group = (p_params->start_pq + num_pqs - 1) /
+ QM_PF_QUEUE_GROUP_SIZE;
+ bool is_bb_a0 = QED_IS_BB_A0(p_hwfn->cdev);
+ u16 i, pq_id, pq_group;
+
+ /* a bit per Tx PQ indicating if the PQ is associated with a VF */
+ u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 };
+ u32 tx_pq_vf_mask_width = is_bb_a0 ? 32 : QM_PF_QUEUE_GROUP_SIZE;
+ u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / tx_pq_vf_mask_width;
+ u32 pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids);
+ u32 vport_pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_vf_cids);
+ u32 mem_addr_4kb = base_mem_addr_4kb;
+
+ /* set mapping from PQ group to PF */
+ for (pq_group = first_pq_group; pq_group <= last_pq_group; pq_group++)
+ STORE_RT_REG(p_hwfn, QM_REG_PQTX2PF_0_RT_OFFSET + pq_group,
+ (u32)(p_params->pf_id));
+ /* set PQ sizes */
+ STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_0_RT_OFFSET,
+ QM_PQ_SIZE_256B(p_params->num_pf_cids));
+ STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_1_RT_OFFSET,
+ QM_PQ_SIZE_256B(p_params->num_vf_cids));
+
+ /* go over all Tx PQs */
+ for (i = 0, pq_id = p_params->start_pq; i < num_pqs; i++, pq_id++) {
+ u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id,
+ p_params->max_phys_tcs_per_port);
+ bool is_vf_pq = (i >= p_params->num_pf_pqs);
+ struct qm_rf_pq_map tx_pq_map;
+
+ /* update first Tx PQ of VPORT/TC */
+ u8 vport_id_in_pf = p_params->pq_params[i].vport_id -
+ p_params->start_vport;
+ u16 *pq_ids = &vport_params[vport_id_in_pf].first_tx_pq_id[0];
+ u16 first_tx_pq_id = pq_ids[p_params->pq_params[i].tc_id];
+
+ if (first_tx_pq_id == QM_INVALID_PQ_ID) {
+ /* create new VP PQ */
+ pq_ids[p_params->pq_params[i].tc_id] = pq_id;
+ first_tx_pq_id = pq_id;
+ /* map VP PQ to VOQ and PF */
+ STORE_RT_REG(p_hwfn,
+ QM_REG_WFQVPMAP_RT_OFFSET +
+ first_tx_pq_id,
+ (voq << QM_WFQ_VP_PQ_VOQ_SHIFT) |
+ (p_params->pf_id <<
+ QM_WFQ_VP_PQ_PF_SHIFT));
+ }
+ /* fill PQ map entry */
+ memset(&tx_pq_map, 0, sizeof(tx_pq_map));
+ SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_PQ_VALID, 1);
+ SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_VALID,
+ is_vf_pq ? 1 : 0);
+ SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VP_PQ_ID, first_tx_pq_id);
+ SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_ID,
+ is_vf_pq ? p_params->pq_params[i].vport_id : 0);
+ SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VOQ, voq);
+ SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_WRR_WEIGHT_GROUP,
+ p_params->pq_params[i].wrr_group);
+ /* write PQ map entry to CAM */
+ STORE_RT_REG(p_hwfn, QM_REG_TXPQMAP_RT_OFFSET + pq_id,
+ *((u32 *)&tx_pq_map));
+ /* set base address */
+ STORE_RT_REG(p_hwfn,
+ QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id,
+ mem_addr_4kb);
+ /* check if VF PQ */
+ if (is_vf_pq) {
+ /* if PQ is associated with a VF, add indication
+ * to PQ VF mask
+ */
+ tx_pq_vf_mask[pq_id / tx_pq_vf_mask_width] |=
+ (1 << (pq_id % tx_pq_vf_mask_width));
+ mem_addr_4kb += vport_pq_mem_4kb;
+ } else {
+ mem_addr_4kb += pq_mem_4kb;
+ }
+ }
+
+ /* store Tx PQ VF mask to size select register */
+ for (i = 0; i < num_tx_pq_vf_masks; i++) {
+ if (tx_pq_vf_mask[i]) {
+ if (is_bb_a0) {
+ u32 curr_mask = 0, addr;
+
+ addr = QM_REG_MAXPQSIZETXSEL_0 + (i * 4);
+ if (!p_params->is_first_pf)
+ curr_mask = qed_rd(p_hwfn, p_ptt,
+ addr);
+
+ addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i;
+
+ STORE_RT_REG(p_hwfn, addr,
+ curr_mask | tx_pq_vf_mask[i]);
+ } else {
+ u32 addr;
+
+ addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i;
+ STORE_RT_REG(p_hwfn, addr,
+ tx_pq_vf_mask[i]);
+ }
+ }
+ }
+}
+
+/* Prepare Other PQ mapping runtime init values for the specified PF */
+static void qed_other_pq_map_rt_init(struct qed_hwfn *p_hwfn,
+ u8 port_id,
+ u8 pf_id,
+ u32 num_pf_cids,
+ u32 num_tids,
+ u32 base_mem_addr_4kb)
+{
+ u16 i, pq_id;
+
+ /* a single other PQ group is used in each PF,
+ * where PQ group i is used in PF i.
+ */
+ u16 pq_group = pf_id;
+ u32 pq_size = num_pf_cids + num_tids;
+ u32 pq_mem_4kb = QM_PQ_MEM_4KB(pq_size);
+ u32 mem_addr_4kb = base_mem_addr_4kb;
+
+ /* map PQ group to PF */
+ STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group,
+ (u32)(pf_id));
+ /* set PQ sizes */
+ STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET,
+ QM_PQ_SIZE_256B(pq_size));
+ /* set base address */
+ for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE;
+ i < QM_OTHER_PQS_PER_PF; i++, pq_id++) {
+ STORE_RT_REG(p_hwfn,
+ QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id,
+ mem_addr_4kb);
+ mem_addr_4kb += pq_mem_4kb;
+ }
+}
+
+/* Prepare PF WFQ runtime init values for the specified PF.
+ * Return -1 on error.
+ */
+static int qed_pf_wfq_rt_init(struct qed_hwfn *p_hwfn,
+ struct qed_qm_pf_rt_init_params *p_params)
+{
+ u16 num_tx_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
+ u32 crd_reg_offset;
+ u32 inc_val;
+ u16 i;
+
+ if (p_params->pf_id < MAX_NUM_PFS_BB)
+ crd_reg_offset = QM_REG_WFQPFCRD_RT_OFFSET;
+ else
+ crd_reg_offset = QM_REG_WFQPFCRD_MSB_RT_OFFSET +
+ (p_params->pf_id % MAX_NUM_PFS_BB);
+
+ inc_val = QM_WFQ_INC_VAL(p_params->pf_wfq);
+ if (inc_val > QM_WFQ_MAX_INC_VAL) {
+ DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration");
+ return -1;
+ }
+ STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + p_params->pf_id,
+ inc_val);
+ STORE_RT_REG(p_hwfn,
+ QM_REG_WFQPFUPPERBOUND_RT_OFFSET + p_params->pf_id,
+ QM_WFQ_UPPER_BOUND | QM_WFQ_CRD_REG_SIGN_BIT);
+
+ for (i = 0; i < num_tx_pqs; i++) {
+ u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id,
+ p_params->max_phys_tcs_per_port);
+
+ OVERWRITE_RT_REG(p_hwfn,
+ crd_reg_offset + voq * MAX_NUM_PFS_BB,
+ QM_WFQ_INIT_CRD(inc_val) |
+ QM_WFQ_CRD_REG_SIGN_BIT);
+ }
+
+ return 0;
+}
+
+/* Prepare PF RL runtime init values for the specified PF.
+ * Return -1 on error.
+ */
+static int qed_pf_rl_rt_init(struct qed_hwfn *p_hwfn,
+ u8 pf_id,
+ u32 pf_rl)
+{
+ u32 inc_val = QM_RL_INC_VAL(pf_rl);
+
+ if (inc_val > QM_RL_MAX_INC_VAL) {
+ DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration");
+ return -1;
+ }
+ STORE_RT_REG(p_hwfn, QM_REG_RLPFCRD_RT_OFFSET + pf_id,
+ QM_RL_CRD_REG_SIGN_BIT);
+ STORE_RT_REG(p_hwfn, QM_REG_RLPFUPPERBOUND_RT_OFFSET + pf_id,
+ QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT);
+ STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val);
+ return 0;
+}
+
+/* Prepare VPORT WFQ runtime init values for the specified VPORTs.
+ * Return -1 on error.
+ */
+static int qed_vp_wfq_rt_init(struct qed_hwfn *p_hwfn,
+ u8 start_vport,
+ u8 num_vports,
+ struct init_qm_vport_params *vport_params)
+{
+ u8 tc, i, vport_id;
+ u32 inc_val;
+
+ /* go over all PF VPORTs */
+ for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) {
+ u32 temp = QM_REG_WFQVPUPPERBOUND_RT_OFFSET;
+ u16 *pq_ids = &vport_params[i].first_tx_pq_id[0];
+
+ if (!vport_params[i].vport_wfq)
+ continue;
+
+ inc_val = QM_WFQ_INC_VAL(vport_params[i].vport_wfq);
+ if (inc_val > QM_WFQ_MAX_INC_VAL) {
+ DP_NOTICE(p_hwfn,
+ "Invalid VPORT WFQ weight configuration");
+ return -1;
+ }
+
+ /* each VPORT can have several VPORT PQ IDs for
+ * different TCs
+ */
+ for (tc = 0; tc < NUM_OF_TCS; tc++) {
+ u16 vport_pq_id = pq_ids[tc];
+
+ if (vport_pq_id != QM_INVALID_PQ_ID) {
+ STORE_RT_REG(p_hwfn,
+ QM_REG_WFQVPWEIGHT_RT_OFFSET +
+ vport_pq_id, inc_val);
+ STORE_RT_REG(p_hwfn, temp + vport_pq_id,
+ QM_WFQ_UPPER_BOUND |
+ QM_WFQ_CRD_REG_SIGN_BIT);
+ STORE_RT_REG(p_hwfn,
+ QM_REG_WFQVPCRD_RT_OFFSET +
+ vport_pq_id,
+ QM_WFQ_INIT_CRD(inc_val) |
+ QM_WFQ_CRD_REG_SIGN_BIT);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int qed_vport_rl_rt_init(struct qed_hwfn *p_hwfn,
+ u8 start_vport,
+ u8 num_vports,
+ struct init_qm_vport_params *vport_params)
+{
+ u8 i, vport_id;
+
+ /* go over all PF VPORTs */
+ for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) {
+ u32 inc_val = QM_RL_INC_VAL(vport_params[i].vport_rl);
+
+ if (inc_val > QM_RL_MAX_INC_VAL) {
+ DP_NOTICE(p_hwfn,
+ "Invalid VPORT rate-limit configuration");
+ return -1;
+ }
+
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLGLBLCRD_RT_OFFSET + vport_id,
+ QM_RL_CRD_REG_SIGN_BIT);
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id,
+ QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT);
+ STORE_RT_REG(p_hwfn,
+ QM_REG_RLGLBLINCVAL_RT_OFFSET + vport_id,
+ inc_val);
+ }
+
+ return 0;
+}
+
+static bool qed_poll_on_qm_cmd_ready(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 reg_val, i;
+
+ for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && reg_val == 0;
+ i++) {
+ udelay(QM_STOP_CMD_POLL_PERIOD_US);
+ reg_val = qed_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY);
+ }
+
+ /* check if timeout while waiting for SDM command ready */
+ if (i == QM_STOP_CMD_MAX_POLL_COUNT) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
+ "Timeout when waiting for QM SDM command ready signal\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool qed_send_qm_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 cmd_addr,
+ u32 cmd_data_lsb,
+ u32 cmd_data_msb)
+{
+ if (!qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt))
+ return false;
+
+ qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDADDR, cmd_addr);
+ qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATALSB, cmd_data_lsb);
+ qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATAMSB, cmd_data_msb);
+ qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 1);
+ qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 0);
+
+ return qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt);
+}
+
+/******************** INTERFACE IMPLEMENTATION *********************/
+u32 qed_qm_pf_mem_size(u8 pf_id,
+ u32 num_pf_cids,
+ u32 num_vf_cids,
+ u32 num_tids,
+ u16 num_pf_pqs,
+ u16 num_vf_pqs)
+{
+ return QM_PQ_MEM_4KB(num_pf_cids) * num_pf_pqs +
+ QM_PQ_MEM_4KB(num_vf_cids) * num_vf_pqs +
+ QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF;
+}
+
+int qed_qm_common_rt_init(
+ struct qed_hwfn *p_hwfn,
+ struct qed_qm_common_rt_init_params *p_params)
+{
+ /* init AFullOprtnstcCrdMask */
+ u32 mask = (QM_OPPOR_LINE_VOQ_DEF <<
+ QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT) |
+ (QM_BYTE_CRD_EN << QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT) |
+ (p_params->pf_wfq_en <<
+ QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT) |
+ (p_params->vport_wfq_en <<
+ QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT) |
+ (p_params->pf_rl_en <<
+ QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT) |
+ (p_params->vport_rl_en <<
+ QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT) |
+ (QM_OPPOR_FW_STOP_DEF <<
+ QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT) |
+ (QM_OPPOR_PQ_EMPTY_DEF <<
+ QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT);
+
+ STORE_RT_REG(p_hwfn, QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET, mask);
+ qed_enable_pf_rl(p_hwfn, p_params->pf_rl_en);
+ qed_enable_pf_wfq(p_hwfn, p_params->pf_wfq_en);
+ qed_enable_vport_rl(p_hwfn, p_params->vport_rl_en);
+ qed_enable_vport_wfq(p_hwfn, p_params->vport_wfq_en);
+ qed_cmdq_lines_rt_init(p_hwfn,
+ p_params->max_ports_per_engine,
+ p_params->max_phys_tcs_per_port,
+ p_params->port_params);
+ qed_btb_blocks_rt_init(p_hwfn,
+ p_params->max_ports_per_engine,
+ p_params->max_phys_tcs_per_port,
+ p_params->port_params);
+ return 0;
+}
+
+int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_qm_pf_rt_init_params *p_params)
+{
+ struct init_qm_vport_params *vport_params = p_params->vport_params;
+ u32 other_mem_size_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids +
+ p_params->num_tids) *
+ QM_OTHER_PQS_PER_PF;
+ u8 tc, i;
+
+ /* clear first Tx PQ ID array for each VPORT */
+ for (i = 0; i < p_params->num_vports; i++)
+ for (tc = 0; tc < NUM_OF_TCS; tc++)
+ vport_params[i].first_tx_pq_id[tc] = QM_INVALID_PQ_ID;
+
+ /* map Other PQs (if any) */
+ qed_other_pq_map_rt_init(p_hwfn, p_params->port_id, p_params->pf_id,
+ p_params->num_pf_cids, p_params->num_tids, 0);
+
+ /* map Tx PQs */
+ qed_tx_pq_map_rt_init(p_hwfn, p_ptt, p_params, other_mem_size_4kb);
+
+ if (p_params->pf_wfq)
+ if (qed_pf_wfq_rt_init(p_hwfn, p_params))
+ return -1;
+
+ if (qed_pf_rl_rt_init(p_hwfn, p_params->pf_id, p_params->pf_rl))
+ return -1;
+
+ if (qed_vp_wfq_rt_init(p_hwfn, p_params->start_vport,
+ p_params->num_vports, vport_params))
+ return -1;
+
+ if (qed_vport_rl_rt_init(p_hwfn, p_params->start_vport,
+ p_params->num_vports, vport_params))
+ return -1;
+
+ return 0;
+}
+
+int qed_init_pf_rl(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 pf_id,
+ u32 pf_rl)
+{
+ u32 inc_val = QM_RL_INC_VAL(pf_rl);
+
+ if (inc_val > QM_RL_MAX_INC_VAL) {
+ DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration");
+ return -1;
+ }
+
+ qed_wr(p_hwfn, p_ptt,
+ QM_REG_RLPFCRD + pf_id * 4,
+ QM_RL_CRD_REG_SIGN_BIT);
+ qed_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val);
+
+ return 0;
+}
+
+int qed_init_vport_rl(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u8 vport_id,
+ u32 vport_rl)
+{
+ u32 inc_val = QM_RL_INC_VAL(vport_rl);
+
+ if (inc_val > QM_RL_MAX_INC_VAL) {
+ DP_NOTICE(p_hwfn, "Invalid VPORT rate-limit configuration");
+ return -1;
+ }
+
+ qed_wr(p_hwfn, p_ptt,
+ QM_REG_RLGLBLCRD + vport_id * 4,
+ QM_RL_CRD_REG_SIGN_BIT);
+ qed_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val);
+
+ return 0;
+}
+
+bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool is_release_cmd,
+ bool is_tx_pq,
+ u16 start_pq,
+ u16 num_pqs)
+{
+ u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = { 0 };
+ u32 pq_mask = 0, last_pq = start_pq + num_pqs - 1, pq_id;
+
+ /* set command's PQ type */
+ QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1);
+
+ for (pq_id = start_pq; pq_id <= last_pq; pq_id++) {
+ /* set PQ bit in mask (stop command only) */
+ if (!is_release_cmd)
+ pq_mask |= (1 << (pq_id % QM_STOP_PQ_MASK_WIDTH));
+
+ /* if last PQ or end of PQ mask, write command */
+ if ((pq_id == last_pq) ||
+ (pq_id % QM_STOP_PQ_MASK_WIDTH ==
+ (QM_STOP_PQ_MASK_WIDTH - 1))) {
+ QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD,
+ PAUSE_MASK, pq_mask);
+ QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD,
+ GROUP_ID,
+ pq_id / QM_STOP_PQ_MASK_WIDTH);
+ if (!qed_send_qm_cmd(p_hwfn, p_ptt, QM_STOP_CMD_ADDR,
+ cmd_arr[0], cmd_arr[1]))
+ return false;
+ pq_mask = 0;
+ }
+ }
+
+ return true;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c
new file mode 100644
index 000000000000..796f1390e598
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c
@@ -0,0 +1,531 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "qed.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_init_ops.h"
+#include "qed_reg_addr.h"
+
+#define QED_INIT_MAX_POLL_COUNT 100
+#define QED_INIT_POLL_PERIOD_US 500
+
+static u32 pxp_global_win[] = {
+ 0,
+ 0,
+ 0x1c02, /* win 2: addr=0x1c02000, size=4096 bytes */
+ 0x1c80, /* win 3: addr=0x1c80000, size=4096 bytes */
+ 0x1d00, /* win 4: addr=0x1d00000, size=4096 bytes */
+ 0x1d01, /* win 5: addr=0x1d01000, size=4096 bytes */
+ 0x1d80, /* win 6: addr=0x1d80000, size=4096 bytes */
+ 0x1d81, /* win 7: addr=0x1d81000, size=4096 bytes */
+ 0x1d82, /* win 8: addr=0x1d82000, size=4096 bytes */
+ 0x1e00, /* win 9: addr=0x1e00000, size=4096 bytes */
+ 0x1e80, /* win 10: addr=0x1e80000, size=4096 bytes */
+ 0x1f00, /* win 11: addr=0x1f00000, size=4096 bytes */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+void qed_init_iro_array(struct qed_dev *cdev)
+{
+ cdev->iro_arr = iro_arr;
+}
+
+/* Runtime configuration helpers */
+void qed_init_clear_rt_data(struct qed_hwfn *p_hwfn)
+{
+ int i;
+
+ for (i = 0; i < RUNTIME_ARRAY_SIZE; i++)
+ p_hwfn->rt_data[i].b_valid = false;
+}
+
+void qed_init_store_rt_reg(struct qed_hwfn *p_hwfn,
+ u32 rt_offset,
+ u32 val)
+{
+ p_hwfn->rt_data[rt_offset].init_val = val;
+ p_hwfn->rt_data[rt_offset].b_valid = true;
+}
+
+void qed_init_store_rt_agg(struct qed_hwfn *p_hwfn,
+ u32 rt_offset,
+ u32 *val,
+ size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size / sizeof(u32); i++) {
+ p_hwfn->rt_data[rt_offset + i].init_val = val[i];
+ p_hwfn->rt_data[rt_offset + i].b_valid = true;
+ }
+}
+
+static void qed_init_rt(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 addr,
+ u32 rt_offset,
+ u32 size)
+{
+ struct qed_rt_data *rt_data = p_hwfn->rt_data + rt_offset;
+ u32 i;
+
+ for (i = 0; i < size; i++) {
+ if (!rt_data[i].b_valid)
+ continue;
+ qed_wr(p_hwfn, p_ptt, addr + (i << 2), rt_data[i].init_val);
+ }
+}
+
+int qed_init_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_rt_data *rt_data;
+
+ rt_data = kzalloc(sizeof(*rt_data) * RUNTIME_ARRAY_SIZE, GFP_ATOMIC);
+ if (!rt_data)
+ return -ENOMEM;
+
+ p_hwfn->rt_data = rt_data;
+
+ return 0;
+}
+
+void qed_init_free(struct qed_hwfn *p_hwfn)
+{
+ kfree(p_hwfn->rt_data);
+ p_hwfn->rt_data = NULL;
+}
+
+static int qed_init_array_dmae(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 addr,
+ u32 dmae_data_offset,
+ u32 size,
+ const u32 *buf,
+ bool b_must_dmae,
+ bool b_can_dmae)
+{
+ int rc = 0;
+
+ /* Perform DMAE only for lengthy enough sections or for wide-bus */
+ if (!b_can_dmae || (!b_must_dmae && (size < 16))) {
+ const u32 *data = buf + dmae_data_offset;
+ u32 i;
+
+ for (i = 0; i < size; i++)
+ qed_wr(p_hwfn, p_ptt, addr + (i << 2), data[i]);
+ } else {
+ rc = qed_dmae_host2grc(p_hwfn, p_ptt,
+ (uintptr_t)(buf + dmae_data_offset),
+ addr, size, 0);
+ }
+
+ return rc;
+}
+
+static int qed_init_fill_dmae(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 addr,
+ u32 fill,
+ u32 fill_count)
+{
+ static u32 zero_buffer[DMAE_MAX_RW_SIZE];
+
+ memset(zero_buffer, 0, sizeof(u32) * DMAE_MAX_RW_SIZE);
+
+ /* invoke the DMAE virtual/physical buffer API with
+ * 1. DMAE init channel
+ * 2. addr,
+ * 3. p_hwfb->temp_data,
+ * 4. fill_count
+ */
+
+ return qed_dmae_host2grc(p_hwfn, p_ptt,
+ (uintptr_t)(&zero_buffer[0]),
+ addr, fill_count,
+ QED_DMAE_FLAG_RW_REPL_SRC);
+}
+
+static void qed_init_fill(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 addr,
+ u32 fill,
+ u32 fill_count)
+{
+ u32 i;
+
+ for (i = 0; i < fill_count; i++, addr += sizeof(u32))
+ qed_wr(p_hwfn, p_ptt, addr, fill);
+}
+
+static int qed_init_cmd_array(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct init_write_op *cmd,
+ bool b_must_dmae,
+ bool b_can_dmae)
+{
+ u32 data = le32_to_cpu(cmd->data);
+ u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2;
+ u32 dmae_array_offset = le32_to_cpu(cmd->args.array_offset);
+ u32 offset, output_len, input_len, max_size;
+ struct qed_dev *cdev = p_hwfn->cdev;
+ union init_array_hdr *hdr;
+ const u32 *array_data;
+ int rc = 0;
+ u32 size;
+
+ array_data = cdev->fw_data->arr_data;
+
+ hdr = (union init_array_hdr *)(array_data +
+ dmae_array_offset);
+ data = le32_to_cpu(hdr->raw.data);
+ switch (GET_FIELD(data, INIT_ARRAY_RAW_HDR_TYPE)) {
+ case INIT_ARR_ZIPPED:
+ offset = dmae_array_offset + 1;
+ input_len = GET_FIELD(data,
+ INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE);
+ max_size = MAX_ZIPPED_SIZE * 4;
+ memset(p_hwfn->unzip_buf, 0, max_size);
+
+ output_len = qed_unzip_data(p_hwfn, input_len,
+ (u8 *)&array_data[offset],
+ max_size, (u8 *)p_hwfn->unzip_buf);
+ if (output_len) {
+ rc = qed_init_array_dmae(p_hwfn, p_ptt, addr, 0,
+ output_len,
+ p_hwfn->unzip_buf,
+ b_must_dmae, b_can_dmae);
+ } else {
+ DP_NOTICE(p_hwfn, "Failed to unzip dmae data\n");
+ rc = -EINVAL;
+ }
+ break;
+ case INIT_ARR_PATTERN:
+ {
+ u32 repeats = GET_FIELD(data,
+ INIT_ARRAY_PATTERN_HDR_REPETITIONS);
+ u32 i;
+
+ size = GET_FIELD(data, INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE);
+
+ for (i = 0; i < repeats; i++, addr += size << 2) {
+ rc = qed_init_array_dmae(p_hwfn, p_ptt, addr,
+ dmae_array_offset + 1,
+ size, array_data,
+ b_must_dmae, b_can_dmae);
+ if (rc)
+ break;
+ }
+ break;
+ }
+ case INIT_ARR_STANDARD:
+ size = GET_FIELD(data, INIT_ARRAY_STANDARD_HDR_SIZE);
+ rc = qed_init_array_dmae(p_hwfn, p_ptt, addr,
+ dmae_array_offset + 1,
+ size, array_data,
+ b_must_dmae, b_can_dmae);
+ break;
+ }
+
+ return rc;
+}
+
+/* init_ops write command */
+static int qed_init_cmd_wr(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct init_write_op *cmd,
+ bool b_can_dmae)
+{
+ u32 data = le32_to_cpu(cmd->data);
+ u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2;
+ bool b_must_dmae = GET_FIELD(data, INIT_WRITE_OP_WIDE_BUS);
+ union init_write_args *arg = &cmd->args;
+ int rc = 0;
+
+ /* Sanitize */
+ if (b_must_dmae && !b_can_dmae) {
+ DP_NOTICE(p_hwfn,
+ "Need to write to %08x for Wide-bus but DMAE isn't allowed\n",
+ addr);
+ return -EINVAL;
+ }
+
+ switch (GET_FIELD(data, INIT_WRITE_OP_SOURCE)) {
+ case INIT_SRC_INLINE:
+ qed_wr(p_hwfn, p_ptt, addr,
+ le32_to_cpu(arg->inline_val));
+ break;
+ case INIT_SRC_ZEROS:
+ if (b_must_dmae ||
+ (b_can_dmae && (le32_to_cpu(arg->zeros_count) >= 64)))
+ rc = qed_init_fill_dmae(p_hwfn, p_ptt, addr, 0,
+ le32_to_cpu(arg->zeros_count));
+ else
+ qed_init_fill(p_hwfn, p_ptt, addr, 0,
+ le32_to_cpu(arg->zeros_count));
+ break;
+ case INIT_SRC_ARRAY:
+ rc = qed_init_cmd_array(p_hwfn, p_ptt, cmd,
+ b_must_dmae, b_can_dmae);
+ break;
+ case INIT_SRC_RUNTIME:
+ qed_init_rt(p_hwfn, p_ptt, addr,
+ le16_to_cpu(arg->runtime.offset),
+ le16_to_cpu(arg->runtime.size));
+ break;
+ }
+
+ return rc;
+}
+
+static inline bool comp_eq(u32 val, u32 expected_val)
+{
+ return val == expected_val;
+}
+
+static inline bool comp_and(u32 val, u32 expected_val)
+{
+ return (val & expected_val) == expected_val;
+}
+
+static inline bool comp_or(u32 val, u32 expected_val)
+{
+ return (val | expected_val) > 0;
+}
+
+/* init_ops read/poll commands */
+static void qed_init_cmd_rd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct init_read_op *cmd)
+{
+ u32 data = le32_to_cpu(cmd->op_data);
+ u32 addr = GET_FIELD(data, INIT_READ_OP_ADDRESS) << 2;
+
+ bool (*comp_check)(u32 val,
+ u32 expected_val);
+ u32 delay = QED_INIT_POLL_PERIOD_US, val;
+
+ val = qed_rd(p_hwfn, p_ptt, addr);
+
+ data = le32_to_cpu(cmd->op_data);
+ if (GET_FIELD(data, INIT_READ_OP_POLL)) {
+ int i;
+
+ switch (GET_FIELD(data, INIT_READ_OP_POLL_COMP)) {
+ case INIT_COMPARISON_EQ:
+ comp_check = comp_eq;
+ break;
+ case INIT_COMPARISON_OR:
+ comp_check = comp_or;
+ break;
+ case INIT_COMPARISON_AND:
+ comp_check = comp_and;
+ break;
+ default:
+ comp_check = NULL;
+ DP_ERR(p_hwfn, "Invalid poll comparison type %08x\n",
+ data);
+ return;
+ }
+
+ for (i = 0;
+ i < QED_INIT_MAX_POLL_COUNT &&
+ !comp_check(val, le32_to_cpu(cmd->expected_val));
+ i++) {
+ udelay(delay);
+ val = qed_rd(p_hwfn, p_ptt, addr);
+ }
+
+ if (i == QED_INIT_MAX_POLL_COUNT)
+ DP_ERR(p_hwfn,
+ "Timeout when polling reg: 0x%08x [ Waiting-for: %08x Got: %08x (comparsion %08x)]\n",
+ addr, le32_to_cpu(cmd->expected_val),
+ val, data);
+ }
+}
+
+/* init_ops callbacks entry point */
+static void qed_init_cmd_cb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct init_callback_op *p_cmd)
+{
+ DP_NOTICE(p_hwfn, "Currently init values have no need of callbacks\n");
+}
+
+static u8 qed_init_cmd_mode_match(struct qed_hwfn *p_hwfn,
+ u16 *offset,
+ int modes)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+ const u8 *modes_tree_buf;
+ u8 arg1, arg2, tree_val;
+
+ modes_tree_buf = cdev->fw_data->modes_tree_buf;
+ tree_val = modes_tree_buf[(*offset)++];
+ switch (tree_val) {
+ case INIT_MODE_OP_NOT:
+ return qed_init_cmd_mode_match(p_hwfn, offset, modes) ^ 1;
+ case INIT_MODE_OP_OR:
+ arg1 = qed_init_cmd_mode_match(p_hwfn, offset, modes);
+ arg2 = qed_init_cmd_mode_match(p_hwfn, offset, modes);
+ return arg1 | arg2;
+ case INIT_MODE_OP_AND:
+ arg1 = qed_init_cmd_mode_match(p_hwfn, offset, modes);
+ arg2 = qed_init_cmd_mode_match(p_hwfn, offset, modes);
+ return arg1 & arg2;
+ default:
+ tree_val -= MAX_INIT_MODE_OPS;
+ return (modes & (1 << tree_val)) ? 1 : 0;
+ }
+}
+
+static u32 qed_init_cmd_mode(struct qed_hwfn *p_hwfn,
+ struct init_if_mode_op *p_cmd,
+ int modes)
+{
+ u16 offset = le16_to_cpu(p_cmd->modes_buf_offset);
+
+ if (qed_init_cmd_mode_match(p_hwfn, &offset, modes))
+ return 0;
+ else
+ return GET_FIELD(le32_to_cpu(p_cmd->op_data),
+ INIT_IF_MODE_OP_CMD_OFFSET);
+}
+
+static u32 qed_init_cmd_phase(struct qed_hwfn *p_hwfn,
+ struct init_if_phase_op *p_cmd,
+ u32 phase,
+ u32 phase_id)
+{
+ u32 data = le32_to_cpu(p_cmd->phase_data);
+ u32 op_data = le32_to_cpu(p_cmd->op_data);
+
+ if (!(GET_FIELD(data, INIT_IF_PHASE_OP_PHASE) == phase &&
+ (GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == ANY_PHASE_ID ||
+ GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == phase_id)))
+ return GET_FIELD(op_data, INIT_IF_PHASE_OP_CMD_OFFSET);
+ else
+ return 0;
+}
+
+int qed_init_run(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ int phase,
+ int phase_id,
+ int modes)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+ u32 cmd_num, num_init_ops;
+ union init_op *init_ops;
+ bool b_dmae = false;
+ int rc = 0;
+
+ num_init_ops = cdev->fw_data->init_ops_size;
+ init_ops = cdev->fw_data->init_ops;
+
+ p_hwfn->unzip_buf = kzalloc(MAX_ZIPPED_SIZE * 4, GFP_ATOMIC);
+ if (!p_hwfn->unzip_buf) {
+ DP_NOTICE(p_hwfn, "Failed to allocate unzip buffer\n");
+ return -ENOMEM;
+ }
+
+ for (cmd_num = 0; cmd_num < num_init_ops; cmd_num++) {
+ union init_op *cmd = &init_ops[cmd_num];
+ u32 data = le32_to_cpu(cmd->raw.op_data);
+
+ switch (GET_FIELD(data, INIT_CALLBACK_OP_OP)) {
+ case INIT_OP_WRITE:
+ rc = qed_init_cmd_wr(p_hwfn, p_ptt, &cmd->write,
+ b_dmae);
+ break;
+ case INIT_OP_READ:
+ qed_init_cmd_rd(p_hwfn, p_ptt, &cmd->read);
+ break;
+ case INIT_OP_IF_MODE:
+ cmd_num += qed_init_cmd_mode(p_hwfn, &cmd->if_mode,
+ modes);
+ break;
+ case INIT_OP_IF_PHASE:
+ cmd_num += qed_init_cmd_phase(p_hwfn, &cmd->if_phase,
+ phase, phase_id);
+ b_dmae = GET_FIELD(data, INIT_IF_PHASE_OP_DMAE_ENABLE);
+ break;
+ case INIT_OP_DELAY:
+ /* qed_init_run is always invoked from
+ * sleep-able context
+ */
+ udelay(le32_to_cpu(cmd->delay.delay));
+ break;
+
+ case INIT_OP_CALLBACK:
+ qed_init_cmd_cb(p_hwfn, p_ptt, &cmd->callback);
+ break;
+ }
+
+ if (rc)
+ break;
+ }
+
+ kfree(p_hwfn->unzip_buf);
+ return rc;
+}
+
+void qed_gtt_init(struct qed_hwfn *p_hwfn)
+{
+ u32 gtt_base;
+ u32 i;
+
+ /* Set the global windows */
+ gtt_base = PXP_PF_WINDOW_ADMIN_START + PXP_PF_WINDOW_ADMIN_GLOBAL_START;
+
+ for (i = 0; i < ARRAY_SIZE(pxp_global_win); i++)
+ if (pxp_global_win[i])
+ REG_WR(p_hwfn, gtt_base + i * PXP_GLOBAL_ENTRY_SIZE,
+ pxp_global_win[i]);
+}
+
+int qed_init_fw_data(struct qed_dev *cdev,
+ const u8 *data)
+{
+ struct qed_fw_data *fw = cdev->fw_data;
+ struct bin_buffer_hdr *buf_hdr;
+ u32 offset, len;
+
+ if (!data) {
+ DP_NOTICE(cdev, "Invalid fw data\n");
+ return -EINVAL;
+ }
+
+ buf_hdr = (struct bin_buffer_hdr *)data;
+
+ offset = buf_hdr[BIN_BUF_INIT_CMD].offset;
+ fw->init_ops = (union init_op *)(data + offset);
+
+ offset = buf_hdr[BIN_BUF_INIT_VAL].offset;
+ fw->arr_data = (u32 *)(data + offset);
+
+ offset = buf_hdr[BIN_BUF_INIT_MODE_TREE].offset;
+ fw->modes_tree_buf = (u8 *)(data + offset);
+ len = buf_hdr[BIN_BUF_INIT_CMD].length;
+ fw->init_ops_size = len / sizeof(struct init_raw_op);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.h b/drivers/net/ethernet/qlogic/qed/qed_init_ops.h
new file mode 100644
index 000000000000..1e832049983d
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.h
@@ -0,0 +1,110 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_INIT_OPS_H
+#define _QED_INIT_OPS_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include "qed.h"
+
+/**
+ * @brief qed_init_iro_array - init iro_arr.
+ *
+ *
+ * @param cdev
+ */
+void qed_init_iro_array(struct qed_dev *cdev);
+
+/**
+ * @brief qed_init_run - Run the init-sequence.
+ *
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param phase
+ * @param phase_id
+ * @param modes
+ * @return _qed_status_t
+ */
+int qed_init_run(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ int phase,
+ int phase_id,
+ int modes);
+
+/**
+ * @brief qed_init_hwfn_allocate - Allocate RT array, Store 'values' ptrs.
+ *
+ *
+ * @param p_hwfn
+ *
+ * @return _qed_status_t
+ */
+int qed_init_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_init_hwfn_deallocate
+ *
+ *
+ * @param p_hwfn
+ */
+void qed_init_free(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_init_clear_rt_data - Clears the runtime init array.
+ *
+ *
+ * @param p_hwfn
+ */
+void qed_init_clear_rt_data(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_init_store_rt_reg - Store a configuration value in the RT array.
+ *
+ *
+ * @param p_hwfn
+ * @param rt_offset
+ * @param val
+ */
+void qed_init_store_rt_reg(struct qed_hwfn *p_hwfn,
+ u32 rt_offset,
+ u32 val);
+
+#define STORE_RT_REG(hwfn, offset, val) \
+ qed_init_store_rt_reg(hwfn, offset, val)
+
+#define OVERWRITE_RT_REG(hwfn, offset, val) \
+ qed_init_store_rt_reg(hwfn, offset, val)
+
+/**
+ * @brief
+ *
+ *
+ * @param p_hwfn
+ * @param rt_offset
+ * @param val
+ * @param size
+ */
+void qed_init_store_rt_agg(struct qed_hwfn *p_hwfn,
+ u32 rt_offset,
+ u32 *val,
+ size_t size);
+
+#define STORE_RT_REG_AGG(hwfn, offset, val) \
+ qed_init_store_rt_agg(hwfn, offset, (u32 *)&val, sizeof(val))
+
+/**
+ * @brief
+ * Initialize GTT global windows and set admin window
+ * related params of GTT/PTT to default values.
+ *
+ * @param p_hwfn
+ */
+void qed_gtt_init(struct qed_hwfn *p_hwfn);
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c
new file mode 100644
index 000000000000..de50e84902af
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -0,0 +1,1129 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "qed.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_init_ops.h"
+#include "qed_int.h"
+#include "qed_mcp.h"
+#include "qed_reg_addr.h"
+#include "qed_sp.h"
+
+struct qed_pi_info {
+ qed_int_comp_cb_t comp_cb;
+ void *cookie;
+};
+
+struct qed_sb_sp_info {
+ struct qed_sb_info sb_info;
+
+ /* per protocol index data */
+ struct qed_pi_info pi_info_arr[PIS_PER_SB];
+};
+
+#define SB_ATTN_ALIGNED_SIZE(p_hwfn) \
+ ALIGNED_TYPE_SIZE(struct atten_status_block, p_hwfn)
+
+#define ATTN_STATE_BITS (0xfff)
+#define ATTN_BITS_MASKABLE (0x3ff)
+struct qed_sb_attn_info {
+ /* Virtual & Physical address of the SB */
+ struct atten_status_block *sb_attn;
+ dma_addr_t sb_phys;
+
+ /* Last seen running index */
+ u16 index;
+
+ /* Previously asserted attentions, which are still unasserted */
+ u16 known_attn;
+
+ /* Cleanup address for the link's general hw attention */
+ u32 mfw_attn_addr;
+};
+
+static inline u16 qed_attn_update_idx(struct qed_hwfn *p_hwfn,
+ struct qed_sb_attn_info *p_sb_desc)
+{
+ u16 rc = 0;
+ u16 index;
+
+ /* Make certain HW write took affect */
+ mmiowb();
+
+ index = le16_to_cpu(p_sb_desc->sb_attn->sb_index);
+ if (p_sb_desc->index != index) {
+ p_sb_desc->index = index;
+ rc = QED_SB_ATT_IDX;
+ }
+
+ /* Make certain we got a consistent view with HW */
+ mmiowb();
+
+ return rc;
+}
+
+/**
+ * @brief qed_int_assertion - handles asserted attention bits
+ *
+ * @param p_hwfn
+ * @param asserted_bits newly asserted bits
+ * @return int
+ */
+static int qed_int_assertion(struct qed_hwfn *p_hwfn,
+ u16 asserted_bits)
+{
+ struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn;
+ u32 igu_mask;
+
+ /* Mask the source of the attention in the IGU */
+ igu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ IGU_REG_ATTENTION_ENABLE);
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "IGU mask: 0x%08x --> 0x%08x\n",
+ igu_mask, igu_mask & ~(asserted_bits & ATTN_BITS_MASKABLE));
+ igu_mask &= ~(asserted_bits & ATTN_BITS_MASKABLE);
+ qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, igu_mask);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+ "inner known ATTN state: 0x%04x --> 0x%04x\n",
+ sb_attn_sw->known_attn,
+ sb_attn_sw->known_attn | asserted_bits);
+ sb_attn_sw->known_attn |= asserted_bits;
+
+ /* Handle MCP events */
+ if (asserted_bits & 0x100) {
+ qed_mcp_handle_events(p_hwfn, p_hwfn->p_dpc_ptt);
+ /* Clean the MCP attention */
+ qed_wr(p_hwfn, p_hwfn->p_dpc_ptt,
+ sb_attn_sw->mfw_attn_addr, 0);
+ }
+
+ DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview +
+ GTT_BAR0_MAP_REG_IGU_CMD +
+ ((IGU_CMD_ATTN_BIT_SET_UPPER -
+ IGU_CMD_INT_ACK_BASE) << 3),
+ (u32)asserted_bits);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "set cmd IGU: 0x%04x\n",
+ asserted_bits);
+
+ return 0;
+}
+
+/**
+ * @brief - handles deassertion of previously asserted attentions.
+ *
+ * @param p_hwfn
+ * @param deasserted_bits - newly deasserted bits
+ * @return int
+ *
+ */
+static int qed_int_deassertion(struct qed_hwfn *p_hwfn,
+ u16 deasserted_bits)
+{
+ struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn;
+ u32 aeu_mask;
+
+ if (deasserted_bits != 0x100)
+ DP_ERR(p_hwfn, "Unexpected - non-link deassertion\n");
+
+ /* Clear IGU indication for the deasserted bits */
+ DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview +
+ GTT_BAR0_MAP_REG_IGU_CMD +
+ ((IGU_CMD_ATTN_BIT_CLR_UPPER -
+ IGU_CMD_INT_ACK_BASE) << 3),
+ ~((u32)deasserted_bits));
+
+ /* Unmask deasserted attentions in IGU */
+ aeu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ IGU_REG_ATTENTION_ENABLE);
+ aeu_mask |= (deasserted_bits & ATTN_BITS_MASKABLE);
+ qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, aeu_mask);
+
+ /* Clear deassertion from inner state */
+ sb_attn_sw->known_attn &= ~deasserted_bits;
+
+ return 0;
+}
+
+static int qed_int_attentions(struct qed_hwfn *p_hwfn)
+{
+ struct qed_sb_attn_info *p_sb_attn_sw = p_hwfn->p_sb_attn;
+ struct atten_status_block *p_sb_attn = p_sb_attn_sw->sb_attn;
+ u32 attn_bits = 0, attn_acks = 0;
+ u16 asserted_bits, deasserted_bits;
+ __le16 index;
+ int rc = 0;
+
+ /* Read current attention bits/acks - safeguard against attentions
+ * by guaranting work on a synchronized timeframe
+ */
+ do {
+ index = p_sb_attn->sb_index;
+ attn_bits = le32_to_cpu(p_sb_attn->atten_bits);
+ attn_acks = le32_to_cpu(p_sb_attn->atten_ack);
+ } while (index != p_sb_attn->sb_index);
+ p_sb_attn->sb_index = index;
+
+ /* Attention / Deassertion are meaningful (and in correct state)
+ * only when they differ and consistent with known state - deassertion
+ * when previous attention & current ack, and assertion when current
+ * attention with no previous attention
+ */
+ asserted_bits = (attn_bits & ~attn_acks & ATTN_STATE_BITS) &
+ ~p_sb_attn_sw->known_attn;
+ deasserted_bits = (~attn_bits & attn_acks & ATTN_STATE_BITS) &
+ p_sb_attn_sw->known_attn;
+
+ if ((asserted_bits & ~0x100) || (deasserted_bits & ~0x100)) {
+ DP_INFO(p_hwfn,
+ "Attention: Index: 0x%04x, Bits: 0x%08x, Acks: 0x%08x, asserted: 0x%04x, De-asserted 0x%04x [Prev. known: 0x%04x]\n",
+ index, attn_bits, attn_acks, asserted_bits,
+ deasserted_bits, p_sb_attn_sw->known_attn);
+ } else if (asserted_bits == 0x100) {
+ DP_INFO(p_hwfn,
+ "MFW indication via attention\n");
+ } else {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+ "MFW indication [deassertion]\n");
+ }
+
+ if (asserted_bits) {
+ rc = qed_int_assertion(p_hwfn, asserted_bits);
+ if (rc)
+ return rc;
+ }
+
+ if (deasserted_bits) {
+ rc = qed_int_deassertion(p_hwfn, deasserted_bits);
+ if (rc)
+ return rc;
+ }
+
+ return rc;
+}
+
+static void qed_sb_ack_attn(struct qed_hwfn *p_hwfn,
+ void __iomem *igu_addr,
+ u32 ack_cons)
+{
+ struct igu_prod_cons_update igu_ack = { 0 };
+
+ igu_ack.sb_id_and_flags =
+ ((ack_cons << IGU_PROD_CONS_UPDATE_SB_INDEX_SHIFT) |
+ (1 << IGU_PROD_CONS_UPDATE_UPDATE_FLAG_SHIFT) |
+ (IGU_INT_NOP << IGU_PROD_CONS_UPDATE_ENABLE_INT_SHIFT) |
+ (IGU_SEG_ACCESS_ATTN <<
+ IGU_PROD_CONS_UPDATE_SEGMENT_ACCESS_SHIFT));
+
+ DIRECT_REG_WR(igu_addr, igu_ack.sb_id_and_flags);
+
+ /* Both segments (interrupts & acks) are written to same place address;
+ * Need to guarantee all commands will be received (in-order) by HW.
+ */
+ mmiowb();
+ barrier();
+}
+
+void qed_int_sp_dpc(unsigned long hwfn_cookie)
+{
+ struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie;
+ struct qed_pi_info *pi_info = NULL;
+ struct qed_sb_attn_info *sb_attn;
+ struct qed_sb_info *sb_info;
+ int arr_size;
+ u16 rc = 0;
+
+ if (!p_hwfn->p_sp_sb) {
+ DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n");
+ return;
+ }
+
+ sb_info = &p_hwfn->p_sp_sb->sb_info;
+ arr_size = ARRAY_SIZE(p_hwfn->p_sp_sb->pi_info_arr);
+ if (!sb_info) {
+ DP_ERR(p_hwfn->cdev,
+ "Status block is NULL - cannot ack interrupts\n");
+ return;
+ }
+
+ if (!p_hwfn->p_sb_attn) {
+ DP_ERR(p_hwfn->cdev, "DPC called - no p_sb_attn");
+ return;
+ }
+ sb_attn = p_hwfn->p_sb_attn;
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n",
+ p_hwfn, p_hwfn->my_id);
+
+ /* Disable ack for def status block. Required both for msix +
+ * inta in non-mask mode, in inta does no harm.
+ */
+ qed_sb_ack(sb_info, IGU_INT_DISABLE, 0);
+
+ /* Gather Interrupts/Attentions information */
+ if (!sb_info->sb_virt) {
+ DP_ERR(
+ p_hwfn->cdev,
+ "Interrupt Status block is NULL - cannot check for new interrupts!\n");
+ } else {
+ u32 tmp_index = sb_info->sb_ack;
+
+ rc = qed_sb_update_sb_idx(sb_info);
+ DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR,
+ "Interrupt indices: 0x%08x --> 0x%08x\n",
+ tmp_index, sb_info->sb_ack);
+ }
+
+ if (!sb_attn || !sb_attn->sb_attn) {
+ DP_ERR(
+ p_hwfn->cdev,
+ "Attentions Status block is NULL - cannot check for new attentions!\n");
+ } else {
+ u16 tmp_index = sb_attn->index;
+
+ rc |= qed_attn_update_idx(p_hwfn, sb_attn);
+ DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR,
+ "Attention indices: 0x%08x --> 0x%08x\n",
+ tmp_index, sb_attn->index);
+ }
+
+ /* Check if we expect interrupts at this time. if not just ack them */
+ if (!(rc & QED_SB_EVENT_MASK)) {
+ qed_sb_ack(sb_info, IGU_INT_ENABLE, 1);
+ return;
+ }
+
+ /* Check the validity of the DPC ptt. If not ack interrupts and fail */
+ if (!p_hwfn->p_dpc_ptt) {
+ DP_NOTICE(p_hwfn->cdev, "Failed to allocate PTT\n");
+ qed_sb_ack(sb_info, IGU_INT_ENABLE, 1);
+ return;
+ }
+
+ if (rc & QED_SB_ATT_IDX)
+ qed_int_attentions(p_hwfn);
+
+ if (rc & QED_SB_IDX) {
+ int pi;
+
+ /* Look for a free index */
+ for (pi = 0; pi < arr_size; pi++) {
+ pi_info = &p_hwfn->p_sp_sb->pi_info_arr[pi];
+ if (pi_info->comp_cb)
+ pi_info->comp_cb(p_hwfn, pi_info->cookie);
+ }
+ }
+
+ if (sb_attn && (rc & QED_SB_ATT_IDX))
+ /* This should be done before the interrupts are enabled,
+ * since otherwise a new attention will be generated.
+ */
+ qed_sb_ack_attn(p_hwfn, sb_info->igu_addr, sb_attn->index);
+
+ qed_sb_ack(sb_info, IGU_INT_ENABLE, 1);
+}
+
+static void qed_int_sb_attn_free(struct qed_hwfn *p_hwfn)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+ struct qed_sb_attn_info *p_sb = p_hwfn->p_sb_attn;
+
+ if (p_sb) {
+ if (p_sb->sb_attn)
+ dma_free_coherent(&cdev->pdev->dev,
+ SB_ATTN_ALIGNED_SIZE(p_hwfn),
+ p_sb->sb_attn,
+ p_sb->sb_phys);
+ kfree(p_sb);
+ }
+}
+
+static void qed_int_sb_attn_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn;
+
+ memset(sb_info->sb_attn, 0, sizeof(*sb_info->sb_attn));
+
+ sb_info->index = 0;
+ sb_info->known_attn = 0;
+
+ /* Configure Attention Status Block in IGU */
+ qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_L,
+ lower_32_bits(p_hwfn->p_sb_attn->sb_phys));
+ qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_H,
+ upper_32_bits(p_hwfn->p_sb_attn->sb_phys));
+}
+
+static void qed_int_sb_attn_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ void *sb_virt_addr,
+ dma_addr_t sb_phy_addr)
+{
+ struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn;
+
+ sb_info->sb_attn = sb_virt_addr;
+ sb_info->sb_phys = sb_phy_addr;
+
+ /* Set the address of cleanup for the mcp attention */
+ sb_info->mfw_attn_addr = (p_hwfn->rel_pf_id << 3) +
+ MISC_REG_AEU_GENERAL_ATTN_0;
+
+ qed_int_sb_attn_setup(p_hwfn, p_ptt);
+}
+
+static int qed_int_sb_attn_alloc(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+ struct qed_sb_attn_info *p_sb;
+ void *p_virt;
+ dma_addr_t p_phys = 0;
+
+ /* SB struct */
+ p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC);
+ if (!p_sb) {
+ DP_NOTICE(cdev, "Failed to allocate `struct qed_sb_attn_info'\n");
+ return -ENOMEM;
+ }
+
+ /* SB ring */
+ p_virt = dma_alloc_coherent(&cdev->pdev->dev,
+ SB_ATTN_ALIGNED_SIZE(p_hwfn),
+ &p_phys, GFP_KERNEL);
+
+ if (!p_virt) {
+ DP_NOTICE(cdev, "Failed to allocate status block (attentions)\n");
+ kfree(p_sb);
+ return -ENOMEM;
+ }
+
+ /* Attention setup */
+ p_hwfn->p_sb_attn = p_sb;
+ qed_int_sb_attn_init(p_hwfn, p_ptt, p_virt, p_phys);
+
+ return 0;
+}
+
+/* coalescing timeout = timeset << (timer_res + 1) */
+#define QED_CAU_DEF_RX_USECS 24
+#define QED_CAU_DEF_TX_USECS 48
+
+void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn,
+ struct cau_sb_entry *p_sb_entry,
+ u8 pf_id,
+ u16 vf_number,
+ u8 vf_valid)
+{
+ u32 cau_state;
+
+ memset(p_sb_entry, 0, sizeof(*p_sb_entry));
+
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id);
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number);
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid);
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F);
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F);
+
+ /* setting the time resultion to a fixed value ( = 1) */
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0,
+ QED_CAU_DEF_RX_TIMER_RES);
+ SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1,
+ QED_CAU_DEF_TX_TIMER_RES);
+
+ cau_state = CAU_HC_DISABLE_STATE;
+
+ if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) {
+ cau_state = CAU_HC_ENABLE_STATE;
+ if (!p_hwfn->cdev->rx_coalesce_usecs)
+ p_hwfn->cdev->rx_coalesce_usecs =
+ QED_CAU_DEF_RX_USECS;
+ if (!p_hwfn->cdev->tx_coalesce_usecs)
+ p_hwfn->cdev->tx_coalesce_usecs =
+ QED_CAU_DEF_TX_USECS;
+ }
+
+ SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state);
+ SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state);
+}
+
+void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ dma_addr_t sb_phys,
+ u16 igu_sb_id,
+ u16 vf_number,
+ u8 vf_valid)
+{
+ struct cau_sb_entry sb_entry;
+ u32 val;
+
+ qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id,
+ vf_number, vf_valid);
+
+ if (p_hwfn->hw_init_done) {
+ val = CAU_REG_SB_ADDR_MEMORY + igu_sb_id * sizeof(u64);
+ qed_wr(p_hwfn, p_ptt, val, lower_32_bits(sb_phys));
+ qed_wr(p_hwfn, p_ptt, val + sizeof(u32),
+ upper_32_bits(sb_phys));
+
+ val = CAU_REG_SB_VAR_MEMORY + igu_sb_id * sizeof(u64);
+ qed_wr(p_hwfn, p_ptt, val, sb_entry.data);
+ qed_wr(p_hwfn, p_ptt, val + sizeof(u32), sb_entry.params);
+ } else {
+ /* Initialize Status Block Address */
+ STORE_RT_REG_AGG(p_hwfn,
+ CAU_REG_SB_ADDR_MEMORY_RT_OFFSET +
+ igu_sb_id * 2,
+ sb_phys);
+
+ STORE_RT_REG_AGG(p_hwfn,
+ CAU_REG_SB_VAR_MEMORY_RT_OFFSET +
+ igu_sb_id * 2,
+ sb_entry);
+ }
+
+ /* Configure pi coalescing if set */
+ if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) {
+ u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >>
+ (QED_CAU_DEF_RX_TIMER_RES + 1);
+ u8 num_tc = 1, i;
+
+ qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI,
+ QED_COAL_RX_STATE_MACHINE,
+ timeset);
+
+ timeset = p_hwfn->cdev->tx_coalesce_usecs >>
+ (QED_CAU_DEF_TX_TIMER_RES + 1);
+
+ for (i = 0; i < num_tc; i++) {
+ qed_int_cau_conf_pi(p_hwfn, p_ptt,
+ igu_sb_id, TX_PI(i),
+ QED_COAL_TX_STATE_MACHINE,
+ timeset);
+ }
+ }
+}
+
+void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u16 igu_sb_id,
+ u32 pi_index,
+ enum qed_coalescing_fsm coalescing_fsm,
+ u8 timeset)
+{
+ struct cau_pi_entry pi_entry;
+ u32 sb_offset;
+ u32 pi_offset;
+
+ sb_offset = igu_sb_id * PIS_PER_SB;
+ memset(&pi_entry, 0, sizeof(struct cau_pi_entry));
+
+ SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset);
+ if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE)
+ SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0);
+ else
+ SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1);
+
+ pi_offset = sb_offset + pi_index;
+ if (p_hwfn->hw_init_done) {
+ qed_wr(p_hwfn, p_ptt,
+ CAU_REG_PI_MEMORY + pi_offset * sizeof(u32),
+ *((u32 *)&(pi_entry)));
+ } else {
+ STORE_RT_REG(p_hwfn,
+ CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset,
+ *((u32 *)&(pi_entry)));
+ }
+}
+
+void qed_int_sb_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_sb_info *sb_info)
+{
+ /* zero status block and ack counter */
+ sb_info->sb_ack = 0;
+ memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt));
+
+ qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys,
+ sb_info->igu_sb_id, 0, 0);
+}
+
+/**
+ * @brief qed_get_igu_sb_id - given a sw sb_id return the
+ * igu_sb_id
+ *
+ * @param p_hwfn
+ * @param sb_id
+ *
+ * @return u16
+ */
+static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn,
+ u16 sb_id)
+{
+ u16 igu_sb_id;
+
+ /* Assuming continuous set of IGU SBs dedicated for given PF */
+ if (sb_id == QED_SP_SB_ID)
+ igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id;
+ else
+ igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb;
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n",
+ (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id);
+
+ return igu_sb_id;
+}
+
+int qed_int_sb_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_sb_info *sb_info,
+ void *sb_virt_addr,
+ dma_addr_t sb_phy_addr,
+ u16 sb_id)
+{
+ sb_info->sb_virt = sb_virt_addr;
+ sb_info->sb_phys = sb_phy_addr;
+
+ sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id);
+
+ if (sb_id != QED_SP_SB_ID) {
+ p_hwfn->sbs_info[sb_id] = sb_info;
+ p_hwfn->num_sbs++;
+ }
+
+ sb_info->cdev = p_hwfn->cdev;
+
+ /* The igu address will hold the absolute address that needs to be
+ * written to for a specific status block
+ */
+ sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview +
+ GTT_BAR0_MAP_REG_IGU_CMD +
+ (sb_info->igu_sb_id << 3);
+
+ sb_info->flags |= QED_SB_INFO_INIT;
+
+ qed_int_sb_setup(p_hwfn, p_ptt, sb_info);
+
+ return 0;
+}
+
+int qed_int_sb_release(struct qed_hwfn *p_hwfn,
+ struct qed_sb_info *sb_info,
+ u16 sb_id)
+{
+ if (sb_id == QED_SP_SB_ID) {
+ DP_ERR(p_hwfn, "Do Not free sp sb using this function");
+ return -EINVAL;
+ }
+
+ /* zero status block and ack counter */
+ sb_info->sb_ack = 0;
+ memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt));
+
+ p_hwfn->sbs_info[sb_id] = NULL;
+ p_hwfn->num_sbs--;
+
+ return 0;
+}
+
+static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn)
+{
+ struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb;
+
+ if (p_sb) {
+ if (p_sb->sb_info.sb_virt)
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ SB_ALIGNED_SIZE(p_hwfn),
+ p_sb->sb_info.sb_virt,
+ p_sb->sb_info.sb_phys);
+ kfree(p_sb);
+ }
+}
+
+static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_sb_sp_info *p_sb;
+ dma_addr_t p_phys = 0;
+ void *p_virt;
+
+ /* SB struct */
+ p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC);
+ if (!p_sb) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n");
+ return -ENOMEM;
+ }
+
+ /* SB ring */
+ p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ SB_ALIGNED_SIZE(p_hwfn),
+ &p_phys, GFP_KERNEL);
+ if (!p_virt) {
+ DP_NOTICE(p_hwfn, "Failed to allocate status block\n");
+ kfree(p_sb);
+ return -ENOMEM;
+ }
+
+ /* Status Block setup */
+ p_hwfn->p_sp_sb = p_sb;
+ qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt,
+ p_phys, QED_SP_SB_ID);
+
+ memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr));
+
+ return 0;
+}
+
+static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ if (!p_hwfn)
+ return;
+
+ if (p_hwfn->p_sp_sb)
+ qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info);
+ else
+ DP_NOTICE(p_hwfn->cdev,
+ "Failed to setup Slow path status block - NULL pointer\n");
+
+ if (p_hwfn->p_sb_attn)
+ qed_int_sb_attn_setup(p_hwfn, p_ptt);
+ else
+ DP_NOTICE(p_hwfn->cdev,
+ "Failed to setup attentions status block - NULL pointer\n");
+}
+
+int qed_int_register_cb(struct qed_hwfn *p_hwfn,
+ qed_int_comp_cb_t comp_cb,
+ void *cookie,
+ u8 *sb_idx,
+ __le16 **p_fw_cons)
+{
+ struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb;
+ int qed_status = -ENOMEM;
+ u8 pi;
+
+ /* Look for a free index */
+ for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) {
+ if (!p_sp_sb->pi_info_arr[pi].comp_cb) {
+ p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb;
+ p_sp_sb->pi_info_arr[pi].cookie = cookie;
+ *sb_idx = pi;
+ *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi];
+ qed_status = 0;
+ break;
+ }
+ }
+
+ return qed_status;
+}
+
+int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi)
+{
+ struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb;
+ int qed_status = -ENOMEM;
+
+ if (p_sp_sb->pi_info_arr[pi].comp_cb) {
+ p_sp_sb->pi_info_arr[pi].comp_cb = NULL;
+ p_sp_sb->pi_info_arr[pi].cookie = NULL;
+ qed_status = 0;
+ }
+
+ return qed_status;
+}
+
+u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn)
+{
+ return p_hwfn->p_sp_sb->sb_info.igu_sb_id;
+}
+
+void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_int_mode int_mode)
+{
+ u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN | IGU_PF_CONF_ATTN_BIT_EN;
+
+ p_hwfn->cdev->int_mode = int_mode;
+ switch (p_hwfn->cdev->int_mode) {
+ case QED_INT_MODE_INTA:
+ igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN;
+ igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN;
+ break;
+
+ case QED_INT_MODE_MSI:
+ igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN;
+ igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN;
+ break;
+
+ case QED_INT_MODE_MSIX:
+ igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN;
+ break;
+ case QED_INT_MODE_POLL:
+ break;
+ }
+
+ qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf);
+}
+
+void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_int_mode int_mode)
+{
+ int i;
+
+ p_hwfn->b_int_enabled = 1;
+
+ /* Mask non-link attentions */
+ for (i = 0; i < 9; i++)
+ qed_wr(p_hwfn, p_ptt,
+ MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0);
+
+ /* Enable interrupt Generation */
+ qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
+
+ /* Configure AEU signal change to produce attentions for link */
+ qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff);
+ qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff);
+
+ /* Flush the writes to IGU */
+ mmiowb();
+
+ /* Unmask AEU signals toward IGU */
+ qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff);
+}
+
+void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ p_hwfn->b_int_enabled = 0;
+
+ qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0);
+}
+
+#define IGU_CLEANUP_SLEEP_LENGTH (1000)
+void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 sb_id,
+ bool cleanup_set,
+ u16 opaque_fid
+ )
+{
+ u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id;
+ u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH;
+ u32 data = 0;
+ u32 cmd_ctrl = 0;
+ u32 val = 0;
+ u32 sb_bit = 0;
+ u32 sb_bit_addr = 0;
+
+ /* Set the data field */
+ SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0);
+ SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0);
+ SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET);
+
+ /* Set the control register */
+ SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr);
+ SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid);
+ SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR);
+
+ qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data);
+
+ barrier();
+
+ qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl);
+
+ /* Flush the write to IGU */
+ mmiowb();
+
+ /* calculate where to read the status bit from */
+ sb_bit = 1 << (sb_id % 32);
+ sb_bit_addr = sb_id / 32 * sizeof(u32);
+
+ sb_bit_addr += IGU_REG_CLEANUP_STATUS_0;
+
+ /* Now wait for the command to complete */
+ do {
+ val = qed_rd(p_hwfn, p_ptt, sb_bit_addr);
+
+ if ((val & sb_bit) == (cleanup_set ? sb_bit : 0))
+ break;
+
+ usleep_range(5000, 10000);
+ } while (--sleep_cnt);
+
+ if (!sleep_cnt)
+ DP_NOTICE(p_hwfn,
+ "Timeout waiting for clear status 0x%08x [for sb %d]\n",
+ val, sb_id);
+}
+
+void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 sb_id,
+ u16 opaque,
+ bool b_set)
+{
+ int pi;
+
+ /* Set */
+ if (b_set)
+ qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque);
+
+ /* Clear */
+ qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque);
+
+ /* Clear the CAU for the SB */
+ for (pi = 0; pi < 12; pi++)
+ qed_wr(p_hwfn, p_ptt,
+ CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0);
+}
+
+void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool b_set,
+ bool b_slowpath)
+{
+ u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb;
+ u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt;
+ u32 sb_id = 0;
+ u32 val = 0;
+
+ val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION);
+ val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN;
+ val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN;
+ qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+ "IGU cleaning SBs [%d,...,%d]\n",
+ igu_base_sb, igu_base_sb + igu_sb_cnt - 1);
+
+ for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++)
+ qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id,
+ p_hwfn->hw_info.opaque_fid,
+ b_set);
+
+ if (b_slowpath) {
+ sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id;
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+ "IGU cleaning slowpath SB [%d]\n", sb_id);
+ qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id,
+ p_hwfn->hw_info.opaque_fid,
+ b_set);
+ }
+}
+
+int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_igu_info *p_igu_info;
+ struct qed_igu_block *blk;
+ u32 val;
+ u16 sb_id;
+ u16 prev_sb_id = 0xFF;
+
+ p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_ATOMIC);
+
+ if (!p_hwfn->hw_info.p_igu_info)
+ return -ENOMEM;
+
+ p_igu_info = p_hwfn->hw_info.p_igu_info;
+
+ /* Initialize base sb / sb cnt for PFs */
+ p_igu_info->igu_base_sb = 0xffff;
+ p_igu_info->igu_sb_cnt = 0;
+ p_igu_info->igu_dsb_id = 0xffff;
+ p_igu_info->igu_base_sb_iov = 0xffff;
+
+ for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev);
+ sb_id++) {
+ blk = &p_igu_info->igu_map.igu_blocks[sb_id];
+
+ val = qed_rd(p_hwfn, p_ptt,
+ IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id);
+
+ /* stop scanning when hit first invalid PF entry */
+ if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) &&
+ GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID))
+ break;
+
+ blk->status = QED_IGU_STATUS_VALID;
+ blk->function_id = GET_FIELD(val,
+ IGU_MAPPING_LINE_FUNCTION_NUMBER);
+ blk->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID);
+ blk->vector_number = GET_FIELD(val,
+ IGU_MAPPING_LINE_VECTOR_NUMBER);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+ "IGU_BLOCK[sb_id]:%x:func_id = %d is_pf = %d vector_num = 0x%x\n",
+ val, blk->function_id, blk->is_pf,
+ blk->vector_number);
+
+ if (blk->is_pf) {
+ if (blk->function_id == p_hwfn->rel_pf_id) {
+ blk->status |= QED_IGU_STATUS_PF;
+
+ if (blk->vector_number == 0) {
+ if (p_igu_info->igu_dsb_id == 0xffff)
+ p_igu_info->igu_dsb_id = sb_id;
+ } else {
+ if (p_igu_info->igu_base_sb ==
+ 0xffff) {
+ p_igu_info->igu_base_sb = sb_id;
+ } else if (prev_sb_id != sb_id - 1) {
+ DP_NOTICE(p_hwfn->cdev,
+ "consecutive igu vectors for HWFN %x broken",
+ p_hwfn->rel_pf_id);
+ break;
+ }
+ prev_sb_id = sb_id;
+ /* we don't count the default */
+ (p_igu_info->igu_sb_cnt)++;
+ }
+ }
+ }
+ }
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+ "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n",
+ p_igu_info->igu_base_sb,
+ p_igu_info->igu_sb_cnt,
+ p_igu_info->igu_dsb_id);
+
+ if (p_igu_info->igu_base_sb == 0xffff ||
+ p_igu_info->igu_dsb_id == 0xffff ||
+ p_igu_info->igu_sb_cnt == 0) {
+ DP_NOTICE(p_hwfn,
+ "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n",
+ p_igu_info->igu_base_sb,
+ p_igu_info->igu_sb_cnt,
+ p_igu_info->igu_dsb_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Initialize igu runtime registers
+ *
+ * @param p_hwfn
+ */
+void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn)
+{
+ u32 igu_pf_conf = 0;
+
+ igu_pf_conf |= IGU_PF_CONF_FUNC_EN;
+
+ STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf);
+}
+
+u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn)
+{
+ u64 intr_status = 0;
+ u32 intr_status_lo = 0;
+ u32 intr_status_hi = 0;
+ u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER -
+ IGU_CMD_INT_ACK_BASE;
+ u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER -
+ IGU_CMD_INT_ACK_BASE;
+
+ intr_status_lo = REG_RD(p_hwfn,
+ GTT_BAR0_MAP_REG_IGU_CMD +
+ lsb_igu_cmd_addr * 8);
+ intr_status_hi = REG_RD(p_hwfn,
+ GTT_BAR0_MAP_REG_IGU_CMD +
+ msb_igu_cmd_addr * 8);
+ intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo;
+
+ return intr_status;
+}
+
+static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn)
+{
+ tasklet_init(p_hwfn->sp_dpc,
+ qed_int_sp_dpc, (unsigned long)p_hwfn);
+ p_hwfn->b_sp_dpc_enabled = true;
+}
+
+static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn)
+{
+ p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_ATOMIC);
+ if (!p_hwfn->sp_dpc)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn)
+{
+ kfree(p_hwfn->sp_dpc);
+}
+
+int qed_int_alloc(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ int rc = 0;
+
+ rc = qed_int_sp_dpc_alloc(p_hwfn);
+ if (rc) {
+ DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n");
+ return rc;
+ }
+ rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt);
+ if (rc) {
+ DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n");
+ return rc;
+ }
+ rc = qed_int_sb_attn_alloc(p_hwfn, p_ptt);
+ if (rc) {
+ DP_ERR(p_hwfn->cdev, "Failed to allocate sb attn mem\n");
+ return rc;
+ }
+ return rc;
+}
+
+void qed_int_free(struct qed_hwfn *p_hwfn)
+{
+ qed_int_sp_sb_free(p_hwfn);
+ qed_int_sb_attn_free(p_hwfn);
+ qed_int_sp_dpc_free(p_hwfn);
+}
+
+void qed_int_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ qed_int_sp_sb_setup(p_hwfn, p_ptt);
+ qed_int_sp_dpc_setup(p_hwfn);
+}
+
+int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn,
+ int *p_iov_blks)
+{
+ struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info;
+
+ if (!info)
+ return 0;
+
+ if (p_iov_blks)
+ *p_iov_blks = info->free_blks;
+
+ return info->igu_sb_cnt;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h
new file mode 100644
index 000000000000..16b57518e706
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.h
@@ -0,0 +1,391 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_INT_H
+#define _QED_INT_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include "qed.h"
+
+/* Fields of IGU PF CONFIGRATION REGISTER */
+#define IGU_PF_CONF_FUNC_EN (0x1 << 0) /* function enable */
+#define IGU_PF_CONF_MSI_MSIX_EN (0x1 << 1) /* MSI/MSIX enable */
+#define IGU_PF_CONF_INT_LINE_EN (0x1 << 2) /* INT enable */
+#define IGU_PF_CONF_ATTN_BIT_EN (0x1 << 3) /* attention enable */
+#define IGU_PF_CONF_SINGLE_ISR_EN (0x1 << 4) /* single ISR mode enable */
+#define IGU_PF_CONF_SIMD_MODE (0x1 << 5) /* simd all ones mode */
+
+/* Igu control commands
+ */
+enum igu_ctrl_cmd {
+ IGU_CTRL_CMD_TYPE_RD,
+ IGU_CTRL_CMD_TYPE_WR,
+ MAX_IGU_CTRL_CMD
+};
+
+/* Control register for the IGU command register
+ */
+struct igu_ctrl_reg {
+ u32 ctrl_data;
+#define IGU_CTRL_REG_FID_MASK 0xFFFF /* Opaque_FID */
+#define IGU_CTRL_REG_FID_SHIFT 0
+#define IGU_CTRL_REG_PXP_ADDR_MASK 0xFFF /* Command address */
+#define IGU_CTRL_REG_PXP_ADDR_SHIFT 16
+#define IGU_CTRL_REG_RESERVED_MASK 0x1
+#define IGU_CTRL_REG_RESERVED_SHIFT 28
+#define IGU_CTRL_REG_TYPE_MASK 0x1 /* use enum igu_ctrl_cmd */
+#define IGU_CTRL_REG_TYPE_SHIFT 31
+};
+
+enum qed_coalescing_fsm {
+ QED_COAL_RX_STATE_MACHINE,
+ QED_COAL_TX_STATE_MACHINE
+};
+
+/**
+ * @brief qed_int_cau_conf_pi - configure cau for a given
+ * status block
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param igu_sb_id
+ * @param pi_index
+ * @param state
+ * @param timeset
+ */
+void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u16 igu_sb_id,
+ u32 pi_index,
+ enum qed_coalescing_fsm coalescing_fsm,
+ u8 timeset);
+
+/**
+ * @brief qed_int_igu_enable_int - enable device interrupts
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param int_mode - interrupt mode to use
+ */
+void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_int_mode int_mode);
+
+/**
+ * @brief qed_int_igu_disable_int - disable device interrupts
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief qed_int_igu_read_sisr_reg - Reads the single isr multiple dpc
+ * register from igu.
+ *
+ * @param p_hwfn
+ *
+ * @return u64
+ */
+u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn);
+
+#define QED_SP_SB_ID 0xffff
+/**
+ * @brief qed_int_sb_init - Initializes the sb_info structure.
+ *
+ * once the structure is initialized it can be passed to sb related functions.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param sb_info points to an uninitialized (but
+ * allocated) sb_info structure
+ * @param sb_virt_addr
+ * @param sb_phy_addr
+ * @param sb_id the sb_id to be used (zero based in driver)
+ * should use QED_SP_SB_ID for SP Status block
+ *
+ * @return int
+ */
+int qed_int_sb_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_sb_info *sb_info,
+ void *sb_virt_addr,
+ dma_addr_t sb_phy_addr,
+ u16 sb_id);
+/**
+ * @brief qed_int_sb_setup - Setup the sb.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param sb_info initialized sb_info structure
+ */
+void qed_int_sb_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_sb_info *sb_info);
+
+/**
+ * @brief qed_int_sb_release - releases the sb_info structure.
+ *
+ * once the structure is released, it's memory can be freed
+ *
+ * @param p_hwfn
+ * @param sb_info points to an allocated sb_info structure
+ * @param sb_id the sb_id to be used (zero based in driver)
+ * should never be equal to QED_SP_SB_ID
+ * (SP Status block)
+ *
+ * @return int
+ */
+int qed_int_sb_release(struct qed_hwfn *p_hwfn,
+ struct qed_sb_info *sb_info,
+ u16 sb_id);
+
+/**
+ * @brief qed_int_sp_dpc - To be called when an interrupt is received on the
+ * default status block.
+ *
+ * @param p_hwfn - pointer to hwfn
+ *
+ */
+void qed_int_sp_dpc(unsigned long hwfn_cookie);
+
+/**
+ * @brief qed_int_get_num_sbs - get the number of status
+ * blocks configured for this funciton in the igu.
+ *
+ * @param p_hwfn
+ * @param p_iov_blks - configured free blks for vfs
+ *
+ * @return int - number of status blocks configured
+ */
+int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn,
+ int *p_iov_blks);
+
+/**
+ * @file
+ *
+ * @brief Interrupt handler
+ */
+
+#define QED_CAU_DEF_RX_TIMER_RES 0
+#define QED_CAU_DEF_TX_TIMER_RES 0
+
+#define QED_SB_ATT_IDX 0x0001
+#define QED_SB_EVENT_MASK 0x0003
+
+#define SB_ALIGNED_SIZE(p_hwfn) \
+ ALIGNED_TYPE_SIZE(struct status_block, p_hwfn)
+
+struct qed_igu_block {
+ u8 status;
+#define QED_IGU_STATUS_FREE 0x01
+#define QED_IGU_STATUS_VALID 0x02
+#define QED_IGU_STATUS_PF 0x04
+
+ u8 vector_number;
+ u8 function_id;
+ u8 is_pf;
+};
+
+struct qed_igu_map {
+ struct qed_igu_block igu_blocks[MAX_TOT_SB_PER_PATH];
+};
+
+struct qed_igu_info {
+ struct qed_igu_map igu_map;
+ u16 igu_dsb_id;
+ u16 igu_base_sb;
+ u16 igu_base_sb_iov;
+ u16 igu_sb_cnt;
+ u16 igu_sb_cnt_iov;
+ u16 free_blks;
+};
+
+/* TODO Names of function may change... */
+void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool b_set,
+ bool b_slowpath);
+
+void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_int_igu_read_cam - Reads the IGU CAM.
+ * This function needs to be called during hardware
+ * prepare. It reads the info from igu cam to know which
+ * status block is the default / base status block etc.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return int
+ */
+int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+typedef int (*qed_int_comp_cb_t)(struct qed_hwfn *p_hwfn,
+ void *cookie);
+/**
+ * @brief qed_int_register_cb - Register callback func for
+ * slowhwfn statusblock.
+ *
+ * Every protocol that uses the slowhwfn status block
+ * should register a callback function that will be called
+ * once there is an update of the sp status block.
+ *
+ * @param p_hwfn
+ * @param comp_cb - function to be called when there is an
+ * interrupt on the sp sb
+ *
+ * @param cookie - passed to the callback function
+ * @param sb_idx - OUT parameter which gives the chosen index
+ * for this protocol.
+ * @param p_fw_cons - pointer to the actual address of the
+ * consumer for this protocol.
+ *
+ * @return int
+ */
+int qed_int_register_cb(struct qed_hwfn *p_hwfn,
+ qed_int_comp_cb_t comp_cb,
+ void *cookie,
+ u8 *sb_idx,
+ __le16 **p_fw_cons);
+
+/**
+ * @brief qed_int_unregister_cb - Unregisters callback
+ * function from sp sb.
+ * Partner of qed_int_register_cb -> should be called
+ * when no longer required.
+ *
+ * @param p_hwfn
+ * @param pi
+ *
+ * @return int
+ */
+int qed_int_unregister_cb(struct qed_hwfn *p_hwfn,
+ u8 pi);
+
+/**
+ * @brief qed_int_get_sp_sb_id - Get the slowhwfn sb id.
+ *
+ * @param p_hwfn
+ *
+ * @return u16
+ */
+u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief Status block cleanup. Should be called for each status
+ * block that will be used -> both PF / VF
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param sb_id - igu status block id
+ * @param cleanup_set - set(1) / clear(0)
+ * @param opaque_fid - the function for which to perform
+ * cleanup, for example a PF on behalf of
+ * its VFs.
+ */
+void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 sb_id,
+ bool cleanup_set,
+ u16 opaque_fid);
+
+/**
+ * @brief Status block cleanup. Should be called for each status
+ * block that will be used -> both PF / VF
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param sb_id - igu status block id
+ * @param opaque - opaque fid of the sb owner.
+ * @param cleanup_set - set(1) / clear(0)
+ */
+void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 sb_id,
+ u16 opaque,
+ bool b_set);
+
+/**
+ * @brief qed_int_cau_conf - configure cau for a given status
+ * block
+ *
+ * @param p_hwfn
+ * @param ptt
+ * @param sb_phys
+ * @param igu_sb_id
+ * @param vf_number
+ * @param vf_valid
+ */
+void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ dma_addr_t sb_phys,
+ u16 igu_sb_id,
+ u16 vf_number,
+ u8 vf_valid);
+
+/**
+ * @brief qed_int_alloc
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return int
+ */
+int qed_int_alloc(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief qed_int_free
+ *
+ * @param p_hwfn
+ */
+void qed_int_free(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_int_setup
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+void qed_int_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief - Enable Interrupt & Attention for hw function
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param int_mode
+ */
+void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_int_mode int_mode);
+
+/**
+ * @brief - Initialize CAU status block entry
+ *
+ * @param p_hwfn
+ * @param p_sb_entry
+ * @param pf_id
+ * @param vf_number
+ * @param vf_valid
+ */
+void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn,
+ struct cau_sb_entry *p_sb_entry,
+ u8 pf_id,
+ u16 vf_number,
+ u8 vf_valid);
+
+#define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev))
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
new file mode 100644
index 000000000000..f72036a2ef5b
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -0,0 +1,1704 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/param.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include "qed.h"
+#include <linux/qed/qed_chain.h>
+#include "qed_cxt.h"
+#include "qed_dev_api.h"
+#include <linux/qed/qed_eth_if.h>
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_int.h"
+#include "qed_reg_addr.h"
+#include "qed_sp.h"
+
+enum qed_rss_caps {
+ QED_RSS_IPV4 = 0x1,
+ QED_RSS_IPV6 = 0x2,
+ QED_RSS_IPV4_TCP = 0x4,
+ QED_RSS_IPV6_TCP = 0x8,
+ QED_RSS_IPV4_UDP = 0x10,
+ QED_RSS_IPV6_UDP = 0x20,
+};
+
+/* Should be the same as ETH_RSS_IND_TABLE_ENTRIES_NUM */
+#define QED_RSS_IND_TABLE_SIZE 128
+#define QED_RSS_KEY_SIZE 10 /* size in 32b chunks */
+
+struct qed_rss_params {
+ u8 update_rss_config;
+ u8 rss_enable;
+ u8 rss_eng_id;
+ u8 update_rss_capabilities;
+ u8 update_rss_ind_table;
+ u8 update_rss_key;
+ u8 rss_caps;
+ u8 rss_table_size_log;
+ u16 rss_ind_table[QED_RSS_IND_TABLE_SIZE];
+ u32 rss_key[QED_RSS_KEY_SIZE];
+};
+
+enum qed_filter_opcode {
+ QED_FILTER_ADD,
+ QED_FILTER_REMOVE,
+ QED_FILTER_MOVE,
+ QED_FILTER_REPLACE, /* Delete all MACs and add new one instead */
+ QED_FILTER_FLUSH, /* Removes all filters */
+};
+
+enum qed_filter_ucast_type {
+ QED_FILTER_MAC,
+ QED_FILTER_VLAN,
+ QED_FILTER_MAC_VLAN,
+ QED_FILTER_INNER_MAC,
+ QED_FILTER_INNER_VLAN,
+ QED_FILTER_INNER_PAIR,
+ QED_FILTER_INNER_MAC_VNI_PAIR,
+ QED_FILTER_MAC_VNI_PAIR,
+ QED_FILTER_VNI,
+};
+
+struct qed_filter_ucast {
+ enum qed_filter_opcode opcode;
+ enum qed_filter_ucast_type type;
+ u8 is_rx_filter;
+ u8 is_tx_filter;
+ u8 vport_to_add_to;
+ u8 vport_to_remove_from;
+ unsigned char mac[ETH_ALEN];
+ u8 assert_on_error;
+ u16 vlan;
+ u32 vni;
+};
+
+struct qed_filter_mcast {
+ /* MOVE is not supported for multicast */
+ enum qed_filter_opcode opcode;
+ u8 vport_to_add_to;
+ u8 vport_to_remove_from;
+ u8 num_mc_addrs;
+#define QED_MAX_MC_ADDRS 64
+ unsigned char mac[QED_MAX_MC_ADDRS][ETH_ALEN];
+};
+
+struct qed_filter_accept_flags {
+ u8 update_rx_mode_config;
+ u8 update_tx_mode_config;
+ u8 rx_accept_filter;
+ u8 tx_accept_filter;
+#define QED_ACCEPT_NONE 0x01
+#define QED_ACCEPT_UCAST_MATCHED 0x02
+#define QED_ACCEPT_UCAST_UNMATCHED 0x04
+#define QED_ACCEPT_MCAST_MATCHED 0x08
+#define QED_ACCEPT_MCAST_UNMATCHED 0x10
+#define QED_ACCEPT_BCAST 0x20
+};
+
+struct qed_sp_vport_update_params {
+ u16 opaque_fid;
+ u8 vport_id;
+ u8 update_vport_active_rx_flg;
+ u8 vport_active_rx_flg;
+ u8 update_vport_active_tx_flg;
+ u8 vport_active_tx_flg;
+ u8 update_approx_mcast_flg;
+ unsigned long bins[8];
+ struct qed_rss_params *rss_params;
+ struct qed_filter_accept_flags accept_flags;
+};
+
+#define QED_MAX_SGES_NUM 16
+#define CRC32_POLY 0x1edc6f41
+
+static int qed_sp_vport_start(struct qed_hwfn *p_hwfn,
+ u32 concrete_fid,
+ u16 opaque_fid,
+ u8 vport_id,
+ u16 mtu,
+ u8 drop_ttl0_flg,
+ u8 inner_vlan_removal_en_flg)
+{
+ struct qed_sp_init_request_params params;
+ struct vport_start_ramrod_data *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ int rc = -EINVAL;
+ u16 rx_mode = 0;
+ u8 abs_vport_id = 0;
+
+ rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id);
+ if (rc != 0)
+ return rc;
+
+ memset(&params, 0, sizeof(params));
+ params.ramrod_data_size = sizeof(*p_ramrod);
+ params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ qed_spq_get_cid(p_hwfn),
+ opaque_fid,
+ ETH_RAMROD_VPORT_START,
+ PROTOCOLID_ETH,
+ &params);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.vport_start;
+ p_ramrod->vport_id = abs_vport_id;
+
+ p_ramrod->mtu = cpu_to_le16(mtu);
+ p_ramrod->inner_vlan_removal_en = inner_vlan_removal_en_flg;
+ p_ramrod->drop_ttl0_en = drop_ttl0_flg;
+
+ SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 1);
+ SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 1);
+
+ p_ramrod->rx_mode.state = cpu_to_le16(rx_mode);
+
+ /* TPA related fields */
+ memset(&p_ramrod->tpa_param, 0,
+ sizeof(struct eth_vport_tpa_param));
+
+ /* Software Function ID in hwfn (PFs are 0 - 15, VFs are 16 - 135) */
+ p_ramrod->sw_fid = qed_concrete_to_sw_fid(p_hwfn->cdev,
+ concrete_fid);
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int
+qed_sp_vport_update_rss(struct qed_hwfn *p_hwfn,
+ struct vport_update_ramrod_data *p_ramrod,
+ struct qed_rss_params *p_params)
+{
+ struct eth_vport_rss_config *rss = &p_ramrod->rss_config;
+ u16 abs_l2_queue = 0, capabilities = 0;
+ int rc = 0, i;
+
+ if (!p_params) {
+ p_ramrod->common.update_rss_flg = 0;
+ return rc;
+ }
+
+ BUILD_BUG_ON(QED_RSS_IND_TABLE_SIZE !=
+ ETH_RSS_IND_TABLE_ENTRIES_NUM);
+
+ rc = qed_fw_rss_eng(p_hwfn, p_params->rss_eng_id, &rss->rss_id);
+ if (rc)
+ return rc;
+
+ p_ramrod->common.update_rss_flg = p_params->update_rss_config;
+ rss->update_rss_capabilities = p_params->update_rss_capabilities;
+ rss->update_rss_ind_table = p_params->update_rss_ind_table;
+ rss->update_rss_key = p_params->update_rss_key;
+
+ rss->rss_mode = p_params->rss_enable ?
+ ETH_VPORT_RSS_MODE_REGULAR :
+ ETH_VPORT_RSS_MODE_DISABLED;
+
+ SET_FIELD(capabilities,
+ ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY,
+ !!(p_params->rss_caps & QED_RSS_IPV4));
+ SET_FIELD(capabilities,
+ ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY,
+ !!(p_params->rss_caps & QED_RSS_IPV6));
+ SET_FIELD(capabilities,
+ ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY,
+ !!(p_params->rss_caps & QED_RSS_IPV4_TCP));
+ SET_FIELD(capabilities,
+ ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY,
+ !!(p_params->rss_caps & QED_RSS_IPV6_TCP));
+ SET_FIELD(capabilities,
+ ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY,
+ !!(p_params->rss_caps & QED_RSS_IPV4_UDP));
+ SET_FIELD(capabilities,
+ ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY,
+ !!(p_params->rss_caps & QED_RSS_IPV6_UDP));
+ rss->tbl_size = p_params->rss_table_size_log;
+
+ rss->capabilities = cpu_to_le16(capabilities);
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP,
+ "update rss flag %d, rss_mode = %d, update_caps = %d, capabilities = %d, update_ind = %d, update_rss_key = %d\n",
+ p_ramrod->common.update_rss_flg,
+ rss->rss_mode, rss->update_rss_capabilities,
+ capabilities, rss->update_rss_ind_table,
+ rss->update_rss_key);
+
+ for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) {
+ rc = qed_fw_l2_queue(p_hwfn,
+ (u8)p_params->rss_ind_table[i],
+ &abs_l2_queue);
+ if (rc)
+ return rc;
+
+ rss->indirection_table[i] = cpu_to_le16(abs_l2_queue);
+ DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, "i= %d, queue = %d\n",
+ i, rss->indirection_table[i]);
+ }
+
+ for (i = 0; i < 10; i++)
+ rss->rss_key[i] = cpu_to_le32(p_params->rss_key[i]);
+
+ return rc;
+}
+
+static void
+qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn,
+ struct vport_update_ramrod_data *p_ramrod,
+ struct qed_filter_accept_flags accept_flags)
+{
+ p_ramrod->common.update_rx_mode_flg =
+ accept_flags.update_rx_mode_config;
+
+ p_ramrod->common.update_tx_mode_flg =
+ accept_flags.update_tx_mode_config;
+
+ /* Set Rx mode accept flags */
+ if (p_ramrod->common.update_rx_mode_flg) {
+ u8 accept_filter = accept_flags.rx_accept_filter;
+ u16 state = 0;
+
+ SET_FIELD(state, ETH_VPORT_RX_MODE_UCAST_DROP_ALL,
+ !(!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) ||
+ !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)));
+
+ SET_FIELD(state, ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED,
+ !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED));
+
+ SET_FIELD(state, ETH_VPORT_RX_MODE_MCAST_DROP_ALL,
+ !(!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) ||
+ !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
+
+ SET_FIELD(state, ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL,
+ (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) &&
+ !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
+
+ SET_FIELD(state, ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL,
+ !!(accept_filter & QED_ACCEPT_BCAST));
+
+ p_ramrod->rx_mode.state = cpu_to_le16(state);
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "p_ramrod->rx_mode.state = 0x%x\n", state);
+ }
+
+ /* Set Tx mode accept flags */
+ if (p_ramrod->common.update_tx_mode_flg) {
+ u8 accept_filter = accept_flags.tx_accept_filter;
+ u16 state = 0;
+
+ SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_DROP_ALL,
+ !!(accept_filter & QED_ACCEPT_NONE));
+
+ 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_MCAST_DROP_ALL,
+ !!(accept_filter & QED_ACCEPT_NONE));
+
+ SET_FIELD(state, ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL,
+ (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) &&
+ !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
+
+ SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL,
+ !!(accept_filter & QED_ACCEPT_BCAST));
+
+ p_ramrod->tx_mode.state = cpu_to_le16(state);
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "p_ramrod->tx_mode.state = 0x%x\n", state);
+ }
+}
+
+static void
+qed_sp_update_mcast_bin(struct qed_hwfn *p_hwfn,
+ struct vport_update_ramrod_data *p_ramrod,
+ struct qed_sp_vport_update_params *p_params)
+{
+ int i;
+
+ memset(&p_ramrod->approx_mcast.bins, 0,
+ sizeof(p_ramrod->approx_mcast.bins));
+
+ if (p_params->update_approx_mcast_flg) {
+ p_ramrod->common.update_approx_mcast_flg = 1;
+ for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) {
+ u32 *p_bins = (u32 *)p_params->bins;
+ __le32 val = cpu_to_le32(p_bins[i]);
+
+ p_ramrod->approx_mcast.bins[i] = val;
+ }
+ }
+}
+
+static int
+qed_sp_vport_update(struct qed_hwfn *p_hwfn,
+ struct qed_sp_vport_update_params *p_params,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ struct qed_rss_params *p_rss_params = p_params->rss_params;
+ struct vport_update_ramrod_data_cmn *p_cmn;
+ struct qed_sp_init_request_params sp_params;
+ struct vport_update_ramrod_data *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ u8 abs_vport_id = 0;
+ int rc = -EINVAL;
+
+ rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
+ if (rc != 0)
+ return rc;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(*p_ramrod);
+ sp_params.comp_mode = comp_mode;
+ sp_params.p_comp_data = p_comp_data;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ qed_spq_get_cid(p_hwfn),
+ p_params->opaque_fid,
+ ETH_RAMROD_VPORT_UPDATE,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ /* Copy input params to ramrod according to FW struct */
+ p_ramrod = &p_ent->ramrod.vport_update;
+ p_cmn = &p_ramrod->common;
+
+ p_cmn->vport_id = abs_vport_id;
+ p_cmn->rx_active_flg = p_params->vport_active_rx_flg;
+ p_cmn->update_rx_active_flg = p_params->update_vport_active_rx_flg;
+ p_cmn->tx_active_flg = p_params->vport_active_tx_flg;
+ p_cmn->update_tx_active_flg = p_params->update_vport_active_tx_flg;
+
+ rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params);
+ if (rc) {
+ /* Return spq entry which is taken in qed_sp_init_request()*/
+ qed_spq_return_entry(p_hwfn, p_ent);
+ return rc;
+ }
+
+ /* Update mcast bins for VFs, PF doesn't use this functionality */
+ qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params);
+
+ qed_sp_update_accept_mode(p_hwfn, p_ramrod, p_params->accept_flags);
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_sp_vport_stop(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ u8 vport_id)
+{
+ struct qed_sp_init_request_params sp_params;
+ struct vport_stop_ramrod_data *p_ramrod;
+ struct qed_spq_entry *p_ent;
+ u8 abs_vport_id = 0;
+ int rc;
+
+ rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id);
+ if (rc != 0)
+ return rc;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(*p_ramrod);
+ sp_params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ qed_spq_get_cid(p_hwfn),
+ opaque_fid,
+ ETH_RAMROD_VPORT_STOP,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.vport_stop;
+ p_ramrod->vport_id = abs_vport_id;
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_filter_accept_cmd(struct qed_dev *cdev,
+ u8 vport,
+ struct qed_filter_accept_flags accept_flags,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ struct qed_sp_vport_update_params vport_update_params;
+ int i, rc;
+
+ /* Prepare and send the vport rx_mode change */
+ memset(&vport_update_params, 0, sizeof(vport_update_params));
+ vport_update_params.vport_id = vport;
+ vport_update_params.accept_flags = accept_flags;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ vport_update_params.opaque_fid = p_hwfn->hw_info.opaque_fid;
+
+ rc = qed_sp_vport_update(p_hwfn, &vport_update_params,
+ comp_mode, p_comp_data);
+ if (rc != 0) {
+ DP_ERR(cdev, "Update rx_mode failed %d\n", rc);
+ return rc;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "Accept filter configured, flags = [Rx]%x [Tx]%x\n",
+ accept_flags.rx_accept_filter,
+ accept_flags.tx_accept_filter);
+ }
+
+ return 0;
+}
+
+static int qed_sp_release_queue_cid(
+ struct qed_hwfn *p_hwfn,
+ struct qed_hw_cid_data *p_cid_data)
+{
+ if (!p_cid_data->b_cid_allocated)
+ return 0;
+
+ qed_cxt_release_cid(p_hwfn, p_cid_data->cid);
+
+ p_cid_data->b_cid_allocated = false;
+
+ return 0;
+}
+
+static int
+qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ u32 cid,
+ struct qed_queue_start_common_params *params,
+ u8 stats_id,
+ u16 bd_max_bytes,
+ dma_addr_t bd_chain_phys_addr,
+ dma_addr_t cqe_pbl_addr,
+ u16 cqe_pbl_size)
+{
+ struct rx_queue_start_ramrod_data *p_ramrod = NULL;
+ struct qed_sp_init_request_params sp_params;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_hw_cid_data *p_rx_cid;
+ u16 abs_rx_q_id = 0;
+ u8 abs_vport_id = 0;
+ int rc = -EINVAL;
+
+ /* Store information for the stop */
+ p_rx_cid = &p_hwfn->p_rx_cids[params->queue_id];
+ p_rx_cid->cid = cid;
+ p_rx_cid->opaque_fid = opaque_fid;
+ p_rx_cid->vport_id = params->vport_id;
+
+ rc = qed_fw_vport(p_hwfn, params->vport_id, &abs_vport_id);
+ if (rc != 0)
+ return rc;
+
+ rc = qed_fw_l2_queue(p_hwfn, params->queue_id, &abs_rx_q_id);
+ if (rc != 0)
+ return rc;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "opaque_fid=0x%x, cid=0x%x, rx_qid=0x%x, vport_id=0x%x, sb_id=0x%x\n",
+ opaque_fid, cid, params->queue_id, params->vport_id,
+ params->sb);
+
+ memset(&sp_params, 0, sizeof(params));
+ sp_params.comp_mode = QED_SPQ_MODE_EBLOCK;
+ sp_params.ramrod_data_size = sizeof(*p_ramrod);
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ cid, opaque_fid,
+ ETH_RAMROD_RX_QUEUE_START,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.rx_queue_start;
+
+ p_ramrod->sb_id = cpu_to_le16(params->sb);
+ p_ramrod->sb_index = params->sb_idx;
+ p_ramrod->vport_id = abs_vport_id;
+ p_ramrod->stats_counter_id = stats_id;
+ p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id);
+ p_ramrod->complete_cqe_flg = 0;
+ p_ramrod->complete_event_flg = 1;
+
+ p_ramrod->bd_max_bytes = cpu_to_le16(bd_max_bytes);
+ p_ramrod->bd_base.hi = DMA_HI_LE(bd_chain_phys_addr);
+ p_ramrod->bd_base.lo = DMA_LO_LE(bd_chain_phys_addr);
+
+ p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size);
+ p_ramrod->cqe_pbl_addr.hi = DMA_HI_LE(cqe_pbl_addr);
+ p_ramrod->cqe_pbl_addr.lo = DMA_LO_LE(cqe_pbl_addr);
+
+ rc = qed_spq_post(p_hwfn, p_ent, NULL);
+
+ return rc;
+}
+
+static int
+qed_sp_eth_rx_queue_start(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_queue_start_common_params *params,
+ u16 bd_max_bytes,
+ dma_addr_t bd_chain_phys_addr,
+ dma_addr_t cqe_pbl_addr,
+ u16 cqe_pbl_size,
+ void __iomem **pp_prod)
+{
+ struct qed_hw_cid_data *p_rx_cid;
+ u64 init_prod_val = 0;
+ u16 abs_l2_queue = 0;
+ u8 abs_stats_id = 0;
+ int rc;
+
+ rc = qed_fw_l2_queue(p_hwfn, params->queue_id, &abs_l2_queue);
+ if (rc != 0)
+ return rc;
+
+ rc = qed_fw_vport(p_hwfn, params->vport_id, &abs_stats_id);
+ if (rc != 0)
+ return rc;
+
+ *pp_prod = (u8 __iomem *)p_hwfn->regview +
+ GTT_BAR0_MAP_REG_MSDM_RAM +
+ MSTORM_PRODS_OFFSET(abs_l2_queue);
+
+ /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
+ __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u64),
+ (u32 *)(&init_prod_val));
+
+ /* Allocate a CID for the queue */
+ p_rx_cid = &p_hwfn->p_rx_cids[params->queue_id];
+ rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH,
+ &p_rx_cid->cid);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to acquire cid\n");
+ return rc;
+ }
+ p_rx_cid->b_cid_allocated = true;
+
+ rc = qed_sp_eth_rxq_start_ramrod(p_hwfn,
+ opaque_fid,
+ p_rx_cid->cid,
+ params,
+ abs_stats_id,
+ bd_max_bytes,
+ bd_chain_phys_addr,
+ cqe_pbl_addr,
+ cqe_pbl_size);
+
+ if (rc != 0)
+ qed_sp_release_queue_cid(p_hwfn, p_rx_cid);
+
+ return rc;
+}
+
+static int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
+ u16 rx_queue_id,
+ bool eq_completion_only,
+ bool cqe_completion)
+{
+ struct qed_hw_cid_data *p_rx_cid = &p_hwfn->p_rx_cids[rx_queue_id];
+ struct rx_queue_stop_ramrod_data *p_ramrod = NULL;
+ struct qed_sp_init_request_params sp_params;
+ struct qed_spq_entry *p_ent = NULL;
+ u16 abs_rx_q_id = 0;
+ int rc = -EINVAL;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(*p_ramrod);
+ sp_params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ p_rx_cid->cid,
+ p_rx_cid->opaque_fid,
+ ETH_RAMROD_RX_QUEUE_STOP,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.rx_queue_stop;
+
+ qed_fw_vport(p_hwfn, p_rx_cid->vport_id, &p_ramrod->vport_id);
+ qed_fw_l2_queue(p_hwfn, rx_queue_id, &abs_rx_q_id);
+ p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id);
+
+ /* Cleaning the queue requires the completion to arrive there.
+ * In addition, VFs require the answer to come as eqe to PF.
+ */
+ p_ramrod->complete_cqe_flg =
+ (!!(p_rx_cid->opaque_fid == p_hwfn->hw_info.opaque_fid) &&
+ !eq_completion_only) || cqe_completion;
+ p_ramrod->complete_event_flg =
+ !(p_rx_cid->opaque_fid == p_hwfn->hw_info.opaque_fid) ||
+ eq_completion_only;
+
+ rc = qed_spq_post(p_hwfn, p_ent, NULL);
+ if (rc)
+ return rc;
+
+ return qed_sp_release_queue_cid(p_hwfn, p_rx_cid);
+}
+
+static int
+qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ u32 cid,
+ struct qed_queue_start_common_params *p_params,
+ u8 stats_id,
+ dma_addr_t pbl_addr,
+ u16 pbl_size,
+ union qed_qm_pq_params *p_pq_params)
+{
+ struct tx_queue_start_ramrod_data *p_ramrod = NULL;
+ struct qed_sp_init_request_params sp_params;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_hw_cid_data *p_tx_cid;
+ u8 abs_vport_id;
+ int rc = -EINVAL;
+ u16 pq_id;
+
+ /* Store information for the stop */
+ p_tx_cid = &p_hwfn->p_tx_cids[p_params->queue_id];
+ p_tx_cid->cid = cid;
+ p_tx_cid->opaque_fid = opaque_fid;
+
+ rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
+ if (rc)
+ return rc;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(*p_ramrod);
+ sp_params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent, cid,
+ opaque_fid,
+ ETH_RAMROD_TX_QUEUE_START,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.tx_queue_start;
+ p_ramrod->vport_id = abs_vport_id;
+
+ p_ramrod->sb_id = cpu_to_le16(p_params->sb);
+ p_ramrod->sb_index = p_params->sb_idx;
+ p_ramrod->stats_counter_id = stats_id;
+ p_ramrod->tc = p_pq_params->eth.tc;
+
+ p_ramrod->pbl_size = cpu_to_le16(pbl_size);
+ p_ramrod->pbl_base_addr.hi = DMA_HI_LE(pbl_addr);
+ p_ramrod->pbl_base_addr.lo = DMA_LO_LE(pbl_addr);
+
+ pq_id = qed_get_qm_pq(p_hwfn,
+ PROTOCOLID_ETH,
+ p_pq_params);
+ p_ramrod->qm_pq_id = cpu_to_le16(pq_id);
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int
+qed_sp_eth_tx_queue_start(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_queue_start_common_params *p_params,
+ dma_addr_t pbl_addr,
+ u16 pbl_size,
+ void __iomem **pp_doorbell)
+{
+ struct qed_hw_cid_data *p_tx_cid;
+ union qed_qm_pq_params pq_params;
+ u8 abs_stats_id = 0;
+ int rc;
+
+ rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_stats_id);
+ if (rc)
+ return rc;
+
+ p_tx_cid = &p_hwfn->p_tx_cids[p_params->queue_id];
+ memset(p_tx_cid, 0, sizeof(*p_tx_cid));
+ memset(&pq_params, 0, sizeof(pq_params));
+
+ /* Allocate a CID for the queue */
+ rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH,
+ &p_tx_cid->cid);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Failed to acquire cid\n");
+ return rc;
+ }
+ p_tx_cid->b_cid_allocated = true;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "opaque_fid=0x%x, cid=0x%x, tx_qid=0x%x, vport_id=0x%x, sb_id=0x%x\n",
+ opaque_fid, p_tx_cid->cid,
+ p_params->queue_id, p_params->vport_id, p_params->sb);
+
+ rc = qed_sp_eth_txq_start_ramrod(p_hwfn,
+ opaque_fid,
+ p_tx_cid->cid,
+ p_params,
+ abs_stats_id,
+ pbl_addr,
+ pbl_size,
+ &pq_params);
+
+ *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
+ qed_db_addr(p_tx_cid->cid, DQ_DEMS_LEGACY);
+
+ if (rc)
+ qed_sp_release_queue_cid(p_hwfn, p_tx_cid);
+
+ return rc;
+}
+
+static int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn,
+ u16 tx_queue_id)
+{
+ struct qed_hw_cid_data *p_tx_cid = &p_hwfn->p_tx_cids[tx_queue_id];
+ struct qed_sp_init_request_params sp_params;
+ struct qed_spq_entry *p_ent = NULL;
+ int rc = -EINVAL;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(struct tx_queue_stop_ramrod_data);
+ sp_params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ p_tx_cid->cid,
+ p_tx_cid->opaque_fid,
+ ETH_RAMROD_TX_QUEUE_STOP,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ rc = qed_spq_post(p_hwfn, p_ent, NULL);
+ if (rc)
+ return rc;
+
+ return qed_sp_release_queue_cid(p_hwfn, p_tx_cid);
+}
+
+static enum eth_filter_action
+qed_filter_action(enum qed_filter_opcode opcode)
+{
+ enum eth_filter_action action = MAX_ETH_FILTER_ACTION;
+
+ switch (opcode) {
+ case QED_FILTER_ADD:
+ action = ETH_FILTER_ACTION_ADD;
+ break;
+ case QED_FILTER_REMOVE:
+ action = ETH_FILTER_ACTION_REMOVE;
+ break;
+ case QED_FILTER_REPLACE:
+ case QED_FILTER_FLUSH:
+ action = ETH_FILTER_ACTION_REPLACE;
+ break;
+ default:
+ action = MAX_ETH_FILTER_ACTION;
+ }
+
+ return action;
+}
+
+static void qed_set_fw_mac_addr(__le16 *fw_msb,
+ __le16 *fw_mid,
+ __le16 *fw_lsb,
+ u8 *mac)
+{
+ ((u8 *)fw_msb)[0] = mac[1];
+ ((u8 *)fw_msb)[1] = mac[0];
+ ((u8 *)fw_mid)[0] = mac[3];
+ ((u8 *)fw_mid)[1] = mac[2];
+ ((u8 *)fw_lsb)[0] = mac[5];
+ ((u8 *)fw_lsb)[1] = mac[4];
+}
+
+static int
+qed_filter_ucast_common(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_filter_ucast *p_filter_cmd,
+ struct vport_filter_update_ramrod_data **pp_ramrod,
+ struct qed_spq_entry **pp_ent,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ u8 vport_to_add_to = 0, vport_to_remove_from = 0;
+ struct vport_filter_update_ramrod_data *p_ramrod;
+ struct qed_sp_init_request_params sp_params;
+ struct eth_filter_cmd *p_first_filter;
+ struct eth_filter_cmd *p_second_filter;
+ enum eth_filter_action action;
+ int rc;
+
+ rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_remove_from,
+ &vport_to_remove_from);
+ if (rc)
+ return rc;
+
+ rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to,
+ &vport_to_add_to);
+ if (rc)
+ return rc;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(**pp_ramrod);
+ sp_params.comp_mode = comp_mode;
+ sp_params.p_comp_data = p_comp_data;
+
+ rc = qed_sp_init_request(p_hwfn, pp_ent,
+ qed_spq_get_cid(p_hwfn),
+ opaque_fid,
+ ETH_RAMROD_FILTERS_UPDATE,
+ PROTOCOLID_ETH,
+ &sp_params);
+ if (rc)
+ return rc;
+
+ *pp_ramrod = &(*pp_ent)->ramrod.vport_filter_update;
+ p_ramrod = *pp_ramrod;
+ p_ramrod->filter_cmd_hdr.rx = p_filter_cmd->is_rx_filter ? 1 : 0;
+ p_ramrod->filter_cmd_hdr.tx = p_filter_cmd->is_tx_filter ? 1 : 0;
+
+ switch (p_filter_cmd->opcode) {
+ case QED_FILTER_FLUSH:
+ p_ramrod->filter_cmd_hdr.cmd_cnt = 0; break;
+ case QED_FILTER_MOVE:
+ p_ramrod->filter_cmd_hdr.cmd_cnt = 2; break;
+ default:
+ p_ramrod->filter_cmd_hdr.cmd_cnt = 1; break;
+ }
+
+ p_first_filter = &p_ramrod->filter_cmds[0];
+ p_second_filter = &p_ramrod->filter_cmds[1];
+
+ switch (p_filter_cmd->type) {
+ case QED_FILTER_MAC:
+ p_first_filter->type = ETH_FILTER_TYPE_MAC; break;
+ case QED_FILTER_VLAN:
+ p_first_filter->type = ETH_FILTER_TYPE_VLAN; break;
+ case QED_FILTER_MAC_VLAN:
+ p_first_filter->type = ETH_FILTER_TYPE_PAIR; break;
+ case QED_FILTER_INNER_MAC:
+ p_first_filter->type = ETH_FILTER_TYPE_INNER_MAC; break;
+ case QED_FILTER_INNER_VLAN:
+ p_first_filter->type = ETH_FILTER_TYPE_INNER_VLAN; break;
+ case QED_FILTER_INNER_PAIR:
+ p_first_filter->type = ETH_FILTER_TYPE_INNER_PAIR; break;
+ case QED_FILTER_INNER_MAC_VNI_PAIR:
+ p_first_filter->type = ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR;
+ break;
+ case QED_FILTER_MAC_VNI_PAIR:
+ p_first_filter->type = ETH_FILTER_TYPE_MAC_VNI_PAIR; break;
+ case QED_FILTER_VNI:
+ p_first_filter->type = ETH_FILTER_TYPE_VNI; break;
+ }
+
+ if ((p_first_filter->type == ETH_FILTER_TYPE_MAC) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_PAIR) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_INNER_PAIR) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_MAC_VNI_PAIR)) {
+ qed_set_fw_mac_addr(&p_first_filter->mac_msb,
+ &p_first_filter->mac_mid,
+ &p_first_filter->mac_lsb,
+ (u8 *)p_filter_cmd->mac);
+ }
+
+ if ((p_first_filter->type == ETH_FILTER_TYPE_VLAN) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_PAIR) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_INNER_VLAN) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_INNER_PAIR))
+ p_first_filter->vlan_id = cpu_to_le16(p_filter_cmd->vlan);
+
+ if ((p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_MAC_VNI_PAIR) ||
+ (p_first_filter->type == ETH_FILTER_TYPE_VNI))
+ p_first_filter->vni = cpu_to_le32(p_filter_cmd->vni);
+
+ if (p_filter_cmd->opcode == QED_FILTER_MOVE) {
+ p_second_filter->type = p_first_filter->type;
+ p_second_filter->mac_msb = p_first_filter->mac_msb;
+ p_second_filter->mac_mid = p_first_filter->mac_mid;
+ p_second_filter->mac_lsb = p_first_filter->mac_lsb;
+ p_second_filter->vlan_id = p_first_filter->vlan_id;
+ p_second_filter->vni = p_first_filter->vni;
+
+ p_first_filter->action = ETH_FILTER_ACTION_REMOVE;
+
+ p_first_filter->vport_id = vport_to_remove_from;
+
+ p_second_filter->action = ETH_FILTER_ACTION_ADD;
+ p_second_filter->vport_id = vport_to_add_to;
+ } else {
+ action = qed_filter_action(p_filter_cmd->opcode);
+
+ if (action == MAX_ETH_FILTER_ACTION) {
+ DP_NOTICE(p_hwfn,
+ "%d is not supported yet\n",
+ p_filter_cmd->opcode);
+ return -EINVAL;
+ }
+
+ p_first_filter->action = action;
+ p_first_filter->vport_id = (p_filter_cmd->opcode ==
+ QED_FILTER_REMOVE) ?
+ vport_to_remove_from :
+ vport_to_add_to;
+ }
+
+ return 0;
+}
+
+static int qed_sp_eth_filter_ucast(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_filter_ucast *p_filter_cmd,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ struct vport_filter_update_ramrod_data *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct eth_filter_cmd_header *p_header;
+ int rc;
+
+ rc = qed_filter_ucast_common(p_hwfn, opaque_fid, p_filter_cmd,
+ &p_ramrod, &p_ent,
+ comp_mode, p_comp_data);
+ if (rc != 0) {
+ DP_ERR(p_hwfn, "Uni. filter command failed %d\n", rc);
+ return rc;
+ }
+ p_header = &p_ramrod->filter_cmd_hdr;
+ p_header->assert_on_error = p_filter_cmd->assert_on_error;
+
+ rc = qed_spq_post(p_hwfn, p_ent, NULL);
+ if (rc != 0) {
+ DP_ERR(p_hwfn,
+ "Unicast filter ADD command failed %d\n",
+ rc);
+ return rc;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "Unicast filter configured, opcode = %s, type = %s, cmd_cnt = %d, is_rx_filter = %d, is_tx_filter = %d\n",
+ (p_filter_cmd->opcode == QED_FILTER_ADD) ? "ADD" :
+ ((p_filter_cmd->opcode == QED_FILTER_REMOVE) ?
+ "REMOVE" :
+ ((p_filter_cmd->opcode == QED_FILTER_MOVE) ?
+ "MOVE" : "REPLACE")),
+ (p_filter_cmd->type == QED_FILTER_MAC) ? "MAC" :
+ ((p_filter_cmd->type == QED_FILTER_VLAN) ?
+ "VLAN" : "MAC & VLAN"),
+ p_ramrod->filter_cmd_hdr.cmd_cnt,
+ p_filter_cmd->is_rx_filter,
+ p_filter_cmd->is_tx_filter);
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "vport_to_add_to = %d, vport_to_remove_from = %d, mac = %2x:%2x:%2x:%2x:%2x:%2x, vlan = %d\n",
+ p_filter_cmd->vport_to_add_to,
+ p_filter_cmd->vport_to_remove_from,
+ p_filter_cmd->mac[0],
+ p_filter_cmd->mac[1],
+ p_filter_cmd->mac[2],
+ p_filter_cmd->mac[3],
+ p_filter_cmd->mac[4],
+ p_filter_cmd->mac[5],
+ p_filter_cmd->vlan);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Description:
+ * Calculates crc 32 on a buffer
+ * Note: crc32_length MUST be aligned to 8
+ * Return:
+ ******************************************************************************/
+static u32 qed_calc_crc32c(u8 *crc32_packet,
+ u32 crc32_length,
+ u32 crc32_seed,
+ u8 complement)
+{
+ u32 byte = 0;
+ u32 bit = 0;
+ u8 msb = 0;
+ u8 current_byte = 0;
+ u32 crc32_result = crc32_seed;
+
+ if ((!crc32_packet) ||
+ (crc32_length == 0) ||
+ ((crc32_length % 8) != 0))
+ return crc32_result;
+ for (byte = 0; byte < crc32_length; byte++) {
+ current_byte = crc32_packet[byte];
+ for (bit = 0; bit < 8; bit++) {
+ msb = (u8)(crc32_result >> 31);
+ crc32_result = crc32_result << 1;
+ if (msb != (0x1 & (current_byte >> bit))) {
+ crc32_result = crc32_result ^ CRC32_POLY;
+ crc32_result |= 1; /*crc32_result[0] = 1;*/
+ }
+ }
+ }
+ return crc32_result;
+}
+
+static inline u32 qed_crc32c_le(u32 seed,
+ u8 *mac,
+ u32 len)
+{
+ u32 packet_buf[2] = { 0 };
+
+ memcpy((u8 *)(&packet_buf[0]), &mac[0], 6);
+ return qed_calc_crc32c((u8 *)packet_buf, 8, seed, 0);
+}
+
+static u8 qed_mcast_bin_from_mac(u8 *mac)
+{
+ u32 crc = qed_crc32c_le(ETH_MULTICAST_BIN_FROM_MAC_SEED,
+ mac, ETH_ALEN);
+
+ return crc & 0xff;
+}
+
+static int
+qed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_filter_mcast *p_filter_cmd,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ unsigned long bins[ETH_MULTICAST_MAC_BINS_IN_REGS];
+ struct vport_update_ramrod_data *p_ramrod = NULL;
+ struct qed_sp_init_request_params sp_params;
+ struct qed_spq_entry *p_ent = NULL;
+ u8 abs_vport_id = 0;
+ int rc, i;
+
+ if (p_filter_cmd->opcode == QED_FILTER_ADD) {
+ rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to,
+ &abs_vport_id);
+ if (rc)
+ return rc;
+ } else {
+ rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_remove_from,
+ &abs_vport_id);
+ if (rc)
+ return rc;
+ }
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ sp_params.ramrod_data_size = sizeof(*p_ramrod);
+ sp_params.comp_mode = comp_mode;
+ sp_params.p_comp_data = p_comp_data;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ qed_spq_get_cid(p_hwfn),
+ p_hwfn->hw_info.opaque_fid,
+ ETH_RAMROD_VPORT_UPDATE,
+ PROTOCOLID_ETH,
+ &sp_params);
+
+ if (rc) {
+ DP_ERR(p_hwfn, "Multi-cast command failed %d\n", rc);
+ return rc;
+ }
+
+ p_ramrod = &p_ent->ramrod.vport_update;
+ p_ramrod->common.update_approx_mcast_flg = 1;
+
+ /* explicitly clear out the entire vector */
+ memset(&p_ramrod->approx_mcast.bins, 0,
+ sizeof(p_ramrod->approx_mcast.bins));
+ memset(bins, 0, sizeof(unsigned long) *
+ ETH_MULTICAST_MAC_BINS_IN_REGS);
+ /* filter ADD op is explicit set op and it removes
+ * any existing filters for the vport
+ */
+ if (p_filter_cmd->opcode == QED_FILTER_ADD) {
+ for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) {
+ u32 bit;
+
+ bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]);
+ __set_bit(bit, bins);
+ }
+
+ /* Convert to correct endianity */
+ for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) {
+ u32 *p_bins = (u32 *)bins;
+ struct vport_update_ramrod_mcast *approx_mcast;
+
+ approx_mcast = &p_ramrod->approx_mcast;
+ approx_mcast->bins[i] = cpu_to_le32(p_bins[i]);
+ }
+ }
+
+ p_ramrod->common.vport_id = abs_vport_id;
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int
+qed_filter_mcast_cmd(struct qed_dev *cdev,
+ struct qed_filter_mcast *p_filter_cmd,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ int rc = 0;
+ int i;
+
+ /* only ADD and REMOVE operations are supported for multi-cast */
+ if ((p_filter_cmd->opcode != QED_FILTER_ADD &&
+ (p_filter_cmd->opcode != QED_FILTER_REMOVE)) ||
+ (p_filter_cmd->num_mc_addrs > QED_MAX_MC_ADDRS))
+ return -EINVAL;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ u16 opaque_fid;
+
+ if (rc != 0)
+ break;
+
+ opaque_fid = p_hwfn->hw_info.opaque_fid;
+
+ rc = qed_sp_eth_filter_mcast(p_hwfn,
+ opaque_fid,
+ p_filter_cmd,
+ comp_mode,
+ p_comp_data);
+ }
+ return rc;
+}
+
+static int qed_filter_ucast_cmd(struct qed_dev *cdev,
+ struct qed_filter_ucast *p_filter_cmd,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_data)
+{
+ int rc = 0;
+ int i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ u16 opaque_fid;
+
+ if (rc != 0)
+ break;
+
+ opaque_fid = p_hwfn->hw_info.opaque_fid;
+
+ rc = qed_sp_eth_filter_ucast(p_hwfn,
+ opaque_fid,
+ p_filter_cmd,
+ comp_mode,
+ p_comp_data);
+ }
+
+ return rc;
+}
+
+static int qed_fill_eth_dev_info(struct qed_dev *cdev,
+ struct qed_dev_eth_info *info)
+{
+ int i;
+
+ memset(info, 0, sizeof(*info));
+
+ info->num_tc = 1;
+
+ if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
+ for_each_hwfn(cdev, i)
+ info->num_queues += FEAT_NUM(&cdev->hwfns[i],
+ QED_PF_L2_QUE);
+ if (cdev->int_params.fp_msix_cnt)
+ info->num_queues = min_t(u8, info->num_queues,
+ cdev->int_params.fp_msix_cnt);
+ } else {
+ info->num_queues = cdev->num_hwfns;
+ }
+
+ info->num_vlan_filters = RESC_NUM(&cdev->hwfns[0], QED_VLAN);
+ ether_addr_copy(info->port_mac,
+ cdev->hwfns[0].hw_info.hw_mac_addr);
+
+ qed_fill_dev_info(cdev, &info->common);
+
+ return 0;
+}
+
+static void qed_register_eth_ops(struct qed_dev *cdev,
+ struct qed_eth_cb_ops *ops,
+ void *cookie)
+{
+ cdev->protocol_ops.eth = ops;
+ cdev->ops_cookie = cookie;
+}
+
+static int qed_start_vport(struct qed_dev *cdev,
+ u8 vport_id,
+ u16 mtu,
+ u8 drop_ttl0_flg,
+ u8 inner_vlan_removal_en_flg)
+{
+ int rc, i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ rc = qed_sp_vport_start(p_hwfn,
+ p_hwfn->hw_info.concrete_fid,
+ p_hwfn->hw_info.opaque_fid,
+ vport_id,
+ mtu,
+ drop_ttl0_flg,
+ inner_vlan_removal_en_flg);
+
+ if (rc) {
+ DP_ERR(cdev, "Failed to start VPORT\n");
+ return rc;
+ }
+
+ qed_hw_start_fastpath(p_hwfn);
+
+ DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
+ "Started V-PORT %d with MTU %d\n",
+ vport_id, mtu);
+ }
+
+ qed_reset_vport_stats(cdev);
+
+ return 0;
+}
+
+static int qed_stop_vport(struct qed_dev *cdev,
+ u8 vport_id)
+{
+ int rc, i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ rc = qed_sp_vport_stop(p_hwfn,
+ p_hwfn->hw_info.opaque_fid,
+ vport_id);
+
+ if (rc) {
+ DP_ERR(cdev, "Failed to stop VPORT\n");
+ return rc;
+ }
+ }
+ return 0;
+}
+
+static int qed_update_vport(struct qed_dev *cdev,
+ struct qed_update_vport_params *params)
+{
+ struct qed_sp_vport_update_params sp_params;
+ struct qed_rss_params sp_rss_params;
+ int rc, i;
+
+ if (!cdev)
+ return -ENODEV;
+
+ memset(&sp_params, 0, sizeof(sp_params));
+ memset(&sp_rss_params, 0, sizeof(sp_rss_params));
+
+ /* Translate protocol params into sp params */
+ sp_params.vport_id = params->vport_id;
+ sp_params.update_vport_active_rx_flg =
+ params->update_vport_active_flg;
+ sp_params.update_vport_active_tx_flg =
+ params->update_vport_active_flg;
+ sp_params.vport_active_rx_flg = params->vport_active_flg;
+ sp_params.vport_active_tx_flg = params->vport_active_flg;
+
+ /* RSS - is a bit tricky, since upper-layer isn't familiar with hwfns.
+ * We need to re-fix the rss values per engine for CMT.
+ */
+ if (cdev->num_hwfns > 1 && params->update_rss_flg) {
+ struct qed_update_vport_rss_params *rss =
+ &params->rss_params;
+ int k, max = 0;
+
+ /* Find largest entry, since it's possible RSS needs to
+ * be disabled [in case only 1 queue per-hwfn]
+ */
+ for (k = 0; k < QED_RSS_IND_TABLE_SIZE; k++)
+ max = (max > rss->rss_ind_table[k]) ?
+ max : rss->rss_ind_table[k];
+
+ /* Either fix RSS values or disable RSS */
+ if (cdev->num_hwfns < max + 1) {
+ int divisor = (max + cdev->num_hwfns - 1) /
+ cdev->num_hwfns;
+
+ DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
+ "CMT - fixing RSS values (modulo %02x)\n",
+ divisor);
+
+ for (k = 0; k < QED_RSS_IND_TABLE_SIZE; k++)
+ rss->rss_ind_table[k] =
+ rss->rss_ind_table[k] % divisor;
+ } else {
+ DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
+ "CMT - 1 queue per-hwfn; Disabling RSS\n");
+ params->update_rss_flg = 0;
+ }
+ }
+
+ /* Now, update the RSS configuration for actual configuration */
+ if (params->update_rss_flg) {
+ sp_rss_params.update_rss_config = 1;
+ sp_rss_params.rss_enable = 1;
+ sp_rss_params.update_rss_capabilities = 1;
+ sp_rss_params.update_rss_ind_table = 1;
+ sp_rss_params.update_rss_key = 1;
+ sp_rss_params.rss_caps = QED_RSS_IPV4 |
+ QED_RSS_IPV6 |
+ QED_RSS_IPV4_TCP | QED_RSS_IPV6_TCP;
+ sp_rss_params.rss_table_size_log = 7; /* 2^7 = 128 */
+ memcpy(sp_rss_params.rss_ind_table,
+ params->rss_params.rss_ind_table,
+ QED_RSS_IND_TABLE_SIZE * sizeof(u16));
+ memcpy(sp_rss_params.rss_key, params->rss_params.rss_key,
+ QED_RSS_KEY_SIZE * sizeof(u32));
+ }
+ sp_params.rss_params = &sp_rss_params;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ sp_params.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ rc = qed_sp_vport_update(p_hwfn, &sp_params,
+ QED_SPQ_MODE_EBLOCK,
+ NULL);
+ if (rc) {
+ DP_ERR(cdev, "Failed to update VPORT\n");
+ return rc;
+ }
+
+ DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
+ "Updated V-PORT %d: active_flag %d [update %d]\n",
+ params->vport_id, params->vport_active_flg,
+ params->update_vport_active_flg);
+ }
+
+ return 0;
+}
+
+static int qed_start_rxq(struct qed_dev *cdev,
+ struct qed_queue_start_common_params *params,
+ u16 bd_max_bytes,
+ dma_addr_t bd_chain_phys_addr,
+ dma_addr_t cqe_pbl_addr,
+ u16 cqe_pbl_size,
+ void __iomem **pp_prod)
+{
+ int rc, hwfn_index;
+ struct qed_hwfn *p_hwfn;
+
+ hwfn_index = params->rss_id % cdev->num_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+
+ /* Fix queue ID in 100g mode */
+ params->queue_id /= cdev->num_hwfns;
+
+ rc = qed_sp_eth_rx_queue_start(p_hwfn,
+ p_hwfn->hw_info.opaque_fid,
+ params,
+ bd_max_bytes,
+ bd_chain_phys_addr,
+ cqe_pbl_addr,
+ cqe_pbl_size,
+ pp_prod);
+
+ if (rc) {
+ DP_ERR(cdev, "Failed to start RXQ#%d\n", params->queue_id);
+ return rc;
+ }
+
+ DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
+ "Started RX-Q %d [rss %d] on V-PORT %d and SB %d\n",
+ params->queue_id, params->rss_id, params->vport_id,
+ params->sb);
+
+ return 0;
+}
+
+static int qed_stop_rxq(struct qed_dev *cdev,
+ struct qed_stop_rxq_params *params)
+{
+ int rc, hwfn_index;
+ struct qed_hwfn *p_hwfn;
+
+ hwfn_index = params->rss_id % cdev->num_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+
+ rc = qed_sp_eth_rx_queue_stop(p_hwfn,
+ params->rx_queue_id / cdev->num_hwfns,
+ params->eq_completion_only,
+ false);
+ if (rc) {
+ DP_ERR(cdev, "Failed to stop RXQ#%d\n", params->rx_queue_id);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int qed_start_txq(struct qed_dev *cdev,
+ struct qed_queue_start_common_params *p_params,
+ dma_addr_t pbl_addr,
+ u16 pbl_size,
+ void __iomem **pp_doorbell)
+{
+ struct qed_hwfn *p_hwfn;
+ int rc, hwfn_index;
+
+ hwfn_index = p_params->rss_id % cdev->num_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+
+ /* Fix queue ID in 100g mode */
+ p_params->queue_id /= cdev->num_hwfns;
+
+ rc = qed_sp_eth_tx_queue_start(p_hwfn,
+ p_hwfn->hw_info.opaque_fid,
+ p_params,
+ pbl_addr,
+ pbl_size,
+ pp_doorbell);
+
+ if (rc) {
+ DP_ERR(cdev, "Failed to start TXQ#%d\n", p_params->queue_id);
+ return rc;
+ }
+
+ DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
+ "Started TX-Q %d [rss %d] on V-PORT %d and SB %d\n",
+ p_params->queue_id, p_params->rss_id, p_params->vport_id,
+ p_params->sb);
+
+ return 0;
+}
+
+#define QED_HW_STOP_RETRY_LIMIT (10)
+static int qed_fastpath_stop(struct qed_dev *cdev)
+{
+ qed_hw_stop_fastpath(cdev);
+
+ return 0;
+}
+
+static int qed_stop_txq(struct qed_dev *cdev,
+ struct qed_stop_txq_params *params)
+{
+ struct qed_hwfn *p_hwfn;
+ int rc, hwfn_index;
+
+ hwfn_index = params->rss_id % cdev->num_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+
+ rc = qed_sp_eth_tx_queue_stop(p_hwfn,
+ params->tx_queue_id / cdev->num_hwfns);
+ if (rc) {
+ DP_ERR(cdev, "Failed to stop TXQ#%d\n", params->tx_queue_id);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int qed_configure_filter_rx_mode(struct qed_dev *cdev,
+ enum qed_filter_rx_mode_type type)
+{
+ struct qed_filter_accept_flags accept_flags;
+
+ memset(&accept_flags, 0, sizeof(accept_flags));
+
+ accept_flags.update_rx_mode_config = 1;
+ accept_flags.update_tx_mode_config = 1;
+ accept_flags.rx_accept_filter = QED_ACCEPT_UCAST_MATCHED |
+ QED_ACCEPT_MCAST_MATCHED |
+ QED_ACCEPT_BCAST;
+ accept_flags.tx_accept_filter = QED_ACCEPT_UCAST_MATCHED |
+ QED_ACCEPT_MCAST_MATCHED |
+ QED_ACCEPT_BCAST;
+
+ if (type == QED_FILTER_RX_MODE_TYPE_PROMISC)
+ accept_flags.rx_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;
+
+ return qed_filter_accept_cmd(cdev, 0, accept_flags,
+ QED_SPQ_MODE_CB, NULL);
+}
+
+static int qed_configure_filter_ucast(struct qed_dev *cdev,
+ struct qed_filter_ucast_params *params)
+{
+ struct qed_filter_ucast ucast;
+
+ if (!params->vlan_valid && !params->mac_valid) {
+ DP_NOTICE(
+ cdev,
+ "Tried configuring a unicast filter, but both MAC and VLAN are not set\n");
+ return -EINVAL;
+ }
+
+ memset(&ucast, 0, sizeof(ucast));
+ switch (params->type) {
+ case QED_FILTER_XCAST_TYPE_ADD:
+ ucast.opcode = QED_FILTER_ADD;
+ break;
+ case QED_FILTER_XCAST_TYPE_DEL:
+ ucast.opcode = QED_FILTER_REMOVE;
+ break;
+ case QED_FILTER_XCAST_TYPE_REPLACE:
+ ucast.opcode = QED_FILTER_REPLACE;
+ break;
+ default:
+ DP_NOTICE(cdev, "Unknown unicast filter type %d\n",
+ params->type);
+ }
+
+ if (params->vlan_valid && params->mac_valid) {
+ ucast.type = QED_FILTER_MAC_VLAN;
+ ether_addr_copy(ucast.mac, params->mac);
+ ucast.vlan = params->vlan;
+ } else if (params->mac_valid) {
+ ucast.type = QED_FILTER_MAC;
+ ether_addr_copy(ucast.mac, params->mac);
+ } else {
+ ucast.type = QED_FILTER_VLAN;
+ ucast.vlan = params->vlan;
+ }
+
+ ucast.is_rx_filter = true;
+ ucast.is_tx_filter = true;
+
+ return qed_filter_ucast_cmd(cdev, &ucast, QED_SPQ_MODE_CB, NULL);
+}
+
+static int qed_configure_filter_mcast(struct qed_dev *cdev,
+ struct qed_filter_mcast_params *params)
+{
+ struct qed_filter_mcast mcast;
+ int i;
+
+ memset(&mcast, 0, sizeof(mcast));
+ switch (params->type) {
+ case QED_FILTER_XCAST_TYPE_ADD:
+ mcast.opcode = QED_FILTER_ADD;
+ break;
+ case QED_FILTER_XCAST_TYPE_DEL:
+ mcast.opcode = QED_FILTER_REMOVE;
+ break;
+ default:
+ DP_NOTICE(cdev, "Unknown multicast filter type %d\n",
+ params->type);
+ }
+
+ mcast.num_mc_addrs = params->num;
+ for (i = 0; i < mcast.num_mc_addrs; i++)
+ ether_addr_copy(mcast.mac[i], params->mac[i]);
+
+ return qed_filter_mcast_cmd(cdev, &mcast,
+ QED_SPQ_MODE_CB, NULL);
+}
+
+static int qed_configure_filter(struct qed_dev *cdev,
+ struct qed_filter_params *params)
+{
+ enum qed_filter_rx_mode_type accept_flags;
+
+ switch (params->type) {
+ case QED_FILTER_TYPE_UCAST:
+ return qed_configure_filter_ucast(cdev, &params->filter.ucast);
+ case QED_FILTER_TYPE_MCAST:
+ return qed_configure_filter_mcast(cdev, &params->filter.mcast);
+ case QED_FILTER_TYPE_RX_MODE:
+ accept_flags = params->filter.accept_flags;
+ return qed_configure_filter_rx_mode(cdev, accept_flags);
+ default:
+ DP_NOTICE(cdev, "Unknown filter type %d\n",
+ (int)params->type);
+ return -EINVAL;
+ }
+}
+
+static int qed_fp_cqe_completion(struct qed_dev *dev,
+ u8 rss_id,
+ struct eth_slow_path_rx_cqe *cqe)
+{
+ return qed_eth_cqe_completion(&dev->hwfns[rss_id % dev->num_hwfns],
+ cqe);
+}
+
+static const struct qed_eth_ops qed_eth_ops_pass = {
+ .common = &qed_common_ops_pass,
+ .fill_dev_info = &qed_fill_eth_dev_info,
+ .register_ops = &qed_register_eth_ops,
+ .vport_start = &qed_start_vport,
+ .vport_stop = &qed_stop_vport,
+ .vport_update = &qed_update_vport,
+ .q_rx_start = &qed_start_rxq,
+ .q_rx_stop = &qed_stop_rxq,
+ .q_tx_start = &qed_start_txq,
+ .q_tx_stop = &qed_stop_txq,
+ .filter_config = &qed_configure_filter,
+ .fastpath_stop = &qed_fastpath_stop,
+ .eth_cqe_completion = &qed_fp_cqe_completion,
+ .get_vport_stats = &qed_get_vport_stats,
+};
+
+const struct qed_eth_ops *qed_get_eth_ops(u32 version)
+{
+ if (version != QED_ETH_INTERFACE_VERSION) {
+ pr_notice("Cannot supply ethtool operations [%08x != %08x]\n",
+ version, QED_ETH_INTERFACE_VERSION);
+ return NULL;
+ }
+
+ return &qed_eth_ops_pass;
+}
+EXPORT_SYMBOL(qed_get_eth_ops);
+
+void qed_put_eth_ops(void)
+{
+ /* TODO - reference count for module? */
+}
+EXPORT_SYMBOL(qed_put_eth_ops);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
new file mode 100644
index 000000000000..947c7af72b25
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -0,0 +1,1169 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/stddef.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/qed/qed_if.h>
+
+#include "qed.h"
+#include "qed_sp.h"
+#include "qed_dev_api.h"
+#include "qed_mcp.h"
+#include "qed_hw.h"
+
+static const char version[] =
+ "QLogic QL4xxx 40G/100G Ethernet Driver qed " DRV_MODULE_VERSION "\n";
+
+MODULE_DESCRIPTION("QLogic 25G/40G/50G/100G Core Module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define FW_FILE_VERSION \
+ __stringify(FW_MAJOR_VERSION) "." \
+ __stringify(FW_MINOR_VERSION) "." \
+ __stringify(FW_REVISION_VERSION) "." \
+ __stringify(FW_ENGINEERING_VERSION)
+
+#define QED_FW_FILE_NAME \
+ "qed/qed_init_values_zipped-" FW_FILE_VERSION ".bin"
+
+static int __init qed_init(void)
+{
+ pr_notice("qed_init called\n");
+
+ pr_info("%s", version);
+
+ return 0;
+}
+
+static void __exit qed_cleanup(void)
+{
+ pr_notice("qed_cleanup called\n");
+}
+
+module_init(qed_init);
+module_exit(qed_cleanup);
+
+/* Check if the DMA controller on the machine can properly handle the DMA
+ * addressing required by the device.
+*/
+static int qed_set_coherency_mask(struct qed_dev *cdev)
+{
+ struct device *dev = &cdev->pdev->dev;
+
+ if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
+ if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
+ DP_NOTICE(cdev,
+ "Can't request 64-bit consistent allocations\n");
+ return -EIO;
+ }
+ } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) {
+ DP_NOTICE(cdev, "Can't request 64b/32b DMA addresses\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void qed_free_pci(struct qed_dev *cdev)
+{
+ struct pci_dev *pdev = cdev->pdev;
+
+ if (cdev->doorbells)
+ iounmap(cdev->doorbells);
+ if (cdev->regview)
+ iounmap(cdev->regview);
+ if (atomic_read(&pdev->enable_cnt) == 1)
+ pci_release_regions(pdev);
+
+ pci_disable_device(pdev);
+}
+
+/* Performs PCI initializations as well as initializing PCI-related parameters
+ * in the device structrue. Returns 0 in case of success.
+ */
+static int qed_init_pci(struct qed_dev *cdev,
+ struct pci_dev *pdev)
+{
+ int rc;
+
+ cdev->pdev = pdev;
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ DP_NOTICE(cdev, "Cannot enable PCI device\n");
+ goto err0;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ DP_NOTICE(cdev, "No memory region found in bar #0\n");
+ rc = -EIO;
+ goto err1;
+ }
+
+ if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
+ DP_NOTICE(cdev, "No memory region found in bar #2\n");
+ rc = -EIO;
+ goto err1;
+ }
+
+ if (atomic_read(&pdev->enable_cnt) == 1) {
+ rc = pci_request_regions(pdev, "qed");
+ if (rc) {
+ DP_NOTICE(cdev,
+ "Failed to request PCI memory resources\n");
+ goto err1;
+ }
+ pci_set_master(pdev);
+ pci_save_state(pdev);
+ }
+
+ if (!pci_is_pcie(pdev)) {
+ DP_NOTICE(cdev, "The bus is not PCI Express\n");
+ rc = -EIO;
+ goto err2;
+ }
+
+ cdev->pci_params.pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (cdev->pci_params.pm_cap == 0)
+ DP_NOTICE(cdev, "Cannot find power management capability\n");
+
+ rc = qed_set_coherency_mask(cdev);
+ if (rc)
+ goto err2;
+
+ cdev->pci_params.mem_start = pci_resource_start(pdev, 0);
+ cdev->pci_params.mem_end = pci_resource_end(pdev, 0);
+ cdev->pci_params.irq = pdev->irq;
+
+ cdev->regview = pci_ioremap_bar(pdev, 0);
+ if (!cdev->regview) {
+ DP_NOTICE(cdev, "Cannot map register space, aborting\n");
+ rc = -ENOMEM;
+ goto err2;
+ }
+
+ cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2);
+ cdev->db_size = pci_resource_len(cdev->pdev, 2);
+ cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size);
+ if (!cdev->doorbells) {
+ DP_NOTICE(cdev, "Cannot map doorbell space\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+
+err2:
+ pci_release_regions(pdev);
+err1:
+ pci_disable_device(pdev);
+err0:
+ return rc;
+}
+
+int qed_fill_dev_info(struct qed_dev *cdev,
+ struct qed_dev_info *dev_info)
+{
+ struct qed_ptt *ptt;
+
+ memset(dev_info, 0, sizeof(struct qed_dev_info));
+
+ dev_info->num_hwfns = cdev->num_hwfns;
+ dev_info->pci_mem_start = cdev->pci_params.mem_start;
+ dev_info->pci_mem_end = cdev->pci_params.mem_end;
+ dev_info->pci_irq = cdev->pci_params.irq;
+ dev_info->is_mf = IS_MF(&cdev->hwfns[0]);
+ ether_addr_copy(dev_info->hw_mac, cdev->hwfns[0].hw_info.hw_mac_addr);
+
+ dev_info->fw_major = FW_MAJOR_VERSION;
+ dev_info->fw_minor = FW_MINOR_VERSION;
+ dev_info->fw_rev = FW_REVISION_VERSION;
+ dev_info->fw_eng = FW_ENGINEERING_VERSION;
+ dev_info->mf_mode = cdev->mf_mode;
+
+ qed_mcp_get_mfw_ver(cdev, &dev_info->mfw_rev);
+
+ ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
+ if (ptt) {
+ qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt,
+ &dev_info->flash_size);
+
+ qed_ptt_release(QED_LEADING_HWFN(cdev), ptt);
+ }
+
+ return 0;
+}
+
+static void qed_free_cdev(struct qed_dev *cdev)
+{
+ kfree((void *)cdev);
+}
+
+static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev)
+{
+ struct qed_dev *cdev;
+
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ if (!cdev)
+ return cdev;
+
+ qed_init_struct(cdev);
+
+ return cdev;
+}
+
+/* Sets the requested power state */
+static int qed_set_power_state(struct qed_dev *cdev,
+ pci_power_t state)
+{
+ if (!cdev)
+ return -ENODEV;
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n");
+ return 0;
+}
+
+/* probing */
+static struct qed_dev *qed_probe(struct pci_dev *pdev,
+ enum qed_protocol protocol,
+ u32 dp_module,
+ u8 dp_level)
+{
+ struct qed_dev *cdev;
+ int rc;
+
+ cdev = qed_alloc_cdev(pdev);
+ if (!cdev)
+ goto err0;
+
+ cdev->protocol = protocol;
+
+ qed_init_dp(cdev, dp_module, dp_level);
+
+ rc = qed_init_pci(cdev, pdev);
+ if (rc) {
+ DP_ERR(cdev, "init pci failed\n");
+ goto err1;
+ }
+ DP_INFO(cdev, "PCI init completed successfully\n");
+
+ rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT);
+ if (rc) {
+ DP_ERR(cdev, "hw prepare failed\n");
+ goto err2;
+ }
+
+ DP_INFO(cdev, "qed_probe completed successffuly\n");
+
+ return cdev;
+
+err2:
+ qed_free_pci(cdev);
+err1:
+ qed_free_cdev(cdev);
+err0:
+ return NULL;
+}
+
+static void qed_remove(struct qed_dev *cdev)
+{
+ if (!cdev)
+ return;
+
+ qed_hw_remove(cdev);
+
+ qed_free_pci(cdev);
+
+ qed_set_power_state(cdev, PCI_D3hot);
+
+ qed_free_cdev(cdev);
+}
+
+static void qed_disable_msix(struct qed_dev *cdev)
+{
+ if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
+ pci_disable_msix(cdev->pdev);
+ kfree(cdev->int_params.msix_table);
+ } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) {
+ pci_disable_msi(cdev->pdev);
+ }
+
+ memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param));
+}
+
+static int qed_enable_msix(struct qed_dev *cdev,
+ struct qed_int_params *int_params)
+{
+ int i, rc, cnt;
+
+ cnt = int_params->in.num_vectors;
+
+ for (i = 0; i < cnt; i++)
+ int_params->msix_table[i].entry = i;
+
+ rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table,
+ int_params->in.min_msix_cnt, cnt);
+ if (rc < cnt && rc >= int_params->in.min_msix_cnt &&
+ (rc % cdev->num_hwfns)) {
+ pci_disable_msix(cdev->pdev);
+
+ /* If fastpath is initialized, we need at least one interrupt
+ * per hwfn [and the slow path interrupts]. New requested number
+ * should be a multiple of the number of hwfns.
+ */
+ cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns;
+ DP_NOTICE(cdev,
+ "Trying to enable MSI-X with less vectors (%d out of %d)\n",
+ cnt, int_params->in.num_vectors);
+ rc = pci_enable_msix_exact(cdev->pdev,
+ int_params->msix_table, cnt);
+ if (!rc)
+ rc = cnt;
+ }
+
+ if (rc > 0) {
+ /* MSI-x configuration was achieved */
+ int_params->out.int_mode = QED_INT_MODE_MSIX;
+ int_params->out.num_vectors = rc;
+ rc = 0;
+ } else {
+ DP_NOTICE(cdev,
+ "Failed to enable MSI-X [Requested %d vectors][rc %d]\n",
+ cnt, rc);
+ }
+
+ return rc;
+}
+
+/* This function outputs the int mode and the number of enabled msix vector */
+static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode)
+{
+ struct qed_int_params *int_params = &cdev->int_params;
+ struct msix_entry *tbl;
+ int rc = 0, cnt;
+
+ switch (int_params->in.int_mode) {
+ case QED_INT_MODE_MSIX:
+ /* Allocate MSIX table */
+ cnt = int_params->in.num_vectors;
+ int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL);
+ if (!int_params->msix_table) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Enable MSIX */
+ rc = qed_enable_msix(cdev, int_params);
+ if (!rc)
+ goto out;
+
+ DP_NOTICE(cdev, "Failed to enable MSI-X\n");
+ kfree(int_params->msix_table);
+ if (force_mode)
+ goto out;
+ /* Fallthrough */
+
+ case QED_INT_MODE_MSI:
+ rc = pci_enable_msi(cdev->pdev);
+ if (!rc) {
+ int_params->out.int_mode = QED_INT_MODE_MSI;
+ goto out;
+ }
+
+ DP_NOTICE(cdev, "Failed to enable MSI\n");
+ if (force_mode)
+ goto out;
+ /* Fallthrough */
+
+ case QED_INT_MODE_INTA:
+ int_params->out.int_mode = QED_INT_MODE_INTA;
+ rc = 0;
+ goto out;
+ default:
+ DP_NOTICE(cdev, "Unknown int_mode value %d\n",
+ int_params->in.int_mode);
+ rc = -EINVAL;
+ }
+
+out:
+ cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE;
+
+ return rc;
+}
+
+static void qed_simd_handler_config(struct qed_dev *cdev, void *token,
+ int index, void(*handler)(void *))
+{
+ struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns];
+ int relative_idx = index / cdev->num_hwfns;
+
+ hwfn->simd_proto_handler[relative_idx].func = handler;
+ hwfn->simd_proto_handler[relative_idx].token = token;
+}
+
+static void qed_simd_handler_clean(struct qed_dev *cdev, int index)
+{
+ struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns];
+ int relative_idx = index / cdev->num_hwfns;
+
+ memset(&hwfn->simd_proto_handler[relative_idx], 0,
+ sizeof(struct qed_simd_fp_handler));
+}
+
+static irqreturn_t qed_msix_sp_int(int irq, void *tasklet)
+{
+ tasklet_schedule((struct tasklet_struct *)tasklet);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qed_single_int(int irq, void *dev_instance)
+{
+ struct qed_dev *cdev = (struct qed_dev *)dev_instance;
+ struct qed_hwfn *hwfn;
+ irqreturn_t rc = IRQ_NONE;
+ u64 status;
+ int i, j;
+
+ for (i = 0; i < cdev->num_hwfns; i++) {
+ status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]);
+
+ if (!status)
+ continue;
+
+ hwfn = &cdev->hwfns[i];
+
+ /* Slowpath interrupt */
+ if (unlikely(status & 0x1)) {
+ tasklet_schedule(hwfn->sp_dpc);
+ status &= ~0x1;
+ rc = IRQ_HANDLED;
+ }
+
+ /* Fastpath interrupts */
+ for (j = 0; j < 64; j++) {
+ if ((0x2ULL << j) & status) {
+ hwfn->simd_proto_handler[j].func(
+ hwfn->simd_proto_handler[j].token);
+ status &= ~(0x2ULL << j);
+ rc = IRQ_HANDLED;
+ }
+ }
+
+ if (unlikely(status))
+ DP_VERBOSE(hwfn, NETIF_MSG_INTR,
+ "got an unknown interrupt status 0x%llx\n",
+ status);
+ }
+
+ return rc;
+}
+
+static int qed_slowpath_irq_req(struct qed_dev *cdev)
+{
+ int i = 0, rc = 0;
+
+ if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
+ /* Request all the slowpath MSI-X vectors */
+ for (i = 0; i < cdev->num_hwfns; i++) {
+ snprintf(cdev->hwfns[i].name, NAME_SIZE,
+ "sp-%d-%02x:%02x.%02x",
+ i, cdev->pdev->bus->number,
+ PCI_SLOT(cdev->pdev->devfn),
+ cdev->hwfns[i].abs_pf_id);
+
+ rc = request_irq(cdev->int_params.msix_table[i].vector,
+ qed_msix_sp_int, 0,
+ cdev->hwfns[i].name,
+ cdev->hwfns[i].sp_dpc);
+ if (rc)
+ break;
+
+ DP_VERBOSE(&cdev->hwfns[i],
+ (NETIF_MSG_INTR | QED_MSG_SP),
+ "Requested slowpath MSI-X\n");
+ }
+
+ if (i != cdev->num_hwfns) {
+ /* Free already request MSI-X vectors */
+ for (i--; i >= 0; i--) {
+ unsigned int vec =
+ cdev->int_params.msix_table[i].vector;
+ synchronize_irq(vec);
+ free_irq(cdev->int_params.msix_table[i].vector,
+ cdev->hwfns[i].sp_dpc);
+ }
+ }
+ } else {
+ unsigned long flags = 0;
+
+ snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x",
+ cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn),
+ PCI_FUNC(cdev->pdev->devfn));
+
+ if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA)
+ flags |= IRQF_SHARED;
+
+ rc = request_irq(cdev->pdev->irq, qed_single_int,
+ flags, cdev->name, cdev);
+ }
+
+ return rc;
+}
+
+static void qed_slowpath_irq_free(struct qed_dev *cdev)
+{
+ int i;
+
+ if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
+ for_each_hwfn(cdev, i) {
+ synchronize_irq(cdev->int_params.msix_table[i].vector);
+ free_irq(cdev->int_params.msix_table[i].vector,
+ cdev->hwfns[i].sp_dpc);
+ }
+ } else {
+ free_irq(cdev->pdev->irq, cdev);
+ }
+}
+
+static int qed_nic_stop(struct qed_dev *cdev)
+{
+ int i, rc;
+
+ rc = qed_hw_stop(cdev);
+
+ for (i = 0; i < cdev->num_hwfns; i++) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ if (p_hwfn->b_sp_dpc_enabled) {
+ tasklet_disable(p_hwfn->sp_dpc);
+ p_hwfn->b_sp_dpc_enabled = false;
+ DP_VERBOSE(cdev, NETIF_MSG_IFDOWN,
+ "Disabled sp taskelt [hwfn %d] at %p\n",
+ i, p_hwfn->sp_dpc);
+ }
+ }
+
+ return rc;
+}
+
+static int qed_nic_reset(struct qed_dev *cdev)
+{
+ int rc;
+
+ rc = qed_hw_reset(cdev);
+ if (rc)
+ return rc;
+
+ qed_resc_free(cdev);
+
+ return 0;
+}
+
+static int qed_nic_setup(struct qed_dev *cdev)
+{
+ int rc;
+
+ rc = qed_resc_alloc(cdev);
+ if (rc)
+ return rc;
+
+ DP_INFO(cdev, "Allocated qed resources\n");
+
+ qed_resc_setup(cdev);
+
+ return rc;
+}
+
+static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt)
+{
+ int limit = 0;
+
+ /* Mark the fastpath as free/used */
+ cdev->int_params.fp_initialized = cnt ? true : false;
+
+ if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX)
+ limit = cdev->num_hwfns * 63;
+ else if (cdev->int_params.fp_msix_cnt)
+ limit = cdev->int_params.fp_msix_cnt;
+
+ if (!limit)
+ return -ENOMEM;
+
+ return min_t(int, cnt, limit);
+}
+
+static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info)
+{
+ memset(info, 0, sizeof(struct qed_int_info));
+
+ if (!cdev->int_params.fp_initialized) {
+ DP_INFO(cdev,
+ "Protocol driver requested interrupt information, but its support is not yet configured\n");
+ return -EINVAL;
+ }
+
+ /* Need to expose only MSI-X information; Single IRQ is handled solely
+ * by qed.
+ */
+ if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
+ int msix_base = cdev->int_params.fp_msix_base;
+
+ info->msix_cnt = cdev->int_params.fp_msix_cnt;
+ info->msix = &cdev->int_params.msix_table[msix_base];
+ }
+
+ return 0;
+}
+
+static int qed_slowpath_setup_int(struct qed_dev *cdev,
+ enum qed_int_mode int_mode)
+{
+ int rc, i;
+ u8 num_vectors = 0;
+
+ memset(&cdev->int_params, 0, sizeof(struct qed_int_params));
+
+ cdev->int_params.in.int_mode = int_mode;
+ for_each_hwfn(cdev, i)
+ num_vectors += qed_int_get_num_sbs(&cdev->hwfns[i], NULL) + 1;
+ cdev->int_params.in.num_vectors = num_vectors;
+
+ /* We want a minimum of one slowpath and one fastpath vector per hwfn */
+ cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2;
+
+ rc = qed_set_int_mode(cdev, false);
+ if (rc) {
+ DP_ERR(cdev, "qed_slowpath_setup_int ERR\n");
+ return rc;
+ }
+
+ cdev->int_params.fp_msix_base = cdev->num_hwfns;
+ cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors -
+ cdev->num_hwfns;
+
+ return 0;
+}
+
+u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len,
+ u8 *input_buf, u32 max_size, u8 *unzip_buf)
+{
+ int rc;
+
+ p_hwfn->stream->next_in = input_buf;
+ p_hwfn->stream->avail_in = input_len;
+ p_hwfn->stream->next_out = unzip_buf;
+ p_hwfn->stream->avail_out = max_size;
+
+ rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS);
+
+ if (rc != Z_OK) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n",
+ rc);
+ return 0;
+ }
+
+ rc = zlib_inflate(p_hwfn->stream, Z_FINISH);
+ zlib_inflateEnd(p_hwfn->stream);
+
+ if (rc != Z_OK && rc != Z_STREAM_END) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n",
+ p_hwfn->stream->msg, rc);
+ return 0;
+ }
+
+ return p_hwfn->stream->total_out / 4;
+}
+
+static int qed_alloc_stream_mem(struct qed_dev *cdev)
+{
+ int i;
+ void *workspace;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL);
+ if (!p_hwfn->stream)
+ return -ENOMEM;
+
+ workspace = vzalloc(zlib_inflate_workspacesize());
+ if (!workspace)
+ return -ENOMEM;
+ p_hwfn->stream->workspace = workspace;
+ }
+
+ return 0;
+}
+
+static void qed_free_stream_mem(struct qed_dev *cdev)
+{
+ int i;
+
+ for_each_hwfn(cdev, i) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ if (!p_hwfn->stream)
+ return;
+
+ vfree(p_hwfn->stream->workspace);
+ kfree(p_hwfn->stream);
+ }
+}
+
+static void qed_update_pf_params(struct qed_dev *cdev,
+ struct qed_pf_params *params)
+{
+ int i;
+
+ for (i = 0; i < cdev->num_hwfns; i++) {
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+ p_hwfn->pf_params = *params;
+ }
+}
+
+static int qed_slowpath_start(struct qed_dev *cdev,
+ struct qed_slowpath_params *params)
+{
+ struct qed_mcp_drv_version drv_version;
+ const u8 *data = NULL;
+ struct qed_hwfn *hwfn;
+ int rc;
+
+ rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME,
+ &cdev->pdev->dev);
+ if (rc) {
+ DP_NOTICE(cdev,
+ "Failed to find fw file - /lib/firmware/%s\n",
+ QED_FW_FILE_NAME);
+ goto err;
+ }
+
+ rc = qed_nic_setup(cdev);
+ if (rc)
+ goto err;
+
+ rc = qed_slowpath_setup_int(cdev, params->int_mode);
+ if (rc)
+ goto err1;
+
+ /* Request the slowpath IRQ */
+ rc = qed_slowpath_irq_req(cdev);
+ if (rc)
+ goto err2;
+
+ /* Allocate stream for unzipping */
+ rc = qed_alloc_stream_mem(cdev);
+ if (rc) {
+ DP_NOTICE(cdev, "Failed to allocate stream memory\n");
+ goto err3;
+ }
+
+ /* Start the slowpath */
+ data = cdev->firmware->data;
+
+ rc = qed_hw_init(cdev, true, cdev->int_params.out.int_mode,
+ true, data);
+ if (rc)
+ goto err3;
+
+ DP_INFO(cdev,
+ "HW initialization and function start completed successfully\n");
+
+ hwfn = QED_LEADING_HWFN(cdev);
+ drv_version.version = (params->drv_major << 24) |
+ (params->drv_minor << 16) |
+ (params->drv_rev << 8) |
+ (params->drv_eng);
+ strlcpy(drv_version.name, params->name,
+ MCP_DRV_VER_STR_SIZE - 4);
+ rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt,
+ &drv_version);
+ if (rc) {
+ DP_NOTICE(cdev, "Failed sending drv version command\n");
+ return rc;
+ }
+
+ return 0;
+
+err3:
+ qed_free_stream_mem(cdev);
+ qed_slowpath_irq_free(cdev);
+err2:
+ qed_disable_msix(cdev);
+err1:
+ qed_resc_free(cdev);
+err:
+ release_firmware(cdev->firmware);
+
+ return rc;
+}
+
+static int qed_slowpath_stop(struct qed_dev *cdev)
+{
+ if (!cdev)
+ return -ENODEV;
+
+ qed_free_stream_mem(cdev);
+
+ qed_nic_stop(cdev);
+ qed_slowpath_irq_free(cdev);
+
+ qed_disable_msix(cdev);
+ qed_nic_reset(cdev);
+
+ release_firmware(cdev->firmware);
+
+ return 0;
+}
+
+static void qed_set_id(struct qed_dev *cdev, char name[NAME_SIZE],
+ char ver_str[VER_SIZE])
+{
+ int i;
+
+ memcpy(cdev->name, name, NAME_SIZE);
+ for_each_hwfn(cdev, i)
+ snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i);
+
+ memcpy(cdev->ver_str, ver_str, VER_SIZE);
+ cdev->drv_type = DRV_ID_DRV_TYPE_LINUX;
+}
+
+static u32 qed_sb_init(struct qed_dev *cdev,
+ struct qed_sb_info *sb_info,
+ void *sb_virt_addr,
+ dma_addr_t sb_phy_addr, u16 sb_id,
+ enum qed_sb_type type)
+{
+ struct qed_hwfn *p_hwfn;
+ int hwfn_index;
+ u16 rel_sb_id;
+ u8 n_hwfns;
+ u32 rc;
+
+ /* RoCE uses single engine and CMT uses two engines. When using both
+ * we force only a single engine. Storage uses only engine 0 too.
+ */
+ if (type == QED_SB_TYPE_L2_QUEUE)
+ n_hwfns = cdev->num_hwfns;
+ else
+ n_hwfns = 1;
+
+ hwfn_index = sb_id % n_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+ rel_sb_id = sb_id / n_hwfns;
+
+ DP_VERBOSE(cdev, NETIF_MSG_INTR,
+ "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n",
+ hwfn_index, rel_sb_id, sb_id);
+
+ rc = qed_int_sb_init(p_hwfn, p_hwfn->p_main_ptt, sb_info,
+ sb_virt_addr, sb_phy_addr, rel_sb_id);
+
+ return rc;
+}
+
+static u32 qed_sb_release(struct qed_dev *cdev,
+ struct qed_sb_info *sb_info,
+ u16 sb_id)
+{
+ struct qed_hwfn *p_hwfn;
+ int hwfn_index;
+ u16 rel_sb_id;
+ u32 rc;
+
+ hwfn_index = sb_id % cdev->num_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+ rel_sb_id = sb_id / cdev->num_hwfns;
+
+ DP_VERBOSE(cdev, NETIF_MSG_INTR,
+ "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n",
+ hwfn_index, rel_sb_id, sb_id);
+
+ rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id);
+
+ return rc;
+}
+
+static int qed_set_link(struct qed_dev *cdev,
+ struct qed_link_params *params)
+{
+ struct qed_hwfn *hwfn;
+ struct qed_mcp_link_params *link_params;
+ struct qed_ptt *ptt;
+ int rc;
+
+ if (!cdev)
+ return -ENODEV;
+
+ /* The link should be set only once per PF */
+ hwfn = &cdev->hwfns[0];
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EBUSY;
+
+ link_params = qed_mcp_get_link_params(hwfn);
+ if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG)
+ link_params->speed.autoneg = params->autoneg;
+ if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
+ link_params->speed.advertised_speeds = 0;
+ if ((params->adv_speeds & SUPPORTED_1000baseT_Half) ||
+ (params->adv_speeds & SUPPORTED_1000baseT_Full))
+ link_params->speed.advertised_speeds |=
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+ if (params->adv_speeds & SUPPORTED_10000baseKR_Full)
+ link_params->speed.advertised_speeds |=
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+ if (params->adv_speeds & SUPPORTED_40000baseLR4_Full)
+ link_params->speed.advertised_speeds |=
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
+ if (params->adv_speeds & 0)
+ link_params->speed.advertised_speeds |=
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
+ if (params->adv_speeds & 0)
+ link_params->speed.advertised_speeds |=
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G;
+ }
+ if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED)
+ link_params->speed.forced_speed = params->forced_speed;
+
+ rc = qed_mcp_set_link(hwfn, ptt, params->link_up);
+
+ qed_ptt_release(hwfn, ptt);
+
+ return rc;
+}
+
+static int qed_get_port_type(u32 media_type)
+{
+ int port_type;
+
+ switch (media_type) {
+ case MEDIA_SFPP_10G_FIBER:
+ case MEDIA_SFP_1G_FIBER:
+ case MEDIA_XFP_FIBER:
+ case MEDIA_KR:
+ port_type = PORT_FIBRE;
+ break;
+ case MEDIA_DA_TWINAX:
+ port_type = PORT_DA;
+ break;
+ case MEDIA_BASE_T:
+ port_type = PORT_TP;
+ break;
+ case MEDIA_NOT_PRESENT:
+ port_type = PORT_NONE;
+ break;
+ case MEDIA_UNSPECIFIED:
+ default:
+ port_type = PORT_OTHER;
+ break;
+ }
+ return port_type;
+}
+
+static void qed_fill_link(struct qed_hwfn *hwfn,
+ struct qed_link_output *if_link)
+{
+ struct qed_mcp_link_params params;
+ struct qed_mcp_link_state link;
+ struct qed_mcp_link_capabilities link_caps;
+ u32 media_type;
+
+ memset(if_link, 0, sizeof(*if_link));
+
+ /* Prepare source inputs */
+ memcpy(&params, qed_mcp_get_link_params(hwfn), sizeof(params));
+ memcpy(&link, qed_mcp_get_link_state(hwfn), sizeof(link));
+ memcpy(&link_caps, qed_mcp_get_link_capabilities(hwfn),
+ sizeof(link_caps));
+
+ /* Set the link parameters to pass to protocol driver */
+ if (link.link_up)
+ if_link->link_up = true;
+
+ /* TODO - at the moment assume supported and advertised speed equal */
+ if_link->supported_caps = SUPPORTED_FIBRE;
+ if (params.speed.autoneg)
+ if_link->supported_caps |= SUPPORTED_Autoneg;
+ if (params.pause.autoneg ||
+ (params.pause.forced_rx && params.pause.forced_tx))
+ if_link->supported_caps |= SUPPORTED_Asym_Pause;
+ if (params.pause.autoneg || params.pause.forced_rx ||
+ params.pause.forced_tx)
+ if_link->supported_caps |= SUPPORTED_Pause;
+
+ if_link->advertised_caps = if_link->supported_caps;
+ if (params.speed.advertised_speeds &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+ if_link->advertised_caps |= SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full;
+ if (params.speed.advertised_speeds &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+ if_link->advertised_caps |= SUPPORTED_10000baseKR_Full;
+ if (params.speed.advertised_speeds &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+ if_link->advertised_caps |= SUPPORTED_40000baseLR4_Full;
+ if (params.speed.advertised_speeds &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+ if_link->advertised_caps |= 0;
+ if (params.speed.advertised_speeds &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G)
+ if_link->advertised_caps |= 0;
+
+ if (link_caps.speed_capabilities &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+ if_link->supported_caps |= SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full;
+ if (link_caps.speed_capabilities &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+ if_link->supported_caps |= SUPPORTED_10000baseKR_Full;
+ if (link_caps.speed_capabilities &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+ if_link->supported_caps |= SUPPORTED_40000baseLR4_Full;
+ if (link_caps.speed_capabilities &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+ if_link->supported_caps |= 0;
+ if (link_caps.speed_capabilities &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G)
+ if_link->supported_caps |= 0;
+
+ if (link.link_up)
+ if_link->speed = link.speed;
+
+ /* TODO - fill duplex properly */
+ if_link->duplex = DUPLEX_FULL;
+ qed_mcp_get_media_type(hwfn->cdev, &media_type);
+ if_link->port = qed_get_port_type(media_type);
+
+ if_link->autoneg = params.speed.autoneg;
+
+ if (params.pause.autoneg)
+ if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
+ if (params.pause.forced_rx)
+ if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE;
+ if (params.pause.forced_tx)
+ if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
+
+ /* Link partner capabilities */
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_1G_HD)
+ if_link->lp_caps |= SUPPORTED_1000baseT_Half;
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_1G_FD)
+ if_link->lp_caps |= SUPPORTED_1000baseT_Full;
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_10G)
+ if_link->lp_caps |= SUPPORTED_10000baseKR_Full;
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_40G)
+ if_link->lp_caps |= SUPPORTED_40000baseLR4_Full;
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_50G)
+ if_link->lp_caps |= 0;
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_100G)
+ if_link->lp_caps |= 0;
+
+ if (link.an_complete)
+ if_link->lp_caps |= SUPPORTED_Autoneg;
+
+ if (link.partner_adv_pause)
+ if_link->lp_caps |= SUPPORTED_Pause;
+ if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE ||
+ link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE)
+ if_link->lp_caps |= SUPPORTED_Asym_Pause;
+}
+
+static void qed_get_current_link(struct qed_dev *cdev,
+ struct qed_link_output *if_link)
+{
+ qed_fill_link(&cdev->hwfns[0], if_link);
+}
+
+void qed_link_update(struct qed_hwfn *hwfn)
+{
+ void *cookie = hwfn->cdev->ops_cookie;
+ struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
+ struct qed_link_output if_link;
+
+ qed_fill_link(hwfn, &if_link);
+
+ if (IS_LEAD_HWFN(hwfn) && cookie)
+ op->link_update(cookie, &if_link);
+}
+
+static int qed_drain(struct qed_dev *cdev)
+{
+ struct qed_hwfn *hwfn;
+ struct qed_ptt *ptt;
+ int i, rc;
+
+ for_each_hwfn(cdev, i) {
+ hwfn = &cdev->hwfns[i];
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt) {
+ DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n");
+ return -EBUSY;
+ }
+ rc = qed_mcp_drain(hwfn, ptt);
+ if (rc)
+ return rc;
+ qed_ptt_release(hwfn, ptt);
+ }
+
+ return 0;
+}
+
+const struct qed_common_ops qed_common_ops_pass = {
+ .probe = &qed_probe,
+ .remove = &qed_remove,
+ .set_power_state = &qed_set_power_state,
+ .set_id = &qed_set_id,
+ .update_pf_params = &qed_update_pf_params,
+ .slowpath_start = &qed_slowpath_start,
+ .slowpath_stop = &qed_slowpath_stop,
+ .set_fp_int = &qed_set_int_fp,
+ .get_fp_int = &qed_get_int_fp,
+ .sb_init = &qed_sb_init,
+ .sb_release = &qed_sb_release,
+ .simd_handler_config = &qed_simd_handler_config,
+ .simd_handler_clean = &qed_simd_handler_clean,
+ .set_link = &qed_set_link,
+ .get_link = &qed_get_current_link,
+ .drain = &qed_drain,
+ .update_msglvl = &qed_init_dp,
+ .chain_alloc = &qed_chain_alloc,
+ .chain_free = &qed_chain_free,
+};
+
+u32 qed_get_protocol_version(enum qed_protocol protocol)
+{
+ switch (protocol) {
+ case QED_PROTOCOL_ETH:
+ return QED_ETH_INTERFACE_VERSION;
+ default:
+ return 0;
+ }
+}
+EXPORT_SYMBOL(qed_get_protocol_version);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
new file mode 100644
index 000000000000..20d048cdcb88
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -0,0 +1,860 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "qed.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_mcp.h"
+#include "qed_reg_addr.h"
+#define CHIP_MCP_RESP_ITER_US 10
+
+#define QED_DRV_MB_MAX_RETRIES (500 * 1000) /* Account for 5 sec */
+#define QED_MCP_RESET_RETRIES (50 * 1000) /* Account for 500 msec */
+
+#define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \
+ qed_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \
+ _val)
+
+#define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \
+ qed_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset))
+
+#define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \
+ DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \
+ offsetof(struct public_drv_mb, _field), _val)
+
+#define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \
+ DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \
+ offsetof(struct public_drv_mb, _field))
+
+#define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \
+ DRV_ID_PDA_COMP_VER_SHIFT)
+
+#define MCP_BYTES_PER_MBIT_SHIFT 17
+
+bool qed_mcp_is_init(struct qed_hwfn *p_hwfn)
+{
+ if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base)
+ return false;
+ return true;
+}
+
+void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
+ PUBLIC_PORT);
+ u32 mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, addr);
+
+ p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize,
+ MFW_PORT(p_hwfn));
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "port_addr = 0x%x, port_id 0x%02x\n",
+ p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn));
+}
+
+void qed_mcp_read_mb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length);
+ u32 tmp, i;
+
+ if (!p_hwfn->mcp_info->public_base)
+ return;
+
+ for (i = 0; i < length; i++) {
+ tmp = qed_rd(p_hwfn, p_ptt,
+ p_hwfn->mcp_info->mfw_mb_addr +
+ (i << 2) + sizeof(u32));
+
+ /* The MB data is actually BE; Need to force it to cpu */
+ ((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] =
+ be32_to_cpu((__force __be32)tmp);
+ }
+}
+
+int qed_mcp_free(struct qed_hwfn *p_hwfn)
+{
+ if (p_hwfn->mcp_info) {
+ kfree(p_hwfn->mcp_info->mfw_mb_cur);
+ kfree(p_hwfn->mcp_info->mfw_mb_shadow);
+ }
+ kfree(p_hwfn->mcp_info);
+
+ return 0;
+}
+
+static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_mcp_info *p_info = p_hwfn->mcp_info;
+ u32 drv_mb_offsize, mfw_mb_offsize;
+ u32 mcp_pf_id = MCP_PF_ID(p_hwfn);
+
+ p_info->public_base = qed_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR);
+ if (!p_info->public_base)
+ return 0;
+
+ p_info->public_base |= GRCBASE_MCP;
+
+ /* Calculate the driver and MFW mailbox address */
+ drv_mb_offsize = qed_rd(p_hwfn, p_ptt,
+ SECTION_OFFSIZE_ADDR(p_info->public_base,
+ PUBLIC_DRV_MB));
+ p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id);
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n",
+ drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id);
+
+ /* Set the MFW MB address */
+ mfw_mb_offsize = qed_rd(p_hwfn, p_ptt,
+ SECTION_OFFSIZE_ADDR(p_info->public_base,
+ PUBLIC_MFW_MB));
+ p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id);
+ p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, p_info->mfw_mb_addr);
+
+ /* Get the current driver mailbox sequence before sending
+ * the first command
+ */
+ p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK;
+
+ /* Get current FW pulse sequence */
+ p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) &
+ DRV_PULSE_SEQ_MASK;
+
+ p_info->mcp_hist = (u16)qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
+
+ return 0;
+}
+
+int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_mcp_info *p_info;
+ u32 size;
+
+ /* Allocate mcp_info structure */
+ p_hwfn->mcp_info = kzalloc(sizeof(*p_hwfn->mcp_info), GFP_ATOMIC);
+ if (!p_hwfn->mcp_info)
+ goto err;
+ p_info = p_hwfn->mcp_info;
+
+ if (qed_load_mcp_offsets(p_hwfn, p_ptt) != 0) {
+ DP_NOTICE(p_hwfn, "MCP is not initialized\n");
+ /* Do not free mcp_info here, since public_base indicate that
+ * the MCP is not initialized
+ */
+ return 0;
+ }
+
+ size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32);
+ p_info->mfw_mb_cur = kzalloc(size, GFP_ATOMIC);
+ p_info->mfw_mb_shadow =
+ kzalloc(sizeof(u32) * MFW_DRV_MSG_MAX_DWORDS(
+ p_info->mfw_mb_length), GFP_ATOMIC);
+ if (!p_info->mfw_mb_shadow || !p_info->mfw_mb_addr)
+ goto err;
+
+ /* Initialize the MFW mutex */
+ mutex_init(&p_info->mutex);
+
+ return 0;
+
+err:
+ DP_NOTICE(p_hwfn, "Failed to allocate mcp memory\n");
+ qed_mcp_free(p_hwfn);
+ return -ENOMEM;
+}
+
+int qed_mcp_reset(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 seq = ++p_hwfn->mcp_info->drv_mb_seq;
+ u8 delay = CHIP_MCP_RESP_ITER_US;
+ u32 org_mcp_reset_seq, cnt = 0;
+ int rc = 0;
+
+ /* Set drv command along with the updated sequence */
+ org_mcp_reset_seq = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
+ DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header,
+ (DRV_MSG_CODE_MCP_RESET | seq));
+
+ do {
+ /* Wait for MFW response */
+ udelay(delay);
+ /* Give the FW up to 500 second (50*1000*10usec) */
+ } while ((org_mcp_reset_seq == qed_rd(p_hwfn, p_ptt,
+ MISCS_REG_GENERIC_POR_0)) &&
+ (cnt++ < QED_MCP_RESET_RETRIES));
+
+ if (org_mcp_reset_seq !=
+ qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "MCP was reset after %d usec\n", cnt * delay);
+ } else {
+ DP_ERR(p_hwfn, "Failed to reset MCP\n");
+ rc = -EAGAIN;
+ }
+
+ return rc;
+}
+
+static int qed_do_mcp_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 cmd,
+ u32 param,
+ u32 *o_mcp_resp,
+ u32 *o_mcp_param)
+{
+ u8 delay = CHIP_MCP_RESP_ITER_US;
+ u32 seq, cnt = 1, actual_mb_seq;
+ int rc = 0;
+
+ /* Get actual driver mailbox sequence */
+ actual_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK;
+
+ /* Use MCP history register to check if MCP reset occurred between
+ * init time and now.
+ */
+ if (p_hwfn->mcp_info->mcp_hist !=
+ qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "Rereading MCP offsets\n");
+ qed_load_mcp_offsets(p_hwfn, p_ptt);
+ qed_mcp_cmd_port_init(p_hwfn, p_ptt);
+ }
+ seq = ++p_hwfn->mcp_info->drv_mb_seq;
+
+ /* Set drv param */
+ DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, param);
+
+ /* Set drv command along with the updated sequence */
+ DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (cmd | seq));
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "wrote command (%x) to MFW MB param 0x%08x\n",
+ (cmd | seq), param);
+
+ do {
+ /* Wait for MFW response */
+ udelay(delay);
+ *o_mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header);
+
+ /* Give the FW up to 5 second (500*10ms) */
+ } while ((seq != (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) &&
+ (cnt++ < QED_DRV_MB_MAX_RETRIES));
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "[after %d ms] read (%x) seq is (%x) from FW MB\n",
+ cnt * delay, *o_mcp_resp, seq);
+
+ /* Is this a reply to our command? */
+ if (seq == (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) {
+ *o_mcp_resp &= FW_MSG_CODE_MASK;
+ /* Get the MCP param */
+ *o_mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param);
+ } else {
+ /* FW BUG! */
+ DP_ERR(p_hwfn, "MFW failed to respond!\n");
+ *o_mcp_resp = 0;
+ rc = -EAGAIN;
+ }
+ return rc;
+}
+
+int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 cmd,
+ u32 param,
+ u32 *o_mcp_resp,
+ u32 *o_mcp_param)
+{
+ int rc = 0;
+
+ /* MCP not initialized */
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized !\n");
+ return -EBUSY;
+ }
+
+ /* Lock Mutex to ensure only single thread is
+ * accessing the MCP at one time
+ */
+ mutex_lock(&p_hwfn->mcp_info->mutex);
+ rc = qed_do_mcp_cmd(p_hwfn, p_ptt, cmd, param,
+ o_mcp_resp, o_mcp_param);
+ /* Release Mutex */
+ mutex_unlock(&p_hwfn->mcp_info->mutex);
+
+ return rc;
+}
+
+static void qed_mcp_set_drv_ver(struct qed_dev *cdev,
+ struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 i;
+
+ /* Copy version string to MCP */
+ for (i = 0; i < MCP_DRV_VER_STR_SIZE_DWORD; i++)
+ DRV_MB_WR(p_hwfn, p_ptt, union_data.ver_str[i],
+ *(u32 *)&cdev->ver_str[i * sizeof(u32)]);
+}
+
+int qed_mcp_load_req(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *p_load_code)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+ u32 param;
+ int rc;
+
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized !\n");
+ return -EBUSY;
+ }
+
+ /* Save driver's version to shmem */
+ qed_mcp_set_drv_ver(cdev, p_hwfn, p_ptt);
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "fw_seq 0x%08x, drv_pulse 0x%x\n",
+ p_hwfn->mcp_info->drv_mb_seq,
+ p_hwfn->mcp_info->drv_pulse_seq);
+
+ /* Load Request */
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_LOAD_REQ,
+ (PDA_COMP | DRV_ID_MCP_HSI_VER_CURRENT |
+ cdev->drv_type),
+ p_load_code, &param);
+
+ /* if mcp fails to respond we must abort */
+ if (rc) {
+ DP_ERR(p_hwfn, "MCP response failure, aborting\n");
+ return rc;
+ }
+
+ /* If MFW refused (e.g. other port is in diagnostic mode) we
+ * must abort. This can happen in the following cases:
+ * - Other port is in diagnostic mode
+ * - Previously loaded function on the engine is not compliant with
+ * the requester.
+ * - MFW cannot cope with the requester's DRV_MFW_HSI_VERSION.
+ * -
+ */
+ if (!(*p_load_code) ||
+ ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI) ||
+ ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_PDA) ||
+ ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG)) {
+ DP_ERR(p_hwfn, "MCP refused load request, aborting\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool b_reset)
+{
+ struct qed_mcp_link_state *p_link;
+ u32 status = 0;
+
+ p_link = &p_hwfn->mcp_info->link_output;
+ memset(p_link, 0, sizeof(*p_link));
+ if (!b_reset) {
+ status = qed_rd(p_hwfn, p_ptt,
+ p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port, link_status));
+ DP_VERBOSE(p_hwfn, (NETIF_MSG_LINK | QED_MSG_SP),
+ "Received link update [0x%08x] from mfw [Addr 0x%x]\n",
+ status,
+ (u32)(p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port,
+ link_status)));
+ } else {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+ "Resetting link indications\n");
+ return;
+ }
+
+ p_link->link_up = !!(status & LINK_STATUS_LINK_UP);
+
+ p_link->full_duplex = true;
+ switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) {
+ case LINK_STATUS_SPEED_AND_DUPLEX_100G:
+ p_link->speed = 100000;
+ break;
+ case LINK_STATUS_SPEED_AND_DUPLEX_50G:
+ p_link->speed = 50000;
+ break;
+ case LINK_STATUS_SPEED_AND_DUPLEX_40G:
+ p_link->speed = 40000;
+ break;
+ case LINK_STATUS_SPEED_AND_DUPLEX_25G:
+ p_link->speed = 25000;
+ break;
+ case LINK_STATUS_SPEED_AND_DUPLEX_20G:
+ p_link->speed = 20000;
+ break;
+ case LINK_STATUS_SPEED_AND_DUPLEX_10G:
+ p_link->speed = 10000;
+ break;
+ case LINK_STATUS_SPEED_AND_DUPLEX_1000THD:
+ p_link->full_duplex = false;
+ /* Fall-through */
+ case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD:
+ p_link->speed = 1000;
+ break;
+ default:
+ p_link->speed = 0;
+ }
+
+ /* Correct speed according to bandwidth allocation */
+ if (p_hwfn->mcp_info->func_info.bandwidth_max && p_link->speed) {
+ p_link->speed = p_link->speed *
+ p_hwfn->mcp_info->func_info.bandwidth_max /
+ 100;
+ qed_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
+ p_link->speed);
+ DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+ "Configured MAX bandwidth to be %08x Mb/sec\n",
+ p_link->speed);
+ }
+
+ p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
+ p_link->an_complete = !!(status &
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE);
+ p_link->parallel_detection = !!(status &
+ LINK_STATUS_PARALLEL_DETECTION_USED);
+ p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED);
+
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_1G_FD : 0;
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_1G_HD : 0;
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_10G : 0;
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_20G : 0;
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_40G : 0;
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_50G : 0;
+ p_link->partner_adv_speed |=
+ (status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ?
+ QED_LINK_PARTNER_SPEED_100G : 0;
+
+ p_link->partner_tx_flow_ctrl_en =
+ !!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED);
+ p_link->partner_rx_flow_ctrl_en =
+ !!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
+
+ switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) {
+ case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE:
+ p_link->partner_adv_pause = QED_LINK_PARTNER_SYMMETRIC_PAUSE;
+ break;
+ case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE:
+ p_link->partner_adv_pause = QED_LINK_PARTNER_ASYMMETRIC_PAUSE;
+ break;
+ case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE:
+ p_link->partner_adv_pause = QED_LINK_PARTNER_BOTH_PAUSE;
+ break;
+ default:
+ p_link->partner_adv_pause = 0;
+ }
+
+ p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT);
+
+ qed_link_update(p_hwfn);
+}
+
+int qed_mcp_set_link(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool b_up)
+{
+ struct qed_mcp_link_params *params = &p_hwfn->mcp_info->link_input;
+ u32 param = 0, reply = 0, cmd;
+ struct pmm_phy_cfg phy_cfg;
+ int rc = 0;
+ u32 i;
+
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized !\n");
+ return -EBUSY;
+ }
+
+ /* Set the shmem configuration according to params */
+ memset(&phy_cfg, 0, sizeof(phy_cfg));
+ cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET;
+ if (!params->speed.autoneg)
+ phy_cfg.speed = params->speed.forced_speed;
+ phy_cfg.pause |= (params->pause.autoneg) ? PMM_PAUSE_AUTONEG : 0;
+ phy_cfg.pause |= (params->pause.forced_rx) ? PMM_PAUSE_RX : 0;
+ phy_cfg.pause |= (params->pause.forced_tx) ? PMM_PAUSE_TX : 0;
+ phy_cfg.adv_speed = params->speed.advertised_speeds;
+ phy_cfg.loopback_mode = params->loopback_mode;
+
+ /* Write the requested configuration to shmem */
+ for (i = 0; i < sizeof(phy_cfg); i += 4)
+ qed_wr(p_hwfn, p_ptt,
+ p_hwfn->mcp_info->drv_mb_addr +
+ offsetof(struct public_drv_mb, union_data) + i,
+ ((u32 *)&phy_cfg)[i >> 2]);
+
+ if (b_up) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+ "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x, features 0x%08x\n",
+ phy_cfg.speed,
+ phy_cfg.pause,
+ phy_cfg.adv_speed,
+ phy_cfg.loopback_mode,
+ phy_cfg.feature_config_flags);
+ } else {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+ "Resetting link\n");
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "fw_seq 0x%08x, drv_pulse 0x%x\n",
+ p_hwfn->mcp_info->drv_mb_seq,
+ p_hwfn->mcp_info->drv_pulse_seq);
+
+ /* Load Request */
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, cmd, 0, &reply, &param);
+
+ /* if mcp fails to respond we must abort */
+ if (rc) {
+ DP_ERR(p_hwfn, "MCP response failure, aborting\n");
+ return rc;
+ }
+
+ /* Reset the link status if needed */
+ if (!b_up)
+ qed_mcp_handle_link_change(p_hwfn, p_ptt, true);
+
+ return 0;
+}
+
+int qed_mcp_handle_events(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_mcp_info *info = p_hwfn->mcp_info;
+ int rc = 0;
+ bool found = false;
+ u16 i;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "Received message from MFW\n");
+
+ /* Read Messages from MFW */
+ qed_mcp_read_mb(p_hwfn, p_ptt);
+
+ /* Compare current messages to old ones */
+ for (i = 0; i < info->mfw_mb_length; i++) {
+ if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i])
+ continue;
+
+ found = true;
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+ "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n",
+ i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]);
+
+ switch (i) {
+ case MFW_DRV_MSG_LINK_CHANGE:
+ qed_mcp_handle_link_change(p_hwfn, p_ptt, false);
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unimplemented MFW message %d\n", i);
+ rc = -EINVAL;
+ }
+ }
+
+ /* ACK everything */
+ for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) {
+ __be32 val = cpu_to_be32(((u32 *)info->mfw_mb_cur)[i]);
+
+ /* MFW expect answer in BE, so we force write in that format */
+ qed_wr(p_hwfn, p_ptt,
+ info->mfw_mb_addr + sizeof(u32) +
+ MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) *
+ sizeof(u32) + i * sizeof(u32),
+ (__force u32)val);
+ }
+
+ if (!found) {
+ DP_NOTICE(p_hwfn,
+ "Received an MFW message indication but no new message!\n");
+ rc = -EINVAL;
+ }
+
+ /* Copy the new mfw messages into the shadow */
+ memcpy(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length);
+
+ return rc;
+}
+
+int qed_mcp_get_mfw_ver(struct qed_dev *cdev,
+ u32 *p_mfw_ver)
+{
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[0];
+ struct qed_ptt *p_ptt;
+ u32 global_offsize;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EBUSY;
+
+ global_offsize = qed_rd(p_hwfn, p_ptt,
+ SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->
+ public_base,
+ PUBLIC_GLOBAL));
+ *p_mfw_ver = qed_rd(p_hwfn, p_ptt,
+ SECTION_ADDR(global_offsize, 0) +
+ offsetof(struct public_global, mfw_ver));
+
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return 0;
+}
+
+int qed_mcp_get_media_type(struct qed_dev *cdev,
+ u32 *p_media_type)
+{
+ struct qed_hwfn *p_hwfn = &cdev->hwfns[0];
+ struct qed_ptt *p_ptt;
+
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized !\n");
+ return -EBUSY;
+ }
+
+ *p_media_type = MEDIA_UNSPECIFIED;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EBUSY;
+
+ *p_media_type = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port, media_type));
+
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return 0;
+}
+
+static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct public_func *p_data,
+ int pfid)
+{
+ u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
+ PUBLIC_FUNC);
+ u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr);
+ u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
+ u32 i, size;
+
+ memset(p_data, 0, sizeof(*p_data));
+
+ size = min_t(u32, sizeof(*p_data),
+ QED_SECTION_SIZE(mfw_path_offsize));
+ for (i = 0; i < size / sizeof(u32); i++)
+ ((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt,
+ func_addr + (i << 2));
+
+ return size;
+}
+
+static int
+qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
+ struct public_func *p_info,
+ enum qed_pci_personality *p_proto)
+{
+ int rc = 0;
+
+ switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) {
+ case FUNC_MF_CFG_PROTOCOL_ETHERNET:
+ *p_proto = QED_PCI_ETH;
+ break;
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_mcp_function_info *info;
+ struct public_func shmem_info;
+
+ qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
+ MCP_PF_ID(p_hwfn));
+ info = &p_hwfn->mcp_info->func_info;
+
+ info->pause_on_host = (shmem_info.config &
+ FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0;
+
+ if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info,
+ &info->protocol)) {
+ DP_ERR(p_hwfn, "Unknown personality %08x\n",
+ (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK));
+ return -EINVAL;
+ }
+
+ if (p_hwfn->cdev->mf_mode != SF) {
+ info->bandwidth_min = (shmem_info.config &
+ FUNC_MF_CFG_MIN_BW_MASK) >>
+ FUNC_MF_CFG_MIN_BW_SHIFT;
+ if (info->bandwidth_min < 1 || info->bandwidth_min > 100) {
+ DP_INFO(p_hwfn,
+ "bandwidth minimum out of bounds [%02x]. Set to 1\n",
+ info->bandwidth_min);
+ info->bandwidth_min = 1;
+ }
+
+ info->bandwidth_max = (shmem_info.config &
+ FUNC_MF_CFG_MAX_BW_MASK) >>
+ FUNC_MF_CFG_MAX_BW_SHIFT;
+ if (info->bandwidth_max < 1 || info->bandwidth_max > 100) {
+ DP_INFO(p_hwfn,
+ "bandwidth maximum out of bounds [%02x]. Set to 100\n",
+ info->bandwidth_max);
+ info->bandwidth_max = 100;
+ }
+ }
+
+ if (shmem_info.mac_upper || shmem_info.mac_lower) {
+ info->mac[0] = (u8)(shmem_info.mac_upper >> 8);
+ info->mac[1] = (u8)(shmem_info.mac_upper);
+ info->mac[2] = (u8)(shmem_info.mac_lower >> 24);
+ info->mac[3] = (u8)(shmem_info.mac_lower >> 16);
+ info->mac[4] = (u8)(shmem_info.mac_lower >> 8);
+ info->mac[5] = (u8)(shmem_info.mac_lower);
+ } else {
+ DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n");
+ }
+
+ info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_upper |
+ (((u64)shmem_info.fcoe_wwn_port_name_lower) << 32);
+ info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_upper |
+ (((u64)shmem_info.fcoe_wwn_node_name_lower) << 32);
+
+ info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
+
+ DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP),
+ "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x\n",
+ info->pause_on_host, info->protocol,
+ info->bandwidth_min, info->bandwidth_max,
+ info->mac[0], info->mac[1], info->mac[2],
+ info->mac[3], info->mac[4], info->mac[5],
+ info->wwn_port, info->wwn_node, info->ovlan);
+
+ return 0;
+}
+
+struct qed_mcp_link_params
+*qed_mcp_get_link_params(struct qed_hwfn *p_hwfn)
+{
+ if (!p_hwfn || !p_hwfn->mcp_info)
+ return NULL;
+ return &p_hwfn->mcp_info->link_input;
+}
+
+struct qed_mcp_link_state
+*qed_mcp_get_link_state(struct qed_hwfn *p_hwfn)
+{
+ if (!p_hwfn || !p_hwfn->mcp_info)
+ return NULL;
+ return &p_hwfn->mcp_info->link_output;
+}
+
+struct qed_mcp_link_capabilities
+*qed_mcp_get_link_capabilities(struct qed_hwfn *p_hwfn)
+{
+ if (!p_hwfn || !p_hwfn->mcp_info)
+ return NULL;
+ return &p_hwfn->mcp_info->link_capabilities;
+}
+
+int qed_mcp_drain(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_NIG_DRAIN, 100,
+ &resp, &param);
+
+ /* Wait for the drain to complete before returning */
+ msleep(120);
+
+ return rc;
+}
+
+int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *p_flash_size)
+{
+ u32 flash_size;
+
+ flash_size = qed_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4);
+ flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >>
+ MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT;
+ flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_SHIFT));
+
+ *p_flash_size = flash_size;
+
+ return 0;
+}
+
+int
+qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_mcp_drv_version *p_ver)
+{
+ int rc = 0;
+ u32 param = 0, reply = 0, i;
+
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized !\n");
+ return -EBUSY;
+ }
+
+ DRV_MB_WR(p_hwfn, p_ptt, union_data.drv_version.version,
+ p_ver->version);
+ /* Copy version string to shmem */
+ for (i = 0; i < (MCP_DRV_VER_STR_SIZE - 4) / 4; i++) {
+ DRV_MB_WR(p_hwfn, p_ptt,
+ union_data.drv_version.name[i * sizeof(u32)],
+ *(u32 *)&p_ver->name[i * sizeof(u32)]);
+ }
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_VERSION, 0, &reply,
+ &param);
+ if (rc) {
+ DP_ERR(p_hwfn, "MCP response failure, aborting\n");
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
new file mode 100644
index 000000000000..dbaae586b4a7
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -0,0 +1,369 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_MCP_H
+#define _QED_MCP_H
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include "qed_hsi.h"
+
+struct qed_mcp_link_speed_params {
+ bool autoneg;
+ u32 advertised_speeds; /* bitmask of DRV_SPEED_CAPABILITY */
+ u32 forced_speed; /* In Mb/s */
+};
+
+struct qed_mcp_link_pause_params {
+ bool autoneg;
+ bool forced_rx;
+ bool forced_tx;
+};
+
+struct qed_mcp_link_params {
+ struct qed_mcp_link_speed_params speed;
+ struct qed_mcp_link_pause_params pause;
+ u32 loopback_mode;
+};
+
+struct qed_mcp_link_capabilities {
+ u32 speed_capabilities;
+};
+
+struct qed_mcp_link_state {
+ bool link_up;
+
+ u32 speed; /* In Mb/s */
+ bool full_duplex;
+
+ bool an;
+ bool an_complete;
+ bool parallel_detection;
+ bool pfc_enabled;
+
+#define QED_LINK_PARTNER_SPEED_1G_HD BIT(0)
+#define QED_LINK_PARTNER_SPEED_1G_FD BIT(1)
+#define QED_LINK_PARTNER_SPEED_10G BIT(2)
+#define QED_LINK_PARTNER_SPEED_20G BIT(3)
+#define QED_LINK_PARTNER_SPEED_40G BIT(4)
+#define QED_LINK_PARTNER_SPEED_50G BIT(5)
+#define QED_LINK_PARTNER_SPEED_100G BIT(6)
+ u32 partner_adv_speed;
+
+ bool partner_tx_flow_ctrl_en;
+ bool partner_rx_flow_ctrl_en;
+
+#define QED_LINK_PARTNER_SYMMETRIC_PAUSE (1)
+#define QED_LINK_PARTNER_ASYMMETRIC_PAUSE (2)
+#define QED_LINK_PARTNER_BOTH_PAUSE (3)
+ u8 partner_adv_pause;
+
+ bool sfp_tx_fault;
+};
+
+struct qed_mcp_function_info {
+ u8 pause_on_host;
+
+ enum qed_pci_personality protocol;
+
+ u8 bandwidth_min;
+ u8 bandwidth_max;
+
+ u8 mac[ETH_ALEN];
+
+ u64 wwn_port;
+ u64 wwn_node;
+
+#define QED_MCP_VLAN_UNSET (0xffff)
+ u16 ovlan;
+};
+
+struct qed_mcp_nvm_common {
+ u32 offset;
+ u32 param;
+ u32 resp;
+ u32 cmd;
+};
+
+struct qed_mcp_drv_version {
+ u32 version;
+ u8 name[MCP_DRV_VER_STR_SIZE - 4];
+};
+
+/**
+ * @brief - returns the link params of the hw function
+ *
+ * @param p_hwfn
+ *
+ * @returns pointer to link params
+ */
+struct qed_mcp_link_params *qed_mcp_get_link_params(struct qed_hwfn *);
+
+/**
+ * @brief - return the link state of the hw function
+ *
+ * @param p_hwfn
+ *
+ * @returns pointer to link state
+ */
+struct qed_mcp_link_state *qed_mcp_get_link_state(struct qed_hwfn *);
+
+/**
+ * @brief - return the link capabilities of the hw function
+ *
+ * @param p_hwfn
+ *
+ * @returns pointer to link capabilities
+ */
+struct qed_mcp_link_capabilities
+ *qed_mcp_get_link_capabilities(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief Request the MFW to set the the link according to 'link_input'.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param b_up - raise link if `true'. Reset link if `false'.
+ *
+ * @return int
+ */
+int qed_mcp_set_link(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ bool b_up);
+
+/**
+ * @brief Get the management firmware version value
+ *
+ * @param cdev - qed dev pointer
+ * @param mfw_ver - mfw version value
+ *
+ * @return int - 0 - operation was successul.
+ */
+int qed_mcp_get_mfw_ver(struct qed_dev *cdev,
+ u32 *mfw_ver);
+
+/**
+ * @brief Get media type value of the port.
+ *
+ * @param cdev - qed dev pointer
+ * @param mfw_ver - media type value
+ *
+ * @return int -
+ * 0 - Operation was successul.
+ * -EBUSY - Operation failed
+ */
+int qed_mcp_get_media_type(struct qed_dev *cdev,
+ u32 *media_type);
+
+/**
+ * @brief General function for sending commands to the MCP
+ * mailbox. It acquire mutex lock for the entire
+ * operation, from sending the request until the MCP
+ * response. Waiting for MCP response will be checked up
+ * to 5 seconds every 5ms.
+ *
+ * @param p_hwfn - hw function
+ * @param p_ptt - PTT required for register access
+ * @param cmd - command to be sent to the MCP.
+ * @param param - Optional param
+ * @param o_mcp_resp - The MCP response code (exclude sequence).
+ * @param o_mcp_param- Optional parameter provided by the MCP
+ * response
+ * @return int - 0 - operation
+ * was successul.
+ */
+int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 cmd,
+ u32 param,
+ u32 *o_mcp_resp,
+ u32 *o_mcp_param);
+
+/**
+ * @brief - drains the nig, allowing completion to pass in case of pauses.
+ * (Should be called only from sleepable context)
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+int qed_mcp_drain(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief Get the flash size value
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param p_flash_size - flash size in bytes to be filled.
+ *
+ * @return int - 0 - operation was successul.
+ */
+int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *p_flash_size);
+
+/**
+ * @brief Send driver version to MFW
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param version - Version value
+ * @param name - Protocol driver name
+ *
+ * @return int - 0 - operation was successul.
+ */
+int
+qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_mcp_drv_version *p_ver);
+
+/* Using hwfn number (and not pf_num) is required since in CMT mode,
+ * same pf_num may be used by two different hwfn
+ * TODO - this shouldn't really be in .h file, but until all fields
+ * required during hw-init will be placed in their correct place in shmem
+ * we need it in qed_dev.c [for readin the nvram reflection in shmem].
+ */
+#define MCP_PF_ID_BY_REL(p_hwfn, rel_pfid) (QED_IS_BB((p_hwfn)->cdev) ? \
+ ((rel_pfid) | \
+ ((p_hwfn)->abs_pf_id & 1) << 3) : \
+ rel_pfid)
+#define MCP_PF_ID(p_hwfn) MCP_PF_ID_BY_REL(p_hwfn, (p_hwfn)->rel_pf_id)
+
+/* TODO - this is only correct as long as only BB is supported, and
+ * no port-swapping is implemented; Afterwards we'll need to fix it.
+ */
+#define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \
+ ((_p_hwfn)->cdev->num_ports_in_engines * 2))
+struct qed_mcp_info {
+ struct mutex mutex; /* MCP access lock */
+ u32 public_base;
+ u32 drv_mb_addr;
+ u32 mfw_mb_addr;
+ u32 port_addr;
+ u16 drv_mb_seq;
+ u16 drv_pulse_seq;
+ struct qed_mcp_link_params link_input;
+ struct qed_mcp_link_state link_output;
+ struct qed_mcp_link_capabilities link_capabilities;
+ struct qed_mcp_function_info func_info;
+ u8 *mfw_mb_cur;
+ u8 *mfw_mb_shadow;
+ u16 mfw_mb_length;
+ u16 mcp_hist;
+};
+
+/**
+ * @brief Initialize the interface with the MCP
+ *
+ * @param p_hwfn - HW func
+ * @param p_ptt - PTT required for register access
+ *
+ * @return int
+ */
+int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief Initialize the port interface with the MCP
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * Can only be called after `num_ports_in_engines' is set
+ */
+void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+/**
+ * @brief Releases resources allocated during the init process.
+ *
+ * @param p_hwfn - HW func
+ * @param p_ptt - PTT required for register access
+ *
+ * @return int
+ */
+
+int qed_mcp_free(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief This function is called from the DPC context. After
+ * pointing PTT to the mfw mb, check for events sent by the MCP
+ * to the driver and ack them. In case a critical event
+ * detected, it will be handled here, otherwise the work will be
+ * queued to a sleepable work-queue.
+ *
+ * @param p_hwfn - HW function
+ * @param p_ptt - PTT required for register access
+ * @return int - 0 - operation
+ * was successul.
+ */
+int qed_mcp_handle_events(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief Sends a LOAD_REQ to the MFW, and in case operation
+ * succeed, returns whether this PF is the first on the
+ * chip/engine/port or function. This function should be
+ * called when driver is ready to accept MFW events after
+ * Storms initializations are done.
+ *
+ * @param p_hwfn - hw function
+ * @param p_ptt - PTT required for register access
+ * @param p_load_code - The MCP response param containing one
+ * of the following:
+ * FW_MSG_CODE_DRV_LOAD_ENGINE
+ * FW_MSG_CODE_DRV_LOAD_PORT
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION
+ * @return int -
+ * 0 - Operation was successul.
+ * -EBUSY - Operation failed
+ */
+int qed_mcp_load_req(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *p_load_code);
+
+/**
+ * @brief Read the MFW mailbox into Current buffer.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+void qed_mcp_read_mb(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief - calls during init to read shmem of all function-related info.
+ *
+ * @param p_hwfn
+ *
+ * @param return 0 upon success.
+ */
+int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief - Reset the MCP using mailbox command.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @param return 0 upon success.
+ */
+int qed_mcp_reset(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief indicates whether the MFW objects [under mcp_info] are accessible
+ *
+ * @param p_hwfn
+ *
+ * @return true iff MFW is running and mcp_info is initialized
+ */
+bool qed_mcp_is_init(struct qed_hwfn *p_hwfn);
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
new file mode 100644
index 000000000000..7a5ce5914ace
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
@@ -0,0 +1,366 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef REG_ADDR_H
+#define REG_ADDR_H
+
+#define CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE_SHIFT \
+ 0
+
+#define CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE ( \
+ 0xfff << 0)
+
+#define CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE_SHIFT \
+ 12
+
+#define CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE ( \
+ 0xfff << 12)
+
+#define CDU_REG_CID_ADDR_PARAMS_NCIB_SHIFT \
+ 24
+
+#define CDU_REG_CID_ADDR_PARAMS_NCIB ( \
+ 0xff << 24)
+
+#define XSDM_REG_OPERATION_GEN \
+ 0xf80408UL
+#define NIG_REG_RX_BRB_OUT_EN \
+ 0x500e18UL
+#define NIG_REG_STORM_OUT_EN \
+ 0x500e08UL
+#define PSWRQ2_REG_L2P_VALIDATE_VFID \
+ 0x240c50UL
+#define PGLUE_B_REG_USE_CLIENTID_IN_TAG \
+ 0x2aae04UL
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER \
+ 0x2aa16cUL
+#define BAR0_MAP_REG_MSDM_RAM \
+ 0x1d00000UL
+#define BAR0_MAP_REG_USDM_RAM \
+ 0x1d80000UL
+#define BAR0_MAP_REG_PSDM_RAM \
+ 0x1f00000UL
+#define BAR0_MAP_REG_TSDM_RAM \
+ 0x1c80000UL
+#define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \
+ 0x5011f4UL
+#define PRS_REG_SEARCH_TCP \
+ 0x1f0400UL
+#define PRS_REG_SEARCH_UDP \
+ 0x1f0404UL
+#define PRS_REG_SEARCH_FCOE \
+ 0x1f0408UL
+#define PRS_REG_SEARCH_ROCE \
+ 0x1f040cUL
+#define PRS_REG_SEARCH_OPENFLOW \
+ 0x1f0434UL
+#define TM_REG_PF_ENABLE_CONN \
+ 0x2c043cUL
+#define TM_REG_PF_ENABLE_TASK \
+ 0x2c0444UL
+#define TM_REG_PF_SCAN_ACTIVE_CONN \
+ 0x2c04fcUL
+#define TM_REG_PF_SCAN_ACTIVE_TASK \
+ 0x2c0500UL
+#define IGU_REG_LEADING_EDGE_LATCH \
+ 0x18082cUL
+#define IGU_REG_TRAILING_EDGE_LATCH \
+ 0x180830UL
+#define QM_REG_USG_CNT_PF_TX \
+ 0x2f2eacUL
+#define QM_REG_USG_CNT_PF_OTHER \
+ 0x2f2eb0UL
+#define DORQ_REG_PF_DB_ENABLE \
+ 0x100508UL
+#define QM_REG_PF_EN \
+ 0x2f2ea4UL
+#define TCFC_REG_STRONG_ENABLE_PF \
+ 0x2d0708UL
+#define CCFC_REG_STRONG_ENABLE_PF \
+ 0x2e0708UL
+#define PGLUE_B_REG_PGL_ADDR_88_F0 \
+ 0x2aa404UL
+#define PGLUE_B_REG_PGL_ADDR_8C_F0 \
+ 0x2aa408UL
+#define PGLUE_B_REG_PGL_ADDR_90_F0 \
+ 0x2aa40cUL
+#define PGLUE_B_REG_PGL_ADDR_94_F0 \
+ 0x2aa410UL
+#define PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR \
+ 0x2aa138UL
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ \
+ 0x2aa174UL
+#define MISC_REG_GEN_PURP_CR0 \
+ 0x008c80UL
+#define MCP_REG_SCRATCH \
+ 0xe20000UL
+#define CNIG_REG_NW_PORT_MODE_BB_B0 \
+ 0x218200UL
+#define MISCS_REG_CHIP_NUM \
+ 0x00976cUL
+#define MISCS_REG_CHIP_REV \
+ 0x009770UL
+#define MISCS_REG_CMT_ENABLED_FOR_PAIR \
+ 0x00971cUL
+#define MISCS_REG_CHIP_TEST_REG \
+ 0x009778UL
+#define MISCS_REG_CHIP_METAL \
+ 0x009774UL
+#define BRB_REG_HEADER_SIZE \
+ 0x340804UL
+#define BTB_REG_HEADER_SIZE \
+ 0xdb0804UL
+#define CAU_REG_LONG_TIMEOUT_THRESHOLD \
+ 0x1c0708UL
+#define CCFC_REG_ACTIVITY_COUNTER \
+ 0x2e8800UL
+#define CDU_REG_CID_ADDR_PARAMS \
+ 0x580900UL
+#define DBG_REG_CLIENT_ENABLE \
+ 0x010004UL
+#define DMAE_REG_INIT \
+ 0x00c000UL
+#define DORQ_REG_IFEN \
+ 0x100040UL
+#define GRC_REG_TIMEOUT_EN \
+ 0x050404UL
+#define IGU_REG_BLOCK_CONFIGURATION \
+ 0x180040UL
+#define MCM_REG_INIT \
+ 0x1200000UL
+#define MCP2_REG_DBG_DWORD_ENABLE \
+ 0x052404UL
+#define MISC_REG_PORT_MODE \
+ 0x008c00UL
+#define MISCS_REG_CLK_100G_MODE \
+ 0x009070UL
+#define MSDM_REG_ENABLE_IN1 \
+ 0xfc0004UL
+#define MSEM_REG_ENABLE_IN \
+ 0x1800004UL
+#define NIG_REG_CM_HDR \
+ 0x500840UL
+#define NCSI_REG_CONFIG \
+ 0x040200UL
+#define PBF_REG_INIT \
+ 0xd80000UL
+#define PTU_REG_ATC_INIT_ARRAY \
+ 0x560000UL
+#define PCM_REG_INIT \
+ 0x1100000UL
+#define PGLUE_B_REG_ADMIN_PER_PF_REGION \
+ 0x2a9000UL
+#define PRM_REG_DISABLE_PRM \
+ 0x230000UL
+#define PRS_REG_SOFT_RST \
+ 0x1f0000UL
+#define PSDM_REG_ENABLE_IN1 \
+ 0xfa0004UL
+#define PSEM_REG_ENABLE_IN \
+ 0x1600004UL
+#define PSWRQ_REG_DBG_SELECT \
+ 0x280020UL
+#define PSWRQ2_REG_CDUT_P_SIZE \
+ 0x24000cUL
+#define PSWHST_REG_DISCARD_INTERNAL_WRITES \
+ 0x2a0040UL
+#define PSWHST2_REG_DBGSYN_ALMOST_FULL_THR \
+ 0x29e050UL
+#define PSWRD_REG_DBG_SELECT \
+ 0x29c040UL
+#define PSWRD2_REG_CONF11 \
+ 0x29d064UL
+#define PSWWR_REG_USDM_FULL_TH \
+ 0x29a040UL
+#define PSWWR2_REG_CDU_FULL_TH2 \
+ 0x29b040UL
+#define QM_REG_MAXPQSIZE_0 \
+ 0x2f0434UL
+#define RSS_REG_RSS_INIT_EN \
+ 0x238804UL
+#define RDIF_REG_STOP_ON_ERROR \
+ 0x300040UL
+#define SRC_REG_SOFT_RST \
+ 0x23874cUL
+#define TCFC_REG_ACTIVITY_COUNTER \
+ 0x2d8800UL
+#define TCM_REG_INIT \
+ 0x1180000UL
+#define TM_REG_PXP_READ_DATA_FIFO_INIT \
+ 0x2c0014UL
+#define TSDM_REG_ENABLE_IN1 \
+ 0xfb0004UL
+#define TSEM_REG_ENABLE_IN \
+ 0x1700004UL
+#define TDIF_REG_STOP_ON_ERROR \
+ 0x310040UL
+#define UCM_REG_INIT \
+ 0x1280000UL
+#define UMAC_REG_IPG_HD_BKP_CNTL_BB_B0 \
+ 0x051004UL
+#define USDM_REG_ENABLE_IN1 \
+ 0xfd0004UL
+#define USEM_REG_ENABLE_IN \
+ 0x1900004UL
+#define XCM_REG_INIT \
+ 0x1000000UL
+#define XSDM_REG_ENABLE_IN1 \
+ 0xf80004UL
+#define XSEM_REG_ENABLE_IN \
+ 0x1400004UL
+#define YCM_REG_INIT \
+ 0x1080000UL
+#define YSDM_REG_ENABLE_IN1 \
+ 0xf90004UL
+#define YSEM_REG_ENABLE_IN \
+ 0x1500004UL
+#define XYLD_REG_SCBD_STRICT_PRIO \
+ 0x4c0000UL
+#define TMLD_REG_SCBD_STRICT_PRIO \
+ 0x4d0000UL
+#define MULD_REG_SCBD_STRICT_PRIO \
+ 0x4e0000UL
+#define YULD_REG_SCBD_STRICT_PRIO \
+ 0x4c8000UL
+#define MISC_REG_SHARED_MEM_ADDR \
+ 0x008c20UL
+#define DMAE_REG_GO_C0 \
+ 0x00c048UL
+#define DMAE_REG_GO_C1 \
+ 0x00c04cUL
+#define DMAE_REG_GO_C2 \
+ 0x00c050UL
+#define DMAE_REG_GO_C3 \
+ 0x00c054UL
+#define DMAE_REG_GO_C4 \
+ 0x00c058UL
+#define DMAE_REG_GO_C5 \
+ 0x00c05cUL
+#define DMAE_REG_GO_C6 \
+ 0x00c060UL
+#define DMAE_REG_GO_C7 \
+ 0x00c064UL
+#define DMAE_REG_GO_C8 \
+ 0x00c068UL
+#define DMAE_REG_GO_C9 \
+ 0x00c06cUL
+#define DMAE_REG_GO_C10 \
+ 0x00c070UL
+#define DMAE_REG_GO_C11 \
+ 0x00c074UL
+#define DMAE_REG_GO_C12 \
+ 0x00c078UL
+#define DMAE_REG_GO_C13 \
+ 0x00c07cUL
+#define DMAE_REG_GO_C14 \
+ 0x00c080UL
+#define DMAE_REG_GO_C15 \
+ 0x00c084UL
+#define DMAE_REG_GO_C16 \
+ 0x00c088UL
+#define DMAE_REG_GO_C17 \
+ 0x00c08cUL
+#define DMAE_REG_GO_C18 \
+ 0x00c090UL
+#define DMAE_REG_GO_C19 \
+ 0x00c094UL
+#define DMAE_REG_GO_C20 \
+ 0x00c098UL
+#define DMAE_REG_GO_C21 \
+ 0x00c09cUL
+#define DMAE_REG_GO_C22 \
+ 0x00c0a0UL
+#define DMAE_REG_GO_C23 \
+ 0x00c0a4UL
+#define DMAE_REG_GO_C24 \
+ 0x00c0a8UL
+#define DMAE_REG_GO_C25 \
+ 0x00c0acUL
+#define DMAE_REG_GO_C26 \
+ 0x00c0b0UL
+#define DMAE_REG_GO_C27 \
+ 0x00c0b4UL
+#define DMAE_REG_GO_C28 \
+ 0x00c0b8UL
+#define DMAE_REG_GO_C29 \
+ 0x00c0bcUL
+#define DMAE_REG_GO_C30 \
+ 0x00c0c0UL
+#define DMAE_REG_GO_C31 \
+ 0x00c0c4UL
+#define DMAE_REG_CMD_MEM \
+ 0x00c800UL
+#define QM_REG_MAXPQSIZETXSEL_0 \
+ 0x2f0440UL
+#define QM_REG_SDMCMDREADY \
+ 0x2f1e10UL
+#define QM_REG_SDMCMDADDR \
+ 0x2f1e04UL
+#define QM_REG_SDMCMDDATALSB \
+ 0x2f1e08UL
+#define QM_REG_SDMCMDDATAMSB \
+ 0x2f1e0cUL
+#define QM_REG_SDMCMDGO \
+ 0x2f1e14UL
+#define QM_REG_RLPFCRD \
+ 0x2f4d80UL
+#define QM_REG_RLPFINCVAL \
+ 0x2f4c80UL
+#define QM_REG_RLGLBLCRD \
+ 0x2f4400UL
+#define QM_REG_RLGLBLINCVAL \
+ 0x2f3400UL
+#define IGU_REG_ATTENTION_ENABLE \
+ 0x18083cUL
+#define IGU_REG_ATTN_MSG_ADDR_L \
+ 0x180820UL
+#define IGU_REG_ATTN_MSG_ADDR_H \
+ 0x180824UL
+#define MISC_REG_AEU_GENERAL_ATTN_0 \
+ 0x008400UL
+#define CAU_REG_SB_ADDR_MEMORY \
+ 0x1c8000UL
+#define CAU_REG_SB_VAR_MEMORY \
+ 0x1c6000UL
+#define CAU_REG_PI_MEMORY \
+ 0x1d0000UL
+#define IGU_REG_PF_CONFIGURATION \
+ 0x180800UL
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_0 \
+ 0x00849cUL
+#define MISC_REG_AEU_MASK_ATTN_IGU \
+ 0x008494UL
+#define IGU_REG_CLEANUP_STATUS_0 \
+ 0x180980UL
+#define IGU_REG_CLEANUP_STATUS_1 \
+ 0x180a00UL
+#define IGU_REG_CLEANUP_STATUS_2 \
+ 0x180a80UL
+#define IGU_REG_CLEANUP_STATUS_3 \
+ 0x180b00UL
+#define IGU_REG_CLEANUP_STATUS_4 \
+ 0x180b80UL
+#define IGU_REG_COMMAND_REG_32LSB_DATA \
+ 0x180840UL
+#define IGU_REG_COMMAND_REG_CTRL \
+ 0x180848UL
+#define IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN ( \
+ 0x1 << 1)
+#define IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN ( \
+ 0x1 << 0)
+#define IGU_REG_MAPPING_MEMORY \
+ 0x184000UL
+#define MISCS_REG_GENERIC_POR_0 \
+ 0x0096d4UL
+#define MCP_REG_NVM_CFG4 \
+ 0xe0642cUL
+#define MCP_REG_NVM_CFG4_FLASH_SIZE ( \
+ 0x7 << 0)
+#define MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT \
+ 0
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h
new file mode 100644
index 000000000000..31a1f1eb4f56
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -0,0 +1,360 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#ifndef _QED_SP_H
+#define _QED_SP_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/qed/qed_chain.h>
+#include "qed.h"
+#include "qed_hsi.h"
+
+enum spq_mode {
+ QED_SPQ_MODE_BLOCK, /* Client will poll a designated mem. address */
+ QED_SPQ_MODE_CB, /* Client supplies a callback */
+ QED_SPQ_MODE_EBLOCK, /* QED should block until completion */
+};
+
+struct qed_spq_comp_cb {
+ void (*function)(struct qed_hwfn *,
+ void *,
+ union event_ring_data *,
+ u8 fw_return_code);
+ void *cookie;
+};
+
+/**
+ * @brief qed_eth_cqe_completion - handles the completion of a
+ * ramrod on the cqe ring
+ *
+ * @param p_hwfn
+ * @param cqe
+ *
+ * @return int
+ */
+int qed_eth_cqe_completion(struct qed_hwfn *p_hwfn,
+ struct eth_slow_path_rx_cqe *cqe);
+
+/**
+ * @file
+ *
+ * QED Slow-hwfn queue interface
+ */
+
+union ramrod_data {
+ struct pf_start_ramrod_data pf_start;
+ struct rx_queue_start_ramrod_data rx_queue_start;
+ struct rx_queue_update_ramrod_data rx_queue_update;
+ struct rx_queue_stop_ramrod_data rx_queue_stop;
+ struct tx_queue_start_ramrod_data tx_queue_start;
+ struct tx_queue_stop_ramrod_data tx_queue_stop;
+ struct vport_start_ramrod_data vport_start;
+ struct vport_stop_ramrod_data vport_stop;
+ struct vport_update_ramrod_data vport_update;
+ struct vport_filter_update_ramrod_data vport_filter_update;
+};
+
+#define EQ_MAX_CREDIT 0xffffffff
+
+enum spq_priority {
+ QED_SPQ_PRIORITY_NORMAL,
+ QED_SPQ_PRIORITY_HIGH,
+};
+
+union qed_spq_req_comp {
+ struct qed_spq_comp_cb cb;
+ u64 *done_addr;
+};
+
+struct qed_spq_comp_done {
+ u64 done;
+ u8 fw_return_code;
+};
+
+struct qed_spq_entry {
+ struct list_head list;
+
+ u8 flags;
+
+ /* HSI slow path element */
+ struct slow_path_element elem;
+
+ union ramrod_data ramrod;
+
+ enum spq_priority priority;
+
+ /* pending queue for this entry */
+ struct list_head *queue;
+
+ enum spq_mode comp_mode;
+ struct qed_spq_comp_cb comp_cb;
+ struct qed_spq_comp_done comp_done; /* SPQ_MODE_EBLOCK */
+};
+
+struct qed_eq {
+ struct qed_chain chain;
+ u8 eq_sb_index; /* index within the SB */
+ __le16 *p_fw_cons; /* ptr to index value */
+};
+
+struct qed_consq {
+ struct qed_chain chain;
+};
+
+struct qed_spq {
+ spinlock_t lock; /* SPQ lock */
+
+ struct list_head unlimited_pending;
+ struct list_head pending;
+ struct list_head completion_pending;
+ struct list_head free_pool;
+
+ struct qed_chain chain;
+
+ /* allocated dma-able memory for spq entries (+ramrod data) */
+ dma_addr_t p_phys;
+ struct qed_spq_entry *p_virt;
+
+ /* Used as index for completions (returns on EQ by FW) */
+ u16 echo_idx;
+
+ /* Statistics */
+ u32 unlimited_pending_count;
+ u32 normal_count;
+ u32 high_count;
+ u32 comp_sent_count;
+ u32 comp_count;
+
+ u32 cid;
+};
+
+/**
+ * @brief qed_spq_post - Posts a Slow hwfn request to FW, or lacking that
+ * Pends it to the future list.
+ *
+ * @param p_hwfn
+ * @param p_req
+ *
+ * @return int
+ */
+int qed_spq_post(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *fw_return_code);
+
+/**
+ * @brief qed_spq_allocate - Alloocates & initializes the SPQ and EQ.
+ *
+ * @param p_hwfn
+ *
+ * @return int
+ */
+int qed_spq_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_spq_setup - Reset the SPQ to its start state.
+ *
+ * @param p_hwfn
+ */
+void qed_spq_setup(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_spq_deallocate - Deallocates the given SPQ struct.
+ *
+ * @param p_hwfn
+ */
+void qed_spq_free(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_spq_get_entry - Obtain an entrry from the spq
+ * free pool list.
+ *
+ *
+ *
+ * @param p_hwfn
+ * @param pp_ent
+ *
+ * @return int
+ */
+int
+qed_spq_get_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry **pp_ent);
+
+/**
+ * @brief qed_spq_return_entry - Return an entry to spq free
+ * pool list
+ *
+ * @param p_hwfn
+ * @param p_ent
+ */
+void qed_spq_return_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent);
+/**
+ * @brief qed_eq_allocate - Allocates & initializes an EQ struct
+ *
+ * @param p_hwfn
+ * @param num_elem number of elements in the eq
+ *
+ * @return struct qed_eq* - a newly allocated structure; NULL upon error.
+ */
+struct qed_eq *qed_eq_alloc(struct qed_hwfn *p_hwfn,
+ u16 num_elem);
+
+/**
+ * @brief qed_eq_setup - Reset the SPQ to its start state.
+ *
+ * @param p_hwfn
+ * @param p_eq
+ */
+void qed_eq_setup(struct qed_hwfn *p_hwfn,
+ struct qed_eq *p_eq);
+
+/**
+ * @brief qed_eq_deallocate - deallocates the given EQ struct.
+ *
+ * @param p_hwfn
+ * @param p_eq
+ */
+void qed_eq_free(struct qed_hwfn *p_hwfn,
+ struct qed_eq *p_eq);
+
+/**
+ * @brief qed_eq_prod_update - update the FW with default EQ producer
+ *
+ * @param p_hwfn
+ * @param prod
+ */
+void qed_eq_prod_update(struct qed_hwfn *p_hwfn,
+ u16 prod);
+
+/**
+ * @brief qed_eq_completion - Completes currently pending EQ elements
+ *
+ * @param p_hwfn
+ * @param cookie
+ *
+ * @return int
+ */
+int qed_eq_completion(struct qed_hwfn *p_hwfn,
+ void *cookie);
+
+/**
+ * @brief qed_spq_completion - Completes a single event
+ *
+ * @param p_hwfn
+ * @param echo - echo value from cookie (used for determining completion)
+ * @param p_data - data from cookie (used in callback function if applicable)
+ *
+ * @return int
+ */
+int qed_spq_completion(struct qed_hwfn *p_hwfn,
+ __le16 echo,
+ u8 fw_return_code,
+ union event_ring_data *p_data);
+
+/**
+ * @brief qed_spq_get_cid - Given p_hwfn, return cid for the hwfn's SPQ
+ *
+ * @param p_hwfn
+ *
+ * @return u32 - SPQ CID
+ */
+u32 qed_spq_get_cid(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_consq_alloc - Allocates & initializes an ConsQ
+ * struct
+ *
+ * @param p_hwfn
+ *
+ * @return struct qed_eq* - a newly allocated structure; NULL upon error.
+ */
+struct qed_consq *qed_consq_alloc(struct qed_hwfn *p_hwfn);
+
+/**
+ * @brief qed_consq_setup - Reset the ConsQ to its start
+ * state.
+ *
+ * @param p_hwfn
+ * @param p_eq
+ */
+void qed_consq_setup(struct qed_hwfn *p_hwfn,
+ struct qed_consq *p_consq);
+
+/**
+ * @brief qed_consq_free - deallocates the given ConsQ struct.
+ *
+ * @param p_hwfn
+ * @param p_eq
+ */
+void qed_consq_free(struct qed_hwfn *p_hwfn,
+ struct qed_consq *p_consq);
+
+/**
+ * @file
+ *
+ * @brief Slow-hwfn low-level commands (Ramrods) function definitions.
+ */
+
+#define QED_SP_EQ_COMPLETION 0x01
+#define QED_SP_CQE_COMPLETION 0x02
+
+struct qed_sp_init_request_params {
+ size_t ramrod_data_size;
+ enum spq_mode comp_mode;
+ struct qed_spq_comp_cb *p_comp_data;
+};
+
+int qed_sp_init_request(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry **pp_ent,
+ u32 cid,
+ u16 opaque_fid,
+ u8 cmd,
+ u8 protocol,
+ struct qed_sp_init_request_params *p_params);
+
+/**
+ * @brief qed_sp_pf_start - PF Function Start Ramrod
+ *
+ * This ramrod is sent to initialize a physical function (PF). It will
+ * configure the function related parameters and write its completion to the
+ * event ring specified in the parameters.
+ *
+ * Ramrods complete on the common event ring for the PF. This ring is
+ * allocated by the driver on host memory and its parameters are written
+ * to the internal RAM of the UStorm by the Function Start Ramrod.
+ *
+ * @param p_hwfn
+ * @param mode
+ *
+ * @return int
+ */
+
+int qed_sp_pf_start(struct qed_hwfn *p_hwfn,
+ enum mf_mode mode);
+
+/**
+ * @brief qed_sp_pf_stop - PF Function Stop Ramrod
+ *
+ * This ramrod is sent to close a Physical Function (PF). It is the last ramrod
+ * sent and the last completion written to the PFs Event Ring. This ramrod also
+ * deletes the context for the Slowhwfn connection on this PF.
+ *
+ * @note Not required for first packet.
+ *
+ * @param p_hwfn
+ *
+ * @return int
+ */
+
+int qed_sp_pf_stop(struct qed_hwfn *p_hwfn);
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
new file mode 100644
index 000000000000..6f7879136633
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
@@ -0,0 +1,170 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include "qed.h"
+#include <linux/qed/qed_chain.h>
+#include "qed_cxt.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_int.h"
+#include "qed_reg_addr.h"
+#include "qed_sp.h"
+
+int qed_sp_init_request(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry **pp_ent,
+ u32 cid,
+ u16 opaque_fid,
+ u8 cmd,
+ u8 protocol,
+ struct qed_sp_init_request_params *p_params)
+{
+ int rc = -EINVAL;
+ struct qed_spq_entry *p_ent = NULL;
+ u32 opaque_cid = opaque_fid << 16 | cid;
+
+ if (!pp_ent)
+ return -ENOMEM;
+
+ rc = qed_spq_get_entry(p_hwfn, pp_ent);
+
+ if (rc != 0)
+ return rc;
+
+ p_ent = *pp_ent;
+
+ p_ent->elem.hdr.cid = cpu_to_le32(opaque_cid);
+ p_ent->elem.hdr.cmd_id = cmd;
+ p_ent->elem.hdr.protocol_id = protocol;
+
+ p_ent->priority = QED_SPQ_PRIORITY_NORMAL;
+ p_ent->comp_mode = p_params->comp_mode;
+ p_ent->comp_done.done = 0;
+
+ switch (p_ent->comp_mode) {
+ case QED_SPQ_MODE_EBLOCK:
+ p_ent->comp_cb.cookie = &p_ent->comp_done;
+ break;
+
+ case QED_SPQ_MODE_BLOCK:
+ if (!p_params->p_comp_data)
+ return -EINVAL;
+
+ p_ent->comp_cb.cookie = p_params->p_comp_data->cookie;
+ break;
+
+ case QED_SPQ_MODE_CB:
+ if (!p_params->p_comp_data)
+ p_ent->comp_cb.function = NULL;
+ else
+ p_ent->comp_cb = *p_params->p_comp_data;
+ break;
+
+ default:
+ DP_NOTICE(p_hwfn, "Unknown SPQE completion mode %d\n",
+ p_ent->comp_mode);
+ return -EINVAL;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+ "Initialized: CID %08x cmd %02x protocol %02x data_addr %lu comp_mode [%s]\n",
+ opaque_cid, cmd, protocol,
+ (unsigned long)&p_ent->ramrod,
+ D_TRINE(p_ent->comp_mode, QED_SPQ_MODE_EBLOCK,
+ QED_SPQ_MODE_BLOCK, "MODE_EBLOCK", "MODE_BLOCK",
+ "MODE_CB"));
+ if (p_params->ramrod_data_size)
+ memset(&p_ent->ramrod, 0, p_params->ramrod_data_size);
+
+ return 0;
+}
+
+int qed_sp_pf_start(struct qed_hwfn *p_hwfn,
+ enum mf_mode mode)
+{
+ struct qed_sp_init_request_params params;
+ struct pf_start_ramrod_data *p_ramrod = NULL;
+ u16 sb = qed_int_get_sp_sb_id(p_hwfn);
+ u8 sb_index = p_hwfn->p_eq->eq_sb_index;
+ struct qed_spq_entry *p_ent = NULL;
+ int rc = -EINVAL;
+
+ /* update initial eq producer */
+ qed_eq_prod_update(p_hwfn,
+ qed_chain_get_prod_idx(&p_hwfn->p_eq->chain));
+
+ memset(&params, 0, sizeof(params));
+ params.ramrod_data_size = sizeof(*p_ramrod);
+ params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn,
+ &p_ent,
+ qed_spq_get_cid(p_hwfn),
+ p_hwfn->hw_info.opaque_fid,
+ COMMON_RAMROD_PF_START,
+ PROTOCOLID_COMMON,
+ &params);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.pf_start;
+
+ p_ramrod->event_ring_sb_id = cpu_to_le16(sb);
+ p_ramrod->event_ring_sb_index = sb_index;
+ p_ramrod->path_id = QED_PATH_ID(p_hwfn);
+ p_ramrod->dont_log_ramrods = 0;
+ p_ramrod->log_type_mask = cpu_to_le16(0xf);
+ p_ramrod->mf_mode = mode;
+ p_ramrod->outer_tag = p_hwfn->hw_info.ovlan;
+
+ /* Place EQ address in RAMROD */
+ p_ramrod->event_ring_pbl_addr.hi =
+ DMA_HI_LE(p_hwfn->p_eq->chain.pbl.p_phys_table);
+ p_ramrod->event_ring_pbl_addr.lo =
+ DMA_LO_LE(p_hwfn->p_eq->chain.pbl.p_phys_table);
+ p_ramrod->event_ring_num_pages = (u8)p_hwfn->p_eq->chain.page_cnt;
+
+ p_ramrod->consolid_q_pbl_addr.hi =
+ DMA_HI_LE(p_hwfn->p_consq->chain.pbl.p_phys_table);
+ p_ramrod->consolid_q_pbl_addr.lo =
+ DMA_LO_LE(p_hwfn->p_consq->chain.pbl.p_phys_table);
+
+ p_hwfn->hw_info.personality = PERSONALITY_ETH;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+ "Setting event_ring_sb [id %04x index %02x], mf [%s] outer_tag [%d]\n",
+ sb, sb_index,
+ (p_ramrod->mf_mode == SF) ? "SF" : "Multi-Pf",
+ p_ramrod->outer_tag);
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+int qed_sp_pf_stop(struct qed_hwfn *p_hwfn)
+{
+ struct qed_sp_init_request_params params;
+ struct qed_spq_entry *p_ent = NULL;
+ int rc = -EINVAL;
+
+ memset(&params, 0, sizeof(params));
+ params.comp_mode = QED_SPQ_MODE_EBLOCK;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent, qed_spq_get_cid(p_hwfn),
+ p_hwfn->hw_info.opaque_fid,
+ COMMON_RAMROD_PF_STOP, PROTOCOLID_COMMON,
+ &params);
+ if (rc)
+ return rc;
+
+ 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
new file mode 100644
index 000000000000..7c0b8459666e
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -0,0 +1,860 @@
+/* QLogic qed NIC Driver
+ * Copyright (c) 2015 QLogic Corporation
+ *
+ * This software is available 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.
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include "qed.h"
+#include "qed_cxt.h"
+#include "qed_dev_api.h"
+#include "qed_hsi.h"
+#include "qed_hw.h"
+#include "qed_int.h"
+#include "qed_mcp.h"
+#include "qed_reg_addr.h"
+#include "qed_sp.h"
+
+/***************************************************************************
+* Structures & Definitions
+***************************************************************************/
+
+#define SPQ_HIGH_PRI_RESERVE_DEFAULT (1)
+#define SPQ_BLOCK_SLEEP_LENGTH (1000)
+
+/***************************************************************************
+* Blocking Imp. (BLOCK/EBLOCK mode)
+***************************************************************************/
+static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn,
+ void *cookie,
+ union event_ring_data *data,
+ u8 fw_return_code)
+{
+ struct qed_spq_comp_done *comp_done;
+
+ comp_done = (struct qed_spq_comp_done *)cookie;
+
+ comp_done->done = 0x1;
+ comp_done->fw_return_code = fw_return_code;
+
+ /* make update visible to waiting thread */
+ smp_wmb();
+}
+
+static int qed_spq_block(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *p_fw_ret)
+{
+ int sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
+ struct qed_spq_comp_done *comp_done;
+ int rc;
+
+ comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
+ while (sleep_count) {
+ /* validate we receive completion update */
+ smp_rmb();
+ if (comp_done->done == 1) {
+ if (p_fw_ret)
+ *p_fw_ret = comp_done->fw_return_code;
+ return 0;
+ }
+ usleep_range(5000, 10000);
+ sleep_count--;
+ }
+
+ DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n");
+ rc = qed_mcp_drain(p_hwfn, p_hwfn->p_main_ptt);
+ if (rc != 0)
+ DP_NOTICE(p_hwfn, "MCP drain failed\n");
+
+ /* Retry after drain */
+ sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
+ while (sleep_count) {
+ /* validate we receive completion update */
+ smp_rmb();
+ if (comp_done->done == 1) {
+ if (p_fw_ret)
+ *p_fw_ret = comp_done->fw_return_code;
+ return 0;
+ }
+ usleep_range(5000, 10000);
+ sleep_count--;
+ }
+
+ if (comp_done->done == 1) {
+ if (p_fw_ret)
+ *p_fw_ret = comp_done->fw_return_code;
+ return 0;
+ }
+
+ DP_NOTICE(p_hwfn, "Ramrod is stuck, MCP drain failed\n");
+
+ return -EBUSY;
+}
+
+/***************************************************************************
+* SPQ entries inner API
+***************************************************************************/
+static int
+qed_spq_fill_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent)
+{
+ p_ent->elem.hdr.echo = 0;
+ p_hwfn->p_spq->echo_idx++;
+ p_ent->flags = 0;
+
+ switch (p_ent->comp_mode) {
+ case QED_SPQ_MODE_EBLOCK:
+ case QED_SPQ_MODE_BLOCK:
+ p_ent->comp_cb.function = qed_spq_blocking_cb;
+ break;
+ case QED_SPQ_MODE_CB:
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unknown SPQE completion mode %d\n",
+ p_ent->comp_mode);
+ return -EINVAL;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+ "Ramrod header: [CID 0x%08x CMD 0x%02x protocol 0x%02x] Data pointer: [%08x:%08x] Completion Mode: %s\n",
+ p_ent->elem.hdr.cid,
+ p_ent->elem.hdr.cmd_id,
+ p_ent->elem.hdr.protocol_id,
+ p_ent->elem.data_ptr.hi,
+ p_ent->elem.data_ptr.lo,
+ D_TRINE(p_ent->comp_mode, QED_SPQ_MODE_EBLOCK,
+ QED_SPQ_MODE_BLOCK, "MODE_EBLOCK", "MODE_BLOCK",
+ "MODE_CB"));
+
+ return 0;
+}
+
+/***************************************************************************
+* HSI access
+***************************************************************************/
+static void qed_spq_hw_initialize(struct qed_hwfn *p_hwfn,
+ struct qed_spq *p_spq)
+{
+ u16 pq;
+ struct qed_cxt_info cxt_info;
+ struct core_conn_context *p_cxt;
+ union qed_qm_pq_params pq_params;
+ int rc;
+
+ cxt_info.iid = p_spq->cid;
+
+ rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info);
+
+ if (rc < 0) {
+ DP_NOTICE(p_hwfn, "Cannot find context info for cid=%d\n",
+ p_spq->cid);
+ return;
+ }
+
+ p_cxt = cxt_info.p_cxt;
+
+ SET_FIELD(p_cxt->xstorm_ag_context.flags10,
+ XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN, 1);
+ SET_FIELD(p_cxt->xstorm_ag_context.flags1,
+ XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE, 1);
+ SET_FIELD(p_cxt->xstorm_ag_context.flags9,
+ XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN, 1);
+
+ /* QM physical queue */
+ memset(&pq_params, 0, sizeof(pq_params));
+ pq_params.core.tc = LB_TC;
+ pq = qed_get_qm_pq(p_hwfn, PROTOCOLID_CORE, &pq_params);
+ p_cxt->xstorm_ag_context.physical_q0 = cpu_to_le16(pq);
+
+ p_cxt->xstorm_st_context.spq_base_lo =
+ DMA_LO_LE(p_spq->chain.p_phys_addr);
+ p_cxt->xstorm_st_context.spq_base_hi =
+ DMA_HI_LE(p_spq->chain.p_phys_addr);
+
+ p_cxt->xstorm_st_context.consolid_base_addr.lo =
+ DMA_LO_LE(p_hwfn->p_consq->chain.p_phys_addr);
+ p_cxt->xstorm_st_context.consolid_base_addr.hi =
+ DMA_HI_LE(p_hwfn->p_consq->chain.p_phys_addr);
+}
+
+static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
+ struct qed_spq *p_spq,
+ struct qed_spq_entry *p_ent)
+{
+ struct qed_chain *p_chain = &p_hwfn->p_spq->chain;
+ struct slow_path_element *elem;
+ struct core_db_data db;
+
+ elem = qed_chain_produce(p_chain);
+ if (!elem) {
+ DP_NOTICE(p_hwfn, "Failed to produce from SPQ chain\n");
+ return -EINVAL;
+ }
+
+ *elem = p_ent->elem; /* struct assignment */
+
+ /* send a doorbell on the slow hwfn session */
+ memset(&db, 0, sizeof(db));
+ SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+ SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
+ SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_SPQ_PROD_CMD);
+ db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
+ /* validate producer is up to-date */
+ rmb();
+
+ db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
+
+ /* do not reorder */
+ barrier();
+
+ DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *)&db);
+
+ /* make sure doorbell is rang */
+ mmiowb();
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+ "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x agg_params: %02x, prod: %04x\n",
+ qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY),
+ p_spq->cid, db.params, db.agg_flags,
+ qed_chain_get_prod_idx(p_chain));
+
+ return 0;
+}
+
+/***************************************************************************
+* Asynchronous events
+***************************************************************************/
+static int
+qed_async_event_completion(struct qed_hwfn *p_hwfn,
+ struct event_ring_entry *p_eqe)
+{
+ DP_NOTICE(p_hwfn,
+ "Unknown Async completion for protocol: %d\n",
+ p_eqe->protocol_id);
+ return -EINVAL;
+}
+
+/***************************************************************************
+* EQ API
+***************************************************************************/
+void qed_eq_prod_update(struct qed_hwfn *p_hwfn,
+ u16 prod)
+{
+ u32 addr = GTT_BAR0_MAP_REG_USDM_RAM +
+ USTORM_EQE_CONS_OFFSET(p_hwfn->rel_pf_id);
+
+ REG_WR16(p_hwfn, addr, prod);
+
+ /* keep prod updates ordered */
+ mmiowb();
+}
+
+int qed_eq_completion(struct qed_hwfn *p_hwfn,
+ void *cookie)
+
+{
+ struct qed_eq *p_eq = cookie;
+ struct qed_chain *p_chain = &p_eq->chain;
+ int rc = 0;
+
+ /* take a snapshot of the FW consumer */
+ u16 fw_cons_idx = le16_to_cpu(*p_eq->p_fw_cons);
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ, "fw_cons_idx %x\n", fw_cons_idx);
+
+ /* Need to guarantee the fw_cons index we use points to a usuable
+ * element (to comply with our chain), so our macros would comply
+ */
+ if ((fw_cons_idx & qed_chain_get_usable_per_page(p_chain)) ==
+ qed_chain_get_usable_per_page(p_chain))
+ fw_cons_idx += qed_chain_get_unusable_per_page(p_chain);
+
+ /* Complete current segment of eq entries */
+ while (fw_cons_idx != qed_chain_get_cons_idx(p_chain)) {
+ struct event_ring_entry *p_eqe = qed_chain_consume(p_chain);
+
+ if (!p_eqe) {
+ rc = -EINVAL;
+ break;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+ "op %x prot %x res0 %x echo %x fwret %x flags %x\n",
+ p_eqe->opcode,
+ p_eqe->protocol_id,
+ p_eqe->reserved0,
+ le16_to_cpu(p_eqe->echo),
+ p_eqe->fw_return_code,
+ p_eqe->flags);
+
+ if (GET_FIELD(p_eqe->flags, EVENT_RING_ENTRY_ASYNC)) {
+ if (qed_async_event_completion(p_hwfn, p_eqe))
+ rc = -EINVAL;
+ } else if (qed_spq_completion(p_hwfn,
+ p_eqe->echo,
+ p_eqe->fw_return_code,
+ &p_eqe->data)) {
+ rc = -EINVAL;
+ }
+
+ qed_chain_recycle_consumed(p_chain);
+ }
+
+ qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain));
+
+ return rc;
+}
+
+struct qed_eq *qed_eq_alloc(struct qed_hwfn *p_hwfn,
+ u16 num_elem)
+{
+ struct qed_eq *p_eq;
+
+ /* Allocate EQ struct */
+ p_eq = kzalloc(sizeof(*p_eq), GFP_ATOMIC);
+ if (!p_eq) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_eq'\n");
+ return NULL;
+ }
+
+ /* Allocate and initialize EQ chain*/
+ if (qed_chain_alloc(p_hwfn->cdev,
+ QED_CHAIN_USE_TO_PRODUCE,
+ QED_CHAIN_MODE_PBL,
+ num_elem,
+ sizeof(union event_ring_element),
+ &p_eq->chain)) {
+ DP_NOTICE(p_hwfn, "Failed to allocate eq chain\n");
+ goto eq_allocate_fail;
+ }
+
+ /* register EQ completion on the SP SB */
+ qed_int_register_cb(p_hwfn,
+ qed_eq_completion,
+ p_eq,
+ &p_eq->eq_sb_index,
+ &p_eq->p_fw_cons);
+
+ return p_eq;
+
+eq_allocate_fail:
+ qed_eq_free(p_hwfn, p_eq);
+ return NULL;
+}
+
+void qed_eq_setup(struct qed_hwfn *p_hwfn,
+ struct qed_eq *p_eq)
+{
+ qed_chain_reset(&p_eq->chain);
+}
+
+void qed_eq_free(struct qed_hwfn *p_hwfn,
+ struct qed_eq *p_eq)
+{
+ if (!p_eq)
+ return;
+ qed_chain_free(p_hwfn->cdev, &p_eq->chain);
+ kfree(p_eq);
+}
+
+/***************************************************************************
+* CQE API - manipulate EQ functionality
+***************************************************************************/
+static int qed_cqe_completion(
+ struct qed_hwfn *p_hwfn,
+ struct eth_slow_path_rx_cqe *cqe,
+ enum protocol_type protocol)
+{
+ /* @@@tmp - it's possible we'll eventually want to handle some
+ * actual commands that can arrive here, but for now this is only
+ * used to complete the ramrod using the echo value on the cqe
+ */
+ return qed_spq_completion(p_hwfn, cqe->echo, 0, NULL);
+}
+
+int qed_eth_cqe_completion(struct qed_hwfn *p_hwfn,
+ struct eth_slow_path_rx_cqe *cqe)
+{
+ int rc;
+
+ rc = qed_cqe_completion(p_hwfn, cqe, PROTOCOLID_ETH);
+ if (rc)
+ DP_NOTICE(p_hwfn,
+ "Failed to handle RXQ CQE [cmd 0x%02x]\n",
+ cqe->ramrod_cmd_id);
+
+ return rc;
+}
+
+/***************************************************************************
+* Slow hwfn Queue (spq)
+***************************************************************************/
+void qed_spq_setup(struct qed_hwfn *p_hwfn)
+{
+ struct qed_spq *p_spq = p_hwfn->p_spq;
+ struct qed_spq_entry *p_virt = NULL;
+ dma_addr_t p_phys = 0;
+ unsigned int i = 0;
+
+ INIT_LIST_HEAD(&p_spq->pending);
+ INIT_LIST_HEAD(&p_spq->completion_pending);
+ INIT_LIST_HEAD(&p_spq->free_pool);
+ INIT_LIST_HEAD(&p_spq->unlimited_pending);
+ spin_lock_init(&p_spq->lock);
+
+ /* SPQ empty pool */
+ p_phys = p_spq->p_phys + offsetof(struct qed_spq_entry, ramrod);
+ p_virt = p_spq->p_virt;
+
+ for (i = 0; i < p_spq->chain.capacity; i++) {
+ p_virt->elem.data_ptr.hi = DMA_HI_LE(p_phys);
+ p_virt->elem.data_ptr.lo = DMA_LO_LE(p_phys);
+
+ list_add_tail(&p_virt->list, &p_spq->free_pool);
+
+ p_virt++;
+ p_phys += sizeof(struct qed_spq_entry);
+ }
+
+ /* Statistics */
+ p_spq->normal_count = 0;
+ p_spq->comp_count = 0;
+ p_spq->comp_sent_count = 0;
+ p_spq->unlimited_pending_count = 0;
+ p_spq->echo_idx = 0;
+
+ /* SPQ cid, cannot fail */
+ qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid);
+ qed_spq_hw_initialize(p_hwfn, p_spq);
+
+ /* reset the chain itself */
+ qed_chain_reset(&p_spq->chain);
+}
+
+int qed_spq_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_spq *p_spq = NULL;
+ dma_addr_t p_phys = 0;
+ struct qed_spq_entry *p_virt = NULL;
+
+ /* SPQ struct */
+ p_spq =
+ kzalloc(sizeof(struct qed_spq), GFP_ATOMIC);
+ if (!p_spq) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_spq'\n");
+ return -ENOMEM;
+ }
+
+ /* SPQ ring */
+ if (qed_chain_alloc(p_hwfn->cdev,
+ QED_CHAIN_USE_TO_PRODUCE,
+ QED_CHAIN_MODE_SINGLE,
+ 0, /* N/A when the mode is SINGLE */
+ sizeof(struct slow_path_element),
+ &p_spq->chain)) {
+ DP_NOTICE(p_hwfn, "Failed to allocate spq chain\n");
+ goto spq_allocate_fail;
+ }
+
+ /* allocate and fill the SPQ elements (incl. ramrod data list) */
+ p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ p_spq->chain.capacity *
+ sizeof(struct qed_spq_entry),
+ &p_phys,
+ GFP_KERNEL);
+
+ if (!p_virt)
+ goto spq_allocate_fail;
+
+ p_spq->p_virt = p_virt;
+ p_spq->p_phys = p_phys;
+ p_hwfn->p_spq = p_spq;
+
+ return 0;
+
+spq_allocate_fail:
+ qed_chain_free(p_hwfn->cdev, &p_spq->chain);
+ kfree(p_spq);
+ return -ENOMEM;
+}
+
+void qed_spq_free(struct qed_hwfn *p_hwfn)
+{
+ struct qed_spq *p_spq = p_hwfn->p_spq;
+
+ if (!p_spq)
+ return;
+
+ if (p_spq->p_virt)
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ p_spq->chain.capacity *
+ sizeof(struct qed_spq_entry),
+ p_spq->p_virt,
+ p_spq->p_phys);
+
+ qed_chain_free(p_hwfn->cdev, &p_spq->chain);
+ ;
+ kfree(p_spq);
+}
+
+int
+qed_spq_get_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry **pp_ent)
+{
+ struct qed_spq *p_spq = p_hwfn->p_spq;
+ struct qed_spq_entry *p_ent = NULL;
+ int rc = 0;
+
+ spin_lock_bh(&p_spq->lock);
+
+ if (list_empty(&p_spq->free_pool)) {
+ p_ent = kzalloc(sizeof(*p_ent), GFP_ATOMIC);
+ if (!p_ent) {
+ rc = -ENOMEM;
+ goto out_unlock;
+ }
+ p_ent->queue = &p_spq->unlimited_pending;
+ } else {
+ p_ent = list_first_entry(&p_spq->free_pool,
+ struct qed_spq_entry,
+ list);
+ list_del(&p_ent->list);
+ p_ent->queue = &p_spq->pending;
+ }
+
+ *pp_ent = p_ent;
+
+out_unlock:
+ spin_unlock_bh(&p_spq->lock);
+ return rc;
+}
+
+/* Locked variant; Should be called while the SPQ lock is taken */
+static void __qed_spq_return_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent)
+{
+ list_add_tail(&p_ent->list, &p_hwfn->p_spq->free_pool);
+}
+
+void qed_spq_return_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent)
+{
+ spin_lock_bh(&p_hwfn->p_spq->lock);
+ __qed_spq_return_entry(p_hwfn, p_ent);
+ spin_unlock_bh(&p_hwfn->p_spq->lock);
+}
+
+/**
+ * @brief qed_spq_add_entry - adds a new entry to the pending
+ * list. Should be used while lock is being held.
+ *
+ * Addes an entry to the pending list is there is room (en empty
+ * element is available in the free_pool), or else places the
+ * entry in the unlimited_pending pool.
+ *
+ * @param p_hwfn
+ * @param p_ent
+ * @param priority
+ *
+ * @return int
+ */
+static int
+qed_spq_add_entry(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ enum spq_priority priority)
+{
+ struct qed_spq *p_spq = p_hwfn->p_spq;
+
+ if (p_ent->queue == &p_spq->unlimited_pending) {
+ struct qed_spq_entry *p_en2;
+
+ if (list_empty(&p_spq->free_pool)) {
+ list_add_tail(&p_ent->list, &p_spq->unlimited_pending);
+ p_spq->unlimited_pending_count++;
+
+ return 0;
+ }
+
+ p_en2 = list_first_entry(&p_spq->free_pool,
+ struct qed_spq_entry,
+ list);
+ list_del(&p_en2->list);
+
+ /* Strcut assignment */
+ *p_en2 = *p_ent;
+
+ kfree(p_ent);
+
+ p_ent = p_en2;
+ }
+
+ /* entry is to be placed in 'pending' queue */
+ switch (priority) {
+ case QED_SPQ_PRIORITY_NORMAL:
+ list_add_tail(&p_ent->list, &p_spq->pending);
+ p_spq->normal_count++;
+ break;
+ case QED_SPQ_PRIORITY_HIGH:
+ list_add(&p_ent->list, &p_spq->pending);
+ p_spq->high_count++;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+* Accessor
+***************************************************************************/
+u32 qed_spq_get_cid(struct qed_hwfn *p_hwfn)
+{
+ if (!p_hwfn->p_spq)
+ return 0xffffffff; /* illegal */
+ return p_hwfn->p_spq->cid;
+}
+
+/***************************************************************************
+* Posting new Ramrods
+***************************************************************************/
+static int qed_spq_post_list(struct qed_hwfn *p_hwfn,
+ struct list_head *head,
+ u32 keep_reserve)
+{
+ struct qed_spq *p_spq = p_hwfn->p_spq;
+ int rc;
+
+ while (qed_chain_get_elem_left(&p_spq->chain) > keep_reserve &&
+ !list_empty(head)) {
+ struct qed_spq_entry *p_ent =
+ list_first_entry(head, struct qed_spq_entry, list);
+ list_del(&p_ent->list);
+ list_add_tail(&p_ent->list, &p_spq->completion_pending);
+ p_spq->comp_sent_count++;
+
+ rc = qed_spq_hw_post(p_hwfn, p_spq, p_ent);
+ if (rc) {
+ list_del(&p_ent->list);
+ __qed_spq_return_entry(p_hwfn, p_ent);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static 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;
+
+ while (!list_empty(&p_spq->free_pool)) {
+ if (list_empty(&p_spq->unlimited_pending))
+ break;
+
+ p_ent = list_first_entry(&p_spq->unlimited_pending,
+ struct qed_spq_entry,
+ list);
+ if (!p_ent)
+ return -EINVAL;
+
+ list_del(&p_ent->list);
+
+ qed_spq_add_entry(p_hwfn, p_ent, p_ent->priority);
+ }
+
+ return qed_spq_post_list(p_hwfn, &p_spq->pending,
+ SPQ_HIGH_PRI_RESERVE_DEFAULT);
+}
+
+int qed_spq_post(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *fw_return_code)
+{
+ int rc = 0;
+ struct qed_spq *p_spq = p_hwfn ? p_hwfn->p_spq : NULL;
+ bool b_ret_ent = true;
+
+ if (!p_hwfn)
+ return -EINVAL;
+
+ if (!p_ent) {
+ DP_NOTICE(p_hwfn, "Got a NULL pointer\n");
+ return -EINVAL;
+ }
+
+ /* Complete the entry */
+ rc = qed_spq_fill_entry(p_hwfn, p_ent);
+
+ spin_lock_bh(&p_spq->lock);
+
+ /* Check return value after LOCK is taken for cleaner error flow */
+ if (rc)
+ goto spq_post_fail;
+
+ /* Add the request to the pending queue */
+ rc = qed_spq_add_entry(p_hwfn, p_ent, p_ent->priority);
+ if (rc)
+ goto spq_post_fail;
+
+ rc = qed_spq_pend_post(p_hwfn);
+ if (rc) {
+ /* Since it's possible that pending failed for a different
+ * entry [although unlikely], the failed entry was already
+ * dealt with; No need to return it here.
+ */
+ b_ret_ent = false;
+ goto spq_post_fail;
+ }
+
+ spin_unlock_bh(&p_spq->lock);
+
+ if (p_ent->comp_mode == QED_SPQ_MODE_EBLOCK) {
+ /* For entries in QED BLOCK mode, the completion code cannot
+ * perform the necessary cleanup - if it did, we couldn't
+ * access p_ent here to see whether it's successful or not.
+ * Thus, after gaining the answer perform the cleanup here.
+ */
+ rc = qed_spq_block(p_hwfn, p_ent, fw_return_code);
+ if (rc)
+ goto spq_post_fail2;
+
+ /* return to pool */
+ qed_spq_return_entry(p_hwfn, p_ent);
+ }
+ return rc;
+
+spq_post_fail2:
+ spin_lock_bh(&p_spq->lock);
+ list_del(&p_ent->list);
+ qed_chain_return_produced(&p_spq->chain);
+
+spq_post_fail:
+ /* return to the free pool */
+ if (b_ret_ent)
+ __qed_spq_return_entry(p_hwfn, p_ent);
+ spin_unlock_bh(&p_spq->lock);
+
+ return rc;
+}
+
+int qed_spq_completion(struct qed_hwfn *p_hwfn,
+ __le16 echo,
+ u8 fw_return_code,
+ union event_ring_data *p_data)
+{
+ struct qed_spq *p_spq;
+ 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;
+
+ p_spq = p_hwfn->p_spq;
+ if (!p_spq)
+ return -EINVAL;
+
+ spin_lock_bh(&p_spq->lock);
+ list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending,
+ list) {
+ if (p_ent->elem.hdr.echo == echo) {
+ list_del(&p_ent->list);
+
+ qed_chain_return_produced(&p_spq->chain);
+ p_spq->comp_count++;
+ found = p_ent;
+ break;
+ }
+ }
+
+ /* Release lock before callback, as callback may post
+ * an additional ramrod.
+ */
+ spin_unlock_bh(&p_spq->lock);
+
+ if (!found) {
+ DP_NOTICE(p_hwfn,
+ "Failed to find an entry this EQE completes\n");
+ return -EEXIST;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SPQ, "Complete: func %p cookie %p)\n",
+ p_ent->comp_cb.function, p_ent->comp_cb.cookie);
+ if (found->comp_cb.function)
+ found->comp_cb.function(p_hwfn, found->comp_cb.cookie, p_data,
+ fw_return_code);
+
+ if (found->comp_mode != QED_SPQ_MODE_EBLOCK)
+ /* EBLOCK is responsible for freeing its own entry */
+ 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;
+}
+
+struct qed_consq *qed_consq_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_consq *p_consq;
+
+ /* Allocate ConsQ struct */
+ p_consq = kzalloc(sizeof(*p_consq), GFP_ATOMIC);
+ if (!p_consq) {
+ DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_consq'\n");
+ return NULL;
+ }
+
+ /* Allocate and initialize EQ chain*/
+ if (qed_chain_alloc(p_hwfn->cdev,
+ QED_CHAIN_USE_TO_PRODUCE,
+ QED_CHAIN_MODE_PBL,
+ QED_CHAIN_PAGE_SIZE / 0x80,
+ 0x80,
+ &p_consq->chain)) {
+ DP_NOTICE(p_hwfn, "Failed to allocate consq chain");
+ goto consq_allocate_fail;
+ }
+
+ return p_consq;
+
+consq_allocate_fail:
+ qed_consq_free(p_hwfn, p_consq);
+ return NULL;
+}
+
+void qed_consq_setup(struct qed_hwfn *p_hwfn,
+ struct qed_consq *p_consq)
+{
+ qed_chain_reset(&p_consq->chain);
+}
+
+void qed_consq_free(struct qed_hwfn *p_hwfn,
+ struct qed_consq *p_consq)
+{
+ if (!p_consq)
+ return;
+ qed_chain_free(p_hwfn->cdev, &p_consq->chain);
+ kfree(p_consq);
+}
diff --git a/drivers/net/ethernet/qlogic/qede/Makefile b/drivers/net/ethernet/qlogic/qede/Makefile
new file mode 100644
index 000000000000..06ff90d87572
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qede/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_QEDE) := qede.o
+
+qede-y := qede_main.o qede_ethtool.o
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
new file mode 100644
index 000000000000..ea00d5f3bab4
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -0,0 +1,285 @@
+/* QLogic qede NIC Driver
+* Copyright (c) 2015 QLogic Corporation
+*
+* This software is available 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.
+*/
+
+#ifndef _QEDE_H_
+#define _QEDE_H_
+#include <linux/compiler.h>
+#include <linux/version.h>
+#include <linux/workqueue.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/bitmap.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/qed/common_hsi.h>
+#include <linux/qed/eth_common.h>
+#include <linux/qed/qed_if.h>
+#include <linux/qed/qed_chain.h>
+#include <linux/qed/qed_eth_if.h>
+
+#define QEDE_MAJOR_VERSION 8
+#define QEDE_MINOR_VERSION 4
+#define QEDE_REVISION_VERSION 0
+#define QEDE_ENGINEERING_VERSION 0
+#define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \
+ __stringify(QEDE_MINOR_VERSION) "." \
+ __stringify(QEDE_REVISION_VERSION) "." \
+ __stringify(QEDE_ENGINEERING_VERSION)
+
+#define QEDE_ETH_INTERFACE_VERSION 300
+
+#define DRV_MODULE_SYM qede
+
+struct qede_stats {
+ u64 no_buff_discards;
+ u64 rx_ucast_bytes;
+ u64 rx_mcast_bytes;
+ u64 rx_bcast_bytes;
+ u64 rx_ucast_pkts;
+ u64 rx_mcast_pkts;
+ u64 rx_bcast_pkts;
+ u64 mftag_filter_discards;
+ u64 mac_filter_discards;
+ u64 tx_ucast_bytes;
+ u64 tx_mcast_bytes;
+ u64 tx_bcast_bytes;
+ u64 tx_ucast_pkts;
+ u64 tx_mcast_pkts;
+ u64 tx_bcast_pkts;
+ u64 tx_err_drop_pkts;
+ u64 coalesced_pkts;
+ u64 coalesced_events;
+ u64 coalesced_aborts_num;
+ u64 non_coalesced_pkts;
+ u64 coalesced_bytes;
+
+ /* port */
+ u64 rx_64_byte_packets;
+ u64 rx_127_byte_packets;
+ u64 rx_255_byte_packets;
+ u64 rx_511_byte_packets;
+ u64 rx_1023_byte_packets;
+ u64 rx_1518_byte_packets;
+ u64 rx_1522_byte_packets;
+ u64 rx_2047_byte_packets;
+ u64 rx_4095_byte_packets;
+ u64 rx_9216_byte_packets;
+ u64 rx_16383_byte_packets;
+ u64 rx_crc_errors;
+ u64 rx_mac_crtl_frames;
+ u64 rx_pause_frames;
+ u64 rx_pfc_frames;
+ u64 rx_align_errors;
+ u64 rx_carrier_errors;
+ u64 rx_oversize_packets;
+ u64 rx_jabbers;
+ u64 rx_undersize_packets;
+ u64 rx_fragments;
+ u64 tx_64_byte_packets;
+ u64 tx_65_to_127_byte_packets;
+ u64 tx_128_to_255_byte_packets;
+ u64 tx_256_to_511_byte_packets;
+ u64 tx_512_to_1023_byte_packets;
+ u64 tx_1024_to_1518_byte_packets;
+ u64 tx_1519_to_2047_byte_packets;
+ u64 tx_2048_to_4095_byte_packets;
+ u64 tx_4096_to_9216_byte_packets;
+ u64 tx_9217_to_16383_byte_packets;
+ u64 tx_pause_frames;
+ u64 tx_pfc_frames;
+ u64 tx_lpi_entry_count;
+ u64 tx_total_collisions;
+ u64 brb_truncates;
+ u64 brb_discards;
+ u64 tx_mac_ctrl_frames;
+};
+
+struct qede_dev {
+ struct qed_dev *cdev;
+ struct net_device *ndev;
+ struct pci_dev *pdev;
+
+ u32 dp_module;
+ u8 dp_level;
+
+ const struct qed_eth_ops *ops;
+
+ struct qed_dev_eth_info dev_info;
+#define QEDE_MAX_RSS_CNT(edev) ((edev)->dev_info.num_queues)
+#define QEDE_MAX_TSS_CNT(edev) ((edev)->dev_info.num_queues * \
+ (edev)->dev_info.num_tc)
+
+ struct qede_fastpath *fp_array;
+ u16 num_rss;
+ u8 num_tc;
+#define QEDE_RSS_CNT(edev) ((edev)->num_rss)
+#define QEDE_TSS_CNT(edev) ((edev)->num_rss * \
+ (edev)->num_tc)
+#define QEDE_TSS_IDX(edev, txqidx) ((txqidx) % (edev)->num_rss)
+#define QEDE_TC_IDX(edev, txqidx) ((txqidx) / (edev)->num_rss)
+#define QEDE_TX_QUEUE(edev, txqidx) \
+ (&(edev)->fp_array[QEDE_TSS_IDX((edev), (txqidx))].txqs[QEDE_TC_IDX( \
+ (edev), (txqidx))])
+
+ struct qed_int_info int_info;
+ unsigned char primary_mac[ETH_ALEN];
+
+ /* Smaller private varaiant of the RTNL lock */
+ struct mutex qede_lock;
+ u32 state; /* Protected by qede_lock */
+ u16 rx_buf_size;
+ /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
+#define ETH_OVERHEAD (ETH_HLEN + 8 + 8)
+ /* Max supported alignment is 256 (8 shift)
+ * minimal alignment shift 6 is optimal for 57xxx HW performance
+ */
+#define QEDE_RX_ALIGN_SHIFT max(6, min(8, L1_CACHE_SHIFT))
+ /* We assume skb_build() uses sizeof(struct skb_shared_info) bytes
+ * at the end of skb->data, to avoid wasting a full cache line.
+ * This reduces memory use (skb->truesize).
+ */
+#define QEDE_FW_RX_ALIGN_END \
+ max_t(u64, 1UL << QEDE_RX_ALIGN_SHIFT, \
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+
+ struct qede_stats stats;
+ struct qed_update_vport_rss_params rss_params;
+ u16 q_num_rx_buffers; /* Must be a power of two */
+ u16 q_num_tx_buffers; /* Must be a power of two */
+
+ struct delayed_work sp_task;
+ unsigned long sp_flags;
+};
+
+enum QEDE_STATE {
+ QEDE_STATE_CLOSED,
+ QEDE_STATE_OPEN,
+};
+
+#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
+
+#define MAX_NUM_TC 8
+#define MAX_NUM_PRI 8
+
+/* The driver supports the new build_skb() API:
+ * RX ring buffer contains pointer to kmalloc() data only,
+ * skb are built only after the frame was DMA-ed.
+ */
+struct sw_rx_data {
+ u8 *data;
+
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+};
+
+struct qede_rx_queue {
+ __le16 *hw_cons_ptr;
+ struct sw_rx_data *sw_rx_ring;
+ u16 sw_rx_cons;
+ u16 sw_rx_prod;
+ struct qed_chain rx_bd_ring;
+ struct qed_chain rx_comp_ring;
+ void __iomem *hw_rxq_prod_addr;
+
+ int rx_buf_size;
+
+ u16 num_rx_buffers;
+ u16 rxq_id;
+
+ u64 rx_hw_errors;
+ u64 rx_alloc_errors;
+};
+
+union db_prod {
+ struct eth_db_data data;
+ u32 raw;
+};
+
+struct sw_tx_bd {
+ struct sk_buff *skb;
+ u8 flags;
+/* Set on the first BD descriptor when there is a split BD */
+#define QEDE_TSO_SPLIT_BD BIT(0)
+};
+
+struct qede_tx_queue {
+ int index; /* Queue index */
+ __le16 *hw_cons_ptr;
+ struct sw_tx_bd *sw_tx_ring;
+ u16 sw_tx_cons;
+ u16 sw_tx_prod;
+ struct qed_chain tx_pbl;
+ void __iomem *doorbell_addr;
+ union db_prod tx_db;
+
+ u16 num_tx_buffers;
+};
+
+#define BD_UNMAP_ADDR(bd) HILO_U64(le32_to_cpu((bd)->addr.hi), \
+ le32_to_cpu((bd)->addr.lo))
+#define BD_SET_UNMAP_ADDR_LEN(bd, maddr, len) \
+ do { \
+ (bd)->addr.hi = cpu_to_le32(upper_32_bits(maddr)); \
+ (bd)->addr.lo = cpu_to_le32(lower_32_bits(maddr)); \
+ (bd)->nbytes = cpu_to_le16(len); \
+ } while (0)
+#define BD_UNMAP_LEN(bd) (le16_to_cpu((bd)->nbytes))
+
+struct qede_fastpath {
+ struct qede_dev *edev;
+ u8 rss_id;
+ struct napi_struct napi;
+ struct qed_sb_info *sb_info;
+ struct qede_rx_queue *rxq;
+ struct qede_tx_queue *txqs;
+
+#define VEC_NAME_SIZE (sizeof(((struct net_device *)0)->name) + 8)
+ char name[VEC_NAME_SIZE];
+};
+
+/* Debug print definitions */
+#define DP_NAME(edev) ((edev)->ndev->name)
+
+#define XMIT_PLAIN 0
+#define XMIT_L4_CSUM BIT(0)
+#define XMIT_LSO BIT(1)
+#define XMIT_ENC BIT(2)
+
+#define QEDE_CSUM_ERROR BIT(0)
+#define QEDE_CSUM_UNNECESSARY BIT(1)
+
+#define QEDE_SP_RX_MODE 1
+
+union qede_reload_args {
+ u16 mtu;
+};
+
+void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level);
+void qede_set_ethtool_ops(struct net_device *netdev);
+void qede_reload(struct qede_dev *edev,
+ void (*func)(struct qede_dev *edev,
+ union qede_reload_args *args),
+ union qede_reload_args *args);
+int qede_change_mtu(struct net_device *dev, int new_mtu);
+void qede_fill_by_demand_stats(struct qede_dev *edev);
+
+#define RX_RING_SIZE_POW 13
+#define RX_RING_SIZE BIT(RX_RING_SIZE_POW)
+#define NUM_RX_BDS_MAX (RX_RING_SIZE - 1)
+#define NUM_RX_BDS_MIN 128
+#define NUM_RX_BDS_DEF NUM_RX_BDS_MAX
+
+#define TX_RING_SIZE_POW 13
+#define TX_RING_SIZE BIT(TX_RING_SIZE_POW)
+#define NUM_TX_BDS_MAX (TX_RING_SIZE - 1)
+#define NUM_TX_BDS_MIN 128
+#define NUM_TX_BDS_DEF NUM_TX_BDS_MAX
+
+#define for_each_rss(i) for (i = 0; i < edev->num_rss; i++)
+
+#endif /* _QEDE_H_ */
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
new file mode 100644
index 000000000000..3a362476a22c
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -0,0 +1,385 @@
+/* QLogic qede NIC Driver
+* Copyright (c) 2015 QLogic Corporation
+*
+* This software is available 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.
+*/
+
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/capability.h>
+#include "qede.h"
+
+#define QEDE_STAT_OFFSET(stat_name) (offsetof(struct qede_stats, stat_name))
+#define QEDE_STAT_STRING(stat_name) (#stat_name)
+#define _QEDE_STAT(stat_name, pf_only) \
+ {QEDE_STAT_OFFSET(stat_name), QEDE_STAT_STRING(stat_name), pf_only}
+#define QEDE_PF_STAT(stat_name) _QEDE_STAT(stat_name, true)
+#define QEDE_STAT(stat_name) _QEDE_STAT(stat_name, false)
+
+#define QEDE_RQSTAT_OFFSET(stat_name) \
+ (offsetof(struct qede_rx_queue, stat_name))
+#define QEDE_RQSTAT_STRING(stat_name) (#stat_name)
+#define QEDE_RQSTAT(stat_name) \
+ {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)}
+static const struct {
+ u64 offset;
+ char string[ETH_GSTRING_LEN];
+} qede_rqstats_arr[] = {
+ QEDE_RQSTAT(rx_hw_errors),
+ QEDE_RQSTAT(rx_alloc_errors),
+};
+
+#define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
+#define QEDE_RQSTATS_DATA(dev, sindex, rqindex) \
+ (*((u64 *)(((char *)(dev->fp_array[(rqindex)].rxq)) +\
+ qede_rqstats_arr[(sindex)].offset)))
+static const struct {
+ u64 offset;
+ char string[ETH_GSTRING_LEN];
+ bool pf_only;
+} qede_stats_arr[] = {
+ QEDE_STAT(rx_ucast_bytes),
+ QEDE_STAT(rx_mcast_bytes),
+ QEDE_STAT(rx_bcast_bytes),
+ QEDE_STAT(rx_ucast_pkts),
+ QEDE_STAT(rx_mcast_pkts),
+ QEDE_STAT(rx_bcast_pkts),
+
+ QEDE_STAT(tx_ucast_bytes),
+ QEDE_STAT(tx_mcast_bytes),
+ QEDE_STAT(tx_bcast_bytes),
+ QEDE_STAT(tx_ucast_pkts),
+ QEDE_STAT(tx_mcast_pkts),
+ QEDE_STAT(tx_bcast_pkts),
+
+ QEDE_PF_STAT(rx_64_byte_packets),
+ QEDE_PF_STAT(rx_127_byte_packets),
+ QEDE_PF_STAT(rx_255_byte_packets),
+ QEDE_PF_STAT(rx_511_byte_packets),
+ QEDE_PF_STAT(rx_1023_byte_packets),
+ QEDE_PF_STAT(rx_1518_byte_packets),
+ QEDE_PF_STAT(rx_1522_byte_packets),
+ QEDE_PF_STAT(rx_2047_byte_packets),
+ QEDE_PF_STAT(rx_4095_byte_packets),
+ QEDE_PF_STAT(rx_9216_byte_packets),
+ QEDE_PF_STAT(rx_16383_byte_packets),
+ QEDE_PF_STAT(tx_64_byte_packets),
+ QEDE_PF_STAT(tx_65_to_127_byte_packets),
+ QEDE_PF_STAT(tx_128_to_255_byte_packets),
+ QEDE_PF_STAT(tx_256_to_511_byte_packets),
+ QEDE_PF_STAT(tx_512_to_1023_byte_packets),
+ QEDE_PF_STAT(tx_1024_to_1518_byte_packets),
+ QEDE_PF_STAT(tx_1519_to_2047_byte_packets),
+ QEDE_PF_STAT(tx_2048_to_4095_byte_packets),
+ QEDE_PF_STAT(tx_4096_to_9216_byte_packets),
+ QEDE_PF_STAT(tx_9217_to_16383_byte_packets),
+
+ QEDE_PF_STAT(rx_mac_crtl_frames),
+ QEDE_PF_STAT(tx_mac_ctrl_frames),
+ QEDE_PF_STAT(rx_pause_frames),
+ QEDE_PF_STAT(tx_pause_frames),
+ QEDE_PF_STAT(rx_pfc_frames),
+ QEDE_PF_STAT(tx_pfc_frames),
+
+ QEDE_PF_STAT(rx_crc_errors),
+ QEDE_PF_STAT(rx_align_errors),
+ QEDE_PF_STAT(rx_carrier_errors),
+ QEDE_PF_STAT(rx_oversize_packets),
+ QEDE_PF_STAT(rx_jabbers),
+ QEDE_PF_STAT(rx_undersize_packets),
+ QEDE_PF_STAT(rx_fragments),
+ QEDE_PF_STAT(tx_lpi_entry_count),
+ QEDE_PF_STAT(tx_total_collisions),
+ QEDE_PF_STAT(brb_truncates),
+ QEDE_PF_STAT(brb_discards),
+ QEDE_STAT(no_buff_discards),
+ QEDE_PF_STAT(mftag_filter_discards),
+ QEDE_PF_STAT(mac_filter_discards),
+ QEDE_STAT(tx_err_drop_pkts),
+
+ QEDE_STAT(coalesced_pkts),
+ QEDE_STAT(coalesced_events),
+ QEDE_STAT(coalesced_aborts_num),
+ QEDE_STAT(non_coalesced_pkts),
+ QEDE_STAT(coalesced_bytes),
+};
+
+#define QEDE_STATS_DATA(dev, index) \
+ (*((u64 *)(((char *)(dev)) + offsetof(struct qede_dev, stats) \
+ + qede_stats_arr[(index)].offset)))
+
+#define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr)
+
+static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
+{
+ int i, j, k;
+
+ for (i = 0, j = 0; i < QEDE_NUM_STATS; i++) {
+ strcpy(buf + j * ETH_GSTRING_LEN,
+ qede_stats_arr[i].string);
+ j++;
+ }
+
+ for (k = 0; k < QEDE_NUM_RQSTATS; k++, j++)
+ strcpy(buf + j * ETH_GSTRING_LEN,
+ qede_rqstats_arr[k].string);
+}
+
+static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ qede_get_strings_stats(edev, buf);
+ break;
+ default:
+ DP_VERBOSE(edev, QED_MSG_DEBUG,
+ "Unsupported stringset 0x%08x\n", stringset);
+ }
+}
+
+static void qede_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *buf)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ int sidx, cnt = 0;
+ int qid;
+
+ qede_fill_by_demand_stats(edev);
+
+ mutex_lock(&edev->qede_lock);
+
+ for (sidx = 0; sidx < QEDE_NUM_STATS; sidx++)
+ buf[cnt++] = QEDE_STATS_DATA(edev, sidx);
+
+ for (sidx = 0; sidx < QEDE_NUM_RQSTATS; sidx++) {
+ buf[cnt] = 0;
+ for (qid = 0; qid < edev->num_rss; qid++)
+ buf[cnt] += QEDE_RQSTATS_DATA(edev, sidx, qid);
+ cnt++;
+ }
+
+ mutex_unlock(&edev->qede_lock);
+}
+
+static int qede_get_sset_count(struct net_device *dev, int stringset)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ int num_stats = QEDE_NUM_STATS;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ return num_stats + QEDE_NUM_RQSTATS;
+
+ default:
+ DP_VERBOSE(edev, QED_MSG_DEBUG,
+ "Unsupported stringset 0x%08x\n", stringset);
+ return -EINVAL;
+ }
+}
+
+static int qede_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ struct qed_link_output current_link;
+
+ memset(&current_link, 0, sizeof(current_link));
+ edev->ops->common->get_link(edev->cdev, &current_link);
+
+ cmd->supported = current_link.supported_caps;
+ cmd->advertising = current_link.advertised_caps;
+ if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) {
+ ethtool_cmd_speed_set(cmd, current_link.speed);
+ cmd->duplex = current_link.duplex;
+ } else {
+ cmd->duplex = DUPLEX_UNKNOWN;
+ ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+ }
+ cmd->port = current_link.port;
+ cmd->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE :
+ AUTONEG_DISABLE;
+ cmd->lp_advertising = current_link.lp_caps;
+
+ return 0;
+}
+
+static int qede_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ struct qed_link_output current_link;
+ struct qed_link_params params;
+ u32 speed;
+
+ if (edev->dev_info.common.is_mf) {
+ DP_INFO(edev,
+ "Link parameters can not be changed in MF mode\n");
+ return -EOPNOTSUPP;
+ }
+
+ memset(&current_link, 0, sizeof(current_link));
+ memset(&params, 0, sizeof(params));
+ edev->ops->common->get_link(edev->cdev, &current_link);
+
+ speed = ethtool_cmd_speed(cmd);
+ params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
+ params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ params.autoneg = true;
+ params.forced_speed = 0;
+ params.adv_speeds = cmd->advertising;
+ } else { /* forced speed */
+ params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
+ params.autoneg = false;
+ params.forced_speed = speed;
+ switch (speed) {
+ case SPEED_10000:
+ if (!(current_link.supported_caps &
+ SUPPORTED_10000baseKR_Full)) {
+ DP_INFO(edev, "10G speed not supported\n");
+ return -EINVAL;
+ }
+ params.adv_speeds = SUPPORTED_10000baseKR_Full;
+ break;
+ case SPEED_40000:
+ if (!(current_link.supported_caps &
+ SUPPORTED_40000baseLR4_Full)) {
+ DP_INFO(edev, "40G speed not supported\n");
+ return -EINVAL;
+ }
+ params.adv_speeds = SUPPORTED_40000baseLR4_Full;
+ break;
+ default:
+ DP_INFO(edev, "Unsupported speed %u\n", speed);
+ return -EINVAL;
+ }
+ }
+
+ params.link_up = true;
+ edev->ops->common->set_link(edev->cdev, &params);
+
+ return 0;
+}
+
+static void qede_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN];
+ struct qede_dev *edev = netdev_priv(ndev);
+
+ strlcpy(info->driver, "qede", sizeof(info->driver));
+ strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
+
+ snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
+ edev->dev_info.common.fw_major,
+ edev->dev_info.common.fw_minor,
+ edev->dev_info.common.fw_rev,
+ edev->dev_info.common.fw_eng);
+
+ snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
+ (edev->dev_info.common.mfw_rev >> 24) & 0xFF,
+ (edev->dev_info.common.mfw_rev >> 16) & 0xFF,
+ (edev->dev_info.common.mfw_rev >> 8) & 0xFF,
+ edev->dev_info.common.mfw_rev & 0xFF);
+
+ if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) <
+ sizeof(info->fw_version)) {
+ snprintf(info->fw_version, sizeof(info->fw_version),
+ "mfw %s storm %s", mfw, storm);
+ } else {
+ snprintf(info->fw_version, sizeof(info->fw_version),
+ "%s %s", mfw, storm);
+ }
+
+ strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
+}
+
+static u32 qede_get_msglevel(struct net_device *ndev)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+
+ return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) |
+ edev->dp_module;
+}
+
+static void qede_set_msglevel(struct net_device *ndev, u32 level)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+ u32 dp_module = 0;
+ u8 dp_level = 0;
+
+ qede_config_debug(level, &dp_module, &dp_level);
+
+ edev->dp_level = dp_level;
+ edev->dp_module = dp_module;
+ edev->ops->common->update_msglvl(edev->cdev,
+ dp_module, dp_level);
+}
+
+static u32 qede_get_link(struct net_device *dev)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ struct qed_link_output current_link;
+
+ memset(&current_link, 0, sizeof(current_link));
+ edev->ops->common->get_link(edev->cdev, &current_link);
+
+ return current_link.link_up;
+}
+
+static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args)
+{
+ edev->ndev->mtu = args->mtu;
+}
+
+/* Netdevice NDOs */
+#define ETH_MAX_JUMBO_PACKET_SIZE 9600
+#define ETH_MIN_PACKET_SIZE 60
+int qede_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+ union qede_reload_args args;
+
+ if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
+ ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) {
+ DP_ERR(edev, "Can't support requested MTU size\n");
+ return -EINVAL;
+ }
+
+ DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
+ "Configuring MTU size of %d\n", new_mtu);
+
+ /* Set the mtu field and re-start the interface if needed*/
+ args.mtu = new_mtu;
+
+ if (netif_running(edev->ndev))
+ qede_reload(edev, &qede_update_mtu, &args);
+
+ qede_update_mtu(edev, &args);
+
+ return 0;
+}
+
+static const struct ethtool_ops qede_ethtool_ops = {
+ .get_settings = qede_get_settings,
+ .set_settings = qede_set_settings,
+ .get_drvinfo = qede_get_drvinfo,
+ .get_msglevel = qede_get_msglevel,
+ .set_msglevel = qede_set_msglevel,
+ .get_link = qede_get_link,
+ .get_strings = qede_get_strings,
+ .get_ethtool_stats = qede_get_ethtool_stats,
+ .get_sset_count = qede_get_sset_count,
+
+};
+
+void qede_set_ethtool_ops(struct net_device *dev)
+{
+ dev->ethtool_ops = &qede_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
new file mode 100644
index 000000000000..f4657a2e730a
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -0,0 +1,2584 @@
+/* QLogic qede NIC Driver
+* Copyright (c) 2015 QLogic Corporation
+*
+* This software is available 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.
+*/
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <asm/byteorder.h>
+#include <asm/param.h>
+#include <linux/io.h>
+#include <linux/netdev_features.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <net/vxlan.h>
+#include <linux/ip.h>
+#include <net/ipv6.h>
+#include <net/tcp.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/pkt_sched.h>
+#include <linux/ethtool.h>
+#include <linux/in.h>
+#include <linux/random.h>
+#include <net/ip6_checksum.h>
+#include <linux/bitops.h>
+
+#include "qede.h"
+
+static const char version[] = "QLogic QL4xxx 40G/100G Ethernet Driver qede "
+ DRV_MODULE_VERSION "\n";
+
+MODULE_DESCRIPTION("QLogic 40G/100G Ethernet Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+static uint debug;
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, " Default debug msglevel");
+
+static const struct qed_eth_ops *qed_ops;
+
+#define CHIP_NUM_57980S_40 0x1634
+#define CHIP_NUM_57980S_10 0x1635
+#define CHIP_NUM_57980S_MF 0x1636
+#define CHIP_NUM_57980S_100 0x1644
+#define CHIP_NUM_57980S_50 0x1654
+#define CHIP_NUM_57980S_25 0x1656
+
+#ifndef PCI_DEVICE_ID_NX2_57980E
+#define PCI_DEVICE_ID_57980S_40 CHIP_NUM_57980S_40
+#define PCI_DEVICE_ID_57980S_10 CHIP_NUM_57980S_10
+#define PCI_DEVICE_ID_57980S_MF CHIP_NUM_57980S_MF
+#define PCI_DEVICE_ID_57980S_100 CHIP_NUM_57980S_100
+#define PCI_DEVICE_ID_57980S_50 CHIP_NUM_57980S_50
+#define PCI_DEVICE_ID_57980S_25 CHIP_NUM_57980S_25
+#endif
+
+static const struct pci_device_id qede_pci_tbl[] = {
+ { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_40), 0 },
+ { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_10), 0 },
+ { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_MF), 0 },
+ { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_100), 0 },
+ { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_50), 0 },
+ { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_25), 0 },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, qede_pci_tbl);
+
+static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+
+#define TX_TIMEOUT (5 * HZ)
+
+static void qede_remove(struct pci_dev *pdev);
+static int qede_alloc_rx_buffer(struct qede_dev *edev,
+ struct qede_rx_queue *rxq);
+static void qede_link_update(void *dev, struct qed_link_output *link);
+
+static struct pci_driver qede_pci_driver = {
+ .name = "qede",
+ .id_table = qede_pci_tbl,
+ .probe = qede_probe,
+ .remove = qede_remove,
+};
+
+static struct qed_eth_cb_ops qede_ll_ops = {
+ {
+ .link_update = qede_link_update,
+ },
+};
+
+static int qede_netdev_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+ struct ethtool_drvinfo drvinfo;
+ struct qede_dev *edev;
+
+ /* Currently only support name change */
+ if (event != NETDEV_CHANGENAME)
+ goto done;
+
+ /* Check whether this is a qede device */
+ if (!ndev || !ndev->ethtool_ops || !ndev->ethtool_ops->get_drvinfo)
+ goto done;
+
+ memset(&drvinfo, 0, sizeof(drvinfo));
+ ndev->ethtool_ops->get_drvinfo(ndev, &drvinfo);
+ if (strcmp(drvinfo.driver, "qede"))
+ goto done;
+ edev = netdev_priv(ndev);
+
+ /* Notify qed of the name change */
+ if (!edev->ops || !edev->ops->common)
+ goto done;
+ edev->ops->common->set_id(edev->cdev, edev->ndev->name,
+ "qede");
+
+done:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block qede_netdev_notifier = {
+ .notifier_call = qede_netdev_event,
+};
+
+static
+int __init qede_init(void)
+{
+ int ret;
+ u32 qed_ver;
+
+ pr_notice("qede_init: %s\n", version);
+
+ qed_ver = qed_get_protocol_version(QED_PROTOCOL_ETH);
+ if (qed_ver != QEDE_ETH_INTERFACE_VERSION) {
+ pr_notice("Version mismatch [%08x != %08x]\n",
+ qed_ver,
+ QEDE_ETH_INTERFACE_VERSION);
+ return -EINVAL;
+ }
+
+ qed_ops = qed_get_eth_ops(QEDE_ETH_INTERFACE_VERSION);
+ if (!qed_ops) {
+ pr_notice("Failed to get qed ethtool operations\n");
+ return -EINVAL;
+ }
+
+ /* Must register notifier before pci ops, since we might miss
+ * interface rename after pci probe and netdev registeration.
+ */
+ ret = register_netdevice_notifier(&qede_netdev_notifier);
+ if (ret) {
+ pr_notice("Failed to register netdevice_notifier\n");
+ qed_put_eth_ops();
+ return -EINVAL;
+ }
+
+ ret = pci_register_driver(&qede_pci_driver);
+ if (ret) {
+ pr_notice("Failed to register driver\n");
+ unregister_netdevice_notifier(&qede_netdev_notifier);
+ qed_put_eth_ops();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __exit qede_cleanup(void)
+{
+ pr_notice("qede_cleanup called\n");
+
+ unregister_netdevice_notifier(&qede_netdev_notifier);
+ pci_unregister_driver(&qede_pci_driver);
+ qed_put_eth_ops();
+}
+
+module_init(qede_init);
+module_exit(qede_cleanup);
+
+/* -------------------------------------------------------------------------
+ * START OF FAST-PATH
+ * -------------------------------------------------------------------------
+ */
+
+/* Unmap the data and free skb */
+static int qede_free_tx_pkt(struct qede_dev *edev,
+ struct qede_tx_queue *txq,
+ int *len)
+{
+ u16 idx = txq->sw_tx_cons & NUM_TX_BDS_MAX;
+ struct sk_buff *skb = txq->sw_tx_ring[idx].skb;
+ struct eth_tx_1st_bd *first_bd;
+ struct eth_tx_bd *tx_data_bd;
+ int bds_consumed = 0;
+ int nbds;
+ bool data_split = txq->sw_tx_ring[idx].flags & QEDE_TSO_SPLIT_BD;
+ int i, split_bd_len = 0;
+
+ if (unlikely(!skb)) {
+ DP_ERR(edev,
+ "skb is null for txq idx=%d txq->sw_tx_cons=%d txq->sw_tx_prod=%d\n",
+ idx, txq->sw_tx_cons, txq->sw_tx_prod);
+ return -1;
+ }
+
+ *len = skb->len;
+
+ first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
+
+ bds_consumed++;
+
+ nbds = first_bd->data.nbds;
+
+ if (data_split) {
+ struct eth_tx_bd *split = (struct eth_tx_bd *)
+ qed_chain_consume(&txq->tx_pbl);
+ split_bd_len = BD_UNMAP_LEN(split);
+ bds_consumed++;
+ }
+ dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
+ BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
+
+ /* Unmap the data of the skb frags */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, bds_consumed++) {
+ tx_data_bd = (struct eth_tx_bd *)
+ qed_chain_consume(&txq->tx_pbl);
+ dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(tx_data_bd),
+ BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE);
+ }
+
+ while (bds_consumed++ < nbds)
+ qed_chain_consume(&txq->tx_pbl);
+
+ /* Free skb */
+ dev_kfree_skb_any(skb);
+ txq->sw_tx_ring[idx].skb = NULL;
+ txq->sw_tx_ring[idx].flags = 0;
+
+ return 0;
+}
+
+/* Unmap the data and free skb when mapping failed during start_xmit */
+static void qede_free_failed_tx_pkt(struct qede_dev *edev,
+ struct qede_tx_queue *txq,
+ struct eth_tx_1st_bd *first_bd,
+ int nbd,
+ bool data_split)
+{
+ u16 idx = txq->sw_tx_prod & NUM_TX_BDS_MAX;
+ struct sk_buff *skb = txq->sw_tx_ring[idx].skb;
+ struct eth_tx_bd *tx_data_bd;
+ int i, split_bd_len = 0;
+
+ /* Return prod to its position before this skb was handled */
+ qed_chain_set_prod(&txq->tx_pbl,
+ le16_to_cpu(txq->tx_db.data.bd_prod),
+ first_bd);
+
+ first_bd = (struct eth_tx_1st_bd *)qed_chain_produce(&txq->tx_pbl);
+
+ if (data_split) {
+ struct eth_tx_bd *split = (struct eth_tx_bd *)
+ qed_chain_produce(&txq->tx_pbl);
+ split_bd_len = BD_UNMAP_LEN(split);
+ nbd--;
+ }
+
+ dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
+ BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
+
+ /* Unmap the data of the skb frags */
+ for (i = 0; i < nbd; i++) {
+ tx_data_bd = (struct eth_tx_bd *)
+ qed_chain_produce(&txq->tx_pbl);
+ if (tx_data_bd->nbytes)
+ dma_unmap_page(&edev->pdev->dev,
+ BD_UNMAP_ADDR(tx_data_bd),
+ BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE);
+ }
+
+ /* Return again prod to its position before this skb was handled */
+ qed_chain_set_prod(&txq->tx_pbl,
+ le16_to_cpu(txq->tx_db.data.bd_prod),
+ first_bd);
+
+ /* Free skb */
+ dev_kfree_skb_any(skb);
+ txq->sw_tx_ring[idx].skb = NULL;
+ txq->sw_tx_ring[idx].flags = 0;
+}
+
+static u32 qede_xmit_type(struct qede_dev *edev,
+ struct sk_buff *skb,
+ int *ipv6_ext)
+{
+ u32 rc = XMIT_L4_CSUM;
+ __be16 l3_proto;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return XMIT_PLAIN;
+
+ l3_proto = vlan_get_protocol(skb);
+ if (l3_proto == htons(ETH_P_IPV6) &&
+ (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
+ *ipv6_ext = 1;
+
+ if (skb_is_gso(skb))
+ rc |= XMIT_LSO;
+
+ return rc;
+}
+
+static void qede_set_params_for_ipv6_ext(struct sk_buff *skb,
+ struct eth_tx_2nd_bd *second_bd,
+ struct eth_tx_3rd_bd *third_bd)
+{
+ u8 l4_proto;
+ u16 bd2_bits = 0, bd2_bits2 = 0;
+
+ bd2_bits2 |= (1 << ETH_TX_DATA_2ND_BD_IPV6_EXT_SHIFT);
+
+ bd2_bits |= ((((u8 *)skb_transport_header(skb) - skb->data) >> 1) &
+ ETH_TX_DATA_2ND_BD_L4_HDR_START_OFFSET_W_MASK)
+ << ETH_TX_DATA_2ND_BD_L4_HDR_START_OFFSET_W_SHIFT;
+
+ bd2_bits2 |= (ETH_L4_PSEUDO_CSUM_CORRECT_LENGTH <<
+ ETH_TX_DATA_2ND_BD_L4_PSEUDO_CSUM_MODE_SHIFT);
+
+ if (vlan_get_protocol(skb) == htons(ETH_P_IPV6))
+ l4_proto = ipv6_hdr(skb)->nexthdr;
+ else
+ l4_proto = ip_hdr(skb)->protocol;
+
+ if (l4_proto == IPPROTO_UDP)
+ bd2_bits2 |= 1 << ETH_TX_DATA_2ND_BD_L4_UDP_SHIFT;
+
+ if (third_bd) {
+ third_bd->data.bitfields |=
+ ((tcp_hdrlen(skb) / 4) &
+ ETH_TX_DATA_3RD_BD_TCP_HDR_LEN_DW_MASK) <<
+ ETH_TX_DATA_3RD_BD_TCP_HDR_LEN_DW_SHIFT;
+ }
+
+ second_bd->data.bitfields = cpu_to_le16(bd2_bits);
+ second_bd->data.bitfields2 = cpu_to_le16(bd2_bits2);
+}
+
+static int map_frag_to_bd(struct qede_dev *edev,
+ skb_frag_t *frag,
+ struct eth_tx_bd *bd)
+{
+ dma_addr_t mapping;
+
+ /* Map skb non-linear frag data for DMA */
+ mapping = skb_frag_dma_map(&edev->pdev->dev, frag, 0,
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
+ DP_NOTICE(edev, "Unable to map frag - dropping packet\n");
+ return -ENOMEM;
+ }
+
+ /* Setup the data pointer of the frag data */
+ BD_SET_UNMAP_ADDR_LEN(bd, mapping, skb_frag_size(frag));
+
+ return 0;
+}
+
+/* Main transmit function */
+static
+netdev_tx_t qede_start_xmit(struct sk_buff *skb,
+ struct net_device *ndev)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+ struct netdev_queue *netdev_txq;
+ struct qede_tx_queue *txq;
+ struct eth_tx_1st_bd *first_bd;
+ struct eth_tx_2nd_bd *second_bd = NULL;
+ struct eth_tx_3rd_bd *third_bd = NULL;
+ struct eth_tx_bd *tx_data_bd = NULL;
+ u16 txq_index;
+ u8 nbd = 0;
+ dma_addr_t mapping;
+ int rc, frag_idx = 0, ipv6_ext = 0;
+ u8 xmit_type;
+ u16 idx;
+ u16 hlen;
+ bool data_split;
+
+ /* Get tx-queue context and netdev index */
+ txq_index = skb_get_queue_mapping(skb);
+ WARN_ON(txq_index >= QEDE_TSS_CNT(edev));
+ txq = QEDE_TX_QUEUE(edev, txq_index);
+ netdev_txq = netdev_get_tx_queue(ndev, txq_index);
+
+ /* Current code doesn't support SKB linearization, since the max number
+ * of skb frags can be passed in the FW HSI.
+ */
+ BUILD_BUG_ON(MAX_SKB_FRAGS > ETH_TX_MAX_BDS_PER_NON_LSO_PACKET);
+
+ WARN_ON(qed_chain_get_elem_left(&txq->tx_pbl) <
+ (MAX_SKB_FRAGS + 1));
+
+ xmit_type = qede_xmit_type(edev, skb, &ipv6_ext);
+
+ /* Fill the entry in the SW ring and the BDs in the FW ring */
+ idx = txq->sw_tx_prod & NUM_TX_BDS_MAX;
+ txq->sw_tx_ring[idx].skb = skb;
+ first_bd = (struct eth_tx_1st_bd *)
+ qed_chain_produce(&txq->tx_pbl);
+ memset(first_bd, 0, sizeof(*first_bd));
+ first_bd->data.bd_flags.bitfields =
+ 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
+
+ /* Map skb linear data for DMA and set in the first BD */
+ mapping = dma_map_single(&edev->pdev->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
+ DP_NOTICE(edev, "SKB mapping failed\n");
+ qede_free_failed_tx_pkt(edev, txq, first_bd, 0, false);
+ return NETDEV_TX_OK;
+ }
+ nbd++;
+ BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb));
+
+ /* In case there is IPv6 with extension headers or LSO we need 2nd and
+ * 3rd BDs.
+ */
+ if (unlikely((xmit_type & XMIT_LSO) | ipv6_ext)) {
+ second_bd = (struct eth_tx_2nd_bd *)
+ qed_chain_produce(&txq->tx_pbl);
+ memset(second_bd, 0, sizeof(*second_bd));
+
+ nbd++;
+ third_bd = (struct eth_tx_3rd_bd *)
+ qed_chain_produce(&txq->tx_pbl);
+ memset(third_bd, 0, sizeof(*third_bd));
+
+ nbd++;
+ /* We need to fill in additional data in second_bd... */
+ tx_data_bd = (struct eth_tx_bd *)second_bd;
+ }
+
+ if (skb_vlan_tag_present(skb)) {
+ first_bd->data.vlan = cpu_to_le16(skb_vlan_tag_get(skb));
+ first_bd->data.bd_flags.bitfields |=
+ 1 << ETH_TX_1ST_BD_FLAGS_VLAN_INSERTION_SHIFT;
+ }
+
+ /* Fill the parsing flags & params according to the requested offload */
+ if (xmit_type & XMIT_L4_CSUM) {
+ /* We don't re-calculate IP checksum as it is already done by
+ * the upper stack
+ */
+ first_bd->data.bd_flags.bitfields |=
+ 1 << ETH_TX_1ST_BD_FLAGS_L4_CSUM_SHIFT;
+
+ /* If the packet is IPv6 with extension header, indicate that
+ * to FW and pass few params, since the device cracker doesn't
+ * support parsing IPv6 with extension header/s.
+ */
+ if (unlikely(ipv6_ext))
+ qede_set_params_for_ipv6_ext(skb, second_bd, third_bd);
+ }
+
+ if (xmit_type & XMIT_LSO) {
+ first_bd->data.bd_flags.bitfields |=
+ (1 << ETH_TX_1ST_BD_FLAGS_LSO_SHIFT);
+ third_bd->data.lso_mss =
+ cpu_to_le16(skb_shinfo(skb)->gso_size);
+
+ first_bd->data.bd_flags.bitfields |=
+ 1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT;
+ hlen = skb_transport_header(skb) +
+ tcp_hdrlen(skb) - skb->data;
+
+ /* @@@TBD - if will not be removed need to check */
+ third_bd->data.bitfields |=
+ (1 << ETH_TX_DATA_3RD_BD_HDR_NBD_SHIFT);
+
+ /* Make life easier for FW guys who can't deal with header and
+ * data on same BD. If we need to split, use the second bd...
+ */
+ if (unlikely(skb_headlen(skb) > hlen)) {
+ DP_VERBOSE(edev, NETIF_MSG_TX_QUEUED,
+ "TSO split header size is %d (%x:%x)\n",
+ first_bd->nbytes, first_bd->addr.hi,
+ first_bd->addr.lo);
+
+ mapping = HILO_U64(le32_to_cpu(first_bd->addr.hi),
+ le32_to_cpu(first_bd->addr.lo)) +
+ hlen;
+
+ BD_SET_UNMAP_ADDR_LEN(tx_data_bd, mapping,
+ le16_to_cpu(first_bd->nbytes) -
+ hlen);
+
+ /* this marks the BD as one that has no
+ * individual mapping
+ */
+ txq->sw_tx_ring[idx].flags |= QEDE_TSO_SPLIT_BD;
+
+ first_bd->nbytes = cpu_to_le16(hlen);
+
+ tx_data_bd = (struct eth_tx_bd *)third_bd;
+ data_split = true;
+ }
+ }
+
+ /* Handle fragmented skb */
+ /* special handle for frags inside 2nd and 3rd bds.. */
+ while (tx_data_bd && frag_idx < skb_shinfo(skb)->nr_frags) {
+ rc = map_frag_to_bd(edev,
+ &skb_shinfo(skb)->frags[frag_idx],
+ tx_data_bd);
+ if (rc) {
+ qede_free_failed_tx_pkt(edev, txq, first_bd, nbd,
+ data_split);
+ return NETDEV_TX_OK;
+ }
+
+ if (tx_data_bd == (struct eth_tx_bd *)second_bd)
+ tx_data_bd = (struct eth_tx_bd *)third_bd;
+ else
+ tx_data_bd = NULL;
+
+ frag_idx++;
+ }
+
+ /* map last frags into 4th, 5th .... */
+ for (; frag_idx < skb_shinfo(skb)->nr_frags; frag_idx++, nbd++) {
+ tx_data_bd = (struct eth_tx_bd *)
+ qed_chain_produce(&txq->tx_pbl);
+
+ memset(tx_data_bd, 0, sizeof(*tx_data_bd));
+
+ rc = map_frag_to_bd(edev,
+ &skb_shinfo(skb)->frags[frag_idx],
+ tx_data_bd);
+ if (rc) {
+ qede_free_failed_tx_pkt(edev, txq, first_bd, nbd,
+ data_split);
+ return NETDEV_TX_OK;
+ }
+ }
+
+ /* update the first BD with the actual num BDs */
+ first_bd->data.nbds = nbd;
+
+ netdev_tx_sent_queue(netdev_txq, skb->len);
+
+ skb_tx_timestamp(skb);
+
+ /* Advance packet producer only before sending the packet since mapping
+ * of pages may fail.
+ */
+ txq->sw_tx_prod++;
+
+ /* 'next page' entries are counted in the producer value */
+ txq->tx_db.data.bd_prod =
+ cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl));
+
+ /* wmb makes sure that the BDs data is updated before updating the
+ * producer, otherwise FW may read old data from the BDs.
+ */
+ wmb();
+ barrier();
+ writel(txq->tx_db.raw, txq->doorbell_addr);
+
+ /* mmiowb is needed to synchronize doorbell writes from more than one
+ * processor. It guarantees that the write arrives to the device before
+ * the queue lock is released and another start_xmit is called (possibly
+ * on another CPU). Without this barrier, the next doorbell can bypass
+ * this doorbell. This is applicable to IA64/Altix systems.
+ */
+ mmiowb();
+
+ if (unlikely(qed_chain_get_elem_left(&txq->tx_pbl)
+ < (MAX_SKB_FRAGS + 1))) {
+ netif_tx_stop_queue(netdev_txq);
+ DP_VERBOSE(edev, NETIF_MSG_TX_QUEUED,
+ "Stop queue was called\n");
+ /* paired memory barrier is in qede_tx_int(), we have to keep
+ * ordering of set_bit() in netif_tx_stop_queue() and read of
+ * fp->bd_tx_cons
+ */
+ smp_mb();
+
+ if (qed_chain_get_elem_left(&txq->tx_pbl)
+ >= (MAX_SKB_FRAGS + 1) &&
+ (edev->state == QEDE_STATE_OPEN)) {
+ netif_tx_wake_queue(netdev_txq);
+ DP_VERBOSE(edev, NETIF_MSG_TX_QUEUED,
+ "Wake queue was called\n");
+ }
+ }
+
+ return NETDEV_TX_OK;
+}
+
+static int qede_txq_has_work(struct qede_tx_queue *txq)
+{
+ u16 hw_bd_cons;
+
+ /* Tell compiler that consumer and producer can change */
+ barrier();
+ hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr);
+ if (qed_chain_get_cons_idx(&txq->tx_pbl) == hw_bd_cons + 1)
+ return 0;
+
+ return hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl);
+}
+
+static int qede_tx_int(struct qede_dev *edev,
+ struct qede_tx_queue *txq)
+{
+ struct netdev_queue *netdev_txq;
+ u16 hw_bd_cons;
+ unsigned int pkts_compl = 0, bytes_compl = 0;
+ int rc;
+
+ netdev_txq = netdev_get_tx_queue(edev->ndev, txq->index);
+
+ hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr);
+ barrier();
+
+ while (hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl)) {
+ int len = 0;
+
+ rc = qede_free_tx_pkt(edev, txq, &len);
+ if (rc) {
+ DP_NOTICE(edev, "hw_bd_cons = %d, chain_cons=%d\n",
+ hw_bd_cons,
+ qed_chain_get_cons_idx(&txq->tx_pbl));
+ break;
+ }
+
+ bytes_compl += len;
+ pkts_compl++;
+ txq->sw_tx_cons++;
+ }
+
+ netdev_tx_completed_queue(netdev_txq, pkts_compl, bytes_compl);
+
+ /* Need to make the tx_bd_cons update visible to start_xmit()
+ * before checking for netif_tx_queue_stopped(). Without the
+ * memory barrier, there is a small possibility that
+ * start_xmit() will miss it and cause the queue to be stopped
+ * forever.
+ * On the other hand we need an rmb() here to ensure the proper
+ * ordering of bit testing in the following
+ * netif_tx_queue_stopped(txq) call.
+ */
+ smp_mb();
+
+ if (unlikely(netif_tx_queue_stopped(netdev_txq))) {
+ /* Taking tx_lock is needed to prevent reenabling the queue
+ * while it's empty. This could have happen if rx_action() gets
+ * suspended in qede_tx_int() after the condition before
+ * netif_tx_wake_queue(), while tx_action (qede_start_xmit()):
+ *
+ * stops the queue->sees fresh tx_bd_cons->releases the queue->
+ * sends some packets consuming the whole queue again->
+ * stops the queue
+ */
+
+ __netif_tx_lock(netdev_txq, smp_processor_id());
+
+ if ((netif_tx_queue_stopped(netdev_txq)) &&
+ (edev->state == QEDE_STATE_OPEN) &&
+ (qed_chain_get_elem_left(&txq->tx_pbl)
+ >= (MAX_SKB_FRAGS + 1))) {
+ netif_tx_wake_queue(netdev_txq);
+ DP_VERBOSE(edev, NETIF_MSG_TX_DONE,
+ "Wake queue was called\n");
+ }
+
+ __netif_tx_unlock(netdev_txq);
+ }
+
+ return 0;
+}
+
+static bool qede_has_rx_work(struct qede_rx_queue *rxq)
+{
+ u16 hw_comp_cons, sw_comp_cons;
+
+ /* Tell compiler that status block fields can change */
+ barrier();
+
+ hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
+ sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
+
+ return hw_comp_cons != sw_comp_cons;
+}
+
+static bool qede_has_tx_work(struct qede_fastpath *fp)
+{
+ u8 tc;
+
+ for (tc = 0; tc < fp->edev->num_tc; tc++)
+ if (qede_txq_has_work(&fp->txqs[tc]))
+ return true;
+ return false;
+}
+
+/* This function copies the Rx buffer from the CONS position to the PROD
+ * position, since we failed to allocate a new Rx buffer.
+ */
+static void qede_reuse_rx_data(struct qede_rx_queue *rxq)
+{
+ struct eth_rx_bd *rx_bd_cons = qed_chain_consume(&rxq->rx_bd_ring);
+ struct eth_rx_bd *rx_bd_prod = qed_chain_produce(&rxq->rx_bd_ring);
+ struct sw_rx_data *sw_rx_data_cons =
+ &rxq->sw_rx_ring[rxq->sw_rx_cons & NUM_RX_BDS_MAX];
+ struct sw_rx_data *sw_rx_data_prod =
+ &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX];
+
+ dma_unmap_addr_set(sw_rx_data_prod, mapping,
+ dma_unmap_addr(sw_rx_data_cons, mapping));
+
+ sw_rx_data_prod->data = sw_rx_data_cons->data;
+ memcpy(rx_bd_prod, rx_bd_cons, sizeof(struct eth_rx_bd));
+
+ rxq->sw_rx_cons++;
+ rxq->sw_rx_prod++;
+}
+
+static inline void qede_update_rx_prod(struct qede_dev *edev,
+ struct qede_rx_queue *rxq)
+{
+ u16 bd_prod = qed_chain_get_prod_idx(&rxq->rx_bd_ring);
+ u16 cqe_prod = qed_chain_get_prod_idx(&rxq->rx_comp_ring);
+ struct eth_rx_prod_data rx_prods = {0};
+
+ /* Update producers */
+ rx_prods.bd_prod = cpu_to_le16(bd_prod);
+ rx_prods.cqe_prod = cpu_to_le16(cqe_prod);
+
+ /* Make sure that the BD and SGE data is updated before updating the
+ * producers since FW might read the BD/SGE right after the producer
+ * is updated.
+ */
+ wmb();
+
+ internal_ram_wr(rxq->hw_rxq_prod_addr, sizeof(rx_prods),
+ (u32 *)&rx_prods);
+
+ /* mmiowb is needed to synchronize doorbell writes from more than one
+ * processor. It guarantees that the write arrives to the device before
+ * the napi lock is released and another qede_poll is called (possibly
+ * on another CPU). Without this barrier, the next doorbell can bypass
+ * this doorbell. This is applicable to IA64/Altix systems.
+ */
+ mmiowb();
+}
+
+static u32 qede_get_rxhash(struct qede_dev *edev,
+ u8 bitfields,
+ __le32 rss_hash,
+ enum pkt_hash_types *rxhash_type)
+{
+ enum rss_hash_type htype;
+
+ htype = GET_FIELD(bitfields, ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE);
+
+ if ((edev->ndev->features & NETIF_F_RXHASH) && htype) {
+ *rxhash_type = ((htype == RSS_HASH_TYPE_IPV4) ||
+ (htype == RSS_HASH_TYPE_IPV6)) ?
+ PKT_HASH_TYPE_L3 : PKT_HASH_TYPE_L4;
+ return le32_to_cpu(rss_hash);
+ }
+ *rxhash_type = PKT_HASH_TYPE_NONE;
+ return 0;
+}
+
+static void qede_set_skb_csum(struct sk_buff *skb, u8 csum_flag)
+{
+ skb_checksum_none_assert(skb);
+
+ if (csum_flag & QEDE_CSUM_UNNECESSARY)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
+static inline void qede_skb_receive(struct qede_dev *edev,
+ struct qede_fastpath *fp,
+ struct sk_buff *skb,
+ u16 vlan_tag)
+{
+ if (vlan_tag)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ vlan_tag);
+
+ napi_gro_receive(&fp->napi, skb);
+}
+
+static u8 qede_check_csum(u16 flag)
+{
+ u16 csum_flag = 0;
+ u8 csum = 0;
+
+ if ((PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_MASK <<
+ PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_SHIFT) & flag) {
+ csum_flag |= PARSING_AND_ERR_FLAGS_L4CHKSMERROR_MASK <<
+ PARSING_AND_ERR_FLAGS_L4CHKSMERROR_SHIFT;
+ csum = QEDE_CSUM_UNNECESSARY;
+ }
+
+ csum_flag |= PARSING_AND_ERR_FLAGS_IPHDRERROR_MASK <<
+ PARSING_AND_ERR_FLAGS_IPHDRERROR_SHIFT;
+
+ if (csum_flag & flag)
+ return QEDE_CSUM_ERROR;
+
+ return csum;
+}
+
+static int qede_rx_int(struct qede_fastpath *fp, int budget)
+{
+ struct qede_dev *edev = fp->edev;
+ struct qede_rx_queue *rxq = fp->rxq;
+
+ u16 hw_comp_cons, sw_comp_cons, sw_rx_index, parse_flag;
+ int rx_pkt = 0;
+ u8 csum_flag;
+
+ hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
+ sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
+
+ /* Memory barrier to prevent the CPU from doing speculative reads of CQE
+ * / BD in the while-loop before reading hw_comp_cons. If the CQE is
+ * read before it is written by FW, then FW writes CQE and SB, and then
+ * the CPU reads the hw_comp_cons, it will use an old CQE.
+ */
+ rmb();
+
+ /* Loop to complete all indicated BDs */
+ while (sw_comp_cons != hw_comp_cons) {
+ struct eth_fast_path_rx_reg_cqe *fp_cqe;
+ enum pkt_hash_types rxhash_type;
+ enum eth_rx_cqe_type cqe_type;
+ struct sw_rx_data *sw_rx_data;
+ union eth_rx_cqe *cqe;
+ struct sk_buff *skb;
+ u16 len, pad;
+ u32 rx_hash;
+ u8 *data;
+
+ /* Get the CQE from the completion ring */
+ cqe = (union eth_rx_cqe *)
+ qed_chain_consume(&rxq->rx_comp_ring);
+ cqe_type = cqe->fast_path_regular.type;
+
+ if (unlikely(cqe_type == ETH_RX_CQE_TYPE_SLOW_PATH)) {
+ edev->ops->eth_cqe_completion(
+ edev->cdev, fp->rss_id,
+ (struct eth_slow_path_rx_cqe *)cqe);
+ goto next_cqe;
+ }
+
+ /* Get the data from the SW ring */
+ sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
+ sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
+ data = sw_rx_data->data;
+
+ fp_cqe = &cqe->fast_path_regular;
+ len = le16_to_cpu(fp_cqe->pkt_len);
+ pad = fp_cqe->placement_offset;
+
+ /* For every Rx BD consumed, we allocate a new BD so the BD ring
+ * is always with a fixed size. If allocation fails, we take the
+ * consumed BD and return it to the ring in the PROD position.
+ * The packet that was received on that BD will be dropped (and
+ * not passed to the upper stack).
+ */
+ if (likely(qede_alloc_rx_buffer(edev, rxq) == 0)) {
+ dma_unmap_single(&edev->pdev->dev,
+ dma_unmap_addr(sw_rx_data, mapping),
+ rxq->rx_buf_size, DMA_FROM_DEVICE);
+
+ /* If this is an error packet then drop it */
+ parse_flag =
+ le16_to_cpu(cqe->fast_path_regular.pars_flags.flags);
+ csum_flag = qede_check_csum(parse_flag);
+ if (csum_flag == QEDE_CSUM_ERROR) {
+ DP_NOTICE(edev,
+ "CQE in CONS = %u has error, flags = %x, dropping incoming packet\n",
+ sw_comp_cons, parse_flag);
+ rxq->rx_hw_errors++;
+ kfree(data);
+ goto next_rx;
+ }
+
+ skb = build_skb(data, 0);
+
+ if (unlikely(!skb)) {
+ DP_NOTICE(edev,
+ "Build_skb failed, dropping incoming packet\n");
+ kfree(data);
+ rxq->rx_alloc_errors++;
+ goto next_rx;
+ }
+
+ skb_reserve(skb, pad);
+
+ } else {
+ DP_NOTICE(edev,
+ "New buffer allocation failed, dropping incoming packet and reusing its buffer\n");
+ qede_reuse_rx_data(rxq);
+ rxq->rx_alloc_errors++;
+ goto next_cqe;
+ }
+
+ sw_rx_data->data = NULL;
+
+ skb_put(skb, len);
+
+ skb->protocol = eth_type_trans(skb, edev->ndev);
+
+ rx_hash = qede_get_rxhash(edev, fp_cqe->bitfields,
+ fp_cqe->rss_hash,
+ &rxhash_type);
+
+ skb_set_hash(skb, rx_hash, rxhash_type);
+
+ qede_set_skb_csum(skb, csum_flag);
+
+ skb_record_rx_queue(skb, fp->rss_id);
+
+ qede_skb_receive(edev, fp, skb, le16_to_cpu(fp_cqe->vlan_tag));
+
+ qed_chain_consume(&rxq->rx_bd_ring);
+
+next_rx:
+ rxq->sw_rx_cons++;
+ rx_pkt++;
+
+next_cqe: /* don't consume bd rx buffer */
+ qed_chain_recycle_consumed(&rxq->rx_comp_ring);
+ sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
+ /* CR TPA - revisit how to handle budget in TPA perhaps
+ * increase on "end"
+ */
+ if (rx_pkt == budget)
+ break;
+ } /* repeat while sw_comp_cons != hw_comp_cons... */
+
+ /* Update producers */
+ qede_update_rx_prod(edev, rxq);
+
+ return rx_pkt;
+}
+
+static int qede_poll(struct napi_struct *napi, int budget)
+{
+ int work_done = 0;
+ struct qede_fastpath *fp = container_of(napi, struct qede_fastpath,
+ napi);
+ struct qede_dev *edev = fp->edev;
+
+ while (1) {
+ u8 tc;
+
+ for (tc = 0; tc < edev->num_tc; tc++)
+ if (qede_txq_has_work(&fp->txqs[tc]))
+ qede_tx_int(edev, &fp->txqs[tc]);
+
+ if (qede_has_rx_work(fp->rxq)) {
+ work_done += qede_rx_int(fp, budget - work_done);
+
+ /* must not complete if we consumed full budget */
+ if (work_done >= budget)
+ break;
+ }
+
+ /* Fall out from the NAPI loop if needed */
+ if (!(qede_has_rx_work(fp->rxq) || qede_has_tx_work(fp))) {
+ qed_sb_update_sb_idx(fp->sb_info);
+ /* *_has_*_work() reads the status block,
+ * thus we need to ensure that status block indices
+ * have been actually read (qed_sb_update_sb_idx)
+ * prior to this check (*_has_*_work) so that
+ * we won't write the "newer" value of the status block
+ * to HW (if there was a DMA right after
+ * qede_has_rx_work and if there is no rmb, the memory
+ * reading (qed_sb_update_sb_idx) may be postponed
+ * to right before *_ack_sb). In this case there
+ * will never be another interrupt until there is
+ * another update of the status block, while there
+ * is still unhandled work.
+ */
+ rmb();
+
+ if (!(qede_has_rx_work(fp->rxq) ||
+ qede_has_tx_work(fp))) {
+ napi_complete(napi);
+ /* Update and reenable interrupts */
+ qed_sb_ack(fp->sb_info, IGU_INT_ENABLE,
+ 1 /*update*/);
+ break;
+ }
+ }
+ }
+
+ return work_done;
+}
+
+static irqreturn_t qede_msix_fp_int(int irq, void *fp_cookie)
+{
+ struct qede_fastpath *fp = fp_cookie;
+
+ qed_sb_ack(fp->sb_info, IGU_INT_DISABLE, 0 /*do not update*/);
+
+ napi_schedule_irqoff(&fp->napi);
+ return IRQ_HANDLED;
+}
+
+/* -------------------------------------------------------------------------
+ * END OF FAST-PATH
+ * -------------------------------------------------------------------------
+ */
+
+static int qede_open(struct net_device *ndev);
+static int qede_close(struct net_device *ndev);
+static int qede_set_mac_addr(struct net_device *ndev, void *p);
+static void qede_set_rx_mode(struct net_device *ndev);
+static void qede_config_rx_mode(struct net_device *ndev);
+
+static int qede_set_ucast_rx_mac(struct qede_dev *edev,
+ enum qed_filter_xcast_params_type opcode,
+ unsigned char mac[ETH_ALEN])
+{
+ struct qed_filter_params filter_cmd;
+
+ memset(&filter_cmd, 0, sizeof(filter_cmd));
+ filter_cmd.type = QED_FILTER_TYPE_UCAST;
+ filter_cmd.filter.ucast.type = opcode;
+ filter_cmd.filter.ucast.mac_valid = 1;
+ ether_addr_copy(filter_cmd.filter.ucast.mac, mac);
+
+ return edev->ops->filter_config(edev->cdev, &filter_cmd);
+}
+
+void qede_fill_by_demand_stats(struct qede_dev *edev)
+{
+ struct qed_eth_stats stats;
+
+ edev->ops->get_vport_stats(edev->cdev, &stats);
+ edev->stats.no_buff_discards = stats.no_buff_discards;
+ edev->stats.rx_ucast_bytes = stats.rx_ucast_bytes;
+ edev->stats.rx_mcast_bytes = stats.rx_mcast_bytes;
+ edev->stats.rx_bcast_bytes = stats.rx_bcast_bytes;
+ edev->stats.rx_ucast_pkts = stats.rx_ucast_pkts;
+ edev->stats.rx_mcast_pkts = stats.rx_mcast_pkts;
+ edev->stats.rx_bcast_pkts = stats.rx_bcast_pkts;
+ edev->stats.mftag_filter_discards = stats.mftag_filter_discards;
+ edev->stats.mac_filter_discards = stats.mac_filter_discards;
+
+ edev->stats.tx_ucast_bytes = stats.tx_ucast_bytes;
+ edev->stats.tx_mcast_bytes = stats.tx_mcast_bytes;
+ edev->stats.tx_bcast_bytes = stats.tx_bcast_bytes;
+ edev->stats.tx_ucast_pkts = stats.tx_ucast_pkts;
+ edev->stats.tx_mcast_pkts = stats.tx_mcast_pkts;
+ edev->stats.tx_bcast_pkts = stats.tx_bcast_pkts;
+ edev->stats.tx_err_drop_pkts = stats.tx_err_drop_pkts;
+ edev->stats.coalesced_pkts = stats.tpa_coalesced_pkts;
+ edev->stats.coalesced_events = stats.tpa_coalesced_events;
+ edev->stats.coalesced_aborts_num = stats.tpa_aborts_num;
+ edev->stats.non_coalesced_pkts = stats.tpa_not_coalesced_pkts;
+ edev->stats.coalesced_bytes = stats.tpa_coalesced_bytes;
+
+ edev->stats.rx_64_byte_packets = stats.rx_64_byte_packets;
+ edev->stats.rx_127_byte_packets = stats.rx_127_byte_packets;
+ edev->stats.rx_255_byte_packets = stats.rx_255_byte_packets;
+ edev->stats.rx_511_byte_packets = stats.rx_511_byte_packets;
+ edev->stats.rx_1023_byte_packets = stats.rx_1023_byte_packets;
+ edev->stats.rx_1518_byte_packets = stats.rx_1518_byte_packets;
+ edev->stats.rx_1522_byte_packets = stats.rx_1522_byte_packets;
+ edev->stats.rx_2047_byte_packets = stats.rx_2047_byte_packets;
+ edev->stats.rx_4095_byte_packets = stats.rx_4095_byte_packets;
+ edev->stats.rx_9216_byte_packets = stats.rx_9216_byte_packets;
+ edev->stats.rx_16383_byte_packets = stats.rx_16383_byte_packets;
+ edev->stats.rx_crc_errors = stats.rx_crc_errors;
+ edev->stats.rx_mac_crtl_frames = stats.rx_mac_crtl_frames;
+ edev->stats.rx_pause_frames = stats.rx_pause_frames;
+ edev->stats.rx_pfc_frames = stats.rx_pfc_frames;
+ edev->stats.rx_align_errors = stats.rx_align_errors;
+ edev->stats.rx_carrier_errors = stats.rx_carrier_errors;
+ edev->stats.rx_oversize_packets = stats.rx_oversize_packets;
+ edev->stats.rx_jabbers = stats.rx_jabbers;
+ edev->stats.rx_undersize_packets = stats.rx_undersize_packets;
+ edev->stats.rx_fragments = stats.rx_fragments;
+ edev->stats.tx_64_byte_packets = stats.tx_64_byte_packets;
+ edev->stats.tx_65_to_127_byte_packets = stats.tx_65_to_127_byte_packets;
+ edev->stats.tx_128_to_255_byte_packets =
+ stats.tx_128_to_255_byte_packets;
+ edev->stats.tx_256_to_511_byte_packets =
+ stats.tx_256_to_511_byte_packets;
+ edev->stats.tx_512_to_1023_byte_packets =
+ stats.tx_512_to_1023_byte_packets;
+ edev->stats.tx_1024_to_1518_byte_packets =
+ stats.tx_1024_to_1518_byte_packets;
+ edev->stats.tx_1519_to_2047_byte_packets =
+ stats.tx_1519_to_2047_byte_packets;
+ edev->stats.tx_2048_to_4095_byte_packets =
+ stats.tx_2048_to_4095_byte_packets;
+ edev->stats.tx_4096_to_9216_byte_packets =
+ stats.tx_4096_to_9216_byte_packets;
+ edev->stats.tx_9217_to_16383_byte_packets =
+ stats.tx_9217_to_16383_byte_packets;
+ edev->stats.tx_pause_frames = stats.tx_pause_frames;
+ edev->stats.tx_pfc_frames = stats.tx_pfc_frames;
+ edev->stats.tx_lpi_entry_count = stats.tx_lpi_entry_count;
+ edev->stats.tx_total_collisions = stats.tx_total_collisions;
+ edev->stats.brb_truncates = stats.brb_truncates;
+ edev->stats.brb_discards = stats.brb_discards;
+ edev->stats.tx_mac_ctrl_frames = stats.tx_mac_ctrl_frames;
+}
+
+static struct rtnl_link_stats64 *qede_get_stats64(
+ struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+
+ qede_fill_by_demand_stats(edev);
+
+ stats->rx_packets = edev->stats.rx_ucast_pkts +
+ edev->stats.rx_mcast_pkts +
+ edev->stats.rx_bcast_pkts;
+ stats->tx_packets = edev->stats.tx_ucast_pkts +
+ edev->stats.tx_mcast_pkts +
+ edev->stats.tx_bcast_pkts;
+
+ stats->rx_bytes = edev->stats.rx_ucast_bytes +
+ edev->stats.rx_mcast_bytes +
+ edev->stats.rx_bcast_bytes;
+
+ stats->tx_bytes = edev->stats.tx_ucast_bytes +
+ edev->stats.tx_mcast_bytes +
+ edev->stats.tx_bcast_bytes;
+
+ stats->tx_errors = edev->stats.tx_err_drop_pkts;
+ stats->multicast = edev->stats.rx_mcast_pkts +
+ edev->stats.rx_bcast_pkts;
+
+ stats->rx_fifo_errors = edev->stats.no_buff_discards;
+
+ stats->collisions = edev->stats.tx_total_collisions;
+ stats->rx_crc_errors = edev->stats.rx_crc_errors;
+ stats->rx_frame_errors = edev->stats.rx_align_errors;
+
+ return stats;
+}
+
+static const struct net_device_ops qede_netdev_ops = {
+ .ndo_open = qede_open,
+ .ndo_stop = qede_close,
+ .ndo_start_xmit = qede_start_xmit,
+ .ndo_set_rx_mode = qede_set_rx_mode,
+ .ndo_set_mac_address = qede_set_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = qede_change_mtu,
+ .ndo_get_stats64 = qede_get_stats64,
+};
+
+/* -------------------------------------------------------------------------
+ * START OF PROBE / REMOVE
+ * -------------------------------------------------------------------------
+ */
+
+static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev,
+ struct pci_dev *pdev,
+ struct qed_dev_eth_info *info,
+ u32 dp_module,
+ u8 dp_level)
+{
+ struct net_device *ndev;
+ struct qede_dev *edev;
+
+ ndev = alloc_etherdev_mqs(sizeof(*edev),
+ info->num_queues,
+ info->num_queues);
+ if (!ndev) {
+ pr_err("etherdev allocation failed\n");
+ return NULL;
+ }
+
+ edev = netdev_priv(ndev);
+ edev->ndev = ndev;
+ edev->cdev = cdev;
+ edev->pdev = pdev;
+ edev->dp_module = dp_module;
+ edev->dp_level = dp_level;
+ edev->ops = qed_ops;
+ edev->q_num_rx_buffers = NUM_RX_BDS_DEF;
+ edev->q_num_tx_buffers = NUM_TX_BDS_DEF;
+
+ DP_INFO(edev, "Allocated netdev with 64 tx queues and 64 rx queues\n");
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ memset(&edev->stats, 0, sizeof(edev->stats));
+ memcpy(&edev->dev_info, info, sizeof(*info));
+
+ edev->num_tc = edev->dev_info.num_tc;
+
+ return edev;
+}
+
+static void qede_init_ndev(struct qede_dev *edev)
+{
+ struct net_device *ndev = edev->ndev;
+ struct pci_dev *pdev = edev->pdev;
+ u32 hw_features;
+
+ pci_set_drvdata(pdev, ndev);
+
+ ndev->mem_start = edev->dev_info.common.pci_mem_start;
+ ndev->base_addr = ndev->mem_start;
+ ndev->mem_end = edev->dev_info.common.pci_mem_end;
+ ndev->irq = edev->dev_info.common.pci_irq;
+
+ ndev->watchdog_timeo = TX_TIMEOUT;
+
+ ndev->netdev_ops = &qede_netdev_ops;
+
+ qede_set_ethtool_ops(ndev);
+
+ /* user-changeble features */
+ hw_features = NETIF_F_GRO | NETIF_F_SG |
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO | NETIF_F_TSO6;
+
+ ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
+ NETIF_F_HIGHDMA;
+ ndev->features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
+ NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HIGHDMA |
+ NETIF_F_HW_VLAN_CTAG_TX;
+
+ ndev->hw_features = hw_features;
+
+ /* Set network device HW mac */
+ ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac);
+}
+
+/* This function converts from 32b param to two params of level and module
+ * Input 32b decoding:
+ * b31 - enable all NOTICE prints. NOTICE prints are for deviation from the
+ * 'happy' flow, e.g. memory allocation failed.
+ * b30 - enable all INFO prints. INFO prints are for major steps in the flow
+ * and provide important parameters.
+ * b29-b0 - per-module bitmap, where each bit enables VERBOSE prints of that
+ * module. VERBOSE prints are for tracking the specific flow in low level.
+ *
+ * Notice that the level should be that of the lowest required logs.
+ */
+void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level)
+{
+ *p_dp_level = QED_LEVEL_NOTICE;
+ *p_dp_module = 0;
+
+ if (debug & QED_LOG_VERBOSE_MASK) {
+ *p_dp_level = QED_LEVEL_VERBOSE;
+ *p_dp_module = (debug & 0x3FFFFFFF);
+ } else if (debug & QED_LOG_INFO_MASK) {
+ *p_dp_level = QED_LEVEL_INFO;
+ } else if (debug & QED_LOG_NOTICE_MASK) {
+ *p_dp_level = QED_LEVEL_NOTICE;
+ }
+}
+
+static void qede_free_fp_array(struct qede_dev *edev)
+{
+ if (edev->fp_array) {
+ struct qede_fastpath *fp;
+ int i;
+
+ for_each_rss(i) {
+ fp = &edev->fp_array[i];
+
+ kfree(fp->sb_info);
+ kfree(fp->rxq);
+ kfree(fp->txqs);
+ }
+ kfree(edev->fp_array);
+ }
+ edev->num_rss = 0;
+}
+
+static int qede_alloc_fp_array(struct qede_dev *edev)
+{
+ struct qede_fastpath *fp;
+ int i;
+
+ edev->fp_array = kcalloc(QEDE_RSS_CNT(edev),
+ sizeof(*edev->fp_array), GFP_KERNEL);
+ if (!edev->fp_array) {
+ DP_NOTICE(edev, "fp array allocation failed\n");
+ goto err;
+ }
+
+ for_each_rss(i) {
+ fp = &edev->fp_array[i];
+
+ fp->sb_info = kcalloc(1, sizeof(*fp->sb_info), GFP_KERNEL);
+ if (!fp->sb_info) {
+ DP_NOTICE(edev, "sb info struct allocation failed\n");
+ goto err;
+ }
+
+ fp->rxq = kcalloc(1, sizeof(*fp->rxq), GFP_KERNEL);
+ if (!fp->rxq) {
+ DP_NOTICE(edev, "RXQ struct allocation failed\n");
+ goto err;
+ }
+
+ fp->txqs = kcalloc(edev->num_tc, sizeof(*fp->txqs), GFP_KERNEL);
+ if (!fp->txqs) {
+ DP_NOTICE(edev, "TXQ array allocation failed\n");
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ qede_free_fp_array(edev);
+ return -ENOMEM;
+}
+
+static void qede_sp_task(struct work_struct *work)
+{
+ struct qede_dev *edev = container_of(work, struct qede_dev,
+ sp_task.work);
+ mutex_lock(&edev->qede_lock);
+
+ if (edev->state == QEDE_STATE_OPEN) {
+ if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags))
+ qede_config_rx_mode(edev->ndev);
+ }
+
+ mutex_unlock(&edev->qede_lock);
+}
+
+static void qede_update_pf_params(struct qed_dev *cdev)
+{
+ struct qed_pf_params pf_params;
+
+ /* 16 rx + 16 tx */
+ memset(&pf_params, 0, sizeof(struct qed_pf_params));
+ pf_params.eth_pf_params.num_cons = 32;
+ qed_ops->common->update_pf_params(cdev, &pf_params);
+}
+
+enum qede_probe_mode {
+ QEDE_PROBE_NORMAL,
+};
+
+static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
+ enum qede_probe_mode mode)
+{
+ struct qed_slowpath_params params;
+ struct qed_dev_eth_info dev_info;
+ struct qede_dev *edev;
+ struct qed_dev *cdev;
+ int rc;
+
+ if (unlikely(dp_level & QED_LEVEL_INFO))
+ pr_notice("Starting qede probe\n");
+
+ cdev = qed_ops->common->probe(pdev, QED_PROTOCOL_ETH,
+ dp_module, dp_level);
+ if (!cdev) {
+ rc = -ENODEV;
+ goto err0;
+ }
+
+ qede_update_pf_params(cdev);
+
+ /* Start the Slowpath-process */
+ memset(&params, 0, sizeof(struct qed_slowpath_params));
+ params.int_mode = QED_INT_MODE_MSIX;
+ params.drv_major = QEDE_MAJOR_VERSION;
+ params.drv_minor = QEDE_MINOR_VERSION;
+ params.drv_rev = QEDE_REVISION_VERSION;
+ params.drv_eng = QEDE_ENGINEERING_VERSION;
+ strlcpy(params.name, "qede LAN", QED_DRV_VER_STR_SIZE);
+ rc = qed_ops->common->slowpath_start(cdev, &params);
+ if (rc) {
+ pr_notice("Cannot start slowpath\n");
+ goto err1;
+ }
+
+ /* Learn information crucial for qede to progress */
+ rc = qed_ops->fill_dev_info(cdev, &dev_info);
+ if (rc)
+ goto err2;
+
+ edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module,
+ dp_level);
+ if (!edev) {
+ rc = -ENOMEM;
+ goto err2;
+ }
+
+ qede_init_ndev(edev);
+
+ rc = register_netdev(edev->ndev);
+ if (rc) {
+ DP_NOTICE(edev, "Cannot register net-device\n");
+ goto err3;
+ }
+
+ edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION);
+
+ edev->ops->register_ops(cdev, &qede_ll_ops, edev);
+
+ INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task);
+ mutex_init(&edev->qede_lock);
+
+ DP_INFO(edev, "Ending successfully qede probe\n");
+
+ return 0;
+
+err3:
+ free_netdev(edev->ndev);
+err2:
+ qed_ops->common->slowpath_stop(cdev);
+err1:
+ qed_ops->common->remove(cdev);
+err0:
+ return rc;
+}
+
+static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ u32 dp_module = 0;
+ u8 dp_level = 0;
+
+ qede_config_debug(debug, &dp_module, &dp_level);
+
+ return __qede_probe(pdev, dp_module, dp_level,
+ QEDE_PROBE_NORMAL);
+}
+
+enum qede_remove_mode {
+ QEDE_REMOVE_NORMAL,
+};
+
+static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct qede_dev *edev = netdev_priv(ndev);
+ struct qed_dev *cdev = edev->cdev;
+
+ DP_INFO(edev, "Starting qede_remove\n");
+
+ cancel_delayed_work_sync(&edev->sp_task);
+ unregister_netdev(ndev);
+
+ edev->ops->common->set_power_state(cdev, PCI_D0);
+
+ pci_set_drvdata(pdev, NULL);
+
+ free_netdev(ndev);
+
+ /* Use global ops since we've freed edev */
+ qed_ops->common->slowpath_stop(cdev);
+ qed_ops->common->remove(cdev);
+
+ pr_notice("Ending successfully qede_remove\n");
+}
+
+static void qede_remove(struct pci_dev *pdev)
+{
+ __qede_remove(pdev, QEDE_REMOVE_NORMAL);
+}
+
+/* -------------------------------------------------------------------------
+ * START OF LOAD / UNLOAD
+ * -------------------------------------------------------------------------
+ */
+
+static int qede_set_num_queues(struct qede_dev *edev)
+{
+ int rc;
+ u16 rss_num;
+
+ /* Setup queues according to possible resources*/
+ rss_num = netif_get_num_default_rss_queues() *
+ edev->dev_info.common.num_hwfns;
+
+ rss_num = min_t(u16, QEDE_MAX_RSS_CNT(edev), rss_num);
+
+ rc = edev->ops->common->set_fp_int(edev->cdev, rss_num);
+ if (rc > 0) {
+ /* Managed to request interrupts for our queues */
+ edev->num_rss = rc;
+ DP_INFO(edev, "Managed %d [of %d] RSS queues\n",
+ QEDE_RSS_CNT(edev), rss_num);
+ rc = 0;
+ }
+ return rc;
+}
+
+static void qede_free_mem_sb(struct qede_dev *edev,
+ struct qed_sb_info *sb_info)
+{
+ if (sb_info->sb_virt)
+ dma_free_coherent(&edev->pdev->dev, sizeof(*sb_info->sb_virt),
+ (void *)sb_info->sb_virt, sb_info->sb_phys);
+}
+
+/* This function allocates fast-path status block memory */
+static int qede_alloc_mem_sb(struct qede_dev *edev,
+ struct qed_sb_info *sb_info,
+ u16 sb_id)
+{
+ struct status_block *sb_virt;
+ dma_addr_t sb_phys;
+ int rc;
+
+ sb_virt = dma_alloc_coherent(&edev->pdev->dev,
+ sizeof(*sb_virt),
+ &sb_phys, GFP_KERNEL);
+ if (!sb_virt) {
+ DP_ERR(edev, "Status block allocation failed\n");
+ return -ENOMEM;
+ }
+
+ rc = edev->ops->common->sb_init(edev->cdev, sb_info,
+ sb_virt, sb_phys, sb_id,
+ QED_SB_TYPE_L2_QUEUE);
+ if (rc) {
+ DP_ERR(edev, "Status block initialization failed\n");
+ dma_free_coherent(&edev->pdev->dev, sizeof(*sb_virt),
+ sb_virt, sb_phys);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void qede_free_rx_buffers(struct qede_dev *edev,
+ struct qede_rx_queue *rxq)
+{
+ u16 i;
+
+ for (i = rxq->sw_rx_cons; i != rxq->sw_rx_prod; i++) {
+ struct sw_rx_data *rx_buf;
+ u8 *data;
+
+ rx_buf = &rxq->sw_rx_ring[i & NUM_RX_BDS_MAX];
+ data = rx_buf->data;
+
+ dma_unmap_single(&edev->pdev->dev,
+ dma_unmap_addr(rx_buf, mapping),
+ rxq->rx_buf_size, DMA_FROM_DEVICE);
+
+ rx_buf->data = NULL;
+ kfree(data);
+ }
+}
+
+static void qede_free_mem_rxq(struct qede_dev *edev,
+ struct qede_rx_queue *rxq)
+{
+ /* Free rx buffers */
+ qede_free_rx_buffers(edev, rxq);
+
+ /* Free the parallel SW ring */
+ kfree(rxq->sw_rx_ring);
+
+ /* Free the real RQ ring used by FW */
+ edev->ops->common->chain_free(edev->cdev, &rxq->rx_bd_ring);
+ edev->ops->common->chain_free(edev->cdev, &rxq->rx_comp_ring);
+}
+
+static int qede_alloc_rx_buffer(struct qede_dev *edev,
+ struct qede_rx_queue *rxq)
+{
+ struct sw_rx_data *sw_rx_data;
+ struct eth_rx_bd *rx_bd;
+ dma_addr_t mapping;
+ u16 rx_buf_size;
+ u8 *data;
+
+ rx_buf_size = rxq->rx_buf_size;
+
+ data = kmalloc(rx_buf_size, GFP_ATOMIC);
+ if (unlikely(!data)) {
+ DP_NOTICE(edev, "Failed to allocate Rx data\n");
+ return -ENOMEM;
+ }
+
+ mapping = dma_map_single(&edev->pdev->dev, data,
+ rx_buf_size, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
+ kfree(data);
+ DP_NOTICE(edev, "Failed to map Rx buffer\n");
+ return -ENOMEM;
+ }
+
+ sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX];
+ sw_rx_data->data = data;
+
+ dma_unmap_addr_set(sw_rx_data, mapping, mapping);
+
+ /* Advance PROD and get BD pointer */
+ rx_bd = (struct eth_rx_bd *)qed_chain_produce(&rxq->rx_bd_ring);
+ WARN_ON(!rx_bd);
+ rx_bd->addr.hi = cpu_to_le32(upper_32_bits(mapping));
+ rx_bd->addr.lo = cpu_to_le32(lower_32_bits(mapping));
+
+ rxq->sw_rx_prod++;
+
+ return 0;
+}
+
+/* This function allocates all memory needed per Rx queue */
+static int qede_alloc_mem_rxq(struct qede_dev *edev,
+ struct qede_rx_queue *rxq)
+{
+ int i, rc, size, num_allocated;
+
+ rxq->num_rx_buffers = edev->q_num_rx_buffers;
+
+ rxq->rx_buf_size = NET_IP_ALIGN +
+ ETH_OVERHEAD +
+ edev->ndev->mtu +
+ QEDE_FW_RX_ALIGN_END;
+
+ /* Allocate the parallel driver ring for Rx buffers */
+ size = sizeof(*rxq->sw_rx_ring) * NUM_RX_BDS_MAX;
+ rxq->sw_rx_ring = kzalloc(size, GFP_KERNEL);
+ if (!rxq->sw_rx_ring) {
+ DP_ERR(edev, "Rx buffers ring allocation failed\n");
+ goto err;
+ }
+
+ /* Allocate FW Rx ring */
+ rc = edev->ops->common->chain_alloc(edev->cdev,
+ QED_CHAIN_USE_TO_CONSUME_PRODUCE,
+ QED_CHAIN_MODE_NEXT_PTR,
+ NUM_RX_BDS_MAX,
+ sizeof(struct eth_rx_bd),
+ &rxq->rx_bd_ring);
+
+ if (rc)
+ goto err;
+
+ /* Allocate FW completion ring */
+ rc = edev->ops->common->chain_alloc(edev->cdev,
+ QED_CHAIN_USE_TO_CONSUME,
+ QED_CHAIN_MODE_PBL,
+ NUM_RX_BDS_MAX,
+ sizeof(union eth_rx_cqe),
+ &rxq->rx_comp_ring);
+ if (rc)
+ goto err;
+
+ /* Allocate buffers for the Rx ring */
+ for (i = 0; i < rxq->num_rx_buffers; i++) {
+ rc = qede_alloc_rx_buffer(edev, rxq);
+ if (rc)
+ break;
+ }
+ num_allocated = i;
+ if (!num_allocated) {
+ DP_ERR(edev, "Rx buffers allocation failed\n");
+ goto err;
+ } else if (num_allocated < rxq->num_rx_buffers) {
+ DP_NOTICE(edev,
+ "Allocated less buffers than desired (%d allocated)\n",
+ num_allocated);
+ }
+
+ return 0;
+
+err:
+ qede_free_mem_rxq(edev, rxq);
+ return -ENOMEM;
+}
+
+static void qede_free_mem_txq(struct qede_dev *edev,
+ struct qede_tx_queue *txq)
+{
+ /* Free the parallel SW ring */
+ kfree(txq->sw_tx_ring);
+
+ /* Free the real RQ ring used by FW */
+ edev->ops->common->chain_free(edev->cdev, &txq->tx_pbl);
+}
+
+/* This function allocates all memory needed per Tx queue */
+static int qede_alloc_mem_txq(struct qede_dev *edev,
+ struct qede_tx_queue *txq)
+{
+ int size, rc;
+ union eth_tx_bd_types *p_virt;
+
+ txq->num_tx_buffers = edev->q_num_tx_buffers;
+
+ /* Allocate the parallel driver ring for Tx buffers */
+ size = sizeof(*txq->sw_tx_ring) * NUM_TX_BDS_MAX;
+ txq->sw_tx_ring = kzalloc(size, GFP_KERNEL);
+ if (!txq->sw_tx_ring) {
+ DP_NOTICE(edev, "Tx buffers ring allocation failed\n");
+ goto err;
+ }
+
+ rc = edev->ops->common->chain_alloc(edev->cdev,
+ QED_CHAIN_USE_TO_CONSUME_PRODUCE,
+ QED_CHAIN_MODE_PBL,
+ NUM_TX_BDS_MAX,
+ sizeof(*p_virt),
+ &txq->tx_pbl);
+ if (rc)
+ goto err;
+
+ return 0;
+
+err:
+ qede_free_mem_txq(edev, txq);
+ return -ENOMEM;
+}
+
+/* This function frees all memory of a single fp */
+static void qede_free_mem_fp(struct qede_dev *edev,
+ struct qede_fastpath *fp)
+{
+ int tc;
+
+ qede_free_mem_sb(edev, fp->sb_info);
+
+ qede_free_mem_rxq(edev, fp->rxq);
+
+ for (tc = 0; tc < edev->num_tc; tc++)
+ qede_free_mem_txq(edev, &fp->txqs[tc]);
+}
+
+/* This function allocates all memory needed for a single fp (i.e. an entity
+ * which contains status block, one rx queue and multiple per-TC tx queues.
+ */
+static int qede_alloc_mem_fp(struct qede_dev *edev,
+ struct qede_fastpath *fp)
+{
+ int rc, tc;
+
+ rc = qede_alloc_mem_sb(edev, fp->sb_info, fp->rss_id);
+ if (rc)
+ goto err;
+
+ rc = qede_alloc_mem_rxq(edev, fp->rxq);
+ if (rc)
+ goto err;
+
+ for (tc = 0; tc < edev->num_tc; tc++) {
+ rc = qede_alloc_mem_txq(edev, &fp->txqs[tc]);
+ if (rc)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ qede_free_mem_fp(edev, fp);
+ return -ENOMEM;
+}
+
+static void qede_free_mem_load(struct qede_dev *edev)
+{
+ int i;
+
+ for_each_rss(i) {
+ struct qede_fastpath *fp = &edev->fp_array[i];
+
+ qede_free_mem_fp(edev, fp);
+ }
+}
+
+/* This function allocates all qede memory at NIC load. */
+static int qede_alloc_mem_load(struct qede_dev *edev)
+{
+ int rc = 0, rss_id;
+
+ for (rss_id = 0; rss_id < QEDE_RSS_CNT(edev); rss_id++) {
+ struct qede_fastpath *fp = &edev->fp_array[rss_id];
+
+ rc = qede_alloc_mem_fp(edev, fp);
+ if (rc)
+ break;
+ }
+
+ if (rss_id != QEDE_RSS_CNT(edev)) {
+ /* Failed allocating memory for all the queues */
+ if (!rss_id) {
+ DP_ERR(edev,
+ "Failed to allocate memory for the leading queue\n");
+ rc = -ENOMEM;
+ } else {
+ DP_NOTICE(edev,
+ "Failed to allocate memory for all of RSS queues\n Desired: %d queues, allocated: %d queues\n",
+ QEDE_RSS_CNT(edev), rss_id);
+ }
+ edev->num_rss = rss_id;
+ }
+
+ return 0;
+}
+
+/* This function inits fp content and resets the SB, RXQ and TXQ structures */
+static void qede_init_fp(struct qede_dev *edev)
+{
+ int rss_id, txq_index, tc;
+ struct qede_fastpath *fp;
+
+ for_each_rss(rss_id) {
+ fp = &edev->fp_array[rss_id];
+
+ fp->edev = edev;
+ fp->rss_id = rss_id;
+
+ memset((void *)&fp->napi, 0, sizeof(fp->napi));
+
+ memset((void *)fp->sb_info, 0, sizeof(*fp->sb_info));
+
+ memset((void *)fp->rxq, 0, sizeof(*fp->rxq));
+ fp->rxq->rxq_id = rss_id;
+
+ memset((void *)fp->txqs, 0, (edev->num_tc * sizeof(*fp->txqs)));
+ for (tc = 0; tc < edev->num_tc; tc++) {
+ txq_index = tc * QEDE_RSS_CNT(edev) + rss_id;
+ fp->txqs[tc].index = txq_index;
+ }
+
+ snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
+ edev->ndev->name, rss_id);
+ }
+}
+
+static int qede_set_real_num_queues(struct qede_dev *edev)
+{
+ int rc = 0;
+
+ rc = netif_set_real_num_tx_queues(edev->ndev, QEDE_TSS_CNT(edev));
+ if (rc) {
+ DP_NOTICE(edev, "Failed to set real number of Tx queues\n");
+ return rc;
+ }
+ rc = netif_set_real_num_rx_queues(edev->ndev, QEDE_RSS_CNT(edev));
+ if (rc) {
+ DP_NOTICE(edev, "Failed to set real number of Rx queues\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static void qede_napi_disable_remove(struct qede_dev *edev)
+{
+ int i;
+
+ for_each_rss(i) {
+ napi_disable(&edev->fp_array[i].napi);
+
+ netif_napi_del(&edev->fp_array[i].napi);
+ }
+}
+
+static void qede_napi_add_enable(struct qede_dev *edev)
+{
+ int i;
+
+ /* Add NAPI objects */
+ for_each_rss(i) {
+ netif_napi_add(edev->ndev, &edev->fp_array[i].napi,
+ qede_poll, NAPI_POLL_WEIGHT);
+ napi_enable(&edev->fp_array[i].napi);
+ }
+}
+
+static void qede_sync_free_irqs(struct qede_dev *edev)
+{
+ int i;
+
+ for (i = 0; i < edev->int_info.used_cnt; i++) {
+ if (edev->int_info.msix_cnt) {
+ synchronize_irq(edev->int_info.msix[i].vector);
+ free_irq(edev->int_info.msix[i].vector,
+ &edev->fp_array[i]);
+ } else {
+ edev->ops->common->simd_handler_clean(edev->cdev, i);
+ }
+ }
+
+ edev->int_info.used_cnt = 0;
+}
+
+static int qede_req_msix_irqs(struct qede_dev *edev)
+{
+ int i, rc;
+
+ /* Sanitize number of interrupts == number of prepared RSS queues */
+ if (QEDE_RSS_CNT(edev) > edev->int_info.msix_cnt) {
+ DP_ERR(edev,
+ "Interrupt mismatch: %d RSS queues > %d MSI-x vectors\n",
+ QEDE_RSS_CNT(edev), edev->int_info.msix_cnt);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < QEDE_RSS_CNT(edev); i++) {
+ rc = request_irq(edev->int_info.msix[i].vector,
+ qede_msix_fp_int, 0, edev->fp_array[i].name,
+ &edev->fp_array[i]);
+ if (rc) {
+ DP_ERR(edev, "Request fp %d irq failed\n", i);
+ qede_sync_free_irqs(edev);
+ return rc;
+ }
+ DP_VERBOSE(edev, NETIF_MSG_INTR,
+ "Requested fp irq for %s [entry %d]. Cookie is at %p\n",
+ edev->fp_array[i].name, i,
+ &edev->fp_array[i]);
+ edev->int_info.used_cnt++;
+ }
+
+ return 0;
+}
+
+static void qede_simd_fp_handler(void *cookie)
+{
+ struct qede_fastpath *fp = (struct qede_fastpath *)cookie;
+
+ napi_schedule_irqoff(&fp->napi);
+}
+
+static int qede_setup_irqs(struct qede_dev *edev)
+{
+ int i, rc = 0;
+
+ /* Learn Interrupt configuration */
+ rc = edev->ops->common->get_fp_int(edev->cdev, &edev->int_info);
+ if (rc)
+ return rc;
+
+ if (edev->int_info.msix_cnt) {
+ rc = qede_req_msix_irqs(edev);
+ if (rc)
+ return rc;
+ edev->ndev->irq = edev->int_info.msix[0].vector;
+ } else {
+ const struct qed_common_ops *ops;
+
+ /* qed should learn receive the RSS ids and callbacks */
+ ops = edev->ops->common;
+ for (i = 0; i < QEDE_RSS_CNT(edev); i++)
+ ops->simd_handler_config(edev->cdev,
+ &edev->fp_array[i], i,
+ qede_simd_fp_handler);
+ edev->int_info.used_cnt = QEDE_RSS_CNT(edev);
+ }
+ return 0;
+}
+
+static int qede_drain_txq(struct qede_dev *edev,
+ struct qede_tx_queue *txq,
+ bool allow_drain)
+{
+ int rc, cnt = 1000;
+
+ while (txq->sw_tx_cons != txq->sw_tx_prod) {
+ if (!cnt) {
+ if (allow_drain) {
+ DP_NOTICE(edev,
+ "Tx queue[%d] is stuck, requesting MCP to drain\n",
+ txq->index);
+ rc = edev->ops->common->drain(edev->cdev);
+ if (rc)
+ return rc;
+ return qede_drain_txq(edev, txq, false);
+ }
+ DP_NOTICE(edev,
+ "Timeout waiting for tx queue[%d]: PROD=%d, CONS=%d\n",
+ txq->index, txq->sw_tx_prod,
+ txq->sw_tx_cons);
+ return -ENODEV;
+ }
+ cnt--;
+ usleep_range(1000, 2000);
+ barrier();
+ }
+
+ /* FW finished processing, wait for HW to transmit all tx packets */
+ usleep_range(1000, 2000);
+
+ return 0;
+}
+
+static int qede_stop_queues(struct qede_dev *edev)
+{
+ struct qed_update_vport_params vport_update_params;
+ struct qed_dev *cdev = edev->cdev;
+ int rc, tc, i;
+
+ /* Disable the vport */
+ memset(&vport_update_params, 0, sizeof(vport_update_params));
+ vport_update_params.vport_id = 0;
+ vport_update_params.update_vport_active_flg = 1;
+ vport_update_params.vport_active_flg = 0;
+ vport_update_params.update_rss_flg = 0;
+
+ rc = edev->ops->vport_update(cdev, &vport_update_params);
+ if (rc) {
+ DP_ERR(edev, "Failed to update vport\n");
+ return rc;
+ }
+
+ /* Flush Tx queues. If needed, request drain from MCP */
+ for_each_rss(i) {
+ struct qede_fastpath *fp = &edev->fp_array[i];
+
+ for (tc = 0; tc < edev->num_tc; tc++) {
+ struct qede_tx_queue *txq = &fp->txqs[tc];
+
+ rc = qede_drain_txq(edev, txq, true);
+ if (rc)
+ return rc;
+ }
+ }
+
+ /* Stop all Queues in reverse order*/
+ for (i = QEDE_RSS_CNT(edev) - 1; i >= 0; i--) {
+ struct qed_stop_rxq_params rx_params;
+
+ /* Stop the Tx Queue(s)*/
+ for (tc = 0; tc < edev->num_tc; tc++) {
+ struct qed_stop_txq_params tx_params;
+
+ tx_params.rss_id = i;
+ tx_params.tx_queue_id = tc * QEDE_RSS_CNT(edev) + i;
+ rc = edev->ops->q_tx_stop(cdev, &tx_params);
+ if (rc) {
+ DP_ERR(edev, "Failed to stop TXQ #%d\n",
+ tx_params.tx_queue_id);
+ return rc;
+ }
+ }
+
+ /* Stop the Rx Queue*/
+ memset(&rx_params, 0, sizeof(rx_params));
+ rx_params.rss_id = i;
+ rx_params.rx_queue_id = i;
+
+ rc = edev->ops->q_rx_stop(cdev, &rx_params);
+ if (rc) {
+ DP_ERR(edev, "Failed to stop RXQ #%d\n", i);
+ return rc;
+ }
+ }
+
+ /* Stop the vport */
+ rc = edev->ops->vport_stop(cdev, 0);
+ if (rc)
+ DP_ERR(edev, "Failed to stop VPORT\n");
+
+ return rc;
+}
+
+static int qede_start_queues(struct qede_dev *edev)
+{
+ int rc, tc, i;
+ int vport_id = 0, drop_ttl0_flg = 1, vlan_removal_en = 1;
+ struct qed_dev *cdev = edev->cdev;
+ struct qed_update_vport_rss_params *rss_params = &edev->rss_params;
+ struct qed_update_vport_params vport_update_params;
+ struct qed_queue_start_common_params q_params;
+
+ if (!edev->num_rss) {
+ DP_ERR(edev,
+ "Cannot update V-VPORT as active as there are no Rx queues\n");
+ return -EINVAL;
+ }
+
+ rc = edev->ops->vport_start(cdev, vport_id,
+ edev->ndev->mtu,
+ drop_ttl0_flg,
+ vlan_removal_en);
+
+ if (rc) {
+ DP_ERR(edev, "Start V-PORT failed %d\n", rc);
+ return rc;
+ }
+
+ DP_VERBOSE(edev, NETIF_MSG_IFUP,
+ "Start vport ramrod passed, vport_id = %d, MTU = %d, vlan_removal_en = %d\n",
+ vport_id, edev->ndev->mtu + 0xe, vlan_removal_en);
+
+ for_each_rss(i) {
+ struct qede_fastpath *fp = &edev->fp_array[i];
+ dma_addr_t phys_table = fp->rxq->rx_comp_ring.pbl.p_phys_table;
+
+ memset(&q_params, 0, sizeof(q_params));
+ q_params.rss_id = i;
+ q_params.queue_id = i;
+ q_params.vport_id = 0;
+ q_params.sb = fp->sb_info->igu_sb_id;
+ q_params.sb_idx = RX_PI;
+
+ rc = edev->ops->q_rx_start(cdev, &q_params,
+ fp->rxq->rx_buf_size,
+ fp->rxq->rx_bd_ring.p_phys_addr,
+ phys_table,
+ fp->rxq->rx_comp_ring.page_cnt,
+ &fp->rxq->hw_rxq_prod_addr);
+ if (rc) {
+ DP_ERR(edev, "Start RXQ #%d failed %d\n", i, rc);
+ return rc;
+ }
+
+ fp->rxq->hw_cons_ptr = &fp->sb_info->sb_virt->pi_array[RX_PI];
+
+ qede_update_rx_prod(edev, fp->rxq);
+
+ for (tc = 0; tc < edev->num_tc; tc++) {
+ struct qede_tx_queue *txq = &fp->txqs[tc];
+ int txq_index = tc * QEDE_RSS_CNT(edev) + i;
+
+ memset(&q_params, 0, sizeof(q_params));
+ q_params.rss_id = i;
+ q_params.queue_id = txq_index;
+ q_params.vport_id = 0;
+ q_params.sb = fp->sb_info->igu_sb_id;
+ q_params.sb_idx = TX_PI(tc);
+
+ rc = edev->ops->q_tx_start(cdev, &q_params,
+ txq->tx_pbl.pbl.p_phys_table,
+ txq->tx_pbl.page_cnt,
+ &txq->doorbell_addr);
+ if (rc) {
+ DP_ERR(edev, "Start TXQ #%d failed %d\n",
+ txq_index, rc);
+ return rc;
+ }
+
+ txq->hw_cons_ptr =
+ &fp->sb_info->sb_virt->pi_array[TX_PI(tc)];
+ SET_FIELD(txq->tx_db.data.params,
+ ETH_DB_DATA_DEST, DB_DEST_XCM);
+ SET_FIELD(txq->tx_db.data.params, ETH_DB_DATA_AGG_CMD,
+ DB_AGG_CMD_SET);
+ SET_FIELD(txq->tx_db.data.params,
+ ETH_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_ETH_TX_BD_PROD_CMD);
+
+ txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD;
+ }
+ }
+
+ /* Prepare and send the vport enable */
+ memset(&vport_update_params, 0, sizeof(vport_update_params));
+ vport_update_params.vport_id = vport_id;
+ vport_update_params.update_vport_active_flg = 1;
+ vport_update_params.vport_active_flg = 1;
+
+ /* Fill struct with RSS params */
+ if (QEDE_RSS_CNT(edev) > 1) {
+ vport_update_params.update_rss_flg = 1;
+ for (i = 0; i < 128; i++)
+ rss_params->rss_ind_table[i] =
+ ethtool_rxfh_indir_default(i, QEDE_RSS_CNT(edev));
+ netdev_rss_key_fill(rss_params->rss_key,
+ sizeof(rss_params->rss_key));
+ } else {
+ memset(rss_params, 0, sizeof(*rss_params));
+ }
+ memcpy(&vport_update_params.rss_params, rss_params,
+ sizeof(*rss_params));
+
+ rc = edev->ops->vport_update(cdev, &vport_update_params);
+ if (rc) {
+ DP_ERR(edev, "Update V-PORT failed %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int qede_set_mcast_rx_mac(struct qede_dev *edev,
+ enum qed_filter_xcast_params_type opcode,
+ unsigned char *mac, int num_macs)
+{
+ struct qed_filter_params filter_cmd;
+ int i;
+
+ memset(&filter_cmd, 0, sizeof(filter_cmd));
+ filter_cmd.type = QED_FILTER_TYPE_MCAST;
+ filter_cmd.filter.mcast.type = opcode;
+ filter_cmd.filter.mcast.num = num_macs;
+
+ for (i = 0; i < num_macs; i++, mac += ETH_ALEN)
+ ether_addr_copy(filter_cmd.filter.mcast.mac[i], mac);
+
+ return edev->ops->filter_config(edev->cdev, &filter_cmd);
+}
+
+enum qede_unload_mode {
+ QEDE_UNLOAD_NORMAL,
+};
+
+static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode)
+{
+ struct qed_link_params link_params;
+ int rc;
+
+ DP_INFO(edev, "Starting qede unload\n");
+
+ mutex_lock(&edev->qede_lock);
+ edev->state = QEDE_STATE_CLOSED;
+
+ /* Close OS Tx */
+ 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;
+ }
+
+ DP_INFO(edev, "Stopped Queues\n");
+
+ edev->ops->fastpath_stop(edev->cdev);
+
+ /* Release the interrupts */
+ qede_sync_free_irqs(edev);
+ edev->ops->common->set_fp_int(edev->cdev, 0);
+
+ qede_napi_disable_remove(edev);
+
+ qede_free_mem_load(edev);
+ qede_free_fp_array(edev);
+
+out:
+ mutex_unlock(&edev->qede_lock);
+ DP_INFO(edev, "Ending qede unload\n");
+}
+
+enum qede_load_mode {
+ QEDE_LOAD_NORMAL,
+};
+
+static int qede_load(struct qede_dev *edev, enum qede_load_mode mode)
+{
+ struct qed_link_params link_params;
+ struct qed_link_output link_output;
+ int rc;
+
+ DP_INFO(edev, "Starting qede load\n");
+
+ rc = qede_set_num_queues(edev);
+ if (rc)
+ goto err0;
+
+ rc = qede_alloc_fp_array(edev);
+ if (rc)
+ goto err0;
+
+ qede_init_fp(edev);
+
+ rc = qede_alloc_mem_load(edev);
+ if (rc)
+ goto err1;
+ DP_INFO(edev, "Allocated %d RSS queues on %d TC/s\n",
+ QEDE_RSS_CNT(edev), edev->num_tc);
+
+ rc = qede_set_real_num_queues(edev);
+ if (rc)
+ goto err2;
+
+ qede_napi_add_enable(edev);
+ DP_INFO(edev, "Napi added and enabled\n");
+
+ rc = qede_setup_irqs(edev);
+ if (rc)
+ goto err3;
+ DP_INFO(edev, "Setup IRQs succeeded\n");
+
+ rc = qede_start_queues(edev);
+ if (rc)
+ goto err4;
+ DP_INFO(edev, "Start VPORT, RXQ and TXQ succeeded\n");
+
+ /* Add primary mac and set Rx filters */
+ ether_addr_copy(edev->primary_mac, edev->ndev->dev_addr);
+
+ mutex_lock(&edev->qede_lock);
+ edev->state = QEDE_STATE_OPEN;
+ mutex_unlock(&edev->qede_lock);
+
+ /* Ask for link-up using current configuration */
+ memset(&link_params, 0, sizeof(link_params));
+ link_params.link_up = true;
+ edev->ops->common->set_link(edev->cdev, &link_params);
+
+ /* Query whether link is already-up */
+ memset(&link_output, 0, sizeof(link_output));
+ edev->ops->common->get_link(edev->cdev, &link_output);
+ qede_link_update(edev, &link_output);
+
+ DP_INFO(edev, "Ending successfully qede load\n");
+
+ return 0;
+
+err4:
+ qede_sync_free_irqs(edev);
+ memset(&edev->int_info.msix_cnt, 0, sizeof(struct qed_int_info));
+err3:
+ qede_napi_disable_remove(edev);
+err2:
+ qede_free_mem_load(edev);
+err1:
+ edev->ops->common->set_fp_int(edev->cdev, 0);
+ qede_free_fp_array(edev);
+ edev->num_rss = 0;
+err0:
+ return rc;
+}
+
+void qede_reload(struct qede_dev *edev,
+ void (*func)(struct qede_dev *, union qede_reload_args *),
+ union qede_reload_args *args)
+{
+ qede_unload(edev, QEDE_UNLOAD_NORMAL);
+ /* Call function handler to update parameters
+ * needed for function load.
+ */
+ if (func)
+ func(edev, args);
+
+ qede_load(edev, QEDE_LOAD_NORMAL);
+
+ mutex_lock(&edev->qede_lock);
+ qede_config_rx_mode(edev->ndev);
+ mutex_unlock(&edev->qede_lock);
+}
+
+/* called with rtnl_lock */
+static int qede_open(struct net_device *ndev)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+
+ netif_carrier_off(ndev);
+
+ edev->ops->common->set_power_state(edev->cdev, PCI_D0);
+
+ return qede_load(edev, QEDE_LOAD_NORMAL);
+}
+
+static int qede_close(struct net_device *ndev)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+
+ qede_unload(edev, QEDE_UNLOAD_NORMAL);
+
+ return 0;
+}
+
+static void qede_link_update(void *dev, struct qed_link_output *link)
+{
+ struct qede_dev *edev = dev;
+
+ if (!netif_running(edev->ndev)) {
+ DP_VERBOSE(edev, NETIF_MSG_LINK, "Interface is not running\n");
+ return;
+ }
+
+ if (link->link_up) {
+ DP_NOTICE(edev, "Link is up\n");
+ netif_tx_start_all_queues(edev->ndev);
+ netif_carrier_on(edev->ndev);
+ } else {
+ DP_NOTICE(edev, "Link is down\n");
+ netif_tx_disable(edev->ndev);
+ netif_carrier_off(edev->ndev);
+ }
+}
+
+static int qede_set_mac_addr(struct net_device *ndev, void *p)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+ struct sockaddr *addr = p;
+ int rc;
+
+ ASSERT_RTNL(); /* @@@TBD To be removed */
+
+ DP_INFO(edev, "Set_mac_addr called\n");
+
+ if (!is_valid_ether_addr(addr->sa_data)) {
+ DP_NOTICE(edev, "The MAC address is not valid\n");
+ return -EFAULT;
+ }
+
+ ether_addr_copy(ndev->dev_addr, addr->sa_data);
+
+ if (!netif_running(ndev)) {
+ DP_NOTICE(edev, "The device is currently down\n");
+ return 0;
+ }
+
+ /* Remove the previous primary mac */
+ rc = qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_DEL,
+ edev->primary_mac);
+ if (rc)
+ return rc;
+
+ /* Add MAC filter according to the new unicast HW MAC address */
+ ether_addr_copy(edev->primary_mac, ndev->dev_addr);
+ return qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD,
+ edev->primary_mac);
+}
+
+static int
+qede_configure_mcast_filtering(struct net_device *ndev,
+ enum qed_filter_rx_mode_type *accept_flags)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+ unsigned char *mc_macs, *temp;
+ struct netdev_hw_addr *ha;
+ int rc = 0, mc_count;
+ size_t size;
+
+ size = 64 * ETH_ALEN;
+
+ mc_macs = kzalloc(size, GFP_KERNEL);
+ if (!mc_macs) {
+ DP_NOTICE(edev,
+ "Failed to allocate memory for multicast MACs\n");
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ temp = mc_macs;
+
+ /* Remove all previously configured MAC filters */
+ rc = qede_set_mcast_rx_mac(edev, QED_FILTER_XCAST_TYPE_DEL,
+ mc_macs, 1);
+ if (rc)
+ goto exit;
+
+ netif_addr_lock_bh(ndev);
+
+ mc_count = netdev_mc_count(ndev);
+ if (mc_count < 64) {
+ netdev_for_each_mc_addr(ha, ndev) {
+ ether_addr_copy(temp, ha->addr);
+ temp += ETH_ALEN;
+ }
+ }
+
+ netif_addr_unlock_bh(ndev);
+
+ /* Check for all multicast @@@TBD resource allocation */
+ if ((ndev->flags & IFF_ALLMULTI) ||
+ (mc_count > 64)) {
+ if (*accept_flags == QED_FILTER_RX_MODE_TYPE_REGULAR)
+ *accept_flags = QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC;
+ } else {
+ /* Add all multicast MAC filters */
+ rc = qede_set_mcast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD,
+ mc_macs, mc_count);
+ }
+
+exit:
+ kfree(mc_macs);
+ return rc;
+}
+
+static void qede_set_rx_mode(struct net_device *ndev)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+
+ DP_INFO(edev, "qede_set_rx_mode called\n");
+
+ if (edev->state != QEDE_STATE_OPEN) {
+ DP_INFO(edev,
+ "qede_set_rx_mode called while interface is down\n");
+ } else {
+ set_bit(QEDE_SP_RX_MODE, &edev->sp_flags);
+ schedule_delayed_work(&edev->sp_task, 0);
+ }
+}
+
+/* Must be called with qede_lock held */
+static void qede_config_rx_mode(struct net_device *ndev)
+{
+ enum qed_filter_rx_mode_type accept_flags = QED_FILTER_TYPE_UCAST;
+ struct qede_dev *edev = netdev_priv(ndev);
+ struct qed_filter_params rx_mode;
+ unsigned char *uc_macs, *temp;
+ struct netdev_hw_addr *ha;
+ int rc, uc_count;
+ size_t size;
+
+ netif_addr_lock_bh(ndev);
+
+ uc_count = netdev_uc_count(ndev);
+ size = uc_count * ETH_ALEN;
+
+ uc_macs = kzalloc(size, GFP_ATOMIC);
+ if (!uc_macs) {
+ DP_NOTICE(edev, "Failed to allocate memory for unicast MACs\n");
+ netif_addr_unlock_bh(ndev);
+ return;
+ }
+
+ temp = uc_macs;
+ netdev_for_each_uc_addr(ha, ndev) {
+ ether_addr_copy(temp, ha->addr);
+ temp += ETH_ALEN;
+ }
+
+ netif_addr_unlock_bh(ndev);
+
+ /* Configure the struct for the Rx mode */
+ memset(&rx_mode, 0, sizeof(struct qed_filter_params));
+ rx_mode.type = QED_FILTER_TYPE_RX_MODE;
+
+ /* Remove all previous unicast secondary macs and multicast macs
+ * (configrue / leave the primary mac)
+ */
+ rc = qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_REPLACE,
+ edev->primary_mac);
+ if (rc)
+ goto out;
+
+ /* Check for promiscuous */
+ if ((ndev->flags & IFF_PROMISC) ||
+ (uc_count > 15)) { /* @@@TBD resource allocation - 1 */
+ accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC;
+ } else {
+ /* Add MAC filters according to the unicast secondary macs */
+ int i;
+
+ temp = uc_macs;
+ for (i = 0; i < uc_count; i++) {
+ rc = qede_set_ucast_rx_mac(edev,
+ QED_FILTER_XCAST_TYPE_ADD,
+ temp);
+ if (rc)
+ goto out;
+
+ temp += ETH_ALEN;
+ }
+
+ rc = qede_configure_mcast_filtering(ndev, &accept_flags);
+ if (rc)
+ goto out;
+ }
+
+ rx_mode.filter.accept_flags = accept_flags;
+ edev->ops->filter_config(edev->cdev, &rx_mode);
+out:
+ kfree(uc_macs);
+}
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 4847713211ca..b09a6b80d107 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -1736,8 +1736,6 @@ static void ql_get_drvinfo(struct net_device *ndev,
sizeof(drvinfo->version));
strlcpy(drvinfo->bus_info, pci_name(qdev->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
}
static u32 ql_get_msglevel(struct net_device *ndev)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index d6696cfa11d2..46bbea8e023c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1092,7 +1092,7 @@ struct qlcnic_filter_hash {
struct qlcnic_mailbox {
struct workqueue_struct *work_q;
struct qlcnic_adapter *adapter;
- struct qlcnic_mbx_ops *ops;
+ const struct qlcnic_mbx_ops *ops;
struct work_struct work;
struct completion completion;
struct list_head cmd_q;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 9f0bdd993955..37a731be7d39 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -4048,7 +4048,7 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
work);
struct qlcnic_adapter *adapter = mbx->adapter;
- struct qlcnic_mbx_ops *mbx_ops = mbx->ops;
+ const struct qlcnic_mbx_ops *mbx_ops = mbx->ops;
struct device *dev = &adapter->pdev->dev;
atomic_t *rsp_status = &mbx->rsp_status;
struct list_head *head = &mbx->cmd_q;
@@ -4098,7 +4098,7 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
}
}
-static struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = {
+static const struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = {
.enqueue_cmd = qlcnic_83xx_enqueue_mbx_cmd,
.dequeue_cmd = qlcnic_83xx_dequeue_mbx_cmd,
.decode_resp = qlcnic_83xx_decode_mbx_rsp,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index d4481454b5f8..1205f6f9c941 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -353,7 +353,8 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
- if (ether_addr_equal_unaligned(adapter->mac_addr, addr->sa_data))
+ if (ether_addr_equal_unaligned(adapter->mac_addr, addr->sa_data) &&
+ ether_addr_equal_unaligned(netdev->dev_addr, addr->sa_data))
return 0;
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
index c3c514e332b5..5dade1fd08b8 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
@@ -415,13 +415,6 @@ static void ql_get_drvinfo(struct net_device *ndev,
(qdev->fw_rev_id & 0x000000ff));
strlcpy(drvinfo->bus_info, pci_name(qdev->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = 0;
- drvinfo->testinfo_len = 0;
- if (!test_bit(QL_FRC_COREDUMP, &qdev->flags))
- drvinfo->regdump_len = sizeof(struct ql_mpi_coredump);
- else
- drvinfo->regdump_len = sizeof(struct ql_reg_dump);
- drvinfo->eedump_len = 0;
}
static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index 2f87909f5186..ddb2c6c6ec94 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -974,7 +974,6 @@ MODULE_DEVICE_TABLE(spi, qca_spi_id);
static struct spi_driver qca_spi_driver = {
.driver = {
.name = QCASPI_DRV_NAME,
- .owner = THIS_MODULE,
.of_match_table = qca_spi_of_match,
},
.id_table = qca_spi_id,
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 686334f4588d..deae10d7426d 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -175,7 +175,7 @@ enum {
LastFrag = (1 << 28), /* Final segment of a packet */
LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
MSSShift = 16, /* MSS value position */
- MSSMask = 0xfff, /* MSS value: 11 bits */
+ MSSMask = 0x7ff, /* MSS value: 11 bits */
TxError = (1 << 23), /* Tx error summary */
RxError = (1 << 20), /* Rx error summary */
IPCS = (1 << 18), /* Calculate IP checksum */
@@ -754,10 +754,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
mss = skb_shinfo(skb)->gso_size;
+ if (mss > MSSMask) {
+ WARN_ONCE(1, "Net bug: GSO size %d too large for 8139CP\n",
+ mss);
+ goto out_dma_error;
+ }
+
opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
opts1 = DescOwn;
if (mss)
- opts1 |= LargeSend | ((mss & MSSMask) << MSSShift);
+ opts1 |= LargeSend | (mss << MSSShift);
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
const struct iphdr *ip = ip_hdr(skb);
if (ip->protocol == IPPROTO_TCP)
@@ -1852,6 +1858,15 @@ static void cp_set_d3_state (struct cp_private *cp)
pci_set_power_state (cp->pdev, PCI_D3hot);
}
+static netdev_features_t cp_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+{
+ if (skb_shinfo(skb)->gso_size > MSSMask)
+ features &= ~NETIF_F_TSO;
+
+ return vlan_features_check(skb, features);
+}
static const struct net_device_ops cp_netdev_ops = {
.ndo_open = cp_open,
.ndo_stop = cp_close,
@@ -1864,6 +1879,7 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_tx_timeout = cp_tx_timeout,
.ndo_set_features = cp_set_features,
.ndo_change_mtu = cp_change_mtu,
+ .ndo_features_check = cp_features_check,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cp_poll_controller,
@@ -1983,12 +1999,12 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->ethtool_ops = &cp_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
- dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
- /* disabled by default until verified */
dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 78bb4ceb1cdd..ef668d300800 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -2388,7 +2388,6 @@ static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
- info->regdump_len = tp->regs_len;
}
static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index b4f21232019a..79ef799f88ab 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7429,15 +7429,15 @@ process_pkt:
rtl8169_rx_vlan_tag(desc, skb);
+ if (skb->pkt_type == PACKET_MULTICAST)
+ dev->stats.multicast++;
+
napi_gro_receive(&tp->napi, skb);
u64_stats_update_begin(&tp->rx_stats.syncp);
tp->rx_stats.packets++;
tp->rx_stats.bytes += pkt_size;
u64_stats_update_end(&tp->rx_stats.syncp);
-
- if (skb->pkt_type == PACKET_MULTICAST)
- dev->stats.multicast++;
}
release_descriptor:
desc->opts2 = 0;
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index a157aaaaff6a..0623fff932e4 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -766,6 +766,11 @@ struct ravb_ptp {
struct ravb_ptp_perout perout[N_PER_OUT];
};
+enum ravb_chip_id {
+ RCAR_GEN2,
+ RCAR_GEN3,
+};
+
struct ravb_private {
struct net_device *ndev;
struct platform_device *pdev;
@@ -806,6 +811,8 @@ struct ravb_private {
int msg_enable;
int speed;
int duplex;
+ int emac_irq;
+ enum ravb_chip_id chip_id;
unsigned no_avb_link:1;
unsigned avb_link_active_low:1;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 450899e9cea2..ee8d1ec61fab 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -201,7 +201,7 @@ static void ravb_ring_free(struct net_device *ndev, int q)
if (priv->rx_ring[q]) {
ring_size = sizeof(struct ravb_ex_rx_desc) *
(priv->num_rx_ring[q] + 1);
- dma_free_coherent(NULL, ring_size, priv->rx_ring[q],
+ dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
priv->rx_desc_dma[q]);
priv->rx_ring[q] = NULL;
}
@@ -209,7 +209,7 @@ static void ravb_ring_free(struct net_device *ndev, int q)
if (priv->tx_ring[q]) {
ring_size = sizeof(struct ravb_tx_desc) *
(priv->num_tx_ring[q] * NUM_TX_DESC + 1);
- dma_free_coherent(NULL, ring_size, priv->tx_ring[q],
+ dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
priv->tx_desc_dma[q]);
priv->tx_ring[q] = NULL;
}
@@ -240,13 +240,13 @@ static void ravb_ring_format(struct net_device *ndev, int q)
rx_desc = &priv->rx_ring[q][i];
/* The size of the buffer should be on 16-byte boundary. */
rx_desc->ds_cc = cpu_to_le16(ALIGN(PKT_BUF_SZ, 16));
- dma_addr = dma_map_single(&ndev->dev, priv->rx_skb[q][i]->data,
+ dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
ALIGN(PKT_BUF_SZ, 16),
DMA_FROM_DEVICE);
/* We just set the data size to 0 for a failed mapping which
* should prevent DMA from happening...
*/
- if (dma_mapping_error(&ndev->dev, dma_addr))
+ if (dma_mapping_error(ndev->dev.parent, dma_addr))
rx_desc->ds_cc = cpu_to_le16(0);
rx_desc->dptr = cpu_to_le32(dma_addr);
rx_desc->die_dt = DT_FEMPTY;
@@ -309,7 +309,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
/* Allocate all RX descriptors. */
ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1);
- priv->rx_ring[q] = dma_alloc_coherent(NULL, ring_size,
+ priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
&priv->rx_desc_dma[q],
GFP_KERNEL);
if (!priv->rx_ring[q])
@@ -320,7 +320,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
/* Allocate all TX descriptors. */
ring_size = sizeof(struct ravb_tx_desc) *
(priv->num_tx_ring[q] * NUM_TX_DESC + 1);
- priv->tx_ring[q] = dma_alloc_coherent(NULL, ring_size,
+ priv->tx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
&priv->tx_desc_dma[q],
GFP_KERNEL);
if (!priv->tx_ring[q])
@@ -408,8 +408,6 @@ static int ravb_dmac_init(struct net_device *ndev)
/* Interrupt enable: */
/* Frame receive */
ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0);
- /* Receive FIFO full warning */
- ravb_write(ndev, RIC1_RFWE, RIC1);
/* Receive FIFO full error, descriptor empty */
ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2);
/* Frame transmitted, timestamp FIFO updated */
@@ -443,7 +441,7 @@ static int ravb_tx_free(struct net_device *ndev, int q)
size = le16_to_cpu(desc->ds_tagl) & TX_DS;
/* Free the original skb. */
if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
- dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr),
+ dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
size, DMA_TO_DEVICE);
/* Last packet descriptor? */
if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
@@ -546,7 +544,7 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q)
skb = priv->rx_skb[q][entry];
priv->rx_skb[q][entry] = NULL;
- dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr),
+ dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
ALIGN(PKT_BUF_SZ, 16),
DMA_FROM_DEVICE);
get_ts &= (q == RAVB_NC) ?
@@ -586,14 +584,14 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q)
if (!skb)
break; /* Better luck next round. */
ravb_set_buffer_align(skb);
- dma_addr = dma_map_single(&ndev->dev, skb->data,
+ dma_addr = dma_map_single(ndev->dev.parent, skb->data,
le16_to_cpu(desc->ds_cc),
DMA_FROM_DEVICE);
skb_checksum_none_assert(skb);
/* We just set the data size to 0 for a failed mapping
* which should prevent DMA from happening...
*/
- if (dma_mapping_error(&ndev->dev, dma_addr))
+ if (dma_mapping_error(ndev->dev.parent, dma_addr))
desc->ds_cc = cpu_to_le16(0);
desc->dptr = cpu_to_le32(dma_addr);
priv->rx_skb[q][entry] = skb;
@@ -733,8 +731,10 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
((tis & tic) & BIT(q))) {
if (napi_schedule_prep(&priv->napi[q])) {
/* Mask RX and TX interrupts */
- ravb_write(ndev, ric0 & ~BIT(q), RIC0);
- ravb_write(ndev, tic & ~BIT(q), TIC);
+ ric0 &= ~BIT(q);
+ tic &= ~BIT(q);
+ ravb_write(ndev, ric0, RIC0);
+ ravb_write(ndev, tic, TIC);
__napi_schedule(&priv->napi[q]);
} else {
netdev_warn(ndev,
@@ -889,6 +889,22 @@ static int ravb_phy_init(struct net_device *ndev)
return -ENOENT;
}
+ /* This driver only support 10/100Mbit speeds on Gen3
+ * at this time.
+ */
+ if (priv->chip_id == RCAR_GEN3) {
+ int err;
+
+ err = phy_set_max_speed(phydev, SPEED_100);
+ if (err) {
+ netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n");
+ phy_disconnect(phydev);
+ return err;
+ }
+
+ netdev_info(ndev, "limited PHY to 100Mbit/s\n");
+ }
+
netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
phydev->addr, phydev->irq, phydev->drv->name);
@@ -1197,6 +1213,15 @@ static int ravb_open(struct net_device *ndev)
goto out_napi_off;
}
+ if (priv->chip_id == RCAR_GEN3) {
+ error = request_irq(priv->emac_irq, ravb_interrupt,
+ IRQF_SHARED, ndev->name, ndev);
+ if (error) {
+ netdev_err(ndev, "cannot request IRQ\n");
+ goto out_free_irq;
+ }
+ }
+
/* Device init */
error = ravb_dmac_init(ndev);
if (error)
@@ -1220,6 +1245,7 @@ out_ptp_stop:
ravb_ptp_stop(ndev);
out_free_irq:
free_irq(ndev->irq, ndev);
+ free_irq(priv->emac_irq, ndev);
out_napi_off:
napi_disable(&priv->napi[RAVB_NC]);
napi_disable(&priv->napi[RAVB_BE]);
@@ -1300,8 +1326,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
entry / NUM_TX_DESC * DPTR_ALIGN;
len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data;
memcpy(buffer, skb->data, len);
- dma_addr = dma_map_single(&ndev->dev, buffer, len, DMA_TO_DEVICE);
- if (dma_mapping_error(&ndev->dev, dma_addr))
+ dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(ndev->dev.parent, dma_addr))
goto drop;
desc = &priv->tx_ring[q][entry];
@@ -1310,8 +1336,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
buffer = skb->data + len;
len = skb->len - len;
- dma_addr = dma_map_single(&ndev->dev, buffer, len, DMA_TO_DEVICE);
- if (dma_mapping_error(&ndev->dev, dma_addr))
+ dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(ndev->dev.parent, dma_addr))
goto unmap;
desc++;
@@ -1323,7 +1349,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
if (!ts_skb) {
desc--;
- dma_unmap_single(&ndev->dev, dma_addr, len,
+ dma_unmap_single(ndev->dev.parent, dma_addr, len,
DMA_TO_DEVICE);
goto unmap;
}
@@ -1358,7 +1384,7 @@ exit:
return NETDEV_TX_OK;
unmap:
- dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr),
+ dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
le16_to_cpu(desc->ds_tagl), DMA_TO_DEVICE);
drop:
dev_kfree_skb_any(skb);
@@ -1625,10 +1651,20 @@ static int ravb_mdio_release(struct ravb_private *priv)
return 0;
}
+static const struct of_device_id ravb_match_table[] = {
+ { .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 },
+ { .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 },
+ { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ravb_match_table);
+
static int ravb_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
struct ravb_private *priv;
+ enum ravb_chip_id chip_id;
struct net_device *ndev;
int error, irq, q;
struct resource *res;
@@ -1657,7 +1693,14 @@ static int ravb_probe(struct platform_device *pdev)
/* The Ether-specific entries in the device structure. */
ndev->base_addr = res->start;
ndev->dma = -1;
- irq = platform_get_irq(pdev, 0);
+
+ match = of_match_device(of_match_ptr(ravb_match_table), &pdev->dev);
+ chip_id = (enum ravb_chip_id)match->data;
+
+ if (chip_id == RCAR_GEN3)
+ irq = platform_get_irq_byname(pdev, "ch22");
+ else
+ irq = platform_get_irq(pdev, 0);
if (irq < 0) {
error = irq;
goto out_release;
@@ -1688,6 +1731,17 @@ static int ravb_probe(struct platform_device *pdev)
priv->avb_link_active_low =
of_property_read_bool(np, "renesas,ether-link-active-low");
+ if (chip_id == RCAR_GEN3) {
+ irq = platform_get_irq_byname(pdev, "ch24");
+ if (irq < 0) {
+ error = irq;
+ goto out_release;
+ }
+ priv->emac_irq = irq;
+ }
+
+ priv->chip_id = chip_id;
+
/* Set function */
ndev->netdev_ops = &ravb_netdev_ops;
ndev->ethtool_ops = &ravb_ethtool_ops;
@@ -1708,10 +1762,10 @@ static int ravb_probe(struct platform_device *pdev)
/* Allocate descriptor base address table */
priv->desc_bat_size = sizeof(struct ravb_desc) * DBAT_ENTRY_NUM;
- priv->desc_bat = dma_alloc_coherent(NULL, priv->desc_bat_size,
+ priv->desc_bat = dma_alloc_coherent(ndev->dev.parent, priv->desc_bat_size,
&priv->desc_bat_dma, GFP_KERNEL);
if (!priv->desc_bat) {
- dev_err(&ndev->dev,
+ dev_err(&pdev->dev,
"Cannot allocate desc base address table (size %d bytes)\n",
priv->desc_bat_size);
error = -ENOMEM;
@@ -1738,7 +1792,7 @@ static int ravb_probe(struct platform_device *pdev)
/* MDIO bus init */
error = ravb_mdio_init(priv);
if (error) {
- dev_err(&ndev->dev, "failed to initialize MDIO\n");
+ dev_err(&pdev->dev, "failed to initialize MDIO\n");
goto out_dma_free;
}
@@ -1763,7 +1817,7 @@ out_napi_del:
netif_napi_del(&priv->napi[RAVB_BE]);
ravb_mdio_release(priv);
out_dma_free:
- dma_free_coherent(NULL, priv->desc_bat_size, priv->desc_bat,
+ dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
priv->desc_bat_dma);
out_release:
if (ndev)
@@ -1779,7 +1833,7 @@ static int ravb_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct ravb_private *priv = netdev_priv(ndev);
- dma_free_coherent(NULL, priv->desc_bat_size, priv->desc_bat,
+ dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
priv->desc_bat_dma);
/* Set reset mode */
ravb_write(ndev, CCC_OPC_RESET, CCC);
@@ -1818,13 +1872,6 @@ static const struct dev_pm_ops ravb_dev_pm_ops = {
#define RAVB_PM_OPS NULL
#endif
-static const struct of_device_id ravb_match_table[] = {
- { .compatible = "renesas,etheravb-r8a7790" },
- { .compatible = "renesas,etheravb-r8a7794" },
- { }
-};
-MODULE_DEVICE_TABLE(of, ravb_match_table);
-
static struct platform_driver ravb_driver = {
.probe = ravb_probe,
.remove = ravb_remove,
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 257ea713b4c1..e7bab7909ed9 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1098,7 +1098,7 @@ static struct mdiobb_ops bb_ops = {
static void sh_eth_ring_free(struct net_device *ndev)
{
struct sh_eth_private *mdp = netdev_priv(ndev);
- int i;
+ int ringsize, i;
/* Free Rx skb ringbuffer */
if (mdp->rx_skbuff) {
@@ -1115,6 +1115,20 @@ static void sh_eth_ring_free(struct net_device *ndev)
}
kfree(mdp->tx_skbuff);
mdp->tx_skbuff = NULL;
+
+ if (mdp->rx_ring) {
+ ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
+ dma_free_coherent(NULL, ringsize, mdp->rx_ring,
+ mdp->rx_desc_dma);
+ mdp->rx_ring = NULL;
+ }
+
+ if (mdp->tx_ring) {
+ ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
+ dma_free_coherent(NULL, ringsize, mdp->tx_ring,
+ mdp->tx_desc_dma);
+ mdp->tx_ring = NULL;
+ }
}
/* format skb and descriptor buffer */
@@ -1127,7 +1141,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
struct sh_eth_txdesc *txdesc = NULL;
int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
- int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+ int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
dma_addr_t dma_addr;
mdp->cur_rx = 0;
@@ -1148,8 +1162,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
/* RX descriptor */
rxdesc = &mdp->rx_ring[i];
- /* The size of the buffer is a multiple of 16 bytes. */
- rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+ /* The size of the buffer is a multiple of 32 bytes. */
+ rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
dma_addr = dma_map_single(&ndev->dev, skb->data,
rxdesc->buffer_length,
DMA_FROM_DEVICE);
@@ -1173,7 +1187,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
mdp->dirty_rx = (u32) (i - mdp->num_rx_ring);
/* Mark the last entry as wrapping the ring. */
- rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
+ rxdesc->status |= cpu_to_edmac(mdp, RD_RDLE);
memset(mdp->tx_ring, 0, tx_ringsize);
@@ -1199,7 +1213,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
static int sh_eth_ring_init(struct net_device *ndev)
{
struct sh_eth_private *mdp = netdev_priv(ndev);
- int rx_ringsize, tx_ringsize, ret = 0;
+ int rx_ringsize, tx_ringsize;
/* +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
* card needs room to do 8 byte alignment, +2 so we can reserve
@@ -1212,28 +1226,22 @@ static int sh_eth_ring_init(struct net_device *ndev)
mdp->rx_buf_sz += NET_IP_ALIGN;
/* Allocate RX and TX skb rings */
- mdp->rx_skbuff = kmalloc_array(mdp->num_rx_ring,
- sizeof(*mdp->rx_skbuff), GFP_KERNEL);
- if (!mdp->rx_skbuff) {
- ret = -ENOMEM;
- return ret;
- }
+ mdp->rx_skbuff = kcalloc(mdp->num_rx_ring, sizeof(*mdp->rx_skbuff),
+ GFP_KERNEL);
+ if (!mdp->rx_skbuff)
+ return -ENOMEM;
- mdp->tx_skbuff = kmalloc_array(mdp->num_tx_ring,
- sizeof(*mdp->tx_skbuff), GFP_KERNEL);
- if (!mdp->tx_skbuff) {
- ret = -ENOMEM;
- goto skb_ring_free;
- }
+ mdp->tx_skbuff = kcalloc(mdp->num_tx_ring, sizeof(*mdp->tx_skbuff),
+ GFP_KERNEL);
+ if (!mdp->tx_skbuff)
+ goto ring_free;
/* Allocate all Rx descriptors. */
rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
GFP_KERNEL);
- if (!mdp->rx_ring) {
- ret = -ENOMEM;
- goto desc_ring_free;
- }
+ if (!mdp->rx_ring)
+ goto ring_free;
mdp->dirty_rx = 0;
@@ -1241,42 +1249,15 @@ static int sh_eth_ring_init(struct net_device *ndev)
tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
GFP_KERNEL);
- if (!mdp->tx_ring) {
- ret = -ENOMEM;
- goto desc_ring_free;
- }
- return ret;
-
-desc_ring_free:
- /* free DMA buffer */
- dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma);
+ if (!mdp->tx_ring)
+ goto ring_free;
+ return 0;
-skb_ring_free:
- /* Free Rx and Tx skb ring buffer */
+ring_free:
+ /* Free Rx and Tx skb ring buffer and DMA buffer */
sh_eth_ring_free(ndev);
- mdp->tx_ring = NULL;
- mdp->rx_ring = NULL;
-
- return ret;
-}
-
-static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
-{
- int ringsize;
-
- if (mdp->rx_ring) {
- ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
- dma_free_coherent(NULL, ringsize, mdp->rx_ring,
- mdp->rx_desc_dma);
- mdp->rx_ring = NULL;
- }
- if (mdp->tx_ring) {
- ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
- dma_free_coherent(NULL, ringsize, mdp->tx_ring,
- mdp->tx_desc_dma);
- mdp->tx_ring = NULL;
- }
+ return -ENOMEM;
}
static int sh_eth_dev_init(struct net_device *ndev, bool start)
@@ -1416,7 +1397,7 @@ static int sh_eth_txfree(struct net_device *ndev)
if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
break;
/* TACT bit must be checked before all the following reads */
- rmb();
+ dma_rmb();
netif_info(mdp, tx_done, ndev,
"tx entry %d status 0x%08x\n",
entry, edmac_to_cpu(mdp, txdesc->status));
@@ -1450,7 +1431,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
struct sk_buff *skb;
u16 pkt_len = 0;
u32 desc_status;
- int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+ int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
dma_addr_t dma_addr;
boguscnt = min(boguscnt, *quota);
@@ -1458,7 +1439,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
rxdesc = &mdp->rx_ring[entry];
while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
/* RACT bit must be checked before all the following reads */
- rmb();
+ dma_rmb();
desc_status = edmac_to_cpu(mdp, rxdesc->status);
pkt_len = rxdesc->frame_length;
@@ -1506,7 +1487,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
if (mdp->cd->rpadir)
skb_reserve(skb, NET_IP_ALIGN);
dma_unmap_single(&ndev->dev, rxdesc->addr,
- ALIGN(mdp->rx_buf_sz, 16),
+ ALIGN(mdp->rx_buf_sz, 32),
DMA_FROM_DEVICE);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
@@ -1524,8 +1505,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
entry = mdp->dirty_rx % mdp->num_rx_ring;
rxdesc = &mdp->rx_ring[entry];
- /* The size of the buffer is 16 byte boundary. */
- rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+ /* The size of the buffer is 32 byte boundary. */
+ rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
if (mdp->rx_skbuff[entry] == NULL) {
skb = netdev_alloc_skb(ndev, skbuff_size);
@@ -1544,10 +1525,10 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
skb_checksum_none_assert(skb);
rxdesc->addr = dma_addr;
}
- wmb(); /* RACT bit must be set after all the above writes */
+ dma_wmb(); /* RACT bit must be set after all the above writes */
if (entry >= mdp->num_rx_ring - 1)
rxdesc->status |=
- cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
+ cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDLE);
else
rxdesc->status |=
cpu_to_edmac(mdp, RD_RACT | RD_RFP);
@@ -2239,10 +2220,8 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
sh_eth_dev_exit(ndev);
- /* Free all the skbuffs in the Rx queue. */
+ /* Free all the skbuffs in the Rx queue and the DMA buffers. */
sh_eth_ring_free(ndev);
- /* Free DMA buffer */
- sh_eth_free_dma_buffer(mdp);
}
/* Set new parameters */
@@ -2403,7 +2382,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
txdesc->buffer_length = skb->len;
- wmb(); /* TACT bit must be set after all the above writes */
+ dma_wmb(); /* TACT bit must be set after all the above writes */
if (entry >= mdp->num_tx_ring - 1)
txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
else
@@ -2487,12 +2466,9 @@ static int sh_eth_close(struct net_device *ndev)
free_irq(ndev->irq, ndev);
- /* Free all the skbuffs in the Rx queue. */
+ /* Free all the skbuffs in the Rx queue and the DMA buffer. */
sh_eth_ring_free(ndev);
- /* free DMA buffer */
- sh_eth_free_dma_buffer(mdp);
-
pm_runtime_put_sync(&mdp->pdev->dev);
mdp->is_opened = 0;
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 06dbbe5201cb..50382b1c9ddc 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -285,7 +285,7 @@ enum DMAC_IM_BIT {
/* Receive descriptor bit */
enum RD_STS_BIT {
- RD_RACT = 0x80000000, RD_RDEL = 0x40000000,
+ RD_RACT = 0x80000000, RD_RDLE = 0x40000000,
RD_RFP1 = 0x20000000, RD_RFP0 = 0x10000000,
RD_RFE = 0x08000000, RD_RFS10 = 0x00000200,
RD_RFS9 = 0x00000100, RD_RFS8 = 0x00000080,
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 34ac41ac9e61..e9f2349e98bc 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -36,7 +36,7 @@
#include <net/ip_fib.h>
#include <net/netevent.h>
#include <net/arp.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <generated/utsrelease.h>
#include "rocker.h"
@@ -152,8 +152,9 @@ struct rocker_fdb_tbl_entry {
struct hlist_node entry;
u32 key_crc32; /* key */
bool learned;
+ unsigned long touched;
struct rocker_fdb_tbl_key {
- u32 pport;
+ struct rocker_port *rocker_port;
u8 addr[ETH_ALEN];
__be16 vlan_id;
} key;
@@ -220,13 +221,13 @@ struct rocker_port {
__be16 internal_vlan_id;
int stp_state;
u32 brport_flags;
+ unsigned long ageing_time;
bool ctrls[ROCKER_CTRL_MAX];
unsigned long vlan_bitmap[ROCKER_VLAN_BITMAP_LEN];
struct napi_struct napi_tx;
struct napi_struct napi_rx;
struct rocker_dma_ring_info tx_ring;
struct rocker_dma_ring_info rx_ring;
- struct list_head trans_mem;
};
struct rocker {
@@ -246,6 +247,7 @@ struct rocker {
u64 flow_tbl_next_cookie;
DECLARE_HASHTABLE(group_tbl, 16);
spinlock_t group_tbl_lock; /* for group tbl accesses */
+ struct timer_list fdb_cleanup_timer;
DECLARE_HASHTABLE(fdb_tbl, 16);
spinlock_t fdb_tbl_lock; /* for fdb tbl accesses */
unsigned long internal_vlan_bitmap[ROCKER_INTERNAL_VLAN_BITMAP_LEN];
@@ -340,74 +342,63 @@ static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port)
#define ROCKER_OP_FLAG_REFRESH BIT(3)
static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
size_t size)
{
- struct list_head *elem = NULL;
+ struct switchdev_trans_item *elem = NULL;
gfp_t gfp_flags = (flags & ROCKER_OP_FLAG_NOWAIT) ?
GFP_ATOMIC : GFP_KERNEL;
/* If in transaction prepare phase, allocate the memory
- * and enqueue it on a per-port list. If in transaction
- * commit phase, dequeue the memory from the per-port list
+ * and enqueue it on a transaction. If in transaction
+ * commit phase, dequeue the memory from the transaction
* rather than re-allocating the memory. The idea is the
* driver code paths for prepare and commit are identical
* so the memory allocated in the prepare phase is the
* memory used in the commit phase.
*/
- switch (trans) {
- case SWITCHDEV_TRANS_PREPARE:
+ if (!trans) {
+ elem = kzalloc(size + sizeof(*elem), gfp_flags);
+ } else if (switchdev_trans_ph_prepare(trans)) {
elem = kzalloc(size + sizeof(*elem), gfp_flags);
if (!elem)
return NULL;
- list_add_tail(elem, &rocker_port->trans_mem);
- break;
- case SWITCHDEV_TRANS_COMMIT:
- BUG_ON(list_empty(&rocker_port->trans_mem));
- elem = rocker_port->trans_mem.next;
- list_del_init(elem);
- break;
- case SWITCHDEV_TRANS_NONE:
- elem = kzalloc(size + sizeof(*elem), gfp_flags);
- if (elem)
- INIT_LIST_HEAD(elem);
- break;
- default:
- break;
+ switchdev_trans_item_enqueue(trans, elem, kfree, elem);
+ } else {
+ elem = switchdev_trans_item_dequeue(trans);
}
return elem ? elem + 1 : NULL;
}
static void *rocker_port_kzalloc(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
size_t size)
{
return __rocker_port_mem_alloc(rocker_port, trans, flags, size);
}
static void *rocker_port_kcalloc(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
size_t n, size_t size)
{
return __rocker_port_mem_alloc(rocker_port, trans, flags, n * size);
}
-static void rocker_port_kfree(enum switchdev_trans trans, const void *mem)
+static void rocker_port_kfree(struct switchdev_trans *trans, const void *mem)
{
- struct list_head *elem;
+ struct switchdev_trans_item *elem;
/* Frees are ignored if in transaction prepare phase. The
* memory remains on the per-port list until freed in the
* commit phase.
*/
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (switchdev_trans_ph_prepare(trans))
return;
- elem = (struct list_head *)mem - 1;
- BUG_ON(!list_empty(elem));
+ elem = (struct switchdev_trans_item *) mem - 1;
kfree(elem);
}
@@ -430,7 +421,7 @@ static void rocker_wait_init(struct rocker_wait *wait)
}
static struct rocker_wait *rocker_wait_create(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
int flags)
{
struct rocker_wait *wait;
@@ -442,7 +433,7 @@ static struct rocker_wait *rocker_wait_create(struct rocker_port *rocker_port,
return wait;
}
-static void rocker_wait_destroy(enum switchdev_trans trans,
+static void rocker_wait_destroy(struct switchdev_trans *trans,
struct rocker_wait *wait)
{
rocker_port_kfree(trans, wait);
@@ -1408,7 +1399,7 @@ static irqreturn_t rocker_cmd_irq_handler(int irq, void *dev_id)
wait = rocker_desc_cookie_ptr_get(desc_info);
if (wait->nowait) {
rocker_desc_gen_clear(desc_info);
- rocker_wait_destroy(SWITCHDEV_TRANS_NONE, wait);
+ rocker_wait_destroy(NULL, wait);
} else {
rocker_wait_wake_up(wait);
}
@@ -1463,7 +1454,7 @@ static int rocker_event_link_change(const struct rocker *rocker,
}
static int rocker_port_fdb(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
const unsigned char *addr,
__be16 vlan_id, int flags);
@@ -1496,8 +1487,7 @@ static int rocker_event_mac_vlan_seen(const struct rocker *rocker,
rocker_port->stp_state != BR_STATE_FORWARDING)
return 0;
- return rocker_port_fdb(rocker_port, SWITCHDEV_TRANS_NONE,
- addr, vlan_id, flags);
+ return rocker_port_fdb(rocker_port, NULL, addr, vlan_id, flags);
}
static int rocker_event_process(const struct rocker *rocker,
@@ -1582,7 +1572,7 @@ typedef int (*rocker_cmd_proc_cb_t)(const struct rocker_port *rocker_port,
void *priv);
static int rocker_cmd_exec(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
rocker_cmd_prep_cb_t prepare, void *prepare_priv,
rocker_cmd_proc_cb_t process, void *process_priv)
{
@@ -1615,7 +1605,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
rocker_desc_cookie_ptr_set(desc_info, wait);
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info);
spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);
@@ -1623,7 +1613,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
if (nowait)
return 0;
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
if (!rocker_wait_event_timeout(wait, HZ / 10))
return -EIO;
@@ -1875,7 +1865,7 @@ rocker_cmd_set_port_learning_prep(const struct rocker_port *rocker_port,
static int rocker_cmd_get_port_settings_ethtool(struct rocker_port *rocker_port,
struct ethtool_cmd *ecmd)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_get_port_settings_prep, NULL,
rocker_cmd_get_port_settings_ethtool_proc,
ecmd);
@@ -1884,7 +1874,7 @@ static int rocker_cmd_get_port_settings_ethtool(struct rocker_port *rocker_port,
static int rocker_cmd_get_port_settings_macaddr(struct rocker_port *rocker_port,
unsigned char *macaddr)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_get_port_settings_prep, NULL,
rocker_cmd_get_port_settings_macaddr_proc,
macaddr);
@@ -1893,7 +1883,7 @@ static int rocker_cmd_get_port_settings_macaddr(struct rocker_port *rocker_port,
static int rocker_cmd_set_port_settings_ethtool(struct rocker_port *rocker_port,
struct ethtool_cmd *ecmd)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_set_port_settings_ethtool_prep,
ecmd, NULL, NULL);
}
@@ -1901,7 +1891,7 @@ static int rocker_cmd_set_port_settings_ethtool(struct rocker_port *rocker_port,
static int rocker_cmd_set_port_settings_macaddr(struct rocker_port *rocker_port,
unsigned char *macaddr)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_set_port_settings_macaddr_prep,
macaddr, NULL, NULL);
}
@@ -1909,13 +1899,13 @@ static int rocker_cmd_set_port_settings_macaddr(struct rocker_port *rocker_port,
static int rocker_cmd_set_port_settings_mtu(struct rocker_port *rocker_port,
int mtu)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_set_port_settings_mtu_prep,
&mtu, NULL, NULL);
}
static int rocker_port_set_learning(struct rocker_port *rocker_port,
- enum switchdev_trans trans)
+ struct switchdev_trans *trans)
{
return rocker_cmd_exec(rocker_port, trans, 0,
rocker_cmd_set_port_learning_prep,
@@ -2433,7 +2423,7 @@ rocker_flow_tbl_find(const struct rocker *rocker,
}
static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
struct rocker_flow_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2449,7 +2439,7 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
if (found) {
match->cookie = found->cookie;
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_del(&found->entry);
rocker_port_kfree(trans, found);
found = match;
@@ -2460,7 +2450,7 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;
}
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_add(rocker->flow_tbl, &found->entry, found->key_crc32);
spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags);
@@ -2470,7 +2460,7 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
struct rocker_flow_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2486,7 +2476,7 @@ static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
found = rocker_flow_tbl_find(rocker, match);
if (found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_del(&found->entry);
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL;
}
@@ -2506,7 +2496,7 @@ static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_do(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
struct rocker_flow_tbl_entry *entry)
{
if (flags & ROCKER_OP_FLAG_REMOVE)
@@ -2516,7 +2506,7 @@ static int rocker_flow_tbl_do(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
u32 in_pport, u32 in_pport_mask,
enum rocker_of_dpa_table_id goto_tbl)
{
@@ -2536,7 +2526,7 @@ static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
u32 in_pport, __be16 vlan_id,
__be16 vlan_id_mask,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2562,7 +2552,7 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
u32 in_pport, u32 in_pport_mask,
__be16 eth_type, const u8 *eth_dst,
const u8 *eth_dst_mask, __be16 vlan_id,
@@ -2599,7 +2589,7 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
const u8 *eth_dst, const u8 *eth_dst_mask,
__be16 vlan_id, u32 tunnel_id,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2653,7 +2643,7 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
__be16 eth_type, __be32 dst,
__be32 dst_mask, u32 priority,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2679,7 +2669,7 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
}
static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
u32 in_pport, u32 in_pport_mask,
const u8 *eth_src, const u8 *eth_src_mask,
const u8 *eth_dst, const u8 *eth_dst_mask,
@@ -2744,7 +2734,7 @@ rocker_group_tbl_find(const struct rocker *rocker,
return NULL;
}
-static void rocker_group_tbl_entry_free(enum switchdev_trans trans,
+static void rocker_group_tbl_entry_free(struct switchdev_trans *trans,
struct rocker_group_tbl_entry *entry)
{
switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) {
@@ -2759,7 +2749,7 @@ static void rocker_group_tbl_entry_free(enum switchdev_trans trans,
}
static int rocker_group_tbl_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
struct rocker_group_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2771,7 +2761,7 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
found = rocker_group_tbl_find(rocker, match);
if (found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_del(&found->entry);
rocker_group_tbl_entry_free(trans, found);
found = match;
@@ -2781,7 +2771,7 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD;
}
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_add(rocker->group_tbl, &found->entry, found->group_id);
spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags);
@@ -2791,7 +2781,7 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
}
static int rocker_group_tbl_del(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
struct rocker_group_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2804,7 +2794,7 @@ static int rocker_group_tbl_del(struct rocker_port *rocker_port,
found = rocker_group_tbl_find(rocker, match);
if (found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_del(&found->entry);
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL;
}
@@ -2824,7 +2814,7 @@ static int rocker_group_tbl_del(struct rocker_port *rocker_port,
}
static int rocker_group_tbl_do(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
struct rocker_group_tbl_entry *entry)
{
if (flags & ROCKER_OP_FLAG_REMOVE)
@@ -2834,7 +2824,7 @@ static int rocker_group_tbl_do(struct rocker_port *rocker_port,
}
static int rocker_group_l2_interface(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
__be16 vlan_id, u32 out_pport,
int pop_vlan)
{
@@ -2851,7 +2841,7 @@ static int rocker_group_l2_interface(struct rocker_port *rocker_port,
}
static int rocker_group_l2_fan_out(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
int flags, u8 group_count,
const u32 *group_ids, u32 group_id)
{
@@ -2876,7 +2866,7 @@ static int rocker_group_l2_fan_out(struct rocker_port *rocker_port,
}
static int rocker_group_l2_flood(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
__be16 vlan_id, u8 group_count,
const u32 *group_ids, u32 group_id)
{
@@ -2886,7 +2876,7 @@ static int rocker_group_l2_flood(struct rocker_port *rocker_port,
}
static int rocker_group_l3_unicast(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
u32 index, const u8 *src_mac, const u8 *dst_mac,
__be16 vlan_id, bool ttl_check, u32 pport)
{
@@ -2922,22 +2912,22 @@ rocker_neigh_tbl_find(const struct rocker *rocker, __be32 ip_addr)
}
static void _rocker_neigh_add(struct rocker *rocker,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
struct rocker_neigh_tbl_entry *entry)
{
- if (trans != SWITCHDEV_TRANS_COMMIT)
+ if (!switchdev_trans_ph_commit(trans))
entry->index = rocker->neigh_tbl_next_index++;
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (switchdev_trans_ph_prepare(trans))
return;
entry->ref_count++;
hash_add(rocker->neigh_tbl, &entry->entry,
be32_to_cpu(entry->ip_addr));
}
-static void _rocker_neigh_del(enum switchdev_trans trans,
+static void _rocker_neigh_del(struct switchdev_trans *trans,
struct rocker_neigh_tbl_entry *entry)
{
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (switchdev_trans_ph_prepare(trans))
return;
if (--entry->ref_count == 0) {
hash_del(&entry->entry);
@@ -2946,19 +2936,19 @@ static void _rocker_neigh_del(enum switchdev_trans trans,
}
static void _rocker_neigh_update(struct rocker_neigh_tbl_entry *entry,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
const u8 *eth_dst, bool ttl_check)
{
if (eth_dst) {
ether_addr_copy(entry->eth_dst, eth_dst);
entry->ttl_check = ttl_check;
- } else if (trans != SWITCHDEV_TRANS_PREPARE) {
+ } else if (!switchdev_trans_ph_prepare(trans)) {
entry->ref_count++;
}
}
static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
int flags, __be32 ip_addr, const u8 *eth_dst)
{
struct rocker *rocker = rocker_port->rocker;
@@ -3050,7 +3040,8 @@ err_out:
}
static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
- enum switchdev_trans trans, __be32 ip_addr)
+ struct switchdev_trans *trans,
+ __be32 ip_addr)
{
struct net_device *dev = rocker_port->dev;
struct neighbour *n = __ipv4_neigh_lookup(dev, (__force u32)ip_addr);
@@ -3078,7 +3069,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
}
static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
__be32 ip_addr, u32 *index)
{
struct rocker *rocker = rocker_port->rocker;
@@ -3137,7 +3128,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
}
static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
int flags, __be16 vlan_id)
{
struct rocker_port *p;
@@ -3186,7 +3177,7 @@ no_ports_in_vlan:
}
static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
__be16 vlan_id, bool pop_vlan)
{
const struct rocker *rocker = rocker_port->rocker;
@@ -3292,7 +3283,7 @@ static struct rocker_ctrl {
};
static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
u32 in_pport = rocker_port->pport;
@@ -3325,7 +3316,8 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans,
+ int flags,
const struct rocker_ctrl *ctrl,
__be16 vlan_id)
{
@@ -3350,7 +3342,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
u32 in_pport_mask = 0xffffffff;
@@ -3374,7 +3366,7 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
if (ctrl->acl)
@@ -3392,7 +3384,7 @@ static int rocker_port_ctrl_vlan(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
__be16 vlan_id)
{
int err = 0;
@@ -3411,7 +3403,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
const struct rocker_ctrl *ctrl)
{
u16 vid;
@@ -3430,7 +3422,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port,
}
static int rocker_port_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags, u16 vid)
+ struct switchdev_trans *trans, int flags, u16 vid)
{
enum rocker_of_dpa_table_id goto_tbl =
ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC;
@@ -3487,14 +3479,14 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
"Error (%d) port VLAN table\n", err);
err_out:
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (switchdev_trans_ph_prepare(trans))
change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap);
return err;
}
static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ struct switchdev_trans *trans, int flags)
{
enum rocker_of_dpa_table_id goto_tbl;
u32 in_pport;
@@ -3522,7 +3514,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
struct rocker_fdb_learn_work {
struct work_struct work;
struct rocker_port *rocker_port;
- enum switchdev_trans trans;
+ struct switchdev_trans *trans;
int flags;
u8 addr[ETH_ALEN];
u16 vid;
@@ -3550,7 +3542,7 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
}
static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
const u8 *addr, __be16 vlan_id)
{
struct rocker_fdb_learn_work *lw;
@@ -3592,7 +3584,7 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
ether_addr_copy(lw->addr, addr);
lw->vid = rocker_port_vlan_to_vid(rocker_port, vlan_id);
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (switchdev_trans_ph_prepare(trans))
rocker_port_kfree(trans, lw);
else
schedule_work(&lw->work);
@@ -3614,7 +3606,7 @@ rocker_fdb_tbl_find(const struct rocker *rocker,
}
static int rocker_port_fdb(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
const unsigned char *addr,
__be16 vlan_id, int flags)
{
@@ -3629,7 +3621,8 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
return -ENOMEM;
fdb->learned = (flags & ROCKER_OP_FLAG_LEARNED);
- fdb->key.pport = rocker_port->pport;
+ fdb->touched = jiffies;
+ fdb->key.rocker_port = rocker_port;
ether_addr_copy(fdb->key.addr, addr);
fdb->key.vlan_id = vlan_id;
fdb->key_crc32 = crc32(~0, &fdb->key, sizeof(fdb->key));
@@ -3638,13 +3631,17 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
found = rocker_fdb_tbl_find(rocker, fdb);
- if (removing && found) {
- rocker_port_kfree(trans, fdb);
- if (trans != SWITCHDEV_TRANS_PREPARE)
- hash_del(&found->entry);
- } else if (!removing && !found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
- hash_add(rocker->fdb_tbl, &fdb->entry, fdb->key_crc32);
+ if (found) {
+ found->touched = jiffies;
+ if (removing) {
+ rocker_port_kfree(trans, fdb);
+ if (!switchdev_trans_ph_prepare(trans))
+ hash_del(&found->entry);
+ }
+ } else if (!removing) {
+ if (!switchdev_trans_ph_prepare(trans))
+ hash_add(rocker->fdb_tbl, &fdb->entry,
+ fdb->key_crc32);
}
spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags);
@@ -3662,7 +3659,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ struct switchdev_trans *trans, int flags)
{
struct rocker *rocker = rocker_port->rocker;
struct rocker_fdb_tbl_entry *found;
@@ -3675,12 +3672,12 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
rocker_port->stp_state == BR_STATE_FORWARDING)
return 0;
- flags |= ROCKER_OP_FLAG_REMOVE;
+ flags |= ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE;
spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags);
hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) {
- if (found->key.pport != rocker_port->pport)
+ if (found->key.rocker_port != rocker_port)
continue;
if (!found->learned)
continue;
@@ -3689,7 +3686,7 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
found->key.vlan_id);
if (err)
goto err_out;
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (!switchdev_trans_ph_prepare(trans))
hash_del(&found->entry);
}
@@ -3699,8 +3696,43 @@ err_out:
return err;
}
+static void rocker_fdb_cleanup(unsigned long data)
+{
+ struct rocker *rocker = (struct rocker *)data;
+ struct rocker_port *rocker_port;
+ struct rocker_fdb_tbl_entry *entry;
+ struct hlist_node *tmp;
+ unsigned long next_timer = jiffies + BR_MIN_AGEING_TIME;
+ unsigned long expires;
+ unsigned long lock_flags;
+ int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE |
+ ROCKER_OP_FLAG_LEARNED;
+ int bkt;
+
+ spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags);
+
+ hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, entry, entry) {
+ if (!entry->learned)
+ continue;
+ rocker_port = entry->key.rocker_port;
+ expires = entry->touched + rocker_port->ageing_time;
+ if (time_before_eq(expires, jiffies)) {
+ rocker_port_fdb_learn(rocker_port, NULL,
+ flags, entry->key.addr,
+ entry->key.vlan_id);
+ hash_del(&entry->entry);
+ } else if (time_before(expires, next_timer)) {
+ next_timer = expires;
+ }
+ }
+
+ spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags);
+
+ mod_timer(&rocker->fdb_cleanup_timer, round_jiffies_up(next_timer));
+}
+
static int rocker_port_router_mac(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
__be16 vlan_id)
{
u32 in_pport_mask = 0xffffffff;
@@ -3733,7 +3765,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
}
static int rocker_port_fwding(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ struct switchdev_trans *trans, int flags)
{
bool pop_vlan;
u32 out_pport;
@@ -3772,16 +3804,16 @@ static int rocker_port_fwding(struct rocker_port *rocker_port,
}
static int rocker_port_stp_update(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ struct switchdev_trans *trans, int flags,
u8 state)
{
bool want[ROCKER_CTRL_MAX] = { 0, };
bool prev_ctrls[ROCKER_CTRL_MAX];
- u8 prev_state;
+ u8 uninitialized_var(prev_state);
int err;
int i;
- if (trans == SWITCHDEV_TRANS_PREPARE) {
+ if (switchdev_trans_ph_prepare(trans)) {
memcpy(prev_ctrls, rocker_port->ctrls, sizeof(prev_ctrls));
prev_state = rocker_port->stp_state;
}
@@ -3833,7 +3865,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
err = rocker_port_fwding(rocker_port, trans, flags);
err_out:
- if (trans == SWITCHDEV_TRANS_PREPARE) {
+ if (switchdev_trans_ph_prepare(trans)) {
memcpy(rocker_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
rocker_port->stp_state = prev_state;
}
@@ -3842,7 +3874,7 @@ err_out:
}
static int rocker_port_fwd_enable(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ struct switchdev_trans *trans, int flags)
{
if (rocker_port_is_bridged(rocker_port))
/* bridge STP will enable port */
@@ -3854,7 +3886,7 @@ static int rocker_port_fwd_enable(struct rocker_port *rocker_port,
}
static int rocker_port_fwd_disable(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ struct switchdev_trans *trans, int flags)
{
if (rocker_port_is_bridged(rocker_port))
/* bridge STP will disable port */
@@ -3952,7 +3984,7 @@ not_found:
}
static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
- enum switchdev_trans trans, __be32 dst,
+ struct switchdev_trans *trans, __be32 dst,
int dst_len, const struct fib_info *fi,
u32 tb_id, int flags)
{
@@ -4026,7 +4058,7 @@ static int rocker_port_open(struct net_device *dev)
goto err_request_rx_irq;
}
- err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_enable(rocker_port, NULL, 0);
if (err)
goto err_fwd_enable;
@@ -4054,7 +4086,7 @@ static int rocker_port_stop(struct net_device *dev)
rocker_port_set_enable(rocker_port, false);
napi_disable(&rocker_port->napi_rx);
napi_disable(&rocker_port->napi_tx);
- rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE,
+ rocker_port_fwd_disable(rocker_port, NULL,
ROCKER_OP_FLAG_NOWAIT);
free_irq(rocker_msix_rx_vector(rocker_port), rocker_port);
free_irq(rocker_msix_tx_vector(rocker_port), rocker_port);
@@ -4240,7 +4272,7 @@ static int rocker_port_get_phys_port_name(struct net_device *dev,
struct port_name name = { .buf = buf, .len = len };
int err;
- err = rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ err = rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_get_port_settings_prep, NULL,
rocker_cmd_get_port_settings_phys_name_proc,
&name);
@@ -4265,7 +4297,7 @@ static void rocker_port_neigh_destroy(struct neighbour *n)
int flags = ROCKER_OP_FLAG_REMOVE | ROCKER_OP_FLAG_NOWAIT;
__be32 ip_addr = *(__be32 *)n->primary_key;
- rocker_port_ipv4_neigh(rocker_port, SWITCHDEV_TRANS_NONE,
+ rocker_port_ipv4_neigh(rocker_port, NULL,
flags, ip_addr, n->ha);
}
@@ -4297,11 +4329,11 @@ static int rocker_port_attr_get(struct net_device *dev,
const struct rocker *rocker = rocker_port->rocker;
switch (attr->id) {
- case SWITCHDEV_ATTR_PORT_PARENT_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_PORT_BRIDGE_FLAGS:
+ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
attr->u.brport_flags = rocker_port->brport_flags;
break;
default:
@@ -4311,18 +4343,8 @@ static int rocker_port_attr_get(struct net_device *dev,
return 0;
}
-static void rocker_port_trans_abort(const struct rocker_port *rocker_port)
-{
- struct list_head *mem, *tmp;
-
- list_for_each_safe(mem, tmp, &rocker_port->trans_mem) {
- list_del(mem);
- kfree(mem);
- }
-}
-
static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ struct switchdev_trans *trans,
unsigned long brport_flags)
{
unsigned long orig_flags;
@@ -4333,39 +4355,44 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
if ((orig_flags ^ rocker_port->brport_flags) & BR_LEARNING)
err = rocker_port_set_learning(rocker_port, trans);
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (switchdev_trans_ph_prepare(trans))
rocker_port->brport_flags = orig_flags;
return err;
}
+static int rocker_port_bridge_ageing_time(struct rocker_port *rocker_port,
+ struct switchdev_trans *trans,
+ u32 ageing_time)
+{
+ if (!switchdev_trans_ph_prepare(trans)) {
+ rocker_port->ageing_time = clock_t_to_jiffies(ageing_time);
+ mod_timer(&rocker_port->rocker->fdb_cleanup_timer, jiffies);
+ }
+
+ return 0;
+}
+
static int rocker_port_attr_set(struct net_device *dev,
- struct switchdev_attr *attr)
+ const struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
{
struct rocker_port *rocker_port = netdev_priv(dev);
int err = 0;
- switch (attr->trans) {
- case SWITCHDEV_TRANS_PREPARE:
- BUG_ON(!list_empty(&rocker_port->trans_mem));
- break;
- case SWITCHDEV_TRANS_ABORT:
- rocker_port_trans_abort(rocker_port);
- return 0;
- default:
- break;
- }
-
switch (attr->id) {
- case SWITCHDEV_ATTR_PORT_STP_STATE:
- err = rocker_port_stp_update(rocker_port, attr->trans,
- ROCKER_OP_FLAG_NOWAIT,
+ case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
+ err = rocker_port_stp_update(rocker_port, trans, 0,
attr->u.stp_state);
break;
- case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS:
- err = rocker_port_brport_flags_set(rocker_port, attr->trans,
+ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
+ err = rocker_port_brport_flags_set(rocker_port, trans,
attr->u.brport_flags);
break;
+ case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
+ err = rocker_port_bridge_ageing_time(rocker_port, trans,
+ attr->u.ageing_time);
+ break;
default:
err = -EOPNOTSUPP;
break;
@@ -4375,7 +4402,8 @@ static int rocker_port_attr_set(struct net_device *dev,
}
static int rocker_port_vlan_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, u16 vid, u16 flags)
+ struct switchdev_trans *trans,
+ u16 vid, u16 flags)
{
int err;
@@ -4394,8 +4422,8 @@ static int rocker_port_vlan_add(struct rocker_port *rocker_port,
}
static int rocker_port_vlans_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
- const struct switchdev_obj_vlan *vlan)
+ struct switchdev_trans *trans,
+ const struct switchdev_obj_port_vlan *vlan)
{
u16 vid;
int err;
@@ -4411,8 +4439,8 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
- const struct switchdev_obj_fdb *fdb)
+ struct switchdev_trans *trans,
+ const struct switchdev_obj_port_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
int flags = 0;
@@ -4424,36 +4452,27 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port,
}
static int rocker_port_obj_add(struct net_device *dev,
- struct switchdev_obj *obj)
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
{
struct rocker_port *rocker_port = netdev_priv(dev);
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
- switch (obj->trans) {
- case SWITCHDEV_TRANS_PREPARE:
- BUG_ON(!list_empty(&rocker_port->trans_mem));
- break;
- case SWITCHDEV_TRANS_ABORT:
- rocker_port_trans_abort(rocker_port);
- return 0;
- default:
- break;
- }
-
switch (obj->id) {
- case SWITCHDEV_OBJ_PORT_VLAN:
- err = rocker_port_vlans_add(rocker_port, obj->trans,
- &obj->u.vlan);
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = rocker_port_vlans_add(rocker_port, trans,
+ SWITCHDEV_OBJ_PORT_VLAN(obj));
break;
- case SWITCHDEV_OBJ_IPV4_FIB:
- fib4 = &obj->u.ipv4_fib;
- err = rocker_port_fib_ipv4(rocker_port, obj->trans,
+ case SWITCHDEV_OBJ_ID_IPV4_FIB:
+ fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
+ err = rocker_port_fib_ipv4(rocker_port, trans,
htonl(fib4->dst), fib4->dst_len,
- fib4->fi, fib4->tb_id, 0);
+ &fib4->fi, fib4->tb_id, 0);
break;
- case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_add(rocker_port, obj->trans, &obj->u.fdb);
+ case SWITCHDEV_OBJ_ID_PORT_FDB:
+ err = rocker_port_fdb_add(rocker_port, trans,
+ SWITCHDEV_OBJ_PORT_FDB(obj));
break;
default:
err = -EOPNOTSUPP;
@@ -4468,17 +4487,17 @@ static int rocker_port_vlan_del(struct rocker_port *rocker_port,
{
int err;
- err = rocker_port_router_mac(rocker_port, SWITCHDEV_TRANS_NONE,
+ err = rocker_port_router_mac(rocker_port, NULL,
ROCKER_OP_FLAG_REMOVE, htons(vid));
if (err)
return err;
- return rocker_port_vlan(rocker_port, SWITCHDEV_TRANS_NONE,
+ return rocker_port_vlan(rocker_port, NULL,
ROCKER_OP_FLAG_REMOVE, vid);
}
static int rocker_port_vlans_del(struct rocker_port *rocker_port,
- const struct switchdev_obj_vlan *vlan)
+ const struct switchdev_obj_port_vlan *vlan)
{
u16 vid;
int err;
@@ -4493,11 +4512,11 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_del(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
- const struct switchdev_obj_fdb *fdb)
+ struct switchdev_trans *trans,
+ const struct switchdev_obj_port_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
- int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE;
+ int flags = ROCKER_OP_FLAG_REMOVE;
if (!rocker_port_is_bridged(rocker_port))
return -EINVAL;
@@ -4506,25 +4525,27 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port,
}
static int rocker_port_obj_del(struct net_device *dev,
- struct switchdev_obj *obj)
+ const struct switchdev_obj *obj)
{
struct rocker_port *rocker_port = netdev_priv(dev);
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
switch (obj->id) {
- case SWITCHDEV_OBJ_PORT_VLAN:
- err = rocker_port_vlans_del(rocker_port, &obj->u.vlan);
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = rocker_port_vlans_del(rocker_port,
+ SWITCHDEV_OBJ_PORT_VLAN(obj));
break;
- case SWITCHDEV_OBJ_IPV4_FIB:
- fib4 = &obj->u.ipv4_fib;
- err = rocker_port_fib_ipv4(rocker_port, SWITCHDEV_TRANS_NONE,
+ case SWITCHDEV_OBJ_ID_IPV4_FIB:
+ fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
+ err = rocker_port_fib_ipv4(rocker_port, NULL,
htonl(fib4->dst), fib4->dst_len,
- fib4->fi, fib4->tb_id,
+ &fib4->fi, fib4->tb_id,
ROCKER_OP_FLAG_REMOVE);
break;
- case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_del(rocker_port, obj->trans, &obj->u.fdb);
+ case SWITCHDEV_OBJ_ID_PORT_FDB:
+ err = rocker_port_fdb_del(rocker_port, NULL,
+ SWITCHDEV_OBJ_PORT_FDB(obj));
break;
default:
err = -EOPNOTSUPP;
@@ -4535,10 +4556,10 @@ static int rocker_port_obj_del(struct net_device *dev,
}
static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
- struct switchdev_obj *obj)
+ struct switchdev_obj_port_fdb *fdb,
+ switchdev_obj_dump_cb_t *cb)
{
struct rocker *rocker = rocker_port->rocker;
- struct switchdev_obj_fdb *fdb = &obj->u.fdb;
struct rocker_fdb_tbl_entry *found;
struct hlist_node *tmp;
unsigned long lock_flags;
@@ -4547,13 +4568,13 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags);
hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) {
- if (found->key.pport != rocker_port->pport)
+ if (found->key.rocker_port != rocker_port)
continue;
- fdb->addr = found->key.addr;
+ ether_addr_copy(fdb->addr, found->key.addr);
fdb->ndm_state = NUD_REACHABLE;
fdb->vid = rocker_port_vlan_to_vid(rocker_port,
found->key.vlan_id);
- err = obj->cb(rocker_port->dev, obj);
+ err = cb(&fdb->obj);
if (err)
break;
}
@@ -4563,9 +4584,9 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
}
static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
- struct switchdev_obj *obj)
+ struct switchdev_obj_port_vlan *vlan,
+ switchdev_obj_dump_cb_t *cb)
{
- struct switchdev_obj_vlan *vlan = &obj->u.vlan;
u16 vid;
int err = 0;
@@ -4576,7 +4597,7 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
if (rocker_vlan_id_is_internal(htons(vid)))
vlan->flags |= BRIDGE_VLAN_INFO_PVID;
vlan->vid_begin = vlan->vid_end = vid;
- err = obj->cb(rocker_port->dev, obj);
+ err = cb(&vlan->obj);
if (err)
break;
}
@@ -4585,17 +4606,20 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
}
static int rocker_port_obj_dump(struct net_device *dev,
- struct switchdev_obj *obj)
+ struct switchdev_obj *obj,
+ switchdev_obj_dump_cb_t *cb)
{
const struct rocker_port *rocker_port = netdev_priv(dev);
int err = 0;
switch (obj->id) {
- case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_dump(rocker_port, obj);
+ case SWITCHDEV_OBJ_ID_PORT_FDB:
+ err = rocker_port_fdb_dump(rocker_port,
+ SWITCHDEV_OBJ_PORT_FDB(obj), cb);
break;
- case SWITCHDEV_OBJ_PORT_VLAN:
- err = rocker_port_vlan_dump(rocker_port, obj);
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = rocker_port_vlan_dump(rocker_port,
+ SWITCHDEV_OBJ_PORT_VLAN(obj), cb);
break;
default:
err = -EOPNOTSUPP;
@@ -4738,7 +4762,7 @@ rocker_cmd_get_port_stats_ethtool_proc(const struct rocker_port *rocker_port,
static int rocker_cmd_get_port_stats_ethtool(struct rocker_port *rocker_port,
void *priv)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, NULL, 0,
rocker_cmd_get_port_stats_prep, NULL,
rocker_cmd_get_port_stats_ethtool_proc,
priv);
@@ -4930,8 +4954,7 @@ static void rocker_remove_ports(const struct rocker *rocker)
rocker_port = rocker->ports[i];
if (!rocker_port)
continue;
- rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE,
- ROCKER_OP_FLAG_REMOVE);
+ rocker_port_ig_tbl(rocker_port, NULL, ROCKER_OP_FLAG_REMOVE);
unregister_netdev(rocker_port->dev);
free_netdev(rocker_port->dev);
}
@@ -4969,7 +4992,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
rocker_port->port_number = port_number;
rocker_port->pport = port_number + 1;
rocker_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC;
- INIT_LIST_HEAD(&rocker_port->trans_mem);
+ rocker_port->ageing_time = BR_DEFAULT_AGEING_TIME;
rocker_port_dev_addr_init(rocker_port);
dev->netdev_ops = &rocker_port_netdev_ops;
@@ -4992,9 +5015,9 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
switchdev_port_fwd_mark_set(rocker_port->dev, NULL, false);
- rocker_port_set_learning(rocker_port, SWITCHDEV_TRANS_NONE);
+ rocker_port_set_learning(rocker_port, NULL);
- err = rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_ig_tbl(rocker_port, NULL, 0);
if (err) {
netdev_err(rocker_port->dev, "install ig port table failed\n");
goto err_port_ig_tbl;
@@ -5003,8 +5026,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
rocker_port->internal_vlan_id =
rocker_port_internal_vlan_id_get(rocker_port, dev->ifindex);
- err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
- untagged_vid, 0);
+ err = rocker_port_vlan_add(rocker_port, NULL, untagged_vid, 0);
if (err) {
netdev_err(rocker_port->dev, "install untagged VLAN failed\n");
goto err_untagged_vlan;
@@ -5013,8 +5035,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
return 0;
err_untagged_vlan:
- rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE,
- ROCKER_OP_FLAG_REMOVE);
+ rocker_port_ig_tbl(rocker_port, NULL, ROCKER_OP_FLAG_REMOVE);
err_port_ig_tbl:
rocker->ports[port_number] = NULL;
unregister_netdev(dev);
@@ -5183,6 +5204,10 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_init_tbls;
}
+ setup_timer(&rocker->fdb_cleanup_timer, rocker_fdb_cleanup,
+ (unsigned long) rocker);
+ mod_timer(&rocker->fdb_cleanup_timer, jiffies);
+
err = rocker_probe_ports(rocker);
if (err) {
dev_err(&pdev->dev, "failed to probe ports\n");
@@ -5195,6 +5220,7 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_probe_ports:
+ del_timer_sync(&rocker->fdb_cleanup_timer);
rocker_free_tbls(rocker);
err_init_tbls:
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);
@@ -5222,6 +5248,7 @@ static void rocker_remove(struct pci_dev *pdev)
{
struct rocker *rocker = pci_get_drvdata(pdev);
+ del_timer_sync(&rocker->fdb_cleanup_timer);
rocker_free_tbls(rocker);
rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET);
rocker_remove_ports(rocker);
@@ -5275,8 +5302,7 @@ static int rocker_port_bridge_join(struct rocker_port *rocker_port,
rocker_port->bridge_dev = bridge;
switchdev_port_fwd_mark_set(rocker_port->dev, bridge, true);
- return rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
- untagged_vid, 0);
+ return rocker_port_vlan_add(rocker_port, NULL, untagged_vid, 0);
}
static int rocker_port_bridge_leave(struct rocker_port *rocker_port)
@@ -5298,14 +5324,12 @@ static int rocker_port_bridge_leave(struct rocker_port *rocker_port)
false);
rocker_port->bridge_dev = NULL;
- err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
- untagged_vid, 0);
+ err = rocker_port_vlan_add(rocker_port, NULL, untagged_vid, 0);
if (err)
return err;
if (rocker_port->dev->flags & IFF_UP)
- err = rocker_port_fwd_enable(rocker_port,
- SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_enable(rocker_port, NULL, 0);
return err;
}
@@ -5318,10 +5342,10 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port,
rocker_port->bridge_dev = master;
- err = rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_disable(rocker_port, NULL, 0);
if (err)
return err;
- err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_enable(rocker_port, NULL, 0);
return err;
}
@@ -5399,8 +5423,7 @@ static int rocker_neigh_update(struct net_device *dev, struct neighbour *n)
ROCKER_OP_FLAG_NOWAIT;
__be32 ip_addr = *(__be32 *)n->primary_key;
- return rocker_port_ipv4_neigh(rocker_port, SWITCHDEV_TRANS_NONE,
- flags, ip_addr, n->ha);
+ return rocker_port_ipv4_neigh(rocker_port, NULL, flags, ip_addr, n->ha);
}
static int rocker_netevent_event(struct notifier_block *unused,
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index ff649ebef637..bc6d21b471be 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1604,6 +1604,22 @@ efx_ef10_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf,
memcpy(outbuf, pdu + offset, outlen);
}
+static void efx_ef10_mcdi_reboot_detected(struct efx_nic *efx)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+
+ /* All our allocations have been reset */
+ efx_ef10_reset_mc_allocations(efx);
+
+ /* The datapath firmware might have been changed */
+ nic_data->must_check_datapath_caps = true;
+
+ /* MAC statistics have been cleared on the NIC; clear the local
+ * statistic that we update with efx_update_diff_stat().
+ */
+ nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0;
+}
+
static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -1623,17 +1639,7 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
return 0;
nic_data->warm_boot_count = rc;
-
- /* All our allocations have been reset */
- efx_ef10_reset_mc_allocations(efx);
-
- /* The datapath firmware might have been changed */
- nic_data->must_check_datapath_caps = true;
-
- /* MAC statistics have been cleared on the NIC; clear the local
- * statistic that we update with efx_update_diff_stat().
- */
- nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0;
+ efx_ef10_mcdi_reboot_detected(efx);
return -EIO;
}
@@ -1849,7 +1855,9 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
unsigned int write_ptr;
efx_qword_t *txd;
- BUG_ON(tx_queue->write_count == tx_queue->insert_count);
+ tx_queue->xmit_more_available = false;
+ if (unlikely(tx_queue->write_count == tx_queue->insert_count))
+ return;
do {
write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
@@ -4670,6 +4678,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.mcdi_poll_response = efx_ef10_mcdi_poll_response,
.mcdi_read_response = efx_ef10_mcdi_read_response,
.mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot,
+ .mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected,
.irq_enable_master = efx_port_dummy_op_void,
.irq_test_generate = efx_ef10_irq_test_generate,
.irq_disable_non_ev = efx_port_dummy_op_void,
@@ -4774,6 +4783,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.mcdi_poll_response = efx_ef10_mcdi_poll_response,
.mcdi_read_response = efx_ef10_mcdi_read_response,
.mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot,
+ .mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected,
.irq_enable_master = efx_port_dummy_op_void,
.irq_test_generate = efx_ef10_irq_test_generate,
.irq_disable_non_ev = efx_port_dummy_op_void,
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 974637d3ae25..a3c42a376741 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1247,11 +1247,9 @@ static int efx_init_io(struct efx_nic *efx)
* masks event though they reject 46 bit masks.
*/
while (dma_mask > 0x7fffffffUL) {
- if (dma_supported(&pci_dev->dev, dma_mask)) {
- rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
- if (rc == 0)
- break;
- }
+ rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
+ if (rc == 0)
+ break;
dma_mask >>= 1;
}
if (rc) {
@@ -2062,7 +2060,7 @@ static void efx_init_napi_channel(struct efx_channel *channel)
netif_napi_add(channel->napi_dev, &channel->napi_str,
efx_poll, napi_weight);
napi_hash_add(&channel->napi_str);
- efx_channel_init_lock(channel);
+ efx_channel_busy_poll_init(channel);
}
static void efx_init_napi(struct efx_nic *efx)
@@ -2125,7 +2123,7 @@ static int efx_busy_poll(struct napi_struct *napi)
if (!netif_running(efx->net_dev))
return LL_FLUSH_FAILED;
- if (!efx_channel_lock_poll(channel))
+ if (!efx_channel_try_lock_poll(channel))
return LL_FLUSH_BUSY;
old_rx_packets = channel->rx_queue.rx_packets;
@@ -3424,7 +3422,7 @@ out:
* with our request for slot reset the mmio_enabled callback will never be
* called, and the link_reset callback is not used by AER or EEH mechanisms.
*/
-static struct pci_error_handlers efx_err_handlers = {
+static const struct pci_error_handlers efx_err_handlers = {
.error_detected = efx_io_error_detected,
.slot_reset = efx_io_slot_reset,
.resume = efx_io_resume,
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index f08266f0eca2..5a1c5a8f278a 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -321,7 +321,9 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
unsigned write_ptr;
unsigned old_write_count = tx_queue->write_count;
- BUG_ON(tx_queue->write_count == tx_queue->insert_count);
+ tx_queue->xmit_more_available = false;
+ if (unlikely(tx_queue->write_count == tx_queue->insert_count))
+ return;
do {
write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 98d172b04f71..41fb6b60a3f0 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -9,7 +9,7 @@
#include <linux/delay.h>
#include <linux/moduleparam.h>
-#include <asm/cmpxchg.h>
+#include <linux/atomic.h>
#include "net_driver.h"
#include "nic.h"
#include "io.h"
@@ -1028,10 +1028,21 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
/* Consume the status word since efx_mcdi_rpc_finish() won't */
for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
- if (efx_mcdi_poll_reboot(efx))
+ rc = efx_mcdi_poll_reboot(efx);
+ if (rc)
break;
udelay(MCDI_STATUS_DELAY_US);
}
+
+ /* On EF10, a CODE_MC_REBOOT event can be received without the
+ * reboot detection in efx_mcdi_poll_reboot() being triggered.
+ * If zero was returned from the final call to
+ * efx_mcdi_poll_reboot(), the MC reboot wasn't noticed but the
+ * MC has definitely rebooted so prepare for the reset.
+ */
+ if (!rc && efx->type->mcdi_reboot_detected)
+ efx->type->mcdi_reboot_detected(efx);
+
mcdi->new_epoch = true;
/* Nobody was waiting for an MCDI request, so trigger a reset */
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index c530e1c4cb4f..a8ddd122f685 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -219,6 +219,7 @@ struct efx_tx_buffer {
* @tso_packets: Number of packets via the TSO xmit path
* @pushes: Number of times the TX push feature has been used
* @pio_packets: Number of times the TX PIO feature has been used
+ * @xmit_more_available: Are any packets waiting to be pushed to the NIC
* @empty_read_count: If the completion path has seen the queue as empty
* and the transmission path has not yet checked this, the value of
* @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
@@ -253,6 +254,7 @@ struct efx_tx_queue {
unsigned int tso_packets;
unsigned int pushes;
unsigned int pio_packets;
+ bool xmit_more_available;
/* Statistics to supplement MAC stats */
unsigned long tx_packets;
@@ -431,21 +433,8 @@ struct efx_channel {
struct net_device *napi_dev;
struct napi_struct napi_str;
#ifdef CONFIG_NET_RX_BUSY_POLL
- unsigned int state;
- spinlock_t state_lock;
-#define EFX_CHANNEL_STATE_IDLE 0
-#define EFX_CHANNEL_STATE_NAPI (1 << 0) /* NAPI owns this channel */
-#define EFX_CHANNEL_STATE_POLL (1 << 1) /* poll owns this channel */
-#define EFX_CHANNEL_STATE_DISABLED (1 << 2) /* channel is disabled */
-#define EFX_CHANNEL_STATE_NAPI_YIELD (1 << 3) /* NAPI yielded this channel */
-#define EFX_CHANNEL_STATE_POLL_YIELD (1 << 4) /* poll yielded this channel */
-#define EFX_CHANNEL_OWNED \
- (EFX_CHANNEL_STATE_NAPI | EFX_CHANNEL_STATE_POLL)
-#define EFX_CHANNEL_LOCKED \
- (EFX_CHANNEL_OWNED | EFX_CHANNEL_STATE_DISABLED)
-#define EFX_CHANNEL_USER_PEND \
- (EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_POLL_YIELD)
-#endif /* CONFIG_NET_RX_BUSY_POLL */
+ unsigned long busy_poll_state;
+#endif
struct efx_special_buffer eventq;
unsigned int eventq_mask;
unsigned int eventq_read_ptr;
@@ -480,98 +469,94 @@ struct efx_channel {
};
#ifdef CONFIG_NET_RX_BUSY_POLL
-static inline void efx_channel_init_lock(struct efx_channel *channel)
+enum efx_channel_busy_poll_state {
+ EFX_CHANNEL_STATE_IDLE = 0,
+ EFX_CHANNEL_STATE_NAPI = BIT(0),
+ EFX_CHANNEL_STATE_NAPI_REQ_BIT = 1,
+ EFX_CHANNEL_STATE_NAPI_REQ = BIT(1),
+ EFX_CHANNEL_STATE_POLL_BIT = 2,
+ EFX_CHANNEL_STATE_POLL = BIT(2),
+ EFX_CHANNEL_STATE_DISABLE_BIT = 3,
+};
+
+static inline void efx_channel_busy_poll_init(struct efx_channel *channel)
{
- spin_lock_init(&channel->state_lock);
+ WRITE_ONCE(channel->busy_poll_state, EFX_CHANNEL_STATE_IDLE);
}
/* Called from the device poll routine to get ownership of a channel. */
static inline bool efx_channel_lock_napi(struct efx_channel *channel)
{
- bool rc = true;
-
- spin_lock_bh(&channel->state_lock);
- if (channel->state & EFX_CHANNEL_LOCKED) {
- WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI);
- channel->state |= EFX_CHANNEL_STATE_NAPI_YIELD;
- rc = false;
- } else {
- /* we don't care if someone yielded */
- channel->state = EFX_CHANNEL_STATE_NAPI;
+ unsigned long prev, old = READ_ONCE(channel->busy_poll_state);
+
+ while (1) {
+ switch (old) {
+ case EFX_CHANNEL_STATE_POLL:
+ /* Ensure efx_channel_try_lock_poll() wont starve us */
+ set_bit(EFX_CHANNEL_STATE_NAPI_REQ_BIT,
+ &channel->busy_poll_state);
+ /* fallthrough */
+ case EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_NAPI_REQ:
+ return false;
+ default:
+ break;
+ }
+ prev = cmpxchg(&channel->busy_poll_state, old,
+ EFX_CHANNEL_STATE_NAPI);
+ if (unlikely(prev != old)) {
+ /* This is likely to mean we've just entered polling
+ * state. Go back round to set the REQ bit.
+ */
+ old = prev;
+ continue;
+ }
+ return true;
}
- spin_unlock_bh(&channel->state_lock);
- return rc;
}
static inline void efx_channel_unlock_napi(struct efx_channel *channel)
{
- spin_lock_bh(&channel->state_lock);
- WARN_ON(channel->state &
- (EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_NAPI_YIELD));
-
- channel->state &= EFX_CHANNEL_STATE_DISABLED;
- spin_unlock_bh(&channel->state_lock);
+ /* Make sure write has completed from efx_channel_lock_napi() */
+ smp_wmb();
+ WRITE_ONCE(channel->busy_poll_state, EFX_CHANNEL_STATE_IDLE);
}
/* Called from efx_busy_poll(). */
-static inline bool efx_channel_lock_poll(struct efx_channel *channel)
+static inline bool efx_channel_try_lock_poll(struct efx_channel *channel)
{
- bool rc = true;
-
- spin_lock_bh(&channel->state_lock);
- if ((channel->state & EFX_CHANNEL_LOCKED)) {
- channel->state |= EFX_CHANNEL_STATE_POLL_YIELD;
- rc = false;
- } else {
- /* preserve yield marks */
- channel->state |= EFX_CHANNEL_STATE_POLL;
- }
- spin_unlock_bh(&channel->state_lock);
- return rc;
+ return cmpxchg(&channel->busy_poll_state, EFX_CHANNEL_STATE_IDLE,
+ EFX_CHANNEL_STATE_POLL) == EFX_CHANNEL_STATE_IDLE;
}
-/* Returns true if NAPI tried to get the channel while it was locked. */
static inline void efx_channel_unlock_poll(struct efx_channel *channel)
{
- spin_lock_bh(&channel->state_lock);
- WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI);
-
- /* will reset state to idle, unless channel is disabled */
- channel->state &= EFX_CHANNEL_STATE_DISABLED;
- spin_unlock_bh(&channel->state_lock);
+ clear_bit_unlock(EFX_CHANNEL_STATE_POLL_BIT, &channel->busy_poll_state);
}
-/* True if a socket is polling, even if it did not get the lock. */
static inline bool efx_channel_busy_polling(struct efx_channel *channel)
{
- WARN_ON(!(channel->state & EFX_CHANNEL_OWNED));
- return channel->state & EFX_CHANNEL_USER_PEND;
+ return test_bit(EFX_CHANNEL_STATE_POLL_BIT, &channel->busy_poll_state);
}
static inline void efx_channel_enable(struct efx_channel *channel)
{
- spin_lock_bh(&channel->state_lock);
- channel->state = EFX_CHANNEL_STATE_IDLE;
- spin_unlock_bh(&channel->state_lock);
+ clear_bit_unlock(EFX_CHANNEL_STATE_DISABLE_BIT,
+ &channel->busy_poll_state);
}
-/* False if the channel is currently owned. */
+/* Stop further polling or napi access.
+ * Returns false if the channel is currently busy polling.
+ */
static inline bool efx_channel_disable(struct efx_channel *channel)
{
- bool rc = true;
-
- spin_lock_bh(&channel->state_lock);
- if (channel->state & EFX_CHANNEL_OWNED)
- rc = false;
- channel->state |= EFX_CHANNEL_STATE_DISABLED;
- spin_unlock_bh(&channel->state_lock);
-
- return rc;
+ set_bit(EFX_CHANNEL_STATE_DISABLE_BIT, &channel->busy_poll_state);
+ /* Implicit barrier in efx_channel_busy_polling() */
+ return !efx_channel_busy_polling(channel);
}
#else /* CONFIG_NET_RX_BUSY_POLL */
-static inline void efx_channel_init_lock(struct efx_channel *channel)
+static inline void efx_channel_busy_poll_init(struct efx_channel *channel)
{
}
@@ -584,7 +569,7 @@ static inline void efx_channel_unlock_napi(struct efx_channel *channel)
{
}
-static inline bool efx_channel_lock_poll(struct efx_channel *channel)
+static inline bool efx_channel_try_lock_poll(struct efx_channel *channel)
{
return false;
}
@@ -1277,6 +1262,7 @@ struct efx_nic_type {
void (*mcdi_read_response)(struct efx_nic *efx, efx_dword_t *pdu,
size_t pdu_offset, size_t pdu_len);
int (*mcdi_poll_reboot)(struct efx_nic *efx);
+ void (*mcdi_reboot_detected)(struct efx_nic *efx);
void (*irq_enable_master)(struct efx_nic *efx);
void (*irq_test_generate)(struct efx_nic *efx);
void (*irq_disable_non_ev)(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index ad62615a93dc..c771e0af4e06 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -401,8 +401,8 @@ size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats)
/* For Siena platforms NIC time is s and ns */
static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor)
{
- struct timespec ts = ns_to_timespec(ns);
- *nic_major = ts.tv_sec;
+ struct timespec64 ts = ns_to_timespec64(ns);
+ *nic_major = (u32)ts.tv_sec;
*nic_minor = ts.tv_nsec;
}
@@ -431,8 +431,8 @@ static ktime_t efx_ptp_s_ns_to_ktime_correction(u32 nic_major, u32 nic_minor,
*/
static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor)
{
- struct timespec ts = ns_to_timespec(ns);
- u32 maj = ts.tv_sec;
+ struct timespec64 ts = ns_to_timespec64(ns);
+ u32 maj = (u32)ts.tv_sec;
u32 min = (u32)(((u64)ts.tv_nsec * NS_TO_S27_MULT +
(1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT);
@@ -646,28 +646,28 @@ static void efx_ptp_send_times(struct efx_nic *efx,
struct pps_event_time *last_time)
{
struct pps_event_time now;
- struct timespec limit;
+ struct timespec64 limit;
struct efx_ptp_data *ptp = efx->ptp_data;
- struct timespec start;
+ struct timespec64 start;
int *mc_running = ptp->start.addr;
pps_get_ts(&now);
start = now.ts_real;
limit = now.ts_real;
- timespec_add_ns(&limit, SYNCHRONISE_PERIOD_NS);
+ timespec64_add_ns(&limit, SYNCHRONISE_PERIOD_NS);
/* Write host time for specified period or until MC is done */
- while ((timespec_compare(&now.ts_real, &limit) < 0) &&
+ while ((timespec64_compare(&now.ts_real, &limit) < 0) &&
ACCESS_ONCE(*mc_running)) {
- struct timespec update_time;
+ struct timespec64 update_time;
unsigned int host_time;
/* Don't update continuously to avoid saturating the PCIe bus */
update_time = now.ts_real;
- timespec_add_ns(&update_time, SYNCHRONISATION_GRANULARITY_NS);
+ timespec64_add_ns(&update_time, SYNCHRONISATION_GRANULARITY_NS);
do {
pps_get_ts(&now);
- } while ((timespec_compare(&now.ts_real, &update_time) < 0) &&
+ } while ((timespec64_compare(&now.ts_real, &update_time) < 0) &&
ACCESS_ONCE(*mc_running));
/* Synchronise NIC with single word of time only */
@@ -723,7 +723,7 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
struct efx_ptp_data *ptp = efx->ptp_data;
u32 last_sec;
u32 start_sec;
- struct timespec delta;
+ struct timespec64 delta;
ktime_t mc_time;
if (number_readings == 0)
@@ -737,14 +737,14 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
*/
for (i = 0; i < number_readings; i++) {
s32 window, corrected;
- struct timespec wait;
+ struct timespec64 wait;
efx_ptp_read_timeset(
MCDI_ARRAY_STRUCT_PTR(synch_buf,
PTP_OUT_SYNCHRONIZE_TIMESET, i),
&ptp->timeset[i]);
- wait = ktime_to_timespec(
+ wait = ktime_to_timespec64(
ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0));
window = ptp->timeset[i].window;
corrected = window - wait.tv_nsec;
@@ -803,7 +803,7 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
ptp->timeset[last_good].minor, 0);
/* Calculate delay from NIC top of second to last_time */
- delta.tv_nsec += ktime_to_timespec(mc_time).tv_nsec;
+ delta.tv_nsec += ktime_to_timespec64(mc_time).tv_nsec;
/* Set PPS timestamp to match NIC top of second */
ptp->host_time_pps = *last_time;
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 1833a0146571..67f6afaa022f 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -431,8 +431,20 @@ finish_packet:
efx_tx_maybe_stop_queue(tx_queue);
/* Pass off to hardware */
- if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+ struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+ /* There could be packets left on the partner queue if those
+ * SKBs had skb->xmit_more set. If we do not push those they
+ * could be left for a long time and cause a netdev watchdog.
+ */
+ if (txq2->xmit_more_available)
+ efx_nic_push_buffers(txq2);
+
efx_nic_push_buffers(tx_queue);
+ } else {
+ tx_queue->xmit_more_available = skb->xmit_more;
+ }
tx_queue->tx_packets++;
@@ -722,6 +734,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
tx_queue->read_count = 0;
tx_queue->old_read_count = 0;
tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID;
+ tx_queue->xmit_more_available = false;
/* Set up TX descriptor ring */
efx_nic_init_tx(tx_queue);
@@ -747,6 +760,7 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
++tx_queue->read_count;
}
+ tx_queue->xmit_more_available = false;
netdev_tx_reset_queue(tx_queue->core_txq);
}
@@ -1302,8 +1316,20 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
efx_tx_maybe_stop_queue(tx_queue);
/* Pass off to hardware */
- if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+ struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+ /* There could be packets left on the partner queue if those
+ * SKBs had skb->xmit_more set. If we do not push those they
+ * could be left for a long time and cause a netdev watchdog.
+ */
+ if (txq2->xmit_more_available)
+ efx_nic_push_buffers(txq2);
+
efx_nic_push_buffers(tx_queue);
+ } else {
+ tx_queue->xmit_more_available = skb->xmit_more;
+ }
tx_queue->tso_bursts++;
return NETDEV_TX_OK;
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 630f0b7800e4..0e2fc1a844ab 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -2018,10 +2018,18 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
lp->cfg.flags |= SMC91X_USE_DMA;
# endif
if (lp->cfg.flags & SMC91X_USE_DMA) {
- int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
- smc_pxa_dma_irq, NULL);
- if (dma >= 0)
- dev->dma = dma;
+ dma_cap_mask_t mask;
+ struct pxad_param param;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ param.prio = PXAD_PRIO_LOWEST;
+ param.drcmr = -1UL;
+
+ lp->dma_chan =
+ dma_request_slave_channel_compat(mask, pxad_filter_fn,
+ &param, &dev->dev,
+ "data");
}
#endif
@@ -2032,8 +2040,8 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
version_string, revision_register & 0x0f,
lp->base, dev->irq);
- if (dev->dma != (unsigned char)-1)
- pr_cont(" DMA %d", dev->dma);
+ if (lp->dma_chan)
+ pr_cont(" DMA %p", lp->dma_chan);
pr_cont("%s%s\n",
lp->cfg.flags & SMC91X_NOWAIT ? " [nowait]" : "",
@@ -2058,8 +2066,8 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
err_out:
#ifdef CONFIG_ARCH_PXA
- if (retval && dev->dma != (unsigned char)-1)
- pxa_free_dma(dev->dma);
+ if (retval && lp->dma_chan)
+ dma_release_channel(lp->dma_chan);
#endif
return retval;
}
@@ -2370,6 +2378,7 @@ static int smc_drv_probe(struct platform_device *pdev)
struct smc_local *lp = netdev_priv(ndev);
lp->device = &pdev->dev;
lp->physaddr = res->start;
+
}
#endif
@@ -2406,8 +2415,8 @@ static int smc_drv_remove(struct platform_device *pdev)
free_irq(ndev->irq, ndev);
#ifdef CONFIG_ARCH_PXA
- if (ndev->dma != (unsigned char)-1)
- pxa_free_dma(ndev->dma);
+ if (lp->dma_chan)
+ dma_release_channel(lp->dma_chan);
#endif
iounmap(lp->base);
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 3a18501d1068..a3c129e1e40a 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -33,6 +33,7 @@
#ifndef _SMC91X_H_
#define _SMC91X_H_
+#include <linux/dmaengine.h>
#include <linux/smc91x.h>
/*
@@ -244,6 +245,7 @@ struct smc_local {
u_long physaddr;
struct device *device;
#endif
+ struct dma_chan *dma_chan;
void __iomem *base;
void __iomem *datacs;
@@ -265,21 +267,47 @@ struct smc_local {
* as RX which can overrun memory and lose packets.
*/
#include <linux/dma-mapping.h>
-#include <mach/dma.h>
+#include <linux/dma/pxa-dma.h>
#ifdef SMC_insl
#undef SMC_insl
#define SMC_insl(a, r, p, l) \
smc_pxa_dma_insl(a, lp, r, dev->dma, p, l)
static inline void
+smc_pxa_dma_inpump(struct smc_local *lp, u_char *buf, int len)
+{
+ dma_addr_t dmabuf;
+ struct dma_async_tx_descriptor *tx;
+ dma_cookie_t cookie;
+ enum dma_status status;
+ struct dma_tx_state state;
+
+ dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
+ tx = dmaengine_prep_slave_single(lp->dma_chan, dmabuf, len,
+ DMA_DEV_TO_MEM, 0);
+ if (tx) {
+ cookie = dmaengine_submit(tx);
+ dma_async_issue_pending(lp->dma_chan);
+ do {
+ status = dmaengine_tx_status(lp->dma_chan, cookie,
+ &state);
+ cpu_relax();
+ } while (status != DMA_COMPLETE && status != DMA_ERROR &&
+ state.residue);
+ dmaengine_terminate_all(lp->dma_chan);
+ }
+ dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+}
+
+static inline void
smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
u_char *buf, int len)
{
- u_long physaddr = lp->physaddr;
- dma_addr_t dmabuf;
+ struct dma_slave_config config;
+ int ret;
/* fallback if no DMA available */
- if (dma == (unsigned char)-1) {
+ if (!lp->dma_chan) {
readsl(ioaddr + reg, buf, len);
return;
}
@@ -291,18 +319,22 @@ smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
len--;
}
+ memset(&config, 0, sizeof(config));
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ config.src_addr = lp->physaddr + reg;
+ config.dst_addr = lp->physaddr + reg;
+ config.src_maxburst = 32;
+ config.dst_maxburst = 32;
+ ret = dmaengine_slave_config(lp->dma_chan, &config);
+ if (ret) {
+ dev_err(lp->device, "dma channel configuration failed: %d\n",
+ ret);
+ return;
+ }
+
len *= 4;
- dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
- DCSR(dma) = DCSR_NODESC;
- DTADR(dma) = dmabuf;
- DSADR(dma) = physaddr + reg;
- DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
- DCMD_WIDTH4 | (DCMD_LENGTH & len));
- DCSR(dma) = DCSR_NODESC | DCSR_RUN;
- while (!(DCSR(dma) & DCSR_STOPSTATE))
- cpu_relax();
- DCSR(dma) = 0;
- dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+ smc_pxa_dma_inpump(lp, buf, len);
}
#endif
@@ -314,11 +346,11 @@ static inline void
smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
u_char *buf, int len)
{
- u_long physaddr = lp->physaddr;
- dma_addr_t dmabuf;
+ struct dma_slave_config config;
+ int ret;
/* fallback if no DMA available */
- if (dma == (unsigned char)-1) {
+ if (!lp->dma_chan) {
readsw(ioaddr + reg, buf, len);
return;
}
@@ -330,26 +362,25 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
len--;
}
+ memset(&config, 0, sizeof(config));
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ config.src_addr = lp->physaddr + reg;
+ config.dst_addr = lp->physaddr + reg;
+ config.src_maxburst = 32;
+ config.dst_maxburst = 32;
+ ret = dmaengine_slave_config(lp->dma_chan, &config);
+ if (ret) {
+ dev_err(lp->device, "dma channel configuration failed: %d\n",
+ ret);
+ return;
+ }
+
len *= 2;
- dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
- DCSR(dma) = DCSR_NODESC;
- DTADR(dma) = dmabuf;
- DSADR(dma) = physaddr + reg;
- DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
- DCMD_WIDTH2 | (DCMD_LENGTH & len));
- DCSR(dma) = DCSR_NODESC | DCSR_RUN;
- while (!(DCSR(dma) & DCSR_STOPSTATE))
- cpu_relax();
- DCSR(dma) = 0;
- dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+ smc_pxa_dma_inpump(lp, buf, len);
}
#endif
-static void
-smc_pxa_dma_irq(int dma, void *dummy)
-{
- DCSR(dma) = 0;
-}
#endif /* CONFIG_ARCH_PXA */
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 3b4cd8a263de..219a99b7a631 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -809,22 +809,17 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata)
static int smsc911x_phy_reset(struct smsc911x_data *pdata)
{
- struct phy_device *phy_dev = pdata->phy_dev;
unsigned int temp;
unsigned int i = 100000;
- BUG_ON(!phy_dev);
- BUG_ON(!phy_dev->bus);
-
- SMSC_TRACE(pdata, hw, "Performing PHY BCR Reset");
- smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, BMCR_RESET);
+ temp = smsc911x_reg_read(pdata, PMT_CTRL);
+ smsc911x_reg_write(pdata, PMT_CTRL, temp | PMT_CTRL_PHY_RST_);
do {
msleep(1);
- temp = smsc911x_mii_read(phy_dev->bus, phy_dev->addr,
- MII_BMCR);
- } while ((i--) && (temp & BMCR_RESET));
+ temp = smsc911x_reg_read(pdata, PMT_CTRL);
+ } while ((i--) && (temp & PMT_CTRL_PHY_RST_));
- if (temp & BMCR_RESET) {
+ if (unlikely(temp & PMT_CTRL_PHY_RST_)) {
SMSC_WARN(pdata, hw, "PHY reset failed to complete");
return -EIO;
}
@@ -1052,6 +1047,7 @@ static int smsc911x_mii_probe(struct net_device *dev)
#ifdef USE_PHY_WORK_AROUND
if (smsc911x_phy_loopbacktest(dev) < 0) {
SMSC_WARN(pdata, hw, "Failed Loop Back Test");
+ phy_disconnect(phydev);
return -ENODEV;
}
SMSC_TRACE(pdata, hw, "Passed Loop Back Test");
@@ -2295,7 +2291,7 @@ static int smsc911x_init(struct net_device *dev)
}
/* Reset the LAN911x */
- if (smsc911x_soft_reset(pdata))
+ if (smsc911x_phy_reset(pdata) || smsc911x_soft_reset(pdata))
return -ENODEV;
dev->flags |= IFF_MULTICAST;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index 9d89bdbf029f..82de68b1a452 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -337,11 +337,11 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
QSGMII_PHY_RX_SIGNAL_DETECT_EN |
QSGMII_PHY_TX_DRIVER_EN |
QSGMII_PHY_QSGMII_EN |
- 0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
- 0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
- 0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
- 0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
- 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
+ 0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
+ 0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET |
+ 0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
+ 0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
+ 0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
}
plat_dat->has_gmac = true;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 11baa4b19779..0cd3ecff768b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -354,7 +354,7 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv)
static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
{
- int phy_iface = phy_iface = bsp_priv->phy_iface;
+ int phy_iface = bsp_priv->phy_iface;
if (enable) {
if (!bsp_priv->clk_enabled) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 771cda2a48b2..2e51b816a7e8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -721,10 +721,13 @@ static int stmmac_get_ts_info(struct net_device *dev,
{
struct stmmac_priv *priv = netdev_priv(dev);
- if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) {
+ if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) {
- info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
if (priv->ptp_clock)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 925f2f8659b8..64d8aa4e0cad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -424,7 +424,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct hwtstamp_config config;
- struct timespec now;
+ struct timespec64 now;
u64 temp = 0;
u32 ptp_v2 = 0;
u32 tstamp_all = 0;
@@ -621,8 +621,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
priv->default_addend);
/* initialize system time */
- getnstimeofday(&now);
- priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
+ ktime_get_real_ts64(&now);
+
+ /* lower 32 bits of tv_sec are safe until y2106 */
+ priv->hw->ptp->init_systime(priv->ioaddr, (u32)now.tv_sec,
now.tv_nsec);
}
@@ -1945,7 +1947,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
unsigned int txsize = priv->dma_tx_size;
- unsigned int entry;
+ int entry;
int i, csum_insertion = 0, is_jumbo = 0;
int nfrags = skb_shinfo(skb)->nr_frags;
struct dma_desc *desc, *first;
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index 6ce973187225..062bce9acde6 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -4529,9 +4529,6 @@ static void cas_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
strlcpy(info->bus_info, pci_name(cp->pdev), sizeof(info->bus_info));
- info->regdump_len = cp->casreg_len < CAS_MAX_REGS ?
- cp->casreg_len : CAS_MAX_REGS;
- info->n_stats = CAS_NUM_STAT_KEYS;
}
static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
index 85b3326775b8..9066d7a8483c 100644
--- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c
+++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
@@ -2970,8 +2970,7 @@ err_out_unregister_netdev:
err_out_clk_dis_aper:
clk_disable_unprepare(lp->apb_pclk);
err_out_free_netdev:
- if (lp->phy_node)
- of_node_put(lp->phy_node);
+ of_node_put(lp->phy_node);
free_netdev(ndev);
platform_set_drvdata(pdev, NULL);
return ret;
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index a9cac8413e49..14c9d1baa85c 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -2182,11 +2182,6 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(priv->pdev),
sizeof(drvinfo->bus_info));
-
- drvinfo->n_stats = ((priv->stats_flag) ? ARRAY_SIZE(bdx_stat_names) : 0);
- drvinfo->testinfo_len = 0;
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
}
/*
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index cba3d9fcb465..77d26fe286c0 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -899,7 +899,6 @@ static void cpmac_get_drvinfo(struct net_device *dev,
strlcpy(info->driver, "cpmac", sizeof(info->driver));
strlcpy(info->version, CPMAC_VERSION, sizeof(info->version));
snprintf(info->bus_info, sizeof(info->bus_info), "%s", "cpmac");
- info->regdump_len = 0;
}
static const struct ethtool_ops cpmac_ethtool_ops = {
diff --git a/drivers/net/ethernet/ti/cpsw-common.c b/drivers/net/ethernet/ti/cpsw-common.c
index f59509486113..c08be62bceba 100644
--- a/drivers/net/ethernet/ti/cpsw-common.c
+++ b/drivers/net/ethernet/ti/cpsw-common.c
@@ -19,11 +19,38 @@
#include "cpsw.h"
-#define AM33XX_CTRL_MAC_LO_REG(offset, id) ((offset) + 0x8 * (id))
-#define AM33XX_CTRL_MAC_HI_REG(offset, id) ((offset) + 0x8 * (id) + 0x4)
+#define CTRL_MAC_LO_REG(offset, id) ((offset) + 0x8 * (id))
+#define CTRL_MAC_HI_REG(offset, id) ((offset) + 0x8 * (id) + 0x4)
-int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave,
- u8 *mac_addr)
+static int davinci_emac_3517_get_macid(struct device *dev, u16 offset,
+ int slave, u8 *mac_addr)
+{
+ u32 macid_lsb;
+ u32 macid_msb;
+ struct regmap *syscon;
+
+ syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
+ if (IS_ERR(syscon)) {
+ if (PTR_ERR(syscon) == -ENODEV)
+ return 0;
+ return PTR_ERR(syscon);
+ }
+
+ regmap_read(syscon, CTRL_MAC_LO_REG(offset, slave), &macid_lsb);
+ regmap_read(syscon, CTRL_MAC_HI_REG(offset, slave), &macid_msb);
+
+ mac_addr[0] = (macid_msb >> 16) & 0xff;
+ mac_addr[1] = (macid_msb >> 8) & 0xff;
+ mac_addr[2] = macid_msb & 0xff;
+ mac_addr[3] = (macid_lsb >> 16) & 0xff;
+ mac_addr[4] = (macid_lsb >> 8) & 0xff;
+ mac_addr[5] = macid_lsb & 0xff;
+
+ return 0;
+}
+
+static int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave,
+ u8 *mac_addr)
{
u32 macid_lo;
u32 macid_hi;
@@ -36,10 +63,8 @@ int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave,
return PTR_ERR(syscon);
}
- regmap_read(syscon, AM33XX_CTRL_MAC_LO_REG(offset, slave),
- &macid_lo);
- regmap_read(syscon, AM33XX_CTRL_MAC_HI_REG(offset, slave),
- &macid_hi);
+ regmap_read(syscon, CTRL_MAC_LO_REG(offset, slave), &macid_lo);
+ regmap_read(syscon, CTRL_MAC_HI_REG(offset, slave), &macid_hi);
mac_addr[5] = (macid_lo >> 8) & 0xff;
mac_addr[4] = macid_lo & 0xff;
@@ -50,6 +75,27 @@ int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave,
return 0;
}
-EXPORT_SYMBOL_GPL(cpsw_am33xx_cm_get_macid);
+
+int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)
+{
+ if (of_machine_is_compatible("ti,am33xx"))
+ return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
+
+ if (of_device_is_compatible(dev->of_node, "ti,am3517-emac"))
+ return davinci_emac_3517_get_macid(dev, 0x110, slave, mac_addr);
+
+ if (of_device_is_compatible(dev->of_node, "ti,dm816-emac"))
+ return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
+
+ if (of_machine_is_compatible("ti,am4372"))
+ return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
+
+ if (of_machine_is_compatible("ti,dra7"))
+ return davinci_emac_3517_get_macid(dev, 0x514, slave, mac_addr);
+
+ dev_err(dev, "incompatible machine/device type for reading mac address\n");
+ return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(ti_cm_get_macid);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c
index 0ea78326cc21..e9cc61e1ec74 100644
--- a/drivers/net/ethernet/ti/cpsw-phy-sel.c
+++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c
@@ -2,6 +2,8 @@
*
* Copyright (C) 2013 Texas Instruments
*
+ * Module Author: Mugunthan V N <mugunthanvnm@ti.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.
@@ -13,7 +15,7 @@
*/
#include <linux/platform_device.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/of.h>
@@ -173,7 +175,6 @@ static const struct of_device_id cpsw_phy_sel_id_table[] = {
},
{}
};
-MODULE_DEVICE_TABLE(of, cpsw_phy_sel_id_table);
static int cpsw_phy_sel_probe(struct platform_device *pdev)
{
@@ -214,7 +215,4 @@ static struct platform_driver cpsw_phy_sel_driver = {
.of_match_table = cpsw_phy_sel_id_table,
},
};
-
-module_platform_driver(cpsw_phy_sel_driver);
-MODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(cpsw_phy_sel_driver);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8fc90f1c872c..48b92c9de12a 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -29,7 +29,9 @@
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include <linux/gpio.h>
#include <linux/of.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_device.h>
#include <linux/if_vlan.h>
@@ -365,6 +367,7 @@ struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
+ struct device_node *phy_node;
struct napi_struct napi_rx;
struct napi_struct napi_tx;
struct device *dev;
@@ -1145,7 +1148,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
- slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
+ if (priv->phy_node)
+ slave->phy = of_phy_connect(priv->ndev, priv->phy_node,
+ &cpsw_adjust_link, 0, slave->data->phy_if);
+ else
+ slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
&cpsw_adjust_link, slave->data->phy_if);
if (IS_ERR(slave->phy)) {
dev_err(priv->dev, "phy %s not found on slave %d\n",
@@ -1783,7 +1790,6 @@ static void cpsw_get_drvinfo(struct net_device *ndev,
strlcpy(info->driver, "cpsw", sizeof(info->driver));
strlcpy(info->version, "1.0", sizeof(info->version));
strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info));
- info->regdump_len = cpsw_get_regs_len(ndev);
}
static u32 cpsw_get_msglevel(struct net_device *ndev)
@@ -1934,11 +1940,12 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
slave->port_vlan = data->dual_emac_res_vlan;
}
-static int cpsw_probe_dt(struct cpsw_platform_data *data,
+static int cpsw_probe_dt(struct cpsw_priv *priv,
struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device_node *slave_node;
+ struct cpsw_platform_data *data = &priv->data;
int i = 0, ret;
u32 prop;
@@ -2029,6 +2036,20 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (strcmp(slave_node->name, "slave"))
continue;
+ priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
+ if (of_phy_is_fixed_link(slave_node)) {
+ struct phy_device *pd;
+
+ ret = of_phy_register_fixed_link(slave_node);
+ if (ret)
+ return ret;
+ pd = of_phy_find_device(slave_node);
+ if (!pd)
+ return -ENODEV;
+ snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+ PHY_ID_FMT, pd->bus->id, pd->phy_id);
+ goto no_phy_slave;
+ }
parp = of_get_property(slave_node, "phy_id", &lenp);
if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i);
@@ -2044,7 +2065,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
PHY_ID_FMT, mdio->name, phyid);
-
slave_data->phy_if = of_get_phy_mode(slave_node);
if (slave_data->phy_if < 0) {
dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
@@ -2057,13 +2077,10 @@ no_phy_slave:
if (mac_addr) {
memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
} else {
- if (of_machine_is_compatible("ti,am33xx")) {
- ret = cpsw_am33xx_cm_get_macid(&pdev->dev,
- 0x630, i,
- slave_data->mac_addr);
- if (ret)
- return ret;
- }
+ ret = ti_cm_get_macid(&pdev->dev, i,
+ slave_data->mac_addr);
+ if (ret)
+ return ret;
}
if (data->dual_emac) {
if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
@@ -2207,6 +2224,7 @@ static int cpsw_probe(struct platform_device *pdev)
void __iomem *ss_regs;
struct resource *res, *ss_res;
const struct of_device_id *of_id;
+ struct gpio_descs *mode;
u32 slave_offset, sliver_offset, slave_size;
int ret = 0, i;
int irq;
@@ -2232,6 +2250,13 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_ndev_ret;
}
+ mode = devm_gpiod_get_array_optional(&pdev->dev, "mode", GPIOD_OUT_LOW);
+ if (IS_ERR(mode)) {
+ ret = PTR_ERR(mode);
+ dev_err(&pdev->dev, "gpio request failed, ret %d\n", ret);
+ goto clean_ndev_ret;
+ }
+
/*
* This may be required here for child devices.
*/
@@ -2240,7 +2265,7 @@ static int cpsw_probe(struct platform_device *pdev)
/* Select default pin state */
pinctrl_pm_select_default_state(&pdev->dev);
- if (cpsw_probe_dt(&priv->data, pdev)) {
+ if (cpsw_probe_dt(priv, pdev)) {
dev_err(&pdev->dev, "cpsw: platform data missing\n");
ret = -ENODEV;
goto clean_runtime_disable_ret;
@@ -2578,17 +2603,7 @@ static struct platform_driver cpsw_driver = {
.remove = cpsw_remove,
};
-static int __init cpsw_init(void)
-{
- return platform_driver_register(&cpsw_driver);
-}
-late_initcall(cpsw_init);
-
-static void __exit cpsw_exit(void)
-{
- platform_driver_unregister(&cpsw_driver);
-}
-module_exit(cpsw_exit);
+module_platform_driver(cpsw_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cyril Chemparathy <cyril@ti.com>");
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index ca90efafd156..442a7038e660 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -41,7 +41,6 @@ struct cpsw_platform_data {
};
void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave);
-int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave,
- u8 *mac_addr);
+int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr);
#endif /* __CPSW_H__ */
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index a21c77bc1b27..33bd3b902304 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1861,8 +1861,12 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
pdata->no_bd_ram = of_property_read_bool(np, "ti,davinci-no-bd-ram");
priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
- if (!priv->phy_node)
- pdata->phy_id = NULL;
+ if (!priv->phy_node) {
+ if (!of_phy_is_fixed_link(np))
+ pdata->phy_id = NULL;
+ else if (of_phy_register_fixed_link(np) >= 0)
+ priv->phy_node = of_node_get(np);
+ }
auxdata = pdev->dev.platform_data;
if (auxdata) {
@@ -1882,51 +1886,13 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
return pdata;
}
-static int davinci_emac_3517_get_macid(struct device *dev, u16 offset,
- int slave, u8 *mac_addr)
-{
- u32 macid_lsb;
- u32 macid_msb;
- struct regmap *syscon;
-
- syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
- if (IS_ERR(syscon)) {
- if (PTR_ERR(syscon) == -ENODEV)
- return 0;
- return PTR_ERR(syscon);
- }
-
- regmap_read(syscon, offset, &macid_lsb);
- regmap_read(syscon, offset + 4, &macid_msb);
-
- mac_addr[0] = (macid_msb >> 16) & 0xff;
- mac_addr[1] = (macid_msb >> 8) & 0xff;
- mac_addr[2] = macid_msb & 0xff;
- mac_addr[3] = (macid_lsb >> 16) & 0xff;
- mac_addr[4] = (macid_lsb >> 8) & 0xff;
- mac_addr[5] = macid_lsb & 0xff;
-
- return 0;
-}
-
static int davinci_emac_try_get_mac(struct platform_device *pdev,
int instance, u8 *mac_addr)
{
- int error = -EINVAL;
-
if (!pdev->dev.of_node)
- return error;
-
- if (of_device_is_compatible(pdev->dev.of_node, "ti,am3517-emac"))
- error = davinci_emac_3517_get_macid(&pdev->dev, 0x110,
- 0, mac_addr);
- else if (of_device_is_compatible(pdev->dev.of_node,
- "ti,dm816-emac"))
- error = cpsw_am33xx_cm_get_macid(&pdev->dev, 0x30,
- instance,
- mac_addr);
-
- return error;
+ return -EINVAL;
+
+ return ti_cm_get_macid(&pdev->dev, instance, mac_addr);
}
/**
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index 9f9832f0dea9..37b9b39192ec 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -1036,7 +1036,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp)
}
desc = knav_pool_desc_get(netcp->tx_pool);
- if (unlikely(IS_ERR_OR_NULL(desc))) {
+ if (IS_ERR_OR_NULL(desc)) {
dev_err(netcp->ndev_dev, "out of TX desc\n");
dma_unmap_single(dev, dma_addr, pkt_len, DMA_TO_DEVICE);
return NULL;
@@ -1069,7 +1069,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp)
}
ndesc = knav_pool_desc_get(netcp->tx_pool);
- if (unlikely(IS_ERR_OR_NULL(ndesc))) {
+ if (IS_ERR_OR_NULL(ndesc)) {
dev_err(netcp->ndev_dev, "out of TX desc for frags\n");
dma_unmap_page(dev, dma_addr, buf_len, DMA_TO_DEVICE);
goto free_descs;
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index 6bff8d82ceab..4e70e7586a09 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -2637,8 +2637,10 @@ static void init_secondary_ports(struct gbe_priv *gbe_dev,
mac_phy_link = true;
slave->open = true;
- if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+ if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+ of_node_put(port);
break;
+ }
}
/* of_phy_connect() is needed only for MAC-PHY interface */
@@ -3137,8 +3139,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
continue;
}
gbe_dev->num_slaves++;
- if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+ if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+ of_node_put(interface);
break;
+ }
}
of_node_put(interfaces);
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 691ec936e88d..a274cd49afe9 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -791,7 +791,6 @@ static void tlan_get_drvinfo(struct net_device *dev,
sizeof(info->bus_info));
else
strlcpy(info->bus_info, "EISA", sizeof(info->bus_info));
- info->eedump_len = TLAN_EEPROM_SIZE;
}
static int tlan_get_eeprom_len(struct net_device *dev)
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index a83263743665..2b7550c43f78 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -2134,10 +2134,11 @@ static int rhine_rx(struct net_device *dev, int limit)
}
skb_put(skb, pkt_len);
- skb->protocol = eth_type_trans(skb, dev);
rhine_rx_vlan_tag(skb, desc, data_size);
+ skb->protocol = eth_type_trans(skb, dev);
+
netif_receive_skb(skb);
u64_stats_update_begin(&rp->rx_stats.syncp);
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index ae68afd50a15..f38696ceee74 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -345,13 +345,6 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability");
*/
VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
-#define VAL_PKT_LEN_DEF 0
-/* ValPktLen[] is used for setting the checksum offload ability of NIC.
- 0: Receive frame with invalid layer 2 length (Default)
- 1: Drop frame with invalid layer 2 length
-*/
-VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
-
#define WOL_OPT_DEF 0
#define WOL_OPT_MIN 0
#define WOL_OPT_MAX 7
@@ -494,7 +487,6 @@ static void velocity_get_options(struct velocity_opt *opts, int index,
velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname);
velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
- velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
velocity_set_int_opt(&opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
opts->numrx = (opts->numrx & ~3);
@@ -2055,8 +2047,9 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
struct sk_buff *skb;
- if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
- VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name);
+ if (unlikely(rd->rdesc0.RSR & (RSR_STP | RSR_EDP | RSR_RL))) {
+ if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP))
+ VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name);
stats->rx_length_errors++;
return -EINVAL;
}
@@ -2069,17 +2062,6 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma,
vptr->rx.buf_sz, DMA_FROM_DEVICE);
- /*
- * Drop frame not meeting IEEE 802.3
- */
-
- if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) {
- if (rd->rdesc0.RSR & RSR_RL) {
- stats->rx_length_errors++;
- return -EINVAL;
- }
- }
-
velocity_rx_csum(rd, skb);
if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
diff --git a/drivers/net/ethernet/xilinx/ll_temac_mdio.c b/drivers/net/ethernet/xilinx/ll_temac_mdio.c
index 8cf9d4f56bb2..415de1eaf641 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_mdio.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_mdio.c
@@ -59,16 +59,15 @@ static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
{
struct mii_bus *bus;
- const u32 *bus_hz;
+ u32 bus_hz;
int clk_div;
- int rc, size;
+ int rc;
struct resource res;
/* Calculate a reasonable divisor for the clock rate */
clk_div = 0x3f; /* worst-case default setting */
- bus_hz = of_get_property(np, "clock-frequency", &size);
- if (bus_hz && size >= sizeof(*bus_hz)) {
- clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1;
+ if (of_property_read_u32(np, "clock-frequency", &bus_hz) == 0) {
+ clk_div = bus_hz / (2500 * 1000 * 2) - 1;
if (clk_div < 1)
clk_div = 1;
if (clk_div > 0x3f)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index d95f9aae95e7..4684644703cc 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1135,7 +1135,6 @@ static void axienet_ethtools_get_drvinfo(struct net_device *ndev,
{
strlcpy(ed->driver, DRIVER_NAME, sizeof(ed->driver));
strlcpy(ed->version, DRIVER_VERSION, sizeof(ed->version));
- ed->regdump_len = sizeof(u32) * AXIENET_REGS_N;
}
/**
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index 2a5a16834c01..507bbb0355c2 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -129,7 +129,6 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
{
int ret;
u32 clk_div, host_clock;
- u32 *property_p;
struct mii_bus *bus;
struct resource res;
struct device_node *np1;
@@ -168,8 +167,7 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
clk_div = DEFAULT_CLOCK_DIVISOR;
goto issue;
}
- property_p = (u32 *) of_get_property(np1, "clock-frequency", NULL);
- if (!property_p) {
+ if (of_property_read_u32(np1, "clock-frequency", &host_clock)) {
netdev_warn(lp->ndev, "clock-frequency property not found.\n");
netdev_warn(lp->ndev,
"Setting MDIO clock divisor to default %d\n",
@@ -179,7 +177,6 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
goto issue;
}
- host_clock = be32_to_cpup(property_p);
clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
/* If there is any remainder from the division of
* fHOST / (MAX_MDIO_FREQ * 2), then we need to add
diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 0119dd199276..9c218e140c41 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -105,8 +105,6 @@ static void fjes_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version));
snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),
"platform:%s", plat_dev->name);
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
}
static int fjes_get_settings(struct net_device *netdev,
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 2d3848c9dc35..b103adb8d62e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -143,9 +143,7 @@ static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
static void fjes_hw_free_epbuf(struct epbuf_handler *epbh)
{
- if (epbh->buffer)
- vfree(epbh->buffer);
-
+ vfree(epbh->buffer);
epbh->buffer = NULL;
epbh->size = 0;
@@ -601,7 +599,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
FJES_CMD_REQ_RES_CODE_BUSY) &&
(timeout > 0)) {
msleep(200 + hw->my_epid * 20);
- timeout -= (200 + hw->my_epid * 20);
+ timeout -= (200 + hw->my_epid * 20);
res_buf->unshare_buffer.length = 0;
res_buf->unshare_buffer.code = 0;
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 8f5c02eed47d..de5c30c9f059 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -46,16 +46,27 @@ struct geneve_net {
static int geneve_net_id;
+union geneve_addr {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr sa;
+};
+
+static union geneve_addr geneve_remote_unspec = { .sa.sa_family = AF_UNSPEC, };
+
/* Pseudo network device */
struct geneve_dev {
struct hlist_node hlist; /* vni hash table */
struct net *net; /* netns for packet i/o */
struct net_device *dev; /* netdev for geneve tunnel */
- struct geneve_sock *sock; /* socket used for geneve tunnel */
+ struct geneve_sock *sock4; /* IPv4 socket used for geneve tunnel */
+#if IS_ENABLED(CONFIG_IPV6)
+ struct geneve_sock *sock6; /* IPv6 socket used for geneve tunnel */
+#endif
u8 vni[3]; /* virtual network ID for tunnel */
u8 ttl; /* TTL override */
u8 tos; /* TOS override */
- struct sockaddr_in remote; /* IPv4 address for link partner */
+ union geneve_addr remote; /* IP address for link partner */
struct list_head next; /* geneve's per namespace list */
__be16 dst_port;
bool collect_md;
@@ -103,12 +114,32 @@ static struct geneve_dev *geneve_lookup(struct geneve_sock *gs,
vni_list_head = &gs->vni_list[hash];
hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) {
if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) &&
- addr == geneve->remote.sin_addr.s_addr)
+ addr == geneve->remote.sin.sin_addr.s_addr)
return geneve;
}
return NULL;
}
+#if IS_ENABLED(CONFIG_IPV6)
+static struct geneve_dev *geneve6_lookup(struct geneve_sock *gs,
+ struct in6_addr addr6, u8 vni[])
+{
+ struct hlist_head *vni_list_head;
+ struct geneve_dev *geneve;
+ __u32 hash;
+
+ /* Find the device for this VNI */
+ hash = geneve_net_vni_hash(vni);
+ vni_list_head = &gs->vni_list[hash];
+ hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) {
+ if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) &&
+ ipv6_addr_equal(&addr6, &geneve->remote.sin6.sin6_addr))
+ return geneve;
+ }
+ return NULL;
+}
+#endif
+
static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb)
{
return (struct genevehdr *)(udp_hdr(skb) + 1);
@@ -121,24 +152,49 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
struct metadata_dst *tun_dst = NULL;
struct geneve_dev *geneve = NULL;
struct pcpu_sw_netstats *stats;
- struct iphdr *iph;
- u8 *vni;
+ struct iphdr *iph = NULL;
__be32 addr;
- int err;
+ static u8 zero_vni[3];
+ u8 *vni;
+ int err = 0;
+ sa_family_t sa_family;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct ipv6hdr *ip6h = NULL;
+ struct in6_addr addr6;
+ static struct in6_addr zero_addr6;
+#endif
- iph = ip_hdr(skb); /* outer IP header... */
+ sa_family = gs->sock->sk->sk_family;
- if (gs->collect_md) {
- static u8 zero_vni[3];
+ if (sa_family == AF_INET) {
+ iph = ip_hdr(skb); /* outer IP header... */
- vni = zero_vni;
- addr = 0;
- } else {
- vni = gnvh->vni;
- addr = iph->saddr;
- }
+ if (gs->collect_md) {
+ vni = zero_vni;
+ addr = 0;
+ } else {
+ vni = gnvh->vni;
- geneve = geneve_lookup(gs, addr, vni);
+ addr = iph->saddr;
+ }
+
+ geneve = geneve_lookup(gs, addr, vni);
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (sa_family == AF_INET6) {
+ ip6h = ipv6_hdr(skb); /* outer IPv6 header... */
+
+ if (gs->collect_md) {
+ vni = zero_vni;
+ addr6 = zero_addr6;
+ } else {
+ vni = gnvh->vni;
+
+ addr6 = ip6h->saddr;
+ }
+
+ geneve = geneve6_lookup(gs, addr6, vni);
+#endif
+ }
if (!geneve)
goto drop;
@@ -149,7 +205,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
(gnvh->oam ? TUNNEL_OAM : 0) |
(gnvh->critical ? TUNNEL_CRIT_OPT : 0);
- tun_dst = udp_tun_rx_dst(skb, AF_INET, flags,
+ tun_dst = udp_tun_rx_dst(skb, sa_family, flags,
vni_to_tunnel_id(gnvh->vni),
gnvh->opt_len * 4);
if (!tun_dst)
@@ -179,12 +235,25 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
skb_reset_network_header(skb);
- err = IP_ECN_decapsulate(iph, skb);
+ if (iph)
+ err = IP_ECN_decapsulate(iph, skb);
+#if IS_ENABLED(CONFIG_IPV6)
+ if (ip6h)
+ err = IP6_ECN_decapsulate(ip6h, skb);
+#endif
if (unlikely(err)) {
- if (log_ecn_error)
- net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
- &iph->saddr, iph->tos);
+ if (log_ecn_error) {
+ if (iph)
+ net_info_ratelimited("non-ECT from %pI4 "
+ "with TOS=%#x\n",
+ &iph->saddr, iph->tos);
+#if IS_ENABLED(CONFIG_IPV6)
+ if (ip6h)
+ net_info_ratelimited("non-ECT from %pI6\n",
+ &ip6h->saddr);
+#endif
+ }
if (err > 1) {
++geneve->dev->stats.rx_frame_errors;
++geneve->dev->stats.rx_errors;
@@ -284,6 +353,7 @@ static struct socket *geneve_create_sock(struct net *net, bool ipv6,
if (ipv6) {
udp_conf.family = AF_INET6;
+ udp_conf.ipv6_v6only = 1;
} else {
udp_conf.family = AF_INET;
udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
@@ -458,9 +528,9 @@ static void geneve_notify_del_rx_port(struct geneve_sock *gs)
udp_del_offload(&gs->udp_offloads);
}
-static void geneve_sock_release(struct geneve_sock *gs)
+static void __geneve_sock_release(struct geneve_sock *gs)
{
- if (--gs->refcnt)
+ if (!gs || --gs->refcnt)
return;
list_del(&gs->list);
@@ -469,66 +539,117 @@ static void geneve_sock_release(struct geneve_sock *gs)
kfree_rcu(gs, rcu);
}
+static void geneve_sock_release(struct geneve_dev *geneve)
+{
+ __geneve_sock_release(geneve->sock4);
+#if IS_ENABLED(CONFIG_IPV6)
+ __geneve_sock_release(geneve->sock6);
+#endif
+}
+
static struct geneve_sock *geneve_find_sock(struct geneve_net *gn,
+ sa_family_t family,
__be16 dst_port)
{
struct geneve_sock *gs;
list_for_each_entry(gs, &gn->sock_list, list) {
if (inet_sk(gs->sock->sk)->inet_sport == dst_port &&
- inet_sk(gs->sock->sk)->sk.sk_family == AF_INET) {
+ inet_sk(gs->sock->sk)->sk.sk_family == family) {
return gs;
}
}
return NULL;
}
-static int geneve_open(struct net_device *dev)
+static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6)
{
- struct geneve_dev *geneve = netdev_priv(dev);
struct net *net = geneve->net;
struct geneve_net *gn = net_generic(net, geneve_net_id);
struct geneve_sock *gs;
__u32 hash;
- gs = geneve_find_sock(gn, geneve->dst_port);
+ gs = geneve_find_sock(gn, ipv6 ? AF_INET6 : AF_INET, geneve->dst_port);
if (gs) {
gs->refcnt++;
goto out;
}
- gs = geneve_socket_create(net, geneve->dst_port, false);
+ gs = geneve_socket_create(net, geneve->dst_port, ipv6);
if (IS_ERR(gs))
return PTR_ERR(gs);
out:
gs->collect_md = geneve->collect_md;
- geneve->sock = gs;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (ipv6)
+ geneve->sock6 = gs;
+ else
+#endif
+ geneve->sock4 = gs;
hash = geneve_net_vni_hash(geneve->vni);
hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]);
return 0;
}
+static int geneve_open(struct net_device *dev)
+{
+ struct geneve_dev *geneve = netdev_priv(dev);
+ bool ipv6 = geneve->remote.sa.sa_family == AF_INET6;
+ bool metadata = geneve->collect_md;
+ int ret = 0;
+
+ geneve->sock4 = NULL;
+#if IS_ENABLED(CONFIG_IPV6)
+ geneve->sock6 = NULL;
+ if (ipv6 || metadata)
+ ret = geneve_sock_add(geneve, true);
+#endif
+ if (!ret && (!ipv6 || metadata))
+ ret = geneve_sock_add(geneve, false);
+ if (ret < 0)
+ geneve_sock_release(geneve);
+
+ return ret;
+}
+
static int geneve_stop(struct net_device *dev)
{
struct geneve_dev *geneve = netdev_priv(dev);
- struct geneve_sock *gs = geneve->sock;
if (!hlist_unhashed(&geneve->hlist))
hlist_del_rcu(&geneve->hlist);
- geneve_sock_release(gs);
+ geneve_sock_release(geneve);
return 0;
}
+static void geneve_build_header(struct genevehdr *geneveh,
+ __be16 tun_flags, u8 vni[3],
+ u8 options_len, u8 *options)
+{
+ geneveh->ver = GENEVE_VER;
+ geneveh->opt_len = options_len / 4;
+ geneveh->oam = !!(tun_flags & TUNNEL_OAM);
+ geneveh->critical = !!(tun_flags & TUNNEL_CRIT_OPT);
+ geneveh->rsvd1 = 0;
+ memcpy(geneveh->vni, vni, 3);
+ geneveh->proto_type = htons(ETH_P_TEB);
+ geneveh->rsvd2 = 0;
+
+ memcpy(geneveh->options, options, options_len);
+}
+
static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
__be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
- bool csum)
+ bool csum, bool xnet)
{
struct genevehdr *gnvh;
int min_headroom;
int err;
+ skb_scrub_packet(skb, xnet);
+
min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
err = skb_cow_head(skb, min_headroom);
@@ -544,15 +665,7 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
}
gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
- gnvh->ver = GENEVE_VER;
- gnvh->opt_len = opt_len / 4;
- gnvh->oam = !!(tun_flags & TUNNEL_OAM);
- gnvh->critical = !!(tun_flags & TUNNEL_CRIT_OPT);
- gnvh->rsvd1 = 0;
- memcpy(gnvh->vni, vni, 3);
- gnvh->proto_type = htons(ETH_P_TEB);
- gnvh->rsvd2 = 0;
- memcpy(gnvh->options, opt, opt_len);
+ geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);
skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return 0;
@@ -562,10 +675,47 @@ free_rt:
return err;
}
-static struct rtable *geneve_get_rt(struct sk_buff *skb,
- struct net_device *dev,
- struct flowi4 *fl4,
- struct ip_tunnel_info *info)
+#if IS_ENABLED(CONFIG_IPV6)
+static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
+ __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
+ bool csum, bool xnet)
+{
+ struct genevehdr *gnvh;
+ int min_headroom;
+ int err;
+
+ skb_scrub_packet(skb, xnet);
+
+ min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
+ + GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr);
+ err = skb_cow_head(skb, min_headroom);
+ if (unlikely(err)) {
+ kfree_skb(skb);
+ goto free_dst;
+ }
+
+ skb = udp_tunnel_handle_offloads(skb, csum);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ goto free_dst;
+ }
+
+ gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
+ geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);
+
+ skb_set_inner_protocol(skb, htons(ETH_P_TEB));
+ return 0;
+
+free_dst:
+ dst_release(dst);
+ return err;
+}
+#endif
+
+static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi4 *fl4,
+ struct ip_tunnel_info *info)
{
struct geneve_dev *geneve = netdev_priv(dev);
struct rtable *rt = NULL;
@@ -588,24 +738,67 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb,
}
fl4->flowi4_tos = RT_TOS(tos);
- fl4->daddr = geneve->remote.sin_addr.s_addr;
+ fl4->daddr = geneve->remote.sin.sin_addr.s_addr;
}
rt = ip_route_output_key(geneve->net, fl4);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr);
- dev->stats.tx_carrier_errors++;
- return rt;
+ return ERR_PTR(-ENETUNREACH);
}
if (rt->dst.dev == dev) { /* is this necessary? */
netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr);
- dev->stats.collisions++;
ip_rt_put(rt);
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ELOOP);
}
return rt;
}
+#if IS_ENABLED(CONFIG_IPV6)
+static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi6 *fl6,
+ struct ip_tunnel_info *info)
+{
+ struct geneve_dev *geneve = netdev_priv(dev);
+ struct geneve_sock *gs6 = geneve->sock6;
+ struct dst_entry *dst = NULL;
+ __u8 prio;
+
+ memset(fl6, 0, sizeof(*fl6));
+ fl6->flowi6_mark = skb->mark;
+ fl6->flowi6_proto = IPPROTO_UDP;
+
+ if (info) {
+ fl6->daddr = info->key.u.ipv6.dst;
+ fl6->saddr = info->key.u.ipv6.src;
+ fl6->flowi6_tos = RT_TOS(info->key.tos);
+ } else {
+ prio = geneve->tos;
+ if (prio == 1) {
+ const struct iphdr *iip = ip_hdr(skb);
+
+ prio = ip_tunnel_get_dsfield(iip, skb);
+ }
+
+ fl6->flowi6_tos = RT_TOS(prio);
+ fl6->daddr = geneve->remote.sin6.sin6_addr;
+ }
+
+ if (ipv6_stub->ipv6_dst_lookup(geneve->net, gs6->sock->sk, &dst, fl6)) {
+ netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr);
+ return ERR_PTR(-ENETUNREACH);
+ }
+ if (dst->dev == dev) { /* is this necessary? */
+ netdev_dbg(dev, "circular route to %pI6\n", &fl6->daddr);
+ dst_release(dst);
+ return ERR_PTR(-ELOOP);
+ }
+
+ return dst;
+}
+#endif
+
/* Convert 64 bit tunnel ID to 24 bit VNI. */
static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni)
{
@@ -620,23 +813,23 @@ static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni)
#endif
}
-static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ struct ip_tunnel_info *info)
{
struct geneve_dev *geneve = netdev_priv(dev);
- struct geneve_sock *gs = geneve->sock;
- struct ip_tunnel_info *info = NULL;
+ struct geneve_sock *gs4 = geneve->sock4;
struct rtable *rt = NULL;
const struct iphdr *iip; /* interior IP header */
+ int err = -EINVAL;
struct flowi4 fl4;
__u8 tos, ttl;
__be16 sport;
bool udp_csum;
__be16 df;
- int err;
+ bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
if (geneve->collect_md) {
- info = skb_tunnel_info(skb);
- if (unlikely(info && !(info->mode & IP_TUNNEL_INFO_TX))) {
+ if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
netdev_dbg(dev, "no tunnel metadata\n");
goto tx_error;
}
@@ -644,10 +837,9 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_error;
}
- rt = geneve_get_rt(skb, dev, &fl4, info);
+ rt = geneve_get_v4_rt(skb, dev, &fl4, info);
if (IS_ERR(rt)) {
- netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr);
- dev->stats.tx_carrier_errors++;
+ err = PTR_ERR(rt);
goto tx_error;
}
@@ -667,7 +859,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
udp_csum = !!(key->tun_flags & TUNNEL_CSUM);
err = geneve_build_skb(rt, skb, key->tun_flags, vni,
- info->options_len, opts, udp_csum);
+ info->options_len, opts, udp_csum, xnet);
if (unlikely(err))
goto err;
@@ -677,7 +869,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
} else {
udp_csum = false;
err = geneve_build_skb(rt, skb, 0, geneve->vni,
- 0, NULL, udp_csum);
+ 0, NULL, udp_csum, xnet);
if (unlikely(err))
goto err;
@@ -688,7 +880,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
df = 0;
}
- err = udp_tunnel_xmit_skb(rt, gs->sock->sk, skb, fl4.saddr, fl4.daddr,
+ err = udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr,
tos, ttl, df, sport, geneve->dst_port,
!net_eq(geneve->net, dev_net(geneve->dev)),
!udp_csum);
@@ -699,10 +891,152 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
tx_error:
dev_kfree_skb(skb);
err:
- dev->stats.tx_errors++;
+ if (err == -ELOOP)
+ dev->stats.collisions++;
+ else if (err == -ENETUNREACH)
+ dev->stats.tx_carrier_errors++;
+ else
+ dev->stats.tx_errors++;
return NETDEV_TX_OK;
}
+#if IS_ENABLED(CONFIG_IPV6)
+static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ struct ip_tunnel_info *info)
+{
+ struct geneve_dev *geneve = netdev_priv(dev);
+ struct geneve_sock *gs6 = geneve->sock6;
+ struct dst_entry *dst = NULL;
+ const struct iphdr *iip; /* interior IP header */
+ int err = -EINVAL;
+ struct flowi6 fl6;
+ __u8 prio, ttl;
+ __be16 sport;
+ bool udp_csum;
+ bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
+
+ if (geneve->collect_md) {
+ if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
+ netdev_dbg(dev, "no tunnel metadata\n");
+ goto tx_error;
+ }
+ }
+
+ dst = geneve_get_v6_dst(skb, dev, &fl6, info);
+ if (IS_ERR(dst)) {
+ err = PTR_ERR(dst);
+ goto tx_error;
+ }
+
+ sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+ skb_reset_mac_header(skb);
+
+ iip = ip_hdr(skb);
+
+ if (info) {
+ const struct ip_tunnel_key *key = &info->key;
+ u8 *opts = NULL;
+ u8 vni[3];
+
+ tunnel_id_to_vni(key->tun_id, vni);
+ if (key->tun_flags & TUNNEL_GENEVE_OPT)
+ opts = ip_tunnel_info_opts(info);
+
+ udp_csum = !!(key->tun_flags & TUNNEL_CSUM);
+ err = geneve6_build_skb(dst, skb, key->tun_flags, vni,
+ info->options_len, opts,
+ udp_csum, xnet);
+ if (unlikely(err))
+ goto err;
+
+ prio = ip_tunnel_ecn_encap(key->tos, iip, skb);
+ ttl = key->ttl;
+ } else {
+ udp_csum = false;
+ err = geneve6_build_skb(dst, skb, 0, geneve->vni,
+ 0, NULL, udp_csum, xnet);
+ if (unlikely(err))
+ goto err;
+
+ prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb);
+ ttl = geneve->ttl;
+ if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
+ ttl = 1;
+ ttl = ttl ? : ip6_dst_hoplimit(dst);
+ }
+ err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
+ &fl6.saddr, &fl6.daddr, prio, ttl,
+ sport, geneve->dst_port, !udp_csum);
+
+ iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
+ return NETDEV_TX_OK;
+
+tx_error:
+ dev_kfree_skb(skb);
+err:
+ if (err == -ELOOP)
+ dev->stats.collisions++;
+ else if (err == -ENETUNREACH)
+ dev->stats.tx_carrier_errors++;
+ else
+ dev->stats.tx_errors++;
+ return NETDEV_TX_OK;
+}
+#endif
+
+static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct geneve_dev *geneve = netdev_priv(dev);
+ struct ip_tunnel_info *info = NULL;
+
+ if (geneve->collect_md)
+ info = skb_tunnel_info(skb);
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if ((info && ip_tunnel_info_af(info) == AF_INET6) ||
+ (!info && geneve->remote.sa.sa_family == AF_INET6))
+ return geneve6_xmit_skb(skb, dev, info);
+#endif
+ return geneve_xmit_skb(skb, dev, info);
+}
+
+static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+ struct geneve_dev *geneve = netdev_priv(dev);
+ struct rtable *rt;
+ struct flowi4 fl4;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct dst_entry *dst;
+ struct flowi6 fl6;
+#endif
+
+ if (ip_tunnel_info_af(info) == AF_INET) {
+ rt = geneve_get_v4_rt(skb, dev, &fl4, info);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+
+ ip_rt_put(rt);
+ info->key.u.ipv4.src = fl4.saddr;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (ip_tunnel_info_af(info) == AF_INET6) {
+ dst = geneve_get_v6_dst(skb, dev, &fl6, info);
+ if (IS_ERR(dst))
+ return PTR_ERR(dst);
+
+ dst_release(dst);
+ info->key.u.ipv6.src = fl6.saddr;
+#endif
+ } else {
+ return -EINVAL;
+ }
+
+ info->key.tp_src = udp_flow_src_port(geneve->net, skb,
+ 1, USHRT_MAX, true);
+ info->key.tp_dst = geneve->dst_port;
+ return 0;
+}
+
static const struct net_device_ops geneve_netdev_ops = {
.ndo_init = geneve_init,
.ndo_uninit = geneve_uninit,
@@ -713,6 +1047,7 @@ static const struct net_device_ops geneve_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_fill_metadata_dst = geneve_fill_metadata_dst,
};
static void geneve_get_drvinfo(struct net_device *dev,
@@ -759,6 +1094,7 @@ static void geneve_setup(struct net_device *dev)
static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
[IFLA_GENEVE_ID] = { .type = NLA_U32 },
[IFLA_GENEVE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+ [IFLA_GENEVE_REMOTE6] = { .len = sizeof(struct in6_addr) },
[IFLA_GENEVE_TTL] = { .type = NLA_U8 },
[IFLA_GENEVE_TOS] = { .type = NLA_U8 },
[IFLA_GENEVE_PORT] = { .type = NLA_U16 },
@@ -790,7 +1126,7 @@ static int geneve_validate(struct nlattr *tb[], struct nlattr *data[])
static struct geneve_dev *geneve_find_dev(struct geneve_net *gn,
__be16 dst_port,
- __be32 rem_addr,
+ union geneve_addr *remote,
u8 vni[],
bool *tun_on_same_port,
bool *tun_collect_md)
@@ -806,7 +1142,7 @@ static struct geneve_dev *geneve_find_dev(struct geneve_net *gn,
*tun_on_same_port = true;
}
if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) &&
- rem_addr == geneve->remote.sin_addr.s_addr &&
+ !memcmp(remote, &geneve->remote, sizeof(geneve->remote)) &&
dst_port == geneve->dst_port)
t = geneve;
}
@@ -814,18 +1150,20 @@ static struct geneve_dev *geneve_find_dev(struct geneve_net *gn,
}
static int geneve_configure(struct net *net, struct net_device *dev,
- __be32 rem_addr, __u32 vni, __u8 ttl, __u8 tos,
- __be16 dst_port, bool metadata)
+ union geneve_addr *remote,
+ __u32 vni, __u8 ttl, __u8 tos, __be16 dst_port,
+ bool metadata)
{
struct geneve_net *gn = net_generic(net, geneve_net_id);
struct geneve_dev *t, *geneve = netdev_priv(dev);
bool tun_collect_md, tun_on_same_port;
int err;
- if (metadata) {
- if (rem_addr || vni || tos || ttl)
- return -EINVAL;
- }
+ if (!remote)
+ return -EINVAL;
+ if (metadata &&
+ (remote->sa.sa_family != AF_UNSPEC || vni || tos || ttl))
+ return -EINVAL;
geneve->net = net;
geneve->dev = dev;
@@ -834,16 +1172,19 @@ static int geneve_configure(struct net *net, struct net_device *dev,
geneve->vni[1] = (vni & 0x0000ff00) >> 8;
geneve->vni[2] = vni & 0x000000ff;
- geneve->remote.sin_addr.s_addr = rem_addr;
- if (IN_MULTICAST(ntohl(geneve->remote.sin_addr.s_addr)))
+ if ((remote->sa.sa_family == AF_INET &&
+ IN_MULTICAST(ntohl(remote->sin.sin_addr.s_addr))) ||
+ (remote->sa.sa_family == AF_INET6 &&
+ ipv6_addr_is_multicast(&remote->sin6.sin6_addr)))
return -EINVAL;
+ geneve->remote = *remote;
geneve->ttl = ttl;
geneve->tos = tos;
geneve->dst_port = dst_port;
geneve->collect_md = metadata;
- t = geneve_find_dev(gn, dst_port, rem_addr, geneve->vni,
+ t = geneve_find_dev(gn, dst_port, remote, geneve->vni,
&tun_on_same_port, &tun_collect_md);
if (t)
return -EBUSY;
@@ -870,14 +1211,35 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
__be16 dst_port = htons(GENEVE_UDP_PORT);
__u8 ttl = 0, tos = 0;
bool metadata = false;
- __be32 rem_addr;
- __u32 vni;
+ union geneve_addr remote = geneve_remote_unspec;
+ __u32 vni = 0;
- if (!data[IFLA_GENEVE_ID] || !data[IFLA_GENEVE_REMOTE])
+ if (data[IFLA_GENEVE_REMOTE] && data[IFLA_GENEVE_REMOTE6])
return -EINVAL;
- vni = nla_get_u32(data[IFLA_GENEVE_ID]);
- rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
+ if (data[IFLA_GENEVE_REMOTE]) {
+ remote.sa.sa_family = AF_INET;
+ remote.sin.sin_addr.s_addr =
+ nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
+ }
+
+ if (data[IFLA_GENEVE_REMOTE6]) {
+ if (!IS_ENABLED(CONFIG_IPV6))
+ return -EPFNOSUPPORT;
+
+ remote.sa.sa_family = AF_INET6;
+ remote.sin6.sin6_addr =
+ nla_get_in6_addr(data[IFLA_GENEVE_REMOTE6]);
+
+ if (ipv6_addr_type(&remote.sin6.sin6_addr) &
+ IPV6_ADDR_LINKLOCAL) {
+ netdev_dbg(dev, "link-local remote is unsupported\n");
+ return -EINVAL;
+ }
+ }
+
+ if (data[IFLA_GENEVE_ID])
+ vni = nla_get_u32(data[IFLA_GENEVE_ID]);
if (data[IFLA_GENEVE_TTL])
ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
@@ -891,8 +1253,8 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
if (data[IFLA_GENEVE_COLLECT_METADATA])
metadata = true;
- return geneve_configure(net, dev, rem_addr, vni,
- ttl, tos, dst_port, metadata);
+ return geneve_configure(net, dev, &remote, vni, ttl, tos, dst_port,
+ metadata);
}
static void geneve_dellink(struct net_device *dev, struct list_head *head)
@@ -906,7 +1268,7 @@ static void geneve_dellink(struct net_device *dev, struct list_head *head)
static size_t geneve_get_size(const struct net_device *dev)
{
return nla_total_size(sizeof(__u32)) + /* IFLA_GENEVE_ID */
- nla_total_size(sizeof(struct in_addr)) + /* IFLA_GENEVE_REMOTE */
+ nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */
nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */
@@ -923,9 +1285,17 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u32(skb, IFLA_GENEVE_ID, vni))
goto nla_put_failure;
- if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE,
- geneve->remote.sin_addr.s_addr))
- goto nla_put_failure;
+ if (geneve->remote.sa.sa_family == AF_INET) {
+ if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE,
+ geneve->remote.sin.sin_addr.s_addr))
+ goto nla_put_failure;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else {
+ if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6,
+ &geneve->remote.sin6.sin6_addr))
+ goto nla_put_failure;
+#endif
+ }
if (nla_put_u8(skb, IFLA_GENEVE_TTL, geneve->ttl) ||
nla_put_u8(skb, IFLA_GENEVE_TOS, geneve->tos))
@@ -971,7 +1341,8 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
if (IS_ERR(dev))
return dev;
- err = geneve_configure(net, dev, 0, 0, 0, 0, htons(dst_port), true);
+ err = geneve_configure(net, dev, &geneve_remote_unspec,
+ 0, 0, 0, htons(dst_port), true);
if (err) {
free_netdev(dev);
return ERR_PTR(err);
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index 1dd5ab8e5054..ce5f1a21e6d7 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -32,10 +32,18 @@ config IEEE802154_AT86RF230
This driver can also be built as a module. To do so, say M here.
the module will be called 'at86rf230'.
+config IEEE802154_AT86RF230_DEBUGFS
+ depends on IEEE802154_AT86RF230
+ bool "AT86RF230 debugfs interface"
+ depends on DEBUG_FS
+ ---help---
+ This option compiles debugfs code for the at86rf230 driver.
+
config IEEE802154_MRF24J40
tristate "Microchip MRF24J40 transceiver driver"
depends on IEEE802154_DRIVERS && MAC802154
depends on SPI
+ select REGMAP_SPI
---help---
Say Y here to enable the MRF24J20 SPI 802.15.4 wireless
controller.
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 6422caac8d40..0fbbba7a0cae 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -31,6 +31,7 @@
#include <linux/skbuff.h>
#include <linux/of_gpio.h>
#include <linux/ieee802154.h>
+#include <linux/debugfs.h>
#include <net/mac802154.h>
#include <net/cfg802154.h>
@@ -80,7 +81,16 @@ struct at86rf230_state_change {
u8 from_state;
u8 to_state;
- bool irq_enable;
+ bool free;
+};
+
+struct at86rf230_trac {
+ u64 success;
+ u64 success_data_pending;
+ u64 success_wait_for_ack;
+ u64 channel_access_failure;
+ u64 no_ack;
+ u64 invalid;
};
struct at86rf230_local {
@@ -95,14 +105,14 @@ struct at86rf230_local {
struct completion state_complete;
struct at86rf230_state_change state;
- struct at86rf230_state_change irq;
-
unsigned long cal_timeout;
bool is_tx;
bool is_tx_from_off;
u8 tx_retry;
struct sk_buff *tx_skb;
struct at86rf230_state_change tx;
+
+ struct at86rf230_trac trac;
};
#define AT86RF2XX_NUMREGS 0x3F
@@ -110,8 +120,7 @@ struct at86rf230_local {
static void
at86rf230_async_state_change(struct at86rf230_local *lp,
struct at86rf230_state_change *ctx,
- const u8 state, void (*complete)(void *context),
- const bool irq_enable);
+ const u8 state, void (*complete)(void *context));
static inline void
at86rf230_sleep(struct at86rf230_local *lp)
@@ -340,8 +349,10 @@ at86rf230_async_error_recover(void *context)
struct at86rf230_local *lp = ctx->lp;
lp->is_tx = 0;
- at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false);
+ at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL);
ieee802154_wake_queue(lp->hw);
+ if (ctx->free)
+ kfree(ctx);
}
static inline void
@@ -351,15 +362,14 @@ at86rf230_async_error(struct at86rf230_local *lp,
dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
- at86rf230_async_error_recover, false);
+ at86rf230_async_error_recover);
}
/* Generic function to get some register value in async mode */
static void
-at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
+at86rf230_async_read_reg(struct at86rf230_local *lp, u8 reg,
struct at86rf230_state_change *ctx,
- void (*complete)(void *context),
- const bool irq_enable)
+ void (*complete)(void *context))
{
int rc;
@@ -367,22 +377,24 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
ctx->msg.complete = complete;
- ctx->irq_enable = irq_enable;
rc = spi_async(lp->spi, &ctx->msg);
- if (rc) {
- if (irq_enable)
- enable_irq(ctx->irq);
-
+ if (rc)
at86rf230_async_error(lp, ctx, rc);
- }
}
-static inline u8 at86rf230_state_to_force(u8 state)
+static void
+at86rf230_async_write_reg(struct at86rf230_local *lp, u8 reg, u8 val,
+ struct at86rf230_state_change *ctx,
+ void (*complete)(void *context))
{
- if (state == STATE_TX_ON)
- return STATE_FORCE_TX_ON;
- else
- return STATE_FORCE_TRX_OFF;
+ int rc;
+
+ ctx->buf[0] = (reg & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
+ ctx->buf[1] = val;
+ ctx->msg.complete = complete;
+ rc = spi_async(lp->spi, &ctx->msg);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
}
static void
@@ -426,12 +438,11 @@ at86rf230_async_state_assert(void *context)
u8 state = ctx->to_state;
if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
- state = at86rf230_state_to_force(state);
+ state = STATE_FORCE_TRX_OFF;
lp->tx_retry++;
at86rf230_async_state_change(lp, ctx, state,
- ctx->complete,
- ctx->irq_enable);
+ ctx->complete);
return;
}
}
@@ -452,8 +463,7 @@ static enum hrtimer_restart at86rf230_async_state_timer(struct hrtimer *timer)
struct at86rf230_local *lp = ctx->lp;
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
- at86rf230_async_state_assert,
- ctx->irq_enable);
+ at86rf230_async_state_assert);
return HRTIMER_NORESTART;
}
@@ -558,14 +568,12 @@ at86rf230_async_state_change_start(void *context)
struct at86rf230_local *lp = ctx->lp;
u8 *buf = ctx->buf;
const u8 trx_state = buf[1] & TRX_STATE_MASK;
- int rc;
/* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
if (trx_state == STATE_TRANSITION_IN_PROGRESS) {
udelay(1);
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
- at86rf230_async_state_change_start,
- ctx->irq_enable);
+ at86rf230_async_state_change_start);
return;
}
@@ -582,31 +590,20 @@ at86rf230_async_state_change_start(void *context)
/* Going into the next step for a state change which do a timing
* relevant delay.
*/
- buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
- buf[1] = ctx->to_state;
- ctx->msg.complete = at86rf230_async_state_delay;
- rc = spi_async(lp->spi, &ctx->msg);
- if (rc) {
- if (ctx->irq_enable)
- enable_irq(ctx->irq);
-
- at86rf230_async_error(lp, ctx, rc);
- }
+ at86rf230_async_write_reg(lp, RG_TRX_STATE, ctx->to_state, ctx,
+ at86rf230_async_state_delay);
}
static void
at86rf230_async_state_change(struct at86rf230_local *lp,
struct at86rf230_state_change *ctx,
- const u8 state, void (*complete)(void *context),
- const bool irq_enable)
+ const u8 state, void (*complete)(void *context))
{
/* Initialization for the state change context */
ctx->to_state = state;
ctx->complete = complete;
- ctx->irq_enable = irq_enable;
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
- at86rf230_async_state_change_start,
- irq_enable);
+ at86rf230_async_state_change_start);
}
static void
@@ -628,8 +625,7 @@ at86rf230_sync_state_change(struct at86rf230_local *lp, unsigned int state)
unsigned long rc;
at86rf230_async_state_change(lp, &lp->state, state,
- at86rf230_sync_state_change_complete,
- false);
+ at86rf230_sync_state_change_complete);
rc = wait_for_completion_timeout(&lp->state_complete,
msecs_to_jiffies(100));
@@ -647,9 +643,8 @@ at86rf230_tx_complete(void *context)
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
- enable_irq(ctx->irq);
-
ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
+ kfree(ctx);
}
static void
@@ -659,7 +654,7 @@ at86rf230_tx_on(void *context)
struct at86rf230_local *lp = ctx->lp;
at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON,
- at86rf230_tx_complete, true);
+ at86rf230_tx_complete);
}
static void
@@ -667,28 +662,33 @@ at86rf230_tx_trac_check(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
- const u8 *buf = ctx->buf;
- const u8 trac = (buf[1] & 0xe0) >> 5;
- /* If trac status is different than zero we need to do a state change
- * to STATE_FORCE_TRX_OFF then STATE_RX_AACK_ON to recover the
- * transceiver.
- */
- if (trac)
- at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
- at86rf230_tx_on, true);
- else
- at86rf230_tx_on(context);
-}
+ if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
+ u8 trac = TRAC_MASK(ctx->buf[1]);
-static void
-at86rf230_tx_trac_status(void *context)
-{
- struct at86rf230_state_change *ctx = context;
- struct at86rf230_local *lp = ctx->lp;
+ switch (trac) {
+ case TRAC_SUCCESS:
+ lp->trac.success++;
+ break;
+ case TRAC_SUCCESS_DATA_PENDING:
+ lp->trac.success_data_pending++;
+ break;
+ case TRAC_CHANNEL_ACCESS_FAILURE:
+ lp->trac.channel_access_failure++;
+ break;
+ case TRAC_NO_ACK:
+ lp->trac.no_ack++;
+ break;
+ case TRAC_INVALID:
+ lp->trac.invalid++;
+ break;
+ default:
+ WARN_ONCE(1, "received tx trac status %d\n", trac);
+ break;
+ }
+ }
- at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
- at86rf230_tx_trac_check, true);
+ at86rf230_async_state_change(lp, ctx, STATE_TX_ON, at86rf230_tx_on);
}
static void
@@ -696,7 +696,6 @@ at86rf230_rx_read_frame_complete(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
- u8 rx_local_buf[AT86RF2XX_MAX_BUF];
const u8 *buf = ctx->buf;
struct sk_buff *skb;
u8 len, lqi;
@@ -708,63 +707,68 @@ at86rf230_rx_read_frame_complete(void *context)
}
lqi = buf[2 + len];
- memcpy(rx_local_buf, buf + 2, len);
- ctx->trx.len = 2;
- enable_irq(ctx->irq);
-
skb = dev_alloc_skb(IEEE802154_MTU);
if (!skb) {
dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n");
+ kfree(ctx);
return;
}
- memcpy(skb_put(skb, len), rx_local_buf, len);
+ memcpy(skb_put(skb, len), buf + 2, len);
ieee802154_rx_irqsafe(lp->hw, skb, lqi);
+ kfree(ctx);
}
static void
-at86rf230_rx_read_frame(void *context)
+at86rf230_rx_trac_check(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
u8 *buf = ctx->buf;
int rc;
+ if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
+ u8 trac = TRAC_MASK(buf[1]);
+
+ switch (trac) {
+ case TRAC_SUCCESS:
+ lp->trac.success++;
+ break;
+ case TRAC_SUCCESS_WAIT_FOR_ACK:
+ lp->trac.success_wait_for_ack++;
+ break;
+ case TRAC_INVALID:
+ lp->trac.invalid++;
+ break;
+ default:
+ WARN_ONCE(1, "received rx trac status %d\n", trac);
+ break;
+ }
+ }
+
buf[0] = CMD_FB;
ctx->trx.len = AT86RF2XX_MAX_BUF;
ctx->msg.complete = at86rf230_rx_read_frame_complete;
rc = spi_async(lp->spi, &ctx->msg);
if (rc) {
ctx->trx.len = 2;
- enable_irq(ctx->irq);
at86rf230_async_error(lp, ctx, rc);
}
}
static void
-at86rf230_rx_trac_check(void *context)
+at86rf230_irq_trx_end(void *context)
{
- /* Possible check on trac status here. This could be useful to make
- * some stats why receive is failed. Not used at the moment, but it's
- * maybe timing relevant. Datasheet doesn't say anything about this.
- * The programming guide say do it so.
- */
-
- at86rf230_rx_read_frame(context);
-}
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
-static void
-at86rf230_irq_trx_end(struct at86rf230_local *lp)
-{
if (lp->is_tx) {
lp->is_tx = 0;
- at86rf230_async_state_change(lp, &lp->irq,
- STATE_FORCE_TX_ON,
- at86rf230_tx_trac_status,
- true);
+ at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
+ at86rf230_tx_trac_check);
} else {
- at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
- at86rf230_rx_trac_check, true);
+ at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
+ at86rf230_rx_trac_check);
}
}
@@ -774,32 +778,59 @@ at86rf230_irq_status(void *context)
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
const u8 *buf = ctx->buf;
- const u8 irq = buf[1];
+ u8 irq = buf[1];
+
+ enable_irq(lp->spi->irq);
if (irq & IRQ_TRX_END) {
- at86rf230_irq_trx_end(lp);
+ at86rf230_irq_trx_end(ctx);
} else {
- enable_irq(ctx->irq);
dev_err(&lp->spi->dev, "not supported irq %02x received\n",
irq);
+ kfree(ctx);
}
}
+static void
+at86rf230_setup_spi_messages(struct at86rf230_local *lp,
+ struct at86rf230_state_change *state)
+{
+ state->lp = lp;
+ state->irq = lp->spi->irq;
+ spi_message_init(&state->msg);
+ state->msg.context = state;
+ state->trx.len = 2;
+ state->trx.tx_buf = state->buf;
+ state->trx.rx_buf = state->buf;
+ spi_message_add_tail(&state->trx, &state->msg);
+ hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ state->timer.function = at86rf230_async_state_timer;
+}
+
static irqreturn_t at86rf230_isr(int irq, void *data)
{
struct at86rf230_local *lp = data;
- struct at86rf230_state_change *ctx = &lp->irq;
- u8 *buf = ctx->buf;
+ struct at86rf230_state_change *ctx;
int rc;
disable_irq_nosync(irq);
- buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
+ ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
+ if (!ctx) {
+ enable_irq(irq);
+ return IRQ_NONE;
+ }
+
+ at86rf230_setup_spi_messages(lp, ctx);
+ /* tell on error handling to free ctx */
+ ctx->free = true;
+
+ ctx->buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
ctx->msg.complete = at86rf230_irq_status;
rc = spi_async(lp->spi, &ctx->msg);
if (rc) {
- enable_irq(irq);
at86rf230_async_error(lp, ctx, rc);
+ enable_irq(irq);
return IRQ_NONE;
}
@@ -811,21 +842,14 @@ at86rf230_write_frame_complete(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
- u8 *buf = ctx->buf;
- int rc;
ctx->trx.len = 2;
- if (gpio_is_valid(lp->slp_tr)) {
+ if (gpio_is_valid(lp->slp_tr))
at86rf230_slp_tr_rising_edge(lp);
- } else {
- buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
- buf[1] = STATE_BUSY_TX;
- ctx->msg.complete = NULL;
- rc = spi_async(lp->spi, &ctx->msg);
- if (rc)
- at86rf230_async_error(lp, ctx, rc);
- }
+ else
+ at86rf230_async_write_reg(lp, RG_TRX_STATE, STATE_BUSY_TX, ctx,
+ NULL);
}
static void
@@ -858,7 +882,7 @@ at86rf230_xmit_tx_on(void *context)
struct at86rf230_local *lp = ctx->lp;
at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
- at86rf230_write_frame, false);
+ at86rf230_write_frame);
}
static void
@@ -871,12 +895,10 @@ at86rf230_xmit_start(void *context)
if (lp->is_tx_from_off) {
lp->is_tx_from_off = false;
at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
- at86rf230_write_frame,
- false);
+ at86rf230_write_frame);
} else {
at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
- at86rf230_xmit_tx_on,
- false);
+ at86rf230_xmit_tx_on);
}
}
@@ -899,7 +921,7 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
if (time_is_before_jiffies(lp->cal_timeout)) {
lp->is_tx_from_off = true;
at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF,
- at86rf230_xmit_start, false);
+ at86rf230_xmit_start);
} else {
at86rf230_xmit_start(ctx);
}
@@ -920,6 +942,10 @@ at86rf230_start(struct ieee802154_hw *hw)
{
struct at86rf230_local *lp = hw->priv;
+ /* reset trac stats on start */
+ if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS))
+ memset(&lp->trac, 0, sizeof(struct at86rf230_trac));
+
at86rf230_awake(lp);
enable_irq(lp->spi->irq);
@@ -1354,10 +1380,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp, u8 xtal_trim)
return rc;
irq_type = irq_get_trigger_type(lp->spi->irq);
- if (irq_type == IRQ_TYPE_EDGE_RISING ||
- irq_type == IRQ_TYPE_EDGE_FALLING)
- dev_warn(&lp->spi->dev,
- "Using edge triggered irq's are not recommended!\n");
if (irq_type == IRQ_TYPE_EDGE_FALLING ||
irq_type == IRQ_TYPE_LEVEL_LOW)
irq_pol = IRQ_ACTIVE_LOW;
@@ -1583,42 +1605,65 @@ not_supp:
return rc;
}
-static void
-at86rf230_setup_spi_messages(struct at86rf230_local *lp)
+#ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS
+static struct dentry *at86rf230_debugfs_root;
+
+static int at86rf230_stats_show(struct seq_file *file, void *offset)
+{
+ struct at86rf230_local *lp = file->private;
+
+ seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success);
+ seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n",
+ lp->trac.success_data_pending);
+ seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n",
+ lp->trac.success_wait_for_ack);
+ seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n",
+ lp->trac.channel_access_failure);
+ seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack);
+ seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid);
+ return 0;
+}
+
+static int at86rf230_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, at86rf230_stats_show, inode->i_private);
+}
+
+static const struct file_operations at86rf230_stats_fops = {
+ .open = at86rf230_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int at86rf230_debugfs_init(struct at86rf230_local *lp)
+{
+ char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-";
+ struct dentry *stats;
+
+ strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN);
+
+ at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
+ if (!at86rf230_debugfs_root)
+ return -ENOMEM;
+
+ stats = debugfs_create_file("trac_stats", S_IRUGO,
+ at86rf230_debugfs_root, lp,
+ &at86rf230_stats_fops);
+ if (!stats)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void at86rf230_debugfs_remove(void)
{
- lp->state.lp = lp;
- lp->state.irq = lp->spi->irq;
- spi_message_init(&lp->state.msg);
- lp->state.msg.context = &lp->state;
- lp->state.trx.len = 2;
- lp->state.trx.tx_buf = lp->state.buf;
- lp->state.trx.rx_buf = lp->state.buf;
- spi_message_add_tail(&lp->state.trx, &lp->state.msg);
- hrtimer_init(&lp->state.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- lp->state.timer.function = at86rf230_async_state_timer;
-
- lp->irq.lp = lp;
- lp->irq.irq = lp->spi->irq;
- spi_message_init(&lp->irq.msg);
- lp->irq.msg.context = &lp->irq;
- lp->irq.trx.len = 2;
- lp->irq.trx.tx_buf = lp->irq.buf;
- lp->irq.trx.rx_buf = lp->irq.buf;
- spi_message_add_tail(&lp->irq.trx, &lp->irq.msg);
- hrtimer_init(&lp->irq.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- lp->irq.timer.function = at86rf230_async_state_timer;
-
- lp->tx.lp = lp;
- lp->tx.irq = lp->spi->irq;
- spi_message_init(&lp->tx.msg);
- lp->tx.msg.context = &lp->tx;
- lp->tx.trx.len = 2;
- lp->tx.trx.tx_buf = lp->tx.buf;
- lp->tx.trx.rx_buf = lp->tx.buf;
- spi_message_add_tail(&lp->tx.trx, &lp->tx.msg);
- hrtimer_init(&lp->tx.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- lp->tx.timer.function = at86rf230_async_state_timer;
+ debugfs_remove_recursive(at86rf230_debugfs_root);
}
+#else
+static int at86rf230_debugfs_init(struct at86rf230_local *lp) { return 0; }
+static void at86rf230_debugfs_remove(void) { }
+#endif
static int at86rf230_probe(struct spi_device *spi)
{
@@ -1681,7 +1726,8 @@ static int at86rf230_probe(struct spi_device *spi)
goto free_dev;
}
- at86rf230_setup_spi_messages(lp);
+ at86rf230_setup_spi_messages(lp, &lp->state);
+ at86rf230_setup_spi_messages(lp, &lp->tx);
rc = at86rf230_detect_device(lp);
if (rc < 0)
@@ -1715,12 +1761,18 @@ static int at86rf230_probe(struct spi_device *spi)
/* going into sleep by default */
at86rf230_sleep(lp);
- rc = ieee802154_register_hw(lp->hw);
+ rc = at86rf230_debugfs_init(lp);
if (rc)
goto free_dev;
+ rc = ieee802154_register_hw(lp->hw);
+ if (rc)
+ goto free_debugfs;
+
return rc;
+free_debugfs:
+ at86rf230_debugfs_remove();
free_dev:
ieee802154_free_hw(lp->hw);
@@ -1735,6 +1787,7 @@ static int at86rf230_remove(struct spi_device *spi)
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
ieee802154_unregister_hw(lp->hw);
ieee802154_free_hw(lp->hw);
+ at86rf230_debugfs_remove();
dev_dbg(&spi->dev, "unregistered at86rf230\n");
return 0;
@@ -1763,7 +1816,6 @@ static struct spi_driver at86rf230_driver = {
.driver = {
.of_match_table = of_match_ptr(at86rf230_of_match),
.name = "at86rf230",
- .owner = THIS_MODULE,
},
.probe = at86rf230_probe,
.remove = at86rf230_remove,
diff --git a/drivers/net/ieee802154/at86rf230.h b/drivers/net/ieee802154/at86rf230.h
index 1e6d1cc677f6..fd9c1f467f63 100644
--- a/drivers/net/ieee802154/at86rf230.h
+++ b/drivers/net/ieee802154/at86rf230.h
@@ -216,5 +216,13 @@
#define STATE_TRANSITION_IN_PROGRESS 0x1F
#define TRX_STATE_MASK (0x1F)
+#define TRAC_MASK(x) ((x & 0xe0) >> 5)
+
+#define TRAC_SUCCESS 0
+#define TRAC_SUCCESS_DATA_PENDING 1
+#define TRAC_SUCCESS_WAIT_FOR_ACK 2
+#define TRAC_CHANNEL_ACCESS_FAILURE 3
+#define TRAC_NO_ACK 5
+#define TRAC_INVALID 7
#endif /* !_AT86RF230_H */
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 80dfc725b8dc..199a94a9c8bc 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -559,6 +559,7 @@ static int atusb_get_and_show_chip(struct atusb *atusb)
{
struct usb_device *usb_dev = atusb->usb_dev;
uint8_t man_id_0, man_id_1, part_num, version_num;
+ const char *chip;
man_id_0 = atusb_read_reg(atusb, RG_MAN_ID_0);
man_id_1 = atusb_read_reg(atusb, RG_MAN_ID_1);
@@ -574,14 +575,22 @@ static int atusb_get_and_show_chip(struct atusb *atusb)
man_id_1, man_id_0);
goto fail;
}
- if (part_num != 3 && part_num != 2) {
+
+ switch (part_num) {
+ case 2:
+ chip = "AT86RF230";
+ break;
+ case 3:
+ chip = "AT86RF231";
+ break;
+ default:
dev_err(&usb_dev->dev,
"unexpected transceiver, part 0x%02x version 0x%02x\n",
part_num, version_num);
goto fail;
}
- dev_info(&usb_dev->dev, "ATUSB: AT86RF231 version %d\n", version_num);
+ dev_info(&usb_dev->dev, "ATUSB: %s version %d\n", chip, version_num);
return 0;
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
index c5b54a15fc4c..e65b60591317 100644
--- a/drivers/net/ieee802154/cc2520.c
+++ b/drivers/net/ieee802154/cc2520.c
@@ -1152,7 +1152,6 @@ MODULE_DEVICE_TABLE(of, cc2520_of_ids);
static struct spi_driver cc2520_driver = {
.driver = {
.name = "cc2520",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(cc2520_of_ids),
},
.id_table = cc2520_ids,
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 997724b8e434..4cdf51638972 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -18,51 +18,172 @@
#include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/regmap.h>
#include <linux/ieee802154.h>
+#include <linux/irq.h>
#include <net/cfg802154.h>
#include <net/mac802154.h>
/* MRF24J40 Short Address Registers */
-#define REG_RXMCR 0x00 /* Receive MAC control */
-#define REG_PANIDL 0x01 /* PAN ID (low) */
-#define REG_PANIDH 0x02 /* PAN ID (high) */
-#define REG_SADRL 0x03 /* Short address (low) */
-#define REG_SADRH 0x04 /* Short address (high) */
-#define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */
-#define REG_TXMCR 0x11 /* Transmit MAC control */
-#define REG_PACON0 0x16 /* Power Amplifier Control */
-#define REG_PACON1 0x17 /* Power Amplifier Control */
-#define REG_PACON2 0x18 /* Power Amplifier Control */
-#define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */
-#define REG_TXSTAT 0x24 /* TX MAC Status Register */
-#define REG_SOFTRST 0x2A /* Soft Reset */
-#define REG_TXSTBL 0x2E /* TX Stabilization */
-#define REG_INTSTAT 0x31 /* Interrupt Status */
-#define REG_INTCON 0x32 /* Interrupt Control */
-#define REG_GPIO 0x33 /* GPIO */
-#define REG_TRISGPIO 0x34 /* GPIO direction */
-#define REG_RFCTL 0x36 /* RF Control Mode Register */
-#define REG_BBREG1 0x39 /* Baseband Registers */
-#define REG_BBREG2 0x3A /* */
-#define REG_BBREG6 0x3E /* */
-#define REG_CCAEDTH 0x3F /* Energy Detection Threshold */
+#define REG_RXMCR 0x00 /* Receive MAC control */
+#define BIT_PROMI BIT(0)
+#define BIT_ERRPKT BIT(1)
+#define BIT_NOACKRSP BIT(5)
+#define BIT_PANCOORD BIT(3)
+
+#define REG_PANIDL 0x01 /* PAN ID (low) */
+#define REG_PANIDH 0x02 /* PAN ID (high) */
+#define REG_SADRL 0x03 /* Short address (low) */
+#define REG_SADRH 0x04 /* Short address (high) */
+#define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */
+#define REG_EADR1 0x06
+#define REG_EADR2 0x07
+#define REG_EADR3 0x08
+#define REG_EADR4 0x09
+#define REG_EADR5 0x0A
+#define REG_EADR6 0x0B
+#define REG_EADR7 0x0C
+#define REG_RXFLUSH 0x0D
+#define REG_ORDER 0x10
+#define REG_TXMCR 0x11 /* Transmit MAC control */
+#define TXMCR_MIN_BE_SHIFT 3
+#define TXMCR_MIN_BE_MASK 0x18
+#define TXMCR_CSMA_RETRIES_SHIFT 0
+#define TXMCR_CSMA_RETRIES_MASK 0x07
+
+#define REG_ACKTMOUT 0x12
+#define REG_ESLOTG1 0x13
+#define REG_SYMTICKL 0x14
+#define REG_SYMTICKH 0x15
+#define REG_PACON0 0x16 /* Power Amplifier Control */
+#define REG_PACON1 0x17 /* Power Amplifier Control */
+#define REG_PACON2 0x18 /* Power Amplifier Control */
+#define REG_TXBCON0 0x1A
+#define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */
+#define BIT_TXNTRIG BIT(0)
+#define BIT_TXNACKREQ BIT(2)
+
+#define REG_TXG1CON 0x1C
+#define REG_TXG2CON 0x1D
+#define REG_ESLOTG23 0x1E
+#define REG_ESLOTG45 0x1F
+#define REG_ESLOTG67 0x20
+#define REG_TXPEND 0x21
+#define REG_WAKECON 0x22
+#define REG_FROMOFFSET 0x23
+#define REG_TXSTAT 0x24 /* TX MAC Status Register */
+#define REG_TXBCON1 0x25
+#define REG_GATECLK 0x26
+#define REG_TXTIME 0x27
+#define REG_HSYMTMRL 0x28
+#define REG_HSYMTMRH 0x29
+#define REG_SOFTRST 0x2A /* Soft Reset */
+#define REG_SECCON0 0x2C
+#define REG_SECCON1 0x2D
+#define REG_TXSTBL 0x2E /* TX Stabilization */
+#define REG_RXSR 0x30
+#define REG_INTSTAT 0x31 /* Interrupt Status */
+#define BIT_TXNIF BIT(0)
+#define BIT_RXIF BIT(3)
+
+#define REG_INTCON 0x32 /* Interrupt Control */
+#define BIT_TXNIE BIT(0)
+#define BIT_RXIE BIT(3)
+
+#define REG_GPIO 0x33 /* GPIO */
+#define REG_TRISGPIO 0x34 /* GPIO direction */
+#define REG_SLPACK 0x35
+#define REG_RFCTL 0x36 /* RF Control Mode Register */
+#define BIT_RFRST BIT(2)
+
+#define REG_SECCR2 0x37
+#define REG_BBREG0 0x38
+#define REG_BBREG1 0x39 /* Baseband Registers */
+#define BIT_RXDECINV BIT(2)
+
+#define REG_BBREG2 0x3A /* */
+#define BBREG2_CCA_MODE_SHIFT 6
+#define BBREG2_CCA_MODE_MASK 0xc0
+
+#define REG_BBREG3 0x3B
+#define REG_BBREG4 0x3C
+#define REG_BBREG6 0x3E /* */
+#define REG_CCAEDTH 0x3F /* Energy Detection Threshold */
/* MRF24J40 Long Address Registers */
-#define REG_RFCON0 0x200 /* RF Control Registers */
-#define REG_RFCON1 0x201
-#define REG_RFCON2 0x202
-#define REG_RFCON3 0x203
-#define REG_RFCON5 0x205
-#define REG_RFCON6 0x206
-#define REG_RFCON7 0x207
-#define REG_RFCON8 0x208
-#define REG_RSSI 0x210
-#define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */
-#define REG_SLPCON1 0x220
-#define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */
-#define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */
-#define REG_TESTMODE 0x22F /* Test mode */
-#define REG_RX_FIFO 0x300 /* Receive FIFO */
+#define REG_RFCON0 0x200 /* RF Control Registers */
+#define RFCON0_CH_SHIFT 4
+#define RFCON0_CH_MASK 0xf0
+#define RFOPT_RECOMMEND 3
+
+#define REG_RFCON1 0x201
+#define REG_RFCON2 0x202
+#define REG_RFCON3 0x203
+
+#define TXPWRL_MASK 0xc0
+#define TXPWRL_SHIFT 6
+#define TXPWRL_30 0x3
+#define TXPWRL_20 0x2
+#define TXPWRL_10 0x1
+#define TXPWRL_0 0x0
+
+#define TXPWRS_MASK 0x38
+#define TXPWRS_SHIFT 3
+#define TXPWRS_6_3 0x7
+#define TXPWRS_4_9 0x6
+#define TXPWRS_3_7 0x5
+#define TXPWRS_2_8 0x4
+#define TXPWRS_1_9 0x3
+#define TXPWRS_1_2 0x2
+#define TXPWRS_0_5 0x1
+#define TXPWRS_0 0x0
+
+#define REG_RFCON5 0x205
+#define REG_RFCON6 0x206
+#define REG_RFCON7 0x207
+#define REG_RFCON8 0x208
+#define REG_SLPCAL0 0x209
+#define REG_SLPCAL1 0x20A
+#define REG_SLPCAL2 0x20B
+#define REG_RFSTATE 0x20F
+#define REG_RSSI 0x210
+#define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */
+#define BIT_INTEDGE BIT(1)
+
+#define REG_SLPCON1 0x220
+#define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */
+#define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */
+#define REG_REMCNTL 0x224
+#define REG_REMCNTH 0x225
+#define REG_MAINCNT0 0x226
+#define REG_MAINCNT1 0x227
+#define REG_MAINCNT2 0x228
+#define REG_MAINCNT3 0x229
+#define REG_TESTMODE 0x22F /* Test mode */
+#define REG_ASSOEAR0 0x230
+#define REG_ASSOEAR1 0x231
+#define REG_ASSOEAR2 0x232
+#define REG_ASSOEAR3 0x233
+#define REG_ASSOEAR4 0x234
+#define REG_ASSOEAR5 0x235
+#define REG_ASSOEAR6 0x236
+#define REG_ASSOEAR7 0x237
+#define REG_ASSOSAR0 0x238
+#define REG_ASSOSAR1 0x239
+#define REG_UNONCE0 0x240
+#define REG_UNONCE1 0x241
+#define REG_UNONCE2 0x242
+#define REG_UNONCE3 0x243
+#define REG_UNONCE4 0x244
+#define REG_UNONCE5 0x245
+#define REG_UNONCE6 0x246
+#define REG_UNONCE7 0x247
+#define REG_UNONCE8 0x248
+#define REG_UNONCE9 0x249
+#define REG_UNONCE10 0x24A
+#define REG_UNONCE11 0x24B
+#define REG_UNONCE12 0x24C
+#define REG_RX_FIFO 0x300 /* Receive FIFO */
/* Device configuration: Only channels 11-26 on page 0 are supported. */
#define MRF24J40_CHAN_MIN 11
@@ -81,11 +202,52 @@ struct mrf24j40 {
struct spi_device *spi;
struct ieee802154_hw *hw;
- struct mutex buffer_mutex; /* only used to protect buf */
- struct completion tx_complete;
- u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
+ struct regmap *regmap_short;
+ struct regmap *regmap_long;
+
+ /* for writing txfifo */
+ struct spi_message tx_msg;
+ u8 tx_hdr_buf[2];
+ struct spi_transfer tx_hdr_trx;
+ u8 tx_len_buf[2];
+ struct spi_transfer tx_len_trx;
+ struct spi_transfer tx_buf_trx;
+ struct sk_buff *tx_skb;
+
+ /* post transmit message to send frame out */
+ struct spi_message tx_post_msg;
+ u8 tx_post_buf[2];
+ struct spi_transfer tx_post_trx;
+
+ /* for protect/unprotect/read length rxfifo */
+ struct spi_message rx_msg;
+ u8 rx_buf[3];
+ struct spi_transfer rx_trx;
+
+ /* receive handling */
+ struct spi_message rx_buf_msg;
+ u8 rx_addr_buf[2];
+ struct spi_transfer rx_addr_trx;
+ u8 rx_lqi_buf[2];
+ struct spi_transfer rx_lqi_trx;
+ u8 rx_fifo_buf[RX_FIFO_SIZE];
+ struct spi_transfer rx_fifo_buf_trx;
+
+ /* isr handling for reading intstat */
+ struct spi_message irq_msg;
+ u8 irq_buf[2];
+ struct spi_transfer irq_trx;
};
+/* regmap information for short address register access */
+#define MRF24J40_SHORT_WRITE 0x01
+#define MRF24J40_SHORT_READ 0x00
+#define MRF24J40_SHORT_NUMREGS 0x3F
+
+/* regmap information for long address register access */
+#define MRF24J40_LONG_ACCESS 0x80
+#define MRF24J40_LONG_NUMREGS 0x38F
+
/* Read/Write SPI Commands for Short and Long Address registers. */
#define MRF24J40_READSHORT(reg) ((reg) << 1)
#define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1)
@@ -97,118 +259,304 @@ struct mrf24j40 {
#define printdev(X) (&X->spi->dev)
-static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value)
+static bool
+mrf24j40_short_reg_writeable(struct device *dev, unsigned int reg)
{
- int ret;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
+ switch (reg) {
+ case REG_RXMCR:
+ case REG_PANIDL:
+ case REG_PANIDH:
+ case REG_SADRL:
+ case REG_SADRH:
+ case REG_EADR0:
+ case REG_EADR1:
+ case REG_EADR2:
+ case REG_EADR3:
+ case REG_EADR4:
+ case REG_EADR5:
+ case REG_EADR6:
+ case REG_EADR7:
+ case REG_RXFLUSH:
+ case REG_ORDER:
+ case REG_TXMCR:
+ case REG_ACKTMOUT:
+ case REG_ESLOTG1:
+ case REG_SYMTICKL:
+ case REG_SYMTICKH:
+ case REG_PACON0:
+ case REG_PACON1:
+ case REG_PACON2:
+ case REG_TXBCON0:
+ case REG_TXNCON:
+ case REG_TXG1CON:
+ case REG_TXG2CON:
+ case REG_ESLOTG23:
+ case REG_ESLOTG45:
+ case REG_ESLOTG67:
+ case REG_TXPEND:
+ case REG_WAKECON:
+ case REG_FROMOFFSET:
+ case REG_TXBCON1:
+ case REG_GATECLK:
+ case REG_TXTIME:
+ case REG_HSYMTMRL:
+ case REG_HSYMTMRH:
+ case REG_SOFTRST:
+ case REG_SECCON0:
+ case REG_SECCON1:
+ case REG_TXSTBL:
+ case REG_RXSR:
+ case REG_INTCON:
+ case REG_TRISGPIO:
+ case REG_GPIO:
+ case REG_RFCTL:
+ case REG_SLPACK:
+ case REG_BBREG0:
+ case REG_BBREG1:
+ case REG_BBREG2:
+ case REG_BBREG3:
+ case REG_BBREG4:
+ case REG_BBREG6:
+ case REG_CCAEDTH:
+ return true;
+ default:
+ return false;
+ }
+}
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
+static bool
+mrf24j40_short_reg_readable(struct device *dev, unsigned int reg)
+{
+ bool rc;
+
+ /* all writeable are also readable */
+ rc = mrf24j40_short_reg_writeable(dev, reg);
+ if (rc)
+ return rc;
+
+ /* readonly regs */
+ switch (reg) {
+ case REG_TXSTAT:
+ case REG_INTSTAT:
+ return true;
+ default:
+ return false;
+ }
+}
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = MRF24J40_WRITESHORT(reg);
- devrec->buf[1] = value;
+static bool
+mrf24j40_short_reg_volatile(struct device *dev, unsigned int reg)
+{
+ /* can be changed during runtime */
+ switch (reg) {
+ case REG_TXSTAT:
+ case REG_INTSTAT:
+ case REG_RXFLUSH:
+ case REG_TXNCON:
+ case REG_SOFTRST:
+ case REG_RFCTL:
+ case REG_TXBCON0:
+ case REG_TXG1CON:
+ case REG_TXG2CON:
+ case REG_TXBCON1:
+ case REG_SECCON0:
+ case REG_RXSR:
+ case REG_SLPACK:
+ case REG_SECCR2:
+ case REG_BBREG6:
+ /* use them in spi_async and regmap so it's volatile */
+ case REG_BBREG1:
+ return true;
+ default:
+ return false;
+ }
+}
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI write Failed for short register 0x%hhx\n", reg);
+static bool
+mrf24j40_short_reg_precious(struct device *dev, unsigned int reg)
+{
+ /* don't clear irq line on read */
+ switch (reg) {
+ case REG_INTSTAT:
+ return true;
+ default:
+ return false;
+ }
+}
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
+static const struct regmap_config mrf24j40_short_regmap = {
+ .name = "mrf24j40_short",
+ .reg_bits = 7,
+ .val_bits = 8,
+ .pad_bits = 1,
+ .write_flag_mask = MRF24J40_SHORT_WRITE,
+ .read_flag_mask = MRF24J40_SHORT_READ,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = MRF24J40_SHORT_NUMREGS,
+ .writeable_reg = mrf24j40_short_reg_writeable,
+ .readable_reg = mrf24j40_short_reg_readable,
+ .volatile_reg = mrf24j40_short_reg_volatile,
+ .precious_reg = mrf24j40_short_reg_precious,
+};
+
+static bool
+mrf24j40_long_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case REG_RFCON0:
+ case REG_RFCON1:
+ case REG_RFCON2:
+ case REG_RFCON3:
+ case REG_RFCON5:
+ case REG_RFCON6:
+ case REG_RFCON7:
+ case REG_RFCON8:
+ case REG_SLPCAL2:
+ case REG_SLPCON0:
+ case REG_SLPCON1:
+ case REG_WAKETIMEL:
+ case REG_WAKETIMEH:
+ case REG_REMCNTL:
+ case REG_REMCNTH:
+ case REG_MAINCNT0:
+ case REG_MAINCNT1:
+ case REG_MAINCNT2:
+ case REG_MAINCNT3:
+ case REG_TESTMODE:
+ case REG_ASSOEAR0:
+ case REG_ASSOEAR1:
+ case REG_ASSOEAR2:
+ case REG_ASSOEAR3:
+ case REG_ASSOEAR4:
+ case REG_ASSOEAR5:
+ case REG_ASSOEAR6:
+ case REG_ASSOEAR7:
+ case REG_ASSOSAR0:
+ case REG_ASSOSAR1:
+ case REG_UNONCE0:
+ case REG_UNONCE1:
+ case REG_UNONCE2:
+ case REG_UNONCE3:
+ case REG_UNONCE4:
+ case REG_UNONCE5:
+ case REG_UNONCE6:
+ case REG_UNONCE7:
+ case REG_UNONCE8:
+ case REG_UNONCE9:
+ case REG_UNONCE10:
+ case REG_UNONCE11:
+ case REG_UNONCE12:
+ return true;
+ default:
+ return false;
+ }
}
-static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
+static bool
+mrf24j40_long_reg_readable(struct device *dev, unsigned int reg)
{
- int ret = -1;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
+ bool rc;
+
+ /* all writeable are also readable */
+ rc = mrf24j40_long_reg_writeable(dev, reg);
+ if (rc)
+ return rc;
+
+ /* readonly regs */
+ switch (reg) {
+ case REG_SLPCAL0:
+ case REG_SLPCAL1:
+ case REG_RFSTATE:
+ case REG_RSSI:
+ return true;
+ default:
+ return false;
+ }
+}
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
+static bool
+mrf24j40_long_reg_volatile(struct device *dev, unsigned int reg)
+{
+ /* can be changed during runtime */
+ switch (reg) {
+ case REG_SLPCAL0:
+ case REG_SLPCAL1:
+ case REG_SLPCAL2:
+ case REG_RFSTATE:
+ case REG_RSSI:
+ case REG_MAINCNT3:
+ return true;
+ default:
+ return false;
+ }
+}
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = MRF24J40_READSHORT(reg);
- devrec->buf[1] = 0;
+static const struct regmap_config mrf24j40_long_regmap = {
+ .name = "mrf24j40_long",
+ .reg_bits = 11,
+ .val_bits = 8,
+ .pad_bits = 5,
+ .write_flag_mask = MRF24J40_LONG_ACCESS,
+ .read_flag_mask = MRF24J40_LONG_ACCESS,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = MRF24J40_LONG_NUMREGS,
+ .writeable_reg = mrf24j40_long_reg_writeable,
+ .readable_reg = mrf24j40_long_reg_readable,
+ .volatile_reg = mrf24j40_long_reg_volatile,
+};
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI read Failed for short register 0x%hhx\n", reg);
- else
- *val = devrec->buf[1];
+static int mrf24j40_long_regmap_write(void *context, const void *data,
+ size_t count)
+{
+ struct spi_device *spi = context;
+ u8 buf[3];
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
+ if (count > 3)
+ return -EINVAL;
+
+ /* regmap supports read/write mask only in frist byte
+ * long write access need to set the 12th bit, so we
+ * make special handling for write.
+ */
+ memcpy(buf, data, count);
+ buf[1] |= (1 << 4);
+
+ return spi_write(spi, buf, count);
}
-static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
+static int
+mrf24j40_long_regmap_read(void *context, const void *reg, size_t reg_size,
+ void *val, size_t val_size)
{
- int ret;
- u16 cmd;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 3,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
-
- cmd = MRF24J40_READLONG(reg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = cmd >> 8 & 0xff;
- devrec->buf[1] = cmd & 0xff;
- devrec->buf[2] = 0;
-
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI read Failed for long register 0x%hx\n", reg);
- else
- *value = devrec->buf[2];
+ struct spi_device *spi = context;
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
+ return spi_write_then_read(spi, reg, reg_size, val, val_size);
}
-static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val)
+static const struct regmap_bus mrf24j40_long_regmap_bus = {
+ .write = mrf24j40_long_regmap_write,
+ .read = mrf24j40_long_regmap_read,
+ .reg_format_endian_default = REGMAP_ENDIAN_BIG,
+ .val_format_endian_default = REGMAP_ENDIAN_BIG,
+};
+
+static void write_tx_buf_complete(void *context)
{
+ struct mrf24j40 *devrec = context;
+ __le16 fc = ieee802154_get_fc_from_skb(devrec->tx_skb);
+ u8 val = BIT_TXNTRIG;
int ret;
- u16 cmd;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 3,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
+ if (ieee802154_is_ackreq(fc))
+ val |= BIT_TXNACKREQ;
- cmd = MRF24J40_WRITELONG(reg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = cmd >> 8 & 0xff;
- devrec->buf[1] = cmd & 0xff;
- devrec->buf[2] = val;
+ devrec->tx_post_msg.complete = NULL;
+ devrec->tx_post_buf[0] = MRF24J40_WRITESHORT(REG_TXNCON);
+ devrec->tx_post_buf[1] = val;
- ret = spi_sync(devrec->spi, &msg);
+ ret = spi_async(devrec->spi, &devrec->tx_post_msg);
if (ret)
- dev_err(printdev(devrec),
- "SPI write Failed for long register 0x%hx\n", reg);
-
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
+ dev_err(printdev(devrec), "SPI write Failed for transmit buf\n");
}
/* This function relies on an undocumented write method. Once a write command
@@ -217,22 +565,8 @@ static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val)
static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
const u8 *data, size_t length)
{
- int ret;
u16 cmd;
- u8 lengths[2];
- struct spi_message msg;
- struct spi_transfer addr_xfer = {
- .len = 2,
- .tx_buf = devrec->buf,
- };
- struct spi_transfer lengths_xfer = {
- .len = 2,
- .tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */
- };
- struct spi_transfer data_xfer = {
- .len = length,
- .tx_buf = data,
- };
+ int ret;
/* Range check the length. 2 bytes are used for the length fields.*/
if (length > TX_FIFO_SIZE-2) {
@@ -240,147 +574,29 @@ static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
length = TX_FIFO_SIZE-2;
}
- spi_message_init(&msg);
- spi_message_add_tail(&addr_xfer, &msg);
- spi_message_add_tail(&lengths_xfer, &msg);
- spi_message_add_tail(&data_xfer, &msg);
-
cmd = MRF24J40_WRITELONG(reg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = cmd >> 8 & 0xff;
- devrec->buf[1] = cmd & 0xff;
- lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
- lengths[1] = length; /* Total length */
-
- ret = spi_sync(devrec->spi, &msg);
+ devrec->tx_hdr_buf[0] = cmd >> 8 & 0xff;
+ devrec->tx_hdr_buf[1] = cmd & 0xff;
+ devrec->tx_len_buf[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
+ devrec->tx_len_buf[1] = length; /* Total length */
+ devrec->tx_buf_trx.tx_buf = data;
+ devrec->tx_buf_trx.len = length;
+
+ ret = spi_async(devrec->spi, &devrec->tx_msg);
if (ret)
dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
-}
-
-static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
- u8 *data, u8 *len, u8 *lqi)
-{
- u8 rx_len;
- u8 addr[2];
- u8 lqi_rssi[2];
- u16 cmd;
- int ret;
- struct spi_message msg;
- struct spi_transfer addr_xfer = {
- .len = 2,
- .tx_buf = &addr,
- };
- struct spi_transfer data_xfer = {
- .len = 0x0, /* set below */
- .rx_buf = data,
- };
- struct spi_transfer status_xfer = {
- .len = 2,
- .rx_buf = &lqi_rssi,
- };
-
- /* Get the length of the data in the RX FIFO. The length in this
- * register exclues the 1-byte length field at the beginning. */
- ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len);
- if (ret)
- goto out;
-
- /* Range check the RX FIFO length, accounting for the one-byte
- * length field at the beginning. */
- if (rx_len > RX_FIFO_SIZE-1) {
- dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n");
- rx_len = RX_FIFO_SIZE-1;
- }
-
- if (rx_len > *len) {
- /* Passed in buffer wasn't big enough. Should never happen. */
- dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n");
- rx_len = *len;
- }
-
- /* Set up the commands to read the data. */
- cmd = MRF24J40_READLONG(REG_RX_FIFO+1);
- addr[0] = cmd >> 8 & 0xff;
- addr[1] = cmd & 0xff;
- data_xfer.len = rx_len;
-
- spi_message_init(&msg);
- spi_message_add_tail(&addr_xfer, &msg);
- spi_message_add_tail(&data_xfer, &msg);
- spi_message_add_tail(&status_xfer, &msg);
-
- ret = spi_sync(devrec->spi, &msg);
- if (ret) {
- dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n");
- goto out;
- }
-
- *lqi = lqi_rssi[0];
- *len = rx_len;
-
-#ifdef DEBUG
- print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
- DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
- pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
- lqi_rssi[0], lqi_rssi[1]);
-#endif
-
-out:
return ret;
}
static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
{
struct mrf24j40 *devrec = hw->priv;
- u8 val;
- int ret = 0;
dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
+ devrec->tx_skb = skb;
- ret = write_tx_buf(devrec, 0x000, skb->data, skb->len);
- if (ret)
- goto err;
-
- reinit_completion(&devrec->tx_complete);
-
- /* Set TXNTRIG bit of TXNCON to send packet */
- ret = read_short_reg(devrec, REG_TXNCON, &val);
- if (ret)
- goto err;
- val |= 0x1;
- /* Set TXNACKREQ if the ACK bit is set in the packet. */
- if (skb->data[0] & IEEE802154_FC_ACK_REQ)
- val |= 0x4;
- write_short_reg(devrec, REG_TXNCON, val);
-
- /* Wait for the device to send the TX complete interrupt. */
- ret = wait_for_completion_interruptible_timeout(
- &devrec->tx_complete,
- 5 * HZ);
- if (ret == -ERESTARTSYS)
- goto err;
- if (ret == 0) {
- dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n");
- ret = -ETIMEDOUT;
- goto err;
- }
-
- /* Check for send error from the device. */
- ret = read_short_reg(devrec, REG_TXSTAT, &val);
- if (ret)
- goto err;
- if (val & 0x1) {
- dev_dbg(printdev(devrec), "Error Sending. Retry count exceeded\n");
- ret = -ECOMM; /* TODO: Better error code ? */
- } else
- dev_dbg(printdev(devrec), "Packet Sent\n");
-
-err:
-
- return ret;
+ return write_tx_buf(devrec, 0x000, skb->data, skb->len);
}
static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
@@ -394,33 +610,23 @@ static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
static int mrf24j40_start(struct ieee802154_hw *hw)
{
struct mrf24j40 *devrec = hw->priv;
- u8 val;
- int ret;
dev_dbg(printdev(devrec), "start\n");
- ret = read_short_reg(devrec, REG_INTCON, &val);
- if (ret)
- return ret;
- val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */
- write_short_reg(devrec, REG_INTCON, val);
-
- return 0;
+ /* Clear TXNIE and RXIE. Enable interrupts */
+ return regmap_update_bits(devrec->regmap_short, REG_INTCON,
+ BIT_TXNIE | BIT_RXIE, 0);
}
static void mrf24j40_stop(struct ieee802154_hw *hw)
{
struct mrf24j40 *devrec = hw->priv;
- u8 val;
- int ret;
dev_dbg(printdev(devrec), "stop\n");
- ret = read_short_reg(devrec, REG_INTCON, &val);
- if (ret)
- return;
- val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
- write_short_reg(devrec, REG_INTCON, val);
+ /* Set TXNIE and RXIE. Disable Interrupts */
+ regmap_update_bits(devrec->regmap_short, REG_INTCON,
+ BIT_TXNIE | BIT_TXNIE, BIT_TXNIE | BIT_TXNIE);
}
static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
@@ -436,21 +642,23 @@ static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
WARN_ON(channel > MRF24J40_CHAN_MAX);
/* Set Channel TODO */
- val = (channel-11) << 4 | 0x03;
- write_long_reg(devrec, REG_RFCON0, val);
+ val = (channel - 11) << RFCON0_CH_SHIFT | RFOPT_RECOMMEND;
+ ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0,
+ RFCON0_CH_MASK, val);
+ if (ret)
+ return ret;
/* RF Reset */
- ret = read_short_reg(devrec, REG_RFCTL, &val);
+ ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST,
+ BIT_RFRST);
if (ret)
return ret;
- val |= 0x04;
- write_short_reg(devrec, REG_RFCTL, val);
- val &= ~0x04;
- write_short_reg(devrec, REG_RFCTL, val);
- udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
+ ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST, 0);
+ if (!ret)
+ udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
- return 0;
+ return ret;
}
static int mrf24j40_filter(struct ieee802154_hw *hw,
@@ -468,8 +676,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
addrl = le16_to_cpu(filt->short_addr) & 0xff;
- write_short_reg(devrec, REG_SADRH, addrh);
- write_short_reg(devrec, REG_SADRL, addrl);
+ regmap_write(devrec->regmap_short, REG_SADRH, addrh);
+ regmap_write(devrec->regmap_short, REG_SADRL, addrl);
dev_dbg(printdev(devrec),
"Set short addr to %04hx\n", filt->short_addr);
}
@@ -480,7 +688,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
memcpy(addr, &filt->ieee_addr, 8);
for (i = 0; i < 8; i++)
- write_short_reg(devrec, REG_EADR0 + i, addr[i]);
+ regmap_write(devrec->regmap_short, REG_EADR0 + i,
+ addr[i]);
#ifdef DEBUG
pr_debug("Set long addr to: ");
@@ -496,8 +705,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
panidl = le16_to_cpu(filt->pan_id) & 0xff;
- write_short_reg(devrec, REG_PANIDH, panidh);
- write_short_reg(devrec, REG_PANIDL, panidl);
+ regmap_write(devrec->regmap_short, REG_PANIDH, panidh);
+ regmap_write(devrec->regmap_short, REG_PANIDL, panidl);
dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
}
@@ -507,14 +716,14 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
u8 val;
int ret;
- ret = read_short_reg(devrec, REG_RXMCR, &val);
- if (ret)
- return ret;
if (filt->pan_coord)
- val |= 0x8;
+ val = BIT_PANCOORD;
else
- val &= ~0x8;
- write_short_reg(devrec, REG_RXMCR, val);
+ val = 0;
+ ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
+ BIT_PANCOORD, val);
+ if (ret)
+ return ret;
/* REG_SLOTTED is maintained as default (unslotted/CSMA-CA).
* REG_ORDER is maintained as default (no beacon/superframe).
@@ -527,168 +736,392 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
return 0;
}
-static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
+static void mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 *devrec)
{
- u8 len = RX_FIFO_SIZE;
- u8 lqi = 0;
- u8 val;
- int ret = 0;
- int ret2;
- struct sk_buff *skb;
+ int ret;
- /* Turn off reception of packets off the air. This prevents the
- * device from overwriting the buffer while we're reading it. */
- ret = read_short_reg(devrec, REG_BBREG1, &val);
+ /* Turn back on reception of packets off the air. */
+ devrec->rx_msg.complete = NULL;
+ devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
+ devrec->rx_buf[1] = 0x00; /* CLR RXDECINV */
+ ret = spi_async(devrec->spi, &devrec->rx_msg);
if (ret)
- goto out;
- val |= 4; /* SET RXDECINV */
- write_short_reg(devrec, REG_BBREG1, val);
+ dev_err(printdev(devrec), "failed to unlock rx buffer\n");
+}
+
+static void mrf24j40_handle_rx_read_buf_complete(void *context)
+{
+ struct mrf24j40 *devrec = context;
+ u8 len = devrec->rx_buf[2];
+ u8 rx_local_buf[RX_FIFO_SIZE];
+ struct sk_buff *skb;
+
+ memcpy(rx_local_buf, devrec->rx_fifo_buf, len);
+ mrf24j40_handle_rx_read_buf_unlock(devrec);
- skb = dev_alloc_skb(len);
+ skb = dev_alloc_skb(IEEE802154_MTU);
if (!skb) {
- ret = -ENOMEM;
- goto out;
+ dev_err(printdev(devrec), "failed to allocate skb\n");
+ return;
}
- ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi);
- if (ret < 0) {
- dev_err(printdev(devrec), "Failure reading RX FIFO\n");
- kfree_skb(skb);
- ret = -EINVAL;
- goto out;
+ memcpy(skb_put(skb, len), rx_local_buf, len);
+ ieee802154_rx_irqsafe(devrec->hw, skb, 0);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", DUMP_PREFIX_OFFSET, 16, 1,
+ rx_local_buf, len, 0);
+ pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
+ devrec->rx_lqi_buf[0], devrec->rx_lqi_buf[1]);
+#endif
+}
+
+static void mrf24j40_handle_rx_read_buf(void *context)
+{
+ struct mrf24j40 *devrec = context;
+ u16 cmd;
+ int ret;
+
+ /* if length is invalid read the full MTU */
+ if (!ieee802154_is_valid_psdu_len(devrec->rx_buf[2]))
+ devrec->rx_buf[2] = IEEE802154_MTU;
+
+ cmd = MRF24J40_READLONG(REG_RX_FIFO + 1);
+ devrec->rx_addr_buf[0] = cmd >> 8 & 0xff;
+ devrec->rx_addr_buf[1] = cmd & 0xff;
+ devrec->rx_fifo_buf_trx.len = devrec->rx_buf[2];
+ ret = spi_async(devrec->spi, &devrec->rx_buf_msg);
+ if (ret) {
+ dev_err(printdev(devrec), "failed to read rx buffer\n");
+ mrf24j40_handle_rx_read_buf_unlock(devrec);
}
+}
- /* Cut off the checksum */
- skb_trim(skb, len-2);
+static void mrf24j40_handle_rx_read_len(void *context)
+{
+ struct mrf24j40 *devrec = context;
+ u16 cmd;
+ int ret;
- /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
- * also from a workqueue). I think irqsafe is not necessary here.
- * Can someone confirm? */
- ieee802154_rx_irqsafe(devrec->hw, skb, lqi);
+ /* read the length of received frame */
+ devrec->rx_msg.complete = mrf24j40_handle_rx_read_buf;
+ devrec->rx_trx.len = 3;
+ cmd = MRF24J40_READLONG(REG_RX_FIFO);
+ devrec->rx_buf[0] = cmd >> 8 & 0xff;
+ devrec->rx_buf[1] = cmd & 0xff;
- dev_dbg(printdev(devrec), "RX Handled\n");
+ ret = spi_async(devrec->spi, &devrec->rx_msg);
+ if (ret) {
+ dev_err(printdev(devrec), "failed to read rx buffer length\n");
+ mrf24j40_handle_rx_read_buf_unlock(devrec);
+ }
+}
-out:
- /* Turn back on reception of packets off the air. */
- ret2 = read_short_reg(devrec, REG_BBREG1, &val);
- if (ret2)
- return ret2;
- val &= ~0x4; /* Clear RXDECINV */
- write_short_reg(devrec, REG_BBREG1, val);
+static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
+{
+ /* Turn off reception of packets off the air. This prevents the
+ * device from overwriting the buffer while we're reading it.
+ */
+ devrec->rx_msg.complete = mrf24j40_handle_rx_read_len;
+ devrec->rx_trx.len = 2;
+ devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
+ devrec->rx_buf[1] = BIT_RXDECINV; /* SET RXDECINV */
+
+ return spi_async(devrec->spi, &devrec->rx_msg);
+}
+
+static int
+mrf24j40_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be,
+ u8 retries)
+{
+ struct mrf24j40 *devrec = hw->priv;
+ u8 val;
+
+ /* min_be */
+ val = min_be << TXMCR_MIN_BE_SHIFT;
+ /* csma backoffs */
+ val |= retries << TXMCR_CSMA_RETRIES_SHIFT;
+
+ return regmap_update_bits(devrec->regmap_short, REG_TXMCR,
+ TXMCR_MIN_BE_MASK | TXMCR_CSMA_RETRIES_MASK,
+ val);
+}
+
+static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw,
+ const struct wpan_phy_cca *cca)
+{
+ struct mrf24j40 *devrec = hw->priv;
+ u8 val;
+
+ /* mapping 802.15.4 to driver spec */
+ switch (cca->mode) {
+ case NL802154_CCA_ENERGY:
+ val = 2;
+ break;
+ case NL802154_CCA_CARRIER:
+ val = 1;
+ break;
+ case NL802154_CCA_ENERGY_CARRIER:
+ switch (cca->opt) {
+ case NL802154_CCA_OPT_ENERGY_CARRIER_AND:
+ val = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(devrec->regmap_short, REG_BBREG2,
+ BBREG2_CCA_MODE_MASK,
+ val << BBREG2_CCA_MODE_SHIFT);
+}
+
+/* array for representing ed levels */
+static const s32 mrf24j40_ed_levels[] = {
+ -9000, -8900, -8800, -8700, -8600, -8500, -8400, -8300, -8200, -8100,
+ -8000, -7900, -7800, -7700, -7600, -7500, -7400, -7300, -7200, -7100,
+ -7000, -6900, -6800, -6700, -6600, -6500, -6400, -6300, -6200, -6100,
+ -6000, -5900, -5800, -5700, -5600, -5500, -5400, -5300, -5200, -5100,
+ -5000, -4900, -4800, -4700, -4600, -4500, -4400, -4300, -4200, -4100,
+ -4000, -3900, -3800, -3700, -3600, -3500
+};
+
+/* map ed levels to register value */
+static const s32 mrf24j40_ed_levels_map[][2] = {
+ { -9000, 0 }, { -8900, 1 }, { -8800, 2 }, { -8700, 5 }, { -8600, 9 },
+ { -8500, 13 }, { -8400, 18 }, { -8300, 23 }, { -8200, 27 },
+ { -8100, 32 }, { -8000, 37 }, { -7900, 43 }, { -7800, 48 },
+ { -7700, 53 }, { -7600, 58 }, { -7500, 63 }, { -7400, 68 },
+ { -7300, 73 }, { -7200, 78 }, { -7100, 83 }, { -7000, 89 },
+ { -6900, 95 }, { -6800, 100 }, { -6700, 107 }, { -6600, 111 },
+ { -6500, 117 }, { -6400, 121 }, { -6300, 125 }, { -6200, 129 },
+ { -6100, 133 }, { -6000, 138 }, { -5900, 143 }, { -5800, 148 },
+ { -5700, 153 }, { -5600, 159 }, { -5500, 165 }, { -5400, 170 },
+ { -5300, 176 }, { -5200, 183 }, { -5100, 188 }, { -5000, 193 },
+ { -4900, 198 }, { -4800, 203 }, { -4700, 207 }, { -4600, 212 },
+ { -4500, 216 }, { -4400, 221 }, { -4300, 225 }, { -4200, 228 },
+ { -4100, 233 }, { -4000, 239 }, { -3900, 245 }, { -3800, 250 },
+ { -3700, 253 }, { -3600, 254 }, { -3500, 255 },
+};
+
+static int mrf24j40_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
+{
+ struct mrf24j40 *devrec = hw->priv;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mrf24j40_ed_levels_map); i++) {
+ if (mrf24j40_ed_levels_map[i][0] == mbm)
+ return regmap_write(devrec->regmap_short, REG_CCAEDTH,
+ mrf24j40_ed_levels_map[i][1]);
+ }
+
+ return -EINVAL;
+}
+
+static const s32 mrf24j40ma_powers[] = {
+ 0, -50, -120, -190, -280, -370, -490, -630, -1000, -1050, -1120, -1190,
+ -1280, -1370, -1490, -1630, -2000, -2050, -2120, -2190, -2280, -2370,
+ -2490, -2630, -3000, -3050, -3120, -3190, -3280, -3370, -3490, -3630,
+};
+
+static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm)
+{
+ struct mrf24j40 *devrec = hw->priv;
+ s32 small_scale;
+ u8 val;
+
+ if (0 >= mbm && mbm > -1000) {
+ val = TXPWRL_0 << TXPWRL_SHIFT;
+ small_scale = mbm;
+ } else if (-1000 >= mbm && mbm > -2000) {
+ val = TXPWRL_10 << TXPWRL_SHIFT;
+ small_scale = mbm + 1000;
+ } else if (-2000 >= mbm && mbm > -3000) {
+ val = TXPWRL_20 << TXPWRL_SHIFT;
+ small_scale = mbm + 2000;
+ } else if (-3000 >= mbm && mbm > -4000) {
+ val = TXPWRL_30 << TXPWRL_SHIFT;
+ small_scale = mbm + 3000;
+ } else {
+ return -EINVAL;
+ }
+
+ switch (small_scale) {
+ case 0:
+ val |= (TXPWRS_0 << TXPWRS_SHIFT);
+ break;
+ case -50:
+ val |= (TXPWRS_0_5 << TXPWRS_SHIFT);
+ break;
+ case -120:
+ val |= (TXPWRS_1_2 << TXPWRS_SHIFT);
+ break;
+ case -190:
+ val |= (TXPWRS_1_9 << TXPWRS_SHIFT);
+ break;
+ case -280:
+ val |= (TXPWRS_2_8 << TXPWRS_SHIFT);
+ break;
+ case -370:
+ val |= (TXPWRS_3_7 << TXPWRS_SHIFT);
+ break;
+ case -490:
+ val |= (TXPWRS_4_9 << TXPWRS_SHIFT);
+ break;
+ case -630:
+ val |= (TXPWRS_6_3 << TXPWRS_SHIFT);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(devrec->regmap_long, REG_RFCON3,
+ TXPWRL_MASK | TXPWRS_MASK, val);
+}
+
+static int mrf24j40_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
+{
+ struct mrf24j40 *devrec = hw->priv;
+ int ret;
+
+ if (on) {
+ /* set PROMI, ERRPKT and NOACKRSP */
+ ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
+ BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP,
+ BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP);
+ } else {
+ /* clear PROMI, ERRPKT and NOACKRSP */
+ ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
+ BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP,
+ 0);
+ }
return ret;
}
static const struct ieee802154_ops mrf24j40_ops = {
.owner = THIS_MODULE,
- .xmit_sync = mrf24j40_tx,
+ .xmit_async = mrf24j40_tx,
.ed = mrf24j40_ed,
.start = mrf24j40_start,
.stop = mrf24j40_stop,
.set_channel = mrf24j40_set_channel,
.set_hw_addr_filt = mrf24j40_filter,
+ .set_csma_params = mrf24j40_csma_params,
+ .set_cca_mode = mrf24j40_set_cca_mode,
+ .set_cca_ed_level = mrf24j40_set_cca_ed_level,
+ .set_txpower = mrf24j40_set_txpower,
+ .set_promiscuous_mode = mrf24j40_set_promiscuous_mode,
};
-static irqreturn_t mrf24j40_isr(int irq, void *data)
+static void mrf24j40_intstat_complete(void *context)
{
- struct mrf24j40 *devrec = data;
- u8 intstat;
- int ret;
+ struct mrf24j40 *devrec = context;
+ u8 intstat = devrec->irq_buf[1];
- /* Read the interrupt status */
- ret = read_short_reg(devrec, REG_INTSTAT, &intstat);
- if (ret)
- goto out;
+ enable_irq(devrec->spi->irq);
/* Check for TX complete */
- if (intstat & 0x1)
- complete(&devrec->tx_complete);
+ if (intstat & BIT_TXNIF)
+ ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false);
/* Check for Rx */
- if (intstat & 0x8)
+ if (intstat & BIT_RXIF)
mrf24j40_handle_rx(devrec);
+}
+
+static irqreturn_t mrf24j40_isr(int irq, void *data)
+{
+ struct mrf24j40 *devrec = data;
+ int ret;
+
+ disable_irq_nosync(irq);
+
+ devrec->irq_buf[0] = MRF24J40_READSHORT(REG_INTSTAT);
+ /* Read the interrupt status */
+ ret = spi_async(devrec->spi, &devrec->irq_msg);
+ if (ret) {
+ enable_irq(irq);
+ return IRQ_NONE;
+ }
-out:
return IRQ_HANDLED;
}
static int mrf24j40_hw_init(struct mrf24j40 *devrec)
{
+ u32 irq_type;
int ret;
- u8 val;
/* Initialize the device.
From datasheet section 3.2: Initialization. */
- ret = write_short_reg(devrec, REG_SOFTRST, 0x07);
+ ret = regmap_write(devrec->regmap_short, REG_SOFTRST, 0x07);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_PACON2, 0x98);
+ ret = regmap_write(devrec->regmap_short, REG_PACON2, 0x98);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_TXSTBL, 0x95);
+ ret = regmap_write(devrec->regmap_short, REG_TXSTBL, 0x95);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_RFCON0, 0x03);
+ ret = regmap_write(devrec->regmap_long, REG_RFCON0, 0x03);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_RFCON1, 0x01);
+ ret = regmap_write(devrec->regmap_long, REG_RFCON1, 0x01);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_RFCON2, 0x80);
+ ret = regmap_write(devrec->regmap_long, REG_RFCON2, 0x80);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_RFCON6, 0x90);
+ ret = regmap_write(devrec->regmap_long, REG_RFCON6, 0x90);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_RFCON7, 0x80);
+ ret = regmap_write(devrec->regmap_long, REG_RFCON7, 0x80);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_RFCON8, 0x10);
+ ret = regmap_write(devrec->regmap_long, REG_RFCON8, 0x10);
if (ret)
goto err_ret;
- ret = write_long_reg(devrec, REG_SLPCON1, 0x21);
+ ret = regmap_write(devrec->regmap_long, REG_SLPCON1, 0x21);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_BBREG2, 0x80);
+ ret = regmap_write(devrec->regmap_short, REG_BBREG2, 0x80);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_CCAEDTH, 0x60);
+ ret = regmap_write(devrec->regmap_short, REG_CCAEDTH, 0x60);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_BBREG6, 0x40);
+ ret = regmap_write(devrec->regmap_short, REG_BBREG6, 0x40);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_RFCTL, 0x04);
+ ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x04);
if (ret)
goto err_ret;
- ret = write_short_reg(devrec, REG_RFCTL, 0x0);
+ ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x0);
if (ret)
goto err_ret;
udelay(192);
/* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
- ret = read_short_reg(devrec, REG_RXMCR, &val);
- if (ret)
- goto err_ret;
-
- val &= ~0x3; /* Clear RX mode (normal) */
-
- ret = write_short_reg(devrec, REG_RXMCR, val);
+ ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x03, 0x00);
if (ret)
goto err_ret;
@@ -696,22 +1129,39 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec)
/* Enable external amplifier.
* From MRF24J40MC datasheet section 1.3: Operation.
*/
- read_long_reg(devrec, REG_TESTMODE, &val);
- val |= 0x7; /* Configure GPIO 0-2 to control amplifier */
- write_long_reg(devrec, REG_TESTMODE, val);
+ regmap_update_bits(devrec->regmap_long, REG_TESTMODE, 0x07,
+ 0x07);
- read_short_reg(devrec, REG_TRISGPIO, &val);
- val |= 0x8; /* Set GPIO3 as output. */
- write_short_reg(devrec, REG_TRISGPIO, val);
+ /* Set GPIO3 as output. */
+ regmap_update_bits(devrec->regmap_short, REG_TRISGPIO, 0x08,
+ 0x08);
- read_short_reg(devrec, REG_GPIO, &val);
- val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */
- write_short_reg(devrec, REG_GPIO, val);
+ /* Set GPIO3 HIGH to enable U5 voltage regulator */
+ regmap_update_bits(devrec->regmap_short, REG_GPIO, 0x08, 0x08);
/* Reduce TX pwr to meet FCC requirements.
* From MRF24J40MC datasheet section 3.1.1
*/
- write_long_reg(devrec, REG_RFCON3, 0x28);
+ regmap_write(devrec->regmap_long, REG_RFCON3, 0x28);
+ }
+
+ irq_type = irq_get_trigger_type(devrec->spi->irq);
+ if (irq_type == IRQ_TYPE_EDGE_RISING ||
+ irq_type == IRQ_TYPE_EDGE_FALLING)
+ dev_warn(&devrec->spi->dev,
+ "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n");
+ switch (irq_type) {
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_LEVEL_HIGH:
+ /* set interrupt polarity to rising */
+ ret = regmap_update_bits(devrec->regmap_long, REG_SLPCON0,
+ BIT_INTEDGE, BIT_INTEDGE);
+ if (ret)
+ goto err_ret;
+ break;
+ default:
+ /* default is falling edge */
+ break;
}
return 0;
@@ -720,67 +1170,178 @@ err_ret:
return ret;
}
-static int mrf24j40_probe(struct spi_device *spi)
+static void
+mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec)
{
- int ret = -ENOMEM;
- struct mrf24j40 *devrec;
+ spi_message_init(&devrec->tx_msg);
+ devrec->tx_msg.context = devrec;
+ devrec->tx_msg.complete = write_tx_buf_complete;
+ devrec->tx_hdr_trx.len = 2;
+ devrec->tx_hdr_trx.tx_buf = devrec->tx_hdr_buf;
+ spi_message_add_tail(&devrec->tx_hdr_trx, &devrec->tx_msg);
+ devrec->tx_len_trx.len = 2;
+ devrec->tx_len_trx.tx_buf = devrec->tx_len_buf;
+ spi_message_add_tail(&devrec->tx_len_trx, &devrec->tx_msg);
+ spi_message_add_tail(&devrec->tx_buf_trx, &devrec->tx_msg);
+
+ spi_message_init(&devrec->tx_post_msg);
+ devrec->tx_post_msg.context = devrec;
+ devrec->tx_post_trx.len = 2;
+ devrec->tx_post_trx.tx_buf = devrec->tx_post_buf;
+ spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg);
+}
- dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
+static void
+mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec)
+{
+ spi_message_init(&devrec->rx_msg);
+ devrec->rx_msg.context = devrec;
+ devrec->rx_trx.len = 2;
+ devrec->rx_trx.tx_buf = devrec->rx_buf;
+ devrec->rx_trx.rx_buf = devrec->rx_buf;
+ spi_message_add_tail(&devrec->rx_trx, &devrec->rx_msg);
+
+ spi_message_init(&devrec->rx_buf_msg);
+ devrec->rx_buf_msg.context = devrec;
+ devrec->rx_buf_msg.complete = mrf24j40_handle_rx_read_buf_complete;
+ devrec->rx_addr_trx.len = 2;
+ devrec->rx_addr_trx.tx_buf = devrec->rx_addr_buf;
+ spi_message_add_tail(&devrec->rx_addr_trx, &devrec->rx_buf_msg);
+ devrec->rx_fifo_buf_trx.rx_buf = devrec->rx_fifo_buf;
+ spi_message_add_tail(&devrec->rx_fifo_buf_trx, &devrec->rx_buf_msg);
+ devrec->rx_lqi_trx.len = 2;
+ devrec->rx_lqi_trx.rx_buf = devrec->rx_lqi_buf;
+ spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg);
+}
- devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL);
- if (!devrec)
- goto err_ret;
- devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL);
- if (!devrec->buf)
- goto err_ret;
+static void
+mrf24j40_setup_irq_spi_messages(struct mrf24j40 *devrec)
+{
+ spi_message_init(&devrec->irq_msg);
+ devrec->irq_msg.context = devrec;
+ devrec->irq_msg.complete = mrf24j40_intstat_complete;
+ devrec->irq_trx.len = 2;
+ devrec->irq_trx.tx_buf = devrec->irq_buf;
+ devrec->irq_trx.rx_buf = devrec->irq_buf;
+ spi_message_add_tail(&devrec->irq_trx, &devrec->irq_msg);
+}
+
+static void mrf24j40_phy_setup(struct mrf24j40 *devrec)
+{
+ ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr);
+ devrec->hw->phy->current_channel = 11;
+
+ /* mrf24j40 supports max_minbe 0 - 3 */
+ devrec->hw->phy->supported.max_minbe = 3;
+ /* datasheet doesn't say anything about max_be, but we have min_be
+ * So we assume the max_be default.
+ */
+ devrec->hw->phy->supported.min_maxbe = 5;
+ devrec->hw->phy->supported.max_maxbe = 5;
+
+ devrec->hw->phy->cca.mode = NL802154_CCA_CARRIER;
+ devrec->hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) |
+ BIT(NL802154_CCA_CARRIER) |
+ BIT(NL802154_CCA_ENERGY_CARRIER);
+ devrec->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND);
+
+ devrec->hw->phy->cca_ed_level = -6900;
+ devrec->hw->phy->supported.cca_ed_levels = mrf24j40_ed_levels;
+ devrec->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(mrf24j40_ed_levels);
+
+ switch (spi_get_device_id(devrec->spi)->driver_data) {
+ case MRF24J40:
+ case MRF24J40MA:
+ devrec->hw->phy->supported.tx_powers = mrf24j40ma_powers;
+ devrec->hw->phy->supported.tx_powers_size = ARRAY_SIZE(mrf24j40ma_powers);
+ devrec->hw->phy->flags |= WPAN_PHY_FLAG_TXPOWER;
+ break;
+ default:
+ break;
+ }
+}
- spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
- if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
- spi->max_speed_hz = MAX_SPI_SPEED_HZ;
+static int mrf24j40_probe(struct spi_device *spi)
+{
+ int ret = -ENOMEM, irq_type;
+ struct ieee802154_hw *hw;
+ struct mrf24j40 *devrec;
- mutex_init(&devrec->buffer_mutex);
- init_completion(&devrec->tx_complete);
- devrec->spi = spi;
- spi_set_drvdata(spi, devrec);
+ dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
/* Register with the 802154 subsystem */
- devrec->hw = ieee802154_alloc_hw(0, &mrf24j40_ops);
- if (!devrec->hw)
+ hw = ieee802154_alloc_hw(sizeof(*devrec), &mrf24j40_ops);
+ if (!hw)
goto err_ret;
- devrec->hw->priv = devrec;
- devrec->hw->parent = &devrec->spi->dev;
+ devrec = hw->priv;
+ devrec->spi = spi;
+ spi_set_drvdata(spi, devrec);
+ devrec->hw = hw;
+ devrec->hw->parent = &spi->dev;
devrec->hw->phy->supported.channels[0] = CHANNEL_MASK;
- devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT;
+ devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
+ IEEE802154_HW_CSMA_PARAMS |
+ IEEE802154_HW_PROMISCUOUS;
+
+ devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE |
+ WPAN_PHY_FLAG_CCA_ED_LEVEL;
+
+ mrf24j40_setup_tx_spi_messages(devrec);
+ mrf24j40_setup_rx_spi_messages(devrec);
+ mrf24j40_setup_irq_spi_messages(devrec);
+
+ devrec->regmap_short = devm_regmap_init_spi(spi,
+ &mrf24j40_short_regmap);
+ if (IS_ERR(devrec->regmap_short)) {
+ ret = PTR_ERR(devrec->regmap_short);
+ dev_err(&spi->dev, "Failed to allocate short register map: %d\n",
+ ret);
+ goto err_register_device;
+ }
- dev_dbg(printdev(devrec), "registered mrf24j40\n");
- ret = ieee802154_register_hw(devrec->hw);
- if (ret)
+ devrec->regmap_long = devm_regmap_init(&spi->dev,
+ &mrf24j40_long_regmap_bus,
+ spi, &mrf24j40_long_regmap);
+ if (IS_ERR(devrec->regmap_long)) {
+ ret = PTR_ERR(devrec->regmap_long);
+ dev_err(&spi->dev, "Failed to allocate long register map: %d\n",
+ ret);
goto err_register_device;
+ }
+
+ if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) {
+ dev_warn(&spi->dev, "spi clock above possible maximum: %d",
+ MAX_SPI_SPEED_HZ);
+ return -EINVAL;
+ }
ret = mrf24j40_hw_init(devrec);
if (ret)
- goto err_hw_init;
+ goto err_register_device;
- ret = devm_request_threaded_irq(&spi->dev,
- spi->irq,
- NULL,
- mrf24j40_isr,
- IRQF_TRIGGER_LOW|IRQF_ONESHOT,
- dev_name(&spi->dev),
- devrec);
+ mrf24j40_phy_setup(devrec);
+ /* request IRQF_TRIGGER_LOW as fallback default */
+ irq_type = irq_get_trigger_type(spi->irq);
+ if (!irq_type)
+ irq_type = IRQF_TRIGGER_LOW;
+
+ ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr,
+ irq_type, dev_name(&spi->dev), devrec);
if (ret) {
dev_err(printdev(devrec), "Unable to get IRQ");
- goto err_irq;
+ goto err_register_device;
}
+ dev_dbg(printdev(devrec), "registered mrf24j40\n");
+ ret = ieee802154_register_hw(devrec->hw);
+ if (ret)
+ goto err_register_device;
+
return 0;
-err_irq:
-err_hw_init:
- ieee802154_unregister_hw(devrec->hw);
err_register_device:
ieee802154_free_hw(devrec->hw);
err_ret:
@@ -801,6 +1362,14 @@ static int mrf24j40_remove(struct spi_device *spi)
return 0;
}
+static const struct of_device_id mrf24j40_of_match[] = {
+ { .compatible = "microchip,mrf24j40", .data = (void *)MRF24J40 },
+ { .compatible = "microchip,mrf24j40ma", .data = (void *)MRF24J40MA },
+ { .compatible = "microchip,mrf24j40mc", .data = (void *)MRF24J40MC },
+ { },
+};
+MODULE_DEVICE_TABLE(of, mrf24j40_of_match);
+
static const struct spi_device_id mrf24j40_ids[] = {
{ "mrf24j40", MRF24J40 },
{ "mrf24j40ma", MRF24J40MA },
@@ -811,8 +1380,8 @@ MODULE_DEVICE_TABLE(spi, mrf24j40_ids);
static struct spi_driver mrf24j40_driver = {
.driver = {
+ .of_match_table = of_match_ptr(mrf24j40_of_match),
.name = "mrf24j40",
- .owner = THIS_MODULE,
},
.id_table = mrf24j40_ids,
.probe = mrf24j40_probe,
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 207f62e8de9a..8c48bb2a94ea 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -254,7 +254,7 @@ acct:
}
}
-static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
+static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,
bool local)
{
struct ipvl_dev *ipvlan = addr->master;
@@ -262,6 +262,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
unsigned int len;
rx_handler_result_t ret = RX_HANDLER_CONSUMED;
bool success = false;
+ struct sk_buff *skb = *pskb;
len = skb->len + ETH_HLEN;
if (unlikely(!(dev->flags & IFF_UP))) {
@@ -273,6 +274,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
if (!skb)
goto out;
+ *pskb = skb;
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
@@ -344,17 +346,18 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
{
const struct iphdr *ip4h = ip_hdr(skb);
struct net_device *dev = skb->dev;
+ struct net *net = dev_net(dev);
struct rtable *rt;
int err, ret = NET_XMIT_DROP;
struct flowi4 fl4 = {
- .flowi4_oif = dev_get_iflink(dev),
+ .flowi4_oif = dev->ifindex,
.flowi4_tos = RT_TOS(ip4h->tos),
.flowi4_flags = FLOWI_FLAG_ANYSRC,
.daddr = ip4h->daddr,
.saddr = ip4h->saddr,
};
- rt = ip_route_output_flow(dev_net(dev), &fl4, NULL);
+ rt = ip_route_output_flow(net, &fl4, NULL);
if (IS_ERR(rt))
goto err;
@@ -364,7 +367,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
}
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
- err = ip_local_out(skb);
+ err = ip_local_out(net, skb->sk, skb);
if (unlikely(net_xmit_eval(err)))
dev->stats.tx_errors++;
else
@@ -381,10 +384,11 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
struct net_device *dev = skb->dev;
+ struct net *net = dev_net(dev);
struct dst_entry *dst;
int err, ret = NET_XMIT_DROP;
struct flowi6 fl6 = {
- .flowi6_iif = skb->dev->ifindex,
+ .flowi6_iif = dev->ifindex,
.daddr = ip6h->daddr,
.saddr = ip6h->saddr,
.flowi6_flags = FLOWI_FLAG_ANYSRC,
@@ -393,7 +397,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
.flowi6_proto = ip6h->nexthdr,
};
- dst = ip6_route_output(dev_net(dev), NULL, &fl6);
+ dst = ip6_route_output(net, NULL, &fl6);
if (dst->error) {
ret = dst->error;
dst_release(dst);
@@ -401,7 +405,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
}
skb_dst_drop(skb);
skb_dst_set(skb, dst);
- err = ip6_local_out(skb);
+ err = ip6_local_out(net, skb->sk, skb);
if (unlikely(net_xmit_eval(err)))
dev->stats.tx_errors++;
else
@@ -484,7 +488,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
if (addr)
- return ipvlan_rcv_frame(addr, skb, true);
+ return ipvlan_rcv_frame(addr, &skb, true);
out:
skb->dev = ipvlan->phy_dev;
@@ -504,7 +508,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
if (lyr3h) {
addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
if (addr)
- return ipvlan_rcv_frame(addr, skb, true);
+ return ipvlan_rcv_frame(addr, &skb, true);
}
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
@@ -587,7 +591,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
if (addr)
- ret = ipvlan_rcv_frame(addr, skb, false);
+ ret = ipvlan_rcv_frame(addr, pskb, false);
out:
return ret;
@@ -624,7 +628,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
if (addr)
- ret = ipvlan_rcv_frame(addr, skb, false);
+ ret = ipvlan_rcv_frame(addr, pskb, false);
}
return ret;
@@ -649,5 +653,5 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
WARN_ONCE(true, "ipvlan_handle_frame() called for mode = [%hx]\n",
port->mode);
kfree_skb(skb);
- return NET_RX_DROP;
+ return RX_HANDLER_CONSUMED;
}
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 100454662e4b..6e8f616be48e 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -19,6 +19,9 @@
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/pxa-dma.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -27,18 +30,17 @@
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
-#include <mach/dma.h>
#include <linux/platform_data/irda-pxaficp.h>
-#include <mach/regs-ost.h>
+#undef __REG
+#define __REG(x) ((x) & 0xffff)
#include <mach/regs-uart.h>
-#define FICP __REG(0x40800000) /* Start of FICP area */
-#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */
-#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */
-#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */
-#define ICDR __REG(0x4080000c) /* ICP Data Register */
-#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */
-#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */
+#define ICCR0 0x0000 /* ICP Control Register 0 */
+#define ICCR1 0x0004 /* ICP Control Register 1 */
+#define ICCR2 0x0008 /* ICP Control Register 2 */
+#define ICDR 0x000c /* ICP Data Register */
+#define ICSR0 0x0014 /* ICP Status Register 0 */
+#define ICSR1 0x0018 /* ICP Status Register 1 */
#define ICCR0_AME (1 << 7) /* Address match enable */
#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */
@@ -56,9 +58,7 @@
#define ICCR2_TRIG_16 (1 << 0) /* >= 16 bytes */
#define ICCR2_TRIG_32 (2 << 0) /* >= 32 bytes */
-#ifdef CONFIG_PXA27x
#define ICSR0_EOC (1 << 6) /* DMA End of Descriptor Chain */
-#endif
#define ICSR0_FRE (1 << 5) /* Framing error */
#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */
#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */
@@ -99,18 +99,61 @@
IrSR_RCVEIR_UART_MODE | \
IrSR_XMITIR_IR_MODE)
+/* macros for registers read/write */
+#define ficp_writel(irda, val, off) \
+ do { \
+ dev_vdbg(irda->dev, \
+ "%s():%d ficp_writel(0x%x, %s)\n", \
+ __func__, __LINE__, (val), #off); \
+ writel_relaxed((val), (irda)->irda_base + (off)); \
+ } while (0)
+
+#define ficp_readl(irda, off) \
+ ({ \
+ unsigned int _v; \
+ _v = readl_relaxed((irda)->irda_base + (off)); \
+ dev_vdbg(irda->dev, \
+ "%s():%d ficp_readl(%s): 0x%x\n", \
+ __func__, __LINE__, #off, _v); \
+ _v; \
+ })
+
+#define stuart_writel(irda, val, off) \
+ do { \
+ dev_vdbg(irda->dev, \
+ "%s():%d stuart_writel(0x%x, %s)\n", \
+ __func__, __LINE__, (val), #off); \
+ writel_relaxed((val), (irda)->stuart_base + (off)); \
+ } while (0)
+
+#define stuart_readl(irda, off) \
+ ({ \
+ unsigned int _v; \
+ _v = readl_relaxed((irda)->stuart_base + (off)); \
+ dev_vdbg(irda->dev, \
+ "%s():%d stuart_readl(%s): 0x%x\n", \
+ __func__, __LINE__, #off, _v); \
+ _v; \
+ })
+
struct pxa_irda {
int speed;
int newspeed;
- unsigned long last_oscr;
+ unsigned long long last_clk;
+ void __iomem *stuart_base;
+ void __iomem *irda_base;
unsigned char *dma_rx_buff;
unsigned char *dma_tx_buff;
dma_addr_t dma_rx_buff_phy;
dma_addr_t dma_tx_buff_phy;
unsigned int dma_tx_buff_len;
- int txdma;
- int rxdma;
+ struct dma_chan *txdma;
+ struct dma_chan *rxdma;
+ dma_cookie_t rx_cookie;
+ dma_cookie_t tx_cookie;
+ int drcmr_rx;
+ int drcmr_tx;
int uart_irq;
int icp_irq;
@@ -128,6 +171,8 @@ struct pxa_irda {
struct clk *cur_clk;
};
+static int pxa_irda_set_speed(struct pxa_irda *si, int speed);
+
static inline void pxa_irda_disable_clk(struct pxa_irda *si)
{
if (si->cur_clk)
@@ -151,22 +196,41 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)
#define IS_FIR(si) ((si)->speed >= 4000000)
#define IRDA_FRAME_SIZE_LIMIT 2047
+static void pxa_irda_fir_dma_rx_irq(void *data);
+static void pxa_irda_fir_dma_tx_irq(void *data);
+
inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si)
{
- DCSR(si->rxdma) = DCSR_NODESC;
- DSADR(si->rxdma) = __PREG(ICDR);
- DTADR(si->rxdma) = si->dma_rx_buff_phy;
- DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT;
- DCSR(si->rxdma) |= DCSR_RUN;
+ struct dma_async_tx_descriptor *tx;
+
+ tx = dmaengine_prep_slave_single(si->rxdma, si->dma_rx_buff_phy,
+ IRDA_FRAME_SIZE_LIMIT, DMA_FROM_DEVICE,
+ DMA_PREP_INTERRUPT);
+ if (!tx) {
+ dev_err(si->dev, "prep_slave_sg() failed\n");
+ return;
+ }
+ tx->callback = pxa_irda_fir_dma_rx_irq;
+ tx->callback_param = si;
+ si->rx_cookie = dmaengine_submit(tx);
+ dma_async_issue_pending(si->rxdma);
}
inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si)
{
- DCSR(si->txdma) = DCSR_NODESC;
- DSADR(si->txdma) = si->dma_tx_buff_phy;
- DTADR(si->txdma) = __PREG(ICDR);
- DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len;
- DCSR(si->txdma) |= DCSR_RUN;
+ struct dma_async_tx_descriptor *tx;
+
+ tx = dmaengine_prep_slave_single(si->txdma, si->dma_tx_buff_phy,
+ si->dma_tx_buff_len, DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT);
+ if (!tx) {
+ dev_err(si->dev, "prep_slave_sg() failed\n");
+ return;
+ }
+ tx->callback = pxa_irda_fir_dma_tx_irq;
+ tx->callback_param = si;
+ si->tx_cookie = dmaengine_submit(tx);
+ dma_async_issue_pending(si->rxdma);
}
/*
@@ -205,9 +269,9 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
if (IS_FIR(si)) {
/* stop RX DMA */
- DCSR(si->rxdma) &= ~DCSR_RUN;
+ dmaengine_terminate_all(si->rxdma);
/* disable FICP */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
pxa_irda_disable_clk(si);
/* set board transceiver to SIR mode */
@@ -218,17 +282,19 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
}
/* disable STUART first */
- STIER = 0;
+ stuart_writel(si, 0, STIER);
/* access DLL & DLH */
- STLCR |= LCR_DLAB;
- STDLL = divisor & 0xff;
- STDLH = divisor >> 8;
- STLCR &= ~LCR_DLAB;
+ stuart_writel(si, stuart_readl(si, STLCR) | LCR_DLAB, STLCR);
+ stuart_writel(si, divisor & 0xff, STDLL);
+ stuart_writel(si, divisor >> 8, STDLH);
+ stuart_writel(si, stuart_readl(si, STLCR) & ~LCR_DLAB, STLCR);
si->speed = speed;
- STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
- STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+ stuart_writel(si, IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6,
+ STISR);
+ stuart_writel(si, IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE,
+ STIER);
local_irq_restore(flags);
break;
@@ -237,12 +303,12 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
local_irq_save(flags);
/* disable STUART */
- STIER = 0;
- STISR = 0;
+ stuart_writel(si, 0, STIER);
+ stuart_writel(si, 0, STISR);
pxa_irda_disable_clk(si);
/* disable FICP first */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
/* set board transceiver to FIR mode */
pxa_irda_set_mode(si, IR_FIRMODE);
@@ -252,7 +318,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
si->speed = speed;
pxa_irda_fir_dma_rx_start(si);
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0);
local_irq_restore(flags);
break;
@@ -271,13 +337,13 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
struct pxa_irda *si = netdev_priv(dev);
int iir, lsr, data;
- iir = STIIR;
+ iir = stuart_readl(si, STIIR);
switch (iir & 0x0F) {
case 0x06: /* Receiver Line Status */
- lsr = STLSR;
+ lsr = stuart_readl(si, STLSR);
while (lsr & LSR_FIFOE) {
- data = STRBR;
+ data = stuart_readl(si, STRBR);
if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
dev->stats.rx_errors++;
@@ -290,9 +356,9 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
async_unwrap_char(dev, &dev->stats,
&si->rx_buff, data);
}
- lsr = STLSR;
+ lsr = stuart_readl(si, STLSR);
}
- si->last_oscr = readl_relaxed(OSCR);
+ si->last_clk = sched_clock();
break;
case 0x04: /* Received Data Available */
@@ -301,14 +367,16 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
case 0x0C: /* Character Timeout Indication */
do {
dev->stats.rx_bytes++;
- async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR);
- } while (STLSR & LSR_DR);
- si->last_oscr = readl_relaxed(OSCR);
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff,
+ stuart_readl(si, STRBR));
+ } while (stuart_readl(si, STLSR) & LSR_DR);
+ si->last_clk = sched_clock();
break;
case 0x02: /* Transmit FIFO Data Request */
- while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
- STTHR = *si->tx_buff.data++;
+ while ((si->tx_buff.len) &&
+ (stuart_readl(si, STLSR) & LSR_TDRQ)) {
+ stuart_writel(si, *si->tx_buff.data++, STTHR);
si->tx_buff.len -= 1;
}
@@ -317,9 +385,9 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head;
/* We need to ensure that the transmitter has finished. */
- while ((STLSR & LSR_TEMT) == 0)
+ while ((stuart_readl(si, STLSR) & LSR_TEMT) == 0)
cpu_relax();
- si->last_oscr = readl_relaxed(OSCR);
+ si->last_clk = sched_clock();
/*
* Ok, we've finished transmitting. Now enable
@@ -331,9 +399,11 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
si->newspeed = 0;
} else {
/* enable IR Receiver, disable IR Transmitter */
- STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+ stuart_writel(si, IrSR_IR_RECEIVE_ON |
+ IrSR_XMODE_PULSE_1_6, STISR);
/* enable STUART and receive interrupts */
- STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+ stuart_writel(si, IER_UUE | IER_RLSE |
+ IER_RAVIE | IER_RTIOE, STIER);
}
/* I'm hungry! */
netif_wake_queue(dev);
@@ -345,35 +415,32 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
}
/* FIR Receive DMA interrupt handler */
-static void pxa_irda_fir_dma_rx_irq(int channel, void *data)
+static void pxa_irda_fir_dma_rx_irq(void *data)
{
- int dcsr = DCSR(channel);
-
- DCSR(channel) = dcsr & ~DCSR_RUN;
+ struct net_device *dev = data;
+ struct pxa_irda *si = netdev_priv(dev);
- printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr);
+ dmaengine_terminate_all(si->rxdma);
+ netdev_dbg(dev, "pxa_ir: fir rx dma bus error\n");
}
/* FIR Transmit DMA interrupt handler */
-static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
+static void pxa_irda_fir_dma_tx_irq(void *data)
{
struct net_device *dev = data;
struct pxa_irda *si = netdev_priv(dev);
- int dcsr;
-
- dcsr = DCSR(channel);
- DCSR(channel) = dcsr & ~DCSR_RUN;
- if (dcsr & DCSR_ENDINTR) {
+ dmaengine_terminate_all(si->txdma);
+ if (dmaengine_tx_status(si->txdma, si->tx_cookie, NULL) == DMA_ERROR) {
+ dev->stats.tx_errors++;
+ } else {
dev->stats.tx_packets++;
dev->stats.tx_bytes += si->dma_tx_buff_len;
- } else {
- dev->stats.tx_errors++;
}
- while (ICSR1 & ICSR1_TBY)
+ while (ficp_readl(si, ICSR1) & ICSR1_TBY)
cpu_relax();
- si->last_oscr = readl_relaxed(OSCR);
+ si->last_clk = sched_clock();
/*
* HACK: It looks like the TBY bit is dropped too soon.
@@ -387,11 +454,11 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
} else {
int i = 64;
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_rx_start(si);
- while ((ICSR1 & ICSR1_RNE) && i--)
- (void)ICDR;
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--)
+ ficp_readl(si, ICDR);
+ ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0);
if (i < 0)
printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
@@ -403,15 +470,18 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0)
{
unsigned int len, stat, data;
+ struct dma_tx_state state;
/* Get the current data position. */
- len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
+
+ dmaengine_tx_status(si->rxdma, si->rx_cookie, &state);
+ len = IRDA_FRAME_SIZE_LIMIT - state.residue;
do {
/* Read Status, and then Data. */
- stat = ICSR1;
+ stat = ficp_readl(si, ICSR1);
rmb();
- data = ICDR;
+ data = ficp_readl(si, ICDR);
if (stat & (ICSR1_CRE | ICSR1_ROR)) {
dev->stats.rx_errors++;
@@ -429,7 +499,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in
/* If we hit the end of frame, there's no point in continuing. */
if (stat & ICSR1_EOF)
break;
- } while (ICSR0 & ICSR0_EIF);
+ } while (ficp_readl(si, ICSR0) & ICSR0_EIF);
if (stat & ICSR1_EOF) {
/* end of frame. */
@@ -472,9 +542,9 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
int icsr0, i = 64;
/* stop RX DMA */
- DCSR(si->rxdma) &= ~DCSR_RUN;
- si->last_oscr = readl_relaxed(OSCR);
- icsr0 = ICSR0;
+ dmaengine_terminate_all(si->rxdma);
+ si->last_clk = sched_clock();
+ icsr0 = ficp_readl(si, ICSR0);
if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
if (icsr0 & ICSR0_FRE) {
@@ -484,7 +554,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
dev->stats.rx_errors++;
}
- ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
+ ficp_writel(si, icsr0 & (ICSR0_FRE | ICSR0_RAB), ICSR0);
}
if (icsr0 & ICSR0_EIF) {
@@ -492,11 +562,11 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
pxa_irda_fir_irq_eif(si, dev, icsr0);
}
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_rx_start(si);
- while ((ICSR1 & ICSR1_RNE) && i--)
- (void)ICDR;
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--)
+ ficp_readl(si, ICDR);
+ ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0);
if (i < 0)
printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
@@ -537,11 +607,12 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
/* Disable STUART interrupts and switch to transmit mode. */
- STIER = 0;
- STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;
+ stuart_writel(si, 0, STIER);
+ stuart_writel(si, IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6,
+ STISR);
/* enable STUART and transmit interrupts */
- STIER = IER_UUE | IER_TIE;
+ stuart_writel(si, IER_UUE | IER_TIE, STIER);
} else {
unsigned long mtt = irda_get_mtt(skb);
@@ -549,15 +620,15 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len);
if (mtt)
- while ((unsigned)(readl_relaxed(OSCR) - si->last_oscr)/4 < mtt)
+ while ((sched_clock() - si->last_clk) * 1000 < mtt)
cpu_relax();
/* stop RX DMA, disable FICP */
- DCSR(si->rxdma) &= ~DCSR_RUN;
- ICCR0 = 0;
+ dmaengine_terminate_all(si->rxdma);
+ ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_tx_start(si);
- ICCR0 = ICCR0_ITR | ICCR0_TXE;
+ ficp_writel(si, ICCR0_ITR | ICCR0_TXE, ICCR0);
}
dev_kfree_skb(skb);
@@ -613,22 +684,18 @@ static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
static void pxa_irda_startup(struct pxa_irda *si)
{
/* Disable STUART interrupts */
- STIER = 0;
+ stuart_writel(si, 0, STIER);
/* enable STUART interrupt to the processor */
- STMCR = MCR_OUT2;
+ stuart_writel(si, MCR_OUT2, STMCR);
/* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */
- STLCR = LCR_WLS0 | LCR_WLS1;
+ stuart_writel(si, LCR_WLS0 | LCR_WLS1, STLCR);
/* enable FIFO, we use FIFO to improve performance */
- STFCR = FCR_TRFIFOE | FCR_ITL_32;
+ stuart_writel(si, FCR_TRFIFOE | FCR_ITL_32, STFCR);
/* disable FICP */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
/* configure FICP ICCR2 */
- ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
-
- /* configure DMAC */
- DRCMR(17) = si->rxdma | DRCMR_MAPVLD;
- DRCMR(18) = si->txdma | DRCMR_MAPVLD;
+ ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2);
/* force SIR reinitialization */
si->speed = 4000000;
@@ -644,22 +711,19 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
local_irq_save(flags);
/* disable STUART and interrupt */
- STIER = 0;
+ stuart_writel(si, 0, STIER);
/* disable STUART SIR mode */
- STISR = 0;
+ stuart_writel(si, 0, STISR);
/* disable DMA */
- DCSR(si->txdma) &= ~DCSR_RUN;
- DCSR(si->rxdma) &= ~DCSR_RUN;
+ dmaengine_terminate_all(si->rxdma);
+ dmaengine_terminate_all(si->txdma);
/* disable FICP */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
/* disable the STUART or FICP clocks */
pxa_irda_disable_clk(si);
- DRCMR(17) = 0;
- DRCMR(18) = 0;
-
local_irq_restore(flags);
/* power off board transceiver */
@@ -671,6 +735,9 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
static int pxa_irda_start(struct net_device *dev)
{
struct pxa_irda *si = netdev_priv(dev);
+ dma_cap_mask_t mask;
+ struct dma_slave_config config;
+ struct pxad_param param;
int err;
si->speed = 9600;
@@ -690,14 +757,37 @@ static int pxa_irda_start(struct net_device *dev)
disable_irq(si->icp_irq);
err = -EBUSY;
- si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
- if (si->rxdma < 0)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ param.prio = PXAD_PRIO_LOWEST;
+
+ memset(&config, 0, sizeof(config));
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ config.src_addr = (dma_addr_t)si->irda_base + ICDR;
+ config.dst_addr = (dma_addr_t)si->irda_base + ICDR;
+ config.src_maxburst = 32;
+ config.dst_maxburst = 32;
+
+ param.drcmr = si->drcmr_rx;
+ si->rxdma = dma_request_slave_channel_compat(mask, pxad_filter_fn,
+ &param, &dev->dev, "rx");
+ if (!si->rxdma)
goto err_rx_dma;
- si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
- if (si->txdma < 0)
+ param.drcmr = si->drcmr_tx;
+ si->txdma = dma_request_slave_channel_compat(mask, pxad_filter_fn,
+ &param, &dev->dev, "tx");
+ if (!si->txdma)
goto err_tx_dma;
+ err = dmaengine_slave_config(si->rxdma, &config);
+ if (err)
+ goto err_dma_rx_buff;
+ err = dmaengine_slave_config(si->txdma, &config);
+ if (err)
+ goto err_dma_rx_buff;
+
err = -ENOMEM;
si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
&si->dma_rx_buff_phy, GFP_KERNEL);
@@ -737,9 +827,9 @@ err_irlap:
err_dma_tx_buff:
dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
err_dma_rx_buff:
- pxa_free_dma(si->txdma);
+ dma_release_channel(si->txdma);
err_tx_dma:
- pxa_free_dma(si->rxdma);
+ dma_release_channel(si->rxdma);
err_rx_dma:
free_irq(si->icp_irq, dev);
err_irq2:
@@ -766,8 +856,10 @@ static int pxa_irda_stop(struct net_device *dev)
free_irq(si->uart_irq, dev);
free_irq(si->icp_irq, dev);
- pxa_free_dma(si->rxdma);
- pxa_free_dma(si->txdma);
+ dmaengine_terminate_all(si->rxdma);
+ dmaengine_terminate_all(si->txdma);
+ dma_release_channel(si->rxdma);
+ dma_release_channel(si->txdma);
if (si->dma_rx_buff)
dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
@@ -830,25 +922,33 @@ static const struct net_device_ops pxa_irda_netdev_ops = {
static int pxa_irda_probe(struct platform_device *pdev)
{
struct net_device *dev;
+ struct resource *res;
struct pxa_irda *si;
+ void __iomem *ficp, *stuart;
unsigned int baudrate_mask;
int err;
if (!pdev->dev.platform_data)
return -ENODEV;
- err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY;
- if (err)
- goto err_mem_1;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ficp = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ficp)) {
+ dev_err(&pdev->dev, "resource ficp not defined\n");
+ return PTR_ERR(ficp);
+ }
- err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY;
- if (err)
- goto err_mem_2;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ stuart = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(stuart)) {
+ dev_err(&pdev->dev, "resource stuart not defined\n");
+ return PTR_ERR(stuart);
+ }
dev = alloc_irdadev(sizeof(struct pxa_irda));
if (!dev) {
err = -ENOMEM;
- goto err_mem_3;
+ goto err_mem_1;
}
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -856,16 +956,25 @@ static int pxa_irda_probe(struct platform_device *pdev)
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
+ si->irda_base = ficp;
+ si->stuart_base = stuart;
si->uart_irq = platform_get_irq(pdev, 0);
si->icp_irq = platform_get_irq(pdev, 1);
- si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
- si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
+ si->sir_clk = devm_clk_get(&pdev->dev, "UARTCLK");
+ si->fir_clk = devm_clk_get(&pdev->dev, "FICPCLK");
if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk);
goto err_mem_4;
}
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (res)
+ si->drcmr_rx = res->start;
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (res)
+ si->drcmr_tx = res->start;
+
/*
* Initialise the SIR buffers
*/
@@ -925,15 +1034,7 @@ err_startup:
err_mem_5:
kfree(si->rx_buff.head);
err_mem_4:
- if (si->sir_clk && !IS_ERR(si->sir_clk))
- clk_put(si->sir_clk);
- if (si->fir_clk && !IS_ERR(si->fir_clk))
- clk_put(si->fir_clk);
free_netdev(dev);
-err_mem_3:
- release_mem_region(__PREG(FICP), 0x1c);
-err_mem_2:
- release_mem_region(__PREG(STUART), 0x24);
}
err_mem_1:
return err;
@@ -952,14 +1053,9 @@ static int pxa_irda_remove(struct platform_device *_dev)
si->pdata->shutdown(si->dev);
kfree(si->tx_buff.head);
kfree(si->rx_buff.head);
- clk_put(si->fir_clk);
- clk_put(si->sir_clk);
free_netdev(dev);
}
- release_mem_region(__PREG(STUART), 0x24);
- release_mem_region(__PREG(FICP), 0x1c);
-
return 0;
}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 47da43595ac2..06c8bfeaccd6 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -412,9 +412,10 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
port = macvlan_port_get_rcu(skb->dev);
if (is_multicast_ether_addr(eth->h_dest)) {
- skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
+ skb = ip_check_defrag(dev_net(skb->dev), skb, IP_DEFRAG_MACVLAN);
if (!skb)
return RX_HANDLER_CONSUMED;
+ *pskb = skb;
eth = eth_hdr(skb);
macvlan_forward_source(skb, port, eth->h_source);
src = macvlan_hash_lookup(port, eth->h_source);
@@ -456,6 +457,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
goto out;
}
+ *pskb = skb;
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 248478c6f6e4..54036ae0a388 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -137,7 +137,7 @@ static const struct proto_ops macvtap_socket_ops;
#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
NETIF_F_TSO6 | NETIF_F_UFO)
#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
-#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST)
static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev)
{
@@ -935,6 +935,9 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q,
/* Nothing to read, let's sleep */
schedule();
}
+ if (!noblock)
+ finish_wait(sk_sleep(&q->sk), &wait);
+
if (skb) {
ret = macvtap_put_user(q, skb, to);
if (unlikely(ret < 0))
@@ -942,8 +945,6 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q,
else
consume_skb(skb);
}
- if (!noblock)
- finish_wait(sk_sleep(&q->sk), &wait);
return ret;
}
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 97f3acd44798..06ee6395117f 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -244,15 +244,6 @@ static void free_param_target(struct netconsole_target *nt)
* <target>/...
*/
-struct netconsole_target_attr {
- struct configfs_attribute attr;
- ssize_t (*show)(struct netconsole_target *nt,
- char *buf);
- ssize_t (*store)(struct netconsole_target *nt,
- const char *buf,
- size_t count);
-};
-
static struct netconsole_target *to_target(struct config_item *item)
{
return item ?
@@ -264,58 +255,62 @@ static struct netconsole_target *to_target(struct config_item *item)
* Attribute operations for netconsole_target.
*/
-static ssize_t show_enabled(struct netconsole_target *nt, char *buf)
+static ssize_t enabled_show(struct config_item *item, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", nt->enabled);
+ return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->enabled);
}
-static ssize_t show_extended(struct netconsole_target *nt, char *buf)
+static ssize_t extended_show(struct config_item *item, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", nt->extended);
+ return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended);
}
-static ssize_t show_dev_name(struct netconsole_target *nt, char *buf)
+static ssize_t dev_name_show(struct config_item *item, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", nt->np.dev_name);
+ return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name);
}
-static ssize_t show_local_port(struct netconsole_target *nt, char *buf)
+static ssize_t local_port_show(struct config_item *item, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.local_port);
+ return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.local_port);
}
-static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
+static ssize_t remote_port_show(struct config_item *item, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.remote_port);
+ return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.remote_port);
}
-static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
+static ssize_t local_ip_show(struct config_item *item, char *buf)
{
+ struct netconsole_target *nt = to_target(item);
+
if (nt->np.ipv6)
return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6);
else
return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
}
-static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
+static ssize_t remote_ip_show(struct config_item *item, char *buf)
{
+ struct netconsole_target *nt = to_target(item);
+
if (nt->np.ipv6)
return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6);
else
return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
}
-static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
+static ssize_t local_mac_show(struct config_item *item, char *buf)
{
- struct net_device *dev = nt->np.dev;
+ struct net_device *dev = to_target(item)->np.dev;
static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast);
}
-static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
+static ssize_t remote_mac_show(struct config_item *item, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac);
+ return snprintf(buf, PAGE_SIZE, "%pM\n", to_target(item)->np.remote_mac);
}
/*
@@ -325,23 +320,26 @@ static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
* would enable him to dynamically add new netpoll targets for new
* network interfaces as and when they come up).
*/
-static ssize_t store_enabled(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t enabled_store(struct config_item *item,
+ const char *buf, size_t count)
{
+ struct netconsole_target *nt = to_target(item);
unsigned long flags;
int enabled;
int err;
+ mutex_lock(&dynamic_netconsole_mutex);
err = kstrtoint(buf, 10, &enabled);
if (err < 0)
- return err;
+ goto out_unlock;
+
+ err = -EINVAL;
if (enabled < 0 || enabled > 1)
- return -EINVAL;
+ goto out_unlock;
if ((bool)enabled == nt->enabled) {
pr_info("network logging has already %s\n",
nt->enabled ? "started" : "stopped");
- return -EINVAL;
+ goto out_unlock;
}
if (enabled) { /* true */
@@ -358,7 +356,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
err = netpoll_setup(&nt->np);
if (err)
- return err;
+ goto out_unlock;
pr_info("netconsole: network logging started\n");
} else { /* false */
@@ -374,42 +372,56 @@ static ssize_t store_enabled(struct netconsole_target *nt,
nt->enabled = enabled;
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return err;
}
-static ssize_t store_extended(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t extended_store(struct config_item *item, const char *buf,
+ size_t count)
{
+ struct netconsole_target *nt = to_target(item);
int extended;
int err;
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
- return -EINVAL;
+ err = -EINVAL;
+ goto out_unlock;
}
err = kstrtoint(buf, 10, &extended);
if (err < 0)
- return err;
- if (extended < 0 || extended > 1)
- return -EINVAL;
+ goto out_unlock;
+ if (extended < 0 || extended > 1) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
nt->extended = extended;
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return err;
}
-static ssize_t store_dev_name(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t dev_name_store(struct config_item *item, const char *buf,
+ size_t count)
{
+ struct netconsole_target *nt = to_target(item);
size_t len;
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
+ mutex_unlock(&dynamic_netconsole_mutex);
return -EINVAL;
}
@@ -420,53 +432,66 @@ static ssize_t store_dev_name(struct netconsole_target *nt,
if (nt->np.dev_name[len - 1] == '\n')
nt->np.dev_name[len - 1] = '\0';
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
}
-static ssize_t store_local_port(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t local_port_store(struct config_item *item, const char *buf,
+ size_t count)
{
- int rv;
+ struct netconsole_target *nt = to_target(item);
+ int rv = -EINVAL;
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
- return -EINVAL;
+ goto out_unlock;
}
rv = kstrtou16(buf, 10, &nt->np.local_port);
if (rv < 0)
- return rv;
+ goto out_unlock;
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return rv;
}
-static ssize_t store_remote_port(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t remote_port_store(struct config_item *item,
+ const char *buf, size_t count)
{
- int rv;
+ struct netconsole_target *nt = to_target(item);
+ int rv = -EINVAL;
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
- return -EINVAL;
+ goto out_unlock;
}
rv = kstrtou16(buf, 10, &nt->np.remote_port);
if (rv < 0)
- return rv;
+ goto out_unlock;
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return rv;
}
-static ssize_t store_local_ip(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t local_ip_store(struct config_item *item, const char *buf,
+ size_t count)
{
+ struct netconsole_target *nt = to_target(item);
+
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
- return -EINVAL;
+ goto out_unlock;
}
if (strnchr(buf, count, ':')) {
@@ -474,29 +499,35 @@ static ssize_t store_local_ip(struct netconsole_target *nt,
if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
if (*end && *end != '\n') {
pr_err("invalid IPv6 address at: <%c>\n", *end);
- return -EINVAL;
+ goto out_unlock;
}
nt->np.ipv6 = true;
} else
- return -EINVAL;
+ goto out_unlock;
} else {
if (!nt->np.ipv6) {
nt->np.local_ip.ip = in_aton(buf);
} else
- return -EINVAL;
+ goto out_unlock;
}
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return -EINVAL;
}
-static ssize_t store_remote_ip(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t remote_ip_store(struct config_item *item, const char *buf,
+ size_t count)
{
+ struct netconsole_target *nt = to_target(item);
+
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
- return -EINVAL;
+ goto out_unlock;
}
if (strnchr(buf, count, ':')) {
@@ -504,74 +535,71 @@ static ssize_t store_remote_ip(struct netconsole_target *nt,
if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
if (*end && *end != '\n') {
pr_err("invalid IPv6 address at: <%c>\n", *end);
- return -EINVAL;
+ goto out_unlock;
}
nt->np.ipv6 = true;
} else
- return -EINVAL;
+ goto out_unlock;
} else {
if (!nt->np.ipv6) {
nt->np.remote_ip.ip = in_aton(buf);
} else
- return -EINVAL;
+ goto out_unlock;
}
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return -EINVAL;
}
-static ssize_t store_remote_mac(struct netconsole_target *nt,
- const char *buf,
- size_t count)
+static ssize_t remote_mac_store(struct config_item *item, const char *buf,
+ size_t count)
{
+ struct netconsole_target *nt = to_target(item);
u8 remote_mac[ETH_ALEN];
+ mutex_lock(&dynamic_netconsole_mutex);
if (nt->enabled) {
pr_err("target (%s) is enabled, disable to update parameters\n",
config_item_name(&nt->item));
- return -EINVAL;
+ goto out_unlock;
}
if (!mac_pton(buf, remote_mac))
- return -EINVAL;
+ goto out_unlock;
if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
- return -EINVAL;
+ goto out_unlock;
memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
+ mutex_unlock(&dynamic_netconsole_mutex);
return strnlen(buf, count);
+out_unlock:
+ mutex_unlock(&dynamic_netconsole_mutex);
+ return -EINVAL;
}
-/*
- * Attribute definitions for netconsole_target.
- */
-
-#define NETCONSOLE_TARGET_ATTR_RO(_name) \
-static struct netconsole_target_attr netconsole_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL)
-
-#define NETCONSOLE_TARGET_ATTR_RW(_name) \
-static struct netconsole_target_attr netconsole_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name)
-
-NETCONSOLE_TARGET_ATTR_RW(enabled);
-NETCONSOLE_TARGET_ATTR_RW(extended);
-NETCONSOLE_TARGET_ATTR_RW(dev_name);
-NETCONSOLE_TARGET_ATTR_RW(local_port);
-NETCONSOLE_TARGET_ATTR_RW(remote_port);
-NETCONSOLE_TARGET_ATTR_RW(local_ip);
-NETCONSOLE_TARGET_ATTR_RW(remote_ip);
-NETCONSOLE_TARGET_ATTR_RO(local_mac);
-NETCONSOLE_TARGET_ATTR_RW(remote_mac);
+CONFIGFS_ATTR(, enabled);
+CONFIGFS_ATTR(, extended);
+CONFIGFS_ATTR(, dev_name);
+CONFIGFS_ATTR(, local_port);
+CONFIGFS_ATTR(, remote_port);
+CONFIGFS_ATTR(, local_ip);
+CONFIGFS_ATTR(, remote_ip);
+CONFIGFS_ATTR_RO(, local_mac);
+CONFIGFS_ATTR(, remote_mac);
static struct configfs_attribute *netconsole_target_attrs[] = {
- &netconsole_target_enabled.attr,
- &netconsole_target_extended.attr,
- &netconsole_target_dev_name.attr,
- &netconsole_target_local_port.attr,
- &netconsole_target_remote_port.attr,
- &netconsole_target_local_ip.attr,
- &netconsole_target_remote_ip.attr,
- &netconsole_target_local_mac.attr,
- &netconsole_target_remote_mac.attr,
+ &attr_enabled,
+ &attr_extended,
+ &attr_dev_name,
+ &attr_local_port,
+ &attr_remote_port,
+ &attr_local_ip,
+ &attr_remote_ip,
+ &attr_local_mac,
+ &attr_remote_mac,
NULL,
};
@@ -584,43 +612,8 @@ static void netconsole_target_release(struct config_item *item)
kfree(to_target(item));
}
-static ssize_t netconsole_target_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *buf)
-{
- ssize_t ret = -EINVAL;
- struct netconsole_target *nt = to_target(item);
- struct netconsole_target_attr *na =
- container_of(attr, struct netconsole_target_attr, attr);
-
- if (na->show)
- ret = na->show(nt, buf);
-
- return ret;
-}
-
-static ssize_t netconsole_target_attr_store(struct config_item *item,
- struct configfs_attribute *attr,
- const char *buf,
- size_t count)
-{
- ssize_t ret = -EINVAL;
- struct netconsole_target *nt = to_target(item);
- struct netconsole_target_attr *na =
- container_of(attr, struct netconsole_target_attr, attr);
-
- mutex_lock(&dynamic_netconsole_mutex);
- if (na->store)
- ret = na->store(nt, buf, count);
- mutex_unlock(&dynamic_netconsole_mutex);
-
- return ret;
-}
-
static struct configfs_item_operations netconsole_target_item_ops = {
.release = netconsole_target_release,
- .show_attribute = netconsole_target_attr_show,
- .store_attribute = netconsole_target_attr_store,
};
static struct config_item_type netconsole_target_type = {
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index c5ad98ace5d0..60994a83a0d6 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -69,20 +69,39 @@ config SMSC_PHY
---help---
Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
+config BCM_NET_PHYLIB
+ tristate
+
config BROADCOM_PHY
tristate "Drivers for Broadcom PHYs"
+ select BCM_NET_PHYLIB
---help---
Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
BCM5481 and BCM5482 PHYs.
+config BCM_CYGNUS_PHY
+ tristate "Drivers for Broadcom Cygnus SoC internal PHY"
+ depends on ARCH_BCM_CYGNUS || COMPILE_TEST
+ depends on MDIO_BCM_IPROC
+ select BCM_NET_PHYLIB
+ ---help---
+ This PHY driver is for the 1G internal PHYs of the Broadcom
+ Cygnus Family SoC.
+
+ Currently supports internal PHY's used in the BCM11300,
+ BCM11320, BCM11350, BCM11360, BCM58300, BCM58302,
+ BCM58303 & BCM58305 Broadcom Cygnus SoCs.
+
config BCM63XX_PHY
tristate "Drivers for Broadcom 63xx SOCs internal PHY"
depends on BCM63XX
+ select BCM_NET_PHYLIB
---help---
Currently supports the 6348 and 6358 PHYs.
config BCM7XXX_PHY
tristate "Drivers for Broadcom 7xxx SOCs internal PHYs"
+ select BCM_NET_PHYLIB
---help---
Currently supports the BCM7366, BCM7439, BCM7445, and
40nm and 65nm generation of BCM7xxx Set Top Box SoCs.
@@ -122,6 +141,11 @@ config MICREL_PHY
---help---
Supports the KSZ9021, VSC8201, KS8001 PHYs.
+config DP83848_PHY
+ tristate "Driver for Texas Instruments DP83848 PHY"
+ ---help---
+ Supports the DP83848 PHY.
+
config DP83867_PHY
tristate "Drivers for Texas Instruments DP83867 Gigabit PHY"
---help---
@@ -168,8 +192,6 @@ config MDIO_OCTEON
busses. It is required by the Octeon and ThunderX ethernet device
drivers.
- If in doubt, say Y.
-
config MDIO_SUN4I
tristate "Allwinner sun4i MDIO interface support"
depends on ARCH_SUNXI
@@ -225,6 +247,15 @@ config MDIO_BCM_UNIMAC
This hardware can be found in the Broadcom GENET Ethernet MAC
controllers as well as some Broadcom Ethernet switches such as the
Starfighter 2 switches.
+
+config MDIO_BCM_IPROC
+ tristate "Broadcom iProc MDIO bus controller"
+ depends on ARCH_BCM_IPROC || COMPILE_TEST
+ depends on HAS_IOMEM && OF_MDIO
+ help
+ This module provides a driver for the MDIO busses found in the
+ Broadcom iProc SoC's.
+
endif # PHYLIB
config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 87f079c4b2c7..f31a4e25cf15 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -12,10 +12,12 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
+obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o
obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o
+obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
@@ -24,6 +26,7 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
+obj-$(CONFIG_DP83848_PHY) += dp83848.o
obj-$(CONFIG_DP83867_PHY) += dp83867.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
@@ -38,3 +41,4 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o
obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
+obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index d6111affbcb6..f1936b7a7af6 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -171,20 +171,7 @@ static struct phy_driver aquantia_driver[] = {
},
};
-static int __init aquantia_init(void)
-{
- return phy_drivers_register(aquantia_driver,
- ARRAY_SIZE(aquantia_driver));
-}
-
-static void __exit aquantia_exit(void)
-{
- return phy_drivers_unregister(aquantia_driver,
- ARRAY_SIZE(aquantia_driver));
-}
-
-module_init(aquantia_init);
-module_exit(aquantia_exit);
+module_phy_driver(aquantia_driver);
static struct mdio_device_id __maybe_unused aquantia_tbl[] = {
{ PHY_ID_AQ1202, 0xfffffff0 },
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index fabf11d32d27..2d020a3ec0b5 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -308,6 +308,8 @@ static struct phy_driver at803x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .ack_interrupt = at803x_ack_interrupt,
+ .config_intr = at803x_config_intr,
.driver = {
.owner = THIS_MODULE,
},
@@ -327,6 +329,8 @@ static struct phy_driver at803x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .ack_interrupt = at803x_ack_interrupt,
+ .config_intr = at803x_config_intr,
.driver = {
.owner = THIS_MODULE,
},
diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c
new file mode 100644
index 000000000000..49bbc6826883
--- /dev/null
+++ b/drivers/net/phy/bcm-cygnus.c
@@ -0,0 +1,158 @@
+/*
+ * 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. */
+#include "bcm-phy-lib.h"
+#include <linux/brcmphy.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+
+/* Broadcom Cygnus Phy specific registers */
+#define MII_BCM_CYGNUS_AFE_VDAC_ICTRL_0 0x91E5 /* VDAL Control register */
+
+static int bcm_cygnus_afe_config(struct phy_device *phydev)
+{
+ int rc;
+
+ /* ensure smdspclk is enabled */
+ rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, 0x0c30);
+ if (rc < 0)
+ return rc;
+
+ /* AFE_VDAC_ICTRL_0 bit 7:4 Iq=1100 for 1g 10bt, normal modes */
+ rc = bcm_phy_write_misc(phydev, 0x39, 0x01, 0xA7C8);
+ if (rc < 0)
+ return rc;
+
+ /* AFE_HPF_TRIM_OTHERS bit11=1, short cascode enable for all modes*/
+ rc = bcm_phy_write_misc(phydev, 0x3A, 0x00, 0x0803);
+ if (rc < 0)
+ return rc;
+
+ /* AFE_TX_CONFIG_1 bit 7:4 Iq=1100 for test modes */
+ rc = bcm_phy_write_misc(phydev, 0x3A, 0x01, 0xA740);
+ if (rc < 0)
+ return rc;
+
+ /* AFE TEMPSEN_OTHERS rcal_HT, rcal_LT 10000 */
+ rc = bcm_phy_write_misc(phydev, 0x3A, 0x03, 0x8400);
+ if (rc < 0)
+ return rc;
+
+ /* AFE_FUTURE_RSV bit 2:0 rccal <2:0>=100 */
+ rc = bcm_phy_write_misc(phydev, 0x3B, 0x00, 0x0004);
+ if (rc < 0)
+ return rc;
+
+ /* Adjust bias current trim to overcome digital offSet */
+ rc = phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x02);
+ if (rc < 0)
+ return rc;
+
+ /* make rcal=100, since rdb default is 000 */
+ rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB1, 0x10);
+ if (rc < 0)
+ return rc;
+
+ /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */
+ rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x10);
+ if (rc < 0)
+ return rc;
+
+ /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */
+ rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x00);
+
+ return 0;
+}
+
+static int bcm_cygnus_config_init(struct phy_device *phydev)
+{
+ int reg, rc;
+
+ reg = phy_read(phydev, MII_BCM54XX_ECR);
+ if (reg < 0)
+ return reg;
+
+ /* Mask interrupts globally. */
+ reg |= MII_BCM54XX_ECR_IM;
+ rc = phy_write(phydev, MII_BCM54XX_ECR, reg);
+ if (rc)
+ return rc;
+
+ /* Unmask events of interest */
+ reg = ~(MII_BCM54XX_INT_DUPLEX |
+ MII_BCM54XX_INT_SPEED |
+ MII_BCM54XX_INT_LINK);
+ rc = phy_write(phydev, MII_BCM54XX_IMR, reg);
+ if (rc)
+ return rc;
+
+ /* Apply AFE settings for the PHY */
+ rc = bcm_cygnus_afe_config(phydev);
+ if (rc)
+ return rc;
+
+ /* Advertise EEE */
+ rc = bcm_phy_enable_eee(phydev);
+ if (rc)
+ return rc;
+
+ /* Enable APD */
+ return bcm_phy_enable_apd(phydev, false);
+}
+
+static int bcm_cygnus_resume(struct phy_device *phydev)
+{
+ int rc;
+
+ genphy_resume(phydev);
+
+ /* Re-initialize the PHY to apply AFE work-arounds and
+ * configurations when coming out of suspend.
+ */
+ rc = bcm_cygnus_config_init(phydev);
+ if (rc)
+ return rc;
+
+ /* restart auto negotiation with the new settings */
+ return genphy_config_aneg(phydev);
+}
+
+static struct phy_driver bcm_cygnus_phy_driver[] = {
+{
+ .phy_id = PHY_ID_BCM_CYGNUS,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom Cygnus PHY",
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .config_init = bcm_cygnus_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = bcm_cygnus_resume,
+} };
+
+static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = {
+ { PHY_ID_BCM_CYGNUS, 0xfffffff0, },
+ { }
+};
+MODULE_DEVICE_TABLE(mdio, bcm_cygnus_phy_tbl);
+
+module_phy_driver(bcm_cygnus_phy_driver);
+
+MODULE_DESCRIPTION("Broadcom Cygnus internal PHY driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Broadcom Corporation");
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
new file mode 100644
index 000000000000..ddb377e53633
--- /dev/null
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -0,0 +1,213 @@
+/*
+ * 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 "bcm-phy-lib.h"
+#include <linux/brcmphy.h>
+#include <linux/export.h>
+#include <linux/mdio.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define MII_BCM_CHANNEL_WIDTH 0x2000
+#define BCM_CL45VEN_EEE_ADV 0x3c
+
+int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
+{
+ int rc;
+
+ rc = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
+ if (rc < 0)
+ return rc;
+
+ return phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_exp);
+
+int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
+{
+ int val;
+
+ val = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
+ if (val < 0)
+ return val;
+
+ val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
+
+ /* Restore default value. It's O.K. if this write fails. */
+ phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
+
+int bcm_phy_write_misc(struct phy_device *phydev,
+ u16 reg, u16 chl, u16 val)
+{
+ int rc;
+ int tmp;
+
+ rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
+ MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ if (rc < 0)
+ return rc;
+
+ tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+ tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
+ rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
+ if (rc < 0)
+ return rc;
+
+ tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
+ rc = bcm_phy_write_exp(phydev, tmp, val);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_misc);
+
+int bcm_phy_read_misc(struct phy_device *phydev,
+ u16 reg, u16 chl)
+{
+ int rc;
+ int tmp;
+
+ rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
+ MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ if (rc < 0)
+ return rc;
+
+ tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+ tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
+ rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
+ if (rc < 0)
+ return rc;
+
+ tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
+ rc = bcm_phy_read_exp(phydev, tmp);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_misc);
+
+int bcm_phy_ack_intr(struct phy_device *phydev)
+{
+ int reg;
+
+ /* Clear pending interrupts. */
+ reg = phy_read(phydev, MII_BCM54XX_ISR);
+ if (reg < 0)
+ return reg;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_ack_intr);
+
+int bcm_phy_config_intr(struct phy_device *phydev)
+{
+ int reg;
+
+ reg = phy_read(phydev, MII_BCM54XX_ECR);
+ if (reg < 0)
+ return reg;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ reg &= ~MII_BCM54XX_ECR_IM;
+ else
+ reg |= MII_BCM54XX_ECR_IM;
+
+ return phy_write(phydev, MII_BCM54XX_ECR, reg);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_config_intr);
+
+int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow)
+{
+ phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
+ return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_shadow);
+
+int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
+ u16 val)
+{
+ return phy_write(phydev, MII_BCM54XX_SHD,
+ MII_BCM54XX_SHD_WRITE |
+ MII_BCM54XX_SHD_VAL(shadow) |
+ MII_BCM54XX_SHD_DATA(val));
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_shadow);
+
+int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down)
+{
+ int val;
+
+ if (dll_pwr_down) {
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
+ if (val < 0)
+ return val;
+
+ val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
+ }
+
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
+ if (val < 0)
+ return val;
+
+ /* Clear APD bits */
+ val &= BCM_APD_CLR_MASK;
+
+ if (phydev->autoneg == AUTONEG_ENABLE)
+ val |= BCM54XX_SHD_APD_EN;
+ else
+ val |= BCM_NO_ANEG_APD_EN;
+
+ /* Enable energy detect single link pulse for easy wakeup */
+ val |= BCM_APD_SINGLELP_EN;
+
+ /* Enable Auto Power-Down (APD) for the PHY */
+ return bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_enable_apd);
+
+int bcm_phy_enable_eee(struct phy_device *phydev)
+{
+ int val;
+
+ /* Enable EEE at PHY level */
+ val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
+ MDIO_MMD_AN, phydev->addr);
+ if (val < 0)
+ return val;
+
+ val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
+
+ phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
+ MDIO_MMD_AN, phydev->addr, (u32)val);
+
+ /* Advertise EEE */
+ val = phy_read_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
+ MDIO_MMD_AN, phydev->addr);
+ if (val < 0)
+ return val;
+
+ val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
+
+ phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
+ MDIO_MMD_AN, phydev->addr, (u32)val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_enable_eee);
+
+MODULE_DESCRIPTION("Broadcom PHY Library");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Broadcom Corporation");
diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h
new file mode 100644
index 000000000000..b2091c88b44d
--- /dev/null
+++ b/drivers/net/phy/bcm-phy-lib.h
@@ -0,0 +1,37 @@
+/*
+ * 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
+#define _LINUX_BCM_PHY_LIB_H
+
+#include <linux/phy.h>
+
+int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
+int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);
+
+int bcm_phy_write_misc(struct phy_device *phydev,
+ u16 reg, u16 chl, u16 value);
+int bcm_phy_read_misc(struct phy_device *phydev,
+ u16 reg, u16 chl);
+
+int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
+ u16 val);
+int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow);
+
+int bcm_phy_ack_intr(struct phy_device *phydev);
+int bcm_phy_config_intr(struct phy_device *phydev);
+
+int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
+
+int bcm_phy_enable_eee(struct phy_device *phydev);
+#endif /* _LINUX_BCM_PHY_LIB_H */
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index 830ec31f952f..86b28052bf06 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -6,6 +6,7 @@
* 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>
#include <linux/phy.h>
@@ -42,35 +43,6 @@ static int bcm63xx_config_init(struct phy_device *phydev)
return phy_write(phydev, MII_BCM63XX_IR, reg);
}
-static int bcm63xx_ack_interrupt(struct phy_device *phydev)
-{
- int reg;
-
- /* Clear pending interrupts. */
- reg = phy_read(phydev, MII_BCM63XX_IR);
- if (reg < 0)
- return reg;
-
- return 0;
-}
-
-static int bcm63xx_config_intr(struct phy_device *phydev)
-{
- int reg, err;
-
- reg = phy_read(phydev, MII_BCM63XX_IR);
- if (reg < 0)
- return reg;
-
- if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
- reg &= ~MII_BCM63XX_IR_GMASK;
- else
- reg |= MII_BCM63XX_IR_GMASK;
-
- err = phy_write(phydev, MII_BCM63XX_IR, reg);
- return err;
-}
-
static struct phy_driver bcm63xx_driver[] = {
{
.phy_id = 0x00406000,
@@ -82,8 +54,8 @@ static struct phy_driver bcm63xx_driver[] = {
.config_init = bcm63xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm63xx_ack_interrupt,
- .config_intr = bcm63xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
/* same phy as above, with just a different OUI */
@@ -95,8 +67,8 @@ static struct phy_driver bcm63xx_driver[] = {
.config_init = bcm63xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm63xx_ack_interrupt,
- .config_intr = bcm63xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
} };
diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
index 6b701b3ded74..03d4809a9126 100644
--- a/drivers/net/phy/bcm7xxx.c
+++ b/drivers/net/phy/bcm7xxx.c
@@ -12,12 +12,12 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/delay.h>
+#include "bcm-phy-lib.h"
#include <linux/bitops.h>
#include <linux/brcmphy.h>
#include <linux/mdio.h>
/* Broadcom BCM7xxx internal PHY registers */
-#define MII_BCM7XXX_CHANNEL_WIDTH 0x2000
/* 40nm only register definitions */
#define MII_BCM7XXX_100TX_AUX_CTL 0x10
@@ -25,7 +25,6 @@
#define MII_BCM7XXX_100TX_DISC 0x14
#define MII_BCM7XXX_AUX_MODE 0x1d
#define MII_BCM7XX_64CLK_MDIO BIT(12)
-#define MII_BCM7XXX_CORE_BASE1E 0x1e
#define MII_BCM7XXX_TEST 0x1f
#define MII_BCM7XXX_SHD_MODE_2 BIT(2)
@@ -46,39 +45,13 @@
#define AFE_VDAC_OTHERS_0 MISC_ADDR(0x39, 3)
#define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0)
-#define CORE_EXPB0 0xb0
-
-static void phy_write_exp(struct phy_device *phydev,
- u16 reg, u16 value)
-{
- phy_write(phydev, MII_BCM54XX_EXP_SEL, MII_BCM54XX_EXP_SEL_ER | reg);
- phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
-}
-
-static void phy_write_misc(struct phy_device *phydev,
- u16 reg, u16 chl, u16 value)
-{
- int tmp;
-
- phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-
- tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
- tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
- phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
-
- tmp = (chl * MII_BCM7XXX_CHANNEL_WIDTH) | reg;
- phy_write(phydev, MII_BCM54XX_EXP_SEL, tmp);
-
- phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
-}
-
static void r_rc_cal_reset(struct phy_device *phydev)
{
/* Reset R_CAL/RC_CAL Engine */
- phy_write_exp(phydev, 0x00b0, 0x0010);
+ bcm_phy_write_exp(phydev, 0x00b0, 0x0010);
/* Disable Reset R_AL/RC_CAL Engine */
- phy_write_exp(phydev, 0x00b0, 0x0000);
+ bcm_phy_write_exp(phydev, 0x00b0, 0x0000);
}
static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
@@ -86,38 +59,38 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
/* Increase VCO range to prevent unlocking problem of PLL at low
* temp
*/
- phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
+ bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
/* Change Ki to 011 */
- phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
+ bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
/* Disable loading of TVCO buffer to bandgap, set bandgap trim
* to 111
*/
- phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
+ bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
/* Adjust bias current trim by -3 */
- phy_write_misc(phydev, DSP_TAP10, 0x690b);
+ bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b);
/* Switch to CORE_BASE1E */
- phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd);
+ phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd);
r_rc_cal_reset(phydev);
/* write AFE_RXCONFIG_0 */
- phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
/* write AFE_RXCONFIG_1 */
- phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
/* write AFE_RX_LP_COUNTER */
- phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
+ bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
/* write AFE_HPF_TRIM_OTHERS */
- phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
+ bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
/* write AFTE_TX_CONFIG */
- phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
+ bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
return 0;
}
@@ -125,36 +98,36 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
{
/* AFE_RXCONFIG_0 */
- phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
/* AFE_RXCONFIG_1 */
- phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
/* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
- phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
/* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
- phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
+ bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
- phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
+ bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
- phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
+ bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
/* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
- phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
+ bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
* offset for HT=0 code
*/
- phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
+ bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
- phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
+ phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
- phy_write_misc(phydev, DSP_TAP10, 0x011b);
+ bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
/* Reset R_CAL/RC_CAL engine */
r_rc_cal_reset(phydev);
@@ -165,24 +138,24 @@ static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
{
/* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
- phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
- phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
+ bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
- phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
+ bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
* offset for HT=0 code
*/
- phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
+ bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
- phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
+ phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
- phy_write_misc(phydev, DSP_TAP10, 0x011b);
+ bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
/* Reset R_CAL/RC_CAL engine */
r_rc_cal_reset(phydev);
@@ -190,53 +163,6 @@ static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
return 0;
}
-static int bcm7xxx_apd_enable(struct phy_device *phydev)
-{
- int val;
-
- /* Enable powering down of the DLL during auto-power down */
- val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
- if (val < 0)
- return val;
-
- val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
- bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
-
- /* Enable auto-power down */
- val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
- if (val < 0)
- return val;
-
- val |= BCM54XX_SHD_APD_EN;
- return bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
-}
-
-static int bcm7xxx_eee_enable(struct phy_device *phydev)
-{
- int val;
-
- val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
- MDIO_MMD_AN, phydev->addr);
- if (val < 0)
- return val;
-
- /* Enable general EEE feature at the PHY level */
- val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
-
- phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
- MDIO_MMD_AN, phydev->addr, val);
-
- /* Advertise supported modes */
- val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
- MDIO_MMD_AN, phydev->addr);
-
- val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
- phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
- MDIO_MMD_AN, phydev->addr, val);
-
- return 0;
-}
-
static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
{
u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
@@ -273,11 +199,11 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
if (ret)
return ret;
- ret = bcm7xxx_eee_enable(phydev);
+ ret = bcm_phy_enable_eee(phydev);
if (ret)
return ret;
- return bcm7xxx_apd_enable(phydev);
+ return bcm_phy_enable_apd(phydev, true);
}
static int bcm7xxx_28nm_resume(struct phy_device *phydev)
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 9c71295f2fef..07a6119121c3 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -14,6 +14,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include "bcm-phy-lib.h"
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/brcmphy.h>
@@ -29,39 +30,6 @@ MODULE_DESCRIPTION("Broadcom PHY driver");
MODULE_AUTHOR("Maciej W. Rozycki");
MODULE_LICENSE("GPL");
-/* Indirect register access functions for the Expansion Registers */
-static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
-{
- int val;
-
- val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
- if (val < 0)
- return val;
-
- val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
-
- /* Restore default value. It's O.K. if this write fails. */
- phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
-
- return val;
-}
-
-static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
-{
- int ret;
-
- ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
- if (ret < 0)
- return ret;
-
- ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
-
- /* Restore default value. It's O.K. if this write fails. */
- phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
-
- return ret;
-}
-
static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
{
return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
@@ -72,28 +40,28 @@ static int bcm50610_a0_workaround(struct phy_device *phydev)
{
int err;
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
if (err < 0)
return err;
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
- MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
+ MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
if (err < 0)
return err;
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
MII_BCM54XX_EXP_EXP75_VDACCTRL);
if (err < 0)
return err;
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
MII_BCM54XX_EXP_EXP96_MYST);
if (err < 0)
return err;
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
MII_BCM54XX_EXP_EXP97_MYST);
return err;
@@ -114,7 +82,7 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev)
if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
/* Clear bit 9 to fix a phy interop issue. */
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
if (err < 0)
goto error;
@@ -129,12 +97,12 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev)
if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
int val;
- val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
+ val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
if (val < 0)
goto error;
val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
- err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
+ err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
}
error:
@@ -159,7 +127,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
return;
- val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
if (val < 0)
return;
@@ -190,9 +158,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
val |= BCM54XX_SHD_SCR3_TRDDAPD;
if (orig != val)
- bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
- val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
if (val < 0)
return;
@@ -204,7 +172,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
val &= ~BCM54XX_SHD_APD_EN;
if (orig != val)
- bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
}
static int bcm54xx_config_init(struct phy_device *phydev)
@@ -232,7 +200,7 @@ static int bcm54xx_config_init(struct phy_device *phydev)
if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
(phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
- bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
(phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
@@ -254,8 +222,8 @@ static int bcm5482_config_init(struct phy_device *phydev)
/*
* Enable secondary SerDes and its use as an LED source
*/
- reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
- bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
+ reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
+ bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
reg |
BCM5482_SHD_SSD_LEDM |
BCM5482_SHD_SSD_EN);
@@ -264,10 +232,10 @@ static int bcm5482_config_init(struct phy_device *phydev)
* Enable SGMII slave mode and auto-detection
*/
reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
- err = bcm54xx_exp_read(phydev, reg);
+ err = bcm_phy_read_exp(phydev, reg);
if (err < 0)
return err;
- err = bcm54xx_exp_write(phydev, reg, err |
+ err = bcm_phy_write_exp(phydev, reg, err |
BCM5482_SSD_SGMII_SLAVE_EN |
BCM5482_SSD_SGMII_SLAVE_AD);
if (err < 0)
@@ -277,10 +245,10 @@ static int bcm5482_config_init(struct phy_device *phydev)
* Disable secondary SerDes powerdown
*/
reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
- err = bcm54xx_exp_read(phydev, reg);
+ err = bcm_phy_read_exp(phydev, reg);
if (err < 0)
return err;
- err = bcm54xx_exp_write(phydev, reg,
+ err = bcm_phy_write_exp(phydev, reg,
err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
if (err < 0)
return err;
@@ -288,15 +256,15 @@ static int bcm5482_config_init(struct phy_device *phydev)
/*
* Select 1000BASE-X register set (primary SerDes)
*/
- reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
- bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
+ reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
+ bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
reg | BCM5482_SHD_MODE_1000BX);
/*
* LED1=ACTIVITYLED, LED3=LINKSPD[2]
* (Use LED1 as secondary SerDes ACTIVITY LED)
*/
- bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
+ bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
@@ -334,35 +302,6 @@ static int bcm5482_read_status(struct phy_device *phydev)
return err;
}
-static int bcm54xx_ack_interrupt(struct phy_device *phydev)
-{
- int reg;
-
- /* Clear pending interrupts. */
- reg = phy_read(phydev, MII_BCM54XX_ISR);
- if (reg < 0)
- return reg;
-
- return 0;
-}
-
-static int bcm54xx_config_intr(struct phy_device *phydev)
-{
- int reg, err;
-
- reg = phy_read(phydev, MII_BCM54XX_ECR);
- if (reg < 0)
- return reg;
-
- if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
- reg &= ~MII_BCM54XX_ECR_IM;
- else
- reg |= MII_BCM54XX_ECR_IM;
-
- err = phy_write(phydev, MII_BCM54XX_ECR, reg);
- return err;
-}
-
static int bcm5481_config_aneg(struct phy_device *phydev)
{
int ret;
@@ -519,8 +458,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM5421,
@@ -532,8 +471,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM5461,
@@ -545,8 +484,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM54616S,
@@ -558,8 +497,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM5464,
@@ -571,8 +510,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM5481,
@@ -584,8 +523,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = bcm5481_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM5482,
@@ -597,8 +536,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm5482_config_init,
.config_aneg = genphy_config_aneg,
.read_status = bcm5482_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM50610,
@@ -610,8 +549,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM50610M,
@@ -623,8 +562,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCM57780,
@@ -636,8 +575,8 @@ static struct phy_driver broadcom_drivers[] = {
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .ack_interrupt = bcm54xx_ack_interrupt,
- .config_intr = bcm54xx_config_intr,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
.driver = { .owner = THIS_MODULE },
}, {
.phy_id = PHY_ID_BCMAC131,
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 185b03c08e16..47b711739ba9 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -20,6 +20,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -36,8 +37,6 @@
#define DP83640_PHY_ID 0x20005ce1
#define PAGESEL 0x13
-#define LAYER4 0x02
-#define LAYER2 0x01
#define MAX_RXTS 64
#define N_EXT_TS 6
#define N_PER_OUT 7
@@ -68,6 +67,8 @@
/* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16
+#define SKB_TIMESTAMP_TIMEOUT 2 /* jiffies */
+
#if defined(__BIG_ENDIAN)
#define ENDIAN_FLAG 0
#elif defined(__LITTLE_ENDIAN)
@@ -110,7 +111,7 @@ struct dp83640_private {
struct list_head list;
struct dp83640_clock *clock;
struct phy_device *phydev;
- struct work_struct ts_work;
+ struct delayed_work ts_work;
int hwts_tx_en;
int hwts_rx_en;
int layer;
@@ -284,7 +285,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
rxts->seqid = p->seqid;
rxts->msgtype = (p->msgtype >> 12) & 0xf;
rxts->hash = p->msgtype & 0x0fff;
- rxts->tmo = jiffies + 2;
+ rxts->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
}
static u64 phy2txts(struct phy_txts *p)
@@ -787,9 +788,12 @@ static int decode_evnt(struct dp83640_private *dp83640,
return parsed;
}
+#define DP83640_PACKET_HASH_OFFSET 20
+#define DP83640_PACKET_HASH_LEN 10
+
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{
- u16 *seqid;
+ u16 *seqid, hash;
unsigned int offset = 0;
u8 *msgtype, *data = skb_mac_header(skb);
@@ -819,11 +823,19 @@ static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
msgtype = data + offset + OFF_PTP_CONTROL;
else
msgtype = data + offset;
+ if (rxts->msgtype != (*msgtype & 0xf))
+ return 0;
seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+ if (rxts->seqid != ntohs(*seqid))
+ return 0;
+
+ hash = ether_crc(DP83640_PACKET_HASH_LEN,
+ data + offset + DP83640_PACKET_HASH_OFFSET) >> 20;
+ if (rxts->hash != hash)
+ return 0;
- return rxts->msgtype == (*msgtype & 0xf) &&
- rxts->seqid == ntohs(*seqid);
+ return 1;
}
static void decode_rxts(struct dp83640_private *dp83640,
@@ -1103,7 +1115,7 @@ static int dp83640_probe(struct phy_device *phydev)
goto no_memory;
dp83640->phydev = phydev;
- INIT_WORK(&dp83640->ts_work, rx_timestamp_work);
+ INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work);
INIT_LIST_HEAD(&dp83640->rxts);
INIT_LIST_HEAD(&dp83640->rxpool);
@@ -1150,7 +1162,7 @@ static void dp83640_remove(struct phy_device *phydev)
return;
enable_status_frames(phydev, false);
- cancel_work_sync(&dp83640->ts_work);
+ cancel_delayed_work_sync(&dp83640->ts_work);
skb_queue_purge(&dp83640->rx_queue);
skb_queue_purge(&dp83640->tx_queue);
@@ -1282,29 +1294,29 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer = LAYER4;
- dp83640->version = 1;
+ dp83640->layer = PTP_CLASS_L4;
+ dp83640->version = PTP_CLASS_V1;
break;
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer = LAYER4;
- dp83640->version = 2;
+ dp83640->layer = PTP_CLASS_L4;
+ dp83640->version = PTP_CLASS_V2;
break;
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer = LAYER2;
- dp83640->version = 2;
+ dp83640->layer = PTP_CLASS_L2;
+ dp83640->version = PTP_CLASS_V2;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer = LAYER4|LAYER2;
- dp83640->version = 2;
+ dp83640->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
+ dp83640->version = PTP_CLASS_V2;
break;
default:
return -ERANGE;
@@ -1313,11 +1325,11 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
- if (dp83640->layer & LAYER2) {
+ if (dp83640->layer & PTP_CLASS_L2) {
txcfg0 |= TX_L2_EN;
rxcfg0 |= RX_L2_EN;
}
- if (dp83640->layer & LAYER4) {
+ if (dp83640->layer & PTP_CLASS_L4) {
txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
}
@@ -1344,7 +1356,7 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
static void rx_timestamp_work(struct work_struct *work)
{
struct dp83640_private *dp83640 =
- container_of(work, struct dp83640_private, ts_work);
+ container_of(work, struct dp83640_private, ts_work.work);
struct sk_buff *skb;
/* Deliver expired packets. */
@@ -1361,7 +1373,7 @@ static void rx_timestamp_work(struct work_struct *work)
}
if (!skb_queue_empty(&dp83640->rx_queue))
- schedule_work(&dp83640->ts_work);
+ schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
}
static bool dp83640_rxtstamp(struct phy_device *phydev,
@@ -1383,7 +1395,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!dp83640->hwts_rx_en)
return false;
+ if ((type & dp83640->version) == 0 || (type & dp83640->layer) == 0)
+ return false;
+
spin_lock_irqsave(&dp83640->rx_lock, flags);
+ prune_rx_ts(dp83640);
list_for_each_safe(this, next, &dp83640->rxts) {
rxts = list_entry(this, struct rxts, list);
if (match(skb, type, rxts)) {
@@ -1400,9 +1416,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!shhwtstamps) {
skb_info->ptp_type = type;
- skb_info->tmo = jiffies + 2;
+ skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
skb_queue_tail(&dp83640->rx_queue, skb);
- schedule_work(&dp83640->ts_work);
+ schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
+ } else {
+ netif_rx_ni(skb);
}
return true;
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
new file mode 100644
index 000000000000..5ce9bef54468
--- /dev/null
+++ b/drivers/net/phy/dp83848.c
@@ -0,0 +1,99 @@
+/*
+ * Driver for the Texas Instruments DP83848 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/module.h>
+#include <linux/phy.h>
+
+#define DP83848_PHY_ID 0x20005c90
+
+/* Registers */
+#define DP83848_MICR 0x11
+#define DP83848_MISR 0x12
+
+/* MICR Register Fields */
+#define DP83848_MICR_INT_OE BIT(0) /* Interrupt Output Enable */
+#define DP83848_MICR_INTEN BIT(1) /* Interrupt Enable */
+
+/* MISR Register Fields */
+#define DP83848_MISR_RHF_INT_EN BIT(0) /* Receive Error Counter */
+#define DP83848_MISR_FHF_INT_EN BIT(1) /* False Carrier Counter */
+#define DP83848_MISR_ANC_INT_EN BIT(2) /* Auto-negotiation complete */
+#define DP83848_MISR_DUP_INT_EN BIT(3) /* Duplex Status */
+#define DP83848_MISR_SPD_INT_EN BIT(4) /* Speed status */
+#define DP83848_MISR_LINK_INT_EN BIT(5) /* Link status */
+#define DP83848_MISR_ED_INT_EN BIT(6) /* Energy detect */
+#define DP83848_MISR_LQM_INT_EN BIT(7) /* Link Quality Monitor */
+
+static int dp83848_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, DP83848_MISR);
+
+ return err < 0 ? err : 0;
+}
+
+static int dp83848_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ err = phy_write(phydev, DP83848_MICR,
+ DP83848_MICR_INT_OE |
+ DP83848_MICR_INTEN);
+ if (err < 0)
+ return err;
+
+ return phy_write(phydev, DP83848_MISR,
+ DP83848_MISR_ANC_INT_EN |
+ DP83848_MISR_DUP_INT_EN |
+ DP83848_MISR_SPD_INT_EN |
+ DP83848_MISR_LINK_INT_EN);
+ }
+
+ return phy_write(phydev, DP83848_MICR, 0x0);
+}
+
+static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
+ { DP83848_PHY_ID, 0xfffffff0 },
+ { }
+};
+MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
+
+static struct phy_driver dp83848_driver[] = {
+ {
+ .phy_id = DP83848_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "TI DP83848",
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+
+ .soft_reset = genphy_soft_reset,
+ .config_init = genphy_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+
+ /* IRQ related */
+ .ack_interrupt = dp83848_ack_interrupt,
+ .config_intr = dp83848_config_intr,
+
+ .driver = { .owner = THIS_MODULE, },
+ },
+};
+module_phy_driver(dp83848_driver);
+
+MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 5de8d5827536..0240552b50f3 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -1154,6 +1154,21 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
+ .phy_id = MARVELL_PHY_ID_88E1540,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+ .name = "Marvell 88E1540",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &m88e1510_config_aneg,
+ .read_status = &marvell_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .did_interrupt = &m88e1121_did_interrupt,
+ .resume = &genphy_resume,
+ .suspend = &genphy_suspend,
+ .driver = { .owner = THIS_MODULE },
+ },
+ {
.phy_id = MARVELL_PHY_ID_88E3016,
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E3016",
@@ -1186,6 +1201,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
{ MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK },
{ MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK },
{ MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
{ MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
{ }
};
diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c
new file mode 100644
index 000000000000..c0b4e65267af
--- /dev/null
+++ b/drivers/net/phy/mdio-bcm-iproc.c
@@ -0,0 +1,213 @@
+/*
+ * 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>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#define IPROC_GPHY_MDCDIV 0x1a
+
+#define MII_CTRL_OFFSET 0x000
+
+#define MII_CTRL_DIV_SHIFT 0
+#define MII_CTRL_PRE_SHIFT 7
+#define MII_CTRL_BUSY_SHIFT 8
+
+#define MII_DATA_OFFSET 0x004
+#define MII_DATA_MASK 0xffff
+#define MII_DATA_TA_SHIFT 16
+#define MII_DATA_TA_VAL 2
+#define MII_DATA_RA_SHIFT 18
+#define MII_DATA_PA_SHIFT 23
+#define MII_DATA_OP_SHIFT 28
+#define MII_DATA_OP_WRITE 1
+#define MII_DATA_OP_READ 2
+#define MII_DATA_SB_SHIFT 30
+
+struct iproc_mdio_priv {
+ struct mii_bus *mii_bus;
+ void __iomem *base;
+};
+
+static inline int iproc_mdio_wait_for_idle(void __iomem *base)
+{
+ u32 val;
+ unsigned int timeout = 1000; /* loop for 1s */
+
+ do {
+ val = readl(base + MII_CTRL_OFFSET);
+ if ((val & BIT(MII_CTRL_BUSY_SHIFT)) == 0)
+ return 0;
+
+ usleep_range(1000, 2000);
+ } while (timeout--);
+
+ return -ETIMEDOUT;
+}
+
+static inline void iproc_mdio_config_clk(void __iomem *base)
+{
+ u32 val;
+
+ val = (IPROC_GPHY_MDCDIV << MII_CTRL_DIV_SHIFT) |
+ BIT(MII_CTRL_PRE_SHIFT);
+ writel(val, base + MII_CTRL_OFFSET);
+}
+
+static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+ struct iproc_mdio_priv *priv = bus->priv;
+ u32 cmd;
+ int rc;
+
+ rc = iproc_mdio_wait_for_idle(priv->base);
+ if (rc)
+ return rc;
+
+ iproc_mdio_config_clk(priv->base);
+
+ /* Prepare the read operation */
+ cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
+ (reg << MII_DATA_RA_SHIFT) |
+ (phy_id << MII_DATA_PA_SHIFT) |
+ BIT(MII_DATA_SB_SHIFT) |
+ (MII_DATA_OP_READ << MII_DATA_OP_SHIFT);
+
+ writel(cmd, priv->base + MII_DATA_OFFSET);
+
+ rc = iproc_mdio_wait_for_idle(priv->base);
+ if (rc)
+ return rc;
+
+ cmd = readl(priv->base + MII_DATA_OFFSET) & MII_DATA_MASK;
+
+ return cmd;
+}
+
+static int iproc_mdio_write(struct mii_bus *bus, int phy_id,
+ int reg, u16 val)
+{
+ struct iproc_mdio_priv *priv = bus->priv;
+ u32 cmd;
+ int rc;
+
+ rc = iproc_mdio_wait_for_idle(priv->base);
+ if (rc)
+ return rc;
+
+ iproc_mdio_config_clk(priv->base);
+
+ /* Prepare the write operation */
+ cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
+ (reg << MII_DATA_RA_SHIFT) |
+ (phy_id << MII_DATA_PA_SHIFT) |
+ BIT(MII_DATA_SB_SHIFT) |
+ (MII_DATA_OP_WRITE << MII_DATA_OP_SHIFT) |
+ ((u32)(val) & MII_DATA_MASK);
+
+ writel(cmd, priv->base + MII_DATA_OFFSET);
+
+ rc = iproc_mdio_wait_for_idle(priv->base);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static int iproc_mdio_probe(struct platform_device *pdev)
+{
+ struct iproc_mdio_priv *priv;
+ struct mii_bus *bus;
+ struct resource *res;
+ int rc;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->base)) {
+ dev_err(&pdev->dev, "failed to ioremap register\n");
+ return PTR_ERR(priv->base);
+ }
+
+ priv->mii_bus = mdiobus_alloc();
+ if (!priv->mii_bus) {
+ dev_err(&pdev->dev, "MDIO bus alloc failed\n");
+ return -ENOMEM;
+ }
+
+ bus = priv->mii_bus;
+ bus->priv = priv;
+ bus->name = "iProc MDIO bus";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
+ bus->parent = &pdev->dev;
+ bus->read = iproc_mdio_read;
+ bus->write = iproc_mdio_write;
+
+ rc = of_mdiobus_register(bus, pdev->dev.of_node);
+ if (rc) {
+ dev_err(&pdev->dev, "MDIO bus registration failed\n");
+ goto err_iproc_mdio;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ dev_info(&pdev->dev, "Broadcom iProc MDIO bus at 0x%p\n", priv->base);
+
+ return 0;
+
+err_iproc_mdio:
+ mdiobus_free(bus);
+ return rc;
+}
+
+static int iproc_mdio_remove(struct platform_device *pdev)
+{
+ struct iproc_mdio_priv *priv = platform_get_drvdata(pdev);
+
+ mdiobus_unregister(priv->mii_bus);
+ mdiobus_free(priv->mii_bus);
+
+ return 0;
+}
+
+static const struct of_device_id iproc_mdio_of_match[] = {
+ { .compatible = "brcm,iproc-mdio", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, iproc_mdio_of_match);
+
+static struct platform_driver iproc_mdio_driver = {
+ .driver = {
+ .name = "iproc-mdio",
+ .of_match_table = iproc_mdio_of_match,
+ },
+ .probe = iproc_mdio_probe,
+ .remove = iproc_mdio_remove,
+};
+
+module_platform_driver(iproc_mdio_driver);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom iProc MDIO bus controller");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:iproc-mdio");
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 3bc9f03349f3..95f51d7267b3 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
-#include <linux/mdio-gpio.h>
+#include <linux/platform_data/mdio-gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_mdio.h>
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 2377c1341172..7fde454fbc4f 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -113,12 +113,14 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
if (!iprop || len != sizeof(uint32_t)) {
dev_err(&pdev->dev, "mdio-mux child node %s is "
"missing a 'reg' property\n", np2->full_name);
+ of_node_put(np2);
return -ENODEV;
}
if (be32_to_cpup(iprop) & ~s->mask) {
dev_err(&pdev->dev, "mdio-mux child node %s has "
"a 'reg' value with unmasked bits\n",
np2->full_name);
+ of_node_put(np2);
return -ENODEV;
}
}
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 280c7c311f72..908e8d486342 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -144,6 +144,7 @@ int mdio_mux_init(struct device *dev,
dev_err(dev,
"Error: Failed to allocate memory for child\n");
ret_val = -ENOMEM;
+ of_node_put(child_bus_node);
break;
}
cb->bus_number = v;
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 12f44c53cc8e..88cb4592b6fb 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -372,6 +372,33 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
EXPORT_SYMBOL(mdiobus_scan);
/**
+ * mdiobus_read_nested - Nested version of the mdiobus_read function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @regnum: register number to read
+ *
+ * In case of nested MDIO bus access avoid lockdep false positives by
+ * using mutex_lock_nested().
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
+{
+ int retval;
+
+ BUG_ON(in_interrupt());
+
+ mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
+ retval = bus->read(bus, addr, regnum);
+ mutex_unlock(&bus->mdio_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(mdiobus_read_nested);
+
+/**
* mdiobus_read - Convenience function for reading a given MII mgmt register
* @bus: the mii_bus struct
* @addr: the phy address
@@ -396,6 +423,34 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
EXPORT_SYMBOL(mdiobus_read);
/**
+ * mdiobus_write_nested - Nested version of the mdiobus_write function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * In case of nested MDIO bus access avoid lockdep false positives by
+ * using mutex_lock_nested().
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)
+{
+ int err;
+
+ BUG_ON(in_interrupt());
+
+ mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
+ err = bus->write(bus, addr, regnum, val);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_write_nested);
+
+/**
* mdiobus_write - Convenience function for writing a given MII mgmt register
* @bus: the mii_bus struct
* @addr: the phy address
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 499185eaf413..cf6312fafea5 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -514,6 +514,27 @@ static int ksz8873mll_read_status(struct phy_device *phydev)
return 0;
}
+static int ksz9031_read_status(struct phy_device *phydev)
+{
+ int err;
+ int regval;
+
+ err = genphy_read_status(phydev);
+ if (err)
+ return err;
+
+ /* Make sure the PHY is not broken. Read idle error count,
+ * and reset the PHY if it is maxed out.
+ */
+ regval = phy_read(phydev, MII_STAT1000);
+ if ((regval & 0xFF) == 0xFF) {
+ phy_init_hw(phydev);
+ phydev->link = 0;
+ }
+
+ return 0;
+}
+
static int ksz8873mll_config_aneg(struct phy_device *phydev)
{
return 0;
@@ -772,7 +793,7 @@ static struct phy_driver ksphy_driver[] = {
.driver_data = &ksz9021_type,
.config_init = ksz9031_config_init,
.config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
+ .read_status = ksz9031_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
.suspend = genphy_suspend,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index adb48abafc87..48ce6ef400fe 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -863,6 +863,9 @@ void phy_state_machine(struct work_struct *work)
needs_aneg = true;
break;
case PHY_NOLINK:
+ if (phy_interrupt_is_valid(phydev))
+ break;
+
err = phy_read_status(phydev);
if (err)
break;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f761288abe66..0bfbabad4431 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -205,6 +205,37 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
}
EXPORT_SYMBOL(phy_device_create);
+/* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers.
+ * @bus: the target MII bus
+ * @addr: PHY address on the MII bus
+ * @dev_addr: MMD address in the PHY.
+ * @devices_in_package: where to store the devices in package information.
+ *
+ * Description: reads devices in package registers of a MMD at @dev_addr
+ * from PHY at @addr on @bus.
+ *
+ * Returns: 0 on success, -EIO on failure.
+ */
+static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr,
+ u32 *devices_in_package)
+{
+ int phy_reg, reg_addr;
+
+ reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS2;
+ phy_reg = mdiobus_read(bus, addr, reg_addr);
+ if (phy_reg < 0)
+ return -EIO;
+ *devices_in_package = (phy_reg & 0xffff) << 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);
+
+ return 0;
+}
+
/**
* get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs.
* @bus: the target MII bus
@@ -223,38 +254,31 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id,
int phy_reg;
int i, reg_addr;
const int num_ids = ARRAY_SIZE(c45_ids->device_ids);
+ u32 *devs = &c45_ids->devices_in_package;
- /* Find first non-zero Devices In package. Device
- * zero is reserved, so don't probe it.
+ /* Find first non-zero Devices In package. Device zero is reserved
+ * for 802.3 c45 complied PHYs, so don't probe it at first.
*/
- for (i = 1;
- i < num_ids && c45_ids->devices_in_package == 0;
- i++) {
-retry: reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS2;
- phy_reg = mdiobus_read(bus, addr, reg_addr);
+ for (i = 1; i < num_ids && *devs == 0; i++) {
+ phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, devs);
if (phy_reg < 0)
return -EIO;
- c45_ids->devices_in_package = (phy_reg & 0xffff) << 16;
- reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS1;
- phy_reg = mdiobus_read(bus, addr, reg_addr);
- if (phy_reg < 0)
- return -EIO;
- c45_ids->devices_in_package |= (phy_reg & 0xffff);
-
- if ((c45_ids->devices_in_package & 0x1fffffff) == 0x1fffffff) {
- if (i) {
- /* If mostly Fs, there is no device there,
- * then let's continue to probe more, as some
- * 10G PHYs have zero Devices In package,
- * e.g. Cortina CS4315/CS4340 PHY.
- */
- i = 0;
- goto retry;
- } else {
- /* no device there, let's get out of here */
+ if ((*devs & 0x1fffffff) == 0x1fffffff) {
+ /* If mostly Fs, there is no device there,
+ * then let's continue to probe more, as some
+ * 10G PHYs have zero Devices In package,
+ * e.g. Cortina CS4315/CS4340 PHY.
+ */
+ phy_reg = get_phy_c45_devs_in_pkg(bus, addr, 0, devs);
+ if (phy_reg < 0)
+ return -EIO;
+ /* no device there, let's get out of here */
+ if ((*devs & 0x1fffffff) == 0x1fffffff) {
*phy_id = 0xffffffff;
return 0;
+ } else {
+ break;
}
}
}
@@ -1239,6 +1263,44 @@ static int gen10g_resume(struct phy_device *phydev)
return 0;
}
+static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
+{
+ /* The default values for phydev->supported are provided by the PHY
+ * driver "features" member, we want to reset to sane defaults first
+ * before supporting higher speeds.
+ */
+ phydev->supported &= PHY_DEFAULT_FEATURES;
+
+ switch (max_speed) {
+ default:
+ return -ENOTSUPP;
+ case SPEED_1000:
+ phydev->supported |= PHY_1000BT_FEATURES;
+ /* fall through */
+ case SPEED_100:
+ phydev->supported |= PHY_100BT_FEATURES;
+ /* fall through */
+ case SPEED_10:
+ phydev->supported |= PHY_10BT_FEATURES;
+ }
+
+ 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;
+
+ phydev->advertising = phydev->supported;
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_set_max_speed);
+
static void of_set_phy_supported(struct phy_device *phydev)
{
struct device_node *node = phydev->dev.of_node;
@@ -1250,25 +1312,8 @@ static void of_set_phy_supported(struct phy_device *phydev)
if (!node)
return;
- if (!of_property_read_u32(node, "max-speed", &max_speed)) {
- /* The default values for phydev->supported are provided by the PHY
- * driver "features" member, we want to reset to sane defaults fist
- * before supporting higher speeds.
- */
- phydev->supported &= PHY_DEFAULT_FEATURES;
-
- switch (max_speed) {
- default:
- return;
-
- case SPEED_1000:
- phydev->supported |= PHY_1000BT_FEATURES;
- case SPEED_100:
- phydev->supported |= PHY_100BT_FEATURES;
- case SPEED_10:
- phydev->supported |= PHY_10BT_FEATURES;
- }
- }
+ if (!of_property_read_u32(node, "max-speed", &max_speed))
+ __set_phy_supported(phydev, max_speed);
}
/**
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 70b08958763a..dc2da8770918 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -43,16 +43,25 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
static int smsc_phy_config_init(struct phy_device *phydev)
{
+ int __maybe_unused len;
+ struct device *dev __maybe_unused = &phydev->dev;
+ struct device_node *of_node __maybe_unused = dev->of_node;
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ int enable_energy = 1;
if (rc < 0)
return rc;
- /* Enable energy detect mode for this SMSC Transceivers */
- rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
- rc | MII_LAN83C185_EDPWRDOWN);
- if (rc < 0)
- return rc;
+ if (of_find_property(of_node, "smsc,disable-energy-detect", &len))
+ enable_energy = 0;
+
+ if (enable_energy) {
+ /* Enable energy detect mode for this SMSC Transceivers */
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+ rc | MII_LAN83C185_EDPWRDOWN);
+ if (rc < 0)
+ return rc;
+ }
return smsc_phy_ack_interrupt(phydev);
}
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
index f091d691cf6f..c72c42206850 100644
--- a/drivers/net/phy/spi_ks8995.c
+++ b/drivers/net/phy/spi_ks8995.c
@@ -343,7 +343,6 @@ static int ks8995_remove(struct spi_device *spi)
static struct spi_driver ks8995_driver = {
.driver = {
.name = "spi-ks8995",
- .owner = THIS_MODULE,
},
.probe = ks8995_probe,
.remove = ks8995_remove,
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index 91e1bec6079f..07463fcca212 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -112,20 +112,7 @@ static struct phy_driver teranetics_driver[] = {
},
};
-static int __init teranetics_init(void)
-{
- return phy_drivers_register(teranetics_driver,
- ARRAY_SIZE(teranetics_driver));
-}
-
-static void __exit teranetics_exit(void)
-{
- return phy_drivers_unregister(teranetics_driver,
- ARRAY_SIZE(teranetics_driver));
-}
-
-module_init(teranetics_init);
-module_exit(teranetics_exit);
+module_phy_driver(teranetics_driver);
static struct mdio_device_id __maybe_unused teranetics_tbl[] = {
{ PHY_ID_TN2020, 0xffffffff },
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 76cad712ddb2..dd295dbaa074 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -66,6 +66,7 @@
#define PHY_ID_VSC8244 0x000fc6c0
#define PHY_ID_VSC8514 0x00070670
#define PHY_ID_VSC8574 0x000704a0
+#define PHY_ID_VSC8601 0x00070420
#define PHY_ID_VSC8662 0x00070660
#define PHY_ID_VSC8221 0x000fc550
#define PHY_ID_VSC8211 0x000fc4b0
@@ -133,7 +134,8 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
(phydev->drv->phy_id == PHY_ID_VSC8234 ||
phydev->drv->phy_id == PHY_ID_VSC8244 ||
phydev->drv->phy_id == PHY_ID_VSC8514 ||
- phydev->drv->phy_id == PHY_ID_VSC8574) ?
+ phydev->drv->phy_id == PHY_ID_VSC8574 ||
+ phydev->drv->phy_id == PHY_ID_VSC8601) ?
MII_VSC8244_IMASK_MASK :
MII_VSC8221_IMASK_MASK);
else {
@@ -272,6 +274,18 @@ static struct phy_driver vsc82xx_driver[] = {
.config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
+ .phy_id = PHY_ID_VSC8601,
+ .name = "Vitesse VSC8601",
+ .phy_id_mask = 0x000ffff0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &genphy_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+}, {
.phy_id = PHY_ID_VSC8662,
.name = "Vitesse VSC8662",
.phy_id_mask = 0x000ffff0,
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index ed00446759b2..9a863c6a6a33 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -721,10 +721,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
val &= 0xffff;
}
vj = slhc_init(val2+1, val+1);
- if (!vj) {
- netdev_err(ppp->dev,
- "PPP: no memory (VJ compressor)\n");
- err = -ENOMEM;
+ if (IS_ERR(vj)) {
+ err = PTR_ERR(vj);
break;
}
ppp_lock(ppp);
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 3837ae344f63..5e0b43283bce 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_device *dev)
if (po->pppoe_dev == dev &&
sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
pppox_unbind_sock(sk);
- sk->sk_state = PPPOX_ZOMBIE;
sk->sk_state_change(sk);
po->pppoe_dev = NULL;
dev_put(dev);
@@ -590,7 +589,7 @@ static int pppoe_release(struct socket *sock)
po = pppox_sk(sk);
- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+ if (po->pppoe_dev) {
dev_put(po->pppoe_dev);
po->pppoe_dev = NULL;
}
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 686f37daa262..fc69e41d0950 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -169,6 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
{
struct sock *sk = (struct sock *) chan->private;
struct pppox_sock *po = pppox_sk(sk);
+ struct net *net = sock_net(sk);
struct pptp_opt *opt = &po->proto.pptp;
struct pptp_gre_header *hdr;
unsigned int header_len = sizeof(*hdr);
@@ -187,7 +188,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
if (sk_pppox(po)->sk_state & PPPOX_DEAD)
goto tx_error;
- rt = ip_route_output_ports(sock_net(sk), &fl4, NULL,
+ rt = ip_route_output_ports(net, &fl4, NULL,
opt->dst_addr.sin_addr.s_addr,
opt->src_addr.sin_addr.s_addr,
0, 0, IPPROTO_GRE,
@@ -279,10 +280,10 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
nf_reset(skb);
skb->ip_summed = CHECKSUM_NONE;
- ip_select_ident(sock_net(sk), skb, NULL);
+ ip_select_ident(net, skb, NULL);
ip_send_check(iph);
- ip_local_out(skb);
+ ip_local_out(net, skb->sk, skb);
return 1;
tx_error:
diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
index 079f7adfcde5..27ed25252aac 100644
--- a/drivers/net/slip/slhc.c
+++ b/drivers/net/slip/slhc.c
@@ -84,8 +84,9 @@ static long decode(unsigned char **cpp);
static unsigned char * put16(unsigned char *cp, unsigned short x);
static unsigned short pull16(unsigned char **cpp);
-/* Initialize compression data structure
+/* Allocate compression data structure
* slots must be in range 0 to 255 (zero meaning no compression)
+ * Returns pointer to structure or ERR_PTR() on error.
*/
struct slcompress *
slhc_init(int rslots, int tslots)
@@ -94,11 +95,14 @@ slhc_init(int rslots, int tslots)
register struct cstate *ts;
struct slcompress *comp;
+ if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255)
+ return ERR_PTR(-EINVAL);
+
comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
if (! comp)
goto out_fail;
- if ( rslots > 0 && rslots < 256 ) {
+ if (rslots > 0) {
size_t rsize = rslots * sizeof(struct cstate);
comp->rstate = kzalloc(rsize, GFP_KERNEL);
if (! comp->rstate)
@@ -106,7 +110,7 @@ slhc_init(int rslots, int tslots)
comp->rslot_limit = rslots - 1;
}
- if ( tslots > 0 && tslots < 256 ) {
+ if (tslots > 0) {
size_t tsize = tslots * sizeof(struct cstate);
comp->tstate = kzalloc(tsize, GFP_KERNEL);
if (! comp->tstate)
@@ -141,7 +145,7 @@ out_free2:
out_free:
kfree(comp);
out_fail:
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 05387b1e2e95..a17d86a57734 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -164,7 +164,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu)
if (cbuff == NULL)
goto err_exit;
slcomp = slhc_init(16, 16);
- if (slcomp == NULL)
+ if (IS_ERR(slcomp))
goto err_exit;
#endif
spin_lock_bh(&sl->lock);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 976aa9704297..b1878faea397 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -858,7 +858,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
goto drop;
- if (skb->sk) {
+ if (skb->sk && sk_fullsock(skb->sk)) {
sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags);
sw_tx_timestamp(skb);
}
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index fbb9325d1f6e..7f83504dfa69 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -109,6 +109,8 @@ config USB_RTL8152
config USB_LAN78XX
tristate "Microchip LAN78XX Based USB Ethernet Adapters"
select MII
+ select PHYLIB
+ select MICROCHIP_PHY
help
This option adds support for Microchip LAN78XX based USB 2
& USB 3 10/100/1000 Ethernet adapters.
@@ -164,6 +166,7 @@ config USB_NET_AX8817X
* Aten UC210T
* ASIX AX88172
* Billionton Systems, USB2AR
+ * Billionton Systems, GUSB2AM-1G-B
* Buffalo LUA-U2-KTX
* Corega FEther USB2-TX
* D-Link DUB-E100
@@ -541,7 +544,7 @@ config USB_NET_INT51X1
config USB_CDC_PHONET
tristate "CDC Phonet support"
- depends on PHONET
+ depends on PHONET && USB_USBNET
help
Choose this option to support the Phonet interface to a Nokia
cellular modem, as found on most Nokia handsets with the
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index 5d049d00c2d7..a2d3ea6efb20 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -168,7 +168,7 @@ struct asix_data {
struct asix_rx_fixup_info {
struct sk_buff *ax_skb;
u32 header;
- u16 size;
+ u16 remaining;
bool split_head;
};
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 75d6f26729a3..bd9acff1eb7b 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -54,69 +54,101 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
struct asix_rx_fixup_info *rx)
{
int offset = 0;
+ u16 size;
+
+ /* When an Ethernet frame spans multiple URB socket buffers,
+ * do a sanity test for the Data header synchronisation.
+ * Attempt to detect the situation of the previous socket buffer having
+ * been truncated or a socket buffer was missing. These situations
+ * cause a discontinuity in the data stream and therefore need to avoid
+ * appending bad data to the end of the current netdev socket buffer.
+ * Also avoid unnecessarily discarding a good current netdev socket
+ * buffer.
+ */
+ if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
+ offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
+ rx->header = get_unaligned_le32(skb->data + offset);
+ offset = 0;
+
+ size = (u16)(rx->header & 0x7ff);
+ if (size != ((~rx->header >> 16) & 0x7ff)) {
+ netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n",
+ rx->remaining);
+ if (rx->ax_skb) {
+ kfree_skb(rx->ax_skb);
+ rx->ax_skb = NULL;
+ /* Discard the incomplete netdev Ethernet frame
+ * and assume the Data header is at the start of
+ * the current URB socket buffer.
+ */
+ }
+ rx->remaining = 0;
+ }
+ }
while (offset + sizeof(u16) <= skb->len) {
- u16 remaining = 0;
+ u16 copy_length;
unsigned char *data;
- if (!rx->size) {
- if ((skb->len - offset == sizeof(u16)) ||
- rx->split_head) {
- if(!rx->split_head) {
- rx->header = get_unaligned_le16(
- skb->data + offset);
- rx->split_head = true;
- offset += sizeof(u16);
- break;
- } else {
- rx->header |= (get_unaligned_le16(
- skb->data + offset)
- << 16);
- rx->split_head = false;
- offset += sizeof(u16);
- }
+ if (!rx->remaining) {
+ if (skb->len - offset == sizeof(u16)) {
+ rx->header = get_unaligned_le16(
+ skb->data + offset);
+ rx->split_head = true;
+ offset += sizeof(u16);
+ break;
+ }
+
+ if (rx->split_head == true) {
+ rx->header |= (get_unaligned_le16(
+ skb->data + offset) << 16);
+ rx->split_head = false;
+ offset += sizeof(u16);
} else {
rx->header = get_unaligned_le32(skb->data +
offset);
offset += sizeof(u32);
}
- /* get the packet length */
- rx->size = (u16) (rx->header & 0x7ff);
- if (rx->size != ((~rx->header >> 16) & 0x7ff)) {
+ /* take frame length from Data header 32-bit word */
+ size = (u16)(rx->header & 0x7ff);
+ if (size != ((~rx->header >> 16) & 0x7ff)) {
netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
rx->header, offset);
- rx->size = 0;
return 0;
}
- rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
- rx->size);
- if (!rx->ax_skb)
+ if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
+ netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
+ size);
return 0;
- }
+ }
- if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
- netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
- rx->size);
- kfree_skb(rx->ax_skb);
- rx->ax_skb = NULL;
- rx->size = 0U;
+ /* Sometimes may fail to get a netdev socket buffer but
+ * continue to process the URB socket buffer so that
+ * synchronisation of the Ethernet frame Data header
+ * word is maintained.
+ */
+ rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
- return 0;
+ rx->remaining = size;
}
- if (rx->size > skb->len - offset) {
- remaining = rx->size - (skb->len - offset);
- rx->size = skb->len - offset;
+ if (rx->remaining > skb->len - offset) {
+ copy_length = skb->len - offset;
+ rx->remaining -= copy_length;
+ } else {
+ copy_length = rx->remaining;
+ rx->remaining = 0;
}
- data = skb_put(rx->ax_skb, rx->size);
- memcpy(data, skb->data + offset, rx->size);
- if (!remaining)
- usbnet_skb_return(dev, rx->ax_skb);
+ if (rx->ax_skb) {
+ data = skb_put(rx->ax_skb, copy_length);
+ memcpy(data, skb->data + offset, copy_length);
+ if (!rx->remaining)
+ usbnet_skb_return(dev, rx->ax_skb);
+ }
- offset += (rx->size + 1) & 0xfffe;
- rx->size = remaining;
+ offset += (copy_length + 1) & 0xfffe;
}
if (skb->len != offset) {
@@ -556,7 +588,6 @@ void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
usbnet_get_drvinfo(net, info);
strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
- info->eedump_len = AX_EEPROM_LEN;
}
int asix_set_mac_address(struct net_device *net, void *p)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 1173a24feda3..5cabefc23494 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -959,6 +959,10 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x08dd, 0x90ff),
.driver_info = (unsigned long) &ax8817x_info,
}, {
+ // Billionton Systems, GUSB2AM-1G-B
+ USB_DEVICE(0x08dd, 0x0114),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
// ATEN UC210T
USB_DEVICE (0x0557, 0x2009),
.driver_info = (unsigned long) &ax8817x_info,
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 415ce8b882c6..ff2270ead2e6 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -340,32 +340,13 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i
u8 *data;
int phonet = 0;
int len, err;
+ struct usb_cdc_parsed_header hdr;
data = intf->altsetting->extra;
len = intf->altsetting->extralen;
- while (len >= 3) {
- u8 dlen = data[0];
- if (dlen < 3)
- return -EINVAL;
-
- /* bDescriptorType */
- if (data[1] == USB_DT_CS_INTERFACE) {
- /* bDescriptorSubType */
- switch (data[2]) {
- case USB_CDC_UNION_TYPE:
- if (union_header || dlen < 5)
- break;
- union_header =
- (struct usb_cdc_union_desc *)data;
- break;
- case 0xAB:
- phonet = 1;
- break;
- }
- }
- data += dlen;
- len -= dlen;
- }
+ cdc_parse_cdc_header(&hdr, intf, data, len);
+ union_header = hdr.usb_cdc_union_desc;
+ phonet = hdr.phonet_magic_present;
if (!union_header || !phonet)
return -EINVAL;
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 35a2bffe848a..3da70bf9936a 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -112,8 +112,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
int rndis;
bool android_rndis_quirk = false;
struct usb_driver *driver = driver_of(intf);
- struct usb_cdc_mdlm_desc *desc = NULL;
- struct usb_cdc_mdlm_detail_desc *detail = NULL;
+ struct usb_cdc_parsed_header header;
if (sizeof(dev->data) < sizeof(*info))
return -EDOM;
@@ -155,156 +154,89 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
memset(info, 0, sizeof(*info));
info->control = intf;
- while (len > 3) {
- if (buf[1] != USB_DT_CS_INTERFACE)
- goto next_desc;
-
- /* use bDescriptorSubType to identify the CDC descriptors.
- * We expect devices with CDC header and union descriptors.
- * For CDC Ethernet we need the ethernet descriptor.
- * For RNDIS, ignore two (pointless) CDC modem descriptors
- * in favor of a complicated OID-based RPC scheme doing what
- * CDC Ethernet achieves with a simple descriptor.
- */
- switch (buf[2]) {
- case USB_CDC_HEADER_TYPE:
- if (info->header) {
- dev_dbg(&intf->dev, "extra CDC header\n");
- goto bad_desc;
- }
- info->header = (void *) buf;
- if (info->header->bLength != sizeof(*info->header)) {
- dev_dbg(&intf->dev, "CDC header len %u\n",
- info->header->bLength);
- goto bad_desc;
- }
- break;
- case USB_CDC_ACM_TYPE:
- /* paranoia: disambiguate a "real" vendor-specific
- * modem interface from an RNDIS non-modem.
- */
- if (rndis) {
- struct usb_cdc_acm_descriptor *acm;
-
- acm = (void *) buf;
- if (acm->bmCapabilities) {
- dev_dbg(&intf->dev,
- "ACM capabilities %02x, "
- "not really RNDIS?\n",
- acm->bmCapabilities);
- goto bad_desc;
- }
- }
- break;
- case USB_CDC_UNION_TYPE:
- if (info->u) {
- dev_dbg(&intf->dev, "extra CDC union\n");
- goto bad_desc;
- }
- info->u = (void *) buf;
- if (info->u->bLength != sizeof(*info->u)) {
- dev_dbg(&intf->dev, "CDC union len %u\n",
- info->u->bLength);
- goto bad_desc;
- }
-
- /* we need a master/control interface (what we're
- * 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);
- if (!info->control || !info->data) {
- dev_dbg(&intf->dev,
- "master #%u/%p slave #%u/%p\n",
- info->u->bMasterInterface0,
- info->control,
- info->u->bSlaveInterface0,
- info->data);
- /* fall back to hard-wiring for RNDIS */
- if (rndis) {
- android_rndis_quirk = true;
- goto next_desc;
- }
- goto bad_desc;
- }
- if (info->control != intf) {
- dev_dbg(&intf->dev, "bogus CDC Union\n");
- /* Ambit USB Cable Modem (and maybe others)
- * interchanges master and slave interface.
- */
- if (info->data == intf) {
- info->data = info->control;
- info->control = intf;
- } else
- goto bad_desc;
- }
-
- /* some devices merge these - skip class check */
- if (info->control == info->data)
- goto next_desc;
-
- /* 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);
- goto bad_desc;
- }
- break;
- case USB_CDC_ETHERNET_TYPE:
- if (info->ether) {
- dev_dbg(&intf->dev, "extra CDC ether\n");
- goto bad_desc;
- }
- info->ether = (void *) buf;
- if (info->ether->bLength != sizeof(*info->ether)) {
- dev_dbg(&intf->dev, "CDC ether len %u\n",
- info->ether->bLength);
- goto bad_desc;
- }
- dev->hard_mtu = le16_to_cpu(
- info->ether->wMaxSegmentSize);
- /* because of Zaurus, we may be ignoring the host
- * side link address we were given.
- */
- break;
- case USB_CDC_MDLM_TYPE:
- if (desc) {
- dev_dbg(&intf->dev, "extra MDLM descriptor\n");
- goto bad_desc;
- }
-
- desc = (void *)buf;
-
- if (desc->bLength != sizeof(*desc))
- goto bad_desc;
-
- if (memcmp(&desc->bGUID, mbm_guid, 16))
- goto bad_desc;
- break;
- case USB_CDC_MDLM_DETAIL_TYPE:
- if (detail) {
- dev_dbg(&intf->dev, "extra MDLM detail descriptor\n");
- goto bad_desc;
- }
-
- detail = (void *)buf;
-
- if (detail->bGuidDescriptorType == 0) {
- if (detail->bLength < (sizeof(*detail) + 1))
- goto bad_desc;
- } else
- goto bad_desc;
- break;
+
+ cdc_parse_cdc_header(&header, intf, buf, len);
+
+ info->u = header.usb_cdc_union_desc;
+ info->header = header.usb_cdc_header_desc;
+ info->ether = header.usb_cdc_ether_desc;
+ /* we need a master/control interface (what we're
+ * 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);
+ if (!info->control || !info->data) {
+ dev_dbg(&intf->dev,
+ "master #%u/%p slave #%u/%p\n",
+ info->u->bMasterInterface0,
+ info->control,
+ info->u->bSlaveInterface0,
+ info->data);
+ /* fall back to hard-wiring for RNDIS */
+ if (rndis) {
+ android_rndis_quirk = true;
+ goto skip;
}
-next_desc:
- len -= buf[0]; /* bLength */
- buf += buf[0];
+ goto bad_desc;
+ }
+ if (info->control != intf) {
+ dev_dbg(&intf->dev, "bogus CDC Union\n");
+ /* Ambit USB Cable Modem (and maybe others)
+ * interchanges master and slave interface.
+ */
+ if (info->data == intf) {
+ info->data = info->control;
+ info->control = intf;
+ } else
+ goto bad_desc;
+ }
+
+ /* some devices merge these - skip class check */
+ if (info->control == info->data)
+ goto skip;
+
+ /* 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);
+ 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 (header.usb_cdc_ether_desc) {
+ dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize);
+ /* because of Zaurus, we may be ignoring the host
+ * side link address we were given.
+ */
+ }
+
+ if (header.usb_cdc_mdlm_desc &&
+ memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
+ dev_dbg(&intf->dev, "GUID doesn't match\n");
+ goto bad_desc;
}
+ if (header.usb_cdc_mdlm_detail_desc &&
+ header.usb_cdc_mdlm_detail_desc->bLength <
+ (sizeof(struct usb_cdc_mdlm_detail_desc) + 1)) {
+ dev_dbg(&intf->dev, "Descriptor too short\n");
+ goto bad_desc;
+ }
+
+
+
/* Microsoft ActiveSync based and some regular RNDIS devices lack the
* CDC descriptors, so we'll hard-wire the interfaces and not check
* for descriptors.
@@ -764,6 +696,11 @@ static const struct usb_device_id products[] = {
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
.driver_info = (kernel_ulong_t) &wwan_info,
}, {
+ /* Dell DW5580 modules */
+ USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = (kernel_ulong_t)&wwan_info,
+}, {
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index efc18e05af0a..bbde9884ab8a 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -342,7 +342,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
in6_dev_put(in6_dev);
/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
- ipv6_stub->ndisc_send_na(netdev, NULL, &iph->saddr, &msg->target,
+ ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target,
is_router /* router */,
true /* solicited */,
false /* override */,
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index db40175b1a0b..a187f08113ec 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -698,6 +698,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
int len;
int temp;
u8 iface_no;
+ struct usb_cdc_parsed_header hdr;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -722,66 +723,14 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
len = intf->cur_altsetting->extralen;
/* parse through descriptors associated with control interface */
- while ((len > 0) && (buf[0] > 2) && (buf[0] <= len)) {
-
- if (buf[1] != USB_DT_CS_INTERFACE)
- goto advance;
-
- switch (buf[2]) {
- case USB_CDC_UNION_TYPE:
- if (buf[0] < sizeof(*union_desc))
- break;
-
- union_desc = (const struct usb_cdc_union_desc *)buf;
- /* the master must be the interface we are probing */
- if (intf->cur_altsetting->desc.bInterfaceNumber !=
- union_desc->bMasterInterface0) {
- dev_dbg(&intf->dev, "bogus CDC Union\n");
- goto error;
- }
- ctx->data = usb_ifnum_to_if(dev->udev,
- union_desc->bSlaveInterface0);
- break;
-
- case USB_CDC_ETHERNET_TYPE:
- if (buf[0] < sizeof(*(ctx->ether_desc)))
- break;
-
- ctx->ether_desc =
- (const struct usb_cdc_ether_desc *)buf;
- break;
-
- case USB_CDC_NCM_TYPE:
- if (buf[0] < sizeof(*(ctx->func_desc)))
- break;
-
- ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
- break;
-
- case USB_CDC_MBIM_TYPE:
- if (buf[0] < sizeof(*(ctx->mbim_desc)))
- break;
-
- ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf;
- break;
-
- case USB_CDC_MBIM_EXTENDED_TYPE:
- if (buf[0] < sizeof(*(ctx->mbim_extended_desc)))
- break;
-
- ctx->mbim_extended_desc =
- (const struct usb_cdc_mbim_extended_desc *)buf;
- break;
-
- default:
- break;
- }
-advance:
- /* advance to next descriptor */
- temp = buf[0];
- buf += temp;
- len -= temp;
- }
+ cdc_parse_cdc_header(&hdr, intf, buf, len);
+
+ ctx->data = usb_ifnum_to_if(dev->udev,
+ hdr.usb_cdc_union_desc->bSlaveInterface0);
+ ctx->ether_desc = hdr.usb_cdc_ether_desc;
+ ctx->func_desc = hdr.usb_cdc_ncm_desc;
+ ctx->mbim_desc = hdr.usb_cdc_mbim_desc;
+ ctx->mbim_extended_desc = hdr.usb_cdc_mbim_extended_desc;
/* some buggy devices have an IAD but no CDC Union */
if (!union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 6e9c344c7a20..0b4bdd39106b 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -258,7 +258,6 @@ static void dm9601_get_drvinfo(struct net_device *net,
{
/* Inherit standard device info */
usbnet_get_drvinfo(net, info);
- info->eedump_len = DM_EEPROM_LEN;
}
static u32 dm9601_get_link(struct net_device *net)
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 1e9cdca37014..f64b25c221e8 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -1177,12 +1177,6 @@ err_fw:
INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
usb_set_intfdata(intf, kaweth);
-#if 0
-// dma_supported() is deeply broken on almost all architectures
- if (dma_supported (dev, 0xffffffffffffffffULL))
- kaweth->net->features |= NETIF_F_HIGHDMA;
-#endif
-
SET_NETDEV_DEV(netdev, dev);
if (register_netdev(netdev) != 0) {
dev_err(dev, "Error registering netdev.\n");
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index a39518fc93aa..226668ead0d8 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -19,7 +19,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
-#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/signal.h>
@@ -31,12 +30,13 @@
#include <linux/ipv6.h>
#include <linux/mdio.h>
#include <net/ip6_checksum.h>
+#include <linux/microchipphy.h>
#include "lan78xx.h"
#define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>"
#define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices"
#define DRIVER_NAME "lan78xx"
-#define DRIVER_VERSION "1.0.0"
+#define DRIVER_VERSION "1.0.1"
#define TX_TIMEOUT_JIFFIES (5 * HZ)
#define THROTTLE_JIFFIES (HZ / 8)
@@ -57,7 +57,6 @@
#define DEFAULT_RX_CSUM_ENABLE (true)
#define DEFAULT_TSO_CSUM_ENABLE (true)
#define DEFAULT_VLAN_FILTER_ENABLE (true)
-#define INTERNAL_PHY_ID (2) /* 2: GMII */
#define TX_OVERHEAD (8)
#define RXW_PADDING 2
@@ -275,10 +274,12 @@ struct lan78xx_net {
struct timer_list delay;
unsigned long data[5];
- struct mii_if_info mii;
int link_on;
u8 mdix_ctrl;
+
+ u32 devid;
+ struct mii_bus *mdiobus;
};
/* use ethtool to change the level for any given device */
@@ -411,222 +412,6 @@ static inline u32 mii_access(int id, int index, int read)
return ret;
}
-static int lan78xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
-{
- struct lan78xx_net *dev = netdev_priv(netdev);
- u32 val, addr;
- int ret;
-
- ret = usb_autopm_get_interface(dev->intf);
- if (ret < 0)
- return ret;
-
- mutex_lock(&dev->phy_mutex);
-
- /* confirm MII not busy */
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* set the address, index & direction (read from PHY) */
- phy_id &= dev->mii.phy_id_mask;
- idx &= dev->mii.reg_num_mask;
- addr = mii_access(phy_id, idx, MII_READ);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- ret = lan78xx_read_reg(dev, MII_DATA, &val);
-
- ret = (int)(val & 0xFFFF);
-
-done:
- mutex_unlock(&dev->phy_mutex);
- usb_autopm_put_interface(dev->intf);
- return ret;
-}
-
-static void lan78xx_mdio_write(struct net_device *netdev, int phy_id,
- int idx, int regval)
-{
- struct lan78xx_net *dev = netdev_priv(netdev);
- u32 val, addr;
- int ret;
-
- if (usb_autopm_get_interface(dev->intf) < 0)
- return;
-
- mutex_lock(&dev->phy_mutex);
-
- /* confirm MII not busy */
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- val = regval;
- ret = lan78xx_write_reg(dev, MII_DATA, val);
-
- /* set the address, index & direction (write to PHY) */
- phy_id &= dev->mii.phy_id_mask;
- idx &= dev->mii.reg_num_mask;
- addr = mii_access(phy_id, idx, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
-done:
- mutex_unlock(&dev->phy_mutex);
- usb_autopm_put_interface(dev->intf);
-}
-
-static void lan78xx_mmd_write(struct net_device *netdev, int phy_id,
- int mmddev, int mmdidx, int regval)
-{
- struct lan78xx_net *dev = netdev_priv(netdev);
- u32 val, addr;
- int ret;
-
- if (usb_autopm_get_interface(dev->intf) < 0)
- return;
-
- mutex_lock(&dev->phy_mutex);
-
- /* confirm MII not busy */
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- mmddev &= 0x1F;
-
- /* set up device address for MMD */
- ret = lan78xx_write_reg(dev, MII_DATA, mmddev);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* select register of MMD */
- val = mmdidx;
- ret = lan78xx_write_reg(dev, MII_DATA, val);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* select register data for MMD */
- val = PHY_MMD_CTRL_OP_DNI_ | mmddev;
- ret = lan78xx_write_reg(dev, MII_DATA, val);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* write to MMD */
- val = regval;
- ret = lan78xx_write_reg(dev, MII_DATA, val);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
-done:
- mutex_unlock(&dev->phy_mutex);
- usb_autopm_put_interface(dev->intf);
-}
-
-static int lan78xx_mmd_read(struct net_device *netdev, int phy_id,
- int mmddev, int mmdidx)
-{
- struct lan78xx_net *dev = netdev_priv(netdev);
- u32 val, addr;
- int ret;
-
- ret = usb_autopm_get_interface(dev->intf);
- if (ret < 0)
- return ret;
-
- mutex_lock(&dev->phy_mutex);
-
- /* confirm MII not busy */
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* set up device address for MMD */
- ret = lan78xx_write_reg(dev, MII_DATA, mmddev);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* select register of MMD */
- val = mmdidx;
- ret = lan78xx_write_reg(dev, MII_DATA, val);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* select register data for MMD */
- val = PHY_MMD_CTRL_OP_DNI_ | mmddev;
- ret = lan78xx_write_reg(dev, MII_DATA, val);
-
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* set the address, index & direction (read from PHY) */
- phy_id &= dev->mii.phy_id_mask;
- addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_READ);
- ret = lan78xx_write_reg(dev, MII_ACC, addr);
-
- ret = lan78xx_phy_wait_not_busy(dev);
- if (ret < 0)
- goto done;
-
- /* read from MMD */
- ret = lan78xx_read_reg(dev, MII_DATA, &val);
-
- ret = (int)(val & 0xFFFF);
-
-done:
- mutex_unlock(&dev->phy_mutex);
- usb_autopm_put_interface(dev->intf);
- return ret;
-}
-
static int lan78xx_wait_eeprom(struct lan78xx_net *dev)
{
unsigned long start_time = jiffies;
@@ -1047,14 +832,13 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex,
static int lan78xx_link_reset(struct lan78xx_net *dev)
{
- struct mii_if_info *mii = &dev->mii;
+ struct phy_device *phydev = dev->net->phydev;
struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
int ladv, radv, ret;
u32 buf;
/* clear PHY interrupt status */
- /* VTSE PHY */
- ret = lan78xx_mdio_read(dev->net, mii->phy_id, PHY_VTSE_INT_STS);
+ ret = phy_read(phydev, LAN88XX_INT_STS);
if (unlikely(ret < 0))
return -EIO;
@@ -1063,7 +847,9 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
if (unlikely(ret < 0))
return -EIO;
- if (!mii_link_ok(mii) && dev->link_on) {
+ phy_read_status(phydev);
+
+ if (!phydev->link && dev->link_on) {
dev->link_on = false;
netif_carrier_off(dev->net);
@@ -1075,13 +861,12 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
ret = lan78xx_write_reg(dev, MAC_CR, buf);
if (unlikely(ret < 0))
return -EIO;
- } else if (mii_link_ok(mii) && !dev->link_on) {
+ } else if (phydev->link && !dev->link_on) {
dev->link_on = true;
- mii_check_media(mii, 1, 1);
- mii_ethtool_gset(&dev->mii, &ecmd);
+ phy_ethtool_gset(phydev, &ecmd);
- mii->mdio_read(mii->dev, mii->phy_id, PHY_VTSE_INT_STS);
+ ret = phy_read(phydev, LAN88XX_INT_STS);
if (dev->udev->speed == USB_SPEED_SUPER) {
if (ethtool_cmd_speed(&ecmd) == 1000) {
@@ -1102,11 +887,11 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
}
}
- ladv = lan78xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
+ ladv = phy_read(phydev, MII_ADVERTISE);
if (ladv < 0)
return ladv;
- radv = lan78xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
+ radv = phy_read(phydev, MII_LPA);
if (radv < 0)
return radv;
@@ -1279,6 +1064,8 @@ static int lan78xx_set_wol(struct net_device *netdev,
device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
+ phy_ethtool_set_wol(netdev->phydev, wol);
+
usb_autopm_put_interface(dev->intf);
return ret;
@@ -1287,49 +1074,39 @@ static int lan78xx_set_wol(struct net_device *netdev,
static int lan78xx_get_eee(struct net_device *net, struct ethtool_eee *edata)
{
struct lan78xx_net *dev = netdev_priv(net);
+ struct phy_device *phydev = net->phydev;
int ret;
u32 buf;
- u32 adv, lpadv;
ret = usb_autopm_get_interface(dev->intf);
if (ret < 0)
return ret;
+ ret = phy_ethtool_get_eee(phydev, edata);
+ if (ret < 0)
+ goto exit;
+
ret = lan78xx_read_reg(dev, MAC_CR, &buf);
if (buf & MAC_CR_EEE_EN_) {
- buf = lan78xx_mmd_read(dev->net, dev->mii.phy_id,
- PHY_MMD_DEV_7, PHY_EEE_ADVERTISEMENT);
- adv = mmd_eee_adv_to_ethtool_adv_t(buf);
- buf = lan78xx_mmd_read(dev->net, dev->mii.phy_id,
- PHY_MMD_DEV_7, PHY_EEE_LP_ADVERTISEMENT);
- lpadv = mmd_eee_adv_to_ethtool_adv_t(buf);
-
edata->eee_enabled = true;
- edata->supported = true;
- edata->eee_active = !!(adv & lpadv);
- edata->advertised = adv;
- edata->lp_advertised = lpadv;
+ edata->eee_active = !!(edata->advertised &
+ edata->lp_advertised);
edata->tx_lpi_enabled = true;
/* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
ret = lan78xx_read_reg(dev, EEE_TX_LPI_REQ_DLY, &buf);
edata->tx_lpi_timer = buf;
} else {
- buf = lan78xx_mmd_read(dev->net, dev->mii.phy_id,
- PHY_MMD_DEV_7, PHY_EEE_LP_ADVERTISEMENT);
- lpadv = mmd_eee_adv_to_ethtool_adv_t(buf);
-
edata->eee_enabled = false;
edata->eee_active = false;
- edata->supported = false;
- edata->advertised = 0;
- edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(lpadv);
edata->tx_lpi_enabled = false;
edata->tx_lpi_timer = 0;
}
+ ret = 0;
+exit:
usb_autopm_put_interface(dev->intf);
- return 0;
+ return ret;
}
static int lan78xx_set_eee(struct net_device *net, struct ethtool_eee *edata)
@@ -1347,9 +1124,10 @@ static int lan78xx_set_eee(struct net_device *net, struct ethtool_eee *edata)
buf |= MAC_CR_EEE_EN_;
ret = lan78xx_write_reg(dev, MAC_CR, buf);
- buf = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
- lan78xx_mmd_write(dev->net, dev->mii.phy_id,
- PHY_MMD_DEV_7, PHY_EEE_ADVERTISEMENT, buf);
+ phy_ethtool_set_eee(net->phydev, edata);
+
+ buf = (u32)edata->tx_lpi_timer;
+ ret = lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, buf);
} else {
ret = lan78xx_read_reg(dev, MAC_CR, &buf);
buf &= ~MAC_CR_EEE_EN_;
@@ -1363,19 +1141,14 @@ static int lan78xx_set_eee(struct net_device *net, struct ethtool_eee *edata)
static u32 lan78xx_get_link(struct net_device *net)
{
- struct lan78xx_net *dev = netdev_priv(net);
+ phy_read_status(net->phydev);
- return mii_link_ok(&dev->mii);
+ return net->phydev->link;
}
int lan78xx_nway_reset(struct net_device *net)
{
- struct lan78xx_net *dev = netdev_priv(net);
-
- if ((!dev->mii.mdio_read) || (!dev->mii.mdio_write))
- return -EOPNOTSUPP;
-
- return mii_nway_restart(&dev->mii);
+ return phy_start_aneg(net->phydev);
}
static void lan78xx_get_drvinfo(struct net_device *net,
@@ -1402,36 +1175,78 @@ static void lan78xx_set_msglevel(struct net_device *net, u32 level)
dev->msg_enable = level;
}
+static int lan78xx_get_mdix_status(struct net_device *net)
+{
+ struct phy_device *phydev = net->phydev;
+ int buf;
+
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1);
+ buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL);
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0);
+
+ return buf;
+}
+
+static void lan78xx_set_mdix_status(struct net_device *net, __u8 mdix_ctrl)
+{
+ struct lan78xx_net *dev = netdev_priv(net);
+ struct phy_device *phydev = net->phydev;
+ int buf;
+
+ if (mdix_ctrl == ETH_TP_MDI) {
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS,
+ LAN88XX_EXT_PAGE_SPACE_1);
+ buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL);
+ buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_;
+ phy_write(phydev, LAN88XX_EXT_MODE_CTRL,
+ buf | LAN88XX_EXT_MODE_CTRL_MDI_);
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS,
+ LAN88XX_EXT_PAGE_SPACE_0);
+ } else if (mdix_ctrl == ETH_TP_MDI_X) {
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS,
+ LAN88XX_EXT_PAGE_SPACE_1);
+ buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL);
+ buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_;
+ phy_write(phydev, LAN88XX_EXT_MODE_CTRL,
+ buf | LAN88XX_EXT_MODE_CTRL_MDI_X_);
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS,
+ LAN88XX_EXT_PAGE_SPACE_0);
+ } else if (mdix_ctrl == ETH_TP_MDI_AUTO) {
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS,
+ LAN88XX_EXT_PAGE_SPACE_1);
+ buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL);
+ buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_;
+ phy_write(phydev, LAN88XX_EXT_MODE_CTRL,
+ buf | LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_);
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS,
+ LAN88XX_EXT_PAGE_SPACE_0);
+ }
+ dev->mdix_ctrl = mdix_ctrl;
+}
+
static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct lan78xx_net *dev = netdev_priv(net);
- struct mii_if_info *mii = &dev->mii;
+ struct phy_device *phydev = net->phydev;
int ret;
int buf;
- if ((!dev->mii.mdio_read) || (!dev->mii.mdio_write))
- return -EOPNOTSUPP;
-
ret = usb_autopm_get_interface(dev->intf);
if (ret < 0)
return ret;
- ret = mii_ethtool_gset(&dev->mii, cmd);
+ ret = phy_ethtool_gset(phydev, cmd);
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1);
- buf = mii->mdio_read(mii->dev, mii->phy_id, PHY_EXT_MODE_CTRL);
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0);
+ buf = lan78xx_get_mdix_status(net);
- buf &= PHY_EXT_MODE_CTRL_MDIX_MASK_;
- if (buf == PHY_EXT_MODE_CTRL_AUTO_MDIX_) {
+ buf &= LAN88XX_EXT_MODE_CTRL_MDIX_MASK_;
+ if (buf == LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_) {
cmd->eth_tp_mdix = ETH_TP_MDI_AUTO;
cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
- } else if (buf == PHY_EXT_MODE_CTRL_MDI_) {
+ } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_) {
cmd->eth_tp_mdix = ETH_TP_MDI;
cmd->eth_tp_mdix_ctrl = ETH_TP_MDI;
- } else if (buf == PHY_EXT_MODE_CTRL_MDI_X_) {
+ } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_X_) {
cmd->eth_tp_mdix = ETH_TP_MDI_X;
cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X;
}
@@ -1444,70 +1259,27 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct lan78xx_net *dev = netdev_priv(net);
- struct mii_if_info *mii = &dev->mii;
+ struct phy_device *phydev = net->phydev;
int ret = 0;
int temp;
- if ((!dev->mii.mdio_read) || (!dev->mii.mdio_write))
- return -EOPNOTSUPP;
-
ret = usb_autopm_get_interface(dev->intf);
if (ret < 0)
return ret;
if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) {
- if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI) {
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE,
- PHY_EXT_GPIO_PAGE_SPACE_1);
- temp = mii->mdio_read(mii->dev, mii->phy_id,
- PHY_EXT_MODE_CTRL);
- temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_;
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_MODE_CTRL,
- temp | PHY_EXT_MODE_CTRL_MDI_);
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE,
- PHY_EXT_GPIO_PAGE_SPACE_0);
- } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_X) {
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE,
- PHY_EXT_GPIO_PAGE_SPACE_1);
- temp = mii->mdio_read(mii->dev, mii->phy_id,
- PHY_EXT_MODE_CTRL);
- temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_;
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_MODE_CTRL,
- temp | PHY_EXT_MODE_CTRL_MDI_X_);
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE,
- PHY_EXT_GPIO_PAGE_SPACE_0);
- } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) {
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE,
- PHY_EXT_GPIO_PAGE_SPACE_1);
- temp = mii->mdio_read(mii->dev, mii->phy_id,
- PHY_EXT_MODE_CTRL);
- temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_;
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_MODE_CTRL,
- temp | PHY_EXT_MODE_CTRL_AUTO_MDIX_);
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE,
- PHY_EXT_GPIO_PAGE_SPACE_0);
- }
+ lan78xx_set_mdix_status(net, cmd->eth_tp_mdix_ctrl);
}
/* change speed & duplex */
- ret = mii_ethtool_sset(&dev->mii, cmd);
+ ret = phy_ethtool_sset(phydev, cmd);
if (!cmd->autoneg) {
/* force link down */
- temp = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
- mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR,
- temp | BMCR_LOOPBACK);
+ temp = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, temp | BMCR_LOOPBACK);
mdelay(1);
- mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, temp);
+ phy_write(phydev, MII_BMCR, temp);
}
usb_autopm_put_interface(dev->intf);
@@ -1537,12 +1309,10 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
{
- struct lan78xx_net *dev = netdev_priv(netdev);
-
if (!netif_running(netdev))
return -EINVAL;
- return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+ return phy_mii_ioctl(netdev->phydev, rq, cmd);
}
static void lan78xx_init_mac_address(struct lan78xx_net *dev)
@@ -1598,53 +1368,183 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
ether_addr_copy(dev->net->dev_addr, addr);
}
-static void lan78xx_mii_init(struct lan78xx_net *dev)
+/* MDIO read and write wrappers for phylib */
+static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)
{
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = lan78xx_mdio_read;
- dev->mii.mdio_write = lan78xx_mdio_write;
- dev->mii.phy_id_mask = 0x1f;
- dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = INTERNAL_PHY_ID;
- dev->mii.supports_gmii = true;
+ struct lan78xx_net *dev = bus->priv;
+ u32 val, addr;
+ int ret;
+
+ ret = usb_autopm_get_interface(dev->intf);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&dev->phy_mutex);
+
+ /* confirm MII not busy */
+ ret = lan78xx_phy_wait_not_busy(dev);
+ if (ret < 0)
+ goto done;
+
+ /* set the address, index & direction (read from PHY) */
+ addr = mii_access(phy_id, idx, MII_READ);
+ ret = lan78xx_write_reg(dev, MII_ACC, addr);
+
+ ret = lan78xx_phy_wait_not_busy(dev);
+ if (ret < 0)
+ goto done;
+
+ ret = lan78xx_read_reg(dev, MII_DATA, &val);
+
+ ret = (int)(val & 0xFFFF);
+
+done:
+ mutex_unlock(&dev->phy_mutex);
+ usb_autopm_put_interface(dev->intf);
+ return ret;
+}
+
+static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,
+ u16 regval)
+{
+ struct lan78xx_net *dev = bus->priv;
+ u32 val, addr;
+ int ret;
+
+ ret = usb_autopm_get_interface(dev->intf);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&dev->phy_mutex);
+
+ /* confirm MII not busy */
+ ret = lan78xx_phy_wait_not_busy(dev);
+ if (ret < 0)
+ goto done;
+
+ val = (u32)regval;
+ ret = lan78xx_write_reg(dev, MII_DATA, val);
+
+ /* set the address, index & direction (write to PHY) */
+ addr = mii_access(phy_id, idx, MII_WRITE);
+ ret = lan78xx_write_reg(dev, MII_ACC, addr);
+
+ ret = lan78xx_phy_wait_not_busy(dev);
+ if (ret < 0)
+ goto done;
+
+done:
+ mutex_unlock(&dev->phy_mutex);
+ usb_autopm_put_interface(dev->intf);
+ return 0;
+}
+
+static int lan78xx_mdio_init(struct lan78xx_net *dev)
+{
+ int ret;
+ int i;
+
+ dev->mdiobus = mdiobus_alloc();
+ if (!dev->mdiobus) {
+ netdev_err(dev->net, "can't allocate MDIO bus\n");
+ return -ENOMEM;
+ }
+
+ dev->mdiobus->priv = (void *)dev;
+ dev->mdiobus->read = lan78xx_mdiobus_read;
+ dev->mdiobus->write = lan78xx_mdiobus_write;
+ dev->mdiobus->name = "lan78xx-mdiobus";
+
+ snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
+ dev->udev->bus->busnum, dev->udev->devnum);
+
+ dev->mdiobus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!dev->mdiobus->irq) {
+ ret = -ENOMEM;
+ goto exit1;
+ }
+
+ /* handle our own interrupt */
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ dev->mdiobus->irq[i] = PHY_IGNORE_INTERRUPT;
+
+ switch (dev->devid & ID_REV_CHIP_ID_MASK_) {
+ case 0x78000000:
+ case 0x78500000:
+ /* set to internal PHY id */
+ dev->mdiobus->phy_mask = ~(1 << 1);
+ break;
+ }
+
+ ret = mdiobus_register(dev->mdiobus);
+ if (ret) {
+ netdev_err(dev->net, "can't register MDIO bus\n");
+ goto exit2;
+ }
+
+ netdev_dbg(dev->net, "registered mdiobus bus %s\n", dev->mdiobus->id);
+ return 0;
+exit2:
+ kfree(dev->mdiobus->irq);
+exit1:
+ mdiobus_free(dev->mdiobus);
+ return ret;
+}
+
+static void lan78xx_remove_mdio(struct lan78xx_net *dev)
+{
+ mdiobus_unregister(dev->mdiobus);
+ kfree(dev->mdiobus->irq);
+ mdiobus_free(dev->mdiobus);
+}
+
+static void lan78xx_link_status_change(struct net_device *net)
+{
+ /* nothing to do */
}
static int lan78xx_phy_init(struct lan78xx_net *dev)
{
- int temp;
- struct mii_if_info *mii = &dev->mii;
+ int ret;
+ struct phy_device *phydev = dev->net->phydev;
- if ((!mii->mdio_write) || (!mii->mdio_read))
- return -EOPNOTSUPP;
+ phydev = phy_find_first(dev->mdiobus);
+ if (!phydev) {
+ netdev_err(dev->net, "no PHY found\n");
+ return -EIO;
+ }
- temp = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
- temp |= ADVERTISE_ALL;
- mii->mdio_write(mii->dev, mii->phy_id, MII_ADVERTISE,
- temp | ADVERTISE_CSMA |
- ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+ ret = phy_connect_direct(dev->net, phydev,
+ lan78xx_link_status_change,
+ PHY_INTERFACE_MODE_GMII);
+ if (ret) {
+ netdev_err(dev->net, "can't attach PHY to %s\n",
+ dev->mdiobus->id);
+ return -EIO;
+ }
/* set to AUTOMDIX */
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1);
- temp = mii->mdio_read(mii->dev, mii->phy_id, PHY_EXT_MODE_CTRL);
- temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_;
- mii->mdio_write(mii->dev, mii->phy_id, PHY_EXT_MODE_CTRL,
- temp | PHY_EXT_MODE_CTRL_AUTO_MDIX_);
- mii->mdio_write(mii->dev, mii->phy_id,
- PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0);
- dev->mdix_ctrl = ETH_TP_MDI_AUTO;
-
- /* MAC doesn't support 1000HD */
- temp = mii->mdio_read(mii->dev, mii->phy_id, MII_CTRL1000);
- mii->mdio_write(mii->dev, mii->phy_id, MII_CTRL1000,
- temp & ~ADVERTISE_1000HALF);
-
- /* clear interrupt */
- mii->mdio_read(mii->dev, mii->phy_id, PHY_VTSE_INT_STS);
- mii->mdio_write(mii->dev, mii->phy_id, PHY_VTSE_INT_MASK,
- PHY_VTSE_INT_MASK_MDINTPIN_EN_ |
- PHY_VTSE_INT_MASK_LINK_CHANGE_);
+ lan78xx_set_mdix_status(dev->net, ETH_TP_MDI_AUTO);
+
+ /* MAC doesn't support 1000T Half */
+ phydev->supported &= ~SUPPORTED_1000baseT_Half;
+ phydev->supported |= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ genphy_config_aneg(phydev);
+
+ /* Workaround to enable PHY interrupt.
+ * phy_start_interrupts() is API for requesting and enabling
+ * PHY interrupt. However, USB-to-Ethernet device can't use
+ * request_irq() called in phy_start_interrupts().
+ * Set PHY to PHY_HALTED and call phy_start()
+ * to make a call to phy_enable_interrupts()
+ */
+ phy_stop(phydev);
+ phy_start(phydev);
netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
@@ -1930,6 +1830,10 @@ static int lan78xx_reset(struct lan78xx_net *dev)
lan78xx_init_mac_address(dev);
+ /* save DEVID for later usage */
+ ret = lan78xx_read_reg(dev, ID_REV, &buf);
+ dev->devid = buf;
+
/* Respond to the IN token with a NAK */
ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
buf |= USB_CFG_BIR_;
@@ -2002,23 +1906,12 @@ static int lan78xx_reset(struct lan78xx_net *dev)
netdev_warn(dev->net, "timeout waiting for PHY Reset");
return -EIO;
}
- } while (buf & PMT_CTL_PHY_RST_);
-
- lan78xx_mii_init(dev);
-
- ret = lan78xx_phy_init(dev);
+ } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_));
ret = lan78xx_read_reg(dev, MAC_CR, &buf);
-
- buf |= MAC_CR_GMII_EN_;
buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_;
-
ret = lan78xx_write_reg(dev, MAC_CR, buf);
- /* enable on PHY */
- if (buf & MAC_CR_EEE_EN_)
- lan78xx_mmd_write(dev->net, dev->mii.phy_id, 0x07, 0x3C, 0x06);
-
/* enable PHY interrupts */
ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
buf |= INT_ENP_PHY_INT;
@@ -2042,9 +1935,6 @@ static int lan78xx_reset(struct lan78xx_net *dev)
buf |= FCT_RX_CTL_EN_;
ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf);
- if (!mii_nway_restart(&dev->mii))
- netif_dbg(dev, link, dev->net, "autoneg initiated");
-
return 0;
}
@@ -2061,6 +1951,10 @@ static int lan78xx_open(struct net_device *net)
if (ret < 0)
goto done;
+ ret = lan78xx_phy_init(dev);
+ if (ret < 0)
+ goto done;
+
/* for Link Check */
if (dev->urb_intr) {
ret = usb_submit_urb(dev->urb_intr, GFP_KERNEL);
@@ -2115,6 +2009,10 @@ int lan78xx_stop(struct net_device *net)
{
struct lan78xx_net *dev = netdev_priv(net);
+ phy_stop(net->phydev);
+ phy_disconnect(net->phydev);
+ net->phydev = NULL;
+
clear_bit(EVENT_DEV_OPEN, &dev->flags);
netif_stop_queue(net);
@@ -2395,6 +2293,8 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
/* Init all registers */
ret = lan78xx_reset(dev);
+ lan78xx_mdio_init(dev);
+
dev->net->flags |= IFF_MULTICAST;
pdata->wol = WAKE_MAGIC;
@@ -2406,6 +2306,8 @@ static void lan78xx_unbind(struct lan78xx_net *dev, struct usb_interface *intf)
{
struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+ lan78xx_remove_mdio(dev);
+
if (pdata) {
netif_dbg(dev, ifdown, dev->net, "free pdata");
kfree(pdata);
@@ -2522,11 +2424,6 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb)
skb_pull(skb, align_count);
}
- if (unlikely(skb->len < 0)) {
- netdev_warn(dev->net, "invalid rx length<0 %d", skb->len);
- return 0;
- }
-
return 1;
}
@@ -3307,7 +3204,6 @@ int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
int ret;
int event;
- ret = 0;
event = message.event;
if (!dev->suspend_count++) {
@@ -3389,6 +3285,7 @@ int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
}
}
+ ret = 0;
out:
return ret;
}
@@ -3459,6 +3356,9 @@ int lan78xx_reset_resume(struct usb_interface *intf)
struct lan78xx_net *dev = usb_get_intfdata(intf);
lan78xx_reset(dev);
+
+ lan78xx_phy_init(dev);
+
return lan78xx_resume(intf);
}
diff --git a/drivers/net/usb/lan78xx.h b/drivers/net/usb/lan78xx.h
index ae7562ee72ad..a93fb653e7c5 100644
--- a/drivers/net/usb/lan78xx.h
+++ b/drivers/net/usb/lan78xx.h
@@ -549,7 +549,6 @@
#define LTM_INACTIVE1_TIMER10_ (0x0000FFFF)
#define MAC_CR (0x100)
-#define MAC_CR_GMII_EN_ (0x00080000)
#define MAC_CR_EEE_TX_CLK_STOP_EN_ (0x00040000)
#define MAC_CR_EEE_EN_ (0x00020000)
#define MAC_CR_EEE_TLAR_EN_ (0x00010000)
@@ -874,196 +873,4 @@
#define OTP_TPVSR_VAL (OTP_BASE_ADDR + 4 * 0x3A)
#define OTP_TPVHR_VAL (OTP_BASE_ADDR + 4 * 0x3B)
#define OTP_TPVSA_VAL (OTP_BASE_ADDR + 4 * 0x3C)
-
-#define PHY_ID1 (0x02)
-#define PHY_ID2 (0x03)
-
-#define PHY_DEV_ID_OUI_VTSE (0x04001C)
-#define PHY_DEV_ID_MODEL_VTSE_8502 (0x23)
-
-#define PHY_AUTONEG_ADV (0x04)
-#define NWAY_AR_NEXT_PAGE_ (0x8000)
-#define NWAY_AR_REMOTE_FAULT_ (0x2000)
-#define NWAY_AR_ASM_DIR_ (0x0800)
-#define NWAY_AR_PAUSE_ (0x0400)
-#define NWAY_AR_100T4_CAPS_ (0x0200)
-#define NWAY_AR_100TX_FD_CAPS_ (0x0100)
-#define NWAY_AR_SELECTOR_FIELD_ (0x001F)
-#define NWAY_AR_100TX_HD_CAPS_ (0x0080)
-#define NWAY_AR_10T_FD_CAPS_ (0x0040)
-#define NWAY_AR_10T_HD_CAPS_ (0x0020)
-#define NWAY_AR_ALL_CAPS_ (NWAY_AR_10T_HD_CAPS_ | \
- NWAY_AR_10T_FD_CAPS_ | \
- NWAY_AR_100TX_HD_CAPS_ | \
- NWAY_AR_100TX_FD_CAPS_)
-#define NWAY_AR_PAUSE_MASK (NWAY_AR_PAUSE_ | NWAY_AR_ASM_DIR_)
-
-#define PHY_LP_ABILITY (0x05)
-#define NWAY_LPAR_NEXT_PAGE_ (0x8000)
-#define NWAY_LPAR_ACKNOWLEDGE_ (0x4000)
-#define NWAY_LPAR_REMOTE_FAULT_ (0x2000)
-#define NWAY_LPAR_ASM_DIR_ (0x0800)
-#define NWAY_LPAR_PAUSE_ (0x0400)
-#define NWAY_LPAR_100T4_CAPS_ (0x0200)
-#define NWAY_LPAR_100TX_FD_CAPS_ (0x0100)
-#define NWAY_LPAR_100TX_HD_CAPS_ (0x0080)
-#define NWAY_LPAR_10T_FD_CAPS_ (0x0040)
-#define NWAY_LPAR_10T_HD_CAPS_ (0x0020)
-#define NWAY_LPAR_SELECTOR_FIELD_ (0x001F)
-
-#define PHY_AUTONEG_EXP (0x06)
-#define NWAY_ER_PAR_DETECT_FAULT_ (0x0010)
-#define NWAY_ER_LP_NEXT_PAGE_CAPS_ (0x0008)
-#define NWAY_ER_NEXT_PAGE_CAPS_ (0x0004)
-#define NWAY_ER_PAGE_RXD_ (0x0002)
-#define NWAY_ER_LP_NWAY_CAPS_ (0x0001)
-
-#define PHY_NEXT_PAGE_TX (0x07)
-#define NPTX_NEXT_PAGE_ (0x8000)
-#define NPTX_MSG_PAGE_ (0x2000)
-#define NPTX_ACKNOWLDGE2_ (0x1000)
-#define NPTX_TOGGLE_ (0x0800)
-#define NPTX_MSG_CODE_FIELD_ (0x0001)
-
-#define PHY_LP_NEXT_PAGE (0x08)
-#define LP_RNPR_NEXT_PAGE_ (0x8000)
-#define LP_RNPR_ACKNOWLDGE_ (0x4000)
-#define LP_RNPR_MSG_PAGE_ (0x2000)
-#define LP_RNPR_ACKNOWLDGE2_ (0x1000)
-#define LP_RNPR_TOGGLE_ (0x0800)
-#define LP_RNPR_MSG_CODE_FIELD_ (0x0001)
-
-#define PHY_1000T_CTRL (0x09)
-#define CR_1000T_TEST_MODE_4_ (0x8000)
-#define CR_1000T_TEST_MODE_3_ (0x6000)
-#define CR_1000T_TEST_MODE_2_ (0x4000)
-#define CR_1000T_TEST_MODE_1_ (0x2000)
-#define CR_1000T_MS_ENABLE_ (0x1000)
-#define CR_1000T_MS_VALUE_ (0x0800)
-#define CR_1000T_REPEATER_DTE_ (0x0400)
-#define CR_1000T_FD_CAPS_ (0x0200)
-#define CR_1000T_HD_CAPS_ (0x0100)
-#define CR_1000T_ASYM_PAUSE_ (0x0080)
-#define CR_1000T_TEST_MODE_NORMAL_ (0x0000)
-
-#define PHY_1000T_STATUS (0x0A)
-#define SR_1000T_MS_CONFIG_FAULT_ (0x8000)
-#define SR_1000T_MS_CONFIG_RES_ (0x4000)
-#define SR_1000T_LOCAL_RX_STATUS_ (0x2000)
-#define SR_1000T_REMOTE_RX_STATUS_ (0x1000)
-#define SR_1000T_LP_FD_CAPS_ (0x0800)
-#define SR_1000T_LP_HD_CAPS_ (0x0400)
-#define SR_1000T_ASYM_PAUSE_DIR_ (0x0100)
-#define SR_1000T_IDLE_ERROR_CNT_ (0x00FF)
-#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12
-#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13
-#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100
-
-#define PHY_EXT_STATUS (0x0F)
-#define IEEE_ESR_1000X_FD_CAPS_ (0x8000)
-#define IEEE_ESR_1000X_HD_CAPS_ (0x4000)
-#define IEEE_ESR_1000T_FD_CAPS_ (0x2000)
-#define IEEE_ESR_1000T_HD_CAPS_ (0x1000)
-#define PHY_TX_POLARITY_MASK_ (0x0100)
-#define PHY_TX_NORMAL_POLARITY_ (0x0000)
-#define AUTO_POLARITY_DISABLE_ (0x0010)
-
-#define PHY_MMD_CTL (0x0D)
-#define PHY_MMD_CTRL_OP_MASK_ (0xC000)
-#define PHY_MMD_CTRL_OP_REG_ (0x0000)
-#define PHY_MMD_CTRL_OP_DNI_ (0x4000)
-#define PHY_MMD_CTRL_OP_DPIRW_ (0x8000)
-#define PHY_MMD_CTRL_OP_DPIWO_ (0xC000)
-#define PHY_MMD_CTRL_DEV_ADDR_MASK_ (0x001F)
-
-#define PHY_MMD_REG_DATA (0x0E)
-
-/* VTSE Vendor Specific registers */
-#define PHY_VTSE_BYPASS (0x12)
-#define PHY_VTSE_BYPASS_DISABLE_PAIR_SWAP_ (0x0020)
-
-#define PHY_VTSE_INT_MASK (0x19)
-#define PHY_VTSE_INT_MASK_MDINTPIN_EN_ (0x8000)
-#define PHY_VTSE_INT_MASK_SPEED_CHANGE_ (0x4000)
-#define PHY_VTSE_INT_MASK_LINK_CHANGE_ (0x2000)
-#define PHY_VTSE_INT_MASK_FDX_CHANGE_ (0x1000)
-#define PHY_VTSE_INT_MASK_AUTONEG_ERR_ (0x0800)
-#define PHY_VTSE_INT_MASK_AUTONEG_DONE_ (0x0400)
-#define PHY_VTSE_INT_MASK_POE_DETECT_ (0x0200)
-#define PHY_VTSE_INT_MASK_SYMBOL_ERR_ (0x0100)
-#define PHY_VTSE_INT_MASK_FAST_LINK_FAIL_ (0x0080)
-#define PHY_VTSE_INT_MASK_WOL_EVENT_ (0x0040)
-#define PHY_VTSE_INT_MASK_EXTENDED_INT_ (0x0020)
-#define PHY_VTSE_INT_MASK_RESERVED_ (0x0010)
-#define PHY_VTSE_INT_MASK_FALSE_CARRIER_ (0x0008)
-#define PHY_VTSE_INT_MASK_LINK_SPEED_DS_ (0x0004)
-#define PHY_VTSE_INT_MASK_MASTER_SLAVE_DONE_ (0x0002)
-#define PHY_VTSE_INT_MASK_RX__ER_ (0x0001)
-
-#define PHY_VTSE_INT_STS (0x1A)
-#define PHY_VTSE_INT_STS_INT_ACTIVE_ (0x8000)
-#define PHY_VTSE_INT_STS_SPEED_CHANGE_ (0x4000)
-#define PHY_VTSE_INT_STS_LINK_CHANGE_ (0x2000)
-#define PHY_VTSE_INT_STS_FDX_CHANGE_ (0x1000)
-#define PHY_VTSE_INT_STS_AUTONEG_ERR_ (0x0800)
-#define PHY_VTSE_INT_STS_AUTONEG_DONE_ (0x0400)
-#define PHY_VTSE_INT_STS_POE_DETECT_ (0x0200)
-#define PHY_VTSE_INT_STS_SYMBOL_ERR_ (0x0100)
-#define PHY_VTSE_INT_STS_FAST_LINK_FAIL_ (0x0080)
-#define PHY_VTSE_INT_STS_WOL_EVENT_ (0x0040)
-#define PHY_VTSE_INT_STS_EXTENDED_INT_ (0x0020)
-#define PHY_VTSE_INT_STS_RESERVED_ (0x0010)
-#define PHY_VTSE_INT_STS_FALSE_CARRIER_ (0x0008)
-#define PHY_VTSE_INT_STS_LINK_SPEED_DS_ (0x0004)
-#define PHY_VTSE_INT_STS_MASTER_SLAVE_DONE_ (0x0002)
-#define PHY_VTSE_INT_STS_RX_ER_ (0x0001)
-
-/* VTSE PHY registers */
-#define PHY_EXT_GPIO_PAGE (0x1F)
-#define PHY_EXT_GPIO_PAGE_SPACE_0 (0x0000)
-#define PHY_EXT_GPIO_PAGE_SPACE_1 (0x0001)
-#define PHY_EXT_GPIO_PAGE_SPACE_2 (0x0002)
-
-/* Extended Register Page 1 space */
-#define PHY_EXT_MODE_CTRL (0x13)
-#define PHY_EXT_MODE_CTRL_MDIX_MASK_ (0x000C)
-#define PHY_EXT_MODE_CTRL_AUTO_MDIX_ (0x0000)
-#define PHY_EXT_MODE_CTRL_MDI_ (0x0008)
-#define PHY_EXT_MODE_CTRL_MDI_X_ (0x000C)
-
-#define PHY_ANA_10BASE_T_HD 0x01
-#define PHY_ANA_10BASE_T_FD 0x02
-#define PHY_ANA_100BASE_TX_HD 0x04
-#define PHY_ANA_100BASE_TX_FD 0x08
-#define PHY_ANA_1000BASE_T_FD 0x10
-#define PHY_ANA_ALL_SUPPORTED_MEDIA (PHY_ANA_10BASE_T_HD | \
- PHY_ANA_10BASE_T_FD | \
- PHY_ANA_100BASE_TX_HD | \
- PHY_ANA_100BASE_TX_FD | \
- PHY_ANA_1000BASE_T_FD)
-/* PHY MMD registers */
-#define PHY_MMD_DEV_3 3
-
-#define PHY_EEE_PCS_STATUS (0x1)
-#define PHY_EEE_PCS_STATUS_TX_LPI_RCVD_ ((WORD)0x0800)
-#define PHY_EEE_PCS_STATUS_RX_LPI_RCVD_ ((WORD)0x0400)
-#define PHY_EEE_PCS_STATUS_TX_LPI_IND_ ((WORD)0x0200)
-#define PHY_EEE_PCS_STATUS_RX_LPI_IND_ ((WORD)0x0100)
-#define PHY_EEE_PCS_STATUS_PCS_RCV_LNK_STS_ ((WORD)0x0004)
-
-#define PHY_EEE_CAPABILITIES (0x14)
-#define PHY_EEE_CAPABILITIES_1000BT_EEE_ ((WORD)0x0004)
-#define PHY_EEE_CAPABILITIES_100BT_EEE_ ((WORD)0x0002)
-
-#define PHY_MMD_DEV_7 7
-
-#define PHY_EEE_ADVERTISEMENT (0x3C)
-#define PHY_EEE_ADVERTISEMENT_1000BT_EEE_ ((WORD)0x0004)
-#define PHY_EEE_ADVERTISEMENT_100BT_EEE_ ((WORD)0x0002)
-
-#define PHY_EEE_LP_ADVERTISEMENT (0x3D)
-#define PHY_EEE_1000BT_EEE_CAPABLE_ ((WORD)0x0004)
-#define PHY_EEE_100BT_EEE_CAPABLE_ ((WORD)0x0002)
#endif /* _LAN78XX_H */
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index 82d844a8ebd0..4f345bd4e6e2 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -445,7 +445,6 @@ static int mcs7830_get_regs_len(struct net_device *net)
static void mcs7830_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *drvinfo)
{
usbnet_get_drvinfo(net, drvinfo);
- drvinfo->regdump_len = mcs7830_get_regs_len(net);
}
static void mcs7830_get_regs(struct net_device *net, struct ethtool_regs *regs, void *data)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 355842b85ee9..34799eaace41 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -229,11 +229,11 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
u8 *buf = intf->cur_altsetting->extra;
int len = intf->cur_altsetting->extralen;
struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc;
- struct usb_cdc_union_desc *cdc_union = NULL;
- struct usb_cdc_ether_desc *cdc_ether = NULL;
- u32 found = 0;
+ struct usb_cdc_union_desc *cdc_union;
+ struct usb_cdc_ether_desc *cdc_ether;
struct usb_driver *driver = driver_of(intf);
struct qmi_wwan_state *info = (void *)&dev->data;
+ struct usb_cdc_parsed_header hdr;
BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) <
sizeof(struct qmi_wwan_state)));
@@ -243,63 +243,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
info->data = intf;
/* and a number of CDC descriptors */
- while (len > 3) {
- struct usb_descriptor_header *h = (void *)buf;
-
- /* ignore any misplaced descriptors */
- if (h->bDescriptorType != USB_DT_CS_INTERFACE)
- goto next_desc;
-
- /* buf[2] is CDC descriptor subtype */
- switch (buf[2]) {
- case USB_CDC_HEADER_TYPE:
- if (found & 1 << USB_CDC_HEADER_TYPE) {
- dev_dbg(&intf->dev, "extra CDC header\n");
- goto err;
- }
- if (h->bLength != sizeof(struct usb_cdc_header_desc)) {
- dev_dbg(&intf->dev, "CDC header len %u\n",
- h->bLength);
- goto err;
- }
- break;
- case USB_CDC_UNION_TYPE:
- if (found & 1 << USB_CDC_UNION_TYPE) {
- dev_dbg(&intf->dev, "extra CDC union\n");
- goto err;
- }
- if (h->bLength != sizeof(struct usb_cdc_union_desc)) {
- dev_dbg(&intf->dev, "CDC union len %u\n",
- h->bLength);
- goto err;
- }
- cdc_union = (struct usb_cdc_union_desc *)buf;
- break;
- case USB_CDC_ETHERNET_TYPE:
- if (found & 1 << USB_CDC_ETHERNET_TYPE) {
- dev_dbg(&intf->dev, "extra CDC ether\n");
- goto err;
- }
- if (h->bLength != sizeof(struct usb_cdc_ether_desc)) {
- dev_dbg(&intf->dev, "CDC ether len %u\n",
- h->bLength);
- goto err;
- }
- cdc_ether = (struct usb_cdc_ether_desc *)buf;
- break;
- }
-
- /* Remember which CDC functional descriptors we've seen. Works
- * for all types we care about, of which USB_CDC_ETHERNET_TYPE
- * (0x0f) is the highest numbered
- */
- if (buf[2] < 32)
- found |= 1 << buf[2];
-
-next_desc:
- len -= h->bLength;
- buf += h->bLength;
- }
+ cdc_parse_cdc_header(&hdr, intf, buf, len);
+ cdc_union = hdr.usb_cdc_union_desc;
+ cdc_ether = hdr.usb_cdc_ether_desc;
/* Use separate control and data interfaces if we found a CDC Union */
if (cdc_union) {
@@ -539,6 +485,10 @@ static const struct usb_device_id products[] = {
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&qmi_wwan_info,
},
+ { /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
+ USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7),
+ .driver_info = (unsigned long)&qmi_wwan_info,
+ },
/* 3. Combined interface devices matching on interface number */
{QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
@@ -765,6 +715,10 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9057, 8)},
{QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */
+ {QMI_FIXED_INTF(0x1199, 0x9070, 8)}, /* Sierra Wireless MC74xx/EM74xx */
+ {QMI_FIXED_INTF(0x1199, 0x9070, 10)}, /* Sierra Wireless MC74xx/EM74xx */
+ {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx/EM74xx */
+ {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx/EM74xx */
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
@@ -787,7 +741,6 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
- {QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
/* 4. Gobi 1000 devices */
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
@@ -818,6 +771,7 @@ static const struct usb_device_id products[] = {
{QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */
{QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
{QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
+ {QMI_FIXED_INTF(0x05c6, 0x9215, 4)}, /* Quectel EC20 Mini PCIe */
{QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
{QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */
{QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */
@@ -849,10 +803,24 @@ static const struct usb_device_id products[] = {
};
MODULE_DEVICE_TABLE(usb, products);
+static bool quectel_ec20_detected(struct usb_interface *intf)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+
+ if (dev->actconfig &&
+ le16_to_cpu(dev->descriptor.idVendor) == 0x05c6 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x9215 &&
+ dev->actconfig->desc.bNumInterfaces == 5)
+ return true;
+
+ return false;
+}
+
static int qmi_wwan_probe(struct usb_interface *intf,
const struct usb_device_id *prod)
{
struct usb_device_id *id = (struct usb_device_id *)prod;
+ struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc;
/* Workaround to enable dynamic IDs. This disables usbnet
* blacklisting functionality. Which, if required, can be
@@ -864,6 +832,12 @@ static int qmi_wwan_probe(struct usb_interface *intf,
id->driver_info = (unsigned long)&qmi_wwan_info;
}
+ /* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */
+ if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) {
+ dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n");
+ return -ENODEV;
+ }
+
return usbnet_probe(intf, id);
}
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index d9e7892262fa..30033dbe6662 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -2185,11 +2185,6 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
skb_pull(skb, align_count);
}
- if (unlikely(skb->len < 0)) {
- netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
- return 0;
- }
-
return 1;
}
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 26423adc35ee..66b3ab9f614e 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1815,11 +1815,6 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
skb_pull(skb, align_count);
}
- if (unlikely(skb->len < 0)) {
- netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
- return 0;
- }
-
return 1;
}
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c
index 953de13267df..a50df0d8fb9a 100644
--- a/drivers/net/usb/sr9800.c
+++ b/drivers/net/usb/sr9800.c
@@ -470,14 +470,10 @@ static int sr_get_eeprom(struct net_device *net,
static void sr_get_drvinfo(struct net_device *net,
struct ethtool_drvinfo *info)
{
- struct usbnet *dev = netdev_priv(net);
- struct sr_data *data = (struct sr_data *)&dev->data;
-
/* Inherit standard device info */
usbnet_get_drvinfo(net, info);
strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
- info->eedump_len = data->eeprom_len;
}
static u32 sr_get_link(struct net_device *net)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index b4cf10781348..0744bf2ef2d6 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -42,6 +42,7 @@
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/pm_runtime.h>
@@ -1661,12 +1662,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
* bind() should set rx_urb_size in that case.
*/
dev->hard_mtu = net->mtu + net->hard_header_len;
-#if 0
-// dma_supported() is deeply broken on almost all architectures
- // possible with some EHCI controllers
- if (dma_supported (&udev->dev, DMA_BIT_MASK(64)))
- net->features |= NETIF_F_HIGHDMA;
-#endif
net->netdev_ops = &usbnet_netdev_ops;
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
@@ -1962,6 +1957,143 @@ out:
return err;
}
+int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
+ struct usb_interface *intf,
+ u8 *buffer,
+ int buflen)
+{
+ /* duplicates are ignored */
+ struct usb_cdc_union_desc *union_header = NULL;
+
+ /* duplicates are not tolerated */
+ struct usb_cdc_header_desc *header = NULL;
+ struct usb_cdc_ether_desc *ether = NULL;
+ struct usb_cdc_mdlm_detail_desc *detail = NULL;
+ struct usb_cdc_mdlm_desc *desc = NULL;
+
+ unsigned int elength;
+ int cnt = 0;
+
+ memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header));
+ hdr->phonet_magic_present = false;
+ while (buflen > 0) {
+ elength = buffer[0];
+ if (!elength) {
+ dev_err(&intf->dev, "skipping garbage byte\n");
+ elength = 1;
+ goto next_desc;
+ }
+ if (buffer[1] != USB_DT_CS_INTERFACE) {
+ dev_err(&intf->dev, "skipping garbage\n");
+ goto next_desc;
+ }
+
+ switch (buffer[2]) {
+ case USB_CDC_UNION_TYPE: /* we've found it */
+ if (elength < sizeof(struct usb_cdc_union_desc))
+ goto next_desc;
+ if (union_header) {
+ dev_err(&intf->dev, "More than one union descriptor, skipping ...\n");
+ goto next_desc;
+ }
+ union_header = (struct usb_cdc_union_desc *)buffer;
+ break;
+ case USB_CDC_COUNTRY_TYPE:
+ if (elength < sizeof(struct usb_cdc_country_functional_desc))
+ goto next_desc;
+ hdr->usb_cdc_country_functional_desc =
+ (struct usb_cdc_country_functional_desc *)buffer;
+ break;
+ case USB_CDC_HEADER_TYPE:
+ if (elength != sizeof(struct usb_cdc_header_desc))
+ goto next_desc;
+ if (header)
+ return -EINVAL;
+ header = (struct usb_cdc_header_desc *)buffer;
+ break;
+ case USB_CDC_ACM_TYPE:
+ if (elength < sizeof(struct usb_cdc_acm_descriptor))
+ goto next_desc;
+ hdr->usb_cdc_acm_descriptor =
+ (struct usb_cdc_acm_descriptor *)buffer;
+ break;
+ case USB_CDC_ETHERNET_TYPE:
+ if (elength != sizeof(struct usb_cdc_ether_desc))
+ goto next_desc;
+ if (ether)
+ return -EINVAL;
+ ether = (struct usb_cdc_ether_desc *)buffer;
+ break;
+ case USB_CDC_CALL_MANAGEMENT_TYPE:
+ if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor))
+ goto next_desc;
+ hdr->usb_cdc_call_mgmt_descriptor =
+ (struct usb_cdc_call_mgmt_descriptor *)buffer;
+ break;
+ case USB_CDC_DMM_TYPE:
+ if (elength < sizeof(struct usb_cdc_dmm_desc))
+ goto next_desc;
+ hdr->usb_cdc_dmm_desc =
+ (struct usb_cdc_dmm_desc *)buffer;
+ break;
+ case USB_CDC_MDLM_TYPE:
+ if (elength < sizeof(struct usb_cdc_mdlm_desc *))
+ goto next_desc;
+ if (desc)
+ return -EINVAL;
+ desc = (struct usb_cdc_mdlm_desc *)buffer;
+ break;
+ case USB_CDC_MDLM_DETAIL_TYPE:
+ if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *))
+ goto next_desc;
+ if (detail)
+ return -EINVAL;
+ detail = (struct usb_cdc_mdlm_detail_desc *)buffer;
+ break;
+ case USB_CDC_NCM_TYPE:
+ if (elength < sizeof(struct usb_cdc_ncm_desc))
+ goto next_desc;
+ hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer;
+ break;
+ case USB_CDC_MBIM_TYPE:
+ if (elength < sizeof(struct usb_cdc_mbim_desc))
+ goto next_desc;
+
+ hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer;
+ break;
+ case USB_CDC_MBIM_EXTENDED_TYPE:
+ if (elength < sizeof(struct usb_cdc_mbim_extended_desc))
+ break;
+ hdr->usb_cdc_mbim_extended_desc =
+ (struct usb_cdc_mbim_extended_desc *)buffer;
+ break;
+ case CDC_PHONET_MAGIC_NUMBER:
+ hdr->phonet_magic_present = true;
+ break;
+ default:
+ /*
+ * there are LOTS more CDC descriptors that
+ * could legitimately be found here.
+ */
+ dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n",
+ buffer[2], elength);
+ goto next_desc;
+ }
+ cnt++;
+next_desc:
+ buflen -= elength;
+ buffer += elength;
+ }
+ hdr->usb_cdc_union_desc = union_header;
+ hdr->usb_cdc_header_desc = header;
+ hdr->usb_cdc_mdlm_detail_desc = detail;
+ hdr->usb_cdc_mdlm_desc = desc;
+ hdr->usb_cdc_ether_desc = ether;
+ return cnt;
+}
+
+EXPORT_SYMBOL(cdc_parse_cdc_header);
+
/*
* The function can't be called inside suspend/resume callback,
* otherwise deadlock will be caused.
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 46f4caddccbe..899ea4288197 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2157,12 +2157,13 @@ vmxnet3_set_mc(struct net_device *netdev)
if (!netdev_mc_empty(netdev)) {
new_table = vmxnet3_copy_mc(netdev);
if (new_table) {
- rxConf->mfTableLen = cpu_to_le16(
- netdev_mc_count(netdev) * ETH_ALEN);
+ size_t sz = netdev_mc_count(netdev) * ETH_ALEN;
+
+ rxConf->mfTableLen = cpu_to_le16(sz);
new_table_pa = dma_map_single(
&adapter->pdev->dev,
new_table,
- rxConf->mfTableLen,
+ sz,
PCI_DMA_TODEVICE);
}
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index c1d0e7a9da04..9ba11d737753 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -183,16 +183,22 @@ vmxnet3_get_sset_count(struct net_device *netdev, int sset)
}
-/* Should be multiple of 4 */
-#define NUM_TX_REGS 8
-#define NUM_RX_REGS 12
-
+/* This is a version 2 of the vmxnet3 ethtool_regs which goes hand in hand with
+ * the version 2 of the vmxnet3 support for ethtool(8) --register-dump.
+ * Therefore, if any registers are added, removed or modified, then a version
+ * bump and a corresponding change in the vmxnet3 support for ethtool(8)
+ * --register-dump would be required.
+ */
static int
vmxnet3_get_regs_len(struct net_device *netdev)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- return (adapter->num_tx_queues * NUM_TX_REGS * sizeof(u32) +
- adapter->num_rx_queues * NUM_RX_REGS * sizeof(u32));
+
+ return ((9 /* BAR1 registers */ +
+ (1 + adapter->intr.num_intrs) +
+ (1 + adapter->num_tx_queues * 17 /* Tx queue registers */) +
+ (1 + adapter->num_rx_queues * 23 /* Rx queue registers */)) *
+ sizeof(u32));
}
@@ -208,10 +214,6 @@ vmxnet3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
- drvinfo->n_stats = vmxnet3_get_sset_count(netdev, ETH_SS_STATS);
- drvinfo->testinfo_len = 0;
- drvinfo->eedump_len = 0;
- drvinfo->regdump_len = vmxnet3_get_regs_len(netdev);
}
@@ -342,6 +344,12 @@ vmxnet3_get_ethtool_stats(struct net_device *netdev,
}
+/* This is a version 2 of the vmxnet3 ethtool_regs which goes hand in hand with
+ * the version 2 of the vmxnet3 support for ethtool(8) --register-dump.
+ * Therefore, if any registers are added, removed or modified, then a version
+ * bump and a corresponding change in the vmxnet3 support for ethtool(8)
+ * --register-dump would be required.
+ */
static void
vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
{
@@ -351,40 +359,90 @@ vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
memset(p, 0, vmxnet3_get_regs_len(netdev));
- regs->version = 1;
+ regs->version = 2;
/* Update vmxnet3_get_regs_len if we want to dump more registers */
- /* make each ring use multiple of 16 bytes */
- for (i = 0; i < adapter->num_tx_queues; i++) {
- buf[j++] = adapter->tx_queue[i].tx_ring.next2fill;
- buf[j++] = adapter->tx_queue[i].tx_ring.next2comp;
- buf[j++] = adapter->tx_queue[i].tx_ring.gen;
- buf[j++] = 0;
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_VRRS);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_UVRS);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_DSAL);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_DSAH);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACL);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACH);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ICR);
+ buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ECR);
+
+ buf[j++] = adapter->intr.num_intrs;
+ for (i = 0; i < adapter->intr.num_intrs; i++) {
+ buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_IMR
+ + i * VMXNET3_REG_ALIGN);
+ }
- buf[j++] = adapter->tx_queue[i].comp_ring.next2proc;
- buf[j++] = adapter->tx_queue[i].comp_ring.gen;
- buf[j++] = adapter->tx_queue[i].stopped;
- buf[j++] = 0;
+ buf[j++] = adapter->num_tx_queues;
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct vmxnet3_tx_queue *tq = &adapter->tx_queue[i];
+
+ buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_TXPROD +
+ i * VMXNET3_REG_ALIGN);
+
+ buf[j++] = VMXNET3_GET_ADDR_LO(tq->tx_ring.basePA);
+ buf[j++] = VMXNET3_GET_ADDR_HI(tq->tx_ring.basePA);
+ buf[j++] = tq->tx_ring.size;
+ buf[j++] = tq->tx_ring.next2fill;
+ buf[j++] = tq->tx_ring.next2comp;
+ buf[j++] = tq->tx_ring.gen;
+
+ buf[j++] = VMXNET3_GET_ADDR_LO(tq->data_ring.basePA);
+ buf[j++] = VMXNET3_GET_ADDR_HI(tq->data_ring.basePA);
+ buf[j++] = tq->data_ring.size;
+ /* transmit data ring buffer size */
+ buf[j++] = VMXNET3_HDR_COPY_SIZE;
+
+ buf[j++] = VMXNET3_GET_ADDR_LO(tq->comp_ring.basePA);
+ buf[j++] = VMXNET3_GET_ADDR_HI(tq->comp_ring.basePA);
+ buf[j++] = tq->comp_ring.size;
+ buf[j++] = tq->comp_ring.next2proc;
+ buf[j++] = tq->comp_ring.gen;
+
+ buf[j++] = tq->stopped;
}
+ buf[j++] = adapter->num_rx_queues;
for (i = 0; i < adapter->num_rx_queues; i++) {
- buf[j++] = adapter->rx_queue[i].rx_ring[0].next2fill;
- buf[j++] = adapter->rx_queue[i].rx_ring[0].next2comp;
- buf[j++] = adapter->rx_queue[i].rx_ring[0].gen;
+ struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i];
+
+ buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_RXPROD +
+ i * VMXNET3_REG_ALIGN);
+ buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_RXPROD2 +
+ i * VMXNET3_REG_ALIGN);
+
+ buf[j++] = VMXNET3_GET_ADDR_LO(rq->rx_ring[0].basePA);
+ buf[j++] = VMXNET3_GET_ADDR_HI(rq->rx_ring[0].basePA);
+ buf[j++] = rq->rx_ring[0].size;
+ buf[j++] = rq->rx_ring[0].next2fill;
+ buf[j++] = rq->rx_ring[0].next2comp;
+ buf[j++] = rq->rx_ring[0].gen;
+
+ buf[j++] = VMXNET3_GET_ADDR_LO(rq->rx_ring[1].basePA);
+ buf[j++] = VMXNET3_GET_ADDR_HI(rq->rx_ring[1].basePA);
+ buf[j++] = rq->rx_ring[1].size;
+ buf[j++] = rq->rx_ring[1].next2fill;
+ buf[j++] = rq->rx_ring[1].next2comp;
+ buf[j++] = rq->rx_ring[1].gen;
+
+ /* receive data ring */
buf[j++] = 0;
-
- buf[j++] = adapter->rx_queue[i].rx_ring[1].next2fill;
- buf[j++] = adapter->rx_queue[i].rx_ring[1].next2comp;
- buf[j++] = adapter->rx_queue[i].rx_ring[1].gen;
buf[j++] = 0;
-
- buf[j++] = adapter->rx_queue[i].comp_ring.next2proc;
- buf[j++] = adapter->rx_queue[i].comp_ring.gen;
buf[j++] = 0;
buf[j++] = 0;
- }
+ buf[j++] = VMXNET3_GET_ADDR_LO(rq->comp_ring.basePA);
+ buf[j++] = VMXNET3_GET_ADDR_HI(rq->comp_ring.basePA);
+ buf[j++] = rq->comp_ring.size;
+ buf[j++] = rq->comp_ring.next2proc;
+ buf[j++] = rq->comp_ring.gen;
+ }
}
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 2652245631d1..4c58c83dc225 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -69,10 +69,10 @@
/*
* Version numbers
*/
-#define VMXNET3_DRIVER_VERSION_STRING "1.4.2.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING "1.4.4.0-k"
/* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM 0x01040200
+#define VMXNET3_DRIVER_VERSION_NUM 0x01040400
#if defined(CONFIG_PCI_MSI)
/* RSS only makes sense if MSI-X is supported. */
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 488c6f50df73..92fa3e1ea65c 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -30,20 +30,38 @@
#include <net/arp.h>
#include <net/ip.h>
#include <net/ip_fib.h>
+#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#include <net/rtnetlink.h>
#include <net/route.h>
#include <net/addrconf.h>
-#include <net/vrf.h>
+#include <net/l3mdev.h>
+
+#define RT_FL_TOS(oldflp4) \
+ ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
#define DRV_NAME "vrf"
#define DRV_VERSION "1.0"
-#define vrf_is_slave(dev) ((dev)->flags & IFF_SLAVE)
-
#define vrf_master_get_rcu(dev) \
((struct net_device *)rcu_dereference(dev->rx_handler_data))
+struct slave {
+ struct list_head list;
+ struct net_device *dev;
+};
+
+struct slave_queue {
+ struct list_head all_slaves;
+};
+
+struct net_vrf {
+ struct slave_queue queue;
+ struct rtable *rth;
+ struct rt6_info *rt6;
+ u32 tb_id;
+};
+
struct pcpu_dstats {
u64 tx_pkts;
u64 tx_bytes;
@@ -58,9 +76,9 @@ static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie)
return dst;
}
-static int vrf_ip_local_out(struct sk_buff *skb)
+static int vrf_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
- return ip_local_out(skb);
+ return ip_local_out(net, sk, skb);
}
static unsigned int vrf_v4_mtu(const struct dst_entry *dst)
@@ -88,12 +106,56 @@ static struct dst_ops vrf_dst_ops = {
.default_advmss = vrf_default_advmss,
};
+/* neighbor handling is done with actual device; do not want
+ * to flip skb->dev for those ndisc packets. This really fails
+ * for multiple next protocols (e.g., NEXTHDR_HOP). But it is
+ * a start.
+ */
+#if IS_ENABLED(CONFIG_IPV6)
+static bool check_ipv6_frame(const struct sk_buff *skb)
+{
+ const struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->data;
+ size_t hlen = sizeof(*ipv6h);
+ bool rc = true;
+
+ if (skb->len < hlen)
+ goto out;
+
+ if (ipv6h->nexthdr == NEXTHDR_ICMP) {
+ const struct icmp6hdr *icmph;
+
+ if (skb->len < hlen + sizeof(*icmph))
+ goto out;
+
+ icmph = (struct icmp6hdr *)(skb->data + sizeof(*ipv6h));
+ switch (icmph->icmp6_type) {
+ case NDISC_ROUTER_SOLICITATION:
+ case NDISC_ROUTER_ADVERTISEMENT:
+ case NDISC_NEIGHBOUR_SOLICITATION:
+ case NDISC_NEIGHBOUR_ADVERTISEMENT:
+ case NDISC_REDIRECT:
+ rc = false;
+ break;
+ }
+ }
+
+out:
+ return rc;
+}
+#else
+static bool check_ipv6_frame(const struct sk_buff *skb)
+{
+ return false;
+}
+#endif
+
static bool is_ip_rx_frame(struct sk_buff *skb)
{
switch (skb->protocol) {
case htons(ETH_P_IP):
- case htons(ETH_P_IPV6):
return true;
+ case htons(ETH_P_IPV6):
+ return check_ipv6_frame(skb);
}
return false;
}
@@ -153,12 +215,53 @@ static struct rtnl_link_stats64 *vrf_get_stats64(struct net_device *dev,
return stats;
}
+#if IS_ENABLED(CONFIG_IPV6)
+static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+ struct net *net = dev_net(skb->dev);
+ struct flowi6 fl6 = {
+ /* needed to match OIF rule */
+ .flowi6_oif = dev->ifindex,
+ .flowi6_iif = LOOPBACK_IFINDEX,
+ .daddr = iph->daddr,
+ .saddr = iph->saddr,
+ .flowlabel = ip6_flowinfo(iph),
+ .flowi6_mark = skb->mark,
+ .flowi6_proto = iph->nexthdr,
+ .flowi6_flags = FLOWI_FLAG_L3MDEV_SRC | FLOWI_FLAG_SKIP_NH_OIF,
+ };
+ int ret = NET_XMIT_DROP;
+ struct dst_entry *dst;
+ struct dst_entry *dst_null = &net->ipv6.ip6_null_entry->dst;
+
+ dst = ip6_route_output(net, NULL, &fl6);
+ if (dst == dst_null)
+ goto err;
+
+ skb_dst_drop(skb);
+ skb_dst_set(skb, dst);
+
+ ret = ip6_local_out(net, skb->sk, skb);
+ if (unlikely(net_xmit_eval(ret)))
+ dev->stats.tx_errors++;
+ else
+ ret = NET_XMIT_SUCCESS;
+
+ return ret;
+err:
+ vrf_tx_error(dev, skb);
+ return NET_XMIT_DROP;
+}
+#else
static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
struct net_device *dev)
{
vrf_tx_error(dev, skb);
return NET_XMIT_DROP;
}
+#endif
static int vrf_send_v4_prep(struct sk_buff *skb, struct flowi4 *fl4,
struct net_device *vrf_dev)
@@ -193,7 +296,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
.flowi4_oif = vrf_dev->ifindex,
.flowi4_iif = LOOPBACK_IFINDEX,
.flowi4_tos = RT_TOS(ip4h->tos),
- .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_VRFSRC |
+ .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_L3MDEV_SRC |
FLOWI_FLAG_SKIP_NH_OIF,
.daddr = ip4h->daddr,
};
@@ -206,7 +309,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
RT_SCOPE_LINK);
}
- ret = ip_local_out(skb);
+ ret = ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
if (unlikely(net_xmit_eval(ret)))
vrf_dev->stats.tx_errors++;
else
@@ -253,8 +356,159 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
return ret;
}
+#if IS_ENABLED(CONFIG_IPV6)
+static struct dst_entry *vrf_ip6_check(struct dst_entry *dst, u32 cookie)
+{
+ return dst;
+}
+
+static struct dst_ops vrf_dst_ops6 = {
+ .family = AF_INET6,
+ .local_out = ip6_local_out,
+ .check = vrf_ip6_check,
+ .mtu = vrf_v4_mtu,
+ .destroy = vrf_dst_destroy,
+ .default_advmss = vrf_default_advmss,
+};
+
+static int init_dst_ops6_kmem_cachep(void)
+{
+ vrf_dst_ops6.kmem_cachep = kmem_cache_create("vrf_ip6_dst_cache",
+ sizeof(struct rt6_info),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+ NULL);
+
+ if (!vrf_dst_ops6.kmem_cachep)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void free_dst_ops6_kmem_cachep(void)
+{
+ kmem_cache_destroy(vrf_dst_ops6.kmem_cachep);
+}
+
+static int vrf_input6(struct sk_buff *skb)
+{
+ skb->dev->stats.rx_errors++;
+ kfree_skb(skb);
+ return 0;
+}
+
+/* modelled after ip6_finish_output2 */
+static int vrf_finish_output6(struct net *net, struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ struct net_device *dev = dst->dev;
+ struct neighbour *neigh;
+ struct in6_addr *nexthop;
+ int ret;
+
+ skb->protocol = htons(ETH_P_IPV6);
+ skb->dev = dev;
+
+ rcu_read_lock_bh();
+ nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
+ neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
+ if (unlikely(!neigh))
+ neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
+ if (!IS_ERR(neigh)) {
+ ret = dst_neigh_output(dst, neigh, skb);
+ rcu_read_unlock_bh();
+ return ret;
+ }
+ rcu_read_unlock_bh();
+
+ IP6_INC_STATS(dev_net(dst->dev),
+ ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/* modelled after ip6_output */
+static int vrf_output6(struct net *net, struct sock *sk, struct sk_buff *skb)
+{
+ return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
+ net, sk, skb, NULL, skb_dst(skb)->dev,
+ vrf_finish_output6,
+ !(IP6CB(skb)->flags & IP6SKB_REROUTED));
+}
+
+static void vrf_rt6_destroy(struct net_vrf *vrf)
+{
+ dst_destroy(&vrf->rt6->dst);
+ free_percpu(vrf->rt6->rt6i_pcpu);
+ vrf->rt6 = NULL;
+}
+
+static int vrf_rt6_create(struct net_device *dev)
+{
+ struct net_vrf *vrf = netdev_priv(dev);
+ struct dst_entry *dst;
+ struct rt6_info *rt6;
+ int cpu;
+ int rc = -ENOMEM;
+
+ rt6 = dst_alloc(&vrf_dst_ops6, dev, 0,
+ DST_OBSOLETE_NONE,
+ (DST_HOST | DST_NOPOLICY | DST_NOXFRM));
+ if (!rt6)
+ goto out;
+
+ dst = &rt6->dst;
+
+ rt6->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_KERNEL);
+ if (!rt6->rt6i_pcpu) {
+ dst_destroy(dst);
+ goto out;
+ }
+ for_each_possible_cpu(cpu) {
+ struct rt6_info **p = per_cpu_ptr(rt6->rt6i_pcpu, cpu);
+ *p = NULL;
+ }
+
+ memset(dst + 1, 0, sizeof(*rt6) - sizeof(*dst));
+
+ INIT_LIST_HEAD(&rt6->rt6i_siblings);
+ INIT_LIST_HEAD(&rt6->rt6i_uncached);
+
+ rt6->dst.input = vrf_input6;
+ rt6->dst.output = vrf_output6;
+
+ rt6->rt6i_table = fib6_get_table(dev_net(dev), vrf->tb_id);
+
+ atomic_set(&rt6->dst.__refcnt, 2);
+
+ vrf->rt6 = rt6;
+ rc = 0;
+out:
+ return rc;
+}
+#else
+static int init_dst_ops6_kmem_cachep(void)
+{
+ return 0;
+}
+
+static void free_dst_ops6_kmem_cachep(void)
+{
+}
+
+static void vrf_rt6_destroy(struct net_vrf *vrf)
+{
+}
+
+static int vrf_rt6_create(struct net_device *dev)
+{
+ return 0;
+}
+#endif
+
/* modelled after ip_finish_output2 */
-static int vrf_finish_output(struct sock *sk, struct sk_buff *skb)
+static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct rtable *rt = (struct rtable *)dst;
@@ -296,17 +550,17 @@ err:
return ret;
}
-static int vrf_output(struct sock *sk, struct sk_buff *skb)
+static int vrf_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
- IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
+ IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len);
skb->dev = dev;
skb->protocol = htons(ETH_P_IP);
- return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb,
- NULL, dev,
+ return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
+ net, sk, skb, NULL, dev,
vrf_finish_output,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
@@ -321,6 +575,7 @@ static void vrf_rtable_destroy(struct net_vrf *vrf)
static struct rtable *vrf_rtable_create(struct net_device *dev)
{
+ struct net_vrf *vrf = netdev_priv(dev);
struct rtable *rth;
rth = dst_alloc(&vrf_dst_ops, dev, 2,
@@ -336,6 +591,7 @@ static struct rtable *vrf_rtable_create(struct net_device *dev)
rth->rt_pmtu = 0;
rth->rt_gateway = 0;
rth->rt_uses_gateway = 0;
+ rth->rt_table_id = vrf->tb_id;
INIT_LIST_HEAD(&rth->rt_uncached);
rth->rt_uncached_list = NULL;
}
@@ -392,18 +648,15 @@ static void __vrf_insert_slave(struct slave_queue *queue, struct slave *slave)
static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
{
- struct net_vrf_dev *vrf_ptr = kmalloc(sizeof(*vrf_ptr), GFP_KERNEL);
struct slave *slave = kzalloc(sizeof(*slave), GFP_KERNEL);
struct net_vrf *vrf = netdev_priv(dev);
struct slave_queue *queue = &vrf->queue;
int ret = -ENOMEM;
- if (!slave || !vrf_ptr)
+ if (!slave)
goto out_fail;
slave->dev = port_dev;
- vrf_ptr->ifindex = dev->ifindex;
- vrf_ptr->tb_id = vrf->tb_id;
/* register the packet handler for slave ports */
ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev);
@@ -418,9 +671,8 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
if (ret < 0)
goto out_unregister;
- port_dev->flags |= IFF_SLAVE;
+ port_dev->priv_flags |= IFF_L3MDEV_SLAVE;
__vrf_insert_slave(queue, slave);
- rcu_assign_pointer(port_dev->vrf_ptr, vrf_ptr);
cycle_netdev(port_dev);
return 0;
@@ -428,14 +680,13 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
out_unregister:
netdev_rx_handler_unregister(port_dev);
out_fail:
- kfree(vrf_ptr);
kfree(slave);
return ret;
}
static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
{
- if (netif_is_vrf(port_dev) || vrf_is_slave(port_dev))
+ if (netif_is_l3_master(port_dev) || netif_is_l3_slave(port_dev))
return -EINVAL;
return do_vrf_add_slave(dev, port_dev);
@@ -444,21 +695,15 @@ static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
/* inverse of do_vrf_add_slave */
static int do_vrf_del_slave(struct net_device *dev, struct net_device *port_dev)
{
- struct net_vrf_dev *vrf_ptr = rtnl_dereference(port_dev->vrf_ptr);
struct net_vrf *vrf = netdev_priv(dev);
struct slave_queue *queue = &vrf->queue;
struct slave *slave;
- RCU_INIT_POINTER(port_dev->vrf_ptr, NULL);
-
netdev_upper_dev_unlink(port_dev, dev);
- port_dev->flags &= ~IFF_SLAVE;
+ port_dev->priv_flags &= ~IFF_L3MDEV_SLAVE;
netdev_rx_handler_unregister(port_dev);
- /* after netdev_rx_handler_unregister for synchronize_rcu */
- kfree(vrf_ptr);
-
cycle_netdev(port_dev);
slave = __vrf_find_slave_dev(queue, port_dev);
@@ -483,6 +728,7 @@ static void vrf_dev_uninit(struct net_device *dev)
struct slave *slave, *next;
vrf_rtable_destroy(vrf);
+ vrf_rt6_destroy(vrf);
list_for_each_entry_safe(slave, next, head, list)
vrf_del_slave(dev, slave->dev);
@@ -506,10 +752,15 @@ static int vrf_dev_init(struct net_device *dev)
if (!vrf->rth)
goto out_stats;
+ if (vrf_rt6_create(dev) != 0)
+ goto out_rth;
+
dev->flags = IFF_MASTER | IFF_NOARP;
return 0;
+out_rth:
+ vrf_rtable_destroy(vrf);
out_stats:
free_percpu(dev->dstats);
dev->dstats = NULL;
@@ -526,6 +777,85 @@ static const struct net_device_ops vrf_netdev_ops = {
.ndo_del_slave = vrf_del_slave,
};
+static u32 vrf_fib_table(const struct net_device *dev)
+{
+ struct net_vrf *vrf = netdev_priv(dev);
+
+ return vrf->tb_id;
+}
+
+static struct rtable *vrf_get_rtable(const struct net_device *dev,
+ const struct flowi4 *fl4)
+{
+ struct rtable *rth = NULL;
+
+ if (!(fl4->flowi4_flags & FLOWI_FLAG_L3MDEV_SRC)) {
+ struct net_vrf *vrf = netdev_priv(dev);
+
+ rth = vrf->rth;
+ atomic_inc(&rth->dst.__refcnt);
+ }
+
+ return rth;
+}
+
+/* called under rcu_read_lock */
+static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
+{
+ struct fib_result res = { .tclassid = 0 };
+ struct net *net = dev_net(dev);
+ u32 orig_tos = fl4->flowi4_tos;
+ u8 flags = fl4->flowi4_flags;
+ u8 scope = fl4->flowi4_scope;
+ u8 tos = RT_FL_TOS(fl4);
+
+ if (unlikely(!fl4->daddr))
+ return;
+
+ fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF;
+ fl4->flowi4_iif = LOOPBACK_IFINDEX;
+ fl4->flowi4_tos = tos & IPTOS_RT_MASK;
+ fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
+ RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
+
+ if (!fib_lookup(net, fl4, &res, 0)) {
+ if (res.type == RTN_LOCAL)
+ fl4->saddr = res.fi->fib_prefsrc ? : fl4->daddr;
+ else
+ fib_select_path(net, &res, fl4, -1);
+ }
+
+ fl4->flowi4_flags = flags;
+ fl4->flowi4_tos = orig_tos;
+ fl4->flowi4_scope = scope;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static struct dst_entry *vrf_get_rt6_dst(const struct net_device *dev,
+ const struct flowi6 *fl6)
+{
+ struct rt6_info *rt = NULL;
+
+ if (!(fl6->flowi6_flags & FLOWI_FLAG_L3MDEV_SRC)) {
+ struct net_vrf *vrf = netdev_priv(dev);
+
+ rt = vrf->rt6;
+ atomic_inc(&rt->dst.__refcnt);
+ }
+
+ return (struct dst_entry *)rt;
+}
+#endif
+
+static const struct l3mdev_ops vrf_l3mdev_ops = {
+ .l3mdev_fib_table = vrf_fib_table,
+ .l3mdev_get_rtable = vrf_get_rtable,
+ .l3mdev_get_saddr = vrf_get_saddr,
+#if IS_ENABLED(CONFIG_IPV6)
+ .l3mdev_get_rt6_dst = vrf_get_rt6_dst,
+#endif
+};
+
static void vrf_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -543,6 +873,7 @@ static void vrf_setup(struct net_device *dev)
/* Initialize the device structure. */
dev->netdev_ops = &vrf_netdev_ops;
+ dev->l3mdev_ops = &vrf_l3mdev_ops;
dev->ethtool_ops = &vrf_ethtool_ops;
dev->destructor = free_netdev;
@@ -569,10 +900,6 @@ static int vrf_validate(struct nlattr *tb[], struct nlattr *data[])
static void vrf_dellink(struct net_device *dev, struct list_head *head)
{
- struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr);
-
- RCU_INIT_POINTER(dev->vrf_ptr, NULL);
- kfree_rcu(vrf_ptr, rcu);
unregister_netdevice_queue(dev, head);
}
@@ -580,7 +907,6 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct net_vrf *vrf = netdev_priv(dev);
- struct net_vrf_dev *vrf_ptr;
int err;
if (!data || !data[IFLA_VRF_TABLE])
@@ -588,26 +914,15 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]);
- dev->priv_flags |= IFF_VRF_MASTER;
-
- err = -ENOMEM;
- vrf_ptr = kmalloc(sizeof(*dev->vrf_ptr), GFP_KERNEL);
- if (!vrf_ptr)
- goto out_fail;
-
- vrf_ptr->ifindex = dev->ifindex;
- vrf_ptr->tb_id = vrf->tb_id;
+ dev->priv_flags |= IFF_L3MDEV_MASTER;
err = register_netdevice(dev);
if (err < 0)
goto out_fail;
- rcu_assign_pointer(dev->vrf_ptr, vrf_ptr);
-
return 0;
out_fail:
- kfree(vrf_ptr);
free_netdev(dev);
return err;
}
@@ -651,10 +966,9 @@ static int vrf_device_event(struct notifier_block *unused,
/* only care about unregister events to drop slave references */
if (event == NETDEV_UNREGISTER) {
- struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr);
struct net_device *vrf_dev;
- if (!vrf_ptr || netif_is_vrf(dev))
+ if (!netif_is_l3_slave(dev))
goto out;
vrf_dev = netdev_master_upper_dev_get(dev);
@@ -681,6 +995,10 @@ static int __init vrf_init_module(void)
if (!vrf_dst_ops.kmem_cachep)
return -ENOMEM;
+ rc = init_dst_ops6_kmem_cachep();
+ if (rc != 0)
+ goto error2;
+
register_netdevice_notifier(&vrf_notifier_block);
rc = rtnl_link_register(&vrf_link_ops);
@@ -691,6 +1009,8 @@ static int __init vrf_init_module(void)
error:
unregister_netdevice_notifier(&vrf_notifier_block);
+ free_dst_ops6_kmem_cachep();
+error2:
kmem_cache_destroy(vrf_dst_ops.kmem_cachep);
return rc;
}
@@ -700,6 +1020,7 @@ static void __exit vrf_cleanup_module(void)
rtnl_link_unregister(&vrf_link_ops);
unregister_netdevice_notifier(&vrf_notifier_block);
kmem_cache_destroy(vrf_dst_ops.kmem_cachep);
+ free_dst_ops6_kmem_cachep();
}
module_init(vrf_init_module);
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bbac1d35ed4e..6369a5734d4c 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -75,8 +75,7 @@ static struct rtnl_link_ops vxlan_link_ops;
static const u8 all_zeros_mac[ETH_ALEN];
-static struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
- bool no_share, u32 flags);
+static int vxlan_sock_add(struct vxlan_dev *vxlan);
/* per-network namespace private data for this module */
struct vxlan_net {
@@ -994,19 +993,30 @@ static bool vxlan_snoop(struct net_device *dev,
static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
{
struct vxlan_dev *vxlan;
+ unsigned short family = dev->default_dst.remote_ip.sa.sa_family;
/* The vxlan_sock is only used by dev, leaving group has
* no effect on other vxlan devices.
*/
- if (atomic_read(&dev->vn_sock->refcnt) == 1)
+ if (family == AF_INET && dev->vn4_sock &&
+ atomic_read(&dev->vn4_sock->refcnt) == 1)
return false;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (family == AF_INET6 && dev->vn6_sock &&
+ atomic_read(&dev->vn6_sock->refcnt) == 1)
+ return false;
+#endif
list_for_each_entry(vxlan, &vn->vxlan_list, next) {
if (!netif_running(vxlan->dev) || vxlan == dev)
continue;
- if (vxlan->vn_sock != dev->vn_sock)
+ if (family == AF_INET && vxlan->vn4_sock != dev->vn4_sock)
+ continue;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (family == AF_INET6 && vxlan->vn6_sock != dev->vn6_sock)
continue;
+#endif
if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip,
&dev->default_dst.remote_ip))
@@ -1022,15 +1032,16 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
return false;
}
-static void vxlan_sock_release(struct vxlan_sock *vs)
+static void __vxlan_sock_release(struct vxlan_sock *vs)
{
- struct sock *sk = vs->sock->sk;
- struct net *net = sock_net(sk);
- struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+ struct vxlan_net *vn;
+ if (!vs)
+ return;
if (!atomic_dec_and_test(&vs->refcnt))
return;
+ vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
spin_lock(&vn->sock_lock);
hlist_del_rcu(&vs->hlist);
vxlan_notify_del_rx_port(vs);
@@ -1039,32 +1050,43 @@ static void vxlan_sock_release(struct vxlan_sock *vs)
queue_work(vxlan_wq, &vs->del_work);
}
+static void vxlan_sock_release(struct vxlan_dev *vxlan)
+{
+ __vxlan_sock_release(vxlan->vn4_sock);
+#if IS_ENABLED(CONFIG_IPV6)
+ __vxlan_sock_release(vxlan->vn6_sock);
+#endif
+}
+
/* Update multicast group membership when first VNI on
* multicast address is brought up
*/
static int vxlan_igmp_join(struct vxlan_dev *vxlan)
{
- struct vxlan_sock *vs = vxlan->vn_sock;
- struct sock *sk = vs->sock->sk;
+ struct sock *sk;
union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
int ifindex = vxlan->default_dst.remote_ifindex;
int ret = -EINVAL;
- lock_sock(sk);
if (ip->sa.sa_family == AF_INET) {
struct ip_mreqn mreq = {
.imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr,
.imr_ifindex = ifindex,
};
+ sk = vxlan->vn4_sock->sock->sk;
+ lock_sock(sk);
ret = ip_mc_join_group(sk, &mreq);
+ release_sock(sk);
#if IS_ENABLED(CONFIG_IPV6)
} else {
+ sk = vxlan->vn6_sock->sock->sk;
+ lock_sock(sk);
ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
&ip->sin6.sin6_addr);
+ release_sock(sk);
#endif
}
- release_sock(sk);
return ret;
}
@@ -1072,27 +1094,30 @@ static int vxlan_igmp_join(struct vxlan_dev *vxlan)
/* Inverse of vxlan_igmp_join when last VNI is brought down */
static int vxlan_igmp_leave(struct vxlan_dev *vxlan)
{
- struct vxlan_sock *vs = vxlan->vn_sock;
- struct sock *sk = vs->sock->sk;
+ struct sock *sk;
union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
int ifindex = vxlan->default_dst.remote_ifindex;
int ret = -EINVAL;
- lock_sock(sk);
if (ip->sa.sa_family == AF_INET) {
struct ip_mreqn mreq = {
.imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr,
.imr_ifindex = ifindex,
};
+ sk = vxlan->vn4_sock->sock->sk;
+ lock_sock(sk);
ret = ip_mc_leave_group(sk, &mreq);
+ release_sock(sk);
#if IS_ENABLED(CONFIG_IPV6)
} else {
+ sk = vxlan->vn6_sock->sock->sk;
+ lock_sock(sk);
ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
&ip->sin6.sin6_addr);
+ release_sock(sk);
#endif
}
- release_sock(sk);
return ret;
}
@@ -1873,8 +1898,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
{
struct ip_tunnel_info *info;
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct sock *sk = vxlan->vn_sock->sock->sk;
- unsigned short family = vxlan_get_sk_family(vxlan->vn_sock);
+ struct sock *sk;
struct rtable *rt = NULL;
const struct iphdr *old_iph;
struct flowi4 fl4;
@@ -1901,13 +1925,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
dev->name);
goto drop;
}
- if (family != ip_tunnel_info_af(info))
- goto drop;
-
dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
vni = be64_to_cpu(info->key.tun_id);
- remote_ip.sa.sa_family = family;
- if (family == AF_INET)
+ remote_ip.sa.sa_family = ip_tunnel_info_af(info);
+ if (remote_ip.sa.sa_family == AF_INET)
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
else
remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
@@ -1952,6 +1973,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
}
if (dst->sa.sa_family == AF_INET) {
+ if (!vxlan->vn4_sock)
+ goto drop;
+ sk = vxlan->vn4_sock->sock->sk;
+
if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT))
df = htons(IP_DF);
@@ -2013,6 +2038,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct flowi6 fl6;
u32 rt6i_flags;
+ if (!vxlan->vn6_sock)
+ goto drop;
+ sk = vxlan->vn6_sock->sock->sk;
+
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_oif = rdst ? rdst->remote_ifindex : 0;
fl6.daddr = dst->sin6.sin6_addr;
@@ -2204,7 +2233,6 @@ static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
__u32 vni = vxlan->default_dst.remote_vni;
- vxlan->vn_sock = vs;
spin_lock(&vn->sock_lock);
hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
spin_unlock(&vn->sock_lock);
@@ -2244,22 +2272,18 @@ static void vxlan_uninit(struct net_device *dev)
static int vxlan_open(struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_sock *vs;
- int ret = 0;
-
- vs = vxlan_sock_add(vxlan->net, vxlan->cfg.dst_port,
- vxlan->cfg.no_share, vxlan->flags);
- if (IS_ERR(vs))
- return PTR_ERR(vs);
+ int ret;
- vxlan_vs_add_dev(vs, vxlan);
+ ret = vxlan_sock_add(vxlan);
+ if (ret < 0)
+ return ret;
if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
ret = vxlan_igmp_join(vxlan);
if (ret == -EADDRINUSE)
ret = 0;
if (ret) {
- vxlan_sock_release(vs);
+ vxlan_sock_release(vxlan);
return ret;
}
}
@@ -2294,7 +2318,6 @@ static int vxlan_stop(struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
- struct vxlan_sock *vs = vxlan->vn_sock;
int ret = 0;
if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
@@ -2304,7 +2327,7 @@ static int vxlan_stop(struct net_device *dev)
del_timer_sync(&vxlan->age_timer);
vxlan_flush(vxlan);
- vxlan_sock_release(vs);
+ vxlan_sock_release(vxlan);
return ret;
}
@@ -2337,6 +2360,46 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+ struct ip_tunnel_info *info,
+ __be16 sport, __be16 dport)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct rtable *rt;
+ struct flowi4 fl4;
+
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.flowi4_tos = RT_TOS(info->key.tos);
+ fl4.flowi4_mark = skb->mark;
+ fl4.flowi4_proto = IPPROTO_UDP;
+ fl4.daddr = info->key.u.ipv4.dst;
+
+ rt = ip_route_output_key(vxlan->net, &fl4);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+ ip_rt_put(rt);
+
+ info->key.u.ipv4.src = fl4.saddr;
+ info->key.tp_src = sport;
+ info->key.tp_dst = dport;
+ return 0;
+}
+
+static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+ __be16 sport, dport;
+
+ sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
+ vxlan->cfg.port_max, true);
+ dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
+
+ if (ip_tunnel_info_af(info) == AF_INET)
+ return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+ return -EINVAL;
+}
+
static const struct net_device_ops vxlan_netdev_ops = {
.ndo_init = vxlan_init,
.ndo_uninit = vxlan_uninit,
@@ -2351,6 +2414,7 @@ static const struct net_device_ops vxlan_netdev_ops = {
.ndo_fdb_add = vxlan_fdb_add,
.ndo_fdb_del = vxlan_fdb_delete,
.ndo_fdb_dump = vxlan_fdb_dump,
+ .ndo_fill_metadata_dst = vxlan_fill_metadata_dst,
};
/* Info for udev, that this is a virtual tunnel endpoint */
@@ -2540,14 +2604,13 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
}
/* Create new listen socket if needed */
-static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
- u32 flags)
+static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
+ __be16 port, u32 flags)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct vxlan_sock *vs;
struct socket *sock;
unsigned int h;
- bool ipv6 = !!(flags & VXLAN_F_IPV6);
struct udp_tunnel_sock_cfg tunnel_cfg;
vs = kzalloc(sizeof(*vs), GFP_KERNEL);
@@ -2592,27 +2655,53 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
return vs;
}
-static struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
- bool no_share, u32 flags)
+static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
{
- struct vxlan_net *vn = net_generic(net, vxlan_net_id);
- struct vxlan_sock *vs;
- bool ipv6 = flags & VXLAN_F_IPV6;
+ struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+ struct vxlan_sock *vs = NULL;
- if (!no_share) {
+ if (!vxlan->cfg.no_share) {
spin_lock(&vn->sock_lock);
- vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port,
- flags);
- if (vs) {
- if (!atomic_add_unless(&vs->refcnt, 1, 0))
- vs = ERR_PTR(-EBUSY);
+ vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
+ vxlan->cfg.dst_port, vxlan->flags);
+ if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) {
spin_unlock(&vn->sock_lock);
- return vs;
+ return -EBUSY;
}
spin_unlock(&vn->sock_lock);
}
+ if (!vs)
+ vs = vxlan_socket_create(vxlan->net, ipv6,
+ vxlan->cfg.dst_port, vxlan->flags);
+ if (IS_ERR(vs))
+ return PTR_ERR(vs);
+#if IS_ENABLED(CONFIG_IPV6)
+ if (ipv6)
+ vxlan->vn6_sock = vs;
+ else
+#endif
+ vxlan->vn4_sock = vs;
+ vxlan_vs_add_dev(vs, vxlan);
+ return 0;
+}
- return vxlan_socket_create(net, port, flags);
+static int vxlan_sock_add(struct vxlan_dev *vxlan)
+{
+ bool ipv6 = vxlan->flags & VXLAN_F_IPV6;
+ bool metadata = vxlan->flags & VXLAN_F_COLLECT_METADATA;
+ int ret = 0;
+
+ vxlan->vn4_sock = NULL;
+#if IS_ENABLED(CONFIG_IPV6)
+ vxlan->vn6_sock = NULL;
+ if (ipv6 || metadata)
+ ret = __vxlan_sock_add(vxlan, true);
+#endif
+ if (!ret && (!ipv6 || metadata))
+ ret = __vxlan_sock_add(vxlan, false);
+ if (ret < 0)
+ vxlan_sock_release(vxlan);
+ return ret;
}
static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
@@ -2621,6 +2710,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
struct vxlan_net *vn = net_generic(src_net, vxlan_net_id);
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
+ unsigned short needed_headroom = ETH_HLEN;
int err;
bool use_ipv6 = false;
__be16 default_port = vxlan->cfg.dst_port;
@@ -2640,6 +2730,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
if (!IS_ENABLED(CONFIG_IPV6))
return -EPFNOSUPPORT;
use_ipv6 = true;
+ vxlan->flags |= VXLAN_F_IPV6;
}
if (conf->remote_ifindex) {
@@ -2660,22 +2751,21 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
pr_info("IPv6 is disabled via sysctl\n");
return -EPERM;
}
- vxlan->flags |= VXLAN_F_IPV6;
}
#endif
if (!conf->mtu)
dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
- dev->needed_headroom = lowerdev->hard_header_len +
- (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
- } else if (use_ipv6) {
- vxlan->flags |= VXLAN_F_IPV6;
- dev->needed_headroom = ETH_HLEN + VXLAN6_HEADROOM;
- } else {
- dev->needed_headroom = ETH_HLEN + VXLAN_HEADROOM;
+ needed_headroom = lowerdev->hard_header_len;
}
+ if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
+ needed_headroom += VXLAN6_HEADROOM;
+ else
+ needed_headroom += VXLAN_HEADROOM;
+ dev->needed_headroom = needed_headroom;
+
memcpy(&vxlan->cfg, conf, sizeof(*conf));
if (!vxlan->cfg.dst_port)
vxlan->cfg.dst_port = default_port;
@@ -2745,11 +2835,10 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
struct vxlan_config conf;
int err;
- if (!data[IFLA_VXLAN_ID])
- return -EINVAL;
-
memset(&conf, 0, sizeof(conf));
- conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
+
+ if (data[IFLA_VXLAN_ID])
+ conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
if (data[IFLA_VXLAN_GROUP]) {
conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index a63ab2e83105..f9f94229bf1b 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -214,8 +214,6 @@ config USB_NET_RNDIS_WLAN
If you choose to build a module, it'll be called rndis_wlan.
-source "drivers/net/wireless/rtl818x/Kconfig"
-
config ADM8211
tristate "ADMtek ADM8211 support"
depends on MAC80211 && PCI
@@ -243,6 +241,8 @@ config ADM8211
Thanks to Infineon-ADMtek for their support of this driver.
+source "drivers/net/wireless/realtek/rtl818x/Kconfig"
+
config MAC80211_HWSIM
tristate "Simulated radio testing tool for mac80211"
depends on MAC80211
@@ -278,7 +278,8 @@ source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/rt2x00/Kconfig"
source "drivers/net/wireless/mediatek/Kconfig"
-source "drivers/net/wireless/rtlwifi/Kconfig"
+source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
+source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
source "drivers/net/wireless/ti/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
source "drivers/net/wireless/mwifiex/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 6b9e729dd8ac..740fdd353c5d 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -22,9 +22,7 @@ obj-$(CONFIG_HOSTAP) += hostap/
obj-$(CONFIG_B43) += b43/
obj-$(CONFIG_B43LEGACY) += b43legacy/
obj-$(CONFIG_ZD1211RW) += zd1211rw/
-obj-$(CONFIG_RTL8180) += rtl818x/
-obj-$(CONFIG_RTL8187) += rtl818x/
-obj-$(CONFIG_RTLWIFI) += rtlwifi/
+obj-$(CONFIG_WLAN) += realtek/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index d0c97c220026..17c40f06f13e 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1231,12 +1231,13 @@ struct airo_info {
dma_addr_t shared_dma;
pm_message_t power;
SsidRid *SSID;
- APListRid *APList;
+ APListRid APList;
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
char proc_name[IFNAMSIZ];
int wep_capable;
int max_wep_idx;
+ int last_auth;
/* WPA-related stuff */
unsigned int bssListFirst;
@@ -1847,11 +1848,6 @@ static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock)
return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);
}
-static int readAPListRid(struct airo_info *ai, APListRid *aplr)
-{
- return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
-}
-
static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock)
{
return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
@@ -2412,7 +2408,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
kfree(ai->flash);
kfree(ai->rssi);
- kfree(ai->APList);
kfree(ai->SSID);
if (freeres) {
/* PCMCIA frees this stuff, so only for PCI and ISA */
@@ -2808,6 +2803,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
init_waitqueue_head (&ai->thr_wait);
ai->tfm = NULL;
add_airo_dev(ai);
+ ai->APList.len = cpu_to_le16(sizeof(struct APListRid));
if (airo_networks_allocate (ai))
goto err_out_free;
@@ -3041,6 +3037,11 @@ static void airo_process_scan_results (struct airo_info *ai) {
}
out:
+ /* write APList back (we cleared it in airo_set_scan) */
+ disable_MAC(ai, 2);
+ writeAPListRid(ai, &ai->APList, 0);
+ enable_MAC(ai, 0);
+
ai->scan_timeout = 0;
clear_bit(JOB_SCAN_RESULTS, &ai->jobs);
up(&ai->sem);
@@ -3266,6 +3267,7 @@ static void airo_handle_link(struct airo_info *ai)
wake_up_interruptible(&ai->thr_wait);
} else
airo_send_event(ai->dev);
+ netif_carrier_on(ai->dev);
} else if (!scan_forceloss) {
if (auto_wep && !ai->expires) {
ai->expires = RUN_AT(3*HZ);
@@ -3276,6 +3278,9 @@ static void airo_handle_link(struct airo_info *ai)
eth_zero_addr(wrqu.ap_addr.sa_data);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL);
+ netif_carrier_off(ai->dev);
+ } else {
+ netif_carrier_off(ai->dev);
}
}
@@ -3608,16 +3613,18 @@ static void disable_MAC( struct airo_info *ai, int lock ) {
Cmd cmd;
Resp rsp;
- if (lock && down_interruptible(&ai->sem))
+ if (lock == 1 && down_interruptible(&ai->sem))
return;
if (test_bit(FLAG_ENABLED, &ai->flags)) {
+ if (lock != 2) /* lock == 2 means don't disable carrier */
+ netif_carrier_off(ai->dev);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_DISABLE; // disable in case already enabled
issuecommand(ai, &cmd, &rsp);
clear_bit(FLAG_ENABLED, &ai->flags);
}
- if (lock)
+ if (lock == 1)
up(&ai->sem);
}
@@ -3786,6 +3793,16 @@ badrx:
}
}
+static inline void set_auth_type(struct airo_info *local, int auth_type)
+{
+ local->config.authType = auth_type;
+ /* Cache the last auth type used (of AUTH_OPEN and AUTH_ENCRYPT).
+ * Used by airo_set_auth()
+ */
+ if (auth_type == AUTH_OPEN || auth_type == AUTH_ENCRYPT)
+ local->last_auth = auth_type;
+}
+
static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
{
Cmd cmd;
@@ -3836,8 +3853,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
tdsRssiRid rssi_rid;
CapabilityRid cap_rid;
- kfree(ai->APList);
- ai->APList = NULL;
kfree(ai->SSID);
ai->SSID = NULL;
// general configuration (read/modify/write)
@@ -3862,7 +3877,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
"level scale");
}
ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
- ai->config.authType = AUTH_OPEN;
+ set_auth_type(ai, AUTH_OPEN);
ai->config.modulation = MOD_CCK;
if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
@@ -4880,13 +4895,13 @@ static void proc_config_on_close(struct inode *inode, struct file *file)
line += 5;
switch( line[0] ) {
case 's':
- ai->config.authType = AUTH_SHAREDKEY;
+ set_auth_type(ai, AUTH_SHAREDKEY);
break;
case 'e':
- ai->config.authType = AUTH_ENCRYPT;
+ set_auth_type(ai, AUTH_ENCRYPT);
break;
default:
- ai->config.authType = AUTH_OPEN;
+ set_auth_type(ai, AUTH_OPEN);
break;
}
set_bit (FLAG_COMMIT, &ai->flags);
@@ -5114,31 +5129,31 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
struct proc_data *data = file->private_data;
struct net_device *dev = PDE_DATA(inode);
struct airo_info *ai = dev->ml_priv;
- APListRid APList_rid;
+ APListRid *APList_rid = &ai->APList;
int i;
if ( !data->writelen ) return;
- memset( &APList_rid, 0, sizeof(APList_rid) );
- APList_rid.len = cpu_to_le16(sizeof(APList_rid));
+ memset(APList_rid, 0, sizeof(*APList_rid));
+ APList_rid->len = cpu_to_le16(sizeof(*APList_rid));
for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
int j;
for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
switch(j%3) {
case 0:
- APList_rid.ap[i][j/3]=
+ APList_rid->ap[i][j/3]=
hex_to_bin(data->wbuffer[j+i*6*3])<<4;
break;
case 1:
- APList_rid.ap[i][j/3]|=
+ APList_rid->ap[i][j/3]|=
hex_to_bin(data->wbuffer[j+i*6*3]);
break;
}
}
}
disable_MAC(ai, 1);
- writeAPListRid(ai, &APList_rid, 1);
+ writeAPListRid(ai, APList_rid, 1);
enable_MAC(ai, 1);
}
@@ -5392,7 +5407,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
struct airo_info *ai = dev->ml_priv;
int i;
char *ptr;
- APListRid APList_rid;
+ APListRid *APList_rid = &ai->APList;
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -5410,13 +5425,12 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
}
data->on_close = proc_APList_on_close;
- readAPListRid(ai, &APList_rid);
ptr = data->rbuffer;
for( i = 0; i < 4; i++ ) {
// We end when we find a zero MAC
- if ( !*(int*)APList_rid.ap[i] &&
- !*(int*)&APList_rid.ap[i][2]) break;
- ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
+ if ( !*(int*)APList_rid->ap[i] &&
+ !*(int*)&APList_rid->ap[i][2]) break;
+ ptr += sprintf(ptr, "%pM\n", APList_rid->ap[i]);
}
if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
@@ -5580,15 +5594,10 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
Cmd cmd;
Resp rsp;
- if (!ai->APList)
- ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL);
- if (!ai->APList)
- return -ENOMEM;
if (!ai->SSID)
ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL);
if (!ai->SSID)
return -ENOMEM;
- readAPListRid(ai, ai->APList);
readSsidRid(ai, ai->SSID);
memset(&cmd, 0, sizeof(cmd));
/* the lock will be released at the end of the resume callback */
@@ -5636,11 +5645,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
kfree(ai->SSID);
ai->SSID = NULL;
}
- if (ai->APList) {
- writeAPListRid(ai, ai->APList, 0);
- kfree(ai->APList);
- ai->APList = NULL;
- }
+ writeAPListRid(ai, &ai->APList, 0);
writeConfigRid(ai, 0);
enable_MAC(ai, 0);
ai->power = PMSG_ON;
@@ -5938,7 +5943,7 @@ static int airo_set_wap(struct net_device *dev,
struct airo_info *local = dev->ml_priv;
Cmd cmd;
Resp rsp;
- APListRid APList_rid;
+ APListRid *APList_rid = &local->APList;
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
@@ -5951,11 +5956,11 @@ static int airo_set_wap(struct net_device *dev,
issuecommand(local, &cmd, &rsp);
up(&local->sem);
} else {
- memset(&APList_rid, 0, sizeof(APList_rid));
- APList_rid.len = cpu_to_le16(sizeof(APList_rid));
- memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
+ memset(APList_rid, 0, sizeof(*APList_rid));
+ APList_rid->len = cpu_to_le16(sizeof(*APList_rid));
+ memcpy(APList_rid->ap[0], awrq->sa_data, ETH_ALEN);
disable_MAC(local, 1);
- writeAPListRid(local, &APList_rid, 1);
+ writeAPListRid(local, APList_rid, 1);
enable_MAC(local, 1);
}
return 0;
@@ -6368,9 +6373,8 @@ static int airo_set_encode(struct net_device *dev,
* should be enabled (user may turn it off later)
* This is also how "iwconfig ethX key on" works */
if((index == current_index) && (key.len > 0) &&
- (local->config.authType == AUTH_OPEN)) {
- local->config.authType = AUTH_ENCRYPT;
- }
+ (local->config.authType == AUTH_OPEN))
+ set_auth_type(local, AUTH_ENCRYPT);
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
@@ -6389,12 +6393,12 @@ static int airo_set_encode(struct net_device *dev,
}
}
/* Read the flags */
- if(dwrq->flags & IW_ENCODE_DISABLED)
- local->config.authType = AUTH_OPEN; // disable encryption
+ if (dwrq->flags & IW_ENCODE_DISABLED)
+ set_auth_type(local, AUTH_OPEN); /* disable encryption */
if(dwrq->flags & IW_ENCODE_RESTRICTED)
- local->config.authType = AUTH_SHAREDKEY; // Only Both
- if(dwrq->flags & IW_ENCODE_OPEN)
- local->config.authType = AUTH_ENCRYPT; // Only Wep
+ set_auth_type(local, AUTH_SHAREDKEY); /* Only Both */
+ if (dwrq->flags & IW_ENCODE_OPEN)
+ set_auth_type(local, AUTH_ENCRYPT); /* Only Wep */
/* Commit the changes to flags if needed */
if (local->config.authType != currentAuthType)
set_bit (FLAG_COMMIT, &local->flags);
@@ -6549,12 +6553,12 @@ static int airo_set_encodeext(struct net_device *dev,
}
/* Read the flags */
- if(encoding->flags & IW_ENCODE_DISABLED)
- local->config.authType = AUTH_OPEN; // disable encryption
+ if (encoding->flags & IW_ENCODE_DISABLED)
+ set_auth_type(local, AUTH_OPEN); /* disable encryption */
if(encoding->flags & IW_ENCODE_RESTRICTED)
- local->config.authType = AUTH_SHAREDKEY; // Only Both
- if(encoding->flags & IW_ENCODE_OPEN)
- local->config.authType = AUTH_ENCRYPT; // Only Wep
+ set_auth_type(local, AUTH_SHAREDKEY); /* Only Both */
+ if (encoding->flags & IW_ENCODE_OPEN)
+ set_auth_type(local, AUTH_ENCRYPT);
/* Commit the changes to flags if needed */
if (local->config.authType != currentAuthType)
set_bit (FLAG_COMMIT, &local->flags);
@@ -6659,9 +6663,9 @@ static int airo_set_auth(struct net_device *dev,
if (param->value) {
/* Only change auth type if unencrypted */
if (currentAuthType == AUTH_OPEN)
- local->config.authType = AUTH_ENCRYPT;
+ set_auth_type(local, AUTH_ENCRYPT);
} else {
- local->config.authType = AUTH_OPEN;
+ set_auth_type(local, AUTH_OPEN);
}
/* Commit the changes to flags if needed */
@@ -6670,13 +6674,14 @@ static int airo_set_auth(struct net_device *dev,
break;
case IW_AUTH_80211_AUTH_ALG: {
- /* FIXME: What about AUTH_OPEN? This API seems to
- * disallow setting our auth to AUTH_OPEN.
- */
if (param->value & IW_AUTH_ALG_SHARED_KEY) {
- local->config.authType = AUTH_SHAREDKEY;
+ set_auth_type(local, AUTH_SHAREDKEY);
} else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
- local->config.authType = AUTH_ENCRYPT;
+ /* We don't know here if WEP open system or
+ * unencrypted mode was requested - so use the
+ * last mode (of these two) used last time
+ */
+ set_auth_type(local, local->last_auth);
} else
return -EINVAL;
@@ -7217,6 +7222,7 @@ static int airo_set_scan(struct net_device *dev,
Cmd cmd;
Resp rsp;
int wake = 0;
+ APListRid APList_rid_empty;
/* Note : you may have realised that, as this is a SET operation,
* this is privileged and therefore a normal user can't
@@ -7234,6 +7240,13 @@ static int airo_set_scan(struct net_device *dev,
if (ai->scan_timeout > 0)
goto out;
+ /* Clear APList as it affects scan results */
+ memset(&APList_rid_empty, 0, sizeof(APList_rid_empty));
+ APList_rid_empty.len = cpu_to_le16(sizeof(APList_rid_empty));
+ disable_MAC(ai, 2);
+ writeAPListRid(ai, &APList_rid_empty, 0);
+ enable_MAC(ai, 0);
+
/* Initiate a scan command */
ai->scan_timeout = RUN_AT(3*HZ);
memset(&cmd, 0, sizeof(cmd));
@@ -7489,10 +7502,8 @@ static int airo_config_commit(struct net_device *dev,
* parameters. It's now time to commit them in the card */
disable_MAC(local, 1);
if (test_bit (FLAG_RESET, &local->flags)) {
- APListRid APList_rid;
SsidRid SSID_rid;
- readAPListRid(local, &APList_rid);
readSsidRid(local, &SSID_rid);
if (test_bit(FLAG_MPI,&local->flags))
setup_card(local, dev->dev_addr, 1 );
@@ -7500,7 +7511,7 @@ static int airo_config_commit(struct net_device *dev,
reset_airo_card(dev);
disable_MAC(local, 1);
writeSsidRid(local, &SSID_rid, 1);
- writeAPListRid(local, &APList_rid, 1);
+ writeAPListRid(local, &local->APList, 1);
}
if (down_interruptible(&local->sem))
return -ERESTARTSYS;
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index df7c7616533b..7d3231acfb24 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -82,6 +82,16 @@ enum bmi_cmd_id {
#define BMI_NVRAM_SEG_NAME_SZ 16
+#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10
+
+#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00
+#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10
+
+#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK 0x18000
+#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15
+
+#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff
+
struct bmi_cmd {
__le32 id; /* enum bmi_cmd_id */
union {
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index cf28fbebaedc..edf3629288bc 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
{
struct ath10k *ar = ce_state->ar;
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
- struct ce_desc *desc, *sdesc;
+ struct ce_desc *desc, sdesc;
unsigned int nentries_mask = src_ring->nentries_mask;
unsigned int sw_index = src_ring->sw_index;
unsigned int write_index = src_ring->write_index;
@@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
write_index);
- sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index);
desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA);
@@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
if (flags & CE_SEND_FLAG_BYTE_SWAP)
desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
- sdesc->addr = __cpu_to_le32(buffer);
- sdesc->nbytes = __cpu_to_le16(nbytes);
- sdesc->flags = __cpu_to_le16(desc_flags);
+ sdesc.addr = __cpu_to_le32(buffer);
+ sdesc.nbytes = __cpu_to_le16(nbytes);
+ sdesc.flags = __cpu_to_le16(desc_flags);
- *desc = *sdesc;
+ *desc = sdesc;
src_ring->per_transfer_context[write_index] = per_transfer_context;
@@ -413,7 +412,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
lockdep_assert_held(&ar_pci->ce_lock);
if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
- return -EIO;
+ return -ENOSPC;
desc->addr = __cpu_to_le32(paddr);
desc->nbytes = 0;
@@ -579,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
* 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,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp)
+ 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;
- struct ce_desc *sdesc, *sbase;
unsigned int read_index;
if (src_ring->hw_index == sw_index) {
@@ -614,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
if (read_index == sw_index)
return -EIO;
- sbase = src_ring->shadow_base;
- sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
-
- /* Return data from completed source descriptor */
- *bufferp = __le32_to_cpu(sdesc->addr);
- *nbytesp = __le16_to_cpu(sdesc->nbytes);
- *transfer_idp = MS(__le16_to_cpu(sdesc->flags),
- CE_DESC_FLAGS_META_DATA);
-
if (per_transfer_contextp)
*per_transfer_contextp =
src_ring->per_transfer_context[sw_index];
@@ -697,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
}
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp)
+ void **per_transfer_contextp)
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -708,9 +691,7 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
spin_lock_bh(&ar_pci->ce_lock);
ret = ath10k_ce_completed_send_next_nolock(ce_state,
- per_transfer_contextp,
- bufferp, nbytesp,
- transfer_idp);
+ per_transfer_contextp);
spin_unlock_bh(&ar_pci->ce_lock);
return ret;
@@ -940,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
src_ring->base_addr_ce_space_unaligned,
CE_DESC_RING_ALIGN);
- /*
- * Also allocate a shadow src ring in regular
- * mem to use for faster access.
- */
- src_ring->shadow_base_unaligned =
- kmalloc((nentries * sizeof(struct ce_desc) +
- CE_DESC_RING_ALIGN), GFP_KERNEL);
- if (!src_ring->shadow_base_unaligned) {
- dma_free_coherent(ar->dev,
- (nentries * sizeof(struct ce_desc) +
- CE_DESC_RING_ALIGN),
- src_ring->base_addr_owner_space,
- src_ring->base_addr_ce_space);
- kfree(src_ring);
- return ERR_PTR(-ENOMEM);
- }
-
- src_ring->shadow_base = PTR_ALIGN(
- src_ring->shadow_base_unaligned,
- CE_DESC_RING_ALIGN);
-
return src_ring;
}
@@ -1076,9 +1036,7 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
}
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
- const struct ce_attr *attr,
- void (*send_cb)(struct ath10k_ce_pipe *),
- void (*recv_cb)(struct ath10k_ce_pipe *))
+ const struct ce_attr *attr)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
@@ -1104,10 +1062,10 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
ce_state->src_sz_max = attr->src_sz_max;
if (attr->src_nentries)
- ce_state->send_cb = send_cb;
+ ce_state->send_cb = attr->send_cb;
if (attr->dest_nentries)
- ce_state->recv_cb = recv_cb;
+ ce_state->recv_cb = attr->recv_cb;
if (attr->src_nentries) {
ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
@@ -1141,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
if (ce_state->src_ring) {
- kfree(ce_state->src_ring->shadow_base_unaligned);
dma_free_coherent(ar->dev,
(ce_state->src_ring->nentries *
sizeof(struct ce_desc) +
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 5c903e15dd65..47b734ce7ecf 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -100,12 +100,6 @@ struct ath10k_ce_ring {
/* CE address space */
u32 base_addr_ce_space;
- /*
- * Start of shadow copy of descriptors, within regular memory.
- * Aligned to descriptor-size boundary.
- */
- void *shadow_base_unaligned;
- struct ce_desc *shadow_base;
/* keep last */
void *per_transfer_context[0];
@@ -192,16 +186,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
* Pops 1 completed send buffer from Source ring.
*/
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp);
+ void **per_transfer_contextp);
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp);
+ void **per_transfer_contextp);
/*==================CE Engine Initialization=======================*/
@@ -209,9 +197,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
const struct ce_attr *attr);
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
- const struct ce_attr *attr,
- void (*send_cb)(struct ath10k_ce_pipe *),
- void (*recv_cb)(struct ath10k_ce_pipe *));
+ const struct ce_attr *attr);
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
/*==================CE Engine Shutdown=======================*/
@@ -277,6 +263,9 @@ struct ce_attr {
/* #entries in destination ring - Must be a power of 2 */
unsigned int dest_nentries;
+
+ void (*send_cb)(struct ath10k_ce_pipe *);
+ void (*recv_cb)(struct ath10k_ce_pipe *);
};
#define SR_BA_ADDRESS 0x0000
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index b87b98617073..aa9bd92ac4ed 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask;
static unsigned int ath10k_cryptmode_param;
static bool uart_print;
static bool skip_otp;
+static bool rawmode;
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644);
+module_param(rawmode, bool, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
+MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
@@ -54,6 +57,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.has_shifted_cc_wraparound = true,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
.fw = {
.dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE,
@@ -70,6 +74,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 6,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
.fw = {
.dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE,
@@ -86,6 +91,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 6,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
.fw = {
.dir = QCA6174_HW_3_0_FW_DIR,
.fw = QCA6174_HW_3_0_FW_FILE,
@@ -102,6 +108,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 6,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
.fw = {
/* uses same binaries as hw3.0 */
.dir = QCA6174_HW_3_0_FW_DIR,
@@ -120,6 +127,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0x00000700,
.continuous_frag_desc = true,
.channel_counters_freq_hz = 150000,
+ .max_probe_resp_desc_thres = 24,
.fw = {
.dir = QCA99X0_HW_2_0_FW_DIR,
.fw = QCA99X0_HW_2_0_FW_FILE,
@@ -129,6 +137,21 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
},
},
+ {
+ .id = QCA9377_HW_1_0_DEV_VERSION,
+ .name = "qca9377 hw1.0",
+ .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .otp_exe_param = 0,
+ .fw = {
+ .dir = QCA9377_HW_1_0_FW_DIR,
+ .fw = QCA9377_HW_1_0_FW_FILE,
+ .otp = QCA9377_HW_1_0_OTP_FILE,
+ .board = QCA9377_HW_1_0_BOARD_DATA_FILE,
+ .board_size = QCA9377_BOARD_DATA_SZ,
+ .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
+ },
+ },
};
static const char *const ath10k_core_fw_feature_str[] = {
@@ -142,12 +165,18 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp",
[ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
+ [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
+ [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
};
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
size_t buf_len,
enum ath10k_fw_features feat)
{
+ /* make sure that ath10k_core_fw_feature_str[] gets updated */
+ BUILD_BUG_ON(ARRAY_SIZE(ath10k_core_fw_feature_str) !=
+ ATH10K_FW_FEATURE_COUNT);
+
if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) ||
WARN_ON(!ath10k_core_fw_feature_str[feat])) {
return scnprintf(buf, buf_len, "bit%d", feat);
@@ -435,6 +464,56 @@ out:
return ret;
}
+static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
+{
+ u32 result, address;
+ u8 board_id, chip_id;
+ int ret;
+
+ address = ar->hw_params.patch_load_addr;
+
+ if (!ar->otp_data || !ar->otp_len) {
+ ath10k_warn(ar,
+ "failed to retrieve board id because of invalid otp\n");
+ return -ENODATA;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot upload otp to 0x%x len %zd for board id\n",
+ address, ar->otp_len);
+
+ ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
+ if (ret) {
+ ath10k_err(ar, "could not write otp for board id check: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EEPROM_BOARD_ID,
+ &result);
+ if (ret) {
+ ath10k_err(ar, "could not execute otp for board id check: %d\n",
+ ret);
+ return ret;
+ }
+
+ board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
+ chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP);
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot get otp board id result 0x%08x board_id %d chip_id %d\n",
+ result, board_id, chip_id);
+
+ if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0)
+ return -EOPNOTSUPP;
+
+ ar->id.bmi_ids_valid = true;
+ ar->id.bmi_board_id = board_id;
+ ar->id.bmi_chip_id = chip_id;
+
+ return 0;
+}
+
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
u32 result, address = ar->hw_params.patch_load_addr;
@@ -473,8 +552,8 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
- ar->fw_features))
- && result != 0) {
+ ar->fw_features)) &&
+ result != 0) {
ath10k_err(ar, "otp calibration failed: %d", result);
return -EINVAL;
}
@@ -497,7 +576,7 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
data_len = ar->firmware_len;
mode_name = "normal";
ret = ath10k_swap_code_seg_configure(ar,
- ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW);
+ ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW);
if (ret) {
ath10k_err(ar, "failed to configure fw code swap: %d\n",
ret);
@@ -505,8 +584,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
}
break;
case ATH10K_FIRMWARE_MODE_UTF:
- data = ar->testmode.utf->data;
- data_len = ar->testmode.utf->size;
+ data = ar->testmode.utf_firmware_data;
+ data_len = ar->testmode.utf_firmware_len;
mode_name = "utf";
break;
default:
@@ -528,11 +607,18 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
return ret;
}
-static void ath10k_core_free_firmware_files(struct ath10k *ar)
+static void ath10k_core_free_board_files(struct ath10k *ar)
{
if (!IS_ERR(ar->board))
release_firmware(ar->board);
+ ar->board = NULL;
+ ar->board_data = NULL;
+ ar->board_len = 0;
+}
+
+static void ath10k_core_free_firmware_files(struct ath10k *ar)
+{
if (!IS_ERR(ar->otp))
release_firmware(ar->otp);
@@ -544,10 +630,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
ath10k_swap_code_seg_release(ar);
- ar->board = NULL;
- ar->board_data = NULL;
- ar->board_len = 0;
-
ar->otp = NULL;
ar->otp_data = NULL;
ar->otp_len = 0;
@@ -557,7 +639,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
ar->firmware_len = 0;
ar->cal_file = NULL;
-
}
static int ath10k_fetch_cal_file(struct ath10k *ar)
@@ -579,68 +660,251 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
return 0;
}
-static int ath10k_core_fetch_spec_board_file(struct ath10k *ar)
+static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)
{
- char filename[100];
-
- scnprintf(filename, sizeof(filename), "board-%s-%s.bin",
- ath10k_bus_str(ar->hif.bus), ar->spec_board_id);
+ if (!ar->hw_params.fw.board) {
+ ath10k_err(ar, "failed to find board file fw entry\n");
+ return -EINVAL;
+ }
- ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
+ ar->board = ath10k_fetch_fw_file(ar,
+ ar->hw_params.fw.dir,
+ ar->hw_params.fw.board);
if (IS_ERR(ar->board))
return PTR_ERR(ar->board);
ar->board_data = ar->board->data;
ar->board_len = ar->board->size;
- ar->spec_board_loaded = true;
return 0;
}
-static int ath10k_core_fetch_generic_board_file(struct ath10k *ar)
+static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
+ const void *buf, size_t buf_len,
+ const char *boardname)
{
- if (!ar->hw_params.fw.board) {
- ath10k_err(ar, "failed to find board file fw entry\n");
- return -EINVAL;
+ const struct ath10k_fw_ie *hdr;
+ bool name_match_found;
+ int ret, board_ie_id;
+ size_t board_ie_len;
+ const void *board_ie_data;
+
+ name_match_found = false;
+
+ /* go through ATH10K_BD_IE_BOARD_ elements */
+ while (buf_len > sizeof(struct ath10k_fw_ie)) {
+ hdr = buf;
+ board_ie_id = le32_to_cpu(hdr->id);
+ board_ie_len = le32_to_cpu(hdr->len);
+ board_ie_data = hdr->data;
+
+ buf_len -= sizeof(*hdr);
+ buf += sizeof(*hdr);
+
+ if (buf_len < ALIGN(board_ie_len, 4)) {
+ ath10k_err(ar, "invalid ATH10K_BD_IE_BOARD length: %zu < %zu\n",
+ buf_len, ALIGN(board_ie_len, 4));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ switch (board_ie_id) {
+ case ATH10K_BD_IE_BOARD_NAME:
+ ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "board name", "",
+ board_ie_data, board_ie_len);
+
+ if (board_ie_len != strlen(boardname))
+ break;
+
+ ret = memcmp(board_ie_data, boardname, strlen(boardname));
+ if (ret)
+ break;
+
+ name_match_found = true;
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot found match for name '%s'",
+ boardname);
+ break;
+ case ATH10K_BD_IE_BOARD_DATA:
+ if (!name_match_found)
+ /* no match found */
+ break;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot found board data for '%s'",
+ boardname);
+
+ ar->board_data = board_ie_data;
+ ar->board_len = board_ie_len;
+
+ ret = 0;
+ goto out;
+ default:
+ ath10k_warn(ar, "unknown ATH10K_BD_IE_BOARD found: %d\n",
+ board_ie_id);
+ break;
+ }
+
+ /* jump over the padding */
+ board_ie_len = ALIGN(board_ie_len, 4);
+
+ buf_len -= board_ie_len;
+ buf += board_ie_len;
}
- ar->board = ath10k_fetch_fw_file(ar,
- ar->hw_params.fw.dir,
- ar->hw_params.fw.board);
+ /* no match found */
+ ret = -ENOENT;
+
+out:
+ return ret;
+}
+
+static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
+ const char *boardname,
+ const char *filename)
+{
+ size_t len, magic_len, ie_len;
+ struct ath10k_fw_ie *hdr;
+ const u8 *data;
+ int ret, ie_id;
+
+ ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
if (IS_ERR(ar->board))
return PTR_ERR(ar->board);
- ar->board_data = ar->board->data;
- ar->board_len = ar->board->size;
- ar->spec_board_loaded = false;
+ data = ar->board->data;
+ len = ar->board->size;
+
+ /* magic has extra null byte padded */
+ magic_len = strlen(ATH10K_BOARD_MAGIC) + 1;
+ if (len < magic_len) {
+ ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n",
+ ar->hw_params.fw.dir, filename, len);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) {
+ ath10k_err(ar, "found invalid board magic\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* magic is padded to 4 bytes */
+ magic_len = ALIGN(magic_len, 4);
+ if (len < magic_len) {
+ ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n",
+ ar->hw_params.fw.dir, filename, len);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ data += magic_len;
+ len -= magic_len;
+
+ while (len > sizeof(struct ath10k_fw_ie)) {
+ hdr = (struct ath10k_fw_ie *)data;
+ ie_id = le32_to_cpu(hdr->id);
+ ie_len = le32_to_cpu(hdr->len);
+
+ len -= sizeof(*hdr);
+ data = hdr->data;
+
+ if (len < ALIGN(ie_len, 4)) {
+ ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
+ ie_id, ie_len, len);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ switch (ie_id) {
+ case ATH10K_BD_IE_BOARD:
+ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
+ boardname);
+ if (ret == -ENOENT)
+ /* no match found, continue */
+ break;
+ else if (ret)
+ /* there was an error, bail out */
+ goto err;
+
+ /* board data found */
+ goto out;
+ }
+
+ /* jump over the padding */
+ ie_len = ALIGN(ie_len, 4);
+
+ len -= ie_len;
+ data += ie_len;
+ }
+
+out:
+ if (!ar->board_data || !ar->board_len) {
+ ath10k_err(ar,
+ "failed to fetch board data for %s from %s/%s\n",
+ ar->hw_params.fw.dir, boardname, filename);
+ ret = -ENODATA;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ ath10k_core_free_board_files(ar);
+ return ret;
+}
+
+static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
+ size_t name_len)
+{
+ if (ar->id.bmi_ids_valid) {
+ scnprintf(name, name_len,
+ "bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
+ ath10k_bus_str(ar->hif.bus),
+ ar->id.bmi_chip_id,
+ ar->id.bmi_board_id);
+ goto out;
+ }
+
+ scnprintf(name, name_len,
+ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x",
+ ath10k_bus_str(ar->hif.bus),
+ ar->id.vendor, ar->id.device,
+ ar->id.subsystem_vendor, ar->id.subsystem_device);
+
+out:
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
return 0;
}
static int ath10k_core_fetch_board_file(struct ath10k *ar)
{
+ char boardname[100];
int ret;
- if (strlen(ar->spec_board_id) > 0) {
- ret = ath10k_core_fetch_spec_board_file(ar);
- if (ret) {
- ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n",
- ret);
- goto generic;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n",
- ar->spec_board_id);
- return 0;
+ ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname));
+ if (ret) {
+ ath10k_err(ar, "failed to create board name: %d", ret);
+ return ret;
}
-generic:
- ret = ath10k_core_fetch_generic_board_file(ar);
+ ar->bd_api = 2;
+ ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
+ ATH10K_BOARD_API2_FILE);
+ if (!ret)
+ goto success;
+
+ ar->bd_api = 1;
+ ret = ath10k_core_fetch_board_data_api_1(ar);
if (ret) {
- ath10k_err(ar, "failed to fetch generic board data: %d\n", ret);
+ ath10k_err(ar, "failed to fetch board data\n");
return ret;
}
+success:
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api);
return 0;
}
@@ -872,12 +1136,6 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
/* calibration file is optional, don't check for any errors */
ath10k_fetch_cal_file(ar);
- ret = ath10k_core_fetch_board_file(ar);
- if (ret) {
- ath10k_err(ar, "failed to fetch board file: %d\n", ret);
- return ret;
- }
-
ar->fw_api = 5;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
@@ -1117,6 +1375,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
+ if (rawmode) {
+ if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
+ ar->fw_features)) {
+ ath10k_err(ar, "rawmode = 1 requires support from firmware");
+ return -EINVAL;
+ }
+ set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
+ }
+
if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;
@@ -1241,10 +1508,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
goto err;
/* Some of of qca988x solutions are having global reset issue
- * during target initialization. Bypassing PLL setting before
- * downloading firmware and letting the SoC run on REF_CLK is
- * fixing the problem. Corresponding firmware change is also needed
- * to set the clock source once the target is initialized.
+ * during target initialization. Bypassing PLL setting before
+ * downloading firmware and letting the SoC run on REF_CLK is
+ * fixing the problem. Corresponding firmware change is also needed
+ * to set the clock source once the target is initialized.
*/
if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT,
ar->fw_features)) {
@@ -1478,6 +1745,19 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_power_down;
}
+ ret = ath10k_core_get_board_id_from_otp(ar);
+ if (ret && ret != -EOPNOTSUPP) {
+ ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = ath10k_core_fetch_board_file(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to fetch board file: %d\n", ret);
+ goto err_free_firmware_files;
+ }
+
ret = ath10k_core_init_firmware_features(ar);
if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n",
@@ -1605,6 +1885,7 @@ void ath10k_core_unregister(struct ath10k *ar)
ath10k_testmode_destroy(ar);
ath10k_core_free_firmware_files(ar);
+ ath10k_core_free_board_files(ar);
ath10k_debug_unregister(ar);
}
@@ -1635,6 +1916,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
ar->hw_values = &qca988x_values;
break;
case ATH10K_HW_QCA6174:
+ case ATH10K_HW_QCA9377:
ar->regs = &qca6174_regs;
ar->hw_values = &qca6174_values;
break;
@@ -1714,6 +1996,7 @@ void ath10k_core_destroy(struct ath10k *ar)
destroy_workqueue(ar->workqueue_aux);
ath10k_debug_destroy(ar);
+ ath10k_wmi_free_host_mem(ar);
ath10k_mac_destroy(ar);
}
EXPORT_SYMBOL(ath10k_core_destroy);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 12542144fe12..018c64f4fd25 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
s32 hw_queued;
s32 hw_reaped;
s32 underrun;
+ u32 hw_paused;
s32 tx_abort;
s32 mpdus_requed;
u32 tx_ko;
@@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
u32 pdev_resets;
u32 phy_underrun;
u32 txop_ovf;
+ u32 seq_posted;
+ u32 seq_failed_queueing;
+ u32 seq_completed;
+ u32 seq_restarted;
+ u32 mu_seq_posted;
+ u32 mpdus_sw_flush;
+ u32 mpdus_hw_filter;
+ u32 mpdus_truncated;
+ u32 mpdus_ack_failed;
+ u32 mpdus_expired;
/* PDEV RX stats */
s32 mid_ppdu_route_change;
@@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
s32 phy_errs;
s32 phy_err_drop;
s32 mpdu_errs;
+ s32 rx_ovfl_errs;
};
struct ath10k_fw_stats {
@@ -250,6 +262,30 @@ struct ath10k_fw_stats {
struct list_head peers;
};
+#define ATH10K_TPC_TABLE_TYPE_FLAG 1
+#define ATH10K_TPC_PREAM_TABLE_END 0xFFFF
+
+struct ath10k_tpc_table {
+ u32 pream_idx[WMI_TPC_RATE_MAX];
+ u8 rate_code[WMI_TPC_RATE_MAX];
+ char tpc_value[WMI_TPC_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
+};
+
+struct ath10k_tpc_stats {
+ u32 reg_domain;
+ u32 chan_freq;
+ u32 phy_mode;
+ u32 twice_antenna_reduction;
+ u32 twice_max_rd_power;
+ s32 twice_antenna_gain;
+ u32 power_limit;
+ u32 num_tx_chain;
+ u32 ctl;
+ u32 rate_max;
+ u8 flag[WMI_TPC_FLAG];
+ struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG];
+};
+
struct ath10k_dfs_stats {
u32 phy_errors;
u32 pulses_total;
@@ -378,6 +414,11 @@ struct ath10k_debug {
struct ath10k_dfs_stats dfs_stats;
struct ath_dfs_pool_stats dfs_pool_stats;
+ /* used for tpc-dump storage, protected by data-lock */
+ struct ath10k_tpc_stats *tpc_stats;
+
+ struct completion tpc_complete;
+
/* protected by conf_mutex */
u32 fw_dbglog_mask;
u32 fw_dbglog_level;
@@ -468,6 +509,9 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10,
+ /* Firmware Supports Adaptive CCA*/
+ ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
+
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
@@ -612,6 +656,11 @@ struct ath10k {
u32 channel_counters_freq_hz;
+ /* Mgmt tx descriptors threshold for limiting probe response
+ * frames.
+ */
+ u32 max_probe_resp_desc_thres;
+
struct ath10k_hw_params_fw {
const char *dir;
const char *fw;
@@ -642,10 +691,19 @@ struct ath10k {
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
} swap;
- char spec_board_id[100];
- bool spec_board_loaded;
+ struct {
+ u32 vendor;
+ u32 device;
+ u32 subsystem_vendor;
+ u32 subsystem_device;
+
+ bool bmi_ids_valid;
+ u8 bmi_board_id;
+ u8 bmi_chip_id;
+ } id;
int fw_api;
+ int bd_api;
enum ath10k_cal_mode cal_mode;
struct {
@@ -680,15 +738,13 @@ struct ath10k {
bool monitor_started;
unsigned int filter_flags;
unsigned long dev_flags;
- u32 dfs_block_radar_events;
+ bool dfs_block_radar_events;
/* protected by conf_mutex */
bool radar_enabled;
int num_started_vdevs;
/* Protected by conf-mutex */
- u8 supp_tx_chainmask;
- u8 supp_rx_chainmask;
u8 cfg_tx_chainmask;
u8 cfg_rx_chainmask;
@@ -771,9 +827,12 @@ struct ath10k {
struct {
/* protected by conf_mutex */
const struct firmware *utf;
+ char utf_version[32];
+ const void *utf_firmware_data;
+ size_t utf_firmware_len;
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
-
+ enum ath10k_fw_wmi_op_version op_version;
/* protected by data_lock */
bool utf_monitor;
} testmode;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index bf033f46f8aa..6cc1aa3449c8 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -125,19 +125,25 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_print_driver_info(struct ath10k *ar)
{
char fw_features[128] = {};
+ char boardinfo[100];
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
- ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
+ if (ar->id.bmi_ids_valid)
+ scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
+ ar->id.bmi_chip_id, ar->id.bmi_board_id);
+ else
+ scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
+ ar->id.subsystem_vendor, ar->id.subsystem_device);
+
+ ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
- (strlen(ar->spec_board_id) > 0 ? ", " : ""),
- ar->spec_board_id,
- (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded
- ? " fallback" : ""),
+ boardinfo,
ar->hw->wiphy->fw_version,
ar->fw_api,
+ ar->bd_api,
ar->htt.target_version_major,
ar->htt.target_version_minor,
ar->wmi.op_version,
@@ -285,28 +291,6 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
spin_unlock_bh(&ar->data_lock);
}
-static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
-{
- struct ath10k_fw_stats_peer *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head)
-{
- struct ath10k_fw_stats_vdev *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_fw_stats stats = {};
@@ -343,8 +327,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
goto free;
}
- num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
- num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
+ num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
!list_empty(&stats.pdevs));
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
@@ -429,240 +413,6 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)
return 0;
}
-/* FIXME: How to calculate the buffer size sanely? */
-#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
-
-static void ath10k_fw_stats_fill(struct ath10k *ar,
- struct ath10k_fw_stats *fw_stats,
- char *buf)
-{
- unsigned int len = 0;
- unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
- const struct ath10k_fw_stats_pdev *pdev;
- const struct ath10k_fw_stats_vdev *vdev;
- const struct ath10k_fw_stats_peer *peer;
- size_t num_peers;
- size_t num_vdevs;
- int i;
-
- spin_lock_bh(&ar->data_lock);
-
- pdev = list_first_entry_or_null(&fw_stats->pdevs,
- struct ath10k_fw_stats_pdev, list);
- if (!pdev) {
- ath10k_warn(ar, "failed to get pdev stats\n");
- goto unlock;
- }
-
- num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s\n",
- "ath10k PDEV stats");
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Channel noise floor", pdev->ch_noise_floor);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "Channel TX power", pdev->chan_tx_power);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "TX frame count", pdev->tx_frame_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RX frame count", pdev->rx_frame_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RX clear count", pdev->rx_clear_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "Cycle count", pdev->cycle_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "PHY error count", pdev->phy_err_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RTS bad count", pdev->rts_bad);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RTS good count", pdev->rts_good);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "FCS bad count", pdev->fcs_bad);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "No beacon count", pdev->no_beacons);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "MIB int count", pdev->mib_int_count);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s\n",
- "ath10k PDEV TX stats");
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HTT cookies queued", pdev->comp_queued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HTT cookies disp.", pdev->comp_delivered);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDU queued", pdev->msdu_enqued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU queued", pdev->mpdu_enqued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs dropped", pdev->wmm_drop);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Local enqued", pdev->local_enqued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Local freed", pdev->local_freed);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HW queued", pdev->hw_queued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PPDUs reaped", pdev->hw_reaped);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Num underruns", pdev->underrun);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PPDUs cleaned", pdev->tx_abort);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs requed", pdev->mpdus_requed);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Excessive retries", pdev->tx_ko);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HW rate", pdev->data_rc);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Sched self tiggers", pdev->self_triggers);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Dropped due to SW retries",
- pdev->sw_retry_failure);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Illegal rate phy errors",
- pdev->illgl_rate_phy_err);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Pdev continous xretry", pdev->pdev_cont_xretry);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "TX timeout", pdev->pdev_tx_timeout);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PDEV resets", pdev->pdev_resets);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY underrun", pdev->phy_underrun);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU is more than txop limit", pdev->txop_ovf);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s\n",
- "ath10k PDEV RX stats");
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Mid PPDU route change",
- pdev->mid_ppdu_route_change);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Tot. number of statuses", pdev->status_rcvd);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 0", pdev->r0_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 1", pdev->r1_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 2", pdev->r2_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 3", pdev->r3_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs delivered to HTT", pdev->htt_msdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs delivered to HTT", pdev->htt_mpdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs delivered to stack", pdev->loc_msdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs delivered to stack", pdev->loc_mpdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Oversized AMSUs", pdev->oversize_amsdu);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY errors", pdev->phy_errs);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY errors drops", pdev->phy_err_drop);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- "ath10k VDEV stats", num_vdevs);
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- list_for_each_entry(vdev, &fw_stats->vdevs, list) {
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "vdev id", vdev->vdev_id);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "beacon snr", vdev->beacon_snr);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "data snr", vdev->data_snr);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rx frames", vdev->num_rx_frames);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rts fail", vdev->num_rts_fail);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rts success", vdev->num_rts_success);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rx err", vdev->num_rx_err);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rx discard", vdev->num_rx_discard);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num tx not acked", vdev->num_tx_not_acked);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "num tx frames", i,
- vdev->num_tx_frames[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "num tx frames retries", i,
- vdev->num_tx_frames_retries[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "num tx frames failures", i,
- vdev->num_tx_frames_failures[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] 0x%08x\n",
- "tx rate history", i,
- vdev->tx_rate_history[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "beacon rssi history", i,
- vdev->beacon_rssi_history[i]);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- }
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- "ath10k PEER stats", num_peers);
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- list_for_each_entry(peer, &fw_stats->peers, list) {
- len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
- "Peer MAC address", peer->peer_macaddr);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer RSSI", peer->peer_rssi);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "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, "\n");
- }
-
-unlock:
- spin_unlock_bh(&ar->data_lock);
-
- if (len >= buf_len)
- buf[len - 1] = 0;
- else
- buf[len] = 0;
-}
-
static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
{
struct ath10k *ar = inode->i_private;
@@ -688,7 +438,12 @@ static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
goto err_free;
}
- ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+ ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+ if (ret) {
+ ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
+ goto err_free;
+ }
+
file->private_data = buf;
mutex_unlock(&ar->conf_mutex);
@@ -1843,6 +1598,233 @@ static const struct file_operations fops_nf_cal_period = {
.llseek = default_llseek,
};
+#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
+
+static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
+{
+ int ret;
+ unsigned long time_left;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ reinit_completion(&ar->debug.tpc_complete);
+
+ ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
+ if (ret) {
+ ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
+ return ret;
+ }
+
+ time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
+ 1 * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+void ath10k_debug_tpc_stats_process(struct ath10k *ar,
+ struct ath10k_tpc_stats *tpc_stats)
+{
+ spin_lock_bh(&ar->data_lock);
+
+ kfree(ar->debug.tpc_stats);
+ ar->debug.tpc_stats = tpc_stats;
+ complete(&ar->debug.tpc_complete);
+
+ spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
+ unsigned int j, char *buf, unsigned int *len)
+{
+ unsigned int i, buf_len;
+ static const char table_str[][5] = { "CDD",
+ "STBC",
+ "TXBF" };
+ static const char pream_str[][6] = { "CCK",
+ "OFDM",
+ "HT20",
+ "HT40",
+ "VHT20",
+ "VHT40",
+ "VHT80",
+ "HTCUP" };
+
+ buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
+ *len += scnprintf(buf + *len, buf_len - *len,
+ "********************************\n");
+ *len += scnprintf(buf + *len, buf_len - *len,
+ "******************* %s POWER TABLE ****************\n",
+ table_str[j]);
+ *len += scnprintf(buf + *len, buf_len - *len,
+ "********************************\n");
+ *len += scnprintf(buf + *len, buf_len - *len,
+ "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
+
+ for (i = 0; i < tpc_stats->rate_max; i++) {
+ *len += scnprintf(buf + *len, buf_len - *len,
+ "%8d %s 0x%2x %s\n", i,
+ pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
+ tpc_stats->tpc_table[j].rate_code[i],
+ tpc_stats->tpc_table[j].tpc_value[i]);
+ }
+
+ *len += scnprintf(buf + *len, buf_len - *len,
+ "***********************************\n");
+}
+
+static void ath10k_tpc_stats_fill(struct ath10k *ar,
+ struct ath10k_tpc_stats *tpc_stats,
+ char *buf)
+{
+ unsigned int len, j, buf_len;
+
+ len = 0;
+ buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
+
+ spin_lock_bh(&ar->data_lock);
+
+ if (!tpc_stats) {
+ ath10k_warn(ar, "failed to get tpc stats\n");
+ goto unlock;
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "*************************************\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "TPC config for channel %4d mode %d\n",
+ tpc_stats->chan_freq,
+ tpc_stats->phy_mode);
+ len += scnprintf(buf + len, buf_len - len,
+ "*************************************\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "CTL = 0x%2x Reg. Domain = %2d\n",
+ tpc_stats->ctl,
+ tpc_stats->reg_domain);
+ len += scnprintf(buf + len, buf_len - len,
+ "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
+ tpc_stats->twice_antenna_gain,
+ tpc_stats->twice_antenna_reduction);
+ len += scnprintf(buf + len, buf_len - len,
+ "Power Limit = %2d Reg. Max Power = %2d\n",
+ tpc_stats->power_limit,
+ tpc_stats->twice_max_rd_power / 2);
+ len += scnprintf(buf + len, buf_len - len,
+ "Num tx chains = %2d Num supported rates = %2d\n",
+ tpc_stats->num_tx_chain,
+ tpc_stats->rate_max);
+
+ for (j = 0; j < tpc_stats->num_tx_chain ; j++) {
+ switch (j) {
+ case WMI_TPC_TABLE_TYPE_CDD:
+ if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
+ len += scnprintf(buf + len, buf_len - len,
+ "CDD not supported\n");
+ break;
+ }
+
+ ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
+ break;
+ case WMI_TPC_TABLE_TYPE_STBC:
+ if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
+ len += scnprintf(buf + len, buf_len - len,
+ "STBC not supported\n");
+ break;
+ }
+
+ ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
+ break;
+ case WMI_TPC_TABLE_TYPE_TXBF:
+ if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
+ len += scnprintf(buf + len, buf_len - len,
+ "TXBF not supported\n***************************\n");
+ break;
+ }
+
+ ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
+ break;
+ default:
+ len += scnprintf(buf + len, buf_len - len,
+ "Invalid Type\n");
+ break;
+ }
+ }
+
+unlock:
+ spin_unlock_bh(&ar->data_lock);
+
+ if (len >= buf_len)
+ buf[len - 1] = 0;
+ else
+ buf[len] = 0;
+}
+
+static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
+{
+ struct ath10k *ar = inode->i_private;
+ void *buf = NULL;
+ int ret;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_ON) {
+ ret = -ENETDOWN;
+ goto err_unlock;
+ }
+
+ buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_unlock;
+ }
+
+ ret = ath10k_debug_tpc_stats_request(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to request tpc config stats: %d\n",
+ ret);
+ goto err_free;
+ }
+
+ ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
+ file->private_data = buf;
+
+ mutex_unlock(&ar->conf_mutex);
+ return 0;
+
+err_free:
+ vfree(buf);
+
+err_unlock:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
+{
+ vfree(file->private_data);
+
+ return 0;
+}
+
+static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ const char *buf = file->private_data;
+ unsigned int len = strlen(buf);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_tpc_stats = {
+ .open = ath10k_tpc_stats_open,
+ .release = ath10k_tpc_stats_release,
+ .read = ath10k_tpc_stats_read,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath10k_debug_start(struct ath10k *ar)
{
int ret;
@@ -2111,6 +2093,8 @@ void ath10k_debug_destroy(struct ath10k *ar)
ar->debug.fw_crash_data = NULL;
ath10k_debug_fw_stats_reset(ar);
+
+ kfree(ar->debug.tpc_stats);
}
int ath10k_debug_register(struct ath10k *ar)
@@ -2127,6 +2111,7 @@ int ath10k_debug_register(struct ath10k *ar)
INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
ath10k_debug_htt_stats_dwork);
+ init_completion(&ar->debug.tpc_complete);
init_completion(&ar->debug.fw_stats_complete);
debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
@@ -2195,6 +2180,9 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_quiet_period);
+ debugfs_create_file("tpc_stats", S_IRUSR,
+ ar->debug.debugfs_phy, ar, &fops_tpc_stats);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 53bd6a19eab6..7de780c4ec8d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -55,6 +55,9 @@ enum ath10k_dbg_aggr_mode {
ATH10K_DBG_AGGR_MODE_MAX,
};
+/* FIXME: How to calculate the buffer size sanely? */
+#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
+
extern unsigned int ath10k_debug_mask;
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
@@ -70,6 +73,8 @@ void ath10k_debug_destroy(struct ath10k *ar);
int ath10k_debug_register(struct ath10k *ar);
void ath10k_debug_unregister(struct ath10k *ar);
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_debug_tpc_stats_process(struct ath10k *ar,
+ struct ath10k_tpc_stats *tpc_stats);
struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
@@ -117,6 +122,12 @@ static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
{
}
+static inline void ath10k_debug_tpc_stats_process(struct ath10k *ar,
+ struct ath10k_tpc_stats *tpc_stats)
+{
+ kfree(tpc_stats);
+}
+
static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
int len)
{
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 0c92e0251e84..89e7076c919f 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -30,13 +30,6 @@ struct ath10k_hif_sg_item {
u16 len;
};
-struct ath10k_hif_cb {
- int (*tx_completion)(struct ath10k *ar,
- struct sk_buff *wbuf);
- int (*rx_completion)(struct ath10k *ar,
- struct sk_buff *wbuf);
-};
-
struct ath10k_hif_ops {
/* send a scatter-gather list to the target */
int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
@@ -65,8 +58,7 @@ struct ath10k_hif_ops {
void (*stop)(struct ath10k *ar);
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
- u8 *ul_pipe, u8 *dl_pipe,
- int *ul_is_polled, int *dl_is_polled);
+ u8 *ul_pipe, u8 *dl_pipe);
void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe);
@@ -80,9 +72,6 @@ struct ath10k_hif_ops {
*/
void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force);
- void (*set_callbacks)(struct ath10k *ar,
- struct ath10k_hif_cb *callbacks);
-
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
u32 (*read32)(struct ath10k *ar, u32 address);
@@ -142,13 +131,10 @@ static inline void ath10k_hif_stop(struct ath10k *ar)
static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar,
u16 service_id,
- u8 *ul_pipe, u8 *dl_pipe,
- int *ul_is_polled,
- int *dl_is_polled)
+ u8 *ul_pipe, u8 *dl_pipe)
{
return ar->hif.ops->map_service_to_pipe(ar, service_id,
- ul_pipe, dl_pipe,
- ul_is_polled, dl_is_polled);
+ ul_pipe, dl_pipe);
}
static inline void ath10k_hif_get_default_pipe(struct ath10k *ar,
@@ -163,12 +149,6 @@ static inline void ath10k_hif_send_complete_check(struct ath10k *ar,
ar->hif.ops->send_complete_check(ar, pipe_id, force);
}
-static inline void ath10k_hif_set_callbacks(struct ath10k *ar,
- struct ath10k_hif_cb *callbacks)
-{
- ar->hif.ops->set_callbacks(ar, callbacks);
-}
-
static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
u8 pipe_id)
{
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 32d9ff1b19dc..5b3c6bcf9598 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -23,16 +23,6 @@
/* Send */
/********/
-static inline void ath10k_htc_send_complete_check(struct ath10k_htc_ep *ep,
- int force)
-{
- /*
- * Check whether HIF has any prior sends that have finished,
- * have not had the post-processing done.
- */
- ath10k_hif_send_complete_check(ep->htc->ar, ep->ul_pipe_id, force);
-}
-
static void ath10k_htc_control_tx_complete(struct ath10k *ar,
struct sk_buff *skb)
{
@@ -181,24 +171,22 @@ err_pull:
return ret;
}
-static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
- struct sk_buff *skb)
+void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_htc *htc = &ar->htc;
struct ath10k_skb_cb *skb_cb;
struct ath10k_htc_ep *ep;
if (WARN_ON_ONCE(!skb))
- return 0;
+ return;
skb_cb = ATH10K_SKB_CB(skb);
ep = &htc->endpoint[skb_cb->eid];
ath10k_htc_notify_tx_completion(ep, skb);
/* the skb now belongs to the completion handler */
-
- return 0;
}
+EXPORT_SYMBOL(ath10k_htc_tx_completion_handler);
/***********/
/* Receive */
@@ -304,8 +292,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
return status;
}
-static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
- struct sk_buff *skb)
+void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
{
int status = 0;
struct ath10k_htc *htc = &ar->htc;
@@ -326,21 +313,11 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid);
ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "",
hdr, sizeof(*hdr));
- status = -EINVAL;
goto out;
}
ep = &htc->endpoint[eid];
- /*
- * If this endpoint that received a message from the target has
- * a to-target HIF pipe whose send completions are polled rather
- * than interrupt-driven, this is a good point to ask HIF to check
- * whether it has any completed sends to handle.
- */
- if (ep->ul_is_polled)
- ath10k_htc_send_complete_check(ep, 1);
-
payload_len = __le16_to_cpu(hdr->len);
if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
@@ -348,7 +325,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
payload_len + sizeof(*hdr));
ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "",
hdr, sizeof(*hdr));
- status = -EINVAL;
goto out;
}
@@ -358,7 +334,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
skb->len, payload_len);
ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len",
"", hdr, sizeof(*hdr));
- status = -EINVAL;
goto out;
}
@@ -374,7 +349,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
(trailer_len > payload_len)) {
ath10k_warn(ar, "Invalid trailer length: %d\n",
trailer_len);
- status = -EPROTO;
goto out;
}
@@ -407,7 +381,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
* sending unsolicited messages on the ep 0
*/
ath10k_warn(ar, "HTC rx ctrl still processing\n");
- status = -EINVAL;
complete(&htc->ctl_resp);
goto out;
}
@@ -439,9 +412,8 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
skb = NULL;
out:
kfree_skb(skb);
-
- return status;
}
+EXPORT_SYMBOL(ath10k_htc_rx_completion_handler);
static void ath10k_htc_control_rx_complete(struct ath10k *ar,
struct sk_buff *skb)
@@ -767,9 +739,7 @@ setup:
status = ath10k_hif_map_service_to_pipe(htc->ar,
ep->service_id,
&ep->ul_pipe_id,
- &ep->dl_pipe_id,
- &ep->ul_is_polled,
- &ep->dl_is_polled);
+ &ep->dl_pipe_id);
if (status)
return status;
@@ -778,10 +748,6 @@ setup:
htc_service_name(ep->service_id), ep->ul_pipe_id,
ep->dl_pipe_id, ep->eid);
- ath10k_dbg(ar, ATH10K_DBG_BOOT,
- "boot htc ep %d ul polled %d dl polled %d\n",
- ep->eid, ep->ul_is_polled, ep->dl_is_polled);
-
if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
ep->tx_credit_flow_enabled = false;
ath10k_dbg(ar, ATH10K_DBG_BOOT,
@@ -841,7 +807,6 @@ int ath10k_htc_start(struct ath10k_htc *htc)
/* registered target arrival callback from the HIF layer */
int ath10k_htc_init(struct ath10k *ar)
{
- struct ath10k_hif_cb htc_callbacks;
struct ath10k_htc_ep *ep = NULL;
struct ath10k_htc *htc = &ar->htc;
@@ -849,15 +814,11 @@ int ath10k_htc_init(struct ath10k *ar)
ath10k_htc_reset_endpoint_states(htc);
- /* setup HIF layer callbacks */
- htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler;
- htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler;
htc->ar = ar;
/* Get HIF default pipe for HTC message exchange */
ep = &htc->endpoint[ATH10K_HTC_EP_0];
- ath10k_hif_set_callbacks(ar, &htc_callbacks);
ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
init_completion(&htc->ctl_resp);
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 527179c0edce..e70aa38e6e05 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -312,8 +312,6 @@ struct ath10k_htc_ep {
int max_ep_message_len;
u8 ul_pipe_id;
u8 dl_pipe_id;
- int ul_is_polled; /* call HIF to get tx completions */
- int dl_is_polled; /* call HIF to fetch rx (not implemented) */
u8 seq_no; /* for debugging */
int tx_credits;
@@ -355,5 +353,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
struct sk_buff *packet);
struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
+void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 573187512895..2bad50e520b5 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1485,9 +1485,9 @@ struct ath10k_htt {
spinlock_t tx_lock;
int max_num_pending_tx;
int num_pending_tx;
+ int num_pending_mgmt_tx;
struct idr pending_tx;
wait_queue_head_t empty_tx_wq;
- struct dma_pool *tx_pool;
/* set if host-fw communication goes haywire
* used to avoid further failures */
@@ -1508,6 +1508,11 @@ struct ath10k_htt {
dma_addr_t paddr;
struct htt_msdu_ext_desc *vaddr;
} frag_desc;
+
+ struct {
+ dma_addr_t paddr;
+ struct ath10k_htt_txbuf *vaddr;
+ } txbuf;
};
#define RX_HTT_HDR_STATUS_LEN 64
@@ -1586,8 +1591,9 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu);
+void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb);
-void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
+void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 1b7a04366256..6060dda4e910 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -643,6 +643,8 @@ struct amsdu_subframe_hdr {
__be16 len;
} __packed;
+#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
+
static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd)
@@ -650,6 +652,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_supported_band *sband;
u8 cck, rate, bw, sgi, mcs, nss;
u8 preamble = 0;
+ u8 group_id;
u32 info1, info2, info3;
info1 = __le32_to_cpu(rxd->ppdu_start.info1);
@@ -692,10 +695,50 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
case HTT_RX_VHT_WITH_TXBF:
/* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
TODO check this */
- mcs = (info3 >> 4) & 0x0F;
- nss = ((info2 >> 10) & 0x07) + 1;
bw = info2 & 3;
sgi = info3 & 1;
+ group_id = (info2 >> 4) & 0x3F;
+
+ if (GROUP_ID_IS_SU_MIMO(group_id)) {
+ mcs = (info3 >> 4) & 0x0F;
+ nss = ((info2 >> 10) & 0x07) + 1;
+ } else {
+ /* Hardware doesn't decode VHT-SIG-B into Rx descriptor
+ * so it's impossible to decode MCS. Also since
+ * firmware consumes Group Id Management frames host
+ * has no knowledge regarding group/user position
+ * mapping so it's impossible to pick the correct Nsts
+ * from VHT-SIG-A1.
+ *
+ * Bandwidth and SGI are valid so report the rateinfo
+ * on best-effort basis.
+ */
+ mcs = 0;
+ nss = 1;
+ }
+
+ if (mcs > 0x09) {
+ ath10k_warn(ar, "invalid MCS received %u\n", mcs);
+ ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n",
+ __le32_to_cpu(rxd->attention.flags),
+ __le32_to_cpu(rxd->mpdu_start.info0),
+ __le32_to_cpu(rxd->mpdu_start.info1),
+ __le32_to_cpu(rxd->msdu_start.common.info0),
+ __le32_to_cpu(rxd->msdu_start.common.info1),
+ rxd->ppdu_start.info0,
+ __le32_to_cpu(rxd->ppdu_start.info1),
+ __le32_to_cpu(rxd->ppdu_start.info2),
+ __le32_to_cpu(rxd->ppdu_start.info3),
+ __le32_to_cpu(rxd->ppdu_start.info4));
+
+ ath10k_warn(ar, "msdu end %08x mpdu end %08x\n",
+ __le32_to_cpu(rxd->msdu_end.common.info0),
+ __le32_to_cpu(rxd->mpdu_end.info0));
+
+ ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
+ "rx desc msdu payload: ",
+ rxd->msdu_payload, 50);
+ }
status->rate_idx = mcs;
status->vht_nss = nss;
@@ -2082,6 +2125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
/* Free the indication buffer */
dev_kfree_skb_any(skb);
}
+EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
static void ath10k_htt_txrx_compl_task(unsigned long ptr)
{
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 43aa5e2d1b87..16823970dbfd 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -22,22 +22,28 @@
#include "txrx.h"
#include "debug.h"
-void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
+void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc)
{
+ if (limit_mgmt_desc)
+ htt->num_pending_mgmt_tx--;
+
htt->num_pending_tx--;
if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
}
-static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
+static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt,
+ bool limit_mgmt_desc)
{
spin_lock_bh(&htt->tx_lock);
- __ath10k_htt_tx_dec_pending(htt);
+ __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
spin_unlock_bh(&htt->tx_lock);
}
-static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
+static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt,
+ bool limit_mgmt_desc, bool is_probe_resp)
{
+ struct ath10k *ar = htt->ar;
int ret = 0;
spin_lock_bh(&htt->tx_lock);
@@ -47,6 +53,15 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
goto exit;
}
+ if (limit_mgmt_desc) {
+ if (is_probe_resp && (htt->num_pending_mgmt_tx >
+ ar->hw_params.max_probe_resp_desc_thres)) {
+ ret = -EBUSY;
+ goto exit;
+ }
+ htt->num_pending_mgmt_tx++;
+ }
+
htt->num_pending_tx++;
if (htt->num_pending_tx == htt->max_num_pending_tx)
ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
@@ -93,9 +108,12 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
spin_lock_init(&htt->tx_lock);
idr_init(&htt->pending_tx);
- htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev,
- sizeof(struct ath10k_htt_txbuf), 4, 0);
- if (!htt->tx_pool) {
+ size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
+ htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
+ &htt->txbuf.paddr,
+ GFP_DMA);
+ if (!htt->txbuf.vaddr) {
+ ath10k_err(ar, "failed to alloc tx buffer\n");
ret = -ENOMEM;
goto free_idr_pending_tx;
}
@@ -110,14 +128,17 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
if (!htt->frag_desc.vaddr) {
ath10k_warn(ar, "failed to alloc fragment desc memory\n");
ret = -ENOMEM;
- goto free_tx_pool;
+ goto free_txbuf;
}
skip_frag_desc_alloc:
return 0;
-free_tx_pool:
- dma_pool_destroy(htt->tx_pool);
+free_txbuf:
+ size = htt->max_num_pending_tx *
+ sizeof(struct ath10k_htt_txbuf);
+ dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr,
+ htt->txbuf.paddr);
free_idr_pending_tx:
idr_destroy(&htt->pending_tx);
return ret;
@@ -145,7 +166,13 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
idr_destroy(&htt->pending_tx);
- dma_pool_destroy(htt->tx_pool);
+
+ if (htt->txbuf.vaddr) {
+ size = htt->max_num_pending_tx *
+ sizeof(struct ath10k_htt_txbuf);
+ dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr,
+ htt->txbuf.paddr);
+ }
if (htt->frag_desc.vaddr) {
size = htt->max_num_pending_tx *
@@ -160,6 +187,12 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
+void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(ath10k_htt_hif_tx_complete);
+
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
{
struct ath10k *ar = htt->ar;
@@ -417,8 +450,19 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int len = 0;
int msdu_id = -1;
int res;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
+ bool limit_mgmt_desc = false;
+ bool is_probe_resp = false;
+
+ if (ar->hw_params.max_probe_resp_desc_thres) {
+ limit_mgmt_desc = true;
+
+ if (ieee80211_is_probe_resp(hdr->frame_control))
+ is_probe_resp = true;
+ }
+
+ res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
- res = ath10k_htt_tx_inc_pending(htt);
if (res)
goto err;
@@ -428,9 +472,9 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
spin_lock_bh(&htt->tx_lock);
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
spin_unlock_bh(&htt->tx_lock);
- if (res < 0) {
+ if (res < 0)
goto err_tx_dec;
- }
+
msdu_id = res;
txdesc = ath10k_htc_alloc_skb(ar, len);
@@ -476,7 +520,7 @@ err_free_msdu_id:
ath10k_htt_tx_free_msdu_id(htt, msdu_id);
spin_unlock_bh(&htt->tx_lock);
err_tx_dec:
- ath10k_htt_tx_dec_pending(htt);
+ ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
err:
return res;
}
@@ -495,32 +539,37 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int res;
u8 flags0 = 0;
u16 msdu_id, flags1 = 0;
- dma_addr_t paddr = 0;
u32 frags_paddr = 0;
struct htt_msdu_ext_desc *ext_desc = NULL;
+ bool limit_mgmt_desc = false;
+ bool is_probe_resp = false;
+
+ if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) &&
+ ar->hw_params.max_probe_resp_desc_thres) {
+ limit_mgmt_desc = true;
+
+ if (ieee80211_is_probe_resp(hdr->frame_control))
+ is_probe_resp = true;
+ }
- res = ath10k_htt_tx_inc_pending(htt);
+ res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
if (res)
goto err;
spin_lock_bh(&htt->tx_lock);
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
spin_unlock_bh(&htt->tx_lock);
- if (res < 0) {
+ if (res < 0)
goto err_tx_dec;
- }
+
msdu_id = res;
prefetch_len = min(htt->prefetch_len, msdu->len);
prefetch_len = roundup(prefetch_len, 4);
- skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC,
- &paddr);
- if (!skb_cb->htt.txbuf) {
- res = -ENOMEM;
- goto err_free_msdu_id;
- }
- skb_cb->htt.txbuf_paddr = paddr;
+ skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id];
+ skb_cb->htt.txbuf_paddr = htt->txbuf.paddr +
+ (sizeof(struct ath10k_htt_txbuf) * msdu_id);
if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) ||
@@ -528,7 +577,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
} else if (!skb_cb->htt.nohwcrypt &&
- skb_cb->txmode == ATH10K_HW_TXRX_RAW) {
+ skb_cb->txmode == ATH10K_HW_TXRX_RAW &&
+ ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
}
@@ -537,7 +587,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
res = dma_mapping_error(dev, skb_cb->paddr);
if (res) {
res = -EIO;
- goto err_free_txbuf;
+ goto err_free_msdu_id;
}
switch (skb_cb->txmode) {
@@ -669,16 +719,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
err_unmap_msdu:
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
-err_free_txbuf:
- dma_pool_free(htt->tx_pool,
- skb_cb->htt.txbuf,
- skb_cb->htt.txbuf_paddr);
err_free_msdu_id:
spin_lock_bh(&htt->tx_lock);
ath10k_htt_tx_free_msdu_id(htt, msdu_id);
spin_unlock_bh(&htt->tx_lock);
err_tx_dec:
- ath10k_htt_tx_dec_pending(htt);
+ ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
err:
return res;
}
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 23afcda2de96..39966a05c1cc 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -84,6 +84,15 @@ enum qca6174_chip_id_rev {
#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
+/* QCA9377 1.0 definitions */
+#define QCA9377_HW_1_0_DEV_VERSION 0x05020001
+#define QCA9377_HW_1_0_CHIP_ID_REV 0x1
+#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
+#define QCA9377_HW_1_0_FW_FILE "firmware.bin"
+#define QCA9377_HW_1_0_OTP_FILE "otp.bin"
+#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
+#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234
+
#define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin"
@@ -94,9 +103,13 @@ enum qca6174_chip_id_rev {
#define ATH10K_FW_API5_FILE "firmware-5.bin"
#define ATH10K_FW_UTF_FILE "utf.bin"
+#define ATH10K_FW_UTF_API2_FILE "utf-2.bin"
/* includes also the null byte */
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
+#define ATH10K_BOARD_MAGIC "QCA-ATH10K-BOARD"
+
+#define ATH10K_BOARD_API2_FILE "board-2.bin"
#define REG_DUMP_COUNT_QCA988X 60
@@ -159,10 +172,21 @@ enum ath10k_fw_htt_op_version {
ATH10K_FW_HTT_OP_VERSION_MAX,
};
+enum ath10k_bd_ie_type {
+ /* contains sub IEs of enum ath10k_bd_ie_board_type */
+ ATH10K_BD_IE_BOARD = 0,
+};
+
+enum ath10k_bd_ie_board_type {
+ ATH10K_BD_IE_BOARD_NAME = 0,
+ ATH10K_BD_IE_BOARD_DATA = 1,
+};
+
enum ath10k_hw_rev {
ATH10K_HW_QCA988X,
ATH10K_HW_QCA6174,
ATH10K_HW_QCA99X0,
+ ATH10K_HW_QCA9377,
};
struct ath10k_hw_regs {
@@ -215,6 +239,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
+#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
/* Known pecularities:
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
@@ -337,7 +362,7 @@ enum ath10k_hw_rate_cck {
#define TARGET_10X_MAX_FRAG_ENTRIES 0
/* 10.2 parameters */
-#define TARGET_10_2_DMA_BURST_SIZE 1
+#define TARGET_10_2_DMA_BURST_SIZE 0
/* Target specific defines for WMI-TLV firmware */
#define TARGET_TLV_NUM_VDEVS 4
@@ -391,7 +416,7 @@ enum ath10k_hw_rate_cck {
#define TARGET_10_4_TX_DBG_LOG_SIZE 1024
#define TARGET_10_4_NUM_WDS_ENTRIES 32
-#define TARGET_10_4_DMA_BURST_SIZE 1
+#define TARGET_10_4_DMA_BURST_SIZE 0
#define TARGET_10_4_MAC_AGGR_DELIM 0
#define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
#define TARGET_10_4_VOW_CONFIG 0
@@ -414,16 +439,6 @@ enum ath10k_hw_rate_cck {
#define CE_COUNT ar->hw_values->ce_count
/*
- * Total number of PCIe MSI interrupts requested for all interrupt sources.
- * PCIe standard forces this to be a power of 2.
- * Some Host OS's limit MSI requests that can be granted to 8
- * so for now we abide by this limit and avoid requesting more
- * than that.
- */
-#define MSI_NUM_REQUEST_LOG2 3
-#define MSI_NUM_REQUEST (1<<MSI_NUM_REQUEST_LOG2)
-
-/*
* Granted MSIs are assigned as follows:
* Firmware uses the first
* Remaining MSIs, if any, are used by Copy Engines
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 64674c955d44..a7411fe90cc4 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -197,9 +197,8 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
return -EOPNOTSUPP;
}
- if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+ if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- }
if (cmd == DISABLE_KEY) {
arg.key_cipher = WMI_CIPHER_NONE;
@@ -1070,6 +1069,7 @@ static bool ath10k_mac_monitor_vdev_is_needed(struct ath10k *ar)
return false;
return ar->monitor ||
+ ar->filter_flags & FIF_OTHER_BSS ||
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
}
@@ -1110,7 +1110,8 @@ static int ath10k_monitor_recalc(struct ath10k *ar)
ret = ath10k_monitor_stop(ar);
if (ret)
- ath10k_warn(ar, "failed to stop disallowed monitor: %d\n", ret);
+ ath10k_warn(ar, "failed to stop disallowed monitor: %d\n",
+ ret);
/* not serious */
}
@@ -2083,7 +2084,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
enum ieee80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
- int i, n, max_nss;
+ int i, n;
+ u8 max_nss;
u32 stbc;
lockdep_assert_held(&ar->conf_mutex);
@@ -2168,7 +2170,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
arg->peer_ht_rates.rates[i] = i;
} else {
arg->peer_ht_rates.num_rates = n;
- arg->peer_num_spatial_streams = max_nss;
+ arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss);
}
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
@@ -3617,9 +3619,6 @@ static int ath10k_start_scan(struct ath10k *ar,
}
spin_unlock_bh(&ar->data_lock);
- /* Add a 200ms margin to account for event/command processing */
- ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
- msecs_to_jiffies(arg->max_scan_time+200));
return 0;
}
@@ -3737,13 +3736,8 @@ static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
mutex_lock(&ar->conf_mutex);
- if (ar->cfg_tx_chainmask) {
- *tx_ant = ar->cfg_tx_chainmask;
- *rx_ant = ar->cfg_rx_chainmask;
- } else {
- *tx_ant = ar->supp_tx_chainmask;
- *rx_ant = ar->supp_rx_chainmask;
- }
+ *tx_ant = ar->cfg_tx_chainmask;
+ *rx_ant = ar->cfg_rx_chainmask;
mutex_unlock(&ar->conf_mutex);
@@ -3763,6 +3757,169 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg)
dbg, cm);
}
+static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
+{
+ int nsts = ar->vht_cap_info;
+
+ nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
+ nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
+
+ /* If firmware does not deliver to host number of space-time
+ * streams supported, assume it support up to 4 BF STS and return
+ * the value for VHT CAP: nsts-1)
+ */
+ if (nsts == 0)
+ return 3;
+
+ return nsts;
+}
+
+static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
+{
+ int sound_dim = ar->vht_cap_info;
+
+ sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
+ sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
+
+ /* If the sounding dimension is not advertised by the firmware,
+ * let's use a default value of 1
+ */
+ if (sound_dim == 0)
+ return 1;
+
+ return sound_dim;
+}
+
+static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
+{
+ struct ieee80211_sta_vht_cap vht_cap = {0};
+ u16 mcs_map;
+ u32 val;
+ int i;
+
+ vht_cap.vht_supported = 1;
+ vht_cap.cap = ar->vht_cap_info;
+
+ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
+ val = ath10k_mac_get_vht_cap_bf_sts(ar);
+ val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
+ val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
+
+ vht_cap.cap |= val;
+ }
+
+ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
+ val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
+ val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
+ val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
+
+ vht_cap.cap |= val;
+ }
+
+ mcs_map = 0;
+ for (i = 0; i < 8; i++) {
+ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
+ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
+ else
+ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
+ }
+
+ vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+ vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+
+ return vht_cap;
+}
+
+static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
+{
+ int i;
+ struct ieee80211_sta_ht_cap ht_cap = {0};
+
+ if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
+ return ht_cap;
+
+ ht_cap.ht_supported = 1;
+ ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
+ ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+ ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+ if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
+ ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+
+ if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
+ ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+
+ if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
+ u32 smps;
+
+ smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
+ smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+ ht_cap.cap |= smps;
+ }
+
+ if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
+ ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
+
+ if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
+ u32 stbc;
+
+ stbc = ar->ht_cap_info;
+ stbc &= WMI_HT_CAP_RX_STBC;
+ stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
+ stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
+ stbc &= IEEE80211_HT_CAP_RX_STBC;
+
+ ht_cap.cap |= stbc;
+ }
+
+ if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
+ ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
+
+ if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
+ ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
+
+ /* max AMSDU is implicitly taken from vht_cap_info */
+ if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
+ ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+ for (i = 0; i < ar->num_rf_chains; i++) {
+ if (ar->cfg_rx_chainmask & BIT(i))
+ ht_cap.mcs.rx_mask[i] = 0xFF;
+ }
+
+ ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+
+ return ht_cap;
+}
+
+static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar)
+{
+ struct ieee80211_supported_band *band;
+ struct ieee80211_sta_vht_cap vht_cap;
+ struct ieee80211_sta_ht_cap ht_cap;
+
+ ht_cap = ath10k_get_ht_cap(ar);
+ vht_cap = ath10k_create_vht_cap(ar);
+
+ if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
+ band = &ar->mac.sbands[IEEE80211_BAND_2GHZ];
+ band->ht_cap = ht_cap;
+
+ /* Enable the VHT support at 2.4 GHz */
+ band->vht_cap = vht_cap;
+ }
+ if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
+ band = &ar->mac.sbands[IEEE80211_BAND_5GHZ];
+ band->ht_cap = ht_cap;
+ band->vht_cap = vht_cap;
+ }
+}
+
static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
{
int ret;
@@ -3795,6 +3952,9 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
return ret;
}
+ /* Reload HT/VHT capability */
+ ath10k_mac_setup_ht_vht_cap(ar);
+
return 0;
}
@@ -3885,9 +4045,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
}
}
- if (ar->cfg_tx_chainmask)
- __ath10k_set_antenna(ar, ar->cfg_tx_chainmask,
- ar->cfg_rx_chainmask);
+ __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
/*
* By default FW set ARP frames ac to voice (6). In that case ARP
@@ -3906,6 +4064,18 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err_core_stop;
}
+ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA,
+ ar->fw_features)) {
+ ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1,
+ WMI_CCA_DETECT_LEVEL_AUTO,
+ WMI_CCA_DETECT_MARGIN_AUTO);
+ if (ret) {
+ ath10k_warn(ar, "failed to enable adaptive cca: %d\n",
+ ret);
+ goto err_core_stop;
+ }
+ }
+
ret = ath10k_wmi_pdev_set_param(ar,
ar->wmi.pdev_param->ani_enable, 1);
if (ret) {
@@ -4068,17 +4238,21 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
{
u32 value = 0;
struct ath10k *ar = arvif->ar;
+ int nsts;
+ int sound_dim;
if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_BEFORE_ASSOC)
return 0;
+ nsts = ath10k_mac_get_vht_cap_bf_sts(ar);
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE))
- value |= SM((ar->num_rf_chains - 1), WMI_TXBF_STS_CAP_OFFSET);
+ value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);
+ sound_dim = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE))
- value |= SM((ar->num_rf_chains - 1), WMI_BF_SOUND_DIM_OFFSET);
+ value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET);
if (!value)
return 0;
@@ -4175,6 +4349,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
case NL80211_IFTYPE_ADHOC:
arvif->vdev_type = WMI_VDEV_TYPE_IBSS;
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+ ret = -EINVAL;
+ ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n");
+ goto err;
+ }
+ arvif->vdev_type = WMI_VDEV_TYPE_AP;
+ break;
case NL80211_IFTYPE_AP:
arvif->vdev_type = WMI_VDEV_TYPE_AP;
@@ -4215,6 +4397,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
* become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
*/
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,
@@ -4554,6 +4737,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
if (ret)
ath10k_warn(ar, "failed to update beacon template: %d\n",
ret);
+
+ if (ieee80211_vif_is_mesh(vif)) {
+ /* mesh doesn't use SSID but firmware needs it */
+ strncpy(arvif->u.ap.ssid, "mesh",
+ sizeof(arvif->u.ap.ssid));
+ arvif->u.ap.ssid_len = 4;
+ }
}
if (changed & BSS_CHANGED_AP_PROBE_RESP) {
@@ -4607,7 +4797,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
info->use_cts_prot ? 1 : 0);
if (ret)
ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n",
- info->use_cts_prot, arvif->vdev_id, ret);
+ info->use_cts_prot, arvif->vdev_id, ret);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -4751,6 +4941,11 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->data_lock);
}
+ /* Add a 200ms margin to account for event/command processing */
+ ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
+ msecs_to_jiffies(arg.max_scan_time +
+ 200));
+
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
@@ -5293,6 +5488,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
/*
* New association.
@@ -5328,6 +5524,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH &&
(vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
/*
* Disassociation.
@@ -5901,7 +6098,7 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
}
static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
- u8 rate, u8 nss, u8 sgi)
+ u8 rate, u8 nss, u8 sgi, u8 ldpc)
{
struct ath10k *ar = arvif->ar;
u32 vdev_param;
@@ -5934,6 +6131,13 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
return ret;
}
+ vdev_param = ar->wmi.vdev_param->ldpc;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ldpc);
+ if (ret) {
+ ath10k_warn(ar, "failed to set ldpc param %d: %d\n", ldpc, ret);
+ return ret;
+ }
+
return 0;
}
@@ -5997,6 +6201,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
u8 rate;
u8 nss;
u8 sgi;
+ u8 ldpc;
int single_nss;
int ret;
@@ -6006,6 +6211,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
band = def.chan->band;
ht_mcs_mask = mask->control[band].ht_mcs;
vht_mcs_mask = mask->control[band].vht_mcs;
+ ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
sgi = mask->control[band].gi;
if (sgi == NL80211_TXRATE_FORCE_LGI)
@@ -6044,7 +6250,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
- ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi);
+ ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
if (ret) {
ath10k_warn(ar, "failed to set fixed rate params on vdev %i: %d\n",
arvif->vdev_id, ret);
@@ -6144,7 +6350,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
@@ -6203,8 +6409,8 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
rcu_read_lock();
if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) {
ieee80211_iter_chan_contexts_atomic(ar->hw,
- ath10k_mac_get_any_chandef_iter,
- &def);
+ ath10k_mac_get_any_chandef_iter,
+ &def);
if (vifs)
def = &vifs[0].new_ctx->def;
@@ -6218,6 +6424,94 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
rcu_read_unlock();
}
+static void
+ath10k_mac_update_vif_chan(struct ath10k *ar,
+ struct ieee80211_vif_chanctx_switch *vifs,
+ int n_vifs)
+{
+ struct ath10k_vif *arvif;
+ int ret;
+ int i;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ /* First stop monitor interface. Some FW versions crash if there's a
+ * lone monitor interface.
+ */
+ if (ar->monitor_started)
+ ath10k_monitor_stop(ar);
+
+ for (i = 0; i < n_vifs; i++) {
+ arvif = ath10k_vif_to_arvif(vifs[i].vif);
+
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
+ arvif->vdev_id,
+ vifs[i].old_ctx->def.chan->center_freq,
+ vifs[i].new_ctx->def.chan->center_freq,
+ vifs[i].old_ctx->def.width,
+ vifs[i].new_ctx->def.width);
+
+ if (WARN_ON(!arvif->is_started))
+ continue;
+
+ if (WARN_ON(!arvif->is_up))
+ continue;
+
+ ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
+ if (ret) {
+ ath10k_warn(ar, "failed to down vdev %d: %d\n",
+ arvif->vdev_id, ret);
+ continue;
+ }
+ }
+
+ /* All relevant vdevs are downed and associated channel resources
+ * should be available for the channel switch now.
+ */
+
+ spin_lock_bh(&ar->data_lock);
+ ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
+ spin_unlock_bh(&ar->data_lock);
+
+ for (i = 0; i < n_vifs; i++) {
+ arvif = ath10k_vif_to_arvif(vifs[i].vif);
+
+ if (WARN_ON(!arvif->is_started))
+ continue;
+
+ if (WARN_ON(!arvif->is_up))
+ continue;
+
+ ret = ath10k_mac_setup_bcn_tmpl(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
+ ret);
+
+ ret = ath10k_mac_setup_prb_tmpl(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
+ ret);
+
+ ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def);
+ if (ret) {
+ ath10k_warn(ar, "failed to restart vdev %d: %d\n",
+ arvif->vdev_id, ret);
+ continue;
+ }
+
+ ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
+ arvif->bssid);
+ if (ret) {
+ ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
+ arvif->vdev_id, ret);
+ continue;
+ }
+ }
+
+ ath10k_monitor_recalc(ar);
+}
+
static int
ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx)
@@ -6264,12 +6558,52 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
+struct ath10k_mac_change_chanctx_arg {
+ struct ieee80211_chanctx_conf *ctx;
+ struct ieee80211_vif_chanctx_switch *vifs;
+ int n_vifs;
+ int next_vif;
+};
+
+static void
+ath10k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct ath10k_mac_change_chanctx_arg *arg = data;
+
+ if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx)
+ return;
+
+ arg->n_vifs++;
+}
+
+static void
+ath10k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct ath10k_mac_change_chanctx_arg *arg = data;
+ struct ieee80211_chanctx_conf *ctx;
+
+ ctx = rcu_access_pointer(vif->chanctx_conf);
+ if (ctx != arg->ctx)
+ return;
+
+ if (WARN_ON(arg->next_vif == arg->n_vifs))
+ return;
+
+ arg->vifs[arg->next_vif].vif = vif;
+ arg->vifs[arg->next_vif].old_ctx = ctx;
+ arg->vifs[arg->next_vif].new_ctx = ctx;
+ arg->next_vif++;
+}
+
static void
ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx,
u32 changed)
{
struct ath10k *ar = hw->priv;
+ struct ath10k_mac_change_chanctx_arg arg = { .ctx = ctx };
mutex_lock(&ar->conf_mutex);
@@ -6283,6 +6617,30 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
goto unlock;
+ if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
+ ieee80211_iterate_active_interfaces_atomic(
+ hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ ath10k_mac_change_chanctx_cnt_iter,
+ &arg);
+ if (arg.n_vifs == 0)
+ goto radar;
+
+ arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]),
+ GFP_KERNEL);
+ if (!arg.vifs)
+ goto radar;
+
+ ieee80211_iterate_active_interfaces_atomic(
+ hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ ath10k_mac_change_chanctx_fill_iter,
+ &arg);
+ ath10k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
+ kfree(arg.vifs);
+ }
+
+radar:
ath10k_recalc_radar_detection(ar);
/* FIXME: How to configure Rx chains properly? */
@@ -6402,91 +6760,13 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
enum ieee80211_chanctx_switch_mode mode)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif;
- int ret;
- int i;
mutex_lock(&ar->conf_mutex);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac chanctx switch n_vifs %d mode %d\n",
n_vifs, mode);
-
- /* First stop monitor interface. Some FW versions crash if there's a
- * lone monitor interface.
- */
- if (ar->monitor_started)
- ath10k_monitor_stop(ar);
-
- for (i = 0; i < n_vifs; i++) {
- arvif = ath10k_vif_to_arvif(vifs[i].vif);
-
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
- arvif->vdev_id,
- vifs[i].old_ctx->def.chan->center_freq,
- vifs[i].new_ctx->def.chan->center_freq,
- vifs[i].old_ctx->def.width,
- vifs[i].new_ctx->def.width);
-
- if (WARN_ON(!arvif->is_started))
- continue;
-
- if (WARN_ON(!arvif->is_up))
- continue;
-
- ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
- if (ret) {
- ath10k_warn(ar, "failed to down vdev %d: %d\n",
- arvif->vdev_id, ret);
- continue;
- }
- }
-
- /* All relevant vdevs are downed and associated channel resources
- * should be available for the channel switch now.
- */
-
- spin_lock_bh(&ar->data_lock);
- ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
- spin_unlock_bh(&ar->data_lock);
-
- for (i = 0; i < n_vifs; i++) {
- arvif = ath10k_vif_to_arvif(vifs[i].vif);
-
- if (WARN_ON(!arvif->is_started))
- continue;
-
- if (WARN_ON(!arvif->is_up))
- continue;
-
- ret = ath10k_mac_setup_bcn_tmpl(arvif);
- if (ret)
- ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
- ret);
-
- ret = ath10k_mac_setup_prb_tmpl(arvif);
- if (ret)
- ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
- ret);
-
- ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def);
- if (ret) {
- ath10k_warn(ar, "failed to restart vdev %d: %d\n",
- arvif->vdev_id, ret);
- continue;
- }
-
- ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
- if (ret) {
- ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
- arvif->vdev_id, ret);
- continue;
- }
- }
-
- ath10k_monitor_recalc(ar);
+ ath10k_mac_update_vif_chan(ar, vifs, n_vifs);
mutex_unlock(&ar->conf_mutex);
return 0;
@@ -6642,6 +6922,9 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
{
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
+#ifdef CONFIG_MAC80211_MESH
+ | BIT(NL80211_IFTYPE_MESH_POINT)
+#endif
},
};
@@ -6649,6 +6932,9 @@ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
{
.max = 8,
.types = BIT(NL80211_IFTYPE_AP)
+#ifdef CONFIG_MAC80211_MESH
+ | BIT(NL80211_IFTYPE_MESH_POINT)
+#endif
},
};
@@ -6686,6 +6972,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = {
{
.max = 2,
.types = BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
},
@@ -6707,6 +6996,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = {
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
BIT(NL80211_IFTYPE_P2P_GO),
},
{
@@ -6773,6 +7065,9 @@ static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = {
{
.max = 16,
.types = BIT(NL80211_IFTYPE_AP)
+#ifdef CONFIG_MAC80211_MESH
+ | BIT(NL80211_IFTYPE_MESH_POINT)
+#endif
},
};
@@ -6792,111 +7087,6 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
},
};
-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
-{
- struct ieee80211_sta_vht_cap vht_cap = {0};
- u16 mcs_map;
- u32 val;
- int i;
-
- vht_cap.vht_supported = 1;
- vht_cap.cap = ar->vht_cap_info;
-
- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
- IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
- val = ar->num_rf_chains - 1;
- val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
- val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
-
- vht_cap.cap |= val;
- }
-
- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
- IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
- val = ar->num_rf_chains - 1;
- val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
- val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
-
- vht_cap.cap |= val;
- }
-
- mcs_map = 0;
- for (i = 0; i < 8; i++) {
- if (i < ar->num_rf_chains)
- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
- else
- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
- }
-
- vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
- vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
-
- return vht_cap;
-}
-
-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
-{
- int i;
- struct ieee80211_sta_ht_cap ht_cap = {0};
-
- if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
- return ht_cap;
-
- ht_cap.ht_supported = 1;
- ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
- ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
- ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
-
- if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
- ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
-
- if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
- ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-
- if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
- u32 smps;
-
- smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
- smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
-
- ht_cap.cap |= smps;
- }
-
- if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
- ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
-
- if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
- u32 stbc;
-
- stbc = ar->ht_cap_info;
- stbc &= WMI_HT_CAP_RX_STBC;
- stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
- stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
- stbc &= IEEE80211_HT_CAP_RX_STBC;
-
- ht_cap.cap |= stbc;
- }
-
- if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
- ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
-
- if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
- ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
-
- /* max AMSDU is implicitly taken from vht_cap_info */
- if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
- ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
-
- for (i = 0; i < ar->num_rf_chains; i++)
- ht_cap.mcs.rx_mask[i] = 0xFF;
-
- ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
-
- return ht_cap;
-}
-
static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -6938,8 +7128,6 @@ int ath10k_mac_register(struct ath10k *ar)
WLAN_CIPHER_SUITE_AES_CMAC,
};
struct ieee80211_supported_band *band;
- struct ieee80211_sta_vht_cap vht_cap;
- struct ieee80211_sta_ht_cap ht_cap;
void *channels;
int ret;
@@ -6947,9 +7135,6 @@ int ath10k_mac_register(struct ath10k *ar)
SET_IEEE80211_DEV(ar->hw, ar->dev);
- ht_cap = ath10k_get_ht_cap(ar);
- vht_cap = ath10k_create_vht_cap(ar);
-
BUILD_BUG_ON((ARRAY_SIZE(ath10k_2ghz_channels) +
ARRAY_SIZE(ath10k_5ghz_channels)) !=
ATH10K_NUM_CHANS);
@@ -6968,10 +7153,6 @@ int ath10k_mac_register(struct ath10k *ar)
band->channels = channels;
band->n_bitrates = ath10k_g_rates_size;
band->bitrates = ath10k_g_rates;
- band->ht_cap = ht_cap;
-
- /* Enable the VHT support at 2.4 GHz */
- band->vht_cap = vht_cap;
ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
}
@@ -6990,17 +7171,18 @@ int ath10k_mac_register(struct ath10k *ar)
band->channels = channels;
band->n_bitrates = ath10k_a_rates_size;
band->bitrates = ath10k_a_rates;
- band->ht_cap = ht_cap;
- band->vht_cap = vht_cap;
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band;
}
+ ath10k_mac_setup_ht_vht_cap(ar);
+
ar->hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP);
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
- ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
- ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
+ ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask;
+ ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask;
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
ar->hw->wiphy->interface_modes |=
@@ -7146,7 +7328,7 @@ int ath10k_mac_register(struct ath10k *ar)
ath10k_reg_notifier);
if (ret) {
ath10k_err(ar, "failed to initialise regulatory: %i\n", ret);
- goto err_free;
+ goto err_dfs_detector_exit;
}
ar->hw->wiphy->cipher_suites = cipher_suites;
@@ -7155,7 +7337,7 @@ int ath10k_mac_register(struct ath10k *ar)
ret = ieee80211_register_hw(ar->hw);
if (ret) {
ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
- goto err_free;
+ goto err_dfs_detector_exit;
}
if (!ath_is_world_regd(&ar->ath_common.regulatory)) {
@@ -7169,10 +7351,16 @@ int ath10k_mac_register(struct ath10k *ar)
err_unregister:
ieee80211_unregister_hw(ar->hw);
+
+err_dfs_detector_exit:
+ if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+ ar->dfs_detector->exit(ar->dfs_detector);
+
err_free:
kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels);
kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels);
+ SET_IEEE80211_DEV(ar->hw, NULL);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 1046ab65b9ab..3fca200b986c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -61,12 +61,14 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
#define QCA6164_2_1_DEVICE_ID (0x0041)
#define QCA6174_2_1_DEVICE_ID (0x003e)
#define QCA99X0_2_0_DEVICE_ID (0x0040)
+#define QCA9377_1_0_DEVICE_ID (0x0042)
static const struct pci_device_id ath10k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
{ PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
{ PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
+ { PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */
{0}
};
@@ -90,6 +92,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
{ QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV },
+ { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV },
};
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
@@ -104,6 +107,10 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
struct ath10k_ce_pipe *rx_pipe,
struct bmi_xfer *xfer);
static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar);
+static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
static const struct ce_attr host_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */
@@ -112,6 +119,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 16,
.src_sz_max = 256,
.dest_nentries = 0,
+ .send_cb = ath10k_pci_htc_tx_cb,
},
/* CE1: target->host HTT + HTC control */
@@ -120,6 +128,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
+ .recv_cb = ath10k_pci_htc_rx_cb,
},
/* CE2: target->host WMI */
@@ -128,6 +137,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 128,
+ .recv_cb = ath10k_pci_htc_rx_cb,
},
/* CE3: host->target WMI */
@@ -136,6 +146,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
+ .send_cb = ath10k_pci_htc_tx_cb,
},
/* CE4: host->target HTT */
@@ -144,14 +155,16 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = CE_HTT_H2T_MSG_SRC_NENTRIES,
.src_sz_max = 256,
.dest_nentries = 0,
+ .send_cb = ath10k_pci_htt_tx_cb,
},
- /* CE5: unused */
+ /* CE5: target->host HTT (HIF->HTT) */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
+ .src_sz_max = 512,
+ .dest_nentries = 512,
+ .recv_cb = ath10k_pci_htt_rx_cb,
},
/* CE6: target autonomous hif_memcpy */
@@ -257,12 +270,12 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
/* NB: 50% of src nentries, since tx has 2 frags */
- /* CE5: unused */
+ /* CE5: target->host HTT (HIF->HTT) */
{
.pipenum = __cpu_to_le32(5),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
+ .nbytes_max = __cpu_to_le32(512),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
@@ -396,7 +409,7 @@ static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
{
__cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(1),
+ __cpu_to_le32(5),
},
/* (Additions here) */
@@ -452,8 +465,12 @@ static int ath10k_pci_wake_wait(struct ath10k *ar)
int curr_delay = 5;
while (tot_delay < PCIE_WAKE_TIMEOUT) {
- if (ath10k_pci_is_awake(ar))
+ if (ath10k_pci_is_awake(ar)) {
+ if (tot_delay > PCIE_WAKE_LATE_US)
+ ath10k_warn(ar, "device wakeup took %d ms which is unusally long, otherwise it works normally.\n",
+ tot_delay / 1000);
return 0;
+ }
udelay(curr_delay);
tot_delay += curr_delay;
@@ -465,12 +482,53 @@ static int ath10k_pci_wake_wait(struct ath10k *ar)
return -ETIMEDOUT;
}
+static int ath10k_pci_force_wake(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&ar_pci->ps_lock, flags);
+
+ if (!ar_pci->ps_awake) {
+ iowrite32(PCIE_SOC_WAKE_V_MASK,
+ ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
+ PCIE_SOC_WAKE_ADDRESS);
+
+ ret = ath10k_pci_wake_wait(ar);
+ if (ret == 0)
+ ar_pci->ps_awake = true;
+ }
+
+ spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
+
+ return ret;
+}
+
+static void ath10k_pci_force_sleep(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ar_pci->ps_lock, flags);
+
+ iowrite32(PCIE_SOC_WAKE_RESET,
+ ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
+ PCIE_SOC_WAKE_ADDRESS);
+ ar_pci->ps_awake = false;
+
+ spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
+}
+
static int ath10k_pci_wake(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
unsigned long flags;
int ret = 0;
+ if (ar_pci->pci_ps == 0)
+ return ret;
+
spin_lock_irqsave(&ar_pci->ps_lock, flags);
ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake refcount %lu awake %d\n",
@@ -502,6 +560,9 @@ static void ath10k_pci_sleep(struct ath10k *ar)
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
unsigned long flags;
+ if (ar_pci->pci_ps == 0)
+ return;
+
spin_lock_irqsave(&ar_pci->ps_lock, flags);
ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep refcount %lu awake %d\n",
@@ -544,6 +605,11 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar)
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
unsigned long flags;
+ if (ar_pci->pci_ps == 0) {
+ ath10k_pci_force_sleep(ar);
+ return;
+ }
+
del_timer_sync(&ar_pci->ps_timer);
spin_lock_irqsave(&ar_pci->ps_lock, flags);
@@ -682,8 +748,6 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
dma_addr_t paddr;
int ret;
- lockdep_assert_held(&ar_pci->ce_lock);
-
skb = dev_alloc_skb(pipe->buf_sz);
if (!skb)
return -ENOMEM;
@@ -701,9 +765,10 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
ATH10K_SKB_RXCB(skb)->paddr = paddr;
+ spin_lock_bh(&ar_pci->ce_lock);
ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr);
+ spin_unlock_bh(&ar_pci->ce_lock);
if (ret) {
- ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret);
dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
@@ -713,25 +778,27 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
return 0;
}
-static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
+static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
{
struct ath10k *ar = pipe->hif_ce_state;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
int ret, num;
- lockdep_assert_held(&ar_pci->ce_lock);
-
if (pipe->buf_sz == 0)
return;
if (!ce_pipe->dest_ring)
return;
+ spin_lock_bh(&ar_pci->ce_lock);
num = __ath10k_ce_rx_num_free_bufs(ce_pipe);
+ spin_unlock_bh(&ar_pci->ce_lock);
while (num--) {
ret = __ath10k_pci_rx_post_buf(pipe);
if (ret) {
+ if (ret == -ENOSPC)
+ break;
ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret);
mod_timer(&ar_pci->rx_post_retry, jiffies +
ATH10K_PCI_RX_POST_RETRY_MS);
@@ -740,25 +807,13 @@ static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
}
}
-static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
-{
- struct ath10k *ar = pipe->hif_ce_state;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
- spin_lock_bh(&ar_pci->ce_lock);
- __ath10k_pci_rx_post_pipe(pipe);
- spin_unlock_bh(&ar_pci->ce_lock);
-}
-
static void ath10k_pci_rx_post(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int i;
- spin_lock_bh(&ar_pci->ce_lock);
for (i = 0; i < CE_COUNT; i++)
- __ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]);
- spin_unlock_bh(&ar_pci->ce_lock);
+ ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]);
}
static void ath10k_pci_rx_replenish_retry(unsigned long ptr)
@@ -775,6 +830,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
switch (ar->hw_rev) {
case ATH10K_HW_QCA988X:
case ATH10K_HW_QCA6174:
+ case ATH10K_HW_QCA9377:
val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
CORE_CTRL_ADDRESS) &
0x7ff) << 21;
@@ -858,9 +914,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
goto done;
i = 0;
- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
- &completed_nbytes,
- &id) != 0) {
+ while (ath10k_ce_completed_send_next_nolock(ce_diag,
+ NULL) != 0) {
mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
ret = -EBUSY;
@@ -868,16 +923,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
}
}
- if (nbytes != completed_nbytes) {
- ret = -EIO;
- goto done;
- }
-
- if (buf != (u32)address) {
- ret = -EIO;
- goto done;
- }
-
i = 0;
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
&completed_nbytes,
@@ -1031,9 +1076,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
goto done;
i = 0;
- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
- &completed_nbytes,
- &id) != 0) {
+ while (ath10k_ce_completed_send_next_nolock(ce_diag,
+ NULL) != 0) {
mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -1042,16 +1086,6 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
}
}
- if (nbytes != completed_nbytes) {
- ret = -EIO;
- goto done;
- }
-
- if (buf != ce_data) {
- ret = -EIO;
- goto done;
- }
-
i = 0;
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
&completed_nbytes,
@@ -1102,20 +1136,14 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value)
}
/* Called by lower (CE) layer when a send to Target completes. */
-static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
+static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state)
{
struct ath10k *ar = ce_state->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
struct sk_buff_head list;
struct sk_buff *skb;
- u32 ce_data;
- unsigned int nbytes;
- unsigned int transfer_id;
__skb_queue_head_init(&list);
- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
- &nbytes, &transfer_id) == 0) {
+ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
/* no need to call tx completion for NULL pointers */
if (skb == NULL)
continue;
@@ -1124,16 +1152,16 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
}
while ((skb = __skb_dequeue(&list)))
- cb->tx_completion(ar, skb);
+ ath10k_htc_tx_completion_handler(ar, skb);
}
-/* Called by lower (CE) layer when data is received from the Target. */
-static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
+static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state,
+ void (*callback)(struct ath10k *ar,
+ struct sk_buff *skb))
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id];
- struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
struct sk_buff *skb;
struct sk_buff_head list;
void *transfer_context;
@@ -1168,12 +1196,52 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
skb->data, skb->len);
- cb->rx_completion(ar, skb);
+ callback(ar, skb);
}
ath10k_pci_rx_post_pipe(pipe_info);
}
+/* Called by lower (CE) layer when data is received from the Target. */
+static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
+}
+
+/* Called by lower (CE) layer when a send to HTT Target completes. */
+static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ struct ath10k *ar = ce_state->ar;
+ struct sk_buff *skb;
+
+ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
+ /* no need to call tx completion for NULL pointers */
+ if (!skb)
+ continue;
+
+ dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
+ skb->len, DMA_TO_DEVICE);
+ ath10k_htt_hif_tx_complete(ar, skb);
+ }
+}
+
+static void ath10k_pci_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb)
+{
+ skb_pull(skb, sizeof(struct ath10k_htc_hdr));
+ ath10k_htt_t2h_msg_handler(ar, skb);
+}
+
+/* Called by lower (CE) layer when HTT data is received from the Target. */
+static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ /* CE4 polling needs to be done whenever CE pipe which transports
+ * HTT Rx (target->host) is processed.
+ */
+ ath10k_ce_per_engine_service(ce_state->ar, 4);
+
+ ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver);
+}
+
static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
struct ath10k_hif_sg_item *items, int n_items)
{
@@ -1343,17 +1411,6 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
ath10k_ce_per_engine_service(ar, pipe);
}
-static void ath10k_pci_hif_set_callbacks(struct ath10k *ar,
- struct ath10k_hif_cb *callbacks)
-{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
- ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif set callbacks\n");
-
- memcpy(&ar_pci->msg_callbacks_current, callbacks,
- sizeof(ar_pci->msg_callbacks_current));
-}
-
static void ath10k_pci_kill_tasklet(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -1368,10 +1425,8 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar)
del_timer_sync(&ar_pci->rx_post_retry);
}
-static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
- u16 service_id, u8 *ul_pipe,
- u8 *dl_pipe, int *ul_is_polled,
- int *dl_is_polled)
+static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id,
+ u8 *ul_pipe, u8 *dl_pipe)
{
const struct service_to_pipe *entry;
bool ul_set = false, dl_set = false;
@@ -1379,9 +1434,6 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif map service\n");
- /* polling for received messages not supported */
- *dl_is_polled = 0;
-
for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
entry = &target_service_to_ce_map_wlan[i];
@@ -1415,25 +1467,17 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
if (WARN_ON(!ul_set || !dl_set))
return -ENOENT;
- *ul_is_polled =
- (host_ce_config_wlan[*ul_pipe].flags & CE_ATTR_DIS_INTR) != 0;
-
return 0;
}
static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
u8 *ul_pipe, u8 *dl_pipe)
{
- int ul_is_polled, dl_is_polled;
-
ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n");
(void)ath10k_pci_hif_map_service_to_pipe(ar,
ATH10K_HTC_SVC_ID_RSVD_CTRL,
- ul_pipe,
- dl_pipe,
- &ul_is_polled,
- &dl_is_polled);
+ ul_pipe, dl_pipe);
}
static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
@@ -1443,6 +1487,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
switch (ar->hw_rev) {
case ATH10K_HW_QCA988X:
case ATH10K_HW_QCA6174:
+ case ATH10K_HW_QCA9377:
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
CORE_CTRL_ADDRESS);
val &= ~CORE_CTRL_PCIE_REG_31_MASK;
@@ -1464,6 +1509,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
switch (ar->hw_rev) {
case ATH10K_HW_QCA988X:
case ATH10K_HW_QCA6174:
+ case ATH10K_HW_QCA9377:
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
CORE_CTRL_ADDRESS);
val |= CORE_CTRL_PCIE_REG_31_MASK;
@@ -1504,6 +1550,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar)
static int ath10k_pci_hif_start(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
ath10k_pci_irq_enable(ar);
@@ -1553,7 +1600,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
struct ath10k_pci *ar_pci;
struct ath10k_ce_pipe *ce_pipe;
struct ath10k_ce_ring *ce_ring;
- struct ce_desc *ce_desc;
struct sk_buff *skb;
int i;
@@ -1568,10 +1614,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
if (!pci_pipe->buf_sz)
return;
- ce_desc = ce_ring->shadow_base;
- if (WARN_ON(!ce_desc))
- return;
-
for (i = 0; i < ce_ring->nentries; i++) {
skb = ce_ring->per_transfer_context[i];
if (!skb)
@@ -1579,7 +1621,7 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
ce_ring->per_transfer_context[i] = NULL;
- ar_pci->msg_callbacks_current.tx_completion(ar, skb);
+ ath10k_htc_tx_completion_handler(ar, skb);
}
}
@@ -1745,12 +1787,8 @@ err_dma:
static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
{
struct bmi_xfer *xfer;
- u32 ce_data;
- unsigned int nbytes;
- unsigned int transfer_id;
- if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data,
- &nbytes, &transfer_id))
+ if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer))
return;
xfer->tx_done = true;
@@ -1840,6 +1878,8 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
return 9;
}
break;
+ case QCA9377_1_0_DEVICE_ID:
+ return 2;
}
ath10k_warn(ar, "unknown number of banks, assuming 1\n");
@@ -1999,9 +2039,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar)
pipe->pipe_num = i;
pipe->hif_ce_state = ar;
- ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i],
- ath10k_pci_ce_send_done,
- ath10k_pci_ce_recv_data);
+ ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);
if (ret) {
ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",
i, ret);
@@ -2257,7 +2295,7 @@ static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar)
ret = ath10k_pci_wait_for_target_init(ar);
if (ret) {
ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
- ret);
+ ret);
return ret;
}
@@ -2302,6 +2340,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar)
return ath10k_pci_qca988x_chip_reset(ar);
else if (QCA_REV_6174(ar))
return ath10k_pci_qca6174_chip_reset(ar);
+ else if (QCA_REV_9377(ar))
+ return ath10k_pci_qca6174_chip_reset(ar);
else if (QCA_REV_99X0(ar))
return ath10k_pci_qca99x0_chip_reset(ar);
else
@@ -2397,6 +2437,15 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct pci_dev *pdev = ar_pci->pdev;
u32 val;
+ int ret = 0;
+
+ if (ar_pci->pci_ps == 0) {
+ ret = ath10k_pci_force_wake(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to wake up target: %d\n", ret);
+ return ret;
+ }
+ }
/* Suspend/Resume resets the PCI configuration space, so we have to
* re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
@@ -2407,7 +2456,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
- return 0;
+ return ret;
}
#endif
@@ -2421,7 +2470,6 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe,
.get_default_pipe = ath10k_pci_hif_get_default_pipe,
.send_complete_check = ath10k_pci_hif_send_complete_check,
- .set_callbacks = ath10k_pci_hif_set_callbacks,
.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,
.power_up = ath10k_pci_hif_power_up,
.power_down = ath10k_pci_hif_power_down,
@@ -2501,6 +2549,16 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
{
struct ath10k *ar = arg;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ int ret;
+
+ if (ar_pci->pci_ps == 0) {
+ ret = ath10k_pci_force_wake(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to wake device up on irq: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+ }
if (ar_pci->num_msi_intrs == 0) {
if (!ath10k_pci_irq_pending(ar))
@@ -2609,12 +2667,9 @@ static int ath10k_pci_request_irq(struct ath10k *ar)
return ath10k_pci_request_irq_legacy(ar);
case 1:
return ath10k_pci_request_irq_msi(ar);
- case MSI_NUM_REQUEST:
+ default:
return ath10k_pci_request_irq_msix(ar);
}
-
- ath10k_warn(ar, "unknown irq configuration upon request\n");
- return -EINVAL;
}
static void ath10k_pci_free_irq(struct ath10k *ar)
@@ -2657,7 +2712,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
/* Try MSI-X */
if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
- ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
+ ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1;
ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
ar_pci->num_msi_intrs);
if (ret > 0)
@@ -2705,18 +2760,13 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar)
switch (ar_pci->num_msi_intrs) {
case 0:
ath10k_pci_deinit_irq_legacy(ar);
- return 0;
- case 1:
- /* fall-through */
- case MSI_NUM_REQUEST:
- pci_disable_msi(ar_pci->pdev);
- return 0;
+ break;
default:
pci_disable_msi(ar_pci->pdev);
+ break;
}
- ath10k_warn(ar, "unknown irq configuration upon deinit\n");
- return -EINVAL;
+ return 0;
}
static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
@@ -2908,17 +2958,25 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
struct ath10k_pci *ar_pci;
enum ath10k_hw_rev hw_rev;
u32 chip_id;
+ bool pci_ps;
switch (pci_dev->device) {
case QCA988X_2_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA988X;
+ pci_ps = false;
break;
case QCA6164_2_1_DEVICE_ID:
case QCA6174_2_1_DEVICE_ID:
hw_rev = ATH10K_HW_QCA6174;
+ pci_ps = true;
break;
case QCA99X0_2_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA99X0;
+ pci_ps = false;
+ break;
+ case QCA9377_1_0_DEVICE_ID:
+ hw_rev = ATH10K_HW_QCA9377;
+ pci_ps = true;
break;
default:
WARN_ON(1);
@@ -2932,19 +2990,21 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
return -ENOMEM;
}
- ath10k_dbg(ar, ATH10K_DBG_PCI, "pci probe\n");
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device);
ar_pci = ath10k_pci_priv(ar);
ar_pci->pdev = pdev;
ar_pci->dev = &pdev->dev;
ar_pci->ar = ar;
ar->dev_id = pci_dev->device;
+ ar_pci->pci_ps = pci_ps;
- if (pdev->subsystem_vendor || pdev->subsystem_device)
- scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id),
- "%04x:%04x:%04x:%04x",
- pdev->vendor, pdev->device,
- pdev->subsystem_vendor, pdev->subsystem_device);
+ ar->id.vendor = pdev->vendor;
+ ar->id.device = pdev->device;
+ ar->id.subsystem_vendor = pdev->subsystem_vendor;
+ ar->id.subsystem_device = pdev->subsystem_device;
spin_lock_init(&ar_pci->ce_lock);
spin_lock_init(&ar_pci->ps_lock);
@@ -2970,6 +3030,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ath10k_pci_ce_deinit(ar);
ath10k_pci_irq_disable(ar);
+ if (ar_pci->pci_ps == 0) {
+ ret = ath10k_pci_force_wake(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to wake up device : %d\n", ret);
+ goto err_free_pipes;
+ }
+ }
+
ret = ath10k_pci_init_irq(ar);
if (ret) {
ath10k_err(ar, "failed to init irqs: %d\n", ret);
@@ -3098,13 +3166,20 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API5_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
+MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
/* QCA6174 2.1 firmware files */
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE);
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE);
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE);
+MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_BOARD_API2_FILE);
/* QCA6174 3.1 firmware files */
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE);
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE);
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
+MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
+
+/* QCA9377 1.0 firmware files */
+MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE);
+MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 8d364fb8f743..f91bf333cb75 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -175,8 +175,6 @@ struct ath10k_pci {
struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
- struct ath10k_hif_cb msg_callbacks_current;
-
/* Copy Engine used for Diagnostic Accesses */
struct ath10k_ce_pipe *ce_diag;
@@ -221,6 +219,12 @@ struct ath10k_pci {
* powersave register state changes.
*/
bool ps_awake;
+
+ /* pci power save, disable for QCA988X and QCA99X0.
+ * Writing 'false' to this variable avoids frequent locking
+ * on MMIO read/write.
+ */
+ bool pci_ps;
};
static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
@@ -230,7 +234,8 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
#define ATH10K_PCI_RX_POST_RETRY_MS 50
#define ATH_PCI_RESET_WAIT_MAX 10 /* ms */
-#define PCIE_WAKE_TIMEOUT 10000 /* 10ms */
+#define PCIE_WAKE_TIMEOUT 30000 /* 30ms */
+#define PCIE_WAKE_LATE_US 10000 /* 10ms */
#define BAR_NUM 0
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
index 768bef629099..05a421bc322a 100644
--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -450,6 +450,9 @@ Fw Mode/SubMode Mask
#define QCA6174_BOARD_DATA_SZ 8192
#define QCA6174_BOARD_EXT_DATA_SZ 0
+#define QCA9377_BOARD_DATA_SZ QCA6174_BOARD_DATA_SZ
+#define QCA9377_BOARD_EXT_DATA_SZ 0
+
#define QCA99X0_BOARD_DATA_SZ 12288
#define QCA99X0_BOARD_EXT_DATA_SZ 0
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index b084f88da102..1d5a2fdcbf56 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
return cfg80211_testmode_reply(skb);
}
-static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
+static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
+{
+ size_t len, magic_len, ie_len;
+ struct ath10k_fw_ie *hdr;
+ char filename[100];
+ __le32 *version;
+ const u8 *data;
+ int ie_id, ret;
+
+ snprintf(filename, sizeof(filename), "%s/%s",
+ ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE);
+
+ /* load utf firmware image */
+ ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
+ if (ret) {
+ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
+ filename, ret);
+ return ret;
+ }
+
+ data = ar->testmode.utf->data;
+ len = ar->testmode.utf->size;
+
+ /* FIXME: call release_firmware() in error cases */
+
+ /* magic also includes the null byte, check that as well */
+ magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
+
+ if (len < magic_len) {
+ ath10k_err(ar, "utf firmware file is too small to contain magic\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
+ ath10k_err(ar, "invalid firmware magic\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* jump over the padding */
+ magic_len = ALIGN(magic_len, 4);
+
+ len -= magic_len;
+ data += magic_len;
+
+ /* loop elements */
+ while (len > sizeof(struct ath10k_fw_ie)) {
+ hdr = (struct ath10k_fw_ie *)data;
+
+ ie_id = le32_to_cpu(hdr->id);
+ ie_len = le32_to_cpu(hdr->len);
+
+ len -= sizeof(*hdr);
+ data += sizeof(*hdr);
+
+ if (len < ie_len) {
+ ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
+ ie_id, len, ie_len);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ switch (ie_id) {
+ case ATH10K_FW_IE_FW_VERSION:
+ if (ie_len > sizeof(ar->testmode.utf_version) - 1)
+ break;
+
+ memcpy(ar->testmode.utf_version, data, ie_len);
+ ar->testmode.utf_version[ie_len] = '\0';
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+ "testmode found fw utf version %s\n",
+ ar->testmode.utf_version);
+ break;
+ case ATH10K_FW_IE_TIMESTAMP:
+ /* ignore timestamp, but don't warn about it either */
+ break;
+ case ATH10K_FW_IE_FW_IMAGE:
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+ "testmode found fw image ie (%zd B)\n",
+ ie_len);
+
+ ar->testmode.utf_firmware_data = data;
+ ar->testmode.utf_firmware_len = ie_len;
+ break;
+ case ATH10K_FW_IE_WMI_OP_VERSION:
+ if (ie_len != sizeof(u32))
+ break;
+ version = (__le32 *)data;
+ ar->testmode.op_version = le32_to_cpup(version);
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n",
+ ar->testmode.op_version);
+ break;
+ default:
+ ath10k_warn(ar, "Unknown testmode FW IE: %u\n",
+ le32_to_cpu(hdr->id));
+ break;
+ }
+ /* jump over the padding */
+ ie_len = ALIGN(ie_len, 4);
+
+ len -= ie_len;
+ data += ie_len;
+ }
+
+ if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) {
+ ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ release_firmware(ar->testmode.utf);
+
+ return ret;
+}
+
+static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
{
char filename[100];
int ret;
+ snprintf(filename, sizeof(filename), "%s/%s",
+ ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
+
+ /* load utf firmware image */
+ ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
+ if (ret) {
+ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
+ filename, ret);
+ return ret;
+ }
+
+ /* We didn't find FW UTF API 1 ("utf.bin") does not advertise
+ * firmware features. Do an ugly hack where we force the firmware
+ * features to match with 10.1 branch so that wmi.c will use the
+ * correct WMI interface.
+ */
+
+ ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
+ ar->testmode.utf_firmware_data = ar->testmode.utf->data;
+ ar->testmode.utf_firmware_len = ar->testmode.utf->size;
+
+ return 0;
+}
+
+static int ath10k_tm_fetch_firmware(struct ath10k *ar)
+{
+ int ret;
+
+ ret = ath10k_tm_fetch_utf_firmware_api_2(ar);
+ if (ret == 0) {
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
+ return 0;
+ }
+
+ ret = ath10k_tm_fetch_utf_firmware_api_1(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
+
+ return 0;
+}
+
+static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
+{
+ const char *ver;
+ int ret;
+
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
mutex_lock(&ar->conf_mutex);
@@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
goto err;
}
- snprintf(filename, sizeof(filename), "%s/%s",
- ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
-
- /* load utf firmware image */
- ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
+ ret = ath10k_tm_fetch_firmware(ar);
if (ret) {
- ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
- filename, ret);
+ ath10k_err(ar, "failed to fetch UTF firmware: %d", ret);
goto err;
}
spin_lock_bh(&ar->data_lock);
-
ar->testmode.utf_monitor = true;
-
spin_unlock_bh(&ar->data_lock);
-
BUILD_BUG_ON(sizeof(ar->fw_features) !=
sizeof(ar->testmode.orig_fw_features));
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
sizeof(ar->fw_features));
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
-
- /* utf.bin firmware image does not advertise firmware features. Do
- * an ugly hack where we force the firmware features so that wmi.c
- * will use the correct WMI interface.
- */
memset(ar->fw_features, 0, sizeof(ar->fw_features));
- ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
+
+ ar->wmi.op_version = ar->testmode.op_version;
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
+ ar->wmi.op_version);
ret = ath10k_hif_power_up(ar);
if (ret) {
@@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
ar->state = ATH10K_STATE_UTF;
- ath10k_info(ar, "UTF firmware started\n");
+ if (strlen(ar->testmode.utf_version) > 0)
+ ver = ar->testmode.utf_version;
+ else
+ ver = "API 1";
+
+ ath10k_info(ar, "UTF firmware %s started\n", ver);
mutex_unlock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c
index 1a899d70dc5d..60fe562e3041 100644
--- a/drivers/net/wireless/ath/ath10k/thermal.c
+++ b/drivers/net/wireless/ath/ath10k/thermal.c
@@ -215,6 +215,6 @@ err_cooling_destroy:
void ath10k_thermal_unregister(struct ath10k *ar)
{
- thermal_cooling_device_unregister(ar->thermal.cdev);
sysfs_remove_link(&ar->dev->kobj, "cooling_device");
+ thermal_cooling_device_unregister(ar->thermal.cdev);
}
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index e4a9c4c8d0cb..6d1105ab4592 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -52,6 +52,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ieee80211_tx_info *info;
struct ath10k_skb_cb *skb_cb;
struct sk_buff *msdu;
+ struct ieee80211_hdr *hdr;
+ __le16 fc;
+ bool limit_mgmt_desc = false;
ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx completion msdu_id %u discard %d no_ack %d success %d\n",
@@ -72,21 +75,23 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
spin_unlock_bh(&htt->tx_lock);
return;
}
+
+ hdr = (struct ieee80211_hdr *)msdu->data;
+ fc = hdr->frame_control;
+
+ if (unlikely(ieee80211_is_mgmt(fc)) &&
+ ar->hw_params.max_probe_resp_desc_thres)
+ limit_mgmt_desc = true;
+
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
- __ath10k_htt_tx_dec_pending(htt);
+ __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
if (htt->num_pending_tx == 0)
wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock);
skb_cb = ATH10K_SKB_CB(msdu);
-
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
- if (skb_cb->htt.txbuf)
- dma_pool_free(htt->tx_pool,
- skb_cb->htt.txbuf,
- skb_cb->htt.txbuf_paddr);
-
ath10k_report_offchan_tx(htt->ar, msdu);
info = IEEE80211_SKB_CB(msdu);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 248ffc3d6620..8f4f6a892581 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -177,6 +177,15 @@ struct wmi_ops {
const struct wmi_tdls_peer_capab_arg *cap,
const struct wmi_channel_arg *chan);
struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable);
+ struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar,
+ u32 param);
+ void (*fw_stats_fill)(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf);
+ struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar,
+ u8 enable,
+ u32 detect_level,
+ u32 detect_margin);
};
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
@@ -1270,4 +1279,52 @@ ath10k_wmi_adaptive_qcs(struct ath10k *ar, bool enable)
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->adaptive_qcs_cmdid);
}
+static inline int
+ath10k_wmi_pdev_get_tpc_config(struct ath10k *ar, u32 param)
+{
+ struct sk_buff *skb;
+
+ if (!ar->wmi.ops->gen_pdev_get_tpc_config)
+ return -EOPNOTSUPP;
+
+ skb = ar->wmi.ops->gen_pdev_get_tpc_config(ar, param);
+
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ return ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->pdev_get_tpc_config_cmdid);
+}
+
+static inline int
+ath10k_wmi_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats,
+ char *buf)
+{
+ if (!ar->wmi.ops->fw_stats_fill)
+ return -EOPNOTSUPP;
+
+ ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf);
+ return 0;
+}
+
+static inline int
+ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
+ u32 detect_level, u32 detect_margin)
+{
+ struct sk_buff *skb;
+
+ if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca)
+ return -EOPNOTSUPP;
+
+ skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable,
+ detect_level,
+ detect_margin);
+
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ return ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
+}
+
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index b5849b3fd2f0..6fbd17b69469 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -23,6 +23,7 @@
#include "wmi-ops.h"
#include "wmi-tlv.h"
#include "p2p.h"
+#include "testmode.h"
/***************/
/* TLV helpers */
@@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_tlv_event_id id;
+ bool consumed;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
+ consumed = ath10k_tm_event_wmi(ar, id, skb);
+
+ /* Ready event must be handled normally also in UTF mode so that we
+ * know the UTF firmware has booted, others we are just bypass WMI
+ * events to testmode.
+ */
+ if (consumed && id != WMI_TLV_READY_EVENTID) {
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi tlv testmode consumed 0x%x\n", id);
+ goto out;
+ }
+
switch (id) {
case WMI_TLV_MGMT_RX_EVENTID:
ath10k_wmi_event_mgmt_rx(ar, skb);
@@ -3468,6 +3482,7 @@ static const struct wmi_ops wmi_tlv_ops = {
.gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
+ .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
};
/************/
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ce01107ef37a..7569db0f69b5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map = {
.gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
.gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
+ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
@@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
.gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
.gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
+ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
@@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
.pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
+ .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS,
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
@@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
+ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
@@ -2475,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src,
dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
}
+static void
+ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src,
+ struct ath10k_fw_stats_pdev *dst)
+{
+ dst->comp_queued = __le32_to_cpu(src->comp_queued);
+ dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
+ dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
+ dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
+ dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
+ dst->local_enqued = __le32_to_cpu(src->local_enqued);
+ dst->local_freed = __le32_to_cpu(src->local_freed);
+ dst->hw_queued = __le32_to_cpu(src->hw_queued);
+ dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
+ dst->underrun = __le32_to_cpu(src->underrun);
+ dst->tx_abort = __le32_to_cpu(src->tx_abort);
+ dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
+ dst->tx_ko = __le32_to_cpu(src->tx_ko);
+ dst->data_rc = __le32_to_cpu(src->data_rc);
+ dst->self_triggers = __le32_to_cpu(src->self_triggers);
+ dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
+ dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
+ dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
+ dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
+ dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
+ dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
+ dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
+ dst->hw_paused = __le32_to_cpu(src->hw_paused);
+ dst->seq_posted = __le32_to_cpu(src->seq_posted);
+ dst->seq_failed_queueing =
+ __le32_to_cpu(src->seq_failed_queueing);
+ dst->seq_completed = __le32_to_cpu(src->seq_completed);
+ dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
+ dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
+ dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
+ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
+ dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
+ dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
+ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
+ dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
+}
+
void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
struct ath10k_fw_stats_pdev *dst)
{
@@ -2785,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
return 0;
}
+static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
+ struct sk_buff *skb,
+ struct ath10k_fw_stats *stats)
+{
+ const struct wmi_10_2_stats_event *ev = (void *)skb->data;
+ u32 num_pdev_stats;
+ u32 num_pdev_ext_stats;
+ u32 num_vdev_stats;
+ u32 num_peer_stats;
+ int i;
+
+ if (!skb_pull(skb, sizeof(*ev)))
+ return -EPROTO;
+
+ num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
+ num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
+ num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
+ num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+
+ for (i = 0; i < num_pdev_stats; i++) {
+ const struct wmi_10_4_pdev_stats *src;
+ struct ath10k_fw_stats_pdev *dst;
+
+ src = (void *)skb->data;
+ if (!skb_pull(skb, sizeof(*src)))
+ return -EPROTO;
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
+ ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst);
+ ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
+ dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
+ ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
+
+ list_add_tail(&dst->list, &stats->pdevs);
+ }
+
+ for (i = 0; i < num_pdev_ext_stats; i++) {
+ const struct wmi_10_2_pdev_ext_stats *src;
+
+ src = (void *)skb->data;
+ if (!skb_pull(skb, sizeof(*src)))
+ return -EPROTO;
+
+ /* FIXME: expose values to userspace
+ *
+ * Note: Even though this loop seems to do nothing it is
+ * required to parse following sub-structures properly.
+ */
+ }
+
+ /* fw doesn't implement vdev stats */
+
+ for (i = 0; i < num_peer_stats; i++) {
+ const struct wmi_10_4_peer_stats *src;
+ struct ath10k_fw_stats_peer *dst;
+
+ src = (void *)skb->data;
+ if (!skb_pull(skb, sizeof(*src)))
+ return -EPROTO;
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
+ dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
+ dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
+ dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
+ /* FIXME: expose 10.4 specific values */
+
+ list_add_tail(&dst->list, &stats->peers);
+ }
+
+ return 0;
+}
+
void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
@@ -3018,8 +3143,6 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
memcpy(skb_put(bcn, arvif->u.ap.noa_len),
arvif->u.ap.noa_data,
arvif->u.ap.noa_len);
-
- return;
}
static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
@@ -3507,7 +3630,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
tsf);
if (res < 0) {
ath10k_dbg(ar, ATH10K_DBG_WMI, "failed to process fft report: %d\n",
- res);
+ res);
return;
}
break;
@@ -3835,9 +3958,258 @@ void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n");
}
+static u8 ath10k_tpc_config_get_rate(struct ath10k *ar,
+ struct wmi_pdev_tpc_config_event *ev,
+ u32 rate_idx, u32 num_chains,
+ u32 rate_code, u8 type)
+{
+ u8 tpc, num_streams, preamble, ch, stm_idx;
+
+ num_streams = ATH10K_HW_NSS(rate_code);
+ preamble = ATH10K_HW_PREAMBLE(rate_code);
+ ch = num_chains - 1;
+
+ tpc = min_t(u8, ev->rates_array[rate_idx], ev->max_reg_allow_pow[ch]);
+
+ if (__le32_to_cpu(ev->num_tx_chain) <= 1)
+ goto out;
+
+ if (preamble == WMI_RATE_PREAMBLE_CCK)
+ goto out;
+
+ stm_idx = num_streams - 1;
+ if (num_chains <= num_streams)
+ goto out;
+
+ switch (type) {
+ case WMI_TPC_TABLE_TYPE_STBC:
+ tpc = min_t(u8, tpc,
+ ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx]);
+ break;
+ case WMI_TPC_TABLE_TYPE_TXBF:
+ tpc = min_t(u8, tpc,
+ ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx]);
+ break;
+ case WMI_TPC_TABLE_TYPE_CDD:
+ tpc = min_t(u8, tpc,
+ ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx]);
+ break;
+ default:
+ ath10k_warn(ar, "unknown wmi tpc table type: %d\n", type);
+ tpc = 0;
+ break;
+ }
+
+out:
+ return tpc;
+}
+
+static void ath10k_tpc_config_disp_tables(struct ath10k *ar,
+ struct wmi_pdev_tpc_config_event *ev,
+ struct ath10k_tpc_stats *tpc_stats,
+ u8 *rate_code, u16 *pream_table, u8 type)
+{
+ u32 i, j, pream_idx, flags;
+ u8 tpc[WMI_TPC_TX_N_CHAIN];
+ char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
+ char buff[WMI_TPC_BUF_SIZE];
+
+ flags = __le32_to_cpu(ev->flags);
+
+ switch (type) {
+ case WMI_TPC_TABLE_TYPE_CDD:
+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) {
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n");
+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
+ return;
+ }
+ break;
+ case WMI_TPC_TABLE_TYPE_STBC:
+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) {
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n");
+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
+ return;
+ }
+ break;
+ case WMI_TPC_TABLE_TYPE_TXBF:
+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) {
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n");
+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
+ return;
+ }
+ break;
+ default:
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "invalid table type in wmi tpc event: %d\n", type);
+ return;
+ }
+
+ pream_idx = 0;
+ for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
+ memset(tpc_value, 0, sizeof(tpc_value));
+ memset(buff, 0, sizeof(buff));
+ if (i == pream_table[pream_idx])
+ pream_idx++;
+
+ for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
+ if (j >= __le32_to_cpu(ev->num_tx_chain))
+ break;
+
+ tpc[j] = ath10k_tpc_config_get_rate(ar, ev, i, j + 1,
+ rate_code[i],
+ type);
+ snprintf(buff, sizeof(buff), "%8d ", tpc[j]);
+ strncat(tpc_value, buff, strlen(buff));
+ }
+ tpc_stats->tpc_table[type].pream_idx[i] = pream_idx;
+ tpc_stats->tpc_table[type].rate_code[i] = rate_code[i];
+ memcpy(tpc_stats->tpc_table[type].tpc_value[i],
+ tpc_value, sizeof(tpc_value));
+ }
+}
+
void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
{
- ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n");
+ u32 i, j, pream_idx, num_tx_chain;
+ u8 rate_code[WMI_TPC_RATE_MAX], rate_idx;
+ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
+ struct wmi_pdev_tpc_config_event *ev;
+ struct ath10k_tpc_stats *tpc_stats;
+
+ ev = (struct wmi_pdev_tpc_config_event *)skb->data;
+
+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
+ if (!tpc_stats)
+ return;
+
+ /* Create the rate code table based on the chains supported */
+ rate_idx = 0;
+ pream_idx = 0;
+
+ /* Fill CCK rate code */
+ for (i = 0; i < 4; i++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_CCK);
+ rate_idx++;
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ /* Fill OFDM rate code */
+ for (i = 0; i < 8; i++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_OFDM);
+ rate_idx++;
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
+
+ /* Fill HT20 rate code */
+ for (i = 0; i < num_tx_chain; i++) {
+ for (j = 0; j < 8; j++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT);
+ rate_idx++;
+ }
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ /* Fill HT40 rate code */
+ for (i = 0; i < num_tx_chain; i++) {
+ for (j = 0; j < 8; j++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT);
+ rate_idx++;
+ }
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ /* Fill VHT20 rate code */
+ for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) {
+ for (j = 0; j < 10; j++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
+ rate_idx++;
+ }
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ /* Fill VHT40 rate code */
+ for (i = 0; i < num_tx_chain; i++) {
+ for (j = 0; j < 10; j++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
+ rate_idx++;
+ }
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ /* Fill VHT80 rate code */
+ for (i = 0; i < num_tx_chain; i++) {
+ for (j = 0; j < 10; j++) {
+ rate_code[rate_idx] =
+ ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
+ rate_idx++;
+ }
+ }
+ pream_table[pream_idx] = rate_idx;
+ pream_idx++;
+
+ rate_code[rate_idx++] =
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK);
+ rate_code[rate_idx++] =
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
+ rate_code[rate_idx++] =
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK);
+ rate_code[rate_idx++] =
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
+ rate_code[rate_idx++] =
+ ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
+
+ pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END;
+
+ tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
+ tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
+ tpc_stats->ctl = __le32_to_cpu(ev->ctl);
+ tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain);
+ tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain);
+ tpc_stats->twice_antenna_reduction =
+ __le32_to_cpu(ev->twice_antenna_reduction);
+ tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
+ tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
+ tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
+ tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
+
+ ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
+ rate_code, pream_table,
+ WMI_TPC_TABLE_TYPE_CDD);
+ ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
+ rate_code, pream_table,
+ WMI_TPC_TABLE_TYPE_STBC);
+ ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
+ rate_code, pream_table,
+ WMI_TPC_TABLE_TYPE_TXBF);
+
+ ath10k_debug_tpc_stats_process(ar, tpc_stats);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi event tpc config channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n",
+ __le32_to_cpu(ev->chan_freq),
+ __le32_to_cpu(ev->phy_mode),
+ __le32_to_cpu(ev->ctl),
+ __le32_to_cpu(ev->reg_domain),
+ a_sle32_to_cpu(ev->twice_antenna_gain),
+ __le32_to_cpu(ev->twice_antenna_reduction),
+ __le32_to_cpu(ev->power_limit),
+ __le32_to_cpu(ev->twice_max_rd_power) / 2,
+ __le32_to_cpu(ev->num_tx_chain),
+ __le32_to_cpu(ev->rate_max));
}
void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
@@ -3917,6 +4289,53 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
return 0;
}
+static bool
+ath10k_wmi_is_host_mem_allocated(struct ath10k *ar,
+ const struct wlan_host_mem_req **mem_reqs,
+ u32 num_mem_reqs)
+{
+ u32 req_id, num_units, unit_size, num_unit_info;
+ u32 pool_size;
+ int i, j;
+ bool found;
+
+ if (ar->wmi.num_mem_chunks != num_mem_reqs)
+ return false;
+
+ for (i = 0; i < num_mem_reqs; ++i) {
+ req_id = __le32_to_cpu(mem_reqs[i]->req_id);
+ num_units = __le32_to_cpu(mem_reqs[i]->num_units);
+ unit_size = __le32_to_cpu(mem_reqs[i]->unit_size);
+ num_unit_info = __le32_to_cpu(mem_reqs[i]->num_unit_info);
+
+ if (num_unit_info & NUM_UNITS_IS_NUM_ACTIVE_PEERS) {
+ if (ar->num_active_peers)
+ num_units = ar->num_active_peers + 1;
+ else
+ num_units = ar->max_num_peers + 1;
+ } else if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) {
+ num_units = ar->max_num_peers + 1;
+ } else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) {
+ num_units = ar->max_num_vdevs + 1;
+ }
+
+ found = false;
+ for (j = 0; j < ar->wmi.num_mem_chunks; j++) {
+ if (ar->wmi.mem_chunks[j].req_id == req_id) {
+ pool_size = num_units * round_up(unit_size, 4);
+ if (ar->wmi.mem_chunks[j].len == pool_size) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found)
+ return false;
+ }
+
+ return true;
+}
+
static int
ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg)
@@ -3997,6 +4416,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
struct wmi_svc_rdy_ev_arg arg = {};
u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
int ret;
+ bool allocated;
if (!skb) {
ath10k_warn(ar, "invalid service ready event skb\n");
@@ -4040,8 +4460,10 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
ar->num_rf_chains = ar->max_spatial_stream;
}
- ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
- ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
+ if (!ar->cfg_tx_chainmask) {
+ ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1;
+ ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1;
+ }
if (strlen(ar->hw->wiphy->fw_version) == 0) {
snprintf(ar->hw->wiphy->fw_version,
@@ -4073,6 +4495,18 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
* and WMI_SERVICE_IRAM_TIDS, etc.
*/
+ allocated = ath10k_wmi_is_host_mem_allocated(ar, arg.mem_reqs,
+ num_mem_reqs);
+ if (allocated)
+ goto skip_mem_alloc;
+
+ /* Either this event is received during boot time or there is a change
+ * in memory requirement from firmware when compared to last request.
+ * Free any old memory and do a fresh allocation based on the current
+ * memory requirement.
+ */
+ ath10k_wmi_free_host_mem(ar);
+
for (i = 0; i < num_mem_reqs; ++i) {
req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
@@ -4108,6 +4542,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
return;
}
+skip_mem_alloc:
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
__le32_to_cpu(arg.min_tx_power),
@@ -4623,6 +5058,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI,
"received event id %d not implemented\n", id);
break;
+ case WMI_10_4_UPDATE_STATS_EVENTID:
+ ath10k_wmi_event_update_stats(ar, skb);
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
@@ -5029,7 +5467,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
config.rx_timeout_pri[2] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI);
config.rx_timeout_pri[3] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_HI_PRI);
- config.rx_decap_mode = __cpu_to_le32(TARGET_10_4_RX_DECAP_MODE);
+ config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
config.scan_max_pending_req = __cpu_to_le32(TARGET_10_4_SCAN_MAX_REQS);
config.bmiss_offload_max_vdev =
__cpu_to_le32(TARGET_10_4_BMISS_OFFLOAD_MAX_VDEV);
@@ -6295,6 +6733,505 @@ ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
return skb;
}
+static struct sk_buff *
+ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param)
+{
+ struct wmi_pdev_get_tpc_config_cmd *cmd;
+ struct sk_buff *skb;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ cmd = (struct wmi_pdev_get_tpc_config_cmd *)skb->data;
+ cmd->param = __cpu_to_le32(param);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi pdev get tcp config param:%d\n", param);
+ return skb;
+}
+
+size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head)
+{
+ struct ath10k_fw_stats_peer *i;
+ size_t num = 0;
+
+ list_for_each_entry(i, head, list)
+ ++num;
+
+ return num;
+}
+
+size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head)
+{
+ struct ath10k_fw_stats_vdev *i;
+ size_t num = 0;
+
+ list_for_each_entry(i, head, list)
+ ++num;
+
+ return num;
+}
+
+static void
+ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s\n",
+ "ath10k PDEV stats");
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Channel noise floor", pdev->ch_noise_floor);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "Channel TX power", pdev->chan_tx_power);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "TX frame count", pdev->tx_frame_count);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "RX frame count", pdev->rx_frame_count);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "RX clear count", pdev->rx_clear_count);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "Cycle count", pdev->cycle_count);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "PHY error count", pdev->phy_err_count);
+
+ *length = len;
+}
+
+static void
+ath10k_wmi_fw_pdev_extra_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "RTS bad count", pdev->rts_bad);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "RTS good count", pdev->rts_good);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "FCS bad count", pdev->fcs_bad);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "No beacon count", pdev->no_beacons);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
+ "MIB int count", pdev->mib_int_count);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ *length = len;
+}
+
+static void
+ath10k_wmi_fw_pdev_tx_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+
+ len += scnprintf(buf + len, buf_len - len, "\n%30s\n",
+ "ath10k PDEV TX stats");
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "HTT cookies queued", pdev->comp_queued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "HTT cookies disp.", pdev->comp_delivered);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MSDU queued", pdev->msdu_enqued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDU queued", pdev->mpdu_enqued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MSDUs dropped", pdev->wmm_drop);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Local enqued", pdev->local_enqued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Local freed", pdev->local_freed);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "HW queued", pdev->hw_queued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "PPDUs reaped", pdev->hw_reaped);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Num underruns", pdev->underrun);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "PPDUs cleaned", pdev->tx_abort);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs requed", pdev->mpdus_requed);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Excessive retries", pdev->tx_ko);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "HW rate", pdev->data_rc);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Sched self tiggers", pdev->self_triggers);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Dropped due to SW retries",
+ pdev->sw_retry_failure);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Illegal rate phy errors",
+ pdev->illgl_rate_phy_err);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Pdev continuous xretry", pdev->pdev_cont_xretry);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "TX timeout", pdev->pdev_tx_timeout);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "PDEV resets", pdev->pdev_resets);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "PHY underrun", pdev->phy_underrun);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDU is more than txop limit", pdev->txop_ovf);
+ *length = len;
+}
+
+static void
+ath10k_wmi_fw_pdev_rx_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+
+ len += scnprintf(buf + len, buf_len - len, "\n%30s\n",
+ "ath10k PDEV RX stats");
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Mid PPDU route change",
+ pdev->mid_ppdu_route_change);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Tot. number of statuses", pdev->status_rcvd);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Extra frags on rings 0", pdev->r0_frags);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Extra frags on rings 1", pdev->r1_frags);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Extra frags on rings 2", pdev->r2_frags);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Extra frags on rings 3", pdev->r3_frags);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MSDUs delivered to HTT", pdev->htt_msdus);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs delivered to HTT", pdev->htt_mpdus);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MSDUs delivered to stack", pdev->loc_msdus);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs delivered to stack", pdev->loc_mpdus);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Oversized AMSUs", pdev->oversize_amsdu);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "PHY errors", pdev->phy_errs);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "PHY errors drops", pdev->phy_err_drop);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
+ *length = len;
+}
+
+static void
+ath10k_wmi_fw_vdev_stats_fill(const struct ath10k_fw_stats_vdev *vdev,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+ int i;
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "vdev id", vdev->vdev_id);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "beacon snr", vdev->beacon_snr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "data snr", vdev->data_snr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx frames", vdev->num_rx_frames);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rts fail", vdev->num_rts_fail);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rts success", vdev->num_rts_success);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx err", vdev->num_rx_err);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx discard", vdev->num_rx_discard);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num tx not acked", vdev->num_tx_not_acked);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames", i,
+ vdev->num_tx_frames[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames retries", i,
+ vdev->num_tx_frames_retries[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames failures", i,
+ vdev->num_tx_frames_failures[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] 0x%08x\n",
+ "tx rate history", i,
+ vdev->tx_rate_history[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "beacon rssi history", i,
+ vdev->beacon_rssi_history[i]);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ *length = len;
+}
+
+static void
+ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
+ "Peer MAC address", peer->peer_macaddr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "Peer RSSI", peer->peer_rssi);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "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, "\n");
+ *length = len;
+}
+
+void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf)
+{
+ u32 len = 0;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+ const struct ath10k_fw_stats_pdev *pdev;
+ const struct ath10k_fw_stats_vdev *vdev;
+ const struct ath10k_fw_stats_peer *peer;
+ size_t num_peers;
+ size_t num_vdevs;
+
+ spin_lock_bh(&ar->data_lock);
+
+ pdev = list_first_entry_or_null(&fw_stats->pdevs,
+ struct ath10k_fw_stats_pdev, list);
+ if (!pdev) {
+ ath10k_warn(ar, "failed to get pdev stats\n");
+ goto unlock;
+ }
+
+ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+
+ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k VDEV stats", num_vdevs);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
+ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k PEER stats", num_peers);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(peer, &fw_stats->peers, list) {
+ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
+ }
+
+unlock:
+ spin_unlock_bh(&ar->data_lock);
+
+ if (len >= buf_len)
+ buf[len - 1] = 0;
+ else
+ buf[len] = 0;
+}
+
+void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf)
+{
+ unsigned int len = 0;
+ unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
+ const struct ath10k_fw_stats_pdev *pdev;
+ const struct ath10k_fw_stats_vdev *vdev;
+ const struct ath10k_fw_stats_peer *peer;
+ size_t num_peers;
+ size_t num_vdevs;
+
+ spin_lock_bh(&ar->data_lock);
+
+ pdev = list_first_entry_or_null(&fw_stats->pdevs,
+ struct ath10k_fw_stats_pdev, list);
+ if (!pdev) {
+ ath10k_warn(ar, "failed to get pdev stats\n");
+ goto unlock;
+ }
+
+ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+
+ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k VDEV stats", num_vdevs);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
+ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k PEER stats", num_peers);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(peer, &fw_stats->peers, list) {
+ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
+ }
+
+unlock:
+ spin_unlock_bh(&ar->data_lock);
+
+ if (len >= buf_len)
+ buf[len - 1] = 0;
+ else
+ buf[len] = 0;
+}
+
+static struct sk_buff *
+ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
+ u32 detect_level, u32 detect_margin)
+{
+ struct wmi_pdev_set_adaptive_cca_params *cmd;
+ struct sk_buff *skb;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data;
+ cmd->enable = __cpu_to_le32(enable);
+ cmd->cca_detect_level = __cpu_to_le32(detect_level);
+ cmd->cca_detect_margin = __cpu_to_le32(detect_margin);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n",
+ enable, detect_level, detect_margin);
+ return skb;
+}
+
+void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf)
+{
+ u32 len = 0;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+ const struct ath10k_fw_stats_pdev *pdev;
+ const struct ath10k_fw_stats_vdev *vdev;
+ const struct ath10k_fw_stats_peer *peer;
+ size_t num_peers;
+ size_t num_vdevs;
+
+ spin_lock_bh(&ar->data_lock);
+
+ pdev = list_first_entry_or_null(&fw_stats->pdevs,
+ struct ath10k_fw_stats_pdev, list);
+ if (!pdev) {
+ ath10k_warn(ar, "failed to get pdev stats\n");
+ goto unlock;
+ }
+
+ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+
+ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
+ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "HW paused", pdev->hw_paused);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Seqs posted", pdev->seq_posted);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Seqs failed queueing", pdev->seq_failed_queueing);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Seqs completed", pdev->seq_completed);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Seqs restarted", pdev->seq_restarted);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MU Seqs posted", pdev->mu_seq_posted);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs SW flushed", pdev->mpdus_sw_flush);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs HW filtered", pdev->mpdus_hw_filter);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs truncated", pdev->mpdus_truncated);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs receive no ACK", pdev->mpdus_ack_failed);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "MPDUs expired", pdev->mpdus_expired);
+
+ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
+ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
+ "Num Rx Overflow errors", pdev->rx_ovfl_errs);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k VDEV stats", num_vdevs);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
+ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k PEER stats", num_peers);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(peer, &fw_stats->peers, list) {
+ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
+ }
+
+unlock:
+ spin_unlock_bh(&ar->data_lock);
+
+ if (len >= buf_len)
+ buf[len - 1] = 0;
+ else
+ buf[len] = 0;
+}
+
static const struct wmi_ops wmi_ops = {
.rx = ath10k_wmi_op_rx,
.map_svc = wmi_main_svc_map,
@@ -6353,10 +7290,12 @@ static const struct wmi_ops wmi_ops = {
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
/* .gen_bcn_tmpl not implemented */
/* .gen_prb_tmpl not implemented */
/* .gen_p2p_go_bcn_ie not implemented */
/* .gen_adaptive_qcs not implemented */
+ /* .gen_pdev_enable_adaptive_cca not implemented */
};
static const struct wmi_ops wmi_10_1_ops = {
@@ -6418,10 +7357,12 @@ static const struct wmi_ops wmi_10_1_ops = {
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
/* .gen_bcn_tmpl not implemented */
/* .gen_prb_tmpl not implemented */
/* .gen_p2p_go_bcn_ie not implemented */
/* .gen_adaptive_qcs not implemented */
+ /* .gen_pdev_enable_adaptive_cca not implemented */
};
static const struct wmi_ops wmi_10_2_ops = {
@@ -6484,6 +7425,8 @@ static const struct wmi_ops wmi_10_2_ops = {
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
+ /* .gen_pdev_enable_adaptive_cca not implemented */
};
static const struct wmi_ops wmi_10_2_4_ops = {
@@ -6545,6 +7488,10 @@ static const struct wmi_ops wmi_10_2_4_ops = {
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
+ .gen_pdev_enable_adaptive_cca =
+ ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
/* .gen_bcn_tmpl not implemented */
/* .gen_prb_tmpl not implemented */
/* .gen_p2p_go_bcn_ie not implemented */
@@ -6555,6 +7502,7 @@ static const struct wmi_ops wmi_10_4_ops = {
.rx = ath10k_wmi_10_4_op_rx,
.map_svc = wmi_10_4_svc_map,
+ .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
.pull_scan = ath10k_wmi_op_pull_scan_ev,
.pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
.pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
@@ -6604,9 +7552,11 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
/* shared with 10.2 */
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
+ .gen_request_stats = ath10k_wmi_op_gen_request_stats,
};
int ath10k_wmi_attach(struct ath10k *ar)
@@ -6660,15 +7610,10 @@ int ath10k_wmi_attach(struct ath10k *ar)
return 0;
}
-void ath10k_wmi_detach(struct ath10k *ar)
+void ath10k_wmi_free_host_mem(struct ath10k *ar)
{
int i;
- cancel_work_sync(&ar->svc_rdy_work);
-
- if (ar->svc_rdy_skb)
- dev_kfree_skb(ar->svc_rdy_skb);
-
/* free the host memory chunks requested by firmware */
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
dma_free_coherent(ar->dev,
@@ -6679,3 +7624,11 @@ void ath10k_wmi_detach(struct ath10k *ar)
ar->wmi.num_mem_chunks = 0;
}
+
+void ath10k_wmi_detach(struct ath10k *ar)
+{
+ cancel_work_sync(&ar->svc_rdy_work);
+
+ if (ar->svc_rdy_skb)
+ dev_kfree_skb(ar->svc_rdy_skb);
+}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 52d35032d53e..72a4ef709577 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -73,6 +73,25 @@ struct wmi_cmd_hdr {
#define HTC_PROTOCOL_VERSION 0x0002
#define WMI_PROTOCOL_VERSION 0x0002
+/*
+ * There is no signed version of __le32, so for a temporary solution come
+ * up with our own version. The idea is from fs/ntfs/types.h.
+ *
+ * Use a_ prefix so that it doesn't conflict if we get proper support to
+ * linux/types.h.
+ */
+typedef __s32 __bitwise a_sle32;
+
+static inline a_sle32 a_cpu_to_sle32(s32 val)
+{
+ return (__force a_sle32)cpu_to_le32(val);
+}
+
+static inline s32 a_sle32_to_cpu(a_sle32 val)
+{
+ return le32_to_cpu((__force __le32)val);
+}
+
enum wmi_service {
WMI_SERVICE_BEACON_OFFLOAD = 0,
WMI_SERVICE_SCAN_OFFLOAD,
@@ -753,6 +772,7 @@ struct wmi_cmd_map {
u32 mu_cal_start_cmdid;
u32 set_cca_params_cmdid;
u32 pdev_bss_chan_info_request_cmdid;
+ u32 pdev_enable_adaptive_cca_cmdid;
};
/*
@@ -1362,6 +1382,9 @@ enum wmi_10_2_cmd_id {
WMI_10_2_VDEV_ATF_REQUEST_CMDID,
WMI_10_2_PEER_ATF_REQUEST_CMDID,
WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
+ WMI_10_2_MU_CAL_START_CMDID,
+ WMI_10_2_SET_LTEU_CONFIG_CMDID,
+ WMI_10_2_SET_CCA_PARAMS,
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
};
@@ -3642,8 +3665,18 @@ struct wmi_pdev_get_tpc_config_cmd {
__le32 param;
} __packed;
+#define WMI_TPC_CONFIG_PARAM 1
#define WMI_TPC_RATE_MAX 160
#define WMI_TPC_TX_N_CHAIN 4
+#define WMI_TPC_PREAM_TABLE_MAX 10
+#define WMI_TPC_FLAG 3
+#define WMI_TPC_BUF_SIZE 10
+
+enum wmi_tpc_table_type {
+ WMI_TPC_TABLE_TYPE_CDD = 0,
+ WMI_TPC_TABLE_TYPE_STBC = 1,
+ WMI_TPC_TABLE_TYPE_TXBF = 2,
+};
enum wmi_tpc_config_event_flag {
WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD = 0x1,
@@ -3657,7 +3690,7 @@ struct wmi_pdev_tpc_config_event {
__le32 phy_mode;
__le32 twice_antenna_reduction;
__le32 twice_max_rd_power;
- s32 twice_antenna_gain;
+ a_sle32 twice_antenna_gain;
__le32 power_limit;
__le32 rate_max;
__le32 num_tx_chain;
@@ -3833,6 +3866,111 @@ struct wmi_pdev_stats_tx {
__le32 txop_ovf;
} __packed;
+struct wmi_10_4_pdev_stats_tx {
+ /* Num HTT cookies queued to dispatch list */
+ __le32 comp_queued;
+
+ /* Num HTT cookies dispatched */
+ __le32 comp_delivered;
+
+ /* Num MSDU queued to WAL */
+ __le32 msdu_enqued;
+
+ /* Num MPDU queue to WAL */
+ __le32 mpdu_enqued;
+
+ /* Num MSDUs dropped by WMM limit */
+ __le32 wmm_drop;
+
+ /* Num Local frames queued */
+ __le32 local_enqued;
+
+ /* Num Local frames done */
+ __le32 local_freed;
+
+ /* Num queued to HW */
+ __le32 hw_queued;
+
+ /* Num PPDU reaped from HW */
+ __le32 hw_reaped;
+
+ /* Num underruns */
+ __le32 underrun;
+
+ /* HW Paused. */
+ __le32 hw_paused;
+
+ /* Num PPDUs cleaned up in TX abort */
+ __le32 tx_abort;
+
+ /* Num MPDUs requed by SW */
+ __le32 mpdus_requed;
+
+ /* excessive retries */
+ __le32 tx_ko;
+
+ /* data hw rate code */
+ __le32 data_rc;
+
+ /* Scheduler self triggers */
+ __le32 self_triggers;
+
+ /* frames dropped due to excessive sw retries */
+ __le32 sw_retry_failure;
+
+ /* illegal rate phy errors */
+ __le32 illgl_rate_phy_err;
+
+ /* wal pdev continuous xretry */
+ __le32 pdev_cont_xretry;
+
+ /* wal pdev tx timeouts */
+ __le32 pdev_tx_timeout;
+
+ /* wal pdev resets */
+ __le32 pdev_resets;
+
+ /* frames dropped due to non-availability of stateless TIDs */
+ __le32 stateless_tid_alloc_failure;
+
+ __le32 phy_underrun;
+
+ /* MPDU is more than txop limit */
+ __le32 txop_ovf;
+
+ /* Number of Sequences posted */
+ __le32 seq_posted;
+
+ /* Number of Sequences failed queueing */
+ __le32 seq_failed_queueing;
+
+ /* Number of Sequences completed */
+ __le32 seq_completed;
+
+ /* Number of Sequences restarted */
+ __le32 seq_restarted;
+
+ /* Number of MU Sequences posted */
+ __le32 mu_seq_posted;
+
+ /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
+ __le32 mpdus_sw_flush;
+
+ /* Num MPDUs filtered by HW, all filter condition (TTL expired) */
+ __le32 mpdus_hw_filter;
+
+ /* Num MPDUs truncated by PDG
+ * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
+ */
+ __le32 mpdus_truncated;
+
+ /* Num MPDUs that was tried but didn't receive ACK or BA */
+ __le32 mpdus_ack_failed;
+
+ /* Num MPDUs that was dropped due to expiry. */
+ __le32 mpdus_expired;
+} __packed;
+
struct wmi_pdev_stats_rx {
/* Cnts any change in ring routing mid-ppdu */
__le32 mid_ppdu_route_change;
@@ -4006,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
struct wmi_pdev_stats_extra extra;
} __packed;
+struct wmi_10_4_pdev_stats {
+ struct wmi_pdev_stats_base base;
+ struct wmi_10_4_pdev_stats_tx tx;
+ struct wmi_pdev_stats_rx rx;
+ __le32 rx_ovfl_errs;
+ struct wmi_pdev_stats_mem mem;
+ __le32 sram_free_size;
+ struct wmi_pdev_stats_extra extra;
+} __packed;
+
/*
* VDEV statistics
* TODO: add all VDEV stats here
@@ -4047,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
__le32 unknown_value; /* FIXME: what is this word? */
} __packed;
+struct wmi_10_4_peer_stats {
+ struct wmi_mac_addr peer_macaddr;
+ __le32 peer_rssi;
+ __le32 peer_rssi_seq_num;
+ __le32 peer_tx_rate;
+ __le32 peer_rx_rate;
+ __le32 current_per;
+ __le32 retries;
+ __le32 tx_rate_count;
+ __le32 max_4ms_frame_len;
+ __le32 total_sub_frames;
+ __le32 tx_bytes;
+ __le32 num_pkt_loss_overflow[4];
+ __le32 num_pkt_loss_excess_retry[4];
+ __le32 peer_rssi_changed;
+} __packed;
+
struct wmi_10_2_pdev_ext_stats {
__le32 rx_rssi_comb;
__le32 rx_rssi[4];
@@ -4253,6 +4418,11 @@ enum wmi_rate_preamble {
WMI_RATE_PREAMBLE_VHT,
};
+#define ATH10K_HW_NSS(rate) (1 + (((rate) >> 4) & 0x3))
+#define ATH10K_HW_PREAMBLE(rate) (((rate) >> 6) & 0x3)
+#define ATH10K_HW_RATECODE(rate, nss, preamble) \
+ (((preamble) << 6) | ((nss) << 4) | (rate))
+
/* Value to disable fixed rate setting */
#define WMI_FIXED_RATE_NONE (0xff)
@@ -6060,13 +6230,24 @@ enum wmi_txbf_conf {
WMI_TXBF_CONF_AFTER_ASSOC,
};
+#define WMI_CCA_DETECT_LEVEL_AUTO 0
+#define WMI_CCA_DETECT_MARGIN_AUTO 0
+
+struct wmi_pdev_set_adaptive_cca_params {
+ __le32 enable;
+ __le32 cca_detect_level;
+ __le32 cca_detect_margin;
+} __packed;
+
struct ath10k;
struct ath10k_vif;
struct ath10k_fw_stats_pdev;
struct ath10k_fw_stats_peer;
+struct ath10k_fw_stats;
int ath10k_wmi_attach(struct ath10k *ar);
void ath10k_wmi_detach(struct ath10k *ar);
+void ath10k_wmi_free_host_mem(struct ath10k *ar);
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
@@ -6144,4 +6325,16 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, const void *phyerr_buf,
int left_len, struct wmi_phyerr_ev_arg *arg);
+void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf);
+void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf);
+size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
+size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
+void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf);
+
#endif /* _WMI_H_ */
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index fa6e89e5c421..ba12f7f4061d 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1367,7 +1367,7 @@ struct ath5k_hw {
u8 ah_retry_long;
u8 ah_retry_short;
- u32 ah_use_32khz_clock;
+ bool ah_use_32khz_clock;
u8 ah_coverage_class;
bool ah_ack_bitrate_high;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index a511ef3614b9..81ac8c59f0ec 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2217,7 +2217,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
/* enter / leave wow suspend on first vif always */
first_vif = ath6kl_vif_first(ar);
- if (WARN_ON(unlikely(!first_vif)) ||
+ if (WARN_ON(!first_vif) ||
!ath6kl_cfg80211_ready(first_vif))
return -EIO;
@@ -2297,7 +2297,7 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
int ret;
vif = ath6kl_vif_first(ar);
- if (WARN_ON(unlikely(!vif)) ||
+ if (WARN_ON(!vif) ||
!ath6kl_cfg80211_ready(vif))
return -EIO;
@@ -3231,6 +3231,15 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
wait, buf, len, no_cck);
}
+static int ath6kl_get_antenna(struct wiphy *wiphy,
+ u32 *tx_ant, u32 *rx_ant)
+{
+ struct ath6kl *ar = wiphy_priv(wiphy);
+ *tx_ant = ar->hw.tx_ant;
+ *rx_ant = ar->hw.rx_ant;
+ return 0;
+}
+
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
struct wireless_dev *wdev,
u16 frame_type, bool reg)
@@ -3312,7 +3321,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
}
/* fw uses seconds, also make sure that it's >0 */
- interval = max_t(u16, 1, request->interval / 1000);
+ interval = max_t(u16, 1, request->scan_plans[0].interval);
ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
interval, interval,
@@ -3447,6 +3456,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
.mgmt_tx = ath6kl_mgmt_tx,
.mgmt_frame_register = ath6kl_mgmt_frame_register,
+ .get_antenna = ath6kl_get_antenna,
.sched_scan_start = ath6kl_cfg80211_sscan_start,
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
@@ -3634,6 +3644,127 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
ar->num_vif--;
}
+static const char ath6kl_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
+ /* Common stats names used by many drivers. */
+ "tx_pkts_nic", "tx_bytes_nic", "rx_pkts_nic", "rx_bytes_nic",
+
+ /* TX stats. */
+ "d_tx_ucast_pkts", "d_tx_bcast_pkts",
+ "d_tx_ucast_bytes", "d_tx_bcast_bytes",
+ "d_tx_rts_ok", "d_tx_error", "d_tx_fail",
+ "d_tx_retry", "d_tx_multi_retry", "d_tx_rts_fail",
+ "d_tx_tkip_counter_measures",
+
+ /* RX Stats. */
+ "d_rx_ucast_pkts", "d_rx_ucast_rate", "d_rx_bcast_pkts",
+ "d_rx_ucast_bytes", "d_rx_bcast_bytes", "d_rx_frag_pkt",
+ "d_rx_error", "d_rx_crc_err", "d_rx_keycache_miss",
+ "d_rx_decrypt_crc_err", "d_rx_duplicate_frames",
+ "d_rx_mic_err", "d_rx_tkip_format_err", "d_rx_ccmp_format_err",
+ "d_rx_ccmp_replay_err",
+
+ /* Misc stats. */
+ "d_beacon_miss", "d_num_connects", "d_num_disconnects",
+ "d_beacon_avg_rssi", "d_arp_received", "d_arp_matched",
+ "d_arp_replied"
+};
+
+#define ATH6KL_STATS_LEN ARRAY_SIZE(ath6kl_gstrings_sta_stats)
+
+static int ath6kl_get_sset_count(struct net_device *dev, int sset)
+{
+ int rv = 0;
+
+ if (sset == ETH_SS_STATS)
+ rv += ATH6KL_STATS_LEN;
+
+ if (rv == 0)
+ return -EOPNOTSUPP;
+ return rv;
+}
+
+static void ath6kl_get_stats(struct net_device *dev,
+ struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct ath6kl_vif *vif = netdev_priv(dev);
+ struct ath6kl *ar = vif->ar;
+ int i = 0;
+ struct target_stats *tgt_stats;
+
+ memset(data, 0, sizeof(u64) * ATH6KL_STATS_LEN);
+
+ ath6kl_read_tgt_stats(ar, vif);
+
+ tgt_stats = &vif->target_stats;
+
+ data[i++] = tgt_stats->tx_ucast_pkt + tgt_stats->tx_bcast_pkt;
+ data[i++] = tgt_stats->tx_ucast_byte + tgt_stats->tx_bcast_byte;
+ data[i++] = tgt_stats->rx_ucast_pkt + tgt_stats->rx_bcast_pkt;
+ data[i++] = tgt_stats->rx_ucast_byte + tgt_stats->rx_bcast_byte;
+
+ data[i++] = tgt_stats->tx_ucast_pkt;
+ data[i++] = tgt_stats->tx_bcast_pkt;
+ data[i++] = tgt_stats->tx_ucast_byte;
+ data[i++] = tgt_stats->tx_bcast_byte;
+ data[i++] = tgt_stats->tx_rts_success_cnt;
+ data[i++] = tgt_stats->tx_err;
+ data[i++] = tgt_stats->tx_fail_cnt;
+ data[i++] = tgt_stats->tx_retry_cnt;
+ data[i++] = tgt_stats->tx_mult_retry_cnt;
+ data[i++] = tgt_stats->tx_rts_fail_cnt;
+ data[i++] = tgt_stats->tkip_cnter_measures_invoked;
+
+ data[i++] = tgt_stats->rx_ucast_pkt;
+ data[i++] = tgt_stats->rx_ucast_rate;
+ data[i++] = tgt_stats->rx_bcast_pkt;
+ data[i++] = tgt_stats->rx_ucast_byte;
+ data[i++] = tgt_stats->rx_bcast_byte;
+ data[i++] = tgt_stats->rx_frgment_pkt;
+ data[i++] = tgt_stats->rx_err;
+ data[i++] = tgt_stats->rx_crc_err;
+ data[i++] = tgt_stats->rx_key_cache_miss;
+ data[i++] = tgt_stats->rx_decrypt_err;
+ data[i++] = tgt_stats->rx_dupl_frame;
+ data[i++] = tgt_stats->tkip_local_mic_fail;
+ data[i++] = tgt_stats->tkip_fmt_err;
+ data[i++] = tgt_stats->ccmp_fmt_err;
+ data[i++] = tgt_stats->ccmp_replays;
+
+ data[i++] = tgt_stats->cs_bmiss_cnt;
+ data[i++] = tgt_stats->cs_connect_cnt;
+ data[i++] = tgt_stats->cs_discon_cnt;
+ data[i++] = tgt_stats->cs_ave_beacon_rssi;
+ data[i++] = tgt_stats->arp_received;
+ data[i++] = tgt_stats->arp_matched;
+ data[i++] = tgt_stats->arp_replied;
+
+ if (i != ATH6KL_STATS_LEN) {
+ WARN_ON_ONCE(1);
+ ath6kl_err("ethtool stats error, i: %d STATS_LEN: %d\n",
+ i, (int)ATH6KL_STATS_LEN);
+ }
+}
+
+/* These stats are per NIC, not really per vdev, so we just ignore dev. */
+static void ath6kl_get_strings(struct net_device *dev, u32 sset, u8 *data)
+{
+ int sz_sta_stats = 0;
+
+ if (sset == ETH_SS_STATS) {
+ sz_sta_stats = sizeof(ath6kl_gstrings_sta_stats);
+ memcpy(data, ath6kl_gstrings_sta_stats, sz_sta_stats);
+ }
+}
+
+static const struct ethtool_ops ath6kl_ethtool_ops = {
+ .get_drvinfo = cfg80211_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_strings = ath6kl_get_strings,
+ .get_ethtool_stats = ath6kl_get_stats,
+ .get_sset_count = ath6kl_get_sset_count,
+};
+
struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
unsigned char name_assign_type,
enum nl80211_iftype type,
@@ -3679,6 +3810,8 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
if (ath6kl_cfg80211_vif_init(vif))
goto err;
+ netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops);
+
if (register_netdevice(ndev))
goto err;
@@ -3786,6 +3919,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_2ghz.ht_cap.ht_supported = false;
ath6kl_band_5ghz.ht_cap.cap = 0;
ath6kl_band_5ghz.ht_cap.ht_supported = false;
+
+ if (ht)
+ ath6kl_err("Firmware lacks RSN-CAP-OVERRIDE, so HT (802.11n) is disabled.");
}
if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
@@ -3794,11 +3930,18 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
+ ar->hw.tx_ant = 2;
+ ar->hw.rx_ant = 2;
} else {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+ ar->hw.tx_ant = 1;
+ ar->hw.rx_ant = 1;
}
+ wiphy->available_antennas_tx = ar->hw.tx_ant;
+ wiphy->available_antennas_rx = ar->hw.rx_ant;
+
if (band_2gig)
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
if (band_5gig)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 2b78c863d030..5f3acfe6015e 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -782,6 +782,8 @@ struct ath6kl {
u32 refclk_hz;
u32 uarttx_pin;
u32 testscript_addr;
+ u8 tx_ant;
+ u8 rx_ant;
enum wmi_phy_cap cap;
u32 flags;
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 81ba48d2938b..e2b7809d7886 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -98,6 +98,33 @@ void ath6kl_warn(const char *fmt, ...)
}
EXPORT_SYMBOL(ath6kl_warn);
+int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif)
+{
+ long left;
+
+ if (down_interruptible(&ar->sem))
+ return -EBUSY;
+
+ set_bit(STATS_UPDATE_PEND, &vif->flags);
+
+ if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
+ up(&ar->sem);
+ return -EIO;
+ }
+
+ left = wait_event_interruptible_timeout(ar->event_wq,
+ !test_bit(STATS_UPDATE_PEND,
+ &vif->flags), WMI_TIMEOUT);
+
+ up(&ar->sem);
+
+ if (left <= 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+EXPORT_SYMBOL(ath6kl_read_tgt_stats);
+
#ifdef CONFIG_ATH6KL_DEBUG
void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...)
@@ -544,42 +571,24 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
char *buf;
unsigned int len = 0, buf_len = 1500;
int i;
- long left;
ssize_t ret_cnt;
+ int rv;
vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
- tgt_stats = &vif->target_stats;
-
buf = kzalloc(buf_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- if (down_interruptible(&ar->sem)) {
+ rv = ath6kl_read_tgt_stats(ar, vif);
+ if (rv < 0) {
kfree(buf);
- return -EBUSY;
+ return rv;
}
- set_bit(STATS_UPDATE_PEND, &vif->flags);
-
- if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
- up(&ar->sem);
- kfree(buf);
- return -EIO;
- }
-
- left = wait_event_interruptible_timeout(ar->event_wq,
- !test_bit(STATS_UPDATE_PEND,
- &vif->flags), WMI_TIMEOUT);
-
- up(&ar->sem);
-
- if (left <= 0) {
- kfree(buf);
- return -ETIMEDOUT;
- }
+ tgt_stats = &vif->target_stats;
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%25s\n",
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 19106ed28961..0614393dd7ae 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -59,6 +59,8 @@ enum ath6kl_war {
ATH6KL_WAR_INVALID_RATE,
};
+int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif);
+
#ifdef CONFIG_ATH6KL_DEBUG
void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index e481f14b9878..fffb65b3e652 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -1085,9 +1085,7 @@ static int htc_setup_tx_complete(struct htc_target *target)
send_pkt->completion = NULL;
ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0);
status = ath6kl_htc_tx_issue(target, send_pkt);
-
- if (send_pkt != NULL)
- htc_reclaim_txctrl_buf(target, send_pkt);
+ htc_reclaim_txctrl_buf(target, send_pkt);
return status;
}
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 6e473fa4b13c..6ae0734f86e0 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -715,6 +715,7 @@ static bool check_device_tree(struct ath6kl *ar)
board_filename, ret);
continue;
}
+ of_node_put(node);
return true;
}
return false;
@@ -994,7 +995,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
switch (ie_id) {
case ATH6KL_FW_IE_FW_VERSION:
strlcpy(ar->wiphy->fw_version, data,
- sizeof(ar->wiphy->fw_version));
+ min(sizeof(ar->wiphy->fw_version), ie_len+1));
ath6kl_dbg(ATH6KL_DBG_BOOT,
"found fw version %s\n",
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
index 6314ae2e93e3..9d17a5375f64 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
@@ -610,8 +610,8 @@
#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127
#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116
-#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120
+#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112
#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127
-#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110
+#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97
#endif
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 174442beb952..0c391997a2f7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -1249,7 +1249,8 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
- if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
+ if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
+ AR_SREV_9561(ah)) {
if (is_2g)
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
@@ -1640,7 +1641,8 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
skip_tx_iqcal:
if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
- if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
+ if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) ||
+ AR_SREV_9561(ah)) {
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (!(ah->rxchainmask & (1 << i)))
continue;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 79fd3b2dcbde..8b238c15916d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -857,7 +857,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
qca956x_1p0_common_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca956x_1p0_common_rx_gain_bounds);
- INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+ INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna,
qca956x_1p0_xlna_only);
} else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
@@ -942,7 +942,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
ar9462_2p1_baseband_core_mix_rxgain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
ar9462_2p1_baseband_postamble_mix_rxgain);
- INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+ INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna,
ar9462_2p1_baseband_postamble_5g_xlna);
} else if (AR_SREV_9462_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
@@ -951,7 +951,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
ar9462_2p0_baseband_core_mix_rxgain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
ar9462_2p0_baseband_postamble_mix_rxgain);
- INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+ INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna,
ar9462_2p0_baseband_postamble_5g_xlna);
}
}
@@ -961,12 +961,12 @@ static void ar9003_rx_gain_table_mode3(struct ath_hw *ah)
if (AR_SREV_9462_21(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p1_common_5g_xlna_only_rxgain);
- INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+ INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna,
ar9462_2p1_baseband_postamble_5g_xlna);
} else if (AR_SREV_9462_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p0_common_5g_xlna_only_rxgain);
- INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+ INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna,
ar9462_2p0_baseband_postamble_5g_xlna);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 1ad66b76749b..201425e7f9cb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -926,19 +926,18 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
*/
if ((ar9003_hw_get_rx_gain_idx(ah) == 2) ||
(ar9003_hw_get_rx_gain_idx(ah) == 3)) {
- REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+ REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna,
modesIndex, regWrites);
}
-
- if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0))
- REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
- modesIndex, regWrites);
}
if (AR_SREV_9550(ah) || AR_SREV_9561(ah))
REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex,
regWrites);
+ if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0))
+ REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna,
+ modesIndex, regWrites);
/*
* TXGAIN initvals.
*/
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c85c47978e1e..b42f4a963ef4 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -635,6 +635,7 @@ struct ath9k_vif_iter_data {
int nstations; /* number of station vifs */
int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
+ int nocbs; /* number of OCB vifs */
struct ieee80211_vif *primary_sta;
};
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c
index 3b289f933405..84afcf78151f 100644
--- a/drivers/net/wireless/ath/ath9k/common-debug.c
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
@@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
+
PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
@@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
- PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
+
+ PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER);
PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
- PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
- PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
+ PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
+ PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
+
PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+ PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF);
+
+ PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
+ PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD);
+ PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL);
if (len > size)
len = size;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index da32c8faad94..6de64cface3c 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -741,8 +741,8 @@ static int read_file_misc(struct seq_file *file, void *data)
i++, (int)(ctx->assigned), iter_data.naps,
iter_data.nstations,
iter_data.nmeshes, iter_data.nwds);
- seq_printf(file, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
- iter_data.nadhocs, sc->cur_chan->nvifs,
+ seq_printf(file, " ADHOC: %i OCB: %i TOTAL: %hi BEACON-VIF: %hi\n",
+ iter_data.nadhocs, iter_data.nocbs, sc->cur_chan->nvifs,
sc->nbcnvifs);
}
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 10c02f5cbc5e..165dd202c365 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -17,12 +17,8 @@
#include <asm/unaligned.h>
#include "htc.h"
-/* identify firmware images */
-#define FIRMWARE_AR7010_1_1 "htc_7010.fw"
-#define FIRMWARE_AR9271 "htc_9271.fw"
-
-MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
-MODULE_FIRMWARE(FIRMWARE_AR9271);
+MODULE_FIRMWARE(HTC_7010_MODULE_FW);
+MODULE_FIRMWARE(HTC_9271_MODULE_FW);
static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
@@ -1080,12 +1076,88 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev)
device_unlock(parent);
}
+static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context);
+
+/* taken from iwlwifi */
+static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev,
+ bool first)
+{
+ char index[8], *chip;
+ int ret;
+
+ if (first) {
+ if (htc_use_dev_fw) {
+ hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX + 1;
+ sprintf(index, "%s", "dev");
+ } else {
+ hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX;
+ sprintf(index, "%d", hif_dev->fw_minor_index);
+ }
+ } else {
+ hif_dev->fw_minor_index--;
+ sprintf(index, "%d", hif_dev->fw_minor_index);
+ }
+
+ /* test for FW 1.3 */
+ if (MAJOR_VERSION_REQ == 1 && hif_dev->fw_minor_index == 3) {
+ const char *filename;
+
+ if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info))
+ filename = FIRMWARE_AR7010_1_1;
+ else
+ filename = FIRMWARE_AR9271;
+
+ /* expected fw locations:
+ * - htc_9271.fw (stable version 1.3, depricated)
+ */
+ snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name),
+ "%s", filename);
+
+ } else if (hif_dev->fw_minor_index < FIRMWARE_MINOR_IDX_MIN) {
+ dev_err(&hif_dev->udev->dev, "no suitable firmware found!\n");
+
+ return -ENOENT;
+ } else {
+ if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info))
+ chip = "7010";
+ else
+ chip = "9271";
+
+ /* expected fw locations:
+ * - ath9k_htc/htc_9271-1.dev.0.fw (development version)
+ * - ath9k_htc/htc_9271-1.4.0.fw (stable version)
+ */
+ snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name),
+ "%s/htc_%s-%d.%s.0.fw", HTC_FW_PATH,
+ chip, MAJOR_VERSION_REQ, index);
+ }
+
+ ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
+ &hif_dev->udev->dev, GFP_KERNEL,
+ hif_dev, ath9k_hif_usb_firmware_cb);
+ if (ret) {
+ dev_err(&hif_dev->udev->dev,
+ "ath9k_htc: Async request for firmware %s failed\n",
+ hif_dev->fw_name);
+ return ret;
+ }
+
+ dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
+ hif_dev->fw_name);
+
+ return ret;
+}
+
static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
{
struct hif_device_usb *hif_dev = context;
int ret;
if (!fw) {
+ ret = ath9k_hif_request_firmware(hif_dev, false);
+ if (!ret)
+ return;
+
dev_err(&hif_dev->udev->dev,
"ath9k_htc: Failed to get firmware %s\n",
hif_dev->fw_name);
@@ -1215,27 +1287,11 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
init_completion(&hif_dev->fw_done);
- /* Find out which firmware to load */
-
- if (IS_AR7010_DEVICE(id->driver_info))
- hif_dev->fw_name = FIRMWARE_AR7010_1_1;
- else
- hif_dev->fw_name = FIRMWARE_AR9271;
-
- ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
- &hif_dev->udev->dev, GFP_KERNEL,
- hif_dev, ath9k_hif_usb_firmware_cb);
- if (ret) {
- dev_err(&hif_dev->udev->dev,
- "ath9k_htc: Async request for firmware %s failed\n",
- hif_dev->fw_name);
+ ret = ath9k_hif_request_firmware(hif_dev, true);
+ if (ret)
goto err_fw_req;
- }
- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
- hif_dev->fw_name);
-
- return 0;
+ return ret;
err_fw_req:
usb_set_intfdata(interface, NULL);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 51496e74b83e..7c2ef7ecd98b 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -17,8 +17,26 @@
#ifndef HTC_USB_H
#define HTC_USB_H
+/* old firmware images */
+#define FIRMWARE_AR7010_1_1 "htc_7010.fw"
+#define FIRMWARE_AR9271 "htc_9271.fw"
+
+/* supported Major FW version */
#define MAJOR_VERSION_REQ 1
#define MINOR_VERSION_REQ 3
+/* minimal and maximal supported Minor FW version. */
+#define FIRMWARE_MINOR_IDX_MAX 4
+#define FIRMWARE_MINOR_IDX_MIN 3
+#define HTC_FW_PATH "ath9k_htc"
+
+#define HTC_9271_MODULE_FW HTC_FW_PATH "/htc_9271-" \
+ __stringify(MAJOR_VERSION_REQ) \
+ "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw"
+#define HTC_7010_MODULE_FW HTC_FW_PATH "/htc_7010-" \
+ __stringify(MAJOR_VERSION_REQ) \
+ "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw"
+
+extern int htc_use_dev_fw;
#define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB))
@@ -101,7 +119,8 @@ struct hif_device_usb {
struct usb_anchor reg_in_submitted;
struct usb_anchor mgmt_submitted;
struct sk_buff *remain_skb;
- const char *fw_name;
+ char fw_name[32];
+ int fw_minor_index;
int rx_remain_len;
int rx_pkt_len;
int rx_transfer_len;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 1e84882f8c5b..8647ab77c019 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -38,6 +38,10 @@ static int ath9k_ps_enable;
module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
+int htc_use_dev_fw = 0;
+module_param_named(use_dev_fw, htc_use_dev_fw, int, 0444);
+MODULE_PARM_DESC(use_dev_fw, "Use development FW version");
+
#ifdef CONFIG_MAC80211_LEDS
int ath9k_htc_led_blink = 1;
module_param_named(blink, ath9k_htc_led_blink, int, 0444);
@@ -736,7 +740,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_MESH_POINT);
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_OCB);
hw->wiphy->iface_combinations = &if_comb;
hw->wiphy->n_iface_combinations = 1;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 172a9ff4aaab..a680a970b7f7 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1659,7 +1659,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size)
+ u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath9k_htc_sta *ista;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1dd0339de372..41382f89abe1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -385,7 +385,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.dma_beacon_response_time = 1;
ah->config.sw_beacon_response_time = 6;
- ah->config.cwm_ignore_extcca = 0;
+ ah->config.cwm_ignore_extcca = false;
ah->config.analog_shiftreg = 1;
ah->config.rx_intr_mitigation = true;
@@ -1241,6 +1241,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
break;
}
/* fall through */
+ case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
set |= AR_STA_ID1_STA_AP;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index e8454db17634..831a54415a25 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -332,14 +332,14 @@ enum ath9k_hw_hang_checks {
struct ath9k_ops_config {
int dma_beacon_response_time;
int sw_beacon_response_time;
- u32 cwm_ignore_extcca;
+ bool cwm_ignore_extcca;
u32 pcie_waen;
u8 analog_shiftreg;
u32 ofdm_trig_low;
u32 ofdm_trig_high;
u32 cck_trig_high;
u32 cck_trig_low;
- u32 enable_paprd;
+ bool enable_paprd;
int serialize_regmode;
bool rx_intr_mitigation;
bool tx_intr_mitigation;
@@ -919,7 +919,7 @@ struct ath_hw {
struct ar5416IniArray iniCckfirJapan2484;
struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray ini_radio_post_sys2ant;
- struct ar5416IniArray ini_modes_rxgain_5g_xlna;
+ struct ar5416IniArray ini_modes_rxgain_xlna;
struct ar5416IniArray ini_modes_rxgain_bb_core;
struct ar5416IniArray ini_modes_rxgain_bb_postamble;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 57f95f2dca5b..2e2b92ba96b8 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -855,7 +855,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT) |
- BIT(NL80211_IFTYPE_WDS);
+ BIT(NL80211_IFTYPE_WDS) |
+ BIT(NL80211_IFTYPE_OCB);
if (ath9k_is_chanctx_enabled())
hw->wiphy->interface_modes |=
@@ -880,6 +881,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->max_rate_tries = 10;
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
+ hw->extra_tx_headroom = 4;
hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index e55fa11894b6..7fbf7f965f61 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -209,21 +209,25 @@ enum ath9k_phyerr {
ATH9K_PHYERR_OFDM_POWER_DROP = 21,
ATH9K_PHYERR_OFDM_SERVICE = 22,
ATH9K_PHYERR_OFDM_RESTART = 23,
- ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
+ ATH9K_PHYERR_CCK_BLOCKER = 24,
ATH9K_PHYERR_CCK_TIMING = 25,
ATH9K_PHYERR_CCK_HEADER_CRC = 26,
ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
+ ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28,
+ ATH9K_PHYERR_CCK_POWER_DROP = 29,
ATH9K_PHYERR_CCK_SERVICE = 30,
ATH9K_PHYERR_CCK_RESTART = 31,
- ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
- ATH9K_PHYERR_CCK_POWER_DROP = 33,
- ATH9K_PHYERR_HT_CRC_ERROR = 34,
- ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
- ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
+ ATH9K_PHYERR_HT_CRC_ERROR = 32,
+ ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33,
+ ATH9K_PHYERR_HT_RATE_ILLEGAL = 34,
+ ATH9K_PHYERR_HT_ZLF = 35,
+
+ ATH9K_PHYERR_FALSE_RADAR_EXT = 36,
+ ATH9K_PHYERR_GREEN_FIELD = 37,
+ ATH9K_PHYERR_SPECTRAL = 38,
- ATH9K_PHYERR_SPECTRAL = 38,
ATH9K_PHYERR_MAX = 39,
};
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c27143ba9ffb..d184e682e636 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -938,6 +938,9 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
if (avp->assoc && !iter_data->primary_sta)
iter_data->primary_sta = vif;
break;
+ case NL80211_IFTYPE_OCB:
+ iter_data->nocbs++;
+ break;
case NL80211_IFTYPE_ADHOC:
iter_data->nadhocs++;
if (vif->bss_conf.enable_beacon)
@@ -1111,6 +1114,8 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
if (iter_data.nmeshes)
ah->opmode = NL80211_IFTYPE_MESH_POINT;
+ else if (iter_data.nocbs)
+ ah->opmode = NL80211_IFTYPE_OCB;
else if (iter_data.nwds)
ah->opmode = NL80211_IFTYPE_AP;
else if (iter_data.nadhocs)
@@ -1760,7 +1765,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath9k_calculate_summary_state(sc, avp->chanctx);
}
- if (changed & BSS_CHANGED_IBSS) {
+ if ((changed & BSS_CHANGED_IBSS) ||
+ (changed & BSS_CHANGED_OCB)) {
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
@@ -1856,7 +1862,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size)
+ u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index d3189daf9996..994daf6c6297 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -403,7 +403,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
(sc->cur_chan->nvifs <= 1) &&
!(sc->cur_chan->rxfilter & FIF_BCN_PRBRESP_PROMISC))
rfilt |= ATH9K_RX_FILTER_MYBEACON;
- else
+ else if (sc->sc_ah->opmode != NL80211_IFTYPE_OCB)
rfilt |= ATH9K_RX_FILTER_BEACON;
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 170c209f99b8..19d3d64416bf 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1415,7 +1415,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size)
+ u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
{
struct ar9170 *ar = hw->priv;
struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 924135b8e575..d66533cbc38a 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -453,7 +453,7 @@ static void carl9170_rx_phy_status(struct ar9170 *ar,
/* post-process RSSI */
for (i = 0; i < 7; i++)
if (phy->rssi[i] & 0x80)
- phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
+ phy->rssi[i] = ((~phy->rssi[i] & 0x7f) + 1) & 0x7f;
/* TODO: we could do something with phy_errors */
status->signal = ar->noise[0] + phy->rssi_combined;
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 656ce42b339a..2303ef96299d 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -21,12 +21,6 @@
#include "dfs_pri_detector.h"
#include "ath.h"
-/*
- * tolerated deviation of radar time stamp in usecs on both sides
- * TODO: this might need to be HW-dependent
- */
-#define PRI_TOLERANCE 16
-
/**
* struct radar_types - contains array of patterns defined for one DFS domain
* @domain: DFS regulatory domain
@@ -121,7 +115,7 @@ static const struct radar_detector_specs jp_radar_ref_types[] = {
JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false),
JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false),
JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false),
- JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20, 50, false),
+ JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, false),
JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false),
};
@@ -290,10 +284,10 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
if (cd == NULL)
return false;
- dpd->last_pulse_ts = event->ts;
/* reset detector on time stamp wraparound, caused by TSF reset */
if (event->ts < dpd->last_pulse_ts)
dpd_reset(dpd);
+ dpd->last_pulse_ts = event->ts;
/* do type individual pattern matching */
for (i = 0; i < dpd->num_radar_types; i++) {
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.h b/drivers/net/wireless/ath/dfs_pattern_detector.h
index 25a43d632f90..92be3530e9b5 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.h
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.h
@@ -21,6 +21,11 @@
#include <linux/list.h>
#include <linux/nl80211.h>
+/* tolerated deviation of radar time stamp in usecs on both sides
+ * TODO: this might need to be HW-dependent
+ */
+#define PRI_TOLERANCE 16
+
/**
* struct ath_dfs_pool_stats - DFS Statistics for global pools
*/
diff --git a/drivers/net/wireless/ath/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c
index cc5c592fc4c0..05b0464c6b92 100644
--- a/drivers/net/wireless/ath/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/dfs_pri_detector.c
@@ -25,6 +25,9 @@ struct ath_dfs_pool_stats global_dfs_pool_stats = {};
#define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++)
#define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--)
+#define GET_PRI_TO_USE(MIN, MAX, RUNTIME) \
+ (MIN + PRI_TOLERANCE == MAX - PRI_TOLERANCE ? \
+ MIN + PRI_TOLERANCE : RUNTIME)
/**
* struct pulse_elem - elements in pulse queue
@@ -243,7 +246,8 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
ps.count_falses = 0;
ps.first_ts = p->ts;
ps.last_ts = ts;
- ps.pri = ts - p->ts;
+ ps.pri = GET_PRI_TO_USE(pde->rs->pri_min,
+ pde->rs->pri_max, ts - p->ts);
ps.dur = ps.pri * (pde->rs->ppb - 1)
+ 2 * pde->rs->max_pri_tolerance;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 086549b732b9..f8dfa05b290a 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -79,6 +79,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch)
struct wcn36xx_dxe_ctl *cur_ctl = NULL;
int i;
+ spin_lock_init(&ch->lock);
for (i = 0; i < ch->desc_num; i++) {
cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL);
if (!cur_ctl)
@@ -169,7 +170,7 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
}
-static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch)
+static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
{
struct wcn36xx_dxe_desc *cur_dxe = NULL;
struct wcn36xx_dxe_desc *prev_dxe = NULL;
@@ -178,7 +179,7 @@ static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch)
int i;
size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
- wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr,
+ wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
GFP_KERNEL);
if (!wcn_ch->cpu_addr)
return -ENOMEM;
@@ -270,7 +271,7 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
return 0;
}
-static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl)
+static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl)
{
struct wcn36xx_dxe_desc *dxe = ctl->desc;
struct sk_buff *skb;
@@ -279,7 +280,7 @@ static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl)
if (skb == NULL)
return -ENOMEM;
- dxe->dst_addr_l = dma_map_single(NULL,
+ dxe->dst_addr_l = dma_map_single(dev,
skb_tail_pointer(skb),
WCN36XX_PKT_SIZE,
DMA_FROM_DEVICE);
@@ -297,7 +298,7 @@ static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn,
cur_ctl = wcn_ch->head_blk_ctl;
for (i = 0; i < wcn_ch->desc_num; i++) {
- wcn36xx_dxe_fill_skb(cur_ctl);
+ wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl);
cur_ctl = cur_ctl->next;
}
@@ -345,7 +346,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status)
static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
{
- struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl;
+ struct wcn36xx_dxe_ctl *ctl;
struct ieee80211_tx_info *info;
unsigned long flags;
@@ -354,23 +355,25 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
* completely full head and tail are pointing to the same element
* and while-do will not make any cycles.
*/
+ spin_lock_irqsave(&ch->lock, flags);
+ ctl = ch->tail_blk_ctl;
do {
if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)
break;
if (ctl->skb) {
- dma_unmap_single(NULL, ctl->desc->src_addr_l,
+ dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
ctl->skb->len, DMA_TO_DEVICE);
info = IEEE80211_SKB_CB(ctl->skb);
if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
/* Keep frame until TX status comes */
ieee80211_free_txskb(wcn->hw, ctl->skb);
}
- spin_lock_irqsave(&ctl->skb_lock, flags);
+ spin_lock(&ctl->skb_lock);
if (wcn->queues_stopped) {
wcn->queues_stopped = false;
ieee80211_wake_queues(wcn->hw);
}
- spin_unlock_irqrestore(&ctl->skb_lock, flags);
+ spin_unlock(&ctl->skb_lock);
ctl->skb = NULL;
}
@@ -379,6 +382,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
!(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK));
ch->tail_blk_ctl = ctl;
+ spin_unlock_irqrestore(&ch->lock, flags);
}
static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
@@ -474,7 +478,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
skb = ctl->skb;
dma_addr = dxe->dst_addr_l;
- wcn36xx_dxe_fill_skb(ctl);
+ wcn36xx_dxe_fill_skb(wcn->dev, ctl);
switch (ch->ch_type) {
case WCN36XX_DXE_CH_RX_L:
@@ -491,7 +495,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
wcn36xx_warn("Unknown channel\n");
}
- dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE,
+ dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
DMA_FROM_DEVICE);
wcn36xx_rx_skb(wcn, skb);
ctl = ctl->next;
@@ -540,7 +544,7 @@ 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_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr,
+ cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr,
GFP_KERNEL);
if (!cpu_addr)
goto out_err;
@@ -555,7 +559,7 @@ 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_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr,
+ cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr,
GFP_KERNEL);
if (!cpu_addr)
goto out_err;
@@ -574,13 +578,13 @@ out_err:
void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn)
{
if (wcn->mgmt_mem_pool.virt_addr)
- dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size *
+ dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size *
WCN36XX_DXE_CH_DESC_NUMB_TX_H,
wcn->mgmt_mem_pool.virt_addr,
wcn->mgmt_mem_pool.phy_addr);
if (wcn->data_mem_pool.virt_addr) {
- dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size *
+ dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size *
WCN36XX_DXE_CH_DESC_NUMB_TX_L,
wcn->data_mem_pool.virt_addr,
wcn->data_mem_pool.phy_addr);
@@ -596,12 +600,14 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
struct wcn36xx_dxe_desc *desc = NULL;
struct wcn36xx_dxe_ch *ch = NULL;
unsigned long flags;
+ int ret;
ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch;
+ spin_lock_irqsave(&ch->lock, flags);
ctl = ch->head_blk_ctl;
- spin_lock_irqsave(&ctl->next->skb_lock, flags);
+ spin_lock(&ctl->next->skb_lock);
/*
* If skb is not null that means that we reached the tail of the ring
@@ -611,10 +617,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
if (NULL != ctl->next->skb) {
ieee80211_stop_queues(wcn->hw);
wcn->queues_stopped = true;
- spin_unlock_irqrestore(&ctl->next->skb_lock, flags);
+ spin_unlock(&ctl->next->skb_lock);
+ spin_unlock_irqrestore(&ch->lock, flags);
return -EBUSY;
}
- spin_unlock_irqrestore(&ctl->next->skb_lock, flags);
+ spin_unlock(&ctl->next->skb_lock);
ctl->skb = NULL;
desc = ctl->desc;
@@ -640,10 +647,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
desc = ctl->desc;
if (ctl->bd_cpu_addr) {
wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
- desc->src_addr_l = dma_map_single(NULL,
+ desc->src_addr_l = dma_map_single(wcn->dev,
ctl->skb->data,
ctl->skb->len,
DMA_TO_DEVICE);
@@ -679,7 +687,10 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
ch->reg_ctrl, ch->def_ctrl);
}
- return 0;
+ ret = 0;
+unlock:
+ spin_unlock_irqrestore(&ch->lock, flags);
+ return ret;
}
int wcn36xx_dxe_init(struct wcn36xx *wcn)
@@ -696,7 +707,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/***************************************/
/* Init descriptors for TX LOW channel */
/***************************************/
- wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch);
+ wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);
/* Write channel head to a NEXT register */
@@ -714,7 +725,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/***************************************/
/* Init descriptors for TX HIGH channel */
/***************************************/
- wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch);
+ wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);
/* Write channel head to a NEXT register */
@@ -734,7 +745,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/***************************************/
/* Init descriptors for RX LOW channel */
/***************************************/
- wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch);
+ wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
/* For RX we need to preallocated buffers */
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
@@ -764,7 +775,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/***************************************/
/* Init descriptors for RX HIGH channel */
/***************************************/
- wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch);
+ wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
/* For RX we need to prealocat buffers */
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h
index 35ee7e966bd2..3eca4f9594f2 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -243,6 +243,7 @@ struct wcn36xx_dxe_ctl {
};
struct wcn36xx_dxe_ch {
+ spinlock_t lock; /* protects head/tail ptrs */
enum wcn36xx_dxe_ch_type ch_type;
void *cpu_addr;
dma_addr_t dma_addr;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 900e72a089d8..7c169abdbafe 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -859,7 +859,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_sta *sta_priv = NULL;
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig
index ce8c0381825e..6dfedc8bd6a3 100644
--- a/drivers/net/wireless/ath/wil6210/Kconfig
+++ b/drivers/net/wireless/ath/wil6210/Kconfig
@@ -1,5 +1,6 @@
config WIL6210
tristate "Wilocity 60g WiFi card wil6210 support"
+ select WANT_DEV_COREDUMP
depends on CFG80211
depends on PCI
default n
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index 64b432625fbb..fdf63d5fe82b 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -17,6 +17,7 @@ wil6210-y += pmc.o
wil6210-$(CONFIG_WIL6210_TRACING) += trace.o
wil6210-y += wil_platform.o
wil6210-y += ethtool.o
+wil6210-y += wil_crash_dump.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index d1a1e160ef31..97bc186f9728 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1373,6 +1373,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
}
}
spin_unlock_bh(&p->tid_rx_lock);
+ seq_printf(s,
+ "Rx invalid frame: non-data %lu, short %lu, large %lu\n",
+ p->stats.rx_non_data_frame,
+ p->stats.rx_short_frame,
+ p->stats.rx_large_frame);
+
seq_puts(s, "Rx/MCS:");
for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
mcs++)
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index a371f036d054..50c136e843c4 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-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
@@ -236,7 +236,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
BIT_DMA_EP_RX_ICR_RX_HTRSH);
- if (likely(test_bit(wil_status_reset_done, wil->status))) {
+ if (likely(test_bit(wil_status_fwready, wil->status))) {
if (likely(test_bit(wil_status_napi_en, wil->status))) {
wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
need_unmask = false;
@@ -286,7 +286,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
/* clear also all VRING interrupts */
isr &= ~(BIT(25) - 1UL);
- if (likely(test_bit(wil_status_reset_done, wil->status))) {
+ if (likely(test_bit(wil_status_fwready, wil->status))) {
wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
need_unmask = false;
napi_schedule(&wil->napi_tx);
@@ -347,7 +347,12 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
wil6210_mask_irq_misc(wil);
if (isr & ISR_MISC_FW_ERROR) {
- wil_err(wil, "Firmware error detected\n");
+ u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE);
+ u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE);
+
+ wil_err(wil,
+ "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n",
+ fw_assert_code, ucode_assert_code);
clear_bit(wil_status_fwready, wil->status);
/*
* do not clear @isr here - we do 2-nd part in thread
@@ -359,7 +364,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
if (isr & ISR_MISC_FW_READY) {
wil_dbg_irq(wil, "IRQ: FW ready\n");
wil_cache_mbox_regs(wil);
- set_bit(wil_status_reset_done, wil->status);
+ set_bit(wil_status_mbox_ready, wil->status);
/**
* Actual FW ready indicated by the
* WMI_FW_READY_EVENTID
@@ -386,6 +391,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
if (isr & ISR_MISC_FW_ERROR) {
+ wil_fw_core_dump(wil);
wil_notify_fw_error(wil);
isr &= ~ISR_MISC_FW_ERROR;
wil_fw_error_recovery(wil);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 2fb04c51da53..bb69a5949aea 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -203,11 +203,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
* - disconnect single STA, already disconnected
* - disconnect all
*
- * For "disconnect all", there are 2 options:
+ * For "disconnect all", there are 3 options:
* - bssid == NULL
+ * - bssid is broadcast address (ff:ff:ff:ff:ff:ff)
* - bssid is our MAC address
*/
- if (bssid && memcmp(ndev->dev_addr, bssid, ETH_ALEN)) {
+ if (bssid && !is_broadcast_ether_addr(bssid) &&
+ !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) {
cid = wil_find_cid(wil, bssid);
wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n",
bssid, cid, reason_code);
@@ -420,7 +422,7 @@ static void wil_connect_worker(struct work_struct *work)
wil->sta[cid].status = wil_sta_connected;
netif_tx_wake_all_queues(ndev);
} else {
- wil->sta[cid].status = wil_sta_unused;
+ wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true);
}
}
@@ -765,6 +767,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
if (wil->hw_version == HW_VER_UNKNOWN)
return -ENODEV;
+ set_bit(wil_status_resetting, wil->status);
+
cancel_work_sync(&wil->disconnect_worker);
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
wil_bcast_fini(wil);
@@ -851,6 +855,12 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
void wil_fw_error_recovery(struct wil6210_priv *wil)
{
wil_dbg_misc(wil, "starting fw error recovery\n");
+
+ if (test_bit(wil_status_resetting, wil->status)) {
+ wil_info(wil, "Reset already in progress\n");
+ return;
+ }
+
wil->recovery_state = fw_recovery_pending;
schedule_work(&wil->fw_error_worker);
}
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index feff1ef10fb3..1a3142c332e1 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -260,6 +260,7 @@ static const struct pci_device_id wil6210_pcie_ids[] = {
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int wil6210_suspend(struct device *dev, bool is_runtime)
{
@@ -307,7 +308,6 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
return rc;
}
-#ifdef CONFIG_PM_SLEEP
static int wil6210_pm_suspend(struct device *dev)
{
return wil6210_suspend(dev, false);
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
index 8a8cdc61b25b..5ca0307a3274 100644
--- a/drivers/net/wireless/ath/wil6210/pmc.c
+++ b/drivers/net/wireless/ath/wil6210/pmc.c
@@ -110,7 +110,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
*/
for (i = 0; i < num_descriptors; i++) {
struct vring_tx_desc *_d = &pmc->pring_va[i];
- struct vring_tx_desc dd, *d = &dd;
+ struct vring_tx_desc dd = {}, *d = &dd;
int j = 0;
pmc->descriptors[i].va = dma_alloc_coherent(dev,
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index 9238c1ac23dd..e3d1be82f314 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -205,6 +205,32 @@ out:
spin_unlock(&sta->tid_rx_lock);
}
+/* process BAR frame, called in NAPI context */
+void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq)
+{
+ struct wil_sta_info *sta = &wil->sta[cid];
+ struct wil_tid_ampdu_rx *r;
+
+ spin_lock(&sta->tid_rx_lock);
+
+ r = sta->tid_rx[tid];
+ if (!r) {
+ wil_err(wil, "BAR for non-existing CID %d TID %d\n", cid, tid);
+ goto out;
+ }
+ if (seq_less(seq, r->head_seq_num)) {
+ wil_err(wil, "BAR Seq 0x%03x preceding head 0x%03x\n",
+ seq, r->head_seq_num);
+ goto out;
+ }
+ wil_dbg_txrx(wil, "BAR: CID %d TID %d Seq 0x%03x head 0x%03x\n",
+ cid, tid, seq, r->head_seq_num);
+ wil_release_reorder_frames(wil, r, seq);
+
+out:
+ spin_unlock(&sta->tid_rx_lock);
+}
+
struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
int size, u16 ssn)
{
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 6229110d558a..3bc9bc0efbac 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -358,6 +358,13 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
}
}
+/* similar to ieee80211_ version, but FC contain only 1-st byte */
+static inline int wil_is_back_req(u8 fc)
+{
+ return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ);
+}
+
/**
* reap 1 frame from @swhead
*
@@ -379,14 +386,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
u16 dmalen;
u8 ftype;
int cid;
- int i = (int)vring->swhead;
+ int i;
struct wil_net_stats *stats;
BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
+again:
if (unlikely(wil_vring_is_empty(vring)))
return NULL;
+ i = (int)vring->swhead;
_d = &vring->va[i].rx;
if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) {
/* it is not error, we just reached end of Rx done area */
@@ -398,7 +407,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
wil_vring_advance_head(vring, 1);
if (!skb) {
wil_err(wil, "No Rx skb at [%d]\n", i);
- return NULL;
+ goto again;
}
d = wil_skb_rxdesc(skb);
*d = *_d;
@@ -409,13 +418,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
trace_wil6210_rx(i, d);
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", i, dmalen);
- wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
+ wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4,
(const void *)d, sizeof(*d), false);
+ cid = wil_rxdesc_cid(d);
+ stats = &wil->sta[cid].stats;
+
if (unlikely(dmalen > sz)) {
wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
+ stats->rx_large_frame++;
kfree_skb(skb);
- return NULL;
+ goto again;
}
skb_trim(skb, dmalen);
@@ -424,8 +437,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb_headlen(skb), false);
- cid = wil_rxdesc_cid(d);
- 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]++;
@@ -437,24 +448,47 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
/* no extra checks if in sniffer mode */
if (ndev->type != ARPHRD_ETHER)
return skb;
- /*
- * Non-data frames may be delivered through Rx DMA channel (ex: BAR)
+ /* Non-data frames may be delivered through Rx DMA channel (ex: BAR)
* Driver should recognize it by frame type, that is found
* in Rx descriptor. If type is not data, it is 802.11 frame as is
*/
ftype = wil_rxdesc_ftype(d) << 2;
if (unlikely(ftype != IEEE80211_FTYPE_DATA)) {
- wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
- /* TODO: process it */
+ u8 fc1 = wil_rxdesc_fc1(d);
+ int mid = wil_rxdesc_mid(d);
+ int tid = wil_rxdesc_tid(d);
+ u16 seq = wil_rxdesc_seq(d);
+
+ wil_dbg_txrx(wil,
+ "Non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n",
+ fc1, mid, cid, tid, seq);
+ stats->rx_non_data_frame++;
+ if (wil_is_back_req(fc1)) {
+ wil_dbg_txrx(wil,
+ "BAR: MID %d CID %d TID %d Seq 0x%03x\n",
+ mid, cid, tid, seq);
+ wil_rx_bar(wil, cid, tid, seq);
+ } else {
+ /* print again all info. One can enable only this
+ * without overhead for printing every Rx frame
+ */
+ wil_dbg_txrx(wil,
+ "Unhandled non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n",
+ fc1, mid, cid, tid, seq);
+ wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4,
+ (const void *)d, sizeof(*d), false);
+ wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
+ skb->data, skb_headlen(skb), false);
+ }
kfree_skb(skb);
- return NULL;
+ goto again;
}
if (unlikely(skb->len < ETH_HLEN + snaplen)) {
wil_err(wil, "Short frame, len = %d\n", skb->len);
- /* TODO: process it (i.e. BAR) */
+ stats->rx_short_frame++;
kfree_skb(skb);
- return NULL;
+ goto again;
}
/* L4 IDENT is on when HW calculated checksum, check status
@@ -1208,6 +1242,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
int tcp_hdr_len;
int skb_net_hdr_len;
int gso_type;
+ int rc = -EINVAL;
wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n",
__func__, skb->len, vring_index);
@@ -1299,8 +1334,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
len, rem_data, descs_used);
if (descs_used == avail) {
- wil_err(wil, "TSO: ring overflow\n");
- goto dma_error;
+ wil_err_ratelimited(wil, "TSO: ring overflow\n");
+ rc = -ENOMEM;
+ goto mem_error;
}
lenmss = min_t(int, rem_data, len);
@@ -1322,8 +1358,10 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
headlen -= lenmss;
}
- if (unlikely(dma_mapping_error(dev, pa)))
- goto dma_error;
+ if (unlikely(dma_mapping_error(dev, pa))) {
+ wil_err(wil, "TSO: DMA map page error\n");
+ goto mem_error;
+ }
_desc = &vring->va[i].tx;
@@ -1422,8 +1460,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
}
/* advance swhead */
- wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead);
wil_vring_advance_head(vring, descs_used);
+ wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead);
/* make sure all writes to descriptors (shared memory) are done before
* committing them to HW
@@ -1433,8 +1471,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
wil_w(wil, vring->hwtail, vring->swhead);
return 0;
-dma_error:
- wil_err(wil, "TSO: DMA map page error\n");
+mem_error:
while (descs_used > 0) {
struct wil_ctx *ctx;
@@ -1445,14 +1482,11 @@ dma_error:
_desc->dma.status = TX_DMA_STATUS_DU;
ctx = &vring->ctx[i];
wil_txdesc_unmap(dev, d, ctx);
- if (ctx->skb)
- dev_kfree_skb_any(ctx->skb);
memset(ctx, 0, sizeof(*ctx));
descs_used--;
}
-
err_exit:
- return -EINVAL;
+ return rc;
}
static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
@@ -1528,8 +1562,11 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
_d = &vring->va[i].tx;
pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev, pa)))
+ if (unlikely(dma_mapping_error(dev, pa))) {
+ wil_err(wil, "Tx[%2d] failed to map fragment\n",
+ vring_index);
goto dma_error;
+ }
vring->ctx[i].mapped_as = wil_mapped_as_page;
wil_tx_desc_map(d, pa, len, vring_index);
/* no need to check return code -
@@ -1589,9 +1626,6 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
_d->dma.status = TX_DMA_STATUS_DU;
wil_txdesc_unmap(dev, d, ctx);
- if (ctx->skb)
- dev_kfree_skb_any(ctx->skb);
-
memset(ctx, 0, sizeof(*ctx));
}
@@ -1633,7 +1667,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
goto drop;
}
if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) {
- wil_err(wil, "FW not connected\n");
+ wil_err_ratelimited(wil, "FW not connected\n");
goto drop;
}
if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) {
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 82a8f9a030e7..ee7c7b4b9a17 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -464,6 +464,12 @@ static inline int wil_rxdesc_subtype(struct vring_rx_desc *d)
return WIL_GET_BITS(d->mac.d0, 12, 15);
}
+/* 1-st byte (with frame type/subtype) of FC field */
+static inline u8 wil_rxdesc_fc1(struct vring_rx_desc *d)
+{
+ return (u8)(WIL_GET_BITS(d->mac.d0, 10, 15) << 2);
+}
+
static inline int wil_rxdesc_seq(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->mac.d0, 16, 27);
@@ -501,6 +507,7 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
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, u8 cid, u8 tid, u16 seq);
struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
int size, u16 ssn);
void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index dd4ea926b8e3..ade5f3b8274b 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -246,6 +246,10 @@ struct RGF_ICR {
#define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */
#define JTAG_DEV_ID_SPARROW_B0 (0x2632072f)
+/* crash codes for FW/Ucode stored here */
+#define RGF_FW_ASSERT_CODE (0x91f020)
+#define RGF_UCODE_ASSERT_CODE (0x91f028)
+
enum {
HW_VER_UNKNOWN,
HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */
@@ -398,13 +402,14 @@ struct vring_tx_data {
};
enum { /* for wil6210_priv.status */
- wil_status_fwready = 0,
+ wil_status_fwready = 0, /* FW operational */
wil_status_fwconnecting,
wil_status_fwconnected,
wil_status_dontscan,
- wil_status_reset_done,
+ wil_status_mbox_ready, /* MBOX structures ready */
wil_status_irqen, /* FIXME: interrupts enabled - for debug */
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
+ wil_status_resetting, /* reset in progress */
wil_status_last /* keep last */
};
@@ -465,6 +470,9 @@ struct wil_net_stats {
unsigned long tx_bytes;
unsigned long tx_errors;
unsigned long rx_dropped;
+ unsigned long rx_non_data_frame;
+ unsigned long rx_short_frame;
+ unsigned long rx_large_frame;
u16 last_mcs_rx;
u64 rx_per_mcs[WIL_MCS_MAX + 1];
};
@@ -820,4 +828,6 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+void wil_fw_core_dump(struct wil6210_priv *wil);
+
#endif /* __WIL6210_H__ */
diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
new file mode 100644
index 000000000000..7e70934990ae
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
@@ -0,0 +1,115 @@
+/*
+ * 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 "wil6210.h"
+#include <linux/devcoredump.h>
+
+static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil,
+ u32 *out_dump_size, u32 *out_host_min)
+{
+ int i;
+ const struct fw_map *map;
+ u32 host_min, host_max, tmp_max;
+
+ if (!out_dump_size)
+ return -EINVAL;
+
+ /* calculate the total size of the unpacked crash dump */
+ BUILD_BUG_ON(ARRAY_SIZE(fw_mapping) == 0);
+ map = &fw_mapping[0];
+ host_min = map->host;
+ host_max = map->host + (map->to - map->from);
+
+ for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) {
+ map = &fw_mapping[i];
+
+ if (map->host < host_min)
+ host_min = map->host;
+
+ tmp_max = map->host + (map->to - map->from);
+ if (tmp_max > host_max)
+ host_max = tmp_max;
+ }
+
+ *out_dump_size = host_max - host_min;
+ if (out_host_min)
+ *out_host_min = host_min;
+
+ return 0;
+}
+
+static int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest,
+ u32 size)
+{
+ int i;
+ const struct fw_map *map;
+ void *data;
+ u32 host_min, dump_size, offset, len;
+
+ if (wil_fw_get_crash_dump_bounds(wil, &dump_size, &host_min)) {
+ wil_err(wil, "%s: fail to obtain crash dump size\n", __func__);
+ return -EINVAL;
+ }
+
+ if (dump_size > size) {
+ wil_err(wil, "%s: not enough space for dump. Need %d have %d\n",
+ __func__, dump_size, size);
+ return -EINVAL;
+ }
+
+ /* copy to crash dump area */
+ for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
+ map = &fw_mapping[i];
+
+ data = (void * __force)wil->csr + HOSTADDR(map->host);
+ len = map->to - map->from;
+ offset = map->host - host_min;
+
+ wil_dbg_misc(wil, "%s() - dump %s, size %d, offset %d\n",
+ __func__, fw_mapping[i].name, len, offset);
+
+ wil_memcpy_fromio_32((void * __force)(dest + offset),
+ (const void __iomem * __force)data, len);
+ }
+
+ return 0;
+}
+
+void wil_fw_core_dump(struct wil6210_priv *wil)
+{
+ void *fw_dump_data;
+ u32 fw_dump_size;
+
+ if (wil_fw_get_crash_dump_bounds(wil, &fw_dump_size, NULL)) {
+ wil_err(wil, "%s: fail to get fw dump size\n", __func__);
+ return;
+ }
+
+ fw_dump_data = vzalloc(fw_dump_size);
+ if (!fw_dump_data)
+ return;
+
+ if (wil_fw_copy_crash_dump(wil, fw_dump_data, fw_dump_size)) {
+ vfree(fw_dump_data);
+ return;
+ }
+ /* fw_dump_data will be free in device coredump release function
+ * after 5 min
+ */
+ dev_coredumpv(wil_to_dev(wil), fw_dump_data, fw_dump_size, GFP_KERNEL);
+ wil_info(wil, "%s: fw core dumped, size %d bytes\n", __func__,
+ fw_dump_size);
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 2f35d4c51f34..6ed26baca0e5 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -293,12 +293,6 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
/* ignore MAC address, we already have it from the boot loader */
snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
"%d", wil->fw_version);
-}
-
-static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
- int len)
-{
- wil_dbg_wmi(wil, "WMI: got FW ready event\n");
wil_set_recovery_state(wil, fw_recovery_idle);
set_bit(wil_status_fwready, wil->status);
@@ -684,13 +678,22 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
spin_unlock_bh(&sta->tid_rx_lock);
}
+/**
+ * Some events are ignored for purpose; and need not be interpreted as
+ * "unhandled events"
+ */
+static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
+{
+ wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
+}
+
static const struct {
int eventid;
void (*handler)(struct wil6210_priv *wil, int eventid,
void *data, int data_len);
} wmi_evt_handlers[] = {
{WMI_READY_EVENTID, wmi_evt_ready},
- {WMI_FW_READY_EVENTID, wmi_evt_fw_ready},
+ {WMI_FW_READY_EVENTID, wmi_evt_ignore},
{WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt},
{WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt},
{WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete},
@@ -701,6 +704,7 @@ static const struct {
{WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
{WMI_DELBA_EVENTID, wmi_evt_delba},
{WMI_VRING_EN_EVENTID, wmi_evt_vring_en},
+ {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
};
/*
@@ -720,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
ulong flags;
unsigned n;
- if (!test_bit(wil_status_reset_done, wil->status)) {
+ if (!test_bit(wil_status_mbox_ready, wil->status)) {
wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
return;
}
@@ -1120,7 +1124,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
cmd.sniffer_cfg.phy_support =
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
- ? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
+ ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
} else {
/* Initialize offload (in non-sniffer mode).
* Linux IP stack always calculates IP checksum
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 759fb8d41fc9..fba856032ca5 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -71,26 +71,6 @@ config B43_PCICORE_AUTOSELECT
select SSB_DRIVER_PCICORE
default y
-config B43_PCMCIA
- bool "Broadcom 43xx PCMCIA device support"
- depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE
- select SSB_PCMCIAHOST
- ---help---
- Broadcom 43xx PCMCIA device support.
-
- Support for 16bit PCMCIA devices.
- Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA
- devices, but 32bit CardBUS devices. CardBUS devices are supported
- out of the box by b43.
-
- With this config option you can drive b43 cards in
- CompactFlash formfactor in a PCMCIA adaptor.
- CF b43 cards can sometimes be found in handheld PCs.
-
- It's safe to select Y here, even if you don't have a B43 PCMCIA device.
-
- If unsure, say N.
-
config B43_SDIO
bool "Broadcom 43xx SDIO device support"
depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index c624d4d90e4f..ddc4df46656f 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -21,7 +21,6 @@ b43-y += pio.o
b43-y += rfkill.o
b43-y += ppr.o
b43-$(CONFIG_B43_LEDS) += leds.o
-b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
b43-$(CONFIG_B43_SDIO) += sdio.o
b43-$(CONFIG_B43_DEBUG) += debugfs.o
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index e807bd930647..b4bcd94aff6c 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -676,15 +676,15 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
e->dyn_debug_dentries[id] = d; \
} while (0)
- add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, 0);
- add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, 0);
- add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0);
- add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0);
- add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
- add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
- add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
- add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
- add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0);
+ add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false);
+ add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false);
+ add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, false);
+ add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, false);
+ add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, false);
+ add_dyn_dbg("debug_lo", B43_DBG_LO, false);
+ add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, false);
+ add_dyn_dbg("debug_keys", B43_DBG_KEYS, false);
+ add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, false);
#undef add_dyn_dbg
}
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index 50517b801cb4..d05377745011 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -68,7 +68,7 @@ struct b43_dfsentry {
u32 shm32read_addr_next;
/* Enabled/Disabled list for the dynamic debugging features. */
- u32 dyn_debug[__B43_NR_DYNDBG];
+ bool dyn_debug[__B43_NR_DYNDBG];
/* Dentries for the dynamic debugging entries. */
struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG];
};
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 28490702124a..ec013fbd6a81 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -56,7 +56,6 @@
#include "sysfs.h"
#include "xmit.h"
#include "lo.h"
-#include "pcmcia.h"
#include "sdio.h"
#include <linux/mmc/sdio_func.h>
@@ -120,6 +119,7 @@ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if over
#ifdef CONFIG_B43_BCMA
static const struct bcma_device_id b43_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x15, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
@@ -5849,12 +5849,9 @@ static int __init b43_init(void)
int err;
b43_debugfs_init();
- err = b43_pcmcia_init();
- if (err)
- goto err_dfs_exit;
err = b43_sdio_init();
if (err)
- goto err_pcmcia_exit;
+ goto err_dfs_exit;
#ifdef CONFIG_B43_BCMA
err = bcma_driver_register(&b43_bcma_driver);
if (err)
@@ -5877,8 +5874,6 @@ err_bcma_driver_exit:
err_sdio_exit:
#endif
b43_sdio_exit();
-err_pcmcia_exit:
- b43_pcmcia_exit();
err_dfs_exit:
b43_debugfs_exit();
return err;
@@ -5893,7 +5888,6 @@ static void __exit b43_exit(void)
bcma_driver_unregister(&b43_bcma_driver);
#endif
b43_sdio_exit();
- b43_pcmcia_exit();
b43_debugfs_exit();
}
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
deleted file mode 100644
index 55f2bd7f8f74..000000000000
--- a/drivers/net/wireless/b43/pcmcia.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-
- Broadcom B43 wireless driver
-
- Copyright (c) 2007 Michael Buesch <m@bues.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.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT 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; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
-*/
-
-#include "pcmcia.h"
-
-#include <linux/ssb/ssb.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-
-static const struct pcmcia_device_id b43_pcmcia_tbl[] = {
- PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
- PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
- PCMCIA_DEVICE_NULL,
-};
-
-MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
-
-#ifdef CONFIG_PM
-static int b43_pcmcia_suspend(struct pcmcia_device *dev)
-{
- struct ssb_bus *ssb = dev->priv;
-
- return ssb_bus_suspend(ssb);
-}
-
-static int b43_pcmcia_resume(struct pcmcia_device *dev)
-{
- struct ssb_bus *ssb = dev->priv;
-
- return ssb_bus_resume(ssb);
-}
-#else /* CONFIG_PM */
-# define b43_pcmcia_suspend NULL
-# define b43_pcmcia_resume NULL
-#endif /* CONFIG_PM */
-
-static int b43_pcmcia_probe(struct pcmcia_device *dev)
-{
- struct ssb_bus *ssb;
- int err = -ENOMEM;
- int res = 0;
-
- ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
- if (!ssb)
- goto out_error;
-
- err = -ENODEV;
-
- dev->config_flags |= CONF_ENABLE_IRQ;
-
- dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
- WIN_USE_WAIT;
- dev->resource[2]->start = 0;
- dev->resource[2]->end = SSB_CORE_SIZE;
- res = pcmcia_request_window(dev, dev->resource[2], 250);
- if (res != 0)
- goto err_kfree_ssb;
-
- res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
- if (res != 0)
- goto err_disable;
-
- if (!dev->irq)
- goto err_disable;
-
- res = pcmcia_enable_device(dev);
- if (res != 0)
- goto err_disable;
-
- err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
- if (err)
- goto err_disable;
- dev->priv = ssb;
-
- return 0;
-
-err_disable:
- pcmcia_disable_device(dev);
-err_kfree_ssb:
- kfree(ssb);
-out_error:
- printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
- res, err);
- return err;
-}
-
-static void b43_pcmcia_remove(struct pcmcia_device *dev)
-{
- struct ssb_bus *ssb = dev->priv;
-
- ssb_bus_unregister(ssb);
- pcmcia_disable_device(dev);
- kfree(ssb);
- dev->priv = NULL;
-}
-
-static struct pcmcia_driver b43_pcmcia_driver = {
- .owner = THIS_MODULE,
- .name = "b43-pcmcia",
- .id_table = b43_pcmcia_tbl,
- .probe = b43_pcmcia_probe,
- .remove = b43_pcmcia_remove,
- .suspend = b43_pcmcia_suspend,
- .resume = b43_pcmcia_resume,
-};
-
-/*
- * These are not module init/exit functions!
- * The module_pcmcia_driver() helper cannot be used here.
- */
-int b43_pcmcia_init(void)
-{
- return pcmcia_register_driver(&b43_pcmcia_driver);
-}
-
-void b43_pcmcia_exit(void)
-{
- pcmcia_unregister_driver(&b43_pcmcia_driver);
-}
diff --git a/drivers/net/wireless/b43/pcmcia.h b/drivers/net/wireless/b43/pcmcia.h
deleted file mode 100644
index 85f120a67cbe..000000000000
--- a/drivers/net/wireless/b43/pcmcia.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef B43_PCMCIA_H_
-#define B43_PCMCIA_H_
-
-#ifdef CONFIG_B43_PCMCIA
-
-int b43_pcmcia_init(void);
-void b43_pcmcia_exit(void);
-
-#else /* CONFIG_B43_PCMCIA */
-
-static inline int b43_pcmcia_init(void)
-{
- return 0;
-}
-static inline void b43_pcmcia_exit(void)
-{
-}
-
-#endif /* CONFIG_B43_PCMCIA */
-#endif /* B43_PCMCIA_H_ */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 1965edb765a2..090910ea259e 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -369,11 +369,11 @@ static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev)
e->dyn_debug_dentries[id] = d; \
} while (0)
- add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, 0);
- add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, 0);
- add_dyn_dbg("debug_dmaverbose", B43legacy_DBG_DMAVERBOSE, 0);
- add_dyn_dbg("debug_pwork_fast", B43legacy_DBG_PWORK_FAST, 0);
- add_dyn_dbg("debug_pwork_stop", B43legacy_DBG_PWORK_STOP, 0);
+ add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, false);
+ add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, false);
+ add_dyn_dbg("debug_dmaverbose", B43legacy_DBG_DMAVERBOSE, false);
+ add_dyn_dbg("debug_pwork_fast", B43legacy_DBG_PWORK_FAST, false);
+ add_dyn_dbg("debug_pwork_stop", B43legacy_DBG_PWORK_STOP, false);
#undef add_dyn_dbg
}
diff --git a/drivers/net/wireless/b43legacy/debugfs.h b/drivers/net/wireless/b43legacy/debugfs.h
index ae3b0d0fa849..9ee32158b947 100644
--- a/drivers/net/wireless/b43legacy/debugfs.h
+++ b/drivers/net/wireless/b43legacy/debugfs.h
@@ -47,7 +47,7 @@ struct b43legacy_dfsentry {
struct b43legacy_txstatus_log txstatlog;
/* Enabled/Disabled list for the dynamic debugging features. */
- u32 dyn_debug[__B43legacy_NR_DYNDBG];
+ bool dyn_debug[__B43legacy_NR_DYNDBG];
/* Dentries for the dynamic debugging entries. */
struct dentry *dyn_debug_dentries[__B43legacy_NR_DYNDBG];
};
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index fe3dc126b149..ab42b1fea03c 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -82,5 +82,6 @@ config BRCM_TRACING
config BRCMDBG
bool "Broadcom driver debug functions"
depends on BRCMSMAC || BRCMFMAC
+ select WANT_DEV_COREDUMP
---help---
Selecting this enables additional code for debug purposes.
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
index 8e0e91c4a0b1..288c84e7c56b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
@@ -272,10 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
}
static int
-brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
- struct sk_buff *pktbuf)
+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+ struct sk_buff *pktbuf, struct brcmf_if **ifp)
{
struct brcmf_proto_bcdc_header *h;
+ struct brcmf_if *tmp_if;
brcmf_dbg(BCDC, "Enter\n");
@@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
trace_brcmf_bcdchdr(pktbuf->data);
h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
- *ifidx = BCDC_GET_IF_IDX(h);
- if (*ifidx >= BRCMF_MAX_IFS) {
- brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
+ tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+ if (!tmp_if) {
+ brcmf_dbg(INFO, "no matching ifp found\n");
return -EBADE;
}
- /* The ifidx is the idx to map to matching netdev/ifp. When receiving
- * events this is easy because it contains the bssidx which maps
- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
- * bssidx 1 is used for p2p0 and no data can be received or
- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
- */
- if (*ifidx)
- (*ifidx)++;
-
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(drvr, *ifidx), h->flags);
+ brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
return -EBADE;
}
if (h->flags & BCDC_FLAG_SUM_GOOD) {
brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
- brcmf_ifname(drvr, *ifidx), h->flags);
+ brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
}
@@ -320,12 +312,14 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
skb_pull(pktbuf, BCDC_HEADER_LEN);
if (do_fws)
- brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
+ brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf);
else
skb_pull(pktbuf, h->data_offset << 2);
if (pktbuf->len == 0)
return -ENODATA;
+
+ *ifp = tmp_if;
return 0;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
index 0445163991b7..4e33f96b3dd1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
@@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data)
static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
bool trump_sco)
{
- struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
+ struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0);
if (trump_sco && !btci->saved_regs_part2) {
/* this should reduce eSCO agressive
@@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
{
struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
struct brcmf_btcoex_info *btci = cfg->btcoex;
- struct brcmf_if *ifp = cfg->pub->iflist[0];
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
switch (mode) {
case BRCMF_BTCOEX_DISABLED:
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
index 89e6a4dc105e..230cad788ace 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
@@ -65,6 +65,8 @@ struct brcmf_bus_dcmd {
* @rxctl: receive a control response message from dongle.
* @gettxq: obtain a reference of bus transmit queue (optional).
* @wowl_config: specify if dongle is configured for wowl when going to suspend
+ * @get_ramsize: obtain size of device memory.
+ * @get_memdump: obtain device memory dump in provided buffer.
*
* This structure provides an abstract interface towards the
* bus specific driver. For control messages to common driver
@@ -79,6 +81,8 @@ struct brcmf_bus_ops {
int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
struct pktq * (*gettxq)(struct device *dev);
void (*wowl_config)(struct device *dev, bool enabled);
+ size_t (*get_ramsize)(struct device *dev);
+ int (*get_memdump)(struct device *dev, void *data, size_t len);
};
@@ -185,6 +189,23 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled)
bus->ops->wowl_config(bus->dev, enabled);
}
+static inline size_t brcmf_bus_get_ramsize(struct brcmf_bus *bus)
+{
+ if (!bus->ops->get_ramsize)
+ return 0;
+
+ return bus->ops->get_ramsize(bus->dev);
+}
+
+static inline
+int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
+{
+ if (!bus->ops->get_memdump)
+ return -EOPNOTSUPP;
+
+ return bus->ops->get_memdump(bus->dev, data, len);
+}
+
/*
* interface functions from common layer
*/
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
index a293275c1b0b..deb5f78dcacc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -236,89 +236,6 @@ static int brcmf_roamoff;
module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
MODULE_PARM_DESC(roamoff, "do not use internal roaming engine");
-/* Quarter dBm units to mW
- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
- * Table is offset so the last entry is largest mW value that fits in
- * a u16.
- */
-
-#define QDBM_OFFSET 153 /* Offset for first entry */
-#define QDBM_TABLE_LEN 40 /* Table size */
-
-/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
- * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
- */
-#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
-
-/* Largest mW value that will round down to the last table entry,
- * QDBM_OFFSET + QDBM_TABLE_LEN-1.
- * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
- * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
- */
-#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
-
-static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
-/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
-/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
-/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
-/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
-/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
-/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
-};
-
-static u16 brcmf_qdbm_to_mw(u8 qdbm)
-{
- uint factor = 1;
- int idx = qdbm - QDBM_OFFSET;
-
- if (idx >= QDBM_TABLE_LEN)
- /* clamp to max u16 mW value */
- return 0xFFFF;
-
- /* scale the qdBm index up to the range of the table 0-40
- * where an offset of 40 qdBm equals a factor of 10 mW.
- */
- while (idx < 0) {
- idx += 40;
- factor *= 10;
- }
-
- /* return the mW value scaled down to the correct factor of 10,
- * adding in factor/2 to get proper rounding.
- */
- return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
-}
-
-static u8 brcmf_mw_to_qdbm(u16 mw)
-{
- u8 qdbm;
- int offset;
- uint mw_uint = mw;
- uint boundary;
-
- /* handle boundary case */
- if (mw_uint <= 1)
- return 0;
-
- offset = QDBM_OFFSET;
-
- /* move mw into the range of the table */
- while (mw_uint < QDBM_TABLE_LOW_BOUND) {
- mw_uint *= 10;
- offset -= 40;
- }
-
- for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
- boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
- nqdBm_to_mW_map[qdbm]) / 2;
- if (mw_uint < boundary)
- break;
- }
-
- qdbm += (u8) offset;
-
- return qdbm;
-}
static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
struct cfg80211_chan_def *ch)
@@ -860,6 +777,37 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
s32 err = 0;
brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
+
+ /* WAR: There are a number of p2p interface related problems which
+ * need to be handled initially (before doing the validate).
+ * wpa_supplicant tends to do iface changes on p2p device/client/go
+ * which are not always possible/allowed. However we need to return
+ * OK otherwise the wpa_supplicant wont start. The situation differs
+ * on configuration and setup (p2pon=1 module param). The first check
+ * is to see if the request is a change to station for p2p iface.
+ */
+ if ((type == NL80211_IFTYPE_STATION) &&
+ ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||
+ (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ||
+ (vif->wdev.iftype == NL80211_IFTYPE_P2P_DEVICE))) {
+ brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");
+ /* Now depending on whether module param p2pon=1 was used the
+ * response needs to be either 0 or EOPNOTSUPP. The reason is
+ * that if p2pon=1 is used, but a newer supplicant is used then
+ * we should return an error, as this combination wont work.
+ * In other situations 0 is returned and supplicant will start
+ * normally. It will give a trace in cfg80211, but it is the
+ * only way to get it working. Unfortunately this will result
+ * in situation where we wont support new supplicant in
+ * combination with module param p2pon=1, but that is the way
+ * it is. If the user tries this then unloading of driver might
+ * fail/lock.
+ */
+ if (cfg->p2p.p2pdev_dynamically)
+ return -EOPNOTSUPP;
+ else
+ return 0;
+ }
err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
if (err) {
brcmf_err("iface validation failed: err=%d\n", err);
@@ -875,18 +823,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
infra = 0;
break;
case NL80211_IFTYPE_STATION:
- /* Ignore change for p2p IF. Unclear why supplicant does this */
- if ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||
- (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) {
- brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");
- /* WAR: It is unexpected to get a change of VIF for P2P
- * IF, but it happens. The request can not be handled
- * but returning EPERM causes a crash. Returning 0
- * without setting ieee80211_ptr->iftype causes trace
- * (WARN_ON) but it works with wpa_supplicant
- */
- return 0;
- }
infra = 1;
break;
case NL80211_IFTYPE_AP:
@@ -904,7 +840,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO);
}
if (!err) {
- set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state);
brcmf_dbg(INFO, "IF Type = AP\n");
}
} else {
@@ -2017,16 +1952,14 @@ static s32
brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, s32 mbm)
{
-
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
struct brcmf_if *ifp = netdev_priv(ndev);
- u16 txpwrmw;
- s32 err = 0;
- s32 disable = 0;
- s32 dbm = MBM_TO_DBM(mbm);
+ s32 err;
+ s32 disable;
+ u32 qdbm = 127;
- brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm);
if (!check_vif_up(ifp->vif))
return -EIO;
@@ -2035,12 +1968,20 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
break;
case NL80211_TX_POWER_LIMITED:
case NL80211_TX_POWER_FIXED:
- if (dbm < 0) {
+ if (mbm < 0) {
brcmf_err("TX_POWER_FIXED - dbm is negative\n");
err = -EINVAL;
goto done;
}
+ qdbm = MBM_TO_DBM(4 * mbm);
+ if (qdbm > 127)
+ qdbm = 127;
+ qdbm |= WL_TXPWR_OVERRIDE;
break;
+ default:
+ brcmf_err("Unsupported type %d\n", type);
+ err = -EINVAL;
+ goto done;
}
/* Make sure radio is off or on as far as software is concerned */
disable = WL_RADIO_SW_DISABLE << 16;
@@ -2048,52 +1989,44 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
if (err)
brcmf_err("WLC_SET_RADIO error (%d)\n", err);
- if (dbm > 0xffff)
- txpwrmw = 0xffff;
- else
- txpwrmw = (u16) dbm;
- err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
- (s32)brcmf_mw_to_qdbm(txpwrmw));
+ err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm);
if (err)
brcmf_err("qtxpower error (%d)\n", err);
- cfg->conf->tx_power = dbm;
done:
- brcmf_dbg(TRACE, "Exit\n");
+ brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE);
return err;
}
-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy,
- struct wireless_dev *wdev,
- s32 *dbm)
+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_if *ifp = netdev_priv(cfg_to_ndev(cfg));
- s32 txpwrdbm;
- u8 result;
- s32 err = 0;
+ struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ s32 qdbm = 0;
+ s32 err;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
- err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
+ err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm);
if (err) {
brcmf_err("error (%d)\n", err);
goto done;
}
-
- result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
- *dbm = (s32) brcmf_qdbm_to_mw(result);
+ *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4;
done:
- brcmf_dbg(TRACE, "Exit\n");
+ brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm);
return err;
}
static s32
brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_idx, bool unicast, bool multicast)
+ u8 key_idx, bool unicast, bool multicast)
{
struct brcmf_if *ifp = netdev_priv(ndev);
u32 index;
@@ -2498,6 +2431,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_sta_info_le sta_info_le;
u32 sta_flags;
u32 is_tdls_peer;
+ s32 total_rssi;
+ s32 count_rssi;
+ u32 i;
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
if (!check_vif_up(ifp->vif))
@@ -2544,13 +2480,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
if (sinfo->tx_packets) {
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
- sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
- sinfo->txrate.legacy /= 100;
+ sinfo->txrate.legacy =
+ le32_to_cpu(sta_info_le.tx_rate) / 100;
}
if (sinfo->rx_packets) {
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
- sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
- sinfo->rxrate.legacy /= 100;
+ sinfo->rxrate.legacy =
+ le32_to_cpu(sta_info_le.rx_rate) / 100;
}
if (le16_to_cpu(sta_info_le.ver) >= 4) {
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
@@ -2558,12 +2494,61 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
}
+ total_rssi = 0;
+ count_rssi = 0;
+ for (i = 0; i < BRCMF_ANT_MAX; i++) {
+ if (sta_info_le.rssi[i]) {
+ sinfo->chain_signal_avg[count_rssi] =
+ sta_info_le.rssi[i];
+ sinfo->chain_signal[count_rssi] =
+ sta_info_le.rssi[i];
+ total_rssi += sta_info_le.rssi[i];
+ count_rssi++;
+ }
+ }
+ if (count_rssi) {
+ sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL);
+ sinfo->chains = count_rssi;
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+ total_rssi /= count_rssi;
+ sinfo->signal = total_rssi;
+ }
}
done:
brcmf_dbg(TRACE, "Exit\n");
return err;
}
+static int
+brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
+ int idx, u8 *mac, struct station_info *sinfo)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ s32 err;
+
+ brcmf_dbg(TRACE, "Enter, idx %d\n", idx);
+
+ if (idx == 0) {
+ cfg->assoclist.count = cpu_to_le32(BRCMF_MAX_ASSOCLIST);
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_ASSOCLIST,
+ &cfg->assoclist,
+ sizeof(cfg->assoclist));
+ if (err) {
+ brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n",
+ err);
+ cfg->assoclist.count = 0;
+ return -EOPNOTSUPP;
+ }
+ }
+ if (idx < le32_to_cpu(cfg->assoclist.count)) {
+ memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN);
+ return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo);
+ }
+ return -ENOENT;
+}
+
static s32
brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
bool enabled, s32 timeout)
@@ -4265,8 +4250,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_dbg(TRACE, "GO mode configuration complete\n");
}
- clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+ brcmf_net_setcarrier(ifp, true);
exit:
if ((err) && (!mbss)) {
@@ -4330,8 +4315,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
}
brcmf_set_mpc(ifp, 1);
brcmf_configure_arp_offload(ifp, true);
- set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+ brcmf_net_setcarrier(ifp, false);
return err;
}
@@ -4663,6 +4648,7 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.join_ibss = brcmf_cfg80211_join_ibss,
.leave_ibss = brcmf_cfg80211_leave_ibss,
.get_station = brcmf_cfg80211_get_station,
+ .dump_station = brcmf_cfg80211_dump_station,
.set_tx_power = brcmf_cfg80211_set_tx_power,
.get_tx_power = brcmf_cfg80211_get_tx_power,
.add_key = brcmf_cfg80211_add_key,
@@ -4747,7 +4733,8 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)
ifp = netdev_priv(ndev);
vif = ifp->vif;
- brcmf_free_vif(vif);
+ if (vif)
+ brcmf_free_vif(vif);
free_netdev(ndev);
}
@@ -4983,7 +4970,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
brcmf_dbg(CONN, "AP mode link down\n");
complete(&cfg->vif_disabled);
if (ifp->vif->mbss)
- brcmf_remove_interface(ifp->drvr, ifp->bssidx);
+ brcmf_remove_interface(ifp);
return 0;
}
@@ -5039,6 +5026,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
&ifp->vif->sme_state);
} else
brcmf_bss_connect_done(cfg, ndev, e, true);
+ brcmf_net_setcarrier(ifp, true);
} else if (brcmf_is_linkdown(e)) {
brcmf_dbg(CONN, "Linkdown\n");
if (!brcmf_is_ibssmode(ifp->vif)) {
@@ -5048,6 +5036,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
brcmf_init_prof(ndev_to_prof(ndev));
if (ndev != cfg_to_ndev(cfg))
complete(&cfg->vif_disabled);
+ brcmf_net_setcarrier(ifp, false);
} else if (brcmf_is_nonetwork(cfg, e)) {
if (brcmf_is_ibssmode(ifp->vif))
clear_bit(BRCMF_VIF_STATUS_CONNECTING,
@@ -6211,9 +6200,10 @@ static void brcmf_free_wiphy(struct wiphy *wiphy)
}
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
- struct device *busdev)
+ struct device *busdev,
+ bool p2pdev_forced)
{
- struct net_device *ndev = drvr->iflist[0]->ndev;
+ struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
struct brcmf_cfg80211_info *cfg;
struct wiphy *wiphy;
struct brcmf_cfg80211_vif *vif;
@@ -6302,8 +6292,19 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
else
*cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
}
+ /* p2p might require that "if-events" get processed by fweh. So
+ * activate the already registered event handlers now and activate
+ * the rest when initialization has completed. drvr->config needs to
+ * be assigned before activating events.
+ */
+ drvr->config = cfg;
+ err = brcmf_fweh_activate_events(ifp);
+ if (err) {
+ brcmf_err("FWEH activation failed (%d)\n", err);
+ goto wiphy_unreg_out;
+ }
- err = brcmf_p2p_attach(cfg);
+ err = brcmf_p2p_attach(cfg, p2pdev_forced);
if (err) {
brcmf_err("P2P initilisation failed (%d)\n", err);
goto wiphy_unreg_out;
@@ -6324,6 +6325,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
brcmf_notify_tdls_peer_event);
}
+ /* (re-) activate FWEH event handling */
+ err = brcmf_fweh_activate_events(ifp);
+ if (err) {
+ brcmf_err("FWEH activation failed (%d)\n", err);
+ goto wiphy_unreg_out;
+ }
+
return cfg;
wiphy_unreg_out:
@@ -6331,6 +6339,7 @@ wiphy_unreg_out:
priv_out:
wl_deinit_priv(cfg);
brcmf_free_vif(vif);
+ ifp->vif = NULL;
wiphy_out:
brcmf_free_wiphy(wiphy);
return NULL;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
index d9e6d01b2b69..6a878c8f883f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
@@ -143,7 +143,6 @@ struct brcmf_cfg80211_profile {
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
- * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
*/
enum brcmf_vif_status {
@@ -151,7 +150,6 @@ enum brcmf_vif_status {
BRCMF_VIF_STATUS_CONNECTING,
BRCMF_VIF_STATUS_CONNECTED,
BRCMF_VIF_STATUS_DISCONNECTING,
- BRCMF_VIF_STATUS_AP_CREATING,
BRCMF_VIF_STATUS_AP_CREATED
};
@@ -407,6 +405,7 @@ struct brcmf_cfg80211_info {
struct brcmu_d11inf d11inf;
bool wowl_enabled;
u32 pre_wowl_pmmode;
+ struct brcmf_assoclist_le assoclist;
};
/**
@@ -469,7 +468,8 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
}
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
- struct device *busdev);
+ struct device *busdev,
+ bool p2pdev_forced);
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
s32 brcmf_cfg80211_up(struct net_device *ndev);
s32 brcmf_cfg80211_down(struct net_device *ndev);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index 288f8314f208..f04833db2fd0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -101,6 +101,9 @@
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE 0x18002000
+/* Max possibly supported memory size (limited by IO mapped memory) */
+#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024)
+
#define CORE_SB(base, field) \
(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
#define SBCOREREV(sbidh) \
@@ -205,6 +208,7 @@ struct sbsocramregs {
};
#define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f)
+#define SYSMEMREGOFFS(_f) offsetof(struct sbsocramregs, _f)
#define ARMCR4_CAP (0x04)
#define ARMCR4_BANKIDX (0x40)
@@ -513,6 +517,9 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
case BCMA_CORE_ARM_CR4:
cpu_found = true;
break;
+ case BCMA_CORE_ARM_CA7:
+ cpu_found = true;
+ break;
default:
break;
}
@@ -611,6 +618,29 @@ static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,
}
}
+/** Return the SYS MEM size */
+static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem)
+{
+ u32 memsize = 0;
+ u32 coreinfo;
+ u32 idx;
+ u32 nb;
+ u32 banksize;
+
+ if (!brcmf_chip_iscoreup(&sysmem->pub))
+ brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0);
+
+ coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo));
+ nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+
+ for (idx = 0; idx < nb; idx++) {
+ brcmf_chip_socram_banksize(sysmem, idx, &banksize);
+ memsize += banksize;
+ }
+
+ return memsize;
+}
+
/** Return the TCM-RAM size of the ARMCR4 core. */
static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
{
@@ -644,6 +674,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
return 0x198000;
case BRCM_CC_4335_CHIP_ID:
case BRCM_CC_4339_CHIP_ID:
+ case BRCM_CC_4350_CHIP_ID:
case BRCM_CC_4354_CHIP_ID:
case BRCM_CC_4356_CHIP_ID:
case BRCM_CC_43567_CHIP_ID:
@@ -651,7 +682,11 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
case BRCM_CC_43570_CHIP_ID:
case BRCM_CC_4358_CHIP_ID:
case BRCM_CC_43602_CHIP_ID:
+ case BRCM_CC_4371_CHIP_ID:
return 0x180000;
+ case BRCM_CC_4365_CHIP_ID:
+ case BRCM_CC_4366_CHIP_ID:
+ return 0x200000;
default:
brcmf_err("unknown chip: %s\n", ci->pub.name);
break;
@@ -674,10 +709,28 @@ static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
return -EINVAL;
}
} else {
- mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM);
- mem_core = container_of(mem, struct brcmf_core_priv, pub);
- brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
- &ci->pub.srsize);
+ mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM);
+ if (mem) {
+ mem_core = container_of(mem, struct brcmf_core_priv,
+ pub);
+ ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core);
+ ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
+ if (!ci->pub.rambase) {
+ brcmf_err("RAM base not provided with ARM CA7 core\n");
+ return -EINVAL;
+ }
+ } else {
+ mem = brcmf_chip_get_core(&ci->pub,
+ BCMA_CORE_INTERNAL_MEM);
+ if (!mem) {
+ brcmf_err("No memory cores found\n");
+ return -ENOMEM;
+ }
+ mem_core = container_of(mem, struct brcmf_core_priv,
+ pub);
+ brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
+ &ci->pub.srsize);
+ }
}
brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",
ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,
@@ -687,6 +740,12 @@ static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
brcmf_err("RAM size is undetermined\n");
return -ENOMEM;
}
+
+ if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
+ brcmf_err("RAM size is incorrect\n");
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -899,13 +958,22 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
/* assure chip is passive for core access */
brcmf_chip_set_passive(&ci->pub);
+
+ /* Call bus specific reset function now. Cores have been determined
+ * but further access may require a chip specific reset at this point.
+ */
+ if (ci->ops->reset) {
+ ci->ops->reset(ci->ctx, &ci->pub);
+ brcmf_chip_set_passive(&ci->pub);
+ }
+
return brcmf_chip_get_raminfo(ci);
}
static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
{
struct brcmf_core *core;
- struct brcmf_core_priv *cr4;
+ struct brcmf_core_priv *cpu;
u32 val;
@@ -918,10 +986,11 @@ static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
brcmf_chip_coredisable(core, 0, 0);
break;
case BCMA_CORE_ARM_CR4:
- cr4 = container_of(core, struct brcmf_core_priv, pub);
+ case BCMA_CORE_ARM_CA7:
+ cpu = container_of(core, struct brcmf_core_priv, pub);
/* clear all IOCTL bits except HALT bit */
- val = chip->ops->read32(chip->ctx, cr4->wrapbase + BCMA_IOCTL);
+ val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL);
val &= ARMCR4_BCMA_IOCTL_CPUHALT;
brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
ARMCR4_BCMA_IOCTL_CPUHALT);
@@ -1143,6 +1212,33 @@ static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
return true;
}
+static inline void
+brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip)
+{
+ struct brcmf_core *core;
+
+ brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7);
+
+ core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+ brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
+ D11_BCMA_IOCTL_PHYCLOCKEN,
+ D11_BCMA_IOCTL_PHYCLOCKEN,
+ D11_BCMA_IOCTL_PHYCLOCKEN);
+}
+
+static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
+{
+ struct brcmf_core *core;
+
+ chip->ops->activate(chip->ctx, &chip->pub, rstvec);
+
+ /* restore ARM */
+ core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7);
+ brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
+
+ return true;
+}
+
void brcmf_chip_set_passive(struct brcmf_chip *pub)
{
struct brcmf_chip_priv *chip;
@@ -1156,8 +1252,16 @@ void brcmf_chip_set_passive(struct brcmf_chip *pub)
brcmf_chip_cr4_set_passive(chip);
return;
}
-
- brcmf_chip_cm3_set_passive(chip);
+ arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
+ if (arm) {
+ brcmf_chip_ca7_set_passive(chip);
+ return;
+ }
+ arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
+ if (arm) {
+ brcmf_chip_cm3_set_passive(chip);
+ return;
+ }
}
bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)
@@ -1171,8 +1275,14 @@ bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)
arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
if (arm)
return brcmf_chip_cr4_set_active(chip, rstvec);
+ arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
+ if (arm)
+ return brcmf_chip_ca7_set_active(chip, rstvec);
+ arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
+ if (arm)
+ return brcmf_chip_cm3_set_active(chip);
- return brcmf_chip_cm3_set_active(chip);
+ return false;
}
bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
index 60dcb38fc77a..f6b5feea23d2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
@@ -73,6 +73,7 @@ struct brcmf_buscore_ops {
u32 (*read32)(void *ctx, u32 addr);
void (*write32)(void *ctx, u32 addr, u32 value);
int (*prepare)(void *ctx);
+ int (*reset)(void *ctx, struct brcmf_chip *chip);
int (*setup)(void *ctx, struct brcmf_chip *chip);
void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
};
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.h b/drivers/net/wireless/brcm80211/brcmfmac/common.h
index 0d39d80cee28..21c7488b4732 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/common.h
@@ -17,4 +17,7 @@
extern const u8 ALLFFMAC[ETH_ALEN];
+/* Sets dongle media info (drv_version, mac address). */
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+
#endif /* BRCMFMAC_COMMON_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index fe9d3fbf5fe2..b5ab98ee1445 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -33,6 +33,7 @@
#include "feature.h"
#include "proto.h"
#include "pcie.h"
+#include "common.h"
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -53,6 +54,8 @@ MODULE_LICENSE("Dual BSD/GPL");
#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
#define BRCMF_RXREORDER_NEW_HOLE 0x10
+#define BRCMF_BSSIDX_INVALID -1
+
/* Error bits */
int brcmf_msg_level;
module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
@@ -60,10 +63,8 @@ MODULE_PARM_DESC(debug, "level of debug output");
/* P2P0 enable */
static int brcmf_p2p_enable;
-#ifdef CONFIG_BRCMDBG
module_param_named(p2pon, brcmf_p2p_enable, int, 0);
-MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
-#endif
+MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality");
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
{
@@ -83,6 +84,24 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
return "<if_none>";
}
+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
+{
+ struct brcmf_if *ifp;
+ s32 bssidx;
+
+ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+ brcmf_err("ifidx %d out of range\n", ifidx);
+ return NULL;
+ }
+
+ ifp = NULL;
+ bssidx = drvr->if2bss[ifidx];
+ if (bssidx >= 0)
+ ifp = drvr->iflist[bssidx];
+
+ return ifp;
+}
+
static void _brcmf_set_multicast_list(struct work_struct *work)
{
struct brcmf_if *ifp;
@@ -520,17 +539,15 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
struct brcmf_skb_reorder_data *rd;
- u8 ifidx;
int ret;
brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
/* process and remove protocol-specific header */
- ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb);
- ifp = drvr->iflist[ifidx];
+ ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
if (ret || !ifp || !ifp->ndev) {
- if ((ret != -ENODATA) && ifp)
+ if (ret != -ENODATA && ifp)
ifp->stats.rx_errors++;
brcmu_pkt_buf_free_skb(skb);
return;
@@ -543,17 +560,11 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
brcmf_netif_rx(ifp, skb);
}
-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
- bool success)
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
{
- struct brcmf_if *ifp;
struct ethhdr *eh;
u16 type;
- ifp = drvr->iflist[ifidx];
- if (!ifp)
- goto done;
-
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);
@@ -565,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
if (!success)
ifp->stats.tx_errors++;
-done:
+
brcmu_pkt_buf_free_skb(txp);
}
@@ -573,17 +584,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
- u8 ifidx;
+ struct brcmf_if *ifp;
/* await txstatus signal for firmware if active */
if (brcmf_fws_fc_active(drvr->fws)) {
if (!success)
brcmf_fws_bustxfail(drvr->fws, txp);
} else {
- if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
+ if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
brcmu_pkt_buf_free_skb(txp);
else
- brcmf_txfinalize(drvr, txp, ifidx, success);
+ brcmf_txfinalize(ifp, txp, success);
}
}
@@ -624,8 +635,7 @@ static int brcmf_netdev_stop(struct net_device *ndev)
brcmf_cfg80211_down(ndev);
- /* Set state and stop OS transmissions */
- netif_stop_queue(ndev);
+ brcmf_net_setcarrier(ifp, false);
return 0;
}
@@ -659,8 +669,8 @@ static int brcmf_netdev_open(struct net_device *ndev)
return -EIO;
}
- /* Allow transmit calls */
- netif_start_queue(ndev);
+ /* Clear, carrier, set when connected or AP mode. */
+ netif_carrier_off(ndev);
return 0;
}
@@ -708,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
}
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
-
- ndev->destructor = brcmf_cfg80211_free_netdev;
return 0;
fail:
@@ -719,6 +727,32 @@ fail:
return -EBADE;
}
+static void brcmf_net_detach(struct net_device *ndev)
+{
+ if (ndev->reg_state == NETREG_REGISTERED)
+ unregister_netdev(ndev);
+ else
+ brcmf_cfg80211_free_netdev(ndev);
+}
+
+void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
+{
+ struct net_device *ndev;
+
+ brcmf_dbg(TRACE, "Enter, idx=%d carrier=%d\n", ifp->bssidx, on);
+
+ ndev = ifp->ndev;
+ brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on);
+ if (on) {
+ if (!netif_carrier_ok(ndev))
+ netif_carrier_on(ndev);
+
+ } else {
+ if (netif_carrier_ok(ndev))
+ netif_carrier_off(ndev);
+ }
+}
+
static int brcmf_net_p2p_open(struct net_device *ndev)
{
brcmf_dbg(TRACE, "Enter\n");
@@ -778,7 +812,7 @@ fail:
}
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
- char *name, u8 *mac_addr)
+ bool is_p2pdev, char *name, u8 *mac_addr)
{
struct brcmf_if *ifp;
struct net_device *ndev;
@@ -795,8 +829,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
ifp->ndev->name);
if (ifidx) {
netif_stop_queue(ifp->ndev);
- unregister_netdev(ifp->ndev);
- free_netdev(ifp->ndev);
+ brcmf_net_detach(ifp->ndev);
drvr->iflist[bssidx] = NULL;
} else {
brcmf_err("ignore IF event\n");
@@ -804,7 +837,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
}
}
- if (!brcmf_p2p_enable && bssidx == 1) {
+ if (!brcmf_p2p_enable && is_p2pdev) {
/* this is P2P_DEVICE interface */
brcmf_dbg(INFO, "allocate non-netdev interface\n");
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
@@ -813,13 +846,17 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
} else {
brcmf_dbg(INFO, "allocate netdev interface\n");
/* Allocate netdev, including space for private structure */
- ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN,
- ether_setup);
+ ndev = alloc_netdev(sizeof(*ifp), is_p2pdev ? "p2p%d" : name,
+ NET_NAME_UNKNOWN, ether_setup);
if (!ndev)
return ERR_PTR(-ENOMEM);
+ ndev->destructor = brcmf_cfg80211_free_netdev;
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
+ /* store mapping ifidx to bssidx */
+ if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID)
+ drvr->if2bss[ifidx] = bssidx;
}
ifp->drvr = drvr;
@@ -850,6 +887,8 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
return;
}
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
+ if (drvr->if2bss[ifp->ifidx] == bssidx)
+ drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID;
if (ifp->ndev) {
if (bssidx == 0) {
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
@@ -865,17 +904,28 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
cancel_work_sync(&ifp->setmacaddr_work);
cancel_work_sync(&ifp->multicast_work);
}
- /* unregister will take care of freeing it */
- unregister_netdev(ifp->ndev);
+ brcmf_net_detach(ifp->ndev);
+ } else {
+ /* Only p2p device interfaces which get dynamically created
+ * end up here. In this case the p2p module should be informed
+ * about the removal of the interface within the firmware. If
+ * not then p2p commands towards the firmware will cause some
+ * serious troublesome side effects. The p2p module will clean
+ * up the ifp if needed.
+ */
+ brcmf_p2p_ifp_removed(ifp);
+ kfree(ifp);
}
}
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
+void brcmf_remove_interface(struct brcmf_if *ifp)
{
- if (drvr->iflist[bssidx]) {
- brcmf_fws_del_interface(drvr->iflist[bssidx]);
- brcmf_del_if(drvr, bssidx);
- }
+ if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
+ return;
+ brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", ifp->bssidx,
+ ifp->ifidx);
+ brcmf_fws_del_interface(ifp);
+ brcmf_del_if(ifp->drvr, ifp->bssidx);
}
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
@@ -906,6 +956,7 @@ int brcmf_attach(struct device *dev)
{
struct brcmf_pub *drvr = NULL;
int ret = 0;
+ int i;
brcmf_dbg(TRACE, "Enter\n");
@@ -914,6 +965,9 @@ int brcmf_attach(struct device *dev)
if (!drvr)
return -ENOMEM;
+ for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
+ drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
+
mutex_init(&drvr->proto_block);
/* Link to bus module */
@@ -921,8 +975,8 @@ int brcmf_attach(struct device *dev)
drvr->bus_if = dev_get_drvdata(dev);
drvr->bus_if->drvr = drvr;
- /* create device debugfs folder */
- brcmf_debugfs_attach(drvr);
+ /* attach debug facilities */
+ brcmf_debug_attach(drvr);
/* Attach and link in the protocol */
ret = brcmf_proto_attach(drvr);
@@ -981,16 +1035,11 @@ int brcmf_bus_start(struct device *dev)
brcmf_dbg(TRACE, "\n");
/* add primary networking interface */
- ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
+ ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
if (IS_ERR(ifp))
return PTR_ERR(ifp);
- if (brcmf_p2p_enable)
- p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
- else
- p2p_ifp = NULL;
- if (IS_ERR(p2p_ifp))
- p2p_ifp = NULL;
+ p2p_ifp = NULL;
/* signal bus ready */
brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
@@ -1017,39 +1066,37 @@ int brcmf_bus_start(struct device *dev)
brcmf_fws_add_interface(ifp);
- drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
+ drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
+ brcmf_p2p_enable);
if (drvr->config == NULL) {
ret = -ENOMEM;
goto fail;
}
- ret = brcmf_fweh_activate_events(ifp);
- if (ret < 0)
- goto fail;
-
ret = brcmf_net_attach(ifp, false);
+
+ if ((!ret) && (brcmf_p2p_enable)) {
+ p2p_ifp = drvr->iflist[1];
+ if (p2p_ifp)
+ ret = brcmf_net_p2p_attach(p2p_ifp);
+ }
fail:
if (ret < 0) {
brcmf_err("failed: %d\n", ret);
- brcmf_cfg80211_detach(drvr->config);
+ if (drvr->config) {
+ brcmf_cfg80211_detach(drvr->config);
+ drvr->config = NULL;
+ }
if (drvr->fws) {
brcmf_fws_del_interface(ifp);
brcmf_fws_deinit(drvr);
}
- if (drvr->iflist[0]) {
- free_netdev(ifp->ndev);
- drvr->iflist[0] = NULL;
- }
- if (p2p_ifp) {
- free_netdev(p2p_ifp->ndev);
- drvr->iflist[1] = NULL;
- }
+ if (ifp)
+ brcmf_net_detach(ifp->ndev);
+ if (p2p_ifp)
+ brcmf_net_detach(p2p_ifp->ndev);
return ret;
}
- if ((brcmf_p2p_enable) && (p2p_ifp))
- if (brcmf_net_p2p_attach(p2p_ifp) < 0)
- brcmf_p2p_enable = 0;
-
return 0;
}
@@ -1105,7 +1152,7 @@ void brcmf_detach(struct device *dev)
/* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
- brcmf_remove_interface(drvr, i);
+ brcmf_remove_interface(drvr->iflist[i]);
brcmf_cfg80211_detach(drvr->config);
@@ -1115,7 +1162,7 @@ void brcmf_detach(struct device *dev)
brcmf_proto_detach(drvr);
- brcmf_debugfs_detach(drvr);
+ brcmf_debug_detach(drvr);
bus_if->drvr = NULL;
kfree(drvr);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h
index 746304121cdb..2f9101b2ad34 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
@@ -122,6 +122,7 @@ struct brcmf_pub {
struct mac_address addresses[BRCMF_MAX_IFS];
struct brcmf_if *iflist[BRCMF_MAX_IFS];
+ s32 if2bss[BRCMF_MAX_IFS];
struct mutex proto_block;
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
@@ -153,10 +154,13 @@ struct brcmf_fws_mac_descriptor;
* netif stopped due to firmware signalling flow control.
* @BRCMF_NETIF_STOP_REASON_FLOW:
* netif stopped due to flowring full.
+ * @BRCMF_NETIF_STOP_REASON_DISCONNECTED:
+ * netif stopped due to not being connected (STA mode).
*/
enum brcmf_netif_stop_reason {
- BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
- BRCMF_NETIF_STOP_REASON_FLOW = 2
+ BRCMF_NETIF_STOP_REASON_FWS_FC = BIT(0),
+ BRCMF_NETIF_STOP_REASON_FLOW = BIT(1),
+ BRCMF_NETIF_STOP_REASON_DISCONNECTED = BIT(2)
};
/**
@@ -202,19 +206,16 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
/* Return pointer to interface name */
char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
-
+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
- char *name, u8 *mac_addr);
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
+ bool is_p2pdev, char *name, u8 *mac_addr);
+void brcmf_remove_interface(struct brcmf_if *ifp);
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
- bool success);
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
-
-/* Sets dongle media info (drv_version, mac address). */
-int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
#endif /* BRCMFMAC_CORE_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
index 2d6d00553858..1299dccc78b4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
@@ -16,15 +16,45 @@
#include <linux/debugfs.h>
#include <linux/netdevice.h>
#include <linux/module.h>
+#include <linux/devcoredump.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "core.h"
#include "bus.h"
+#include "fweh.h"
#include "debug.h"
static struct dentry *root_folder;
+static int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
+ size_t len)
+{
+ void *dump;
+ size_t ramsize;
+
+ ramsize = brcmf_bus_get_ramsize(bus);
+ if (ramsize) {
+ dump = vzalloc(len + ramsize);
+ if (!dump)
+ return -ENOMEM;
+ memcpy(dump, data, len);
+ brcmf_bus_get_memdump(bus, dump + len, ramsize);
+ dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL);
+ }
+ return 0;
+}
+
+static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *evtmsg,
+ void *data)
+{
+ brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
+
+ return brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
+ evtmsg->datalen);
+}
+
void brcmf_debugfs_init(void)
{
root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
@@ -41,7 +71,7 @@ void brcmf_debugfs_exit(void)
root_folder = NULL;
}
-int brcmf_debugfs_attach(struct brcmf_pub *drvr)
+int brcmf_debug_attach(struct brcmf_pub *drvr)
{
struct device *dev = drvr->bus_if->dev;
@@ -49,12 +79,18 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
return -ENODEV;
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
+ if (IS_ERR(drvr->dbgfs_dir))
+ return PTR_ERR(drvr->dbgfs_dir);
- return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
+
+ return brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
+ brcmf_debug_psm_watchdog_notify);
}
-void brcmf_debugfs_detach(struct brcmf_pub *drvr)
+void brcmf_debug_detach(struct brcmf_pub *drvr)
{
+ brcmf_fweh_unregister(drvr, BRCMF_E_PSM_WATCHDOG);
+
if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
debugfs_remove_recursive(drvr->dbgfs_dir);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
index eb0b8c47479d..d0d9676f7f9d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
@@ -37,6 +37,7 @@
#define BRCMF_SDIO_VAL 0x00020000
#define BRCMF_MSGBUF_VAL 0x00040000
#define BRCMF_PCIE_VAL 0x00080000
+#define BRCMF_FWCON_VAL 0x00100000
/* set default print format */
#undef pr_fmt
@@ -78,6 +79,7 @@ do { \
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
+#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL)
#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
@@ -90,6 +92,7 @@ do { \
#define BRCMF_GLOM_ON() 0
#define BRCMF_EVENT_ON() 0
#define BRCMF_FIL_ON() 0
+#define BRCMF_FWCON_ON() 0
#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
@@ -106,8 +109,8 @@ struct brcmf_pub;
#ifdef DEBUG
void brcmf_debugfs_init(void);
void brcmf_debugfs_exit(void);
-int brcmf_debugfs_attach(struct brcmf_pub *drvr);
-void brcmf_debugfs_detach(struct brcmf_pub *drvr);
+int brcmf_debug_attach(struct brcmf_pub *drvr);
+void brcmf_debug_detach(struct brcmf_pub *drvr);
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data));
@@ -118,11 +121,11 @@ static inline void brcmf_debugfs_init(void)
static inline void brcmf_debugfs_exit(void)
{
}
-static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
+static inline int brcmf_debug_attach(struct brcmf_pub *drvr)
{
return 0;
}
-static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
+static inline void brcmf_debug_detach(struct brcmf_pub *drvr)
{
}
static inline
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
index 1e94e94e01dc..44bb30636690 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
@@ -15,6 +15,7 @@
*/
#include <linux/netdevice.h>
+#include <linux/module.h>
#include <brcm_hw_ids.h>
#include "core.h"
@@ -23,6 +24,12 @@
#include "fwil.h"
#include "feature.h"
+
+/* Module param feature_disable (global for all devices) */
+static int brcmf_feature_disable;
+module_param_named(feature_disable, brcmf_feature_disable, int, 0);
+MODULE_PARM_DESC(feature_disable, "Disable features");
+
/*
* expand feature list to array of feature strings.
*/
@@ -121,7 +128,7 @@ static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp,
void brcmf_feat_attach(struct brcmf_pub *drvr)
{
- struct brcmf_if *ifp = drvr->iflist[0];
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
@@ -131,6 +138,12 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
+ if (brcmf_feature_disable) {
+ brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
+ ifp->drvr->feat_flags, brcmf_feature_disable);
+ ifp->drvr->feat_flags &= ~brcmf_feature_disable;
+ }
+
/* set chip related quirks */
switch (drvr->bus_if->chip) {
case BRCM_CC_43236_CHIP_ID:
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 971920f77b68..4248f3c80e78 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -29,7 +29,7 @@
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
-module_param_string(firmware_path, brcmf_firmware_path,
+module_param_string(alternative_fw_path, brcmf_firmware_path,
BRCMF_FW_PATH_LEN, 0440);
enum nvram_parser_state {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
index 8d1ab4ab5be8..2ca783fa50cf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
@@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
bus_if = dev_get_drvdata(flow->dev);
drvr = bus_if->drvr;
- ifp = drvr->iflist[ifidx];
+ ifp = brcmf_get_ifp(drvr, ifidx);
brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
spin_unlock_irqrestore(&flow->block_lock, flags);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
index 5551861a44bc..95fd1c9675d1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
@@ -34,7 +34,7 @@ enum ring_status {
};
struct brcmf_flowring_ring {
- u8 hash_id;
+ u16 hash_id;
bool blocked;
enum ring_status status;
struct sk_buff_head skblist;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index ec62492ffa69..3878b6f6cfce 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -179,25 +179,28 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
{
struct brcmf_if_event *ifevent = data;
struct brcmf_if *ifp;
+ bool is_p2pdev;
int err = 0;
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
ifevent->action, ifevent->ifidx, ifevent->bssidx,
ifevent->flags, ifevent->role);
- /* The P2P Device interface event must not be ignored
- * contrary to what firmware tells us. The only way to
- * distinguish the P2P Device is by looking at the ifidx
- * and bssidx received.
+ /* The P2P Device interface event must not be ignored contrary to what
+ * firmware tells us. Older firmware uses p2p noif, with sta role.
+ * This should be accepted when p2pdev_setup is ongoing. TDLS setup will
+ * use the same ifevent and should be ignored.
*/
- if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
- (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+ is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
+ (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT ||
+ ((ifevent->role == BRCMF_E_IF_ROLE_STA) &&
+ (drvr->fweh.p2pdev_setup_ongoing))));
+ if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
brcmf_dbg(EVENT, "event can be ignored\n");
return;
}
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
- brcmf_err("invalid interface index: %u\n",
- ifevent->ifidx);
+ brcmf_err("invalid interface index: %u\n", ifevent->ifidx);
return;
}
@@ -207,10 +210,11 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
emsg->addr);
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
- emsg->ifname, emsg->addr);
+ is_p2pdev, emsg->ifname, emsg->addr);
if (IS_ERR(ifp))
return;
- brcmf_fws_add_interface(ifp);
+ if (!is_p2pdev)
+ brcmf_fws_add_interface(ifp);
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
if (brcmf_net_attach(ifp, false) < 0)
return;
@@ -222,7 +226,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
if (ifp && ifevent->action == BRCMF_E_IF_DEL)
- brcmf_remove_interface(drvr, ifevent->bssidx);
+ brcmf_remove_interface(ifp);
}
/**
@@ -297,8 +301,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
goto event_free;
}
- if ((event->code == BRCMF_E_TDLS_PEER_EVENT) &&
- (emsg.bsscfgidx == 1))
+ if (event->code == BRCMF_E_TDLS_PEER_EVENT)
ifp = drvr->iflist[0];
else
ifp = drvr->iflist[emsg.bsscfgidx];
@@ -315,6 +318,17 @@ event_free:
}
/**
+ * brcmf_fweh_p2pdev_setup() - P2P device setup ongoing (or not).
+ *
+ * @ifp: ifp on which setup is taking place or finished.
+ * @ongoing: p2p device setup in progress (or not).
+ */
+void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing)
+{
+ ifp->drvr->fweh.p2pdev_setup_ongoing = ongoing;
+}
+
+/**
* brcmf_fweh_attach() - initialize firmware event handling.
*
* @drvr: driver information object.
@@ -335,7 +349,7 @@ void brcmf_fweh_attach(struct brcmf_pub *drvr)
void brcmf_fweh_detach(struct brcmf_pub *drvr)
{
struct brcmf_fweh_info *fweh = &drvr->fweh;
- struct brcmf_if *ifp = drvr->iflist[0];
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
if (ifp) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
index 1326898d608e..d9a942842382 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
@@ -230,12 +230,14 @@ typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
/**
* struct brcmf_fweh_info - firmware event handling information.
*
+ * @p2pdev_setup_ongoing: P2P device creation in progress.
* @event_work: event worker.
* @evt_q_lock: lock for event queue protection.
* @event_q: event queue.
* @evt_handler: registered event handlers.
*/
struct brcmf_fweh_info {
+ bool p2pdev_setup_ongoing;
struct work_struct event_work;
spinlock_t evt_q_lock;
struct list_head event_q;
@@ -255,6 +257,7 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr,
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
struct brcmf_event *event_packet);
+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)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
index 5434dcf64f7d..b20fc0f82a48 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
@@ -72,6 +72,7 @@
#define BRCMF_C_GET_BSS_INFO 136
#define BRCMF_C_GET_BANDLIST 140
#define BRCMF_C_SET_SCB_TIMEOUT 158
+#define BRCMF_C_GET_ASSOCLIST 159
#define BRCMF_C_GET_PHYLIST 180
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 297911f38fa0..daa427b46712 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -119,6 +119,8 @@
#define BRCMF_COUNTRY_BUF_SZ 4
#define BRCMF_ANT_MAX 4
+#define BRCMF_MAX_ASSOCLIST 128
+
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1,
@@ -621,4 +623,15 @@ struct brcmf_rev_info_le {
__le32 nvramrev;
};
+/**
+ * struct brcmf_assoclist_le - request assoc list.
+ *
+ * @count: indicates number of stations.
+ * @mac: MAC addresses of stations.
+ */
+struct brcmf_assoclist_le {
+ __le32 count;
+ u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN];
+};
+
#endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 5017eaa4af45..086cac3f86d6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -972,7 +972,7 @@ static void
brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
u8 if_id)
{
- struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1];
+ struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
if (WARN_ON(!ifp))
return;
@@ -1398,7 +1398,7 @@ done:
}
static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
- struct sk_buff *skb, u8 ifidx,
+ struct sk_buff *skb,
u32 genbit, u16 seq)
{
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
@@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
struct sk_buff *skb;
struct brcmf_skbuff_cb *skcb;
struct brcmf_fws_mac_descriptor *entry = NULL;
- u8 ifidx;
+ struct brcmf_if *ifp;
brcmf_dbg(DATA, "flags %d\n", flags);
@@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
}
brcmf_fws_macdesc_return_req_credit(skb);
- if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
+ ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
+ if (ret) {
brcmu_pkt_buf_free_skb(skb);
return -EINVAL;
}
if (!remove_from_hanger)
- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
genbit, seq);
if (remove_from_hanger || ret)
- brcmf_txfinalize(fws->drvr, skb, ifidx, true);
+ brcmf_txfinalize(ifp, skb, true);
return 0;
}
@@ -1615,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
return 0;
}
-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
- struct sk_buff *skb)
+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
{
struct brcmf_skb_reorder_data *rd;
- struct brcmf_fws_info *fws = drvr->fws;
+ struct brcmf_fws_info *fws = ifp->drvr->fws;
u8 *signal_data;
s16 data_len;
u8 type;
@@ -1629,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
s32 err;
brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
- ifidx, skb->len, signal_len);
+ ifp->ifidx, skb->len, siglen);
- WARN_ON(signal_len > skb->len);
+ WARN_ON(siglen > skb->len);
- if (!signal_len)
- return 0;
+ if (!siglen)
+ return;
/* if flow control disabled, skip to packet data and leave */
if ((!fws) || (!fws->fw_signals)) {
- skb_pull(skb, signal_len);
- return 0;
+ skb_pull(skb, siglen);
+ return;
}
fws->stats.header_pulls++;
- data_len = signal_len;
+ data_len = siglen;
signal_data = skb->data;
status = BRCMF_FWS_RET_OK_NOSCHEDULE;
@@ -1730,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
/* signalling processing result does
* not affect the actual ethernet packet.
*/
- skb_pull(skb, signal_len);
+ skb_pull(skb, siglen);
/* this may be a signal-only packet
*/
if (skb->len == 0)
fws->stats.header_only_pkt++;
-
- return 0;
}
static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
@@ -1848,7 +1846,7 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
entry->transit_count--;
if (entry->suppressed)
entry->suppr_transit_count--;
- brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
+ (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
goto rollback;
}
@@ -1904,7 +1902,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
if (fws->avoid_queueing) {
rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
if (rc < 0)
- brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+ brcmf_txfinalize(ifp, skb, false);
return rc;
}
@@ -1928,7 +1926,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_schedule_deq(fws);
} else {
brcmf_err("drop skb: no hanger slot\n");
- brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+ brcmf_txfinalize(ifp, skb, false);
rc = -ENOMEM;
}
brcmf_fws_unlock(fws);
@@ -2008,8 +2006,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
brcmf_fws_lock(fws);
if (ret < 0)
- brcmf_txfinalize(drvr, skb, ifidx,
- false);
+ brcmf_txfinalize(brcmf_get_ifp(drvr,
+ ifidx),
+ skb, false);
if (fws->bus_flow_blocked)
break;
}
@@ -2117,6 +2116,7 @@ static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
int brcmf_fws_init(struct brcmf_pub *drvr)
{
struct brcmf_fws_info *fws;
+ struct brcmf_if *ifp;
u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
int rc;
u32 mode;
@@ -2176,21 +2176,22 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
* continue. Set mode back to none indicating not enabled.
*/
fws->fw_signals = true;
- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
+ ifp = brcmf_get_ifp(drvr, 0);
+ if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
brcmf_err("failed to set bdcv2 tlv signaling\n");
fws->fcmode = BRCMF_FWS_FCMODE_NONE;
fws->fw_signals = false;
}
- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
+ if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1))
brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
/* Enable seq number reuse, if supported */
- if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) {
+ if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) {
if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
mode = 0;
BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
- if (brcmf_fil_iovar_int_set(drvr->iflist[0],
+ if (brcmf_fil_iovar_int_set(ifp,
"wlfc_mode", mode) == 0) {
BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
index 9fc860910bd8..a36bac17eafd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
@@ -21,8 +21,7 @@
int brcmf_fws_init(struct brcmf_pub *drvr);
void brcmf_fws_deinit(struct brcmf_pub *drvr);
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
- struct sk_buff *skb);
+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_fws_reset_interface(struct brcmf_if *ifp);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index 7b2136c9badb..44e618f9d890 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
- u8 *ifidx, struct sk_buff *skb)
+ struct sk_buff *skb, struct brcmf_if **ifp)
{
return -ENODEV;
}
@@ -873,7 +873,8 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
commonring = msgbuf->flowrings[flowid];
atomic_dec(&commonring->outstanding_tx);
- brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
+ brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
+ skb, true);
}
@@ -1081,15 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb,
{
struct brcmf_if *ifp;
- /* The ifidx is the idx to map to matching netdev/ifp. When receiving
- * events this is easy because it contains the bssidx which maps
- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
- * bssidx 1 is used for p2p0 and no data can be received or
- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
- */
- if (ifidx)
- (ifidx)++;
- ifp = msgbuf->drvr->iflist[ifidx];
+ ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
if (!ifp || !ifp->ndev) {
brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
brcmu_pkt_buf_free_skb(skb);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index a9ba775a24c1..d224b3dd72ed 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -2084,11 +2084,13 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif);
+ brcmf_fweh_p2pdev_setup(pri_ifp, true);
/* 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");
+ brcmf_fweh_p2pdev_setup(pri_ifp, false);
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
goto fail;
}
@@ -2097,6 +2099,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD,
msecs_to_jiffies(1500));
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
+ brcmf_fweh_p2pdev_setup(pri_ifp, false);
if (!err) {
brcmf_err("timeout occurred\n");
err = -EIO;
@@ -2131,20 +2134,6 @@ fail:
}
/**
- * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface.
- *
- * @vif: virtual interface object to delete.
- */
-static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
- struct brcmf_cfg80211_vif *vif)
-{
- cfg80211_unregister_wdev(&vif->wdev);
- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
- brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
- brcmf_free_vif(vif);
-}
-
-/**
* brcmf_p2p_add_vif() - create a new P2P virtual interface.
*
* @wiphy: wiphy device of new interface.
@@ -2255,6 +2244,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
brcmf_dbg(TRACE, "delete P2P vif\n");
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+ brcmf_cfg80211_arm_vif_event(cfg, vif);
switch (vif->wdev.iftype) {
case NL80211_IFTYPE_P2P_CLIENT:
if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
@@ -2267,10 +2257,10 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
break;
case NL80211_IFTYPE_P2P_DEVICE:
+ if (!p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+ return 0;
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
brcmf_p2p_deinit_discovery(p2p);
- brcmf_p2p_delete_p2pdev(p2p, vif);
- return 0;
default:
return -ENOTSUPP;
}
@@ -2282,10 +2272,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
wait_for_completion_timeout(&cfg->vif_disabled,
msecs_to_jiffies(500));
- brcmf_vif_clear_mgmt_ies(vif);
-
- brcmf_cfg80211_arm_vif_event(cfg, vif);
- err = brcmf_p2p_release_p2p_if(vif);
+ err = 0;
+ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) {
+ brcmf_vif_clear_mgmt_ies(vif);
+ err = brcmf_p2p_release_p2p_if(vif);
+ }
if (!err) {
/* wait for firmware event */
err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
@@ -2295,12 +2286,31 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
else
err = 0;
}
+ if (err)
+ brcmf_remove_interface(vif->ifp);
+
brcmf_cfg80211_arm_vif_event(cfg, NULL);
- p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
+ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
+ p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
return err;
}
+void brcmf_p2p_ifp_removed(struct brcmf_if *ifp)
+{
+ struct brcmf_cfg80211_info *cfg;
+ struct brcmf_cfg80211_vif *vif;
+
+ brcmf_dbg(INFO, "P2P: device interface removed\n");
+ vif = ifp->vif;
+ cfg = wdev_to_cfg(&vif->wdev);
+ cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+ rtnl_lock();
+ cfg80211_unregister_wdev(&vif->wdev);
+ rtnl_unlock();
+ brcmf_free_vif(vif);
+}
+
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
@@ -2324,87 +2334,49 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
struct brcmf_cfg80211_vif *vif;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
- mutex_lock(&cfg->usr_sync);
- (void)brcmf_p2p_deinit_discovery(p2p);
- brcmf_abort_scanning(cfg);
- clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
- mutex_unlock(&cfg->usr_sync);
+ /* This call can be result of the unregister_wdev call. In that case
+ * we dont want to do anything anymore. Just return. The config vif
+ * will have been cleared at this point.
+ */
+ if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) {
+ mutex_lock(&cfg->usr_sync);
+ /* Set the discovery state to SCAN */
+ (void)brcmf_p2p_set_discover_state(vif->ifp,
+ WL_P2P_DISC_ST_SCAN, 0, 0);
+ brcmf_abort_scanning(cfg);
+ clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
+ mutex_unlock(&cfg->usr_sync);
+ }
}
/**
* brcmf_p2p_attach() - attach for P2P.
*
* @cfg: driver private data for cfg80211 interface.
+ * @p2pdev_forced: create p2p device interface at attach.
*/
-s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced)
{
- struct brcmf_if *pri_ifp;
- struct brcmf_if *p2p_ifp;
- struct brcmf_cfg80211_vif *p2p_vif;
struct brcmf_p2p_info *p2p;
- struct brcmf_pub *drvr;
- s32 bssidx;
+ struct brcmf_if *pri_ifp;
s32 err = 0;
+ void *err_ptr;
p2p = &cfg->p2p;
p2p->cfg = cfg;
- drvr = cfg->pub;
-
- pri_ifp = drvr->iflist[0];
- p2p_ifp = drvr->iflist[1];
-
+ pri_ifp = brcmf_get_ifp(cfg->pub, 0);
p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
- if (p2p_ifp) {
- p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
- false);
- if (IS_ERR(p2p_vif)) {
- brcmf_err("could not create discovery vif\n");
- err = -ENOMEM;
- goto exit;
- }
-
- p2p_vif->ifp = p2p_ifp;
- p2p_ifp->vif = p2p_vif;
- p2p_vif->wdev.netdev = p2p_ifp->ndev;
- p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
- SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
-
- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
-
- brcmf_p2p_generate_bss_mac(p2p, NULL);
- memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
- brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
-
- /* 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");
- brcmf_free_vif(p2p_vif);
- goto exit;
- }
- /* obtain bsscfg index for P2P discovery */
- err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
- if (err < 0) {
- brcmf_err("retrieving discover bsscfg index failed\n");
- brcmf_free_vif(p2p_vif);
- goto exit;
- }
- /* Verify that firmware uses same bssidx as driver !! */
- if (p2p_ifp->bssidx != bssidx) {
- brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
- bssidx, p2p_ifp->bssidx);
- brcmf_free_vif(p2p_vif);
- goto exit;
+ if (p2pdev_forced) {
+ err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL);
+ if (IS_ERR(err_ptr)) {
+ brcmf_err("P2P device creation failed.\n");
+ err = PTR_ERR(err_ptr);
}
-
- init_completion(&p2p->send_af_done);
- INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
- init_completion(&p2p->afx_hdl.act_frm_scan);
- init_completion(&p2p->wait_next_af);
+ } else {
+ p2p->p2pdev_dynamically = true;
}
-exit:
return err;
}
@@ -2421,10 +2393,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
if (vif != NULL) {
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
brcmf_p2p_deinit_discovery(p2p);
- /* remove discovery interface */
- rtnl_lock();
- brcmf_p2p_delete_p2pdev(p2p, vif);
- rtnl_unlock();
+ brcmf_remove_interface(vif->ifp);
}
/* just set it all to zero */
memset(p2p, 0, sizeof(*p2p));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
index 872f382d9e49..5d49059021a9 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
@@ -124,6 +124,7 @@ struct afx_hdl {
* @wait_next_af: thread synchronizing struct.
* @gon_req_action: about to send go negotiation requets frame.
* @block_gon_req_tx: drop tx go negotiation requets frame.
+ * @p2pdev_dynamically: is p2p device if created by module param or supplicant.
*/
struct brcmf_p2p_info {
struct brcmf_cfg80211_info *cfg;
@@ -144,9 +145,10 @@ struct brcmf_p2p_info {
struct completion wait_next_af;
bool gon_req_action;
bool block_gon_req_tx;
+ bool p2pdev_dynamically;
};
-s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced);
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
unsigned char name_assign_type,
@@ -155,6 +157,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
enum brcmf_fil_p2p_if_types if_type);
+void brcmf_p2p_ifp_removed(struct brcmf_if *ifp);
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
int brcmf_p2p_scan_prep(struct wiphy *wiphy,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
index 3a98c4306d1d..83d804221715 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
@@ -47,12 +47,20 @@ enum brcmf_pcie_state {
#define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin"
#define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt"
+#define BRCMF_PCIE_4350_FW_NAME "brcm/brcmfmac4350-pcie.bin"
+#define BRCMF_PCIE_4350_NVRAM_NAME "brcm/brcmfmac4350-pcie.txt"
#define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin"
#define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt"
#define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin"
#define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt"
#define BRCMF_PCIE_4358_FW_NAME "brcm/brcmfmac4358-pcie.bin"
#define BRCMF_PCIE_4358_NVRAM_NAME "brcm/brcmfmac4358-pcie.txt"
+#define BRCMF_PCIE_4365_FW_NAME "brcm/brcmfmac4365b-pcie.bin"
+#define BRCMF_PCIE_4365_NVRAM_NAME "brcm/brcmfmac4365b-pcie.txt"
+#define BRCMF_PCIE_4366_FW_NAME "brcm/brcmfmac4366b-pcie.bin"
+#define BRCMF_PCIE_4366_NVRAM_NAME "brcm/brcmfmac4366b-pcie.txt"
+#define BRCMF_PCIE_4371_FW_NAME "brcm/brcmfmac4371-pcie.bin"
+#define BRCMF_PCIE_4371_NVRAM_NAME "brcm/brcmfmac4371-pcie.txt"
#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */
@@ -74,6 +82,8 @@ enum brcmf_pcie_state {
#define BRCMF_PCIE_REG_INTMASK 0x94
#define BRCMF_PCIE_REG_SBMBX 0x98
+#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC
+
#define BRCMF_PCIE_PCIE2REG_INTMASK 0x24
#define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48
#define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C
@@ -192,12 +202,20 @@ enum brcmf_pcie_state {
MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4350_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4350_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4371_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4371_NVRAM_NAME);
struct brcmf_pcie_console {
@@ -434,6 +452,47 @@ brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
}
+static void
+brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ void *dstaddr, u32 len)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+ __le32 *dst32;
+ __le16 *dst16;
+ u8 *dst8;
+
+ if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) {
+ if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) {
+ dst8 = (u8 *)dstaddr;
+ while (len) {
+ *dst8 = ioread8(address);
+ address++;
+ dst8++;
+ len--;
+ }
+ } else {
+ len = len / 2;
+ dst16 = (__le16 *)dstaddr;
+ while (len) {
+ *dst16 = cpu_to_le16(ioread16(address));
+ address += 2;
+ dst16++;
+ len--;
+ }
+ }
+ } else {
+ len = len / 4;
+ dst32 = (__le32 *)dstaddr;
+ while (len) {
+ *dst32 = cpu_to_le32(ioread32(address));
+ address += 4;
+ dst32++;
+ len--;
+ }
+ }
+}
+
+
#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
CHIPCREGOFFS(reg), value)
@@ -466,6 +525,7 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
{
+ struct brcmf_core *core;
u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
BRCMF_PCIE_CFGREG_PM_CSR,
BRCMF_PCIE_CFGREG_MSI_CAP,
@@ -484,32 +544,38 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
if (!devinfo->ci)
return;
+ /* Disable ASPM */
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
- lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+ pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+ &lsc);
val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+ val);
+ /* Watchdog reset */
brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
WRITECC32(devinfo, watchdog, 4);
msleep(100);
+ /* Restore ASPM */
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
-
- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
- for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
- cfg_offset[i]);
- val = brcmf_pcie_read_reg32(devinfo,
- BRCMF_PCIE_PCIE2REG_CONFIGDATA);
- brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
- cfg_offset[i], val);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
- val);
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+ lsc);
+
+ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
+ if (core->rev <= 13) {
+ for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+ brcmf_pcie_write_reg32(devinfo,
+ BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+ cfg_offset[i]);
+ val = brcmf_pcie_read_reg32(devinfo,
+ BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+ brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+ cfg_offset[i], val);
+ brcmf_pcie_write_reg32(devinfo,
+ BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+ val);
+ }
}
}
@@ -519,8 +585,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
u32 config;
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
- brcmf_pcie_reset_device(devinfo);
/* BAR1 window may not be sized properly */
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
@@ -644,7 +708,7 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
- brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n",
+ brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",
console->base_addr, console->buf_addr, console->bufsize);
}
@@ -656,6 +720,9 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
u8 ch;
u32 newidx;
+ if (!BRCMF_FWCON_ON())
+ return;
+
console = &devinfo->shared.console;
addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
newidx = brcmf_pcie_read_tcm32(devinfo, addr);
@@ -677,7 +744,7 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
}
if (ch == '\n') {
console->log_str[console->log_idx] = 0;
- brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str);
+ pr_debug("CONSOLE: %s", console->log_str);
console->log_idx = 0;
}
}
@@ -1330,12 +1397,36 @@ static void brcmf_pcie_wowl_config(struct device *dev, bool enabled)
}
+static size_t brcmf_pcie_get_ramsize(struct device *dev)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
+
+ return devinfo->ci->ramsize - devinfo->ci->srsize;
+}
+
+
+static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
+
+ brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len);
+ brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len);
+ return 0;
+}
+
+
static struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.txdata = brcmf_pcie_tx,
.stop = brcmf_pcie_down,
.txctl = brcmf_pcie_tx_ctlpkt,
.rxctl = brcmf_pcie_rx_ctlpkt,
.wowl_config = brcmf_pcie_wowl_config,
+ .get_ramsize = brcmf_pcie_get_ramsize,
+ .get_memdump = brcmf_pcie_get_memdump,
};
@@ -1408,6 +1499,10 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo)
fw_name = BRCMF_PCIE_43602_FW_NAME;
nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
break;
+ case BRCM_CC_4350_CHIP_ID:
+ fw_name = BRCMF_PCIE_4350_FW_NAME;
+ nvram_name = BRCMF_PCIE_4350_NVRAM_NAME;
+ break;
case BRCM_CC_4356_CHIP_ID:
fw_name = BRCMF_PCIE_4356_FW_NAME;
nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
@@ -1422,6 +1517,18 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo)
fw_name = BRCMF_PCIE_4358_FW_NAME;
nvram_name = BRCMF_PCIE_4358_NVRAM_NAME;
break;
+ case BRCM_CC_4365_CHIP_ID:
+ fw_name = BRCMF_PCIE_4365_FW_NAME;
+ nvram_name = BRCMF_PCIE_4365_NVRAM_NAME;
+ break;
+ case BRCM_CC_4366_CHIP_ID:
+ fw_name = BRCMF_PCIE_4366_FW_NAME;
+ nvram_name = BRCMF_PCIE_4366_NVRAM_NAME;
+ break;
+ case BRCM_CC_4371_CHIP_ID:
+ fw_name = BRCMF_PCIE_4371_FW_NAME;
+ nvram_name = BRCMF_PCIE_4371_NVRAM_NAME;
+ break;
default:
brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
return -ENODEV;
@@ -1633,6 +1740,23 @@ static int brcmf_pcie_buscoreprep(void *ctx)
}
+static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+ u32 val;
+
+ devinfo->ci = chip;
+ brcmf_pcie_reset_device(devinfo);
+
+ val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ if (val != 0xffffffff)
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ val);
+
+ return 0;
+}
+
+
static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
u32 rstvec)
{
@@ -1644,6 +1768,7 @@ static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
.prepare = brcmf_pcie_buscoreprep,
+ .reset = brcmf_pcie_buscore_reset,
.activate = brcmf_pcie_buscore_activate,
.read32 = brcmf_pcie_buscore_read32,
.write32 = brcmf_pcie_buscore_write32,
@@ -1811,7 +1936,6 @@ brcmf_pcie_remove(struct pci_dev *pdev)
brcmf_pcie_intr_disable(devinfo);
brcmf_detach(&pdev->dev);
- brcmf_pcie_reset_device(devinfo);
kfree(bus->bus_priv.pcie);
kfree(bus->msgbuf->flowrings);
@@ -1929,6 +2053,7 @@ cleanup:
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
static struct pci_device_id brcmf_pcie_devid_table[] = {
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
@@ -1937,6 +2062,13 @@ static struct pci_device_id brcmf_pcie_devid_table[] = {
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID),
{ /* end: all zeroes */ }
};
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
index 971172ff686c..d55119d36755 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
@@ -24,8 +24,8 @@ enum proto_addr_mode {
struct brcmf_proto {
- int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
- struct sk_buff *skb);
+ int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
+ struct sk_buff *skb, struct brcmf_if **ifp);
int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
void *buf, uint len);
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
@@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub *drvr);
void brcmf_proto_detach(struct brcmf_pub *drvr);
static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
- u8 *ifidx, struct sk_buff *skb)
+ struct sk_buff *skb,
+ struct brcmf_if **ifp)
{
- return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb);
+ struct brcmf_if *tmp = NULL;
+
+ /* assure protocol is always called with
+ * non-null initialized pointer.
+ */
+ if (ifp)
+ *ifp = NULL;
+ else
+ ifp = &tmp;
+ return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
}
static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index f990e3d0e696..7e74ac3ad815 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -15,6 +15,7 @@
*/
#include <linux/types.h>
+#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/printk.h>
@@ -123,6 +124,7 @@ struct rte_console {
#define BRCMF_FIRSTREAD (1 << 6)
+#define BRCMF_CONSOLE 10 /* watchdog interval to poll console */
/* SBSDIO_DEVICE_CTL */
@@ -3204,6 +3206,8 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
if (IS_ERR_OR_NULL(dentry))
return;
+ bus->console_interval = BRCMF_CONSOLE;
+
brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
brcmf_debugfs_add_entry(drvr, "counters",
brcmf_debugfs_sdio_count_read);
@@ -3535,6 +3539,51 @@ done:
return err;
}
+static size_t brcmf_sdio_bus_get_ramsize(struct device *dev)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_sdio *bus = sdiodev->bus;
+
+ return bus->ci->ramsize - bus->ci->srsize;
+}
+
+static int brcmf_sdio_bus_get_memdump(struct device *dev, void *data,
+ size_t mem_size)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_sdio *bus = sdiodev->bus;
+ int err;
+ int address;
+ int offset;
+ int len;
+
+ brcmf_dbg(INFO, "dump at 0x%08x: size=%zu\n", bus->ci->rambase,
+ mem_size);
+
+ address = bus->ci->rambase;
+ offset = err = 0;
+ sdio_claim_host(sdiodev->func[1]);
+ while (offset < mem_size) {
+ len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK :
+ mem_size - offset;
+ err = brcmf_sdiod_ramrw(sdiodev, false, address, data, len);
+ if (err) {
+ brcmf_err("error %d on reading %d membytes at 0x%08x\n",
+ err, len, address);
+ goto done;
+ }
+ data += len;
+ offset += len;
+ address += len;
+ }
+
+done:
+ sdio_release_host(sdiodev->func[1]);
+ return err;
+}
+
void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
{
if (!bus->dpc_triggered) {
@@ -3613,7 +3662,7 @@ static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
}
#ifdef DEBUG
/* Poll for console output periodically */
- if (bus->sdiodev->state == BRCMF_SDIOD_DATA &&
+ if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() &&
bus->console_interval != 0) {
bus->console.count += BRCMF_WD_POLL_MS;
if (bus->console.count >= bus->console_interval) {
@@ -3983,7 +4032,9 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.txctl = brcmf_sdio_bus_txctl,
.rxctl = brcmf_sdio_bus_rxctl,
.gettxq = brcmf_sdio_bus_gettxq,
- .wowl_config = brcmf_sdio_wowl_config
+ .wowl_config = brcmf_sdio_wowl_config,
+ .get_ramsize = brcmf_sdio_bus_get_ramsize,
+ .get_memdump = brcmf_sdio_bus_get_memdump,
};
static void brcmf_sdio_firmware_callback(struct device *dev,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index daba86d881bc..689e64d004bc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -144,6 +144,7 @@ struct brcmf_usbdev_info {
struct usb_device *usbdev;
struct device *dev;
+ struct mutex dev_init_lock;
int ctl_in_pipe, ctl_out_pipe;
struct urb *ctl_urb; /* URB for control endpoint */
@@ -1204,6 +1205,8 @@ static void brcmf_usb_probe_phase2(struct device *dev,
int ret;
brcmf_dbg(USB, "Start fw downloading\n");
+
+ devinfo = bus->bus_priv.usb->devinfo;
ret = check_file(fw->data);
if (ret < 0) {
brcmf_err("invalid firmware\n");
@@ -1211,7 +1214,6 @@ static void brcmf_usb_probe_phase2(struct device *dev,
goto error;
}
- devinfo = bus->bus_priv.usb->devinfo;
devinfo->image = fw->data;
devinfo->image_len = fw->size;
@@ -1224,9 +1226,11 @@ static void brcmf_usb_probe_phase2(struct device *dev,
if (ret)
goto error;
+ mutex_unlock(&devinfo->dev_init_lock);
return;
error:
brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
+ mutex_unlock(&devinfo->dev_init_lock);
device_release_driver(dev);
}
@@ -1264,6 +1268,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
if (ret)
goto fail;
/* we are done */
+ mutex_unlock(&devinfo->dev_init_lock);
return 0;
}
bus->chip = bus_pub->devid;
@@ -1317,6 +1322,12 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
devinfo->usbdev = usb;
devinfo->dev = &usb->dev;
+ /* Take an init lock, to protect for disconnect while still loading.
+ * Necessary because of the asynchronous firmware load construction
+ */
+ mutex_init(&devinfo->dev_init_lock);
+ mutex_lock(&devinfo->dev_init_lock);
+
usb_set_intfdata(intf, devinfo);
/* Check that the device supports only one configuration */
@@ -1391,6 +1402,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return 0;
fail:
+ mutex_unlock(&devinfo->dev_init_lock);
kfree(devinfo);
usb_set_intfdata(intf, NULL);
return ret;
@@ -1403,8 +1415,19 @@ brcmf_usb_disconnect(struct usb_interface *intf)
brcmf_dbg(USB, "Enter\n");
devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
- brcmf_usb_disconnect_cb(devinfo);
- kfree(devinfo);
+
+ if (devinfo) {
+ mutex_lock(&devinfo->dev_init_lock);
+ /* Make sure that devinfo still exists. Firmware probe routines
+ * may have released the device and cleared the intfdata.
+ */
+ if (!usb_get_intfdata(intf))
+ goto done;
+
+ brcmf_usb_disconnect_cb(devinfo);
+ kfree(devinfo);
+ }
+done:
brcmf_dbg(USB, "Exit\n");
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index d2c5747e3ac9..bec2dc1ca2e4 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -820,7 +820,7 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct brcms_info *wl = hw->priv;
struct scb *scb = &wl->wlc->pri_scb;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9728be0e704b..218cbc8bf3a7 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -4585,7 +4585,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
wlc_hw->machwcap_backup = wlc_hw->machwcap;
/* init tx fifo size */
- WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 ||
+ WARN_ON(wlc_hw->corerev < XMTFIFOTBL_STARTREV ||
(wlc_hw->corerev - XMTFIFOTBL_STARTREV) >
ARRAY_SIZE(xmtfifo_sz));
wlc_hw->xmtfifo_sz =
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index 7a6daa37dc6b..aa06ea231db3 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -39,6 +39,7 @@
#define BRCM_CC_4339_CHIP_ID 0x4339
#define BRCM_CC_43430_CHIP_ID 43430
#define BRCM_CC_4345_CHIP_ID 0x4345
+#define BRCM_CC_4350_CHIP_ID 0x4350
#define BRCM_CC_4354_CHIP_ID 0x4354
#define BRCM_CC_4356_CHIP_ID 0x4356
#define BRCM_CC_43566_CHIP_ID 43566
@@ -47,6 +48,9 @@
#define BRCM_CC_43570_CHIP_ID 43570
#define BRCM_CC_4358_CHIP_ID 0x4358
#define BRCM_CC_43602_CHIP_ID 43602
+#define BRCM_CC_4365_CHIP_ID 0x4365
+#define BRCM_CC_4366_CHIP_ID 0x4366
+#define BRCM_CC_4371_CHIP_ID 0x4371
/* USB Device IDs */
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
@@ -56,6 +60,7 @@
#define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc
/* PCIE Device IDs */
+#define BRCM_PCIE_4350_DEVICE_ID 0x43a3
#define BRCM_PCIE_4354_DEVICE_ID 0x43df
#define BRCM_PCIE_4356_DEVICE_ID 0x43ec
#define BRCM_PCIE_43567_DEVICE_ID 0x43d3
@@ -65,6 +70,14 @@
#define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb
#define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc
#define BRCM_PCIE_43602_RAW_DEVICE_ID 43602
+#define BRCM_PCIE_4365_DEVICE_ID 0x43ca
+#define BRCM_PCIE_4365_2G_DEVICE_ID 0x43cb
+#define BRCM_PCIE_4365_5G_DEVICE_ID 0x43cc
+#define BRCM_PCIE_4366_DEVICE_ID 0x43c3
+#define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4
+#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5
+#define BRCM_PCIE_4371_DEVICE_ID 0x440d
+
/* brcmsmac IDs */
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c
index 29185aeccba8..a740083634d8 100644
--- a/drivers/net/wireless/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/cw1200/cw1200_spi.c
@@ -467,7 +467,6 @@ static struct spi_driver spi_driver = {
.remove = cw1200_spi_disconnect,
.driver = {
.name = "cw1200_wlan_spi",
- .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &cw1200_pm_ops,
#endif
diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c
index b86500b4418f..95a7fdb3cc1c 100644
--- a/drivers/net/wireless/cw1200/sta.c
+++ b/drivers/net/wireless/cw1200/sta.c
@@ -2137,7 +2137,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
/* Aggregation is implemented fully in firmware,
* including block ack negotiation. Do not allow
diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h
index b7e386b7662b..bebb3379017f 100644
--- a/drivers/net/wireless/cw1200/sta.h
+++ b/drivers/net/wireless/cw1200/sta.h
@@ -111,7 +111,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size);
+ u8 buf_size, bool amsdu);
void cw1200_suspend_resume(struct cw1200_common *priv,
struct wsm_suspend_resume *arg);
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 39f3e6f5cbcd..ed0adaf1eec4 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -10470,7 +10470,6 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
vers, date);
strlcpy(info->bus_info, pci_name(p->pci_dev),
sizeof(info->bus_info));
- info->eedump_len = IPW_EEPROM_IMAGE_SIZE;
}
static u32 ipw_ethtool_get_link(struct net_device *dev)
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index a6877dd6ba73..cef7f7d79cd9 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1091,8 +1091,6 @@ static const char *get_info_element_string(u16 id)
MFIE_STRING(TIM);
MFIE_STRING(IBSS_PARAMS);
MFIE_STRING(COUNTRY);
- MFIE_STRING(HP_PARAMS);
- MFIE_STRING(HP_TABLE);
MFIE_STRING(REQUEST);
MFIE_STRING(CHALLENGE);
MFIE_STRING(PWR_CONSTRAINT);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 44fa422f255e..6656215a13a9 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5984,7 +5984,7 @@ int
il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 * ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct il_priv *il = hw->priv;
int ret = -EINVAL;
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index 3a57f71b8ed5..8ab8706f9422 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -184,7 +184,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw,
int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 * ssn,
- u8 buf_size);
+ u8 buf_size, bool amsdu);
int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index 5b972798bdff..ce52cf114fde 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -1425,9 +1425,9 @@ struct il_priv {
#endif /* CONFIG_IWLEGACY_DEBUGFS */
struct work_struct txpower_work;
- u32 disable_sens_cal;
- u32 disable_chain_noise_cal;
- u32 disable_tx_power_cal;
+ bool disable_sens_cal;
+ bool disable_chain_noise_cal;
+ bool disable_tx_power_cal;
struct work_struct run_time_calib_work;
struct timer_list stats_periodic;
struct timer_list watchdog;
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index aba095761ac6..6e949df399d6 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -142,6 +142,7 @@ config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
depends on EVENT_TRACING
+ default y
help
Say Y here to trace all commands, including TX frames and IO
accesses, sent to the device. If you say yes, iwlwifi will
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index ab45819c1fbb..e18629a16fb0 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -1020,7 +1020,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
u8 *pn = seq.ccmp.pn;
ieee80211_get_key_rx_seq(key, i, &seq);
- aes_sc->pn = cpu_to_le64(
+ aes_sc[i].pn = cpu_to_le64(
(u64)pn[5] |
((u64)pn[4] << 8) |
((u64)pn[3] << 16) |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 453f7c315ab5..b3ad34e8bf5a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -731,7 +731,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int ret = -EINVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 6951aba620eb..1a73c7a1da77 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -72,12 +72,10 @@
#define IWL7260_UCODE_API_MAX 17
/* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK 12
-#define IWL3165_UCODE_API_OK 13
+#define IWL7260_UCODE_API_OK 13
/* Lowest firmware API version supported */
-#define IWL7260_UCODE_API_MIN 12
-#define IWL3165_UCODE_API_MIN 13
+#define IWL7260_UCODE_API_MIN 13
/* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d
@@ -113,7 +111,7 @@
static const struct iwl_base_params iwl7000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000,
- .num_of_queues = IWLAGN_NUM_QUEUES,
+ .num_of_queues = 31,
.pll_cfg_val = 0,
.shadow_ram_support = true,
.led_compensation = 57,
@@ -269,11 +267,6 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3165",
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7000,
- /* sparse doens't like the re-assignment but it is safe */
-#ifndef __CHECKER__
- .ucode_api_ok = IWL3165_UCODE_API_OK,
- .ucode_api_min = IWL3165_UCODE_API_MIN,
-#endif
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3165_NVM_VERSION,
.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
@@ -348,6 +341,6 @@ const struct iwl_cfg iwl7265d_n_cfg = {
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
+MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index 197abe43ddc5..0116e5a4c393 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -72,10 +72,10 @@
#define IWL8000_UCODE_API_MAX 17
/* Oldest version we won't warn about */
-#define IWL8000_UCODE_API_OK 12
+#define IWL8000_UCODE_API_OK 13
/* Lowest firmware API version supported */
-#define IWL8000_UCODE_API_MIN 12
+#define IWL8000_UCODE_API_MIN 13
/* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d
@@ -107,7 +107,7 @@
static const struct iwl_base_params iwl8000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
- .num_of_queues = IWLAGN_NUM_QUEUES,
+ .num_of_queues = 31,
.pll_cfg_val = 0,
.shadow_ram_support = true,
.led_compensation = 57,
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 939fa229c038..910970858f98 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -223,13 +223,13 @@ struct iwl_tt_tx_backoff {
* @support_tx_backoff: Support tx-backoff?
*/
struct iwl_tt_params {
- s32 ct_kill_entry;
- s32 ct_kill_exit;
+ u32 ct_kill_entry;
+ u32 ct_kill_exit;
u32 ct_kill_duration;
- s32 dynamic_smps_entry;
- s32 dynamic_smps_exit;
- s32 tx_protection_entry;
- s32 tx_protection_exit;
+ u32 dynamic_smps_entry;
+ u32 dynamic_smps_exit;
+ u32 tx_protection_entry;
+ u32 tx_protection_exit;
struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE];
bool support_ct_kill;
bool support_dynamic_smps;
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index a86aa5bcee7d..463cadfbfccb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -450,7 +450,7 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
u32 api_flags = le32_to_cpu(ucode_api->api_flags);
int i;
- if (api_index >= IWL_API_MAX_BITS / 32) {
+ if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) {
IWL_ERR(drv, "api_index larger than supported by driver\n");
/* don't return an error so we can load FW that has more bits */
return 0;
@@ -472,7 +472,7 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
u32 api_flags = le32_to_cpu(ucode_capa->api_capa);
int i;
- if (api_index >= IWL_CAPABILITIES_MAX_BITS / 32) {
+ if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) {
IWL_ERR(drv, "api_index larger than supported by driver\n");
/* don't return an error so we can load FW that has more bits */
return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index af5b3201492c..9dbe19cbb4dd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -86,6 +86,8 @@
* Structured as &struct iwl_fw_error_dump_trigger_desc.
* @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as
* &struct iwl_fw_error_dump_rb
+ * @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were
+ * paged to the DRAM.
*/
enum iwl_fw_error_dump_type {
/* 0 is deprecated */
@@ -100,6 +102,7 @@ enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_MEM = 9,
IWL_FW_ERROR_DUMP_ERROR_INFO = 10,
IWL_FW_ERROR_DUMP_RB = 11,
+ IWL_FW_ERROR_DUMP_PAGING = 12,
IWL_FW_ERROR_DUMP_MAX,
};
@@ -240,6 +243,19 @@ struct iwl_fw_error_dump_rb {
};
/**
+ * struct iwl_fw_error_dump_paging - content of the UMAC's image page
+ * block on DRAM
+ * @index: the index of the page block
+ * @reserved:
+ * @data: the content of the page block
+ */
+struct iwl_fw_error_dump_paging {
+ __le32 index;
+ __le32 reserved;
+ u8 data[];
+};
+
+/**
* iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block
* Returns: next data block
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 84653e3d02ba..08303db0000f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -247,36 +247,31 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
* longer than the passive one, which is essential for fragmented scan.
* @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.
- * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR
- * @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power.
* @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header
- * @IWL_UCODE_TLV_API_SCD_CFG: This firmware can configure the scheduler
- * through the dedicated host command.
- * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too.
- * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported.
* @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params
- * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10
* @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format
* @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority
* instead of 3.
* @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size
* (command version 3) that supports per-chain limits
+ *
+ * @NUM_IWL_UCODE_TLV_API: number of bits used
*/
enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3,
IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8,
IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9,
- IWL_UCODE_TLV_API_HDC_PHASE_0 = (__force iwl_ucode_tlv_api_t)10,
- IWL_UCODE_TLV_API_TX_POWER_DEV = (__force iwl_ucode_tlv_api_t)11,
IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14,
- IWL_UCODE_TLV_API_SCD_CFG = (__force iwl_ucode_tlv_api_t)15,
- IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = (__force iwl_ucode_tlv_api_t)16,
- IWL_UCODE_TLV_API_ASYNC_DTM = (__force iwl_ucode_tlv_api_t)17,
IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18,
- IWL_UCODE_TLV_API_STATS_V10 = (__force iwl_ucode_tlv_api_t)19,
IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20,
IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24,
IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27,
+
+ NUM_IWL_UCODE_TLV_API
+#ifdef __CHECKER__
+ /* sparse says it cannot increment the previous enum member */
+ = 128
+#endif
};
typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
@@ -311,6 +306,10 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
* is supported.
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
+ * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
+ * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
+ *
+ * @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0,
@@ -333,6 +332,14 @@ 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,
+ 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,
+
+ NUM_IWL_UCODE_TLV_CAPA
+#ifdef __CHECKER__
+ /* sparse says it cannot increment the previous enum member */
+ = 128
+#endif
};
/* The default calibrate table size if not specified by firmware file */
@@ -343,9 +350,6 @@ enum iwl_ucode_tlv_capa {
/* The default max probe length if not specified by the firmware file */
#define IWL_DEFAULT_MAX_PROBE_LENGTH 200
-#define IWL_API_MAX_BITS 64
-#define IWL_CAPABILITIES_MAX_BITS 64
-
/*
* For 16.0 uCode and above, there is no differentiation between sections,
* just an offset to the HW address.
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 45e732150d28..84ec0cefb62a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -105,8 +105,8 @@ struct iwl_ucode_capabilities {
u32 n_scan_channels;
u32 standard_phy_calibration_size;
u32 flags;
- unsigned long _api[BITS_TO_LONGS(IWL_API_MAX_BITS)];
- unsigned long _capa[BITS_TO_LONGS(IWL_CAPABILITIES_MAX_BITS)];
+ unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
+ unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
};
static inline bool
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 27c66e477833..0bd9d4aad0c0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -36,6 +36,29 @@
#include "iwl-prph.h"
#include "iwl-fh.h"
+void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
+{
+ trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
+ iwl_trans_write8(trans, ofs, val);
+}
+IWL_EXPORT_SYMBOL(iwl_write8);
+
+void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
+{
+ trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
+ iwl_trans_write32(trans, ofs, val);
+}
+IWL_EXPORT_SYMBOL(iwl_write32);
+
+u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
+{
+ u32 val = iwl_trans_read32(trans, ofs);
+
+ trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
+ return val;
+}
+IWL_EXPORT_SYMBOL(iwl_read32);
+
#define IWL_POLL_INTERVAL 10 /* microseconds */
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 705d12c079e8..501d0560c061 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -32,24 +32,9 @@
#include "iwl-devtrace.h"
#include "iwl-trans.h"
-static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
-{
- trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
- iwl_trans_write8(trans, ofs, val);
-}
-
-static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
-{
- trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
- iwl_trans_write32(trans, ofs, val);
-}
-
-static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
-{
- u32 val = iwl_trans_read32(trans, ofs);
- trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
- return val;
-}
+void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val);
+void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val);
+u32 iwl_read32(struct iwl_trans *trans, u32 ofs);
static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 3b8e85e51002..d82984912e04 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -580,13 +580,15 @@ static void iwl_set_hw_address_family_8000(struct device *dev,
IWL_ERR_DEV(dev, "mac address is not found\n");
}
+#define IWL_4165_DEVICE_ID 0x5501
+
struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw,
const __le16 *nvm_calib, const __le16 *regulatory,
const __le16 *mac_override, const __le16 *phy_sku,
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
- u32 mac_addr0, u32 mac_addr1)
+ u32 mac_addr0, u32 mac_addr1, u32 hw_id)
{
struct iwl_nvm_data *data;
u32 sku;
@@ -625,6 +627,17 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
(sku & NVM_SKU_CAP_11AC_ENABLE);
data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE;
+ /*
+ * OTP 0x52 bug work around
+ * define antenna 1x1 according to MIMO disabled
+ */
+ if (hw_id == IWL_4165_DEVICE_ID && data->sku_cap_mimo_disabled) {
+ data->valid_tx_ant = ANT_B;
+ data->valid_rx_ant = ANT_B;
+ tx_chains = ANT_B;
+ rx_chains = ANT_B;
+ }
+
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
index 822ba52e0e5a..9f44d8188c5c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
@@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_calib, const __le16 *regulatory,
const __le16 *mac_override, const __le16 *phy_sku,
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
- u32 mac_addr0, u32 mac_addr1);
+ u32 mac_addr0, u32 mac_addr1, u32 hw_id);
/**
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index b47fe9d6b97a..2a58d6833224 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -7,6 +7,7 @@
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * 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
@@ -33,6 +34,7 @@
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -108,7 +110,8 @@ struct iwl_cfg;
* interact with it. The driver layer typically calls the start and stop
* handlers, the transport layer calls the others.
*
- * All the handlers MUST be implemented
+ * All the handlers MUST be implemented, except @rx_rss which can be left
+ * out *iff* the opmode will never run on hardware with multi-queue capability.
*
* @start: start the op_mode. The transport layer is already allocated.
* May sleep
@@ -116,6 +119,10 @@ struct iwl_cfg;
* May sleep
* @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
* HCMD this Rx responds to. Can't sleep.
+ * @rx_rss: data queue RX notification to the op_mode, for (data) notifications
+ * received on the RSS queue(s). The queue parameter indicates which of the
+ * RSS queues received this frame; it will always be non-zero.
+ * This method must not sleep.
* @queue_full: notifies that a HW queue is full.
* Must be atomic and called with BH disabled.
* @queue_not_full: notifies that a HW queue is not full any more.
@@ -146,6 +153,8 @@ struct iwl_op_mode_ops {
void (*stop)(struct iwl_op_mode *op_mode);
void (*rx)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb);
+ void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, unsigned int queue);
void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
@@ -186,6 +195,14 @@ static inline void iwl_op_mode_rx(struct iwl_op_mode *op_mode,
return op_mode->ops->rx(op_mode, napi, rxb);
}
+static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode,
+ struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb,
+ unsigned int queue)
+{
+ op_mode->ops->rx_rss(op_mode, napi, rxb, queue);
+}
+
static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode,
int queue)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 9f8bcefc04c5..71610968c365 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -87,6 +87,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
trans->cfg = cfg;
trans->ops = ops;
trans->dev_cmd_headroom = dev_cmd_headroom;
+ trans->num_rx_queues = 1;
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
"iwl_cmd_pool:%s", dev_name(trans->dev));
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index c829c505e141..6f76525088f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -386,6 +386,7 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
#define IWL_MAX_HW_QUEUES 32
#define IWL_MAX_TID_COUNT 8
#define IWL_FRAME_LIMIT 64
+#define IWL_MAX_RX_HW_QUEUES 16
/**
* enum iwl_wowlan_status - WoWLAN image/device status
@@ -408,6 +409,7 @@ enum iwl_d3_status {
* @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands
* 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
*/
enum iwl_trans_status {
STATUS_SYNC_HCMD_ACTIVE,
@@ -418,6 +420,7 @@ enum iwl_trans_status {
STATUS_FW_ERROR,
STATUS_TRANS_GOING_IDLE,
STATUS_TRANS_IDLE,
+ STATUS_TRANS_DEAD,
};
/**
@@ -654,6 +657,8 @@ enum iwl_d0i3_mode {
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
+ * @num_rx_queues: number of RX queues allocated by the transport;
+ * the transport must set this before calling iwl_drv_start()
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
* The user should use iwl_trans_{alloc,free}_tx_cmd.
* @dev_cmd_headroom: room needed for the transport's private use before the
@@ -693,6 +698,8 @@ struct iwl_trans {
bool pm_support;
bool ltr_enabled;
+ u8 num_rx_queues;
+
/* The following fields are internal only */
struct kmem_cache *dev_cmd_pool;
size_t dev_cmd_headroom;
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index b8ee3121fbd2..5c21231e195d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -71,6 +71,9 @@
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
+#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */
+#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */
+#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
@@ -101,7 +104,7 @@
#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
#define IWL_MVM_QUOTA_THRESHOLD 4
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
-#define IWL_MVM_RS_DISABLE_P2P_MIMO 0
+#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
#define IWL_MVM_TOF_IS_RESPONDER 0
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 04264e417c1c..85ae902df7c0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -274,18 +274,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
break;
case WLAN_CIPHER_SUITE_CCMP:
if (sta) {
- u8 *pn = seq.ccmp.pn;
+ u64 pn64;
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
- ieee80211_get_key_tx_seq(key, &seq);
- aes_tx_sc->pn = cpu_to_le64((u64)pn[5] |
- ((u64)pn[4] << 8) |
- ((u64)pn[3] << 16) |
- ((u64)pn[2] << 24) |
- ((u64)pn[1] << 32) |
- ((u64)pn[0] << 40));
+ pn64 = atomic64_read(&key->tx_pn);
+ aes_tx_sc->pn = cpu_to_le64(pn64);
} else {
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
}
@@ -298,12 +293,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
u8 *pn = seq.ccmp.pn;
ieee80211_get_key_rx_seq(key, i, &seq);
- aes_sc->pn = cpu_to_le64((u64)pn[5] |
- ((u64)pn[4] << 8) |
- ((u64)pn[3] << 16) |
- ((u64)pn[2] << 24) |
- ((u64)pn[1] << 32) |
- ((u64)pn[0] << 40));
+ aes_sc[i].pn = cpu_to_le64((u64)pn[5] |
+ ((u64)pn[4] << 8) |
+ ((u64)pn[3] << 16) |
+ ((u64)pn[2] << 24) |
+ ((u64)pn[1] << 32) |
+ ((u64)pn[0] << 40));
}
data->use_rsc_tsc = true;
break;
@@ -1170,6 +1165,9 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
+ /* make sure the d0i3 exit work is not pending */
+ flush_work(&mvm->d0i3_exit_work);
+
ret = iwl_trans_suspend(mvm->trans);
if (ret)
return ret;
@@ -1453,15 +1451,15 @@ static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
- iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq);
iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key);
+ atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
break;
case WLAN_CIPHER_SUITE_TKIP:
iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
+ ieee80211_set_key_tx_seq(key, &seq);
break;
}
- ieee80211_set_key_tx_seq(key, &seq);
/* that's it for this key */
return;
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index 383a3162046c..7904b41a04c6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -511,7 +511,8 @@ static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
- int value, ret = -EINVAL;
+ u32 value;
+ int ret = -EINVAL;
char *data;
mutex_lock(&mvm->mutex);
@@ -599,7 +600,8 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
- int value, ret = 0;
+ u32 value;
+ int ret = 0;
char *data;
mutex_lock(&mvm->mutex);
@@ -713,11 +715,30 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
goto out;
}
- data = iwl_dbgfs_is_match("ctrl_ch_position=", buf);
+ 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)
- mvm->tof_data.responder_cfg.ctrl_ch_position = value;
+ if (ret == 0 && value) {
+ enum ieee80211_band band = (cmd->channel_num <= 14) ?
+ IEEE80211_BAND_2GHZ :
+ IEEE80211_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;
}
@@ -822,7 +843,8 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
- int value, ret = 0;
+ u32 value;
+ int ret = 0;
char *data;
mutex_lock(&mvm->mutex);
@@ -892,6 +914,7 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
goto out;
}
memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN);
+ goto out;
}
data = iwl_dbgfs_is_match("macaddr_mask=", buf);
@@ -903,21 +926,22 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
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;
+ 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 %hhx %hhx"
+ if (sscanf(data, "%u %hhd %hhd %hhd"
"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
- "%hhx %hhx %hx"
- "%hhx %hhx %x"
- "%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,
@@ -944,12 +968,12 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
data = iwl_dbgfs_is_match("send_range_request=", buf);
if (data) {
ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value) {
+ if (ret == 0 && value)
ret = iwl_mvm_tof_range_request_cmd(mvm, vif);
- goto out;
- }
+ goto out;
}
+ ret = -EINVAL;
out:
mutex_unlock(&mvm->mutex);
return ret ?: count;
@@ -994,16 +1018,18 @@ static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file,
struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i];
pos += scnprintf(buf + pos, bufsz - pos,
- "ap %.2d: channel_num=%hhx bw=%hhx"
- " control=%hhx bssid=%pM type=%hhx"
- " num_of_bursts=%hhx burst_period=%hx ftm=%hhx"
- " retries=%hhx tsf_delta=%x location_req=%hhx "
- " asap=%hhx enable=%hhx rssi=%hhx\n",
+ "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);
}
@@ -1019,7 +1045,8 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
- int value, ret = 0;
+ u32 value;
+ int ret = 0;
char *data;
mutex_lock(&mvm->mutex);
@@ -1071,12 +1098,12 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif,
data = iwl_dbgfs_is_match("send_range_req_ext=", buf);
if (data) {
ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value) {
+ if (ret == 0 && value)
ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif);
- goto out;
- }
+ goto out;
}
+ ret = -EINVAL;
out:
mutex_unlock(&mvm->mutex);
return ret ?: count;
@@ -1099,18 +1126,18 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file,
mutex_lock(&mvm->mutex);
pos += scnprintf(buf + pos, bufsz - pos,
- "tsf_timer_offset_msec = %hx\n",
+ "tsf_timer_offset_msec = %hd\n",
cmd->tsf_timer_offset_msec);
- pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhx\n",
+ 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 = %hhx\n",
+ "ftm_format_and_bw20M = %hhd\n",
cmd->ftm_format_and_bw20M);
pos += scnprintf(buf + pos, bufsz - pos,
- "ftm_format_and_bw40M = %hhx\n",
+ "ftm_format_and_bw40M = %hhd\n",
cmd->ftm_format_and_bw40M);
pos += scnprintf(buf + pos, bufsz - pos,
- "ftm_format_and_bw80M = %hhx\n",
+ "ftm_format_and_bw80M = %hhd\n",
cmd->ftm_format_and_bw80M);
mutex_unlock(&mvm->mutex);
@@ -1123,8 +1150,8 @@ static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
- int value, ret = 0;
- int abort_id;
+ u32 value;
+ int abort_id, ret = 0;
char *data;
mutex_lock(&mvm->mutex);
@@ -1205,11 +1232,11 @@ static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file,
struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i];
pos += scnprintf(buf + pos, bufsz - pos,
- "ap %.2d: bssid=%pM status=%hhx bw=%hhx"
- " rtt=%x rtt_var=%x rtt_spread=%x"
- " rssi=%hhx rssi_spread=%hhx"
- " range=%x range_var=%x"
- " time_stamp=%x\n",
+ "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,
@@ -1250,11 +1277,10 @@ 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[3];
+ char buf[2];
buf[0] = mvmvif->low_latency ? '1' : '0';
buf[1] = '\n';
- buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 7d69a556bcc8..05928fb4021d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -85,7 +85,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count;
+ ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count;
mutex_unlock(&mvm->mutex);
return ret;
@@ -1214,118 +1214,6 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
return ret;
}
-
-#define MAX_NUM_ND_MATCHSETS 10
-
-static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf,
- size_t count, loff_t *ppos)
-{
- const char *seps = ",\n";
- char *buf_ptr = buf;
- char *value_str = NULL;
- int ret, i;
-
- /* TODO: don't free if write is being called several times in one go */
- if (mvm->nd_config) {
- kfree(mvm->nd_config->match_sets);
- kfree(mvm->nd_config);
- mvm->nd_config = NULL;
- }
-
- mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) +
- (11 * sizeof(struct ieee80211_channel *)),
- GFP_KERNEL);
- if (!mvm->nd_config) {
- ret = -ENOMEM;
- goto out_free;
- }
-
- mvm->nd_config->n_channels = 11;
- mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20;
- mvm->nd_config->interval = 5;
- mvm->nd_config->min_rssi_thold = -80;
- for (i = 0; i < mvm->nd_config->n_channels; i++)
- mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i];
-
- mvm->nd_config->match_sets =
- kcalloc(MAX_NUM_ND_MATCHSETS,
- sizeof(*mvm->nd_config->match_sets),
- GFP_KERNEL);
- if (!mvm->nd_config->match_sets) {
- ret = -ENOMEM;
- goto out_free;
- }
-
- while ((value_str = strsep(&buf_ptr, seps)) &&
- strlen(value_str)) {
- struct cfg80211_match_set *set;
-
- if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) {
- ret = -EINVAL;
- goto out_free;
- }
-
- set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets];
- set->ssid.ssid_len = strlen(value_str);
-
- if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
- ret = -EINVAL;
- goto out_free;
- }
-
- memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len);
-
- mvm->nd_config->n_match_sets++;
- }
-
- ret = count;
-
- if (mvm->nd_config->n_match_sets)
- goto out;
-
-out_free:
- if (mvm->nd_config)
- kfree(mvm->nd_config->match_sets);
- kfree(mvm->nd_config);
- mvm->nd_config = NULL;
-out:
- return ret;
-}
-
-static ssize_t
-iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm *mvm = file->private_data;
- size_t bufsz, ret;
- char *buf;
- int i, n_match_sets, pos = 0;
-
- n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0;
-
- bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1;
- buf = kzalloc(bufsz, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for (i = 0; i < n_match_sets; i++) {
- if (pos +
- mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) {
- ret = -EIO;
- goto out;
- }
-
- memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid,
- mvm->nd_config->match_sets[i].ssid.ssid_len);
- pos += mvm->nd_config->match_sets[i].ssid.ssid_len;
- buf[pos++] = '\n';
- }
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-out:
- kfree(buf);
- return ret;
-}
#endif
#define PRINT_MVM_REF(ref) do { \
@@ -1473,11 +1361,25 @@ out:
return count;
}
+static ssize_t
+iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
+ size_t count, loff_t *ppos)
+{
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+ ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
+ mutex_unlock(&mvm->mutex);
+
+ return ret ?: count;
+}
+
MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
/* Device wide debugfs entries */
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
+MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
@@ -1503,7 +1405,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384);
#endif
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
@@ -1538,6 +1439,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
+ MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
if (!debugfs_create_bool("enable_scan_iteration_notif",
S_IRUSR | S_IWUSR,
mvm->debugfs_dir,
@@ -1572,7 +1474,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR,
mvm->debugfs_dir, &mvm->last_netdetect_scans))
goto err;
- MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
#endif
if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
@@ -1594,6 +1495,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
if (!debugfs_create_blob("nvm_prod", S_IRUSR,
mvm->debugfs_dir, &mvm->nvm_prod_blob))
goto err;
+ if (!debugfs_create_blob("nvm_phy_sku", S_IRUSR,
+ mvm->debugfs_dir, &mvm->nvm_phy_sku_blob))
+ goto err;
/*
* Create a symlink with mac80211. It will be removed when mac80211
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 7005fa4be74a..c8f3e2536cbb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -192,16 +192,10 @@ struct iwl_powertable_cmd {
/**
* enum iwl_device_power_flags - masks for device power command flags
* @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
- * receiver and transmitter. '0' - does not allow. This flag should be
- * always set to '1' unless one need to disable actual power down for debug
- * purposes.
- * @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning
- * that power management is disabled. '0' Power management is enabled, one
- * of power schemes is applied.
+ * receiver and transmitter. '0' - does not allow.
*/
enum iwl_device_power_flags {
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
- DEVICE_POWER_FLAGS_CAM_MSK = BIT(13),
};
/**
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h
new file mode 100644
index 000000000000..9b7e49d4620f
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h
@@ -0,0 +1,238 @@
+/******************************************************************************
+ *
+ * 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) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * 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 __fw_api_rx_h__
+#define __fw_api_rx_h__
+
+#define IWL_RX_INFO_PHY_CNT 8
+#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
+#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
+#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
+#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
+#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
+#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
+#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
+
+/**
+ * struct iwl_rx_phy_info - phy info
+ * (REPLY_RX_PHY_CMD = 0xc0)
+ * @non_cfg_phy_cnt: non configurable DSP phy data byte count
+ * @cfg_phy_cnt: configurable DSP phy data byte count
+ * @stat_id: configurable DSP phy data set ID
+ * @reserved1:
+ * @system_timestamp: GP2 at on air rise
+ * @timestamp: TSF at on air rise
+ * @beacon_time_stamp: beacon at on-air rise
+ * @phy_flags: general phy flags: band, modulation, ...
+ * @channel: channel number
+ * @non_cfg_phy_buf: for various implementations of non_cfg_phy
+ * @rate_n_flags: RATE_MCS_*
+ * @byte_count: frame's byte-count
+ * @frame_time: frame's time on the air, based on byte count and frame rate
+ * calculation
+ * @mac_active_msk: what MACs were active when the frame was received
+ *
+ * Before each Rx, the device sends this data. It contains PHY information
+ * about the reception of the packet.
+ */
+struct iwl_rx_phy_info {
+ u8 non_cfg_phy_cnt;
+ u8 cfg_phy_cnt;
+ u8 stat_id;
+ u8 reserved1;
+ __le32 system_timestamp;
+ __le64 timestamp;
+ __le32 beacon_time_stamp;
+ __le16 phy_flags;
+ __le16 channel;
+ __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
+ __le32 rate_n_flags;
+ __le32 byte_count;
+ __le16 mac_active_msk;
+ __le16 frame_time;
+} __packed;
+
+/*
+ * TCP offload Rx assist info
+ *
+ * bits 0:3 - reserved
+ * bits 4:7 - MIC CRC length
+ * bits 8:12 - MAC header length
+ * bit 13 - Padding indication
+ * bit 14 - A-AMSDU indication
+ * bit 15 - Offload enabled
+ */
+enum iwl_csum_rx_assist_info {
+ CSUM_RXA_RESERVED_MASK = 0x000f,
+ CSUM_RXA_MICSIZE_MASK = 0x00f0,
+ CSUM_RXA_HEADERLEN_MASK = 0x1f00,
+ CSUM_RXA_PADD = BIT(13),
+ CSUM_RXA_AMSDU = BIT(14),
+ CSUM_RXA_ENA = BIT(15)
+};
+
+/**
+ * struct iwl_rx_mpdu_res_start - phy info
+ * @assist: see CSUM_RX_ASSIST_ above
+ */
+struct iwl_rx_mpdu_res_start {
+ __le16 byte_count;
+ __le16 assist;
+} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */
+
+/**
+ * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags
+ * @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band
+ * @RX_RES_PHY_FLAGS_MOD_CCK:
+ * @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short
+ * @RX_RES_PHY_FLAGS_NARROW_BAND:
+ * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received
+ * @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU
+ * @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame
+ * @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble
+ * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame
+ */
+enum iwl_rx_phy_flags {
+ RX_RES_PHY_FLAGS_BAND_24 = BIT(0),
+ RX_RES_PHY_FLAGS_MOD_CCK = BIT(1),
+ RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2),
+ RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3),
+ RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4),
+ RX_RES_PHY_FLAGS_ANTENNA_POS = 4,
+ RX_RES_PHY_FLAGS_AGG = BIT(7),
+ RX_RES_PHY_FLAGS_OFDM_HT = BIT(8),
+ RX_RES_PHY_FLAGS_OFDM_GF = BIT(9),
+ RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10),
+};
+
+/**
+ * enum iwl_mvm_rx_status - written by fw for each Rx packet
+ * @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine
+ * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow
+ * @RX_MPDU_RES_STATUS_SRC_STA_FOUND:
+ * @RX_MPDU_RES_STATUS_KEY_VALID:
+ * @RX_MPDU_RES_STATUS_KEY_PARAM_OK:
+ * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed
+ * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked
+ * in the driver.
+ * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine
+ * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or
+ * alg = CCM only. Checks replay attack for 11w frames. Relevant only if
+ * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set.
+ * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted
+ * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP
+ * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM
+ * @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP
+ * @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC
+ * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted
+ * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm
+ * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted
+ * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP:
+ * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:
+ * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:
+ * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame
+ * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw
+ * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
+ * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK:
+ * @RX_MPDU_RES_STATUS_STA_ID_MSK:
+ * @RX_MPDU_RES_STATUS_RRF_KILL:
+ * @RX_MPDU_RES_STATUS_FILTERING_MSK:
+ * @RX_MPDU_RES_STATUS2_FILTERING_MSK:
+ */
+enum iwl_mvm_rx_status {
+ RX_MPDU_RES_STATUS_CRC_OK = BIT(0),
+ RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1),
+ RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2),
+ RX_MPDU_RES_STATUS_KEY_VALID = BIT(3),
+ RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4),
+ RX_MPDU_RES_STATUS_ICV_OK = BIT(5),
+ RX_MPDU_RES_STATUS_MIC_OK = BIT(6),
+ RX_MPDU_RES_STATUS_TTAK_OK = BIT(7),
+ RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7),
+ RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8),
+ RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8),
+ RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8),
+ RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8),
+ RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8),
+ RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8),
+ RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8),
+ RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8),
+ RX_MPDU_RES_STATUS_DEC_DONE = BIT(11),
+ RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12),
+ RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13),
+ RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14),
+ RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15),
+ RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
+ RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
+ RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
+ RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000),
+ RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
+ RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
+ RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
+};
+
+#endif /* __fw_api_rx_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 660cc1c93e19..3a657e4b60ac 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -101,6 +101,7 @@ struct iwl_ssid_ie {
#define IWL_FULL_SCAN_MULTIPLIER 5
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
+#define IWL_MAX_SCHED_SCAN_PLANS 2
enum scan_framework_client {
SCAN_CLIENT_SCHED_SCAN = BIT(0),
@@ -359,7 +360,7 @@ struct iwl_scan_req_lmac {
/* SCAN_REQ_PERIODIC_PARAMS_API_S */
__le32 iter_num;
__le32 delay;
- struct iwl_scan_schedule_lmac schedule[2];
+ struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS];
struct iwl_scan_channel_opt channel_opt[2];
u8 data[];
} __packed;
@@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule {
*/
struct iwl_scan_req_umac_tail {
/* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
- struct iwl_scan_umac_schedule schedule[2];
+ struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS];
__le16 delay;
__le16 reserved;
/* SCAN_PROBE_PARAMS_API_S_VER_1 */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h
index 709e28d8b1b0..0c321f63ee42 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h
@@ -219,32 +219,6 @@ struct mvm_statistics_bt_activity {
__le32 lo_priority_rx_denied_cnt;
} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */
-struct mvm_statistics_general_v5 {
- __le32 radio_temperature;
- __le32 radio_voltage;
- struct mvm_statistics_dbg dbg;
- __le32 sleep_time;
- __le32 slots_out;
- __le32 slots_idle;
- __le32 ttl_timestamp;
- struct mvm_statistics_div slow_div;
- __le32 rx_enable_counter;
- /*
- * num_of_sos_states:
- * count the number of times we have to re-tune
- * in order to get out of bad PHY status
- */
- __le32 num_of_sos_states;
- __le32 beacon_filtered;
- __le32 missed_beacons;
- __s8 beacon_filter_average_energy;
- __s8 beacon_filter_reason;
- __s8 beacon_filter_current_energy;
- __s8 beacon_filter_reserved;
- __le32 beacon_filter_delta_time;
- struct mvm_statistics_bt_activity bt_activity;
-} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */
-
struct mvm_statistics_general_v8 {
__le32 radio_temperature;
__le32 radio_voltage;
@@ -263,10 +237,10 @@ struct mvm_statistics_general_v8 {
__le32 num_of_sos_states;
__le32 beacon_filtered;
__le32 missed_beacons;
- __s8 beacon_filter_average_energy;
- __s8 beacon_filter_reason;
- __s8 beacon_filter_current_energy;
- __s8 beacon_filter_reserved;
+ u8 beacon_filter_average_energy;
+ u8 beacon_filter_reason;
+ u8 beacon_filter_current_energy;
+ u8 beacon_filter_reserved;
__le32 beacon_filter_delta_time;
struct mvm_statistics_bt_activity bt_activity;
__le64 rx_time;
@@ -293,13 +267,6 @@ struct mvm_statistics_rx {
* STATISTICS_CMD (0x9c), below.
*/
-struct iwl_notif_statistics_v8 {
- __le32 flag;
- struct mvm_statistics_rx rx;
- struct mvm_statistics_tx tx;
- struct mvm_statistics_general_v5 general;
-} __packed; /* STATISTICS_NTFY_API_S_VER_8 */
-
struct iwl_notif_statistics_v10 {
__le32 flag;
struct mvm_statistics_rx rx;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 4af7513adda2..181590fbd3b3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -67,6 +67,7 @@
#define __fw_api_h__
#include "fw-api-rs.h"
+#include "fw-api-rx.h"
#include "fw-api-tx.h"
#include "fw-api-sta.h"
#include "fw-api-mac.h"
@@ -100,6 +101,7 @@ enum iwl_mvm_tx_fifo {
enum {
MVM_ALIVE = 0x1,
REPLY_ERROR = 0x2,
+ ECHO_CMD = 0x3,
INIT_COMPLETE_NOTIF = 0x4,
@@ -266,6 +268,16 @@ enum {
REPLY_MAX = 0xff,
};
+enum iwl_phy_ops_subcmd_ids {
+ CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
+ DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
+};
+
+/* command groups */
+enum {
+ PHY_OPS_GROUP = 0x4,
+};
+
/**
* struct iwl_cmd_response - generic response struct for most commands
* @status: status of the command asked, changes for each one
@@ -1070,190 +1082,6 @@ struct iwl_hs20_roc_res {
__le32 status;
} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
-#define IWL_RX_INFO_PHY_CNT 8
-#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
-#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
-#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
-#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
-#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
-#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
-#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
-
-#define IWL_RX_INFO_AGC_IDX 1
-#define IWL_RX_INFO_RSSI_AB_IDX 2
-#define IWL_OFDM_AGC_A_MSK 0x0000007f
-#define IWL_OFDM_AGC_A_POS 0
-#define IWL_OFDM_AGC_B_MSK 0x00003f80
-#define IWL_OFDM_AGC_B_POS 7
-#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000
-#define IWL_OFDM_AGC_CODE_POS 20
-#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
-#define IWL_OFDM_RSSI_A_POS 0
-#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
-#define IWL_OFDM_RSSI_ALLBAND_A_POS 8
-#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
-#define IWL_OFDM_RSSI_B_POS 16
-#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
-#define IWL_OFDM_RSSI_ALLBAND_B_POS 24
-
-/**
- * struct iwl_rx_phy_info - phy info
- * (REPLY_RX_PHY_CMD = 0xc0)
- * @non_cfg_phy_cnt: non configurable DSP phy data byte count
- * @cfg_phy_cnt: configurable DSP phy data byte count
- * @stat_id: configurable DSP phy data set ID
- * @reserved1:
- * @system_timestamp: GP2 at on air rise
- * @timestamp: TSF at on air rise
- * @beacon_time_stamp: beacon at on-air rise
- * @phy_flags: general phy flags: band, modulation, ...
- * @channel: channel number
- * @non_cfg_phy_buf: for various implementations of non_cfg_phy
- * @rate_n_flags: RATE_MCS_*
- * @byte_count: frame's byte-count
- * @frame_time: frame's time on the air, based on byte count and frame rate
- * calculation
- * @mac_active_msk: what MACs were active when the frame was received
- *
- * Before each Rx, the device sends this data. It contains PHY information
- * about the reception of the packet.
- */
-struct iwl_rx_phy_info {
- u8 non_cfg_phy_cnt;
- u8 cfg_phy_cnt;
- u8 stat_id;
- u8 reserved1;
- __le32 system_timestamp;
- __le64 timestamp;
- __le32 beacon_time_stamp;
- __le16 phy_flags;
- __le16 channel;
- __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
- __le32 rate_n_flags;
- __le32 byte_count;
- __le16 mac_active_msk;
- __le16 frame_time;
-} __packed;
-
-/*
- * TCP offload Rx assist info
- *
- * bits 0:3 - reserved
- * bits 4:7 - MIC CRC length
- * bits 8:12 - MAC header length
- * bit 13 - Padding indication
- * bit 14 - A-AMSDU indication
- * bit 15 - Offload enabled
- */
-enum iwl_csum_rx_assist_info {
- CSUM_RXA_RESERVED_MASK = 0x000f,
- CSUM_RXA_MICSIZE_MASK = 0x00f0,
- CSUM_RXA_HEADERLEN_MASK = 0x1f00,
- CSUM_RXA_PADD = BIT(13),
- CSUM_RXA_AMSDU = BIT(14),
- CSUM_RXA_ENA = BIT(15)
-};
-
-/**
- * struct iwl_rx_mpdu_res_start - phy info
- * @assist: see CSUM_RX_ASSIST_ above
- */
-struct iwl_rx_mpdu_res_start {
- __le16 byte_count;
- __le16 assist;
-} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */
-
-/**
- * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags
- * @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band
- * @RX_RES_PHY_FLAGS_MOD_CCK:
- * @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short
- * @RX_RES_PHY_FLAGS_NARROW_BAND:
- * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received
- * @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU
- * @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame
- * @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble
- * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame
- */
-enum iwl_rx_phy_flags {
- RX_RES_PHY_FLAGS_BAND_24 = BIT(0),
- RX_RES_PHY_FLAGS_MOD_CCK = BIT(1),
- RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2),
- RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3),
- RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4),
- RX_RES_PHY_FLAGS_ANTENNA_POS = 4,
- RX_RES_PHY_FLAGS_AGG = BIT(7),
- RX_RES_PHY_FLAGS_OFDM_HT = BIT(8),
- RX_RES_PHY_FLAGS_OFDM_GF = BIT(9),
- RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10),
-};
-
-/**
- * enum iwl_mvm_rx_status - written by fw for each Rx packet
- * @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine
- * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow
- * @RX_MPDU_RES_STATUS_SRC_STA_FOUND:
- * @RX_MPDU_RES_STATUS_KEY_VALID:
- * @RX_MPDU_RES_STATUS_KEY_PARAM_OK:
- * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed
- * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked
- * in the driver.
- * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine
- * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or
- * alg = CCM only. Checks replay attack for 11w frames. Relevant only if
- * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set.
- * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted
- * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP
- * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM
- * @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP
- * @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC
- * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted
- * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm
- * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted
- * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP:
- * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:
- * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:
- * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame
- * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw
- * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
- * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK:
- * @RX_MPDU_RES_STATUS_STA_ID_MSK:
- * @RX_MPDU_RES_STATUS_RRF_KILL:
- * @RX_MPDU_RES_STATUS_FILTERING_MSK:
- * @RX_MPDU_RES_STATUS2_FILTERING_MSK:
- */
-enum iwl_mvm_rx_status {
- RX_MPDU_RES_STATUS_CRC_OK = BIT(0),
- RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1),
- RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2),
- RX_MPDU_RES_STATUS_KEY_VALID = BIT(3),
- RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4),
- RX_MPDU_RES_STATUS_ICV_OK = BIT(5),
- RX_MPDU_RES_STATUS_MIC_OK = BIT(6),
- RX_MPDU_RES_STATUS_TTAK_OK = BIT(7),
- RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7),
- RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8),
- RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8),
- RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8),
- RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8),
- RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8),
- RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8),
- RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8),
- RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8),
- RX_MPDU_RES_STATUS_DEC_DONE = BIT(11),
- RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12),
- RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13),
- RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14),
- RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15),
- RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
- RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
- RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
- RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000),
- RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
- RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
- RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
-};
-
/**
* struct iwl_radio_version_notif - information on the radio version
* ( RADIO_VERSION_NOTIFICATION = 0x68 )
@@ -1696,6 +1524,69 @@ struct iwl_dts_measurement_cmd {
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */
/**
+* enum iwl_dts_control_measurement_mode - DTS measurement type
+* @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read
+* back (latest value. Not waiting for new value). Use automatic
+* SW DTS configuration.
+* @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings,
+* trigger DTS reading and provide read back temperature read
+* when available.
+* @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read
+* @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result,
+* without measurement trigger.
+*/
+enum iwl_dts_control_measurement_mode {
+ DTS_AUTOMATIC = 0,
+ DTS_REQUEST_READ = 1,
+ DTS_OVER_WRITE = 2,
+ DTS_DIRECT_WITHOUT_MEASURE = 3,
+};
+
+/**
+* enum iwl_dts_used - DTS to use or used for measurement in the DTS request
+* @DTS_USE_TOP: Top
+* @DTS_USE_CHAIN_A: chain A
+* @DTS_USE_CHAIN_B: chain B
+* @DTS_USE_CHAIN_C: chain C
+* @XTAL_TEMPERATURE - read temperature from xtal
+*/
+enum iwl_dts_used {
+ DTS_USE_TOP = 0,
+ DTS_USE_CHAIN_A = 1,
+ DTS_USE_CHAIN_B = 2,
+ DTS_USE_CHAIN_C = 3,
+ XTAL_TEMPERATURE = 4,
+};
+
+/**
+* enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode
+* @DTS_BIT6_MODE: bit 6 mode
+* @DTS_BIT8_MODE: bit 8 mode
+*/
+enum iwl_dts_bit_mode {
+ DTS_BIT6_MODE = 0,
+ DTS_BIT8_MODE = 1,
+};
+
+/**
+ * iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements
+ * @control_mode: see &enum iwl_dts_control_measurement_mode
+ * @temperature: used when over write DTS mode is selected
+ * @sensor: set temperature sensor to use. See &enum iwl_dts_used
+ * @avg_factor: average factor to DTS in request DTS read mode
+ * @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode
+ * @step_duration: step duration for the DTS
+ */
+struct iwl_ext_dts_measurement_cmd {
+ __le32 control_mode;
+ __le32 temperature;
+ __le32 sensor;
+ __le32 avg_factor;
+ __le32 bit_mode;
+ __le32 step_duration;
+} __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */
+
+/**
* iwl_dts_measurement_notif - notification received with the measurements
*
* @temp: the measured temperature
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 4a0ce83315bd..d906fa13ba97 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -616,12 +616,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
* will be empty.
*/
- for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
- if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE)
- mvm->queue_to_mac80211[i] = i;
- else
- mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
- }
+ memset(&mvm->queue_info, 0, sizeof(mvm->queue_info));
+ mvm->queue_info[IWL_MVM_CMD_QUEUE].hw_queue_refcount = 1;
for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
@@ -703,7 +699,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
* abort after reading the nvm in case RF Kill is on, we will complete
* the init seq later when RF kill will switch to off
*/
- if (iwl_mvm_is_radio_killed(mvm)) {
+ if (iwl_mvm_is_radio_hw_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm,
"jump over all phy activities due to RF kill\n");
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
@@ -736,7 +732,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
MVM_UCODE_CALIB_TIMEOUT);
- if (ret && iwl_mvm_is_radio_killed(mvm)) {
+ if (ret && iwl_mvm_is_radio_hw_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
ret = 1;
}
@@ -940,19 +936,6 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
return ret;
}
-static int iwl_mvm_config_ltr_v1(struct iwl_mvm *mvm)
-{
- struct iwl_ltr_config_cmd_v1 cmd_v1 = {
- .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
- };
-
- if (!mvm->trans->ltr_enabled)
- return 0;
-
- return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
- sizeof(cmd_v1), &cmd_v1);
-}
-
static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
{
struct iwl_ltr_config_cmd cmd = {
@@ -962,9 +945,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
if (!mvm->trans->ltr_enabled)
return 0;
- if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_HDC_PHASE_0))
- return iwl_mvm_config_ltr_v1(mvm);
-
return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
sizeof(cmd), &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 3424315dd876..ad7ad720d2e7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * 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
@@ -33,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -484,16 +486,18 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_TX_FIFO_VO, wdg_timeout);
+ IWL_MVM_OFFCHANNEL_QUEUE,
+ IWL_MVM_TX_FIFO_VO, 0, wdg_timeout);
break;
case NL80211_IFTYPE_AP:
- iwl_mvm_enable_ac_txq(mvm, vif->cab_queue,
- IWL_MVM_TX_FIFO_MCAST, wdg_timeout);
+ iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue,
+ IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
/* fall through */
default:
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac],
- iwl_mvm_ac_to_tx_fifo[ac],
+ vif->hw_queue[ac],
+ iwl_mvm_ac_to_tx_fifo[ac], 0,
wdg_timeout);
break;
}
@@ -509,14 +513,19 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
- iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, 0);
+ iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
+ IWL_MVM_OFFCHANNEL_QUEUE, IWL_MAX_TID_COUNT,
+ 0);
break;
case NL80211_IFTYPE_AP:
- iwl_mvm_disable_txq(mvm, vif->cab_queue, 0);
+ iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
+ IWL_MAX_TID_COUNT, 0);
/* fall through */
default:
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], 0);
+ iwl_mvm_disable_txq(mvm, vif->hw_queue[ac],
+ vif->hw_queue[ac],
+ IWL_MAX_TID_COUNT, 0);
}
}
@@ -834,6 +843,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);
+ if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p)
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
+
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
@@ -1128,6 +1140,7 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 action)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mac_ctx_cmd cmd = {};
WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
@@ -1137,10 +1150,16 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
/*
* pass probe requests and beacons from other APs (needed
- * for ht protection)
+ * for ht protection); when there're no any associated station
+ * don't ask FW to pass beacons to prevent unnecessary wake-ups.
*/
- cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
- MAC_FILTER_IN_BEACON);
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
+ if (mvmvif->ap_assoc_sta_count) {
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
+ IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
+ } else {
+ IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
+ }
/* Fill the data specific for ap mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index aa8c2b7f23c7..1fb684693040 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
/* we create the 802.11 header and zero length SSID IE. */
hw->wiphy->max_sched_scan_ie_len =
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
+ hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS;
+ hw->wiphy->max_sched_scan_plan_interval = U16_MAX;
+
+ /*
+ * the firmware uses u8 for num of iterations, but 0xff is saved for
+ * infinite loop, so the maximum number of iterations is actually 254.
+ */
+ hw->wiphy->max_sched_scan_plan_iterations = 254;
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
NL80211_FEATURE_LOW_PRIORITY_SCAN |
@@ -820,7 +828,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid,
- u16 *ssn, u8 buf_size)
+ u16 *ssn, u8 buf_size, bool amsdu)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -1129,6 +1137,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
+ /* there's no point in fw dump if the bus is dead */
+ if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
+ IWL_ERR(mvm, "Skip fw error dump since bus is dead\n");
+ return;
+ }
+
if (mvm->fw_dump_trig &&
mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)
monitor_dump_only = true;
@@ -1192,6 +1206,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
if (sram2_len)
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
+ /* Make room for fw's virtual image pages, if it exists */
+ if (mvm->fw->img[mvm->cur_ucode].paging_mem_size)
+ file_len += mvm->num_of_paging_blk *
+ (sizeof(*dump_data) +
+ sizeof(struct iwl_fw_error_dump_paging) +
+ PAGING_BLOCK_SIZE);
+
/* If we only want a monitor dump, reset the file length */
if (monitor_dump_only) {
file_len = sizeof(*dump_file) + sizeof(*dump_data) +
@@ -1302,6 +1323,26 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
dump_mem->data, IWL8260_ICCM_LEN);
}
+ /* Dump fw's virtual image */
+ if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) {
+ u32 i;
+
+ for (i = 1; i < mvm->num_of_paging_blk + 1; i++) {
+ struct iwl_fw_error_dump_paging *paging;
+ struct page *pages =
+ mvm->fw_paging_db[i].fw_paging_block;
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
+ dump_data->len = cpu_to_le32(sizeof(*paging) +
+ PAGING_BLOCK_SIZE);
+ paging = (void *)dump_data->data;
+ paging->index = cpu_to_le32(i);
+ memcpy(paging->data, page_address(pages),
+ PAGING_BLOCK_SIZE);
+ }
+ }
+
dump_trans_data:
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans,
mvm->fw_dump_trig);
@@ -1577,20 +1618,6 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
return NULL;
}
-static int iwl_mvm_set_tx_power_old(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif, s8 tx_power)
-{
- /* FW is in charge of regulatory enforcement */
- struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
- .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
- .pwr_restriction = cpu_to_le16(tx_power),
- };
-
- return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0,
- sizeof(reduce_txpwr_cmd),
- &reduce_txpwr_cmd);
-}
-
static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s16 tx_power)
{
@@ -1602,9 +1629,6 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
};
int len = sizeof(cmd);
- if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_DEV))
- return iwl_mvm_set_tx_power_old(mvm, vif, tx_power);
-
if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
cmd.v2.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
@@ -1771,7 +1795,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
* Flush them here.
*/
mutex_lock(&mvm->mutex);
- iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
+ iwl_mvm_flush_tx_path(mvm, tfd_msk, 0);
mutex_unlock(&mvm->mutex);
/*
@@ -1972,6 +1996,27 @@ out:
*total_flags = 0;
}
+static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ unsigned int filter_flags,
+ unsigned int changed_flags)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ /* We support only filter for probe requests */
+ if (!(changed_flags & FIF_PROBE_REQ))
+ return;
+
+ /* Supported only for p2p client interfaces */
+ if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc ||
+ !vif->p2p)
+ return;
+
+ mutex_lock(&mvm->mutex);
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ mutex_unlock(&mvm->mutex);
+}
+
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
struct iwl_bcast_iter_data {
struct iwl_mvm *mvm;
@@ -2319,6 +2364,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
+ mvmvif->ap_assoc_sta_count = 0;
+
/* Add the mac context */
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret)
@@ -2388,6 +2435,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data);
RCU_INIT_POINTER(mvm->csa_vif, NULL);
+ mvmvif->csa_countdown = false;
}
if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) {
@@ -2613,6 +2661,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
/*
@@ -2627,6 +2676,12 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id]))
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
ERR_PTR(-ENOENT));
+
+ if (mvm_sta->vif->type == NL80211_IFTYPE_AP) {
+ mvmvif->ap_assoc_sta_count--;
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ }
+
mutex_unlock(&mvm->mutex);
}
@@ -3905,7 +3960,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
}
if (drop) {
- if (iwl_mvm_flush_tx_path(mvm, msk, true))
+ if (iwl_mvm_flush_tx_path(mvm, msk, 0))
IWL_ERR(mvm, "flush request fail\n");
mutex_unlock(&mvm->mutex);
} else {
@@ -4142,6 +4197,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.config = iwl_mvm_mac_config,
.prepare_multicast = iwl_mvm_prepare_multicast,
.configure_filter = iwl_mvm_configure_filter,
+ .config_iface_filter = iwl_mvm_config_iface_filter,
.bss_info_changed = iwl_mvm_bss_info_changed,
.hw_scan = iwl_mvm_mac_hw_scan,
.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index b95a07ec9e36..4bde2d027dcd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -82,7 +82,6 @@
#include "constants.h"
#include "tof.h"
-#define IWL_INVALID_MAC80211_QUEUE 0xff
#define IWL_MVM_MAX_ADDRESSES 5
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
@@ -323,11 +322,11 @@ enum iwl_bt_force_ant_mode {
struct iwl_mvm_vif_bf_data {
bool bf_enabled;
bool ba_enabled;
- s8 ave_beacon_signal;
- s8 last_cqm_event;
- s8 bt_coex_min_thold;
- s8 bt_coex_max_thold;
- s8 last_bt_coex_event;
+ int ave_beacon_signal;
+ int last_cqm_event;
+ int bt_coex_min_thold;
+ int bt_coex_max_thold;
+ int last_bt_coex_event;
};
/**
@@ -338,6 +337,8 @@ struct iwl_mvm_vif_bf_data {
* @bssid: BSSID for this (client) interface
* @associated: indicates that we're currently associated, used only for
* managing the firmware state in iwl_mvm_bss_info_changed_station()
+ * @ap_assoc_sta_count: count of stations associated to us - valid only
+ * if VIF type is AP
* @uploaded: indicates the MAC context has been added to the device
* @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
* should get quota etc.
@@ -367,6 +368,7 @@ struct iwl_mvm_vif {
u8 bssid[ETH_ALEN];
bool associated;
+ u8 ap_assoc_sta_count;
bool uploaded;
bool ap_ibss_active;
@@ -602,7 +604,14 @@ struct iwl_mvm {
u64 on_time_scan;
} radio_stats, accu_radio_stats;
- u8 queue_to_mac80211[IWL_MAX_HW_QUEUES];
+ struct {
+ /* Map to HW queue */
+ u32 hw_queue_to_mac80211;
+ u8 hw_queue_refcount;
+ bool setup_reserved;
+ u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */
+ } queue_info[IWL_MAX_HW_QUEUES];
+ spinlock_t queue_info_lock; /* For syncing queue mgmt operations */
atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES];
const char *nvm_file_name;
@@ -649,7 +658,7 @@ struct iwl_mvm {
const struct iwl_fw_bcast_filter *bcast_filters;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
- u32 override; /* u32 for debugfs_create_bool */
+ bool override;
struct iwl_bcast_filter_cmd cmd;
} dbgfs_bcast_filtering;
#endif
@@ -673,12 +682,13 @@ struct iwl_mvm {
bool disable_power_off;
bool disable_power_off_d3;
- u32 scan_iter_notif_enabled; /* must be u32 for debugfs_create_bool */
+ bool scan_iter_notif_enabled;
struct debugfs_blob_wrapper nvm_hw_blob;
struct debugfs_blob_wrapper nvm_sw_blob;
struct debugfs_blob_wrapper nvm_calib_blob;
struct debugfs_blob_wrapper nvm_prod_blob;
+ struct debugfs_blob_wrapper nvm_phy_sku_blob;
struct iwl_mvm_frame_stats drv_rx_stats;
spinlock_t drv_stats_lock;
@@ -729,7 +739,7 @@ struct iwl_mvm {
int n_nd_channels;
bool net_detect;
#ifdef CONFIG_IWLWIFI_DEBUGFS
- u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
+ bool d3_wake_sysassert;
bool d3_test_active;
bool store_d3_resume_sram;
void *d3_resume_sram;
@@ -860,6 +870,11 @@ static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
}
+static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm)
+{
+ return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
+}
+
/* Must be called with rcu_read_lock() held and it can only be
* released when mvmsta is not needed anymore.
*/
@@ -907,6 +922,12 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
}
+static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
+{
+ return fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
+}
+
static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
{
bool nvm_lar = mvm->nvm_data->lar_enabled;
@@ -934,11 +955,6 @@ static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC);
}
-static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm)
-{
- return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SCD_CFG);
-}
-
static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm)
{
return fw_has_capa(&mvm->fw->ucode_capa,
@@ -959,6 +975,12 @@ static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT);
}
+static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
+{
+ /* firmware flag isn't defined yet */
+ return false;
+}
+
extern const u8 iwl_mvm_ac_to_tx_fifo[];
struct iwl_rate_info {
@@ -1014,7 +1036,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status);
#else
static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
#endif
-int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync);
+int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags);
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
@@ -1131,7 +1153,6 @@ 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);
-
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -1344,14 +1365,20 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
}
/* hw scheduler queue config */
-void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn,
- const struct iwl_trans_txq_scd_cfg *cfg,
+void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+ u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout);
-void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags);
+/*
+ * Disable a TXQ.
+ * Note that in non-DQA mode the %mac80211_queue and %tid params are ignored.
+ */
+void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+ u8 tid, u8 flags);
+int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq);
static inline
-void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue,
- u8 fifo, unsigned int wdg_timeout)
+void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+ u8 fifo, u16 ssn, unsigned int wdg_timeout)
{
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = fifo,
@@ -1360,13 +1387,13 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue,
.frame_limit = IWL_FRAME_LIMIT,
};
- iwl_mvm_enable_txq(mvm, queue, 0, &cfg, wdg_timeout);
+ iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout);
}
static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue,
- int fifo, int sta_id, int tid,
- int frame_limit, u16 ssn,
- unsigned int wdg_timeout)
+ int mac80211_queue, int fifo,
+ int sta_id, int tid, int frame_limit,
+ u16 ssn, unsigned int wdg_timeout)
{
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = fifo,
@@ -1376,7 +1403,7 @@ static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue,
.aggregate = true,
};
- iwl_mvm_enable_txq(mvm, queue, ssn, &cfg, wdg_timeout);
+ iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout);
}
/* Thermal management and CT-kill */
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 328187da7541..2ee0f6fe56a1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -316,7 +316,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
regulatory, mac_override, phy_sku,
mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant,
- lar_enabled, mac_addr0, mac_addr1);
+ lar_enabled, mac_addr0, mac_addr1,
+ mvm->trans->hw_id);
}
#define MAX_NVM_FILE_LEN 16384
@@ -482,6 +483,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
ret = -ENOMEM;
break;
}
+ kfree(mvm->nvm_sections[section_id].data);
mvm->nvm_sections[section_id].data = temp;
mvm->nvm_sections[section_id].length = section_size;
@@ -563,6 +565,10 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
mvm->nvm_prod_blob.data = temp;
mvm->nvm_prod_blob.size = ret;
break;
+ case NVM_SECTION_TYPE_PHY_SKU:
+ mvm->nvm_phy_sku_blob.data = temp;
+ mvm->nvm_phy_sku_blob.size = ret;
+ break;
default:
if (section == mvm->cfg->nvm_hw_section_num) {
mvm->nvm_hw_blob.data = temp;
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index a37de3f410a0..13c97f665ba8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -89,6 +89,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
static const struct iwl_op_mode_ops iwl_mvm_ops;
+static const struct iwl_op_mode_ops iwl_mvm_ops_mq;
struct iwl_mvm_mod_params iwlmvm_mod_params = {
.power_scheme = IWL_POWER_SCHEME_BPS,
@@ -222,7 +223,6 @@ struct iwl_rx_handlers {
* called from a worker with mvm->mutex held.
*/
static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
- RX_HANDLER(REPLY_RX_PHY_CMD, iwl_mvm_rx_rx_phy_cmd, false),
RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false),
RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false),
@@ -257,6 +257,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION,
iwl_mvm_power_uapsd_misbehaving_ap_notif, false),
RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true),
+ RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE,
+ iwl_mvm_temp_notif, true),
RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif,
true),
@@ -271,6 +273,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = {
CMD(MVM_ALIVE),
CMD(REPLY_ERROR),
+ CMD(ECHO_CMD),
CMD(INIT_COMPLETE_NOTIF),
CMD(PHY_CONTEXT_CMD),
CMD(MGMT_MCAST_KEY),
@@ -422,7 +425,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
op_mode = hw->priv;
- op_mode->ops = &iwl_mvm_ops;
mvm = IWL_OP_MODE_GET_MVM(op_mode);
mvm->dev = trans->dev;
@@ -431,6 +433,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->fw = fw;
mvm->hw = hw;
+ if (iwl_mvm_has_new_rx_api(mvm)) {
+ op_mode->ops = &iwl_mvm_ops_mq;
+ } else {
+ op_mode->ops = &iwl_mvm_ops;
+
+ if (WARN_ON(trans->num_rx_queues > 1))
+ goto out_free;
+ }
+
mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
mvm->aux_queue = 15;
@@ -451,6 +462,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);
+ spin_lock_init(&mvm->queue_info_lock);
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
@@ -590,6 +602,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
ieee80211_unregister_hw(mvm->hw);
iwl_mvm_leds_exit(mvm);
out_free:
+ flush_delayed_work(&mvm->fw_dump_wk);
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name)
@@ -617,6 +630,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
kfree(mvm->d3_resume_sram);
if (mvm->nd_config) {
kfree(mvm->nd_config->match_sets);
+ kfree(mvm->nd_config->scan_plans);
kfree(mvm->nd_config);
mvm->nd_config = NULL;
}
@@ -716,18 +730,11 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
}
}
-static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
- struct napi_struct *napi,
- struct iwl_rx_cmd_buffer *rxb)
+static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_rx_packet *pkt)
{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- u8 i;
-
- if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) {
- iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
- return;
- }
+ int i;
iwl_mvm_rx_check_trigger(mvm, pkt);
@@ -767,40 +774,84 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
}
}
+static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
+ struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+ if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
+ iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
+ else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
+ iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
+ else
+ iwl_mvm_rx_common(mvm, rxb, pkt);
+}
+
+static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
+ struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+ if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
+ iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
+ else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
+ iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
+ else
+ iwl_mvm_rx_common(mvm, rxb, pkt);
+}
+
static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- int mq = mvm->queue_to_mac80211[queue];
+ unsigned long mq;
+ int q;
- if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
- return;
+ spin_lock_bh(&mvm->queue_info_lock);
+ mq = mvm->queue_info[queue].hw_queue_to_mac80211;
+ spin_unlock_bh(&mvm->queue_info_lock);
- if (atomic_inc_return(&mvm->mac80211_queue_stop_count[mq]) > 1) {
- IWL_DEBUG_TX_QUEUES(mvm,
- "queue %d (mac80211 %d) already stopped\n",
- queue, mq);
+ if (WARN_ON_ONCE(!mq))
return;
- }
- ieee80211_stop_queue(mvm->hw, mq);
+ 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,
+ "queue %d (mac80211 %d) already stopped\n",
+ queue, q);
+ continue;
+ }
+
+ ieee80211_stop_queue(mvm->hw, q);
+ }
}
static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- int mq = mvm->queue_to_mac80211[queue];
+ unsigned long mq;
+ int q;
- if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
- return;
+ spin_lock_bh(&mvm->queue_info_lock);
+ mq = mvm->queue_info[queue].hw_queue_to_mac80211;
+ spin_unlock_bh(&mvm->queue_info_lock);
- if (atomic_dec_return(&mvm->mac80211_queue_stop_count[mq]) > 0) {
- IWL_DEBUG_TX_QUEUES(mvm,
- "queue %d (mac80211 %d) still stopped\n",
- queue, mq);
+ if (WARN_ON_ONCE(!mq))
return;
- }
- ieee80211_wake_queue(mvm->hw, mq);
+ 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,
+ "queue %d (mac80211 %d) still stopped\n",
+ queue, q);
+ continue;
+ }
+
+ ieee80211_wake_queue(mvm->hw, q);
+ }
}
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
@@ -1145,12 +1196,17 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
/* make sure we have no running tx while configuring the seqno */
synchronize_net();
- iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, &d0i3_iter_data);
- ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
- sizeof(wowlan_config_cmd),
- &wowlan_config_cmd);
- if (ret)
- return ret;
+ /* configure wowlan configuration only if needed */
+ if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) {
+ iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd,
+ &d0i3_iter_data);
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
+ sizeof(wowlan_config_cmd),
+ &wowlan_config_cmd);
+ if (ret)
+ return ret;
+ }
return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD,
flags | CMD_MAKE_TRANS_IDLE,
@@ -1257,7 +1313,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
};
struct iwl_wowlan_status *status;
int ret;
- u32 handled_reasons, wakeup_reasons;
+ u32 handled_reasons, wakeup_reasons = 0;
__le16 *qos_seq = NULL;
mutex_lock(&mvm->mutex);
@@ -1289,6 +1345,9 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
out:
iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
+ IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n",
+ wakeup_reasons);
+
/* qos_seq might point inside resp_pkt, so free it only now */
if (get_status_cmd.resp_pkt)
iwl_free_resp(&get_status_cmd);
@@ -1338,17 +1397,38 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
return _iwl_mvm_exit_d0i3(mvm);
}
+#define IWL_MVM_COMMON_OPS \
+ /* these could be differentiated */ \
+ .queue_full = iwl_mvm_stop_sw_queue, \
+ .queue_not_full = iwl_mvm_wake_sw_queue, \
+ .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \
+ .free_skb = iwl_mvm_free_skb, \
+ .nic_error = iwl_mvm_nic_error, \
+ .cmd_queue_full = iwl_mvm_cmd_queue_full, \
+ .nic_config = iwl_mvm_nic_config, \
+ .enter_d0i3 = iwl_mvm_enter_d0i3, \
+ .exit_d0i3 = iwl_mvm_exit_d0i3, \
+ /* as we only register one, these MUST be common! */ \
+ .start = iwl_op_mode_mvm_start, \
+ .stop = iwl_op_mode_mvm_stop
+
static const struct iwl_op_mode_ops iwl_mvm_ops = {
- .start = iwl_op_mode_mvm_start,
- .stop = iwl_op_mode_mvm_stop,
- .rx = iwl_mvm_rx_dispatch,
- .queue_full = iwl_mvm_stop_sw_queue,
- .queue_not_full = iwl_mvm_wake_sw_queue,
- .hw_rf_kill = iwl_mvm_set_hw_rfkill_state,
- .free_skb = iwl_mvm_free_skb,
- .nic_error = iwl_mvm_nic_error,
- .cmd_queue_full = iwl_mvm_cmd_queue_full,
- .nic_config = iwl_mvm_nic_config,
- .enter_d0i3 = iwl_mvm_enter_d0i3,
- .exit_d0i3 = iwl_mvm_exit_d0i3,
+ IWL_MVM_COMMON_OPS,
+ .rx = iwl_mvm_rx,
+};
+
+static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
+ struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb,
+ unsigned int queue)
+{
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+ iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
+}
+
+static const struct iwl_op_mode_ops iwl_mvm_ops_mq = {
+ IWL_MVM_COMMON_OPS,
+ .rx = iwl_mvm_rx_mq,
+ .rx_rss = iwl_mvm_rx_mq_rss,
};
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 4645877882a6..bed9696ee410 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * 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
@@ -33,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -306,13 +308,51 @@ static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
return radar_detect;
}
+static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct iwl_mac_power_cmd *cmd,
+ bool host_awake)
+{
+ int dtimper = vif->bss_conf.dtim_period ?: 1;
+ int skip;
+
+ /* disable, in case we're supposed to override */
+ cmd->skip_dtim_periods = 0;
+ cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+
+ if (iwl_mvm_power_is_radar(vif))
+ return;
+
+ if (dtimper >= 10)
+ return;
+
+ /* TODO: check that multicast wake lock is off */
+
+ if (host_awake) {
+ if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
+ return;
+ skip = 2;
+ } else {
+ int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
+
+ if (WARN_ON(!dtimper_tu))
+ return;
+ /* configure skip over dtim up to 306TU - 314 msec */
+ skip = max_t(u8, 1, 306 / dtimper_tu);
+ }
+
+ /* the firmware really expects "look at every X DTIMs", so add 1 */
+ cmd->skip_dtim_periods = 1 + skip;
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+}
+
static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct iwl_mac_power_cmd *cmd)
+ struct iwl_mac_power_cmd *cmd,
+ bool host_awake)
{
int dtimper, bi;
int keep_alive;
- bool radar_detect = false;
struct iwl_mvm_vif *mvmvif __maybe_unused =
iwl_mvm_vif_from_mac80211(vif);
@@ -337,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
- if (!vif->bss_conf.ps || !mvmvif->pm_enabled ||
- (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p))
+ if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
+ return;
+
+ if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
+ (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
+ !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
return;
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
@@ -350,27 +395,25 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
}
- /* Check if radar detection is required on current channel */
- radar_detect = iwl_mvm_power_is_radar(vif);
+ iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake);
- /* Check skip over DTIM conditions */
- if (!radar_detect && (dtimper < 10) &&
- (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
- mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
- cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
- cmd->skip_dtim_periods = 3;
- }
-
- if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
+ if (!host_awake) {
cmd->rx_data_timeout =
- cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
+ cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
cmd->tx_data_timeout =
- cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
+ cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
+ } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
+ fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
+ cmd->tx_data_timeout =
+ cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
+ cmd->rx_data_timeout =
+ cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
} else {
cmd->rx_data_timeout =
- cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
+ cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
cmd->tx_data_timeout =
- cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
+ cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
}
if (iwl_mvm_power_allow_uapsd(mvm, vif))
@@ -427,7 +470,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
{
struct iwl_mac_power_cmd cmd = {};
- iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+ iwl_mvm_power_build_cmd(mvm, vif, &cmd,
+ mvm->cur_ucode != IWL_UCODE_WOWLAN);
iwl_mvm_power_log(mvm, &cmd);
#ifdef CONFIG_IWLWIFI_DEBUGFS
memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
@@ -440,14 +484,14 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
{
struct iwl_device_power_cmd cmd = {
- .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
+ .flags = 0,
};
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
mvm->ps_disabled = true;
- if (mvm->ps_disabled)
- cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
+ if (!mvm->ps_disabled)
+ cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 :
@@ -963,25 +1007,8 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
if (!vif->bss_conf.assoc)
return 0;
- iwl_mvm_power_build_cmd(mvm, vif, &cmd);
- if (enable) {
- /* configure skip over dtim up to 306TU - 314 msec */
- int dtimper = vif->bss_conf.dtim_period ?: 1;
- int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
- bool radar_detect = iwl_mvm_power_is_radar(vif);
+ iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
- if (WARN_ON(!dtimper_tu))
- return 0;
-
- /* Check skip over DTIM conditions */
- /* TODO: check that multicast wake lock is off */
- if (!radar_detect && (dtimper < 10)) {
- cmd.skip_dtim_periods = 306 / dtimper_tu;
- if (cmd.skip_dtim_periods)
- cmd.flags |= cpu_to_le16(
- POWER_FLAGS_SKIP_OVER_DTIM_MSK);
- }
- }
iwl_mvm_power_log(mvm, &cmd);
#ifdef CONFIG_IWLWIFI_DEBUGFS
memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 5ae9c8aa868f..d1ad10391b47 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
mvmsta = iwl_mvm_sta_from_mac80211(sta);
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
- if (IWL_MVM_RS_DISABLE_P2P_MIMO &&
- iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p)
- return false;
if (mvm->nvm_data->sku_cap_mimo_disabled)
return false;
@@ -524,14 +521,56 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
return lq_types[type];
}
+static char *rs_pretty_rate(const struct rs_rate *rate)
+{
+ static char buf[40];
+ static const char * const legacy_rates[] = {
+ [IWL_RATE_1M_INDEX] = "1M",
+ [IWL_RATE_2M_INDEX] = "2M",
+ [IWL_RATE_5M_INDEX] = "5.5M",
+ [IWL_RATE_11M_INDEX] = "11M",
+ [IWL_RATE_6M_INDEX] = "6M",
+ [IWL_RATE_9M_INDEX] = "9M",
+ [IWL_RATE_12M_INDEX] = "12M",
+ [IWL_RATE_18M_INDEX] = "18M",
+ [IWL_RATE_24M_INDEX] = "24M",
+ [IWL_RATE_36M_INDEX] = "36M",
+ [IWL_RATE_48M_INDEX] = "48M",
+ [IWL_RATE_54M_INDEX] = "54M",
+ };
+ static const char *const ht_vht_rates[] = {
+ [IWL_RATE_MCS_0_INDEX] = "MCS0",
+ [IWL_RATE_MCS_1_INDEX] = "MCS1",
+ [IWL_RATE_MCS_2_INDEX] = "MCS2",
+ [IWL_RATE_MCS_3_INDEX] = "MCS3",
+ [IWL_RATE_MCS_4_INDEX] = "MCS4",
+ [IWL_RATE_MCS_5_INDEX] = "MCS5",
+ [IWL_RATE_MCS_6_INDEX] = "MCS6",
+ [IWL_RATE_MCS_7_INDEX] = "MCS7",
+ [IWL_RATE_MCS_8_INDEX] = "MCS8",
+ [IWL_RATE_MCS_9_INDEX] = "MCS9",
+ };
+ const char *rate_str;
+
+ if (is_type_legacy(rate->type))
+ rate_str = legacy_rates[rate->index];
+ else if (is_type_ht(rate->type) || is_type_vht(rate->type))
+ rate_str = ht_vht_rates[rate->index];
+ else
+ rate_str = "BAD_RATE";
+
+ sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type),
+ rs_pretty_ant(rate->ant), rate_str);
+ return buf;
+}
+
static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
const char *prefix)
{
IWL_DEBUG_RATE(mvm,
- "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n",
- prefix, rs_pretty_lq_type(rate->type),
- rate->index, rs_pretty_ant(rate->ant),
- rate->bw, rate->sgi, rate->ldpc, rate->stbc);
+ "%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\n",
+ prefix, rs_pretty_rate(rate), rate->bw,
+ rate->sgi, rate->ldpc, rate->stbc);
}
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -562,8 +601,8 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
}
static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
- struct iwl_lq_sta *lq_data, u8 tid,
- struct ieee80211_sta *sta)
+ struct iwl_lq_sta *lq_data, u8 tid,
+ struct ieee80211_sta *sta)
{
int ret = -EAGAIN;
@@ -1485,7 +1524,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
u32 target_tpt;
int rate_idx;
- if (success_ratio > IWL_MVM_RS_SR_NO_DECREASE) {
+ if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) {
target_tpt = 100 * expected_current_tpt;
IWL_DEBUG_RATE(mvm,
"SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",
@@ -1493,7 +1532,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
} else {
target_tpt = lq_sta->last_tpt;
IWL_DEBUG_RATE(mvm,
- "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",
+ "SR %d not that good. Find rate exceeding ACTUAL_TPT %d\n",
success_ratio, target_tpt);
}
@@ -1622,6 +1661,51 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
}
+static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ struct iwl_lq_sta *lq_sta,
+ struct iwl_scale_tbl_info *tbl,
+ enum rs_action scale_action)
+{
+ if (sta->bandwidth != IEEE80211_STA_RX_BW_80)
+ return false;
+
+ if (!is_vht_siso(&tbl->rate))
+ return false;
+
+ if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) &&
+ (tbl->rate.index == IWL_RATE_MCS_0_INDEX) &&
+ (scale_action == RS_ACTION_DOWNSCALE)) {
+ tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20;
+ tbl->rate.index = IWL_RATE_MCS_4_INDEX;
+ IWL_DEBUG_RATE(mvm, "Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\n");
+ goto tweaked;
+ }
+
+ /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is
+ * sustainable, i.e. we're past the test window. We can't go back
+ * if MCS5 is just tested as this will happen always after switching
+ * to 20Mhz MCS4 because the rate stats are cleared.
+ */
+ if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) &&
+ (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) &&
+ (scale_action == RS_ACTION_STAY)) ||
+ ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) &&
+ (scale_action == RS_ACTION_UPSCALE)))) {
+ tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80;
+ tbl->rate.index = IWL_RATE_MCS_1_INDEX;
+ IWL_DEBUG_RATE(mvm, "Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\n");
+ goto tweaked;
+ }
+
+ return false;
+
+tweaked:
+ rs_set_expected_tpt_table(lq_sta, tbl);
+ rs_rate_scale_clear_tbl_windows(mvm, tbl);
+ return true;
+}
+
static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct ieee80211_sta *sta,
@@ -2174,9 +2258,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) {
IWL_DEBUG_RATE(mvm,
- "(%s: %d): Test Window: succ %d total %d\n",
- rs_pretty_lq_type(rate->type),
- index, window->success_counter, window->counter);
+ "%s: Test Window: succ %d total %d\n",
+ rs_pretty_rate(rate),
+ window->success_counter, window->counter);
/* Can't calculate this yet; not enough history */
window->average_tpt = IWL_INVALID_VALUE;
@@ -2253,8 +2337,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
high_tpt = tbl->win[high].average_tpt;
IWL_DEBUG_RATE(mvm,
- "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n",
- rs_pretty_lq_type(rate->type), index, current_tpt, sr,
+ "%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n",
+ rs_pretty_rate(rate), current_tpt, sr,
low, high, low_tpt, high_tpt);
scale_action = rs_get_rate_action(mvm, tbl, sr, low, high,
@@ -2305,6 +2389,8 @@ lq_update:
/* Replace uCode's rate table for the destination station. */
if (update_lq) {
tbl->rate.index = index;
+ if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK)
+ rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action);
rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
}
@@ -2542,7 +2628,6 @@ static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm,
}
}
- rs_dump_rate(mvm, rate, "OPTIMAL RATE");
return rate;
}
@@ -2983,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
else
rs_vht_init(mvm, sta, lq_sta, vht_cap);
- if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p)
- lq_sta->active_mimo2_rate = 0;
-
lq_sta->max_legacy_rate_idx =
rs_get_max_rate_from_mask(lq_sta->active_legacy_rate);
lq_sta->max_siso_rate_idx =
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index c37c10a423ce..5b58f5320e8d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -202,7 +202,6 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
return -1;
stats->flag |= RX_FLAG_DECRYPTED;
- IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n");
*crypt_len = IEEE80211_CCMP_HDR_LEN;
return 0;
@@ -299,13 +298,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
return;
}
- if ((unlikely(phy_info->cfg_phy_cnt > 20))) {
- IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n",
- phy_info->cfg_phy_cnt);
- kfree_skb(skb);
- return;
- }
-
/*
* Keep packets with CRC errors (and with overrun) for monitor mode
* (otherwise the firmware discards them) but mark them as bad.
@@ -354,8 +346,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
/* This is fine since we don't support multiple AP interfaces */
sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
if (sta) {
- struct iwl_mvm_sta *mvmsta;
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
@@ -459,7 +451,7 @@ static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm,
struct iwl_mvm_stat_data {
struct iwl_mvm *mvm;
__le32 mac_id;
- __s8 beacon_filter_average_energy;
+ u8 beacon_filter_average_energy;
struct mvm_statistics_general_v8 *general;
};
@@ -577,56 +569,33 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
- size_t v8_len = sizeof(struct iwl_notif_statistics_v8);
- size_t v10_len = sizeof(struct iwl_notif_statistics_v10);
+ struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data;
struct iwl_mvm_stat_data data = {
.mvm = mvm,
};
u32 temperature;
- if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STATS_V10)) {
- struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data;
-
- if (iwl_rx_packet_payload_len(pkt) != v10_len)
- goto invalid;
+ if (iwl_rx_packet_payload_len(pkt) != sizeof(*stats))
+ goto invalid;
- temperature = le32_to_cpu(stats->general.radio_temperature);
- data.mac_id = stats->rx.general.mac_id;
- data.beacon_filter_average_energy =
- stats->general.beacon_filter_average_energy;
+ temperature = le32_to_cpu(stats->general.radio_temperature);
+ data.mac_id = stats->rx.general.mac_id;
+ data.beacon_filter_average_energy =
+ stats->general.beacon_filter_average_energy;
- iwl_mvm_update_rx_statistics(mvm, &stats->rx);
+ iwl_mvm_update_rx_statistics(mvm, &stats->rx);
- mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time);
- mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time);
- mvm->radio_stats.on_time_rf =
- le64_to_cpu(stats->general.on_time_rf);
- mvm->radio_stats.on_time_scan =
- le64_to_cpu(stats->general.on_time_scan);
+ mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time);
+ mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time);
+ mvm->radio_stats.on_time_rf =
+ le64_to_cpu(stats->general.on_time_rf);
+ mvm->radio_stats.on_time_scan =
+ le64_to_cpu(stats->general.on_time_scan);
- data.general = &stats->general;
- } else {
- struct iwl_notif_statistics_v8 *stats = (void *)&pkt->data;
-
- if (iwl_rx_packet_payload_len(pkt) != v8_len)
- goto invalid;
-
- temperature = le32_to_cpu(stats->general.radio_temperature);
- data.mac_id = stats->rx.general.mac_id;
- data.beacon_filter_average_energy =
- stats->general.beacon_filter_average_energy;
-
- iwl_mvm_update_rx_statistics(mvm, &stats->rx);
- }
+ data.general = &stats->general;
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
- /* Only handle rx statistics temperature changes if async temp
- * notifications are not supported
- */
- if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_ASYNC_DTM))
- iwl_mvm_tt_temp_changed(mvm, temperature);
-
ieee80211_iterate_active_interfaces(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_stat_iterator,
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 56559d4d34ad..d6e0c1b5c20c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -131,7 +131,6 @@ struct iwl_mvm_scan_params {
int n_ssids;
struct cfg80211_ssid *ssids;
struct ieee80211_channel **channels;
- u16 interval; /* interval between scans (in secs) */
u32 flags;
u8 *mac_addr;
u8 *mac_addr_mask;
@@ -140,7 +139,8 @@ struct iwl_mvm_scan_params {
int n_match_sets;
struct iwl_scan_probe_req preq;
struct cfg80211_match_set *match_sets;
- u8 iterations[2];
+ int n_scan_plans;
+ struct cfg80211_sched_scan_plan *scan_plans;
};
static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
@@ -474,7 +474,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
int ret;
if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES))
- return -EIO;
+ return -EIO;
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL)
blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN;
@@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
}
static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- int n_iterations)
+ struct ieee80211_vif *vif)
{
const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa;
@@ -750,16 +749,9 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
*/
return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) &&
mvm->last_ebs_successful &&
- (n_iterations > 1 ||
- fw_has_api(capa, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)) &&
vif->type != NL80211_IFTYPE_P2P_DEVICE);
}
-static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params)
-{
- return params->iterations[0] + params->iterations[1];
-}
-
static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params)
{
@@ -798,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
(void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
mvm->fw->ucode_capa.n_scan_channels);
u32 ssid_bitmap = 0;
- int n_iterations = iwl_mvm_scan_total_iterations(params);
+ int i;
lockdep_assert_held(&mvm->mutex);
memset(cmd, 0, ksize(cmd));
+ if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
+ return -EINVAL;
+
iwl_mvm_scan_lmac_dwell(mvm, cmd, params);
cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);
@@ -823,14 +818,26 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* this API uses bits 1-20 instead of 0-19 */
ssid_bitmap <<= 1;
- cmd->schedule[0].delay = cpu_to_le16(params->interval);
- cmd->schedule[0].iterations = params->iterations[0];
- cmd->schedule[0].full_scan_mul = 1;
- cmd->schedule[1].delay = cpu_to_le16(params->interval);
- cmd->schedule[1].iterations = params->iterations[1];
- cmd->schedule[1].full_scan_mul = 1;
+ for (i = 0; i < params->n_scan_plans; i++) {
+ struct cfg80211_sched_scan_plan *scan_plan =
+ &params->scan_plans[i];
+
+ cmd->schedule[i].delay =
+ cpu_to_le16(scan_plan->interval);
+ cmd->schedule[i].iterations = scan_plan->iterations;
+ cmd->schedule[i].full_scan_mul = 1;
+ }
+
+ /*
+ * If the number of iterations of the last scan plan is set to
+ * zero, it should run infinitely. However, this is not always the case.
+ * For example, when regular scan is requested the driver sets one scan
+ * plan with one iteration.
+ */
+ if (!cmd->schedule[i - 1].iterations)
+ cmd->schedule[i - 1].iterations = 0xff;
- if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) {
+ if (iwl_mvm_scan_use_ebs(mvm, vif)) {
cmd->channel_opt[0].flags =
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
@@ -894,7 +901,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)
int iwl_mvm_config_scan(struct iwl_mvm *mvm)
{
-
struct iwl_scan_config *scan_config;
struct ieee80211_supported_band *band;
int num_channels =
@@ -970,6 +976,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)
return -ENOENT;
}
+static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params)
+{
+ return params->n_scan_plans == 1 &&
+ params->scan_plans[0].iterations == 1;
+}
+
static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
struct iwl_scan_req_umac *cmd,
struct iwl_mvm_scan_params *params)
@@ -982,7 +994,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
cmd->scan_priority =
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
- if (iwl_mvm_scan_total_iterations(params) == 1)
+ if (iwl_mvm_is_regular_scan(params))
cmd->ooc_priority =
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
else
@@ -1029,7 +1041,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
else
flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;
- if (iwl_mvm_scan_total_iterations(params) > 1)
+ if (!iwl_mvm_is_regular_scan(params))
flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -1047,12 +1059,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
sizeof(struct iwl_scan_channel_cfg_umac) *
mvm->fw->ucode_capa.n_scan_channels;
- int uid;
+ int uid, i;
u32 ssid_bitmap = 0;
- int n_iterations = iwl_mvm_scan_total_iterations(params);
lockdep_assert_held(&mvm->mutex);
+ if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
+ return -EINVAL;
+
uid = iwl_mvm_scan_uid_by_status(mvm, 0);
if (uid < 0)
return uid;
@@ -1069,7 +1083,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (type == IWL_MVM_SCAN_SCHED)
cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
- if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations))
+ if (iwl_mvm_scan_use_ebs(mvm, vif))
cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
@@ -1081,12 +1095,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
params->n_channels, ssid_bitmap, cmd);
- /* With UMAC we use only one schedule for now, so use the sum
- * of the iterations (with a a maximum of 255).
+ for (i = 0; i < params->n_scan_plans; i++) {
+ struct cfg80211_sched_scan_plan *scan_plan =
+ &params->scan_plans[i];
+
+ sec_part->schedule[i].iter_count = scan_plan->iterations;
+ sec_part->schedule[i].interval =
+ cpu_to_le16(scan_plan->interval);
+ }
+
+ /*
+ * If the number of iterations of the last scan plan is set to
+ * zero, it should run infinitely. However, this is not always the case.
+ * For example, when regular scan is requested the driver sets one scan
+ * plan with one iteration.
*/
- sec_part->schedule[0].iter_count =
- (n_iterations > 255) ? 255 : n_iterations;
- sec_part->schedule[0].interval = cpu_to_le16(params->interval);
+ if (!sec_part->schedule[i - 1].iter_count)
+ sec_part->schedule[i - 1].iter_count = 0xff;
sec_part->delay = cpu_to_le16(params->delay);
sec_part->preq = params->preq;
@@ -1152,6 +1177,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
};
struct iwl_mvm_scan_params params = {};
int ret;
+ struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 };
lockdep_assert_held(&mvm->mutex);
@@ -1164,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (ret)
return ret;
- iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
-
/* we should have failed registration if scan_cmd was NULL */
if (WARN_ON(!mvm->scan_cmd))
return -ENOMEM;
@@ -1177,7 +1201,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
params.flags = req->flags;
params.n_channels = req->n_channels;
params.delay = 0;
- params.interval = 0;
params.ssids = req->ssids;
params.channels = req->channels;
params.mac_addr = req->mac_addr;
@@ -1187,8 +1210,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
params.n_match_sets = 0;
params.match_sets = NULL;
- params.iterations[0] = 1;
- params.iterations[1] = 0;
+ params.scan_plans = &scan_plan;
+ params.n_scan_plans = 1;
params.type = iwl_mvm_get_scan_type(mvm, vif, &params);
@@ -1207,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
ret = iwl_mvm_send_cmd(mvm, &hcmd);
- if (!ret) {
- IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
- mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
- } else {
+ if (ret) {
/* If the scan failed, it usually means that the FW was unable
* to allocate the time events. Warn on it, but maybe we
* should try to send the command again with different params.
*/
IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
+ return ret;
}
- if (ret)
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+ IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
+ mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
+ iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
- return ret;
+ return 0;
}
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
@@ -1267,20 +1289,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
params.pass_all = iwl_mvm_scan_pass_all(mvm, req);
params.n_match_sets = req->n_match_sets;
params.match_sets = req->match_sets;
+ if (!req->n_scan_plans)
+ return -EINVAL;
- params.iterations[0] = 0;
- params.iterations[1] = 0xff;
+ params.n_scan_plans = req->n_scan_plans;
+ params.scan_plans = req->scan_plans;
params.type = iwl_mvm_get_scan_type(mvm, vif, &params);
- if (req->interval > U16_MAX) {
- IWL_DEBUG_SCAN(mvm,
- "interval value is > 16-bits, set to max possible\n");
- params.interval = U16_MAX;
- } else {
- params.interval = req->interval / MSEC_PER_SEC;
- }
-
/* In theory, LMAC scans can handle a 32-bit delay, but since
* waiting for over 18 hours to start the scan is a bit silly
* and to keep it aligned with UMAC scans (which only support
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index df216cd0c98f..300a249486e4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -234,7 +234,9 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
/* Found a place for all queues - enable them */
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac],
- iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout);
+ mvmsta->hw_queue[ac],
+ iwl_mvm_ac_to_tx_fifo[ac], 0,
+ wdg_timeout);
mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]);
}
@@ -253,7 +255,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm,
/* disable the TDLS STA-specific queues */
sta_msk = mvmsta->tfd_queue_msk;
for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE)
- iwl_mvm_disable_txq(mvm, i, 0);
+ iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0);
}
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
@@ -275,6 +277,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
if (sta_id == IWL_MVM_STATION_COUNT)
return -ENOSPC;
+ if (vif->type == NL80211_IFTYPE_AP) {
+ mvmvif->ap_assoc_sta_count++;
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ }
+
spin_lock_init(&mvm_sta->lock);
mvm_sta->sta_id = sta_id;
@@ -287,7 +294,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
/* HW restart, don't assume the memory has been zeroed */
atomic_set(&mvm->pending_frames[sta_id], 0);
- mvm_sta->tid_disable_agg = 0;
+ mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */
mvm_sta->tfd_queue_msk = 0;
/* allocate new queues for a TDLS station */
@@ -467,7 +474,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk)
unsigned long i, msk = mvm->tfd_drained[sta_id];
for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE)
- iwl_mvm_disable_txq(mvm, i, 0);
+ iwl_mvm_disable_txq(mvm, i, i,
+ IWL_MAX_TID_COUNT, 0);
mvm->tfd_drained[sta_id] = 0;
IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n",
@@ -494,7 +502,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
if (ret)
return ret;
/* flush its queues here since we are freeing mvm_sta */
- ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
+ ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0);
if (ret)
return ret;
ret = iwl_trans_wait_tx_queue_empty(mvm->trans,
@@ -646,8 +654,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
/* Map Aux queue to fifo - needs to happen before adding Aux station */
- iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue,
- IWL_MVM_TX_FIFO_MCAST, wdg_timeout);
+ iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue,
+ IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
/* Allocate aux station and assign to it the aux queue */
ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
@@ -918,6 +926,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;
int txq_id;
+ int ret;
if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
return -EINVAL;
@@ -930,17 +939,6 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
- for (txq_id = mvm->first_agg_queue;
- txq_id <= mvm->last_agg_queue; txq_id++)
- if (mvm->queue_to_mac80211[txq_id] ==
- IWL_INVALID_MAC80211_QUEUE)
- break;
-
- if (txq_id > mvm->last_agg_queue) {
- IWL_ERR(mvm, "Failed to allocate agg queue\n");
- return -EIO;
- }
-
spin_lock_bh(&mvmsta->lock);
/* possible race condition - we entered D0i3 while starting agg */
@@ -950,8 +948,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return -EIO;
}
- /* the new tx queue is still connected to the same mac80211 queue */
- mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]];
+ spin_lock_bh(&mvm->queue_info_lock);
+
+ txq_id = iwl_mvm_find_free_queue(mvm, mvm->first_agg_queue,
+ mvm->last_agg_queue);
+ if (txq_id < 0) {
+ ret = txq_id;
+ spin_unlock_bh(&mvm->queue_info_lock);
+ IWL_ERR(mvm, "Failed to allocate agg queue\n");
+ goto release_locks;
+ }
+ mvm->queue_info[txq_id].setup_reserved = true;
+ spin_unlock_bh(&mvm->queue_info_lock);
tid_data = &mvmsta->tid_data[tid];
tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
@@ -970,9 +978,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA;
}
+ ret = 0;
+
+release_locks:
spin_unlock_bh(&mvmsta->lock);
- return 0;
+ return ret;
}
int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1000,13 +1011,19 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
- iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid,
- buf_size, ssn, wdg_timeout);
+ iwl_mvm_enable_agg_txq(mvm, queue,
+ vif->hw_queue[tid_to_mac80211_ac[tid]], fifo,
+ mvmsta->sta_id, tid, buf_size, ssn, wdg_timeout);
ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
if (ret)
return -EIO;
+ /* No need to mark as reserved */
+ spin_lock_bh(&mvm->queue_info_lock);
+ mvm->queue_info[queue].setup_reserved = false;
+ spin_unlock_bh(&mvm->queue_info_lock);
+
/*
* Even though in theory the peer could have different
* aggregation reorder buffer sizes for different sessions,
@@ -1051,6 +1068,11 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmsta->agg_tids &= ~BIT(tid);
+ /* No need to mark as reserved anymore */
+ spin_lock_bh(&mvm->queue_info_lock);
+ mvm->queue_info[txq_id].setup_reserved = false;
+ spin_unlock_bh(&mvm->queue_info_lock);
+
switch (tid_data->state) {
case IWL_AGG_ON:
tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
@@ -1068,14 +1090,15 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
tid_data->ssn = 0xffff;
tid_data->state = IWL_AGG_OFF;
- mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE;
spin_unlock_bh(&mvmsta->lock);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
- iwl_mvm_disable_txq(mvm, txq_id, 0);
+ iwl_mvm_disable_txq(mvm, txq_id,
+ vif->hw_queue[tid_to_mac80211_ac[tid]], tid,
+ 0);
return 0;
case IWL_AGG_STARTING:
case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -1086,7 +1109,6 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* No barriers since we are under mutex */
lockdep_assert_held(&mvm->mutex);
- mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE;
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
tid_data->state = IWL_AGG_OFF;
@@ -1127,9 +1149,14 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmsta->agg_tids &= ~BIT(tid);
spin_unlock_bh(&mvmsta->lock);
+ /* No need to mark as reserved */
+ spin_lock_bh(&mvm->queue_info_lock);
+ mvm->queue_info[txq_id].setup_reserved = false;
+ spin_unlock_bh(&mvm->queue_info_lock);
+
if (old_state >= IWL_AGG_ON) {
iwl_mvm_drain_sta(mvm, mvmsta, true);
- if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
+ if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0))
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
iwl_trans_wait_tx_queue_empty(mvm->trans,
mvmsta->tfd_queue_msk);
@@ -1137,12 +1164,11 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
- iwl_mvm_disable_txq(mvm, tid_data->txq_id, 0);
+ iwl_mvm_disable_txq(mvm, tid_data->txq_id,
+ vif->hw_queue[tid_to_mac80211_ac[tid]], tid,
+ 0);
}
- mvm->queue_to_mac80211[tid_data->txq_id] =
- IWL_INVALID_MAC80211_QUEUE;
-
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index dbd7d544575d..7530eb23035d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -129,7 +129,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
- iwl_mvm_flush_tx_path(mvm, queues, false);
+ iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.c b/drivers/net/wireless/iwlwifi/mvm/tof.c
index 380972f8fb82..4007f1d421dd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tof.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tof.c
@@ -178,12 +178,14 @@ int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm,
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
return -EINVAL;
- if (vif->p2p || vif->type != NL80211_IFTYPE_AP) {
+ 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);
diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.h b/drivers/net/wireless/iwlwifi/mvm/tof.h
index 50ae8adaaa6e..9beebc33cb8d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tof.h
+++ b/drivers/net/wireless/iwlwifi/mvm/tof.h
@@ -60,7 +60,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-#ifndef __tof
+#ifndef __tof_h__
#define __tof_h__
#include "fw-api-tof.h"
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index fe7145c2c98a..cadfc0460597 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -176,17 +176,34 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
struct iwl_dts_measurement_cmd cmd = {
.flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP),
};
+ struct iwl_ext_dts_measurement_cmd extcmd = {
+ .control_mode = cpu_to_le32(DTS_AUTOMATIC),
+ };
+ u32 cmdid;
+
+ if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR))
+ cmdid = iwl_cmd_id(CMD_DTS_MEASUREMENT_TRIGGER_WIDE,
+ PHY_OPS_GROUP, 0);
+ else
+ cmdid = CMD_DTS_MEASUREMENT_TRIGGER;
- return iwl_mvm_send_cmd_pdu(mvm, CMD_DTS_MEASUREMENT_TRIGGER, 0,
- sizeof(cmd), &cmd);
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE))
+ return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd);
+
+ return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd);
}
int iwl_mvm_get_temp(struct iwl_mvm *mvm)
{
struct iwl_notification_wait wait_temp_notif;
- static const u16 temp_notif[] = { DTS_MEASUREMENT_NOTIFICATION };
+ static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP,
+ DTS_MEASUREMENT_NOTIF_WIDE) };
int ret, temp;
+ if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR))
+ temp_notif[0] = DTS_MEASUREMENT_NOTIFICATION;
+
lockdep_assert_held(&mvm->mutex);
iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif,
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 6df5aada4f16..c652a66be803 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -560,15 +560,10 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
IWL_DEBUG_TX_QUEUES(mvm,
"Can continue DELBA flow ssn = next_recl = %d\n",
tid_data->next_reclaimed);
- iwl_mvm_disable_txq(mvm, tid_data->txq_id, CMD_ASYNC);
+ iwl_mvm_disable_txq(mvm, tid_data->txq_id,
+ vif->hw_queue[tid_to_mac80211_ac[tid]], tid,
+ CMD_ASYNC);
tid_data->state = IWL_AGG_OFF;
- /*
- * we can't hold the mutex - but since we are after a sequence
- * point (call to iwl_mvm_disable_txq(), so we don't even need
- * a memory barrier.
- */
- mvm->queue_to_mac80211[tid_data->txq_id] =
- IWL_INVALID_MAC80211_QUEUE;
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
@@ -1104,7 +1099,7 @@ out:
* 2) flush the Tx path
* 3) wait for the transport queues to be empty
*/
-int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
+int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags)
{
int ret;
struct iwl_tx_path_flush_cmd flush_cmd = {
@@ -1112,8 +1107,6 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
.flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH),
};
- u32 flags = sync ? 0 : CMD_ASYNC;
-
ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags,
sizeof(flush_cmd), &flush_cmd);
if (ret)
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index a7d434256423..ad0f16909e2e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * 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
@@ -657,45 +658,143 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
if (mvm->support_umac_log)
iwl_mvm_dump_umac_error_log(mvm);
}
-void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn,
- const struct iwl_trans_txq_scd_cfg *cfg,
+
+int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq)
+{
+ int i;
+
+ lockdep_assert_held(&mvm->queue_info_lock);
+
+ for (i = minq; i <= maxq; i++)
+ if (mvm->queue_info[i].hw_queue_refcount == 0 &&
+ !mvm->queue_info[i].setup_reserved)
+ return i;
+
+ return -ENOSPC;
+}
+
+void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+ u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout)
{
- struct iwl_scd_txq_cfg_cmd cmd = {
- .scd_queue = queue,
- .enable = 1,
- .window = cfg->frame_limit,
- .sta_id = cfg->sta_id,
- .ssn = cpu_to_le16(ssn),
- .tx_fifo = cfg->fifo,
- .aggregate = cfg->aggregate,
- .tid = cfg->tid,
- };
+ bool enable_queue = true;
- if (!iwl_mvm_is_scd_cfg_supported(mvm)) {
- iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg,
- wdg_timeout);
+ spin_lock_bh(&mvm->queue_info_lock);
+
+ /* Make sure this TID isn't already enabled */
+ if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) {
+ spin_unlock_bh(&mvm->queue_info_lock);
+ IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n",
+ cfg->tid);
return;
}
- iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout);
- WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd),
- "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo);
+ /* Update mappings and refcounts */
+ mvm->queue_info[queue].hw_queue_to_mac80211 |= BIT(mac80211_queue);
+ mvm->queue_info[queue].hw_queue_refcount++;
+ if (mvm->queue_info[queue].hw_queue_refcount > 1)
+ enable_queue = false;
+ mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid);
+
+ IWL_DEBUG_TX_QUEUES(mvm,
+ "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n",
+ queue, mvm->queue_info[queue].hw_queue_refcount,
+ mvm->queue_info[queue].hw_queue_to_mac80211);
+
+ spin_unlock_bh(&mvm->queue_info_lock);
+
+ /* Send the enabling command if we need to */
+ if (enable_queue) {
+ struct iwl_scd_txq_cfg_cmd cmd = {
+ .scd_queue = queue,
+ .enable = 1,
+ .window = cfg->frame_limit,
+ .sta_id = cfg->sta_id,
+ .ssn = cpu_to_le16(ssn),
+ .tx_fifo = cfg->fifo,
+ .aggregate = cfg->aggregate,
+ .tid = cfg->tid,
+ };
+
+ iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL,
+ wdg_timeout);
+ WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd),
+ &cmd),
+ "Failed to configure queue %d on FIFO %d\n", queue,
+ cfg->fifo);
+ }
}
-void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags)
+void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+ u8 tid, u8 flags)
{
struct iwl_scd_txq_cfg_cmd cmd = {
.scd_queue = queue,
.enable = 0,
};
+ bool remove_mac_queue = true;
int ret;
- if (!iwl_mvm_is_scd_cfg_supported(mvm)) {
- iwl_trans_txq_disable(mvm->trans, queue, true);
+ spin_lock_bh(&mvm->queue_info_lock);
+
+ if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) {
+ spin_unlock_bh(&mvm->queue_info_lock);
+ return;
+ }
+
+ 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->queue_info[queue].hw_queue_to_mac80211 &=
+ ~BIT(mac80211_queue);
+ mvm->queue_info[queue].hw_queue_refcount--;
+
+ cmd.enable = mvm->queue_info[queue].hw_queue_refcount ? 1 : 0;
+
+ IWL_DEBUG_TX_QUEUES(mvm,
+ "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n",
+ queue,
+ mvm->queue_info[queue].hw_queue_refcount,
+ mvm->queue_info[queue].hw_queue_to_mac80211);
+
+ /* If the queue is still enabled - nothing left to do in this func */
+ if (cmd.enable) {
+ spin_unlock_bh(&mvm->queue_info_lock);
return;
}
+ /* Make sure queue info is correct even though we overwrite it */
+ WARN(mvm->queue_info[queue].hw_queue_refcount ||
+ mvm->queue_info[queue].tid_bitmap ||
+ mvm->queue_info[queue].hw_queue_to_mac80211,
+ "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n",
+ queue, mvm->queue_info[queue].hw_queue_refcount,
+ mvm->queue_info[queue].hw_queue_to_mac80211,
+ 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].hw_queue_refcount = 0;
+ mvm->queue_info[queue].tid_bitmap = 0;
+ mvm->queue_info[queue].hw_queue_to_mac80211 = 0;
+
+ spin_unlock_bh(&mvm->queue_info_lock);
+
iwl_trans_txq_disable(mvm->trans, queue, false);
ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags,
sizeof(cmd), &cmd);
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index b0825c402c73..644b58bc5226 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -414,6 +414,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)},
/* 8000 Series */
{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 6ba7d300b08f..90283453073c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -592,10 +592,8 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
do {
ret = iwl_pcie_set_hw_ready(trans);
- if (ret >= 0) {
- ret = 0;
- goto out;
- }
+ if (ret >= 0)
+ return 0;
usleep_range(200, 1000);
t += 200;
@@ -605,10 +603,6 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
IWL_ERR(trans, "Couldn't prepare the card\n");
-out:
- iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
- CSR_RESET_LINK_PWR_MGMT_DISABLED);
-
return ret;
}
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index f11728a866ff..82c0796377aa 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1283,7 +1283,6 @@ static struct spi_driver libertas_spi_driver = {
.remove = libertas_spi_remove,
.driver = {
.name = "libertas_spi",
- .owner = THIS_MODULE,
.pm = &if_spi_pm_ops,
},
};
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 520bef80747f..c00a7daaa4bc 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -787,7 +787,7 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
struct mac80211_hwsim_data *data = hw->priv;
u64 now = mac80211_hwsim_get_tsf(hw, vif);
u32 bcn_int = data->beacon_int;
- u64 delta = abs64(tsf - now);
+ u64 delta = abs(tsf - now);
/* adjust after beaconing with new timestamp at old TBTT */
if (tsf > now) {
@@ -1819,7 +1819,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
switch (action) {
case IEEE80211_AMPDU_TX_START:
@@ -2190,9 +2190,8 @@ static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
struct genl_info *info)
{
if (info)
- genl_notify(&hwsim_genl_family, mcast_skb,
- genl_info_net(info), info->snd_portid,
- HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL);
+ genl_notify(&hwsim_genl_family, mcast_skb, info,
+ HWSIM_MCGRP_CONFIG, GFP_KERNEL);
else
genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0,
HWSIM_MCGRP_CONFIG, GFP_KERNEL);
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index 169384b48b27..f715eee39851 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -335,7 +335,8 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int
mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size)
+ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
+ bool amsdu)
{
struct mt7601u_dev *dev = hw->priv;
struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index f7c717253a66..aa498e0d2204 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -173,7 +173,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
int pad = 0, aggr_num = 0, ret;
struct mwifiex_tx_param tx_param;
struct txpd *ptx_pd = NULL;
- struct timeval tv;
int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
skb_src = skb_peek(&pra_list->skb_head);
@@ -202,9 +201,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
skb_aggr->priority = skb_src->priority;
+ skb_aggr->tstamp = skb_src->tstamp;
- do_gettimeofday(&tv);
- skb_aggr->tstamp = timeval_to_ktime(tv);
+ skb_aggr->tstamp = ktime_get_real();
do {
/* Check if AMSDU can accommodate this MSDU */
@@ -258,8 +257,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
}
if (adapter->iface_type == MWIFIEX_USB) {
- adapter->data_sent = true;
- ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA,
+ ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
skb_aggr, NULL);
} else {
if (skb_src)
@@ -299,16 +297,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
break;
case -1:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n",
__func__, ret);
adapter->dbg.num_tx_host_to_card_failure++;
mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
return 0;
case -EINPROGRESS:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
break;
case 0:
mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 2906cd543532..b3970a8c9e48 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -615,10 +615,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
((end_win > start_win) && ((seq_num > end_win) ||
(seq_num < start_win)))) {
end_win = seq_num;
- if (((seq_num - win_size) + 1) >= 0)
+ if (((end_win - win_size) + 1) >= 0)
start_win = (end_win - win_size) + 1;
else
- start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1;
+ start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1;
mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
}
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 317d99189556..279167ddd293 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -33,12 +33,12 @@ config MWIFIEX_PCIE
mwifiex_pcie.
config MWIFIEX_USB
- tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897/8997"
+ tristate "Marvell WiFi-Ex Driver for USB8766/8797/8997"
depends on MWIFIEX && USB
select FW_LOADER
---help---
This adds support for wireless adapters based on Marvell
- 8797/8897/8997 chipset with USB interface.
+ 8797/8997 chipset with USB interface.
If you choose to build it as a module, it will be called
mwifiex_usb.
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index ff63cb5632eb..4073116e6e9f 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1821,6 +1821,10 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
return -1;
}
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
+ mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+
return 0;
}
@@ -1925,6 +1929,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
if (mwifiex_set_mgmt_ies(priv, &params->beacon))
return -1;
+ if (!netif_carrier_ok(priv->netdev))
+ netif_carrier_on(priv->netdev);
+ mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);
+
memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
kfree(bss_cfg);
return 0;
@@ -1994,8 +2002,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
CFG80211_BSS_FTYPE_UNKNOWN,
bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
0, ie_buf, ie_len, 0, GFP_KERNEL);
- cfg80211_put_bss(priv->wdev.wiphy, bss);
- memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
+ if (bss) {
+ cfg80211_put_bss(priv->wdev.wiphy, bss);
+ ether_addr_copy(priv->cfg_bssid, bss_info.bssid);
+ }
return 0;
}
@@ -2372,7 +2382,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
* CFG802.11 operation handler for scan request.
*
* This function issues a scan request to the firmware based upon
- * the user specified scan configuration. On successfull completion,
+ * the user specified scan configuration. On successful completion,
* it also informs the results.
*/
static int
@@ -2859,14 +2869,14 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
- adapter->curr_iface_comb.sta_intf++;
+ adapter->curr_iface_comb.sta_intf--;
break;
case NL80211_IFTYPE_AP:
- adapter->curr_iface_comb.uap_intf++;
+ adapter->curr_iface_comb.uap_intf--;
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
- adapter->curr_iface_comb.p2p_intf++;
+ adapter->curr_iface_comb.p2p_intf--;
break;
default:
mwifiex_dbg(adapter, ERROR,
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 5a0636d43a1b..9824d8dd2b44 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -731,7 +731,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
(struct mwifiex_private *) file->private_data;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *) addr;
- int pos = 0, ret = 0, i;
+ int pos, ret, i;
u8 value[MAX_EEPROM_DATA];
if (!buf)
@@ -739,7 +739,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
if (saved_offset == -1) {
/* No command has been given */
- pos += snprintf(buf, PAGE_SIZE, "0");
+ pos = snprintf(buf, PAGE_SIZE, "0");
goto done;
}
@@ -748,17 +748,17 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
(u16) saved_bytes, value);
if (ret) {
ret = -EINVAL;
- goto done;
+ goto out_free;
}
- pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
+ pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
for (i = 0; i < saved_bytes; i++)
- pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]);
-
- ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
done:
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+out_free:
free_page(addr);
return ret;
}
@@ -856,6 +856,56 @@ mwifiex_hscfg_read(struct file *file, char __user *ubuf,
return ret;
}
+static ssize_t
+mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct mwifiex_private *priv = file->private_data;
+ char buf[3];
+ bool timeshare_coex;
+ int ret;
+ unsigned int len;
+
+ if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
+ return -EOPNOTSUPP;
+
+ ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
+ HostCmd_ACT_GEN_GET, 0, &timeshare_coex, true);
+ if (ret)
+ return ret;
+
+ len = sprintf(buf, "%d\n", timeshare_coex);
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static ssize_t
+mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ bool timeshare_coex;
+ struct mwifiex_private *priv = file->private_data;
+ char kbuf[16];
+ int ret;
+
+ if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
+ return -EOPNOTSUPP;
+
+ memset(kbuf, 0, sizeof(kbuf));
+
+ if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count)))
+ return -EFAULT;
+
+ if (strtobool(kbuf, &timeshare_coex))
+ return -EINVAL;
+
+ ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
+ HostCmd_ACT_GEN_SET, 0, &timeshare_coex, true);
+ if (ret)
+ return ret;
+ else
+ return count;
+}
+
#define MWIFIEX_DFS_ADD_FILE(name) do { \
if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \
priv, &mwifiex_dfs_##name##_fops)) \
@@ -892,6 +942,7 @@ MWIFIEX_DFS_FILE_OPS(memrw);
MWIFIEX_DFS_FILE_OPS(hscfg);
MWIFIEX_DFS_FILE_OPS(histogram);
MWIFIEX_DFS_FILE_OPS(debug_mask);
+MWIFIEX_DFS_FILE_OPS(timeshare_coex);
/*
* This function creates the debug FS directory structure and the files.
@@ -918,6 +969,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
MWIFIEX_DFS_ADD_FILE(hscfg);
MWIFIEX_DFS_ADD_FILE(histogram);
MWIFIEX_DFS_ADD_FILE(debug_mask);
+ MWIFIEX_DFS_ADD_FILE(timeshare_coex);
}
/*
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 3ec2ac82e394..1e1e81a0a8d4 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -101,9 +101,13 @@ enum KEY_TYPE_ID {
#define FIRMWARE_READY_SDIO 0xfedc
#define FIRMWARE_READY_PCIE 0xfedcba00
+#define MWIFIEX_COEX_MODE_TIMESHARE 0x01
+#define MWIFIEX_COEX_MODE_SPATIAL 0x82
+
enum mwifiex_usb_ep {
MWIFIEX_USB_EP_CMD_EVENT = 1,
MWIFIEX_USB_EP_DATA = 2,
+ MWIFIEX_USB_EP_DATA_CH2 = 3,
};
enum MWIFIEX_802_11_PRIVACY_FILTER {
@@ -162,6 +166,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91)
#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93)
#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94)
+#define TLV_TYPE_ROBUST_COEX (PROPRIETARY_TLV_BASE_ID + 96)
#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104)
#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105)
#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113)
@@ -173,6 +178,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154)
#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156)
#define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183)
+#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184)
#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197)
#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
@@ -352,6 +358,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df
#define HostCmd_CMD_TXPWR_CFG 0x00d1
#define HostCmd_CMD_TX_RATE_CFG 0x00d6
+#define HostCmd_CMD_ROBUST_COEX 0x00e0
#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4
#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5
#define HostCmd_CMD_P2P_MODE_CFG 0x00eb
@@ -1875,6 +1882,11 @@ struct mwifiex_ie_types_btcoex_aggr_win_size {
u8 reserved;
} __packed;
+struct mwifiex_ie_types_robust_coex {
+ struct mwifiex_ie_types_header header;
+ __le32 mode;
+} __packed;
+
struct host_cmd_ds_version_ext {
u8 version_str_sel;
char version_str[128];
@@ -1984,6 +1996,22 @@ struct mwifiex_ie_types_multi_chan_info {
u8 tlv_buffer[0];
} __packed;
+struct mwifiex_ie_types_mc_group_info {
+ struct mwifiex_ie_types_header header;
+ u8 chan_group_id;
+ u8 chan_buf_weight;
+ u8 band_config;
+ u8 chan_num;
+ u32 chan_time;
+ u32 reserved;
+ union {
+ u8 sdio_func_num;
+ u8 usb_ep_num;
+ } hid_num;
+ u8 intf_num;
+ u8 bss_type_numlist[0];
+} __packed;
+
struct meas_rpt_map {
u8 rssi:3;
u8 unmeasured:1;
@@ -2060,6 +2088,11 @@ struct host_cmd_ds_multi_chan_policy {
__le16 policy;
} __packed;
+struct host_cmd_ds_robust_coex {
+ __le16 action;
+ __le16 reserved;
+} __packed;
+
struct host_cmd_ds_command {
__le16 command;
__le16 size;
@@ -2129,6 +2162,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_chan_rpt_req chan_rpt_req;
struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg;
struct host_cmd_ds_multi_chan_policy mc_policy;
+ struct host_cmd_ds_robust_coex coex;
} params;
} __packed;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 5d3ae63baea4..de74a7773fb6 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -78,6 +78,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
priv->media_connected = false;
eth_broadcast_addr(priv->curr_addr);
priv->port_open = false;
+ priv->usb_port = MWIFIEX_USB_EP_DATA;
priv->pkt_tx_ctrl = 0;
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
priv->data_rate = 0; /* Initially indicate the rate as auto */
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 278dc94eaecb..969ca1e1f3e9 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -294,9 +294,15 @@ process_start:
/* We have tried to wakeup the card already */
if (adapter->pm_wakeup_fw_try)
break;
- if (adapter->ps_state != PS_STATE_AWAKE ||
- adapter->tx_lock_flag)
+ if (adapter->ps_state != PS_STATE_AWAKE)
break;
+ if (adapter->tx_lock_flag) {
+ if (adapter->iface_type == MWIFIEX_USB) {
+ if (!adapter->usb_mc_setup)
+ break;
+ } else
+ break;
+ }
if ((!adapter->scan_chan_gap_enabled &&
adapter->scan_processing) || adapter->data_sent ||
@@ -345,11 +351,18 @@ process_start:
*/
if ((adapter->ps_state == PS_STATE_SLEEP) ||
(adapter->ps_state == PS_STATE_PRE_SLEEP) ||
- (adapter->ps_state == PS_STATE_SLEEP_CFM) ||
- adapter->tx_lock_flag){
+ (adapter->ps_state == PS_STATE_SLEEP_CFM)) {
continue;
}
+ if (adapter->tx_lock_flag) {
+ if (adapter->iface_type == MWIFIEX_USB) {
+ if (!adapter->usb_mc_setup)
+ continue;
+ } else
+ continue;
+ }
+
if (!adapter->cmd_sent && !adapter->curr_cmd &&
mwifiex_is_send_cmd_allowed
(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
@@ -359,6 +372,13 @@ process_start:
}
}
+ /** If USB Multi channel setup ongoing,
+ * wait for ready to tx data.
+ */
+ if (adapter->iface_type == MWIFIEX_USB &&
+ adapter->usb_mc_setup)
+ continue;
+
if ((adapter->scan_chan_gap_enabled ||
!adapter->scan_processing) &&
!adapter->data_sent &&
@@ -928,6 +948,32 @@ mwifiex_tx_timeout(struct net_device *dev)
}
}
+void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter)
+{
+ struct usb_card_rec *card = adapter->card;
+ struct mwifiex_private *priv;
+ u16 tx_buf_size;
+ int i, ret;
+
+ card->mc_resync_flag = true;
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ if (atomic_read(&card->port[i].tx_data_urb_pending)) {
+ mwifiex_dbg(adapter, WARN, "pending data urb in sys\n");
+ return;
+ }
+ }
+
+ card->mc_resync_flag = false;
+ tx_buf_size = 0xffff;
+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+ ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
+ HostCmd_ACT_GEN_SET, 0, &tx_buf_size, false);
+ if (ret)
+ mwifiex_dbg(adapter, ERROR,
+ "send reconfig tx buf size cmd err\n");
+}
+EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);
+
void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
{
void *p;
@@ -963,8 +1009,10 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
cardp = (struct usb_card_rec *)adapter->card;
p += sprintf(p, "tx_cmd_urb_pending = %d\n",
atomic_read(&cardp->tx_cmd_urb_pending));
- p += sprintf(p, "tx_data_urb_pending = %d\n",
- atomic_read(&cardp->tx_data_urb_pending));
+ p += sprintf(p, "tx_data_urb_pending_port_0 = %d\n",
+ atomic_read(&cardp->port[0].tx_data_urb_pending));
+ p += sprintf(p, "tx_data_urb_pending_port_1 = %d\n",
+ atomic_read(&cardp->port[1].tx_data_urb_pending));
p += sprintf(p, "rx_cmd_urb_pending = %d\n",
atomic_read(&cardp->rx_cmd_urb_pending));
p += sprintf(p, "rx_data_urb_pending = %d\n",
@@ -1151,6 +1199,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
.ndo_stop = mwifiex_close,
.ndo_start_xmit = mwifiex_hard_start_xmit,
.ndo_set_mac_address = mwifiex_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = mwifiex_tx_timeout,
.ndo_get_stats = mwifiex_get_stats,
.ndo_set_rx_mode = mwifiex_set_multicast_list,
@@ -1447,6 +1496,26 @@ exit_sem_err:
}
EXPORT_SYMBOL_GPL(mwifiex_remove_card);
+void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ if (!adapter->dev || !(adapter->debug_mask & mask))
+ return;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ dev_info(adapter->dev, "%pV", &vaf);
+
+ va_end(args);
+}
+EXPORT_SYMBOL_GPL(_mwifiex_dbg);
+
/*
* This function initializes the module.
*
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 6b9512140e7a..3959f1c97f4e 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -48,6 +48,9 @@
extern const char driver_version[];
+struct mwifiex_adapter;
+struct mwifiex_private;
+
enum {
MWIFIEX_ASYNC_CMD,
MWIFIEX_SYNC_CMD
@@ -180,12 +183,11 @@ enum MWIFIEX_DEBUG_LEVEL {
MWIFIEX_DBG_FATAL | \
MWIFIEX_DBG_ERROR)
-#define mwifiex_dbg(adapter, dbg_mask, fmt, args...) \
-do { \
- if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask) \
- if ((adapter)->dev) \
- dev_info((adapter)->dev, fmt, ## args); \
-} while (0)
+__printf(3, 4)
+void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
+ const char *fmt, ...);
+#define mwifiex_dbg(adapter, mask, fmt, ...) \
+ _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
#define DEBUG_DUMP_DATA_MAX_LEN 128
#define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len) \
@@ -506,9 +508,6 @@ enum mwifiex_iface_work_flags {
MWIFIEX_IFACE_WORK_CARD_RESET,
};
-struct mwifiex_adapter;
-struct mwifiex_private;
-
struct mwifiex_private {
struct mwifiex_adapter *adapter;
u8 bss_type;
@@ -520,6 +519,7 @@ struct mwifiex_private {
u8 curr_addr[ETH_ALEN];
u8 media_connected;
u8 port_open;
+ u8 usb_port;
u32 num_tx_timeout;
/* track consecutive timeout */
u8 tx_timeout_cnt;
@@ -816,6 +816,8 @@ struct mwifiex_if_ops {
void (*iface_work)(struct work_struct *work);
void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *);
+ void (*multi_port_resync)(struct mwifiex_adapter *);
+ bool (*is_port_ready)(struct mwifiex_private *);
};
struct mwifiex_adapter {
@@ -861,6 +863,8 @@ struct mwifiex_adapter {
u8 more_task_flag;
u16 tx_buf_size;
u16 curr_tx_buf_size;
+ /* sdio single port rx aggregation capability */
+ bool host_disable_sdio_rx_aggr;
bool sdio_rx_aggr_enable;
u16 sdio_rx_block_size;
u32 ioport;
@@ -988,6 +992,8 @@ struct mwifiex_adapter {
u8 coex_rx_win_size;
bool drcs_enabled;
u8 active_scan_triggered;
+ bool usb_mc_status;
+ bool usb_mc_setup;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1561,6 +1567,7 @@ void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
struct sk_buff *event);
void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
struct sk_buff *event_skb);
+void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter);
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 408b68460716..21192b6f9c64 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1815,7 +1815,6 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
if (!card->evt_buf_list[rdptr]) {
skb_push(skb, INTF_HEADER_LEN);
skb_put(skb, MAX_EVENT_SIZE - skb->len);
- memset(skb->data, 0, MAX_EVENT_SIZE);
if (mwifiex_map_pci_memory(adapter, skb,
MAX_EVENT_SIZE,
PCI_DMA_FROMDEVICE))
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 5847863a2d6b..c20017ced566 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1839,14 +1839,18 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
bssid, timestamp,
cap_info_bitmap, beacon_period,
ie_buf, ie_len, rssi, GFP_KERNEL);
- bss_priv = (struct mwifiex_bss_priv *)bss->priv;
- bss_priv->band = band;
- bss_priv->fw_tsf = fw_tsf;
- if (priv->media_connected &&
- !memcmp(bssid, priv->curr_bss_params.bss_descriptor
- .mac_address, ETH_ALEN))
- mwifiex_update_curr_bss_params(priv, bss);
- cfg80211_put_bss(priv->wdev.wiphy, bss);
+ if (bss) {
+ bss_priv = (struct mwifiex_bss_priv *)bss->priv;
+ bss_priv->band = band;
+ bss_priv->fw_tsf = fw_tsf;
+ if (priv->media_connected &&
+ !memcmp(bssid, priv->curr_bss_params.
+ bss_descriptor.mac_address,
+ ETH_ALEN))
+ mwifiex_update_curr_bss_params(priv,
+ bss);
+ cfg80211_put_bss(priv->wdev.wiphy, bss);
+ }
if ((chan->flags & IEEE80211_CHAN_RADAR) ||
(chan->flags & IEEE80211_CHAN_NO_IR)) {
@@ -1889,7 +1893,7 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
u8 id = 0;
struct mwifiex_user_scan_cfg *user_scan_cfg;
- if (adapter->active_scan_triggered) {
+ if (adapter->active_scan_triggered || !priv->scan_request) {
adapter->active_scan_triggered = false;
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 5d05c6fe6429..78a8474e1a3d 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1606,8 +1606,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
(rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
1) / MWIFIEX_SDIO_BLOCK_SIZE;
if (rx_len <= INTF_HEADER_LEN ||
- (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
- card->mpa_rx.buf_size) {
+ (card->mpa_rx.enabled &&
+ ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
+ card->mpa_rx.buf_size))) {
mwifiex_dbg(adapter, ERROR,
"invalid rx_len=%d\n",
rx_len);
@@ -1925,6 +1926,8 @@ error:
if (ret) {
kfree(card->mpa_tx.buf);
kfree(card->mpa_rx.buf);
+ card->mpa_tx.buf_size = 0;
+ card->mpa_rx.buf_size = 0;
}
return ret;
@@ -2055,16 +2058,26 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
ret = mwifiex_alloc_sdio_mpa_buffers(adapter,
card->mp_tx_agg_buf_size,
card->mp_rx_agg_buf_size);
- if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "failed to alloc sdio mp-a buffers\n");
- kfree(card->mp_regs);
- return -1;
+
+ /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */
+ if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX ||
+ card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) {
+ /* Disable rx single port aggregation */
+ adapter->host_disable_sdio_rx_aggr = true;
+
+ ret = mwifiex_alloc_sdio_mpa_buffers
+ (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+ MWIFIEX_MP_AGGR_BUF_SIZE_32K);
+ if (ret) {
+ /* Disable multi port aggregation */
+ card->mpa_tx.enabled = 0;
+ card->mpa_rx.enabled = 0;
+ }
}
adapter->auto_tdls = card->can_auto_tdls;
adapter->ext_scan = card->can_ext_scan;
- return ret;
+ return 0;
}
/*
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index a49a80dd773e..e486867a4c67 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1531,6 +1531,33 @@ mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv,
return 0;
}
+static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action, bool *is_timeshare)
+{
+ struct host_cmd_ds_robust_coex *coex = &cmd->params.coex;
+ struct mwifiex_ie_types_robust_coex *coex_tlv;
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX);
+ cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN);
+
+ coex->action = cpu_to_le16(cmd_action);
+ coex_tlv = (struct mwifiex_ie_types_robust_coex *)
+ ((u8 *)coex + sizeof(*coex));
+ coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX);
+ coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode));
+
+ if (coex->action == HostCmd_ACT_GEN_GET)
+ return 0;
+
+ if (*is_timeshare)
+ coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE);
+ else
+ coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL);
+
+ return 0;
+}
+
static int
mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
@@ -2040,6 +2067,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action,
data_buf);
break;
+ case HostCmd_CMD_ROBUST_COEX:
+ ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action,
+ data_buf);
+ break;
default:
mwifiex_dbg(priv->adapter, ERROR,
"PREP_CMD: unknown cmd- %#x\n", cmd_no);
@@ -2125,7 +2156,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
/** Set SDIO Single Port RX Aggr Info */
if (priv->adapter->iface_type == MWIFIEX_SDIO &&
- ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info)) {
+ ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) &&
+ !priv->adapter->host_disable_sdio_rx_aggr) {
sdio_sp_rx_aggr_enable = true;
ret = mwifiex_send_cmd(priv,
HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 87b69d8ad120..9ac7aa2431b4 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -1007,6 +1007,28 @@ static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv,
return 0;
}
+static int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *resp,
+ bool *is_timeshare)
+{
+ struct host_cmd_ds_robust_coex *coex = &resp->params.coex;
+ struct mwifiex_ie_types_robust_coex *coex_tlv;
+ u16 action = le16_to_cpu(coex->action);
+ u32 mode;
+
+ coex_tlv = (struct mwifiex_ie_types_robust_coex
+ *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex));
+ if (action == HostCmd_ACT_GEN_GET) {
+ mode = le32_to_cpu(coex_tlv->mode);
+ if (mode == MWIFIEX_COEX_MODE_TIMESHARE)
+ *is_timeshare = true;
+ else
+ *is_timeshare = false;
+ }
+
+ return 0;
+}
+
/*
* This function handles the command responses.
*
@@ -1128,6 +1150,17 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
ret = mwifiex_ret_11n_addba_resp(priv, resp);
break;
case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+ if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) {
+ if (adapter->iface_type == MWIFIEX_USB &&
+ adapter->usb_mc_setup) {
+ if (adapter->if_ops.multi_port_resync)
+ adapter->if_ops.
+ multi_port_resync(adapter);
+ adapter->usb_mc_setup = false;
+ adapter->tx_lock_flag = false;
+ }
+ break;
+ }
adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
tx_buf.buff_size);
adapter->tx_buf_size = (adapter->tx_buf_size
@@ -1202,6 +1235,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
break;
case HostCmd_CMD_TDLS_CONFIG:
break;
+ case HostCmd_CMD_ROBUST_COEX:
+ ret = mwifiex_ret_robust_coex(priv, resp, data_buf);
+ break;
default:
mwifiex_dbg(adapter, ERROR,
"CMD_RESP: unknown cmd response %#x\n",
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 3d18c585e543..ff3ee9dfbbd5 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -313,24 +313,78 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
struct sk_buff *event_skb)
{
struct mwifiex_ie_types_multi_chan_info *chan_info;
- u16 status;
+ struct mwifiex_ie_types_mc_group_info *grp_info;
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct mwifiex_ie_types_header *tlv;
+ u16 tlv_buf_left, tlv_type, tlv_len;
+ int intf_num, bss_type, bss_num, i;
+ struct mwifiex_private *intf_priv;
+ tlv_buf_left = event_skb->len - sizeof(u32);
chan_info = (void *)event_skb->data + sizeof(u32);
- if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO) {
- mwifiex_dbg(priv->adapter, ERROR,
+ if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO ||
+ tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) {
+ mwifiex_dbg(adapter, ERROR,
"unknown TLV in chan_info event\n");
return;
}
- status = le16_to_cpu(chan_info->status);
+ adapter->usb_mc_status = le16_to_cpu(chan_info->status);
+ mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n",
+ adapter->usb_mc_status ? "started" : "over");
- if (status) {
- mwifiex_dbg(priv->adapter, EVENT,
- "multi-channel operation started\n");
- } else {
- mwifiex_dbg(priv->adapter, EVENT,
- "multi-channel operation over\n");
+ tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info);
+ tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer;
+
+ while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_len = le16_to_cpu(tlv->len);
+ if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
+ tlv_buf_left) {
+ mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t"
+ "tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
+ break;
+ }
+ if (tlv_type != TLV_TYPE_MC_GROUP_INFO) {
+ mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n",
+ tlv_type);
+ break;
+ }
+
+ grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv;
+ intf_num = grp_info->intf_num;
+ for (i = 0; i < intf_num; i++) {
+ bss_type = grp_info->bss_type_numlist[i] >> 4;
+ bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK;
+ intf_priv = mwifiex_get_priv_by_id(adapter, bss_num,
+ bss_type);
+ if (!intf_priv) {
+ mwifiex_dbg(adapter, ERROR,
+ "Invalid bss_type bss_num\t"
+ "in multi channel event\n");
+ continue;
+ }
+ if (adapter->iface_type == MWIFIEX_USB) {
+ u8 ep;
+
+ ep = grp_info->hid_num.usb_ep_num;
+ if (ep == MWIFIEX_USB_EP_DATA ||
+ ep == MWIFIEX_USB_EP_DATA_CH2)
+ intf_priv->usb_port = ep;
+ }
+ }
+
+ tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
+ tlv_len;
+ tlv = (void *)((u8 *)tlv + tlv_len +
+ sizeof(struct mwifiex_ie_types_header));
+ }
+
+ if (adapter->iface_type == MWIFIEX_USB) {
+ adapter->tx_lock_flag = true;
+ adapter->usb_mc_setup = true;
+ mwifiex_multi_chan_resync(adapter);
}
}
@@ -562,7 +616,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
adapter->tx_lock_flag = false;
if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
if (mwifiex_check_last_packet_indication(priv)) {
- if (adapter->data_sent) {
+ if (adapter->data_sent ||
+ (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv))) {
adapter->ps_state = PS_STATE_AWAKE;
adapter->pm_wakeup_card_req = false;
adapter->pm_wakeup_fw_try = false;
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index 355ac5904fac..f6683ea6bd5d 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -153,6 +153,10 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
if (adapter->data_sent)
return -1;
+ if (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv))
+ return -1;
+
skb = dev_alloc_skb(data_len);
if (!skb)
return -1;
@@ -174,7 +178,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
local_tx_pd->bss_type = priv->bss_type;
if (adapter->iface_type == MWIFIEX_USB) {
- ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA,
+ ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
skb, NULL);
} else {
skb_push(skb, INTF_HEADER_LEN);
@@ -191,7 +195,6 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
adapter->dbg.num_tx_host_to_card_failure++;
break;
case -1:
- adapter->data_sent = false;
dev_kfree_skb_any(skb);
mwifiex_dbg(adapter, ERROR,
"%s: host_to_card failed: ret=%d\n",
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index b3e163de9899..9275f9c3f869 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -204,6 +204,12 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
return -1;
}
+ if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) {
+ mwifiex_dbg(priv->adapter, WARN,
+ "TDLS peer doesn't support ht capabilities\n");
+ return 0;
+ }
+
pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
*pos++ = WLAN_EID_HT_OPERATION;
*pos++ = sizeof(struct ieee80211_ht_operation);
@@ -252,6 +258,12 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
return -1;
}
+ if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) {
+ mwifiex_dbg(adapter, WARN,
+ "TDLS peer doesn't support vht capabilities\n");
+ return 0;
+ }
+
if (!mwifiex_is_bss_in_11ac_mode(priv)) {
if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 8b1e5b5d47fe..bf6182b646a5 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -115,9 +115,8 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
local_tx_pd = (struct txpd *)(head_ptr + hroom);
if (adapter->iface_type == MWIFIEX_USB) {
- adapter->data_sent = true;
ret = adapter->if_ops.host_to_card(adapter,
- MWIFIEX_USB_EP_DATA,
+ priv->usb_port,
skb, NULL);
} else {
ret = adapter->if_ops.host_to_card(adapter,
@@ -130,7 +129,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
switch (ret) {
case -ENOSR:
- mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
+ mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n");
break;
case -EBUSY:
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
@@ -142,8 +141,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
break;
case -1:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
mwifiex_dbg(adapter, ERROR,
"mwifiex_write_data_async failed: 0x%X\n",
ret);
@@ -151,8 +148,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
mwifiex_write_data_complete(adapter, skb, 0, ret);
break;
case -EINPROGRESS:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
break;
case 0:
mwifiex_write_data_complete(adapter, skb, 0, ret);
@@ -193,9 +188,8 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
}
if (adapter->iface_type == MWIFIEX_USB) {
- adapter->data_sent = true;
ret = adapter->if_ops.host_to_card(adapter,
- MWIFIEX_USB_EP_DATA,
+ priv->usb_port,
skb, NULL);
} else {
ret = adapter->if_ops.host_to_card(adapter,
@@ -222,16 +216,12 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
break;
case -1:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
mwifiex_dbg(adapter, ERROR,
"mwifiex_write_data_async failed: 0x%X\n", ret);
adapter->dbg.num_tx_host_to_card_failure++;
mwifiex_write_data_complete(adapter, skb, 0, ret);
break;
case -EINPROGRESS:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
break;
case 0:
mwifiex_write_data_complete(adapter, skb, 0, ret);
@@ -306,9 +296,6 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
if (!priv)
goto done;
- if (adapter->iface_type == MWIFIEX_USB)
- adapter->data_sent = false;
-
mwifiex_set_trans_start(priv->netdev);
if (!status) {
priv->stats.tx_packets++;
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 4d5a6e3b6361..759a6ada5b0f 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -846,22 +846,6 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv,
{
enum state_11d_t state_11d;
- if (mwifiex_del_mgmt_ies(priv))
- mwifiex_dbg(priv->adapter, ERROR,
- "Failed to delete mgmt IEs!\n");
-
- if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
- HostCmd_ACT_GEN_SET, 0, NULL, true)) {
- mwifiex_dbg(priv->adapter, ERROR, "Failed to stop the BSS\n");
- return -1;
- }
-
- if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
- HostCmd_ACT_GEN_SET, 0, NULL, true)) {
- mwifiex_dbg(priv->adapter, ERROR, "Failed to reset BSS\n");
- return -1;
- }
-
if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
HostCmd_ACT_GEN_SET,
UAP_BSS_PARAMS_I, bss_cfg, false)) {
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 46c972a650a4..86ff54296f39 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -179,19 +179,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
case EVENT_UAP_BSS_IDLE:
priv->media_connected = false;
priv->port_open = false;
- if (netif_carrier_ok(priv->netdev))
- netif_carrier_off(priv->netdev);
- mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-
mwifiex_clean_txrx(priv);
mwifiex_del_all_sta_list(priv);
break;
case EVENT_UAP_BSS_ACTIVE:
priv->media_connected = true;
priv->port_open = true;
- if (!netif_carrier_ok(priv->netdev))
- netif_carrier_on(priv->netdev);
- mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
break;
case EVENT_UAP_BSS_START:
mwifiex_dbg(adapter, EVENT,
@@ -269,7 +262,9 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
adapter->tx_lock_flag = false;
if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
if (mwifiex_check_last_packet_indication(priv)) {
- if (adapter->data_sent) {
+ if (adapter->data_sent ||
+ (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv))) {
adapter->ps_state = PS_STATE_AWAKE;
adapter->pm_wakeup_card_req = false;
adapter->pm_wakeup_fw_try = false;
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index 87667418af5f..74d5d7238633 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -31,7 +31,8 @@
*/
static bool
mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv,
- struct list_head *ra_list_head)
+ struct list_head *ra_list_head,
+ int tid)
{
struct mwifiex_ra_list_tbl *ra_list;
struct sk_buff *skb, *tmp;
@@ -49,7 +50,10 @@ mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv,
__skb_unlink(skb, &ra_list->skb_head);
mwifiex_write_data_complete(adapter, skb, 0,
-1);
- atomic_dec(&priv->wmm.tx_pkts_queued);
+ if (ra_list->tx_paused)
+ priv->wmm.pkts_paused[tid]--;
+ else
+ atomic_dec(&priv->wmm.tx_pkts_queued);
pkt_deleted = true;
}
if ((atomic_read(&adapter->pending_bridged_pkts) <=
@@ -77,7 +81,7 @@ static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv)
if (priv->del_list_idx == MAX_NUM_TID)
priv->del_list_idx = 0;
ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list;
- if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list)) {
+ if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) {
priv->del_list_idx++;
break;
}
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 5e789b2e06ea..e43aff932360 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -42,11 +42,6 @@ static struct usb_device_id mwifiex_usb_table[] = {
{USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2,
USB_CLASS_VENDOR_SPEC,
USB_SUBCLASS_VENDOR_SPEC, 0xff)},
- /* 8897 */
- {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)},
- {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2,
- USB_CLASS_VENDOR_SPEC,
- USB_SUBCLASS_VENDOR_SPEC, 0xff)},
/* 8997 */
{USB_DEVICE(USB8XXX_VID, USB8997_PID_1)},
{USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2,
@@ -264,6 +259,8 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
struct urb_context *context = (struct urb_context *)(urb->context);
struct mwifiex_adapter *adapter = context->adapter;
struct usb_card_rec *card = adapter->card;
+ struct usb_tx_data_port *port;
+ int i;
mwifiex_dbg(adapter, INFO,
"%s: status: %d\n", __func__, urb->status);
@@ -276,11 +273,22 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
} else {
mwifiex_dbg(adapter, DATA,
"%s: DATA\n", __func__);
- atomic_dec(&card->tx_data_urb_pending);
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ port = &card->port[i];
+ if (context->ep == port->tx_data_ep) {
+ atomic_dec(&port->tx_data_urb_pending);
+ port->block_status = false;
+ break;
+ }
+ }
+ adapter->data_sent = false;
mwifiex_write_data_complete(adapter, context->skb, 0,
urb->status ? -1 : 0);
}
+ if (card->mc_resync_flag)
+ mwifiex_multi_chan_resync(adapter);
+
mwifiex_queue_main_work(adapter);
return;
@@ -327,7 +335,8 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size)
static void mwifiex_usb_free(struct usb_card_rec *card)
{
- int i;
+ struct usb_tx_data_port *port;
+ int i, j;
if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
usb_kill_urb(card->rx_cmd.urb);
@@ -345,9 +354,12 @@ static void mwifiex_usb_free(struct usb_card_rec *card)
card->rx_data_list[i].urb = NULL;
}
- for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) {
- usb_free_urb(card->tx_data_list[i].urb);
- card->tx_data_list[i].urb = NULL;
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ port = &card->port[i];
+ for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+ usb_free_urb(port->tx_data_list[j].urb);
+ port->tx_data_list[j].urb = NULL;
+ }
}
usb_free_urb(card->tx_cmd.urb);
@@ -386,14 +398,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
case USB8766_PID_1:
case USB8797_PID_1:
case USB8801_PID_1:
- case USB8897_PID_1:
case USB8997_PID_1:
card->usb_boot_state = USB8XXX_FW_DNLD;
break;
case USB8766_PID_2:
case USB8797_PID_2:
case USB8801_PID_2:
- case USB8897_PID_2:
case USB8997_PID_2:
card->usb_boot_state = USB8XXX_FW_READY;
break;
@@ -437,8 +447,18 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n",
le16_to_cpu(epd->wMaxPacketSize),
epd->bEndpointAddress);
- card->tx_data_ep = usb_endpoint_num(epd);
- atomic_set(&card->tx_data_urb_pending, 0);
+ card->port[0].tx_data_ep = usb_endpoint_num(epd);
+ atomic_set(&card->port[0].tx_data_urb_pending, 0);
+ }
+ if (usb_endpoint_dir_out(epd) &&
+ usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA_CH2 &&
+ usb_endpoint_xfer_bulk(epd)) {
+ pr_debug("info: bulk OUT chan2:\t"
+ "max pkt size: %d, addr: %d\n",
+ le16_to_cpu(epd->wMaxPacketSize),
+ epd->bEndpointAddress);
+ card->port[1].tx_data_ep = usb_endpoint_num(epd);
+ atomic_set(&card->port[1].tx_data_urb_pending, 0);
}
if (usb_endpoint_dir_out(epd) &&
usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT &&
@@ -480,7 +500,8 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usb_card_rec *card = usb_get_intfdata(intf);
struct mwifiex_adapter *adapter;
- int i;
+ struct usb_tx_data_port *port;
+ int i, j;
if (!card || !card->adapter) {
pr_err("%s: card or card->adapter is NULL\n", __func__);
@@ -511,9 +532,13 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
if (card->rx_data_list[i].urb)
usb_kill_urb(card->rx_data_list[i].urb);
- for (i = 0; i < MWIFIEX_TX_DATA_URB; i++)
- if (card->tx_data_list[i].urb)
- usb_kill_urb(card->tx_data_list[i].urb);
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ port = &card->port[i];
+ for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+ if (port->tx_data_list[j].urb)
+ usb_kill_urb(port->tx_data_list[j].urb);
+ }
+ }
if (card->tx_cmd.urb)
usb_kill_urb(card->tx_cmd.urb);
@@ -625,7 +650,8 @@ static struct usb_driver mwifiex_usb_driver = {
static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
{
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
- int i;
+ struct usb_tx_data_port *port;
+ int i, j;
card->tx_cmd.adapter = adapter;
card->tx_cmd.ep = card->tx_cmd_ep;
@@ -637,17 +663,25 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
return -ENOMEM;
}
- card->tx_data_ix = 0;
-
- for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) {
- card->tx_data_list[i].adapter = adapter;
- card->tx_data_list[i].ep = card->tx_data_ep;
-
- card->tx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!card->tx_data_list[i].urb) {
- mwifiex_dbg(adapter, ERROR,
- "tx_data_list[] urb allocation failed\n");
- return -ENOMEM;
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ port = &card->port[i];
+ if (!port->tx_data_ep)
+ continue;
+ port->tx_data_ix = 0;
+ if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
+ port->block_status = false;
+ else
+ port->block_status = true;
+ for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+ port->tx_data_list[j].adapter = adapter;
+ port->tx_data_list[j].ep = port->tx_data_ep;
+ port->tx_data_list[j].urb =
+ usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->tx_data_list[j].urb) {
+ mwifiex_dbg(adapter, ERROR,
+ "urb allocation failed\n");
+ return -ENOMEM;
+ }
}
}
@@ -736,15 +770,89 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
return ret;
}
+static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter)
+{
+ struct usb_card_rec *card = adapter->card;
+ u8 active_port = MWIFIEX_USB_EP_DATA;
+ struct mwifiex_private *priv = NULL;
+ int i;
+
+ if (adapter->usb_mc_status) {
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (!priv)
+ continue;
+ if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP &&
+ !priv->bss_started) ||
+ (priv->bss_role == MWIFIEX_BSS_ROLE_STA &&
+ !priv->media_connected))
+ priv->usb_port = MWIFIEX_USB_EP_DATA;
+ }
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++)
+ card->port[i].block_status = false;
+ } else {
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (!priv)
+ continue;
+ if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP &&
+ priv->bss_started) ||
+ (priv->bss_role == MWIFIEX_BSS_ROLE_STA &&
+ priv->media_connected)) {
+ active_port = priv->usb_port;
+ break;
+ }
+ }
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (priv)
+ priv->usb_port = active_port;
+ }
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ if (active_port == card->port[i].tx_data_ep)
+ card->port[i].block_status = false;
+ else
+ card->port[i].block_status = true;
+ }
+ }
+}
+
+static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv)
+{
+ struct usb_card_rec *card = priv->adapter->card;
+ int idx;
+
+ for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+ if (priv->usb_port == card->port[idx].tx_data_ep)
+ return !card->port[idx].block_status;
+ }
+
+ return false;
+}
+
+static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter)
+{
+ struct usb_card_rec *card = adapter->card;
+ int i;
+
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++)
+ if (!card->port[i].block_status)
+ return false;
+
+ return true;
+}
+
/* This function write a command/data packet to card. */
static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
struct sk_buff *skb,
struct mwifiex_tx_param *tx_param)
{
struct usb_card_rec *card = adapter->card;
- struct urb_context *context;
+ struct urb_context *context = NULL;
+ struct usb_tx_data_port *port = NULL;
u8 *data = (u8 *)skb->data;
struct urb *tx_urb;
+ int idx, ret;
if (adapter->is_suspended) {
mwifiex_dbg(adapter, ERROR,
@@ -757,19 +865,31 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
return -1;
}
- if (ep == card->tx_data_ep &&
- atomic_read(&card->tx_data_urb_pending) >= MWIFIEX_TX_DATA_URB) {
- return -EBUSY;
- }
-
mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep);
if (ep == card->tx_cmd_ep) {
context = &card->tx_cmd;
} else {
- if (card->tx_data_ix >= MWIFIEX_TX_DATA_URB)
- card->tx_data_ix = 0;
- context = &card->tx_data_list[card->tx_data_ix++];
+ for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+ if (ep == card->port[idx].tx_data_ep) {
+ port = &card->port[idx];
+ if (atomic_read(&port->tx_data_urb_pending)
+ >= MWIFIEX_TX_DATA_URB) {
+ port->block_status = true;
+ ret = -EBUSY;
+ goto done;
+ }
+ if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+ port->tx_data_ix = 0;
+ context =
+ &port->tx_data_list[port->tx_data_ix++];
+ break;
+ }
+ }
+ if (!port) {
+ mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
+ return -1;
+ }
}
context->adapter = adapter;
@@ -786,7 +906,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
if (ep == card->tx_cmd_ep)
atomic_inc(&card->tx_cmd_urb_pending);
else
- atomic_inc(&card->tx_data_urb_pending);
+ atomic_inc(&port->tx_data_urb_pending);
if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
mwifiex_dbg(adapter, ERROR,
@@ -794,22 +914,32 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
if (ep == card->tx_cmd_ep) {
atomic_dec(&card->tx_cmd_urb_pending);
} else {
- atomic_dec(&card->tx_data_urb_pending);
- if (card->tx_data_ix)
- card->tx_data_ix--;
+ atomic_dec(&port->tx_data_urb_pending);
+ port->block_status = false;
+ if (port->tx_data_ix)
+ port->tx_data_ix--;
else
- card->tx_data_ix = MWIFIEX_TX_DATA_URB;
+ port->tx_data_ix = MWIFIEX_TX_DATA_URB;
}
return -1;
} else {
- if (ep == card->tx_data_ep &&
- atomic_read(&card->tx_data_urb_pending) ==
- MWIFIEX_TX_DATA_URB)
- return -ENOSR;
+ if (ep != card->tx_cmd_ep &&
+ atomic_read(&port->tx_data_urb_pending) ==
+ MWIFIEX_TX_DATA_URB) {
+ port->block_status = true;
+ ret = -ENOSR;
+ goto done;
+ }
}
return -EINPROGRESS;
+
+done:
+ if (ep != card->tx_cmd_ep)
+ adapter->data_sent = mwifiex_usb_data_sent(adapter);
+
+ return ret;
}
/* This function register usb device and initialize parameter. */
@@ -827,12 +957,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME);
adapter->ext_scan = true;
break;
- case USB8897_PID_1:
- case USB8897_PID_2:
- adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
- strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME);
- adapter->ext_scan = true;
- break;
case USB8766_PID_1:
case USB8766_PID_2:
adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
@@ -853,6 +977,9 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
break;
}
+ adapter->usb_mc_status = false;
+ adapter->usb_mc_setup = false;
+
return 0;
}
@@ -1082,6 +1209,8 @@ static struct mwifiex_if_ops usb_ops = {
.event_complete = mwifiex_usb_cmd_event_complete,
.host_to_card = mwifiex_usb_host_to_card,
.submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs,
+ .multi_port_resync = mwifiex_usb_port_resync,
+ .is_port_ready = mwifiex_usb_is_port_ready,
};
/* This function initializes the USB driver module.
@@ -1135,5 +1264,4 @@ MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME);
-MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h
index f0051f8c8981..b4e9246bbcdc 100644
--- a/drivers/net/wireless/mwifiex/usb.h
+++ b/drivers/net/wireless/mwifiex/usb.h
@@ -28,11 +28,9 @@
#define USB8766_PID_2 0x2042
#define USB8797_PID_1 0x2043
#define USB8797_PID_2 0x2044
-#define USB8897_PID_1 0x2045
-#define USB8897_PID_2 0x2046
#define USB8801_PID_1 0x2049
#define USB8801_PID_2 0x204a
-#define USB8997_PID_1 0x204d
+#define USB8997_PID_1 0x2052
#define USB8997_PID_2 0x204e
@@ -40,6 +38,7 @@
#define USB8XXX_FW_READY 2
#define USB8XXX_FW_MAX_RETRY 3
+#define MWIFIEX_TX_DATA_PORT 2
#define MWIFIEX_TX_DATA_URB 6
#define MWIFIEX_RX_DATA_URB 6
#define MWIFIEX_USB_TIMEOUT 100
@@ -47,7 +46,6 @@
#define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin"
#define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin"
#define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin"
-#define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin"
#define USB8997_DEFAULT_FW_NAME "mrvl/usb8997_uapsta.bin"
#define FW_DNLD_TX_BUF_SIZE 620
@@ -64,6 +62,14 @@ struct urb_context {
u8 ep;
};
+struct usb_tx_data_port {
+ u8 tx_data_ep;
+ u8 block_status;
+ atomic_t tx_data_urb_pending;
+ int tx_data_ix;
+ struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
+};
+
struct usb_card_rec {
struct mwifiex_adapter *adapter;
struct usb_device *udev;
@@ -75,14 +81,12 @@ struct usb_card_rec {
u8 usb_boot_state;
u8 rx_data_ep;
atomic_t rx_data_urb_pending;
- u8 tx_data_ep;
u8 tx_cmd_ep;
- atomic_t tx_data_urb_pending;
atomic_t tx_cmd_urb_pending;
int bulk_out_maxpktsize;
struct urb_context tx_cmd;
- int tx_data_ix;
- struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
+ u8 mc_resync_flag;
+ struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT];
};
struct fw_header {
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 173d3663c2e0..acccd6734e3b 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -117,22 +117,15 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
*/
static u8 mwifiex_get_random_ba_threshold(void)
{
- u32 sec, usec;
- struct timeval ba_tstamp;
- u8 ba_threshold;
-
+ u64 ns;
/* setup ba_packet_threshold here random number between
* [BA_SETUP_PACKET_OFFSET,
* BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
*/
+ ns = ktime_get_ns();
+ ns += (ns >> 32) + (ns >> 16);
- do_gettimeofday(&ba_tstamp);
- sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16);
- usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16);
- ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD)
- + BA_SETUP_PACKET_OFFSET;
-
- return ba_threshold;
+ return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET;
}
/*
@@ -160,7 +153,6 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
ra_list->tdls_link = false;
ra_list->ba_status = BA_SETUP_NONE;
ra_list->amsdu_in_ampdu = false;
- ra_list->tx_paused = false;
if (!mwifiex_queuing_ra_based(priv)) {
if (mwifiex_is_tdls_link_setup
(mwifiex_get_tdls_link_status(priv, ra))) {
@@ -173,6 +165,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
} else {
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
node = mwifiex_get_sta_entry(priv, ra);
+ if (node)
+ ra_list->tx_paused = node->tx_pause;
ra_list->is_11n_enabled =
mwifiex_is_sta_11n_enabled(priv, node);
if (ra_list->is_11n_enabled)
@@ -451,7 +445,21 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter)
{
- return atomic_read(&adapter->bypass_tx_pending) ? false : true;
+ struct mwifiex_private *priv;
+ int i;
+
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (!priv)
+ continue;
+ if (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv))
+ continue;
+ if (!skb_queue_empty(&priv->bypass_txq))
+ return false;
+ }
+
+ return true;
}
/*
@@ -465,9 +473,14 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)
for (i = 0; i < adapter->priv_num; ++i) {
priv = adapter->priv[i];
- if (priv && !priv->port_open)
+ if (!priv)
+ continue;
+ if (!priv->port_open)
continue;
- if (priv && atomic_read(&priv->wmm.tx_pkts_queued))
+ if (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv))
+ continue;
+ if (atomic_read(&priv->wmm.tx_pkts_queued))
return false;
}
@@ -671,7 +684,7 @@ void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
if (!memcmp(ra_list->ra, mac, ETH_ALEN))
continue;
- if (ra_list && ra_list->tx_paused != tx_pause) {
+ if (ra_list->tx_paused != tx_pause) {
pkt_cnt += ra_list->total_pkt_count;
ra_list->tx_paused = tx_pause;
if (tx_pause)
@@ -737,7 +750,11 @@ mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
if (!ra_list)
continue;
mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
- atomic_sub(ra_list->total_pkt_count, &priv->wmm.tx_pkts_queued);
+ if (ra_list->tx_paused)
+ priv->wmm.pkts_paused[i] -= ra_list->total_pkt_count;
+ else
+ atomic_sub(ra_list->total_pkt_count,
+ &priv->wmm.tx_pkts_queued);
list_del(&ra_list->list);
kfree(ra_list);
}
@@ -1086,6 +1103,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
(atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0))
continue;
+ if (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv_tmp))
+ continue;
+
/* iterate over the WMM queues of the BSS */
hqp = &priv_tmp->wmm.highest_queued_prio;
for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
@@ -1321,8 +1342,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
if (adapter->iface_type == MWIFIEX_USB) {
- adapter->data_sent = true;
- ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA,
+ ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
skb, NULL);
} else {
tx_param.next_pkt_len =
@@ -1351,15 +1371,11 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
ra_list_flags);
break;
case -1:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret);
adapter->dbg.num_tx_host_to_card_failure++;
mwifiex_write_data_complete(adapter, skb, 0, ret);
break;
case -EINPROGRESS:
- if (adapter->iface_type != MWIFIEX_PCIE)
- adapter->data_sent = false;
break;
case 0:
mwifiex_write_data_complete(adapter, skb, 0, ret);
@@ -1467,6 +1483,13 @@ void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter)
for (i = 0; i < adapter->priv_num; ++i) {
priv = adapter->priv[i];
+ if (!priv)
+ continue;
+
+ if (adapter->if_ops.is_port_ready &&
+ !adapter->if_ops.is_port_ready(priv))
+ continue;
+
if (skb_queue_empty(&priv->bypass_txq))
continue;
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9420fc61c2e6..30e3aaae32e2 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -5423,7 +5423,7 @@ static int
mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
int i, rc = 0;
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index a9e94b6db5b7..0f6ea316e38e 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -220,7 +220,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
/* Set fragmentation */
if (priv->has_mwo) {
- if (wiphy->frag_threshold < 0)
+ if (wiphy->frag_threshold == -1)
frag_value = 0;
else {
printk(KERN_WARNING "%s: Fixed fragmentation "
@@ -230,7 +230,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
frag_value = 1;
}
} else {
- if (wiphy->frag_threshold < 0)
+ if (wiphy->frag_threshold == -1)
frag_value = 2346;
else if ((wiphy->frag_threshold < 257) ||
(wiphy->frag_threshold > 2347))
@@ -252,7 +252,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
* the upper limit.
*/
- if (wiphy->rts_threshold < 0)
+ if (wiphy->rts_threshold == -1)
rts_value = 2347;
else if (wiphy->rts_threshold > 2347)
err = -EINVAL;
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 26a57d773d30..f2cd513d54b2 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -1576,6 +1576,7 @@ static int ezusb_probe(struct usb_interface *interface,
ezusb_hard_reset, NULL);
if (!priv) {
err("Couldn't allocate orinocodev");
+ retval = -ENOMEM;
goto exit;
}
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 63de5eed25cf..7ab2f43ab425 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -705,7 +705,6 @@ static int p54spi_remove(struct spi_device *spi)
static struct spi_driver p54spi_driver = {
.driver = {
.name = "p54spi",
- .owner = THIS_MODULE,
},
.probe = p54spi_probe,
diff --git a/drivers/net/wireless/realtek/Makefile b/drivers/net/wireless/realtek/Makefile
new file mode 100644
index 000000000000..9c78deb5eea9
--- /dev/null
+++ b/drivers/net/wireless/realtek/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the Linux Wireless network device drivers for Realtek units
+#
+
+obj-$(CONFIG_RTL8180) += rtl818x/
+obj-$(CONFIG_RTL8187) += rtl818x/
+obj-$(CONFIG_RTLWIFI) += rtlwifi/
+obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/
+
diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/realtek/rtl818x/Kconfig
index 1ce1d55f0010..1ce1d55f0010 100644
--- a/drivers/net/wireless/rtl818x/Kconfig
+++ b/drivers/net/wireless/realtek/rtl818x/Kconfig
diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/realtek/rtl818x/Makefile
index 997569076923..997569076923 100644
--- a/drivers/net/wireless/rtl818x/Makefile
+++ b/drivers/net/wireless/realtek/rtl818x/Makefile
diff --git a/drivers/net/wireless/rtl818x/rtl8180/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile
index 21005bd8b43c..2966681efaef 100644
--- a/drivers/net/wireless/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/rtl818x
+ccflags-y += -Idrivers/net/wireless/realtek/rtl818x
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
index a43a16fde59d..a43a16fde59d 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c
index b1bfee738937..b1bfee738937 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c
diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h
index 4d80a2785123..4d80a2785123 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h
diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c
index eebf23976524..eebf23976524 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/max2820.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c
diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h
index 8e982b72b690..8e982b72b690 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/max2820.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h
index e8243a44d6b6..e8243a44d6b6 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c
index 9bda5bc78eda..9bda5bc78eda 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h
index 310013a2d726..310013a2d726 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c
index fde89866fa8d..fde89866fa8d 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h
index 229400264088..229400264088 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h
diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c
index 959b049827de..959b049827de 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c
diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h
index fb0093f35148..fb0093f35148 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h
diff --git a/drivers/net/wireless/rtl818x/rtl8187/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile
index 7b6299268ecf..ff074912a095 100644
--- a/drivers/net/wireless/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/rtl818x
+ccflags-y += -Idrivers/net/wireless/realtek/rtl818x
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
index b7f72f9c7988..b7f72f9c7988 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c
index c2d5b495c179..c2d5b495c179 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/leds.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c
diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h
index d743c96d4a20..d743c96d4a20 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/leds.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rfkill.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c
index 34116719974a..34116719974a 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rfkill.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rfkill.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h
index e12575e96d11..e12575e96d11 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rfkill.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h
index a6ad79f61bf9..a6ad79f61bf9 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
index 5ecf18ed67b8..5ecf18ed67b8 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h
index 141afb09a5b4..141afb09a5b4 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/realtek/rtl818x/rtl818x.h
index 7abef95d278b..7abef95d278b 100644
--- a/drivers/net/wireless/rtl818x/rtl818x.h
+++ b/drivers/net/wireless/realtek/rtl818x/rtl818x.h
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
new file mode 100644
index 000000000000..dd4d626aecbc
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
@@ -0,0 +1,34 @@
+#
+# RTL8XXXU Wireless LAN device configuration
+#
+config RTL8XXXU
+ tristate "RTL8723AU/RTL8188[CR]U/RTL819[12]CU (mac80211) support"
+ depends on MAC80211 && USB
+ ---help---
+ This is an alternative driver for various Realtek RTL8XXX
+ parts written to utilize the Linux mac80211 stack.
+ The driver is known to work with a number of RTL8723AU,
+ RL8188CU, RTL8188RU, RTL8191CU, and RTL8192CU devices
+
+ This driver is under development and has a limited feature
+ set. In particular it does not yet support 40MHz channels
+ and power management. However it should have a smaller
+ memory footprint than the vendor drivers and benetifs
+ from the in kernel mac80211 stack.
+
+ It can coexist with drivers from drivers/staging/rtl8723au,
+ drivers/staging/rtl8192u, and drivers/net/wireless/rtlwifi,
+ but you will need to control which module you wish to load.
+
+ To compile this driver as a module, choose M here: the module will
+ be called r8xxxu. If unsure, say N.
+
+config RTL8XXXU_UNTESTED
+ bool "Include support for untested Realtek 8xxx USB devices (EXPERIMENTAL)"
+ depends on RTL8XXXU
+ ---help---
+ This option enables detection of Realtek 8723/8188/8191/8192 WiFi
+ USB devices which have not been tested directly by the driver
+ author or reported to be working by third parties.
+
+ Please report your results!
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile
new file mode 100644
index 000000000000..5dea3bb93069
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
new file mode 100644
index 000000000000..6aed923a709a
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
@@ -0,0 +1,5993 @@
+/*
+ * RTL8XXXU mac80211 USB driver
+ *
+ * Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com>
+ *
+ * Portions, notably calibration code:
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ * This driver was written as a replacement for the vendor provided
+ * rtl8723au driver. As the Realtek 8xxx chips are very similar in
+ * their programming interface, I have started adding support for
+ * additional 8xxx chips like the 8192cu, 8188cus, etc.
+ *
+ * This program 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/moduleparam.h>
+#include <net/mac80211.h>
+#include "rtl8xxxu.h"
+#include "rtl8xxxu_regs.h"
+
+#define DRIVER_NAME "rtl8xxxu"
+
+static int rtl8xxxu_debug;
+static bool rtl8xxxu_ht40_2g;
+
+MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>");
+MODULE_DESCRIPTION("RTL8XXXu USB mac80211 Wireless LAN Driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin");
+
+module_param_named(debug, rtl8xxxu_debug, int, 0600);
+MODULE_PARM_DESC(debug, "Set debug mask");
+module_param_named(ht40_2g, rtl8xxxu_ht40_2g, bool, 0600);
+MODULE_PARM_DESC(ht40_2g, "Enable HT40 support on the 2.4GHz band");
+
+#define USB_VENDOR_ID_REALTEK 0x0bda
+/* Minimum IEEE80211_MAX_FRAME_LEN */
+#define RTL_RX_BUFFER_SIZE IEEE80211_MAX_FRAME_LEN
+#define RTL8XXXU_RX_URBS 32
+#define RTL8XXXU_RX_URB_PENDING_WATER 8
+#define RTL8XXXU_TX_URBS 64
+#define RTL8XXXU_TX_URB_LOW_WATER 25
+#define RTL8XXXU_TX_URB_HIGH_WATER 32
+
+static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_rx_urb *rx_urb);
+
+static struct ieee80211_rate rtl8xxxu_rates[] = {
+ { .bitrate = 10, .hw_value = DESC_RATE_1M, .flags = 0 },
+ { .bitrate = 20, .hw_value = DESC_RATE_2M, .flags = 0 },
+ { .bitrate = 55, .hw_value = DESC_RATE_5_5M, .flags = 0 },
+ { .bitrate = 110, .hw_value = DESC_RATE_11M, .flags = 0 },
+ { .bitrate = 60, .hw_value = DESC_RATE_6M, .flags = 0 },
+ { .bitrate = 90, .hw_value = DESC_RATE_9M, .flags = 0 },
+ { .bitrate = 120, .hw_value = DESC_RATE_12M, .flags = 0 },
+ { .bitrate = 180, .hw_value = DESC_RATE_18M, .flags = 0 },
+ { .bitrate = 240, .hw_value = DESC_RATE_24M, .flags = 0 },
+ { .bitrate = 360, .hw_value = DESC_RATE_36M, .flags = 0 },
+ { .bitrate = 480, .hw_value = DESC_RATE_48M, .flags = 0 },
+ { .bitrate = 540, .hw_value = DESC_RATE_54M, .flags = 0 },
+};
+
+static struct ieee80211_channel rtl8xxxu_channels_2g[] = {
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412,
+ .hw_value = 1, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417,
+ .hw_value = 2, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422,
+ .hw_value = 3, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427,
+ .hw_value = 4, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432,
+ .hw_value = 5, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437,
+ .hw_value = 6, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442,
+ .hw_value = 7, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447,
+ .hw_value = 8, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452,
+ .hw_value = 9, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457,
+ .hw_value = 10, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462,
+ .hw_value = 11, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467,
+ .hw_value = 12, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472,
+ .hw_value = 13, .max_power = 30 },
+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484,
+ .hw_value = 14, .max_power = 30 }
+};
+
+static struct ieee80211_supported_band rtl8xxxu_supported_band = {
+ .channels = rtl8xxxu_channels_2g,
+ .n_channels = ARRAY_SIZE(rtl8xxxu_channels_2g),
+ .bitrates = rtl8xxxu_rates,
+ .n_bitrates = ARRAY_SIZE(rtl8xxxu_rates),
+};
+
+static struct rtl8xxxu_reg8val rtl8723a_mac_init_table[] = {
+ {0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00},
+ {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05},
+ {0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00},
+ {0x43a, 0x00}, {0x43b, 0x01}, {0x43c, 0x04}, {0x43d, 0x05},
+ {0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01},
+ {0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f},
+ {0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72},
+ {0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x462, 0x08},
+ {0x463, 0x03}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff},
+ {0x4cd, 0xff}, {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2},
+ {0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3},
+ {0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4},
+ {0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4},
+ {0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a},
+ {0x515, 0x10}, {0x516, 0x0a}, {0x517, 0x10}, {0x51a, 0x16},
+ {0x524, 0x0f}, {0x525, 0x4f}, {0x546, 0x40}, {0x547, 0x00},
+ {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, {0x55a, 0x02},
+ {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a},
+ {0x652, 0x20}, {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e},
+ {0x63f, 0x0e}, {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43},
+ {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43},
+ {0x70a, 0x65}, {0x70b, 0x87}, {0xffff, 0xff},
+};
+
+static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = {
+ {0x800, 0x80040000}, {0x804, 0x00000003},
+ {0x808, 0x0000fc00}, {0x80c, 0x0000000a},
+ {0x810, 0x10001331}, {0x814, 0x020c3d10},
+ {0x818, 0x02200385}, {0x81c, 0x00000000},
+ {0x820, 0x01000100}, {0x824, 0x00390004},
+ {0x828, 0x00000000}, {0x82c, 0x00000000},
+ {0x830, 0x00000000}, {0x834, 0x00000000},
+ {0x838, 0x00000000}, {0x83c, 0x00000000},
+ {0x840, 0x00010000}, {0x844, 0x00000000},
+ {0x848, 0x00000000}, {0x84c, 0x00000000},
+ {0x850, 0x00000000}, {0x854, 0x00000000},
+ {0x858, 0x569a569a}, {0x85c, 0x001b25a4},
+ {0x860, 0x66f60110}, {0x864, 0x061f0130},
+ {0x868, 0x00000000}, {0x86c, 0x32323200},
+ {0x870, 0x07000760}, {0x874, 0x22004000},
+ {0x878, 0x00000808}, {0x87c, 0x00000000},
+ {0x880, 0xc0083070}, {0x884, 0x000004d5},
+ {0x888, 0x00000000}, {0x88c, 0xccc000c0},
+ {0x890, 0x00000800}, {0x894, 0xfffffffe},
+ {0x898, 0x40302010}, {0x89c, 0x00706050},
+ {0x900, 0x00000000}, {0x904, 0x00000023},
+ {0x908, 0x00000000}, {0x90c, 0x81121111},
+ {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c},
+ {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f},
+ {0xa10, 0x9500bb78}, {0xa14, 0x11144028},
+ {0xa18, 0x00881117}, {0xa1c, 0x89140f00},
+ {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317},
+ {0xa28, 0x00000204}, {0xa2c, 0x00d30000},
+ {0xa70, 0x101fbf00}, {0xa74, 0x00000007},
+ {0xa78, 0x00000900},
+ {0xc00, 0x48071d40}, {0xc04, 0x03a05611},
+ {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c},
+ {0xc10, 0x08800000}, {0xc14, 0x40000100},
+ {0xc18, 0x08800000}, {0xc1c, 0x40000100},
+ {0xc20, 0x00000000}, {0xc24, 0x00000000},
+ {0xc28, 0x00000000}, {0xc2c, 0x00000000},
+ {0xc30, 0x69e9ac44}, {0xc34, 0x469652af},
+ {0xc38, 0x49795994}, {0xc3c, 0x0a97971c},
+ {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7},
+ {0xc48, 0xec020107}, {0xc4c, 0x007f037f},
+ {0xc50, 0x69543420}, {0xc54, 0x43bc0094},
+ {0xc58, 0x69543420}, {0xc5c, 0x433c0094},
+ {0xc60, 0x00000000}, {0xc64, 0x7112848b},
+ {0xc68, 0x47c00bff}, {0xc6c, 0x00000036},
+ {0xc70, 0x2c7f000d}, {0xc74, 0x018610db},
+ {0xc78, 0x0000001f}, {0xc7c, 0x00b91612},
+ {0xc80, 0x40000100}, {0xc84, 0x20f60000},
+ {0xc88, 0x40000100}, {0xc8c, 0x20200000},
+ {0xc90, 0x00121820}, {0xc94, 0x00000000},
+ {0xc98, 0x00121820}, {0xc9c, 0x00007f7f},
+ {0xca0, 0x00000000}, {0xca4, 0x00000080},
+ {0xca8, 0x00000000}, {0xcac, 0x00000000},
+ {0xcb0, 0x00000000}, {0xcb4, 0x00000000},
+ {0xcb8, 0x00000000}, {0xcbc, 0x28000000},
+ {0xcc0, 0x00000000}, {0xcc4, 0x00000000},
+ {0xcc8, 0x00000000}, {0xccc, 0x00000000},
+ {0xcd0, 0x00000000}, {0xcd4, 0x00000000},
+ {0xcd8, 0x64b22427}, {0xcdc, 0x00766932},
+ {0xce0, 0x00222222}, {0xce4, 0x00000000},
+ {0xce8, 0x37644302}, {0xcec, 0x2f97d40c},
+ {0xd00, 0x00080740}, {0xd04, 0x00020401},
+ {0xd08, 0x0000907f}, {0xd0c, 0x20010201},
+ {0xd10, 0xa0633333}, {0xd14, 0x3333bc43},
+ {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975},
+ {0xd30, 0x00000000}, {0xd34, 0x80608000},
+ {0xd38, 0x00000000}, {0xd3c, 0x00027293},
+ {0xd40, 0x00000000}, {0xd44, 0x00000000},
+ {0xd48, 0x00000000}, {0xd4c, 0x00000000},
+ {0xd50, 0x6437140a}, {0xd54, 0x00000000},
+ {0xd58, 0x00000000}, {0xd5c, 0x30032064},
+ {0xd60, 0x4653de68}, {0xd64, 0x04518a3c},
+ {0xd68, 0x00002101}, {0xd6c, 0x2a201c16},
+ {0xd70, 0x1812362e}, {0xd74, 0x322c2220},
+ {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a},
+ {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a},
+ {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a},
+ {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a},
+ {0xe28, 0x00000000}, {0xe30, 0x1000dc1f},
+ {0xe34, 0x10008c1f}, {0xe38, 0x02140102},
+ {0xe3c, 0x681604c2}, {0xe40, 0x01007c00},
+ {0xe44, 0x01004800}, {0xe48, 0xfb000000},
+ {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f},
+ {0xe54, 0x10008c1f}, {0xe58, 0x02140102},
+ {0xe5c, 0x28160d05}, {0xe60, 0x00000008},
+ {0xe68, 0x001b25a4}, {0xe6c, 0x631b25a0},
+ {0xe70, 0x631b25a0}, {0xe74, 0x081b25a0},
+ {0xe78, 0x081b25a0}, {0xe7c, 0x081b25a0},
+ {0xe80, 0x081b25a0}, {0xe84, 0x631b25a0},
+ {0xe88, 0x081b25a0}, {0xe8c, 0x631b25a0},
+ {0xed0, 0x631b25a0}, {0xed4, 0x631b25a0},
+ {0xed8, 0x631b25a0}, {0xedc, 0x001b25a0},
+ {0xee0, 0x001b25a0}, {0xeec, 0x6b1b25a0},
+ {0xf14, 0x00000003}, {0xf4c, 0x00000000},
+ {0xf00, 0x00000300},
+ {0xffff, 0xffffffff},
+};
+
+static struct rtl8xxxu_reg32val rtl8192cu_phy_2t_init_table[] = {
+ {0x024, 0x0011800f}, {0x028, 0x00ffdb83},
+ {0x800, 0x80040002}, {0x804, 0x00000003},
+ {0x808, 0x0000fc00}, {0x80c, 0x0000000a},
+ {0x810, 0x10000330}, {0x814, 0x020c3d10},
+ {0x818, 0x02200385}, {0x81c, 0x00000000},
+ {0x820, 0x01000100}, {0x824, 0x00390004},
+ {0x828, 0x01000100}, {0x82c, 0x00390004},
+ {0x830, 0x27272727}, {0x834, 0x27272727},
+ {0x838, 0x27272727}, {0x83c, 0x27272727},
+ {0x840, 0x00010000}, {0x844, 0x00010000},
+ {0x848, 0x27272727}, {0x84c, 0x27272727},
+ {0x850, 0x00000000}, {0x854, 0x00000000},
+ {0x858, 0x569a569a}, {0x85c, 0x0c1b25a4},
+ {0x860, 0x66e60230}, {0x864, 0x061f0130},
+ {0x868, 0x27272727}, {0x86c, 0x2b2b2b27},
+ {0x870, 0x07000700}, {0x874, 0x22184000},
+ {0x878, 0x08080808}, {0x87c, 0x00000000},
+ {0x880, 0xc0083070}, {0x884, 0x000004d5},
+ {0x888, 0x00000000}, {0x88c, 0xcc0000c0},
+ {0x890, 0x00000800}, {0x894, 0xfffffffe},
+ {0x898, 0x40302010}, {0x89c, 0x00706050},
+ {0x900, 0x00000000}, {0x904, 0x00000023},
+ {0x908, 0x00000000}, {0x90c, 0x81121313},
+ {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c},
+ {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f},
+ {0xa10, 0x9500bb78}, {0xa14, 0x11144028},
+ {0xa18, 0x00881117}, {0xa1c, 0x89140f00},
+ {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317},
+ {0xa28, 0x00000204}, {0xa2c, 0x00d30000},
+ {0xa70, 0x101fbf00}, {0xa74, 0x00000007},
+ {0xc00, 0x48071d40}, {0xc04, 0x03a05633},
+ {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c},
+ {0xc10, 0x08800000}, {0xc14, 0x40000100},
+ {0xc18, 0x08800000}, {0xc1c, 0x40000100},
+ {0xc20, 0x00000000}, {0xc24, 0x00000000},
+ {0xc28, 0x00000000}, {0xc2c, 0x00000000},
+ {0xc30, 0x69e9ac44}, {0xc34, 0x469652cf},
+ {0xc38, 0x49795994}, {0xc3c, 0x0a97971c},
+ {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7},
+ {0xc48, 0xec020107}, {0xc4c, 0x007f037f},
+ {0xc50, 0x69543420}, {0xc54, 0x43bc0094},
+ {0xc58, 0x69543420}, {0xc5c, 0x433c0094},
+ {0xc60, 0x00000000}, {0xc64, 0x5116848b},
+ {0xc68, 0x47c00bff}, {0xc6c, 0x00000036},
+ {0xc70, 0x2c7f000d}, {0xc74, 0x2186115b},
+ {0xc78, 0x0000001f}, {0xc7c, 0x00b99612},
+ {0xc80, 0x40000100}, {0xc84, 0x20f60000},
+ {0xc88, 0x40000100}, {0xc8c, 0xa0e40000},
+ {0xc90, 0x00121820}, {0xc94, 0x00000000},
+ {0xc98, 0x00121820}, {0xc9c, 0x00007f7f},
+ {0xca0, 0x00000000}, {0xca4, 0x00000080},
+ {0xca8, 0x00000000}, {0xcac, 0x00000000},
+ {0xcb0, 0x00000000}, {0xcb4, 0x00000000},
+ {0xcb8, 0x00000000}, {0xcbc, 0x28000000},
+ {0xcc0, 0x00000000}, {0xcc4, 0x00000000},
+ {0xcc8, 0x00000000}, {0xccc, 0x00000000},
+ {0xcd0, 0x00000000}, {0xcd4, 0x00000000},
+ {0xcd8, 0x64b22427}, {0xcdc, 0x00766932},
+ {0xce0, 0x00222222}, {0xce4, 0x00000000},
+ {0xce8, 0x37644302}, {0xcec, 0x2f97d40c},
+ {0xd00, 0x00080740}, {0xd04, 0x00020403},
+ {0xd08, 0x0000907f}, {0xd0c, 0x20010201},
+ {0xd10, 0xa0633333}, {0xd14, 0x3333bc43},
+ {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975},
+ {0xd30, 0x00000000}, {0xd34, 0x80608000},
+ {0xd38, 0x00000000}, {0xd3c, 0x00027293},
+ {0xd40, 0x00000000}, {0xd44, 0x00000000},
+ {0xd48, 0x00000000}, {0xd4c, 0x00000000},
+ {0xd50, 0x6437140a}, {0xd54, 0x00000000},
+ {0xd58, 0x00000000}, {0xd5c, 0x30032064},
+ {0xd60, 0x4653de68}, {0xd64, 0x04518a3c},
+ {0xd68, 0x00002101}, {0xd6c, 0x2a201c16},
+ {0xd70, 0x1812362e}, {0xd74, 0x322c2220},
+ {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a},
+ {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a},
+ {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a},
+ {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a},
+ {0xe28, 0x00000000}, {0xe30, 0x1000dc1f},
+ {0xe34, 0x10008c1f}, {0xe38, 0x02140102},
+ {0xe3c, 0x681604c2}, {0xe40, 0x01007c00},
+ {0xe44, 0x01004800}, {0xe48, 0xfb000000},
+ {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f},
+ {0xe54, 0x10008c1f}, {0xe58, 0x02140102},
+ {0xe5c, 0x28160d05}, {0xe60, 0x00000010},
+ {0xe68, 0x001b25a4}, {0xe6c, 0x63db25a4},
+ {0xe70, 0x63db25a4}, {0xe74, 0x0c1b25a4},
+ {0xe78, 0x0c1b25a4}, {0xe7c, 0x0c1b25a4},
+ {0xe80, 0x0c1b25a4}, {0xe84, 0x63db25a4},
+ {0xe88, 0x0c1b25a4}, {0xe8c, 0x63db25a4},
+ {0xed0, 0x63db25a4}, {0xed4, 0x63db25a4},
+ {0xed8, 0x63db25a4}, {0xedc, 0x001b25a4},
+ {0xee0, 0x001b25a4}, {0xeec, 0x6fdb25a4},
+ {0xf14, 0x00000003}, {0xf4c, 0x00000000},
+ {0xf00, 0x00000300},
+ {0xffff, 0xffffffff},
+};
+
+static struct rtl8xxxu_reg32val rtl8188ru_phy_1t_highpa_table[] = {
+ {0x024, 0x0011800f}, {0x028, 0x00ffdb83},
+ {0x040, 0x000c0004}, {0x800, 0x80040000},
+ {0x804, 0x00000001}, {0x808, 0x0000fc00},
+ {0x80c, 0x0000000a}, {0x810, 0x10005388},
+ {0x814, 0x020c3d10}, {0x818, 0x02200385},
+ {0x81c, 0x00000000}, {0x820, 0x01000100},
+ {0x824, 0x00390204}, {0x828, 0x00000000},
+ {0x82c, 0x00000000}, {0x830, 0x00000000},
+ {0x834, 0x00000000}, {0x838, 0x00000000},
+ {0x83c, 0x00000000}, {0x840, 0x00010000},
+ {0x844, 0x00000000}, {0x848, 0x00000000},
+ {0x84c, 0x00000000}, {0x850, 0x00000000},
+ {0x854, 0x00000000}, {0x858, 0x569a569a},
+ {0x85c, 0x001b25a4}, {0x860, 0x66e60230},
+ {0x864, 0x061f0130}, {0x868, 0x00000000},
+ {0x86c, 0x20202000}, {0x870, 0x03000300},
+ {0x874, 0x22004000}, {0x878, 0x00000808},
+ {0x87c, 0x00ffc3f1}, {0x880, 0xc0083070},
+ {0x884, 0x000004d5}, {0x888, 0x00000000},
+ {0x88c, 0xccc000c0}, {0x890, 0x00000800},
+ {0x894, 0xfffffffe}, {0x898, 0x40302010},
+ {0x89c, 0x00706050}, {0x900, 0x00000000},
+ {0x904, 0x00000023}, {0x908, 0x00000000},
+ {0x90c, 0x81121111}, {0xa00, 0x00d047c8},
+ {0xa04, 0x80ff000c}, {0xa08, 0x8c838300},
+ {0xa0c, 0x2e68120f}, {0xa10, 0x9500bb78},
+ {0xa14, 0x11144028}, {0xa18, 0x00881117},
+ {0xa1c, 0x89140f00}, {0xa20, 0x15160000},
+ {0xa24, 0x070b0f12}, {0xa28, 0x00000104},
+ {0xa2c, 0x00d30000}, {0xa70, 0x101fbf00},
+ {0xa74, 0x00000007}, {0xc00, 0x48071d40},
+ {0xc04, 0x03a05611}, {0xc08, 0x000000e4},
+ {0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000},
+ {0xc14, 0x40000100}, {0xc18, 0x08800000},
+ {0xc1c, 0x40000100}, {0xc20, 0x00000000},
+ {0xc24, 0x00000000}, {0xc28, 0x00000000},
+ {0xc2c, 0x00000000}, {0xc30, 0x69e9ac44},
+ {0xc34, 0x469652cf}, {0xc38, 0x49795994},
+ {0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f},
+ {0xc44, 0x000100b7}, {0xc48, 0xec020107},
+ {0xc4c, 0x007f037f}, {0xc50, 0x6954342e},
+ {0xc54, 0x43bc0094}, {0xc58, 0x6954342f},
+ {0xc5c, 0x433c0094}, {0xc60, 0x00000000},
+ {0xc64, 0x5116848b}, {0xc68, 0x47c00bff},
+ {0xc6c, 0x00000036}, {0xc70, 0x2c46000d},
+ {0xc74, 0x018610db}, {0xc78, 0x0000001f},
+ {0xc7c, 0x00b91612}, {0xc80, 0x24000090},
+ {0xc84, 0x20f60000}, {0xc88, 0x24000090},
+ {0xc8c, 0x20200000}, {0xc90, 0x00121820},
+ {0xc94, 0x00000000}, {0xc98, 0x00121820},
+ {0xc9c, 0x00007f7f}, {0xca0, 0x00000000},
+ {0xca4, 0x00000080}, {0xca8, 0x00000000},
+ {0xcac, 0x00000000}, {0xcb0, 0x00000000},
+ {0xcb4, 0x00000000}, {0xcb8, 0x00000000},
+ {0xcbc, 0x28000000}, {0xcc0, 0x00000000},
+ {0xcc4, 0x00000000}, {0xcc8, 0x00000000},
+ {0xccc, 0x00000000}, {0xcd0, 0x00000000},
+ {0xcd4, 0x00000000}, {0xcd8, 0x64b22427},
+ {0xcdc, 0x00766932}, {0xce0, 0x00222222},
+ {0xce4, 0x00000000}, {0xce8, 0x37644302},
+ {0xcec, 0x2f97d40c}, {0xd00, 0x00080740},
+ {0xd04, 0x00020401}, {0xd08, 0x0000907f},
+ {0xd0c, 0x20010201}, {0xd10, 0xa0633333},
+ {0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b},
+ {0xd2c, 0xcc979975}, {0xd30, 0x00000000},
+ {0xd34, 0x80608000}, {0xd38, 0x00000000},
+ {0xd3c, 0x00027293}, {0xd40, 0x00000000},
+ {0xd44, 0x00000000}, {0xd48, 0x00000000},
+ {0xd4c, 0x00000000}, {0xd50, 0x6437140a},
+ {0xd54, 0x00000000}, {0xd58, 0x00000000},
+ {0xd5c, 0x30032064}, {0xd60, 0x4653de68},
+ {0xd64, 0x04518a3c}, {0xd68, 0x00002101},
+ {0xd6c, 0x2a201c16}, {0xd70, 0x1812362e},
+ {0xd74, 0x322c2220}, {0xd78, 0x000e3c24},
+ {0xe00, 0x24242424}, {0xe04, 0x24242424},
+ {0xe08, 0x03902024}, {0xe10, 0x24242424},
+ {0xe14, 0x24242424}, {0xe18, 0x24242424},
+ {0xe1c, 0x24242424}, {0xe28, 0x00000000},
+ {0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f},
+ {0xe38, 0x02140102}, {0xe3c, 0x681604c2},
+ {0xe40, 0x01007c00}, {0xe44, 0x01004800},
+ {0xe48, 0xfb000000}, {0xe4c, 0x000028d1},
+ {0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f},
+ {0xe58, 0x02140102}, {0xe5c, 0x28160d05},
+ {0xe60, 0x00000008}, {0xe68, 0x001b25a4},
+ {0xe6c, 0x631b25a0}, {0xe70, 0x631b25a0},
+ {0xe74, 0x081b25a0}, {0xe78, 0x081b25a0},
+ {0xe7c, 0x081b25a0}, {0xe80, 0x081b25a0},
+ {0xe84, 0x631b25a0}, {0xe88, 0x081b25a0},
+ {0xe8c, 0x631b25a0}, {0xed0, 0x631b25a0},
+ {0xed4, 0x631b25a0}, {0xed8, 0x631b25a0},
+ {0xedc, 0x001b25a0}, {0xee0, 0x001b25a0},
+ {0xeec, 0x6b1b25a0}, {0xee8, 0x31555448},
+ {0xf14, 0x00000003}, {0xf4c, 0x00000000},
+ {0xf00, 0x00000300},
+ {0xffff, 0xffffffff},
+};
+
+static struct rtl8xxxu_reg32val rtl8xxx_agc_standard_table[] = {
+ {0xc78, 0x7b000001}, {0xc78, 0x7b010001},
+ {0xc78, 0x7b020001}, {0xc78, 0x7b030001},
+ {0xc78, 0x7b040001}, {0xc78, 0x7b050001},
+ {0xc78, 0x7a060001}, {0xc78, 0x79070001},
+ {0xc78, 0x78080001}, {0xc78, 0x77090001},
+ {0xc78, 0x760a0001}, {0xc78, 0x750b0001},
+ {0xc78, 0x740c0001}, {0xc78, 0x730d0001},
+ {0xc78, 0x720e0001}, {0xc78, 0x710f0001},
+ {0xc78, 0x70100001}, {0xc78, 0x6f110001},
+ {0xc78, 0x6e120001}, {0xc78, 0x6d130001},
+ {0xc78, 0x6c140001}, {0xc78, 0x6b150001},
+ {0xc78, 0x6a160001}, {0xc78, 0x69170001},
+ {0xc78, 0x68180001}, {0xc78, 0x67190001},
+ {0xc78, 0x661a0001}, {0xc78, 0x651b0001},
+ {0xc78, 0x641c0001}, {0xc78, 0x631d0001},
+ {0xc78, 0x621e0001}, {0xc78, 0x611f0001},
+ {0xc78, 0x60200001}, {0xc78, 0x49210001},
+ {0xc78, 0x48220001}, {0xc78, 0x47230001},
+ {0xc78, 0x46240001}, {0xc78, 0x45250001},
+ {0xc78, 0x44260001}, {0xc78, 0x43270001},
+ {0xc78, 0x42280001}, {0xc78, 0x41290001},
+ {0xc78, 0x402a0001}, {0xc78, 0x262b0001},
+ {0xc78, 0x252c0001}, {0xc78, 0x242d0001},
+ {0xc78, 0x232e0001}, {0xc78, 0x222f0001},
+ {0xc78, 0x21300001}, {0xc78, 0x20310001},
+ {0xc78, 0x06320001}, {0xc78, 0x05330001},
+ {0xc78, 0x04340001}, {0xc78, 0x03350001},
+ {0xc78, 0x02360001}, {0xc78, 0x01370001},
+ {0xc78, 0x00380001}, {0xc78, 0x00390001},
+ {0xc78, 0x003a0001}, {0xc78, 0x003b0001},
+ {0xc78, 0x003c0001}, {0xc78, 0x003d0001},
+ {0xc78, 0x003e0001}, {0xc78, 0x003f0001},
+ {0xc78, 0x7b400001}, {0xc78, 0x7b410001},
+ {0xc78, 0x7b420001}, {0xc78, 0x7b430001},
+ {0xc78, 0x7b440001}, {0xc78, 0x7b450001},
+ {0xc78, 0x7a460001}, {0xc78, 0x79470001},
+ {0xc78, 0x78480001}, {0xc78, 0x77490001},
+ {0xc78, 0x764a0001}, {0xc78, 0x754b0001},
+ {0xc78, 0x744c0001}, {0xc78, 0x734d0001},
+ {0xc78, 0x724e0001}, {0xc78, 0x714f0001},
+ {0xc78, 0x70500001}, {0xc78, 0x6f510001},
+ {0xc78, 0x6e520001}, {0xc78, 0x6d530001},
+ {0xc78, 0x6c540001}, {0xc78, 0x6b550001},
+ {0xc78, 0x6a560001}, {0xc78, 0x69570001},
+ {0xc78, 0x68580001}, {0xc78, 0x67590001},
+ {0xc78, 0x665a0001}, {0xc78, 0x655b0001},
+ {0xc78, 0x645c0001}, {0xc78, 0x635d0001},
+ {0xc78, 0x625e0001}, {0xc78, 0x615f0001},
+ {0xc78, 0x60600001}, {0xc78, 0x49610001},
+ {0xc78, 0x48620001}, {0xc78, 0x47630001},
+ {0xc78, 0x46640001}, {0xc78, 0x45650001},
+ {0xc78, 0x44660001}, {0xc78, 0x43670001},
+ {0xc78, 0x42680001}, {0xc78, 0x41690001},
+ {0xc78, 0x406a0001}, {0xc78, 0x266b0001},
+ {0xc78, 0x256c0001}, {0xc78, 0x246d0001},
+ {0xc78, 0x236e0001}, {0xc78, 0x226f0001},
+ {0xc78, 0x21700001}, {0xc78, 0x20710001},
+ {0xc78, 0x06720001}, {0xc78, 0x05730001},
+ {0xc78, 0x04740001}, {0xc78, 0x03750001},
+ {0xc78, 0x02760001}, {0xc78, 0x01770001},
+ {0xc78, 0x00780001}, {0xc78, 0x00790001},
+ {0xc78, 0x007a0001}, {0xc78, 0x007b0001},
+ {0xc78, 0x007c0001}, {0xc78, 0x007d0001},
+ {0xc78, 0x007e0001}, {0xc78, 0x007f0001},
+ {0xc78, 0x3800001e}, {0xc78, 0x3801001e},
+ {0xc78, 0x3802001e}, {0xc78, 0x3803001e},
+ {0xc78, 0x3804001e}, {0xc78, 0x3805001e},
+ {0xc78, 0x3806001e}, {0xc78, 0x3807001e},
+ {0xc78, 0x3808001e}, {0xc78, 0x3c09001e},
+ {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e},
+ {0xc78, 0x440c001e}, {0xc78, 0x480d001e},
+ {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e},
+ {0xc78, 0x5210001e}, {0xc78, 0x5611001e},
+ {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e},
+ {0xc78, 0x6014001e}, {0xc78, 0x6015001e},
+ {0xc78, 0x6016001e}, {0xc78, 0x6217001e},
+ {0xc78, 0x6218001e}, {0xc78, 0x6219001e},
+ {0xc78, 0x621a001e}, {0xc78, 0x621b001e},
+ {0xc78, 0x621c001e}, {0xc78, 0x621d001e},
+ {0xc78, 0x621e001e}, {0xc78, 0x621f001e},
+ {0xffff, 0xffffffff}
+};
+
+static struct rtl8xxxu_reg32val rtl8xxx_agc_highpa_table[] = {
+ {0xc78, 0x7b000001}, {0xc78, 0x7b010001},
+ {0xc78, 0x7b020001}, {0xc78, 0x7b030001},
+ {0xc78, 0x7b040001}, {0xc78, 0x7b050001},
+ {0xc78, 0x7b060001}, {0xc78, 0x7b070001},
+ {0xc78, 0x7b080001}, {0xc78, 0x7a090001},
+ {0xc78, 0x790a0001}, {0xc78, 0x780b0001},
+ {0xc78, 0x770c0001}, {0xc78, 0x760d0001},
+ {0xc78, 0x750e0001}, {0xc78, 0x740f0001},
+ {0xc78, 0x73100001}, {0xc78, 0x72110001},
+ {0xc78, 0x71120001}, {0xc78, 0x70130001},
+ {0xc78, 0x6f140001}, {0xc78, 0x6e150001},
+ {0xc78, 0x6d160001}, {0xc78, 0x6c170001},
+ {0xc78, 0x6b180001}, {0xc78, 0x6a190001},
+ {0xc78, 0x691a0001}, {0xc78, 0x681b0001},
+ {0xc78, 0x671c0001}, {0xc78, 0x661d0001},
+ {0xc78, 0x651e0001}, {0xc78, 0x641f0001},
+ {0xc78, 0x63200001}, {0xc78, 0x62210001},
+ {0xc78, 0x61220001}, {0xc78, 0x60230001},
+ {0xc78, 0x46240001}, {0xc78, 0x45250001},
+ {0xc78, 0x44260001}, {0xc78, 0x43270001},
+ {0xc78, 0x42280001}, {0xc78, 0x41290001},
+ {0xc78, 0x402a0001}, {0xc78, 0x262b0001},
+ {0xc78, 0x252c0001}, {0xc78, 0x242d0001},
+ {0xc78, 0x232e0001}, {0xc78, 0x222f0001},
+ {0xc78, 0x21300001}, {0xc78, 0x20310001},
+ {0xc78, 0x06320001}, {0xc78, 0x05330001},
+ {0xc78, 0x04340001}, {0xc78, 0x03350001},
+ {0xc78, 0x02360001}, {0xc78, 0x01370001},
+ {0xc78, 0x00380001}, {0xc78, 0x00390001},
+ {0xc78, 0x003a0001}, {0xc78, 0x003b0001},
+ {0xc78, 0x003c0001}, {0xc78, 0x003d0001},
+ {0xc78, 0x003e0001}, {0xc78, 0x003f0001},
+ {0xc78, 0x7b400001}, {0xc78, 0x7b410001},
+ {0xc78, 0x7b420001}, {0xc78, 0x7b430001},
+ {0xc78, 0x7b440001}, {0xc78, 0x7b450001},
+ {0xc78, 0x7b460001}, {0xc78, 0x7b470001},
+ {0xc78, 0x7b480001}, {0xc78, 0x7a490001},
+ {0xc78, 0x794a0001}, {0xc78, 0x784b0001},
+ {0xc78, 0x774c0001}, {0xc78, 0x764d0001},
+ {0xc78, 0x754e0001}, {0xc78, 0x744f0001},
+ {0xc78, 0x73500001}, {0xc78, 0x72510001},
+ {0xc78, 0x71520001}, {0xc78, 0x70530001},
+ {0xc78, 0x6f540001}, {0xc78, 0x6e550001},
+ {0xc78, 0x6d560001}, {0xc78, 0x6c570001},
+ {0xc78, 0x6b580001}, {0xc78, 0x6a590001},
+ {0xc78, 0x695a0001}, {0xc78, 0x685b0001},
+ {0xc78, 0x675c0001}, {0xc78, 0x665d0001},
+ {0xc78, 0x655e0001}, {0xc78, 0x645f0001},
+ {0xc78, 0x63600001}, {0xc78, 0x62610001},
+ {0xc78, 0x61620001}, {0xc78, 0x60630001},
+ {0xc78, 0x46640001}, {0xc78, 0x45650001},
+ {0xc78, 0x44660001}, {0xc78, 0x43670001},
+ {0xc78, 0x42680001}, {0xc78, 0x41690001},
+ {0xc78, 0x406a0001}, {0xc78, 0x266b0001},
+ {0xc78, 0x256c0001}, {0xc78, 0x246d0001},
+ {0xc78, 0x236e0001}, {0xc78, 0x226f0001},
+ {0xc78, 0x21700001}, {0xc78, 0x20710001},
+ {0xc78, 0x06720001}, {0xc78, 0x05730001},
+ {0xc78, 0x04740001}, {0xc78, 0x03750001},
+ {0xc78, 0x02760001}, {0xc78, 0x01770001},
+ {0xc78, 0x00780001}, {0xc78, 0x00790001},
+ {0xc78, 0x007a0001}, {0xc78, 0x007b0001},
+ {0xc78, 0x007c0001}, {0xc78, 0x007d0001},
+ {0xc78, 0x007e0001}, {0xc78, 0x007f0001},
+ {0xc78, 0x3800001e}, {0xc78, 0x3801001e},
+ {0xc78, 0x3802001e}, {0xc78, 0x3803001e},
+ {0xc78, 0x3804001e}, {0xc78, 0x3805001e},
+ {0xc78, 0x3806001e}, {0xc78, 0x3807001e},
+ {0xc78, 0x3808001e}, {0xc78, 0x3c09001e},
+ {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e},
+ {0xc78, 0x440c001e}, {0xc78, 0x480d001e},
+ {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e},
+ {0xc78, 0x5210001e}, {0xc78, 0x5611001e},
+ {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e},
+ {0xc78, 0x6014001e}, {0xc78, 0x6015001e},
+ {0xc78, 0x6016001e}, {0xc78, 0x6217001e},
+ {0xc78, 0x6218001e}, {0xc78, 0x6219001e},
+ {0xc78, 0x621a001e}, {0xc78, 0x621b001e},
+ {0xc78, 0x621c001e}, {0xc78, 0x621d001e},
+ {0xc78, 0x621e001e}, {0xc78, 0x621f001e},
+ {0xffff, 0xffffffff}
+};
+
+static struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = {
+ {0x00, 0x00030159}, {0x01, 0x00031284},
+ {0x02, 0x00098000}, {0x03, 0x00039c63},
+ {0x04, 0x000210e7}, {0x09, 0x0002044f},
+ {0x0a, 0x0001a3f1}, {0x0b, 0x00014787},
+ {0x0c, 0x000896fe}, {0x0d, 0x0000e02c},
+ {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
+ {0x19, 0x00000000}, {0x1a, 0x00030355},
+ {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
+ {0x1d, 0x000a1250}, {0x1e, 0x0000024f},
+ {0x1f, 0x00000000}, {0x20, 0x0000b614},
+ {0x21, 0x0006c000}, {0x22, 0x00000000},
+ {0x23, 0x00001558}, {0x24, 0x00000060},
+ {0x25, 0x00000483}, {0x26, 0x0004f000},
+ {0x27, 0x000ec7d9}, {0x28, 0x00057730},
+ {0x29, 0x00004783}, {0x2a, 0x00000001},
+ {0x2b, 0x00021334}, {0x2a, 0x00000000},
+ {0x2b, 0x00000054}, {0x2a, 0x00000001},
+ {0x2b, 0x00000808}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000c}, {0x2a, 0x00000002},
+ {0x2b, 0x00000808}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000003},
+ {0x2b, 0x00000808}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000004},
+ {0x2b, 0x00000808}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000005},
+ {0x2b, 0x00000808}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000006},
+ {0x2b, 0x00000709}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000007},
+ {0x2b, 0x00000709}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000008},
+ {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000009},
+ {0x2b, 0x0000060a}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
+ {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
+ {0x2b, 0x0000060a}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
+ {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
+ {0x2b, 0x0000060a}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
+ {0x2b, 0x0000050b}, {0x2b, 0x00066666},
+ {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
+ {0x10, 0x0004000f}, {0x11, 0x000e31fc},
+ {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
+ {0x10, 0x0002000f}, {0x11, 0x000203f9},
+ {0x10, 0x0003000f}, {0x11, 0x000ff500},
+ {0x10, 0x00000000}, {0x11, 0x00000000},
+ {0x10, 0x0008000f}, {0x11, 0x0003f100},
+ {0x10, 0x0009000f}, {0x11, 0x00023100},
+ {0x12, 0x00032000}, {0x12, 0x00071000},
+ {0x12, 0x000b0000}, {0x12, 0x000fc000},
+ {0x13, 0x000287b3}, {0x13, 0x000244b7},
+ {0x13, 0x000204ab}, {0x13, 0x0001c49f},
+ {0x13, 0x00018493}, {0x13, 0x0001429b},
+ {0x13, 0x00010299}, {0x13, 0x0000c29c},
+ {0x13, 0x000081a0}, {0x13, 0x000040ac},
+ {0x13, 0x00000020}, {0x14, 0x0001944c},
+ {0x14, 0x00059444}, {0x14, 0x0009944c},
+ {0x14, 0x000d9444}, {0x15, 0x0000f474},
+ {0x15, 0x0004f477}, {0x15, 0x0008f455},
+ {0x15, 0x000cf455}, {0x16, 0x00000339},
+ {0x16, 0x00040339}, {0x16, 0x00080339},
+ {0x16, 0x000c0366}, {0x00, 0x00010159},
+ {0x18, 0x0000f401}, {0xfe, 0x00000000},
+ {0xfe, 0x00000000}, {0x1f, 0x00000003},
+ {0xfe, 0x00000000}, {0xfe, 0x00000000},
+ {0x1e, 0x00000247}, {0x1f, 0x00000000},
+ {0x00, 0x00030159},
+ {0xff, 0xffffffff}
+};
+
+static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = {
+ {0x00, 0x00030159}, {0x01, 0x00031284},
+ {0x02, 0x00098000}, {0x03, 0x00018c63},
+ {0x04, 0x000210e7}, {0x09, 0x0002044f},
+ {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
+ {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
+ {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
+ {0x19, 0x00000000}, {0x1a, 0x00010255},
+ {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
+ {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
+ {0x1f, 0x00080001}, {0x20, 0x0000b614},
+ {0x21, 0x0006c000}, {0x22, 0x00000000},
+ {0x23, 0x00001558}, {0x24, 0x00000060},
+ {0x25, 0x00000483}, {0x26, 0x0004f000},
+ {0x27, 0x000ec7d9}, {0x28, 0x000577c0},
+ {0x29, 0x00004783}, {0x2a, 0x00000001},
+ {0x2b, 0x00021334}, {0x2a, 0x00000000},
+ {0x2b, 0x00000054}, {0x2a, 0x00000001},
+ {0x2b, 0x00000808}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000c}, {0x2a, 0x00000002},
+ {0x2b, 0x00000808}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000003},
+ {0x2b, 0x00000808}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000004},
+ {0x2b, 0x00000808}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000005},
+ {0x2b, 0x00000808}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000006},
+ {0x2b, 0x00000709}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000007},
+ {0x2b, 0x00000709}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000008},
+ {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000009},
+ {0x2b, 0x0000060a}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
+ {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
+ {0x2b, 0x0000060a}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
+ {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
+ {0x2b, 0x0000060a}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
+ {0x2b, 0x0000050b}, {0x2b, 0x00066666},
+ {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
+ {0x10, 0x0004000f}, {0x11, 0x000e31fc},
+ {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
+ {0x10, 0x0002000f}, {0x11, 0x000203f9},
+ {0x10, 0x0003000f}, {0x11, 0x000ff500},
+ {0x10, 0x00000000}, {0x11, 0x00000000},
+ {0x10, 0x0008000f}, {0x11, 0x0003f100},
+ {0x10, 0x0009000f}, {0x11, 0x00023100},
+ {0x12, 0x00032000}, {0x12, 0x00071000},
+ {0x12, 0x000b0000}, {0x12, 0x000fc000},
+ {0x13, 0x000287b3}, {0x13, 0x000244b7},
+ {0x13, 0x000204ab}, {0x13, 0x0001c49f},
+ {0x13, 0x00018493}, {0x13, 0x0001429b},
+ {0x13, 0x00010299}, {0x13, 0x0000c29c},
+ {0x13, 0x000081a0}, {0x13, 0x000040ac},
+ {0x13, 0x00000020}, {0x14, 0x0001944c},
+ {0x14, 0x00059444}, {0x14, 0x0009944c},
+ {0x14, 0x000d9444}, {0x15, 0x0000f424},
+ {0x15, 0x0004f424}, {0x15, 0x0008f424},
+ {0x15, 0x000cf424}, {0x16, 0x000e0330},
+ {0x16, 0x000a0330}, {0x16, 0x00060330},
+ {0x16, 0x00020330}, {0x00, 0x00010159},
+ {0x18, 0x0000f401}, {0xfe, 0x00000000},
+ {0xfe, 0x00000000}, {0x1f, 0x00080003},
+ {0xfe, 0x00000000}, {0xfe, 0x00000000},
+ {0x1e, 0x00044457}, {0x1f, 0x00080000},
+ {0x00, 0x00030159},
+ {0xff, 0xffffffff}
+};
+
+static struct rtl8xxxu_rfregval rtl8192cu_radiob_2t_init_table[] = {
+ {0x00, 0x00030159}, {0x01, 0x00031284},
+ {0x02, 0x00098000}, {0x03, 0x00018c63},
+ {0x04, 0x000210e7}, {0x09, 0x0002044f},
+ {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
+ {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
+ {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
+ {0x12, 0x00032000}, {0x12, 0x00071000},
+ {0x12, 0x000b0000}, {0x12, 0x000fc000},
+ {0x13, 0x000287af}, {0x13, 0x000244b7},
+ {0x13, 0x000204ab}, {0x13, 0x0001c49f},
+ {0x13, 0x00018493}, {0x13, 0x00014297},
+ {0x13, 0x00010295}, {0x13, 0x0000c298},
+ {0x13, 0x0000819c}, {0x13, 0x000040a8},
+ {0x13, 0x0000001c}, {0x14, 0x0001944c},
+ {0x14, 0x00059444}, {0x14, 0x0009944c},
+ {0x14, 0x000d9444}, {0x15, 0x0000f424},
+ {0x15, 0x0004f424}, {0x15, 0x0008f424},
+ {0x15, 0x000cf424}, {0x16, 0x000e0330},
+ {0x16, 0x000a0330}, {0x16, 0x00060330},
+ {0x16, 0x00020330},
+ {0xff, 0xffffffff}
+};
+
+static struct rtl8xxxu_rfregval rtl8192cu_radioa_1t_init_table[] = {
+ {0x00, 0x00030159}, {0x01, 0x00031284},
+ {0x02, 0x00098000}, {0x03, 0x00018c63},
+ {0x04, 0x000210e7}, {0x09, 0x0002044f},
+ {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
+ {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
+ {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
+ {0x19, 0x00000000}, {0x1a, 0x00010255},
+ {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
+ {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
+ {0x1f, 0x00080001}, {0x20, 0x0000b614},
+ {0x21, 0x0006c000}, {0x22, 0x00000000},
+ {0x23, 0x00001558}, {0x24, 0x00000060},
+ {0x25, 0x00000483}, {0x26, 0x0004f000},
+ {0x27, 0x000ec7d9}, {0x28, 0x000577c0},
+ {0x29, 0x00004783}, {0x2a, 0x00000001},
+ {0x2b, 0x00021334}, {0x2a, 0x00000000},
+ {0x2b, 0x00000054}, {0x2a, 0x00000001},
+ {0x2b, 0x00000808}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000c}, {0x2a, 0x00000002},
+ {0x2b, 0x00000808}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000003},
+ {0x2b, 0x00000808}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000004},
+ {0x2b, 0x00000808}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000005},
+ {0x2b, 0x00000808}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000006},
+ {0x2b, 0x00000709}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000007},
+ {0x2b, 0x00000709}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000008},
+ {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000009},
+ {0x2b, 0x0000060a}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
+ {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
+ {0x2b, 0x0000060a}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
+ {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
+ {0x2b, 0x0000060a}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
+ {0x2b, 0x0000050b}, {0x2b, 0x00066666},
+ {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
+ {0x10, 0x0004000f}, {0x11, 0x000e31fc},
+ {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
+ {0x10, 0x0002000f}, {0x11, 0x000203f9},
+ {0x10, 0x0003000f}, {0x11, 0x000ff500},
+ {0x10, 0x00000000}, {0x11, 0x00000000},
+ {0x10, 0x0008000f}, {0x11, 0x0003f100},
+ {0x10, 0x0009000f}, {0x11, 0x00023100},
+ {0x12, 0x00032000}, {0x12, 0x00071000},
+ {0x12, 0x000b0000}, {0x12, 0x000fc000},
+ {0x13, 0x000287b3}, {0x13, 0x000244b7},
+ {0x13, 0x000204ab}, {0x13, 0x0001c49f},
+ {0x13, 0x00018493}, {0x13, 0x0001429b},
+ {0x13, 0x00010299}, {0x13, 0x0000c29c},
+ {0x13, 0x000081a0}, {0x13, 0x000040ac},
+ {0x13, 0x00000020}, {0x14, 0x0001944c},
+ {0x14, 0x00059444}, {0x14, 0x0009944c},
+ {0x14, 0x000d9444}, {0x15, 0x0000f405},
+ {0x15, 0x0004f405}, {0x15, 0x0008f405},
+ {0x15, 0x000cf405}, {0x16, 0x000e0330},
+ {0x16, 0x000a0330}, {0x16, 0x00060330},
+ {0x16, 0x00020330}, {0x00, 0x00010159},
+ {0x18, 0x0000f401}, {0xfe, 0x00000000},
+ {0xfe, 0x00000000}, {0x1f, 0x00080003},
+ {0xfe, 0x00000000}, {0xfe, 0x00000000},
+ {0x1e, 0x00044457}, {0x1f, 0x00080000},
+ {0x00, 0x00030159},
+ {0xff, 0xffffffff}
+};
+
+static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = {
+ {0x00, 0x00030159}, {0x01, 0x00031284},
+ {0x02, 0x00098000}, {0x03, 0x00018c63},
+ {0x04, 0x000210e7}, {0x09, 0x0002044f},
+ {0x0a, 0x0001adb0}, {0x0b, 0x00054867},
+ {0x0c, 0x0008992e}, {0x0d, 0x0000e529},
+ {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
+ {0x19, 0x00000000}, {0x1a, 0x00000255},
+ {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
+ {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
+ {0x1f, 0x00080001}, {0x20, 0x0000b614},
+ {0x21, 0x0006c000}, {0x22, 0x0000083c},
+ {0x23, 0x00001558}, {0x24, 0x00000060},
+ {0x25, 0x00000483}, {0x26, 0x0004f000},
+ {0x27, 0x000ec7d9}, {0x28, 0x000977c0},
+ {0x29, 0x00004783}, {0x2a, 0x00000001},
+ {0x2b, 0x00021334}, {0x2a, 0x00000000},
+ {0x2b, 0x00000054}, {0x2a, 0x00000001},
+ {0x2b, 0x00000808}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000c}, {0x2a, 0x00000002},
+ {0x2b, 0x00000808}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000003},
+ {0x2b, 0x00000808}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000004},
+ {0x2b, 0x00000808}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000005},
+ {0x2b, 0x00000808}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000006},
+ {0x2b, 0x00000709}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000007},
+ {0x2b, 0x00000709}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000008},
+ {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x00000009},
+ {0x2b, 0x0000060a}, {0x2b, 0x00053333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
+ {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
+ {0x2b, 0x0000060a}, {0x2b, 0x00063333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
+ {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
+ {0x2b, 0x0000060a}, {0x2b, 0x00073333},
+ {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
+ {0x2b, 0x0000050b}, {0x2b, 0x00066666},
+ {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
+ {0x10, 0x0004000f}, {0x11, 0x000e31fc},
+ {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
+ {0x10, 0x0002000f}, {0x11, 0x000203f9},
+ {0x10, 0x0003000f}, {0x11, 0x000ff500},
+ {0x10, 0x00000000}, {0x11, 0x00000000},
+ {0x10, 0x0008000f}, {0x11, 0x0003f100},
+ {0x10, 0x0009000f}, {0x11, 0x00023100},
+ {0x12, 0x000d8000}, {0x12, 0x00090000},
+ {0x12, 0x00051000}, {0x12, 0x00012000},
+ {0x13, 0x00028fb4}, {0x13, 0x00024fa8},
+ {0x13, 0x000207a4}, {0x13, 0x0001c3b0},
+ {0x13, 0x000183a4}, {0x13, 0x00014398},
+ {0x13, 0x000101a4}, {0x13, 0x0000c198},
+ {0x13, 0x000080a4}, {0x13, 0x00004098},
+ {0x13, 0x00000000}, {0x14, 0x0001944c},
+ {0x14, 0x00059444}, {0x14, 0x0009944c},
+ {0x14, 0x000d9444}, {0x15, 0x0000f405},
+ {0x15, 0x0004f405}, {0x15, 0x0008f405},
+ {0x15, 0x000cf405}, {0x16, 0x000e0330},
+ {0x16, 0x000a0330}, {0x16, 0x00060330},
+ {0x16, 0x00020330}, {0x00, 0x00010159},
+ {0x18, 0x0000f401}, {0xfe, 0x00000000},
+ {0xfe, 0x00000000}, {0x1f, 0x00080003},
+ {0xfe, 0x00000000}, {0xfe, 0x00000000},
+ {0x1e, 0x00044457}, {0x1f, 0x00080000},
+ {0x00, 0x00030159},
+ {0xff, 0xffffffff}
+};
+
+static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = {
+ { /* RF_A */
+ .hssiparm1 = REG_FPGA0_XA_HSSI_PARM1,
+ .hssiparm2 = REG_FPGA0_XA_HSSI_PARM2,
+ .lssiparm = REG_FPGA0_XA_LSSI_PARM,
+ .hspiread = REG_HSPI_XA_READBACK,
+ .lssiread = REG_FPGA0_XA_LSSI_READBACK,
+ .rf_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL,
+ },
+ { /* RF_B */
+ .hssiparm1 = REG_FPGA0_XB_HSSI_PARM1,
+ .hssiparm2 = REG_FPGA0_XB_HSSI_PARM2,
+ .lssiparm = REG_FPGA0_XB_LSSI_PARM,
+ .hspiread = REG_HSPI_XB_READBACK,
+ .lssiread = REG_FPGA0_XB_LSSI_READBACK,
+ .rf_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL,
+ },
+};
+
+static const u32 rtl8723au_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = {
+ REG_OFDM0_XA_RX_IQ_IMBALANCE,
+ REG_OFDM0_XB_RX_IQ_IMBALANCE,
+ REG_OFDM0_ENERGY_CCA_THRES,
+ REG_OFDM0_AGCR_SSI_TABLE,
+ REG_OFDM0_XA_TX_IQ_IMBALANCE,
+ REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ REG_OFDM0_XC_TX_AFE,
+ REG_OFDM0_XD_TX_AFE,
+ REG_OFDM0_RX_IQ_EXT_ANTA
+};
+
+static u8 rtl8xxxu_read8(struct rtl8xxxu_priv *priv, u16 addr)
+{
+ struct usb_device *udev = priv->udev;
+ int len;
+ u8 data;
+
+ mutex_lock(&priv->usb_buf_mutex);
+ len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_READ,
+ addr, 0, &priv->usb_buf.val8, sizeof(u8),
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ data = priv->usb_buf.val8;
+ mutex_unlock(&priv->usb_buf_mutex);
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ)
+ dev_info(&udev->dev, "%s(%04x) = 0x%02x, len %i\n",
+ __func__, addr, data, len);
+ return data;
+}
+
+static u16 rtl8xxxu_read16(struct rtl8xxxu_priv *priv, u16 addr)
+{
+ struct usb_device *udev = priv->udev;
+ int len;
+ u16 data;
+
+ mutex_lock(&priv->usb_buf_mutex);
+ len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_READ,
+ addr, 0, &priv->usb_buf.val16, sizeof(u16),
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ data = le16_to_cpu(priv->usb_buf.val16);
+ mutex_unlock(&priv->usb_buf_mutex);
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ)
+ dev_info(&udev->dev, "%s(%04x) = 0x%04x, len %i\n",
+ __func__, addr, data, len);
+ return data;
+}
+
+static u32 rtl8xxxu_read32(struct rtl8xxxu_priv *priv, u16 addr)
+{
+ struct usb_device *udev = priv->udev;
+ int len;
+ u32 data;
+
+ mutex_lock(&priv->usb_buf_mutex);
+ len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_READ,
+ addr, 0, &priv->usb_buf.val32, sizeof(u32),
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ data = le32_to_cpu(priv->usb_buf.val32);
+ mutex_unlock(&priv->usb_buf_mutex);
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ)
+ dev_info(&udev->dev, "%s(%04x) = 0x%08x, len %i\n",
+ __func__, addr, data, len);
+ return data;
+}
+
+static int rtl8xxxu_write8(struct rtl8xxxu_priv *priv, u16 addr, u8 val)
+{
+ struct usb_device *udev = priv->udev;
+ int ret;
+
+ mutex_lock(&priv->usb_buf_mutex);
+ priv->usb_buf.val8 = val;
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE,
+ addr, 0, &priv->usb_buf.val8, sizeof(u8),
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+
+ mutex_unlock(&priv->usb_buf_mutex);
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE)
+ dev_info(&udev->dev, "%s(%04x) = 0x%02x\n",
+ __func__, addr, val);
+ return ret;
+}
+
+static int rtl8xxxu_write16(struct rtl8xxxu_priv *priv, u16 addr, u16 val)
+{
+ struct usb_device *udev = priv->udev;
+ int ret;
+
+ mutex_lock(&priv->usb_buf_mutex);
+ priv->usb_buf.val16 = cpu_to_le16(val);
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE,
+ addr, 0, &priv->usb_buf.val16, sizeof(u16),
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ mutex_unlock(&priv->usb_buf_mutex);
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE)
+ dev_info(&udev->dev, "%s(%04x) = 0x%04x\n",
+ __func__, addr, val);
+ return ret;
+}
+
+static int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val)
+{
+ struct usb_device *udev = priv->udev;
+ int ret;
+
+ mutex_lock(&priv->usb_buf_mutex);
+ priv->usb_buf.val32 = cpu_to_le32(val);
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE,
+ addr, 0, &priv->usb_buf.val32, sizeof(u32),
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ mutex_unlock(&priv->usb_buf_mutex);
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE)
+ dev_info(&udev->dev, "%s(%04x) = 0x%08x\n",
+ __func__, addr, val);
+ return ret;
+}
+
+static int
+rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len)
+{
+ struct usb_device *udev = priv->udev;
+ int blocksize = priv->fops->writeN_block_size;
+ int ret, i, count, remainder;
+
+ count = len / blocksize;
+ remainder = len % blocksize;
+
+ for (i = 0; i < count; i++) {
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE,
+ addr, 0, buf, blocksize,
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ if (ret != blocksize)
+ goto write_error;
+
+ addr += blocksize;
+ buf += blocksize;
+ }
+
+ if (remainder) {
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE,
+ addr, 0, buf, remainder,
+ RTW_USB_CONTROL_MSG_TIMEOUT);
+ if (ret != remainder)
+ goto write_error;
+ }
+
+ return len;
+
+write_error:
+ dev_info(&udev->dev,
+ "%s: Failed to write block at addr: %04x size: %04x\n",
+ __func__, addr, blocksize);
+ return -EAGAIN;
+}
+
+static u32 rtl8xxxu_read_rfreg(struct rtl8xxxu_priv *priv,
+ enum rtl8xxxu_rfpath path, u8 reg)
+{
+ u32 hssia, val32, retval;
+
+ hssia = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2);
+ if (path != RF_A)
+ val32 = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hssiparm2);
+ else
+ val32 = hssia;
+
+ val32 &= ~FPGA0_HSSI_PARM2_ADDR_MASK;
+ val32 |= (reg << FPGA0_HSSI_PARM2_ADDR_SHIFT);
+ val32 |= FPGA0_HSSI_PARM2_EDGE_READ;
+ hssia &= ~FPGA0_HSSI_PARM2_EDGE_READ;
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, hssia);
+
+ udelay(10);
+
+ rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].hssiparm2, val32);
+ udelay(100);
+
+ hssia |= FPGA0_HSSI_PARM2_EDGE_READ;
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, hssia);
+ udelay(10);
+
+ val32 = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hssiparm1);
+ if (val32 & FPGA0_HSSI_PARM1_PI)
+ retval = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hspiread);
+ else
+ retval = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].lssiread);
+
+ retval &= 0xfffff;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_READ)
+ dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n",
+ __func__, reg, retval);
+ return retval;
+}
+
+static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv,
+ enum rtl8xxxu_rfpath path, u8 reg, u32 data)
+{
+ int ret, retval;
+ u32 dataaddr;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_WRITE)
+ dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n",
+ __func__, reg, data);
+
+ data &= FPGA0_LSSI_PARM_DATA_MASK;
+ dataaddr = (reg << FPGA0_LSSI_PARM_ADDR_SHIFT) | data;
+
+ /* Use XB for path B */
+ ret = rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].lssiparm, dataaddr);
+ if (ret != sizeof(dataaddr))
+ retval = -EIO;
+ else
+ retval = 0;
+
+ udelay(1);
+
+ return retval;
+}
+
+static int rtl8723a_h2c_cmd(struct rtl8xxxu_priv *priv, struct h2c_cmd *h2c)
+{
+ struct device *dev = &priv->udev->dev;
+ int mbox_nr, retry, retval = 0;
+ int mbox_reg, mbox_ext_reg;
+ u8 val8;
+
+ mutex_lock(&priv->h2c_mutex);
+
+ mbox_nr = priv->next_mbox;
+ mbox_reg = REG_HMBOX_0 + (mbox_nr * 4);
+ mbox_ext_reg = REG_HMBOX_EXT_0 + (mbox_nr * 2);
+
+ /*
+ * MBOX ready?
+ */
+ retry = 100;
+ do {
+ val8 = rtl8xxxu_read8(priv, REG_HMTFR);
+ if (!(val8 & BIT(mbox_nr)))
+ break;
+ } while (retry--);
+
+ if (!retry) {
+ dev_dbg(dev, "%s: Mailbox busy\n", __func__);
+ retval = -EBUSY;
+ goto error;
+ }
+
+ /*
+ * Need to swap as it's being swapped again by rtl8xxxu_write16/32()
+ */
+ if (h2c->cmd.cmd & H2C_EXT) {
+ rtl8xxxu_write16(priv, mbox_ext_reg,
+ le16_to_cpu(h2c->raw.ext));
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C)
+ dev_info(dev, "H2C_EXT %04x\n",
+ le16_to_cpu(h2c->raw.ext));
+ }
+ rtl8xxxu_write32(priv, mbox_reg, le32_to_cpu(h2c->raw.data));
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C)
+ dev_info(dev, "H2C %08x\n", le32_to_cpu(h2c->raw.data));
+
+ priv->next_mbox = (mbox_nr + 1) % H2C_MAX_MBOX;
+
+error:
+ mutex_unlock(&priv->h2c_mutex);
+ return retval;
+}
+
+static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ u32 val32;
+
+ val8 = rtl8xxxu_read8(priv, REG_SPS0_CTRL);
+ val8 |= BIT(0) | BIT(3);
+ rtl8xxxu_write8(priv, REG_SPS0_CTRL, val8);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM);
+ val32 &= ~(BIT(4) | BIT(5));
+ val32 |= BIT(3);
+ if (priv->rf_paths == 2) {
+ val32 &= ~(BIT(20) | BIT(21));
+ val32 |= BIT(19);
+ }
+ rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~OFDM_RF_PATH_TX_MASK;
+ if (priv->tx_paths == 2)
+ val32 |= OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B;
+ else if (priv->rtlchip == 0x8192c || priv->rtlchip == 0x8191c)
+ val32 |= OFDM_RF_PATH_TX_B;
+ else
+ val32 |= OFDM_RF_PATH_TX_A;
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ val32 &= ~FPGA_RF_MODE_JAPAN;
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+
+ if (priv->rf_paths == 2)
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x63db25a0);
+ else
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x631b25a0);
+
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x32d95);
+ if (priv->rf_paths == 2)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x32d95);
+
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
+}
+
+static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv)
+{
+ u8 sps0;
+ u32 val32;
+
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+
+ sps0 = rtl8xxxu_read8(priv, REG_SPS0_CTRL);
+
+ /* RF RX code for preamble power saving */
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM);
+ val32 &= ~(BIT(3) | BIT(4) | BIT(5));
+ if (priv->rf_paths == 2)
+ val32 &= ~(BIT(19) | BIT(20) | BIT(21));
+ rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val32);
+
+ /* Disable TX for four paths */
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~OFDM_RF_PATH_TX_MASK;
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ /* Enable power saving */
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ val32 |= FPGA_RF_MODE_JAPAN;
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+
+ /* AFE control register to power down bits [30:22] */
+ if (priv->rf_paths == 2)
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00db25a0);
+ else
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x001b25a0);
+
+ /* Power down RF module */
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0);
+ if (priv->rf_paths == 2)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0);
+
+ sps0 &= ~(BIT(0) | BIT(3));
+ rtl8xxxu_write8(priv, REG_SPS0_CTRL, sps0);
+}
+
+
+static void rtl8723a_stop_tx_beacon(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2);
+ val8 &= ~BIT(6);
+ rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8);
+
+ rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x64);
+ val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2);
+ val8 &= ~BIT(0);
+ rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
+}
+
+
+/*
+ * The rtl8723a has 3 channel groups for it's efuse settings. It only
+ * supports the 2.4GHz band, so channels 1 - 14:
+ * group 0: channels 1 - 3
+ * group 1: channels 4 - 9
+ * group 2: channels 10 - 14
+ *
+ * Note: We index from 0 in the code
+ */
+static int rtl8723a_channel_to_group(int channel)
+{
+ int group;
+
+ if (channel < 4)
+ group = 0;
+ else if (channel < 10)
+ group = 1;
+ else
+ group = 2;
+
+ return group;
+}
+
+static void rtl8723au_config_channel(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ u32 val32, rsr;
+ u8 val8, opmode;
+ bool ht = true;
+ int sec_ch_above, channel;
+ int i;
+
+ opmode = rtl8xxxu_read8(priv, REG_BW_OPMODE);
+ rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET);
+ channel = hw->conf.chandef.chan->hw_value;
+
+ switch (hw->conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ ht = false;
+ case NL80211_CHAN_WIDTH_20:
+ opmode |= BW_OPMODE_20MHZ;
+ rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ val32 &= ~FPGA_RF_MODE;
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE);
+ val32 &= ~FPGA_RF_MODE;
+ rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2);
+ val32 |= FPGA0_ANALOG2_20MHZ;
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val32);
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ if (hw->conf.chandef.center_freq1 >
+ hw->conf.chandef.chan->center_freq) {
+ sec_ch_above = 1;
+ channel += 2;
+ } else {
+ sec_ch_above = 0;
+ channel -= 2;
+ }
+
+ opmode &= ~BW_OPMODE_20MHZ;
+ rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode);
+ rsr &= ~RSR_RSC_BANDWIDTH_40M;
+ if (sec_ch_above)
+ rsr |= RSR_RSC_UPPER_SUB_CHANNEL;
+ else
+ rsr |= RSR_RSC_LOWER_SUB_CHANNEL;
+ rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, rsr);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ val32 |= FPGA_RF_MODE;
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE);
+ val32 |= FPGA_RF_MODE;
+ rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32);
+
+ /*
+ * Set Control channel to upper or lower. These settings
+ * are required only for 40MHz
+ */
+ val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM);
+ val32 &= ~CCK0_SIDEBAND;
+ if (!sec_ch_above)
+ val32 |= CCK0_SIDEBAND;
+ rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF);
+ val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */
+ if (sec_ch_above)
+ val32 |= OFDM_LSTF_PRIME_CH_LOW;
+ else
+ val32 |= OFDM_LSTF_PRIME_CH_HIGH;
+ rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2);
+ val32 &= ~FPGA0_ANALOG2_20MHZ;
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE);
+ val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL);
+ if (sec_ch_above)
+ val32 |= FPGA0_PS_UPPER_CHANNEL;
+ else
+ val32 |= FPGA0_PS_LOWER_CHANNEL;
+ rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32);
+ break;
+
+ default:
+ break;
+ }
+
+ for (i = RF_A; i < priv->rf_paths; i++) {
+ val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG);
+ val32 &= ~MODE_AG_CHANNEL_MASK;
+ val32 |= channel;
+ rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32);
+ }
+
+ if (ht)
+ val8 = 0x0e;
+ else
+ val8 = 0x0a;
+
+ rtl8xxxu_write8(priv, REG_SIFS_CCK + 1, val8);
+ rtl8xxxu_write8(priv, REG_SIFS_OFDM + 1, val8);
+
+ rtl8xxxu_write16(priv, REG_R2T_SIFS, 0x0808);
+ rtl8xxxu_write16(priv, REG_T2T_SIFS, 0x0a0a);
+
+ for (i = RF_A; i < priv->rf_paths; i++) {
+ val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG);
+ if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40)
+ val32 &= ~MODE_AG_CHANNEL_20MHZ;
+ else
+ val32 |= MODE_AG_CHANNEL_20MHZ;
+ rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32);
+ }
+}
+
+static void
+rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
+{
+ u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS];
+ u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS];
+ u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b;
+ u8 val8;
+ int group, i;
+
+ group = rtl8723a_channel_to_group(channel);
+
+ cck[0] = priv->cck_tx_power_index_A[group];
+ cck[1] = priv->cck_tx_power_index_B[group];
+
+ ofdm[0] = priv->ht40_1s_tx_power_index_A[group];
+ ofdm[1] = priv->ht40_1s_tx_power_index_B[group];
+
+ ofdmbase[0] = ofdm[0] + priv->ofdm_tx_power_index_diff[group].a;
+ ofdmbase[1] = ofdm[1] + priv->ofdm_tx_power_index_diff[group].b;
+
+ mcsbase[0] = ofdm[0];
+ mcsbase[1] = ofdm[1];
+ if (!ht40) {
+ mcsbase[0] += priv->ht20_tx_power_index_diff[group].a;
+ mcsbase[1] += priv->ht20_tx_power_index_diff[group].b;
+ }
+
+ if (priv->tx_paths > 1) {
+ if (ofdm[0] > priv->ht40_2s_tx_power_index_diff[group].a)
+ ofdm[0] -= priv->ht40_2s_tx_power_index_diff[group].a;
+ if (ofdm[1] > priv->ht40_2s_tx_power_index_diff[group].b)
+ ofdm[1] -= priv->ht40_2s_tx_power_index_diff[group].b;
+ }
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL)
+ dev_info(&priv->udev->dev,
+ "%s: Setting TX power CCK A: %02x, "
+ "CCK B: %02x, OFDM A: %02x, OFDM B: %02x\n",
+ __func__, cck[0], cck[1], ofdm[0], ofdm[1]);
+
+ for (i = 0; i < RTL8723A_MAX_RF_PATHS; i++) {
+ if (cck[i] > RF6052_MAX_TX_PWR)
+ cck[i] = RF6052_MAX_TX_PWR;
+ if (ofdm[i] > RF6052_MAX_TX_PWR)
+ ofdm[i] = RF6052_MAX_TX_PWR;
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32);
+ val32 &= 0xffff00ff;
+ val32 |= (cck[0] << 8);
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11);
+ val32 &= 0xff;
+ val32 |= ((cck[0] << 8) | (cck[0] << 16) | (cck[0] << 24));
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11);
+ val32 &= 0xffffff00;
+ val32 |= cck[1];
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32);
+ val32 &= 0xff;
+ val32 |= ((cck[1] << 8) | (cck[1] << 16) | (cck[1] << 24));
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val32);
+
+ ofdm_a = ofdmbase[0] | ofdmbase[0] << 8 |
+ ofdmbase[0] << 16 | ofdmbase[0] << 24;
+ ofdm_b = ofdmbase[1] | ofdmbase[1] << 8 |
+ ofdmbase[1] << 16 | ofdmbase[1] << 24;
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm_a);
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm_b);
+
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm_a);
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm_b);
+
+ mcs_a = mcsbase[0] | mcsbase[0] << 8 |
+ mcsbase[0] << 16 | mcsbase[0] << 24;
+ mcs_b = mcsbase[1] | mcsbase[1] << 8 |
+ mcsbase[1] << 16 | mcsbase[1] << 24;
+
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs_a);
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs_b);
+
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs_a);
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs_b);
+
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs_a);
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs_b);
+
+ rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs_a);
+ for (i = 0; i < 3; i++) {
+ if (i != 2)
+ val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0;
+ else
+ val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0;
+ rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val8);
+ }
+ rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs_b);
+ for (i = 0; i < 3; i++) {
+ if (i != 2)
+ val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0;
+ else
+ val8 = (mcsbase[1] > 6) ? (mcsbase[1] - 6) : 0;
+ rtl8xxxu_write8(priv, REG_OFDM0_XD_TX_IQ_IMBALANCE + i, val8);
+ }
+}
+
+static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv,
+ enum nl80211_iftype linktype)
+{
+ u16 val8;
+
+ val8 = rtl8xxxu_read16(priv, REG_MSR);
+ val8 &= ~MSR_LINKTYPE_MASK;
+
+ switch (linktype) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ val8 |= MSR_LINKTYPE_NONE;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ val8 |= MSR_LINKTYPE_ADHOC;
+ break;
+ case NL80211_IFTYPE_STATION:
+ val8 |= MSR_LINKTYPE_STATION;
+ break;
+ case NL80211_IFTYPE_AP:
+ val8 |= MSR_LINKTYPE_AP;
+ break;
+ default:
+ goto out;
+ }
+
+ rtl8xxxu_write8(priv, REG_MSR, val8);
+out:
+ return;
+}
+
+static void
+rtl8xxxu_set_retry(struct rtl8xxxu_priv *priv, u16 short_retry, u16 long_retry)
+{
+ u16 val16;
+
+ val16 = ((short_retry << RETRY_LIMIT_SHORT_SHIFT) &
+ RETRY_LIMIT_SHORT_MASK) |
+ ((long_retry << RETRY_LIMIT_LONG_SHIFT) &
+ RETRY_LIMIT_LONG_MASK);
+
+ rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16);
+}
+
+static void
+rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm)
+{
+ u16 val16;
+
+ val16 = ((cck << SPEC_SIFS_CCK_SHIFT) & SPEC_SIFS_CCK_MASK) |
+ ((ofdm << SPEC_SIFS_OFDM_SHIFT) & SPEC_SIFS_OFDM_MASK);
+
+ rtl8xxxu_write16(priv, REG_SPEC_SIFS, val16);
+}
+
+static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ char *cut;
+
+ switch (priv->chip_cut) {
+ case 0:
+ cut = "A";
+ break;
+ case 1:
+ cut = "B";
+ break;
+ default:
+ cut = "unknown";
+ }
+
+ dev_info(dev,
+ "RTL%s rev %s (%s) %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n",
+ priv->chip_name, cut, priv->vendor_umc ? "UMC" : "TSMC",
+ priv->tx_paths, priv->rx_paths, priv->ep_tx_count,
+ priv->has_wifi, priv->has_bluetooth, priv->has_gps,
+ priv->hi_pa);
+
+ dev_info(dev, "RTL%s MAC: %pM\n", priv->chip_name, priv->mac_addr);
+}
+
+static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 val32, bonding;
+ u16 val16;
+
+ val32 = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >>
+ SYS_CFG_CHIP_VERSION_SHIFT;
+ if (val32 & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ return -ENOTSUPP;
+ }
+
+ if (val32 & SYS_CFG_BT_FUNC) {
+ sprintf(priv->chip_name, "8723AU");
+ priv->rf_paths = 1;
+ priv->rx_paths = 1;
+ priv->tx_paths = 1;
+ priv->rtlchip = 0x8723a;
+
+ val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL);
+ if (val32 & MULTI_WIFI_FUNC_EN)
+ priv->has_wifi = 1;
+ if (val32 & MULTI_BT_FUNC_EN)
+ priv->has_bluetooth = 1;
+ if (val32 & MULTI_GPS_FUNC_EN)
+ priv->has_gps = 1;
+ } else if (val32 & SYS_CFG_TYPE_ID) {
+ bonding = rtl8xxxu_read32(priv, REG_HPON_FSM);
+ bonding &= HPON_FSM_BONDING_MASK;
+ if (bonding == HPON_FSM_BONDING_1T2R) {
+ sprintf(priv->chip_name, "8191CU");
+ priv->rf_paths = 2;
+ priv->rx_paths = 2;
+ priv->tx_paths = 1;
+ priv->rtlchip = 0x8191c;
+ } else {
+ sprintf(priv->chip_name, "8192CU");
+ priv->rf_paths = 2;
+ priv->rx_paths = 2;
+ priv->tx_paths = 2;
+ priv->rtlchip = 0x8192c;
+ }
+ priv->has_wifi = 1;
+ } else {
+ sprintf(priv->chip_name, "8188CU");
+ priv->rf_paths = 1;
+ priv->rx_paths = 1;
+ priv->tx_paths = 1;
+ priv->rtlchip = 0x8188c;
+ priv->has_wifi = 1;
+ }
+
+ if (val32 & SYS_CFG_VENDOR_ID)
+ priv->vendor_umc = 1;
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = (val32 & GPIO_RF_RL_ID) >> 28;
+
+ val16 = rtl8xxxu_read16(priv, REG_NORMAL_SIE_EP_TX);
+ if (val16 & NORMAL_SIE_EP_TX_HIGH_MASK) {
+ priv->ep_tx_high_queue = 1;
+ priv->ep_tx_count++;
+ }
+
+ if (val16 & NORMAL_SIE_EP_TX_NORMAL_MASK) {
+ priv->ep_tx_normal_queue = 1;
+ priv->ep_tx_count++;
+ }
+
+ if (val16 & NORMAL_SIE_EP_TX_LOW_MASK) {
+ priv->ep_tx_low_queue = 1;
+ priv->ep_tx_count++;
+ }
+
+ /*
+ * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
+ */
+ if (!priv->ep_tx_count) {
+ switch (priv->nr_out_eps) {
+ case 3:
+ priv->ep_tx_low_queue = 1;
+ priv->ep_tx_count++;
+ case 2:
+ priv->ep_tx_normal_queue = 1;
+ priv->ep_tx_count++;
+ case 1:
+ priv->ep_tx_high_queue = 1;
+ priv->ep_tx_count++;
+ break;
+ default:
+ dev_info(dev, "Unsupported USB TX end-points\n");
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv)
+{
+ if (priv->efuse_wifi.efuse8723.rtl_id != cpu_to_le16(0x8129))
+ return -EINVAL;
+
+ ether_addr_copy(priv->mac_addr, priv->efuse_wifi.efuse8723.mac_addr);
+
+ memcpy(priv->cck_tx_power_index_A,
+ priv->efuse_wifi.efuse8723.cck_tx_power_index_A,
+ sizeof(priv->cck_tx_power_index_A));
+ memcpy(priv->cck_tx_power_index_B,
+ priv->efuse_wifi.efuse8723.cck_tx_power_index_B,
+ sizeof(priv->cck_tx_power_index_B));
+
+ memcpy(priv->ht40_1s_tx_power_index_A,
+ priv->efuse_wifi.efuse8723.ht40_1s_tx_power_index_A,
+ sizeof(priv->ht40_1s_tx_power_index_A));
+ memcpy(priv->ht40_1s_tx_power_index_B,
+ priv->efuse_wifi.efuse8723.ht40_1s_tx_power_index_B,
+ sizeof(priv->ht40_1s_tx_power_index_B));
+
+ memcpy(priv->ht20_tx_power_index_diff,
+ priv->efuse_wifi.efuse8723.ht20_tx_power_index_diff,
+ sizeof(priv->ht20_tx_power_index_diff));
+ memcpy(priv->ofdm_tx_power_index_diff,
+ priv->efuse_wifi.efuse8723.ofdm_tx_power_index_diff,
+ sizeof(priv->ofdm_tx_power_index_diff));
+
+ memcpy(priv->ht40_max_power_offset,
+ priv->efuse_wifi.efuse8723.ht40_max_power_offset,
+ sizeof(priv->ht40_max_power_offset));
+ memcpy(priv->ht20_max_power_offset,
+ priv->efuse_wifi.efuse8723.ht20_max_power_offset,
+ sizeof(priv->ht20_max_power_offset));
+
+ dev_info(&priv->udev->dev, "Vendor: %.7s\n",
+ priv->efuse_wifi.efuse8723.vendor_name);
+ dev_info(&priv->udev->dev, "Product: %.41s\n",
+ priv->efuse_wifi.efuse8723.device_name);
+ return 0;
+}
+
+#ifdef CONFIG_RTL8XXXU_UNTESTED
+
+static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv)
+{
+ int i;
+
+ if (priv->efuse_wifi.efuse8192.rtl_id != cpu_to_le16(0x8129))
+ return -EINVAL;
+
+ ether_addr_copy(priv->mac_addr, priv->efuse_wifi.efuse8192.mac_addr);
+
+ memcpy(priv->cck_tx_power_index_A,
+ priv->efuse_wifi.efuse8192.cck_tx_power_index_A,
+ sizeof(priv->cck_tx_power_index_A));
+ memcpy(priv->cck_tx_power_index_B,
+ priv->efuse_wifi.efuse8192.cck_tx_power_index_B,
+ sizeof(priv->cck_tx_power_index_B));
+
+ memcpy(priv->ht40_1s_tx_power_index_A,
+ priv->efuse_wifi.efuse8192.ht40_1s_tx_power_index_A,
+ sizeof(priv->ht40_1s_tx_power_index_A));
+ memcpy(priv->ht40_1s_tx_power_index_B,
+ priv->efuse_wifi.efuse8192.ht40_1s_tx_power_index_B,
+ sizeof(priv->ht40_1s_tx_power_index_B));
+ memcpy(priv->ht40_2s_tx_power_index_diff,
+ priv->efuse_wifi.efuse8192.ht40_2s_tx_power_index_diff,
+ sizeof(priv->ht40_2s_tx_power_index_diff));
+
+ memcpy(priv->ht20_tx_power_index_diff,
+ priv->efuse_wifi.efuse8192.ht20_tx_power_index_diff,
+ sizeof(priv->ht20_tx_power_index_diff));
+ memcpy(priv->ofdm_tx_power_index_diff,
+ priv->efuse_wifi.efuse8192.ofdm_tx_power_index_diff,
+ sizeof(priv->ofdm_tx_power_index_diff));
+
+ memcpy(priv->ht40_max_power_offset,
+ priv->efuse_wifi.efuse8192.ht40_max_power_offset,
+ sizeof(priv->ht40_max_power_offset));
+ memcpy(priv->ht20_max_power_offset,
+ priv->efuse_wifi.efuse8192.ht20_max_power_offset,
+ sizeof(priv->ht20_max_power_offset));
+
+ dev_info(&priv->udev->dev, "Vendor: %.7s\n",
+ priv->efuse_wifi.efuse8192.vendor_name);
+ dev_info(&priv->udev->dev, "Product: %.20s\n",
+ priv->efuse_wifi.efuse8192.device_name);
+
+ if (priv->efuse_wifi.efuse8192.rf_regulatory & 0x20) {
+ sprintf(priv->chip_name, "8188RU");
+ priv->hi_pa = 1;
+ }
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) {
+ unsigned char *raw = priv->efuse_wifi.raw;
+
+ dev_info(&priv->udev->dev,
+ "%s: dumping efuse (0x%02zx bytes):\n",
+ __func__, sizeof(struct rtl8192cu_efuse));
+ for (i = 0; i < sizeof(struct rtl8192cu_efuse); i += 8) {
+ dev_info(&priv->udev->dev, "%02x: "
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
+ raw[i], raw[i + 1], raw[i + 2],
+ raw[i + 3], raw[i + 4], raw[i + 5],
+ raw[i + 6], raw[i + 7]);
+ }
+ }
+ return 0;
+}
+
+#endif
+
+static int
+rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data)
+{
+ int i;
+ u8 val8;
+ u32 val32;
+
+ /* Write Address */
+ rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 1, offset & 0xff);
+ val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 2);
+ val8 &= 0xfc;
+ val8 |= (offset >> 8) & 0x03;
+ rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 2, val8);
+
+ val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 3);
+ rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 3, val8 & 0x7f);
+
+ /* Poll for data read */
+ val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL);
+ for (i = 0; i < RTL8XXXU_MAX_REG_POLL; i++) {
+ val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL);
+ if (val32 & BIT(31))
+ break;
+ }
+
+ if (i == RTL8XXXU_MAX_REG_POLL)
+ return -EIO;
+
+ udelay(50);
+ val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL);
+
+ *data = val32 & 0xff;
+ return 0;
+}
+
+static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ int i, ret = 0;
+ u8 val8, word_mask, header, extheader;
+ u16 val16, efuse_addr, offset;
+ u32 val32;
+
+ val16 = rtl8xxxu_read16(priv, REG_9346CR);
+ if (val16 & EEPROM_ENABLE)
+ priv->has_eeprom = 1;
+ if (val16 & EEPROM_BOOT)
+ priv->boot_eeprom = 1;
+
+ val32 = rtl8xxxu_read32(priv, REG_EFUSE_TEST);
+ val32 = (val32 & ~EFUSE_SELECT_MASK) | EFUSE_WIFI_SELECT;
+ rtl8xxxu_write32(priv, REG_EFUSE_TEST, val32);
+
+ dev_dbg(dev, "Booting from %s\n",
+ priv->boot_eeprom ? "EEPROM" : "EFUSE");
+
+ rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_ENABLE);
+
+ /* 1.2V Power: From VDDON with Power Cut(0x0000[15]), default valid */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL);
+ if (!(val16 & SYS_ISO_PWC_EV12V)) {
+ val16 |= SYS_ISO_PWC_EV12V;
+ rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16);
+ }
+ /* Reset: 0x0000[28], default valid */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
+ if (!(val16 & SYS_FUNC_ELDR)) {
+ val16 |= SYS_FUNC_ELDR;
+ rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
+ }
+
+ /*
+ * Clock: Gated(0x0008[5]) 8M(0x0008[1]) clock from ANA, default valid
+ */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR);
+ if (!(val16 & SYS_CLK_LOADER_ENABLE) || !(val16 & SYS_CLK_ANA8M)) {
+ val16 |= (SYS_CLK_LOADER_ENABLE | SYS_CLK_ANA8M);
+ rtl8xxxu_write16(priv, REG_SYS_CLKR, val16);
+ }
+
+ /* Default value is 0xff */
+ memset(priv->efuse_wifi.raw, 0xff, EFUSE_MAP_LEN_8723A);
+
+ efuse_addr = 0;
+ while (efuse_addr < EFUSE_REAL_CONTENT_LEN_8723A) {
+ ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &header);
+ if (ret || header == 0xff)
+ goto exit;
+
+ if ((header & 0x1f) == 0x0f) { /* extended header */
+ offset = (header & 0xe0) >> 5;
+
+ ret = rtl8xxxu_read_efuse8(priv, efuse_addr++,
+ &extheader);
+ if (ret)
+ goto exit;
+ /* All words disabled */
+ if ((extheader & 0x0f) == 0x0f)
+ continue;
+
+ offset |= ((extheader & 0xf0) >> 1);
+ word_mask = extheader & 0x0f;
+ } else {
+ offset = (header >> 4) & 0x0f;
+ word_mask = header & 0x0f;
+ }
+
+ if (offset < EFUSE_MAX_SECTION_8723A) {
+ u16 map_addr;
+ /* Get word enable value from PG header */
+
+ /* We have 8 bits to indicate validity */
+ map_addr = offset * 8;
+ if (map_addr >= EFUSE_MAP_LEN_8723A) {
+ dev_warn(dev, "%s: Illegal map_addr (%04x), "
+ "efuse corrupt!\n",
+ __func__, map_addr);
+ ret = -EINVAL;
+ goto exit;
+ }
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(word_mask & BIT(i))) {
+ ret = rtl8xxxu_read_efuse8(priv,
+ efuse_addr++,
+ &val8);
+ if (ret)
+ goto exit;
+ priv->efuse_wifi.raw[map_addr++] = val8;
+
+ ret = rtl8xxxu_read_efuse8(priv,
+ efuse_addr++,
+ &val8);
+ if (ret)
+ goto exit;
+ priv->efuse_wifi.raw[map_addr++] = val8;
+ } else
+ map_addr += 2;
+ }
+ } else {
+ dev_warn(dev,
+ "%s: Illegal offset (%04x), efuse corrupt!\n",
+ __func__, offset);
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
+
+exit:
+ rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_DISABLE);
+
+ return ret;
+}
+
+static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ int ret = 0, i;
+ u32 val32;
+
+ /* Poll checksum report */
+ for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) {
+ val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
+ if (val32 & MCU_FW_DL_CSUM_REPORT)
+ break;
+ }
+
+ if (i == RTL8XXXU_FIRMWARE_POLL_MAX) {
+ dev_warn(dev, "Firmware checksum poll timed out\n");
+ ret = -EAGAIN;
+ goto exit;
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
+ val32 |= MCU_FW_DL_READY;
+ val32 &= ~MCU_WINT_INIT_READY;
+ rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32);
+
+ /* Wait for firmware to become ready */
+ for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) {
+ val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
+ if (val32 & MCU_WINT_INIT_READY)
+ break;
+
+ udelay(100);
+ }
+
+ if (i == RTL8XXXU_FIRMWARE_POLL_MAX) {
+ dev_warn(dev, "Firmware failed to start\n");
+ ret = -EAGAIN;
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
+{
+ int pages, remainder, i, ret;
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ u8 *fwptr;
+
+ val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1);
+ val8 |= 4;
+ rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8);
+
+ /* 8051 enable */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
+ rtl8xxxu_write16(priv, REG_SYS_FUNC, val16 | SYS_FUNC_CPU_ENABLE);
+
+ /* MCU firmware download enable */
+ val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_ENABLE);
+
+ /* 8051 reset */
+ val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
+ rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32 & ~BIT(19));
+
+ /* Reset firmware download checksum */
+ val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_CSUM_REPORT);
+
+ pages = priv->fw_size / RTL_FW_PAGE_SIZE;
+ remainder = priv->fw_size % RTL_FW_PAGE_SIZE;
+
+ fwptr = priv->fw_data->data;
+
+ for (i = 0; i < pages; i++) {
+ val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8;
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i);
+
+ ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
+ fwptr, RTL_FW_PAGE_SIZE);
+ if (ret != RTL_FW_PAGE_SIZE) {
+ ret = -EAGAIN;
+ goto fw_abort;
+ }
+
+ fwptr += RTL_FW_PAGE_SIZE;
+ }
+
+ if (remainder) {
+ val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8;
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i);
+ ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
+ fwptr, remainder);
+ if (ret != remainder) {
+ ret = -EAGAIN;
+ goto fw_abort;
+ }
+ }
+
+ ret = 0;
+fw_abort:
+ /* MCU firmware download disable */
+ val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL);
+ rtl8xxxu_write16(priv, REG_MCU_FW_DL,
+ val16 & (~MCU_FW_DL_ENABLE & 0xff));
+
+ return ret;
+}
+
+static int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name)
+{
+ struct device *dev = &priv->udev->dev;
+ const struct firmware *fw;
+ int ret = 0;
+ u16 signature;
+
+ dev_info(dev, "%s: Loading firmware %s\n", DRIVER_NAME, fw_name);
+ if (request_firmware(&fw, fw_name, &priv->udev->dev)) {
+ dev_warn(dev, "request_firmware(%s) failed\n", fw_name);
+ ret = -EAGAIN;
+ goto exit;
+ }
+ if (!fw) {
+ dev_warn(dev, "Firmware data not available\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ priv->fw_data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+ priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header);
+
+ signature = le16_to_cpu(priv->fw_data->signature);
+ switch (signature & 0xfff0) {
+ case 0x92c0:
+ case 0x88c0:
+ case 0x2300:
+ break;
+ default:
+ ret = -EINVAL;
+ dev_warn(dev, "%s: Invalid firmware signature: 0x%04x\n",
+ __func__, signature);
+ }
+
+ dev_info(dev, "Firmware revision %i.%i (signature 0x%04x)\n",
+ le16_to_cpu(priv->fw_data->major_version),
+ priv->fw_data->minor_version, signature);
+
+exit:
+ release_firmware(fw);
+ return ret;
+}
+
+static int rtl8723au_load_firmware(struct rtl8xxxu_priv *priv)
+{
+ char *fw_name;
+ int ret;
+
+ switch (priv->chip_cut) {
+ case 0:
+ fw_name = "rtlwifi/rtl8723aufw_A.bin";
+ break;
+ case 1:
+ if (priv->enable_bluetooth)
+ fw_name = "rtlwifi/rtl8723aufw_B.bin";
+ else
+ fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = rtl8xxxu_load_firmware(priv, fw_name);
+ return ret;
+}
+
+#ifdef CONFIG_RTL8XXXU_UNTESTED
+
+static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv)
+{
+ char *fw_name;
+ int ret;
+
+ if (!priv->vendor_umc)
+ fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
+ else if (priv->chip_cut || priv->rtlchip == 0x8192c)
+ fw_name = "rtlwifi/rtl8192cufw_B.bin";
+ else
+ fw_name = "rtlwifi/rtl8192cufw_A.bin";
+
+ ret = rtl8xxxu_load_firmware(priv, fw_name);
+
+ return ret;
+}
+
+#endif
+
+static void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+ int i = 100;
+
+ /* Inform 8051 to perform reset */
+ rtl8xxxu_write8(priv, REG_HMTFR + 3, 0x20);
+
+ for (i = 100; i > 0; i--) {
+ val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
+
+ if (!(val16 & SYS_FUNC_CPU_ENABLE)) {
+ dev_dbg(&priv->udev->dev,
+ "%s: Firmware self reset success!\n", __func__);
+ break;
+ }
+ udelay(50);
+ }
+
+ if (!i) {
+ /* Force firmware reset */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
+ val16 &= ~SYS_FUNC_CPU_ENABLE;
+ rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
+ }
+}
+
+static int
+rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array)
+{
+ int i, ret;
+ u16 reg;
+ u8 val;
+
+ for (i = 0; ; i++) {
+ reg = array[i].reg;
+ val = array[i].val;
+
+ if (reg == 0xffff && val == 0xff)
+ break;
+
+ ret = rtl8xxxu_write8(priv, reg, val);
+ if (ret != 1) {
+ dev_warn(&priv->udev->dev,
+ "Failed to initialize MAC\n");
+ return -EAGAIN;
+ }
+ }
+
+ rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, 0x0a);
+
+ return 0;
+}
+
+static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_reg32val *array)
+{
+ int i, ret;
+ u16 reg;
+ u32 val;
+
+ for (i = 0; ; i++) {
+ reg = array[i].reg;
+ val = array[i].val;
+
+ if (reg == 0xffff && val == 0xffffffff)
+ break;
+
+ ret = rtl8xxxu_write32(priv, reg, val);
+ if (ret != sizeof(val)) {
+ dev_warn(&priv->udev->dev,
+ "Failed to initialize PHY\n");
+ return -EAGAIN;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+/*
+ * Most of this is black magic retrieved from the old rtl8723au driver
+ */
+static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv)
+{
+ u8 val8, ldoa15, ldov12d, lpldo, ldohci12;
+ u32 val32;
+
+ /*
+ * Todo: The vendor driver maintains a table of PHY register
+ * addresses, which is initialized here. Do we need this?
+ */
+
+ val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL);
+ udelay(2);
+ val8 |= AFE_PLL_320_ENABLE;
+ rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8);
+ udelay(2);
+
+ rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff);
+ udelay(2);
+
+ val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
+ val8 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB;
+ rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
+
+ /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */
+ val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
+ val32 &= ~AFE_XTAL_RF_GATE;
+ if (priv->has_bluetooth)
+ val32 &= ~AFE_XTAL_BT_GATE;
+ rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32);
+
+ /* 6. 0x1f[7:0] = 0x07 */
+ val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB;
+ rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
+
+ if (priv->hi_pa)
+ rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table);
+ else if (priv->tx_paths == 2)
+ rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table);
+ else
+ rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table);
+
+
+ if (priv->rtlchip == 0x8188c && priv->hi_pa &&
+ priv->vendor_umc && priv->chip_cut == 1)
+ rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50);
+
+ if (priv->tx_paths == 1 && priv->rx_paths == 2) {
+ /*
+ * For 1T2R boards, patch the registers.
+ *
+ * It looks like 8191/2 1T2R boards use path B for TX
+ */
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_TX_INFO);
+ val32 &= ~(BIT(0) | BIT(1));
+ val32 |= BIT(1);
+ rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA1_TX_INFO);
+ val32 &= ~0x300033;
+ val32 |= 0x200022;
+ rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING);
+ val32 &= 0xff000000;
+ val32 |= 0x45000000;
+ rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK);
+ val32 |= (OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B |
+ OFDM_RF_PATH_TX_B);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_PARM1);
+ val32 &= ~(BIT(4) | BIT(5));
+ val32 |= BIT(4);
+ rtl8xxxu_write32(priv, REG_OFDM0_AGC_PARM1, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_CCK_RFON);
+ val32 &= ~(BIT(27) | BIT(26));
+ val32 |= BIT(27);
+ rtl8xxxu_write32(priv, REG_TX_CCK_RFON, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_CCK_BBON);
+ val32 &= ~(BIT(27) | BIT(26));
+ val32 |= BIT(27);
+ rtl8xxxu_write32(priv, REG_TX_CCK_BBON, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_RFON);
+ val32 &= ~(BIT(27) | BIT(26));
+ val32 |= BIT(27);
+ rtl8xxxu_write32(priv, REG_TX_OFDM_RFON, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_BBON);
+ val32 &= ~(BIT(27) | BIT(26));
+ val32 |= BIT(27);
+ rtl8xxxu_write32(priv, REG_TX_OFDM_BBON, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_TO_TX);
+ val32 &= ~(BIT(27) | BIT(26));
+ val32 |= BIT(27);
+ rtl8xxxu_write32(priv, REG_TX_TO_TX, val32);
+ }
+
+ if (priv->hi_pa)
+ rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table);
+ else
+ rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table);
+
+ if (priv->rtlchip == 0x8723a &&
+ priv->efuse_wifi.efuse8723.version >= 0x01) {
+ val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL);
+
+ val8 = priv->efuse_wifi.efuse8723.xtal_k & 0x3f;
+ val32 &= 0xff000fff;
+ val32 |= ((val8 | (val8 << 6)) << 12);
+
+ rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32);
+ }
+
+ ldoa15 = LDOA15_ENABLE | LDOA15_OBUF;
+ ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT);
+ ldohci12 = 0x57;
+ lpldo = 1;
+ val32 = (lpldo << 24) | (ldohci12 << 16) | (ldov12d << 8) | ldoa15;
+
+ rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32);
+
+ return 0;
+}
+
+static int rtl8xxxu_init_rf_regs(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_rfregval *array,
+ enum rtl8xxxu_rfpath path)
+{
+ int i, ret;
+ u8 reg;
+ u32 val;
+
+ for (i = 0; ; i++) {
+ reg = array[i].reg;
+ val = array[i].val;
+
+ if (reg == 0xff && val == 0xffffffff)
+ break;
+
+ switch (reg) {
+ case 0xfe:
+ msleep(50);
+ continue;
+ case 0xfd:
+ mdelay(5);
+ continue;
+ case 0xfc:
+ mdelay(1);
+ continue;
+ case 0xfb:
+ udelay(50);
+ continue;
+ case 0xfa:
+ udelay(5);
+ continue;
+ case 0xf9:
+ udelay(1);
+ continue;
+ }
+
+ reg &= 0x3f;
+
+ ret = rtl8xxxu_write_rfreg(priv, path, reg, val);
+ if (ret) {
+ dev_warn(&priv->udev->dev,
+ "Failed to initialize RF\n");
+ return -EAGAIN;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int rtl8xxxu_init_phy_rf(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_rfregval *table,
+ enum rtl8xxxu_rfpath path)
+{
+ u32 val32;
+ u16 val16, rfsi_rfenv;
+ u16 reg_sw_ctrl, reg_int_oe, reg_hssi_parm2;
+
+ switch (path) {
+ case RF_A:
+ reg_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL;
+ reg_int_oe = REG_FPGA0_XA_RF_INT_OE;
+ reg_hssi_parm2 = REG_FPGA0_XA_HSSI_PARM2;
+ break;
+ case RF_B:
+ reg_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL;
+ reg_int_oe = REG_FPGA0_XB_RF_INT_OE;
+ reg_hssi_parm2 = REG_FPGA0_XB_HSSI_PARM2;
+ break;
+ default:
+ dev_err(&priv->udev->dev, "%s:Unsupported RF path %c\n",
+ __func__, path + 'A');
+ return -EINVAL;
+ }
+ /* For path B, use XB */
+ rfsi_rfenv = rtl8xxxu_read16(priv, reg_sw_ctrl);
+ rfsi_rfenv &= FPGA0_RF_RFENV;
+
+ /*
+ * These two we might be able to optimize into one
+ */
+ val32 = rtl8xxxu_read32(priv, reg_int_oe);
+ val32 |= BIT(20); /* 0x10 << 16 */
+ rtl8xxxu_write32(priv, reg_int_oe, val32);
+ udelay(1);
+
+ val32 = rtl8xxxu_read32(priv, reg_int_oe);
+ val32 |= BIT(4);
+ rtl8xxxu_write32(priv, reg_int_oe, val32);
+ udelay(1);
+
+ /*
+ * These two we might be able to optimize into one
+ */
+ val32 = rtl8xxxu_read32(priv, reg_hssi_parm2);
+ val32 &= ~FPGA0_HSSI_3WIRE_ADDR_LEN;
+ rtl8xxxu_write32(priv, reg_hssi_parm2, val32);
+ udelay(1);
+
+ val32 = rtl8xxxu_read32(priv, reg_hssi_parm2);
+ val32 &= ~FPGA0_HSSI_3WIRE_DATA_LEN;
+ rtl8xxxu_write32(priv, reg_hssi_parm2, val32);
+ udelay(1);
+
+ rtl8xxxu_init_rf_regs(priv, table, path);
+
+ /* For path B, use XB */
+ val16 = rtl8xxxu_read16(priv, reg_sw_ctrl);
+ val16 &= ~FPGA0_RF_RFENV;
+ val16 |= rfsi_rfenv;
+ rtl8xxxu_write16(priv, reg_sw_ctrl, val16);
+
+ return 0;
+}
+
+static int rtl8xxxu_llt_write(struct rtl8xxxu_priv *priv, u8 address, u8 data)
+{
+ int ret = -EBUSY;
+ int count = 0;
+ u32 value;
+
+ value = LLT_OP_WRITE | address << 8 | data;
+
+ rtl8xxxu_write32(priv, REG_LLT_INIT, value);
+
+ do {
+ value = rtl8xxxu_read32(priv, REG_LLT_INIT);
+ if ((value & LLT_OP_MASK) == LLT_OP_INACTIVE) {
+ ret = 0;
+ break;
+ }
+ } while (count++ < 20);
+
+ return ret;
+}
+
+static int rtl8xxxu_init_llt_table(struct rtl8xxxu_priv *priv, u8 last_tx_page)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < last_tx_page; i++) {
+ ret = rtl8xxxu_llt_write(priv, i, i + 1);
+ if (ret)
+ goto exit;
+ }
+
+ ret = rtl8xxxu_llt_write(priv, last_tx_page, 0xff);
+ if (ret)
+ goto exit;
+
+ /* Mark remaining pages as a ring buffer */
+ for (i = last_tx_page + 1; i < 0xff; i++) {
+ ret = rtl8xxxu_llt_write(priv, i, (i + 1));
+ if (ret)
+ goto exit;
+ }
+
+ /* Let last entry point to the start entry of ring buffer */
+ ret = rtl8xxxu_llt_write(priv, 0xff, last_tx_page + 1);
+ if (ret)
+ goto exit;
+
+exit:
+ return ret;
+}
+
+static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv)
+{
+ u16 val16, hi, lo;
+ u16 hiq, mgq, bkq, beq, viq, voq;
+ int hip, mgp, bkp, bep, vip, vop;
+ int ret = 0;
+
+ switch (priv->ep_tx_count) {
+ case 1:
+ if (priv->ep_tx_high_queue) {
+ hi = TRXDMA_QUEUE_HIGH;
+ } else if (priv->ep_tx_low_queue) {
+ hi = TRXDMA_QUEUE_LOW;
+ } else if (priv->ep_tx_normal_queue) {
+ hi = TRXDMA_QUEUE_NORMAL;
+ } else {
+ hi = 0;
+ ret = -EINVAL;
+ }
+
+ hiq = hi;
+ mgq = hi;
+ bkq = hi;
+ beq = hi;
+ viq = hi;
+ voq = hi;
+
+ hip = 0;
+ mgp = 0;
+ bkp = 0;
+ bep = 0;
+ vip = 0;
+ vop = 0;
+ break;
+ case 2:
+ if (priv->ep_tx_high_queue && priv->ep_tx_low_queue) {
+ hi = TRXDMA_QUEUE_HIGH;
+ lo = TRXDMA_QUEUE_LOW;
+ } else if (priv->ep_tx_normal_queue && priv->ep_tx_low_queue) {
+ hi = TRXDMA_QUEUE_NORMAL;
+ lo = TRXDMA_QUEUE_LOW;
+ } else if (priv->ep_tx_high_queue && priv->ep_tx_normal_queue) {
+ hi = TRXDMA_QUEUE_HIGH;
+ lo = TRXDMA_QUEUE_NORMAL;
+ } else {
+ ret = -EINVAL;
+ hi = 0;
+ lo = 0;
+ }
+
+ hiq = hi;
+ mgq = hi;
+ bkq = lo;
+ beq = lo;
+ viq = hi;
+ voq = hi;
+
+ hip = 0;
+ mgp = 0;
+ bkp = 1;
+ bep = 1;
+ vip = 0;
+ vop = 0;
+ break;
+ case 3:
+ beq = TRXDMA_QUEUE_LOW;
+ bkq = TRXDMA_QUEUE_LOW;
+ viq = TRXDMA_QUEUE_NORMAL;
+ voq = TRXDMA_QUEUE_HIGH;
+ mgq = TRXDMA_QUEUE_HIGH;
+ hiq = TRXDMA_QUEUE_HIGH;
+
+ hip = hiq ^ 3;
+ mgp = mgq ^ 3;
+ bkp = bkq ^ 3;
+ bep = beq ^ 3;
+ vip = viq ^ 3;
+ vop = viq ^ 3;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ /*
+ * None of the vendor drivers are configuring the beacon
+ * queue here .... why?
+ */
+ if (!ret) {
+ val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL);
+ val16 &= 0x7;
+ val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) |
+ (viq << TRXDMA_CTRL_VIQ_SHIFT) |
+ (beq << TRXDMA_CTRL_BEQ_SHIFT) |
+ (bkq << TRXDMA_CTRL_BKQ_SHIFT) |
+ (mgq << TRXDMA_CTRL_MGQ_SHIFT) |
+ (hiq << TRXDMA_CTRL_HIQ_SHIFT);
+ rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16);
+
+ priv->pipe_out[TXDESC_QUEUE_VO] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[vop]);
+ priv->pipe_out[TXDESC_QUEUE_VI] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[vip]);
+ priv->pipe_out[TXDESC_QUEUE_BE] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[bep]);
+ priv->pipe_out[TXDESC_QUEUE_BK] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[bkp]);
+ priv->pipe_out[TXDESC_QUEUE_BEACON] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[0]);
+ priv->pipe_out[TXDESC_QUEUE_MGNT] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[mgp]);
+ priv->pipe_out[TXDESC_QUEUE_HIGH] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[hip]);
+ priv->pipe_out[TXDESC_QUEUE_CMD] =
+ usb_sndbulkpipe(priv->udev, priv->out_ep[0]);
+ }
+
+ return ret;
+}
+
+static void rtl8xxxu_fill_iqk_matrix_a(struct rtl8xxxu_priv *priv,
+ bool iqk_ok, int result[][8],
+ int candidate, bool tx_only)
+{
+ u32 oldval, x, tx0_a, reg;
+ int y, tx0_c;
+ u32 val32;
+
+ if (!iqk_ok)
+ return;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE);
+ oldval = val32 >> 22;
+
+ x = result[candidate][0];
+ if ((x & 0x00000200) != 0)
+ x = x | 0xfffffc00;
+ tx0_a = (x * oldval) >> 8;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE);
+ val32 &= ~0x3ff;
+ val32 |= tx0_a;
+ rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES);
+ val32 &= ~BIT(31);
+ if ((x * oldval >> 7) & 0x1)
+ val32 |= BIT(31);
+ rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32);
+
+ y = result[candidate][1];
+ if ((y & 0x00000200) != 0)
+ y = y | 0xfffffc00;
+ tx0_c = (y * oldval) >> 8;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XC_TX_AFE);
+ val32 &= ~0xf0000000;
+ val32 |= (((tx0_c & 0x3c0) >> 6) << 28);
+ rtl8xxxu_write32(priv, REG_OFDM0_XC_TX_AFE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE);
+ val32 &= ~0x003f0000;
+ val32 |= ((tx0_c & 0x3f) << 16);
+ rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES);
+ val32 &= ~BIT(29);
+ if ((y * oldval >> 7) & 0x1)
+ val32 |= BIT(29);
+ rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32);
+
+ if (tx_only) {
+ dev_dbg(&priv->udev->dev, "%s: only TX\n", __func__);
+ return;
+ }
+
+ reg = result[candidate][2];
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE);
+ val32 &= ~0x3ff;
+ val32 |= (reg & 0x3ff);
+ rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val32);
+
+ reg = result[candidate][3] & 0x3F;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE);
+ val32 &= ~0xfc00;
+ val32 |= ((reg << 10) & 0xfc00);
+ rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val32);
+
+ reg = (result[candidate][3] >> 6) & 0xF;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_RX_IQ_EXT_ANTA);
+ val32 &= ~0xf0000000;
+ val32 |= (reg << 28);
+ rtl8xxxu_write32(priv, REG_OFDM0_RX_IQ_EXT_ANTA, val32);
+}
+
+static void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv,
+ bool iqk_ok, int result[][8],
+ int candidate, bool tx_only)
+{
+ u32 oldval, x, tx1_a, reg;
+ int y, tx1_c;
+ u32 val32;
+
+ if (!iqk_ok)
+ return;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE);
+ oldval = val32 >> 22;
+
+ x = result[candidate][4];
+ if ((x & 0x00000200) != 0)
+ x = x | 0xfffffc00;
+ tx1_a = (x * oldval) >> 8;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE);
+ val32 &= ~0x3ff;
+ val32 |= tx1_a;
+ rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES);
+ val32 &= ~BIT(27);
+ if ((x * oldval >> 7) & 0x1)
+ val32 |= BIT(27);
+ rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32);
+
+ y = result[candidate][5];
+ if ((y & 0x00000200) != 0)
+ y = y | 0xfffffc00;
+ tx1_c = (y * oldval) >> 8;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XD_TX_AFE);
+ val32 &= ~0xf0000000;
+ val32 |= (((tx1_c & 0x3c0) >> 6) << 28);
+ rtl8xxxu_write32(priv, REG_OFDM0_XD_TX_AFE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE);
+ val32 &= ~0x003f0000;
+ val32 |= ((tx1_c & 0x3f) << 16);
+ rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES);
+ val32 &= ~BIT(25);
+ if ((y * oldval >> 7) & 0x1)
+ val32 |= BIT(25);
+ rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32);
+
+ if (tx_only) {
+ dev_dbg(&priv->udev->dev, "%s: only TX\n", __func__);
+ return;
+ }
+
+ reg = result[candidate][6];
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE);
+ val32 &= ~0x3ff;
+ val32 |= (reg & 0x3ff);
+ rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val32);
+
+ reg = result[candidate][7] & 0x3f;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE);
+ val32 &= ~0xfc00;
+ val32 |= ((reg << 10) & 0xfc00);
+ rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val32);
+
+ reg = (result[candidate][7] >> 6) & 0xf;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE);
+ val32 &= ~0x0000f000;
+ val32 |= (reg << 12);
+ rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32);
+}
+
+#define MAX_TOLERANCE 5
+
+static bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv,
+ int result[][8], int c1, int c2)
+{
+ u32 i, j, diff, simubitmap, bound = 0;
+ int candidate[2] = {-1, -1}; /* for path A and path B */
+ bool retval = true;
+
+ if (priv->tx_paths > 1)
+ bound = 8;
+ else
+ bound = 4;
+
+ simubitmap = 0;
+
+ for (i = 0; i < bound; i++) {
+ diff = (result[c1][i] > result[c2][i]) ?
+ (result[c1][i] - result[c2][i]) :
+ (result[c2][i] - result[c1][i]);
+ if (diff > MAX_TOLERANCE) {
+ if ((i == 2 || i == 6) && !simubitmap) {
+ if (result[c1][i] + result[c1][i + 1] == 0)
+ candidate[(i / 4)] = c2;
+ else if (result[c2][i] + result[c2][i + 1] == 0)
+ candidate[(i / 4)] = c1;
+ else
+ simubitmap = simubitmap | (1 << i);
+ } else {
+ simubitmap = simubitmap | (1 << i);
+ }
+ }
+ }
+
+ if (simubitmap == 0) {
+ for (i = 0; i < (bound / 4); i++) {
+ if (candidate[i] >= 0) {
+ for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+ result[3][j] = result[candidate[i]][j];
+ retval = false;
+ }
+ }
+ return retval;
+ } else if (!(simubitmap & 0x0f)) {
+ /* path A OK */
+ for (i = 0; i < 4; i++)
+ result[3][i] = result[c1][i];
+ } else if (!(simubitmap & 0xf0) && priv->tx_paths > 1) {
+ /* path B OK */
+ for (i = 4; i < 8; i++)
+ result[3][i] = result[c1][i];
+ }
+
+ return false;
+}
+
+static void
+rtl8xxxu_save_mac_regs(struct rtl8xxxu_priv *priv, const u32 *reg, u32 *backup)
+{
+ int i;
+
+ for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++)
+ backup[i] = rtl8xxxu_read8(priv, reg[i]);
+
+ backup[i] = rtl8xxxu_read32(priv, reg[i]);
+}
+
+static void rtl8xxxu_restore_mac_regs(struct rtl8xxxu_priv *priv,
+ const u32 *reg, u32 *backup)
+{
+ int i;
+
+ for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++)
+ rtl8xxxu_write8(priv, reg[i], backup[i]);
+
+ rtl8xxxu_write32(priv, reg[i], backup[i]);
+}
+
+static void rtl8xxxu_save_regs(struct rtl8xxxu_priv *priv, const u32 *regs,
+ u32 *backup, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ backup[i] = rtl8xxxu_read32(priv, regs[i]);
+}
+
+static void rtl8xxxu_restore_regs(struct rtl8xxxu_priv *priv, const u32 *regs,
+ u32 *backup, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ rtl8xxxu_write32(priv, regs[i], backup[i]);
+}
+
+
+static void rtl8xxxu_path_adda_on(struct rtl8xxxu_priv *priv, const u32 *regs,
+ bool path_a_on)
+{
+ u32 path_on;
+ int i;
+
+ path_on = path_a_on ? 0x04db25a4 : 0x0b1b25a4;
+ if (priv->tx_paths == 1) {
+ path_on = 0x0bdb25a0;
+ rtl8xxxu_write32(priv, regs[0], 0x0b1b25a0);
+ } else {
+ rtl8xxxu_write32(priv, regs[0], path_on);
+ }
+
+ for (i = 1 ; i < RTL8XXXU_ADDA_REGS ; i++)
+ rtl8xxxu_write32(priv, regs[i], path_on);
+}
+
+static void rtl8xxxu_mac_calibration(struct rtl8xxxu_priv *priv,
+ const u32 *regs, u32 *backup)
+{
+ int i = 0;
+
+ rtl8xxxu_write8(priv, regs[i], 0x3f);
+
+ for (i = 1 ; i < (RTL8XXXU_MAC_REGS - 1); i++)
+ rtl8xxxu_write8(priv, regs[i], (u8)(backup[i] & ~BIT(3)));
+
+ rtl8xxxu_write8(priv, regs[i], (u8)(backup[i] & ~BIT(5)));
+}
+
+static int rtl8xxxu_iqk_path_a(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_e94, reg_e9c, reg_ea4, val32;
+ int result = 0;
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x10008c1f);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x10008c1f);
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82140102);
+
+ val32 = (priv->rf_paths > 1) ? 0x28160202 :
+ /*IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202: */
+ 0x28160502;
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, val32);
+
+ /* path-B IQK setting */
+ if (priv->rf_paths > 1) {
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x10008c22);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x10008c22);
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82140102);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160202);
+ }
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x001028d1);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
+
+ mdelay(1);
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+ reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
+
+ if (!(reg_eac & BIT(28)) &&
+ ((reg_e94 & 0x03ff0000) != 0x01420000) &&
+ ((reg_e9c & 0x03ff0000) != 0x00420000))
+ result |= 0x01;
+ else /* If TX not OK, ignore RX */
+ goto out;
+
+ /* If TX is OK, check whether RX is OK */
+ if (!(reg_eac & BIT(27)) &&
+ ((reg_ea4 & 0x03ff0000) != 0x01320000) &&
+ ((reg_eac & 0x03ff0000) != 0x00360000))
+ result |= 0x02;
+ else
+ dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n",
+ __func__);
+out:
+ return result;
+}
+
+static int rtl8xxxu_iqk_path_b(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+ int result = 0;
+
+ /* One shot, path B LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000002);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000000);
+
+ mdelay(1);
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+ reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
+ reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
+
+ if (!(reg_eac & BIT(31)) &&
+ ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
+ ((reg_ebc & 0x03ff0000) != 0x00420000))
+ result |= 0x01;
+ else
+ goto out;
+
+ if (!(reg_eac & BIT(30)) &&
+ (((reg_ec4 & 0x03ff0000) >> 16) != 0x132) &&
+ (((reg_ecc & 0x03ff0000) >> 16) != 0x36))
+ result |= 0x02;
+ else
+ dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n",
+ __func__);
+out:
+ return result;
+}
+
+static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
+ int result[][8], int t)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 i, val32;
+ int path_a_ok, path_b_ok;
+ int retry = 2;
+ const u32 adda_regs[RTL8XXXU_ADDA_REGS] = {
+ REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH,
+ REG_RX_WAIT_CCA, REG_TX_CCK_RFON,
+ REG_TX_CCK_BBON, REG_TX_OFDM_RFON,
+ REG_TX_OFDM_BBON, REG_TX_TO_RX,
+ REG_TX_TO_TX, REG_RX_CCK,
+ REG_RX_OFDM, REG_RX_WAIT_RIFS,
+ REG_RX_TO_RX, REG_STANDBY,
+ REG_SLEEP, REG_PMPD_ANAEN
+ };
+ const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
+ REG_TXPAUSE, REG_BEACON_CTRL,
+ REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
+ };
+ const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
+ REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
+ REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
+ REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE,
+ REG_FPGA0_XB_RF_INT_OE, REG_FPGA0_RF_MODE
+ };
+
+ /*
+ * Note: IQ calibration must be performed after loading
+ * PHY_REG.txt , and radio_a, radio_b.txt
+ */
+
+ if (t == 0) {
+ /* Save ADDA parameters, turn Path A ADDA on */
+ rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup,
+ RTL8XXXU_ADDA_REGS);
+ rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
+ rtl8xxxu_save_regs(priv, iqk_bb_regs,
+ priv->bb_backup, RTL8XXXU_BB_REGS);
+ }
+
+ rtl8xxxu_path_adda_on(priv, adda_regs, true);
+
+ if (t == 0) {
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM1);
+ if (val32 & FPGA0_HSSI_PARM1_PI)
+ priv->pi_enabled = 1;
+ }
+
+ if (!priv->pi_enabled) {
+ /* Switch BB to PI mode to do IQ Calibration. */
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+ rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, 0x01000100);
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ val32 &= ~FPGA_RF_MODE_CCK;
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL);
+ val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT));
+ rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32);
+
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE);
+ val32 &= ~BIT(10);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32);
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE);
+ val32 &= ~BIT(10);
+ rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32);
+
+ if (priv->tx_paths > 1) {
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00010000);
+ rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, 0x00010000);
+ }
+
+ /* MAC settings */
+ rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup);
+
+ /* Page B init */
+ rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, 0x00080000);
+
+ if (priv->tx_paths > 1)
+ rtl8xxxu_write32(priv, REG_CONFIG_ANT_B, 0x00080000);
+
+ /* IQ calibration setting */
+ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ for (i = 0; i < retry; i++) {
+ path_a_ok = rtl8xxxu_iqk_path_a(priv);
+ if (path_a_ok == 0x03) {
+ val32 = rtl8xxxu_read32(priv,
+ REG_TX_POWER_BEFORE_IQK_A);
+ result[t][0] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv,
+ REG_TX_POWER_AFTER_IQK_A);
+ result[t][1] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv,
+ REG_RX_POWER_BEFORE_IQK_A_2);
+ result[t][2] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv,
+ REG_RX_POWER_AFTER_IQK_A_2);
+ result[t][3] = (val32 >> 16) & 0x3ff;
+ break;
+ } else if (i == (retry - 1) && path_a_ok == 0x01) {
+ /* TX IQK OK */
+ dev_dbg(dev, "%s: Path A IQK Only Tx Success!!\n",
+ __func__);
+
+ val32 = rtl8xxxu_read32(priv,
+ REG_TX_POWER_BEFORE_IQK_A);
+ result[t][0] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv,
+ REG_TX_POWER_AFTER_IQK_A);
+ result[t][1] = (val32 >> 16) & 0x3ff;
+ }
+ }
+
+ if (!path_a_ok)
+ dev_dbg(dev, "%s: Path A IQK failed!\n", __func__);
+
+ if (priv->tx_paths > 1) {
+ /*
+ * Path A into standby
+ */
+ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x0);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00010000);
+ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
+
+ /* Turn Path B ADDA on */
+ rtl8xxxu_path_adda_on(priv, adda_regs, false);
+
+ for (i = 0; i < retry; i++) {
+ path_b_ok = rtl8xxxu_iqk_path_b(priv);
+ if (path_b_ok == 0x03) {
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ result[t][4] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+ result[t][5] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
+ result[t][6] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
+ result[t][7] = (val32 >> 16) & 0x3ff;
+ break;
+ } else if (i == (retry - 1) && path_b_ok == 0x01) {
+ /* TX IQK OK */
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ result[t][4] = (val32 >> 16) & 0x3ff;
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+ result[t][5] = (val32 >> 16) & 0x3ff;
+ }
+ }
+
+ if (!path_b_ok)
+ dev_dbg(dev, "%s: Path B IQK failed!\n", __func__);
+ }
+
+ /* Back to BB mode, load original value */
+ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0);
+
+ if (t) {
+ if (!priv->pi_enabled) {
+ /*
+ * Switch back BB to SI mode after finishing
+ * IQ Calibration
+ */
+ val32 = 0x01000000;
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, val32);
+ rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, val32);
+ }
+
+ /* Reload ADDA power saving parameters */
+ rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup,
+ RTL8XXXU_ADDA_REGS);
+
+ /* Reload MAC parameters */
+ rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
+
+ /* Reload BB parameters */
+ rtl8xxxu_restore_regs(priv, iqk_bb_regs,
+ priv->bb_backup, RTL8XXXU_BB_REGS);
+
+ /* Restore RX initial gain */
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00032ed3);
+
+ if (priv->tx_paths > 1) {
+ rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM,
+ 0x00032ed3);
+ }
+
+ /* Load 0xe30 IQC default value */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00);
+ }
+}
+
+static void rtl8723a_phy_iq_calibrate(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ int result[4][8]; /* last is final result */
+ int i, candidate;
+ bool path_a_ok, path_b_ok;
+ u32 reg_e94, reg_e9c, reg_ea4, reg_eac;
+ u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+ s32 reg_tmp = 0;
+ bool simu;
+
+ memset(result, 0, sizeof(result));
+ candidate = -1;
+
+ path_a_ok = false;
+ path_b_ok = false;
+
+ rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+
+ for (i = 0; i < 3; i++) {
+ rtl8xxxu_phy_iqcalibrate(priv, result, i);
+
+ if (i == 1) {
+ simu = rtl8xxxu_simularity_compare(priv, result, 0, 1);
+ if (simu) {
+ candidate = 0;
+ break;
+ }
+ }
+
+ if (i == 2) {
+ simu = rtl8xxxu_simularity_compare(priv, result, 0, 2);
+ if (simu) {
+ candidate = 0;
+ break;
+ }
+
+ simu = rtl8xxxu_simularity_compare(priv, result, 1, 2);
+ if (simu) {
+ candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ reg_tmp += result[3][i];
+
+ if (reg_tmp)
+ candidate = 3;
+ else
+ candidate = -1;
+ }
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ reg_e94 = result[i][0];
+ reg_e9c = result[i][1];
+ reg_ea4 = result[i][2];
+ reg_eac = result[i][3];
+ reg_eb4 = result[i][4];
+ reg_ebc = result[i][5];
+ reg_ec4 = result[i][6];
+ reg_ecc = result[i][7];
+ }
+
+ if (candidate >= 0) {
+ reg_e94 = result[candidate][0];
+ priv->rege94 = reg_e94;
+ reg_e9c = result[candidate][1];
+ priv->rege9c = reg_e9c;
+ reg_ea4 = result[candidate][2];
+ reg_eac = result[candidate][3];
+ reg_eb4 = result[candidate][4];
+ priv->regeb4 = reg_eb4;
+ reg_ebc = result[candidate][5];
+ priv->regebc = reg_ebc;
+ reg_ec4 = result[candidate][6];
+ reg_ecc = result[candidate][7];
+ dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate);
+ dev_dbg(dev,
+ "%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x "
+ "ecc=%x\n ", __func__, reg_e94, reg_e9c,
+ reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc);
+ path_a_ok = true;
+ path_b_ok = true;
+ } else {
+ reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100;
+ reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0;
+ }
+
+ if (reg_e94 && candidate >= 0)
+ rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result,
+ candidate, (reg_ea4 == 0));
+
+ if (priv->tx_paths > 1 && reg_eb4)
+ rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result,
+ candidate, (reg_ec4 == 0));
+
+ rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg,
+ priv->bb_recovery_backup, RTL8XXXU_BB_REGS);
+}
+
+static void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+ u32 rf_amode, rf_bmode = 0, lstf;
+
+ /* Check continuous TX and Packet TX */
+ lstf = rtl8xxxu_read32(priv, REG_OFDM1_LSTF);
+
+ if (lstf & OFDM_LSTF_MASK) {
+ /* Disable all continuous TX */
+ val32 = lstf & ~OFDM_LSTF_MASK;
+ rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32);
+
+ /* Read original RF mode Path A */
+ rf_amode = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_AC);
+
+ /* Set RF mode to standby Path A */
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC,
+ (rf_amode & 0x8ffff) | 0x10000);
+
+ /* Path-B */
+ if (priv->tx_paths > 1) {
+ rf_bmode = rtl8xxxu_read_rfreg(priv, RF_B,
+ RF6052_REG_AC);
+
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC,
+ (rf_bmode & 0x8ffff) | 0x10000);
+ }
+ } else {
+ /* Deal with Packet TX case */
+ /* block all queues */
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+ }
+
+ /* Start LC calibration */
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
+ val32 |= 0x08000;
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
+
+ msleep(100);
+
+ /* Restore original parameters */
+ if (lstf & OFDM_LSTF_MASK) {
+ /* Path-A */
+ rtl8xxxu_write32(priv, REG_OFDM1_LSTF, lstf);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, rf_amode);
+
+ /* Path-B */
+ if (priv->tx_paths > 1)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC,
+ rf_bmode);
+ } else /* Deal with Packet TX case */
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
+}
+
+static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv)
+{
+ int i;
+ u16 reg;
+
+ reg = REG_MACID;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl8xxxu_write8(priv, reg + i, priv->mac_addr[i]);
+
+ return 0;
+}
+
+static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid)
+{
+ int i;
+ u16 reg;
+
+ dev_dbg(&priv->udev->dev, "%s: (%pM)\n", __func__, bssid);
+
+ reg = REG_BSSID;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl8xxxu_write8(priv, reg + i, bssid[i]);
+
+ return 0;
+}
+
+static void
+rtl8xxxu_set_ampdu_factor(struct rtl8xxxu_priv *priv, u8 ampdu_factor)
+{
+ u8 vals[4] = { 0x41, 0xa8, 0x72, 0xb9 };
+ u8 max_agg = 0xf;
+ int i;
+
+ ampdu_factor = 1 << (ampdu_factor + 2);
+ if (ampdu_factor > max_agg)
+ ampdu_factor = max_agg;
+
+ for (i = 0; i < 4; i++) {
+ if ((vals[i] & 0xf0) > (ampdu_factor << 4))
+ vals[i] = (vals[i] & 0x0f) | (ampdu_factor << 4);
+
+ if ((vals[i] & 0x0f) > ampdu_factor)
+ vals[i] = (vals[i] & 0xf0) | ampdu_factor;
+
+ rtl8xxxu_write8(priv, REG_AGGLEN_LMT + i, vals[i]);
+ }
+}
+
+static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density)
+{
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, REG_AMPDU_MIN_SPACE);
+ val8 &= 0xf8;
+ val8 |= density;
+ rtl8xxxu_write8(priv, REG_AMPDU_MIN_SPACE, val8);
+}
+
+static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ int count, ret;
+
+ /* Start of rtl8723AU_card_enable_flow */
+ /* Act to Cardemu sequence*/
+ /* Turn off RF */
+ rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
+
+ /* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */
+ val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
+ val8 &= ~LEDCFG2_DPDT_SELECT;
+ rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
+
+ /* 0x0005[1] = 1 turn off MAC by HW state machine*/
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 |= BIT(1);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ if ((val8 & BIT(1)) == 0)
+ break;
+ udelay(10);
+ }
+
+ if (!count) {
+ dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
+ __func__);
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */
+ val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
+ val8 |= SYS_ISO_ANALOG_IPS;
+ rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
+
+ /* 0x0020[0] = 0 disable LDOA12 MACRO block*/
+ val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL);
+ val8 &= ~LDOA15_ENABLE;
+ rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8);
+
+exit:
+ return ret;
+}
+
+static int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ u8 val32;
+ int count, ret;
+
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+
+ /*
+ * Poll - wait for RX packet to complete
+ */
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, 0x5f8);
+ if (!val32)
+ break;
+ udelay(10);
+ }
+
+ if (!count) {
+ dev_warn(&priv->udev->dev,
+ "%s: RX poll timed out (0x05f8)\n", __func__);
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ /* Disable CCK and OFDM, clock gated */
+ val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
+ val8 &= ~SYS_FUNC_BBRSTB;
+ rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
+
+ udelay(2);
+
+ /* Reset baseband */
+ val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
+ val8 &= ~SYS_FUNC_BB_GLB_RSTN;
+ rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
+
+ /* Reset MAC TRX */
+ val8 = rtl8xxxu_read8(priv, REG_CR);
+ val8 = CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE;
+ rtl8xxxu_write8(priv, REG_CR, val8);
+
+ /* Reset MAC TRX */
+ val8 = rtl8xxxu_read8(priv, REG_CR + 1);
+ val8 &= ~BIT(1); /* CR_SECURITY_ENABLE */
+ rtl8xxxu_write8(priv, REG_CR + 1, val8);
+
+ /* Respond TX OK to scheduler */
+ val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
+ val8 |= DUAL_TSF_TX_OK;
+ rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
+
+exit:
+ return ret;
+}
+
+static void rtl8xxxu_disabled_to_emu(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+
+ /* Clear suspend enable and power down enable*/
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 &= ~(BIT(3) | BIT(7));
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ /* 0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/
+ val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2);
+ val8 &= ~BIT(0);
+ rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8);
+
+ /* 0x04[12:11] = 11 enable WL suspend*/
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 &= ~(BIT(3) | BIT(4));
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+}
+
+static int rtl8xxxu_emu_to_active(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ u32 val32;
+ int count, ret = 0;
+
+ /* 0x20[0] = 1 enable LDOA12 MACRO block for all interface*/
+ val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL);
+ val8 |= LDOA15_ENABLE;
+ rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8);
+
+ /* 0x67[0] = 0 to disable BT_GPS_SEL pins*/
+ val8 = rtl8xxxu_read8(priv, 0x0067);
+ val8 &= ~BIT(4);
+ rtl8xxxu_write8(priv, 0x0067, val8);
+
+ mdelay(1);
+
+ /* 0x00[5] = 0 release analog Ips to digital, 1:isolation */
+ val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
+ val8 &= ~SYS_ISO_ANALOG_IPS;
+ rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
+
+ /* disable SW LPS 0x04[10]= 0 */
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 &= ~BIT(2);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ /* wait till 0x04[17] = 1 power ready*/
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if (val32 & BIT(17))
+ break;
+
+ udelay(10);
+ }
+
+ if (!count) {
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ /* We should be able to optimize the following three entries into one */
+
+ /* release WLON reset 0x04[16]= 1*/
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
+ val8 |= BIT(0);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
+
+ /* disable HWPDN 0x04[15]= 0*/
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 &= ~BIT(7);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ /* disable WL suspend*/
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 &= ~(BIT(3) | BIT(4));
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ /* set, then poll until 0 */
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ val32 |= APS_FSMCO_MAC_ENABLE;
+ rtl8xxxu_write32(priv, REG_APS_FSMCO, val32);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) {
+ ret = 0;
+ break;
+ }
+ udelay(10);
+ }
+
+ if (!count) {
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ /* 0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */
+ /*
+ * Note: Vendor driver actually clears this bit, despite the
+ * documentation claims it's being set!
+ */
+ val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
+ val8 |= LEDCFG2_DPDT_SELECT;
+ val8 &= ~LEDCFG2_DPDT_SELECT;
+ rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
+
+exit:
+ return ret;
+}
+
+static int rtl8xxxu_emu_to_disabled(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+
+ /* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20);
+
+ /* 0x04[12:11] = 01 enable WL suspend */
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 &= ~BIT(4);
+ val8 |= BIT(3);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
+ val8 |= BIT(7);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
+
+ /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */
+ val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2);
+ val8 |= BIT(0);
+ rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8);
+
+ return 0;
+}
+
+static int rtl8723au_power_on(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ int ret;
+
+ /*
+ * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
+ */
+ rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
+
+ rtl8xxxu_disabled_to_emu(priv);
+
+ ret = rtl8xxxu_emu_to_active(priv);
+ if (ret)
+ goto exit;
+
+ /*
+ * 0x0004[19] = 1, reset 8051
+ */
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
+ val8 |= BIT(3);
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
+
+ /*
+ * Enable MAC DMA/WMAC/SCHEDULE/SEC block
+ * Set CR bit10 to enable 32k calibration.
+ */
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
+ CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
+ CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
+ CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE |
+ CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE);
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ /* For EFuse PG */
+ val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL);
+ val32 &= ~(BIT(28) | BIT(29) | BIT(30));
+ val32 |= (0x06 << 28);
+ rtl8xxxu_write32(priv, REG_EFUSE_CTRL, val32);
+exit:
+ return ret;
+}
+
+#ifdef CONFIG_RTL8XXXU_UNTESTED
+
+static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ int i;
+
+ for (i = 100; i; i--) {
+ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO);
+ if (val8 & APS_FSMCO_PFM_ALDN)
+ break;
+ }
+
+ if (!i) {
+ pr_info("%s: Poll failed\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
+ */
+ rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
+ rtl8xxxu_write8(priv, REG_SPS0_CTRL, 0x2b);
+ udelay(100);
+
+ val8 = rtl8xxxu_read8(priv, REG_LDOV12D_CTRL);
+ if (!(val8 & LDOV12D_ENABLE)) {
+ pr_info("%s: Enabling LDOV12D (%02x)\n", __func__, val8);
+ val8 |= LDOV12D_ENABLE;
+ rtl8xxxu_write8(priv, REG_LDOV12D_CTRL, val8);
+
+ udelay(100);
+
+ val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
+ val8 &= ~SYS_ISO_MD2PP;
+ rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
+ }
+
+ /*
+ * Auto enable WLAN
+ */
+ val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
+ val16 |= APS_FSMCO_MAC_ENABLE;
+ rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
+
+ for (i = 1000; i; i--) {
+ val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
+ if (!(val16 & APS_FSMCO_MAC_ENABLE))
+ break;
+ }
+ if (!i) {
+ pr_info("%s: FSMCO_MAC_ENABLE poll failed\n", __func__);
+ return -EBUSY;
+ }
+
+ /*
+ * Enable radio, GPIO, LED
+ */
+ val16 = APS_FSMCO_HW_SUSPEND | APS_FSMCO_ENABLE_POWERDOWN |
+ APS_FSMCO_PFM_ALDN;
+ rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
+
+ /*
+ * Release RF digital isolation
+ */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL);
+ val16 &= ~SYS_ISO_DIOR;
+ rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16);
+
+ val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
+ val8 &= ~APSD_CTRL_OFF;
+ rtl8xxxu_write8(priv, REG_APSD_CTRL, val8);
+ for (i = 200; i; i--) {
+ val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
+ if (!(val8 & APSD_CTRL_OFF_STATUS))
+ break;
+ }
+
+ if (!i) {
+ pr_info("%s: APSD_CTRL poll failed\n", __func__);
+ return -EBUSY;
+ }
+
+ /*
+ * Enable MAC DMA/WMAC/SCHEDULE/SEC block
+ */
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
+ CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | CR_PROTOCOL_ENABLE |
+ CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE;
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ /*
+ * Workaround for 8188RU LNA power leakage problem.
+ */
+ if (priv->rtlchip == 0x8188c && priv->hi_pa) {
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM);
+ val32 &= ~BIT(1);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32);
+ }
+ return 0;
+}
+
+#endif
+
+static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+ u16 val16;
+ u32 val32;
+
+ /*
+ * Workaround for 8188RU LNA power leakage problem.
+ */
+ if (priv->rtlchip == 0x8188c && priv->hi_pa) {
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM);
+ val32 |= BIT(1);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32);
+ }
+
+ rtl8xxxu_active_to_lps(priv);
+
+ /* Turn off RF */
+ rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
+
+ /* Reset Firmware if running in RAM */
+ if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
+ rtl8xxxu_firmware_self_reset(priv);
+
+ /* Reset MCU */
+ val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
+ val16 &= ~SYS_FUNC_CPU_ENABLE;
+ rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
+
+ /* Reset MCU ready status */
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
+
+ rtl8xxxu_active_to_emu(priv);
+ rtl8xxxu_emu_to_disabled(priv);
+
+ /* Reset MCU IO Wrapper */
+ val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
+ val8 &= ~BIT(0);
+ rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
+
+ val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
+ val8 |= BIT(0);
+ rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
+
+ /* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */
+ rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e);
+}
+
+static void rtl8xxxu_init_bt(struct rtl8xxxu_priv *priv)
+{
+ if (!priv->has_bluetooth)
+ return;
+}
+
+static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ struct rtl8xxxu_rfregval *rftable;
+ bool macpower;
+ int ret;
+ u8 val8;
+ u16 val16;
+ u32 val32;
+
+ /* Check if MAC is already powered on */
+ val8 = rtl8xxxu_read8(priv, REG_CR);
+
+ /*
+ * Fix 92DU-VC S3 hang with the reason is that secondary mac is not
+ * initialized. First MAC returns 0xea, second MAC returns 0x00
+ */
+ if (val8 == 0xea)
+ macpower = false;
+ else
+ macpower = true;
+
+ ret = priv->fops->power_on(priv);
+ if (ret < 0) {
+ dev_warn(dev, "%s: Failed power on\n", __func__);
+ goto exit;
+ }
+
+ dev_dbg(dev, "%s: macpower %i\n", __func__, macpower);
+ if (!macpower) {
+ ret = rtl8xxxu_init_llt_table(priv, TX_TOTAL_PAGE_NUM);
+ if (ret) {
+ dev_warn(dev, "%s: LLT table init failed\n", __func__);
+ goto exit;
+ }
+ }
+
+ ret = rtl8xxxu_download_firmware(priv);
+ dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret);
+ if (ret)
+ goto exit;
+ ret = rtl8xxxu_start_firmware(priv);
+ dev_dbg(dev, "%s: start_fiwmare %i\n", __func__, ret);
+ if (ret)
+ goto exit;
+
+ ret = rtl8xxxu_init_mac(priv, rtl8723a_mac_init_table);
+ dev_dbg(dev, "%s: init_mac %i\n", __func__, ret);
+ if (ret)
+ goto exit;
+
+ ret = rtl8xxxu_init_phy_bb(priv);
+ dev_dbg(dev, "%s: init_phy_bb %i\n", __func__, ret);
+ if (ret)
+ goto exit;
+
+ switch(priv->rtlchip) {
+ case 0x8723a:
+ rftable = rtl8723au_radioa_1t_init_table;
+ ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
+ break;
+ case 0x8188c:
+ if (priv->hi_pa)
+ rftable = rtl8188ru_radioa_1t_highpa_table;
+ else
+ rftable = rtl8192cu_radioa_1t_init_table;
+ ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
+ break;
+ case 0x8191c:
+ rftable = rtl8192cu_radioa_1t_init_table;
+ ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
+ break;
+ case 0x8192c:
+ rftable = rtl8192cu_radioa_2t_init_table;
+ ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
+ if (ret)
+ break;
+ rftable = rtl8192cu_radiob_2t_init_table;
+ ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ goto exit;
+
+ /* Reduce 80M spur */
+ rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d);
+ rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83);
+ rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82);
+ rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83);
+
+ /* RFSW Control - clear bit 14 ?? */
+ rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003);
+ /* 0x07000760 */
+ val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW |
+ FPGA0_RF_ANTSWB | FPGA0_RF_PAPE |
+ ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) <<
+ FPGA0_RF_BD_CTRL_SHIFT);
+ rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32);
+ /* 0x860[6:5]= 00 - why? - this sets antenna B */
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66F60210);
+
+ priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A,
+ RF6052_REG_MODE_AG);
+
+ dev_dbg(dev, "%s: macpower %i\n", __func__, macpower);
+ if (!macpower) {
+ if (priv->ep_tx_normal_queue)
+ val8 = TX_PAGE_NUM_NORM_PQ;
+ else
+ val8 = 0;
+
+ rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8);
+
+ val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD;
+
+ if (priv->ep_tx_high_queue)
+ val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT);
+ if (priv->ep_tx_low_queue)
+ val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT);
+
+ rtl8xxxu_write32(priv, REG_RQPN, val32);
+
+ /*
+ * Set TX buffer boundary
+ */
+ val8 = TX_TOTAL_PAGE_NUM + 1;
+ rtl8xxxu_write8(priv, REG_TXPKTBUF_BCNQ_BDNY, val8);
+ rtl8xxxu_write8(priv, REG_TXPKTBUF_MGQ_BDNY, val8);
+ rtl8xxxu_write8(priv, REG_TXPKTBUF_WMAC_LBK_BF_HD, val8);
+ rtl8xxxu_write8(priv, REG_TRXFF_BNDY, val8);
+ rtl8xxxu_write8(priv, REG_TDECTRL + 1, val8);
+ }
+
+ ret = rtl8xxxu_init_queue_priority(priv);
+ dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret);
+ if (ret)
+ goto exit;
+
+ /*
+ * Set RX page boundary
+ */
+ rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff);
+ /*
+ * Transfer page size is always 128
+ */
+ val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) |
+ (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT);
+ rtl8xxxu_write8(priv, REG_PBP, val8);
+
+ /*
+ * Unit in 8 bytes, not obvious what it is used for
+ */
+ rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, 4);
+
+ /*
+ * Enable all interrupts - not obvious USB needs to do this
+ */
+ rtl8xxxu_write32(priv, REG_HISR, 0xffffffff);
+ rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff);
+
+ rtl8xxxu_set_mac(priv);
+ rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION);
+
+ /*
+ * Configure initial WMAC settings
+ */
+ val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST |
+ /* RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON | */
+ RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL |
+ RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC;
+ rtl8xxxu_write32(priv, REG_RCR, val32);
+
+ /*
+ * Accept all multicast
+ */
+ rtl8xxxu_write32(priv, REG_MAR, 0xffffffff);
+ rtl8xxxu_write32(priv, REG_MAR + 4, 0xffffffff);
+
+ /*
+ * Init adaptive controls
+ */
+ val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET);
+ val32 &= ~RESPONSE_RATE_BITMAP_ALL;
+ val32 |= RESPONSE_RATE_RRSR_CCK_ONLY_1M;
+ rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32);
+
+ /* CCK = 0x0a, OFDM = 0x10 */
+ rtl8xxxu_set_spec_sifs(priv, 0x10, 0x10);
+ rtl8xxxu_set_retry(priv, 0x30, 0x30);
+ rtl8xxxu_set_spec_sifs(priv, 0x0a, 0x10);
+
+ /*
+ * Init EDCA
+ */
+ rtl8xxxu_write16(priv, REG_MAC_SPEC_SIFS, 0x100a);
+
+ /* Set CCK SIFS */
+ rtl8xxxu_write16(priv, REG_SIFS_CCK, 0x100a);
+
+ /* Set OFDM SIFS */
+ rtl8xxxu_write16(priv, REG_SIFS_OFDM, 0x100a);
+
+ /* TXOP */
+ rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, 0x005ea42b);
+ rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, 0x0000a44f);
+ rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, 0x005ea324);
+ rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, 0x002fa226);
+
+ /* Set data auto rate fallback retry count */
+ rtl8xxxu_write32(priv, REG_DARFRC, 0x00000000);
+ rtl8xxxu_write32(priv, REG_DARFRC + 4, 0x10080404);
+ rtl8xxxu_write32(priv, REG_RARFRC, 0x04030201);
+ rtl8xxxu_write32(priv, REG_RARFRC + 4, 0x08070605);
+
+ val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL);
+ val8 |= FWHW_TXQ_CTRL_AMPDU_RETRY;
+ rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, val8);
+
+ /* Set ACK timeout */
+ rtl8xxxu_write8(priv, REG_ACKTO, 0x40);
+
+ /*
+ * Initialize beacon parameters
+ */
+ val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8);
+ rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16);
+ rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404);
+ rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME);
+ rtl8xxxu_write8(priv, REG_BEACON_DMA_TIME, BEACON_DMA_ATIME_INT_TIME);
+ rtl8xxxu_write16(priv, REG_BEACON_TCFG, 0x660F);
+
+ /*
+ * Enable CCK and OFDM block
+ */
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ val32 |= (FPGA_RF_MODE_CCK | FPGA_RF_MODE_OFDM);
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+
+ /*
+ * Invalidate all CAM entries - bit 30 is undocumented
+ */
+ rtl8xxxu_write32(priv, REG_CAM_CMD, CAM_CMD_POLLING | BIT(30));
+
+ /*
+ * Start out with default power levels for channel 6, 20MHz
+ */
+ rtl8723a_set_tx_power(priv, 1, false);
+
+ /* Let the 8051 take control of antenna setting */
+ val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
+ val8 |= LEDCFG2_DPDT_SELECT;
+ rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
+
+ rtl8xxxu_write8(priv, REG_HWSEQ_CTRL, 0xff);
+
+ /* Disable BAR - not sure if this has any effect on USB */
+ rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff);
+
+ rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0);
+
+ /*
+ * Not sure if we should get into this at all
+ */
+ if (priv->iqk_initialized) {
+ rtl8xxxu_restore_regs(priv, rtl8723au_iqk_phy_iq_bb_reg,
+ priv->bb_recovery_backup,
+ RTL8XXXU_BB_REGS);
+ } else {
+ rtl8723a_phy_iq_calibrate(priv);
+ priv->iqk_initialized = true;
+ }
+
+ /*
+ * This should enable thermal meter
+ */
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_T_METER, 0x60);
+
+ rtl8723a_phy_lc_calibrate(priv);
+
+ /* fix USB interface interference issue */
+ rtl8xxxu_write8(priv, 0xfe40, 0xe0);
+ rtl8xxxu_write8(priv, 0xfe41, 0x8d);
+ rtl8xxxu_write8(priv, 0xfe42, 0x80);
+ rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320);
+
+ /* Solve too many protocol error on USB bus */
+ /* Can't do this for 8188/8192 UMC A cut parts */
+ rtl8xxxu_write8(priv, 0xfe40, 0xe6);
+ rtl8xxxu_write8(priv, 0xfe41, 0x94);
+ rtl8xxxu_write8(priv, 0xfe42, 0x80);
+
+ rtl8xxxu_write8(priv, 0xfe40, 0xe0);
+ rtl8xxxu_write8(priv, 0xfe41, 0x19);
+ rtl8xxxu_write8(priv, 0xfe42, 0x80);
+
+ rtl8xxxu_write8(priv, 0xfe40, 0xe5);
+ rtl8xxxu_write8(priv, 0xfe41, 0x91);
+ rtl8xxxu_write8(priv, 0xfe42, 0x80);
+
+ rtl8xxxu_write8(priv, 0xfe40, 0xe2);
+ rtl8xxxu_write8(priv, 0xfe41, 0x81);
+ rtl8xxxu_write8(priv, 0xfe42, 0x80);
+
+ /* Init BT hw config. */
+ rtl8xxxu_init_bt(priv);
+
+ /*
+ * Not sure if we really need to save these parameters, but the
+ * vendor driver does
+ */
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2);
+ if (val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR)
+ priv->path_a_hi_power = 1;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ priv->path_a_rf_paths = val32 & OFDM_RF_PATH_RX_MASK;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
+ priv->path_a_ig_value = val32 & OFDM0_X_AGC_CORE1_IGI_MASK;
+
+ /* Set NAV_UPPER to 30000us */
+ val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT);
+ rtl8xxxu_write8(priv, REG_NAV_UPPER, val8);
+
+ /*
+ * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test,
+ * but we need to fin root cause.
+ */
+ val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
+ if ((val32 & 0xff000000) != 0x83000000) {
+ val32 |= FPGA_RF_MODE_CCK;
+ rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL);
+ val32 |= FWHW_TXQ_CTRL_XMIT_MGMT_ACK;
+ /* ack for xmit mgmt frames. */
+ rtl8xxxu_write32(priv, REG_FWHW_TXQ_CTRL, val32);
+
+exit:
+ return ret;
+}
+
+static void rtl8xxxu_disable_device(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ rtl8xxxu_power_off(priv);
+}
+
+static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv,
+ struct ieee80211_key_conf *key, const u8 *mac)
+{
+ u32 cmd, val32, addr, ctrl;
+ int j, i, tmp_debug;
+
+ tmp_debug = rtl8xxxu_debug;
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_KEY)
+ rtl8xxxu_debug |= RTL8XXXU_DEBUG_REG_WRITE;
+
+ /*
+ * This is a bit of a hack - the lower bits of the cipher
+ * suite selector happens to match the cipher index in the CAM
+ */
+ addr = key->keyidx << CAM_CMD_KEY_SHIFT;
+ ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID;
+
+ for (j = 5; j >= 0; j--) {
+ switch (j) {
+ case 0:
+ val32 = ctrl | (mac[0] << 16) | (mac[1] << 24);
+ break;
+ case 1:
+ val32 = mac[2] | (mac[3] << 8) |
+ (mac[4] << 16) | (mac[5] << 24);
+ break;
+ default:
+ i = (j - 2) << 2;
+ val32 = key->key[i] | (key->key[i + 1] << 8) |
+ key->key[i + 2] << 16 | key->key[i + 3] << 24;
+ break;
+ }
+
+ rtl8xxxu_write32(priv, REG_CAM_WRITE, val32);
+ cmd = CAM_CMD_POLLING | CAM_CMD_WRITE | (addr + j);
+ rtl8xxxu_write32(priv, REG_CAM_CMD, cmd);
+ udelay(100);
+ }
+
+ rtl8xxxu_debug = tmp_debug;
+}
+
+static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, const u8* mac)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
+ val8 |= BEACON_DISABLE_TSF_UPDATE;
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
+}
+
+static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
+ val8 &= ~BEACON_DISABLE_TSF_UPDATE;
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
+}
+
+static void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
+ u32 ramask, int sgi)
+{
+ struct h2c_cmd h2c;
+
+ h2c.ramask.cmd = H2C_SET_RATE_MASK;
+ h2c.ramask.mask_lo = cpu_to_le16(ramask & 0xffff);
+ h2c.ramask.mask_hi = cpu_to_le16(ramask >> 16);
+
+ h2c.ramask.arg = 0x80;
+ if (sgi)
+ h2c.ramask.arg |= 0x20;
+
+ dev_dbg(&priv->udev->dev, "%s: rate mask %08x, arg %02x\n", __func__,
+ ramask, h2c.ramask.arg);
+ rtl8723a_h2c_cmd(priv, &h2c);
+}
+
+static void rtl8xxxu_set_basic_rates(struct rtl8xxxu_priv *priv, u32 rate_cfg)
+{
+ u32 val32;
+ u8 rate_idx = 0;
+
+ rate_cfg &= RESPONSE_RATE_BITMAP_ALL;
+
+ val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET);
+ val32 &= ~RESPONSE_RATE_BITMAP_ALL;
+ val32 |= rate_cfg;
+ rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32);
+
+ dev_dbg(&priv->udev->dev, "%s: rates %08x\n", __func__, rate_cfg);
+
+ while (rate_cfg) {
+ rate_cfg = (rate_cfg >> 1);
+ rate_idx++;
+ }
+ rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx);
+}
+
+static void
+rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf, u32 changed)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ struct ieee80211_sta *sta;
+ u32 val32;
+ u8 val8;
+
+ if (changed & BSS_CHANGED_ASSOC) {
+ struct h2c_cmd h2c;
+
+ dev_dbg(dev, "Changed ASSOC: %i!\n", bss_conf->assoc);
+
+ memset(&h2c, 0, sizeof(struct h2c_cmd));
+ rtl8xxxu_set_linktype(priv, vif->type);
+
+ if (bss_conf->assoc) {
+ u32 ramask;
+ int sgi = 0;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(vif, bss_conf->bssid);
+ if (!sta) {
+ dev_info(dev, "%s: ASSOC no sta found\n",
+ __func__);
+ rcu_read_unlock();
+ goto error;
+ }
+
+ if (sta->ht_cap.ht_supported)
+ dev_info(dev, "%s: HT supported\n", __func__);
+ if (sta->vht_cap.vht_supported)
+ dev_info(dev, "%s: VHT supported\n", __func__);
+
+ /* TODO: Set bits 28-31 for rate adaptive id */
+ ramask = (sta->supp_rates[0] & 0xfff) |
+ sta->ht_cap.mcs.rx_mask[0] << 12 |
+ sta->ht_cap.mcs.rx_mask[1] << 20;
+ if (sta->ht_cap.cap &
+ (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))
+ sgi = 1;
+ rcu_read_unlock();
+
+ rtl8xxxu_update_rate_mask(priv, ramask, sgi);
+
+ val32 = rtl8xxxu_read32(priv, REG_RCR);
+ val32 |= RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON;
+ rtl8xxxu_write32(priv, REG_RCR, val32);
+
+ /* Enable RX of data frames */
+ rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
+
+ rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
+
+ rtl8723a_stop_tx_beacon(priv);
+
+ /* joinbss sequence */
+ rtl8xxxu_write16(priv, REG_BCN_PSR_RPT,
+ 0xc000 | bss_conf->aid);
+
+ h2c.joinbss.data = H2C_JOIN_BSS_CONNECT;
+ } else {
+ val32 = rtl8xxxu_read32(priv, REG_RCR);
+ val32 &= ~(RCR_CHECK_BSSID_MATCH |
+ RCR_CHECK_BSSID_BEACON);
+ rtl8xxxu_write32(priv, REG_RCR, val32);
+
+ val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
+ val8 |= BEACON_DISABLE_TSF_UPDATE;
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
+
+ /* Disable RX of data frames */
+ rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000);
+ h2c.joinbss.data = H2C_JOIN_BSS_DISCONNECT;
+ }
+ h2c.joinbss.cmd = H2C_JOIN_BSS_REPORT;
+ rtl8723a_h2c_cmd(priv, &h2c);
+ }
+
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ dev_dbg(dev, "Changed ERP_PREAMBLE: Use short preamble %i\n",
+ bss_conf->use_short_preamble);
+ val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET);
+ if (bss_conf->use_short_preamble)
+ val32 |= RSR_ACK_SHORT_PREAMBLE;
+ else
+ val32 &= ~RSR_ACK_SHORT_PREAMBLE;
+ rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32);
+ }
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ dev_dbg(dev, "Changed ERP_SLOT: short_slot_time %i\n",
+ bss_conf->use_short_slot);
+
+ if (bss_conf->use_short_slot)
+ val8 = 9;
+ else
+ val8 = 20;
+ rtl8xxxu_write8(priv, REG_SLOT, val8);
+ }
+
+ if (changed & BSS_CHANGED_BSSID) {
+ dev_dbg(dev, "Changed BSSID!\n");
+ rtl8xxxu_set_bssid(priv, bss_conf->bssid);
+ }
+
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ dev_dbg(dev, "Changed BASIC_RATES!\n");
+ rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates);
+ }
+error:
+ return;
+}
+
+static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue)
+{
+ u32 rtlqueue;
+
+ switch (queue) {
+ case IEEE80211_AC_VO:
+ rtlqueue = TXDESC_QUEUE_VO;
+ break;
+ case IEEE80211_AC_VI:
+ rtlqueue = TXDESC_QUEUE_VI;
+ break;
+ case IEEE80211_AC_BE:
+ rtlqueue = TXDESC_QUEUE_BE;
+ break;
+ case IEEE80211_AC_BK:
+ rtlqueue = TXDESC_QUEUE_BK;
+ break;
+ default:
+ rtlqueue = TXDESC_QUEUE_BE;
+ }
+
+ return rtlqueue;
+}
+
+static u32 rtl8xxxu_queue_select(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ u32 queue;
+
+ if (ieee80211_is_mgmt(hdr->frame_control))
+ queue = TXDESC_QUEUE_MGNT;
+ else
+ queue = rtl8xxxu_80211_to_rtl_queue(skb_get_queue_mapping(skb));
+
+ return queue;
+}
+
+static void rtl8xxxu_calc_tx_desc_csum(struct rtl8xxxu_tx_desc *tx_desc)
+{
+ __le16 *ptr = (__le16 *)tx_desc;
+ u16 csum = 0;
+ int i;
+
+ /*
+ * Clear csum field before calculation, as the csum field is
+ * in the middle of the struct.
+ */
+ tx_desc->csum = cpu_to_le16(0);
+
+ for (i = 0; i < (sizeof(struct rtl8xxxu_tx_desc) / sizeof(u16)); i++)
+ csum = csum ^ le16_to_cpu(ptr[i]);
+
+ tx_desc->csum |= cpu_to_le16(csum);
+}
+
+static void rtl8xxxu_free_tx_resources(struct rtl8xxxu_priv *priv)
+{
+ struct rtl8xxxu_tx_urb *tx_urb, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_urb_lock, flags);
+ list_for_each_entry_safe(tx_urb, tmp, &priv->tx_urb_free_list, list) {
+ list_del(&tx_urb->list);
+ priv->tx_urb_free_count--;
+ usb_free_urb(&tx_urb->urb);
+ }
+ spin_unlock_irqrestore(&priv->tx_urb_lock, flags);
+}
+
+static struct rtl8xxxu_tx_urb *
+rtl8xxxu_alloc_tx_urb(struct rtl8xxxu_priv *priv)
+{
+ struct rtl8xxxu_tx_urb *tx_urb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_urb_lock, flags);
+ tx_urb = list_first_entry_or_null(&priv->tx_urb_free_list,
+ struct rtl8xxxu_tx_urb, list);
+ if (tx_urb) {
+ list_del(&tx_urb->list);
+ priv->tx_urb_free_count--;
+ if (priv->tx_urb_free_count < RTL8XXXU_TX_URB_LOW_WATER &&
+ !priv->tx_stopped) {
+ priv->tx_stopped = true;
+ ieee80211_stop_queues(priv->hw);
+ }
+ }
+
+ spin_unlock_irqrestore(&priv->tx_urb_lock, flags);
+
+ return tx_urb;
+}
+
+static void rtl8xxxu_free_tx_urb(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_tx_urb *tx_urb)
+{
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&tx_urb->list);
+
+ spin_lock_irqsave(&priv->tx_urb_lock, flags);
+
+ list_add(&tx_urb->list, &priv->tx_urb_free_list);
+ priv->tx_urb_free_count++;
+ if (priv->tx_urb_free_count > RTL8XXXU_TX_URB_HIGH_WATER &&
+ priv->tx_stopped) {
+ priv->tx_stopped = false;
+ ieee80211_wake_queues(priv->hw);
+ }
+
+ spin_unlock_irqrestore(&priv->tx_urb_lock, flags);
+}
+
+static void rtl8xxxu_tx_complete(struct urb *urb)
+{
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_hw *hw;
+ struct rtl8xxxu_tx_urb *tx_urb =
+ container_of(urb, struct rtl8xxxu_tx_urb, urb);
+
+ tx_info = IEEE80211_SKB_CB(skb);
+ hw = tx_info->rate_driver_data[0];
+
+ skb_pull(skb, sizeof(struct rtl8xxxu_tx_desc));
+
+ ieee80211_tx_info_clear_status(tx_info);
+ tx_info->status.rates[0].idx = -1;
+ tx_info->status.rates[0].count = 0;
+
+ if (!urb->status)
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+
+ ieee80211_tx_status_irqsafe(hw, skb);
+
+ rtl8xxxu_free_tx_urb(hw->priv, tx_urb);
+}
+
+static void rtl8xxxu_dump_action(struct device *dev,
+ struct ieee80211_hdr *hdr)
+{
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr;
+ u16 cap, timeout;
+
+ if (!(rtl8xxxu_debug & RTL8XXXU_DEBUG_ACTION))
+ return;
+
+ switch (mgmt->u.action.u.addba_resp.action_code) {
+ case WLAN_ACTION_ADDBA_RESP:
+ cap = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
+ timeout = le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
+ dev_info(dev, "WLAN_ACTION_ADDBA_RESP: "
+ "timeout %i, tid %02x, buf_size %02x, policy %02x, "
+ "status %02x\n",
+ timeout,
+ (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2,
+ (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6,
+ (cap >> 1) & 0x1,
+ le16_to_cpu(mgmt->u.action.u.addba_resp.status));
+ break;
+ case WLAN_ACTION_ADDBA_REQ:
+ cap = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
+ dev_info(dev, "WLAN_ACTION_ADDBA_REQ: "
+ "timeout %i, tid %02x, buf_size %02x, policy %02x\n",
+ timeout,
+ (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2,
+ (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6,
+ (cap >> 1) & 0x1);
+ break;
+ default:
+ dev_info(dev, "action frame %02x\n",
+ mgmt->u.action.u.addba_resp.action_code);
+ break;
+ }
+}
+
+static void rtl8xxxu_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 *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct rtl8xxxu_tx_desc *tx_desc;
+ struct rtl8xxxu_tx_urb *tx_urb;
+ struct ieee80211_sta *sta = NULL;
+ struct ieee80211_vif *vif = tx_info->control.vif;
+ struct device *dev = &priv->udev->dev;
+ u32 queue, rate;
+ u16 pktlen = skb->len;
+ u16 seq_number;
+ u16 rate_flag = tx_info->control.rates[0].flags;
+ int ret;
+
+ if (skb_headroom(skb) < sizeof(struct rtl8xxxu_tx_desc)) {
+ dev_warn(dev,
+ "%s: Not enough headroom (%i) for tx descriptor\n",
+ __func__, skb_headroom(skb));
+ goto error;
+ }
+
+ if (unlikely(skb->len > (65535 - sizeof(struct rtl8xxxu_tx_desc)))) {
+ dev_warn(dev, "%s: Trying to send over-sized skb (%i)\n",
+ __func__, skb->len);
+ goto error;
+ }
+
+ tx_urb = rtl8xxxu_alloc_tx_urb(priv);
+ if (!tx_urb) {
+ dev_warn(dev, "%s: Unable to allocate tx urb\n", __func__);
+ goto error;
+ }
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
+ dev_info(dev, "%s: TX rate: %d (%d), pkt size %d\n",
+ __func__, tx_rate->bitrate, tx_rate->hw_value, pktlen);
+
+ if (ieee80211_is_action(hdr->frame_control))
+ rtl8xxxu_dump_action(dev, hdr);
+
+ tx_info->rate_driver_data[0] = hw;
+
+ if (control && control->sta)
+ sta = control->sta;
+
+ tx_desc = (struct rtl8xxxu_tx_desc *)
+ skb_push(skb, sizeof(struct rtl8xxxu_tx_desc));
+
+ memset(tx_desc, 0, sizeof(struct rtl8xxxu_tx_desc));
+ tx_desc->pkt_size = cpu_to_le16(pktlen);
+ tx_desc->pkt_offset = sizeof(struct rtl8xxxu_tx_desc);
+
+ tx_desc->txdw0 =
+ TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
+ if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
+ is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
+ tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
+
+ queue = rtl8xxxu_queue_select(hw, skb);
+ tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT);
+
+ if (tx_info->control.hw_key) {
+ switch (tx_info->control.hw_key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_RC4);
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_AES);
+ break;
+ default:
+ break;
+ }
+ }
+
+ seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+ tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC_SEQ_SHIFT);
+
+ if (rate_flag & IEEE80211_TX_RC_MCS)
+ rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
+ else
+ rate = tx_rate->hw_value;
+ tx_desc->txdw5 = cpu_to_le32(rate);
+
+ if (ieee80211_is_data(hdr->frame_control))
+ tx_desc->txdw5 |= cpu_to_le32(0x0001ff00);
+
+ /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */
+ if (ieee80211_is_data_qos(hdr->frame_control) && sta) {
+ if (sta->ht_cap.ht_supported) {
+ u32 ampdu, val32;
+
+ ampdu = (u32)sta->ht_cap.ampdu_density;
+ val32 = ampdu << TXDESC_AMPDU_DENSITY_SHIFT;
+ tx_desc->txdw2 |= cpu_to_le32(val32);
+ tx_desc->txdw1 |= cpu_to_le32(TXDESC_AGG_ENABLE);
+ } else
+ tx_desc->txdw1 |= cpu_to_le32(TXDESC_BK);
+ } else
+ tx_desc->txdw1 |= cpu_to_le32(TXDESC_BK);
+
+ if (ieee80211_is_data_qos(hdr->frame_control))
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC_QOS);
+ if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ||
+ (sta && vif && vif->bss_conf.use_short_preamble))
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC_SHORT_PREAMBLE);
+ if (rate_flag & IEEE80211_TX_RC_SHORT_GI ||
+ (ieee80211_is_data_qos(hdr->frame_control) &&
+ sta && sta->ht_cap.cap &
+ (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))) {
+ tx_desc->txdw5 |= cpu_to_le32(TXDESC_SHORT_GI);
+ }
+ if (ieee80211_is_mgmt(hdr->frame_control)) {
+ tx_desc->txdw5 = cpu_to_le32(tx_rate->hw_value);
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC_USE_DRIVER_RATE);
+ tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC_RETRY_LIMIT_SHIFT);
+ tx_desc->txdw5 |= cpu_to_le32(TXDESC_RETRY_LIMIT_ENABLE);
+ }
+
+ if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
+ /* Use RTS rate 24M - does the mac80211 tell us which to use? */
+ tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M);
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC_RTS_CTS_ENABLE);
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC_HW_RTS_ENABLE);
+ }
+
+ rtl8xxxu_calc_tx_desc_csum(tx_desc);
+
+ usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue],
+ skb->data, skb->len, rtl8xxxu_tx_complete, skb);
+
+ usb_anchor_urb(&tx_urb->urb, &priv->tx_anchor);
+ ret = usb_submit_urb(&tx_urb->urb, GFP_ATOMIC);
+ if (ret) {
+ usb_unanchor_urb(&tx_urb->urb);
+ rtl8xxxu_free_tx_urb(priv, tx_urb);
+ goto error;
+ }
+ return;
+error:
+ dev_kfree_skb(skb);
+}
+
+static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
+ struct ieee80211_rx_status *rx_status,
+ struct rtl8xxxu_rx_desc *rx_desc,
+ struct rtl8723au_phy_stats *phy_stats)
+{
+ if (phy_stats->sgi_en)
+ rx_status->flag |= RX_FLAG_SHORT_GI;
+
+ if (rx_desc->rxmcs < DESC_RATE_6M) {
+ /*
+ * Handle PHY stats for CCK rates
+ */
+ u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
+
+ switch (cck_agc_rpt & 0xc0) {
+ case 0xc0:
+ rx_status->signal = -46 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x80:
+ rx_status->signal = -26 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x40:
+ rx_status->signal = -12 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x00:
+ rx_status->signal = 16 - (cck_agc_rpt & 0x3e);
+ break;
+ }
+ } else {
+ rx_status->signal =
+ (phy_stats->cck_sig_qual_ofdm_pwdb_all >> 1) - 110;
+ }
+}
+
+static void rtl8xxxu_free_rx_resources(struct rtl8xxxu_priv *priv)
+{
+ struct rtl8xxxu_rx_urb *rx_urb, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->rx_urb_lock, flags);
+
+ list_for_each_entry_safe(rx_urb, tmp,
+ &priv->rx_urb_pending_list, list) {
+ list_del(&rx_urb->list);
+ priv->rx_urb_pending_count--;
+ usb_free_urb(&rx_urb->urb);
+ }
+
+ spin_unlock_irqrestore(&priv->rx_urb_lock, flags);
+}
+
+static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_rx_urb *rx_urb)
+{
+ struct sk_buff *skb;
+ unsigned long flags;
+ int pending = 0;
+
+ spin_lock_irqsave(&priv->rx_urb_lock, flags);
+
+ if (!priv->shutdown) {
+ list_add_tail(&rx_urb->list, &priv->rx_urb_pending_list);
+ priv->rx_urb_pending_count++;
+ pending = priv->rx_urb_pending_count;
+ } else {
+ skb = (struct sk_buff *)rx_urb->urb.context;
+ dev_kfree_skb(skb);
+ usb_free_urb(&rx_urb->urb);
+ }
+
+ spin_unlock_irqrestore(&priv->rx_urb_lock, flags);
+
+ if (pending > RTL8XXXU_RX_URB_PENDING_WATER)
+ schedule_work(&priv->rx_urb_wq);
+}
+
+static void rtl8xxxu_rx_urb_work(struct work_struct *work)
+{
+ struct rtl8xxxu_priv *priv;
+ struct rtl8xxxu_rx_urb *rx_urb, *tmp;
+ struct list_head local;
+ struct sk_buff *skb;
+ unsigned long flags;
+ int ret;
+
+ priv = container_of(work, struct rtl8xxxu_priv, rx_urb_wq);
+ INIT_LIST_HEAD(&local);
+
+ spin_lock_irqsave(&priv->rx_urb_lock, flags);
+
+ list_splice_init(&priv->rx_urb_pending_list, &local);
+ priv->rx_urb_pending_count = 0;
+
+ spin_unlock_irqrestore(&priv->rx_urb_lock, flags);
+
+ list_for_each_entry_safe(rx_urb, tmp, &local, list) {
+ list_del_init(&rx_urb->list);
+ ret = rtl8xxxu_submit_rx_urb(priv, rx_urb);
+ /*
+ * If out of memory or temporary error, put it back on the
+ * queue and try again. Otherwise the device is dead/gone
+ * and we should drop it.
+ */
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOMEM:
+ case -EAGAIN:
+ rtl8xxxu_queue_rx_urb(priv, rx_urb);
+ break;
+ default:
+ pr_info("failed to requeue urb %i\n", ret);
+ skb = (struct sk_buff *)rx_urb->urb.context;
+ dev_kfree_skb(skb);
+ usb_free_urb(&rx_urb->urb);
+ }
+ }
+}
+
+static void rtl8xxxu_rx_complete(struct urb *urb)
+{
+ struct rtl8xxxu_rx_urb *rx_urb =
+ container_of(urb, struct rtl8xxxu_rx_urb, urb);
+ struct ieee80211_hw *hw = rx_urb->hw;
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data;
+ struct rtl8723au_phy_stats *phy_stats;
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_mgmt *mgmt;
+ struct device *dev = &priv->udev->dev;
+ __le32 *_rx_desc_le = (__le32 *)skb->data;
+ u32 *_rx_desc = (u32 *)skb->data;
+ int cnt, len, drvinfo_sz, desc_shift, i;
+
+ for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++)
+ _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]);
+
+ cnt = rx_desc->frag;
+ len = rx_desc->pktlen;
+ drvinfo_sz = rx_desc->drvinfo_sz * 8;
+ desc_shift = rx_desc->shift;
+ skb_put(skb, urb->actual_length);
+
+ if (urb->status == 0) {
+ skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc));
+ phy_stats = (struct rtl8723au_phy_stats *)skb->data;
+
+ skb_pull(skb, drvinfo_sz + desc_shift);
+
+ mgmt = (struct ieee80211_mgmt *)skb->data;
+
+ memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+
+ if (rx_desc->phy_stats)
+ rtl8xxxu_rx_parse_phystats(priv, rx_status,
+ rx_desc, phy_stats);
+
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+
+ rx_status->mactime = le32_to_cpu(rx_desc->tsfl);
+ rx_status->flag |= RX_FLAG_MACTIME_START;
+
+ if (!rx_desc->swdec)
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (rx_desc->crc32)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (rx_desc->bw)
+ rx_status->flag |= RX_FLAG_40MHZ;
+
+ if (rx_desc->rxht) {
+ rx_status->flag |= RX_FLAG_HT;
+ rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
+ } else {
+ rx_status->rate_idx = rx_desc->rxmcs;
+ }
+
+ ieee80211_rx_irqsafe(hw, skb);
+ skb = NULL;
+ rx_urb->urb.context = NULL;
+ rtl8xxxu_queue_rx_urb(priv, rx_urb);
+ } else {
+ dev_dbg(dev, "%s: status %i\n", __func__, urb->status);
+ goto cleanup;
+ }
+ return;
+
+cleanup:
+ usb_free_urb(urb);
+ dev_kfree_skb(skb);
+ return;
+}
+
+static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv,
+ struct rtl8xxxu_rx_urb *rx_urb)
+{
+ struct sk_buff *skb;
+ int skb_size;
+ int ret;
+
+ skb_size = sizeof(struct rtl8xxxu_rx_desc) + RTL_RX_BUFFER_SIZE;
+ skb = __netdev_alloc_skb(NULL, skb_size, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ memset(skb->data, 0, sizeof(struct rtl8xxxu_rx_desc));
+ usb_fill_bulk_urb(&rx_urb->urb, priv->udev, priv->pipe_in, skb->data,
+ skb_size, rtl8xxxu_rx_complete, skb);
+ usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor);
+ ret = usb_submit_urb(&rx_urb->urb, GFP_ATOMIC);
+ if (ret)
+ usb_unanchor_urb(&rx_urb->urb);
+ return ret;
+}
+
+static void rtl8xxxu_int_complete(struct urb *urb)
+{
+ struct rtl8xxxu_priv *priv = (struct rtl8xxxu_priv *)urb->context;
+ struct device *dev = &priv->udev->dev;
+ int ret;
+
+ dev_dbg(dev, "%s: status %i\n", __func__, urb->status);
+ if (urb->status == 0) {
+ usb_anchor_urb(urb, &priv->int_anchor);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ usb_unanchor_urb(urb);
+ } else {
+ dev_info(dev, "%s: Error %i\n", __func__, urb->status);
+ }
+}
+
+
+static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct urb *urb;
+ u32 val32;
+ int ret;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ usb_fill_int_urb(urb, priv->udev, priv->pipe_interrupt,
+ priv->int_buf, USB_INTR_CONTENT_LENGTH,
+ rtl8xxxu_int_complete, priv, 1);
+ usb_anchor_urb(urb, &priv->int_anchor);
+ ret = usb_submit_urb(urb, GFP_KERNEL);
+ if (ret) {
+ usb_unanchor_urb(urb);
+ goto error;
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_USB_HIMR);
+ val32 |= USB_HIMR_CPWM;
+ rtl8xxxu_write32(priv, REG_USB_HIMR, val32);
+
+error:
+ return ret;
+}
+
+static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ int ret;
+ u8 val8;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ rtl8723a_stop_tx_beacon(priv);
+
+ val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
+ val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE |
+ BEACON_DISABLE_TSF_UPDATE;
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
+ ret = 0;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ rtl8xxxu_set_linktype(priv, vif->type);
+
+ return ret;
+}
+
+static void rtl8xxxu_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ dev_dbg(&priv->udev->dev, "%s\n", __func__);
+}
+
+static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ u16 val16;
+ int ret = 0, channel;
+ bool ht40;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL)
+ dev_info(dev,
+ "%s: channel: %i (changed %08x chandef.width %02x)\n",
+ __func__, hw->conf.chandef.chan->hw_value,
+ changed, hw->conf.chandef.width);
+
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+ val16 = ((hw->conf.long_frame_max_tx_count <<
+ RETRY_LIMIT_LONG_SHIFT) & RETRY_LIMIT_LONG_MASK) |
+ ((hw->conf.short_frame_max_tx_count <<
+ RETRY_LIMIT_SHORT_SHIFT) & RETRY_LIMIT_SHORT_MASK);
+ rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16);
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ switch (hw->conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ ht40 = false;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ ht40 = true;
+ break;
+ default:
+ ret = -ENOTSUPP;
+ goto exit;
+ }
+
+ channel = hw->conf.chandef.chan->hw_value;
+
+ rtl8723a_set_tx_power(priv, channel, ht40);
+
+ rtl8723au_config_channel(hw);
+ }
+
+exit:
+ return ret;
+}
+
+static int rtl8xxxu_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *param)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ u32 val32;
+ u8 aifs, acm_ctrl, acm_bit;
+
+ aifs = param->aifs;
+
+ val32 = aifs |
+ fls(param->cw_min) << EDCA_PARAM_ECW_MIN_SHIFT |
+ fls(param->cw_max) << EDCA_PARAM_ECW_MAX_SHIFT |
+ (u32)param->txop << EDCA_PARAM_TXOP_SHIFT;
+
+ acm_ctrl = rtl8xxxu_read8(priv, REG_ACM_HW_CTRL);
+ dev_dbg(dev,
+ "%s: IEEE80211 queue %02x val %08x, acm %i, acm_ctrl %02x\n",
+ __func__, queue, val32, param->acm, acm_ctrl);
+
+ switch (queue) {
+ case IEEE80211_AC_VO:
+ acm_bit = ACM_HW_CTRL_VO;
+ rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, val32);
+ break;
+ case IEEE80211_AC_VI:
+ acm_bit = ACM_HW_CTRL_VI;
+ rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, val32);
+ break;
+ case IEEE80211_AC_BE:
+ acm_bit = ACM_HW_CTRL_BE;
+ rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, val32);
+ break;
+ case IEEE80211_AC_BK:
+ acm_bit = ACM_HW_CTRL_BK;
+ rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, val32);
+ break;
+ default:
+ acm_bit = 0;
+ break;
+ }
+
+ if (param->acm)
+ acm_ctrl |= acm_bit;
+ else
+ acm_ctrl &= ~acm_bit;
+ rtl8xxxu_write8(priv, REG_ACM_HW_CTRL, acm_ctrl);
+
+ return 0;
+}
+
+static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags, u64 multicast)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n",
+ __func__, changed_flags, *total_flags);
+
+ *total_flags &= (FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC);
+}
+
+static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts)
+{
+ if (rts > 2347)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int rtl8xxxu_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 rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ u8 mac_addr[ETH_ALEN];
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ int retval = -EOPNOTSUPP;
+
+ dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n",
+ __func__, cmd, key->cipher, key->keyidx);
+
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (key->keyidx > 3)
+ return -EOPNOTSUPP;
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
+ dev_dbg(dev, "%s: pairwise key\n", __func__);
+ ether_addr_copy(mac_addr, sta->addr);
+ } else {
+ dev_dbg(dev, "%s: group key\n", __func__);
+ eth_broadcast_addr(mac_addr);
+ }
+
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 |= CR_SECURITY_ENABLE;
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ val8 = SEC_CFG_TX_SEC_ENABLE | SEC_CFG_TXBC_USE_DEFKEY |
+ SEC_CFG_RX_SEC_ENABLE | SEC_CFG_RXBC_USE_DEFKEY;
+ val8 |= SEC_CFG_TX_USE_DEFKEY | SEC_CFG_RX_USE_DEFKEY;
+ rtl8xxxu_write8(priv, REG_SECURITY_CFG, val8);
+
+ switch (cmd) {
+ case SET_KEY:
+ key->hw_key_idx = key->keyidx;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ rtl8xxxu_cam_write(priv, key, mac_addr);
+ retval = 0;
+ break;
+ case DISABLE_KEY:
+ rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000);
+ val32 = CAM_CMD_POLLING | CAM_CMD_WRITE |
+ key->keyidx << CAM_CMD_KEY_SHIFT;
+ rtl8xxxu_write32(priv, REG_CAM_CMD, val32);
+ retval = 0;
+ break;
+ default:
+ dev_warn(dev, "%s: Unsupported command %02x\n", __func__, cmd);
+ }
+
+ return retval;
+}
+
+static int
+rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ enum ieee80211_ampdu_mlme_action action,
+ struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
+ bool amsdu)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ u8 ampdu_factor, ampdu_density;
+
+ switch (action) {
+ case IEEE80211_AMPDU_TX_START:
+ dev_info(dev, "%s: IEEE80211_AMPDU_TX_START\n", __func__);
+ ampdu_factor = sta->ht_cap.ampdu_factor;
+ ampdu_density = sta->ht_cap.ampdu_density;
+ rtl8xxxu_set_ampdu_factor(priv, ampdu_factor);
+ rtl8xxxu_set_ampdu_min_space(priv, ampdu_density);
+ dev_dbg(dev,
+ "Changed HT: ampdu_factor %02x, ampdu_density %02x\n",
+ ampdu_factor, ampdu_density);
+ break;
+ case IEEE80211_AMPDU_TX_STOP_FLUSH:
+ dev_info(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH\n", __func__);
+ rtl8xxxu_set_ampdu_factor(priv, 0);
+ rtl8xxxu_set_ampdu_min_space(priv, 0);
+ break;
+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ dev_info(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH_CONT\n",
+ __func__);
+ rtl8xxxu_set_ampdu_factor(priv, 0);
+ rtl8xxxu_set_ampdu_min_space(priv, 0);
+ break;
+ case IEEE80211_AMPDU_RX_START:
+ dev_info(dev, "%s: IEEE80211_AMPDU_RX_START\n", __func__);
+ break;
+ case IEEE80211_AMPDU_RX_STOP:
+ dev_info(dev, "%s: IEEE80211_AMPDU_RX_STOP\n", __func__);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int rtl8xxxu_start(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct rtl8xxxu_rx_urb *rx_urb;
+ struct rtl8xxxu_tx_urb *tx_urb;
+ unsigned long flags;
+ int ret, i;
+
+ ret = 0;
+
+ init_usb_anchor(&priv->rx_anchor);
+ init_usb_anchor(&priv->tx_anchor);
+ init_usb_anchor(&priv->int_anchor);
+
+ rtl8723a_enable_rf(priv);
+ ret = rtl8xxxu_submit_int_urb(hw);
+ if (ret)
+ goto exit;
+
+ for (i = 0; i < RTL8XXXU_TX_URBS; i++) {
+ tx_urb = kmalloc(sizeof(struct rtl8xxxu_tx_urb), GFP_KERNEL);
+ if (!tx_urb) {
+ if (!i)
+ ret = -ENOMEM;
+
+ goto error_out;
+ }
+ usb_init_urb(&tx_urb->urb);
+ INIT_LIST_HEAD(&tx_urb->list);
+ tx_urb->hw = hw;
+ list_add(&tx_urb->list, &priv->tx_urb_free_list);
+ priv->tx_urb_free_count++;
+ }
+
+ priv->tx_stopped = false;
+
+ spin_lock_irqsave(&priv->rx_urb_lock, flags);
+ priv->shutdown = false;
+ spin_unlock_irqrestore(&priv->rx_urb_lock, flags);
+
+ for (i = 0; i < RTL8XXXU_RX_URBS; i++) {
+ rx_urb = kmalloc(sizeof(struct rtl8xxxu_rx_urb), GFP_KERNEL);
+ if (!rx_urb) {
+ if (!i)
+ ret = -ENOMEM;
+
+ goto error_out;
+ }
+ usb_init_urb(&rx_urb->urb);
+ INIT_LIST_HEAD(&rx_urb->list);
+ rx_urb->hw = hw;
+
+ ret = rtl8xxxu_submit_rx_urb(priv, rx_urb);
+ }
+exit:
+ /*
+ * Disable all data frames
+ */
+ rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000);
+ /*
+ * Accept all mgmt frames
+ */
+ rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0xffff);
+
+ rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6954341e);
+
+ return ret;
+
+error_out:
+ rtl8xxxu_free_tx_resources(priv);
+ /*
+ * Disable all data and mgmt frames
+ */
+ rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000);
+ rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000);
+
+ return ret;
+}
+
+static void rtl8xxxu_stop(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ unsigned long flags;
+
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+
+ rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000);
+ rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000);
+
+ spin_lock_irqsave(&priv->rx_urb_lock, flags);
+ priv->shutdown = true;
+ spin_unlock_irqrestore(&priv->rx_urb_lock, flags);
+
+ usb_kill_anchored_urbs(&priv->rx_anchor);
+ usb_kill_anchored_urbs(&priv->tx_anchor);
+ usb_kill_anchored_urbs(&priv->int_anchor);
+
+ rtl8723a_disable_rf(priv);
+
+ /*
+ * Disable interrupts
+ */
+ rtl8xxxu_write32(priv, REG_USB_HIMR, 0);
+
+ rtl8xxxu_free_rx_resources(priv);
+ rtl8xxxu_free_tx_resources(priv);
+}
+
+static const struct ieee80211_ops rtl8xxxu_ops = {
+ .tx = rtl8xxxu_tx,
+ .add_interface = rtl8xxxu_add_interface,
+ .remove_interface = rtl8xxxu_remove_interface,
+ .config = rtl8xxxu_config,
+ .conf_tx = rtl8xxxu_conf_tx,
+ .bss_info_changed = rtl8xxxu_bss_info_changed,
+ .configure_filter = rtl8xxxu_configure_filter,
+ .set_rts_threshold = rtl8xxxu_set_rts_threshold,
+ .start = rtl8xxxu_start,
+ .stop = rtl8xxxu_stop,
+ .sw_scan_start = rtl8xxxu_sw_scan_start,
+ .sw_scan_complete = rtl8xxxu_sw_scan_complete,
+ .set_key = rtl8xxxu_set_key,
+ .ampdu_action = rtl8xxxu_ampdu_action,
+};
+
+static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv,
+ struct usb_interface *interface)
+{
+ struct usb_interface_descriptor *interface_desc;
+ struct usb_host_interface *host_interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct device *dev = &priv->udev->dev;
+ int i, j = 0, endpoints;
+ u8 dir, xtype, num;
+ int ret = 0;
+
+ host_interface = &interface->altsetting[0];
+ interface_desc = &host_interface->desc;
+ endpoints = interface_desc->bNumEndpoints;
+
+ for (i = 0; i < endpoints; i++) {
+ endpoint = &host_interface->endpoint[i].desc;
+
+ dir = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+ num = usb_endpoint_num(endpoint);
+ xtype = usb_endpoint_type(endpoint);
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB)
+ dev_dbg(dev,
+ "%s: endpoint: dir %02x, # %02x, type %02x\n",
+ __func__, dir, num, xtype);
+ if (usb_endpoint_dir_in(endpoint) &&
+ usb_endpoint_xfer_bulk(endpoint)) {
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB)
+ dev_dbg(dev, "%s: in endpoint num %i\n",
+ __func__, num);
+
+ if (priv->pipe_in) {
+ dev_warn(dev,
+ "%s: Too many IN pipes\n", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ priv->pipe_in = usb_rcvbulkpipe(priv->udev, num);
+ }
+
+ if (usb_endpoint_dir_in(endpoint) &&
+ usb_endpoint_xfer_int(endpoint)) {
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB)
+ dev_dbg(dev, "%s: interrupt endpoint num %i\n",
+ __func__, num);
+
+ if (priv->pipe_interrupt) {
+ dev_warn(dev, "%s: Too many INTERRUPT pipes\n",
+ __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ priv->pipe_interrupt = usb_rcvintpipe(priv->udev, num);
+ }
+
+ if (usb_endpoint_dir_out(endpoint) &&
+ usb_endpoint_xfer_bulk(endpoint)) {
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB)
+ dev_dbg(dev, "%s: out endpoint num %i\n",
+ __func__, num);
+ if (j >= RTL8XXXU_OUT_ENDPOINTS) {
+ dev_warn(dev,
+ "%s: Too many OUT pipes\n", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+ priv->out_ep[j++] = num;
+ }
+ }
+exit:
+ priv->nr_out_eps = j;
+ return ret;
+}
+
+static int rtl8xxxu_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct rtl8xxxu_priv *priv;
+ struct ieee80211_hw *hw;
+ struct usb_device *udev;
+ struct ieee80211_supported_band *sband;
+ int ret = 0;
+ int untested = 1;
+
+ udev = usb_get_dev(interface_to_usbdev(interface));
+
+ switch (id->idVendor) {
+ case USB_VENDOR_ID_REALTEK:
+ switch(id->idProduct) {
+ case 0x1724:
+ case 0x8176:
+ case 0x8178:
+ case 0x817f:
+ untested = 0;
+ break;
+ }
+ break;
+ case 0x7392:
+ if (id->idProduct == 0x7811)
+ untested = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (untested) {
+ rtl8xxxu_debug = RTL8XXXU_DEBUG_EFUSE;
+ dev_info(&udev->dev,
+ "This Realtek USB WiFi dongle (0x%04x:0x%04x) is untested!\n",
+ id->idVendor, id->idProduct);
+ dev_info(&udev->dev,
+ "Please report results to Jes.Sorensen@gmail.com\n");
+ }
+
+ hw = ieee80211_alloc_hw(sizeof(struct rtl8xxxu_priv), &rtl8xxxu_ops);
+ if (!hw) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ priv = hw->priv;
+ priv->hw = hw;
+ priv->udev = udev;
+ priv->fops = (struct rtl8xxxu_fileops *)id->driver_info;
+ mutex_init(&priv->usb_buf_mutex);
+ mutex_init(&priv->h2c_mutex);
+ INIT_LIST_HEAD(&priv->tx_urb_free_list);
+ spin_lock_init(&priv->tx_urb_lock);
+ INIT_LIST_HEAD(&priv->rx_urb_pending_list);
+ spin_lock_init(&priv->rx_urb_lock);
+ INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
+
+ usb_set_intfdata(interface, hw);
+
+ ret = rtl8xxxu_parse_usb(priv, interface);
+ if (ret)
+ goto exit;
+
+ ret = rtl8xxxu_identify_chip(priv);
+ if (ret) {
+ dev_err(&udev->dev, "Fatal - failed to identify chip\n");
+ goto exit;
+ }
+
+ ret = rtl8xxxu_read_efuse(priv);
+ if (ret) {
+ dev_err(&udev->dev, "Fatal - failed to read EFuse\n");
+ goto exit;
+ }
+
+ ret = priv->fops->parse_efuse(priv);
+ if (ret) {
+ dev_err(&udev->dev, "Fatal - failed to parse EFuse\n");
+ goto exit;
+ }
+
+ rtl8xxxu_print_chipinfo(priv);
+
+ ret = priv->fops->load_firmware(priv);
+ if (ret) {
+ dev_err(&udev->dev, "Fatal - failed to load firmware\n");
+ goto exit;
+ }
+
+ ret = rtl8xxxu_init_device(hw);
+
+ hw->wiphy->max_scan_ssids = 1;
+ hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ hw->queues = 4;
+
+ sband = &rtl8xxxu_supported_band;
+ sband->ht_cap.ht_supported = true;
+ sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ sband->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+ sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40;
+ memset(&sband->ht_cap.mcs, 0, sizeof(sband->ht_cap.mcs));
+ sband->ht_cap.mcs.rx_mask[0] = 0xff;
+ sband->ht_cap.mcs.rx_mask[4] = 0x01;
+ if (priv->rf_paths > 1) {
+ sband->ht_cap.mcs.rx_mask[1] = 0xff;
+ sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+ }
+ sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+ /*
+ * Some APs will negotiate HT20_40 in a noisy environment leading
+ * to miserable performance. Rather than defaulting to this, only
+ * enable it if explicitly requested at module load time.
+ */
+ if (rtl8xxxu_ht40_2g) {
+ dev_info(&udev->dev, "Enabling HT_20_40 on the 2.4GHz band\n");
+ sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
+
+ hw->wiphy->rts_threshold = 2347;
+
+ SET_IEEE80211_DEV(priv->hw, &interface->dev);
+ SET_IEEE80211_PERM_ADDR(hw, priv->mac_addr);
+
+ hw->extra_tx_headroom = sizeof(struct rtl8xxxu_tx_desc);
+ ieee80211_hw_set(hw, SIGNAL_DBM);
+ /*
+ * The firmware handles rate control
+ */
+ ieee80211_hw_set(hw, HAS_RATE_CONTROL);
+ ieee80211_hw_set(hw, AMPDU_AGGREGATION);
+
+ ret = ieee80211_register_hw(priv->hw);
+ if (ret) {
+ dev_err(&udev->dev, "%s: Failed to register: %i\n",
+ __func__, ret);
+ goto exit;
+ }
+
+exit:
+ if (ret < 0)
+ usb_put_dev(udev);
+ return ret;
+}
+
+static void rtl8xxxu_disconnect(struct usb_interface *interface)
+{
+ struct rtl8xxxu_priv *priv;
+ struct ieee80211_hw *hw;
+
+ hw = usb_get_intfdata(interface);
+ priv = hw->priv;
+
+ rtl8xxxu_disable_device(hw);
+ usb_set_intfdata(interface, NULL);
+
+ dev_info(&priv->udev->dev, "disconnecting\n");
+
+ ieee80211_unregister_hw(hw);
+
+ kfree(priv->fw_data);
+ mutex_destroy(&priv->usb_buf_mutex);
+ mutex_destroy(&priv->h2c_mutex);
+
+ usb_put_dev(priv->udev);
+ ieee80211_free_hw(hw);
+}
+
+static struct rtl8xxxu_fileops rtl8723au_fops = {
+ .parse_efuse = rtl8723au_parse_efuse,
+ .load_firmware = rtl8723au_load_firmware,
+ .power_on = rtl8723au_power_on,
+ .writeN_block_size = 1024,
+};
+
+#ifdef CONFIG_RTL8XXXU_UNTESTED
+
+static struct rtl8xxxu_fileops rtl8192cu_fops = {
+ .parse_efuse = rtl8192cu_parse_efuse,
+ .load_firmware = rtl8192cu_load_firmware,
+ .power_on = rtl8192cu_power_on,
+ .writeN_block_size = 128,
+};
+
+#endif
+
+static struct usb_device_id dev_table[] = {
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8724, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8723au_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1724, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8723au_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x0724, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8723au_fops},
+#ifdef CONFIG_RTL8XXXU_UNTESTED
+/* Still supported by rtlwifi */
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8178, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817f, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+/* Tested by Larry Finger */
+{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+/* Currently untested 8188 series devices */
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8170, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8177, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817a, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817b, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817d, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817e, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818a, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0631, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x094c, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1102, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ba, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1e1e, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x5088, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0052, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x005c, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0eb0, 0x9071, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x103c, 0x1629, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3357, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3308, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330b, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x4902, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2a, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2e, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xed17, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x648b, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0090, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x4856, 0x0091, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops}, /* Netcore 8188RU */
+{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff9, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffa, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff8, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffb, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffc, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x1201, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+/* Currently untested 8192 series devices */
+{USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0950, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2102, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2103, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x341f, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe035, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ab, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0061, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0070, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016d, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x07aa, 0x0056, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8178, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9021, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0xf001, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2e2e, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0019, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0020, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3307, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3309, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330a, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2b, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x624d, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0100, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0091, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7822, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+#endif
+{ }
+};
+
+static struct usb_driver rtl8xxxu_driver = {
+ .name = DRIVER_NAME,
+ .probe = rtl8xxxu_probe,
+ .disconnect = rtl8xxxu_disconnect,
+ .id_table = dev_table,
+ .disable_hub_initiated_lpm = 1,
+};
+
+static int __init rtl8xxxu_module_init(void)
+{
+ int res;
+
+ res = usb_register(&rtl8xxxu_driver);
+ if (res < 0)
+ pr_err(DRIVER_NAME ": usb_register() failed (%i)\n", res);
+
+ return res;
+}
+
+static void __exit rtl8xxxu_module_exit(void)
+{
+ usb_deregister(&rtl8xxxu_driver);
+}
+
+
+MODULE_DEVICE_TABLE(usb, dev_table);
+
+module_init(rtl8xxxu_module_init);
+module_exit(rtl8xxxu_module_exit);
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
new file mode 100644
index 000000000000..f2a1bac6c8ec
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com>
+ *
+ * This program 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.
+ *
+ * Register definitions taken from original Realtek rtl8723au driver
+ */
+
+#include <asm/byteorder.h>
+
+#define RTL8XXXU_DEBUG_REG_WRITE 0x01
+#define RTL8XXXU_DEBUG_REG_READ 0x02
+#define RTL8XXXU_DEBUG_RFREG_WRITE 0x04
+#define RTL8XXXU_DEBUG_RFREG_READ 0x08
+#define RTL8XXXU_DEBUG_CHANNEL 0x10
+#define RTL8XXXU_DEBUG_TX 0x20
+#define RTL8XXXU_DEBUG_TX_DUMP 0x40
+#define RTL8XXXU_DEBUG_RX 0x80
+#define RTL8XXXU_DEBUG_RX_DUMP 0x100
+#define RTL8XXXU_DEBUG_USB 0x200
+#define RTL8XXXU_DEBUG_KEY 0x400
+#define RTL8XXXU_DEBUG_H2C 0x800
+#define RTL8XXXU_DEBUG_ACTION 0x1000
+#define RTL8XXXU_DEBUG_EFUSE 0x2000
+
+#define RTW_USB_CONTROL_MSG_TIMEOUT 500
+#define RTL8XXXU_MAX_REG_POLL 500
+#define USB_INTR_CONTENT_LENGTH 56
+
+#define RTL8XXXU_OUT_ENDPOINTS 3
+
+#define REALTEK_USB_READ 0xc0
+#define REALTEK_USB_WRITE 0x40
+#define REALTEK_USB_CMD_REQ 0x05
+#define REALTEK_USB_CMD_IDX 0x00
+
+#define TX_TOTAL_PAGE_NUM 0xf8
+/* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */
+#define TX_PAGE_NUM_PUBQ 0xe7
+#define TX_PAGE_NUM_HI_PQ 0x0c
+#define TX_PAGE_NUM_LO_PQ 0x02
+#define TX_PAGE_NUM_NORM_PQ 0x02
+
+#define RTL_FW_PAGE_SIZE 4096
+#define RTL8XXXU_FIRMWARE_POLL_MAX 1000
+
+#define RTL8723A_CHANNEL_GROUPS 3
+#define RTL8723A_MAX_RF_PATHS 2
+#define RF6052_MAX_TX_PWR 0x3f
+
+#define EFUSE_MAP_LEN_8723A 256
+#define EFUSE_MAX_SECTION_8723A 32
+#define EFUSE_REAL_CONTENT_LEN_8723A 512
+#define EFUSE_BT_MAP_LEN_8723A 1024
+#define EFUSE_MAX_WORD_UNIT 4
+
+struct rtl8xxxu_rx_desc {
+#ifdef __LITTLE_ENDIAN
+ u32 pktlen:14;
+ u32 crc32:1;
+ u32 icverr:1;
+ u32 drvinfo_sz:4;
+ u32 security:3;
+ u32 qos:1;
+ u32 shift:2;
+ u32 phy_stats:1;
+ u32 swdec:1;
+ u32 ls:1;
+ u32 fs:1;
+ u32 eor:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 tid:4;
+ u32 hwrsvd:4;
+ u32 amsdu:1;
+ u32 paggr:1;
+ u32 faggr:1;
+ u32 a1fit:4;
+ u32 a2fit:4;
+ u32 pam:1;
+ u32 pwr:1;
+ u32 md:1;
+ u32 mf:1;
+ u32 type:2;
+ u32 mc:1;
+ u32 bc:1;
+
+ u32 seq:12;
+ u32 frag:4;
+ u32 nextpktlen:14;
+ u32 nextind:1;
+ u32 reserved0:1;
+
+ u32 rxmcs:6;
+ u32 rxht:1;
+ u32 gf:1;
+ u32 splcp:1;
+ u32 bw:1;
+ u32 htc:1;
+ u32 eosp:1;
+ u32 bssidfit:2;
+ u32 reserved1:16;
+ u32 unicastwake:1;
+ u32 magicwake:1;
+
+ u32 pattern0match:1;
+ u32 pattern1match:1;
+ u32 pattern2match:1;
+ u32 pattern3match:1;
+ u32 pattern4match:1;
+ u32 pattern5match:1;
+ u32 pattern6match:1;
+ u32 pattern7match:1;
+ u32 pattern8match:1;
+ u32 pattern9match:1;
+ u32 patternamatch:1;
+ u32 patternbmatch:1;
+ u32 patterncmatch:1;
+ u32 reserved2:19;
+#else
+ u32 own:1;
+ u32 eor:1;
+ u32 fs:1;
+ u32 ls:1;
+ u32 swdec:1;
+ u32 phy_stats:1;
+ u32 shift:2;
+ u32 qos:1;
+ u32 security:3;
+ u32 drvinfo_sz:4;
+ u32 icverr:1;
+ u32 crc32:1;
+ u32 pktlen:14;
+
+ u32 bc:1;
+ u32 mc:1;
+ u32 type:2;
+ u32 mf:1;
+ u32 md:1;
+ u32 pwr:1;
+ u32 pam:1;
+ u32 a2fit:4;
+ u32 a1fit:4;
+ u32 faggr:1;
+ u32 paggr:1;
+ u32 amsdu:1;
+ u32 hwrsvd:4;
+ u32 tid:4;
+ u32 macid:5;
+
+ u32 reserved0:1;
+ u32 nextind:1;
+ u32 nextpktlen:14;
+ u32 frag:4;
+ u32 seq:12;
+
+ u32 magicwake:1;
+ u32 unicastwake:1;
+ u32 reserved1:16;
+ u32 bssidfit:2;
+ u32 eosp:1;
+ u32 htc:1;
+ u32 bw:1;
+ u32 splcp:1;
+ u32 gf:1;
+ u32 rxht:1;
+ u32 rxmcs:6;
+
+ u32 reserved2:19;
+ u32 patterncmatch:1;
+ u32 patternbmatch:1;
+ u32 patternamatch:1;
+ u32 pattern9match:1;
+ u32 pattern8match:1;
+ u32 pattern7match:1;
+ u32 pattern6match:1;
+ u32 pattern5match:1;
+ u32 pattern4match:1;
+ u32 pattern3match:1;
+ u32 pattern2match:1;
+ u32 pattern1match:1;
+ u32 pattern0match:1;
+#endif
+ __le32 tsfl;
+#if 0
+ u32 bassn:12;
+ u32 bavld:1;
+ u32 reserved3:19;
+#endif
+};
+
+struct rtl8xxxu_tx_desc {
+ __le16 pkt_size;
+ u8 pkt_offset;
+ u8 txdw0;
+ __le32 txdw1;
+ __le32 txdw2;
+ __le32 txdw3;
+ __le32 txdw4;
+ __le32 txdw5;
+ __le32 txdw6;
+ __le16 csum;
+ __le16 txdw7;
+};
+
+/* CCK Rates, TxHT = 0 */
+#define DESC_RATE_1M 0x00
+#define DESC_RATE_2M 0x01
+#define DESC_RATE_5_5M 0x02
+#define DESC_RATE_11M 0x03
+
+/* OFDM Rates, TxHT = 0 */
+#define DESC_RATE_6M 0x04
+#define DESC_RATE_9M 0x05
+#define DESC_RATE_12M 0x06
+#define DESC_RATE_18M 0x07
+#define DESC_RATE_24M 0x08
+#define DESC_RATE_36M 0x09
+#define DESC_RATE_48M 0x0a
+#define DESC_RATE_54M 0x0b
+
+/* MCS Rates, TxHT = 1 */
+#define DESC_RATE_MCS0 0x0c
+#define DESC_RATE_MCS1 0x0d
+#define DESC_RATE_MCS2 0x0e
+#define DESC_RATE_MCS3 0x0f
+#define DESC_RATE_MCS4 0x10
+#define DESC_RATE_MCS5 0x11
+#define DESC_RATE_MCS6 0x12
+#define DESC_RATE_MCS7 0x13
+#define DESC_RATE_MCS8 0x14
+#define DESC_RATE_MCS9 0x15
+#define DESC_RATE_MCS10 0x16
+#define DESC_RATE_MCS11 0x17
+#define DESC_RATE_MCS12 0x18
+#define DESC_RATE_MCS13 0x19
+#define DESC_RATE_MCS14 0x1a
+#define DESC_RATE_MCS15 0x1b
+#define DESC_RATE_MCS15_SG 0x1c
+#define DESC_RATE_MCS32 0x20
+
+#define TXDESC_OFFSET_SZ 0
+#define TXDESC_OFFSET_SHT 16
+#if 0
+#define TXDESC_BMC BIT(24)
+#define TXDESC_LSG BIT(26)
+#define TXDESC_FSG BIT(27)
+#define TXDESC_OWN BIT(31)
+#else
+#define TXDESC_BROADMULTICAST BIT(0)
+#define TXDESC_LAST_SEGMENT BIT(2)
+#define TXDESC_FIRST_SEGMENT BIT(3)
+#define TXDESC_OWN BIT(7)
+#endif
+
+/* Word 1 */
+#define TXDESC_PKT_OFFSET_SZ 0
+#define TXDESC_AGG_ENABLE BIT(5)
+#define TXDESC_BK BIT(6)
+#define TXDESC_QUEUE_SHIFT 8
+#define TXDESC_QUEUE_MASK 0x1f00
+#define TXDESC_QUEUE_BK 0x2
+#define TXDESC_QUEUE_BE 0x0
+#define TXDESC_QUEUE_VI 0x5
+#define TXDESC_QUEUE_VO 0x7
+#define TXDESC_QUEUE_BEACON 0x10
+#define TXDESC_QUEUE_HIGH 0x11
+#define TXDESC_QUEUE_MGNT 0x12
+#define TXDESC_QUEUE_CMD 0x13
+#define TXDESC_QUEUE_MAX (TXDESC_QUEUE_CMD + 1)
+
+#define DESC_RATE_ID_SHIFT 16
+#define DESC_RATE_ID_MASK 0xf
+#define TXDESC_NAVUSEHDR BIT(20)
+#define TXDESC_SEC_RC4 0x00400000
+#define TXDESC_SEC_AES 0x00c00000
+#define TXDESC_PKT_OFFSET_SHIFT 26
+#define TXDESC_AGG_EN BIT(29)
+#define TXDESC_HWPC BIT(31)
+
+/* Word 2 */
+#define TXDESC_ACK_REPORT BIT(19)
+#define TXDESC_AMPDU_DENSITY_SHIFT 20
+
+/* Word 3 */
+#define TXDESC_SEQ_SHIFT 16
+#define TXDESC_SEQ_MASK 0x0fff0000
+
+/* Word 4 */
+#define TXDESC_QOS BIT(6)
+#define TXDESC_HW_SEQ_ENABLE BIT(7)
+#define TXDESC_USE_DRIVER_RATE BIT(8)
+#define TXDESC_DISABLE_DATA_FB BIT(10)
+#define TXDESC_CTS_SELF_ENABLE BIT(11)
+#define TXDESC_RTS_CTS_ENABLE BIT(12)
+#define TXDESC_HW_RTS_ENABLE BIT(13)
+#define TXDESC_PRIME_CH_OFF_LOWER BIT(20)
+#define TXDESC_PRIME_CH_OFF_UPPER BIT(21)
+#define TXDESC_SHORT_PREAMBLE BIT(24)
+#define TXDESC_DATA_BW BIT(25)
+#define TXDESC_RTS_DATA_BW BIT(27)
+#define TXDESC_RTS_PRIME_CH_OFF_LOWER BIT(28)
+#define TXDESC_RTS_PRIME_CH_OFF_UPPER BIT(29)
+
+/* Word 5 */
+#define TXDESC_RTS_RATE_SHIFT 0
+#define TXDESC_RTS_RATE_MASK 0x3f
+#define TXDESC_SHORT_GI BIT(6)
+#define TXDESC_CCX_TAG BIT(7)
+#define TXDESC_RETRY_LIMIT_ENABLE BIT(17)
+#define TXDESC_RETRY_LIMIT_SHIFT 18
+#define TXDESC_RETRY_LIMIT_MASK 0x00fc0000
+
+/* Word 6 */
+#define TXDESC_MAX_AGG_SHIFT 11
+
+struct phy_rx_agc_info {
+#ifdef __LITTLE_ENDIAN
+ u8 gain:7, trsw:1;
+#else
+ u8 trsw:1, gain:7;
+#endif
+};
+
+struct rtl8723au_phy_stats {
+ struct phy_rx_agc_info path_agc[RTL8723A_MAX_RF_PATHS];
+ u8 ch_corr[RTL8723A_MAX_RF_PATHS];
+ u8 cck_sig_qual_ofdm_pwdb_all;
+ u8 cck_agc_rpt_ofdm_cfosho_a;
+ u8 cck_rpt_b_ofdm_cfosho_b;
+ u8 reserved_1;
+ u8 noise_power_db_msb;
+ u8 path_cfotail[RTL8723A_MAX_RF_PATHS];
+ u8 pcts_mask[RTL8723A_MAX_RF_PATHS];
+ s8 stream_rxevm[RTL8723A_MAX_RF_PATHS];
+ u8 path_rxsnr[RTL8723A_MAX_RF_PATHS];
+ u8 noise_power_db_lsb;
+ u8 reserved_2[3];
+ u8 stream_csi[RTL8723A_MAX_RF_PATHS];
+ u8 stream_target_csi[RTL8723A_MAX_RF_PATHS];
+ s8 sig_evm;
+ u8 reserved_3;
+
+#ifdef __LITTLE_ENDIAN
+ u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
+ u8 sgi_en:1;
+ u8 rxsc:2;
+ u8 idle_long:1;
+ u8 r_ant_train_en:1;
+ u8 antenna_select_b:1;
+ u8 antenna_select:1;
+#else /* _BIG_ENDIAN_ */
+ u8 antenna_select:1;
+ u8 antenna_select_b:1;
+ u8 r_ant_train_en:1;
+ u8 idle_long:1;
+ u8 rxsc:2;
+ u8 sgi_en:1;
+ u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
+#endif
+};
+
+/*
+ * Regs to backup
+ */
+#define RTL8XXXU_ADDA_REGS 16
+#define RTL8XXXU_MAC_REGS 4
+#define RTL8XXXU_BB_REGS 9
+
+struct rtl8xxxu_firmware_header {
+ __le16 signature; /* 92C0: test chip; 92C,
+ 88C0: test chip;
+ 88C1: MP A-cut;
+ 92C1: MP A-cut */
+ u8 category; /* AP/NIC and USB/PCI */
+ u8 function;
+
+ __le16 major_version; /* FW Version */
+ u8 minor_version; /* FW Subversion, default 0x00 */
+ u8 reserved1;
+
+ u8 month; /* Release time Month field */
+ u8 date; /* Release time Date field */
+ u8 hour; /* Release time Hour field */
+ u8 minute; /* Release time Minute field */
+
+ __le16 ramcodesize; /* Size of RAM code */
+ u16 reserved2;
+
+ __le32 svn_idx; /* SVN entry index */
+ u32 reserved3;
+
+ u32 reserved4;
+ u32 reserved5;
+
+ u8 data[0];
+};
+
+/*
+ * The 8723au has 3 channel groups: 1-3, 4-9, and 10-14
+ */
+struct rtl8723au_idx {
+#ifdef __LITTLE_ENDIAN
+ int a:4;
+ int b:4;
+#else
+ int b:4;
+ int a:4;
+#endif
+} __attribute__((packed));
+
+struct rtl8723au_efuse {
+ __le16 rtl_id;
+ u8 res0[0xe];
+ u8 cck_tx_power_index_A[3]; /* 0x10 */
+ u8 cck_tx_power_index_B[3];
+ u8 ht40_1s_tx_power_index_A[3]; /* 0x16 */
+ u8 ht40_1s_tx_power_index_B[3];
+ /*
+ * The following entries are half-bytes split as:
+ * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed
+ */
+ struct rtl8723au_idx ht20_tx_power_index_diff[3];
+ struct rtl8723au_idx ofdm_tx_power_index_diff[3];
+ struct rtl8723au_idx ht40_max_power_offset[3];
+ struct rtl8723au_idx ht20_max_power_offset[3];
+ u8 channel_plan; /* 0x28 */
+ u8 tssi_a;
+ u8 thermal_meter;
+ u8 rf_regulatory;
+ u8 rf_option_2;
+ u8 rf_option_3;
+ u8 rf_option_4;
+ u8 res7;
+ u8 version /* 0x30 */;
+ u8 customer_id_major;
+ u8 customer_id_minor;
+ u8 xtal_k;
+ u8 chipset; /* 0x34 */
+ u8 res8[0x82];
+ u8 vid; /* 0xb7 */
+ u8 res9;
+ u8 pid; /* 0xb9 */
+ u8 res10[0x0c];
+ u8 mac_addr[ETH_ALEN]; /* 0xc6 */
+ u8 res11[2];
+ u8 vendor_name[7];
+ u8 res12[2];
+ u8 device_name[0x29]; /* 0xd7 */
+};
+
+struct rtl8192cu_efuse {
+ __le16 rtl_id;
+ __le16 hpon;
+ u8 res0[2];
+ __le16 clk;
+ __le16 testr;
+ __le16 vid;
+ __le16 did;
+ __le16 svid;
+ __le16 smid; /* 0x10 */
+ u8 res1[4];
+ u8 mac_addr[ETH_ALEN]; /* 0x16 */
+ u8 res2[2];
+ u8 vendor_name[7];
+ u8 res3[3];
+ u8 device_name[0x14]; /* 0x28 */
+ u8 res4[0x1e]; /* 0x3c */
+ u8 cck_tx_power_index_A[3]; /* 0x5a */
+ u8 cck_tx_power_index_B[3];
+ u8 ht40_1s_tx_power_index_A[3]; /* 0x60 */
+ u8 ht40_1s_tx_power_index_B[3];
+ /*
+ * The following entries are half-bytes split as:
+ * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed
+ */
+ struct rtl8723au_idx ht40_2s_tx_power_index_diff[3];
+ struct rtl8723au_idx ht20_tx_power_index_diff[3]; /* 0x69 */
+ struct rtl8723au_idx ofdm_tx_power_index_diff[3];
+ struct rtl8723au_idx ht40_max_power_offset[3]; /* 0x6f */
+ struct rtl8723au_idx ht20_max_power_offset[3];
+ u8 channel_plan; /* 0x75 */
+ u8 tssi_a;
+ u8 tssi_b;
+ u8 thermal_meter; /* xtal_k */ /* 0x78 */
+ u8 rf_regulatory;
+ u8 rf_option_2;
+ u8 rf_option_3;
+ u8 rf_option_4;
+ u8 res5[1]; /* 0x7d */
+ u8 version;
+ u8 customer_id;
+};
+
+struct rtl8xxxu_reg8val {
+ u16 reg;
+ u8 val;
+};
+
+struct rtl8xxxu_reg32val {
+ u16 reg;
+ u32 val;
+};
+
+struct rtl8xxxu_rfregval {
+ u8 reg;
+ u32 val;
+};
+
+enum rtl8xxxu_rfpath {
+ RF_A = 0,
+ RF_B = 1,
+};
+
+struct rtl8xxxu_rfregs {
+ u16 hssiparm1;
+ u16 hssiparm2;
+ u16 lssiparm;
+ u16 hspiread;
+ u16 lssiread;
+ u16 rf_sw_ctrl;
+};
+
+#define H2C_MAX_MBOX 4
+#define H2C_EXT BIT(7)
+#define H2C_SET_POWER_MODE 1
+#define H2C_JOIN_BSS_REPORT 2
+#define H2C_JOIN_BSS_DISCONNECT 0
+#define H2C_JOIN_BSS_CONNECT 1
+#define H2C_SET_RSSI 5
+#define H2C_SET_RATE_MASK (6 | H2C_EXT)
+
+struct h2c_cmd {
+ union {
+ struct {
+ u8 cmd;
+ u8 data[5];
+ } __packed cmd;
+ struct {
+ __le32 data;
+ __le16 ext;
+ } __packed raw;
+ struct {
+ u8 cmd;
+ u8 data;
+ u8 pad[4];
+ } __packed joinbss;
+ struct {
+ u8 cmd;
+ __le16 mask_hi;
+ u8 arg;
+ __le16 mask_lo;
+ } __packed ramask;
+ };
+};
+
+struct rtl8xxxu_fileops;
+
+struct rtl8xxxu_priv {
+ struct ieee80211_hw *hw;
+ struct usb_device *udev;
+ struct rtl8xxxu_fileops *fops;
+
+ spinlock_t tx_urb_lock;
+ struct list_head tx_urb_free_list;
+ int tx_urb_free_count;
+ bool tx_stopped;
+
+ spinlock_t rx_urb_lock;
+ struct list_head rx_urb_pending_list;
+ int rx_urb_pending_count;
+ bool shutdown;
+ struct work_struct rx_urb_wq;
+
+ u8 mac_addr[ETH_ALEN];
+ char chip_name[8];
+ u8 cck_tx_power_index_A[3]; /* 0x10 */
+ u8 cck_tx_power_index_B[3];
+ u8 ht40_1s_tx_power_index_A[3]; /* 0x16 */
+ u8 ht40_1s_tx_power_index_B[3];
+ /*
+ * The following entries are half-bytes split as:
+ * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed
+ */
+ struct rtl8723au_idx ht40_2s_tx_power_index_diff[3];
+ struct rtl8723au_idx ht20_tx_power_index_diff[3];
+ struct rtl8723au_idx ofdm_tx_power_index_diff[3];
+ struct rtl8723au_idx ht40_max_power_offset[3];
+ struct rtl8723au_idx ht20_max_power_offset[3];
+ u32 chip_cut:4;
+ u32 rom_rev:4;
+ u32 has_wifi:1;
+ u32 has_bluetooth:1;
+ u32 enable_bluetooth:1;
+ u32 has_gps:1;
+ u32 hi_pa:1;
+ u32 vendor_umc:1;
+ u32 has_polarity_ctrl:1;
+ u32 has_eeprom:1;
+ u32 boot_eeprom:1;
+ u32 ep_tx_high_queue:1;
+ u32 ep_tx_normal_queue:1;
+ u32 ep_tx_low_queue:1;
+ u32 path_a_hi_power:1;
+ u32 path_a_rf_paths:4;
+ unsigned int pipe_interrupt;
+ unsigned int pipe_in;
+ unsigned int pipe_out[TXDESC_QUEUE_MAX];
+ u8 out_ep[RTL8XXXU_OUT_ENDPOINTS];
+ u8 path_a_ig_value;
+ u8 ep_tx_count;
+ u8 rf_paths;
+ u8 rx_paths;
+ u8 tx_paths;
+ u32 rf_mode_ag[2];
+ u32 rege94;
+ u32 rege9c;
+ u32 regeb4;
+ u32 regebc;
+ int next_mbox;
+ int nr_out_eps;
+
+ struct mutex h2c_mutex;
+
+ struct usb_anchor rx_anchor;
+ struct usb_anchor tx_anchor;
+ struct usb_anchor int_anchor;
+ struct rtl8xxxu_firmware_header *fw_data;
+ size_t fw_size;
+ struct mutex usb_buf_mutex;
+ union {
+ __le32 val32;
+ __le16 val16;
+ u8 val8;
+ } usb_buf;
+ union {
+ u8 raw[EFUSE_MAP_LEN_8723A];
+ struct rtl8723au_efuse efuse8723;
+ struct rtl8192cu_efuse efuse8192;
+ } efuse_wifi;
+ u32 adda_backup[RTL8XXXU_ADDA_REGS];
+ u32 mac_backup[RTL8XXXU_MAC_REGS];
+ u32 bb_backup[RTL8XXXU_BB_REGS];
+ u32 bb_recovery_backup[RTL8XXXU_BB_REGS];
+ u32 rtlchip;
+ u8 pi_enabled:1;
+ u8 iqk_initialized:1;
+ u8 int_buf[USB_INTR_CONTENT_LENGTH];
+};
+
+struct rtl8xxxu_rx_urb {
+ struct urb urb;
+ struct ieee80211_hw *hw;
+ struct list_head list;
+};
+
+struct rtl8xxxu_tx_urb {
+ struct urb urb;
+ struct ieee80211_hw *hw;
+ struct list_head list;
+};
+
+struct rtl8xxxu_fileops {
+ int (*parse_efuse) (struct rtl8xxxu_priv *priv);
+ int (*load_firmware) (struct rtl8xxxu_priv *priv);
+ int (*power_on) (struct rtl8xxxu_priv *priv);
+ int writeN_block_size;
+};
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
new file mode 100644
index 000000000000..23208f79b97c
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
@@ -0,0 +1,981 @@
+/*
+ * Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com>
+ *
+ * This program 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.
+ *
+ * Register definitions taken from original Realtek rtl8723au driver
+ */
+
+/* 0x0000 ~ 0x00FF System Configuration */
+#define REG_SYS_ISO_CTRL 0x0000
+#define SYS_ISO_MD2PP BIT(0)
+#define SYS_ISO_ANALOG_IPS BIT(5)
+#define SYS_ISO_DIOR BIT(9)
+#define SYS_ISO_PWC_EV25V BIT(14)
+#define SYS_ISO_PWC_EV12V BIT(15)
+
+#define REG_SYS_FUNC 0x0002
+#define SYS_FUNC_BBRSTB BIT(0)
+#define SYS_FUNC_BB_GLB_RSTN BIT(1)
+#define SYS_FUNC_USBA BIT(2)
+#define SYS_FUNC_UPLL BIT(3)
+#define SYS_FUNC_USBD BIT(4)
+#define SYS_FUNC_DIO_PCIE BIT(5)
+#define SYS_FUNC_PCIEA BIT(6)
+#define SYS_FUNC_PPLL BIT(7)
+#define SYS_FUNC_PCIED BIT(8)
+#define SYS_FUNC_DIOE BIT(9)
+#define SYS_FUNC_CPU_ENABLE BIT(10)
+#define SYS_FUNC_DCORE BIT(11)
+#define SYS_FUNC_ELDR BIT(12)
+#define SYS_FUNC_DIO_RF BIT(13)
+#define SYS_FUNC_HWPDN BIT(14)
+#define SYS_FUNC_MREGEN BIT(15)
+
+#define REG_APS_FSMCO 0x0004
+#define APS_FSMCO_PFM_ALDN BIT(1)
+#define APS_FSMCO_PFM_WOWL BIT(3)
+#define APS_FSMCO_ENABLE_POWERDOWN BIT(4)
+#define APS_FSMCO_MAC_ENABLE BIT(8)
+#define APS_FSMCO_MAC_OFF BIT(9)
+#define APS_FSMCO_HW_SUSPEND BIT(11)
+#define APS_FSMCO_PCIE BIT(12)
+#define APS_FSMCO_HW_POWERDOWN BIT(15)
+#define APS_FSMCO_WLON_RESET BIT(16)
+
+#define REG_SYS_CLKR 0x0008
+#define SYS_CLK_ANAD16V_ENABLE BIT(0)
+#define SYS_CLK_ANA8M BIT(1)
+#define SYS_CLK_MACSLP BIT(4)
+#define SYS_CLK_LOADER_ENABLE BIT(5)
+#define SYS_CLK_80M_SSC_DISABLE BIT(7)
+#define SYS_CLK_80M_SSC_ENABLE_HO BIT(8)
+#define SYS_CLK_PHY_SSC_RSTB BIT(9)
+#define SYS_CLK_SEC_CLK_ENABLE BIT(10)
+#define SYS_CLK_MAC_CLK_ENABLE BIT(11)
+#define SYS_CLK_ENABLE BIT(12)
+#define SYS_CLK_RING_CLK_ENABLE BIT(13)
+
+#define REG_9346CR 0x000a
+#define EEPROM_BOOT BIT(4)
+#define EEPROM_ENABLE BIT(5)
+
+#define REG_EE_VPD 0x000c
+#define REG_AFE_MISC 0x0010
+#define REG_SPS0_CTRL 0x0011
+#define REG_SPS_OCP_CFG 0x0018
+#define REG_RSV_CTRL 0x001c
+
+#define REG_RF_CTRL 0x001f
+#define RF_ENABLE BIT(0)
+#define RF_RSTB BIT(1)
+#define RF_SDMRSTB BIT(2)
+
+#define REG_LDOA15_CTRL 0x0020
+#define LDOA15_ENABLE BIT(0)
+#define LDOA15_STANDBY BIT(1)
+#define LDOA15_OBUF BIT(2)
+#define LDOA15_REG_VOS BIT(3)
+#define LDOA15_VOADJ_SHIFT 4
+
+#define REG_LDOV12D_CTRL 0x0021
+#define LDOV12D_ENABLE BIT(0)
+#define LDOV12D_STANDBY BIT(1)
+#define LDOV12D_VADJ_SHIFT 4
+
+#define REG_LDOHCI12_CTRL 0x0022
+
+#define REG_LPLDO_CTRL 0x0023
+#define LPLDO_HSM BIT(2)
+#define LPLDO_LSM_DIS BIT(3)
+
+#define REG_AFE_XTAL_CTRL 0x0024
+#define AFE_XTAL_ENABLE BIT(0)
+#define AFE_XTAL_B_SELECT BIT(1)
+#define AFE_XTAL_GATE_USB BIT(8)
+#define AFE_XTAL_GATE_AFE BIT(11)
+#define AFE_XTAL_RF_GATE BIT(14)
+#define AFE_XTAL_GATE_DIG BIT(17)
+#define AFE_XTAL_BT_GATE BIT(20)
+
+#define REG_AFE_PLL_CTRL 0x0028
+#define AFE_PLL_ENABLE BIT(0)
+#define AFE_PLL_320_ENABLE BIT(1)
+#define APE_PLL_FREF_SELECT BIT(2)
+#define AFE_PLL_EDGE_SELECT BIT(3)
+#define AFE_PLL_WDOGB BIT(4)
+#define AFE_PLL_LPF_ENABLE BIT(5)
+
+#define REG_MAC_PHY_CTRL 0x002c
+
+#define REG_EFUSE_CTRL 0x0030
+#define REG_EFUSE_TEST 0x0034
+#define EFUSE_TRPT BIT(7)
+ /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */
+#define EFUSE_CELL_SEL (BIT(8) | BIT(9))
+#define EFUSE_LDOE25_ENABLE BIT(31)
+#define EFUSE_SELECT_MASK 0x0300
+#define EFUSE_WIFI_SELECT 0x0000
+#define EFUSE_BT0_SELECT 0x0100
+#define EFUSE_BT1_SELECT 0x0200
+#define EFUSE_BT2_SELECT 0x0300
+
+#define EFUSE_ACCESS_ENABLE 0x69 /* RTL8723 only */
+#define EFUSE_ACCESS_DISABLE 0x00 /* RTL8723 only */
+
+#define REG_PWR_DATA 0x0038
+#define REG_CAL_TIMER 0x003c
+#define REG_ACLK_MON 0x003e
+#define REG_GPIO_MUXCFG 0x0040
+#define REG_GPIO_IO_SEL 0x0042
+#define REG_MAC_PINMUX_CFG 0x0043
+#define REG_GPIO_PIN_CTRL 0x0044
+#define REG_GPIO_INTM 0x0048
+#define REG_LEDCFG0 0x004c
+#define REG_LEDCFG1 0x004d
+#define REG_LEDCFG2 0x004e
+#define LEDCFG2_DPDT_SELECT BIT(7)
+#define REG_LEDCFG3 0x004f
+#define REG_LEDCFG REG_LEDCFG2
+#define REG_FSIMR 0x0050
+#define REG_FSISR 0x0054
+#define REG_HSIMR 0x0058
+#define REG_HSISR 0x005c
+/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */
+#define REG_GPIO_PIN_CTRL_2 0x0060
+/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */
+#define REG_GPIO_IO_SEL_2 0x0062
+
+/* RTL8723 only WIFI/BT/GPS Multi-Function control source. */
+#define REG_MULTI_FUNC_CTRL 0x0068
+
+#define MULTI_FN_WIFI_HW_PWRDOWN_EN BIT(0) /* Enable GPIO[9] as WiFi HW
+ powerdown source */
+#define MULTI_FN_WIFI_HW_PWRDOWN_SL BIT(1) /* WiFi HW powerdown polarity
+ control */
+#define MULTI_WIFI_FUNC_EN BIT(2) /* WiFi function enable */
+
+#define MULTI_WIFI_HW_ROF_EN BIT(3) /* Enable GPIO[9] as WiFi RF HW
+ powerdown source */
+#define MULTI_BT_HW_PWRDOWN_EN BIT(16) /* Enable GPIO[11] as BT HW
+ powerdown source */
+#define MULTI_BT_HW_PWRDOWN_SL BIT(17) /* BT HW powerdown polarity
+ control */
+#define MULTI_BT_FUNC_EN BIT(18) /* BT function enable */
+#define MULTI_BT_HW_ROF_EN BIT(19) /* Enable GPIO[11] as BT/GPS
+ RF HW powerdown source */
+#define MULTI_GPS_HW_PWRDOWN_EN BIT(20) /* Enable GPIO[10] as GPS HW
+ powerdown source */
+#define MULTI_GPS_HW_PWRDOWN_SL BIT(21) /* GPS HW powerdown polarity
+ control */
+#define MULTI_GPS_FUNC_EN BIT(22) /* GPS function enable */
+
+#define REG_MCU_FW_DL 0x0080
+#define MCU_FW_DL_ENABLE BIT(0)
+#define MCU_FW_DL_READY BIT(1)
+#define MCU_FW_DL_CSUM_REPORT BIT(2)
+#define MCU_MAC_INIT_READY BIT(3)
+#define MCU_BB_INIT_READY BIT(4)
+#define MCU_RF_INIT_READY BIT(5)
+#define MCU_WINT_INIT_READY BIT(6)
+#define MCU_FW_RAM_SEL BIT(7) /* 1: RAM, 0:ROM */
+#define MCU_CP_RESET BIT(23)
+
+#define REG_HMBOX_EXT_0 0x0088
+#define REG_HMBOX_EXT_1 0x008a
+#define REG_HMBOX_EXT_2 0x008c
+#define REG_HMBOX_EXT_3 0x008e
+/* Host suspend counter on FPGA platform */
+#define REG_HOST_SUSP_CNT 0x00bc
+/* Efuse access protection for RTL8723 */
+#define REG_EFUSE_ACCESS 0x00cf
+#define REG_BIST_SCAN 0x00d0
+#define REG_BIST_RPT 0x00d4
+#define REG_BIST_ROM_RPT 0x00d8
+#define REG_USB_SIE_INTF 0x00e0
+#define REG_PCIE_MIO_INTF 0x00e4
+#define REG_PCIE_MIO_INTD 0x00e8
+#define REG_HPON_FSM 0x00ec
+#define HPON_FSM_BONDING_MASK (BIT(22) | BIT(23))
+#define HPON_FSM_BONDING_1T2R BIT(22)
+#define REG_SYS_CFG 0x00f0
+#define SYS_CFG_XCLK_VLD BIT(0)
+#define SYS_CFG_ACLK_VLD BIT(1)
+#define SYS_CFG_UCLK_VLD BIT(2)
+#define SYS_CFG_PCLK_VLD BIT(3)
+#define SYS_CFG_PCIRSTB BIT(4)
+#define SYS_CFG_V15_VLD BIT(5)
+#define SYS_CFG_TRP_B15V_EN BIT(7)
+#define SYS_CFG_SIC_IDLE BIT(8)
+#define SYS_CFG_BD_MAC2 BIT(9)
+#define SYS_CFG_BD_MAC1 BIT(10)
+#define SYS_CFG_IC_MACPHY_MODE BIT(11)
+#define SYS_CFG_CHIP_VER (BIT(12) | BIT(13) | BIT(14) | BIT(15))
+#define SYS_CFG_BT_FUNC BIT(16)
+#define SYS_CFG_VENDOR_ID BIT(19)
+#define SYS_CFG_PAD_HWPD_IDN BIT(22)
+#define SYS_CFG_TRP_VAUX_EN BIT(23)
+#define SYS_CFG_TRP_BT_EN BIT(24)
+#define SYS_CFG_BD_PKG_SEL BIT(25)
+#define SYS_CFG_BD_HCI_SEL BIT(26)
+#define SYS_CFG_TYPE_ID BIT(27)
+#define SYS_CFG_RTL_ID BIT(23) /* TestChip ID,
+ 1:Test(RLE); 0:MP(RL) */
+#define SYS_CFG_SPS_SEL BIT(24) /* 1:LDO regulator mode;
+ 0:Switching regulator mode*/
+#define SYS_CFG_CHIP_VERSION_MASK 0xf000 /* Bit 12 - 15 */
+#define SYS_CFG_CHIP_VERSION_SHIFT 12
+
+#define REG_GPIO_OUTSTS 0x00f4 /* For RTL8723 only. */
+#define GPIO_EFS_HCI_SEL (BIT(0) | BIT(1))
+#define GPIO_PAD_HCI_SEL (BIT(2) | BIT(3))
+#define GPIO_HCI_SEL (BIT(4) | BIT(5))
+#define GPIO_PKG_SEL_HCI BIT(6)
+#define GPIO_FEN_GPS BIT(7)
+#define GPIO_FEN_BT BIT(8)
+#define GPIO_FEN_WL BIT(9)
+#define GPIO_FEN_PCI BIT(10)
+#define GPIO_FEN_USB BIT(11)
+#define GPIO_BTRF_HWPDN_N BIT(12)
+#define GPIO_WLRF_HWPDN_N BIT(13)
+#define GPIO_PDN_BT_N BIT(14)
+#define GPIO_PDN_GPS_N BIT(15)
+#define GPIO_BT_CTL_HWPDN BIT(16)
+#define GPIO_GPS_CTL_HWPDN BIT(17)
+#define GPIO_PPHY_SUSB BIT(20)
+#define GPIO_UPHY_SUSB BIT(21)
+#define GPIO_PCI_SUSEN BIT(22)
+#define GPIO_USB_SUSEN BIT(23)
+#define GPIO_RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28))
+
+/* 0x0100 ~ 0x01FF MACTOP General Configuration */
+#define REG_CR 0x0100
+#define CR_HCI_TXDMA_ENABLE BIT(0)
+#define CR_HCI_RXDMA_ENABLE BIT(1)
+#define CR_TXDMA_ENABLE BIT(2)
+#define CR_RXDMA_ENABLE BIT(3)
+#define CR_PROTOCOL_ENABLE BIT(4)
+#define CR_SCHEDULE_ENABLE BIT(5)
+#define CR_MAC_TX_ENABLE BIT(6)
+#define CR_MAC_RX_ENABLE BIT(7)
+#define CR_SW_BEACON_ENABLE BIT(8)
+#define CR_SECURITY_ENABLE BIT(9)
+#define CR_CALTIMER_ENABLE BIT(10)
+
+/* Media Status Register */
+#define REG_MSR 0x0102
+#define MSR_LINKTYPE_MASK 0x3
+#define MSR_LINKTYPE_NONE 0x0
+#define MSR_LINKTYPE_ADHOC 0x1
+#define MSR_LINKTYPE_STATION 0x2
+#define MSR_LINKTYPE_AP 0x3
+
+#define REG_PBP 0x0104
+#define PBP_PAGE_SIZE_RX_SHIFT 0
+#define PBP_PAGE_SIZE_TX_SHIFT 4
+#define PBP_PAGE_SIZE_64 0x0
+#define PBP_PAGE_SIZE_128 0x1
+#define PBP_PAGE_SIZE_256 0x2
+#define PBP_PAGE_SIZE_512 0x3
+#define PBP_PAGE_SIZE_1024 0x4
+
+#define REG_TRXDMA_CTRL 0x010c
+#define TRXDMA_CTRL_VOQ_SHIFT 4
+#define TRXDMA_CTRL_VIQ_SHIFT 6
+#define TRXDMA_CTRL_BEQ_SHIFT 8
+#define TRXDMA_CTRL_BKQ_SHIFT 10
+#define TRXDMA_CTRL_MGQ_SHIFT 12
+#define TRXDMA_CTRL_HIQ_SHIFT 14
+#define TRXDMA_QUEUE_LOW 1
+#define TRXDMA_QUEUE_NORMAL 2
+#define TRXDMA_QUEUE_HIGH 3
+
+#define REG_TRXFF_BNDY 0x0114
+#define REG_TRXFF_STATUS 0x0118
+#define REG_RXFF_PTR 0x011c
+#define REG_HIMR 0x0120
+#define REG_HISR 0x0124
+#define REG_HIMRE 0x0128
+#define REG_HISRE 0x012c
+#define REG_CPWM 0x012f
+#define REG_FWIMR 0x0130
+#define REG_FWISR 0x0134
+#define REG_PKTBUF_DBG_CTRL 0x0140
+#define REG_PKTBUF_DBG_DATA_L 0x0144
+#define REG_PKTBUF_DBG_DATA_H 0x0148
+
+#define REG_TC0_CTRL 0x0150
+#define REG_TC1_CTRL 0x0154
+#define REG_TC2_CTRL 0x0158
+#define REG_TC3_CTRL 0x015c
+#define REG_TC4_CTRL 0x0160
+#define REG_TCUNIT_BASE 0x0164
+#define REG_MBIST_START 0x0174
+#define REG_MBIST_DONE 0x0178
+#define REG_MBIST_FAIL 0x017c
+#define REG_C2HEVT_MSG_NORMAL 0x01a0
+#define REG_C2HEVT_CLEAR 0x01af
+#define REG_C2HEVT_MSG_TEST 0x01b8
+#define REG_MCUTST_1 0x01c0
+#define REG_FMTHR 0x01c8
+#define REG_HMTFR 0x01cc
+#define REG_HMBOX_0 0x01d0
+#define REG_HMBOX_1 0x01d4
+#define REG_HMBOX_2 0x01d8
+#define REG_HMBOX_3 0x01dc
+
+#define REG_LLT_INIT 0x01e0
+#define LLT_OP_INACTIVE 0x0
+#define LLT_OP_WRITE (0x1 << 30)
+#define LLT_OP_READ (0x2 << 30)
+#define LLT_OP_MASK (0x3 << 30)
+
+#define REG_BB_ACCEESS_CTRL 0x01e8
+#define REG_BB_ACCESS_DATA 0x01ec
+
+/* 0x0200 ~ 0x027F TXDMA Configuration */
+#define REG_RQPN 0x0200
+#define RQPN_HI_PQ_SHIFT 0
+#define RQPN_LO_PQ_SHIFT 8
+#define RQPN_NORM_PQ_SHIFT 16
+#define RQPN_LOAD BIT(31)
+
+#define REG_FIFOPAGE 0x0204
+#define REG_TDECTRL 0x0208
+#define REG_TXDMA_OFFSET_CHK 0x020c
+#define REG_TXDMA_STATUS 0x0210
+#define REG_RQPN_NPQ 0x0214
+
+/* 0x0280 ~ 0x02FF RXDMA Configuration */
+#define REG_RXDMA_AGG_PG_TH 0x0280
+#define REG_RXPKT_NUM 0x0284
+#define REG_RXDMA_STATUS 0x0288
+
+#define REG_RF_BB_CMD_ADDR 0x02c0
+#define REG_RF_BB_CMD_DATA 0x02c4
+
+/* spec version 11 */
+/* 0x0400 ~ 0x047F Protocol Configuration */
+#define REG_VOQ_INFORMATION 0x0400
+#define REG_VIQ_INFORMATION 0x0404
+#define REG_BEQ_INFORMATION 0x0408
+#define REG_BKQ_INFORMATION 0x040c
+#define REG_MGQ_INFORMATION 0x0410
+#define REG_HGQ_INFORMATION 0x0414
+#define REG_BCNQ_INFORMATION 0x0418
+
+#define REG_CPU_MGQ_INFORMATION 0x041c
+#define REG_FWHW_TXQ_CTRL 0x0420
+#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7)
+#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12)
+
+#define REG_HWSEQ_CTRL 0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
+#define REG_TXPKTBUF_MGQ_BDNY 0x0425
+#define REG_LIFETIME_EN 0x0426
+#define REG_MULTI_BCNQ_OFFSET 0x0427
+
+#define REG_SPEC_SIFS 0x0428
+#define SPEC_SIFS_CCK_MASK 0x00ff
+#define SPEC_SIFS_CCK_SHIFT 0
+#define SPEC_SIFS_OFDM_MASK 0xff00
+#define SPEC_SIFS_OFDM_SHIFT 8
+
+#define REG_RETRY_LIMIT 0x042a
+#define RETRY_LIMIT_LONG_SHIFT 0
+#define RETRY_LIMIT_LONG_MASK 0x003f
+#define RETRY_LIMIT_SHORT_SHIFT 8
+#define RETRY_LIMIT_SHORT_MASK 0x3f00
+
+#define REG_DARFRC 0x0430
+#define REG_RARFRC 0x0438
+#define REG_RESPONSE_RATE_SET 0x0440
+#define RESPONSE_RATE_BITMAP_ALL 0xfffff
+#define RESPONSE_RATE_RRSR_CCK_ONLY_1M 0xffff1
+#define RSR_1M BIT(0)
+#define RSR_2M BIT(1)
+#define RSR_5_5M BIT(2)
+#define RSR_11M BIT(3)
+#define RSR_6M BIT(4)
+#define RSR_9M BIT(5)
+#define RSR_12M BIT(6)
+#define RSR_18M BIT(7)
+#define RSR_24M BIT(8)
+#define RSR_36M BIT(9)
+#define RSR_48M BIT(10)
+#define RSR_54M BIT(11)
+#define RSR_MCS0 BIT(12)
+#define RSR_MCS1 BIT(13)
+#define RSR_MCS2 BIT(14)
+#define RSR_MCS3 BIT(15)
+#define RSR_MCS4 BIT(16)
+#define RSR_MCS5 BIT(17)
+#define RSR_MCS6 BIT(18)
+#define RSR_MCS7 BIT(19)
+#define RSR_RSC_LOWER_SUB_CHANNEL BIT(21) /* 0x200000 */
+#define RSR_RSC_UPPER_SUB_CHANNEL BIT(22) /* 0x400000 */
+#define RSR_RSC_BANDWIDTH_40M (RSR_RSC_UPPER_SUB_CHANNEL | \
+ RSR_RSC_LOWER_SUB_CHANNEL)
+#define RSR_ACK_SHORT_PREAMBLE BIT(23)
+
+#define REG_ARFR0 0x0444
+#define REG_ARFR1 0x0448
+#define REG_ARFR2 0x044c
+#define REG_ARFR3 0x0450
+#define REG_AGGLEN_LMT 0x0458
+#define REG_AMPDU_MIN_SPACE 0x045c
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045d
+#define REG_FAST_EDCA_CTRL 0x0460
+#define REG_RD_RESP_PKT_TH 0x0463
+#define REG_INIRTS_RATE_SEL 0x0480
+#define REG_INIDATA_RATE_SEL 0x0484
+
+#define REG_POWER_STATUS 0x04a4
+#define REG_POWER_STAGE1 0x04b4
+#define REG_POWER_STAGE2 0x04b8
+#define REG_PKT_VO_VI_LIFE_TIME 0x04c0
+#define REG_PKT_BE_BK_LIFE_TIME 0x04c2
+#define REG_STBC_SETTING 0x04c4
+#define REG_PROT_MODE_CTRL 0x04c8
+#define REG_MAX_AGGR_NUM 0x04ca
+#define REG_RTS_MAX_AGGR_NUM 0x04cb
+#define REG_BAR_MODE_CTRL 0x04cc
+#define REG_RA_TRY_RATE_AGG_LMT 0x04cf
+#define REG_NQOS_SEQ 0x04dc
+#define REG_QOS_SEQ 0x04de
+#define REG_NEED_CPU_HANDLE 0x04e0
+#define REG_PKT_LOSE_RPT 0x04e1
+#define REG_PTCL_ERR_STATUS 0x04e2
+#define REG_DUMMY 0x04fc
+
+/* 0x0500 ~ 0x05FF EDCA Configuration */
+#define REG_EDCA_VO_PARAM 0x0500
+#define REG_EDCA_VI_PARAM 0x0504
+#define REG_EDCA_BE_PARAM 0x0508
+#define REG_EDCA_BK_PARAM 0x050c
+#define EDCA_PARAM_ECW_MIN_SHIFT 8
+#define EDCA_PARAM_ECW_MAX_SHIFT 12
+#define EDCA_PARAM_TXOP_SHIFT 16
+#define REG_BEACON_TCFG 0x0510
+#define REG_PIFS 0x0512
+#define REG_RDG_PIFS 0x0513
+#define REG_SIFS_CCK 0x0514
+#define REG_SIFS_OFDM 0x0516
+#define REG_TSFTR_SYN_OFFSET 0x0518
+#define REG_AGGR_BREAK_TIME 0x051a
+#define REG_SLOT 0x051b
+#define REG_TX_PTCL_CTRL 0x0520
+#define REG_TXPAUSE 0x0522
+#define REG_DIS_TXREQ_CLR 0x0523
+#define REG_RD_CTRL 0x0524
+#define REG_TBTT_PROHIBIT 0x0540
+#define REG_RD_NAV_NXT 0x0544
+#define REG_NAV_PROT_LEN 0x0546
+
+#define REG_BEACON_CTRL 0x0550
+#define REG_BEACON_CTRL_1 0x0551
+#define BEACON_ATIM BIT(0)
+#define BEACON_CTRL_MBSSID BIT(1)
+#define BEACON_CTRL_TX_BEACON_RPT BIT(2)
+#define BEACON_FUNCTION_ENABLE BIT(3)
+#define BEACON_DISABLE_TSF_UPDATE BIT(4)
+
+#define REG_MBID_NUM 0x0552
+#define REG_DUAL_TSF_RST 0x0553
+#define DUAL_TSF_RESET_TSF0 BIT(0)
+#define DUAL_TSF_RESET_TSF1 BIT(1)
+#define DUAL_TSF_RESET_P2P BIT(4)
+#define DUAL_TSF_TX_OK BIT(5)
+
+/* The same as REG_MBSSID_BCN_SPACE */
+#define REG_BCN_INTERVAL 0x0554
+#define REG_MBSSID_BCN_SPACE 0x0554
+
+#define REG_DRIVER_EARLY_INT 0x0558
+#define DRIVER_EARLY_INT_TIME 5
+
+#define REG_BEACON_DMA_TIME 0x0559
+#define BEACON_DMA_ATIME_INT_TIME 2
+
+#define REG_ATIMWND 0x055a
+#define REG_BCN_MAX_ERR 0x055d
+#define REG_RXTSF_OFFSET_CCK 0x055e
+#define REG_RXTSF_OFFSET_OFDM 0x055f
+#define REG_TSFTR 0x0560
+#define REG_TSFTR1 0x0568
+#define REG_INIT_TSFTR 0x0564
+#define REG_ATIMWND_1 0x0570
+#define REG_PSTIMER 0x0580
+#define REG_TIMER0 0x0584
+#define REG_TIMER1 0x0588
+#define REG_ACM_HW_CTRL 0x05c0
+#define ACM_HW_CTRL_BK BIT(0)
+#define ACM_HW_CTRL_BE BIT(1)
+#define ACM_HW_CTRL_VI BIT(2)
+#define ACM_HW_CTRL_VO BIT(3)
+#define REG_ACM_RST_CTRL 0x05c1
+#define REG_ACMAVG 0x05c2
+#define REG_VO_ADMTIME 0x05c4
+#define REG_VI_ADMTIME 0x05c6
+#define REG_BE_ADMTIME 0x05c8
+#define REG_EDCA_RANDOM_GEN 0x05cc
+#define REG_SCH_TXCMD 0x05d0
+
+/* define REG_FW_TSF_SYNC_CNT 0x04a0 */
+#define REG_FW_RESET_TSF_CNT_1 0x05fc
+#define REG_FW_RESET_TSF_CNT_0 0x05fd
+#define REG_FW_BCN_DIS_CNT 0x05fe
+
+/* 0x0600 ~ 0x07FF WMAC Configuration */
+#define REG_APSD_CTRL 0x0600
+#define APSD_CTRL_OFF BIT(6)
+#define APSD_CTRL_OFF_STATUS BIT(7)
+#define REG_BW_OPMODE 0x0603
+#define BW_OPMODE_20MHZ BIT(2)
+#define BW_OPMODE_5G BIT(1)
+#define BW_OPMODE_11J BIT(0)
+
+#define REG_TCR 0x0604
+
+/* Receive Configuration Register */
+#define REG_RCR 0x0608
+#define RCR_ACCEPT_AP BIT(0) /* Accept all unicast packet */
+#define RCR_ACCEPT_PHYS_MATCH BIT(1) /* Accept phys match packet */
+#define RCR_ACCEPT_MCAST BIT(2)
+#define RCR_ACCEPT_BCAST BIT(3)
+#define RCR_ACCEPT_ADDR3 BIT(4) /* Accept address 3 match
+ packet */
+#define RCR_ACCEPT_PM BIT(5) /* Accept power management
+ packet */
+#define RCR_CHECK_BSSID_MATCH BIT(6) /* Accept BSSID match packet */
+#define RCR_CHECK_BSSID_BEACON BIT(7) /* Accept BSSID match packet
+ (Rx beacon, probe rsp) */
+#define RCR_ACCEPT_CRC32 BIT(8) /* Accept CRC32 error packet */
+#define RCR_ACCEPT_ICV BIT(9) /* Accept ICV error packet */
+#define RCR_ACCEPT_DATA_FRAME BIT(11)
+#define RCR_ACCEPT_CTRL_FRAME BIT(12)
+#define RCR_ACCEPT_MGMT_FRAME BIT(13)
+#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */
+#define RCR_MFBEN BIT(22)
+#define RCR_LSIGEN BIT(23)
+#define RCR_MULTI_BSSID_ENABLE BIT(24) /* Enable Multiple BssId */
+#define RCR_ACCEPT_BA_SSN BIT(27) /* Accept BA SSN */
+#define RCR_APPEND_PHYSTAT BIT(28)
+#define RCR_APPEND_ICV BIT(29)
+#define RCR_APPEND_MIC BIT(30)
+#define RCR_APPEND_FCS BIT(31) /* WMAC append FCS after */
+
+#define REG_RX_PKT_LIMIT 0x060c
+#define REG_RX_DLK_TIME 0x060d
+#define REG_RX_DRVINFO_SZ 0x060f
+
+#define REG_MACID 0x0610
+#define REG_BSSID 0x0618
+#define REG_MAR 0x0620
+#define REG_MBIDCAMCFG 0x0628
+
+#define REG_USTIME_EDCA 0x0638
+#define REG_MAC_SPEC_SIFS 0x063a
+
+/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */
+ /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */
+#define REG_R2T_SIFS 0x063c
+ /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */
+#define REG_T2T_SIFS 0x063e
+#define REG_ACKTO 0x0640
+#define REG_CTS2TO 0x0641
+#define REG_EIFS 0x0642
+
+/* WMA, BA, CCX */
+#define REG_NAV_CTRL 0x0650
+/* In units of 128us */
+#define REG_NAV_UPPER 0x0652
+#define NAV_UPPER_UNIT 128
+
+#define REG_BACAMCMD 0x0654
+#define REG_BACAMCONTENT 0x0658
+#define REG_LBDLY 0x0660
+#define REG_FWDLY 0x0661
+#define REG_RXERR_RPT 0x0664
+#define REG_WMAC_TRXPTCL_CTL 0x0668
+
+/* Security */
+#define REG_CAM_CMD 0x0670
+#define CAM_CMD_POLLING BIT(31)
+#define CAM_CMD_WRITE BIT(16)
+#define CAM_CMD_KEY_SHIFT 3
+#define REG_CAM_WRITE 0x0674
+#define CAM_WRITE_VALID BIT(15)
+#define REG_CAM_READ 0x0678
+#define REG_CAM_DEBUG 0x067c
+#define REG_SECURITY_CFG 0x0680
+#define SEC_CFG_TX_USE_DEFKEY BIT(0)
+#define SEC_CFG_RX_USE_DEFKEY BIT(1)
+#define SEC_CFG_TX_SEC_ENABLE BIT(2)
+#define SEC_CFG_RX_SEC_ENABLE BIT(3)
+#define SEC_CFG_SKBYA2 BIT(4)
+#define SEC_CFG_NO_SKMC BIT(5)
+#define SEC_CFG_TXBC_USE_DEFKEY BIT(6)
+#define SEC_CFG_RXBC_USE_DEFKEY BIT(7)
+
+/* Power */
+#define REG_WOW_CTRL 0x0690
+#define REG_PSSTATUS 0x0691
+#define REG_PS_RX_INFO 0x0692
+#define REG_LPNAV_CTRL 0x0694
+#define REG_WKFMCAM_CMD 0x0698
+#define REG_WKFMCAM_RWD 0x069c
+#define REG_RXFLTMAP0 0x06a0
+#define REG_RXFLTMAP1 0x06a2
+#define REG_RXFLTMAP2 0x06a4
+#define REG_BCN_PSR_RPT 0x06a8
+#define REG_CALB32K_CTRL 0x06ac
+#define REG_PKT_MON_CTRL 0x06b4
+#define REG_BT_COEX_TABLE 0x06c0
+#define REG_WMAC_RESP_TXINFO 0x06d8
+
+#define REG_MACID1 0x0700
+#define REG_BSSID1 0x0708
+
+#define REG_FPGA0_RF_MODE 0x0800
+#define FPGA_RF_MODE BIT(0)
+#define FPGA_RF_MODE_JAPAN BIT(1)
+#define FPGA_RF_MODE_CCK BIT(24)
+#define FPGA_RF_MODE_OFDM BIT(25)
+
+#define REG_FPGA0_TX_INFO 0x0804
+#define REG_FPGA0_PSD_FUNC 0x0808
+#define REG_FPGA0_TX_GAIN 0x080c
+#define REG_FPGA0_RF_TIMING1 0x0810
+#define REG_FPGA0_RF_TIMING2 0x0814
+#define REG_FPGA0_POWER_SAVE 0x0818
+#define FPGA0_PS_LOWER_CHANNEL BIT(26)
+#define FPGA0_PS_UPPER_CHANNEL BIT(27)
+
+#define REG_FPGA0_XA_HSSI_PARM1 0x0820 /* RF 3 wire register */
+#define FPGA0_HSSI_PARM1_PI BIT(8)
+#define REG_FPGA0_XA_HSSI_PARM2 0x0824
+#define REG_FPGA0_XB_HSSI_PARM1 0x0828
+#define REG_FPGA0_XB_HSSI_PARM2 0x082c
+#define FPGA0_HSSI_3WIRE_DATA_LEN 0x800
+#define FPGA0_HSSI_3WIRE_ADDR_LEN 0x400
+#define FPGA0_HSSI_PARM2_ADDR_SHIFT 23
+#define FPGA0_HSSI_PARM2_ADDR_MASK 0x7f800000 /* 0xff << 23 */
+#define FPGA0_HSSI_PARM2_CCK_HIGH_PWR BIT(9)
+#define FPGA0_HSSI_PARM2_EDGE_READ BIT(31)
+
+#define REG_TX_AGC_B_RATE18_06 0x0830
+#define REG_TX_AGC_B_RATE54_24 0x0834
+#define REG_TX_AGC_B_CCK1_55_MCS32 0x0838
+#define REG_TX_AGC_B_MCS03_MCS00 0x083c
+
+#define REG_FPGA0_XA_LSSI_PARM 0x0840
+#define REG_FPGA0_XB_LSSI_PARM 0x0844
+#define FPGA0_LSSI_PARM_ADDR_SHIFT 20
+#define FPGA0_LSSI_PARM_ADDR_MASK 0x0ff00000
+#define FPGA0_LSSI_PARM_DATA_MASK 0x000fffff
+
+#define REG_TX_AGC_B_MCS07_MCS04 0x0848
+#define REG_TX_AGC_B_MCS11_MCS08 0x084c
+
+#define REG_FPGA0_XCD_SWITCH_CTRL 0x085c
+
+#define REG_FPGA0_XA_RF_INT_OE 0x0860 /* RF Channel switch */
+#define REG_FPGA0_XB_RF_INT_OE 0x0864
+#define FPGA0_INT_OE_ANTENNA_AB_OPEN 0x000
+#define FPGA0_INT_OE_ANTENNA_A BIT(8)
+#define FPGA0_INT_OE_ANTENNA_B BIT(9)
+#define FPGA0_INT_OE_ANTENNA_MASK (FPGA0_INT_OE_ANTENNA_A | \
+ FPGA0_INT_OE_ANTENNA_B)
+
+#define REG_TX_AGC_B_MCS15_MCS12 0x0868
+#define REG_TX_AGC_B_CCK11_A_CCK2_11 0x086c
+
+#define REG_FPGA0_XAB_RF_SW_CTRL 0x0870
+#define REG_FPGA0_XA_RF_SW_CTRL 0x0870 /* 16 bit */
+#define REG_FPGA0_XB_RF_SW_CTRL 0x0872 /* 16 bit */
+#define REG_FPGA0_XCD_RF_SW_CTRL 0x0874
+#define REG_FPGA0_XC_RF_SW_CTRL 0x0874 /* 16 bit */
+#define REG_FPGA0_XD_RF_SW_CTRL 0x0876 /* 16 bit */
+#define FPGA0_RF_3WIRE_DATA BIT(0)
+#define FPGA0_RF_3WIRE_CLOC BIT(1)
+#define FPGA0_RF_3WIRE_LOAD BIT(2)
+#define FPGA0_RF_3WIRE_RW BIT(3)
+#define FPGA0_RF_3WIRE_MASK 0xf
+#define FPGA0_RF_RFENV BIT(4)
+#define FPGA0_RF_TRSW BIT(5) /* Useless now */
+#define FPGA0_RF_TRSWB BIT(6)
+#define FPGA0_RF_ANTSW BIT(8)
+#define FPGA0_RF_ANTSWB BIT(9)
+#define FPGA0_RF_PAPE BIT(10)
+#define FPGA0_RF_PAPE5G BIT(11)
+#define FPGA0_RF_BD_CTRL_SHIFT 16
+
+#define REG_FPGA0_XAB_RF_PARM 0x0878 /* Antenna select path in ODM */
+#define REG_FPGA0_XA_RF_PARM 0x0878 /* 16 bit */
+#define REG_FPGA0_XB_RF_PARM 0x087a /* 16 bit */
+#define REG_FPGA0_XCD_RF_PARM 0x087c
+#define REG_FPGA0_XC_RF_PARM 0x087c /* 16 bit */
+#define REG_FPGA0_XD_RF_PARM 0x087e /* 16 bit */
+#define FPGA0_RF_PARM_RFA_ENABLE BIT(1)
+#define FPGA0_RF_PARM_RFB_ENABLE BIT(17)
+#define FPGA0_RF_PARM_CLK_GATE BIT(31)
+
+#define REG_FPGA0_ANALOG1 0x0880
+#define REG_FPGA0_ANALOG2 0x0884
+#define FPGA0_ANALOG2_20MHZ BIT(10)
+#define REG_FPGA0_ANALOG3 0x0888
+#define REG_FPGA0_ANALOG4 0x088c
+
+#define REG_FPGA0_XA_LSSI_READBACK 0x08a0 /* Tranceiver LSSI Readback */
+#define REG_FPGA0_XB_LSSI_READBACK 0x08a4
+#define REG_HSPI_XA_READBACK 0x08b8 /* Transceiver A HSPI read */
+#define REG_HSPI_XB_READBACK 0x08bc /* Transceiver B HSPI read */
+
+#define REG_FPGA1_RF_MODE 0x0900
+
+#define REG_FPGA1_TX_INFO 0x090c
+
+#define REG_CCK0_SYSTEM 0x0a00
+#define CCK0_SIDEBAND BIT(4)
+
+#define REG_CCK0_AFE_SETTING 0x0a04
+
+#define REG_CONFIG_ANT_A 0x0b68
+#define REG_CONFIG_ANT_B 0x0b6c
+
+#define REG_OFDM0_TRX_PATH_ENABLE 0x0c04
+#define OFDM_RF_PATH_RX_MASK 0x0f
+#define OFDM_RF_PATH_RX_A BIT(0)
+#define OFDM_RF_PATH_RX_B BIT(1)
+#define OFDM_RF_PATH_RX_C BIT(2)
+#define OFDM_RF_PATH_RX_D BIT(3)
+#define OFDM_RF_PATH_TX_MASK 0xf0
+#define OFDM_RF_PATH_TX_A BIT(4)
+#define OFDM_RF_PATH_TX_B BIT(5)
+#define OFDM_RF_PATH_TX_C BIT(6)
+#define OFDM_RF_PATH_TX_D BIT(7)
+
+#define REG_OFDM0_TR_MUX_PAR 0x0c08
+
+#define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14
+#define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c
+
+#define REG_OFDM0_ENERGY_CCA_THRES 0x0c4c
+
+#define REG_OFDM0_XA_AGC_CORE1 0x0c50
+#define REG_OFDM0_XA_AGC_CORE2 0x0c54
+#define REG_OFDM0_XB_AGC_CORE1 0x0c58
+#define REG_OFDM0_XB_AGC_CORE2 0x0c5c
+#define REG_OFDM0_XC_AGC_CORE1 0x0c60
+#define REG_OFDM0_XC_AGC_CORE2 0x0c64
+#define REG_OFDM0_XD_AGC_CORE1 0x0c68
+#define REG_OFDM0_XD_AGC_CORE2 0x0c6c
+#define OFDM0_X_AGC_CORE1_IGI_MASK 0x0000007F
+
+#define REG_OFDM0_AGC_PARM1 0x0c70
+
+#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78
+
+#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80
+#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88
+#define REG_OFDM0_XC_TX_IQ_IMBALANCE 0x0c90
+#define REG_OFDM0_XD_TX_IQ_IMBALANCE 0x0c98
+
+#define REG_OFDM0_XC_TX_AFE 0x0c94
+#define REG_OFDM0_XD_TX_AFE 0x0c9c
+
+#define REG_OFDM0_RX_IQ_EXT_ANTA 0x0ca0
+
+#define REG_OFDM1_LSTF 0x0d00
+#define OFDM_LSTF_PRIME_CH_LOW BIT(10)
+#define OFDM_LSTF_PRIME_CH_HIGH BIT(11)
+#define OFDM_LSTF_PRIME_CH_MASK (OFDM_LSTF_PRIME_CH_LOW | \
+ OFDM_LSTF_PRIME_CH_HIGH)
+#define OFDM_LSTF_CONTINUE_TX BIT(28)
+#define OFDM_LSTF_SINGLE_CARRIER BIT(29)
+#define OFDM_LSTF_SINGLE_TONE BIT(30)
+#define OFDM_LSTF_MASK 0x70000000
+
+#define REG_OFDM1_TRX_PATH_ENABLE 0x0d04
+
+#define REG_TX_AGC_A_RATE18_06 0x0e00
+#define REG_TX_AGC_A_RATE54_24 0x0e04
+#define REG_TX_AGC_A_CCK1_MCS32 0x0e08
+#define REG_TX_AGC_A_MCS03_MCS00 0x0e10
+#define REG_TX_AGC_A_MCS07_MCS04 0x0e14
+#define REG_TX_AGC_A_MCS11_MCS08 0x0e18
+#define REG_TX_AGC_A_MCS15_MCS12 0x0e1c
+
+#define REG_FPGA0_IQK 0x0e28
+
+#define REG_TX_IQK_TONE_A 0x0e30
+#define REG_RX_IQK_TONE_A 0x0e34
+#define REG_TX_IQK_PI_A 0x0e38
+#define REG_RX_IQK_PI_A 0x0e3c
+
+#define REG_TX_IQK 0x0e40
+#define REG_RX_IQK 0x0e44
+#define REG_IQK_AGC_PTS 0x0e48
+#define REG_IQK_AGC_RSP 0x0e4c
+#define REG_TX_IQK_TONE_B 0x0e50
+#define REG_RX_IQK_TONE_B 0x0e54
+#define REG_TX_IQK_PI_B 0x0e58
+#define REG_RX_IQK_PI_B 0x0e5c
+#define REG_IQK_AGC_CONT 0x0e60
+
+#define REG_BLUETOOTH 0x0e6c
+#define REG_RX_WAIT_CCA 0x0e70
+#define REG_TX_CCK_RFON 0x0e74
+#define REG_TX_CCK_BBON 0x0e78
+#define REG_TX_OFDM_RFON 0x0e7c
+#define REG_TX_OFDM_BBON 0x0e80
+#define REG_TX_TO_RX 0x0e84
+#define REG_TX_TO_TX 0x0e88
+#define REG_RX_CCK 0x0e8c
+
+#define REG_TX_POWER_BEFORE_IQK_A 0x0e94
+#define REG_TX_POWER_AFTER_IQK_A 0x0e9c
+
+#define REG_RX_POWER_BEFORE_IQK_A 0x0ea0
+#define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4
+#define REG_RX_POWER_AFTER_IQK_A 0x0ea8
+#define REG_RX_POWER_AFTER_IQK_A_2 0x0eac
+
+#define REG_TX_POWER_BEFORE_IQK_B 0x0eb4
+#define REG_TX_POWER_AFTER_IQK_B 0x0ebc
+
+#define REG_RX_POWER_BEFORE_IQK_B 0x0ec0
+#define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4
+#define REG_RX_POWER_AFTER_IQK_B 0x0ec8
+#define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc
+
+#define REG_RX_OFDM 0x0ed0
+#define REG_RX_WAIT_RIFS 0x0ed4
+#define REG_RX_TO_RX 0x0ed8
+#define REG_STANDBY 0x0edc
+#define REG_SLEEP 0x0ee0
+#define REG_PMPD_ANAEN 0x0eec
+
+#define REG_FW_START_ADDRESS 0x1000
+
+#define REG_USB_INFO 0xfe17
+#define REG_USB_HIMR 0xfe38
+#define USB_HIMR_TIMEOUT2 BIT(31)
+#define USB_HIMR_TIMEOUT1 BIT(30)
+#define USB_HIMR_PSTIMEOUT BIT(29)
+#define USB_HIMR_GTINT4 BIT(28)
+#define USB_HIMR_GTINT3 BIT(27)
+#define USB_HIMR_TXBCNERR BIT(26)
+#define USB_HIMR_TXBCNOK BIT(25)
+#define USB_HIMR_TSF_BIT32_TOGGLE BIT(24)
+#define USB_HIMR_BCNDMAINT3 BIT(23)
+#define USB_HIMR_BCNDMAINT2 BIT(22)
+#define USB_HIMR_BCNDMAINT1 BIT(21)
+#define USB_HIMR_BCNDMAINT0 BIT(20)
+#define USB_HIMR_BCNDOK3 BIT(19)
+#define USB_HIMR_BCNDOK2 BIT(18)
+#define USB_HIMR_BCNDOK1 BIT(17)
+#define USB_HIMR_BCNDOK0 BIT(16)
+#define USB_HIMR_HSISR_IND BIT(15)
+#define USB_HIMR_BCNDMAINT_E BIT(14)
+/* RSVD BIT(13) */
+#define USB_HIMR_CTW_END BIT(12)
+/* RSVD BIT(11) */
+#define USB_HIMR_C2HCMD BIT(10)
+#define USB_HIMR_CPWM2 BIT(9)
+#define USB_HIMR_CPWM BIT(8)
+#define USB_HIMR_HIGHDOK BIT(7) /* High Queue DMA OK
+ Interrupt */
+#define USB_HIMR_MGNTDOK BIT(6) /* Management Queue DMA OK
+ Interrupt */
+#define USB_HIMR_BKDOK BIT(5) /* AC_BK DMA OK Interrupt */
+#define USB_HIMR_BEDOK BIT(4) /* AC_BE DMA OK Interrupt */
+#define USB_HIMR_VIDOK BIT(3) /* AC_VI DMA OK Interrupt */
+#define USB_HIMR_VODOK BIT(2) /* AC_VO DMA Interrupt */
+#define USB_HIMR_RDU BIT(1) /* Receive Descriptor
+ Unavailable */
+#define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */
+
+#define REG_USB_SPECIAL_OPTION 0xfe55
+#define REG_USB_DMA_AGG_TO 0xfe5b
+#define REG_USB_AGG_TO 0xfe5c
+#define REG_USB_AGG_TH 0xfe5d
+
+#define REG_NORMAL_SIE_VID 0xfe60 /* 0xfe60 - 0xfe61 */
+#define REG_NORMAL_SIE_PID 0xfe62 /* 0xfe62 - 0xfe63 */
+#define REG_NORMAL_SIE_OPTIONAL 0xfe64
+#define REG_NORMAL_SIE_EP 0xfe65 /* 0xfe65 - 0xfe67 */
+#define REG_NORMAL_SIE_EP_TX 0xfe66
+#define NORMAL_SIE_EP_TX_HIGH_MASK 0x000f
+#define NORMAL_SIE_EP_TX_NORMAL_MASK 0x00f0
+#define NORMAL_SIE_EP_TX_LOW_MASK 0x0f00
+
+#define REG_NORMAL_SIE_PHY 0xfe68 /* 0xfe68 - 0xfe6b */
+#define REG_NORMAL_SIE_OPTIONAL2 0xfe6c
+#define REG_NORMAL_SIE_GPS_EP 0xfe6d /* RTL8723 only */
+#define REG_NORMAL_SIE_MAC_ADDR 0xfe70 /* 0xfe70 - 0xfe75 */
+#define REG_NORMAL_SIE_STRING 0xfe80 /* 0xfe80 - 0xfedf */
+
+/* RF6052 registers */
+#define RF6052_REG_AC 0x00
+#define RF6052_REG_IQADJ_G1 0x01
+#define RF6052_REG_IQADJ_G2 0x02
+#define RF6052_REG_BS_PA_APSET_G1_G4 0x03
+#define RF6052_REG_BS_PA_APSET_G5_G8 0x04
+#define RF6052_REG_POW_TRSW 0x05
+#define RF6052_REG_GAIN_RX 0x06
+#define RF6052_REG_GAIN_TX 0x07
+#define RF6052_REG_TXM_IDAC 0x08
+#define RF6052_REG_IPA_G 0x09
+#define RF6052_REG_TXBIAS_G 0x0a
+#define RF6052_REG_TXPA_AG 0x0b
+#define RF6052_REG_IPA_A 0x0c
+#define RF6052_REG_TXBIAS_A 0x0d
+#define RF6052_REG_BS_PA_APSET_G9_G11 0x0e
+#define RF6052_REG_BS_IQGEN 0x0f
+#define RF6052_REG_MODE1 0x10
+#define RF6052_REG_MODE2 0x11
+#define RF6052_REG_RX_AGC_HP 0x12
+#define RF6052_REG_TX_AGC 0x13
+#define RF6052_REG_BIAS 0x14
+#define RF6052_REG_IPA 0x15
+#define RF6052_REG_TXBIAS 0x16
+#define RF6052_REG_POW_ABILITY 0x17
+#define RF6052_REG_MODE_AG 0x18 /* RF channel and BW switch */
+#define MODE_AG_CHANNEL_MASK 0x3ff
+#define MODE_AG_CHANNEL_20MHZ BIT(10)
+
+#define RF6052_REG_TOP 0x19
+#define RF6052_REG_RX_G1 0x1a
+#define RF6052_REG_RX_G2 0x1b
+#define RF6052_REG_RX_BB2 0x1c
+#define RF6052_REG_RX_BB1 0x1d
+#define RF6052_REG_RCK1 0x1e
+#define RF6052_REG_RCK2 0x1f
+#define RF6052_REG_TX_G1 0x20
+#define RF6052_REG_TX_G2 0x21
+#define RF6052_REG_TX_G3 0x22
+#define RF6052_REG_TX_BB1 0x23
+#define RF6052_REG_T_METER 0x24
+#define RF6052_REG_SYN_G1 0x25 /* RF TX Power control */
+#define RF6052_REG_SYN_G2 0x26 /* RF TX Power control */
+#define RF6052_REG_SYN_G3 0x27 /* RF TX Power control */
+#define RF6052_REG_SYN_G4 0x28 /* RF TX Power control */
+#define RF6052_REG_SYN_G5 0x29 /* RF TX Power control */
+#define RF6052_REG_SYN_G6 0x2a /* RF TX Power control */
+#define RF6052_REG_SYN_G7 0x2b /* RF TX Power control */
+#define RF6052_REG_SYN_G8 0x2c /* RF TX Power control */
+
+#define RF6052_REG_RCK_OS 0x30 /* RF TX PA control */
+
+#define RF6052_REG_TXPA_G1 0x31 /* RF TX PA control */
+#define RF6052_REG_TXPA_G2 0x32 /* RF TX PA control */
+#define RF6052_REG_TXPA_G3 0x33 /* RF TX PA control */
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/realtek/rtlwifi/Kconfig
index 73067cac289c..73067cac289c 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/realtek/rtlwifi/Kconfig
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/realtek/rtlwifi/Makefile
index ad6d3c52ec57..ad6d3c52ec57 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/Makefile
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 0517a4f2d3f2..0517a4f2d3f2 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 74233d601a90..74233d601a90 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/Makefile b/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile
index 47ceecfcb7dc..47ceecfcb7dc 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
index 39b9a3309cfd..39b9a3309cfd 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
index 53261d6f8578..53261d6f8578 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
index 75e1f7d0db06..75e1f7d0db06 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
index c4acd403e5f6..c4acd403e5f6 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
index 75f8094b7a34..75f8094b7a34 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index f2b9d11adc9e..f2b9d11adc9e 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
index 567f354caf95..567f354caf95 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
index b72e5377bdbc..b72e5377bdbc 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
index 20e904890fc2..20e904890fc2 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
index cf819f02ed23..cf819f02ed23 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
index b4cf1f53d510..b4cf1f53d510 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index b2791c893417..b2791c893417 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index 0a903ea179ef..0a903ea179ef 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index b9b0cb7af8ea..b9b0cb7af8ea 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
index ccd5a0f91e3b..ccd5a0f91e3b 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/realtek/rtlwifi/cam.c
index 8fe8b4cfae6c..8fe8b4cfae6c 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/realtek/rtlwifi/cam.c
diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/realtek/rtlwifi/cam.h
index e2e647d511c1..e2e647d511c1 100644
--- a/drivers/net/wireless/rtlwifi/cam.h
+++ b/drivers/net/wireless/realtek/rtlwifi/cam.h
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 585d0883c7e5..c925a4dff599 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1373,7 +1373,7 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h
index 782ac2fc4b28..782ac2fc4b28 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/realtek/rtlwifi/core.h
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c
index fd25abad2b9e..fd25abad2b9e 100644
--- a/drivers/net/wireless/rtlwifi/debug.c
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.c
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h
index fc794b3e9f4a..fc794b3e9f4a 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.h
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c
index 0b4082c9272a..0b4082c9272a 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h
index be02e7894c61..be02e7894c61 100644
--- a/drivers/net/wireless/rtlwifi/efuse.h
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index f46c9d7f6528..f46c9d7f6528 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index d4567d12e07e..5da6703942d9 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -247,6 +247,8 @@ struct rtl_pci {
/* MSI support */
bool msi_support;
bool using_msi;
+ /* interrupt clear before set */
+ bool int_clear;
};
struct mp_adapter {
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index b69321d45f04..b69321d45f04 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/realtek/rtlwifi/ps.h
index 29dfc514212d..29dfc514212d 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.h
diff --git a/drivers/net/wireless/rtlwifi/pwrseqcmd.h b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h
index 17ce0cb2c35c..17ce0cb2c35c 100644
--- a/drivers/net/wireless/rtlwifi/pwrseqcmd.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c
index 74c14ce28238..74c14ce28238 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rc.c
diff --git a/drivers/net/wireless/rtlwifi/rc.h b/drivers/net/wireless/realtek/rtlwifi/rc.h
index f29643d60d6b..f29643d60d6b 100644
--- a/drivers/net/wireless/rtlwifi/rc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rc.h
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c
index a62bf0a65c32..a62bf0a65c32 100644
--- a/drivers/net/wireless/rtlwifi/regd.c
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/realtek/rtlwifi/regd.h
index f7f15bce35dd..f7f15bce35dd 100644
--- a/drivers/net/wireless/rtlwifi/regd.h
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile
index a85419a37651..a85419a37651 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h
index 0532b9852444..0532b9852444 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
index ce4da9d79fbd..ce4da9d79fbd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
index 071ccee69eae..071ccee69eae 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
index 629125658b87..629125658b87 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
index 21bd4a5337ab..21bd4a5337ab 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
index 8ee83b093c0d..8ee83b093c0d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
index 1850fde881b5..1850fde881b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
index b504bd092fc4..b504bd092fc4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
index 4b325b75faaf..4b325b75faaf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
index a2bb02c7b837..a2bb02c7b837 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h
index b29bd77210f4..b29bd77210f4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c
index 02013df968a0..02013df968a0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h
index f2d9c6116e5c..f2d9c6116e5c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
index 15400ee6c04b..15400ee6c04b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c
index 40893cef7dfe..40893cef7dfe 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h
index 0eca030e3238..0eca030e3238 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 11344121c55e..11344121c55e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h
index 22398c3753a6..22398c3753a6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c
index 68bcb7fe6a65..68bcb7fe6a65 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h
index 403c4ddd236f..403c4ddd236f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
index 791efbe6b18c..791efbe6b18c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
index eab5ae0eb46c..eab5ae0eb46c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile
index aee42d7ae8a2..aee42d7ae8a2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
index 03cbe4cf110b..03cbe4cf110b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
index 4422e31fedd9..4422e31fedd9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
index 43fcb25c885f..43fcb25c885f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
index 864806c19ca7..864806c19ca7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
index 918b1d129e77..918b1d129e77 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/main.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
index 77e61b19bf36..77e61b19bf36 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
index 64bc49f4dbc6..64bc49f4dbc6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile
index c0cb0cfe7d37..c0cb0cfe7d37 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
index 690a7a1675e2..690a7a1675e2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
index 09898cf2e07a..09898cf2e07a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
index 38ba707015f5..38ba707015f5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index 04eb5c3f8464..04eb5c3f8464 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
index 98a086822aac..98a086822aac 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
index 8283e9b27639..8283e9b27639 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
index c5761066d383..c5761066d383 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
index 1ee5a6ae9960..1ee5a6ae9960 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
index e5e1353a94c3..e5e1353a94c3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
index dc8460c0b32f..dc8460c0b32f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
index a9c406f33d0a..a9c406f33d0a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
index ebd72cae10b6..ebd72cae10b6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index de6cb6c3a48c..de6cb6c3a48c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
index d2367a5d0cf5..d2367a5d0cf5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
index 752f943a84ae..752f943a84ae 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
index 8b79161f71be..8b79161f71be 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index 84ddd4d07a1d..84ddd4d07a1d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
index 4bec4b07e3e0..4bec4b07e3e0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile
index ad2de6b839ef..ad2de6b839ef 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
index 74a479ac323d..74a479ac323d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
index c16209a336ea..c16209a336ea 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
index fafa6bac2a3f..fafa6bac2a3f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
index 25db369b5d18..34ce06441d1b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
@@ -1946,6 +1946,14 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val);
mac->rx_data_filter = *(u16 *)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,
+ array);
+ break;
+ }
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
index 67588083e6cc..67588083e6cc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
index 75a2deb23af1..75a2deb23af1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
index 0f372278b7af..0f372278b7af 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index 035713311a4a..035713311a4a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
index 553a4bfac668..553a4bfac668 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
index c972fa50926d..c972fa50926d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
index 42b068660483..42b068660483 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
index 8b81465c629b..8b81465c629b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
index 5624ade92cc0..5624ade92cc0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
index 6f987de5b441..6f987de5b441 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
index fd4a5353d216..fd4a5353d216 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
index a1310abd0d54..a1310abd0d54 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
index 7903c154de00..7903c154de00 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
index 4b020e9e30b1..4b020e9e30b1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 95880fe4106e..95880fe4106e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index fd8051dcd98a..fd8051dcd98a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile
index e3213c8264b6..e3213c8264b6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
index 0a443ed17cf4..0a443ed17cf4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
index 7c1db7e7572d..7c1db7e7572d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
index f2d318ceeb28..f2d318ceeb28 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
index 62ef8209718f..62ef8209718f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
index 8a38daa316cb..8a38daa316cb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
index f49b60d31450..f49b60d31450 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
index 1bc7b1a96d4a..1bc7b1a96d4a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
index 76a57ae4af3e..76a57ae4af3e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
index a29df30c3025..a29df30c3025 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
index bb06fe836fe7..bb06fe836fe7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
index 48d5c6835b6a..48d5c6835b6a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
index 315a298bab06..315a298bab06 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
index 6a6ac540d5b5..6a6ac540d5b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
index 7303d12c266f..7303d12c266f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index b19d0398215f..b19d0398215f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
index 0e6035b8fd86..0e6035b8fd86 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
index 8ea6f528dfa6..8ea6f528dfa6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
index 8b724a86117a..8b724a86117a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
index 1feaa629dd4f..1feaa629dd4f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
index fb5cf0634e8d..fb5cf0634e8d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile
index 0315eeda9b60..0315eeda9b60 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h
index 60f5728b4e2d..60f5728b4e2d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c
index 459f3d0efa2f..459f3d0efa2f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h
index 107d5a488fa8..107d5a488fa8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
index 0708eedd9671..0708eedd9671 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
index 069da1e7e80a..069da1e7e80a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
index 5f14308e8eb3..5f14308e8eb3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h
index 05413f189685..05413f189685 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
index 8388e371c8e2..8388e371c8e2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
index 8ef640a2ef7f..8ef640a2ef7f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
index 018340aedf09..018340aedf09 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h
index c6e97c8df54c..c6e97c8df54c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c
index 1a701d007f0c..1a701d007f0c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h
index 781eeaa6af49..781eeaa6af49 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h
index 1eaa1fab550d..1eaa1fab550d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c
index c9bc33cd1090..c9bc33cd1090 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h
index 039c0133ad6b..039c0133ad6b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index c31c6bfb536d..c31c6bfb536d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h
index 21433d0332d0..21433d0332d0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c
index abcdd0670fd8..abcdd0670fd8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h
index bff9df88815d..bff9df88815d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
index d39ee67f6113..d39ee67f6113 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
index 8f78ac9e6040..8f78ac9e6040 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile
index b7eb13819cbc..b7eb13819cbc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
index 41466f957cdc..41466f957cdc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
index 9bae5a92e30f..9bae5a92e30f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
index de6ac796c74d..de6ac796c74d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
index 331b1584a1a2..331b1584a1a2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
index b1e44b86e8ed..b1e44b86e8ed 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
index 12b0978ba4fa..12b0978ba4fa 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
index 4cacee10f31e..4cacee10f31e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
index 44949b5cbb87..44949b5cbb87 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
index 2182dbeb5f32..2182dbeb5f32 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
index 4b4612fe2fdb..4b4612fe2fdb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
index 8acf4765a7a6..8acf4765a7a6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
index e13043479b71..e13043479b71 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
index 78a81c1e390b..78a81c1e390b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
index 8a29eb94ab17..8a29eb94ab17 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index e1fd27c888bf..e1fd27c888bf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
index 2eb88862ebe4..2eb88862ebe4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
index f1a73f75127e..f1a73f75127e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
index 2feb73b71a4f..2feb73b71a4f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
index 125b29bd2f93..125b29bd2f93 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
index 5a13f17e3b41..5a13f17e3b41 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile
index 6220672a96f4..6220672a96f4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h
index 06c448c010fd..06c448c010fd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h
index bcdf2273688e..bcdf2273688e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
index 4c1c96c96a5a..4c1c96c96a5a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
index 57111052e86b..57111052e86b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
index b7c0d38ee5b5..b7c0d38ee5b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
index 9d1fe25db953..9d1fe25db953 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c
index 5aac45d5a974..5aac45d5a974 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
index bcd64a22acc0..bcd64a22acc0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c
index 00a0531cc5f4..00a0531cc5f4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h
index 3723d7476717..3723d7476717 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
index a4b7eac6856f..a4b7eac6856f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h
index 32c1ace97c3f..32c1ace97c3f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
index 13173351cbfd..13173351cbfd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
index c22b19f542a6..c22b19f542a6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
index d367097f490b..d367097f490b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h
index b85f5c7c5c01..b85f5c7c5c01 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c
index 2f7f81af8a55..2f7f81af8a55 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h
index 4ac7db526f15..4ac7db526f15 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
index 306059f9b9cc..306059f9b9cc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c
index 9ebc8281ff99..9ebc8281ff99 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h
index 7b44ebc0fac9..7b44ebc0fac9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 3859b3e3d158..3859b3e3d158 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h
index 46478780d262..46478780d262 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c
index 61e86045f15c..61e86045f15c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h
index 57a548ceba7d..57a548ceba7d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
index 2f7c144d7980..2f7c144d7980 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h
index 017da7e194d8..017da7e194d8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile
index a77c34102792..a77c34102792 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h
index 025ea5c0f3f6..025ea5c0f3f6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c
index 3a81cdba8ca3..3a81cdba8ca3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h
index f752a2cad63d..f752a2cad63d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
index d5da0f3c1217..d5da0f3c1217 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
index 067429669bda..067429669bda 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index c983d2fe147f..c983d2fe147f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h
index eae863d08de8..eae863d08de8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
index 4196efb723a2..4196efb723a2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
index c57de379ee8d..c57de379ee8d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
index b7b73cbe346d..b7b73cbe346d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h
index 9021d4745ab7..9021d4745ab7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c
index a1bb1f6116fb..a1bb1f6116fb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h
index 0fee5e0e55c2..0fee5e0e55c2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
index 03581d2a5da0..03581d2a5da0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c
index 5ed4492d3c80..5ed4492d3c80 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h
index f423e157020f..f423e157020f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index d091f1d5f91e..d091f1d5f91e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h
index a7b25e769950..a7b25e769950 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c
index a180761e8810..a180761e8810 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h
index dc17001632f7..dc17001632f7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
index 338ec9a9d09b..338ec9a9d09b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
index 45949ac4854c..45949ac4854c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile
index 345a68adcf38..345a68adcf38 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c
index 064340641913..064340641913 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h
index 5c1b94ce2f86..5c1b94ce2f86 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
index a2f5e89bedfe..a2f5e89bedfe 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h
index 8ea372d1626e..8ea372d1626e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c
index 9014a94fac6a..9014a94fac6a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/main.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
index 75cbd1509b52..75cbd1509b52 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h
index 83b891a9adb8..83b891a9adb8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile
index f7a26f71197e..f7a26f71197e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h
index dfbdf539de1a..dfbdf539de1a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
index b57cfd965196..b57cfd965196 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h
index 625a6bbb21fc..625a6bbb21fc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
index 525eb234627c..525eb234627c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
index 8f5b4aade3c9..8f5b4aade3c9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index b7f18e2155eb..6e9418ed90c2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2253,11 +2253,28 @@ void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci)
}
}
+static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 tmp = rtl_read_dword(rtlpriv, REG_HISR);
+
+ rtl_write_dword(rtlpriv, REG_HISR, tmp);
+
+ tmp = rtl_read_dword(rtlpriv, REG_HISRE);
+ rtl_write_dword(rtlpriv, REG_HISRE, tmp);
+
+ tmp = rtl_read_dword(rtlpriv, REG_HSISR);
+ rtl_write_dword(rtlpriv, REG_HSISR, tmp);
+}
+
void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ if (!rtlpci->int_clear)
+ rtl8821ae_clear_interrupt(hw);/*clear it here first*/
+
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
rtlpci->irq_enabled = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h
index a3553e3abaa1..a3553e3abaa1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
index ba1946a0280e..ba1946a0280e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
index 038e64e18ae8..038e64e18ae8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
index 9b4d8a637915..9b4d8a637915 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h
index c411f0a95cc4..c411f0a95cc4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c
index 9ddf78a187dd..9ddf78a187dd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h
index 36b3e91d996e..36b3e91d996e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
index 1d6110f9c1fb..1d6110f9c1fb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c
index 2922538160e5..2922538160e5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h
index efd22bd0b139..efd22bd0b139 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index a4988121e1ab..8ee141a55bc5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -96,6 +96,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
rtl8821ae_bt_reg_init(hw);
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
rtlpriv->dm.dm_initialgain_enable = 1;
@@ -167,6 +168,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
@@ -308,6 +310,7 @@ static struct rtl_mod_params rtl8821ae_mod_params = {
.swctrl_lps = false,
.fwctrl_lps = true,
.msi_support = true,
+ .int_clear = true,
.debug = DBG_EMERG,
.disable_watchdog = 0,
};
@@ -437,6 +440,7 @@ module_param_named(fwlps, rtl8821ae_mod_params.fwctrl_lps, bool, 0444);
module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444);
module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog,
bool, 0444);
+module_param_named(int_clear, rtl8821ae_mod_params.int_clear, 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");
@@ -444,6 +448,7 @@ MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
+MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h
index d001e7ce3052..d001e7ce3052 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
index 62a0fb76f080..62a0fb76f080 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
index 24bcff6bc507..24bcff6bc507 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
index 174743aef943..174743aef943 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
index 31409042d8dd..31409042d8dd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/realtek/rtlwifi/stats.c
index d8b30690b00d..d8b30690b00d 100644
--- a/drivers/net/wireless/rtlwifi/stats.c
+++ b/drivers/net/wireless/realtek/rtlwifi/stats.c
diff --git a/drivers/net/wireless/rtlwifi/stats.h b/drivers/net/wireless/realtek/rtlwifi/stats.h
index 2b57dffef572..2b57dffef572 100644
--- a/drivers/net/wireless/rtlwifi/stats.h
+++ b/drivers/net/wireless/realtek/rtlwifi/stats.h
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 2721cf89fb16..2721cf89fb16 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h
index 685273ca9561..685273ca9561 100644
--- a/drivers/net/wireless/rtlwifi/usb.h
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.h
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index b90ca618b123..4544752a2ba8 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2249,6 +2249,9 @@ struct rtl_mod_params {
/* default 0: 1 means disable */
bool disable_watchdog;
+
+ /* default 0: 1 means do not disable interrupts */
+ bool int_clear;
};
struct rtl_hal_usbint_cfg {
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 71a825c750cf..a13d1f2b5912 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1236,7 +1236,7 @@ static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold)
netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold);
- if (rts_threshold < 0 || rts_threshold > 2347)
+ if (rts_threshold == -1 || rts_threshold > 2347)
rts_threshold = 2347;
tmp = cpu_to_le32(rts_threshold);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 7e804324bfa7..b5bcc933a2a6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -664,6 +664,7 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
* @tid: Traffic identifier.
* @ssn: Pointer to ssn value.
* @buf_size: Buffer size (for kernel version > 2.6.38).
+ * @amsdu: is AMSDU in AMPDU allowed
*
* Return: status: 0 on success, negative error code on failure.
*/
@@ -673,7 +674,8 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
unsigned short tid,
unsigned short *ssn,
- unsigned char buf_size)
+ unsigned char buf_size,
+ bool amsdu)
{
int status = -EOPNOTSUPP;
struct rsi_hw *adapter = hw->priv;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 9524564f873b..9733b31a780d 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7937,7 +7937,7 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf);
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
int ret = 0;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 1609b8a7f7eb..440790b92b19 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -220,7 +220,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size);
+ u8 buf_size, bool amsdu);
int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5932306084fd..bf9afbf46c1b 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1114,6 +1114,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0db0, 0x871c) },
{ USB_DEVICE(0x0db0, 0x899a) },
/* Ovislink */
+ { USB_DEVICE(0x1b75, 0x3070) },
{ USB_DEVICE(0x1b75, 0x3071) },
{ USB_DEVICE(0x1b75, 0x3072) },
{ USB_DEVICE(0x1b75, 0xa200) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 48a2cad29477..7e8bb1198ae9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -266,7 +266,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
if (beacon_diff > beacon_int)
beacon_diff = 0;
- autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff;
+ autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff;
queue_delayed_work(rt2x00dev->workqueue,
&rt2x00dev->autowakeup_work,
autowake_timeout - 15);
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
index 735be5352143..8de9d4444a6a 100644
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -354,7 +354,6 @@ static int wl1251_spi_remove(struct spi_device *spi)
static struct spi_driver wl1251_spi_driver = {
.driver = {
.name = DRIVER_NAME,
- .owner = THIS_MODULE,
},
.probe = wl1251_spi_probe,
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c
index 7c355fff2c5e..ebed13af9852 100644
--- a/drivers/net/wireless/ti/wl12xx/scan.c
+++ b/drivers/net/wireless/ti/wl12xx/scan.c
@@ -350,7 +350,8 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
cfg->bss_type = SCAN_BSS_TYPE_ANY;
/* currently NL80211 supports only a single interval */
for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
- cfg->intervals[i] = cpu_to_le32(req->interval);
+ cfg->intervals[i] = cpu_to_le32(req->scan_plans[0].interval *
+ MSEC_PER_SEC);
cfg->ssid_len = 0;
ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req);
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index abbf054fb6da..50cce42089a5 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -2115,3 +2115,4 @@ MODULE_PARM_DESC(num_rx_desc_param,
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
+MODULE_FIRMWARE(WL18XX_CONF_FILE_NAME);
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c
index c938c494c785..bc15aa2c3efa 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.c
+++ b/drivers/net/wireless/ti/wl18xx/scan.c
@@ -228,13 +228,15 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
wl18xx_adjust_channels(cmd, cmd_channels);
if (c->num_short_intervals && c->long_interval &&
- c->long_interval > req->interval) {
- cmd->short_cycles_msec = cpu_to_le16(req->interval);
+ c->long_interval > req->scan_plans[0].interval * MSEC_PER_SEC) {
+ cmd->short_cycles_msec =
+ cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC);
cmd->long_cycles_msec = cpu_to_le16(c->long_interval);
cmd->short_cycles_count = c->num_short_intervals;
} else {
cmd->short_cycles_msec = 0;
- cmd->long_cycles_msec = cpu_to_le16(req->interval);
+ cmd->long_cycles_msec =
+ cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC);
cmd->short_cycles_count = 0;
}
wl1271_debug(DEBUG_SCAN, "short_interval: %d, long_interval: %d, num_short: %d",
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index e819369d8f8f..ec7f6af3fab2 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5263,7 +5263,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size)
+ u8 buf_size, bool amsdu)
{
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index f1ac2839d97c..236b41090827 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -408,7 +408,6 @@ static int wl1271_remove(struct spi_device *spi)
static struct spi_driver wl1271_spi_driver = {
.driver = {
.name = "wl1271_spi",
- .owner = THIS_MODULE,
},
.probe = wl1271_probe,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index a1b6040e6491..906be6aa4eb6 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -318,7 +318,7 @@ struct wl1271 {
bool watchdog_recovery;
/* Reg domain last configuration */
- u32 reg_ch_conf_last[2];
+ u32 reg_ch_conf_last[2] __aligned(8);
/* Reg domain pending configuration */
u32 reg_ch_conf_pending[2];
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index a7bf74727116..0333ab0fd926 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -44,6 +44,7 @@
#include <xen/interface/grant_table.h>
#include <xen/grant_table.h>
#include <xen/xenbus.h>
+#include <xen/page.h>
#include <linux/debugfs.h>
typedef unsigned int pending_ring_idx_t;
@@ -64,8 +65,8 @@ struct pending_tx_info {
struct ubuf_info callback_struct;
};
-#define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
-#define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
+#define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, XEN_PAGE_SIZE)
+#define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, XEN_PAGE_SIZE)
struct xenvif_rx_meta {
int id;
@@ -80,16 +81,21 @@ struct xenvif_rx_meta {
/* Discriminate from any valid pending_idx value. */
#define INVALID_PENDING_IDX 0xFFFF
-#define MAX_BUFFER_OFFSET PAGE_SIZE
+#define MAX_BUFFER_OFFSET XEN_PAGE_SIZE
#define MAX_PENDING_REQS XEN_NETIF_TX_RING_SIZE
+/* The maximum number of frags is derived from the size of a grant (same
+ * as a Xen page size for now).
+ */
+#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
+
/* It's possible for an skb to have a maximal number of frags
* but still be less than MAX_BUFFER_OFFSET in size. Thus the
- * worst-case number of copy operations is MAX_SKB_FRAGS per
+ * worst-case number of copy operations is MAX_XEN_SKB_FRAGS per
* ring slot.
*/
-#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
+#define MAX_GRANT_COPY_OPS (MAX_XEN_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
#define NETBACK_INVALID_HANDLE -1
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index ec98d43916a8..e481f3710bd3 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -152,9 +152,9 @@ static inline pending_ring_idx_t pending_index(unsigned i)
static int xenvif_rx_ring_slots_needed(struct xenvif *vif)
{
if (vif->gso_mask)
- return DIV_ROUND_UP(vif->dev->gso_max_size, PAGE_SIZE) + 1;
+ return DIV_ROUND_UP(vif->dev->gso_max_size, XEN_PAGE_SIZE) + 1;
else
- return DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
+ return DIV_ROUND_UP(vif->dev->mtu, XEN_PAGE_SIZE);
}
static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue)
@@ -274,6 +274,80 @@ static struct xenvif_rx_meta *get_next_rx_buffer(struct xenvif_queue *queue,
return meta;
}
+struct gop_frag_copy {
+ struct xenvif_queue *queue;
+ struct netrx_pending_operations *npo;
+ struct xenvif_rx_meta *meta;
+ int head;
+ int gso_type;
+
+ struct page *page;
+};
+
+static void xenvif_setup_copy_gop(unsigned long gfn,
+ unsigned int offset,
+ unsigned int *len,
+ struct gop_frag_copy *info)
+{
+ struct gnttab_copy *copy_gop;
+ struct xen_page_foreign *foreign;
+ /* Convenient aliases */
+ struct xenvif_queue *queue = info->queue;
+ struct netrx_pending_operations *npo = info->npo;
+ struct page *page = info->page;
+
+ BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET);
+
+ if (npo->copy_off == MAX_BUFFER_OFFSET)
+ info->meta = get_next_rx_buffer(queue, npo);
+
+ if (npo->copy_off + *len > MAX_BUFFER_OFFSET)
+ *len = MAX_BUFFER_OFFSET - npo->copy_off;
+
+ copy_gop = npo->copy + npo->copy_prod++;
+ copy_gop->flags = GNTCOPY_dest_gref;
+ copy_gop->len = *len;
+
+ foreign = xen_page_foreign(page);
+ if (foreign) {
+ copy_gop->source.domid = foreign->domid;
+ copy_gop->source.u.ref = foreign->gref;
+ copy_gop->flags |= GNTCOPY_source_gref;
+ } else {
+ copy_gop->source.domid = DOMID_SELF;
+ copy_gop->source.u.gmfn = gfn;
+ }
+ copy_gop->source.offset = offset;
+
+ copy_gop->dest.domid = queue->vif->domid;
+ copy_gop->dest.offset = npo->copy_off;
+ copy_gop->dest.u.ref = npo->copy_gref;
+
+ npo->copy_off += *len;
+ info->meta->size += *len;
+
+ /* Leave a gap for the GSO descriptor. */
+ if (info->head && ((1 << info->gso_type) & queue->vif->gso_mask))
+ queue->rx.req_cons++;
+
+ info->head = 0; /* There must be something in this buffer now */
+}
+
+static void xenvif_gop_frag_copy_grant(unsigned long gfn,
+ unsigned offset,
+ unsigned int len,
+ void *data)
+{
+ unsigned int bytes;
+
+ while (len) {
+ bytes = len;
+ xenvif_setup_copy_gop(gfn, offset, &bytes, data);
+ offset += bytes;
+ len -= bytes;
+ }
+}
+
/*
* Set up the grant operations for this fragment. If it's a flipping
* interface, we also set up the unmap request from here.
@@ -283,83 +357,52 @@ static void xenvif_gop_frag_copy(struct xenvif_queue *queue, struct sk_buff *skb
struct page *page, unsigned long size,
unsigned long offset, int *head)
{
- struct gnttab_copy *copy_gop;
- struct xenvif_rx_meta *meta;
+ struct gop_frag_copy info = {
+ .queue = queue,
+ .npo = npo,
+ .head = *head,
+ .gso_type = XEN_NETIF_GSO_TYPE_NONE,
+ };
unsigned long bytes;
- int gso_type = XEN_NETIF_GSO_TYPE_NONE;
+
+ if (skb_is_gso(skb)) {
+ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+ info.gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+ info.gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
+ }
/* Data must not cross a page boundary. */
BUG_ON(size + offset > PAGE_SIZE<<compound_order(page));
- meta = npo->meta + npo->meta_prod - 1;
+ info.meta = npo->meta + npo->meta_prod - 1;
/* Skip unused frames from start of page */
page += offset >> PAGE_SHIFT;
offset &= ~PAGE_MASK;
while (size > 0) {
- struct xen_page_foreign *foreign;
-
BUG_ON(offset >= PAGE_SIZE);
- BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET);
-
- if (npo->copy_off == MAX_BUFFER_OFFSET)
- meta = get_next_rx_buffer(queue, npo);
bytes = PAGE_SIZE - offset;
if (bytes > size)
bytes = size;
- if (npo->copy_off + bytes > MAX_BUFFER_OFFSET)
- bytes = MAX_BUFFER_OFFSET - npo->copy_off;
-
- copy_gop = npo->copy + npo->copy_prod++;
- copy_gop->flags = GNTCOPY_dest_gref;
- copy_gop->len = bytes;
-
- foreign = xen_page_foreign(page);
- if (foreign) {
- copy_gop->source.domid = foreign->domid;
- copy_gop->source.u.ref = foreign->gref;
- copy_gop->flags |= GNTCOPY_source_gref;
- } else {
- copy_gop->source.domid = DOMID_SELF;
- copy_gop->source.u.gmfn =
- virt_to_gfn(page_address(page));
- }
- copy_gop->source.offset = offset;
-
- copy_gop->dest.domid = queue->vif->domid;
- copy_gop->dest.offset = npo->copy_off;
- copy_gop->dest.u.ref = npo->copy_gref;
-
- npo->copy_off += bytes;
- meta->size += bytes;
-
- offset += bytes;
+ info.page = page;
+ gnttab_foreach_grant_in_range(page, offset, bytes,
+ xenvif_gop_frag_copy_grant,
+ &info);
size -= bytes;
+ offset = 0;
- /* Next frame */
- if (offset == PAGE_SIZE && size) {
+ /* Next page */
+ if (size) {
BUG_ON(!PageCompound(page));
page++;
- offset = 0;
}
-
- /* Leave a gap for the GSO descriptor. */
- if (skb_is_gso(skb)) {
- if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
- gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
- else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
- gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
- }
-
- if (*head && ((1 << gso_type) & queue->vif->gso_mask))
- queue->rx.req_cons++;
-
- *head = 0; /* There must be something in this buffer now. */
-
}
+
+ *head = info.head;
}
/*
@@ -758,7 +801,7 @@ static int xenvif_count_requests(struct xenvif_queue *queue,
first->size -= txp->size;
slots++;
- if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
+ if (unlikely((txp->offset + txp->size) > XEN_PAGE_SIZE)) {
netdev_err(queue->vif->dev, "Cross page boundary, txp->offset: %u, size: %u\n",
txp->offset, txp->size);
xenvif_fatal_tx_err(queue->vif);
@@ -1339,11 +1382,11 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
}
/* No crossing a page as the payload mustn't fragment. */
- if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
+ if (unlikely((txreq.offset + txreq.size) > XEN_PAGE_SIZE)) {
netdev_err(queue->vif->dev,
"txreq.offset: %u, size: %u, end: %lu\n",
txreq.offset, txreq.size,
- (unsigned long)(txreq.offset&~PAGE_MASK) + txreq.size);
+ (unsigned long)(txreq.offset&~XEN_PAGE_MASK) + txreq.size);
xenvif_fatal_tx_err(queue->vif);
break;
}
@@ -1409,7 +1452,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
virt_to_gfn(skb->data);
queue->tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF;
queue->tx_copy_ops[*copy_ops].dest.offset =
- offset_in_page(skb->data);
+ offset_in_page(skb->data) & ~XEN_PAGE_MASK;
queue->tx_copy_ops[*copy_ops].len = data_len;
queue->tx_copy_ops[*copy_ops].flags = GNTCOPY_source_gref;
@@ -1894,7 +1937,7 @@ int xenvif_map_frontend_rings(struct xenvif_queue *queue,
goto err;
txs = (struct xen_netif_tx_sring *)addr;
- BACK_RING_INIT(&queue->tx, txs, PAGE_SIZE);
+ BACK_RING_INIT(&queue->tx, txs, XEN_PAGE_SIZE);
err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(queue->vif),
&rx_ring_ref, 1, &addr);
@@ -1902,7 +1945,7 @@ int xenvif_map_frontend_rings(struct xenvif_queue *queue,
goto err;
rxs = (struct xen_netif_rx_sring *)addr;
- BACK_RING_INIT(&queue->rx, rxs, PAGE_SIZE);
+ BACK_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE);
return 0;
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 929a6e7e5ecf..56ebd8267386 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -788,6 +788,12 @@ static void connect(struct backend_info *be)
/* Use the number of queues requested by the frontend */
be->vif->queues = vzalloc(requested_num_queues *
sizeof(struct xenvif_queue));
+ if (!be->vif->queues) {
+ xenbus_dev_fatal(dev, -ENOMEM,
+ "allocating queues");
+ return;
+ }
+
be->vif->num_queues = requested_num_queues;
be->vif->stalled_queues = requested_num_queues;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index f821a97d7827..d6abf191122a 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -74,8 +74,8 @@ struct netfront_cb {
#define GRANT_INVALID_REF 0
-#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
-#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
+#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, XEN_PAGE_SIZE)
+#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, XEN_PAGE_SIZE)
/* Minimum number of Rx slots (includes slot for GSO metadata). */
#define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1)
@@ -291,7 +291,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
struct sk_buff *skb;
unsigned short id;
grant_ref_t ref;
- unsigned long gfn;
+ struct page *page;
struct xen_netif_rx_request *req;
skb = xennet_alloc_one_rx_buffer(queue);
@@ -307,14 +307,13 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
BUG_ON((signed short)ref < 0);
queue->grant_rx_ref[id] = ref;
- gfn = xen_page_to_gfn(skb_frag_page(&skb_shinfo(skb)->frags[0]));
+ page = skb_frag_page(&skb_shinfo(skb)->frags[0]);
req = RING_GET_REQUEST(&queue->rx, req_prod);
- gnttab_grant_foreign_access_ref(ref,
- queue->info->xbdev->otherend_id,
- gfn,
- 0);
-
+ gnttab_page_grant_foreign_access_ref_one(ref,
+ queue->info->xbdev->otherend_id,
+ page,
+ 0);
req->id = id;
req->gref = ref;
}
@@ -415,25 +414,33 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue)
xennet_maybe_wake_tx(queue);
}
-static struct xen_netif_tx_request *xennet_make_one_txreq(
- struct netfront_queue *queue, struct sk_buff *skb,
- struct page *page, unsigned int offset, unsigned int len)
+struct xennet_gnttab_make_txreq {
+ struct netfront_queue *queue;
+ struct sk_buff *skb;
+ struct page *page;
+ struct xen_netif_tx_request *tx; /* Last request */
+ unsigned int size;
+};
+
+static void xennet_tx_setup_grant(unsigned long gfn, unsigned int offset,
+ unsigned int len, void *data)
{
+ struct xennet_gnttab_make_txreq *info = data;
unsigned int id;
struct xen_netif_tx_request *tx;
grant_ref_t ref;
-
- len = min_t(unsigned int, PAGE_SIZE - offset, len);
+ /* convenient aliases */
+ struct page *page = info->page;
+ struct netfront_queue *queue = info->queue;
+ struct sk_buff *skb = info->skb;
id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs);
tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++);
ref = gnttab_claim_grant_reference(&queue->gref_tx_head);
BUG_ON((signed short)ref < 0);
- gnttab_grant_foreign_access_ref(ref,
- queue->info->xbdev->otherend_id,
- xen_page_to_gfn(page),
- GNTMAP_readonly);
+ gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id,
+ gfn, GNTMAP_readonly);
queue->tx_skbs[id].skb = skb;
queue->grant_tx_page[id] = page;
@@ -445,7 +452,34 @@ static struct xen_netif_tx_request *xennet_make_one_txreq(
tx->size = len;
tx->flags = 0;
- return tx;
+ info->tx = tx;
+ info->size += tx->size;
+}
+
+static struct xen_netif_tx_request *xennet_make_first_txreq(
+ struct netfront_queue *queue, struct sk_buff *skb,
+ struct page *page, unsigned int offset, unsigned int len)
+{
+ struct xennet_gnttab_make_txreq info = {
+ .queue = queue,
+ .skb = skb,
+ .page = page,
+ .size = 0,
+ };
+
+ gnttab_for_one_grant(page, offset, len, xennet_tx_setup_grant, &info);
+
+ return info.tx;
+}
+
+static void xennet_make_one_txreq(unsigned long gfn, unsigned int offset,
+ unsigned int len, void *data)
+{
+ struct xennet_gnttab_make_txreq *info = data;
+
+ info->tx->flags |= XEN_NETTXF_more_data;
+ skb_get(info->skb);
+ xennet_tx_setup_grant(gfn, offset, len, data);
}
static struct xen_netif_tx_request *xennet_make_txreqs(
@@ -453,20 +487,30 @@ static struct xen_netif_tx_request *xennet_make_txreqs(
struct sk_buff *skb, struct page *page,
unsigned int offset, unsigned int len)
{
+ struct xennet_gnttab_make_txreq info = {
+ .queue = queue,
+ .skb = skb,
+ .tx = tx,
+ };
+
/* Skip unused frames from start of page */
page += offset >> PAGE_SHIFT;
offset &= ~PAGE_MASK;
while (len) {
- tx->flags |= XEN_NETTXF_more_data;
- tx = xennet_make_one_txreq(queue, skb_get(skb),
- page, offset, len);
+ info.page = page;
+ info.size = 0;
+
+ gnttab_foreach_grant_in_range(page, offset, len,
+ xennet_make_one_txreq,
+ &info);
+
page++;
offset = 0;
- len -= tx->size;
+ len -= info.size;
}
- return tx;
+ return info.tx;
}
/*
@@ -476,9 +520,10 @@ static struct xen_netif_tx_request *xennet_make_txreqs(
static int xennet_count_skb_slots(struct sk_buff *skb)
{
int i, frags = skb_shinfo(skb)->nr_frags;
- int pages;
+ int slots;
- pages = PFN_UP(offset_in_page(skb->data) + skb_headlen(skb));
+ slots = gnttab_count_grant(offset_in_page(skb->data),
+ skb_headlen(skb));
for (i = 0; i < frags; i++) {
skb_frag_t *frag = skb_shinfo(skb)->frags + i;
@@ -488,10 +533,10 @@ static int xennet_count_skb_slots(struct sk_buff *skb)
/* Skip unused frames from start of page */
offset &= ~PAGE_MASK;
- pages += PFN_UP(offset + size);
+ slots += gnttab_count_grant(offset, size);
}
- return pages;
+ return slots;
}
static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb,
@@ -512,6 +557,8 @@ static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb,
return queue_idx;
}
+#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
+
static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct netfront_info *np = netdev_priv(dev);
@@ -546,7 +593,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
slots = xennet_count_skb_slots(skb);
- if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+ if (unlikely(slots > MAX_XEN_SKB_FRAGS + 1)) {
net_dbg_ratelimited("xennet: skb rides the rocket: %d slots, %d bytes\n",
slots, skb->len);
if (skb_linearize(skb))
@@ -567,10 +614,13 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* First request for the linear area. */
- first_tx = tx = xennet_make_one_txreq(queue, skb,
- page, offset, len);
- page++;
- offset = 0;
+ first_tx = tx = xennet_make_first_txreq(queue, skb,
+ page, offset, len);
+ offset += tx->size;
+ if (offset == PAGE_SIZE) {
+ page++;
+ offset = 0;
+ }
len -= tx->size;
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -732,7 +782,7 @@ static int xennet_get_responses(struct netfront_queue *queue,
for (;;) {
if (unlikely(rx->status < 0 ||
- rx->offset + rx->status > PAGE_SIZE)) {
+ rx->offset + rx->status > XEN_PAGE_SIZE)) {
if (net_ratelimit())
dev_warn(dev, "rx->offset: %u, size: %d\n",
rx->offset, rx->status);
@@ -1496,7 +1546,7 @@ static int setup_netfront(struct xenbus_device *dev,
goto fail;
}
SHARED_RING_INIT(txs);
- FRONT_RING_INIT(&queue->tx, txs, PAGE_SIZE);
+ FRONT_RING_INIT(&queue->tx, txs, XEN_PAGE_SIZE);
err = xenbus_grant_ring(dev, txs, 1, &gref);
if (err < 0)
@@ -1510,7 +1560,7 @@ static int setup_netfront(struct xenbus_device *dev,
goto alloc_rx_ring_fail;
}
SHARED_RING_INIT(rxs);
- FRONT_RING_INIT(&queue->rx, rxs, PAGE_SIZE);
+ FRONT_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE);
err = xenbus_grant_ring(dev, rxs, 1, &gref);
if (err < 0)
@@ -1706,19 +1756,19 @@ static void xennet_destroy_queues(struct netfront_info *info)
}
static int xennet_create_queues(struct netfront_info *info,
- unsigned int num_queues)
+ unsigned int *num_queues)
{
unsigned int i;
int ret;
- info->queues = kcalloc(num_queues, sizeof(struct netfront_queue),
+ info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue),
GFP_KERNEL);
if (!info->queues)
return -ENOMEM;
rtnl_lock();
- for (i = 0; i < num_queues; i++) {
+ for (i = 0; i < *num_queues; i++) {
struct netfront_queue *queue = &info->queues[i];
queue->id = i;
@@ -1728,7 +1778,7 @@ static int xennet_create_queues(struct netfront_info *info,
if (ret < 0) {
dev_warn(&info->netdev->dev,
"only created %d queues\n", i);
- num_queues = i;
+ *num_queues = i;
break;
}
@@ -1738,11 +1788,11 @@ static int xennet_create_queues(struct netfront_info *info,
napi_enable(&queue->napi);
}
- netif_set_real_num_tx_queues(info->netdev, num_queues);
+ netif_set_real_num_tx_queues(info->netdev, *num_queues);
rtnl_unlock();
- if (num_queues == 0) {
+ if (*num_queues == 0) {
dev_err(&info->netdev->dev, "no queues\n");
return -EINVAL;
}
@@ -1788,7 +1838,7 @@ static int talk_to_netback(struct xenbus_device *dev,
if (info->queues)
xennet_destroy_queues(info);
- err = xennet_create_queues(info, num_queues);
+ err = xennet_create_queues(info, &num_queues);
if (err < 0)
goto destroy_ring;
@@ -1819,19 +1869,22 @@ again:
goto destroy_ring;
}
- if (num_queues == 1) {
- err = write_queue_xenstore_keys(&info->queues[0], &xbt, 0); /* flat */
- if (err)
- goto abort_transaction_no_dev_fatal;
- } else {
+ if (xenbus_exists(XBT_NIL,
+ info->xbdev->otherend, "multi-queue-max-queues")) {
/* Write the number of queues */
- err = xenbus_printf(xbt, dev->nodename, "multi-queue-num-queues",
- "%u", num_queues);
+ err = xenbus_printf(xbt, dev->nodename,
+ "multi-queue-num-queues", "%u", num_queues);
if (err) {
message = "writing multi-queue-num-queues";
goto abort_transaction_no_dev_fatal;
}
+ }
+ if (num_queues == 1) {
+ err = write_queue_xenstore_keys(&info->queues[0], &xbt, 0); /* flat */
+ if (err)
+ goto abort_transaction_no_dev_fatal;
+ } else {
/* Write the keys for each queue */
for (i = 0; i < num_queues; ++i) {
queue = &info->queues[i];
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 6639cd1cae36..0d6003dee3af 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -68,6 +68,7 @@ config NFC_PORT100
If unsure, say N.
+source "drivers/nfc/fdp/Kconfig"
source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
source "drivers/nfc/nfcmrvl/Kconfig"
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 2757fe1b8aa5..e3621416a48e 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -2,6 +2,7 @@
# Makefile for nfc devices
#
+obj-$(CONFIG_NFC_FDP) += fdp/
obj-$(CONFIG_NFC_PN544) += pn544/
obj-$(CONFIG_NFC_MICROREAD) += microread/
obj-$(CONFIG_NFC_PN533) += pn533.o
diff --git a/drivers/nfc/fdp/Kconfig b/drivers/nfc/fdp/Kconfig
new file mode 100644
index 000000000000..fbccd9dd887d
--- /dev/null
+++ b/drivers/nfc/fdp/Kconfig
@@ -0,0 +1,23 @@
+config NFC_FDP
+ tristate "Intel FDP NFC driver"
+ depends on NFC_NCI
+ select CRC_CCITT
+ default n
+ ---help---
+ Intel Fields Peak NFC controller core driver.
+ This is a driver based on the NCI NFC kernel layers.
+
+ To compile this driver as a module, choose m here. The module will
+ be called fdp.
+ Say N if unsure.
+
+config NFC_FDP_I2C
+ tristate "NFC FDP i2c support"
+ depends on NFC_FDP && I2C
+ ---help---
+ This module adds support for the Intel Fields Peak NFC controller
+ i2c interface.
+ Select this if your platform is using the i2c bus.
+
+ If you choose to build a module, it'll be called fdp_i2c.
+ Say N if unsure.
diff --git a/drivers/nfc/fdp/Makefile b/drivers/nfc/fdp/Makefile
new file mode 100644
index 000000000000..e79d51bdeec7
--- /dev/null
+++ b/drivers/nfc/fdp/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for FDP NCI based NFC driver
+#
+
+obj-$(CONFIG_NFC_FDP) += fdp.o
+obj-$(CONFIG_NFC_FDP_I2C) += fdp_i2c.o
+
+fdp_i2c-objs = i2c.o
+
diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c
new file mode 100644
index 000000000000..ccb07a1b153d
--- /dev/null
+++ b/drivers/nfc/fdp/fdp.c
@@ -0,0 +1,817 @@
+/* -------------------------------------------------------------------------
+ * Copyright (C) 2014-2016, Intel 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; 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/nfc.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <net/nfc/nci_core.h>
+
+#include "fdp.h"
+
+#define FDP_OTP_PATCH_NAME "otp.bin"
+#define FDP_RAM_PATCH_NAME "ram.bin"
+#define FDP_FW_HEADER_SIZE 576
+#define FDP_FW_UPDATE_SLEEP 1000
+
+#define NCI_GET_VERSION_TIMEOUT 8000
+#define NCI_PATCH_REQUEST_TIMEOUT 8000
+#define FDP_PATCH_CONN_DEST 0xC2
+#define FDP_PATCH_CONN_PARAM_TYPE 0xA0
+
+#define NCI_PATCH_TYPE_RAM 0x00
+#define NCI_PATCH_TYPE_OTP 0x01
+#define NCI_PATCH_TYPE_EOT 0xFF
+
+#define NCI_PARAM_ID_FW_RAM_VERSION 0xA0
+#define NCI_PARAM_ID_FW_OTP_VERSION 0xA1
+#define NCI_PARAM_ID_OTP_LIMITED_VERSION 0xC5
+#define NCI_PARAM_ID_KEY_INDEX_ID 0xC6
+
+#define NCI_GID_PROP 0x0F
+#define NCI_OP_PROP_PATCH_OID 0x08
+#define NCI_OP_PROP_SET_PDATA_OID 0x23
+
+struct fdp_nci_info {
+ struct nfc_phy_ops *phy_ops;
+ struct fdp_i2c_phy *phy;
+ struct nci_dev *ndev;
+
+ const struct firmware *otp_patch;
+ const struct firmware *ram_patch;
+ u32 otp_patch_version;
+ u32 ram_patch_version;
+
+ u32 otp_version;
+ u32 ram_version;
+ u32 limited_otp_version;
+ u8 key_index;
+
+ u8 *fw_vsc_cfg;
+ u8 clock_type;
+ u32 clock_freq;
+
+ atomic_t data_pkt_counter;
+ void (*data_pkt_counter_cb)(struct nci_dev *ndev);
+ u8 setup_patch_sent;
+ u8 setup_patch_ntf;
+ u8 setup_patch_status;
+ u8 setup_reset_ntf;
+ wait_queue_head_t setup_wq;
+};
+
+static u8 nci_core_get_config_otp_ram_version[5] = {
+ 0x04,
+ NCI_PARAM_ID_FW_RAM_VERSION,
+ NCI_PARAM_ID_FW_OTP_VERSION,
+ NCI_PARAM_ID_OTP_LIMITED_VERSION,
+ NCI_PARAM_ID_KEY_INDEX_ID
+};
+
+struct nci_core_get_config_rsp {
+ u8 status;
+ u8 count;
+ u8 data[0];
+};
+
+static int fdp_nci_create_conn(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct core_conn_create_dest_spec_params param;
+ int r;
+
+ /* proprietary destination specific paramerer without value */
+ param.type = FDP_PATCH_CONN_PARAM_TYPE;
+ param.length = 0x00;
+
+ r = nci_core_conn_create(info->ndev, FDP_PATCH_CONN_DEST, 1,
+ sizeof(param), &param);
+ if (r)
+ return r;
+
+ return nci_get_conn_info_by_id(ndev, 0);
+}
+
+static inline int fdp_nci_get_versions(struct nci_dev *ndev)
+{
+ return nci_core_cmd(ndev, NCI_OP_CORE_GET_CONFIG_CMD,
+ sizeof(nci_core_get_config_otp_ram_version),
+ (__u8 *) &nci_core_get_config_otp_ram_version);
+}
+
+static inline int fdp_nci_patch_cmd(struct nci_dev *ndev, u8 type)
+{
+ return nci_prop_cmd(ndev, NCI_OP_PROP_PATCH_OID, sizeof(type), &type);
+}
+
+static inline int fdp_nci_set_production_data(struct nci_dev *ndev, u8 len,
+ char *data)
+{
+ return nci_prop_cmd(ndev, NCI_OP_PROP_SET_PDATA_OID, len, data);
+}
+
+static int fdp_nci_set_clock(struct nci_dev *ndev, u8 clock_type,
+ u32 clock_freq)
+{
+ u32 fc = 13560;
+ u32 nd, num, delta;
+ char data[9];
+
+ nd = (24 * fc) / clock_freq;
+ delta = 24 * fc - nd * clock_freq;
+ num = (32768 * delta) / clock_freq;
+
+ data[0] = 0x00;
+ data[1] = 0x00;
+ data[2] = 0x00;
+
+ data[3] = 0x10;
+ data[4] = 0x04;
+ data[5] = num & 0xFF;
+ data[6] = (num >> 8) & 0xff;
+ data[7] = nd;
+ data[8] = clock_type;
+
+ return fdp_nci_set_production_data(ndev, 9, data);
+}
+
+static void fdp_nci_send_patch_cb(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+
+ info->setup_patch_sent = 1;
+ wake_up(&info->setup_wq);
+}
+
+/**
+ * Register a packet sent counter and a callback
+ *
+ * We have no other way of knowing when all firmware packets were sent out
+ * on the i2c bus. We need to know that in order to close the connection and
+ * send the patch end message.
+ */
+static void fdp_nci_set_data_pkt_counter(struct nci_dev *ndev,
+ void (*cb)(struct nci_dev *ndev), int count)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "NCI data pkt counter %d\n", count);
+ atomic_set(&info->data_pkt_counter, count);
+ info->data_pkt_counter_cb = cb;
+}
+
+/**
+ * The device is expecting a stream of packets. All packets need to
+ * have the PBF flag set to 0x0 (last packet) even if the firmware
+ * file is segmented and there are multiple packets. If we give the
+ * whole firmware to nci_send_data it will segment it and it will set
+ * the PBF flag to 0x01 so we need to do the segmentation here.
+ *
+ * The firmware will be analyzed and applied when we send NCI_OP_PROP_PATCH_CMD
+ * command with NCI_PATCH_TYPE_EOT parameter. The device will send a
+ * NFCC_PATCH_NTF packaet and a NCI_OP_CORE_RESET_NTF packet.
+ */
+static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ const struct firmware *fw;
+ struct sk_buff *skb;
+ unsigned long len;
+ u8 max_size, payload_size;
+ int rc = 0;
+
+ if ((type == NCI_PATCH_TYPE_OTP && !info->otp_patch) ||
+ (type == NCI_PATCH_TYPE_RAM && !info->ram_patch))
+ return -EINVAL;
+
+ if (type == NCI_PATCH_TYPE_OTP)
+ fw = info->otp_patch;
+ else
+ fw = info->ram_patch;
+
+ max_size = nci_conn_max_data_pkt_payload_size(ndev, conn_id);
+ if (max_size <= 0)
+ return -EINVAL;
+
+ len = fw->size;
+
+ fdp_nci_set_data_pkt_counter(ndev, fdp_nci_send_patch_cb,
+ DIV_ROUND_UP(fw->size, max_size));
+
+ while (len) {
+
+ payload_size = min_t(unsigned long, (unsigned long) max_size,
+ len);
+
+ skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + payload_size),
+ GFP_KERNEL);
+ if (!skb) {
+ fdp_nci_set_data_pkt_counter(ndev, NULL, 0);
+ return -ENOMEM;
+ }
+
+
+ skb_reserve(skb, NCI_CTRL_HDR_SIZE);
+
+ memcpy(skb_put(skb, payload_size), fw->data + (fw->size - len),
+ payload_size);
+
+ rc = nci_send_data(ndev, conn_id, skb);
+
+ if (rc) {
+ fdp_nci_set_data_pkt_counter(ndev, NULL, 0);
+ return rc;
+ }
+
+ len -= payload_size;
+ }
+
+ return rc;
+}
+
+static int fdp_nci_open(struct nci_dev *ndev)
+{
+ int r;
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ r = info->phy_ops->enable(info->phy);
+
+ return r;
+}
+
+static int fdp_nci_close(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+ return 0;
+}
+
+static int fdp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (atomic_dec_and_test(&info->data_pkt_counter))
+ info->data_pkt_counter_cb(ndev);
+
+ return info->phy_ops->write(info->phy, skb);
+}
+
+int fdp_nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+ return nci_recv_frame(ndev, skb);
+}
+EXPORT_SYMBOL(fdp_nci_recv_frame);
+
+static int fdp_nci_request_firmware(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ u8 *data;
+ int r;
+
+ r = request_firmware(&info->ram_patch, FDP_RAM_PATCH_NAME, dev);
+ if (r < 0) {
+ nfc_err(dev, "RAM patch request error\n");
+ goto error;
+ }
+
+ data = (u8 *) info->ram_patch->data;
+ info->ram_patch_version =
+ data[FDP_FW_HEADER_SIZE] |
+ (data[FDP_FW_HEADER_SIZE + 1] << 8) |
+ (data[FDP_FW_HEADER_SIZE + 2] << 16) |
+ (data[FDP_FW_HEADER_SIZE + 3] << 24);
+
+ dev_dbg(dev, "RAM patch version: %d, size: %d\n",
+ info->ram_patch_version, (int) info->ram_patch->size);
+
+
+ r = request_firmware(&info->otp_patch, FDP_OTP_PATCH_NAME, dev);
+ if (r < 0) {
+ nfc_err(dev, "OTP patch request error\n");
+ goto out;
+ }
+
+ data = (u8 *) info->otp_patch->data;
+ info->otp_patch_version =
+ data[FDP_FW_HEADER_SIZE] |
+ (data[FDP_FW_HEADER_SIZE + 1] << 8) |
+ (data[FDP_FW_HEADER_SIZE+2] << 16) |
+ (data[FDP_FW_HEADER_SIZE+3] << 24);
+
+ dev_dbg(dev, "OTP patch version: %d, size: %d\n",
+ info->otp_patch_version, (int) info->otp_patch->size);
+out:
+ return 0;
+error:
+ return r;
+}
+
+static void fdp_nci_release_firmware(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+
+ if (info->otp_patch) {
+ release_firmware(info->otp_patch);
+ info->otp_patch = NULL;
+ }
+
+ if (info->ram_patch) {
+ release_firmware(info->ram_patch);
+ info->otp_patch = NULL;
+ }
+}
+
+static int fdp_nci_patch_otp(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ u8 conn_id;
+ int r = 0;
+
+ if (info->otp_version >= info->otp_patch_version)
+ goto out;
+
+ info->setup_patch_sent = 0;
+ info->setup_reset_ntf = 0;
+ info->setup_patch_ntf = 0;
+
+ /* Patch init request */
+ r = fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_OTP);
+ if (r)
+ goto out;
+
+ /* Patch data connection creation */
+ conn_id = fdp_nci_create_conn(ndev);
+ if (conn_id < 0) {
+ r = conn_id;
+ goto out;
+ }
+
+ /* Send the patch over the data connection */
+ r = fdp_nci_send_patch(ndev, conn_id, NCI_PATCH_TYPE_OTP);
+ if (r)
+ goto out;
+
+ /* Wait for all the packets to be send over i2c */
+ wait_event_interruptible(info->setup_wq,
+ info->setup_patch_sent == 1);
+
+ /* make sure that the NFCC processed the last data packet */
+ msleep(FDP_FW_UPDATE_SLEEP);
+
+ /* Close the data connection */
+ r = nci_core_conn_close(info->ndev, conn_id);
+ if (r)
+ goto out;
+
+ /* Patch finish message */
+ if (fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_EOT)) {
+ nfc_err(dev, "OTP patch error 0x%x\n", r);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* If the patch notification didn't arrive yet, wait for it */
+ wait_event_interruptible(info->setup_wq, info->setup_patch_ntf);
+
+ /* Check if the patching was successful */
+ r = info->setup_patch_status;
+ if (r) {
+ nfc_err(dev, "OTP patch error 0x%x\n", r);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * We need to wait for the reset notification before we
+ * can continue
+ */
+ wait_event_interruptible(info->setup_wq, info->setup_reset_ntf);
+
+out:
+ return r;
+}
+
+static int fdp_nci_patch_ram(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ u8 conn_id;
+ int r = 0;
+
+ if (info->ram_version >= info->ram_patch_version)
+ goto out;
+
+ info->setup_patch_sent = 0;
+ info->setup_reset_ntf = 0;
+ info->setup_patch_ntf = 0;
+
+ /* Patch init request */
+ r = fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_RAM);
+ if (r)
+ goto out;
+
+ /* Patch data connection creation */
+ conn_id = fdp_nci_create_conn(ndev);
+ if (conn_id < 0) {
+ r = conn_id;
+ goto out;
+ }
+
+ /* Send the patch over the data connection */
+ r = fdp_nci_send_patch(ndev, conn_id, NCI_PATCH_TYPE_RAM);
+ if (r)
+ goto out;
+
+ /* Wait for all the packets to be send over i2c */
+ wait_event_interruptible(info->setup_wq,
+ info->setup_patch_sent == 1);
+
+ /* make sure that the NFCC processed the last data packet */
+ msleep(FDP_FW_UPDATE_SLEEP);
+
+ /* Close the data connection */
+ r = nci_core_conn_close(info->ndev, conn_id);
+ if (r)
+ goto out;
+
+ /* Patch finish message */
+ if (fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_EOT)) {
+ nfc_err(dev, "RAM patch error 0x%x\n", r);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* If the patch notification didn't arrive yet, wait for it */
+ wait_event_interruptible(info->setup_wq, info->setup_patch_ntf);
+
+ /* Check if the patching was successful */
+ r = info->setup_patch_status;
+ if (r) {
+ nfc_err(dev, "RAM patch error 0x%x\n", r);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * We need to wait for the reset notification before we
+ * can continue
+ */
+ wait_event_interruptible(info->setup_wq, info->setup_reset_ntf);
+
+out:
+ return r;
+}
+
+static int fdp_nci_setup(struct nci_dev *ndev)
+{
+ /* Format: total length followed by an NCI packet */
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ int r;
+ u8 patched = 0;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ r = nci_core_init(ndev);
+ if (r)
+ goto error;
+
+ /* Get RAM and OTP version */
+ r = fdp_nci_get_versions(ndev);
+ if (r)
+ goto error;
+
+ /* Load firmware from disk */
+ r = fdp_nci_request_firmware(ndev);
+ if (r)
+ goto error;
+
+ /* Update OTP */
+ if (info->otp_version < info->otp_patch_version) {
+ r = fdp_nci_patch_otp(ndev);
+ if (r)
+ goto error;
+ patched = 1;
+ }
+
+ /* Update RAM */
+ if (info->ram_version < info->ram_patch_version) {
+ r = fdp_nci_patch_ram(ndev);
+ if (r)
+ goto error;
+ patched = 1;
+ }
+
+ /* Release the firmware buffers */
+ fdp_nci_release_firmware(ndev);
+
+ /* If a patch was applied the new version is checked */
+ if (patched) {
+ r = nci_core_init(ndev);
+ if (r)
+ goto error;
+
+ r = fdp_nci_get_versions(ndev);
+ if (r)
+ goto error;
+
+ if (info->otp_version != info->otp_patch_version ||
+ info->ram_version != info->ram_patch_version) {
+ nfc_err(dev, "Firmware update failed");
+ r = -EINVAL;
+ goto error;
+ }
+ }
+
+ /*
+ * We initialized the devices but the NFC subsystem expects
+ * it to not be initialized.
+ */
+ return nci_core_reset(ndev);
+
+error:
+ fdp_nci_release_firmware(ndev);
+ nfc_err(dev, "Setup error %d\n", r);
+ return r;
+}
+
+static int fdp_nci_post_setup(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ int r;
+
+ /* Check if the device has VSC */
+ if (info->fw_vsc_cfg && info->fw_vsc_cfg[0]) {
+
+ /* Set the vendor specific configuration */
+ r = fdp_nci_set_production_data(ndev, info->fw_vsc_cfg[3],
+ &info->fw_vsc_cfg[4]);
+ if (r) {
+ nfc_err(dev, "Vendor specific config set error %d\n",
+ r);
+ return r;
+ }
+ }
+
+ /* Set clock type and frequency */
+ r = fdp_nci_set_clock(ndev, info->clock_type, info->clock_freq);
+ if (r) {
+ nfc_err(dev, "Clock set error %d\n", r);
+ return r;
+ }
+
+ /*
+ * In order to apply the VSC FDP needs a reset
+ */
+ r = nci_core_reset(ndev);
+ if (r)
+ return r;
+
+ /**
+ * The nci core was initialized when post setup was called
+ * so we leave it like that
+ */
+ return nci_core_init(ndev);
+}
+
+static int fdp_nci_core_reset_ntf_packet(struct nci_dev *ndev,
+ struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+ info->setup_reset_ntf = 1;
+ wake_up(&info->setup_wq);
+
+ return 0;
+}
+
+static int fdp_nci_prop_patch_ntf_packet(struct nci_dev *ndev,
+ struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+ info->setup_patch_ntf = 1;
+ info->setup_patch_status = skb->data[0];
+ wake_up(&info->setup_wq);
+
+ return 0;
+}
+
+static int fdp_nci_prop_patch_rsp_packet(struct nci_dev *ndev,
+ struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ u8 status = skb->data[0];
+
+ dev_dbg(dev, "%s: status 0x%x\n", __func__, status);
+ nci_req_complete(ndev, status);
+
+ return 0;
+}
+
+static int fdp_nci_prop_set_production_data_rsp_packet(struct nci_dev *ndev,
+ struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ u8 status = skb->data[0];
+
+ dev_dbg(dev, "%s: status 0x%x\n", __func__, status);
+ nci_req_complete(ndev, status);
+
+ return 0;
+}
+
+static int fdp_nci_core_get_config_rsp_packet(struct nci_dev *ndev,
+ struct sk_buff *skb)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+ struct nci_core_get_config_rsp *rsp = (void *) skb->data;
+ u8 i, *p;
+
+ if (rsp->status == NCI_STATUS_OK) {
+
+ p = rsp->data;
+ for (i = 0; i < 4; i++) {
+
+ switch (*p++) {
+ case NCI_PARAM_ID_FW_RAM_VERSION:
+ p++;
+ info->ram_version = le32_to_cpup((__le32 *) p);
+ p += 4;
+ break;
+ case NCI_PARAM_ID_FW_OTP_VERSION:
+ p++;
+ info->otp_version = le32_to_cpup((__le32 *) p);
+ p += 4;
+ break;
+ case NCI_PARAM_ID_OTP_LIMITED_VERSION:
+ p++;
+ info->otp_version = le32_to_cpup((__le32 *) p);
+ p += 4;
+ break;
+ case NCI_PARAM_ID_KEY_INDEX_ID:
+ p++;
+ info->key_index = *p++;
+ }
+ }
+ }
+
+ dev_dbg(dev, "OTP version %d\n", info->otp_version);
+ dev_dbg(dev, "RAM version %d\n", info->ram_version);
+ dev_dbg(dev, "key index %d\n", info->key_index);
+ dev_dbg(dev, "%s: status 0x%x\n", __func__, rsp->status);
+
+ nci_req_complete(ndev, rsp->status);
+
+ return 0;
+}
+
+static struct nci_driver_ops fdp_core_ops[] = {
+ {
+ .opcode = NCI_OP_CORE_GET_CONFIG_RSP,
+ .rsp = fdp_nci_core_get_config_rsp_packet,
+ },
+ {
+ .opcode = NCI_OP_CORE_RESET_NTF,
+ .ntf = fdp_nci_core_reset_ntf_packet,
+ },
+};
+
+static struct nci_driver_ops fdp_prop_ops[] = {
+ {
+ .opcode = nci_opcode_pack(NCI_GID_PROP, NCI_OP_PROP_PATCH_OID),
+ .rsp = fdp_nci_prop_patch_rsp_packet,
+ .ntf = fdp_nci_prop_patch_ntf_packet,
+ },
+ {
+ .opcode = nci_opcode_pack(NCI_GID_PROP,
+ NCI_OP_PROP_SET_PDATA_OID),
+ .rsp = fdp_nci_prop_set_production_data_rsp_packet,
+ },
+};
+
+struct nci_ops nci_ops = {
+ .open = fdp_nci_open,
+ .close = fdp_nci_close,
+ .send = fdp_nci_send,
+ .setup = fdp_nci_setup,
+ .post_setup = fdp_nci_post_setup,
+ .prop_ops = fdp_prop_ops,
+ .n_prop_ops = ARRAY_SIZE(fdp_prop_ops),
+ .core_ops = fdp_core_ops,
+ .n_core_ops = ARRAY_SIZE(fdp_core_ops),
+};
+
+int fdp_nci_probe(struct fdp_i2c_phy *phy, struct nfc_phy_ops *phy_ops,
+ struct nci_dev **ndevp, int tx_headroom,
+ int tx_tailroom, u8 clock_type, u32 clock_freq,
+ u8 *fw_vsc_cfg)
+{
+ struct device *dev = &phy->i2c_dev->dev;
+ struct fdp_nci_info *info;
+ struct nci_dev *ndev;
+ u32 protocols;
+ int r;
+
+ info = kzalloc(sizeof(struct fdp_nci_info), GFP_KERNEL);
+ if (!info) {
+ r = -ENOMEM;
+ goto err_info_alloc;
+ }
+
+ info->phy = phy;
+ info->phy_ops = phy_ops;
+ info->clock_type = clock_type;
+ info->clock_freq = clock_freq;
+ info->fw_vsc_cfg = fw_vsc_cfg;
+
+ init_waitqueue_head(&info->setup_wq);
+
+ protocols = NFC_PROTO_JEWEL_MASK |
+ NFC_PROTO_MIFARE_MASK |
+ NFC_PROTO_FELICA_MASK |
+ NFC_PROTO_ISO14443_MASK |
+ NFC_PROTO_ISO14443_B_MASK |
+ NFC_PROTO_NFC_DEP_MASK |
+ NFC_PROTO_ISO15693_MASK;
+
+ ndev = nci_allocate_device(&nci_ops, protocols, tx_headroom,
+ tx_tailroom);
+ if (!ndev) {
+ nfc_err(dev, "Cannot allocate nfc ndev\n");
+ r = -ENOMEM;
+ goto err_alloc_ndev;
+ }
+
+ r = nci_register_device(ndev);
+ if (r)
+ goto err_regdev;
+
+ *ndevp = ndev;
+ info->ndev = ndev;
+
+ nci_set_drvdata(ndev, info);
+
+ return 0;
+
+err_regdev:
+ nci_free_device(ndev);
+err_alloc_ndev:
+ kfree(info);
+err_info_alloc:
+ return r;
+}
+EXPORT_SYMBOL(fdp_nci_probe);
+
+void fdp_nci_remove(struct nci_dev *ndev)
+{
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
+ struct device *dev = &info->phy->i2c_dev->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ nci_unregister_device(ndev);
+ nci_free_device(ndev);
+ kfree(info);
+}
+EXPORT_SYMBOL(fdp_nci_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("NFC NCI driver for Intel Fields Peak NFC controller");
+MODULE_AUTHOR("Robert Dolca <robert.dolca@intel.com>");
diff --git a/drivers/nfc/fdp/fdp.h b/drivers/nfc/fdp/fdp.h
new file mode 100644
index 000000000000..0bd36c00535d
--- /dev/null
+++ b/drivers/nfc/fdp/fdp.h
@@ -0,0 +1,38 @@
+/* -------------------------------------------------------------------------
+ * Copyright (C) 2014-2016, Intel 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef __LOCAL_FDP_H_
+#define __LOCAL_FDP_H_
+
+#include <net/nfc/nci_core.h>
+#include <linux/gpio/consumer.h>
+
+struct fdp_i2c_phy {
+ struct i2c_client *i2c_dev;
+ struct gpio_desc *power_gpio;
+ struct nci_dev *ndev;
+
+ /* < 0 if i2c error occurred */
+ int hard_fault;
+ uint16_t next_read_size;
+};
+
+int fdp_nci_probe(struct fdp_i2c_phy *phy, struct nfc_phy_ops *phy_ops,
+ struct nci_dev **ndev, int tx_headroom, int tx_tailroom,
+ u8 clock_type, u32 clock_freq, u8 *fw_vsc_cfg);
+void fdp_nci_remove(struct nci_dev *ndev);
+int fdp_nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
+
+#endif /* __LOCAL_FDP_H_ */
diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c
new file mode 100644
index 000000000000..532db28145c7
--- /dev/null
+++ b/drivers/nfc/fdp/i2c.c
@@ -0,0 +1,388 @@
+/* -------------------------------------------------------------------------
+ * Copyright (C) 2014-2016, Intel 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; 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/acpi.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/nfc.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <net/nfc/nfc.h>
+#include <net/nfc/nci_core.h>
+
+#include "fdp.h"
+
+#define FDP_I2C_DRIVER_NAME "fdp_nci_i2c"
+
+#define FDP_DP_POWER_GPIO_NAME "power"
+#define FDP_DP_CLOCK_TYPE_NAME "clock-type"
+#define FDP_DP_CLOCK_FREQ_NAME "clock-freq"
+#define FDP_DP_FW_VSC_CFG_NAME "fw-vsc-cfg"
+
+#define FDP_FRAME_HEADROOM 2
+#define FDP_FRAME_TAILROOM 1
+
+#define FDP_NCI_I2C_MIN_PAYLOAD 5
+#define FDP_NCI_I2C_MAX_PAYLOAD 261
+
+#define FDP_POWER_OFF 0
+#define FDP_POWER_ON 1
+
+#define fdp_nci_i2c_dump_skb(dev, prefix, skb) \
+ print_hex_dump(KERN_DEBUG, prefix": ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, 0)
+
+static void fdp_nci_i2c_reset(struct fdp_i2c_phy *phy)
+{
+ /* Reset RST/WakeUP for at least 100 micro-second */
+ gpiod_set_value_cansleep(phy->power_gpio, FDP_POWER_OFF);
+ usleep_range(1000, 4000);
+ gpiod_set_value_cansleep(phy->power_gpio, FDP_POWER_ON);
+ usleep_range(10000, 14000);
+}
+
+static int fdp_nci_i2c_enable(void *phy_id)
+{
+ struct fdp_i2c_phy *phy = phy_id;
+
+ dev_dbg(&phy->i2c_dev->dev, "%s\n", __func__);
+ fdp_nci_i2c_reset(phy);
+
+ return 0;
+}
+
+static void fdp_nci_i2c_disable(void *phy_id)
+{
+ struct fdp_i2c_phy *phy = phy_id;
+
+ dev_dbg(&phy->i2c_dev->dev, "%s\n", __func__);
+ fdp_nci_i2c_reset(phy);
+}
+
+static void fdp_nci_i2c_add_len_lrc(struct sk_buff *skb)
+{
+ u8 lrc = 0;
+ u16 len, i;
+
+ /* Add length header */
+ len = skb->len;
+ *skb_push(skb, 1) = len & 0xff;
+ *skb_push(skb, 1) = len >> 8;
+
+ /* Compute and add lrc */
+ for (i = 0; i < len + 2; i++)
+ lrc ^= skb->data[i];
+
+ *skb_put(skb, 1) = lrc;
+}
+
+static void fdp_nci_i2c_remove_len_lrc(struct sk_buff *skb)
+{
+ skb_pull(skb, FDP_FRAME_HEADROOM);
+ skb_trim(skb, skb->len - FDP_FRAME_TAILROOM);
+}
+
+static int fdp_nci_i2c_write(void *phy_id, struct sk_buff *skb)
+{
+ struct fdp_i2c_phy *phy = phy_id;
+ struct i2c_client *client = phy->i2c_dev;
+ int r;
+
+ if (phy->hard_fault != 0)
+ return phy->hard_fault;
+
+ fdp_nci_i2c_add_len_lrc(skb);
+ fdp_nci_i2c_dump_skb(&client->dev, "fdp_wr", skb);
+
+ r = i2c_master_send(client, skb->data, skb->len);
+ if (r == -EREMOTEIO) { /* Retry, chip was in standby */
+ usleep_range(1000, 4000);
+ r = i2c_master_send(client, skb->data, skb->len);
+ }
+
+ if (r < 0 || r != skb->len)
+ dev_dbg(&client->dev, "%s: error err=%d len=%d\n",
+ __func__, r, skb->len);
+
+ if (r >= 0) {
+ if (r != skb->len) {
+ phy->hard_fault = r;
+ r = -EREMOTEIO;
+ } else {
+ r = 0;
+ }
+ }
+
+ fdp_nci_i2c_remove_len_lrc(skb);
+
+ return r;
+}
+
+static struct nfc_phy_ops i2c_phy_ops = {
+ .write = fdp_nci_i2c_write,
+ .enable = fdp_nci_i2c_enable,
+ .disable = fdp_nci_i2c_disable,
+};
+
+static int fdp_nci_i2c_read(struct fdp_i2c_phy *phy, struct sk_buff **skb)
+{
+ int r, len;
+ u8 tmp[FDP_NCI_I2C_MAX_PAYLOAD], lrc, k;
+ u16 i;
+ struct i2c_client *client = phy->i2c_dev;
+
+ *skb = NULL;
+
+ /* Read the length packet and the data packet */
+ for (k = 0; k < 2; k++) {
+
+ len = phy->next_read_size;
+
+ r = i2c_master_recv(client, tmp, len);
+ if (r != len) {
+ dev_dbg(&client->dev, "%s: i2c recv err: %d\n",
+ __func__, r);
+ goto flush;
+ }
+
+ /* Check packet integruty */
+ for (lrc = i = 0; i < r; i++)
+ lrc ^= tmp[i];
+
+ /*
+ * LRC check failed. This may due to transmission error or
+ * desynchronization between driver and FDP. Drop the paquet
+ * and force resynchronization
+ */
+ if (lrc) {
+ dev_dbg(&client->dev, "%s: corrupted packet\n",
+ __func__);
+ phy->next_read_size = 5;
+ goto flush;
+ }
+
+ /* Packet that contains a length */
+ if (tmp[0] == 0 && tmp[1] == 0) {
+ phy->next_read_size = (tmp[2] << 8) + tmp[3] + 3;
+ } else {
+ phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;
+
+ *skb = alloc_skb(len, GFP_KERNEL);
+ if (*skb == NULL) {
+ r = -ENOMEM;
+ goto flush;
+ }
+
+ memcpy(skb_put(*skb, len), tmp, len);
+ fdp_nci_i2c_dump_skb(&client->dev, "fdp_rd", *skb);
+
+ fdp_nci_i2c_remove_len_lrc(*skb);
+ }
+ }
+
+ return 0;
+
+flush:
+ /* Flush the remaining data */
+ if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
+ r = -EREMOTEIO;
+
+ return r;
+}
+
+static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
+{
+ struct fdp_i2c_phy *phy = phy_id;
+ struct i2c_client *client;
+ struct sk_buff *skb;
+ int r;
+
+ client = phy->i2c_dev;
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ if (!phy || irq != phy->i2c_dev->irq) {
+ WARN_ON_ONCE(1);
+ return IRQ_NONE;
+ }
+
+ r = fdp_nci_i2c_read(phy, &skb);
+
+ if (r == -EREMOTEIO)
+ return IRQ_HANDLED;
+ else if (r == -ENOMEM || r == -EBADMSG)
+ return IRQ_HANDLED;
+
+ if (skb != NULL)
+ fdp_nci_recv_frame(phy->ndev, skb);
+
+ return IRQ_HANDLED;
+}
+
+static void fdp_nci_i2c_read_device_properties(struct device *dev,
+ u8 *clock_type, u32 *clock_freq,
+ u8 **fw_vsc_cfg)
+{
+ int r;
+ u8 len;
+
+ r = device_property_read_u8(dev, FDP_DP_CLOCK_TYPE_NAME, clock_type);
+ if (r) {
+ dev_dbg(dev, "Using default clock type");
+ *clock_type = 0;
+ }
+
+ r = device_property_read_u32(dev, FDP_DP_CLOCK_FREQ_NAME, clock_freq);
+ if (r) {
+ dev_dbg(dev, "Using default clock frequency\n");
+ *clock_freq = 26000;
+ }
+
+ if (device_property_present(dev, FDP_DP_FW_VSC_CFG_NAME)) {
+ r = device_property_read_u8(dev, FDP_DP_FW_VSC_CFG_NAME,
+ &len);
+
+ if (r || len <= 0)
+ goto vsc_read_err;
+
+ /* Add 1 to the length to inclue the length byte itself */
+ len++;
+
+ *fw_vsc_cfg = devm_kmalloc(dev,
+ len * sizeof(**fw_vsc_cfg),
+ GFP_KERNEL);
+
+ r = device_property_read_u8_array(dev, FDP_DP_FW_VSC_CFG_NAME,
+ *fw_vsc_cfg, len);
+
+ if (r) {
+ devm_kfree(dev, fw_vsc_cfg);
+ goto vsc_read_err;
+ }
+ } else {
+vsc_read_err:
+ dev_dbg(dev, "FW vendor specific commands not present\n");
+ *fw_vsc_cfg = NULL;
+ }
+
+ dev_dbg(dev, "Clock type: %d, clock frequency: %d, VSC: %s",
+ *clock_type, *clock_freq, *fw_vsc_cfg != NULL ? "yes" : "no");
+}
+
+static int fdp_nci_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct fdp_i2c_phy *phy;
+ struct device *dev = &client->dev;
+ u8 *fw_vsc_cfg;
+ u8 clock_type;
+ u32 clock_freq;
+ int r = 0;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ nfc_err(dev, "No I2C_FUNC_I2C support\n");
+ return -ENODEV;
+ }
+
+ phy = devm_kzalloc(dev, sizeof(struct fdp_i2c_phy),
+ GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ phy->i2c_dev = client;
+ phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;
+ i2c_set_clientdata(client, phy);
+
+ /* Checking if we have an irq */
+ if (client->irq <= 0) {
+ dev_err(dev, "IRQ not present\n");
+ return -ENODEV;
+ }
+
+ r = request_threaded_irq(client->irq, NULL, fdp_nci_i2c_irq_thread_fn,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ FDP_I2C_DRIVER_NAME, phy);
+
+ if (r < 0) {
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+ return r;
+ }
+
+ /* Requesting the power gpio */
+ phy->power_gpio = devm_gpiod_get(dev, FDP_DP_POWER_GPIO_NAME,
+ GPIOD_OUT_LOW);
+
+ if (IS_ERR(phy->power_gpio)) {
+ nfc_err(dev, "Power GPIO request failed\n");
+ return PTR_ERR(phy->power_gpio);
+ }
+
+ /* read device properties to get the clock and production settings */
+ fdp_nci_i2c_read_device_properties(dev, &clock_type, &clock_freq,
+ &fw_vsc_cfg);
+
+ /* Call the NFC specific probe function */
+ r = fdp_nci_probe(phy, &i2c_phy_ops, &phy->ndev,
+ FDP_FRAME_HEADROOM, FDP_FRAME_TAILROOM,
+ clock_type, clock_freq, fw_vsc_cfg);
+ if (r < 0) {
+ nfc_err(dev, "NCI probing error\n");
+ return r;
+ }
+
+ dev_dbg(dev, "I2C driver loaded\n");
+ return 0;
+}
+
+static int fdp_nci_i2c_remove(struct i2c_client *client)
+{
+ struct fdp_i2c_phy *phy = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ fdp_nci_remove(phy->ndev);
+ fdp_nci_i2c_disable(phy);
+
+ return 0;
+}
+
+static struct i2c_device_id fdp_nci_i2c_id_table[] = {
+ {"int339a", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, fdp_nci_i2c_id_table);
+
+static const struct acpi_device_id fdp_nci_i2c_acpi_match[] = {
+ {"INT339A", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, fdp_nci_i2c_acpi_match);
+
+static struct i2c_driver fdp_nci_i2c_driver = {
+ .driver = {
+ .name = FDP_I2C_DRIVER_NAME,
+ .acpi_match_table = ACPI_PTR(fdp_nci_i2c_acpi_match),
+ },
+ .id_table = fdp_nci_i2c_id_table,
+ .probe = fdp_nci_i2c_probe,
+ .remove = fdp_nci_i2c_remove,
+};
+module_i2c_driver(fdp_nci_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("I2C driver for Intel Fields Peak NFC controller");
+MODULE_AUTHOR("Robert Dolca <robert.dolca@intel.com>");
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
index 754a9bb0f58d..83deda4bb4d6 100644
--- a/drivers/nfc/mei_phy.c
+++ b/drivers/nfc/mei_phy.c
@@ -118,7 +118,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy)
cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
MEI_DUMP_NFC_HDR("version", &cmd.hdr);
- r = mei_cl_send(phy->device, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
+ r = mei_cldev_send(phy->cldev, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
if (r < 0) {
pr_err("Could not send IF version cmd\n");
return r;
@@ -132,7 +132,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy)
if (!reply)
return -ENOMEM;
- bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, if_version_length);
+ bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, if_version_length);
if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
pr_err("Could not read IF version\n");
r = -EIO;
@@ -186,13 +186,14 @@ static int mei_nfc_connect(struct nfc_mei_phy *phy)
connect->vendor_id = phy->vendor_id;
MEI_DUMP_NFC_HDR("connect request", &cmd->hdr);
- r = mei_cl_send(phy->device, (u8 *)cmd, connect_length);
+ r = mei_cldev_send(phy->cldev, (u8 *)cmd, connect_length);
if (r < 0) {
pr_err("Could not send connect cmd %d\n", r);
goto err;
}
- bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, connect_resp_length);
+ bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply,
+ connect_resp_length);
if (bytes_recv < 0) {
r = bytes_recv;
pr_err("Could not read connect response %d\n", r);
@@ -238,7 +239,7 @@ static int mei_nfc_send(struct nfc_mei_phy *phy, u8 *buf, size_t length)
MEI_DUMP_NFC_HDR("send", hdr);
memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
- err = mei_cl_send(phy->device, mei_buf, length + MEI_NFC_HEADER_SIZE);
+ err = mei_cldev_send(phy->cldev, mei_buf, length + MEI_NFC_HEADER_SIZE);
if (err < 0)
goto out;
@@ -278,7 +279,7 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length)
struct mei_nfc_hdr *hdr;
int received_length;
- received_length = mei_cl_recv(phy->device, buf, length);
+ received_length = mei_cldev_recv(phy->cldev, buf, length);
if (received_length < 0)
return received_length;
@@ -296,7 +297,7 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length)
}
-static void nfc_mei_event_cb(struct mei_cl_device *device, u32 events,
+static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events,
void *context)
{
struct nfc_mei_phy *phy = context;
@@ -337,7 +338,7 @@ static int nfc_mei_phy_enable(void *phy_id)
if (phy->powered == 1)
return 0;
- r = mei_cl_enable_device(phy->device);
+ r = mei_cldev_enable(phy->cldev);
if (r < 0) {
pr_err("Could not enable device %d\n", r);
return r;
@@ -355,7 +356,7 @@ static int nfc_mei_phy_enable(void *phy_id)
goto err;
}
- r = mei_cl_register_event_cb(phy->device, BIT(MEI_CL_EVENT_RX),
+ r = mei_cldev_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX),
nfc_mei_event_cb, phy);
if (r) {
pr_err("Event cb registration failed %d\n", r);
@@ -368,7 +369,7 @@ static int nfc_mei_phy_enable(void *phy_id)
err:
phy->powered = 0;
- mei_cl_disable_device(phy->device);
+ mei_cldev_disable(phy->cldev);
return r;
}
@@ -378,7 +379,7 @@ static void nfc_mei_phy_disable(void *phy_id)
pr_info("%s\n", __func__);
- mei_cl_disable_device(phy->device);
+ mei_cldev_disable(phy->cldev);
phy->powered = 0;
}
@@ -390,7 +391,7 @@ struct nfc_phy_ops mei_phy_ops = {
};
EXPORT_SYMBOL_GPL(mei_phy_ops);
-struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device)
+struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *cldev)
{
struct nfc_mei_phy *phy;
@@ -398,9 +399,9 @@ struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device)
if (!phy)
return NULL;
- phy->device = device;
+ phy->cldev = cldev;
init_waitqueue_head(&phy->send_wq);
- mei_cl_set_drvdata(device, phy);
+ mei_cldev_set_drvdata(cldev, phy);
return phy;
}
@@ -408,7 +409,7 @@ EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc);
void nfc_mei_phy_free(struct nfc_mei_phy *phy)
{
- mei_cl_disable_device(phy->device);
+ mei_cldev_disable(phy->cldev);
kfree(phy);
}
EXPORT_SYMBOL_GPL(nfc_mei_phy_free);
diff --git a/drivers/nfc/mei_phy.h b/drivers/nfc/mei_phy.h
index fbfa3e61738f..acd3a1fc69e6 100644
--- a/drivers/nfc/mei_phy.h
+++ b/drivers/nfc/mei_phy.h
@@ -13,7 +13,7 @@
/**
* struct nfc_mei_phy
*
- * @device: mei device
+ * @cldev: mei client device
* @hdev: nfc hci device
* @send_wq: send completion wait queue
@@ -28,7 +28,7 @@
* and prevents normal operation.
*/
struct nfc_mei_phy {
- struct mei_cl_device *device;
+ struct mei_cl_device *cldev;
struct nfc_hci_dev *hdev;
wait_queue_head_t send_wq;
diff --git a/drivers/nfc/microread/Kconfig b/drivers/nfc/microread/Kconfig
index 951d5542f6bc..2c6dbc9f6781 100644
--- a/drivers/nfc/microread/Kconfig
+++ b/drivers/nfc/microread/Kconfig
@@ -1,20 +1,15 @@
config NFC_MICROREAD
- tristate "Inside Secure microread NFC driver"
- depends on NFC_HCI
+ tristate
select CRC_CCITT
- default n
---help---
This module contains the main code for Inside Secure microread
NFC chipsets. It implements the chipset HCI logic and hooks into
the NFC kernel APIs. Physical layers will register against it.
- To compile this driver as a module, choose m here. The module will
- be called microread.
- Say N if unsure.
-
config NFC_MICROREAD_I2C
- tristate "NFC Microread i2c support"
- depends on NFC_MICROREAD && I2C && NFC_SHDLC
+ tristate "Inside Secure Microread device support (I2C)"
+ depends on NFC_HCI && I2C && NFC_SHDLC
+ select NFC_MICROREAD
---help---
This module adds support for the i2c interface of adapters using
Inside microread chipsets. Select this if your platform is using
@@ -24,8 +19,9 @@ config NFC_MICROREAD_I2C
Say N if unsure.
config NFC_MICROREAD_MEI
- tristate "NFC Microread MEI support"
- depends on NFC_MICROREAD && NFC_MEI_PHY
+ tristate "Inside Secure Microread device support (MEI)"
+ depends on NFC_HCI && NFC_MEI_PHY
+ select NFC_MICROREAD
---help---
This module adds support for the mei interface of adapters using
Inside microread chipsets. Select this if your microread chipset
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c
index f9f5fc97cdd7..3092501f26c4 100644
--- a/drivers/nfc/microread/mei.c
+++ b/drivers/nfc/microread/mei.c
@@ -29,7 +29,7 @@
#define MICROREAD_DRIVER_NAME "microread"
-static int microread_mei_probe(struct mei_cl_device *device,
+static int microread_mei_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
{
struct nfc_mei_phy *phy;
@@ -37,7 +37,7 @@ static int microread_mei_probe(struct mei_cl_device *device,
pr_info("Probing NFC microread\n");
- phy = nfc_mei_phy_alloc(device);
+ phy = nfc_mei_phy_alloc(cldev);
if (!phy) {
pr_err("Cannot allocate memory for microread mei phy.\n");
return -ENOMEM;
@@ -55,9 +55,9 @@ static int microread_mei_probe(struct mei_cl_device *device,
return 0;
}
-static int microread_mei_remove(struct mei_cl_device *device)
+static int microread_mei_remove(struct mei_cl_device *cldev)
{
- struct nfc_mei_phy *phy = mei_cl_get_drvdata(device);
+ struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
microread_remove(phy->hdev);
@@ -67,7 +67,7 @@ static int microread_mei_remove(struct mei_cl_device *device)
}
static struct mei_cl_device_id microread_mei_tbl[] = {
- { MICROREAD_DRIVER_NAME, MEI_NFC_UUID},
+ { MICROREAD_DRIVER_NAME, MEI_NFC_UUID, MEI_CL_VERSION_ANY},
/* required last entry */
{ }
@@ -88,7 +88,7 @@ static int microread_mei_init(void)
pr_debug(DRIVER_DESC ": %s\n", __func__);
- r = mei_cl_driver_register(&microread_driver);
+ r = mei_cldev_driver_register(&microread_driver);
if (r) {
pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n");
return r;
@@ -99,7 +99,7 @@ static int microread_mei_init(void)
static void microread_mei_exit(void)
{
- mei_cl_driver_unregister(&microread_driver);
+ mei_cldev_driver_unregister(&microread_driver);
}
module_init(microread_mei_init);
diff --git a/drivers/nfc/nfcmrvl/Kconfig b/drivers/nfc/nfcmrvl/Kconfig
index 796be2411440..670af76922e0 100644
--- a/drivers/nfc/nfcmrvl/Kconfig
+++ b/drivers/nfc/nfcmrvl/Kconfig
@@ -1,18 +1,15 @@
config NFC_MRVL
- tristate "Marvell NFC driver support"
- depends on NFC_NCI
+ tristate
help
The core driver to support Marvell NFC devices.
This driver is required if you want to support
Marvell NFC device 8897.
- Say Y here to compile Marvell NFC driver into the kernel or
- say M to compile it as module.
-
config NFC_MRVL_USB
tristate "Marvell NFC-over-USB driver"
- depends on NFC_MRVL && USB
+ depends on NFC_NCI && USB
+ select NFC_MRVL
help
Marvell NFC-over-USB driver.
@@ -24,7 +21,8 @@ config NFC_MRVL_USB
config NFC_MRVL_UART
tristate "Marvell NFC-over-UART driver"
- depends on NFC_MRVL && NFC_NCI_UART
+ depends on NFC_NCI && NFC_NCI_UART
+ select NFC_MRVL
help
Marvell NFC-over-UART driver.
@@ -32,3 +30,25 @@ config NFC_MRVL_UART
Say Y here to compile support for Marvell NFC-over-UART driver
into the kernel or say M to compile it as module.
+
+config NFC_MRVL_I2C
+ tristate "Marvell NFC-over-I2C driver"
+ depends on NFC_MRVL && I2C
+ help
+ Marvell NFC-over-I2C driver.
+
+ This driver provides support for Marvell NFC-over-I2C devices.
+
+ Say Y here to compile support for Marvell NFC-over-I2C driver
+ into the kernel or say M to compile it as module.
+
+config NFC_MRVL_SPI
+ tristate "Marvell NFC-over-SPI driver"
+ depends on NFC_MRVL && NFC_NCI_SPI
+ help
+ Marvell NFC-over-SPI driver.
+
+ This driver provides support for Marvell NFC-over-SPI devices.
+
+ Say Y here to compile support for Marvell NFC-over-SPI driver
+ into the kernel or say M to compile it as module.
diff --git a/drivers/nfc/nfcmrvl/Makefile b/drivers/nfc/nfcmrvl/Makefile
index 775196274d1f..fa07c7806492 100644
--- a/drivers/nfc/nfcmrvl/Makefile
+++ b/drivers/nfc/nfcmrvl/Makefile
@@ -2,7 +2,7 @@
# Makefile for NFCMRVL NCI based NFC driver
#
-nfcmrvl-y += main.o
+nfcmrvl-y += main.o fw_dnld.o
obj-$(CONFIG_NFC_MRVL) += nfcmrvl.o
nfcmrvl_usb-y += usb.o
@@ -10,3 +10,9 @@ obj-$(CONFIG_NFC_MRVL_USB) += nfcmrvl_usb.o
nfcmrvl_uart-y += uart.o
obj-$(CONFIG_NFC_MRVL_UART) += nfcmrvl_uart.o
+
+nfcmrvl_i2c-y += i2c.o
+obj-$(CONFIG_NFC_MRVL_I2C) += nfcmrvl_i2c.o
+
+nfcmrvl_spi-y += spi.o
+obj-$(CONFIG_NFC_MRVL_SPI) += nfcmrvl_spi.o
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c
new file mode 100644
index 000000000000..f8dcdf4b24f6
--- /dev/null
+++ b/drivers/nfc/nfcmrvl/fw_dnld.c
@@ -0,0 +1,559 @@
+/*
+ * Marvell NFC driver: Firmware downloader
+ *
+ * Copyright (C) 2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/module.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/firmware.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include "nfcmrvl.h"
+
+#define FW_DNLD_TIMEOUT 15000
+
+#define NCI_OP_PROPRIETARY_BOOT_CMD nci_opcode_pack(NCI_GID_PROPRIETARY, \
+ NCI_OP_PROP_BOOT_CMD)
+
+/* FW download states */
+
+enum {
+ STATE_RESET = 0,
+ STATE_INIT,
+ STATE_SET_REF_CLOCK,
+ STATE_SET_HI_CONFIG,
+ STATE_OPEN_LC,
+ STATE_FW_DNLD,
+ STATE_CLOSE_LC,
+ STATE_BOOT
+};
+
+enum {
+ SUBSTATE_WAIT_COMMAND = 0,
+ SUBSTATE_WAIT_ACK_CREDIT,
+ SUBSTATE_WAIT_NACK_CREDIT,
+ SUBSTATE_WAIT_DATA_CREDIT,
+};
+
+/*
+** Patterns for responses
+*/
+
+static const uint8_t nci_pattern_core_reset_ntf[] = {
+ 0x60, 0x00, 0x02, 0xA0, 0x01
+};
+
+static const uint8_t nci_pattern_core_init_rsp[] = {
+ 0x40, 0x01, 0x11
+};
+
+static const uint8_t nci_pattern_core_set_config_rsp[] = {
+ 0x40, 0x02, 0x02, 0x00, 0x00
+};
+
+static const uint8_t nci_pattern_core_conn_create_rsp[] = {
+ 0x40, 0x04, 0x04, 0x00
+};
+
+static const uint8_t nci_pattern_core_conn_close_rsp[] = {
+ 0x40, 0x05, 0x01, 0x00
+};
+
+static const uint8_t nci_pattern_core_conn_credits_ntf[] = {
+ 0x60, 0x06, 0x03, 0x01, NCI_CORE_LC_CONNID_PROP_FW_DL, 0x01
+};
+
+static const uint8_t nci_pattern_proprietary_boot_rsp[] = {
+ 0x4F, 0x3A, 0x01, 0x00
+};
+
+static struct sk_buff *alloc_lc_skb(struct nfcmrvl_private *priv, uint8_t plen)
+{
+ struct sk_buff *skb;
+ struct nci_data_hdr *hdr;
+
+ skb = nci_skb_alloc(priv->ndev, (NCI_DATA_HDR_SIZE + plen), GFP_KERNEL);
+ if (!skb) {
+ pr_err("no memory for data\n");
+ return NULL;
+ }
+
+ hdr = (struct nci_data_hdr *) skb_put(skb, NCI_DATA_HDR_SIZE);
+ hdr->conn_id = NCI_CORE_LC_CONNID_PROP_FW_DL;
+ hdr->rfu = 0;
+ hdr->plen = plen;
+
+ nci_mt_set((__u8 *)hdr, NCI_MT_DATA_PKT);
+ nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST);
+
+ return skb;
+}
+
+static void fw_dnld_over(struct nfcmrvl_private *priv, u32 error)
+{
+ if (priv->fw_dnld.fw) {
+ release_firmware(priv->fw_dnld.fw);
+ priv->fw_dnld.fw = NULL;
+ priv->fw_dnld.header = NULL;
+ priv->fw_dnld.binary_config = NULL;
+ }
+
+ atomic_set(&priv->ndev->cmd_cnt, 0);
+
+ if (timer_pending(&priv->ndev->cmd_timer))
+ del_timer_sync(&priv->ndev->cmd_timer);
+
+ if (timer_pending(&priv->fw_dnld.timer))
+ del_timer_sync(&priv->fw_dnld.timer);
+
+ nfc_info(priv->dev, "FW loading over (%d)]\n", error);
+
+ if (error != 0) {
+ /* failed, halt the chip to avoid power consumption */
+ nfcmrvl_chip_halt(priv);
+ }
+
+ nfc_fw_download_done(priv->ndev->nfc_dev, priv->fw_dnld.name, error);
+}
+
+static void fw_dnld_timeout(unsigned long arg)
+{
+ struct nfcmrvl_private *priv = (struct nfcmrvl_private *) arg;
+
+ nfc_err(priv->dev, "FW loading timeout");
+ priv->fw_dnld.state = STATE_RESET;
+ fw_dnld_over(priv, -ETIMEDOUT);
+}
+
+static int process_state_reset(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ if (sizeof(nci_pattern_core_reset_ntf) != skb->len ||
+ memcmp(skb->data, nci_pattern_core_reset_ntf,
+ sizeof(nci_pattern_core_reset_ntf)))
+ return -EINVAL;
+
+ nfc_info(priv->dev, "BootROM reset, start fw download\n");
+
+ /* Start FW download state machine */
+ priv->fw_dnld.state = STATE_INIT;
+ nci_send_cmd(priv->ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+
+ return 0;
+}
+
+static int process_state_init(struct nfcmrvl_private *priv, struct sk_buff *skb)
+{
+ struct nci_core_set_config_cmd cmd;
+
+ if (sizeof(nci_pattern_core_init_rsp) >= skb->len ||
+ memcmp(skb->data, nci_pattern_core_init_rsp,
+ sizeof(nci_pattern_core_init_rsp)))
+ return -EINVAL;
+
+ cmd.num_params = 1;
+ cmd.param.id = NFCMRVL_PROP_REF_CLOCK;
+ cmd.param.len = 4;
+ memcpy(cmd.param.val, &priv->fw_dnld.header->ref_clock, 4);
+
+ nci_send_cmd(priv->ndev, NCI_OP_CORE_SET_CONFIG_CMD, 3 + cmd.param.len,
+ &cmd);
+
+ priv->fw_dnld.state = STATE_SET_REF_CLOCK;
+ return 0;
+}
+
+static void create_lc(struct nfcmrvl_private *priv)
+{
+ uint8_t param[2] = { NCI_CORE_LC_PROP_FW_DL, 0x0 };
+
+ priv->fw_dnld.state = STATE_OPEN_LC;
+ nci_send_cmd(priv->ndev, NCI_OP_CORE_CONN_CREATE_CMD, 2, param);
+}
+
+static int process_state_set_ref_clock(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ struct nci_core_set_config_cmd cmd;
+
+ if (sizeof(nci_pattern_core_set_config_rsp) != skb->len ||
+ memcmp(skb->data, nci_pattern_core_set_config_rsp, skb->len))
+ return -EINVAL;
+
+ cmd.num_params = 1;
+ cmd.param.id = NFCMRVL_PROP_SET_HI_CONFIG;
+
+ switch (priv->phy) {
+ case NFCMRVL_PHY_UART:
+ cmd.param.len = 5;
+ memcpy(cmd.param.val,
+ &priv->fw_dnld.binary_config->uart.baudrate,
+ 4);
+ cmd.param.val[4] =
+ priv->fw_dnld.binary_config->uart.flow_control;
+ break;
+ case NFCMRVL_PHY_I2C:
+ cmd.param.len = 5;
+ memcpy(cmd.param.val,
+ &priv->fw_dnld.binary_config->i2c.clk,
+ 4);
+ cmd.param.val[4] = 0;
+ break;
+ case NFCMRVL_PHY_SPI:
+ cmd.param.len = 5;
+ memcpy(cmd.param.val,
+ &priv->fw_dnld.binary_config->spi.clk,
+ 4);
+ cmd.param.val[4] = 0;
+ break;
+ default:
+ create_lc(priv);
+ return 0;
+ }
+
+ priv->fw_dnld.state = STATE_SET_HI_CONFIG;
+ nci_send_cmd(priv->ndev, NCI_OP_CORE_SET_CONFIG_CMD, 3 + cmd.param.len,
+ &cmd);
+ return 0;
+}
+
+static int process_state_set_hi_config(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ if (sizeof(nci_pattern_core_set_config_rsp) != skb->len ||
+ memcmp(skb->data, nci_pattern_core_set_config_rsp, skb->len))
+ return -EINVAL;
+
+ create_lc(priv);
+ return 0;
+}
+
+static int process_state_open_lc(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ if (sizeof(nci_pattern_core_conn_create_rsp) >= skb->len ||
+ memcmp(skb->data, nci_pattern_core_conn_create_rsp,
+ sizeof(nci_pattern_core_conn_create_rsp)))
+ return -EINVAL;
+
+ priv->fw_dnld.state = STATE_FW_DNLD;
+ priv->fw_dnld.substate = SUBSTATE_WAIT_COMMAND;
+ priv->fw_dnld.offset = priv->fw_dnld.binary_config->offset;
+ return 0;
+}
+
+static int process_state_fw_dnld(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ uint16_t len;
+ uint16_t comp_len;
+ struct sk_buff *out_skb;
+
+ switch (priv->fw_dnld.substate) {
+ case SUBSTATE_WAIT_COMMAND:
+ /*
+ * Command format:
+ * B0..2: NCI header
+ * B3 : Helper command (0xA5)
+ * B4..5: le16 data size
+ * B6..7: le16 data size complement (~)
+ * B8..N: payload
+ */
+
+ /* Remove NCI HDR */
+ skb_pull(skb, 3);
+ if (skb->data[0] != HELPER_CMD_PACKET_FORMAT || skb->len != 5) {
+ nfc_err(priv->dev, "bad command");
+ return -EINVAL;
+ }
+ skb_pull(skb, 1);
+ memcpy(&len, skb->data, 2);
+ skb_pull(skb, 2);
+ memcpy(&comp_len, skb->data, 2);
+ skb_pull(skb, 2);
+ len = get_unaligned_le16(&len);
+ comp_len = get_unaligned_le16(&comp_len);
+ if (((~len) & 0xFFFF) != comp_len) {
+ nfc_err(priv->dev, "bad len complement: %x %x %x",
+ len, comp_len, (~len & 0xFFFF));
+ out_skb = alloc_lc_skb(priv, 1);
+ if (!out_skb)
+ return -ENOMEM;
+ *skb_put(out_skb, 1) = 0xBF;
+ nci_send_frame(priv->ndev, out_skb);
+ priv->fw_dnld.substate = SUBSTATE_WAIT_NACK_CREDIT;
+ return 0;
+ }
+ priv->fw_dnld.chunk_len = len;
+ out_skb = alloc_lc_skb(priv, 1);
+ if (!out_skb)
+ return -ENOMEM;
+ *skb_put(out_skb, 1) = HELPER_ACK_PACKET_FORMAT;
+ nci_send_frame(priv->ndev, out_skb);
+ priv->fw_dnld.substate = SUBSTATE_WAIT_ACK_CREDIT;
+ break;
+
+ case SUBSTATE_WAIT_ACK_CREDIT:
+ if (sizeof(nci_pattern_core_conn_credits_ntf) != skb->len ||
+ memcmp(nci_pattern_core_conn_credits_ntf, skb->data,
+ skb->len)) {
+ nfc_err(priv->dev, "bad packet: waiting for credit");
+ return -EINVAL;
+ }
+ if (priv->fw_dnld.chunk_len == 0) {
+ /* FW Loading is done */
+ uint8_t conn_id = NCI_CORE_LC_CONNID_PROP_FW_DL;
+
+ priv->fw_dnld.state = STATE_CLOSE_LC;
+ nci_send_cmd(priv->ndev, NCI_OP_CORE_CONN_CLOSE_CMD,
+ 1, &conn_id);
+ } else {
+ out_skb = alloc_lc_skb(priv, priv->fw_dnld.chunk_len);
+ if (!out_skb)
+ return -ENOMEM;
+ memcpy(skb_put(out_skb, priv->fw_dnld.chunk_len),
+ ((uint8_t *)priv->fw_dnld.fw->data) +
+ priv->fw_dnld.offset,
+ priv->fw_dnld.chunk_len);
+ nci_send_frame(priv->ndev, out_skb);
+ priv->fw_dnld.substate = SUBSTATE_WAIT_DATA_CREDIT;
+ }
+ break;
+
+ case SUBSTATE_WAIT_DATA_CREDIT:
+ if (sizeof(nci_pattern_core_conn_credits_ntf) != skb->len ||
+ memcmp(nci_pattern_core_conn_credits_ntf, skb->data,
+ skb->len)) {
+ nfc_err(priv->dev, "bad packet: waiting for credit");
+ return -EINVAL;
+ }
+ priv->fw_dnld.offset += priv->fw_dnld.chunk_len;
+ priv->fw_dnld.chunk_len = 0;
+ priv->fw_dnld.substate = SUBSTATE_WAIT_COMMAND;
+ break;
+
+ case SUBSTATE_WAIT_NACK_CREDIT:
+ if (sizeof(nci_pattern_core_conn_credits_ntf) != skb->len ||
+ memcmp(nci_pattern_core_conn_credits_ntf, skb->data,
+ skb->len)) {
+ nfc_err(priv->dev, "bad packet: waiting for credit");
+ return -EINVAL;
+ }
+ priv->fw_dnld.substate = SUBSTATE_WAIT_COMMAND;
+ break;
+ }
+ return 0;
+}
+
+static int process_state_close_lc(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ if (sizeof(nci_pattern_core_conn_close_rsp) != skb->len ||
+ memcmp(skb->data, nci_pattern_core_conn_close_rsp, skb->len))
+ return -EINVAL;
+
+ priv->fw_dnld.state = STATE_BOOT;
+ nci_send_cmd(priv->ndev, NCI_OP_PROPRIETARY_BOOT_CMD, 0, NULL);
+ return 0;
+}
+
+static int process_state_boot(struct nfcmrvl_private *priv, struct sk_buff *skb)
+{
+ if (sizeof(nci_pattern_proprietary_boot_rsp) != skb->len ||
+ memcmp(skb->data, nci_pattern_proprietary_boot_rsp, skb->len))
+ return -EINVAL;
+
+ /*
+ * Update HI config to use the right configuration for the next
+ * data exchanges.
+ */
+ priv->if_ops->nci_update_config(priv,
+ &priv->fw_dnld.binary_config->config);
+
+ if (priv->fw_dnld.binary_config == &priv->fw_dnld.header->helper) {
+ /*
+ * This is the case where an helper was needed and we have
+ * uploaded it. Now we have to wait the next RESET NTF to start
+ * FW download.
+ */
+ priv->fw_dnld.state = STATE_RESET;
+ priv->fw_dnld.binary_config = &priv->fw_dnld.header->firmware;
+ nfc_info(priv->dev, "FW loading: helper loaded");
+ } else {
+ nfc_info(priv->dev, "FW loading: firmware loaded");
+ fw_dnld_over(priv, 0);
+ }
+ return 0;
+}
+
+static void fw_dnld_rx_work(struct work_struct *work)
+{
+ int ret;
+ struct sk_buff *skb;
+ struct nfcmrvl_fw_dnld *fw_dnld = container_of(work,
+ struct nfcmrvl_fw_dnld,
+ rx_work);
+ struct nfcmrvl_private *priv = container_of(fw_dnld,
+ struct nfcmrvl_private,
+ fw_dnld);
+
+ while ((skb = skb_dequeue(&fw_dnld->rx_q))) {
+ nfc_send_to_raw_sock(priv->ndev->nfc_dev, skb,
+ RAW_PAYLOAD_NCI, NFC_DIRECTION_RX);
+ switch (fw_dnld->state) {
+ case STATE_RESET:
+ ret = process_state_reset(priv, skb);
+ break;
+ case STATE_INIT:
+ ret = process_state_init(priv, skb);
+ break;
+ case STATE_SET_REF_CLOCK:
+ ret = process_state_set_ref_clock(priv, skb);
+ break;
+ case STATE_SET_HI_CONFIG:
+ ret = process_state_set_hi_config(priv, skb);
+ break;
+ case STATE_OPEN_LC:
+ ret = process_state_open_lc(priv, skb);
+ break;
+ case STATE_FW_DNLD:
+ ret = process_state_fw_dnld(priv, skb);
+ break;
+ case STATE_CLOSE_LC:
+ ret = process_state_close_lc(priv, skb);
+ break;
+ case STATE_BOOT:
+ ret = process_state_boot(priv, skb);
+ break;
+ default:
+ ret = -EFAULT;
+ }
+
+ kfree_skb(skb);
+
+ if (ret != 0) {
+ nfc_err(priv->dev, "FW loading error");
+ fw_dnld_over(priv, ret);
+ break;
+ }
+ }
+}
+
+int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv)
+{
+ char name[32];
+
+ INIT_WORK(&priv->fw_dnld.rx_work, fw_dnld_rx_work);
+ snprintf(name, sizeof(name), "%s_nfcmrvl_fw_dnld_rx_wq",
+ dev_name(priv->dev));
+ priv->fw_dnld.rx_wq = create_singlethread_workqueue(name);
+ if (!priv->fw_dnld.rx_wq)
+ return -ENOMEM;
+ skb_queue_head_init(&priv->fw_dnld.rx_q);
+ return 0;
+}
+
+void nfcmrvl_fw_dnld_deinit(struct nfcmrvl_private *priv)
+{
+ destroy_workqueue(priv->fw_dnld.rx_wq);
+}
+
+void nfcmrvl_fw_dnld_recv_frame(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ /* Discard command timer */
+ if (timer_pending(&priv->ndev->cmd_timer))
+ del_timer_sync(&priv->ndev->cmd_timer);
+
+ /* Allow next command */
+ atomic_set(&priv->ndev->cmd_cnt, 1);
+
+ /* Queue and trigger rx work */
+ skb_queue_tail(&priv->fw_dnld.rx_q, skb);
+ queue_work(priv->fw_dnld.rx_wq, &priv->fw_dnld.rx_work);
+}
+
+void nfcmrvl_fw_dnld_abort(struct nfcmrvl_private *priv)
+{
+ fw_dnld_over(priv, -EHOSTDOWN);
+}
+
+int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name)
+{
+ struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
+ struct nfcmrvl_fw_dnld *fw_dnld = &priv->fw_dnld;
+
+ if (!priv->support_fw_dnld)
+ return -ENOTSUPP;
+
+ if (!firmware_name || !firmware_name[0])
+ return -EINVAL;
+
+ strcpy(fw_dnld->name, firmware_name);
+
+ /*
+ * Retrieve FW binary file and parse it to initialize FW download
+ * state machine.
+ */
+
+ /* Retrieve FW binary */
+ if (request_firmware(&fw_dnld->fw, firmware_name, priv->dev) < 0) {
+ nfc_err(priv->dev, "failed to retrieve FW %s", firmware_name);
+ return -ENOENT;
+ }
+
+ fw_dnld->header = (const struct nfcmrvl_fw *) priv->fw_dnld.fw->data;
+
+ if (fw_dnld->header->magic != NFCMRVL_FW_MAGIC ||
+ fw_dnld->header->phy != priv->phy) {
+ nfc_err(priv->dev, "bad firmware binary %s magic=0x%x phy=%d",
+ firmware_name, fw_dnld->header->magic,
+ fw_dnld->header->phy);
+ release_firmware(fw_dnld->fw);
+ fw_dnld->header = NULL;
+ return -EINVAL;
+ }
+
+ if (fw_dnld->header->helper.offset != 0) {
+ nfc_info(priv->dev, "loading helper");
+ fw_dnld->binary_config = &fw_dnld->header->helper;
+ } else {
+ nfc_info(priv->dev, "loading firmware");
+ fw_dnld->binary_config = &fw_dnld->header->firmware;
+ }
+
+ /* Configure a timer for timeout */
+ setup_timer(&priv->fw_dnld.timer, fw_dnld_timeout,
+ (unsigned long) priv);
+ mod_timer(&priv->fw_dnld.timer,
+ jiffies + msecs_to_jiffies(FW_DNLD_TIMEOUT));
+
+ /* Ronfigure HI to be sure that it is the bootrom values */
+ priv->if_ops->nci_update_config(priv,
+ &fw_dnld->header->bootrom.config);
+
+ /* Allow first command */
+ atomic_set(&priv->ndev->cmd_cnt, 1);
+
+ /* First, reset the chip */
+ priv->fw_dnld.state = STATE_RESET;
+ nfcmrvl_chip_reset(priv);
+
+ /* Now wait for CORE_RESET_NTF or timeout */
+
+ return 0;
+}
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.h b/drivers/nfc/nfcmrvl/fw_dnld.h
new file mode 100644
index 000000000000..ee4a339c05fd
--- /dev/null
+++ b/drivers/nfc/nfcmrvl/fw_dnld.h
@@ -0,0 +1,98 @@
+/**
+ * Marvell NFC driver: Firmware downloader
+ *
+ * Copyright (C) 2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ **/
+
+#ifndef __NFCMRVL_FW_DNLD_H__
+#define __NFCMRVL_FW_DNLD_H__
+
+#include <linux/workqueue.h>
+
+#define NFCMRVL_FW_MAGIC 0x88888888
+
+#define NCI_OP_PROP_BOOT_CMD 0x3A
+
+#define NCI_CORE_LC_PROP_FW_DL 0xFD
+#define NCI_CORE_LC_CONNID_PROP_FW_DL 0x02
+
+#define HELPER_CMD_ENTRY_POINT 0x04
+#define HELPER_CMD_PACKET_FORMAT 0xA5
+#define HELPER_ACK_PACKET_FORMAT 0x5A
+#define HELPER_RETRY_REQUESTED (1 << 15)
+
+struct nfcmrvl_private;
+
+struct nfcmrvl_fw_uart_config {
+ uint8_t flow_control;
+ uint32_t baudrate;
+} __packed;
+
+struct nfcmrvl_fw_i2c_config {
+ uint32_t clk;
+} __packed;
+
+struct nfcmrvl_fw_spi_config {
+ uint32_t clk;
+} __packed;
+
+struct nfcmrvl_fw_binary_config {
+ uint32_t offset;
+ union {
+ void *config;
+ struct nfcmrvl_fw_uart_config uart;
+ struct nfcmrvl_fw_i2c_config i2c;
+ struct nfcmrvl_fw_spi_config spi;
+ uint8_t reserved[64];
+ };
+} __packed;
+
+struct nfcmrvl_fw {
+ uint32_t magic;
+ uint32_t ref_clock;
+ uint32_t phy;
+ struct nfcmrvl_fw_binary_config bootrom;
+ struct nfcmrvl_fw_binary_config helper;
+ struct nfcmrvl_fw_binary_config firmware;
+ uint8_t reserved[64];
+} __packed;
+
+struct nfcmrvl_fw_dnld {
+ char name[NFC_FIRMWARE_NAME_MAXSIZE + 1];
+ const struct firmware *fw;
+
+ const struct nfcmrvl_fw *header;
+ const struct nfcmrvl_fw_binary_config *binary_config;
+
+ int state;
+ int substate;
+ int offset;
+ int chunk_len;
+
+ struct workqueue_struct *rx_wq;
+ struct work_struct rx_work;
+ struct sk_buff_head rx_q;
+
+ struct timer_list timer;
+};
+
+int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv);
+void nfcmrvl_fw_dnld_deinit(struct nfcmrvl_private *priv);
+void nfcmrvl_fw_dnld_abort(struct nfcmrvl_private *priv);
+int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name);
+void nfcmrvl_fw_dnld_recv_frame(struct nfcmrvl_private *priv,
+ struct sk_buff *skb);
+
+#endif
diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
new file mode 100644
index 000000000000..78b7aa835c81
--- /dev/null
+++ b/drivers/nfc/nfcmrvl/i2c.c
@@ -0,0 +1,290 @@
+/**
+ * Marvell NFC-over-I2C driver: I2C interface related functions
+ *
+ * Copyright (C) 2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ **/
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/nfc.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include "nfcmrvl.h"
+
+struct nfcmrvl_i2c_drv_data {
+ unsigned long flags;
+ struct device *dev;
+ struct i2c_client *i2c;
+ struct nfcmrvl_private *priv;
+};
+
+static int nfcmrvl_i2c_read(struct nfcmrvl_i2c_drv_data *drv_data,
+ struct sk_buff **skb)
+{
+ int ret;
+ struct nci_ctrl_hdr nci_hdr;
+
+ /* Read NCI header to know the payload size */
+ ret = i2c_master_recv(drv_data->i2c, (u8 *)&nci_hdr, NCI_CTRL_HDR_SIZE);
+ if (ret != NCI_CTRL_HDR_SIZE) {
+ nfc_err(&drv_data->i2c->dev, "cannot read NCI header\n");
+ return -EBADMSG;
+ }
+
+ if (nci_hdr.plen > NCI_MAX_PAYLOAD_SIZE) {
+ nfc_err(&drv_data->i2c->dev, "invalid packet payload size\n");
+ return -EBADMSG;
+ }
+
+ *skb = nci_skb_alloc(drv_data->priv->ndev,
+ nci_hdr.plen + NCI_CTRL_HDR_SIZE, GFP_KERNEL);
+ if (!*skb)
+ return -ENOMEM;
+
+ /* Copy NCI header into the SKB */
+ memcpy(skb_put(*skb, NCI_CTRL_HDR_SIZE), &nci_hdr, NCI_CTRL_HDR_SIZE);
+
+ if (nci_hdr.plen) {
+ /* Read the NCI payload */
+ ret = i2c_master_recv(drv_data->i2c,
+ skb_put(*skb, nci_hdr.plen),
+ nci_hdr.plen);
+
+ if (ret != nci_hdr.plen) {
+ nfc_err(&drv_data->i2c->dev,
+ "Invalid frame payload length: %u (expected %u)\n",
+ ret, nci_hdr.plen);
+ kfree_skb(*skb);
+ return -EBADMSG;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t nfcmrvl_i2c_int_irq_thread_fn(int irq, void *drv_data_ptr)
+{
+ struct nfcmrvl_i2c_drv_data *drv_data = drv_data_ptr;
+ struct sk_buff *skb = NULL;
+ int ret;
+
+ if (!drv_data->priv)
+ return IRQ_HANDLED;
+
+ if (test_bit(NFCMRVL_PHY_ERROR, &drv_data->priv->flags))
+ return IRQ_HANDLED;
+
+ ret = nfcmrvl_i2c_read(drv_data, &skb);
+
+ switch (ret) {
+ case -EREMOTEIO:
+ set_bit(NFCMRVL_PHY_ERROR, &drv_data->priv->flags);
+ break;
+ case -ENOMEM:
+ case -EBADMSG:
+ nfc_err(&drv_data->i2c->dev, "read failed %d\n", ret);
+ break;
+ default:
+ if (nfcmrvl_nci_recv_frame(drv_data->priv, skb) < 0)
+ nfc_err(&drv_data->i2c->dev, "corrupted RX packet\n");
+ break;
+ }
+ return IRQ_HANDLED;
+}
+
+static int nfcmrvl_i2c_nci_open(struct nfcmrvl_private *priv)
+{
+ struct nfcmrvl_i2c_drv_data *drv_data = priv->drv_data;
+
+ if (!drv_data)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int nfcmrvl_i2c_nci_close(struct nfcmrvl_private *priv)
+{
+ return 0;
+}
+
+static int nfcmrvl_i2c_nci_send(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ struct nfcmrvl_i2c_drv_data *drv_data = priv->drv_data;
+ int ret;
+
+ if (test_bit(NFCMRVL_PHY_ERROR, &priv->flags))
+ return -EREMOTEIO;
+
+ ret = i2c_master_send(drv_data->i2c, skb->data, skb->len);
+
+ /* Retry if chip was in standby */
+ if (ret == -EREMOTEIO) {
+ nfc_info(drv_data->dev, "chip may sleep, retry\n");
+ usleep_range(6000, 10000);
+ ret = i2c_master_send(drv_data->i2c, skb->data, skb->len);
+ }
+
+ if (ret >= 0) {
+ if (ret != skb->len) {
+ nfc_err(drv_data->dev,
+ "Invalid length sent: %u (expected %u)\n",
+ ret, skb->len);
+ ret = -EREMOTEIO;
+ } else
+ ret = 0;
+ kfree_skb(skb);
+ }
+
+ return ret;
+}
+
+static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv,
+ const void *param)
+{
+}
+
+static struct nfcmrvl_if_ops i2c_ops = {
+ .nci_open = nfcmrvl_i2c_nci_open,
+ .nci_close = nfcmrvl_i2c_nci_close,
+ .nci_send = nfcmrvl_i2c_nci_send,
+ .nci_update_config = nfcmrvl_i2c_nci_update_config,
+};
+
+static int nfcmrvl_i2c_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata)
+{
+ int ret;
+
+ ret = nfcmrvl_parse_dt(node, pdata);
+ if (ret < 0) {
+ pr_err("Failed to get generic entries\n");
+ return ret;
+ }
+
+ if (of_find_property(node, "i2c-int-falling", NULL))
+ pdata->irq_polarity = IRQF_TRIGGER_FALLING;
+ else
+ pdata->irq_polarity = IRQF_TRIGGER_RISING;
+
+ ret = irq_of_parse_and_map(node, 0);
+ if (ret < 0) {
+ pr_err("Unable to get irq, error: %d\n", ret);
+ return ret;
+ }
+ pdata->irq = ret;
+
+ return 0;
+}
+
+static int nfcmrvl_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct nfcmrvl_i2c_drv_data *drv_data;
+ struct nfcmrvl_platform_data *pdata;
+ struct nfcmrvl_platform_data config;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
+ return -ENODEV;
+ }
+
+ drv_data = devm_kzalloc(&client->dev, sizeof(*drv_data), GFP_KERNEL);
+ if (!drv_data)
+ return -ENOMEM;
+
+ drv_data->i2c = client;
+ drv_data->dev = &client->dev;
+ drv_data->priv = NULL;
+
+ i2c_set_clientdata(client, drv_data);
+
+ pdata = client->dev.platform_data;
+
+ if (!pdata && client->dev.of_node)
+ if (nfcmrvl_i2c_parse_dt(client->dev.of_node, &config) == 0)
+ pdata = &config;
+
+ if (!pdata)
+ return -EINVAL;
+
+ /* Request the read IRQ */
+ ret = devm_request_threaded_irq(&drv_data->i2c->dev, pdata->irq,
+ NULL, nfcmrvl_i2c_int_irq_thread_fn,
+ pdata->irq_polarity | IRQF_ONESHOT,
+ "nfcmrvl_i2c_int", drv_data);
+ if (ret < 0) {
+ nfc_err(&drv_data->i2c->dev,
+ "Unable to register IRQ handler\n");
+ return ret;
+ }
+
+ drv_data->priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_I2C,
+ drv_data, &i2c_ops,
+ &drv_data->i2c->dev, pdata);
+
+ if (IS_ERR(drv_data->priv))
+ return PTR_ERR(drv_data->priv);
+
+ drv_data->priv->support_fw_dnld = true;
+
+ return 0;
+}
+
+static int nfcmrvl_i2c_remove(struct i2c_client *client)
+{
+ struct nfcmrvl_i2c_drv_data *drv_data = i2c_get_clientdata(client);
+
+ nfcmrvl_nci_unregister_dev(drv_data->priv);
+
+ return 0;
+}
+
+
+static const struct of_device_id of_nfcmrvl_i2c_match[] = {
+ { .compatible = "marvell,nfc-i2c", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_nfcmrvl_i2c_match);
+
+static struct i2c_device_id nfcmrvl_i2c_id_table[] = {
+ { "nfcmrvl_i2c", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, nfcmrvl_i2c_id_table);
+
+static struct i2c_driver nfcmrvl_i2c_driver = {
+ .probe = nfcmrvl_i2c_probe,
+ .id_table = nfcmrvl_i2c_id_table,
+ .remove = nfcmrvl_i2c_remove,
+ .driver = {
+ .name = "nfcmrvl_i2c",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_nfcmrvl_i2c_match),
+ },
+};
+
+module_i2c_driver(nfcmrvl_i2c_driver);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell NFC-over-I2C driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
index 4a8866d62941..51c8240a1672 100644
--- a/drivers/nfc/nfcmrvl/main.c
+++ b/drivers/nfc/nfcmrvl/main.c
@@ -1,7 +1,7 @@
/*
* Marvell NFC driver: major functions
*
- * Copyright (C) 2014, Marvell International Ltd.
+ * Copyright (C) 2014-2015 Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -25,8 +25,6 @@
#include <net/nfc/nci_core.h>
#include "nfcmrvl.h"
-#define VERSION "1.0"
-
static int nfcmrvl_nci_open(struct nci_dev *ndev)
{
struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
@@ -35,6 +33,9 @@ static int nfcmrvl_nci_open(struct nci_dev *ndev)
if (test_and_set_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
return 0;
+ /* Reset possible fault of previous session */
+ clear_bit(NFCMRVL_PHY_ERROR, &priv->flags);
+
err = priv->if_ops->nci_open(priv);
if (err)
@@ -63,9 +64,6 @@ static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
skb->dev = (void *)ndev;
- if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
- return -EBUSY;
-
if (priv->config.hci_muxed) {
unsigned char *hdr;
unsigned char len = skb->len;
@@ -88,21 +86,30 @@ static int nfcmrvl_nci_setup(struct nci_dev *ndev)
return 0;
}
+static int nfcmrvl_nci_fw_download(struct nci_dev *ndev,
+ const char *firmware_name)
+{
+ return nfcmrvl_fw_dnld_start(ndev, firmware_name);
+}
+
static struct nci_ops nfcmrvl_nci_ops = {
.open = nfcmrvl_nci_open,
.close = nfcmrvl_nci_close,
.send = nfcmrvl_nci_send,
.setup = nfcmrvl_nci_setup,
+ .fw_download = nfcmrvl_nci_fw_download,
};
-struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
+struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy,
+ void *drv_data,
struct nfcmrvl_if_ops *ops,
struct device *dev,
struct nfcmrvl_platform_data *pdata)
{
struct nfcmrvl_private *priv;
int rc;
- int headroom = 0;
+ int headroom;
+ int tailroom;
u32 protocols;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -112,6 +119,7 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
priv->drv_data = drv_data;
priv->if_ops = ops;
priv->dev = dev;
+ priv->phy = phy;
memcpy(&priv->config, pdata, sizeof(*pdata));
@@ -124,8 +132,14 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
nfc_err(dev, "failed to request reset_n io\n");
}
+ if (phy == NFCMRVL_PHY_SPI) {
+ headroom = NCI_SPI_HDR_LEN;
+ tailroom = 1;
+ } else
+ headroom = tailroom = 0;
+
if (priv->config.hci_muxed)
- headroom = NFCMRVL_HCI_EVENT_HEADER_SIZE;
+ headroom += NFCMRVL_HCI_EVENT_HEADER_SIZE;
protocols = NFC_PROTO_JEWEL_MASK
| NFC_PROTO_MIFARE_MASK
@@ -136,7 +150,7 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
| NFC_PROTO_NFC_DEP_MASK;
priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols,
- headroom, 0);
+ headroom, tailroom);
if (!priv->ndev) {
nfc_err(dev, "nci_allocate_device failed\n");
rc = -ENOMEM;
@@ -145,18 +159,26 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
nci_set_drvdata(priv->ndev, priv);
- nfcmrvl_chip_reset(priv);
-
rc = nci_register_device(priv->ndev);
if (rc) {
nfc_err(dev, "nci_register_device failed %d\n", rc);
- nci_free_device(priv->ndev);
- goto error;
+ goto error_free_dev;
+ }
+
+ /* Ensure that controller is powered off */
+ nfcmrvl_chip_halt(priv);
+
+ rc = nfcmrvl_fw_dnld_init(priv);
+ if (rc) {
+ nfc_err(dev, "failed to initialize FW download %d\n", rc);
+ goto error_free_dev;
}
nfc_info(dev, "registered with nci successfully\n");
return priv;
+error_free_dev:
+ nci_free_device(priv->ndev);
error:
kfree(priv);
return ERR_PTR(rc);
@@ -167,6 +189,14 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
{
struct nci_dev *ndev = priv->ndev;
+ if (priv->ndev->nfc_dev->fw_download_in_progress)
+ nfcmrvl_fw_dnld_abort(priv);
+
+ nfcmrvl_fw_dnld_deinit(priv);
+
+ if (priv->config.reset_n_io)
+ devm_gpio_free(priv->dev, priv->config.reset_n_io);
+
nci_unregister_device(ndev);
nci_free_device(ndev);
kfree(priv);
@@ -187,6 +217,11 @@ int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, struct sk_buff *skb)
}
}
+ if (priv->ndev->nfc_dev->fw_download_in_progress) {
+ nfcmrvl_fw_dnld_recv_frame(priv, skb);
+ return 0;
+ }
+
if (test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
nci_recv_frame(priv->ndev, skb);
else {
@@ -201,10 +236,8 @@ EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame);
void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
{
- /*
- * This function does not take care if someone is using the device.
- * To be improved.
- */
+ /* Reset possible fault of previous session */
+ clear_bit(NFCMRVL_PHY_ERROR, &priv->flags);
if (priv->config.reset_n_io) {
nfc_info(priv->dev, "reset the chip\n");
@@ -215,7 +248,11 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
nfc_info(priv->dev, "no reset available on this interface\n");
}
-#ifdef CONFIG_OF
+void nfcmrvl_chip_halt(struct nfcmrvl_private *priv)
+{
+ if (priv->config.reset_n_io)
+ gpio_set_value(priv->config.reset_n_io, 0);
+}
int nfcmrvl_parse_dt(struct device_node *node,
struct nfcmrvl_platform_data *pdata)
@@ -239,19 +276,8 @@ int nfcmrvl_parse_dt(struct device_node *node,
return 0;
}
-
-#else
-
-int nfcmrvl_parse_dt(struct device_node *node,
- struct nfcmrvl_platform_data *pdata)
-{
- return -ENODEV;
-}
-
-#endif
EXPORT_SYMBOL_GPL(nfcmrvl_parse_dt);
MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell NFC driver ver " VERSION);
-MODULE_VERSION(VERSION);
+MODULE_DESCRIPTION("Marvell NFC driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/nfc/nfcmrvl/nfcmrvl.h b/drivers/nfc/nfcmrvl/nfcmrvl.h
index e5a7e5464f2e..de68ff45e49a 100644
--- a/drivers/nfc/nfcmrvl/nfcmrvl.h
+++ b/drivers/nfc/nfcmrvl/nfcmrvl.h
@@ -1,7 +1,7 @@
/**
* Marvell NFC driver
*
- * Copyright (C) 2014, Marvell International Ltd.
+ * Copyright (C) 2014-2015, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -21,8 +21,11 @@
#include <linux/platform_data/nfcmrvl.h>
+#include "fw_dnld.h"
+
/* Define private flags: */
#define NFCMRVL_NCI_RUNNING 1
+#define NFCMRVL_PHY_ERROR 2
#define NFCMRVL_EXT_COEX_ID 0xE0
#define NFCMRVL_NOT_ALLOWED_ID 0xE1
@@ -37,6 +40,8 @@
*/
#define NFCMRVL_PB_BAIL_OUT 0x11
+#define NFCMRVL_PROP_REF_CLOCK 0xF0
+#define NFCMRVL_PROP_SET_HI_CONFIG 0xF1
/*
** HCI defines
@@ -52,9 +57,10 @@
enum nfcmrvl_phy {
NFCMRVL_PHY_USB = 0,
NFCMRVL_PHY_UART = 1,
+ NFCMRVL_PHY_I2C = 2,
+ NFCMRVL_PHY_SPI = 3,
};
-
struct nfcmrvl_private {
unsigned long flags;
@@ -62,8 +68,15 @@ struct nfcmrvl_private {
/* Platform configuration */
struct nfcmrvl_platform_data config;
+ /* Parent dev */
struct nci_dev *ndev;
+ /* FW download context */
+ struct nfcmrvl_fw_dnld fw_dnld;
+
+ /* FW download support */
+ bool support_fw_dnld;
+
/*
** PHY related information
*/
@@ -82,17 +95,21 @@ struct nfcmrvl_if_ops {
int (*nci_open) (struct nfcmrvl_private *priv);
int (*nci_close) (struct nfcmrvl_private *priv);
int (*nci_send) (struct nfcmrvl_private *priv, struct sk_buff *skb);
+ void (*nci_update_config)(struct nfcmrvl_private *priv,
+ const void *param);
};
void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv);
int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, struct sk_buff *skb);
-struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
+struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy,
+ void *drv_data,
struct nfcmrvl_if_ops *ops,
struct device *dev,
struct nfcmrvl_platform_data *pdata);
void nfcmrvl_chip_reset(struct nfcmrvl_private *priv);
+void nfcmrvl_chip_halt(struct nfcmrvl_private *priv);
int nfcmrvl_parse_dt(struct device_node *node,
struct nfcmrvl_platform_data *pdata);
diff --git a/drivers/nfc/nfcmrvl/spi.c b/drivers/nfc/nfcmrvl/spi.c
new file mode 100644
index 000000000000..a7faa0bcc01e
--- /dev/null
+++ b/drivers/nfc/nfcmrvl/spi.c
@@ -0,0 +1,228 @@
+/**
+ * Marvell NFC-over-SPI driver: SPI interface related functions
+ *
+ * Copyright (C) 2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ **/
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/nfc.h>
+#include <linux/gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include "nfcmrvl.h"
+
+#define SPI_WAIT_HANDSHAKE 1
+
+struct nfcmrvl_spi_drv_data {
+ unsigned long flags;
+ struct spi_device *spi;
+ struct nci_spi *nci_spi;
+ struct completion handshake_completion;
+ struct nfcmrvl_private *priv;
+};
+
+static irqreturn_t nfcmrvl_spi_int_irq_thread_fn(int irq, void *drv_data_ptr)
+{
+ struct nfcmrvl_spi_drv_data *drv_data = drv_data_ptr;
+ struct sk_buff *skb;
+
+ /*
+ * Special case where we are waiting for SPI_INT deassertion to start a
+ * transfer.
+ */
+ if (test_and_clear_bit(SPI_WAIT_HANDSHAKE, &drv_data->flags)) {
+ complete(&drv_data->handshake_completion);
+ return IRQ_HANDLED;
+ }
+
+ /* Normal case, SPI_INT deasserted by slave to trigger a master read */
+
+ skb = nci_spi_read(drv_data->nci_spi);
+ if (!skb) {
+ nfc_err(&drv_data->spi->dev, "failed to read spi packet");
+ return IRQ_HANDLED;
+ }
+
+ if (nfcmrvl_nci_recv_frame(drv_data->priv, skb) < 0)
+ nfc_err(&drv_data->spi->dev, "corrupted RX packet");
+
+ return IRQ_HANDLED;
+}
+
+static int nfcmrvl_spi_nci_open(struct nfcmrvl_private *priv)
+{
+ return 0;
+}
+
+static int nfcmrvl_spi_nci_close(struct nfcmrvl_private *priv)
+{
+ return 0;
+}
+
+static int nfcmrvl_spi_nci_send(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ struct nfcmrvl_spi_drv_data *drv_data = priv->drv_data;
+ int err;
+
+ /* Reinit completion for slave handshake */
+ reinit_completion(&drv_data->handshake_completion);
+ set_bit(SPI_WAIT_HANDSHAKE, &drv_data->flags);
+
+ /*
+ * Append a dummy byte at the end of SPI frame. This is due to a
+ * specific DMA implementation in the controller
+ */
+ skb_put(skb, 1);
+
+ /* Send the SPI packet */
+ err = nci_spi_send(drv_data->nci_spi, &drv_data->handshake_completion,
+ skb);
+ if (err != 0) {
+ nfc_err(priv->dev, "spi_send failed %d", err);
+ kfree_skb(skb);
+ }
+ return err;
+}
+
+static void nfcmrvl_spi_nci_update_config(struct nfcmrvl_private *priv,
+ const void *param)
+{
+ struct nfcmrvl_spi_drv_data *drv_data = priv->drv_data;
+ const struct nfcmrvl_fw_spi_config *config = param;
+
+ drv_data->nci_spi->xfer_speed_hz = config->clk;
+}
+
+static struct nfcmrvl_if_ops spi_ops = {
+ .nci_open = nfcmrvl_spi_nci_open,
+ .nci_close = nfcmrvl_spi_nci_close,
+ .nci_send = nfcmrvl_spi_nci_send,
+ .nci_update_config = nfcmrvl_spi_nci_update_config,
+};
+
+static int nfcmrvl_spi_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata)
+{
+ int ret;
+
+ ret = nfcmrvl_parse_dt(node, pdata);
+ if (ret < 0) {
+ pr_err("Failed to get generic entries\n");
+ return ret;
+ }
+
+ ret = irq_of_parse_and_map(node, 0);
+ if (ret < 0) {
+ pr_err("Unable to get irq, error: %d\n", ret);
+ return ret;
+ }
+ pdata->irq = ret;
+
+ return 0;
+}
+
+static int nfcmrvl_spi_probe(struct spi_device *spi)
+{
+ struct nfcmrvl_platform_data *pdata;
+ struct nfcmrvl_platform_data config;
+ struct nfcmrvl_spi_drv_data *drv_data;
+ int ret = 0;
+
+ drv_data = devm_kzalloc(&spi->dev, sizeof(*drv_data), GFP_KERNEL);
+ if (!drv_data)
+ return -ENOMEM;
+
+ drv_data->spi = spi;
+ drv_data->priv = NULL;
+ spi_set_drvdata(spi, drv_data);
+
+ pdata = spi->dev.platform_data;
+
+ if (!pdata && spi->dev.of_node)
+ if (nfcmrvl_spi_parse_dt(spi->dev.of_node, &config) == 0)
+ pdata = &config;
+
+ if (!pdata)
+ return -EINVAL;
+
+ ret = devm_request_threaded_irq(&drv_data->spi->dev, pdata->irq,
+ NULL, nfcmrvl_spi_int_irq_thread_fn,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "nfcmrvl_spi_int", drv_data);
+ if (ret < 0) {
+ nfc_err(&drv_data->spi->dev, "Unable to register IRQ handler");
+ return -ENODEV;
+ }
+
+ drv_data->priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_SPI,
+ drv_data, &spi_ops,
+ &drv_data->spi->dev,
+ pdata);
+ if (IS_ERR(drv_data->priv))
+ return PTR_ERR(drv_data->priv);
+
+ drv_data->priv->support_fw_dnld = true;
+
+ drv_data->nci_spi = nci_spi_allocate_spi(drv_data->spi, 0, 10,
+ drv_data->priv->ndev);
+
+ /* Init completion for slave handshake */
+ init_completion(&drv_data->handshake_completion);
+ return 0;
+}
+
+static int nfcmrvl_spi_remove(struct spi_device *spi)
+{
+ struct nfcmrvl_spi_drv_data *drv_data = spi_get_drvdata(spi);
+
+ nfcmrvl_nci_unregister_dev(drv_data->priv);
+ return 0;
+}
+
+static const struct of_device_id of_nfcmrvl_spi_match[] = {
+ { .compatible = "marvell,nfc-spi", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_nfcmrvl_spi_match);
+
+static const struct spi_device_id nfcmrvl_spi_id_table[] = {
+ { "nfcmrvl_spi", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, nfcmrvl_spi_id_table);
+
+static struct spi_driver nfcmrvl_spi_driver = {
+ .probe = nfcmrvl_spi_probe,
+ .remove = nfcmrvl_spi_remove,
+ .id_table = nfcmrvl_spi_id_table,
+ .driver = {
+ .name = "nfcmrvl_spi",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_nfcmrvl_spi_match),
+ },
+};
+
+module_spi_driver(nfcmrvl_spi_driver);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell NFC-over-SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c
index 61442d6528a6..83a99e38e7bd 100644
--- a/drivers/nfc/nfcmrvl/uart.c
+++ b/drivers/nfc/nfcmrvl/uart.c
@@ -50,23 +50,36 @@ static int nfcmrvl_uart_nci_send(struct nfcmrvl_private *priv,
return nu->ops.send(nu, skb);
}
+static void nfcmrvl_uart_nci_update_config(struct nfcmrvl_private *priv,
+ const void *param)
+{
+ struct nci_uart *nu = priv->drv_data;
+ const struct nfcmrvl_fw_uart_config *config = param;
+
+ nci_uart_set_config(nu, le32_to_cpu(config->baudrate),
+ config->flow_control);
+}
+
static struct nfcmrvl_if_ops uart_ops = {
.nci_open = nfcmrvl_uart_nci_open,
.nci_close = nfcmrvl_uart_nci_close,
.nci_send = nfcmrvl_uart_nci_send,
+ .nci_update_config = nfcmrvl_uart_nci_update_config
};
-#ifdef CONFIG_OF
-
static int nfcmrvl_uart_parse_dt(struct device_node *node,
struct nfcmrvl_platform_data *pdata)
{
struct device_node *matched_node;
int ret;
- matched_node = of_find_compatible_node(node, NULL, "mrvl,nfc-uart");
- if (!matched_node)
- return -ENODEV;
+ matched_node = of_find_compatible_node(node, NULL, "marvell,nfc-uart");
+ if (!matched_node) {
+ matched_node = of_find_compatible_node(node, NULL,
+ "mrvl,nfc-uart");
+ if (!matched_node)
+ return -ENODEV;
+ }
ret = nfcmrvl_parse_dt(matched_node, pdata);
if (ret < 0) {
@@ -87,16 +100,6 @@ static int nfcmrvl_uart_parse_dt(struct device_node *node,
return 0;
}
-#else
-
-static int nfcmrvl_uart_parse_dt(struct device_node *node,
- struct nfcmrvl_platform_data *pdata)
-{
- return -ENODEV;
-}
-
-#endif
-
/*
** NCI UART OPS
*/
@@ -127,19 +130,16 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu)
pdata = &config;
}
- priv = nfcmrvl_nci_register_dev(nu, &uart_ops, nu->tty->dev, pdata);
+ priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_UART, nu, &uart_ops,
+ nu->tty->dev, pdata);
if (IS_ERR(priv))
return PTR_ERR(priv);
- priv->phy = NFCMRVL_PHY_UART;
+ priv->support_fw_dnld = true;
nu->drv_data = priv;
nu->ndev = priv->ndev;
- /* Set BREAK */
- if (priv->config.break_control && nu->tty->ops->break_ctl)
- nu->tty->ops->break_ctl(nu->tty, -1);
-
return 0;
}
@@ -158,6 +158,9 @@ static void nfcmrvl_nci_uart_tx_start(struct nci_uart *nu)
{
struct nfcmrvl_private *priv = (struct nfcmrvl_private *)nu->drv_data;
+ if (priv->ndev->nfc_dev->fw_download_in_progress)
+ return;
+
/* Remove BREAK to wake up the NFCC */
if (priv->config.break_control && nu->tty->ops->break_ctl) {
nu->tty->ops->break_ctl(nu->tty, 0);
@@ -169,13 +172,18 @@ static void nfcmrvl_nci_uart_tx_done(struct nci_uart *nu)
{
struct nfcmrvl_private *priv = (struct nfcmrvl_private *)nu->drv_data;
+ if (priv->ndev->nfc_dev->fw_download_in_progress)
+ return;
+
/*
** To ensure that if the NFCC goes in DEEP SLEEP sate we can wake him
** up. we set BREAK. Once we will be ready to send again we will remove
** it.
*/
- if (priv->config.break_control && nu->tty->ops->break_ctl)
+ if (priv->config.break_control && nu->tty->ops->break_ctl) {
nu->tty->ops->break_ctl(nu->tty, -1);
+ usleep_range(1000, 3000);
+ }
}
static struct nci_uart nfcmrvl_nci_uart = {
diff --git a/drivers/nfc/nfcmrvl/usb.c b/drivers/nfc/nfcmrvl/usb.c
index 7d1fe436c9f6..585a0f20835b 100644
--- a/drivers/nfc/nfcmrvl/usb.c
+++ b/drivers/nfc/nfcmrvl/usb.c
@@ -23,8 +23,6 @@
#include <net/nfc/nci_core.h>
#include "nfcmrvl.h"
-#define VERSION "1.0"
-
static struct usb_device_id nfcmrvl_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x1286, 0x2046,
USB_CLASS_VENDOR_SPEC, 4, 1) },
@@ -342,13 +340,14 @@ static int nfcmrvl_probe(struct usb_interface *intf,
init_usb_anchor(&drv_data->bulk_anchor);
init_usb_anchor(&drv_data->deferred);
- priv = nfcmrvl_nci_register_dev(drv_data, &usb_ops,
+ priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_USB, drv_data, &usb_ops,
&drv_data->udev->dev, &config);
if (IS_ERR(priv))
return PTR_ERR(priv);
drv_data->priv = priv;
- drv_data->priv->phy = NFCMRVL_PHY_USB;
+ drv_data->priv->support_fw_dnld = false;
+
priv->dev = &drv_data->udev->dev;
usb_set_intfdata(intf, drv_data);
@@ -469,6 +468,5 @@ static struct usb_driver nfcmrvl_usb_driver = {
module_usb_driver(nfcmrvl_usb_driver);
MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell NFC-over-USB driver ver " VERSION);
-MODULE_VERSION(VERSION);
+MODULE_DESCRIPTION("Marvell NFC-over-USB driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c
index 93111fa8d282..26ac9e5fa1ab 100644
--- a/drivers/nfc/nfcsim.c
+++ b/drivers/nfc/nfcsim.c
@@ -246,7 +246,7 @@ static int nfcsim_activate_target(struct nfc_dev *nfc_dev,
}
static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev,
- struct nfc_target *target)
+ struct nfc_target *target, u8 mode)
{
struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
index ce2e2cf54fbc..f81e500e7650 100644
--- a/drivers/nfc/nfcwilink.c
+++ b/drivers/nfc/nfcwilink.c
@@ -497,7 +497,7 @@ static struct nci_ops nfcwilink_ops = {
static int nfcwilink_probe(struct platform_device *pdev)
{
- static struct nfcwilink *drv;
+ struct nfcwilink *drv;
int rc;
__u32 protocols;
diff --git a/drivers/nfc/nxp-nci/core.c b/drivers/nfc/nxp-nci/core.c
index 8979636d48ea..2e4b004a96aa 100644
--- a/drivers/nfc/nxp-nci/core.c
+++ b/drivers/nfc/nxp-nci/core.c
@@ -109,7 +109,8 @@ static struct nci_ops nxp_nci_ops = {
};
int nxp_nci_probe(void *phy_id, struct device *pdev,
- struct nxp_nci_phy_ops *phy_ops, unsigned int max_payload,
+ const struct nxp_nci_phy_ops *phy_ops,
+ unsigned int max_payload,
struct nci_dev **ndev)
{
struct nxp_nci_info *info;
diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
index fac80c691914..df4333c7ee0f 100644
--- a/drivers/nfc/nxp-nci/i2c.c
+++ b/drivers/nfc/nxp-nci/i2c.c
@@ -106,7 +106,7 @@ static int nxp_nci_i2c_write(void *phy_id, struct sk_buff *skb)
return r;
}
-static struct nxp_nci_phy_ops i2c_phy_ops = {
+static const struct nxp_nci_phy_ops i2c_phy_ops = {
.set_mode = nxp_nci_i2c_set_mode,
.write = nxp_nci_i2c_write,
};
diff --git a/drivers/nfc/nxp-nci/nxp-nci.h b/drivers/nfc/nxp-nci/nxp-nci.h
index f1fecc4e2457..20408cbff4f1 100644
--- a/drivers/nfc/nxp-nci/nxp-nci.h
+++ b/drivers/nfc/nxp-nci/nxp-nci.h
@@ -68,7 +68,7 @@ struct nxp_nci_info {
enum nxp_nci_mode mode;
- struct nxp_nci_phy_ops *phy_ops;
+ const struct nxp_nci_phy_ops *phy_ops;
unsigned int max_payload;
struct mutex info_lock;
@@ -82,7 +82,8 @@ void nxp_nci_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
void nxp_nci_fw_work_complete(struct nxp_nci_info *info, int result);
int nxp_nci_probe(void *phy_id, struct device *pdev,
- struct nxp_nci_phy_ops *phy_ops, unsigned int max_payload,
+ const struct nxp_nci_phy_ops *phy_ops,
+ unsigned int max_payload,
struct nci_dev **ndev);
void nxp_nci_remove(struct nci_dev *ndev);
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index a03e4eb5fe29..bb3d5ea9869c 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -2263,7 +2263,7 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev,
}
static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
- struct nfc_target *target)
+ struct nfc_target *target, u8 mode)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
struct sk_buff *skb;
diff --git a/drivers/nfc/pn544/Kconfig b/drivers/nfc/pn544/Kconfig
index ccf06f5f6ebb..2b8bde39540d 100644
--- a/drivers/nfc/pn544/Kconfig
+++ b/drivers/nfc/pn544/Kconfig
@@ -1,20 +1,15 @@
config NFC_PN544
- tristate "NXP PN544 NFC driver"
- depends on NFC_HCI
+ tristate
select CRC_CCITT
- default n
---help---
NXP PN544 core driver.
This is a driver based on the HCI NFC kernel layers and
will thus not work with NXP libnfc library.
- To compile this driver as a module, choose m here. The module will
- be called pn544.
- Say N if unsure.
-
config NFC_PN544_I2C
- tristate "NFC PN544 i2c support"
- depends on NFC_PN544 && I2C && NFC_SHDLC
+ tristate "NXP PN544 device support (I2C)"
+ depends on NFC_HCI && I2C && NFC_SHDLC
+ select NFC_PN544
---help---
This module adds support for the NXP pn544 i2c interface.
Select this if your platform is using the i2c bus.
@@ -23,8 +18,9 @@ config NFC_PN544_I2C
Say N if unsure.
config NFC_PN544_MEI
- tristate "NFC PN544 MEI support"
- depends on NFC_PN544 && NFC_MEI_PHY
+ tristate "NXP PN544 device support (MEI)"
+ depends on NFC_HCI && NFC_MEI_PHY
+ select NFC_PN544
---help---
This module adds support for the mei interface of adapters using
NXP pn544 chipsets. Select this if your pn544 chipset
diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c
index 101a37e12efa..46d0eb24eef9 100644
--- a/drivers/nfc/pn544/mei.c
+++ b/drivers/nfc/pn544/mei.c
@@ -27,7 +27,7 @@
#define PN544_DRIVER_NAME "pn544"
-static int pn544_mei_probe(struct mei_cl_device *device,
+static int pn544_mei_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
{
struct nfc_mei_phy *phy;
@@ -35,7 +35,7 @@ static int pn544_mei_probe(struct mei_cl_device *device,
pr_info("Probing NFC pn544\n");
- phy = nfc_mei_phy_alloc(device);
+ phy = nfc_mei_phy_alloc(cldev);
if (!phy) {
pr_err("Cannot allocate memory for pn544 mei phy.\n");
return -ENOMEM;
@@ -53,9 +53,9 @@ static int pn544_mei_probe(struct mei_cl_device *device,
return 0;
}
-static int pn544_mei_remove(struct mei_cl_device *device)
+static int pn544_mei_remove(struct mei_cl_device *cldev)
{
- struct nfc_mei_phy *phy = mei_cl_get_drvdata(device);
+ struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
pr_info("Removing pn544\n");
@@ -67,7 +67,7 @@ static int pn544_mei_remove(struct mei_cl_device *device)
}
static struct mei_cl_device_id pn544_mei_tbl[] = {
- { PN544_DRIVER_NAME, MEI_NFC_UUID},
+ { PN544_DRIVER_NAME, MEI_NFC_UUID, MEI_CL_VERSION_ANY},
/* required last entry */
{ }
@@ -88,7 +88,7 @@ static int pn544_mei_init(void)
pr_debug(DRIVER_DESC ": %s\n", __func__);
- r = mei_cl_driver_register(&pn544_driver);
+ r = mei_cldev_driver_register(&pn544_driver);
if (r) {
pr_err(PN544_DRIVER_NAME ": driver registration failed\n");
return r;
@@ -99,7 +99,7 @@ static int pn544_mei_init(void)
static void pn544_mei_exit(void)
{
- mei_cl_driver_unregister(&pn544_driver);
+ mei_cldev_driver_unregister(&pn544_driver);
}
module_init(pn544_mei_init);
diff --git a/drivers/nfc/s3fwrn5/Kconfig b/drivers/nfc/s3fwrn5/Kconfig
index 7e3b255b3f99..1eef9199486e 100644
--- a/drivers/nfc/s3fwrn5/Kconfig
+++ b/drivers/nfc/s3fwrn5/Kconfig
@@ -1,5 +1,6 @@
config NFC_S3FWRN5
tristate
+ select CRYPTO
---help---
Core driver for Samsung S3FWRN5 NFC chip. Contains core utilities
of chip. It's intended to be used by PHYs to avoid duplicating lots
diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index 3381c34faf62..ddfa7be7dd05 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -7,5 +7,3 @@ s3fwrn5_i2c-objs = i2c.o
obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
-
-ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index b4dd7dd47473..c61d8a308da4 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -258,7 +258,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- ret = request_threaded_irq(phy->i2c_dev->irq, NULL,
+ ret = devm_request_threaded_irq(&client->dev, phy->i2c_dev->irq, NULL,
s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
S3FWRN5_I2C_DRIVER_NAME, phy);
if (ret)
diff --git a/drivers/nfc/s3fwrn5/nci.c b/drivers/nfc/s3fwrn5/nci.c
index ace0071c5339..075e4e877b33 100644
--- a/drivers/nfc/s3fwrn5/nci.c
+++ b/drivers/nfc/s3fwrn5/nci.c
@@ -31,7 +31,7 @@ static int s3fwrn5_nci_prop_rsp(struct nci_dev *ndev, struct sk_buff *skb)
return 0;
}
-static struct nci_prop_ops s3fwrn5_nci_prop_ops[] = {
+static struct nci_driver_ops s3fwrn5_nci_prop_ops[] = {
{
.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
NCI_PROP_AGAIN),
@@ -79,7 +79,7 @@ static struct nci_prop_ops s3fwrn5_nci_prop_ops[] = {
},
};
-void s3fwrn5_nci_get_prop_ops(struct nci_prop_ops **ops, size_t *n)
+void s3fwrn5_nci_get_prop_ops(struct nci_driver_ops **ops, size_t *n)
{
*ops = s3fwrn5_nci_prop_ops;
*n = ARRAY_SIZE(s3fwrn5_nci_prop_ops);
diff --git a/drivers/nfc/s3fwrn5/nci.h b/drivers/nfc/s3fwrn5/nci.h
index 0e68d439dde6..60c7fb575b66 100644
--- a/drivers/nfc/s3fwrn5/nci.h
+++ b/drivers/nfc/s3fwrn5/nci.h
@@ -83,7 +83,7 @@ struct nci_prop_fw_cfg_rsp {
#define NCI_PROP_WR_RESET 0x2f
-void s3fwrn5_nci_get_prop_ops(struct nci_prop_ops **ops, size_t *n);
+void s3fwrn5_nci_get_prop_ops(struct nci_driver_ops **ops, size_t *n);
int s3fwrn5_nci_rf_configure(struct s3fwrn5_info *info, const char *fw_name);
#endif /* __LOCAL_S3FWRN5_NCI_H_ */
diff --git a/drivers/nfc/st-nci/Makefile b/drivers/nfc/st-nci/Makefile
index 348ce76f2177..439b2fa8654a 100644
--- a/drivers/nfc/st-nci/Makefile
+++ b/drivers/nfc/st-nci/Makefile
@@ -1,8 +1,8 @@
#
-# Makefile for ST21NFCB NCI based NFC driver
+# Makefile for ST_NCI NCI based NFC driver
#
-st-nci-objs = ndlc.o core.o st-nci_se.o
+st-nci-objs = ndlc.o core.o se.o vendor_cmds.o
obj-$(CONFIG_NFC_ST_NCI) += st-nci.o
st-nci_i2c-objs = i2c.o
diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
index c419d3943973..c693128ee6fb 100644
--- a/drivers/nfc/st-nci/core.c
+++ b/drivers/nfc/st-nci/core.c
@@ -24,7 +24,6 @@
#include <linux/delay.h>
#include "st-nci.h"
-#include "st-nci_se.h"
#define DRIVER_DESC "NCI NFC driver for ST_NCI"
@@ -98,7 +97,7 @@ static int st_nci_prop_rsp_packet(struct nci_dev *ndev,
return 0;
}
-static struct nci_prop_ops st_nci_prop_ops[] = {
+static struct nci_driver_ops st_nci_prop_ops[] = {
{
.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
ST_NCI_CORE_PROP),
@@ -124,7 +123,7 @@ static struct nci_ops st_nci_ops = {
};
int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
- int phy_tailroom)
+ int phy_tailroom, struct st_nci_se_status *se_status)
{
struct st_nci_info *info;
int r;
@@ -153,14 +152,23 @@ int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
nci_set_drvdata(ndlc->ndev, info);
+ r = st_nci_vendor_cmds_init(ndlc->ndev);
+ if (r) {
+ pr_err("Cannot register proprietary vendor cmds\n");
+ goto err_reg_dev;
+ }
+
r = nci_register_device(ndlc->ndev);
if (r) {
pr_err("Cannot register nfc device to nci core\n");
- nci_free_device(ndlc->ndev);
- return r;
+ goto err_reg_dev;
}
- return st_nci_se_init(ndlc->ndev);
+ return st_nci_se_init(ndlc->ndev, se_status);
+
+err_reg_dev:
+ nci_free_device(ndlc->ndev);
+ return r;
}
EXPORT_SYMBOL_GPL(st_nci_probe);
diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 707ed2eb5936..15e3ce2d274c 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -27,12 +27,12 @@
#include <linux/nfc.h>
#include <linux/platform_data/st-nci.h>
-#include "ndlc.h"
+#include "st-nci.h"
#define DRIVER_DESC "NCI NFC driver for ST_NCI"
/* ndlc header */
-#define ST_NCI_FRAME_HEADROOM 1
+#define ST_NCI_FRAME_HEADROOM 1
#define ST_NCI_FRAME_TAILROOM 0
#define ST_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
@@ -50,16 +50,13 @@ struct st_nci_i2c_phy {
struct i2c_client *i2c_dev;
struct llt_ndlc *ndlc;
+ bool irq_active;
+
unsigned int gpio_reset;
unsigned int irq_polarity;
-};
-#define I2C_DUMP_SKB(info, skb) \
-do { \
- pr_debug("%s:\n", info); \
- print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \
- 16, 1, (skb)->data, (skb)->len, 0); \
-} while (0)
+ struct st_nci_se_status se_status;
+};
static int st_nci_i2c_enable(void *phy_id)
{
@@ -70,8 +67,10 @@ static int st_nci_i2c_enable(void *phy_id)
gpio_set_value(phy->gpio_reset, 1);
usleep_range(80000, 85000);
- if (phy->ndlc->powered == 0)
+ if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
enable_irq(phy->i2c_dev->irq);
+ phy->irq_active = true;
+ }
return 0;
}
@@ -81,6 +80,7 @@ static void st_nci_i2c_disable(void *phy_id)
struct st_nci_i2c_phy *phy = phy_id;
disable_irq_nosync(phy->i2c_dev->irq);
+ phy->irq_active = false;
}
/*
@@ -94,8 +94,6 @@ static int st_nci_i2c_write(void *phy_id, struct sk_buff *skb)
struct st_nci_i2c_phy *phy = phy_id;
struct i2c_client *client = phy->i2c_dev;
- I2C_DUMP_SKB("st_nci_i2c_write", skb);
-
if (phy->ndlc->hard_fault != 0)
return phy->ndlc->hard_fault;
@@ -166,8 +164,6 @@ static int st_nci_i2c_read(struct st_nci_i2c_phy *phy,
skb_put(*skb, len);
memcpy((*skb)->data + ST_NCI_I2C_MIN_SIZE, buf, len);
- I2C_DUMP_SKB("i2c frame read", *skb);
-
return 0;
}
@@ -245,6 +241,11 @@ static int st_nci_i2c_of_request_resources(struct i2c_client *client)
phy->irq_polarity = irq_get_trigger_type(client->irq);
+ phy->se_status.is_ese_present =
+ of_property_read_bool(pp, "ese-present");
+ phy->se_status.is_uicc_present =
+ of_property_read_bool(pp, "uicc-present");
+
return 0;
}
#else
@@ -277,6 +278,9 @@ static int st_nci_i2c_request_resources(struct i2c_client *client)
return r;
}
+ phy->se_status.is_ese_present = pdata->is_ese_present;
+ phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
return 0;
}
@@ -326,12 +330,13 @@ static int st_nci_i2c_probe(struct i2c_client *client,
r = ndlc_probe(phy, &i2c_phy_ops, &client->dev,
ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
- &phy->ndlc);
+ &phy->ndlc, &phy->se_status);
if (r < 0) {
nfc_err(&client->dev, "Unable to register ndlc layer\n");
return r;
}
+ phy->irq_active = true;
r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
st_nci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT,
diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c
index d2cf84e680c6..0884b11001ef 100644
--- a/drivers/nfc/st-nci/ndlc.c
+++ b/drivers/nfc/st-nci/ndlc.c
@@ -19,8 +19,8 @@
#include <linux/sched.h>
#include <net/nfc/nci_core.h>
-#include "ndlc.h"
#include "st-nci.h"
+#include "ndlc.h"
#define NDLC_TIMER_T1 100
#define NDLC_TIMER_T1_WAIT 400
@@ -266,7 +266,8 @@ static void ndlc_t2_timeout(unsigned long data)
}
int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
- int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id)
+ int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id,
+ struct st_nci_se_status *se_status)
{
struct llt_ndlc *ndlc;
@@ -296,7 +297,7 @@ int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work);
- return st_nci_probe(ndlc, phy_headroom, phy_tailroom);
+ return st_nci_probe(ndlc, phy_headroom, phy_tailroom, se_status);
}
EXPORT_SYMBOL(ndlc_probe);
diff --git a/drivers/nfc/st-nci/ndlc.h b/drivers/nfc/st-nci/ndlc.h
index 6361005ef003..bdf78ffd5bb7 100644
--- a/drivers/nfc/st-nci/ndlc.h
+++ b/drivers/nfc/st-nci/ndlc.h
@@ -22,6 +22,8 @@
#include <linux/skbuff.h>
#include <net/nfc/nfc.h>
+struct st_nci_se_status;
+
/* Low Level Transport description */
struct llt_ndlc {
struct nci_dev *ndev;
@@ -55,6 +57,7 @@ void ndlc_close(struct llt_ndlc *ndlc);
int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb);
void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb);
int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
- int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id);
+ int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id,
+ struct st_nci_se_status *se_status);
void ndlc_remove(struct llt_ndlc *ndlc);
#endif /* __LOCAL_NDLC_H__ */
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/se.c
index c742ef65a05a..dbab722a0654 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -23,7 +23,6 @@
#include <net/nfc/nci_core.h>
#include "st-nci.h"
-#include "st-nci_se.h"
struct st_nci_pipe_info {
u8 pipe_state;
@@ -40,7 +39,6 @@ struct st_nci_pipe_info {
#define ST_NCI_ESE_HOST_ID 0xc0
/* Gates */
-#define ST_NCI_DEVICE_MGNT_GATE 0x01
#define ST_NCI_APDU_READER_GATE 0xf0
#define ST_NCI_CONNECTIVITY_GATE 0x41
@@ -64,7 +62,7 @@ struct st_nci_pipe_info {
#define ST_NCI_EVT_SE_HARD_RESET 0x20
#define ST_NCI_EVT_TRANSMIT_DATA 0x10
-#define ST_NCI_EVT_WTX_REQUEST 0x11
+#define ST_NCI_EVT_WTX_REQUEST 0x11
#define ST_NCI_EVT_SE_SOFT_RESET 0x11
#define ST_NCI_EVT_SE_END_OF_APDU_TRANSFER 0x21
#define ST_NCI_EVT_HOT_PLUG 0x03
@@ -113,6 +111,11 @@ static struct nci_hci_gate st_nci_gates[] = {
{ST_NCI_DEVICE_MGNT_GATE, ST_NCI_DEVICE_MGNT_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
+ {NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
+ {NCI_HCI_LOOPBACK_GATE, NCI_HCI_INVALID_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
+
/* Secure element pipes are created by secure element host */
{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
@@ -226,27 +229,32 @@ int st_nci_hci_load_session(struct nci_dev *ndev)
continue;
}
- for (j = 0; (j < ARRAY_SIZE(st_nci_gates)) &&
+ for (j = 3; (j < ARRAY_SIZE(st_nci_gates)) &&
(st_nci_gates[j].gate != dm_pipe_info->dst_gate_id); j++)
;
if (j < ARRAY_SIZE(st_nci_gates) &&
st_nci_gates[j].gate == dm_pipe_info->dst_gate_id &&
ST_NCI_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) {
- st_nci_gates[j].pipe = pipe_info[2];
+ ndev->hci_dev->init_data.gates[j].pipe = pipe_info[2];
ndev->hci_dev->gate2pipe[st_nci_gates[j].gate] =
- st_nci_gates[j].pipe;
- ndev->hci_dev->pipes[st_nci_gates[j].pipe].gate =
+ pipe_info[2];
+ ndev->hci_dev->pipes[pipe_info[2]].gate =
st_nci_gates[j].gate;
- ndev->hci_dev->pipes[st_nci_gates[j].pipe].host =
+ ndev->hci_dev->pipes[pipe_info[2]].host =
dm_pipe_info->src_host_id;
}
kfree_skb(skb_pipe_info);
}
- memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
- sizeof(st_nci_gates));
+ /*
+ * 3 gates have a well known pipe ID. Only NCI_HCI_LINK_MGMT_GATE
+ * is not yet open at this stage.
+ */
+ r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID,
+ NCI_HCI_LINK_MGMT_GATE,
+ NCI_HCI_LINK_MGMT_PIPE);
kfree_skb(skb_pipe_list);
return r;
@@ -272,6 +280,8 @@ static void st_nci_hci_admin_event_received(struct nci_dev *ndev,
}
}
break;
+ default:
+ nfc_err(&ndev->nfc_dev->dev, "Unexpected event on admin gate\n");
}
}
@@ -295,6 +305,9 @@ static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev,
mod_timer(&info->se_info.bwi_timer, jiffies +
msecs_to_jiffies(info->se_info.wt_timeout));
break;
+ default:
+ nfc_err(&ndev->nfc_dev->dev, "Unexpected event on apdu reader gate\n");
+ return 1;
}
kfree_skb(skb);
@@ -349,6 +362,7 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
r = nfc_se_transaction(ndev->nfc_dev, host, transaction);
break;
default:
+ nfc_err(&ndev->nfc_dev->dev, "Unexpected event on connectivity gate\n");
return 1;
}
kfree_skb(skb);
@@ -369,8 +383,10 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
st_nci_hci_apdu_reader_event_received(ndev, event, skb);
break;
case ST_NCI_CONNECTIVITY_GATE:
- st_nci_hci_connectivity_event_received(ndev, host, event,
- skb);
+ st_nci_hci_connectivity_event_received(ndev, host, event, skb);
+ break;
+ case NCI_HCI_LOOPBACK_GATE:
+ st_nci_hci_loopback_event_received(ndev, event, skb);
break;
}
}
@@ -403,15 +419,11 @@ void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
}
EXPORT_SYMBOL_GPL(st_nci_hci_cmd_received);
-/*
- * Remarks: On some early st_nci firmware, nci_nfcee_mode_set(0)
- * is rejected
- */
static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
- u8 state)
+ u8 state)
{
struct st_nci_info *info = nci_get_drvdata(ndev);
- int r;
+ int r, i;
struct sk_buff *sk_host_list;
u8 host_id;
@@ -433,7 +445,7 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
* retrieve a relevant host list.
*/
reinit_completion(&info->se_info.req_completion);
- r = nci_nfcee_mode_set(ndev, se_idx, NCI_NFCEE_ENABLE);
+ r = nci_nfcee_mode_set(ndev, se_idx, state);
if (r != NCI_STATUS_OK)
return r;
@@ -449,14 +461,19 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
* There is no possible synchronization to prevent this.
* Adding a small delay is the only way to solve the issue.
*/
- usleep_range(3000, 5000);
+ if (info->se_info.se_status->is_ese_present &&
+ info->se_info.se_status->is_uicc_present)
+ usleep_range(15000, 20000);
r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
if (r != NCI_HCI_ANY_OK)
return r;
- host_id = sk_host_list->data[sk_host_list->len - 1];
+ for (i = 0; i < sk_host_list->len &&
+ sk_host_list->data[i] != se_idx; i++)
+ ;
+ host_id = sk_host_list->data[i];
kfree_skb(sk_host_list);
if (state == ST_NCI_SE_MODE_ON && host_id == se_idx)
return se_idx;
@@ -472,11 +489,20 @@ int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
pr_debug("st_nci_disable_se\n");
- if (se_idx == NFC_SE_EMBEDDED) {
- r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
- ST_NCI_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
- if (r < 0)
- return r;
+ /*
+ * According to upper layer, se_idx == NFC_SE_UICC when
+ * info->se_info.se_status->is_uicc_enable is true should never happen
+ * Same for eSE.
+ */
+ r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_OFF);
+ if (r < 0) {
+ /* Do best effort to release SWP */
+ if (se_idx == NFC_SE_EMBEDDED) {
+ r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
+ ST_NCI_EVT_SE_END_OF_APDU_TRANSFER,
+ NULL, 0);
+ }
+ return r;
}
return 0;
@@ -489,11 +515,25 @@ int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
pr_debug("st_nci_enable_se\n");
- if (se_idx == ST_NCI_HCI_HOST_ID_ESE) {
+ /*
+ * According to upper layer, se_idx == NFC_SE_UICC when
+ * info->se_info.se_status->is_uicc_enable is true should never happen.
+ * Same for eSE.
+ */
+ r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_ON);
+ if (r == ST_NCI_HCI_HOST_ID_ESE) {
+ st_nci_se_get_atr(ndev);
r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
- if (r < 0)
- return r;
+ }
+
+ if (r < 0) {
+ /*
+ * The activation procedure failed, the secure element
+ * is not connected. Remove from the list.
+ */
+ nfc_remove_se(ndev->nfc_dev, se_idx);
+ return r;
}
return 0;
@@ -502,6 +542,7 @@ EXPORT_SYMBOL_GPL(st_nci_enable_se);
static int st_nci_hci_network_init(struct nci_dev *ndev)
{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
struct core_conn_create_dest_spec_params *dest_params;
struct dest_spec_params spec_params;
struct nci_conn_info *conn_info;
@@ -532,6 +573,7 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
if (!conn_info)
goto free_dest_params;
+ ndev->hci_dev->init_data.gate_count = ARRAY_SIZE(st_nci_gates);
memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
sizeof(st_nci_gates));
@@ -553,10 +595,17 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
if (r != NCI_HCI_ANY_OK)
goto free_dest_params;
- r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
- NCI_NFCEE_ENABLE);
- if (r != NCI_STATUS_OK)
- goto free_dest_params;
+ /*
+ * In factory mode, we prevent secure elements activation
+ * by disabling nfcee on the current HCI connection id.
+ * HCI will be used here only for proprietary commands.
+ */
+ if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
+ r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+ NCI_NFCEE_DISABLE);
+ else
+ r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+ NCI_NFCEE_ENABLE);
free_dest_params:
kfree(dest_params);
@@ -567,9 +616,10 @@ exit:
int st_nci_discover_se(struct nci_dev *ndev)
{
- u8 param[2];
- int r;
+ u8 white_list[2];
+ int r, wl_size = 0;
int se_count = 0;
+ struct st_nci_info *info = nci_get_drvdata(ndev);
pr_debug("st_nci_discover_se\n");
@@ -577,29 +627,37 @@ int st_nci_discover_se(struct nci_dev *ndev)
if (r != 0)
return r;
- param[0] = ST_NCI_UICC_HOST_ID;
- param[1] = ST_NCI_HCI_HOST_ID_ESE;
- r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
- NCI_HCI_ADMIN_PARAM_WHITELIST,
- param, sizeof(param));
- if (r != NCI_HCI_ANY_OK)
- return r;
+ if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
+ return 0;
+
+ if (info->se_info.se_status->is_ese_present &&
+ info->se_info.se_status->is_uicc_present) {
+ white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
+ white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
+ } else if (!info->se_info.se_status->is_ese_present &&
+ info->se_info.se_status->is_uicc_present) {
+ white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
+ } else if (info->se_info.se_status->is_ese_present &&
+ !info->se_info.se_status->is_uicc_present) {
+ white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
+ }
- r = st_nci_control_se(ndev, ST_NCI_UICC_HOST_ID,
- ST_NCI_SE_MODE_ON);
- if (r == ST_NCI_UICC_HOST_ID) {
+ if (wl_size) {
+ r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
+ NCI_HCI_ADMIN_PARAM_WHITELIST,
+ white_list, wl_size);
+ if (r != NCI_HCI_ANY_OK)
+ return r;
+ }
+
+ if (info->se_info.se_status->is_uicc_present) {
nfc_add_se(ndev->nfc_dev, ST_NCI_UICC_HOST_ID, NFC_SE_UICC);
se_count++;
}
- /* Try to enable eSE in order to check availability */
- r = st_nci_control_se(ndev, ST_NCI_HCI_HOST_ID_ESE,
- ST_NCI_SE_MODE_ON);
- if (r == ST_NCI_HCI_HOST_ID_ESE) {
- nfc_add_se(ndev->nfc_dev, ST_NCI_HCI_HOST_ID_ESE,
- NFC_SE_EMBEDDED);
+ if (info->se_info.se_status->is_ese_present) {
+ nfc_add_se(ndev->nfc_dev, ST_NCI_ESE_HOST_ID, NFC_SE_EMBEDDED);
se_count++;
- st_nci_se_get_atr(ndev);
}
return !se_count;
@@ -672,7 +730,7 @@ static void st_nci_se_activation_timeout(unsigned long data)
complete(&info->se_info.req_completion);
}
-int st_nci_se_init(struct nci_dev *ndev)
+int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status)
{
struct st_nci_info *info = nci_get_drvdata(ndev);
@@ -694,6 +752,8 @@ int st_nci_se_init(struct nci_dev *ndev)
info->se_info.wt_timeout =
ST_NCI_BWI_TO_TIMEOUT(ST_NCI_ATR_DEFAULT_BWI);
+ info->se_info.se_status = se_status;
+
return 0;
}
EXPORT_SYMBOL(st_nci_se_init);
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index 598a58c4d6d1..d6519bb9dba5 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -25,9 +25,10 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
+#include <net/nfc/nci.h>
#include <linux/platform_data/st-nci.h>
-#include "ndlc.h"
+#include "st-nci.h"
#define DRIVER_DESC "NCI NFC driver for ST_NCI"
@@ -50,16 +51,13 @@ struct st_nci_spi_phy {
struct spi_device *spi_dev;
struct llt_ndlc *ndlc;
+ bool irq_active;
+
unsigned int gpio_reset;
unsigned int irq_polarity;
-};
-#define SPI_DUMP_SKB(info, skb) \
-do { \
- pr_debug("%s:\n", info); \
- print_hex_dump(KERN_DEBUG, "spi: ", DUMP_PREFIX_OFFSET, \
- 16, 1, (skb)->data, (skb)->len, 0); \
-} while (0)
+ struct st_nci_se_status se_status;
+};
static int st_nci_spi_enable(void *phy_id)
{
@@ -70,8 +68,10 @@ static int st_nci_spi_enable(void *phy_id)
gpio_set_value(phy->gpio_reset, 1);
usleep_range(80000, 85000);
- if (phy->ndlc->powered == 0)
+ if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
enable_irq(phy->spi_dev->irq);
+ phy->irq_active = true;
+ }
return 0;
}
@@ -81,6 +81,7 @@ static void st_nci_spi_disable(void *phy_id)
struct st_nci_spi_phy *phy = phy_id;
disable_irq_nosync(phy->spi_dev->irq);
+ phy->irq_active = false;
}
/*
@@ -94,15 +95,14 @@ static int st_nci_spi_write(void *phy_id, struct sk_buff *skb)
struct st_nci_spi_phy *phy = phy_id;
struct spi_device *dev = phy->spi_dev;
struct sk_buff *skb_rx;
- u8 buf[ST_NCI_SPI_MAX_SIZE];
+ u8 buf[ST_NCI_SPI_MAX_SIZE + NCI_DATA_HDR_SIZE +
+ ST_NCI_FRAME_HEADROOM + ST_NCI_FRAME_TAILROOM];
struct spi_transfer spi_xfer = {
.tx_buf = skb->data,
.rx_buf = buf,
.len = skb->len,
};
- SPI_DUMP_SKB("st_nci_spi_write", skb);
-
if (phy->ndlc->hard_fault != 0)
return phy->ndlc->hard_fault;
@@ -179,8 +179,6 @@ static int st_nci_spi_read(struct st_nci_spi_phy *phy,
skb_put(*skb, len);
memcpy((*skb)->data + ST_NCI_SPI_MIN_SIZE, buf, len);
- SPI_DUMP_SKB("spi frame read", *skb);
-
return 0;
}
@@ -258,6 +256,11 @@ static int st_nci_spi_of_request_resources(struct spi_device *dev)
phy->irq_polarity = irq_get_trigger_type(dev->irq);
+ phy->se_status.is_ese_present =
+ of_property_read_bool(pp, "ese-present");
+ phy->se_status.is_uicc_present =
+ of_property_read_bool(pp, "uicc-present");
+
return 0;
}
#else
@@ -290,6 +293,9 @@ static int st_nci_spi_request_resources(struct spi_device *dev)
return r;
}
+ phy->se_status.is_ese_present = pdata->is_ese_present;
+ phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
return 0;
}
@@ -340,12 +346,13 @@ static int st_nci_spi_probe(struct spi_device *dev)
r = ndlc_probe(phy, &spi_phy_ops, &dev->dev,
ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
- &phy->ndlc);
+ &phy->ndlc, &phy->se_status);
if (r < 0) {
nfc_err(&dev->dev, "Unable to register ndlc layer\n");
return r;
}
+ phy->irq_active = true;
r = devm_request_threaded_irq(&dev->dev, dev->irq, NULL,
st_nci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT,
@@ -377,7 +384,6 @@ MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
static struct spi_driver st_nci_spi_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = ST_NCI_SPI_DRIVER_NAME,
.of_match_table = of_match_ptr(of_st_nci_spi_match),
},
diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index 850a2395deb7..8b9f77b0249c 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -19,7 +19,6 @@
#ifndef __LOCAL_ST_NCI_H_
#define __LOCAL_ST_NCI_H_
-#include "st-nci_se.h"
#include "ndlc.h"
/* Define private flags: */
@@ -28,6 +27,18 @@
#define ST_NCI_CORE_PROP 0x01
#define ST_NCI_SET_NFC_MODE 0x02
+/*
+ * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
+ * sequence of at most 32 characters.
+ */
+#define ST_NCI_ESE_MAX_LENGTH 33
+#define ST_NCI_HCI_HOST_ID_ESE 0xc0
+
+#define ST_NCI_DEVICE_MGNT_GATE 0x01
+
+#define ST_NCI_VENDOR_OUI 0x0080E1 /* STMicroelectronics */
+#define ST_NCI_FACTORY_MODE 2
+
struct nci_mode_set_cmd {
u8 cmd_type;
u8 mode;
@@ -37,14 +48,116 @@ struct nci_mode_set_rsp {
u8 status;
} __packed;
+struct st_nci_se_status {
+ bool is_ese_present;
+ bool is_uicc_present;
+};
+
+struct st_nci_se_info {
+ struct st_nci_se_status *se_status;
+ u8 atr[ST_NCI_ESE_MAX_LENGTH];
+ struct completion req_completion;
+
+ struct timer_list bwi_timer;
+ int wt_timeout; /* in msecs */
+ bool bwi_active;
+
+ struct timer_list se_active_timer;
+ bool se_active;
+
+ bool xch_error;
+
+ se_io_cb_t cb;
+ void *cb_context;
+};
+
+/**
+ * enum nfc_vendor_cmds - supported nfc vendor commands
+ *
+ * @FACTORY_MODE: Allow to set the driver into a mode where no secure element
+ * are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
+ * It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
+ * RF trimmings or low level drivers configurations (I2C, SPI, SWP).
+ * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
+ * table following RF technology, CLF mode or protocol.
+ * @HCI_DM_GET_INFO: Allow to retrieve CLF information.
+ * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
+ * level drivers configurations or RF trimmings.
+ * @HCI_DM_DIRECT_LOAD: Allow to load a firmware into the CLF. A complete
+ * packet can be more than 8KB.
+ * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
+ * configuration changes without CLF power off.
+ * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
+ * white list).
+ * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
+ * technology. When using this command to anti-collision is done.
+ * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
+ * connectivity.
+ * @HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
+ * CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
+ * @HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
+ * specific CLF command as there is no GPIO for this.
+ * @HCI_DM_FWUPD_END: Allow to complete firmware update.
+ * @HCI_DM_VDC_VALUE_COMPARISON: Allow to compare the field applied on the
+ * CLF antenna to a reference value.
+ * @MANUFACTURER_SPECIFIC: Allow to retrieve manufacturer specific data
+ * received during a NCI_CORE_INIT_CMD.
+ */
+enum nfc_vendor_cmds {
+ FACTORY_MODE,
+ HCI_CLEAR_ALL_PIPES,
+ HCI_DM_PUT_DATA,
+ HCI_DM_UPDATE_AID,
+ HCI_DM_GET_INFO,
+ HCI_DM_GET_DATA,
+ HCI_DM_DIRECT_LOAD,
+ HCI_DM_RESET,
+ HCI_GET_PARAM,
+ HCI_DM_FIELD_GENERATOR,
+ HCI_LOOPBACK,
+ HCI_DM_FWUPD_START,
+ HCI_DM_FWUPD_END,
+ HCI_DM_VDC_MEASUREMENT_VALUE,
+ HCI_DM_VDC_VALUE_COMPARISON,
+ MANUFACTURER_SPECIFIC,
+};
+
+struct st_nci_vendor_info {
+ struct completion req_completion;
+ struct sk_buff *rx_skb;
+};
+
struct st_nci_info {
struct llt_ndlc *ndlc;
unsigned long flags;
+
struct st_nci_se_info se_info;
+ struct st_nci_vendor_info vendor_info;
};
void st_nci_remove(struct nci_dev *ndev);
int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
- int phy_tailroom);
+ int phy_tailroom, struct st_nci_se_status *se_status);
+
+int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status);
+void st_nci_se_deinit(struct nci_dev *ndev);
+
+int st_nci_discover_se(struct nci_dev *ndev);
+int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx);
+int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx);
+int st_nci_se_io(struct nci_dev *ndev, u32 se_idx,
+ u8 *apdu, size_t apdu_length,
+ se_io_cb_t cb, void *cb_context);
+int st_nci_hci_load_session(struct nci_dev *ndev);
+void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
+ u8 event, struct sk_buff *skb);
+void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
+ struct sk_buff *skb);
+
+void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
+ struct sk_buff *skb);
+int st_nci_vendor_cmds_init(struct nci_dev *ndev);
#endif /* __LOCAL_ST_NCI_H_ */
diff --git a/drivers/nfc/st-nci/st-nci_se.h b/drivers/nfc/st-nci/st-nci_se.h
deleted file mode 100644
index ea66e879d67f..000000000000
--- a/drivers/nfc/st-nci/st-nci_se.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Secure Element Driver for STMicroelectronics NFC NCI Chip
- *
- * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
- *
- * 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 that it will be useful,
- * but WITHOUT 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 __LOCAL_ST_NCI_SE_H_
-#define __LOCAL_ST_NCI_SE_H_
-
-/*
- * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
- * sequence of at most 32 characters.
- */
-#define ST_NCI_ESE_MAX_LENGTH 33
-#define ST_NCI_HCI_HOST_ID_ESE 0xc0
-
-struct st_nci_se_info {
- u8 atr[ST_NCI_ESE_MAX_LENGTH];
- struct completion req_completion;
-
- struct timer_list bwi_timer;
- int wt_timeout; /* in msecs */
- bool bwi_active;
-
- struct timer_list se_active_timer;
- bool se_active;
-
- bool xch_error;
-
- se_io_cb_t cb;
- void *cb_context;
-};
-
-int st_nci_se_init(struct nci_dev *ndev);
-void st_nci_se_deinit(struct nci_dev *ndev);
-
-int st_nci_discover_se(struct nci_dev *ndev);
-int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx);
-int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx);
-int st_nci_se_io(struct nci_dev *ndev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context);
-int st_nci_hci_load_session(struct nci_dev *ndev);
-void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
- u8 event, struct sk_buff *skb);
-void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
- struct sk_buff *skb);
-
-
-#endif /* __LOCAL_ST_NCI_SE_H_ */
diff --git a/drivers/nfc/st-nci/vendor_cmds.c b/drivers/nfc/st-nci/vendor_cmds.c
new file mode 100644
index 000000000000..b5debce4ae0b
--- /dev/null
+++ b/drivers/nfc/st-nci/vendor_cmds.c
@@ -0,0 +1,516 @@
+/*
+ * Proprietary commands extension for STMicroelectronics NFC NCI Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * 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 that it will be useful,
+ * but WITHOUT 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 <net/genetlink.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/delay.h>
+#include <net/nfc/nci_core.h>
+
+#include "st-nci.h"
+
+#define ST_NCI_HCI_DM_GETDATA 0x10
+#define ST_NCI_HCI_DM_PUTDATA 0x11
+#define ST_NCI_HCI_DM_LOAD 0x12
+#define ST_NCI_HCI_DM_GETINFO 0x13
+#define ST_NCI_HCI_DM_FWUPD_START 0x14
+#define ST_NCI_HCI_DM_FWUPD_STOP 0x15
+#define ST_NCI_HCI_DM_UPDATE_AID 0x20
+#define ST_NCI_HCI_DM_RESET 0x3e
+
+#define ST_NCI_HCI_DM_FIELD_GENERATOR 0x32
+#define ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE 0x33
+#define ST_NCI_HCI_DM_VDC_VALUE_COMPARISON 0x34
+
+#define ST_NCI_FACTORY_MODE_ON 1
+#define ST_NCI_FACTORY_MODE_OFF 0
+
+#define ST_NCI_EVT_POST_DATA 0x02
+
+struct get_param_data {
+ u8 gate;
+ u8 data;
+} __packed;
+
+static int st_nci_factory_mode(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ if (data_len != 1)
+ return -EINVAL;
+
+ pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
+
+ switch (((u8 *)data)[0]) {
+ case ST_NCI_FACTORY_MODE_ON:
+ test_and_set_bit(ST_NCI_FACTORY_MODE, &info->flags);
+ break;
+ case ST_NCI_FACTORY_MODE_OFF:
+ clear_bit(ST_NCI_FACTORY_MODE, &info->flags);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int st_nci_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_clear_all_pipes(ndev);
+}
+
+static int st_nci_hci_dm_put_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_PUTDATA, data,
+ data_len, NULL);
+}
+
+static int st_nci_hci_dm_update_aid(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_UPDATE_AID, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_get_info(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETINFO,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_GET_INFO, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_get_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETDATA,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_GET_DATA, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_fwupd_start(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ dev->fw_download_in_progress = true;
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_FWUPD_START, data, data_len, NULL);
+ if (r)
+ dev->fw_download_in_progress = false;
+
+ return r;
+}
+
+static int st_nci_hci_dm_fwupd_end(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_FWUPD_STOP, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_direct_load(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ if (dev->fw_download_in_progress) {
+ dev->fw_download_in_progress = false;
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_LOAD, data, data_len, NULL);
+ }
+ return -EPROTO;
+}
+
+static int st_nci_hci_dm_reset(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_RESET, data, data_len, NULL);
+ msleep(200);
+
+ return 0;
+}
+
+static int st_nci_hci_get_param(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+ struct get_param_data *param = (struct get_param_data *)data;
+
+ if (data_len < sizeof(struct get_param_data))
+ return -EPROTO;
+
+ r = nci_hci_get_param(ndev, param->gate, param->data, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_GET_PARAM, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_field_generator(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_FIELD_GENERATOR, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_vdc_measurement_value(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ if (data_len != 4)
+ return -EPROTO;
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_VDC_MEASUREMENT_VALUE, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_vdc_value_comparison(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ if (data_len != 2)
+ return -EPROTO;
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_VDC_VALUE_COMPARISON,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_VDC_VALUE_COMPARISON, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
+ struct sk_buff *skb)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ switch (event) {
+ case ST_NCI_EVT_POST_DATA:
+ info->vendor_info.rx_skb = skb;
+ break;
+ default:
+ nfc_err(&ndev->nfc_dev->dev, "Unexpected event on loopback gate\n");
+ }
+ complete(&info->vendor_info.req_completion);
+}
+EXPORT_SYMBOL(st_nci_hci_loopback_event_received);
+
+static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ if (data_len <= 0)
+ return -EPROTO;
+
+ reinit_completion(&info->vendor_info.req_completion);
+ info->vendor_info.rx_skb = NULL;
+
+ r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
+ ST_NCI_EVT_POST_DATA, data, data_len);
+ if (r != data_len) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ wait_for_completion_interruptible(&info->vendor_info.req_completion);
+
+ if (!info->vendor_info.rx_skb ||
+ info->vendor_info.rx_skb->len != data_len) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
+ ST_NCI_VENDOR_OUI,
+ HCI_LOOPBACK,
+ info->vendor_info.rx_skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
+ info->vendor_info.rx_skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+free_skb:
+ kfree_skb(info->vendor_info.rx_skb);
+exit:
+ return r;
+}
+
+static int st_nci_manufacturer_specific(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct sk_buff *msg;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ MANUFACTURER_SPECIFIC,
+ sizeof(ndev->manufact_specific_info));
+ if (!msg)
+ return -ENOMEM;
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, sizeof(ndev->manufact_specific_info),
+ &ndev->manufact_specific_info)) {
+ kfree_skb(msg);
+ return -ENOBUFS;
+ }
+
+ return nfc_vendor_cmd_reply(msg);
+}
+
+static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = FACTORY_MODE,
+ .doit = st_nci_factory_mode,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_CLEAR_ALL_PIPES,
+ .doit = st_nci_hci_clear_all_pipes,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_PUT_DATA,
+ .doit = st_nci_hci_dm_put_data,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_UPDATE_AID,
+ .doit = st_nci_hci_dm_update_aid,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_INFO,
+ .doit = st_nci_hci_dm_get_info,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_DATA,
+ .doit = st_nci_hci_dm_get_data,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_DIRECT_LOAD,
+ .doit = st_nci_hci_dm_direct_load,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_RESET,
+ .doit = st_nci_hci_dm_reset,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_GET_PARAM,
+ .doit = st_nci_hci_get_param,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_FIELD_GENERATOR,
+ .doit = st_nci_hci_dm_field_generator,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_FWUPD_START,
+ .doit = st_nci_hci_dm_fwupd_start,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_FWUPD_END,
+ .doit = st_nci_hci_dm_fwupd_end,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_LOOPBACK,
+ .doit = st_nci_hci_loopback,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_VDC_MEASUREMENT_VALUE,
+ .doit = st_nci_hci_dm_vdc_measurement_value,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_VDC_VALUE_COMPARISON,
+ .doit = st_nci_hci_dm_vdc_value_comparison,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = MANUFACTURER_SPECIFIC,
+ .doit = st_nci_manufacturer_specific,
+ },
+};
+
+int st_nci_vendor_cmds_init(struct nci_dev *ndev)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ init_completion(&info->vendor_info.req_completion);
+ return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
+ sizeof(st_nci_vendor_cmds));
+}
+EXPORT_SYMBOL(st_nci_vendor_cmds_init);
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 97edab4bbdf8..ded6489c3eeb 100644
--- a/drivers/nfc/st21nfca/Makefile
+++ b/drivers/nfc/st21nfca/Makefile
@@ -2,7 +2,7 @@
# Makefile for ST21NFCA HCI based NFC driver
#
-st21nfca_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o
+st21nfca_hci-objs = core.o dep.o se.o vendor_cmds.o
obj-$(CONFIG_NFC_ST21NFCA) += st21nfca_hci.o
st21nfca_i2c-objs = i2c.o
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/core.c
index 051286562fab..dd8b150fbffa 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -22,8 +22,6 @@
#include <net/nfc/llc.h>
#include "st21nfca.h"
-#include "st21nfca_dep.h"
-#include "st21nfca_se.h"
#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
@@ -87,12 +85,13 @@ static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
static struct nfc_hci_gate st21nfca_gates[] = {
{NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE},
+ {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
+ {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
+
{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
- {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
- {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
@@ -163,7 +162,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
ST21NFCA_DM_GETINFO, pipe_info,
sizeof(pipe_info), &skb_pipe_info);
-
if (r)
continue;
@@ -185,43 +183,33 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
continue;
}
- for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
+ for (j = 3; (j < ARRAY_SIZE(st21nfca_gates)) &&
(st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
;
if (j < ARRAY_SIZE(st21nfca_gates) &&
st21nfca_gates[j].gate == info->dst_gate_id &&
ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {
- st21nfca_gates[j].pipe = pipe_info[2];
+ hdev->init_data.gates[j].pipe = pipe_info[2];
hdev->gate2pipe[st21nfca_gates[j].gate] =
- st21nfca_gates[j].pipe;
- hdev->pipes[st21nfca_gates[j].pipe].gate =
- st21nfca_gates[j].gate;
- hdev->pipes[st21nfca_gates[j].pipe].dest_host =
- info->src_host_id;
+ pipe_info[2];
+ hdev->pipes[pipe_info[2]].gate =
+ st21nfca_gates[j].gate;
+ hdev->pipes[pipe_info[2]].dest_host =
+ info->src_host_id;
}
kfree_skb(skb_pipe_info);
}
/*
- * 3 gates have a well known pipe ID.
- * They will never appear in the pipe list
+ * 3 gates have a well known pipe ID. Only NFC_HCI_LINK_MGMT_GATE
+ * is not yet open at this stage.
*/
- if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {
- for (i = skb_pipe_list->len + 3;
- i < ARRAY_SIZE(st21nfca_gates) - 2; i++) {
- r = nfc_hci_connect_gate(hdev,
- NFC_HCI_HOST_CONTROLLER_ID,
- st21nfca_gates[i].gate,
- st21nfca_gates[i].pipe);
- if (r < 0)
- goto free_list;
- }
- }
+ r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
+ NFC_HCI_LINK_MGMT_GATE,
+ NFC_HCI_LINK_MGMT_PIPE);
- memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));
-free_list:
kfree_skb(skb_pipe_list);
return r;
}
@@ -905,6 +893,8 @@ static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event,
}
}
break;
+ default:
+ nfc_err(&hdev->ndev->dev, "Unexpected event on admin gate\n");
}
kfree_skb(skb);
return 0;
@@ -933,6 +923,8 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
event, skb);
case ST21NFCA_APDU_READER_GATE:
return st21nfca_apdu_reader_event_received(hdev, event, skb);
+ case NFC_HCI_LOOPBACK_GATE:
+ return st21nfca_hci_loopback_event_received(hdev, event, skb);
default:
return 1;
}
@@ -993,7 +985,6 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
* persistent info to discriminate 2 identical chips
*/
dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES);
-
if (dev_num >= ST21NFCA_NUM_DEVICES)
return -ENODEV;
@@ -1035,6 +1026,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
*hdev = info->hdev;
st21nfca_dep_init(info->hdev);
st21nfca_se_init(info->hdev);
+ st21nfca_vendor_cmds_init(info->hdev);
return 0;
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/dep.c
index 8882181d65de..798a32bbac5d 100644
--- a/drivers/nfc/st21nfca/st21nfca_dep.c
+++ b/drivers/nfc/st21nfca/dep.c
@@ -17,7 +17,6 @@
#include <net/nfc/hci.h>
#include "st21nfca.h"
-#include "st21nfca_dep.h"
#define ST21NFCA_NFCIP1_INITIATOR 0x00
#define ST21NFCA_NFCIP1_REQ 0xd4
@@ -436,6 +435,7 @@ int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
return r;
return 0;
default:
+ nfc_err(&hdev->ndev->dev, "Unexpected event on card f gate\n");
return 1;
}
kfree_skb(skb);
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index a32143951616..a98da33e680a 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -94,6 +94,7 @@ struct st21nfca_i2c_phy {
int hard_fault;
struct mutex phy_lock;
};
+
static u8 len_seq[] = { 16, 24, 12, 29 };
static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};
diff --git a/drivers/nfc/st21nfca/st21nfca_se.c b/drivers/nfc/st21nfca/se.c
index 3197e9bb66f7..c79d99b24c96 100644
--- a/drivers/nfc/st21nfca/st21nfca_se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -17,10 +17,9 @@
#include <net/nfc/hci.h>
#include "st21nfca.h"
-#include "st21nfca_se.h"
#define ST21NFCA_EVT_UICC_ACTIVATE 0x10
-#define ST21NFCA_EVT_UICC_DEACTIVATE 0x13
+#define ST21NFCA_EVT_UICC_DEACTIVATE 0x13
#define ST21NFCA_EVT_SE_HARD_RESET 0x20
#define ST21NFCA_EVT_SE_SOFT_RESET 0x11
#define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER 0x21
@@ -101,7 +100,7 @@ static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
u8 state)
{
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
- int r;
+ int r, i;
struct sk_buff *sk_host_list;
u8 se_event, host_id;
@@ -149,7 +148,10 @@ static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
if (r < 0)
return r;
- host_id = sk_host_list->data[sk_host_list->len - 1];
+ for (i = 0; i < sk_host_list->len &&
+ sk_host_list->data[i] != se_idx; i++)
+ ;
+ host_id = sk_host_list->data[i];
kfree_skb(sk_host_list);
if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx)
@@ -165,6 +167,9 @@ int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev)
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
int se_count = 0;
+ if (test_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks))
+ return 0;
+
if (info->se_status->is_uicc_present) {
nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
se_count++;
@@ -189,7 +194,6 @@ int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
* Same for eSE.
*/
r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON);
-
if (r == ST21NFCA_ESE_HOST_ID) {
st21nfca_se_get_atr(hdev);
r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
@@ -340,6 +344,7 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
r = nfc_se_transaction(hdev->ndev, host, transaction);
break;
default:
+ nfc_err(&hdev->ndev->dev, "Unexpected event on connectivity gate\n");
return 1;
}
kfree_skb(skb);
@@ -371,6 +376,9 @@ int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
mod_timer(&info->se_info.bwi_timer, jiffies +
msecs_to_jiffies(info->se_info.wt_timeout));
break;
+ default:
+ nfc_err(&hdev->ndev->dev, "Unexpected event on apdu reader gate\n");
+ return 1;
}
exit:
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 15a78d330a9f..94ffb0501e87 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -18,9 +18,8 @@
#define __LOCAL_ST21NFCA_H_
#include <net/nfc/hci.h>
-
-#include "st21nfca_dep.h"
-#include "st21nfca_se.h"
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
#define HCI_MODE 0
@@ -46,28 +45,115 @@
#define ST21NFCA_HCI_LLC_MAX_SIZE (ST21NFCA_HCI_LLC_LEN_CRC + 1 + \
ST21NFCA_HCI_LLC_MAX_PAYLOAD)
+/* Reader RF commands */
+#define ST21NFCA_WR_XCHG_DATA 0x10
+
+#define ST21NFCA_DEVICE_MGNT_GATE 0x01
+#define ST21NFCA_RF_READER_F_GATE 0x14
+#define ST21NFCA_RF_CARD_F_GATE 0x24
+#define ST21NFCA_APDU_READER_GATE 0xf0
+#define ST21NFCA_CONNECTIVITY_GATE 0x41
+
+/*
+ * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
+ * sequence of at most 32 characters.
+ */
+#define ST21NFCA_ESE_MAX_LENGTH 33
+#define ST21NFCA_ESE_HOST_ID 0xc0
+
#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
-#define ST21NFCA_HCI_MODE 0
+#define ST21NFCA_HCI_MODE 0
+#define ST21NFCA_NUM_DEVICES 256
-#define ST21NFCA_NUM_DEVICES 256
+#define ST21NFCA_VENDOR_OUI 0x0080E1 /* STMicroelectronics */
+#define ST21NFCA_FACTORY_MODE 2
struct st21nfca_se_status {
bool is_ese_present;
bool is_uicc_present;
};
-int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
- char *llc_name, int phy_headroom, int phy_tailroom,
- int phy_payload, struct nfc_hci_dev **hdev,
- struct st21nfca_se_status *se_status);
-void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
-
enum st21nfca_state {
ST21NFCA_ST_COLD,
ST21NFCA_ST_READY,
};
+/**
+ * enum nfc_vendor_cmds - supported nfc vendor commands
+ *
+ * @FACTORY_MODE: Allow to set the driver into a mode where no secure element
+ * are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
+ * It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
+ * RF trimmings or low level drivers configurations (I2C, SPI, SWP).
+ * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
+ * table following RF technology, CLF mode or protocol.
+ * @HCI_DM_GET_INFO: Allow to retrieve CLF information.
+ * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
+ * level drivers configurations or RF trimmings.
+ * @HCI_DM_LOAD: Allow to load a firmware into the CLF. A complete
+ * packet can be more than 8KB.
+ * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
+ * configuration changes without CLF power off.
+ * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
+ * white list).
+ * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
+ * technology. When using this command to anti-collision is done.
+ * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
+ * connectivity.
+ */
+enum nfc_vendor_cmds {
+ FACTORY_MODE,
+ HCI_CLEAR_ALL_PIPES,
+ HCI_DM_PUT_DATA,
+ HCI_DM_UPDATE_AID,
+ HCI_DM_GET_INFO,
+ HCI_DM_GET_DATA,
+ HCI_DM_LOAD,
+ HCI_DM_RESET,
+ HCI_GET_PARAM,
+ HCI_DM_FIELD_GENERATOR,
+ HCI_LOOPBACK,
+};
+
+struct st21nfca_vendor_info {
+ struct completion req_completion;
+ struct sk_buff *rx_skb;
+};
+
+struct st21nfca_dep_info {
+ struct sk_buff *tx_pending;
+ struct work_struct tx_work;
+ u8 curr_nfc_dep_pni;
+ u32 idx;
+ u8 to;
+ u8 did;
+ u8 bsi;
+ u8 bri;
+ u8 lri;
+} __packed;
+
+struct st21nfca_se_info {
+ u8 atr[ST21NFCA_ESE_MAX_LENGTH];
+ struct completion req_completion;
+
+ struct timer_list bwi_timer;
+ int wt_timeout; /* in msecs */
+ bool bwi_active;
+
+ struct timer_list se_active_timer;
+ bool se_active;
+ int expected_pipes;
+ int count_pipes;
+
+ bool xch_error;
+
+ se_io_cb_t cb;
+ void *cb_context;
+};
+
struct st21nfca_hci_info {
struct nfc_phy_ops *phy_ops;
void *phy_id;
@@ -85,15 +171,41 @@ struct st21nfca_hci_info {
struct st21nfca_dep_info dep_info;
struct st21nfca_se_info se_info;
+ struct st21nfca_vendor_info vendor_info;
};
-/* Reader RF commands */
-#define ST21NFCA_WR_XCHG_DATA 0x10
+int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
+ char *llc_name, int phy_headroom, int phy_tailroom,
+ int phy_payload, struct nfc_hci_dev **hdev,
+ struct st21nfca_se_status *se_status);
+void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
-#define ST21NFCA_DEVICE_MGNT_GATE 0x01
-#define ST21NFCA_RF_READER_F_GATE 0x14
-#define ST21NFCA_RF_CARD_F_GATE 0x24
-#define ST21NFCA_APDU_READER_GATE 0xf0
-#define ST21NFCA_CONNECTIVITY_GATE 0x41
+int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
+ u8 event, struct sk_buff *skb);
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+void st21nfca_dep_init(struct nfc_hci_dev *hdev);
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev);
+
+int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+ u8 event, struct sk_buff *skb);
+int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
+ u8 event, struct sk_buff *skb);
+
+int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev);
+int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx);
+int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx);
+int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
+ u8 *apdu, size_t apdu_length,
+ se_io_cb_t cb, void *cb_context);
+
+void st21nfca_se_init(struct nfc_hci_dev *hdev);
+void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
+
+int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *ndev, u8 event,
+ struct sk_buff *skb);
+int st21nfca_vendor_cmds_init(struct nfc_hci_dev *ndev);
#endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.h b/drivers/nfc/st21nfca/st21nfca_dep.h
deleted file mode 100644
index baf4664b4fc4..000000000000
--- a/drivers/nfc/st21nfca/st21nfca_dep.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
- *
- * 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 that it will be useful,
- * but WITHOUT 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 __ST21NFCA_DEP_H
-#define __ST21NFCA_DEP_H
-
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-
-struct st21nfca_dep_info {
- struct sk_buff *tx_pending;
- struct work_struct tx_work;
- u8 curr_nfc_dep_pni;
- u32 idx;
- u8 to;
- u8 did;
- u8 bsi;
- u8 bri;
- u8 lri;
-} __packed;
-
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
- u8 event, struct sk_buff *skb);
-int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
-
-int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
-int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb);
-void st21nfca_dep_init(struct nfc_hci_dev *hdev);
-void st21nfca_dep_deinit(struct nfc_hci_dev *hdev);
-#endif /* __ST21NFCA_DEP_H */
diff --git a/drivers/nfc/st21nfca/st21nfca_se.h b/drivers/nfc/st21nfca/st21nfca_se.h
deleted file mode 100644
index b172cfcaeb90..000000000000
--- a/drivers/nfc/st21nfca/st21nfca_se.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
- *
- * 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 that it will be useful,
- * but WITHOUT 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 __ST21NFCA_SE_H
-#define __ST21NFCA_SE_H
-
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-
-/*
- * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
- * sequence of at most 32 characters.
- */
-#define ST21NFCA_ESE_MAX_LENGTH 33
-#define ST21NFCA_ESE_HOST_ID 0xc0
-
-struct st21nfca_se_info {
- u8 atr[ST21NFCA_ESE_MAX_LENGTH];
- struct completion req_completion;
-
- struct timer_list bwi_timer;
- int wt_timeout; /* in msecs */
- bool bwi_active;
-
- struct timer_list se_active_timer;
- bool se_active;
- int expected_pipes;
- int count_pipes;
-
- bool xch_error;
-
- se_io_cb_t cb;
- void *cb_context;
-};
-
-int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
- u8 event, struct sk_buff *skb);
-int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
- u8 event, struct sk_buff *skb);
-
-int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev);
-int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx);
-int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx);
-int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context);
-
-void st21nfca_se_init(struct nfc_hci_dev *hdev);
-void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
-#endif /* __ST21NFCA_SE_H */
diff --git a/drivers/nfc/st21nfca/vendor_cmds.c b/drivers/nfc/st21nfca/vendor_cmds.c
new file mode 100644
index 000000000000..ab765e5478c0
--- /dev/null
+++ b/drivers/nfc/st21nfca/vendor_cmds.c
@@ -0,0 +1,375 @@
+/*
+ * Proprietary commands extension for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * 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 that it will be useful,
+ * but WITHOUT 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 <net/genetlink.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "st21nfca.h"
+
+#define ST21NFCA_HCI_DM_GETDATA 0x10
+#define ST21NFCA_HCI_DM_PUTDATA 0x11
+#define ST21NFCA_HCI_DM_LOAD 0x12
+#define ST21NFCA_HCI_DM_GETINFO 0x13
+#define ST21NFCA_HCI_DM_UPDATE_AID 0x20
+#define ST21NFCA_HCI_DM_RESET 0x3e
+
+#define ST21NFCA_HCI_DM_FIELD_GENERATOR 0x32
+
+#define ST21NFCA_FACTORY_MODE_ON 1
+#define ST21NFCA_FACTORY_MODE_OFF 0
+
+#define ST21NFCA_EVT_POST_DATA 0x02
+
+struct get_param_data {
+ u8 gate;
+ u8 data;
+} __packed;
+
+static int st21nfca_factory_mode(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ if (data_len != 1)
+ return -EINVAL;
+
+ pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
+
+ switch (((u8 *)data)[0]) {
+ case ST21NFCA_FACTORY_MODE_ON:
+ test_and_set_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
+ break;
+ case ST21NFCA_FACTORY_MODE_OFF:
+ clear_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int st21nfca_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_disconnect_all_gates(hdev);
+}
+
+static int st21nfca_hci_dm_put_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_PUTDATA, data,
+ data_len, NULL);
+}
+
+static int st21nfca_hci_dm_update_aid(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_UPDATE_AID, data, data_len, NULL);
+}
+
+static int st21nfca_hci_dm_get_info(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ r = nfc_hci_send_cmd(hdev,
+ ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_GETINFO,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+ HCI_DM_GET_INFO, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st21nfca_hci_dm_get_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ r = nfc_hci_send_cmd(hdev,
+ ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_GETDATA,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+ HCI_DM_GET_DATA, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st21nfca_hci_dm_load(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_LOAD, data, data_len, NULL);
+}
+
+static int st21nfca_hci_dm_reset(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ r = nfc_hci_send_cmd_async(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_RESET, data, data_len, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ r = nfc_llc_stop(hdev->llc);
+ if (r < 0)
+ return r;
+
+ return nfc_llc_start(hdev->llc);
+}
+
+static int st21nfca_hci_get_param(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+ struct get_param_data *param = (struct get_param_data *)data;
+
+ if (data_len < sizeof(struct get_param_data))
+ return -EPROTO;
+
+ r = nfc_hci_get_param(hdev, param->gate, param->data, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+ HCI_GET_PARAM, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st21nfca_hci_dm_field_generator(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev,
+ ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_FIELD_GENERATOR,
+ data, data_len, NULL);
+}
+
+int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *hdev, u8 event,
+ struct sk_buff *skb)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ switch (event) {
+ case ST21NFCA_EVT_POST_DATA:
+ info->vendor_info.rx_skb = skb;
+ break;
+ default:
+ nfc_err(&hdev->ndev->dev, "Unexpected event on loopback gate\n");
+ }
+ complete(&info->vendor_info.req_completion);
+ return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_loopback_event_received);
+
+static int st21nfca_hci_loopback(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ if (data_len <= 0)
+ return -EPROTO;
+
+ reinit_completion(&info->vendor_info.req_completion);
+ info->vendor_info.rx_skb = NULL;
+
+ r = nfc_hci_send_event(hdev, NFC_HCI_LOOPBACK_GATE,
+ ST21NFCA_EVT_POST_DATA, data, data_len);
+ if (r < 0) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ wait_for_completion_interruptible(&info->vendor_info.req_completion);
+ if (!info->vendor_info.rx_skb ||
+ info->vendor_info.rx_skb->len != data_len) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(hdev->ndev,
+ ST21NFCA_VENDOR_OUI,
+ HCI_LOOPBACK,
+ info->vendor_info.rx_skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
+ info->vendor_info.rx_skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+free_skb:
+ kfree_skb(info->vendor_info.rx_skb);
+exit:
+ return r;
+}
+
+static struct nfc_vendor_cmd st21nfca_vendor_cmds[] = {
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = FACTORY_MODE,
+ .doit = st21nfca_factory_mode,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_CLEAR_ALL_PIPES,
+ .doit = st21nfca_hci_clear_all_pipes,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_PUT_DATA,
+ .doit = st21nfca_hci_dm_put_data,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_UPDATE_AID,
+ .doit = st21nfca_hci_dm_update_aid,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_INFO,
+ .doit = st21nfca_hci_dm_get_info,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_DATA,
+ .doit = st21nfca_hci_dm_get_data,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_LOAD,
+ .doit = st21nfca_hci_dm_load,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_RESET,
+ .doit = st21nfca_hci_dm_reset,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_GET_PARAM,
+ .doit = st21nfca_hci_get_param,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_FIELD_GENERATOR,
+ .doit = st21nfca_hci_dm_field_generator,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_LOOPBACK,
+ .doit = st21nfca_hci_loopback,
+ },
+};
+
+int st21nfca_vendor_cmds_init(struct nfc_hci_dev *hdev)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ init_completion(&info->vendor_info.req_completion);
+ return nfc_set_vendor_cmds(hdev->ndev, st21nfca_vendor_cmds,
+ sizeof(st21nfca_vendor_cmds));
+}
+EXPORT_SYMBOL(st21nfca_vendor_cmds_init);
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index 70b0707fd9a9..f857feb2b573 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c
@@ -2211,6 +2211,12 @@ static const struct dev_pm_ops trf7970a_pm_ops = {
trf7970a_pm_runtime_resume, NULL)
};
+static const struct of_device_id trf7970a_of_match[] = {
+ { .compatible = "ti,trf7970a", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, trf7970a_of_match);
+
static const struct spi_device_id trf7970a_id_table[] = {
{ "trf7970a", 0 },
{ }
@@ -2223,7 +2229,7 @@ static struct spi_driver trf7970a_spi_driver = {
.id_table = trf7970a_id_table,
.driver = {
.name = "trf7970a",
- .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(trf7970a_of_match),
.pm = &trf7970a_pm_ops,
},
};
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.c b/drivers/ntb/hw/intel/ntb_hw_intel.c
index 865a3e3cc581..a198f8298258 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.c
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.c
@@ -2204,17 +2204,17 @@ static const struct intel_ntb_xlat_reg xeon_sec_xlat = {
};
static struct intel_b2b_addr xeon_b2b_usd_addr = {
- .bar2_addr64 = XEON_B2B_BAR2_USD_ADDR64,
- .bar4_addr64 = XEON_B2B_BAR4_USD_ADDR64,
- .bar4_addr32 = XEON_B2B_BAR4_USD_ADDR32,
- .bar5_addr32 = XEON_B2B_BAR5_USD_ADDR32,
+ .bar2_addr64 = XEON_B2B_BAR2_ADDR64,
+ .bar4_addr64 = XEON_B2B_BAR4_ADDR64,
+ .bar4_addr32 = XEON_B2B_BAR4_ADDR32,
+ .bar5_addr32 = XEON_B2B_BAR5_ADDR32,
};
static struct intel_b2b_addr xeon_b2b_dsd_addr = {
- .bar2_addr64 = XEON_B2B_BAR2_DSD_ADDR64,
- .bar4_addr64 = XEON_B2B_BAR4_DSD_ADDR64,
- .bar4_addr32 = XEON_B2B_BAR4_DSD_ADDR32,
- .bar5_addr32 = XEON_B2B_BAR5_DSD_ADDR32,
+ .bar2_addr64 = XEON_B2B_BAR2_ADDR64,
+ .bar4_addr64 = XEON_B2B_BAR4_ADDR64,
+ .bar4_addr32 = XEON_B2B_BAR4_ADDR32,
+ .bar5_addr32 = XEON_B2B_BAR5_ADDR32,
};
/* operations for primary side of local ntb */
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.h b/drivers/ntb/hw/intel/ntb_hw_intel.h
index ea0612f797df..2eb4addd10d0 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.h
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.h
@@ -227,16 +227,11 @@
/* Use the following addresses for translation between b2b ntb devices in case
* the hardware default values are not reliable. */
-#define XEON_B2B_BAR0_USD_ADDR 0x1000000000000000ull
-#define XEON_B2B_BAR2_USD_ADDR64 0x2000000000000000ull
-#define XEON_B2B_BAR4_USD_ADDR64 0x4000000000000000ull
-#define XEON_B2B_BAR4_USD_ADDR32 0x20000000u
-#define XEON_B2B_BAR5_USD_ADDR32 0x40000000u
-#define XEON_B2B_BAR0_DSD_ADDR 0x9000000000000000ull
-#define XEON_B2B_BAR2_DSD_ADDR64 0xa000000000000000ull
-#define XEON_B2B_BAR4_DSD_ADDR64 0xc000000000000000ull
-#define XEON_B2B_BAR4_DSD_ADDR32 0xa0000000u
-#define XEON_B2B_BAR5_DSD_ADDR32 0xc0000000u
+#define XEON_B2B_BAR0_ADDR 0x1000000000000000ull
+#define XEON_B2B_BAR2_ADDR64 0x2000000000000000ull
+#define XEON_B2B_BAR4_ADDR64 0x4000000000000000ull
+#define XEON_B2B_BAR4_ADDR32 0x20000000u
+#define XEON_B2B_BAR5_ADDR32 0x40000000u
/* The peer ntb secondary config space is 32KB fixed size */
#define XEON_B2B_MIN_SIZE 0x8000
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 6e3ee907d186..60654d524858 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -605,7 +605,7 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
num_qps_mw = qp_count / mw_count;
rx_size = (unsigned int)mw->xlat_size / num_qps_mw;
- qp->rx_buff = mw->virt_addr + rx_size * qp_num / mw_count;
+ qp->rx_buff = mw->virt_addr + rx_size * (qp_num / mw_count);
rx_size -= sizeof(struct ntb_rx_info);
qp->remote_rx_info = qp->rx_buff + rx_size;
@@ -825,10 +825,10 @@ static void ntb_transport_link_work(struct work_struct *work)
size = max_mw_size;
spad = MW0_SZ_HIGH + (i * 2);
- ntb_peer_spad_write(ndev, spad, (u32)(size >> 32));
+ ntb_peer_spad_write(ndev, spad, upper_32_bits(size));
spad = MW0_SZ_LOW + (i * 2);
- ntb_peer_spad_write(ndev, spad, (u32)size);
+ ntb_peer_spad_write(ndev, spad, lower_32_bits(size));
}
ntb_peer_spad_write(ndev, NUM_MWS, nt->mw_count);
@@ -928,7 +928,6 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
unsigned int qp_num)
{
struct ntb_transport_qp *qp;
- struct ntb_transport_mw *mw;
phys_addr_t mw_base;
resource_size_t mw_size;
unsigned int num_qps_mw, tx_size;
@@ -939,7 +938,6 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
qp_count = nt->qp_count;
mw_num = QP_TO_MW(nt, qp_num);
- mw = &nt->mw_vec[mw_num];
qp = &nt->qp_vec[qp_num];
qp->qp_num = qp_num;
@@ -958,7 +956,7 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
mw_size = nt->mw_vec[mw_num].phys_size;
tx_size = (unsigned int)mw_size / num_qps_mw;
- qp_offset = tx_size * qp_num / mw_count;
+ qp_offset = tx_size * (qp_num / mw_count);
qp->tx_mw = nt->mw_vec[mw_num].vbase + qp_offset;
if (!qp->tx_mw)
@@ -1080,7 +1078,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
GFP_KERNEL, node);
if (!nt->qp_vec) {
rc = -ENOMEM;
- goto err2;
+ goto err1;
}
if (nt_debugfs_dir) {
@@ -1092,7 +1090,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
for (i = 0; i < qp_count; i++) {
rc = ntb_transport_init_queue(nt, i);
if (rc)
- goto err3;
+ goto err2;
}
INIT_DELAYED_WORK(&nt->link_work, ntb_transport_link_work);
@@ -1100,12 +1098,12 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
rc = ntb_set_ctx(ndev, nt, &ntb_transport_ops);
if (rc)
- goto err3;
+ goto err2;
INIT_LIST_HEAD(&nt->client_devs);
rc = ntb_bus_init(nt);
if (rc)
- goto err4;
+ goto err3;
nt->link_is_up = false;
ntb_link_enable(ndev, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
@@ -1113,17 +1111,16 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
return 0;
-err4:
- ntb_clear_ctx(ndev);
err3:
- kfree(nt->qp_vec);
+ ntb_clear_ctx(ndev);
err2:
- kfree(nt->mw_vec);
+ kfree(nt->qp_vec);
err1:
while (i--) {
mw = &nt->mw_vec[i];
iounmap(mw->vbase);
}
+ kfree(nt->mw_vec);
err:
kfree(nt);
return rc;
@@ -1931,13 +1928,11 @@ EXPORT_SYMBOL_GPL(ntb_transport_link_up);
*/
void ntb_transport_link_down(struct ntb_transport_qp *qp)
{
- struct pci_dev *pdev;
int val;
if (!qp)
return;
- pdev = qp->ndev->pdev;
qp->client_ready = false;
val = ntb_spad_read(qp->ndev, QP_LINKS);
@@ -1996,23 +1991,24 @@ EXPORT_SYMBOL_GPL(ntb_transport_qp_num);
*/
unsigned int ntb_transport_max_size(struct ntb_transport_qp *qp)
{
- unsigned int max;
+ unsigned int max_size;
unsigned int copy_align;
+ struct dma_chan *rx_chan, *tx_chan;
if (!qp)
return 0;
- if (!qp->tx_dma_chan && !qp->rx_dma_chan)
- return qp->tx_max_frame - sizeof(struct ntb_payload_header);
+ rx_chan = qp->rx_dma_chan;
+ tx_chan = qp->tx_dma_chan;
- copy_align = max(qp->tx_dma_chan->device->copy_align,
- qp->rx_dma_chan->device->copy_align);
+ copy_align = max(rx_chan ? rx_chan->device->copy_align : 0,
+ tx_chan ? tx_chan->device->copy_align : 0);
/* If DMA engine usage is possible, try to find the max size for that */
- max = qp->tx_max_frame - sizeof(struct ntb_payload_header);
- max -= max % (1 << copy_align);
+ max_size = qp->tx_max_frame - sizeof(struct ntb_payload_header);
+ max_size = round_down(max_size, 1 << copy_align);
- return max;
+ return max_size;
}
EXPORT_SYMBOL_GPL(ntb_transport_max_size);
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
index 0df77cb07df6..91a336ea8c4f 100644
--- a/drivers/nvdimm/blk.c
+++ b/drivers/nvdimm/blk.c
@@ -161,7 +161,7 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev,
return err;
}
-static void nd_blk_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
struct gendisk *disk = bdev->bd_disk;
@@ -208,6 +208,7 @@ static void nd_blk_make_request(struct request_queue *q, struct bio *bio)
out:
bio_endio(bio);
+ return BLK_QC_T_NONE;
}
static int nd_blk_rw_bytes(struct nd_namespace_common *ndns,
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 254239746020..efb2c1ceef98 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1150,7 +1150,7 @@ static int btt_do_bvec(struct btt *btt, struct bio_integrity_payload *bip,
return ret;
}
-static void btt_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
{
struct bio_integrity_payload *bip = bio_integrity(bio);
struct btt *btt = q->queuedata;
@@ -1198,6 +1198,7 @@ static void btt_make_request(struct request_queue *q, struct bio *bio)
out:
bio_endio(bio);
+ return BLK_QC_T_NONE;
}
static int btt_rw_page(struct block_device *bdev, sector_t sector,
@@ -1279,7 +1280,6 @@ static int btt_blk_init(struct btt *btt)
static void btt_blk_cleanup(struct btt *btt)
{
- blk_integrity_unregister(btt->btt_disk);
del_gendisk(btt->btt_disk);
put_disk(btt->btt_disk);
blk_cleanup_queue(btt->btt_queue);
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index cb62ec6a12d0..82c49bb87055 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -392,29 +392,18 @@ void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus)
EXPORT_SYMBOL_GPL(nvdimm_bus_unregister);
#ifdef CONFIG_BLK_DEV_INTEGRITY
-static int nd_pi_nop_generate_verify(struct blk_integrity_iter *iter)
-{
- return 0;
-}
-
int nd_integrity_init(struct gendisk *disk, unsigned long meta_size)
{
- struct blk_integrity integrity = {
- .name = "ND-PI-NOP",
- .generate_fn = nd_pi_nop_generate_verify,
- .verify_fn = nd_pi_nop_generate_verify,
- .tuple_size = meta_size,
- .tag_size = meta_size,
- };
- int ret;
+ struct blk_integrity bi;
if (meta_size == 0)
return 0;
- ret = blk_integrity_register(disk, &integrity);
- if (ret)
- return ret;
+ bi.profile = NULL;
+ bi.tuple_size = meta_size;
+ bi.tag_size = meta_size;
+ blk_integrity_register(disk, &bi);
blk_queue_max_integrity_segments(disk->queue, 1);
return 0;
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index 8282db2ef99e..b0045a505dc8 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -3,6 +3,7 @@
* Copyright (c) 2015, Intel Corporation.
*/
#include <linux/platform_device.h>
+#include <linux/memory_hotplug.h>
#include <linux/libnvdimm.h>
#include <linux/module.h>
@@ -25,6 +26,18 @@ static int e820_pmem_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_MEMORY_HOTPLUG
+static int e820_range_to_nid(resource_size_t addr)
+{
+ return memory_add_physaddr_to_nid(addr);
+}
+#else
+static int e820_range_to_nid(resource_size_t addr)
+{
+ return NUMA_NO_NODE;
+}
+#endif
+
static int e820_pmem_probe(struct platform_device *pdev)
{
static struct nvdimm_bus_descriptor nd_desc;
@@ -48,7 +61,7 @@ static int e820_pmem_probe(struct platform_device *pdev)
memset(&ndr_desc, 0, sizeof(ndr_desc));
ndr_desc.res = p;
ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
- ndr_desc.numa_node = NUMA_NO_NODE;
+ ndr_desc.numa_node = e820_range_to_nid(p->start);
set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
goto err;
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 0ba6a978f227..8ee79893d2f5 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -64,7 +64,7 @@ static void pmem_do_bvec(struct pmem_device *pmem, struct page *page,
kunmap_atomic(mem);
}
-static void pmem_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
{
bool do_acct;
unsigned long start;
@@ -84,6 +84,7 @@ static void pmem_make_request(struct request_queue *q, struct bio *bio)
wmb_pmem();
bio_endio(bio);
+ return BLK_QC_T_NONE;
}
static int pmem_rw_page(struct block_device *bdev, sector_t sector,
@@ -104,22 +105,11 @@ static long pmem_direct_access(struct block_device *bdev, sector_t sector,
{
struct pmem_device *pmem = bdev->bd_disk->private_data;
resource_size_t offset = sector * 512 + pmem->data_offset;
- resource_size_t size;
-
- if (pmem->data_offset) {
- /*
- * Limit the direct_access() size to what is covered by
- * the memmap
- */
- size = (pmem->size - offset) & ~ND_PFN_MASK;
- } else
- size = pmem->size - offset;
-
- /* FIXME convert DAX to comprehend that this mapping has a lifetime */
+
*kaddr = pmem->virt_addr + offset;
*pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
- return size;
+ return pmem->size - offset;
}
static const struct block_device_operations pmem_fops = {
@@ -150,18 +140,15 @@ static struct pmem_device *pmem_alloc(struct device *dev,
return ERR_PTR(-EBUSY);
}
- if (pmem_should_map_pages(dev)) {
- void *addr = devm_memremap_pages(dev, res);
+ if (pmem_should_map_pages(dev))
+ pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, res);
+ else
+ pmem->virt_addr = (void __pmem *) devm_memremap(dev,
+ pmem->phys_addr, pmem->size,
+ ARCH_MEMREMAP_PMEM);
- if (IS_ERR(addr))
- return addr;
- pmem->virt_addr = (void __pmem *) addr;
- } else {
- pmem->virt_addr = memremap_pmem(dev, pmem->phys_addr,
- pmem->size);
- if (!pmem->virt_addr)
- return ERR_PTR(-ENXIO);
- }
+ if (IS_ERR(pmem->virt_addr))
+ return (void __force *) pmem->virt_addr;
return pmem;
}
@@ -179,9 +166,10 @@ static void pmem_detach_disk(struct pmem_device *pmem)
static int pmem_attach_disk(struct device *dev,
struct nd_namespace_common *ndns, struct pmem_device *pmem)
{
+ int nid = dev_to_node(dev);
struct gendisk *disk;
- pmem->pmem_queue = blk_alloc_queue(GFP_KERNEL);
+ pmem->pmem_queue = blk_alloc_queue_node(GFP_KERNEL, nid);
if (!pmem->pmem_queue)
return -ENOMEM;
@@ -191,7 +179,7 @@ static int pmem_attach_disk(struct device *dev,
blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, pmem->pmem_queue);
- disk = alloc_disk(0);
+ disk = alloc_disk_node(0, nid);
if (!disk) {
blk_cleanup_queue(pmem->pmem_queue);
return -ENOMEM;
@@ -363,8 +351,8 @@ static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
/* establish pfn range for lookup, and switch to direct map */
pmem = dev_get_drvdata(dev);
- memunmap_pmem(dev, pmem->virt_addr);
- pmem->virt_addr = (void __pmem *)devm_memremap_pages(dev, &nsio->res);
+ devm_memunmap(dev, (void __force *) pmem->virt_addr);
+ pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, &nsio->res);
if (IS_ERR(pmem->virt_addr)) {
rc = PTR_ERR(pmem->virt_addr);
goto err;
diff --git a/drivers/nvme/Kconfig b/drivers/nvme/Kconfig
new file mode 100644
index 000000000000..a39d9431eaec
--- /dev/null
+++ b/drivers/nvme/Kconfig
@@ -0,0 +1 @@
+source "drivers/nvme/host/Kconfig"
diff --git a/drivers/nvme/Makefile b/drivers/nvme/Makefile
new file mode 100644
index 000000000000..9421e829d2a9
--- /dev/null
+++ b/drivers/nvme/Makefile
@@ -0,0 +1,2 @@
+
+obj-y += host/
diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
new file mode 100644
index 000000000000..002a94abdbc4
--- /dev/null
+++ b/drivers/nvme/host/Kconfig
@@ -0,0 +1,10 @@
+config BLK_DEV_NVME
+ tristate "NVM Express block device"
+ depends on PCI && BLOCK
+ ---help---
+ The NVM Express driver is for solid state drives directly
+ connected to the PCI or PCI Express bus. If you know you
+ don't have one of these, it is safe to answer N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called nvme.
diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile
new file mode 100644
index 000000000000..219dc206fa5f
--- /dev/null
+++ b/drivers/nvme/host/Makefile
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
+
+nvme-y += pci.o scsi.o lightnvm.o
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
new file mode 100644
index 000000000000..e0b7b95813bc
--- /dev/null
+++ b/drivers/nvme/host/lightnvm.c
@@ -0,0 +1,526 @@
+/*
+ * nvme-lightnvm.c - LightNVM NVMe device
+ *
+ * Copyright (C) 2014-2015 IT University of Copenhagen
+ * Initial release: Matias Bjorling <mb@lightnvm.io>
+ *
+ * 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ */
+
+#include "nvme.h"
+
+#ifdef CONFIG_NVM
+
+#include <linux/nvme.h>
+#include <linux/bitops.h>
+#include <linux/lightnvm.h>
+#include <linux/vmalloc.h>
+
+enum nvme_nvm_admin_opcode {
+ nvme_nvm_admin_identity = 0xe2,
+ nvme_nvm_admin_get_l2p_tbl = 0xea,
+ nvme_nvm_admin_get_bb_tbl = 0xf2,
+ nvme_nvm_admin_set_bb_tbl = 0xf1,
+};
+
+struct nvme_nvm_hb_rw {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u64 rsvd2;
+ __le64 metadata;
+ __le64 prp1;
+ __le64 prp2;
+ __le64 spba;
+ __le16 length;
+ __le16 control;
+ __le32 dsmgmt;
+ __le64 slba;
+};
+
+struct nvme_nvm_ph_rw {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u64 rsvd2;
+ __le64 metadata;
+ __le64 prp1;
+ __le64 prp2;
+ __le64 spba;
+ __le16 length;
+ __le16 control;
+ __le32 dsmgmt;
+ __le64 resv;
+};
+
+struct nvme_nvm_identity {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u64 rsvd[2];
+ __le64 prp1;
+ __le64 prp2;
+ __le32 chnl_off;
+ __u32 rsvd11[5];
+};
+
+struct nvme_nvm_l2ptbl {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __le32 cdw2[4];
+ __le64 prp1;
+ __le64 prp2;
+ __le64 slba;
+ __le32 nlb;
+ __le16 cdw14[6];
+};
+
+struct nvme_nvm_bbtbl {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u64 rsvd[2];
+ __le64 prp1;
+ __le64 prp2;
+ __le32 prp1_len;
+ __le32 prp2_len;
+ __le32 lbb;
+ __u32 rsvd11[3];
+};
+
+struct nvme_nvm_erase_blk {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u64 rsvd[2];
+ __le64 prp1;
+ __le64 prp2;
+ __le64 spba;
+ __le16 length;
+ __le16 control;
+ __le32 dsmgmt;
+ __le64 resv;
+};
+
+struct nvme_nvm_command {
+ union {
+ struct nvme_common_command common;
+ struct nvme_nvm_identity identity;
+ struct nvme_nvm_hb_rw hb_rw;
+ struct nvme_nvm_ph_rw ph_rw;
+ struct nvme_nvm_l2ptbl l2p;
+ struct nvme_nvm_bbtbl get_bb;
+ struct nvme_nvm_bbtbl set_bb;
+ struct nvme_nvm_erase_blk erase;
+ };
+};
+
+struct nvme_nvm_id_group {
+ __u8 mtype;
+ __u8 fmtype;
+ __le16 res16;
+ __u8 num_ch;
+ __u8 num_lun;
+ __u8 num_pln;
+ __le16 num_blk;
+ __le16 num_pg;
+ __le16 fpg_sz;
+ __le16 csecs;
+ __le16 sos;
+ __le32 trdt;
+ __le32 trdm;
+ __le32 tprt;
+ __le32 tprm;
+ __le32 tbet;
+ __le32 tbem;
+ __le32 mpos;
+ __le16 cpar;
+ __u8 reserved[913];
+} __packed;
+
+struct nvme_nvm_addr_format {
+ __u8 ch_offset;
+ __u8 ch_len;
+ __u8 lun_offset;
+ __u8 lun_len;
+ __u8 pln_offset;
+ __u8 pln_len;
+ __u8 blk_offset;
+ __u8 blk_len;
+ __u8 pg_offset;
+ __u8 pg_len;
+ __u8 sect_offset;
+ __u8 sect_len;
+ __u8 res[4];
+} __packed;
+
+struct nvme_nvm_id {
+ __u8 ver_id;
+ __u8 vmnt;
+ __u8 cgrps;
+ __u8 res[5];
+ __le32 cap;
+ __le32 dom;
+ struct nvme_nvm_addr_format ppaf;
+ __u8 ppat;
+ __u8 resv[223];
+ struct nvme_nvm_id_group groups[4];
+} __packed;
+
+/*
+ * Check we didn't inadvertently grow the command struct
+ */
+static inline void _nvme_nvm_check_size(void)
+{
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_identity) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_hb_rw) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_ph_rw) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_bbtbl) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_l2ptbl) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_erase_blk) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_id_group) != 960);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_addr_format) != 128);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_id) != 4096);
+}
+
+static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
+{
+ struct nvme_nvm_id_group *src;
+ struct nvm_id_group *dst;
+ int i, end;
+
+ end = min_t(u32, 4, nvm_id->cgrps);
+
+ for (i = 0; i < end; i++) {
+ src = &nvme_nvm_id->groups[i];
+ dst = &nvm_id->groups[i];
+
+ dst->mtype = src->mtype;
+ dst->fmtype = src->fmtype;
+ dst->num_ch = src->num_ch;
+ dst->num_lun = src->num_lun;
+ dst->num_pln = src->num_pln;
+
+ dst->num_pg = le16_to_cpu(src->num_pg);
+ dst->num_blk = le16_to_cpu(src->num_blk);
+ dst->fpg_sz = le16_to_cpu(src->fpg_sz);
+ dst->csecs = le16_to_cpu(src->csecs);
+ dst->sos = le16_to_cpu(src->sos);
+
+ dst->trdt = le32_to_cpu(src->trdt);
+ dst->trdm = le32_to_cpu(src->trdm);
+ dst->tprt = le32_to_cpu(src->tprt);
+ dst->tprm = le32_to_cpu(src->tprm);
+ dst->tbet = le32_to_cpu(src->tbet);
+ dst->tbem = le32_to_cpu(src->tbem);
+ dst->mpos = le32_to_cpu(src->mpos);
+
+ dst->cpar = le16_to_cpu(src->cpar);
+ }
+
+ return 0;
+}
+
+static int nvme_nvm_identity(struct request_queue *q, struct nvm_id *nvm_id)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct nvme_nvm_id *nvme_nvm_id;
+ struct nvme_nvm_command c = {};
+ int ret;
+
+ c.identity.opcode = nvme_nvm_admin_identity;
+ c.identity.nsid = cpu_to_le32(ns->ns_id);
+ c.identity.chnl_off = 0;
+
+ nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
+ if (!nvme_nvm_id)
+ return -ENOMEM;
+
+ ret = nvme_submit_sync_cmd(q, (struct nvme_command *)&c, nvme_nvm_id,
+ sizeof(struct nvme_nvm_id));
+ if (ret) {
+ ret = -EIO;
+ goto out;
+ }
+
+ nvm_id->ver_id = nvme_nvm_id->ver_id;
+ nvm_id->vmnt = nvme_nvm_id->vmnt;
+ nvm_id->cgrps = nvme_nvm_id->cgrps;
+ nvm_id->cap = le32_to_cpu(nvme_nvm_id->cap);
+ nvm_id->dom = le32_to_cpu(nvme_nvm_id->dom);
+
+ ret = init_grps(nvm_id, nvme_nvm_id);
+out:
+ kfree(nvme_nvm_id);
+ return ret;
+}
+
+static int nvme_nvm_get_l2p_tbl(struct request_queue *q, u64 slba, u32 nlb,
+ nvm_l2p_update_fn *update_l2p, void *priv)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct nvme_dev *dev = ns->dev;
+ struct nvme_nvm_command c = {};
+ u32 len = queue_max_hw_sectors(q) << 9;
+ u32 nlb_pr_rq = len / sizeof(u64);
+ u64 cmd_slba = slba;
+ void *entries;
+ int ret = 0;
+
+ c.l2p.opcode = nvme_nvm_admin_get_l2p_tbl;
+ c.l2p.nsid = cpu_to_le32(ns->ns_id);
+ entries = kmalloc(len, GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ while (nlb) {
+ u32 cmd_nlb = min(nlb_pr_rq, nlb);
+
+ c.l2p.slba = cpu_to_le64(cmd_slba);
+ c.l2p.nlb = cpu_to_le32(cmd_nlb);
+
+ ret = nvme_submit_sync_cmd(q, (struct nvme_command *)&c,
+ entries, len);
+ if (ret) {
+ dev_err(dev->dev, "L2P table transfer failed (%d)\n",
+ ret);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (update_l2p(cmd_slba, cmd_nlb, entries, priv)) {
+ ret = -EINTR;
+ goto out;
+ }
+
+ cmd_slba += cmd_nlb;
+ nlb -= cmd_nlb;
+ }
+
+out:
+ kfree(entries);
+ return ret;
+}
+
+static int nvme_nvm_get_bb_tbl(struct request_queue *q, int lunid,
+ unsigned int nr_blocks,
+ nvm_bb_update_fn *update_bbtbl, void *priv)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct nvme_dev *dev = ns->dev;
+ struct nvme_nvm_command c = {};
+ void *bb_bitmap;
+ u16 bb_bitmap_size;
+ int ret = 0;
+
+ c.get_bb.opcode = nvme_nvm_admin_get_bb_tbl;
+ c.get_bb.nsid = cpu_to_le32(ns->ns_id);
+ c.get_bb.lbb = cpu_to_le32(lunid);
+ bb_bitmap_size = ((nr_blocks >> 15) + 1) * PAGE_SIZE;
+ bb_bitmap = kmalloc(bb_bitmap_size, GFP_KERNEL);
+ if (!bb_bitmap)
+ return -ENOMEM;
+
+ bitmap_zero(bb_bitmap, nr_blocks);
+
+ ret = nvme_submit_sync_cmd(q, (struct nvme_command *)&c, bb_bitmap,
+ bb_bitmap_size);
+ if (ret) {
+ dev_err(dev->dev, "get bad block table failed (%d)\n", ret);
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = update_bbtbl(lunid, bb_bitmap, nr_blocks, priv);
+ if (ret) {
+ ret = -EINTR;
+ goto out;
+ }
+
+out:
+ kfree(bb_bitmap);
+ return ret;
+}
+
+static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd,
+ struct nvme_ns *ns, struct nvme_nvm_command *c)
+{
+ c->ph_rw.opcode = rqd->opcode;
+ c->ph_rw.nsid = cpu_to_le32(ns->ns_id);
+ c->ph_rw.spba = cpu_to_le64(rqd->ppa_addr.ppa);
+ c->ph_rw.control = cpu_to_le16(rqd->flags);
+ c->ph_rw.length = cpu_to_le16(rqd->nr_pages - 1);
+
+ if (rqd->opcode == NVM_OP_HBWRITE || rqd->opcode == NVM_OP_HBREAD)
+ c->hb_rw.slba = cpu_to_le64(nvme_block_nr(ns,
+ rqd->bio->bi_iter.bi_sector));
+}
+
+static void nvme_nvm_end_io(struct request *rq, int error)
+{
+ struct nvm_rq *rqd = rq->end_io_data;
+ struct nvm_dev *dev = rqd->dev;
+
+ if (dev->mt->end_io(rqd, error))
+ pr_err("nvme: err status: %x result: %lx\n",
+ rq->errors, (unsigned long)rq->special);
+
+ kfree(rq->cmd);
+ blk_mq_free_request(rq);
+}
+
+static int nvme_nvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct request *rq;
+ struct bio *bio = rqd->bio;
+ struct nvme_nvm_command *cmd;
+
+ rq = blk_mq_alloc_request(q, bio_rw(bio), GFP_KERNEL, 0);
+ if (IS_ERR(rq))
+ return -ENOMEM;
+
+ cmd = kzalloc(sizeof(struct nvme_nvm_command), GFP_KERNEL);
+ if (!cmd) {
+ blk_mq_free_request(rq);
+ return -ENOMEM;
+ }
+
+ rq->cmd_type = REQ_TYPE_DRV_PRIV;
+ rq->ioprio = bio_prio(bio);
+
+ if (bio_has_data(bio))
+ rq->nr_phys_segments = bio_phys_segments(q, bio);
+
+ rq->__data_len = bio->bi_iter.bi_size;
+ rq->bio = rq->biotail = bio;
+
+ nvme_nvm_rqtocmd(rq, rqd, ns, cmd);
+
+ rq->cmd = (unsigned char *)cmd;
+ rq->cmd_len = sizeof(struct nvme_nvm_command);
+ rq->special = (void *)0;
+
+ rq->end_io_data = rqd;
+
+ blk_execute_rq_nowait(q, NULL, rq, 0, nvme_nvm_end_io);
+
+ return 0;
+}
+
+static int nvme_nvm_erase_block(struct request_queue *q, struct nvm_rq *rqd)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct nvme_nvm_command c = {};
+
+ c.erase.opcode = NVM_OP_ERASE;
+ c.erase.nsid = cpu_to_le32(ns->ns_id);
+ c.erase.spba = cpu_to_le64(rqd->ppa_addr.ppa);
+ c.erase.length = cpu_to_le16(rqd->nr_pages - 1);
+
+ return nvme_submit_sync_cmd(q, (struct nvme_command *)&c, NULL, 0);
+}
+
+static void *nvme_nvm_create_dma_pool(struct request_queue *q, char *name)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct nvme_dev *dev = ns->dev;
+
+ return dma_pool_create(name, dev->dev, PAGE_SIZE, PAGE_SIZE, 0);
+}
+
+static void nvme_nvm_destroy_dma_pool(void *pool)
+{
+ struct dma_pool *dma_pool = pool;
+
+ dma_pool_destroy(dma_pool);
+}
+
+static void *nvme_nvm_dev_dma_alloc(struct request_queue *q, void *pool,
+ gfp_t mem_flags, dma_addr_t *dma_handler)
+{
+ return dma_pool_alloc(pool, mem_flags, dma_handler);
+}
+
+static void nvme_nvm_dev_dma_free(void *pool, void *ppa_list,
+ dma_addr_t dma_handler)
+{
+ dma_pool_free(pool, ppa_list, dma_handler);
+}
+
+static struct nvm_dev_ops nvme_nvm_dev_ops = {
+ .identity = nvme_nvm_identity,
+
+ .get_l2p_tbl = nvme_nvm_get_l2p_tbl,
+
+ .get_bb_tbl = nvme_nvm_get_bb_tbl,
+
+ .submit_io = nvme_nvm_submit_io,
+ .erase_block = nvme_nvm_erase_block,
+
+ .create_dma_pool = nvme_nvm_create_dma_pool,
+ .destroy_dma_pool = nvme_nvm_destroy_dma_pool,
+ .dev_dma_alloc = nvme_nvm_dev_dma_alloc,
+ .dev_dma_free = nvme_nvm_dev_dma_free,
+
+ .max_phys_sect = 64,
+};
+
+int nvme_nvm_register(struct request_queue *q, char *disk_name)
+{
+ return nvm_register(q, disk_name, &nvme_nvm_dev_ops);
+}
+
+void nvme_nvm_unregister(struct request_queue *q, char *disk_name)
+{
+ nvm_unregister(disk_name);
+}
+
+int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id)
+{
+ struct nvme_dev *dev = ns->dev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+ /* QEMU NVMe simulator - PCI ID + Vendor specific bit */
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x5845 &&
+ id->vs[0] == 0x1)
+ return 1;
+
+ /* CNEX Labs - PCI ID + Vendor specific bit */
+ if (pdev->vendor == 0x1d1d && pdev->device == 0x2807 &&
+ id->vs[0] == 0x1)
+ return 1;
+
+ return 0;
+}
+#else
+int nvme_nvm_register(struct request_queue *q, char *disk_name)
+{
+ return 0;
+}
+void nvme_nvm_unregister(struct request_queue *q, char *disk_name) {};
+int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id)
+{
+ return 0;
+}
+#endif /* CONFIG_NVM */
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
new file mode 100644
index 000000000000..fdb4e5bad9ac
--- /dev/null
+++ b/drivers/nvme/host/nvme.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011-2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _NVME_H
+#define _NVME_H
+
+#include <linux/nvme.h>
+#include <linux/pci.h>
+#include <linux/kref.h>
+#include <linux/blk-mq.h>
+
+extern unsigned char nvme_io_timeout;
+#define NVME_IO_TIMEOUT (nvme_io_timeout * HZ)
+
+enum {
+ NVME_NS_LBA = 0,
+ NVME_NS_LIGHTNVM = 1,
+};
+
+/*
+ * Represents an NVM Express device. Each nvme_dev is a PCI function.
+ */
+struct nvme_dev {
+ struct list_head node;
+ struct nvme_queue **queues;
+ struct request_queue *admin_q;
+ struct blk_mq_tag_set tagset;
+ struct blk_mq_tag_set admin_tagset;
+ u32 __iomem *dbs;
+ struct device *dev;
+ struct dma_pool *prp_page_pool;
+ struct dma_pool *prp_small_pool;
+ int instance;
+ unsigned queue_count;
+ unsigned online_queues;
+ unsigned max_qid;
+ int q_depth;
+ u32 db_stride;
+ u32 ctrl_config;
+ struct msix_entry *entry;
+ struct nvme_bar __iomem *bar;
+ struct list_head namespaces;
+ struct kref kref;
+ struct device *device;
+ struct work_struct reset_work;
+ struct work_struct probe_work;
+ struct work_struct scan_work;
+ char name[12];
+ char serial[20];
+ char model[40];
+ char firmware_rev[8];
+ bool subsystem;
+ u32 max_hw_sectors;
+ u32 stripe_size;
+ u32 page_size;
+ void __iomem *cmb;
+ dma_addr_t cmb_dma_addr;
+ u64 cmb_size;
+ u32 cmbsz;
+ u16 oncs;
+ u16 abort_limit;
+ u8 event_limit;
+ u8 vwc;
+};
+
+/*
+ * An NVM Express namespace is equivalent to a SCSI LUN
+ */
+struct nvme_ns {
+ struct list_head list;
+
+ struct nvme_dev *dev;
+ struct request_queue *queue;
+ struct gendisk *disk;
+ struct kref kref;
+
+ unsigned ns_id;
+ int lba_shift;
+ u16 ms;
+ bool ext;
+ u8 pi_type;
+ int type;
+ u64 mode_select_num_blocks;
+ u32 mode_select_block_len;
+};
+
+/*
+ * The nvme_iod describes the data in an I/O, including the list of PRP
+ * entries. You can't see it in this data structure because C doesn't let
+ * me express that. Use nvme_alloc_iod to ensure there's enough space
+ * allocated to store the PRP list.
+ */
+struct nvme_iod {
+ unsigned long private; /* For the use of the submitter of the I/O */
+ int npages; /* In the PRP list. 0 means small pool in use */
+ int offset; /* Of PRP list */
+ int nents; /* Used in scatterlist */
+ int length; /* Of data, in bytes */
+ dma_addr_t first_dma;
+ struct scatterlist meta_sg[1]; /* metadata requires single contiguous buffer */
+ struct scatterlist sg[0];
+};
+
+static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector)
+{
+ return (sector >> (ns->lba_shift - 9));
+}
+
+int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
+ void *buf, unsigned bufflen);
+int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
+ void *buffer, void __user *ubuffer, unsigned bufflen,
+ u32 *result, unsigned timeout);
+int nvme_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl **id);
+int nvme_identify_ns(struct nvme_dev *dev, unsigned nsid,
+ struct nvme_id_ns **id);
+int nvme_get_log_page(struct nvme_dev *dev, struct nvme_smart_log **log);
+int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
+ dma_addr_t dma_addr, u32 *result);
+int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
+ dma_addr_t dma_addr, u32 *result);
+
+struct sg_io_hdr;
+
+int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr);
+int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg);
+int nvme_sg_get_version_num(int __user *ip);
+
+int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id);
+int nvme_nvm_register(struct request_queue *q, char *disk_name);
+void nvme_nvm_unregister(struct request_queue *q, char *disk_name);
+
+#endif /* _NVME_H */
diff --git a/drivers/block/nvme-core.c b/drivers/nvme/host/pci.c
index 6f04771f1019..8187df204695 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/nvme/host/pci.c
@@ -12,7 +12,6 @@
* more details.
*/
-#include <linux/nvme.h>
#include <linux/bitops.h>
#include <linux/blkdev.h>
#include <linux/blk-mq.h>
@@ -40,8 +39,13 @@
#include <linux/slab.h>
#include <linux/t10-pi.h>
#include <linux/types.h>
+#include <linux/pr.h>
#include <scsi/sg.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <asm/unaligned.h>
+
+#include <uapi/linux/nvme_ioctl.h>
+#include "nvme.h"
#define NVME_MINORS (1U << MINORBITS)
#define NVME_Q_DEPTH 1024
@@ -84,9 +88,10 @@ static wait_queue_head_t nvme_kthread_wait;
static struct class *nvme_class;
-static void nvme_reset_failed_dev(struct work_struct *ws);
+static int __nvme_reset(struct nvme_dev *dev);
static int nvme_reset(struct nvme_dev *dev);
-static int nvme_process_cq(struct nvme_queue *nvmeq);
+static void nvme_process_cq(struct nvme_queue *nvmeq);
+static void nvme_dead_ctrl(struct nvme_dev *dev);
struct async_cmd_info {
struct kthread_work work;
@@ -535,7 +540,7 @@ static void nvme_dif_remap(struct request *req,
virt = bip_get_seed(bip);
phys = nvme_block_nr(ns, blk_rq_pos(req));
nlb = (blk_rq_bytes(req) >> ns->lba_shift);
- ts = ns->disk->integrity->tuple_size;
+ ts = ns->disk->queue->integrity.tuple_size;
for (i = 0; i < nlb; i++, virt++, phys++) {
pi = (struct t10_pi_tuple *)p;
@@ -545,36 +550,20 @@ static void nvme_dif_remap(struct request *req,
kunmap_atomic(pmap);
}
-static int nvme_noop_verify(struct blk_integrity_iter *iter)
-{
- return 0;
-}
-
-static int nvme_noop_generate(struct blk_integrity_iter *iter)
-{
- return 0;
-}
-
-struct blk_integrity nvme_meta_noop = {
- .name = "NVME_META_NOOP",
- .generate_fn = nvme_noop_generate,
- .verify_fn = nvme_noop_verify,
-};
-
static void nvme_init_integrity(struct nvme_ns *ns)
{
struct blk_integrity integrity;
switch (ns->pi_type) {
case NVME_NS_DPS_PI_TYPE3:
- integrity = t10_pi_type3_crc;
+ integrity.profile = &t10_pi_type3_crc;
break;
case NVME_NS_DPS_PI_TYPE1:
case NVME_NS_DPS_PI_TYPE2:
- integrity = t10_pi_type1_crc;
+ integrity.profile = &t10_pi_type1_crc;
break;
default:
- integrity = nvme_meta_noop;
+ integrity.profile = NULL;
break;
}
integrity.tuple_size = ns->ms;
@@ -603,27 +592,31 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
struct nvme_iod *iod = ctx;
struct request *req = iod_get_private(iod);
struct nvme_cmd_info *cmd_rq = blk_mq_rq_to_pdu(req);
-
u16 status = le16_to_cpup(&cqe->status) >> 1;
+ bool requeue = false;
+ int error = 0;
if (unlikely(status)) {
if (!(status & NVME_SC_DNR || blk_noretry_request(req))
&& (jiffies - req->start_time) < req->timeout) {
unsigned long flags;
+ requeue = true;
blk_mq_requeue_request(req);
spin_lock_irqsave(req->q->queue_lock, flags);
if (!blk_queue_stopped(req->q))
blk_mq_kick_requeue_list(req->q);
spin_unlock_irqrestore(req->q->queue_lock, flags);
- return;
+ goto release_iod;
}
if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
if (cmd_rq->ctx == CMD_CTX_CANCELLED)
- status = -EINTR;
+ error = -EINTR;
+ else
+ error = status;
} else {
- status = nvme_error_status(status);
+ error = nvme_error_status(status);
}
}
@@ -635,8 +628,9 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
if (cmd_rq->aborted)
dev_warn(nvmeq->dev->dev,
"completing aborted command with status:%04x\n",
- status);
+ error);
+release_iod:
if (iod->nents) {
dma_unmap_sg(nvmeq->dev->dev, iod->sg, iod->nents,
rq_data_dir(req) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
@@ -649,7 +643,8 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
}
nvme_free_iod(nvmeq->dev, iod);
- blk_mq_complete_request(req, status);
+ if (likely(!requeue))
+ blk_mq_complete_request(req, error);
}
/* length is in bytes. gfp flags indicates whether we may sleep. */
@@ -940,7 +935,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_MQ_RQ_QUEUE_BUSY;
}
-static int nvme_process_cq(struct nvme_queue *nvmeq)
+static void __nvme_process_cq(struct nvme_queue *nvmeq, unsigned int *tag)
{
u16 head, phase;
@@ -958,6 +953,8 @@ static int nvme_process_cq(struct nvme_queue *nvmeq)
head = 0;
phase = !phase;
}
+ if (tag && *tag == cqe.command_id)
+ *tag = -1;
ctx = nvme_finish_cmd(nvmeq, cqe.command_id, &fn);
fn(nvmeq, ctx, &cqe);
}
@@ -969,14 +966,18 @@ static int nvme_process_cq(struct nvme_queue *nvmeq)
* a big problem.
*/
if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
- return 0;
+ return;
writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
nvmeq->cq_head = head;
nvmeq->cq_phase = phase;
nvmeq->cqe_seen = 1;
- return 1;
+}
+
+static void nvme_process_cq(struct nvme_queue *nvmeq)
+{
+ __nvme_process_cq(nvmeq, NULL);
}
static irqreturn_t nvme_irq(int irq, void *data)
@@ -1000,6 +1001,23 @@ static irqreturn_t nvme_irq_check(int irq, void *data)
return IRQ_WAKE_THREAD;
}
+static int nvme_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag)
+{
+ struct nvme_queue *nvmeq = hctx->driver_data;
+
+ if ((le16_to_cpu(nvmeq->cqes[nvmeq->cq_head].status) & 1) ==
+ nvmeq->cq_phase) {
+ spin_lock_irq(&nvmeq->q_lock);
+ __nvme_process_cq(nvmeq, &tag);
+ spin_unlock_irq(&nvmeq->q_lock);
+
+ if (tag == -1)
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Returns 0 on success. If the result is negative, it's a Linux error code;
* if the result is positive, it's an NVM Express status code
@@ -1030,11 +1048,13 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
req->special = (void *)0;
if (buffer && bufflen) {
- ret = blk_rq_map_kern(q, req, buffer, bufflen, __GFP_WAIT);
+ ret = blk_rq_map_kern(q, req, buffer, bufflen,
+ __GFP_DIRECT_RECLAIM);
if (ret)
goto out;
} else if (ubuffer && bufflen) {
- ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen, __GFP_WAIT);
+ ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
+ __GFP_DIRECT_RECLAIM);
if (ret)
goto out;
bio = req->bio;
@@ -1277,18 +1297,13 @@ static void nvme_abort_req(struct request *req)
struct nvme_command cmd;
if (!nvmeq->qid || cmd_rq->aborted) {
- unsigned long flags;
-
- spin_lock_irqsave(&dev_list_lock, flags);
- if (work_busy(&dev->reset_work))
- goto out;
- list_del_init(&dev->node);
- dev_warn(dev->dev, "I/O %d QID %d timeout, reset controller\n",
- req->tag, nvmeq->qid);
- dev->reset_workfn = nvme_reset_failed_dev;
- queue_work(nvme_workq, &dev->reset_work);
- out:
- spin_unlock_irqrestore(&dev_list_lock, flags);
+ spin_lock(&dev_list_lock);
+ if (!__nvme_reset(dev)) {
+ dev_warn(dev->dev,
+ "I/O %d QID %d timeout, reset controller\n",
+ req->tag, nvmeq->qid);
+ }
+ spin_unlock(&dev_list_lock);
return;
}
@@ -1664,6 +1679,7 @@ static struct blk_mq_ops nvme_mq_ops = {
.init_hctx = nvme_init_hctx,
.init_request = nvme_init_request,
.timeout = nvme_timeout,
+ .poll = nvme_poll,
};
static void nvme_dev_remove_admin(struct nvme_dev *dev)
@@ -1709,7 +1725,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
{
int result;
u32 aqa;
- u64 cap = readq(&dev->bar->cap);
+ u64 cap = lo_hi_readq(&dev->bar->cap);
struct nvme_queue *nvmeq;
unsigned page_shift = PAGE_SHIFT;
unsigned dev_page_min = NVME_CAP_MPSMIN(cap) + 12;
@@ -1758,8 +1774,8 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
writel(aqa, &dev->bar->aqa);
- writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
- writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
+ lo_hi_writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
+ lo_hi_writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
result = nvme_enable_ctrl(dev, cap);
if (result)
@@ -1804,7 +1820,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
length = (io.nblocks + 1) << ns->lba_shift;
meta_len = (io.nblocks + 1) * ns->ms;
- metadata = (void __user *)(unsigned long)io.metadata;
+ metadata = (void __user *)(uintptr_t)io.metadata;
write = io.opcode & 1;
if (ns->ext) {
@@ -1844,7 +1860,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
c.rw.metadata = cpu_to_le64(meta_dma);
status = __nvme_submit_sync_cmd(ns->queue, &c, NULL,
- (void __user *)io.addr, length, NULL, 0);
+ (void __user *)(uintptr_t)io.addr, length, NULL, 0);
unmap:
if (meta) {
if (status == NVME_SC_SUCCESS && !write) {
@@ -1886,7 +1902,7 @@ static int nvme_user_cmd(struct nvme_dev *dev, struct nvme_ns *ns,
timeout = msecs_to_jiffies(cmd.timeout_ms);
status = __nvme_submit_sync_cmd(ns ? ns->queue : dev->admin_q, &c,
- NULL, (void __user *)cmd.addr, cmd.data_len,
+ NULL, (void __user *)(uintptr_t)cmd.addr, cmd.data_len,
&cmd.result, timeout);
if (status >= 0) {
if (put_user(cmd.result, &ucmd->result))
@@ -1943,6 +1959,23 @@ static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode,
#define nvme_compat_ioctl NULL
#endif
+static void nvme_free_dev(struct kref *kref);
+static void nvme_free_ns(struct kref *kref)
+{
+ struct nvme_ns *ns = container_of(kref, struct nvme_ns, kref);
+
+ if (ns->type == NVME_NS_LIGHTNVM)
+ nvme_nvm_unregister(ns->queue, ns->disk->disk_name);
+
+ spin_lock(&dev_list_lock);
+ ns->disk->private_data = NULL;
+ spin_unlock(&dev_list_lock);
+
+ kref_put(&ns->dev->kref, nvme_free_dev);
+ put_disk(ns->disk);
+ kfree(ns);
+}
+
static int nvme_open(struct block_device *bdev, fmode_t mode)
{
int ret = 0;
@@ -1952,21 +1985,17 @@ static int nvme_open(struct block_device *bdev, fmode_t mode)
ns = bdev->bd_disk->private_data;
if (!ns)
ret = -ENXIO;
- else if (!kref_get_unless_zero(&ns->dev->kref))
+ else if (!kref_get_unless_zero(&ns->kref))
ret = -ENXIO;
spin_unlock(&dev_list_lock);
return ret;
}
-static void nvme_free_dev(struct kref *kref);
-
static void nvme_release(struct gendisk *disk, fmode_t mode)
{
struct nvme_ns *ns = disk->private_data;
- struct nvme_dev *dev = ns->dev;
-
- kref_put(&dev->kref, nvme_free_dev);
+ kref_put(&ns->kref, nvme_free_ns);
}
static int nvme_getgeo(struct block_device *bd, struct hd_geometry *geo)
@@ -2007,6 +2036,16 @@ static int nvme_revalidate_disk(struct gendisk *disk)
return -ENODEV;
}
+ if (nvme_nvm_ns_supported(ns, id) && ns->type != NVME_NS_LIGHTNVM) {
+ if (nvme_nvm_register(ns->queue, disk->disk_name)) {
+ dev_warn(dev->dev,
+ "%s: LightNVM init failure\n", __func__);
+ kfree(id);
+ return -ENODEV;
+ }
+ ns->type = NVME_NS_LIGHTNVM;
+ }
+
old_ms = ns->ms;
lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
ns->lba_shift = id->lbaf[lbaf].ds;
@@ -2025,6 +2064,7 @@ static int nvme_revalidate_disk(struct gendisk *disk)
pi_type = ns->ms == sizeof(struct t10_pi_tuple) ?
id->dps & NVME_NS_DPS_PI_MASK : 0;
+ blk_mq_freeze_queue(disk->queue);
if (blk_get_integrity(disk) && (ns->pi_type != pi_type ||
ns->ms != old_ms ||
bs != queue_logical_block_size(disk->queue) ||
@@ -2034,22 +2074,116 @@ static int nvme_revalidate_disk(struct gendisk *disk)
ns->pi_type = pi_type;
blk_queue_logical_block_size(ns->queue, bs);
- if (ns->ms && !blk_get_integrity(disk) && (disk->flags & GENHD_FL_UP) &&
- !ns->ext)
+ if (ns->ms && !ns->ext)
nvme_init_integrity(ns);
- if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk))
+ if ((ns->ms && !(ns->ms == 8 && ns->pi_type) &&
+ !blk_get_integrity(disk)) ||
+ ns->type == NVME_NS_LIGHTNVM)
set_capacity(disk, 0);
else
set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
if (dev->oncs & NVME_CTRL_ONCS_DSM)
nvme_config_discard(ns);
+ blk_mq_unfreeze_queue(disk->queue);
kfree(id);
return 0;
}
+static char nvme_pr_type(enum pr_type type)
+{
+ switch (type) {
+ case PR_WRITE_EXCLUSIVE:
+ return 1;
+ case PR_EXCLUSIVE_ACCESS:
+ return 2;
+ case PR_WRITE_EXCLUSIVE_REG_ONLY:
+ return 3;
+ case PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ return 4;
+ case PR_WRITE_EXCLUSIVE_ALL_REGS:
+ return 5;
+ case PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ return 6;
+ default:
+ return 0;
+ }
+};
+
+static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
+ u64 key, u64 sa_key, u8 op)
+{
+ struct nvme_ns *ns = bdev->bd_disk->private_data;
+ struct nvme_command c;
+ u8 data[16] = { 0, };
+
+ put_unaligned_le64(key, &data[0]);
+ put_unaligned_le64(sa_key, &data[8]);
+
+ memset(&c, 0, sizeof(c));
+ c.common.opcode = op;
+ c.common.nsid = cpu_to_le32(ns->ns_id);
+ c.common.cdw10[0] = cpu_to_le32(cdw10);
+
+ return nvme_submit_sync_cmd(ns->queue, &c, data, 16);
+}
+
+static int nvme_pr_register(struct block_device *bdev, u64 old,
+ u64 new, unsigned flags)
+{
+ u32 cdw10;
+
+ if (flags & ~PR_FL_IGNORE_KEY)
+ return -EOPNOTSUPP;
+
+ cdw10 = old ? 2 : 0;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
+ cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
+ return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
+}
+
+static int nvme_pr_reserve(struct block_device *bdev, u64 key,
+ enum pr_type type, unsigned flags)
+{
+ u32 cdw10;
+
+ if (flags & ~PR_FL_IGNORE_KEY)
+ return -EOPNOTSUPP;
+
+ cdw10 = nvme_pr_type(type) << 8;
+ cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
+}
+
+static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
+ enum pr_type type, bool abort)
+{
+ u32 cdw10 = nvme_pr_type(type) << 8 | abort ? 2 : 1;
+ return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
+}
+
+static int nvme_pr_clear(struct block_device *bdev, u64 key)
+{
+ u32 cdw10 = 1 | (key ? 1 << 3 : 0);
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_register);
+}
+
+static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+{
+ u32 cdw10 = nvme_pr_type(type) << 8 | key ? 1 << 3 : 0;
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+}
+
+static const struct pr_ops nvme_pr_ops = {
+ .pr_register = nvme_pr_register,
+ .pr_reserve = nvme_pr_reserve,
+ .pr_release = nvme_pr_release,
+ .pr_preempt = nvme_pr_preempt,
+ .pr_clear = nvme_pr_clear,
+};
+
static const struct block_device_operations nvme_fops = {
.owner = THIS_MODULE,
.ioctl = nvme_ioctl,
@@ -2058,6 +2192,7 @@ static const struct block_device_operations nvme_fops = {
.release = nvme_release,
.getgeo = nvme_getgeo,
.revalidate_disk= nvme_revalidate_disk,
+ .pr_ops = &nvme_pr_ops,
};
static int nvme_kthread(void *data)
@@ -2073,14 +2208,11 @@ static int nvme_kthread(void *data)
if ((dev->subsystem && (csts & NVME_CSTS_NSSRO)) ||
csts & NVME_CSTS_CFS) {
- if (work_busy(&dev->reset_work))
- continue;
- list_del_init(&dev->node);
- dev_warn(dev->dev,
- "Failed status: %x, reset controller\n",
- readl(&dev->bar->csts));
- dev->reset_workfn = nvme_reset_failed_dev;
- queue_work(nvme_workq, &dev->reset_work);
+ if (!__nvme_reset(dev)) {
+ dev_warn(dev->dev,
+ "Failed status: %x, reset controller\n",
+ readl(&dev->bar->csts));
+ }
continue;
}
for (i = 0; i < dev->queue_count; i++) {
@@ -2126,6 +2258,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
if (!disk)
goto out_free_queue;
+ kref_init(&ns->kref);
ns->ns_id = nsid;
ns->disk = disk;
ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */
@@ -2162,17 +2295,20 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
if (nvme_revalidate_disk(ns->disk))
goto out_free_disk;
- add_disk(ns->disk);
- if (ns->ms) {
- struct block_device *bd = bdget_disk(ns->disk, 0);
- if (!bd)
- return;
- if (blkdev_get(bd, FMODE_READ, NULL)) {
- bdput(bd);
- return;
+ kref_get(&dev->kref);
+ if (ns->type != NVME_NS_LIGHTNVM) {
+ add_disk(ns->disk);
+ if (ns->ms) {
+ struct block_device *bd = bdget_disk(ns->disk, 0);
+ if (!bd)
+ return;
+ if (blkdev_get(bd, FMODE_READ, NULL)) {
+ bdput(bd);
+ return;
+ }
+ blkdev_reread_part(bd);
+ blkdev_put(bd, FMODE_READ);
}
- blkdev_reread_part(bd);
- blkdev_put(bd, FMODE_READ);
}
return;
out_free_disk:
@@ -2184,6 +2320,13 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
kfree(ns);
}
+/*
+ * Create I/O queues. Failing to create an I/O queue is not an issue,
+ * we can continue with less than the desired amount of queues, and
+ * even a controller without I/O queues an still be used to issue
+ * admin commands. This might be useful to upgrade a buggy firmware
+ * for example.
+ */
static void nvme_create_io_queues(struct nvme_dev *dev)
{
unsigned i;
@@ -2193,8 +2336,10 @@ static void nvme_create_io_queues(struct nvme_dev *dev)
break;
for (i = dev->online_queues; i <= dev->queue_count - 1; i++)
- if (nvme_create_queue(dev->queues[i], i))
+ if (nvme_create_queue(dev->queues[i], i)) {
+ nvme_free_queues(dev, i);
break;
+ }
}
static int set_queue_count(struct nvme_dev *dev, int count)
@@ -2357,18 +2502,6 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
return result;
}
-static void nvme_free_namespace(struct nvme_ns *ns)
-{
- list_del(&ns->list);
-
- spin_lock(&dev_list_lock);
- ns->disk->private_data = NULL;
- spin_unlock(&dev_list_lock);
-
- put_disk(ns->disk);
- kfree(ns);
-}
-
static int ns_cmp(void *priv, struct list_head *a, struct list_head *b)
{
struct nvme_ns *nsa = container_of(a, struct nvme_ns, list);
@@ -2402,15 +2535,14 @@ static void nvme_ns_remove(struct nvme_ns *ns)
if (kill)
blk_set_queue_dying(ns->queue);
- if (ns->disk->flags & GENHD_FL_UP) {
- if (blk_get_integrity(ns->disk))
- blk_integrity_unregister(ns->disk);
+ if (ns->disk->flags & GENHD_FL_UP)
del_gendisk(ns->disk);
- }
if (kill || !blk_queue_dying(ns->queue)) {
blk_mq_abort_requeue_list(ns->queue);
blk_cleanup_queue(ns->queue);
- }
+ }
+ list_del_init(&ns->list);
+ kref_put(&ns->kref, nvme_free_ns);
}
static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn)
@@ -2421,18 +2553,14 @@ static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn)
for (i = 1; i <= nn; i++) {
ns = nvme_find_ns(dev, i);
if (ns) {
- if (revalidate_disk(ns->disk)) {
+ if (revalidate_disk(ns->disk))
nvme_ns_remove(ns);
- nvme_free_namespace(ns);
- }
} else
nvme_alloc_ns(dev, i);
}
list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
- if (ns->ns_id > nn) {
+ if (ns->ns_id > nn)
nvme_ns_remove(ns);
- nvme_free_namespace(ns);
- }
}
list_sort(NULL, &dev->namespaces, ns_cmp);
}
@@ -2478,7 +2606,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
struct pci_dev *pdev = to_pci_dev(dev->dev);
int res;
struct nvme_id_ctrl *ctrl;
- int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
+ int shift = NVME_CAP_MPSMIN(lo_hi_readq(&dev->bar->cap)) + 12;
res = nvme_identify_ctrl(dev, &ctrl);
if (res) {
@@ -2494,6 +2622,8 @@ static int nvme_dev_add(struct nvme_dev *dev)
memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
if (ctrl->mdts)
dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
+ else
+ dev->max_hw_sectors = UINT_MAX;
if ((pdev->vendor == PCI_VENDOR_ID_INTEL) &&
(pdev->device == 0x0953) && ctrl->vs[3]) {
unsigned int max_hw_sectors;
@@ -2567,7 +2697,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
goto unmap;
}
- cap = readq(&dev->bar->cap);
+ cap = lo_hi_readq(&dev->bar->cap);
dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
dev->db_stride = 1 << NVME_CAP_STRIDE(cap);
dev->dbs = ((void __iomem *)dev->bar) + 4096;
@@ -2630,7 +2760,7 @@ static void nvme_wait_dq(struct nvme_delq_ctx *dq, struct nvme_dev *dev)
* queues than admin tags.
*/
set_current_state(TASK_RUNNING);
- nvme_disable_ctrl(dev, readq(&dev->bar->cap));
+ nvme_disable_ctrl(dev, lo_hi_readq(&dev->bar->cap));
nvme_clear_queue(dev->queues[0]);
flush_kthread_worker(dq->worker);
nvme_disable_queue(dev, 0);
@@ -2822,9 +2952,9 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
static void nvme_dev_remove(struct nvme_dev *dev)
{
- struct nvme_ns *ns;
+ struct nvme_ns *ns, *next;
- list_for_each_entry(ns, &dev->namespaces, list)
+ list_for_each_entry_safe(ns, next, &dev->namespaces, list)
nvme_ns_remove(ns);
}
@@ -2880,21 +3010,12 @@ static void nvme_release_instance(struct nvme_dev *dev)
spin_unlock(&dev_list_lock);
}
-static void nvme_free_namespaces(struct nvme_dev *dev)
-{
- struct nvme_ns *ns, *next;
-
- list_for_each_entry_safe(ns, next, &dev->namespaces, list)
- nvme_free_namespace(ns);
-}
-
static void nvme_free_dev(struct kref *kref)
{
struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
put_device(dev->dev);
put_device(dev->device);
- nvme_free_namespaces(dev);
nvme_release_instance(dev);
if (dev->tagset.tags)
blk_mq_free_tag_set(&dev->tagset);
@@ -2968,14 +3089,15 @@ static const struct file_operations nvme_dev_fops = {
.compat_ioctl = nvme_dev_ioctl,
};
-static int nvme_dev_start(struct nvme_dev *dev)
+static void nvme_probe_work(struct work_struct *work)
{
- int result;
+ struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work);
bool start_thread = false;
+ int result;
result = nvme_dev_map(dev);
if (result)
- return result;
+ goto out;
result = nvme_configure_admin_queue(dev);
if (result)
@@ -3010,7 +3132,20 @@ static int nvme_dev_start(struct nvme_dev *dev)
goto free_tags;
dev->event_limit = 1;
- return result;
+
+ /*
+ * Keep the controller around but remove all namespaces if we don't have
+ * any working I/O queue.
+ */
+ if (dev->online_queues < 2) {
+ dev_warn(dev->dev, "IO queues not created\n");
+ nvme_dev_remove(dev);
+ } else {
+ nvme_unfreeze_queues(dev);
+ nvme_dev_add(dev);
+ }
+
+ return;
free_tags:
nvme_dev_remove_admin(dev);
@@ -3022,7 +3157,9 @@ static int nvme_dev_start(struct nvme_dev *dev)
nvme_dev_list_remove(dev);
unmap:
nvme_dev_unmap(dev);
- return result;
+ out:
+ if (!work_busy(&dev->reset_work))
+ nvme_dead_ctrl(dev);
}
static int nvme_remove_dead_ctrl(void *arg)
@@ -3036,33 +3173,6 @@ static int nvme_remove_dead_ctrl(void *arg)
return 0;
}
-static void nvme_remove_disks(struct work_struct *ws)
-{
- struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
-
- nvme_free_queues(dev, 1);
- nvme_dev_remove(dev);
-}
-
-static int nvme_dev_resume(struct nvme_dev *dev)
-{
- int ret;
-
- ret = nvme_dev_start(dev);
- if (ret)
- return ret;
- if (dev->online_queues < 2) {
- spin_lock(&dev_list_lock);
- dev->reset_workfn = nvme_remove_disks;
- queue_work(nvme_workq, &dev->reset_work);
- spin_unlock(&dev_list_lock);
- } else {
- nvme_unfreeze_queues(dev);
- nvme_dev_add(dev);
- }
- return 0;
-}
-
static void nvme_dead_ctrl(struct nvme_dev *dev)
{
dev_warn(dev->dev, "Device failed to resume\n");
@@ -3075,8 +3185,9 @@ static void nvme_dead_ctrl(struct nvme_dev *dev)
}
}
-static void nvme_dev_reset(struct nvme_dev *dev)
+static void nvme_reset_work(struct work_struct *ws)
{
+ struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
bool in_probe = work_busy(&dev->probe_work);
nvme_dev_shutdown(dev);
@@ -3096,31 +3207,24 @@ static void nvme_dev_reset(struct nvme_dev *dev)
schedule_work(&dev->probe_work);
}
-static void nvme_reset_failed_dev(struct work_struct *ws)
-{
- struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
- nvme_dev_reset(dev);
-}
-
-static void nvme_reset_workfn(struct work_struct *work)
+static int __nvme_reset(struct nvme_dev *dev)
{
- struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
- dev->reset_workfn(work);
+ if (work_pending(&dev->reset_work))
+ return -EBUSY;
+ list_del_init(&dev->node);
+ queue_work(nvme_workq, &dev->reset_work);
+ return 0;
}
static int nvme_reset(struct nvme_dev *dev)
{
- int ret = -EBUSY;
+ int ret;
if (!dev->admin_q || blk_queue_dying(dev->admin_q))
return -ENODEV;
spin_lock(&dev_list_lock);
- if (!work_pending(&dev->reset_work)) {
- dev->reset_workfn = nvme_reset_failed_dev;
- queue_work(nvme_workq, &dev->reset_work);
- ret = 0;
- }
+ ret = __nvme_reset(dev);
spin_unlock(&dev_list_lock);
if (!ret) {
@@ -3147,7 +3251,6 @@ static ssize_t nvme_sysfs_reset(struct device *dev,
}
static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset);
-static void nvme_async_probe(struct work_struct *work);
static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int node, result = -ENOMEM;
@@ -3170,8 +3273,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto free;
INIT_LIST_HEAD(&dev->namespaces);
- dev->reset_workfn = nvme_reset_failed_dev;
- INIT_WORK(&dev->reset_work, nvme_reset_workfn);
+ INIT_WORK(&dev->reset_work, nvme_reset_work);
dev->dev = get_device(&pdev->dev);
pci_set_drvdata(pdev, dev);
result = nvme_set_instance(dev);
@@ -3199,7 +3301,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&dev->node);
INIT_WORK(&dev->scan_work, nvme_dev_scan);
- INIT_WORK(&dev->probe_work, nvme_async_probe);
+ INIT_WORK(&dev->probe_work, nvme_probe_work);
schedule_work(&dev->probe_work);
return 0;
@@ -3219,14 +3321,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return result;
}
-static void nvme_async_probe(struct work_struct *work)
-{
- struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work);
-
- if (nvme_dev_resume(dev) && !work_busy(&dev->reset_work))
- nvme_dead_ctrl(dev);
-}
-
static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
{
struct nvme_dev *dev = pci_get_drvdata(pdev);
@@ -3234,7 +3328,7 @@ static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
if (prepare)
nvme_dev_shutdown(dev);
else
- nvme_dev_resume(dev);
+ schedule_work(&dev->probe_work);
}
static void nvme_shutdown(struct pci_dev *pdev)
@@ -3288,10 +3382,7 @@ static int nvme_resume(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct nvme_dev *ndev = pci_get_drvdata(pdev);
- if (nvme_dev_resume(ndev) && !work_busy(&ndev->reset_work)) {
- ndev->reset_workfn = nvme_reset_failed_dev;
- queue_work(nvme_workq, &ndev->reset_work);
- }
+ schedule_work(&ndev->probe_work);
return 0;
}
#endif
@@ -3312,6 +3403,7 @@ static const struct pci_error_handlers nvme_err_handler = {
static const struct pci_device_id nvme_id_table[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, nvme_id_table);
diff --git a/drivers/block/nvme-scsi.c b/drivers/nvme/host/scsi.c
index e5a63f06fb0f..c3d8d3887a31 100644
--- a/drivers/block/nvme-scsi.c
+++ b/drivers/nvme/host/scsi.c
@@ -17,7 +17,6 @@
* each command is translated.
*/
-#include <linux/nvme.h>
#include <linux/bio.h>
#include <linux/bitops.h>
#include <linux/blkdev.h>
@@ -45,6 +44,7 @@
#include <scsi/sg.h>
#include <scsi/scsi.h>
+#include "nvme.h"
static int sg_version_num = 30534; /* 2 digits for each component */
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 8db297821f78..bc4ea585b42e 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -14,6 +14,28 @@ menuconfig NVMEM
if NVMEM
+config NVMEM_IMX_OCOTP
+ tristate "i.MX6 On-Chip OTP Controller support"
+ depends on SOC_IMX6
+ help
+ This is a driver for the On-Chip OTP Controller (OCOTP) available on
+ i.MX6 SoCs, providing access to 4 Kbits of one-time programmable
+ eFuses.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-imx-ocotp.
+
+config NVMEM_MXS_OCOTP
+ tristate "Freescale MXS On-Chip OTP Memory Support"
+ depends on ARCH_MXS || COMPILE_TEST
+ help
+ If you say Y here, you will get readonly access to the
+ One Time Programmable memory pages that are stored
+ on the Freescale i.MX23/i.MX28 processor.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-mxs-ocotp.
+
config QCOM_QFPROM
tristate "QCOM QFPROM Support"
depends on ARCH_QCOM || COMPILE_TEST
@@ -25,6 +47,16 @@ config QCOM_QFPROM
This driver can also be built as a module. If so, the module
will be called nvmem_qfprom.
+config ROCKCHIP_EFUSE
+ tristate "Rockchip eFuse Support"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ help
+ This is a simple drive to dump specified values of Rockchip SoC
+ from eFuse, such as cpu-leakage.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_rockchip_efuse.
+
config NVMEM_SUNXI_SID
tristate "Allwinner SoCs SID support"
depends on ARCH_SUNXI
@@ -36,4 +68,14 @@ config NVMEM_SUNXI_SID
This driver can also be built as a module. If so, the module
will be called nvmem_sunxi_sid.
+config NVMEM_VF610_OCOTP
+ tristate "VF610 SoC OCOTP support"
+ depends on SOC_VF610 || COMPILE_TEST
+ help
+ This is a driver for the 'OCOTP' peripheral available on Vybrid
+ devices like VF5xx and VF6xx.
+
+ This driver can also be build as a module. If so, the module will
+ be called nvmem-vf610-ocotp.
+
endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 4328b930ad9a..95dde3f8f085 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -6,7 +6,15 @@ obj-$(CONFIG_NVMEM) += nvmem_core.o
nvmem_core-y := core.o
# Devices
+obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
+nvmem-imx-ocotp-y := imx-ocotp.o
+obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o
+nvmem-mxs-ocotp-y := mxs-ocotp.o
obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
nvmem_qfprom-y := qfprom.o
+obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
+nvmem_rockchip_efuse-y := rockchip-efuse.o
obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
nvmem_sunxi_sid-y := sunxi_sid.o
+obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
+nvmem-vf610-ocotp-y := vf610-ocotp.o
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
new file mode 100644
index 000000000000..b7971d410b60
--- /dev/null
+++ b/drivers/nvmem/imx-ocotp.c
@@ -0,0 +1,154 @@
+/*
+ * i.MX6 OCOTP fusebox driver
+ *
+ * Copyright (c) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
+ *
+ * Based on the barebox ocotp driver,
+ * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>,
+ * Orex Computed Radiography
+ *
+ * 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.
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+struct ocotp_priv {
+ struct device *dev;
+ void __iomem *base;
+ unsigned int nregs;
+};
+
+static int imx_ocotp_read(void *context, const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct ocotp_priv *priv = context;
+ unsigned int offset = *(u32 *)reg;
+ unsigned int count;
+ int i;
+ u32 index;
+
+ index = offset >> 2;
+ count = val_size >> 2;
+
+ if (count > (priv->nregs - index))
+ count = priv->nregs - index;
+
+ for (i = index; i < (index + count); i++) {
+ *(u32 *)val = readl(priv->base + 0x400 + i * 0x10);
+ val += 4;
+ }
+
+ return (i - index) * 4;
+}
+
+static int imx_ocotp_write(void *context, const void *data, size_t count)
+{
+ /* Not implemented */
+ return 0;
+}
+
+static struct regmap_bus imx_ocotp_bus = {
+ .read = imx_ocotp_read,
+ .write = imx_ocotp_write,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static bool imx_ocotp_writeable_reg(struct device *dev, unsigned int reg)
+{
+ return false;
+}
+
+static struct regmap_config imx_ocotp_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .writeable_reg = imx_ocotp_writeable_reg,
+ .name = "imx-ocotp",
+};
+
+static struct nvmem_config imx_ocotp_nvmem_config = {
+ .name = "imx-ocotp",
+ .read_only = true,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id imx_ocotp_dt_ids[] = {
+ { .compatible = "fsl,imx6q-ocotp", (void *)128 },
+ { .compatible = "fsl,imx6sl-ocotp", (void *)32 },
+ { .compatible = "fsl,imx6sx-ocotp", (void *)128 },
+ { },
+};
+MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
+
+static int imx_ocotp_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct regmap *regmap;
+ struct ocotp_priv *priv;
+ struct nvmem_device *nvmem;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ of_id = of_match_device(imx_ocotp_dt_ids, dev);
+ priv->nregs = (unsigned int)of_id->data;
+ imx_ocotp_regmap_config.max_register = 4 * priv->nregs - 4;
+
+ regmap = devm_regmap_init(dev, &imx_ocotp_bus, priv,
+ &imx_ocotp_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "regmap init failed\n");
+ return PTR_ERR(regmap);
+ }
+ imx_ocotp_nvmem_config.dev = dev;
+ nvmem = nvmem_register(&imx_ocotp_nvmem_config);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ platform_set_drvdata(pdev, nvmem);
+
+ return 0;
+}
+
+static int imx_ocotp_remove(struct platform_device *pdev)
+{
+ struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+ return nvmem_unregister(nvmem);
+}
+
+static struct platform_driver imx_ocotp_driver = {
+ .probe = imx_ocotp_probe,
+ .remove = imx_ocotp_remove,
+ .driver = {
+ .name = "imx_ocotp",
+ .of_match_table = imx_ocotp_dt_ids,
+ },
+};
+module_platform_driver(imx_ocotp_driver);
+
+MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
+MODULE_DESCRIPTION("i.MX6 OCOTP fuse box driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
new file mode 100644
index 000000000000..8ba19bba3156
--- /dev/null
+++ b/drivers/nvmem/mxs-ocotp.c
@@ -0,0 +1,257 @@
+/*
+ * Freescale MXS On-Chip OTP driver
+ *
+ * Copyright (C) 2015 Stefan Wahren <stefan.wahren@i2se.com>
+ *
+ * Based on the driver from Huang Shijie and Christoph G. Baumann
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/stmp_device.h>
+
+/* OCOTP registers and bits */
+
+#define BM_OCOTP_CTRL_RD_BANK_OPEN BIT(12)
+#define BM_OCOTP_CTRL_ERROR BIT(9)
+#define BM_OCOTP_CTRL_BUSY BIT(8)
+
+#define OCOTP_TIMEOUT 10000
+#define OCOTP_DATA_OFFSET 0x20
+
+struct mxs_ocotp {
+ struct clk *clk;
+ void __iomem *base;
+ struct nvmem_device *nvmem;
+};
+
+static int mxs_ocotp_wait(struct mxs_ocotp *otp)
+{
+ int timeout = OCOTP_TIMEOUT;
+ unsigned int status = 0;
+
+ while (timeout--) {
+ status = readl(otp->base);
+
+ if (!(status & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)))
+ break;
+
+ cpu_relax();
+ }
+
+ if (status & BM_OCOTP_CTRL_BUSY)
+ return -EBUSY;
+ else if (status & BM_OCOTP_CTRL_ERROR)
+ return -EIO;
+
+ return 0;
+}
+
+static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct mxs_ocotp *otp = context;
+ unsigned int offset = *(u32 *)reg;
+ u32 *buf = val;
+ int ret;
+
+ ret = clk_enable(otp->clk);
+ if (ret)
+ return ret;
+
+ writel(BM_OCOTP_CTRL_ERROR, otp->base + STMP_OFFSET_REG_CLR);
+
+ ret = mxs_ocotp_wait(otp);
+ if (ret)
+ goto disable_clk;
+
+ /* open OCOTP banks for read */
+ writel(BM_OCOTP_CTRL_RD_BANK_OPEN, otp->base + STMP_OFFSET_REG_SET);
+
+ /* approximately wait 33 hclk cycles */
+ udelay(1);
+
+ ret = mxs_ocotp_wait(otp);
+ if (ret)
+ goto close_banks;
+
+ while (val_size) {
+ if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
+ /* fill up non-data register */
+ *buf = 0;
+ } else {
+ *buf = readl(otp->base + offset);
+ }
+
+ buf++;
+ val_size--;
+ offset += reg_size;
+ }
+
+close_banks:
+ /* close banks for power saving */
+ writel(BM_OCOTP_CTRL_RD_BANK_OPEN, otp->base + STMP_OFFSET_REG_CLR);
+
+disable_clk:
+ clk_disable(otp->clk);
+
+ return ret;
+}
+
+static int mxs_ocotp_write(void *context, const void *data, size_t count)
+{
+ /* We don't want to support writing */
+ return 0;
+}
+
+static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
+{
+ return false;
+}
+
+static struct nvmem_config ocotp_config = {
+ .name = "mxs-ocotp",
+ .owner = THIS_MODULE,
+};
+
+static const struct regmap_range imx23_ranges[] = {
+ regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
+};
+
+static const struct regmap_access_table imx23_access = {
+ .yes_ranges = imx23_ranges,
+ .n_yes_ranges = ARRAY_SIZE(imx23_ranges),
+};
+
+static const struct regmap_range imx28_ranges[] = {
+ regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
+};
+
+static const struct regmap_access_table imx28_access = {
+ .yes_ranges = imx28_ranges,
+ .n_yes_ranges = ARRAY_SIZE(imx28_ranges),
+};
+
+static struct regmap_bus mxs_ocotp_bus = {
+ .read = mxs_ocotp_read,
+ .write = mxs_ocotp_write, /* make regmap_init() happy */
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static struct regmap_config mxs_ocotp_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 16,
+ .writeable_reg = mxs_ocotp_writeable_reg,
+};
+
+static const struct of_device_id mxs_ocotp_match[] = {
+ { .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
+ { .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
+ { /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
+
+static int mxs_ocotp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mxs_ocotp *otp;
+ struct resource *res;
+ const struct of_device_id *match;
+ struct regmap *regmap;
+ const struct regmap_access_table *access;
+ int ret;
+
+ match = of_match_device(dev->driver->of_match_table, dev);
+ if (!match || !match->data)
+ return -EINVAL;
+
+ otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL);
+ if (!otp)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ otp->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(otp->base))
+ return PTR_ERR(otp->base);
+
+ otp->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(otp->clk))
+ return PTR_ERR(otp->clk);
+
+ ret = clk_prepare(otp->clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to prepare clk: %d\n", ret);
+ return ret;
+ }
+
+ access = match->data;
+ mxs_ocotp_config.rd_table = access;
+ mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
+
+ regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "regmap init failed\n");
+ ret = PTR_ERR(regmap);
+ goto err_clk;
+ }
+
+ ocotp_config.dev = dev;
+ otp->nvmem = nvmem_register(&ocotp_config);
+ if (IS_ERR(otp->nvmem)) {
+ ret = PTR_ERR(otp->nvmem);
+ goto err_clk;
+ }
+
+ platform_set_drvdata(pdev, otp);
+
+ return 0;
+
+err_clk:
+ clk_unprepare(otp->clk);
+
+ return ret;
+}
+
+static int mxs_ocotp_remove(struct platform_device *pdev)
+{
+ struct mxs_ocotp *otp = platform_get_drvdata(pdev);
+
+ clk_unprepare(otp->clk);
+
+ return nvmem_unregister(otp->nvmem);
+}
+
+static struct platform_driver mxs_ocotp_driver = {
+ .probe = mxs_ocotp_probe,
+ .remove = mxs_ocotp_remove,
+ .driver = {
+ .name = "mxs-ocotp",
+ .of_match_table = mxs_ocotp_match,
+ },
+};
+
+module_platform_driver(mxs_ocotp_driver);
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_DESCRIPTION("driver for OCOTP in i.MX23/i.MX28");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
new file mode 100644
index 000000000000..f55213424222
--- /dev/null
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -0,0 +1,186 @@
+/*
+ * Rockchip eFuse Driver
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Caesar Wang <wxt@rock-chips.com>
+ *
+ * This program 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+
+#define EFUSE_A_SHIFT 6
+#define EFUSE_A_MASK 0x3ff
+#define EFUSE_PGENB BIT(3)
+#define EFUSE_LOAD BIT(2)
+#define EFUSE_STROBE BIT(1)
+#define EFUSE_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x0000
+#define REG_EFUSE_DOUT 0x0004
+
+struct rockchip_efuse_context {
+ struct device *dev;
+ void __iomem *base;
+ struct clk *efuse_clk;
+};
+
+static int rockchip_efuse_write(void *context, const void *data, size_t count)
+{
+ /* Nothing TBD, Read-Only */
+ return 0;
+}
+
+static int rockchip_efuse_read(void *context,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ unsigned int offset = *(u32 *)reg;
+ struct rockchip_efuse_context *_context = context;
+ void __iomem *base = _context->base;
+ struct clk *clk = _context->efuse_clk;
+ u8 *buf = val;
+ int ret;
+
+ ret = clk_prepare_enable(clk);
+ if (ret < 0) {
+ dev_err(_context->dev, "failed to prepare/enable efuse clk\n");
+ return ret;
+ }
+
+ writel(EFUSE_LOAD | EFUSE_PGENB, base + REG_EFUSE_CTRL);
+ udelay(1);
+ while (val_size) {
+ writel(readl(base + REG_EFUSE_CTRL) &
+ (~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+ base + REG_EFUSE_CTRL);
+ writel(readl(base + REG_EFUSE_CTRL) |
+ ((offset & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+ base + REG_EFUSE_CTRL);
+ udelay(1);
+ writel(readl(base + REG_EFUSE_CTRL) |
+ EFUSE_STROBE, base + REG_EFUSE_CTRL);
+ udelay(1);
+ *buf++ = readb(base + REG_EFUSE_DOUT);
+ writel(readl(base + REG_EFUSE_CTRL) &
+ (~EFUSE_STROBE), base + REG_EFUSE_CTRL);
+ udelay(1);
+
+ val_size -= 1;
+ offset += 1;
+ }
+
+ /* Switch to standby mode */
+ writel(EFUSE_PGENB | EFUSE_CSB, base + REG_EFUSE_CTRL);
+
+ clk_disable_unprepare(clk);
+
+ return 0;
+}
+
+static struct regmap_bus rockchip_efuse_bus = {
+ .read = rockchip_efuse_read,
+ .write = rockchip_efuse_write,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static struct regmap_config rockchip_efuse_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 1,
+ .val_bits = 8,
+};
+
+static struct nvmem_config econfig = {
+ .name = "rockchip-efuse",
+ .owner = THIS_MODULE,
+ .read_only = true,
+};
+
+static const struct of_device_id rockchip_efuse_match[] = {
+ { .compatible = "rockchip,rockchip-efuse",},
+ { /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, rockchip_efuse_match);
+
+static int rockchip_efuse_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct nvmem_device *nvmem;
+ struct regmap *regmap;
+ void __iomem *base;
+ struct clk *clk;
+ struct rockchip_efuse_context *context;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ context = devm_kzalloc(dev, sizeof(struct rockchip_efuse_context),
+ GFP_KERNEL);
+ if (IS_ERR(context))
+ return PTR_ERR(context);
+
+ clk = devm_clk_get(dev, "pclk_efuse");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ context->dev = dev;
+ context->base = base;
+ context->efuse_clk = clk;
+
+ rockchip_efuse_regmap_config.max_register = resource_size(res) - 1;
+
+ regmap = devm_regmap_init(dev, &rockchip_efuse_bus,
+ context, &rockchip_efuse_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "regmap init failed\n");
+ return PTR_ERR(regmap);
+ }
+ econfig.dev = dev;
+ nvmem = nvmem_register(&econfig);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ platform_set_drvdata(pdev, nvmem);
+
+ return 0;
+}
+
+static int rockchip_efuse_remove(struct platform_device *pdev)
+{
+ struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+ return nvmem_unregister(nvmem);
+}
+
+static struct platform_driver rockchip_efuse_driver = {
+ .probe = rockchip_efuse_probe,
+ .remove = rockchip_efuse_remove,
+ .driver = {
+ .name = "rockchip-efuse",
+ .of_match_table = rockchip_efuse_match,
+ },
+};
+
+module_platform_driver(rockchip_efuse_driver);
+MODULE_DESCRIPTION("rockchip_efuse driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/vf610-ocotp.c b/drivers/nvmem/vf610-ocotp.c
new file mode 100644
index 000000000000..8641319efeda
--- /dev/null
+++ b/drivers/nvmem/vf610-ocotp.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2015 Toradex AG.
+ *
+ * Author: Sanchayan Maity <sanchayan.maity@toradex.com>
+ *
+ * Based on the barebox ocotp driver,
+ * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>
+ * Orex Computed Radiography
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+#include <linux/clk.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/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* OCOTP Register Offsets */
+#define OCOTP_CTRL_REG 0x00
+#define OCOTP_CTRL_SET 0x04
+#define OCOTP_CTRL_CLR 0x08
+#define OCOTP_TIMING 0x10
+#define OCOTP_DATA 0x20
+#define OCOTP_READ_CTRL_REG 0x30
+#define OCOTP_READ_FUSE_DATA 0x40
+
+/* OCOTP Register bits and masks */
+#define OCOTP_CTRL_WR_UNLOCK 16
+#define OCOTP_CTRL_WR_UNLOCK_KEY 0x3E77
+#define OCOTP_CTRL_WR_UNLOCK_MASK GENMASK(31, 16)
+#define OCOTP_CTRL_ADDR 0
+#define OCOTP_CTRL_ADDR_MASK GENMASK(6, 0)
+#define OCOTP_CTRL_RELOAD_SHADOWS BIT(10)
+#define OCOTP_CTRL_ERR BIT(9)
+#define OCOTP_CTRL_BUSY BIT(8)
+
+#define OCOTP_TIMING_STROBE_READ 16
+#define OCOTP_TIMING_STROBE_READ_MASK GENMASK(21, 16)
+#define OCOTP_TIMING_RELAX 12
+#define OCOTP_TIMING_RELAX_MASK GENMASK(15, 12)
+#define OCOTP_TIMING_STROBE_PROG 0
+#define OCOTP_TIMING_STROBE_PROG_MASK GENMASK(11, 0)
+
+#define OCOTP_READ_CTRL_READ_FUSE 0x1
+
+#define VF610_OCOTP_TIMEOUT 100000
+
+#define BF(value, field) (((value) << field) & field##_MASK)
+
+#define DEF_RELAX 20
+
+static const int base_to_fuse_addr_mappings[][2] = {
+ {0x400, 0x00},
+ {0x410, 0x01},
+ {0x420, 0x02},
+ {0x450, 0x05},
+ {0x4F0, 0x0F},
+ {0x600, 0x20},
+ {0x610, 0x21},
+ {0x620, 0x22},
+ {0x630, 0x23},
+ {0x640, 0x24},
+ {0x650, 0x25},
+ {0x660, 0x26},
+ {0x670, 0x27},
+ {0x6F0, 0x2F},
+ {0x880, 0x38},
+ {0x890, 0x39},
+ {0x8A0, 0x3A},
+ {0x8B0, 0x3B},
+ {0x8C0, 0x3C},
+ {0x8D0, 0x3D},
+ {0x8E0, 0x3E},
+ {0x8F0, 0x3F},
+ {0xC80, 0x78},
+ {0xC90, 0x79},
+ {0xCA0, 0x7A},
+ {0xCB0, 0x7B},
+ {0xCC0, 0x7C},
+ {0xCD0, 0x7D},
+ {0xCE0, 0x7E},
+ {0xCF0, 0x7F},
+};
+
+struct vf610_ocotp {
+ void __iomem *base;
+ struct clk *clk;
+ struct device *dev;
+ struct nvmem_device *nvmem;
+ int timing;
+};
+
+static int vf610_ocotp_wait_busy(void __iomem *base)
+{
+ int timeout = VF610_OCOTP_TIMEOUT;
+
+ while ((readl(base) & OCOTP_CTRL_BUSY) && --timeout)
+ udelay(10);
+
+ if (!timeout) {
+ writel(OCOTP_CTRL_ERR, base + OCOTP_CTRL_CLR);
+ return -ETIMEDOUT;
+ }
+
+ udelay(10);
+
+ return 0;
+}
+
+static int vf610_ocotp_calculate_timing(struct vf610_ocotp *ocotp_dev)
+{
+ u32 clk_rate;
+ u32 relax, strobe_read, strobe_prog;
+ u32 timing;
+
+ clk_rate = clk_get_rate(ocotp_dev->clk);
+
+ /* Refer section OTP read/write timing parameters in TRM */
+ relax = clk_rate / (1000000000 / DEF_RELAX) - 1;
+ strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1;
+ strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1;
+
+ timing = BF(relax, OCOTP_TIMING_RELAX);
+ timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ);
+ timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG);
+
+ return timing;
+}
+
+static int vf610_get_fuse_address(int base_addr_offset)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(base_to_fuse_addr_mappings); i++) {
+ if (base_to_fuse_addr_mappings[i][0] == base_addr_offset)
+ return base_to_fuse_addr_mappings[i][1];
+ }
+
+ return -EINVAL;
+}
+
+static int vf610_ocotp_write(void *context, const void *data, size_t count)
+{
+ return 0;
+}
+
+static int vf610_ocotp_read(void *context,
+ const void *off, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct vf610_ocotp *ocotp = context;
+ void __iomem *base = ocotp->base;
+ unsigned int offset = *(u32 *)off;
+ u32 reg, *buf = val;
+ int fuse_addr;
+ int ret;
+
+ while (val_size > 0) {
+ fuse_addr = vf610_get_fuse_address(offset);
+ if (fuse_addr > 0) {
+ writel(ocotp->timing, base + OCOTP_TIMING);
+ ret = vf610_ocotp_wait_busy(base + OCOTP_CTRL_REG);
+ if (ret)
+ return ret;
+
+ reg = readl(base + OCOTP_CTRL_REG);
+ reg &= ~OCOTP_CTRL_ADDR_MASK;
+ reg &= ~OCOTP_CTRL_WR_UNLOCK_MASK;
+ reg |= BF(fuse_addr, OCOTP_CTRL_ADDR);
+ writel(reg, base + OCOTP_CTRL_REG);
+
+ writel(OCOTP_READ_CTRL_READ_FUSE,
+ base + OCOTP_READ_CTRL_REG);
+ ret = vf610_ocotp_wait_busy(base + OCOTP_CTRL_REG);
+ if (ret)
+ return ret;
+
+ if (readl(base) & OCOTP_CTRL_ERR) {
+ dev_dbg(ocotp->dev, "Error reading from fuse address %x\n",
+ fuse_addr);
+ writel(OCOTP_CTRL_ERR, base + OCOTP_CTRL_CLR);
+ }
+
+ /*
+ * In case of error, we do not abort and expect to read
+ * 0xBADABADA as mentioned by the TRM. We just read this
+ * value and return.
+ */
+ *buf = readl(base + OCOTP_READ_FUSE_DATA);
+ } else {
+ *buf = 0;
+ }
+
+ buf++;
+ val_size--;
+ offset += reg_size;
+ }
+
+ return 0;
+}
+
+static struct regmap_bus vf610_ocotp_bus = {
+ .read = vf610_ocotp_read,
+ .write = vf610_ocotp_write,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static struct regmap_config ocotp_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static struct nvmem_config ocotp_config = {
+ .name = "ocotp",
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id ocotp_of_match[] = {
+ { .compatible = "fsl,vf610-ocotp", },
+ {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, ocotp_of_match);
+
+static int vf610_ocotp_remove(struct platform_device *pdev)
+{
+ struct vf610_ocotp *ocotp_dev = platform_get_drvdata(pdev);
+
+ return nvmem_unregister(ocotp_dev->nvmem);
+}
+
+static int vf610_ocotp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct regmap *regmap;
+ struct vf610_ocotp *ocotp_dev;
+
+ ocotp_dev = devm_kzalloc(&pdev->dev,
+ sizeof(struct vf610_ocotp), GFP_KERNEL);
+ if (!ocotp_dev)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ocotp_dev->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ocotp_dev->base))
+ return PTR_ERR(ocotp_dev->base);
+
+ ocotp_dev->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(ocotp_dev->clk)) {
+ dev_err(dev, "failed getting clock, err = %ld\n",
+ PTR_ERR(ocotp_dev->clk));
+ return PTR_ERR(ocotp_dev->clk);
+ }
+
+ ocotp_regmap_config.max_register = resource_size(res);
+ regmap = devm_regmap_init(dev,
+ &vf610_ocotp_bus, ocotp_dev, &ocotp_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "regmap init failed\n");
+ return PTR_ERR(regmap);
+ }
+ ocotp_config.dev = dev;
+
+ ocotp_dev->nvmem = nvmem_register(&ocotp_config);
+ if (IS_ERR(ocotp_dev->nvmem))
+ return PTR_ERR(ocotp_dev->nvmem);
+
+ ocotp_dev->dev = dev;
+ platform_set_drvdata(pdev, ocotp_dev);
+
+ ocotp_dev->timing = vf610_ocotp_calculate_timing(ocotp_dev);
+
+ return 0;
+}
+
+static struct platform_driver vf610_ocotp_driver = {
+ .probe = vf610_ocotp_probe,
+ .remove = vf610_ocotp_remove,
+ .driver = {
+ .name = "vf610-ocotp",
+ .of_match_table = ocotp_of_match,
+ },
+};
+module_platform_driver(vf610_ocotp_driver);
+MODULE_AUTHOR("Sanchayan Maity <sanchayan.maity@toradex.com>");
+MODULE_DESCRIPTION("Vybrid OCOTP driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 59bb8556e43a..e2a48415d969 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -23,6 +23,16 @@ config OF_UNITTEST
If unsure, say N here, but this option is safe to enable.
+config OF_ALL_DTBS
+ bool "Build all Device Tree Blobs"
+ depends on COMPILE_TEST
+ select DTC
+ help
+ This option builds all possible Device Tree Blobs (DTBs) for the
+ current architecture.
+
+ If unsure, say N here, but this option is safe to enable.
+
config OF_FLATTREE
bool
select DTC
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 384574c3987c..cd53fe4a0c86 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -330,6 +330,12 @@ int of_pci_range_to_resource(struct of_pci_range *range,
}
res->start = port;
} else {
+ if ((sizeof(resource_size_t) < 8) &&
+ upper_32_bits(range->cpu_addr)) {
+ err = -EINVAL;
+ goto invalid_range;
+ }
+
res->start = range->cpu_addr;
}
res->end = res->start + range->size - 1;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 8b5a187a7682..017dd94f16ea 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -375,10 +375,7 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
cpu, thread))
return true;
- if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
- return true;
-
- return false;
+ return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);
}
/**
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 8b91ea241b10..e5f47cec75f3 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -60,11 +60,12 @@ int of_device_add(struct platform_device *ofdev)
ofdev->name = dev_name(&ofdev->dev);
ofdev->id = -1;
- /* device_add will assume that this device is on the same node as
- * the parent. If there is no parent defined, set the node
- * explicitly */
- if (!ofdev->dev.parent)
- set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
+ /*
+ * If this device has not binding numa node in devicetree, that is
+ * of_node_to_nid returns NUMA_NO_NODE. device_add will assume that this
+ * device is on the same node as the parent.
+ */
+ set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
return device_add(&ofdev->dev);
}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 6e82bc42373b..d2430298a309 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -184,7 +184,7 @@ static void * unflatten_dt_node(const void *blob,
struct property *pp, **prev_pp = NULL;
const char *pathp;
unsigned int l, allocl;
- static int depth = 0;
+ static int depth;
int old_depth;
int offset;
int has_name = 0;
@@ -813,20 +813,24 @@ static int __init early_init_dt_scan_chosen_serial(void)
if (!p || !l)
return -ENOENT;
+ /* Remove console options if present */
+ l = strchrnul(p, ':') - p;
+
/* Get the node specified by stdout-path */
- offset = fdt_path_offset(fdt, p);
+ offset = fdt_path_offset_namelen(fdt, p, l);
if (offset < 0)
return -ENODEV;
while (match->compatible[0]) {
- unsigned long addr;
+ u64 addr;
+
if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
match++;
continue;
}
addr = fdt_translate_address(fdt, offset);
- if (!addr)
+ if (addr == OF_BAD_ADDR)
return -ENXIO;
of_setup_earlycon(addr, match->data);
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 55317fa9c9dc..902b89be7217 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
* Returns a pointer to the interrupt parent node, or NULL if the interrupt
* parent could not be determined.
*/
-struct device_node *of_irq_find_parent(struct device_node *child)
+static struct device_node *of_irq_find_parent(struct device_node *child)
{
struct device_node *p;
const __be32 *parp;
@@ -501,10 +501,12 @@ void __init of_irq_init(const struct of_device_id *matches)
* pointer, interrupt-parent device_node etc.
*/
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
- if (WARN_ON(!desc))
+ if (WARN_ON(!desc)) {
+ of_node_put(np);
goto err;
+ }
- desc->dev = np;
+ desc->dev = of_node_get(np);
desc->interrupt_parent = of_irq_find_parent(np);
if (desc->interrupt_parent == np)
desc->interrupt_parent = NULL;
@@ -575,26 +577,192 @@ void __init of_irq_init(const struct of_device_id *matches)
err:
list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
list_del(&desc->list);
+ of_node_put(desc->dev);
kfree(desc);
}
}
+static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
+ u32 rid_in)
+{
+ struct device *parent_dev;
+ struct device_node *msi_controller_node;
+ struct device_node *msi_np = *np;
+ u32 map_mask, masked_rid, rid_base, msi_base, rid_len, phandle;
+ int msi_map_len;
+ bool matched;
+ u32 rid_out = rid_in;
+ const __be32 *msi_map = NULL;
+
+ /*
+ * Walk up the device parent links looking for one with a
+ * "msi-map" property.
+ */
+ for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
+ if (!parent_dev->of_node)
+ continue;
+
+ msi_map = of_get_property(parent_dev->of_node,
+ "msi-map", &msi_map_len);
+ if (!msi_map)
+ continue;
+
+ if (msi_map_len % (4 * sizeof(__be32))) {
+ dev_err(parent_dev, "Error: Bad msi-map length: %d\n",
+ msi_map_len);
+ return rid_out;
+ }
+ /* We have a good parent_dev and msi_map, let's use them. */
+ break;
+ }
+ if (!msi_map)
+ return rid_out;
+
+ /* The default is to select all bits. */
+ map_mask = 0xffffffff;
+
+ /*
+ * Can be overridden by "msi-map-mask" property. If
+ * of_property_read_u32() fails, the default is used.
+ */
+ of_property_read_u32(parent_dev->of_node, "msi-map-mask", &map_mask);
+
+ masked_rid = map_mask & rid_in;
+ matched = false;
+ while (!matched && msi_map_len >= 4 * sizeof(__be32)) {
+ rid_base = be32_to_cpup(msi_map + 0);
+ phandle = be32_to_cpup(msi_map + 1);
+ msi_base = be32_to_cpup(msi_map + 2);
+ rid_len = be32_to_cpup(msi_map + 3);
+
+ msi_controller_node = of_find_node_by_phandle(phandle);
+
+ matched = (masked_rid >= rid_base &&
+ masked_rid < rid_base + rid_len);
+ if (msi_np)
+ matched &= msi_np == msi_controller_node;
+
+ if (matched && !msi_np) {
+ *np = msi_np = msi_controller_node;
+ break;
+ }
+
+ of_node_put(msi_controller_node);
+ msi_map_len -= 4 * sizeof(__be32);
+ msi_map += 4;
+ }
+ if (!matched)
+ return rid_out;
+
+ rid_out = masked_rid + msi_base;
+ dev_dbg(dev,
+ "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n",
+ dev_name(parent_dev), map_mask, rid_base, msi_base,
+ rid_len, rid_in, rid_out);
+
+ return rid_out;
+}
+
/**
- * of_msi_configure - Set the msi_domain field of a device
- * @dev: device structure to associate with an MSI irq domain
- * @np: device node for that device
+ * of_msi_map_rid - Map a MSI requester ID for a device.
+ * @dev: device for which the mapping is to be done.
+ * @msi_np: device node of the expected msi controller.
+ * @rid_in: unmapped MSI requester ID for the device.
+ *
+ * Walk up the device hierarchy looking for devices with a "msi-map"
+ * property. If found, apply the mapping to @rid_in.
+ *
+ * Returns the mapped MSI requester ID.
*/
-void of_msi_configure(struct device *dev, struct device_node *np)
+u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in)
+{
+ return __of_msi_map_rid(dev, &msi_np, rid_in);
+}
+
+static struct irq_domain *__of_get_msi_domain(struct device_node *np,
+ enum irq_domain_bus_token token)
+{
+ struct irq_domain *d;
+
+ d = irq_find_matching_host(np, token);
+ if (!d)
+ d = irq_find_host(np);
+
+ return d;
+}
+
+/**
+ * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
+ * @dev: device for which the mapping is to be done.
+ * @rid: Requester ID for the device.
+ *
+ * Walk up the device hierarchy looking for devices with a "msi-map"
+ * property.
+ *
+ * Returns: the MSI domain for this device (or NULL on failure)
+ */
+struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
+{
+ struct device_node *np = NULL;
+
+ __of_msi_map_rid(dev, &np, rid);
+ return __of_get_msi_domain(np, DOMAIN_BUS_PCI_MSI);
+}
+
+/**
+ * of_msi_get_domain - Use msi-parent to find the relevant MSI domain
+ * @dev: device for which the domain is requested
+ * @np: device node for @dev
+ * @token: bus type for this domain
+ *
+ * Parse the msi-parent property (both the simple and the complex
+ * versions), and returns the corresponding MSI domain.
+ *
+ * Returns: the MSI domain for this device (or NULL on failure).
+ */
+struct irq_domain *of_msi_get_domain(struct device *dev,
+ struct device_node *np,
+ enum irq_domain_bus_token token)
{
struct device_node *msi_np;
struct irq_domain *d;
+ /* Check for a single msi-parent property */
msi_np = of_parse_phandle(np, "msi-parent", 0);
- if (!msi_np)
- return;
+ if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) {
+ d = __of_get_msi_domain(msi_np, token);
+ if (!d)
+ of_node_put(msi_np);
+ return d;
+ }
- d = irq_find_matching_host(msi_np, DOMAIN_BUS_PLATFORM_MSI);
- if (!d)
- d = irq_find_host(msi_np);
- dev_set_msi_domain(dev, d);
+ if (token == DOMAIN_BUS_PLATFORM_MSI) {
+ /* Check for the complex msi-parent version */
+ struct of_phandle_args args;
+ int index = 0;
+
+ while (!of_parse_phandle_with_args(np, "msi-parent",
+ "#msi-cells",
+ index, &args)) {
+ d = __of_get_msi_domain(args.np, token);
+ if (d)
+ return d;
+
+ of_node_put(args.np);
+ index++;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * of_msi_configure - Set the msi_domain field of a device
+ * @dev: device structure to associate with an MSI irq domain
+ * @np: device node for that device
+ */
+void of_msi_configure(struct device *dev, struct device_node *np)
+{
+ dev_set_msi_domain(dev,
+ of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI));
}
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 5751dc5b6494..b1449f71601c 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -5,6 +5,7 @@
#include <linux/of_device.h>
#include <linux/of_pci.h>
#include <linux/slab.h>
+#include <asm-generic/pci-bridge.h>
static inline int __of_pci_pci_compare(struct device_node *node,
unsigned int data)
@@ -118,24 +119,29 @@ int of_get_pci_domain_nr(struct device_node *node)
EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
/**
- * of_pci_dma_configure - Setup DMA configuration
- * @dev: ptr to pci_dev struct of the PCI device
- *
- * Function to update PCI devices's DMA configuration using the same
- * info from the OF node of host bridge's parent (if any).
+ * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only
+ * is present and valid
*/
-void of_pci_dma_configure(struct pci_dev *pci_dev)
+void of_pci_check_probe_only(void)
{
- struct device *dev = &pci_dev->dev;
- struct device *bridge = pci_get_host_bridge_device(pci_dev);
+ u32 val;
+ int ret;
- if (!bridge->parent)
+ ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val);
+ if (ret) {
+ if (ret == -ENODATA || ret == -EOVERFLOW)
+ pr_warn("linux,pci-probe-only without valid value, ignoring\n");
return;
+ }
+
+ if (val)
+ pci_add_flags(PCI_PROBE_ONLY);
+ else
+ pci_clear_flags(PCI_PROBE_ONLY);
- of_dma_configure(dev, bridge->parent->of_node);
- pci_put_host_bridge_device(bridge);
+ pr_info("PCI: PROBE_ONLY %sabled\n", val ? "en" : "dis");
}
-EXPORT_SYMBOL_GPL(of_pci_dma_configure);
+EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
#if defined(CONFIG_OF_ADDRESS)
/**
@@ -223,8 +229,10 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
}
err = of_pci_range_to_resource(&range, dev, res);
- if (err)
- goto conversion_failed;
+ if (err) {
+ kfree(res);
+ continue;
+ }
if (resource_type(res) == IORESOURCE_IO) {
if (!io_base) {
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 726ebe792813..be77e75c587d 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -1,7 +1,7 @@
/*
* Device tree based initialization code for reserved memory.
*
- * Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ * Copyright (c) 2013, 2015 The Linux Foundation. All Rights Reserved.
* Copyright (c) 2013,2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
* Author: Marek Szyprowski <m.szyprowski@samsung.com>
@@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/sizes.h>
#include <linux/of_reserved_mem.h>
+#include <linux/sort.h>
#define MAX_RESERVED_REGIONS 16
static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
@@ -123,6 +124,10 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
align = dt_mem_next_cell(dt_root_addr_cells, &prop);
}
+ /* Need adjust the alignment to satisfy the CMA requirement */
+ if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool"))
+ align = max(align, (phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
+
prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
if (prop) {
@@ -197,12 +202,51 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
return -ENOENT;
}
+static int __init __rmem_cmp(const void *a, const void *b)
+{
+ const struct reserved_mem *ra = a, *rb = b;
+
+ return ra->base - rb->base;
+}
+
+static void __init __rmem_check_for_overlap(void)
+{
+ int i;
+
+ if (reserved_mem_count < 2)
+ return;
+
+ sort(reserved_mem, reserved_mem_count, sizeof(reserved_mem[0]),
+ __rmem_cmp, NULL);
+ for (i = 0; i < reserved_mem_count - 1; i++) {
+ struct reserved_mem *this, *next;
+
+ this = &reserved_mem[i];
+ next = &reserved_mem[i + 1];
+ if (!(this->base && next->base))
+ continue;
+ if (this->base + this->size > next->base) {
+ phys_addr_t this_end, next_end;
+
+ this_end = this->base + this->size;
+ next_end = next->base + next->size;
+ pr_err("Reserved memory: OVERLAP DETECTED!\n%s (%pa--%pa) overlaps with %s (%pa--%pa)\n",
+ this->name, &this->base, &this_end,
+ next->name, &next->base, &next_end);
+ }
+ }
+}
+
/**
* fdt_init_reserved_mem - allocate and init all saved reserved memory regions
*/
void __init fdt_init_reserved_mem(void)
{
int i;
+
+ /* check for overlapping reserved regions */
+ __rmem_check_for_overlap();
+
for (i = 0; i < reserved_mem_count; i++) {
struct reserved_mem *rmem = &reserved_mem[i];
unsigned long node = rmem->fdt_node;
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 24e025f79299..54e5af9d7377 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -149,6 +149,7 @@ static int of_overlay_apply_one(struct of_overlay *ov,
pr_err("%s: Failed to apply single node @%s/%s\n",
__func__, target->full_name,
child->name);
+ of_node_put(child);
return ret;
}
}
@@ -417,8 +418,10 @@ static int overlay_subtree_check(struct device_node *tree,
return 1;
for_each_child_of_node(tree, child) {
- if (overlay_subtree_check(child, dn))
+ if (overlay_subtree_check(child, dn)) {
+ of_node_put(child);
return 1;
+ }
}
return 0;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 1001efaedcb8..af98343614d8 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -405,8 +405,10 @@ int of_platform_bus_probe(struct device_node *root,
if (!of_match_node(matches, child))
continue;
rc = of_platform_bus_create(child, matches, NULL, parent, false);
- if (rc)
+ if (rc) {
+ of_node_put(child);
break;
+ }
}
of_node_put(root);
@@ -447,8 +449,10 @@ int of_platform_populate(struct device_node *root,
for_each_child_of_node(root, child) {
rc = of_platform_bus_create(child, matches, lookup, parent, true);
- if (rc)
+ if (rc) {
+ of_node_put(child);
break;
+ }
}
of_node_set_flag(root, OF_POPULATED_BUS);
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 9f71770b6226..e16ea5717b7f 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -205,16 +205,20 @@ static int __init of_unittest_check_node_linkage(struct device_node *np)
if (child->parent != np) {
pr_err("Child node %s links to wrong parent %s\n",
child->name, np->name);
- return -EINVAL;
+ rc = -EINVAL;
+ goto put_child;
}
rc = of_unittest_check_node_linkage(child);
if (rc < 0)
- return rc;
+ goto put_child;
count += rc;
}
return count + 1;
+put_child:
+ of_node_put(child);
+ return rc;
}
static void __init of_unittest_check_tree_linkage(void)
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 957b42198328..8e11fb2831cd 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -704,8 +704,6 @@ ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
* ccio_dma_supported - Verify the IOMMU supports the DMA address range.
* @dev: The PCI device.
* @mask: A bit mask describing the DMA address range of the device.
- *
- * This function implements the pci_dma_supported function.
*/
static int
ccio_dma_supported(struct device *dev, u64 mask)
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index a32c1f6c252c..42844c2bc065 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -624,6 +624,10 @@ extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len)
{
struct resource *tmp;
+ /* exit if not a C8000 */
+ if (boot_cpu_data.cpu_type < mako)
+ return end;
+
pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n",
end - start, lba_len);
@@ -631,10 +635,6 @@ extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len)
pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end);
- if (boot_cpu_data.cpu_type < mako) {
- pr_info("LBA: Not a C8000 system - not extending LMMIO range.\n");
- return end;
- }
end += lba_len;
if (end < start) /* fix overflow */
@@ -1557,9 +1557,9 @@ lba_driver_probe(struct parisc_device *dev)
pci_add_resource_offset(&resources, &lba_dev->hba.lmmio_space,
lba_dev->hba.lmmio_space_offset);
if (lba_dev->hba.gmmio_space.flags) {
+ /* Not registering GMMIO space - according to docs it's not
+ * even used on HP-UX. */
/* pci_add_resource(&resources, &lba_dev->hba.gmmio_space); */
- pr_warn("LBA: Not registering GMMIO space %pR\n",
- &lba_dev->hba.gmmio_space);
}
pci_add_resource(&resources, &lba_dev->hba.bus_num);
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index d5e58bae95cf..f131ba947dc6 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -39,7 +39,8 @@ config PCI_TEGRA
config PCI_RCAR_GEN2
bool "Renesas R-Car Gen2 Internal PCI controller"
- depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
+ depends on ARM
+ depends on ARCH_SHMOBILE || COMPILE_TEST
help
Say Y here if you want internal PCI support on R-Car Gen2 SoC.
There are 3 internal PCI controllers available with a single
@@ -47,7 +48,8 @@ config PCI_RCAR_GEN2
config PCI_RCAR_GEN2_PCIE
bool "Renesas R-Car PCIe controller"
- depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
+ depends on ARM
+ depends on ARCH_SHMOBILE || COMPILE_TEST
help
Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
@@ -105,7 +107,7 @@ config PCI_XGENE_MSI
config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller"
- depends on OF && ARM
+ depends on OF && (ARM || ARCH_LAYERSCAPE)
select PCIE_DW
select MFD_SYSCON
help
@@ -145,4 +147,29 @@ config PCIE_IPROC_BCMA
Say Y here if you want to use the Broadcom iProc PCIe controller
through the BCMA bus interface
+config PCIE_ALTERA
+ bool "Altera PCIe controller"
+ depends on ARM || NIOS2
+ depends on OF_PCI
+ select PCI_DOMAINS
+ help
+ Say Y here if you want to enable PCIe controller support on Altera
+ FPGA.
+
+config PCIE_ALTERA_MSI
+ bool "Altera PCIe MSI feature"
+ depends on PCIE_ALTERA && PCI_MSI
+ select PCI_MSI_IRQ_DOMAIN
+ help
+ Say Y here if you want PCIe MSI support for the Altera FPGA.
+ This MSI driver supports Altera MSI to GIC controller IP.
+
+config PCI_HISI
+ depends on OF && ARM64
+ bool "HiSilicon SoC HIP05 PCIe controller"
+ select PCIEPORTBUS
+ select PCIE_DW
+ help
+ Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
+
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 140d66f796e4..9d4d3c6924a1 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -17,3 +17,6 @@ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
+obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
+obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 199e29a044cd..8c3688046c02 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -62,6 +62,7 @@
#define PCIECTRL_DRA7XX_CONF_PHY_CS 0x010C
#define LINK_UP BIT(16)
+#define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF
struct dra7xx_pcie {
void __iomem *base;
@@ -151,6 +152,12 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
static void dra7xx_pcie_host_init(struct pcie_port *pp)
{
dw_pcie_setup_rc(pp);
+
+ pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
+ pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
+ pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
+ pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
+
dra7xx_pcie_establish_link(pp);
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f9f468d9a819..01095e1160a4 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -454,7 +454,7 @@ static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
int ret;
exynos_pcie_sideband_dbi_r_mode(pp, true);
- ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, size, val);
+ ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
exynos_pcie_sideband_dbi_r_mode(pp, false);
return ret;
}
@@ -465,8 +465,7 @@ static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
int ret;
exynos_pcie_sideband_dbi_w_mode(pp, true);
- ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3),
- where, size, val);
+ ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
exynos_pcie_sideband_dbi_w_mode(pp, false);
return ret;
}
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 265dd25169bf..5434c90db243 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -27,7 +27,7 @@
struct gen_pci_cfg_bus_ops {
u32 bus_shift;
- void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int);
+ struct pci_ops ops;
};
struct gen_pci_cfg_windows {
@@ -35,7 +35,7 @@ struct gen_pci_cfg_windows {
struct resource *bus_range;
void __iomem **win;
- const struct gen_pci_cfg_bus_ops *ops;
+ struct gen_pci_cfg_bus_ops *ops;
};
/*
@@ -65,7 +65,11 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = {
.bus_shift = 16,
- .map_bus = gen_pci_map_cfg_bus_cam,
+ .ops = {
+ .map_bus = gen_pci_map_cfg_bus_cam,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
+ }
};
static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
@@ -80,12 +84,11 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = {
.bus_shift = 20,
- .map_bus = gen_pci_map_cfg_bus_ecam,
-};
-
-static struct pci_ops gen_pci_ops = {
- .read = pci_generic_config_read,
- .write = pci_generic_config_write,
+ .ops = {
+ .map_bus = gen_pci_map_cfg_bus_ecam,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
+ }
};
static const struct of_device_id gen_pci_of_match[] = {
@@ -166,6 +169,7 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
struct resource *bus_range;
struct device *dev = pci->host.dev.parent;
struct device_node *np = dev->of_node;
+ u32 sz = 1 << pci->cfg.ops->bus_shift;
err = of_address_to_resource(np, 0, &pci->cfg.res);
if (err) {
@@ -193,10 +197,9 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
bus_range = pci->cfg.bus_range;
for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
u32 idx = busn - bus_range->start;
- u32 sz = 1 << pci->cfg.ops->bus_shift;
pci->cfg.win[idx] = devm_ioremap(dev,
- pci->cfg.res.start + busn * sz,
+ pci->cfg.res.start + idx * sz,
sz);
if (!pci->cfg.win[idx])
return -ENOMEM;
@@ -210,7 +213,6 @@ static int gen_pci_probe(struct platform_device *pdev)
int err;
const char *type;
const struct of_device_id *of_id;
- const int *prop;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
@@ -225,17 +227,10 @@ static int gen_pci_probe(struct platform_device *pdev)
return -EINVAL;
}
- prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL);
- if (prop) {
- if (*prop)
- pci_add_flags(PCI_PROBE_ONLY);
- else
- pci_clear_flags(PCI_PROBE_ONLY);
- }
+ of_pci_check_probe_only();
of_id = of_match_node(gen_pci_of_match, np);
- pci->cfg.ops = of_id->data;
- gen_pci_ops.map_bus = pci->cfg.ops->map_bus;
+ pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
pci->host.dev.parent = dev;
INIT_LIST_HEAD(&pci->host.windows);
INIT_LIST_HEAD(&pci->resources);
@@ -256,7 +251,9 @@ static int gen_pci_probe(struct platform_device *pdev)
if (!pci_has_flag(PCI_PROBE_ONLY))
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
- bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources);
+
+ bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start,
+ &pci->cfg.ops->ops, pci, &pci->resources);
if (!bus) {
dev_err(dev, "Scanning rootbus failed");
return -ENODEV;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 8f3a9813c4e5..22e8224126fd 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -74,6 +74,7 @@ struct imx6_pcie {
/* PHY registers (not memory-mapped) */
#define PCIE_PHY_RX_ASIC_OUT 0x100D
+#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
#define PHY_RX_OVRD_IN_LO 0x1005
#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
@@ -503,7 +504,7 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
- if (rx_valid & 0x01)
+ if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID)
return 0;
if ((debug_r0 & 0x3f) != 0x0d)
@@ -539,7 +540,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
IRQF_SHARED, "mx6-pcie-msi", pp);
if (ret) {
dev_err(&pdev->dev, "failed to request MSI irq\n");
- return -ENODEV;
+ return ret;
}
}
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index e71da991949b..ed34c9520a02 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -70,7 +70,7 @@ static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
*bit_pos = offset >> 3;
}
-u32 ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
+phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
@@ -322,7 +322,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
{
struct pcie_port *pp = &ks_pcie->pp;
- u32 start = pp->mem.start, end = pp->mem.end;
+ u32 start = pp->mem->start, end = pp->mem->end;
int i, tr_size;
/* Disable BARs for inbound access */
@@ -398,7 +398,7 @@ int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
- return dw_pcie_cfg_read(addr + (where & ~0x3), where, size, val);
+ return dw_pcie_cfg_read(addr + where, size, val);
}
int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
@@ -410,7 +410,7 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
- return dw_pcie_cfg_write(addr + (where & ~0x3), where, size, val);
+ return dw_pcie_cfg_write(addr + where, size, val);
}
/**
diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/host/pci-keystone.h
index 478d932b602d..f0944e8c4b02 100644
--- a/drivers/pci/host/pci-keystone.h
+++ b/drivers/pci/host/pci-keystone.h
@@ -37,7 +37,7 @@ struct keystone_pcie {
/* Keystone DW specific MSI controller APIs/definitions */
void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset);
-u32 ks_dw_pcie_get_msi_addr(struct pcie_port *pp);
+phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp);
/* Keystone specific PCI controller APIs */
void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index b2328ea13dcf..3923bed93c7e 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Freescale Semiconductor.
*
- * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
+ * Author: Minghuan Lian <Minghuan.Lian@freescale.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
@@ -11,7 +11,6 @@
*/
#include <linux/kernel.h>
-#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_pci.h>
@@ -32,27 +31,60 @@
#define LTSSM_STATE_MASK 0x3f
#define LTSSM_PCIE_L0 0x11 /* L0 state */
-/* Symbol Timer Register and Filter Mask Register 1 */
-#define PCIE_STRFMR1 0x71c
+/* PEX Internal Configuration Registers */
+#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */
+#define PCIE_DBI_RO_WR_EN 0x8bc /* DBI Read-Only Write Enable Register */
+
+/* PEX LUT registers */
+#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug Register */
+
+struct ls_pcie_drvdata {
+ u32 lut_offset;
+ u32 ltssm_shift;
+ struct pcie_host_ops *ops;
+};
struct ls_pcie {
- struct list_head node;
- struct device *dev;
- struct pci_bus *bus;
void __iomem *dbi;
+ void __iomem *lut;
struct regmap *scfg;
struct pcie_port pp;
+ const struct ls_pcie_drvdata *drvdata;
int index;
- int msi_irq;
};
#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
-static int ls_pcie_link_up(struct pcie_port *pp)
+static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
+{
+ u32 header_type;
+
+ header_type = ioread8(pcie->dbi + PCI_HEADER_TYPE);
+ header_type &= 0x7f;
+
+ return header_type == PCI_HEADER_TYPE_BRIDGE;
+}
+
+/* Clear multi-function bit */
+static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
+{
+ iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE);
+}
+
+/* Fix class value */
+static void ls_pcie_fix_class(struct ls_pcie *pcie)
+{
+ iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
+}
+
+static int ls1021_pcie_link_up(struct pcie_port *pp)
{
u32 state;
struct ls_pcie *pcie = to_ls_pcie(pp);
+ if (!pcie->scfg)
+ return 0;
+
regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state);
state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
@@ -62,27 +94,27 @@ static int ls_pcie_link_up(struct pcie_port *pp)
return 1;
}
-static int ls_pcie_establish_link(struct pcie_port *pp)
+static void ls1021_pcie_host_init(struct pcie_port *pp)
{
- unsigned int retries;
+ struct ls_pcie *pcie = to_ls_pcie(pp);
+ u32 val, index[2];
- for (retries = 0; retries < 200; retries++) {
- if (dw_pcie_link_up(pp))
- return 0;
- usleep_range(100, 1000);
+ pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node,
+ "fsl,pcie-scfg");
+ if (IS_ERR(pcie->scfg)) {
+ dev_err(pp->dev, "No syscfg phandle specified\n");
+ pcie->scfg = NULL;
+ return;
}
- dev_err(pp->dev, "phy link never came up\n");
- return -EINVAL;
-}
-
-static void ls_pcie_host_init(struct pcie_port *pp)
-{
- struct ls_pcie *pcie = to_ls_pcie(pp);
- u32 val;
+ if (of_property_read_u32_array(pp->dev->of_node,
+ "fsl,pcie-scfg", index, 2)) {
+ pcie->scfg = NULL;
+ return;
+ }
+ pcie->index = index[1];
dw_pcie_setup_rc(pp);
- ls_pcie_establish_link(pp);
/*
* LS1021A Workaround for internal TKT228622
@@ -93,21 +125,97 @@ static void ls_pcie_host_init(struct pcie_port *pp)
iowrite32(val, pcie->dbi + PCIE_STRFMR1);
}
+static int ls_pcie_link_up(struct pcie_port *pp)
+{
+ struct ls_pcie *pcie = to_ls_pcie(pp);
+ u32 state;
+
+ state = (ioread32(pcie->lut + PCIE_LUT_DBG) >>
+ pcie->drvdata->ltssm_shift) &
+ LTSSM_STATE_MASK;
+
+ if (state < LTSSM_PCIE_L0)
+ return 0;
+
+ return 1;
+}
+
+static void ls_pcie_host_init(struct pcie_port *pp)
+{
+ struct ls_pcie *pcie = to_ls_pcie(pp);
+
+ iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
+ ls_pcie_fix_class(pcie);
+ ls_pcie_clear_multifunction(pcie);
+ iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
+}
+
+static int ls_pcie_msi_host_init(struct pcie_port *pp,
+ struct msi_controller *chip)
+{
+ struct device_node *msi_node;
+ struct device_node *np = pp->dev->of_node;
+
+ /*
+ * The MSI domain is set by the generic of_msi_configure(). This
+ * .msi_host_init() function keeps us from doing the default MSI
+ * domain setup in dw_pcie_host_init() and also enforces the
+ * requirement that "msi-parent" exists.
+ */
+ msi_node = of_parse_phandle(np, "msi-parent", 0);
+ if (!msi_node) {
+ dev_err(pp->dev, "failed to find msi-parent\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct pcie_host_ops ls1021_pcie_host_ops = {
+ .link_up = ls1021_pcie_link_up,
+ .host_init = ls1021_pcie_host_init,
+ .msi_host_init = ls_pcie_msi_host_init,
+};
+
static struct pcie_host_ops ls_pcie_host_ops = {
.link_up = ls_pcie_link_up,
.host_init = ls_pcie_host_init,
+ .msi_host_init = ls_pcie_msi_host_init,
+};
+
+static struct ls_pcie_drvdata ls1021_drvdata = {
+ .ops = &ls1021_pcie_host_ops,
+};
+
+static struct ls_pcie_drvdata ls1043_drvdata = {
+ .lut_offset = 0x10000,
+ .ltssm_shift = 24,
+ .ops = &ls_pcie_host_ops,
};
-static int ls_add_pcie_port(struct ls_pcie *pcie)
+static struct ls_pcie_drvdata ls2080_drvdata = {
+ .lut_offset = 0x80000,
+ .ltssm_shift = 0,
+ .ops = &ls_pcie_host_ops,
+};
+
+static const struct of_device_id ls_pcie_of_match[] = {
+ { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
+ { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
+ { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
+
+static int __init ls_add_pcie_port(struct pcie_port *pp,
+ struct platform_device *pdev)
{
- struct pcie_port *pp;
int ret;
+ struct ls_pcie *pcie = to_ls_pcie(pp);
- pp = &pcie->pp;
- pp->dev = pcie->dev;
+ pp->dev = &pdev->dev;
pp->dbi_base = pcie->dbi;
- pp->root_bus_nr = -1;
- pp->ops = &ls_pcie_host_ops;
+ pp->ops = pcie->drvdata->ops;
ret = dw_pcie_host_init(pp);
if (ret) {
@@ -120,17 +228,19 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
static int __init ls_pcie_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match;
struct ls_pcie *pcie;
struct resource *dbi_base;
- u32 index[2];
int ret;
+ match = of_match_device(ls_pcie_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
return -ENOMEM;
- pcie->dev = &pdev->dev;
-
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base);
if (IS_ERR(pcie->dbi)) {
@@ -138,20 +248,13 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
return PTR_ERR(pcie->dbi);
}
- pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
- "fsl,pcie-scfg");
- if (IS_ERR(pcie->scfg)) {
- dev_err(&pdev->dev, "No syscfg phandle specified\n");
- return PTR_ERR(pcie->scfg);
- }
+ pcie->drvdata = match->data;
+ pcie->lut = pcie->dbi + pcie->drvdata->lut_offset;
- ret = of_property_read_u32_array(pdev->dev.of_node,
- "fsl,pcie-scfg", index, 2);
- if (ret)
- return ret;
- pcie->index = index[1];
+ if (!ls_pcie_is_bridge(pcie))
+ return -ENODEV;
- ret = ls_add_pcie_port(pcie);
+ ret = ls_add_pcie_port(&pcie->pp, pdev);
if (ret < 0)
return ret;
@@ -160,12 +263,6 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id ls_pcie_of_match[] = {
- { .compatible = "fsl,ls1021a-pcie" },
- { },
-};
-MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
-
static struct platform_driver ls_pcie_driver = {
.driver = {
.name = "layerscape-pcie",
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 67ec5e1c99db..53b79c5f0559 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -30,6 +30,7 @@
#define PCIE_DEV_REV_OFF 0x0008
#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3))
#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3))
+#define PCIE_CAP_PCIEXP 0x0060
#define PCIE_HEADER_LOG_4_OFF 0x0128
#define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4))
#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4))
@@ -57,14 +58,35 @@
#define PCIE_STAT_BUS 0xff00
#define PCIE_STAT_DEV 0x1f0000
#define PCIE_STAT_LINK_DOWN BIT(0)
+#define PCIE_RC_RTSTA 0x1a14
#define PCIE_DEBUG_CTRL 0x1a60
#define PCIE_DEBUG_SOFT_RESET BIT(20)
+enum {
+ PCISWCAP = PCI_BRIDGE_CONTROL + 2,
+ PCISWCAP_EXP_LIST_ID = PCISWCAP + PCI_CAP_LIST_ID,
+ PCISWCAP_EXP_DEVCAP = PCISWCAP + PCI_EXP_DEVCAP,
+ PCISWCAP_EXP_DEVCTL = PCISWCAP + PCI_EXP_DEVCTL,
+ PCISWCAP_EXP_LNKCAP = PCISWCAP + PCI_EXP_LNKCAP,
+ PCISWCAP_EXP_LNKCTL = PCISWCAP + PCI_EXP_LNKCTL,
+ PCISWCAP_EXP_SLTCAP = PCISWCAP + PCI_EXP_SLTCAP,
+ PCISWCAP_EXP_SLTCTL = PCISWCAP + PCI_EXP_SLTCTL,
+ PCISWCAP_EXP_RTCTL = PCISWCAP + PCI_EXP_RTCTL,
+ PCISWCAP_EXP_RTSTA = PCISWCAP + PCI_EXP_RTSTA,
+ PCISWCAP_EXP_DEVCAP2 = PCISWCAP + PCI_EXP_DEVCAP2,
+ PCISWCAP_EXP_DEVCTL2 = PCISWCAP + PCI_EXP_DEVCTL2,
+ PCISWCAP_EXP_LNKCAP2 = PCISWCAP + PCI_EXP_LNKCAP2,
+ PCISWCAP_EXP_LNKCTL2 = PCISWCAP + PCI_EXP_LNKCTL2,
+ PCISWCAP_EXP_SLTCAP2 = PCISWCAP + PCI_EXP_SLTCAP2,
+ PCISWCAP_EXP_SLTCTL2 = PCISWCAP + PCI_EXP_SLTCTL2,
+};
+
/* PCI configuration space of a PCI-to-PCI bridge */
struct mvebu_sw_pci_bridge {
u16 vendor;
u16 device;
u16 command;
+ u16 status;
u16 class;
u8 interface;
u8 revision;
@@ -84,13 +106,15 @@ struct mvebu_sw_pci_bridge {
u16 memlimit;
u16 iobaseupper;
u16 iolimitupper;
- u8 cappointer;
- u8 reserved1;
- u16 reserved2;
u32 romaddr;
u8 intline;
u8 intpin;
u16 bridgectrl;
+
+ /* PCI express capability */
+ u32 pcie_sltcap;
+ u16 pcie_devctl;
+ u16 pcie_rtctl;
};
struct mvebu_pcie_port;
@@ -119,8 +143,7 @@ struct mvebu_pcie_port {
unsigned int io_target;
unsigned int io_attr;
struct clk *clk;
- int reset_gpio;
- int reset_active_low;
+ struct gpio_desc *reset_gpio;
char *reset_name;
struct mvebu_sw_pci_bridge bridge;
struct device_node *dn;
@@ -254,15 +277,22 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
struct pci_bus *bus,
u32 devfn, int where, int size, u32 *val)
{
+ void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
+
mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
PCIE_CONF_ADDR_OFF);
- *val = mvebu_readl(port, PCIE_CONF_DATA_OFF);
-
- if (size == 1)
- *val = (*val >> (8 * (where & 3))) & 0xff;
- else if (size == 2)
- *val = (*val >> (8 * (where & 3))) & 0xffff;
+ switch (size) {
+ case 1:
+ *val = readb_relaxed(conf_data + (where & 3));
+ break;
+ case 2:
+ *val = readw_relaxed(conf_data + (where & 2));
+ break;
+ case 4:
+ *val = readl_relaxed(conf_data);
+ break;
+ }
return PCIBIOS_SUCCESSFUL;
}
@@ -271,22 +301,24 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
struct pci_bus *bus,
u32 devfn, int where, int size, u32 val)
{
- u32 _val, shift = 8 * (where & 3);
+ void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
PCIE_CONF_ADDR_OFF);
- _val = mvebu_readl(port, PCIE_CONF_DATA_OFF);
- if (size == 4)
- _val = val;
- else if (size == 2)
- _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
- else if (size == 1)
- _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
- else
+ switch (size) {
+ case 1:
+ writeb(val, conf_data + (where & 3));
+ break;
+ case 2:
+ writew(val, conf_data + (where & 2));
+ break;
+ case 4:
+ writel(val, conf_data);
+ break;
+ default:
return PCIBIOS_BAD_REGISTER_NUMBER;
-
- mvebu_writel(port, _val, PCIE_CONF_DATA_OFF);
+ }
return PCIBIOS_SUCCESSFUL;
}
@@ -443,6 +475,9 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
/* We support 32 bits I/O addressing */
bridge->iobase = PCI_IO_RANGE_TYPE_32;
bridge->iolimit = PCI_IO_RANGE_TYPE_32;
+
+ /* Add capabilities */
+ bridge->status = PCI_STATUS_CAP_LIST;
}
/*
@@ -460,7 +495,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
break;
case PCI_COMMAND:
- *value = bridge->command;
+ *value = bridge->command | bridge->status << 16;
break;
case PCI_CLASS_REVISION:
@@ -505,6 +540,10 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
*value = (bridge->iolimitupper << 16 | bridge->iobaseupper);
break;
+ case PCI_CAPABILITY_LIST:
+ *value = PCISWCAP;
+ break;
+
case PCI_ROM_ADDRESS1:
*value = 0;
break;
@@ -514,9 +553,67 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
*value = 0;
break;
+ case PCISWCAP_EXP_LIST_ID:
+ /* Set PCIe v2, root port, slot support */
+ *value = (PCI_EXP_TYPE_ROOT_PORT << 4 | 2 |
+ PCI_EXP_FLAGS_SLOT) << 16 | PCI_CAP_ID_EXP;
+ break;
+
+ case PCISWCAP_EXP_DEVCAP:
+ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCAP);
+ break;
+
+ case PCISWCAP_EXP_DEVCTL:
+ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL) &
+ ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE |
+ PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE);
+ *value |= bridge->pcie_devctl;
+ break;
+
+ case PCISWCAP_EXP_LNKCAP:
+ /*
+ * PCIe requires the clock power management capability to be
+ * hard-wired to zero for downstream ports
+ */
+ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP) &
+ ~PCI_EXP_LNKCAP_CLKPM;
+ break;
+
+ case PCISWCAP_EXP_LNKCTL:
+ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL);
+ break;
+
+ case PCISWCAP_EXP_SLTCAP:
+ *value = bridge->pcie_sltcap;
+ break;
+
+ case PCISWCAP_EXP_SLTCTL:
+ *value = PCI_EXP_SLTSTA_PDS << 16;
+ break;
+
+ case PCISWCAP_EXP_RTCTL:
+ *value = bridge->pcie_rtctl;
+ break;
+
+ case PCISWCAP_EXP_RTSTA:
+ *value = mvebu_readl(port, PCIE_RC_RTSTA);
+ break;
+
+ /* PCIe requires the v2 fields to be hard-wired to zero */
+ case PCISWCAP_EXP_DEVCAP2:
+ case PCISWCAP_EXP_DEVCTL2:
+ case PCISWCAP_EXP_LNKCAP2:
+ case PCISWCAP_EXP_LNKCTL2:
+ case PCISWCAP_EXP_SLTCAP2:
+ case PCISWCAP_EXP_SLTCTL2:
default:
- *value = 0xffffffff;
- return PCIBIOS_BAD_REGISTER_NUMBER;
+ /*
+ * PCI defines configuration read accesses to reserved or
+ * unimplemented registers to read as zero and complete
+ * normally.
+ */
+ *value = 0;
+ return PCIBIOS_SUCCESSFUL;
}
if (size == 2)
@@ -601,6 +698,51 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
mvebu_pcie_set_local_bus_nr(port, bridge->secondary_bus);
break;
+ case PCISWCAP_EXP_DEVCTL:
+ /*
+ * Armada370 data says these bits must always
+ * be zero when in root complex mode.
+ */
+ value &= ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE |
+ PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE);
+
+ /*
+ * If the mask is 0xffff0000, then we only want to write
+ * the device control register, rather than clearing the
+ * RW1C bits in the device status register. Mask out the
+ * status register bits.
+ */
+ if (mask == 0xffff0000)
+ value &= 0xffff;
+
+ mvebu_writel(port, value, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL);
+ break;
+
+ case PCISWCAP_EXP_LNKCTL:
+ /*
+ * If we don't support CLKREQ, we must ensure that the
+ * CLKREQ enable bit always reads zero. Since we haven't
+ * had this capability, and it's dependent on board wiring,
+ * disable it for the time being.
+ */
+ value &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+
+ /*
+ * If the mask is 0xffff0000, then we only want to write
+ * the link control register, rather than clearing the
+ * RW1C bits in the link status register. Mask out the
+ * status register bits.
+ */
+ if (mask == 0xffff0000)
+ value &= 0xffff;
+
+ mvebu_writel(port, value, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL);
+ break;
+
+ case PCISWCAP_EXP_RTSTA:
+ mvebu_writel(port, value, PCIE_RC_RTSTA);
+ break;
+
default:
break;
}
@@ -652,17 +794,6 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
if (!mvebu_pcie_link_up(port))
return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * On the secondary bus, we don't want to expose any other
- * device than the device physically connected in the PCIe
- * slot, visible in slot 0. In slot 1, there's a special
- * Marvell device that only makes sense when the Armada is
- * used as a PCIe endpoint.
- */
- if (bus->number == port->bridge.secondary_bus &&
- PCI_SLOT(devfn) != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
/* Access the real PCIe interface */
ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
where, size, val);
@@ -693,19 +824,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
return PCIBIOS_DEVICE_NOT_FOUND;
}
- /*
- * On the secondary bus, we don't want to expose any other
- * device than the device physically connected in the PCIe
- * slot, visible in slot 0. In slot 1, there's a special
- * Marvell device that only makes sense when the Armada is
- * used as a PCIe endpoint.
- */
- if (bus->number == port->bridge.secondary_bus &&
- PCI_SLOT(devfn) != 0) {
- *val = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
/* Access the real PCIe interface */
ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
where, size, val);
@@ -914,12 +1032,167 @@ static int mvebu_pcie_resume(struct device *dev)
return 0;
}
+static void mvebu_pcie_port_clk_put(void *data)
+{
+ struct mvebu_pcie_port *port = data;
+
+ clk_put(port->clk);
+}
+
+static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
+ struct mvebu_pcie_port *port, struct device_node *child)
+{
+ struct device *dev = &pcie->pdev->dev;
+ enum of_gpio_flags flags;
+ int reset_gpio, ret;
+
+ port->pcie = pcie;
+
+ if (of_property_read_u32(child, "marvell,pcie-port", &port->port)) {
+ dev_warn(dev, "ignoring %s, missing pcie-port property\n",
+ of_node_full_name(child));
+ goto skip;
+ }
+
+ if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane))
+ port->lane = 0;
+
+ port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port,
+ port->lane);
+ if (!port->name) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ port->devfn = of_pci_get_devfn(child);
+ if (port->devfn < 0)
+ goto skip;
+
+ ret = mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_MEM,
+ &port->mem_target, &port->mem_attr);
+ if (ret < 0) {
+ dev_err(dev, "%s: cannot get tgt/attr for mem window\n",
+ port->name);
+ goto skip;
+ }
+
+ if (resource_size(&pcie->io) != 0) {
+ mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO,
+ &port->io_target, &port->io_attr);
+ } else {
+ port->io_target = -1;
+ port->io_attr = -1;
+ }
+
+ reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags);
+ if (reset_gpio == -EPROBE_DEFER) {
+ ret = reset_gpio;
+ goto err;
+ }
+
+ if (gpio_is_valid(reset_gpio)) {
+ unsigned long gpio_flags;
+
+ port->reset_name = devm_kasprintf(dev, GFP_KERNEL, "%s-reset",
+ port->name);
+ if (!port->reset_name) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (flags & OF_GPIO_ACTIVE_LOW) {
+ dev_info(dev, "%s: reset gpio is active low\n",
+ of_node_full_name(child));
+ gpio_flags = GPIOF_ACTIVE_LOW |
+ GPIOF_OUT_INIT_LOW;
+ } else {
+ gpio_flags = GPIOF_OUT_INIT_HIGH;
+ }
+
+ ret = devm_gpio_request_one(dev, reset_gpio, gpio_flags,
+ port->reset_name);
+ if (ret) {
+ if (ret == -EPROBE_DEFER)
+ goto err;
+ goto skip;
+ }
+
+ port->reset_gpio = gpio_to_desc(reset_gpio);
+ }
+
+ port->clk = of_clk_get_by_name(child, NULL);
+ if (IS_ERR(port->clk)) {
+ dev_err(dev, "%s: cannot get clock\n", port->name);
+ goto skip;
+ }
+
+ ret = devm_add_action(dev, mvebu_pcie_port_clk_put, port);
+ if (ret < 0) {
+ clk_put(port->clk);
+ goto err;
+ }
+
+ return 1;
+
+skip:
+ ret = 0;
+
+ /* In the case of skipping, we need to free these */
+ devm_kfree(dev, port->reset_name);
+ port->reset_name = NULL;
+ devm_kfree(dev, port->name);
+ port->name = NULL;
+
+err:
+ return ret;
+}
+
+/*
+ * Power up a PCIe port. PCIe requires the refclk to be stable for 100µs
+ * prior to releasing PERST. See table 2-4 in section 2.6.2 AC Specifications
+ * of the PCI Express Card Electromechanical Specification, 1.1.
+ */
+static int mvebu_pcie_powerup(struct mvebu_pcie_port *port)
+{
+ int ret;
+
+ ret = clk_prepare_enable(port->clk);
+ if (ret < 0)
+ return ret;
+
+ if (port->reset_gpio) {
+ u32 reset_udelay = 20000;
+
+ of_property_read_u32(port->dn, "reset-delay-us",
+ &reset_udelay);
+
+ udelay(100);
+
+ gpiod_set_value_cansleep(port->reset_gpio, 0);
+ msleep(reset_udelay / 1000);
+ }
+
+ return 0;
+}
+
+/*
+ * Power down a PCIe port. Strictly, PCIe requires us to place the card
+ * in D3hot state before asserting PERST#.
+ */
+static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port)
+{
+ if (port->reset_gpio)
+ gpiod_set_value_cansleep(port->reset_gpio, 1);
+
+ clk_disable_unprepare(port->clk);
+}
+
static int mvebu_pcie_probe(struct platform_device *pdev)
{
struct mvebu_pcie *pcie;
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
- int i, ret;
+ int num, i, ret;
pcie = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pcie),
GFP_KERNEL);
@@ -955,112 +1228,52 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
return ret;
}
- i = 0;
- for_each_child_of_node(pdev->dev.of_node, child) {
- if (!of_device_is_available(child))
- continue;
- i++;
- }
+ num = of_get_available_child_count(pdev->dev.of_node);
- pcie->ports = devm_kzalloc(&pdev->dev, i *
- sizeof(struct mvebu_pcie_port),
+ pcie->ports = devm_kcalloc(&pdev->dev, num, sizeof(*pcie->ports),
GFP_KERNEL);
if (!pcie->ports)
return -ENOMEM;
i = 0;
- for_each_child_of_node(pdev->dev.of_node, child) {
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
struct mvebu_pcie_port *port = &pcie->ports[i];
- enum of_gpio_flags flags;
-
- if (!of_device_is_available(child))
- continue;
- port->pcie = pcie;
-
- if (of_property_read_u32(child, "marvell,pcie-port",
- &port->port)) {
- dev_warn(&pdev->dev,
- "ignoring PCIe DT node, missing pcie-port property\n");
- continue;
- }
-
- if (of_property_read_u32(child, "marvell,pcie-lane",
- &port->lane))
- port->lane = 0;
-
- port->name = kasprintf(GFP_KERNEL, "pcie%d.%d",
- port->port, port->lane);
-
- port->devfn = of_pci_get_devfn(child);
- if (port->devfn < 0)
- continue;
-
- ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM,
- &port->mem_target, &port->mem_attr);
+ ret = mvebu_pcie_parse_port(pcie, port, child);
if (ret < 0) {
- dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n",
- port->port, port->lane);
+ of_node_put(child);
+ return ret;
+ } else if (ret == 0) {
continue;
}
- if (resource_size(&pcie->io) != 0)
- mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
- &port->io_target, &port->io_attr);
- else {
- port->io_target = -1;
- port->io_attr = -1;
- }
+ port->dn = child;
+ i++;
+ }
+ pcie->nports = i;
- port->reset_gpio = of_get_named_gpio_flags(child,
- "reset-gpios", 0, &flags);
- if (gpio_is_valid(port->reset_gpio)) {
- u32 reset_udelay = 20000;
-
- port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
- port->reset_name = kasprintf(GFP_KERNEL,
- "pcie%d.%d-reset", port->port, port->lane);
- of_property_read_u32(child, "reset-delay-us",
- &reset_udelay);
-
- ret = devm_gpio_request_one(&pdev->dev,
- port->reset_gpio, GPIOF_DIR_OUT, port->reset_name);
- if (ret) {
- if (ret == -EPROBE_DEFER)
- return ret;
- continue;
- }
-
- gpio_set_value(port->reset_gpio,
- (port->reset_active_low) ? 1 : 0);
- msleep(reset_udelay/1000);
- }
+ for (i = 0; i < pcie->nports; i++) {
+ struct mvebu_pcie_port *port = &pcie->ports[i];
- port->clk = of_clk_get_by_name(child, NULL);
- if (IS_ERR(port->clk)) {
- dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
- port->port, port->lane);
+ child = port->dn;
+ if (!child)
continue;
- }
- ret = clk_prepare_enable(port->clk);
- if (ret)
+ ret = mvebu_pcie_powerup(port);
+ if (ret < 0)
continue;
port->base = mvebu_pcie_map_registers(pdev, child, port);
if (IS_ERR(port->base)) {
- dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
- port->port, port->lane);
+ dev_err(&pdev->dev, "%s: cannot map registers\n",
+ port->name);
port->base = NULL;
- clk_disable_unprepare(port->clk);
+ mvebu_pcie_powerdown(port);
continue;
}
mvebu_pcie_set_local_dev_nr(port, 1);
-
- port->dn = child;
mvebu_sw_pci_bridge_init(port);
- i++;
}
pcie->nports = i;
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 81df0c1fe063..3018ae52e092 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -382,8 +382,8 @@ static unsigned long tegra_pcie_conf_offset(unsigned int devfn, int where)
static struct tegra_pcie_bus *tegra_pcie_bus_alloc(struct tegra_pcie *pcie,
unsigned int busnr)
{
- pgprot_t prot = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_XN |
- L_PTE_MT_DEV_SHARED | L_PTE_SHARED;
+ pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_XN | L_PTE_MT_DEV_SHARED | L_PTE_SHARED);
phys_addr_t cs = pcie->cs->start;
struct tegra_pcie_bus *bus;
unsigned int i;
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index e491681daf22..a6456b578269 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -256,7 +256,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
if (!msi->inner_domain)
return -ENOMEM;
- msi->msi_domain = pci_msi_create_irq_domain(msi->node,
+ msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
&xgene_msi_domain_info,
msi->inner_domain);
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index 0236ab9d5720..ae00ce22d5a6 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -509,24 +509,6 @@ static int xgene_pcie_setup(struct xgene_pcie_port *port,
return 0;
}
-static int xgene_pcie_msi_enable(struct pci_bus *bus)
-{
- struct device_node *msi_node;
-
- msi_node = of_parse_phandle(bus->dev.of_node,
- "msi-parent", 0);
- if (!msi_node)
- return -ENODEV;
-
- bus->msi = of_pci_find_msi_chip_by_node(msi_node);
- if (!bus->msi)
- return -ENODEV;
-
- of_node_put(msi_node);
- bus->msi->dev = &bus->dev;
- return 0;
-}
-
static int xgene_pcie_probe_bridge(struct platform_device *pdev)
{
struct device_node *dn = pdev->dev.of_node;
@@ -567,10 +549,6 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (!bus)
return -ENOMEM;
- if (IS_ENABLED(CONFIG_PCI_MSI))
- if (xgene_pcie_msi_enable(bus))
- dev_info(port->dev, "failed to enable MSI\n");
-
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
pci_bus_add_devices(bus);
diff --git a/drivers/pci/host/pcie-altera-msi.c b/drivers/pci/host/pcie-altera-msi.c
new file mode 100644
index 000000000000..99177f4ccde2
--- /dev/null
+++ b/drivers/pci/host/pcie-altera-msi.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright Altera Corporation (C) 2013-2015. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define MSI_STATUS 0x0
+#define MSI_ERROR 0x4
+#define MSI_INTMASK 0x8
+
+#define MAX_MSI_VECTORS 32
+
+struct altera_msi {
+ DECLARE_BITMAP(used, MAX_MSI_VECTORS);
+ struct mutex lock; /* protect "used" bitmap */
+ struct platform_device *pdev;
+ struct irq_domain *msi_domain;
+ struct irq_domain *inner_domain;
+ void __iomem *csr_base;
+ void __iomem *vector_base;
+ phys_addr_t vector_phy;
+ u32 num_of_vectors;
+ int irq;
+};
+
+static inline void msi_writel(struct altera_msi *msi, const u32 value,
+ const u32 reg)
+{
+ writel_relaxed(value, msi->csr_base + reg);
+}
+
+static inline u32 msi_readl(struct altera_msi *msi, const u32 reg)
+{
+ return readl_relaxed(msi->csr_base + reg);
+}
+
+static void altera_msi_isr(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct altera_msi *msi;
+ unsigned long status;
+ u32 num_of_vectors;
+ u32 bit;
+ u32 virq;
+
+ chained_irq_enter(chip, desc);
+ msi = irq_desc_get_handler_data(desc);
+ num_of_vectors = msi->num_of_vectors;
+
+ while ((status = msi_readl(msi, MSI_STATUS)) != 0) {
+ for_each_set_bit(bit, &status, msi->num_of_vectors) {
+ /* Dummy read from vector to clear the interrupt */
+ readl_relaxed(msi->vector_base + (bit * sizeof(u32)));
+
+ virq = irq_find_mapping(msi->inner_domain, bit);
+ if (virq)
+ generic_handle_irq(virq);
+ else
+ dev_err(&msi->pdev->dev, "unexpected MSI\n");
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip altera_msi_irq_chip = {
+ .name = "Altera PCIe MSI",
+ .irq_mask = pci_msi_mask_irq,
+ .irq_unmask = pci_msi_unmask_irq,
+};
+
+static struct msi_domain_info altera_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_PCI_MSIX),
+ .chip = &altera_msi_irq_chip,
+};
+
+static void altera_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct altera_msi *msi = irq_data_get_irq_chip_data(data);
+ phys_addr_t addr = msi->vector_phy + (data->hwirq * sizeof(u32));
+
+ msg->address_lo = lower_32_bits(addr);
+ msg->address_hi = upper_32_bits(addr);
+ msg->data = data->hwirq;
+
+ dev_dbg(&msi->pdev->dev, "msi#%d address_hi %#x address_lo %#x\n",
+ (int)data->hwirq, msg->address_hi, msg->address_lo);
+}
+
+static int altera_msi_set_affinity(struct irq_data *irq_data,
+ const struct cpumask *mask, bool force)
+{
+ return -EINVAL;
+}
+
+static struct irq_chip altera_msi_bottom_irq_chip = {
+ .name = "Altera MSI",
+ .irq_compose_msi_msg = altera_compose_msi_msg,
+ .irq_set_affinity = altera_msi_set_affinity,
+};
+
+static int altera_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *args)
+{
+ struct altera_msi *msi = domain->host_data;
+ unsigned long bit;
+ u32 mask;
+
+ WARN_ON(nr_irqs != 1);
+ mutex_lock(&msi->lock);
+
+ bit = find_first_zero_bit(msi->used, msi->num_of_vectors);
+ if (bit >= msi->num_of_vectors) {
+ mutex_unlock(&msi->lock);
+ return -ENOSPC;
+ }
+
+ set_bit(bit, msi->used);
+
+ mutex_unlock(&msi->lock);
+
+ irq_domain_set_info(domain, virq, bit, &altera_msi_bottom_irq_chip,
+ domain->host_data, handle_simple_irq,
+ NULL, NULL);
+
+ mask = msi_readl(msi, MSI_INTMASK);
+ mask |= 1 << bit;
+ msi_writel(msi, mask, MSI_INTMASK);
+
+ return 0;
+}
+
+static void altera_irq_domain_free(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct altera_msi *msi = irq_data_get_irq_chip_data(d);
+ u32 mask;
+
+ mutex_lock(&msi->lock);
+
+ if (!test_bit(d->hwirq, msi->used)) {
+ dev_err(&msi->pdev->dev, "trying to free unused MSI#%lu\n",
+ d->hwirq);
+ } else {
+ __clear_bit(d->hwirq, msi->used);
+ mask = msi_readl(msi, MSI_INTMASK);
+ mask &= ~(1 << d->hwirq);
+ msi_writel(msi, mask, MSI_INTMASK);
+ }
+
+ mutex_unlock(&msi->lock);
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+ .alloc = altera_irq_domain_alloc,
+ .free = altera_irq_domain_free,
+};
+
+static int altera_allocate_domains(struct altera_msi *msi)
+{
+ struct fwnode_handle *fwnode = of_node_to_fwnode(msi->pdev->dev.of_node);
+
+ msi->inner_domain = irq_domain_add_linear(NULL, msi->num_of_vectors,
+ &msi_domain_ops, msi);
+ if (!msi->inner_domain) {
+ dev_err(&msi->pdev->dev, "failed to create IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+ &altera_msi_domain_info, msi->inner_domain);
+ if (!msi->msi_domain) {
+ dev_err(&msi->pdev->dev, "failed to create MSI domain\n");
+ irq_domain_remove(msi->inner_domain);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void altera_free_domains(struct altera_msi *msi)
+{
+ irq_domain_remove(msi->msi_domain);
+ irq_domain_remove(msi->inner_domain);
+}
+
+static int altera_msi_remove(struct platform_device *pdev)
+{
+ struct altera_msi *msi = platform_get_drvdata(pdev);
+
+ msi_writel(msi, 0, MSI_INTMASK);
+ irq_set_chained_handler(msi->irq, NULL);
+ irq_set_handler_data(msi->irq, NULL);
+
+ altera_free_domains(msi);
+
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static int altera_msi_probe(struct platform_device *pdev)
+{
+ struct altera_msi *msi;
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ int ret;
+
+ msi = devm_kzalloc(&pdev->dev, sizeof(struct altera_msi),
+ GFP_KERNEL);
+ if (!msi)
+ return -ENOMEM;
+
+ mutex_init(&msi->lock);
+ msi->pdev = pdev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr");
+ if (!res) {
+ dev_err(&pdev->dev, "no csr memory resource defined\n");
+ return -ENODEV;
+ }
+
+ msi->csr_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(msi->csr_base)) {
+ dev_err(&pdev->dev, "failed to map csr memory\n");
+ return PTR_ERR(msi->csr_base);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "vector_slave");
+ if (!res) {
+ dev_err(&pdev->dev, "no vector_slave memory resource defined\n");
+ return -ENODEV;
+ }
+
+ msi->vector_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(msi->vector_base)) {
+ dev_err(&pdev->dev, "failed to map vector_slave memory\n");
+ return PTR_ERR(msi->vector_base);
+ }
+
+ msi->vector_phy = res->start;
+
+ if (of_property_read_u32(np, "num-vectors", &msi->num_of_vectors)) {
+ dev_err(&pdev->dev, "failed to parse the number of vectors\n");
+ return -EINVAL;
+ }
+
+ ret = altera_allocate_domains(msi);
+ if (ret)
+ return ret;
+
+ msi->irq = platform_get_irq(pdev, 0);
+ if (msi->irq <= 0) {
+ dev_err(&pdev->dev, "failed to map IRQ: %d\n", msi->irq);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ irq_set_chained_handler_and_data(msi->irq, altera_msi_isr, msi);
+ platform_set_drvdata(pdev, msi);
+
+ return 0;
+
+err:
+ altera_msi_remove(pdev);
+ return ret;
+}
+
+static const struct of_device_id altera_msi_of_match[] = {
+ { .compatible = "altr,msi-1.0", NULL },
+ { },
+};
+
+static struct platform_driver altera_msi_driver = {
+ .driver = {
+ .name = "altera-msi",
+ .of_match_table = altera_msi_of_match,
+ },
+ .probe = altera_msi_probe,
+ .remove = altera_msi_remove,
+};
+
+static int __init altera_msi_init(void)
+{
+ return platform_driver_register(&altera_msi_driver);
+}
+subsys_initcall(altera_msi_init);
+
+MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>");
+MODULE_DESCRIPTION("Altera PCIe MSI support");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c
new file mode 100644
index 000000000000..e5dda38bdde5
--- /dev/null
+++ b/drivers/pci/host/pcie-altera.c
@@ -0,0 +1,579 @@
+/*
+ * Copyright Altera Corporation (C) 2013-2015. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define RP_TX_REG0 0x2000
+#define RP_TX_REG1 0x2004
+#define RP_TX_CNTRL 0x2008
+#define RP_TX_EOP 0x2
+#define RP_TX_SOP 0x1
+#define RP_RXCPL_STATUS 0x2010
+#define RP_RXCPL_EOP 0x2
+#define RP_RXCPL_SOP 0x1
+#define RP_RXCPL_REG0 0x2014
+#define RP_RXCPL_REG1 0x2018
+#define P2A_INT_STATUS 0x3060
+#define P2A_INT_STS_ALL 0xf
+#define P2A_INT_ENABLE 0x3070
+#define P2A_INT_ENA_ALL 0xf
+#define RP_LTSSM 0x3c64
+#define LTSSM_L0 0xf
+
+/* TLP configuration type 0 and 1 */
+#define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */
+#define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */
+#define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */
+#define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */
+#define TLP_PAYLOAD_SIZE 0x01
+#define TLP_READ_TAG 0x1d
+#define TLP_WRITE_TAG 0x10
+#define TLP_CFG_DW0(fmttype) (((fmttype) << 24) | TLP_PAYLOAD_SIZE)
+#define TLP_CFG_DW1(reqid, tag, be) (((reqid) << 16) | (tag << 8) | (be))
+#define TLP_CFG_DW2(bus, devfn, offset) \
+ (((bus) << 24) | ((devfn) << 16) | (offset))
+#define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn))
+#define TLP_HDR_SIZE 3
+#define TLP_LOOP 500
+
+#define INTX_NUM 4
+
+#define DWORD_MASK 3
+
+struct altera_pcie {
+ struct platform_device *pdev;
+ void __iomem *cra_base;
+ int irq;
+ u8 root_bus_nr;
+ struct irq_domain *irq_domain;
+ struct resource bus_range;
+ struct list_head resources;
+};
+
+struct tlp_rp_regpair_t {
+ u32 ctrl;
+ u32 reg0;
+ u32 reg1;
+};
+
+static void altera_pcie_retrain(struct pci_dev *dev)
+{
+ u16 linkcap, linkstat;
+
+ /*
+ * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
+ * current speed is 2.5 GB/s.
+ */
+ pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap);
+
+ if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
+ return;
+
+ pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat);
+ if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB)
+ pcie_capability_set_word(dev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_RL);
+}
+DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain);
+
+/*
+ * Altera PCIe port uses BAR0 of RC's configuration space as the translation
+ * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space
+ * using these registers, so it can be reached by DMA from EP devices.
+ * This BAR0 will also access to MSI vector when receiving MSI/MSIX interrupt
+ * from EP devices, eventually trigger interrupt to GIC. The BAR0 of bridge
+ * should be hidden during enumeration to avoid the sizing and resource
+ * allocation by PCIe core.
+ */
+static bool altera_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,
+ int offset)
+{
+ if (pci_is_root_bus(bus) && (devfn == 0) &&
+ (offset == PCI_BASE_ADDRESS_0))
+ return true;
+
+ return false;
+}
+
+static inline void cra_writel(struct altera_pcie *pcie, const u32 value,
+ const u32 reg)
+{
+ writel_relaxed(value, pcie->cra_base + reg);
+}
+
+static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg)
+{
+ return readl_relaxed(pcie->cra_base + reg);
+}
+
+static void tlp_write_tx(struct altera_pcie *pcie,
+ struct tlp_rp_regpair_t *tlp_rp_regdata)
+{
+ cra_writel(pcie, tlp_rp_regdata->reg0, RP_TX_REG0);
+ cra_writel(pcie, tlp_rp_regdata->reg1, RP_TX_REG1);
+ cra_writel(pcie, tlp_rp_regdata->ctrl, RP_TX_CNTRL);
+}
+
+static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
+{
+ return !!(cra_readl(pcie, RP_LTSSM) & LTSSM_L0);
+}
+
+static bool altera_pcie_valid_config(struct altera_pcie *pcie,
+ struct pci_bus *bus, int dev)
+{
+ /* If there is no link, then there is no device */
+ if (bus->number != pcie->root_bus_nr) {
+ if (!altera_pcie_link_is_up(pcie))
+ return false;
+ }
+
+ /* access only one slot on each root port */
+ if (bus->number == pcie->root_bus_nr && dev > 0)
+ return false;
+
+ /*
+ * Do not read more than one device on the bus directly attached
+ * to root port, root port can only attach to one downstream port.
+ */
+ if (bus->primary == pcie->root_bus_nr && dev > 0)
+ return false;
+
+ return true;
+}
+
+static int tlp_read_packet(struct altera_pcie *pcie, u32 *value)
+{
+ u8 loop;
+ bool sop = 0;
+ u32 ctrl;
+ u32 reg0, reg1;
+
+ /*
+ * Minimum 2 loops to read TLP headers and 1 loop to read data
+ * payload.
+ */
+ for (loop = 0; loop < TLP_LOOP; loop++) {
+ ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
+ if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) {
+ reg0 = cra_readl(pcie, RP_RXCPL_REG0);
+ reg1 = cra_readl(pcie, RP_RXCPL_REG1);
+
+ if (ctrl & RP_RXCPL_SOP)
+ sop = true;
+
+ if (ctrl & RP_RXCPL_EOP) {
+ if (value)
+ *value = reg0;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ }
+ udelay(5);
+ }
+
+ return -ENOENT;
+}
+
+static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers,
+ u32 data, bool align)
+{
+ struct tlp_rp_regpair_t tlp_rp_regdata;
+
+ tlp_rp_regdata.reg0 = headers[0];
+ tlp_rp_regdata.reg1 = headers[1];
+ tlp_rp_regdata.ctrl = RP_TX_SOP;
+ tlp_write_tx(pcie, &tlp_rp_regdata);
+
+ if (align) {
+ tlp_rp_regdata.reg0 = headers[2];
+ tlp_rp_regdata.reg1 = 0;
+ tlp_rp_regdata.ctrl = 0;
+ tlp_write_tx(pcie, &tlp_rp_regdata);
+
+ tlp_rp_regdata.reg0 = data;
+ tlp_rp_regdata.reg1 = 0;
+ } else {
+ tlp_rp_regdata.reg0 = headers[2];
+ tlp_rp_regdata.reg1 = data;
+ }
+
+ tlp_rp_regdata.ctrl = RP_TX_EOP;
+ tlp_write_tx(pcie, &tlp_rp_regdata);
+}
+
+static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn,
+ int where, u8 byte_en, u32 *value)
+{
+ u32 headers[TLP_HDR_SIZE];
+
+ if (bus == pcie->root_bus_nr)
+ headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD0);
+ else
+ headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1);
+
+ headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
+ TLP_READ_TAG, byte_en);
+ headers[2] = TLP_CFG_DW2(bus, devfn, where);
+
+ tlp_write_packet(pcie, headers, 0, false);
+
+ return tlp_read_packet(pcie, value);
+}
+
+static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn,
+ int where, u8 byte_en, u32 value)
+{
+ u32 headers[TLP_HDR_SIZE];
+ int ret;
+
+ if (bus == pcie->root_bus_nr)
+ headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR0);
+ else
+ headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1);
+
+ headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
+ TLP_WRITE_TAG, byte_en);
+ headers[2] = TLP_CFG_DW2(bus, devfn, where);
+
+ /* check alignment to Qword */
+ if ((where & 0x7) == 0)
+ tlp_write_packet(pcie, headers, value, true);
+ else
+ tlp_write_packet(pcie, headers, value, false);
+
+ ret = tlp_read_packet(pcie, NULL);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+
+ /*
+ * Monitor changes to PCI_PRIMARY_BUS register on root port
+ * and update local copy of root bus number accordingly.
+ */
+ if ((bus == pcie->root_bus_nr) && (where == PCI_PRIMARY_BUS))
+ pcie->root_bus_nr = (u8)(value);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ struct altera_pcie *pcie = bus->sysdata;
+ int ret;
+ u32 data;
+ u8 byte_en;
+
+ if (altera_pcie_hide_rc_bar(bus, devfn, where))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
+ *value = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ switch (size) {
+ case 1:
+ byte_en = 1 << (where & 3);
+ break;
+ case 2:
+ byte_en = 3 << (where & 3);
+ break;
+ default:
+ byte_en = 0xf;
+ break;
+ }
+
+ ret = tlp_cfg_dword_read(pcie, bus->number, devfn,
+ (where & ~DWORD_MASK), byte_en, &data);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+
+ switch (size) {
+ case 1:
+ *value = (data >> (8 * (where & 0x3))) & 0xff;
+ break;
+ case 2:
+ *value = (data >> (8 * (where & 0x2))) & 0xffff;
+ break;
+ default:
+ *value = data;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ struct altera_pcie *pcie = bus->sysdata;
+ u32 data32;
+ u32 shift = 8 * (where & 3);
+ u8 byte_en;
+
+ if (altera_pcie_hide_rc_bar(bus, devfn, where))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (size) {
+ case 1:
+ data32 = (value & 0xff) << shift;
+ byte_en = 1 << (where & 3);
+ break;
+ case 2:
+ data32 = (value & 0xffff) << shift;
+ byte_en = 3 << (where & 3);
+ break;
+ default:
+ data32 = value;
+ byte_en = 0xf;
+ break;
+ }
+
+ return tlp_cfg_dword_write(pcie, bus->number, devfn,
+ (where & ~DWORD_MASK), byte_en, data32);
+}
+
+static struct pci_ops altera_pcie_ops = {
+ .read = altera_pcie_cfg_read,
+ .write = altera_pcie_cfg_write,
+};
+
+static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+ .map = altera_pcie_intx_map,
+};
+
+static void altera_pcie_isr(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct altera_pcie *pcie;
+ unsigned long status;
+ u32 bit;
+ u32 virq;
+
+ chained_irq_enter(chip, desc);
+ pcie = irq_desc_get_handler_data(desc);
+
+ while ((status = cra_readl(pcie, P2A_INT_STATUS)
+ & P2A_INT_STS_ALL) != 0) {
+ for_each_set_bit(bit, &status, INTX_NUM) {
+ /* clear interrupts */
+ cra_writel(pcie, 1 << bit, P2A_INT_STATUS);
+
+ virq = irq_find_mapping(pcie->irq_domain, bit + 1);
+ if (virq)
+ generic_handle_irq(virq);
+ else
+ dev_err(&pcie->pdev->dev,
+ "unexpected IRQ, INT%d\n", bit);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void altera_pcie_release_of_pci_ranges(struct altera_pcie *pcie)
+{
+ pci_free_resource_list(&pcie->resources);
+}
+
+static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
+{
+ int err, res_valid = 0;
+ struct device *dev = &pcie->pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct resource_entry *win;
+
+ err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pcie->resources,
+ NULL);
+ if (err)
+ return err;
+
+ resource_list_for_each_entry(win, &pcie->resources) {
+ struct resource *parent, *res = win->res;
+
+ switch (resource_type(res)) {
+ case IORESOURCE_MEM:
+ parent = &iomem_resource;
+ res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+ break;
+ default:
+ continue;
+ }
+
+ err = devm_request_resource(dev, parent, res);
+ if (err)
+ goto out_release_res;
+ }
+
+ if (!res_valid) {
+ dev_err(dev, "non-prefetchable memory resource required\n");
+ err = -EINVAL;
+ goto out_release_res;
+ }
+
+ return 0;
+
+out_release_res:
+ altera_pcie_release_of_pci_ranges(pcie);
+ return err;
+}
+
+static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
+{
+ struct device *dev = &pcie->pdev->dev;
+ struct device_node *node = dev->of_node;
+
+ /* Setup INTx */
+ pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM,
+ &intx_domain_ops, pcie);
+ if (!pcie->irq_domain) {
+ dev_err(dev, "Failed to get a INTx IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int altera_pcie_parse_dt(struct altera_pcie *pcie)
+{
+ struct resource *cra;
+ struct platform_device *pdev = pcie->pdev;
+
+ cra = platform_get_resource_byname(pdev, IORESOURCE_MEM, "Cra");
+ if (!cra) {
+ dev_err(&pdev->dev, "no Cra memory resource defined\n");
+ return -ENODEV;
+ }
+
+ pcie->cra_base = devm_ioremap_resource(&pdev->dev, cra);
+ if (IS_ERR(pcie->cra_base)) {
+ dev_err(&pdev->dev, "failed to map cra memory\n");
+ return PTR_ERR(pcie->cra_base);
+ }
+
+ /* setup IRQ */
+ pcie->irq = platform_get_irq(pdev, 0);
+ if (pcie->irq <= 0) {
+ dev_err(&pdev->dev, "failed to get IRQ: %d\n", pcie->irq);
+ return -EINVAL;
+ }
+
+ irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie);
+
+ return 0;
+}
+
+static int altera_pcie_probe(struct platform_device *pdev)
+{
+ struct altera_pcie *pcie;
+ struct pci_bus *bus;
+ struct pci_bus *child;
+ int ret;
+
+ pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+
+ pcie->pdev = pdev;
+
+ ret = altera_pcie_parse_dt(pcie);
+ if (ret) {
+ dev_err(&pdev->dev, "Parsing DT failed\n");
+ return ret;
+ }
+
+ INIT_LIST_HEAD(&pcie->resources);
+
+ ret = altera_pcie_parse_request_of_pci_ranges(pcie);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed add resources\n");
+ return ret;
+ }
+
+ ret = altera_pcie_init_irq_domain(pcie);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed creating IRQ Domain\n");
+ return ret;
+ }
+
+ /* clear all interrupts */
+ cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS);
+ /* enable all interrupts */
+ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
+
+ bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops,
+ pcie, &pcie->resources);
+ if (!bus)
+ return -ENOMEM;
+
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+ pci_assign_unassigned_bus_resources(bus);
+
+ /* Configure PCI Express setting. */
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
+
+ pci_bus_add_devices(bus);
+
+ platform_set_drvdata(pdev, pcie);
+ return ret;
+}
+
+static const struct of_device_id altera_pcie_of_match[] = {
+ { .compatible = "altr,pcie-root-port-1.0", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, altera_pcie_of_match);
+
+static struct platform_driver altera_pcie_driver = {
+ .probe = altera_pcie_probe,
+ .driver = {
+ .name = "altera-pcie",
+ .of_match_table = altera_pcie_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+static int altera_pcie_init(void)
+{
+ return platform_driver_register(&altera_pcie_driver);
+}
+module_init(altera_pcie_init);
+
+MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>");
+MODULE_DESCRIPTION("Altera PCIe host controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 52aa6e34002b..540f077c37ea 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -35,7 +35,7 @@
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
-#define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8)
+#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8)
#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
@@ -69,39 +69,40 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
+int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
{
- BUG_ON(!sys->private_data);
-
- return sys->private_data;
-}
-
-int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
-{
- *val = readl(addr);
+ if ((uintptr_t)addr & (size - 1)) {
+ *val = 0;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
- if (size == 1)
- *val = (*val >> (8 * (where & 3))) & 0xff;
+ if (size == 4)
+ *val = readl(addr);
else if (size == 2)
- *val = (*val >> (8 * (where & 3))) & 0xffff;
- else if (size != 4)
+ *val = readw(addr);
+ else if (size == 1)
+ *val = readb(addr);
+ else {
+ *val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
return PCIBIOS_SUCCESSFUL;
}
-int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val)
+int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val)
{
+ if ((uintptr_t)addr & (size - 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
if (size == 4)
writel(val, addr);
else if (size == 2)
- writew(val, addr + (where & 2));
+ writew(val, addr);
else if (size == 1)
- writeb(val, addr + (where & 3));
+ writeb(val, addr);
else
return PCIBIOS_BAD_REGISTER_NUMBER;
@@ -132,8 +133,7 @@ static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
if (pp->ops->rd_own_conf)
ret = pp->ops->rd_own_conf(pp, where, size, val);
else
- ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where,
- size, val);
+ ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
return ret;
}
@@ -146,8 +146,7 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
if (pp->ops->wr_own_conf)
ret = pp->ops->wr_own_conf(pp, where, size, val);
else
- ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), where,
- size, val);
+ ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
return ret;
}
@@ -205,12 +204,16 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
void dw_pcie_msi_init(struct pcie_port *pp)
{
+ u64 msi_target;
+
pp->msi_data = __get_free_pages(GFP_KERNEL, 0);
+ msi_target = virt_to_phys((void *)pp->msi_data);
/* program the msi_data */
dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
- virt_to_phys((void *)pp->msi_data));
- dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+ (u32)(msi_target & 0xffffffff));
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4,
+ (u32)(msi_target >> 32 & 0xffffffff));
}
static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
@@ -255,7 +258,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
{
int irq, pos0, i;
- struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(desc));
+ struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(desc);
pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
order_base_2(no_irqs));
@@ -286,6 +289,9 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
}
*pos = pos0;
+ desc->nvec_used = no_irqs;
+ desc->msi_attrib.multiple = order_base_2(no_irqs);
+
return irq;
no_valid_irq:
@@ -293,12 +299,32 @@ no_valid_irq:
return -ENOSPC;
}
+static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos)
+{
+ struct msi_msg msg;
+ u64 msi_target;
+
+ if (pp->ops->get_msi_addr)
+ msi_target = pp->ops->get_msi_addr(pp);
+ else
+ msi_target = virt_to_phys((void *)pp->msi_data);
+
+ msg.address_lo = (u32)(msi_target & 0xffffffff);
+ msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff);
+
+ if (pp->ops->get_msi_data)
+ msg.data = pp->ops->get_msi_data(pp, pos);
+ else
+ msg.data = pos;
+
+ pci_write_msi_msg(irq, &msg);
+}
+
static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
struct msi_desc *desc)
{
int irq, pos;
- struct msi_msg msg;
- struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+ struct pcie_port *pp = pdev->bus->sysdata;
if (desc->msi_attrib.is_msix)
return -EINVAL;
@@ -307,33 +333,50 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
if (irq < 0)
return irq;
- if (pp->ops->get_msi_addr)
- msg.address_lo = pp->ops->get_msi_addr(pp);
- else
- msg.address_lo = virt_to_phys((void *)pp->msi_data);
- msg.address_hi = 0x0;
+ dw_msi_setup_msg(pp, irq, pos);
- if (pp->ops->get_msi_data)
- msg.data = pp->ops->get_msi_data(pp, pos);
- else
- msg.data = pos;
+ return 0;
+}
- pci_write_msi_msg(irq, &msg);
+static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev,
+ int nvec, int type)
+{
+#ifdef CONFIG_PCI_MSI
+ int irq, pos;
+ struct msi_desc *desc;
+ struct pcie_port *pp = pdev->bus->sysdata;
+
+ /* MSI-X interrupts are not supported */
+ if (type == PCI_CAP_ID_MSIX)
+ return -EINVAL;
+
+ WARN_ON(!list_is_singular(&pdev->dev.msi_list));
+ desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list);
+
+ irq = assign_irq(nvec, desc, &pos);
+ if (irq < 0)
+ return irq;
+
+ dw_msi_setup_msg(pp, irq, pos);
return 0;
+#else
+ return -EINVAL;
+#endif
}
static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
{
struct irq_data *data = irq_get_irq_data(irq);
struct msi_desc *msi = irq_data_get_msi_desc(data);
- struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+ struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
clear_irq_range(pp, irq, 1, data->hwirq);
}
static struct msi_controller dw_pcie_msi_chip = {
.setup_irq = dw_msi_setup_irq,
+ .setup_irqs = dw_msi_setup_irqs,
.teardown_irq = dw_msi_teardown_irq,
};
@@ -362,18 +405,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
{
struct device_node *np = pp->dev->of_node;
struct platform_device *pdev = to_platform_device(pp->dev);
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus, *child;
struct resource *cfg_res;
- u32 val, na, ns;
- const __be32 *addrp;
- int i, index, ret;
-
- /* Find the address cell size and the number of cells in order to get
- * the untranslated address.
- */
- of_property_read_u32(np, "#address-cells", &na);
- ns = of_n_size_cells(np);
+ u32 val;
+ int i, ret;
+ LIST_HEAD(res);
+ struct resource_entry *win;
cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
if (cfg_res) {
@@ -381,88 +418,61 @@ int dw_pcie_host_init(struct pcie_port *pp)
pp->cfg1_size = resource_size(cfg_res)/2;
pp->cfg0_base = cfg_res->start;
pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
- /* Find the untranslated configuration space address */
- index = of_property_match_string(np, "reg-names", "config");
- addrp = of_get_address(np, index, NULL, NULL);
- pp->cfg0_mod_base = of_read_number(addrp, ns);
- pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
} else if (!pp->va_cfg0_base) {
dev_err(pp->dev, "missing *config* reg space\n");
}
- if (of_pci_range_parser_init(&parser, np)) {
- dev_err(pp->dev, "missing ranges property\n");
- return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+ if (ret)
+ return ret;
/* Get the I/O and memory ranges from DT */
- for_each_of_pci_range(&parser, &range) {
- unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
- if (restype == IORESOURCE_IO) {
- of_pci_range_to_resource(&range, np, &pp->io);
- pp->io.name = "I/O";
- pp->io.start = max_t(resource_size_t,
- PCIBIOS_MIN_IO,
- range.pci_addr + global_io_offset);
- pp->io.end = min_t(resource_size_t,
- IO_SPACE_LIMIT,
- range.pci_addr + range.size
- + global_io_offset - 1);
- pp->io_size = resource_size(&pp->io);
- pp->io_bus_addr = range.pci_addr;
- pp->io_base = range.cpu_addr;
-
- /* Find the untranslated IO space address */
- pp->io_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- }
- if (restype == IORESOURCE_MEM) {
- of_pci_range_to_resource(&range, np, &pp->mem);
- pp->mem.name = "MEM";
- pp->mem_size = resource_size(&pp->mem);
- pp->mem_bus_addr = range.pci_addr;
-
- /* Find the untranslated MEM space address */
- pp->mem_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- }
- if (restype == 0) {
- of_pci_range_to_resource(&range, np, &pp->cfg);
- pp->cfg0_size = resource_size(&pp->cfg)/2;
- pp->cfg1_size = resource_size(&pp->cfg)/2;
- pp->cfg0_base = pp->cfg.start;
- pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
- /* Find the untranslated configuration space address */
- pp->cfg0_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- pp->cfg1_mod_base = pp->cfg0_mod_base +
- pp->cfg0_size;
+ resource_list_for_each_entry(win, &res) {
+ switch (resource_type(win->res)) {
+ case IORESOURCE_IO:
+ pp->io = win->res;
+ pp->io->name = "I/O";
+ pp->io_size = resource_size(pp->io);
+ pp->io_bus_addr = pp->io->start - win->offset;
+ ret = pci_remap_iospace(pp->io, pp->io_base);
+ if (ret) {
+ dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+ ret, pp->io);
+ continue;
+ }
+ pp->io_base = pp->io->start;
+ break;
+ case IORESOURCE_MEM:
+ pp->mem = win->res;
+ pp->mem->name = "MEM";
+ pp->mem_size = resource_size(pp->mem);
+ pp->mem_bus_addr = pp->mem->start - win->offset;
+ break;
+ case 0:
+ pp->cfg = win->res;
+ pp->cfg0_size = resource_size(pp->cfg)/2;
+ pp->cfg1_size = resource_size(pp->cfg)/2;
+ pp->cfg0_base = pp->cfg->start;
+ pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+ break;
+ case IORESOURCE_BUS:
+ pp->busn = win->res;
+ break;
+ default:
+ continue;
}
}
- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
- pp->busn.name = np->name;
- pp->busn.start = 0;
- pp->busn.end = 0xff;
- pp->busn.flags = IORESOURCE_BUS;
- dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
- ret, &pp->busn);
- }
-
if (!pp->dbi_base) {
- pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
- resource_size(&pp->cfg));
+ pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+ resource_size(pp->cfg));
if (!pp->dbi_base) {
dev_err(pp->dev, "error with ioremap\n");
return -ENOMEM;
}
}
- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;
if (!pp->va_cfg0_base) {
pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -482,10 +492,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
}
}
- if (of_property_read_u32(np, "num-lanes", &pp->lanes)) {
- dev_err(pp->dev, "Failed to parse the number of lanes\n");
- return -EINVAL;
- }
+ ret = of_property_read_u32(np, "num-lanes", &pp->lanes);
+ if (ret)
+ pp->lanes = 0;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
if (!pp->ops->msi_host_init) {
@@ -511,7 +520,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (!pp->ops->rd_other_conf)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
- PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+ PCIE_ATU_TYPE_MEM, pp->mem_base,
pp->mem_bus_addr, pp->mem_size);
dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
@@ -523,15 +532,35 @@ int dw_pcie_host_init(struct pcie_port *pp)
val |= PORT_LOGIC_SPEED_CHANGE;
dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
+ pp->root_bus_nr = pp->busn->start;
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr,
+ &dw_pcie_ops, pp, &res,
+ &dw_pcie_msi_chip);
+ dw_pcie_msi_chip.dev = pp->dev;
+ } else
+ bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+ pp, &res);
+ if (!bus)
+ return -ENOMEM;
+
+ if (pp->ops->scan_bus)
+ pp->ops->scan_bus(pp);
+
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ if (!pci_has_flag(PCI_PROBE_ONLY)) {
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
- pci_common_init_dev(pp->dev, &dw_pci);
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
+ }
+ pci_bus_add_devices(bus);
return 0;
}
@@ -539,22 +568,21 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
u32 devfn, int where, int size, u32 *val)
{
int ret, type;
- u32 address, busdev, cfg_size;
+ u32 busdev, cfg_size;
u64 cpu_addr;
void __iomem *va_cfg_base;
busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
PCIE_ATU_FUNC(PCI_FUNC(devfn));
- address = where & ~0x3;
if (bus->parent->number == pp->root_bus_nr) {
type = PCIE_ATU_TYPE_CFG0;
- cpu_addr = pp->cfg0_mod_base;
+ cpu_addr = pp->cfg0_base;
cfg_size = pp->cfg0_size;
va_cfg_base = pp->va_cfg0_base;
} else {
type = PCIE_ATU_TYPE_CFG1;
- cpu_addr = pp->cfg1_mod_base;
+ cpu_addr = pp->cfg1_base;
cfg_size = pp->cfg1_size;
va_cfg_base = pp->va_cfg1_base;
}
@@ -562,9 +590,9 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
type, cpu_addr,
busdev, cfg_size);
- ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
+ ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
- PCIE_ATU_TYPE_IO, pp->io_mod_base,
+ PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
return ret;
@@ -574,22 +602,21 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
u32 devfn, int where, int size, u32 val)
{
int ret, type;
- u32 address, busdev, cfg_size;
+ u32 busdev, cfg_size;
u64 cpu_addr;
void __iomem *va_cfg_base;
busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
PCIE_ATU_FUNC(PCI_FUNC(devfn));
- address = where & ~0x3;
if (bus->parent->number == pp->root_bus_nr) {
type = PCIE_ATU_TYPE_CFG0;
- cpu_addr = pp->cfg0_mod_base;
+ cpu_addr = pp->cfg0_base;
cfg_size = pp->cfg0_size;
va_cfg_base = pp->va_cfg0_base;
} else {
type = PCIE_ATU_TYPE_CFG1;
- cpu_addr = pp->cfg1_mod_base;
+ cpu_addr = pp->cfg1_base;
cfg_size = pp->cfg1_size;
va_cfg_base = pp->va_cfg1_base;
}
@@ -597,9 +624,9 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
type, cpu_addr,
busdev, cfg_size);
- ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
+ ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
- PCIE_ATU_TYPE_IO, pp->io_mod_base,
+ PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
return ret;
@@ -631,7 +658,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -655,7 +682,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -679,69 +706,6 @@ static struct pci_ops dw_pcie_ops = {
.write = dw_pcie_wr_conf,
};
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
- sys->io_offset = global_io_offset - pp->io_bus_addr;
- pci_ioremap_io(global_io_offset, pp->io_base);
- global_io_offset += SZ_64K;
- pci_add_resource_offset(&sys->resources, &pp->io,
- sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
- pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);
-
- pp->root_bus_nr = sys->busnr;
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- bus = pci_scan_root_bus_msi(pp->dev, sys->busnr, &dw_pcie_ops,
- sys, &sys->resources,
- &dw_pcie_msi_chip);
- else
- bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
- sys, &sys->resources);
-
- if (!bus)
- return NULL;
-
- if (bus && pp->ops->scan_bus)
- pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
- irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup = dw_pcie_setup,
- .scan = dw_pcie_scan_bus,
- .map_irq = dw_pcie_map_irq,
-};
-
void dw_pcie_setup_rc(struct pcie_port *pp)
{
u32 val;
@@ -764,6 +728,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
case 8:
val |= PORT_LINK_MODE_8_LANES;
break;
+ default:
+ dev_err(pp->dev, "num-lanes %u: invalid value\n", pp->lanes);
+ return;
}
dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd276840d..2356d29e8527 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -27,25 +27,21 @@ struct pcie_port {
u8 root_bus_nr;
void __iomem *dbi_base;
u64 cfg0_base;
- u64 cfg0_mod_base;
void __iomem *va_cfg0_base;
u32 cfg0_size;
u64 cfg1_base;
- u64 cfg1_mod_base;
void __iomem *va_cfg1_base;
u32 cfg1_size;
- u64 io_base;
- u64 io_mod_base;
+ resource_size_t io_base;
phys_addr_t io_bus_addr;
u32 io_size;
u64 mem_base;
- u64 mem_mod_base;
phys_addr_t mem_bus_addr;
u32 mem_size;
- struct resource cfg;
- struct resource io;
- struct resource mem;
- struct resource busn;
+ struct resource *cfg;
+ struct resource *io;
+ struct resource *mem;
+ struct resource *busn;
int irq;
u32 lanes;
struct pcie_host_ops *ops;
@@ -70,14 +66,14 @@ struct pcie_host_ops {
void (*host_init)(struct pcie_port *pp);
void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq);
- u32 (*get_msi_addr)(struct pcie_port *pp);
+ phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
u32 (*get_msi_data)(struct pcie_port *pp, int pos);
void (*scan_bus)(struct pcie_port *pp);
int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip);
};
-int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
-int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val);
+int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val);
+int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val);
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);
int dw_pcie_link_up(struct pcie_port *pp);
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
new file mode 100644
index 000000000000..35457ecd8e70
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,198 @@
+/*
+ * PCIe host controller driver for HiSilicon Hip05 SoC
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1@hisilicon.com>
+ * Dacai Zhu <zhudacai@hisilicon.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/interrupt.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
+#define PCIE_LTSSM_LINKUP_STATE 0x11
+#define PCIE_LTSSM_STATE_MASK 0x3F
+
+#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
+
+struct hisi_pcie {
+ struct regmap *subctrl;
+ void __iomem *reg_base;
+ u32 port_id;
+ struct pcie_port pp;
+};
+
+static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
+ u32 val, u32 reg)
+{
+ writel(val, pcie->reg_base + reg);
+}
+
+static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
+{
+ return readl(pcie->reg_base + reg);
+}
+
+/* Hip05 PCIe host only supports 32-bit config access */
+static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
+ u32 *val)
+{
+ u32 reg;
+ u32 reg_val;
+ struct hisi_pcie *pcie = to_hisi_pcie(pp);
+ void *walker = &reg_val;
+
+ walker += (where & 0x3);
+ reg = where & ~0x3;
+ reg_val = hisi_pcie_apb_readl(pcie, reg);
+
+ if (size == 1)
+ *val = *(u8 __force *) walker;
+ else if (size == 2)
+ *val = *(u16 __force *) walker;
+ else if (size != 4)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/* Hip05 PCIe host only supports 32-bit config access */
+static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
+ u32 val)
+{
+ u32 reg_val;
+ u32 reg;
+ struct hisi_pcie *pcie = to_hisi_pcie(pp);
+ void *walker = &reg_val;
+
+ walker += (where & 0x3);
+ reg = where & ~0x3;
+ if (size == 4)
+ hisi_pcie_apb_writel(pcie, val, reg);
+ else if (size == 2) {
+ reg_val = hisi_pcie_apb_readl(pcie, reg);
+ *(u16 __force *) walker = val;
+ hisi_pcie_apb_writel(pcie, reg_val, reg);
+ } else if (size == 1) {
+ reg_val = hisi_pcie_apb_readl(pcie, reg);
+ *(u8 __force *) walker = val;
+ hisi_pcie_apb_writel(pcie, reg_val, reg);
+ } else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int hisi_pcie_link_up(struct pcie_port *pp)
+{
+ u32 val;
+ struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+ regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG +
+ 0x100 * hisi_pcie->port_id, &val);
+
+ return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
+static struct pcie_host_ops hisi_pcie_host_ops = {
+ .rd_own_conf = hisi_pcie_cfg_read,
+ .wr_own_conf = hisi_pcie_cfg_write,
+ .link_up = hisi_pcie_link_up,
+};
+
+static int __init hisi_add_pcie_port(struct pcie_port *pp,
+ struct platform_device *pdev)
+{
+ int ret;
+ u32 port_id;
+ struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+ if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
+ dev_err(&pdev->dev, "failed to read port-id\n");
+ return -EINVAL;
+ }
+ if (port_id > 3) {
+ dev_err(&pdev->dev, "Invalid port-id: %d\n", port_id);
+ return -EINVAL;
+ }
+ hisi_pcie->port_id = port_id;
+
+ pp->ops = &hisi_pcie_host_ops;
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init hisi_pcie_probe(struct platform_device *pdev)
+{
+ struct hisi_pcie *hisi_pcie;
+ struct pcie_port *pp;
+ struct resource *reg;
+ int ret;
+
+ hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
+ if (!hisi_pcie)
+ return -ENOMEM;
+
+ pp = &hisi_pcie->pp;
+ pp->dev = &pdev->dev;
+
+ hisi_pcie->subctrl =
+ syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl");
+ if (IS_ERR(hisi_pcie->subctrl)) {
+ dev_err(pp->dev, "cannot get subctrl base\n");
+ return PTR_ERR(hisi_pcie->subctrl);
+ }
+
+ reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
+ hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
+ if (IS_ERR(hisi_pcie->reg_base)) {
+ dev_err(pp->dev, "cannot get rc_dbi base\n");
+ return PTR_ERR(hisi_pcie->reg_base);
+ }
+
+ hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+
+ ret = hisi_add_pcie_port(pp, pdev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, hisi_pcie);
+
+ dev_warn(pp->dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n");
+
+ return 0;
+}
+
+static const struct of_device_id hisi_pcie_of_match[] = {
+ {.compatible = "hisilicon,hip05-pcie",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
+
+static struct platform_driver hisi_pcie_driver = {
+ .probe = hisi_pcie_probe,
+ .driver = {
+ .name = "hisi-pcie",
+ .of_match_table = hisi_pcie_of_match,
+ },
+};
+
+module_platform_driver(hisi_pcie_driver);
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c
index 9aedc8eb2c6e..c9550dc8b8ed 100644
--- a/drivers/pci/host/pcie-iproc-platform.c
+++ b/drivers/pci/host/pcie-iproc-platform.c
@@ -54,6 +54,33 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ if (of_property_read_bool(np, "brcm,pcie-ob")) {
+ u32 val;
+
+ ret = of_property_read_u32(np, "brcm,pcie-ob-axi-offset",
+ &val);
+ if (ret) {
+ dev_err(pcie->dev,
+ "missing brcm,pcie-ob-axi-offset property\n");
+ return ret;
+ }
+ pcie->ob.axi_offset = val;
+
+ ret = of_property_read_u32(np, "brcm,pcie-ob-window-size",
+ &val);
+ if (ret) {
+ dev_err(pcie->dev,
+ "missing brcm,pcie-ob-window-size property\n");
+ return ret;
+ }
+ pcie->ob.window_size = (resource_size_t)val * SZ_1M;
+
+ if (of_property_read_bool(np, "brcm,pcie-ob-oarr-size"))
+ pcie->ob.set_oarr_size = true;
+
+ pcie->need_ob_cfg = true;
+ }
+
/* PHY use is optional */
pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy");
if (IS_ERR(pcie->phy)) {
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
index fe2efb141a9b..eac719af16aa 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de>
- * Copyright (C) 2015 Broadcom Corporatcommon ion
+ * 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
@@ -31,6 +31,8 @@
#include "pcie-iproc.h"
#define CLK_CONTROL_OFFSET 0x000
+#define EP_PERST_SOURCE_SELECT_SHIFT 2
+#define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT)
#define EP_MODE_SURVIVE_PERST_SHIFT 1
#define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT)
#define RC_PCIE_RST_OUTPUT_SHIFT 0
@@ -58,6 +60,24 @@
#define SYS_RC_INTX_EN 0x330
#define SYS_RC_INTX_MASK 0xf
+#define PCIE_LINK_STATUS_OFFSET 0xf0c
+#define PCIE_PHYLINKUP_SHIFT 3
+#define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT)
+#define PCIE_DL_ACTIVE_SHIFT 2
+#define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT)
+
+#define OARR_VALID_SHIFT 0
+#define OARR_VALID BIT(OARR_VALID_SHIFT)
+#define OARR_SIZE_CFG_SHIFT 1
+#define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT)
+
+#define OARR_LO(window) (0xd20 + (window) * 8)
+#define OARR_HI(window) (0xd24 + (window) * 8)
+#define OMAP_LO(window) (0xd40 + (window) * 8)
+#define OMAP_HI(window) (0xd44 + (window) * 8)
+
+#define MAX_NUM_OB_WINDOWS 2
+
static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
{
struct iproc_pcie *pcie;
@@ -119,23 +139,32 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
u32 val;
/*
- * Configure the PCIe controller as root complex and send a downstream
- * reset
+ * Select perst_b signal as reset source. Put the device into reset,
+ * and then bring it out of reset
*/
- val = EP_MODE_SURVIVE_PERST | RC_PCIE_RST_OUTPUT;
+ val = readl(pcie->base + CLK_CONTROL_OFFSET);
+ val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
+ ~RC_PCIE_RST_OUTPUT;
writel(val, pcie->base + CLK_CONTROL_OFFSET);
udelay(250);
- val &= ~EP_MODE_SURVIVE_PERST;
+
+ val |= RC_PCIE_RST_OUTPUT;
writel(val, pcie->base + CLK_CONTROL_OFFSET);
- msleep(250);
+ msleep(100);
}
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
{
u8 hdr_type;
- u32 link_ctrl;
+ u32 link_ctrl, class, val;
u16 pos, link_status;
- int link_is_active = 0;
+ bool link_is_active = false;
+
+ val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
+ if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) {
+ dev_err(pcie->dev, "PHY or data link is INACTIVE!\n");
+ return -ENODEV;
+ }
/* make sure we are not in EP mode */
pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type);
@@ -145,14 +174,19 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
}
/* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
- pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE,
- PCI_CLASS_BRIDGE_PCI);
+#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
+#define PCI_CLASS_BRIDGE_MASK 0xffff00
+#define PCI_CLASS_BRIDGE_SHIFT 8
+ pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class);
+ class &= ~PCI_CLASS_BRIDGE_MASK;
+ class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
+ pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class);
/* check link status to see if link is active */
pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status);
if (link_status & PCI_EXP_LNKSTA_NLW)
- link_is_active = 1;
+ link_is_active = true;
if (!link_is_active) {
/* try GEN 1 link speed */
@@ -176,7 +210,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA,
&link_status);
if (link_status & PCI_EXP_LNKSTA_NLW)
- link_is_active = 1;
+ link_is_active = true;
}
}
@@ -190,6 +224,101 @@ static void iproc_pcie_enable(struct iproc_pcie *pcie)
writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN);
}
+/**
+ * Some iProc SoCs require the SW to configure the outbound address mapping
+ *
+ * Outbound address translation:
+ *
+ * iproc_pcie_address = axi_address - axi_offset
+ * OARR = iproc_pcie_address
+ * OMAP = pci_addr
+ *
+ * axi_addr -> iproc_pcie_address -> OARR -> OMAP -> pci_address
+ */
+static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr,
+ u64 pci_addr, resource_size_t size)
+{
+ struct iproc_pcie_ob *ob = &pcie->ob;
+ unsigned i;
+ u64 max_size = (u64)ob->window_size * MAX_NUM_OB_WINDOWS;
+ u64 remainder;
+
+ if (size > max_size) {
+ dev_err(pcie->dev,
+ "res size 0x%pap exceeds max supported size 0x%llx\n",
+ &size, max_size);
+ return -EINVAL;
+ }
+
+ div64_u64_rem(size, ob->window_size, &remainder);
+ if (remainder) {
+ dev_err(pcie->dev,
+ "res size %pap needs to be multiple of window size %pap\n",
+ &size, &ob->window_size);
+ return -EINVAL;
+ }
+
+ if (axi_addr < ob->axi_offset) {
+ dev_err(pcie->dev,
+ "axi address %pap less than offset %pap\n",
+ &axi_addr, &ob->axi_offset);
+ return -EINVAL;
+ }
+
+ /*
+ * Translate the AXI address to the internal address used by the iProc
+ * PCIe core before programming the OARR
+ */
+ axi_addr -= ob->axi_offset;
+
+ for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) {
+ writel(lower_32_bits(axi_addr) | OARR_VALID |
+ (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i));
+ writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i));
+ writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i));
+ writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i));
+
+ size -= ob->window_size;
+ if (size == 0)
+ break;
+
+ axi_addr += ob->window_size;
+ pci_addr += ob->window_size;
+ }
+
+ return 0;
+}
+
+static int iproc_pcie_map_ranges(struct iproc_pcie *pcie,
+ struct list_head *resources)
+{
+ struct resource_entry *window;
+ int ret;
+
+ resource_list_for_each_entry(window, resources) {
+ struct resource *res = window->res;
+ u64 res_type = resource_type(res);
+
+ switch (res_type) {
+ case IORESOURCE_IO:
+ case IORESOURCE_BUS:
+ break;
+ case IORESOURCE_MEM:
+ ret = iproc_pcie_setup_ob(pcie, res->start,
+ res->start - window->offset,
+ resource_size(res));
+ if (ret)
+ return ret;
+ break;
+ default:
+ dev_err(pcie->dev, "invalid resource %pR\n", res);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
{
int ret;
@@ -213,6 +342,14 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
iproc_pcie_reset(pcie);
+ if (pcie->need_ob_cfg) {
+ ret = iproc_pcie_map_ranges(pcie, res);
+ if (ret) {
+ dev_err(pcie->dev, "map failed\n");
+ goto err_power_off_phy;
+ }
+ }
+
#ifdef CONFIG_ARM
pcie->sysdata.private_data = pcie;
sysdata = &pcie->sysdata;
@@ -238,9 +375,7 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
-#ifdef CONFIG_ARM
pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
-#endif
pci_bus_add_devices(bus);
return 0;
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h
index c9e4c10a462e..d3dc940f773a 100644
--- a/drivers/pci/host/pcie-iproc.h
+++ b/drivers/pci/host/pcie-iproc.h
@@ -14,17 +14,30 @@
#ifndef _PCIE_IPROC_H
#define _PCIE_IPROC_H
-#define IPROC_PCIE_MAX_NUM_IRQS 6
+/**
+ * iProc PCIe outbound mapping
+ * @set_oarr_size: indicates the OARR size bit needs to be set
+ * @axi_offset: offset from the AXI address to the internal address used by
+ * the iProc PCIe core
+ * @window_size: outbound window size
+ */
+struct iproc_pcie_ob {
+ bool set_oarr_size;
+ resource_size_t axi_offset;
+ resource_size_t window_size;
+};
/**
* iProc PCIe device
* @dev: pointer to device data structure
* @base: PCIe host controller I/O register base
- * @resources: linked list of all PCI resources
* @sysdata: Per PCI controller data (ARM-specific)
* @root_bus: pointer to root bus
* @phy: optional PHY device that controls the Serdes
* @irqs: interrupt IDs
+ * @map_irq: function callback to map interrupts
+ * @need_ob_cfg: indidates SW needs to configure the outbound mapping window
+ * @ob: outbound mapping parameters
*/
struct iproc_pcie {
struct device *dev;
@@ -34,8 +47,9 @@ struct iproc_pcie {
#endif
struct pci_bus *root_bus;
struct phy *phy;
- int irqs[IPROC_PCIE_MAX_NUM_IRQS];
int (*map_irq)(const struct pci_dev *, u8, u8);
+ bool need_ob_cfg;
+ struct iproc_pcie_ob ob;
};
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 7678fe0820d7..f4fa6c537448 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -108,6 +108,8 @@
#define RCAR_PCI_MAX_RESOURCES 4
#define MAX_NR_INBOUND_MAPS 6
+static unsigned long global_io_offset;
+
struct rcar_msi {
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
struct irq_domain *domain;
@@ -124,7 +126,16 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip)
}
/* Structure representing the PCIe interface */
+/*
+ * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
+ * sysdata. Add pci_sys_data as the first element in struct gen_pci so
+ * that when we use a gen_pci pointer as sysdata, it is also a pointer to
+ * a struct pci_sys_data.
+ */
struct rcar_pcie {
+#ifdef CONFIG_ARM
+ struct pci_sys_data sys;
+#endif
struct device *dev;
void __iomem *base;
struct resource res[RCAR_PCI_MAX_RESOURCES];
@@ -135,11 +146,6 @@ struct rcar_pcie {
struct rcar_msi msi;
};
-static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
-{
- return sys->private_data;
-}
-
static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
unsigned long reg)
{
@@ -258,7 +264,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
- struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+ struct rcar_pcie *pcie = bus->sysdata;
int ret;
ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
@@ -283,7 +289,7 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
- struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+ struct rcar_pcie *pcie = bus->sysdata;
int shift, ret;
u32 data;
@@ -353,13 +359,12 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
}
-static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
+static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie)
{
- struct rcar_pcie *pcie = sys_to_pcie(sys);
struct resource *res;
int i;
- pcie->root_bus_nr = -1;
+ pcie->root_bus_nr = pcie->busn.start;
/* Setup PCI resources */
for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
@@ -372,32 +377,53 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
if (res->flags & IORESOURCE_IO) {
phys_addr_t io_start = pci_pio_to_address(res->start);
- pci_ioremap_io(nr * SZ_64K, io_start);
- } else
- pci_add_resource(&sys->resources, res);
+ pci_ioremap_io(global_io_offset, io_start);
+ global_io_offset += SZ_64K;
+ }
+
+ pci_add_resource(resource, res);
}
- pci_add_resource(&sys->resources, &pcie->busn);
+ pci_add_resource(resource, &pcie->busn);
return 1;
}
-static struct hw_pci rcar_pci = {
- .setup = rcar_pcie_setup,
- .map_irq = of_irq_parse_and_map_pci,
- .ops = &rcar_pcie_ops,
-};
-
-static void rcar_pcie_enable(struct rcar_pcie *pcie)
+static int rcar_pcie_enable(struct rcar_pcie *pcie)
{
- struct platform_device *pdev = to_platform_device(pcie->dev);
+ struct pci_bus *bus, *child;
+ LIST_HEAD(res);
- rcar_pci.nr_controllers = 1;
- rcar_pci.private_data = (void **)&pcie;
-#ifdef CONFIG_PCI_MSI
- rcar_pci.msi_ctrl = &pcie->msi.chip;
-#endif
+ rcar_pcie_setup(&res, pcie);
+
+ /* Do not reassign resources if probe only */
+ if (!pci_has_flag(PCI_PROBE_ONLY))
+ pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
- pci_common_init_dev(&pdev->dev, &rcar_pci);
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ bus = pci_scan_root_bus_msi(pcie->dev, pcie->root_bus_nr,
+ &rcar_pcie_ops, pcie, &res, &pcie->msi.chip);
+ else
+ bus = pci_scan_root_bus(pcie->dev, pcie->root_bus_nr,
+ &rcar_pcie_ops, pcie, &res);
+
+ if (!bus) {
+ dev_err(pcie->dev, "Scanning rootbus failed");
+ return -ENODEV;
+ }
+
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+
+ if (!pci_has_flag(PCI_PROBE_ONLY)) {
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
+ }
+
+ pci_bus_add_devices(bus);
+
+ return 0;
}
static int phy_wait_for_ack(struct rcar_pcie *pcie)
@@ -970,9 +996,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
data = rcar_pci_read_reg(pcie, MACSR);
dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
- rcar_pcie_enable(pcie);
-
- return 0;
+ return rcar_pcie_enable(pcie);
}
static struct platform_driver rcar_pcie_driver = {
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index 98d2683181bc..b95b7563c052 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -163,34 +163,34 @@ static int spear13xx_pcie_establish_link(struct pcie_port *pp)
* default value in capability register is 512 bytes. So force
* it to 128 here.
*/
- dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, &val);
+ dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, &val);
val &= ~PCI_EXP_DEVCTL_READRQ;
- dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, val);
+ dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, val);
- dw_pcie_cfg_write(pp->dbi_base, PCI_VENDOR_ID, 2, 0x104A);
- dw_pcie_cfg_write(pp->dbi_base, PCI_DEVICE_ID, 2, 0xCD80);
+ dw_pcie_cfg_write(pp->dbi_base + PCI_VENDOR_ID, 2, 0x104A);
+ dw_pcie_cfg_write(pp->dbi_base + PCI_DEVICE_ID, 2, 0xCD80);
/*
* if is_gen1 is set then handle it, so that some buggy card
* also works
*/
if (spear13xx_pcie->is_gen1) {
- dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCAP, 4,
- &val);
+ dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCAP,
+ 4, &val);
if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
val &= ~((u32)PCI_EXP_LNKCAP_SLS);
val |= PCI_EXP_LNKCAP_SLS_2_5GB;
- dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
- PCI_EXP_LNKCAP, 4, val);
+ dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
+ PCI_EXP_LNKCAP, 4, val);
}
- dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCTL2, 4,
- &val);
+ dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2,
+ 2, &val);
if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
val &= ~((u32)PCI_EXP_LNKCAP_SLS);
val |= PCI_EXP_LNKCAP_SLS_2_5GB;
- dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
- PCI_EXP_LNKCTL2, 4, val);
+ dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
+ PCI_EXP_LNKCTL2, 2, val);
}
}
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f3796124ad7c..4c8f4cde6854 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -204,36 +204,39 @@ static void pciehp_power_thread(struct work_struct *work)
kfree(info);
}
-void pciehp_queue_pushbutton_work(struct work_struct *work)
+static void pciehp_queue_power_work(struct slot *p_slot, int req)
{
- struct slot *p_slot = container_of(work, struct slot, work.work);
struct power_work_info *info;
+ p_slot->state = (req == ENABLE_REQ) ? POWERON_STATE : POWEROFF_STATE;
+
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
- ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
- __func__);
+ ctrl_err(p_slot->ctrl, "no memory to queue %s request\n",
+ (req == ENABLE_REQ) ? "poweron" : "poweroff");
return;
}
info->p_slot = p_slot;
INIT_WORK(&info->work, pciehp_power_thread);
+ info->req = req;
+ queue_work(p_slot->wq, &info->work);
+}
+
+void pciehp_queue_pushbutton_work(struct work_struct *work)
+{
+ struct slot *p_slot = container_of(work, struct slot, work.work);
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case BLINKINGOFF_STATE:
- p_slot->state = POWEROFF_STATE;
- info->req = DISABLE_REQ;
+ pciehp_queue_power_work(p_slot, DISABLE_REQ);
break;
case BLINKINGON_STATE:
- p_slot->state = POWERON_STATE;
- info->req = ENABLE_REQ;
+ pciehp_queue_power_work(p_slot, ENABLE_REQ);
break;
default:
- kfree(info);
- goto out;
+ break;
}
- queue_work(p_slot->wq, &info->work);
- out:
mutex_unlock(&p_slot->lock);
}
@@ -301,27 +304,12 @@ static void handle_button_press_event(struct slot *p_slot)
static void handle_surprise_event(struct slot *p_slot)
{
u8 getstatus;
- struct power_work_info *info;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
- __func__);
- return;
- }
- info->p_slot = p_slot;
- INIT_WORK(&info->work, pciehp_power_thread);
pciehp_get_adapter_status(p_slot, &getstatus);
- if (!getstatus) {
- p_slot->state = POWEROFF_STATE;
- info->req = DISABLE_REQ;
- } else {
- p_slot->state = POWERON_STATE;
- info->req = ENABLE_REQ;
- }
-
- queue_work(p_slot->wq, &info->work);
+ if (!getstatus)
+ pciehp_queue_power_work(p_slot, DISABLE_REQ);
+ else
+ pciehp_queue_power_work(p_slot, ENABLE_REQ);
}
/*
@@ -330,17 +318,6 @@ static void handle_surprise_event(struct slot *p_slot)
static void handle_link_event(struct slot *p_slot, u32 event)
{
struct controller *ctrl = p_slot->ctrl;
- struct power_work_info *info;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
- __func__);
- return;
- }
- info->p_slot = p_slot;
- info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ;
- INIT_WORK(&info->work, pciehp_power_thread);
switch (p_slot->state) {
case BLINKINGON_STATE:
@@ -348,22 +325,19 @@ static void handle_link_event(struct slot *p_slot, u32 event)
cancel_delayed_work(&p_slot->work);
/* Fall through */
case STATIC_STATE:
- p_slot->state = event == INT_LINK_UP ?
- POWERON_STATE : POWEROFF_STATE;
- queue_work(p_slot->wq, &info->work);
+ pciehp_queue_power_work(p_slot, event == INT_LINK_UP ?
+ ENABLE_REQ : DISABLE_REQ);
break;
case POWERON_STATE:
if (event == INT_LINK_UP) {
ctrl_info(ctrl,
"Link Up event ignored on slot(%s): already powering on\n",
slot_name(p_slot));
- kfree(info);
} else {
ctrl_info(ctrl,
"Link Down event queued on slot(%s): currently getting powered on\n",
slot_name(p_slot));
- p_slot->state = POWEROFF_STATE;
- queue_work(p_slot->wq, &info->work);
+ pciehp_queue_power_work(p_slot, DISABLE_REQ);
}
break;
case POWEROFF_STATE:
@@ -371,19 +345,16 @@ static void handle_link_event(struct slot *p_slot, u32 event)
ctrl_info(ctrl,
"Link Up event queued on slot(%s): currently getting powered off\n",
slot_name(p_slot));
- p_slot->state = POWERON_STATE;
- queue_work(p_slot->wq, &info->work);
+ pciehp_queue_power_work(p_slot, ENABLE_REQ);
} else {
ctrl_info(ctrl,
"Link Down event ignored on slot(%s): already powering off\n",
slot_name(p_slot));
- kfree(info);
}
break;
default:
ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n",
p_slot->state, slot_name(p_slot));
- kfree(info);
break;
}
}
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index ee0ebff103a4..31f31d460fc9 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -54,24 +54,29 @@ static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn)
* The PF consumes one bus number. NumVFs, First VF Offset, and VF Stride
* determine how many additional bus numbers will be consumed by VFs.
*
- * Iterate over all valid NumVFs and calculate the maximum number of bus
- * numbers that could ever be required.
+ * Iterate over all valid NumVFs, validate offset and stride, and calculate
+ * the maximum number of bus numbers that could ever be required.
*/
-static inline u8 virtfn_max_buses(struct pci_dev *dev)
+static int compute_max_vf_buses(struct pci_dev *dev)
{
struct pci_sriov *iov = dev->sriov;
- int nr_virtfn;
- u8 max = 0;
- int busnr;
+ int nr_virtfn, busnr, rc = 0;
- for (nr_virtfn = 1; nr_virtfn <= iov->total_VFs; nr_virtfn++) {
+ for (nr_virtfn = iov->total_VFs; nr_virtfn; nr_virtfn--) {
pci_iov_set_numvfs(dev, nr_virtfn);
+ if (!iov->offset || (nr_virtfn > 1 && !iov->stride)) {
+ rc = -EIO;
+ goto out;
+ }
+
busnr = pci_iov_virtfn_bus(dev, nr_virtfn - 1);
- if (busnr > max)
- max = busnr;
+ if (busnr > iov->max_VF_buses)
+ iov->max_VF_buses = busnr;
}
- return max;
+out:
+ pci_iov_set_numvfs(dev, 0);
+ return rc;
}
static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
@@ -222,21 +227,25 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)
int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
{
- return 0;
+ return 0;
+}
+
+int __weak pcibios_sriov_disable(struct pci_dev *pdev)
+{
+ return 0;
}
static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
{
int rc;
- int i, j;
+ int i;
int nres;
- u16 offset, stride, initial;
+ u16 initial;
struct resource *res;
struct pci_dev *pdev;
struct pci_sriov *iov = dev->sriov;
int bars = 0;
int bus;
- int retval;
if (!nr_virtfn)
return 0;
@@ -253,11 +262,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
return -EINVAL;
- pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset);
- pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride);
- if (!offset || (nr_virtfn > 1 && !stride))
- return -EIO;
-
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
bars |= (1 << (i + PCI_IOV_RESOURCES));
@@ -270,9 +274,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return -ENOMEM;
}
- iov->offset = offset;
- iov->stride = stride;
-
bus = pci_iov_virtfn_bus(dev, nr_virtfn - 1);
if (bus > dev->bus->busn_res.end) {
dev_err(&dev->dev, "can't enable %d VFs (bus %02x out of range of %pR)\n",
@@ -313,10 +314,10 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
if (nr_virtfn < initial)
initial = nr_virtfn;
- if ((retval = pcibios_sriov_enable(dev, initial))) {
- dev_err(&dev->dev, "failure %d from pcibios_sriov_enable()\n",
- retval);
- return retval;
+ rc = pcibios_sriov_enable(dev, initial);
+ if (rc) {
+ dev_err(&dev->dev, "failure %d from pcibios_sriov_enable()\n", rc);
+ goto err_pcibios;
}
for (i = 0; i < initial; i++) {
@@ -331,27 +332,24 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return 0;
failed:
- for (j = 0; j < i; j++)
- virtfn_remove(dev, j, 0);
+ while (i--)
+ virtfn_remove(dev, i, 0);
+ pcibios_sriov_disable(dev);
+err_pcibios:
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
- pci_iov_set_numvfs(dev, 0);
ssleep(1);
pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
+ pci_iov_set_numvfs(dev, 0);
return rc;
}
-int __weak pcibios_sriov_disable(struct pci_dev *pdev)
-{
- return 0;
-}
-
static void sriov_disable(struct pci_dev *dev)
{
int i;
@@ -384,7 +382,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
int rc;
int nres;
u32 pgsz;
- u16 ctrl, total, offset, stride;
+ u16 ctrl, total;
struct pci_sriov *iov;
struct resource *res;
struct pci_dev *pdev;
@@ -399,10 +397,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
ssleep(1);
}
- pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total);
- if (!total)
- return 0;
-
ctrl = 0;
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
if (pdev->is_physfn)
@@ -414,11 +408,10 @@ static int sriov_init(struct pci_dev *dev, int pos)
found:
pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl);
- pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, 0);
- pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
- pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
- if (!offset || (total > 1 && !stride))
- return -EIO;
+
+ pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total);
+ if (!total)
+ return 0;
pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &pgsz);
i = PAGE_SHIFT > 12 ? PAGE_SHIFT - 12 : 0;
@@ -436,8 +429,15 @@ found:
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &dev->resource[i + PCI_IOV_RESOURCES];
- bar64 = __pci_read_base(dev, pci_bar_unknown, res,
- pos + PCI_SRIOV_BAR + i * 4);
+ /*
+ * If it is already FIXED, don't change it, something
+ * (perhaps EA or header fixups) wants it this way.
+ */
+ if (res->flags & IORESOURCE_PCI_FIXED)
+ bar64 = (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
+ else
+ bar64 = __pci_read_base(dev, pci_bar_unknown, res,
+ pos + PCI_SRIOV_BAR + i * 4);
if (!res->flags)
continue;
if (resource_size(res) & (PAGE_SIZE - 1)) {
@@ -456,8 +456,6 @@ found:
iov->nres = nres;
iov->ctrl = ctrl;
iov->total_VFs = total;
- iov->offset = offset;
- iov->stride = stride;
iov->pgsz = pgsz;
iov->self = dev;
pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
@@ -474,10 +472,15 @@ found:
dev->sriov = iov;
dev->is_physfn = 1;
- iov->max_VF_buses = virtfn_max_buses(dev);
+ rc = compute_max_vf_buses(dev);
+ if (rc)
+ goto fail_max_buses;
return 0;
+fail_max_buses:
+ dev->sriov = NULL;
+ dev->is_physfn = 0;
failed:
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &dev->resource[i + PCI_IOV_RESOURCES];
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d4497141d083..53e463244bb7 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -20,6 +20,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
#include "pci.h"
@@ -105,9 +106,12 @@ void __weak arch_teardown_msi_irq(unsigned int irq)
int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
+ struct msi_controller *chip = dev->bus->msi;
struct msi_desc *entry;
int ret;
+ if (chip && chip->setup_irqs)
+ return chip->setup_irqs(chip, dev, nvec, type);
/*
* If an architecture wants to support multiple MSI, it needs to
* override arch_setup_msi_irqs()
@@ -475,10 +479,11 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
int ret = -ENOMEM;
int num_msi = 0;
int count = 0;
+ int i;
/* Determine how many msi entries we have */
for_each_pci_msi_entry(entry, pdev)
- ++num_msi;
+ num_msi += entry->nvec_used;
if (!num_msi)
return 0;
@@ -487,19 +492,21 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
if (!msi_attrs)
return -ENOMEM;
for_each_pci_msi_entry(entry, pdev) {
- msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
- if (!msi_dev_attr)
- goto error_attrs;
- msi_attrs[count] = &msi_dev_attr->attr;
-
- sysfs_attr_init(&msi_dev_attr->attr);
- msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d",
- entry->irq);
- if (!msi_dev_attr->attr.name)
- goto error_attrs;
- msi_dev_attr->attr.mode = S_IRUGO;
- msi_dev_attr->show = msi_mode_show;
- ++count;
+ for (i = 0; i < entry->nvec_used; i++) {
+ msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
+ if (!msi_dev_attr)
+ goto error_attrs;
+ msi_attrs[count] = &msi_dev_attr->attr;
+
+ sysfs_attr_init(&msi_dev_attr->attr);
+ msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d",
+ entry->irq + i);
+ if (!msi_dev_attr->attr.name)
+ goto error_attrs;
+ msi_dev_attr->attr.mode = S_IRUGO;
+ msi_dev_attr->show = msi_mode_show;
+ ++count;
+ }
}
msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL);
@@ -1243,11 +1250,15 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
BUG_ON(!chip);
if (!chip->irq_write_msi_msg)
chip->irq_write_msi_msg = pci_msi_domain_write_msg;
+ if (!chip->irq_mask)
+ chip->irq_mask = pci_msi_mask_irq;
+ if (!chip->irq_unmask)
+ chip->irq_unmask = pci_msi_unmask_irq;
}
/**
- * pci_msi_create_irq_domain - Creat a MSI interrupt domain
- * @node: Optional device-tree node of the interrupt controller
+ * pci_msi_create_irq_domain - Create a MSI interrupt domain
+ * @fwnode: Optional fwnode of the interrupt controller
* @info: MSI domain info
* @parent: Parent irq domain
*
@@ -1256,7 +1267,7 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
* Returns:
* A domain pointer or NULL in case of failure.
*/
-struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
struct msi_domain_info *info,
struct irq_domain *parent)
{
@@ -1267,7 +1278,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
pci_msi_domain_update_chip_ops(info);
- domain = msi_create_irq_domain(node, info, parent);
+ domain = msi_create_irq_domain(fwnode, info, parent);
if (!domain)
return NULL;
@@ -1303,14 +1314,14 @@ void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev)
/**
* pci_msi_create_default_irq_domain - Create a default MSI interrupt domain
- * @node: Optional device-tree node of the interrupt controller
+ * @fwnode: Optional fwnode of the interrupt controller
* @info: MSI domain info
* @parent: Parent irq domain
*
* Returns: A domain pointer or NULL in case of failure. If successful
* the default PCI/MSI irqdomain pointer is updated.
*/
-struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
+struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode,
struct msi_domain_info *info, struct irq_domain *parent)
{
struct irq_domain *domain;
@@ -1320,11 +1331,59 @@ struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node,
pr_err("PCI: default irq domain for PCI MSI has already been created.\n");
domain = NULL;
} else {
- domain = pci_msi_create_irq_domain(node, info, parent);
+ domain = pci_msi_create_irq_domain(fwnode, info, parent);
pci_msi_default_domain = domain;
}
mutex_unlock(&pci_msi_domain_lock);
return domain;
}
+
+static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data)
+{
+ u32 *pa = data;
+
+ *pa = alias;
+ return 0;
+}
+/**
+ * pci_msi_domain_get_msi_rid - Get the MSI requester id (RID)
+ * @domain: The interrupt domain
+ * @pdev: The PCI device.
+ *
+ * The RID for a device is formed from the alias, with a firmware
+ * supplied mapping applied
+ *
+ * Returns: The RID.
+ */
+u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
+{
+ struct device_node *of_node;
+ u32 rid = 0;
+
+ pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
+
+ of_node = irq_domain_get_of_node(domain);
+ if (of_node)
+ rid = of_msi_map_rid(&pdev->dev, of_node, rid);
+
+ return rid;
+}
+
+/**
+ * pci_msi_get_device_domain - Get the MSI domain for a given PCI device
+ * @pdev: The PCI device
+ *
+ * Use the firmware data to find a device-specific MSI domain
+ * (i.e. not one that is ste as a default).
+ *
+ * Returns: The coresponding MSI domain or NULL if none has been found.
+ */
+struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
+{
+ u32 rid = 0;
+
+ pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
+ return of_msi_map_get_device_domain(&pdev->dev, rid);
+}
#endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 2e99a500cb83..e112da11630e 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include "pci.h"
@@ -64,27 +65,25 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
{
#ifdef CONFIG_IRQ_DOMAIN
- struct device_node *np;
struct irq_domain *d;
if (!bus->dev.of_node)
return NULL;
/* Start looking for a phandle to an MSI controller. */
- np = of_parse_phandle(bus->dev.of_node, "msi-parent", 0);
+ d = of_msi_get_domain(&bus->dev, bus->dev.of_node, DOMAIN_BUS_PCI_MSI);
+ if (d)
+ return d;
/*
* If we don't have an msi-parent property, look for a domain
* directly attached to the host bridge.
*/
- if (!np)
- np = bus->dev.of_node;
-
- d = irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+ d = irq_find_matching_host(bus->dev.of_node, DOMAIN_BUS_PCI_MSI);
if (d)
return d;
- return irq_find_host(np);
+ return irq_find_host(bus->dev.of_node);
#else
return NULL;
#endif
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 108a3118ace7..4446fcb5effd 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -172,7 +172,7 @@ static ssize_t store_remove_id(struct device_driver *driver, const char *buf,
__u32 vendor, device, subvendor = PCI_ANY_ID,
subdevice = PCI_ANY_ID, class = 0, class_mask = 0;
int fields = 0;
- int retval = -ENODEV;
+ size_t retval = -ENODEV;
fields = sscanf(buf, "%x %x %x %x %x %x",
&vendor, &device, &subvendor, &subdevice,
@@ -190,15 +190,13 @@ static ssize_t store_remove_id(struct device_driver *driver, const char *buf,
!((id->class ^ class) & class_mask)) {
list_del(&dynid->node);
kfree(dynid);
- retval = 0;
+ retval = count;
break;
}
}
spin_unlock(&pdrv->dynids.lock);
- if (retval)
- return retval;
- return count;
+ return retval;
}
static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
@@ -684,10 +682,16 @@ static int pci_pm_prepare(struct device *dev)
return pci_dev_keep_suspended(to_pci_dev(dev));
}
+static void pci_pm_complete(struct device *dev)
+{
+ pci_dev_complete_resume(to_pci_dev(dev));
+ pm_complete_with_resume_check(dev);
+}
#else /* !CONFIG_PM_SLEEP */
#define pci_pm_prepare NULL
+#define pci_pm_complete NULL
#endif /* !CONFIG_PM_SLEEP */
@@ -1218,6 +1222,7 @@ static int pci_pm_runtime_idle(struct device *dev)
static const struct dev_pm_ops pci_dev_pm_ops = {
.prepare = pci_pm_prepare,
+ .complete = pci_pm_complete,
.suspend = pci_pm_suspend,
.resume = pci_pm_resume,
.freeze = pci_pm_freeze,
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 312f23a8429c..92618686604c 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -216,7 +216,7 @@ static ssize_t numa_node_store(struct device *dev,
if (ret)
return ret;
- if (!node_online(node))
+ if (node >= MAX_NUMNODES || !node_online(node))
return -EINVAL;
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6a9a1116f1eb..314db8c1047a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -27,6 +27,7 @@
#include <linux/pci_hotplug.h>
#include <asm-generic/pci-bridge.h>
#include <asm/setup.h>
+#include <linux/aer.h>
#include "pci.h"
const char *pci_power_names[] = {
@@ -458,6 +459,30 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev,
EXPORT_SYMBOL(pci_find_parent_resource);
/**
+ * pci_find_pcie_root_port - return PCIe Root Port
+ * @dev: PCI device to query
+ *
+ * Traverse up the parent chain and return the PCIe Root Port PCI Device
+ * for a given PCI Device.
+ */
+struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev)
+{
+ struct pci_dev *bridge, *highest_pcie_bridge = NULL;
+
+ bridge = pci_upstream_bridge(dev);
+ while (bridge && pci_is_pcie(bridge)) {
+ highest_pcie_bridge = bridge;
+ bridge = pci_upstream_bridge(bridge);
+ }
+
+ if (pci_pcie_type(highest_pcie_bridge) != PCI_EXP_TYPE_ROOT_PORT)
+ return NULL;
+
+ return highest_pcie_bridge;
+}
+EXPORT_SYMBOL(pci_find_pcie_root_port);
+
+/**
* pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos
* @dev: the PCI device to operate on
* @pos: config space offset of status word
@@ -484,7 +509,7 @@ int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
}
/**
- * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
+ * pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
* @dev: PCI device to have its BARs restored
*
* Restore the BAR values for a given device, so as to make it
@@ -494,6 +519,10 @@ static void pci_restore_bars(struct pci_dev *dev)
{
int i;
+ /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
+ if (dev->is_virtfn)
+ return;
+
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++)
pci_update_resource(dev, i);
}
@@ -1099,6 +1128,8 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_ats_state(dev);
pci_restore_vc_state(dev);
+ pci_cleanup_aer_error_status_regs(dev);
+
pci_restore_config_space(dev);
pci_restore_pcix_state(dev);
@@ -1710,15 +1741,7 @@ static void pci_pme_list_scan(struct work_struct *work)
mutex_unlock(&pci_pme_list_mutex);
}
-/**
- * pci_pme_active - enable or disable PCI device's PME# function
- * @dev: PCI device to handle.
- * @enable: 'true' to enable PME# generation; 'false' to disable it.
- *
- * The caller must verify that the device is capable of generating PME# before
- * calling this function with @enable equal to 'true'.
- */
-void pci_pme_active(struct pci_dev *dev, bool enable)
+static void __pci_pme_active(struct pci_dev *dev, bool enable)
{
u16 pmcsr;
@@ -1732,6 +1755,19 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
+}
+
+/**
+ * pci_pme_active - enable or disable PCI device's PME# function
+ * @dev: PCI device to handle.
+ * @enable: 'true' to enable PME# generation; 'false' to disable it.
+ *
+ * The caller must verify that the device is capable of generating PME# before
+ * calling this function with @enable equal to 'true'.
+ */
+void pci_pme_active(struct pci_dev *dev, bool enable)
+{
+ __pci_pme_active(dev, enable);
/*
* PCI (as opposed to PCIe) PME requires that the device have
@@ -2032,17 +2068,60 @@ EXPORT_SYMBOL_GPL(pci_dev_run_wake);
* reconfigured due to wakeup settings difference between system and runtime
* suspend and the current power state of it is suitable for the upcoming
* (system) transition.
+ *
+ * If the device is not configured for system wakeup, disable PME for it before
+ * returning 'true' to prevent it from waking up the system unnecessarily.
*/
bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
{
struct device *dev = &pci_dev->dev;
if (!pm_runtime_suspended(dev)
- || (device_can_wakeup(dev) && !device_may_wakeup(dev))
+ || pci_target_state(pci_dev) != pci_dev->current_state
|| platform_pci_need_resume(pci_dev))
return false;
- return pci_target_state(pci_dev) == pci_dev->current_state;
+ /*
+ * At this point the device is good to go unless it's been configured
+ * to generate PME at the runtime suspend time, but it is not supposed
+ * to wake up the system. In that case, simply disable PME for it
+ * (it will have to be re-enabled on exit from system resume).
+ *
+ * If the device's power state is D3cold and the platform check above
+ * hasn't triggered, the device's configuration is suitable and we don't
+ * need to manipulate it at all.
+ */
+ spin_lock_irq(&dev->power.lock);
+
+ if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold &&
+ !device_may_wakeup(dev))
+ __pci_pme_active(pci_dev, false);
+
+ spin_unlock_irq(&dev->power.lock);
+ return true;
+}
+
+/**
+ * pci_dev_complete_resume - Finalize resume from system sleep for a device.
+ * @pci_dev: Device to handle.
+ *
+ * If the device is runtime suspended and wakeup-capable, enable PME for it as
+ * it might have been disabled during the prepare phase of system suspend if
+ * the device was not configured for system wakeup.
+ */
+void pci_dev_complete_resume(struct pci_dev *pci_dev)
+{
+ struct device *dev = &pci_dev->dev;
+
+ if (!pci_dev_run_wake(pci_dev))
+ return;
+
+ spin_lock_irq(&dev->power.lock);
+
+ if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold)
+ __pci_pme_active(pci_dev, true);
+
+ spin_unlock_irq(&dev->power.lock);
}
void pci_config_pm_runtime_get(struct pci_dev *pdev)
@@ -2148,6 +2227,198 @@ void pci_pm_init(struct pci_dev *dev)
}
}
+static unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop)
+{
+ unsigned long flags = IORESOURCE_PCI_FIXED;
+
+ switch (prop) {
+ case PCI_EA_P_MEM:
+ case PCI_EA_P_VF_MEM:
+ flags |= IORESOURCE_MEM;
+ break;
+ case PCI_EA_P_MEM_PREFETCH:
+ case PCI_EA_P_VF_MEM_PREFETCH:
+ flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ break;
+ case PCI_EA_P_IO:
+ flags |= IORESOURCE_IO;
+ break;
+ default:
+ return 0;
+ }
+
+ return flags;
+}
+
+static struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei,
+ u8 prop)
+{
+ if (bei <= PCI_EA_BEI_BAR5 && prop <= PCI_EA_P_IO)
+ return &dev->resource[bei];
+#ifdef CONFIG_PCI_IOV
+ else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5 &&
+ (prop == PCI_EA_P_VF_MEM || prop == PCI_EA_P_VF_MEM_PREFETCH))
+ return &dev->resource[PCI_IOV_RESOURCES +
+ bei - PCI_EA_BEI_VF_BAR0];
+#endif
+ else if (bei == PCI_EA_BEI_ROM)
+ return &dev->resource[PCI_ROM_RESOURCE];
+ else
+ return NULL;
+}
+
+/* Read an Enhanced Allocation (EA) entry */
+static int pci_ea_read(struct pci_dev *dev, int offset)
+{
+ struct resource *res;
+ int ent_size, ent_offset = offset;
+ resource_size_t start, end;
+ unsigned long flags;
+ u32 dw0, bei, base, max_offset;
+ u8 prop;
+ bool support_64 = (sizeof(resource_size_t) >= 8);
+
+ pci_read_config_dword(dev, ent_offset, &dw0);
+ ent_offset += 4;
+
+ /* Entry size field indicates DWORDs after 1st */
+ ent_size = ((dw0 & PCI_EA_ES) + 1) << 2;
+
+ if (!(dw0 & PCI_EA_ENABLE)) /* Entry not enabled */
+ goto out;
+
+ bei = (dw0 & PCI_EA_BEI) >> 4;
+ prop = (dw0 & PCI_EA_PP) >> 8;
+
+ /*
+ * If the Property is in the reserved range, try the Secondary
+ * Property instead.
+ */
+ if (prop > PCI_EA_P_BRIDGE_IO && prop < PCI_EA_P_MEM_RESERVED)
+ prop = (dw0 & PCI_EA_SP) >> 16;
+ if (prop > PCI_EA_P_BRIDGE_IO)
+ goto out;
+
+ res = pci_ea_get_resource(dev, bei, prop);
+ if (!res) {
+ dev_err(&dev->dev, "Unsupported EA entry BEI: %u\n", bei);
+ goto out;
+ }
+
+ flags = pci_ea_flags(dev, prop);
+ if (!flags) {
+ dev_err(&dev->dev, "Unsupported EA properties: %#x\n", prop);
+ goto out;
+ }
+
+ /* Read Base */
+ pci_read_config_dword(dev, ent_offset, &base);
+ start = (base & PCI_EA_FIELD_MASK);
+ ent_offset += 4;
+
+ /* Read MaxOffset */
+ pci_read_config_dword(dev, ent_offset, &max_offset);
+ ent_offset += 4;
+
+ /* Read Base MSBs (if 64-bit entry) */
+ if (base & PCI_EA_IS_64) {
+ u32 base_upper;
+
+ pci_read_config_dword(dev, ent_offset, &base_upper);
+ ent_offset += 4;
+
+ flags |= IORESOURCE_MEM_64;
+
+ /* entry starts above 32-bit boundary, can't use */
+ if (!support_64 && base_upper)
+ goto out;
+
+ if (support_64)
+ start |= ((u64)base_upper << 32);
+ }
+
+ end = start + (max_offset | 0x03);
+
+ /* Read MaxOffset MSBs (if 64-bit entry) */
+ if (max_offset & PCI_EA_IS_64) {
+ u32 max_offset_upper;
+
+ pci_read_config_dword(dev, ent_offset, &max_offset_upper);
+ ent_offset += 4;
+
+ flags |= IORESOURCE_MEM_64;
+
+ /* entry too big, can't use */
+ if (!support_64 && max_offset_upper)
+ goto out;
+
+ if (support_64)
+ end += ((u64)max_offset_upper << 32);
+ }
+
+ if (end < start) {
+ dev_err(&dev->dev, "EA Entry crosses address boundary\n");
+ goto out;
+ }
+
+ if (ent_size != ent_offset - offset) {
+ dev_err(&dev->dev,
+ "EA Entry Size (%d) does not match length read (%d)\n",
+ ent_size, ent_offset - offset);
+ goto out;
+ }
+
+ res->name = pci_name(dev);
+ res->start = start;
+ res->end = end;
+ res->flags = flags;
+
+ if (bei <= PCI_EA_BEI_BAR5)
+ dev_printk(KERN_DEBUG, &dev->dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
+ bei, res, prop);
+ else if (bei == PCI_EA_BEI_ROM)
+ dev_printk(KERN_DEBUG, &dev->dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",
+ res, prop);
+ else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5)
+ dev_printk(KERN_DEBUG, &dev->dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
+ bei - PCI_EA_BEI_VF_BAR0, res, prop);
+ else
+ dev_printk(KERN_DEBUG, &dev->dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",
+ bei, res, prop);
+
+out:
+ return offset + ent_size;
+}
+
+/* Enhanced Allocation Initalization */
+void pci_ea_init(struct pci_dev *dev)
+{
+ int ea;
+ u8 num_ent;
+ int offset;
+ int i;
+
+ /* find PCI EA capability in list */
+ ea = pci_find_capability(dev, PCI_CAP_ID_EA);
+ if (!ea)
+ return;
+
+ /* determine the number of entries */
+ pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT,
+ &num_ent);
+ num_ent &= PCI_EA_NUM_ENT_MASK;
+
+ offset = ea + PCI_EA_FIRST_ENT;
+
+ /* Skip DWORD 2 for type 1 functions */
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ offset += 4;
+
+ /* parse each EA entry */
+ for (i = 0; i < num_ent; ++i)
+ offset = pci_ea_read(dev, offset);
+}
+
static void pci_add_saved_cap(struct pci_dev *pci_dev,
struct pci_cap_saved_state *new_cap)
{
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 24ba9dc8910a..fd2f03fa53f3 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -75,9 +75,11 @@ void pci_disable_enabled_device(struct pci_dev *dev);
int pci_finish_runtime_suspend(struct pci_dev *dev);
int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
bool pci_dev_keep_suspended(struct pci_dev *dev);
+void pci_dev_complete_resume(struct pci_dev *pci_dev);
void pci_config_pm_runtime_get(struct pci_dev *dev);
void pci_config_pm_runtime_put(struct pci_dev *dev);
void pci_pm_init(struct pci_dev *dev);
+void pci_ea_init(struct pci_dev *dev);
void pci_allocate_cap_save_buffers(struct pci_dev *dev);
void pci_free_cap_save_buffers(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 9803e3d039fe..fba785e9df75 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -74,6 +74,34 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
+{
+ int pos;
+ u32 status;
+ int port_type;
+
+ if (!pci_is_pcie(dev))
+ return -ENODEV;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ return -EIO;
+
+ port_type = pci_pcie_type(dev);
+ if (port_type == PCI_EXP_TYPE_ROOT_PORT) {
+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
+ }
+
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
+
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+
+ return 0;
+}
+
/**
* add_error_device - list device to be handled
* @e_info: pointer to error info
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8361d27e5eca..edb1984201e9 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -6,12 +6,15 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/of_device.h>
#include <linux/of_pci.h>
#include <linux/pci_hotplug.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/cpumask.h>
#include <linux/pci-aspm.h>
+#include <linux/aer.h>
+#include <linux/acpi.h>
#include <asm-generic/pci-bridge.h>
#include "pci.h"
@@ -1597,6 +1600,9 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
static void pci_init_capabilities(struct pci_dev *dev)
{
+ /* Enhanced Allocation */
+ pci_ea_init(dev);
+
/* MSI/MSI-X list */
pci_msi_init_pci_dev(dev);
@@ -1620,17 +1626,80 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* Enable ACS P2P upstream forwarding */
pci_enable_acs(dev);
+
+ pci_cleanup_aer_error_status_regs(dev);
+}
+
+/*
+ * This is the equivalent of pci_host_bridge_msi_domain that acts on
+ * devices. Firmware interfaces that can select the MSI domain on a
+ * per-device basis should be called from here.
+ */
+static struct irq_domain *pci_dev_msi_domain(struct pci_dev *dev)
+{
+ struct irq_domain *d;
+
+ /*
+ * If a domain has been set through the pcibios_add_device
+ * callback, then this is the one (platform code knows best).
+ */
+ d = dev_get_msi_domain(&dev->dev);
+ if (d)
+ return d;
+
+ /*
+ * Let's see if we have a firmware interface able to provide
+ * the domain.
+ */
+ d = pci_msi_get_device_domain(dev);
+ if (d)
+ return d;
+
+ return NULL;
}
static void pci_set_msi_domain(struct pci_dev *dev)
{
+ struct irq_domain *d;
+
/*
- * If no domain has been set through the pcibios_add_device
- * callback, inherit the default from the bus device.
+ * If the platform or firmware interfaces cannot supply a
+ * device-specific MSI domain, then inherit the default domain
+ * from the host bridge itself.
*/
- if (!dev_get_msi_domain(&dev->dev))
- dev_set_msi_domain(&dev->dev,
- dev_get_msi_domain(&dev->bus->dev));
+ d = pci_dev_msi_domain(dev);
+ if (!d)
+ d = dev_get_msi_domain(&dev->bus->dev);
+
+ dev_set_msi_domain(&dev->dev, d);
+}
+
+/**
+ * pci_dma_configure - Setup DMA configuration
+ * @dev: ptr to pci_dev struct of the PCI device
+ *
+ * Function to update PCI devices's DMA configuration using the same
+ * info from the OF node or ACPI node of host bridge's parent (if any).
+ */
+static void pci_dma_configure(struct pci_dev *dev)
+{
+ struct device *bridge = pci_get_host_bridge_device(dev);
+
+ if (IS_ENABLED(CONFIG_OF) &&
+ bridge->parent && bridge->parent->of_node) {
+ of_dma_configure(&dev->dev, bridge->parent->of_node);
+ } else if (has_acpi_companion(bridge)) {
+ struct acpi_device *adev = to_acpi_device_node(bridge->fwnode);
+ enum dev_dma_attr attr = acpi_get_dma_attr(adev);
+
+ if (attr == DEV_DMA_NOT_SUPPORTED)
+ dev_warn(&dev->dev, "DMA not supported.\n");
+ else
+ arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
+ attr == DEV_DMA_COHERENT);
+ }
+
+ pci_put_host_bridge_device(bridge);
}
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
@@ -1646,7 +1715,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
dev->dev.dma_mask = &dev->dma_mask;
dev->dev.dma_parms = &dev->dma_parms;
dev->dev.coherent_dma_mask = 0xffffffffull;
- of_pci_dma_configure(dev);
+ pci_dma_configure(dev);
pci_set_dma_max_seg_size(dev, 65536);
pci_set_dma_seg_boundary(dev, 0xffffffff);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b03373fd05ca..7e327309cf69 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2246,6 +2246,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disab
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, 0x0761, quirk_disable_all_msi);
/* Disable MSI on chipsets that are known to not support it */
static void quirk_disable_msi(struct pci_dev *dev)
@@ -3708,6 +3709,63 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, PCI_CLASS_NOT_DEFINED, 8,
quirk_tw686x_class);
/*
+ * Per PCIe r3.0, sec 2.2.9, "Completion headers must supply the same
+ * values for the Attribute as were supplied in the header of the
+ * corresponding Request, except as explicitly allowed when IDO is used."
+ *
+ * If a non-compliant device generates a completion with a different
+ * attribute than the request, the receiver may accept it (which itself
+ * seems non-compliant based on sec 2.3.2), or it may handle it as a
+ * Malformed TLP or an Unexpected Completion, which will probably lead to a
+ * device access timeout.
+ *
+ * If the non-compliant device generates completions with zero attributes
+ * (instead of copying the attributes from the request), we can work around
+ * this by disabling the "Relaxed Ordering" and "No Snoop" attributes in
+ * upstream devices so they always generate requests with zero attributes.
+ *
+ * This affects other devices under the same Root Port, but since these
+ * attributes are performance hints, there should be no functional problem.
+ *
+ * Note that Configuration Space accesses are never supposed to have TLP
+ * Attributes, so we're safe waiting till after any Configuration Space
+ * accesses to do the Root Port fixup.
+ */
+static void quirk_disable_root_port_attributes(struct pci_dev *pdev)
+{
+ struct pci_dev *root_port = pci_find_pcie_root_port(pdev);
+
+ if (!root_port) {
+ dev_warn(&pdev->dev, "PCIe Completion erratum may cause device errors\n");
+ return;
+ }
+
+ dev_info(&root_port->dev, "Disabling No Snoop/Relaxed Ordering Attributes to avoid PCIe Completion erratum in %s\n",
+ dev_name(&pdev->dev));
+ pcie_capability_clear_and_set_word(root_port, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_RELAX_EN |
+ PCI_EXP_DEVCTL_NOSNOOP_EN, 0);
+}
+
+/*
+ * The Chelsio T5 chip fails to copy TLP Attributes from a Request to the
+ * Completion it generates.
+ */
+static void quirk_chelsio_T5_disable_root_port_attributes(struct pci_dev *pdev)
+{
+ /*
+ * This mask/compare operation selects for Physical Function 4 on a
+ * T5. We only need to fix up the Root Port once for any of the
+ * PFs. PF[0..3] have PCI Device IDs of 0x50xx, but PF4 is uniquely
+ * 0x54xx so we use that one,
+ */
+ if ((pdev->device & 0xff00) == 0x5400)
+ quirk_disable_root_port_attributes(pdev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
+ quirk_chelsio_T5_disable_root_port_attributes);
+
+/*
* AMD has indicated that the devices below do not support peer-to-peer
* in any system where they are found in the southbridge with an AMD
* IOMMU in the system. Multifunction devices that do not support
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 508cc56130e3..1723ac1b30e1 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1037,9 +1037,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
struct resource *r = &dev->resource[i];
resource_size_t r_size;
- if (r->parent || ((r->flags & mask) != type &&
- (r->flags & mask) != type2 &&
- (r->flags & mask) != type3))
+ if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) ||
+ ((r->flags & mask) != type &&
+ (r->flags & mask) != type2 &&
+ (r->flags & mask) != type3))
continue;
r_size = resource_size(r);
#ifdef CONFIG_PCI_IOV
@@ -1340,6 +1341,47 @@ void pci_bus_size_bridges(struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_bus_size_bridges);
+static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r)
+{
+ int i;
+ struct resource *parent_r;
+ unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM |
+ IORESOURCE_PREFETCH;
+
+ pci_bus_for_each_resource(b, parent_r, i) {
+ if (!parent_r)
+ continue;
+
+ if ((r->flags & mask) == (parent_r->flags & mask) &&
+ resource_contains(parent_r, r))
+ request_resource(parent_r, r);
+ }
+}
+
+/*
+ * Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they
+ * are skipped by pbus_assign_resources_sorted().
+ */
+static void pdev_assign_fixed_resources(struct pci_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct pci_bus *b;
+ struct resource *r = &dev->resource[i];
+
+ if (r->parent || !(r->flags & IORESOURCE_PCI_FIXED) ||
+ !(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+ continue;
+
+ b = dev->bus;
+ while (b && !r->parent) {
+ assign_fixed_resource_on_bus(b, r);
+ b = b->parent;
+ }
+ }
+}
+
void __pci_bus_assign_resources(const struct pci_bus *bus,
struct list_head *realloc_head,
struct list_head *fail_head)
@@ -1350,6 +1392,8 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
pbus_assign_resources_sorted(bus, realloc_head, fail_head);
list_for_each_entry(dev, &bus->devices, bus_list) {
+ pdev_assign_fixed_resources(dev);
+
b = dev->subordinate;
if (!b)
continue;
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 232f9254c11a..604011e047d6 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -36,6 +36,11 @@ void pci_update_resource(struct pci_dev *dev, int resno)
enum pci_bar_type type;
struct resource *res = dev->resource + resno;
+ if (dev->is_virtfn) {
+ dev_warn(&dev->dev, "can't update VF BAR%d\n", resno);
+ return;
+ }
+
/*
* Ignore resources for unimplemented BARs and unused resource slots
* for 64 bit BARs.
@@ -177,6 +182,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
end = res->end;
res->start = fw_addr;
res->end = res->start + size - 1;
+ res->flags &= ~IORESOURCE_UNSET;
root = pci_find_parent_resource(dev, res);
if (!root) {
@@ -194,6 +200,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
resno, res, conflict->name, conflict);
res->start = start;
res->end = end;
+ res->flags |= IORESOURCE_UNSET;
return -EBUSY;
}
return 0;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0decee6c556e..489ea1098c96 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -468,12 +468,10 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
if ((length < 2) || (length > 255))
continue;
- new = kmalloc(sizeof(char) * length, GFP_KERNEL);
+ new = kstrdup(tmp, GFP_KERNEL);
if (!new)
continue;
- new = strncpy(new, tmp, length);
-
tmp = p_dev->prod_id[i];
p_dev->prod_id[i] = new;
kfree(tmp);
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index d9de36ee165d..04e2653bb8c0 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -5,7 +5,7 @@
menu "Performance monitor support"
config ARM_PMU
- depends on PERF_EVENTS && ARM
+ depends on PERF_EVENTS && (ARM || ARM64)
bool "ARM PMU framework"
default y
help
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 2365a32a595e..be3755c973e9 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -823,9 +823,15 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
}
/* Now look up the logical CPU number */
- for_each_possible_cpu(cpu)
- if (dn == of_cpu_device_node_get(cpu))
+ for_each_possible_cpu(cpu) {
+ struct device_node *cpu_dn;
+
+ cpu_dn = of_cpu_device_node_get(cpu);
+ of_node_put(cpu_dn);
+
+ if (dn == cpu_dn)
break;
+ }
if (cpu >= nr_cpu_ids) {
pr_warn("Failed to find logical CPU for %s\n",
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 47da573d0bab..7eb5859dd035 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -206,6 +206,15 @@ config PHY_HIX5HD2_SATA
help
Support for SATA PHY on Hisilicon hix5hd2 Soc.
+config PHY_MT65XX_USB3
+ tristate "Mediatek USB3.0 PHY Driver"
+ depends on ARCH_MEDIATEK && OF
+ select GENERIC_PHY
+ help
+ Say 'Y' here to add support for Mediatek USB3.0 PHY driver
+ for mt65xx SoCs. it supports two usb2.0 ports and
+ one usb3.0 port.
+
config PHY_SUN4I_USB
tristate "Allwinner sunxi SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
@@ -371,4 +380,13 @@ config PHY_BRCMSTB_SATA
Enable this to support the SATA3 PHY on 28nm Broadcom STB SoCs.
Likely useful only with CONFIG_SATA_BRCMSTB enabled.
+config PHY_CYGNUS_PCIE
+ tristate "Broadcom Cygnus PCIe PHY driver"
+ depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
+ select GENERIC_PHY
+ default ARCH_BCM_CYGNUS
+ help
+ Enable this to support the Broadcom Cygnus PCIe PHY.
+ If unsure, say N.
+
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a5b18c18fc12..075db1a81aa5 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
+obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
@@ -46,3 +47,4 @@ obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
+obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
diff --git a/drivers/phy/phy-bcm-cygnus-pcie.c b/drivers/phy/phy-bcm-cygnus-pcie.c
new file mode 100644
index 000000000000..7ad72b7d2b98
--- /dev/null
+++ b/drivers/phy/phy-bcm-cygnus-pcie.c
@@ -0,0 +1,213 @@
+/*
+ * 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>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define PCIE_CFG_OFFSET 0x00
+#define PCIE1_PHY_IDDQ_SHIFT 10
+#define PCIE0_PHY_IDDQ_SHIFT 2
+
+enum cygnus_pcie_phy_id {
+ CYGNUS_PHY_PCIE0 = 0,
+ CYGNUS_PHY_PCIE1,
+ MAX_NUM_PHYS,
+};
+
+struct cygnus_pcie_phy_core;
+
+/**
+ * struct cygnus_pcie_phy - Cygnus PCIe PHY device
+ * @core: pointer to the Cygnus PCIe PHY core control
+ * @id: internal ID to identify the Cygnus PCIe PHY
+ * @phy: pointer to the kernel PHY device
+ */
+struct cygnus_pcie_phy {
+ struct cygnus_pcie_phy_core *core;
+ enum cygnus_pcie_phy_id id;
+ struct phy *phy;
+};
+
+/**
+ * struct cygnus_pcie_phy_core - Cygnus PCIe PHY core control
+ * @dev: pointer to device
+ * @base: base register
+ * @lock: mutex to protect access to individual PHYs
+ * @phys: pointer to Cygnus PHY device
+ */
+struct cygnus_pcie_phy_core {
+ struct device *dev;
+ void __iomem *base;
+ struct mutex lock;
+ struct cygnus_pcie_phy phys[MAX_NUM_PHYS];
+};
+
+static int cygnus_pcie_power_config(struct cygnus_pcie_phy *phy, bool enable)
+{
+ struct cygnus_pcie_phy_core *core = phy->core;
+ unsigned shift;
+ u32 val;
+
+ mutex_lock(&core->lock);
+
+ switch (phy->id) {
+ case CYGNUS_PHY_PCIE0:
+ shift = PCIE0_PHY_IDDQ_SHIFT;
+ break;
+
+ case CYGNUS_PHY_PCIE1:
+ shift = PCIE1_PHY_IDDQ_SHIFT;
+ break;
+
+ default:
+ mutex_unlock(&core->lock);
+ dev_err(core->dev, "PCIe PHY %d invalid\n", phy->id);
+ return -EINVAL;
+ }
+
+ if (enable) {
+ val = readl(core->base + PCIE_CFG_OFFSET);
+ val &= ~BIT(shift);
+ writel(val, core->base + PCIE_CFG_OFFSET);
+ /*
+ * Wait 50 ms for the PCIe Serdes to stabilize after the analog
+ * front end is brought up
+ */
+ msleep(50);
+ } else {
+ val = readl(core->base + PCIE_CFG_OFFSET);
+ val |= BIT(shift);
+ writel(val, core->base + PCIE_CFG_OFFSET);
+ }
+
+ mutex_unlock(&core->lock);
+ dev_dbg(core->dev, "PCIe PHY %d %s\n", phy->id,
+ enable ? "enabled" : "disabled");
+ return 0;
+}
+
+static int cygnus_pcie_phy_power_on(struct phy *p)
+{
+ struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
+
+ return cygnus_pcie_power_config(phy, true);
+}
+
+static int cygnus_pcie_phy_power_off(struct phy *p)
+{
+ struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
+
+ return cygnus_pcie_power_config(phy, false);
+}
+
+static struct phy_ops cygnus_pcie_phy_ops = {
+ .power_on = cygnus_pcie_phy_power_on,
+ .power_off = cygnus_pcie_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int cygnus_pcie_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node, *child;
+ struct cygnus_pcie_phy_core *core;
+ struct phy_provider *provider;
+ struct resource *res;
+ unsigned cnt = 0;
+
+ if (of_get_child_count(node) == 0) {
+ dev_err(dev, "PHY no child node\n");
+ return -ENODEV;
+ }
+
+ core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
+ if (!core)
+ return -ENOMEM;
+
+ core->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ core->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(core->base))
+ return PTR_ERR(core->base);
+
+ mutex_init(&core->lock);
+
+ for_each_available_child_of_node(node, child) {
+ unsigned int id;
+ struct cygnus_pcie_phy *p;
+
+ if (of_property_read_u32(child, "reg", &id)) {
+ dev_err(dev, "missing reg property for %s\n",
+ child->name);
+ return -EINVAL;
+ }
+
+ if (id >= MAX_NUM_PHYS) {
+ dev_err(dev, "invalid PHY id: %u\n", id);
+ return -EINVAL;
+ }
+
+ if (core->phys[id].phy) {
+ dev_err(dev, "duplicated PHY id: %u\n", id);
+ return -EINVAL;
+ }
+
+ p = &core->phys[id];
+ p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
+ if (IS_ERR(p->phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(p->phy);
+ }
+
+ p->core = core;
+ p->id = id;
+ phy_set_drvdata(p->phy, p);
+ cnt++;
+ }
+
+ dev_set_drvdata(dev, core);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider)) {
+ dev_err(dev, "failed to register PHY provider\n");
+ return PTR_ERR(provider);
+ }
+
+ dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
+
+ return 0;
+}
+
+static const struct of_device_id cygnus_pcie_phy_match_table[] = {
+ { .compatible = "brcm,cygnus-pcie-phy" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cygnus_pcie_phy_match_table);
+
+static struct platform_driver cygnus_pcie_phy_driver = {
+ .driver = {
+ .name = "cygnus-pcie-phy",
+ .of_match_table = cygnus_pcie_phy_match_table,
+ },
+ .probe = cygnus_pcie_phy_probe,
+};
+module_platform_driver(cygnus_pcie_phy_driver);
+
+MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom Cygnus PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c
new file mode 100644
index 000000000000..f30b28bd41fe
--- /dev/null
+++ b/drivers/phy/phy-mt65xx-usb3.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.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 <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+/*
+ * for sifslv2 register, but exclude port's;
+ * relative to USB3_SIF2_BASE base address
+ */
+#define SSUSB_SIFSLV_SPLLC 0x0000
+
+/* offsets of sub-segment in each port registers */
+#define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000
+#define SSUSB_SIFSLV_U3PHYD_BASE 0x0100
+#define SSUSB_USB30_PHYA_SIV_B_BASE 0x0300
+#define SSUSB_SIFSLV_U3PHYA_DA_BASE 0x0400
+
+#define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0000)
+#define PA0_RG_U2PLL_FORCE_ON BIT(15)
+
+#define U3P_USBPHYACR2 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0008)
+#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18)
+
+#define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014)
+#define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12)
+#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
+#define PA5_RG_U2_HS_100U_U3_EN BIT(11)
+
+#define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018)
+#define PA6_RG_U2_ISO_EN BIT(31)
+#define PA6_RG_U2_BC11_SW_EN BIT(23)
+#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
+
+#define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020)
+#define P2C_RG_USB20_GPIO_CTL BIT(9)
+#define P2C_USB20_GPIO_MODE BIT(8)
+#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
+
+#define U3D_U2PHYDCR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0060)
+#define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24)
+
+#define U3P_U2PHYDTM0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0068)
+#define P2C_FORCE_UART_EN BIT(26)
+#define P2C_FORCE_DATAIN BIT(23)
+#define P2C_FORCE_DM_PULLDOWN BIT(21)
+#define P2C_FORCE_DP_PULLDOWN BIT(20)
+#define P2C_FORCE_XCVRSEL BIT(19)
+#define P2C_FORCE_SUSPENDM BIT(18)
+#define P2C_FORCE_TERMSEL BIT(17)
+#define P2C_RG_DATAIN GENMASK(13, 10)
+#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10)
+#define P2C_RG_DMPULLDOWN BIT(7)
+#define P2C_RG_DPPULLDOWN BIT(6)
+#define P2C_RG_XCVRSEL GENMASK(5, 4)
+#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
+#define P2C_RG_SUSPENDM BIT(3)
+#define P2C_RG_TERMSEL BIT(2)
+#define P2C_DTM0_PART_MASK \
+ (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
+ P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
+ P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
+ P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL)
+
+#define U3P_U2PHYDTM1 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x006C)
+#define P2C_RG_UART_EN BIT(16)
+#define P2C_RG_VBUSVALID BIT(5)
+#define P2C_RG_SESSEND BIT(4)
+#define P2C_RG_AVALID BIT(2)
+
+#define U3P_U3_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0000)
+#define P3A_RG_U3_VUSB10_ON BIT(5)
+
+#define U3P_U3_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018)
+#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
+#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
+
+#define U3P_U3_PHYA_REG9 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024)
+#define P3A_RG_RX_DAC_MUX GENMASK(5, 1)
+#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
+
+#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0000)
+#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
+#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
+
+#define U3P_PHYD_CDR1 (SSUSB_SIFSLV_U3PHYD_BASE + 0x005c)
+#define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24)
+#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
+#define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8)
+#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8)
+
+#define U3P_XTALCTL3 (SSUSB_SIFSLV_SPLLC + 0x0018)
+#define XC3_RG_U3_XTAL_RX_PWD BIT(9)
+#define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8)
+
+struct mt65xx_phy_instance {
+ struct phy *phy;
+ void __iomem *port_base;
+ u32 index;
+ u8 type;
+};
+
+struct mt65xx_u3phy {
+ struct device *dev;
+ void __iomem *sif_base; /* include sif2, but exclude port's */
+ struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
+ struct mt65xx_phy_instance **phys;
+ int nphys;
+};
+
+static void phy_instance_init(struct mt65xx_u3phy *u3phy,
+ struct mt65xx_phy_instance *instance)
+{
+ void __iomem *port_base = instance->port_base;
+ u32 index = instance->index;
+ u32 tmp;
+
+ /* switch to USB function. (system register, force ip into usb mode) */
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp &= ~P2C_FORCE_UART_EN;
+ tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0);
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+
+ tmp = readl(port_base + U3P_U2PHYDTM1);
+ tmp &= ~P2C_RG_UART_EN;
+ writel(tmp, port_base + U3P_U2PHYDTM1);
+
+ if (!index) {
+ tmp = readl(port_base + U3P_U2PHYACR4);
+ tmp &= ~P2C_U2_GPIO_CTR_MSK;
+ writel(tmp, port_base + U3P_U2PHYACR4);
+
+ tmp = readl(port_base + U3P_USBPHYACR2);
+ tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
+ writel(tmp, port_base + U3P_USBPHYACR2);
+
+ tmp = readl(port_base + U3D_U2PHYDCR0);
+ tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
+ writel(tmp, port_base + U3D_U2PHYDCR0);
+ } else {
+ tmp = readl(port_base + U3D_U2PHYDCR0);
+ tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
+ writel(tmp, port_base + U3D_U2PHYDCR0);
+
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+ }
+
+ /* DP/DM BC1.1 path Disable */
+ tmp = readl(port_base + U3P_USBPHYACR6);
+ tmp &= ~PA6_RG_U2_BC11_SW_EN;
+ writel(tmp, port_base + U3P_USBPHYACR6);
+
+ tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
+ tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
+ tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
+ writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
+
+ tmp = readl(port_base + U3P_U3_PHYA_REG9);
+ tmp &= ~P3A_RG_RX_DAC_MUX;
+ tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
+ writel(tmp, port_base + U3P_U3_PHYA_REG9);
+
+ tmp = readl(port_base + U3P_U3_PHYA_REG6);
+ tmp &= ~P3A_RG_TX_EIDLE_CM;
+ tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
+ writel(tmp, port_base + U3P_U3_PHYA_REG6);
+
+ tmp = readl(port_base + U3P_PHYD_CDR1);
+ tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1);
+ tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3);
+ writel(tmp, port_base + U3P_PHYD_CDR1);
+
+ dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
+}
+
+static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
+ struct mt65xx_phy_instance *instance)
+{
+ void __iomem *port_base = instance->port_base;
+ u32 index = instance->index;
+ u32 tmp;
+
+ if (!index) {
+ /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
+ tmp = readl(port_base + U3P_U3_PHYA_REG0);
+ tmp |= P3A_RG_U3_VUSB10_ON;
+ writel(tmp, port_base + U3P_U3_PHYA_REG0);
+ }
+
+ /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL);
+ tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+
+ /* OTG Enable */
+ tmp = readl(port_base + U3P_USBPHYACR6);
+ tmp |= PA6_RG_U2_OTG_VBUSCMP_EN;
+ writel(tmp, port_base + U3P_USBPHYACR6);
+
+ if (!index) {
+ tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
+ tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
+ writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
+
+ /* [mt8173]disable Change 100uA current from SSUSB */
+ tmp = readl(port_base + U3P_USBPHYACR5);
+ tmp &= ~PA5_RG_U2_HS_100U_U3_EN;
+ writel(tmp, port_base + U3P_USBPHYACR5);
+ }
+
+ tmp = readl(port_base + U3P_U2PHYDTM1);
+ tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID;
+ tmp &= ~P2C_RG_SESSEND;
+ writel(tmp, port_base + U3P_U2PHYDTM1);
+
+ /* USB 2.0 slew rate calibration */
+ tmp = readl(port_base + U3P_USBPHYACR5);
+ tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
+ tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4);
+ writel(tmp, port_base + U3P_USBPHYACR5);
+
+ if (index) {
+ tmp = readl(port_base + U3D_U2PHYDCR0);
+ tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
+ writel(tmp, port_base + U3D_U2PHYDCR0);
+
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+ }
+ dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
+}
+
+static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
+ struct mt65xx_phy_instance *instance)
+{
+ void __iomem *port_base = instance->port_base;
+ u32 index = instance->index;
+ u32 tmp;
+
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN);
+ tmp |= P2C_FORCE_SUSPENDM;
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+
+ /* OTG Disable */
+ tmp = readl(port_base + U3P_USBPHYACR6);
+ tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN;
+ writel(tmp, port_base + U3P_USBPHYACR6);
+
+ if (!index) {
+ /* (also disable)Change 100uA current switch to USB2.0 */
+ tmp = readl(port_base + U3P_USBPHYACR5);
+ tmp &= ~PA5_RG_U2_HS_100U_U3_EN;
+ writel(tmp, port_base + U3P_USBPHYACR5);
+ }
+
+ /* let suspendm=0, set utmi into analog power down */
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp &= ~P2C_RG_SUSPENDM;
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+ udelay(1);
+
+ tmp = readl(port_base + U3P_U2PHYDTM1);
+ tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID);
+ tmp |= P2C_RG_SESSEND;
+ writel(tmp, port_base + U3P_U2PHYDTM1);
+
+ if (!index) {
+ tmp = readl(port_base + U3P_U3_PHYA_REG0);
+ tmp &= ~P3A_RG_U3_VUSB10_ON;
+ writel(tmp, port_base + U3P_U3_PHYA_REG0);
+ } else {
+ tmp = readl(port_base + U3D_U2PHYDCR0);
+ tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
+ writel(tmp, port_base + U3D_U2PHYDCR0);
+ }
+
+ dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
+}
+
+static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
+ struct mt65xx_phy_instance *instance)
+{
+ void __iomem *port_base = instance->port_base;
+ u32 index = instance->index;
+ u32 tmp;
+
+ if (index) {
+ tmp = readl(port_base + U3D_U2PHYDCR0);
+ tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
+ writel(tmp, port_base + U3D_U2PHYDCR0);
+
+ tmp = readl(port_base + U3P_U2PHYDTM0);
+ tmp &= ~P2C_FORCE_SUSPENDM;
+ writel(tmp, port_base + U3P_U2PHYDTM0);
+ }
+}
+
+static int mt65xx_phy_init(struct phy *phy)
+{
+ struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+ struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+ int ret;
+
+ ret = clk_prepare_enable(u3phy->u3phya_ref);
+ if (ret) {
+ dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
+ return ret;
+ }
+
+ phy_instance_init(u3phy, instance);
+ return 0;
+}
+
+static int mt65xx_phy_power_on(struct phy *phy)
+{
+ struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+ struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+
+ phy_instance_power_on(u3phy, instance);
+ return 0;
+}
+
+static int mt65xx_phy_power_off(struct phy *phy)
+{
+ struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+ struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+
+ phy_instance_power_off(u3phy, instance);
+ return 0;
+}
+
+static int mt65xx_phy_exit(struct phy *phy)
+{
+ struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+ struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+
+ phy_instance_exit(u3phy, instance);
+ clk_disable_unprepare(u3phy->u3phya_ref);
+ return 0;
+}
+
+static struct phy *mt65xx_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev);
+ struct mt65xx_phy_instance *instance = NULL;
+ struct device_node *phy_np = args->np;
+ int index;
+
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (index = 0; index < u3phy->nphys; index++)
+ if (phy_np == u3phy->phys[index]->phy->dev.of_node) {
+ instance = u3phy->phys[index];
+ break;
+ }
+
+ if (!instance) {
+ dev_err(dev, "failed to find appropriate phy\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ instance->type = args->args[0];
+
+ if (!(instance->type == PHY_TYPE_USB2 ||
+ instance->type == PHY_TYPE_USB3)) {
+ dev_err(dev, "unsupported device type: %d\n", instance->type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return instance->phy;
+}
+
+static struct phy_ops mt65xx_u3phy_ops = {
+ .init = mt65xx_phy_init,
+ .exit = mt65xx_phy_exit,
+ .power_on = mt65xx_phy_power_on,
+ .power_off = mt65xx_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int mt65xx_u3phy_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 resource *sif_res;
+ struct mt65xx_u3phy *u3phy;
+ struct resource res;
+ int port;
+
+ u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
+ if (!u3phy)
+ return -ENOMEM;
+
+ u3phy->nphys = of_get_child_count(np);
+ u3phy->phys = devm_kcalloc(dev, u3phy->nphys,
+ sizeof(*u3phy->phys), GFP_KERNEL);
+ if (!u3phy->phys)
+ return -ENOMEM;
+
+ u3phy->dev = dev;
+ platform_set_drvdata(pdev, u3phy);
+
+ sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
+ if (IS_ERR(u3phy->sif_base)) {
+ dev_err(dev, "failed to remap sif regs\n");
+ return PTR_ERR(u3phy->sif_base);
+ }
+
+ u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
+ if (IS_ERR(u3phy->u3phya_ref)) {
+ dev_err(dev, "error to get u3phya_ref\n");
+ return PTR_ERR(u3phy->u3phya_ref);
+ }
+
+ port = 0;
+ for_each_child_of_node(np, child_np) {
+ struct mt65xx_phy_instance *instance;
+ struct phy *phy;
+ int retval;
+
+ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+ if (!instance)
+ return -ENOMEM;
+
+ u3phy->phys[port] = instance;
+
+ phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create phy\n");
+ return PTR_ERR(phy);
+ }
+
+ retval = of_address_to_resource(child_np, 0, &res);
+ if (retval) {
+ dev_err(dev, "failed to get address resource(id-%d)\n",
+ port);
+ return retval;
+ }
+
+ instance->port_base = devm_ioremap_resource(&phy->dev, &res);
+ if (IS_ERR(instance->port_base)) {
+ dev_err(dev, "failed to remap phy regs\n");
+ return PTR_ERR(instance->port_base);
+ }
+
+ instance->phy = phy;
+ instance->index = port;
+ phy_set_drvdata(phy, instance);
+ port++;
+ }
+
+ provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id mt65xx_u3phy_id_table[] = {
+ { .compatible = "mediatek,mt8173-u3phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
+
+static struct platform_driver mt65xx_u3phy_driver = {
+ .probe = mt65xx_u3phy_probe,
+ .driver = {
+ .name = "mt65xx-u3phy",
+ .of_match_table = mt65xx_u3phy_id_table,
+ },
+};
+
+module_platform_driver(mt65xx_u3phy_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("mt65xx USB PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
index 6e0d9fa8e1d1..c7a05996d5c1 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/phy-rcar-gen2.c
@@ -17,8 +17,7 @@
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
-
-#include <asm/cmpxchg.h>
+#include <linux/atomic.h>
#define USBHS_LPSTS 0x02
#define USBHS_UGCTRL 0x80
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index f278a9c547e1..1d22d93b552d 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -27,6 +27,13 @@ static int samsung_usb2_phy_power_on(struct phy *phy)
dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
inst->cfg->label);
+
+ if (drv->vbus) {
+ ret = regulator_enable(drv->vbus);
+ if (ret)
+ goto err_regulator;
+ }
+
ret = clk_prepare_enable(drv->clk);
if (ret)
goto err_main_clk;
@@ -48,6 +55,9 @@ err_power_on:
err_instance_clk:
clk_disable_unprepare(drv->clk);
err_main_clk:
+ if (drv->vbus)
+ regulator_disable(drv->vbus);
+err_regulator:
return ret;
}
@@ -55,7 +65,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
{
struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
struct samsung_usb2_phy_driver *drv = inst->drv;
- int ret;
+ int ret = 0;
dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
inst->cfg->label);
@@ -68,7 +78,10 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
}
clk_disable_unprepare(drv->ref_clk);
clk_disable_unprepare(drv->clk);
- return 0;
+ if (drv->vbus)
+ ret = regulator_disable(drv->vbus);
+
+ return ret;
}
static const struct phy_ops samsung_usb2_phy_ops = {
@@ -203,6 +216,14 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
return ret;
}
+ drv->vbus = devm_regulator_get(dev, "vbus");
+ if (IS_ERR(drv->vbus)) {
+ ret = PTR_ERR(drv->vbus);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ drv->vbus = NULL;
+ }
+
for (i = 0; i < drv->cfg->num_phys; i++) {
char *label = drv->cfg->phys[i].label;
struct samsung_usb2_phy_instance *p = &drv->instances[i];
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 44bead9b8f34..6563e7ca0ac4 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
+#include <linux/regulator/consumer.h>
#define KHZ 1000
#define MHZ (KHZ * KHZ)
@@ -37,6 +38,7 @@ struct samsung_usb2_phy_driver {
const struct samsung_usb2_phy_config *cfg;
struct clk *clk;
struct clk *ref_clk;
+ struct regulator *vbus;
unsigned long ref_rate;
u32 ref_reg_val;
struct device *dev;
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 731b395d6e6a..b12964b70625 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -551,19 +551,15 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
if (IS_ERR(data->base))
return PTR_ERR(data->base);
- data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN);
- if (IS_ERR(data->id_det_gpio)) {
- if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- data->id_det_gpio = NULL;
- }
-
- data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN);
- if (IS_ERR(data->vbus_det_gpio)) {
- if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- data->vbus_det_gpio = NULL;
- }
+ data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
+ GPIOD_IN);
+ if (IS_ERR(data->id_det_gpio))
+ return PTR_ERR(data->id_det_gpio);
+
+ data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
+ GPIOD_IN);
+ if (IS_ERR(data->vbus_det_gpio))
+ return PTR_ERR(data->vbus_det_gpio);
if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 84dd2ed47a92..b422e4ed73f4 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -67,6 +67,19 @@ config PINCTRL_AT91
help
Say Y here to enable the at91 pinctrl driver
+config PINCTRL_AT91PIO4
+ bool "AT91 PIO4 pinctrl driver"
+ depends on OF
+ depends on ARCH_AT91
+ select PINMUX
+ select GENERIC_PINCONF
+ select GPIOLIB
+ select GPIOLIB_IRQCHIP
+ select OF_GPIO
+ help
+ Say Y here to enable the at91 pinctrl/gpio driver for Atmel PIO4
+ controller available on sama5d2 SoC.
+
config PINCTRL_AMD
bool "AMD GPIO pin control"
depends on GPIOLIB
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index cad077c43fb7..738cb4929a49 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
+obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o
obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o
obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
@@ -50,6 +51,6 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/
obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
-obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
+obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 8efa235ca1c9..a1ea565fcd46 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -330,16 +330,6 @@ static inline void bcm2835_pinctrl_fsel_set(
bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
}
-static int bcm2835_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void bcm2835_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_gpio_direction_input(chip->base + offset);
@@ -375,8 +365,8 @@ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
static struct gpio_chip bcm2835_gpio_chip = {
.label = MODULE_NAME,
.owner = THIS_MODULE,
- .request = bcm2835_gpio_request,
- .free = bcm2835_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.direction_input = bcm2835_gpio_direction_input,
.direction_output = bcm2835_gpio_direction_output,
.get = bcm2835_gpio_get,
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
index 1ca783098e47..12a48f498b75 100644
--- a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
@@ -29,7 +29,6 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
@@ -597,127 +596,6 @@ static const struct pinconf_ops cygnus_pconf_ops = {
};
/*
- * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX
- * pinctrl pin space
- */
-struct cygnus_gpio_pin_range {
- unsigned offset;
- unsigned pin_base;
- unsigned num_pins;
-};
-
-#define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n }
-
-/*
- * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins
- */
-static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
- CYGNUS_PINRANGE(0, 42, 1),
- CYGNUS_PINRANGE(1, 44, 3),
- CYGNUS_PINRANGE(4, 48, 1),
- CYGNUS_PINRANGE(5, 50, 3),
- CYGNUS_PINRANGE(8, 126, 1),
- CYGNUS_PINRANGE(9, 155, 1),
- CYGNUS_PINRANGE(10, 152, 1),
- CYGNUS_PINRANGE(11, 154, 1),
- CYGNUS_PINRANGE(12, 153, 1),
- CYGNUS_PINRANGE(13, 127, 3),
- CYGNUS_PINRANGE(16, 140, 1),
- CYGNUS_PINRANGE(17, 145, 7),
- CYGNUS_PINRANGE(24, 130, 10),
- CYGNUS_PINRANGE(34, 141, 4),
- CYGNUS_PINRANGE(38, 54, 1),
- CYGNUS_PINRANGE(39, 56, 3),
- CYGNUS_PINRANGE(42, 60, 3),
- CYGNUS_PINRANGE(45, 64, 3),
- CYGNUS_PINRANGE(48, 68, 2),
- CYGNUS_PINRANGE(50, 84, 6),
- CYGNUS_PINRANGE(56, 94, 6),
- CYGNUS_PINRANGE(62, 72, 1),
- CYGNUS_PINRANGE(63, 70, 1),
- CYGNUS_PINRANGE(64, 80, 1),
- CYGNUS_PINRANGE(65, 74, 3),
- CYGNUS_PINRANGE(68, 78, 1),
- CYGNUS_PINRANGE(69, 82, 1),
- CYGNUS_PINRANGE(70, 156, 17),
- CYGNUS_PINRANGE(87, 104, 12),
- CYGNUS_PINRANGE(99, 102, 2),
- CYGNUS_PINRANGE(101, 90, 4),
- CYGNUS_PINRANGE(105, 116, 6),
- CYGNUS_PINRANGE(111, 100, 2),
- CYGNUS_PINRANGE(113, 122, 4),
- CYGNUS_PINRANGE(123, 11, 1),
- CYGNUS_PINRANGE(124, 38, 4),
- CYGNUS_PINRANGE(128, 43, 1),
- CYGNUS_PINRANGE(129, 47, 1),
- CYGNUS_PINRANGE(130, 49, 1),
- CYGNUS_PINRANGE(131, 53, 1),
- CYGNUS_PINRANGE(132, 55, 1),
- CYGNUS_PINRANGE(133, 59, 1),
- CYGNUS_PINRANGE(134, 63, 1),
- CYGNUS_PINRANGE(135, 67, 1),
- CYGNUS_PINRANGE(136, 71, 1),
- CYGNUS_PINRANGE(137, 73, 1),
- CYGNUS_PINRANGE(138, 77, 1),
- CYGNUS_PINRANGE(139, 79, 1),
- CYGNUS_PINRANGE(140, 81, 1),
- CYGNUS_PINRANGE(141, 83, 1),
- CYGNUS_PINRANGE(142, 10, 1)
-};
-
-/*
- * The Cygnus IOMUX controller mainly supports group based mux configuration,
- * but certain pins can be muxed to GPIO individually. Only the ASIU GPIO
- * controller can support this, so it's an optional configuration
- *
- * Return -ENODEV means no support and that's fine
- */
-static int cygnus_gpio_pinmux_add_range(struct cygnus_gpio *chip)
-{
- struct device_node *node = chip->dev->of_node;
- struct device_node *pinmux_node;
- struct platform_device *pinmux_pdev;
- struct gpio_chip *gc = &chip->gc;
- int i, ret = 0;
-
- /* parse DT to find the phandle to the pinmux controller */
- pinmux_node = of_parse_phandle(node, "pinmux", 0);
- if (!pinmux_node)
- return -ENODEV;
-
- pinmux_pdev = of_find_device_by_node(pinmux_node);
- /* no longer need the pinmux node */
- of_node_put(pinmux_node);
- if (!pinmux_pdev) {
- dev_err(chip->dev, "failed to get pinmux device\n");
- return -EINVAL;
- }
-
- /* now need to create the mapping between local GPIO and PINMUX pins */
- for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) {
- ret = gpiochip_add_pin_range(gc, dev_name(&pinmux_pdev->dev),
- cygnus_gpio_pintable[i].offset,
- cygnus_gpio_pintable[i].pin_base,
- cygnus_gpio_pintable[i].num_pins);
- if (ret) {
- dev_err(chip->dev, "unable to add GPIO pin range\n");
- goto err_put_device;
- }
- }
-
- chip->pinmux_is_supported = true;
-
- /* no need for pinmux_pdev device reference anymore */
- put_device(&pinmux_pdev->dev);
- return 0;
-
-err_put_device:
- put_device(&pinmux_pdev->dev);
- gpiochip_remove_pin_ranges(gc);
- return ret;
-}
-
-/*
* Cygnus GPIO controller supports some PINCONF related configurations such as
* pull up, pull down, and drive strength, when the pin is configured to GPIO
*
@@ -851,18 +729,15 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
gc->set = cygnus_gpio_set;
gc->get = cygnus_gpio_get;
+ chip->pinmux_is_supported = of_property_read_bool(dev->of_node,
+ "gpio-ranges");
+
ret = gpiochip_add(gc);
if (ret < 0) {
dev_err(dev, "unable to add GPIO chip\n");
return ret;
}
- ret = cygnus_gpio_pinmux_add_range(chip);
- if (ret && ret != -ENODEV) {
- dev_err(dev, "unable to add GPIO pin range\n");
- goto err_rm_gpiochip;
- }
-
ret = cygnus_gpio_register_pinconf(chip);
if (ret) {
dev_err(dev, "unable to register pinconf\n");
diff --git a/drivers/pinctrl/berlin/Kconfig b/drivers/pinctrl/berlin/Kconfig
index b18322bc7bf9..8fe6ad7795dc 100644
--- a/drivers/pinctrl/berlin/Kconfig
+++ b/drivers/pinctrl/berlin/Kconfig
@@ -1,4 +1,4 @@
-if ARCH_BERLIN
+if (ARCH_BERLIN || COMPILE_TEST)
config PINCTRL_BERLIN
bool
@@ -6,15 +6,23 @@ config PINCTRL_BERLIN
select REGMAP_MMIO
config PINCTRL_BERLIN_BG2
- bool
+ def_bool MACH_BERLIN_BG2
+ depends on OF
select PINCTRL_BERLIN
config PINCTRL_BERLIN_BG2CD
- bool
+ def_bool MACH_BERLIN_BG2CD
+ depends on OF
select PINCTRL_BERLIN
config PINCTRL_BERLIN_BG2Q
- bool
+ def_bool MACH_BERLIN_BG2Q
+ depends on OF
+ select PINCTRL_BERLIN
+
+config PINCTRL_BERLIN_BG4CT
+ bool "Marvell berlin4ct pin controller driver"
+ depends on OF
select PINCTRL_BERLIN
endif
diff --git a/drivers/pinctrl/berlin/Makefile b/drivers/pinctrl/berlin/Makefile
index deb0c6baf316..06f94029ad66 100644
--- a/drivers/pinctrl/berlin/Makefile
+++ b/drivers/pinctrl/berlin/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL_BERLIN) += berlin.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2) += berlin-bg2.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2CD) += berlin-bg2cd.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2Q) += berlin-bg2q.o
+obj-$(CONFIG_PINCTRL_BERLIN_BG4CT) += berlin-bg4ct.o
diff --git a/drivers/pinctrl/berlin/berlin-bg2.c b/drivers/pinctrl/berlin/berlin-bg2.c
index 274c5535b531..fabe728ae268 100644
--- a/drivers/pinctrl/berlin/berlin-bg2.c
+++ b/drivers/pinctrl/berlin/berlin-bg2.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
- * Antoine Ténart <antoine.tenart@free-electrons.com>
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -246,6 +246,6 @@ static struct platform_driver berlin2_pinctrl_driver = {
};
module_platform_driver(berlin2_pinctrl_driver);
-MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Berlin BG2 pinctrl driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/berlin/berlin-bg2cd.c b/drivers/pinctrl/berlin/berlin-bg2cd.c
index 0cb793a3552a..ad8c75861373 100644
--- a/drivers/pinctrl/berlin/berlin-bg2cd.c
+++ b/drivers/pinctrl/berlin/berlin-bg2cd.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
- * Antoine Ténart <antoine.tenart@free-electrons.com>
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -19,24 +19,24 @@
static const struct berlin_desc_group berlin2cd_soc_pinctrl_groups[] = {
/* G */
- BERLIN_PINCTRL_GROUP("G0", 0x00, 0x1, 0x00,
+ BERLIN_PINCTRL_GROUP("G0", 0x00, 0x3, 0x00,
BERLIN_PINCTRL_FUNCTION(0x0, "jtag"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x2, "led"),
BERLIN_PINCTRL_FUNCTION(0x3, "pwm")),
- BERLIN_PINCTRL_GROUP("G1", 0x00, 0x2, 0x01,
+ BERLIN_PINCTRL_GROUP("G1", 0x00, 0x3, 0x03,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
- BERLIN_PINCTRL_GROUP("G2", 0x00, 0x2, 0x02,
+ BERLIN_PINCTRL_GROUP("G2", 0x00, 0x3, 0x06,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "fe"),
BERLIN_PINCTRL_FUNCTION(0x3, "pll"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
- BERLIN_PINCTRL_GROUP("G3", 0x00, 0x2, 0x04,
+ BERLIN_PINCTRL_GROUP("G3", 0x00, 0x3, 0x09,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi2"),
@@ -44,7 +44,7 @@ static const struct berlin_desc_group berlin2cd_soc_pinctrl_groups[] = {
BERLIN_PINCTRL_FUNCTION(0x4, "fe"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
- BERLIN_PINCTRL_GROUP("G4", 0x00, 0x2, 0x06,
+ BERLIN_PINCTRL_GROUP("G4", 0x00, 0x3, 0x0c,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi3"),
@@ -52,7 +52,7 @@ static const struct berlin_desc_group berlin2cd_soc_pinctrl_groups[] = {
BERLIN_PINCTRL_FUNCTION(0x4, "pwm"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
- BERLIN_PINCTRL_GROUP("G5", 0x00, 0x3, 0x08,
+ BERLIN_PINCTRL_GROUP("G5", 0x00, 0x3, 0x0f,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi3"),
@@ -60,64 +60,66 @@ static const struct berlin_desc_group berlin2cd_soc_pinctrl_groups[] = {
BERLIN_PINCTRL_FUNCTION(0x4, "pwm"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
- BERLIN_PINCTRL_GROUP("G6", 0x00, 0x2, 0x0b,
+ BERLIN_PINCTRL_GROUP("G6", 0x00, 0x3, 0x12,
BERLIN_PINCTRL_FUNCTION(0x0, "uart0"), /* RX/TX */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G7", 0x00, 0x3, 0x0d,
+ BERLIN_PINCTRL_GROUP("G7", 0x00, 0x3, 0x15,
BERLIN_PINCTRL_FUNCTION(0x0, "eddc"),
BERLIN_PINCTRL_FUNCTION(0x1, "twsi1"),
BERLIN_PINCTRL_FUNCTION(0x2, "gpio")),
- BERLIN_PINCTRL_GROUP("G8", 0x00, 0x3, 0x10,
+ BERLIN_PINCTRL_GROUP("G8", 0x00, 0x3, 0x18,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G9", 0x00, 0x3, 0x13,
+ BERLIN_PINCTRL_GROUP("G9", 0x00, 0x3, 0x1b,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SS1n/SS2n */
- BERLIN_PINCTRL_FUNCTION(0x2, "twsi0")),
- BERLIN_PINCTRL_GROUP("G10", 0x00, 0x2, 0x16,
+ BERLIN_PINCTRL_FUNCTION(0x3, "twsi0")),
+ BERLIN_PINCTRL_GROUP("G10", 0x00, 0x2, 0x1e,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* CLK */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G11", 0x00, 0x2, 0x18,
+ BERLIN_PINCTRL_GROUP("G11", 0x04, 0x2, 0x00,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SDI/SDO */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G12", 0x00, 0x3, 0x1a,
+ BERLIN_PINCTRL_GROUP("G12", 0x04, 0x3, 0x02,
BERLIN_PINCTRL_FUNCTION(0x0, "usb1"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G13", 0x04, 0x3, 0x00,
+ BERLIN_PINCTRL_GROUP("G13", 0x04, 0x3, 0x05,
BERLIN_PINCTRL_FUNCTION(0x0, "nand"),
BERLIN_PINCTRL_FUNCTION(0x1, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x2, "usb1_dbg")),
- BERLIN_PINCTRL_GROUP("G14", 0x04, 0x1, 0x03,
+ BERLIN_PINCTRL_GROUP("G14", 0x04, 0x1, 0x08,
BERLIN_PINCTRL_FUNCTION(0x0, "nand"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G15", 0x04, 0x2, 0x04,
+ BERLIN_PINCTRL_GROUP("G15", 0x04, 0x3, 0x09,
BERLIN_PINCTRL_FUNCTION(0x0, "jtag"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
- BERLIN_PINCTRL_GROUP("G16", 0x04, 0x3, 0x06,
+ BERLIN_PINCTRL_GROUP("G16", 0x04, 0x3, 0x0c,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G17", 0x04, 0x3, 0x09,
+ BERLIN_PINCTRL_GROUP("G17", 0x04, 0x3, 0x0f,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G18", 0x04, 0x1, 0x0c,
+ BERLIN_PINCTRL_GROUP("G18", 0x04, 0x2, 0x12,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G19", 0x04, 0x1, 0x0d,
+ BERLIN_PINCTRL_GROUP("G19", 0x04, 0x2, 0x14,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G20", 0x04, 0x1, 0x0e,
+ BERLIN_PINCTRL_GROUP("G20", 0x04, 0x2, 0x16,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G21", 0x04, 0x3, 0x0f,
+ BERLIN_PINCTRL_GROUP("G21", 0x04, 0x3, 0x18,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G22", 0x04, 0x3, 0x12,
+ BERLIN_PINCTRL_GROUP("G22", 0x04, 0x3, 0x1b,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G23", 0x04, 0x3, 0x15,
+ BERLIN_PINCTRL_GROUP("G23", 0x08, 0x3, 0x00,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G24", 0x04, 0x2, 0x18,
+ BERLIN_PINCTRL_GROUP("G24", 0x08, 0x2, 0x03,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G25", 0x04, 0x2, 0x1a,
+ BERLIN_PINCTRL_GROUP("G25", 0x08, 0x2, 0x05,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G26", 0x04, 0x1, 0x1c,
+ BERLIN_PINCTRL_GROUP("G26", 0x08, 0x1, 0x07,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G27", 0x04, 0x1, 0x1d,
+ BERLIN_PINCTRL_GROUP("G27", 0x08, 0x2, 0x08,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
- BERLIN_PINCTRL_GROUP("G28", 0x04, 0x2, 0x1e,
+ BERLIN_PINCTRL_GROUP("G28", 0x08, 0x3, 0x0a,
+ BERLIN_PINCTRL_FUNCTION_UNKNOWN),
+ BERLIN_PINCTRL_GROUP("G29", 0x08, 0x3, 0x0d,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
};
@@ -189,6 +191,6 @@ static struct platform_driver berlin2cd_pinctrl_driver = {
};
module_platform_driver(berlin2cd_pinctrl_driver);
-MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Berlin BG2CD pinctrl driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/berlin/berlin-bg2q.c b/drivers/pinctrl/berlin/berlin-bg2q.c
index a466054a8206..cd171aea8ca8 100644
--- a/drivers/pinctrl/berlin/berlin-bg2q.c
+++ b/drivers/pinctrl/berlin/berlin-bg2q.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
- * Antoine Ténart <antoine.tenart@free-electrons.com>
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -408,6 +408,6 @@ static struct platform_driver berlin2q_pinctrl_driver = {
};
module_platform_driver(berlin2q_pinctrl_driver);
-MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Berlin BG2Q pinctrl driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/berlin/berlin-bg4ct.c b/drivers/pinctrl/berlin/berlin-bg4ct.c
new file mode 100644
index 000000000000..09172043d589
--- /dev/null
+++ b/drivers/pinctrl/berlin/berlin-bg4ct.c
@@ -0,0 +1,503 @@
+/*
+ * Marvell berlin4ct pinctrl driver
+ *
+ * Copyright (C) 2015 Marvell Technology Group Ltd.
+ *
+ * Author: Jisheng Zhang <jszhang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "berlin.h"
+
+static const struct berlin_desc_group berlin4ct_soc_pinctrl_groups[] = {
+ BERLIN_PINCTRL_GROUP("EMMC_RSTn", 0x0, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "emmc"), /* RSTn */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* GPIO47 */
+ BERLIN_PINCTRL_GROUP("NAND_IO0", 0x0, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO0 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* RXD0 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO0 */
+ BERLIN_PINCTRL_GROUP("NAND_IO1", 0x0, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO1 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* RXD1 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* CDn */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO1 */
+ BERLIN_PINCTRL_GROUP("NAND_IO2", 0x0, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO2 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* RXD2 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* DAT0 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO2 */
+ BERLIN_PINCTRL_GROUP("NAND_IO3", 0x0, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO3 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* RXD3 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* DAT1 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO3 */
+ BERLIN_PINCTRL_GROUP("NAND_IO4", 0x0, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO4 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* RXC */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* DAT2 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO4 */
+ BERLIN_PINCTRL_GROUP("NAND_IO5", 0x0, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO5 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* RXCTL */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* DAT3 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO5 */
+ BERLIN_PINCTRL_GROUP("NAND_IO6", 0x0, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO6 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* MDC */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* CMD */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO6 */
+ BERLIN_PINCTRL_GROUP("NAND_IO7", 0x0, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* IO7 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* MDIO */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sd1"), /* WP */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO7 */
+ BERLIN_PINCTRL_GROUP("NAND_ALE", 0x0, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* ALE */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* TXD0 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO8 */
+ BERLIN_PINCTRL_GROUP("NAND_CLE", 0x4, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* CLE */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* TXD1 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO9 */
+ BERLIN_PINCTRL_GROUP("NAND_WEn", 0x4, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* WEn */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* TXD2 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO10 */
+ BERLIN_PINCTRL_GROUP("NAND_REn", 0x4, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* REn */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* TXD3 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO11 */
+ BERLIN_PINCTRL_GROUP("NAND_WPn", 0x4, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* WPn */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO12 */
+ BERLIN_PINCTRL_GROUP("NAND_CEn", 0x4, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* CEn */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* TXC */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO13 */
+ BERLIN_PINCTRL_GROUP("NAND_RDY", 0x4, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "nand"), /* RDY */
+ BERLIN_PINCTRL_FUNCTION(0x1, "rgmii"), /* TXCTL */
+ BERLIN_PINCTRL_FUNCTION(0x3, "gpio")), /* GPIO14 */
+ BERLIN_PINCTRL_GROUP("SD0_CLK", 0x4, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO29 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* CLK*/
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts4"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG8 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG8 */
+ BERLIN_PINCTRL_GROUP("SD0_DAT0", 0x4, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO30 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* DAT0 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts4"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG9 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG9 */
+ BERLIN_PINCTRL_GROUP("SD0_DAT1", 0x4, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO31 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* DAT1 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts4"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG10 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG10 */
+ BERLIN_PINCTRL_GROUP("SD0_DAT2", 0x4, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO32 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* DAT2 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts4"), /* VALD */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG11 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG11 */
+ BERLIN_PINCTRL_GROUP("SD0_DAT3", 0x8, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO33 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* DAT3 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts5"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG12 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG12 */
+ BERLIN_PINCTRL_GROUP("SD0_CDn", 0x8, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO34 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* CDn */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts5"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG13 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG13 */
+ BERLIN_PINCTRL_GROUP("SD0_CMD", 0x8, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO35 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* CMD */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts5"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG14 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG14 */
+ BERLIN_PINCTRL_GROUP("SD0_WP", 0x8, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO36 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd0"), /* WP */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts5"), /* VALD */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG15 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG15 */
+ BERLIN_PINCTRL_GROUP("STS0_CLK", 0x8, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO21 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts0"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x2, "cpupll"), /* CLKO */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG0 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG0 */
+ BERLIN_PINCTRL_GROUP("STS0_SOP", 0x8, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO22 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts0"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x2, "syspll"), /* CLKO */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG1 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG1 */
+ BERLIN_PINCTRL_GROUP("STS0_SD", 0x8, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO23 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts0"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x2, "mempll"), /* CLKO */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG2 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG2 */
+ BERLIN_PINCTRL_GROUP("STS0_VALD", 0x8, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO24 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts0"), /* VALD */
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG3 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG3 */
+ BERLIN_PINCTRL_GROUP("STS1_CLK", 0x8, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO25 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts1"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm0"),
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG4 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG4 */
+ BERLIN_PINCTRL_GROUP("STS1_SOP", 0x8, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO26 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts1"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm1"),
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG5 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG5 */
+ BERLIN_PINCTRL_GROUP("STS1_SD", 0xc, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO27 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts1"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm2"),
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG6 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG6 */
+ BERLIN_PINCTRL_GROUP("STS1_VALD", 0xc, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO28 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sts1"), /* VALD */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm3"),
+ BERLIN_PINCTRL_FUNCTION(0x5, "v4g"), /* DBG7 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "phy")), /* DBG7 */
+ BERLIN_PINCTRL_GROUP("SCRD0_RST", 0xc, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO15 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* RST */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* CLK */
+ BERLIN_PINCTRL_GROUP("SCRD0_DCLK", 0xc, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO16 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* DCLK */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* CMD */
+ BERLIN_PINCTRL_GROUP("SCRD0_GPIO0", 0xc, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO17 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* SCRD0 GPIO0 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sif"), /* DIO */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT0 */
+ BERLIN_PINCTRL_GROUP("SCRD0_GPIO1", 0xc, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO18 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* SCRD0 GPIO1 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sif"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT1 */
+ BERLIN_PINCTRL_GROUP("SCRD0_DIO", 0xc, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO19 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* DIO */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sif"), /* DEN */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT2 */
+ BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */
+ BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */
+ BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts2")), /* CLK */
+ BERLIN_PINCTRL_GROUP("SPI1_SS1n", 0xc, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS1n */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO38 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts2"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x4, "pwm1")),
+ BERLIN_PINCTRL_GROUP("SPI1_SS2n", 0x10, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS2n */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO39 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts2"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x4, "pwm0")),
+ BERLIN_PINCTRL_GROUP("SPI1_SS3n", 0x10, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS3n */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO40 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts2")), /* VALD */
+ BERLIN_PINCTRL_GROUP("SPI1_SCLK", 0x10, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SCLK */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO41 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts3")), /* CLK */
+ BERLIN_PINCTRL_GROUP("SPI1_SDO", 0x10, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SDO */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO42 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts3")), /* SOP */
+ BERLIN_PINCTRL_GROUP("SPI1_SDI", 0x10, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SDI */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO43 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts3")), /* SD */
+ BERLIN_PINCTRL_GROUP("USB0_DRV_VBUS", 0x10, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO44 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "usb0"), /* VBUS */
+ BERLIN_PINCTRL_FUNCTION(0x2, "sts3")), /* VALD */
+ BERLIN_PINCTRL_GROUP("TW0_SCL", 0x10, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO45 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tw0")), /* SCL */
+ BERLIN_PINCTRL_GROUP("TW0_SDA", 0x10, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO46 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tw0")), /* SDA */
+};
+
+static const struct berlin_desc_group berlin4ct_avio_pinctrl_groups[] = {
+ BERLIN_PINCTRL_GROUP("TX_EDDC_SCL", 0x0, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO0 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tx_eddc"), /* SCL */
+ BERLIN_PINCTRL_FUNCTION(0x2, "tw1")), /* SCL */
+ BERLIN_PINCTRL_GROUP("TX_EDDC_SDA", 0x0, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO1 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tx_eddc"), /* SDA */
+ BERLIN_PINCTRL_FUNCTION(0x2, "tw1")), /* SDA */
+ BERLIN_PINCTRL_GROUP("I2S1_LRCKO", 0x0, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO2 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* LRCKO */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts6"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac"), /* DBG0 */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x7, "avio")), /* DBG0 */
+ BERLIN_PINCTRL_GROUP("I2S1_BCLKO", 0x0, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO3 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* BCLKO */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts6"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac"), /* DBG1 */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b"), /* CMD */
+ BERLIN_PINCTRL_FUNCTION(0x7, "avio")), /* DBG1 */
+ BERLIN_PINCTRL_GROUP("I2S1_DO", 0x0, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO4 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* DO */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts6"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac"), /* DBG2 */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b"), /* DAT0 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "avio")), /* DBG2 */
+ BERLIN_PINCTRL_GROUP("I2S1_MCLK", 0x0, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO5 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* MCLK */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts6"), /* VALD */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac_test"), /* MCLK */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b"), /* DAT1 */
+ BERLIN_PINCTRL_FUNCTION(0x7, "avio")), /* DBG3 */
+ BERLIN_PINCTRL_GROUP("SPDIFO", 0x0, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO6 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "spdifo"),
+ BERLIN_PINCTRL_FUNCTION(0x2, "avpll"), /* CLKO */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac")), /* DBG3 */
+ BERLIN_PINCTRL_GROUP("I2S2_MCLK", 0x0, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO7 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* MCLK */
+ BERLIN_PINCTRL_FUNCTION(0x4, "hdmi"), /* FBCLK */
+ BERLIN_PINCTRL_FUNCTION(0x5, "pdm")), /* CLKO */
+ BERLIN_PINCTRL_GROUP("I2S2_LRCKI", 0x0, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO8 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* LRCKI */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm0"),
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts7"), /* CLK */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac_test"), /* LRCK */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b")), /* DAT2 */
+ BERLIN_PINCTRL_GROUP("I2S2_BCLKI", 0x0, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO9 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* BCLKI */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm1"),
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts7"), /* SOP */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac_test"), /* BCLK */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b")), /* DAT3 */
+ BERLIN_PINCTRL_GROUP("I2S2_DI0", 0x4, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO10 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* DI0 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm2"),
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts7"), /* SD */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac_test"), /* SDIN */
+ BERLIN_PINCTRL_FUNCTION(0x5, "pdm"), /* DI0 */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b")), /* CDn */
+ BERLIN_PINCTRL_GROUP("I2S2_DI1", 0x4, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* AVIO GPIO11 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* DI1 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm3"),
+ BERLIN_PINCTRL_FUNCTION(0x3, "sts7"), /* VALD */
+ BERLIN_PINCTRL_FUNCTION(0x4, "adac_test"), /* PWMCLK */
+ BERLIN_PINCTRL_FUNCTION(0x5, "pdm"), /* DI1 */
+ BERLIN_PINCTRL_FUNCTION(0x6, "sd1b")), /* WP */
+};
+
+static const struct berlin_desc_group berlin4ct_sysmgr_pinctrl_groups[] = {
+ BERLIN_PINCTRL_GROUP("SM_TW2_SCL", 0x0, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO19 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tw2")), /* SCL */
+ BERLIN_PINCTRL_GROUP("SM_TW2_SDA", 0x0, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO20 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tw2")), /* SDA */
+ BERLIN_PINCTRL_GROUP("SM_TW3_SCL", 0x0, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO21 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tw3")), /* SCL */
+ BERLIN_PINCTRL_GROUP("SM_TW3_SDA", 0x0, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO22 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "tw3")), /* SDA */
+ BERLIN_PINCTRL_GROUP("SM_TMS", 0x0, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "jtag"), /* TMS */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* SM GPIO0 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm0")),
+ BERLIN_PINCTRL_GROUP("SM_TDI", 0x0, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "jtag"), /* TDI */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* SM GPIO1 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "pwm1")),
+ BERLIN_PINCTRL_GROUP("SM_TDO", 0x0, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "jtag"), /* TDO */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO2 */
+ BERLIN_PINCTRL_GROUP("SM_URT0_TXD", 0x0, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "uart0"), /* TXD */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO3 */
+ BERLIN_PINCTRL_GROUP("SM_URT0_RXD", 0x0, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "uart0"), /* RXD */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO4 */
+ BERLIN_PINCTRL_GROUP("SM_URT1_TXD", 0x0, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO5 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "uart1"), /* TXD */
+ BERLIN_PINCTRL_FUNCTION(0x2, "eth1"), /* RXCLK */
+ BERLIN_PINCTRL_FUNCTION(0x3, "pwm2"),
+ BERLIN_PINCTRL_FUNCTION(0x4, "timer0"),
+ BERLIN_PINCTRL_FUNCTION(0x5, "clk_25m")),
+ BERLIN_PINCTRL_GROUP("SM_URT1_RXD", 0x4, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO6 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "uart1"), /* RXD */
+ BERLIN_PINCTRL_FUNCTION(0x3, "pwm3"),
+ BERLIN_PINCTRL_FUNCTION(0x4, "timer1")),
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SS0n", 0x4, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi2"), /* SS0 n*/
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO7 */
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SS1n", 0x4, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO8 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "spi2")), /* SS1n */
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SS2n", 0x4, 0x3, 0x09,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO9 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SS2n */
+ BERLIN_PINCTRL_FUNCTION(0x2, "eth1"), /* MDC */
+ BERLIN_PINCTRL_FUNCTION(0x3, "pwm0"),
+ BERLIN_PINCTRL_FUNCTION(0x4, "timer0"),
+ BERLIN_PINCTRL_FUNCTION(0x5, "clk_25m")),
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SS3n", 0x4, 0x3, 0x0c,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO10 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SS3n */
+ BERLIN_PINCTRL_FUNCTION(0x2, "eth1"), /* MDIO */
+ BERLIN_PINCTRL_FUNCTION(0x3, "pwm1"),
+ BERLIN_PINCTRL_FUNCTION(0x4, "timer1")),
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SDO", 0x4, 0x3, 0x0f,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi2"), /* SDO */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO11 */
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SDI", 0x4, 0x3, 0x12,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi2"), /* SDI */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO12 */
+ BERLIN_PINCTRL_GROUP("SM_SPI2_SCLK", 0x4, 0x3, 0x15,
+ BERLIN_PINCTRL_FUNCTION(0x0, "spi2"), /* SCLK */
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio")), /* SM GPIO13 */
+ BERLIN_PINCTRL_GROUP("SM_FE_LED0", 0x4, 0x3, 0x18,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO14 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "led")), /* LED0 */
+ BERLIN_PINCTRL_GROUP("SM_FE_LED1", 0x4, 0x3, 0x1b,
+ BERLIN_PINCTRL_FUNCTION(0x0, "pwr"),
+ BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* SM GPIO 15 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "led")), /* LED1 */
+ BERLIN_PINCTRL_GROUP("SM_FE_LED2", 0x8, 0x3, 0x00,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO16 */
+ BERLIN_PINCTRL_FUNCTION(0x2, "led")), /* LED2 */
+ BERLIN_PINCTRL_GROUP("SM_HDMI_HPD", 0x8, 0x3, 0x03,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO17 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "hdmi")), /* HPD */
+ BERLIN_PINCTRL_GROUP("SM_HDMI_CEC", 0x8, 0x3, 0x06,
+ BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO18 */
+ BERLIN_PINCTRL_FUNCTION(0x1, "hdmi")), /* CEC */
+};
+
+static const struct berlin_pinctrl_desc berlin4ct_soc_pinctrl_data = {
+ .groups = berlin4ct_soc_pinctrl_groups,
+ .ngroups = ARRAY_SIZE(berlin4ct_soc_pinctrl_groups),
+};
+
+static const struct berlin_pinctrl_desc berlin4ct_avio_pinctrl_data = {
+ .groups = berlin4ct_avio_pinctrl_groups,
+ .ngroups = ARRAY_SIZE(berlin4ct_avio_pinctrl_groups),
+};
+
+static const struct berlin_pinctrl_desc berlin4ct_sysmgr_pinctrl_data = {
+ .groups = berlin4ct_sysmgr_pinctrl_groups,
+ .ngroups = ARRAY_SIZE(berlin4ct_sysmgr_pinctrl_groups),
+};
+
+static const struct of_device_id berlin4ct_pinctrl_match[] = {
+ {
+ .compatible = "marvell,berlin4ct-soc-pinctrl",
+ .data = &berlin4ct_soc_pinctrl_data,
+ },
+ {
+ .compatible = "marvell,berlin4ct-avio-pinctrl",
+ .data = &berlin4ct_avio_pinctrl_data,
+ },
+ {
+ .compatible = "marvell,berlin4ct-system-pinctrl",
+ .data = &berlin4ct_sysmgr_pinctrl_data,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, berlin4ct_pinctrl_match);
+
+static int berlin4ct_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match =
+ of_match_device(berlin4ct_pinctrl_match, &pdev->dev);
+ struct regmap_config *rmconfig;
+ struct regmap *regmap;
+ struct resource *res;
+ void __iomem *base;
+
+ rmconfig = devm_kzalloc(&pdev->dev, sizeof(*rmconfig), GFP_KERNEL);
+ if (!rmconfig)
+ 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);
+
+ rmconfig->reg_bits = 32,
+ rmconfig->val_bits = 32,
+ rmconfig->reg_stride = 4,
+ rmconfig->max_register = resource_size(res);
+
+ regmap = devm_regmap_init_mmio(&pdev->dev, base, rmconfig);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return berlin_pinctrl_probe_regmap(pdev, match->data, regmap);
+}
+
+static struct platform_driver berlin4ct_pinctrl_driver = {
+ .probe = berlin4ct_pinctrl_probe,
+ .driver = {
+ .name = "berlin4ct-pinctrl",
+ .of_match_table = berlin4ct_pinctrl_match,
+ },
+};
+module_platform_driver(berlin4ct_pinctrl_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@marvell.com>");
+MODULE_DESCRIPTION("Marvell berlin4ct pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
index f49580617055..46f2b4818da3 100644
--- a/drivers/pinctrl/berlin/berlin.c
+++ b/drivers/pinctrl/berlin/berlin.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
- * Antoine Ténart <antoine.tenart@free-electrons.com>
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -292,20 +292,14 @@ static struct pinctrl_desc berlin_pctrl_desc = {
.owner = THIS_MODULE,
};
-int berlin_pinctrl_probe(struct platform_device *pdev,
- const struct berlin_pinctrl_desc *desc)
+int berlin_pinctrl_probe_regmap(struct platform_device *pdev,
+ const struct berlin_pinctrl_desc *desc,
+ struct regmap *regmap)
{
struct device *dev = &pdev->dev;
- struct device_node *parent_np = of_get_parent(dev->of_node);
struct berlin_pinctrl *pctrl;
- struct regmap *regmap;
int ret;
- regmap = syscon_node_to_regmap(parent_np);
- of_node_put(parent_np);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
@@ -330,3 +324,17 @@ int berlin_pinctrl_probe(struct platform_device *pdev,
return 0;
}
+
+int berlin_pinctrl_probe(struct platform_device *pdev,
+ const struct berlin_pinctrl_desc *desc)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *parent_np = of_get_parent(dev->of_node);
+ struct regmap *regmap = syscon_node_to_regmap(parent_np);
+
+ of_node_put(parent_np);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return berlin_pinctrl_probe_regmap(pdev, desc, regmap);
+}
diff --git a/drivers/pinctrl/berlin/berlin.h b/drivers/pinctrl/berlin/berlin.h
index e1aa84145194..e9b30f95b03e 100644
--- a/drivers/pinctrl/berlin/berlin.h
+++ b/drivers/pinctrl/berlin/berlin.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
- * Antoine Ténart <antoine.tenart@free-electrons.com>
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -58,4 +58,8 @@ struct berlin_pinctrl_function {
int berlin_pinctrl_probe(struct platform_device *pdev,
const struct berlin_pinctrl_desc *desc);
+int berlin_pinctrl_probe_regmap(struct platform_device *pdev,
+ const struct berlin_pinctrl_desc *desc,
+ struct regmap *regmap);
+
#endif /* __PINCTRL_BERLIN_H */
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 9638a00c67c2..2686a4450dfc 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1240,6 +1240,38 @@ int pinctrl_force_default(struct pinctrl_dev *pctldev)
}
EXPORT_SYMBOL_GPL(pinctrl_force_default);
+/**
+ * pinctrl_init_done() - tell pinctrl probe is done
+ *
+ * We'll use this time to switch the pins from "init" to "default" unless the
+ * driver selected some other state.
+ *
+ * @dev: device to that's done probing
+ */
+int pinctrl_init_done(struct device *dev)
+{
+ struct dev_pin_info *pins = dev->pins;
+ int ret;
+
+ if (!pins)
+ return 0;
+
+ if (IS_ERR(pins->init_state))
+ return 0; /* No such state */
+
+ if (pins->p->state != pins->init_state)
+ return 0; /* Not at init anyway */
+
+ if (IS_ERR(pins->default_state))
+ return 0; /* No default state */
+
+ ret = pinctrl_select_state(pins->p, pins->default_state);
+ if (ret)
+ dev_err(dev, "failed to activate default pinctrl state\n");
+
+ return ret;
+}
+
#ifdef CONFIG_PM
/**
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index d7b98ba36825..a5bb93987378 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_address.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
@@ -39,6 +40,7 @@ struct imx_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
void __iomem *base;
+ void __iomem *input_sel_base;
const struct imx_pinctrl_soc_info *info;
};
@@ -254,7 +256,12 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
* Regular select input register can never be at offset
* 0, and we only print register value for regular case.
*/
- writel(pin->input_val, ipctl->base + pin->input_reg);
+ if (ipctl->input_sel_base)
+ writel(pin->input_val, ipctl->input_sel_base +
+ pin->input_reg);
+ else
+ writel(pin->input_val, ipctl->base +
+ pin->input_reg);
dev_dbg(ipctl->dev,
"==>select_input: offset 0x%x val 0x%x\n",
pin->input_reg, pin->input_val);
@@ -542,6 +549,9 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
struct imx_pin_reg *pin_reg;
struct imx_pin *pin = &grp->pins[i];
+ if (!(info->flags & ZERO_OFFSET_VALID) && !mux_reg)
+ mux_reg = -1;
+
if (info->flags & SHARE_MUX_CONF_REG) {
conf_reg = mux_reg;
} else {
@@ -550,7 +560,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
conf_reg = -1;
}
- pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
+ pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
pin_reg = &info->pin_regs[pin_id];
pin->pin = pin_id;
grp->pin_ids[i] = pin_id;
@@ -580,7 +590,6 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
struct device_node *child;
struct imx_pmx_func *func;
struct imx_pin_group *grp;
- static u32 grp_index;
u32 i = 0;
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
@@ -599,7 +608,7 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
for_each_child_of_node(np, child) {
func->groups[i] = child->name;
- grp = &info->groups[grp_index++];
+ grp = &info->groups[info->group_index++];
imx_pinctrl_parse_groups(child, grp, info, i++);
}
@@ -683,6 +692,8 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
int imx_pinctrl_probe(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info)
{
+ struct device_node *dev_np = pdev->dev.of_node;
+ struct device_node *np;
struct imx_pinctrl *ipctl;
struct resource *res;
int ret, i;
@@ -713,6 +724,23 @@ int imx_pinctrl_probe(struct platform_device *pdev,
if (IS_ERR(ipctl->base))
return PTR_ERR(ipctl->base);
+ if (of_property_read_bool(dev_np, "fsl,input-sel")) {
+ np = of_parse_phandle(dev_np, "fsl,input-sel", 0);
+ if (np) {
+ ipctl->input_sel_base = of_iomap(np, 0);
+ if (IS_ERR(ipctl->input_sel_base)) {
+ of_node_put(np);
+ dev_err(&pdev->dev,
+ "iomuxc input select base address not found\n");
+ return PTR_ERR(ipctl->input_sel_base);
+ }
+ } else {
+ dev_err(&pdev->dev, "iomuxc fsl,input-sel property not found\n");
+ return -EINVAL;
+ }
+ of_node_put(np);
+ }
+
imx_pinctrl_desc.name = dev_name(&pdev->dev);
imx_pinctrl_desc.pins = info->pins;
imx_pinctrl_desc.npins = info->npins;
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h b/drivers/pinctrl/freescale/pinctrl-imx.h
index 49e55d39f7c8..2a592f657c18 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -78,12 +78,14 @@ struct imx_pinctrl_soc_info {
struct imx_pin_reg *pin_regs;
struct imx_pin_group *groups;
unsigned int ngroups;
+ unsigned int group_index;
struct imx_pmx_func *functions;
unsigned int nfunctions;
unsigned int flags;
};
#define SHARE_MUX_CONF_REG 0x1
+#define ZERO_OFFSET_VALID 0x2
#define NO_MUX 0x0
#define NO_PAD 0x0
diff --git a/drivers/pinctrl/freescale/pinctrl-imx25.c b/drivers/pinctrl/freescale/pinctrl-imx25.c
index faf635654312..293ed4381cc0 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx25.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx25.c
@@ -26,7 +26,8 @@
#include "pinctrl-imx.h"
enum imx25_pads {
- MX25_PAD_RESERVE0 = 1,
+ MX25_PAD_RESERVE0 = 0,
+ MX25_PAD_RESERVE1 = 1,
MX25_PAD_A10 = 2,
MX25_PAD_A13 = 3,
MX25_PAD_A14 = 4,
@@ -169,6 +170,7 @@ enum imx25_pads {
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX25_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(MX25_PAD_RESERVE1),
IMX_PINCTRL_PIN(MX25_PAD_A10),
IMX_PINCTRL_PIN(MX25_PAD_A13),
IMX_PINCTRL_PIN(MX25_PAD_A14),
diff --git a/drivers/pinctrl/freescale/pinctrl-imx7d.c b/drivers/pinctrl/freescale/pinctrl-imx7d.c
index 1fa7530530dd..16dc925117de 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx7d.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx7d.c
@@ -174,6 +174,17 @@ enum imx7d_pads {
MX7D_PAD_ENET1_COL = 154,
};
+enum imx7d_lpsr_pads {
+ MX7D_PAD_GPIO1_IO00 = 0,
+ MX7D_PAD_GPIO1_IO01 = 1,
+ MX7D_PAD_GPIO1_IO02 = 2,
+ MX7D_PAD_GPIO1_IO03 = 3,
+ MX7D_PAD_GPIO1_IO04 = 4,
+ MX7D_PAD_GPIO1_IO05 = 5,
+ MX7D_PAD_GPIO1_IO06 = 6,
+ MX7D_PAD_GPIO1_IO07 = 7,
+};
+
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx7d_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX7D_PAD_RESERVE0),
@@ -333,13 +344,32 @@ static const struct pinctrl_pin_desc imx7d_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX7D_PAD_ENET1_COL),
};
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx7d_lpsr_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO00),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO01),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO02),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO03),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO04),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO05),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO06),
+ IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO07),
+};
+
static struct imx_pinctrl_soc_info imx7d_pinctrl_info = {
.pins = imx7d_pinctrl_pads,
.npins = ARRAY_SIZE(imx7d_pinctrl_pads),
};
+static struct imx_pinctrl_soc_info imx7d_lpsr_pinctrl_info = {
+ .pins = imx7d_lpsr_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx7d_lpsr_pinctrl_pads),
+ .flags = ZERO_OFFSET_VALID,
+};
+
static struct of_device_id imx7d_pinctrl_of_match[] = {
{ .compatible = "fsl,imx7d-iomuxc", .data = &imx7d_pinctrl_info, },
+ { .compatible = "fsl,imx7d-iomuxc-lpsr", .data = &imx7d_lpsr_pinctrl_info },
{ /* sentinel */ }
};
diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c
index f64eecb24755..6bbda6b4ab50 100644
--- a/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -474,7 +474,7 @@ static int mxs_pinctrl_probe_dt(struct platform_device *pdev,
f->name = fn = child->name;
}
f->ngroups++;
- };
+ }
/* Get groups for each function */
idxf = 0;
diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig
index fe5e07db0a95..4d2efad6553c 100644
--- a/drivers/pinctrl/intel/Kconfig
+++ b/drivers/pinctrl/intel/Kconfig
@@ -34,6 +34,14 @@ config PINCTRL_INTEL
select GPIOLIB
select GPIOLIB_IRQCHIP
+config PINCTRL_BROXTON
+ tristate "Intel Broxton pinctrl and GPIO driver"
+ depends on ACPI
+ select PINCTRL_INTEL
+ help
+ Broxton pinctrl driver provides an interface that allows
+ configuring of SoC pins and using them as GPIOs.
+
config PINCTRL_SUNRISEPOINT
tristate "Intel Sunrisepoint pinctrl and GPIO driver"
depends on ACPI
diff --git a/drivers/pinctrl/intel/Makefile b/drivers/pinctrl/intel/Makefile
index fee756e1255b..03bc68e3546c 100644
--- a/drivers/pinctrl/intel/Makefile
+++ b/drivers/pinctrl/intel/Makefile
@@ -3,4 +3,5 @@
obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o
obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o
+obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o
obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index f79ea430f651..b59ce75b1947 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -696,6 +696,7 @@ static int byt_gpio_resume(struct device *dev)
}
#endif
+#ifdef CONFIG_PM
static int byt_gpio_runtime_suspend(struct device *dev)
{
return 0;
@@ -705,6 +706,7 @@ static int byt_gpio_runtime_resume(struct device *dev)
{
return 0;
}
+#endif
static const struct dev_pm_ops byt_gpio_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c
new file mode 100644
index 000000000000..e42d5d4183f5
--- /dev/null
+++ b/drivers/pinctrl/intel/pinctrl-broxton.c
@@ -0,0 +1,1065 @@
+/*
+ * Intel Broxton SoC pinctrl/GPIO driver
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-intel.h"
+
+#define BXT_PAD_OWN 0x020
+#define BXT_HOSTSW_OWN 0x080
+#define BXT_PADCFGLOCK 0x090
+#define BXT_GPI_IE 0x110
+
+#define BXT_COMMUNITY(s, e) \
+ { \
+ .padown_offset = BXT_PAD_OWN, \
+ .padcfglock_offset = BXT_PADCFGLOCK, \
+ .hostown_offset = BXT_HOSTSW_OWN, \
+ .ie_offset = BXT_GPI_IE, \
+ .pin_base = (s), \
+ .npins = ((e) - (s) + 1), \
+ }
+
+/* BXT */
+static const struct pinctrl_pin_desc bxt_north_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "PWM0"),
+ PINCTRL_PIN(35, "PWM1"),
+ PINCTRL_PIN(36, "PWM2"),
+ PINCTRL_PIN(37, "PWM3"),
+ PINCTRL_PIN(38, "LPSS_UART0_RXD"),
+ PINCTRL_PIN(39, "LPSS_UART0_TXD"),
+ PINCTRL_PIN(40, "LPSS_UART0_RTS_B"),
+ PINCTRL_PIN(41, "LPSS_UART0_CTS_B"),
+ PINCTRL_PIN(42, "LPSS_UART1_RXD"),
+ PINCTRL_PIN(43, "LPSS_UART1_TXD"),
+ PINCTRL_PIN(44, "LPSS_UART1_RTS_B"),
+ PINCTRL_PIN(45, "LPSS_UART1_CTS_B"),
+ PINCTRL_PIN(46, "LPSS_UART2_RXD"),
+ PINCTRL_PIN(47, "LPSS_UART2_TXD"),
+ PINCTRL_PIN(48, "LPSS_UART2_RTS_B"),
+ PINCTRL_PIN(49, "LPSS_UART2_CTS_B"),
+ PINCTRL_PIN(50, "ISH_UART0_RXD"),
+ PINCTRL_PIN(51, "ISH_UART0_TXT"),
+ PINCTRL_PIN(52, "ISH_UART0_RTS_B"),
+ PINCTRL_PIN(53, "ISH_UART0_CTS_B"),
+ PINCTRL_PIN(54, "ISH_UART1_RXD"),
+ PINCTRL_PIN(55, "ISH_UART1_TXT"),
+ PINCTRL_PIN(56, "ISH_UART1_RTS_B"),
+ PINCTRL_PIN(57, "ISH_UART1_CTS_B"),
+ PINCTRL_PIN(58, "ISH_UART2_RXD"),
+ PINCTRL_PIN(59, "ISH_UART2_TXD"),
+ PINCTRL_PIN(60, "ISH_UART2_RTS_B"),
+ PINCTRL_PIN(61, "ISH_UART2_CTS_B"),
+ PINCTRL_PIN(62, "GP_CAMERASB00"),
+ PINCTRL_PIN(63, "GP_CAMERASB01"),
+ PINCTRL_PIN(64, "GP_CAMERASB02"),
+ PINCTRL_PIN(65, "GP_CAMERASB03"),
+ PINCTRL_PIN(66, "GP_CAMERASB04"),
+ PINCTRL_PIN(67, "GP_CAMERASB05"),
+ PINCTRL_PIN(68, "GP_CAMERASB06"),
+ PINCTRL_PIN(69, "GP_CAMERASB07"),
+ PINCTRL_PIN(70, "GP_CAMERASB08"),
+ PINCTRL_PIN(71, "GP_CAMERASB09"),
+ PINCTRL_PIN(72, "GP_CAMERASB10"),
+ PINCTRL_PIN(73, "GP_CAMERASB11"),
+ PINCTRL_PIN(74, "TCK"),
+ PINCTRL_PIN(75, "TRST_B"),
+ PINCTRL_PIN(76, "TMS"),
+ PINCTRL_PIN(77, "TDI"),
+ PINCTRL_PIN(78, "CX_PMODE"),
+ PINCTRL_PIN(79, "CX_PREQ_B"),
+ PINCTRL_PIN(80, "JTAGX"),
+ PINCTRL_PIN(81, "CX_PRDY_B"),
+ PINCTRL_PIN(82, "TDO"),
+};
+
+static const unsigned bxt_north_pwm0_pins[] = { 34 };
+static const unsigned bxt_north_pwm1_pins[] = { 35 };
+static const unsigned bxt_north_pwm2_pins[] = { 36 };
+static const unsigned bxt_north_pwm3_pins[] = { 37 };
+static const unsigned bxt_north_uart0_pins[] = { 38, 39, 40, 41 };
+static const unsigned bxt_north_uart1_pins[] = { 42, 43, 44, 45 };
+static const unsigned bxt_north_uart2_pins[] = { 46, 47, 48, 49 };
+static const unsigned bxt_north_uart0b_pins[] = { 50, 51, 52, 53 };
+static const unsigned bxt_north_uart1b_pins[] = { 54, 55, 56, 57 };
+static const unsigned bxt_north_uart2b_pins[] = { 58, 59, 60, 61 };
+static const unsigned bxt_north_uart3_pins[] = { 58, 59, 60, 61 };
+
+static const struct intel_pingroup bxt_north_groups[] = {
+ PIN_GROUP("pwm0_grp", bxt_north_pwm0_pins, 1),
+ PIN_GROUP("pwm1_grp", bxt_north_pwm1_pins, 1),
+ PIN_GROUP("pwm2_grp", bxt_north_pwm2_pins, 1),
+ PIN_GROUP("pwm3_grp", bxt_north_pwm3_pins, 1),
+ PIN_GROUP("uart0_grp", bxt_north_uart0_pins, 1),
+ PIN_GROUP("uart1_grp", bxt_north_uart1_pins, 1),
+ PIN_GROUP("uart2_grp", bxt_north_uart2_pins, 1),
+ PIN_GROUP("uart0b_grp", bxt_north_uart0b_pins, 2),
+ PIN_GROUP("uart1b_grp", bxt_north_uart1b_pins, 2),
+ PIN_GROUP("uart2b_grp", bxt_north_uart2b_pins, 2),
+ PIN_GROUP("uart3_grp", bxt_north_uart3_pins, 3),
+};
+
+static const char * const bxt_north_pwm0_groups[] = { "pwm0_grp" };
+static const char * const bxt_north_pwm1_groups[] = { "pwm1_grp" };
+static const char * const bxt_north_pwm2_groups[] = { "pwm2_grp" };
+static const char * const bxt_north_pwm3_groups[] = { "pwm3_grp" };
+static const char * const bxt_north_uart0_groups[] = {
+ "uart0_grp", "uart0b_grp",
+};
+static const char * const bxt_north_uart1_groups[] = {
+ "uart1_grp", "uart1b_grp",
+};
+static const char * const bxt_north_uart2_groups[] = {
+ "uart2_grp", "uart2b_grp",
+};
+static const char * const bxt_north_uart3_groups[] = { "uart3_grp" };
+
+static const struct intel_function bxt_north_functions[] = {
+ FUNCTION("pwm0", bxt_north_pwm0_groups),
+ FUNCTION("pwm1", bxt_north_pwm1_groups),
+ FUNCTION("pwm2", bxt_north_pwm2_groups),
+ FUNCTION("pwm3", bxt_north_pwm3_groups),
+ FUNCTION("uart0", bxt_north_uart0_groups),
+ FUNCTION("uart1", bxt_north_uart1_groups),
+ FUNCTION("uart2", bxt_north_uart2_groups),
+ FUNCTION("uart3", bxt_north_uart3_groups),
+};
+
+static const struct intel_community bxt_north_communities[] = {
+ BXT_COMMUNITY(0, 82),
+};
+
+static const struct intel_pinctrl_soc_data bxt_north_soc_data = {
+ .uid = "1",
+ .pins = bxt_north_pins,
+ .npins = ARRAY_SIZE(bxt_north_pins),
+ .groups = bxt_north_groups,
+ .ngroups = ARRAY_SIZE(bxt_north_groups),
+ .functions = bxt_north_functions,
+ .nfunctions = ARRAY_SIZE(bxt_north_functions),
+ .communities = bxt_north_communities,
+ .ncommunities = ARRAY_SIZE(bxt_north_communities),
+};
+
+static const struct pinctrl_pin_desc bxt_northwest_pins[] = {
+ PINCTRL_PIN(0, "PMC_SPI_FS0"),
+ PINCTRL_PIN(1, "PMC_SPI_FS1"),
+ PINCTRL_PIN(2, "PMC_SPI_FS2"),
+ PINCTRL_PIN(3, "PMC_SPI_RXD"),
+ PINCTRL_PIN(4, "PMC_SPI_TXD"),
+ PINCTRL_PIN(5, "PMC_SPI_CLK"),
+ PINCTRL_PIN(6, "PMC_UART_RXD"),
+ PINCTRL_PIN(7, "PMC_UART_TXD"),
+ PINCTRL_PIN(8, "PMIC_PWRGOOD"),
+ PINCTRL_PIN(9, "PMIC_RESET_B"),
+ PINCTRL_PIN(10, "RTC_CLK"),
+ PINCTRL_PIN(11, "PMIC_SDWN_B"),
+ PINCTRL_PIN(12, "PMIC_BCUDISW2"),
+ PINCTRL_PIN(13, "PMIC_BCUDISCRIT"),
+ PINCTRL_PIN(14, "PMIC_THERMTRIP_B"),
+ PINCTRL_PIN(15, "PMIC_STDBY"),
+ PINCTRL_PIN(16, "SVID0_ALERT_B"),
+ PINCTRL_PIN(17, "SVID0_DATA"),
+ PINCTRL_PIN(18, "SVID0_CLK"),
+ PINCTRL_PIN(19, "PMIC_I2C_SCL"),
+ PINCTRL_PIN(20, "PMIC_I2C_SDA"),
+ PINCTRL_PIN(21, "AVS_I2S1_MCLK"),
+ PINCTRL_PIN(22, "AVS_I2S1_BCLK"),
+ PINCTRL_PIN(23, "AVS_I2S1_WS_SYNC"),
+ PINCTRL_PIN(24, "AVS_I2S1_SDI"),
+ PINCTRL_PIN(25, "AVS_I2S1_SDO"),
+ PINCTRL_PIN(26, "AVS_M_CLK_A1"),
+ PINCTRL_PIN(27, "AVS_M_CLK_B1"),
+ PINCTRL_PIN(28, "AVS_M_DATA_1"),
+ PINCTRL_PIN(29, "AVS_M_CLK_AB2"),
+ PINCTRL_PIN(30, "AVS_M_DATA_2"),
+ PINCTRL_PIN(31, "AVS_I2S2_MCLK"),
+ PINCTRL_PIN(32, "AVS_I2S2_BCLK"),
+ PINCTRL_PIN(33, "AVS_I2S2_WS_SYNC"),
+ PINCTRL_PIN(34, "AVS_I2S2_SDI"),
+ PINCTRL_PIN(35, "AVS_I2S2_SDOK"),
+ PINCTRL_PIN(36, "AVS_I2S3_BCLK"),
+ PINCTRL_PIN(37, "AVS_I2S3_WS_SYNC"),
+ PINCTRL_PIN(38, "AVS_I2S3_SDI"),
+ PINCTRL_PIN(39, "AVS_I2S3_SDO"),
+ PINCTRL_PIN(40, "AVS_I2S4_BCLK"),
+ PINCTRL_PIN(41, "AVS_I2S4_WS_SYNC"),
+ PINCTRL_PIN(42, "AVS_I2S4_SDI"),
+ PINCTRL_PIN(43, "AVS_I2S4_SDO"),
+ PINCTRL_PIN(44, "PROCHOT_B"),
+ PINCTRL_PIN(45, "FST_SPI_CS0_B"),
+ PINCTRL_PIN(46, "FST_SPI_CS1_B"),
+ PINCTRL_PIN(47, "FST_SPI_MOSI_IO0"),
+ PINCTRL_PIN(48, "FST_SPI_MISO_IO1"),
+ PINCTRL_PIN(49, "FST_SPI_IO2"),
+ PINCTRL_PIN(50, "FST_SPI_IO3"),
+ PINCTRL_PIN(51, "FST_SPI_CLK"),
+ PINCTRL_PIN(52, "FST_SPI_CLK_FB"),
+ PINCTRL_PIN(53, "GP_SSP_0_CLK"),
+ PINCTRL_PIN(54, "GP_SSP_0_FS0"),
+ PINCTRL_PIN(55, "GP_SSP_0_FS1"),
+ PINCTRL_PIN(56, "GP_SSP_0_FS2"),
+ PINCTRL_PIN(57, "GP_SSP_0_RXD"),
+ PINCTRL_PIN(58, "GP_SSP_0_TXD"),
+ PINCTRL_PIN(59, "GP_SSP_1_CLK"),
+ PINCTRL_PIN(60, "GP_SSP_1_FS0"),
+ PINCTRL_PIN(61, "GP_SSP_1_FS1"),
+ PINCTRL_PIN(62, "GP_SSP_1_FS2"),
+ PINCTRL_PIN(63, "GP_SSP_1_FS3"),
+ PINCTRL_PIN(64, "GP_SSP_1_RXD"),
+ PINCTRL_PIN(65, "GP_SSP_1_TXD"),
+ PINCTRL_PIN(66, "GP_SSP_2_CLK"),
+ PINCTRL_PIN(67, "GP_SSP_2_FS0"),
+ PINCTRL_PIN(68, "GP_SSP_2_FS1"),
+ PINCTRL_PIN(69, "GP_SSP_2_FS2"),
+ PINCTRL_PIN(70, "GP_SSP_2_RXD"),
+ PINCTRL_PIN(71, "GP_SSP_2_TXD"),
+};
+
+static const unsigned bxt_northwest_ssp0_pins[] = { 53, 54, 55, 56, 57, 58 };
+static const unsigned bxt_northwest_ssp1_pins[] = {
+ 59, 60, 61, 62, 63, 64, 65
+};
+static const unsigned bxt_northwest_ssp2_pins[] = { 66, 67, 68, 69, 70, 71 };
+static const unsigned bxt_northwest_uart3_pins[] = { 67, 68, 69, 70 };
+
+static const struct intel_pingroup bxt_northwest_groups[] = {
+ PIN_GROUP("ssp0_grp", bxt_northwest_ssp0_pins, 1),
+ PIN_GROUP("ssp1_grp", bxt_northwest_ssp1_pins, 1),
+ PIN_GROUP("ssp2_grp", bxt_northwest_ssp2_pins, 1),
+ PIN_GROUP("uart3_grp", bxt_northwest_uart3_pins, 2),
+};
+
+static const char * const bxt_northwest_ssp0_groups[] = { "ssp0_grp" };
+static const char * const bxt_northwest_ssp1_groups[] = { "ssp1_grp" };
+static const char * const bxt_northwest_ssp2_groups[] = { "ssp2_grp" };
+static const char * const bxt_northwest_uart3_groups[] = { "uart3_grp" };
+
+static const struct intel_function bxt_northwest_functions[] = {
+ FUNCTION("ssp0", bxt_northwest_ssp0_groups),
+ FUNCTION("ssp1", bxt_northwest_ssp1_groups),
+ FUNCTION("ssp2", bxt_northwest_ssp2_groups),
+ FUNCTION("uart3", bxt_northwest_uart3_groups),
+};
+
+static const struct intel_community bxt_northwest_communities[] = {
+ BXT_COMMUNITY(0, 71),
+};
+
+static const struct intel_pinctrl_soc_data bxt_northwest_soc_data = {
+ .uid = "2",
+ .pins = bxt_northwest_pins,
+ .npins = ARRAY_SIZE(bxt_northwest_pins),
+ .groups = bxt_northwest_groups,
+ .ngroups = ARRAY_SIZE(bxt_northwest_groups),
+ .functions = bxt_northwest_functions,
+ .nfunctions = ARRAY_SIZE(bxt_northwest_functions),
+ .communities = bxt_northwest_communities,
+ .ncommunities = ARRAY_SIZE(bxt_northwest_communities),
+};
+
+static const struct pinctrl_pin_desc bxt_west_pins[] = {
+ PINCTRL_PIN(0, "LPSS_I2C0_SDA"),
+ PINCTRL_PIN(1, "LPSS_I2C0_SCL"),
+ PINCTRL_PIN(2, "LPSS_I2C1_SDA"),
+ PINCTRL_PIN(3, "LPSS_I2C1_SCL"),
+ PINCTRL_PIN(4, "LPSS_I2C2_SDA"),
+ PINCTRL_PIN(5, "LPSS_I2C2_SCL"),
+ PINCTRL_PIN(6, "LPSS_I2C3_SDA"),
+ PINCTRL_PIN(7, "LPSS_I2C3_SCL"),
+ PINCTRL_PIN(8, "LPSS_I2C4_SDA"),
+ PINCTRL_PIN(9, "LPSS_I2C4_SCL"),
+ PINCTRL_PIN(10, "LPSS_I2C5_SDA"),
+ PINCTRL_PIN(11, "LPSS_I2C5_SCL"),
+ PINCTRL_PIN(12, "LPSS_I2C6_SDA"),
+ PINCTRL_PIN(13, "LPSS_I2C6_SCL"),
+ PINCTRL_PIN(14, "LPSS_I2C7_SDA"),
+ PINCTRL_PIN(15, "LPSS_I2C7_SCL"),
+ PINCTRL_PIN(16, "ISH_I2C0_SDA"),
+ PINCTRL_PIN(17, "ISH_I2C0_SCL"),
+ PINCTRL_PIN(18, "ISH_I2C1_SDA"),
+ PINCTRL_PIN(19, "ISH_I2C1_SCL"),
+ PINCTRL_PIN(20, "ISH_I2C2_SDA"),
+ PINCTRL_PIN(21, "ISH_I2C2_SCL"),
+ PINCTRL_PIN(22, "ISH_GPIO_0"),
+ PINCTRL_PIN(23, "ISH_GPIO_1"),
+ PINCTRL_PIN(24, "ISH_GPIO_2"),
+ PINCTRL_PIN(25, "ISH_GPIO_3"),
+ PINCTRL_PIN(26, "ISH_GPIO_4"),
+ PINCTRL_PIN(27, "ISH_GPIO_5"),
+ PINCTRL_PIN(28, "ISH_GPIO_6"),
+ PINCTRL_PIN(29, "ISH_GPIO_7"),
+ PINCTRL_PIN(30, "ISH_GPIO_8"),
+ PINCTRL_PIN(31, "ISH_GPIO_9"),
+ PINCTRL_PIN(32, "MODEM_CLKREQ"),
+ PINCTRL_PIN(33, "DGCLKDBG_PMC_0"),
+ PINCTRL_PIN(34, "DGCLKDBG_PMC_1"),
+ PINCTRL_PIN(35, "DGCLKDBG_PMC_2"),
+ PINCTRL_PIN(36, "DGCLKDBG_ICLK_0"),
+ PINCTRL_PIN(37, "DGCLKDBG_ICLK_1"),
+ PINCTRL_PIN(38, "OSC_CLK_OUT_0"),
+ PINCTRL_PIN(39, "OSC_CLK_OUT_1"),
+ PINCTRL_PIN(40, "OSC_CLK_OUT_2"),
+ PINCTRL_PIN(41, "OSC_CLK_OUT_3"),
+};
+
+static const unsigned bxt_west_i2c0_pins[] = { 0, 1 };
+static const unsigned bxt_west_i2c1_pins[] = { 2, 3 };
+static const unsigned bxt_west_i2c2_pins[] = { 4, 5 };
+static const unsigned bxt_west_i2c3_pins[] = { 6, 7 };
+static const unsigned bxt_west_i2c4_pins[] = { 8, 9 };
+static const unsigned bxt_west_i2c5_pins[] = { 10, 11 };
+static const unsigned bxt_west_i2c6_pins[] = { 12, 13 };
+static const unsigned bxt_west_i2c7_pins[] = { 14, 15 };
+static const unsigned bxt_west_i2c5b_pins[] = { 16, 17 };
+static const unsigned bxt_west_i2c6b_pins[] = { 18, 19 };
+static const unsigned bxt_west_i2c7b_pins[] = { 20, 21 };
+
+static const struct intel_pingroup bxt_west_groups[] = {
+ PIN_GROUP("i2c0_grp", bxt_west_i2c0_pins, 1),
+ PIN_GROUP("i2c1_grp", bxt_west_i2c1_pins, 1),
+ PIN_GROUP("i2c2_grp", bxt_west_i2c2_pins, 1),
+ PIN_GROUP("i2c3_grp", bxt_west_i2c3_pins, 1),
+ PIN_GROUP("i2c4_grp", bxt_west_i2c4_pins, 1),
+ PIN_GROUP("i2c5_grp", bxt_west_i2c5_pins, 1),
+ PIN_GROUP("i2c6_grp", bxt_west_i2c6_pins, 1),
+ PIN_GROUP("i2c7_grp", bxt_west_i2c7_pins, 1),
+ PIN_GROUP("i2c5b_grp", bxt_west_i2c5b_pins, 2),
+ PIN_GROUP("i2c6b_grp", bxt_west_i2c6b_pins, 2),
+ PIN_GROUP("i2c7b_grp", bxt_west_i2c7b_pins, 2),
+};
+
+static const char * const bxt_west_i2c0_groups[] = { "i2c0_grp" };
+static const char * const bxt_west_i2c1_groups[] = { "i2c1_grp" };
+static const char * const bxt_west_i2c2_groups[] = { "i2c2_grp" };
+static const char * const bxt_west_i2c3_groups[] = { "i2c3_grp" };
+static const char * const bxt_west_i2c4_groups[] = { "i2c4_grp" };
+static const char * const bxt_west_i2c5_groups[] = { "i2c5_grp", "i2c5b_grp" };
+static const char * const bxt_west_i2c6_groups[] = { "i2c6_grp", "i2c6b_grp" };
+static const char * const bxt_west_i2c7_groups[] = { "i2c7_grp", "i2c7b_grp" };
+
+static const struct intel_function bxt_west_functions[] = {
+ FUNCTION("i2c0", bxt_west_i2c0_groups),
+ FUNCTION("i2c1", bxt_west_i2c1_groups),
+ FUNCTION("i2c2", bxt_west_i2c2_groups),
+ FUNCTION("i2c3", bxt_west_i2c3_groups),
+ FUNCTION("i2c4", bxt_west_i2c4_groups),
+ FUNCTION("i2c5", bxt_west_i2c5_groups),
+ FUNCTION("i2c6", bxt_west_i2c6_groups),
+ FUNCTION("i2c7", bxt_west_i2c7_groups),
+};
+
+static const struct intel_community bxt_west_communities[] = {
+ BXT_COMMUNITY(0, 41),
+};
+
+static const struct intel_pinctrl_soc_data bxt_west_soc_data = {
+ .uid = "3",
+ .pins = bxt_west_pins,
+ .npins = ARRAY_SIZE(bxt_west_pins),
+ .groups = bxt_west_groups,
+ .ngroups = ARRAY_SIZE(bxt_west_groups),
+ .functions = bxt_west_functions,
+ .nfunctions = ARRAY_SIZE(bxt_west_functions),
+ .communities = bxt_west_communities,
+ .ncommunities = ARRAY_SIZE(bxt_west_communities),
+};
+
+static const struct pinctrl_pin_desc bxt_southwest_pins[] = {
+ PINCTRL_PIN(0, "EMMC0_CLK"),
+ PINCTRL_PIN(1, "EMMC0_D0"),
+ PINCTRL_PIN(2, "EMMC0_D1"),
+ PINCTRL_PIN(3, "EMMC0_D2"),
+ PINCTRL_PIN(4, "EMMC0_D3"),
+ PINCTRL_PIN(5, "EMMC0_D4"),
+ PINCTRL_PIN(6, "EMMC0_D5"),
+ PINCTRL_PIN(7, "EMMC0_D6"),
+ PINCTRL_PIN(8, "EMMC0_D7"),
+ PINCTRL_PIN(9, "EMMC0_CMD"),
+ PINCTRL_PIN(10, "SDIO_CLK"),
+ PINCTRL_PIN(11, "SDIO_D0"),
+ PINCTRL_PIN(12, "SDIO_D1"),
+ PINCTRL_PIN(13, "SDIO_D2"),
+ PINCTRL_PIN(14, "SDIO_D3"),
+ PINCTRL_PIN(15, "SDIO_CMD"),
+ PINCTRL_PIN(16, "SDCARD_CLK"),
+ PINCTRL_PIN(17, "SDCARD_D0"),
+ PINCTRL_PIN(18, "SDCARD_D1"),
+ PINCTRL_PIN(19, "SDCARD_D2"),
+ PINCTRL_PIN(20, "SDCARD_D3"),
+ PINCTRL_PIN(21, "SDCARD_CD_B"),
+ PINCTRL_PIN(22, "SDCARD_CMD"),
+ PINCTRL_PIN(23, "SDCARD_LVL_CLK_FB"),
+ PINCTRL_PIN(24, "SDCARD_LVL_CMD_DIR"),
+ PINCTRL_PIN(25, "SDCARD_LVL_DAT_DIR"),
+ PINCTRL_PIN(26, "EMMC0_STROBE"),
+ PINCTRL_PIN(27, "SDIO_PWR_DOWN_B"),
+ PINCTRL_PIN(28, "SDCARD_PWR_DOWN_B"),
+ PINCTRL_PIN(29, "SDCARD_LVL_SEL"),
+ PINCTRL_PIN(30, "SDCARD_LVL_WP"),
+};
+
+static const unsigned bxt_southwest_emmc0_pins[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 26,
+};
+static const unsigned bxt_southwest_sdio_pins[] = {
+ 10, 11, 12, 13, 14, 15, 27,
+};
+static const unsigned bxt_southwest_sdcard_pins[] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30,
+};
+
+static const struct intel_pingroup bxt_southwest_groups[] = {
+ PIN_GROUP("emmc0_grp", bxt_southwest_emmc0_pins, 1),
+ PIN_GROUP("sdio_grp", bxt_southwest_sdio_pins, 1),
+ PIN_GROUP("sdcard_grp", bxt_southwest_sdcard_pins, 1),
+};
+
+static const char * const bxt_southwest_emmc0_groups[] = { "emmc0_grp" };
+static const char * const bxt_southwest_sdio_groups[] = { "sdio_grp" };
+static const char * const bxt_southwest_sdcard_groups[] = { "sdcard_grp" };
+
+static const struct intel_function bxt_southwest_functions[] = {
+ FUNCTION("emmc0", bxt_southwest_emmc0_groups),
+ FUNCTION("sdio", bxt_southwest_sdio_groups),
+ FUNCTION("sdcard", bxt_southwest_sdcard_groups),
+};
+
+static const struct intel_community bxt_southwest_communities[] = {
+ BXT_COMMUNITY(0, 30),
+};
+
+static const struct intel_pinctrl_soc_data bxt_southwest_soc_data = {
+ .uid = "4",
+ .pins = bxt_southwest_pins,
+ .npins = ARRAY_SIZE(bxt_southwest_pins),
+ .groups = bxt_southwest_groups,
+ .ngroups = ARRAY_SIZE(bxt_southwest_groups),
+ .functions = bxt_southwest_functions,
+ .nfunctions = ARRAY_SIZE(bxt_southwest_functions),
+ .communities = bxt_southwest_communities,
+ .ncommunities = ARRAY_SIZE(bxt_southwest_communities),
+};
+
+static const struct pinctrl_pin_desc bxt_south_pins[] = {
+ PINCTRL_PIN(0, "HV_DDI0_DDC_SDA"),
+ PINCTRL_PIN(1, "HV_DDI0_DDC_SCL"),
+ PINCTRL_PIN(2, "HV_DDI1_DDC_SDA"),
+ PINCTRL_PIN(3, "HV_DDI1_DDC_SCL"),
+ PINCTRL_PIN(4, "DBI_SDA"),
+ PINCTRL_PIN(5, "DBI_SCL"),
+ PINCTRL_PIN(6, "PANEL0_VDDEN"),
+ PINCTRL_PIN(7, "PANEL0_BKLTEN"),
+ PINCTRL_PIN(8, "PANEL0_BKLTCTL"),
+ PINCTRL_PIN(9, "PANEL1_VDDEN"),
+ PINCTRL_PIN(10, "PANEL1_BKLTEN"),
+ PINCTRL_PIN(11, "PANEL1_BKLTCTL"),
+ PINCTRL_PIN(12, "DBI_CSX"),
+ PINCTRL_PIN(13, "DBI_RESX"),
+ PINCTRL_PIN(14, "GP_INTD_DSI_TE1"),
+ PINCTRL_PIN(15, "GP_INTD_DSI_TE2"),
+ PINCTRL_PIN(16, "USB_OC0_B"),
+ PINCTRL_PIN(17, "USB_OC1_B"),
+ PINCTRL_PIN(18, "MEX_WAKE0_B"),
+ PINCTRL_PIN(19, "MEX_WAKE1_B"),
+};
+
+static const struct intel_community bxt_south_communities[] = {
+ BXT_COMMUNITY(0, 19),
+};
+
+static const struct intel_pinctrl_soc_data bxt_south_soc_data = {
+ .uid = "5",
+ .pins = bxt_south_pins,
+ .npins = ARRAY_SIZE(bxt_south_pins),
+ .communities = bxt_south_communities,
+ .ncommunities = ARRAY_SIZE(bxt_south_communities),
+};
+
+static const struct intel_pinctrl_soc_data *bxt_pinctrl_soc_data[] = {
+ &bxt_north_soc_data,
+ &bxt_northwest_soc_data,
+ &bxt_west_soc_data,
+ &bxt_southwest_soc_data,
+ &bxt_south_soc_data,
+ NULL,
+};
+
+/* APL */
+static const struct pinctrl_pin_desc apl_north_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "PWM0"),
+ PINCTRL_PIN(35, "PWM1"),
+ PINCTRL_PIN(36, "PWM2"),
+ PINCTRL_PIN(37, "PWM3"),
+ PINCTRL_PIN(38, "LPSS_UART0_RXD"),
+ PINCTRL_PIN(39, "LPSS_UART0_TXD"),
+ PINCTRL_PIN(40, "LPSS_UART0_RTS_B"),
+ PINCTRL_PIN(41, "LPSS_UART0_CTS_B"),
+ PINCTRL_PIN(42, "LPSS_UART1_RXD"),
+ PINCTRL_PIN(43, "LPSS_UART1_TXD"),
+ PINCTRL_PIN(44, "LPSS_UART1_RTS_B"),
+ PINCTRL_PIN(45, "LPSS_UART1_CTS_B"),
+ PINCTRL_PIN(46, "LPSS_UART2_RXD"),
+ PINCTRL_PIN(47, "LPSS_UART2_TXD"),
+ PINCTRL_PIN(48, "LPSS_UART2_RTS_B"),
+ PINCTRL_PIN(49, "LPSS_UART2_CTS_B"),
+ PINCTRL_PIN(50, "GP_CAMERASB00"),
+ PINCTRL_PIN(51, "GP_CAMERASB01"),
+ PINCTRL_PIN(52, "GP_CAMERASB02"),
+ PINCTRL_PIN(53, "GP_CAMERASB03"),
+ PINCTRL_PIN(54, "GP_CAMERASB04"),
+ PINCTRL_PIN(55, "GP_CAMERASB05"),
+ PINCTRL_PIN(56, "GP_CAMERASB06"),
+ PINCTRL_PIN(57, "GP_CAMERASB07"),
+ PINCTRL_PIN(58, "GP_CAMERASB08"),
+ PINCTRL_PIN(59, "GP_CAMERASB09"),
+ PINCTRL_PIN(60, "GP_CAMERASB10"),
+ PINCTRL_PIN(61, "GP_CAMERASB11"),
+ PINCTRL_PIN(62, "TCK"),
+ PINCTRL_PIN(63, "TRST_B"),
+ PINCTRL_PIN(64, "TMS"),
+ PINCTRL_PIN(65, "TDI"),
+ PINCTRL_PIN(66, "CX_PMODE"),
+ PINCTRL_PIN(67, "CX_PREQ_B"),
+ PINCTRL_PIN(68, "JTAGX"),
+ PINCTRL_PIN(69, "CX_PRDY_B"),
+ PINCTRL_PIN(70, "TDO"),
+ PINCTRL_PIN(71, "CNV_BRI_DT"),
+ PINCTRL_PIN(72, "CNV_BRI_RSP"),
+ PINCTRL_PIN(73, "CNV_RGI_DT"),
+ PINCTRL_PIN(74, "CNV_RGI_RSP"),
+ PINCTRL_PIN(75, "SVID0_ALERT_B"),
+ PINCTRL_PIN(76, "SVID0_DATA"),
+ PINCTRL_PIN(77, "SVID0_CLK"),
+};
+
+static const unsigned apl_north_pwm0_pins[] = { 34 };
+static const unsigned apl_north_pwm1_pins[] = { 35 };
+static const unsigned apl_north_pwm2_pins[] = { 36 };
+static const unsigned apl_north_pwm3_pins[] = { 37 };
+static const unsigned apl_north_uart0_pins[] = { 38, 39, 40, 41 };
+static const unsigned apl_north_uart1_pins[] = { 42, 43, 44, 45 };
+static const unsigned apl_north_uart2_pins[] = { 46, 47, 48, 49 };
+
+static const struct intel_pingroup apl_north_groups[] = {
+ PIN_GROUP("pwm0_grp", apl_north_pwm0_pins, 1),
+ PIN_GROUP("pwm1_grp", apl_north_pwm1_pins, 1),
+ PIN_GROUP("pwm2_grp", apl_north_pwm2_pins, 1),
+ PIN_GROUP("pwm3_grp", apl_north_pwm3_pins, 1),
+ PIN_GROUP("uart0_grp", apl_north_uart0_pins, 1),
+ PIN_GROUP("uart1_grp", apl_north_uart1_pins, 1),
+ PIN_GROUP("uart2_grp", apl_north_uart2_pins, 1),
+};
+
+static const char * const apl_north_pwm0_groups[] = { "pwm0_grp" };
+static const char * const apl_north_pwm1_groups[] = { "pwm1_grp" };
+static const char * const apl_north_pwm2_groups[] = { "pwm2_grp" };
+static const char * const apl_north_pwm3_groups[] = { "pwm3_grp" };
+static const char * const apl_north_uart0_groups[] = { "uart0_grp" };
+static const char * const apl_north_uart1_groups[] = { "uart1_grp" };
+static const char * const apl_north_uart2_groups[] = { "uart2_grp" };
+
+static const struct intel_function apl_north_functions[] = {
+ FUNCTION("pwm0", apl_north_pwm0_groups),
+ FUNCTION("pwm1", apl_north_pwm1_groups),
+ FUNCTION("pwm2", apl_north_pwm2_groups),
+ FUNCTION("pwm3", apl_north_pwm3_groups),
+ FUNCTION("uart0", apl_north_uart0_groups),
+ FUNCTION("uart1", apl_north_uart1_groups),
+ FUNCTION("uart2", apl_north_uart2_groups),
+};
+
+static const struct intel_community apl_north_communities[] = {
+ BXT_COMMUNITY(0, 77),
+};
+
+static const struct intel_pinctrl_soc_data apl_north_soc_data = {
+ .uid = "1",
+ .pins = apl_north_pins,
+ .npins = ARRAY_SIZE(apl_north_pins),
+ .groups = apl_north_groups,
+ .ngroups = ARRAY_SIZE(apl_north_groups),
+ .functions = apl_north_functions,
+ .nfunctions = ARRAY_SIZE(apl_north_functions),
+ .communities = apl_north_communities,
+ .ncommunities = ARRAY_SIZE(apl_north_communities),
+};
+
+static const struct pinctrl_pin_desc apl_northwest_pins[] = {
+ PINCTRL_PIN(0, "HV_DDI0_DDC_SDA"),
+ PINCTRL_PIN(1, "HV_DDI0_DDC_SCL"),
+ PINCTRL_PIN(2, "HV_DDI1_DDC_SDA"),
+ PINCTRL_PIN(3, "HV_DDI1_DDC_SCL"),
+ PINCTRL_PIN(4, "DBI_SDA"),
+ PINCTRL_PIN(5, "DBI_SCL"),
+ PINCTRL_PIN(6, "PANEL0_VDDEN"),
+ PINCTRL_PIN(7, "PANEL0_BKLTEN"),
+ PINCTRL_PIN(8, "PANEL0_BKLTCTL"),
+ PINCTRL_PIN(9, "PANEL1_VDDEN"),
+ PINCTRL_PIN(10, "PANEL1_BKLTEN"),
+ PINCTRL_PIN(11, "PANEL1_BKLTCTL"),
+ PINCTRL_PIN(12, "DBI_CSX"),
+ PINCTRL_PIN(13, "DBI_RESX"),
+ PINCTRL_PIN(14, "GP_INTD_DSI_TE1"),
+ PINCTRL_PIN(15, "GP_INTD_DSI_TE2"),
+ PINCTRL_PIN(16, "USB_OC0_B"),
+ PINCTRL_PIN(17, "USB_OC1_B"),
+ PINCTRL_PIN(18, "PMC_SPI_FS0"),
+ PINCTRL_PIN(19, "PMC_SPI_FS1"),
+ PINCTRL_PIN(20, "PMC_SPI_FS2"),
+ PINCTRL_PIN(21, "PMC_SPI_RXD"),
+ PINCTRL_PIN(22, "PMC_SPI_TXD"),
+ PINCTRL_PIN(23, "PMC_SPI_CLK"),
+ PINCTRL_PIN(24, "PMIC_PWRGOOD"),
+ PINCTRL_PIN(25, "PMIC_RESET_B"),
+ PINCTRL_PIN(26, "PMIC_SDWN_B"),
+ PINCTRL_PIN(27, "PMIC_BCUDISW2"),
+ PINCTRL_PIN(28, "PMIC_BCUDISCRIT"),
+ PINCTRL_PIN(29, "PMIC_THERMTRIP_B"),
+ PINCTRL_PIN(30, "PMIC_STDBY"),
+ PINCTRL_PIN(31, "PROCHOT_B"),
+ PINCTRL_PIN(32, "PMIC_I2C_SCL"),
+ PINCTRL_PIN(33, "PMIC_I2C_SDA"),
+ PINCTRL_PIN(34, "AVS_I2S1_MCLK"),
+ PINCTRL_PIN(35, "AVS_I2S1_BCLK"),
+ PINCTRL_PIN(36, "AVS_I2S1_WS_SYNC"),
+ PINCTRL_PIN(37, "AVS_I2S1_SDI"),
+ PINCTRL_PIN(38, "AVS_I2S1_SDO"),
+ PINCTRL_PIN(39, "AVS_M_CLK_A1"),
+ PINCTRL_PIN(40, "AVS_M_CLK_B1"),
+ PINCTRL_PIN(41, "AVS_M_DATA_1"),
+ PINCTRL_PIN(42, "AVS_M_CLK_AB2"),
+ PINCTRL_PIN(43, "AVS_M_DATA_2"),
+ PINCTRL_PIN(44, "AVS_I2S2_MCLK"),
+ PINCTRL_PIN(45, "AVS_I2S2_BCLK"),
+ PINCTRL_PIN(46, "AVS_I2S2_WS_SYNC"),
+ PINCTRL_PIN(47, "AVS_I2S2_SDI"),
+ PINCTRL_PIN(48, "AVS_I2S2_SDO"),
+ PINCTRL_PIN(49, "AVS_I2S3_BCLK"),
+ PINCTRL_PIN(50, "AVS_I2S3_WS_SYNC"),
+ PINCTRL_PIN(51, "AVS_I2S3_SDI"),
+ PINCTRL_PIN(52, "AVS_I2S3_SDO"),
+ PINCTRL_PIN(53, "FST_SPI_CS0_B"),
+ PINCTRL_PIN(54, "FST_SPI_CS1_B"),
+ PINCTRL_PIN(55, "FST_SPI_MOSI_IO0"),
+ PINCTRL_PIN(56, "FST_SPI_MISO_IO1"),
+ PINCTRL_PIN(57, "FST_SPI_IO2"),
+ PINCTRL_PIN(58, "FST_SPI_IO3"),
+ PINCTRL_PIN(59, "FST_SPI_CLK"),
+ PINCTRL_PIN(60, "FST_SPI_CLK_FB"),
+ PINCTRL_PIN(61, "GP_SSP_0_CLK"),
+ PINCTRL_PIN(62, "GP_SSP_0_FS0"),
+ PINCTRL_PIN(63, "GP_SSP_0_FS1"),
+ PINCTRL_PIN(64, "GP_SSP_0_RXD"),
+ PINCTRL_PIN(65, "GP_SSP_0_TXD"),
+ PINCTRL_PIN(66, "GP_SSP_1_CLK"),
+ PINCTRL_PIN(67, "GP_SSP_1_FS0"),
+ PINCTRL_PIN(68, "GP_SSP_1_FS1"),
+ PINCTRL_PIN(69, "GP_SSP_1_RXD"),
+ PINCTRL_PIN(70, "GP_SSP_1_TXD"),
+ PINCTRL_PIN(71, "GP_SSP_2_CLK"),
+ PINCTRL_PIN(72, "GP_SSP_2_FS0"),
+ PINCTRL_PIN(73, "GP_SSP_2_FS1"),
+ PINCTRL_PIN(74, "GP_SSP_2_FS2"),
+ PINCTRL_PIN(75, "GP_SSP_2_RXD"),
+ PINCTRL_PIN(76, "GP_SSP_2_TXD"),
+};
+
+static const unsigned apl_northwest_ssp0_pins[] = { 61, 62, 63, 64, 65 };
+static const unsigned apl_northwest_ssp1_pins[] = { 66, 67, 68, 69, 70 };
+static const unsigned apl_northwest_ssp2_pins[] = { 71, 72, 73, 74, 75, 76 };
+static const unsigned apl_northwest_uart3_pins[] = { 67, 68, 69, 70 };
+
+static const struct intel_pingroup apl_northwest_groups[] = {
+ PIN_GROUP("ssp0_grp", apl_northwest_ssp0_pins, 1),
+ PIN_GROUP("ssp1_grp", apl_northwest_ssp1_pins, 1),
+ PIN_GROUP("ssp2_grp", apl_northwest_ssp2_pins, 1),
+ PIN_GROUP("uart3_grp", apl_northwest_uart3_pins, 2),
+};
+
+static const char * const apl_northwest_ssp0_groups[] = { "ssp0_grp" };
+static const char * const apl_northwest_ssp1_groups[] = { "ssp1_grp" };
+static const char * const apl_northwest_ssp2_groups[] = { "ssp2_grp" };
+static const char * const apl_northwest_uart3_groups[] = { "uart3_grp" };
+
+static const struct intel_function apl_northwest_functions[] = {
+ FUNCTION("ssp0", apl_northwest_ssp0_groups),
+ FUNCTION("ssp1", apl_northwest_ssp1_groups),
+ FUNCTION("ssp2", apl_northwest_ssp2_groups),
+ FUNCTION("uart3", apl_northwest_uart3_groups),
+};
+
+static const struct intel_community apl_northwest_communities[] = {
+ BXT_COMMUNITY(0, 76),
+};
+
+static const struct intel_pinctrl_soc_data apl_northwest_soc_data = {
+ .uid = "2",
+ .pins = apl_northwest_pins,
+ .npins = ARRAY_SIZE(apl_northwest_pins),
+ .groups = apl_northwest_groups,
+ .ngroups = ARRAY_SIZE(apl_northwest_groups),
+ .functions = apl_northwest_functions,
+ .nfunctions = ARRAY_SIZE(apl_northwest_functions),
+ .communities = apl_northwest_communities,
+ .ncommunities = ARRAY_SIZE(apl_northwest_communities),
+};
+
+static const struct pinctrl_pin_desc apl_west_pins[] = {
+ PINCTRL_PIN(0, "LPSS_I2C0_SDA"),
+ PINCTRL_PIN(1, "LPSS_I2C0_SCL"),
+ PINCTRL_PIN(2, "LPSS_I2C1_SDA"),
+ PINCTRL_PIN(3, "LPSS_I2C1_SCL"),
+ PINCTRL_PIN(4, "LPSS_I2C2_SDA"),
+ PINCTRL_PIN(5, "LPSS_I2C2_SCL"),
+ PINCTRL_PIN(6, "LPSS_I2C3_SDA"),
+ PINCTRL_PIN(7, "LPSS_I2C3_SCL"),
+ PINCTRL_PIN(8, "LPSS_I2C4_SDA"),
+ PINCTRL_PIN(9, "LPSS_I2C4_SCL"),
+ PINCTRL_PIN(10, "LPSS_I2C5_SDA"),
+ PINCTRL_PIN(11, "LPSS_I2C5_SCL"),
+ PINCTRL_PIN(12, "LPSS_I2C6_SDA"),
+ PINCTRL_PIN(13, "LPSS_I2C6_SCL"),
+ PINCTRL_PIN(14, "LPSS_I2C7_SDA"),
+ PINCTRL_PIN(15, "LPSS_I2C7_SCL"),
+ PINCTRL_PIN(16, "ISH_GPIO_0"),
+ PINCTRL_PIN(17, "ISH_GPIO_1"),
+ PINCTRL_PIN(18, "ISH_GPIO_2"),
+ PINCTRL_PIN(19, "ISH_GPIO_3"),
+ PINCTRL_PIN(20, "ISH_GPIO_4"),
+ PINCTRL_PIN(21, "ISH_GPIO_5"),
+ PINCTRL_PIN(22, "ISH_GPIO_6"),
+ PINCTRL_PIN(23, "ISH_GPIO_7"),
+ PINCTRL_PIN(24, "ISH_GPIO_8"),
+ PINCTRL_PIN(25, "ISH_GPIO_9"),
+ PINCTRL_PIN(26, "PCIE_CLKREQ0_B"),
+ PINCTRL_PIN(27, "PCIE_CLKREQ1_B"),
+ PINCTRL_PIN(28, "PCIE_CLKREQ2_B"),
+ PINCTRL_PIN(29, "PCIE_CLKREQ3_B"),
+ PINCTRL_PIN(30, "OSC_CLK_OUT_0"),
+ PINCTRL_PIN(31, "OSC_CLK_OUT_1"),
+ PINCTRL_PIN(32, "OSC_CLK_OUT_2"),
+ PINCTRL_PIN(33, "OSC_CLK_OUT_3"),
+ PINCTRL_PIN(34, "OSC_CLK_OUT_4"),
+ PINCTRL_PIN(35, "PMU_AC_PRESENT"),
+ PINCTRL_PIN(36, "PMU_BATLOW_B"),
+ PINCTRL_PIN(37, "PMU_PLTRST_B"),
+ PINCTRL_PIN(38, "PMU_PWRBTN_B"),
+ PINCTRL_PIN(39, "PMU_RESETBUTTON_B"),
+ PINCTRL_PIN(40, "PMU_SLP_S0_B"),
+ PINCTRL_PIN(41, "PMU_SLP_S3_B"),
+ PINCTRL_PIN(42, "PMU_SLP_S4_B"),
+ PINCTRL_PIN(43, "PMU_SUSCLK"),
+ PINCTRL_PIN(44, "PMU_WAKE_B"),
+ PINCTRL_PIN(45, "SUS_STAT_B"),
+ PINCTRL_PIN(46, "SUSPWRDNACK"),
+};
+
+static const unsigned apl_west_i2c0_pins[] = { 0, 1 };
+static const unsigned apl_west_i2c1_pins[] = { 2, 3 };
+static const unsigned apl_west_i2c2_pins[] = { 4, 5 };
+static const unsigned apl_west_i2c3_pins[] = { 6, 7 };
+static const unsigned apl_west_i2c4_pins[] = { 8, 9 };
+static const unsigned apl_west_i2c5_pins[] = { 10, 11 };
+static const unsigned apl_west_i2c6_pins[] = { 12, 13 };
+static const unsigned apl_west_i2c7_pins[] = { 14, 15 };
+static const unsigned apl_west_uart2_pins[] = { 20, 21, 22, 34 };
+
+static const struct intel_pingroup apl_west_groups[] = {
+ PIN_GROUP("i2c0_grp", apl_west_i2c0_pins, 1),
+ PIN_GROUP("i2c1_grp", apl_west_i2c1_pins, 1),
+ PIN_GROUP("i2c2_grp", apl_west_i2c2_pins, 1),
+ PIN_GROUP("i2c3_grp", apl_west_i2c3_pins, 1),
+ PIN_GROUP("i2c4_grp", apl_west_i2c4_pins, 1),
+ PIN_GROUP("i2c5_grp", apl_west_i2c5_pins, 1),
+ PIN_GROUP("i2c6_grp", apl_west_i2c6_pins, 1),
+ PIN_GROUP("i2c7_grp", apl_west_i2c7_pins, 1),
+ PIN_GROUP("uart2_grp", apl_west_uart2_pins, 3),
+};
+
+static const char * const apl_west_i2c0_groups[] = { "i2c0_grp" };
+static const char * const apl_west_i2c1_groups[] = { "i2c1_grp" };
+static const char * const apl_west_i2c2_groups[] = { "i2c2_grp" };
+static const char * const apl_west_i2c3_groups[] = { "i2c3_grp" };
+static const char * const apl_west_i2c4_groups[] = { "i2c4_grp" };
+static const char * const apl_west_i2c5_groups[] = { "i2c5_grp" };
+static const char * const apl_west_i2c6_groups[] = { "i2c6_grp" };
+static const char * const apl_west_i2c7_groups[] = { "i2c7_grp" };
+static const char * const apl_west_uart2_groups[] = { "uart2_grp" };
+
+static const struct intel_function apl_west_functions[] = {
+ FUNCTION("i2c0", apl_west_i2c0_groups),
+ FUNCTION("i2c1", apl_west_i2c1_groups),
+ FUNCTION("i2c2", apl_west_i2c2_groups),
+ FUNCTION("i2c3", apl_west_i2c3_groups),
+ FUNCTION("i2c4", apl_west_i2c4_groups),
+ FUNCTION("i2c5", apl_west_i2c5_groups),
+ FUNCTION("i2c6", apl_west_i2c6_groups),
+ FUNCTION("i2c7", apl_west_i2c7_groups),
+ FUNCTION("uart2", apl_west_uart2_groups),
+};
+
+static const struct intel_community apl_west_communities[] = {
+ BXT_COMMUNITY(0, 46),
+};
+
+static const struct intel_pinctrl_soc_data apl_west_soc_data = {
+ .uid = "3",
+ .pins = apl_west_pins,
+ .npins = ARRAY_SIZE(apl_west_pins),
+ .groups = apl_west_groups,
+ .ngroups = ARRAY_SIZE(apl_west_groups),
+ .functions = apl_west_functions,
+ .nfunctions = ARRAY_SIZE(apl_west_functions),
+ .communities = apl_west_communities,
+ .ncommunities = ARRAY_SIZE(apl_west_communities),
+};
+
+static const struct pinctrl_pin_desc apl_southwest_pins[] = {
+ PINCTRL_PIN(0, "PCIE_WAKE0_B"),
+ PINCTRL_PIN(1, "PCIE_WAKE1_B"),
+ PINCTRL_PIN(2, "PCIE_WAKE2_B"),
+ PINCTRL_PIN(3, "PCIE_WAKE3_B"),
+ PINCTRL_PIN(4, "EMMC0_CLK"),
+ PINCTRL_PIN(5, "EMMC0_D0"),
+ PINCTRL_PIN(6, "EMMC0_D1"),
+ PINCTRL_PIN(7, "EMMC0_D2"),
+ PINCTRL_PIN(8, "EMMC0_D3"),
+ PINCTRL_PIN(9, "EMMC0_D4"),
+ PINCTRL_PIN(10, "EMMC0_D5"),
+ PINCTRL_PIN(11, "EMMC0_D6"),
+ PINCTRL_PIN(12, "EMMC0_D7"),
+ PINCTRL_PIN(13, "EMMC0_CMD"),
+ PINCTRL_PIN(14, "SDIO_CLK"),
+ PINCTRL_PIN(15, "SDIO_D0"),
+ PINCTRL_PIN(16, "SDIO_D1"),
+ PINCTRL_PIN(17, "SDIO_D2"),
+ PINCTRL_PIN(18, "SDIO_D3"),
+ PINCTRL_PIN(19, "SDIO_CMD"),
+ PINCTRL_PIN(20, "SDCARD_CLK"),
+ PINCTRL_PIN(21, "SDCARD_CLK_FB"),
+ PINCTRL_PIN(22, "SDCARD_D0"),
+ PINCTRL_PIN(23, "SDCARD_D1"),
+ PINCTRL_PIN(24, "SDCARD_D2"),
+ PINCTRL_PIN(25, "SDCARD_D3"),
+ PINCTRL_PIN(26, "SDCARD_CD_B"),
+ PINCTRL_PIN(27, "SDCARD_CMD"),
+ PINCTRL_PIN(28, "SDCARD_LVL_WP"),
+ PINCTRL_PIN(29, "EMMC0_STROBE"),
+ PINCTRL_PIN(30, "SDIO_PWR_DOWN_B"),
+ PINCTRL_PIN(31, "SMB_ALERTB"),
+ PINCTRL_PIN(32, "SMB_CLK"),
+ PINCTRL_PIN(33, "SMB_DATA"),
+ PINCTRL_PIN(34, "LPC_ILB_SERIRQ"),
+ PINCTRL_PIN(35, "LPC_CLKOUT0"),
+ PINCTRL_PIN(36, "LPC_CLKOUT1"),
+ PINCTRL_PIN(37, "LPC_AD0"),
+ PINCTRL_PIN(38, "LPC_AD1"),
+ PINCTRL_PIN(39, "LPC_AD2"),
+ PINCTRL_PIN(40, "LPC_AD3"),
+ PINCTRL_PIN(41, "LPC_CLKRUNB"),
+ PINCTRL_PIN(42, "LPC_FRAMEB"),
+};
+
+static const unsigned apl_southwest_emmc0_pins[] = {
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 29,
+};
+static const unsigned apl_southwest_sdio_pins[] = {
+ 14, 15, 16, 17, 18, 19, 30,
+};
+static const unsigned apl_southwest_sdcard_pins[] = {
+ 20, 21, 22, 23, 24, 25, 26, 27, 28,
+};
+static const unsigned apl_southwest_i2c7_pins[] = { 32, 33 };
+
+static const struct intel_pingroup apl_southwest_groups[] = {
+ PIN_GROUP("emmc0_grp", apl_southwest_emmc0_pins, 1),
+ PIN_GROUP("sdio_grp", apl_southwest_sdio_pins, 1),
+ PIN_GROUP("sdcard_grp", apl_southwest_sdcard_pins, 1),
+ PIN_GROUP("i2c7_grp", apl_southwest_i2c7_pins, 2),
+};
+
+static const char * const apl_southwest_emmc0_groups[] = { "emmc0_grp" };
+static const char * const apl_southwest_sdio_groups[] = { "sdio_grp" };
+static const char * const apl_southwest_sdcard_groups[] = { "sdcard_grp" };
+static const char * const apl_southwest_i2c7_groups[] = { "i2c7_grp" };
+
+static const struct intel_function apl_southwest_functions[] = {
+ FUNCTION("emmc0", apl_southwest_emmc0_groups),
+ FUNCTION("sdio", apl_southwest_sdio_groups),
+ FUNCTION("sdcard", apl_southwest_sdcard_groups),
+ FUNCTION("i2c7", apl_southwest_i2c7_groups),
+};
+
+static const struct intel_community apl_southwest_communities[] = {
+ BXT_COMMUNITY(0, 42),
+};
+
+static const struct intel_pinctrl_soc_data apl_southwest_soc_data = {
+ .uid = "4",
+ .pins = apl_southwest_pins,
+ .npins = ARRAY_SIZE(apl_southwest_pins),
+ .groups = apl_southwest_groups,
+ .ngroups = ARRAY_SIZE(apl_southwest_groups),
+ .functions = apl_southwest_functions,
+ .nfunctions = ARRAY_SIZE(apl_southwest_functions),
+ .communities = apl_southwest_communities,
+ .ncommunities = ARRAY_SIZE(apl_southwest_communities),
+};
+
+static const struct intel_pinctrl_soc_data *apl_pinctrl_soc_data[] = {
+ &apl_north_soc_data,
+ &apl_northwest_soc_data,
+ &apl_west_soc_data,
+ &apl_southwest_soc_data,
+ NULL,
+};
+
+static const struct acpi_device_id bxt_pinctrl_acpi_match[] = {
+ { "INT3452", (kernel_ulong_t)apl_pinctrl_soc_data },
+ { "INT34D1", (kernel_ulong_t)bxt_pinctrl_soc_data },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, bxt_pinctrl_acpi_match);
+
+static int bxt_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct intel_pinctrl_soc_data *soc_data = NULL;
+ const struct intel_pinctrl_soc_data **soc_table;
+ const struct acpi_device_id *id;
+ struct acpi_device *adev;
+ int i;
+
+ adev = ACPI_COMPANION(&pdev->dev);
+ if (!adev)
+ return -ENODEV;
+
+ id = acpi_match_device(bxt_pinctrl_acpi_match, &pdev->dev);
+ if (!id)
+ return -ENODEV;
+
+ soc_table = (const struct intel_pinctrl_soc_data **)id->driver_data;
+
+ for (i = 0; soc_table[i]; i++) {
+ if (!strcmp(adev->pnp.unique_id, soc_table[i]->uid)) {
+ soc_data = soc_table[i];
+ break;
+ }
+ }
+
+ if (!soc_data)
+ return -ENODEV;
+
+ return intel_pinctrl_probe(pdev, soc_data);
+}
+
+static const struct dev_pm_ops bxt_pinctrl_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
+ intel_pinctrl_resume)
+};
+
+static struct platform_driver bxt_pinctrl_driver = {
+ .probe = bxt_pinctrl_probe,
+ .remove = intel_pinctrl_remove,
+ .driver = {
+ .name = "broxton-pinctrl",
+ .acpi_match_table = bxt_pinctrl_acpi_match,
+ .pm = &bxt_pinctrl_pm_ops,
+ },
+};
+
+static int __init bxt_pinctrl_init(void)
+{
+ return platform_driver_register(&bxt_pinctrl_driver);
+}
+subsys_initcall(bxt_pinctrl_init);
+
+static void __exit bxt_pinctrl_exit(void)
+{
+ platform_driver_unregister(&bxt_pinctrl_driver);
+}
+module_exit(bxt_pinctrl_exit);
+
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Broxton SoC pinctrl/GPIO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 270c127e03ea..84936bae6e5e 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1149,16 +1149,6 @@ static struct pinctrl_desc chv_pinctrl_desc = {
.owner = THIS_MODULE,
};
-static int chv_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void chv_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static unsigned chv_gpio_offset_to_pin(struct chv_pinctrl *pctrl,
unsigned offset)
{
@@ -1238,8 +1228,8 @@ static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static const struct gpio_chip chv_gpio_chip = {
.owner = THIS_MODULE,
- .request = chv_gpio_request,
- .free = chv_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.get_direction = chv_gpio_get_direction,
.direction_input = chv_gpio_direction_input,
.direction_output = chv_gpio_direction_output,
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 54848b8decef..392e28d3f48d 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/acpi.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
@@ -159,8 +160,7 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
return !(readl(padown) & PADOWN_MASK(padno));
}
-static bool intel_pad_reserved_for_acpi(struct intel_pinctrl *pctrl,
- unsigned pin)
+static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
{
const struct intel_community *community;
unsigned padno, gpp, offset;
@@ -216,7 +216,6 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned pin)
{
return intel_pad_owned_by_host(pctrl, pin) &&
- !intel_pad_reserved_for_acpi(pctrl, pin) &&
!intel_pad_locked(pctrl, pin);
}
@@ -269,7 +268,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1);
locked = intel_pad_locked(pctrl, pin);
- acpi = intel_pad_reserved_for_acpi(pctrl, pin);
+ acpi = intel_pad_acpi_mode(pctrl, pin);
if (locked || acpi) {
seq_puts(s, " [");
@@ -597,16 +596,6 @@ static const struct pinctrl_desc intel_pinctrl_desc = {
.owner = THIS_MODULE,
};
-static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void intel_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
@@ -654,8 +643,8 @@ static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static const struct gpio_chip intel_gpio_chip = {
.owner = THIS_MODULE,
- .request = intel_gpio_request,
- .free = intel_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.direction_input = intel_gpio_direction_input,
.direction_output = intel_gpio_direction_output,
.get = intel_gpio_get,
@@ -736,6 +725,16 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
if (!reg)
return -EINVAL;
+ /*
+ * If the pin is in ACPI mode it is still usable as a GPIO but it
+ * cannot be used as IRQ because GPI_IS status bit will not be
+ * updated by the host controller hardware.
+ */
+ if (intel_pad_acpi_mode(pctrl, pin)) {
+ dev_warn(pctrl->dev, "pin %u cannot be used as IRQ\n", pin);
+ return -EPERM;
+ }
+
spin_lock_irqsave(&pctrl->lock, flags);
value = readl(reg);
@@ -803,9 +802,11 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
return 0;
}
-static void intel_gpio_community_irq_handler(struct gpio_chip *gc,
+static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
const struct intel_community *community)
{
+ struct gpio_chip *gc = &pctrl->chip;
+ irqreturn_t ret = IRQ_NONE;
int gpp;
for (gpp = 0; gpp < community->ngpps; gpp++) {
@@ -832,24 +833,28 @@ static void intel_gpio_community_irq_handler(struct gpio_chip *gc,
irq = irq_find_mapping(gc->irqdomain,
community->pin_base + padno);
generic_handle_irq(irq);
+
+ ret |= IRQ_HANDLED;
}
}
+
+ return ret;
}
-static void intel_gpio_irq_handler(struct irq_desc *desc)
+static irqreturn_t intel_gpio_irq(int irq, void *data)
{
- struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
+ const struct intel_community *community;
+ struct intel_pinctrl *pctrl = data;
+ irqreturn_t ret = IRQ_NONE;
int i;
- chained_irq_enter(chip, desc);
-
/* Need to check all communities for pending interrupts */
- for (i = 0; i < pctrl->ncommunities; i++)
- intel_gpio_community_irq_handler(gc, &pctrl->communities[i]);
+ for (i = 0; i < pctrl->ncommunities; i++) {
+ community = &pctrl->communities[i];
+ ret |= intel_gpio_community_irq_handler(pctrl, community);
+ }
- chained_irq_exit(chip, desc);
+ return ret;
}
static struct irq_chip intel_gpio_irqchip = {
@@ -861,26 +866,6 @@ static struct irq_chip intel_gpio_irqchip = {
.irq_set_wake = intel_gpio_irq_wake,
};
-static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
-{
- size_t i;
-
- for (i = 0; i < pctrl->ncommunities; i++) {
- const struct intel_community *community;
- void __iomem *base;
- unsigned gpp;
-
- community = &pctrl->communities[i];
- base = community->regs;
-
- for (gpp = 0; gpp < community->ngpps; gpp++) {
- /* Mask and clear all interrupts */
- writel(0, base + community->ie_offset + gpp * 4);
- writel(0xffff, base + GPI_IS + gpp * 4);
- }
- }
-}
-
static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
{
int ret;
@@ -902,21 +887,36 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
0, 0, pctrl->soc->npins);
if (ret) {
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
- gpiochip_remove(&pctrl->chip);
- return ret;
+ goto fail;
+ }
+
+ /*
+ * We need to request the interrupt here (instead of providing chip
+ * to the irq directly) because on some platforms several GPIO
+ * controllers share the same interrupt line.
+ */
+ ret = devm_request_irq(pctrl->dev, irq, intel_gpio_irq, IRQF_SHARED,
+ dev_name(pctrl->dev), pctrl);
+ if (ret) {
+ dev_err(pctrl->dev, "failed to request interrupt\n");
+ goto fail;
}
ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "failed to add irqchip\n");
- gpiochip_remove(&pctrl->chip);
- return ret;
+ goto fail;
}
gpiochip_set_chained_irqchip(&pctrl->chip, &intel_gpio_irqchip, irq,
- intel_gpio_irq_handler);
+ NULL);
return 0;
+
+fail:
+ gpiochip_remove(&pctrl->chip);
+
+ return ret;
}
static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl)
@@ -1087,6 +1087,26 @@ int intel_pinctrl_suspend(struct device *dev)
}
EXPORT_SYMBOL_GPL(intel_pinctrl_suspend);
+static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
+{
+ size_t i;
+
+ for (i = 0; i < pctrl->ncommunities; i++) {
+ const struct intel_community *community;
+ void __iomem *base;
+ unsigned gpp;
+
+ community = &pctrl->communities[i];
+ base = community->regs;
+
+ for (gpp = 0; gpp < community->ngpps; gpp++) {
+ /* Mask and clear all interrupts */
+ writel(0, base + community->ie_offset + gpp * 4);
+ writel(0xffff, base + GPI_IS + gpp * 4);
+ }
+ }
+}
+
int intel_pinctrl_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 1b22f96ba839..f307f1d27d64 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -723,16 +723,6 @@ static const struct pinmux_ops mtk_pmx_ops = {
.gpio_set_direction = mtk_pmx_gpio_set_direction,
};
-static int mtk_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void mtk_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int mtk_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@@ -899,7 +889,7 @@ static int mtk_eint_flip_edge(struct mtk_pinctrl *pctl, int hwirq)
int start_level, curr_level;
unsigned int reg_offset;
const struct mtk_eint_offsets *eint_offsets = &(pctl->devdata->eint_offsets);
- u32 mask = 1 << (hwirq & 0x1f);
+ u32 mask = BIT(hwirq & 0x1f);
u32 port = (hwirq >> 5) & eint_offsets->port_mask;
void __iomem *reg = pctl->eint_reg_base + (port << 2);
const struct mtk_desc_pin *pin;
@@ -1005,8 +995,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip mtk_gpio_chip = {
.owner = THIS_MODULE,
- .request = mtk_gpio_request,
- .free = mtk_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.direction_input = mtk_gpio_direction_input,
.direction_output = mtk_gpio_direction_output,
.get = mtk_gpio_get,
@@ -1436,7 +1426,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip,
handle_level_irq);
irq_set_chip_data(virq, pctl);
- };
+ }
irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl);
return 0;
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index 97681fac082e..b59fbb4b1fb1 100644
--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -654,25 +654,11 @@ static inline void abx500_gpio_dbg_show_one(struct seq_file *s,
#define abx500_gpio_dbg_show NULL
#endif
-static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- return pinctrl_request_gpio(gpio);
-}
-
-static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- pinctrl_free_gpio(gpio);
-}
-
static struct gpio_chip abx500gpio_chip = {
.label = "abx500-gpio",
.owner = THIS_MODULE,
- .request = abx500_gpio_request,
- .free = abx500_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.direction_input = abx500_gpio_direction_input,
.get = abx500_gpio_get,
.direction_output = abx500_gpio_direction_output,
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index 96cf03908e93..eebfae0c9b7c 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -884,24 +884,6 @@ static void nmk_gpio_latent_irq_handler(struct irq_desc *desc)
/* I/O Functions */
-static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- /*
- * Map back to global GPIO space and request muxing, the direction
- * parameter does not matter for this controller.
- */
- int gpio = chip->base + offset;
-
- return pinctrl_request_gpio(gpio);
-}
-
-static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- pinctrl_free_gpio(gpio);
-}
-
static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
{
struct nmk_gpio_chip *nmk_chip =
@@ -1267,8 +1249,8 @@ static int nmk_gpio_probe(struct platform_device *dev)
spin_lock_init(&nmk_chip->lock);
chip = &nmk_chip->chip;
- chip->request = nmk_gpio_request;
- chip->free = nmk_gpio_free;
+ chip->request = gpiochip_generic_request;
+ chip->free = gpiochip_generic_free;
chip->direction_input = nmk_gpio_make_input;
chip->get = nmk_gpio_get_input;
chip->direction_output = nmk_gpio_make_output;
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index e63ad9fbd388..099a3442ff42 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -28,25 +28,25 @@
#ifdef CONFIG_DEBUG_FS
static const struct pin_config_item conf_items[] = {
+ PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL, false),
PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL, false),
PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL, false),
- PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL, false),
- PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL, false),
PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
"input bias pull to pin specific state", NULL, false),
- PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
+ PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
+ PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA", true),
+ PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec", true),
PCONFDUMP(PIN_CONFIG_INPUT_ENABLE, "input enabled", NULL, false),
- PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL, false),
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL, false),
- PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec", true),
- PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector", true),
- PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true),
+ PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL, false),
PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode", true),
PCONFDUMP(PIN_CONFIG_OUTPUT, "pin output", "level", true),
+ PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector", true),
+ PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true),
};
static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev,
@@ -150,27 +150,28 @@ EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
#ifdef CONFIG_OF
static const struct pinconf_generic_params dt_params[] = {
+ { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
- { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
- { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
- { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
+ { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
- { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+ { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
- { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+ { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+ { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
- { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
- { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
- { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
+ { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
- { "output-low", PIN_CONFIG_OUTPUT, 0, },
+ { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
{ "output-high", PIN_CONFIG_OUTPUT, 1, },
- { "slew-rate", PIN_CONFIG_SLEW_RATE, 0},
+ { "output-low", PIN_CONFIG_OUTPUT, 0, },
+ { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
+ { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
};
/**
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 29a7bb17a42f..4dd7722f9935 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -411,7 +411,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
const struct pinctrl_map *found = NULL;
struct pinctrl_dev *pctldev;
struct dbg_cfg *dbg = &pinconf_dbg_conf;
- int i, j;
+ int i;
mutex_lock(&pinctrl_maps_mutex);
@@ -424,13 +424,10 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
if (strcmp(map->name, dbg->state_name))
continue;
- for (j = 0; j < map->data.configs.num_configs; j++) {
- if (!strcmp(map->data.configs.group_or_pin,
- dbg->pin_name)) {
- /* We found the right pin / state */
- found = map;
- break;
- }
+ if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
+ /* We found the right pin */
+ found = map;
+ break;
}
}
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index f6be68518c87..fd342dffe4dc 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -713,16 +713,6 @@ static struct pinctrl_desc adi_pinmux_desc = {
.owner = THIS_MODULE,
};
-static int adi_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void adi_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct gpio_port *port;
@@ -994,8 +984,8 @@ static int adi_gpio_probe(struct platform_device *pdev)
port->chip.get = adi_gpio_get_value;
port->chip.direction_output = adi_gpio_direction_output;
port->chip.set = adi_gpio_set_value;
- port->chip.request = adi_gpio_request;
- port->chip.free = adi_gpio_free;
+ port->chip.request = gpiochip_generic_request,
+ port->chip.free = gpiochip_generic_free,
port->chip.to_irq = adi_gpio_to_irq;
if (pdata->port_gpio_base > 0)
port->chip.base = pdata->port_gpio_base;
diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c
index 4747e08f5389..56af28b95a44 100644
--- a/drivers/pinctrl/pinctrl-as3722.c
+++ b/drivers/pinctrl/pinctrl-as3722.c
@@ -536,21 +536,11 @@ static int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return as3722_irq_get_virq(as_pci->as3722, offset);
}
-static int as3722_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void as3722_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static const struct gpio_chip as3722_gpio_chip = {
.label = "as3722-gpio",
.owner = THIS_MODULE,
- .request = as3722_gpio_request,
- .free = as3722_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.get = as3722_gpio_get,
.set = as3722_gpio_set,
.direction_input = as3722_gpio_direction_input,
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
new file mode 100644
index 000000000000..33edd07d9149
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -0,0 +1,1094 @@
+/*
+ * Driver for the Atmel PIO4 controller
+ *
+ * Copyright (C) 2015 Atmel,
+ * 2015 Ludovic Desroches <ludovic.desroches@atmel.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 <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/slab.h>
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+/*
+ * Warning:
+ * In order to not introduce confusion between Atmel PIO groups and pinctrl
+ * framework groups, Atmel PIO groups will be called banks, line is kept to
+ * designed the pin id into this bank.
+ */
+
+#define ATMEL_PIO_MSKR 0x0000
+#define ATMEL_PIO_CFGR 0x0004
+#define ATMEL_PIO_CFGR_FUNC_MASK GENMASK(2, 0)
+#define ATMEL_PIO_DIR_MASK BIT(8)
+#define ATMEL_PIO_PUEN_MASK BIT(9)
+#define ATMEL_PIO_PDEN_MASK BIT(10)
+#define ATMEL_PIO_IFEN_MASK BIT(12)
+#define ATMEL_PIO_IFSCEN_MASK BIT(13)
+#define ATMEL_PIO_OPD_MASK BIT(14)
+#define ATMEL_PIO_SCHMITT_MASK BIT(15)
+#define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24)
+#define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_BOTH (2 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_LOW (3 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_HIGH (4 << 24)
+#define ATMEL_PIO_PDSR 0x0008
+#define ATMEL_PIO_LOCKSR 0x000C
+#define ATMEL_PIO_SODR 0x0010
+#define ATMEL_PIO_CODR 0x0014
+#define ATMEL_PIO_ODSR 0x0018
+#define ATMEL_PIO_IER 0x0020
+#define ATMEL_PIO_IDR 0x0024
+#define ATMEL_PIO_IMR 0x0028
+#define ATMEL_PIO_ISR 0x002C
+#define ATMEL_PIO_IOFR 0x003C
+
+#define ATMEL_PIO_NPINS_PER_BANK 32
+#define ATMEL_PIO_BANK(pin_id) (pin_id / ATMEL_PIO_NPINS_PER_BANK)
+#define ATMEL_PIO_LINE(pin_id) (pin_id % ATMEL_PIO_NPINS_PER_BANK)
+#define ATMEL_PIO_BANK_OFFSET 0x40
+
+#define ATMEL_GET_PIN_NO(pinfunc) ((pinfunc) & 0xff)
+#define ATMEL_GET_PIN_FUNC(pinfunc) ((pinfunc >> 16) & 0xf)
+#define ATMEL_GET_PIN_IOSET(pinfunc) ((pinfunc >> 20) & 0xf)
+
+struct atmel_pioctrl_data {
+ unsigned nbanks;
+};
+
+struct atmel_group {
+ const char *name;
+ u32 pin;
+};
+
+struct atmel_pin {
+ unsigned pin_id;
+ unsigned mux;
+ unsigned ioset;
+ unsigned bank;
+ unsigned line;
+ const char *device;
+};
+
+/**
+ * struct atmel_pioctrl - Atmel PIO controller (pinmux + gpio)
+ * @reg_base: base address of the controller.
+ * @clk: clock of the controller.
+ * @nbanks: number of PIO groups, it can vary depending on the SoC.
+ * @pinctrl_dev: pinctrl device registered.
+ * @groups: groups table to provide group name and pin in the group to pinctrl.
+ * @group_names: group names table to provide all the group/pin names to
+ * pinctrl or gpio.
+ * @pins: pins table used for both pinctrl and gpio. pin_id, bank and line
+ * fields are set at probe time. Other ones are set when parsing dt
+ * pinctrl.
+ * @npins: number of pins.
+ * @gpio_chip: gpio chip registered.
+ * @irq_domain: irq domain for the gpio controller.
+ * @irqs: table containing the hw irq number of the bank. The index of the
+ * table is the bank id.
+ * @dev: device entry for the Atmel PIO controller.
+ * @node: node of the Atmel PIO controller.
+ */
+struct atmel_pioctrl {
+ void __iomem *reg_base;
+ struct clk *clk;
+ unsigned nbanks;
+ struct pinctrl_dev *pinctrl_dev;
+ struct atmel_group *groups;
+ const char * const *group_names;
+ struct atmel_pin **pins;
+ unsigned npins;
+ struct gpio_chip *gpio_chip;
+ struct irq_domain *irq_domain;
+ int *irqs;
+ unsigned *pm_wakeup_sources;
+ unsigned *pm_suspend_backup;
+ struct device *dev;
+ struct device_node *node;
+};
+
+static const char * const atmel_functions[] = {
+ "GPIO", "A", "B", "C", "D", "E", "F", "G"
+};
+
+/* --- GPIO --- */
+static unsigned int atmel_gpio_read(struct atmel_pioctrl *atmel_pioctrl,
+ unsigned int bank, unsigned int reg)
+{
+ return readl_relaxed(atmel_pioctrl->reg_base
+ + ATMEL_PIO_BANK_OFFSET * bank + reg);
+}
+
+static void atmel_gpio_write(struct atmel_pioctrl *atmel_pioctrl,
+ unsigned int bank, unsigned int reg,
+ unsigned int val)
+{
+ writel_relaxed(val, atmel_pioctrl->reg_base
+ + ATMEL_PIO_BANK_OFFSET * bank + reg);
+}
+
+static void atmel_gpio_irq_ack(struct irq_data *d)
+{
+ /*
+ * Nothing to do, interrupt is cleared when reading the status
+ * register.
+ */
+}
+
+static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned type)
+{
+ struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
+ struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
+ unsigned reg;
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
+ BIT(pin->line));
+ reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR);
+ reg &= (~ATMEL_PIO_CFGR_EVTSEL_MASK);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ irq_set_handler_locked(d, handle_edge_irq);
+ reg |= ATMEL_PIO_CFGR_EVTSEL_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ irq_set_handler_locked(d, handle_edge_irq);
+ reg |= ATMEL_PIO_CFGR_EVTSEL_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ irq_set_handler_locked(d, handle_edge_irq);
+ reg |= ATMEL_PIO_CFGR_EVTSEL_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ irq_set_handler_locked(d, handle_level_irq);
+ reg |= ATMEL_PIO_CFGR_EVTSEL_LOW;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ irq_set_handler_locked(d, handle_level_irq);
+ reg |= ATMEL_PIO_CFGR_EVTSEL_HIGH;
+ break;
+ case IRQ_TYPE_NONE:
+ default:
+ return -EINVAL;
+ }
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg);
+
+ return 0;
+}
+
+static void atmel_gpio_irq_mask(struct irq_data *d)
+{
+ struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
+ struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_IDR,
+ BIT(pin->line));
+}
+
+static void atmel_gpio_irq_unmask(struct irq_data *d)
+{
+ struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
+ struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_IER,
+ BIT(pin->line));
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int atmel_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
+ int bank = ATMEL_PIO_BANK(d->hwirq);
+ int line = ATMEL_PIO_LINE(d->hwirq);
+
+ /* The gpio controller has one interrupt line per bank. */
+ irq_set_irq_wake(atmel_pioctrl->irqs[bank], on);
+
+ if (on)
+ atmel_pioctrl->pm_wakeup_sources[bank] |= BIT(line);
+ else
+ atmel_pioctrl->pm_wakeup_sources[bank] &= ~(BIT(line));
+
+ return 0;
+}
+#else
+#define atmel_gpio_irq_set_wake NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct irq_chip atmel_gpio_irq_chip = {
+ .name = "GPIO",
+ .irq_ack = atmel_gpio_irq_ack,
+ .irq_mask = atmel_gpio_irq_mask,
+ .irq_unmask = atmel_gpio_irq_unmask,
+ .irq_set_type = atmel_gpio_irq_set_type,
+ .irq_set_wake = atmel_gpio_irq_set_wake,
+};
+
+static void atmel_gpio_irq_handler(struct irq_desc *desc)
+{
+ unsigned int irq = irq_desc_get_irq(desc);
+ struct atmel_pioctrl *atmel_pioctrl = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long isr;
+ int n, bank = -1;
+
+ /* Find from which bank is the irq received. */
+ for (n = 0; n < atmel_pioctrl->nbanks; n++) {
+ if (atmel_pioctrl->irqs[n] == irq) {
+ bank = n;
+ break;
+ }
+ }
+
+ if (bank < 0) {
+ dev_err(atmel_pioctrl->dev,
+ "no bank associated to irq %u\n", irq);
+ return;
+ }
+
+ chained_irq_enter(chip, desc);
+
+ for (;;) {
+ isr = (unsigned long)atmel_gpio_read(atmel_pioctrl, bank,
+ ATMEL_PIO_ISR);
+ isr &= (unsigned long)atmel_gpio_read(atmel_pioctrl, bank,
+ ATMEL_PIO_IMR);
+ if (!isr)
+ break;
+
+ for_each_set_bit(n, &isr, BITS_PER_LONG)
+ generic_handle_irq(gpio_to_irq(bank *
+ ATMEL_PIO_NPINS_PER_BANK + n));
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+ unsigned reg;
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
+ BIT(pin->line));
+ reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR);
+ reg &= ~ATMEL_PIO_DIR_MASK;
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg);
+
+ return 0;
+}
+
+static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+ unsigned reg;
+
+ reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR);
+
+ return !!(reg & BIT(pin->line));
+}
+
+static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+ unsigned reg;
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank,
+ value ? ATMEL_PIO_SODR : ATMEL_PIO_CODR,
+ BIT(pin->line));
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
+ BIT(pin->line));
+ reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR);
+ reg |= ATMEL_PIO_DIR_MASK;
+ atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg);
+
+ return 0;
+}
+
+static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank,
+ val ? ATMEL_PIO_SODR : ATMEL_PIO_CODR,
+ BIT(pin->line));
+}
+
+static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
+
+ return irq_find_mapping(atmel_pioctrl->irq_domain, offset);
+}
+
+static struct gpio_chip atmel_gpio_chip = {
+ .direction_input = atmel_gpio_direction_input,
+ .get = atmel_gpio_get,
+ .direction_output = atmel_gpio_direction_output,
+ .set = atmel_gpio_set,
+ .to_irq = atmel_gpio_to_irq,
+ .base = 0,
+};
+
+/* --- PINCTRL --- */
+static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev,
+ unsigned pin_id)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
+ unsigned line = atmel_pioctrl->pins[pin_id]->line;
+ void __iomem *addr = atmel_pioctrl->reg_base
+ + bank * ATMEL_PIO_BANK_OFFSET;
+
+ writel_relaxed(BIT(line), addr + ATMEL_PIO_MSKR);
+ /* Have to set MSKR first, to access the right pin CFGR. */
+ wmb();
+
+ return readl_relaxed(addr + ATMEL_PIO_CFGR);
+}
+
+static void atmel_pin_config_write(struct pinctrl_dev *pctldev,
+ unsigned pin_id, u32 conf)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
+ unsigned line = atmel_pioctrl->pins[pin_id]->line;
+ void __iomem *addr = atmel_pioctrl->reg_base
+ + bank * ATMEL_PIO_BANK_OFFSET;
+
+ writel_relaxed(BIT(line), addr + ATMEL_PIO_MSKR);
+ /* Have to set MSKR first, to access the right pin CFGR. */
+ wmb();
+ writel_relaxed(conf, addr + ATMEL_PIO_CFGR);
+}
+
+static int atmel_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return atmel_pioctrl->npins;
+}
+
+static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return atmel_pioctrl->groups[selector].name;
+}
+
+static int atmel_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned selector, const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = (unsigned *)&atmel_pioctrl->groups[selector].pin;
+ *num_pins = 1;
+
+ return 0;
+}
+
+struct atmel_group *atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev,
+ unsigned pin)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ int i;
+
+ for (i = 0; i < atmel_pioctrl->npins; i++) {
+ struct atmel_group *grp = atmel_pioctrl->groups + i;
+
+ if (grp->pin == pin)
+ return grp;
+ }
+
+ return NULL;
+}
+
+static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ u32 pinfunc, const char **grp_name,
+ const char **func_name)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned pin_id, func_id;
+ struct atmel_group *grp;
+
+ pin_id = ATMEL_GET_PIN_NO(pinfunc);
+ func_id = ATMEL_GET_PIN_FUNC(pinfunc);
+
+ if (func_id >= ARRAY_SIZE(atmel_functions))
+ return -EINVAL;
+
+ *func_name = atmel_functions[func_id];
+
+ grp = atmel_pctl_find_group_by_pin(pctldev, pin_id);
+ if (!grp)
+ return -EINVAL;
+ *grp_name = grp->name;
+
+ atmel_pioctrl->pins[pin_id]->mux = func_id;
+ atmel_pioctrl->pins[pin_id]->ioset = ATMEL_GET_PIN_IOSET(pinfunc);
+ /* Want the device name not the group one. */
+ if (np->parent == atmel_pioctrl->node)
+ atmel_pioctrl->pins[pin_id]->device = np->name;
+ else
+ atmel_pioctrl->pins[pin_id]->device = np->parent->name;
+
+ return 0;
+}
+
+static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned *reserved_maps,
+ unsigned *num_maps)
+{
+ unsigned num_pins, num_configs, reserve;
+ unsigned long *configs;
+ struct property *pins;
+ bool has_config;
+ u32 pinfunc;
+ int ret, i;
+
+ pins = of_find_property(np, "pinmux", NULL);
+ if (!pins)
+ return -EINVAL;
+
+ ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
+ &num_configs);
+ if (ret < 0) {
+ dev_err(pctldev->dev, "%s: could not parse node property\n",
+ of_node_full_name(np));
+ return ret;
+ }
+
+ if (num_configs)
+ has_config = true;
+
+ num_pins = pins->length / sizeof(u32);
+ if (!num_pins) {
+ dev_err(pctldev->dev, "no pins found in node %s\n",
+ of_node_full_name(np));
+ return -EINVAL;
+ }
+
+ /*
+ * Reserve maps, at least there is a mux map and an optional conf
+ * map for each pin.
+ */
+ reserve = 1;
+ if (has_config && num_pins >= 1)
+ reserve++;
+ reserve *= num_pins;
+ ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
+ reserve);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < num_pins; i++) {
+ const char *group, *func;
+
+ ret = of_property_read_u32_index(np, "pinmux", i, &pinfunc);
+ if (ret)
+ return ret;
+
+ ret = atmel_pctl_xlate_pinfunc(pctldev, np, pinfunc, &group,
+ &func);
+ if (ret)
+ return ret;
+
+ pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps,
+ group, func);
+
+ if (has_config) {
+ ret = pinctrl_utils_add_map_configs(pctldev, map,
+ reserved_maps, num_maps, group,
+ configs, num_configs,
+ PIN_MAP_TYPE_CONFIGS_GROUP);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
+{
+ struct device_node *np;
+ unsigned reserved_maps;
+ int ret;
+
+ *map = NULL;
+ *num_maps = 0;
+ reserved_maps = 0;
+
+ /*
+ * If all the pins of a device have the same configuration (or no one),
+ * it is useless to add a subnode, so directly parse node referenced by
+ * phandle.
+ */
+ ret = atmel_pctl_dt_subnode_to_map(pctldev, np_config, map,
+ &reserved_maps, num_maps);
+ if (ret) {
+ for_each_child_of_node(np_config, np) {
+ ret = atmel_pctl_dt_subnode_to_map(pctldev, np, map,
+ &reserved_maps, num_maps);
+ if (ret < 0)
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+ dev_err(pctldev->dev, "can't create maps for node %s\n",
+ np_config->full_name);
+ }
+
+ return ret;
+}
+
+static const struct pinctrl_ops atmel_pctlops = {
+ .get_groups_count = atmel_pctl_get_groups_count,
+ .get_group_name = atmel_pctl_get_group_name,
+ .get_group_pins = atmel_pctl_get_group_pins,
+ .dt_node_to_map = atmel_pctl_dt_node_to_map,
+ .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(atmel_functions);
+}
+
+static const char *atmel_pmx_get_function_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return atmel_functions[selector];
+}
+
+static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = atmel_pioctrl->group_names;
+ *num_groups = atmel_pioctrl->npins;
+
+ return 0;
+}
+
+static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev,
+ unsigned function,
+ unsigned group)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned pin;
+ u32 conf;
+
+ dev_dbg(pctldev->dev, "enable function %s group %s\n",
+ atmel_functions[function], atmel_pioctrl->groups[group].name);
+
+ pin = atmel_pioctrl->groups[group].pin;
+ conf = atmel_pin_config_read(pctldev, pin);
+ conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
+ conf |= (function & ATMEL_PIO_CFGR_FUNC_MASK);
+ dev_dbg(pctldev->dev, "pin: %u, conf: 0x%08x\n", pin, conf);
+ atmel_pin_config_write(pctldev, pin, conf);
+
+ return 0;
+}
+
+static const struct pinmux_ops atmel_pmxops = {
+ .get_functions_count = atmel_pmx_get_functions_count,
+ .get_function_name = atmel_pmx_get_function_name,
+ .get_function_groups = atmel_pmx_get_function_groups,
+ .set_mux = atmel_pmx_set_mux,
+};
+
+static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
+ unsigned group,
+ unsigned long *config)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned param = pinconf_to_config_param(*config), arg = 0;
+ struct atmel_group *grp = atmel_pioctrl->groups + group;
+ unsigned pin_id = grp->pin;
+ u32 res;
+
+ res = atmel_pin_config_read(pctldev, pin_id);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (!(res & ATMEL_PIO_PUEN_MASK))
+ return -EINVAL;
+ arg = 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if ((res & ATMEL_PIO_PUEN_MASK) ||
+ (!(res & ATMEL_PIO_PDEN_MASK)))
+ return -EINVAL;
+ arg = 1;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ if ((res & ATMEL_PIO_PUEN_MASK) ||
+ ((res & ATMEL_PIO_PDEN_MASK)))
+ return -EINVAL;
+ arg = 1;
+ break;
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ if (!(res & ATMEL_PIO_OPD_MASK))
+ return -EINVAL;
+ arg = 1;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!(res & ATMEL_PIO_SCHMITT_MASK))
+ return -EINVAL;
+ arg = 1;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+ return 0;
+}
+
+static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
+ unsigned group,
+ unsigned long *configs,
+ unsigned num_configs)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct atmel_group *grp = atmel_pioctrl->groups + group;
+ unsigned bank, pin, pin_id = grp->pin;
+ u32 mask, conf = 0;
+ int i;
+
+ conf = atmel_pin_config_read(pctldev, pin_id);
+
+ for (i = 0; i < num_configs; i++) {
+ unsigned param = pinconf_to_config_param(configs[i]);
+ unsigned arg = pinconf_to_config_argument(configs[i]);
+
+ dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n",
+ __func__, pin_id, configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ conf &= (~ATMEL_PIO_PUEN_MASK);
+ conf &= (~ATMEL_PIO_PDEN_MASK);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ conf |= ATMEL_PIO_PUEN_MASK;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ conf |= ATMEL_PIO_PDEN_MASK;
+ break;
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ if (arg == 0)
+ conf &= (~ATMEL_PIO_OPD_MASK);
+ else
+ conf |= ATMEL_PIO_OPD_MASK;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (arg == 0)
+ conf |= ATMEL_PIO_SCHMITT_MASK;
+ else
+ conf &= (~ATMEL_PIO_SCHMITT_MASK);
+ break;
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ if (arg == 0) {
+ conf &= (~ATMEL_PIO_IFEN_MASK);
+ conf &= (~ATMEL_PIO_IFSCEN_MASK);
+ } else {
+ /*
+ * We don't care about the debounce value for several reasons:
+ * - can't have different debounce periods inside a same group,
+ * - the register to configure this period is a secure register.
+ * The debouncing filter can filter a pulse with a duration of less
+ * than 1/2 slow clock period.
+ */
+ conf |= ATMEL_PIO_IFEN_MASK;
+ conf |= ATMEL_PIO_IFSCEN_MASK;
+ }
+ break;
+ case PIN_CONFIG_OUTPUT:
+ conf |= ATMEL_PIO_DIR_MASK;
+ bank = ATMEL_PIO_BANK(pin_id);
+ pin = ATMEL_PIO_LINE(pin_id);
+ mask = 1 << pin;
+
+ if (arg == 0) {
+ writel_relaxed(mask, atmel_pioctrl->reg_base +
+ bank * ATMEL_PIO_BANK_OFFSET +
+ ATMEL_PIO_CODR);
+ } else {
+ writel_relaxed(mask, atmel_pioctrl->reg_base +
+ bank * ATMEL_PIO_BANK_OFFSET +
+ ATMEL_PIO_SODR);
+ }
+ break;
+ default:
+ dev_warn(pctldev->dev,
+ "unsupported configuration parameter: %u\n",
+ param);
+ continue;
+ }
+ }
+
+ dev_dbg(pctldev->dev, "%s: reg=0x%08x\n", __func__, conf);
+ atmel_pin_config_write(pctldev, pin_id, conf);
+
+ return 0;
+}
+
+static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
+ u32 conf;
+
+ if (!atmel_pioctrl->pins[pin_id]->device)
+ return;
+
+ if (atmel_pioctrl->pins[pin_id])
+ seq_printf(s, " (%s, ioset %u) ",
+ atmel_pioctrl->pins[pin_id]->device,
+ atmel_pioctrl->pins[pin_id]->ioset);
+
+ conf = atmel_pin_config_read(pctldev, pin_id);
+ if (conf & ATMEL_PIO_PUEN_MASK)
+ seq_printf(s, "%s ", "pull-up");
+ if (conf & ATMEL_PIO_PDEN_MASK)
+ seq_printf(s, "%s ", "pull-down");
+ if (conf & ATMEL_PIO_IFEN_MASK)
+ seq_printf(s, "%s ", "debounce");
+ if (conf & ATMEL_PIO_OPD_MASK)
+ seq_printf(s, "%s ", "open-drain");
+ if (conf & ATMEL_PIO_SCHMITT_MASK)
+ seq_printf(s, "%s ", "schmitt");
+}
+
+static const struct pinconf_ops atmel_confops = {
+ .pin_config_group_get = atmel_conf_pin_config_group_get,
+ .pin_config_group_set = atmel_conf_pin_config_group_set,
+ .pin_config_dbg_show = atmel_conf_pin_config_dbg_show,
+};
+
+static struct pinctrl_desc atmel_pinctrl_desc = {
+ .name = "atmel_pinctrl",
+ .confops = &atmel_confops,
+ .pctlops = &atmel_pctlops,
+ .pmxops = &atmel_pmxops,
+};
+
+static int atmel_pctrl_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
+ int i;
+
+ /*
+ * For each bank, save IMR to restore it later and disable all GPIO
+ * interrupts excepting the ones marked as wakeup sources.
+ */
+ for (i = 0; i < atmel_pioctrl->nbanks; i++) {
+ atmel_pioctrl->pm_suspend_backup[i] =
+ atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_IMR);
+ atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IDR,
+ ~atmel_pioctrl->pm_wakeup_sources[i]);
+ }
+
+ return 0;
+}
+
+static int atmel_pctrl_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < atmel_pioctrl->nbanks; i++)
+ atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IER,
+ atmel_pioctrl->pm_suspend_backup[i]);
+
+ return 0;
+}
+
+static const struct dev_pm_ops atmel_pctrl_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(atmel_pctrl_suspend, atmel_pctrl_resume)
+};
+
+/*
+ * The number of banks can be different from a SoC to another one.
+ * We can have up to 16 banks.
+ */
+static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
+ .nbanks = 4,
+};
+
+static const struct of_device_id atmel_pctrl_of_match[] = {
+ {
+ .compatible = "atmel,sama5d2-pinctrl",
+ .data = &atmel_sama5d2_pioctrl_data,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, atmel_pctrl_of_match);
+
+static int atmel_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pinctrl_pin_desc *pin_desc;
+ const char **group_names;
+ const struct of_device_id *match;
+ int i, ret;
+ struct resource *res;
+ struct atmel_pioctrl *atmel_pioctrl;
+ struct atmel_pioctrl_data *atmel_pioctrl_data;
+
+ atmel_pioctrl = devm_kzalloc(dev, sizeof(*atmel_pioctrl), GFP_KERNEL);
+ if (!atmel_pioctrl)
+ return -ENOMEM;
+ atmel_pioctrl->dev = dev;
+ atmel_pioctrl->node = dev->of_node;
+ platform_set_drvdata(pdev, atmel_pioctrl);
+
+ match = of_match_node(atmel_pctrl_of_match, dev->of_node);
+ if (!match) {
+ dev_err(dev, "unknown compatible string\n");
+ return -ENODEV;
+ }
+ atmel_pioctrl_data = (struct atmel_pioctrl_data *)match->data;
+ atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks;
+ atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "unable to get atmel pinctrl resource\n");
+ return -EINVAL;
+ }
+ atmel_pioctrl->reg_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(atmel_pioctrl->reg_base))
+ return -EINVAL;
+
+ atmel_pioctrl->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(atmel_pioctrl->clk)) {
+ dev_err(dev, "failed to get clock\n");
+ return PTR_ERR(atmel_pioctrl->clk);
+ }
+
+ atmel_pioctrl->pins = devm_kzalloc(dev, sizeof(*atmel_pioctrl->pins)
+ * atmel_pioctrl->npins, GFP_KERNEL);
+ if (!atmel_pioctrl->pins)
+ return -ENOMEM;
+
+ pin_desc = devm_kzalloc(dev, sizeof(*pin_desc)
+ * atmel_pioctrl->npins, GFP_KERNEL);
+ if (!pin_desc)
+ return -ENOMEM;
+ atmel_pinctrl_desc.pins = pin_desc;
+ atmel_pinctrl_desc.npins = atmel_pioctrl->npins;
+
+ /* One pin is one group since a pin can achieve all functions. */
+ group_names = devm_kzalloc(dev, sizeof(*group_names)
+ * atmel_pioctrl->npins, GFP_KERNEL);
+ if (!group_names)
+ return -ENOMEM;
+ atmel_pioctrl->group_names = group_names;
+
+ atmel_pioctrl->groups = devm_kzalloc(&pdev->dev,
+ sizeof(*atmel_pioctrl->groups) * atmel_pioctrl->npins,
+ GFP_KERNEL);
+ if (!atmel_pioctrl->groups)
+ return -ENOMEM;
+ for (i = 0 ; i < atmel_pioctrl->npins; i++) {
+ struct atmel_group *group = atmel_pioctrl->groups + i;
+ unsigned bank = ATMEL_PIO_BANK(i);
+ unsigned line = ATMEL_PIO_LINE(i);
+
+ atmel_pioctrl->pins[i] = devm_kzalloc(dev,
+ sizeof(**atmel_pioctrl->pins), GFP_KERNEL);
+ if (!atmel_pioctrl->pins[i])
+ return -ENOMEM;
+
+ atmel_pioctrl->pins[i]->pin_id = i;
+ atmel_pioctrl->pins[i]->bank = bank;
+ atmel_pioctrl->pins[i]->line = line;
+
+ pin_desc[i].number = i;
+ /* Pin naming convention: P(bank_name)(bank_pin_number). */
+ pin_desc[i].name = kasprintf(GFP_KERNEL, "P%c%d",
+ bank + 'A', line);
+
+ group->name = group_names[i] = pin_desc[i].name;
+ group->pin = pin_desc[i].number;
+
+ dev_dbg(dev, "pin_id=%u, bank=%u, line=%u", i, bank, line);
+ }
+
+ atmel_pioctrl->gpio_chip = &atmel_gpio_chip;
+ atmel_pioctrl->gpio_chip->of_node = dev->of_node;
+ atmel_pioctrl->gpio_chip->ngpio = atmel_pioctrl->npins;
+ atmel_pioctrl->gpio_chip->label = dev_name(dev);
+ atmel_pioctrl->gpio_chip->dev = dev;
+ atmel_pioctrl->gpio_chip->names = atmel_pioctrl->group_names;
+
+ atmel_pioctrl->pm_wakeup_sources = devm_kzalloc(dev,
+ sizeof(*atmel_pioctrl->pm_wakeup_sources)
+ * atmel_pioctrl->nbanks, GFP_KERNEL);
+ if (!atmel_pioctrl->pm_wakeup_sources)
+ return -ENOMEM;
+
+ atmel_pioctrl->pm_suspend_backup = devm_kzalloc(dev,
+ sizeof(*atmel_pioctrl->pm_suspend_backup)
+ * atmel_pioctrl->nbanks, GFP_KERNEL);
+ if (!atmel_pioctrl->pm_suspend_backup)
+ return -ENOMEM;
+
+ atmel_pioctrl->irqs = devm_kzalloc(dev, sizeof(*atmel_pioctrl->irqs)
+ * atmel_pioctrl->nbanks, GFP_KERNEL);
+ if (!atmel_pioctrl->irqs)
+ return -ENOMEM;
+
+ /* There is one controller but each bank has its own irq line. */
+ for (i = 0; i < atmel_pioctrl->nbanks; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(dev, "missing irq resource for group %c\n",
+ 'A' + i);
+ return -EINVAL;
+ }
+ atmel_pioctrl->irqs[i] = res->start;
+ irq_set_chained_handler(res->start, atmel_gpio_irq_handler);
+ irq_set_handler_data(res->start, atmel_pioctrl);
+ dev_dbg(dev, "bank %i: hwirq=%u\n", i, res->start);
+ }
+
+ atmel_pioctrl->irq_domain = irq_domain_add_linear(dev->of_node,
+ atmel_pioctrl->gpio_chip->ngpio,
+ &irq_domain_simple_ops, NULL);
+ if (!atmel_pioctrl->irq_domain) {
+ dev_err(dev, "can't add the irq domain\n");
+ return -ENODEV;
+ }
+ atmel_pioctrl->irq_domain->name = "atmel gpio";
+
+ for (i = 0; i < atmel_pioctrl->npins; i++) {
+ int irq = irq_create_mapping(atmel_pioctrl->irq_domain, i);
+
+ irq_set_chip_and_handler(irq, &atmel_gpio_irq_chip,
+ handle_simple_irq);
+ irq_set_chip_data(irq, atmel_pioctrl);
+ dev_dbg(dev,
+ "atmel gpio irq domain: hwirq: %d, linux irq: %d\n",
+ i, irq);
+ }
+
+ ret = clk_prepare_enable(atmel_pioctrl->clk);
+ if (ret) {
+ dev_err(dev, "failed to prepare and enable clock\n");
+ goto clk_prepare_enable_error;
+ }
+
+ atmel_pioctrl->pinctrl_dev = pinctrl_register(&atmel_pinctrl_desc,
+ &pdev->dev,
+ atmel_pioctrl);
+ if (!atmel_pioctrl->pinctrl_dev) {
+ dev_err(dev, "pinctrl registration failed\n");
+ goto pinctrl_register_error;
+ }
+
+ ret = gpiochip_add(atmel_pioctrl->gpio_chip);
+ if (ret) {
+ dev_err(dev, "failed to add gpiochip\n");
+ goto gpiochip_add_error;
+ }
+
+ ret = gpiochip_add_pin_range(atmel_pioctrl->gpio_chip, dev_name(dev),
+ 0, 0, atmel_pioctrl->gpio_chip->ngpio);
+ if (ret) {
+ dev_err(dev, "failed to add gpio pin range\n");
+ goto gpiochip_add_pin_range_error;
+ }
+
+ dev_info(&pdev->dev, "atmel pinctrl initialized\n");
+
+ return 0;
+
+clk_prepare_enable_error:
+ irq_domain_remove(atmel_pioctrl->irq_domain);
+pinctrl_register_error:
+ clk_disable_unprepare(atmel_pioctrl->clk);
+gpiochip_add_error:
+ pinctrl_unregister(atmel_pioctrl->pinctrl_dev);
+gpiochip_add_pin_range_error:
+ gpiochip_remove(atmel_pioctrl->gpio_chip);
+
+ return ret;
+}
+
+int atmel_pinctrl_remove(struct platform_device *pdev)
+{
+ struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
+
+ irq_domain_remove(atmel_pioctrl->irq_domain);
+ clk_disable_unprepare(atmel_pioctrl->clk);
+ pinctrl_unregister(atmel_pioctrl->pinctrl_dev);
+ gpiochip_remove(atmel_pioctrl->gpio_chip);
+
+ return 0;
+}
+
+static struct platform_driver atmel_pinctrl_driver = {
+ .driver = {
+ .name = "pinctrl-at91-pio4",
+ .of_match_table = atmel_pctrl_of_match,
+ .pm = &atmel_pctrl_pm_ops,
+ },
+ .probe = atmel_pinctrl_probe,
+ .remove = atmel_pinctrl_remove,
+};
+module_platform_driver(atmel_pinctrl_driver);
+
+MODULE_AUTHOR(Ludovic Desroches <ludovic.desroches@atmel.com>);
+MODULE_DESCRIPTION("Atmel PIO4 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index b0fde0f385e6..0d2fc0cff35e 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1122,8 +1122,10 @@ static int at91_pinctrl_parse_functions(struct device_node *np,
func->groups[i] = child->name;
grp = &info->groups[grp_index++];
ret = at91_pinctrl_parse_groups(child, grp, info, i++);
- if (ret)
+ if (ret) {
+ of_node_put(child);
return ret;
+ }
}
return 0;
@@ -1196,6 +1198,7 @@ static int at91_pinctrl_probe_dt(struct platform_device *pdev,
ret = at91_pinctrl_parse_functions(child, info, i++);
if (ret) {
dev_err(&pdev->dev, "failed to parse function\n");
+ of_node_put(child);
return ret;
}
}
@@ -1277,28 +1280,6 @@ static int at91_pinctrl_remove(struct platform_device *pdev)
return 0;
}
-static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- /*
- * Map back to global GPIO space and request muxing, the direction
- * parameter does not matter for this controller.
- */
- int gpio = chip->base + offset;
- int bank = chip->base / chip->ngpio;
-
- dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
- 'A' + bank, offset, gpio);
-
- return pinctrl_request_gpio(gpio);
-}
-
-static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- pinctrl_free_gpio(gpio);
-}
-
static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
@@ -1684,8 +1665,8 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
/* This structure is replicated for each GPIO block allocated at probe time */
static struct gpio_chip at91_gpio_template = {
- .request = at91_gpio_request,
- .free = at91_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.get_direction = at91_gpio_get_direction,
.direction_input = at91_gpio_direction_input,
.get = at91_gpio_get,
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 9c9b88934bcc..813eb7c771ec 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -217,24 +217,6 @@ static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
return container_of(chip, struct u300_gpio, chip);
}
-static int u300_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- /*
- * Map back to global GPIO space and request muxing, the direction
- * parameter does not matter for this controller.
- */
- int gpio = chip->base + offset;
-
- return pinctrl_request_gpio(gpio);
-}
-
-static void u300_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- pinctrl_free_gpio(gpio);
-}
-
static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct u300_gpio *gpio = to_u300_gpio(chip);
@@ -417,8 +399,8 @@ int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip u300_gpio_chip = {
.label = "u300-gpio-chip",
.owner = THIS_MODULE,
- .request = u300_gpio_request,
- .free = u300_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.get = u300_gpio_get,
.set = u300_gpio_set,
.direction_input = u300_gpio_direction_input,
diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c
index 11f8b835d3b6..38a7799f8257 100644
--- a/drivers/pinctrl/pinctrl-digicolor.c
+++ b/drivers/pinctrl/pinctrl-digicolor.c
@@ -169,16 +169,6 @@ static struct pinmux_ops dc_pmxops = {
.gpio_request_enable = dc_pmx_request_gpio,
};
-static int dc_gpio_request(struct gpio_chip *chip, unsigned gpio)
-{
- return pinctrl_request_gpio(chip->base + gpio);
-}
-
-static void dc_gpio_free(struct gpio_chip *chip, unsigned gpio)
-{
- pinctrl_free_gpio(chip->base + gpio);
-}
-
static int dc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip);
@@ -255,8 +245,8 @@ static int dc_gpiochip_add(struct dc_pinmap *pmap, struct device_node *np)
chip->label = DRIVER_NAME;
chip->dev = pmap->dev;
- chip->request = dc_gpio_request;
- chip->free = dc_gpio_free;
+ chip->request = gpiochip_generic_request;
+ chip->free = gpiochip_generic_free;
chip->direction_input = dc_gpio_direction_input;
chip->direction_output = dc_gpio_direction_output;
chip->get = dc_gpio_get;
diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
index 952b1c623887..85c9046c690e 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -1171,16 +1171,6 @@ static struct pinctrl_desc pistachio_pinctrl_desc = {
.confops = &pistachio_pinconf_ops,
};
-static int pistachio_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void pistachio_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int pistachio_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct pistachio_gpio_bank *bank = gc_to_bank(chip);
@@ -1332,8 +1322,8 @@ static void pistachio_gpio_irq_handler(struct irq_desc *desc)
.npins = _npins, \
.gpio_chip = { \
.label = "GPIO" #_bank, \
- .request = pistachio_gpio_request, \
- .free = pistachio_gpio_free, \
+ .request = gpiochip_generic_request, \
+ .free = gpiochip_generic_free, \
.get_direction = pistachio_gpio_get_direction, \
.direction_input = pistachio_gpio_direction_input, \
.direction_output = pistachio_gpio_direction_output, \
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 88bb707e107a..a0651128e23a 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1374,16 +1374,6 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
* GPIO handling
*/
-static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
@@ -1461,8 +1451,8 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
}
static const struct gpio_chip rockchip_gpiolib_chip = {
- .request = rockchip_gpio_request,
- .free = rockchip_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.set = rockchip_gpio_set,
.get = rockchip_gpio_get,
.direction_input = rockchip_gpio_direction_input,
@@ -2089,6 +2079,21 @@ static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
.pull_calc_reg = rk2928_calc_pull_reg_and_bit,
};
+static struct rockchip_pin_bank rk3036_pin_banks[] = {
+ PIN_BANK(0, 32, "gpio0"),
+ PIN_BANK(1, 32, "gpio1"),
+ PIN_BANK(2, 32, "gpio2"),
+};
+
+static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
+ .pin_banks = rk3036_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3036_pin_banks),
+ .label = "RK3036-GPIO",
+ .type = RK2928,
+ .grf_mux_offset = 0xa8,
+ .pull_calc_reg = rk2928_calc_pull_reg_and_bit,
+};
+
static struct rockchip_pin_bank rk3066a_pin_banks[] = {
PIN_BANK(0, 32, "gpio0"),
PIN_BANK(1, 32, "gpio1"),
@@ -2207,6 +2212,8 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
{ .compatible = "rockchip,rk2928-pinctrl",
.data = (void *)&rk2928_pin_ctrl },
+ { .compatible = "rockchip,rk3036-pinctrl",
+ .data = (void *)&rk3036_pin_ctrl },
{ .compatible = "rockchip,rk3066a-pinctrl",
.data = (void *)&rk3066a_pin_ctrl },
{ .compatible = "rockchip,rk3066b-pinctrl",
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 389526e704fb..b58d3f29148a 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -742,16 +742,6 @@ static void st_gpio_direction(struct st_gpio_bank *bank,
}
}
-static int st_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void st_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int st_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
@@ -1490,8 +1480,8 @@ static void st_gpio_irqmux_handler(struct irq_desc *desc)
}
static struct gpio_chip st_gpio_template = {
- .request = st_gpio_request,
- .free = st_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.get = st_gpio_get,
.set = st_gpio_set,
.direction_input = st_gpio_direction_input,
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index 2651d04bd1be..84a43e612952 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -760,24 +760,15 @@ static const char * const tegra124_pcie_groups[] = {
"pcie-2",
"pcie-3",
"pcie-4",
- "sata-0",
};
static const char * const tegra124_usb3_groups[] = {
"pcie-0",
"pcie-1",
- "pcie-2",
- "pcie-3",
- "pcie-4",
"sata-0",
};
static const char * const tegra124_sata_groups[] = {
- "pcie-0",
- "pcie-1",
- "pcie-2",
- "pcie-3",
- "pcie-4",
"sata-0",
};
diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c
index c349911708ef..b89ad3c0c731 100644
--- a/drivers/pinctrl/pinctrl-tz1090-pdc.c
+++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c
@@ -668,7 +668,7 @@ static int tz1090_pdc_pinconf_reg(struct pinctrl_dev *pctldev,
break;
default:
return -ENOTSUPP;
- };
+ }
/* Only input bias parameters supported */
*reg = REG_GPIO_CONTROL2;
@@ -801,7 +801,7 @@ static int tz1090_pdc_pinconf_group_reg(struct pinctrl_dev *pctldev,
break;
default:
return -ENOTSUPP;
- };
+ }
/* Calculate field information */
*mask = (BIT(*width) - 1) << *shift;
diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c
index 6d07a2f64d97..5425299d759d 100644
--- a/drivers/pinctrl/pinctrl-tz1090.c
+++ b/drivers/pinctrl/pinctrl-tz1090.c
@@ -1661,7 +1661,7 @@ static int tz1090_pinconf_reg(struct pinctrl_dev *pctldev,
break;
default:
return -ENOTSUPP;
- };
+ }
/* Only input bias parameters supported */
pu = &tz1090_pinconf_pullup[pin];
@@ -1790,7 +1790,7 @@ static int tz1090_pinconf_group_reg(struct pinctrl_dev *pctldev,
break;
default:
return -ENOTSUPP;
- };
+ }
/* Calculate field information */
*shift = g->slw_bit * *width;
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index 779950c62e53..ae724bdab3d3 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -682,28 +682,14 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
return 0;
}
-static int xway_gpio_req(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- return pinctrl_request_gpio(gpio);
-}
-
-static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
-
- pinctrl_free_gpio(gpio);
-}
-
static struct gpio_chip xway_chip = {
.label = "gpio-xway",
.direction_input = xway_gpio_dir_in,
.direction_output = xway_gpio_dir_out,
.get = xway_gpio_get,
.set = xway_gpio_set,
- .request = xway_gpio_req,
- .free = xway_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.base = -1,
};
diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c
index 5aafea8c6590..d57b5eca7b98 100644
--- a/drivers/pinctrl/pinctrl-zynq.c
+++ b/drivers/pinctrl/pinctrl-zynq.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Xilinx
*
- * Sören Brinkmann <soren.brinkmann@xilinx.com>
+ * Sören Brinkmann <soren.brinkmann@xilinx.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
@@ -1230,8 +1230,18 @@ static struct platform_driver zynq_pinctrl_driver = {
.remove = zynq_pinctrl_remove,
};
-module_platform_driver(zynq_pinctrl_driver);
+static int __init zynq_pinctrl_init(void)
+{
+ return platform_driver_register(&zynq_pinctrl_driver);
+}
+arch_initcall(zynq_pinctrl_init);
+
+static void __exit zynq_pinctrl_exit(void)
+{
+ platform_driver_unregister(&zynq_pinctrl_driver);
+}
+module_exit(zynq_pinctrl_exit);
-MODULE_AUTHOR("Sören Brinkmann <soren.brinkmann@xilinx.com>");
+MODULE_AUTHOR("Sören Brinkmann <soren.brinkmann@xilinx.com>");
MODULE_DESCRIPTION("Xilinx Zynq pinctrl driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index a0c7407c1cac..146264a41ec8 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -458,18 +458,6 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_unlock_irqrestore(&pctrl->lock, flags);
}
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
- return pinctrl_request_gpio(gpio);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- int gpio = chip->base + offset;
- return pinctrl_free_gpio(gpio);
-}
-
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
@@ -527,8 +515,8 @@ static struct gpio_chip msm_gpio_template = {
.direction_output = msm_gpio_direction_output,
.get = msm_gpio_get,
.set = msm_gpio_set,
- .request = msm_gpio_request,
- .free = msm_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.dbg_show = msm_gpio_dbg_show,
};
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index bd1e24598e12..6c42ca14d2fd 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -546,16 +546,6 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
pmic_gpio_config_set(state->ctrl, pin, &config, 1);
}
-static int pmic_gpio_request(struct gpio_chip *chip, unsigned base)
-{
- return pinctrl_request_gpio(chip->base + base);
-}
-
-static void pmic_gpio_free(struct gpio_chip *chip, unsigned base)
-{
- pinctrl_free_gpio(chip->base + base);
-}
-
static int pmic_gpio_of_xlate(struct gpio_chip *chip,
const struct of_phandle_args *gpio_desc,
u32 *flags)
@@ -595,8 +585,8 @@ static const struct gpio_chip pmic_gpio_gpio_template = {
.direction_output = pmic_gpio_direction_output,
.get = pmic_gpio_get,
.set = pmic_gpio_set,
- .request = pmic_gpio_request,
- .free = pmic_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.of_xlate = pmic_gpio_of_xlate,
.to_irq = pmic_gpio_to_irq,
.dbg_show = pmic_gpio_dbg_show,
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
index e3be3ce2cada..9ce0e30e33e8 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
@@ -604,16 +604,6 @@ static void pmic_mpp_set(struct gpio_chip *chip, unsigned pin, int value)
pmic_mpp_config_set(state->ctrl, pin, &config, 1);
}
-static int pmic_mpp_request(struct gpio_chip *chip, unsigned base)
-{
- return pinctrl_request_gpio(chip->base + base);
-}
-
-static void pmic_mpp_free(struct gpio_chip *chip, unsigned base)
-{
- pinctrl_free_gpio(chip->base + base);
-}
-
static int pmic_mpp_of_xlate(struct gpio_chip *chip,
const struct of_phandle_args *gpio_desc,
u32 *flags)
@@ -653,8 +643,8 @@ static const struct gpio_chip pmic_mpp_gpio_template = {
.direction_output = pmic_mpp_direction_output,
.get = pmic_mpp_get,
.set = pmic_mpp_set,
- .request = pmic_mpp_request,
- .free = pmic_mpp_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.of_xlate = pmic_mpp_of_xlate,
.to_irq = pmic_mpp_to_irq,
.dbg_show = pmic_mpp_dbg_show,
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
index e1a3721bc8e5..d809c9eaa323 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
@@ -584,7 +584,7 @@ static void pm8xxx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
}
#else
-#define msm_gpio_dbg_show NULL
+#define pm8xxx_gpio_dbg_show NULL
#endif
static struct gpio_chip pm8xxx_gpio_template = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
index 6652b8d7f707..8982027de8e8 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
@@ -639,7 +639,7 @@ static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)
}
#else
-#define msm_mpp_dbg_show NULL
+#define pm8xxx_mpp_dbg_show NULL
#endif
static struct gpio_chip pm8xxx_mpp_template = {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index 9ce0b8619d4c..82dc109f7ed4 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -284,7 +284,7 @@ static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,
if (!idx)
kfree(map[idx].data.configs.group_or_pin);
}
- };
+ }
kfree(map);
}
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index c760bf43d116..3f622ccd8eab 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -888,19 +888,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
return 0;
}
-static int samsung_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void samsung_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static const struct gpio_chip samsung_gpiolib_chip = {
- .request = samsung_gpio_request,
- .free = samsung_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.set = samsung_gpio_set,
.get = samsung_gpio_get,
.direction_input = samsung_gpio_direction_input,
diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
index 8e024c9c9115..35d6e95fa21f 100644
--- a/drivers/pinctrl/sh-pfc/Kconfig
+++ b/drivers/pinctrl/sh-pfc/Kconfig
@@ -65,6 +65,11 @@ config PINCTRL_PFC_R8A7794
depends on ARCH_R8A7794
select PINCTRL_SH_PFC
+config PINCTRL_PFC_R8A7795
+ def_bool y
+ depends on ARCH_R8A7795
+ select PINCTRL_SH_PFC
+
config PINCTRL_PFC_SH7203
def_bool y
depends on CPU_SUBTYPE_SH7203
diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile
index ea2a60ef122a..173305fa3811 100644
--- a/drivers/pinctrl/sh-pfc/Makefile
+++ b/drivers/pinctrl/sh-pfc/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7790) += pfc-r8a7790.o
obj-$(CONFIG_PINCTRL_PFC_R8A7791) += pfc-r8a7791.o
obj-$(CONFIG_PINCTRL_PFC_R8A7793) += pfc-r8a7791.o
obj-$(CONFIG_PINCTRL_PFC_R8A7794) += pfc-r8a7794.o
+obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795.o
obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index fb9c44805234..181ea98a63b7 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -272,7 +272,7 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
u16 *enum_idp)
{
- const u16 *data = pfc->info->gpio_data;
+ const u16 *data = pfc->info->pinmux_data;
unsigned int k;
if (pos) {
@@ -280,7 +280,7 @@ static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
return pos + 1;
}
- for (k = 0; k < pfc->info->gpio_data_size; k++) {
+ for (k = 0; k < pfc->info->pinmux_data_size; k++) {
if (data[k] == mark) {
*enum_idp = data[k + 1];
return k + 1;
@@ -489,6 +489,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
.data = &r8a7794_pinmux_info,
},
#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7795
+ {
+ .compatible = "renesas,pfc-r8a7795",
+ .data = &r8a7795_pinmux_info,
+ },
+#endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
{
.compatible = "renesas,pfc-sh73a0",
@@ -587,12 +593,6 @@ static int sh_pfc_remove(struct platform_device *pdev)
}
static const struct platform_device_id sh_pfc_id_table[] = {
-#ifdef CONFIG_PINCTRL_PFC_R8A7778
- { "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info },
-#endif
-#ifdef CONFIG_PINCTRL_PFC_R8A7779
- { "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
-#endif
#ifdef CONFIG_PINCTRL_PFC_SH7203
{ "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
#endif
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index 4c3c37bf7161..62f53b22ae85 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -46,7 +46,9 @@ struct sh_pfc {
unsigned int nr_gpio_pins;
struct sh_pfc_chip *gpio;
+#ifdef CONFIG_SUPERH
struct sh_pfc_chip *func;
+#endif
struct sh_pfc_pinctrl *pinctrl;
};
@@ -73,6 +75,7 @@ extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
extern const struct sh_pfc_soc_info r8a7793_pinmux_info;
extern const struct sh_pfc_soc_info r8a7794_pinmux_info;
+extern const struct sh_pfc_soc_info r8a7795_pinmux_info;
extern const struct sh_pfc_soc_info sh7203_pinmux_info;
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
extern const struct sh_pfc_soc_info sh7269_pinmux_info;
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index ba353735ecf2..db3f09aa8993 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -219,10 +219,7 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset)
return -ENOSYS;
found:
- if (pfc->num_irqs)
- return pfc->irqs[i];
- else
- return pfc->info->gpio_irq[i].irq;
+ return pfc->irqs[i];
}
static int gpio_pin_setup(struct sh_pfc_chip *chip)
@@ -261,6 +258,7 @@ static int gpio_pin_setup(struct sh_pfc_chip *chip)
* Function GPIOs
*/
+#ifdef CONFIG_SUPERH
static int gpio_function_request(struct gpio_chip *gc, unsigned offset)
{
static bool __print_once;
@@ -286,17 +284,12 @@ static int gpio_function_request(struct gpio_chip *gc, unsigned offset)
return ret;
}
-static void gpio_function_free(struct gpio_chip *gc, unsigned offset)
-{
-}
-
static int gpio_function_setup(struct sh_pfc_chip *chip)
{
struct sh_pfc *pfc = chip->pfc;
struct gpio_chip *gc = &chip->gpio_chip;
gc->request = gpio_function_request;
- gc->free = gpio_function_free;
gc->label = pfc->info->name;
gc->owner = THIS_MODULE;
@@ -305,6 +298,7 @@ static int gpio_function_setup(struct sh_pfc_chip *chip)
return 0;
}
+#endif
/* -----------------------------------------------------------------------------
* Register/unregister
@@ -344,7 +338,6 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
struct sh_pfc_chip *chip;
phys_addr_t address;
unsigned int i;
- int ret;
if (pfc->info->data_regs == NULL)
return 0;
@@ -367,7 +360,7 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
return 0;
/* If we have IRQ resources make sure their number is correct. */
- if (pfc->num_irqs && pfc->num_irqs != pfc->info->gpio_irq_size) {
+ if (pfc->num_irqs != pfc->info->gpio_irq_size) {
dev_err(pfc->dev, "invalid number of IRQ resources\n");
return -EINVAL;
}
@@ -379,20 +372,26 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
pfc->gpio = chip;
- /* Register the GPIO to pin mappings. As pins with GPIO ports must come
- * first in the ranges, skip the pins without GPIO ports by stopping at
- * the first range that contains such a pin.
+ if (IS_ENABLED(CONFIG_OF) && pfc->dev->of_node)
+ return 0;
+
+#ifdef CONFIG_SUPERH
+ /*
+ * Register the GPIO to pin mappings. As pins with GPIO ports
+ * must come first in the ranges, skip the pins without GPIO
+ * ports by stopping at the first range that contains such a
+ * pin.
*/
for (i = 0; i < pfc->nr_ranges; ++i) {
const struct sh_pfc_pin_range *range = &pfc->ranges[i];
+ int ret;
if (range->start >= pfc->nr_gpio_pins)
break;
ret = gpiochip_add_pin_range(&chip->gpio_chip,
- dev_name(pfc->dev),
- range->start, range->start,
- range->end - range->start + 1);
+ dev_name(pfc->dev), range->start, range->start,
+ range->end - range->start + 1);
if (ret < 0)
return ret;
}
@@ -406,6 +405,7 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
return PTR_ERR(chip);
pfc->func = chip;
+#endif /* CONFIG_SUPERH */
return 0;
}
@@ -413,7 +413,8 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc)
{
gpiochip_remove(&pfc->gpio->gpio_chip);
+#ifdef CONFIG_SUPERH
gpiochip_remove(&pfc->func->gpio_chip);
-
+#endif
return 0;
}
diff --git a/drivers/pinctrl/sh-pfc/pfc-emev2.c b/drivers/pinctrl/sh-pfc/pfc-emev2.c
index 849c6943ed30..02118ab336fc 100644
--- a/drivers/pinctrl/sh-pfc/pfc-emev2.c
+++ b/drivers/pinctrl/sh-pfc/pfc-emev2.c
@@ -1706,6 +1706,6 @@ const struct sh_pfc_soc_info emev2_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
index ba18d2e65e67..d9d9228b15fa 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
@@ -2603,64 +2603,64 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
};
static const struct pinmux_irq pinmux_irqs[] = {
- PINMUX_IRQ(irq_pin(0), 0),
- PINMUX_IRQ(irq_pin(1), 1),
- PINMUX_IRQ(irq_pin(2), 2),
- PINMUX_IRQ(irq_pin(3), 3),
- PINMUX_IRQ(irq_pin(4), 4),
- PINMUX_IRQ(irq_pin(5), 5),
- PINMUX_IRQ(irq_pin(6), 6),
- PINMUX_IRQ(irq_pin(7), 7),
- PINMUX_IRQ(irq_pin(8), 8),
- PINMUX_IRQ(irq_pin(9), 9),
- PINMUX_IRQ(irq_pin(10), 10),
- PINMUX_IRQ(irq_pin(11), 11),
- PINMUX_IRQ(irq_pin(12), 12),
- PINMUX_IRQ(irq_pin(13), 13),
- PINMUX_IRQ(irq_pin(14), 14),
- PINMUX_IRQ(irq_pin(15), 15),
- PINMUX_IRQ(irq_pin(16), 320),
- PINMUX_IRQ(irq_pin(17), 321),
- PINMUX_IRQ(irq_pin(18), 85),
- PINMUX_IRQ(irq_pin(19), 84),
- PINMUX_IRQ(irq_pin(20), 160),
- PINMUX_IRQ(irq_pin(21), 161),
- PINMUX_IRQ(irq_pin(22), 162),
- PINMUX_IRQ(irq_pin(23), 163),
- PINMUX_IRQ(irq_pin(24), 175),
- PINMUX_IRQ(irq_pin(25), 176),
- PINMUX_IRQ(irq_pin(26), 177),
- PINMUX_IRQ(irq_pin(27), 178),
- PINMUX_IRQ(irq_pin(28), 322),
- PINMUX_IRQ(irq_pin(29), 323),
- PINMUX_IRQ(irq_pin(30), 324),
- PINMUX_IRQ(irq_pin(31), 192),
- PINMUX_IRQ(irq_pin(32), 193),
- PINMUX_IRQ(irq_pin(33), 194),
- PINMUX_IRQ(irq_pin(34), 195),
- PINMUX_IRQ(irq_pin(35), 196),
- PINMUX_IRQ(irq_pin(36), 197),
- PINMUX_IRQ(irq_pin(37), 198),
- PINMUX_IRQ(irq_pin(38), 199),
- PINMUX_IRQ(irq_pin(39), 200),
- PINMUX_IRQ(irq_pin(40), 66),
- PINMUX_IRQ(irq_pin(41), 102),
- PINMUX_IRQ(irq_pin(42), 103),
- PINMUX_IRQ(irq_pin(43), 109),
- PINMUX_IRQ(irq_pin(44), 110),
- PINMUX_IRQ(irq_pin(45), 111),
- PINMUX_IRQ(irq_pin(46), 112),
- PINMUX_IRQ(irq_pin(47), 113),
- PINMUX_IRQ(irq_pin(48), 114),
- PINMUX_IRQ(irq_pin(49), 115),
- PINMUX_IRQ(irq_pin(50), 301),
- PINMUX_IRQ(irq_pin(51), 290),
- PINMUX_IRQ(irq_pin(52), 296),
- PINMUX_IRQ(irq_pin(53), 325),
- PINMUX_IRQ(irq_pin(54), 326),
- PINMUX_IRQ(irq_pin(55), 327),
- PINMUX_IRQ(irq_pin(56), 328),
- PINMUX_IRQ(irq_pin(57), 329),
+ PINMUX_IRQ(0), /* IRQ0 */
+ PINMUX_IRQ(1), /* IRQ1 */
+ PINMUX_IRQ(2), /* IRQ2 */
+ PINMUX_IRQ(3), /* IRQ3 */
+ PINMUX_IRQ(4), /* IRQ4 */
+ PINMUX_IRQ(5), /* IRQ5 */
+ PINMUX_IRQ(6), /* IRQ6 */
+ PINMUX_IRQ(7), /* IRQ7 */
+ PINMUX_IRQ(8), /* IRQ8 */
+ PINMUX_IRQ(9), /* IRQ9 */
+ PINMUX_IRQ(10), /* IRQ10 */
+ PINMUX_IRQ(11), /* IRQ11 */
+ PINMUX_IRQ(12), /* IRQ12 */
+ PINMUX_IRQ(13), /* IRQ13 */
+ PINMUX_IRQ(14), /* IRQ14 */
+ PINMUX_IRQ(15), /* IRQ15 */
+ PINMUX_IRQ(320), /* IRQ16 */
+ PINMUX_IRQ(321), /* IRQ17 */
+ PINMUX_IRQ(85), /* IRQ18 */
+ PINMUX_IRQ(84), /* IRQ19 */
+ PINMUX_IRQ(160), /* IRQ20 */
+ PINMUX_IRQ(161), /* IRQ21 */
+ PINMUX_IRQ(162), /* IRQ22 */
+ PINMUX_IRQ(163), /* IRQ23 */
+ PINMUX_IRQ(175), /* IRQ24 */
+ PINMUX_IRQ(176), /* IRQ25 */
+ PINMUX_IRQ(177), /* IRQ26 */
+ PINMUX_IRQ(178), /* IRQ27 */
+ PINMUX_IRQ(322), /* IRQ28 */
+ PINMUX_IRQ(323), /* IRQ29 */
+ PINMUX_IRQ(324), /* IRQ30 */
+ PINMUX_IRQ(192), /* IRQ31 */
+ PINMUX_IRQ(193), /* IRQ32 */
+ PINMUX_IRQ(194), /* IRQ33 */
+ PINMUX_IRQ(195), /* IRQ34 */
+ PINMUX_IRQ(196), /* IRQ35 */
+ PINMUX_IRQ(197), /* IRQ36 */
+ PINMUX_IRQ(198), /* IRQ37 */
+ PINMUX_IRQ(199), /* IRQ38 */
+ PINMUX_IRQ(200), /* IRQ39 */
+ PINMUX_IRQ(66), /* IRQ40 */
+ PINMUX_IRQ(102), /* IRQ41 */
+ PINMUX_IRQ(103), /* IRQ42 */
+ PINMUX_IRQ(109), /* IRQ43 */
+ PINMUX_IRQ(110), /* IRQ44 */
+ PINMUX_IRQ(111), /* IRQ45 */
+ PINMUX_IRQ(112), /* IRQ46 */
+ PINMUX_IRQ(113), /* IRQ47 */
+ PINMUX_IRQ(114), /* IRQ48 */
+ PINMUX_IRQ(115), /* IRQ49 */
+ PINMUX_IRQ(301), /* IRQ50 */
+ PINMUX_IRQ(290), /* IRQ51 */
+ PINMUX_IRQ(296), /* IRQ52 */
+ PINMUX_IRQ(325), /* IRQ53 */
+ PINMUX_IRQ(326), /* IRQ54 */
+ PINMUX_IRQ(327), /* IRQ55 */
+ PINMUX_IRQ(328), /* IRQ56 */
+ PINMUX_IRQ(329), /* IRQ57 */
};
#define PORTCR_PULMD_OFF (0 << 6)
@@ -2734,11 +2734,11 @@ const struct sh_pfc_soc_info r8a73a4_pinmux_info = {
.functions = pinmux_functions,
.nr_functions = ARRAY_SIZE(pinmux_functions),
- .cfg_regs = pinmux_config_regs,
- .data_regs = pinmux_data_regs,
+ .cfg_regs = pinmux_config_regs,
+ .data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
.gpio_irq = pinmux_irqs,
.gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
index 82ef1862dd1b..279e9dd442e4 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
@@ -3651,38 +3651,38 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
};
static const struct pinmux_irq pinmux_irqs[] = {
- PINMUX_IRQ(irq_pin(0), 2, 13), /* IRQ0A */
- PINMUX_IRQ(irq_pin(1), 20), /* IRQ1A */
- PINMUX_IRQ(irq_pin(2), 11, 12), /* IRQ2A */
- PINMUX_IRQ(irq_pin(3), 10, 14), /* IRQ3A */
- PINMUX_IRQ(irq_pin(4), 15, 172), /* IRQ4A */
- PINMUX_IRQ(irq_pin(5), 0, 1), /* IRQ5A */
- PINMUX_IRQ(irq_pin(6), 121, 173), /* IRQ6A */
- PINMUX_IRQ(irq_pin(7), 120, 209), /* IRQ7A */
- PINMUX_IRQ(irq_pin(8), 119), /* IRQ8A */
- PINMUX_IRQ(irq_pin(9), 118, 210), /* IRQ9A */
- PINMUX_IRQ(irq_pin(10), 19), /* IRQ10A */
- PINMUX_IRQ(irq_pin(11), 104), /* IRQ11A */
- PINMUX_IRQ(irq_pin(12), 42, 97), /* IRQ12A */
- PINMUX_IRQ(irq_pin(13), 64, 98), /* IRQ13A */
- PINMUX_IRQ(irq_pin(14), 63, 99), /* IRQ14A */
- PINMUX_IRQ(irq_pin(15), 62, 100), /* IRQ15A */
- PINMUX_IRQ(irq_pin(16), 68, 211), /* IRQ16A */
- PINMUX_IRQ(irq_pin(17), 69), /* IRQ17A */
- PINMUX_IRQ(irq_pin(18), 70), /* IRQ18A */
- PINMUX_IRQ(irq_pin(19), 71), /* IRQ19A */
- PINMUX_IRQ(irq_pin(20), 67), /* IRQ20A */
- PINMUX_IRQ(irq_pin(21), 202), /* IRQ21A */
- PINMUX_IRQ(irq_pin(22), 95), /* IRQ22A */
- PINMUX_IRQ(irq_pin(23), 96), /* IRQ23A */
- PINMUX_IRQ(irq_pin(24), 180), /* IRQ24A */
- PINMUX_IRQ(irq_pin(25), 38), /* IRQ25A */
- PINMUX_IRQ(irq_pin(26), 58, 81), /* IRQ26A */
- PINMUX_IRQ(irq_pin(27), 57, 168), /* IRQ27A */
- PINMUX_IRQ(irq_pin(28), 56, 169), /* IRQ28A */
- PINMUX_IRQ(irq_pin(29), 50, 170), /* IRQ29A */
- PINMUX_IRQ(irq_pin(30), 49, 171), /* IRQ30A */
- PINMUX_IRQ(irq_pin(31), 41, 167), /* IRQ31A */
+ PINMUX_IRQ(2, 13), /* IRQ0A */
+ PINMUX_IRQ(20), /* IRQ1A */
+ PINMUX_IRQ(11, 12), /* IRQ2A */
+ PINMUX_IRQ(10, 14), /* IRQ3A */
+ PINMUX_IRQ(15, 172), /* IRQ4A */
+ PINMUX_IRQ(0, 1), /* IRQ5A */
+ PINMUX_IRQ(121, 173), /* IRQ6A */
+ PINMUX_IRQ(120, 209), /* IRQ7A */
+ PINMUX_IRQ(119), /* IRQ8A */
+ PINMUX_IRQ(118, 210), /* IRQ9A */
+ PINMUX_IRQ(19), /* IRQ10A */
+ PINMUX_IRQ(104), /* IRQ11A */
+ PINMUX_IRQ(42, 97), /* IRQ12A */
+ PINMUX_IRQ(64, 98), /* IRQ13A */
+ PINMUX_IRQ(63, 99), /* IRQ14A */
+ PINMUX_IRQ(62, 100), /* IRQ15A */
+ PINMUX_IRQ(68, 211), /* IRQ16A */
+ PINMUX_IRQ(69), /* IRQ17A */
+ PINMUX_IRQ(70), /* IRQ18A */
+ PINMUX_IRQ(71), /* IRQ19A */
+ PINMUX_IRQ(67), /* IRQ20A */
+ PINMUX_IRQ(202), /* IRQ21A */
+ PINMUX_IRQ(95), /* IRQ22A */
+ PINMUX_IRQ(96), /* IRQ23A */
+ PINMUX_IRQ(180), /* IRQ24A */
+ PINMUX_IRQ(38), /* IRQ25A */
+ PINMUX_IRQ(58, 81), /* IRQ26A */
+ PINMUX_IRQ(57, 168), /* IRQ27A */
+ PINMUX_IRQ(56, 169), /* IRQ28A */
+ PINMUX_IRQ(50, 170), /* IRQ29A */
+ PINMUX_IRQ(49, 171), /* IRQ30A */
+ PINMUX_IRQ(41, 167), /* IRQ31A */
};
#define PORTnCR_PULMD_OFF (0 << 6)
@@ -3774,8 +3774,8 @@ const struct sh_pfc_soc_info r8a7740_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
.gpio_irq = pinmux_irqs,
.gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
index c7d610d1f3ef..bbd35dc1a0c4 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -4,6 +4,7 @@
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
* Copyright (C) 2013 Cogent Embedded, Inc.
+ * Copyright (C) 2015 Ulrich Hecht
*
* based on
* Copyright (C) 2011 Renesas Solutions Corp.
@@ -19,32 +20,37 @@
* GNU General Public License for more details.
*/
-#include <linux/platform_data/gpio-rcar.h>
+#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include "core.h"
#include "sh_pfc.h"
-#define PORT_GP_27(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
- PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
- PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
- PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
- PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
- PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
- PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
- PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx), \
- PORT_GP_1(bank, 26, fn, sfx)
+#define PORT_GP_PUP_1(bank, pin, fn, sfx) \
+ PORT_GP_CFG_1(bank, pin, fn, sfx, SH_PFC_PIN_CFG_PULL_UP)
+
+#define PORT_GP_PUP_27(bank, fn, sfx) \
+ PORT_GP_PUP_1(bank, 0, fn, sfx), PORT_GP_PUP_1(bank, 1, fn, sfx), \
+ PORT_GP_PUP_1(bank, 2, fn, sfx), PORT_GP_PUP_1(bank, 3, fn, sfx), \
+ PORT_GP_PUP_1(bank, 4, fn, sfx), PORT_GP_PUP_1(bank, 5, fn, sfx), \
+ PORT_GP_PUP_1(bank, 6, fn, sfx), PORT_GP_PUP_1(bank, 7, fn, sfx), \
+ PORT_GP_PUP_1(bank, 8, fn, sfx), PORT_GP_PUP_1(bank, 9, fn, sfx), \
+ PORT_GP_PUP_1(bank, 10, fn, sfx), PORT_GP_PUP_1(bank, 11, fn, sfx), \
+ PORT_GP_PUP_1(bank, 12, fn, sfx), PORT_GP_PUP_1(bank, 13, fn, sfx), \
+ PORT_GP_PUP_1(bank, 14, fn, sfx), PORT_GP_PUP_1(bank, 15, fn, sfx), \
+ PORT_GP_PUP_1(bank, 16, fn, sfx), PORT_GP_PUP_1(bank, 17, fn, sfx), \
+ PORT_GP_PUP_1(bank, 18, fn, sfx), PORT_GP_PUP_1(bank, 19, fn, sfx), \
+ PORT_GP_PUP_1(bank, 20, fn, sfx), PORT_GP_PUP_1(bank, 21, fn, sfx), \
+ PORT_GP_PUP_1(bank, 22, fn, sfx), PORT_GP_PUP_1(bank, 23, fn, sfx), \
+ PORT_GP_PUP_1(bank, 24, fn, sfx), PORT_GP_PUP_1(bank, 25, fn, sfx), \
+ PORT_GP_PUP_1(bank, 26, fn, sfx)
#define CPU_ALL_PORT(fn, sfx) \
- PORT_GP_32(0, fn, sfx), \
- PORT_GP_32(1, fn, sfx), \
- PORT_GP_32(2, fn, sfx), \
- PORT_GP_32(3, fn, sfx), \
- PORT_GP_27(4, fn, sfx)
+ PORT_GP_CFG_32(0, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
+ PORT_GP_CFG_32(1, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
+ PORT_GP_CFG_32(2, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
+ PORT_GP_CFG_32(3, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
+ PORT_GP_PUP_27(4, fn, sfx)
enum {
PINMUX_RESERVED = 0,
@@ -2905,8 +2911,222 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
{ },
};
+#define PUPR0 0x100
+#define PUPR1 0x104
+#define PUPR2 0x108
+#define PUPR3 0x10c
+#define PUPR4 0x110
+#define PUPR5 0x114
+
+static const struct {
+ u16 reg : 11;
+ u16 bit : 5;
+} pullups[] = {
+ [RCAR_GP_PIN(0, 6)] = { PUPR0, 0 }, /* A0 */
+ [RCAR_GP_PIN(0, 7)] = { PUPR0, 1 }, /* A1 */
+ [RCAR_GP_PIN(0, 8)] = { PUPR0, 2 }, /* A2 */
+ [RCAR_GP_PIN(0, 9)] = { PUPR0, 3 }, /* A3 */
+ [RCAR_GP_PIN(0, 10)] = { PUPR0, 4 }, /* A4 */
+ [RCAR_GP_PIN(0, 11)] = { PUPR0, 5 }, /* A5 */
+ [RCAR_GP_PIN(0, 12)] = { PUPR0, 6 }, /* A6 */
+ [RCAR_GP_PIN(0, 13)] = { PUPR0, 7 }, /* A7 */
+ [RCAR_GP_PIN(0, 14)] = { PUPR0, 8 }, /* A8 */
+ [RCAR_GP_PIN(0, 15)] = { PUPR0, 9 }, /* A9 */
+ [RCAR_GP_PIN(0, 16)] = { PUPR0, 10 }, /* A10 */
+ [RCAR_GP_PIN(0, 17)] = { PUPR0, 11 }, /* A11 */
+ [RCAR_GP_PIN(0, 18)] = { PUPR0, 12 }, /* A12 */
+ [RCAR_GP_PIN(0, 19)] = { PUPR0, 13 }, /* A13 */
+ [RCAR_GP_PIN(0, 20)] = { PUPR0, 14 }, /* A14 */
+ [RCAR_GP_PIN(0, 21)] = { PUPR0, 15 }, /* A15 */
+ [RCAR_GP_PIN(0, 22)] = { PUPR0, 16 }, /* A16 */
+ [RCAR_GP_PIN(0, 23)] = { PUPR0, 17 }, /* A17 */
+ [RCAR_GP_PIN(0, 24)] = { PUPR0, 18 }, /* A18 */
+ [RCAR_GP_PIN(0, 25)] = { PUPR0, 19 }, /* A19 */
+ [RCAR_GP_PIN(0, 26)] = { PUPR0, 20 }, /* A20 */
+ [RCAR_GP_PIN(0, 27)] = { PUPR0, 21 }, /* A21 */
+ [RCAR_GP_PIN(0, 28)] = { PUPR0, 22 }, /* A22 */
+ [RCAR_GP_PIN(0, 29)] = { PUPR0, 23 }, /* A23 */
+ [RCAR_GP_PIN(0, 30)] = { PUPR0, 24 }, /* A24 */
+ [RCAR_GP_PIN(0, 31)] = { PUPR0, 25 }, /* A25 */
+ [RCAR_GP_PIN(1, 3)] = { PUPR0, 26 }, /* /EX_CS0 */
+ [RCAR_GP_PIN(1, 4)] = { PUPR0, 27 }, /* /EX_CS1 */
+ [RCAR_GP_PIN(1, 5)] = { PUPR0, 28 }, /* /EX_CS2 */
+ [RCAR_GP_PIN(1, 6)] = { PUPR0, 29 }, /* /EX_CS3 */
+ [RCAR_GP_PIN(1, 7)] = { PUPR0, 30 }, /* /EX_CS4 */
+ [RCAR_GP_PIN(1, 8)] = { PUPR0, 31 }, /* /EX_CS5 */
+
+ [RCAR_GP_PIN(0, 0)] = { PUPR1, 0 }, /* /PRESETOUT */
+ [RCAR_GP_PIN(0, 5)] = { PUPR1, 1 }, /* /BS */
+ [RCAR_GP_PIN(1, 0)] = { PUPR1, 2 }, /* RD//WR */
+ [RCAR_GP_PIN(1, 1)] = { PUPR1, 3 }, /* /WE0 */
+ [RCAR_GP_PIN(1, 2)] = { PUPR1, 4 }, /* /WE1 */
+ [RCAR_GP_PIN(1, 11)] = { PUPR1, 5 }, /* EX_WAIT0 */
+ [RCAR_GP_PIN(1, 9)] = { PUPR1, 6 }, /* DREQ0 */
+ [RCAR_GP_PIN(1, 10)] = { PUPR1, 7 }, /* DACK0 */
+ [RCAR_GP_PIN(1, 12)] = { PUPR1, 8 }, /* IRQ0 */
+ [RCAR_GP_PIN(1, 13)] = { PUPR1, 9 }, /* IRQ1 */
+
+ [RCAR_GP_PIN(1, 22)] = { PUPR2, 0 }, /* DU0_DR0 */
+ [RCAR_GP_PIN(1, 23)] = { PUPR2, 1 }, /* DU0_DR1 */
+ [RCAR_GP_PIN(1, 24)] = { PUPR2, 2 }, /* DU0_DR2 */
+ [RCAR_GP_PIN(1, 25)] = { PUPR2, 3 }, /* DU0_DR3 */
+ [RCAR_GP_PIN(1, 26)] = { PUPR2, 4 }, /* DU0_DR4 */
+ [RCAR_GP_PIN(1, 27)] = { PUPR2, 5 }, /* DU0_DR5 */
+ [RCAR_GP_PIN(1, 28)] = { PUPR2, 6 }, /* DU0_DR6 */
+ [RCAR_GP_PIN(1, 29)] = { PUPR2, 7 }, /* DU0_DR7 */
+ [RCAR_GP_PIN(1, 30)] = { PUPR2, 8 }, /* DU0_DG0 */
+ [RCAR_GP_PIN(1, 31)] = { PUPR2, 9 }, /* DU0_DG1 */
+ [RCAR_GP_PIN(2, 0)] = { PUPR2, 10 }, /* DU0_DG2 */
+ [RCAR_GP_PIN(2, 1)] = { PUPR2, 11 }, /* DU0_DG3 */
+ [RCAR_GP_PIN(2, 2)] = { PUPR2, 12 }, /* DU0_DG4 */
+ [RCAR_GP_PIN(2, 3)] = { PUPR2, 13 }, /* DU0_DG5 */
+ [RCAR_GP_PIN(2, 4)] = { PUPR2, 14 }, /* DU0_DG6 */
+ [RCAR_GP_PIN(2, 5)] = { PUPR2, 15 }, /* DU0_DG7 */
+ [RCAR_GP_PIN(2, 6)] = { PUPR2, 16 }, /* DU0_DB0 */
+ [RCAR_GP_PIN(2, 7)] = { PUPR2, 17 }, /* DU0_DB1 */
+ [RCAR_GP_PIN(2, 8)] = { PUPR2, 18 }, /* DU0_DB2 */
+ [RCAR_GP_PIN(2, 9)] = { PUPR2, 19 }, /* DU0_DB3 */
+ [RCAR_GP_PIN(2, 10)] = { PUPR2, 20 }, /* DU0_DB4 */
+ [RCAR_GP_PIN(2, 11)] = { PUPR2, 21 }, /* DU0_DB5 */
+ [RCAR_GP_PIN(2, 12)] = { PUPR2, 22 }, /* DU0_DB6 */
+ [RCAR_GP_PIN(2, 13)] = { PUPR2, 23 }, /* DU0_DB7 */
+ [RCAR_GP_PIN(2, 14)] = { PUPR2, 24 }, /* DU0_DOTCLKIN */
+ [RCAR_GP_PIN(2, 15)] = { PUPR2, 25 }, /* DU0_DOTCLKOUT0 */
+ [RCAR_GP_PIN(2, 17)] = { PUPR2, 26 }, /* DU0_HSYNC */
+ [RCAR_GP_PIN(2, 18)] = { PUPR2, 27 }, /* DU0_VSYNC */
+ [RCAR_GP_PIN(2, 19)] = { PUPR2, 28 }, /* DU0_EXODDF */
+ [RCAR_GP_PIN(2, 20)] = { PUPR2, 29 }, /* DU0_DISP */
+ [RCAR_GP_PIN(2, 21)] = { PUPR2, 30 }, /* DU0_CDE */
+ [RCAR_GP_PIN(2, 16)] = { PUPR2, 31 }, /* DU0_DOTCLKOUT1 */
+
+ [RCAR_GP_PIN(3, 24)] = { PUPR3, 0 }, /* VI0_CLK */
+ [RCAR_GP_PIN(3, 25)] = { PUPR3, 1 }, /* VI0_CLKENB */
+ [RCAR_GP_PIN(3, 26)] = { PUPR3, 2 }, /* VI0_FIELD */
+ [RCAR_GP_PIN(3, 27)] = { PUPR3, 3 }, /* /VI0_HSYNC */
+ [RCAR_GP_PIN(3, 28)] = { PUPR3, 4 }, /* /VI0_VSYNC */
+ [RCAR_GP_PIN(3, 29)] = { PUPR3, 5 }, /* VI0_DATA0 */
+ [RCAR_GP_PIN(3, 30)] = { PUPR3, 6 }, /* VI0_DATA1 */
+ [RCAR_GP_PIN(3, 31)] = { PUPR3, 7 }, /* VI0_DATA2 */
+ [RCAR_GP_PIN(4, 0)] = { PUPR3, 8 }, /* VI0_DATA3 */
+ [RCAR_GP_PIN(4, 1)] = { PUPR3, 9 }, /* VI0_DATA4 */
+ [RCAR_GP_PIN(4, 2)] = { PUPR3, 10 }, /* VI0_DATA5 */
+ [RCAR_GP_PIN(4, 3)] = { PUPR3, 11 }, /* VI0_DATA6 */
+ [RCAR_GP_PIN(4, 4)] = { PUPR3, 12 }, /* VI0_DATA7 */
+ [RCAR_GP_PIN(4, 5)] = { PUPR3, 13 }, /* VI0_G2 */
+ [RCAR_GP_PIN(4, 6)] = { PUPR3, 14 }, /* VI0_G3 */
+ [RCAR_GP_PIN(4, 7)] = { PUPR3, 15 }, /* VI0_G4 */
+ [RCAR_GP_PIN(4, 8)] = { PUPR3, 16 }, /* VI0_G5 */
+ [RCAR_GP_PIN(4, 21)] = { PUPR3, 17 }, /* VI1_DATA12 */
+ [RCAR_GP_PIN(4, 22)] = { PUPR3, 18 }, /* VI1_DATA13 */
+ [RCAR_GP_PIN(4, 23)] = { PUPR3, 19 }, /* VI1_DATA14 */
+ [RCAR_GP_PIN(4, 24)] = { PUPR3, 20 }, /* VI1_DATA15 */
+ [RCAR_GP_PIN(4, 9)] = { PUPR3, 21 }, /* ETH_REF_CLK */
+ [RCAR_GP_PIN(4, 10)] = { PUPR3, 22 }, /* ETH_TXD0 */
+ [RCAR_GP_PIN(4, 11)] = { PUPR3, 23 }, /* ETH_TXD1 */
+ [RCAR_GP_PIN(4, 12)] = { PUPR3, 24 }, /* ETH_CRS_DV */
+ [RCAR_GP_PIN(4, 13)] = { PUPR3, 25 }, /* ETH_TX_EN */
+ [RCAR_GP_PIN(4, 14)] = { PUPR3, 26 }, /* ETH_RX_ER */
+ [RCAR_GP_PIN(4, 15)] = { PUPR3, 27 }, /* ETH_RXD0 */
+ [RCAR_GP_PIN(4, 16)] = { PUPR3, 28 }, /* ETH_RXD1 */
+ [RCAR_GP_PIN(4, 17)] = { PUPR3, 29 }, /* ETH_MDC */
+ [RCAR_GP_PIN(4, 18)] = { PUPR3, 30 }, /* ETH_MDIO */
+ [RCAR_GP_PIN(4, 19)] = { PUPR3, 31 }, /* ETH_LINK */
+
+ [RCAR_GP_PIN(3, 6)] = { PUPR4, 0 }, /* SSI_SCK012 */
+ [RCAR_GP_PIN(3, 7)] = { PUPR4, 1 }, /* SSI_WS012 */
+ [RCAR_GP_PIN(3, 10)] = { PUPR4, 2 }, /* SSI_SDATA0 */
+ [RCAR_GP_PIN(3, 9)] = { PUPR4, 3 }, /* SSI_SDATA1 */
+ [RCAR_GP_PIN(3, 8)] = { PUPR4, 4 }, /* SSI_SDATA2 */
+ [RCAR_GP_PIN(3, 2)] = { PUPR4, 5 }, /* SSI_SCK34 */
+ [RCAR_GP_PIN(3, 3)] = { PUPR4, 6 }, /* SSI_WS34 */
+ [RCAR_GP_PIN(3, 5)] = { PUPR4, 7 }, /* SSI_SDATA3 */
+ [RCAR_GP_PIN(3, 4)] = { PUPR4, 8 }, /* SSI_SDATA4 */
+ [RCAR_GP_PIN(2, 31)] = { PUPR4, 9 }, /* SSI_SCK5 */
+ [RCAR_GP_PIN(3, 0)] = { PUPR4, 10 }, /* SSI_WS5 */
+ [RCAR_GP_PIN(3, 1)] = { PUPR4, 11 }, /* SSI_SDATA5 */
+ [RCAR_GP_PIN(2, 28)] = { PUPR4, 12 }, /* SSI_SCK6 */
+ [RCAR_GP_PIN(2, 29)] = { PUPR4, 13 }, /* SSI_WS6 */
+ [RCAR_GP_PIN(2, 30)] = { PUPR4, 14 }, /* SSI_SDATA6 */
+ [RCAR_GP_PIN(2, 24)] = { PUPR4, 15 }, /* SSI_SCK78 */
+ [RCAR_GP_PIN(2, 25)] = { PUPR4, 16 }, /* SSI_WS78 */
+ [RCAR_GP_PIN(2, 27)] = { PUPR4, 17 }, /* SSI_SDATA7 */
+ [RCAR_GP_PIN(2, 26)] = { PUPR4, 18 }, /* SSI_SDATA8 */
+ [RCAR_GP_PIN(3, 23)] = { PUPR4, 19 }, /* TCLK0 */
+ [RCAR_GP_PIN(3, 11)] = { PUPR4, 20 }, /* SD0_CLK */
+ [RCAR_GP_PIN(3, 12)] = { PUPR4, 21 }, /* SD0_CMD */
+ [RCAR_GP_PIN(3, 13)] = { PUPR4, 22 }, /* SD0_DAT0 */
+ [RCAR_GP_PIN(3, 14)] = { PUPR4, 23 }, /* SD0_DAT1 */
+ [RCAR_GP_PIN(3, 15)] = { PUPR4, 24 }, /* SD0_DAT2 */
+ [RCAR_GP_PIN(3, 16)] = { PUPR4, 25 }, /* SD0_DAT3 */
+ [RCAR_GP_PIN(3, 17)] = { PUPR4, 26 }, /* SD0_CD */
+ [RCAR_GP_PIN(3, 18)] = { PUPR4, 27 }, /* SD0_WP */
+ [RCAR_GP_PIN(2, 22)] = { PUPR4, 28 }, /* AUDIO_CLKA */
+ [RCAR_GP_PIN(2, 23)] = { PUPR4, 29 }, /* AUDIO_CLKB */
+ [RCAR_GP_PIN(1, 14)] = { PUPR4, 30 }, /* IRQ2 */
+ [RCAR_GP_PIN(1, 15)] = { PUPR4, 31 }, /* IRQ3 */
+
+ [RCAR_GP_PIN(0, 1)] = { PUPR5, 0 }, /* PENC0 */
+ [RCAR_GP_PIN(0, 2)] = { PUPR5, 1 }, /* PENC1 */
+ [RCAR_GP_PIN(0, 3)] = { PUPR5, 2 }, /* USB_OVC0 */
+ [RCAR_GP_PIN(0, 4)] = { PUPR5, 3 }, /* USB_OVC1 */
+ [RCAR_GP_PIN(1, 16)] = { PUPR5, 4 }, /* SCIF_CLK */
+ [RCAR_GP_PIN(1, 17)] = { PUPR5, 5 }, /* TX0 */
+ [RCAR_GP_PIN(1, 18)] = { PUPR5, 6 }, /* RX0 */
+ [RCAR_GP_PIN(1, 19)] = { PUPR5, 7 }, /* SCK0 */
+ [RCAR_GP_PIN(1, 20)] = { PUPR5, 8 }, /* /CTS0 */
+ [RCAR_GP_PIN(1, 21)] = { PUPR5, 9 }, /* /RTS0 */
+ [RCAR_GP_PIN(3, 19)] = { PUPR5, 10 }, /* HSPI_CLK0 */
+ [RCAR_GP_PIN(3, 20)] = { PUPR5, 11 }, /* /HSPI_CS0 */
+ [RCAR_GP_PIN(3, 21)] = { PUPR5, 12 }, /* HSPI_RX0 */
+ [RCAR_GP_PIN(3, 22)] = { PUPR5, 13 }, /* HSPI_TX0 */
+ [RCAR_GP_PIN(4, 20)] = { PUPR5, 14 }, /* ETH_MAGIC */
+ [RCAR_GP_PIN(4, 25)] = { PUPR5, 15 }, /* AVS1 */
+ [RCAR_GP_PIN(4, 26)] = { PUPR5, 16 }, /* AVS2 */
+};
+
+static unsigned int r8a7778_pinmux_get_bias(struct sh_pfc *pfc,
+ unsigned int pin)
+{
+ void __iomem *addr;
+
+ if (WARN_ON_ONCE(!pullups[pin].reg))
+ return PIN_CONFIG_BIAS_DISABLE;
+
+ addr = pfc->windows->virt + pullups[pin].reg;
+
+ if (ioread32(addr) & BIT(pullups[pin].bit))
+ return PIN_CONFIG_BIAS_PULL_UP;
+ else
+ return PIN_CONFIG_BIAS_DISABLE;
+}
+
+static void r8a7778_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
+ unsigned int bias)
+{
+ void __iomem *addr;
+ u32 value;
+ u32 bit;
+
+ if (WARN_ON_ONCE(!pullups[pin].reg))
+ return;
+
+ addr = pfc->windows->virt + pullups[pin].reg;
+ bit = BIT(pullups[pin].bit);
+
+ value = ioread32(addr) & ~bit;
+ if (bias == PIN_CONFIG_BIAS_PULL_UP)
+ value |= bit;
+ iowrite32(value, addr);
+}
+
+static const struct sh_pfc_soc_operations r8a7778_pfc_ops = {
+ .get_bias = r8a7778_pinmux_get_bias,
+ .set_bias = r8a7778_pinmux_set_bias,
+};
+
const struct sh_pfc_soc_info r8a7778_pinmux_info = {
.name = "r8a7778_pfc",
+ .ops = &r8a7778_pfc_ops,
.unlock_reg = 0xfffc0000, /* PMMR */
@@ -2923,6 +3143,6 @@ const struct sh_pfc_soc_info r8a7778_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
index f5c01e1e2615..ed4e0788035c 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
@@ -20,7 +20,6 @@
*/
#include <linux/kernel.h>
-#include <linux/platform_data/gpio-rcar.h>
#include "sh_pfc.h"
@@ -620,18 +619,18 @@ static const u16 pinmux_data[] = {
PINMUX_DATA(USB_PENC1_MARK, FN_USB_PENC1),
PINMUX_IPSR_DATA(IP0_2_0, USB_PENC2),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, SCK0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP0_2_0, SCK0, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP0_2_0, PWM1),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, PWMFSW0, SEL_PWMFSW_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, SCIF_CLK, SEL_SCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, TCLK0_C, SEL_TMU0_2),
+ PINMUX_IPSR_MSEL(IP0_2_0, PWMFSW0, SEL_PWMFSW_0),
+ PINMUX_IPSR_MSEL(IP0_2_0, SCIF_CLK, SEL_SCIF_0),
+ PINMUX_IPSR_MSEL(IP0_2_0, TCLK0_C, SEL_TMU0_2),
PINMUX_IPSR_DATA(IP0_5_3, BS),
PINMUX_IPSR_DATA(IP0_5_3, SD1_DAT2),
PINMUX_IPSR_DATA(IP0_5_3, MMC0_D2),
PINMUX_IPSR_DATA(IP0_5_3, FD2),
PINMUX_IPSR_DATA(IP0_5_3, ATADIR0),
PINMUX_IPSR_DATA(IP0_5_3, SDSELF),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_3, HCTS1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP0_5_3, HCTS1, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP0_5_3, TX4_C),
PINMUX_IPSR_DATA(IP0_7_6, A0),
PINMUX_IPSR_DATA(IP0_7_6, SD1_DAT3),
@@ -641,37 +640,37 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP0_9_8, TX5_D),
PINMUX_IPSR_DATA(IP0_9_8, HSPI_TX2_B),
PINMUX_IPSR_DATA(IP0_11_10, A21),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_10, SCK5_D, SEL_SCIF5_3),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_10, HSPI_CLK2_B, SEL_HSPI2_1),
+ PINMUX_IPSR_MSEL(IP0_11_10, SCK5_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MSEL(IP0_11_10, HSPI_CLK2_B, SEL_HSPI2_1),
PINMUX_IPSR_DATA(IP0_13_12, A22),
- PINMUX_IPSR_MODSEL_DATA(IP0_13_12, RX5_D, SEL_SCIF5_3),
- PINMUX_IPSR_MODSEL_DATA(IP0_13_12, HSPI_RX2_B, SEL_HSPI2_1),
+ PINMUX_IPSR_MSEL(IP0_13_12, RX5_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MSEL(IP0_13_12, HSPI_RX2_B, SEL_HSPI2_1),
PINMUX_IPSR_DATA(IP0_13_12, VI1_R0),
PINMUX_IPSR_DATA(IP0_15_14, A23),
PINMUX_IPSR_DATA(IP0_15_14, FCLE),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_14, HSPI_CLK2, SEL_HSPI2_0),
+ PINMUX_IPSR_MSEL(IP0_15_14, HSPI_CLK2, SEL_HSPI2_0),
PINMUX_IPSR_DATA(IP0_15_14, VI1_R1),
PINMUX_IPSR_DATA(IP0_18_16, A24),
PINMUX_IPSR_DATA(IP0_18_16, SD1_CD),
PINMUX_IPSR_DATA(IP0_18_16, MMC0_D4),
PINMUX_IPSR_DATA(IP0_18_16, FD4),
- PINMUX_IPSR_MODSEL_DATA(IP0_18_16, HSPI_CS2, SEL_HSPI2_0),
+ PINMUX_IPSR_MSEL(IP0_18_16, HSPI_CS2, SEL_HSPI2_0),
PINMUX_IPSR_DATA(IP0_18_16, VI1_R2),
- PINMUX_IPSR_MODSEL_DATA(IP0_18_16, SSI_WS78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP0_18_16, SSI_WS78_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP0_22_19, A25),
PINMUX_IPSR_DATA(IP0_22_19, SD1_WP),
PINMUX_IPSR_DATA(IP0_22_19, MMC0_D5),
PINMUX_IPSR_DATA(IP0_22_19, FD5),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_19, HSPI_RX2, SEL_HSPI2_0),
+ PINMUX_IPSR_MSEL(IP0_22_19, HSPI_RX2, SEL_HSPI2_0),
PINMUX_IPSR_DATA(IP0_22_19, VI1_R3),
PINMUX_IPSR_DATA(IP0_22_19, TX5_B),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_19, SSI_SDATA7_B, SEL_SSI7_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_19, CTS0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP0_22_19, SSI_SDATA7_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP0_22_19, CTS0_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP0_24_23, CLKOUT),
PINMUX_IPSR_DATA(IP0_24_23, TX3C_IRDA_TX_C),
PINMUX_IPSR_DATA(IP0_24_23, PWM0_B),
PINMUX_IPSR_DATA(IP0_25, CS0),
- PINMUX_IPSR_MODSEL_DATA(IP0_25, HSPI_CS2_B, SEL_HSPI2_1),
+ PINMUX_IPSR_MSEL(IP0_25, HSPI_CS2_B, SEL_HSPI2_1),
PINMUX_IPSR_DATA(IP0_27_26, CS1_A26),
PINMUX_IPSR_DATA(IP0_27_26, HSPI_TX2),
PINMUX_IPSR_DATA(IP0_27_26, SDSELF_B),
@@ -679,11 +678,11 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP0_30_28, FWE),
PINMUX_IPSR_DATA(IP0_30_28, ATAG0),
PINMUX_IPSR_DATA(IP0_30_28, VI1_R7),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_28, HRTS1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_28, RX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP0_30_28, HRTS1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP0_30_28, RX4_C, SEL_SCIF4_2),
PINMUX_IPSR_DATA(IP1_1_0, EX_CS0),
- PINMUX_IPSR_MODSEL_DATA(IP1_1_0, RX3_C_IRDA_RX_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MSEL(IP1_1_0, RX3_C_IRDA_RX_C, SEL_SCIF3_2),
PINMUX_IPSR_DATA(IP1_1_0, MMC0_D6),
PINMUX_IPSR_DATA(IP1_1_0, FD6),
PINMUX_IPSR_DATA(IP1_3_2, EX_CS1),
@@ -700,45 +699,45 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP1_10_7, FRE),
PINMUX_IPSR_DATA(IP1_10_7, ATACS10),
PINMUX_IPSR_DATA(IP1_10_7, VI1_R4),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_7, RX5_B, SEL_SCIF5_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_7, HSCK1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_7, SSI_SDATA8_B, SEL_SSI8_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_7, RTS0_B_TANS_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_7, SSI_SDATA9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP1_10_7, RX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP1_10_7, HSCK1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP1_10_7, SSI_SDATA8_B, SEL_SSI8_1),
+ PINMUX_IPSR_MSEL(IP1_10_7, RTS0_B_TANS_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP1_10_7, SSI_SDATA9, SEL_SSI9_0),
PINMUX_IPSR_DATA(IP1_14_11, EX_CS4),
PINMUX_IPSR_DATA(IP1_14_11, SD1_DAT0),
PINMUX_IPSR_DATA(IP1_14_11, MMC0_D0),
PINMUX_IPSR_DATA(IP1_14_11, FD0),
PINMUX_IPSR_DATA(IP1_14_11, ATARD0),
PINMUX_IPSR_DATA(IP1_14_11, VI1_R5),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_11, SCK5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP1_14_11, SCK5_B, SEL_SCIF5_1),
PINMUX_IPSR_DATA(IP1_14_11, HTX1),
PINMUX_IPSR_DATA(IP1_14_11, TX2_E),
PINMUX_IPSR_DATA(IP1_14_11, TX0_B),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_11, SSI_SCK9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP1_14_11, SSI_SCK9, SEL_SSI9_0),
PINMUX_IPSR_DATA(IP1_18_15, EX_CS5),
PINMUX_IPSR_DATA(IP1_18_15, SD1_DAT1),
PINMUX_IPSR_DATA(IP1_18_15, MMC0_D1),
PINMUX_IPSR_DATA(IP1_18_15, FD1),
PINMUX_IPSR_DATA(IP1_18_15, ATAWR0),
PINMUX_IPSR_DATA(IP1_18_15, VI1_R6),
- PINMUX_IPSR_MODSEL_DATA(IP1_18_15, HRX1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_18_15, RX2_E, SEL_SCIF2_4),
- PINMUX_IPSR_MODSEL_DATA(IP1_18_15, RX0_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_18_15, SSI_WS9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP1_18_15, HRX1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP1_18_15, RX2_E, SEL_SCIF2_4),
+ PINMUX_IPSR_MSEL(IP1_18_15, RX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP1_18_15, SSI_WS9, SEL_SSI9_0),
PINMUX_IPSR_DATA(IP1_20_19, MLB_CLK),
PINMUX_IPSR_DATA(IP1_20_19, PWM2),
- PINMUX_IPSR_MODSEL_DATA(IP1_20_19, SCK4, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP1_20_19, SCK4, SEL_SCIF4_0),
PINMUX_IPSR_DATA(IP1_22_21, MLB_SIG),
PINMUX_IPSR_DATA(IP1_22_21, PWM3),
PINMUX_IPSR_DATA(IP1_22_21, TX4),
PINMUX_IPSR_DATA(IP1_24_23, MLB_DAT),
PINMUX_IPSR_DATA(IP1_24_23, PWM4),
- PINMUX_IPSR_MODSEL_DATA(IP1_24_23, RX4, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP1_24_23, RX4, SEL_SCIF4_0),
PINMUX_IPSR_DATA(IP1_28_25, HTX0),
PINMUX_IPSR_DATA(IP1_28_25, TX1),
PINMUX_IPSR_DATA(IP1_28_25, SDATA),
- PINMUX_IPSR_MODSEL_DATA(IP1_28_25, CTS0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP1_28_25, CTS0_C, SEL_SCIF0_2),
PINMUX_IPSR_DATA(IP1_28_25, SUB_TCK),
PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE2),
PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE10),
@@ -746,39 +745,39 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE26),
PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE34),
- PINMUX_IPSR_MODSEL_DATA(IP2_3_0, HRX0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_3_0, RX1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP2_3_0, HRX0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP2_3_0, RX1, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP2_3_0, SCKZ),
- PINMUX_IPSR_MODSEL_DATA(IP2_3_0, RTS0_C_TANS_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP2_3_0, RTS0_C_TANS_C, SEL_SCIF0_2),
PINMUX_IPSR_DATA(IP2_3_0, SUB_TDI),
PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE3),
PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE11),
PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE19),
PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE27),
PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE35),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_4, HSCK0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_4, SCK1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP2_7_4, HSCK0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP2_7_4, SCK1, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP2_7_4, MTS),
PINMUX_IPSR_DATA(IP2_7_4, PWM5),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_4, SCK0_C, SEL_SCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_4, SSI_SDATA9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP2_7_4, SCK0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP2_7_4, SSI_SDATA9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP2_7_4, SUB_TDO),
PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE0),
PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE8),
PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE16),
PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE24),
PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE32),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_8, HCTS0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_8, CTS1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP2_11_8, HCTS0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP2_11_8, CTS1, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP2_11_8, STM),
PINMUX_IPSR_DATA(IP2_11_8, PWM0_D),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_8, RX0_C, SEL_SCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_8, SCIF_CLK_C, SEL_SCIF_2),
+ PINMUX_IPSR_MSEL(IP2_11_8, RX0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP2_11_8, SCIF_CLK_C, SEL_SCIF_2),
PINMUX_IPSR_DATA(IP2_11_8, SUB_TRST),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_8, TCLK1_B, SEL_TMU1_1),
+ PINMUX_IPSR_MSEL(IP2_11_8, TCLK1_B, SEL_TMU1_1),
PINMUX_IPSR_DATA(IP2_11_8, CC5_OSCOUT),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_12, HRTS0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_12, RTS1_TANS, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP2_15_12, HRTS0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP2_15_12, RTS1_TANS, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP2_15_12, MDATA),
PINMUX_IPSR_DATA(IP2_15_12, TX0_C),
PINMUX_IPSR_DATA(IP2_15_12, SUB_TMS),
@@ -789,17 +788,17 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP2_15_12, CC5_STATE33),
PINMUX_IPSR_DATA(IP2_18_16, DU0_DR0),
PINMUX_IPSR_DATA(IP2_18_16, LCDOUT0),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, DREQ0, SEL_EXBUS0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, GPS_CLK_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP2_18_16, DREQ0, SEL_EXBUS0_0),
+ PINMUX_IPSR_MSEL(IP2_18_16, GPS_CLK_B, SEL_GPS_1),
PINMUX_IPSR_DATA(IP2_18_16, AUDATA0),
PINMUX_IPSR_DATA(IP2_18_16, TX5_C),
PINMUX_IPSR_DATA(IP2_21_19, DU0_DR1),
PINMUX_IPSR_DATA(IP2_21_19, LCDOUT1),
PINMUX_IPSR_DATA(IP2_21_19, DACK0),
PINMUX_IPSR_DATA(IP2_21_19, DRACK0),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_19, GPS_SIGN_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP2_21_19, GPS_SIGN_B, SEL_GPS_1),
PINMUX_IPSR_DATA(IP2_21_19, AUDATA1),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_19, RX5_C, SEL_SCIF5_2),
+ PINMUX_IPSR_MSEL(IP2_21_19, RX5_C, SEL_SCIF5_2),
PINMUX_IPSR_DATA(IP2_22, DU0_DR2),
PINMUX_IPSR_DATA(IP2_22, LCDOUT2),
PINMUX_IPSR_DATA(IP2_23, DU0_DR3),
@@ -814,14 +813,14 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP2_27, LCDOUT7),
PINMUX_IPSR_DATA(IP2_30_28, DU0_DG0),
PINMUX_IPSR_DATA(IP2_30_28, LCDOUT8),
- PINMUX_IPSR_MODSEL_DATA(IP2_30_28, DREQ1, SEL_EXBUS1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_30_28, SCL2, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP2_30_28, DREQ1, SEL_EXBUS1_0),
+ PINMUX_IPSR_MSEL(IP2_30_28, SCL2, SEL_I2C2_0),
PINMUX_IPSR_DATA(IP2_30_28, AUDATA2),
PINMUX_IPSR_DATA(IP3_2_0, DU0_DG1),
PINMUX_IPSR_DATA(IP3_2_0, LCDOUT9),
PINMUX_IPSR_DATA(IP3_2_0, DACK1),
- PINMUX_IPSR_MODSEL_DATA(IP3_2_0, SDA2, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP3_2_0, SDA2, SEL_I2C2_0),
PINMUX_IPSR_DATA(IP3_2_0, AUDATA3),
PINMUX_IPSR_DATA(IP3_3, DU0_DG2),
PINMUX_IPSR_DATA(IP3_3, LCDOUT10),
@@ -838,16 +837,16 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP3_11_9, DU0_DB0),
PINMUX_IPSR_DATA(IP3_11_9, LCDOUT16),
PINMUX_IPSR_DATA(IP3_11_9, EX_WAIT1),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, SCL1, SEL_I2C1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, TCLK1, SEL_TMU1_0),
+ PINMUX_IPSR_MSEL(IP3_11_9, SCL1, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP3_11_9, TCLK1, SEL_TMU1_0),
PINMUX_IPSR_DATA(IP3_11_9, AUDATA4),
PINMUX_IPSR_DATA(IP3_14_12, DU0_DB1),
PINMUX_IPSR_DATA(IP3_14_12, LCDOUT17),
PINMUX_IPSR_DATA(IP3_14_12, EX_WAIT2),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, SDA1, SEL_I2C1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, GPS_MAG_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP3_14_12, SDA1, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP3_14_12, GPS_MAG_B, SEL_GPS_1),
PINMUX_IPSR_DATA(IP3_14_12, AUDATA5),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, SCK5_C, SEL_SCIF5_2),
+ PINMUX_IPSR_MSEL(IP3_14_12, SCK5_C, SEL_SCIF5_2),
PINMUX_IPSR_DATA(IP3_15, DU0_DB2),
PINMUX_IPSR_DATA(IP3_15, LCDOUT18),
PINMUX_IPSR_DATA(IP3_16, DU0_DB3),
@@ -863,14 +862,14 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP3_22_21, DU0_DOTCLKIN),
PINMUX_IPSR_DATA(IP3_22_21, QSTVA_QVS),
PINMUX_IPSR_DATA(IP3_22_21, TX3_D_IRDA_TX_D),
- PINMUX_IPSR_MODSEL_DATA(IP3_22_21, SCL3_B, SEL_I2C3_1),
+ PINMUX_IPSR_MSEL(IP3_22_21, SCL3_B, SEL_I2C3_1),
PINMUX_IPSR_DATA(IP3_23, DU0_DOTCLKOUT0),
PINMUX_IPSR_DATA(IP3_23, QCLK),
PINMUX_IPSR_DATA(IP3_26_24, DU0_DOTCLKOUT1),
PINMUX_IPSR_DATA(IP3_26_24, QSTVB_QVE),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, RX3_D_IRDA_RX_D, SEL_SCIF3_3),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, SDA3_B, SEL_I2C3_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, SDA2_C, SEL_I2C2_2),
+ PINMUX_IPSR_MSEL(IP3_26_24, RX3_D_IRDA_RX_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MSEL(IP3_26_24, SDA3_B, SEL_I2C3_1),
+ PINMUX_IPSR_MSEL(IP3_26_24, SDA2_C, SEL_I2C2_2),
PINMUX_IPSR_DATA(IP3_26_24, DACK0_B),
PINMUX_IPSR_DATA(IP3_26_24, DRACK0_B),
PINMUX_IPSR_DATA(IP3_27, DU0_EXHSYNC_DU0_HSYNC),
@@ -881,34 +880,34 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP3_31_29, QCPV_QDE),
PINMUX_IPSR_DATA(IP3_31_29, CAN1_TX),
PINMUX_IPSR_DATA(IP3_31_29, TX2_C),
- PINMUX_IPSR_MODSEL_DATA(IP3_31_29, SCL2_C, SEL_I2C2_2),
+ PINMUX_IPSR_MSEL(IP3_31_29, SCL2_C, SEL_I2C2_2),
PINMUX_IPSR_DATA(IP3_31_29, REMOCON),
PINMUX_IPSR_DATA(IP4_1_0, DU0_DISP),
PINMUX_IPSR_DATA(IP4_1_0, QPOLA),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, CAN_CLK_C, SEL_CANCLK_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SCK2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP4_1_0, CAN_CLK_C, SEL_CANCLK_2),
+ PINMUX_IPSR_MSEL(IP4_1_0, SCK2_C, SEL_SCIF2_2),
PINMUX_IPSR_DATA(IP4_4_2, DU0_CDE),
PINMUX_IPSR_DATA(IP4_4_2, QPOLB),
PINMUX_IPSR_DATA(IP4_4_2, CAN1_RX),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, RX2_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, DREQ0_B, SEL_EXBUS0_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SSI_SCK78_B, SEL_SSI7_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SCK0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP4_4_2, RX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP4_4_2, DREQ0_B, SEL_EXBUS0_1),
+ PINMUX_IPSR_MSEL(IP4_4_2, SSI_SCK78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP4_4_2, SCK0_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP4_7_5, DU1_DR0),
PINMUX_IPSR_DATA(IP4_7_5, VI2_DATA0_VI2_B0),
PINMUX_IPSR_DATA(IP4_7_5, PWM6),
PINMUX_IPSR_DATA(IP4_7_5, SD3_CLK),
PINMUX_IPSR_DATA(IP4_7_5, TX3_E_IRDA_TX_E),
PINMUX_IPSR_DATA(IP4_7_5, AUDCK),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, PWMFSW0_B, SEL_PWMFSW_1),
+ PINMUX_IPSR_MSEL(IP4_7_5, PWMFSW0_B, SEL_PWMFSW_1),
PINMUX_IPSR_DATA(IP4_10_8, DU1_DR1),
PINMUX_IPSR_DATA(IP4_10_8, VI2_DATA1_VI2_B1),
PINMUX_IPSR_DATA(IP4_10_8, PWM0),
PINMUX_IPSR_DATA(IP4_10_8, SD3_CMD),
- PINMUX_IPSR_MODSEL_DATA(IP4_10_8, RX3_E_IRDA_RX_E, SEL_SCIF3_4),
+ PINMUX_IPSR_MSEL(IP4_10_8, RX3_E_IRDA_RX_E, SEL_SCIF3_4),
PINMUX_IPSR_DATA(IP4_10_8, AUDSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP4_10_8, CTS0_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP4_10_8, CTS0_D, SEL_SCIF0_3),
PINMUX_IPSR_DATA(IP4_11, DU1_DR2),
PINMUX_IPSR_DATA(IP4_11, VI2_G0),
PINMUX_IPSR_DATA(IP4_12, DU1_DR3),
@@ -923,18 +922,18 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP4_16, VI2_G5),
PINMUX_IPSR_DATA(IP4_19_17, DU1_DG0),
PINMUX_IPSR_DATA(IP4_19_17, VI2_DATA2_VI2_B2),
- PINMUX_IPSR_MODSEL_DATA(IP4_19_17, SCL1_B, SEL_I2C1_1),
+ PINMUX_IPSR_MSEL(IP4_19_17, SCL1_B, SEL_I2C1_1),
PINMUX_IPSR_DATA(IP4_19_17, SD3_DAT2),
- PINMUX_IPSR_MODSEL_DATA(IP4_19_17, SCK3_E, SEL_SCIF3_4),
+ PINMUX_IPSR_MSEL(IP4_19_17, SCK3_E, SEL_SCIF3_4),
PINMUX_IPSR_DATA(IP4_19_17, AUDATA6),
PINMUX_IPSR_DATA(IP4_19_17, TX0_D),
PINMUX_IPSR_DATA(IP4_22_20, DU1_DG1),
PINMUX_IPSR_DATA(IP4_22_20, VI2_DATA3_VI2_B3),
- PINMUX_IPSR_MODSEL_DATA(IP4_22_20, SDA1_B, SEL_I2C1_1),
+ PINMUX_IPSR_MSEL(IP4_22_20, SDA1_B, SEL_I2C1_1),
PINMUX_IPSR_DATA(IP4_22_20, SD3_DAT3),
- PINMUX_IPSR_MODSEL_DATA(IP4_22_20, SCK5, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP4_22_20, SCK5, SEL_SCIF5_0),
PINMUX_IPSR_DATA(IP4_22_20, AUDATA7),
- PINMUX_IPSR_MODSEL_DATA(IP4_22_20, RX0_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP4_22_20, RX0_D, SEL_SCIF0_3),
PINMUX_IPSR_DATA(IP4_23, DU1_DG2),
PINMUX_IPSR_DATA(IP4_23, VI2_G6),
PINMUX_IPSR_DATA(IP4_24, DU1_DG3),
@@ -949,17 +948,17 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP4_28, VI2_R3),
PINMUX_IPSR_DATA(IP4_31_29, DU1_DB0),
PINMUX_IPSR_DATA(IP4_31_29, VI2_DATA4_VI2_B4),
- PINMUX_IPSR_MODSEL_DATA(IP4_31_29, SCL2_B, SEL_I2C2_1),
+ PINMUX_IPSR_MSEL(IP4_31_29, SCL2_B, SEL_I2C2_1),
PINMUX_IPSR_DATA(IP4_31_29, SD3_DAT0),
PINMUX_IPSR_DATA(IP4_31_29, TX5),
- PINMUX_IPSR_MODSEL_DATA(IP4_31_29, SCK0_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP4_31_29, SCK0_D, SEL_SCIF0_3),
PINMUX_IPSR_DATA(IP5_2_0, DU1_DB1),
PINMUX_IPSR_DATA(IP5_2_0, VI2_DATA5_VI2_B5),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, SDA2_B, SEL_I2C2_1),
+ PINMUX_IPSR_MSEL(IP5_2_0, SDA2_B, SEL_I2C2_1),
PINMUX_IPSR_DATA(IP5_2_0, SD3_DAT1),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, RX5, SEL_SCIF5_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, RTS0_D_TANS_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP5_2_0, RX5, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP5_2_0, RTS0_D_TANS_D, SEL_SCIF0_3),
PINMUX_IPSR_DATA(IP5_3, DU1_DB2),
PINMUX_IPSR_DATA(IP5_3, VI2_R4),
PINMUX_IPSR_DATA(IP5_4, DU1_DB3),
@@ -969,16 +968,16 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP5_6, DU1_DB5),
PINMUX_IPSR_DATA(IP5_6, VI2_R7),
PINMUX_IPSR_DATA(IP5_7, DU1_DB6),
- PINMUX_IPSR_MODSEL_DATA(IP5_7, SCL2_D, SEL_I2C2_3),
+ PINMUX_IPSR_MSEL(IP5_7, SCL2_D, SEL_I2C2_3),
PINMUX_IPSR_DATA(IP5_8, DU1_DB7),
- PINMUX_IPSR_MODSEL_DATA(IP5_8, SDA2_D, SEL_I2C2_3),
+ PINMUX_IPSR_MSEL(IP5_8, SDA2_D, SEL_I2C2_3),
PINMUX_IPSR_DATA(IP5_10_9, DU1_DOTCLKIN),
PINMUX_IPSR_DATA(IP5_10_9, VI2_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP5_10_9, HSPI_CS1, SEL_HSPI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_10_9, SCL1_D, SEL_I2C1_3),
+ PINMUX_IPSR_MSEL(IP5_10_9, HSPI_CS1, SEL_HSPI1_0),
+ PINMUX_IPSR_MSEL(IP5_10_9, SCL1_D, SEL_I2C1_3),
PINMUX_IPSR_DATA(IP5_12_11, DU1_DOTCLKOUT),
PINMUX_IPSR_DATA(IP5_12_11, VI2_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP5_12_11, SDA1_D, SEL_I2C1_3),
+ PINMUX_IPSR_MSEL(IP5_12_11, SDA1_D, SEL_I2C1_3),
PINMUX_IPSR_DATA(IP5_14_13, DU1_EXHSYNC_DU1_HSYNC),
PINMUX_IPSR_DATA(IP5_14_13, VI2_HSYNC),
PINMUX_IPSR_DATA(IP5_14_13, VI3_HSYNC),
@@ -995,26 +994,26 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP5_20_17, AUDIO_CLKC),
PINMUX_IPSR_DATA(IP5_20_17, TX2_D),
PINMUX_IPSR_DATA(IP5_20_17, SPEEDIN),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_17, GPS_SIGN_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP5_20_17, GPS_SIGN_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP5_23_21, DU1_DISP),
PINMUX_IPSR_DATA(IP5_23_21, VI2_DATA6_VI2_B6),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, TCLK0, SEL_TMU0_0),
+ PINMUX_IPSR_MSEL(IP5_23_21, TCLK0, SEL_TMU0_0),
PINMUX_IPSR_DATA(IP5_23_21, QSTVA_B_QVS_B),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, HSPI_CLK1, SEL_HSPI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, SCK2_D, SEL_SCIF2_3),
+ PINMUX_IPSR_MSEL(IP5_23_21, HSPI_CLK1, SEL_HSPI1_0),
+ PINMUX_IPSR_MSEL(IP5_23_21, SCK2_D, SEL_SCIF2_3),
PINMUX_IPSR_DATA(IP5_23_21, AUDIO_CLKOUT_B),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, GPS_MAG_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP5_23_21, GPS_MAG_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP5_27_24, DU1_CDE),
PINMUX_IPSR_DATA(IP5_27_24, VI2_DATA7_VI2_B7),
- PINMUX_IPSR_MODSEL_DATA(IP5_27_24, RX3_B_IRDA_RX_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP5_27_24, RX3_B_IRDA_RX_B, SEL_SCIF3_1),
PINMUX_IPSR_DATA(IP5_27_24, SD3_WP),
- PINMUX_IPSR_MODSEL_DATA(IP5_27_24, HSPI_RX1, SEL_HSPI1_0),
+ PINMUX_IPSR_MSEL(IP5_27_24, HSPI_RX1, SEL_HSPI1_0),
PINMUX_IPSR_DATA(IP5_27_24, VI1_FIELD),
PINMUX_IPSR_DATA(IP5_27_24, VI3_FIELD),
PINMUX_IPSR_DATA(IP5_27_24, AUDIO_CLKOUT),
- PINMUX_IPSR_MODSEL_DATA(IP5_27_24, RX2_D, SEL_SCIF2_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_27_24, GPS_CLK_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_27_24, GPS_CLK_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP5_27_24, RX2_D, SEL_SCIF2_3),
+ PINMUX_IPSR_MSEL(IP5_27_24, GPS_CLK_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP5_27_24, GPS_CLK_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP5_28, AUDIO_CLKA),
PINMUX_IPSR_DATA(IP5_28, CAN_TXCLK),
PINMUX_IPSR_DATA(IP5_30_29, AUDIO_CLKB),
@@ -1039,82 +1038,82 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP6_11_9, SSI_SCK34),
PINMUX_IPSR_DATA(IP6_11_9, CAN_DEBUGOUT6),
PINMUX_IPSR_DATA(IP6_11_9, CAN0_TX_B),
- PINMUX_IPSR_MODSEL_DATA(IP6_11_9, IERX, SEL_IE_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_11_9, SSI_SCK9_C, SEL_SSI9_2),
+ PINMUX_IPSR_MSEL(IP6_11_9, IERX, SEL_IE_0),
+ PINMUX_IPSR_MSEL(IP6_11_9, SSI_SCK9_C, SEL_SSI9_2),
PINMUX_IPSR_DATA(IP6_14_12, SSI_WS34),
PINMUX_IPSR_DATA(IP6_14_12, CAN_DEBUGOUT7),
- PINMUX_IPSR_MODSEL_DATA(IP6_14_12, CAN0_RX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP6_14_12, CAN0_RX_B, SEL_CAN0_1),
PINMUX_IPSR_DATA(IP6_14_12, IETX),
- PINMUX_IPSR_MODSEL_DATA(IP6_14_12, SSI_WS9_C, SEL_SSI9_2),
+ PINMUX_IPSR_MSEL(IP6_14_12, SSI_WS9_C, SEL_SSI9_2),
PINMUX_IPSR_DATA(IP6_17_15, SSI_SDATA3),
PINMUX_IPSR_DATA(IP6_17_15, PWM0_C),
PINMUX_IPSR_DATA(IP6_17_15, CAN_DEBUGOUT8),
- PINMUX_IPSR_MODSEL_DATA(IP6_17_15, CAN_CLK_B, SEL_CANCLK_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_17_15, IECLK, SEL_IE_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_17_15, SCIF_CLK_B, SEL_SCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_17_15, TCLK0_B, SEL_TMU0_1),
+ PINMUX_IPSR_MSEL(IP6_17_15, CAN_CLK_B, SEL_CANCLK_1),
+ PINMUX_IPSR_MSEL(IP6_17_15, IECLK, SEL_IE_0),
+ PINMUX_IPSR_MSEL(IP6_17_15, SCIF_CLK_B, SEL_SCIF_1),
+ PINMUX_IPSR_MSEL(IP6_17_15, TCLK0_B, SEL_TMU0_1),
PINMUX_IPSR_DATA(IP6_19_18, SSI_SDATA4),
PINMUX_IPSR_DATA(IP6_19_18, CAN_DEBUGOUT9),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_18, SSI_SDATA9_C, SEL_SSI9_2),
+ PINMUX_IPSR_MSEL(IP6_19_18, SSI_SDATA9_C, SEL_SSI9_2),
PINMUX_IPSR_DATA(IP6_22_20, SSI_SCK5),
PINMUX_IPSR_DATA(IP6_22_20, ADICLK),
PINMUX_IPSR_DATA(IP6_22_20, CAN_DEBUGOUT10),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCK3, SEL_SCIF3_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, TCLK0_D, SEL_TMU0_3),
+ PINMUX_IPSR_MSEL(IP6_22_20, SCK3, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP6_22_20, TCLK0_D, SEL_TMU0_3),
PINMUX_IPSR_DATA(IP6_24_23, SSI_WS5),
- PINMUX_IPSR_MODSEL_DATA(IP6_24_23, ADICS_SAMP, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP6_24_23, ADICS_SAMP, SEL_ADI_0),
PINMUX_IPSR_DATA(IP6_24_23, CAN_DEBUGOUT11),
PINMUX_IPSR_DATA(IP6_24_23, TX3_IRDA_TX),
PINMUX_IPSR_DATA(IP6_26_25, SSI_SDATA5),
- PINMUX_IPSR_MODSEL_DATA(IP6_26_25, ADIDATA, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP6_26_25, ADIDATA, SEL_ADI_0),
PINMUX_IPSR_DATA(IP6_26_25, CAN_DEBUGOUT12),
- PINMUX_IPSR_MODSEL_DATA(IP6_26_25, RX3_IRDA_RX, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP6_26_25, RX3_IRDA_RX, SEL_SCIF3_0),
PINMUX_IPSR_DATA(IP6_30_29, SSI_SCK6),
PINMUX_IPSR_DATA(IP6_30_29, ADICHS0),
PINMUX_IPSR_DATA(IP6_30_29, CAN0_TX),
- PINMUX_IPSR_MODSEL_DATA(IP6_30_29, IERX_B, SEL_IE_1),
+ PINMUX_IPSR_MSEL(IP6_30_29, IERX_B, SEL_IE_1),
PINMUX_IPSR_DATA(IP7_1_0, SSI_WS6),
PINMUX_IPSR_DATA(IP7_1_0, ADICHS1),
- PINMUX_IPSR_MODSEL_DATA(IP7_1_0, CAN0_RX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP7_1_0, CAN0_RX, SEL_CAN0_0),
PINMUX_IPSR_DATA(IP7_1_0, IETX_B),
PINMUX_IPSR_DATA(IP7_3_2, SSI_SDATA6),
PINMUX_IPSR_DATA(IP7_3_2, ADICHS2),
- PINMUX_IPSR_MODSEL_DATA(IP7_3_2, CAN_CLK, SEL_CANCLK_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_3_2, IECLK_B, SEL_IE_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_6_4, SSI_SCK78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP7_3_2, CAN_CLK, SEL_CANCLK_0),
+ PINMUX_IPSR_MSEL(IP7_3_2, IECLK_B, SEL_IE_1),
+ PINMUX_IPSR_MSEL(IP7_6_4, SSI_SCK78, SEL_SSI7_0),
PINMUX_IPSR_DATA(IP7_6_4, CAN_DEBUGOUT13),
- PINMUX_IPSR_MODSEL_DATA(IP7_6_4, IRQ0_B, SEL_INT0_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_6_4, SSI_SCK9_B, SEL_SSI9_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_6_4, HSPI_CLK1_C, SEL_HSPI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_9_7, SSI_WS78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP7_6_4, IRQ0_B, SEL_INT0_1),
+ PINMUX_IPSR_MSEL(IP7_6_4, SSI_SCK9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP7_6_4, HSPI_CLK1_C, SEL_HSPI1_2),
+ PINMUX_IPSR_MSEL(IP7_9_7, SSI_WS78, SEL_SSI7_0),
PINMUX_IPSR_DATA(IP7_9_7, CAN_DEBUGOUT14),
- PINMUX_IPSR_MODSEL_DATA(IP7_9_7, IRQ1_B, SEL_INT1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_9_7, SSI_WS9_B, SEL_SSI9_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_9_7, HSPI_CS1_C, SEL_HSPI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_10, SSI_SDATA7, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP7_9_7, IRQ1_B, SEL_INT1_1),
+ PINMUX_IPSR_MSEL(IP7_9_7, SSI_WS9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP7_9_7, HSPI_CS1_C, SEL_HSPI1_2),
+ PINMUX_IPSR_MSEL(IP7_12_10, SSI_SDATA7, SEL_SSI7_0),
PINMUX_IPSR_DATA(IP7_12_10, CAN_DEBUGOUT15),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_10, IRQ2_B, SEL_INT2_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_10, TCLK1_C, SEL_TMU1_2),
+ PINMUX_IPSR_MSEL(IP7_12_10, IRQ2_B, SEL_INT2_1),
+ PINMUX_IPSR_MSEL(IP7_12_10, TCLK1_C, SEL_TMU1_2),
PINMUX_IPSR_DATA(IP7_12_10, HSPI_TX1_C),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_13, SSI_SDATA8, SEL_SSI8_0),
+ PINMUX_IPSR_MSEL(IP7_14_13, SSI_SDATA8, SEL_SSI8_0),
PINMUX_IPSR_DATA(IP7_14_13, VSP),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_13, IRQ3_B, SEL_INT3_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_13, HSPI_RX1_C, SEL_HSPI1_2),
+ PINMUX_IPSR_MSEL(IP7_14_13, IRQ3_B, SEL_INT3_1),
+ PINMUX_IPSR_MSEL(IP7_14_13, HSPI_RX1_C, SEL_HSPI1_2),
PINMUX_IPSR_DATA(IP7_16_15, SD0_CLK),
PINMUX_IPSR_DATA(IP7_16_15, ATACS01),
- PINMUX_IPSR_MODSEL_DATA(IP7_16_15, SCK1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP7_16_15, SCK1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP7_18_17, SD0_CMD),
PINMUX_IPSR_DATA(IP7_18_17, ATACS11),
PINMUX_IPSR_DATA(IP7_18_17, TX1_B),
PINMUX_IPSR_DATA(IP7_18_17, CC5_TDO),
PINMUX_IPSR_DATA(IP7_20_19, SD0_DAT0),
PINMUX_IPSR_DATA(IP7_20_19, ATADIR1),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_19, RX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP7_20_19, RX1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP7_20_19, CC5_TRST),
PINMUX_IPSR_DATA(IP7_22_21, SD0_DAT1),
PINMUX_IPSR_DATA(IP7_22_21, ATAG1),
- PINMUX_IPSR_MODSEL_DATA(IP7_22_21, SCK2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP7_22_21, SCK2_B, SEL_SCIF2_1),
PINMUX_IPSR_DATA(IP7_22_21, CC5_TMS),
PINMUX_IPSR_DATA(IP7_24_23, SD0_DAT2),
PINMUX_IPSR_DATA(IP7_24_23, ATARD1),
@@ -1122,17 +1121,17 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP7_24_23, CC5_TCK),
PINMUX_IPSR_DATA(IP7_26_25, SD0_DAT3),
PINMUX_IPSR_DATA(IP7_26_25, ATAWR1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_25, RX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP7_26_25, RX2_B, SEL_SCIF2_1),
PINMUX_IPSR_DATA(IP7_26_25, CC5_TDI),
PINMUX_IPSR_DATA(IP7_28_27, SD0_CD),
- PINMUX_IPSR_MODSEL_DATA(IP7_28_27, DREQ2, SEL_EXBUS2_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_28_27, RTS1_B_TANS_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP7_28_27, DREQ2, SEL_EXBUS2_0),
+ PINMUX_IPSR_MSEL(IP7_28_27, RTS1_B_TANS_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP7_30_29, SD0_WP),
PINMUX_IPSR_DATA(IP7_30_29, DACK2),
- PINMUX_IPSR_MODSEL_DATA(IP7_30_29, CTS1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP7_30_29, CTS1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP8_3_0, HSPI_CLK0),
- PINMUX_IPSR_MODSEL_DATA(IP8_3_0, CTS0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_3_0, CTS0, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP8_3_0, USB_OVC0),
PINMUX_IPSR_DATA(IP8_3_0, AD_CLK),
PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE4),
@@ -1141,7 +1140,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE28),
PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE36),
PINMUX_IPSR_DATA(IP8_7_4, HSPI_CS0),
- PINMUX_IPSR_MODSEL_DATA(IP8_7_4, RTS0_TANS, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_7_4, RTS0_TANS, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP8_7_4, USB_OVC1),
PINMUX_IPSR_DATA(IP8_7_4, AD_DI),
PINMUX_IPSR_DATA(IP8_7_4, CC5_STATE5),
@@ -1159,7 +1158,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE30),
PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE38),
PINMUX_IPSR_DATA(IP8_15_12, HSPI_RX0),
- PINMUX_IPSR_MODSEL_DATA(IP8_15_12, RX0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_15_12, RX0, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP8_15_12, CAN_STEP0),
PINMUX_IPSR_DATA(IP8_15_12, AD_NCS),
PINMUX_IPSR_DATA(IP8_15_12, CC5_STATE7),
@@ -1181,25 +1180,25 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP8_22_21, HTX1_B),
PINMUX_IPSR_DATA(IP8_22_21, MT1_SYNC),
PINMUX_IPSR_DATA(IP8_24_23, VI0_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP8_24_23, RX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_24_23, HRX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP8_24_23, RX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP8_24_23, HRX1_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP8_27_25, VI0_HSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_25, VI0_DATA0_B_VI0_B0_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_25, CTS1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP8_27_25, VI0_DATA0_B_VI0_B0_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP8_27_25, CTS1_C, SEL_SCIF1_2),
PINMUX_IPSR_DATA(IP8_27_25, TX4_D),
PINMUX_IPSR_DATA(IP8_27_25, MMC1_CMD),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_25, HSCK1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP8_27_25, HSCK1_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP8_30_28, VI0_VSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, VI0_DATA1_B_VI0_B1_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, RTS1_C_TANS_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, RX4_D, SEL_SCIF4_3),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, PWMFSW0_C, SEL_PWMFSW_2),
+ PINMUX_IPSR_MSEL(IP8_30_28, VI0_DATA1_B_VI0_B1_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP8_30_28, RTS1_C_TANS_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP8_30_28, RX4_D, SEL_SCIF4_3),
+ PINMUX_IPSR_MSEL(IP8_30_28, PWMFSW0_C, SEL_PWMFSW_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, VI0_DATA0_VI0_B0, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, HRTS1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP9_1_0, VI0_DATA0_VI0_B0, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP9_1_0, HRTS1_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP9_1_0, MT1_VCXO),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, VI0_DATA1_VI0_B1, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, HCTS1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP9_3_2, VI0_DATA1_VI0_B1, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP9_3_2, HCTS1_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP9_3_2, MT1_PWM),
PINMUX_IPSR_DATA(IP9_4, VI0_DATA2_VI0_B2),
PINMUX_IPSR_DATA(IP9_4, MMC1_D0),
@@ -1216,12 +1215,12 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP9_11_10, MMC1_D5),
PINMUX_IPSR_DATA(IP9_11_10, ARM_TRACEDATA_1),
PINMUX_IPSR_DATA(IP9_13_12, VI0_G0),
- PINMUX_IPSR_MODSEL_DATA(IP9_13_12, SSI_SCK78_C, SEL_SSI7_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_13_12, IRQ0, SEL_INT0_0),
+ PINMUX_IPSR_MSEL(IP9_13_12, SSI_SCK78_C, SEL_SSI7_2),
+ PINMUX_IPSR_MSEL(IP9_13_12, IRQ0, SEL_INT0_0),
PINMUX_IPSR_DATA(IP9_13_12, ARM_TRACEDATA_2),
PINMUX_IPSR_DATA(IP9_15_14, VI0_G1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_14, SSI_WS78_C, SEL_SSI7_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_14, IRQ1, SEL_INT1_0),
+ PINMUX_IPSR_MSEL(IP9_15_14, SSI_WS78_C, SEL_SSI7_2),
+ PINMUX_IPSR_MSEL(IP9_15_14, IRQ1, SEL_INT1_0),
PINMUX_IPSR_DATA(IP9_15_14, ARM_TRACEDATA_3),
PINMUX_IPSR_DATA(IP9_18_16, VI0_G2),
PINMUX_IPSR_DATA(IP9_18_16, ETH_TXD1),
@@ -1235,29 +1234,29 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP9_21_19, TS_SDAT0),
PINMUX_IPSR_DATA(IP9_23_22, VI0_G4),
PINMUX_IPSR_DATA(IP9_23_22, ETH_TX_EN),
- PINMUX_IPSR_MODSEL_DATA(IP9_23_22, SD2_DAT0_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP9_23_22, SD2_DAT0_B, SEL_SD2_1),
PINMUX_IPSR_DATA(IP9_23_22, ARM_TRACEDATA_6),
PINMUX_IPSR_DATA(IP9_25_24, VI0_G5),
PINMUX_IPSR_DATA(IP9_25_24, ETH_RX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP9_25_24, SD2_DAT1_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP9_25_24, SD2_DAT1_B, SEL_SD2_1),
PINMUX_IPSR_DATA(IP9_25_24, ARM_TRACEDATA_7),
PINMUX_IPSR_DATA(IP9_27_26, VI0_G6),
PINMUX_IPSR_DATA(IP9_27_26, ETH_RXD0),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_26, SD2_DAT2_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP9_27_26, SD2_DAT2_B, SEL_SD2_1),
PINMUX_IPSR_DATA(IP9_27_26, ARM_TRACEDATA_8),
PINMUX_IPSR_DATA(IP9_29_28, VI0_G7),
PINMUX_IPSR_DATA(IP9_29_28, ETH_RXD1),
- PINMUX_IPSR_MODSEL_DATA(IP9_29_28, SD2_DAT3_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP9_29_28, SD2_DAT3_B, SEL_SD2_1),
PINMUX_IPSR_DATA(IP9_29_28, ARM_TRACEDATA_9),
PINMUX_IPSR_DATA(IP10_2_0, VI0_R0),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SSI_SDATA7_C, SEL_SSI7_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SCK1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, DREQ1_B, SEL_EXBUS1_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, SSI_SDATA7_C, SEL_SSI7_2),
+ PINMUX_IPSR_MSEL(IP10_2_0, SCK1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP10_2_0, DREQ1_B, SEL_EXBUS1_0),
PINMUX_IPSR_DATA(IP10_2_0, ARM_TRACEDATA_10),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, DREQ0_C, SEL_EXBUS0_2),
+ PINMUX_IPSR_MSEL(IP10_2_0, DREQ0_C, SEL_EXBUS0_2),
PINMUX_IPSR_DATA(IP10_5_3, VI0_R1),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SSI_SDATA8_C, SEL_SSI8_2),
+ PINMUX_IPSR_MSEL(IP10_5_3, SSI_SDATA8_C, SEL_SSI8_2),
PINMUX_IPSR_DATA(IP10_5_3, DACK1_B),
PINMUX_IPSR_DATA(IP10_5_3, ARM_TRACEDATA_11),
PINMUX_IPSR_DATA(IP10_5_3, DACK0_C),
@@ -1265,74 +1264,74 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP10_8_6, VI0_R2),
PINMUX_IPSR_DATA(IP10_8_6, ETH_LINK),
PINMUX_IPSR_DATA(IP10_8_6, SD2_CLK_B),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, IRQ2, SEL_INT2_0),
+ PINMUX_IPSR_MSEL(IP10_8_6, IRQ2, SEL_INT2_0),
PINMUX_IPSR_DATA(IP10_8_6, ARM_TRACEDATA_12),
PINMUX_IPSR_DATA(IP10_11_9, VI0_R3),
PINMUX_IPSR_DATA(IP10_11_9, ETH_MAGIC),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SD2_CMD_B, SEL_SD2_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, IRQ3, SEL_INT3_0),
+ PINMUX_IPSR_MSEL(IP10_11_9, SD2_CMD_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP10_11_9, IRQ3, SEL_INT3_0),
PINMUX_IPSR_DATA(IP10_11_9, ARM_TRACEDATA_13),
PINMUX_IPSR_DATA(IP10_14_12, VI0_R4),
PINMUX_IPSR_DATA(IP10_14_12, ETH_REFCLK),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SD2_CD_B, SEL_SD2_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, HSPI_CLK1_B, SEL_HSPI1_1),
+ PINMUX_IPSR_MSEL(IP10_14_12, SD2_CD_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP10_14_12, HSPI_CLK1_B, SEL_HSPI1_1),
PINMUX_IPSR_DATA(IP10_14_12, ARM_TRACEDATA_14),
PINMUX_IPSR_DATA(IP10_14_12, MT1_CLK),
PINMUX_IPSR_DATA(IP10_14_12, TS_SCK0),
PINMUX_IPSR_DATA(IP10_17_15, VI0_R5),
PINMUX_IPSR_DATA(IP10_17_15, ETH_TXD0),
- PINMUX_IPSR_MODSEL_DATA(IP10_17_15, SD2_WP_B, SEL_SD2_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_17_15, HSPI_CS1_B, SEL_HSPI1_1),
+ PINMUX_IPSR_MSEL(IP10_17_15, SD2_WP_B, SEL_SD2_1),
+ PINMUX_IPSR_MSEL(IP10_17_15, HSPI_CS1_B, SEL_HSPI1_1),
PINMUX_IPSR_DATA(IP10_17_15, ARM_TRACEDATA_15),
PINMUX_IPSR_DATA(IP10_17_15, MT1_D),
PINMUX_IPSR_DATA(IP10_17_15, TS_SDEN0),
PINMUX_IPSR_DATA(IP10_20_18, VI0_R6),
PINMUX_IPSR_DATA(IP10_20_18, ETH_MDC),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, DREQ2_C, SEL_EXBUS2_2),
+ PINMUX_IPSR_MSEL(IP10_20_18, DREQ2_C, SEL_EXBUS2_2),
PINMUX_IPSR_DATA(IP10_20_18, HSPI_TX1_B),
PINMUX_IPSR_DATA(IP10_20_18, TRACECLK),
PINMUX_IPSR_DATA(IP10_20_18, MT1_BEN),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, PWMFSW0_D, SEL_PWMFSW_3),
+ PINMUX_IPSR_MSEL(IP10_20_18, PWMFSW0_D, SEL_PWMFSW_3),
PINMUX_IPSR_DATA(IP10_23_21, VI0_R7),
PINMUX_IPSR_DATA(IP10_23_21, ETH_MDIO),
PINMUX_IPSR_DATA(IP10_23_21, DACK2_C),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, HSPI_RX1_B, SEL_HSPI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, SCIF_CLK_D, SEL_SCIF_3),
+ PINMUX_IPSR_MSEL(IP10_23_21, HSPI_RX1_B, SEL_HSPI1_1),
+ PINMUX_IPSR_MSEL(IP10_23_21, SCIF_CLK_D, SEL_SCIF_3),
PINMUX_IPSR_DATA(IP10_23_21, TRACECTL),
PINMUX_IPSR_DATA(IP10_23_21, MT1_PEN),
PINMUX_IPSR_DATA(IP10_25_24, VI1_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_24, SIM_D, SEL_SIM_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_24, SDA3, SEL_I2C3_0),
+ PINMUX_IPSR_MSEL(IP10_25_24, SIM_D, SEL_SIM_0),
+ PINMUX_IPSR_MSEL(IP10_25_24, SDA3, SEL_I2C3_0),
PINMUX_IPSR_DATA(IP10_28_26, VI1_HSYNC),
PINMUX_IPSR_DATA(IP10_28_26, VI3_CLK),
PINMUX_IPSR_DATA(IP10_28_26, SSI_SCK4),
- PINMUX_IPSR_MODSEL_DATA(IP10_28_26, GPS_SIGN_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_28_26, PWMFSW0_E, SEL_PWMFSW_4),
+ PINMUX_IPSR_MSEL(IP10_28_26, GPS_SIGN_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP10_28_26, PWMFSW0_E, SEL_PWMFSW_4),
PINMUX_IPSR_DATA(IP10_31_29, VI1_VSYNC),
PINMUX_IPSR_DATA(IP10_31_29, AUDIO_CLKOUT_C),
PINMUX_IPSR_DATA(IP10_31_29, SSI_WS4),
PINMUX_IPSR_DATA(IP10_31_29, SIM_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_29, GPS_MAG_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP10_31_29, GPS_MAG_C, SEL_GPS_2),
PINMUX_IPSR_DATA(IP10_31_29, SPV_TRST),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_29, SCL3, SEL_I2C3_0),
+ PINMUX_IPSR_MSEL(IP10_31_29, SCL3, SEL_I2C3_0),
PINMUX_IPSR_DATA(IP11_2_0, VI1_DATA0_VI1_B0),
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, SD2_DAT0, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_2_0, SD2_DAT0, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_2_0, SIM_RST),
PINMUX_IPSR_DATA(IP11_2_0, SPV_TCK),
PINMUX_IPSR_DATA(IP11_2_0, ADICLK_B),
PINMUX_IPSR_DATA(IP11_5_3, VI1_DATA1_VI1_B1),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, SD2_DAT1, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_5_3, SD2_DAT1, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_5_3, MT0_CLK),
PINMUX_IPSR_DATA(IP11_5_3, SPV_TMS),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, ADICS_B_SAMP_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP11_5_3, ADICS_B_SAMP_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP11_8_6, VI1_DATA2_VI1_B2),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SD2_DAT2, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_8_6, SD2_DAT2, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_8_6, MT0_D),
PINMUX_IPSR_DATA(IP11_8_6, SPVTDI),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, ADIDATA_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP11_8_6, ADIDATA_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP11_11_9, VI1_DATA3_VI1_B3),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_9, SD2_DAT3, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_11_9, SD2_DAT3, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_11_9, MT0_BEN),
PINMUX_IPSR_DATA(IP11_11_9, SPV_TDO),
PINMUX_IPSR_DATA(IP11_11_9, ADICHS0_B),
@@ -1340,74 +1339,74 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP11_14_12, SD2_CLK),
PINMUX_IPSR_DATA(IP11_14_12, MT0_PEN),
PINMUX_IPSR_DATA(IP11_14_12, SPA_TRST),
- PINMUX_IPSR_MODSEL_DATA(IP11_14_12, HSPI_CLK1_D, SEL_HSPI1_3),
+ PINMUX_IPSR_MSEL(IP11_14_12, HSPI_CLK1_D, SEL_HSPI1_3),
PINMUX_IPSR_DATA(IP11_14_12, ADICHS1_B),
PINMUX_IPSR_DATA(IP11_17_15, VI1_DATA5_VI1_B5),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_15, SD2_CMD, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_17_15, SD2_CMD, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_17_15, MT0_SYNC),
PINMUX_IPSR_DATA(IP11_17_15, SPA_TCK),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_15, HSPI_CS1_D, SEL_HSPI1_3),
+ PINMUX_IPSR_MSEL(IP11_17_15, HSPI_CS1_D, SEL_HSPI1_3),
PINMUX_IPSR_DATA(IP11_17_15, ADICHS2_B),
PINMUX_IPSR_DATA(IP11_20_18, VI1_DATA6_VI1_B6),
- PINMUX_IPSR_MODSEL_DATA(IP11_20_18, SD2_CD, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_20_18, SD2_CD, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_20_18, MT0_VCXO),
PINMUX_IPSR_DATA(IP11_20_18, SPA_TMS),
PINMUX_IPSR_DATA(IP11_20_18, HSPI_TX1_D),
PINMUX_IPSR_DATA(IP11_23_21, VI1_DATA7_VI1_B7),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_21, SD2_WP, SEL_SD2_0),
+ PINMUX_IPSR_MSEL(IP11_23_21, SD2_WP, SEL_SD2_0),
PINMUX_IPSR_DATA(IP11_23_21, MT0_PWM),
PINMUX_IPSR_DATA(IP11_23_21, SPA_TDI),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_21, HSPI_RX1_D, SEL_HSPI1_3),
+ PINMUX_IPSR_MSEL(IP11_23_21, HSPI_RX1_D, SEL_HSPI1_3),
PINMUX_IPSR_DATA(IP11_26_24, VI1_G0),
PINMUX_IPSR_DATA(IP11_26_24, VI3_DATA0),
PINMUX_IPSR_DATA(IP11_26_24, TS_SCK1),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, DREQ2_B, SEL_EXBUS2_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, DREQ2_B, SEL_EXBUS2_1),
PINMUX_IPSR_DATA(IP11_26_24, TX2),
PINMUX_IPSR_DATA(IP11_26_24, SPA_TDO),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, HCTS0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, HCTS0_B, SEL_HSCIF0_1),
PINMUX_IPSR_DATA(IP11_29_27, VI1_G1),
PINMUX_IPSR_DATA(IP11_29_27, VI3_DATA1),
PINMUX_IPSR_DATA(IP11_29_27, SSI_SCK1),
PINMUX_IPSR_DATA(IP11_29_27, TS_SDEN1),
PINMUX_IPSR_DATA(IP11_29_27, DACK2_B),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, RX2, SEL_SCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, HRTS0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP11_29_27, RX2, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP11_29_27, HRTS0_B, SEL_HSCIF0_1),
PINMUX_IPSR_DATA(IP12_2_0, VI1_G2),
PINMUX_IPSR_DATA(IP12_2_0, VI3_DATA2),
PINMUX_IPSR_DATA(IP12_2_0, SSI_WS1),
PINMUX_IPSR_DATA(IP12_2_0, TS_SPSYNC1),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, SCK2, SEL_SCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, HSCK0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP12_2_0, SCK2, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP12_2_0, HSCK0_B, SEL_HSCIF0_1),
PINMUX_IPSR_DATA(IP12_5_3, VI1_G3),
PINMUX_IPSR_DATA(IP12_5_3, VI3_DATA3),
PINMUX_IPSR_DATA(IP12_5_3, SSI_SCK2),
PINMUX_IPSR_DATA(IP12_5_3, TS_SDAT1),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_3, SCL1_C, SEL_I2C1_2),
+ PINMUX_IPSR_MSEL(IP12_5_3, SCL1_C, SEL_I2C1_2),
PINMUX_IPSR_DATA(IP12_5_3, HTX0_B),
PINMUX_IPSR_DATA(IP12_8_6, VI1_G4),
PINMUX_IPSR_DATA(IP12_8_6, VI3_DATA4),
PINMUX_IPSR_DATA(IP12_8_6, SSI_WS2),
- PINMUX_IPSR_MODSEL_DATA(IP12_8_6, SDA1_C, SEL_I2C1_2),
+ PINMUX_IPSR_MSEL(IP12_8_6, SDA1_C, SEL_I2C1_2),
PINMUX_IPSR_DATA(IP12_8_6, SIM_RST_B),
- PINMUX_IPSR_MODSEL_DATA(IP12_8_6, HRX0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP12_8_6, HRX0_B, SEL_HSCIF0_1),
PINMUX_IPSR_DATA(IP12_11_9, VI1_G5),
PINMUX_IPSR_DATA(IP12_11_9, VI3_DATA5),
- PINMUX_IPSR_MODSEL_DATA(IP12_11_9, GPS_CLK, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP12_11_9, GPS_CLK, SEL_GPS_0),
PINMUX_IPSR_DATA(IP12_11_9, FSE),
PINMUX_IPSR_DATA(IP12_11_9, TX4_B),
- PINMUX_IPSR_MODSEL_DATA(IP12_11_9, SIM_D_B, SEL_SIM_1),
+ PINMUX_IPSR_MSEL(IP12_11_9, SIM_D_B, SEL_SIM_1),
PINMUX_IPSR_DATA(IP12_14_12, VI1_G6),
PINMUX_IPSR_DATA(IP12_14_12, VI3_DATA6),
- PINMUX_IPSR_MODSEL_DATA(IP12_14_12, GPS_SIGN, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP12_14_12, GPS_SIGN, SEL_GPS_0),
PINMUX_IPSR_DATA(IP12_14_12, FRB),
- PINMUX_IPSR_MODSEL_DATA(IP12_14_12, RX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP12_14_12, RX4_B, SEL_SCIF4_1),
PINMUX_IPSR_DATA(IP12_14_12, SIM_CLK_B),
PINMUX_IPSR_DATA(IP12_17_15, VI1_G7),
PINMUX_IPSR_DATA(IP12_17_15, VI3_DATA7),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_15, GPS_MAG, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP12_17_15, GPS_MAG, SEL_GPS_0),
PINMUX_IPSR_DATA(IP12_17_15, FCE),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_15, SCK4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP12_17_15, SCK4_B, SEL_SCIF4_1),
};
static const struct sh_pfc_pin pinmux_pins[] = {
@@ -3868,6 +3867,6 @@ const struct sh_pfc_soc_info r8a7779_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index fc344a7c2b53..d9924b0d53b7 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -22,7 +22,6 @@
*/
#include <linux/kernel.h>
-#include <linux/platform_data/gpio-rcar.h>
#include "core.h"
#include "sh_pfc.h"
@@ -818,103 +817,103 @@ static const u16 pinmux_data[] = {
PINMUX_DATA(DU_DOTCLKIN2_MARK, FN_DU_DOTCLKIN2),
PINMUX_IPSR_DATA(IP0_2_0, D0),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, MSIOF3_SCK_B, SEL_SOF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, VI3_DATA0, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, VI0_G4, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_2_0, VI0_G4_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_2_0, MSIOF3_SCK_B, SEL_SOF3_1),
+ PINMUX_IPSR_MSEL(IP0_2_0, VI3_DATA0, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_2_0, VI0_G4, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_2_0, VI0_G4_B, SEL_VI0_1),
PINMUX_IPSR_DATA(IP0_5_3, D1),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_3, MSIOF3_SYNC_B, SEL_SOF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_3, VI3_DATA1, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_3, VI0_G5, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_3, VI0_G5_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_5_3, MSIOF3_SYNC_B, SEL_SOF3_1),
+ PINMUX_IPSR_MSEL(IP0_5_3, VI3_DATA1, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_5_3, VI0_G5, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_5_3, VI0_G5_B, SEL_VI0_1),
PINMUX_IPSR_DATA(IP0_8_6, D2),
- PINMUX_IPSR_MODSEL_DATA(IP0_8_6, MSIOF3_RXD_B, SEL_SOF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_8_6, VI3_DATA2, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_8_6, VI0_G6, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_8_6, VI0_G6_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_8_6, MSIOF3_RXD_B, SEL_SOF3_1),
+ PINMUX_IPSR_MSEL(IP0_8_6, VI3_DATA2, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_8_6, VI0_G6, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_8_6, VI0_G6_B, SEL_VI0_1),
PINMUX_IPSR_DATA(IP0_11_9, D3),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_9, MSIOF3_TXD_B, SEL_SOF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_9, VI3_DATA3, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_9, VI0_G7, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_9, VI0_G7_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_11_9, MSIOF3_TXD_B, SEL_SOF3_1),
+ PINMUX_IPSR_MSEL(IP0_11_9, VI3_DATA3, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_11_9, VI0_G7, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_11_9, VI0_G7_B, SEL_VI0_1),
PINMUX_IPSR_DATA(IP0_15_12, D4),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_12, SCIFB1_RXD_F, SEL_SCIFB1_5),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_12, SCIFB0_RXD_C, SEL_SCIFB_2),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_12, VI3_DATA4, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_12, VI0_R0, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_12, VI0_R0_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_12, RX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP0_15_12, SCIFB1_RXD_F, SEL_SCIFB1_5),
+ PINMUX_IPSR_MSEL(IP0_15_12, SCIFB0_RXD_C, SEL_SCIFB_2),
+ PINMUX_IPSR_MSEL(IP0_15_12, VI3_DATA4, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_15_12, VI0_R0, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_15_12, VI0_R0_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_15_12, RX0_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP0_19_16, D5),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_16, SCIFB1_TXD_F, SEL_SCIFB1_5),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_16, SCIFB0_TXD_C, SEL_SCIFB_2),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_16, VI3_DATA5, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_16, VI0_R1, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_16, VI0_R1_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_16, TX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP0_19_16, SCIFB1_TXD_F, SEL_SCIFB1_5),
+ PINMUX_IPSR_MSEL(IP0_19_16, SCIFB0_TXD_C, SEL_SCIFB_2),
+ PINMUX_IPSR_MSEL(IP0_19_16, VI3_DATA5, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_19_16, VI0_R1, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_19_16, VI0_R1_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_19_16, TX0_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP0_22_20, D6),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_20, IIC2_SCL_C, SEL_IIC2_2),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_20, VI3_DATA6, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_20, VI0_R2, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_20, VI0_R2_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_20, I2C2_SCL_C, SEL_I2C2_2),
+ PINMUX_IPSR_MSEL(IP0_22_20, IIC2_SCL_C, SEL_IIC2_2),
+ PINMUX_IPSR_MSEL(IP0_22_20, VI3_DATA6, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_22_20, VI0_R2, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_22_20, VI0_R2_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_22_20, I2C2_SCL_C, SEL_I2C2_2),
PINMUX_IPSR_DATA(IP0_26_23, D7),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, AD_DI_B, SEL_ADI_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, IIC2_SDA_C, SEL_IIC2_2),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, VI3_DATA7, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, VI0_R3, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, VI0_R3_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, I2C2_SDA_C, SEL_I2C2_2),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_23, TCLK1, SEL_TMU1_0),
+ PINMUX_IPSR_MSEL(IP0_26_23, AD_DI_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP0_26_23, IIC2_SDA_C, SEL_IIC2_2),
+ PINMUX_IPSR_MSEL(IP0_26_23, VI3_DATA7, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP0_26_23, VI0_R3, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_26_23, VI0_R3_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_26_23, I2C2_SDA_C, SEL_I2C2_2),
+ PINMUX_IPSR_MSEL(IP0_26_23, TCLK1, SEL_TMU1_0),
PINMUX_IPSR_DATA(IP0_30_27, D8),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_27, SCIFA1_SCK_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP0_30_27, SCIFA1_SCK_C, SEL_SCIFA1_2),
PINMUX_IPSR_DATA(IP0_30_27, AVB_TXD0),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_27, VI0_G0, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_27, VI0_G0_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_27, VI2_DATA0_VI2_B0, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP0_30_27, VI0_G0, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP0_30_27, VI0_G0_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP0_30_27, VI2_DATA0_VI2_B0, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_3_0, D9),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_0, SCIFA1_RXD_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP1_3_0, SCIFA1_RXD_C, SEL_SCIFA1_2),
PINMUX_IPSR_DATA(IP1_3_0, AVB_TXD1),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_0, VI0_G1, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_0, VI0_G1_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_0, VI2_DATA1_VI2_B1, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_3_0, VI0_G1, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_3_0, VI0_G1_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_3_0, VI2_DATA1_VI2_B1, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_7_4, D10),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_4, SCIFA1_TXD_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP1_7_4, SCIFA1_TXD_C, SEL_SCIFA1_2),
PINMUX_IPSR_DATA(IP1_7_4, AVB_TXD2),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_4, VI0_G2, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_4, VI0_G2_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_4, VI2_DATA2_VI2_B2, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_7_4, VI0_G2, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_7_4, VI0_G2_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_7_4, VI2_DATA2_VI2_B2, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_11_8, D11),
- PINMUX_IPSR_MODSEL_DATA(IP1_11_8, SCIFA1_CTS_N_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP1_11_8, SCIFA1_CTS_N_C, SEL_SCIFA1_2),
PINMUX_IPSR_DATA(IP1_11_8, AVB_TXD3),
- PINMUX_IPSR_MODSEL_DATA(IP1_11_8, VI0_G3, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_11_8, VI0_G3_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_11_8, VI2_DATA3_VI2_B3, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_11_8, VI0_G3, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_11_8, VI0_G3_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_11_8, VI2_DATA3_VI2_B3, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_14_12, D12),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_12, SCIFA1_RTS_N_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP1_14_12, SCIFA1_RTS_N_C, SEL_SCIFA1_2),
PINMUX_IPSR_DATA(IP1_14_12, AVB_TXD4),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_12, VI0_HSYNC_N, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_12, VI0_HSYNC_N_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_12, VI2_DATA4_VI2_B4, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_14_12, VI0_HSYNC_N, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_14_12, VI0_HSYNC_N_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_14_12, VI2_DATA4_VI2_B4, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_17_15, D13),
PINMUX_IPSR_DATA(IP1_17_15, AVB_TXD5),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_15, VI0_VSYNC_N, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_15, VI0_VSYNC_N_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_15, VI2_DATA5_VI2_B5, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_17_15, VI0_VSYNC_N, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_17_15, VI0_VSYNC_N_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_17_15, VI2_DATA5_VI2_B5, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_21_18, D14),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_18, SCIFB1_RXD_C, SEL_SCIFB1_2),
+ PINMUX_IPSR_MSEL(IP1_21_18, SCIFB1_RXD_C, SEL_SCIFB1_2),
PINMUX_IPSR_DATA(IP1_21_18, AVB_TXD6),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_18, RX1_B, SEL_SCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_18, VI0_CLKENB, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_18, VI0_CLKENB_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_18, VI2_DATA6_VI2_B6, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_21_18, RX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP1_21_18, VI0_CLKENB, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_21_18, VI0_CLKENB_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_21_18, VI2_DATA6_VI2_B6, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_25_22, D15),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_22, SCIFB1_TXD_C, SEL_SCIFB1_2),
+ PINMUX_IPSR_MSEL(IP1_25_22, SCIFB1_TXD_C, SEL_SCIFB1_2),
PINMUX_IPSR_DATA(IP1_25_22, AVB_TXD7),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_22, TX1_B, SEL_SCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_22, VI0_FIELD, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_22, VI0_FIELD_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_22, VI2_DATA7_VI2_B7, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP1_25_22, TX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP1_25_22, VI0_FIELD, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP1_25_22, VI0_FIELD_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP1_25_22, VI2_DATA7_VI2_B7, SEL_VI2_0),
PINMUX_IPSR_DATA(IP1_27_26, A0),
PINMUX_IPSR_DATA(IP1_27_26, PWM3),
PINMUX_IPSR_DATA(IP1_29_28, A1),
@@ -922,512 +921,512 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP2_2_0, A2),
PINMUX_IPSR_DATA(IP2_2_0, PWM5),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, MSIOF1_SS1_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP2_2_0, MSIOF1_SS1_B, SEL_SOF1_1),
PINMUX_IPSR_DATA(IP2_5_3, A3),
PINMUX_IPSR_DATA(IP2_5_3, PWM6),
- PINMUX_IPSR_MODSEL_DATA(IP2_5_3, MSIOF1_SS2_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP2_5_3, MSIOF1_SS2_B, SEL_SOF1_1),
PINMUX_IPSR_DATA(IP2_8_6, A4),
- PINMUX_IPSR_MODSEL_DATA(IP2_8_6, MSIOF1_TXD_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP2_8_6, MSIOF1_TXD_B, SEL_SOF1_1),
PINMUX_IPSR_DATA(IP2_8_6, TPU0TO0),
PINMUX_IPSR_DATA(IP2_11_9, A5),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_9, SCIFA1_TXD_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP2_11_9, SCIFA1_TXD_B, SEL_SCIFA1_1),
PINMUX_IPSR_DATA(IP2_11_9, TPU0TO1),
PINMUX_IPSR_DATA(IP2_14_12, A6),
- PINMUX_IPSR_MODSEL_DATA(IP2_14_12, SCIFA1_RTS_N_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP2_14_12, SCIFA1_RTS_N_B, SEL_SCIFA1_1),
PINMUX_IPSR_DATA(IP2_14_12, TPU0TO2),
PINMUX_IPSR_DATA(IP2_17_15, A7),
- PINMUX_IPSR_MODSEL_DATA(IP2_17_15, SCIFA1_SCK_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP2_17_15, SCIFA1_SCK_B, SEL_SCIFA1_1),
PINMUX_IPSR_DATA(IP2_17_15, AUDIO_CLKOUT_B),
PINMUX_IPSR_DATA(IP2_17_15, TPU0TO3),
PINMUX_IPSR_DATA(IP2_21_18, A8),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, SCIFA1_RXD_B, SEL_SCIFA1_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, SSI_SCK5_B, SEL_SSI5_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, VI0_R4, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, VI0_R4_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, SCIFB2_RXD_C, SEL_SCIFB2_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, RX2_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_21_18, VI2_DATA0_VI2_B0_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP2_21_18, SCIFA1_RXD_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP2_21_18, SSI_SCK5_B, SEL_SSI5_1),
+ PINMUX_IPSR_MSEL(IP2_21_18, VI0_R4, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP2_21_18, VI0_R4_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP2_21_18, SCIFB2_RXD_C, SEL_SCIFB2_2),
+ PINMUX_IPSR_MSEL(IP2_21_18, RX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP2_21_18, VI2_DATA0_VI2_B0_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP2_25_22, A9),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, SCIFA1_CTS_N_B, SEL_SCIFA1_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, SSI_WS5_B, SEL_SSI5_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, VI0_R5, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, VI0_R5_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, SCIFB2_TXD_C, SEL_SCIFB2_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, TX2_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_25_22, VI2_DATA1_VI2_B1_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP2_25_22, SCIFA1_CTS_N_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP2_25_22, SSI_WS5_B, SEL_SSI5_1),
+ PINMUX_IPSR_MSEL(IP2_25_22, VI0_R5, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP2_25_22, VI0_R5_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP2_25_22, SCIFB2_TXD_C, SEL_SCIFB2_2),
+ PINMUX_IPSR_MSEL(IP2_25_22, TX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP2_25_22, VI2_DATA1_VI2_B1_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP2_28_26, A10),
- PINMUX_IPSR_MODSEL_DATA(IP2_28_26, SSI_SDATA5_B, SEL_SSI5_1),
+ PINMUX_IPSR_MSEL(IP2_28_26, SSI_SDATA5_B, SEL_SSI5_1),
PINMUX_IPSR_DATA(IP2_28_26, MSIOF2_SYNC),
- PINMUX_IPSR_MODSEL_DATA(IP2_28_26, VI0_R6, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_28_26, VI0_R6_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_28_26, VI2_DATA2_VI2_B2_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP2_28_26, VI0_R6, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP2_28_26, VI0_R6_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP2_28_26, VI2_DATA2_VI2_B2_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP3_3_0, A11),
- PINMUX_IPSR_MODSEL_DATA(IP3_3_0, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP3_3_0, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
PINMUX_IPSR_DATA(IP3_3_0, MSIOF2_SCK),
- PINMUX_IPSR_MODSEL_DATA(IP3_3_0, VI1_R0, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_3_0, VI1_R0_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP3_3_0, VI1_R0, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP3_3_0, VI1_R0_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP3_3_0, VI2_G0),
- PINMUX_IPSR_MODSEL_DATA(IP3_3_0, VI2_DATA3_VI2_B3_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP3_3_0, VI2_DATA3_VI2_B3_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP3_7_4, A12),
- PINMUX_IPSR_MODSEL_DATA(IP3_7_4, SCIFB2_RXD_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP3_7_4, SCIFB2_RXD_B, SEL_SCIFB2_1),
PINMUX_IPSR_DATA(IP3_7_4, MSIOF2_TXD),
- PINMUX_IPSR_MODSEL_DATA(IP3_7_4, VI1_R1, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_7_4, VI1_R1_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP3_7_4, VI1_R1, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP3_7_4, VI1_R1_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP3_7_4, VI2_G1),
- PINMUX_IPSR_MODSEL_DATA(IP3_7_4, VI2_DATA4_VI2_B4_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP3_7_4, VI2_DATA4_VI2_B4_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP3_11_8, A13),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_8, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP3_11_8, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
PINMUX_IPSR_DATA(IP3_11_8, EX_WAIT2),
PINMUX_IPSR_DATA(IP3_11_8, MSIOF2_RXD),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI1_R2, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI1_R2_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP3_11_8, VI1_R2, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP3_11_8, VI1_R2_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP3_11_8, VI2_G2),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI2_DATA5_VI2_B5_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP3_11_8, VI2_DATA5_VI2_B5_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP3_14_12, A14),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, SCIFB2_TXD_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP3_14_12, SCIFB2_TXD_B, SEL_SCIFB2_1),
PINMUX_IPSR_DATA(IP3_14_12, ATACS11_N),
PINMUX_IPSR_DATA(IP3_14_12, MSIOF2_SS1),
PINMUX_IPSR_DATA(IP3_17_15, A15),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, SCIFB2_SCK_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP3_17_15, SCIFB2_SCK_B, SEL_SCIFB2_1),
PINMUX_IPSR_DATA(IP3_17_15, ATARD1_N),
PINMUX_IPSR_DATA(IP3_17_15, MSIOF2_SS2),
PINMUX_IPSR_DATA(IP3_19_18, A16),
PINMUX_IPSR_DATA(IP3_19_18, ATAWR1_N),
PINMUX_IPSR_DATA(IP3_22_20, A17),
- PINMUX_IPSR_MODSEL_DATA(IP3_22_20, AD_DO_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP3_22_20, AD_DO_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP3_22_20, ATADIR1_N),
PINMUX_IPSR_DATA(IP3_25_23, A18),
- PINMUX_IPSR_MODSEL_DATA(IP3_25_23, AD_CLK_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP3_25_23, AD_CLK_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP3_25_23, ATAG1_N),
PINMUX_IPSR_DATA(IP3_28_26, A19),
- PINMUX_IPSR_MODSEL_DATA(IP3_28_26, AD_NCS_N_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP3_28_26, AD_NCS_N_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP3_28_26, ATACS01_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_28_26, EX_WAIT0_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP3_28_26, EX_WAIT0_B, SEL_LBS_1),
PINMUX_IPSR_DATA(IP3_31_29, A20),
PINMUX_IPSR_DATA(IP3_31_29, SPCLK),
- PINMUX_IPSR_MODSEL_DATA(IP3_31_29, VI1_R3, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_31_29, VI1_R3_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP3_31_29, VI1_R3, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP3_31_29, VI1_R3_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP3_31_29, VI2_G4),
PINMUX_IPSR_DATA(IP4_2_0, A21),
PINMUX_IPSR_DATA(IP4_2_0, MOSI_IO0),
- PINMUX_IPSR_MODSEL_DATA(IP4_2_0, VI1_R4, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_2_0, VI1_R4_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_2_0, VI1_R4, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_2_0, VI1_R4_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_2_0, VI2_G5),
PINMUX_IPSR_DATA(IP4_5_3, A22),
PINMUX_IPSR_DATA(IP4_5_3, MISO_IO1),
- PINMUX_IPSR_MODSEL_DATA(IP4_5_3, VI1_R5, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_5_3, VI1_R5_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_5_3, VI1_R5, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_5_3, VI1_R5_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_5_3, VI2_G6),
PINMUX_IPSR_DATA(IP4_8_6, A23),
PINMUX_IPSR_DATA(IP4_8_6, IO2),
- PINMUX_IPSR_MODSEL_DATA(IP4_8_6, VI1_G7, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_8_6, VI1_G7_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_8_6, VI1_G7, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_8_6, VI1_G7_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_8_6, VI2_G7),
PINMUX_IPSR_DATA(IP4_11_9, A24),
PINMUX_IPSR_DATA(IP4_11_9, IO3),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, VI1_R7, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, VI1_R7_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, VI2_CLKENB, SEL_VI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, VI2_CLKENB_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP4_11_9, VI1_R7, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_11_9, VI1_R7_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_11_9, VI2_CLKENB, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP4_11_9, VI2_CLKENB_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP4_14_12, A25),
PINMUX_IPSR_DATA(IP4_14_12, SSL),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, VI1_G6, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, VI1_G6_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, VI2_FIELD, SEL_VI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, VI2_FIELD_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP4_14_12, VI1_G6, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_14_12, VI1_G6_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_14_12, VI2_FIELD, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP4_14_12, VI2_FIELD_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP4_17_15, CS0_N),
- PINMUX_IPSR_MODSEL_DATA(IP4_17_15, VI1_R6, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_17_15, VI1_R6_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_17_15, VI1_R6, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_17_15, VI1_R6_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_17_15, VI2_G3),
- PINMUX_IPSR_MODSEL_DATA(IP4_17_15, MSIOF0_SS2_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP4_17_15, MSIOF0_SS2_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP4_20_18, CS1_N_A26),
PINMUX_IPSR_DATA(IP4_20_18, SPEEDIN),
- PINMUX_IPSR_MODSEL_DATA(IP4_20_18, VI0_R7, SEL_VI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_20_18, VI0_R7_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_20_18, VI2_CLK, SEL_VI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_20_18, VI2_CLK_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP4_20_18, VI0_R7, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP4_20_18, VI0_R7_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP4_20_18, VI2_CLK, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP4_20_18, VI2_CLK_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP4_23_21, EX_CS0_N),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_21, HRX1_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_21, VI1_G5, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_21, VI1_G5_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_23_21, HRX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_23_21, VI1_G5, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_23_21, VI1_G5_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_23_21, VI2_R0),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_21, HTX0_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_21, MSIOF0_SS1_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP4_23_21, HTX0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP4_23_21, MSIOF0_SS1_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP4_26_24, EX_CS1_N),
PINMUX_IPSR_DATA(IP4_26_24, GPS_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP4_26_24, HCTS1_N_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_26_24, VI1_FIELD, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_26_24, VI1_FIELD_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_26_24, HCTS1_N_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_26_24, VI1_FIELD, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_26_24, VI1_FIELD_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_26_24, VI2_R1),
PINMUX_IPSR_DATA(IP4_29_27, EX_CS2_N),
PINMUX_IPSR_DATA(IP4_29_27, GPS_SIGN),
- PINMUX_IPSR_MODSEL_DATA(IP4_29_27, HRTS1_N_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_29_27, HRTS1_N_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP4_29_27, VI3_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP4_29_27, VI1_G0, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_29_27, VI1_G0_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP4_29_27, VI1_G0, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP4_29_27, VI1_G0_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP4_29_27, VI2_R2),
PINMUX_IPSR_DATA(IP5_2_0, EX_CS3_N),
PINMUX_IPSR_DATA(IP5_2_0, GPS_MAG),
PINMUX_IPSR_DATA(IP5_2_0, VI3_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, VI1_G1, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, VI1_G1_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP5_2_0, VI1_G1, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP5_2_0, VI1_G1_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP5_2_0, VI2_R3),
PINMUX_IPSR_DATA(IP5_5_3, EX_CS4_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, MSIOF1_SCK_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP5_5_3, MSIOF1_SCK_B, SEL_SOF1_1),
PINMUX_IPSR_DATA(IP5_5_3, VI3_HSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, VI2_HSYNC_N, SEL_VI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, IIC1_SCL, SEL_IIC1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, VI2_HSYNC_N_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP5_5_3, VI2_HSYNC_N, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, IIC1_SCL, SEL_IIC1_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, VI2_HSYNC_N_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP5_5_3, INTC_EN0_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, I2C1_SCL, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, I2C1_SCL, SEL_I2C1_0),
PINMUX_IPSR_DATA(IP5_9_6, EX_CS5_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_9_6, CAN0_RX, SEL_CAN0_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_9_6, MSIOF1_RXD_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP5_9_6, CAN0_RX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP5_9_6, MSIOF1_RXD_B, SEL_SOF1_1),
PINMUX_IPSR_DATA(IP5_9_6, VI3_VSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_9_6, VI1_G2, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_9_6, VI1_G2_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP5_9_6, VI1_G2, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP5_9_6, VI1_G2_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP5_9_6, VI2_R4),
- PINMUX_IPSR_MODSEL_DATA(IP5_9_6, IIC1_SDA, SEL_IIC1_0),
+ PINMUX_IPSR_MSEL(IP5_9_6, IIC1_SDA, SEL_IIC1_0),
PINMUX_IPSR_DATA(IP5_9_6, INTC_EN1_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_9_6, I2C1_SDA, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP5_9_6, I2C1_SDA, SEL_I2C1_0),
PINMUX_IPSR_DATA(IP5_12_10, BS_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_12_10, IETX, SEL_IEB_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_12_10, HTX1_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_12_10, CAN1_TX, SEL_CAN1_0),
+ PINMUX_IPSR_MSEL(IP5_12_10, IETX, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP5_12_10, HTX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP5_12_10, CAN1_TX, SEL_CAN1_0),
PINMUX_IPSR_DATA(IP5_12_10, DRACK0),
- PINMUX_IPSR_MODSEL_DATA(IP5_12_10, IETX_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP5_12_10, IETX_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP5_14_13, RD_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_13, CAN0_TX, SEL_CAN0_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_13, SCIFA0_SCK_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP5_14_13, CAN0_TX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP5_14_13, SCIFA0_SCK_B, SEL_SCFA_1),
PINMUX_IPSR_DATA(IP5_17_15, RD_WR_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_17_15, VI1_G3, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_17_15, VI1_G3_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP5_17_15, VI1_G3, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP5_17_15, VI1_G3_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP5_17_15, VI2_R5),
- PINMUX_IPSR_MODSEL_DATA(IP5_17_15, SCIFA0_RXD_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP5_17_15, SCIFA0_RXD_B, SEL_SCFA_1),
PINMUX_IPSR_DATA(IP5_17_15, INTC_IRQ4_N),
PINMUX_IPSR_DATA(IP5_20_18, WE0_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, IECLK, SEL_IEB_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, CAN_CLK, SEL_CANCLK_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, VI2_VSYNC_N, SEL_VI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, SCIFA0_TXD_B, SEL_SCFA_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, VI2_VSYNC_N_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP5_20_18, IECLK, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP5_20_18, CAN_CLK, SEL_CANCLK_0),
+ PINMUX_IPSR_MSEL(IP5_20_18, VI2_VSYNC_N, SEL_VI2_0),
+ PINMUX_IPSR_MSEL(IP5_20_18, SCIFA0_TXD_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP5_20_18, VI2_VSYNC_N_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP5_23_21, WE1_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, IERX, SEL_IEB_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, CAN1_RX, SEL_CAN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, VI1_G4, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, VI1_G4_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP5_23_21, IERX, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP5_23_21, CAN1_RX, SEL_CAN1_0),
+ PINMUX_IPSR_MSEL(IP5_23_21, VI1_G4, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP5_23_21, VI1_G4_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP5_23_21, VI2_R6),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, SCIFA0_CTS_N_B, SEL_SCFA_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_21, IERX_C, SEL_IEB_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_24, EX_WAIT0, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP5_23_21, SCIFA0_CTS_N_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP5_23_21, IERX_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP5_26_24, EX_WAIT0, SEL_LBS_0),
PINMUX_IPSR_DATA(IP5_26_24, IRQ3),
PINMUX_IPSR_DATA(IP5_26_24, INTC_IRQ3_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_24, VI3_CLK, SEL_VI3_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_24, SCIFA0_RTS_N_B, SEL_SCFA_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_24, HRX0_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_24, MSIOF0_SCK_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP5_26_24, VI3_CLK, SEL_VI3_0),
+ PINMUX_IPSR_MSEL(IP5_26_24, SCIFA0_RTS_N_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP5_26_24, HRX0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP5_26_24, MSIOF0_SCK_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP5_29_27, DREQ0_N),
- PINMUX_IPSR_MODSEL_DATA(IP5_29_27, VI1_HSYNC_N, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_29_27, VI1_HSYNC_N_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP5_29_27, VI1_HSYNC_N, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP5_29_27, VI1_HSYNC_N_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP5_29_27, VI2_R7),
- PINMUX_IPSR_MODSEL_DATA(IP5_29_27, SSI_SCK78_C, SEL_SSI7_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_29_27, SSI_WS78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP5_29_27, SSI_SCK78_C, SEL_SSI7_2),
+ PINMUX_IPSR_MSEL(IP5_29_27, SSI_WS78_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP6_2_0, DACK0),
PINMUX_IPSR_DATA(IP6_2_0, IRQ0),
PINMUX_IPSR_DATA(IP6_2_0, INTC_IRQ0_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SSI_SCK6_B, SEL_SSI6_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, VI1_VSYNC_N, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, VI1_VSYNC_N_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SSI_WS78_C, SEL_SSI7_2),
+ PINMUX_IPSR_MSEL(IP6_2_0, SSI_SCK6_B, SEL_SSI6_1),
+ PINMUX_IPSR_MSEL(IP6_2_0, VI1_VSYNC_N, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP6_2_0, VI1_VSYNC_N_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP6_2_0, SSI_WS78_C, SEL_SSI7_2),
PINMUX_IPSR_DATA(IP6_5_3, DREQ1_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, VI1_CLKENB, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, VI1_CLKENB_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SSI_SDATA7_C, SEL_SSI7_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SSI_SCK78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP6_5_3, VI1_CLKENB, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP6_5_3, VI1_CLKENB_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP6_5_3, SSI_SDATA7_C, SEL_SSI7_2),
+ PINMUX_IPSR_MSEL(IP6_5_3, SSI_SCK78_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP6_8_6, DACK1),
PINMUX_IPSR_DATA(IP6_8_6, IRQ1),
PINMUX_IPSR_DATA(IP6_8_6, INTC_IRQ1_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_8_6, SSI_WS6_B, SEL_SSI6_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_8_6, SSI_SDATA8_C, SEL_SSI8_2),
+ PINMUX_IPSR_MSEL(IP6_8_6, SSI_WS6_B, SEL_SSI6_1),
+ PINMUX_IPSR_MSEL(IP6_8_6, SSI_SDATA8_C, SEL_SSI8_2),
PINMUX_IPSR_DATA(IP6_10_9, DREQ2_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_10_9, HSCK1_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_10_9, HCTS0_N_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_10_9, MSIOF0_TXD_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP6_10_9, HSCK1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP6_10_9, HCTS0_N_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_10_9, MSIOF0_TXD_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP6_13_11, DACK2),
PINMUX_IPSR_DATA(IP6_13_11, IRQ2),
PINMUX_IPSR_DATA(IP6_13_11, INTC_IRQ2_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_13_11, SSI_SDATA6_B, SEL_SSI6_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_13_11, HRTS0_N_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_13_11, MSIOF0_RXD_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP6_13_11, SSI_SDATA6_B, SEL_SSI6_1),
+ PINMUX_IPSR_MSEL(IP6_13_11, HRTS0_N_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_13_11, MSIOF0_RXD_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP6_16_14, ETH_CRS_DV),
- PINMUX_IPSR_MODSEL_DATA(IP6_16_14, STP_ISCLK_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_16_14, TS_SDEN0_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_16_14, GLO_Q0_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_16_14, IIC2_SCL_E, SEL_IIC2_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_16_14, I2C2_SCL_E, SEL_I2C2_4),
+ PINMUX_IPSR_MSEL(IP6_16_14, STP_ISCLK_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_16_14, TS_SDEN0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP6_16_14, GLO_Q0_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP6_16_14, IIC2_SCL_E, SEL_IIC2_4),
+ PINMUX_IPSR_MSEL(IP6_16_14, I2C2_SCL_E, SEL_I2C2_4),
PINMUX_IPSR_DATA(IP6_19_17, ETH_RX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, STP_ISD_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, TS_SPSYNC0_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, GLO_Q1_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, IIC2_SDA_E, SEL_IIC2_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, I2C2_SDA_E, SEL_I2C2_4),
+ PINMUX_IPSR_MSEL(IP6_19_17, STP_ISD_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_19_17, TS_SPSYNC0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP6_19_17, GLO_Q1_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP6_19_17, IIC2_SDA_E, SEL_IIC2_4),
+ PINMUX_IPSR_MSEL(IP6_19_17, I2C2_SDA_E, SEL_I2C2_4),
PINMUX_IPSR_DATA(IP6_22_20, ETH_RXD0),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, STP_ISEN_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, TS_SDAT0_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, GLO_I0_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCIFB1_SCK_G, SEL_SCIFB1_6),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCK1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MSEL(IP6_22_20, STP_ISEN_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_22_20, TS_SDAT0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP6_22_20, GLO_I0_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP6_22_20, SCIFB1_SCK_G, SEL_SCIFB1_6),
+ PINMUX_IPSR_MSEL(IP6_22_20, SCK1_E, SEL_SCIF1_4),
PINMUX_IPSR_DATA(IP6_25_23, ETH_RXD1),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, HRX0_E, SEL_HSCIF0_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, STP_ISSYNC_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, TS_SCK0_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, GLO_I1_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, SCIFB1_RXD_G, SEL_SCIFB1_6),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, RX1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MSEL(IP6_25_23, HRX0_E, SEL_HSCIF0_4),
+ PINMUX_IPSR_MSEL(IP6_25_23, STP_ISSYNC_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_25_23, TS_SCK0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP6_25_23, GLO_I1_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP6_25_23, SCIFB1_RXD_G, SEL_SCIFB1_6),
+ PINMUX_IPSR_MSEL(IP6_25_23, RX1_E, SEL_SCIF1_4),
PINMUX_IPSR_DATA(IP6_28_26, ETH_LINK),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, HTX0_E, SEL_HSCIF0_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, STP_IVCXO27_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, SCIFB1_TXD_G, SEL_SCIFB1_6),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, TX1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MSEL(IP6_28_26, HTX0_E, SEL_HSCIF0_4),
+ PINMUX_IPSR_MSEL(IP6_28_26, STP_IVCXO27_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_28_26, SCIFB1_TXD_G, SEL_SCIFB1_6),
+ PINMUX_IPSR_MSEL(IP6_28_26, TX1_E, SEL_SCIF1_4),
PINMUX_IPSR_DATA(IP6_31_29, ETH_REF_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, HCTS0_N_E, SEL_HSCIF0_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, STP_IVCXO27_1_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, HRX0_F, SEL_HSCIF0_5),
+ PINMUX_IPSR_MSEL(IP6_31_29, HCTS0_N_E, SEL_HSCIF0_4),
+ PINMUX_IPSR_MSEL(IP6_31_29, STP_IVCXO27_1_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_31_29, HRX0_F, SEL_HSCIF0_5),
PINMUX_IPSR_DATA(IP7_2_0, ETH_MDIO),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, HRTS0_N_E, SEL_HSCIF0_4),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, SIM0_D_C, SEL_SIM_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, HCTS0_N_F, SEL_HSCIF0_5),
+ PINMUX_IPSR_MSEL(IP7_2_0, HRTS0_N_E, SEL_HSCIF0_4),
+ PINMUX_IPSR_MSEL(IP7_2_0, SIM0_D_C, SEL_SIM_2),
+ PINMUX_IPSR_MSEL(IP7_2_0, HCTS0_N_F, SEL_HSCIF0_5),
PINMUX_IPSR_DATA(IP7_5_3, ETH_TXD1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, HTX0_F, SEL_HSCIF0_5),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, BPFCLK_G, SEL_FM_6),
+ PINMUX_IPSR_MSEL(IP7_5_3, HTX0_F, SEL_HSCIF0_5),
+ PINMUX_IPSR_MSEL(IP7_5_3, BPFCLK_G, SEL_FM_6),
PINMUX_IPSR_DATA(IP7_7_6, ETH_TX_EN),
- PINMUX_IPSR_MODSEL_DATA(IP7_7_6, SIM0_CLK_C, SEL_SIM_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_7_6, HRTS0_N_F, SEL_HSCIF0_5),
+ PINMUX_IPSR_MSEL(IP7_7_6, SIM0_CLK_C, SEL_SIM_2),
+ PINMUX_IPSR_MSEL(IP7_7_6, HRTS0_N_F, SEL_HSCIF0_5),
PINMUX_IPSR_DATA(IP7_9_8, ETH_MAGIC),
- PINMUX_IPSR_MODSEL_DATA(IP7_9_8, SIM0_RST_C, SEL_SIM_2),
+ PINMUX_IPSR_MSEL(IP7_9_8, SIM0_RST_C, SEL_SIM_2),
PINMUX_IPSR_DATA(IP7_12_10, ETH_TXD0),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_10, STP_ISCLK_1_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_10, TS_SDEN1_C, SEL_TSIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_10, GLO_SCLK_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP7_12_10, STP_ISCLK_1_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP7_12_10, TS_SDEN1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP7_12_10, GLO_SCLK_C, SEL_GPS_2),
PINMUX_IPSR_DATA(IP7_15_13, ETH_MDC),
- PINMUX_IPSR_MODSEL_DATA(IP7_15_13, STP_ISD_1_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_15_13, TS_SPSYNC1_C, SEL_TSIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_15_13, GLO_SDATA_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP7_15_13, STP_ISD_1_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP7_15_13, TS_SPSYNC1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP7_15_13, GLO_SDATA_C, SEL_GPS_2),
PINMUX_IPSR_DATA(IP7_18_16, PWM0),
- PINMUX_IPSR_MODSEL_DATA(IP7_18_16, SCIFA2_SCK_C, SEL_SCIFA2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_18_16, STP_ISEN_1_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_18_16, TS_SDAT1_C, SEL_TSIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_18_16, GLO_SS_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP7_18_16, SCIFA2_SCK_C, SEL_SCIFA2_2),
+ PINMUX_IPSR_MSEL(IP7_18_16, STP_ISEN_1_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP7_18_16, TS_SDAT1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP7_18_16, GLO_SS_C, SEL_GPS_2),
PINMUX_IPSR_DATA(IP7_21_19, PWM1),
- PINMUX_IPSR_MODSEL_DATA(IP7_21_19, SCIFA2_TXD_C, SEL_SCIFA2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_21_19, STP_ISSYNC_1_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_21_19, TS_SCK1_C, SEL_TSIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_21_19, GLO_RFON_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP7_21_19, SCIFA2_TXD_C, SEL_SCIFA2_2),
+ PINMUX_IPSR_MSEL(IP7_21_19, STP_ISSYNC_1_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP7_21_19, TS_SCK1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP7_21_19, GLO_RFON_C, SEL_GPS_2),
PINMUX_IPSR_DATA(IP7_21_19, PCMOE_N),
PINMUX_IPSR_DATA(IP7_24_22, PWM2),
PINMUX_IPSR_DATA(IP7_24_22, PWMFSW0),
- PINMUX_IPSR_MODSEL_DATA(IP7_24_22, SCIFA2_RXD_C, SEL_SCIFA2_2),
+ PINMUX_IPSR_MSEL(IP7_24_22, SCIFA2_RXD_C, SEL_SCIFA2_2),
PINMUX_IPSR_DATA(IP7_24_22, PCMWE_N),
- PINMUX_IPSR_MODSEL_DATA(IP7_24_22, IECLK_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP7_24_22, IECLK_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP7_26_25, DU_DOTCLKIN1),
PINMUX_IPSR_DATA(IP7_26_25, AUDIO_CLKC),
PINMUX_IPSR_DATA(IP7_26_25, AUDIO_CLKOUT_C),
- PINMUX_IPSR_MODSEL_DATA(IP7_28_27, VI0_CLK, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP7_28_27, VI0_CLK, SEL_VI0_0),
PINMUX_IPSR_DATA(IP7_28_27, ATACS00_N),
PINMUX_IPSR_DATA(IP7_28_27, AVB_RXD1),
- PINMUX_IPSR_MODSEL_DATA(IP7_30_29, VI0_DATA0_VI0_B0, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP7_30_29, VI0_DATA0_VI0_B0, SEL_VI0_0),
PINMUX_IPSR_DATA(IP7_30_29, ATACS10_N),
PINMUX_IPSR_DATA(IP7_30_29, AVB_RXD2),
- PINMUX_IPSR_MODSEL_DATA(IP8_1_0, VI0_DATA1_VI0_B1, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_1_0, VI0_DATA1_VI0_B1, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_1_0, ATARD0_N),
PINMUX_IPSR_DATA(IP8_1_0, AVB_RXD3),
- PINMUX_IPSR_MODSEL_DATA(IP8_3_2, VI0_DATA2_VI0_B2, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_3_2, VI0_DATA2_VI0_B2, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_3_2, ATAWR0_N),
PINMUX_IPSR_DATA(IP8_3_2, AVB_RXD4),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_4, VI0_DATA3_VI0_B3, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_5_4, VI0_DATA3_VI0_B3, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_5_4, ATADIR0_N),
PINMUX_IPSR_DATA(IP8_5_4, AVB_RXD5),
- PINMUX_IPSR_MODSEL_DATA(IP8_7_6, VI0_DATA4_VI0_B4, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_7_6, VI0_DATA4_VI0_B4, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_7_6, ATAG0_N),
PINMUX_IPSR_DATA(IP8_7_6, AVB_RXD6),
- PINMUX_IPSR_MODSEL_DATA(IP8_9_8, VI0_DATA5_VI0_B5, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_9_8, VI0_DATA5_VI0_B5, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_9_8, EX_WAIT1),
PINMUX_IPSR_DATA(IP8_9_8, AVB_RXD7),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_10, VI0_DATA6_VI0_B6, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_11_10, VI0_DATA6_VI0_B6, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_11_10, AVB_RX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP8_13_12, VI0_DATA7_VI0_B7, SEL_VI0_0),
+ PINMUX_IPSR_MSEL(IP8_13_12, VI0_DATA7_VI0_B7, SEL_VI0_0),
PINMUX_IPSR_DATA(IP8_13_12, AVB_RX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP8_15_14, VI1_CLK, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_15_14, VI1_CLK, SEL_VI1_0),
PINMUX_IPSR_DATA(IP8_15_14, AVB_RX_DV),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_16, VI1_DATA0_VI1_B0, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_16, SCIFA1_SCK_D, SEL_SCIFA1_3),
+ PINMUX_IPSR_MSEL(IP8_17_16, VI1_DATA0_VI1_B0, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_17_16, SCIFA1_SCK_D, SEL_SCIFA1_3),
PINMUX_IPSR_DATA(IP8_17_16, AVB_CRS),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_18, VI1_DATA1_VI1_B1, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_18, SCIFA1_RXD_D, SEL_SCIFA1_3),
+ PINMUX_IPSR_MSEL(IP8_19_18, VI1_DATA1_VI1_B1, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_19_18, SCIFA1_RXD_D, SEL_SCIFA1_3),
PINMUX_IPSR_DATA(IP8_19_18, AVB_MDC),
- PINMUX_IPSR_MODSEL_DATA(IP8_21_20, VI1_DATA2_VI1_B2, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_21_20, SCIFA1_TXD_D, SEL_SCIFA1_3),
+ PINMUX_IPSR_MSEL(IP8_21_20, VI1_DATA2_VI1_B2, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_21_20, SCIFA1_TXD_D, SEL_SCIFA1_3),
PINMUX_IPSR_DATA(IP8_21_20, AVB_MDIO),
- PINMUX_IPSR_MODSEL_DATA(IP8_23_22, VI1_DATA3_VI1_B3, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_23_22, SCIFA1_CTS_N_D, SEL_SCIFA1_3),
+ PINMUX_IPSR_MSEL(IP8_23_22, VI1_DATA3_VI1_B3, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_23_22, SCIFA1_CTS_N_D, SEL_SCIFA1_3),
PINMUX_IPSR_DATA(IP8_23_22, AVB_GTX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_24, VI1_DATA4_VI1_B4, SEL_VI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_24, SCIFA1_RTS_N_D, SEL_SCIFA1_3),
+ PINMUX_IPSR_MSEL(IP8_25_24, VI1_DATA4_VI1_B4, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_25_24, SCIFA1_RTS_N_D, SEL_SCIFA1_3),
PINMUX_IPSR_DATA(IP8_25_24, AVB_MAGIC),
- PINMUX_IPSR_MODSEL_DATA(IP8_26, VI1_DATA5_VI1_B5, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_26, VI1_DATA5_VI1_B5, SEL_VI1_0),
PINMUX_IPSR_DATA(IP8_26, AVB_PHY_INT),
- PINMUX_IPSR_MODSEL_DATA(IP8_27, VI1_DATA6_VI1_B6, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP8_27, VI1_DATA6_VI1_B6, SEL_VI1_0),
PINMUX_IPSR_DATA(IP8_27, AVB_GTXREFCLK),
PINMUX_IPSR_DATA(IP8_28, SD0_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP8_28, VI1_DATA0_VI1_B0_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_28, VI1_DATA0_VI1_B0_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP8_30_29, SD0_CMD),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_29, SCIFB1_SCK_B, SEL_SCIFB1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_29, VI1_DATA1_VI1_B1_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_30_29, SCIFB1_SCK_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP8_30_29, VI1_DATA1_VI1_B1_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP9_1_0, SD0_DAT0),
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, SCIFB1_RXD_B, SEL_SCIFB1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, VI1_DATA2_VI1_B2_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP9_1_0, SCIFB1_RXD_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP9_1_0, VI1_DATA2_VI1_B2_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP9_3_2, SD0_DAT1),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, SCIFB1_TXD_B, SEL_SCIFB1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, VI1_DATA3_VI1_B3_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP9_3_2, SCIFB1_TXD_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP9_3_2, VI1_DATA3_VI1_B3_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP9_5_4, SD0_DAT2),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_4, SCIFB1_CTS_N_B, SEL_SCIFB1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_4, VI1_DATA4_VI1_B4_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP9_5_4, SCIFB1_CTS_N_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP9_5_4, VI1_DATA4_VI1_B4_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP9_7_6, SD0_DAT3),
- PINMUX_IPSR_MODSEL_DATA(IP9_7_6, SCIFB1_RTS_N_B, SEL_SCIFB1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_7_6, VI1_DATA5_VI1_B5_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP9_7_6, SCIFB1_RTS_N_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP9_7_6, VI1_DATA5_VI1_B5_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP9_11_8, SD0_CD),
PINMUX_IPSR_DATA(IP9_11_8, MMC0_D6),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_8, TS_SDEN0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP9_11_8, TS_SDEN0_B, SEL_TSIF0_1),
PINMUX_IPSR_DATA(IP9_11_8, USB0_EXTP),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_8, GLO_SCLK, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_8, VI1_DATA6_VI1_B6_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_8, IIC1_SCL_B, SEL_IIC1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_8, I2C1_SCL_B, SEL_I2C1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_8, VI2_DATA6_VI2_B6_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP9_11_8, GLO_SCLK, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP9_11_8, VI1_DATA6_VI1_B6_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP9_11_8, IIC1_SCL_B, SEL_IIC1_1),
+ PINMUX_IPSR_MSEL(IP9_11_8, I2C1_SCL_B, SEL_I2C1_1),
+ PINMUX_IPSR_MSEL(IP9_11_8, VI2_DATA6_VI2_B6_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP9_15_12, SD0_WP),
PINMUX_IPSR_DATA(IP9_15_12, MMC0_D7),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_12, TS_SPSYNC0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP9_15_12, TS_SPSYNC0_B, SEL_TSIF0_1),
PINMUX_IPSR_DATA(IP9_15_12, USB0_IDIN),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_12, GLO_SDATA, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_12, VI1_DATA7_VI1_B7_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_12, IIC1_SDA_B, SEL_IIC1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_12, I2C1_SDA_B, SEL_I2C1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_12, VI2_DATA7_VI2_B7_B, SEL_VI2_1),
+ PINMUX_IPSR_MSEL(IP9_15_12, GLO_SDATA, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP9_15_12, VI1_DATA7_VI1_B7_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP9_15_12, IIC1_SDA_B, SEL_IIC1_1),
+ PINMUX_IPSR_MSEL(IP9_15_12, I2C1_SDA_B, SEL_I2C1_1),
+ PINMUX_IPSR_MSEL(IP9_15_12, VI2_DATA7_VI2_B7_B, SEL_VI2_1),
PINMUX_IPSR_DATA(IP9_17_16, SD1_CLK),
PINMUX_IPSR_DATA(IP9_17_16, AVB_TX_EN),
PINMUX_IPSR_DATA(IP9_19_18, SD1_CMD),
PINMUX_IPSR_DATA(IP9_19_18, AVB_TX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP9_19_18, SCIFB0_SCK_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP9_19_18, SCIFB0_SCK_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP9_21_20, SD1_DAT0),
PINMUX_IPSR_DATA(IP9_21_20, AVB_TX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_20, SCIFB0_RXD_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP9_21_20, SCIFB0_RXD_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP9_23_22, SD1_DAT1),
PINMUX_IPSR_DATA(IP9_23_22, AVB_LINK),
- PINMUX_IPSR_MODSEL_DATA(IP9_23_22, SCIFB0_TXD_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP9_23_22, SCIFB0_TXD_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP9_25_24, SD1_DAT2),
PINMUX_IPSR_DATA(IP9_25_24, AVB_COL),
- PINMUX_IPSR_MODSEL_DATA(IP9_25_24, SCIFB0_CTS_N_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP9_25_24, SCIFB0_CTS_N_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP9_27_26, SD1_DAT3),
PINMUX_IPSR_DATA(IP9_27_26, AVB_RXD0),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_26, SCIFB0_RTS_N_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP9_27_26, SCIFB0_RTS_N_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP9_31_28, SD1_CD),
PINMUX_IPSR_DATA(IP9_31_28, MMC1_D6),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, TS_SDEN1, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP9_31_28, TS_SDEN1, SEL_TSIF1_0),
PINMUX_IPSR_DATA(IP9_31_28, USB1_EXTP),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, GLO_SS, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, VI0_CLK_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, IIC2_SCL_D, SEL_IIC2_3),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, I2C2_SCL_D, SEL_I2C2_3),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, SIM0_CLK_B, SEL_SIM_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_28, VI3_CLK_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP9_31_28, GLO_SS, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP9_31_28, VI0_CLK_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP9_31_28, IIC2_SCL_D, SEL_IIC2_3),
+ PINMUX_IPSR_MSEL(IP9_31_28, I2C2_SCL_D, SEL_I2C2_3),
+ PINMUX_IPSR_MSEL(IP9_31_28, SIM0_CLK_B, SEL_SIM_1),
+ PINMUX_IPSR_MSEL(IP9_31_28, VI3_CLK_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_3_0, SD1_WP),
PINMUX_IPSR_DATA(IP10_3_0, MMC1_D7),
- PINMUX_IPSR_MODSEL_DATA(IP10_3_0, TS_SPSYNC1, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP10_3_0, TS_SPSYNC1, SEL_TSIF1_0),
PINMUX_IPSR_DATA(IP10_3_0, USB1_IDIN),
- PINMUX_IPSR_MODSEL_DATA(IP10_3_0, GLO_RFON, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_3_0, VI1_CLK_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_3_0, IIC2_SDA_D, SEL_IIC2_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_3_0, I2C2_SDA_D, SEL_I2C2_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_3_0, SIM0_D_B, SEL_SIM_1),
+ PINMUX_IPSR_MSEL(IP10_3_0, GLO_RFON, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP10_3_0, VI1_CLK_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP10_3_0, IIC2_SDA_D, SEL_IIC2_3),
+ PINMUX_IPSR_MSEL(IP10_3_0, I2C2_SDA_D, SEL_I2C2_3),
+ PINMUX_IPSR_MSEL(IP10_3_0, SIM0_D_B, SEL_SIM_1),
PINMUX_IPSR_DATA(IP10_6_4, SD2_CLK),
PINMUX_IPSR_DATA(IP10_6_4, MMC0_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP10_6_4, SIM0_CLK, SEL_SIM_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_6_4, VI0_DATA0_VI0_B0_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_6_4, TS_SDEN0_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_6_4, GLO_SCLK_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_6_4, VI3_DATA0_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_6_4, SIM0_CLK, SEL_SIM_0),
+ PINMUX_IPSR_MSEL(IP10_6_4, VI0_DATA0_VI0_B0_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_6_4, TS_SDEN0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_6_4, GLO_SCLK_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_6_4, VI3_DATA0_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_10_7, SD2_CMD),
PINMUX_IPSR_DATA(IP10_10_7, MMC0_CMD),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, SIM0_D, SEL_SIM_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, VI0_DATA1_VI0_B1_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, SCIFB1_SCK_E, SEL_SCIFB1_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, SCK1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, TS_SPSYNC0_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, GLO_SDATA_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_10_7, VI3_DATA1_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_10_7, SIM0_D, SEL_SIM_0),
+ PINMUX_IPSR_MSEL(IP10_10_7, VI0_DATA1_VI0_B1_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_10_7, SCIFB1_SCK_E, SEL_SCIFB1_4),
+ PINMUX_IPSR_MSEL(IP10_10_7, SCK1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_10_7, TS_SPSYNC0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_10_7, GLO_SDATA_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_10_7, VI3_DATA1_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_14_11, SD2_DAT0),
PINMUX_IPSR_DATA(IP10_14_11, MMC0_D0),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, FMCLK_B, SEL_FM_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, VI0_DATA2_VI0_B2_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, SCIFB1_RXD_E, SEL_SCIFB1_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, RX1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, TS_SDAT0_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, GLO_SS_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_11, VI3_DATA2_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_14_11, FMCLK_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP10_14_11, VI0_DATA2_VI0_B2_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_14_11, SCIFB1_RXD_E, SEL_SCIFB1_4),
+ PINMUX_IPSR_MSEL(IP10_14_11, RX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_14_11, TS_SDAT0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_14_11, GLO_SS_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_14_11, VI3_DATA2_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_18_15, SD2_DAT1),
PINMUX_IPSR_DATA(IP10_18_15, MMC0_D1),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, FMIN_B, SEL_FM_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, VI0_DATA3_VI0_B3_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, SCIFB1_TXD_E, SEL_SCIFB1_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, TX1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, TS_SCK0_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, GLO_RFON_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_15, VI3_DATA3_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_18_15, FMIN_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP10_18_15, VI0_DATA3_VI0_B3_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_18_15, SCIFB1_TXD_E, SEL_SCIFB1_4),
+ PINMUX_IPSR_MSEL(IP10_18_15, TX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_18_15, TS_SCK0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_18_15, GLO_RFON_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_18_15, VI3_DATA3_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_22_19, SD2_DAT2),
PINMUX_IPSR_DATA(IP10_22_19, MMC0_D2),
- PINMUX_IPSR_MODSEL_DATA(IP10_22_19, BPFCLK_B, SEL_FM_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_22_19, VI0_DATA4_VI0_B4_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_22_19, HRX0_D, SEL_HSCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_22_19, TS_SDEN1_B, SEL_TSIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_22_19, GLO_Q0_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_22_19, VI3_DATA4_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_22_19, BPFCLK_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP10_22_19, VI0_DATA4_VI0_B4_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_22_19, HRX0_D, SEL_HSCIF0_3),
+ PINMUX_IPSR_MSEL(IP10_22_19, TS_SDEN1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP10_22_19, GLO_Q0_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_22_19, VI3_DATA4_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_25_23, SD2_DAT3),
PINMUX_IPSR_DATA(IP10_25_23, MMC0_D3),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_23, SIM0_RST, SEL_SIM_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_23, VI0_DATA5_VI0_B5_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_23, HTX0_D, SEL_HSCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_23, TS_SPSYNC1_B, SEL_TSIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_23, GLO_Q1_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_25_23, VI3_DATA5_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_25_23, SIM0_RST, SEL_SIM_0),
+ PINMUX_IPSR_MSEL(IP10_25_23, VI0_DATA5_VI0_B5_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_25_23, HTX0_D, SEL_HSCIF0_3),
+ PINMUX_IPSR_MSEL(IP10_25_23, TS_SPSYNC1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP10_25_23, GLO_Q1_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_25_23, VI3_DATA5_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP10_29_26, SD2_CD),
PINMUX_IPSR_DATA(IP10_29_26, MMC0_D4),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, TS_SDAT0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP10_29_26, TS_SDAT0_B, SEL_TSIF0_1),
PINMUX_IPSR_DATA(IP10_29_26, USB2_EXTP),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, GLO_I0, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, VI0_DATA6_VI0_B6_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, HCTS0_N_D, SEL_HSCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, TS_SDAT1_B, SEL_TSIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, GLO_I0_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_26, VI3_DATA6_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP10_29_26, GLO_I0, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP10_29_26, VI0_DATA6_VI0_B6_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP10_29_26, HCTS0_N_D, SEL_HSCIF0_3),
+ PINMUX_IPSR_MSEL(IP10_29_26, TS_SDAT1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP10_29_26, GLO_I0_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_29_26, VI3_DATA6_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP11_3_0, SD2_WP),
PINMUX_IPSR_DATA(IP11_3_0, MMC0_D5),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, TS_SCK0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP11_3_0, TS_SCK0_B, SEL_TSIF0_1),
PINMUX_IPSR_DATA(IP11_3_0, USB2_IDIN),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, GLO_I1, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, VI0_DATA7_VI0_B7_B, SEL_VI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, HRTS0_N_D, SEL_HSCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, TS_SCK1_B, SEL_TSIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, GLO_I1_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_3_0, VI3_DATA7_B, SEL_VI3_1),
+ PINMUX_IPSR_MSEL(IP11_3_0, GLO_I1, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP11_3_0, VI0_DATA7_VI0_B7_B, SEL_VI0_1),
+ PINMUX_IPSR_MSEL(IP11_3_0, HRTS0_N_D, SEL_HSCIF0_3),
+ PINMUX_IPSR_MSEL(IP11_3_0, TS_SCK1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP11_3_0, GLO_I1_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP11_3_0, VI3_DATA7_B, SEL_VI3_1),
PINMUX_IPSR_DATA(IP11_4, SD3_CLK),
PINMUX_IPSR_DATA(IP11_4, MMC1_CLK),
PINMUX_IPSR_DATA(IP11_6_5, SD3_CMD),
@@ -1447,298 +1446,298 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP11_14_13, SCKZ),
PINMUX_IPSR_DATA(IP11_17_15, SD3_CD),
PINMUX_IPSR_DATA(IP11_17_15, MMC1_D4),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_15, TS_SDAT1, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP11_17_15, TS_SDAT1, SEL_TSIF1_0),
PINMUX_IPSR_DATA(IP11_17_15, VSP),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_15, GLO_Q0, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_15, SIM0_RST_B, SEL_SIM_1),
+ PINMUX_IPSR_MSEL(IP11_17_15, GLO_Q0, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP11_17_15, SIM0_RST_B, SEL_SIM_1),
PINMUX_IPSR_DATA(IP11_21_18, SD3_WP),
PINMUX_IPSR_DATA(IP11_21_18, MMC1_D5),
- PINMUX_IPSR_MODSEL_DATA(IP11_21_18, TS_SCK1, SEL_TSIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_21_18, GLO_Q1, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_21_18, FMIN_C, SEL_FM_2),
- PINMUX_IPSR_MODSEL_DATA(IP11_21_18, FMIN_E, SEL_FM_4),
- PINMUX_IPSR_MODSEL_DATA(IP11_21_18, FMIN_F, SEL_FM_5),
+ PINMUX_IPSR_MSEL(IP11_21_18, TS_SCK1, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP11_21_18, GLO_Q1, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP11_21_18, FMIN_C, SEL_FM_2),
+ PINMUX_IPSR_MSEL(IP11_21_18, FMIN_E, SEL_FM_4),
+ PINMUX_IPSR_MSEL(IP11_21_18, FMIN_F, SEL_FM_5),
PINMUX_IPSR_DATA(IP11_23_22, MLB_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_22, IIC2_SCL_B, SEL_IIC2_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_22, I2C2_SCL_B, SEL_I2C2_1),
+ PINMUX_IPSR_MSEL(IP11_23_22, IIC2_SCL_B, SEL_IIC2_1),
+ PINMUX_IPSR_MSEL(IP11_23_22, I2C2_SCL_B, SEL_I2C2_1),
PINMUX_IPSR_DATA(IP11_26_24, MLB_SIG),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, SCIFB1_RXD_D, SEL_SCIFB1_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, RX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, IIC2_SDA_B, SEL_IIC2_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, I2C2_SDA_B, SEL_I2C2_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, SCIFB1_RXD_D, SEL_SCIFB1_3),
+ PINMUX_IPSR_MSEL(IP11_26_24, RX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP11_26_24, IIC2_SDA_B, SEL_IIC2_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, I2C2_SDA_B, SEL_I2C2_1),
PINMUX_IPSR_DATA(IP11_29_27, MLB_DAT),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, SCIFB1_TXD_D, SEL_SCIFB1_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, TX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, BPFCLK_C, SEL_FM_2),
+ PINMUX_IPSR_MSEL(IP11_29_27, SCIFB1_TXD_D, SEL_SCIFB1_3),
+ PINMUX_IPSR_MSEL(IP11_29_27, TX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP11_29_27, BPFCLK_C, SEL_FM_2),
PINMUX_IPSR_DATA(IP11_31_30, SSI_SCK0129),
- PINMUX_IPSR_MODSEL_DATA(IP11_31_30, CAN_CLK_B, SEL_CANCLK_1),
+ PINMUX_IPSR_MSEL(IP11_31_30, CAN_CLK_B, SEL_CANCLK_1),
PINMUX_IPSR_DATA(IP11_31_30, MOUT0),
PINMUX_IPSR_DATA(IP12_1_0, SSI_WS0129),
- PINMUX_IPSR_MODSEL_DATA(IP12_1_0, CAN0_TX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP12_1_0, CAN0_TX_B, SEL_CAN0_1),
PINMUX_IPSR_DATA(IP12_1_0, MOUT1),
PINMUX_IPSR_DATA(IP12_3_2, SSI_SDATA0),
- PINMUX_IPSR_MODSEL_DATA(IP12_3_2, CAN0_RX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP12_3_2, CAN0_RX_B, SEL_CAN0_1),
PINMUX_IPSR_DATA(IP12_3_2, MOUT2),
PINMUX_IPSR_DATA(IP12_5_4, SSI_SDATA1),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_4, CAN1_TX_B, SEL_CAN1_1),
+ PINMUX_IPSR_MSEL(IP12_5_4, CAN1_TX_B, SEL_CAN1_1),
PINMUX_IPSR_DATA(IP12_5_4, MOUT5),
PINMUX_IPSR_DATA(IP12_7_6, SSI_SDATA2),
- PINMUX_IPSR_MODSEL_DATA(IP12_7_6, CAN1_RX_B, SEL_CAN1_1),
+ PINMUX_IPSR_MSEL(IP12_7_6, CAN1_RX_B, SEL_CAN1_1),
PINMUX_IPSR_DATA(IP12_7_6, SSI_SCK1),
PINMUX_IPSR_DATA(IP12_7_6, MOUT6),
PINMUX_IPSR_DATA(IP12_10_8, SSI_SCK34),
PINMUX_IPSR_DATA(IP12_10_8, STP_OPWM_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_10_8, SCIFB0_SCK, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_10_8, MSIOF1_SCK, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP12_10_8, SCIFB0_SCK, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP12_10_8, MSIOF1_SCK, SEL_SOF1_0),
PINMUX_IPSR_DATA(IP12_10_8, CAN_DEBUG_HW_TRIGGER),
PINMUX_IPSR_DATA(IP12_13_11, SSI_WS34),
- PINMUX_IPSR_MODSEL_DATA(IP12_13_11, STP_IVCXO27_0, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_13_11, SCIFB0_RXD, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP12_13_11, STP_IVCXO27_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_13_11, SCIFB0_RXD, SEL_SCIFB_0),
PINMUX_IPSR_DATA(IP12_13_11, MSIOF1_SYNC),
PINMUX_IPSR_DATA(IP12_13_11, CAN_STEP0),
PINMUX_IPSR_DATA(IP12_16_14, SSI_SDATA3),
- PINMUX_IPSR_MODSEL_DATA(IP12_16_14, STP_ISCLK_0, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_16_14, SCIFB0_TXD, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_16_14, MSIOF1_SS1, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP12_16_14, STP_ISCLK_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_16_14, SCIFB0_TXD, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP12_16_14, MSIOF1_SS1, SEL_SOF1_0),
PINMUX_IPSR_DATA(IP12_16_14, CAN_TXCLK),
PINMUX_IPSR_DATA(IP12_19_17, SSI_SCK4),
- PINMUX_IPSR_MODSEL_DATA(IP12_19_17, STP_ISD_0, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_19_17, SCIFB0_CTS_N, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_19_17, MSIOF1_SS2, SEL_SOF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_19_17, SSI_SCK5_C, SEL_SSI5_2),
+ PINMUX_IPSR_MSEL(IP12_19_17, STP_ISD_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_19_17, SCIFB0_CTS_N, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP12_19_17, MSIOF1_SS2, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP12_19_17, SSI_SCK5_C, SEL_SSI5_2),
PINMUX_IPSR_DATA(IP12_19_17, CAN_DEBUGOUT0),
PINMUX_IPSR_DATA(IP12_22_20, SSI_WS4),
- PINMUX_IPSR_MODSEL_DATA(IP12_22_20, STP_ISEN_0, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_22_20, SCIFB0_RTS_N, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_22_20, MSIOF1_TXD, SEL_SOF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_22_20, SSI_WS5_C, SEL_SSI5_2),
+ PINMUX_IPSR_MSEL(IP12_22_20, STP_ISEN_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_22_20, SCIFB0_RTS_N, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP12_22_20, MSIOF1_TXD, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP12_22_20, SSI_WS5_C, SEL_SSI5_2),
PINMUX_IPSR_DATA(IP12_22_20, CAN_DEBUGOUT1),
PINMUX_IPSR_DATA(IP12_24_23, SSI_SDATA4),
- PINMUX_IPSR_MODSEL_DATA(IP12_24_23, STP_ISSYNC_0, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_24_23, MSIOF1_RXD, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP12_24_23, STP_ISSYNC_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_24_23, MSIOF1_RXD, SEL_SOF1_0),
PINMUX_IPSR_DATA(IP12_24_23, CAN_DEBUGOUT2),
- PINMUX_IPSR_MODSEL_DATA(IP12_27_25, SSI_SCK5, SEL_SSI5_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_27_25, SCIFB1_SCK, SEL_SCIFB1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_27_25, IERX_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP12_27_25, SSI_SCK5, SEL_SSI5_0),
+ PINMUX_IPSR_MSEL(IP12_27_25, SCIFB1_SCK, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP12_27_25, IERX_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP12_27_25, DU2_EXHSYNC_DU2_HSYNC),
PINMUX_IPSR_DATA(IP12_27_25, QSTH_QHS),
PINMUX_IPSR_DATA(IP12_27_25, CAN_DEBUGOUT3),
- PINMUX_IPSR_MODSEL_DATA(IP12_30_28, SSI_WS5, SEL_SSI5_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_30_28, SCIFB1_RXD, SEL_SCIFB1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_30_28, IECLK_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP12_30_28, SSI_WS5, SEL_SSI5_0),
+ PINMUX_IPSR_MSEL(IP12_30_28, SCIFB1_RXD, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP12_30_28, IECLK_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP12_30_28, DU2_EXVSYNC_DU2_VSYNC),
PINMUX_IPSR_DATA(IP12_30_28, QSTB_QHE),
PINMUX_IPSR_DATA(IP12_30_28, CAN_DEBUGOUT4),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SSI_SDATA5, SEL_SSI5_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SCIFB1_TXD, SEL_SCIFB1_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, IETX_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP13_2_0, SSI_SDATA5, SEL_SSI5_0),
+ PINMUX_IPSR_MSEL(IP13_2_0, SCIFB1_TXD, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP13_2_0, IETX_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP13_2_0, DU2_DR2),
PINMUX_IPSR_DATA(IP13_2_0, LCDOUT2),
PINMUX_IPSR_DATA(IP13_2_0, CAN_DEBUGOUT5),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_3, SSI_SCK6, SEL_SSI6_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_3, SCIFB1_CTS_N, SEL_SCIFB1_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_3, BPFCLK_D, SEL_FM_3),
+ PINMUX_IPSR_MSEL(IP13_6_3, SSI_SCK6, SEL_SSI6_0),
+ PINMUX_IPSR_MSEL(IP13_6_3, SCIFB1_CTS_N, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP13_6_3, BPFCLK_D, SEL_FM_3),
PINMUX_IPSR_DATA(IP13_6_3, DU2_DR3),
PINMUX_IPSR_DATA(IP13_6_3, LCDOUT3),
PINMUX_IPSR_DATA(IP13_6_3, CAN_DEBUGOUT6),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_3, BPFCLK_F, SEL_FM_5),
- PINMUX_IPSR_MODSEL_DATA(IP13_9_7, SSI_WS6, SEL_SSI6_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_9_7, SCIFB1_RTS_N, SEL_SCIFB1_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_9_7, CAN0_TX_D, SEL_CAN0_3),
+ PINMUX_IPSR_MSEL(IP13_6_3, BPFCLK_F, SEL_FM_5),
+ PINMUX_IPSR_MSEL(IP13_9_7, SSI_WS6, SEL_SSI6_0),
+ PINMUX_IPSR_MSEL(IP13_9_7, SCIFB1_RTS_N, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP13_9_7, CAN0_TX_D, SEL_CAN0_3),
PINMUX_IPSR_DATA(IP13_9_7, DU2_DR4),
PINMUX_IPSR_DATA(IP13_9_7, LCDOUT4),
PINMUX_IPSR_DATA(IP13_9_7, CAN_DEBUGOUT7),
- PINMUX_IPSR_MODSEL_DATA(IP13_12_10, SSI_SDATA6, SEL_SSI6_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_12_10, FMIN_D, SEL_FM_3),
+ PINMUX_IPSR_MSEL(IP13_12_10, SSI_SDATA6, SEL_SSI6_0),
+ PINMUX_IPSR_MSEL(IP13_12_10, FMIN_D, SEL_FM_3),
PINMUX_IPSR_DATA(IP13_12_10, DU2_DR5),
PINMUX_IPSR_DATA(IP13_12_10, LCDOUT5),
PINMUX_IPSR_DATA(IP13_12_10, CAN_DEBUGOUT8),
- PINMUX_IPSR_MODSEL_DATA(IP13_15_13, SSI_SCK78, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_15_13, STP_IVCXO27_1, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_15_13, SCK1, SEL_SCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_15_13, SCIFA1_SCK, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP13_15_13, SSI_SCK78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP13_15_13, STP_IVCXO27_1, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_15_13, SCK1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP13_15_13, SCIFA1_SCK, SEL_SCIFA1_0),
PINMUX_IPSR_DATA(IP13_15_13, DU2_DR6),
PINMUX_IPSR_DATA(IP13_15_13, LCDOUT6),
PINMUX_IPSR_DATA(IP13_15_13, CAN_DEBUGOUT9),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, SSI_WS78, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, STP_ISCLK_1, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, SCIFB2_SCK, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP13_18_16, SSI_WS78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP13_18_16, STP_ISCLK_1, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_18_16, SCIFB2_SCK, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP13_18_16, SCIFA2_CTS_N),
PINMUX_IPSR_DATA(IP13_18_16, DU2_DR7),
PINMUX_IPSR_DATA(IP13_18_16, LCDOUT7),
PINMUX_IPSR_DATA(IP13_18_16, CAN_DEBUGOUT10),
- PINMUX_IPSR_MODSEL_DATA(IP13_22_19, SSI_SDATA7, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_22_19, STP_ISD_1, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_22_19, SCIFB2_RXD, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP13_22_19, SSI_SDATA7, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP13_22_19, STP_ISD_1, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_22_19, SCIFB2_RXD, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP13_22_19, SCIFA2_RTS_N),
PINMUX_IPSR_DATA(IP13_22_19, TCLK2),
PINMUX_IPSR_DATA(IP13_22_19, QSTVA_QVS),
PINMUX_IPSR_DATA(IP13_22_19, CAN_DEBUGOUT11),
- PINMUX_IPSR_MODSEL_DATA(IP13_22_19, BPFCLK_E, SEL_FM_4),
- PINMUX_IPSR_MODSEL_DATA(IP13_22_19, SSI_SDATA7_B, SEL_SSI7_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_22_19, FMIN_G, SEL_FM_6),
- PINMUX_IPSR_MODSEL_DATA(IP13_25_23, SSI_SDATA8, SEL_SSI8_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_25_23, STP_ISEN_1, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_25_23, SCIFB2_TXD, SEL_SCIFB2_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_25_23, CAN0_TX_C, SEL_CAN0_2),
+ PINMUX_IPSR_MSEL(IP13_22_19, BPFCLK_E, SEL_FM_4),
+ PINMUX_IPSR_MSEL(IP13_22_19, SSI_SDATA7_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP13_22_19, FMIN_G, SEL_FM_6),
+ PINMUX_IPSR_MSEL(IP13_25_23, SSI_SDATA8, SEL_SSI8_0),
+ PINMUX_IPSR_MSEL(IP13_25_23, STP_ISEN_1, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_25_23, SCIFB2_TXD, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP13_25_23, CAN0_TX_C, SEL_CAN0_2),
PINMUX_IPSR_DATA(IP13_25_23, CAN_DEBUGOUT12),
- PINMUX_IPSR_MODSEL_DATA(IP13_25_23, SSI_SDATA8_B, SEL_SSI8_1),
+ PINMUX_IPSR_MSEL(IP13_25_23, SSI_SDATA8_B, SEL_SSI8_1),
PINMUX_IPSR_DATA(IP13_28_26, SSI_SDATA9),
- PINMUX_IPSR_MODSEL_DATA(IP13_28_26, STP_ISSYNC_1, SEL_SSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_28_26, SCIFB2_CTS_N, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP13_28_26, STP_ISSYNC_1, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_28_26, SCIFB2_CTS_N, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP13_28_26, SSI_WS1),
- PINMUX_IPSR_MODSEL_DATA(IP13_28_26, SSI_SDATA5_C, SEL_SSI5_2),
+ PINMUX_IPSR_MSEL(IP13_28_26, SSI_SDATA5_C, SEL_SSI5_2),
PINMUX_IPSR_DATA(IP13_28_26, CAN_DEBUGOUT13),
PINMUX_IPSR_DATA(IP13_30_29, AUDIO_CLKA),
- PINMUX_IPSR_MODSEL_DATA(IP13_30_29, SCIFB2_RTS_N, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP13_30_29, SCIFB2_RTS_N, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP13_30_29, CAN_DEBUGOUT14),
PINMUX_IPSR_DATA(IP14_2_0, AUDIO_CLKB),
- PINMUX_IPSR_MODSEL_DATA(IP14_2_0, SCIF_CLK, SEL_SCIFCLK_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_2_0, CAN0_RX_D, SEL_CAN0_3),
+ PINMUX_IPSR_MSEL(IP14_2_0, SCIF_CLK, SEL_SCIFCLK_0),
+ PINMUX_IPSR_MSEL(IP14_2_0, CAN0_RX_D, SEL_CAN0_3),
PINMUX_IPSR_DATA(IP14_2_0, DVC_MUTE),
- PINMUX_IPSR_MODSEL_DATA(IP14_2_0, CAN0_RX_C, SEL_CAN0_2),
+ PINMUX_IPSR_MSEL(IP14_2_0, CAN0_RX_C, SEL_CAN0_2),
PINMUX_IPSR_DATA(IP14_2_0, CAN_DEBUGOUT15),
PINMUX_IPSR_DATA(IP14_2_0, REMOCON),
- PINMUX_IPSR_MODSEL_DATA(IP14_5_3, SCIFA0_SCK, SEL_SCFA_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_5_3, HSCK1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_5_3, SCIFA0_SCK, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP14_5_3, HSCK1, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP14_5_3, SCK0),
PINMUX_IPSR_DATA(IP14_5_3, MSIOF3_SS2),
PINMUX_IPSR_DATA(IP14_5_3, DU2_DG2),
PINMUX_IPSR_DATA(IP14_5_3, LCDOUT10),
- PINMUX_IPSR_MODSEL_DATA(IP14_5_3, IIC1_SDA_C, SEL_IIC1_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_5_3, I2C1_SDA_C, SEL_I2C1_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_8_6, SCIFA0_RXD, SEL_SCFA_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_8_6, HRX1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_8_6, RX0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP14_5_3, IIC1_SDA_C, SEL_IIC1_2),
+ PINMUX_IPSR_MSEL(IP14_5_3, I2C1_SDA_C, SEL_I2C1_2),
+ PINMUX_IPSR_MSEL(IP14_8_6, SCIFA0_RXD, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP14_8_6, HRX1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_8_6, RX0, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP14_8_6, DU2_DR0),
PINMUX_IPSR_DATA(IP14_8_6, LCDOUT0),
- PINMUX_IPSR_MODSEL_DATA(IP14_11_9, SCIFA0_TXD, SEL_SCFA_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_11_9, HTX1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_11_9, TX0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP14_11_9, SCIFA0_TXD, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP14_11_9, HTX1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_11_9, TX0, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP14_11_9, DU2_DR1),
PINMUX_IPSR_DATA(IP14_11_9, LCDOUT1),
- PINMUX_IPSR_MODSEL_DATA(IP14_15_12, SCIFA0_CTS_N, SEL_SCFA_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_15_12, HCTS1_N, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_15_12, SCIFA0_CTS_N, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP14_15_12, HCTS1_N, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP14_15_12, CTS0_N),
- PINMUX_IPSR_MODSEL_DATA(IP14_15_12, MSIOF3_SYNC, SEL_SOF3_0),
+ PINMUX_IPSR_MSEL(IP14_15_12, MSIOF3_SYNC, SEL_SOF3_0),
PINMUX_IPSR_DATA(IP14_15_12, DU2_DG3),
PINMUX_IPSR_DATA(IP14_15_12, LCDOUT11),
PINMUX_IPSR_DATA(IP14_15_12, PWM0_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_15_12, IIC1_SCL_C, SEL_IIC1_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_15_12, I2C1_SCL_C, SEL_I2C1_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_18_16, SCIFA0_RTS_N, SEL_SCFA_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_18_16, HRTS1_N, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_15_12, IIC1_SCL_C, SEL_IIC1_2),
+ PINMUX_IPSR_MSEL(IP14_15_12, I2C1_SCL_C, SEL_I2C1_2),
+ PINMUX_IPSR_MSEL(IP14_18_16, SCIFA0_RTS_N, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP14_18_16, HRTS1_N, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP14_18_16, RTS0_N),
PINMUX_IPSR_DATA(IP14_18_16, MSIOF3_SS1),
PINMUX_IPSR_DATA(IP14_18_16, DU2_DG0),
PINMUX_IPSR_DATA(IP14_18_16, LCDOUT8),
PINMUX_IPSR_DATA(IP14_18_16, PWM1_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_21_19, SCIFA1_RXD, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_21_19, AD_DI, SEL_ADI_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_21_19, RX1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_21_19, SCIFA1_RXD, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP14_21_19, AD_DI, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP14_21_19, RX1, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP14_21_19, DU2_EXODDF_DU2_ODDF_DISP_CDE),
PINMUX_IPSR_DATA(IP14_21_19, QCPV_QDE),
- PINMUX_IPSR_MODSEL_DATA(IP14_24_22, SCIFA1_TXD, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_24_22, AD_DO, SEL_ADI_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_24_22, TX1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP14_24_22, SCIFA1_TXD, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP14_24_22, AD_DO, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP14_24_22, TX1, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP14_24_22, DU2_DG1),
PINMUX_IPSR_DATA(IP14_24_22, LCDOUT9),
- PINMUX_IPSR_MODSEL_DATA(IP14_27_25, SCIFA1_CTS_N, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_27_25, AD_CLK, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP14_27_25, SCIFA1_CTS_N, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP14_27_25, AD_CLK, SEL_ADI_0),
PINMUX_IPSR_DATA(IP14_27_25, CTS1_N),
- PINMUX_IPSR_MODSEL_DATA(IP14_27_25, MSIOF3_RXD, SEL_SOF3_0),
+ PINMUX_IPSR_MSEL(IP14_27_25, MSIOF3_RXD, SEL_SOF3_0),
PINMUX_IPSR_DATA(IP14_27_25, DU0_DOTCLKOUT),
PINMUX_IPSR_DATA(IP14_27_25, QCLK),
- PINMUX_IPSR_MODSEL_DATA(IP14_30_28, SCIFA1_RTS_N, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_30_28, AD_NCS_N, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP14_30_28, SCIFA1_RTS_N, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP14_30_28, AD_NCS_N, SEL_ADI_0),
PINMUX_IPSR_DATA(IP14_30_28, RTS1_N),
- PINMUX_IPSR_MODSEL_DATA(IP14_30_28, MSIOF3_TXD, SEL_SOF3_0),
+ PINMUX_IPSR_MSEL(IP14_30_28, MSIOF3_TXD, SEL_SOF3_0),
PINMUX_IPSR_DATA(IP14_30_28, DU1_DOTCLKOUT),
PINMUX_IPSR_DATA(IP14_30_28, QSTVB_QVE),
- PINMUX_IPSR_MODSEL_DATA(IP14_30_28, HRTS0_N_C, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP14_30_28, HRTS0_N_C, SEL_HSCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_2_0, SCIFA2_SCK, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_2_0, FMCLK, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP15_2_0, SCIFA2_SCK, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP15_2_0, FMCLK, SEL_FM_0),
PINMUX_IPSR_DATA(IP15_2_0, SCK2),
- PINMUX_IPSR_MODSEL_DATA(IP15_2_0, MSIOF3_SCK, SEL_SOF3_0),
+ PINMUX_IPSR_MSEL(IP15_2_0, MSIOF3_SCK, SEL_SOF3_0),
PINMUX_IPSR_DATA(IP15_2_0, DU2_DG7),
PINMUX_IPSR_DATA(IP15_2_0, LCDOUT15),
- PINMUX_IPSR_MODSEL_DATA(IP15_2_0, SCIF_CLK_B, SEL_SCIFCLK_1),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_3, FMIN, SEL_FM_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_3, TX2, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP15_2_0, SCIF_CLK_B, SEL_SCIFCLK_1),
+ PINMUX_IPSR_MSEL(IP15_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP15_5_3, FMIN, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP15_5_3, TX2, SEL_SCIF2_0),
PINMUX_IPSR_DATA(IP15_5_3, DU2_DB0),
PINMUX_IPSR_DATA(IP15_5_3, LCDOUT16),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_3, IIC2_SCL, SEL_IIC2_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_3, I2C2_SCL, SEL_I2C2_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, SCIFA2_TXD, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, BPFCLK, SEL_FM_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, RX2, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP15_5_3, IIC2_SCL, SEL_IIC2_0),
+ PINMUX_IPSR_MSEL(IP15_5_3, I2C2_SCL, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP15_8_6, SCIFA2_TXD, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP15_8_6, BPFCLK, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP15_8_6, RX2, SEL_SCIF2_0),
PINMUX_IPSR_DATA(IP15_8_6, DU2_DB1),
PINMUX_IPSR_DATA(IP15_8_6, LCDOUT17),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, IIC2_SDA, SEL_IIC2_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, I2C2_SDA, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP15_8_6, IIC2_SDA, SEL_IIC2_0),
+ PINMUX_IPSR_MSEL(IP15_8_6, I2C2_SDA, SEL_I2C2_0),
PINMUX_IPSR_DATA(IP15_11_9, HSCK0),
- PINMUX_IPSR_MODSEL_DATA(IP15_11_9, TS_SDEN0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP15_11_9, TS_SDEN0, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP15_11_9, DU2_DG4),
PINMUX_IPSR_DATA(IP15_11_9, LCDOUT12),
- PINMUX_IPSR_MODSEL_DATA(IP15_11_9, HCTS0_N_C, SEL_HSCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_13_12, HRX0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_11_9, HCTS0_N_C, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP15_13_12, HRX0, SEL_HSCIF0_0),
PINMUX_IPSR_DATA(IP15_13_12, DU2_DB2),
PINMUX_IPSR_DATA(IP15_13_12, LCDOUT18),
- PINMUX_IPSR_MODSEL_DATA(IP15_15_14, HTX0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_15_14, HTX0, SEL_HSCIF0_0),
PINMUX_IPSR_DATA(IP15_15_14, DU2_DB3),
PINMUX_IPSR_DATA(IP15_15_14, LCDOUT19),
- PINMUX_IPSR_MODSEL_DATA(IP15_17_16, HCTS0_N, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_17_16, HCTS0_N, SEL_HSCIF0_0),
PINMUX_IPSR_DATA(IP15_17_16, SSI_SCK9),
PINMUX_IPSR_DATA(IP15_17_16, DU2_DB4),
PINMUX_IPSR_DATA(IP15_17_16, LCDOUT20),
- PINMUX_IPSR_MODSEL_DATA(IP15_19_18, HRTS0_N, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_19_18, HRTS0_N, SEL_HSCIF0_0),
PINMUX_IPSR_DATA(IP15_19_18, SSI_WS9),
PINMUX_IPSR_DATA(IP15_19_18, DU2_DB5),
PINMUX_IPSR_DATA(IP15_19_18, LCDOUT21),
- PINMUX_IPSR_MODSEL_DATA(IP15_22_20, MSIOF0_SCK, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_22_20, TS_SDAT0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP15_22_20, MSIOF0_SCK, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP15_22_20, TS_SDAT0, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP15_22_20, ADICLK),
PINMUX_IPSR_DATA(IP15_22_20, DU2_DB6),
PINMUX_IPSR_DATA(IP15_22_20, LCDOUT22),
PINMUX_IPSR_DATA(IP15_25_23, MSIOF0_SYNC),
- PINMUX_IPSR_MODSEL_DATA(IP15_25_23, TS_SCK0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP15_25_23, TS_SCK0, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP15_25_23, SSI_SCK2),
PINMUX_IPSR_DATA(IP15_25_23, ADIDATA),
PINMUX_IPSR_DATA(IP15_25_23, DU2_DB7),
PINMUX_IPSR_DATA(IP15_25_23, LCDOUT23),
- PINMUX_IPSR_MODSEL_DATA(IP15_25_23, HRX0_C, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP15_27_26, MSIOF0_SS1, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP15_25_23, HRX0_C, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP15_27_26, MSIOF0_SS1, SEL_SOF0_0),
PINMUX_IPSR_DATA(IP15_27_26, ADICHS0),
PINMUX_IPSR_DATA(IP15_27_26, DU2_DG5),
PINMUX_IPSR_DATA(IP15_27_26, LCDOUT13),
- PINMUX_IPSR_MODSEL_DATA(IP15_29_28, MSIOF0_TXD, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP15_29_28, MSIOF0_TXD, SEL_SOF0_0),
PINMUX_IPSR_DATA(IP15_29_28, ADICHS1),
PINMUX_IPSR_DATA(IP15_29_28, DU2_DG6),
PINMUX_IPSR_DATA(IP15_29_28, LCDOUT14),
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, MSIOF0_SS2, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP16_2_0, MSIOF0_SS2, SEL_SOF0_0),
PINMUX_IPSR_DATA(IP16_2_0, AUDIO_CLKOUT),
PINMUX_IPSR_DATA(IP16_2_0, ADICHS2),
PINMUX_IPSR_DATA(IP16_2_0, DU2_DISP),
PINMUX_IPSR_DATA(IP16_2_0, QPOLA),
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, HTX0_C, SEL_HSCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, SCIFA2_TXD_B, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, MSIOF0_RXD, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, TS_SPSYNC0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP16_2_0, HTX0_C, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP16_2_0, SCIFA2_TXD_B, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP16_5_3, MSIOF0_RXD, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP16_5_3, TS_SPSYNC0, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP16_5_3, SSI_WS2),
PINMUX_IPSR_DATA(IP16_5_3, ADICS_SAMP),
PINMUX_IPSR_DATA(IP16_5_3, DU2_CDE),
PINMUX_IPSR_DATA(IP16_5_3, QPOLB),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, SCIFA2_RXD_B, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP16_5_3, SCIFA2_RXD_B, SEL_HSCIF0_2),
PINMUX_IPSR_DATA(IP16_6, USB1_PWEN),
PINMUX_IPSR_DATA(IP16_6, AUDIO_CLKOUT_D),
PINMUX_IPSR_DATA(IP16_7, USB1_OVC),
- PINMUX_IPSR_MODSEL_DATA(IP16_7, TCLK1_B, SEL_TMU1_1),
+ PINMUX_IPSR_MSEL(IP16_7, TCLK1_B, SEL_TMU1_1),
PINMUX_DATA(IIC0_SCL_MARK, FN_SEL_IIC0_0),
PINMUX_DATA(IIC0_SDA_MARK, FN_SEL_IIC0_0),
@@ -3624,25 +3623,6 @@ static const unsigned int usb2_pins[] = {
static const unsigned int usb2_mux[] = {
USB2_PWEN_MARK, USB2_OVC_MARK,
};
-
-union vin_data {
- unsigned int data24[24];
- unsigned int data20[20];
- unsigned int data16[16];
- unsigned int data12[12];
- unsigned int data10[10];
- unsigned int data8[8];
- unsigned int data4[4];
-};
-
-#define VIN_DATA_PIN_GROUP(n, s) \
- { \
- .name = #n#s, \
- .pins = n##_pins.data##s, \
- .mux = n##_mux.data##s, \
- .nr_pins = ARRAY_SIZE(n##_pins.data##s), \
- }
-
/* - VIN0 ------------------------------------------------------------------- */
static const union vin_data vin0_data_pins = {
.data24 = {
@@ -5719,6 +5699,6 @@ const struct sh_pfc_soc_info r8a7790_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 25e8117f5a1a..87a4f44147c1 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -9,7 +9,6 @@
*/
#include <linux/kernel.h>
-#include <linux/platform_data/gpio-rcar.h>
#include "core.h"
#include "sh_pfc.h"
@@ -824,459 +823,459 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP0_14, D14),
PINMUX_IPSR_DATA(IP0_15, D15),
PINMUX_IPSR_DATA(IP0_18_16, A0),
- PINMUX_IPSR_MODSEL_DATA(IP0_18_16, ATAWR0_N_C, SEL_LBS_2),
- PINMUX_IPSR_MODSEL_DATA(IP0_18_16, MSIOF0_SCK_B, SEL_SOF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_18_16, SCL0_C, SEL_IIC0_2),
+ PINMUX_IPSR_MSEL(IP0_18_16, ATAWR0_N_C, SEL_LBS_2),
+ PINMUX_IPSR_MSEL(IP0_18_16, MSIOF0_SCK_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP0_18_16, SCL0_C, SEL_IIC0_2),
PINMUX_IPSR_DATA(IP0_18_16, PWM2_B),
PINMUX_IPSR_DATA(IP0_20_19, A1),
- PINMUX_IPSR_MODSEL_DATA(IP0_20_19, MSIOF0_SYNC_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP0_20_19, MSIOF0_SYNC_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP0_22_21, A2),
- PINMUX_IPSR_MODSEL_DATA(IP0_22_21, MSIOF0_SS1_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP0_22_21, MSIOF0_SS1_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP0_24_23, A3),
- PINMUX_IPSR_MODSEL_DATA(IP0_24_23, MSIOF0_SS2_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP0_24_23, MSIOF0_SS2_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP0_26_25, A4),
- PINMUX_IPSR_MODSEL_DATA(IP0_26_25, MSIOF0_TXD_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP0_26_25, MSIOF0_TXD_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP0_28_27, A5),
- PINMUX_IPSR_MODSEL_DATA(IP0_28_27, MSIOF0_RXD_B, SEL_SOF0_1),
+ PINMUX_IPSR_MSEL(IP0_28_27, MSIOF0_RXD_B, SEL_SOF0_1),
PINMUX_IPSR_DATA(IP0_30_29, A6),
- PINMUX_IPSR_MODSEL_DATA(IP0_30_29, MSIOF1_SCK, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP0_30_29, MSIOF1_SCK, SEL_SOF1_0),
/* IPSR1 */
PINMUX_IPSR_DATA(IP1_1_0, A7),
- PINMUX_IPSR_MODSEL_DATA(IP1_1_0, MSIOF1_SYNC, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP1_1_0, MSIOF1_SYNC, SEL_SOF1_0),
PINMUX_IPSR_DATA(IP1_3_2, A8),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_2, MSIOF1_SS1, SEL_SOF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_2, SCL0, SEL_IIC0_0),
+ PINMUX_IPSR_MSEL(IP1_3_2, MSIOF1_SS1, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP1_3_2, SCL0, SEL_IIC0_0),
PINMUX_IPSR_DATA(IP1_5_4, A9),
- PINMUX_IPSR_MODSEL_DATA(IP1_5_4, MSIOF1_SS2, SEL_SOF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_5_4, SDA0, SEL_IIC0_0),
+ PINMUX_IPSR_MSEL(IP1_5_4, MSIOF1_SS2, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP1_5_4, SDA0, SEL_IIC0_0),
PINMUX_IPSR_DATA(IP1_7_6, A10),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_6, MSIOF1_TXD, SEL_SOF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_6, MSIOF1_TXD_D, SEL_SOF1_3),
+ PINMUX_IPSR_MSEL(IP1_7_6, MSIOF1_TXD, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP1_7_6, MSIOF1_TXD_D, SEL_SOF1_3),
PINMUX_IPSR_DATA(IP1_10_8, A11),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_8, MSIOF1_RXD, SEL_SOF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_8, SCL3_D, SEL_IIC3_3),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_8, MSIOF1_RXD_D, SEL_SOF1_3),
+ PINMUX_IPSR_MSEL(IP1_10_8, MSIOF1_RXD, SEL_SOF1_0),
+ PINMUX_IPSR_MSEL(IP1_10_8, SCL3_D, SEL_IIC3_3),
+ PINMUX_IPSR_MSEL(IP1_10_8, MSIOF1_RXD_D, SEL_SOF1_3),
PINMUX_IPSR_DATA(IP1_13_11, A12),
- PINMUX_IPSR_MODSEL_DATA(IP1_13_11, FMCLK, SEL_FM_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_13_11, SDA3_D, SEL_IIC3_3),
- PINMUX_IPSR_MODSEL_DATA(IP1_13_11, MSIOF1_SCK_D, SEL_SOF1_3),
+ PINMUX_IPSR_MSEL(IP1_13_11, FMCLK, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP1_13_11, SDA3_D, SEL_IIC3_3),
+ PINMUX_IPSR_MSEL(IP1_13_11, MSIOF1_SCK_D, SEL_SOF1_3),
PINMUX_IPSR_DATA(IP1_16_14, A13),
- PINMUX_IPSR_MODSEL_DATA(IP1_16_14, ATAG0_N_C, SEL_LBS_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_16_14, BPFCLK, SEL_FM_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_16_14, MSIOF1_SS1_D, SEL_SOF1_3),
+ PINMUX_IPSR_MSEL(IP1_16_14, ATAG0_N_C, SEL_LBS_2),
+ PINMUX_IPSR_MSEL(IP1_16_14, BPFCLK, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP1_16_14, MSIOF1_SS1_D, SEL_SOF1_3),
PINMUX_IPSR_DATA(IP1_19_17, A14),
- PINMUX_IPSR_MODSEL_DATA(IP1_19_17, ATADIR0_N_C, SEL_LBS_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_19_17, FMIN, SEL_FM_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_19_17, FMIN_C, SEL_FM_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_19_17, MSIOF1_SYNC_D, SEL_SOF1_3),
+ PINMUX_IPSR_MSEL(IP1_19_17, ATADIR0_N_C, SEL_LBS_2),
+ PINMUX_IPSR_MSEL(IP1_19_17, FMIN, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP1_19_17, FMIN_C, SEL_FM_2),
+ PINMUX_IPSR_MSEL(IP1_19_17, MSIOF1_SYNC_D, SEL_SOF1_3),
PINMUX_IPSR_DATA(IP1_22_20, A15),
- PINMUX_IPSR_MODSEL_DATA(IP1_22_20, BPFCLK_C, SEL_FM_2),
+ PINMUX_IPSR_MSEL(IP1_22_20, BPFCLK_C, SEL_FM_2),
PINMUX_IPSR_DATA(IP1_25_23, A16),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_23, DREQ2_B, SEL_LBS_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_23, FMCLK_C, SEL_FM_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_23, SCIFA1_SCK_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP1_25_23, DREQ2_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP1_25_23, FMCLK_C, SEL_FM_2),
+ PINMUX_IPSR_MSEL(IP1_25_23, SCIFA1_SCK_B, SEL_SCIFA1_1),
PINMUX_IPSR_DATA(IP1_28_26, A17),
- PINMUX_IPSR_MODSEL_DATA(IP1_28_26, DACK2_B, SEL_LBS_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_28_26, SDA0_C, SEL_IIC0_2),
+ PINMUX_IPSR_MSEL(IP1_28_26, DACK2_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP1_28_26, SDA0_C, SEL_IIC0_2),
PINMUX_IPSR_DATA(IP1_31_29, A18),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_29, DREQ1, SEL_LBS_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_29, SCIFA1_RXD_C, SEL_SCIFA1_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_29, SCIFB1_RXD_C, SEL_SCIFB1_2),
+ PINMUX_IPSR_MSEL(IP1_31_29, DREQ1, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP1_31_29, SCIFA1_RXD_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP1_31_29, SCIFB1_RXD_C, SEL_SCIFB1_2),
/* IPSR2 */
PINMUX_IPSR_DATA(IP2_2_0, A19),
PINMUX_IPSR_DATA(IP2_2_0, DACK1),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SCIFA1_TXD_C, SEL_SCIFA1_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SCIFB1_TXD_C, SEL_SCIFB1_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SCIFB1_SCK_B, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP2_2_0, SCIFA1_TXD_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP2_2_0, SCIFB1_TXD_C, SEL_SCIFB1_2),
+ PINMUX_IPSR_MSEL(IP2_2_0, SCIFB1_SCK_B, SEL_SCIFB1_1),
PINMUX_IPSR_DATA(IP2_2_0, A20),
- PINMUX_IPSR_MODSEL_DATA(IP2_4_3, SPCLK, SEL_QSP_0),
+ PINMUX_IPSR_MSEL(IP2_4_3, SPCLK, SEL_QSP_0),
PINMUX_IPSR_DATA(IP2_6_5, A21),
- PINMUX_IPSR_MODSEL_DATA(IP2_6_5, ATAWR0_N_B, SEL_LBS_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_6_5, MOSI_IO0, SEL_QSP_0),
+ PINMUX_IPSR_MSEL(IP2_6_5, ATAWR0_N_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP2_6_5, MOSI_IO0, SEL_QSP_0),
PINMUX_IPSR_DATA(IP2_9_7, A22),
- PINMUX_IPSR_MODSEL_DATA(IP2_9_7, MISO_IO1, SEL_QSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_9_7, FMCLK_B, SEL_FM_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_9_7, TX0, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_9_7, SCIFA0_TXD, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP2_9_7, MISO_IO1, SEL_QSP_0),
+ PINMUX_IPSR_MSEL(IP2_9_7, FMCLK_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP2_9_7, TX0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP2_9_7, SCIFA0_TXD, SEL_SCFA_0),
PINMUX_IPSR_DATA(IP2_12_10, A23),
- PINMUX_IPSR_MODSEL_DATA(IP2_12_10, IO2, SEL_QSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_12_10, BPFCLK_B, SEL_FM_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_12_10, RX0, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_12_10, SCIFA0_RXD, SEL_SCFA_0),
+ PINMUX_IPSR_MSEL(IP2_12_10, IO2, SEL_QSP_0),
+ PINMUX_IPSR_MSEL(IP2_12_10, BPFCLK_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP2_12_10, RX0, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP2_12_10, SCIFA0_RXD, SEL_SCFA_0),
PINMUX_IPSR_DATA(IP2_15_13, A24),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_13, DREQ2, SEL_LBS_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_13, IO3, SEL_QSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_13, TX1, SEL_SCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_13, SCIFA1_TXD, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP2_15_13, DREQ2, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_15_13, IO3, SEL_QSP_0),
+ PINMUX_IPSR_MSEL(IP2_15_13, TX1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP2_15_13, SCIFA1_TXD, SEL_SCIFA1_0),
PINMUX_IPSR_DATA(IP2_18_16, A25),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, DACK2, SEL_LBS_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, SSL, SEL_QSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, DREQ1_C, SEL_LBS_2),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, RX1, SEL_SCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_18_16, SCIFA1_RXD, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP2_18_16, DACK2, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_18_16, SSL, SEL_QSP_0),
+ PINMUX_IPSR_MSEL(IP2_18_16, DREQ1_C, SEL_LBS_2),
+ PINMUX_IPSR_MSEL(IP2_18_16, RX1, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP2_18_16, SCIFA1_RXD, SEL_SCIFA1_0),
PINMUX_IPSR_DATA(IP2_20_19, CS0_N),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_19, ATAG0_N_B, SEL_LBS_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_19, SCL1, SEL_IIC1_0),
+ PINMUX_IPSR_MSEL(IP2_20_19, ATAG0_N_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP2_20_19, SCL1, SEL_IIC1_0),
PINMUX_IPSR_DATA(IP2_22_21, CS1_N_A26),
- PINMUX_IPSR_MODSEL_DATA(IP2_22_21, ATADIR0_N_B, SEL_LBS_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_22_21, SDA1, SEL_IIC1_0),
+ PINMUX_IPSR_MSEL(IP2_22_21, ATADIR0_N_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP2_22_21, SDA1, SEL_IIC1_0),
PINMUX_IPSR_DATA(IP2_24_23, EX_CS1_N),
- PINMUX_IPSR_MODSEL_DATA(IP2_24_23, MSIOF2_SCK, SEL_SOF2_0),
+ PINMUX_IPSR_MSEL(IP2_24_23, MSIOF2_SCK, SEL_SOF2_0),
PINMUX_IPSR_DATA(IP2_26_25, EX_CS2_N),
- PINMUX_IPSR_MODSEL_DATA(IP2_26_25, ATAWR0_N, SEL_LBS_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_26_25, MSIOF2_SYNC, SEL_SOF2_0),
+ PINMUX_IPSR_MSEL(IP2_26_25, ATAWR0_N, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_26_25, MSIOF2_SYNC, SEL_SOF2_0),
PINMUX_IPSR_DATA(IP2_29_27, EX_CS3_N),
- PINMUX_IPSR_MODSEL_DATA(IP2_29_27, ATADIR0_N, SEL_LBS_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_29_27, MSIOF2_TXD, SEL_SOF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_29_27, ATAG0_N, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_29_27, ATADIR0_N, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_29_27, MSIOF2_TXD, SEL_SOF2_0),
+ PINMUX_IPSR_MSEL(IP2_29_27, ATAG0_N, SEL_LBS_0),
PINMUX_IPSR_DATA(IP2_29_27, EX_WAIT1),
/* IPSR3 */
PINMUX_IPSR_DATA(IP3_2_0, EX_CS4_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_2_0, ATARD0_N, SEL_LBS_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_2_0, MSIOF2_RXD, SEL_SOF2_0),
+ PINMUX_IPSR_MSEL(IP3_2_0, ATARD0_N, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP3_2_0, MSIOF2_RXD, SEL_SOF2_0),
PINMUX_IPSR_DATA(IP3_2_0, EX_WAIT2),
PINMUX_IPSR_DATA(IP3_5_3, EX_CS5_N),
PINMUX_IPSR_DATA(IP3_5_3, ATACS00_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_5_3, MSIOF2_SS1, SEL_SOF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_5_3, HRX1_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_5_3, SCIFB1_RXD_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP3_5_3, MSIOF2_SS1, SEL_SOF2_0),
+ PINMUX_IPSR_MSEL(IP3_5_3, HRX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP3_5_3, SCIFB1_RXD_B, SEL_SCIFB1_1),
PINMUX_IPSR_DATA(IP3_5_3, PWM1),
PINMUX_IPSR_DATA(IP3_5_3, TPU_TO1),
PINMUX_IPSR_DATA(IP3_8_6, BS_N),
PINMUX_IPSR_DATA(IP3_8_6, ATACS10_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_8_6, MSIOF2_SS2, SEL_SOF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_8_6, HTX1_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_8_6, SCIFB1_TXD_B, SEL_SCIFB1_1),
+ PINMUX_IPSR_MSEL(IP3_8_6, MSIOF2_SS2, SEL_SOF2_0),
+ PINMUX_IPSR_MSEL(IP3_8_6, HTX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP3_8_6, SCIFB1_TXD_B, SEL_SCIFB1_1),
PINMUX_IPSR_DATA(IP3_8_6, PWM2),
PINMUX_IPSR_DATA(IP3_8_6, TPU_TO2),
PINMUX_IPSR_DATA(IP3_11_9, RD_WR_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, HRX2_B, SEL_HSCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, FMIN_B, SEL_FM_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, SCIFB0_RXD_B, SEL_SCIFB_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, DREQ1_D, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP3_11_9, HRX2_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP3_11_9, FMIN_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP3_11_9, SCIFB0_RXD_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP3_11_9, DREQ1_D, SEL_LBS_1),
PINMUX_IPSR_DATA(IP3_13_12, WE0_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_13_12, HCTS2_N_B, SEL_HSCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_13_12, SCIFB0_TXD_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP3_13_12, HCTS2_N_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP3_13_12, SCIFB0_TXD_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP3_15_14, WE1_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_15_14, ATARD0_N_B, SEL_LBS_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_15_14, HTX2_B, SEL_HSCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_15_14, SCIFB0_RTS_N_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP3_15_14, ATARD0_N_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP3_15_14, HTX2_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP3_15_14, SCIFB0_RTS_N_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP3_17_16, EX_WAIT0),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_16, HRTS2_N_B, SEL_HSCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_16, SCIFB0_CTS_N_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP3_17_16, HRTS2_N_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP3_17_16, SCIFB0_CTS_N_B, SEL_SCIFB_1),
PINMUX_IPSR_DATA(IP3_19_18, DREQ0),
PINMUX_IPSR_DATA(IP3_19_18, PWM3),
PINMUX_IPSR_DATA(IP3_19_18, TPU_TO3),
PINMUX_IPSR_DATA(IP3_21_20, DACK0),
PINMUX_IPSR_DATA(IP3_21_20, DRACK0),
- PINMUX_IPSR_MODSEL_DATA(IP3_21_20, REMOCON, SEL_RCN_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_24_22, SPEEDIN, SEL_RSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_24_22, HSCK0_C, SEL_HSCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_24_22, HSCK2_C, SEL_HSCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_24_22, SCIFB0_SCK_B, SEL_SCIFB_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_24_22, SCIFB2_SCK_B, SEL_SCIFB2_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_24_22, DREQ2_C, SEL_LBS_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_30_28, HTX2_C, SEL_HSCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_27_25, SSI_SCK0129, SEL_SSI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_27_25, HRX0_C, SEL_HSCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_27_25, HRX2_C, SEL_HSCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_27_25, SCIFB0_RXD_C, SEL_SCIFB_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_27_25, SCIFB2_RXD_C, SEL_SCIFB2_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_30_28, SSI_WS0129, SEL_SSI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_30_28, HTX0_C, SEL_HSCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_30_28, HTX2_C, SEL_HSCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_30_28, SCIFB0_TXD_C, SEL_SCIFB_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_30_28, SCIFB2_TXD_C, SEL_SCIFB2_2),
+ PINMUX_IPSR_MSEL(IP3_21_20, REMOCON, SEL_RCN_0),
+ PINMUX_IPSR_MSEL(IP3_24_22, SPEEDIN, SEL_RSP_0),
+ PINMUX_IPSR_MSEL(IP3_24_22, HSCK0_C, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP3_24_22, HSCK2_C, SEL_HSCIF2_2),
+ PINMUX_IPSR_MSEL(IP3_24_22, SCIFB0_SCK_B, SEL_SCIFB_1),
+ PINMUX_IPSR_MSEL(IP3_24_22, SCIFB2_SCK_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP3_24_22, DREQ2_C, SEL_LBS_2),
+ PINMUX_IPSR_MSEL(IP3_30_28, HTX2_C, SEL_HSCIF2_2),
+ PINMUX_IPSR_MSEL(IP3_27_25, SSI_SCK0129, SEL_SSI0_0),
+ PINMUX_IPSR_MSEL(IP3_27_25, HRX0_C, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP3_27_25, HRX2_C, SEL_HSCIF2_2),
+ PINMUX_IPSR_MSEL(IP3_27_25, SCIFB0_RXD_C, SEL_SCIFB_2),
+ PINMUX_IPSR_MSEL(IP3_27_25, SCIFB2_RXD_C, SEL_SCIFB2_2),
+ PINMUX_IPSR_MSEL(IP3_30_28, SSI_WS0129, SEL_SSI0_0),
+ PINMUX_IPSR_MSEL(IP3_30_28, HTX0_C, SEL_HSCIF0_2),
+ PINMUX_IPSR_MSEL(IP3_30_28, HTX2_C, SEL_HSCIF2_2),
+ PINMUX_IPSR_MSEL(IP3_30_28, SCIFB0_TXD_C, SEL_SCIFB_2),
+ PINMUX_IPSR_MSEL(IP3_30_28, SCIFB2_TXD_C, SEL_SCIFB2_2),
/* IPSR4 */
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SSI_SDATA0, SEL_SSI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SCL0_B, SEL_IIC0_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SCL7_B, SEL_IIC7_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, MSIOF2_SCK_C, SEL_SOF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SSI_SCK1, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SDA0_B, SEL_IIC0_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SDA7_B, SEL_IIC7_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, MSIOF2_SYNC_C, SEL_SOF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, GLO_I0_D, SEL_GPS_3),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SSI_WS1, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SCL1_B, SEL_IIC1_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SCL8_B, SEL_IIC8_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, MSIOF2_TXD_C, SEL_SOF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, GLO_I1_D, SEL_GPS_3),
- PINMUX_IPSR_MODSEL_DATA(IP4_9_8, SSI_SDATA1, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_9_8, SDA1_B, SEL_IIC1_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_9_8, SDA8_B, SEL_IIC8_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_9_8, MSIOF2_RXD_C, SEL_SOF2_2),
+ PINMUX_IPSR_MSEL(IP4_1_0, SSI_SDATA0, SEL_SSI0_0),
+ PINMUX_IPSR_MSEL(IP4_1_0, SCL0_B, SEL_IIC0_1),
+ PINMUX_IPSR_MSEL(IP4_1_0, SCL7_B, SEL_IIC7_1),
+ PINMUX_IPSR_MSEL(IP4_1_0, MSIOF2_SCK_C, SEL_SOF2_2),
+ PINMUX_IPSR_MSEL(IP4_4_2, SSI_SCK1, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP4_4_2, SDA0_B, SEL_IIC0_1),
+ PINMUX_IPSR_MSEL(IP4_4_2, SDA7_B, SEL_IIC7_1),
+ PINMUX_IPSR_MSEL(IP4_4_2, MSIOF2_SYNC_C, SEL_SOF2_2),
+ PINMUX_IPSR_MSEL(IP4_4_2, GLO_I0_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP4_7_5, SSI_WS1, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP4_7_5, SCL1_B, SEL_IIC1_1),
+ PINMUX_IPSR_MSEL(IP4_7_5, SCL8_B, SEL_IIC8_1),
+ PINMUX_IPSR_MSEL(IP4_7_5, MSIOF2_TXD_C, SEL_SOF2_2),
+ PINMUX_IPSR_MSEL(IP4_7_5, GLO_I1_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP4_9_8, SSI_SDATA1, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP4_9_8, SDA1_B, SEL_IIC1_1),
+ PINMUX_IPSR_MSEL(IP4_9_8, SDA8_B, SEL_IIC8_1),
+ PINMUX_IPSR_MSEL(IP4_9_8, MSIOF2_RXD_C, SEL_SOF2_2),
PINMUX_IPSR_DATA(IP4_12_10, SSI_SCK2),
- PINMUX_IPSR_MODSEL_DATA(IP4_12_10, SCL2, SEL_IIC2_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_12_10, GPS_CLK_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_12_10, GLO_Q0_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP4_12_10, SCL2, SEL_IIC2_0),
+ PINMUX_IPSR_MSEL(IP4_12_10, GPS_CLK_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP4_12_10, GLO_Q0_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP4_15_13, SSI_WS2),
- PINMUX_IPSR_MODSEL_DATA(IP4_15_13, SDA2, SEL_IIC2_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_15_13, GPS_SIGN_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_15_13, RX2_E, SEL_SCIF2_4),
- PINMUX_IPSR_MODSEL_DATA(IP4_15_13, GLO_Q1_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP4_15_13, SDA2, SEL_IIC2_0),
+ PINMUX_IPSR_MSEL(IP4_15_13, GPS_SIGN_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP4_15_13, RX2_E, SEL_SCIF2_4),
+ PINMUX_IPSR_MSEL(IP4_15_13, GLO_Q1_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP4_18_16, SSI_SDATA2),
- PINMUX_IPSR_MODSEL_DATA(IP4_18_16, GPS_MAG_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_18_16, TX2_E, SEL_SCIF2_4),
+ PINMUX_IPSR_MSEL(IP4_18_16, GPS_MAG_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP4_18_16, TX2_E, SEL_SCIF2_4),
PINMUX_IPSR_DATA(IP4_19, SSI_SCK34),
PINMUX_IPSR_DATA(IP4_20, SSI_WS34),
PINMUX_IPSR_DATA(IP4_21, SSI_SDATA3),
PINMUX_IPSR_DATA(IP4_23_22, SSI_SCK4),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_22, GLO_SS_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP4_23_22, GLO_SS_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP4_25_24, SSI_WS4),
- PINMUX_IPSR_MODSEL_DATA(IP4_25_24, GLO_RFON_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP4_25_24, GLO_RFON_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP4_27_26, SSI_SDATA4),
- PINMUX_IPSR_MODSEL_DATA(IP4_27_26, MSIOF2_SCK_D, SEL_SOF2_3),
+ PINMUX_IPSR_MSEL(IP4_27_26, MSIOF2_SCK_D, SEL_SOF2_3),
PINMUX_IPSR_DATA(IP4_30_28, SSI_SCK5),
- PINMUX_IPSR_MODSEL_DATA(IP4_30_28, MSIOF1_SCK_C, SEL_SOF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_30_28, TS_SDATA0, SEL_TSIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_30_28, GLO_I0, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_30_28, MSIOF2_SYNC_D, SEL_SOF2_3),
+ PINMUX_IPSR_MSEL(IP4_30_28, MSIOF1_SCK_C, SEL_SOF1_2),
+ PINMUX_IPSR_MSEL(IP4_30_28, TS_SDATA0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP4_30_28, GLO_I0, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP4_30_28, MSIOF2_SYNC_D, SEL_SOF2_3),
PINMUX_IPSR_DATA(IP4_30_28, VI1_R2_B),
/* IPSR5 */
PINMUX_IPSR_DATA(IP5_2_0, SSI_WS5),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, MSIOF1_SYNC_C, SEL_SOF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, TS_SCK0, SEL_TSIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, GLO_I1, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, MSIOF2_TXD_D, SEL_SOF2_3),
+ PINMUX_IPSR_MSEL(IP5_2_0, MSIOF1_SYNC_C, SEL_SOF1_2),
+ PINMUX_IPSR_MSEL(IP5_2_0, TS_SCK0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP5_2_0, GLO_I1, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_2_0, MSIOF2_TXD_D, SEL_SOF2_3),
PINMUX_IPSR_DATA(IP5_2_0, VI1_R3_B),
PINMUX_IPSR_DATA(IP5_5_3, SSI_SDATA5),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, MSIOF1_TXD_C, SEL_SOF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, TS_SDEN0, SEL_TSIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, GLO_Q0, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, MSIOF2_SS1_D, SEL_SOF2_3),
+ PINMUX_IPSR_MSEL(IP5_5_3, MSIOF1_TXD_C, SEL_SOF1_2),
+ PINMUX_IPSR_MSEL(IP5_5_3, TS_SDEN0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, GLO_Q0, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, MSIOF2_SS1_D, SEL_SOF2_3),
PINMUX_IPSR_DATA(IP5_5_3, VI1_R4_B),
PINMUX_IPSR_DATA(IP5_8_6, SSI_SCK6),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, MSIOF1_RXD_C, SEL_SOF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, TS_SPSYNC0, SEL_TSIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, GLO_Q1, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, MSIOF2_RXD_D, SEL_SOF2_3),
+ PINMUX_IPSR_MSEL(IP5_8_6, MSIOF1_RXD_C, SEL_SOF1_2),
+ PINMUX_IPSR_MSEL(IP5_8_6, TS_SPSYNC0, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP5_8_6, GLO_Q1, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_8_6, MSIOF2_RXD_D, SEL_SOF2_3),
PINMUX_IPSR_DATA(IP5_8_6, VI1_R5_B),
PINMUX_IPSR_DATA(IP5_11_9, SSI_WS6),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, GLO_SCLK, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, MSIOF2_SS2_D, SEL_SOF2_3),
+ PINMUX_IPSR_MSEL(IP5_11_9, GLO_SCLK, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_11_9, MSIOF2_SS2_D, SEL_SOF2_3),
PINMUX_IPSR_DATA(IP5_11_9, VI1_R6_B),
PINMUX_IPSR_DATA(IP5_14_12, SSI_SDATA6),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_12, STP_IVCXO27_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_12, GLO_SDATA, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_14_12, STP_IVCXO27_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP5_14_12, GLO_SDATA, SEL_GPS_0),
PINMUX_IPSR_DATA(IP5_14_12, VI1_R7_B),
- PINMUX_IPSR_MODSEL_DATA(IP5_16_15, SSI_SCK78, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_16_15, STP_ISCLK_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_16_15, GLO_SS, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_19_17, SSI_WS78, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_19_17, TX0_D, SEL_SCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_19_17, STP_ISD_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_19_17, GLO_RFON, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_21_20, SSI_SDATA7, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_21_20, RX0_D, SEL_SCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_21_20, STP_ISEN_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_22, SSI_SDATA8, SEL_SSI8_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_22, TX1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_23_22, STP_ISSYNC_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_25_24, SSI_SCK9, SEL_SSI9_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_25_24, RX1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_25_24, GLO_SCLK_D, SEL_GPS_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_28_26, SSI_WS9, SEL_SSI9_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_28_26, TX3_D, SEL_SCIF3_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_28_26, CAN0_TX_D, SEL_CAN0_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_28_26, GLO_SDATA_D, SEL_GPS_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_31_29, SSI_SDATA9, SEL_SSI9_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_31_29, RX3_D, SEL_SCIF3_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_31_29, CAN0_RX_D, SEL_CAN0_3),
+ PINMUX_IPSR_MSEL(IP5_16_15, SSI_SCK78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP5_16_15, STP_ISCLK_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP5_16_15, GLO_SS, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_19_17, SSI_WS78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP5_19_17, TX0_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP5_19_17, STP_ISD_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP5_19_17, GLO_RFON, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP5_21_20, SSI_SDATA7, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP5_21_20, RX0_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP5_21_20, STP_ISEN_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP5_23_22, SSI_SDATA8, SEL_SSI8_0),
+ PINMUX_IPSR_MSEL(IP5_23_22, TX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP5_23_22, STP_ISSYNC_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP5_25_24, SSI_SCK9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP5_25_24, RX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP5_25_24, GLO_SCLK_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP5_28_26, SSI_WS9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP5_28_26, TX3_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MSEL(IP5_28_26, CAN0_TX_D, SEL_CAN0_3),
+ PINMUX_IPSR_MSEL(IP5_28_26, GLO_SDATA_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP5_31_29, SSI_SDATA9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP5_31_29, RX3_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MSEL(IP5_31_29, CAN0_RX_D, SEL_CAN0_3),
/* IPSR6 */
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, AUDIO_CLKB, SEL_ADG_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, STP_OPWM_0_B, SEL_SSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, MSIOF1_SCK_B, SEL_SOF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SCIF_CLK, SEL_SCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, BPFCLK_E, SEL_FM_4),
+ PINMUX_IPSR_MSEL(IP6_2_0, AUDIO_CLKB, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP6_2_0, STP_OPWM_0_B, SEL_SSP_1),
+ PINMUX_IPSR_MSEL(IP6_2_0, MSIOF1_SCK_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP6_2_0, SCIF_CLK, SEL_SCIF_0),
+ PINMUX_IPSR_MSEL(IP6_2_0, BPFCLK_E, SEL_FM_4),
PINMUX_IPSR_DATA(IP6_5_3, AUDIO_CLKC),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SCIFB0_SCK_C, SEL_SCIFB_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, MSIOF1_SYNC_B, SEL_SOF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, RX2, SEL_SCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, FMIN_E, SEL_FM_4),
+ PINMUX_IPSR_MSEL(IP6_5_3, SCIFB0_SCK_C, SEL_SCIFB_2),
+ PINMUX_IPSR_MSEL(IP6_5_3, MSIOF1_SYNC_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP6_5_3, RX2, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP6_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP6_5_3, FMIN_E, SEL_FM_4),
PINMUX_IPSR_DATA(IP6_7_6, AUDIO_CLKOUT),
- PINMUX_IPSR_MODSEL_DATA(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, TX2, SEL_SCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP6_5_3, TX2, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0),
PINMUX_IPSR_DATA(IP6_9_8, IRQ0),
- PINMUX_IPSR_MODSEL_DATA(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3),
+ PINMUX_IPSR_MSEL(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3),
PINMUX_IPSR_DATA(IP6_9_8, INTC_IRQ0_N),
PINMUX_IPSR_DATA(IP6_11_10, IRQ1),
- PINMUX_IPSR_MODSEL_DATA(IP6_11_10, SCIFB1_SCK_C, SEL_SCIFB1_2),
+ PINMUX_IPSR_MSEL(IP6_11_10, SCIFB1_SCK_C, SEL_SCIFB1_2),
PINMUX_IPSR_DATA(IP6_11_10, INTC_IRQ1_N),
PINMUX_IPSR_DATA(IP6_13_12, IRQ2),
- PINMUX_IPSR_MODSEL_DATA(IP6_13_12, SCIFB1_TXD_D, SEL_SCIFB1_3),
+ PINMUX_IPSR_MSEL(IP6_13_12, SCIFB1_TXD_D, SEL_SCIFB1_3),
PINMUX_IPSR_DATA(IP6_13_12, INTC_IRQ2_N),
PINMUX_IPSR_DATA(IP6_15_14, IRQ3),
- PINMUX_IPSR_MODSEL_DATA(IP6_15_14, SCL4_C, SEL_IIC4_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_15_14, MSIOF2_TXD_E, SEL_SOF2_4),
+ PINMUX_IPSR_MSEL(IP6_15_14, SCL4_C, SEL_IIC4_2),
+ PINMUX_IPSR_MSEL(IP6_15_14, MSIOF2_TXD_E, SEL_SOF2_4),
PINMUX_IPSR_DATA(IP6_15_14, INTC_IRQ4_N),
PINMUX_IPSR_DATA(IP6_18_16, IRQ4),
- PINMUX_IPSR_MODSEL_DATA(IP6_18_16, HRX1_C, SEL_HSCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_18_16, SDA4_C, SEL_IIC4_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_18_16, MSIOF2_RXD_E, SEL_SOF2_4),
+ PINMUX_IPSR_MSEL(IP6_18_16, HRX1_C, SEL_HSCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_18_16, SDA4_C, SEL_IIC4_2),
+ PINMUX_IPSR_MSEL(IP6_18_16, MSIOF2_RXD_E, SEL_SOF2_4),
PINMUX_IPSR_DATA(IP6_18_16, INTC_IRQ4_N),
PINMUX_IPSR_DATA(IP6_20_19, IRQ5),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_19, HTX1_C, SEL_HSCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_19, SCL1_E, SEL_IIC1_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_19, MSIOF2_SCK_E, SEL_SOF2_4),
+ PINMUX_IPSR_MSEL(IP6_20_19, HTX1_C, SEL_HSCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_20_19, SCL1_E, SEL_IIC1_4),
+ PINMUX_IPSR_MSEL(IP6_20_19, MSIOF2_SCK_E, SEL_SOF2_4),
PINMUX_IPSR_DATA(IP6_23_21, IRQ6),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, HSCK1_C, SEL_HSCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, MSIOF1_SS2_B, SEL_SOF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, SDA1_E, SEL_IIC1_4),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, MSIOF2_SYNC_E, SEL_SOF2_4),
+ PINMUX_IPSR_MSEL(IP6_23_21, HSCK1_C, SEL_HSCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_23_21, MSIOF1_SS2_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP6_23_21, SDA1_E, SEL_IIC1_4),
+ PINMUX_IPSR_MSEL(IP6_23_21, MSIOF2_SYNC_E, SEL_SOF2_4),
PINMUX_IPSR_DATA(IP6_26_24, IRQ7),
- PINMUX_IPSR_MODSEL_DATA(IP6_26_24, HCTS1_N_C, SEL_HSCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_26_24, MSIOF1_TXD_B, SEL_SOF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_26_24, GPS_CLK_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_26_24, GPS_CLK_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP6_26_24, HCTS1_N_C, SEL_HSCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_26_24, MSIOF1_TXD_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP6_26_24, GPS_CLK_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP6_26_24, GPS_CLK_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP6_29_27, IRQ8),
- PINMUX_IPSR_MODSEL_DATA(IP6_29_27, HRTS1_N_C, SEL_HSCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_29_27, MSIOF1_RXD_B, SEL_SOF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_29_27, GPS_SIGN_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_29_27, GPS_SIGN_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP6_29_27, HRTS1_N_C, SEL_HSCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_29_27, MSIOF1_RXD_B, SEL_SOF1_1),
+ PINMUX_IPSR_MSEL(IP6_29_27, GPS_SIGN_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP6_29_27, GPS_SIGN_D, SEL_GPS_3),
/* IPSR7 */
PINMUX_IPSR_DATA(IP7_2_0, IRQ9),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, DU1_DOTCLKIN_B, SEL_DIS_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, CAN_CLK_D, SEL_CANCLK_3),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, GPS_MAG_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, SCIF_CLK_B, SEL_SCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, GPS_MAG_D, SEL_GPS_3),
+ PINMUX_IPSR_MSEL(IP7_2_0, DU1_DOTCLKIN_B, SEL_DIS_1),
+ PINMUX_IPSR_MSEL(IP7_2_0, CAN_CLK_D, SEL_CANCLK_3),
+ PINMUX_IPSR_MSEL(IP7_2_0, GPS_MAG_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP7_2_0, SCIF_CLK_B, SEL_SCIF_1),
+ PINMUX_IPSR_MSEL(IP7_2_0, GPS_MAG_D, SEL_GPS_3),
PINMUX_IPSR_DATA(IP7_5_3, DU1_DR0),
PINMUX_IPSR_DATA(IP7_5_3, LCDOUT0),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, VI1_DATA0_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, TX0_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, SCIFA0_TXD_B, SEL_SCFA_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, MSIOF2_SCK_B, SEL_SOF2_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, VI1_DATA0_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, TX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, SCIFA0_TXD_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, MSIOF2_SCK_B, SEL_SOF2_1),
PINMUX_IPSR_DATA(IP7_8_6, DU1_DR1),
PINMUX_IPSR_DATA(IP7_8_6, LCDOUT1),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, VI1_DATA1_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, RX0_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, SCIFA0_RXD_B, SEL_SCFA_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, MSIOF2_SYNC_B, SEL_SOF2_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, VI1_DATA1_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, RX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, SCIFA0_RXD_B, SEL_SCFA_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, MSIOF2_SYNC_B, SEL_SOF2_1),
PINMUX_IPSR_DATA(IP7_10_9, DU1_DR2),
PINMUX_IPSR_DATA(IP7_10_9, LCDOUT2),
- PINMUX_IPSR_MODSEL_DATA(IP7_10_9, SSI_SCK0129_B, SEL_SSI0_1),
+ PINMUX_IPSR_MSEL(IP7_10_9, SSI_SCK0129_B, SEL_SSI0_1),
PINMUX_IPSR_DATA(IP7_12_11, DU1_DR3),
PINMUX_IPSR_DATA(IP7_12_11, LCDOUT3),
- PINMUX_IPSR_MODSEL_DATA(IP7_12_11, SSI_WS0129_B, SEL_SSI0_1),
+ PINMUX_IPSR_MSEL(IP7_12_11, SSI_WS0129_B, SEL_SSI0_1),
PINMUX_IPSR_DATA(IP7_14_13, DU1_DR4),
PINMUX_IPSR_DATA(IP7_14_13, LCDOUT4),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_13, SSI_SDATA0_B, SEL_SSI0_1),
+ PINMUX_IPSR_MSEL(IP7_14_13, SSI_SDATA0_B, SEL_SSI0_1),
PINMUX_IPSR_DATA(IP7_16_15, DU1_DR5),
PINMUX_IPSR_DATA(IP7_16_15, LCDOUT5),
- PINMUX_IPSR_MODSEL_DATA(IP7_16_15, SSI_SCK1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP7_16_15, SSI_SCK1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP7_18_17, DU1_DR6),
PINMUX_IPSR_DATA(IP7_18_17, LCDOUT6),
- PINMUX_IPSR_MODSEL_DATA(IP7_18_17, SSI_WS1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP7_18_17, SSI_WS1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP7_20_19, DU1_DR7),
PINMUX_IPSR_DATA(IP7_20_19, LCDOUT7),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_19, SSI_SDATA1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP7_20_19, SSI_SDATA1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP7_23_21, DU1_DG0),
PINMUX_IPSR_DATA(IP7_23_21, LCDOUT8),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, VI1_DATA2_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, TX1_B, SEL_SCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, SCIFA1_TXD_B, SEL_SCIFA1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, MSIOF2_SS1_B, SEL_SOF2_1),
+ PINMUX_IPSR_MSEL(IP7_23_21, VI1_DATA2_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP7_23_21, TX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP7_23_21, SCIFA1_TXD_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP7_23_21, MSIOF2_SS1_B, SEL_SOF2_1),
PINMUX_IPSR_DATA(IP7_26_24, DU1_DG1),
PINMUX_IPSR_DATA(IP7_26_24, LCDOUT9),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, VI1_DATA3_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, RX1_B, SEL_SCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, SCIFA1_RXD_B, SEL_SCIFA1_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, MSIOF2_SS2_B, SEL_SOF2_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, VI1_DATA3_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, RX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, SCIFA1_RXD_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, MSIOF2_SS2_B, SEL_SOF2_1),
PINMUX_IPSR_DATA(IP7_29_27, DU1_DG2),
PINMUX_IPSR_DATA(IP7_29_27, LCDOUT10),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, VI1_DATA4_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP7_29_27, VI1_DATA4_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP7_29_27, SCIF1_SCK_B),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, SCIFA1_SCK, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, SSI_SCK78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP7_29_27, SCIFA1_SCK, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP7_29_27, SSI_SCK78_B, SEL_SSI7_1),
/* IPSR8 */
PINMUX_IPSR_DATA(IP8_2_0, DU1_DG3),
PINMUX_IPSR_DATA(IP8_2_0, LCDOUT11),
- PINMUX_IPSR_MODSEL_DATA(IP8_2_0, VI1_DATA5_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_2_0, SSI_WS78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP8_2_0, VI1_DATA5_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_2_0, SSI_WS78_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP8_5_3, DU1_DG4),
PINMUX_IPSR_DATA(IP8_5_3, LCDOUT12),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, VI1_DATA6_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, HRX0_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, SCIFB2_RXD_B, SEL_SCIFB2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, SSI_SDATA7_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP8_5_3, VI1_DATA6_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_5_3, HRX0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP8_5_3, SCIFB2_RXD_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP8_5_3, SSI_SDATA7_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP8_8_6, DU1_DG5),
PINMUX_IPSR_DATA(IP8_8_6, LCDOUT13),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, VI1_DATA7_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, HCTS0_N_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, SCIFB2_TXD_B, SEL_SCIFB2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, SSI_SDATA8_B, SEL_SSI8_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, VI1_DATA7_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, HCTS0_N_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, SCIFB2_TXD_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, SSI_SDATA8_B, SEL_SSI8_1),
PINMUX_IPSR_DATA(IP8_11_9, DU1_DG6),
PINMUX_IPSR_DATA(IP8_11_9, LCDOUT14),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_9, HRTS0_N_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_9, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_9, SSI_SCK9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP8_11_9, HRTS0_N_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP8_11_9, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP8_11_9, SSI_SCK9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP8_14_12, DU1_DG7),
PINMUX_IPSR_DATA(IP8_14_12, LCDOUT15),
- PINMUX_IPSR_MODSEL_DATA(IP8_14_12, HTX0_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_14_12, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_14_12, SSI_WS9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP8_14_12, HTX0_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP8_14_12, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
+ PINMUX_IPSR_MSEL(IP8_14_12, SSI_WS9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP8_17_15, DU1_DB0),
PINMUX_IPSR_DATA(IP8_17_15, LCDOUT16),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_15, VI1_CLK_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_15, TX2_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_15, SCIFA2_TXD_B, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_15, MSIOF2_TXD_B, SEL_SOF2_1),
+ PINMUX_IPSR_MSEL(IP8_17_15, VI1_CLK_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_17_15, TX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP8_17_15, SCIFA2_TXD_B, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP8_17_15, MSIOF2_TXD_B, SEL_SOF2_1),
PINMUX_IPSR_DATA(IP8_20_18, DU1_DB1),
PINMUX_IPSR_DATA(IP8_20_18, LCDOUT17),
- PINMUX_IPSR_MODSEL_DATA(IP8_20_18, VI1_HSYNC_N_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_20_18, RX2_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_20_18, SCIFA2_RXD_B, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_20_18, MSIOF2_RXD_B, SEL_SOF2_1),
+ PINMUX_IPSR_MSEL(IP8_20_18, VI1_HSYNC_N_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_20_18, RX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP8_20_18, SCIFA2_RXD_B, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP8_20_18, MSIOF2_RXD_B, SEL_SOF2_1),
PINMUX_IPSR_DATA(IP8_23_21, DU1_DB2),
PINMUX_IPSR_DATA(IP8_23_21, LCDOUT18),
- PINMUX_IPSR_MODSEL_DATA(IP8_23_21, VI1_VSYNC_N_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_23_21, VI1_VSYNC_N_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP8_23_21, SCIF2_SCK_B),
- PINMUX_IPSR_MODSEL_DATA(IP8_23_21, SCIFA2_SCK, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_23_21, SSI_SDATA9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP8_23_21, SCIFA2_SCK, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP8_23_21, SSI_SDATA9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP8_25_24, DU1_DB3),
PINMUX_IPSR_DATA(IP8_25_24, LCDOUT19),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_24, VI1_CLKENB_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_25_24, VI1_CLKENB_B, SEL_VI1_1),
PINMUX_IPSR_DATA(IP8_27_26, DU1_DB4),
PINMUX_IPSR_DATA(IP8_27_26, LCDOUT20),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_26, VI1_FIELD_B, SEL_VI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_26, CAN1_RX, SEL_CAN1_0),
+ PINMUX_IPSR_MSEL(IP8_27_26, VI1_FIELD_B, SEL_VI1_1),
+ PINMUX_IPSR_MSEL(IP8_27_26, CAN1_RX, SEL_CAN1_0),
PINMUX_IPSR_DATA(IP8_30_28, DU1_DB5),
PINMUX_IPSR_DATA(IP8_30_28, LCDOUT21),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, TX3, SEL_SCIF3_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, SCIFA3_TXD, SEL_SCIFA3_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_30_28, CAN1_TX, SEL_CAN1_0),
+ PINMUX_IPSR_MSEL(IP8_30_28, TX3, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP8_30_28, SCIFA3_TXD, SEL_SCIFA3_0),
+ PINMUX_IPSR_MSEL(IP8_30_28, CAN1_TX, SEL_CAN1_0),
/* IPSR9 */
PINMUX_IPSR_DATA(IP9_2_0, DU1_DB6),
PINMUX_IPSR_DATA(IP9_2_0, LCDOUT22),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, SCL3_C, SEL_IIC3_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, RX3, SEL_SCIF3_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
+ PINMUX_IPSR_MSEL(IP9_2_0, SCL3_C, SEL_IIC3_2),
+ PINMUX_IPSR_MSEL(IP9_2_0, RX3, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP9_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
PINMUX_IPSR_DATA(IP9_5_3, DU1_DB7),
PINMUX_IPSR_DATA(IP9_5_3, LCDOUT23),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_3, SDA3_C, SEL_IIC3_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_3, SCIF3_SCK, SEL_SCIF3_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_3, SCIFA3_SCK, SEL_SCIFA3_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_6, DU1_DOTCLKIN, SEL_DIS_0),
+ PINMUX_IPSR_MSEL(IP9_5_3, SDA3_C, SEL_IIC3_2),
+ PINMUX_IPSR_MSEL(IP9_5_3, SCIF3_SCK, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP9_5_3, SCIFA3_SCK, SEL_SCIFA3_0),
+ PINMUX_IPSR_MSEL(IP9_6, DU1_DOTCLKIN, SEL_DIS_0),
PINMUX_IPSR_DATA(IP9_6, QSTVA_QVS),
PINMUX_IPSR_DATA(IP9_7, DU1_DOTCLKOUT0),
PINMUX_IPSR_DATA(IP9_7, QCLK),
PINMUX_IPSR_DATA(IP9_10_8, DU1_DOTCLKOUT1),
PINMUX_IPSR_DATA(IP9_10_8, QSTVB_QVE),
- PINMUX_IPSR_MODSEL_DATA(IP9_10_8, CAN0_TX, SEL_CAN0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_10_8, TX3_B, SEL_SCIF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_10_8, SCL2_B, SEL_IIC2_1),
+ PINMUX_IPSR_MSEL(IP9_10_8, CAN0_TX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP9_10_8, TX3_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP9_10_8, SCL2_B, SEL_IIC2_1),
PINMUX_IPSR_DATA(IP9_10_8, PWM4),
PINMUX_IPSR_DATA(IP9_11, DU1_EXHSYNC_DU1_HSYNC),
PINMUX_IPSR_DATA(IP9_11, QSTH_QHS),
@@ -1284,280 +1283,280 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP9_12, QSTB_QHE),
PINMUX_IPSR_DATA(IP9_15_13, DU1_EXODDF_DU1_ODDF_DISP_CDE),
PINMUX_IPSR_DATA(IP9_15_13, QCPV_QDE),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_13, CAN0_RX, SEL_CAN0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_13, RX3_B, SEL_SCIF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_13, SDA2_B, SEL_IIC2_1),
+ PINMUX_IPSR_MSEL(IP9_15_13, CAN0_RX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP9_15_13, RX3_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP9_15_13, SDA2_B, SEL_IIC2_1),
PINMUX_IPSR_DATA(IP9_16, DU1_DISP),
PINMUX_IPSR_DATA(IP9_16, QPOLA),
PINMUX_IPSR_DATA(IP9_18_17, DU1_CDE),
PINMUX_IPSR_DATA(IP9_18_17, QPOLB),
PINMUX_IPSR_DATA(IP9_18_17, PWM4_B),
PINMUX_IPSR_DATA(IP9_20_19, VI0_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP9_20_19, TX4, SEL_SCIF4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_20_19, SCIFA4_TXD, SEL_SCIFA4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_20_19, TS_SDATA0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP9_20_19, TX4, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP9_20_19, SCIFA4_TXD, SEL_SCIFA4_0),
+ PINMUX_IPSR_MSEL(IP9_20_19, TS_SDATA0_D, SEL_TSIF0_3),
PINMUX_IPSR_DATA(IP9_22_21, VI0_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP9_22_21, RX4, SEL_SCIF4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_22_21, SCIFA4_RXD, SEL_SCIFA4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_22_21, TS_SCK0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP9_22_21, RX4, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP9_22_21, SCIFA4_RXD, SEL_SCIFA4_0),
+ PINMUX_IPSR_MSEL(IP9_22_21, TS_SCK0_D, SEL_TSIF0_3),
PINMUX_IPSR_DATA(IP9_24_23, VI0_HSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_23, TX5, SEL_SCIF5_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_23, SCIFA5_TXD, SEL_SCIFA5_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_23, TS_SDEN0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP9_24_23, TX5, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP9_24_23, SCIFA5_TXD, SEL_SCIFA5_0),
+ PINMUX_IPSR_MSEL(IP9_24_23, TS_SDEN0_D, SEL_TSIF0_3),
PINMUX_IPSR_DATA(IP9_26_25, VI0_VSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP9_26_25, RX5, SEL_SCIF5_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_26_25, SCIFA5_RXD, SEL_SCIFA5_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_26_25, TS_SPSYNC0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP9_26_25, RX5, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP9_26_25, SCIFA5_RXD, SEL_SCIFA5_0),
+ PINMUX_IPSR_MSEL(IP9_26_25, TS_SPSYNC0_D, SEL_TSIF0_3),
PINMUX_IPSR_DATA(IP9_28_27, VI0_DATA3_VI0_B3),
- PINMUX_IPSR_MODSEL_DATA(IP9_28_27, SCIF3_SCK_B, SEL_SCIF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_28_27, SCIFA3_SCK_B, SEL_SCIFA3_1),
+ PINMUX_IPSR_MSEL(IP9_28_27, SCIF3_SCK_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP9_28_27, SCIFA3_SCK_B, SEL_SCIFA3_1),
PINMUX_IPSR_DATA(IP9_31_29, VI0_G0),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_29, SCL8, SEL_IIC8_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_29, STP_IVCXO27_0_C, SEL_SSP_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_29, SCL4, SEL_IIC4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_29, HCTS2_N, SEL_HSCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_31_29, SCIFB2_CTS_N, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP9_31_29, SCL8, SEL_IIC8_0),
+ PINMUX_IPSR_MSEL(IP9_31_29, STP_IVCXO27_0_C, SEL_SSP_2),
+ PINMUX_IPSR_MSEL(IP9_31_29, SCL4, SEL_IIC4_0),
+ PINMUX_IPSR_MSEL(IP9_31_29, HCTS2_N, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP9_31_29, SCIFB2_CTS_N, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP9_31_29, ATAWR1_N),
/* IPSR10 */
PINMUX_IPSR_DATA(IP10_2_0, VI0_G1),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SDA8, SEL_IIC8_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, STP_ISCLK_0_C, SEL_SSP_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SDA4, SEL_IIC4_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, HRTS2_N, SEL_HSCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SCIFB2_RTS_N, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, SDA8, SEL_IIC8_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, STP_ISCLK_0_C, SEL_SSP_2),
+ PINMUX_IPSR_MSEL(IP10_2_0, SDA4, SEL_IIC4_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, HRTS2_N, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, SCIFB2_RTS_N, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP10_2_0, ATADIR1_N),
PINMUX_IPSR_DATA(IP10_5_3, VI0_G2),
PINMUX_IPSR_DATA(IP10_5_3, VI2_HSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, STP_ISD_0_C, SEL_SSP_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SCL3_B, SEL_IIC3_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, HSCK2, SEL_HSCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SCIFB2_SCK, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP10_5_3, STP_ISD_0_C, SEL_SSP_2),
+ PINMUX_IPSR_MSEL(IP10_5_3, SCL3_B, SEL_IIC3_1),
+ PINMUX_IPSR_MSEL(IP10_5_3, HSCK2, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_5_3, SCIFB2_SCK, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP10_5_3, ATARD1_N),
PINMUX_IPSR_DATA(IP10_8_6, VI0_G3),
PINMUX_IPSR_DATA(IP10_8_6, VI2_VSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, STP_ISEN_0_C, SEL_SSP_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, SDA3_B, SEL_IIC3_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, HRX2, SEL_HSCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, SCIFB2_RXD, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP10_8_6, STP_ISEN_0_C, SEL_SSP_2),
+ PINMUX_IPSR_MSEL(IP10_8_6, SDA3_B, SEL_IIC3_1),
+ PINMUX_IPSR_MSEL(IP10_8_6, HRX2, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_8_6, SCIFB2_RXD, SEL_SCIFB2_0),
PINMUX_IPSR_DATA(IP10_8_6, ATACS01_N),
PINMUX_IPSR_DATA(IP10_11_9, VI0_G4),
PINMUX_IPSR_DATA(IP10_11_9, VI2_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, STP_ISSYNC_0_C, SEL_SSP_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, HTX2, SEL_HSCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SCIFB2_TXD, SEL_SCIFB2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SCIFB0_SCK_D, SEL_SCIFB_3),
+ PINMUX_IPSR_MSEL(IP10_11_9, STP_ISSYNC_0_C, SEL_SSP_2),
+ PINMUX_IPSR_MSEL(IP10_11_9, HTX2, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_11_9, SCIFB2_TXD, SEL_SCIFB2_0),
+ PINMUX_IPSR_MSEL(IP10_11_9, SCIFB0_SCK_D, SEL_SCIFB_3),
PINMUX_IPSR_DATA(IP10_14_12, VI0_G5),
PINMUX_IPSR_DATA(IP10_14_12, VI2_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, STP_OPWM_0_C, SEL_SSP_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, FMCLK_D, SEL_FM_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, CAN0_TX_E, SEL_CAN0_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, HTX1_D, SEL_HSCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SCIFB0_TXD_D, SEL_SCIFB_3),
+ PINMUX_IPSR_MSEL(IP10_14_12, STP_OPWM_0_C, SEL_SSP_2),
+ PINMUX_IPSR_MSEL(IP10_14_12, FMCLK_D, SEL_FM_3),
+ PINMUX_IPSR_MSEL(IP10_14_12, CAN0_TX_E, SEL_CAN0_4),
+ PINMUX_IPSR_MSEL(IP10_14_12, HTX1_D, SEL_HSCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_14_12, SCIFB0_TXD_D, SEL_SCIFB_3),
PINMUX_IPSR_DATA(IP10_16_15, VI0_G6),
PINMUX_IPSR_DATA(IP10_16_15, VI2_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP10_16_15, BPFCLK_D, SEL_FM_3),
+ PINMUX_IPSR_MSEL(IP10_16_15, BPFCLK_D, SEL_FM_3),
PINMUX_IPSR_DATA(IP10_18_17, VI0_G7),
PINMUX_IPSR_DATA(IP10_18_17, VI2_DATA0),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_17, FMIN_D, SEL_FM_3),
+ PINMUX_IPSR_MSEL(IP10_18_17, FMIN_D, SEL_FM_3),
PINMUX_IPSR_DATA(IP10_21_19, VI0_R0),
PINMUX_IPSR_DATA(IP10_21_19, VI2_DATA1),
- PINMUX_IPSR_MODSEL_DATA(IP10_21_19, GLO_I0_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_21_19, TS_SDATA0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_21_19, GLO_I0_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_21_19, TS_SDATA0_C, SEL_TSIF0_2),
PINMUX_IPSR_DATA(IP10_21_19, ATACS11_N),
PINMUX_IPSR_DATA(IP10_24_22, VI0_R1),
PINMUX_IPSR_DATA(IP10_24_22, VI2_DATA2),
- PINMUX_IPSR_MODSEL_DATA(IP10_24_22, GLO_I1_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_24_22, TS_SCK0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_24_22, GLO_I1_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_24_22, TS_SCK0_C, SEL_TSIF0_2),
PINMUX_IPSR_DATA(IP10_24_22, ATAG1_N),
PINMUX_IPSR_DATA(IP10_26_25, VI0_R2),
PINMUX_IPSR_DATA(IP10_26_25, VI2_DATA3),
- PINMUX_IPSR_MODSEL_DATA(IP10_26_25, GLO_Q0_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_26_25, TS_SDEN0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_26_25, GLO_Q0_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_26_25, TS_SDEN0_C, SEL_TSIF0_2),
PINMUX_IPSR_DATA(IP10_28_27, VI0_R3),
PINMUX_IPSR_DATA(IP10_28_27, VI2_DATA4),
- PINMUX_IPSR_MODSEL_DATA(IP10_28_27, GLO_Q1_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_28_27, TS_SPSYNC0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_28_27, GLO_Q1_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_28_27, TS_SPSYNC0_C, SEL_TSIF0_2),
PINMUX_IPSR_DATA(IP10_31_29, VI0_R4),
PINMUX_IPSR_DATA(IP10_31_29, VI2_DATA5),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_29, GLO_SCLK_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_29, TX0_C, SEL_SCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_29, SCL1_D, SEL_IIC1_3),
+ PINMUX_IPSR_MSEL(IP10_31_29, GLO_SCLK_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP10_31_29, TX0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP10_31_29, SCL1_D, SEL_IIC1_3),
/* IPSR11 */
PINMUX_IPSR_DATA(IP11_2_0, VI0_R5),
PINMUX_IPSR_DATA(IP11_2_0, VI2_DATA6),
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, GLO_SDATA_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, RX0_C, SEL_SCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, SDA1_D, SEL_IIC1_3),
+ PINMUX_IPSR_MSEL(IP11_2_0, GLO_SDATA_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP11_2_0, RX0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP11_2_0, SDA1_D, SEL_IIC1_3),
PINMUX_IPSR_DATA(IP11_5_3, VI0_R6),
PINMUX_IPSR_DATA(IP11_5_3, VI2_DATA7),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, GLO_SS_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, TX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, SCL4_B, SEL_IIC4_1),
+ PINMUX_IPSR_MSEL(IP11_5_3, GLO_SS_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP11_5_3, TX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP11_5_3, SCL4_B, SEL_IIC4_1),
PINMUX_IPSR_DATA(IP11_8_6, VI0_R7),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, GLO_RFON_B, SEL_GPS_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, RX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, CAN0_RX_E, SEL_CAN0_4),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SDA4_B, SEL_IIC4_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, HRX1_D, SEL_HSCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SCIFB0_RXD_D, SEL_SCIFB_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_9, VI1_HSYNC_N, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_8_6, GLO_RFON_B, SEL_GPS_1),
+ PINMUX_IPSR_MSEL(IP11_8_6, RX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP11_8_6, CAN0_RX_E, SEL_CAN0_4),
+ PINMUX_IPSR_MSEL(IP11_8_6, SDA4_B, SEL_IIC4_1),
+ PINMUX_IPSR_MSEL(IP11_8_6, HRX1_D, SEL_HSCIF1_3),
+ PINMUX_IPSR_MSEL(IP11_8_6, SCIFB0_RXD_D, SEL_SCIFB_3),
+ PINMUX_IPSR_MSEL(IP11_11_9, VI1_HSYNC_N, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_11_9, AVB_RXD0),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_9, TS_SDATA0_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_9, TX4_B, SEL_SCIF4_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_9, SCIFA4_TXD_B, SEL_SCIFA4_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_14_12, VI1_VSYNC_N, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_11_9, TS_SDATA0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP11_11_9, TX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP11_11_9, SCIFA4_TXD_B, SEL_SCIFA4_1),
+ PINMUX_IPSR_MSEL(IP11_14_12, VI1_VSYNC_N, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_14_12, AVB_RXD1),
- PINMUX_IPSR_MODSEL_DATA(IP11_14_12, TS_SCK0_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_14_12, RX4_B, SEL_SCIF4_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_14_12, SCIFA4_RXD_B, SEL_SCIFA4_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_16_15, VI1_CLKENB, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_14_12, TS_SCK0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP11_14_12, RX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP11_14_12, SCIFA4_RXD_B, SEL_SCIFA4_1),
+ PINMUX_IPSR_MSEL(IP11_16_15, VI1_CLKENB, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_16_15, AVB_RXD2),
- PINMUX_IPSR_MODSEL_DATA(IP11_16_15, TS_SDEN0_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_18_17, VI1_FIELD, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_16_15, TS_SDEN0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP11_18_17, VI1_FIELD, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_18_17, AVB_RXD3),
- PINMUX_IPSR_MODSEL_DATA(IP11_18_17, TS_SPSYNC0_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_19, VI1_CLK, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_18_17, TS_SPSYNC0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP11_19, VI1_CLK, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_19, AVB_RXD4),
- PINMUX_IPSR_MODSEL_DATA(IP11_20, VI1_DATA0, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_20, VI1_DATA0, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_20, AVB_RXD5),
- PINMUX_IPSR_MODSEL_DATA(IP11_21, VI1_DATA1, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_21, VI1_DATA1, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_21, AVB_RXD6),
- PINMUX_IPSR_MODSEL_DATA(IP11_22, VI1_DATA2, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_22, VI1_DATA2, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_22, AVB_RXD7),
- PINMUX_IPSR_MODSEL_DATA(IP11_23, VI1_DATA3, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_23, VI1_DATA3, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_23, AVB_RX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP11_24, VI1_DATA4, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_24, VI1_DATA4, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_24, AVB_MDIO),
- PINMUX_IPSR_MODSEL_DATA(IP11_25, VI1_DATA5, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_25, VI1_DATA5, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_25, AVB_RX_DV),
- PINMUX_IPSR_MODSEL_DATA(IP11_26, VI1_DATA6, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_26, VI1_DATA6, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_26, AVB_MAGIC),
- PINMUX_IPSR_MODSEL_DATA(IP11_27, VI1_DATA7, SEL_VI1_0),
+ PINMUX_IPSR_MSEL(IP11_27, VI1_DATA7, SEL_VI1_0),
PINMUX_IPSR_DATA(IP11_27, AVB_MDC),
PINMUX_IPSR_DATA(IP11_29_28, ETH_MDIO),
PINMUX_IPSR_DATA(IP11_29_28, AVB_RX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_28, SCL2_C, SEL_IIC2_2),
+ PINMUX_IPSR_MSEL(IP11_29_28, SCL2_C, SEL_IIC2_2),
PINMUX_IPSR_DATA(IP11_31_30, ETH_CRS_DV),
PINMUX_IPSR_DATA(IP11_31_30, AVB_LINK),
- PINMUX_IPSR_MODSEL_DATA(IP11_31_30, SDA2_C, SEL_IIC2_2),
+ PINMUX_IPSR_MSEL(IP11_31_30, SDA2_C, SEL_IIC2_2),
/* IPSR12 */
PINMUX_IPSR_DATA(IP12_1_0, ETH_RX_ER),
PINMUX_IPSR_DATA(IP12_1_0, AVB_CRS),
- PINMUX_IPSR_MODSEL_DATA(IP12_1_0, SCL3, SEL_IIC3_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_1_0, SCL7, SEL_IIC7_0),
+ PINMUX_IPSR_MSEL(IP12_1_0, SCL3, SEL_IIC3_0),
+ PINMUX_IPSR_MSEL(IP12_1_0, SCL7, SEL_IIC7_0),
PINMUX_IPSR_DATA(IP12_3_2, ETH_RXD0),
PINMUX_IPSR_DATA(IP12_3_2, AVB_PHY_INT),
- PINMUX_IPSR_MODSEL_DATA(IP12_3_2, SDA3, SEL_IIC3_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_3_2, SDA7, SEL_IIC7_0),
+ PINMUX_IPSR_MSEL(IP12_3_2, SDA3, SEL_IIC3_0),
+ PINMUX_IPSR_MSEL(IP12_3_2, SDA7, SEL_IIC7_0),
PINMUX_IPSR_DATA(IP12_6_4, ETH_RXD1),
PINMUX_IPSR_DATA(IP12_6_4, AVB_GTXREFCLK),
- PINMUX_IPSR_MODSEL_DATA(IP12_6_4, CAN0_TX_C, SEL_CAN0_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_6_4, SCL2_D, SEL_IIC2_3),
- PINMUX_IPSR_MODSEL_DATA(IP12_6_4, MSIOF1_RXD_E, SEL_SOF1_4),
+ PINMUX_IPSR_MSEL(IP12_6_4, CAN0_TX_C, SEL_CAN0_2),
+ PINMUX_IPSR_MSEL(IP12_6_4, SCL2_D, SEL_IIC2_3),
+ PINMUX_IPSR_MSEL(IP12_6_4, MSIOF1_RXD_E, SEL_SOF1_4),
PINMUX_IPSR_DATA(IP12_9_7, ETH_LINK),
PINMUX_IPSR_DATA(IP12_9_7, AVB_TXD0),
- PINMUX_IPSR_MODSEL_DATA(IP12_9_7, CAN0_RX_C, SEL_CAN0_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_9_7, SDA2_D, SEL_IIC2_3),
- PINMUX_IPSR_MODSEL_DATA(IP12_9_7, MSIOF1_SCK_E, SEL_SOF1_4),
+ PINMUX_IPSR_MSEL(IP12_9_7, CAN0_RX_C, SEL_CAN0_2),
+ PINMUX_IPSR_MSEL(IP12_9_7, SDA2_D, SEL_IIC2_3),
+ PINMUX_IPSR_MSEL(IP12_9_7, MSIOF1_SCK_E, SEL_SOF1_4),
PINMUX_IPSR_DATA(IP12_12_10, ETH_REFCLK),
PINMUX_IPSR_DATA(IP12_12_10, AVB_TXD1),
- PINMUX_IPSR_MODSEL_DATA(IP12_12_10, SCIFA3_RXD_B, SEL_SCIFA3_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_12_10, CAN1_RX_C, SEL_CAN1_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_12_10, MSIOF1_SYNC_E, SEL_SOF1_4),
+ PINMUX_IPSR_MSEL(IP12_12_10, SCIFA3_RXD_B, SEL_SCIFA3_1),
+ PINMUX_IPSR_MSEL(IP12_12_10, CAN1_RX_C, SEL_CAN1_2),
+ PINMUX_IPSR_MSEL(IP12_12_10, MSIOF1_SYNC_E, SEL_SOF1_4),
PINMUX_IPSR_DATA(IP12_15_13, ETH_TXD1),
PINMUX_IPSR_DATA(IP12_15_13, AVB_TXD2),
- PINMUX_IPSR_MODSEL_DATA(IP12_15_13, SCIFA3_TXD_B, SEL_SCIFA3_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_15_13, CAN1_TX_C, SEL_CAN1_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_15_13, MSIOF1_TXD_E, SEL_SOF1_4),
+ PINMUX_IPSR_MSEL(IP12_15_13, SCIFA3_TXD_B, SEL_SCIFA3_1),
+ PINMUX_IPSR_MSEL(IP12_15_13, CAN1_TX_C, SEL_CAN1_2),
+ PINMUX_IPSR_MSEL(IP12_15_13, MSIOF1_TXD_E, SEL_SOF1_4),
PINMUX_IPSR_DATA(IP12_17_16, ETH_TX_EN),
PINMUX_IPSR_DATA(IP12_17_16, AVB_TXD3),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_16, TCLK1_B, SEL_TMU1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_16, CAN_CLK_B, SEL_CANCLK_1),
+ PINMUX_IPSR_MSEL(IP12_17_16, TCLK1_B, SEL_TMU1_0),
+ PINMUX_IPSR_MSEL(IP12_17_16, CAN_CLK_B, SEL_CANCLK_1),
PINMUX_IPSR_DATA(IP12_19_18, ETH_MAGIC),
PINMUX_IPSR_DATA(IP12_19_18, AVB_TXD4),
- PINMUX_IPSR_MODSEL_DATA(IP12_19_18, IETX_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP12_19_18, IETX_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP12_21_20, ETH_TXD0),
PINMUX_IPSR_DATA(IP12_21_20, AVB_TXD5),
- PINMUX_IPSR_MODSEL_DATA(IP12_21_20, IECLK_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP12_21_20, IECLK_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP12_23_22, ETH_MDC),
PINMUX_IPSR_DATA(IP12_23_22, AVB_TXD6),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_22, IERX_C, SEL_IEB_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, STP_IVCXO27_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_23_22, IERX_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP12_26_24, STP_IVCXO27_0, SEL_SSP_0),
PINMUX_IPSR_DATA(IP12_26_24, AVB_TXD7),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, SCIFB2_TXD_D, SEL_SCIFB2_3),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, ADIDATA_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, MSIOF0_SYNC_C, SEL_SOF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, STP_ISCLK_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP12_26_24, SCIFB2_TXD_D, SEL_SCIFB2_3),
+ PINMUX_IPSR_MSEL(IP12_26_24, ADIDATA_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP12_26_24, MSIOF0_SYNC_C, SEL_SOF0_2),
+ PINMUX_IPSR_MSEL(IP12_29_27, STP_ISCLK_0, SEL_SSP_0),
PINMUX_IPSR_DATA(IP12_29_27, AVB_TX_EN),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, SCIFB2_RXD_D, SEL_SCIFB2_3),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, ADICS_SAMP_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, MSIOF0_SCK_C, SEL_SOF0_2),
+ PINMUX_IPSR_MSEL(IP12_29_27, SCIFB2_RXD_D, SEL_SCIFB2_3),
+ PINMUX_IPSR_MSEL(IP12_29_27, ADICS_SAMP_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP12_29_27, MSIOF0_SCK_C, SEL_SOF0_2),
/* IPSR13 */
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, STP_ISD_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_2_0, STP_ISD_0, SEL_SSP_0),
PINMUX_IPSR_DATA(IP13_2_0, AVB_TX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SCIFB2_SCK_C, SEL_SCIFB2_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, ADICLK_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, MSIOF0_SS1_C, SEL_SOF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_4_3, STP_ISEN_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_2_0, SCIFB2_SCK_C, SEL_SCIFB2_2),
+ PINMUX_IPSR_MSEL(IP13_2_0, ADICLK_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP13_2_0, MSIOF0_SS1_C, SEL_SOF0_2),
+ PINMUX_IPSR_MSEL(IP13_4_3, STP_ISEN_0, SEL_SSP_0),
PINMUX_IPSR_DATA(IP13_4_3, AVB_TX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP13_4_3, ADICHS0_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_4_3, MSIOF0_SS2_C, SEL_SOF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_5, STP_ISSYNC_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_4_3, ADICHS0_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP13_4_3, MSIOF0_SS2_C, SEL_SOF0_2),
+ PINMUX_IPSR_MSEL(IP13_6_5, STP_ISSYNC_0, SEL_SSP_0),
PINMUX_IPSR_DATA(IP13_6_5, AVB_COL),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_5, ADICHS1_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_6_5, MSIOF0_RXD_C, SEL_SOF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_9_7, STP_OPWM_0, SEL_SSP_0),
+ PINMUX_IPSR_MSEL(IP13_6_5, ADICHS1_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP13_6_5, MSIOF0_RXD_C, SEL_SOF0_2),
+ PINMUX_IPSR_MSEL(IP13_9_7, STP_OPWM_0, SEL_SSP_0),
PINMUX_IPSR_DATA(IP13_9_7, AVB_GTX_CLK),
PINMUX_IPSR_DATA(IP13_9_7, PWM0_B),
- PINMUX_IPSR_MODSEL_DATA(IP13_9_7, ADICHS2_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_9_7, MSIOF0_TXD_C, SEL_SOF0_2),
+ PINMUX_IPSR_MSEL(IP13_9_7, ADICHS2_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP13_9_7, MSIOF0_TXD_C, SEL_SOF0_2),
PINMUX_IPSR_DATA(IP13_10, SD0_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP13_10, SPCLK_B, SEL_QSP_1),
+ PINMUX_IPSR_MSEL(IP13_10, SPCLK_B, SEL_QSP_1),
PINMUX_IPSR_DATA(IP13_11, SD0_CMD),
- PINMUX_IPSR_MODSEL_DATA(IP13_11, MOSI_IO0_B, SEL_QSP_1),
+ PINMUX_IPSR_MSEL(IP13_11, MOSI_IO0_B, SEL_QSP_1),
PINMUX_IPSR_DATA(IP13_12, SD0_DATA0),
- PINMUX_IPSR_MODSEL_DATA(IP13_12, MISO_IO1_B, SEL_QSP_1),
+ PINMUX_IPSR_MSEL(IP13_12, MISO_IO1_B, SEL_QSP_1),
PINMUX_IPSR_DATA(IP13_13, SD0_DATA1),
- PINMUX_IPSR_MODSEL_DATA(IP13_13, IO2_B, SEL_QSP_1),
+ PINMUX_IPSR_MSEL(IP13_13, IO2_B, SEL_QSP_1),
PINMUX_IPSR_DATA(IP13_14, SD0_DATA2),
- PINMUX_IPSR_MODSEL_DATA(IP13_14, IO3_B, SEL_QSP_1),
+ PINMUX_IPSR_MSEL(IP13_14, IO3_B, SEL_QSP_1),
PINMUX_IPSR_DATA(IP13_15, SD0_DATA3),
- PINMUX_IPSR_MODSEL_DATA(IP13_15, SSL_B, SEL_QSP_1),
+ PINMUX_IPSR_MSEL(IP13_15, SSL_B, SEL_QSP_1),
PINMUX_IPSR_DATA(IP13_18_16, SD0_CD),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, MMC_D6_B, SEL_MMC_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, SIM0_RST_B, SEL_SIM_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, CAN0_RX_F, SEL_CAN0_5),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, SCIFA5_TXD_B, SEL_SCIFA5_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_18_16, TX3_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MSEL(IP13_18_16, MMC_D6_B, SEL_MMC_1),
+ PINMUX_IPSR_MSEL(IP13_18_16, SIM0_RST_B, SEL_SIM_1),
+ PINMUX_IPSR_MSEL(IP13_18_16, CAN0_RX_F, SEL_CAN0_5),
+ PINMUX_IPSR_MSEL(IP13_18_16, SCIFA5_TXD_B, SEL_SCIFA5_1),
+ PINMUX_IPSR_MSEL(IP13_18_16, TX3_C, SEL_SCIF3_2),
PINMUX_IPSR_DATA(IP13_21_19, SD0_WP),
- PINMUX_IPSR_MODSEL_DATA(IP13_21_19, MMC_D7_B, SEL_MMC_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_21_19, SIM0_D_B, SEL_SIM_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_21_19, CAN0_TX_F, SEL_CAN0_5),
- PINMUX_IPSR_MODSEL_DATA(IP13_21_19, SCIFA5_RXD_B, SEL_SCIFA5_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_21_19, RX3_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MSEL(IP13_21_19, MMC_D7_B, SEL_MMC_1),
+ PINMUX_IPSR_MSEL(IP13_21_19, SIM0_D_B, SEL_SIM_1),
+ PINMUX_IPSR_MSEL(IP13_21_19, CAN0_TX_F, SEL_CAN0_5),
+ PINMUX_IPSR_MSEL(IP13_21_19, SCIFA5_RXD_B, SEL_SCIFA5_1),
+ PINMUX_IPSR_MSEL(IP13_21_19, RX3_C, SEL_SCIF3_2),
PINMUX_IPSR_DATA(IP13_22, SD1_CMD),
- PINMUX_IPSR_MODSEL_DATA(IP13_22, REMOCON_B, SEL_RCN_1),
+ PINMUX_IPSR_MSEL(IP13_22, REMOCON_B, SEL_RCN_1),
PINMUX_IPSR_DATA(IP13_24_23, SD1_DATA0),
- PINMUX_IPSR_MODSEL_DATA(IP13_24_23, SPEEDIN_B, SEL_RSP_1),
+ PINMUX_IPSR_MSEL(IP13_24_23, SPEEDIN_B, SEL_RSP_1),
PINMUX_IPSR_DATA(IP13_25, SD1_DATA1),
- PINMUX_IPSR_MODSEL_DATA(IP13_25, IETX_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP13_25, IETX_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP13_26, SD1_DATA2),
- PINMUX_IPSR_MODSEL_DATA(IP13_26, IECLK_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP13_26, IECLK_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP13_27, SD1_DATA3),
- PINMUX_IPSR_MODSEL_DATA(IP13_27, IERX_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP13_27, IERX_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP13_30_28, SD1_CD),
PINMUX_IPSR_DATA(IP13_30_28, PWM0),
PINMUX_IPSR_DATA(IP13_30_28, TPU_TO0),
- PINMUX_IPSR_MODSEL_DATA(IP13_30_28, SCL1_C, SEL_IIC1_2),
+ PINMUX_IPSR_MSEL(IP13_30_28, SCL1_C, SEL_IIC1_2),
/* IPSR14 */
PINMUX_IPSR_DATA(IP14_1_0, SD1_WP),
PINMUX_IPSR_DATA(IP14_1_0, PWM1_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_1_0, SDA1_C, SEL_IIC1_2),
+ PINMUX_IPSR_MSEL(IP14_1_0, SDA1_C, SEL_IIC1_2),
PINMUX_IPSR_DATA(IP14_2, SD2_CLK),
PINMUX_IPSR_DATA(IP14_2, MMC_CLK),
PINMUX_IPSR_DATA(IP14_3, SD2_CMD),
@@ -1572,123 +1571,123 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP14_7, MMC_D3),
PINMUX_IPSR_DATA(IP14_10_8, SD2_CD),
PINMUX_IPSR_DATA(IP14_10_8, MMC_D4),
- PINMUX_IPSR_MODSEL_DATA(IP14_10_8, SCL8_C, SEL_IIC8_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_10_8, TX5_B, SEL_SCIF5_1),
- PINMUX_IPSR_MODSEL_DATA(IP14_10_8, SCIFA5_TXD_C, SEL_SCIFA5_2),
+ PINMUX_IPSR_MSEL(IP14_10_8, SCL8_C, SEL_IIC8_2),
+ PINMUX_IPSR_MSEL(IP14_10_8, TX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP14_10_8, SCIFA5_TXD_C, SEL_SCIFA5_2),
PINMUX_IPSR_DATA(IP14_13_11, SD2_WP),
PINMUX_IPSR_DATA(IP14_13_11, MMC_D5),
- PINMUX_IPSR_MODSEL_DATA(IP14_13_11, SDA8_C, SEL_IIC8_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_13_11, RX5_B, SEL_SCIF5_1),
- PINMUX_IPSR_MODSEL_DATA(IP14_13_11, SCIFA5_RXD_C, SEL_SCIFA5_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_16_14, MSIOF0_SCK, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_16_14, RX2_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_16_14, ADIDATA, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_16_14, VI1_CLK_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP14_13_11, SDA8_C, SEL_IIC8_2),
+ PINMUX_IPSR_MSEL(IP14_13_11, RX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP14_13_11, SCIFA5_RXD_C, SEL_SCIFA5_2),
+ PINMUX_IPSR_MSEL(IP14_16_14, MSIOF0_SCK, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP14_16_14, RX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP14_16_14, ADIDATA, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP14_16_14, VI1_CLK_C, SEL_VI1_2),
PINMUX_IPSR_DATA(IP14_16_14, VI1_G0_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_19_17, MSIOF0_SYNC, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_19_17, TX2_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_19_17, ADICS_SAMP, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_19_17, VI1_CLKENB_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP14_19_17, MSIOF0_SYNC, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP14_19_17, TX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP14_19_17, ADICS_SAMP, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP14_19_17, VI1_CLKENB_C, SEL_VI1_2),
PINMUX_IPSR_DATA(IP14_19_17, VI1_G1_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_22_20, MSIOF0_TXD, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_22_20, ADICLK, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_22_20, VI1_FIELD_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP14_22_20, MSIOF0_TXD, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP14_22_20, ADICLK, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP14_22_20, VI1_FIELD_C, SEL_VI1_2),
PINMUX_IPSR_DATA(IP14_22_20, VI1_G2_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_25_23, MSIOF0_RXD, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_25_23, ADICHS0, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_25_23, VI1_DATA0_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP14_25_23, MSIOF0_RXD, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP14_25_23, ADICHS0, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP14_25_23, VI1_DATA0_C, SEL_VI1_2),
PINMUX_IPSR_DATA(IP14_25_23, VI1_G3_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_28_26, MSIOF0_SS1, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_28_26, MMC_D6, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_28_26, ADICHS1, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_28_26, TX0_E, SEL_SCIF0_4),
- PINMUX_IPSR_MODSEL_DATA(IP14_28_26, VI1_HSYNC_N_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_28_26, SCL7_C, SEL_IIC7_2),
+ PINMUX_IPSR_MSEL(IP14_28_26, MSIOF0_SS1, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP14_28_26, MMC_D6, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP14_28_26, ADICHS1, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP14_28_26, TX0_E, SEL_SCIF0_4),
+ PINMUX_IPSR_MSEL(IP14_28_26, VI1_HSYNC_N_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP14_28_26, SCL7_C, SEL_IIC7_2),
PINMUX_IPSR_DATA(IP14_28_26, VI1_G4_B),
- PINMUX_IPSR_MODSEL_DATA(IP14_31_29, MSIOF0_SS2, SEL_SOF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_31_29, MMC_D7, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_31_29, ADICHS2, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP14_31_29, RX0_E, SEL_SCIF0_4),
- PINMUX_IPSR_MODSEL_DATA(IP14_31_29, VI1_VSYNC_N_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP14_31_29, SDA7_C, SEL_IIC7_2),
+ PINMUX_IPSR_MSEL(IP14_31_29, MSIOF0_SS2, SEL_SOF0_0),
+ PINMUX_IPSR_MSEL(IP14_31_29, MMC_D7, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP14_31_29, ADICHS2, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP14_31_29, RX0_E, SEL_SCIF0_4),
+ PINMUX_IPSR_MSEL(IP14_31_29, VI1_VSYNC_N_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP14_31_29, SDA7_C, SEL_IIC7_2),
PINMUX_IPSR_DATA(IP14_31_29, VI1_G5_B),
/* IPSR15 */
- PINMUX_IPSR_MODSEL_DATA(IP15_1_0, SIM0_RST, SEL_SIM_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_1_0, IETX, SEL_IEB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_1_0, CAN1_TX_D, SEL_CAN1_3),
+ PINMUX_IPSR_MSEL(IP15_1_0, SIM0_RST, SEL_SIM_0),
+ PINMUX_IPSR_MSEL(IP15_1_0, IETX, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP15_1_0, CAN1_TX_D, SEL_CAN1_3),
PINMUX_IPSR_DATA(IP15_3_2, SIM0_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP15_3_2, IECLK, SEL_IEB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_3_2, CAN_CLK_C, SEL_CANCLK_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_4, SIM0_D, SEL_SIM_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_4, IERX, SEL_IEB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_5_4, CAN1_RX_D, SEL_CAN1_3),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, GPS_CLK, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, DU1_DOTCLKIN_C, SEL_DIS_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, AUDIO_CLKB_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP15_3_2, IECLK, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP15_3_2, CAN_CLK_C, SEL_CANCLK_2),
+ PINMUX_IPSR_MSEL(IP15_5_4, SIM0_D, SEL_SIM_0),
+ PINMUX_IPSR_MSEL(IP15_5_4, IERX, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP15_5_4, CAN1_RX_D, SEL_CAN1_3),
+ PINMUX_IPSR_MSEL(IP15_8_6, GPS_CLK, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP15_8_6, DU1_DOTCLKIN_C, SEL_DIS_2),
+ PINMUX_IPSR_MSEL(IP15_8_6, AUDIO_CLKB_B, SEL_ADG_1),
PINMUX_IPSR_DATA(IP15_8_6, PWM5_B),
- PINMUX_IPSR_MODSEL_DATA(IP15_8_6, SCIFA3_TXD_C, SEL_SCIFA3_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_11_9, GPS_SIGN, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_11_9, TX4_C, SEL_SCIF4_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
+ PINMUX_IPSR_MSEL(IP15_8_6, SCIFA3_TXD_C, SEL_SCIFA3_2),
+ PINMUX_IPSR_MSEL(IP15_11_9, GPS_SIGN, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP15_11_9, TX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP15_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
PINMUX_IPSR_DATA(IP15_11_9, PWM5),
PINMUX_IPSR_DATA(IP15_11_9, VI1_G6_B),
- PINMUX_IPSR_MODSEL_DATA(IP15_11_9, SCIFA3_RXD_C, SEL_SCIFA3_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_14_12, GPS_MAG, SEL_GPS_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_14_12, RX4_C, SEL_SCIF4_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_14_12, SCIFA4_RXD_C, SEL_SCIFA4_2),
+ PINMUX_IPSR_MSEL(IP15_11_9, SCIFA3_RXD_C, SEL_SCIFA3_2),
+ PINMUX_IPSR_MSEL(IP15_14_12, GPS_MAG, SEL_GPS_0),
+ PINMUX_IPSR_MSEL(IP15_14_12, RX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP15_14_12, SCIFA4_RXD_C, SEL_SCIFA4_2),
PINMUX_IPSR_DATA(IP15_14_12, PWM6),
PINMUX_IPSR_DATA(IP15_14_12, VI1_G7_B),
- PINMUX_IPSR_MODSEL_DATA(IP15_14_12, SCIFA3_SCK_C, SEL_SCIFA3_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_17_15, HCTS0_N, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_17_15, SCIFB0_CTS_N, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_17_15, GLO_I0_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_17_15, TCLK1, SEL_TMU1_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_17_15, VI1_DATA1_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_20_18, HRTS0_N, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_20_18, SCIFB0_RTS_N, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_20_18, GLO_I1_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_20_18, VI1_DATA2_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_23_21, HSCK0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_23_21, SCIFB0_SCK, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_23_21, GLO_Q0_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_23_21, CAN_CLK, SEL_CANCLK_0),
+ PINMUX_IPSR_MSEL(IP15_14_12, SCIFA3_SCK_C, SEL_SCIFA3_2),
+ PINMUX_IPSR_MSEL(IP15_17_15, HCTS0_N, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_17_15, SCIFB0_CTS_N, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP15_17_15, GLO_I0_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP15_17_15, TCLK1, SEL_TMU1_0),
+ PINMUX_IPSR_MSEL(IP15_17_15, VI1_DATA1_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP15_20_18, HRTS0_N, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_20_18, SCIFB0_RTS_N, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP15_20_18, GLO_I1_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP15_20_18, VI1_DATA2_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP15_23_21, HSCK0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_23_21, SCIFB0_SCK, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP15_23_21, GLO_Q0_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP15_23_21, CAN_CLK, SEL_CANCLK_0),
PINMUX_IPSR_DATA(IP15_23_21, TCLK2),
- PINMUX_IPSR_MODSEL_DATA(IP15_23_21, VI1_DATA3_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_26_24, HRX0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_26_24, SCIFB0_RXD, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_26_24, GLO_Q1_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_26_24, CAN0_RX_B, SEL_CAN0_1),
- PINMUX_IPSR_MODSEL_DATA(IP15_26_24, VI1_DATA4_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_29_27, HTX0, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_29_27, SCIFB0_TXD, SEL_SCIFB_0),
- PINMUX_IPSR_MODSEL_DATA(IP15_29_27, GLO_SCLK_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP15_29_27, CAN0_TX_B, SEL_CAN0_1),
- PINMUX_IPSR_MODSEL_DATA(IP15_29_27, VI1_DATA5_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP15_23_21, VI1_DATA3_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP15_26_24, HRX0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_26_24, SCIFB0_RXD, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP15_26_24, GLO_Q1_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP15_26_24, CAN0_RX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP15_26_24, VI1_DATA4_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP15_29_27, HTX0, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP15_29_27, SCIFB0_TXD, SEL_SCIFB_0),
+ PINMUX_IPSR_MSEL(IP15_29_27, GLO_SCLK_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP15_29_27, CAN0_TX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP15_29_27, VI1_DATA5_C, SEL_VI1_2),
/* IPSR16 */
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, HRX1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, SCIFB1_RXD, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP16_2_0, HRX1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP16_2_0, SCIFB1_RXD, SEL_SCIFB1_0),
PINMUX_IPSR_DATA(IP16_2_0, VI1_R0_B),
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, GLO_SDATA_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP16_2_0, VI1_DATA6_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, HTX1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, SCIFB1_TXD, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP16_2_0, GLO_SDATA_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP16_2_0, VI1_DATA6_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP16_5_3, HTX1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP16_5_3, SCIFB1_TXD, SEL_SCIFB1_0),
PINMUX_IPSR_DATA(IP16_5_3, VI1_R1_B),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, GLO_SS_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP16_5_3, VI1_DATA7_C, SEL_VI1_2),
- PINMUX_IPSR_MODSEL_DATA(IP16_7_6, HSCK1, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP16_7_6, SCIFB1_SCK, SEL_SCIFB1_0),
+ PINMUX_IPSR_MSEL(IP16_5_3, GLO_SS_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP16_5_3, VI1_DATA7_C, SEL_VI1_2),
+ PINMUX_IPSR_MSEL(IP16_7_6, HSCK1, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP16_7_6, SCIFB1_SCK, SEL_SCIFB1_0),
PINMUX_IPSR_DATA(IP16_7_6, MLB_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP16_7_6, GLO_RFON_C, SEL_GPS_2),
- PINMUX_IPSR_MODSEL_DATA(IP16_9_8, HCTS1_N, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP16_7_6, GLO_RFON_C, SEL_GPS_2),
+ PINMUX_IPSR_MSEL(IP16_9_8, HCTS1_N, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP16_9_8, SCIFB1_CTS_N),
PINMUX_IPSR_DATA(IP16_9_8, MLB_SIG),
- PINMUX_IPSR_MODSEL_DATA(IP16_9_8, CAN1_TX_B, SEL_CAN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP16_11_10, HRTS1_N, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP16_9_8, CAN1_TX_B, SEL_CAN1_1),
+ PINMUX_IPSR_MSEL(IP16_11_10, HRTS1_N, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP16_11_10, SCIFB1_RTS_N),
PINMUX_IPSR_DATA(IP16_11_10, MLB_DAT),
- PINMUX_IPSR_MODSEL_DATA(IP16_11_10, CAN1_RX_B, SEL_CAN1_1),
+ PINMUX_IPSR_MSEL(IP16_11_10, CAN1_RX_B, SEL_CAN1_1),
};
static const struct sh_pfc_pin pinmux_pins[] = {
@@ -3986,24 +3985,6 @@ static const unsigned int usb1_mux[] = {
USB1_PWEN_MARK,
USB1_OVC_MARK,
};
-
-union vin_data {
- unsigned int data24[24];
- unsigned int data20[20];
- unsigned int data16[16];
- unsigned int data12[12];
- unsigned int data10[10];
- unsigned int data8[8];
-};
-
-#define VIN_DATA_PIN_GROUP(n, s) \
- { \
- .name = #n#s, \
- .pins = n##_pins.data##s, \
- .mux = n##_mux.data##s, \
- .nr_pins = ARRAY_SIZE(n##_pins.data##s), \
- }
-
/* - VIN0 ------------------------------------------------------------------- */
static const union vin_data vin0_data_pins = {
.data24 = {
@@ -6337,8 +6318,8 @@ const struct sh_pfc_soc_info r8a7791_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
#endif
@@ -6358,7 +6339,7 @@ const struct sh_pfc_soc_info r8a7793_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
#endif
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
index 5248685dbb4e..086f6798b129 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
@@ -11,7 +11,6 @@
*/
#include <linux/kernel.h>
-#include <linux/platform_data/gpio-rcar.h>
#include "core.h"
#include "sh_pfc.h"
@@ -644,10 +643,10 @@ static const u16 pinmux_data[] = {
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_0, SD1_CD),
- PINMUX_IPSR_MODSEL_DATA(IP0_0, CAN0_RX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP0_0, CAN0_RX, SEL_CAN0_0),
PINMUX_IPSR_DATA(IP0_9_8, SD1_WP),
PINMUX_IPSR_DATA(IP0_9_8, IRQ7),
- PINMUX_IPSR_MODSEL_DATA(IP0_9_8, CAN0_TX, SEL_CAN0_0),
+ PINMUX_IPSR_MSEL(IP0_9_8, CAN0_TX, SEL_CAN0_0),
PINMUX_IPSR_DATA(IP0_10, MMC_CLK),
PINMUX_IPSR_DATA(IP0_10, SD2_CLK),
PINMUX_IPSR_DATA(IP0_11, MMC_CMD),
@@ -665,68 +664,68 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP0_17, MMC_D5),
PINMUX_IPSR_DATA(IP0_17, SD2_WP),
PINMUX_IPSR_DATA(IP0_19_18, MMC_D6),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_18, SCIF0_RXD, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_18, I2C2_SCL_B, SEL_I2C02_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_18, CAN1_RX, SEL_CAN1_0),
+ PINMUX_IPSR_MSEL(IP0_19_18, SCIF0_RXD, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP0_19_18, I2C2_SCL_B, SEL_I2C02_1),
+ PINMUX_IPSR_MSEL(IP0_19_18, CAN1_RX, SEL_CAN1_0),
PINMUX_IPSR_DATA(IP0_21_20, MMC_D7),
- PINMUX_IPSR_MODSEL_DATA(IP0_21_20, SCIF0_TXD, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_21_20, I2C2_SDA_B, SEL_I2C02_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_21_20, CAN1_TX, SEL_CAN1_0),
+ PINMUX_IPSR_MSEL(IP0_21_20, SCIF0_TXD, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP0_21_20, I2C2_SDA_B, SEL_I2C02_1),
+ PINMUX_IPSR_MSEL(IP0_21_20, CAN1_TX, SEL_CAN1_0),
PINMUX_IPSR_DATA(IP0_23_22, D0),
- PINMUX_IPSR_MODSEL_DATA(IP0_23_22, SCIFA3_SCK_B, SEL_SCIFA3_1),
+ PINMUX_IPSR_MSEL(IP0_23_22, SCIFA3_SCK_B, SEL_SCIFA3_1),
PINMUX_IPSR_DATA(IP0_23_22, IRQ4),
PINMUX_IPSR_DATA(IP0_24, D1),
- PINMUX_IPSR_MODSEL_DATA(IP0_24, SCIFA3_RXD_B, SEL_SCIFA3_1),
+ PINMUX_IPSR_MSEL(IP0_24, SCIFA3_RXD_B, SEL_SCIFA3_1),
PINMUX_IPSR_DATA(IP0_25, D2),
- PINMUX_IPSR_MODSEL_DATA(IP0_25, SCIFA3_TXD_B, SEL_SCIFA3_1),
+ PINMUX_IPSR_MSEL(IP0_25, SCIFA3_TXD_B, SEL_SCIFA3_1),
PINMUX_IPSR_DATA(IP0_27_26, D3),
- PINMUX_IPSR_MODSEL_DATA(IP0_27_26, I2C3_SCL_B, SEL_I2C03_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_27_26, SCIF5_RXD_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP0_27_26, I2C3_SCL_B, SEL_I2C03_1),
+ PINMUX_IPSR_MSEL(IP0_27_26, SCIF5_RXD_B, SEL_SCIF5_1),
PINMUX_IPSR_DATA(IP0_29_28, D4),
- PINMUX_IPSR_MODSEL_DATA(IP0_29_28, I2C3_SDA_B, SEL_I2C03_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_29_28, SCIF5_TXD_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP0_29_28, I2C3_SDA_B, SEL_I2C03_1),
+ PINMUX_IPSR_MSEL(IP0_29_28, SCIF5_TXD_B, SEL_SCIF5_1),
PINMUX_IPSR_DATA(IP0_31_30, D5),
- PINMUX_IPSR_MODSEL_DATA(IP0_31_30, SCIF4_RXD_B, SEL_SCIF4_1),
- PINMUX_IPSR_MODSEL_DATA(IP0_31_30, I2C0_SCL_D, SEL_I2C00_3),
+ PINMUX_IPSR_MSEL(IP0_31_30, SCIF4_RXD_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP0_31_30, I2C0_SCL_D, SEL_I2C00_3),
/* IPSR1 */
PINMUX_IPSR_DATA(IP1_1_0, D6),
- PINMUX_IPSR_MODSEL_DATA(IP1_1_0, SCIF4_TXD_B, SEL_SCIF4_1),
- PINMUX_IPSR_MODSEL_DATA(IP1_1_0, I2C0_SDA_D, SEL_I2C00_3),
+ PINMUX_IPSR_MSEL(IP1_1_0, SCIF4_TXD_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP1_1_0, I2C0_SDA_D, SEL_I2C00_3),
PINMUX_IPSR_DATA(IP1_3_2, D7),
PINMUX_IPSR_DATA(IP1_3_2, IRQ3),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_2, TCLK1, SEL_TMU_0),
+ PINMUX_IPSR_MSEL(IP1_3_2, TCLK1, SEL_TMU_0),
PINMUX_IPSR_DATA(IP1_3_2, PWM6_B),
PINMUX_IPSR_DATA(IP1_5_4, D8),
PINMUX_IPSR_DATA(IP1_5_4, HSCIF2_HRX),
- PINMUX_IPSR_MODSEL_DATA(IP1_5_4, I2C1_SCL_B, SEL_I2C01_1),
+ PINMUX_IPSR_MSEL(IP1_5_4, I2C1_SCL_B, SEL_I2C01_1),
PINMUX_IPSR_DATA(IP1_7_6, D9),
PINMUX_IPSR_DATA(IP1_7_6, HSCIF2_HTX),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_6, I2C1_SDA_B, SEL_I2C01_1),
+ PINMUX_IPSR_MSEL(IP1_7_6, I2C1_SDA_B, SEL_I2C01_1),
PINMUX_IPSR_DATA(IP1_10_8, D10),
PINMUX_IPSR_DATA(IP1_10_8, HSCIF2_HSCK),
- PINMUX_IPSR_MODSEL_DATA(IP1_10_8, SCIF1_SCK_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP1_10_8, SCIF1_SCK_C, SEL_SCIF1_2),
PINMUX_IPSR_DATA(IP1_10_8, IRQ6),
PINMUX_IPSR_DATA(IP1_10_8, PWM5_C),
PINMUX_IPSR_DATA(IP1_12_11, D11),
PINMUX_IPSR_DATA(IP1_12_11, HSCIF2_HCTS_N),
- PINMUX_IPSR_MODSEL_DATA(IP1_12_11, SCIF1_RXD_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_12_11, I2C1_SCL_D, SEL_I2C01_3),
+ PINMUX_IPSR_MSEL(IP1_12_11, SCIF1_RXD_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP1_12_11, I2C1_SCL_D, SEL_I2C01_3),
PINMUX_IPSR_DATA(IP1_14_13, D12),
PINMUX_IPSR_DATA(IP1_14_13, HSCIF2_HRTS_N),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_13, SCIF1_TXD_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP1_14_13, I2C1_SDA_D, SEL_I2C01_3),
+ PINMUX_IPSR_MSEL(IP1_14_13, SCIF1_TXD_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP1_14_13, I2C1_SDA_D, SEL_I2C01_3),
PINMUX_IPSR_DATA(IP1_17_15, D13),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_15, SCIFA1_SCK, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP1_17_15, SCIFA1_SCK, SEL_SCIFA1_0),
PINMUX_IPSR_DATA(IP1_17_15, TANS1),
PINMUX_IPSR_DATA(IP1_17_15, PWM2_C),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_15, TCLK2_B, SEL_TMU_1),
+ PINMUX_IPSR_MSEL(IP1_17_15, TCLK2_B, SEL_TMU_1),
PINMUX_IPSR_DATA(IP1_19_18, D14),
- PINMUX_IPSR_MODSEL_DATA(IP1_19_18, SCIFA1_RXD, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_19_18, IIC0_SCL_B, SEL_IIC00_1),
+ PINMUX_IPSR_MSEL(IP1_19_18, SCIFA1_RXD, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP1_19_18, IIC0_SCL_B, SEL_IIC00_1),
PINMUX_IPSR_DATA(IP1_21_20, D15),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_20, SCIFA1_TXD, SEL_SCIFA1_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_21_20, IIC0_SDA_B, SEL_IIC00_1),
+ PINMUX_IPSR_MSEL(IP1_21_20, SCIFA1_TXD, SEL_SCIFA1_0),
+ PINMUX_IPSR_MSEL(IP1_21_20, IIC0_SDA_B, SEL_IIC00_1),
PINMUX_IPSR_DATA(IP1_23_22, A0),
PINMUX_IPSR_DATA(IP1_23_22, SCIFB1_SCK),
PINMUX_IPSR_DATA(IP1_23_22, PWM3_B),
@@ -742,58 +741,58 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP1_29_28, TPUTO3_C),
PINMUX_IPSR_DATA(IP1_31_30, A6),
PINMUX_IPSR_DATA(IP1_31_30, SCIFB0_CTS_N),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_30, SCIFA4_RXD_B, SEL_SCIFA4_1),
+ PINMUX_IPSR_MSEL(IP1_31_30, SCIFA4_RXD_B, SEL_SCIFA4_1),
PINMUX_IPSR_DATA(IP1_31_30, TPUTO2_C),
/* IPSR2 */
PINMUX_IPSR_DATA(IP2_1_0, A7),
PINMUX_IPSR_DATA(IP2_1_0, SCIFB0_RTS_N),
- PINMUX_IPSR_MODSEL_DATA(IP2_1_0, SCIFA4_TXD_B, SEL_SCIFA4_1),
+ PINMUX_IPSR_MSEL(IP2_1_0, SCIFA4_TXD_B, SEL_SCIFA4_1),
PINMUX_IPSR_DATA(IP2_3_2, A8),
- PINMUX_IPSR_MODSEL_DATA(IP2_3_2, MSIOF1_RXD, SEL_MSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_3_2, SCIFA0_RXD_B, SEL_SCIFA0_1),
+ PINMUX_IPSR_MSEL(IP2_3_2, MSIOF1_RXD, SEL_MSI1_0),
+ PINMUX_IPSR_MSEL(IP2_3_2, SCIFA0_RXD_B, SEL_SCIFA0_1),
PINMUX_IPSR_DATA(IP2_5_4, A9),
- PINMUX_IPSR_MODSEL_DATA(IP2_5_4, MSIOF1_TXD, SEL_MSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_5_4, SCIFA0_TXD_B, SEL_SCIFA0_1),
+ PINMUX_IPSR_MSEL(IP2_5_4, MSIOF1_TXD, SEL_MSI1_0),
+ PINMUX_IPSR_MSEL(IP2_5_4, SCIFA0_TXD_B, SEL_SCIFA0_1),
PINMUX_IPSR_DATA(IP2_7_6, A10),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_6, MSIOF1_SCK, SEL_MSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_6, IIC1_SCL_B, SEL_IIC01_1),
+ PINMUX_IPSR_MSEL(IP2_7_6, MSIOF1_SCK, SEL_MSI1_0),
+ PINMUX_IPSR_MSEL(IP2_7_6, IIC1_SCL_B, SEL_IIC01_1),
PINMUX_IPSR_DATA(IP2_9_8, A11),
- PINMUX_IPSR_MODSEL_DATA(IP2_9_8, MSIOF1_SYNC, SEL_MSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_9_8, IIC1_SDA_B, SEL_IIC01_1),
+ PINMUX_IPSR_MSEL(IP2_9_8, MSIOF1_SYNC, SEL_MSI1_0),
+ PINMUX_IPSR_MSEL(IP2_9_8, IIC1_SDA_B, SEL_IIC01_1),
PINMUX_IPSR_DATA(IP2_11_10, A12),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_10, MSIOF1_SS1, SEL_MSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_11_10, SCIFA5_RXD_B, SEL_SCIFA5_1),
+ PINMUX_IPSR_MSEL(IP2_11_10, MSIOF1_SS1, SEL_MSI1_0),
+ PINMUX_IPSR_MSEL(IP2_11_10, SCIFA5_RXD_B, SEL_SCIFA5_1),
PINMUX_IPSR_DATA(IP2_13_12, A13),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_12, MSIOF1_SS2, SEL_MSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_12, SCIFA5_TXD_B, SEL_SCIFA5_1),
+ PINMUX_IPSR_MSEL(IP2_13_12, MSIOF1_SS2, SEL_MSI1_0),
+ PINMUX_IPSR_MSEL(IP2_13_12, SCIFA5_TXD_B, SEL_SCIFA5_1),
PINMUX_IPSR_DATA(IP2_15_14, A14),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_14, MSIOF2_RXD, SEL_MSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_14, HSCIF0_HRX_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_15_14, DREQ1_N, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_15_14, MSIOF2_RXD, SEL_MSI2_0),
+ PINMUX_IPSR_MSEL(IP2_15_14, HSCIF0_HRX_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP2_15_14, DREQ1_N, SEL_LBS_0),
PINMUX_IPSR_DATA(IP2_17_16, A15),
- PINMUX_IPSR_MODSEL_DATA(IP2_17_16, MSIOF2_TXD, SEL_MSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_17_16, HSCIF0_HTX_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_17_16, DACK1, SEL_LBS_0),
+ PINMUX_IPSR_MSEL(IP2_17_16, MSIOF2_TXD, SEL_MSI2_0),
+ PINMUX_IPSR_MSEL(IP2_17_16, HSCIF0_HTX_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP2_17_16, DACK1, SEL_LBS_0),
PINMUX_IPSR_DATA(IP2_20_18, A16),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_18, MSIOF2_SCK, SEL_MSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_18, HSCIF0_HSCK_B, SEL_HSCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_18, SPEEDIN, SEL_RSP_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_18, VSP, SEL_SPDM_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_20_18, CAN_CLK_C, SEL_CAN_2),
+ PINMUX_IPSR_MSEL(IP2_20_18, MSIOF2_SCK, SEL_MSI2_0),
+ PINMUX_IPSR_MSEL(IP2_20_18, HSCIF0_HSCK_B, SEL_HSCIF0_1),
+ PINMUX_IPSR_MSEL(IP2_20_18, SPEEDIN, SEL_RSP_0),
+ PINMUX_IPSR_MSEL(IP2_20_18, VSP, SEL_SPDM_0),
+ PINMUX_IPSR_MSEL(IP2_20_18, CAN_CLK_C, SEL_CAN_2),
PINMUX_IPSR_DATA(IP2_20_18, TPUTO2_B),
PINMUX_IPSR_DATA(IP2_23_21, A17),
- PINMUX_IPSR_MODSEL_DATA(IP2_23_21, MSIOF2_SYNC, SEL_MSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_23_21, SCIF4_RXD_E, SEL_SCIF4_4),
- PINMUX_IPSR_MODSEL_DATA(IP2_23_21, CAN1_RX_B, SEL_CAN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_23_21, AVB_AVTP_CAPTURE_B, SEL_AVB_1),
+ PINMUX_IPSR_MSEL(IP2_23_21, MSIOF2_SYNC, SEL_MSI2_0),
+ PINMUX_IPSR_MSEL(IP2_23_21, SCIF4_RXD_E, SEL_SCIF4_4),
+ PINMUX_IPSR_MSEL(IP2_23_21, CAN1_RX_B, SEL_CAN1_1),
+ PINMUX_IPSR_MSEL(IP2_23_21, AVB_AVTP_CAPTURE_B, SEL_AVB_1),
PINMUX_IPSR_DATA(IP2_26_24, A18),
- PINMUX_IPSR_MODSEL_DATA(IP2_26_24, MSIOF2_SS1, SEL_MSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_26_24, SCIF4_TXD_E, SEL_SCIF4_4),
- PINMUX_IPSR_MODSEL_DATA(IP2_26_24, CAN1_TX_B, SEL_CAN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_26_24, AVB_AVTP_MATCH_B, SEL_AVB_1),
+ PINMUX_IPSR_MSEL(IP2_26_24, MSIOF2_SS1, SEL_MSI2_0),
+ PINMUX_IPSR_MSEL(IP2_26_24, SCIF4_TXD_E, SEL_SCIF4_4),
+ PINMUX_IPSR_MSEL(IP2_26_24, CAN1_TX_B, SEL_CAN1_1),
+ PINMUX_IPSR_MSEL(IP2_26_24, AVB_AVTP_MATCH_B, SEL_AVB_1),
PINMUX_IPSR_DATA(IP2_29_27, A19),
- PINMUX_IPSR_MODSEL_DATA(IP2_29_27, MSIOF2_SS2, SEL_MSI2_0),
+ PINMUX_IPSR_MSEL(IP2_29_27, MSIOF2_SS2, SEL_MSI2_0),
PINMUX_IPSR_DATA(IP2_29_27, PWM4),
PINMUX_IPSR_DATA(IP2_29_27, TPUTO2),
PINMUX_IPSR_DATA(IP2_29_27, MOUT0),
@@ -831,42 +830,42 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP3_14_13, VI1_DATA11),
PINMUX_IPSR_DATA(IP3_17_15, EX_CS2_N),
PINMUX_IPSR_DATA(IP3_17_15, PWM0),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, SCIF4_RXD_C, SEL_SCIF4_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, TS_SDATA_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, RIF0_SYNC, SEL_DR0_0),
+ PINMUX_IPSR_MSEL(IP3_17_15, SCIF4_RXD_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP3_17_15, TS_SDATA_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP3_17_15, RIF0_SYNC, SEL_DR0_0),
PINMUX_IPSR_DATA(IP3_17_15, TPUTO3),
PINMUX_IPSR_DATA(IP3_17_15, SCIFB2_TXD),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, SDATA_B, SEL_FSN_1),
+ PINMUX_IPSR_MSEL(IP3_17_15, SDATA_B, SEL_FSN_1),
PINMUX_IPSR_DATA(IP3_20_18, EX_CS3_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_20_18, SCIFA2_SCK, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_20_18, SCIF4_TXD_C, SEL_SCIF4_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_20_18, TS_SCK_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_20_18, RIF0_CLK, SEL_DR0_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_20_18, BPFCLK, SEL_DARC_0),
+ PINMUX_IPSR_MSEL(IP3_20_18, SCIFA2_SCK, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP3_20_18, SCIF4_TXD_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP3_20_18, TS_SCK_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP3_20_18, RIF0_CLK, SEL_DR0_0),
+ PINMUX_IPSR_MSEL(IP3_20_18, BPFCLK, SEL_DARC_0),
PINMUX_IPSR_DATA(IP3_20_18, SCIFB2_SCK),
- PINMUX_IPSR_MODSEL_DATA(IP3_20_18, MDATA_B, SEL_FSN_1),
+ PINMUX_IPSR_MSEL(IP3_20_18, MDATA_B, SEL_FSN_1),
PINMUX_IPSR_DATA(IP3_23_21, EX_CS4_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, SCIFA2_RXD, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, I2C2_SCL_E, SEL_I2C02_4),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, TS_SDEN_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, RIF0_D0, SEL_DR0_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, FMCLK, SEL_DARC_0),
+ PINMUX_IPSR_MSEL(IP3_23_21, SCIFA2_RXD, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP3_23_21, I2C2_SCL_E, SEL_I2C02_4),
+ PINMUX_IPSR_MSEL(IP3_23_21, TS_SDEN_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP3_23_21, RIF0_D0, SEL_DR0_0),
+ PINMUX_IPSR_MSEL(IP3_23_21, FMCLK, SEL_DARC_0),
PINMUX_IPSR_DATA(IP3_23_21, SCIFB2_CTS_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, SCKZ_B, SEL_FSN_1),
+ PINMUX_IPSR_MSEL(IP3_23_21, SCKZ_B, SEL_FSN_1),
PINMUX_IPSR_DATA(IP3_26_24, EX_CS5_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, SCIFA2_TXD, SEL_SCIFA2_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, I2C2_SDA_E, SEL_I2C02_4),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, TS_SPSYNC_B, SEL_TSIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, RIF0_D1, SEL_DR1_0),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, FMIN, SEL_DARC_0),
+ PINMUX_IPSR_MSEL(IP3_26_24, SCIFA2_TXD, SEL_SCIFA2_0),
+ PINMUX_IPSR_MSEL(IP3_26_24, I2C2_SDA_E, SEL_I2C02_4),
+ PINMUX_IPSR_MSEL(IP3_26_24, TS_SPSYNC_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP3_26_24, RIF0_D1, SEL_DR1_0),
+ PINMUX_IPSR_MSEL(IP3_26_24, FMIN, SEL_DARC_0),
PINMUX_IPSR_DATA(IP3_26_24, SCIFB2_RTS_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, STM_N_B, SEL_FSN_1),
+ PINMUX_IPSR_MSEL(IP3_26_24, STM_N_B, SEL_FSN_1),
PINMUX_IPSR_DATA(IP3_29_27, BS_N),
PINMUX_IPSR_DATA(IP3_29_27, DRACK0),
PINMUX_IPSR_DATA(IP3_29_27, PWM1_C),
PINMUX_IPSR_DATA(IP3_29_27, TPUTO0_C),
PINMUX_IPSR_DATA(IP3_29_27, ATACS01_N),
- PINMUX_IPSR_MODSEL_DATA(IP3_29_27, MTS_N_B, SEL_FSN_1),
+ PINMUX_IPSR_MSEL(IP3_29_27, MTS_N_B, SEL_FSN_1),
PINMUX_IPSR_DATA(IP3_30, RD_N),
PINMUX_IPSR_DATA(IP3_30, ATACS11_N),
PINMUX_IPSR_DATA(IP3_31, RD_WR_N),
@@ -874,18 +873,18 @@ static const u16 pinmux_data[] = {
/* IPSR4 */
PINMUX_IPSR_DATA(IP4_1_0, EX_WAIT0),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, CAN_CLK_B, SEL_CAN_1),
- PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SCIF_CLK, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP4_1_0, CAN_CLK_B, SEL_CAN_1),
+ PINMUX_IPSR_MSEL(IP4_1_0, SCIF_CLK, SEL_SCIF0_0),
PINMUX_IPSR_DATA(IP4_1_0, PWMFSW0),
PINMUX_IPSR_DATA(IP4_4_2, DU0_DR0),
PINMUX_IPSR_DATA(IP4_4_2, LCDOUT16),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SCIF5_RXD_C, SEL_SCIF5_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_4_2, I2C2_SCL_D, SEL_I2C02_3),
+ PINMUX_IPSR_MSEL(IP4_4_2, SCIF5_RXD_C, SEL_SCIF5_2),
+ PINMUX_IPSR_MSEL(IP4_4_2, I2C2_SCL_D, SEL_I2C02_3),
PINMUX_IPSR_DATA(IP4_4_2, CC50_STATE0),
PINMUX_IPSR_DATA(IP4_7_5, DU0_DR1),
PINMUX_IPSR_DATA(IP4_7_5, LCDOUT17),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SCIF5_TXD_C, SEL_SCIF5_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_7_5, I2C2_SDA_D, SEL_I2C02_3),
+ PINMUX_IPSR_MSEL(IP4_7_5, SCIF5_TXD_C, SEL_SCIF5_2),
+ PINMUX_IPSR_MSEL(IP4_7_5, I2C2_SDA_D, SEL_I2C02_3),
PINMUX_IPSR_DATA(IP4_9_8, CC50_STATE1),
PINMUX_IPSR_DATA(IP4_9_8, DU0_DR2),
PINMUX_IPSR_DATA(IP4_9_8, LCDOUT18),
@@ -907,13 +906,13 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP4_19_18, CC50_STATE7),
PINMUX_IPSR_DATA(IP4_22_20, DU0_DG0),
PINMUX_IPSR_DATA(IP4_22_20, LCDOUT8),
- PINMUX_IPSR_MODSEL_DATA(IP4_22_20, SCIFA0_RXD_C, SEL_SCIFA0_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_22_20, I2C3_SCL_D, SEL_I2C03_3),
+ PINMUX_IPSR_MSEL(IP4_22_20, SCIFA0_RXD_C, SEL_SCIFA0_2),
+ PINMUX_IPSR_MSEL(IP4_22_20, I2C3_SCL_D, SEL_I2C03_3),
PINMUX_IPSR_DATA(IP4_22_20, CC50_STATE8),
PINMUX_IPSR_DATA(IP4_25_23, DU0_DG1),
PINMUX_IPSR_DATA(IP4_25_23, LCDOUT9),
- PINMUX_IPSR_MODSEL_DATA(IP4_25_23, SCIFA0_TXD_C, SEL_SCIFA0_2),
- PINMUX_IPSR_MODSEL_DATA(IP4_25_23, I2C3_SDA_D, SEL_I2C03_3),
+ PINMUX_IPSR_MSEL(IP4_25_23, SCIFA0_TXD_C, SEL_SCIFA0_2),
+ PINMUX_IPSR_MSEL(IP4_25_23, I2C3_SDA_D, SEL_I2C03_3),
PINMUX_IPSR_DATA(IP4_25_23, CC50_STATE9),
PINMUX_IPSR_DATA(IP4_27_26, DU0_DG2),
PINMUX_IPSR_DATA(IP4_27_26, LCDOUT10),
@@ -937,15 +936,15 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP5_5_4, CC50_STATE15),
PINMUX_IPSR_DATA(IP5_8_6, DU0_DB0),
PINMUX_IPSR_DATA(IP5_8_6, LCDOUT0),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, SCIFA4_RXD_C, SEL_SCIFA4_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, I2C4_SCL_D, SEL_I2C04_3),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, CAN0_RX_C, SEL_CAN0_2),
+ PINMUX_IPSR_MSEL(IP5_8_6, SCIFA4_RXD_C, SEL_SCIFA4_2),
+ PINMUX_IPSR_MSEL(IP5_8_6, I2C4_SCL_D, SEL_I2C04_3),
+ PINMUX_IPSR_MSEL(IP7_8_6, CAN0_RX_C, SEL_CAN0_2),
PINMUX_IPSR_DATA(IP5_8_6, CC50_STATE16),
PINMUX_IPSR_DATA(IP5_11_9, DU0_DB1),
PINMUX_IPSR_DATA(IP5_11_9, LCDOUT1),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, I2C4_SDA_D, SEL_I2C04_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, CAN0_TX_C, SEL_CAN0_2),
+ PINMUX_IPSR_MSEL(IP5_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
+ PINMUX_IPSR_MSEL(IP5_11_9, I2C4_SDA_D, SEL_I2C04_3),
+ PINMUX_IPSR_MSEL(IP5_11_9, CAN0_TX_C, SEL_CAN0_2),
PINMUX_IPSR_DATA(IP5_11_9, CC50_STATE17),
PINMUX_IPSR_DATA(IP5_13_12, DU0_DB2),
PINMUX_IPSR_DATA(IP5_13_12, LCDOUT2),
@@ -1010,501 +1009,501 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP6_16, VI0_DATA7_VI0_B7),
PINMUX_IPSR_DATA(IP6_16, AVB_RXD6),
PINMUX_IPSR_DATA(IP6_19_17, VI0_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, I2C3_SCL, SEL_I2C03_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, SCIFA5_RXD_C, SEL_SCIFA5_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_19_17, IETX_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP6_19_17, I2C3_SCL, SEL_I2C03_0),
+ PINMUX_IPSR_MSEL(IP6_19_17, SCIFA5_RXD_C, SEL_SCIFA5_2),
+ PINMUX_IPSR_MSEL(IP6_19_17, IETX_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP6_19_17, AVB_RXD7),
PINMUX_IPSR_DATA(IP6_22_20, VI0_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, I2C3_SDA, SEL_I2C03_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCIFA5_TXD_C, SEL_SCIFA5_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_22_20, IECLK_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP6_22_20, I2C3_SDA, SEL_I2C03_0),
+ PINMUX_IPSR_MSEL(IP6_22_20, SCIFA5_TXD_C, SEL_SCIFA5_2),
+ PINMUX_IPSR_MSEL(IP6_22_20, IECLK_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP6_22_20, AVB_RX_ER),
PINMUX_IPSR_DATA(IP6_25_23, VI0_HSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, SCIF0_RXD_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, I2C0_SCL_C, SEL_I2C00_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_25_23, IERX_C, SEL_IEB_2),
+ PINMUX_IPSR_MSEL(IP6_25_23, SCIF0_RXD_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_25_23, I2C0_SCL_C, SEL_I2C00_2),
+ PINMUX_IPSR_MSEL(IP6_25_23, IERX_C, SEL_IEB_2),
PINMUX_IPSR_DATA(IP6_25_23, AVB_COL),
PINMUX_IPSR_DATA(IP6_28_26, VI0_VSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, SCIF0_TXD_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, I2C0_SDA_C, SEL_I2C00_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_28_26, AUDIO_CLKOUT_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP6_28_26, SCIF0_TXD_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_28_26, I2C0_SDA_C, SEL_I2C00_2),
+ PINMUX_IPSR_MSEL(IP6_28_26, AUDIO_CLKOUT_B, SEL_ADG_1),
PINMUX_IPSR_DATA(IP6_28_26, AVB_TX_EN),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, ETH_MDIO, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP6_31_29, ETH_MDIO, SEL_ETH_0),
PINMUX_IPSR_DATA(IP6_31_29, VI0_G0),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, MSIOF2_RXD_B, SEL_MSI2_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, IIC0_SCL_D, SEL_IIC00_3),
+ PINMUX_IPSR_MSEL(IP6_31_29, MSIOF2_RXD_B, SEL_MSI2_1),
+ PINMUX_IPSR_MSEL(IP6_31_29, IIC0_SCL_D, SEL_IIC00_3),
PINMUX_IPSR_DATA(IP6_31_29, AVB_TX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, ADIDATA, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_31_29, AD_DI, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP6_31_29, ADIDATA, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP6_31_29, AD_DI, SEL_ADI_0),
/* IPSR7 */
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, ETH_CRS_DV, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_2_0, ETH_CRS_DV, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_2_0, VI0_G1),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, MSIOF2_TXD_B, SEL_MSI2_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, IIC0_SDA_D, SEL_IIC00_3),
+ PINMUX_IPSR_MSEL(IP7_2_0, MSIOF2_TXD_B, SEL_MSI2_1),
+ PINMUX_IPSR_MSEL(IP7_2_0, IIC0_SDA_D, SEL_IIC00_3),
PINMUX_IPSR_DATA(IP7_2_0, AVB_TXD0),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, ADICS_SAMP, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, AD_DO, SEL_ADI_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, ETH_RX_ER, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_2_0, ADICS_SAMP, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP7_2_0, AD_DO, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP7_5_3, ETH_RX_ER, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_5_3, VI0_G2),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, MSIOF2_SCK_B, SEL_MSI2_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, CAN0_RX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, MSIOF2_SCK_B, SEL_MSI2_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, CAN0_RX_B, SEL_CAN0_1),
PINMUX_IPSR_DATA(IP7_5_3, AVB_TXD1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, ADICLK, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, AD_CLK, SEL_ADI_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, ETH_RXD0, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_5_3, ADICLK, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP7_5_3, AD_CLK, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP7_8_6, ETH_RXD0, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_8_6, VI0_G3),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, MSIOF2_SYNC_B, SEL_MSI2_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, CAN0_TX_B, SEL_CAN0_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, MSIOF2_SYNC_B, SEL_MSI2_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, CAN0_TX_B, SEL_CAN0_1),
PINMUX_IPSR_DATA(IP7_8_6, AVB_TXD2),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, ADICHS0, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, AD_NCS_N, SEL_ADI_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, ETH_RXD1, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_8_6, ADICHS0, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP7_8_6, AD_NCS_N, SEL_ADI_0),
+ PINMUX_IPSR_MSEL(IP7_11_9, ETH_RXD1, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_11_9, VI0_G4),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, MSIOF2_SS1_B, SEL_MSI2_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, SCIF4_RXD_D, SEL_SCIF4_3),
+ PINMUX_IPSR_MSEL(IP7_11_9, MSIOF2_SS1_B, SEL_MSI2_1),
+ PINMUX_IPSR_MSEL(IP7_11_9, SCIF4_RXD_D, SEL_SCIF4_3),
PINMUX_IPSR_DATA(IP7_11_9, AVB_TXD3),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, ADICHS1, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, ETH_LINK, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_11_9, ADICHS1, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP7_14_12, ETH_LINK, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_14_12, VI0_G5),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, MSIOF2_SS2_B, SEL_MSI2_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, SCIF4_TXD_D, SEL_SCIF4_3),
+ PINMUX_IPSR_MSEL(IP7_14_12, MSIOF2_SS2_B, SEL_MSI2_1),
+ PINMUX_IPSR_MSEL(IP7_14_12, SCIF4_TXD_D, SEL_SCIF4_3),
PINMUX_IPSR_DATA(IP7_14_12, AVB_TXD4),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, ADICHS2, SEL_RAD_0),
- PINMUX_IPSR_MODSEL_DATA(IP7_17_15, ETH_REFCLK, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_14_12, ADICHS2, SEL_RAD_0),
+ PINMUX_IPSR_MSEL(IP7_17_15, ETH_REFCLK, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_17_15, VI0_G6),
- PINMUX_IPSR_MODSEL_DATA(IP7_17_15, SCIF2_SCK_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP7_17_15, SCIF2_SCK_C, SEL_SCIF2_2),
PINMUX_IPSR_DATA(IP7_17_15, AVB_TXD5),
- PINMUX_IPSR_MODSEL_DATA(IP7_17_15, SSI_SCK5_B, SEL_SSI5_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, ETH_TXD1, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_17_15, SSI_SCK5_B, SEL_SSI5_1),
+ PINMUX_IPSR_MSEL(IP7_20_18, ETH_TXD1, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_20_18, VI0_G7),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, SCIF2_RXD_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, IIC1_SCL_D, SEL_IIC01_3),
+ PINMUX_IPSR_MSEL(IP7_20_18, SCIF2_RXD_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP7_20_18, IIC1_SCL_D, SEL_IIC01_3),
PINMUX_IPSR_DATA(IP7_20_18, AVB_TXD6),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, SSI_WS5_B, SEL_SSI5_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, ETH_TX_EN, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_20_18, SSI_WS5_B, SEL_SSI5_1),
+ PINMUX_IPSR_MSEL(IP7_23_21, ETH_TX_EN, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_23_21, VI0_R0),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, SCIF2_TXD_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, IIC1_SDA_D, SEL_IIC01_3),
+ PINMUX_IPSR_MSEL(IP7_23_21, SCIF2_TXD_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP7_23_21, IIC1_SDA_D, SEL_IIC01_3),
PINMUX_IPSR_DATA(IP7_23_21, AVB_TXD7),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, SSI_SDATA5_B, SEL_SSI5_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, ETH_MAGIC, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_23_21, SSI_SDATA5_B, SEL_SSI5_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, ETH_MAGIC, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_26_24, VI0_R1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, SCIF3_SCK_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, SCIF3_SCK_B, SEL_SCIF3_1),
PINMUX_IPSR_DATA(IP7_26_24, AVB_TX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, SSI_SCK6_B, SEL_SSI6_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, ETH_TXD0, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP7_26_24, SSI_SCK6_B, SEL_SSI6_1),
+ PINMUX_IPSR_MSEL(IP7_29_27, ETH_TXD0, SEL_ETH_0),
PINMUX_IPSR_DATA(IP7_29_27, VI0_R2),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, SCIF3_RXD_B, SEL_SCIF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, I2C4_SCL_E, SEL_I2C04_4),
+ PINMUX_IPSR_MSEL(IP7_29_27, SCIF3_RXD_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP7_29_27, I2C4_SCL_E, SEL_I2C04_4),
PINMUX_IPSR_DATA(IP7_29_27, AVB_GTX_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP7_29_27, SSI_WS6_B, SEL_SSI6_1),
+ PINMUX_IPSR_MSEL(IP7_29_27, SSI_WS6_B, SEL_SSI6_1),
PINMUX_IPSR_DATA(IP7_31, DREQ0_N),
PINMUX_IPSR_DATA(IP7_31, SCIFB1_RXD),
/* IPSR8 */
- PINMUX_IPSR_MODSEL_DATA(IP8_2_0, ETH_MDC, SEL_ETH_0),
+ PINMUX_IPSR_MSEL(IP8_2_0, ETH_MDC, SEL_ETH_0),
PINMUX_IPSR_DATA(IP8_2_0, VI0_R3),
- PINMUX_IPSR_MODSEL_DATA(IP8_2_0, SCIF3_TXD_B, SEL_SCIF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_2_0, I2C4_SDA_E, SEL_I2C04_4),
+ PINMUX_IPSR_MSEL(IP8_2_0, SCIF3_TXD_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP8_2_0, I2C4_SDA_E, SEL_I2C04_4),
PINMUX_IPSR_DATA(IP8_2_0, AVB_MDC),
- PINMUX_IPSR_MODSEL_DATA(IP8_2_0, SSI_SDATA6_B, SEL_SSI6_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, HSCIF0_HRX, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_2_0, SSI_SDATA6_B, SEL_SSI6_1),
+ PINMUX_IPSR_MSEL(IP8_5_3, HSCIF0_HRX, SEL_HSCIF0_0),
PINMUX_IPSR_DATA(IP8_5_3, VI0_R4),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, I2C1_SCL_C, SEL_I2C01_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, AUDIO_CLKA_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP8_5_3, I2C1_SCL_C, SEL_I2C01_2),
+ PINMUX_IPSR_MSEL(IP8_5_3, AUDIO_CLKA_B, SEL_ADG_1),
PINMUX_IPSR_DATA(IP8_5_3, AVB_MDIO),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_3, SSI_SCK78_B, SEL_SSI7_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, HSCIF0_HTX, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_5_3, SSI_SCK78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, HSCIF0_HTX, SEL_HSCIF0_0),
PINMUX_IPSR_DATA(IP8_8_6, VI0_R5),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, I2C1_SDA_C, SEL_I2C01_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, AUDIO_CLKB_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, I2C1_SDA_C, SEL_I2C01_2),
+ PINMUX_IPSR_MSEL(IP8_8_6, AUDIO_CLKB_B, SEL_ADG_1),
PINMUX_IPSR_DATA(IP8_5_3, AVB_LINK),
- PINMUX_IPSR_MODSEL_DATA(IP8_8_6, SSI_WS78_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP8_8_6, SSI_WS78_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP8_11_9, HSCIF0_HCTS_N),
PINMUX_IPSR_DATA(IP8_11_9, VI0_R6),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_9, SCIF0_RXD_D, SEL_SCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_9, I2C0_SCL_E, SEL_I2C00_4),
+ PINMUX_IPSR_MSEL(IP8_11_9, SCIF0_RXD_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP8_11_9, I2C0_SCL_E, SEL_I2C00_4),
PINMUX_IPSR_DATA(IP8_11_9, AVB_MAGIC),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_9, SSI_SDATA7_B, SEL_SSI7_1),
+ PINMUX_IPSR_MSEL(IP8_11_9, SSI_SDATA7_B, SEL_SSI7_1),
PINMUX_IPSR_DATA(IP8_14_12, HSCIF0_HRTS_N),
PINMUX_IPSR_DATA(IP8_14_12, VI0_R7),
- PINMUX_IPSR_MODSEL_DATA(IP8_14_12, SCIF0_TXD_D, SEL_SCIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP8_14_12, I2C0_SDA_E, SEL_I2C00_4),
+ PINMUX_IPSR_MSEL(IP8_14_12, SCIF0_TXD_D, SEL_SCIF0_3),
+ PINMUX_IPSR_MSEL(IP8_14_12, I2C0_SDA_E, SEL_I2C00_4),
PINMUX_IPSR_DATA(IP8_14_12, AVB_PHY_INT),
- PINMUX_IPSR_MODSEL_DATA(IP8_14_12, SSI_SDATA8_B, SEL_SSI8_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_16_15, HSCIF0_HSCK, SEL_HSCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_16_15, SCIF_CLK_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP8_14_12, SSI_SDATA8_B, SEL_SSI8_1),
+ PINMUX_IPSR_MSEL(IP8_16_15, HSCIF0_HSCK, SEL_HSCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_16_15, SCIF_CLK_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP8_16_15, AVB_CRS),
- PINMUX_IPSR_MODSEL_DATA(IP8_16_15, AUDIO_CLKC_B, SEL_ADG_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_17, I2C0_SCL, SEL_I2C00_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_17, SCIF0_RXD_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP8_16_15, AUDIO_CLKC_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP8_19_17, I2C0_SCL, SEL_I2C00_0),
+ PINMUX_IPSR_MSEL(IP8_19_17, SCIF0_RXD_C, SEL_SCIF0_2),
PINMUX_IPSR_DATA(IP8_19_17, PWM5),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_17, TCLK1_B, SEL_TMU_1),
+ PINMUX_IPSR_MSEL(IP8_19_17, TCLK1_B, SEL_TMU_1),
PINMUX_IPSR_DATA(IP8_19_17, AVB_GTXREFCLK),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_17, CAN1_RX_D, SEL_CAN1_3),
+ PINMUX_IPSR_MSEL(IP8_19_17, CAN1_RX_D, SEL_CAN1_3),
PINMUX_IPSR_DATA(IP8_19_17, TPUTO0_B),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, I2C0_SDA, SEL_I2C00_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, SCIF0_TXD_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP8_22_20, I2C0_SDA, SEL_I2C00_0),
+ PINMUX_IPSR_MSEL(IP8_22_20, SCIF0_TXD_C, SEL_SCIF0_2),
PINMUX_IPSR_DATA(IP8_22_20, TPUTO0),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, CAN_CLK, SEL_CAN_0),
+ PINMUX_IPSR_MSEL(IP8_22_20, CAN_CLK, SEL_CAN_0),
PINMUX_IPSR_DATA(IP8_22_20, DVC_MUTE),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, CAN1_TX_D, SEL_CAN1_3),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, I2C1_SCL, SEL_I2C01_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, SCIF4_RXD, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP8_22_20, CAN1_TX_D, SEL_CAN1_3),
+ PINMUX_IPSR_MSEL(IP8_25_23, I2C1_SCL, SEL_I2C01_0),
+ PINMUX_IPSR_MSEL(IP8_25_23, SCIF4_RXD, SEL_SCIF4_0),
PINMUX_IPSR_DATA(IP8_25_23, PWM5_B),
PINMUX_IPSR_DATA(IP8_25_23, DU1_DR0),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, RIF1_SYNC_B, SEL_DR2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, TS_SDATA_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP8_25_23, RIF1_SYNC_B, SEL_DR2_1),
+ PINMUX_IPSR_MSEL(IP8_25_23, TS_SDATA_D, SEL_TSIF0_3),
PINMUX_IPSR_DATA(IP8_25_23, TPUTO1_B),
- PINMUX_IPSR_MODSEL_DATA(IP8_28_26, I2C1_SDA, SEL_I2C01_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_28_26, SCIF4_TXD, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP8_28_26, I2C1_SDA, SEL_I2C01_0),
+ PINMUX_IPSR_MSEL(IP8_28_26, SCIF4_TXD, SEL_SCIF4_0),
PINMUX_IPSR_DATA(IP8_28_26, IRQ5),
PINMUX_IPSR_DATA(IP8_28_26, DU1_DR1),
- PINMUX_IPSR_MODSEL_DATA(IP8_28_26, RIF1_CLK_B, SEL_DR2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_28_26, TS_SCK_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP8_28_26, BPFCLK_C, SEL_DARC_2),
+ PINMUX_IPSR_MSEL(IP8_28_26, RIF1_CLK_B, SEL_DR2_1),
+ PINMUX_IPSR_MSEL(IP8_28_26, TS_SCK_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP8_28_26, BPFCLK_C, SEL_DARC_2),
PINMUX_IPSR_DATA(IP8_31_29, MSIOF0_RXD),
- PINMUX_IPSR_MODSEL_DATA(IP8_31_29, SCIF5_RXD, SEL_SCIF5_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_31_29, I2C2_SCL_C, SEL_I2C02_2),
+ PINMUX_IPSR_MSEL(IP8_31_29, SCIF5_RXD, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP8_31_29, I2C2_SCL_C, SEL_I2C02_2),
PINMUX_IPSR_DATA(IP8_31_29, DU1_DR2),
- PINMUX_IPSR_MODSEL_DATA(IP8_31_29, RIF1_D0_B, SEL_DR2_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_31_29, TS_SDEN_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP8_31_29, FMCLK_C, SEL_DARC_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_31_29, RDS_CLK, SEL_RDS_0),
+ PINMUX_IPSR_MSEL(IP8_31_29, RIF1_D0_B, SEL_DR2_1),
+ PINMUX_IPSR_MSEL(IP8_31_29, TS_SDEN_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP8_31_29, FMCLK_C, SEL_DARC_2),
+ PINMUX_IPSR_MSEL(IP8_31_29, RDS_CLK, SEL_RDS_0),
/* IPSR9 */
PINMUX_IPSR_DATA(IP9_2_0, MSIOF0_TXD),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, SCIF5_TXD, SEL_SCIF5_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, I2C2_SDA_C, SEL_I2C02_2),
+ PINMUX_IPSR_MSEL(IP9_2_0, SCIF5_TXD, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP9_2_0, I2C2_SDA_C, SEL_I2C02_2),
PINMUX_IPSR_DATA(IP9_2_0, DU1_DR3),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, RIF1_D1_B, SEL_DR3_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, TS_SPSYNC_D, SEL_TSIF0_3),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, FMIN_C, SEL_DARC_2),
- PINMUX_IPSR_MODSEL_DATA(IP9_2_0, RDS_DATA, SEL_RDS_0),
+ PINMUX_IPSR_MSEL(IP9_2_0, RIF1_D1_B, SEL_DR3_1),
+ PINMUX_IPSR_MSEL(IP9_2_0, TS_SPSYNC_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP9_2_0, FMIN_C, SEL_DARC_2),
+ PINMUX_IPSR_MSEL(IP9_2_0, RDS_DATA, SEL_RDS_0),
PINMUX_IPSR_DATA(IP9_5_3, MSIOF0_SCK),
PINMUX_IPSR_DATA(IP9_5_3, IRQ0),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_3, TS_SDATA, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP9_5_3, TS_SDATA, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP9_5_3, DU1_DR4),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_3, RIF1_SYNC, SEL_DR2_0),
+ PINMUX_IPSR_MSEL(IP9_5_3, RIF1_SYNC, SEL_DR2_0),
PINMUX_IPSR_DATA(IP9_5_3, TPUTO1_C),
PINMUX_IPSR_DATA(IP9_8_6, MSIOF0_SYNC),
PINMUX_IPSR_DATA(IP9_8_6, PWM1),
- PINMUX_IPSR_MODSEL_DATA(IP9_8_6, TS_SCK, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP9_8_6, TS_SCK, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP9_8_6, DU1_DR5),
- PINMUX_IPSR_MODSEL_DATA(IP9_8_6, RIF1_CLK, SEL_DR2_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_8_6, BPFCLK_B, SEL_DARC_1),
+ PINMUX_IPSR_MSEL(IP9_8_6, RIF1_CLK, SEL_DR2_0),
+ PINMUX_IPSR_MSEL(IP9_8_6, BPFCLK_B, SEL_DARC_1),
PINMUX_IPSR_DATA(IP9_11_9, MSIOF0_SS1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_9, SCIFA0_RXD, SEL_SCIFA0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_9, TS_SDEN, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP9_11_9, SCIFA0_RXD, SEL_SCIFA0_0),
+ PINMUX_IPSR_MSEL(IP9_11_9, TS_SDEN, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP9_11_9, DU1_DR6),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_9, RIF1_D0, SEL_DR2_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_9, FMCLK_B, SEL_DARC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_9, RDS_CLK_B, SEL_RDS_1),
+ PINMUX_IPSR_MSEL(IP9_11_9, RIF1_D0, SEL_DR2_0),
+ PINMUX_IPSR_MSEL(IP9_11_9, FMCLK_B, SEL_DARC_1),
+ PINMUX_IPSR_MSEL(IP9_11_9, RDS_CLK_B, SEL_RDS_1),
PINMUX_IPSR_DATA(IP9_14_12, MSIOF0_SS2),
- PINMUX_IPSR_MODSEL_DATA(IP9_14_12, SCIFA0_TXD, SEL_SCIFA0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_14_12, TS_SPSYNC, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP9_14_12, SCIFA0_TXD, SEL_SCIFA0_0),
+ PINMUX_IPSR_MSEL(IP9_14_12, TS_SPSYNC, SEL_TSIF0_0),
PINMUX_IPSR_DATA(IP9_14_12, DU1_DR7),
- PINMUX_IPSR_MODSEL_DATA(IP9_14_12, RIF1_D1, SEL_DR3_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_14_12, FMIN_B, SEL_DARC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_14_12, RDS_DATA_B, SEL_RDS_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_16_15, HSCIF1_HRX, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_16_15, I2C4_SCL, SEL_I2C04_0),
+ PINMUX_IPSR_MSEL(IP9_14_12, RIF1_D1, SEL_DR3_0),
+ PINMUX_IPSR_MSEL(IP9_14_12, FMIN_B, SEL_DARC_1),
+ PINMUX_IPSR_MSEL(IP9_14_12, RDS_DATA_B, SEL_RDS_1),
+ PINMUX_IPSR_MSEL(IP9_16_15, HSCIF1_HRX, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP9_16_15, I2C4_SCL, SEL_I2C04_0),
PINMUX_IPSR_DATA(IP9_16_15, PWM6),
PINMUX_IPSR_DATA(IP9_16_15, DU1_DG0),
- PINMUX_IPSR_MODSEL_DATA(IP9_18_17, HSCIF1_HTX, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_18_17, I2C4_SDA, SEL_I2C04_0),
+ PINMUX_IPSR_MSEL(IP9_18_17, HSCIF1_HTX, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP9_18_17, I2C4_SDA, SEL_I2C04_0),
PINMUX_IPSR_DATA(IP9_18_17, TPUTO1),
PINMUX_IPSR_DATA(IP9_18_17, DU1_DG1),
PINMUX_IPSR_DATA(IP9_21_19, HSCIF1_HSCK),
PINMUX_IPSR_DATA(IP9_21_19, PWM2),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_19, IETX, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP9_21_19, IETX, SEL_IEB_0),
PINMUX_IPSR_DATA(IP9_21_19, DU1_DG2),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_19, REMOCON_B, SEL_RCN_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_19, SPEEDIN_B, SEL_RSP_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_19, VSP_B, SEL_SPDM_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_22, HSCIF1_HCTS_N, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_22, SCIFA4_RXD, SEL_SCIFA4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_22, IECLK, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP9_21_19, REMOCON_B, SEL_RCN_1),
+ PINMUX_IPSR_MSEL(IP9_21_19, SPEEDIN_B, SEL_RSP_1),
+ PINMUX_IPSR_MSEL(IP9_21_19, VSP_B, SEL_SPDM_1),
+ PINMUX_IPSR_MSEL(IP9_24_22, HSCIF1_HCTS_N, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP9_24_22, SCIFA4_RXD, SEL_SCIFA4_0),
+ PINMUX_IPSR_MSEL(IP9_24_22, IECLK, SEL_IEB_0),
PINMUX_IPSR_DATA(IP9_24_22, DU1_DG3),
- PINMUX_IPSR_MODSEL_DATA(IP9_24_22, SSI_SCK1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP9_24_22, SSI_SCK1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP9_24_22, CAN_DEBUG_HW_TRIGGER),
PINMUX_IPSR_DATA(IP9_24_22, CC50_STATE32),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_25, HSCIF1_HRTS_N, SEL_HSCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_25, SCIFA4_TXD, SEL_SCIFA4_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_25, IERX, SEL_IEB_0),
+ PINMUX_IPSR_MSEL(IP9_27_25, HSCIF1_HRTS_N, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP9_27_25, SCIFA4_TXD, SEL_SCIFA4_0),
+ PINMUX_IPSR_MSEL(IP9_27_25, IERX, SEL_IEB_0),
PINMUX_IPSR_DATA(IP9_27_25, DU1_DG4),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_25, SSI_WS1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP9_27_25, SSI_WS1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP9_27_25, CAN_STEP0),
PINMUX_IPSR_DATA(IP9_27_25, CC50_STATE33),
- PINMUX_IPSR_MODSEL_DATA(IP9_30_28, SCIF1_SCK, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP9_30_28, SCIF1_SCK, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP9_30_28, PWM3),
- PINMUX_IPSR_MODSEL_DATA(IP9_30_28, TCLK2, SEL_TMU_0),
+ PINMUX_IPSR_MSEL(IP9_30_28, TCLK2, SEL_TMU_0),
PINMUX_IPSR_DATA(IP9_30_28, DU1_DG5),
- PINMUX_IPSR_MODSEL_DATA(IP9_30_28, SSI_SDATA1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP9_30_28, SSI_SDATA1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP9_30_28, CAN_TXCLK),
PINMUX_IPSR_DATA(IP9_30_28, CC50_STATE34),
/* IPSR10 */
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SCIF1_RXD, SEL_SCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, IIC0_SCL, SEL_IIC00_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, SCIF1_RXD, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP10_2_0, IIC0_SCL, SEL_IIC00_0),
PINMUX_IPSR_DATA(IP10_2_0, DU1_DG6),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SSI_SCK2_B, SEL_SSI2_1),
+ PINMUX_IPSR_MSEL(IP10_2_0, SSI_SCK2_B, SEL_SSI2_1),
PINMUX_IPSR_DATA(IP10_2_0, CAN_DEBUGOUT0),
PINMUX_IPSR_DATA(IP10_2_0, CC50_STATE35),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SCIF1_TXD, SEL_SCIF1_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, IIC0_SDA, SEL_IIC00_0),
+ PINMUX_IPSR_MSEL(IP10_5_3, SCIF1_TXD, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP10_5_3, IIC0_SDA, SEL_IIC00_0),
PINMUX_IPSR_DATA(IP10_5_3, DU1_DG7),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SSI_WS2_B, SEL_SSI2_1),
+ PINMUX_IPSR_MSEL(IP10_5_3, SSI_WS2_B, SEL_SSI2_1),
PINMUX_IPSR_DATA(IP10_5_3, CAN_DEBUGOUT1),
PINMUX_IPSR_DATA(IP10_5_3, CC50_STATE36),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, SCIF2_RXD, SEL_SCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, IIC1_SCL, SEL_IIC01_0),
+ PINMUX_IPSR_MSEL(IP10_8_6, SCIF2_RXD, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_8_6, IIC1_SCL, SEL_IIC01_0),
PINMUX_IPSR_DATA(IP10_8_6, DU1_DB0),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, SSI_SDATA2_B, SEL_SSI2_1),
+ PINMUX_IPSR_MSEL(IP10_8_6, SSI_SDATA2_B, SEL_SSI2_1),
PINMUX_IPSR_DATA(IP10_8_6, USB0_EXTLP),
PINMUX_IPSR_DATA(IP10_8_6, CAN_DEBUGOUT2),
PINMUX_IPSR_DATA(IP10_8_6, CC50_STATE37),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SCIF2_TXD, SEL_SCIF2_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, IIC1_SDA, SEL_IIC01_0),
+ PINMUX_IPSR_MSEL(IP10_11_9, SCIF2_TXD, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_11_9, IIC1_SDA, SEL_IIC01_0),
PINMUX_IPSR_DATA(IP10_11_9, DU1_DB1),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SSI_SCK9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP10_11_9, SSI_SCK9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP10_11_9, USB0_OVC1),
PINMUX_IPSR_DATA(IP10_11_9, CAN_DEBUGOUT3),
PINMUX_IPSR_DATA(IP10_11_9, CC50_STATE38),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SCIF2_SCK, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP10_14_12, SCIF2_SCK, SEL_SCIF2_0),
PINMUX_IPSR_DATA(IP10_14_12, IRQ1),
PINMUX_IPSR_DATA(IP10_14_12, DU1_DB2),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SSI_WS9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP10_14_12, SSI_WS9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP10_14_12, USB0_IDIN),
PINMUX_IPSR_DATA(IP10_14_12, CAN_DEBUGOUT4),
PINMUX_IPSR_DATA(IP10_14_12, CC50_STATE39),
- PINMUX_IPSR_MODSEL_DATA(IP10_17_15, SCIF3_SCK, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP10_17_15, SCIF3_SCK, SEL_SCIF3_0),
PINMUX_IPSR_DATA(IP10_17_15, IRQ2),
- PINMUX_IPSR_MODSEL_DATA(IP10_17_15, BPFCLK_D, SEL_DARC_3),
+ PINMUX_IPSR_MSEL(IP10_17_15, BPFCLK_D, SEL_DARC_3),
PINMUX_IPSR_DATA(IP10_17_15, DU1_DB3),
- PINMUX_IPSR_MODSEL_DATA(IP10_17_15, SSI_SDATA9_B, SEL_SSI9_1),
+ PINMUX_IPSR_MSEL(IP10_17_15, SSI_SDATA9_B, SEL_SSI9_1),
PINMUX_IPSR_DATA(IP10_17_15, TANS2),
PINMUX_IPSR_DATA(IP10_17_15, CAN_DEBUGOUT5),
PINMUX_IPSR_DATA(IP10_17_15, CC50_OSCOUT),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, SCIF3_RXD, SEL_SCIF3_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, I2C1_SCL_E, SEL_I2C01_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, FMCLK_D, SEL_DARC_3),
+ PINMUX_IPSR_MSEL(IP10_20_18, SCIF3_RXD, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP10_20_18, I2C1_SCL_E, SEL_I2C01_4),
+ PINMUX_IPSR_MSEL(IP10_20_18, FMCLK_D, SEL_DARC_3),
PINMUX_IPSR_DATA(IP10_20_18, DU1_DB4),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, AUDIO_CLKA_C, SEL_ADG_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, SSI_SCK4_B, SEL_SSI4_1),
+ PINMUX_IPSR_MSEL(IP10_20_18, AUDIO_CLKA_C, SEL_ADG_2),
+ PINMUX_IPSR_MSEL(IP10_20_18, SSI_SCK4_B, SEL_SSI4_1),
PINMUX_IPSR_DATA(IP10_20_18, CAN_DEBUGOUT6),
- PINMUX_IPSR_MODSEL_DATA(IP10_20_18, RDS_CLK_C, SEL_RDS_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, SCIF3_TXD, SEL_SCIF3_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, I2C1_SDA_E, SEL_I2C01_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, FMIN_D, SEL_DARC_3),
+ PINMUX_IPSR_MSEL(IP10_20_18, RDS_CLK_C, SEL_RDS_2),
+ PINMUX_IPSR_MSEL(IP10_23_21, SCIF3_TXD, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP10_23_21, I2C1_SDA_E, SEL_I2C01_4),
+ PINMUX_IPSR_MSEL(IP10_23_21, FMIN_D, SEL_DARC_3),
PINMUX_IPSR_DATA(IP10_23_21, DU1_DB5),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, AUDIO_CLKB_C, SEL_ADG_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, SSI_WS4_B, SEL_SSI4_1),
+ PINMUX_IPSR_MSEL(IP10_23_21, AUDIO_CLKB_C, SEL_ADG_2),
+ PINMUX_IPSR_MSEL(IP10_23_21, SSI_WS4_B, SEL_SSI4_1),
PINMUX_IPSR_DATA(IP10_23_21, CAN_DEBUGOUT7),
- PINMUX_IPSR_MODSEL_DATA(IP10_23_21, RDS_DATA_C, SEL_RDS_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_26_24, I2C2_SCL, SEL_I2C02_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_26_24, SCIFA5_RXD, SEL_SCIFA5_0),
+ PINMUX_IPSR_MSEL(IP10_23_21, RDS_DATA_C, SEL_RDS_2),
+ PINMUX_IPSR_MSEL(IP10_26_24, I2C2_SCL, SEL_I2C02_0),
+ PINMUX_IPSR_MSEL(IP10_26_24, SCIFA5_RXD, SEL_SCIFA5_0),
PINMUX_IPSR_DATA(IP10_26_24, DU1_DB6),
- PINMUX_IPSR_MODSEL_DATA(IP10_26_24, AUDIO_CLKC_C, SEL_ADG_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_26_24, SSI_SDATA4_B, SEL_SSI4_1),
+ PINMUX_IPSR_MSEL(IP10_26_24, AUDIO_CLKC_C, SEL_ADG_2),
+ PINMUX_IPSR_MSEL(IP10_26_24, SSI_SDATA4_B, SEL_SSI4_1),
PINMUX_IPSR_DATA(IP10_26_24, CAN_DEBUGOUT8),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_27, I2C2_SDA, SEL_I2C02_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_27, SCIFA5_TXD, SEL_SCIFA5_0),
+ PINMUX_IPSR_MSEL(IP10_29_27, I2C2_SDA, SEL_I2C02_0),
+ PINMUX_IPSR_MSEL(IP10_29_27, SCIFA5_TXD, SEL_SCIFA5_0),
PINMUX_IPSR_DATA(IP10_29_27, DU1_DB7),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_27, AUDIO_CLKOUT_C, SEL_ADG_2),
+ PINMUX_IPSR_MSEL(IP10_29_27, AUDIO_CLKOUT_C, SEL_ADG_2),
PINMUX_IPSR_DATA(IP10_29_27, CAN_DEBUGOUT9),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_30, SSI_SCK5, SEL_SSI5_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_31_30, SCIFA3_SCK, SEL_SCIFA3_0),
+ PINMUX_IPSR_MSEL(IP10_31_30, SSI_SCK5, SEL_SSI5_0),
+ PINMUX_IPSR_MSEL(IP10_31_30, SCIFA3_SCK, SEL_SCIFA3_0),
PINMUX_IPSR_DATA(IP10_31_30, DU1_DOTCLKIN),
PINMUX_IPSR_DATA(IP10_31_30, CAN_DEBUGOUT10),
/* IPSR11 */
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, SSI_WS5, SEL_SSI5_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_2_0, I2C3_SCL_C, SEL_I2C03_2),
+ PINMUX_IPSR_MSEL(IP11_2_0, SSI_WS5, SEL_SSI5_0),
+ PINMUX_IPSR_MSEL(IP11_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
+ PINMUX_IPSR_MSEL(IP11_2_0, I2C3_SCL_C, SEL_I2C03_2),
PINMUX_IPSR_DATA(IP11_2_0, DU1_DOTCLKOUT0),
PINMUX_IPSR_DATA(IP11_2_0, CAN_DEBUGOUT11),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, SSI_SDATA5, SEL_SSI5_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, SCIFA3_TXD, SEL_SCIFA3_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_5_3, I2C3_SDA_C, SEL_I2C03_2),
+ PINMUX_IPSR_MSEL(IP11_5_3, SSI_SDATA5, SEL_SSI5_0),
+ PINMUX_IPSR_MSEL(IP11_5_3, SCIFA3_TXD, SEL_SCIFA3_0),
+ PINMUX_IPSR_MSEL(IP11_5_3, I2C3_SDA_C, SEL_I2C03_2),
PINMUX_IPSR_DATA(IP11_5_3, DU1_DOTCLKOUT1),
PINMUX_IPSR_DATA(IP11_5_3, CAN_DEBUGOUT12),
- PINMUX_IPSR_MODSEL_DATA(IP11_7_6, SSI_SCK6, SEL_SSI6_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_7_6, SCIFA1_SCK_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP11_7_6, SSI_SCK6, SEL_SSI6_0),
+ PINMUX_IPSR_MSEL(IP11_7_6, SCIFA1_SCK_B, SEL_SCIFA1_1),
PINMUX_IPSR_DATA(IP11_7_6, DU1_EXHSYNC_DU1_HSYNC),
PINMUX_IPSR_DATA(IP11_7_6, CAN_DEBUGOUT13),
- PINMUX_IPSR_MODSEL_DATA(IP11_10_8, SSI_WS6, SEL_SSI6_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_10_8, SCIFA1_RXD_B, SEL_SCIFA1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_10_8, I2C4_SCL_C, SEL_I2C04_2),
+ PINMUX_IPSR_MSEL(IP11_10_8, SSI_WS6, SEL_SSI6_0),
+ PINMUX_IPSR_MSEL(IP11_10_8, SCIFA1_RXD_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP11_10_8, I2C4_SCL_C, SEL_I2C04_2),
PINMUX_IPSR_DATA(IP11_10_8, DU1_EXVSYNC_DU1_VSYNC),
PINMUX_IPSR_DATA(IP11_10_8, CAN_DEBUGOUT14),
- PINMUX_IPSR_MODSEL_DATA(IP11_13_11, SSI_SDATA6, SEL_SSI6_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_13_11, SCIFA1_TXD_B, SEL_SCIFA1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_13_11, I2C4_SDA_C, SEL_I2C04_2),
+ PINMUX_IPSR_MSEL(IP11_13_11, SSI_SDATA6, SEL_SSI6_0),
+ PINMUX_IPSR_MSEL(IP11_13_11, SCIFA1_TXD_B, SEL_SCIFA1_1),
+ PINMUX_IPSR_MSEL(IP11_13_11, I2C4_SDA_C, SEL_I2C04_2),
PINMUX_IPSR_DATA(IP11_13_11, DU1_EXODDF_DU1_ODDF_DISP_CDE),
PINMUX_IPSR_DATA(IP11_13_11, CAN_DEBUGOUT15),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_14, SSI_SCK78, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_14, SCIFA2_SCK_B, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_14, IIC0_SDA_C, SEL_IIC00_2),
+ PINMUX_IPSR_MSEL(IP11_15_14, SSI_SCK78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP11_15_14, SCIFA2_SCK_B, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP11_15_14, IIC0_SDA_C, SEL_IIC00_2),
PINMUX_IPSR_DATA(IP11_15_14, DU1_DISP),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_16, SSI_WS78, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_16, SCIFA2_RXD_B, SEL_SCIFA2_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_17_16, IIC0_SCL_C, SEL_IIC00_2),
+ PINMUX_IPSR_MSEL(IP11_17_16, SSI_WS78, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP11_17_16, SCIFA2_RXD_B, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP11_17_16, IIC0_SCL_C, SEL_IIC00_2),
PINMUX_IPSR_DATA(IP11_17_16, DU1_CDE),
- PINMUX_IPSR_MODSEL_DATA(IP11_20_18, SSI_SDATA7, SEL_SSI7_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_20_18, SCIFA2_TXD_B, SEL_SCIFA2_1),
+ PINMUX_IPSR_MSEL(IP11_20_18, SSI_SDATA7, SEL_SSI7_0),
+ PINMUX_IPSR_MSEL(IP11_20_18, SCIFA2_TXD_B, SEL_SCIFA2_1),
PINMUX_IPSR_DATA(IP11_20_18, IRQ8),
- PINMUX_IPSR_MODSEL_DATA(IP11_20_18, AUDIO_CLKA_D, SEL_ADG_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_20_18, CAN_CLK_D, SEL_CAN_3),
+ PINMUX_IPSR_MSEL(IP11_20_18, AUDIO_CLKA_D, SEL_ADG_3),
+ PINMUX_IPSR_MSEL(IP11_20_18, CAN_CLK_D, SEL_CAN_3),
PINMUX_IPSR_DATA(IP11_20_18, PCMOE_N),
PINMUX_IPSR_DATA(IP11_23_21, SSI_SCK0129),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_21, MSIOF1_RXD_B, SEL_MSI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_21, SCIF5_RXD_D, SEL_SCIF5_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_21, ADIDATA_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_23_21, AD_DI_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP11_23_21, MSIOF1_RXD_B, SEL_MSI1_1),
+ PINMUX_IPSR_MSEL(IP11_23_21, SCIF5_RXD_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MSEL(IP11_23_21, ADIDATA_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP11_23_21, AD_DI_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP11_23_21, PCMWE_N),
PINMUX_IPSR_DATA(IP11_26_24, SSI_WS0129),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, MSIOF1_TXD_B, SEL_MSI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, SCIF5_TXD_D, SEL_SCIF5_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, ADICS_SAMP_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_26_24, AD_DO_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, MSIOF1_TXD_B, SEL_MSI1_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, SCIF5_TXD_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MSEL(IP11_26_24, ADICS_SAMP_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP11_26_24, AD_DO_B, SEL_ADI_1),
PINMUX_IPSR_DATA(IP11_29_27, SSI_SDATA0),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, MSIOF1_SCK_B, SEL_MSI1_1),
+ PINMUX_IPSR_MSEL(IP11_29_27, MSIOF1_SCK_B, SEL_MSI1_1),
PINMUX_IPSR_DATA(IP11_29_27, PWM0_B),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, ADICLK_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_29_27, AD_CLK_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP11_29_27, ADICLK_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP11_29_27, AD_CLK_B, SEL_ADI_1),
/* IPSR12 */
PINMUX_IPSR_DATA(IP12_2_0, SSI_SCK34),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, MSIOF1_SYNC_B, SEL_MSI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, SCIFA1_SCK_C, SEL_SCIFA1_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, ADICHS0_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, AD_NCS_N_B, SEL_ADI_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_2_0, DREQ1_N_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP12_2_0, MSIOF1_SYNC_B, SEL_MSI1_1),
+ PINMUX_IPSR_MSEL(IP12_2_0, SCIFA1_SCK_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP12_2_0, ADICHS0_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP12_2_0, AD_NCS_N_B, SEL_ADI_1),
+ PINMUX_IPSR_MSEL(IP12_2_0, DREQ1_N_B, SEL_LBS_1),
PINMUX_IPSR_DATA(IP12_5_3, SSI_WS34),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_3, MSIOF1_SS1_B, SEL_MSI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_3, SCIFA1_RXD_C, SEL_SCIFA1_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_3, ADICHS1_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_3, CAN1_RX_C, SEL_CAN1_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_5_3, DACK1_B, SEL_LBS_1),
+ PINMUX_IPSR_MSEL(IP12_5_3, MSIOF1_SS1_B, SEL_MSI1_1),
+ PINMUX_IPSR_MSEL(IP12_5_3, SCIFA1_RXD_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP12_5_3, ADICHS1_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP12_5_3, CAN1_RX_C, SEL_CAN1_2),
+ PINMUX_IPSR_MSEL(IP12_5_3, DACK1_B, SEL_LBS_1),
PINMUX_IPSR_DATA(IP12_8_6, SSI_SDATA3),
- PINMUX_IPSR_MODSEL_DATA(IP12_8_6, MSIOF1_SS2_B, SEL_MSI1_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_8_6, SCIFA1_TXD_C, SEL_SCIFA1_2),
- PINMUX_IPSR_MODSEL_DATA(IP12_8_6, ADICHS2_B, SEL_RAD_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_8_6, CAN1_TX_C, SEL_CAN1_2),
+ PINMUX_IPSR_MSEL(IP12_8_6, MSIOF1_SS2_B, SEL_MSI1_1),
+ PINMUX_IPSR_MSEL(IP12_8_6, SCIFA1_TXD_C, SEL_SCIFA1_2),
+ PINMUX_IPSR_MSEL(IP12_8_6, ADICHS2_B, SEL_RAD_1),
+ PINMUX_IPSR_MSEL(IP12_8_6, CAN1_TX_C, SEL_CAN1_2),
PINMUX_IPSR_DATA(IP12_8_6, DREQ2_N),
- PINMUX_IPSR_MODSEL_DATA(IP12_10_9, SSI_SCK4, SEL_SSI4_0),
+ PINMUX_IPSR_MSEL(IP12_10_9, SSI_SCK4, SEL_SSI4_0),
PINMUX_IPSR_DATA(IP12_10_9, MLB_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP12_10_9, IETX_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP12_10_9, IETX_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP12_10_9, IRD_TX),
- PINMUX_IPSR_MODSEL_DATA(IP12_12_11, SSI_WS4, SEL_SSI4_0),
+ PINMUX_IPSR_MSEL(IP12_12_11, SSI_WS4, SEL_SSI4_0),
PINMUX_IPSR_DATA(IP12_12_11, MLB_SIG),
- PINMUX_IPSR_MODSEL_DATA(IP12_12_11, IECLK_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP12_12_11, IECLK_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP12_12_11, IRD_RX),
- PINMUX_IPSR_MODSEL_DATA(IP12_14_13, SSI_SDATA4, SEL_SSI4_0),
+ PINMUX_IPSR_MSEL(IP12_14_13, SSI_SDATA4, SEL_SSI4_0),
PINMUX_IPSR_DATA(IP12_14_13, MLB_DAT),
- PINMUX_IPSR_MODSEL_DATA(IP12_14_13, IERX_B, SEL_IEB_1),
+ PINMUX_IPSR_MSEL(IP12_14_13, IERX_B, SEL_IEB_1),
PINMUX_IPSR_DATA(IP12_14_13, IRD_SCK),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_15, SSI_SDATA8, SEL_SSI8_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_15, SCIF1_SCK_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP12_17_15, SSI_SDATA8, SEL_SSI8_0),
+ PINMUX_IPSR_MSEL(IP12_17_15, SCIF1_SCK_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP12_17_15, PWM1_B),
PINMUX_IPSR_DATA(IP12_17_15, IRQ9),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_15, REMOCON, SEL_RCN_0),
+ PINMUX_IPSR_MSEL(IP12_17_15, REMOCON, SEL_RCN_0),
PINMUX_IPSR_DATA(IP12_17_15, DACK2),
- PINMUX_IPSR_MODSEL_DATA(IP12_17_15, ETH_MDIO_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_20_18, SSI_SCK1, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_20_18, SCIF1_RXD_B, SEL_SCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_20_18, IIC1_SCL_C, SEL_IIC01_2),
+ PINMUX_IPSR_MSEL(IP12_17_15, ETH_MDIO_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP12_20_18, SSI_SCK1, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP12_20_18, SCIF1_RXD_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP12_20_18, IIC1_SCL_C, SEL_IIC01_2),
PINMUX_IPSR_DATA(IP12_20_18, VI1_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP12_20_18, CAN0_RX_D, SEL_CAN0_3),
- PINMUX_IPSR_MODSEL_DATA(IP12_20_18, AVB_AVTP_CAPTURE, SEL_AVB_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_20_18, ETH_CRS_DV_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_21, SSI_WS1, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_21, SCIF1_TXD_B, SEL_SCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_21, IIC1_SDA_C, SEL_IIC01_2),
+ PINMUX_IPSR_MSEL(IP12_20_18, CAN0_RX_D, SEL_CAN0_3),
+ PINMUX_IPSR_MSEL(IP12_20_18, AVB_AVTP_CAPTURE, SEL_AVB_0),
+ PINMUX_IPSR_MSEL(IP12_20_18, ETH_CRS_DV_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP12_23_21, SSI_WS1, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP12_23_21, SCIF1_TXD_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP12_23_21, IIC1_SDA_C, SEL_IIC01_2),
PINMUX_IPSR_DATA(IP12_23_21, VI1_DATA0),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_21, CAN0_TX_D, SEL_CAN0_3),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_21, AVB_AVTP_MATCH, SEL_AVB_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_23_21, ETH_RX_ER_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, SSI_SDATA1, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, HSCIF1_HRX_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP12_23_21, CAN0_TX_D, SEL_CAN0_3),
+ PINMUX_IPSR_MSEL(IP12_23_21, AVB_AVTP_MATCH, SEL_AVB_0),
+ PINMUX_IPSR_MSEL(IP12_23_21, ETH_RX_ER_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP12_26_24, SSI_SDATA1, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP12_26_24, HSCIF1_HRX_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP12_26_24, VI1_DATA1),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, SDATA, SEL_FSN_0),
+ PINMUX_IPSR_MSEL(IP12_26_24, SDATA, SEL_FSN_0),
PINMUX_IPSR_DATA(IP12_26_24, ATAG0_N),
- PINMUX_IPSR_MODSEL_DATA(IP12_26_24, ETH_RXD0_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, SSI_SCK2, SEL_SSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, HSCIF1_HTX_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP12_26_24, ETH_RXD0_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP12_29_27, SSI_SCK2, SEL_SSI2_0),
+ PINMUX_IPSR_MSEL(IP12_29_27, HSCIF1_HTX_B, SEL_HSCIF1_1),
PINMUX_IPSR_DATA(IP12_29_27, VI1_DATA2),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, MDATA, SEL_FSN_0),
+ PINMUX_IPSR_MSEL(IP12_29_27, MDATA, SEL_FSN_0),
PINMUX_IPSR_DATA(IP12_29_27, ATAWR0_N),
- PINMUX_IPSR_MODSEL_DATA(IP12_29_27, ETH_RXD1_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP12_29_27, ETH_RXD1_B, SEL_ETH_1),
/* IPSR13 */
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SSI_WS2, SEL_SSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, HSCIF1_HCTS_N_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SCIFA0_RXD_D, SEL_SCIFA0_3),
+ PINMUX_IPSR_MSEL(IP13_2_0, SSI_WS2, SEL_SSI2_0),
+ PINMUX_IPSR_MSEL(IP13_2_0, HSCIF1_HCTS_N_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP13_2_0, SCIFA0_RXD_D, SEL_SCIFA0_3),
PINMUX_IPSR_DATA(IP13_2_0, VI1_DATA3),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SCKZ, SEL_FSN_0),
+ PINMUX_IPSR_MSEL(IP13_2_0, SCKZ, SEL_FSN_0),
PINMUX_IPSR_DATA(IP13_2_0, ATACS00_N),
- PINMUX_IPSR_MODSEL_DATA(IP13_2_0, ETH_LINK_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_5_3, SSI_SDATA2, SEL_SSI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_5_3, HSCIF1_HRTS_N_B, SEL_HSCIF1_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_5_3, SCIFA0_TXD_D, SEL_SCIFA0_3),
+ PINMUX_IPSR_MSEL(IP13_2_0, ETH_LINK_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_5_3, SSI_SDATA2, SEL_SSI2_0),
+ PINMUX_IPSR_MSEL(IP13_5_3, HSCIF1_HRTS_N_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP13_5_3, SCIFA0_TXD_D, SEL_SCIFA0_3),
PINMUX_IPSR_DATA(IP13_5_3, VI1_DATA4),
- PINMUX_IPSR_MODSEL_DATA(IP13_5_3, STM_N, SEL_FSN_0),
+ PINMUX_IPSR_MSEL(IP13_5_3, STM_N, SEL_FSN_0),
PINMUX_IPSR_DATA(IP13_5_3, ATACS10_N),
- PINMUX_IPSR_MODSEL_DATA(IP13_5_3, ETH_REFCLK_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_8_6, SSI_SCK9, SEL_SSI9_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_8_6, SCIF2_SCK_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP13_5_3, ETH_REFCLK_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_8_6, SSI_SCK9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP13_8_6, SCIF2_SCK_B, SEL_SCIF2_1),
PINMUX_IPSR_DATA(IP13_8_6, PWM2_B),
PINMUX_IPSR_DATA(IP13_8_6, VI1_DATA5),
- PINMUX_IPSR_MODSEL_DATA(IP13_8_6, MTS_N, SEL_FSN_0),
+ PINMUX_IPSR_MSEL(IP13_8_6, MTS_N, SEL_FSN_0),
PINMUX_IPSR_DATA(IP13_8_6, EX_WAIT1),
- PINMUX_IPSR_MODSEL_DATA(IP13_8_6, ETH_TXD1_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_11_9, SSI_WS9, SEL_SSI9_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_11_9, SCIF2_RXD_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_11_9, I2C3_SCL_E, SEL_I2C03_4),
+ PINMUX_IPSR_MSEL(IP13_8_6, ETH_TXD1_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_11_9, SSI_WS9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP13_11_9, SCIF2_RXD_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP13_11_9, I2C3_SCL_E, SEL_I2C03_4),
PINMUX_IPSR_DATA(IP13_11_9, VI1_DATA6),
PINMUX_IPSR_DATA(IP13_11_9, ATARD0_N),
- PINMUX_IPSR_MODSEL_DATA(IP13_11_9, ETH_TX_EN_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_14_12, SSI_SDATA9, SEL_SSI9_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_14_12, SCIF2_TXD_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_14_12, I2C3_SDA_E, SEL_I2C03_4),
+ PINMUX_IPSR_MSEL(IP13_11_9, ETH_TX_EN_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_14_12, SSI_SDATA9, SEL_SSI9_0),
+ PINMUX_IPSR_MSEL(IP13_14_12, SCIF2_TXD_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP13_14_12, I2C3_SDA_E, SEL_I2C03_4),
PINMUX_IPSR_DATA(IP13_14_12, VI1_DATA7),
PINMUX_IPSR_DATA(IP13_14_12, ATADIR0_N),
- PINMUX_IPSR_MODSEL_DATA(IP13_14_12, ETH_MAGIC_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_17_15, AUDIO_CLKA, SEL_ADG_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_17_15, I2C0_SCL_B, SEL_I2C00_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_17_15, SCIFA4_RXD_D, SEL_SCIFA4_3),
+ PINMUX_IPSR_MSEL(IP13_14_12, ETH_MAGIC_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_17_15, AUDIO_CLKA, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP13_17_15, I2C0_SCL_B, SEL_I2C00_1),
+ PINMUX_IPSR_MSEL(IP13_17_15, SCIFA4_RXD_D, SEL_SCIFA4_3),
PINMUX_IPSR_DATA(IP13_17_15, VI1_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP13_17_15, TS_SDATA_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_17_15, RIF0_SYNC_B, SEL_DR0_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_17_15, ETH_TXD0_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, AUDIO_CLKB, SEL_ADG_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, I2C0_SDA_B, SEL_I2C00_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, SCIFA4_TXD_D, SEL_SCIFA4_3),
+ PINMUX_IPSR_MSEL(IP13_17_15, TS_SDATA_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP13_17_15, RIF0_SYNC_B, SEL_DR0_1),
+ PINMUX_IPSR_MSEL(IP13_17_15, ETH_TXD0_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_20_18, AUDIO_CLKB, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP13_20_18, I2C0_SDA_B, SEL_I2C00_1),
+ PINMUX_IPSR_MSEL(IP13_20_18, SCIFA4_TXD_D, SEL_SCIFA4_3),
PINMUX_IPSR_DATA(IP13_20_18, VI1_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, TS_SCK_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, RIF0_CLK_B, SEL_DR0_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, BPFCLK_E, SEL_DARC_4),
- PINMUX_IPSR_MODSEL_DATA(IP13_20_18, ETH_MDC_B, SEL_ETH_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, AUDIO_CLKC, SEL_ADG_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, I2C4_SCL_B, SEL_I2C04_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, SCIFA5_RXD_D, SEL_SCIFA5_3),
+ PINMUX_IPSR_MSEL(IP13_20_18, TS_SCK_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP13_20_18, RIF0_CLK_B, SEL_DR0_1),
+ PINMUX_IPSR_MSEL(IP13_20_18, BPFCLK_E, SEL_DARC_4),
+ PINMUX_IPSR_MSEL(IP13_20_18, ETH_MDC_B, SEL_ETH_1),
+ PINMUX_IPSR_MSEL(IP13_23_21, AUDIO_CLKC, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP13_23_21, I2C4_SCL_B, SEL_I2C04_1),
+ PINMUX_IPSR_MSEL(IP13_23_21, SCIFA5_RXD_D, SEL_SCIFA5_3),
PINMUX_IPSR_DATA(IP13_23_21, VI1_HSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, TS_SDEN_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, RIF0_D0_B, SEL_DR0_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, FMCLK_E, SEL_DARC_4),
- PINMUX_IPSR_MODSEL_DATA(IP13_23_21, RDS_CLK_D, SEL_RDS_3),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, AUDIO_CLKOUT, SEL_ADG_0),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, I2C4_SDA_B, SEL_I2C04_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, SCIFA5_TXD_D, SEL_SCIFA5_3),
+ PINMUX_IPSR_MSEL(IP13_23_21, TS_SDEN_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP13_23_21, RIF0_D0_B, SEL_DR0_1),
+ PINMUX_IPSR_MSEL(IP13_23_21, FMCLK_E, SEL_DARC_4),
+ PINMUX_IPSR_MSEL(IP13_23_21, RDS_CLK_D, SEL_RDS_3),
+ PINMUX_IPSR_MSEL(IP13_26_24, AUDIO_CLKOUT, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP13_26_24, I2C4_SDA_B, SEL_I2C04_1),
+ PINMUX_IPSR_MSEL(IP13_26_24, SCIFA5_TXD_D, SEL_SCIFA5_3),
PINMUX_IPSR_DATA(IP13_26_24, VI1_VSYNC_N),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, TS_SPSYNC_C, SEL_TSIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, RIF0_D1_B, SEL_DR1_1),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, FMIN_E, SEL_DARC_4),
- PINMUX_IPSR_MODSEL_DATA(IP13_26_24, RDS_DATA_D, SEL_RDS_3),
+ PINMUX_IPSR_MSEL(IP13_26_24, TS_SPSYNC_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP13_26_24, RIF0_D1_B, SEL_DR1_1),
+ PINMUX_IPSR_MSEL(IP13_26_24, FMIN_E, SEL_DARC_4),
+ PINMUX_IPSR_MSEL(IP13_26_24, RDS_DATA_D, SEL_RDS_3),
};
static const struct sh_pfc_pin pinmux_pins[] = {
@@ -2197,13 +2196,6 @@ static const unsigned int scif0_data_pins[] = {
static const unsigned int scif0_data_mux[] = {
SCIF0_RXD_MARK, SCIF0_TXD_MARK,
};
-static const unsigned int scif0_clk_pins[] = {
- /* SCK */
- RCAR_GP_PIN(1, 23),
-};
-static const unsigned int scif0_clk_mux[] = {
- SCIF_CLK_MARK,
-};
static const unsigned int scif0_data_b_pins[] = {
/* RX, TX */
RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 12),
@@ -2211,13 +2203,6 @@ static const unsigned int scif0_data_b_pins[] = {
static const unsigned int scif0_data_b_mux[] = {
SCIF0_RXD_B_MARK, SCIF0_TXD_B_MARK,
};
-static const unsigned int scif0_clk_b_pins[] = {
- /* SCK */
- RCAR_GP_PIN(3, 29),
-};
-static const unsigned int scif0_clk_b_mux[] = {
- SCIF_CLK_B_MARK,
-};
static const unsigned int scif0_data_c_pins[] = {
/* RX, TX */
RCAR_GP_PIN(3, 30), RCAR_GP_PIN(3, 31),
@@ -2788,6 +2773,146 @@ static const unsigned int usb1_mux[] = {
USB1_PWEN_MARK,
USB1_OVC_MARK,
};
+/* - VIN0 ------------------------------------------------------------------- */
+static const union vin_data vin0_data_pins = {
+ .data24 = {
+ /* B */
+ RCAR_GP_PIN(3, 1), RCAR_GP_PIN(3, 2),
+ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 4),
+ RCAR_GP_PIN(3, 5), RCAR_GP_PIN(3, 6),
+ RCAR_GP_PIN(3, 7), RCAR_GP_PIN(3, 8),
+ /* G */
+ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14),
+ RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16),
+ RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 18),
+ RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 20),
+ /* R */
+ RCAR_GP_PIN(3, 21), RCAR_GP_PIN(3, 22),
+ RCAR_GP_PIN(3, 23), RCAR_GP_PIN(3, 24),
+ RCAR_GP_PIN(3, 25), RCAR_GP_PIN(3, 26),
+ RCAR_GP_PIN(3, 27), RCAR_GP_PIN(3, 28),
+ },
+};
+static const union vin_data vin0_data_mux = {
+ .data24 = {
+ /* B */
+ VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK,
+ VI0_DATA2_VI0_B2_MARK, VI0_DATA3_VI0_B3_MARK,
+ VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK,
+ VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK,
+ /* G */
+ VI0_G0_MARK, VI0_G1_MARK,
+ VI0_G2_MARK, VI0_G3_MARK,
+ VI0_G4_MARK, VI0_G5_MARK,
+ VI0_G6_MARK, VI0_G7_MARK,
+ /* R */
+ VI0_R0_MARK, VI0_R1_MARK,
+ VI0_R2_MARK, VI0_R3_MARK,
+ VI0_R4_MARK, VI0_R5_MARK,
+ VI0_R6_MARK, VI0_R7_MARK,
+ },
+};
+static const unsigned int vin0_data18_pins[] = {
+ /* B */
+ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 4),
+ RCAR_GP_PIN(3, 5), RCAR_GP_PIN(3, 6),
+ RCAR_GP_PIN(3, 7), RCAR_GP_PIN(3, 8),
+ /* G */
+ RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16),
+ RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 18),
+ RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 20),
+ /* R */
+ RCAR_GP_PIN(3, 23), RCAR_GP_PIN(3, 24),
+ RCAR_GP_PIN(3, 25), RCAR_GP_PIN(3, 26),
+ RCAR_GP_PIN(3, 27), RCAR_GP_PIN(3, 28),
+};
+static const unsigned int vin0_data18_mux[] = {
+ /* B */
+ VI0_DATA2_VI0_B2_MARK, VI0_DATA3_VI0_B3_MARK,
+ VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK,
+ VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK,
+ /* G */
+ VI0_G2_MARK, VI0_G3_MARK,
+ VI0_G4_MARK, VI0_G5_MARK,
+ VI0_G6_MARK, VI0_G7_MARK,
+ /* R */
+ VI0_R2_MARK, VI0_R3_MARK,
+ VI0_R4_MARK, VI0_R5_MARK,
+ VI0_R6_MARK, VI0_R7_MARK,
+};
+static const unsigned int vin0_sync_pins[] = {
+ RCAR_GP_PIN(3, 11), /* HSYNC */
+ RCAR_GP_PIN(3, 12), /* VSYNC */
+};
+static const unsigned int vin0_sync_mux[] = {
+ VI0_HSYNC_N_MARK,
+ VI0_VSYNC_N_MARK,
+};
+static const unsigned int vin0_field_pins[] = {
+ RCAR_GP_PIN(3, 10),
+};
+static const unsigned int vin0_field_mux[] = {
+ VI0_FIELD_MARK,
+};
+static const unsigned int vin0_clkenb_pins[] = {
+ RCAR_GP_PIN(3, 9),
+};
+static const unsigned int vin0_clkenb_mux[] = {
+ VI0_CLKENB_MARK,
+};
+static const unsigned int vin0_clk_pins[] = {
+ RCAR_GP_PIN(3, 0),
+};
+static const unsigned int vin0_clk_mux[] = {
+ VI0_CLK_MARK,
+};
+/* - VIN1 ------------------------------------------------------------------- */
+static const union vin_data vin1_data_pins = {
+ .data12 = {
+ RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 13),
+ RCAR_GP_PIN(5, 14), RCAR_GP_PIN(5, 15),
+ RCAR_GP_PIN(5, 16), RCAR_GP_PIN(5, 17),
+ RCAR_GP_PIN(5, 18), RCAR_GP_PIN(5, 19),
+ RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 11),
+ RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 13),
+ },
+};
+static const union vin_data vin1_data_mux = {
+ .data12 = {
+ VI1_DATA0_MARK, VI1_DATA1_MARK,
+ VI1_DATA2_MARK, VI1_DATA3_MARK,
+ VI1_DATA4_MARK, VI1_DATA5_MARK,
+ VI1_DATA6_MARK, VI1_DATA7_MARK,
+ VI1_DATA8_MARK, VI1_DATA9_MARK,
+ VI1_DATA10_MARK, VI1_DATA11_MARK,
+ },
+};
+static const unsigned int vin1_sync_pins[] = {
+ RCAR_GP_PIN(5, 22), /* HSYNC */
+ RCAR_GP_PIN(5, 23), /* VSYNC */
+};
+static const unsigned int vin1_sync_mux[] = {
+ VI1_HSYNC_N_MARK,
+ VI1_VSYNC_N_MARK,
+};
+static const unsigned int vin1_field_pins[] = {
+ RCAR_GP_PIN(5, 21),
+};
+static const unsigned int vin1_field_mux[] = {
+ VI1_FIELD_MARK,
+};
+static const unsigned int vin1_clkenb_pins[] = {
+ RCAR_GP_PIN(5, 20),
+};
+static const unsigned int vin1_clkenb_mux[] = {
+ VI1_CLKENB_MARK,
+};
+static const unsigned int vin1_clk_pins[] = {
+ RCAR_GP_PIN(5, 11),
+};
+static const unsigned int vin1_clk_mux[] = {
+ VI1_CLK_MARK,
+};
static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(eth_link),
@@ -2884,9 +3009,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(qspi_data2),
SH_PFC_PIN_GROUP(qspi_data4),
SH_PFC_PIN_GROUP(scif0_data),
- SH_PFC_PIN_GROUP(scif0_clk),
SH_PFC_PIN_GROUP(scif0_data_b),
- SH_PFC_PIN_GROUP(scif0_clk_b),
SH_PFC_PIN_GROUP(scif0_data_c),
SH_PFC_PIN_GROUP(scif0_data_d),
SH_PFC_PIN_GROUP(scif1_data),
@@ -2965,6 +3088,24 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(sdhi2_wp),
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
+ VIN_DATA_PIN_GROUP(vin0_data, 24),
+ VIN_DATA_PIN_GROUP(vin0_data, 20),
+ SH_PFC_PIN_GROUP(vin0_data18),
+ VIN_DATA_PIN_GROUP(vin0_data, 16),
+ VIN_DATA_PIN_GROUP(vin0_data, 12),
+ VIN_DATA_PIN_GROUP(vin0_data, 10),
+ VIN_DATA_PIN_GROUP(vin0_data, 8),
+ SH_PFC_PIN_GROUP(vin0_sync),
+ SH_PFC_PIN_GROUP(vin0_field),
+ SH_PFC_PIN_GROUP(vin0_clkenb),
+ SH_PFC_PIN_GROUP(vin0_clk),
+ VIN_DATA_PIN_GROUP(vin1_data, 12),
+ VIN_DATA_PIN_GROUP(vin1_data, 10),
+ VIN_DATA_PIN_GROUP(vin1_data, 8),
+ SH_PFC_PIN_GROUP(vin1_sync),
+ SH_PFC_PIN_GROUP(vin1_field),
+ SH_PFC_PIN_GROUP(vin1_clkenb),
+ SH_PFC_PIN_GROUP(vin1_clk),
};
static const char * const eth_groups[] = {
@@ -3107,9 +3248,7 @@ static const char * const qspi_groups[] = {
static const char * const scif0_groups[] = {
"scif0_data",
- "scif0_clk",
"scif0_data_b",
- "scif0_clk_b",
"scif0_data_c",
"scif0_data_d",
};
@@ -3247,6 +3386,30 @@ static const char * const usb1_groups[] = {
"usb1",
};
+static const char * const vin0_groups[] = {
+ "vin0_data24",
+ "vin0_data20",
+ "vin0_data18",
+ "vin0_data16",
+ "vin0_data12",
+ "vin0_data10",
+ "vin0_data8",
+ "vin0_sync",
+ "vin0_field",
+ "vin0_clkenb",
+ "vin0_clk",
+};
+
+static const char * const vin1_groups[] = {
+ "vin1_data12",
+ "vin1_data10",
+ "vin1_data8",
+ "vin1_sync",
+ "vin1_field",
+ "vin1_clkenb",
+ "vin1_clk",
+};
+
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(eth),
SH_PFC_FUNCTION(hscif0),
@@ -3283,6 +3446,8 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(sdhi2),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
+ SH_PFC_FUNCTION(vin0),
+ SH_PFC_FUNCTION(vin1),
};
static const struct pinmux_cfg_reg pinmux_config_regs[] = {
@@ -4232,6 +4397,6 @@ const struct sh_pfc_soc_info r8a7794_pinmux_info = {
.cfg_regs = pinmux_config_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
new file mode 100644
index 000000000000..7ddb2adfc5a5
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
@@ -0,0 +1,2816 @@
+/*
+ * R-Car Gen3 processor support - PFC hardware block.
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/kernel.h>
+
+#include "core.h"
+#include "sh_pfc.h"
+
+#define PORT_GP_3(bank, fn, sfx) \
+ PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
+ PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx)
+
+#define PORT_GP_14(bank, fn, sfx) \
+ PORT_GP_3(bank, fn, sfx), \
+ PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
+ PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
+ PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
+ PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
+ PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
+ PORT_GP_1(bank, 14, fn, sfx)
+
+#define PORT_GP_15(bank, fn, sfx) \
+ PORT_GP_14(bank, fn, sfx), PORT_GP_1(bank, 15, fn, sfx)
+
+#define PORT_GP_17(bank, fn, sfx) \
+ PORT_GP_15(bank, fn, sfx), \
+ PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx)
+
+#define PORT_GP_25(bank, fn, sfx) \
+ PORT_GP_17(bank, fn, sfx), \
+ PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
+ PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
+ PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
+ PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx)
+
+#define PORT_GP_27(bank, fn, sfx) \
+ PORT_GP_25(bank, fn, sfx), \
+ PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx)
+
+#define CPU_ALL_PORT(fn, sfx) \
+ PORT_GP_15(0, fn, sfx), \
+ PORT_GP_27(1, fn, sfx), \
+ PORT_GP_14(2, fn, sfx), \
+ PORT_GP_15(3, fn, sfx), \
+ PORT_GP_17(4, fn, sfx), \
+ PORT_GP_25(5, fn, sfx), \
+ PORT_GP_32(6, fn, sfx), \
+ PORT_GP_3(7, fn, sfx)
+/*
+ * F_() : just information
+ * FM() : macro for FN_xxx / xxx_MARK
+ */
+
+/* GPSR0 */
+#define GPSR0_15 F_(D15, IP7_11_8)
+#define GPSR0_14 F_(D14, IP7_7_4)
+#define GPSR0_13 F_(D13, IP7_3_0)
+#define GPSR0_12 F_(D12, IP6_31_28)
+#define GPSR0_11 F_(D11, IP6_27_24)
+#define GPSR0_10 F_(D10, IP6_23_20)
+#define GPSR0_9 F_(D9, IP6_19_16)
+#define GPSR0_8 F_(D8, IP6_15_12)
+#define GPSR0_7 F_(D7, IP6_11_8)
+#define GPSR0_6 F_(D6, IP6_7_4)
+#define GPSR0_5 F_(D5, IP6_3_0)
+#define GPSR0_4 F_(D4, IP5_31_28)
+#define GPSR0_3 F_(D3, IP5_27_24)
+#define GPSR0_2 F_(D2, IP5_23_20)
+#define GPSR0_1 F_(D1, IP5_19_16)
+#define GPSR0_0 F_(D0, IP5_15_12)
+
+/* GPSR1 */
+#define GPSR1_27 F_(EX_WAIT0_A, IP5_11_8)
+#define GPSR1_26 F_(WE1_N, IP5_7_4)
+#define GPSR1_25 F_(WE0_N, IP5_3_0)
+#define GPSR1_24 F_(RD_WR_N, IP4_31_28)
+#define GPSR1_23 F_(RD_N, IP4_27_24)
+#define GPSR1_22 F_(BS_N, IP4_23_20)
+#define GPSR1_21 F_(CS1_N_A26, IP4_19_16)
+#define GPSR1_20 F_(CS0_N, IP4_15_12)
+#define GPSR1_19 F_(A19, IP4_11_8)
+#define GPSR1_18 F_(A18, IP4_7_4)
+#define GPSR1_17 F_(A17, IP4_3_0)
+#define GPSR1_16 F_(A16, IP3_31_28)
+#define GPSR1_15 F_(A15, IP3_27_24)
+#define GPSR1_14 F_(A14, IP3_23_20)
+#define GPSR1_13 F_(A13, IP3_19_16)
+#define GPSR1_12 F_(A12, IP3_15_12)
+#define GPSR1_11 F_(A11, IP3_11_8)
+#define GPSR1_10 F_(A10, IP3_7_4)
+#define GPSR1_9 F_(A9, IP3_3_0)
+#define GPSR1_8 F_(A8, IP2_31_28)
+#define GPSR1_7 F_(A7, IP2_27_24)
+#define GPSR1_6 F_(A6, IP2_23_20)
+#define GPSR1_5 F_(A5, IP2_19_16)
+#define GPSR1_4 F_(A4, IP2_15_12)
+#define GPSR1_3 F_(A3, IP2_11_8)
+#define GPSR1_2 F_(A2, IP2_7_4)
+#define GPSR1_1 F_(A1, IP2_3_0)
+#define GPSR1_0 F_(A0, IP1_31_28)
+
+/* GPSR2 */
+#define GPSR2_14 F_(AVB_AVTP_CAPTURE_A, IP0_23_20)
+#define GPSR2_13 F_(AVB_AVTP_MATCH_A, IP0_19_16)
+#define GPSR2_12 F_(AVB_LINK, IP0_15_12)
+#define GPSR2_11 F_(AVB_PHY_INT, IP0_11_8)
+#define GPSR2_10 F_(AVB_MAGIC, IP0_7_4)
+#define GPSR2_9 F_(AVB_MDC, IP0_3_0)
+#define GPSR2_8 F_(PWM2_A, IP1_27_24)
+#define GPSR2_7 F_(PWM1_A, IP1_23_20)
+#define GPSR2_6 F_(PWM0, IP1_19_16)
+#define GPSR2_5 F_(IRQ5, IP1_15_12)
+#define GPSR2_4 F_(IRQ4, IP1_11_8)
+#define GPSR2_3 F_(IRQ3, IP1_7_4)
+#define GPSR2_2 F_(IRQ2, IP1_3_0)
+#define GPSR2_1 F_(IRQ1, IP0_31_28)
+#define GPSR2_0 F_(IRQ0, IP0_27_24)
+
+/* GPSR3 */
+#define GPSR3_15 F_(SD1_WP, IP10_23_20)
+#define GPSR3_14 F_(SD1_CD, IP10_19_16)
+#define GPSR3_13 F_(SD0_WP, IP10_15_12)
+#define GPSR3_12 F_(SD0_CD, IP10_11_8)
+#define GPSR3_11 F_(SD1_DAT3, IP8_31_28)
+#define GPSR3_10 F_(SD1_DAT2, IP8_27_24)
+#define GPSR3_9 F_(SD1_DAT1, IP8_23_20)
+#define GPSR3_8 F_(SD1_DAT0, IP8_19_16)
+#define GPSR3_7 F_(SD1_CMD, IP8_15_12)
+#define GPSR3_6 F_(SD1_CLK, IP8_11_8)
+#define GPSR3_5 F_(SD0_DAT3, IP8_7_4)
+#define GPSR3_4 F_(SD0_DAT2, IP8_3_0)
+#define GPSR3_3 F_(SD0_DAT1, IP7_31_28)
+#define GPSR3_2 F_(SD0_DAT0, IP7_27_24)
+#define GPSR3_1 F_(SD0_CMD, IP7_23_20)
+#define GPSR3_0 F_(SD0_CLK, IP7_19_16)
+
+/* GPSR4 */
+#define GPSR4_17 FM(SD3_DS)
+#define GPSR4_16 F_(SD3_DAT7, IP10_7_4)
+#define GPSR4_15 F_(SD3_DAT6, IP10_3_0)
+#define GPSR4_14 F_(SD3_DAT5, IP9_31_28)
+#define GPSR4_13 F_(SD3_DAT4, IP9_27_24)
+#define GPSR4_12 FM(SD3_DAT3)
+#define GPSR4_11 FM(SD3_DAT2)
+#define GPSR4_10 FM(SD3_DAT1)
+#define GPSR4_9 FM(SD3_DAT0)
+#define GPSR4_8 FM(SD3_CMD)
+#define GPSR4_7 FM(SD3_CLK)
+#define GPSR4_6 F_(SD2_DS, IP9_23_20)
+#define GPSR4_5 F_(SD2_DAT3, IP9_19_16)
+#define GPSR4_4 F_(SD2_DAT2, IP9_15_12)
+#define GPSR4_3 F_(SD2_DAT1, IP9_11_8)
+#define GPSR4_2 F_(SD2_DAT0, IP9_7_4)
+#define GPSR4_1 FM(SD2_CMD)
+#define GPSR4_0 F_(SD2_CLK, IP9_3_0)
+
+/* GPSR5 */
+#define GPSR5_25 F_(MLB_DAT, IP13_19_16)
+#define GPSR5_24 F_(MLB_SIG, IP13_15_12)
+#define GPSR5_23 F_(MLB_CLK, IP13_11_8)
+#define GPSR5_22 FM(MSIOF0_RXD)
+#define GPSR5_21 F_(MSIOF0_SS2, IP13_7_4)
+#define GPSR5_20 FM(MSIOF0_TXD)
+#define GPSR5_19 F_(MSIOF0_SS1, IP13_3_0)
+#define GPSR5_18 F_(MSIOF0_SYNC, IP12_31_28)
+#define GPSR5_17 FM(MSIOF0_SCK)
+#define GPSR5_16 F_(HRTS0_N, IP12_27_24)
+#define GPSR5_15 F_(HCTS0_N, IP12_23_20)
+#define GPSR5_14 F_(HTX0, IP12_19_16)
+#define GPSR5_13 F_(HRX0, IP12_15_12)
+#define GPSR5_12 F_(HSCK0, IP12_11_8)
+#define GPSR5_11 F_(RX2_A, IP12_7_4)
+#define GPSR5_10 F_(TX2_A, IP12_3_0)
+#define GPSR5_9 F_(SCK2, IP11_31_28)
+#define GPSR5_8 F_(RTS1_N_TANS, IP11_27_24)
+#define GPSR5_7 F_(CTS1_N, IP11_23_20)
+#define GPSR5_6 F_(TX1_A, IP11_19_16)
+#define GPSR5_5 F_(RX1_A, IP11_15_12)
+#define GPSR5_4 F_(RTS0_N_TANS, IP11_11_8)
+#define GPSR5_3 F_(CTS0_N, IP11_7_4)
+#define GPSR5_2 F_(TX0, IP11_3_0)
+#define GPSR5_1 F_(RX0, IP10_31_28)
+#define GPSR5_0 F_(SCK0, IP10_27_24)
+
+/* GPSR6 */
+#define GPSR6_31 F_(USB31_OVC, IP17_7_4)
+#define GPSR6_30 F_(USB31_PWEN, IP17_3_0)
+#define GPSR6_29 F_(USB30_OVC, IP16_31_28)
+#define GPSR6_28 F_(USB30_PWEN, IP16_27_24)
+#define GPSR6_27 F_(USB1_OVC, IP16_23_20)
+#define GPSR6_26 F_(USB1_PWEN, IP16_19_16)
+#define GPSR6_25 F_(USB0_OVC, IP16_15_12)
+#define GPSR6_24 F_(USB0_PWEN, IP16_11_8)
+#define GPSR6_23 F_(AUDIO_CLKB_B, IP16_7_4)
+#define GPSR6_22 F_(AUDIO_CLKA_A, IP16_3_0)
+#define GPSR6_21 F_(SSI_SDATA9_A, IP15_31_28)
+#define GPSR6_20 F_(SSI_SDATA8, IP15_27_24)
+#define GPSR6_19 F_(SSI_SDATA7, IP15_23_20)
+#define GPSR6_18 F_(SSI_WS78, IP15_19_16)
+#define GPSR6_17 F_(SSI_SCK78, IP15_15_12)
+#define GPSR6_16 F_(SSI_SDATA6, IP15_11_8)
+#define GPSR6_15 F_(SSI_WS6, IP15_7_4)
+#define GPSR6_14 F_(SSI_SCK6, IP15_3_0)
+#define GPSR6_13 FM(SSI_SDATA5)
+#define GPSR6_12 FM(SSI_WS5)
+#define GPSR6_11 FM(SSI_SCK5)
+#define GPSR6_10 F_(SSI_SDATA4, IP14_31_28)
+#define GPSR6_9 F_(SSI_WS4, IP14_27_24)
+#define GPSR6_8 F_(SSI_SCK4, IP14_23_20)
+#define GPSR6_7 F_(SSI_SDATA3, IP14_19_16)
+#define GPSR6_6 F_(SSI_WS34, IP14_15_12)
+#define GPSR6_5 F_(SSI_SCK34, IP14_11_8)
+#define GPSR6_4 F_(SSI_SDATA2_A, IP14_7_4)
+#define GPSR6_3 F_(SSI_SDATA1_A, IP14_3_0)
+#define GPSR6_2 F_(SSI_SDATA0, IP13_31_28)
+#define GPSR6_1 F_(SSI_WS0129, IP13_27_24)
+#define GPSR6_0 F_(SSI_SCK0129, IP13_23_20)
+
+/* GPSR7 */
+#define GPSR7_3 FM(HDMI1_CEC)
+#define GPSR7_2 FM(HDMI0_CEC)
+#define GPSR7_1 FM(AVS2)
+#define GPSR7_0 FM(AVS1)
+
+
+/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */
+#define IP0_3_0 FM(AVB_MDC) F_(0, 0) FM(MSIOF2_SS2_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_7_4 FM(AVB_MAGIC) F_(0, 0) FM(MSIOF2_SS1_C) FM(SCK4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_11_8 FM(AVB_PHY_INT) F_(0, 0) FM(MSIOF2_SYNC_C) FM(RX4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_15_12 FM(AVB_LINK) F_(0, 0) FM(MSIOF2_SCK_C) FM(TX4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_19_16 FM(AVB_AVTP_MATCH_A) F_(0, 0) FM(MSIOF2_RXD_C) FM(CTS4_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_TANS_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_3_0 FM(IRQ2) FM(QCPV_QDE) F_(0, 0) FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(VI4_DATA2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) FM(A25) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) FM(A24) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_15_12 FM(IRQ5) FM(QSTB_QHE) FM(A23) FM(DU_EXVSYNC_DU_VSYNC) FM(VI4_DATA5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(PWM6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_19_16 FM(PWM0) FM(AVB_AVTP_PPS)FM(A22) F_(0, 0) FM(VI4_DATA6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IECLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_23_20 FM(PWM1_A) F_(0, 0) FM(A21) FM(HRX3_D) FM(VI4_DATA7_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IERX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_27_24 FM(PWM2_A) F_(0, 0) FM(A20) FM(HTX3_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IETX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_31_28 FM(A0) FM(LCDOUT16) FM(MSIOF3_SYNC_B) F_(0, 0) FM(VI4_DATA8) F_(0, 0) FM(DU_DB0) F_(0, 0) F_(0, 0) FM(PWM3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_3_0 FM(A1) FM(LCDOUT17) FM(MSIOF3_TXD_B) F_(0, 0) FM(VI4_DATA9) F_(0, 0) FM(DU_DB1) F_(0, 0) F_(0, 0) FM(PWM4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_7_4 FM(A2) FM(LCDOUT18) FM(MSIOF3_SCK_B) F_(0, 0) FM(VI4_DATA10) F_(0, 0) FM(DU_DB2) F_(0, 0) F_(0, 0) FM(PWM5_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_11_8 FM(A3) FM(LCDOUT19) FM(MSIOF3_RXD_B) F_(0, 0) FM(VI4_DATA11) F_(0, 0) FM(DU_DB3) F_(0, 0) F_(0, 0) FM(PWM6_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */
+#define IP2_15_12 FM(A4) FM(LCDOUT20) FM(MSIOF3_SS1_B) F_(0, 0) FM(VI4_DATA12) FM(VI5_DATA12) FM(DU_DB4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_19_16 FM(A5) FM(LCDOUT21) FM(MSIOF3_SS2_B) FM(SCK4_B) FM(VI4_DATA13) FM(VI5_DATA13) FM(DU_DB5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_23_20 FM(A6) FM(LCDOUT22) FM(MSIOF2_SS1_A) FM(RX4_B) FM(VI4_DATA14) FM(VI5_DATA14) FM(DU_DB6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_27_24 FM(A7) FM(LCDOUT23) FM(MSIOF2_SS2_A) FM(TX4_B) FM(VI4_DATA15) FM(VI5_DATA15) FM(DU_DB7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2_31_28 FM(A8) FM(RX3_B) FM(MSIOF2_SYNC_A) FM(HRX4_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(SDA6_A) FM(AVB_AVTP_MATCH_B) FM(PWM1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_3_0 FM(A9) F_(0, 0) FM(MSIOF2_SCK_A) FM(CTS4_N_B) F_(0, 0) FM(VI5_VSYNC_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_7_4 FM(A10) F_(0, 0) FM(MSIOF2_RXD_A) FM(RTS4_N_TANS_B) F_(0, 0) FM(VI5_HSYNC_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_11_8 FM(A11) FM(TX3_B) FM(MSIOF2_TXD_A) FM(HTX4_B) FM(HSCK4) FM(VI5_FIELD) F_(0, 0) FM(SCL6_A) FM(AVB_AVTP_CAPTURE_B) FM(PWM2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_15_12 FM(A12) FM(LCDOUT12) FM(MSIOF3_SCK_C) F_(0, 0) FM(HRX4_A) FM(VI5_DATA8) FM(DU_DG4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_19_16 FM(A13) FM(LCDOUT13) FM(MSIOF3_SYNC_C) F_(0, 0) FM(HTX4_A) FM(VI5_DATA9) FM(DU_DG5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_23_20 FM(A14) FM(LCDOUT14) FM(MSIOF3_RXD_C) F_(0, 0) FM(HCTS4_N) FM(VI5_DATA10) FM(DU_DG6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_27_24 FM(A15) FM(LCDOUT15) FM(MSIOF3_TXD_C) F_(0, 0) FM(HRTS4_N) FM(VI5_DATA11) FM(DU_DG7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3_31_28 FM(A16) FM(LCDOUT8) F_(0, 0) F_(0, 0) FM(VI4_FIELD) F_(0, 0) FM(DU_DG0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_3_0 FM(A17) FM(LCDOUT9) F_(0, 0) F_(0, 0) FM(VI4_VSYNC_N) F_(0, 0) FM(DU_DG1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_7_4 FM(A18) FM(LCDOUT10) F_(0, 0) F_(0, 0) FM(VI4_HSYNC_N) F_(0, 0) FM(DU_DG2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_11_8 FM(A19) FM(LCDOUT11) F_(0, 0) F_(0, 0) FM(VI4_CLKENB) F_(0, 0) FM(DU_DG3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_15_12 FM(CS0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(VI5_CLKENB) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_19_16 FM(CS1_N_A26) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(VI5_CLK) F_(0, 0) FM(EX_WAIT0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_23_20 FM(BS_N) FM(QSTVA_QVS) FM(MSIOF3_SCK_D) FM(SCK3) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN1_TX) FM(CANFD1_TX) FM(IETX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_27_24 FM(RD_N) F_(0, 0) FM(MSIOF3_SYNC_D) FM(RX3_A) FM(HRX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_TX_A) FM(CANFD0_TX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP4_31_28 FM(RD_WR_N) F_(0, 0) FM(MSIOF3_RXD_D) FM(TX3_A) FM(HTX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_RX_A) FM(CANFD0_RX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_3_0 FM(WE0_N) F_(0, 0) FM(MSIOF3_TXD_D) FM(CTS3_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) FM(SCL6_B) FM(CAN_CLK) F_(0, 0) FM(IECLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_7_4 FM(WE1_N) F_(0, 0) FM(MSIOF3_SS1_D) FM(RTS3_N_TANS) FM(HRTS3_N) F_(0, 0) F_(0, 0) FM(SDA6_B) FM(CAN1_RX) FM(CANFD1_RX) FM(IERX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_11_8 FM(EX_WAIT0_A) FM(QCLK) F_(0, 0) F_(0, 0) FM(VI4_CLK) F_(0, 0) FM(DU_DOTCLKOUT0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_15_12 FM(D0) FM(MSIOF2_SS1_B)FM(MSIOF3_SCK_A) F_(0, 0) FM(VI4_DATA16) FM(VI5_DATA0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_19_16 FM(D1) FM(MSIOF2_SS2_B)FM(MSIOF3_SYNC_A) F_(0, 0) FM(VI4_DATA17) FM(VI5_DATA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_23_20 FM(D2) F_(0, 0) FM(MSIOF3_RXD_A) F_(0, 0) FM(VI4_DATA18) FM(VI5_DATA2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_27_24 FM(D3) F_(0, 0) FM(MSIOF3_TXD_A) F_(0, 0) FM(VI4_DATA19) FM(VI5_DATA3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_31_28 FM(D4) FM(MSIOF2_SCK_B)F_(0, 0) F_(0, 0) FM(VI4_DATA20) FM(VI5_DATA4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_3_0 FM(D5) FM(MSIOF2_SYNC_B)F_(0, 0) F_(0, 0) FM(VI4_DATA21) FM(VI5_DATA5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_7_4 FM(D6) FM(MSIOF2_RXD_B)F_(0, 0) F_(0, 0) FM(VI4_DATA22) FM(VI5_DATA6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_11_8 FM(D7) FM(MSIOF2_TXD_B)F_(0, 0) F_(0, 0) FM(VI4_DATA23) FM(VI5_DATA7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_15_12 FM(D8) FM(LCDOUT0) FM(MSIOF2_SCK_D) FM(SCK4_C) FM(VI4_DATA0_A) F_(0, 0) FM(DU_DR0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_19_16 FM(D9) FM(LCDOUT1) FM(MSIOF2_SYNC_D) F_(0, 0) FM(VI4_DATA1_A) F_(0, 0) FM(DU_DR1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_23_20 FM(D10) FM(LCDOUT2) FM(MSIOF2_RXD_D) FM(HRX3_B) FM(VI4_DATA2_A) FM(CTS4_N_C) FM(DU_DR2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_27_24 FM(D11) FM(LCDOUT3) FM(MSIOF2_TXD_D) FM(HTX3_B) FM(VI4_DATA3_A) FM(RTS4_N_TANS_C)FM(DU_DR3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP6_31_28 FM(D12) FM(LCDOUT4) FM(MSIOF2_SS1_D) FM(RX4_C) FM(VI4_DATA4_A) F_(0, 0) FM(DU_DR4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_3_0 FM(D13) FM(LCDOUT5) FM(MSIOF2_SS2_D) FM(TX4_C) FM(VI4_DATA5_A) F_(0, 0) FM(DU_DR5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_7_4 FM(D14) FM(LCDOUT6) FM(MSIOF3_SS1_A) FM(HRX3_C) FM(VI4_DATA6_A) F_(0, 0) FM(DU_DR6) FM(SCL6_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_11_8 FM(D15) FM(LCDOUT7) FM(MSIOF3_SS2_A) FM(HTX3_C) FM(VI4_DATA7_A) F_(0, 0) FM(DU_DR7) FM(SDA6_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_15_12 FM(FSCLKST) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_19_16 FM(SD0_CLK) F_(0, 0) FM(MSIOF1_SCK_E) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_OPWM_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */
+#define IP7_23_20 FM(SD0_CMD) F_(0, 0) FM(MSIOF1_SYNC_E) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_IVCXO27_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_27_24 FM(SD0_DAT0) F_(0, 0) FM(MSIOF1_RXD_E) F_(0, 0) F_(0, 0) FM(TS_SCK0_B) FM(STP_ISCLK_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP7_31_28 FM(SD0_DAT1) F_(0, 0) FM(MSIOF1_TXD_E) F_(0, 0) F_(0, 0) FM(TS_SPSYNC0_B)FM(STP_ISSYNC_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_3_0 FM(SD0_DAT2) F_(0, 0) FM(MSIOF1_SS1_E) F_(0, 0) F_(0, 0) FM(TS_SDAT0_B) FM(STP_ISD_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_7_4 FM(SD0_DAT3) F_(0, 0) FM(MSIOF1_SS2_E) F_(0, 0) F_(0, 0) FM(TS_SDEN0_B) FM(STP_ISEN_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_11_8 FM(SD1_CLK) F_(0, 0) FM(MSIOF1_SCK_G) F_(0, 0) F_(0, 0) FM(SIM0_CLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_15_12 FM(SD1_CMD) F_(0, 0) FM(MSIOF1_SYNC_G) F_(0, 0) F_(0, 0) FM(SIM0_D_A) FM(STP_IVCXO27_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_19_16 FM(SD1_DAT0) FM(SD2_DAT4) FM(MSIOF1_RXD_G) F_(0, 0) F_(0, 0) FM(TS_SCK1_B) FM(STP_ISCLK_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_23_20 FM(SD1_DAT1) FM(SD2_DAT5) FM(MSIOF1_TXD_G) F_(0, 0) F_(0, 0) FM(TS_SPSYNC1_B)FM(STP_ISSYNC_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_27_24 FM(SD1_DAT2) FM(SD2_DAT6) FM(MSIOF1_SS1_G) F_(0, 0) F_(0, 0) FM(TS_SDAT1_B) FM(STP_ISD_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_31_28 FM(SD1_DAT3) FM(SD2_DAT7) FM(MSIOF1_SS2_G) F_(0, 0) F_(0, 0) FM(TS_SDEN1_B) FM(STP_ISEN_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_3_0 FM(SD2_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_7_4 FM(SD2_DAT0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_11_8 FM(SD2_DAT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_15_12 FM(SD2_DAT2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_19_16 FM(SD2_DAT3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_23_20 FM(SD2_DS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SATA_DEVSLP_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_27_24 FM(SD3_DAT4) FM(SD2_CD_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_31_28 FM(SD3_DAT5) FM(SD2_WP_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_3_0 FM(SD3_DAT6) FM(SD3_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_7_4 FM(SD3_DAT7) FM(SD3_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_11_8 FM(SD0_CD) F_(0, 0) F_(0, 0) F_(0, 0) FM(SCL2_B) FM(SIM0_RST_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_15_12 FM(SD0_WP) F_(0, 0) F_(0, 0) F_(0, 0) FM(SDA2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_19_16 FM(SD1_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SIM0_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_23_20 FM(SD1_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SIM0_D_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_27_24 FM(SCK0) FM(HSCK1_B) FM(MSIOF1_SS2_B) FM(AUDIO_CLKC_B) FM(SDA2_A) FM(SIM0_RST_B) FM(STP_OPWM_0_C) FM(RIF0_CLK_B) F_(0, 0) FM(ADICHS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP10_31_28 FM(RX0) FM(HRX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SCK0_C) FM(STP_ISCLK_0_C) FM(RIF0_D0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_3_0 FM(TX0) FM(HTX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SPSYNC0_C)FM(STP_ISSYNC_0_C) FM(RIF0_D1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_7_4 FM(CTS0_N) FM(HCTS1_N_B) FM(MSIOF1_SYNC_B) F_(0, 0) F_(0, 0) FM(TS_SPSYNC1_C)FM(STP_ISSYNC_1_C) FM(RIF1_SYNC_B) FM(AUDIO_CLKOUT_C) FM(ADICS_SAMP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_11_8 FM(RTS0_N_TANS) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) F_(0, 0) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_15_12 FM(RX1_A) FM(HRX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDAT0_C) FM(STP_ISD_0_C) FM(RIF1_CLK_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_19_16 FM(TX1_A) FM(HTX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDEN0_C) FM(STP_ISEN_0_C) FM(RIF1_D0_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_23_20 FM(CTS1_N) FM(HCTS1_N_A) FM(MSIOF1_RXD_B) F_(0, 0) F_(0, 0) FM(TS_SDEN1_C) FM(STP_ISEN_1_C) FM(RIF1_D0_B) F_(0, 0) FM(ADIDATA) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_27_24 FM(RTS1_N_TANS) FM(HRTS1_N_A) FM(MSIOF1_TXD_B) F_(0, 0) F_(0, 0) FM(TS_SDAT1_C) FM(STP_ISD_1_C) FM(RIF1_D1_B) F_(0, 0) FM(ADICHS0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP11_31_28 FM(SCK2) FM(SCIF_CLK_B) FM(MSIOF1_SCK_B) F_(0, 0) F_(0, 0) FM(TS_SCK1_C) FM(STP_ISCLK_1_C) FM(RIF1_CLK_B) F_(0, 0) FM(ADICLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_3_0 FM(TX2_A) F_(0, 0) F_(0, 0) FM(SD2_CD_B) FM(SCL1_A) F_(0, 0) FM(FMCLK_A) FM(RIF1_D1_C) F_(0, 0) FM(FSO_CFE_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_7_4 FM(RX2_A) F_(0, 0) F_(0, 0) FM(SD2_WP_B) FM(SDA1_A) F_(0, 0) FM(FMIN_A) FM(RIF1_SYNC_C) F_(0, 0) FM(FSO_CFE_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_11_8 FM(HSCK0) F_(0, 0) FM(MSIOF1_SCK_D) FM(AUDIO_CLKB_A) FM(SSI_SDATA1_B)FM(TS_SCK0_D) FM(STP_ISCLK_0_D) FM(RIF0_CLK_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_15_12 FM(HRX0) F_(0, 0) FM(MSIOF1_RXD_D) F_(0, 0) FM(SSI_SDATA2_B)FM(TS_SDEN0_D) FM(STP_ISEN_0_D) FM(RIF0_D0_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_19_16 FM(HTX0) F_(0, 0) FM(MSIOF1_TXD_D) F_(0, 0) FM(SSI_SDATA9_B)FM(TS_SDAT0_D) FM(STP_ISD_0_D) FM(RIF0_D1_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_23_20 FM(HCTS0_N) FM(RX2_B) FM(MSIOF1_SYNC_D) F_(0, 0) FM(SSI_SCK9_A) FM(TS_SPSYNC0_D)FM(STP_ISSYNC_0_D) FM(RIF0_SYNC_C) FM(AUDIO_CLKOUT1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_27_24 FM(HRTS0_N) FM(TX2_B) FM(MSIOF1_SS1_D) F_(0, 0) FM(SSI_WS9_A) F_(0, 0) FM(STP_IVCXO27_0_D) FM(BPFCLK_A) FM(AUDIO_CLKOUT2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */
+#define IP12_31_28 FM(MSIOF0_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_3_0 FM(MSIOF0_SS1) FM(RX5) F_(0, 0) FM(AUDIO_CLKA_C) FM(SSI_SCK2_A) F_(0, 0) FM(STP_IVCXO27_0_C) F_(0, 0) FM(AUDIO_CLKOUT3_A) F_(0, 0) FM(TCLK1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_7_4 FM(MSIOF0_SS2) FM(TX5) FM(MSIOF1_SS2_D) FM(AUDIO_CLKC_A) FM(SSI_WS2_A) F_(0, 0) FM(STP_OPWM_0_D) F_(0, 0) FM(AUDIO_CLKOUT_D) F_(0, 0) FM(SPEEDIN_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_11_8 FM(MLB_CLK) F_(0, 0) FM(MSIOF1_SCK_F) F_(0, 0) FM(SCL1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_15_12 FM(MLB_SIG) FM(RX1_B) FM(MSIOF1_SYNC_F) F_(0, 0) FM(SDA1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_19_16 FM(MLB_DAT) FM(TX1_B) FM(MSIOF1_RXD_F) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_23_20 FM(SSI_SCK0129) F_(0, 0) FM(MSIOF1_TXD_F) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_27_24 FM(SSI_WS0129) F_(0, 0) FM(MSIOF1_SS1_F) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_31_28 FM(SSI_SDATA0) F_(0, 0) FM(MSIOF1_SS2_F) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_3_0 FM(SSI_SDATA1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_7_4 FM(SSI_SDATA2_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(SSI_SCK1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_11_8 FM(SSI_SCK34) F_(0, 0) FM(MSIOF1_SS1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_OPWM_0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_15_12 FM(SSI_WS34) FM(HCTS2_N_A) FM(MSIOF1_SS2_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_IVCXO27_0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_19_16 FM(SSI_SDATA3) FM(HRTS2_N_A) FM(MSIOF1_TXD_A) F_(0, 0) F_(0, 0) FM(TS_SCK0_A) FM(STP_ISCLK_0_A) FM(RIF0_D1_A) FM(RIF2_D0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_23_20 FM(SSI_SCK4) FM(HRX2_A) FM(MSIOF1_SCK_A) F_(0, 0) F_(0, 0) FM(TS_SDAT0_A) FM(STP_ISD_0_A) FM(RIF0_CLK_A) FM(RIF2_CLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_27_24 FM(SSI_WS4) FM(HTX2_A) FM(MSIOF1_SYNC_A) F_(0, 0) F_(0, 0) FM(TS_SDEN0_A) FM(STP_ISEN_0_A) FM(RIF0_SYNC_A) FM(RIF2_SYNC_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP14_31_28 FM(SSI_SDATA4) FM(HSCK2_A) FM(MSIOF1_RXD_A) F_(0, 0) F_(0, 0) FM(TS_SPSYNC0_A)FM(STP_ISSYNC_0_A) FM(RIF0_D0_A) FM(RIF2_D1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_3_0 FM(SSI_SCK6) FM(USB2_PWEN) F_(0, 0) FM(SIM0_RST_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_7_4 FM(SSI_WS6) FM(USB2_OVC) F_(0, 0) FM(SIM0_D_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_11_8 FM(SSI_SDATA6) F_(0, 0) F_(0, 0) FM(SIM0_CLK_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SATA_DEVSLP_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_15_12 FM(SSI_SCK78) FM(HRX2_B) FM(MSIOF1_SCK_C) F_(0, 0) F_(0, 0) FM(TS_SCK1_A) FM(STP_ISCLK_1_A) FM(RIF1_CLK_A) FM(RIF3_CLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_19_16 FM(SSI_WS78) FM(HTX2_B) FM(MSIOF1_SYNC_C) F_(0, 0) F_(0, 0) FM(TS_SDAT1_A) FM(STP_ISD_1_A) FM(RIF1_SYNC_A) FM(RIF3_SYNC_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_23_20 FM(SSI_SDATA7) FM(HCTS2_N_B) FM(MSIOF1_RXD_C) F_(0, 0) F_(0, 0) FM(TS_SDEN1_A) FM(STP_ISEN_1_A) FM(RIF1_D0_A) FM(RIF3_D0_A) F_(0, 0) FM(TCLK2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_27_24 FM(SSI_SDATA8) FM(HRTS2_N_B) FM(MSIOF1_TXD_C) F_(0, 0) F_(0, 0) FM(TS_SPSYNC1_A)FM(STP_ISSYNC_1_A) FM(RIF1_D1_A) FM(RIF3_D1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP15_31_28 FM(SSI_SDATA9_A) FM(HSCK2_B) FM(MSIOF1_SS1_C) FM(HSCK1_A) FM(SSI_WS1_B) FM(SCK1) FM(STP_IVCXO27_1_A) FM(SCK5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_3_0 FM(AUDIO_CLKA_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_7_4 FM(AUDIO_CLKB_B) FM(SCIF_CLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_IVCXO27_1_D) FM(REMOCON_A) F_(0, 0) F_(0, 0) FM(TCLK1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_11_8 FM(USB0_PWEN) F_(0, 0) F_(0, 0) FM(SIM0_RST_C) F_(0, 0) FM(TS_SCK1_D) FM(STP_ISCLK_1_D) FM(BPFCLK_B) FM(RIF3_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_15_12 FM(USB0_OVC) F_(0, 0) F_(0, 0) FM(SIM0_D_C) F_(0, 0) FM(TS_SDAT1_D) FM(STP_ISD_1_D) F_(0, 0) FM(RIF3_SYNC_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_19_16 FM(USB1_PWEN) F_(0, 0) F_(0, 0) FM(SIM0_CLK_C) FM(SSI_SCK1_A) FM(TS_SCK0_E) FM(STP_ISCLK_0_E) FM(FMCLK_B) FM(RIF2_CLK_B) F_(0, 0) FM(SPEEDIN_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_23_20 FM(USB1_OVC) F_(0, 0) FM(MSIOF1_SS2_C) F_(0, 0) FM(SSI_WS1_A) FM(TS_SDAT0_E) FM(STP_ISD_0_E) FM(FMIN_B) FM(RIF2_SYNC_B) F_(0, 0) FM(REMOCON_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_27_24 FM(USB30_PWEN) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT_B) FM(SSI_SCK2_B) FM(TS_SDEN1_D) FM(STP_ISEN_1_D) FM(STP_OPWM_0_E)FM(RIF3_D0_B) F_(0, 0) FM(TCLK2_B) FM(TPU0TO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP16_31_28 FM(USB30_OVC) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT1_B) FM(SSI_WS2_B) FM(TS_SPSYNC1_D)FM(STP_ISSYNC_1_D) FM(STP_IVCXO27_0_E)FM(RIF3_D1_B) F_(0, 0) FM(FSO_TOE_B) FM(TPU0TO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP17_3_0 FM(USB31_PWEN) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT2_B) FM(SSI_SCK9_B) FM(TS_SDEN0_E) FM(STP_ISEN_0_E) F_(0, 0) FM(RIF2_D0_B) F_(0, 0) F_(0, 0) FM(TPU0TO2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP17_7_4 FM(USB31_OVC) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT3_B) FM(SSI_WS9_B) FM(TS_SPSYNC0_E)FM(STP_ISSYNC_0_E) F_(0, 0) FM(RIF2_D1_B) F_(0, 0) F_(0, 0) FM(TPU0TO3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+#define PINMUX_GPSR \
+\
+ GPSR6_31 \
+ GPSR6_30 \
+ GPSR6_29 \
+ GPSR6_28 \
+ GPSR1_27 GPSR6_27 \
+ GPSR1_26 GPSR6_26 \
+ GPSR1_25 GPSR5_25 GPSR6_25 \
+ GPSR1_24 GPSR5_24 GPSR6_24 \
+ GPSR1_23 GPSR5_23 GPSR6_23 \
+ GPSR1_22 GPSR5_22 GPSR6_22 \
+ GPSR1_21 GPSR5_21 GPSR6_21 \
+ GPSR1_20 GPSR5_20 GPSR6_20 \
+ GPSR1_19 GPSR5_19 GPSR6_19 \
+ GPSR1_18 GPSR5_18 GPSR6_18 \
+ GPSR1_17 GPSR4_17 GPSR5_17 GPSR6_17 \
+ GPSR1_16 GPSR4_16 GPSR5_16 GPSR6_16 \
+GPSR0_15 GPSR1_15 GPSR3_15 GPSR4_15 GPSR5_15 GPSR6_15 \
+GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR4_14 GPSR5_14 GPSR6_14 \
+GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR4_13 GPSR5_13 GPSR6_13 \
+GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR4_12 GPSR5_12 GPSR6_12 \
+GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR4_11 GPSR5_11 GPSR6_11 \
+GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR4_10 GPSR5_10 GPSR6_10 \
+GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR4_9 GPSR5_9 GPSR6_9 \
+GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR4_8 GPSR5_8 GPSR6_8 \
+GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR4_7 GPSR5_7 GPSR6_7 \
+GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR4_6 GPSR5_6 GPSR6_6 \
+GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 GPSR6_5 \
+GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 GPSR6_4 \
+GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 GPSR6_3 GPSR7_3 \
+GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 GPSR6_2 GPSR7_2 \
+GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 GPSR6_1 GPSR7_1 \
+GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0 GPSR6_0 GPSR7_0
+
+#define PINMUX_IPSR \
+\
+FM(IP0_3_0) IP0_3_0 FM(IP1_3_0) IP1_3_0 FM(IP2_3_0) IP2_3_0 FM(IP3_3_0) IP3_3_0 \
+FM(IP0_7_4) IP0_7_4 FM(IP1_7_4) IP1_7_4 FM(IP2_7_4) IP2_7_4 FM(IP3_7_4) IP3_7_4 \
+FM(IP0_11_8) IP0_11_8 FM(IP1_11_8) IP1_11_8 FM(IP2_11_8) IP2_11_8 FM(IP3_11_8) IP3_11_8 \
+FM(IP0_15_12) IP0_15_12 FM(IP1_15_12) IP1_15_12 FM(IP2_15_12) IP2_15_12 FM(IP3_15_12) IP3_15_12 \
+FM(IP0_19_16) IP0_19_16 FM(IP1_19_16) IP1_19_16 FM(IP2_19_16) IP2_19_16 FM(IP3_19_16) IP3_19_16 \
+FM(IP0_23_20) IP0_23_20 FM(IP1_23_20) IP1_23_20 FM(IP2_23_20) IP2_23_20 FM(IP3_23_20) IP3_23_20 \
+FM(IP0_27_24) IP0_27_24 FM(IP1_27_24) IP1_27_24 FM(IP2_27_24) IP2_27_24 FM(IP3_27_24) IP3_27_24 \
+FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_31_28) IP3_31_28 \
+\
+FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \
+FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \
+FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \
+FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \
+FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \
+FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \
+FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \
+FM(IP4_31_28) IP4_31_28 FM(IP5_31_28) IP5_31_28 FM(IP6_31_28) IP6_31_28 FM(IP7_31_28) IP7_31_28 \
+\
+FM(IP8_3_0) IP8_3_0 FM(IP9_3_0) IP9_3_0 FM(IP10_3_0) IP10_3_0 FM(IP11_3_0) IP11_3_0 \
+FM(IP8_7_4) IP8_7_4 FM(IP9_7_4) IP9_7_4 FM(IP10_7_4) IP10_7_4 FM(IP11_7_4) IP11_7_4 \
+FM(IP8_11_8) IP8_11_8 FM(IP9_11_8) IP9_11_8 FM(IP10_11_8) IP10_11_8 FM(IP11_11_8) IP11_11_8 \
+FM(IP8_15_12) IP8_15_12 FM(IP9_15_12) IP9_15_12 FM(IP10_15_12) IP10_15_12 FM(IP11_15_12) IP11_15_12 \
+FM(IP8_19_16) IP8_19_16 FM(IP9_19_16) IP9_19_16 FM(IP10_19_16) IP10_19_16 FM(IP11_19_16) IP11_19_16 \
+FM(IP8_23_20) IP8_23_20 FM(IP9_23_20) IP9_23_20 FM(IP10_23_20) IP10_23_20 FM(IP11_23_20) IP11_23_20 \
+FM(IP8_27_24) IP8_27_24 FM(IP9_27_24) IP9_27_24 FM(IP10_27_24) IP10_27_24 FM(IP11_27_24) IP11_27_24 \
+FM(IP8_31_28) IP8_31_28 FM(IP9_31_28) IP9_31_28 FM(IP10_31_28) IP10_31_28 FM(IP11_31_28) IP11_31_28 \
+\
+FM(IP12_3_0) IP12_3_0 FM(IP13_3_0) IP13_3_0 FM(IP14_3_0) IP14_3_0 FM(IP15_3_0) IP15_3_0 \
+FM(IP12_7_4) IP12_7_4 FM(IP13_7_4) IP13_7_4 FM(IP14_7_4) IP14_7_4 FM(IP15_7_4) IP15_7_4 \
+FM(IP12_11_8) IP12_11_8 FM(IP13_11_8) IP13_11_8 FM(IP14_11_8) IP14_11_8 FM(IP15_11_8) IP15_11_8 \
+FM(IP12_15_12) IP12_15_12 FM(IP13_15_12) IP13_15_12 FM(IP14_15_12) IP14_15_12 FM(IP15_15_12) IP15_15_12 \
+FM(IP12_19_16) IP12_19_16 FM(IP13_19_16) IP13_19_16 FM(IP14_19_16) IP14_19_16 FM(IP15_19_16) IP15_19_16 \
+FM(IP12_23_20) IP12_23_20 FM(IP13_23_20) IP13_23_20 FM(IP14_23_20) IP14_23_20 FM(IP15_23_20) IP15_23_20 \
+FM(IP12_27_24) IP12_27_24 FM(IP13_27_24) IP13_27_24 FM(IP14_27_24) IP14_27_24 FM(IP15_27_24) IP15_27_24 \
+FM(IP12_31_28) IP12_31_28 FM(IP13_31_28) IP13_31_28 FM(IP14_31_28) IP14_31_28 FM(IP15_31_28) IP15_31_28 \
+\
+FM(IP16_3_0) IP16_3_0 FM(IP17_3_0) IP17_3_0 \
+FM(IP16_7_4) IP16_7_4 FM(IP17_7_4) IP17_7_4 \
+FM(IP16_11_8) IP16_11_8 \
+FM(IP16_15_12) IP16_15_12 \
+FM(IP16_19_16) IP16_19_16 \
+FM(IP16_23_20) IP16_23_20 \
+FM(IP16_27_24) IP16_27_24 \
+FM(IP16_31_28) IP16_31_28
+
+/* MOD_SEL0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */
+#define MOD_SEL0_30_29 FM(SEL_MSIOF3_0) FM(SEL_MSIOF3_1) FM(SEL_MSIOF3_2) FM(SEL_MSIOF3_3)
+#define MOD_SEL0_28_27 FM(SEL_MSIOF2_0) FM(SEL_MSIOF2_1) FM(SEL_MSIOF2_2) FM(SEL_MSIOF2_3)
+#define MOD_SEL0_26_25_24 FM(SEL_MSIOF1_0) FM(SEL_MSIOF1_1) FM(SEL_MSIOF1_2) FM(SEL_MSIOF1_3) FM(SEL_MSIOF1_4) FM(SEL_MSIOF1_5) FM(SEL_MSIOF1_6) F_(0, 0)
+#define MOD_SEL0_23 FM(SEL_LBSC_0) FM(SEL_LBSC_1)
+#define MOD_SEL0_22 FM(SEL_IEBUS_0) FM(SEL_IEBUS_1)
+#define MOD_SEL0_21_20 FM(SEL_I2C6_0) FM(SEL_I2C6_1) FM(SEL_I2C6_2) F_(0, 0)
+#define MOD_SEL0_19 FM(SEL_I2C2_0) FM(SEL_I2C2_1)
+#define MOD_SEL0_18 FM(SEL_I2C1_0) FM(SEL_I2C1_1)
+#define MOD_SEL0_17 FM(SEL_HSCIF4_0) FM(SEL_HSCIF4_1)
+#define MOD_SEL0_16_15 FM(SEL_HSCIF3_0) FM(SEL_HSCIF3_1) FM(SEL_HSCIF3_2) FM(SEL_HSCIF3_3)
+#define MOD_SEL0_14 FM(SEL_HSCIF2_0) FM(SEL_HSCIF2_1)
+#define MOD_SEL0_13 FM(SEL_HSCIF1_0) FM(SEL_HSCIF1_1)
+#define MOD_SEL0_12 FM(SEL_FSO_0) FM(SEL_FSO_1)
+#define MOD_SEL0_11 FM(SEL_FM_0) FM(SEL_FM_1)
+#define MOD_SEL0_10 FM(SEL_ETHERAVB_0) FM(SEL_ETHERAVB_1)
+#define MOD_SEL0_9 FM(SEL_DRIF3_0) FM(SEL_DRIF3_1)
+#define MOD_SEL0_8 FM(SEL_DRIF2_0) FM(SEL_DRIF2_1)
+#define MOD_SEL0_7_6 FM(SEL_DRIF1_0) FM(SEL_DRIF1_1) FM(SEL_DRIF1_2) F_(0, 0)
+#define MOD_SEL0_5_4 FM(SEL_DRIF0_0) FM(SEL_DRIF0_1) FM(SEL_DRIF0_2) F_(0, 0)
+#define MOD_SEL0_3 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1)
+#define MOD_SEL0_2_1 FM(SEL_ADG_0) FM(SEL_ADG_1) FM(SEL_ADG_2) FM(SEL_ADG_3)
+
+/* MOD_SEL1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */
+#define MOD_SEL1_31_30 FM(SEL_TSIF1_0) FM(SEL_TSIF1_1) FM(SEL_TSIF1_2) FM(SEL_TSIF1_3)
+#define MOD_SEL1_29_28_27 FM(SEL_TSIF0_0) FM(SEL_TSIF0_1) FM(SEL_TSIF0_2) FM(SEL_TSIF0_3) FM(SEL_TSIF0_4) F_(0, 0) F_(0, 0) F_(0, 0)
+#define MOD_SEL1_26 FM(SEL_TIMER_TMU_0) FM(SEL_TIMER_TMU_1)
+#define MOD_SEL1_25_24 FM(SEL_SSP1_1_0) FM(SEL_SSP1_1_1) FM(SEL_SSP1_1_2) FM(SEL_SSP1_1_3)
+#define MOD_SEL1_23_22_21 FM(SEL_SSP1_0_0) FM(SEL_SSP1_0_1) FM(SEL_SSP1_0_2) FM(SEL_SSP1_0_3) FM(SEL_SSP1_0_4) F_(0, 0) F_(0, 0) F_(0, 0)
+#define MOD_SEL1_20 FM(SEL_SSI_0) FM(SEL_SSI_1)
+#define MOD_SEL1_19 FM(SEL_SPEED_PULSE_0) FM(SEL_SPEED_PULSE_1)
+#define MOD_SEL1_18_17 FM(SEL_SIMCARD_0) FM(SEL_SIMCARD_1) FM(SEL_SIMCARD_2) FM(SEL_SIMCARD_3)
+#define MOD_SEL1_16 FM(SEL_SDHI2_0) FM(SEL_SDHI2_1)
+#define MOD_SEL1_15_14 FM(SEL_SCIF4_0) FM(SEL_SCIF4_1) FM(SEL_SCIF4_2) F_(0, 0)
+#define MOD_SEL1_13 FM(SEL_SCIF3_0) FM(SEL_SCIF3_1)
+#define MOD_SEL1_12 FM(SEL_SCIF2_0) FM(SEL_SCIF2_1)
+#define MOD_SEL1_11 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1)
+#define MOD_SEL1_10 FM(SEL_SCIF_0) FM(SEL_SCIF_1)
+#define MOD_SEL1_9 FM(SEL_REMOCON_0) FM(SEL_REMOCON_1)
+#define MOD_SEL1_6 FM(SEL_RCAN0_0) FM(SEL_RCAN0_1)
+#define MOD_SEL1_5 FM(SEL_PWM6_0) FM(SEL_PWM6_1)
+#define MOD_SEL1_4 FM(SEL_PWM5_0) FM(SEL_PWM5_1)
+#define MOD_SEL1_3 FM(SEL_PWM4_0) FM(SEL_PWM4_1)
+#define MOD_SEL1_2 FM(SEL_PWM3_0) FM(SEL_PWM3_1)
+#define MOD_SEL1_1 FM(SEL_PWM2_0) FM(SEL_PWM2_1)
+#define MOD_SEL1_0 FM(SEL_PWM1_0) FM(SEL_PWM1_1)
+
+/* MOD_SEL2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */
+#define MOD_SEL2_31 FM(I2C_SEL_5_0) FM(I2C_SEL_5_1)
+#define MOD_SEL2_30 FM(I2C_SEL_3_0) FM(I2C_SEL_3_1)
+#define MOD_SEL2_29 FM(I2C_SEL_0_0) FM(I2C_SEL_0_1)
+#define MOD_SEL2_2_1 FM(SEL_VSP_0) FM(SEL_VSP_1) FM(SEL_VSP_2) FM(SEL_VSP_3)
+#define MOD_SEL2_0 FM(SEL_VIN4_0) FM(SEL_VIN4_1)
+
+#define PINMUX_MOD_SELS\
+\
+ MOD_SEL1_31_30 MOD_SEL2_31 \
+MOD_SEL0_30_29 MOD_SEL2_30 \
+ MOD_SEL1_29_28_27 MOD_SEL2_29 \
+MOD_SEL0_28_27 \
+\
+MOD_SEL0_26_25_24 MOD_SEL1_26 \
+ MOD_SEL1_25_24 \
+\
+MOD_SEL0_23 MOD_SEL1_23_22_21 \
+MOD_SEL0_22 \
+MOD_SEL0_21_20 \
+ MOD_SEL1_20 \
+MOD_SEL0_19 MOD_SEL1_19 \
+MOD_SEL0_18 MOD_SEL1_18_17 \
+MOD_SEL0_17 \
+MOD_SEL0_16_15 MOD_SEL1_16 \
+ MOD_SEL1_15_14 \
+MOD_SEL0_14 \
+MOD_SEL0_13 MOD_SEL1_13 \
+MOD_SEL0_12 MOD_SEL1_12 \
+MOD_SEL0_11 MOD_SEL1_11 \
+MOD_SEL0_10 MOD_SEL1_10 \
+MOD_SEL0_9 MOD_SEL1_9 \
+MOD_SEL0_8 \
+MOD_SEL0_7_6 \
+ MOD_SEL1_6 \
+MOD_SEL0_5_4 MOD_SEL1_5 \
+ MOD_SEL1_4 \
+MOD_SEL0_3 MOD_SEL1_3 \
+MOD_SEL0_2_1 MOD_SEL1_2 MOD_SEL2_2_1 \
+ MOD_SEL1_1 \
+ MOD_SEL1_0 MOD_SEL2_0
+
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ GP_ALL(DATA),
+ PINMUX_DATA_END,
+
+#define F_(x, y)
+#define FM(x) FN_##x,
+ PINMUX_FUNCTION_BEGIN,
+ GP_ALL(FN),
+ PINMUX_GPSR
+ PINMUX_IPSR
+ PINMUX_MOD_SELS
+ PINMUX_FUNCTION_END,
+#undef F_
+#undef FM
+
+#define F_(x, y)
+#define FM(x) x##_MARK,
+ PINMUX_MARK_BEGIN,
+ PINMUX_GPSR
+ PINMUX_IPSR
+ PINMUX_MOD_SELS
+ PINMUX_MARK_END,
+#undef F_
+#undef FM
+};
+
+static const u16 pinmux_data[] = {
+ PINMUX_DATA_GP_ALL(),
+
+ /* IPSR0 */
+ PINMUX_IPSR_DATA(IP0_3_0, AVB_MDC),
+ PINMUX_IPSR_MSEL(IP0_3_0, MSIOF2_SS2_C, SEL_MSIOF2_2),
+
+ PINMUX_IPSR_DATA(IP0_7_4, AVB_MAGIC),
+ PINMUX_IPSR_MSEL(IP0_7_4, MSIOF2_SS1_C, SEL_MSIOF2_2),
+ PINMUX_IPSR_MSEL(IP0_7_4, SCK4_A, SEL_SCIF4_0),
+
+ PINMUX_IPSR_DATA(IP0_11_8, AVB_PHY_INT),
+ PINMUX_IPSR_MSEL(IP0_11_8, MSIOF2_SYNC_C, SEL_MSIOF2_2),
+ PINMUX_IPSR_MSEL(IP0_11_8, RX4_A, SEL_SCIF4_0),
+
+ PINMUX_IPSR_DATA(IP0_15_12, AVB_LINK),
+ PINMUX_IPSR_MSEL(IP0_15_12, MSIOF2_SCK_C, SEL_MSIOF2_2),
+ PINMUX_IPSR_MSEL(IP0_15_12, TX4_A, SEL_SCIF4_0),
+
+ PINMUX_IPSR_MSEL(IP0_19_16, AVB_AVTP_MATCH_A, SEL_ETHERAVB_0),
+ PINMUX_IPSR_MSEL(IP0_19_16, MSIOF2_RXD_C, SEL_MSIOF2_2),
+ PINMUX_IPSR_MSEL(IP0_19_16, CTS4_N_A, SEL_SCIF4_0),
+
+ PINMUX_IPSR_MSEL(IP0_23_20, AVB_AVTP_CAPTURE_A, SEL_ETHERAVB_0),
+ PINMUX_IPSR_MSEL(IP0_23_20, MSIOF2_TXD_C, SEL_MSIOF2_2),
+ PINMUX_IPSR_MSEL(IP0_23_20, RTS4_N_TANS_A, SEL_SCIF4_0),
+
+ PINMUX_IPSR_DATA(IP0_27_24, IRQ0),
+ PINMUX_IPSR_DATA(IP0_27_24, QPOLB),
+ PINMUX_IPSR_DATA(IP0_27_24, DU_CDE),
+ PINMUX_IPSR_MSEL(IP0_27_24, VI4_DATA0_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP0_27_24, CAN0_TX_B, SEL_RCAN0_1),
+ PINMUX_IPSR_MSEL(IP0_27_24, CANFD0_TX_B, SEL_CANFD0_1),
+
+ PINMUX_IPSR_DATA(IP0_31_28, IRQ1),
+ PINMUX_IPSR_DATA(IP0_31_28, QPOLA),
+ PINMUX_IPSR_DATA(IP0_31_28, DU_DISP),
+ PINMUX_IPSR_MSEL(IP0_31_28, VI4_DATA1_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP0_31_28, CAN0_RX_B, SEL_RCAN0_1),
+ PINMUX_IPSR_MSEL(IP0_31_28, CANFD0_RX_B, SEL_CANFD0_1),
+
+ /* IPSR1 */
+ PINMUX_IPSR_DATA(IP1_3_0, IRQ2),
+ PINMUX_IPSR_DATA(IP1_3_0, QCPV_QDE),
+ PINMUX_IPSR_DATA(IP1_3_0, DU_EXODDF_DU_ODDF_DISP_CDE),
+ PINMUX_IPSR_MSEL(IP1_3_0, VI4_DATA2_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP1_3_0, PWM3_B, SEL_PWM3_1),
+
+ PINMUX_IPSR_DATA(IP1_7_4, IRQ3),
+ PINMUX_IPSR_DATA(IP1_7_4, QSTVB_QVE),
+ PINMUX_IPSR_DATA(IP1_7_4, A25),
+ PINMUX_IPSR_DATA(IP1_7_4, DU_DOTCLKOUT1),
+ PINMUX_IPSR_MSEL(IP1_7_4, VI4_DATA3_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP1_7_4, PWM4_B, SEL_PWM4_1),
+
+ PINMUX_IPSR_DATA(IP1_11_8, IRQ4),
+ PINMUX_IPSR_DATA(IP1_11_8, QSTH_QHS),
+ PINMUX_IPSR_DATA(IP1_11_8, A24),
+ PINMUX_IPSR_DATA(IP1_11_8, DU_EXHSYNC_DU_HSYNC),
+ PINMUX_IPSR_MSEL(IP1_11_8, VI4_DATA4_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP1_11_8, PWM5_B, SEL_PWM5_1),
+
+ PINMUX_IPSR_DATA(IP1_15_12, IRQ5),
+ PINMUX_IPSR_DATA(IP1_15_12, QSTB_QHE),
+ PINMUX_IPSR_DATA(IP1_15_12, A23),
+ PINMUX_IPSR_DATA(IP1_15_12, DU_EXVSYNC_DU_VSYNC),
+ PINMUX_IPSR_MSEL(IP1_15_12, VI4_DATA5_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP1_15_12, PWM6_B, SEL_PWM6_1),
+
+ PINMUX_IPSR_DATA(IP1_19_16, PWM0),
+ PINMUX_IPSR_DATA(IP1_19_16, AVB_AVTP_PPS),
+ PINMUX_IPSR_DATA(IP1_19_16, A22),
+ PINMUX_IPSR_MSEL(IP1_19_16, VI4_DATA6_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP1_19_16, IECLK_B, SEL_IEBUS_1),
+
+ PINMUX_IPSR_MSEL(IP1_23_20, PWM1_A, SEL_PWM1_0),
+ PINMUX_IPSR_DATA(IP1_23_20, A21),
+ PINMUX_IPSR_MSEL(IP1_23_20, HRX3_D, SEL_HSCIF3_3),
+ PINMUX_IPSR_MSEL(IP1_23_20, VI4_DATA7_B, SEL_VIN4_1),
+ PINMUX_IPSR_MSEL(IP1_23_20, IERX_B, SEL_IEBUS_1),
+
+ PINMUX_IPSR_MSEL(IP1_27_24, PWM2_A, SEL_PWM2_0),
+ PINMUX_IPSR_DATA(IP1_27_24, A20),
+ PINMUX_IPSR_MSEL(IP1_27_24, HTX3_D, SEL_HSCIF3_3),
+ PINMUX_IPSR_MSEL(IP1_27_24, IETX_B, SEL_IEBUS_1),
+
+ PINMUX_IPSR_DATA(IP1_31_28, A0),
+ PINMUX_IPSR_DATA(IP1_31_28, LCDOUT16),
+ PINMUX_IPSR_MSEL(IP1_31_28, MSIOF3_SYNC_B, SEL_MSIOF3_1),
+ PINMUX_IPSR_DATA(IP1_31_28, VI4_DATA8),
+ PINMUX_IPSR_DATA(IP1_31_28, DU_DB0),
+ PINMUX_IPSR_MSEL(IP1_31_28, PWM3_A, SEL_PWM3_0),
+
+ /* IPSR2 */
+ PINMUX_IPSR_DATA(IP2_3_0, A1),
+ PINMUX_IPSR_DATA(IP2_3_0, LCDOUT17),
+ PINMUX_IPSR_MSEL(IP2_3_0, MSIOF3_TXD_B, SEL_MSIOF3_1),
+ PINMUX_IPSR_DATA(IP2_3_0, VI4_DATA9),
+ PINMUX_IPSR_DATA(IP2_3_0, DU_DB1),
+ PINMUX_IPSR_MSEL(IP2_3_0, PWM4_A, SEL_PWM4_0),
+
+ PINMUX_IPSR_DATA(IP2_7_4, A2),
+ PINMUX_IPSR_DATA(IP2_7_4, LCDOUT18),
+ PINMUX_IPSR_MSEL(IP2_7_4, MSIOF3_SCK_B, SEL_MSIOF3_1),
+ PINMUX_IPSR_DATA(IP2_7_4, VI4_DATA10),
+ PINMUX_IPSR_DATA(IP2_7_4, DU_DB2),
+ PINMUX_IPSR_MSEL(IP2_7_4, PWM5_A, SEL_PWM5_0),
+
+ PINMUX_IPSR_DATA(IP2_11_8, A3),
+ PINMUX_IPSR_DATA(IP2_11_8, LCDOUT19),
+ PINMUX_IPSR_MSEL(IP2_11_8, MSIOF3_RXD_B, SEL_MSIOF3_1),
+ PINMUX_IPSR_DATA(IP2_11_8, VI4_DATA11),
+ PINMUX_IPSR_DATA(IP2_11_8, DU_DB3),
+ PINMUX_IPSR_MSEL(IP2_11_8, PWM6_A, SEL_PWM6_0),
+
+ PINMUX_IPSR_DATA(IP2_15_12, A4),
+ PINMUX_IPSR_DATA(IP2_15_12, LCDOUT20),
+ PINMUX_IPSR_MSEL(IP2_15_12, MSIOF3_SS1_B, SEL_MSIOF3_1),
+ PINMUX_IPSR_DATA(IP2_15_12, VI4_DATA12),
+ PINMUX_IPSR_DATA(IP2_15_12, VI5_DATA12),
+ PINMUX_IPSR_DATA(IP2_15_12, DU_DB4),
+
+ PINMUX_IPSR_DATA(IP2_19_16, A5),
+ PINMUX_IPSR_DATA(IP2_19_16, LCDOUT21),
+ PINMUX_IPSR_MSEL(IP2_19_16, MSIOF3_SS2_B, SEL_MSIOF3_1),
+ PINMUX_IPSR_MSEL(IP2_19_16, SCK4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_DATA(IP2_19_16, VI4_DATA13),
+ PINMUX_IPSR_DATA(IP2_19_16, VI5_DATA13),
+ PINMUX_IPSR_DATA(IP2_19_16, DU_DB5),
+
+ PINMUX_IPSR_DATA(IP2_23_20, A6),
+ PINMUX_IPSR_DATA(IP2_23_20, LCDOUT22),
+ PINMUX_IPSR_MSEL(IP2_23_20, MSIOF2_SS1_A, SEL_MSIOF2_0),
+ PINMUX_IPSR_MSEL(IP2_23_20, RX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_DATA(IP2_23_20, VI4_DATA14),
+ PINMUX_IPSR_DATA(IP2_23_20, VI5_DATA14),
+ PINMUX_IPSR_DATA(IP2_23_20, DU_DB6),
+
+ PINMUX_IPSR_DATA(IP2_27_24, A7),
+ PINMUX_IPSR_DATA(IP2_27_24, LCDOUT23),
+ PINMUX_IPSR_MSEL(IP2_27_24, MSIOF2_SS2_A, SEL_MSIOF2_0),
+ PINMUX_IPSR_MSEL(IP2_27_24, TX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_DATA(IP2_27_24, VI4_DATA15),
+ PINMUX_IPSR_DATA(IP2_27_24, VI5_DATA15),
+ PINMUX_IPSR_DATA(IP2_27_24, DU_DB7),
+
+ PINMUX_IPSR_DATA(IP2_31_28, A8),
+ PINMUX_IPSR_MSEL(IP2_31_28, RX3_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP2_31_28, MSIOF2_SYNC_A, SEL_MSIOF2_0),
+ PINMUX_IPSR_MSEL(IP2_31_28, HRX4_B, SEL_HSCIF4_1),
+ PINMUX_IPSR_MSEL(IP2_31_28, SDA6_A, SEL_I2C6_0),
+ PINMUX_IPSR_MSEL(IP2_31_28, AVB_AVTP_MATCH_B, SEL_ETHERAVB_1),
+ PINMUX_IPSR_MSEL(IP2_31_28, PWM1_B, SEL_PWM1_1),
+
+ /* IPSR3 */
+ PINMUX_IPSR_DATA(IP3_3_0, A9),
+ PINMUX_IPSR_MSEL(IP3_3_0, MSIOF2_SCK_A, SEL_MSIOF2_0),
+ PINMUX_IPSR_MSEL(IP3_3_0, CTS4_N_B, SEL_SCIF4_1),
+ PINMUX_IPSR_DATA(IP3_3_0, VI5_VSYNC_N),
+
+ PINMUX_IPSR_DATA(IP3_7_4, A10),
+ PINMUX_IPSR_MSEL(IP3_7_4, MSIOF2_RXD_A, SEL_MSIOF2_0),
+ PINMUX_IPSR_MSEL(IP3_7_4, RTS4_N_TANS_B, SEL_SCIF4_1),
+ PINMUX_IPSR_DATA(IP3_7_4, VI5_HSYNC_N),
+
+ PINMUX_IPSR_DATA(IP3_11_8, A11),
+ PINMUX_IPSR_MSEL(IP3_11_8, TX3_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP3_11_8, MSIOF2_TXD_A, SEL_MSIOF2_0),
+ PINMUX_IPSR_MSEL(IP3_11_8, HTX4_B, SEL_HSCIF4_1),
+ PINMUX_IPSR_DATA(IP3_11_8, HSCK4),
+ PINMUX_IPSR_DATA(IP3_11_8, VI5_FIELD),
+ PINMUX_IPSR_MSEL(IP3_11_8, SCL6_A, SEL_I2C6_0),
+ PINMUX_IPSR_MSEL(IP3_11_8, AVB_AVTP_CAPTURE_B, SEL_ETHERAVB_1),
+ PINMUX_IPSR_MSEL(IP3_11_8, PWM2_B, SEL_PWM2_1),
+
+ PINMUX_IPSR_DATA(IP3_15_12, A12),
+ PINMUX_IPSR_DATA(IP3_15_12, LCDOUT12),
+ PINMUX_IPSR_MSEL(IP3_15_12, MSIOF3_SCK_C, SEL_MSIOF3_2),
+ PINMUX_IPSR_MSEL(IP3_15_12, HRX4_A, SEL_HSCIF4_0),
+ PINMUX_IPSR_DATA(IP3_15_12, VI5_DATA8),
+ PINMUX_IPSR_DATA(IP3_15_12, DU_DG4),
+
+ PINMUX_IPSR_DATA(IP3_19_16, A13),
+ PINMUX_IPSR_DATA(IP3_19_16, LCDOUT13),
+ PINMUX_IPSR_MSEL(IP3_19_16, MSIOF3_SYNC_C, SEL_MSIOF3_2),
+ PINMUX_IPSR_MSEL(IP3_19_16, HTX4_A, SEL_HSCIF4_0),
+ PINMUX_IPSR_DATA(IP3_19_16, VI5_DATA9),
+ PINMUX_IPSR_DATA(IP3_19_16, DU_DG5),
+
+ PINMUX_IPSR_DATA(IP3_23_20, A14),
+ PINMUX_IPSR_DATA(IP3_23_20, LCDOUT14),
+ PINMUX_IPSR_MSEL(IP3_23_20, MSIOF3_RXD_C, SEL_MSIOF3_2),
+ PINMUX_IPSR_DATA(IP3_23_20, HCTS4_N),
+ PINMUX_IPSR_DATA(IP3_23_20, VI5_DATA10),
+ PINMUX_IPSR_DATA(IP3_23_20, DU_DG6),
+
+ PINMUX_IPSR_DATA(IP3_27_24, A15),
+ PINMUX_IPSR_DATA(IP3_27_24, LCDOUT15),
+ PINMUX_IPSR_MSEL(IP3_27_24, MSIOF3_TXD_C, SEL_MSIOF3_2),
+ PINMUX_IPSR_DATA(IP3_27_24, HRTS4_N),
+ PINMUX_IPSR_DATA(IP3_27_24, VI5_DATA11),
+ PINMUX_IPSR_DATA(IP3_27_24, DU_DG7),
+
+ PINMUX_IPSR_DATA(IP3_31_28, A16),
+ PINMUX_IPSR_DATA(IP3_31_28, LCDOUT8),
+ PINMUX_IPSR_DATA(IP3_31_28, VI4_FIELD),
+ PINMUX_IPSR_DATA(IP3_31_28, DU_DG0),
+
+ /* IPSR4 */
+ PINMUX_IPSR_DATA(IP4_3_0, A17),
+ PINMUX_IPSR_DATA(IP4_3_0, LCDOUT9),
+ PINMUX_IPSR_DATA(IP4_3_0, VI4_VSYNC_N),
+ PINMUX_IPSR_DATA(IP4_3_0, DU_DG1),
+
+ PINMUX_IPSR_DATA(IP4_7_4, A18),
+ PINMUX_IPSR_DATA(IP4_7_4, LCDOUT10),
+ PINMUX_IPSR_DATA(IP4_7_4, VI4_HSYNC_N),
+ PINMUX_IPSR_DATA(IP4_7_4, DU_DG2),
+
+ PINMUX_IPSR_DATA(IP4_11_8, A19),
+ PINMUX_IPSR_DATA(IP4_11_8, LCDOUT11),
+ PINMUX_IPSR_DATA(IP4_11_8, VI4_CLKENB),
+ PINMUX_IPSR_DATA(IP4_11_8, DU_DG3),
+
+ PINMUX_IPSR_DATA(IP4_15_12, CS0_N),
+ PINMUX_IPSR_DATA(IP4_15_12, VI5_CLKENB),
+
+ PINMUX_IPSR_DATA(IP4_19_16, CS1_N_A26),
+ PINMUX_IPSR_DATA(IP4_19_16, VI5_CLK),
+ PINMUX_IPSR_MSEL(IP4_19_16, EX_WAIT0_B, SEL_LBSC_1),
+
+ PINMUX_IPSR_DATA(IP4_23_20, BS_N),
+ PINMUX_IPSR_DATA(IP4_23_20, QSTVA_QVS),
+ PINMUX_IPSR_MSEL(IP4_23_20, MSIOF3_SCK_D, SEL_MSIOF3_3),
+ PINMUX_IPSR_DATA(IP4_23_20, SCK3),
+ PINMUX_IPSR_DATA(IP4_23_20, HSCK3),
+ PINMUX_IPSR_DATA(IP4_23_20, CAN1_TX),
+ PINMUX_IPSR_DATA(IP4_23_20, CANFD1_TX),
+ PINMUX_IPSR_MSEL(IP4_23_20, IETX_A, SEL_IEBUS_0),
+
+ PINMUX_IPSR_DATA(IP4_27_24, RD_N),
+ PINMUX_IPSR_MSEL(IP4_27_24, MSIOF3_SYNC_D, SEL_MSIOF3_3),
+ PINMUX_IPSR_MSEL(IP4_27_24, RX3_A, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP4_27_24, HRX3_A, SEL_HSCIF3_0),
+ PINMUX_IPSR_MSEL(IP4_27_24, CAN0_TX_A, SEL_RCAN0_0),
+ PINMUX_IPSR_MSEL(IP4_27_24, CANFD0_TX_A, SEL_CANFD0_0),
+
+ PINMUX_IPSR_DATA(IP4_31_28, RD_WR_N),
+ PINMUX_IPSR_MSEL(IP4_31_28, MSIOF3_RXD_D, SEL_MSIOF3_3),
+ PINMUX_IPSR_MSEL(IP4_31_28, TX3_A, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP4_31_28, HTX3_A, SEL_HSCIF3_0),
+ PINMUX_IPSR_MSEL(IP4_31_28, CAN0_RX_A, SEL_RCAN0_0),
+ PINMUX_IPSR_MSEL(IP4_31_28, CANFD0_RX_A, SEL_CANFD0_0),
+
+ /* IPSR5 */
+ PINMUX_IPSR_DATA(IP5_3_0, WE0_N),
+ PINMUX_IPSR_MSEL(IP5_3_0, MSIOF3_TXD_D, SEL_MSIOF3_3),
+ PINMUX_IPSR_DATA(IP5_3_0, CTS3_N),
+ PINMUX_IPSR_DATA(IP5_3_0, HCTS3_N),
+ PINMUX_IPSR_MSEL(IP5_3_0, SCL6_B, SEL_I2C6_1),
+ PINMUX_IPSR_DATA(IP5_3_0, CAN_CLK),
+ PINMUX_IPSR_MSEL(IP5_3_0, IECLK_A, SEL_IEBUS_0),
+
+ PINMUX_IPSR_DATA(IP5_7_4, WE1_N),
+ PINMUX_IPSR_MSEL(IP5_7_4, MSIOF3_SS1_D, SEL_MSIOF3_3),
+ PINMUX_IPSR_DATA(IP5_7_4, RTS3_N_TANS),
+ PINMUX_IPSR_DATA(IP5_7_4, HRTS3_N),
+ PINMUX_IPSR_MSEL(IP5_7_4, SDA6_B, SEL_I2C6_1),
+ PINMUX_IPSR_DATA(IP5_7_4, CAN1_RX),
+ PINMUX_IPSR_DATA(IP5_7_4, CANFD1_RX),
+ PINMUX_IPSR_MSEL(IP5_7_4, IERX_A, SEL_IEBUS_0),
+
+ PINMUX_IPSR_MSEL(IP5_11_8, EX_WAIT0_A, SEL_LBSC_0),
+ PINMUX_IPSR_DATA(IP5_11_8, QCLK),
+ PINMUX_IPSR_DATA(IP5_11_8, VI4_CLK),
+ PINMUX_IPSR_DATA(IP5_11_8, DU_DOTCLKOUT0),
+
+ PINMUX_IPSR_DATA(IP5_15_12, D0),
+ PINMUX_IPSR_MSEL(IP5_15_12, MSIOF2_SS1_B, SEL_MSIOF2_1),
+ PINMUX_IPSR_MSEL(IP5_15_12, MSIOF3_SCK_A, SEL_MSIOF3_0),
+ PINMUX_IPSR_DATA(IP5_15_12, VI4_DATA16),
+ PINMUX_IPSR_DATA(IP5_15_12, VI5_DATA0),
+
+ PINMUX_IPSR_DATA(IP5_19_16, D1),
+ PINMUX_IPSR_MSEL(IP5_19_16, MSIOF2_SS2_B, SEL_MSIOF2_1),
+ PINMUX_IPSR_MSEL(IP5_19_16, MSIOF3_SYNC_A, SEL_MSIOF3_0),
+ PINMUX_IPSR_DATA(IP5_19_16, VI4_DATA17),
+ PINMUX_IPSR_DATA(IP5_19_16, VI5_DATA1),
+
+ PINMUX_IPSR_DATA(IP5_23_20, D2),
+ PINMUX_IPSR_MSEL(IP5_23_20, MSIOF3_RXD_A, SEL_MSIOF3_0),
+ PINMUX_IPSR_DATA(IP5_23_20, VI4_DATA18),
+ PINMUX_IPSR_DATA(IP5_23_20, VI5_DATA2),
+
+ PINMUX_IPSR_DATA(IP5_27_24, D3),
+ PINMUX_IPSR_MSEL(IP5_27_24, MSIOF3_TXD_A, SEL_MSIOF3_0),
+ PINMUX_IPSR_DATA(IP5_27_24, VI4_DATA19),
+ PINMUX_IPSR_DATA(IP5_27_24, VI5_DATA3),
+
+ PINMUX_IPSR_DATA(IP5_31_28, D4),
+ PINMUX_IPSR_MSEL(IP5_31_28, MSIOF2_SCK_B, SEL_MSIOF2_1),
+ PINMUX_IPSR_DATA(IP5_31_28, VI4_DATA20),
+ PINMUX_IPSR_DATA(IP5_31_28, VI5_DATA4),
+
+ /* IPSR6 */
+ PINMUX_IPSR_DATA(IP6_3_0, D5),
+ PINMUX_IPSR_MSEL(IP6_3_0, MSIOF2_SYNC_B, SEL_MSIOF2_1),
+ PINMUX_IPSR_DATA(IP6_3_0, VI4_DATA21),
+ PINMUX_IPSR_DATA(IP6_3_0, VI5_DATA5),
+
+ PINMUX_IPSR_DATA(IP6_7_4, D6),
+ PINMUX_IPSR_MSEL(IP6_7_4, MSIOF2_RXD_B, SEL_MSIOF2_1),
+ PINMUX_IPSR_DATA(IP6_7_4, VI4_DATA22),
+ PINMUX_IPSR_DATA(IP6_7_4, VI5_DATA6),
+
+ PINMUX_IPSR_DATA(IP6_11_8, D7),
+ PINMUX_IPSR_MSEL(IP6_11_8, MSIOF2_TXD_B, SEL_MSIOF2_1),
+ PINMUX_IPSR_DATA(IP6_11_8, VI4_DATA23),
+ PINMUX_IPSR_DATA(IP6_11_8, VI5_DATA7),
+
+ PINMUX_IPSR_DATA(IP6_15_12, D8),
+ PINMUX_IPSR_DATA(IP6_15_12, LCDOUT0),
+ PINMUX_IPSR_MSEL(IP6_15_12, MSIOF2_SCK_D, SEL_MSIOF2_3),
+ PINMUX_IPSR_MSEL(IP6_15_12, SCK4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP6_15_12, VI4_DATA0_A, SEL_VIN4_0),
+ PINMUX_IPSR_DATA(IP6_15_12, DU_DR0),
+
+ PINMUX_IPSR_DATA(IP6_19_16, D9),
+ PINMUX_IPSR_DATA(IP6_19_16, LCDOUT1),
+ PINMUX_IPSR_MSEL(IP6_19_16, MSIOF2_SYNC_D, SEL_MSIOF2_3),
+ PINMUX_IPSR_MSEL(IP6_19_16, VI4_DATA1_A, SEL_VIN4_0),
+ PINMUX_IPSR_DATA(IP6_19_16, DU_DR1),
+
+ PINMUX_IPSR_DATA(IP6_23_20, D10),
+ PINMUX_IPSR_DATA(IP6_23_20, LCDOUT2),
+ PINMUX_IPSR_MSEL(IP6_23_20, MSIOF2_RXD_D, SEL_MSIOF2_3),
+ PINMUX_IPSR_MSEL(IP6_23_20, HRX3_B, SEL_HSCIF3_1),
+ PINMUX_IPSR_MSEL(IP6_23_20, VI4_DATA2_A, SEL_VIN4_0),
+ PINMUX_IPSR_MSEL(IP6_23_20, CTS4_N_C, SEL_SCIF4_2),
+ PINMUX_IPSR_DATA(IP6_23_20, DU_DR2),
+
+ PINMUX_IPSR_DATA(IP6_27_24, D11),
+ PINMUX_IPSR_DATA(IP6_27_24, LCDOUT3),
+ PINMUX_IPSR_MSEL(IP6_27_24, MSIOF2_TXD_D, SEL_MSIOF2_3),
+ PINMUX_IPSR_MSEL(IP6_27_24, HTX3_B, SEL_HSCIF3_1),
+ PINMUX_IPSR_MSEL(IP6_27_24, VI4_DATA3_A, SEL_VIN4_0),
+ PINMUX_IPSR_MSEL(IP6_27_24, RTS4_N_TANS_C, SEL_SCIF4_2),
+ PINMUX_IPSR_DATA(IP6_27_24, DU_DR3),
+
+ PINMUX_IPSR_DATA(IP6_31_28, D12),
+ PINMUX_IPSR_DATA(IP6_31_28, LCDOUT4),
+ PINMUX_IPSR_MSEL(IP6_31_28, MSIOF2_SS1_D, SEL_MSIOF2_3),
+ PINMUX_IPSR_MSEL(IP6_31_28, RX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP6_31_28, VI4_DATA4_A, SEL_VIN4_0),
+ PINMUX_IPSR_DATA(IP6_31_28, DU_DR4),
+
+ /* IPSR7 */
+ PINMUX_IPSR_DATA(IP7_3_0, D13),
+ PINMUX_IPSR_DATA(IP7_3_0, LCDOUT5),
+ PINMUX_IPSR_MSEL(IP7_3_0, MSIOF2_SS2_D, SEL_MSIOF2_3),
+ PINMUX_IPSR_MSEL(IP7_3_0, TX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP7_3_0, VI4_DATA5_A, SEL_VIN4_0),
+ PINMUX_IPSR_DATA(IP7_3_0, DU_DR5),
+
+ PINMUX_IPSR_DATA(IP7_7_4, D14),
+ PINMUX_IPSR_DATA(IP7_7_4, LCDOUT6),
+ PINMUX_IPSR_MSEL(IP7_7_4, MSIOF3_SS1_A, SEL_MSIOF3_0),
+ PINMUX_IPSR_MSEL(IP7_7_4, HRX3_C, SEL_HSCIF3_2),
+ PINMUX_IPSR_MSEL(IP7_7_4, VI4_DATA6_A, SEL_VIN4_0),
+ PINMUX_IPSR_DATA(IP7_7_4, DU_DR6),
+ PINMUX_IPSR_MSEL(IP7_7_4, SCL6_C, SEL_I2C6_2),
+
+ PINMUX_IPSR_DATA(IP7_11_8, D15),
+ PINMUX_IPSR_DATA(IP7_11_8, LCDOUT7),
+ PINMUX_IPSR_MSEL(IP7_11_8, MSIOF3_SS2_A, SEL_MSIOF3_0),
+ PINMUX_IPSR_MSEL(IP7_11_8, HTX3_C, SEL_HSCIF3_2),
+ PINMUX_IPSR_MSEL(IP7_11_8, VI4_DATA7_A, SEL_VIN4_0),
+ PINMUX_IPSR_DATA(IP7_11_8, DU_DR7),
+ PINMUX_IPSR_MSEL(IP7_11_8, SDA6_C, SEL_I2C6_2),
+
+ PINMUX_IPSR_DATA(IP7_15_12, FSCLKST),
+
+ PINMUX_IPSR_DATA(IP7_19_16, SD0_CLK),
+ PINMUX_IPSR_MSEL(IP7_19_16, MSIOF1_SCK_E, SEL_MSIOF1_4),
+ PINMUX_IPSR_MSEL(IP7_19_16, STP_OPWM_0_B, SEL_SSP1_0_1),
+
+ PINMUX_IPSR_DATA(IP7_23_20, SD0_CMD),
+ PINMUX_IPSR_MSEL(IP7_23_20, MSIOF1_SYNC_E, SEL_MSIOF1_4),
+ PINMUX_IPSR_MSEL(IP7_23_20, STP_IVCXO27_0_B, SEL_SSP1_0_1),
+
+ PINMUX_IPSR_DATA(IP7_27_24, SD0_DAT0),
+ PINMUX_IPSR_MSEL(IP7_27_24, MSIOF1_RXD_E, SEL_MSIOF1_4),
+ PINMUX_IPSR_MSEL(IP7_27_24, TS_SCK0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP7_27_24, STP_ISCLK_0_B, SEL_SSP1_0_1),
+
+ PINMUX_IPSR_DATA(IP7_31_28, SD0_DAT1),
+ PINMUX_IPSR_MSEL(IP7_31_28, MSIOF1_TXD_E, SEL_MSIOF1_4),
+ PINMUX_IPSR_MSEL(IP7_31_28, TS_SPSYNC0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP7_31_28, STP_ISSYNC_0_B, SEL_SSP1_0_1),
+
+ /* IPSR8 */
+ PINMUX_IPSR_DATA(IP8_3_0, SD0_DAT2),
+ PINMUX_IPSR_MSEL(IP8_3_0, MSIOF1_SS1_E, SEL_MSIOF1_4),
+ PINMUX_IPSR_MSEL(IP8_3_0, TS_SDAT0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP8_3_0, STP_ISD_0_B, SEL_SSP1_0_1),
+
+ PINMUX_IPSR_DATA(IP8_7_4, SD0_DAT3),
+ PINMUX_IPSR_MSEL(IP8_7_4, MSIOF1_SS2_E, SEL_MSIOF1_4),
+ PINMUX_IPSR_MSEL(IP8_7_4, TS_SDEN0_B, SEL_TSIF0_1),
+ PINMUX_IPSR_MSEL(IP8_7_4, STP_ISEN_0_B, SEL_SSP1_0_1),
+
+ PINMUX_IPSR_DATA(IP8_11_8, SD1_CLK),
+ PINMUX_IPSR_MSEL(IP8_11_8, MSIOF1_SCK_G, SEL_MSIOF1_6),
+ PINMUX_IPSR_MSEL(IP8_11_8, SIM0_CLK_A, SEL_SIMCARD_0),
+
+ PINMUX_IPSR_DATA(IP8_15_12, SD1_CMD),
+ PINMUX_IPSR_MSEL(IP8_15_12, MSIOF1_SYNC_G, SEL_MSIOF1_6),
+ PINMUX_IPSR_MSEL(IP8_15_12, SIM0_D_A, SEL_SIMCARD_0),
+ PINMUX_IPSR_MSEL(IP8_15_12, STP_IVCXO27_1_B, SEL_SSP1_1_1),
+
+ PINMUX_IPSR_DATA(IP8_19_16, SD1_DAT0),
+ PINMUX_IPSR_DATA(IP8_19_16, SD2_DAT4),
+ PINMUX_IPSR_MSEL(IP8_19_16, MSIOF1_RXD_G, SEL_MSIOF1_6),
+ PINMUX_IPSR_MSEL(IP8_19_16, TS_SCK1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP8_19_16, STP_ISCLK_1_B, SEL_SSP1_1_1),
+
+ PINMUX_IPSR_DATA(IP8_23_20, SD1_DAT1),
+ PINMUX_IPSR_DATA(IP8_23_20, SD2_DAT5),
+ PINMUX_IPSR_MSEL(IP8_23_20, MSIOF1_TXD_G, SEL_MSIOF1_6),
+ PINMUX_IPSR_MSEL(IP8_23_20, TS_SPSYNC1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP8_23_20, STP_ISSYNC_1_B, SEL_SSP1_1_1),
+
+ PINMUX_IPSR_DATA(IP8_27_24, SD1_DAT2),
+ PINMUX_IPSR_DATA(IP8_27_24, SD2_DAT6),
+ PINMUX_IPSR_MSEL(IP8_27_24, MSIOF1_SS1_G, SEL_MSIOF1_6),
+ PINMUX_IPSR_MSEL(IP8_27_24, TS_SDAT1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP8_27_24, STP_ISD_1_B, SEL_SSP1_1_1),
+
+ PINMUX_IPSR_DATA(IP8_31_28, SD1_DAT3),
+ PINMUX_IPSR_DATA(IP8_31_28, SD2_DAT7),
+ PINMUX_IPSR_MSEL(IP8_31_28, MSIOF1_SS2_G, SEL_MSIOF1_6),
+ PINMUX_IPSR_MSEL(IP8_31_28, TS_SDEN1_B, SEL_TSIF1_1),
+ PINMUX_IPSR_MSEL(IP8_31_28, STP_ISEN_1_B, SEL_SSP1_1_1),
+
+ /* IPSR9 */
+ PINMUX_IPSR_DATA(IP9_3_0, SD2_CLK),
+
+ PINMUX_IPSR_DATA(IP9_7_4, SD2_DAT0),
+
+ PINMUX_IPSR_DATA(IP9_11_8, SD2_DAT1),
+
+ PINMUX_IPSR_DATA(IP9_15_12, SD2_DAT2),
+
+ PINMUX_IPSR_DATA(IP9_19_16, SD2_DAT3),
+
+ PINMUX_IPSR_DATA(IP9_23_20, SD2_DS),
+ PINMUX_IPSR_MSEL(IP9_23_20, SATA_DEVSLP_B, SEL_SCIF_1),
+
+ PINMUX_IPSR_DATA(IP9_27_24, SD3_DAT4),
+ PINMUX_IPSR_MSEL(IP9_27_24, SD2_CD_A, SEL_SDHI2_0),
+
+ PINMUX_IPSR_DATA(IP9_31_28, SD3_DAT5),
+ PINMUX_IPSR_MSEL(IP9_31_28, SD2_WP_A, SEL_SDHI2_0),
+
+ /* IPSR10 */
+ PINMUX_IPSR_DATA(IP10_3_0, SD3_DAT6),
+ PINMUX_IPSR_DATA(IP10_3_0, SD3_CD),
+
+ PINMUX_IPSR_DATA(IP10_7_4, SD3_DAT7),
+ PINMUX_IPSR_DATA(IP10_7_4, SD3_WP),
+
+ PINMUX_IPSR_DATA(IP10_11_8, SD0_CD),
+ PINMUX_IPSR_MSEL(IP10_11_8, SCL2_B, SEL_I2C2_1),
+ PINMUX_IPSR_MSEL(IP10_11_8, SIM0_RST_A, SEL_SIMCARD_0),
+
+ PINMUX_IPSR_DATA(IP10_15_12, SD0_WP),
+ PINMUX_IPSR_MSEL(IP10_15_12, SDA2_B, SEL_I2C2_1),
+
+ PINMUX_IPSR_DATA(IP10_19_16, SD1_CD),
+ PINMUX_IPSR_MSEL(IP10_19_16, SIM0_CLK_B, SEL_SIMCARD_1),
+
+ PINMUX_IPSR_DATA(IP10_23_20, SD1_WP),
+ PINMUX_IPSR_MSEL(IP10_23_20, SIM0_D_B, SEL_SIMCARD_1),
+
+ PINMUX_IPSR_DATA(IP10_27_24, SCK0),
+ PINMUX_IPSR_MSEL(IP10_27_24, HSCK1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP10_27_24, MSIOF1_SS2_B, SEL_MSIOF1_1),
+ PINMUX_IPSR_MSEL(IP10_27_24, AUDIO_CLKC_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP10_27_24, SDA2_A, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP10_27_24, SIM0_RST_B, SEL_SIMCARD_1),
+ PINMUX_IPSR_MSEL(IP10_27_24, STP_OPWM_0_C, SEL_SSP1_0_2),
+ PINMUX_IPSR_MSEL(IP10_27_24, RIF0_CLK_B, SEL_DRIF0_1),
+ PINMUX_IPSR_DATA(IP10_27_24, ADICHS2),
+
+ PINMUX_IPSR_DATA(IP10_31_28, RX0),
+ PINMUX_IPSR_MSEL(IP10_31_28, HRX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP10_31_28, TS_SCK0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP10_31_28, STP_ISCLK_0_C, SEL_SSP1_0_2),
+ PINMUX_IPSR_MSEL(IP10_31_28, RIF0_D0_B, SEL_DRIF0_1),
+
+ /* IPSR11 */
+ PINMUX_IPSR_DATA(IP11_3_0, TX0),
+ PINMUX_IPSR_MSEL(IP11_3_0, HTX1_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP11_3_0, TS_SPSYNC0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP11_3_0, STP_ISSYNC_0_C, SEL_SSP1_0_2),
+ PINMUX_IPSR_MSEL(IP11_3_0, RIF0_D1_B, SEL_DRIF0_1),
+
+ PINMUX_IPSR_DATA(IP11_7_4, CTS0_N),
+ PINMUX_IPSR_MSEL(IP11_7_4, HCTS1_N_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP11_7_4, MSIOF1_SYNC_B, SEL_MSIOF1_1),
+ PINMUX_IPSR_MSEL(IP11_7_4, TS_SPSYNC1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP11_7_4, STP_ISSYNC_1_C, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP11_7_4, RIF1_SYNC_B, SEL_DRIF1_1),
+ PINMUX_IPSR_MSEL(IP11_7_4, AUDIO_CLKOUT_C, SEL_ADG_2),
+ PINMUX_IPSR_DATA(IP11_7_4, ADICS_SAMP),
+
+ PINMUX_IPSR_DATA(IP11_11_8, RTS0_N_TANS),
+ PINMUX_IPSR_MSEL(IP11_11_8, HRTS1_N_B, SEL_HSCIF1_1),
+ PINMUX_IPSR_MSEL(IP11_11_8, MSIOF1_SS1_B, SEL_MSIOF1_1),
+ PINMUX_IPSR_MSEL(IP11_11_8, AUDIO_CLKA_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP11_11_8, SCL2_A, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP11_11_8, STP_IVCXO27_1_C, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP11_11_8, RIF0_SYNC_B, SEL_DRIF0_1),
+ PINMUX_IPSR_DATA(IP11_11_8, ADICHS1),
+
+ PINMUX_IPSR_MSEL(IP11_15_12, RX1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP11_15_12, HRX1_A, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP11_15_12, TS_SDAT0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP11_15_12, STP_ISD_0_C, SEL_SSP1_0_2),
+ PINMUX_IPSR_MSEL(IP11_15_12, RIF1_CLK_C, SEL_DRIF1_2),
+
+ PINMUX_IPSR_MSEL(IP11_19_16, TX1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP11_19_16, HTX1_A, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP11_19_16, TS_SDEN0_C, SEL_TSIF0_2),
+ PINMUX_IPSR_MSEL(IP11_19_16, STP_ISEN_0_C, SEL_SSP1_0_2),
+ PINMUX_IPSR_MSEL(IP11_19_16, RIF1_D0_C, SEL_DRIF1_2),
+
+ PINMUX_IPSR_DATA(IP11_23_20, CTS1_N),
+ PINMUX_IPSR_MSEL(IP11_23_20, HCTS1_N_A, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP11_23_20, MSIOF1_RXD_B, SEL_MSIOF1_1),
+ PINMUX_IPSR_MSEL(IP11_23_20, TS_SDEN1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP11_23_20, STP_ISEN_1_C, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP11_23_20, RIF1_D0_B, SEL_DRIF1_1),
+ PINMUX_IPSR_DATA(IP11_23_20, ADIDATA),
+
+ PINMUX_IPSR_DATA(IP11_27_24, RTS1_N_TANS),
+ PINMUX_IPSR_MSEL(IP11_27_24, HRTS1_N_A, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP11_27_24, MSIOF1_TXD_B, SEL_MSIOF1_1),
+ PINMUX_IPSR_MSEL(IP11_27_24, TS_SDAT1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP11_27_24, STP_ISD_1_C, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP11_27_24, RIF1_D1_B, SEL_DRIF1_1),
+ PINMUX_IPSR_DATA(IP11_27_24, ADICHS0),
+
+ PINMUX_IPSR_DATA(IP11_31_28, SCK2),
+ PINMUX_IPSR_MSEL(IP11_31_28, SCIF_CLK_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP11_31_28, MSIOF1_SCK_B, SEL_MSIOF1_1),
+ PINMUX_IPSR_MSEL(IP11_31_28, TS_SCK1_C, SEL_TSIF1_2),
+ PINMUX_IPSR_MSEL(IP11_31_28, STP_ISCLK_1_C, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP11_31_28, RIF1_CLK_B, SEL_DRIF1_1),
+ PINMUX_IPSR_DATA(IP11_31_28, ADICLK),
+
+ /* IPSR12 */
+ PINMUX_IPSR_MSEL(IP12_3_0, TX2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP12_3_0, SD2_CD_B, SEL_SDHI2_1),
+ PINMUX_IPSR_MSEL(IP12_3_0, SCL1_A, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP12_3_0, FMCLK_A, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP12_3_0, RIF1_D1_C, SEL_DRIF1_2),
+ PINMUX_IPSR_MSEL(IP12_3_0, FSO_CFE_0_B, SEL_FSO_1),
+
+ PINMUX_IPSR_MSEL(IP12_7_4, RX2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP12_7_4, SD2_WP_B, SEL_SDHI2_1),
+ PINMUX_IPSR_MSEL(IP12_7_4, SDA1_A, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP12_7_4, FMIN_A, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP12_7_4, RIF1_SYNC_C, SEL_DRIF1_2),
+ PINMUX_IPSR_MSEL(IP12_7_4, FSO_CFE_1_B, SEL_FSO_1),
+
+ PINMUX_IPSR_DATA(IP12_11_8, HSCK0),
+ PINMUX_IPSR_MSEL(IP12_11_8, MSIOF1_SCK_D, SEL_MSIOF1_3),
+ PINMUX_IPSR_MSEL(IP12_11_8, AUDIO_CLKB_A, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP12_11_8, SSI_SDATA1_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP12_11_8, TS_SCK0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP12_11_8, STP_ISCLK_0_D, SEL_SSP1_0_3),
+ PINMUX_IPSR_MSEL(IP12_11_8, RIF0_CLK_C, SEL_DRIF0_2),
+
+ PINMUX_IPSR_DATA(IP12_15_12, HRX0),
+ PINMUX_IPSR_MSEL(IP12_15_12, MSIOF1_RXD_D, SEL_MSIOF1_3),
+ PINMUX_IPSR_MSEL(IP12_15_12, SSI_SDATA2_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP12_15_12, TS_SDEN0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP12_15_12, STP_ISEN_0_D, SEL_SSP1_0_3),
+ PINMUX_IPSR_MSEL(IP12_15_12, RIF0_D0_C, SEL_DRIF0_2),
+
+ PINMUX_IPSR_DATA(IP12_19_16, HTX0),
+ PINMUX_IPSR_MSEL(IP12_19_16, MSIOF1_TXD_D, SEL_MSIOF1_3),
+ PINMUX_IPSR_MSEL(IP12_19_16, SSI_SDATA9_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP12_19_16, TS_SDAT0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP12_19_16, STP_ISD_0_D, SEL_SSP1_0_3),
+ PINMUX_IPSR_MSEL(IP12_19_16, RIF0_D1_C, SEL_DRIF0_2),
+
+ PINMUX_IPSR_DATA(IP12_23_20, HCTS0_N),
+ PINMUX_IPSR_MSEL(IP12_23_20, RX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP12_23_20, MSIOF1_SYNC_D, SEL_MSIOF1_3),
+ PINMUX_IPSR_MSEL(IP12_23_20, SSI_SCK9_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP12_23_20, TS_SPSYNC0_D, SEL_TSIF0_3),
+ PINMUX_IPSR_MSEL(IP12_23_20, STP_ISSYNC_0_D, SEL_SSP1_0_3),
+ PINMUX_IPSR_MSEL(IP12_23_20, RIF0_SYNC_C, SEL_DRIF0_2),
+ PINMUX_IPSR_MSEL(IP12_23_20, AUDIO_CLKOUT1_A, SEL_ADG_0),
+
+ PINMUX_IPSR_DATA(IP12_27_24, HRTS0_N),
+ PINMUX_IPSR_MSEL(IP12_27_24, TX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP12_27_24, MSIOF1_SS1_D, SEL_MSIOF1_3),
+ PINMUX_IPSR_MSEL(IP12_27_24, SSI_WS9_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP12_27_24, STP_IVCXO27_0_D, SEL_SSP1_0_3),
+ PINMUX_IPSR_MSEL(IP12_27_24, BPFCLK_A, SEL_FM_0),
+ PINMUX_IPSR_MSEL(IP12_27_24, AUDIO_CLKOUT2_A, SEL_ADG_0),
+
+ PINMUX_IPSR_DATA(IP12_31_28, MSIOF0_SYNC),
+ PINMUX_IPSR_MSEL(IP12_31_28, AUDIO_CLKOUT_A, SEL_ADG_0),
+
+ /* IPSR13 */
+ PINMUX_IPSR_DATA(IP13_3_0, MSIOF0_SS1),
+ PINMUX_IPSR_DATA(IP13_3_0, RX5),
+ PINMUX_IPSR_MSEL(IP13_3_0, AUDIO_CLKA_C, SEL_ADG_2),
+ PINMUX_IPSR_MSEL(IP13_3_0, SSI_SCK2_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP13_3_0, STP_IVCXO27_0_C, SEL_SSP1_0_2),
+ PINMUX_IPSR_MSEL(IP13_3_0, AUDIO_CLKOUT3_A, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP13_3_0, TCLK1_B, SEL_TIMER_TMU_1),
+
+ PINMUX_IPSR_DATA(IP13_7_4, MSIOF0_SS2),
+ PINMUX_IPSR_DATA(IP13_7_4, TX5),
+ PINMUX_IPSR_MSEL(IP13_7_4, MSIOF1_SS2_D, SEL_MSIOF1_3),
+ PINMUX_IPSR_MSEL(IP13_7_4, AUDIO_CLKC_A, SEL_ADG_0),
+ PINMUX_IPSR_MSEL(IP13_7_4, SSI_WS2_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP13_7_4, STP_OPWM_0_D, SEL_SSP1_0_3),
+ PINMUX_IPSR_MSEL(IP13_7_4, AUDIO_CLKOUT_D, SEL_ADG_3),
+ PINMUX_IPSR_MSEL(IP13_7_4, SPEEDIN_B, SEL_SPEED_PULSE_1),
+
+ PINMUX_IPSR_DATA(IP13_11_8, MLB_CLK),
+ PINMUX_IPSR_MSEL(IP13_11_8, MSIOF1_SCK_F, SEL_MSIOF1_5),
+ PINMUX_IPSR_MSEL(IP13_11_8, SCL1_B, SEL_I2C1_1),
+
+ PINMUX_IPSR_DATA(IP13_15_12, MLB_SIG),
+ PINMUX_IPSR_MSEL(IP13_15_12, RX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP13_15_12, MSIOF1_SYNC_F, SEL_MSIOF1_5),
+ PINMUX_IPSR_MSEL(IP13_15_12, SDA1_B, SEL_I2C1_1),
+
+ PINMUX_IPSR_DATA(IP13_19_16, MLB_DAT),
+ PINMUX_IPSR_MSEL(IP13_19_16, TX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP13_19_16, MSIOF1_RXD_F, SEL_MSIOF1_5),
+
+ PINMUX_IPSR_DATA(IP13_23_20, SSI_SCK0129),
+ PINMUX_IPSR_MSEL(IP13_23_20, MSIOF1_TXD_F, SEL_MSIOF1_5),
+
+ PINMUX_IPSR_DATA(IP13_27_24, SSI_WS0129),
+ PINMUX_IPSR_MSEL(IP13_27_24, MSIOF1_SS1_F, SEL_MSIOF1_5),
+
+ PINMUX_IPSR_DATA(IP13_31_28, SSI_SDATA0),
+ PINMUX_IPSR_MSEL(IP13_31_28, MSIOF1_SS2_F, SEL_MSIOF1_5),
+
+ /* IPSR14 */
+ PINMUX_IPSR_MSEL(IP14_3_0, SSI_SDATA1_A, SEL_SSI_0),
+
+ PINMUX_IPSR_MSEL(IP14_7_4, SSI_SDATA2_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP14_7_4, SSI_SCK1_B, SEL_SSI_1),
+
+ PINMUX_IPSR_DATA(IP14_11_8, SSI_SCK34),
+ PINMUX_IPSR_MSEL(IP14_11_8, MSIOF1_SS1_A, SEL_MSIOF1_0),
+ PINMUX_IPSR_MSEL(IP14_11_8, STP_OPWM_0_A, SEL_SSP1_0_0),
+
+ PINMUX_IPSR_DATA(IP14_15_12, SSI_WS34),
+ PINMUX_IPSR_MSEL(IP14_15_12, HCTS2_N_A, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP14_15_12, MSIOF1_SS2_A, SEL_MSIOF1_0),
+ PINMUX_IPSR_MSEL(IP14_15_12, STP_IVCXO27_0_A, SEL_SSP1_0_0),
+
+ PINMUX_IPSR_DATA(IP14_19_16, SSI_SDATA3),
+ PINMUX_IPSR_MSEL(IP14_19_16, HRTS2_N_A, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP14_19_16, MSIOF1_TXD_A, SEL_MSIOF1_0),
+ PINMUX_IPSR_MSEL(IP14_19_16, TS_SCK0_A, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP14_19_16, STP_ISCLK_0_A, SEL_SSP1_0_0),
+ PINMUX_IPSR_MSEL(IP14_19_16, RIF0_D1_A, SEL_DRIF0_0),
+ PINMUX_IPSR_MSEL(IP14_19_16, RIF2_D0_A, SEL_DRIF2_0),
+
+ PINMUX_IPSR_DATA(IP14_23_20, SSI_SCK4),
+ PINMUX_IPSR_MSEL(IP14_23_20, HRX2_A, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP14_23_20, MSIOF1_SCK_A, SEL_MSIOF1_0),
+ PINMUX_IPSR_MSEL(IP14_23_20, TS_SDAT0_A, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP14_23_20, STP_ISD_0_A, SEL_SSP1_0_0),
+ PINMUX_IPSR_MSEL(IP14_23_20, RIF0_CLK_A, SEL_DRIF0_0),
+ PINMUX_IPSR_MSEL(IP14_23_20, RIF2_CLK_A, SEL_DRIF2_0),
+
+ PINMUX_IPSR_DATA(IP14_27_24, SSI_WS4),
+ PINMUX_IPSR_MSEL(IP14_27_24, HTX2_A, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP14_27_24, MSIOF1_SYNC_A, SEL_MSIOF1_0),
+ PINMUX_IPSR_MSEL(IP14_27_24, TS_SDEN0_A, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP14_27_24, STP_ISEN_0_A, SEL_SSP1_0_0),
+ PINMUX_IPSR_MSEL(IP14_27_24, RIF0_SYNC_A, SEL_DRIF0_0),
+ PINMUX_IPSR_MSEL(IP14_27_24, RIF2_SYNC_A, SEL_DRIF2_0),
+
+ PINMUX_IPSR_DATA(IP14_31_28, SSI_SDATA4),
+ PINMUX_IPSR_MSEL(IP14_31_28, HSCK2_A, SEL_HSCIF2_0),
+ PINMUX_IPSR_MSEL(IP14_31_28, MSIOF1_RXD_A, SEL_MSIOF1_0),
+ PINMUX_IPSR_MSEL(IP14_31_28, TS_SPSYNC0_A, SEL_TSIF0_0),
+ PINMUX_IPSR_MSEL(IP14_31_28, STP_ISSYNC_0_A, SEL_SSP1_0_0),
+ PINMUX_IPSR_MSEL(IP14_31_28, RIF0_D0_A, SEL_DRIF0_0),
+ PINMUX_IPSR_MSEL(IP14_31_28, RIF2_D1_A, SEL_DRIF2_0),
+
+ /* IPSR15 */
+ PINMUX_IPSR_DATA(IP15_3_0, SSI_SCK6),
+ PINMUX_IPSR_DATA(IP15_3_0, USB2_PWEN),
+ PINMUX_IPSR_MSEL(IP15_3_0, SIM0_RST_D, SEL_SIMCARD_3),
+
+ PINMUX_IPSR_DATA(IP15_7_4, SSI_WS6),
+ PINMUX_IPSR_DATA(IP15_7_4, USB2_OVC),
+ PINMUX_IPSR_MSEL(IP15_7_4, SIM0_D_D, SEL_SIMCARD_3),
+
+ PINMUX_IPSR_DATA(IP15_11_8, SSI_SDATA6),
+ PINMUX_IPSR_MSEL(IP15_11_8, SIM0_CLK_D, SEL_SIMCARD_3),
+ PINMUX_IPSR_MSEL(IP15_11_8, SATA_DEVSLP_A, SEL_SCIF_0),
+
+ PINMUX_IPSR_DATA(IP15_15_12, SSI_SCK78),
+ PINMUX_IPSR_MSEL(IP15_15_12, HRX2_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP15_15_12, MSIOF1_SCK_C, SEL_MSIOF1_2),
+ PINMUX_IPSR_MSEL(IP15_15_12, TS_SCK1_A, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP15_15_12, STP_ISCLK_1_A, SEL_SSP1_1_0),
+ PINMUX_IPSR_MSEL(IP15_15_12, RIF1_CLK_A, SEL_DRIF1_0),
+ PINMUX_IPSR_MSEL(IP15_15_12, RIF3_CLK_A, SEL_DRIF3_0),
+
+ PINMUX_IPSR_DATA(IP15_19_16, SSI_WS78),
+ PINMUX_IPSR_MSEL(IP15_19_16, HTX2_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP15_19_16, MSIOF1_SYNC_C, SEL_MSIOF1_2),
+ PINMUX_IPSR_MSEL(IP15_19_16, TS_SDAT1_A, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP15_19_16, STP_ISD_1_A, SEL_SSP1_1_0),
+ PINMUX_IPSR_MSEL(IP15_19_16, RIF1_SYNC_A, SEL_DRIF1_0),
+ PINMUX_IPSR_MSEL(IP15_19_16, RIF3_SYNC_A, SEL_DRIF3_0),
+
+ PINMUX_IPSR_DATA(IP15_23_20, SSI_SDATA7),
+ PINMUX_IPSR_MSEL(IP15_23_20, HCTS2_N_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP15_23_20, MSIOF1_RXD_C, SEL_MSIOF1_2),
+ PINMUX_IPSR_MSEL(IP15_23_20, TS_SDEN1_A, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP15_23_20, STP_ISEN_1_A, SEL_SSP1_1_0),
+ PINMUX_IPSR_MSEL(IP15_23_20, RIF1_D0_A, SEL_DRIF1_0),
+ PINMUX_IPSR_MSEL(IP15_23_20, RIF3_D0_A, SEL_DRIF3_0),
+ PINMUX_IPSR_MSEL(IP15_23_20, TCLK2_A, SEL_TIMER_TMU_0),
+
+ PINMUX_IPSR_DATA(IP15_27_24, SSI_SDATA8),
+ PINMUX_IPSR_MSEL(IP15_27_24, HRTS2_N_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP15_27_24, MSIOF1_TXD_C, SEL_MSIOF1_2),
+ PINMUX_IPSR_MSEL(IP15_27_24, TS_SPSYNC1_A, SEL_TSIF1_0),
+ PINMUX_IPSR_MSEL(IP15_27_24, STP_ISSYNC_1_A, SEL_SSP1_1_0),
+ PINMUX_IPSR_MSEL(IP15_27_24, RIF1_D1_A, SEL_DRIF1_0),
+ PINMUX_IPSR_MSEL(IP15_27_24, RIF3_D1_A, SEL_DRIF3_0),
+
+ PINMUX_IPSR_MSEL(IP15_31_28, SSI_SDATA9_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP15_31_28, HSCK2_B, SEL_HSCIF2_1),
+ PINMUX_IPSR_MSEL(IP15_31_28, MSIOF1_SS1_C, SEL_MSIOF1_2),
+ PINMUX_IPSR_MSEL(IP15_31_28, HSCK1_A, SEL_HSCIF1_0),
+ PINMUX_IPSR_MSEL(IP15_31_28, SSI_WS1_B, SEL_SSI_1),
+ PINMUX_IPSR_DATA(IP15_31_28, SCK1),
+ PINMUX_IPSR_MSEL(IP15_31_28, STP_IVCXO27_1_A, SEL_SSP1_1_0),
+ PINMUX_IPSR_DATA(IP15_31_28, SCK5),
+
+ /* IPSR16 */
+ PINMUX_IPSR_MSEL(IP16_3_0, AUDIO_CLKA_A, SEL_ADG_0),
+ PINMUX_IPSR_DATA(IP16_3_0, CC5_OSCOUT),
+
+ PINMUX_IPSR_MSEL(IP16_7_4, AUDIO_CLKB_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP16_7_4, SCIF_CLK_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP16_7_4, STP_IVCXO27_1_D, SEL_SSP1_1_3),
+ PINMUX_IPSR_MSEL(IP16_7_4, REMOCON_A, SEL_REMOCON_0),
+ PINMUX_IPSR_MSEL(IP16_7_4, TCLK1_A, SEL_TIMER_TMU_0),
+
+ PINMUX_IPSR_DATA(IP16_11_8, USB0_PWEN),
+ PINMUX_IPSR_MSEL(IP16_11_8, SIM0_RST_C, SEL_SIMCARD_2),
+ PINMUX_IPSR_MSEL(IP16_11_8, TS_SCK1_D, SEL_TSIF1_3),
+ PINMUX_IPSR_MSEL(IP16_11_8, STP_ISCLK_1_D, SEL_SSP1_1_3),
+ PINMUX_IPSR_MSEL(IP16_11_8, BPFCLK_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP16_11_8, RIF3_CLK_B, SEL_DRIF3_1),
+
+ PINMUX_IPSR_DATA(IP16_15_12, USB0_OVC),
+ PINMUX_IPSR_MSEL(IP16_11_8, SIM0_D_C, SEL_SIMCARD_2),
+ PINMUX_IPSR_MSEL(IP16_11_8, TS_SDAT1_D, SEL_TSIF1_3),
+ PINMUX_IPSR_MSEL(IP16_11_8, STP_ISD_1_D, SEL_SSP1_1_3),
+ PINMUX_IPSR_MSEL(IP16_11_8, RIF3_SYNC_B, SEL_DRIF3_1),
+
+ PINMUX_IPSR_DATA(IP16_19_16, USB1_PWEN),
+ PINMUX_IPSR_MSEL(IP16_19_16, SIM0_CLK_C, SEL_SIMCARD_2),
+ PINMUX_IPSR_MSEL(IP16_19_16, SSI_SCK1_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP16_19_16, TS_SCK0_E, SEL_TSIF0_4),
+ PINMUX_IPSR_MSEL(IP16_19_16, STP_ISCLK_0_E, SEL_SSP1_0_4),
+ PINMUX_IPSR_MSEL(IP16_19_16, FMCLK_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP16_19_16, RIF2_CLK_B, SEL_DRIF2_1),
+ PINMUX_IPSR_MSEL(IP16_19_16, SPEEDIN_A, SEL_SPEED_PULSE_0),
+
+ PINMUX_IPSR_DATA(IP16_23_20, USB1_OVC),
+ PINMUX_IPSR_MSEL(IP16_23_20, MSIOF1_SS2_C, SEL_MSIOF1_2),
+ PINMUX_IPSR_MSEL(IP16_23_20, SSI_WS1_A, SEL_SSI_0),
+ PINMUX_IPSR_MSEL(IP16_23_20, TS_SDAT0_E, SEL_TSIF0_4),
+ PINMUX_IPSR_MSEL(IP16_23_20, STP_ISD_0_E, SEL_SSP1_0_4),
+ PINMUX_IPSR_MSEL(IP16_23_20, FMIN_B, SEL_FM_1),
+ PINMUX_IPSR_MSEL(IP16_23_20, RIF2_SYNC_B, SEL_DRIF2_1),
+ PINMUX_IPSR_MSEL(IP16_23_20, REMOCON_B, SEL_REMOCON_1),
+
+ PINMUX_IPSR_DATA(IP16_27_24, USB30_PWEN),
+ PINMUX_IPSR_MSEL(IP16_27_24, AUDIO_CLKOUT_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP16_27_24, SSI_SCK2_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP16_27_24, TS_SDEN1_D, SEL_TSIF1_3),
+ PINMUX_IPSR_MSEL(IP16_27_24, STP_ISEN_1_D, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP16_27_24, STP_OPWM_0_E, SEL_SSP1_0_4),
+ PINMUX_IPSR_MSEL(IP16_27_24, RIF3_D0_B, SEL_DRIF3_1),
+ PINMUX_IPSR_MSEL(IP16_27_24, TCLK2_B, SEL_TIMER_TMU_1),
+ PINMUX_IPSR_DATA(IP16_27_24, TPU0TO0),
+
+ PINMUX_IPSR_DATA(IP16_31_28, USB30_OVC),
+ PINMUX_IPSR_MSEL(IP16_31_28, AUDIO_CLKOUT1_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP16_31_28, SSI_WS2_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP16_31_28, TS_SPSYNC1_D, SEL_TSIF1_3),
+ PINMUX_IPSR_MSEL(IP16_31_28, STP_ISSYNC_1_D, SEL_SSP1_1_3),
+ PINMUX_IPSR_MSEL(IP16_31_28, STP_IVCXO27_0_E, SEL_SSP1_0_4),
+ PINMUX_IPSR_MSEL(IP16_31_28, RIF3_D1_B, SEL_DRIF3_1),
+ PINMUX_IPSR_MSEL(IP16_31_28, FSO_TOE_B, SEL_FSO_1),
+ PINMUX_IPSR_DATA(IP16_31_28, TPU0TO1),
+
+ /* IPSR17 */
+ PINMUX_IPSR_DATA(IP17_3_0, USB31_PWEN),
+ PINMUX_IPSR_MSEL(IP17_3_0, AUDIO_CLKOUT2_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP17_3_0, SSI_SCK9_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP17_3_0, TS_SDEN0_E, SEL_TSIF0_4),
+ PINMUX_IPSR_MSEL(IP17_3_0, STP_ISEN_0_E, SEL_SSP1_0_4),
+ PINMUX_IPSR_MSEL(IP17_3_0, RIF2_D0_B, SEL_DRIF2_1),
+ PINMUX_IPSR_DATA(IP17_3_0, TPU0TO2),
+
+ PINMUX_IPSR_DATA(IP17_7_4, USB31_OVC),
+ PINMUX_IPSR_MSEL(IP17_7_4, AUDIO_CLKOUT3_B, SEL_ADG_1),
+ PINMUX_IPSR_MSEL(IP17_7_4, SSI_WS9_B, SEL_SSI_1),
+ PINMUX_IPSR_MSEL(IP17_7_4, TS_SPSYNC0_E, SEL_TSIF0_4),
+ PINMUX_IPSR_MSEL(IP17_7_4, STP_ISSYNC_0_E, SEL_SSP1_0_4),
+ PINMUX_IPSR_MSEL(IP17_7_4, RIF2_D1_B, SEL_DRIF2_1),
+ PINMUX_IPSR_DATA(IP17_7_4, TPU0TO3),
+
+ /* I2C */
+ PINMUX_IPSR_NOGP(0, I2C_SEL_0_1),
+ PINMUX_IPSR_NOGP(0, I2C_SEL_3_1),
+ PINMUX_IPSR_NOGP(0, I2C_SEL_5_1),
+};
+
+static const struct sh_pfc_pin pinmux_pins[] = {
+ PINMUX_GPIO_GP_ALL(),
+};
+
+/* - AUDIO CLOCK ------------------------------------------------------------ */
+static const unsigned int audio_clk_a_a_pins[] = {
+ /* CLK A */
+ RCAR_GP_PIN(6, 22),
+};
+static const unsigned int audio_clk_a_a_mux[] = {
+ AUDIO_CLKA_A_MARK,
+};
+static const unsigned int audio_clk_a_b_pins[] = {
+ /* CLK A */
+ RCAR_GP_PIN(5, 4),
+};
+static const unsigned int audio_clk_a_b_mux[] = {
+ AUDIO_CLKA_B_MARK,
+};
+static const unsigned int audio_clk_a_c_pins[] = {
+ /* CLK A */
+ RCAR_GP_PIN(5, 19),
+};
+static const unsigned int audio_clk_a_c_mux[] = {
+ AUDIO_CLKA_C_MARK,
+};
+static const unsigned int audio_clk_b_a_pins[] = {
+ /* CLK B */
+ RCAR_GP_PIN(5, 12),
+};
+static const unsigned int audio_clk_b_a_mux[] = {
+ AUDIO_CLKB_A_MARK,
+};
+static const unsigned int audio_clk_b_b_pins[] = {
+ /* CLK B */
+ RCAR_GP_PIN(6, 23),
+};
+static const unsigned int audio_clk_b_b_mux[] = {
+ AUDIO_CLKB_B_MARK,
+};
+static const unsigned int audio_clk_c_a_pins[] = {
+ /* CLK C */
+ RCAR_GP_PIN(5, 21),
+};
+static const unsigned int audio_clk_c_a_mux[] = {
+ AUDIO_CLKC_A_MARK,
+};
+static const unsigned int audio_clk_c_b_pins[] = {
+ /* CLK C */
+ RCAR_GP_PIN(5, 0),
+};
+static const unsigned int audio_clk_c_b_mux[] = {
+ AUDIO_CLKC_B_MARK,
+};
+static const unsigned int audio_clkout_a_pins[] = {
+ /* CLKOUT */
+ RCAR_GP_PIN(5, 18),
+};
+static const unsigned int audio_clkout_a_mux[] = {
+ AUDIO_CLKOUT_A_MARK,
+};
+static const unsigned int audio_clkout_b_pins[] = {
+ /* CLKOUT */
+ RCAR_GP_PIN(6, 28),
+};
+static const unsigned int audio_clkout_b_mux[] = {
+ AUDIO_CLKOUT_B_MARK,
+};
+static const unsigned int audio_clkout_c_pins[] = {
+ /* CLKOUT */
+ RCAR_GP_PIN(5, 3),
+};
+static const unsigned int audio_clkout_c_mux[] = {
+ AUDIO_CLKOUT_C_MARK,
+};
+static const unsigned int audio_clkout_d_pins[] = {
+ /* CLKOUT */
+ RCAR_GP_PIN(5, 21),
+};
+static const unsigned int audio_clkout_d_mux[] = {
+ AUDIO_CLKOUT_D_MARK,
+};
+static const unsigned int audio_clkout1_a_pins[] = {
+ /* CLKOUT1 */
+ RCAR_GP_PIN(5, 15),
+};
+static const unsigned int audio_clkout1_a_mux[] = {
+ AUDIO_CLKOUT1_A_MARK,
+};
+static const unsigned int audio_clkout1_b_pins[] = {
+ /* CLKOUT1 */
+ RCAR_GP_PIN(6, 29),
+};
+static const unsigned int audio_clkout1_b_mux[] = {
+ AUDIO_CLKOUT1_B_MARK,
+};
+static const unsigned int audio_clkout2_a_pins[] = {
+ /* CLKOUT2 */
+ RCAR_GP_PIN(5, 16),
+};
+static const unsigned int audio_clkout2_a_mux[] = {
+ AUDIO_CLKOUT2_A_MARK,
+};
+static const unsigned int audio_clkout2_b_pins[] = {
+ /* CLKOUT2 */
+ RCAR_GP_PIN(6, 30),
+};
+static const unsigned int audio_clkout2_b_mux[] = {
+ AUDIO_CLKOUT2_B_MARK,
+};
+
+static const unsigned int audio_clkout3_a_pins[] = {
+ /* CLKOUT3 */
+ RCAR_GP_PIN(5, 19),
+};
+static const unsigned int audio_clkout3_a_mux[] = {
+ AUDIO_CLKOUT3_A_MARK,
+};
+static const unsigned int audio_clkout3_b_pins[] = {
+ /* CLKOUT3 */
+ RCAR_GP_PIN(6, 31),
+};
+static const unsigned int audio_clkout3_b_mux[] = {
+ AUDIO_CLKOUT3_B_MARK,
+};
+
+/* - EtherAVB --------------------------------------------------------------- */
+static const unsigned int avb_link_pins[] = {
+ /* AVB_LINK */
+ RCAR_GP_PIN(2, 12),
+};
+static const unsigned int avb_link_mux[] = {
+ AVB_LINK_MARK,
+};
+static const unsigned int avb_magic_pins[] = {
+ /* AVB_MAGIC_ */
+ RCAR_GP_PIN(2, 10),
+};
+static const unsigned int avb_magic_mux[] = {
+ AVB_MAGIC_MARK,
+};
+static const unsigned int avb_phy_int_pins[] = {
+ /* AVB_PHY_INT */
+ RCAR_GP_PIN(2, 11),
+};
+static const unsigned int avb_phy_int_mux[] = {
+ AVB_PHY_INT_MARK,
+};
+static const unsigned int avb_mdc_pins[] = {
+ /* AVB_MDC */
+ RCAR_GP_PIN(2, 9),
+};
+static const unsigned int avb_mdc_mux[] = {
+ AVB_MDC_MARK,
+};
+static const unsigned int avb_avtp_pps_pins[] = {
+ /* AVB_AVTP_PPS */
+ RCAR_GP_PIN(2, 6),
+};
+static const unsigned int avb_avtp_pps_mux[] = {
+ AVB_AVTP_PPS_MARK,
+};
+static const unsigned int avb_avtp_match_a_pins[] = {
+ /* AVB_AVTP_MATCH_A */
+ RCAR_GP_PIN(2, 13),
+};
+static const unsigned int avb_avtp_match_a_mux[] = {
+ AVB_AVTP_MATCH_A_MARK,
+};
+static const unsigned int avb_avtp_capture_a_pins[] = {
+ /* AVB_AVTP_CAPTURE_A */
+ RCAR_GP_PIN(2, 14),
+};
+static const unsigned int avb_avtp_capture_a_mux[] = {
+ AVB_AVTP_CAPTURE_A_MARK,
+};
+static const unsigned int avb_avtp_match_b_pins[] = {
+ /* AVB_AVTP_MATCH_B */
+ RCAR_GP_PIN(1, 8),
+};
+static const unsigned int avb_avtp_match_b_mux[] = {
+ AVB_AVTP_MATCH_B_MARK,
+};
+static const unsigned int avb_avtp_capture_b_pins[] = {
+ /* AVB_AVTP_CAPTURE_B */
+ RCAR_GP_PIN(1, 11),
+};
+static const unsigned int avb_avtp_capture_b_mux[] = {
+ AVB_AVTP_CAPTURE_B_MARK,
+};
+
+/* - I2C -------------------------------------------------------------------- */
+static const unsigned int i2c1_a_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 10),
+};
+static const unsigned int i2c1_a_mux[] = {
+ SDA1_A_MARK, SCL1_A_MARK,
+};
+static const unsigned int i2c1_b_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 23),
+};
+static const unsigned int i2c1_b_mux[] = {
+ SDA1_B_MARK, SCL1_B_MARK,
+};
+static const unsigned int i2c2_a_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 4),
+};
+static const unsigned int i2c2_a_mux[] = {
+ SDA2_A_MARK, SCL2_A_MARK,
+};
+static const unsigned int i2c2_b_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12),
+};
+static const unsigned int i2c2_b_mux[] = {
+ SDA2_B_MARK, SCL2_B_MARK,
+};
+static const unsigned int i2c6_a_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 11),
+};
+static const unsigned int i2c6_a_mux[] = {
+ SDA6_A_MARK, SCL6_A_MARK,
+};
+static const unsigned int i2c6_b_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25),
+};
+static const unsigned int i2c6_b_mux[] = {
+ SDA6_B_MARK, SCL6_B_MARK,
+};
+static const unsigned int i2c6_c_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14),
+};
+static const unsigned int i2c6_c_mux[] = {
+ SDA6_C_MARK, SCL6_C_MARK,
+};
+
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2),
+};
+static const unsigned int scif0_data_mux[] = {
+ RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 0),
+};
+static const unsigned int scif0_clk_mux[] = {
+ SCK0_MARK,
+};
+static const unsigned int scif0_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(5, 4), RCAR_GP_PIN(5, 3),
+};
+static const unsigned int scif0_ctrl_mux[] = {
+ RTS0_N_TANS_MARK, CTS0_N_MARK,
+};
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 6),
+};
+static const unsigned int scif1_data_a_mux[] = {
+ RX1_A_MARK, TX1_A_MARK,
+};
+static const unsigned int scif1_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 21),
+};
+static const unsigned int scif1_clk_mux[] = {
+ SCK1_MARK,
+};
+static const unsigned int scif1_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 7),
+};
+static const unsigned int scif1_ctrl_mux[] = {
+ RTS1_N_TANS_MARK, CTS1_N_MARK,
+};
+
+static const unsigned int scif1_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25),
+};
+static const unsigned int scif1_data_b_mux[] = {
+ RX1_B_MARK, TX1_B_MARK,
+};
+/* - SCIF2 ------------------------------------------------------------------ */
+static const unsigned int scif2_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 10),
+};
+static const unsigned int scif2_data_a_mux[] = {
+ RX2_A_MARK, TX2_A_MARK,
+};
+static const unsigned int scif2_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 9),
+};
+static const unsigned int scif2_clk_mux[] = {
+ SCK2_MARK,
+};
+static const unsigned int scif2_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 16),
+};
+static const unsigned int scif2_data_b_mux[] = {
+ RX2_B_MARK, TX2_B_MARK,
+};
+/* - SCIF3 ------------------------------------------------------------------ */
+static const unsigned int scif3_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24),
+};
+static const unsigned int scif3_data_a_mux[] = {
+ RX3_A_MARK, TX3_A_MARK,
+};
+static const unsigned int scif3_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 22),
+};
+static const unsigned int scif3_clk_mux[] = {
+ SCK3_MARK,
+};
+static const unsigned int scif3_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25),
+};
+static const unsigned int scif3_ctrl_mux[] = {
+ RTS3_N_TANS_MARK, CTS3_N_MARK,
+};
+static const unsigned int scif3_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 11),
+};
+static const unsigned int scif3_data_b_mux[] = {
+ RX3_B_MARK, TX3_B_MARK,
+};
+/* - SCIF4 ------------------------------------------------------------------ */
+static const unsigned int scif4_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 12),
+};
+static const unsigned int scif4_data_a_mux[] = {
+ RX4_A_MARK, TX4_A_MARK,
+};
+static const unsigned int scif4_clk_a_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(2, 10),
+};
+static const unsigned int scif4_clk_a_mux[] = {
+ SCK4_A_MARK,
+};
+static const unsigned int scif4_ctrl_a_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
+};
+static const unsigned int scif4_ctrl_a_mux[] = {
+ RTS4_N_TANS_A_MARK, CTS4_N_A_MARK,
+};
+static const unsigned int scif4_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7),
+};
+static const unsigned int scif4_data_b_mux[] = {
+ RX4_B_MARK, TX4_B_MARK,
+};
+static const unsigned int scif4_clk_b_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 5),
+};
+static const unsigned int scif4_clk_b_mux[] = {
+ SCK4_B_MARK,
+};
+static const unsigned int scif4_ctrl_b_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 9),
+};
+static const unsigned int scif4_ctrl_b_mux[] = {
+ RTS4_N_TANS_B_MARK, CTS4_N_B_MARK,
+};
+static const unsigned int scif4_data_c_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13),
+};
+static const unsigned int scif4_data_c_mux[] = {
+ RX4_C_MARK, TX4_C_MARK,
+};
+static const unsigned int scif4_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(0, 8),
+};
+static const unsigned int scif4_clk_c_mux[] = {
+ SCK4_C_MARK,
+};
+static const unsigned int scif4_ctrl_c_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10),
+};
+static const unsigned int scif4_ctrl_c_mux[] = {
+ RTS4_N_TANS_C_MARK, CTS4_N_C_MARK,
+};
+/* - SCIF5 ------------------------------------------------------------------ */
+static const unsigned int scif5_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 21),
+};
+static const unsigned int scif5_data_mux[] = {
+ RX5_MARK, TX5_MARK,
+};
+static const unsigned int scif5_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 21),
+};
+static const unsigned int scif5_clk_mux[] = {
+ SCK5_MARK,
+};
+
+/* - SSI -------------------------------------------------------------------- */
+static const unsigned int ssi0_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 2),
+};
+static const unsigned int ssi0_data_mux[] = {
+ SSI_SDATA0_MARK,
+};
+static const unsigned int ssi01239_ctrl_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 0), RCAR_GP_PIN(6, 1),
+};
+static const unsigned int ssi01239_ctrl_mux[] = {
+ SSI_SCK0129_MARK, SSI_WS0129_MARK,
+};
+static const unsigned int ssi1_data_a_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 3),
+};
+static const unsigned int ssi1_data_a_mux[] = {
+ SSI_SDATA1_A_MARK,
+};
+static const unsigned int ssi1_data_b_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(5, 12),
+};
+static const unsigned int ssi1_data_b_mux[] = {
+ SSI_SDATA1_B_MARK,
+};
+static const unsigned int ssi1_ctrl_a_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 26), RCAR_GP_PIN(6, 27),
+};
+static const unsigned int ssi1_ctrl_a_mux[] = {
+ SSI_SCK1_A_MARK, SSI_WS1_A_MARK,
+};
+static const unsigned int ssi1_ctrl_b_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 4), RCAR_GP_PIN(6, 21),
+};
+static const unsigned int ssi1_ctrl_b_mux[] = {
+ SSI_SCK1_B_MARK, SSI_WS1_B_MARK,
+};
+static const unsigned int ssi2_data_a_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 4),
+};
+static const unsigned int ssi2_data_a_mux[] = {
+ SSI_SDATA2_A_MARK,
+};
+static const unsigned int ssi2_data_b_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(5, 13),
+};
+static const unsigned int ssi2_data_b_mux[] = {
+ SSI_SDATA2_B_MARK,
+};
+static const unsigned int ssi2_ctrl_a_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 21),
+};
+static const unsigned int ssi2_ctrl_a_mux[] = {
+ SSI_SCK2_A_MARK, SSI_WS2_A_MARK,
+};
+static const unsigned int ssi2_ctrl_b_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 28), RCAR_GP_PIN(6, 29),
+};
+static const unsigned int ssi2_ctrl_b_mux[] = {
+ SSI_SCK2_B_MARK, SSI_WS2_B_MARK,
+};
+static const unsigned int ssi3_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 7),
+};
+static const unsigned int ssi3_data_mux[] = {
+ SSI_SDATA3_MARK,
+};
+static const unsigned int ssi34_ctrl_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 5), RCAR_GP_PIN(6, 6),
+};
+static const unsigned int ssi34_ctrl_mux[] = {
+ SSI_SCK34_MARK, SSI_WS34_MARK,
+};
+static const unsigned int ssi4_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 10),
+};
+static const unsigned int ssi4_data_mux[] = {
+ SSI_SDATA4_MARK,
+};
+static const unsigned int ssi4_ctrl_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9),
+};
+static const unsigned int ssi4_ctrl_mux[] = {
+ SSI_SCK4_MARK, SSI_WS4_MARK,
+};
+static const unsigned int ssi5_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 13),
+};
+static const unsigned int ssi5_data_mux[] = {
+ SSI_SDATA5_MARK,
+};
+static const unsigned int ssi5_ctrl_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 11), RCAR_GP_PIN(6, 12),
+};
+static const unsigned int ssi5_ctrl_mux[] = {
+ SSI_SCK5_MARK, SSI_WS5_MARK,
+};
+static const unsigned int ssi6_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 16),
+};
+static const unsigned int ssi6_data_mux[] = {
+ SSI_SDATA6_MARK,
+};
+static const unsigned int ssi6_ctrl_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 14), RCAR_GP_PIN(6, 15),
+};
+static const unsigned int ssi6_ctrl_mux[] = {
+ SSI_SCK6_MARK, SSI_WS6_MARK,
+};
+static const unsigned int ssi7_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 19),
+};
+static const unsigned int ssi7_data_mux[] = {
+ SSI_SDATA7_MARK,
+};
+static const unsigned int ssi78_ctrl_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18),
+};
+static const unsigned int ssi78_ctrl_mux[] = {
+ SSI_SCK78_MARK, SSI_WS78_MARK,
+};
+static const unsigned int ssi8_data_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 20),
+};
+static const unsigned int ssi8_data_mux[] = {
+ SSI_SDATA8_MARK,
+};
+static const unsigned int ssi9_data_a_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(6, 21),
+};
+static const unsigned int ssi9_data_a_mux[] = {
+ SSI_SDATA9_A_MARK,
+};
+static const unsigned int ssi9_data_b_pins[] = {
+ /* SDATA */
+ RCAR_GP_PIN(5, 14),
+};
+static const unsigned int ssi9_data_b_mux[] = {
+ SSI_SDATA9_B_MARK,
+};
+static const unsigned int ssi9_ctrl_a_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 16),
+};
+static const unsigned int ssi9_ctrl_a_mux[] = {
+ SSI_SCK9_A_MARK, SSI_WS9_A_MARK,
+};
+static const unsigned int ssi9_ctrl_b_pins[] = {
+ /* SCK, WS */
+ RCAR_GP_PIN(6, 30), RCAR_GP_PIN(6, 31),
+};
+static const unsigned int ssi9_ctrl_b_mux[] = {
+ SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(audio_clk_a_a),
+ SH_PFC_PIN_GROUP(audio_clk_a_b),
+ SH_PFC_PIN_GROUP(audio_clk_a_c),
+ SH_PFC_PIN_GROUP(audio_clk_b_a),
+ SH_PFC_PIN_GROUP(audio_clk_b_b),
+ SH_PFC_PIN_GROUP(audio_clk_c_a),
+ SH_PFC_PIN_GROUP(audio_clk_c_b),
+ SH_PFC_PIN_GROUP(audio_clkout_a),
+ SH_PFC_PIN_GROUP(audio_clkout_b),
+ SH_PFC_PIN_GROUP(audio_clkout_c),
+ SH_PFC_PIN_GROUP(audio_clkout_d),
+ SH_PFC_PIN_GROUP(audio_clkout1_a),
+ SH_PFC_PIN_GROUP(audio_clkout1_b),
+ SH_PFC_PIN_GROUP(audio_clkout2_a),
+ SH_PFC_PIN_GROUP(audio_clkout2_b),
+ SH_PFC_PIN_GROUP(audio_clkout3_a),
+ SH_PFC_PIN_GROUP(audio_clkout3_b),
+ SH_PFC_PIN_GROUP(avb_link),
+ SH_PFC_PIN_GROUP(avb_magic),
+ SH_PFC_PIN_GROUP(avb_phy_int),
+ SH_PFC_PIN_GROUP(avb_mdc),
+ SH_PFC_PIN_GROUP(avb_avtp_pps),
+ SH_PFC_PIN_GROUP(avb_avtp_match_a),
+ SH_PFC_PIN_GROUP(avb_avtp_capture_a),
+ SH_PFC_PIN_GROUP(avb_avtp_match_b),
+ SH_PFC_PIN_GROUP(avb_avtp_capture_b),
+ SH_PFC_PIN_GROUP(i2c1_a),
+ SH_PFC_PIN_GROUP(i2c1_b),
+ SH_PFC_PIN_GROUP(i2c2_a),
+ SH_PFC_PIN_GROUP(i2c2_b),
+ SH_PFC_PIN_GROUP(i2c6_a),
+ SH_PFC_PIN_GROUP(i2c6_b),
+ SH_PFC_PIN_GROUP(i2c6_c),
+ SH_PFC_PIN_GROUP(scif0_data),
+ SH_PFC_PIN_GROUP(scif0_clk),
+ SH_PFC_PIN_GROUP(scif0_ctrl),
+ SH_PFC_PIN_GROUP(scif1_data_a),
+ SH_PFC_PIN_GROUP(scif1_clk),
+ SH_PFC_PIN_GROUP(scif1_ctrl),
+ SH_PFC_PIN_GROUP(scif1_data_b),
+ SH_PFC_PIN_GROUP(scif2_data_a),
+ SH_PFC_PIN_GROUP(scif2_clk),
+ SH_PFC_PIN_GROUP(scif2_data_b),
+ SH_PFC_PIN_GROUP(scif3_data_a),
+ SH_PFC_PIN_GROUP(scif3_clk),
+ SH_PFC_PIN_GROUP(scif3_ctrl),
+ SH_PFC_PIN_GROUP(scif3_data_b),
+ SH_PFC_PIN_GROUP(scif4_data_a),
+ SH_PFC_PIN_GROUP(scif4_clk_a),
+ SH_PFC_PIN_GROUP(scif4_ctrl_a),
+ SH_PFC_PIN_GROUP(scif4_data_b),
+ SH_PFC_PIN_GROUP(scif4_clk_b),
+ SH_PFC_PIN_GROUP(scif4_ctrl_b),
+ SH_PFC_PIN_GROUP(scif4_data_c),
+ SH_PFC_PIN_GROUP(scif4_clk_c),
+ SH_PFC_PIN_GROUP(scif4_ctrl_c),
+ SH_PFC_PIN_GROUP(scif5_data),
+ SH_PFC_PIN_GROUP(scif5_clk),
+ SH_PFC_PIN_GROUP(ssi0_data),
+ SH_PFC_PIN_GROUP(ssi01239_ctrl),
+ SH_PFC_PIN_GROUP(ssi1_data_a),
+ SH_PFC_PIN_GROUP(ssi1_data_b),
+ SH_PFC_PIN_GROUP(ssi1_ctrl_a),
+ SH_PFC_PIN_GROUP(ssi1_ctrl_b),
+ SH_PFC_PIN_GROUP(ssi2_data_a),
+ SH_PFC_PIN_GROUP(ssi2_data_b),
+ SH_PFC_PIN_GROUP(ssi2_ctrl_a),
+ SH_PFC_PIN_GROUP(ssi2_ctrl_b),
+ SH_PFC_PIN_GROUP(ssi3_data),
+ SH_PFC_PIN_GROUP(ssi34_ctrl),
+ SH_PFC_PIN_GROUP(ssi4_data),
+ SH_PFC_PIN_GROUP(ssi4_ctrl),
+ SH_PFC_PIN_GROUP(ssi5_data),
+ SH_PFC_PIN_GROUP(ssi5_ctrl),
+ SH_PFC_PIN_GROUP(ssi6_data),
+ SH_PFC_PIN_GROUP(ssi6_ctrl),
+ SH_PFC_PIN_GROUP(ssi7_data),
+ SH_PFC_PIN_GROUP(ssi78_ctrl),
+ SH_PFC_PIN_GROUP(ssi8_data),
+ SH_PFC_PIN_GROUP(ssi9_data_a),
+ SH_PFC_PIN_GROUP(ssi9_data_b),
+ SH_PFC_PIN_GROUP(ssi9_ctrl_a),
+ SH_PFC_PIN_GROUP(ssi9_ctrl_b),
+};
+
+static const char * const audio_clk_groups[] = {
+ "audio_clk_a_a",
+ "audio_clk_a_b",
+ "audio_clk_a_c",
+ "audio_clk_b_a",
+ "audio_clk_b_b",
+ "audio_clk_c_a",
+ "audio_clk_c_b",
+ "audio_clkout_a",
+ "audio_clkout_b",
+ "audio_clkout_c",
+ "audio_clkout_d",
+ "audio_clkout1_a",
+ "audio_clkout1_b",
+ "audio_clkout2_a",
+ "audio_clkout2_b",
+ "audio_clkout3_a",
+ "audio_clkout3_b",
+};
+
+static const char * const avb_groups[] = {
+ "avb_link",
+ "avb_magic",
+ "avb_phy_int",
+ "avb_mdc",
+ "avb_avtp_pps",
+ "avb_avtp_match_a",
+ "avb_avtp_capture_a",
+ "avb_avtp_match_b",
+ "avb_avtp_capture_b",
+};
+
+static const char * const i2c1_groups[] = {
+ "i2c1_a",
+ "i2c1_b",
+};
+
+static const char * const i2c2_groups[] = {
+ "i2c2_a",
+ "i2c2_b",
+};
+
+static const char * const i2c6_groups[] = {
+ "i2c6_a",
+ "i2c6_b",
+ "i2c6_c",
+};
+
+static const char * const scif0_groups[] = {
+ "scif0_data",
+ "scif0_clk",
+ "scif0_ctrl",
+};
+
+static const char * const scif1_groups[] = {
+ "scif1_data_a",
+ "scif1_clk",
+ "scif1_ctrl",
+ "scif1_data_b",
+};
+
+static const char * const scif2_groups[] = {
+ "scif2_data_a",
+ "scif2_clk",
+ "scif2_data_b",
+};
+
+static const char * const scif3_groups[] = {
+ "scif3_data_a",
+ "scif3_clk",
+ "scif3_ctrl",
+ "scif3_data_b",
+};
+
+static const char * const scif4_groups[] = {
+ "scif4_data_a",
+ "scif4_clk_a",
+ "scif4_ctrl_a",
+ "scif4_data_b",
+ "scif4_clk_b",
+ "scif4_ctrl_b",
+ "scif4_data_c",
+ "scif4_clk_c",
+ "scif4_ctrl_c",
+};
+
+static const char * const scif5_groups[] = {
+ "scif5_data",
+ "scif5_clk",
+};
+
+static const char * const ssi_groups[] = {
+ "ssi0_data",
+ "ssi01239_ctrl",
+ "ssi1_data_a",
+ "ssi1_data_b",
+ "ssi1_ctrl_a",
+ "ssi1_ctrl_b",
+ "ssi2_data_a",
+ "ssi2_data_b",
+ "ssi2_ctrl_a",
+ "ssi2_ctrl_b",
+ "ssi3_data",
+ "ssi34_ctrl",
+ "ssi4_data",
+ "ssi4_ctrl",
+ "ssi5_data",
+ "ssi5_ctrl",
+ "ssi6_data",
+ "ssi6_ctrl",
+ "ssi7_data",
+ "ssi78_ctrl",
+ "ssi8_data",
+ "ssi9_data_a",
+ "ssi9_data_b",
+ "ssi9_ctrl_a",
+ "ssi9_ctrl_b",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(audio_clk),
+ SH_PFC_FUNCTION(avb),
+ SH_PFC_FUNCTION(i2c1),
+ SH_PFC_FUNCTION(i2c2),
+ SH_PFC_FUNCTION(i2c6),
+ SH_PFC_FUNCTION(scif0),
+ SH_PFC_FUNCTION(scif1),
+ SH_PFC_FUNCTION(scif2),
+ SH_PFC_FUNCTION(scif3),
+ SH_PFC_FUNCTION(scif4),
+ SH_PFC_FUNCTION(scif5),
+ SH_PFC_FUNCTION(ssi),
+};
+
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
+#define F_(x, y) FN_##y
+#define FM(x) FN_##x
+ { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_0_15_FN, GPSR0_15,
+ GP_0_14_FN, GPSR0_14,
+ GP_0_13_FN, GPSR0_13,
+ GP_0_12_FN, GPSR0_12,
+ GP_0_11_FN, GPSR0_11,
+ GP_0_10_FN, GPSR0_10,
+ GP_0_9_FN, GPSR0_9,
+ GP_0_8_FN, GPSR0_8,
+ GP_0_7_FN, GPSR0_7,
+ GP_0_6_FN, GPSR0_6,
+ GP_0_5_FN, GPSR0_5,
+ GP_0_4_FN, GPSR0_4,
+ GP_0_3_FN, GPSR0_3,
+ GP_0_2_FN, GPSR0_2,
+ GP_0_1_FN, GPSR0_1,
+ GP_0_0_FN, GPSR0_0, }
+ },
+ { PINMUX_CFG_REG("GPSR1", 0xe6060104, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_1_27_FN, GPSR1_27,
+ GP_1_26_FN, GPSR1_26,
+ GP_1_25_FN, GPSR1_25,
+ GP_1_24_FN, GPSR1_24,
+ GP_1_23_FN, GPSR1_23,
+ GP_1_22_FN, GPSR1_22,
+ GP_1_21_FN, GPSR1_21,
+ GP_1_20_FN, GPSR1_20,
+ GP_1_19_FN, GPSR1_19,
+ GP_1_18_FN, GPSR1_18,
+ GP_1_17_FN, GPSR1_17,
+ GP_1_16_FN, GPSR1_16,
+ GP_1_15_FN, GPSR1_15,
+ GP_1_14_FN, GPSR1_14,
+ GP_1_13_FN, GPSR1_13,
+ GP_1_12_FN, GPSR1_12,
+ GP_1_11_FN, GPSR1_11,
+ GP_1_10_FN, GPSR1_10,
+ GP_1_9_FN, GPSR1_9,
+ GP_1_8_FN, GPSR1_8,
+ GP_1_7_FN, GPSR1_7,
+ GP_1_6_FN, GPSR1_6,
+ GP_1_5_FN, GPSR1_5,
+ GP_1_4_FN, GPSR1_4,
+ GP_1_3_FN, GPSR1_3,
+ GP_1_2_FN, GPSR1_2,
+ GP_1_1_FN, GPSR1_1,
+ GP_1_0_FN, GPSR1_0, }
+ },
+ { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_2_14_FN, GPSR2_14,
+ GP_2_13_FN, GPSR2_13,
+ GP_2_12_FN, GPSR2_12,
+ GP_2_11_FN, GPSR2_11,
+ GP_2_10_FN, GPSR2_10,
+ GP_2_9_FN, GPSR2_9,
+ GP_2_8_FN, GPSR2_8,
+ GP_2_7_FN, GPSR2_7,
+ GP_2_6_FN, GPSR2_6,
+ GP_2_5_FN, GPSR2_5,
+ GP_2_4_FN, GPSR2_4,
+ GP_2_3_FN, GPSR2_3,
+ GP_2_2_FN, GPSR2_2,
+ GP_2_1_FN, GPSR2_1,
+ GP_2_0_FN, GPSR2_0, }
+ },
+ { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_3_15_FN, GPSR3_15,
+ GP_3_14_FN, GPSR3_14,
+ GP_3_13_FN, GPSR3_13,
+ GP_3_12_FN, GPSR3_12,
+ GP_3_11_FN, GPSR3_11,
+ GP_3_10_FN, GPSR3_10,
+ GP_3_9_FN, GPSR3_9,
+ GP_3_8_FN, GPSR3_8,
+ GP_3_7_FN, GPSR3_7,
+ GP_3_6_FN, GPSR3_6,
+ GP_3_5_FN, GPSR3_5,
+ GP_3_4_FN, GPSR3_4,
+ GP_3_3_FN, GPSR3_3,
+ GP_3_2_FN, GPSR3_2,
+ GP_3_1_FN, GPSR3_1,
+ GP_3_0_FN, GPSR3_0, }
+ },
+ { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_4_17_FN, GPSR4_17,
+ GP_4_16_FN, GPSR4_16,
+ GP_4_15_FN, GPSR4_15,
+ GP_4_14_FN, GPSR4_14,
+ GP_4_13_FN, GPSR4_13,
+ GP_4_12_FN, GPSR4_12,
+ GP_4_11_FN, GPSR4_11,
+ GP_4_10_FN, GPSR4_10,
+ GP_4_9_FN, GPSR4_9,
+ GP_4_8_FN, GPSR4_8,
+ GP_4_7_FN, GPSR4_7,
+ GP_4_6_FN, GPSR4_6,
+ GP_4_5_FN, GPSR4_5,
+ GP_4_4_FN, GPSR4_4,
+ GP_4_3_FN, GPSR4_3,
+ GP_4_2_FN, GPSR4_2,
+ GP_4_1_FN, GPSR4_1,
+ GP_4_0_FN, GPSR4_0, }
+ },
+ { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_5_25_FN, GPSR5_25,
+ GP_5_24_FN, GPSR5_24,
+ GP_5_23_FN, GPSR5_23,
+ GP_5_22_FN, GPSR5_22,
+ GP_5_21_FN, GPSR5_21,
+ GP_5_20_FN, GPSR5_20,
+ GP_5_19_FN, GPSR5_19,
+ GP_5_18_FN, GPSR5_18,
+ GP_5_17_FN, GPSR5_17,
+ GP_5_16_FN, GPSR5_16,
+ GP_5_15_FN, GPSR5_15,
+ GP_5_14_FN, GPSR5_14,
+ GP_5_13_FN, GPSR5_13,
+ GP_5_12_FN, GPSR5_12,
+ GP_5_11_FN, GPSR5_11,
+ GP_5_10_FN, GPSR5_10,
+ GP_5_9_FN, GPSR5_9,
+ GP_5_8_FN, GPSR5_8,
+ GP_5_7_FN, GPSR5_7,
+ GP_5_6_FN, GPSR5_6,
+ GP_5_5_FN, GPSR5_5,
+ GP_5_4_FN, GPSR5_4,
+ GP_5_3_FN, GPSR5_3,
+ GP_5_2_FN, GPSR5_2,
+ GP_5_1_FN, GPSR5_1,
+ GP_5_0_FN, GPSR5_0, }
+ },
+ { PINMUX_CFG_REG("GPSR6", 0xe6060118, 32, 1) {
+ GP_6_31_FN, GPSR6_31,
+ GP_6_30_FN, GPSR6_30,
+ GP_6_29_FN, GPSR6_29,
+ GP_6_28_FN, GPSR6_28,
+ GP_6_27_FN, GPSR6_27,
+ GP_6_26_FN, GPSR6_26,
+ GP_6_25_FN, GPSR6_25,
+ GP_6_24_FN, GPSR6_24,
+ GP_6_23_FN, GPSR6_23,
+ GP_6_22_FN, GPSR6_22,
+ GP_6_21_FN, GPSR6_21,
+ GP_6_20_FN, GPSR6_20,
+ GP_6_19_FN, GPSR6_19,
+ GP_6_18_FN, GPSR6_18,
+ GP_6_17_FN, GPSR6_17,
+ GP_6_16_FN, GPSR6_16,
+ GP_6_15_FN, GPSR6_15,
+ GP_6_14_FN, GPSR6_14,
+ GP_6_13_FN, GPSR6_13,
+ GP_6_12_FN, GPSR6_12,
+ GP_6_11_FN, GPSR6_11,
+ GP_6_10_FN, GPSR6_10,
+ GP_6_9_FN, GPSR6_9,
+ GP_6_8_FN, GPSR6_8,
+ GP_6_7_FN, GPSR6_7,
+ GP_6_6_FN, GPSR6_6,
+ GP_6_5_FN, GPSR6_5,
+ GP_6_4_FN, GPSR6_4,
+ GP_6_3_FN, GPSR6_3,
+ GP_6_2_FN, GPSR6_2,
+ GP_6_1_FN, GPSR6_1,
+ GP_6_0_FN, GPSR6_0, }
+ },
+ { PINMUX_CFG_REG("GPSR7", 0xe606011c, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_7_3_FN, GPSR7_3,
+ GP_7_2_FN, GPSR7_2,
+ GP_7_1_FN, GPSR7_1,
+ GP_7_0_FN, GPSR7_0, }
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG("IPSR0", 0xe6060200, 32, 4) {
+ IP0_31_28
+ IP0_27_24
+ IP0_23_20
+ IP0_19_16
+ IP0_15_12
+ IP0_11_8
+ IP0_7_4
+ IP0_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR1", 0xe6060204, 32, 4) {
+ IP1_31_28
+ IP1_27_24
+ IP1_23_20
+ IP1_19_16
+ IP1_15_12
+ IP1_11_8
+ IP1_7_4
+ IP1_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR2", 0xe6060208, 32, 4) {
+ IP2_31_28
+ IP2_27_24
+ IP2_23_20
+ IP2_19_16
+ IP2_15_12
+ IP2_11_8
+ IP2_7_4
+ IP2_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR3", 0xe606020c, 32, 4) {
+ IP3_31_28
+ IP3_27_24
+ IP3_23_20
+ IP3_19_16
+ IP3_15_12
+ IP3_11_8
+ IP3_7_4
+ IP3_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR4", 0xe6060210, 32, 4) {
+ IP4_31_28
+ IP4_27_24
+ IP4_23_20
+ IP4_19_16
+ IP4_15_12
+ IP4_11_8
+ IP4_7_4
+ IP4_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR5", 0xe6060214, 32, 4) {
+ IP5_31_28
+ IP5_27_24
+ IP5_23_20
+ IP5_19_16
+ IP5_15_12
+ IP5_11_8
+ IP5_7_4
+ IP5_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR6", 0xe6060218, 32, 4) {
+ IP6_31_28
+ IP6_27_24
+ IP6_23_20
+ IP6_19_16
+ IP6_15_12
+ IP6_11_8
+ IP6_7_4
+ IP6_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4) {
+ IP7_31_28
+ IP7_27_24
+ IP7_23_20
+ IP7_19_16
+ IP7_15_12
+ IP7_11_8
+ IP7_7_4
+ IP7_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4) {
+ IP8_31_28
+ IP8_27_24
+ IP8_23_20
+ IP8_19_16
+ IP8_15_12
+ IP8_11_8
+ IP8_7_4
+ IP8_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR9", 0xe6060224, 32, 4) {
+ IP9_31_28
+ IP9_27_24
+ IP9_23_20
+ IP9_19_16
+ IP9_15_12
+ IP9_11_8
+ IP9_7_4
+ IP9_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR10", 0xe6060228, 32, 4) {
+ IP10_31_28
+ IP10_27_24
+ IP10_23_20
+ IP10_19_16
+ IP10_15_12
+ IP10_11_8
+ IP10_7_4
+ IP10_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR11", 0xe606022c, 32, 4) {
+ IP11_31_28
+ IP11_27_24
+ IP11_23_20
+ IP11_19_16
+ IP11_15_12
+ IP11_11_8
+ IP11_7_4
+ IP11_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR12", 0xe6060230, 32, 4) {
+ IP12_31_28
+ IP12_27_24
+ IP12_23_20
+ IP12_19_16
+ IP12_15_12
+ IP12_11_8
+ IP12_7_4
+ IP12_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR13", 0xe6060234, 32, 4) {
+ IP13_31_28
+ IP13_27_24
+ IP13_23_20
+ IP13_19_16
+ IP13_15_12
+ IP13_11_8
+ IP13_7_4
+ IP13_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR14", 0xe6060238, 32, 4) {
+ IP14_31_28
+ IP14_27_24
+ IP14_23_20
+ IP14_19_16
+ IP14_15_12
+ IP14_11_8
+ IP14_7_4
+ IP14_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR15", 0xe606023c, 32, 4) {
+ IP15_31_28
+ IP15_27_24
+ IP15_23_20
+ IP15_19_16
+ IP15_15_12
+ IP15_11_8
+ IP15_7_4
+ IP15_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR16", 0xe6060240, 32, 4) {
+ IP16_31_28
+ IP16_27_24
+ IP16_23_20
+ IP16_19_16
+ IP16_15_12
+ IP16_11_8
+ IP16_7_4
+ IP16_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR17", 0xe6060244, 32, 4) {
+ /* IP17_31_28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* IP17_27_24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* IP17_23_20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* IP17_19_16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* IP17_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* IP17_11_8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ IP17_7_4
+ IP17_3_0 }
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32,
+ 1, 2, 2, 3, 1, 1, 2, 1, 1, 1,
+ 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1) {
+ 0, 0, /* RESERVED 31 */
+ MOD_SEL0_30_29
+ MOD_SEL0_28_27
+ MOD_SEL0_26_25_24
+ MOD_SEL0_23
+ MOD_SEL0_22
+ MOD_SEL0_21_20
+ MOD_SEL0_19
+ MOD_SEL0_18
+ MOD_SEL0_17
+ MOD_SEL0_16_15
+ MOD_SEL0_14
+ MOD_SEL0_13
+ MOD_SEL0_12
+ MOD_SEL0_11
+ MOD_SEL0_10
+ MOD_SEL0_9
+ MOD_SEL0_8
+ MOD_SEL0_7_6
+ MOD_SEL0_5_4
+ MOD_SEL0_3
+ MOD_SEL0_2_1
+ 0, 0, /* RESERVED 0 */ }
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32,
+ 2, 3, 1, 2, 3, 1, 1, 2, 1,
+ 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1) {
+ MOD_SEL1_31_30
+ MOD_SEL1_29_28_27
+ MOD_SEL1_26
+ MOD_SEL1_25_24
+ MOD_SEL1_23_22_21
+ MOD_SEL1_20
+ MOD_SEL1_19
+ MOD_SEL1_18_17
+ MOD_SEL1_16
+ MOD_SEL1_15_14
+ MOD_SEL1_13
+ MOD_SEL1_12
+ MOD_SEL1_11
+ MOD_SEL1_10
+ MOD_SEL1_9
+ 0, 0, 0, 0, /* RESERVED 8, 7 */
+ MOD_SEL1_6
+ MOD_SEL1_5
+ MOD_SEL1_4
+ MOD_SEL1_3
+ MOD_SEL1_2
+ MOD_SEL1_1
+ MOD_SEL1_0 }
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xe6060508, 32,
+ 1, 1, 1, 1, 4, 4, 4,
+ 4, 4, 4, 1, 2, 1) {
+ MOD_SEL2_31
+ MOD_SEL2_30
+ MOD_SEL2_29
+ /* RESERVED 28 */
+ 0, 0,
+ /* RESERVED 27, 26, 25, 24 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 23, 22, 21, 20 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 19, 18, 17, 16 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 15, 14, 13, 12 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 11, 10, 9, 8 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 7, 6, 5, 4 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 3 */
+ 0, 0,
+ MOD_SEL2_2_1
+ MOD_SEL2_0 }
+ },
+ { },
+};
+
+const struct sh_pfc_soc_info r8a7795_pinmux_info = {
+ .name = "r8a77950_pfc",
+ .unlock_reg = 0xe6060000, /* PMMR */
+
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .pins = pinmux_pins,
+ .nr_pins = ARRAY_SIZE(pinmux_pins),
+ .groups = pinmux_groups,
+ .nr_groups = ARRAY_SIZE(pinmux_groups),
+ .functions = pinmux_functions,
+ .nr_functions = ARRAY_SIZE(pinmux_functions),
+
+ .cfg_regs = pinmux_config_regs,
+
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
+};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7203.c b/drivers/pinctrl/sh-pfc/pfc-sh7203.c
index 3bda7bafd0ab..61b27ec48876 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7203.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7203.c
@@ -1587,6 +1587,6 @@ const struct sh_pfc_soc_info sh7203_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7264.c b/drivers/pinctrl/sh-pfc/pfc-sh7264.c
index e1cb6dc05028..8070765311db 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7264.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7264.c
@@ -2126,6 +2126,6 @@ const struct sh_pfc_soc_info sh7264_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7269.c b/drivers/pinctrl/sh-pfc/pfc-sh7269.c
index 7a11320ad96d..a50d22bef1f4 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7269.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7269.c
@@ -2830,6 +2830,6 @@ const struct sh_pfc_soc_info sh7269_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index 097526576f88..6a69c8c5d943 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -3649,38 +3649,38 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
};
static const struct pinmux_irq pinmux_irqs[] = {
- PINMUX_IRQ(irq_pin(0), 11),
- PINMUX_IRQ(irq_pin(1), 10),
- PINMUX_IRQ(irq_pin(2), 149),
- PINMUX_IRQ(irq_pin(3), 224),
- PINMUX_IRQ(irq_pin(4), 159),
- PINMUX_IRQ(irq_pin(5), 227),
- PINMUX_IRQ(irq_pin(6), 147),
- PINMUX_IRQ(irq_pin(7), 150),
- PINMUX_IRQ(irq_pin(8), 223),
- PINMUX_IRQ(irq_pin(9), 56, 308),
- PINMUX_IRQ(irq_pin(10), 54),
- PINMUX_IRQ(irq_pin(11), 238),
- PINMUX_IRQ(irq_pin(12), 156),
- PINMUX_IRQ(irq_pin(13), 239),
- PINMUX_IRQ(irq_pin(14), 251),
- PINMUX_IRQ(irq_pin(15), 0),
- PINMUX_IRQ(irq_pin(16), 249),
- PINMUX_IRQ(irq_pin(17), 234),
- PINMUX_IRQ(irq_pin(18), 13),
- PINMUX_IRQ(irq_pin(19), 9),
- PINMUX_IRQ(irq_pin(20), 14),
- PINMUX_IRQ(irq_pin(21), 15),
- PINMUX_IRQ(irq_pin(22), 40),
- PINMUX_IRQ(irq_pin(23), 53),
- PINMUX_IRQ(irq_pin(24), 118),
- PINMUX_IRQ(irq_pin(25), 164),
- PINMUX_IRQ(irq_pin(26), 115),
- PINMUX_IRQ(irq_pin(27), 116),
- PINMUX_IRQ(irq_pin(28), 117),
- PINMUX_IRQ(irq_pin(29), 28),
- PINMUX_IRQ(irq_pin(30), 27),
- PINMUX_IRQ(irq_pin(31), 26),
+ PINMUX_IRQ(11), /* IRQ0 */
+ PINMUX_IRQ(10), /* IRQ1 */
+ PINMUX_IRQ(149), /* IRQ2 */
+ PINMUX_IRQ(224), /* IRQ3 */
+ PINMUX_IRQ(159), /* IRQ4 */
+ PINMUX_IRQ(227), /* IRQ5 */
+ PINMUX_IRQ(147), /* IRQ6 */
+ PINMUX_IRQ(150), /* IRQ7 */
+ PINMUX_IRQ(223), /* IRQ8 */
+ PINMUX_IRQ(56, 308), /* IRQ9 */
+ PINMUX_IRQ(54), /* IRQ10 */
+ PINMUX_IRQ(238), /* IRQ11 */
+ PINMUX_IRQ(156), /* IRQ12 */
+ PINMUX_IRQ(239), /* IRQ13 */
+ PINMUX_IRQ(251), /* IRQ14 */
+ PINMUX_IRQ(0), /* IRQ15 */
+ PINMUX_IRQ(249), /* IRQ16 */
+ PINMUX_IRQ(234), /* IRQ17 */
+ PINMUX_IRQ(13), /* IRQ18 */
+ PINMUX_IRQ(9), /* IRQ19 */
+ PINMUX_IRQ(14), /* IRQ20 */
+ PINMUX_IRQ(15), /* IRQ21 */
+ PINMUX_IRQ(40), /* IRQ22 */
+ PINMUX_IRQ(53), /* IRQ23 */
+ PINMUX_IRQ(118), /* IRQ24 */
+ PINMUX_IRQ(164), /* IRQ25 */
+ PINMUX_IRQ(115), /* IRQ26 */
+ PINMUX_IRQ(116), /* IRQ27 */
+ PINMUX_IRQ(117), /* IRQ28 */
+ PINMUX_IRQ(28), /* IRQ29 */
+ PINMUX_IRQ(27), /* IRQ30 */
+ PINMUX_IRQ(26), /* IRQ31 */
};
/* -----------------------------------------------------------------------------
@@ -3865,8 +3865,8 @@ const struct sh_pfc_soc_info sh73a0_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
.gpio_irq = pinmux_irqs,
.gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7720.c b/drivers/pinctrl/sh-pfc/pfc-sh7720.c
index 13d05f88bc01..e07a82df42c8 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7720.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7720.c
@@ -1201,6 +1201,6 @@ const struct sh_pfc_soc_info sh7720_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7722.c b/drivers/pinctrl/sh-pfc/pfc-sh7722.c
index 914d872c37a4..29c69133b0ef 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7722.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7722.c
@@ -1741,6 +1741,6 @@ const struct sh_pfc_soc_info sh7722_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7723.c b/drivers/pinctrl/sh-pfc/pfc-sh7723.c
index 4eb7eae2e6d0..8ea18df03492 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7723.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7723.c
@@ -1893,6 +1893,6 @@ const struct sh_pfc_soc_info sh7723_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7724.c b/drivers/pinctrl/sh-pfc/pfc-sh7724.c
index 74a1a7f1317c..7f6c36c1a8fa 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7724.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7724.c
@@ -2175,6 +2175,6 @@ const struct sh_pfc_soc_info sh7724_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7734.c b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
index e53dd1cb1625..e7deb51de7dc 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7734.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
@@ -598,502 +598,502 @@ static const u16 pinmux_data[] = {
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_1_0, A0),
PINMUX_IPSR_DATA(IP0_1_0, ST0_CLKIN),
- PINMUX_IPSR_MODSEL_DATA(IP0_1_0, LCD_DATA0_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_1_0, TCLKA_C, SEL_MTU2_CLK_1),
+ PINMUX_IPSR_MSEL(IP0_1_0, LCD_DATA0_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_1_0, TCLKA_C, SEL_MTU2_CLK_1),
PINMUX_IPSR_DATA(IP0_3_2, A1),
PINMUX_IPSR_DATA(IP0_3_2, ST0_REQ),
- PINMUX_IPSR_MODSEL_DATA(IP0_3_2, LCD_DATA1_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_3_2, TCLKB_C, SEL_MTU2_CLK_1),
+ PINMUX_IPSR_MSEL(IP0_3_2, LCD_DATA1_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_3_2, TCLKB_C, SEL_MTU2_CLK_1),
PINMUX_IPSR_DATA(IP0_5_4, A2),
PINMUX_IPSR_DATA(IP0_5_4, ST0_SYC),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_4, LCD_DATA2_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_5_4, TCLKC_C, SEL_MTU2_CLK_1),
+ PINMUX_IPSR_MSEL(IP0_5_4, LCD_DATA2_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_5_4, TCLKC_C, SEL_MTU2_CLK_1),
PINMUX_IPSR_DATA(IP0_7_6, A3),
PINMUX_IPSR_DATA(IP0_7_6, ST0_VLD),
- PINMUX_IPSR_MODSEL_DATA(IP0_7_6, LCD_DATA3_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_7_6, TCLKD_C, SEL_MTU2_CLK_1),
+ PINMUX_IPSR_MSEL(IP0_7_6, LCD_DATA3_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_7_6, TCLKD_C, SEL_MTU2_CLK_1),
PINMUX_IPSR_DATA(IP0_9_8, A4),
PINMUX_IPSR_DATA(IP0_9_8, ST0_D0),
- PINMUX_IPSR_MODSEL_DATA(IP0_9_8, LCD_DATA4_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_9_8, TIOC0A_C, SEL_MTU2_CH0_1),
+ PINMUX_IPSR_MSEL(IP0_9_8, LCD_DATA4_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_9_8, TIOC0A_C, SEL_MTU2_CH0_1),
PINMUX_IPSR_DATA(IP0_11_10, A5),
PINMUX_IPSR_DATA(IP0_11_10, ST0_D1),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_10, LCD_DATA5_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_11_10, TIOC0B_C, SEL_MTU2_CH0_1),
+ PINMUX_IPSR_MSEL(IP0_11_10, LCD_DATA5_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_11_10, TIOC0B_C, SEL_MTU2_CH0_1),
PINMUX_IPSR_DATA(IP0_13_12, A6),
PINMUX_IPSR_DATA(IP0_13_12, ST0_D2),
- PINMUX_IPSR_MODSEL_DATA(IP0_13_12, LCD_DATA6_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_13_12, TIOC0C_C, SEL_MTU2_CH0_1),
+ PINMUX_IPSR_MSEL(IP0_13_12, LCD_DATA6_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_13_12, TIOC0C_C, SEL_MTU2_CH0_1),
PINMUX_IPSR_DATA(IP0_15_14, A7),
PINMUX_IPSR_DATA(IP0_15_14, ST0_D3),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_14, LCD_DATA7_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_15_14, TIOC0D_C, SEL_MTU2_CH0_1),
+ PINMUX_IPSR_MSEL(IP0_15_14, LCD_DATA7_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_15_14, TIOC0D_C, SEL_MTU2_CH0_1),
PINMUX_IPSR_DATA(IP0_17_16, A8),
PINMUX_IPSR_DATA(IP0_17_16, ST0_D4),
- PINMUX_IPSR_MODSEL_DATA(IP0_17_16, LCD_DATA8_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_17_16, TIOC1A_C, SEL_MTU2_CH1_2),
+ PINMUX_IPSR_MSEL(IP0_17_16, LCD_DATA8_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_17_16, TIOC1A_C, SEL_MTU2_CH1_2),
PINMUX_IPSR_DATA(IP0_19_18, A9),
PINMUX_IPSR_DATA(IP0_19_18, ST0_D5),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_18, LCD_DATA9_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_19_18, TIOC1B_C, SEL_MTU2_CH1_2),
+ PINMUX_IPSR_MSEL(IP0_19_18, LCD_DATA9_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_19_18, TIOC1B_C, SEL_MTU2_CH1_2),
PINMUX_IPSR_DATA(IP0_21_20, A10),
PINMUX_IPSR_DATA(IP0_21_20, ST0_D6),
- PINMUX_IPSR_MODSEL_DATA(IP0_21_20, LCD_DATA10_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_21_20, TIOC2A_C, SEL_MTU2_CH2_2),
+ PINMUX_IPSR_MSEL(IP0_21_20, LCD_DATA10_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_21_20, TIOC2A_C, SEL_MTU2_CH2_2),
PINMUX_IPSR_DATA(IP0_23_22, A11),
PINMUX_IPSR_DATA(IP0_23_22, ST0_D7),
- PINMUX_IPSR_MODSEL_DATA(IP0_23_22, LCD_DATA11_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_23_22, TIOC2B_C, SEL_MTU2_CH2_2),
+ PINMUX_IPSR_MSEL(IP0_23_22, LCD_DATA11_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_23_22, TIOC2B_C, SEL_MTU2_CH2_2),
PINMUX_IPSR_DATA(IP0_25_24, A12),
- PINMUX_IPSR_MODSEL_DATA(IP0_25_24, LCD_DATA12_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_25_24, TIOC3A_C, SEL_MTU2_CH3_1),
+ PINMUX_IPSR_MSEL(IP0_25_24, LCD_DATA12_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_25_24, TIOC3A_C, SEL_MTU2_CH3_1),
PINMUX_IPSR_DATA(IP0_27_26, A13),
- PINMUX_IPSR_MODSEL_DATA(IP0_27_26, LCD_DATA13_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_27_26, TIOC3B_C, SEL_MTU2_CH3_1),
+ PINMUX_IPSR_MSEL(IP0_27_26, LCD_DATA13_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_27_26, TIOC3B_C, SEL_MTU2_CH3_1),
PINMUX_IPSR_DATA(IP0_29_28, A14),
- PINMUX_IPSR_MODSEL_DATA(IP0_29_28, LCD_DATA14_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_29_28, TIOC3C_C, SEL_MTU2_CH3_1),
+ PINMUX_IPSR_MSEL(IP0_29_28, LCD_DATA14_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_29_28, TIOC3C_C, SEL_MTU2_CH3_1),
PINMUX_IPSR_DATA(IP0_31_30, A15),
PINMUX_IPSR_DATA(IP0_31_30, ST0_VCO_CLKIN),
- PINMUX_IPSR_MODSEL_DATA(IP0_31_30, LCD_DATA15_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP0_31_30, TIOC3D_C, SEL_MTU2_CH3_1),
+ PINMUX_IPSR_MSEL(IP0_31_30, LCD_DATA15_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP0_31_30, TIOC3D_C, SEL_MTU2_CH3_1),
/* IPSR1 */
PINMUX_IPSR_DATA(IP1_1_0, A16),
PINMUX_IPSR_DATA(IP1_1_0, ST0_PWM),
- PINMUX_IPSR_MODSEL_DATA(IP1_1_0, LCD_DON_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_1_0, TIOC4A_C, SEL_MTU2_CH4_1),
+ PINMUX_IPSR_MSEL(IP1_1_0, LCD_DON_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_1_0, TIOC4A_C, SEL_MTU2_CH4_1),
PINMUX_IPSR_DATA(IP1_3_2, A17),
PINMUX_IPSR_DATA(IP1_3_2, ST1_VCO_CLKIN),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_2, LCD_CL1_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_3_2, TIOC4B_C, SEL_MTU2_CH4_1),
+ PINMUX_IPSR_MSEL(IP1_3_2, LCD_CL1_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_3_2, TIOC4B_C, SEL_MTU2_CH4_1),
PINMUX_IPSR_DATA(IP1_5_4, A18),
PINMUX_IPSR_DATA(IP1_5_4, ST1_PWM),
- PINMUX_IPSR_MODSEL_DATA(IP1_5_4, LCD_CL2_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_5_4, TIOC4C_C, SEL_MTU2_CH4_1),
+ PINMUX_IPSR_MSEL(IP1_5_4, LCD_CL2_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_5_4, TIOC4C_C, SEL_MTU2_CH4_1),
PINMUX_IPSR_DATA(IP1_7_6, A19),
PINMUX_IPSR_DATA(IP1_7_6, ST1_CLKIN),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_6, LCD_CLK_A, SEL_LCDC_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_7_6, TIOC4D_C, SEL_MTU2_CH4_1),
+ PINMUX_IPSR_MSEL(IP1_7_6, LCD_CLK_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_7_6, TIOC4D_C, SEL_MTU2_CH4_1),
PINMUX_IPSR_DATA(IP1_9_8, A20),
PINMUX_IPSR_DATA(IP1_9_8, ST1_REQ),
- PINMUX_IPSR_MODSEL_DATA(IP1_9_8, LCD_FLM_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_9_8, LCD_FLM_A, SEL_LCDC_0),
PINMUX_IPSR_DATA(IP1_11_10, A21),
PINMUX_IPSR_DATA(IP1_11_10, ST1_SYC),
- PINMUX_IPSR_MODSEL_DATA(IP1_11_10, LCD_VCPWC_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_11_10, LCD_VCPWC_A, SEL_LCDC_0),
PINMUX_IPSR_DATA(IP1_13_12, A22),
PINMUX_IPSR_DATA(IP1_13_12, ST1_VLD),
- PINMUX_IPSR_MODSEL_DATA(IP1_13_12, LCD_VEPWC_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_13_12, LCD_VEPWC_A, SEL_LCDC_0),
PINMUX_IPSR_DATA(IP1_15_14, A23),
PINMUX_IPSR_DATA(IP1_15_14, ST1_D0),
- PINMUX_IPSR_MODSEL_DATA(IP1_15_14, LCD_M_DISP_A, SEL_LCDC_0),
+ PINMUX_IPSR_MSEL(IP1_15_14, LCD_M_DISP_A, SEL_LCDC_0),
PINMUX_IPSR_DATA(IP1_17_16, A24),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_16, RX2_D, SEL_SCIF2_3),
+ PINMUX_IPSR_MSEL(IP1_17_16, RX2_D, SEL_SCIF2_3),
PINMUX_IPSR_DATA(IP1_17_16, ST1_D1),
PINMUX_IPSR_DATA(IP1_19_18, A25),
- PINMUX_IPSR_MODSEL_DATA(IP1_17_16, RX2_D, SEL_SCIF2_3),
+ PINMUX_IPSR_MSEL(IP1_17_16, RX2_D, SEL_SCIF2_3),
PINMUX_IPSR_DATA(IP1_17_16, ST1_D2),
PINMUX_IPSR_DATA(IP1_22_20, D0),
- PINMUX_IPSR_MODSEL_DATA(IP1_22_20, SD0_DAT0_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_22_20, MMC_D0_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP1_22_20, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP1_22_20, MMC_D0_A, SEL_MMC_0),
PINMUX_IPSR_DATA(IP1_22_20, ST1_D3),
- PINMUX_IPSR_MODSEL_DATA(IP1_22_20, FD0_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP1_22_20, FD0_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP1_25_23, D1),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_23, SD0_DAT0_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_23, MMC_D1_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP1_25_23, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP1_25_23, MMC_D1_A, SEL_MMC_0),
PINMUX_IPSR_DATA(IP1_25_23, ST1_D4),
- PINMUX_IPSR_MODSEL_DATA(IP1_25_23, FD1_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP1_25_23, FD1_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP1_28_26, D2),
- PINMUX_IPSR_MODSEL_DATA(IP1_28_26, SD0_DAT0_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_28_26, MMC_D2_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP1_28_26, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP1_28_26, MMC_D2_A, SEL_MMC_0),
PINMUX_IPSR_DATA(IP1_28_26, ST1_D5),
- PINMUX_IPSR_MODSEL_DATA(IP1_28_26, FD2_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP1_28_26, FD2_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP1_31_29, D3),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_29, SD0_DAT0_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_29, MMC_D3_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP1_31_29, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP1_31_29, MMC_D3_A, SEL_MMC_0),
PINMUX_IPSR_DATA(IP1_31_29, ST1_D6),
- PINMUX_IPSR_MODSEL_DATA(IP1_31_29, FD3_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP1_31_29, FD3_A, SEL_FLCTL_0),
/* IPSR2 */
PINMUX_IPSR_DATA(IP2_2_0, D4),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SD0_CD_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, MMC_D4_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP2_2_0, SD0_CD_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP2_2_0, MMC_D4_A, SEL_MMC_0),
PINMUX_IPSR_DATA(IP2_2_0, ST1_D7),
- PINMUX_IPSR_MODSEL_DATA(IP2_2_0, FD4_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_2_0, FD4_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP2_4_3, D5),
- PINMUX_IPSR_MODSEL_DATA(IP2_4_3, SD0_WP_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_4_3, MMC_D5_A, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_4_3, FD5_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_4_3, SD0_WP_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP2_4_3, MMC_D5_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP2_4_3, FD5_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP2_7_5, D6),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_5, RSPI_RSPCK_A, SEL_RSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_5, MMC_D6_A, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_5, QSPCLK_A, SEL_RQSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_7_5, FD6_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_7_5, RSPI_RSPCK_A, SEL_RSPI_0),
+ PINMUX_IPSR_MSEL(IP2_7_5, MMC_D6_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP2_7_5, QSPCLK_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MSEL(IP2_7_5, FD6_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP2_10_8, D7),
- PINMUX_IPSR_MODSEL_DATA(IP2_10_8, RSPI_SSL_A, SEL_RSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_10_8, MMC_D7_A, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_10_8, QSSL_A, SEL_RQSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_10_8, FD7_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_10_8, RSPI_SSL_A, SEL_RSPI_0),
+ PINMUX_IPSR_MSEL(IP2_10_8, MMC_D7_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP2_10_8, QSSL_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MSEL(IP2_10_8, FD7_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP2_13_11, D8),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_11, SD0_CLK_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_11, MMC_CLK_A, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_11, QIO2_A, SEL_RQSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_11, FCE_A, SEL_FLCTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_13_11, ET0_GTX_CLK_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP2_13_11, SD0_CLK_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP2_13_11, MMC_CLK_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP2_13_11, QIO2_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MSEL(IP2_13_11, FCE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_13_11, ET0_GTX_CLK_B, SEL_ET0_1),
PINMUX_IPSR_DATA(IP2_16_14, D9),
- PINMUX_IPSR_MODSEL_DATA(IP2_16_14, SD0_CMD_A, SEL_SDHI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_16_14, MMC_CMD_A, SEL_MMC_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_16_14, QIO3_A, SEL_RQSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_16_14, FCLE_A, SEL_FLCTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_16_14, ET0_ETXD1_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP2_16_14, SD0_CMD_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MSEL(IP2_16_14, MMC_CMD_A, SEL_MMC_0),
+ PINMUX_IPSR_MSEL(IP2_16_14, QIO3_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MSEL(IP2_16_14, FCLE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_16_14, ET0_ETXD1_B, SEL_ET0_1),
PINMUX_IPSR_DATA(IP2_19_17, D10),
- PINMUX_IPSR_MODSEL_DATA(IP2_19_17, RSPI_MOSI_A, SEL_RSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_19_17, QMO_QIO0_A, SEL_RQSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_19_17, FALE_A, SEL_FLCTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_19_17, ET0_ETXD2_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP2_19_17, RSPI_MOSI_A, SEL_RSPI_0),
+ PINMUX_IPSR_MSEL(IP2_19_17, QMO_QIO0_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MSEL(IP2_19_17, FALE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_19_17, ET0_ETXD2_B, SEL_ET0_1),
PINMUX_IPSR_DATA(IP2_22_20, D11),
- PINMUX_IPSR_MODSEL_DATA(IP2_22_20, RSPI_MISO_A, SEL_RSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_22_20, QMI_QIO1_A, SEL_RQSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_22_20, FRE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_22_20, RSPI_MISO_A, SEL_RSPI_0),
+ PINMUX_IPSR_MSEL(IP2_22_20, QMI_QIO1_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MSEL(IP2_22_20, FRE_A, SEL_FLCTL_0),
PINMUX_IPSR_DATA(IP2_24_23, D12),
- PINMUX_IPSR_MODSEL_DATA(IP2_24_23, FWE_A, SEL_FLCTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_24_23, ET0_ETXD5_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP2_24_23, FWE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_24_23, ET0_ETXD5_B, SEL_ET0_1),
PINMUX_IPSR_DATA(IP2_27_25, D13),
- PINMUX_IPSR_MODSEL_DATA(IP2_27_25, RX2_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_27_25, FRB_A, SEL_FLCTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_27_25, ET0_ETXD6_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP2_27_25, RX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP2_27_25, FRB_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_27_25, ET0_ETXD6_B, SEL_ET0_1),
PINMUX_IPSR_DATA(IP2_30_28, D14),
- PINMUX_IPSR_MODSEL_DATA(IP2_30_28, TX2_B, SEL_SCIF2_1),
- PINMUX_IPSR_MODSEL_DATA(IP2_30_28, FSE_A, SEL_FLCTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP2_30_28, ET0_TX_CLK_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP2_30_28, TX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP2_30_28, FSE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MSEL(IP2_30_28, ET0_TX_CLK_B, SEL_ET0_1),
/* IPSR3 */
PINMUX_IPSR_DATA(IP3_1_0, D15),
- PINMUX_IPSR_MODSEL_DATA(IP3_1_0, SCK2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP3_1_0, SCK2_B, SEL_SCIF2_1),
PINMUX_IPSR_DATA(IP3_2, CS1_A26),
- PINMUX_IPSR_MODSEL_DATA(IP3_2, QIO3_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MSEL(IP3_2, QIO3_B, SEL_RQSPI_1),
PINMUX_IPSR_DATA(IP3_5_3, EX_CS1),
- PINMUX_IPSR_MODSEL_DATA(IP3_5_3, RX3_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MSEL(IP3_5_3, RX3_B, SEL_SCIF2_1),
PINMUX_IPSR_DATA(IP3_5_3, ATACS0),
- PINMUX_IPSR_MODSEL_DATA(IP3_5_3, QIO2_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MSEL(IP3_5_3, QIO2_B, SEL_RQSPI_1),
PINMUX_IPSR_DATA(IP3_5_3, ET0_ETXD0),
PINMUX_IPSR_DATA(IP3_8_6, EX_CS2),
- PINMUX_IPSR_MODSEL_DATA(IP3_8_6, TX3_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP3_8_6, TX3_B, SEL_SCIF3_1),
PINMUX_IPSR_DATA(IP3_8_6, ATACS1),
- PINMUX_IPSR_MODSEL_DATA(IP3_8_6, QSPCLK_B, SEL_RQSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_8_6, ET0_GTX_CLK_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP3_8_6, QSPCLK_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MSEL(IP3_8_6, ET0_GTX_CLK_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP3_11_9, EX_CS3),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, SD1_CD_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP3_11_9, SD1_CD_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP3_11_9, ATARD),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, QMO_QIO0_B, SEL_RQSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_11_9, ET0_ETXD1_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP3_11_9, QMO_QIO0_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MSEL(IP3_11_9, ET0_ETXD1_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP3_14_12, EX_CS4),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, SD1_WP_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP3_14_12, SD1_WP_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP3_14_12, ATAWR),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, QMI_QIO1_B, SEL_RQSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_14_12, ET0_ETXD2_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP3_14_12, QMI_QIO1_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MSEL(IP3_14_12, ET0_ETXD2_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP3_17_15, EX_CS5),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, SD1_CMD_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP3_17_15, SD1_CMD_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP3_17_15, ATADIR),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, QSSL_B, SEL_RQSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP3_17_15, ET0_ETXD3_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP3_17_15, QSSL_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MSEL(IP3_17_15, ET0_ETXD3_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP3_19_18, RD_WR),
PINMUX_IPSR_DATA(IP3_19_18, TCLK0),
- PINMUX_IPSR_MODSEL_DATA(IP3_19_18, CAN_CLK_B, SEL_RCAN_CLK_1),
+ PINMUX_IPSR_MSEL(IP3_19_18, CAN_CLK_B, SEL_RCAN_CLK_1),
PINMUX_IPSR_DATA(IP3_19_18, ET0_ETXD4),
PINMUX_IPSR_DATA(IP3_20, EX_WAIT0),
- PINMUX_IPSR_MODSEL_DATA(IP3_20, TCLK1_B, SEL_TMU_1),
+ PINMUX_IPSR_MSEL(IP3_20, TCLK1_B, SEL_TMU_1),
PINMUX_IPSR_DATA(IP3_23_21, EX_WAIT1),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, SD1_DAT0_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP3_23_21, SD1_DAT0_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP3_23_21, DREQ2),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, CAN1_TX_C, SEL_RCAN1_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, ET0_LINK_C, SEL_ET0_CTL_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_23_21, ET0_ETXD5_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP3_23_21, CAN1_TX_C, SEL_RCAN1_2),
+ PINMUX_IPSR_MSEL(IP3_23_21, ET0_LINK_C, SEL_ET0_CTL_2),
+ PINMUX_IPSR_MSEL(IP3_23_21, ET0_ETXD5_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP3_26_24, EX_WAIT2),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, SD1_DAT1_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP3_26_24, SD1_DAT1_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP3_26_24, DACK2),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, CAN1_RX_C, SEL_RCAN1_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, ET0_MAGIC_C, SEL_ET0_CTL_2),
- PINMUX_IPSR_MODSEL_DATA(IP3_26_24, ET0_ETXD6_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP3_26_24, CAN1_RX_C, SEL_RCAN1_2),
+ PINMUX_IPSR_MSEL(IP3_26_24, ET0_MAGIC_C, SEL_ET0_CTL_2),
+ PINMUX_IPSR_MSEL(IP3_26_24, ET0_ETXD6_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP3_29_27, DRACK0),
- PINMUX_IPSR_MODSEL_DATA(IP3_29_27, SD1_DAT2_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP3_29_27, SD1_DAT2_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP3_29_27, ATAG),
- PINMUX_IPSR_MODSEL_DATA(IP3_29_27, TCLK1_A, SEL_TMU_0),
+ PINMUX_IPSR_MSEL(IP3_29_27, TCLK1_A, SEL_TMU_0),
PINMUX_IPSR_DATA(IP3_29_27, ET0_ETXD7),
/* IPSR4 */
- PINMUX_IPSR_MODSEL_DATA(IP4_2_0, HCTS0_A, SEL_HSCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_2_0, CTS1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP4_2_0, HCTS0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MSEL(IP4_2_0, CTS1_A, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP4_2_0, VI0_FIELD),
- PINMUX_IPSR_MODSEL_DATA(IP4_2_0, RMII0_RXD1_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP4_2_0, RMII0_RXD1_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP4_2_0, ET0_ERXD7),
- PINMUX_IPSR_MODSEL_DATA(IP4_5_3, HRTS0_A, SEL_HSCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_5_3, RTS1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP4_5_3, HRTS0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MSEL(IP4_5_3, RTS1_A, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP4_5_3, VI0_HSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP4_5_3, RMII0_TXD_EN_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP4_5_3, RMII0_TXD_EN_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP4_5_3, ET0_RX_DV),
- PINMUX_IPSR_MODSEL_DATA(IP4_8_6, HSCK0_A, SEL_HSCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_8_6, SCK1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP4_8_6, HSCK0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MSEL(IP4_8_6, SCK1_A, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP4_8_6, VI0_VSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP4_8_6, RMII0_RX_ER_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP4_8_6, RMII0_RX_ER_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP4_8_6, ET0_RX_ER),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, HRX0_A, SEL_HSCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, RX1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP4_11_9, HRX0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MSEL(IP4_11_9, RX1_A, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP4_11_9, VI0_DATA0_VI0_B0),
- PINMUX_IPSR_MODSEL_DATA(IP4_11_9, RMII0_CRS_DV_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP4_11_9, RMII0_CRS_DV_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP4_11_9, ET0_CRS),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, HTX0_A, SEL_HSCIF_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, TX1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_MSEL(IP4_14_12, HTX0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MSEL(IP4_14_12, TX1_A, SEL_SCIF1_0),
PINMUX_IPSR_DATA(IP4_14_12, VI0_DATA1_VI0_B1),
- PINMUX_IPSR_MODSEL_DATA(IP4_14_12, RMII0_MDC_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP4_14_12, RMII0_MDC_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP4_14_12, ET0_COL),
- PINMUX_IPSR_MODSEL_DATA(IP4_17_15, CTS0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP4_17_15, CTS0_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP4_17_15, VI0_DATA2_VI0_B2),
- PINMUX_IPSR_MODSEL_DATA(IP4_17_15, RMII0_MDIO_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP4_17_15, RMII0_MDIO_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP4_17_15, ET0_MDC),
- PINMUX_IPSR_MODSEL_DATA(IP4_19_18, RTS0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP4_19_18, RTS0_B, SEL_SCIF0_1),
PINMUX_IPSR_DATA(IP4_19_18, VI0_DATA3_VI0_B3),
- PINMUX_IPSR_MODSEL_DATA(IP4_19_18, ET0_MDIO_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP4_19_18, ET0_MDIO_A, SEL_ET0_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_21_20, SCK1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_21_20, SCK1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP4_21_20, VI0_DATA4_VI0_B4),
- PINMUX_IPSR_MODSEL_DATA(IP4_21_20, ET0_LINK_A, SEL_ET0_CTL_0),
+ PINMUX_IPSR_MSEL(IP4_21_20, ET0_LINK_A, SEL_ET0_CTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_22, RX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_23_22, RX1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP4_23_22, VI0_DATA5_VI0_B5),
- PINMUX_IPSR_MODSEL_DATA(IP4_23_22, ET0_MAGIC_A, SEL_ET0_CTL_0),
+ PINMUX_IPSR_MSEL(IP4_23_22, ET0_MAGIC_A, SEL_ET0_CTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_25_24, TX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_25_24, TX1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP4_25_24, VI0_DATA6_VI0_G0),
- PINMUX_IPSR_MODSEL_DATA(IP4_25_24, ET0_PHY_INT_A, SEL_ET0_CTL_0),
+ PINMUX_IPSR_MSEL(IP4_25_24, ET0_PHY_INT_A, SEL_ET0_CTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP4_27_26, CTS1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_27_26, CTS1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP4_27_26, VI0_DATA7_VI0_G1),
- PINMUX_IPSR_MODSEL_DATA(IP4_29_28, RTS1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_MSEL(IP4_29_28, RTS1_B, SEL_SCIF1_1),
PINMUX_IPSR_DATA(IP4_29_28, VI0_G2),
- PINMUX_IPSR_MODSEL_DATA(IP4_31_30, SCK2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP4_31_30, SCK2_A, SEL_SCIF2_0),
PINMUX_IPSR_DATA(IP4_31_30, VI0_G3),
/* IPSR5 */
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, SD2_CLK_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, RX2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP5_2_0, SD2_CLK_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_2_0, RX2_A, SEL_SCIF2_0),
PINMUX_IPSR_DATA(IP5_2_0, VI0_G4),
- PINMUX_IPSR_MODSEL_DATA(IP5_2_0, ET0_RX_CLK_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP5_2_0, ET0_RX_CLK_B, SEL_ET0_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, SD2_CMD_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, TX2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, SD2_CMD_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_5_3, TX2_A, SEL_SCIF2_0),
PINMUX_IPSR_DATA(IP5_5_3, VI0_G5),
- PINMUX_IPSR_MODSEL_DATA(IP5_5_3, ET0_ERXD2_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP5_5_3, ET0_ERXD2_B, SEL_ET0_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, SD2_DAT0_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_8_6, RX3_A, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP5_8_6, SD2_DAT0_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_8_6, RX3_A, SEL_SCIF3_0),
PINMUX_IPSR_DATA(IP4_8_6, VI0_R0),
- PINMUX_IPSR_MODSEL_DATA(IP4_8_6, ET0_ERXD2_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP4_8_6, ET0_ERXD2_B, SEL_ET0_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, SD2_DAT1_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, TX3_A, SEL_SCIF3_0),
+ PINMUX_IPSR_MSEL(IP5_11_9, SD2_DAT1_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_11_9, TX3_A, SEL_SCIF3_0),
PINMUX_IPSR_DATA(IP5_11_9, VI0_R1),
- PINMUX_IPSR_MODSEL_DATA(IP5_11_9, ET0_MDIO_B, SEL_ET0_1),
+ PINMUX_IPSR_MSEL(IP5_11_9, ET0_MDIO_B, SEL_ET0_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_12, SD2_DAT2_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_12, RX4_A, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP5_14_12, SD2_DAT2_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_14_12, RX4_A, SEL_SCIF4_0),
PINMUX_IPSR_DATA(IP5_14_12, VI0_R2),
- PINMUX_IPSR_MODSEL_DATA(IP5_14_12, ET0_LINK_B, SEL_ET0_CTL_1),
+ PINMUX_IPSR_MSEL(IP5_14_12, ET0_LINK_B, SEL_ET0_CTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_17_15, SD2_DAT3_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_17_15, TX4_A, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP5_17_15, SD2_DAT3_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_17_15, TX4_A, SEL_SCIF4_0),
PINMUX_IPSR_DATA(IP5_17_15, VI0_R3),
- PINMUX_IPSR_MODSEL_DATA(IP5_17_15, ET0_MAGIC_B, SEL_ET0_CTL_1),
+ PINMUX_IPSR_MSEL(IP5_17_15, ET0_MAGIC_B, SEL_ET0_CTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, SD2_CD_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, RX5_A, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP5_20_18, SD2_CD_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_20_18, RX5_A, SEL_SCIF5_0),
PINMUX_IPSR_DATA(IP5_20_18, VI0_R4),
- PINMUX_IPSR_MODSEL_DATA(IP5_20_18, ET0_PHY_INT_B, SEL_ET0_CTL_1),
+ PINMUX_IPSR_MSEL(IP5_20_18, ET0_PHY_INT_B, SEL_ET0_CTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP5_22_21, SD2_WP_A, SEL_SDHI2_0),
- PINMUX_IPSR_MODSEL_DATA(IP5_22_21, TX5_A, SEL_SCIF5_0),
+ PINMUX_IPSR_MSEL(IP5_22_21, SD2_WP_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MSEL(IP5_22_21, TX5_A, SEL_SCIF5_0),
PINMUX_IPSR_DATA(IP5_22_21, VI0_R5),
PINMUX_IPSR_DATA(IP5_24_23, REF125CK),
PINMUX_IPSR_DATA(IP5_24_23, ADTRG),
- PINMUX_IPSR_MODSEL_DATA(IP5_24_23, RX5_C, SEL_SCIF5_2),
+ PINMUX_IPSR_MSEL(IP5_24_23, RX5_C, SEL_SCIF5_2),
PINMUX_IPSR_DATA(IP5_26_25, REF50CK),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_25, CTS1_E, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP5_26_25, HCTS0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MSEL(IP5_26_25, CTS1_E, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP5_26_25, HCTS0_D, SEL_HSCIF_3),
/* IPSR6 */
PINMUX_IPSR_DATA(IP6_2_0, DU0_DR0),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SCIF_CLK_B, SEL_SCIF_CLK_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, HRX0_D, SEL_HSCIF_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, IETX_A, SEL_IEBUS_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_2_0, TCLKA_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_MSEL(IP6_2_0, SCIF_CLK_B, SEL_SCIF_CLK_1),
+ PINMUX_IPSR_MSEL(IP6_2_0, HRX0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MSEL(IP6_2_0, IETX_A, SEL_IEBUS_0),
+ PINMUX_IPSR_MSEL(IP6_2_0, TCLKA_A, SEL_MTU2_CLK_0),
PINMUX_IPSR_DATA(IP6_2_0, HIFD00),
PINMUX_IPSR_DATA(IP6_5_3, DU0_DR1),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SCK0_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, HTX0_D, SEL_HSCIF_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, IERX_A, SEL_IEBUS_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_5_3, TCLKB_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_MSEL(IP6_5_3, SCK0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_5_3, HTX0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MSEL(IP6_5_3, IERX_A, SEL_IEBUS_0),
+ PINMUX_IPSR_MSEL(IP6_5_3, TCLKB_A, SEL_MTU2_CLK_0),
PINMUX_IPSR_DATA(IP6_5_3, HIFD01),
PINMUX_IPSR_DATA(IP6_7_6, DU0_DR2),
- PINMUX_IPSR_MODSEL_DATA(IP6_7_6, RX0_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_7_6, TCLKC_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_MSEL(IP6_7_6, RX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_7_6, TCLKC_A, SEL_MTU2_CLK_0),
PINMUX_IPSR_DATA(IP6_7_6, HIFD02),
PINMUX_IPSR_DATA(IP6_9_8, DU0_DR3),
- PINMUX_IPSR_MODSEL_DATA(IP6_9_8, TX0_B, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_9_8, TCLKD_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_MSEL(IP6_9_8, TX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_9_8, TCLKD_A, SEL_MTU2_CLK_0),
PINMUX_IPSR_DATA(IP6_9_8, HIFD03),
PINMUX_IPSR_DATA(IP6_11_10, DU0_DR4),
- PINMUX_IPSR_MODSEL_DATA(IP6_11_10, CTS0_C, SEL_SCIF0_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_11_10, TIOC0A_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_MSEL(IP6_11_10, CTS0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MSEL(IP6_11_10, TIOC0A_A, SEL_MTU2_CH0_0),
PINMUX_IPSR_DATA(IP6_11_10, HIFD04),
PINMUX_IPSR_DATA(IP6_13_12, DU0_DR5),
- PINMUX_IPSR_MODSEL_DATA(IP6_13_12, RTS0_C, SEL_SCIF0_1),
- PINMUX_IPSR_MODSEL_DATA(IP6_13_12, TIOC0B_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_MSEL(IP6_13_12, RTS0_C, SEL_SCIF0_1),
+ PINMUX_IPSR_MSEL(IP6_13_12, TIOC0B_A, SEL_MTU2_CH0_0),
PINMUX_IPSR_DATA(IP6_13_12, HIFD05),
PINMUX_IPSR_DATA(IP6_15_14, DU0_DR6),
- PINMUX_IPSR_MODSEL_DATA(IP6_15_14, SCK1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_15_14, TIOC0C_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_MSEL(IP6_15_14, SCK1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_15_14, TIOC0C_A, SEL_MTU2_CH0_0),
PINMUX_IPSR_DATA(IP6_15_14, HIFD06),
PINMUX_IPSR_DATA(IP6_17_16, DU0_DR7),
- PINMUX_IPSR_MODSEL_DATA(IP6_17_16, RX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_17_16, TIOC0D_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_MSEL(IP6_17_16, RX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_17_16, TIOC0D_A, SEL_MTU2_CH0_0),
PINMUX_IPSR_DATA(IP6_17_16, HIFD07),
PINMUX_IPSR_DATA(IP6_20_18, DU0_DG0),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_18, TX1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_18, HSCK0_D, SEL_HSCIF_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_18, IECLK_A, SEL_IEBUS_0),
- PINMUX_IPSR_MODSEL_DATA(IP6_20_18, TIOC1A_A, SEL_MTU2_CH1_0),
+ PINMUX_IPSR_MSEL(IP6_20_18, TX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_20_18, HSCK0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MSEL(IP6_20_18, IECLK_A, SEL_IEBUS_0),
+ PINMUX_IPSR_MSEL(IP6_20_18, TIOC1A_A, SEL_MTU2_CH1_0),
PINMUX_IPSR_DATA(IP6_20_18, HIFD08),
PINMUX_IPSR_DATA(IP6_23_21, DU0_DG1),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, CTS1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, HRTS0_D, SEL_HSCIF_3),
- PINMUX_IPSR_MODSEL_DATA(IP6_23_21, TIOC1B_A, SEL_MTU2_CH1_0),
+ PINMUX_IPSR_MSEL(IP6_23_21, CTS1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP6_23_21, HRTS0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MSEL(IP6_23_21, TIOC1B_A, SEL_MTU2_CH1_0),
PINMUX_IPSR_DATA(IP6_23_21, HIFD09),
/* IPSR7 */
PINMUX_IPSR_DATA(IP7_2_0, DU0_DG2),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, RTS1_C, SEL_SCIF1_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, RMII0_MDC_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_2_0, TIOC2A_A, SEL_MTU2_CH2_0),
+ PINMUX_IPSR_MSEL(IP7_2_0, RTS1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP7_2_0, RMII0_MDC_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_2_0, TIOC2A_A, SEL_MTU2_CH2_0),
PINMUX_IPSR_DATA(IP7_2_0, HIFD10),
PINMUX_IPSR_DATA(IP7_5_3, DU0_DG3),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, SCK2_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, RMII0_MDIO_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_5_3, TIOC2B_A, SEL_MTU2_CH2_0),
+ PINMUX_IPSR_MSEL(IP7_5_3, SCK2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP7_5_3, RMII0_MDIO_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_5_3, TIOC2B_A, SEL_MTU2_CH2_0),
PINMUX_IPSR_DATA(IP7_5_3, HIFD11),
PINMUX_IPSR_DATA(IP7_8_6, DU0_DG4),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, RX2_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, RMII0_CRS_DV_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_8_6, TIOC3A_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_MSEL(IP7_8_6, RX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP7_8_6, RMII0_CRS_DV_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_8_6, TIOC3A_A, SEL_MTU2_CH3_0),
PINMUX_IPSR_DATA(IP7_8_6, HIFD12),
PINMUX_IPSR_DATA(IP7_11_9, DU0_DG5),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, TX2_C, SEL_SCIF2_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, RMII0_RX_ER_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_11_9, TIOC3B_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_MSEL(IP7_11_9, TX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MSEL(IP7_11_9, RMII0_RX_ER_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_11_9, TIOC3B_A, SEL_MTU2_CH3_0),
PINMUX_IPSR_DATA(IP7_11_9, HIFD13),
PINMUX_IPSR_DATA(IP7_14_12, DU0_DG6),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, RX3_C, SEL_SCIF3_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, RMII0_RXD0_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_14_12, TIOC3C_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_MSEL(IP7_14_12, RX3_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MSEL(IP7_14_12, RMII0_RXD0_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_14_12, TIOC3C_A, SEL_MTU2_CH3_0),
PINMUX_IPSR_DATA(IP7_14_12, HIFD14),
PINMUX_IPSR_DATA(IP7_17_15, DU0_DG7),
- PINMUX_IPSR_MODSEL_DATA(IP7_17_15, TX3_C, SEL_SCIF3_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_17_15, RMII0_RXD1_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_17_15, TIOC3D_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_MSEL(IP7_17_15, TX3_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MSEL(IP7_17_15, RMII0_RXD1_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_17_15, TIOC3D_A, SEL_MTU2_CH3_0),
PINMUX_IPSR_DATA(IP7_17_15, HIFD15),
PINMUX_IPSR_DATA(IP7_20_18, DU0_DB0),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, RX4_C, SEL_SCIF4_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, RMII0_TXD_EN_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_20_18, TIOC4A_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_MSEL(IP7_20_18, RX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP7_20_18, RMII0_TXD_EN_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_20_18, TIOC4A_A, SEL_MTU2_CH4_0),
PINMUX_IPSR_DATA(IP7_20_18, HIFCS),
PINMUX_IPSR_DATA(IP7_23_21, DU0_DB1),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, TX4_C, SEL_SCIF4_2),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, RMII0_TXD0_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_23_21, TIOC4B_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_MSEL(IP7_23_21, TX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP7_23_21, RMII0_TXD0_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_23_21, TIOC4B_A, SEL_MTU2_CH4_0),
PINMUX_IPSR_DATA(IP7_23_21, HIFWR),
PINMUX_IPSR_DATA(IP7_26_24, DU0_DB2),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, RX5_B, SEL_SCIF5_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, RMII0_TXD1_B, SEL_RMII_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_26_24, TIOC4C_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_MSEL(IP7_26_24, RX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, RMII0_TXD1_B, SEL_RMII_1),
+ PINMUX_IPSR_MSEL(IP7_26_24, TIOC4C_A, SEL_MTU2_CH4_0),
PINMUX_IPSR_DATA(IP7_28_27, DU0_DB3),
- PINMUX_IPSR_MODSEL_DATA(IP7_28_27, TX5_B, SEL_SCIF5_1),
- PINMUX_IPSR_MODSEL_DATA(IP7_28_27, TIOC4D_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_MSEL(IP7_28_27, TX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MSEL(IP7_28_27, TIOC4D_A, SEL_MTU2_CH4_0),
PINMUX_IPSR_DATA(IP7_28_27, HIFRD),
PINMUX_IPSR_DATA(IP7_30_29, DU0_DB4),
@@ -1107,251 +1107,251 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP8_3_2, HIFRDY),
PINMUX_IPSR_DATA(IP8_5_4, DU0_DB7),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_4, SSI_SCK0_B, SEL_SSI0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_5_4, HIFEBL_B, SEL_HIF_1),
+ PINMUX_IPSR_MSEL(IP8_5_4, SSI_SCK0_B, SEL_SSI0_1),
+ PINMUX_IPSR_MSEL(IP8_5_4, HIFEBL_B, SEL_HIF_1),
PINMUX_IPSR_DATA(IP8_7_6, DU0_DOTCLKIN),
- PINMUX_IPSR_MODSEL_DATA(IP8_7_6, HSPI_CS0_C, SEL_HSPI_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_7_6, SSI_WS0_B, SEL_SSI0_1),
+ PINMUX_IPSR_MSEL(IP8_7_6, HSPI_CS0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MSEL(IP8_7_6, SSI_WS0_B, SEL_SSI0_1),
PINMUX_IPSR_DATA(IP8_9_8, DU0_DOTCLKOUT),
- PINMUX_IPSR_MODSEL_DATA(IP8_9_8, HSPI_CLK0_C, SEL_HSPI_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_9_8, SSI_SDATA0_B, SEL_SSI0_1),
+ PINMUX_IPSR_MSEL(IP8_9_8, HSPI_CLK0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MSEL(IP8_9_8, SSI_SDATA0_B, SEL_SSI0_1),
PINMUX_IPSR_DATA(IP8_11_10, DU0_EXHSYNC_DU0_HSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_10, HSPI_TX0_C, SEL_HSPI_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_11_10, SSI_SCK1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP8_11_10, HSPI_TX0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MSEL(IP8_11_10, SSI_SCK1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP8_13_12, DU0_EXVSYNC_DU0_VSYNC),
- PINMUX_IPSR_MODSEL_DATA(IP8_13_12, HSPI_RX0_C, SEL_HSPI_2),
- PINMUX_IPSR_MODSEL_DATA(IP8_13_12, SSI_WS1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP8_13_12, HSPI_RX0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MSEL(IP8_13_12, SSI_WS1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP8_15_14, DU0_EXODDF_DU0_ODDF),
- PINMUX_IPSR_MODSEL_DATA(IP8_15_14, CAN0_RX_B, SEL_RCAN0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_15_14, HSCK0_B, SEL_HSCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_15_14, SSI_SDATA1_B, SEL_SSI1_1),
+ PINMUX_IPSR_MSEL(IP8_15_14, CAN0_RX_B, SEL_RCAN0_1),
+ PINMUX_IPSR_MSEL(IP8_15_14, HSCK0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MSEL(IP8_15_14, SSI_SDATA1_B, SEL_SSI1_1),
PINMUX_IPSR_DATA(IP8_17_16, DU0_DISP),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_16, CAN0_TX_B, SEL_RCAN0_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_16, HRX0_B, SEL_HSCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_17_16, AUDIO_CLKA_B, SEL_AUDIO_CLKA_1),
+ PINMUX_IPSR_MSEL(IP8_17_16, CAN0_TX_B, SEL_RCAN0_1),
+ PINMUX_IPSR_MSEL(IP8_17_16, HRX0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MSEL(IP8_17_16, AUDIO_CLKA_B, SEL_AUDIO_CLKA_1),
PINMUX_IPSR_DATA(IP8_19_18, DU0_CDE),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_18, HTX0_B, SEL_HSCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_18, AUDIO_CLKB_B, SEL_AUDIO_CLKB_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_19_18, LCD_VCPWC_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP8_19_18, HTX0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MSEL(IP8_19_18, AUDIO_CLKB_B, SEL_AUDIO_CLKB_1),
+ PINMUX_IPSR_MSEL(IP8_19_18, LCD_VCPWC_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, IRQ0_A, SEL_INTC_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, HSPI_TX_B, SEL_HSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_22_20, RX3_E, SEL_SCIF3_4),
+ PINMUX_IPSR_MSEL(IP8_22_20, IRQ0_A, SEL_INTC_0),
+ PINMUX_IPSR_MSEL(IP8_22_20, HSPI_TX_B, SEL_HSPI_1),
+ PINMUX_IPSR_MSEL(IP8_22_20, RX3_E, SEL_SCIF3_4),
PINMUX_IPSR_DATA(IP8_22_20, ET0_ERXD0),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, IRQ1_A, SEL_INTC_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, HSPI_RX_B, SEL_HSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_25_23, TX3_E, SEL_SCIF3_4),
+ PINMUX_IPSR_MSEL(IP8_25_23, IRQ1_A, SEL_INTC_0),
+ PINMUX_IPSR_MSEL(IP8_25_23, HSPI_RX_B, SEL_HSPI_1),
+ PINMUX_IPSR_MSEL(IP8_25_23, TX3_E, SEL_SCIF3_4),
PINMUX_IPSR_DATA(IP8_25_23, ET0_ERXD1),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_26, IRQ2_A, SEL_INTC_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_26, CTS0_A, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_26, HCTS0_B, SEL_HSCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_27_26, ET0_ERXD2_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP8_27_26, IRQ2_A, SEL_INTC_0),
+ PINMUX_IPSR_MSEL(IP8_27_26, CTS0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_27_26, HCTS0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MSEL(IP8_27_26, ET0_ERXD2_A, SEL_ET0_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_29_28, IRQ3_A, SEL_INTC_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_29_28, RTS0_A, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP8_29_28, HRTS0_B, SEL_HSCIF_1),
- PINMUX_IPSR_MODSEL_DATA(IP8_29_28, ET0_ERXD3_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP8_29_28, IRQ3_A, SEL_INTC_0),
+ PINMUX_IPSR_MSEL(IP8_29_28, RTS0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP8_29_28, HRTS0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MSEL(IP8_29_28, ET0_ERXD3_A, SEL_ET0_0),
/* IPSR9 */
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, VI1_CLK_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, FD0_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_1_0, LCD_DATA0_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_1_0, VI1_CLK_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_1_0, FD0_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_1_0, LCD_DATA0_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, VI1_0_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, FD1_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_3_2, LCD_DATA1_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_3_2, VI1_0_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_3_2, FD1_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_3_2, LCD_DATA1_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_4, VI1_1_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_4, FD2_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_5_4, LCD_DATA2_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_5_4, VI1_1_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_5_4, FD2_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_5_4, LCD_DATA2_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_7_6, VI1_2_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_7_6, FD3_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_7_6, LCD_DATA3_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_7_6, VI1_2_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_7_6, FD3_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_7_6, LCD_DATA3_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_9_8, VI1_3_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_9_8, FD4_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_9_8, LCD_DATA4_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_9_8, VI1_3_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_9_8, FD4_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_9_8, LCD_DATA4_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_10, VI1_4_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_10, FD5_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_11_10, LCD_DATA5_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_11_10, VI1_4_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_11_10, FD5_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_11_10, LCD_DATA5_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_13_12, VI1_5_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_13_12, FD6_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_13_12, LCD_DATA6_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_13_12, VI1_5_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_13_12, FD6_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_13_12, LCD_DATA6_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_14, VI1_6_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_14, FD7_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_15_14, LCD_DATA7_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_15_14, VI1_6_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_15_14, FD7_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_15_14, LCD_DATA7_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_17_16, VI1_7_A, SEL_VIN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_17_16, FCE_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_17_16, LCD_DATA8_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_17_16, VI1_7_A, SEL_VIN1_0),
+ PINMUX_IPSR_MSEL(IP9_17_16, FCE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP9_17_16, LCD_DATA8_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_19_18, SSI_SCK0_A, SEL_SSI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_19_18, TIOC1A_B, SEL_MTU2_CH1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_19_18, LCD_DATA9_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_19_18, SSI_SCK0_A, SEL_SSI0_0),
+ PINMUX_IPSR_MSEL(IP9_19_18, TIOC1A_B, SEL_MTU2_CH1_1),
+ PINMUX_IPSR_MSEL(IP9_19_18, LCD_DATA9_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_20, SSI_WS0_A, SEL_SSI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_20, TIOC1B_B, SEL_MTU2_CH1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_21_20, LCD_DATA10_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_21_20, SSI_WS0_A, SEL_SSI0_0),
+ PINMUX_IPSR_MSEL(IP9_21_20, TIOC1B_B, SEL_MTU2_CH1_1),
+ PINMUX_IPSR_MSEL(IP9_21_20, LCD_DATA10_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_23_22, SSI_SDATA0_A, SEL_SSI0_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_23_22, VI1_0_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_23_22, TIOC2A_B, SEL_MTU2_CH2_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_23_22, LCD_DATA11_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_23_22, SSI_SDATA0_A, SEL_SSI0_0),
+ PINMUX_IPSR_MSEL(IP9_23_22, VI1_0_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP9_23_22, TIOC2A_B, SEL_MTU2_CH2_1),
+ PINMUX_IPSR_MSEL(IP9_23_22, LCD_DATA11_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_25_24, SSI_SCK1_A, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_25_24, VI1_1_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_25_24, TIOC2B_B, SEL_MTU2_CH2_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_25_24, LCD_DATA12_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_25_24, SSI_SCK1_A, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP9_25_24, VI1_1_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP9_25_24, TIOC2B_B, SEL_MTU2_CH2_1),
+ PINMUX_IPSR_MSEL(IP9_25_24, LCD_DATA12_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_26, SSI_WS1_A, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_26, VI1_2_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_27_26, LCD_DATA13_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_27_26, SSI_WS1_A, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP9_27_26, VI1_2_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP9_27_26, LCD_DATA13_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_29_28, SSI_SDATA1_A, SEL_SSI1_0),
- PINMUX_IPSR_MODSEL_DATA(IP9_29_28, VI1_3_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP9_29_28, LCD_DATA14_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP9_29_28, SSI_SDATA1_A, SEL_SSI1_0),
+ PINMUX_IPSR_MSEL(IP9_29_28, VI1_3_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP9_29_28, LCD_DATA14_B, SEL_LCDC_1),
/* IPSE10 */
PINMUX_IPSR_DATA(IP10_2_0, SSI_SCK23),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, VI1_4_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, RX1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, FCLE_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_2_0, LCD_DATA15_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_2_0, VI1_4_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP10_2_0, RX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_2_0, FCLE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP10_2_0, LCD_DATA15_B, SEL_LCDC_1),
PINMUX_IPSR_DATA(IP10_5_3, SSI_WS23),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, VI1_5_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, TX1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, HSCK0_C, SEL_HSCIF_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, FALE_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_5_3, LCD_DON_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_5_3, VI1_5_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP10_5_3, TX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_5_3, HSCK0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MSEL(IP10_5_3, FALE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP10_5_3, LCD_DON_B, SEL_LCDC_1),
PINMUX_IPSR_DATA(IP10_8_6, SSI_SDATA2),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, VI1_6_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, HRX0_C, SEL_HSCIF_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, FRE_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_8_6, LCD_CL1_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_8_6, VI1_6_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP10_8_6, HRX0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MSEL(IP10_8_6, FRE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP10_8_6, LCD_CL1_B, SEL_LCDC_1),
PINMUX_IPSR_DATA(IP10_11_9, SSI_SDATA3),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, VI1_7_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, HTX0_C, SEL_HSCIF_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, FWE_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_11_9, LCD_CL2_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_11_9, VI1_7_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP10_11_9, HTX0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MSEL(IP10_11_9, FWE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP10_11_9, LCD_CL2_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, AUDIO_CLKA_A, SEL_AUDIO_CLKA_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, VI1_CLK_B, SEL_VIN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SCK1_D, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, IECLK_B, SEL_IEBUS_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_14_12, LCD_FLM_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_14_12, AUDIO_CLKA_A, SEL_AUDIO_CLKA_0),
+ PINMUX_IPSR_MSEL(IP10_14_12, VI1_CLK_B, SEL_VIN1_1),
+ PINMUX_IPSR_MSEL(IP10_14_12, SCK1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP10_14_12, IECLK_B, SEL_IEBUS_1),
+ PINMUX_IPSR_MSEL(IP10_14_12, LCD_FLM_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_15, AUDIO_CLKB_A, SEL_AUDIO_CLKB_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_15, LCD_CLK_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_15, AUDIO_CLKB_A, SEL_AUDIO_CLKB_0),
+ PINMUX_IPSR_MSEL(IP10_15, LCD_CLK_B, SEL_LCDC_1),
PINMUX_IPSR_DATA(IP10_18_16, AUDIO_CLKC),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_16, SCK1_E, SEL_SCIF1_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_16, HCTS0_C, SEL_HSCIF_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_16, FRB_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_18_16, LCD_VEPWC_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_18_16, SCK1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MSEL(IP10_18_16, HCTS0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MSEL(IP10_18_16, FRB_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP10_18_16, LCD_VEPWC_B, SEL_LCDC_1),
PINMUX_IPSR_DATA(IP10_21_19, AUDIO_CLKOUT),
- PINMUX_IPSR_MODSEL_DATA(IP10_21_19, TX1_E, SEL_SCIF1_4),
- PINMUX_IPSR_MODSEL_DATA(IP10_21_19, HRTS0_C, SEL_HSCIF_2),
- PINMUX_IPSR_MODSEL_DATA(IP10_21_19, FSE_B, SEL_FLCTL_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_21_19, LCD_M_DISP_B, SEL_LCDC_1),
+ PINMUX_IPSR_MSEL(IP10_21_19, TX1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MSEL(IP10_21_19, HRTS0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MSEL(IP10_21_19, FSE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MSEL(IP10_21_19, LCD_M_DISP_B, SEL_LCDC_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_22, CAN_CLK_A, SEL_RCAN_CLK_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_22, RX4_D, SEL_SCIF4_3),
+ PINMUX_IPSR_MSEL(IP10_22, CAN_CLK_A, SEL_RCAN_CLK_0),
+ PINMUX_IPSR_MSEL(IP10_22, RX4_D, SEL_SCIF4_3),
- PINMUX_IPSR_MODSEL_DATA(IP10_24_23, CAN0_TX_A, SEL_RCAN0_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_24_23, TX4_D, SEL_SCIF4_3),
+ PINMUX_IPSR_MSEL(IP10_24_23, CAN0_TX_A, SEL_RCAN0_0),
+ PINMUX_IPSR_MSEL(IP10_24_23, TX4_D, SEL_SCIF4_3),
PINMUX_IPSR_DATA(IP10_24_23, MLB_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP10_25, CAN1_RX_A, SEL_RCAN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_25, IRQ1_B, SEL_INTC_1),
+ PINMUX_IPSR_MSEL(IP10_25, CAN1_RX_A, SEL_RCAN1_0),
+ PINMUX_IPSR_MSEL(IP10_25, IRQ1_B, SEL_INTC_1),
- PINMUX_IPSR_MODSEL_DATA(IP10_27_26, CAN0_RX_A, SEL_RCAN0_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_27_26, IRQ0_B, SEL_INTC_1),
+ PINMUX_IPSR_MSEL(IP10_27_26, CAN0_RX_A, SEL_RCAN0_0),
+ PINMUX_IPSR_MSEL(IP10_27_26, IRQ0_B, SEL_INTC_1),
PINMUX_IPSR_DATA(IP10_27_26, MLB_SIG),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_28, CAN1_TX_A, SEL_RCAN1_0),
- PINMUX_IPSR_MODSEL_DATA(IP10_29_28, TX5_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MSEL(IP10_29_28, CAN1_TX_A, SEL_RCAN1_0),
+ PINMUX_IPSR_MSEL(IP10_29_28, TX5_C, SEL_SCIF1_2),
PINMUX_IPSR_DATA(IP10_29_28, MLB_DAT),
/* IPSR11 */
PINMUX_IPSR_DATA(IP11_0, SCL1),
- PINMUX_IPSR_MODSEL_DATA(IP11_0, SCIF_CLK_C, SEL_SCIF_CLK_2),
+ PINMUX_IPSR_MSEL(IP11_0, SCIF_CLK_C, SEL_SCIF_CLK_2),
PINMUX_IPSR_DATA(IP11_1, SDA1),
- PINMUX_IPSR_MODSEL_DATA(IP11_0, RX1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MSEL(IP11_0, RX1_E, SEL_SCIF1_4),
PINMUX_IPSR_DATA(IP11_2, SDA0),
- PINMUX_IPSR_MODSEL_DATA(IP11_2, HIFEBL_A, SEL_HIF_0),
+ PINMUX_IPSR_MSEL(IP11_2, HIFEBL_A, SEL_HIF_0),
PINMUX_IPSR_DATA(IP11_3, SDSELF),
- PINMUX_IPSR_MODSEL_DATA(IP11_3, RTS1_E, SEL_SCIF1_3),
+ PINMUX_IPSR_MSEL(IP11_3, RTS1_E, SEL_SCIF1_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_6_4, SCIF_CLK_A, SEL_SCIF_CLK_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_6_4, HSPI_CLK_A, SEL_HSPI_0),
+ PINMUX_IPSR_MSEL(IP11_6_4, SCIF_CLK_A, SEL_SCIF_CLK_0),
+ PINMUX_IPSR_MSEL(IP11_6_4, HSPI_CLK_A, SEL_HSPI_0),
PINMUX_IPSR_DATA(IP11_6_4, VI0_CLK),
- PINMUX_IPSR_MODSEL_DATA(IP11_6_4, RMII0_TXD0_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP11_6_4, RMII0_TXD0_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP11_6_4, ET0_ERXD4),
- PINMUX_IPSR_MODSEL_DATA(IP11_9_7, SCK0_A, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_9_7, HSPI_CS_A, SEL_HSPI_0),
+ PINMUX_IPSR_MSEL(IP11_9_7, SCK0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP11_9_7, HSPI_CS_A, SEL_HSPI_0),
PINMUX_IPSR_DATA(IP11_9_7, VI0_CLKENB),
- PINMUX_IPSR_MODSEL_DATA(IP11_9_7, RMII0_TXD1_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP11_9_7, RMII0_TXD1_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP11_9_7, ET0_ERXD5),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_10, RX0_A, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_10, HSPI_RX_A, SEL_HSPI_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_11_10, RMII0_RXD0_A, SEL_RMII_0),
+ PINMUX_IPSR_MSEL(IP11_11_10, RX0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP11_11_10, HSPI_RX_A, SEL_HSPI_0),
+ PINMUX_IPSR_MSEL(IP11_11_10, RMII0_RXD0_A, SEL_RMII_0),
PINMUX_IPSR_DATA(IP11_11_10, ET0_ERXD6),
- PINMUX_IPSR_MODSEL_DATA(IP11_12, TX0_A, SEL_SCIF0_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_12, HSPI_TX_A, SEL_HSPI_0),
+ PINMUX_IPSR_MSEL(IP11_12, TX0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MSEL(IP11_12, HSPI_TX_A, SEL_HSPI_0),
PINMUX_IPSR_DATA(IP11_15_13, PENC1),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_13, TX3_D, SEL_SCIF3_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_13, CAN1_TX_B, SEL_RCAN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_13, TX5_D, SEL_SCIF5_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_15_13, IETX_B, SEL_IEBUS_1),
+ PINMUX_IPSR_MSEL(IP11_15_13, TX3_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MSEL(IP11_15_13, CAN1_TX_B, SEL_RCAN1_1),
+ PINMUX_IPSR_MSEL(IP11_15_13, TX5_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MSEL(IP11_15_13, IETX_B, SEL_IEBUS_1),
PINMUX_IPSR_DATA(IP11_18_16, USB_OVC1),
- PINMUX_IPSR_MODSEL_DATA(IP11_18_16, RX3_D, SEL_SCIF3_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_18_16, CAN1_RX_B, SEL_RCAN1_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_18_16, RX5_D, SEL_SCIF5_3),
- PINMUX_IPSR_MODSEL_DATA(IP11_18_16, IERX_B, SEL_IEBUS_1),
+ PINMUX_IPSR_MSEL(IP11_18_16, RX3_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MSEL(IP11_18_16, CAN1_RX_B, SEL_RCAN1_1),
+ PINMUX_IPSR_MSEL(IP11_18_16, RX5_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MSEL(IP11_18_16, IERX_B, SEL_IEBUS_1),
PINMUX_IPSR_DATA(IP11_20_19, DREQ0),
- PINMUX_IPSR_MODSEL_DATA(IP11_20_19, SD1_CLK_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP11_20_19, SD1_CLK_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP11_20_19, ET0_TX_EN),
PINMUX_IPSR_DATA(IP11_22_21, DACK0),
- PINMUX_IPSR_MODSEL_DATA(IP11_22_21, SD1_DAT3_A, SEL_SDHI1_0),
+ PINMUX_IPSR_MSEL(IP11_22_21, SD1_DAT3_A, SEL_SDHI1_0),
PINMUX_IPSR_DATA(IP11_22_21, ET0_TX_ER),
PINMUX_IPSR_DATA(IP11_25_23, DREQ1),
- PINMUX_IPSR_MODSEL_DATA(IP11_25_23, HSPI_CLK_B, SEL_HSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_25_23, RX4_B, SEL_SCIF4_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_25_23, ET0_PHY_INT_C, SEL_ET0_CTL_0),
- PINMUX_IPSR_MODSEL_DATA(IP11_25_23, ET0_TX_CLK_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP11_25_23, HSPI_CLK_B, SEL_HSPI_1),
+ PINMUX_IPSR_MSEL(IP11_25_23, RX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP11_25_23, ET0_PHY_INT_C, SEL_ET0_CTL_0),
+ PINMUX_IPSR_MSEL(IP11_25_23, ET0_TX_CLK_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP11_27_26, DACK1),
- PINMUX_IPSR_MODSEL_DATA(IP11_27_26, HSPI_CS_B, SEL_HSPI_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_27_26, TX4_B, SEL_SCIF3_1),
- PINMUX_IPSR_MODSEL_DATA(IP11_27_26, ET0_RX_CLK_A, SEL_ET0_0),
+ PINMUX_IPSR_MSEL(IP11_27_26, HSPI_CS_B, SEL_HSPI_1),
+ PINMUX_IPSR_MSEL(IP11_27_26, TX4_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MSEL(IP11_27_26, ET0_RX_CLK_A, SEL_ET0_0),
PINMUX_IPSR_DATA(IP11_28, PRESETOUT),
PINMUX_IPSR_DATA(IP11_28, ST_CLKOUT),
@@ -2445,6 +2445,6 @@ const struct sh_pfc_soc_info sh7734_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7757.c b/drivers/pinctrl/sh-pfc/pfc-sh7757.c
index 625661a88c52..0555a1fe076e 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7757.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7757.c
@@ -2238,6 +2238,6 @@ const struct sh_pfc_soc_info sh7757_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7785.c b/drivers/pinctrl/sh-pfc/pfc-sh7785.c
index b38dd7e3e375..1934cbec3965 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7785.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7785.c
@@ -1269,6 +1269,6 @@ const struct sh_pfc_soc_info sh7785_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7786.c b/drivers/pinctrl/sh-pfc/pfc-sh7786.c
index 6cb4e0aaf20b..c98585d80de8 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7786.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7786.c
@@ -813,6 +813,6 @@ const struct sh_pfc_soc_info sh7786_pinmux_info = {
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-shx3.c b/drivers/pinctrl/sh-pfc/pfc-shx3.c
index a3fcb2284d91..3f60c900645e 100644
--- a/drivers/pinctrl/sh-pfc/pfc-shx3.c
+++ b/drivers/pinctrl/sh-pfc/pfc-shx3.c
@@ -554,8 +554,8 @@ const struct sh_pfc_soc_info shx3_pinmux_info = {
.nr_pins = ARRAY_SIZE(pinmux_pins),
.func_gpios = pinmux_func_gpios,
.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
};
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 15afd49fd4e3..7b373d43d981 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -52,6 +52,29 @@ struct sh_pfc_pin_group {
unsigned int nr_pins;
};
+/*
+ * Using union vin_data saves memory occupied by the VIN data pins.
+ * VIN_DATA_PIN_GROUP() is a macro used to describe the VIN pin groups
+ * in this case.
+ */
+#define VIN_DATA_PIN_GROUP(n, s) \
+ { \
+ .name = #n#s, \
+ .pins = n##_pins.data##s, \
+ .mux = n##_mux.data##s, \
+ .nr_pins = ARRAY_SIZE(n##_pins.data##s), \
+ }
+
+union vin_data {
+ unsigned int data24[24];
+ unsigned int data20[20];
+ unsigned int data16[16];
+ unsigned int data12[12];
+ unsigned int data10[10];
+ unsigned int data8[8];
+ unsigned int data4[4];
+};
+
#define SH_PFC_FUNCTION(n) \
{ \
.name = #n, \
@@ -98,17 +121,11 @@ struct pinmux_data_reg {
.enum_ids = (const u16 [r_width]) \
struct pinmux_irq {
- int irq;
const short *gpios;
};
-#ifdef CONFIG_ARCH_MULTIPLATFORM
-#define PINMUX_IRQ(irq_nr, ids...) \
+#define PINMUX_IRQ(ids...) \
{ .gpios = (const short []) { ids, -1 } }
-#else
-#define PINMUX_IRQ(irq_nr, ids...) \
- { .irq = irq_nr, .gpios = (const short []) { ids, -1 } }
-#endif
struct pinmux_range {
u16 begin;
@@ -143,14 +160,16 @@ struct sh_pfc_soc_info {
const struct sh_pfc_function *functions;
unsigned int nr_functions;
+#ifdef CONFIG_SUPERH
const struct pinmux_func *func_gpios;
unsigned int nr_func_gpios;
+#endif
const struct pinmux_cfg_reg *cfg_regs;
const struct pinmux_data_reg *data_regs;
- const u16 *gpio_data;
- unsigned int gpio_data_size;
+ const u16 *pinmux_data;
+ unsigned int pinmux_data_size;
const struct pinmux_irq *gpio_irq;
unsigned int gpio_irq_size;
@@ -163,7 +182,7 @@ struct sh_pfc_soc_info {
*/
/*
- * sh_pfc_soc_info gpio_data array macros
+ * sh_pfc_soc_info pinmux_data array macros
*/
#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
@@ -177,33 +196,33 @@ struct sh_pfc_soc_info {
#define PINMUX_IPSR_NOFN(ipsr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##ms)
#define PINMUX_IPSR_MSEL(ipsr, fn, ms) \
- PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr, FN_##ms)
-#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
/*
* GP port style (32 ports banks)
*/
-#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
-
-#define PORT_GP_32(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
- PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
- PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
- PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
- PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
- PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
- PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
- PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx), \
- PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx), \
- PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx), \
- PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
+#define PORT_GP_CFG_1(bank, pin, fn, sfx, cfg) fn(bank, pin, GP_##bank##_##pin, sfx, cfg)
+#define PORT_GP_1(bank, pin, fn, sfx) PORT_GP_CFG_1(bank, pin, fn, sfx, 0)
+
+#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_1(bank, 0, fn, sfx, cfg), PORT_GP_CFG_1(bank, 1, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 2, fn, sfx, cfg), PORT_GP_CFG_1(bank, 3, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), PORT_GP_CFG_1(bank, 5, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 6, fn, sfx, cfg), PORT_GP_CFG_1(bank, 7, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 8, fn, sfx, cfg), PORT_GP_CFG_1(bank, 9, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 10, fn, sfx, cfg), PORT_GP_CFG_1(bank, 11, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 12, fn, sfx, cfg), PORT_GP_CFG_1(bank, 13, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 14, fn, sfx, cfg), PORT_GP_CFG_1(bank, 15, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 16, fn, sfx, cfg), PORT_GP_CFG_1(bank, 17, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), PORT_GP_CFG_1(bank, 19, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 20, fn, sfx, cfg), PORT_GP_CFG_1(bank, 21, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 22, fn, sfx, cfg), PORT_GP_CFG_1(bank, 23, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 24, fn, sfx, cfg), PORT_GP_CFG_1(bank, 25, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 26, fn, sfx, cfg), PORT_GP_CFG_1(bank, 27, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 28, fn, sfx, cfg), PORT_GP_CFG_1(bank, 29, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 30, fn, sfx, cfg), PORT_GP_CFG_1(bank, 31, fn, sfx, cfg)
+#define PORT_GP_32(bank, fn, sfx) PORT_GP_CFG_32(bank, fn, sfx, 0)
#define PORT_GP_32_REV(bank, fn, sfx) \
PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx), \
@@ -224,20 +243,21 @@ struct sh_pfc_soc_info {
PORT_GP_1(bank, 1, fn, sfx), PORT_GP_1(bank, 0, fn, sfx)
/* GP_ALL(suffix) - Expand to a list of GP_#_#_suffix */
-#define _GP_ALL(bank, pin, name, sfx) name##_##sfx
+#define _GP_ALL(bank, pin, name, sfx, cfg) name##_##sfx
#define GP_ALL(str) CPU_ALL_PORT(_GP_ALL, str)
/* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */
-#define _GP_GPIO(bank, _pin, _name, sfx) \
+#define _GP_GPIO(bank, _pin, _name, sfx, cfg) \
{ \
.pin = (bank * 32) + _pin, \
.name = __stringify(_name), \
.enum_id = _name##_DATA, \
+ .configs = cfg, \
}
#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, unused)
/* PINMUX_DATA_GP_ALL - Expand to a list of name_DATA, name_FN marks */
-#define _GP_DATA(bank, pin, name, sfx) PINMUX_DATA(name##_DATA, name##_FN)
+#define _GP_DATA(bank, pin, name, sfx, cfg) PINMUX_DATA(name##_DATA, name##_FN)
#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, unused)
/*
@@ -326,4 +346,9 @@ struct sh_pfc_soc_info {
} \
}
+/*
+ * GPIO number helper macro for R-Car
+ */
+#define RCAR_GP_PIN(bank, pin) (((bank) * 32) + (pin))
+
#endif /* __SH_PFC_H */
diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c
index 0d24d9e4b70c..829018c812bd 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas7.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c
@@ -544,6 +544,11 @@ static const struct pinctrl_pin_desc atlas7_ioc_pads[] = {
PINCTRL_PIN(156, "lvds_tx0d1n"),
PINCTRL_PIN(157, "lvds_tx0d0p"),
PINCTRL_PIN(158, "lvds_tx0d0n"),
+ PINCTRL_PIN(159, "jtag_tdo"),
+ PINCTRL_PIN(160, "jtag_tms"),
+ PINCTRL_PIN(161, "jtag_tck"),
+ PINCTRL_PIN(162, "jtag_tdi"),
+ PINCTRL_PIN(163, "jtag_trstn"),
};
struct atlas7_pad_config atlas7_ioc_pad_confs[] = {
@@ -708,6 +713,11 @@ struct atlas7_pad_config atlas7_ioc_pad_confs[] = {
PADCONF(156, 7, 0x130, 0x270, -1, 0x480, 28, 14, 0, 7),
PADCONF(157, 7, 0x138, 0x278, -1, 0x480, 0, 0, 0, 8),
PADCONF(158, 7, 0x138, 0x278, -1, 0x480, 4, 2, 0, 9),
+ PADCONF(159, 5, 0x140, 0x280, 0x380, -1, 0, 0, 0, 0),
+ PADCONF(160, 6, 0x140, 0x280, 0x380, -1, 4, 2, 2, 0),
+ PADCONF(161, 5, 0x140, 0x280, 0x380, -1, 8, 4, 4, 0),
+ PADCONF(162, 6, 0x140, 0x280, 0x380, -1, 12, 6, 6, 0),
+ PADCONF(163, 6, 0x140, 0x280, 0x380, -1, 16, 8, 8, 0),
};
/* pin list of each pin group */
@@ -724,12 +734,15 @@ static const unsigned int sp_rgmii_gpio_pins[] = { 97, 98, 99, 100, 101, 102,
141, 142, 143, 144, 145, 146, 147, 148, };
static const unsigned int lvds_gpio_pins[] = { 157, 158, 155, 156, 153, 154,
151, 152, 149, 150, };
-static const unsigned int uart_nand_gpio_pins[] = { 44, 43, 42, 41, 40, 39,
- 38, 37, 46, 47, 48, 49, 50, 52, 51, 45, 133, 134, 135, 136,
- 137, 138, 139, 140, };
+static const unsigned int jtag_uart_nand_gpio_pins[] = { 44, 43, 42, 41, 40,
+ 39, 38, 37, 46, 47, 48, 49, 50, 52, 51, 45, 133, 134, 135,
+ 136, 137, 138, 139, 140, 159, 160, 161, 162, 163, };
static const unsigned int rtc_gpio_pins[] = { 0, 1, 2, 3, 4, 10, 11, 12, 13,
- 14, 15, 16, 17, };
+ 14, 15, 16, 17, 9, };
static const unsigned int audio_ac97_pins[] = { 113, 118, 115, 114, };
+static const unsigned int audio_digmic_pins0[] = { 51, };
+static const unsigned int audio_digmic_pins1[] = { 122, };
+static const unsigned int audio_digmic_pins2[] = { 161, };
static const unsigned int audio_func_dbg_pins[] = { 141, 144, 44, 43, 42, 41,
40, 39, 38, 37, 74, 75, 76, 77, 78, 79, 81, 113, 114, 118,
115, 49, 50, 142, 143, 80, };
@@ -737,16 +750,49 @@ static const unsigned int audio_i2s_pins[] = { 118, 115, 116, 117, 112, 113,
114, };
static const unsigned int audio_i2s_2ch_pins[] = { 118, 115, 112, 113, 114, };
static const unsigned int audio_i2s_extclk_pins[] = { 112, };
-static const unsigned int audio_uart0_pins[] = { 143, 142, 141, 144, };
-static const unsigned int audio_uart1_pins[] = { 147, 146, 145, 148, };
-static const unsigned int audio_uart2_pins0[] = { 20, 21, 19, 18, };
-static const unsigned int audio_uart2_pins1[] = { 109, 110, 101, 111, };
-static const unsigned int c_can_trnsvr_pins[] = { 1, };
-static const unsigned int c0_can_pins0[] = { 11, 10, };
-static const unsigned int c0_can_pins1[] = { 2, 3, };
-static const unsigned int c1_can_pins0[] = { 138, 137, };
-static const unsigned int c1_can_pins1[] = { 147, 146, };
-static const unsigned int c1_can_pins2[] = { 2, 3, };
+static const unsigned int audio_spdif_out_pins0[] = { 112, };
+static const unsigned int audio_spdif_out_pins1[] = { 116, };
+static const unsigned int audio_spdif_out_pins2[] = { 142, };
+static const unsigned int audio_uart0_basic_pins[] = { 143, 142, 141, 144, };
+static const unsigned int audio_uart0_urfs_pins0[] = { 117, };
+static const unsigned int audio_uart0_urfs_pins1[] = { 139, };
+static const unsigned int audio_uart0_urfs_pins2[] = { 163, };
+static const unsigned int audio_uart0_urfs_pins3[] = { 162, };
+static const unsigned int audio_uart1_basic_pins[] = { 147, 146, 145, 148, };
+static const unsigned int audio_uart1_urfs_pins0[] = { 117, };
+static const unsigned int audio_uart1_urfs_pins1[] = { 140, };
+static const unsigned int audio_uart1_urfs_pins2[] = { 163, };
+static const unsigned int audio_uart2_urfs_pins0[] = { 139, };
+static const unsigned int audio_uart2_urfs_pins1[] = { 163, };
+static const unsigned int audio_uart2_urfs_pins2[] = { 96, };
+static const unsigned int audio_uart2_urxd_pins0[] = { 20, };
+static const unsigned int audio_uart2_urxd_pins1[] = { 109, };
+static const unsigned int audio_uart2_urxd_pins2[] = { 93, };
+static const unsigned int audio_uart2_usclk_pins0[] = { 19, };
+static const unsigned int audio_uart2_usclk_pins1[] = { 101, };
+static const unsigned int audio_uart2_usclk_pins2[] = { 91, };
+static const unsigned int audio_uart2_utfs_pins0[] = { 18, };
+static const unsigned int audio_uart2_utfs_pins1[] = { 111, };
+static const unsigned int audio_uart2_utfs_pins2[] = { 94, };
+static const unsigned int audio_uart2_utxd_pins0[] = { 21, };
+static const unsigned int audio_uart2_utxd_pins1[] = { 110, };
+static const unsigned int audio_uart2_utxd_pins2[] = { 92, };
+static const unsigned int c_can_trnsvr_en_pins0[] = { 2, };
+static const unsigned int c_can_trnsvr_en_pins1[] = { 0, };
+static const unsigned int c_can_trnsvr_intr_pins[] = { 1, };
+static const unsigned int c_can_trnsvr_stb_n_pins[] = { 3, };
+static const unsigned int c0_can_rxd_trnsv0_pins[] = { 11, };
+static const unsigned int c0_can_rxd_trnsv1_pins[] = { 2, };
+static const unsigned int c0_can_txd_trnsv0_pins[] = { 10, };
+static const unsigned int c0_can_txd_trnsv1_pins[] = { 3, };
+static const unsigned int c1_can_rxd_pins0[] = { 138, };
+static const unsigned int c1_can_rxd_pins1[] = { 147, };
+static const unsigned int c1_can_rxd_pins2[] = { 2, };
+static const unsigned int c1_can_rxd_pins3[] = { 162, };
+static const unsigned int c1_can_txd_pins0[] = { 137, };
+static const unsigned int c1_can_txd_pins1[] = { 146, };
+static const unsigned int c1_can_txd_pins2[] = { 3, };
+static const unsigned int c1_can_txd_pins3[] = { 161, };
static const unsigned int ca_audio_lpc_pins[] = { 62, 63, 64, 65, 66, 67, 68,
69, 70, 71, };
static const unsigned int ca_bt_lpc_pins[] = { 85, 86, 87, 88, 89, 90, };
@@ -804,7 +850,29 @@ static const unsigned int gn_trg_shutdown_pins2[] = { 117, };
static const unsigned int gn_trg_shutdown_pins3[] = { 123, };
static const unsigned int i2c0_pins[] = { 128, 127, };
static const unsigned int i2c1_pins[] = { 126, 125, };
-static const unsigned int jtag_pins0[] = { 125, 4, 2, 0, 1, 3, };
+static const unsigned int i2s0_pins[] = { 91, 93, 94, 92, };
+static const unsigned int i2s1_basic_pins[] = { 95, 96, };
+static const unsigned int i2s1_rxd0_pins0[] = { 61, };
+static const unsigned int i2s1_rxd0_pins1[] = { 131, };
+static const unsigned int i2s1_rxd0_pins2[] = { 129, };
+static const unsigned int i2s1_rxd0_pins3[] = { 117, };
+static const unsigned int i2s1_rxd0_pins4[] = { 83, };
+static const unsigned int i2s1_rxd1_pins0[] = { 72, };
+static const unsigned int i2s1_rxd1_pins1[] = { 132, };
+static const unsigned int i2s1_rxd1_pins2[] = { 130, };
+static const unsigned int i2s1_rxd1_pins3[] = { 118, };
+static const unsigned int i2s1_rxd1_pins4[] = { 84, };
+static const unsigned int jtag_jt_dbg_nsrst_pins[] = { 125, };
+static const unsigned int jtag_ntrst_pins0[] = { 4, };
+static const unsigned int jtag_ntrst_pins1[] = { 163, };
+static const unsigned int jtag_swdiotms_pins0[] = { 2, };
+static const unsigned int jtag_swdiotms_pins1[] = { 160, };
+static const unsigned int jtag_tck_pins0[] = { 0, };
+static const unsigned int jtag_tck_pins1[] = { 161, };
+static const unsigned int jtag_tdi_pins0[] = { 1, };
+static const unsigned int jtag_tdi_pins1[] = { 162, };
+static const unsigned int jtag_tdo_pins0[] = { 3, };
+static const unsigned int jtag_tdo_pins1[] = { 159, };
static const unsigned int ks_kas_spi_pins0[] = { 141, 144, 143, 142, };
static const unsigned int ld_ldd_pins[] = { 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80,
@@ -821,7 +889,7 @@ static const unsigned int nd_df_pins[] = { 44, 43, 42, 41, 40, 39, 38, 37,
47, 46, 52, 51, 45, 49, 50, 48, 124, };
static const unsigned int nd_df_nowp_pins[] = { 44, 43, 42, 41, 40, 39, 38,
37, 47, 46, 52, 51, 45, 49, 50, 48, };
-static const unsigned int ps_pins[] = { 120, 119, };
+static const unsigned int ps_pins[] = { 120, 119, 121, };
static const unsigned int pwc_core_on_pins[] = { 8, };
static const unsigned int pwc_ext_on_pins[] = { 6, };
static const unsigned int pwc_gpio3_clk_pins[] = { 3, };
@@ -836,18 +904,26 @@ static const unsigned int pwc_wakeup_src3_pins[] = { 3, };
static const unsigned int pw_cko0_pins0[] = { 123, };
static const unsigned int pw_cko0_pins1[] = { 101, };
static const unsigned int pw_cko0_pins2[] = { 82, };
+static const unsigned int pw_cko0_pins3[] = { 162, };
static const unsigned int pw_cko1_pins0[] = { 124, };
static const unsigned int pw_cko1_pins1[] = { 110, };
+static const unsigned int pw_cko1_pins2[] = { 163, };
static const unsigned int pw_i2s01_clk_pins0[] = { 125, };
static const unsigned int pw_i2s01_clk_pins1[] = { 117, };
-static const unsigned int pw_pwm0_pins[] = { 119, };
-static const unsigned int pw_pwm1_pins[] = { 120, };
+static const unsigned int pw_i2s01_clk_pins2[] = { 132, };
+static const unsigned int pw_pwm0_pins0[] = { 119, };
+static const unsigned int pw_pwm0_pins1[] = { 159, };
+static const unsigned int pw_pwm1_pins0[] = { 120, };
+static const unsigned int pw_pwm1_pins1[] = { 160, };
+static const unsigned int pw_pwm1_pins2[] = { 131, };
static const unsigned int pw_pwm2_pins0[] = { 121, };
static const unsigned int pw_pwm2_pins1[] = { 98, };
+static const unsigned int pw_pwm2_pins2[] = { 161, };
static const unsigned int pw_pwm3_pins0[] = { 122, };
static const unsigned int pw_pwm3_pins1[] = { 73, };
static const unsigned int pw_pwm_cpu_vol_pins0[] = { 121, };
static const unsigned int pw_pwm_cpu_vol_pins1[] = { 98, };
+static const unsigned int pw_pwm_cpu_vol_pins2[] = { 161, };
static const unsigned int pw_backlight_pins0[] = { 122, };
static const unsigned int pw_backlight_pins1[] = { 73, };
static const unsigned int rg_eth_mac_pins[] = { 108, 103, 104, 105, 106, 107,
@@ -863,8 +939,11 @@ static const unsigned int sd1_pins[] = { 48, 49, 44, 43, 42, 41, 40, 39, 38,
37, };
static const unsigned int sd1_4bit_pins0[] = { 48, 49, 44, 43, 42, 41, };
static const unsigned int sd1_4bit_pins1[] = { 48, 49, 40, 39, 38, 37, };
-static const unsigned int sd2_pins0[] = { 124, 31, 32, 33, 34, 35, 36, 123, };
-static const unsigned int sd2_no_cdb_pins0[] = { 31, 32, 33, 34, 35, 36, 123, };
+static const unsigned int sd2_basic_pins[] = { 31, 32, 33, 34, 35, 36, };
+static const unsigned int sd2_cdb_pins0[] = { 124, };
+static const unsigned int sd2_cdb_pins1[] = { 161, };
+static const unsigned int sd2_wpb_pins0[] = { 123, };
+static const unsigned int sd2_wpb_pins1[] = { 163, };
static const unsigned int sd3_pins[] = { 85, 86, 87, 88, 89, 90, };
static const unsigned int sd5_pins[] = { 91, 92, 93, 94, 95, 96, };
static const unsigned int sd6_pins0[] = { 79, 78, 74, 75, 76, 77, };
@@ -877,19 +956,39 @@ static const unsigned int tpiu_trace_pins[] = { 53, 56, 57, 58, 59, 60, 61,
static const unsigned int uart0_pins[] = { 121, 120, 134, 133, };
static const unsigned int uart0_nopause_pins[] = { 134, 133, };
static const unsigned int uart1_pins[] = { 136, 135, };
-static const unsigned int uart2_pins[] = { 11, 10, };
-static const unsigned int uart3_pins0[] = { 125, 126, 138, 137, };
-static const unsigned int uart3_pins1[] = { 111, 109, 84, 83, };
-static const unsigned int uart3_pins2[] = { 140, 139, 138, 137, };
-static const unsigned int uart3_pins3[] = { 139, 140, 84, 83, };
-static const unsigned int uart3_nopause_pins0[] = { 138, 137, };
-static const unsigned int uart3_nopause_pins1[] = { 84, 83, };
-static const unsigned int uart4_pins0[] = { 122, 123, 140, 139, };
-static const unsigned int uart4_pins1[] = { 100, 99, 140, 139, };
-static const unsigned int uart4_pins2[] = { 117, 116, 140, 139, };
-static const unsigned int uart4_nopause_pins[] = { 140, 139, };
-static const unsigned int usb0_drvvbus_pins[] = { 51, };
-static const unsigned int usb1_drvvbus_pins[] = { 134, };
+static const unsigned int uart2_cts_pins0[] = { 132, };
+static const unsigned int uart2_cts_pins1[] = { 162, };
+static const unsigned int uart2_rts_pins0[] = { 131, };
+static const unsigned int uart2_rts_pins1[] = { 161, };
+static const unsigned int uart2_rxd_pins0[] = { 11, };
+static const unsigned int uart2_rxd_pins1[] = { 160, };
+static const unsigned int uart2_rxd_pins2[] = { 130, };
+static const unsigned int uart2_txd_pins0[] = { 10, };
+static const unsigned int uart2_txd_pins1[] = { 159, };
+static const unsigned int uart2_txd_pins2[] = { 129, };
+static const unsigned int uart3_cts_pins0[] = { 125, };
+static const unsigned int uart3_cts_pins1[] = { 111, };
+static const unsigned int uart3_cts_pins2[] = { 140, };
+static const unsigned int uart3_rts_pins0[] = { 126, };
+static const unsigned int uart3_rts_pins1[] = { 109, };
+static const unsigned int uart3_rts_pins2[] = { 139, };
+static const unsigned int uart3_rxd_pins0[] = { 138, };
+static const unsigned int uart3_rxd_pins1[] = { 84, };
+static const unsigned int uart3_rxd_pins2[] = { 162, };
+static const unsigned int uart3_txd_pins0[] = { 137, };
+static const unsigned int uart3_txd_pins1[] = { 83, };
+static const unsigned int uart3_txd_pins2[] = { 161, };
+static const unsigned int uart4_basic_pins[] = { 140, 139, };
+static const unsigned int uart4_cts_pins0[] = { 122, };
+static const unsigned int uart4_cts_pins1[] = { 100, };
+static const unsigned int uart4_cts_pins2[] = { 117, };
+static const unsigned int uart4_rts_pins0[] = { 123, };
+static const unsigned int uart4_rts_pins1[] = { 99, };
+static const unsigned int uart4_rts_pins2[] = { 116, };
+static const unsigned int usb0_drvvbus_pins0[] = { 51, };
+static const unsigned int usb0_drvvbus_pins1[] = { 162, };
+static const unsigned int usb1_drvvbus_pins0[] = { 134, };
+static const unsigned int usb1_drvvbus_pins1[] = { 163, };
static const unsigned int visbus_dout_pins[] = { 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 53, 54, 55, 56, 85, 86,
87, 88, 89, 90, 91, 92, 93, 94, 95, 96, };
@@ -910,23 +1009,59 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("sdio_i2s_gpio_grp", sdio_i2s_gpio_pins),
GROUP("sp_rgmii_gpio_grp", sp_rgmii_gpio_pins),
GROUP("lvds_gpio_grp", lvds_gpio_pins),
- GROUP("uart_nand_gpio_grp", uart_nand_gpio_pins),
+ GROUP("jtag_uart_nand_gpio_grp", jtag_uart_nand_gpio_pins),
GROUP("rtc_gpio_grp", rtc_gpio_pins),
GROUP("audio_ac97_grp", audio_ac97_pins),
+ GROUP("audio_digmic_grp0", audio_digmic_pins0),
+ GROUP("audio_digmic_grp1", audio_digmic_pins1),
+ GROUP("audio_digmic_grp2", audio_digmic_pins2),
GROUP("audio_func_dbg_grp", audio_func_dbg_pins),
GROUP("audio_i2s_grp", audio_i2s_pins),
GROUP("audio_i2s_2ch_grp", audio_i2s_2ch_pins),
GROUP("audio_i2s_extclk_grp", audio_i2s_extclk_pins),
- GROUP("audio_uart0_grp", audio_uart0_pins),
- GROUP("audio_uart1_grp", audio_uart1_pins),
- GROUP("audio_uart2_grp0", audio_uart2_pins0),
- GROUP("audio_uart2_grp1", audio_uart2_pins1),
- GROUP("c_can_trnsvr_grp", c_can_trnsvr_pins),
- GROUP("c0_can_grp0", c0_can_pins0),
- GROUP("c0_can_grp1", c0_can_pins1),
- GROUP("c1_can_grp0", c1_can_pins0),
- GROUP("c1_can_grp1", c1_can_pins1),
- GROUP("c1_can_grp2", c1_can_pins2),
+ GROUP("audio_spdif_out_grp0", audio_spdif_out_pins0),
+ GROUP("audio_spdif_out_grp1", audio_spdif_out_pins1),
+ GROUP("audio_spdif_out_grp2", audio_spdif_out_pins2),
+ GROUP("audio_uart0_basic_grp", audio_uart0_basic_pins),
+ GROUP("audio_uart0_urfs_grp0", audio_uart0_urfs_pins0),
+ GROUP("audio_uart0_urfs_grp1", audio_uart0_urfs_pins1),
+ GROUP("audio_uart0_urfs_grp2", audio_uart0_urfs_pins2),
+ GROUP("audio_uart0_urfs_grp3", audio_uart0_urfs_pins3),
+ GROUP("audio_uart1_basic_grp", audio_uart1_basic_pins),
+ GROUP("audio_uart1_urfs_grp0", audio_uart1_urfs_pins0),
+ GROUP("audio_uart1_urfs_grp1", audio_uart1_urfs_pins1),
+ GROUP("audio_uart1_urfs_grp2", audio_uart1_urfs_pins2),
+ GROUP("audio_uart2_urfs_grp0", audio_uart2_urfs_pins0),
+ GROUP("audio_uart2_urfs_grp1", audio_uart2_urfs_pins1),
+ GROUP("audio_uart2_urfs_grp2", audio_uart2_urfs_pins2),
+ GROUP("audio_uart2_urxd_grp0", audio_uart2_urxd_pins0),
+ GROUP("audio_uart2_urxd_grp1", audio_uart2_urxd_pins1),
+ GROUP("audio_uart2_urxd_grp2", audio_uart2_urxd_pins2),
+ GROUP("audio_uart2_usclk_grp0", audio_uart2_usclk_pins0),
+ GROUP("audio_uart2_usclk_grp1", audio_uart2_usclk_pins1),
+ GROUP("audio_uart2_usclk_grp2", audio_uart2_usclk_pins2),
+ GROUP("audio_uart2_utfs_grp0", audio_uart2_utfs_pins0),
+ GROUP("audio_uart2_utfs_grp1", audio_uart2_utfs_pins1),
+ GROUP("audio_uart2_utfs_grp2", audio_uart2_utfs_pins2),
+ GROUP("audio_uart2_utxd_grp0", audio_uart2_utxd_pins0),
+ GROUP("audio_uart2_utxd_grp1", audio_uart2_utxd_pins1),
+ GROUP("audio_uart2_utxd_grp2", audio_uart2_utxd_pins2),
+ GROUP("c_can_trnsvr_en_grp0", c_can_trnsvr_en_pins0),
+ GROUP("c_can_trnsvr_en_grp1", c_can_trnsvr_en_pins1),
+ GROUP("c_can_trnsvr_intr_grp", c_can_trnsvr_intr_pins),
+ GROUP("c_can_trnsvr_stb_n_grp", c_can_trnsvr_stb_n_pins),
+ GROUP("c0_can_rxd_trnsv0_grp", c0_can_rxd_trnsv0_pins),
+ GROUP("c0_can_rxd_trnsv1_grp", c0_can_rxd_trnsv1_pins),
+ GROUP("c0_can_txd_trnsv0_grp", c0_can_txd_trnsv0_pins),
+ GROUP("c0_can_txd_trnsv1_grp", c0_can_txd_trnsv1_pins),
+ GROUP("c1_can_rxd_grp0", c1_can_rxd_pins0),
+ GROUP("c1_can_rxd_grp1", c1_can_rxd_pins1),
+ GROUP("c1_can_rxd_grp2", c1_can_rxd_pins2),
+ GROUP("c1_can_rxd_grp3", c1_can_rxd_pins3),
+ GROUP("c1_can_txd_grp0", c1_can_txd_pins0),
+ GROUP("c1_can_txd_grp1", c1_can_txd_pins1),
+ GROUP("c1_can_txd_grp2", c1_can_txd_pins2),
+ GROUP("c1_can_txd_grp3", c1_can_txd_pins3),
GROUP("ca_audio_lpc_grp", ca_audio_lpc_pins),
GROUP("ca_bt_lpc_grp", ca_bt_lpc_pins),
GROUP("ca_coex_grp", ca_coex_pins),
@@ -977,7 +1112,29 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("gn_trg_shutdown_grp3", gn_trg_shutdown_pins3),
GROUP("i2c0_grp", i2c0_pins),
GROUP("i2c1_grp", i2c1_pins),
- GROUP("jtag_grp0", jtag_pins0),
+ GROUP("i2s0_grp", i2s0_pins),
+ GROUP("i2s1_basic_grp", i2s1_basic_pins),
+ GROUP("i2s1_rxd0_grp0", i2s1_rxd0_pins0),
+ GROUP("i2s1_rxd0_grp1", i2s1_rxd0_pins1),
+ GROUP("i2s1_rxd0_grp2", i2s1_rxd0_pins2),
+ GROUP("i2s1_rxd0_grp3", i2s1_rxd0_pins3),
+ GROUP("i2s1_rxd0_grp4", i2s1_rxd0_pins4),
+ GROUP("i2s1_rxd1_grp0", i2s1_rxd1_pins0),
+ GROUP("i2s1_rxd1_grp1", i2s1_rxd1_pins1),
+ GROUP("i2s1_rxd1_grp2", i2s1_rxd1_pins2),
+ GROUP("i2s1_rxd1_grp3", i2s1_rxd1_pins3),
+ GROUP("i2s1_rxd1_grp4", i2s1_rxd1_pins4),
+ GROUP("jtag_jt_dbg_nsrst_grp", jtag_jt_dbg_nsrst_pins),
+ GROUP("jtag_ntrst_grp0", jtag_ntrst_pins0),
+ GROUP("jtag_ntrst_grp1", jtag_ntrst_pins1),
+ GROUP("jtag_swdiotms_grp0", jtag_swdiotms_pins0),
+ GROUP("jtag_swdiotms_grp1", jtag_swdiotms_pins1),
+ GROUP("jtag_tck_grp0", jtag_tck_pins0),
+ GROUP("jtag_tck_grp1", jtag_tck_pins1),
+ GROUP("jtag_tdi_grp0", jtag_tdi_pins0),
+ GROUP("jtag_tdi_grp1", jtag_tdi_pins1),
+ GROUP("jtag_tdo_grp0", jtag_tdo_pins0),
+ GROUP("jtag_tdo_grp1", jtag_tdo_pins1),
GROUP("ks_kas_spi_grp0", ks_kas_spi_pins0),
GROUP("ld_ldd_grp", ld_ldd_pins),
GROUP("ld_ldd_16bit_grp", ld_ldd_16bit_pins),
@@ -1002,18 +1159,26 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("pw_cko0_grp0", pw_cko0_pins0),
GROUP("pw_cko0_grp1", pw_cko0_pins1),
GROUP("pw_cko0_grp2", pw_cko0_pins2),
+ GROUP("pw_cko0_grp3", pw_cko0_pins3),
GROUP("pw_cko1_grp0", pw_cko1_pins0),
GROUP("pw_cko1_grp1", pw_cko1_pins1),
+ GROUP("pw_cko1_grp2", pw_cko1_pins2),
GROUP("pw_i2s01_clk_grp0", pw_i2s01_clk_pins0),
GROUP("pw_i2s01_clk_grp1", pw_i2s01_clk_pins1),
- GROUP("pw_pwm0_grp", pw_pwm0_pins),
- GROUP("pw_pwm1_grp", pw_pwm1_pins),
+ GROUP("pw_i2s01_clk_grp2", pw_i2s01_clk_pins2),
+ GROUP("pw_pwm0_grp0", pw_pwm0_pins0),
+ GROUP("pw_pwm0_grp1", pw_pwm0_pins1),
+ GROUP("pw_pwm1_grp0", pw_pwm1_pins0),
+ GROUP("pw_pwm1_grp1", pw_pwm1_pins1),
+ GROUP("pw_pwm1_grp2", pw_pwm1_pins2),
GROUP("pw_pwm2_grp0", pw_pwm2_pins0),
GROUP("pw_pwm2_grp1", pw_pwm2_pins1),
+ GROUP("pw_pwm2_grp2", pw_pwm2_pins2),
GROUP("pw_pwm3_grp0", pw_pwm3_pins0),
GROUP("pw_pwm3_grp1", pw_pwm3_pins1),
GROUP("pw_pwm_cpu_vol_grp0", pw_pwm_cpu_vol_pins0),
GROUP("pw_pwm_cpu_vol_grp1", pw_pwm_cpu_vol_pins1),
+ GROUP("pw_pwm_cpu_vol_grp2", pw_pwm_cpu_vol_pins2),
GROUP("pw_backlight_grp0", pw_backlight_pins0),
GROUP("pw_backlight_grp1", pw_backlight_pins1),
GROUP("rg_eth_mac_grp", rg_eth_mac_pins),
@@ -1026,8 +1191,11 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("sd1_grp", sd1_pins),
GROUP("sd1_4bit_grp0", sd1_4bit_pins0),
GROUP("sd1_4bit_grp1", sd1_4bit_pins1),
- GROUP("sd2_grp0", sd2_pins0),
- GROUP("sd2_no_cdb_grp0", sd2_no_cdb_pins0),
+ GROUP("sd2_basic_grp", sd2_basic_pins),
+ GROUP("sd2_cdb_grp0", sd2_cdb_pins0),
+ GROUP("sd2_cdb_grp1", sd2_cdb_pins1),
+ GROUP("sd2_wpb_grp0", sd2_wpb_pins0),
+ GROUP("sd2_wpb_grp1", sd2_wpb_pins1),
GROUP("sd3_grp", sd3_pins),
GROUP("sd5_grp", sd5_pins),
GROUP("sd6_grp0", sd6_pins0),
@@ -1039,19 +1207,39 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("uart0_grp", uart0_pins),
GROUP("uart0_nopause_grp", uart0_nopause_pins),
GROUP("uart1_grp", uart1_pins),
- GROUP("uart2_grp", uart2_pins),
- GROUP("uart3_grp0", uart3_pins0),
- GROUP("uart3_grp1", uart3_pins1),
- GROUP("uart3_grp2", uart3_pins2),
- GROUP("uart3_grp3", uart3_pins3),
- GROUP("uart3_nopause_grp0", uart3_nopause_pins0),
- GROUP("uart3_nopause_grp1", uart3_nopause_pins1),
- GROUP("uart4_grp0", uart4_pins0),
- GROUP("uart4_grp1", uart4_pins1),
- GROUP("uart4_grp2", uart4_pins2),
- GROUP("uart4_nopause_grp", uart4_nopause_pins),
- GROUP("usb0_drvvbus_grp", usb0_drvvbus_pins),
- GROUP("usb1_drvvbus_grp", usb1_drvvbus_pins),
+ GROUP("uart2_cts_grp0", uart2_cts_pins0),
+ GROUP("uart2_cts_grp1", uart2_cts_pins1),
+ GROUP("uart2_rts_grp0", uart2_rts_pins0),
+ GROUP("uart2_rts_grp1", uart2_rts_pins1),
+ GROUP("uart2_rxd_grp0", uart2_rxd_pins0),
+ GROUP("uart2_rxd_grp1", uart2_rxd_pins1),
+ GROUP("uart2_rxd_grp2", uart2_rxd_pins2),
+ GROUP("uart2_txd_grp0", uart2_txd_pins0),
+ GROUP("uart2_txd_grp1", uart2_txd_pins1),
+ GROUP("uart2_txd_grp2", uart2_txd_pins2),
+ GROUP("uart3_cts_grp0", uart3_cts_pins0),
+ GROUP("uart3_cts_grp1", uart3_cts_pins1),
+ GROUP("uart3_cts_grp2", uart3_cts_pins2),
+ GROUP("uart3_rts_grp0", uart3_rts_pins0),
+ GROUP("uart3_rts_grp1", uart3_rts_pins1),
+ GROUP("uart3_rts_grp2", uart3_rts_pins2),
+ GROUP("uart3_rxd_grp0", uart3_rxd_pins0),
+ GROUP("uart3_rxd_grp1", uart3_rxd_pins1),
+ GROUP("uart3_rxd_grp2", uart3_rxd_pins2),
+ GROUP("uart3_txd_grp0", uart3_txd_pins0),
+ GROUP("uart3_txd_grp1", uart3_txd_pins1),
+ GROUP("uart3_txd_grp2", uart3_txd_pins2),
+ GROUP("uart4_basic_grp", uart4_basic_pins),
+ GROUP("uart4_cts_grp0", uart4_cts_pins0),
+ GROUP("uart4_cts_grp1", uart4_cts_pins1),
+ GROUP("uart4_cts_grp2", uart4_cts_pins2),
+ GROUP("uart4_rts_grp0", uart4_rts_pins0),
+ GROUP("uart4_rts_grp1", uart4_rts_pins1),
+ GROUP("uart4_rts_grp2", uart4_rts_pins2),
+ GROUP("usb0_drvvbus_grp0", usb0_drvvbus_pins0),
+ GROUP("usb0_drvvbus_grp1", usb0_drvvbus_pins1),
+ GROUP("usb1_drvvbus_grp0", usb1_drvvbus_pins0),
+ GROUP("usb1_drvvbus_grp1", usb1_drvvbus_pins1),
GROUP("visbus_dout_grp", visbus_dout_pins),
GROUP("vi_vip1_grp", vi_vip1_pins),
GROUP("vi_vip1_ext_grp", vi_vip1_ext_pins),
@@ -1065,23 +1253,90 @@ static const char * const lcd_vip_gpio_grp[] = { "lcd_vip_gpio_grp", };
static const char * const sdio_i2s_gpio_grp[] = { "sdio_i2s_gpio_grp", };
static const char * const sp_rgmii_gpio_grp[] = { "sp_rgmii_gpio_grp", };
static const char * const lvds_gpio_grp[] = { "lvds_gpio_grp", };
-static const char * const uart_nand_gpio_grp[] = { "uart_nand_gpio_grp", };
+static const char * const jtag_uart_nand_gpio_grp[] = {
+ "jtag_uart_nand_gpio_grp", };
static const char * const rtc_gpio_grp[] = { "rtc_gpio_grp", };
static const char * const audio_ac97_grp[] = { "audio_ac97_grp", };
+static const char * const audio_digmic_grp0[] = { "audio_digmic_grp0", };
+static const char * const audio_digmic_grp1[] = { "audio_digmic_grp1", };
+static const char * const audio_digmic_grp2[] = { "audio_digmic_grp2", };
static const char * const audio_func_dbg_grp[] = { "audio_func_dbg_grp", };
static const char * const audio_i2s_grp[] = { "audio_i2s_grp", };
static const char * const audio_i2s_2ch_grp[] = { "audio_i2s_2ch_grp", };
static const char * const audio_i2s_extclk_grp[] = { "audio_i2s_extclk_grp", };
-static const char * const audio_uart0_grp[] = { "audio_uart0_grp", };
-static const char * const audio_uart1_grp[] = { "audio_uart1_grp", };
-static const char * const audio_uart2_grp0[] = { "audio_uart2_grp0", };
-static const char * const audio_uart2_grp1[] = { "audio_uart2_grp1", };
-static const char * const c_can_trnsvr_grp[] = { "c_can_trnsvr_grp", };
-static const char * const c0_can_grp0[] = { "c0_can_grp0", };
-static const char * const c0_can_grp1[] = { "c0_can_grp1", };
-static const char * const c1_can_grp0[] = { "c1_can_grp0", };
-static const char * const c1_can_grp1[] = { "c1_can_grp1", };
-static const char * const c1_can_grp2[] = { "c1_can_grp2", };
+static const char * const audio_spdif_out_grp0[] = { "audio_spdif_out_grp0", };
+static const char * const audio_spdif_out_grp1[] = { "audio_spdif_out_grp1", };
+static const char * const audio_spdif_out_grp2[] = { "audio_spdif_out_grp2", };
+static const char * const audio_uart0_basic_grp[] = {
+ "audio_uart0_basic_grp", };
+static const char * const audio_uart0_urfs_grp0[] = {
+ "audio_uart0_urfs_grp0", };
+static const char * const audio_uart0_urfs_grp1[] = {
+ "audio_uart0_urfs_grp1", };
+static const char * const audio_uart0_urfs_grp2[] = {
+ "audio_uart0_urfs_grp2", };
+static const char * const audio_uart0_urfs_grp3[] = {
+ "audio_uart0_urfs_grp3", };
+static const char * const audio_uart1_basic_grp[] = {
+ "audio_uart1_basic_grp", };
+static const char * const audio_uart1_urfs_grp0[] = {
+ "audio_uart1_urfs_grp0", };
+static const char * const audio_uart1_urfs_grp1[] = {
+ "audio_uart1_urfs_grp1", };
+static const char * const audio_uart1_urfs_grp2[] = {
+ "audio_uart1_urfs_grp2", };
+static const char * const audio_uart2_urfs_grp0[] = {
+ "audio_uart2_urfs_grp0", };
+static const char * const audio_uart2_urfs_grp1[] = {
+ "audio_uart2_urfs_grp1", };
+static const char * const audio_uart2_urfs_grp2[] = {
+ "audio_uart2_urfs_grp2", };
+static const char * const audio_uart2_urxd_grp0[] = {
+ "audio_uart2_urxd_grp0", };
+static const char * const audio_uart2_urxd_grp1[] = {
+ "audio_uart2_urxd_grp1", };
+static const char * const audio_uart2_urxd_grp2[] = {
+ "audio_uart2_urxd_grp2", };
+static const char * const audio_uart2_usclk_grp0[] = {
+ "audio_uart2_usclk_grp0", };
+static const char * const audio_uart2_usclk_grp1[] = {
+ "audio_uart2_usclk_grp1", };
+static const char * const audio_uart2_usclk_grp2[] = {
+ "audio_uart2_usclk_grp2", };
+static const char * const audio_uart2_utfs_grp0[] = {
+ "audio_uart2_utfs_grp0", };
+static const char * const audio_uart2_utfs_grp1[] = {
+ "audio_uart2_utfs_grp1", };
+static const char * const audio_uart2_utfs_grp2[] = {
+ "audio_uart2_utfs_grp2", };
+static const char * const audio_uart2_utxd_grp0[] = {
+ "audio_uart2_utxd_grp0", };
+static const char * const audio_uart2_utxd_grp1[] = {
+ "audio_uart2_utxd_grp1", };
+static const char * const audio_uart2_utxd_grp2[] = {
+ "audio_uart2_utxd_grp2", };
+static const char * const c_can_trnsvr_en_grp0[] = { "c_can_trnsvr_en_grp0", };
+static const char * const c_can_trnsvr_en_grp1[] = { "c_can_trnsvr_en_grp1", };
+static const char * const c_can_trnsvr_intr_grp[] = {
+ "c_can_trnsvr_intr_grp", };
+static const char * const c_can_trnsvr_stb_n_grp[] = {
+ "c_can_trnsvr_stb_n_grp", };
+static const char * const c0_can_rxd_trnsv0_grp[] = {
+ "c0_can_rxd_trnsv0_grp", };
+static const char * const c0_can_rxd_trnsv1_grp[] = {
+ "c0_can_rxd_trnsv1_grp", };
+static const char * const c0_can_txd_trnsv0_grp[] = {
+ "c0_can_txd_trnsv0_grp", };
+static const char * const c0_can_txd_trnsv1_grp[] = {
+ "c0_can_txd_trnsv1_grp", };
+static const char * const c1_can_rxd_grp0[] = { "c1_can_rxd_grp0", };
+static const char * const c1_can_rxd_grp1[] = { "c1_can_rxd_grp1", };
+static const char * const c1_can_rxd_grp2[] = { "c1_can_rxd_grp2", };
+static const char * const c1_can_rxd_grp3[] = { "c1_can_rxd_grp3", };
+static const char * const c1_can_txd_grp0[] = { "c1_can_txd_grp0", };
+static const char * const c1_can_txd_grp1[] = { "c1_can_txd_grp1", };
+static const char * const c1_can_txd_grp2[] = { "c1_can_txd_grp2", };
+static const char * const c1_can_txd_grp3[] = { "c1_can_txd_grp3", };
static const char * const ca_audio_lpc_grp[] = { "ca_audio_lpc_grp", };
static const char * const ca_bt_lpc_grp[] = { "ca_bt_lpc_grp", };
static const char * const ca_coex_grp[] = { "ca_coex_grp", };
@@ -1135,7 +1390,30 @@ static const char * const gn_trg_shutdown_grp2[] = { "gn_trg_shutdown_grp2", };
static const char * const gn_trg_shutdown_grp3[] = { "gn_trg_shutdown_grp3", };
static const char * const i2c0_grp[] = { "i2c0_grp", };
static const char * const i2c1_grp[] = { "i2c1_grp", };
-static const char * const jtag_grp0[] = { "jtag_grp0", };
+static const char * const i2s0_grp[] = { "i2s0_grp", };
+static const char * const i2s1_basic_grp[] = { "i2s1_basic_grp", };
+static const char * const i2s1_rxd0_grp0[] = { "i2s1_rxd0_grp0", };
+static const char * const i2s1_rxd0_grp1[] = { "i2s1_rxd0_grp1", };
+static const char * const i2s1_rxd0_grp2[] = { "i2s1_rxd0_grp2", };
+static const char * const i2s1_rxd0_grp3[] = { "i2s1_rxd0_grp3", };
+static const char * const i2s1_rxd0_grp4[] = { "i2s1_rxd0_grp4", };
+static const char * const i2s1_rxd1_grp0[] = { "i2s1_rxd1_grp0", };
+static const char * const i2s1_rxd1_grp1[] = { "i2s1_rxd1_grp1", };
+static const char * const i2s1_rxd1_grp2[] = { "i2s1_rxd1_grp2", };
+static const char * const i2s1_rxd1_grp3[] = { "i2s1_rxd1_grp3", };
+static const char * const i2s1_rxd1_grp4[] = { "i2s1_rxd1_grp4", };
+static const char * const jtag_jt_dbg_nsrst_grp[] = {
+ "jtag_jt_dbg_nsrst_grp", };
+static const char * const jtag_ntrst_grp0[] = { "jtag_ntrst_grp0", };
+static const char * const jtag_ntrst_grp1[] = { "jtag_ntrst_grp1", };
+static const char * const jtag_swdiotms_grp0[] = { "jtag_swdiotms_grp0", };
+static const char * const jtag_swdiotms_grp1[] = { "jtag_swdiotms_grp1", };
+static const char * const jtag_tck_grp0[] = { "jtag_tck_grp0", };
+static const char * const jtag_tck_grp1[] = { "jtag_tck_grp1", };
+static const char * const jtag_tdi_grp0[] = { "jtag_tdi_grp0", };
+static const char * const jtag_tdi_grp1[] = { "jtag_tdi_grp1", };
+static const char * const jtag_tdo_grp0[] = { "jtag_tdo_grp0", };
+static const char * const jtag_tdo_grp1[] = { "jtag_tdo_grp1", };
static const char * const ks_kas_spi_grp0[] = { "ks_kas_spi_grp0", };
static const char * const ld_ldd_grp[] = { "ld_ldd_grp", };
static const char * const ld_ldd_16bit_grp[] = { "ld_ldd_16bit_grp", };
@@ -1160,18 +1438,26 @@ static const char * const pwc_wakeup_src3_grp[] = { "pwc_wakeup_src3_grp", };
static const char * const pw_cko0_grp0[] = { "pw_cko0_grp0", };
static const char * const pw_cko0_grp1[] = { "pw_cko0_grp1", };
static const char * const pw_cko0_grp2[] = { "pw_cko0_grp2", };
+static const char * const pw_cko0_grp3[] = { "pw_cko0_grp3", };
static const char * const pw_cko1_grp0[] = { "pw_cko1_grp0", };
static const char * const pw_cko1_grp1[] = { "pw_cko1_grp1", };
+static const char * const pw_cko1_grp2[] = { "pw_cko1_grp2", };
static const char * const pw_i2s01_clk_grp0[] = { "pw_i2s01_clk_grp0", };
static const char * const pw_i2s01_clk_grp1[] = { "pw_i2s01_clk_grp1", };
-static const char * const pw_pwm0_grp[] = { "pw_pwm0_grp", };
-static const char * const pw_pwm1_grp[] = { "pw_pwm1_grp", };
+static const char * const pw_i2s01_clk_grp2[] = { "pw_i2s01_clk_grp2", };
+static const char * const pw_pwm0_grp0[] = { "pw_pwm0_grp0", };
+static const char * const pw_pwm0_grp1[] = { "pw_pwm0_grp1", };
+static const char * const pw_pwm1_grp0[] = { "pw_pwm1_grp0", };
+static const char * const pw_pwm1_grp1[] = { "pw_pwm1_grp1", };
+static const char * const pw_pwm1_grp2[] = { "pw_pwm1_grp2", };
static const char * const pw_pwm2_grp0[] = { "pw_pwm2_grp0", };
static const char * const pw_pwm2_grp1[] = { "pw_pwm2_grp1", };
+static const char * const pw_pwm2_grp2[] = { "pw_pwm2_grp2", };
static const char * const pw_pwm3_grp0[] = { "pw_pwm3_grp0", };
static const char * const pw_pwm3_grp1[] = { "pw_pwm3_grp1", };
static const char * const pw_pwm_cpu_vol_grp0[] = { "pw_pwm_cpu_vol_grp0", };
static const char * const pw_pwm_cpu_vol_grp1[] = { "pw_pwm_cpu_vol_grp1", };
+static const char * const pw_pwm_cpu_vol_grp2[] = { "pw_pwm_cpu_vol_grp2", };
static const char * const pw_backlight_grp0[] = { "pw_backlight_grp0", };
static const char * const pw_backlight_grp1[] = { "pw_backlight_grp1", };
static const char * const rg_eth_mac_grp[] = { "rg_eth_mac_grp", };
@@ -1187,8 +1473,11 @@ static const char * const sd0_4bit_grp[] = { "sd0_4bit_grp", };
static const char * const sd1_grp[] = { "sd1_grp", };
static const char * const sd1_4bit_grp0[] = { "sd1_4bit_grp0", };
static const char * const sd1_4bit_grp1[] = { "sd1_4bit_grp1", };
-static const char * const sd2_grp0[] = { "sd2_grp0", };
-static const char * const sd2_no_cdb_grp0[] = { "sd2_no_cdb_grp0", };
+static const char * const sd2_basic_grp[] = { "sd2_basic_grp", };
+static const char * const sd2_cdb_grp0[] = { "sd2_cdb_grp0", };
+static const char * const sd2_cdb_grp1[] = { "sd2_cdb_grp1", };
+static const char * const sd2_wpb_grp0[] = { "sd2_wpb_grp0", };
+static const char * const sd2_wpb_grp1[] = { "sd2_wpb_grp1", };
static const char * const sd3_grp[] = { "sd3_grp", };
static const char * const sd5_grp[] = { "sd5_grp", };
static const char * const sd6_grp0[] = { "sd6_grp0", };
@@ -1200,19 +1489,39 @@ static const char * const tpiu_trace_grp[] = { "tpiu_trace_grp", };
static const char * const uart0_grp[] = { "uart0_grp", };
static const char * const uart0_nopause_grp[] = { "uart0_nopause_grp", };
static const char * const uart1_grp[] = { "uart1_grp", };
-static const char * const uart2_grp[] = { "uart2_grp", };
-static const char * const uart3_grp0[] = { "uart3_grp0", };
-static const char * const uart3_grp1[] = { "uart3_grp1", };
-static const char * const uart3_grp2[] = { "uart3_grp2", };
-static const char * const uart3_grp3[] = { "uart3_grp3", };
-static const char * const uart3_nopause_grp0[] = { "uart3_nopause_grp0", };
-static const char * const uart3_nopause_grp1[] = { "uart3_nopause_grp1", };
-static const char * const uart4_grp0[] = { "uart4_grp0", };
-static const char * const uart4_grp1[] = { "uart4_grp1", };
-static const char * const uart4_grp2[] = { "uart4_grp2", };
-static const char * const uart4_nopause_grp[] = { "uart4_nopause_grp", };
-static const char * const usb0_drvvbus_grp[] = { "usb0_drvvbus_grp", };
-static const char * const usb1_drvvbus_grp[] = { "usb1_drvvbus_grp", };
+static const char * const uart2_cts_grp0[] = { "uart2_cts_grp0", };
+static const char * const uart2_cts_grp1[] = { "uart2_cts_grp1", };
+static const char * const uart2_rts_grp0[] = { "uart2_rts_grp0", };
+static const char * const uart2_rts_grp1[] = { "uart2_rts_grp1", };
+static const char * const uart2_rxd_grp0[] = { "uart2_rxd_grp0", };
+static const char * const uart2_rxd_grp1[] = { "uart2_rxd_grp1", };
+static const char * const uart2_rxd_grp2[] = { "uart2_rxd_grp2", };
+static const char * const uart2_txd_grp0[] = { "uart2_txd_grp0", };
+static const char * const uart2_txd_grp1[] = { "uart2_txd_grp1", };
+static const char * const uart2_txd_grp2[] = { "uart2_txd_grp2", };
+static const char * const uart3_cts_grp0[] = { "uart3_cts_grp0", };
+static const char * const uart3_cts_grp1[] = { "uart3_cts_grp1", };
+static const char * const uart3_cts_grp2[] = { "uart3_cts_grp2", };
+static const char * const uart3_rts_grp0[] = { "uart3_rts_grp0", };
+static const char * const uart3_rts_grp1[] = { "uart3_rts_grp1", };
+static const char * const uart3_rts_grp2[] = { "uart3_rts_grp2", };
+static const char * const uart3_rxd_grp0[] = { "uart3_rxd_grp0", };
+static const char * const uart3_rxd_grp1[] = { "uart3_rxd_grp1", };
+static const char * const uart3_rxd_grp2[] = { "uart3_rxd_grp2", };
+static const char * const uart3_txd_grp0[] = { "uart3_txd_grp0", };
+static const char * const uart3_txd_grp1[] = { "uart3_txd_grp1", };
+static const char * const uart3_txd_grp2[] = { "uart3_txd_grp2", };
+static const char * const uart4_basic_grp[] = { "uart4_basic_grp", };
+static const char * const uart4_cts_grp0[] = { "uart4_cts_grp0", };
+static const char * const uart4_cts_grp1[] = { "uart4_cts_grp1", };
+static const char * const uart4_cts_grp2[] = { "uart4_cts_grp2", };
+static const char * const uart4_rts_grp0[] = { "uart4_rts_grp0", };
+static const char * const uart4_rts_grp1[] = { "uart4_rts_grp1", };
+static const char * const uart4_rts_grp2[] = { "uart4_rts_grp2", };
+static const char * const usb0_drvvbus_grp0[] = { "usb0_drvvbus_grp0", };
+static const char * const usb0_drvvbus_grp1[] = { "usb0_drvvbus_grp1", };
+static const char * const usb1_drvvbus_grp0[] = { "usb1_drvvbus_grp0", };
+static const char * const usb1_drvvbus_grp1[] = { "usb1_drvvbus_grp1", };
static const char * const visbus_dout_grp[] = { "visbus_dout_grp", };
static const char * const vi_vip1_grp[] = { "vi_vip1_grp", };
static const char * const vi_vip1_ext_grp[] = { "vi_vip1_ext_grp", };
@@ -1376,7 +1685,7 @@ static struct atlas7_grp_mux lvds_gpio_grp_mux = {
.pad_mux_list = lvds_gpio_grp_pad_mux,
};
-static struct atlas7_pad_mux uart_nand_gpio_grp_pad_mux[] = {
+static struct atlas7_pad_mux jtag_uart_nand_gpio_grp_pad_mux[] = {
MUX(1, 44, 0, N, N, N, N),
MUX(1, 43, 0, N, N, N, N),
MUX(1, 42, 0, N, N, N, N),
@@ -1401,11 +1710,16 @@ static struct atlas7_pad_mux uart_nand_gpio_grp_pad_mux[] = {
MUX(1, 138, 0, N, N, N, N),
MUX(1, 139, 0, N, N, N, N),
MUX(1, 140, 0, N, N, N, N),
+ MUX(1, 159, 0, N, N, N, N),
+ MUX(1, 160, 0, N, N, N, N),
+ MUX(1, 161, 0, N, N, N, N),
+ MUX(1, 162, 0, N, N, N, N),
+ MUX(1, 163, 0, N, N, N, N),
};
-static struct atlas7_grp_mux uart_nand_gpio_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(uart_nand_gpio_grp_pad_mux),
- .pad_mux_list = uart_nand_gpio_grp_pad_mux,
+static struct atlas7_grp_mux jtag_uart_nand_gpio_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_uart_nand_gpio_grp_pad_mux),
+ .pad_mux_list = jtag_uart_nand_gpio_grp_pad_mux,
};
static struct atlas7_pad_mux rtc_gpio_grp_pad_mux[] = {
@@ -1422,6 +1736,7 @@ static struct atlas7_pad_mux rtc_gpio_grp_pad_mux[] = {
MUX(0, 15, 0, N, N, N, N),
MUX(0, 16, 0, N, N, N, N),
MUX(0, 17, 0, N, N, N, N),
+ MUX(0, 9, 0, N, N, N, N),
};
static struct atlas7_grp_mux rtc_gpio_grp_mux = {
@@ -1441,6 +1756,33 @@ static struct atlas7_grp_mux audio_ac97_grp_mux = {
.pad_mux_list = audio_ac97_grp_pad_mux,
};
+static struct atlas7_pad_mux audio_digmic_grp0_pad_mux[] = {
+ MUX(1, 51, 3, 0xa10, 20, 0xa90, 20),
+};
+
+static struct atlas7_grp_mux audio_digmic_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_digmic_grp0_pad_mux),
+ .pad_mux_list = audio_digmic_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_digmic_grp1_pad_mux[] = {
+ MUX(1, 122, 5, 0xa10, 20, 0xa90, 20),
+};
+
+static struct atlas7_grp_mux audio_digmic_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_digmic_grp1_pad_mux),
+ .pad_mux_list = audio_digmic_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_digmic_grp2_pad_mux[] = {
+ MUX(1, 161, 7, 0xa10, 20, 0xa90, 20),
+};
+
+static struct atlas7_grp_mux audio_digmic_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_digmic_grp2_pad_mux),
+ .pad_mux_list = audio_digmic_grp2_pad_mux,
+};
+
static struct atlas7_pad_mux audio_func_dbg_grp_pad_mux[] = {
MUX(1, 141, 4, N, N, N, N),
MUX(1, 144, 4, N, N, N, N),
@@ -1512,111 +1854,397 @@ static struct atlas7_grp_mux audio_i2s_extclk_grp_mux = {
.pad_mux_list = audio_i2s_extclk_grp_pad_mux,
};
-static struct atlas7_pad_mux audio_uart0_grp_pad_mux[] = {
+static struct atlas7_pad_mux audio_spdif_out_grp0_pad_mux[] = {
+ MUX(1, 112, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux audio_spdif_out_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_spdif_out_grp0_pad_mux),
+ .pad_mux_list = audio_spdif_out_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_spdif_out_grp1_pad_mux[] = {
+ MUX(1, 116, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux audio_spdif_out_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_spdif_out_grp1_pad_mux),
+ .pad_mux_list = audio_spdif_out_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_spdif_out_grp2_pad_mux[] = {
+ MUX(1, 142, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux audio_spdif_out_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_spdif_out_grp2_pad_mux),
+ .pad_mux_list = audio_spdif_out_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart0_basic_grp_pad_mux[] = {
MUX(1, 143, 1, N, N, N, N),
MUX(1, 142, 1, N, N, N, N),
MUX(1, 141, 1, N, N, N, N),
MUX(1, 144, 1, N, N, N, N),
};
-static struct atlas7_grp_mux audio_uart0_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(audio_uart0_grp_pad_mux),
- .pad_mux_list = audio_uart0_grp_pad_mux,
+static struct atlas7_grp_mux audio_uart0_basic_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart0_basic_grp_pad_mux),
+ .pad_mux_list = audio_uart0_basic_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart0_urfs_grp0_pad_mux[] = {
+ MUX(1, 117, 5, 0xa10, 28, 0xa90, 28),
};
-static struct atlas7_pad_mux audio_uart1_grp_pad_mux[] = {
- MUX(1, 147, 1, N, N, N, N),
- MUX(1, 146, 1, N, N, N, N),
- MUX(1, 145, 1, N, N, N, N),
- MUX(1, 148, 1, N, N, N, N),
+static struct atlas7_grp_mux audio_uart0_urfs_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart0_urfs_grp0_pad_mux),
+ .pad_mux_list = audio_uart0_urfs_grp0_pad_mux,
};
-static struct atlas7_grp_mux audio_uart1_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(audio_uart1_grp_pad_mux),
- .pad_mux_list = audio_uart1_grp_pad_mux,
+static struct atlas7_pad_mux audio_uart0_urfs_grp1_pad_mux[] = {
+ MUX(1, 139, 3, 0xa10, 28, 0xa90, 28),
};
-static struct atlas7_pad_mux audio_uart2_grp0_pad_mux[] = {
+static struct atlas7_grp_mux audio_uart0_urfs_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart0_urfs_grp1_pad_mux),
+ .pad_mux_list = audio_uart0_urfs_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart0_urfs_grp2_pad_mux[] = {
+ MUX(1, 163, 3, 0xa10, 28, 0xa90, 28),
+};
+
+static struct atlas7_grp_mux audio_uart0_urfs_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart0_urfs_grp2_pad_mux),
+ .pad_mux_list = audio_uart0_urfs_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart0_urfs_grp3_pad_mux[] = {
+ MUX(1, 162, 6, 0xa10, 28, 0xa90, 28),
+};
+
+static struct atlas7_grp_mux audio_uart0_urfs_grp3_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart0_urfs_grp3_pad_mux),
+ .pad_mux_list = audio_uart0_urfs_grp3_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart1_basic_grp_pad_mux[] = {
+ MUX(1, 147, 1, 0xa10, 24, 0xa90, 24),
+ MUX(1, 146, 1, 0xa10, 25, 0xa90, 25),
+ MUX(1, 145, 1, 0xa10, 23, 0xa90, 23),
+ MUX(1, 148, 1, 0xa10, 22, 0xa90, 22),
+};
+
+static struct atlas7_grp_mux audio_uart1_basic_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart1_basic_grp_pad_mux),
+ .pad_mux_list = audio_uart1_basic_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart1_urfs_grp0_pad_mux[] = {
+ MUX(1, 117, 6, 0xa10, 29, 0xa90, 29),
+};
+
+static struct atlas7_grp_mux audio_uart1_urfs_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart1_urfs_grp0_pad_mux),
+ .pad_mux_list = audio_uart1_urfs_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart1_urfs_grp1_pad_mux[] = {
+ MUX(1, 140, 3, 0xa10, 29, 0xa90, 29),
+};
+
+static struct atlas7_grp_mux audio_uart1_urfs_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart1_urfs_grp1_pad_mux),
+ .pad_mux_list = audio_uart1_urfs_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart1_urfs_grp2_pad_mux[] = {
+ MUX(1, 163, 4, 0xa10, 29, 0xa90, 29),
+};
+
+static struct atlas7_grp_mux audio_uart1_urfs_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart1_urfs_grp2_pad_mux),
+ .pad_mux_list = audio_uart1_urfs_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_urfs_grp0_pad_mux[] = {
+ MUX(1, 139, 4, 0xa10, 30, 0xa90, 30),
+};
+
+static struct atlas7_grp_mux audio_uart2_urfs_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_urfs_grp0_pad_mux),
+ .pad_mux_list = audio_uart2_urfs_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_urfs_grp1_pad_mux[] = {
+ MUX(1, 163, 6, 0xa10, 30, 0xa90, 30),
+};
+
+static struct atlas7_grp_mux audio_uart2_urfs_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_urfs_grp1_pad_mux),
+ .pad_mux_list = audio_uart2_urfs_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_urfs_grp2_pad_mux[] = {
+ MUX(1, 96, 3, 0xa10, 30, 0xa90, 30),
+};
+
+static struct atlas7_grp_mux audio_uart2_urfs_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_urfs_grp2_pad_mux),
+ .pad_mux_list = audio_uart2_urfs_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_urxd_grp0_pad_mux[] = {
MUX(1, 20, 2, 0xa00, 24, 0xa80, 24),
- MUX(1, 21, 2, 0xa00, 25, 0xa80, 25),
- MUX(1, 19, 2, 0xa00, 23, 0xa80, 23),
- MUX(1, 18, 2, 0xa00, 22, 0xa80, 22),
};
-static struct atlas7_grp_mux audio_uart2_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(audio_uart2_grp0_pad_mux),
- .pad_mux_list = audio_uart2_grp0_pad_mux,
+static struct atlas7_grp_mux audio_uart2_urxd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_urxd_grp0_pad_mux),
+ .pad_mux_list = audio_uart2_urxd_grp0_pad_mux,
};
-static struct atlas7_pad_mux audio_uart2_grp1_pad_mux[] = {
+static struct atlas7_pad_mux audio_uart2_urxd_grp1_pad_mux[] = {
MUX(1, 109, 2, 0xa00, 24, 0xa80, 24),
- MUX(1, 110, 2, 0xa00, 25, 0xa80, 25),
+};
+
+static struct atlas7_grp_mux audio_uart2_urxd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_urxd_grp1_pad_mux),
+ .pad_mux_list = audio_uart2_urxd_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_urxd_grp2_pad_mux[] = {
+ MUX(1, 93, 3, 0xa00, 24, 0xa80, 24),
+};
+
+static struct atlas7_grp_mux audio_uart2_urxd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_urxd_grp2_pad_mux),
+ .pad_mux_list = audio_uart2_urxd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_usclk_grp0_pad_mux[] = {
+ MUX(1, 19, 2, 0xa00, 23, 0xa80, 23),
+};
+
+static struct atlas7_grp_mux audio_uart2_usclk_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_usclk_grp0_pad_mux),
+ .pad_mux_list = audio_uart2_usclk_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_usclk_grp1_pad_mux[] = {
MUX(1, 101, 2, 0xa00, 23, 0xa80, 23),
+};
+
+static struct atlas7_grp_mux audio_uart2_usclk_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_usclk_grp1_pad_mux),
+ .pad_mux_list = audio_uart2_usclk_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_usclk_grp2_pad_mux[] = {
+ MUX(1, 91, 3, 0xa00, 23, 0xa80, 23),
+};
+
+static struct atlas7_grp_mux audio_uart2_usclk_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_usclk_grp2_pad_mux),
+ .pad_mux_list = audio_uart2_usclk_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_utfs_grp0_pad_mux[] = {
+ MUX(1, 18, 2, 0xa00, 22, 0xa80, 22),
+};
+
+static struct atlas7_grp_mux audio_uart2_utfs_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_utfs_grp0_pad_mux),
+ .pad_mux_list = audio_uart2_utfs_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_utfs_grp1_pad_mux[] = {
MUX(1, 111, 2, 0xa00, 22, 0xa80, 22),
};
-static struct atlas7_grp_mux audio_uart2_grp1_mux = {
- .pad_mux_count = ARRAY_SIZE(audio_uart2_grp1_pad_mux),
- .pad_mux_list = audio_uart2_grp1_pad_mux,
+static struct atlas7_grp_mux audio_uart2_utfs_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_utfs_grp1_pad_mux),
+ .pad_mux_list = audio_uart2_utfs_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_utfs_grp2_pad_mux[] = {
+ MUX(1, 94, 3, 0xa00, 22, 0xa80, 22),
+};
+
+static struct atlas7_grp_mux audio_uart2_utfs_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_utfs_grp2_pad_mux),
+ .pad_mux_list = audio_uart2_utfs_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_utxd_grp0_pad_mux[] = {
+ MUX(1, 21, 2, 0xa00, 25, 0xa80, 25),
+};
+
+static struct atlas7_grp_mux audio_uart2_utxd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_utxd_grp0_pad_mux),
+ .pad_mux_list = audio_uart2_utxd_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_utxd_grp1_pad_mux[] = {
+ MUX(1, 110, 2, 0xa00, 25, 0xa80, 25),
+};
+
+static struct atlas7_grp_mux audio_uart2_utxd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_utxd_grp1_pad_mux),
+ .pad_mux_list = audio_uart2_utxd_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux audio_uart2_utxd_grp2_pad_mux[] = {
+ MUX(1, 92, 3, 0xa00, 25, 0xa80, 25),
+};
+
+static struct atlas7_grp_mux audio_uart2_utxd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(audio_uart2_utxd_grp2_pad_mux),
+ .pad_mux_list = audio_uart2_utxd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux c_can_trnsvr_en_grp0_pad_mux[] = {
+ MUX(0, 2, 6, N, N, N, N),
};
-static struct atlas7_pad_mux c_can_trnsvr_grp_pad_mux[] = {
+static struct atlas7_grp_mux c_can_trnsvr_en_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(c_can_trnsvr_en_grp0_pad_mux),
+ .pad_mux_list = c_can_trnsvr_en_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux c_can_trnsvr_en_grp1_pad_mux[] = {
+ MUX(0, 0, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux c_can_trnsvr_en_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(c_can_trnsvr_en_grp1_pad_mux),
+ .pad_mux_list = c_can_trnsvr_en_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux c_can_trnsvr_intr_grp_pad_mux[] = {
MUX(0, 1, 2, N, N, N, N),
};
-static struct atlas7_grp_mux c_can_trnsvr_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(c_can_trnsvr_grp_pad_mux),
- .pad_mux_list = c_can_trnsvr_grp_pad_mux,
+static struct atlas7_grp_mux c_can_trnsvr_intr_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(c_can_trnsvr_intr_grp_pad_mux),
+ .pad_mux_list = c_can_trnsvr_intr_grp_pad_mux,
};
-static struct atlas7_pad_mux c0_can_grp0_pad_mux[] = {
+static struct atlas7_pad_mux c_can_trnsvr_stb_n_grp_pad_mux[] = {
+ MUX(0, 3, 6, N, N, N, N),
+};
+
+static struct atlas7_grp_mux c_can_trnsvr_stb_n_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(c_can_trnsvr_stb_n_grp_pad_mux),
+ .pad_mux_list = c_can_trnsvr_stb_n_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux c0_can_rxd_trnsv0_grp_pad_mux[] = {
MUX(0, 11, 1, 0xa08, 9, 0xa88, 9),
+};
+
+static struct atlas7_grp_mux c0_can_rxd_trnsv0_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(c0_can_rxd_trnsv0_grp_pad_mux),
+ .pad_mux_list = c0_can_rxd_trnsv0_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux c0_can_rxd_trnsv1_grp_pad_mux[] = {
+ MUX(0, 2, 5, 0xa10, 9, 0xa90, 9),
+};
+
+static struct atlas7_grp_mux c0_can_rxd_trnsv1_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(c0_can_rxd_trnsv1_grp_pad_mux),
+ .pad_mux_list = c0_can_rxd_trnsv1_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux c0_can_txd_trnsv0_grp_pad_mux[] = {
MUX(0, 10, 1, N, N, N, N),
};
-static struct atlas7_grp_mux c0_can_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(c0_can_grp0_pad_mux),
- .pad_mux_list = c0_can_grp0_pad_mux,
+static struct atlas7_grp_mux c0_can_txd_trnsv0_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(c0_can_txd_trnsv0_grp_pad_mux),
+ .pad_mux_list = c0_can_txd_trnsv0_grp_pad_mux,
};
-static struct atlas7_pad_mux c0_can_grp1_pad_mux[] = {
- MUX(0, 2, 5, 0xa08, 9, 0xa88, 9),
+static struct atlas7_pad_mux c0_can_txd_trnsv1_grp_pad_mux[] = {
MUX(0, 3, 5, N, N, N, N),
};
-static struct atlas7_grp_mux c0_can_grp1_mux = {
- .pad_mux_count = ARRAY_SIZE(c0_can_grp1_pad_mux),
- .pad_mux_list = c0_can_grp1_pad_mux,
+static struct atlas7_grp_mux c0_can_txd_trnsv1_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(c0_can_txd_trnsv1_grp_pad_mux),
+ .pad_mux_list = c0_can_txd_trnsv1_grp_pad_mux,
};
-static struct atlas7_pad_mux c1_can_grp0_pad_mux[] = {
+static struct atlas7_pad_mux c1_can_rxd_grp0_pad_mux[] = {
MUX(1, 138, 2, 0xa00, 4, 0xa80, 4),
- MUX(1, 137, 2, N, N, N, N),
};
-static struct atlas7_grp_mux c1_can_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(c1_can_grp0_pad_mux),
- .pad_mux_list = c1_can_grp0_pad_mux,
+static struct atlas7_grp_mux c1_can_rxd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_rxd_grp0_pad_mux),
+ .pad_mux_list = c1_can_rxd_grp0_pad_mux,
};
-static struct atlas7_pad_mux c1_can_grp1_pad_mux[] = {
+static struct atlas7_pad_mux c1_can_rxd_grp1_pad_mux[] = {
MUX(1, 147, 2, 0xa00, 4, 0xa80, 4),
- MUX(1, 146, 2, N, N, N, N),
};
-static struct atlas7_grp_mux c1_can_grp1_mux = {
- .pad_mux_count = ARRAY_SIZE(c1_can_grp1_pad_mux),
- .pad_mux_list = c1_can_grp1_pad_mux,
+static struct atlas7_grp_mux c1_can_rxd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_rxd_grp1_pad_mux),
+ .pad_mux_list = c1_can_rxd_grp1_pad_mux,
};
-static struct atlas7_pad_mux c1_can_grp2_pad_mux[] = {
+static struct atlas7_pad_mux c1_can_rxd_grp2_pad_mux[] = {
MUX(0, 2, 2, 0xa00, 4, 0xa80, 4),
+};
+
+static struct atlas7_grp_mux c1_can_rxd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_rxd_grp2_pad_mux),
+ .pad_mux_list = c1_can_rxd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux c1_can_rxd_grp3_pad_mux[] = {
+ MUX(1, 162, 4, 0xa00, 4, 0xa80, 4),
+};
+
+static struct atlas7_grp_mux c1_can_rxd_grp3_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_rxd_grp3_pad_mux),
+ .pad_mux_list = c1_can_rxd_grp3_pad_mux,
+};
+
+static struct atlas7_pad_mux c1_can_txd_grp0_pad_mux[] = {
+ MUX(1, 137, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux c1_can_txd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_txd_grp0_pad_mux),
+ .pad_mux_list = c1_can_txd_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux c1_can_txd_grp1_pad_mux[] = {
+ MUX(1, 146, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux c1_can_txd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_txd_grp1_pad_mux),
+ .pad_mux_list = c1_can_txd_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux c1_can_txd_grp2_pad_mux[] = {
MUX(0, 3, 2, N, N, N, N),
};
-static struct atlas7_grp_mux c1_can_grp2_mux = {
- .pad_mux_count = ARRAY_SIZE(c1_can_grp2_pad_mux),
- .pad_mux_list = c1_can_grp2_pad_mux,
+static struct atlas7_grp_mux c1_can_txd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_txd_grp2_pad_mux),
+ .pad_mux_list = c1_can_txd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux c1_can_txd_grp3_pad_mux[] = {
+ MUX(1, 161, 4, N, N, N, N),
+};
+
+static struct atlas7_grp_mux c1_can_txd_grp3_mux = {
+ .pad_mux_count = ARRAY_SIZE(c1_can_txd_grp3_pad_mux),
+ .pad_mux_list = c1_can_txd_grp3_pad_mux,
};
static struct atlas7_pad_mux ca_audio_lpc_grp_pad_mux[] = {
@@ -2198,18 +2826,215 @@ static struct atlas7_grp_mux i2c1_grp_mux = {
.pad_mux_list = i2c1_grp_pad_mux,
};
-static struct atlas7_pad_mux jtag_grp0_pad_mux[] = {
+static struct atlas7_pad_mux i2s0_grp_pad_mux[] = {
+ MUX(1, 91, 2, 0xa10, 12, 0xa90, 12),
+ MUX(1, 93, 2, 0xa10, 13, 0xa90, 13),
+ MUX(1, 94, 2, 0xa10, 14, 0xa90, 14),
+ MUX(1, 92, 2, 0xa10, 15, 0xa90, 15),
+};
+
+static struct atlas7_grp_mux i2s0_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s0_grp_pad_mux),
+ .pad_mux_list = i2s0_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_basic_grp_pad_mux[] = {
+ MUX(1, 95, 2, 0xa10, 16, 0xa90, 16),
+ MUX(1, 96, 2, 0xa10, 19, 0xa90, 19),
+};
+
+static struct atlas7_grp_mux i2s1_basic_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_basic_grp_pad_mux),
+ .pad_mux_list = i2s1_basic_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd0_grp0_pad_mux[] = {
+ MUX(1, 61, 4, 0xa10, 17, 0xa90, 17),
+};
+
+static struct atlas7_grp_mux i2s1_rxd0_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd0_grp0_pad_mux),
+ .pad_mux_list = i2s1_rxd0_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd0_grp1_pad_mux[] = {
+ MUX(1, 131, 4, 0xa10, 17, 0xa90, 17),
+};
+
+static struct atlas7_grp_mux i2s1_rxd0_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd0_grp1_pad_mux),
+ .pad_mux_list = i2s1_rxd0_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd0_grp2_pad_mux[] = {
+ MUX(1, 129, 2, 0xa10, 17, 0xa90, 17),
+};
+
+static struct atlas7_grp_mux i2s1_rxd0_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd0_grp2_pad_mux),
+ .pad_mux_list = i2s1_rxd0_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd0_grp3_pad_mux[] = {
+ MUX(1, 117, 7, 0xa10, 17, 0xa90, 17),
+};
+
+static struct atlas7_grp_mux i2s1_rxd0_grp3_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd0_grp3_pad_mux),
+ .pad_mux_list = i2s1_rxd0_grp3_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd0_grp4_pad_mux[] = {
+ MUX(1, 83, 4, 0xa10, 17, 0xa90, 17),
+};
+
+static struct atlas7_grp_mux i2s1_rxd0_grp4_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd0_grp4_pad_mux),
+ .pad_mux_list = i2s1_rxd0_grp4_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd1_grp0_pad_mux[] = {
+ MUX(1, 72, 4, 0xa10, 18, 0xa90, 18),
+};
+
+static struct atlas7_grp_mux i2s1_rxd1_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd1_grp0_pad_mux),
+ .pad_mux_list = i2s1_rxd1_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd1_grp1_pad_mux[] = {
+ MUX(1, 132, 4, 0xa10, 18, 0xa90, 18),
+};
+
+static struct atlas7_grp_mux i2s1_rxd1_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd1_grp1_pad_mux),
+ .pad_mux_list = i2s1_rxd1_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd1_grp2_pad_mux[] = {
+ MUX(1, 130, 2, 0xa10, 18, 0xa90, 18),
+};
+
+static struct atlas7_grp_mux i2s1_rxd1_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd1_grp2_pad_mux),
+ .pad_mux_list = i2s1_rxd1_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd1_grp3_pad_mux[] = {
+ MUX(1, 118, 7, 0xa10, 18, 0xa90, 18),
+};
+
+static struct atlas7_grp_mux i2s1_rxd1_grp3_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd1_grp3_pad_mux),
+ .pad_mux_list = i2s1_rxd1_grp3_pad_mux,
+};
+
+static struct atlas7_pad_mux i2s1_rxd1_grp4_pad_mux[] = {
+ MUX(1, 84, 4, 0xa10, 18, 0xa90, 18),
+};
+
+static struct atlas7_grp_mux i2s1_rxd1_grp4_mux = {
+ .pad_mux_count = ARRAY_SIZE(i2s1_rxd1_grp4_pad_mux),
+ .pad_mux_list = i2s1_rxd1_grp4_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_jt_dbg_nsrst_grp_pad_mux[] = {
MUX(1, 125, 5, 0xa08, 2, 0xa88, 2),
+};
+
+static struct atlas7_grp_mux jtag_jt_dbg_nsrst_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_jt_dbg_nsrst_grp_pad_mux),
+ .pad_mux_list = jtag_jt_dbg_nsrst_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_ntrst_grp0_pad_mux[] = {
MUX(0, 4, 3, 0xa08, 3, 0xa88, 3),
- MUX(0, 2, 3, N, N, N, N),
- MUX(0, 0, 3, N, N, N, N),
- MUX(0, 1, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux jtag_ntrst_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_ntrst_grp0_pad_mux),
+ .pad_mux_list = jtag_ntrst_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_ntrst_grp1_pad_mux[] = {
+ MUX(1, 163, 1, 0xa08, 3, 0xa88, 3),
+};
+
+static struct atlas7_grp_mux jtag_ntrst_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_ntrst_grp1_pad_mux),
+ .pad_mux_list = jtag_ntrst_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_swdiotms_grp0_pad_mux[] = {
+ MUX(0, 2, 3, 0xa10, 10, 0xa90, 10),
+};
+
+static struct atlas7_grp_mux jtag_swdiotms_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_swdiotms_grp0_pad_mux),
+ .pad_mux_list = jtag_swdiotms_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_swdiotms_grp1_pad_mux[] = {
+ MUX(1, 160, 1, 0xa10, 10, 0xa90, 10),
+};
+
+static struct atlas7_grp_mux jtag_swdiotms_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_swdiotms_grp1_pad_mux),
+ .pad_mux_list = jtag_swdiotms_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_tck_grp0_pad_mux[] = {
+ MUX(0, 0, 3, 0xa10, 11, 0xa90, 11),
+};
+
+static struct atlas7_grp_mux jtag_tck_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_tck_grp0_pad_mux),
+ .pad_mux_list = jtag_tck_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_tck_grp1_pad_mux[] = {
+ MUX(1, 161, 1, 0xa10, 11, 0xa90, 11),
+};
+
+static struct atlas7_grp_mux jtag_tck_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_tck_grp1_pad_mux),
+ .pad_mux_list = jtag_tck_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_tdi_grp0_pad_mux[] = {
+ MUX(0, 1, 3, 0xa10, 31, 0xa90, 31),
+};
+
+static struct atlas7_grp_mux jtag_tdi_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_tdi_grp0_pad_mux),
+ .pad_mux_list = jtag_tdi_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_tdi_grp1_pad_mux[] = {
+ MUX(1, 162, 1, 0xa10, 31, 0xa90, 31),
+};
+
+static struct atlas7_grp_mux jtag_tdi_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_tdi_grp1_pad_mux),
+ .pad_mux_list = jtag_tdi_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_tdo_grp0_pad_mux[] = {
MUX(0, 3, 3, N, N, N, N),
};
-static struct atlas7_grp_mux jtag_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(jtag_grp0_pad_mux),
- .pad_mux_list = jtag_grp0_pad_mux,
+static struct atlas7_grp_mux jtag_tdo_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_tdo_grp0_pad_mux),
+ .pad_mux_list = jtag_tdo_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux jtag_tdo_grp1_pad_mux[] = {
+ MUX(1, 159, 1, N, N, N, N),
+};
+
+static struct atlas7_grp_mux jtag_tdo_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(jtag_tdo_grp1_pad_mux),
+ .pad_mux_list = jtag_tdo_grp1_pad_mux,
};
static struct atlas7_pad_mux ks_kas_spi_grp0_pad_mux[] = {
@@ -2401,6 +3226,7 @@ static struct atlas7_grp_mux nd_df_nowp_grp_mux = {
static struct atlas7_pad_mux ps_grp_pad_mux[] = {
MUX(1, 120, 2, N, N, N, N),
MUX(1, 119, 2, N, N, N, N),
+ MUX(1, 121, 5, N, N, N, N),
};
static struct atlas7_grp_mux ps_grp_mux = {
@@ -2534,6 +3360,15 @@ static struct atlas7_grp_mux pw_cko0_grp2_mux = {
.pad_mux_list = pw_cko0_grp2_pad_mux,
};
+static struct atlas7_pad_mux pw_cko0_grp3_pad_mux[] = {
+ MUX(1, 162, 5, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_cko0_grp3_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_cko0_grp3_pad_mux),
+ .pad_mux_list = pw_cko0_grp3_pad_mux,
+};
+
static struct atlas7_pad_mux pw_cko1_grp0_pad_mux[] = {
MUX(1, 124, 3, N, N, N, N),
};
@@ -2552,6 +3387,15 @@ static struct atlas7_grp_mux pw_cko1_grp1_mux = {
.pad_mux_list = pw_cko1_grp1_pad_mux,
};
+static struct atlas7_pad_mux pw_cko1_grp2_pad_mux[] = {
+ MUX(1, 163, 5, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_cko1_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_cko1_grp2_pad_mux),
+ .pad_mux_list = pw_cko1_grp2_pad_mux,
+};
+
static struct atlas7_pad_mux pw_i2s01_clk_grp0_pad_mux[] = {
MUX(1, 125, 3, N, N, N, N),
};
@@ -2570,22 +3414,58 @@ static struct atlas7_grp_mux pw_i2s01_clk_grp1_mux = {
.pad_mux_list = pw_i2s01_clk_grp1_pad_mux,
};
-static struct atlas7_pad_mux pw_pwm0_grp_pad_mux[] = {
+static struct atlas7_pad_mux pw_i2s01_clk_grp2_pad_mux[] = {
+ MUX(1, 132, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_i2s01_clk_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_i2s01_clk_grp2_pad_mux),
+ .pad_mux_list = pw_i2s01_clk_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux pw_pwm0_grp0_pad_mux[] = {
MUX(1, 119, 3, N, N, N, N),
};
-static struct atlas7_grp_mux pw_pwm0_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(pw_pwm0_grp_pad_mux),
- .pad_mux_list = pw_pwm0_grp_pad_mux,
+static struct atlas7_grp_mux pw_pwm0_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm0_grp0_pad_mux),
+ .pad_mux_list = pw_pwm0_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux pw_pwm0_grp1_pad_mux[] = {
+ MUX(1, 159, 5, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_pwm0_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm0_grp1_pad_mux),
+ .pad_mux_list = pw_pwm0_grp1_pad_mux,
};
-static struct atlas7_pad_mux pw_pwm1_grp_pad_mux[] = {
+static struct atlas7_pad_mux pw_pwm1_grp0_pad_mux[] = {
MUX(1, 120, 3, N, N, N, N),
};
-static struct atlas7_grp_mux pw_pwm1_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(pw_pwm1_grp_pad_mux),
- .pad_mux_list = pw_pwm1_grp_pad_mux,
+static struct atlas7_grp_mux pw_pwm1_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm1_grp0_pad_mux),
+ .pad_mux_list = pw_pwm1_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux pw_pwm1_grp1_pad_mux[] = {
+ MUX(1, 160, 5, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_pwm1_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm1_grp1_pad_mux),
+ .pad_mux_list = pw_pwm1_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux pw_pwm1_grp2_pad_mux[] = {
+ MUX(1, 131, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_pwm1_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm1_grp2_pad_mux),
+ .pad_mux_list = pw_pwm1_grp2_pad_mux,
};
static struct atlas7_pad_mux pw_pwm2_grp0_pad_mux[] = {
@@ -2606,6 +3486,15 @@ static struct atlas7_grp_mux pw_pwm2_grp1_mux = {
.pad_mux_list = pw_pwm2_grp1_pad_mux,
};
+static struct atlas7_pad_mux pw_pwm2_grp2_pad_mux[] = {
+ MUX(1, 161, 5, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_pwm2_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm2_grp2_pad_mux),
+ .pad_mux_list = pw_pwm2_grp2_pad_mux,
+};
+
static struct atlas7_pad_mux pw_pwm3_grp0_pad_mux[] = {
MUX(1, 122, 3, N, N, N, N),
};
@@ -2642,6 +3531,15 @@ static struct atlas7_grp_mux pw_pwm_cpu_vol_grp1_mux = {
.pad_mux_list = pw_pwm_cpu_vol_grp1_pad_mux,
};
+static struct atlas7_pad_mux pw_pwm_cpu_vol_grp2_pad_mux[] = {
+ MUX(1, 161, 5, N, N, N, N),
+};
+
+static struct atlas7_grp_mux pw_pwm_cpu_vol_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(pw_pwm_cpu_vol_grp2_pad_mux),
+ .pad_mux_list = pw_pwm_cpu_vol_grp2_pad_mux,
+};
+
static struct atlas7_pad_mux pw_backlight_grp0_pad_mux[] = {
MUX(1, 122, 3, N, N, N, N),
};
@@ -2795,35 +3693,54 @@ static struct atlas7_grp_mux sd1_4bit_grp1_mux = {
.pad_mux_list = sd1_4bit_grp1_pad_mux,
};
-static struct atlas7_pad_mux sd2_grp0_pad_mux[] = {
- MUX(1, 124, 2, 0xa08, 7, 0xa88, 7),
+static struct atlas7_pad_mux sd2_basic_grp_pad_mux[] = {
MUX(1, 31, 1, N, N, N, N),
MUX(1, 32, 1, N, N, N, N),
MUX(1, 33, 1, N, N, N, N),
MUX(1, 34, 1, N, N, N, N),
MUX(1, 35, 1, N, N, N, N),
MUX(1, 36, 1, N, N, N, N),
- MUX(1, 123, 2, N, N, N, N),
};
-static struct atlas7_grp_mux sd2_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(sd2_grp0_pad_mux),
- .pad_mux_list = sd2_grp0_pad_mux,
+static struct atlas7_grp_mux sd2_basic_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(sd2_basic_grp_pad_mux),
+ .pad_mux_list = sd2_basic_grp_pad_mux,
};
-static struct atlas7_pad_mux sd2_no_cdb_grp0_pad_mux[] = {
- MUX(1, 31, 1, N, N, N, N),
- MUX(1, 32, 1, N, N, N, N),
- MUX(1, 33, 1, N, N, N, N),
- MUX(1, 34, 1, N, N, N, N),
- MUX(1, 35, 1, N, N, N, N),
- MUX(1, 36, 1, N, N, N, N),
- MUX(1, 123, 2, N, N, N, N),
+static struct atlas7_pad_mux sd2_cdb_grp0_pad_mux[] = {
+ MUX(1, 124, 2, 0xa08, 7, 0xa88, 7),
};
-static struct atlas7_grp_mux sd2_no_cdb_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(sd2_no_cdb_grp0_pad_mux),
- .pad_mux_list = sd2_no_cdb_grp0_pad_mux,
+static struct atlas7_grp_mux sd2_cdb_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(sd2_cdb_grp0_pad_mux),
+ .pad_mux_list = sd2_cdb_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux sd2_cdb_grp1_pad_mux[] = {
+ MUX(1, 161, 6, 0xa08, 7, 0xa88, 7),
+};
+
+static struct atlas7_grp_mux sd2_cdb_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(sd2_cdb_grp1_pad_mux),
+ .pad_mux_list = sd2_cdb_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux sd2_wpb_grp0_pad_mux[] = {
+ MUX(1, 123, 2, 0xa10, 6, 0xa90, 6),
+};
+
+static struct atlas7_grp_mux sd2_wpb_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(sd2_wpb_grp0_pad_mux),
+ .pad_mux_list = sd2_wpb_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux sd2_wpb_grp1_pad_mux[] = {
+ MUX(1, 163, 7, 0xa10, 6, 0xa90, 6),
+};
+
+static struct atlas7_grp_mux sd2_wpb_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(sd2_wpb_grp1_pad_mux),
+ .pad_mux_list = sd2_wpb_grp1_pad_mux,
};
static struct atlas7_pad_mux sd3_grp_pad_mux[] = {
@@ -2975,146 +3892,302 @@ static struct atlas7_grp_mux uart1_grp_mux = {
.pad_mux_list = uart1_grp_pad_mux,
};
-static struct atlas7_pad_mux uart2_grp_pad_mux[] = {
- MUX(0, 11, 2, N, N, N, N),
+static struct atlas7_pad_mux uart2_cts_grp0_pad_mux[] = {
+ MUX(1, 132, 3, 0xa10, 2, 0xa90, 2),
+};
+
+static struct atlas7_grp_mux uart2_cts_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_cts_grp0_pad_mux),
+ .pad_mux_list = uart2_cts_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_cts_grp1_pad_mux[] = {
+ MUX(1, 162, 2, 0xa10, 2, 0xa90, 2),
+};
+
+static struct atlas7_grp_mux uart2_cts_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_cts_grp1_pad_mux),
+ .pad_mux_list = uart2_cts_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_rts_grp0_pad_mux[] = {
+ MUX(1, 131, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart2_rts_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_rts_grp0_pad_mux),
+ .pad_mux_list = uart2_rts_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_rts_grp1_pad_mux[] = {
+ MUX(1, 161, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart2_rts_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_rts_grp1_pad_mux),
+ .pad_mux_list = uart2_rts_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_rxd_grp0_pad_mux[] = {
+ MUX(0, 11, 2, 0xa10, 5, 0xa90, 5),
+};
+
+static struct atlas7_grp_mux uart2_rxd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_rxd_grp0_pad_mux),
+ .pad_mux_list = uart2_rxd_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_rxd_grp1_pad_mux[] = {
+ MUX(1, 160, 2, 0xa10, 5, 0xa90, 5),
+};
+
+static struct atlas7_grp_mux uart2_rxd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_rxd_grp1_pad_mux),
+ .pad_mux_list = uart2_rxd_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_rxd_grp2_pad_mux[] = {
+ MUX(1, 130, 3, 0xa10, 5, 0xa90, 5),
+};
+
+static struct atlas7_grp_mux uart2_rxd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_rxd_grp2_pad_mux),
+ .pad_mux_list = uart2_rxd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_txd_grp0_pad_mux[] = {
MUX(0, 10, 2, N, N, N, N),
};
-static struct atlas7_grp_mux uart2_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(uart2_grp_pad_mux),
- .pad_mux_list = uart2_grp_pad_mux,
+static struct atlas7_grp_mux uart2_txd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_txd_grp0_pad_mux),
+ .pad_mux_list = uart2_txd_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_txd_grp1_pad_mux[] = {
+ MUX(1, 159, 2, N, N, N, N),
};
-static struct atlas7_pad_mux uart3_grp0_pad_mux[] = {
+static struct atlas7_grp_mux uart2_txd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_txd_grp1_pad_mux),
+ .pad_mux_list = uart2_txd_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux uart2_txd_grp2_pad_mux[] = {
+ MUX(1, 129, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart2_txd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart2_txd_grp2_pad_mux),
+ .pad_mux_list = uart2_txd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux uart3_cts_grp0_pad_mux[] = {
MUX(1, 125, 2, 0xa08, 0, 0xa88, 0),
- MUX(1, 126, 2, N, N, N, N),
- MUX(1, 138, 1, 0xa00, 5, 0xa80, 5),
- MUX(1, 137, 1, N, N, N, N),
};
-static struct atlas7_grp_mux uart3_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(uart3_grp0_pad_mux),
- .pad_mux_list = uart3_grp0_pad_mux,
+static struct atlas7_grp_mux uart3_cts_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_cts_grp0_pad_mux),
+ .pad_mux_list = uart3_cts_grp0_pad_mux,
};
-static struct atlas7_pad_mux uart3_grp1_pad_mux[] = {
+static struct atlas7_pad_mux uart3_cts_grp1_pad_mux[] = {
MUX(1, 111, 4, 0xa08, 0, 0xa88, 0),
- MUX(1, 109, 4, N, N, N, N),
- MUX(1, 84, 2, 0xa00, 5, 0xa80, 5),
- MUX(1, 83, 2, N, N, N, N),
};
-static struct atlas7_grp_mux uart3_grp1_mux = {
- .pad_mux_count = ARRAY_SIZE(uart3_grp1_pad_mux),
- .pad_mux_list = uart3_grp1_pad_mux,
+static struct atlas7_grp_mux uart3_cts_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_cts_grp1_pad_mux),
+ .pad_mux_list = uart3_cts_grp1_pad_mux,
};
-static struct atlas7_pad_mux uart3_grp2_pad_mux[] = {
+static struct atlas7_pad_mux uart3_cts_grp2_pad_mux[] = {
MUX(1, 140, 2, 0xa08, 0, 0xa88, 0),
+};
+
+static struct atlas7_grp_mux uart3_cts_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_cts_grp2_pad_mux),
+ .pad_mux_list = uart3_cts_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux uart3_rts_grp0_pad_mux[] = {
+ MUX(1, 126, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart3_rts_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_rts_grp0_pad_mux),
+ .pad_mux_list = uart3_rts_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux uart3_rts_grp1_pad_mux[] = {
+ MUX(1, 109, 4, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart3_rts_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_rts_grp1_pad_mux),
+ .pad_mux_list = uart3_rts_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux uart3_rts_grp2_pad_mux[] = {
MUX(1, 139, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart3_rts_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_rts_grp2_pad_mux),
+ .pad_mux_list = uart3_rts_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux uart3_rxd_grp0_pad_mux[] = {
MUX(1, 138, 1, 0xa00, 5, 0xa80, 5),
- MUX(1, 137, 1, N, N, N, N),
};
-static struct atlas7_grp_mux uart3_grp2_mux = {
- .pad_mux_count = ARRAY_SIZE(uart3_grp2_pad_mux),
- .pad_mux_list = uart3_grp2_pad_mux,
+static struct atlas7_grp_mux uart3_rxd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_rxd_grp0_pad_mux),
+ .pad_mux_list = uart3_rxd_grp0_pad_mux,
};
-static struct atlas7_pad_mux uart3_grp3_pad_mux[] = {
- MUX(1, 139, 2, N, N, N, N),
- MUX(1, 140, 2, 0xa08, 0, 0xa88, 0),
+static struct atlas7_pad_mux uart3_rxd_grp1_pad_mux[] = {
MUX(1, 84, 2, 0xa00, 5, 0xa80, 5),
- MUX(1, 83, 2, N, N, N, N),
};
-static struct atlas7_grp_mux uart3_grp3_mux = {
- .pad_mux_count = ARRAY_SIZE(uart3_grp3_pad_mux),
- .pad_mux_list = uart3_grp3_pad_mux,
+static struct atlas7_grp_mux uart3_rxd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_rxd_grp1_pad_mux),
+ .pad_mux_list = uart3_rxd_grp1_pad_mux,
};
-static struct atlas7_pad_mux uart3_nopause_grp0_pad_mux[] = {
- MUX(1, 138, 1, 0xa00, 5, 0xa80, 5),
+static struct atlas7_pad_mux uart3_rxd_grp2_pad_mux[] = {
+ MUX(1, 162, 3, 0xa00, 5, 0xa80, 5),
+};
+
+static struct atlas7_grp_mux uart3_rxd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_rxd_grp2_pad_mux),
+ .pad_mux_list = uart3_rxd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux uart3_txd_grp0_pad_mux[] = {
MUX(1, 137, 1, N, N, N, N),
};
-static struct atlas7_grp_mux uart3_nopause_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(uart3_nopause_grp0_pad_mux),
- .pad_mux_list = uart3_nopause_grp0_pad_mux,
+static struct atlas7_grp_mux uart3_txd_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_txd_grp0_pad_mux),
+ .pad_mux_list = uart3_txd_grp0_pad_mux,
};
-static struct atlas7_pad_mux uart3_nopause_grp1_pad_mux[] = {
- MUX(1, 84, 2, 0xa00, 5, 0xa80, 5),
+static struct atlas7_pad_mux uart3_txd_grp1_pad_mux[] = {
MUX(1, 83, 2, N, N, N, N),
};
-static struct atlas7_grp_mux uart3_nopause_grp1_mux = {
- .pad_mux_count = ARRAY_SIZE(uart3_nopause_grp1_pad_mux),
- .pad_mux_list = uart3_nopause_grp1_pad_mux,
+static struct atlas7_grp_mux uart3_txd_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_txd_grp1_pad_mux),
+ .pad_mux_list = uart3_txd_grp1_pad_mux,
};
-static struct atlas7_pad_mux uart4_grp0_pad_mux[] = {
- MUX(1, 122, 4, 0xa08, 1, 0xa88, 1),
- MUX(1, 123, 4, N, N, N, N),
+static struct atlas7_pad_mux uart3_txd_grp2_pad_mux[] = {
+ MUX(1, 161, 3, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart3_txd_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart3_txd_grp2_pad_mux),
+ .pad_mux_list = uart3_txd_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux uart4_basic_grp_pad_mux[] = {
MUX(1, 140, 1, N, N, N, N),
MUX(1, 139, 1, N, N, N, N),
};
-static struct atlas7_grp_mux uart4_grp0_mux = {
- .pad_mux_count = ARRAY_SIZE(uart4_grp0_pad_mux),
- .pad_mux_list = uart4_grp0_pad_mux,
+static struct atlas7_grp_mux uart4_basic_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_basic_grp_pad_mux),
+ .pad_mux_list = uart4_basic_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux uart4_cts_grp0_pad_mux[] = {
+ MUX(1, 122, 4, 0xa08, 1, 0xa88, 1),
+};
+
+static struct atlas7_grp_mux uart4_cts_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_cts_grp0_pad_mux),
+ .pad_mux_list = uart4_cts_grp0_pad_mux,
};
-static struct atlas7_pad_mux uart4_grp1_pad_mux[] = {
+static struct atlas7_pad_mux uart4_cts_grp1_pad_mux[] = {
MUX(1, 100, 4, 0xa08, 1, 0xa88, 1),
- MUX(1, 99, 4, N, N, N, N),
- MUX(1, 140, 1, N, N, N, N),
- MUX(1, 139, 1, N, N, N, N),
};
-static struct atlas7_grp_mux uart4_grp1_mux = {
- .pad_mux_count = ARRAY_SIZE(uart4_grp1_pad_mux),
- .pad_mux_list = uart4_grp1_pad_mux,
+static struct atlas7_grp_mux uart4_cts_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_cts_grp1_pad_mux),
+ .pad_mux_list = uart4_cts_grp1_pad_mux,
};
-static struct atlas7_pad_mux uart4_grp2_pad_mux[] = {
+static struct atlas7_pad_mux uart4_cts_grp2_pad_mux[] = {
MUX(1, 117, 2, 0xa08, 1, 0xa88, 1),
- MUX(1, 116, 2, N, N, N, N),
- MUX(1, 140, 1, N, N, N, N),
- MUX(1, 139, 1, N, N, N, N),
};
-static struct atlas7_grp_mux uart4_grp2_mux = {
- .pad_mux_count = ARRAY_SIZE(uart4_grp2_pad_mux),
- .pad_mux_list = uart4_grp2_pad_mux,
+static struct atlas7_grp_mux uart4_cts_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_cts_grp2_pad_mux),
+ .pad_mux_list = uart4_cts_grp2_pad_mux,
};
-static struct atlas7_pad_mux uart4_nopause_grp_pad_mux[] = {
- MUX(1, 140, 1, N, N, N, N),
- MUX(1, 139, 1, N, N, N, N),
+static struct atlas7_pad_mux uart4_rts_grp0_pad_mux[] = {
+ MUX(1, 123, 4, N, N, N, N),
};
-static struct atlas7_grp_mux uart4_nopause_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(uart4_nopause_grp_pad_mux),
- .pad_mux_list = uart4_nopause_grp_pad_mux,
+static struct atlas7_grp_mux uart4_rts_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_rts_grp0_pad_mux),
+ .pad_mux_list = uart4_rts_grp0_pad_mux,
};
-static struct atlas7_pad_mux usb0_drvvbus_grp_pad_mux[] = {
+static struct atlas7_pad_mux uart4_rts_grp1_pad_mux[] = {
+ MUX(1, 99, 4, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart4_rts_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_rts_grp1_pad_mux),
+ .pad_mux_list = uart4_rts_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux uart4_rts_grp2_pad_mux[] = {
+ MUX(1, 116, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux uart4_rts_grp2_mux = {
+ .pad_mux_count = ARRAY_SIZE(uart4_rts_grp2_pad_mux),
+ .pad_mux_list = uart4_rts_grp2_pad_mux,
+};
+
+static struct atlas7_pad_mux usb0_drvvbus_grp0_pad_mux[] = {
MUX(1, 51, 2, N, N, N, N),
};
-static struct atlas7_grp_mux usb0_drvvbus_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(usb0_drvvbus_grp_pad_mux),
- .pad_mux_list = usb0_drvvbus_grp_pad_mux,
+static struct atlas7_grp_mux usb0_drvvbus_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(usb0_drvvbus_grp0_pad_mux),
+ .pad_mux_list = usb0_drvvbus_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux usb0_drvvbus_grp1_pad_mux[] = {
+ MUX(1, 162, 7, N, N, N, N),
};
-static struct atlas7_pad_mux usb1_drvvbus_grp_pad_mux[] = {
+static struct atlas7_grp_mux usb0_drvvbus_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(usb0_drvvbus_grp1_pad_mux),
+ .pad_mux_list = usb0_drvvbus_grp1_pad_mux,
+};
+
+static struct atlas7_pad_mux usb1_drvvbus_grp0_pad_mux[] = {
MUX(1, 134, 2, N, N, N, N),
};
-static struct atlas7_grp_mux usb1_drvvbus_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(usb1_drvvbus_grp_pad_mux),
- .pad_mux_list = usb1_drvvbus_grp_pad_mux,
+static struct atlas7_grp_mux usb1_drvvbus_grp0_mux = {
+ .pad_mux_count = ARRAY_SIZE(usb1_drvvbus_grp0_pad_mux),
+ .pad_mux_list = usb1_drvvbus_grp0_pad_mux,
+};
+
+static struct atlas7_pad_mux usb1_drvvbus_grp1_pad_mux[] = {
+ MUX(1, 163, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux usb1_drvvbus_grp1_mux = {
+ .pad_mux_count = ARRAY_SIZE(usb1_drvvbus_grp1_pad_mux),
+ .pad_mux_list = usb1_drvvbus_grp1_pad_mux,
};
static struct atlas7_pad_mux visbus_dout_grp_pad_mux[] = {
@@ -3252,11 +4325,20 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("sdio_i2s_gpio", sdio_i2s_gpio_grp, &sdio_i2s_gpio_grp_mux),
FUNCTION("sp_rgmii_gpio", sp_rgmii_gpio_grp, &sp_rgmii_gpio_grp_mux),
FUNCTION("lvds_gpio", lvds_gpio_grp, &lvds_gpio_grp_mux),
- FUNCTION("uart_nand_gpio",
- uart_nand_gpio_grp,
- &uart_nand_gpio_grp_mux),
+ FUNCTION("jtag_uart_nand_gpio",
+ jtag_uart_nand_gpio_grp,
+ &jtag_uart_nand_gpio_grp_mux),
FUNCTION("rtc_gpio", rtc_gpio_grp, &rtc_gpio_grp_mux),
FUNCTION("audio_ac97", audio_ac97_grp, &audio_ac97_grp_mux),
+ FUNCTION("audio_digmic_m0",
+ audio_digmic_grp0,
+ &audio_digmic_grp0_mux),
+ FUNCTION("audio_digmic_m1",
+ audio_digmic_grp1,
+ &audio_digmic_grp1_mux),
+ FUNCTION("audio_digmic_m2",
+ audio_digmic_grp2,
+ &audio_digmic_grp2_mux),
FUNCTION("audio_func_dbg",
audio_func_dbg_grp,
&audio_func_dbg_grp_mux),
@@ -3265,16 +4347,119 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("audio_i2s_extclk",
audio_i2s_extclk_grp,
&audio_i2s_extclk_grp_mux),
- FUNCTION("audio_uart0", audio_uart0_grp, &audio_uart0_grp_mux),
- FUNCTION("audio_uart1", audio_uart1_grp, &audio_uart1_grp_mux),
- FUNCTION("audio_uart2_m0", audio_uart2_grp0, &audio_uart2_grp0_mux),
- FUNCTION("audio_uart2_m1", audio_uart2_grp1, &audio_uart2_grp1_mux),
- FUNCTION("c_can_trnsvr", c_can_trnsvr_grp, &c_can_trnsvr_grp_mux),
- FUNCTION("c0_can_m0", c0_can_grp0, &c0_can_grp0_mux),
- FUNCTION("c0_can_m1", c0_can_grp1, &c0_can_grp1_mux),
- FUNCTION("c1_can_m0", c1_can_grp0, &c1_can_grp0_mux),
- FUNCTION("c1_can_m1", c1_can_grp1, &c1_can_grp1_mux),
- FUNCTION("c1_can_m2", c1_can_grp2, &c1_can_grp2_mux),
+ FUNCTION("audio_spdif_out_m0",
+ audio_spdif_out_grp0,
+ &audio_spdif_out_grp0_mux),
+ FUNCTION("audio_spdif_out_m1",
+ audio_spdif_out_grp1,
+ &audio_spdif_out_grp1_mux),
+ FUNCTION("audio_spdif_out_m2",
+ audio_spdif_out_grp2,
+ &audio_spdif_out_grp2_mux),
+ FUNCTION("audio_uart0_basic",
+ audio_uart0_basic_grp,
+ &audio_uart0_basic_grp_mux),
+ FUNCTION("audio_uart0_urfs_m0",
+ audio_uart0_urfs_grp0,
+ &audio_uart0_urfs_grp0_mux),
+ FUNCTION("audio_uart0_urfs_m1",
+ audio_uart0_urfs_grp1,
+ &audio_uart0_urfs_grp1_mux),
+ FUNCTION("audio_uart0_urfs_m2",
+ audio_uart0_urfs_grp2,
+ &audio_uart0_urfs_grp2_mux),
+ FUNCTION("audio_uart0_urfs_m3",
+ audio_uart0_urfs_grp3,
+ &audio_uart0_urfs_grp3_mux),
+ FUNCTION("audio_uart1_basic",
+ audio_uart1_basic_grp,
+ &audio_uart1_basic_grp_mux),
+ FUNCTION("audio_uart1_urfs_m0",
+ audio_uart1_urfs_grp0,
+ &audio_uart1_urfs_grp0_mux),
+ FUNCTION("audio_uart1_urfs_m1",
+ audio_uart1_urfs_grp1,
+ &audio_uart1_urfs_grp1_mux),
+ FUNCTION("audio_uart1_urfs_m2",
+ audio_uart1_urfs_grp2,
+ &audio_uart1_urfs_grp2_mux),
+ FUNCTION("audio_uart2_urfs_m0",
+ audio_uart2_urfs_grp0,
+ &audio_uart2_urfs_grp0_mux),
+ FUNCTION("audio_uart2_urfs_m1",
+ audio_uart2_urfs_grp1,
+ &audio_uart2_urfs_grp1_mux),
+ FUNCTION("audio_uart2_urfs_m2",
+ audio_uart2_urfs_grp2,
+ &audio_uart2_urfs_grp2_mux),
+ FUNCTION("audio_uart2_urxd_m0",
+ audio_uart2_urxd_grp0,
+ &audio_uart2_urxd_grp0_mux),
+ FUNCTION("audio_uart2_urxd_m1",
+ audio_uart2_urxd_grp1,
+ &audio_uart2_urxd_grp1_mux),
+ FUNCTION("audio_uart2_urxd_m2",
+ audio_uart2_urxd_grp2,
+ &audio_uart2_urxd_grp2_mux),
+ FUNCTION("audio_uart2_usclk_m0",
+ audio_uart2_usclk_grp0,
+ &audio_uart2_usclk_grp0_mux),
+ FUNCTION("audio_uart2_usclk_m1",
+ audio_uart2_usclk_grp1,
+ &audio_uart2_usclk_grp1_mux),
+ FUNCTION("audio_uart2_usclk_m2",
+ audio_uart2_usclk_grp2,
+ &audio_uart2_usclk_grp2_mux),
+ FUNCTION("audio_uart2_utfs_m0",
+ audio_uart2_utfs_grp0,
+ &audio_uart2_utfs_grp0_mux),
+ FUNCTION("audio_uart2_utfs_m1",
+ audio_uart2_utfs_grp1,
+ &audio_uart2_utfs_grp1_mux),
+ FUNCTION("audio_uart2_utfs_m2",
+ audio_uart2_utfs_grp2,
+ &audio_uart2_utfs_grp2_mux),
+ FUNCTION("audio_uart2_utxd_m0",
+ audio_uart2_utxd_grp0,
+ &audio_uart2_utxd_grp0_mux),
+ FUNCTION("audio_uart2_utxd_m1",
+ audio_uart2_utxd_grp1,
+ &audio_uart2_utxd_grp1_mux),
+ FUNCTION("audio_uart2_utxd_m2",
+ audio_uart2_utxd_grp2,
+ &audio_uart2_utxd_grp2_mux),
+ FUNCTION("c_can_trnsvr_en_m0",
+ c_can_trnsvr_en_grp0,
+ &c_can_trnsvr_en_grp0_mux),
+ FUNCTION("c_can_trnsvr_en_m1",
+ c_can_trnsvr_en_grp1,
+ &c_can_trnsvr_en_grp1_mux),
+ FUNCTION("c_can_trnsvr_intr",
+ c_can_trnsvr_intr_grp,
+ &c_can_trnsvr_intr_grp_mux),
+ FUNCTION("c_can_trnsvr_stb_n",
+ c_can_trnsvr_stb_n_grp,
+ &c_can_trnsvr_stb_n_grp_mux),
+ FUNCTION("c0_can_rxd_trnsv0",
+ c0_can_rxd_trnsv0_grp,
+ &c0_can_rxd_trnsv0_grp_mux),
+ FUNCTION("c0_can_rxd_trnsv1",
+ c0_can_rxd_trnsv1_grp,
+ &c0_can_rxd_trnsv1_grp_mux),
+ FUNCTION("c0_can_txd_trnsv0",
+ c0_can_txd_trnsv0_grp,
+ &c0_can_txd_trnsv0_grp_mux),
+ FUNCTION("c0_can_txd_trnsv1",
+ c0_can_txd_trnsv1_grp,
+ &c0_can_txd_trnsv1_grp_mux),
+ FUNCTION("c1_can_rxd_m0", c1_can_rxd_grp0, &c1_can_rxd_grp0_mux),
+ FUNCTION("c1_can_rxd_m1", c1_can_rxd_grp1, &c1_can_rxd_grp1_mux),
+ FUNCTION("c1_can_rxd_m2", c1_can_rxd_grp2, &c1_can_rxd_grp2_mux),
+ FUNCTION("c1_can_rxd_m3", c1_can_rxd_grp3, &c1_can_rxd_grp3_mux),
+ FUNCTION("c1_can_txd_m0", c1_can_txd_grp0, &c1_can_txd_grp0_mux),
+ FUNCTION("c1_can_txd_m1", c1_can_txd_grp1, &c1_can_txd_grp1_mux),
+ FUNCTION("c1_can_txd_m2", c1_can_txd_grp2, &c1_can_txd_grp2_mux),
+ FUNCTION("c1_can_txd_m3", c1_can_txd_grp3, &c1_can_txd_grp3_mux),
FUNCTION("ca_audio_lpc", ca_audio_lpc_grp, &ca_audio_lpc_grp_mux),
FUNCTION("ca_bt_lpc", ca_bt_lpc_grp, &ca_bt_lpc_grp_mux),
FUNCTION("ca_coex", ca_coex_grp, &ca_coex_grp_mux),
@@ -3377,7 +4562,35 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
&gn_trg_shutdown_grp3_mux),
FUNCTION("i2c0", i2c0_grp, &i2c0_grp_mux),
FUNCTION("i2c1", i2c1_grp, &i2c1_grp_mux),
- FUNCTION("jtag_m0", jtag_grp0, &jtag_grp0_mux),
+ FUNCTION("i2s0", i2s0_grp, &i2s0_grp_mux),
+ FUNCTION("i2s1_basic", i2s1_basic_grp, &i2s1_basic_grp_mux),
+ FUNCTION("i2s1_rxd0_m0", i2s1_rxd0_grp0, &i2s1_rxd0_grp0_mux),
+ FUNCTION("i2s1_rxd0_m1", i2s1_rxd0_grp1, &i2s1_rxd0_grp1_mux),
+ FUNCTION("i2s1_rxd0_m2", i2s1_rxd0_grp2, &i2s1_rxd0_grp2_mux),
+ FUNCTION("i2s1_rxd0_m3", i2s1_rxd0_grp3, &i2s1_rxd0_grp3_mux),
+ FUNCTION("i2s1_rxd0_m4", i2s1_rxd0_grp4, &i2s1_rxd0_grp4_mux),
+ FUNCTION("i2s1_rxd1_m0", i2s1_rxd1_grp0, &i2s1_rxd1_grp0_mux),
+ FUNCTION("i2s1_rxd1_m1", i2s1_rxd1_grp1, &i2s1_rxd1_grp1_mux),
+ FUNCTION("i2s1_rxd1_m2", i2s1_rxd1_grp2, &i2s1_rxd1_grp2_mux),
+ FUNCTION("i2s1_rxd1_m3", i2s1_rxd1_grp3, &i2s1_rxd1_grp3_mux),
+ FUNCTION("i2s1_rxd1_m4", i2s1_rxd1_grp4, &i2s1_rxd1_grp4_mux),
+ FUNCTION("jtag_jt_dbg_nsrst",
+ jtag_jt_dbg_nsrst_grp,
+ &jtag_jt_dbg_nsrst_grp_mux),
+ FUNCTION("jtag_ntrst_m0", jtag_ntrst_grp0, &jtag_ntrst_grp0_mux),
+ FUNCTION("jtag_ntrst_m1", jtag_ntrst_grp1, &jtag_ntrst_grp1_mux),
+ FUNCTION("jtag_swdiotms_m0",
+ jtag_swdiotms_grp0,
+ &jtag_swdiotms_grp0_mux),
+ FUNCTION("jtag_swdiotms_m1",
+ jtag_swdiotms_grp1,
+ &jtag_swdiotms_grp1_mux),
+ FUNCTION("jtag_tck_m0", jtag_tck_grp0, &jtag_tck_grp0_mux),
+ FUNCTION("jtag_tck_m1", jtag_tck_grp1, &jtag_tck_grp1_mux),
+ FUNCTION("jtag_tdi_m0", jtag_tdi_grp0, &jtag_tdi_grp0_mux),
+ FUNCTION("jtag_tdi_m1", jtag_tdi_grp1, &jtag_tdi_grp1_mux),
+ FUNCTION("jtag_tdo_m0", jtag_tdo_grp0, &jtag_tdo_grp0_mux),
+ FUNCTION("jtag_tdo_m1", jtag_tdo_grp1, &jtag_tdo_grp1_mux),
FUNCTION("ks_kas_spi_m0", ks_kas_spi_grp0, &ks_kas_spi_grp0_mux),
FUNCTION("ld_ldd", ld_ldd_grp, &ld_ldd_grp_mux),
FUNCTION("ld_ldd_16bit", ld_ldd_16bit_grp, &ld_ldd_16bit_grp_mux),
@@ -3414,18 +4627,27 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("pw_cko0_m0", pw_cko0_grp0, &pw_cko0_grp0_mux),
FUNCTION("pw_cko0_m1", pw_cko0_grp1, &pw_cko0_grp1_mux),
FUNCTION("pw_cko0_m2", pw_cko0_grp2, &pw_cko0_grp2_mux),
+ FUNCTION("pw_cko0_m3", pw_cko0_grp3, &pw_cko0_grp3_mux),
FUNCTION("pw_cko1_m0", pw_cko1_grp0, &pw_cko1_grp0_mux),
FUNCTION("pw_cko1_m1", pw_cko1_grp1, &pw_cko1_grp1_mux),
+ FUNCTION("pw_cko1_m2", pw_cko1_grp2, &pw_cko1_grp2_mux),
FUNCTION("pw_i2s01_clk_m0",
pw_i2s01_clk_grp0,
&pw_i2s01_clk_grp0_mux),
FUNCTION("pw_i2s01_clk_m1",
pw_i2s01_clk_grp1,
&pw_i2s01_clk_grp1_mux),
- FUNCTION("pw_pwm0", pw_pwm0_grp, &pw_pwm0_grp_mux),
- FUNCTION("pw_pwm1", pw_pwm1_grp, &pw_pwm1_grp_mux),
+ FUNCTION("pw_i2s01_clk_m2",
+ pw_i2s01_clk_grp2,
+ &pw_i2s01_clk_grp2_mux),
+ FUNCTION("pw_pwm0_m0", pw_pwm0_grp0, &pw_pwm0_grp0_mux),
+ FUNCTION("pw_pwm0_m1", pw_pwm0_grp1, &pw_pwm0_grp1_mux),
+ FUNCTION("pw_pwm1_m0", pw_pwm1_grp0, &pw_pwm1_grp0_mux),
+ FUNCTION("pw_pwm1_m1", pw_pwm1_grp1, &pw_pwm1_grp1_mux),
+ FUNCTION("pw_pwm1_m2", pw_pwm1_grp2, &pw_pwm1_grp2_mux),
FUNCTION("pw_pwm2_m0", pw_pwm2_grp0, &pw_pwm2_grp0_mux),
FUNCTION("pw_pwm2_m1", pw_pwm2_grp1, &pw_pwm2_grp1_mux),
+ FUNCTION("pw_pwm2_m2", pw_pwm2_grp2, &pw_pwm2_grp2_mux),
FUNCTION("pw_pwm3_m0", pw_pwm3_grp0, &pw_pwm3_grp0_mux),
FUNCTION("pw_pwm3_m1", pw_pwm3_grp1, &pw_pwm3_grp1_mux),
FUNCTION("pw_pwm_cpu_vol_m0",
@@ -3434,6 +4656,9 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("pw_pwm_cpu_vol_m1",
pw_pwm_cpu_vol_grp1,
&pw_pwm_cpu_vol_grp1_mux),
+ FUNCTION("pw_pwm_cpu_vol_m2",
+ pw_pwm_cpu_vol_grp2,
+ &pw_pwm_cpu_vol_grp2_mux),
FUNCTION("pw_backlight_m0",
pw_backlight_grp0,
&pw_backlight_grp0_mux),
@@ -3456,8 +4681,11 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("sd1", sd1_grp, &sd1_grp_mux),
FUNCTION("sd1_4bit_m0", sd1_4bit_grp0, &sd1_4bit_grp0_mux),
FUNCTION("sd1_4bit_m1", sd1_4bit_grp1, &sd1_4bit_grp1_mux),
- FUNCTION("sd2_m0", sd2_grp0, &sd2_grp0_mux),
- FUNCTION("sd2_no_cdb_m0", sd2_no_cdb_grp0, &sd2_no_cdb_grp0_mux),
+ FUNCTION("sd2_basic", sd2_basic_grp, &sd2_basic_grp_mux),
+ FUNCTION("sd2_cdb_m0", sd2_cdb_grp0, &sd2_cdb_grp0_mux),
+ FUNCTION("sd2_cdb_m1", sd2_cdb_grp1, &sd2_cdb_grp1_mux),
+ FUNCTION("sd2_wpb_m0", sd2_wpb_grp0, &sd2_wpb_grp0_mux),
+ FUNCTION("sd2_wpb_m1", sd2_wpb_grp1, &sd2_wpb_grp1_mux),
FUNCTION("sd3", sd3_grp, &sd3_grp_mux),
FUNCTION("sd5", sd5_grp, &sd5_grp_mux),
FUNCTION("sd6_m0", sd6_grp0, &sd6_grp0_mux),
@@ -3471,23 +4699,47 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("uart0", uart0_grp, &uart0_grp_mux),
FUNCTION("uart0_nopause", uart0_nopause_grp, &uart0_nopause_grp_mux),
FUNCTION("uart1", uart1_grp, &uart1_grp_mux),
- FUNCTION("uart2", uart2_grp, &uart2_grp_mux),
- FUNCTION("uart3_m0", uart3_grp0, &uart3_grp0_mux),
- FUNCTION("uart3_m1", uart3_grp1, &uart3_grp1_mux),
- FUNCTION("uart3_m2", uart3_grp2, &uart3_grp2_mux),
- FUNCTION("uart3_m3", uart3_grp3, &uart3_grp3_mux),
- FUNCTION("uart3_nopause_m0",
- uart3_nopause_grp0,
- &uart3_nopause_grp0_mux),
- FUNCTION("uart3_nopause_m1",
- uart3_nopause_grp1,
- &uart3_nopause_grp1_mux),
- FUNCTION("uart4_m0", uart4_grp0, &uart4_grp0_mux),
- FUNCTION("uart4_m1", uart4_grp1, &uart4_grp1_mux),
- FUNCTION("uart4_m2", uart4_grp2, &uart4_grp2_mux),
- FUNCTION("uart4_nopause", uart4_nopause_grp, &uart4_nopause_grp_mux),
- FUNCTION("usb0_drvvbus", usb0_drvvbus_grp, &usb0_drvvbus_grp_mux),
- FUNCTION("usb1_drvvbus", usb1_drvvbus_grp, &usb1_drvvbus_grp_mux),
+ FUNCTION("uart2_cts_m0", uart2_cts_grp0, &uart2_cts_grp0_mux),
+ FUNCTION("uart2_cts_m1", uart2_cts_grp1, &uart2_cts_grp1_mux),
+ FUNCTION("uart2_rts_m0", uart2_rts_grp0, &uart2_rts_grp0_mux),
+ FUNCTION("uart2_rts_m1", uart2_rts_grp1, &uart2_rts_grp1_mux),
+ FUNCTION("uart2_rxd_m0", uart2_rxd_grp0, &uart2_rxd_grp0_mux),
+ FUNCTION("uart2_rxd_m1", uart2_rxd_grp1, &uart2_rxd_grp1_mux),
+ FUNCTION("uart2_rxd_m2", uart2_rxd_grp2, &uart2_rxd_grp2_mux),
+ FUNCTION("uart2_txd_m0", uart2_txd_grp0, &uart2_txd_grp0_mux),
+ FUNCTION("uart2_txd_m1", uart2_txd_grp1, &uart2_txd_grp1_mux),
+ FUNCTION("uart2_txd_m2", uart2_txd_grp2, &uart2_txd_grp2_mux),
+ FUNCTION("uart3_cts_m0", uart3_cts_grp0, &uart3_cts_grp0_mux),
+ FUNCTION("uart3_cts_m1", uart3_cts_grp1, &uart3_cts_grp1_mux),
+ FUNCTION("uart3_cts_m2", uart3_cts_grp2, &uart3_cts_grp2_mux),
+ FUNCTION("uart3_rts_m0", uart3_rts_grp0, &uart3_rts_grp0_mux),
+ FUNCTION("uart3_rts_m1", uart3_rts_grp1, &uart3_rts_grp1_mux),
+ FUNCTION("uart3_rts_m2", uart3_rts_grp2, &uart3_rts_grp2_mux),
+ FUNCTION("uart3_rxd_m0", uart3_rxd_grp0, &uart3_rxd_grp0_mux),
+ FUNCTION("uart3_rxd_m1", uart3_rxd_grp1, &uart3_rxd_grp1_mux),
+ FUNCTION("uart3_rxd_m2", uart3_rxd_grp2, &uart3_rxd_grp2_mux),
+ FUNCTION("uart3_txd_m0", uart3_txd_grp0, &uart3_txd_grp0_mux),
+ FUNCTION("uart3_txd_m1", uart3_txd_grp1, &uart3_txd_grp1_mux),
+ FUNCTION("uart3_txd_m2", uart3_txd_grp2, &uart3_txd_grp2_mux),
+ FUNCTION("uart4_basic", uart4_basic_grp, &uart4_basic_grp_mux),
+ FUNCTION("uart4_cts_m0", uart4_cts_grp0, &uart4_cts_grp0_mux),
+ FUNCTION("uart4_cts_m1", uart4_cts_grp1, &uart4_cts_grp1_mux),
+ FUNCTION("uart4_cts_m2", uart4_cts_grp2, &uart4_cts_grp2_mux),
+ FUNCTION("uart4_rts_m0", uart4_rts_grp0, &uart4_rts_grp0_mux),
+ FUNCTION("uart4_rts_m1", uart4_rts_grp1, &uart4_rts_grp1_mux),
+ FUNCTION("uart4_rts_m2", uart4_rts_grp2, &uart4_rts_grp2_mux),
+ FUNCTION("usb0_drvvbus_m0",
+ usb0_drvvbus_grp0,
+ &usb0_drvvbus_grp0_mux),
+ FUNCTION("usb0_drvvbus_m1",
+ usb0_drvvbus_grp1,
+ &usb0_drvvbus_grp1_mux),
+ FUNCTION("usb1_drvvbus_m0",
+ usb1_drvvbus_grp0,
+ &usb1_drvvbus_grp0_mux),
+ FUNCTION("usb1_drvvbus_m1",
+ usb1_drvvbus_grp1,
+ &usb1_drvvbus_grp1_mux),
FUNCTION("visbus_dout", visbus_dout_grp, &visbus_dout_grp_mux),
FUNCTION("vi_vip1", vi_vip1_grp, &vi_vip1_grp_mux),
FUNCTION("vi_vip1_ext", vi_vip1_ext_grp, &vi_vip1_ext_grp_mux),
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index ae27872ff3a6..e68fd951129a 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -42,6 +42,10 @@ config PINCTRL_SUN8I_A33
def_bool MACH_SUN8I
select PINCTRL_SUNXI_COMMON
+config PINCTRL_SUN8I_A83T
+ def_bool MACH_SUN8I
+ select PINCTRL_SUNXI_COMMON
+
config PINCTRL_SUN8I_A23_R
def_bool MACH_SUN8I
depends on RESET_CONTROLLER
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 227a1213947c..e08029034510 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -12,4 +12,5 @@ obj-$(CONFIG_PINCTRL_SUN7I_A20) += pinctrl-sun7i-a20.o
obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o
obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o
obj-$(CONFIG_PINCTRL_SUN8I_A33) += pinctrl-sun8i-a33.o
+obj-$(CONFIG_PINCTRL_SUN8I_A83T) += pinctrl-sun8i-a83t.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
index 63676617bc59..f9a3f8f446f7 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
@@ -653,7 +653,7 @@ static const struct sunxi_desc_pin sun5i_a10s_pins[] = {
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CS1 */
- SUNXI_FUNCTION(0x3, "uart3"), /* PWM1 */
+ SUNXI_FUNCTION(0x3, "pwm"), /* PWM1 */
SUNXI_FUNCTION(0x5, "uart2"), /* CTS */
SUNXI_FUNCTION_IRQ(0x6, 13)), /* EINT13 */
};
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
index 9596b0a3df6b..d4bc4f0e8be0 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
@@ -47,45 +47,57 @@ static const struct sunxi_desc_pin sun6i_a31_r_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 0, 0), /* PL_EINT0 */
SUNXI_FUNCTION(0x3, "s_jtag")), /* MS */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 0, 1), /* PL_EINT1 */
SUNXI_FUNCTION(0x3, "s_jtag")), /* CK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 0, 2), /* PL_EINT2 */
SUNXI_FUNCTION(0x3, "s_jtag")), /* DO */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 0, 3), /* PL_EINT3 */
SUNXI_FUNCTION(0x3, "s_jtag")), /* DI */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 0)), /* PM_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 1)), /* PM_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 2), /* PM_EINT2 */
SUNXI_FUNCTION(0x3, "1wire")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 3)), /* PM_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 4)), /* PM_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 5)), /* PM_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 6)), /* PM_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x2, 1, 7), /* PM_EINT7 */
SUNXI_FUNCTION(0x3, "rtc")), /* CLKO */
};
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
new file mode 100644
index 000000000000..90b973e15982
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
@@ -0,0 +1,603 @@
+/*
+ * Allwinner a83t SoCs pinctrl driver.
+ *
+ * Copyright (C) 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
+ *
+ * Based on pinctrl-sun8i-a23.c, which is:
+ * Copyright (C) 2014 Chen-Yu Tsai <wens@csie.org>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_a83t_pins[] = {
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PB_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CK0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PB_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DO0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PB_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DI0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PB_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* LRCK */
+ SUNXI_FUNCTION(0x3, "tdm"), /* LRCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PB_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* BCLK */
+ SUNXI_FUNCTION(0x3, "tdm"), /* BCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PB_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "tdm"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PB_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */
+ SUNXI_FUNCTION(0x3, "tdm"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PB_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "tdm"), /* MCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PB_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PB_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PB_EINT10 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* WE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RE */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQS */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand")), /* CE2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand")), /* CE3 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D2 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D3 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXD2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D4 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D5 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D6 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D7 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXDV */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D10 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII RXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D11 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII TXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D12 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII TXD2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D13 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII TXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D14 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII / MII TXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D15 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* RGMII-NULL / MII-CRS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D18 */
+ SUNXI_FUNCTION(0x3, "lvds0"), /* VP0 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* GTXCK / ETXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D19 */
+ SUNXI_FUNCTION(0x3, "lvds0"), /* VN0 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* GTXCTL / ETXEL */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D20 */
+ SUNXI_FUNCTION(0x3, "lvds0"), /* VP1 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* GNULL / ETXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D21 */
+ SUNXI_FUNCTION(0x3, "lvds0"), /* VN1 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* GCLKIN / ECOL */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D22 */
+ SUNXI_FUNCTION(0x3, "lvds0"), /* VP2 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* GMDC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 23),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D23 */
+ SUNXI_FUNCTION(0x3, "lvds0"), /* VN2 */
+ SUNXI_FUNCTION(0x4, "gmac")), /* GMDIO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 24),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VPC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 25),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* DE */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 26),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 27),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 28),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm")), /* PWM */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 29),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* PCLK */
+ SUNXI_FUNCTION(0x4, "ccir")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* MCLK */
+ SUNXI_FUNCTION(0x4, "ccir")), /* DE */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */
+ SUNXI_FUNCTION(0x4, "ccir")), /* HSYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */
+ SUNXI_FUNCTION(0x4, "ccir")), /* VSYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D2 */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D3 */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D4 */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D5 */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D6 */
+ SUNXI_FUNCTION(0x3, "uart4"), /* TX */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D7 */
+ SUNXI_FUNCTION(0x3, "uart4"), /* RX */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D8 */
+ SUNXI_FUNCTION(0x3, "uart4"), /* RTS */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D9 */
+ SUNXI_FUNCTION(0x3, "uart4"), /* CTS */
+ SUNXI_FUNCTION(0x4, "ccir")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SCK */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SDA */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "owa")), /* DOUT */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* MS1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DI1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DO1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* CK1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PG_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PG_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PG_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PG_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PG_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PG_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* TX */
+ SUNXI_FUNCTION(0x3, "spi1"), /* CS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PG_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RX */
+ SUNXI_FUNCTION(0x3, "spi1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PG_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
+ SUNXI_FUNCTION(0x3, "spi1"), /* MOSI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)), /* PG_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
+ SUNXI_FUNCTION(0x3, "spi1"), /* MISO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)), /* PG_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* BCLK */
+ SUNXI_FUNCTION(0x3, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), /* PG_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* LRCK */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), /* PG_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)), /* PG_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */
+ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)), /* PG_EINT13 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)), /* PH_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)), /* PH_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)), /* PH_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)), /* PH_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c2"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)), /* PH_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c2"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)), /* PH_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "hdmi"), /* HSCL */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)), /* PH_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "hdmi"), /* HSDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)), /* PH_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "hdmi"), /* HCEC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)), /* PH_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)), /* PH_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)), /* PH_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)), /* PH_EINT11 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_a83t_pinctrl_data = {
+ .pins = sun8i_a83t_pins,
+ .npins = ARRAY_SIZE(sun8i_a83t_pins),
+ .irq_banks = 3,
+};
+
+static int sun8i_a83t_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun8i_a83t_pinctrl_data);
+}
+
+static const struct of_device_id sun8i_a83t_pinctrl_match[] = {
+ { .compatible = "allwinner,sun8i-a83t-pinctrl", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_a83t_pinctrl_match);
+
+static struct platform_driver sun8i_a83t_pinctrl_driver = {
+ .probe = sun8i_a83t_pinctrl_probe,
+ .driver = {
+ .name = "sun8i-a83t-pinctrl",
+ .of_match_table = sun8i_a83t_pinctrl_match,
+ },
+};
+module_platform_driver(sun8i_a83t_pinctrl_driver);
+
+MODULE_AUTHOR("Vishnu Patekar <vishnupatekar0510@gmail.com>");
+MODULE_DESCRIPTION("Allwinner a83t pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 38e0c7bdd2ac..dead97daca35 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -446,16 +446,6 @@ static const struct pinmux_ops sunxi_pmx_ops = {
.gpio_set_direction = sunxi_pmx_gpio_set_direction,
};
-static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@@ -716,6 +706,7 @@ static int sunxi_pinctrl_irq_of_xlate(struct irq_domain *d,
unsigned long *out_hwirq,
unsigned int *out_type)
{
+ struct sunxi_pinctrl *pctl = d->host_data;
struct sunxi_desc_function *desc;
int pin, base;
@@ -723,10 +714,9 @@ static int sunxi_pinctrl_irq_of_xlate(struct irq_domain *d,
return -EINVAL;
base = PINS_PER_BANK * intspec[0];
- pin = base + intspec[1];
+ pin = pctl->desc->pin_base + base + intspec[1];
- desc = sunxi_pinctrl_desc_find_function_by_pin(d->host_data,
- pin, "irq");
+ desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pin, "irq");
if (!desc)
return -EINVAL;
@@ -956,8 +946,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
pctl->chip->owner = THIS_MODULE;
- pctl->chip->request = sunxi_pinctrl_gpio_request,
- pctl->chip->free = sunxi_pinctrl_gpio_free,
+ pctl->chip->request = gpiochip_generic_request,
+ pctl->chip->free = gpiochip_generic_free,
pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input,
pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output,
pctl->chip->get = sunxi_pinctrl_gpio_get,
@@ -1029,7 +1019,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
handle_edge_irq);
irq_set_chip_data(irqno, pctl);
- };
+ }
for (i = 0; i < pctl->desc->irq_banks; i++) {
/* Mask and clear all IRQs before registering a handler */
diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
index eab23ef9ddbf..ad907072e09f 100644
--- a/drivers/pinctrl/uniphier/Kconfig
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -1,32 +1,32 @@
if ARCH_UNIPHIER
-config PINCTRL_UNIPHIER_CORE
+config PINCTRL_UNIPHIER
bool
select PINMUX
select GENERIC_PINCONF
config PINCTRL_UNIPHIER_PH1_LD4
tristate "UniPhier PH1-LD4 SoC pinctrl driver"
- select PINCTRL_UNIPHIER_CORE
+ select PINCTRL_UNIPHIER
config PINCTRL_UNIPHIER_PH1_PRO4
tristate "UniPhier PH1-Pro4 SoC pinctrl driver"
- select PINCTRL_UNIPHIER_CORE
+ select PINCTRL_UNIPHIER
config PINCTRL_UNIPHIER_PH1_SLD8
tristate "UniPhier PH1-sLD8 SoC pinctrl driver"
- select PINCTRL_UNIPHIER_CORE
+ select PINCTRL_UNIPHIER
config PINCTRL_UNIPHIER_PH1_PRO5
tristate "UniPhier PH1-Pro5 SoC pinctrl driver"
- select PINCTRL_UNIPHIER_CORE
+ select PINCTRL_UNIPHIER
config PINCTRL_UNIPHIER_PROXSTREAM2
tristate "UniPhier ProXstream2 SoC pinctrl driver"
- select PINCTRL_UNIPHIER_CORE
+ select PINCTRL_UNIPHIER
config PINCTRL_UNIPHIER_PH1_LD6B
tristate "UniPhier PH1-LD6b SoC pinctrl driver"
- select PINCTRL_UNIPHIER_CORE
+ select PINCTRL_UNIPHIER
endif
diff --git a/drivers/pinctrl/uniphier/Makefile b/drivers/pinctrl/uniphier/Makefile
index e215b1097297..e7ce9670306c 100644
--- a/drivers/pinctrl/uniphier/Makefile
+++ b/drivers/pinctrl/uniphier/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PINCTRL_UNIPHIER_CORE) += pinctrl-uniphier-core.o
+obj-y += pinctrl-uniphier-core.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD4) += pinctrl-ph1-ld4.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO4) += pinctrl-ph1-pro4.o
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c b/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c
index 7beb87e8f499..a7056dccfa53 100644
--- a/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c
@@ -537,6 +537,8 @@ static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {22, 23};
static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {44, 45, 46, 47, 48, 49, 50, 51, 52};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static const unsigned uart0_pins[] = {85, 88};
static const unsigned uart0_muxvals[] = {1, 1};
static const unsigned uart1_pins[] = {155, 156};
@@ -619,6 +621,7 @@ static const struct uniphier_pinctrl_group ph1_ld4_groups[] = {
UNIPHIER_PINCTRL_GROUP(i2c3),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart1),
UNIPHIER_PINCTRL_GROUP(uart1b),
@@ -776,6 +779,7 @@ static const char * const i2c1_groups[] = {"i2c1"};
static const char * const i2c2_groups[] = {"i2c2"};
static const char * const i2c3_groups[] = {"i2c3"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
static const char * const uart0_groups[] = {"uart0"};
static const char * const uart1_groups[] = {"uart1", "uart1b"};
static const char * const uart2_groups[] = {"uart2"};
@@ -831,6 +835,7 @@ static const struct uniphier_pinmux_function ph1_ld4_functions[] = {
UNIPHIER_PINMUX_FUNCTION(i2c2),
UNIPHIER_PINMUX_FUNCTION(i2c3),
UNIPHIER_PINMUX_FUNCTION(nand),
+ UNIPHIER_PINMUX_FUNCTION(sd),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c
index 9720e697fbc1..1824831bb4da 100644
--- a/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c
@@ -761,6 +761,8 @@ static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {37, 38};
static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static const unsigned uart0_pins[] = {135, 136};
static const unsigned uart0_muxvals[] = {3, 3};
static const unsigned uart0b_pins[] = {11, 12};
@@ -866,6 +868,7 @@ static const struct uniphier_pinctrl_group ph1_ld6b_groups[] = {
UNIPHIER_PINCTRL_GROUP(i2c3),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart0b),
UNIPHIER_PINCTRL_GROUP(uart1),
@@ -1136,6 +1139,7 @@ static const char * const i2c1_groups[] = {"i2c1"};
static const char * const i2c2_groups[] = {"i2c2"};
static const char * const i2c3_groups[] = {"i2c3"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
static const char * const uart0_groups[] = {"uart0", "uart0b"};
static const char * const uart1_groups[] = {"uart1", "uart1b"};
static const char * const uart2_groups[] = {"uart2", "uart2b"};
@@ -1219,6 +1223,7 @@ static const struct uniphier_pinmux_function ph1_ld6b_functions[] = {
UNIPHIER_PINMUX_FUNCTION(i2c2),
UNIPHIER_PINMUX_FUNCTION(i2c3),
UNIPHIER_PINMUX_FUNCTION(nand),
+ UNIPHIER_PINMUX_FUNCTION(sd),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c b/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c
index 96921e40da5f..ec8e92dfaf8c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c
@@ -1031,6 +1031,11 @@ static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {131, 132};
static const unsigned nand_cs1_muxvals[] = {1, 1};
+static const unsigned sd_pins[] = {150, 151, 152, 153, 154, 155, 156, 157, 158};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned sd1_pins[] = {319, 320, 321, 322, 323, 324, 325, 326,
+ 327};
+static const unsigned sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static const unsigned uart0_pins[] = {127, 128};
static const unsigned uart0_muxvals[] = {0, 0};
static const unsigned uart1_pins[] = {129, 130};
@@ -1140,6 +1145,8 @@ static const struct uniphier_pinctrl_group ph1_pro4_groups[] = {
UNIPHIER_PINCTRL_GROUP(i2c6),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(sd1),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart1),
UNIPHIER_PINCTRL_GROUP(uart2),
@@ -1412,6 +1419,8 @@ static const char * const i2c2_groups[] = {"i2c2"};
static const char * const i2c3_groups[] = {"i2c3"};
static const char * const i2c6_groups[] = {"i2c6"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const sd1_groups[] = {"sd1"};
static const char * const uart0_groups[] = {"uart0"};
static const char * const uart1_groups[] = {"uart1"};
static const char * const uart2_groups[] = {"uart2"};
@@ -1498,6 +1507,8 @@ static const struct uniphier_pinmux_function ph1_pro4_functions[] = {
UNIPHIER_PINMUX_FUNCTION(i2c3),
UNIPHIER_PINMUX_FUNCTION(i2c6),
UNIPHIER_PINMUX_FUNCTION(nand),
+ UNIPHIER_PINMUX_FUNCTION(sd),
+ UNIPHIER_PINMUX_FUNCTION(sd1),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c b/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c
index 9af455978058..e3d648eae85a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c
@@ -818,6 +818,8 @@ static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {26, 27};
static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {250, 251, 252, 253, 254, 255, 256, 257, 258};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static const unsigned uart0_pins[] = {47, 48};
static const unsigned uart0_muxvals[] = {0, 0};
static const unsigned uart0b_pins[] = {227, 228};
@@ -930,6 +932,7 @@ static const struct uniphier_pinctrl_group ph1_pro5_groups[] = {
UNIPHIER_PINCTRL_GROUP(i2c5b),
UNIPHIER_PINCTRL_GROUP(i2c5c),
UNIPHIER_PINCTRL_GROUP(i2c6),
+ UNIPHIER_PINCTRL_GROUP(sd),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart0b),
UNIPHIER_PINCTRL_GROUP(uart1),
@@ -1209,6 +1212,7 @@ static const char * const i2c3_groups[] = {"i2c3"};
static const char * const i2c5_groups[] = {"i2c5", "i2c5b", "i2c5c"};
static const char * const i2c6_groups[] = {"i2c6"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
static const char * const uart0_groups[] = {"uart0", "uart0b"};
static const char * const uart1_groups[] = {"uart1"};
static const char * const uart2_groups[] = {"uart2"};
@@ -1296,6 +1300,7 @@ static const struct uniphier_pinmux_function ph1_pro5_functions[] = {
UNIPHIER_PINMUX_FUNCTION(i2c5),
UNIPHIER_PINMUX_FUNCTION(i2c6),
UNIPHIER_PINMUX_FUNCTION(nand),
+ UNIPHIER_PINMUX_FUNCTION(sd),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
index 7e9dae54fcb2..c3700a33a5da 100644
--- a/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
@@ -22,49 +22,49 @@
#define DRIVER_NAME "ph1-sld8-pinctrl"
static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
- UNIPHIER_PINCTRL_PIN(0, "PCA00", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
15, UNIPHIER_PIN_DRV_4_8,
15, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(1, "PCA01", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(1, "PCA01", 0,
16, UNIPHIER_PIN_DRV_4_8,
16, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(2, "PCA02", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(2, "PCA02", 0,
17, UNIPHIER_PIN_DRV_4_8,
17, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(3, "PCA03", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(3, "PCA03", 0,
18, UNIPHIER_PIN_DRV_4_8,
18, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(4, "PCA04", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(4, "PCA04", 0,
19, UNIPHIER_PIN_DRV_4_8,
19, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(5, "PCA05", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(5, "PCA05", 0,
20, UNIPHIER_PIN_DRV_4_8,
20, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(6, "PCA06", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(6, "PCA06", 0,
21, UNIPHIER_PIN_DRV_4_8,
21, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(7, "PCA07", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(7, "PCA07", 0,
22, UNIPHIER_PIN_DRV_4_8,
22, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(8, "PCA08", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(8, "PCA08", 0,
23, UNIPHIER_PIN_DRV_4_8,
23, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(9, "PCA09", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(9, "PCA09", 0,
24, UNIPHIER_PIN_DRV_4_8,
24, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(10, "PCA10", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(10, "PCA10", 0,
25, UNIPHIER_PIN_DRV_4_8,
25, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(11, "PCA11", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(11, "PCA11", 0,
26, UNIPHIER_PIN_DRV_4_8,
26, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(12, "PCA12", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(12, "PCA12", 0,
27, UNIPHIER_PIN_DRV_4_8,
27, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(13, "PCA13", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(13, "PCA13", 0,
28, UNIPHIER_PIN_DRV_4_8,
28, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(14, "PCA14", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(14, "PCA14", 0,
29, UNIPHIER_PIN_DRV_4_8,
29, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(15, "XNFRE_GB", UNIPHIER_PIN_IECTRL_NONE,
@@ -118,199 +118,199 @@ static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
36, UNIPHIER_PIN_DRV_8_12_16_20,
128, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(32, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(32, "SDCLK", 8,
40, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(33, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(33, "SDCMD", 8,
44, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(34, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(34, "SDDAT0", 8,
48, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(35, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(35, "SDDAT1", 8,
52, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(36, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(36, "SDDAT2", 8,
56, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(37, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(37, "SDDAT3", 8,
60, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(38, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(38, "SDCD", 8,
-1, UNIPHIER_PIN_DRV_FIXED_4,
129, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(39, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(39, "SDWP", 8,
-1, UNIPHIER_PIN_DRV_FIXED_4,
130, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(40, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(40, "SDVOLC", 9,
-1, UNIPHIER_PIN_DRV_FIXED_4,
131, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", 0,
37, UNIPHIER_PIN_DRV_4_8,
37, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(42, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(42, "USB0OD", 0,
38, UNIPHIER_PIN_DRV_4_8,
38, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", 0,
39, UNIPHIER_PIN_DRV_4_8,
39, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(44, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(44, "USB1OD", 0,
40, UNIPHIER_PIN_DRV_4_8,
40, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(45, "PCRESET", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(45, "PCRESET", 0,
41, UNIPHIER_PIN_DRV_4_8,
41, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(46, "PCREG", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(46, "PCREG", 0,
42, UNIPHIER_PIN_DRV_4_8,
42, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(47, "PCCE2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(47, "PCCE2", 0,
43, UNIPHIER_PIN_DRV_4_8,
43, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(48, "PCVS1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(48, "PCVS1", 0,
44, UNIPHIER_PIN_DRV_4_8,
44, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(49, "PCCD2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(49, "PCCD2", 0,
45, UNIPHIER_PIN_DRV_4_8,
45, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(50, "PCCD1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(50, "PCCD1", 0,
46, UNIPHIER_PIN_DRV_4_8,
46, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(51, "PCREADY", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(51, "PCREADY", 0,
47, UNIPHIER_PIN_DRV_4_8,
47, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(52, "PCDOE", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(52, "PCDOE", 0,
48, UNIPHIER_PIN_DRV_4_8,
48, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(53, "PCCE1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(53, "PCCE1", 0,
49, UNIPHIER_PIN_DRV_4_8,
49, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(54, "PCWE", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(54, "PCWE", 0,
50, UNIPHIER_PIN_DRV_4_8,
50, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(55, "PCOE", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(55, "PCOE", 0,
51, UNIPHIER_PIN_DRV_4_8,
51, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(56, "PCWAIT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(56, "PCWAIT", 0,
52, UNIPHIER_PIN_DRV_4_8,
52, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(57, "PCIOWR", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(57, "PCIOWR", 0,
53, UNIPHIER_PIN_DRV_4_8,
53, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(58, "PCIORD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(58, "PCIORD", 0,
54, UNIPHIER_PIN_DRV_4_8,
54, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", 0,
55, UNIPHIER_PIN_DRV_4_8,
55, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", 0,
56, UNIPHIER_PIN_DRV_4_8,
56, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", 0,
57, UNIPHIER_PIN_DRV_4_8,
57, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", 0,
58, UNIPHIER_PIN_DRV_4_8,
58, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", 0,
59, UNIPHIER_PIN_DRV_4_8,
59, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", 0,
60, UNIPHIER_PIN_DRV_4_8,
60, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", 0,
61, UNIPHIER_PIN_DRV_4_8,
61, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", 0,
62, UNIPHIER_PIN_DRV_4_8,
62, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", 0,
63, UNIPHIER_PIN_DRV_4_8,
63, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", 0,
64, UNIPHIER_PIN_DRV_4_8,
64, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", 0,
65, UNIPHIER_PIN_DRV_4_8,
65, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", 0,
66, UNIPHIER_PIN_DRV_4_8,
66, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", 0,
67, UNIPHIER_PIN_DRV_4_8,
67, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", 0,
68, UNIPHIER_PIN_DRV_4_8,
68, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", 0,
69, UNIPHIER_PIN_DRV_4_8,
69, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", 0,
70, UNIPHIER_PIN_DRV_4_8,
70, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", 0,
71, UNIPHIER_PIN_DRV_4_8,
71, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", 0,
72, UNIPHIER_PIN_DRV_4_8,
72, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", 0,
73, UNIPHIER_PIN_DRV_4_8,
73, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", 0,
74, UNIPHIER_PIN_DRV_4_8,
74, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", 0,
75, UNIPHIER_PIN_DRV_4_8,
75, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", 0,
76, UNIPHIER_PIN_DRV_4_8,
76, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", 0,
77, UNIPHIER_PIN_DRV_4_8,
77, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", 0,
78, UNIPHIER_PIN_DRV_4_8,
78, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", 0,
79, UNIPHIER_PIN_DRV_4_8,
79, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", 0,
80, UNIPHIER_PIN_DRV_4_8,
80, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", 0,
81, UNIPHIER_PIN_DRV_4_8,
81, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", 0,
82, UNIPHIER_PIN_DRV_4_8,
82, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", 0,
83, UNIPHIER_PIN_DRV_4_8,
83, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", 0,
84, UNIPHIER_PIN_DRV_4_8,
84, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", 0,
85, UNIPHIER_PIN_DRV_4_8,
85, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", 0,
86, UNIPHIER_PIN_DRV_4_8,
86, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", 0,
87, UNIPHIER_PIN_DRV_4_8,
87, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(92, "AGCI", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(92, "AGCI", 3,
-1, UNIPHIER_PIN_DRV_FIXED_4,
132, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(93, "AGCR", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(93, "AGCR", 4,
-1, UNIPHIER_PIN_DRV_FIXED_4,
133, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(94, "AGCBS", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(94, "AGCBS", 5,
-1, UNIPHIER_PIN_DRV_FIXED_4,
134, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(95, "IECOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(95, "IECOUT", 0,
88, UNIPHIER_PIN_DRV_4_8,
88, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(96, "ASMCK", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(96, "ASMCK", 0,
89, UNIPHIER_PIN_DRV_4_8,
89, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(97, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
@@ -325,31 +325,31 @@ static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
UNIPHIER_PINCTRL_PIN(100, "ASDOUT1", UNIPHIER_PIN_IECTRL_NONE,
93, UNIPHIER_PIN_DRV_4_8,
93, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(101, "ARCOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
94, UNIPHIER_PIN_DRV_4_8,
94, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(102, "SDA0", 10,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(103, "SCL0", 10,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(104, "SDA1", 11,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(105, "SCL1", 11,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", 12,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", 12,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", 13,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", 13,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
@@ -358,76 +358,76 @@ static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
96, UNIPHIER_PIN_DRV_4_8,
96, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(112, "SBO1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(112, "SBO1", 0,
97, UNIPHIER_PIN_DRV_4_8,
97, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(113, "SBI1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(113, "SBI1", 0,
98, UNIPHIER_PIN_DRV_4_8,
98, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(114, "TXD1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(114, "TXD1", 0,
99, UNIPHIER_PIN_DRV_4_8,
99, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(115, "RXD1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(115, "RXD1", 0,
100, UNIPHIER_PIN_DRV_4_8,
100, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(116, "HIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(116, "HIN", 1,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(117, "VIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(117, "VIN", 2,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(118, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(118, "TCON0", 0,
101, UNIPHIER_PIN_DRV_4_8,
101, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(119, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(119, "TCON1", 0,
102, UNIPHIER_PIN_DRV_4_8,
102, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(120, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(120, "TCON2", 0,
103, UNIPHIER_PIN_DRV_4_8,
103, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(121, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(121, "TCON3", 0,
104, UNIPHIER_PIN_DRV_4_8,
104, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(122, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(122, "TCON4", 0,
105, UNIPHIER_PIN_DRV_4_8,
105, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(123, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(123, "TCON5", 0,
106, UNIPHIER_PIN_DRV_4_8,
106, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(124, "TCON6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(124, "TCON6", 0,
107, UNIPHIER_PIN_DRV_4_8,
107, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(125, "TCON7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(125, "TCON7", 0,
108, UNIPHIER_PIN_DRV_4_8,
108, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(126, "TCON8", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(126, "TCON8", 0,
109, UNIPHIER_PIN_DRV_4_8,
109, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(127, "PWMA", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(127, "PWMA", 0,
110, UNIPHIER_PIN_DRV_4_8,
110, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(128, "XIRQ0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(128, "XIRQ0", 0,
111, UNIPHIER_PIN_DRV_4_8,
111, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(129, "XIRQ1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(129, "XIRQ1", 0,
112, UNIPHIER_PIN_DRV_4_8,
112, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(130, "XIRQ2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(130, "XIRQ2", 0,
113, UNIPHIER_PIN_DRV_4_8,
113, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(131, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(131, "XIRQ3", 0,
114, UNIPHIER_PIN_DRV_4_8,
114, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(132, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(132, "XIRQ4", 0,
115, UNIPHIER_PIN_DRV_4_8,
115, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(133, "XIRQ5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(133, "XIRQ5", 0,
116, UNIPHIER_PIN_DRV_4_8,
116, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(134, "XIRQ6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(134, "XIRQ6", 0,
117, UNIPHIER_PIN_DRV_4_8,
117, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(135, "XIRQ7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(135, "XIRQ7", 0,
118, UNIPHIER_PIN_DRV_4_8,
118, UNIPHIER_PIN_PULL_DOWN),
};
@@ -450,6 +450,8 @@ static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {22, 23};
static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, 40};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static const unsigned uart0_pins[] = {70, 71};
static const unsigned uart0_muxvals[] = {3, 3};
static const unsigned uart1_pins[] = {114, 115};
@@ -536,6 +538,7 @@ static const struct uniphier_pinctrl_group ph1_sld8_groups[] = {
UNIPHIER_PINCTRL_GROUP(i2c3),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart1),
UNIPHIER_PINCTRL_GROUP(uart2),
@@ -684,6 +687,7 @@ static const char * const i2c1_groups[] = {"i2c1"};
static const char * const i2c2_groups[] = {"i2c2"};
static const char * const i2c3_groups[] = {"i2c3"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
static const char * const uart0_groups[] = {"uart0"};
static const char * const uart1_groups[] = {"uart1"};
static const char * const uart2_groups[] = {"uart2"};
@@ -739,6 +743,7 @@ static const struct uniphier_pinmux_function ph1_sld8_functions[] = {
UNIPHIER_PINMUX_FUNCTION(i2c2),
UNIPHIER_PINMUX_FUNCTION(i2c3),
UNIPHIER_PINMUX_FUNCTION(nand),
+ UNIPHIER_PINMUX_FUNCTION(sd),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-proxstream2.c b/drivers/pinctrl/uniphier/pinctrl-proxstream2.c
index 3f036e236ad9..bc00d7591c59 100644
--- a/drivers/pinctrl/uniphier/pinctrl-proxstream2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-proxstream2.c
@@ -751,6 +751,8 @@ static const unsigned nand_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8};
static const unsigned nand_cs1_pins[] = {37, 38};
static const unsigned nand_cs1_muxvals[] = {8, 8};
+static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
+static const unsigned sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
static const unsigned uart0_pins[] = {217, 218};
static const unsigned uart0_muxvals[] = {8, 8};
static const unsigned uart0b_pins[] = {179, 180};
@@ -857,6 +859,7 @@ static const struct uniphier_pinctrl_group proxstream2_groups[] = {
UNIPHIER_PINCTRL_GROUP(i2c6),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart0b),
UNIPHIER_PINCTRL_GROUP(uart1),
@@ -1128,6 +1131,7 @@ static const char * const i2c3_groups[] = {"i2c3"};
static const char * const i2c5_groups[] = {"i2c5"};
static const char * const i2c6_groups[] = {"i2c6"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
static const char * const uart0_groups[] = {"uart0", "uart0b"};
static const char * const uart1_groups[] = {"uart1"};
static const char * const uart2_groups[] = {"uart2"};
@@ -1213,6 +1217,7 @@ static const struct uniphier_pinmux_function proxstream2_functions[] = {
UNIPHIER_PINMUX_FUNCTION(i2c5),
UNIPHIER_PINMUX_FUNCTION(i2c6),
UNIPHIER_PINMUX_FUNCTION(nand),
+ UNIPHIER_PINMUX_FUNCTION(sd),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 918f3b643f1b..589872cc8adb 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -539,6 +539,12 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
unsigned reg, reg_end, shift, mask;
int ret;
+ /* some pins need input-enabling */
+ ret = uniphier_conf_pin_input_enable(pctldev,
+ &pctldev->desc->pins[pin], 1);
+ if (ret)
+ return ret;
+
reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
reg_end = reg + reg_stride;
shift = pin * mux_bits % 32;
@@ -563,9 +569,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
return ret;
}
- /* some pins need input-enabling */
- return uniphier_conf_pin_input_enable(pctldev,
- &pctldev->desc->pins[pin], 1);
+ return 0;
}
static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index c15316b003c5..fb22d3f62480 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -486,16 +486,6 @@ static struct pinctrl_desc wmt_desc = {
.confops = &wmt_pinconf_ops,
};
-static int wmt_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void wmt_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev);
@@ -560,8 +550,8 @@ static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip wmt_gpio_chip = {
.label = "gpio-wmt",
.owner = THIS_MODULE,
- .request = wmt_gpio_request,
- .free = wmt_gpio_free,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
.get_direction = wmt_gpio_get_direction,
.direction_input = wmt_gpio_direction_input,
.direction_output = wmt_gpio_direction_output,
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 3271cd1abe7c..d03df4a60d05 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -4,6 +4,7 @@
menuconfig CHROME_PLATFORMS
bool "Platform support for Chrome hardware"
+ depends on X86 || ARM || ARM64 || COMPILE_TEST
---help---
Say Y here to get to see options for platform support for
various Chromebooks and Chromeboxes. This option alone does
@@ -39,7 +40,7 @@ config CHROMEOS_PSTORE
config CROS_EC_CHARDEV
tristate "Chrome OS Embedded Controller userspace device interface"
- depends on CROS_EC_PROTO
+ depends on MFD_CROS_EC
---help---
This driver adds support to talk with the ChromeOS EC from userspace.
@@ -48,7 +49,7 @@ config CROS_EC_CHARDEV
config CROS_EC_LPC
tristate "ChromeOS Embedded Controller (LPC)"
- depends on MFD_CROS_EC && CROS_EC_PROTO && (X86 || COMPILE_TEST)
+ depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
help
If you say Y here, you get support for talking to the ChromeOS EC
over an LPC bus. This uses a simple byte-level protocol with a
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4a11b010f5d8..bc498bda8211 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -1,7 +1,8 @@
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
-cros_ec_devs-objs := cros_ec_dev.o cros_ec_sysfs.o cros_ec_lightbar.o
+cros_ec_devs-objs := cros_ec_dev.o cros_ec_sysfs.o \
+ cros_ec_lightbar.o cros_ec_vbc.o
obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_devs.o
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index 02072749fff3..2b441e9ae593 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -47,8 +47,8 @@ static const char *i2c_adapter_names[] = {
"SMBus I801 adapter",
"i915 gmbus vga",
"i915 gmbus panel",
- "i2c-designware-pci",
- "i2c-designware-pci",
+ "Synopsys DesignWare I2C adapter",
+ "Synopsys DesignWare I2C adapter",
};
/* Keep this enum consistent with i2c_adapter_names */
diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index e8fcdc237029..d45cd254ed1c 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -32,6 +32,7 @@ static int ec_major;
static const struct attribute_group *cros_ec_groups[] = {
&cros_ec_attr_group,
&cros_ec_lightbar_attr_group,
+ &cros_ec_vbc_attr_group,
NULL,
};
@@ -287,6 +288,12 @@ static int ec_device_remove(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id cros_ec_id[] = {
+ { "cros-ec-ctl", 0 },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, cros_ec_id);
+
static struct platform_driver cros_ec_dev_driver = {
.driver = {
.name = "cros-ec-ctl",
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
index 144e09df9b84..ff7640575c75 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -252,7 +252,7 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
ret = sscanf(buf, "%i", &val[i++]);
if (ret == 0)
- return -EINVAL;
+ goto exit;
if (i == 4) {
param = (struct ec_params_lightbar *)msg->data;
@@ -268,17 +268,15 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
if ((j++ % 4) == 0) {
ret = lb_throttle();
if (ret)
- return ret;
+ goto exit;
}
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
if (ret < 0)
goto exit;
- if (msg->result != EC_RES_SUCCESS) {
- ret = -EINVAL;
+ if (msg->result != EC_RES_SUCCESS)
goto exit;
- }
i = 0;
ok = 1;
@@ -352,10 +350,6 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
struct cros_ec_dev *ec = container_of(dev,
struct cros_ec_dev, class_dev);
- msg = alloc_lightbar_cmd_msg(ec);
- if (!msg)
- return -ENOMEM;
-
for (len = 0; len < count; len++)
if (!isalnum(buf[len]))
break;
@@ -370,21 +364,30 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
return ret;
}
+ msg = alloc_lightbar_cmd_msg(ec);
+ if (!msg)
+ return -ENOMEM;
+
param = (struct ec_params_lightbar *)msg->data;
param->cmd = LIGHTBAR_CMD_SEQ;
param->seq.num = num;
ret = lb_throttle();
if (ret)
- return ret;
+ goto exit;
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
if (ret < 0)
- return ret;
+ goto exit;
- if (msg->result != EC_RES_SUCCESS)
- return -EINVAL;
+ if (msg->result != EC_RES_SUCCESS) {
+ ret = -EINVAL;
+ goto exit;
+ }
- return count;
+ ret = count;
+exit:
+ kfree(msg);
+ return ret;
}
/* Module initialization */
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index bdd77ce45f05..f9a245465fd0 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -166,19 +166,9 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
/* Check result */
msg->result = inb(EC_LPC_ADDR_HOST_DATA);
-
- switch (msg->result) {
- case EC_RES_SUCCESS:
- break;
- case EC_RES_IN_PROGRESS:
- ret = -EAGAIN;
- dev_dbg(ec->dev, "command 0x%02x in progress\n",
- msg->command);
+ ret = cros_ec_check_result(ec, msg);
+ if (ret)
goto done;
- default:
- dev_dbg(ec->dev, "command 0x%02x returned %d\n",
- msg->command, msg->result);
- }
/* Read back args */
args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
@@ -330,6 +320,13 @@ static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
},
},
{
+ /* x86-samus, the Chromebook Pixel 2. */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
+ },
+ },
+ {
/* x86-peppy, the Acer C720 Chromebook. */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c
new file mode 100644
index 000000000000..564a0d08c8bf
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_vbc.c
@@ -0,0 +1,137 @@
+/*
+ * cros_ec_vbc - Expose the vboot context nvram to userspace
+ *
+ * Copyright (C) 2015 Collabora Ltd.
+ *
+ * based on vendor driver,
+ *
+ * Copyright (C) 2012 The Chromium OS Authors
+ *
+ * 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/of.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/slab.h>
+
+static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *att, char *buf,
+ loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+ class_dev);
+ struct cros_ec_device *ecdev = ec->ec_dev;
+ struct ec_params_vbnvcontext *params;
+ struct cros_ec_command *msg;
+ int err;
+ const size_t para_sz = sizeof(params->op);
+ const size_t resp_sz = sizeof(struct ec_response_vbnvcontext);
+ const size_t payload = max(para_sz, resp_sz);
+
+ msg = kmalloc(sizeof(*msg) + payload, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ /* NB: we only kmalloc()ated enough space for the op field */
+ params = (struct ec_params_vbnvcontext *)msg->data;
+ params->op = EC_VBNV_CONTEXT_OP_READ;
+
+ msg->version = EC_VER_VBNV_CONTEXT;
+ msg->command = EC_CMD_VBNV_CONTEXT;
+ msg->outsize = para_sz;
+ msg->insize = resp_sz;
+
+ err = cros_ec_cmd_xfer(ecdev, msg);
+ if (err < 0) {
+ dev_err(dev, "Error sending read request: %d\n", err);
+ kfree(msg);
+ return err;
+ }
+
+ memcpy(buf, msg->data, resp_sz);
+
+ kfree(msg);
+ return resp_sz;
+}
+
+static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+ class_dev);
+ struct cros_ec_device *ecdev = ec->ec_dev;
+ struct ec_params_vbnvcontext *params;
+ struct cros_ec_command *msg;
+ int err;
+ const size_t para_sz = sizeof(*params);
+ const size_t data_sz = sizeof(params->block);
+
+ /* Only write full values */
+ if (count != data_sz)
+ return -EINVAL;
+
+ msg = kmalloc(sizeof(*msg) + para_sz, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ params = (struct ec_params_vbnvcontext *)msg->data;
+ params->op = EC_VBNV_CONTEXT_OP_WRITE;
+ memcpy(params->block, buf, data_sz);
+
+ msg->version = EC_VER_VBNV_CONTEXT;
+ msg->command = EC_CMD_VBNV_CONTEXT;
+ msg->outsize = para_sz;
+ msg->insize = 0;
+
+ err = cros_ec_cmd_xfer(ecdev, msg);
+ if (err < 0) {
+ dev_err(dev, "Error sending write request: %d\n", err);
+ kfree(msg);
+ return err;
+ }
+
+ kfree(msg);
+ return data_sz;
+}
+
+static umode_t cros_ec_vbc_is_visible(struct kobject *kobj,
+ struct bin_attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+ class_dev);
+ struct device_node *np = ec->ec_dev->dev->of_node;
+
+ if (IS_ENABLED(CONFIG_OF) && np) {
+ if (of_property_read_bool(np, "google,has-vbc-nvram"))
+ return a->attr.mode;
+ }
+
+ return 0;
+}
+
+static BIN_ATTR_RW(vboot_context, 16);
+
+static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
+ &bin_attr_vboot_context,
+ NULL
+};
+
+struct attribute_group cros_ec_vbc_attr_group = {
+ .name = "vbc",
+ .bin_attrs = cros_ec_vbc_bin_attrs,
+ .is_bin_visible = cros_ec_vbc_is_visible,
+};
diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index f9119525f557..f99b183d5296 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -192,18 +192,15 @@ static ssize_t ec_dbgfs_cmd_write(struct file *file, const char __user *buf,
for (i = 0; i <= ec_cmd_bytes; i++)
ec_cmd[i] = ec_cmd_int[i];
- pr_debug("olpc-ec: debugfs cmd 0x%02x with %d args %02x %02x %02x %02x %02x, want %d returns\n",
- ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2],
- ec_cmd[3], ec_cmd[4], ec_cmd[5], ec_dbgfs_resp_bytes);
+ pr_debug("olpc-ec: debugfs cmd 0x%02x with %d args %5ph, want %d returns\n",
+ ec_cmd[0], ec_cmd_bytes, ec_cmd + 1,
+ ec_dbgfs_resp_bytes);
olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1],
ec_cmd_bytes, ec_dbgfs_resp, ec_dbgfs_resp_bytes);
- pr_debug("olpc-ec: response %02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n",
- ec_dbgfs_resp[0], ec_dbgfs_resp[1], ec_dbgfs_resp[2],
- ec_dbgfs_resp[3], ec_dbgfs_resp[4], ec_dbgfs_resp[5],
- ec_dbgfs_resp[6], ec_dbgfs_resp[7],
- ec_dbgfs_resp_bytes);
+ pr_debug("olpc-ec: response %8ph (%d bytes expected)\n",
+ ec_dbgfs_resp, ec_dbgfs_resp_bytes);
out:
mutex_unlock(&ec_dbgfs_lock);
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index c69bb703f483..1089eaa02b00 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -309,8 +309,8 @@ config COMPAL_LAPTOP
This is a driver for laptops built by Compal, and some models by
other brands (e.g. Dell, Toshiba).
- It adds support for rfkill, Bluetooth, WLAN and LCD brightness
- control.
+ It adds support for rfkill, Bluetooth, WLAN, LCD brightness, hwmon
+ and battery charging level control.
For a (possibly incomplete) list of supported laptops, please refer
to: Documentation/platform/x86-laptop-drivers.txt
@@ -345,6 +345,7 @@ config IDEAPAD_LAPTOP
depends on SERIO_I8042
depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO || ACPI_VIDEO = n
+ depends on ACPI_WMI || ACPI_WMI = n
select INPUT_SPARSEKMAP
help
This is a driver for Lenovo IdeaPad netbooks contains drivers for
@@ -700,6 +701,24 @@ config TOSHIBA_HAPS
If you have a recent Toshiba laptop with a built-in accelerometer
device, say Y.
+config TOSHIBA_WMI
+ tristate "Toshiba WMI Hotkeys Driver (EXPERIMENTAL)"
+ default n
+ depends on ACPI_WMI
+ depends on INPUT
+ select INPUT_SPARSEKMAP
+ ---help---
+ This driver adds hotkey monitoring support to some Toshiba models
+ that manage the hotkeys via WMI events.
+
+ WARNING: This driver is incomplete as it lacks a proper keymap and the
+ *notify function only prints the ACPI event type value. Be warned that
+ you will need to provide some information if you have a Toshiba model
+ with WMI event hotkeys and want to help with the develpment of this
+ driver.
+
+ If you have a WMI-based hotkeys Toshiba laptop, say Y or M here.
+
config ACPI_CMPC
tristate "CMPC Laptop Extras"
depends on X86 && ACPI
@@ -914,6 +933,7 @@ config PVPANIC
config INTEL_PMC_IPC
tristate "Intel PMC IPC Driver"
+ depends on ACPI
---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/Makefile b/drivers/platform/x86/Makefile
index ada512819028..3ca78a3eb6f8 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
+obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index d773b9dc48a0..1062fa42ff26 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1662,58 +1662,6 @@ static void acer_rfkill_exit(void)
return;
}
-/*
- * sysfs interface
- */
-static ssize_t show_bool_threeg(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u32 result; \
- acpi_status status;
-
- pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n",
- current->comm);
- status = get_u32(&result, ACER_CAP_THREEG);
- if (ACPI_SUCCESS(status))
- return sprintf(buf, "%u\n", result);
- return sprintf(buf, "Read error\n");
-}
-
-static ssize_t set_bool_threeg(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- u32 tmp = simple_strtoul(buf, NULL, 10);
- acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
- pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n",
- current->comm);
- if (ACPI_FAILURE(status))
- return -EINVAL;
- return count;
-}
-static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
- set_bool_threeg);
-
-static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- pr_info("This interface sysfs will be removed in 2014 - used by: %s\n",
- current->comm);
- switch (interface->type) {
- case ACER_AMW0:
- return sprintf(buf, "AMW0\n");
- case ACER_AMW0_V2:
- return sprintf(buf, "AMW0 v2\n");
- case ACER_WMID:
- return sprintf(buf, "WMID\n");
- case ACER_WMID_v2:
- return sprintf(buf, "WMID v2\n");
- default:
- return sprintf(buf, "Error!\n");
- }
-}
-
-static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
-
static void acer_wmi_notify(u32 value, void *context)
{
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -2127,39 +2075,6 @@ static struct platform_driver acer_platform_driver = {
static struct platform_device *acer_platform_device;
-static int remove_sysfs(struct platform_device *device)
-{
- if (has_cap(ACER_CAP_THREEG))
- device_remove_file(&device->dev, &dev_attr_threeg);
-
- device_remove_file(&device->dev, &dev_attr_interface);
-
- return 0;
-}
-
-static int __init create_sysfs(void)
-{
- int retval = -ENOMEM;
-
- if (has_cap(ACER_CAP_THREEG)) {
- retval = device_create_file(&acer_platform_device->dev,
- &dev_attr_threeg);
- if (retval)
- goto error_sysfs;
- }
-
- retval = device_create_file(&acer_platform_device->dev,
- &dev_attr_interface);
- if (retval)
- goto error_sysfs;
-
- return 0;
-
-error_sysfs:
- remove_sysfs(acer_platform_device);
- return retval;
-}
-
static void remove_debugfs(void)
{
debugfs_remove(interface->debug.devices);
@@ -2290,10 +2205,6 @@ static int __init acer_wmi_init(void)
if (err)
goto error_device_add;
- err = create_sysfs();
- if (err)
- goto error_create_sys;
-
if (wmi_has_guid(WMID_GUID2)) {
interface->debug.wmid_devices = get_wmid_devices();
err = create_debugfs();
@@ -2307,8 +2218,6 @@ static int __init acer_wmi_init(void)
return 0;
error_create_debugfs:
- remove_sysfs(acer_platform_device);
-error_create_sys:
platform_device_del(acer_platform_device);
error_device_add:
platform_device_put(acer_platform_device);
@@ -2331,7 +2240,6 @@ static void __exit acer_wmi_exit(void)
if (has_cap(ACER_CAP_ACCEL))
acer_wmi_accel_destroy();
- remove_sysfs(acer_platform_device);
remove_debugfs();
platform_device_unregister(acer_platform_device);
platform_driver_unregister(&acer_platform_driver);
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 0dec3f59917a..976efeb3f2ba 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -346,7 +346,7 @@ gmux_active_client(struct apple_gmux_data *gmux_data)
return VGA_SWITCHEROO_DIS;
}
-static struct vga_switcheroo_handler gmux_handler = {
+static const struct vga_switcheroo_handler gmux_handler = {
.switchto = gmux_switchto,
.power_state = gmux_set_power_state,
.get_client_id = gmux_get_client_id,
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index efbc3f0c592b..f96f7b865267 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -582,7 +582,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
static int asus_wmi_led_init(struct asus_wmi *asus)
{
- int rv = 0;
+ int rv = 0, led_val;
asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
if (!asus->led_workqueue)
@@ -602,9 +602,11 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
- if (kbd_led_read(asus, NULL, NULL) >= 0) {
+ led_val = kbd_led_read(asus, NULL, NULL);
+ if (led_val >= 0) {
INIT_WORK(&asus->kbd_led_work, kbd_led_update);
+ asus->kbd_led_wk = led_val;
asus->kbd_led.name = "asus::kbd_backlight";
asus->kbd_led.brightness_set = kbd_led_set;
asus->kbd_led.brightness_get = kbd_led_get;
@@ -1318,7 +1320,7 @@ static ssize_t asus_hwmon_temp1(struct device *dev,
if (err < 0)
return err;
- value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
+ value = DECI_KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
return sprintf(buf, "%d\n", value);
}
@@ -1680,7 +1682,7 @@ static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
int rv, err, value;
value = asus_wmi_get_devstate_simple(asus, devid);
- if (value == -ENODEV) /* Check device presence */
+ if (value < 0)
return value;
rv = parse_arg(buf, count, &value);
@@ -2160,6 +2162,16 @@ static int asus_hotk_thaw(struct device *device)
return 0;
}
+static int asus_hotk_resume(struct device *device)
+{
+ struct asus_wmi *asus = dev_get_drvdata(device);
+
+ if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
+
+ return 0;
+}
+
static int asus_hotk_restore(struct device *device)
{
struct asus_wmi *asus = dev_get_drvdata(device);
@@ -2190,6 +2202,8 @@ static int asus_hotk_restore(struct device *device)
bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
rfkill_set_sw_state(asus->uwb.rfkill, bl);
}
+ if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
return 0;
}
@@ -2197,6 +2211,7 @@ static int asus_hotk_restore(struct device *device)
static const struct dev_pm_ops asus_pm_ops = {
.thaw = asus_hotk_thaw,
.restore = asus_hotk_restore,
+ .resume = asus_hotk_resume,
};
static int asus_wmi_probe(struct platform_device *pdev)
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index f2706d27adff..e1c2b6d4b24a 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -151,6 +151,8 @@
#define BAT_STATUS2 0xF1
#define BAT_STOP_CHARGE1 0xF2
#define BAT_STOP_CHARGE2 0xF3
+#define BAT_CHARGE_LIMIT 0x03
+#define BAT_CHARGE_LIMIT_MAX 100
#define BAT_S0_DISCHARGE (1 << 0)
#define BAT_S0_DISCHRG_CRITICAL (1 << 2)
@@ -601,6 +603,12 @@ static int bat_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_NOW:
val->intval = ec_read_u16(BAT_CHARGE_NOW) * 1000;
break;
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ val->intval = ec_read_u8(BAT_CHARGE_LIMIT);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
+ val->intval = BAT_CHARGE_LIMIT_MAX;
+ break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = ec_read_u8(BAT_CAPACITY);
break;
@@ -634,6 +642,36 @@ static int bat_get_property(struct power_supply *psy,
return 0;
}
+static int bat_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ int level;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ level = val->intval;
+ if (level < 0 || level > BAT_CHARGE_LIMIT_MAX)
+ return -EINVAL;
+ if (ec_write(BAT_CHARGE_LIMIT, level) < 0)
+ return -EIO;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int bat_writeable_property(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ return 1;
+ default:
+ return 0;
+ }
+}
@@ -726,6 +764,8 @@ static enum power_supply_property compal_bat_properties[] = {
POWER_SUPPLY_PROP_POWER_NOW,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TEMP,
@@ -880,11 +920,12 @@ static const struct power_supply_desc psy_bat_desc = {
.properties = compal_bat_properties,
.num_properties = ARRAY_SIZE(compal_bat_properties),
.get_property = bat_get_property,
+ .set_property = bat_set_property,
+ .property_is_writeable = bat_writeable_property,
};
static void initialize_power_supply_data(struct compal_data *data)
{
-
ec_read_sequence(BAT_MANUFACTURER_NAME_ADDR,
data->bat_manufacturer_name,
BAT_MANUFACTURER_NAME_LEN);
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
index 97c2be195efc..c62e5e11ca4b 100644
--- a/drivers/platform/x86/ibm_rtl.c
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -33,7 +33,7 @@
#include <linux/mutex.h>
#include <asm/bios_ebda.h>
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
static bool force;
module_param(force, bool, 0);
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index fce49f3c6ed6..a313dfc0245f 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -47,6 +47,10 @@
#define CFG_WIFI_BIT (18)
#define CFG_CAMERA_BIT (19)
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+static const char ideapad_wmi_fnesc_event[] = "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6";
+#endif
+
enum {
VPCCMD_R_VPC1 = 0x10,
VPCCMD_R_BL_MAX,
@@ -567,6 +571,8 @@ static const struct key_entry ideapad_keymap[] = {
{ KE_KEY, 65, { KEY_PROG4 } },
{ KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
{ KE_KEY, 67, { KEY_TOUCHPAD_ON } },
+ { KE_KEY, 128, { KEY_ESC } },
+
{ KE_END, 0 },
};
@@ -825,6 +831,19 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
}
}
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+static void ideapad_wmi_notify(u32 value, void *context)
+{
+ switch (value) {
+ case 128:
+ ideapad_input_report(context, value);
+ break;
+ default:
+ pr_info("Unknown WMI event %u\n", value);
+ }
+}
+#endif
+
/*
* Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
* always results in 0 on these models, causing ideapad_laptop to wrongly
@@ -853,24 +872,31 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
},
},
{
- .ident = "Lenovo Yoga 3 14",
+ .ident = "Lenovo Yoga 2 11 / 13 / Pro",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3 14"),
+ DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
},
},
{
- .ident = "Lenovo Yoga 2 11 / 13 / Pro",
+ .ident = "Lenovo Yoga 3 1170 / 1470",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3"),
},
},
{
.ident = "Lenovo Yoga 3 Pro 1370",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3 Pro-1370"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"),
+ },
+ },
+ {
+ .ident = "Lenovo Yoga 900",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 900"),
},
},
{}
@@ -935,8 +961,18 @@ static int ideapad_acpi_add(struct platform_device *pdev)
ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
if (ret)
goto notification_failed;
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+ ret = wmi_install_notify_handler(ideapad_wmi_fnesc_event, ideapad_wmi_notify, priv);
+ if (ret != AE_OK && ret != AE_NOT_EXIST)
+ goto notification_failed_wmi;
+#endif
return 0;
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+notification_failed_wmi:
+ acpi_remove_notify_handler(priv->adev->handle,
+ ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
+#endif
notification_failed:
ideapad_backlight_exit(priv);
backlight_failed:
@@ -955,6 +991,9 @@ static int ideapad_acpi_remove(struct platform_device *pdev)
struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
int i;
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+ wmi_remove_notify_handler(ideapad_wmi_fnesc_event);
+#endif
acpi_remove_notify_handler(priv->adev->handle,
ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
ideapad_backlight_exit(priv);
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index e2065e06a3f3..55663b3d7282 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -78,7 +78,7 @@
#include <asm/processor.h>
#include "intel_ips.h"
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index e8b46d2c468c..0a919d81662c 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -315,7 +315,7 @@ static ssize_t aux0_show(struct device *dev,
result = sensor_get_auxtrip(attr->handle, 0, &value);
- return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value));
+ return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value));
}
static ssize_t aux1_show(struct device *dev,
@@ -327,7 +327,7 @@ static ssize_t aux1_show(struct device *dev,
result = sensor_get_auxtrip(attr->handle, 1, &value);
- return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value));
+ return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value));
}
static ssize_t aux0_store(struct device *dev,
@@ -345,7 +345,7 @@ static ssize_t aux0_store(struct device *dev,
if (value < 0)
return -EINVAL;
- result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_KELVIN(value));
+ result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_DECI_KELVIN(value));
return result ? result : count;
}
@@ -364,7 +364,7 @@ static ssize_t aux1_store(struct device *dev,
if (value < 0)
return -EINVAL;
- result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_KELVIN(value));
+ result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_DECI_KELVIN(value));
return result ? result : count;
}
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
index 22606d6b2af3..1fc0de870ff8 100644
--- a/drivers/platform/x86/intel_mid_powerbtn.c
+++ b/drivers/platform/x86/intel_mid_powerbtn.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/mfd/intel_msic.h>
+#include <linux/pm_wakeirq.h>
#define DRIVER_NAME "msic_power_btn"
@@ -76,14 +77,17 @@ static int mfld_pb_probe(struct platform_device *pdev)
input_set_capability(input, EV_KEY, KEY_POWER);
- error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_NO_SUSPEND,
- DRIVER_NAME, input);
+ error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
+ DRIVER_NAME, input);
if (error) {
dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
"button\n", irq);
goto err_free_input;
}
+ device_init_wakeup(&pdev->dev, true);
+ dev_pm_set_wake_irq(&pdev->dev, irq);
+
error = input_register_device(input);
if (error) {
dev_err(&pdev->dev, "Unable to register input dev, error "
@@ -124,6 +128,8 @@ static int mfld_pb_remove(struct platform_device *pdev)
struct input_dev *input = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
free_irq(irq, input);
input_unregister_device(input);
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 187d1086d15c..f94b730540e2 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -92,11 +92,8 @@ static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
.irq_mode = 0,
};
-static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id);
-static void ipc_remove(struct pci_dev *pdev);
-
struct intel_scu_ipc_dev {
- struct pci_dev *pdev;
+ struct device *dev;
void __iomem *ipc_base;
void __iomem *i2c_base;
struct completion cmd_complete;
@@ -118,28 +115,30 @@ static struct intel_scu_ipc_dev ipcdev; /* Only one for now */
static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
/*
+ * Send ipc command
* Command Register (Write Only):
* A write to this register results in an interrupt to the SCU core processor
* Format:
* |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)|
*/
-static inline void ipc_command(u32 cmd) /* Send ipc command */
+static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)
{
- if (ipcdev.irq_mode) {
- reinit_completion(&ipcdev.cmd_complete);
- writel(cmd | IPC_IOC, ipcdev.ipc_base);
+ if (scu->irq_mode) {
+ reinit_completion(&scu->cmd_complete);
+ writel(cmd | IPC_IOC, scu->ipc_base);
}
- writel(cmd, ipcdev.ipc_base);
+ writel(cmd, scu->ipc_base);
}
/*
+ * Write ipc data
* IPC Write Buffer (Write Only):
* 16-byte buffer for sending data associated with IPC command to
* SCU. Size of the data is specified in the IPC_COMMAND_REG register
*/
-static inline void ipc_data_writel(u32 data, u32 offset) /* Write ipc data */
+static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset)
{
- writel(data, ipcdev.ipc_base + 0x80 + offset);
+ writel(data, scu->ipc_base + 0x80 + offset);
}
/*
@@ -149,35 +148,37 @@ static inline void ipc_data_writel(u32 data, u32 offset) /* Write ipc data */
* Format:
* |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)|
*/
-static inline u8 ipc_read_status(void)
+static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu)
{
- return __raw_readl(ipcdev.ipc_base + 0x04);
+ return __raw_readl(scu->ipc_base + 0x04);
}
-static inline u8 ipc_data_readb(u32 offset) /* Read ipc byte data */
+/* Read ipc byte data */
+static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset)
{
- return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
+ return readb(scu->ipc_base + IPC_READ_BUFFER + offset);
}
-static inline u32 ipc_data_readl(u32 offset) /* Read ipc u32 data */
+/* Read ipc u32 data */
+static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)
{
- return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
+ return readl(scu->ipc_base + IPC_READ_BUFFER + offset);
}
/* Wait till scu status is busy */
-static inline int busy_loop(void)
+static inline int busy_loop(struct intel_scu_ipc_dev *scu)
{
- u32 status = ipc_read_status();
+ u32 status = ipc_read_status(scu);
u32 loop_count = 100000;
/* break if scu doesn't reset busy bit after huge retry */
while ((status & BIT(0)) && --loop_count) {
udelay(1); /* scu processing time is in few u secods */
- status = ipc_read_status();
+ status = ipc_read_status(scu);
}
if (status & BIT(0)) {
- dev_err(&ipcdev.pdev->dev, "IPC timed out");
+ dev_err(scu->dev, "IPC timed out");
return -ETIMEDOUT;
}
@@ -188,31 +189,31 @@ static inline int busy_loop(void)
}
/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
-static inline int ipc_wait_for_interrupt(void)
+static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
{
int status;
- if (!wait_for_completion_timeout(&ipcdev.cmd_complete, 3 * HZ)) {
- struct device *dev = &ipcdev.pdev->dev;
- dev_err(dev, "IPC timed out\n");
+ if (!wait_for_completion_timeout(&scu->cmd_complete, 3 * HZ)) {
+ dev_err(scu->dev, "IPC timed out\n");
return -ETIMEDOUT;
}
- status = ipc_read_status();
+ status = ipc_read_status(scu);
if (status & BIT(1))
return -EIO;
return 0;
}
-static int intel_scu_ipc_check_status(void)
+static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu)
{
- return ipcdev.irq_mode ? ipc_wait_for_interrupt() : busy_loop();
+ return scu->irq_mode ? ipc_wait_for_interrupt(scu) : busy_loop(scu);
}
/* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */
static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
int nc;
u32 offset = 0;
int err;
@@ -223,7 +224,7 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
@@ -235,27 +236,27 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
if (id == IPC_CMD_PCNTRL_R) {
for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
- ipc_data_writel(wbuf[nc], offset);
- ipc_command((count * 2) << 16 | id << 12 | 0 << 8 | op);
+ ipc_data_writel(scu, wbuf[nc], offset);
+ ipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op);
} else if (id == IPC_CMD_PCNTRL_W) {
for (nc = 0; nc < count; nc++, offset += 1)
cbuf[offset] = data[nc];
for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
- ipc_data_writel(wbuf[nc], offset);
- ipc_command((count * 3) << 16 | id << 12 | 0 << 8 | op);
+ ipc_data_writel(scu, wbuf[nc], offset);
+ ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op);
} else if (id == IPC_CMD_PCNTRL_M) {
cbuf[offset] = data[0];
cbuf[offset + 1] = data[1];
- ipc_data_writel(wbuf[0], 0); /* Write wbuff */
- ipc_command(4 << 16 | id << 12 | 0 << 8 | op);
+ ipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */
+ ipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op);
}
- err = intel_scu_ipc_check_status();
+ err = intel_scu_ipc_check_status(scu);
if (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */
/* Workaround: values are read as 0 without memcpy_fromio */
- memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16);
+ memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16);
for (nc = 0; nc < count; nc++)
- data[nc] = ipc_data_readb(nc);
+ data[nc] = ipc_data_readb(scu, nc);
}
mutex_unlock(&ipclock);
return err;
@@ -436,15 +437,16 @@ EXPORT_SYMBOL(intel_scu_ipc_update_register);
*/
int intel_scu_ipc_simple_command(int cmd, int sub)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
int err;
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
- ipc_command(sub << 12 | cmd);
- err = intel_scu_ipc_check_status();
+ ipc_command(scu, sub << 12 | cmd);
+ err = intel_scu_ipc_check_status(scu);
mutex_unlock(&ipclock);
return err;
}
@@ -465,23 +467,24 @@ EXPORT_SYMBOL(intel_scu_ipc_simple_command);
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
u32 *out, int outlen)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
int i, err;
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
for (i = 0; i < inlen; i++)
- ipc_data_writel(*in++, 4 * i);
+ ipc_data_writel(scu, *in++, 4 * i);
- ipc_command((inlen << 16) | (sub << 12) | cmd);
- err = intel_scu_ipc_check_status();
+ ipc_command(scu, (inlen << 16) | (sub << 12) | cmd);
+ err = intel_scu_ipc_check_status(scu);
if (!err) {
for (i = 0; i < outlen; i++)
- *out++ = ipc_data_readl(4 * i);
+ *out++ = ipc_data_readl(scu, 4 * i);
}
mutex_unlock(&ipclock);
@@ -507,25 +510,26 @@ EXPORT_SYMBOL(intel_scu_ipc_command);
*/
int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
u32 cmd = 0;
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
cmd = (addr >> 24) & 0xFF;
if (cmd == IPC_I2C_READ) {
- writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
+ writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
/* Write not getting updated without delay */
mdelay(1);
- *data = readl(ipcdev.i2c_base + I2C_DATA_ADDR);
+ *data = readl(scu->i2c_base + I2C_DATA_ADDR);
} else if (cmd == IPC_I2C_WRITE) {
- writel(*data, ipcdev.i2c_base + I2C_DATA_ADDR);
+ writel(*data, scu->i2c_base + I2C_DATA_ADDR);
mdelay(1);
- writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
+ writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
} else {
- dev_err(&ipcdev.pdev->dev,
+ dev_err(scu->dev,
"intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd);
mutex_unlock(&ipclock);
@@ -545,63 +549,65 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
*/
static irqreturn_t ioc(int irq, void *dev_id)
{
- if (ipcdev.irq_mode)
- complete(&ipcdev.cmd_complete);
+ struct intel_scu_ipc_dev *scu = dev_id;
+
+ if (scu->irq_mode)
+ complete(&scu->cmd_complete);
return IRQ_HANDLED;
}
/**
* ipc_probe - probe an Intel SCU IPC
- * @dev: the PCI device matching
+ * @pdev: the PCI device matching
* @id: entry in the match table
*
* Enable and install an intel SCU IPC. This appears in the PCI space
* but uses some hard coded addresses as well.
*/
-static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ int platform; /* Platform type */
int err;
+ struct intel_scu_ipc_dev *scu = &ipcdev;
struct intel_scu_ipc_pdata_t *pdata;
- resource_size_t base;
- if (ipcdev.pdev) /* We support only one SCU */
+ platform = intel_mid_identify_cpu();
+ if (platform == 0)
+ return -ENODEV;
+
+ if (scu->dev) /* We support only one SCU */
return -EBUSY;
pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data;
- ipcdev.pdev = pci_dev_get(dev);
- ipcdev.irq_mode = pdata->irq_mode;
+ scu->dev = &pdev->dev;
+ scu->irq_mode = pdata->irq_mode;
- err = pci_enable_device(dev);
+ err = pcim_enable_device(pdev);
if (err)
return err;
- err = pci_request_regions(dev, "intel_scu_ipc");
+ err = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
if (err)
return err;
- base = pci_resource_start(dev, 0);
- if (!base)
- return -ENOMEM;
+ init_completion(&scu->cmd_complete);
- init_completion(&ipcdev.cmd_complete);
+ err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc",
+ scu);
+ if (err)
+ return err;
- if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev))
- return -EBUSY;
+ scu->ipc_base = pcim_iomap_table(pdev)[0];
- ipcdev.ipc_base = ioremap_nocache(base, pci_resource_len(dev, 0));
- if (!ipcdev.ipc_base)
+ scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
+ if (!scu->i2c_base)
return -ENOMEM;
- ipcdev.i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
- if (!ipcdev.i2c_base) {
- iounmap(ipcdev.ipc_base);
- return -ENOMEM;
- }
-
intel_scu_devices_create();
+ pci_set_drvdata(pdev, scu);
return 0;
}
@@ -617,12 +623,13 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
*/
static void ipc_remove(struct pci_dev *pdev)
{
- free_irq(pdev->irq, &ipcdev);
- pci_release_regions(pdev);
- pci_dev_put(ipcdev.pdev);
- iounmap(ipcdev.ipc_base);
- iounmap(ipcdev.i2c_base);
- ipcdev.pdev = NULL;
+ struct intel_scu_ipc_dev *scu = pci_get_drvdata(pdev);
+
+ mutex_lock(&ipclock);
+ scu->dev = NULL;
+ mutex_unlock(&ipclock);
+
+ iounmap(scu->i2c_base);
intel_scu_devices_destroy();
}
@@ -652,24 +659,8 @@ static struct pci_driver ipc_driver = {
.remove = ipc_remove,
};
-static int __init intel_scu_ipc_init(void)
-{
- int platform; /* Platform type */
-
- platform = intel_mid_identify_cpu();
- if (platform == 0)
- return -ENODEV;
- return pci_register_driver(&ipc_driver);
-}
-
-static void __exit intel_scu_ipc_exit(void)
-{
- pci_unregister_driver(&ipc_driver);
-}
+module_pci_driver(ipc_driver);
MODULE_AUTHOR("Sreedhara DS <sreedhara.ds@intel.com>");
MODULE_DESCRIPTION("Intel SCU IPC driver");
MODULE_LICENSE("GPL");
-
-module_init(intel_scu_ipc_init);
-module_exit(intel_scu_ipc_exit);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index aeb80d1c2b07..f73c29558cd3 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1204,6 +1204,8 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
{
u32 real_ev = event;
u8 ev_type = 0;
+ int ret;
+
dprintk("sony_nc_notify, event: 0x%.2x\n", event);
if (event >= 0x90) {
@@ -1225,13 +1227,12 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
case 0x0100:
case 0x0127:
ev_type = HOTKEY;
- real_ev = sony_nc_hotkeys_decode(event, handle);
+ ret = sony_nc_hotkeys_decode(event, handle);
- if (real_ev > 0)
- sony_laptop_report_input_event(real_ev);
- else
- /* restore the original event for reporting */
- real_ev = event;
+ if (ret > 0) {
+ sony_laptop_report_input_event(ret);
+ real_ev = ret;
+ }
break;
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 131dd7464183..0bed4733c4f0 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6459,8 +6459,7 @@ static void __init tpacpi_detect_brightness_capabilities(void)
pr_info("detected a 8-level brightness capable ThinkPad\n");
break;
default:
- pr_err("Unsupported brightness interface, "
- "please contact %s\n", TPACPI_MAIL);
+ pr_info("Unsupported brightness interface\n");
tp_features.bright_unkfw = 1;
bright_maxlvl = b - 1;
}
diff --git a/drivers/platform/x86/toshiba-wmi.c b/drivers/platform/x86/toshiba-wmi.c
new file mode 100644
index 000000000000..feac4576b837
--- /dev/null
+++ b/drivers/platform/x86/toshiba-wmi.c
@@ -0,0 +1,138 @@
+/*
+ * toshiba_wmi.c - Toshiba WMI Hotkey Driver
+ *
+ * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+
+MODULE_AUTHOR("Azael Avalos");
+MODULE_DESCRIPTION("Toshiba WMI Hotkey Driver");
+MODULE_LICENSE("GPL");
+
+#define TOSHIBA_WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"
+
+MODULE_ALIAS("wmi:"TOSHIBA_WMI_EVENT_GUID);
+
+static struct input_dev *toshiba_wmi_input_dev;
+
+static const struct key_entry toshiba_wmi_keymap[] __initconst = {
+ /* TODO: Add keymap values once found... */
+ /*{ KE_KEY, 0x00, { KEY_ } },*/
+ { KE_END, 0 }
+};
+
+static void toshiba_wmi_notify(u32 value, void *context)
+{
+ struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ acpi_status status;
+
+ status = wmi_get_event_data(value, &response);
+ if (ACPI_FAILURE(status)) {
+ pr_err("Bad event status 0x%x\n", status);
+ return;
+ }
+
+ obj = (union acpi_object *)response.pointer;
+ if (!obj)
+ return;
+
+ /* TODO: Add proper checks once we have data */
+ pr_debug("Unknown event received, obj type %x\n", obj->type);
+
+ kfree(response.pointer);
+}
+
+static int __init toshiba_wmi_input_setup(void)
+{
+ acpi_status status;
+ int err;
+
+ toshiba_wmi_input_dev = input_allocate_device();
+ if (!toshiba_wmi_input_dev)
+ return -ENOMEM;
+
+ toshiba_wmi_input_dev->name = "Toshiba WMI hotkeys";
+ toshiba_wmi_input_dev->phys = "wmi/input0";
+ toshiba_wmi_input_dev->id.bustype = BUS_HOST;
+
+ err = sparse_keymap_setup(toshiba_wmi_input_dev,
+ toshiba_wmi_keymap, NULL);
+ if (err)
+ goto err_free_dev;
+
+ status = wmi_install_notify_handler(TOSHIBA_WMI_EVENT_GUID,
+ toshiba_wmi_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ err = -EIO;
+ goto err_free_keymap;
+ }
+
+ err = input_register_device(toshiba_wmi_input_dev);
+ if (err)
+ goto err_remove_notifier;
+
+ return 0;
+
+ err_remove_notifier:
+ wmi_remove_notify_handler(TOSHIBA_WMI_EVENT_GUID);
+ err_free_keymap:
+ sparse_keymap_free(toshiba_wmi_input_dev);
+ err_free_dev:
+ input_free_device(toshiba_wmi_input_dev);
+ return err;
+}
+
+static void toshiba_wmi_input_destroy(void)
+{
+ wmi_remove_notify_handler(TOSHIBA_WMI_EVENT_GUID);
+ sparse_keymap_free(toshiba_wmi_input_dev);
+ input_unregister_device(toshiba_wmi_input_dev);
+}
+
+static int __init toshiba_wmi_init(void)
+{
+ int ret;
+
+ if (!wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+ return -ENODEV;
+
+ ret = toshiba_wmi_input_setup();
+ if (ret) {
+ pr_err("Failed to setup input device\n");
+ return ret;
+ }
+
+ pr_info("Toshiba WMI Hotkey Driver\n");
+
+ return 0;
+}
+
+static void __exit toshiba_wmi_exit(void)
+{
+ if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+ toshiba_wmi_input_destroy();
+}
+
+module_init(toshiba_wmi_init);
+module_exit(toshiba_wmi_exit);
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index f2372f400ddb..c01302989ee4 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -131,7 +131,7 @@ MODULE_LICENSE("GPL");
/* Field definitions */
#define HCI_ACCEL_MASK 0x7fff
#define HCI_HOTKEY_DISABLE 0x0b
-#define HCI_HOTKEY_ENABLE 0x09
+#define HCI_HOTKEY_ENABLE 0x01
#define HCI_HOTKEY_SPECIAL_FUNCTIONS 0x10
#define HCI_LCD_BRIGHTNESS_BITS 3
#define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS)
@@ -198,6 +198,7 @@ struct toshiba_acpi_dev {
unsigned int panel_power_on_supported:1;
unsigned int usb_three_supported:1;
unsigned int sysfs_created:1;
+ unsigned int special_functions;
bool kbd_led_registered;
bool illumination_led_registered;
@@ -1668,10 +1669,10 @@ static ssize_t available_kbd_modes_show(struct device *dev,
struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
if (toshiba->kbd_type == 1)
- return sprintf(buf, "%x %x\n",
+ return sprintf(buf, "0x%x 0x%x\n",
SCI_KBD_MODE_FNZ, SCI_KBD_MODE_AUTO);
- return sprintf(buf, "%x %x %x\n",
+ return sprintf(buf, "0x%x 0x%x 0x%x\n",
SCI_KBD_MODE_AUTO, SCI_KBD_MODE_ON, SCI_KBD_MODE_OFF);
}
static DEVICE_ATTR_RO(available_kbd_modes);
@@ -2253,7 +2254,16 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = hci_write(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE);
+ /*
+ * Enable the "Special Functions" mode only if they are
+ * supported and if they are activated.
+ */
+ if (dev->kbd_function_keys_supported && dev->special_functions)
+ result = hci_write(dev, HCI_HOTKEY_EVENT,
+ HCI_HOTKEY_SPECIAL_FUNCTIONS);
+ else
+ result = hci_write(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE);
+
if (result == TOS_FAILURE)
return -EIO;
else if (result == TOS_NOT_SUPPORTED)
@@ -2262,20 +2272,6 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev)
return 0;
}
-static void toshiba_acpi_enable_special_functions(struct toshiba_acpi_dev *dev)
-{
- u32 result;
-
- /*
- * Re-activate the hotkeys, but this time, we are using the
- * "Special Functions" mode.
- */
- result = hci_write(dev, HCI_HOTKEY_EVENT,
- HCI_HOTKEY_SPECIAL_FUNCTIONS);
- if (result != TOS_SUCCESS)
- pr_err("Could not enable the Special Function mode\n");
-}
-
static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
@@ -2385,8 +2381,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
{
const struct key_entry *keymap = toshiba_acpi_keymap;
acpi_handle ec_handle;
- u32 events_type;
- u32 hci_result;
int error;
if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) {
@@ -2398,11 +2392,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
if (error)
return error;
- if (toshiba_hotkey_event_type_get(dev, &events_type))
+ if (toshiba_hotkey_event_type_get(dev, &dev->hotkey_event_type))
pr_notice("Unable to query Hotkey Event Type\n");
- dev->hotkey_event_type = events_type;
-
dev->hotkey_dev = input_allocate_device();
if (!dev->hotkey_dev)
return -ENOMEM;
@@ -2411,14 +2403,15 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
dev->hotkey_dev->phys = "toshiba_acpi/input0";
dev->hotkey_dev->id.bustype = BUS_HOST;
- if (events_type == HCI_SYSTEM_TYPE1 ||
+ if (dev->hotkey_event_type == HCI_SYSTEM_TYPE1 ||
!dev->kbd_function_keys_supported)
keymap = toshiba_acpi_keymap;
- else if (events_type == HCI_SYSTEM_TYPE2 ||
+ else if (dev->hotkey_event_type == HCI_SYSTEM_TYPE2 ||
dev->kbd_function_keys_supported)
keymap = toshiba_acpi_alt_keymap;
else
- pr_info("Unknown event type received %x\n", events_type);
+ pr_info("Unknown event type received %x\n",
+ dev->hotkey_event_type);
error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL);
if (error)
goto err_free_dev;
@@ -2449,11 +2442,8 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
*/
if (acpi_has_method(dev->acpi_dev->handle, "INFO"))
dev->info_supported = 1;
- else {
- hci_result = hci_write(dev, HCI_SYSTEM_EVENT, 1);
- if (hci_result == TOS_SUCCESS)
- dev->system_event_supported = 1;
- }
+ else if (hci_write(dev, HCI_SYSTEM_EVENT, 1) == TOS_SUCCESS)
+ dev->system_event_supported = 1;
if (!dev->info_supported && !dev->system_event_supported) {
pr_warn("No hotkey query interface found\n");
@@ -2631,7 +2621,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
{
struct toshiba_acpi_dev *dev;
const char *hci_method;
- u32 special_functions;
u32 dummy;
int ret = 0;
@@ -2673,9 +2662,10 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
* with the new keyboard layout, query for its presence to help
* determine the keymap layout to use.
*/
- ret = toshiba_function_keys_get(dev, &special_functions);
+ ret = toshiba_function_keys_get(dev, &dev->special_functions);
dev->kbd_function_keys_supported = !ret;
+ dev->hotkey_event_type = 0;
if (toshiba_acpi_setup_keyboard(dev))
pr_info("Unable to activate hotkeys\n");
@@ -2748,13 +2738,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
print_supported_features(dev);
- /*
- * Enable the "Special Functions" mode only if they are
- * supported and if they are activated.
- */
- if (dev->kbd_function_keys_supported && special_functions)
- toshiba_acpi_enable_special_functions(dev);
-
ret = sysfs_create_group(&dev->acpi_dev->dev.kobj,
&toshiba_attr_group);
if (ret) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 5153d1d69aee..9113876487ed 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -207,7 +207,7 @@ struct pnp_protocol pnpacpi_protocol = {
};
EXPORT_SYMBOL(pnpacpi_protocol);
-static char *__init pnpacpi_get_id(struct acpi_device *device)
+static const char *__init pnpacpi_get_id(struct acpi_device *device)
{
struct acpi_hardware_id *id;
@@ -222,7 +222,7 @@ static char *__init pnpacpi_get_id(struct acpi_device *device)
static int __init pnpacpi_add_device(struct acpi_device *device)
{
struct pnp_dev *dev;
- char *pnpid;
+ const char *pnpid;
struct acpi_hardware_id *id;
int error;
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
index d49579b227ec..63c57dc82ac1 100644
--- a/drivers/power/88pm860x_battery.c
+++ b/drivers/power/88pm860x_battery.c
@@ -954,47 +954,33 @@ static int pm860x_battery_probe(struct platform_device *pdev)
else
info->resistor = 300; /* set default internal resistor */
- info->battery = power_supply_register(&pdev->dev, &pm860x_battery_desc,
- NULL);
+ info->battery = devm_power_supply_register(&pdev->dev,
+ &pm860x_battery_desc,
+ NULL);
if (IS_ERR(info->battery))
return PTR_ERR(info->battery);
info->battery->dev.parent = &pdev->dev;
- ret = request_threaded_irq(info->irq_cc, NULL,
- pm860x_coulomb_handler, IRQF_ONESHOT,
- "coulomb", info);
+ ret = devm_request_threaded_irq(chip->dev, info->irq_cc, NULL,
+ pm860x_coulomb_handler, IRQF_ONESHOT,
+ "coulomb", info);
if (ret < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
info->irq_cc, ret);
- goto out_reg;
+ return ret;
}
- ret = request_threaded_irq(info->irq_batt, NULL, pm860x_batt_handler,
- IRQF_ONESHOT, "battery", info);
+ ret = devm_request_threaded_irq(chip->dev, info->irq_batt, NULL,
+ pm860x_batt_handler,
+ IRQF_ONESHOT, "battery", info);
if (ret < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
info->irq_batt, ret);
- goto out_coulomb;
+ return ret;
}
return 0;
-
-out_coulomb:
- free_irq(info->irq_cc, info);
-out_reg:
- power_supply_unregister(info->battery);
- return ret;
-}
-
-static int pm860x_battery_remove(struct platform_device *pdev)
-{
- struct pm860x_battery_info *info = platform_get_drvdata(pdev);
-
- free_irq(info->irq_batt, info);
- free_irq(info->irq_cc, info);
- power_supply_unregister(info->battery);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1028,7 +1014,6 @@ static struct platform_driver pm860x_battery_driver = {
.pm = &pm860x_battery_pm_ops,
},
.probe = pm860x_battery_probe,
- .remove = pm860x_battery_remove,
};
module_platform_driver(pm860x_battery_driver);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index f8758d6febf8..237d7aa73e8c 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -157,26 +157,25 @@ config BATTERY_SBS
Say Y to include support for SBS battery driver for SBS-compliant
gas gauges.
-config BATTERY_BQ27x00
- tristate "BQ27x00 battery driver"
- depends on I2C || I2C=n
+config BATTERY_BQ27XXX
+ tristate "BQ27xxx battery driver"
help
- Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
+ Say Y here to enable support for batteries with BQ27xxx (I2C/HDQ) chips.
-config BATTERY_BQ27X00_I2C
- bool "BQ27200/BQ27500 support"
- depends on BATTERY_BQ27x00
+config BATTERY_BQ27XXX_I2C
+ bool "BQ27xxx I2C support"
+ depends on BATTERY_BQ27XXX
depends on I2C
default y
help
- Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
+ Say Y here to enable support for batteries with BQ27xxx (I2C) chips.
-config BATTERY_BQ27X00_PLATFORM
- bool "BQ27000 support"
- depends on BATTERY_BQ27x00
+config BATTERY_BQ27XXX_PLATFORM
+ bool "BQ27xxx HDQ support"
+ depends on BATTERY_BQ27XXX
default y
help
- Say Y here to enable support for batteries with BQ27000 (HDQ) chips.
+ Say Y here to enable support for batteries with BQ27xxx (HDQ) chips.
config BATTERY_DA9030
tristate "DA9030 battery driver"
@@ -204,6 +203,16 @@ config CHARGER_DA9150
This driver can also be built as a module. If so, the module will be
called da9150-charger.
+config BATTERY_DA9150
+ tristate "Dialog Semiconductor DA9150 Fuel Gauge support"
+ depends on MFD_DA9150
+ help
+ Say Y here to enable support for the Fuel-Gauge unit of the DA9150
+ Integrated Charger & Fuel-Gauge IC
+
+ This driver can also be built as a module. If so, the module will be
+ called da9150-fg.
+
config AXP288_CHARGER
tristate "X-Powers AXP288 Charger"
depends on MFD_AXP20X && EXTCON_AXP288
@@ -313,7 +322,7 @@ config CHARGER_MAX8903
config CHARGER_TWL4030
tristate "OMAP TWL4030 BCI charger driver"
- depends on TWL4030_CORE
+ depends on IIO && TWL4030_CORE
help
Say Y here to enable support for TWL4030 Battery Charge Interface.
@@ -379,6 +388,18 @@ config CHARGER_MAX8998
Say Y to enable support for the battery charger control sysfs and
platform data of MAX8998/LP3974 PMICs.
+config CHARGER_QCOM_SMBB
+ tristate "Qualcomm Switch-Mode Battery Charger and Boost"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ depends on OF
+ help
+ Say Y to include support for the Switch-Mode Battery Charger and
+ Boost (SMBB) hardware found in Qualcomm PM8941 PMICs. The charger
+ is an integrated, single-cell lithium-ion battery charger. DT
+ configuration is required for loading, see the devicetree
+ documentation for more detail. The base name for this driver is
+ 'pm8941_charger'.
+
config CHARGER_BQ2415X
tristate "TI BQ2415x battery charger driver"
depends on I2C
@@ -397,12 +418,13 @@ config CHARGER_BQ24190
Say Y to enable support for the TI BQ24190 battery charger.
config CHARGER_BQ24257
- tristate "TI BQ24257 battery charger driver"
+ tristate "TI BQ24250/24251/24257 battery charger driver"
depends on I2C
depends on GPIOLIB || COMPILE_TEST
depends on REGMAP_I2C
help
- Say Y to enable support for the TI BQ24257 battery charger.
+ Say Y to enable support for the TI BQ24250, BQ24251, and BQ24257 battery
+ chargers.
config CHARGER_BQ24735
tristate "TI BQ24735 battery charger support"
@@ -434,6 +456,13 @@ config CHARGER_TPS65090
Say Y here to enable support for battery charging with TPS65090
PMIC chips.
+config CHARGER_TPS65217
+ tristate "TPS65217 battery charger driver"
+ depends on MFD_TPS65217
+ help
+ Say Y here to enable support for battery charging with TPS65217
+ PMIC chips.
+
config BATTERY_GAUGE_LTC2941
tristate "LTC2941/LTC2943 Battery Gauge Driver"
depends on I2C
@@ -472,6 +501,13 @@ config CHARGER_RT9455
help
Say Y to enable support for Richtek RT9455 battery charger.
+config AXP20X_POWER
+ tristate "AXP20x power supply driver"
+ depends on MFD_AXP20X
+ help
+ This driver provides support for the power supply features of
+ AXP20x PMIC.
+
source "drivers/power/reset/Kconfig"
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 5752ce818f51..b656638f8b39 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o
obj-$(CONFIG_PDA_POWER) += pda_power.o
obj-$(CONFIG_APM_POWER) += apm_power.o
+obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o
obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
@@ -29,10 +30,11 @@ obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
-obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
+obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o
+obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
@@ -57,6 +59,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
+obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o
obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o
@@ -65,6 +68,7 @@ obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
+obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
obj-$(CONFIG_POWER_RESET) += reset/
obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o
diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c
index 2e300028f0f7..80994566a1c8 100644
--- a/drivers/power/avs/rockchip-io-domain.c
+++ b/drivers/power/avs/rockchip-io-domain.c
@@ -271,6 +271,7 @@ static const struct of_device_id rockchip_iodomain_match[] = {
},
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
static int rockchip_iodomain_probe(struct platform_device *pdev)
{
diff --git a/drivers/power/axp20x_usb_power.c b/drivers/power/axp20x_usb_power.c
new file mode 100644
index 000000000000..421a90b83567
--- /dev/null
+++ b/drivers/power/axp20x_usb_power.c
@@ -0,0 +1,248 @@
+/*
+ * AXP20x PMIC USB power supply status driver
+ *
+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.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.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define DRVNAME "axp20x-usb-power-supply"
+
+#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5)
+#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
+
+#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
+
+#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000)
+#define AXP20X_VBUS_CLIMIT_MASK 3
+#define AXP20X_VBUC_CLIMIT_900mA 0
+#define AXP20X_VBUC_CLIMIT_500mA 1
+#define AXP20X_VBUC_CLIMIT_100mA 2
+#define AXP20X_VBUC_CLIMIT_NONE 3
+
+#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
+#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
+
+#define AXP20X_VBUS_MON_VBUS_VALID BIT(3)
+
+struct axp20x_usb_power {
+ struct regmap *regmap;
+ struct power_supply *supply;
+};
+
+static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
+{
+ struct axp20x_usb_power *power = devid;
+
+ power_supply_changed(power->supply);
+
+ return IRQ_HANDLED;
+}
+
+static int axp20x_usb_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp, union power_supply_propval *val)
+{
+ struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
+ unsigned int input, v;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
+ if (ret)
+ return ret;
+
+ val->intval = AXP20X_VBUS_VHOLD_uV(v);
+ return 0;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = axp20x_read_variable_width(power->regmap,
+ AXP20X_VBUS_V_ADC_H, 12);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 1700; /* 1 step = 1.7 mV */
+ return 0;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
+ if (ret)
+ return ret;
+
+ switch (v & AXP20X_VBUS_CLIMIT_MASK) {
+ case AXP20X_VBUC_CLIMIT_100mA:
+ val->intval = 100000;
+ break;
+ case AXP20X_VBUC_CLIMIT_500mA:
+ val->intval = 500000;
+ break;
+ case AXP20X_VBUC_CLIMIT_900mA:
+ val->intval = 900000;
+ break;
+ case AXP20X_VBUC_CLIMIT_NONE:
+ val->intval = -1;
+ break;
+ }
+ return 0;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = axp20x_read_variable_width(power->regmap,
+ AXP20X_VBUS_I_ADC_H, 12);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 375; /* 1 step = 0.375 mA */
+ return 0;
+ default:
+ break;
+ }
+
+ /* All the properties below need the input-status reg value */
+ ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
+ if (ret)
+ return ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+ break;
+ }
+
+ ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v);
+ if (ret)
+ return ret;
+
+ if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) {
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+ }
+
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property axp20x_usb_power_properties[] = {
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+static const struct power_supply_desc axp20x_usb_power_desc = {
+ .name = "axp20x-usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = axp20x_usb_power_properties,
+ .num_properties = ARRAY_SIZE(axp20x_usb_power_properties),
+ .get_property = axp20x_usb_power_get_property,
+};
+
+static int axp20x_usb_power_probe(struct platform_device *pdev)
+{
+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+ struct power_supply_config psy_cfg = {};
+ struct axp20x_usb_power *power;
+ static const char * const irq_names[] = { "VBUS_PLUGIN",
+ "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" };
+ int i, irq, ret;
+
+ if (!of_device_is_available(pdev->dev.of_node))
+ return -ENODEV;
+
+ if (!axp20x) {
+ dev_err(&pdev->dev, "Parent drvdata not set\n");
+ return -EINVAL;
+ }
+
+ power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);
+ if (!power)
+ return -ENOMEM;
+
+ power->regmap = axp20x->regmap;
+
+ /* Enable vbus valid checking */
+ ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
+ AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID);
+ if (ret)
+ return ret;
+
+ /* Enable vbus voltage and current measurement */
+ ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
+ AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT,
+ AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT);
+ if (ret)
+ return ret;
+
+ psy_cfg.of_node = pdev->dev.of_node;
+ psy_cfg.drv_data = power;
+
+ power->supply = devm_power_supply_register(&pdev->dev,
+ &axp20x_usb_power_desc, &psy_cfg);
+ if (IS_ERR(power->supply))
+ return PTR_ERR(power->supply);
+
+ /* Request irqs after registering, as irqs may trigger immediately */
+ for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
+ irq = platform_get_irq_byname(pdev, irq_names[i]);
+ if (irq < 0) {
+ dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
+ irq_names[i], irq);
+ continue;
+ }
+ irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
+ ret = devm_request_any_context_irq(&pdev->dev, irq,
+ axp20x_usb_power_irq, 0, DRVNAME, power);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n",
+ irq_names[i], ret);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id axp20x_usb_power_match[] = {
+ { .compatible = "x-powers,axp202-usb-power-supply" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);
+
+static struct platform_driver axp20x_usb_power_driver = {
+ .probe = axp20x_usb_power_probe,
+ .driver = {
+ .name = DRVNAME,
+ .of_match_table = axp20x_usb_power_match,
+ },
+};
+
+module_platform_driver(axp20x_usb_power_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index ec212b5be755..4afd76848bce 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1704,7 +1704,7 @@ error_4:
error_3:
bq2415x_power_supply_exit(bq);
error_2:
- if (bq->notify_node)
+ if (bq && bq->notify_node)
of_node_put(bq->notify_node);
kfree(name);
error_1:
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c
index 469a452cbe10..f5746b9f4e83 100644
--- a/drivers/power/bq24190_charger.c
+++ b/drivers/power/bq24190_charger.c
@@ -1543,5 +1543,4 @@ module_i2c_driver(bq24190_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
-MODULE_ALIAS("i2c:bq24190-charger");
MODULE_DESCRIPTION("TI BQ24190 Charger Driver");
diff --git a/drivers/power/bq24257_charger.c b/drivers/power/bq24257_charger.c
index 5859bc7c1616..1fea2c7ef97f 100644
--- a/drivers/power/bq24257_charger.c
+++ b/drivers/power/bq24257_charger.c
@@ -13,6 +13,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ * Datasheets:
+ * http://www.ti.com/product/bq24250
+ * http://www.ti.com/product/bq24251
+ * http://www.ti.com/product/bq24257
*/
#include <linux/module.h>
@@ -36,18 +40,33 @@
#define BQ24257_REG_7 0x06
#define BQ24257_MANUFACTURER "Texas Instruments"
-#define BQ24257_STAT_IRQ "stat"
#define BQ24257_PG_GPIO "pg"
#define BQ24257_ILIM_SET_DELAY 1000 /* msec */
+/*
+ * When adding support for new devices make sure that enum bq2425x_chip and
+ * bq2425x_chip_name[] always stay in sync!
+ */
+enum bq2425x_chip {
+ BQ24250,
+ BQ24251,
+ BQ24257,
+};
+
+static const char *const bq2425x_chip_name[] = {
+ "bq24250",
+ "bq24251",
+ "bq24257",
+};
+
enum bq24257_fields {
F_WD_FAULT, F_WD_EN, F_STAT, F_FAULT, /* REG 1 */
F_RESET, F_IILIMIT, F_EN_STAT, F_EN_TERM, F_CE, F_HZ_MODE, /* REG 2 */
F_VBAT, F_USB_DET, /* REG 3 */
F_ICHG, F_ITERM, /* REG 4 */
F_LOOP_STATUS, F_LOW_CHG, F_DPDM_EN, F_CE_STATUS, F_VINDPM, /* REG 5 */
- F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_STAT, /* REG 6 */
+ F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_EN, F_TS_STAT, /* REG 6 */
F_VOVP, F_CLR_VDP, F_FORCE_BATDET, F_FORCE_PTM, /* REG 7 */
F_MAX_FIELDS
@@ -58,6 +77,9 @@ struct bq24257_init_data {
u8 ichg; /* charge current */
u8 vbat; /* regulation voltage */
u8 iterm; /* termination current */
+ u8 iilimit; /* input current limit */
+ u8 vovp; /* over voltage protection voltage */
+ u8 vindpm; /* VDMP input threshold voltage */
};
struct bq24257_state {
@@ -71,6 +93,8 @@ struct bq24257_device {
struct device *dev;
struct power_supply *charger;
+ enum bq2425x_chip chip;
+
struct regmap *rmap;
struct regmap_field *rmap_fields[F_MAX_FIELDS];
@@ -82,6 +106,8 @@ struct bq24257_device {
struct bq24257_state state;
struct mutex lock; /* protect state data */
+
+ bool iilimit_autoset_enable;
};
static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg)
@@ -135,6 +161,7 @@ static const struct reg_field bq24257_reg_fields[] = {
[F_X2_TMR_EN] = REG_FIELD(BQ24257_REG_6, 7, 7),
[F_TMR] = REG_FIELD(BQ24257_REG_6, 5, 6),
[F_SYSOFF] = REG_FIELD(BQ24257_REG_6, 4, 4),
+ [F_TS_EN] = REG_FIELD(BQ24257_REG_6, 3, 3),
[F_TS_STAT] = REG_FIELD(BQ24257_REG_6, 0, 2),
/* REG 7 */
[F_VOVP] = REG_FIELD(BQ24257_REG_7, 5, 7),
@@ -169,6 +196,26 @@ static const u32 bq24257_iterm_map[] = {
#define BQ24257_ITERM_MAP_SIZE ARRAY_SIZE(bq24257_iterm_map)
+static const u32 bq24257_iilimit_map[] = {
+ 100000, 150000, 500000, 900000, 1500000, 2000000
+};
+
+#define BQ24257_IILIMIT_MAP_SIZE ARRAY_SIZE(bq24257_iilimit_map)
+
+static const u32 bq24257_vovp_map[] = {
+ 6000000, 6500000, 7000000, 8000000, 9000000, 9500000, 10000000,
+ 10500000
+};
+
+#define BQ24257_VOVP_MAP_SIZE ARRAY_SIZE(bq24257_vovp_map)
+
+static const u32 bq24257_vindpm_map[] = {
+ 4200000, 4280000, 4360000, 4440000, 4520000, 4600000, 4680000,
+ 4760000
+};
+
+#define BQ24257_VINDPM_MAP_SIZE ARRAY_SIZE(bq24257_vindpm_map)
+
static int bq24257_field_read(struct bq24257_device *bq,
enum bq24257_fields field_id)
{
@@ -220,6 +267,47 @@ enum bq24257_fault {
FAULT_INPUT_LDO_LOW,
};
+static int bq24257_get_input_current_limit(struct bq24257_device *bq,
+ union power_supply_propval *val)
+{
+ int ret;
+
+ ret = bq24257_field_read(bq, F_IILIMIT);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The "External ILIM" and "Production & Test" modes are not exposed
+ * through this driver and not being covered by the lookup table.
+ * Should such a mode have become active let's return an error rather
+ * than exceeding the bounds of the lookup table and returning
+ * garbage.
+ */
+ if (ret >= BQ24257_IILIMIT_MAP_SIZE)
+ return -ENODATA;
+
+ val->intval = bq24257_iilimit_map[ret];
+
+ return 0;
+}
+
+static int bq24257_set_input_current_limit(struct bq24257_device *bq,
+ const union power_supply_propval *val)
+{
+ /*
+ * Address the case where the user manually sets an input current limit
+ * while the charger auto-detection mechanism is is active. In this
+ * case we want to abort and go straight to the user-specified value.
+ */
+ if (bq->iilimit_autoset_enable)
+ cancel_delayed_work_sync(&bq->iilimit_setup_work);
+
+ return bq24257_field_write(bq, F_IILIMIT,
+ bq24257_find_idx(val->intval,
+ bq24257_iilimit_map,
+ BQ24257_IILIMIT_MAP_SIZE));
+}
+
static int bq24257_power_supply_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -249,6 +337,10 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
val->strval = BQ24257_MANUFACTURER;
break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = bq2425x_chip_name[bq->chip];
+ break;
+
case POWER_SUPPLY_PROP_ONLINE:
val->intval = state.power_good;
break;
@@ -300,6 +392,9 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
val->intval = bq24257_iterm_map[bq->init_data.iterm];
break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return bq24257_get_input_current_limit(bq, val);
+
default:
return -EINVAL;
}
@@ -307,6 +402,31 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
return 0;
}
+static int bq24257_power_supply_set_property(struct power_supply *psy,
+ enum power_supply_property prop,
+ const union power_supply_propval *val)
+{
+ struct bq24257_device *bq = power_supply_get_drvdata(psy);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return bq24257_set_input_current_limit(bq, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bq24257_power_supply_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int bq24257_get_chip_state(struct bq24257_device *bq,
struct bq24257_state *state)
{
@@ -324,7 +444,26 @@ static int bq24257_get_chip_state(struct bq24257_device *bq,
state->fault = ret;
- state->power_good = !gpiod_get_value_cansleep(bq->pg);
+ if (bq->pg)
+ state->power_good = !gpiod_get_value_cansleep(bq->pg);
+ else
+ /*
+ * If we have a chip without a dedicated power-good GPIO or
+ * some other explicit bit that would provide this information
+ * assume the power is good if there is no supply related
+ * fault - and not good otherwise. There is a possibility for
+ * other errors to mask that power in fact is not good but this
+ * is probably the best we can do here.
+ */
+ switch (state->fault) {
+ case FAULT_INPUT_OVP:
+ case FAULT_INPUT_UVLO:
+ case FAULT_INPUT_LDO_LOW:
+ state->power_good = false;
+ break;
+ default:
+ state->power_good = true;
+ }
return 0;
}
@@ -361,6 +500,28 @@ enum bq24257_in_ilimit {
IILIMIT_NONE,
};
+enum bq24257_vovp {
+ VOVP_6000,
+ VOVP_6500,
+ VOVP_7000,
+ VOVP_8000,
+ VOVP_9000,
+ VOVP_9500,
+ VOVP_10000,
+ VOVP_10500
+};
+
+enum bq24257_vindpm {
+ VINDPM_4200,
+ VINDPM_4280,
+ VINDPM_4360,
+ VINDPM_4440,
+ VINDPM_4520,
+ VINDPM_4600,
+ VINDPM_4680,
+ VINDPM_4760
+};
+
enum bq24257_port_type {
PORT_TYPE_DCP, /* Dedicated Charging Port */
PORT_TYPE_CDP, /* Charging Downstream Port */
@@ -449,41 +610,43 @@ static void bq24257_handle_state_change(struct bq24257_device *bq,
{
int ret;
struct bq24257_state old_state;
- bool reset_iilimit = false;
- bool config_iilimit = false;
mutex_lock(&bq->lock);
old_state = bq->state;
mutex_unlock(&bq->lock);
- if (!new_state->power_good) { /* power removed */
- cancel_delayed_work_sync(&bq->iilimit_setup_work);
-
- /* activate D+/D- port detection algorithm */
- ret = bq24257_field_write(bq, F_DPDM_EN, 1);
+ /*
+ * Handle BQ2425x state changes observing whether the D+/D- based input
+ * current limit autoset functionality is enabled.
+ */
+ if (!new_state->power_good) {
+ dev_dbg(bq->dev, "Power removed\n");
+ if (bq->iilimit_autoset_enable) {
+ cancel_delayed_work_sync(&bq->iilimit_setup_work);
+
+ /* activate D+/D- port detection algorithm */
+ ret = bq24257_field_write(bq, F_DPDM_EN, 1);
+ if (ret < 0)
+ goto error;
+ }
+ /*
+ * When power is removed always return to the default input
+ * current limit as configured during probe.
+ */
+ ret = bq24257_field_write(bq, F_IILIMIT, bq->init_data.iilimit);
if (ret < 0)
goto error;
+ } else if (!old_state.power_good) {
+ dev_dbg(bq->dev, "Power inserted\n");
- reset_iilimit = true;
- } else if (!old_state.power_good) { /* power inserted */
- config_iilimit = true;
- } else if (new_state->fault == FAULT_NO_BAT) { /* battery removed */
- cancel_delayed_work_sync(&bq->iilimit_setup_work);
-
- reset_iilimit = true;
- } else if (old_state.fault == FAULT_NO_BAT) { /* battery connected */
- config_iilimit = true;
- } else if (new_state->fault == FAULT_TIMER) { /* safety timer expired */
- dev_err(bq->dev, "Safety timer expired! Battery dead?\n");
- }
-
- if (reset_iilimit) {
- ret = bq24257_field_write(bq, F_IILIMIT, IILIMIT_500);
- if (ret < 0)
- goto error;
- } else if (config_iilimit) {
- schedule_delayed_work(&bq->iilimit_setup_work,
+ if (bq->iilimit_autoset_enable)
+ /* configure input current limit */
+ schedule_delayed_work(&bq->iilimit_setup_work,
msecs_to_jiffies(BQ24257_ILIM_SET_DELAY));
+ } else if (new_state->fault == FAULT_NO_BAT) {
+ dev_warn(bq->dev, "Battery removed\n");
+ } else if (new_state->fault == FAULT_TIMER) {
+ dev_err(bq->dev, "Safety timer expired! Battery dead?\n");
}
return;
@@ -531,7 +694,9 @@ static int bq24257_hw_init(struct bq24257_device *bq)
} init_data[] = {
{F_ICHG, bq->init_data.ichg},
{F_VBAT, bq->init_data.vbat},
- {F_ITERM, bq->init_data.iterm}
+ {F_ITERM, bq->init_data.iterm},
+ {F_VOVP, bq->init_data.vovp},
+ {F_VINDPM, bq->init_data.vindpm},
};
/*
@@ -558,7 +723,16 @@ static int bq24257_hw_init(struct bq24257_device *bq)
bq->state = state;
mutex_unlock(&bq->lock);
- if (!state.power_good)
+ if (!bq->iilimit_autoset_enable) {
+ dev_dbg(bq->dev, "manually setting iilimit = %u\n",
+ bq->init_data.iilimit);
+
+ /* program fixed input current limit */
+ ret = bq24257_field_write(bq, F_IILIMIT,
+ bq->init_data.iilimit);
+ if (ret < 0)
+ return ret;
+ } else if (!state.power_good)
/* activate D+/D- detection algorithm */
ret = bq24257_field_write(bq, F_DPDM_EN, 1);
else if (state.fault != FAULT_NO_BAT)
@@ -569,6 +743,7 @@ static int bq24257_hw_init(struct bq24257_device *bq)
static enum power_supply_property bq24257_power_supply_props[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_HEALTH,
@@ -577,6 +752,7 @@ static enum power_supply_property bq24257_power_supply_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
static char *bq24257_charger_supplied_to[] = {
@@ -589,45 +765,127 @@ static const struct power_supply_desc bq24257_power_supply_desc = {
.properties = bq24257_power_supply_props,
.num_properties = ARRAY_SIZE(bq24257_power_supply_props),
.get_property = bq24257_power_supply_get_property,
+ .set_property = bq24257_power_supply_set_property,
+ .property_is_writeable = bq24257_power_supply_property_is_writeable,
};
-static int bq24257_power_supply_init(struct bq24257_device *bq)
+static ssize_t bq24257_show_ovp_voltage(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct power_supply_config psy_cfg = { .drv_data = bq, };
+ struct power_supply *psy = dev_get_drvdata(dev);
+ struct bq24257_device *bq = power_supply_get_drvdata(psy);
- psy_cfg.supplied_to = bq24257_charger_supplied_to;
- psy_cfg.num_supplicants = ARRAY_SIZE(bq24257_charger_supplied_to);
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ bq24257_vovp_map[bq->init_data.vovp]);
+}
- bq->charger = power_supply_register(bq->dev, &bq24257_power_supply_desc,
- &psy_cfg);
- if (IS_ERR(bq->charger))
- return PTR_ERR(bq->charger);
+static ssize_t bq24257_show_in_dpm_voltage(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct power_supply *psy = dev_get_drvdata(dev);
+ struct bq24257_device *bq = power_supply_get_drvdata(psy);
- return 0;
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ bq24257_vindpm_map[bq->init_data.vindpm]);
}
-static int bq24257_irq_probe(struct bq24257_device *bq)
+static ssize_t bq24257_sysfs_show_enable(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct gpio_desc *stat_irq;
+ struct power_supply *psy = dev_get_drvdata(dev);
+ struct bq24257_device *bq = power_supply_get_drvdata(psy);
+ int ret;
- stat_irq = devm_gpiod_get_index(bq->dev, BQ24257_STAT_IRQ, 0, GPIOD_IN);
- if (IS_ERR(stat_irq)) {
- dev_err(bq->dev, "could not probe stat_irq pin\n");
- return PTR_ERR(stat_irq);
- }
+ if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
+ ret = bq24257_field_read(bq, F_HZ_MODE);
+ else if (strcmp(attr->attr.name, "sysoff_enable") == 0)
+ ret = bq24257_field_read(bq, F_SYSOFF);
+ else
+ return -EINVAL;
- return gpiod_to_irq(stat_irq);
+ if (ret < 0)
+ return ret;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
}
-static int bq24257_pg_gpio_probe(struct bq24257_device *bq)
+static ssize_t bq24257_sysfs_set_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
{
- bq->pg = devm_gpiod_get_index(bq->dev, BQ24257_PG_GPIO, 0, GPIOD_IN);
- if (IS_ERR(bq->pg)) {
- dev_err(bq->dev, "could not probe PG pin\n");
- return PTR_ERR(bq->pg);
+ struct power_supply *psy = dev_get_drvdata(dev);
+ struct bq24257_device *bq = power_supply_get_drvdata(psy);
+ long val;
+ int ret;
+
+ if (kstrtol(buf, 10, &val) < 0)
+ return -EINVAL;
+
+ if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
+ ret = bq24257_field_write(bq, F_HZ_MODE, (bool)val);
+ else if (strcmp(attr->attr.name, "sysoff_enable") == 0)
+ ret = bq24257_field_write(bq, F_SYSOFF, (bool)val);
+ else
+ return -EINVAL;
+
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(ovp_voltage, S_IRUGO, bq24257_show_ovp_voltage, NULL);
+static DEVICE_ATTR(in_dpm_voltage, S_IRUGO, bq24257_show_in_dpm_voltage, NULL);
+static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO,
+ bq24257_sysfs_show_enable, bq24257_sysfs_set_enable);
+static DEVICE_ATTR(sysoff_enable, S_IWUSR | S_IRUGO,
+ bq24257_sysfs_show_enable, bq24257_sysfs_set_enable);
+
+static struct attribute *bq24257_charger_attr[] = {
+ &dev_attr_ovp_voltage.attr,
+ &dev_attr_in_dpm_voltage.attr,
+ &dev_attr_high_impedance_enable.attr,
+ &dev_attr_sysoff_enable.attr,
+ NULL,
+};
+
+static const struct attribute_group bq24257_attr_group = {
+ .attrs = bq24257_charger_attr,
+};
+
+static int bq24257_power_supply_init(struct bq24257_device *bq)
+{
+ struct power_supply_config psy_cfg = { .drv_data = bq, };
+
+ psy_cfg.supplied_to = bq24257_charger_supplied_to;
+ psy_cfg.num_supplicants = ARRAY_SIZE(bq24257_charger_supplied_to);
+
+ bq->charger = devm_power_supply_register(bq->dev,
+ &bq24257_power_supply_desc,
+ &psy_cfg);
+
+ return PTR_ERR_OR_ZERO(bq->charger);
+}
+
+static void bq24257_pg_gpio_probe(struct bq24257_device *bq)
+{
+ bq->pg = devm_gpiod_get_optional(bq->dev, BQ24257_PG_GPIO, GPIOD_IN);
+
+ if (PTR_ERR(bq->pg) == -EPROBE_DEFER) {
+ dev_info(bq->dev, "probe retry requested for PG pin\n");
+ return;
+ } else if (IS_ERR(bq->pg)) {
+ dev_err(bq->dev, "error probing PG pin\n");
+ bq->pg = NULL;
+ return;
}
- return 0;
+ if (bq->pg)
+ dev_dbg(bq->dev, "probed PG pin = %d\n", desc_to_gpio(bq->pg));
}
static int bq24257_fw_probe(struct bq24257_device *bq)
@@ -635,6 +893,7 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
int ret;
u32 property;
+ /* Required properties */
ret = device_property_read_u32(bq->dev, "ti,charge-current", &property);
if (ret < 0)
return ret;
@@ -658,6 +917,43 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
bq->init_data.iterm = bq24257_find_idx(property, bq24257_iterm_map,
BQ24257_ITERM_MAP_SIZE);
+ /* Optional properties. If not provided use reasonable default. */
+ ret = device_property_read_u32(bq->dev, "ti,current-limit",
+ &property);
+ if (ret < 0) {
+ bq->iilimit_autoset_enable = true;
+
+ /*
+ * Explicitly set a default value which will be needed for
+ * devices that don't support the automatic setting of the input
+ * current limit through the charger type detection mechanism.
+ */
+ bq->init_data.iilimit = IILIMIT_500;
+ } else
+ bq->init_data.iilimit =
+ bq24257_find_idx(property,
+ bq24257_iilimit_map,
+ BQ24257_IILIMIT_MAP_SIZE);
+
+ ret = device_property_read_u32(bq->dev, "ti,ovp-voltage",
+ &property);
+ if (ret < 0)
+ bq->init_data.vovp = VOVP_6500;
+ else
+ bq->init_data.vovp = bq24257_find_idx(property,
+ bq24257_vovp_map,
+ BQ24257_VOVP_MAP_SIZE);
+
+ ret = device_property_read_u32(bq->dev, "ti,in-dpm-voltage",
+ &property);
+ if (ret < 0)
+ bq->init_data.vindpm = VINDPM_4360;
+ else
+ bq->init_data.vindpm =
+ bq24257_find_idx(property,
+ bq24257_vindpm_map,
+ BQ24257_VINDPM_MAP_SIZE);
+
return 0;
}
@@ -666,6 +962,7 @@ static int bq24257_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct device *dev = &client->dev;
+ const struct acpi_device_id *acpi_id;
struct bq24257_device *bq;
int ret;
int i;
@@ -682,6 +979,18 @@ static int bq24257_probe(struct i2c_client *client,
bq->client = client;
bq->dev = dev;
+ if (ACPI_HANDLE(dev)) {
+ acpi_id = acpi_match_device(dev->driver->acpi_match_table,
+ &client->dev);
+ if (!acpi_id) {
+ dev_err(dev, "Failed to match ACPI device\n");
+ return -ENODEV;
+ }
+ bq->chip = (enum bq2425x_chip)acpi_id->driver_data;
+ } else {
+ bq->chip = (enum bq2425x_chip)id->driver_data;
+ }
+
mutex_init(&bq->lock);
bq->rmap = devm_regmap_init_i2c(client, &bq24257_regmap_config);
@@ -703,8 +1012,6 @@ static int bq24257_probe(struct i2c_client *client,
i2c_set_clientdata(client, bq);
- INIT_DELAYED_WORK(&bq->iilimit_setup_work, bq24257_iilimit_setup_work);
-
if (!dev->platform_data) {
ret = bq24257_fw_probe(bq);
if (ret < 0) {
@@ -715,10 +1022,31 @@ static int bq24257_probe(struct i2c_client *client,
return -ENODEV;
}
- /* we can only check Power Good status by probing the PG pin */
- ret = bq24257_pg_gpio_probe(bq);
- if (ret < 0)
- return ret;
+ /*
+ * The BQ24250 doesn't support the D+/D- based charger type detection
+ * used for the automatic setting of the input current limit setting so
+ * explicitly disable that feature.
+ */
+ if (bq->chip == BQ24250)
+ bq->iilimit_autoset_enable = false;
+
+ if (bq->iilimit_autoset_enable)
+ INIT_DELAYED_WORK(&bq->iilimit_setup_work,
+ bq24257_iilimit_setup_work);
+
+ /*
+ * The BQ24250 doesn't have a dedicated Power Good (PG) pin so let's
+ * not probe for it and instead use a SW-based approach to determine
+ * the PG state. We also use a SW-based approach for all other devices
+ * if the PG pin is either not defined or can't be probed.
+ */
+ if (bq->chip != BQ24250)
+ bq24257_pg_gpio_probe(bq);
+
+ if (PTR_ERR(bq->pg) == -EPROBE_DEFER)
+ return PTR_ERR(bq->pg);
+ else if (!bq->pg)
+ dev_info(bq->dev, "using SW-based power-good detection\n");
/* reset all registers to defaults */
ret = bq24257_field_write(bq, F_RESET, 1);
@@ -740,36 +1068,39 @@ static int bq24257_probe(struct i2c_client *client,
return ret;
}
- if (client->irq <= 0)
- client->irq = bq24257_irq_probe(bq);
-
- if (client->irq < 0) {
- dev_err(dev, "no irq resource found\n");
- return client->irq;
- }
-
ret = devm_request_threaded_irq(dev, client->irq, NULL,
bq24257_irq_handler_thread,
IRQF_TRIGGER_FALLING |
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- BQ24257_STAT_IRQ, bq);
- if (ret)
+ bq2425x_chip_name[bq->chip], bq);
+ if (ret) {
+ dev_err(dev, "Failed to request IRQ #%d\n", client->irq);
return ret;
+ }
ret = bq24257_power_supply_init(bq);
- if (ret < 0)
+ if (ret < 0) {
dev_err(dev, "Failed to register power supply\n");
+ return ret;
+ }
- return ret;
+ ret = sysfs_create_group(&bq->charger->dev.kobj, &bq24257_attr_group);
+ if (ret < 0) {
+ dev_err(dev, "Can't create sysfs entries\n");
+ return ret;
+ }
+
+ return 0;
}
static int bq24257_remove(struct i2c_client *client)
{
struct bq24257_device *bq = i2c_get_clientdata(client);
- cancel_delayed_work_sync(&bq->iilimit_setup_work);
+ if (bq->iilimit_autoset_enable)
+ cancel_delayed_work_sync(&bq->iilimit_setup_work);
- power_supply_unregister(bq->charger);
+ sysfs_remove_group(&bq->charger->dev.kobj, &bq24257_attr_group);
bq24257_field_write(bq, F_RESET, 1); /* reset to defaults */
@@ -782,7 +1113,8 @@ static int bq24257_suspend(struct device *dev)
struct bq24257_device *bq = dev_get_drvdata(dev);
int ret = 0;
- cancel_delayed_work_sync(&bq->iilimit_setup_work);
+ if (bq->iilimit_autoset_enable)
+ cancel_delayed_work_sync(&bq->iilimit_setup_work);
/* reset all registers to default (and activate standalone mode) */
ret = bq24257_field_write(bq, F_RESET, 1);
@@ -823,19 +1155,25 @@ static const struct dev_pm_ops bq24257_pm = {
};
static const struct i2c_device_id bq24257_i2c_ids[] = {
- { "bq24257", 0 },
+ { "bq24250", BQ24250 },
+ { "bq24251", BQ24251 },
+ { "bq24257", BQ24257 },
{},
};
MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids);
static const struct of_device_id bq24257_of_match[] = {
+ { .compatible = "ti,bq24250", },
+ { .compatible = "ti,bq24251", },
{ .compatible = "ti,bq24257", },
{ },
};
MODULE_DEVICE_TABLE(of, bq24257_of_match);
static const struct acpi_device_id bq24257_acpi_match[] = {
- {"BQ242570", 0},
+ { "BQ242500", BQ24250 },
+ { "BQ242510", BQ24251 },
+ { "BQ242570", BQ24257 },
{},
};
MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match);
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
deleted file mode 100644
index 8287261fd978..000000000000
--- a/drivers/power/bq27x00_battery.c
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * BQ27x00 battery driver
- *
- * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
- * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
- * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
- * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com>
- *
- * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
- *
- * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Datasheets:
- * http://focus.ti.com/docs/prod/folders/print/bq27000.html
- * http://focus.ti.com/docs/prod/folders/print/bq27500.html
- * http://www.ti.com/product/bq27425-g1
- * http://www.ti.com/product/BQ27742-G1
- * http://www.ti.com/product/BQ27510-G3
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/idr.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-
-#include <linux/power/bq27x00_battery.h>
-
-#define DRIVER_VERSION "1.2.0"
-
-#define BQ27XXX_MANUFACTURER "Texas Instruments"
-
-#define BQ27x00_REG_TEMP 0x06
-#define BQ27x00_REG_VOLT 0x08
-#define BQ27x00_REG_AI 0x14
-#define BQ27x00_REG_FLAGS 0x0A
-#define BQ27x00_REG_TTE 0x16
-#define BQ27x00_REG_TTF 0x18
-#define BQ27x00_REG_TTECP 0x26
-#define BQ27x00_REG_NAC 0x0C /* Nominal available capacity */
-#define BQ27x00_REG_LMD 0x12 /* Last measured discharge */
-#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */
-#define BQ27x00_REG_AE 0x22 /* Available energy */
-#define BQ27x00_POWER_AVG 0x24
-
-#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
-#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */
-#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */
-#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */
-#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */
-#define BQ27000_FLAG_FC BIT(5)
-#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
-
-#define BQ27500_REG_SOC 0x2C
-#define BQ27500_REG_DCAP 0x3C /* Design capacity */
-#define BQ27500_FLAG_DSC BIT(0)
-#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
-#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
-#define BQ27500_FLAG_FC BIT(9)
-#define BQ27500_FLAG_OTC BIT(15)
-
-#define BQ27742_POWER_AVG 0x76
-
-#define BQ27510_REG_SOC 0x20
-#define BQ27510_REG_DCAP 0x2E /* Design capacity */
-#define BQ27510_REG_CYCT 0x1E /* Cycle count total */
-
-/* bq27425 register addresses are same as bq27x00 addresses minus 4 */
-#define BQ27425_REG_OFFSET 0x04
-#define BQ27425_REG_SOC (0x1C + BQ27425_REG_OFFSET)
-#define BQ27425_REG_DCAP (0x3C + BQ27425_REG_OFFSET)
-
-#define BQ27000_RS 20 /* Resistor sense */
-#define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000)
-
-struct bq27x00_device_info;
-struct bq27x00_access_methods {
- int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
-};
-
-enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510};
-
-struct bq27x00_reg_cache {
- int temperature;
- int time_to_empty;
- int time_to_empty_avg;
- int time_to_full;
- int charge_full;
- int cycle_count;
- int capacity;
- int energy;
- int flags;
- int power_avg;
- int health;
-};
-
-struct bq27x00_device_info {
- struct device *dev;
- int id;
- enum bq27x00_chip chip;
-
- struct bq27x00_reg_cache cache;
- int charge_design_full;
-
- unsigned long last_update;
- struct delayed_work work;
-
- struct power_supply *bat;
-
- struct bq27x00_access_methods bus;
-
- struct mutex lock;
-};
-
-static enum power_supply_property bq27x00_battery_props[] = {
- POWER_SUPPLY_PROP_STATUS,
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CAPACITY_LEVEL,
- POWER_SUPPLY_PROP_TEMP,
- POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
- POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
- POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
- POWER_SUPPLY_PROP_TECHNOLOGY,
- POWER_SUPPLY_PROP_CHARGE_FULL,
- POWER_SUPPLY_PROP_CHARGE_NOW,
- POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
- POWER_SUPPLY_PROP_CYCLE_COUNT,
- POWER_SUPPLY_PROP_ENERGY_NOW,
- POWER_SUPPLY_PROP_POWER_AVG,
- POWER_SUPPLY_PROP_HEALTH,
- POWER_SUPPLY_PROP_MANUFACTURER,
-};
-
-static enum power_supply_property bq27425_battery_props[] = {
- POWER_SUPPLY_PROP_STATUS,
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CAPACITY_LEVEL,
- POWER_SUPPLY_PROP_TEMP,
- POWER_SUPPLY_PROP_TECHNOLOGY,
- POWER_SUPPLY_PROP_CHARGE_FULL,
- POWER_SUPPLY_PROP_CHARGE_NOW,
- POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
- POWER_SUPPLY_PROP_MANUFACTURER,
-};
-
-static enum power_supply_property bq27742_battery_props[] = {
- POWER_SUPPLY_PROP_STATUS,
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CAPACITY_LEVEL,
- POWER_SUPPLY_PROP_TEMP,
- POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
- POWER_SUPPLY_PROP_TECHNOLOGY,
- POWER_SUPPLY_PROP_CHARGE_FULL,
- POWER_SUPPLY_PROP_CHARGE_NOW,
- POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
- POWER_SUPPLY_PROP_CYCLE_COUNT,
- POWER_SUPPLY_PROP_POWER_AVG,
- POWER_SUPPLY_PROP_HEALTH,
- POWER_SUPPLY_PROP_MANUFACTURER,
-};
-
-static enum power_supply_property bq27510_battery_props[] = {
- POWER_SUPPLY_PROP_STATUS,
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CAPACITY_LEVEL,
- POWER_SUPPLY_PROP_TEMP,
- POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
- POWER_SUPPLY_PROP_TECHNOLOGY,
- POWER_SUPPLY_PROP_CHARGE_FULL,
- POWER_SUPPLY_PROP_CHARGE_NOW,
- POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
- POWER_SUPPLY_PROP_CYCLE_COUNT,
- POWER_SUPPLY_PROP_POWER_AVG,
- POWER_SUPPLY_PROP_HEALTH,
- POWER_SUPPLY_PROP_MANUFACTURER,
-};
-
-static unsigned int poll_interval = 360;
-module_param(poll_interval, uint, 0644);
-MODULE_PARM_DESC(poll_interval,
- "battery poll interval in seconds - 0 disables polling");
-
-/*
- * Common code for BQ27x00 devices
- */
-
-static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
- bool single)
-{
- if (di->chip == BQ27425)
- return di->bus.read(di, reg - BQ27425_REG_OFFSET, single);
- return di->bus.read(di, reg, single);
-}
-
-/*
- * Higher versions of the chip like BQ27425 and BQ27500
- * differ from BQ27000 and BQ27200 in calculation of certain
- * parameters. Hence we need to check for the chip type.
- */
-static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di)
-{
- if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742
- || di->chip == BQ27510)
- return true;
- return false;
-}
-
-/*
- * Return the battery Relative State-of-Charge
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
-{
- int rsoc;
-
- if (di->chip == BQ27500 || di->chip == BQ27742)
- rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
- else if (di->chip == BQ27510)
- rsoc = bq27x00_read(di, BQ27510_REG_SOC, false);
- else if (di->chip == BQ27425)
- rsoc = bq27x00_read(di, BQ27425_REG_SOC, false);
- else
- rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
-
- if (rsoc < 0)
- dev_dbg(di->dev, "error reading relative State-of-Charge\n");
-
- return rsoc;
-}
-
-/*
- * Return a battery charge value in µAh
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
-{
- int charge;
-
- charge = bq27x00_read(di, reg, false);
- if (charge < 0) {
- dev_dbg(di->dev, "error reading charge register %02x: %d\n",
- reg, charge);
- return charge;
- }
-
- if (bq27xxx_is_chip_version_higher(di))
- charge *= 1000;
- else
- charge = charge * 3570 / BQ27000_RS;
-
- return charge;
-}
-
-/*
- * Return the battery Nominal available capaciy in µAh
- * Or < 0 if something fails.
- */
-static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
-{
- int flags;
- bool is_bq27500 = di->chip == BQ27500;
- bool is_bq27742 = di->chip == BQ27742;
- bool is_higher = bq27xxx_is_chip_version_higher(di);
- bool flags_1b = !(is_bq27500 || is_bq27742);
-
- flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b);
- if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
- return -ENODATA;
-
- return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
-}
-
-/*
- * Return the battery Last measured discharge in µAh
- * Or < 0 if something fails.
- */
-static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di)
-{
- return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD);
-}
-
-/*
- * Return the battery Initial last measured discharge in µAh
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
-{
- int ilmd;
-
- if (bq27xxx_is_chip_version_higher(di)) {
- if (di->chip == BQ27425)
- ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false);
- else if (di->chip == BQ27510)
- ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false);
- else
- ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
- } else {
- ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
- }
-
- if (ilmd < 0) {
- dev_dbg(di->dev, "error reading initial last measured discharge\n");
- return ilmd;
- }
-
- if (bq27xxx_is_chip_version_higher(di))
- ilmd *= 1000;
- else
- ilmd = ilmd * 256 * 3570 / BQ27000_RS;
-
- return ilmd;
-}
-
-/*
- * Return the battery Available energy in µWh
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
-{
- int ae;
-
- ae = bq27x00_read(di, BQ27x00_REG_AE, false);
- if (ae < 0) {
- dev_dbg(di->dev, "error reading available energy\n");
- return ae;
- }
-
- if (di->chip == BQ27500)
- ae *= 1000;
- else
- ae = ae * 29200 / BQ27000_RS;
-
- return ae;
-}
-
-/*
- * Return the battery temperature in tenths of degree Kelvin
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
-{
- int temp;
-
- temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
- if (temp < 0) {
- dev_err(di->dev, "error reading temperature\n");
- return temp;
- }
-
- if (!bq27xxx_is_chip_version_higher(di))
- temp = 5 * temp / 2;
-
- return temp;
-}
-
-/*
- * Return the battery Cycle count total
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
-{
- int cyct;
-
- if (di->chip == BQ27510)
- cyct = bq27x00_read(di, BQ27510_REG_CYCT, false);
- else
- cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
- if (cyct < 0)
- dev_err(di->dev, "error reading cycle count total\n");
-
- return cyct;
-}
-
-/*
- * Read a time register.
- * Return < 0 if something fails.
- */
-static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
-{
- int tval;
-
- tval = bq27x00_read(di, reg, false);
- if (tval < 0) {
- dev_dbg(di->dev, "error reading time register %02x: %d\n",
- reg, tval);
- return tval;
- }
-
- if (tval == 65535)
- return -ENODATA;
-
- return tval * 60;
-}
-
-/*
- * Read a power avg register.
- * Return < 0 if something fails.
- */
-static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg)
-{
- int tval;
-
- tval = bq27x00_read(di, reg, false);
- if (tval < 0) {
- dev_err(di->dev, "error reading power avg rgister %02x: %d\n",
- reg, tval);
- return tval;
- }
-
- if (di->chip == BQ27500)
- return tval;
- else
- return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS;
-}
-
-/*
- * Read flag register.
- * Return < 0 if something fails.
- */
-static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
-{
- int tval;
-
- tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
- if (tval < 0) {
- dev_err(di->dev, "error reading flag register:%d\n", tval);
- return tval;
- }
-
- if (di->chip == BQ27500) {
- if (tval & BQ27500_FLAG_SOCF)
- tval = POWER_SUPPLY_HEALTH_DEAD;
- else if (tval & BQ27500_FLAG_OTC)
- tval = POWER_SUPPLY_HEALTH_OVERHEAT;
- else
- tval = POWER_SUPPLY_HEALTH_GOOD;
- return tval;
- } else if (di->chip == BQ27510) {
- if (tval & BQ27500_FLAG_OTC)
- return POWER_SUPPLY_HEALTH_OVERHEAT;
- return POWER_SUPPLY_HEALTH_GOOD;
- } else {
- if (tval & BQ27000_FLAG_EDV1)
- tval = POWER_SUPPLY_HEALTH_DEAD;
- else
- tval = POWER_SUPPLY_HEALTH_GOOD;
- return tval;
- }
-
- return -1;
-}
-
-static void bq27x00_update(struct bq27x00_device_info *di)
-{
- struct bq27x00_reg_cache cache = {0, };
- bool is_bq27500 = di->chip == BQ27500;
- bool is_bq27510 = di->chip == BQ27510;
- bool is_bq27425 = di->chip == BQ27425;
- bool is_bq27742 = di->chip == BQ27742;
- bool flags_1b = !(is_bq27500 || is_bq27742);
-
- cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b);
- if ((cache.flags & 0xff) == 0xff)
- /* read error */
- cache.flags = -1;
- if (cache.flags >= 0) {
- if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510
- && (cache.flags & BQ27000_FLAG_CI)) {
- dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
- cache.capacity = -ENODATA;
- cache.energy = -ENODATA;
- cache.time_to_empty = -ENODATA;
- cache.time_to_empty_avg = -ENODATA;
- cache.time_to_full = -ENODATA;
- cache.charge_full = -ENODATA;
- cache.health = -ENODATA;
- } else {
- cache.capacity = bq27x00_battery_read_rsoc(di);
- if (is_bq27742 || is_bq27510)
- cache.time_to_empty =
- bq27x00_battery_read_time(di,
- BQ27x00_REG_TTE);
- else if (!is_bq27425) {
- cache.energy = bq27x00_battery_read_energy(di);
- cache.time_to_empty =
- bq27x00_battery_read_time(di,
- BQ27x00_REG_TTE);
- cache.time_to_empty_avg =
- bq27x00_battery_read_time(di,
- BQ27x00_REG_TTECP);
- cache.time_to_full =
- bq27x00_battery_read_time(di,
- BQ27x00_REG_TTF);
- }
- cache.charge_full = bq27x00_battery_read_lmd(di);
- cache.health = bq27x00_battery_read_health(di);
- }
- cache.temperature = bq27x00_battery_read_temperature(di);
- if (!is_bq27425)
- cache.cycle_count = bq27x00_battery_read_cyct(di);
- if (is_bq27742)
- cache.power_avg =
- bq27x00_battery_read_pwr_avg(di,
- BQ27742_POWER_AVG);
- else
- cache.power_avg =
- bq27x00_battery_read_pwr_avg(di,
- BQ27x00_POWER_AVG);
-
- /* We only have to read charge design full once */
- if (di->charge_design_full <= 0)
- di->charge_design_full = bq27x00_battery_read_ilmd(di);
- }
-
- if (di->cache.capacity != cache.capacity)
- power_supply_changed(di->bat);
-
- if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
- di->cache = cache;
-
- di->last_update = jiffies;
-}
-
-static void bq27x00_battery_poll(struct work_struct *work)
-{
- struct bq27x00_device_info *di =
- container_of(work, struct bq27x00_device_info, work.work);
-
- bq27x00_update(di);
-
- if (poll_interval > 0) {
- /* The timer does not have to be accurate. */
- set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
- schedule_delayed_work(&di->work, poll_interval * HZ);
- }
-}
-
-/*
- * Return the battery average current in µA
- * Note that current can be negative signed as well
- * Or 0 if something fails.
- */
-static int bq27x00_battery_current(struct bq27x00_device_info *di,
- union power_supply_propval *val)
-{
- int curr;
- int flags;
-
- curr = bq27x00_read(di, BQ27x00_REG_AI, false);
- if (curr < 0) {
- dev_err(di->dev, "error reading current\n");
- return curr;
- }
-
- if (bq27xxx_is_chip_version_higher(di)) {
- /* bq27500 returns signed value */
- val->intval = (int)((s16)curr) * 1000;
- } else {
- flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
- if (flags & BQ27000_FLAG_CHGS) {
- dev_dbg(di->dev, "negative current!\n");
- curr = -curr;
- }
-
- val->intval = curr * 3570 / BQ27000_RS;
- }
-
- return 0;
-}
-
-static int bq27x00_battery_status(struct bq27x00_device_info *di,
- union power_supply_propval *val)
-{
- int status;
-
- if (bq27xxx_is_chip_version_higher(di)) {
- if (di->cache.flags & BQ27500_FLAG_FC)
- status = POWER_SUPPLY_STATUS_FULL;
- else if (di->cache.flags & BQ27500_FLAG_DSC)
- status = POWER_SUPPLY_STATUS_DISCHARGING;
- else
- status = POWER_SUPPLY_STATUS_CHARGING;
- } else {
- if (di->cache.flags & BQ27000_FLAG_FC)
- status = POWER_SUPPLY_STATUS_FULL;
- else if (di->cache.flags & BQ27000_FLAG_CHGS)
- status = POWER_SUPPLY_STATUS_CHARGING;
- else if (power_supply_am_i_supplied(di->bat))
- status = POWER_SUPPLY_STATUS_NOT_CHARGING;
- else
- status = POWER_SUPPLY_STATUS_DISCHARGING;
- }
-
- val->intval = status;
-
- return 0;
-}
-
-static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
- union power_supply_propval *val)
-{
- int level;
-
- if (bq27xxx_is_chip_version_higher(di)) {
- if (di->cache.flags & BQ27500_FLAG_FC)
- level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
- else if (di->cache.flags & BQ27500_FLAG_SOC1)
- level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
- else if (di->cache.flags & BQ27500_FLAG_SOCF)
- level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
- else
- level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
- } else {
- if (di->cache.flags & BQ27000_FLAG_FC)
- level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
- else if (di->cache.flags & BQ27000_FLAG_EDV1)
- level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
- else if (di->cache.flags & BQ27000_FLAG_EDVF)
- level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
- else
- level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
- }
-
- val->intval = level;
-
- return 0;
-}
-
-/*
- * Return the battery Voltage in millivolts
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
- union power_supply_propval *val)
-{
- int volt;
-
- volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
- if (volt < 0) {
- dev_err(di->dev, "error reading voltage\n");
- return volt;
- }
-
- val->intval = volt * 1000;
-
- return 0;
-}
-
-static int bq27x00_simple_value(int value,
- union power_supply_propval *val)
-{
- if (value < 0)
- return value;
-
- val->intval = value;
-
- return 0;
-}
-
-static int bq27x00_battery_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
-{
- int ret = 0;
- struct bq27x00_device_info *di = power_supply_get_drvdata(psy);
-
- mutex_lock(&di->lock);
- if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
- cancel_delayed_work_sync(&di->work);
- bq27x00_battery_poll(&di->work.work);
- }
- mutex_unlock(&di->lock);
-
- if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
- return -ENODEV;
-
- switch (psp) {
- case POWER_SUPPLY_PROP_STATUS:
- ret = bq27x00_battery_status(di, val);
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- ret = bq27x00_battery_voltage(di, val);
- break;
- case POWER_SUPPLY_PROP_PRESENT:
- val->intval = di->cache.flags < 0 ? 0 : 1;
- break;
- case POWER_SUPPLY_PROP_CURRENT_NOW:
- ret = bq27x00_battery_current(di, val);
- break;
- case POWER_SUPPLY_PROP_CAPACITY:
- ret = bq27x00_simple_value(di->cache.capacity, val);
- break;
- case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
- ret = bq27x00_battery_capacity_level(di, val);
- break;
- case POWER_SUPPLY_PROP_TEMP:
- ret = bq27x00_simple_value(di->cache.temperature, val);
- if (ret == 0)
- val->intval -= 2731;
- break;
- case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
- ret = bq27x00_simple_value(di->cache.time_to_empty, val);
- break;
- case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
- ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val);
- break;
- case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
- ret = bq27x00_simple_value(di->cache.time_to_full, val);
- break;
- case POWER_SUPPLY_PROP_TECHNOLOGY:
- val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
- break;
- case POWER_SUPPLY_PROP_CHARGE_NOW:
- ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val);
- break;
- case POWER_SUPPLY_PROP_CHARGE_FULL:
- ret = bq27x00_simple_value(di->cache.charge_full, val);
- break;
- case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
- ret = bq27x00_simple_value(di->charge_design_full, val);
- break;
- case POWER_SUPPLY_PROP_CYCLE_COUNT:
- ret = bq27x00_simple_value(di->cache.cycle_count, val);
- break;
- case POWER_SUPPLY_PROP_ENERGY_NOW:
- ret = bq27x00_simple_value(di->cache.energy, val);
- break;
- case POWER_SUPPLY_PROP_POWER_AVG:
- ret = bq27x00_simple_value(di->cache.power_avg, val);
- break;
- case POWER_SUPPLY_PROP_HEALTH:
- ret = bq27x00_simple_value(di->cache.health, val);
- break;
- case POWER_SUPPLY_PROP_MANUFACTURER:
- val->strval = BQ27XXX_MANUFACTURER;
- break;
- default:
- return -EINVAL;
- }
-
- return ret;
-}
-
-static void bq27x00_external_power_changed(struct power_supply *psy)
-{
- struct bq27x00_device_info *di = power_supply_get_drvdata(psy);
-
- cancel_delayed_work_sync(&di->work);
- schedule_delayed_work(&di->work, 0);
-}
-
-static int bq27x00_powersupply_init(struct bq27x00_device_info *di,
- const char *name)
-{
- int ret;
- struct power_supply_desc *psy_desc;
- struct power_supply_config psy_cfg = { .drv_data = di, };
-
- psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL);
- if (!psy_desc)
- return -ENOMEM;
-
- psy_desc->name = name;
- psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
- if (di->chip == BQ27425) {
- psy_desc->properties = bq27425_battery_props;
- psy_desc->num_properties = ARRAY_SIZE(bq27425_battery_props);
- } else if (di->chip == BQ27742) {
- psy_desc->properties = bq27742_battery_props;
- psy_desc->num_properties = ARRAY_SIZE(bq27742_battery_props);
- } else if (di->chip == BQ27510) {
- psy_desc->properties = bq27510_battery_props;
- psy_desc->num_properties = ARRAY_SIZE(bq27510_battery_props);
- } else {
- psy_desc->properties = bq27x00_battery_props;
- psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props);
- }
- psy_desc->get_property = bq27x00_battery_get_property;
- psy_desc->external_power_changed = bq27x00_external_power_changed;
-
- INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
- mutex_init(&di->lock);
-
- di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
- if (IS_ERR(di->bat)) {
- ret = PTR_ERR(di->bat);
- dev_err(di->dev, "failed to register battery: %d\n", ret);
- return ret;
- }
-
- dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
-
- bq27x00_update(di);
-
- return 0;
-}
-
-static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
-{
- /*
- * power_supply_unregister call bq27x00_battery_get_property which
- * call bq27x00_battery_poll.
- * Make sure that bq27x00_battery_poll will not call
- * schedule_delayed_work again after unregister (which cause OOPS).
- */
- poll_interval = 0;
-
- cancel_delayed_work_sync(&di->work);
-
- power_supply_unregister(di->bat);
-
- mutex_destroy(&di->lock);
-}
-
-/* i2c specific code */
-#ifdef CONFIG_BATTERY_BQ27X00_I2C
-
-/* If the system has several batteries we need a different name for each
- * of them...
- */
-static DEFINE_IDR(battery_id);
-static DEFINE_MUTEX(battery_mutex);
-
-static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)
-{
- struct i2c_client *client = to_i2c_client(di->dev);
- struct i2c_msg msg[2];
- unsigned char data[2];
- int ret;
-
- if (!client->adapter)
- return -ENODEV;
-
- msg[0].addr = client->addr;
- msg[0].flags = 0;
- msg[0].buf = &reg;
- msg[0].len = sizeof(reg);
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = data;
- if (single)
- msg[1].len = 1;
- else
- msg[1].len = 2;
-
- ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
- if (ret < 0)
- return ret;
-
- if (!single)
- ret = get_unaligned_le16(data);
- else
- ret = data[0];
-
- return ret;
-}
-
-static int bq27x00_battery_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- char *name;
- struct bq27x00_device_info *di;
- int num;
- int retval = 0;
-
- /* Get new ID for the new battery device */
- mutex_lock(&battery_mutex);
- num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
- mutex_unlock(&battery_mutex);
- if (num < 0)
- return num;
-
- name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
- if (!name) {
- retval = -ENOMEM;
- goto batt_failed;
- }
-
- di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
- if (!di) {
- retval = -ENOMEM;
- goto batt_failed;
- }
-
- di->id = num;
- di->dev = &client->dev;
- di->chip = id->driver_data;
- di->bus.read = &bq27x00_read_i2c;
-
- retval = bq27x00_powersupply_init(di, name);
- if (retval)
- goto batt_failed;
-
- i2c_set_clientdata(client, di);
-
- return 0;
-
-batt_failed:
- mutex_lock(&battery_mutex);
- idr_remove(&battery_id, num);
- mutex_unlock(&battery_mutex);
-
- return retval;
-}
-
-static int bq27x00_battery_remove(struct i2c_client *client)
-{
- struct bq27x00_device_info *di = i2c_get_clientdata(client);
-
- bq27x00_powersupply_unregister(di);
-
- mutex_lock(&battery_mutex);
- idr_remove(&battery_id, di->id);
- mutex_unlock(&battery_mutex);
-
- return 0;
-}
-
-static const struct i2c_device_id bq27x00_id[] = {
- { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */
- { "bq27500", BQ27500 },
- { "bq27425", BQ27425 },
- { "bq27742", BQ27742 },
- { "bq27510", BQ27510 },
- {},
-};
-MODULE_DEVICE_TABLE(i2c, bq27x00_id);
-
-static struct i2c_driver bq27x00_battery_driver = {
- .driver = {
- .name = "bq27x00-battery",
- },
- .probe = bq27x00_battery_probe,
- .remove = bq27x00_battery_remove,
- .id_table = bq27x00_id,
-};
-
-static inline int bq27x00_battery_i2c_init(void)
-{
- int ret = i2c_add_driver(&bq27x00_battery_driver);
-
- if (ret)
- pr_err("Unable to register BQ27x00 i2c driver\n");
-
- return ret;
-}
-
-static inline void bq27x00_battery_i2c_exit(void)
-{
- i2c_del_driver(&bq27x00_battery_driver);
-}
-
-#else
-
-static inline int bq27x00_battery_i2c_init(void) { return 0; }
-static inline void bq27x00_battery_i2c_exit(void) {};
-
-#endif
-
-/* platform specific code */
-#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
-
-static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
- bool single)
-{
- struct device *dev = di->dev;
- struct bq27000_platform_data *pdata = dev->platform_data;
- unsigned int timeout = 3;
- int upper, lower;
- int temp;
-
- if (!single) {
- /* Make sure the value has not changed in between reading the
- * lower and the upper part */
- upper = pdata->read(dev, reg + 1);
- do {
- temp = upper;
- if (upper < 0)
- return upper;
-
- lower = pdata->read(dev, reg);
- if (lower < 0)
- return lower;
-
- upper = pdata->read(dev, reg + 1);
- } while (temp != upper && --timeout);
-
- if (timeout == 0)
- return -EIO;
-
- return (upper << 8) | lower;
- }
-
- return pdata->read(dev, reg);
-}
-
-static int bq27000_battery_probe(struct platform_device *pdev)
-{
- struct bq27x00_device_info *di;
- struct bq27000_platform_data *pdata = pdev->dev.platform_data;
- const char *name;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform_data supplied\n");
- return -EINVAL;
- }
-
- if (!pdata->read) {
- dev_err(&pdev->dev, "no hdq read callback supplied\n");
- return -EINVAL;
- }
-
- di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
- if (!di)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, di);
-
- di->dev = &pdev->dev;
- di->chip = BQ27000;
-
- name = pdata->name ?: dev_name(&pdev->dev);
- di->bus.read = &bq27000_read_platform;
-
- return bq27x00_powersupply_init(di, name);
-}
-
-static int bq27000_battery_remove(struct platform_device *pdev)
-{
- struct bq27x00_device_info *di = platform_get_drvdata(pdev);
-
- bq27x00_powersupply_unregister(di);
-
- return 0;
-}
-
-static struct platform_driver bq27000_battery_driver = {
- .probe = bq27000_battery_probe,
- .remove = bq27000_battery_remove,
- .driver = {
- .name = "bq27000-battery",
- },
-};
-
-static inline int bq27x00_battery_platform_init(void)
-{
- int ret = platform_driver_register(&bq27000_battery_driver);
-
- if (ret)
- pr_err("Unable to register BQ27000 platform driver\n");
-
- return ret;
-}
-
-static inline void bq27x00_battery_platform_exit(void)
-{
- platform_driver_unregister(&bq27000_battery_driver);
-}
-
-#else
-
-static inline int bq27x00_battery_platform_init(void) { return 0; }
-static inline void bq27x00_battery_platform_exit(void) {};
-
-#endif
-
-/*
- * Module stuff
- */
-
-static int __init bq27x00_battery_init(void)
-{
- int ret;
-
- ret = bq27x00_battery_i2c_init();
- if (ret)
- return ret;
-
- ret = bq27x00_battery_platform_init();
- if (ret)
- bq27x00_battery_i2c_exit();
-
- return ret;
-}
-module_init(bq27x00_battery_init);
-
-static void __exit bq27x00_battery_exit(void)
-{
- bq27x00_battery_platform_exit();
- bq27x00_battery_i2c_exit();
-}
-module_exit(bq27x00_battery_exit);
-
-#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
-MODULE_ALIAS("platform:bq27000-battery");
-#endif
-
-#ifdef CONFIG_BATTERY_BQ27X00_I2C
-MODULE_ALIAS("i2c:bq27000-battery");
-#endif
-
-MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
-MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
new file mode 100644
index 000000000000..880233ce9343
--- /dev/null
+++ b/drivers/power/bq27xxx_battery.c
@@ -0,0 +1,1375 @@
+/*
+ * BQ27xxx battery driver
+ *
+ * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
+ * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com>
+ *
+ * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Datasheets:
+ * http://www.ti.com/product/bq27000
+ * http://www.ti.com/product/bq27200
+ * http://www.ti.com/product/bq27010
+ * http://www.ti.com/product/bq27210
+ * http://www.ti.com/product/bq27500
+ * http://www.ti.com/product/bq27510-g3
+ * http://www.ti.com/product/bq27520-g4
+ * http://www.ti.com/product/bq27530-g1
+ * http://www.ti.com/product/bq27531-g1
+ * http://www.ti.com/product/bq27541-g1
+ * http://www.ti.com/product/bq27542-g1
+ * http://www.ti.com/product/bq27546-g1
+ * http://www.ti.com/product/bq27742-g1
+ * http://www.ti.com/product/bq27545-g1
+ * http://www.ti.com/product/bq27421-g1
+ * http://www.ti.com/product/bq27425-g1
+ * http://www.ti.com/product/bq27411-g1
+ * http://www.ti.com/product/bq27621-g1
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/idr.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/unaligned.h>
+
+#include <linux/power/bq27xxx_battery.h>
+
+#define DRIVER_VERSION "1.2.0"
+
+#define BQ27XXX_MANUFACTURER "Texas Instruments"
+
+/* BQ27XXX Flags */
+#define BQ27XXX_FLAG_DSC BIT(0)
+#define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
+#define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
+#define BQ27XXX_FLAG_FC BIT(9)
+#define BQ27XXX_FLAG_OTD BIT(14)
+#define BQ27XXX_FLAG_OTC BIT(15)
+#define BQ27XXX_FLAG_UT BIT(14)
+#define BQ27XXX_FLAG_OT BIT(15)
+
+/* BQ27000 has different layout for Flags register */
+#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */
+#define BQ27000_FLAG_FC BIT(5)
+#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
+
+#define BQ27XXX_RS (20) /* Resistor sense mOhm */
+#define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
+#define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
+
+struct bq27xxx_device_info;
+struct bq27xxx_access_methods {
+ int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
+};
+
+#define INVALID_REG_ADDR 0xff
+
+/*
+ * bq27xxx_reg_index - Register names
+ *
+ * These are indexes into a device's register mapping array.
+ */
+enum bq27xxx_reg_index {
+ BQ27XXX_REG_CTRL = 0, /* Control */
+ BQ27XXX_REG_TEMP, /* Temperature */
+ BQ27XXX_REG_INT_TEMP, /* Internal Temperature */
+ BQ27XXX_REG_VOLT, /* Voltage */
+ BQ27XXX_REG_AI, /* Average Current */
+ BQ27XXX_REG_FLAGS, /* Flags */
+ BQ27XXX_REG_TTE, /* Time-to-Empty */
+ BQ27XXX_REG_TTF, /* Time-to-Full */
+ BQ27XXX_REG_TTES, /* Time-to-Empty Standby */
+ BQ27XXX_REG_TTECP, /* Time-to-Empty at Constant Power */
+ BQ27XXX_REG_NAC, /* Nominal Available Capacity */
+ BQ27XXX_REG_FCC, /* Full Charge Capacity */
+ BQ27XXX_REG_CYCT, /* Cycle Count */
+ BQ27XXX_REG_AE, /* Available Energy */
+ BQ27XXX_REG_SOC, /* State-of-Charge */
+ BQ27XXX_REG_DCAP, /* Design Capacity */
+ BQ27XXX_REG_AP, /* Average Power */
+};
+
+struct bq27xxx_reg_cache {
+ int temperature;
+ int time_to_empty;
+ int time_to_empty_avg;
+ int time_to_full;
+ int charge_full;
+ int cycle_count;
+ int capacity;
+ int energy;
+ int flags;
+ int power_avg;
+ int health;
+};
+
+struct bq27xxx_device_info {
+ struct device *dev;
+ int id;
+ enum bq27xxx_chip chip;
+
+ struct bq27xxx_reg_cache cache;
+ int charge_design_full;
+
+ unsigned long last_update;
+ struct delayed_work work;
+
+ struct power_supply *bat;
+
+ struct bq27xxx_access_methods bus;
+
+ struct mutex lock;
+
+ u8 *regs;
+};
+
+/* Register mappings */
+static u8 bq27000_regs[] = {
+ 0x00, /* CONTROL */
+ 0x06, /* TEMP */
+ INVALID_REG_ADDR, /* INT TEMP - NA*/
+ 0x08, /* VOLT */
+ 0x14, /* AVG CURR */
+ 0x0a, /* FLAGS */
+ 0x16, /* TTE */
+ 0x18, /* TTF */
+ 0x1c, /* TTES */
+ 0x26, /* TTECP */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+ 0x2a, /* CYCT */
+ 0x22, /* AE */
+ 0x0b, /* SOC(RSOC) */
+ 0x76, /* DCAP(ILMD) */
+ 0x24, /* AP */
+};
+
+static u8 bq27010_regs[] = {
+ 0x00, /* CONTROL */
+ 0x06, /* TEMP */
+ INVALID_REG_ADDR, /* INT TEMP - NA*/
+ 0x08, /* VOLT */
+ 0x14, /* AVG CURR */
+ 0x0a, /* FLAGS */
+ 0x16, /* TTE */
+ 0x18, /* TTF */
+ 0x1c, /* TTES */
+ 0x26, /* TTECP */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+ 0x2a, /* CYCT */
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x0b, /* SOC(RSOC) */
+ 0x76, /* DCAP(ILMD) */
+ INVALID_REG_ADDR, /* AP - NA */
+};
+
+static u8 bq27500_regs[] = {
+ 0x00, /* CONTROL */
+ 0x06, /* TEMP */
+ 0x28, /* INT TEMP */
+ 0x08, /* VOLT */
+ 0x14, /* AVG CURR */
+ 0x0a, /* FLAGS */
+ 0x16, /* TTE */
+ INVALID_REG_ADDR, /* TTF - NA */
+ 0x1a, /* TTES */
+ INVALID_REG_ADDR, /* TTECP - NA */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+ 0x1e, /* CYCT */
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x20, /* SOC(RSOC) */
+ 0x2e, /* DCAP(ILMD) */
+ INVALID_REG_ADDR, /* AP - NA */
+};
+
+static u8 bq27530_regs[] = {
+ 0x00, /* CONTROL */
+ 0x06, /* TEMP */
+ 0x32, /* INT TEMP */
+ 0x08, /* VOLT */
+ 0x14, /* AVG CURR */
+ 0x0a, /* FLAGS */
+ 0x16, /* TTE */
+ INVALID_REG_ADDR, /* TTF - NA */
+ INVALID_REG_ADDR, /* TTES - NA */
+ INVALID_REG_ADDR, /* TTECP - NA */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+ 0x2a, /* CYCT */
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x2c, /* SOC(RSOC) */
+ INVALID_REG_ADDR, /* DCAP - NA */
+ 0x24, /* AP */
+};
+
+static u8 bq27541_regs[] = {
+ 0x00, /* CONTROL */
+ 0x06, /* TEMP */
+ 0x28, /* INT TEMP */
+ 0x08, /* VOLT */
+ 0x14, /* AVG CURR */
+ 0x0a, /* FLAGS */
+ 0x16, /* TTE */
+ INVALID_REG_ADDR, /* TTF - NA */
+ INVALID_REG_ADDR, /* TTES - NA */
+ INVALID_REG_ADDR, /* TTECP - NA */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+ 0x2a, /* CYCT */
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x2c, /* SOC(RSOC) */
+ 0x3c, /* DCAP */
+ 0x76, /* AP */
+};
+
+static u8 bq27545_regs[] = {
+ 0x00, /* CONTROL */
+ 0x06, /* TEMP */
+ 0x28, /* INT TEMP */
+ 0x08, /* VOLT */
+ 0x14, /* AVG CURR */
+ 0x0a, /* FLAGS */
+ 0x16, /* TTE */
+ INVALID_REG_ADDR, /* TTF - NA */
+ INVALID_REG_ADDR, /* TTES - NA */
+ INVALID_REG_ADDR, /* TTECP - NA */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+ 0x2a, /* CYCT */
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x2c, /* SOC(RSOC) */
+ INVALID_REG_ADDR, /* DCAP - NA */
+ 0x24, /* AP */
+};
+
+static u8 bq27421_regs[] = {
+ 0x00, /* CONTROL */
+ 0x02, /* TEMP */
+ 0x1e, /* INT TEMP */
+ 0x04, /* VOLT */
+ 0x10, /* AVG CURR */
+ 0x06, /* FLAGS */
+ INVALID_REG_ADDR, /* TTE - NA */
+ INVALID_REG_ADDR, /* TTF - NA */
+ INVALID_REG_ADDR, /* TTES - NA */
+ INVALID_REG_ADDR, /* TTECP - NA */
+ 0x08, /* NAC */
+ 0x0e, /* FCC */
+ INVALID_REG_ADDR, /* CYCT - NA */
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x1c, /* SOC */
+ 0x3c, /* DCAP */
+ 0x18, /* AP */
+};
+
+static u8 *bq27xxx_regs[] = {
+ [BQ27000] = bq27000_regs,
+ [BQ27010] = bq27010_regs,
+ [BQ27500] = bq27500_regs,
+ [BQ27530] = bq27530_regs,
+ [BQ27541] = bq27541_regs,
+ [BQ27545] = bq27545_regs,
+ [BQ27421] = bq27421_regs,
+};
+
+static enum power_supply_property bq27000_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_POWER_AVG,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27010_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27500_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27530_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_POWER_AVG,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27541_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_POWER_AVG,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27545_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_POWER_AVG,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property bq27421_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+#define BQ27XXX_PROP(_id, _prop) \
+ [_id] = { \
+ .props = _prop, \
+ .size = ARRAY_SIZE(_prop), \
+ }
+
+static struct {
+ enum power_supply_property *props;
+ size_t size;
+} bq27xxx_battery_props[] = {
+ BQ27XXX_PROP(BQ27000, bq27000_battery_props),
+ BQ27XXX_PROP(BQ27010, bq27010_battery_props),
+ BQ27XXX_PROP(BQ27500, bq27500_battery_props),
+ BQ27XXX_PROP(BQ27530, bq27530_battery_props),
+ BQ27XXX_PROP(BQ27541, bq27541_battery_props),
+ BQ27XXX_PROP(BQ27545, bq27545_battery_props),
+ BQ27XXX_PROP(BQ27421, bq27421_battery_props),
+};
+
+static unsigned int poll_interval = 360;
+module_param(poll_interval, uint, 0644);
+MODULE_PARM_DESC(poll_interval,
+ "battery poll interval in seconds - 0 disables polling");
+
+/*
+ * Common code for BQ27xxx devices
+ */
+
+static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index,
+ bool single)
+{
+ /* Reports EINVAL for invalid/missing registers */
+ if (!di || di->regs[reg_index] == INVALID_REG_ADDR)
+ return -EINVAL;
+
+ return di->bus.read(di, di->regs[reg_index], single);
+}
+
+/*
+ * Return the battery State-of-Charge
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di)
+{
+ int soc;
+
+ soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
+
+ if (soc < 0)
+ dev_dbg(di->dev, "error reading State-of-Charge\n");
+
+ return soc;
+}
+
+/*
+ * Return a battery charge value in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
+{
+ int charge;
+
+ charge = bq27xxx_read(di, reg, false);
+ if (charge < 0) {
+ dev_dbg(di->dev, "error reading charge register %02x: %d\n",
+ reg, charge);
+ return charge;
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+ else
+ charge *= 1000;
+
+ return charge;
+}
+
+/*
+ * Return the battery Nominal available capacity in µAh
+ * Or < 0 if something fails.
+ */
+static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
+{
+ int flags;
+
+ if (di->chip == BQ27000 || di->chip == BQ27010) {
+ flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true);
+ if (flags >= 0 && (flags & BQ27000_FLAG_CI))
+ return -ENODATA;
+ }
+
+ return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC);
+}
+
+/*
+ * Return the battery Full Charge Capacity in µAh
+ * Or < 0 if something fails.
+ */
+static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
+{
+ return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC);
+}
+
+/*
+ * Return the Design Capacity in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
+{
+ int dcap;
+
+ dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
+
+ if (dcap < 0) {
+ dev_dbg(di->dev, "error reading initial last measured discharge\n");
+ return dcap;
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+ else
+ dcap *= 1000;
+
+ return dcap;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di)
+{
+ int ae;
+
+ ae = bq27xxx_read(di, BQ27XXX_REG_AE, false);
+ if (ae < 0) {
+ dev_dbg(di->dev, "error reading available energy\n");
+ return ae;
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS;
+ else
+ ae *= 1000;
+
+ return ae;
+}
+
+/*
+ * Return the battery temperature in tenths of degree Kelvin
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di)
+{
+ int temp;
+
+ temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false);
+ if (temp < 0) {
+ dev_err(di->dev, "error reading temperature\n");
+ return temp;
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ temp = 5 * temp / 2;
+
+ return temp;
+}
+
+/*
+ * Return the battery Cycle count total
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di)
+{
+ int cyct;
+
+ cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false);
+ if (cyct < 0)
+ dev_err(di->dev, "error reading cycle count total\n");
+
+ return cyct;
+}
+
+/*
+ * Read a time register.
+ * Return < 0 if something fails.
+ */
+static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg)
+{
+ int tval;
+
+ tval = bq27xxx_read(di, reg, false);
+ if (tval < 0) {
+ dev_dbg(di->dev, "error reading time register %02x: %d\n",
+ reg, tval);
+ return tval;
+ }
+
+ if (tval == 65535)
+ return -ENODATA;
+
+ return tval * 60;
+}
+
+/*
+ * Read an average power register.
+ * Return < 0 if something fails.
+ */
+static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
+{
+ int tval;
+
+ tval = bq27xxx_read(di, BQ27XXX_REG_AP, false);
+ if (tval < 0) {
+ dev_err(di->dev, "error reading average power register %02x: %d\n",
+ BQ27XXX_REG_AP, tval);
+ return tval;
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
+ else
+ return tval;
+}
+
+/*
+ * Returns true if a battery over temperature condition is detected
+ */
+static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
+{
+ if (di->chip == BQ27500 || di->chip == BQ27541 || di->chip == BQ27545)
+ return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD);
+ if (di->chip == BQ27530 || di->chip == BQ27421)
+ return flags & BQ27XXX_FLAG_OT;
+
+ return false;
+}
+
+/*
+ * Returns true if a battery under temperature condition is detected
+ */
+static bool bq27xxx_battery_undertemp(struct bq27xxx_device_info *di, u16 flags)
+{
+ if (di->chip == BQ27530 || di->chip == BQ27421)
+ return flags & BQ27XXX_FLAG_UT;
+
+ return false;
+}
+
+/*
+ * Returns true if a low state of charge condition is detected
+ */
+static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags)
+{
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF);
+ else
+ return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF);
+}
+
+/*
+ * Read flag register.
+ * Return < 0 if something fails.
+ */
+static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
+{
+ int flags;
+
+ flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
+ if (flags < 0) {
+ dev_err(di->dev, "error reading flag register:%d\n", flags);
+ return flags;
+ }
+
+ /* Unlikely but important to return first */
+ if (unlikely(bq27xxx_battery_overtemp(di, flags)))
+ return POWER_SUPPLY_HEALTH_OVERHEAT;
+ if (unlikely(bq27xxx_battery_undertemp(di, flags)))
+ return POWER_SUPPLY_HEALTH_COLD;
+ if (unlikely(bq27xxx_battery_dead(di, flags)))
+ return POWER_SUPPLY_HEALTH_DEAD;
+
+ return POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+{
+ struct bq27xxx_reg_cache cache = {0, };
+ bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010;
+ bool has_singe_flag = di->chip == BQ27000 || di->chip == BQ27010;
+
+ cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
+ if ((cache.flags & 0xff) == 0xff)
+ cache.flags = -1; /* read error */
+ if (cache.flags >= 0) {
+ cache.temperature = bq27xxx_battery_read_temperature(di);
+ if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) {
+ dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
+ cache.capacity = -ENODATA;
+ cache.energy = -ENODATA;
+ cache.time_to_empty = -ENODATA;
+ cache.time_to_empty_avg = -ENODATA;
+ cache.time_to_full = -ENODATA;
+ cache.charge_full = -ENODATA;
+ cache.health = -ENODATA;
+ } else {
+ if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+ cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+ if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+ cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+ if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+ cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+ cache.charge_full = bq27xxx_battery_read_fcc(di);
+ cache.capacity = bq27xxx_battery_read_soc(di);
+ if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
+ cache.energy = bq27xxx_battery_read_energy(di);
+ cache.health = bq27xxx_battery_read_health(di);
+ }
+ if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+ cache.cycle_count = bq27xxx_battery_read_cyct(di);
+ if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR)
+ cache.power_avg = bq27xxx_battery_read_pwr_avg(di);
+
+ /* We only have to read charge design full once */
+ if (di->charge_design_full <= 0)
+ di->charge_design_full = bq27xxx_battery_read_dcap(di);
+ }
+
+ if (di->cache.capacity != cache.capacity)
+ power_supply_changed(di->bat);
+
+ if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
+ di->cache = cache;
+
+ di->last_update = jiffies;
+}
+
+static void bq27xxx_battery_poll(struct work_struct *work)
+{
+ struct bq27xxx_device_info *di =
+ container_of(work, struct bq27xxx_device_info,
+ work.work);
+
+ bq27xxx_battery_update(di);
+
+ if (poll_interval > 0) {
+ /* The timer does not have to be accurate. */
+ set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
+ schedule_delayed_work(&di->work, poll_interval * HZ);
+ }
+}
+
+/*
+ * Return the battery average current in µA
+ * Note that current can be negative signed as well
+ * Or 0 if something fails.
+ */
+static int bq27xxx_battery_current(struct bq27xxx_device_info *di,
+ union power_supply_propval *val)
+{
+ int curr;
+ int flags;
+
+ curr = bq27xxx_read(di, BQ27XXX_REG_AI, false);
+ if (curr < 0) {
+ dev_err(di->dev, "error reading current\n");
+ return curr;
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010) {
+ flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false);
+ if (flags & BQ27000_FLAG_CHGS) {
+ dev_dbg(di->dev, "negative current!\n");
+ curr = -curr;
+ }
+
+ val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+ } else {
+ /* Other gauges return signed value */
+ val->intval = (int)((s16)curr) * 1000;
+ }
+
+ return 0;
+}
+
+static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
+ union power_supply_propval *val)
+{
+ int status;
+
+ if (di->chip == BQ27000 || di->chip == BQ27010) {
+ if (di->cache.flags & BQ27000_FLAG_FC)
+ status = POWER_SUPPLY_STATUS_FULL;
+ else if (di->cache.flags & BQ27000_FLAG_CHGS)
+ status = POWER_SUPPLY_STATUS_CHARGING;
+ else if (power_supply_am_i_supplied(di->bat))
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+ status = POWER_SUPPLY_STATUS_DISCHARGING;
+ } else {
+ if (di->cache.flags & BQ27XXX_FLAG_FC)
+ status = POWER_SUPPLY_STATUS_FULL;
+ else if (di->cache.flags & BQ27XXX_FLAG_DSC)
+ status = POWER_SUPPLY_STATUS_DISCHARGING;
+ else
+ status = POWER_SUPPLY_STATUS_CHARGING;
+ }
+
+ val->intval = status;
+
+ return 0;
+}
+
+static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
+ union power_supply_propval *val)
+{
+ int level;
+
+ if (di->chip == BQ27000 || di->chip == BQ27010) {
+ if (di->cache.flags & BQ27000_FLAG_FC)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->cache.flags & BQ27000_FLAG_EDV1)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (di->cache.flags & BQ27000_FLAG_EDVF)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ else
+ level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ } else {
+ if (di->cache.flags & BQ27XXX_FLAG_FC)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->cache.flags & BQ27XXX_FLAG_SOC1)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (di->cache.flags & BQ27XXX_FLAG_SOCF)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ else
+ level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ }
+
+ val->intval = level;
+
+ return 0;
+}
+
+/*
+ * Return the battery Voltage in millivolts
+ * Or < 0 if something fails.
+ */
+static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di,
+ union power_supply_propval *val)
+{
+ int volt;
+
+ volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false);
+ if (volt < 0) {
+ dev_err(di->dev, "error reading voltage\n");
+ return volt;
+ }
+
+ val->intval = volt * 1000;
+
+ return 0;
+}
+
+static int bq27xxx_simple_value(int value,
+ union power_supply_propval *val)
+{
+ if (value < 0)
+ return value;
+
+ val->intval = value;
+
+ return 0;
+}
+
+static int bq27xxx_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
+
+ mutex_lock(&di->lock);
+ if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
+ cancel_delayed_work_sync(&di->work);
+ bq27xxx_battery_poll(&di->work.work);
+ }
+ mutex_unlock(&di->lock);
+
+ if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = bq27xxx_battery_status(di, val);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = bq27xxx_battery_voltage(di, val);
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = di->cache.flags < 0 ? 0 : 1;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = bq27xxx_battery_current(di, val);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = bq27xxx_simple_value(di->cache.capacity, val);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ ret = bq27xxx_battery_capacity_level(di, val);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = bq27xxx_simple_value(di->cache.temperature, val);
+ if (ret == 0)
+ val->intval -= 2731; /* convert decidegree k to c */
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+ ret = bq27xxx_simple_value(di->cache.time_to_empty, val);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+ ret = bq27xxx_simple_value(di->cache.time_to_empty_avg, val);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+ ret = bq27xxx_simple_value(di->cache.time_to_full, val);
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ ret = bq27xxx_simple_value(bq27xxx_battery_read_nac(di), val);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ ret = bq27xxx_simple_value(di->cache.charge_full, val);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ ret = bq27xxx_simple_value(di->charge_design_full, val);
+ break;
+ case POWER_SUPPLY_PROP_CYCLE_COUNT:
+ ret = bq27xxx_simple_value(di->cache.cycle_count, val);
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_NOW:
+ ret = bq27xxx_simple_value(di->cache.energy, val);
+ break;
+ case POWER_SUPPLY_PROP_POWER_AVG:
+ ret = bq27xxx_simple_value(di->cache.power_avg, val);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = bq27xxx_simple_value(di->cache.health, val);
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = BQ27XXX_MANUFACTURER;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static void bq27xxx_external_power_changed(struct power_supply *psy)
+{
+ struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
+
+ cancel_delayed_work_sync(&di->work);
+ schedule_delayed_work(&di->work, 0);
+}
+
+static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
+ const char *name)
+{
+ int ret;
+ struct power_supply_desc *psy_desc;
+ struct power_supply_config psy_cfg = { .drv_data = di, };
+
+ psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL);
+ if (!psy_desc)
+ return -ENOMEM;
+
+ psy_desc->name = name;
+ psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
+ psy_desc->properties = bq27xxx_battery_props[di->chip].props;
+ psy_desc->num_properties = bq27xxx_battery_props[di->chip].size;
+ psy_desc->get_property = bq27xxx_battery_get_property;
+ psy_desc->external_power_changed = bq27xxx_external_power_changed;
+
+ INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
+ mutex_init(&di->lock);
+
+ di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
+ if (IS_ERR(di->bat)) {
+ ret = PTR_ERR(di->bat);
+ dev_err(di->dev, "failed to register battery: %d\n", ret);
+ return ret;
+ }
+
+ dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+ bq27xxx_battery_update(di);
+
+ return 0;
+}
+
+static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di)
+{
+ /*
+ * power_supply_unregister call bq27xxx_battery_get_property which
+ * call bq27xxx_battery_poll.
+ * Make sure that bq27xxx_battery_poll will not call
+ * schedule_delayed_work again after unregister (which cause OOPS).
+ */
+ poll_interval = 0;
+
+ cancel_delayed_work_sync(&di->work);
+
+ power_supply_unregister(di->bat);
+
+ mutex_destroy(&di->lock);
+}
+
+/* i2c specific code */
+#ifdef CONFIG_BATTERY_BQ27XXX_I2C
+
+/* If the system has several batteries we need a different name for each
+ * of them...
+ */
+static DEFINE_IDR(battery_id);
+static DEFINE_MUTEX(battery_mutex);
+
+static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
+{
+ struct bq27xxx_device_info *di = data;
+
+ bq27xxx_battery_update(di);
+
+ return IRQ_HANDLED;
+}
+
+static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
+ bool single)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ struct i2c_msg msg[2];
+ unsigned char data[2];
+ int ret;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].buf = &reg;
+ msg[0].len = sizeof(reg);
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = data;
+ if (single)
+ msg[1].len = 1;
+ else
+ msg[1].len = 2;
+
+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (ret < 0)
+ return ret;
+
+ if (!single)
+ ret = get_unaligned_le16(data);
+ else
+ ret = data[0];
+
+ return ret;
+}
+
+static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ char *name;
+ struct bq27xxx_device_info *di;
+ int num;
+ int retval = 0;
+
+ /* Get new ID for the new battery device */
+ mutex_lock(&battery_mutex);
+ num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
+ mutex_unlock(&battery_mutex);
+ if (num < 0)
+ return num;
+
+ name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
+ if (!name) {
+ retval = -ENOMEM;
+ goto batt_failed;
+ }
+
+ di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ retval = -ENOMEM;
+ goto batt_failed;
+ }
+
+ di->id = num;
+ di->dev = &client->dev;
+ di->chip = id->driver_data;
+ di->bus.read = &bq27xxx_battery_i2c_read;
+ di->regs = bq27xxx_regs[di->chip];
+
+ retval = bq27xxx_powersupply_init(di, name);
+ if (retval)
+ goto batt_failed;
+
+ /* Schedule a polling after about 1 min */
+ schedule_delayed_work(&di->work, 60 * HZ);
+
+ i2c_set_clientdata(client, di);
+
+ if (client->irq) {
+ retval = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, bq27xxx_battery_irq_handler_thread,
+ IRQF_ONESHOT,
+ name, di);
+ if (retval) {
+ dev_err(&client->dev,
+ "Unable to register IRQ %d error %d\n",
+ client->irq, retval);
+ return retval;
+ }
+ }
+
+ return 0;
+
+batt_failed:
+ mutex_lock(&battery_mutex);
+ idr_remove(&battery_id, num);
+ mutex_unlock(&battery_mutex);
+
+ return retval;
+}
+
+static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
+{
+ struct bq27xxx_device_info *di = i2c_get_clientdata(client);
+
+ bq27xxx_powersupply_unregister(di);
+
+ mutex_lock(&battery_mutex);
+ idr_remove(&battery_id, di->id);
+ mutex_unlock(&battery_mutex);
+
+ return 0;
+}
+
+static const struct i2c_device_id bq27xxx_id[] = {
+ { "bq27200", BQ27000 },
+ { "bq27210", BQ27010 },
+ { "bq27500", BQ27500 },
+ { "bq27510", BQ27500 },
+ { "bq27520", BQ27500 },
+ { "bq27530", BQ27530 },
+ { "bq27531", BQ27530 },
+ { "bq27541", BQ27541 },
+ { "bq27542", BQ27541 },
+ { "bq27546", BQ27541 },
+ { "bq27742", BQ27541 },
+ { "bq27545", BQ27545 },
+ { "bq27421", BQ27421 },
+ { "bq27425", BQ27421 },
+ { "bq27441", BQ27421 },
+ { "bq27621", BQ27421 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, bq27xxx_id);
+
+static struct i2c_driver bq27xxx_battery_i2c_driver = {
+ .driver = {
+ .name = "bq27xxx-battery",
+ },
+ .probe = bq27xxx_battery_i2c_probe,
+ .remove = bq27xxx_battery_i2c_remove,
+ .id_table = bq27xxx_id,
+};
+
+static inline int bq27xxx_battery_i2c_init(void)
+{
+ int ret = i2c_add_driver(&bq27xxx_battery_i2c_driver);
+
+ if (ret)
+ pr_err("Unable to register BQ27xxx i2c driver\n");
+
+ return ret;
+}
+
+static inline void bq27xxx_battery_i2c_exit(void)
+{
+ i2c_del_driver(&bq27xxx_battery_i2c_driver);
+}
+
+#else
+
+static inline int bq27xxx_battery_i2c_init(void) { return 0; }
+static inline void bq27xxx_battery_i2c_exit(void) {};
+
+#endif
+
+/* platform specific code */
+#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM
+
+static int bq27xxx_battery_platform_read(struct bq27xxx_device_info *di, u8 reg,
+ bool single)
+{
+ struct device *dev = di->dev;
+ struct bq27xxx_platform_data *pdata = dev->platform_data;
+ unsigned int timeout = 3;
+ int upper, lower;
+ int temp;
+
+ if (!single) {
+ /* Make sure the value has not changed in between reading the
+ * lower and the upper part */
+ upper = pdata->read(dev, reg + 1);
+ do {
+ temp = upper;
+ if (upper < 0)
+ return upper;
+
+ lower = pdata->read(dev, reg);
+ if (lower < 0)
+ return lower;
+
+ upper = pdata->read(dev, reg + 1);
+ } while (temp != upper && --timeout);
+
+ if (timeout == 0)
+ return -EIO;
+
+ return (upper << 8) | lower;
+ }
+
+ return pdata->read(dev, reg);
+}
+
+static int bq27xxx_battery_platform_probe(struct platform_device *pdev)
+{
+ struct bq27xxx_device_info *di;
+ struct bq27xxx_platform_data *pdata = pdev->dev.platform_data;
+ const char *name;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform_data supplied\n");
+ return -EINVAL;
+ }
+
+ if (!pdata->read) {
+ dev_err(&pdev->dev, "no hdq read callback supplied\n");
+ return -EINVAL;
+ }
+
+ if (!pdata->chip) {
+ dev_err(&pdev->dev, "no device supplied\n");
+ return -EINVAL;
+ }
+
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, di);
+
+ di->dev = &pdev->dev;
+ di->chip = pdata->chip;
+ di->regs = bq27xxx_regs[di->chip];
+
+ name = pdata->name ?: dev_name(&pdev->dev);
+ di->bus.read = &bq27xxx_battery_platform_read;
+
+ return bq27xxx_powersupply_init(di, name);
+}
+
+static int bq27xxx_battery_platform_remove(struct platform_device *pdev)
+{
+ struct bq27xxx_device_info *di = platform_get_drvdata(pdev);
+
+ bq27xxx_powersupply_unregister(di);
+
+ return 0;
+}
+
+static struct platform_driver bq27xxx_battery_platform_driver = {
+ .probe = bq27xxx_battery_platform_probe,
+ .remove = bq27xxx_battery_platform_remove,
+ .driver = {
+ .name = "bq27000-battery",
+ },
+};
+
+static inline int bq27xxx_battery_platform_init(void)
+{
+ int ret = platform_driver_register(&bq27xxx_battery_platform_driver);
+
+ if (ret)
+ pr_err("Unable to register BQ27xxx platform driver\n");
+
+ return ret;
+}
+
+static inline void bq27xxx_battery_platform_exit(void)
+{
+ platform_driver_unregister(&bq27xxx_battery_platform_driver);
+}
+
+#else
+
+static inline int bq27xxx_battery_platform_init(void) { return 0; }
+static inline void bq27xxx_battery_platform_exit(void) {};
+
+#endif
+
+/*
+ * Module stuff
+ */
+
+static int __init bq27xxx_battery_init(void)
+{
+ int ret;
+
+ ret = bq27xxx_battery_i2c_init();
+ if (ret)
+ return ret;
+
+ ret = bq27xxx_battery_platform_init();
+ if (ret)
+ bq27xxx_battery_i2c_exit();
+
+ return ret;
+}
+module_init(bq27xxx_battery_init);
+
+static void __exit bq27xxx_battery_exit(void)
+{
+ bq27xxx_battery_platform_exit();
+ bq27xxx_battery_i2c_exit();
+}
+module_exit(bq27xxx_battery_exit);
+
+#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM
+MODULE_ALIAS("platform:bq27000-battery");
+#endif
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("BQ27xxx battery monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 907293e6f2a4..1ea5d1aa268b 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1581,8 +1581,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
cables = devm_kzalloc(dev, sizeof(*cables)
* chg_regs->num_cables,
GFP_KERNEL);
- if (!cables)
+ if (!cables) {
+ of_node_put(child);
return ERR_PTR(-ENOMEM);
+ }
chg_regs->cables = cables;
diff --git a/drivers/power/da9150-fg.c b/drivers/power/da9150-fg.c
new file mode 100644
index 000000000000..8b8ce978656a
--- /dev/null
+++ b/drivers/power/da9150-fg.c
@@ -0,0 +1,579 @@
+/*
+ * DA9150 Fuel-Gauge Driver
+ *
+ * Copyright (c) 2015 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.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/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/power_supply.h>
+#include <linux/list.h>
+#include <asm/div64.h>
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+/* Core2Wire */
+#define DA9150_QIF_READ (0x0 << 7)
+#define DA9150_QIF_WRITE (0x1 << 7)
+#define DA9150_QIF_CODE_MASK 0x7F
+
+#define DA9150_QIF_BYTE_SIZE 8
+#define DA9150_QIF_BYTE_MASK 0xFF
+#define DA9150_QIF_SHORT_SIZE 2
+#define DA9150_QIF_LONG_SIZE 4
+
+/* QIF Codes */
+#define DA9150_QIF_UAVG 6
+#define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_IAVG 8
+#define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_NTCAVG 12
+#define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_SHUNT_VAL 36
+#define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_SD_GAIN 38
+#define DA9150_QIF_SD_GAIN_SIZE DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_FCC_MAH 40
+#define DA9150_QIF_FCC_MAH_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_SOC_PCT 43
+#define DA9150_QIF_SOC_PCT_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_CHARGE_LIMIT 44
+#define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_DISCHARGE_LIMIT 45
+#define DA9150_QIF_DISCHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_FW_MAIN_VER 118
+#define DA9150_QIF_FW_MAIN_VER_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_E_FG_STATUS 126
+#define DA9150_QIF_E_FG_STATUS_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_SYNC 127
+#define DA9150_QIF_SYNC_SIZE DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_MAX_CODES 128
+
+/* QIF Sync Timeout */
+#define DA9150_QIF_SYNC_TIMEOUT 1000
+#define DA9150_QIF_SYNC_RETRIES 10
+
+/* QIF E_FG_STATUS */
+#define DA9150_FG_IRQ_LOW_SOC_MASK (1 << 0)
+#define DA9150_FG_IRQ_HIGH_SOC_MASK (1 << 1)
+#define DA9150_FG_IRQ_SOC_MASK \
+ (DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK)
+
+/* Private data */
+struct da9150_fg {
+ struct da9150 *da9150;
+ struct device *dev;
+
+ struct mutex io_lock;
+
+ struct power_supply *battery;
+ struct delayed_work work;
+ u32 interval;
+
+ int warn_soc;
+ int crit_soc;
+ int soc;
+};
+
+/* Battery Properties */
+static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size)
+
+{
+ u8 buf[size];
+ u8 read_addr;
+ u32 res = 0;
+ int i;
+
+ /* Set QIF code (READ mode) */
+ read_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_READ;
+
+ da9150_read_qif(fg->da9150, read_addr, size, buf);
+ for (i = 0; i < size; ++i)
+ res |= (buf[i] << (i * DA9150_QIF_BYTE_SIZE));
+
+ return res;
+}
+
+static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size,
+ u32 val)
+
+{
+ u8 buf[size];
+ u8 write_addr;
+ int i;
+
+ /* Set QIF code (WRITE mode) */
+ write_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_WRITE;
+
+ for (i = 0; i < size; ++i) {
+ buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) &
+ DA9150_QIF_BYTE_MASK;
+ }
+ da9150_write_qif(fg->da9150, write_addr, size, buf);
+}
+
+/* Trigger QIF Sync to update QIF readable data */
+static void da9150_fg_read_sync_start(struct da9150_fg *fg)
+{
+ int i = 0;
+ u32 res = 0;
+
+ mutex_lock(&fg->io_lock);
+
+ /* Check if QIF sync already requested, and write to sync if not */
+ res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+ DA9150_QIF_SYNC_SIZE);
+ if (res > 0)
+ da9150_fg_write_attr(fg, DA9150_QIF_SYNC,
+ DA9150_QIF_SYNC_SIZE, 0);
+
+ /* Wait for sync to complete */
+ res = 0;
+ while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
+ usleep_range(DA9150_QIF_SYNC_TIMEOUT,
+ DA9150_QIF_SYNC_TIMEOUT * 2);
+ res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+ DA9150_QIF_SYNC_SIZE);
+ }
+
+ /* Check if sync completed */
+ if (res == 0)
+ dev_err(fg->dev, "Failed to perform QIF read sync!\n");
+}
+
+/*
+ * Should always be called after QIF sync read has been performed, and all
+ * attributes required have been accessed.
+ */
+static inline void da9150_fg_read_sync_end(struct da9150_fg *fg)
+{
+ mutex_unlock(&fg->io_lock);
+}
+
+/* Sync read of single QIF attribute */
+static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size)
+{
+ u32 val;
+
+ da9150_fg_read_sync_start(fg);
+ val = da9150_fg_read_attr(fg, code, size);
+ da9150_fg_read_sync_end(fg);
+
+ return val;
+}
+
+/* Wait for QIF Sync, write QIF data and wait for ack */
+static void da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size,
+ u32 val)
+{
+ int i = 0;
+ u32 res = 0, sync_val;
+
+ mutex_lock(&fg->io_lock);
+
+ /* Check if QIF sync already requested */
+ res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+ DA9150_QIF_SYNC_SIZE);
+
+ /* Wait for an existing sync to complete */
+ while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
+ usleep_range(DA9150_QIF_SYNC_TIMEOUT,
+ DA9150_QIF_SYNC_TIMEOUT * 2);
+ res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+ DA9150_QIF_SYNC_SIZE);
+ }
+
+ if (res == 0) {
+ dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n");
+ mutex_unlock(&fg->io_lock);
+ return;
+ }
+
+ /* Write value for QIF code */
+ da9150_fg_write_attr(fg, code, size, val);
+
+ /* Wait for write acknowledgment */
+ i = 0;
+ sync_val = res;
+ while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
+ usleep_range(DA9150_QIF_SYNC_TIMEOUT,
+ DA9150_QIF_SYNC_TIMEOUT * 2);
+ res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+ DA9150_QIF_SYNC_SIZE);
+ }
+
+ mutex_unlock(&fg->io_lock);
+
+ /* Check write was actually successful */
+ if (res != (sync_val + 1))
+ dev_err(fg->dev, "Error performing QIF sync write for code %d\n",
+ code);
+}
+
+/* Power Supply attributes */
+static int da9150_fg_capacity(struct da9150_fg *fg,
+ union power_supply_propval *val)
+{
+ val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
+ DA9150_QIF_SOC_PCT_SIZE);
+
+ if (val->intval > 100)
+ val->intval = 100;
+
+ return 0;
+}
+
+static int da9150_fg_current_avg(struct da9150_fg *fg,
+ union power_supply_propval *val)
+{
+ u32 iavg, sd_gain, shunt_val;
+ u64 div, res;
+
+ da9150_fg_read_sync_start(fg);
+ iavg = da9150_fg_read_attr(fg, DA9150_QIF_IAVG,
+ DA9150_QIF_IAVG_SIZE);
+ shunt_val = da9150_fg_read_attr(fg, DA9150_QIF_SHUNT_VAL,
+ DA9150_QIF_SHUNT_VAL_SIZE);
+ sd_gain = da9150_fg_read_attr(fg, DA9150_QIF_SD_GAIN,
+ DA9150_QIF_SD_GAIN_SIZE);
+ da9150_fg_read_sync_end(fg);
+
+ div = (u64) (sd_gain * shunt_val * 65536ULL);
+ do_div(div, 1000000);
+ res = (u64) (iavg * 1000000ULL);
+ do_div(res, div);
+
+ val->intval = (int) res;
+
+ return 0;
+}
+
+static int da9150_fg_voltage_avg(struct da9150_fg *fg,
+ union power_supply_propval *val)
+{
+ u64 res;
+
+ val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_UAVG,
+ DA9150_QIF_UAVG_SIZE);
+
+ res = (u64) (val->intval * 186ULL);
+ do_div(res, 10000);
+ val->intval = (int) res;
+
+ return 0;
+}
+
+static int da9150_fg_charge_full(struct da9150_fg *fg,
+ union power_supply_propval *val)
+{
+ val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_FCC_MAH,
+ DA9150_QIF_FCC_MAH_SIZE);
+
+ val->intval = val->intval * 1000;
+
+ return 0;
+}
+
+/*
+ * Temperature reading from device is only valid if battery/system provides
+ * valid NTC to associated pin of DA9150 chip.
+ */
+static int da9150_fg_temp(struct da9150_fg *fg,
+ union power_supply_propval *val)
+{
+ val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG,
+ DA9150_QIF_NTCAVG_SIZE);
+
+ val->intval = (val->intval * 10) / 1048576;
+
+ return 0;
+}
+
+static enum power_supply_property da9150_fg_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+static int da9150_fg_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = da9150_fg_capacity(fg, val);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = da9150_fg_current_avg(fg, val);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = da9150_fg_voltage_avg(fg, val);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ ret = da9150_fg_charge_full(fg, val);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = da9150_fg_temp(fg, val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/* Repeated SOC check */
+static bool da9150_fg_soc_changed(struct da9150_fg *fg)
+{
+ union power_supply_propval val;
+
+ da9150_fg_capacity(fg, &val);
+ if (val.intval != fg->soc) {
+ fg->soc = val.intval;
+ return true;
+ }
+
+ return false;
+}
+
+static void da9150_fg_work(struct work_struct *work)
+{
+ struct da9150_fg *fg = container_of(work, struct da9150_fg, work.work);
+
+ /* Report if SOC has changed */
+ if (da9150_fg_soc_changed(fg))
+ power_supply_changed(fg->battery);
+
+ schedule_delayed_work(&fg->work, msecs_to_jiffies(fg->interval));
+}
+
+/* SOC level event configuration */
+static void da9150_fg_soc_event_config(struct da9150_fg *fg)
+{
+ int soc;
+
+ soc = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
+ DA9150_QIF_SOC_PCT_SIZE);
+
+ if (soc > fg->warn_soc) {
+ /* If SOC > warn level, set discharge warn level event */
+ da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
+ DA9150_QIF_DISCHARGE_LIMIT_SIZE,
+ fg->warn_soc + 1);
+ } else if ((soc <= fg->warn_soc) && (soc > fg->crit_soc)) {
+ /*
+ * If SOC <= warn level, set discharge crit level event,
+ * and set charge warn level event.
+ */
+ da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
+ DA9150_QIF_DISCHARGE_LIMIT_SIZE,
+ fg->crit_soc + 1);
+
+ da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
+ DA9150_QIF_CHARGE_LIMIT_SIZE,
+ fg->warn_soc);
+ } else if (soc <= fg->crit_soc) {
+ /* If SOC <= crit level, set charge crit level event */
+ da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
+ DA9150_QIF_CHARGE_LIMIT_SIZE,
+ fg->crit_soc);
+ }
+}
+
+static irqreturn_t da9150_fg_irq(int irq, void *data)
+{
+ struct da9150_fg *fg = data;
+ u32 e_fg_status;
+
+ /* Read FG IRQ status info */
+ e_fg_status = da9150_fg_read_attr(fg, DA9150_QIF_E_FG_STATUS,
+ DA9150_QIF_E_FG_STATUS_SIZE);
+
+ /* Handle warning/critical threhold events */
+ if (e_fg_status & DA9150_FG_IRQ_SOC_MASK)
+ da9150_fg_soc_event_config(fg);
+
+ /* Clear any FG IRQs */
+ da9150_fg_write_attr(fg, DA9150_QIF_E_FG_STATUS,
+ DA9150_QIF_E_FG_STATUS_SIZE, e_fg_status);
+
+ return IRQ_HANDLED;
+}
+
+static struct da9150_fg_pdata *da9150_fg_dt_pdata(struct device *dev)
+{
+ struct device_node *fg_node = dev->of_node;
+ struct da9150_fg_pdata *pdata;
+
+ pdata = devm_kzalloc(dev, sizeof(struct da9150_fg_pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ of_property_read_u32(fg_node, "dlg,update-interval",
+ &pdata->update_interval);
+ of_property_read_u8(fg_node, "dlg,warn-soc-level",
+ &pdata->warn_soc_lvl);
+ of_property_read_u8(fg_node, "dlg,crit-soc-level",
+ &pdata->crit_soc_lvl);
+
+ return pdata;
+}
+
+static const struct power_supply_desc fg_desc = {
+ .name = "da9150-fg",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = da9150_fg_props,
+ .num_properties = ARRAY_SIZE(da9150_fg_props),
+ .get_property = da9150_fg_get_prop,
+};
+
+static int da9150_fg_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+ struct da9150_fg_pdata *fg_pdata = dev_get_platdata(dev);
+ struct da9150_fg *fg;
+ int ver, irq, ret = 0;
+
+ fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL);
+ if (fg == NULL)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, fg);
+ fg->da9150 = da9150;
+ fg->dev = dev;
+
+ mutex_init(&fg->io_lock);
+
+ /* Enable QIF */
+ da9150_set_bits(da9150, DA9150_CORE2WIRE_CTRL_A, DA9150_FG_QIF_EN_MASK,
+ DA9150_FG_QIF_EN_MASK);
+
+ fg->battery = devm_power_supply_register(dev, &fg_desc, NULL);
+ if (IS_ERR(fg->battery)) {
+ ret = PTR_ERR(fg->battery);
+ return ret;
+ }
+
+ ver = da9150_fg_read_attr(fg, DA9150_QIF_FW_MAIN_VER,
+ DA9150_QIF_FW_MAIN_VER_SIZE);
+ dev_info(dev, "Version: 0x%x\n", ver);
+
+ /* Handle DT data if provided */
+ if (dev->of_node) {
+ fg_pdata = da9150_fg_dt_pdata(dev);
+ dev->platform_data = fg_pdata;
+ }
+
+ /* Handle any pdata provided */
+ if (fg_pdata) {
+ fg->interval = fg_pdata->update_interval;
+
+ if (fg_pdata->warn_soc_lvl > 100)
+ dev_warn(dev, "Invalid SOC warning level provided, Ignoring");
+ else
+ fg->warn_soc = fg_pdata->warn_soc_lvl;
+
+ if ((fg_pdata->crit_soc_lvl > 100) ||
+ (fg_pdata->crit_soc_lvl >= fg_pdata->warn_soc_lvl))
+ dev_warn(dev, "Invalid SOC critical level provided, Ignoring");
+ else
+ fg->crit_soc = fg_pdata->crit_soc_lvl;
+
+
+ }
+
+ /* Configure initial SOC level events */
+ da9150_fg_soc_event_config(fg);
+
+ /*
+ * If an interval period has been provided then setup repeating
+ * work for reporting data updates.
+ */
+ if (fg->interval) {
+ INIT_DELAYED_WORK(&fg->work, da9150_fg_work);
+ schedule_delayed_work(&fg->work,
+ msecs_to_jiffies(fg->interval));
+ }
+
+ /* Register IRQ */
+ irq = platform_get_irq_byname(pdev, "FG");
+ if (irq < 0) {
+ dev_err(dev, "Failed to get IRQ FG: %d\n", irq);
+ ret = irq;
+ goto irq_fail;
+ }
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq,
+ IRQF_ONESHOT, "FG", fg);
+ if (ret) {
+ dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
+ goto irq_fail;
+ }
+
+ return 0;
+
+irq_fail:
+ if (fg->interval)
+ cancel_delayed_work(&fg->work);
+
+ return ret;
+}
+
+static int da9150_fg_remove(struct platform_device *pdev)
+{
+ struct da9150_fg *fg = platform_get_drvdata(pdev);
+
+ if (fg->interval)
+ cancel_delayed_work(&fg->work);
+
+ return 0;
+}
+
+static int da9150_fg_resume(struct platform_device *pdev)
+{
+ struct da9150_fg *fg = platform_get_drvdata(pdev);
+
+ /*
+ * Trigger SOC check to happen now so as to indicate any value change
+ * since last check before suspend.
+ */
+ if (fg->interval)
+ flush_delayed_work(&fg->work);
+
+ return 0;
+}
+
+static struct platform_driver da9150_fg_driver = {
+ .driver = {
+ .name = "da9150-fuel-gauge",
+ },
+ .probe = da9150_fg_probe,
+ .remove = da9150_fg_remove,
+ .resume = da9150_fg_resume,
+};
+
+module_platform_driver(da9150_fg_driver);
+
+MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index 7e741f1d3cd5..042fb3dacb46 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -508,23 +508,23 @@ out:
return param;
}
-static int lp8727_parse_dt(struct device *dev)
+static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
struct device_node *child;
struct lp8727_platform_data *pdata;
const char *type;
- /* If charging parameter is not defined, just skip parsing the dt */
- if (of_get_child_count(np) == 0)
- goto out;
-
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec);
+ /* If charging parameter is not defined, just skip parsing the dt */
+ if (of_get_child_count(np) == 0)
+ return pdata;
+
for_each_child_of_node(np, child) {
of_property_read_string(child, "charger-type", &type);
@@ -535,29 +535,30 @@ static int lp8727_parse_dt(struct device *dev)
pdata->usb = lp8727_parse_charge_pdata(dev, child);
}
- dev->platform_data = pdata;
-out:
- return 0;
+ return pdata;
}
#else
-static int lp8727_parse_dt(struct device *dev)
+static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
{
- return 0;
+ return NULL;
}
#endif
static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
{
struct lp8727_chg *pchg;
+ struct lp8727_platform_data *pdata;
int ret;
if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
if (cl->dev.of_node) {
- ret = lp8727_parse_dt(&cl->dev);
- if (ret)
- return ret;
+ pdata = lp8727_parse_dt(&cl->dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ } else {
+ pdata = dev_get_platdata(&cl->dev);
}
pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);
@@ -566,7 +567,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
pchg->client = cl;
pchg->dev = &cl->dev;
- pchg->pdata = cl->dev.platform_data;
+ pchg->pdata = pdata;
i2c_set_clientdata(cl, pchg);
mutex_init(&pchg->xfer_lock);
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index e89255764745..9c65f134d447 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -909,18 +909,21 @@ static int max17042_probe(struct i2c_client *client,
regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
}
- chip->battery = power_supply_register(&client->dev, max17042_desc,
- &psy_cfg);
+ chip->battery = devm_power_supply_register(&client->dev, max17042_desc,
+ &psy_cfg);
if (IS_ERR(chip->battery)) {
dev_err(&client->dev, "failed: power supply register\n");
return PTR_ERR(chip->battery);
}
if (client->irq) {
- ret = request_threaded_irq(client->irq, NULL,
- max17042_thread_handler,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- chip->battery->desc->name, chip);
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL,
+ max17042_thread_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ chip->battery->desc->name,
+ chip);
if (!ret) {
regmap_update_bits(chip->regmap, MAX17042_CONFIG,
CONFIG_ALRT_BIT_ENBL,
@@ -944,16 +947,6 @@ static int max17042_probe(struct i2c_client *client,
return 0;
}
-static int max17042_remove(struct i2c_client *client)
-{
- struct max17042_chip *chip = i2c_get_clientdata(client);
-
- if (client->irq)
- free_irq(client->irq, chip);
- power_supply_unregister(chip->battery);
- return 0;
-}
-
#ifdef CONFIG_PM_SLEEP
static int max17042_suspend(struct device *dev)
{
@@ -1014,7 +1007,6 @@ static struct i2c_driver max17042_i2c_driver = {
.pm = &max17042_pm_ops,
},
.probe = max17042_probe,
- .remove = max17042_remove,
.id_table = max17042_id,
};
module_i2c_driver(max17042_i2c_driver);
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index bf2b4b3a7cae..6d39d52040d4 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -201,8 +201,7 @@ static int max8903_probe(struct platform_device *pdev)
if (pdata->dc_valid == false && pdata->usb_valid == false) {
dev_err(dev, "No valid power sources.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
if (pdata->dc_valid) {
@@ -216,8 +215,7 @@ static int max8903_probe(struct platform_device *pdev)
} else {
dev_err(dev, "When DC is wired, DOK and DCM should"
" be wired as well.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
} else {
if (pdata->dcm) {
@@ -225,8 +223,7 @@ static int max8903_probe(struct platform_device *pdev)
gpio_set_value(pdata->dcm, 0);
else {
dev_err(dev, "Invalid pin: dcm.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
}
}
@@ -238,8 +235,7 @@ static int max8903_probe(struct platform_device *pdev)
} else {
dev_err(dev, "When USB is wired, UOK should be wired."
"as well.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
}
@@ -248,32 +244,28 @@ static int max8903_probe(struct platform_device *pdev)
gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1);
} else {
dev_err(dev, "Invalid pin: cen.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
}
if (pdata->chg) {
if (!gpio_is_valid(pdata->chg)) {
dev_err(dev, "Invalid pin: chg.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
}
if (pdata->flt) {
if (!gpio_is_valid(pdata->flt)) {
dev_err(dev, "Invalid pin: flt.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
}
if (pdata->usus) {
if (!gpio_is_valid(pdata->usus)) {
dev_err(dev, "Invalid pin: usus.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
}
@@ -291,85 +283,56 @@ static int max8903_probe(struct platform_device *pdev)
psy_cfg.drv_data = data;
- data->psy = power_supply_register(dev, &data->psy_desc, &psy_cfg);
+ data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg);
if (IS_ERR(data->psy)) {
dev_err(dev, "failed: power supply register.\n");
- ret = PTR_ERR(data->psy);
- goto err;
+ return PTR_ERR(data->psy);
}
if (pdata->dc_valid) {
- ret = request_threaded_irq(gpio_to_irq(pdata->dok),
- NULL, max8903_dcin,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "MAX8903 DC IN", data);
+ ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok),
+ NULL, max8903_dcin,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING,
+ "MAX8903 DC IN", data);
if (ret) {
dev_err(dev, "Cannot request irq %d for DC (%d)\n",
gpio_to_irq(pdata->dok), ret);
- goto err_psy;
+ return ret;
}
}
if (pdata->usb_valid) {
- ret = request_threaded_irq(gpio_to_irq(pdata->uok),
- NULL, max8903_usbin,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "MAX8903 USB IN", data);
+ ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok),
+ NULL, max8903_usbin,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING,
+ "MAX8903 USB IN", data);
if (ret) {
dev_err(dev, "Cannot request irq %d for USB (%d)\n",
gpio_to_irq(pdata->uok), ret);
- goto err_dc_irq;
+ return ret;
}
}
if (pdata->flt) {
- ret = request_threaded_irq(gpio_to_irq(pdata->flt),
- NULL, max8903_fault,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "MAX8903 Fault", data);
+ ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt),
+ NULL, max8903_fault,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING,
+ "MAX8903 Fault", data);
if (ret) {
dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
gpio_to_irq(pdata->flt), ret);
- goto err_usb_irq;
+ return ret;
}
}
return 0;
-
-err_usb_irq:
- if (pdata->usb_valid)
- free_irq(gpio_to_irq(pdata->uok), data);
-err_dc_irq:
- if (pdata->dc_valid)
- free_irq(gpio_to_irq(pdata->dok), data);
-err_psy:
- power_supply_unregister(data->psy);
-err:
- return ret;
-}
-
-static int max8903_remove(struct platform_device *pdev)
-{
- struct max8903_data *data = platform_get_drvdata(pdev);
-
- if (data) {
- struct max8903_pdata *pdata = &data->pdata;
-
- if (pdata->flt)
- free_irq(gpio_to_irq(pdata->flt), data);
- if (pdata->usb_valid)
- free_irq(gpio_to_irq(pdata->uok), data);
- if (pdata->dc_valid)
- free_irq(gpio_to_irq(pdata->dok), data);
- power_supply_unregister(data->psy);
- }
-
- return 0;
}
static struct platform_driver max8903_driver = {
.probe = max8903_probe,
- .remove = max8903_remove,
.driver = {
.name = "max8903-charger",
},
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 47448d4bc6cd..b64cf0f14142 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -117,8 +117,7 @@ static int max8998_battery_probe(struct platform_device *pdev)
"EOC value not set: leave it unchanged.\n");
} else {
dev_err(max8998->dev, "Invalid EOC value\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
/* Setup Charge Restart Level */
@@ -141,8 +140,7 @@ static int max8998_battery_probe(struct platform_device *pdev)
break;
default:
dev_err(max8998->dev, "Invalid Restart Level\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
/* Setup Charge Full Timeout */
@@ -165,34 +163,22 @@ static int max8998_battery_probe(struct platform_device *pdev)
break;
default:
dev_err(max8998->dev, "Invalid Full Timeout value\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
psy_cfg.drv_data = max8998;
- max8998->battery = power_supply_register(max8998->dev,
- &max8998_battery_desc,
- &psy_cfg);
+ max8998->battery = devm_power_supply_register(max8998->dev,
+ &max8998_battery_desc,
+ &psy_cfg);
if (IS_ERR(max8998->battery)) {
ret = PTR_ERR(max8998->battery);
dev_err(max8998->dev, "failed: power supply register: %d\n",
ret);
- goto err;
+ return ret;
}
return 0;
-err:
- return ret;
-}
-
-static int max8998_battery_remove(struct platform_device *pdev)
-{
- struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
-
- power_supply_unregister(max8998->battery);
-
- return 0;
}
static const struct platform_device_id max8998_battery_id[] = {
@@ -205,7 +191,6 @@ static struct platform_driver max8998_battery_driver = {
.name = "max8998-battery",
},
.probe = max8998_battery_probe,
- .remove = max8998_battery_remove,
.id_table = max8998_battery_id,
};
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c
index 3a45cc0c4dce..8f9bd1d0eeb6 100644
--- a/drivers/power/pm2301_charger.c
+++ b/drivers/power/pm2301_charger.c
@@ -1264,5 +1264,4 @@ module_exit(pm2xxx_charger_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay");
-MODULE_ALIAS("i2c:pm2xxx-charger");
MODULE_DESCRIPTION("PM2xxx charger management driver");
diff --git a/drivers/power/qcom_smbb.c b/drivers/power/qcom_smbb.c
new file mode 100644
index 000000000000..5eb1e9e543e2
--- /dev/null
+++ b/drivers/power/qcom_smbb.c
@@ -0,0 +1,951 @@
+/* Copyright (c) 2014, Sony Mobile Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ * This driver is for the multi-block Switch-Mode Battery Charger and Boost
+ * (SMBB) hardware, found in Qualcomm PM8941 PMICs. The charger is an
+ * integrated, single-cell lithium-ion battery charger.
+ *
+ * Sub-components:
+ * - Charger core
+ * - Buck
+ * - DC charge-path
+ * - USB charge-path
+ * - Battery interface
+ * - Boost (not implemented)
+ * - Misc
+ * - HF-Buck
+ */
+
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define SMBB_CHG_VMAX 0x040
+#define SMBB_CHG_VSAFE 0x041
+#define SMBB_CHG_CFG 0x043
+#define SMBB_CHG_IMAX 0x044
+#define SMBB_CHG_ISAFE 0x045
+#define SMBB_CHG_VIN_MIN 0x047
+#define SMBB_CHG_CTRL 0x049
+#define CTRL_EN BIT(7)
+#define SMBB_CHG_VBAT_WEAK 0x052
+#define SMBB_CHG_IBAT_TERM_CHG 0x05b
+#define IBAT_TERM_CHG_IEOC BIT(7)
+#define IBAT_TERM_CHG_IEOC_BMS BIT(7)
+#define IBAT_TERM_CHG_IEOC_CHG 0
+#define SMBB_CHG_VBAT_DET 0x05d
+#define SMBB_CHG_TCHG_MAX_EN 0x060
+#define TCHG_MAX_EN BIT(7)
+#define SMBB_CHG_WDOG_TIME 0x062
+#define SMBB_CHG_WDOG_EN 0x065
+#define WDOG_EN BIT(7)
+
+#define SMBB_BUCK_REG_MODE 0x174
+#define BUCK_REG_MODE BIT(0)
+#define BUCK_REG_MODE_VBAT BIT(0)
+#define BUCK_REG_MODE_VSYS 0
+
+#define SMBB_BAT_PRES_STATUS 0x208
+#define PRES_STATUS_BAT_PRES BIT(7)
+#define SMBB_BAT_TEMP_STATUS 0x209
+#define TEMP_STATUS_OK BIT(7)
+#define TEMP_STATUS_HOT BIT(6)
+#define SMBB_BAT_BTC_CTRL 0x249
+#define BTC_CTRL_COMP_EN BIT(7)
+#define BTC_CTRL_COLD_EXT BIT(1)
+#define BTC_CTRL_HOT_EXT_N BIT(0)
+
+#define SMBB_USB_IMAX 0x344
+#define SMBB_USB_ENUM_TIMER_STOP 0x34e
+#define ENUM_TIMER_STOP BIT(0)
+#define SMBB_USB_SEC_ACCESS 0x3d0
+#define SEC_ACCESS_MAGIC 0xa5
+#define SMBB_USB_REV_BST 0x3ed
+#define REV_BST_CHG_GONE BIT(7)
+
+#define SMBB_DC_IMAX 0x444
+
+#define SMBB_MISC_REV2 0x601
+#define SMBB_MISC_BOOT_DONE 0x642
+#define BOOT_DONE BIT(7)
+
+#define STATUS_USBIN_VALID BIT(0) /* USB connection is valid */
+#define STATUS_DCIN_VALID BIT(1) /* DC connection is valid */
+#define STATUS_BAT_HOT BIT(2) /* Battery temp 1=Hot, 0=Cold */
+#define STATUS_BAT_OK BIT(3) /* Battery temp OK */
+#define STATUS_BAT_PRESENT BIT(4) /* Battery is present */
+#define STATUS_CHG_DONE BIT(5) /* Charge cycle is complete */
+#define STATUS_CHG_TRKL BIT(6) /* Trickle charging */
+#define STATUS_CHG_FAST BIT(7) /* Fast charging */
+#define STATUS_CHG_GONE BIT(8) /* No charger is connected */
+
+enum smbb_attr {
+ ATTR_BAT_ISAFE,
+ ATTR_BAT_IMAX,
+ ATTR_USBIN_IMAX,
+ ATTR_DCIN_IMAX,
+ ATTR_BAT_VSAFE,
+ ATTR_BAT_VMAX,
+ ATTR_BAT_VMIN,
+ ATTR_CHG_VDET,
+ ATTR_VIN_MIN,
+ _ATTR_CNT,
+};
+
+struct smbb_charger {
+ unsigned int revision;
+ unsigned int addr;
+ struct device *dev;
+
+ bool dc_disabled;
+ bool jeita_ext_temp;
+ unsigned long status;
+ struct mutex statlock;
+
+ unsigned int attr[_ATTR_CNT];
+
+ struct power_supply *usb_psy;
+ struct power_supply *dc_psy;
+ struct power_supply *bat_psy;
+ struct regmap *regmap;
+};
+
+static int smbb_vbat_weak_fn(unsigned int index)
+{
+ return 2100000 + index * 100000;
+}
+
+static int smbb_vin_fn(unsigned int index)
+{
+ if (index > 42)
+ return 5600000 + (index - 43) * 200000;
+ return 3400000 + index * 50000;
+}
+
+static int smbb_vmax_fn(unsigned int index)
+{
+ return 3240000 + index * 10000;
+}
+
+static int smbb_vbat_det_fn(unsigned int index)
+{
+ return 3240000 + index * 20000;
+}
+
+static int smbb_imax_fn(unsigned int index)
+{
+ if (index < 2)
+ return 100000 + index * 50000;
+ return index * 100000;
+}
+
+static int smbb_bat_imax_fn(unsigned int index)
+{
+ return index * 50000;
+}
+
+static unsigned int smbb_hw_lookup(unsigned int val, int (*fn)(unsigned int))
+{
+ unsigned int widx;
+ unsigned int sel;
+
+ for (widx = sel = 0; (*fn)(widx) <= val; ++widx)
+ sel = widx;
+
+ return sel;
+}
+
+static const struct smbb_charger_attr {
+ const char *name;
+ unsigned int reg;
+ unsigned int safe_reg;
+ unsigned int max;
+ unsigned int min;
+ unsigned int fail_ok;
+ int (*hw_fn)(unsigned int);
+} smbb_charger_attrs[] = {
+ [ATTR_BAT_ISAFE] = {
+ .name = "qcom,fast-charge-safe-current",
+ .reg = SMBB_CHG_ISAFE,
+ .max = 3000000,
+ .min = 200000,
+ .hw_fn = smbb_bat_imax_fn,
+ .fail_ok = 1,
+ },
+ [ATTR_BAT_IMAX] = {
+ .name = "qcom,fast-charge-current-limit",
+ .reg = SMBB_CHG_IMAX,
+ .safe_reg = SMBB_CHG_ISAFE,
+ .max = 3000000,
+ .min = 200000,
+ .hw_fn = smbb_bat_imax_fn,
+ },
+ [ATTR_DCIN_IMAX] = {
+ .name = "qcom,dc-current-limit",
+ .reg = SMBB_DC_IMAX,
+ .max = 2500000,
+ .min = 100000,
+ .hw_fn = smbb_imax_fn,
+ },
+ [ATTR_BAT_VSAFE] = {
+ .name = "qcom,fast-charge-safe-voltage",
+ .reg = SMBB_CHG_VSAFE,
+ .max = 5000000,
+ .min = 3240000,
+ .hw_fn = smbb_vmax_fn,
+ .fail_ok = 1,
+ },
+ [ATTR_BAT_VMAX] = {
+ .name = "qcom,fast-charge-high-threshold-voltage",
+ .reg = SMBB_CHG_VMAX,
+ .safe_reg = SMBB_CHG_VSAFE,
+ .max = 5000000,
+ .min = 3240000,
+ .hw_fn = smbb_vmax_fn,
+ },
+ [ATTR_BAT_VMIN] = {
+ .name = "qcom,fast-charge-low-threshold-voltage",
+ .reg = SMBB_CHG_VBAT_WEAK,
+ .max = 3600000,
+ .min = 2100000,
+ .hw_fn = smbb_vbat_weak_fn,
+ },
+ [ATTR_CHG_VDET] = {
+ .name = "qcom,auto-recharge-threshold-voltage",
+ .reg = SMBB_CHG_VBAT_DET,
+ .max = 5000000,
+ .min = 3240000,
+ .hw_fn = smbb_vbat_det_fn,
+ },
+ [ATTR_VIN_MIN] = {
+ .name = "qcom,minimum-input-voltage",
+ .reg = SMBB_CHG_VIN_MIN,
+ .max = 9600000,
+ .min = 4200000,
+ .hw_fn = smbb_vin_fn,
+ },
+ [ATTR_USBIN_IMAX] = {
+ .name = "usb-charge-current-limit",
+ .reg = SMBB_USB_IMAX,
+ .max = 2500000,
+ .min = 100000,
+ .hw_fn = smbb_imax_fn,
+ },
+};
+
+static int smbb_charger_attr_write(struct smbb_charger *chg,
+ enum smbb_attr which, unsigned int val)
+{
+ const struct smbb_charger_attr *prop;
+ unsigned int wval;
+ unsigned int out;
+ int rc;
+
+ prop = &smbb_charger_attrs[which];
+
+ if (val > prop->max || val < prop->min) {
+ dev_err(chg->dev, "value out of range for %s [%u:%u]\n",
+ prop->name, prop->min, prop->max);
+ return -EINVAL;
+ }
+
+ if (prop->safe_reg) {
+ rc = regmap_read(chg->regmap,
+ chg->addr + prop->safe_reg, &wval);
+ if (rc) {
+ dev_err(chg->dev,
+ "unable to read safe value for '%s'\n",
+ prop->name);
+ return rc;
+ }
+
+ wval = prop->hw_fn(wval);
+
+ if (val > wval) {
+ dev_warn(chg->dev,
+ "%s above safe value, clamping at %u\n",
+ prop->name, wval);
+ val = wval;
+ }
+ }
+
+ wval = smbb_hw_lookup(val, prop->hw_fn);
+
+ rc = regmap_write(chg->regmap, chg->addr + prop->reg, wval);
+ if (rc) {
+ dev_err(chg->dev, "unable to update %s", prop->name);
+ return rc;
+ }
+ out = prop->hw_fn(wval);
+ if (out != val) {
+ dev_warn(chg->dev,
+ "%s inaccurate, rounded to %u\n",
+ prop->name, out);
+ }
+
+ dev_dbg(chg->dev, "%s <= %d\n", prop->name, out);
+
+ chg->attr[which] = out;
+
+ return 0;
+}
+
+static int smbb_charger_attr_read(struct smbb_charger *chg,
+ enum smbb_attr which)
+{
+ const struct smbb_charger_attr *prop;
+ unsigned int val;
+ int rc;
+
+ prop = &smbb_charger_attrs[which];
+
+ rc = regmap_read(chg->regmap, chg->addr + prop->reg, &val);
+ if (rc) {
+ dev_err(chg->dev, "failed to read %s\n", prop->name);
+ return rc;
+ }
+ val = prop->hw_fn(val);
+ dev_dbg(chg->dev, "%s => %d\n", prop->name, val);
+
+ chg->attr[which] = val;
+
+ return 0;
+}
+
+static int smbb_charger_attr_parse(struct smbb_charger *chg,
+ enum smbb_attr which)
+{
+ const struct smbb_charger_attr *prop;
+ unsigned int val;
+ int rc;
+
+ prop = &smbb_charger_attrs[which];
+
+ rc = of_property_read_u32(chg->dev->of_node, prop->name, &val);
+ if (rc == 0) {
+ rc = smbb_charger_attr_write(chg, which, val);
+ if (!rc || !prop->fail_ok)
+ return rc;
+ }
+ return smbb_charger_attr_read(chg, which);
+}
+
+static void smbb_set_line_flag(struct smbb_charger *chg, int irq, int flag)
+{
+ bool state;
+ int ret;
+
+ ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL, &state);
+ if (ret < 0) {
+ dev_err(chg->dev, "failed to read irq line\n");
+ return;
+ }
+
+ mutex_lock(&chg->statlock);
+ if (state)
+ chg->status |= flag;
+ else
+ chg->status &= ~flag;
+ mutex_unlock(&chg->statlock);
+
+ dev_dbg(chg->dev, "status = %03lx\n", chg->status);
+}
+
+static irqreturn_t smbb_usb_valid_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_USBIN_VALID);
+ power_supply_changed(chg->usb_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_dc_valid_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_DCIN_VALID);
+ if (!chg->dc_disabled)
+ power_supply_changed(chg->dc_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_bat_temp_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+ unsigned int val;
+ int rc;
+
+ rc = regmap_read(chg->regmap, chg->addr + SMBB_BAT_TEMP_STATUS, &val);
+ if (rc)
+ return IRQ_HANDLED;
+
+ mutex_lock(&chg->statlock);
+ if (val & TEMP_STATUS_OK) {
+ chg->status |= STATUS_BAT_OK;
+ } else {
+ chg->status &= ~STATUS_BAT_OK;
+ if (val & TEMP_STATUS_HOT)
+ chg->status |= STATUS_BAT_HOT;
+ }
+ mutex_unlock(&chg->statlock);
+
+ power_supply_changed(chg->bat_psy);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_bat_present_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_BAT_PRESENT);
+ power_supply_changed(chg->bat_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_chg_done_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_CHG_DONE);
+ power_supply_changed(chg->bat_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_chg_gone_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_CHG_GONE);
+ power_supply_changed(chg->bat_psy);
+ power_supply_changed(chg->usb_psy);
+ if (!chg->dc_disabled)
+ power_supply_changed(chg->dc_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_chg_fast_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_CHG_FAST);
+ power_supply_changed(chg->bat_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smbb_chg_trkl_handler(int irq, void *_data)
+{
+ struct smbb_charger *chg = _data;
+
+ smbb_set_line_flag(chg, irq, STATUS_CHG_TRKL);
+ power_supply_changed(chg->bat_psy);
+
+ return IRQ_HANDLED;
+}
+
+static const struct smbb_irq {
+ const char *name;
+ irqreturn_t (*handler)(int, void *);
+} smbb_charger_irqs[] = {
+ { "chg-done", smbb_chg_done_handler },
+ { "chg-fast", smbb_chg_fast_handler },
+ { "chg-trkl", smbb_chg_trkl_handler },
+ { "bat-temp-ok", smbb_bat_temp_handler },
+ { "bat-present", smbb_bat_present_handler },
+ { "chg-gone", smbb_chg_gone_handler },
+ { "usb-valid", smbb_usb_valid_handler },
+ { "dc-valid", smbb_dc_valid_handler },
+};
+
+static int smbb_usbin_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct smbb_charger *chg = power_supply_get_drvdata(psy);
+ int rc = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ mutex_lock(&chg->statlock);
+ val->intval = !(chg->status & STATUS_CHG_GONE) &&
+ (chg->status & STATUS_USBIN_VALID);
+ mutex_unlock(&chg->statlock);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ val->intval = chg->attr[ATTR_USBIN_IMAX];
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
+ val->intval = 2500000;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int smbb_usbin_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct smbb_charger *chg = power_supply_get_drvdata(psy);
+ int rc;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ rc = smbb_charger_attr_write(chg, ATTR_USBIN_IMAX,
+ val->intval);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int smbb_dcin_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct smbb_charger *chg = power_supply_get_drvdata(psy);
+ int rc = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ mutex_lock(&chg->statlock);
+ val->intval = !(chg->status & STATUS_CHG_GONE) &&
+ (chg->status & STATUS_DCIN_VALID);
+ mutex_unlock(&chg->statlock);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ val->intval = chg->attr[ATTR_DCIN_IMAX];
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
+ val->intval = 2500000;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int smbb_dcin_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct smbb_charger *chg = power_supply_get_drvdata(psy);
+ int rc;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ rc = smbb_charger_attr_write(chg, ATTR_DCIN_IMAX,
+ val->intval);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int smbb_charger_writable_property(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ return psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT;
+}
+
+static int smbb_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct smbb_charger *chg = power_supply_get_drvdata(psy);
+ unsigned long status;
+ int rc = 0;
+
+ mutex_lock(&chg->statlock);
+ status = chg->status;
+ mutex_unlock(&chg->statlock);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (status & STATUS_CHG_GONE)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (!(status & (STATUS_DCIN_VALID | STATUS_USBIN_VALID)))
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (status & STATUS_CHG_DONE)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else if (!(status & STATUS_BAT_OK))
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (status & (STATUS_CHG_FAST | STATUS_CHG_TRKL))
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else /* everything is ok for charging, but we are not... */
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (status & STATUS_BAT_OK)
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ else if (status & STATUS_BAT_HOT)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ if (status & STATUS_CHG_FAST)
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ else if (status & STATUS_CHG_TRKL)
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ else
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(status & STATUS_BAT_PRESENT);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = chg->attr[ATTR_BAT_IMAX];
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ val->intval = chg->attr[ATTR_BAT_VMAX];
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ /* this charger is a single-cell lithium-ion battery charger
+ * only. If you hook up some other technology, there will be
+ * fireworks.
+ */
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = 3000000; /* single-cell li-ion low end */
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int smbb_battery_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct smbb_charger *chg = power_supply_get_drvdata(psy);
+ int rc;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ rc = smbb_charger_attr_write(chg, ATTR_BAT_IMAX, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ rc = smbb_charger_attr_write(chg, ATTR_BAT_VMAX, val->intval);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int smbb_battery_writable_property(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static enum power_supply_property smbb_charger_properties[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
+};
+
+static enum power_supply_property smbb_battery_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+};
+
+static const struct reg_off_mask_default {
+ unsigned int offset;
+ unsigned int mask;
+ unsigned int value;
+ unsigned int rev_mask;
+} smbb_charger_setup[] = {
+ /* The bootloader is supposed to set this... make sure anyway. */
+ { SMBB_MISC_BOOT_DONE, BOOT_DONE, BOOT_DONE },
+
+ /* Disable software timer */
+ { SMBB_CHG_TCHG_MAX_EN, TCHG_MAX_EN, 0 },
+
+ /* Clear and disable watchdog */
+ { SMBB_CHG_WDOG_TIME, 0xff, 160 },
+ { SMBB_CHG_WDOG_EN, WDOG_EN, 0 },
+
+ /* Use charger based EoC detection */
+ { SMBB_CHG_IBAT_TERM_CHG, IBAT_TERM_CHG_IEOC, IBAT_TERM_CHG_IEOC_CHG },
+
+ /* Disable GSM PA load adjustment.
+ * The PA signal is incorrectly connected on v2.
+ */
+ { SMBB_CHG_CFG, 0xff, 0x00, BIT(3) },
+
+ /* Use VBAT (not VSYS) to compensate for IR drop during fast charging */
+ { SMBB_BUCK_REG_MODE, BUCK_REG_MODE, BUCK_REG_MODE_VBAT },
+
+ /* Enable battery temperature comparators */
+ { SMBB_BAT_BTC_CTRL, BTC_CTRL_COMP_EN, BTC_CTRL_COMP_EN },
+
+ /* Stop USB enumeration timer */
+ { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP },
+
+#if 0 /* FIXME supposedly only to disable hardware ARB termination */
+ { SMBB_USB_SEC_ACCESS, SEC_ACCESS_MAGIC },
+ { SMBB_USB_REV_BST, 0xff, REV_BST_CHG_GONE },
+#endif
+
+ /* Stop USB enumeration timer, again */
+ { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP },
+
+ /* Enable charging */
+ { SMBB_CHG_CTRL, CTRL_EN, CTRL_EN },
+};
+
+static char *smbb_bif[] = { "smbb-bif" };
+
+static const struct power_supply_desc bat_psy_desc = {
+ .name = "smbb-bif",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = smbb_battery_properties,
+ .num_properties = ARRAY_SIZE(smbb_battery_properties),
+ .get_property = smbb_battery_get_property,
+ .set_property = smbb_battery_set_property,
+ .property_is_writeable = smbb_battery_writable_property,
+};
+
+static const struct power_supply_desc usb_psy_desc = {
+ .name = "smbb-usbin",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = smbb_charger_properties,
+ .num_properties = ARRAY_SIZE(smbb_charger_properties),
+ .get_property = smbb_usbin_get_property,
+ .set_property = smbb_usbin_set_property,
+ .property_is_writeable = smbb_charger_writable_property,
+};
+
+static const struct power_supply_desc dc_psy_desc = {
+ .name = "smbb-dcin",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = smbb_charger_properties,
+ .num_properties = ARRAY_SIZE(smbb_charger_properties),
+ .get_property = smbb_dcin_get_property,
+ .set_property = smbb_dcin_set_property,
+ .property_is_writeable = smbb_charger_writable_property,
+};
+
+static int smbb_charger_probe(struct platform_device *pdev)
+{
+ struct power_supply_config bat_cfg = {};
+ struct power_supply_config usb_cfg = {};
+ struct power_supply_config dc_cfg = {};
+ struct smbb_charger *chg;
+ int rc, i;
+
+ chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL);
+ if (!chg)
+ return -ENOMEM;
+
+ chg->dev = &pdev->dev;
+ mutex_init(&chg->statlock);
+
+ chg->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chg->regmap) {
+ dev_err(&pdev->dev, "failed to locate regmap\n");
+ return -ENODEV;
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &chg->addr);
+ if (rc) {
+ dev_err(&pdev->dev, "missing or invalid 'reg' property\n");
+ return rc;
+ }
+
+ rc = regmap_read(chg->regmap, chg->addr + SMBB_MISC_REV2, &chg->revision);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to read revision\n");
+ return rc;
+ }
+
+ chg->revision += 1;
+ if (chg->revision != 2 && chg->revision != 3) {
+ dev_err(&pdev->dev, "v1 hardware not supported\n");
+ return -ENODEV;
+ }
+ dev_info(&pdev->dev, "Initializing SMBB rev %u", chg->revision);
+
+ chg->dc_disabled = of_property_read_bool(pdev->dev.of_node, "qcom,disable-dc");
+
+ for (i = 0; i < _ATTR_CNT; ++i) {
+ rc = smbb_charger_attr_parse(chg, i);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to parse/apply settings\n");
+ return rc;
+ }
+ }
+
+ bat_cfg.drv_data = chg;
+ bat_cfg.of_node = pdev->dev.of_node;
+ chg->bat_psy = devm_power_supply_register(&pdev->dev,
+ &bat_psy_desc,
+ &bat_cfg);
+ if (IS_ERR(chg->bat_psy)) {
+ dev_err(&pdev->dev, "failed to register battery\n");
+ return PTR_ERR(chg->bat_psy);
+ }
+
+ usb_cfg.drv_data = chg;
+ usb_cfg.supplied_to = smbb_bif;
+ usb_cfg.num_supplicants = ARRAY_SIZE(smbb_bif);
+ chg->usb_psy = devm_power_supply_register(&pdev->dev,
+ &usb_psy_desc,
+ &usb_cfg);
+ if (IS_ERR(chg->usb_psy)) {
+ dev_err(&pdev->dev, "failed to register USB power supply\n");
+ return PTR_ERR(chg->usb_psy);
+ }
+
+ if (!chg->dc_disabled) {
+ dc_cfg.drv_data = chg;
+ dc_cfg.supplied_to = smbb_bif;
+ dc_cfg.num_supplicants = ARRAY_SIZE(smbb_bif);
+ chg->dc_psy = devm_power_supply_register(&pdev->dev,
+ &dc_psy_desc,
+ &dc_cfg);
+ if (IS_ERR(chg->dc_psy)) {
+ dev_err(&pdev->dev, "failed to register DC power supply\n");
+ return PTR_ERR(chg->dc_psy);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(smbb_charger_irqs); ++i) {
+ int irq;
+
+ irq = platform_get_irq_byname(pdev, smbb_charger_irqs[i].name);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq '%s'\n",
+ smbb_charger_irqs[i].name);
+ return irq;
+ }
+
+ smbb_charger_irqs[i].handler(irq, chg);
+
+ rc = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ smbb_charger_irqs[i].handler, IRQF_ONESHOT,
+ smbb_charger_irqs[i].name, chg);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to request irq '%s'\n",
+ smbb_charger_irqs[i].name);
+ return rc;
+ }
+ }
+
+ chg->jeita_ext_temp = of_property_read_bool(pdev->dev.of_node,
+ "qcom,jeita-extended-temp-range");
+
+ /* Set temperature range to [35%:70%] or [25%:80%] accordingly */
+ rc = regmap_update_bits(chg->regmap, chg->addr + SMBB_BAT_BTC_CTRL,
+ BTC_CTRL_COLD_EXT | BTC_CTRL_HOT_EXT_N,
+ chg->jeita_ext_temp ?
+ BTC_CTRL_COLD_EXT :
+ BTC_CTRL_HOT_EXT_N);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "unable to set %s temperature range\n",
+ chg->jeita_ext_temp ? "JEITA extended" : "normal");
+ return rc;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(smbb_charger_setup); ++i) {
+ const struct reg_off_mask_default *r = &smbb_charger_setup[i];
+
+ if (r->rev_mask & BIT(chg->revision))
+ continue;
+
+ rc = regmap_update_bits(chg->regmap, chg->addr + r->offset,
+ r->mask, r->value);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "unable to initializing charging, bailing\n");
+ return rc;
+ }
+ }
+
+ platform_set_drvdata(pdev, chg);
+
+ return 0;
+}
+
+static int smbb_charger_remove(struct platform_device *pdev)
+{
+ struct smbb_charger *chg;
+
+ chg = platform_get_drvdata(pdev);
+
+ regmap_update_bits(chg->regmap, chg->addr + SMBB_CHG_CTRL, CTRL_EN, 0);
+
+ return 0;
+}
+
+static const struct of_device_id smbb_charger_id_table[] = {
+ { .compatible = "qcom,pm8941-charger" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smbb_charger_id_table);
+
+static struct platform_driver smbb_charger_driver = {
+ .probe = smbb_charger_probe,
+ .remove = smbb_charger_remove,
+ .driver = {
+ .name = "qcom-smbb",
+ .of_match_table = smbb_charger_id_table,
+ },
+};
+module_platform_driver(smbb_charger_driver);
+
+MODULE_DESCRIPTION("Qualcomm Switch-Mode Battery Charger and Boost driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 5a0189bf19bb..1131cf75acc6 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -15,7 +15,7 @@ config POWER_RESET_AS3722
This driver supports turning off board via a ams AS3722 power-off.
config POWER_RESET_AT91_POWEROFF
- bool "Atmel AT91 poweroff driver"
+ tristate "Atmel AT91 poweroff driver"
depends on ARCH_AT91
default SOC_AT91SAM9 || SOC_SAMA5
help
@@ -23,7 +23,7 @@ config POWER_RESET_AT91_POWEROFF
SoCs
config POWER_RESET_AT91_RESET
- bool "Atmel AT91 reset driver"
+ tristate "Atmel AT91 reset driver"
depends on ARCH_AT91
default SOC_AT91SAM9 || SOC_SAMA5
help
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
index 9847cfb7e23d..e9e24df35f26 100644
--- a/drivers/power/reset/at91-poweroff.c
+++ b/drivers/power/reset/at91-poweroff.c
@@ -10,6 +10,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -48,6 +49,7 @@ static const char *shdwc_wakeup_modes[] = {
};
static void __iomem *at91_shdwc_base;
+static struct clk *sclk;
static void __init at91_wakeup_status(void)
{
@@ -119,9 +121,10 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
}
-static int at91_poweroff_probe(struct platform_device *pdev)
+static int __init at91_poweroff_probe(struct platform_device *pdev)
{
struct resource *res;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
@@ -130,6 +133,16 @@ static int at91_poweroff_probe(struct platform_device *pdev)
return PTR_ERR(at91_shdwc_base);
}
+ sclk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(sclk))
+ return PTR_ERR(sclk);
+
+ ret = clk_prepare_enable(sclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable slow clock\n");
+ return ret;
+ }
+
at91_wakeup_status();
if (pdev->dev.of_node)
@@ -140,6 +153,16 @@ static int at91_poweroff_probe(struct platform_device *pdev)
return 0;
}
+static int __exit at91_poweroff_remove(struct platform_device *pdev)
+{
+ if (pm_power_off == at91_poweroff)
+ pm_power_off = NULL;
+
+ clk_disable_unprepare(sclk);
+
+ return 0;
+}
+
static const struct of_device_id at91_poweroff_of_match[] = {
{ .compatible = "atmel,at91sam9260-shdwc", },
{ .compatible = "atmel,at91sam9rl-shdwc", },
@@ -148,10 +171,14 @@ static const struct of_device_id at91_poweroff_of_match[] = {
};
static struct platform_driver at91_poweroff_driver = {
- .probe = at91_poweroff_probe,
+ .remove = __exit_p(at91_poweroff_remove),
.driver = {
.name = "at91-poweroff",
.of_match_table = at91_poweroff_of_match,
},
};
-module_platform_driver(at91_poweroff_driver);
+module_platform_driver_probe(at91_poweroff_driver, at91_poweroff_probe);
+
+MODULE_AUTHOR("Atmel Corporation");
+MODULE_DESCRIPTION("Shutdown driver for Atmel SoCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
index c378d4ec826f..3f6b5dd7c3d4 100644
--- a/drivers/power/reset/at91-reset.c
+++ b/drivers/power/reset/at91-reset.c
@@ -1,5 +1,5 @@
/*
- * Atmel AT91 SAM9 SoCs reset code
+ * Atmel AT91 SAM9 & SAMA5 SoCs reset code
*
* Copyright (C) 2007 Atmel Corporation.
* Copyright (C) BitBox Ltd 2010
@@ -11,6 +11,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
@@ -46,6 +47,7 @@ enum reset_type {
};
static void __iomem *at91_ramc_base[2], *at91_rstc_base;
+static struct clk *sclk;
/*
* unless the SDRAM is cleanly shutdown before we hit the
@@ -178,11 +180,11 @@ static struct notifier_block at91_restart_nb = {
.priority = 192,
};
-static int at91_reset_of_probe(struct platform_device *pdev)
+static int __init at91_reset_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device_node *np;
- int idx = 0;
+ int ret, idx = 0;
at91_rstc_base = of_iomap(pdev->dev.of_node, 0);
if (!at91_rstc_base) {
@@ -204,53 +206,32 @@ static int at91_reset_of_probe(struct platform_device *pdev)
match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
at91_restart_nb.notifier_call = match->data;
- return register_restart_handler(&at91_restart_nb);
-}
-static int at91_reset_platform_probe(struct platform_device *pdev)
-{
- const struct platform_device_id *match;
- struct resource *res;
- int idx = 0;
+ sclk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(sclk))
+ return PTR_ERR(sclk);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(at91_rstc_base)) {
- dev_err(&pdev->dev, "Could not map reset controller address\n");
- return PTR_ERR(at91_rstc_base);
+ ret = clk_prepare_enable(sclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable slow clock\n");
+ return ret;
}
- for (idx = 0; idx < 2; idx++) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
- at91_ramc_base[idx] = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!at91_ramc_base[idx]) {
- dev_err(&pdev->dev, "Could not map ram controller address\n");
- return -ENOMEM;
- }
+ ret = register_restart_handler(&at91_restart_nb);
+ if (ret) {
+ clk_disable_unprepare(sclk);
+ return ret;
}
- match = platform_get_device_id(pdev);
- at91_restart_nb.notifier_call =
- (int (*)(struct notifier_block *,
- unsigned long, void *)) match->driver_data;
+ at91_reset_status(pdev);
- return register_restart_handler(&at91_restart_nb);
+ return 0;
}
-static int at91_reset_probe(struct platform_device *pdev)
+static int __exit at91_reset_remove(struct platform_device *pdev)
{
- int ret;
-
- if (pdev->dev.of_node)
- ret = at91_reset_of_probe(pdev);
- else
- ret = at91_reset_platform_probe(pdev);
-
- if (ret)
- return ret;
-
- at91_reset_status(pdev);
+ unregister_restart_handler(&at91_restart_nb);
+ clk_disable_unprepare(sclk);
return 0;
}
@@ -262,11 +243,15 @@ static const struct platform_device_id at91_reset_plat_match[] = {
};
static struct platform_driver at91_reset_driver = {
- .probe = at91_reset_probe,
+ .remove = __exit_p(at91_reset_remove),
.driver = {
.name = "at91-reset",
.of_match_table = at91_reset_of_match,
},
.id_table = at91_reset_plat_match,
};
-module_platform_driver(at91_reset_driver);
+module_platform_driver_probe(at91_reset_driver, at91_reset_probe);
+
+MODULE_AUTHOR("Atmel Corporation");
+MODULE_DESCRIPTION("Reset driver for Atmel SoCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/rt9455_charger.c b/drivers/power/rt9455_charger.c
index a49a9d44bdda..cfdbde9daf94 100644
--- a/drivers/power/rt9455_charger.c
+++ b/drivers/power/rt9455_charger.c
@@ -1760,5 +1760,4 @@ module_i2c_driver(rt9455_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anda-Maria Nicolae <anda-maria.nicolae@intel.com>");
-MODULE_ALIAS("i2c:rt9455-charger");
MODULE_DESCRIPTION("Richtek RT9455 Charger Driver");
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index 0b60a0b5878b..072c5189bd6d 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -1332,4 +1332,3 @@ MODULE_AUTHOR("Bruce E. Robertson <bruce.e.robertson@intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("SMB347 battery charger driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("i2c:smb347");
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 7e8fbd29c30e..1b4b5e09538e 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -353,6 +353,7 @@ static const struct of_device_id of_tps65090_charger_match[] = {
{ .compatible = "ti,tps65090-charger", },
{ /* end */ }
};
+MODULE_DEVICE_TABLE(of, of_tps65090_charger_match);
static struct platform_driver tps65090_charger_driver = {
.driver = {
diff --git a/drivers/power/tps65217_charger.c b/drivers/power/tps65217_charger.c
new file mode 100644
index 000000000000..d9f56730c735
--- /dev/null
+++ b/drivers/power/tps65217_charger.c
@@ -0,0 +1,264 @@
+/*
+ * Battery charger driver for TI's tps65217
+ *
+ * Copyright (c) 2015, Collabora Ltd.
+
+ * 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/>.
+ */
+
+/*
+ * Battery charger driver for TI's tps65217
+ */
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/power_supply.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65217.h>
+
+#define POLL_INTERVAL (HZ * 2)
+
+struct tps65217_charger {
+ struct tps65217 *tps;
+ struct device *dev;
+ struct power_supply *ac;
+
+ int ac_online;
+ int prev_ac_online;
+
+ struct task_struct *poll_task;
+};
+
+static enum power_supply_property tps65217_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int tps65217_config_charger(struct tps65217_charger *charger)
+{
+ int ret;
+
+ dev_dbg(charger->dev, "%s\n", __func__);
+
+ /*
+ * tps65217 rev. G, p. 31 (see p. 32 for NTC schematic)
+ *
+ * The device can be configured to support a 100k NTC (B = 3960) by
+ * setting the the NTC_TYPE bit in register CHGCONFIG1 to 1. However it
+ * is not recommended to do so. In sleep mode, the charger continues
+ * charging the battery, but all register values are reset to default
+ * values. Therefore, the charger would get the wrong temperature
+ * information. If 100k NTC setting is required, please contact the
+ * factory.
+ *
+ * ATTENTION, conflicting information, from p. 46
+ *
+ * NTC TYPE (for battery temperature measurement)
+ * 0 – 100k (curve 1, B = 3960)
+ * 1 – 10k (curve 2, B = 3480) (default on reset)
+ *
+ */
+ ret = tps65217_clear_bits(charger->tps, TPS65217_REG_CHGCONFIG1,
+ TPS65217_CHGCONFIG1_NTC_TYPE,
+ TPS65217_PROTECT_NONE);
+ if (ret) {
+ dev_err(charger->dev,
+ "failed to set 100k NTC setting: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tps65217_enable_charging(struct tps65217_charger *charger)
+{
+ int ret;
+
+ /* charger already enabled */
+ if (charger->ac_online)
+ return 0;
+
+ dev_dbg(charger->dev, "%s: enable charging\n", __func__);
+ ret = tps65217_set_bits(charger->tps, TPS65217_REG_CHGCONFIG1,
+ TPS65217_CHGCONFIG1_CHG_EN,
+ TPS65217_CHGCONFIG1_CHG_EN,
+ TPS65217_PROTECT_NONE);
+ if (ret) {
+ dev_err(charger->dev,
+ "%s: Error in writing CHG_EN in reg 0x%x: %d\n",
+ __func__, TPS65217_REG_CHGCONFIG1, ret);
+ return ret;
+ }
+
+ charger->ac_online = 1;
+
+ return 0;
+}
+
+static int tps65217_ac_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct tps65217_charger *charger = power_supply_get_drvdata(psy);
+
+ if (psp == POWER_SUPPLY_PROP_ONLINE) {
+ val->intval = charger->ac_online;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static irqreturn_t tps65217_charger_irq(int irq, void *dev)
+{
+ int ret, val;
+ struct tps65217_charger *charger = dev;
+
+ charger->prev_ac_online = charger->ac_online;
+
+ ret = tps65217_reg_read(charger->tps, TPS65217_REG_STATUS, &val);
+ if (ret < 0) {
+ dev_err(charger->dev, "%s: Error in reading reg 0x%x\n",
+ __func__, TPS65217_REG_STATUS);
+ return IRQ_HANDLED;
+ }
+
+ dev_dbg(charger->dev, "%s: 0x%x\n", __func__, val);
+
+ /* check for AC status bit */
+ if (val & TPS65217_STATUS_ACPWR) {
+ ret = tps65217_enable_charging(charger);
+ if (ret) {
+ dev_err(charger->dev,
+ "failed to enable charger: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+ } else {
+ charger->ac_online = 0;
+ }
+
+ if (charger->prev_ac_online != charger->ac_online)
+ power_supply_changed(charger->ac);
+
+ ret = tps65217_reg_read(charger->tps, TPS65217_REG_CHGCONFIG0, &val);
+ if (ret < 0) {
+ dev_err(charger->dev, "%s: Error in reading reg 0x%x\n",
+ __func__, TPS65217_REG_CHGCONFIG0);
+ return IRQ_HANDLED;
+ }
+
+ if (val & TPS65217_CHGCONFIG0_ACTIVE)
+ dev_dbg(charger->dev, "%s: charger is charging\n", __func__);
+ else
+ dev_dbg(charger->dev,
+ "%s: charger is NOT charging\n", __func__);
+
+ return IRQ_HANDLED;
+}
+
+static int tps65217_charger_poll_task(void *data)
+{
+ set_freezable();
+
+ while (!kthread_should_stop()) {
+ schedule_timeout_interruptible(POLL_INTERVAL);
+ try_to_freeze();
+ tps65217_charger_irq(-1, data);
+ }
+ return 0;
+}
+
+static const struct power_supply_desc tps65217_charger_desc = {
+ .name = "tps65217-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .get_property = tps65217_ac_get_property,
+ .properties = tps65217_ac_props,
+ .num_properties = ARRAY_SIZE(tps65217_ac_props),
+};
+
+static int tps65217_charger_probe(struct platform_device *pdev)
+{
+ struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct tps65217_charger *charger;
+ int ret;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ charger->tps = tps;
+ charger->dev = &pdev->dev;
+
+ charger->ac = devm_power_supply_register(&pdev->dev,
+ &tps65217_charger_desc,
+ NULL);
+ if (IS_ERR(charger->ac)) {
+ dev_err(&pdev->dev, "failed: power supply register\n");
+ return PTR_ERR(charger->ac);
+ }
+
+ ret = tps65217_config_charger(charger);
+ if (ret < 0) {
+ dev_err(charger->dev, "charger config failed, err %d\n", ret);
+ return ret;
+ }
+
+ charger->poll_task = kthread_run(tps65217_charger_poll_task,
+ charger, "ktps65217charger");
+ if (IS_ERR(charger->poll_task)) {
+ ret = PTR_ERR(charger->poll_task);
+ dev_err(charger->dev, "Unable to run kthread err %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tps65217_charger_remove(struct platform_device *pdev)
+{
+ struct tps65217_charger *charger = platform_get_drvdata(pdev);
+
+ kthread_stop(charger->poll_task);
+
+ return 0;
+}
+
+static const struct of_device_id tps65217_charger_match_table[] = {
+ { .compatible = "ti,tps65217-charger", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tps65217_charger_match_table);
+
+static struct platform_driver tps65217_charger_driver = {
+ .probe = tps65217_charger_probe,
+ .remove = tps65217_charger_remove,
+ .driver = {
+ .name = "tps65217-charger",
+ .of_match_table = of_match_ptr(tps65217_charger_match_table),
+ },
+
+};
+module_platform_driver(tps65217_charger_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Enric Balletbo Serra <enric.balletbo@collabora.com>");
+MODULE_DESCRIPTION("TPS65217 battery charger driver");
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 74f2d3ff1d7c..bcd4dc304f27 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -22,7 +22,7 @@
#include <linux/power_supply.h>
#include <linux/notifier.h>
#include <linux/usb/otg.h>
-#include <linux/i2c/twl4030-madc.h>
+#include <linux/iio/consumer.h>
#define TWL4030_BCIMDEN 0x00
#define TWL4030_BCIMDKEY 0x01
@@ -91,21 +91,23 @@
#define TWL4030_MSTATEC_COMPLETE1 0x0b
#define TWL4030_MSTATEC_COMPLETE4 0x0e
-#if IS_REACHABLE(CONFIG_TWL4030_MADC)
/*
* If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
* then AC is available.
*/
-static inline int ac_available(void)
+static inline int ac_available(struct iio_channel *channel_vac)
{
- return twl4030_get_madc_conversion(11) > 4500;
-}
-#else
-static inline int ac_available(void)
-{
- return 0;
+ int val, err;
+
+ if (!channel_vac)
+ return 0;
+
+ err = iio_read_channel_processed(channel_vac, &val);
+ if (err < 0)
+ return 0;
+ return val > 4500;
}
-#endif
+
static bool allow_usb;
module_param(allow_usb, bool, 0644);
MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
@@ -128,6 +130,7 @@ struct twl4030_bci {
*/
unsigned int ichg_eoc, ichg_lo, ichg_hi;
unsigned int usb_cur, ac_cur;
+ struct iio_channel *channel_vac;
bool ac_is_active;
int usb_mode, ac_mode; /* charging mode requested */
#define CHARGE_OFF 0
@@ -278,7 +281,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
* If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
* and AC is enabled, set current for 'ac'
*/
- if (ac_available()) {
+ if (ac_available(bci->channel_vac)) {
cur = bci->ac_cur;
bci->ac_is_active = true;
} else {
@@ -1048,6 +1051,12 @@ static int twl4030_bci_probe(struct platform_device *pdev)
return ret;
}
+ bci->channel_vac = iio_channel_get(&pdev->dev, "vac");
+ if (IS_ERR(bci->channel_vac)) {
+ bci->channel_vac = NULL;
+ dev_warn(&pdev->dev, "could not request vac iio channel");
+ }
+
INIT_WORK(&bci->work, twl4030_bci_usb_work);
INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker);
@@ -1069,7 +1078,7 @@ static int twl4030_bci_probe(struct platform_device *pdev)
TWL4030_INTERRUPTS_BCIIMR1A);
if (ret < 0) {
dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
- return ret;
+ goto fail;
}
reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
@@ -1102,6 +1111,10 @@ static int twl4030_bci_probe(struct platform_device *pdev)
twl4030_charger_enable_backup(0, 0);
return 0;
+fail:
+ iio_channel_release(bci->channel_vac);
+
+ return ret;
}
static int __exit twl4030_bci_remove(struct platform_device *pdev)
@@ -1112,6 +1125,8 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
twl4030_charger_enable_usb(bci, false);
twl4030_charger_enable_backup(0, 0);
+ iio_channel_release(bci->channel_vac);
+
device_remove_file(&bci->usb->dev, &dev_attr_max_current);
device_remove_file(&bci->usb->dev, &dev_attr_mode);
device_remove_file(&bci->ac->dev, &dev_attr_max_current);
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6599f3..7082301da945 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -499,7 +499,8 @@ static int wm831x_power_probe(struct platform_device *pdev)
struct wm831x_power *power;
int ret, irq, i;
- power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL);
+ power = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_power),
+ GFP_KERNEL);
if (power == NULL)
return -ENOMEM;
@@ -536,7 +537,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
NULL);
if (IS_ERR(power->wall)) {
ret = PTR_ERR(power->wall);
- goto err_kmalloc;
+ goto err;
}
power->usb_desc.name = power->usb_name,
@@ -572,7 +573,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
- IRQF_TRIGGER_RISING, "System power low",
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "System power low",
power);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
@@ -582,7 +583,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq,
- IRQF_TRIGGER_RISING, "Power source",
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "Power source",
power);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n",
@@ -595,7 +596,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
platform_get_irq_byname(pdev,
wm831x_bat_irqs[i]));
ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
- IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
wm831x_bat_irqs[i],
power);
if (ret != 0) {
@@ -626,8 +627,7 @@ err_usb:
power_supply_unregister(power->usb);
err_wall:
power_supply_unregister(power->wall);
-err_kmalloc:
- kfree(power);
+err:
return ret;
}
@@ -654,7 +654,6 @@ static int wm831x_power_remove(struct platform_device *pdev)
power_supply_unregister(wm831x_power->battery);
power_supply_unregister(wm831x_power->wall);
power_supply_unregister(wm831x_power->usb);
- kfree(wm831x_power);
return 0;
}
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 5efacd050c7d..cc97f0869791 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -1102,6 +1102,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
RAPL_CPU(0x4A, rapl_defaults_tng),/* Tangier */
RAPL_CPU(0x56, rapl_defaults_core),/* Future Xeon */
RAPL_CPU(0x5A, rapl_defaults_ann),/* Annidale */
+ RAPL_CPU(0X5C, rapl_defaults_core),/* Broxton */
RAPL_CPU(0x5E, rapl_defaults_core),/* Skylake-H/S */
RAPL_CPU(0x57, rapl_defaults_hsw_server),/* Knights Landing */
{}
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index cdad4d95b20e..805c749ac1ad 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -179,8 +179,8 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
/* check event type */
BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
- dev_dbg(pps->dev, "PPS event at %ld.%09ld\n",
- ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
+ dev_dbg(pps->dev, "PPS event at %lld.%09ld\n",
+ (s64)ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
timespec_to_pps_ktime(&ts_real, ts->ts_real);
diff --git a/drivers/ps3/ps3-lpm.c b/drivers/ps3/ps3-lpm.c
index cb7d3a67380d..e34de9a7d517 100644
--- a/drivers/ps3/ps3-lpm.c
+++ b/drivers/ps3/ps3-lpm.c
@@ -901,7 +901,7 @@ void ps3_disable_pm(u32 cpu)
result = lv1_stop_lpm(lpm_priv->lpm_id, &tmp);
if (result) {
- if(result != LV1_WRONG_STATE)
+ if (result != LV1_WRONG_STATE)
dev_err(sbd_core(), "%s:%u: lv1_stop_lpm failed: %s\n",
__func__, __LINE__, ps3_result(result));
return;
diff --git a/drivers/ps3/ps3-vuart.c b/drivers/ps3/ps3-vuart.c
index d6db822bef84..632701a1d993 100644
--- a/drivers/ps3/ps3-vuart.c
+++ b/drivers/ps3/ps3-vuart.c
@@ -1000,12 +1000,11 @@ static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
drv = ps3_system_bus_dev_to_vuart_drv(dev);
+ BUG_ON(!drv);
dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
drv->core.core.name);
- BUG_ON(!drv);
-
if (dev->port_number >= PORT_COUNT) {
BUG();
return -EINVAL;
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 062630ab7424..2f4641a0e88b 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -92,6 +92,15 @@ config PWM_BCM2835
To compile this driver as a module, choose M here: the module
will be called pwm-bcm2835.
+config PWM_BERLIN
+ tristate "Marvell Berlin PWM support"
+ depends on ARCH_BERLIN
+ help
+ PWM framework driver for Marvell Berlin SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-berlin.
+
config PWM_BFIN
tristate "Blackfin PWM support"
depends on BFIN_GPTIMERS
@@ -101,6 +110,16 @@ config PWM_BFIN
To compile this driver as a module, choose M here: the module
will be called pwm-bfin.
+config PWM_BRCMSTB
+ tristate "Broadcom STB PWM support"
+ depends on ARCH_BRCMSTB || BMIPS_GENERIC
+ help
+ Generic PWM framework driver for the Broadcom Set-top-Box
+ SoCs (BCM7xxx).
+
+ To compile this driver as a module, choose M Here: the module
+ will be called pwm-brcmstb.c.
+
config PWM_CLPS711X
tristate "CLPS711X PWM support"
depends on ARCH_CLPS711X || COMPILE_TEST
@@ -230,6 +249,17 @@ config PWM_LPSS_PLATFORM
To compile this driver as a module, choose M here: the module
will be called pwm-lpss-platform.
+config PWM_MTK_DISP
+ tristate "MediaTek display PWM driver"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ Generic PWM framework driver for MediaTek disp-pwm device.
+ The PWM is used to control the backlight brightness for display.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-mtk-disp.
+
config PWM_MXS
tristate "Freescale MXS PWM support"
depends on ARCH_MXS && OF
@@ -242,7 +272,7 @@ config PWM_MXS
config PWM_PCA9685
tristate "NXP PCA9685 PWM driver"
- depends on OF && I2C
+ depends on I2C
select REGMAP_I2C
help
Generic PWM framework driver for NXP PCA9685 LED controller.
@@ -268,6 +298,17 @@ config PWM_PXA
To compile this driver as a module, choose M here: the module
will be called pwm-pxa.
+config PWM_RCAR
+ tristate "Renesas R-Car PWM support"
+ depends on ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ This driver exposes the PWM Timer controller found in Renesas
+ R-Car chips through the PWM API.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-rcar.
+
config PWM_RENESAS_TPU
tristate "Renesas TPU PWM support"
depends on ARCH_SHMOBILE || COMPILE_TEST
@@ -338,7 +379,7 @@ config PWM_TEGRA
config PWM_TIECAP
tristate "ECAP PWM support"
- depends on SOC_AM33XX || ARCH_DAVINCI_DA8XX
+ depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX
help
PWM driver support for the ECAP APWM controller found on AM33XX
TI SOC
@@ -348,7 +389,7 @@ config PWM_TIECAP
config PWM_TIEHRPWM
tristate "EHRPWM PWM support"
- depends on SOC_AM33XX || ARCH_DAVINCI_DA8XX
+ depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX
help
PWM driver support for the EHRPWM controller found on AM33XX
TI SOC
@@ -358,7 +399,7 @@ config PWM_TIEHRPWM
config PWM_TIPWMSS
bool
- default y if SOC_AM33XX && (PWM_TIECAP || PWM_TIEHRPWM)
+ default y if (ARCH_OMAP2PLUS) && (PWM_TIECAP || PWM_TIEHRPWM)
help
PWM Subsystem driver support for AM33xx SOC.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index a0e00c09ead3..69b8275f3c08 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -6,7 +6,9 @@ obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o
obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o
+obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o
obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
+obj-$(CONFIG_PWM_BRCMSTB) += pwm-brcmstb.o
obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o
obj-$(CONFIG_PWM_CRC) += pwm-crc.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
@@ -20,10 +22,12 @@ obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o
obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o
obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
+obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
+obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o
obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 3f9df3ea3350..d24ca5f281b4 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -269,6 +269,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,
pwm->pwm = chip->base + i;
pwm->hwpwm = i;
pwm->polarity = polarity;
+ mutex_init(&pwm->lock);
radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
}
@@ -473,16 +474,22 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
if (!pwm->chip->ops->set_polarity)
return -ENOSYS;
- if (pwm_is_enabled(pwm))
- return -EBUSY;
+ mutex_lock(&pwm->lock);
+
+ if (pwm_is_enabled(pwm)) {
+ err = -EBUSY;
+ goto unlock;
+ }
err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
if (err)
- return err;
+ goto unlock;
pwm->polarity = polarity;
- return 0;
+unlock:
+ mutex_unlock(&pwm->lock);
+ return err;
}
EXPORT_SYMBOL_GPL(pwm_set_polarity);
@@ -494,10 +501,22 @@ EXPORT_SYMBOL_GPL(pwm_set_polarity);
*/
int pwm_enable(struct pwm_device *pwm)
{
- if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags))
- return pwm->chip->ops->enable(pwm->chip, pwm);
+ int err = 0;
- return pwm ? 0 : -EINVAL;
+ if (!pwm)
+ return -EINVAL;
+
+ mutex_lock(&pwm->lock);
+
+ if (!test_and_set_bit(PWMF_ENABLED, &pwm->flags)) {
+ err = pwm->chip->ops->enable(pwm->chip, pwm);
+ if (err)
+ clear_bit(PWMF_ENABLED, &pwm->flags);
+ }
+
+ mutex_unlock(&pwm->lock);
+
+ return err;
}
EXPORT_SYMBOL_GPL(pwm_enable);
@@ -719,8 +738,10 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
}
}
- if (!chosen)
+ if (!chosen) {
+ pwm = ERR_PTR(-ENODEV);
goto out;
+ }
chip = pwmchip_find_by_name(chosen->provider);
if (!chip)
diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c
index 5df1db40fc07..f994c7eaf41c 100644
--- a/drivers/pwm/pwm-atmel-hlcdc.c
+++ b/drivers/pwm/pwm-atmel-hlcdc.c
@@ -227,6 +227,9 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = {
.data = &atmel_hlcdc_pwm_at91sam9x5_errata,
},
{
+ .compatible = "atmel,sama5d2-hlcdc",
+ },
+ {
.compatible = "atmel,sama5d3-hlcdc",
.data = &atmel_hlcdc_pwm_sama5d3_errata,
},
@@ -236,6 +239,7 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = {
},
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, atmel_hlcdc_dt_ids);
static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
{
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index 6da01b3bf6f4..75db585a2a94 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -305,7 +305,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
*/
if (i == 5) {
i = slowclk;
- rate = 32768;
+ rate = clk_get_rate(tc->slow_clk);
min = div_u64(NSEC_PER_SEC, rate);
max = min << tc->tcb_config->counter_width;
@@ -387,9 +387,9 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL);
if (tcbpwm == NULL) {
- atmel_tc_free(tc);
+ err = -ENOMEM;
dev_err(&pdev->dev, "failed to allocate memory\n");
- return -ENOMEM;
+ goto err_free_tc;
}
tcbpwm->chip.dev = &pdev->dev;
@@ -400,17 +400,27 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
tcbpwm->chip.npwm = NPWM;
tcbpwm->tc = tc;
+ err = clk_prepare_enable(tc->slow_clk);
+ if (err)
+ goto err_free_tc;
+
spin_lock_init(&tcbpwm->lock);
err = pwmchip_add(&tcbpwm->chip);
- if (err < 0) {
- atmel_tc_free(tc);
- return err;
- }
+ if (err < 0)
+ goto err_disable_clk;
platform_set_drvdata(pdev, tcbpwm);
return 0;
+
+err_disable_clk:
+ clk_disable_unprepare(tcbpwm->tc->slow_clk);
+
+err_free_tc:
+ atmel_tc_free(tc);
+
+ return err;
}
static int atmel_tcb_pwm_remove(struct platform_device *pdev)
@@ -418,6 +428,8 @@ static int atmel_tcb_pwm_remove(struct platform_device *pdev)
struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
int err;
+ clk_disable_unprepare(tcbpwm->tc->slow_clk);
+
err = pwmchip_remove(&tcbpwm->chip);
if (err < 0)
return err;
diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c
new file mode 100644
index 000000000000..65108129d505
--- /dev/null
+++ b/drivers/pwm/pwm-berlin.c
@@ -0,0 +1,219 @@
+/*
+ * Marvell Berlin PWM driver
+ *
+ * Copyright (C) 2015 Marvell Technology Group Ltd.
+ *
+ * Author: Antoine Tenart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define BERLIN_PWM_EN 0x0
+#define BERLIN_PWM_ENABLE BIT(0)
+#define BERLIN_PWM_CONTROL 0x4
+#define BERLIN_PWM_PRESCALE_MASK 0x7
+#define BERLIN_PWM_PRESCALE_MAX 4096
+#define BERLIN_PWM_INVERT_POLARITY BIT(3)
+#define BERLIN_PWM_DUTY 0x8
+#define BERLIN_PWM_TCNT 0xc
+#define BERLIN_PWM_MAX_TCNT 65535
+
+struct berlin_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ void __iomem *base;
+};
+
+static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct berlin_pwm_chip, chip);
+}
+
+static const u32 prescaler_table[] = {
+ 1, 4, 8, 16, 64, 256, 1024, 4096
+};
+
+static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip,
+ unsigned int channel, unsigned long offset)
+{
+ return readl_relaxed(chip->base + channel * 0x10 + offset);
+}
+
+static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip,
+ unsigned int channel, u32 value,
+ unsigned long offset)
+{
+ writel_relaxed(value, chip->base + channel * 0x10 + offset);
+}
+
+static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
+ int duty_ns, int period_ns)
+{
+ struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+ unsigned int prescale;
+ u32 value, duty, period;
+ u64 cycles, tmp;
+
+ cycles = clk_get_rate(pwm->clk);
+ cycles *= period_ns;
+ do_div(cycles, NSEC_PER_SEC);
+
+ for (prescale = 0; prescale < ARRAY_SIZE(prescaler_table); prescale++) {
+ tmp = cycles;
+ do_div(tmp, prescaler_table[prescale]);
+
+ if (tmp <= BERLIN_PWM_MAX_TCNT)
+ break;
+ }
+
+ if (tmp > BERLIN_PWM_MAX_TCNT)
+ return -ERANGE;
+
+ period = tmp;
+ cycles = tmp * duty_ns;
+ do_div(cycles, period_ns);
+ duty = cycles;
+
+ value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
+ value &= ~BERLIN_PWM_PRESCALE_MASK;
+ value |= prescale;
+ berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
+
+ berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY);
+ berlin_pwm_writel(pwm, pwm_dev->hwpwm, period, BERLIN_PWM_TCNT);
+
+ return 0;
+}
+
+static int berlin_pwm_set_polarity(struct pwm_chip *chip,
+ struct pwm_device *pwm_dev,
+ enum pwm_polarity polarity)
+{
+ struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+ u32 value;
+
+ value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
+
+ if (polarity == PWM_POLARITY_NORMAL)
+ value &= ~BERLIN_PWM_INVERT_POLARITY;
+ else
+ value |= BERLIN_PWM_INVERT_POLARITY;
+
+ berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
+
+ return 0;
+}
+
+static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev)
+{
+ struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+ u32 value;
+
+ value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN);
+ value |= BERLIN_PWM_ENABLE;
+ berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN);
+
+ return 0;
+}
+
+static void berlin_pwm_disable(struct pwm_chip *chip,
+ struct pwm_device *pwm_dev)
+{
+ struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+ u32 value;
+
+ value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN);
+ value &= ~BERLIN_PWM_ENABLE;
+ berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN);
+}
+
+static const struct pwm_ops berlin_pwm_ops = {
+ .config = berlin_pwm_config,
+ .set_polarity = berlin_pwm_set_polarity,
+ .enable = berlin_pwm_enable,
+ .disable = berlin_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id berlin_pwm_match[] = {
+ { .compatible = "marvell,berlin-pwm" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, berlin_pwm_match);
+
+static int berlin_pwm_probe(struct platform_device *pdev)
+{
+ struct berlin_pwm_chip *pwm;
+ struct resource *res;
+ int ret;
+
+ pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
+ if (!pwm)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pwm->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pwm->base))
+ return PTR_ERR(pwm->base);
+
+ pwm->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pwm->clk))
+ return PTR_ERR(pwm->clk);
+
+ ret = clk_prepare_enable(pwm->clk);
+ if (ret)
+ return ret;
+
+ pwm->chip.dev = &pdev->dev;
+ pwm->chip.ops = &berlin_pwm_ops;
+ pwm->chip.base = -1;
+ pwm->chip.npwm = 4;
+ pwm->chip.can_sleep = true;
+ pwm->chip.of_xlate = of_pwm_xlate_with_flags;
+ pwm->chip.of_pwm_n_cells = 3;
+
+ ret = pwmchip_add(&pwm->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+ clk_disable_unprepare(pwm->clk);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pwm);
+
+ return 0;
+}
+
+static int berlin_pwm_remove(struct platform_device *pdev)
+{
+ struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = pwmchip_remove(&pwm->chip);
+ clk_disable_unprepare(pwm->clk);
+
+ return ret;
+}
+
+static struct platform_driver berlin_pwm_driver = {
+ .probe = berlin_pwm_probe,
+ .remove = berlin_pwm_remove,
+ .driver = {
+ .name = "berlin-pwm",
+ .of_match_table = berlin_pwm_match,
+ },
+};
+module_platform_driver(berlin_pwm_driver);
+
+MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Berlin PWM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-brcmstb.c b/drivers/pwm/pwm-brcmstb.c
new file mode 100644
index 000000000000..423ce087cd9c
--- /dev/null
+++ b/drivers/pwm/pwm-brcmstb.c
@@ -0,0 +1,343 @@
+/*
+ * Broadcom BCM7038 PWM driver
+ * Author: Florian Fainelli
+ *
+ * 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; 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/spinlock.h>
+
+#define PWM_CTRL 0x00
+#define CTRL_START BIT(0)
+#define CTRL_OEB BIT(1)
+#define CTRL_FORCE_HIGH BIT(2)
+#define CTRL_OPENDRAIN BIT(3)
+#define CTRL_CHAN_OFFS 4
+
+#define PWM_CTRL2 0x04
+#define CTRL2_OUT_SELECT BIT(0)
+
+#define PWM_CH_SIZE 0x8
+
+#define PWM_CWORD_MSB(ch) (0x08 + ((ch) * PWM_CH_SIZE))
+#define PWM_CWORD_LSB(ch) (0x0c + ((ch) * PWM_CH_SIZE))
+
+/* Number of bits for the CWORD value */
+#define CWORD_BIT_SIZE 16
+
+/*
+ * Maximum control word value allowed when variable-frequency PWM is used as a
+ * clock for the constant-frequency PMW.
+ */
+#define CONST_VAR_F_MAX 32768
+#define CONST_VAR_F_MIN 1
+
+#define PWM_ON(ch) (0x18 + ((ch) * PWM_CH_SIZE))
+#define PWM_ON_MIN 1
+#define PWM_PERIOD(ch) (0x1c + ((ch) * PWM_CH_SIZE))
+#define PWM_PERIOD_MIN 0
+
+#define PWM_ON_PERIOD_MAX 0xff
+
+struct brcmstb_pwm {
+ void __iomem *base;
+ spinlock_t lock;
+ struct clk *clk;
+ struct pwm_chip chip;
+};
+
+static inline u32 brcmstb_pwm_readl(struct brcmstb_pwm *p,
+ unsigned int offset)
+{
+ if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ return __raw_readl(p->base + offset);
+ else
+ return readl_relaxed(p->base + offset);
+}
+
+static inline void brcmstb_pwm_writel(struct brcmstb_pwm *p, u32 value,
+ unsigned int offset)
+{
+ if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ __raw_writel(value, p->base + offset);
+ else
+ writel_relaxed(value, p->base + offset);
+}
+
+static inline struct brcmstb_pwm *to_brcmstb_pwm(struct pwm_chip *chip)
+{
+ return container_of(chip, struct brcmstb_pwm, chip);
+}
+
+/*
+ * Fv is derived from the variable frequency output. The variable frequency
+ * output is configured using this formula:
+ *
+ * W = cword, if cword < 2 ^ 15 else 16-bit 2's complement of cword
+ *
+ * Fv = W x 2 ^ -16 x 27Mhz (reference clock)
+ *
+ * The period is: (period + 1) / Fv and "on" time is on / (period + 1)
+ *
+ * The PWM core framework specifies that the "duty_ns" parameter is in fact the
+ * "on" time, so this translates directly into our HW programming here.
+ */
+static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct brcmstb_pwm *p = to_brcmstb_pwm(chip);
+ unsigned long pc, dc, cword = CONST_VAR_F_MAX;
+ unsigned int channel = pwm->hwpwm;
+ u32 value;
+
+ /*
+ * If asking for a duty_ns equal to period_ns, we need to substract
+ * the period value by 1 to make it shorter than the "on" time and
+ * produce a flat 100% duty cycle signal, and max out the "on" time
+ */
+ if (duty_ns == period_ns) {
+ dc = PWM_ON_PERIOD_MAX;
+ pc = PWM_ON_PERIOD_MAX - 1;
+ goto done;
+ }
+
+ while (1) {
+ u64 rate, tmp;
+
+ /*
+ * Calculate the base rate from base frequency and current
+ * cword
+ */
+ rate = (u64)clk_get_rate(p->clk) * (u64)cword;
+ do_div(rate, 1 << CWORD_BIT_SIZE);
+
+ tmp = period_ns * rate;
+ do_div(tmp, NSEC_PER_SEC);
+ pc = tmp;
+
+ tmp = (duty_ns + 1) * rate;
+ do_div(tmp, NSEC_PER_SEC);
+ dc = tmp;
+
+ /*
+ * We can be called with separate duty and period updates,
+ * so do not reject dc == 0 right away
+ */
+ if (pc == PWM_PERIOD_MIN || (dc < PWM_ON_MIN && duty_ns))
+ return -EINVAL;
+
+ /* We converged on a calculation */
+ if (pc <= PWM_ON_PERIOD_MAX && dc <= PWM_ON_PERIOD_MAX)
+ break;
+
+ /*
+ * The cword needs to be a power of 2 for the variable
+ * frequency generator to output a 50% duty cycle variable
+ * frequency which is used as input clock to the fixed
+ * frequency generator.
+ */
+ cword >>= 1;
+
+ /*
+ * Desired periods are too large, we do not have a divider
+ * for them
+ */
+ if (cword < CONST_VAR_F_MIN)
+ return -EINVAL;
+ }
+
+done:
+ /*
+ * Configure the defined "cword" value to have the variable frequency
+ * generator output a base frequency for the constant frequency
+ * generator to derive from.
+ */
+ spin_lock(&p->lock);
+ brcmstb_pwm_writel(p, cword >> 8, PWM_CWORD_MSB(channel));
+ brcmstb_pwm_writel(p, cword & 0xff, PWM_CWORD_LSB(channel));
+
+ /* Select constant frequency signal output */
+ value = brcmstb_pwm_readl(p, PWM_CTRL2);
+ value |= CTRL2_OUT_SELECT << (channel * CTRL_CHAN_OFFS);
+ brcmstb_pwm_writel(p, value, PWM_CTRL2);
+
+ /* Configure on and period value */
+ brcmstb_pwm_writel(p, pc, PWM_PERIOD(channel));
+ brcmstb_pwm_writel(p, dc, PWM_ON(channel));
+ spin_unlock(&p->lock);
+
+ return 0;
+}
+
+static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p,
+ unsigned int channel, bool enable)
+{
+ unsigned int shift = channel * CTRL_CHAN_OFFS;
+ u32 value;
+
+ spin_lock(&p->lock);
+ value = brcmstb_pwm_readl(p, PWM_CTRL);
+
+ if (enable) {
+ value &= ~(CTRL_OEB << shift);
+ value |= (CTRL_START | CTRL_OPENDRAIN) << shift;
+ } else {
+ value &= ~((CTRL_START | CTRL_OPENDRAIN) << shift);
+ value |= CTRL_OEB << shift;
+ }
+
+ brcmstb_pwm_writel(p, value, PWM_CTRL);
+ spin_unlock(&p->lock);
+}
+
+static int brcmstb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct brcmstb_pwm *p = to_brcmstb_pwm(chip);
+
+ brcmstb_pwm_enable_set(p, pwm->hwpwm, true);
+
+ return 0;
+}
+
+static void brcmstb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct brcmstb_pwm *p = to_brcmstb_pwm(chip);
+
+ brcmstb_pwm_enable_set(p, pwm->hwpwm, false);
+}
+
+static const struct pwm_ops brcmstb_pwm_ops = {
+ .config = brcmstb_pwm_config,
+ .enable = brcmstb_pwm_enable,
+ .disable = brcmstb_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id brcmstb_pwm_of_match[] = {
+ { .compatible = "brcm,bcm7038-pwm", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, brcmstb_pwm_of_match);
+
+static int brcmstb_pwm_probe(struct platform_device *pdev)
+{
+ struct brcmstb_pwm *p;
+ struct resource *res;
+ int ret;
+
+ p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ spin_lock_init(&p->lock);
+
+ p->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(p->clk)) {
+ dev_err(&pdev->dev, "failed to obtain clock\n");
+ return PTR_ERR(p->clk);
+ }
+
+ ret = clk_prepare_enable(p->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, p);
+
+ p->chip.dev = &pdev->dev;
+ p->chip.ops = &brcmstb_pwm_ops;
+ p->chip.base = -1;
+ p->chip.npwm = 2;
+ p->chip.can_sleep = true;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ p->base = devm_ioremap_resource(&pdev->dev, res);
+ if (!p->base) {
+ ret = -ENOMEM;
+ goto out_clk;
+ }
+
+ ret = pwmchip_add(&p->chip);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+ goto out_clk;
+ }
+
+ return 0;
+
+out_clk:
+ clk_disable_unprepare(p->clk);
+ return ret;
+}
+
+static int brcmstb_pwm_remove(struct platform_device *pdev)
+{
+ struct brcmstb_pwm *p = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = pwmchip_remove(&p->chip);
+ clk_disable_unprepare(p->clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcmstb_pwm_suspend(struct device *dev)
+{
+ struct brcmstb_pwm *p = dev_get_drvdata(dev);
+
+ clk_disable(p->clk);
+
+ return 0;
+}
+
+static int brcmstb_pwm_resume(struct device *dev)
+{
+ struct brcmstb_pwm *p = dev_get_drvdata(dev);
+
+ clk_enable(p->clk);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(brcmstb_pwm_pm_ops, brcmstb_pwm_suspend,
+ brcmstb_pwm_resume);
+
+static struct platform_driver brcmstb_pwm_driver = {
+ .probe = brcmstb_pwm_probe,
+ .remove = brcmstb_pwm_remove,
+ .driver = {
+ .name = "pwm-brcmstb",
+ .of_match_table = brcmstb_pwm_of_match,
+ .pm = &brcmstb_pwm_pm_ops,
+ },
+};
+module_platform_driver(brcmstb_pwm_driver);
+
+MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>");
+MODULE_DESCRIPTION("Broadcom STB PWM driver");
+MODULE_ALIAS("platform:pwm-brcmstb");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
index 45042c1b2046..7160e8ab38a4 100644
--- a/drivers/pwm/pwm-lpss-pci.c
+++ b/drivers/pwm/pwm-lpss-pci.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/pm_runtime.h>
#include "pwm-lpss.h"
@@ -33,6 +34,10 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev,
return PTR_ERR(lpwm);
pci_set_drvdata(pdev, lpwm);
+
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_allow(&pdev->dev);
+
return 0;
}
@@ -40,16 +45,41 @@ static void pwm_lpss_remove_pci(struct pci_dev *pdev)
{
struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev);
+ pm_runtime_forbid(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
pwm_lpss_remove(lpwm);
}
+#ifdef CONFIG_PM
+static int pwm_lpss_runtime_suspend_pci(struct device *dev)
+{
+ /*
+ * The PCI core will handle transition to D3 automatically. We only
+ * need to provide runtime PM hooks for that to happen.
+ */
+ return 0;
+}
+
+static int pwm_lpss_runtime_resume_pci(struct device *dev)
+{
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops pwm_lpss_pci_pm = {
+ SET_RUNTIME_PM_OPS(pwm_lpss_runtime_suspend_pci,
+ pwm_lpss_runtime_resume_pci, NULL)
+};
+
static const struct pci_device_id pwm_lpss_pci_ids[] = {
- { PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bsw_info},
+ { PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info},
{ PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
{ PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info},
- { PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bsw_info},
+ { PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bxt_info},
{ PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
+ { PCI_VDEVICE(INTEL, 0x5ac8), (unsigned long)&pwm_lpss_bxt_info},
{ },
};
MODULE_DEVICE_TABLE(pci, pwm_lpss_pci_ids);
@@ -59,6 +89,9 @@ static struct pci_driver pwm_lpss_driver_pci = {
.id_table = pwm_lpss_pci_ids,
.probe = pwm_lpss_probe_pci,
.remove = pwm_lpss_remove_pci,
+ .driver = {
+ .pm = &pwm_lpss_pci_pm,
+ },
};
module_pci_driver(pwm_lpss_driver_pci);
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
index 18a9c880a76d..54433fc6d1a4 100644
--- a/drivers/pwm/pwm-lpss-platform.c
+++ b/drivers/pwm/pwm-lpss-platform.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include "pwm-lpss.h"
@@ -36,6 +37,10 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
return PTR_ERR(lpwm);
platform_set_drvdata(pdev, lpwm);
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
return 0;
}
@@ -43,12 +48,14 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
{
struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
+ pm_runtime_disable(&pdev->dev);
return pwm_lpss_remove(lpwm);
}
static const struct acpi_device_id pwm_lpss_acpi_match[] = {
{ "80860F09", (unsigned long)&pwm_lpss_byt_info },
{ "80862288", (unsigned long)&pwm_lpss_bsw_info },
+ { "80865AC8", (unsigned long)&pwm_lpss_bxt_info },
{ },
};
MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index e9798253a16f..25044104003b 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include "pwm-lpss.h"
@@ -29,6 +30,9 @@
#define PWM_LIMIT (0x8000 + PWM_DIVISION_CORRECTION)
#define NSECS_PER_SEC 1000000000UL
+/* Size of each PWM register space if multiple */
+#define PWM_SIZE 0x400
+
struct pwm_lpss_chip {
struct pwm_chip chip;
void __iomem *regs;
@@ -37,21 +41,44 @@ struct pwm_lpss_chip {
/* BayTrail */
const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
- .clk_rate = 25000000
+ .clk_rate = 25000000,
+ .npwm = 1,
};
EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
/* Braswell */
const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
- .clk_rate = 19200000
+ .clk_rate = 19200000,
+ .npwm = 1,
};
EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
+/* Broxton */
+const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
+ .clk_rate = 19200000,
+ .npwm = 4,
+};
+EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);
+
static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
{
return container_of(chip, struct pwm_lpss_chip, chip);
}
+static inline u32 pwm_lpss_read(const struct pwm_device *pwm)
+{
+ struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
+
+ return readl(lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM);
+}
+
+static inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value)
+{
+ struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
+
+ writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM);
+}
+
static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
@@ -79,38 +106,36 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
duty_ns = 1;
on_time_div = 255 - (255 * duty_ns / period_ns);
- ctrl = readl(lpwm->regs + PWM);
+ pm_runtime_get_sync(chip->dev);
+
+ ctrl = pwm_lpss_read(pwm);
ctrl &= ~(PWM_BASE_UNIT_MASK | PWM_ON_TIME_DIV_MASK);
ctrl |= (u16) base_unit << PWM_BASE_UNIT_SHIFT;
ctrl |= on_time_div;
/* request PWM to update on next cycle */
ctrl |= PWM_SW_UPDATE;
- writel(ctrl, lpwm->regs + PWM);
+ pwm_lpss_write(pwm, ctrl);
+
+ pm_runtime_put(chip->dev);
return 0;
}
static int pwm_lpss_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
- struct pwm_lpss_chip *lpwm = to_lpwm(chip);
- u32 ctrl;
-
- ctrl = readl(lpwm->regs + PWM);
- writel(ctrl | PWM_ENABLE, lpwm->regs + PWM);
-
+ pm_runtime_get_sync(chip->dev);
+ pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE);
return 0;
}
static void pwm_lpss_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
- struct pwm_lpss_chip *lpwm = to_lpwm(chip);
- u32 ctrl;
-
- ctrl = readl(lpwm->regs + PWM);
- writel(ctrl & ~PWM_ENABLE, lpwm->regs + PWM);
+ pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
+ pm_runtime_put(chip->dev);
}
static const struct pwm_ops pwm_lpss_ops = {
+ .free = pwm_lpss_disable,
.config = pwm_lpss_config,
.enable = pwm_lpss_enable,
.disable = pwm_lpss_disable,
@@ -135,7 +160,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
lpwm->chip.dev = dev;
lpwm->chip.ops = &pwm_lpss_ops;
lpwm->chip.base = -1;
- lpwm->chip.npwm = 1;
+ lpwm->chip.npwm = info->npwm;
ret = pwmchip_add(&lpwm->chip);
if (ret) {
@@ -149,11 +174,6 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe);
int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
{
- u32 ctrl;
-
- ctrl = readl(lpwm->regs + PWM);
- writel(ctrl & ~PWM_ENABLE, lpwm->regs + PWM);
-
return pwmchip_remove(&lpwm->chip);
}
EXPORT_SYMBOL_GPL(pwm_lpss_remove);
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
index aa041bb1b67d..e8cf337ae1d1 100644
--- a/drivers/pwm/pwm-lpss.h
+++ b/drivers/pwm/pwm-lpss.h
@@ -20,10 +20,12 @@ struct pwm_lpss_chip;
struct pwm_lpss_boardinfo {
unsigned long clk_rate;
+ unsigned int npwm;
};
extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
extern const struct pwm_lpss_boardinfo pwm_lpss_bsw_info;
+extern const struct pwm_lpss_boardinfo pwm_lpss_bxt_info;
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
const struct pwm_lpss_boardinfo *info);
diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
new file mode 100644
index 000000000000..0ad3385298c0
--- /dev/null
+++ b/drivers/pwm/pwm-mtk-disp.c
@@ -0,0 +1,243 @@
+/*
+ * MediaTek display pulse-width-modulation controller driver.
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: YH Huang <yh.huang@mediatek.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define DISP_PWM_EN 0x00
+#define PWM_ENABLE_MASK BIT(0)
+
+#define DISP_PWM_COMMIT 0x08
+#define PWM_COMMIT_MASK BIT(0)
+
+#define DISP_PWM_CON_0 0x10
+#define PWM_CLKDIV_SHIFT 16
+#define PWM_CLKDIV_MAX 0x3ff
+#define PWM_CLKDIV_MASK (PWM_CLKDIV_MAX << PWM_CLKDIV_SHIFT)
+
+#define DISP_PWM_CON_1 0x14
+#define PWM_PERIOD_BIT_WIDTH 12
+#define PWM_PERIOD_MASK ((1 << PWM_PERIOD_BIT_WIDTH) - 1)
+
+#define PWM_HIGH_WIDTH_SHIFT 16
+#define PWM_HIGH_WIDTH_MASK (0x1fff << PWM_HIGH_WIDTH_SHIFT)
+
+struct mtk_disp_pwm {
+ struct pwm_chip chip;
+ struct clk *clk_main;
+ struct clk *clk_mm;
+ void __iomem *base;
+};
+
+static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
+{
+ return container_of(chip, struct mtk_disp_pwm, chip);
+}
+
+static void mtk_disp_pwm_update_bits(struct mtk_disp_pwm *mdp, u32 offset,
+ u32 mask, u32 data)
+{
+ void __iomem *address = mdp->base + offset;
+ u32 value;
+
+ value = readl(address);
+ value &= ~mask;
+ value |= data;
+ writel(value, address);
+}
+
+static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
+ u32 clk_div, period, high_width, value;
+ u64 div, rate;
+ int err;
+
+ /*
+ * Find period, high_width and clk_div to suit duty_ns and period_ns.
+ * Calculate proper div value to keep period value in the bound.
+ *
+ * period_ns = 10^9 * (clk_div + 1) * (period + 1) / PWM_CLK_RATE
+ * duty_ns = 10^9 * (clk_div + 1) * high_width / PWM_CLK_RATE
+ *
+ * period = (PWM_CLK_RATE * period_ns) / (10^9 * (clk_div + 1)) - 1
+ * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1))
+ */
+ rate = clk_get_rate(mdp->clk_main);
+ clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >>
+ PWM_PERIOD_BIT_WIDTH;
+ if (clk_div > PWM_CLKDIV_MAX)
+ return -EINVAL;
+
+ div = NSEC_PER_SEC * (clk_div + 1);
+ period = div64_u64(rate * period_ns, div);
+ if (period > 0)
+ period--;
+
+ high_width = div64_u64(rate * duty_ns, div);
+ value = period | (high_width << PWM_HIGH_WIDTH_SHIFT);
+
+ err = clk_enable(mdp->clk_main);
+ if (err < 0)
+ return err;
+
+ err = clk_enable(mdp->clk_mm);
+ if (err < 0) {
+ clk_disable(mdp->clk_main);
+ return err;
+ }
+
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_CON_0, PWM_CLKDIV_MASK,
+ clk_div << PWM_CLKDIV_SHIFT);
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_CON_1,
+ PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK, value);
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT, PWM_COMMIT_MASK, 1);
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT, PWM_COMMIT_MASK, 0);
+
+ clk_disable(mdp->clk_mm);
+ clk_disable(mdp->clk_main);
+
+ return 0;
+}
+
+static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
+ int err;
+
+ err = clk_enable(mdp->clk_main);
+ if (err < 0)
+ return err;
+
+ err = clk_enable(mdp->clk_mm);
+ if (err < 0) {
+ clk_disable(mdp->clk_main);
+ return err;
+ }
+
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, PWM_ENABLE_MASK, 1);
+
+ return 0;
+}
+
+static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
+
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, PWM_ENABLE_MASK, 0);
+
+ clk_disable(mdp->clk_mm);
+ clk_disable(mdp->clk_main);
+}
+
+static const struct pwm_ops mtk_disp_pwm_ops = {
+ .config = mtk_disp_pwm_config,
+ .enable = mtk_disp_pwm_enable,
+ .disable = mtk_disp_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_disp_pwm_probe(struct platform_device *pdev)
+{
+ struct mtk_disp_pwm *mdp;
+ struct resource *r;
+ int ret;
+
+ mdp = devm_kzalloc(&pdev->dev, sizeof(*mdp), GFP_KERNEL);
+ if (!mdp)
+ return -ENOMEM;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mdp->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(mdp->base))
+ return PTR_ERR(mdp->base);
+
+ mdp->clk_main = devm_clk_get(&pdev->dev, "main");
+ if (IS_ERR(mdp->clk_main))
+ return PTR_ERR(mdp->clk_main);
+
+ mdp->clk_mm = devm_clk_get(&pdev->dev, "mm");
+ if (IS_ERR(mdp->clk_mm))
+ return PTR_ERR(mdp->clk_mm);
+
+ ret = clk_prepare(mdp->clk_main);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_prepare(mdp->clk_mm);
+ if (ret < 0)
+ goto disable_clk_main;
+
+ mdp->chip.dev = &pdev->dev;
+ mdp->chip.ops = &mtk_disp_pwm_ops;
+ mdp->chip.base = -1;
+ mdp->chip.npwm = 1;
+
+ ret = pwmchip_add(&mdp->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+ goto disable_clk_mm;
+ }
+
+ platform_set_drvdata(pdev, mdp);
+
+ return 0;
+
+disable_clk_mm:
+ clk_unprepare(mdp->clk_mm);
+disable_clk_main:
+ clk_unprepare(mdp->clk_main);
+ return ret;
+}
+
+static int mtk_disp_pwm_remove(struct platform_device *pdev)
+{
+ struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = pwmchip_remove(&mdp->chip);
+ clk_unprepare(mdp->clk_mm);
+ clk_unprepare(mdp->clk_main);
+
+ return ret;
+}
+
+static const struct of_device_id mtk_disp_pwm_of_match[] = {
+ { .compatible = "mediatek,mt8173-disp-pwm" },
+ { .compatible = "mediatek,mt6595-disp-pwm" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match);
+
+static struct platform_driver mtk_disp_pwm_driver = {
+ .driver = {
+ .name = "mediatek-disp-pwm",
+ .of_match_table = mtk_disp_pwm_of_match,
+ },
+ .probe = mtk_disp_pwm_probe,
+ .remove = mtk_disp_pwm_remove,
+};
+module_platform_driver(mtk_disp_pwm_driver);
+
+MODULE_AUTHOR("YH Huang <yh.huang@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek SoC display PWM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
index 70448a6079b0..117fccf7934a 100644
--- a/drivers/pwm/pwm-pca9685.c
+++ b/drivers/pwm/pwm-pca9685.c
@@ -19,9 +19,11 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/pwm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -297,7 +299,6 @@ static const struct regmap_config pca9685_regmap_i2c_config = {
static int pca9685_pwm_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct device_node *np = client->dev.of_node;
struct pca9685 *pca;
int ret;
int mode2;
@@ -320,12 +321,12 @@ static int pca9685_pwm_probe(struct i2c_client *client,
regmap_read(pca->regmap, PCA9685_MODE2, &mode2);
- if (of_property_read_bool(np, "invert"))
+ if (device_property_read_bool(&client->dev, "invert"))
mode2 |= MODE2_INVRT;
else
mode2 &= ~MODE2_INVRT;
- if (of_property_read_bool(np, "open-drain"))
+ if (device_property_read_bool(&client->dev, "open-drain"))
mode2 &= ~MODE2_OUTDRV;
else
mode2 |= MODE2_OUTDRV;
@@ -363,16 +364,27 @@ static const struct i2c_device_id pca9685_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca9685_id);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id pca9685_acpi_ids[] = {
+ { "INT3492", 0 },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(acpi, pca9685_acpi_ids);
+#endif
+
+#ifdef CONFIG_OF
static const struct of_device_id pca9685_dt_ids[] = {
{ .compatible = "nxp,pca9685-pwm", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pca9685_dt_ids);
+#endif
static struct i2c_driver pca9685_i2c_driver = {
.driver = {
.name = "pca9685-pwm",
- .of_match_table = pca9685_dt_ids,
+ .acpi_match_table = ACPI_PTR(pca9685_acpi_ids),
+ .of_match_table = of_match_ptr(pca9685_dt_ids),
},
.probe = pca9685_pwm_probe,
.remove = pca9685_pwm_remove,
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
new file mode 100644
index 000000000000..6e99a63ffa29
--- /dev/null
+++ b/drivers/pwm/pwm-rcar.c
@@ -0,0 +1,274 @@
+/*
+ * R-Car PWM Timer driver
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * This 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define RCAR_PWM_MAX_DIVISION 24
+#define RCAR_PWM_MAX_CYCLE 1023
+
+#define RCAR_PWMCR 0x00
+#define RCAR_PWMCR_CC0_MASK 0x000f0000
+#define RCAR_PWMCR_CC0_SHIFT 16
+#define RCAR_PWMCR_CCMD BIT(15)
+#define RCAR_PWMCR_SYNC BIT(11)
+#define RCAR_PWMCR_SS0 BIT(4)
+#define RCAR_PWMCR_EN0 BIT(0)
+
+#define RCAR_PWMCNT 0x04
+#define RCAR_PWMCNT_CYC0_MASK 0x03ff0000
+#define RCAR_PWMCNT_CYC0_SHIFT 16
+#define RCAR_PWMCNT_PH0_MASK 0x000003ff
+#define RCAR_PWMCNT_PH0_SHIFT 0
+
+struct rcar_pwm_chip {
+ struct pwm_chip chip;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static inline struct rcar_pwm_chip *to_rcar_pwm_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct rcar_pwm_chip, chip);
+}
+
+static void rcar_pwm_write(struct rcar_pwm_chip *rp, u32 data,
+ unsigned int offset)
+{
+ writel(data, rp->base + offset);
+}
+
+static u32 rcar_pwm_read(struct rcar_pwm_chip *rp, unsigned int offset)
+{
+ return readl(rp->base + offset);
+}
+
+static void rcar_pwm_update(struct rcar_pwm_chip *rp, u32 mask, u32 data,
+ unsigned int offset)
+{
+ u32 value;
+
+ value = rcar_pwm_read(rp, offset);
+ value &= ~mask;
+ value |= data & mask;
+ rcar_pwm_write(rp, value, offset);
+}
+
+static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns)
+{
+ unsigned long clk_rate = clk_get_rate(rp->clk);
+ unsigned long long max; /* max cycle / nanoseconds */
+ unsigned int div;
+
+ if (clk_rate == 0)
+ return -EINVAL;
+
+ for (div = 0; div <= RCAR_PWM_MAX_DIVISION; div++) {
+ max = (unsigned long long)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE *
+ (1 << div);
+ do_div(max, clk_rate);
+ if (period_ns < max)
+ break;
+ }
+
+ return (div <= RCAR_PWM_MAX_DIVISION) ? div : -ERANGE;
+}
+
+static void rcar_pwm_set_clock_control(struct rcar_pwm_chip *rp,
+ unsigned int div)
+{
+ u32 value;
+
+ value = rcar_pwm_read(rp, RCAR_PWMCR);
+ value &= ~(RCAR_PWMCR_CCMD | RCAR_PWMCR_CC0_MASK);
+
+ if (div & 1)
+ value |= RCAR_PWMCR_CCMD;
+
+ div >>= 1;
+
+ value |= div << RCAR_PWMCR_CC0_SHIFT;
+ rcar_pwm_write(rp, value, RCAR_PWMCR);
+}
+
+static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns,
+ int period_ns)
+{
+ unsigned long long one_cycle, tmp; /* 0.01 nanoseconds */
+ unsigned long clk_rate = clk_get_rate(rp->clk);
+ u32 cyc, ph;
+
+ one_cycle = (unsigned long long)NSEC_PER_SEC * 100ULL * (1 << div);
+ do_div(one_cycle, clk_rate);
+
+ tmp = period_ns * 100ULL;
+ do_div(tmp, one_cycle);
+ cyc = (tmp << RCAR_PWMCNT_CYC0_SHIFT) & RCAR_PWMCNT_CYC0_MASK;
+
+ tmp = duty_ns * 100ULL;
+ do_div(tmp, one_cycle);
+ ph = tmp & RCAR_PWMCNT_PH0_MASK;
+
+ /* Avoid prohibited setting */
+ if (cyc == 0 || ph == 0)
+ return -EINVAL;
+
+ rcar_pwm_write(rp, cyc | ph, RCAR_PWMCNT);
+
+ return 0;
+}
+
+static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
+
+ return clk_prepare_enable(rp->clk);
+}
+
+static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
+
+ clk_disable_unprepare(rp->clk);
+}
+
+static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
+ int div, ret;
+
+ div = rcar_pwm_get_clock_division(rp, period_ns);
+ if (div < 0)
+ return div;
+
+ /* Let the core driver set pwm->period if disabled and duty_ns == 0 */
+ if (!test_bit(PWMF_ENABLED, &pwm->flags) && !duty_ns)
+ return 0;
+
+ rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR);
+
+ ret = rcar_pwm_set_counter(rp, div, duty_ns, period_ns);
+ if (!ret)
+ rcar_pwm_set_clock_control(rp, div);
+
+ /* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */
+ rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR);
+
+ return ret;
+}
+
+static int rcar_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
+ u32 value;
+
+ /* Don't enable the PWM device if CYC0 or PH0 is 0 */
+ value = rcar_pwm_read(rp, RCAR_PWMCNT);
+ if ((value & RCAR_PWMCNT_CYC0_MASK) == 0 ||
+ (value & RCAR_PWMCNT_PH0_MASK) == 0)
+ return -EINVAL;
+
+ rcar_pwm_update(rp, RCAR_PWMCR_EN0, RCAR_PWMCR_EN0, RCAR_PWMCR);
+
+ return 0;
+}
+
+static void rcar_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
+
+ rcar_pwm_update(rp, RCAR_PWMCR_EN0, 0, RCAR_PWMCR);
+}
+
+static const struct pwm_ops rcar_pwm_ops = {
+ .request = rcar_pwm_request,
+ .free = rcar_pwm_free,
+ .config = rcar_pwm_config,
+ .enable = rcar_pwm_enable,
+ .disable = rcar_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static int rcar_pwm_probe(struct platform_device *pdev)
+{
+ struct rcar_pwm_chip *rcar_pwm;
+ struct resource *res;
+ int ret;
+
+ rcar_pwm = devm_kzalloc(&pdev->dev, sizeof(*rcar_pwm), GFP_KERNEL);
+ if (rcar_pwm == NULL)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rcar_pwm->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rcar_pwm->base))
+ return PTR_ERR(rcar_pwm->base);
+
+ rcar_pwm->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(rcar_pwm->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ return PTR_ERR(rcar_pwm->clk);
+ }
+
+ platform_set_drvdata(pdev, rcar_pwm);
+
+ rcar_pwm->chip.dev = &pdev->dev;
+ rcar_pwm->chip.ops = &rcar_pwm_ops;
+ rcar_pwm->chip.base = -1;
+ rcar_pwm->chip.npwm = 1;
+
+ ret = pwmchip_add(&rcar_pwm->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to register PWM chip: %d\n", ret);
+ return ret;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+}
+
+static int rcar_pwm_remove(struct platform_device *pdev)
+{
+ struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(&pdev->dev);
+
+ return pwmchip_remove(&rcar_pwm->chip);
+}
+
+static const struct of_device_id rcar_pwm_of_table[] = {
+ { .compatible = "renesas,pwm-rcar", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rcar_pwm_of_table);
+
+static struct platform_driver rcar_pwm_driver = {
+ .probe = rcar_pwm_probe,
+ .remove = rcar_pwm_remove,
+ .driver = {
+ .name = "pwm-rcar",
+ .of_match_table = of_match_ptr(rcar_pwm_of_table),
+ }
+};
+module_platform_driver(rcar_pwm_driver);
+
+MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
+MODULE_DESCRIPTION("Renesas PWM Timer Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:pwm-rcar");
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index cd9dde563018..67af9f62361f 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -68,6 +68,7 @@ static const u32 prescaler_table[] = {
struct sun4i_pwm_data {
bool has_prescaler_bypass;
bool has_rdy;
+ unsigned int npwm;
};
struct sun4i_pwm_chip {
@@ -114,7 +115,7 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* is not an integer so round it half up instead of
* truncating to get less surprising values.
*/
- div = clk_rate * period_ns + NSEC_PER_SEC/2;
+ div = clk_rate * period_ns + NSEC_PER_SEC / 2;
do_div(div, NSEC_PER_SEC);
if (div - 1 > PWM_PRD_MASK)
prescaler = 0;
@@ -262,11 +263,25 @@ static const struct pwm_ops sun4i_pwm_ops = {
static const struct sun4i_pwm_data sun4i_pwm_data_a10 = {
.has_prescaler_bypass = false,
.has_rdy = false,
+ .npwm = 2,
+};
+
+static const struct sun4i_pwm_data sun4i_pwm_data_a10s = {
+ .has_prescaler_bypass = true,
+ .has_rdy = true,
+ .npwm = 2,
+};
+
+static const struct sun4i_pwm_data sun4i_pwm_data_a13 = {
+ .has_prescaler_bypass = true,
+ .has_rdy = true,
+ .npwm = 1,
};
static const struct sun4i_pwm_data sun4i_pwm_data_a20 = {
.has_prescaler_bypass = true,
.has_rdy = true,
+ .npwm = 2,
};
static const struct of_device_id sun4i_pwm_dt_ids[] = {
@@ -274,6 +289,12 @@ static const struct of_device_id sun4i_pwm_dt_ids[] = {
.compatible = "allwinner,sun4i-a10-pwm",
.data = &sun4i_pwm_data_a10,
}, {
+ .compatible = "allwinner,sun5i-a10s-pwm",
+ .data = &sun4i_pwm_data_a10s,
+ }, {
+ .compatible = "allwinner,sun5i-a13-pwm",
+ .data = &sun4i_pwm_data_a13,
+ }, {
.compatible = "allwinner,sun7i-a20-pwm",
.data = &sun4i_pwm_data_a20,
}, {
@@ -305,14 +326,14 @@ static int sun4i_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->clk))
return PTR_ERR(pwm->clk);
+ pwm->data = match->data;
pwm->chip.dev = &pdev->dev;
pwm->chip.ops = &sun4i_pwm_ops;
pwm->chip.base = -1;
- pwm->chip.npwm = 2;
+ pwm->chip.npwm = pwm->data->npwm;
pwm->chip.can_sleep = true;
pwm->chip.of_xlate = of_pwm_xlate_with_flags;
pwm->chip.of_pwm_n_cells = 3;
- pwm->data = match->data;
spin_lock_init(&pwm->ctrl_lock);
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index c472772f00a7..9c90886f4123 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -40,18 +40,18 @@ static struct pwm_device *child_to_pwm_device(struct device *child)
return export->pwm;
}
-static ssize_t pwm_period_show(struct device *child,
- struct device_attribute *attr,
- char *buf)
+static ssize_t period_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
{
const struct pwm_device *pwm = child_to_pwm_device(child);
return sprintf(buf, "%u\n", pwm_get_period(pwm));
}
-static ssize_t pwm_period_store(struct device *child,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static ssize_t period_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
struct pwm_device *pwm = child_to_pwm_device(child);
unsigned int val;
@@ -66,18 +66,18 @@ static ssize_t pwm_period_store(struct device *child,
return ret ? : size;
}
-static ssize_t pwm_duty_cycle_show(struct device *child,
- struct device_attribute *attr,
- char *buf)
+static ssize_t duty_cycle_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
{
const struct pwm_device *pwm = child_to_pwm_device(child);
return sprintf(buf, "%u\n", pwm_get_duty_cycle(pwm));
}
-static ssize_t pwm_duty_cycle_store(struct device *child,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static ssize_t duty_cycle_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
struct pwm_device *pwm = child_to_pwm_device(child);
unsigned int val;
@@ -92,19 +92,18 @@ static ssize_t pwm_duty_cycle_store(struct device *child,
return ret ? : size;
}
-static ssize_t pwm_enable_show(struct device *child,
- struct device_attribute *attr,
- char *buf)
+static ssize_t enable_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
{
const struct pwm_device *pwm = child_to_pwm_device(child);
- int enabled = pwm_is_enabled(pwm);
- return sprintf(buf, "%d\n", enabled);
+ return sprintf(buf, "%d\n", pwm_is_enabled(pwm));
}
-static ssize_t pwm_enable_store(struct device *child,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static ssize_t enable_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
struct pwm_device *pwm = child_to_pwm_device(child);
int val, ret;
@@ -128,9 +127,9 @@ static ssize_t pwm_enable_store(struct device *child,
return ret ? : size;
}
-static ssize_t pwm_polarity_show(struct device *child,
- struct device_attribute *attr,
- char *buf)
+static ssize_t polarity_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
{
const struct pwm_device *pwm = child_to_pwm_device(child);
const char *polarity = "unknown";
@@ -148,9 +147,9 @@ static ssize_t pwm_polarity_show(struct device *child,
return sprintf(buf, "%s\n", polarity);
}
-static ssize_t pwm_polarity_store(struct device *child,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static ssize_t polarity_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
struct pwm_device *pwm = child_to_pwm_device(child);
enum pwm_polarity polarity;
@@ -168,10 +167,10 @@ static ssize_t pwm_polarity_store(struct device *child,
return ret ? : size;
}
-static DEVICE_ATTR(period, 0644, pwm_period_show, pwm_period_store);
-static DEVICE_ATTR(duty_cycle, 0644, pwm_duty_cycle_show, pwm_duty_cycle_store);
-static DEVICE_ATTR(enable, 0644, pwm_enable_show, pwm_enable_store);
-static DEVICE_ATTR(polarity, 0644, pwm_polarity_show, pwm_polarity_store);
+static DEVICE_ATTR_RW(period);
+static DEVICE_ATTR_RW(duty_cycle);
+static DEVICE_ATTR_RW(enable);
+static DEVICE_ATTR_RW(polarity);
static struct attribute *pwm_attrs[] = {
&dev_attr_period.attr,
@@ -245,9 +244,9 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
return 0;
}
-static ssize_t pwm_export_store(struct device *parent,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static ssize_t export_store(struct device *parent,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
{
struct pwm_chip *chip = dev_get_drvdata(parent);
struct pwm_device *pwm;
@@ -271,11 +270,11 @@ static ssize_t pwm_export_store(struct device *parent,
return ret ? : len;
}
-static DEVICE_ATTR(export, 0200, NULL, pwm_export_store);
+static DEVICE_ATTR_WO(export);
-static ssize_t pwm_unexport_store(struct device *parent,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static ssize_t unexport_store(struct device *parent,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
{
struct pwm_chip *chip = dev_get_drvdata(parent);
unsigned int hwpwm;
@@ -292,7 +291,7 @@ static ssize_t pwm_unexport_store(struct device *parent,
return ret ? : len;
}
-static DEVICE_ATTR(unexport, 0200, NULL, pwm_unexport_store);
+static DEVICE_ATTR_WO(unexport);
static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
char *buf)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 64bccff557be..8df0b0e62976 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -627,7 +627,7 @@ config REGULATOR_TI_ABB
config REGULATOR_STW481X_VMMC
bool "ST Microelectronics STW481X VMMC regulator"
- depends on MFD_STW481X
+ depends on MFD_STW481X || COMPILE_TEST
default y if MFD_STW481X
help
This driver supports the internal VMMC regulator in the STw481x
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 896db168e4bd..f8d4cd3d1397 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -261,6 +261,16 @@ static const struct regulator_desc act8865_regulators[] = {
ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
};
+static const struct regulator_desc act8865_alt_regulators[] = {
+ ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET2, "vp1"),
+ ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET2, "vp2"),
+ ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET2, "vp3"),
+ ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
+ ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
+ ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
+ ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
+};
+
#ifdef CONFIG_OF
static const struct of_device_id act8865_dt_ids[] = {
{ .compatible = "active-semi,act8600", .data = (void *)ACT8600 },
@@ -413,6 +423,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
struct act8865 *act8865;
unsigned long type;
int off_reg, off_mask;
+ int voltage_select = 0;
pdata = dev_get_platdata(dev);
@@ -424,6 +435,10 @@ static int act8865_pmic_probe(struct i2c_client *client,
return -ENODEV;
type = (unsigned long) id->data;
+
+ voltage_select = !!of_get_property(dev->of_node,
+ "active-semi,vsel-high",
+ NULL);
} else {
type = i2c_id->driver_data;
}
@@ -442,8 +457,13 @@ static int act8865_pmic_probe(struct i2c_client *client,
off_mask = ACT8846_OFF_SYSMASK;
break;
case ACT8865:
- regulators = act8865_regulators;
- num_regulators = ARRAY_SIZE(act8865_regulators);
+ if (voltage_select) {
+ regulators = act8865_alt_regulators;
+ num_regulators = ARRAY_SIZE(act8865_alt_regulators);
+ } else {
+ regulators = act8865_regulators;
+ num_regulators = ARRAY_SIZE(act8865_regulators);
+ }
off_reg = ACT8865_SYS_CTRL;
off_mask = ACT8865_MSTROFF;
break;
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 52ea605f8130..63cd5e68c864 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -30,6 +30,7 @@
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
@@ -199,6 +200,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
rdesc->owner = THIS_MODULE;
initdata = of_get_regulator_init_data(dev, np, rdesc);
+ initdata->supply_regulator = "vin";
sreg->initdata = initdata;
anatop_np = of_get_parent(np);
@@ -262,6 +264,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
rdesc->vsel_reg = sreg->control_reg;
rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
sreg->vol_bit_shift;
+ rdesc->min_dropout_uV = 125000;
config.dev = &pdev->dev;
config.init_data = initdata;
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 5e947a8ddb84..f7c88ff90c43 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -17,6 +17,7 @@
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
@@ -189,13 +190,22 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
{
struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_ldo1 *ldo1 = config->driver_data;
+ struct device_node *np = arizona->dev->of_node;
struct device_node *init_node, *dcvdd_node;
struct regulator_init_data *init_data;
- pdata->ldoena = arizona_of_get_named_gpio(arizona, "wlf,ldoena", true);
+ pdata->ldoena = of_get_named_gpio(np, "wlf,ldoena", 0);
+ if (pdata->ldoena < 0) {
+ dev_warn(arizona->dev,
+ "LDOENA GPIO property missing/malformed: %d\n",
+ pdata->ldoena);
+ pdata->ldoena = 0;
+ } else {
+ config->ena_gpio_initialized = true;
+ }
- init_node = of_get_child_by_name(arizona->dev->of_node, "ldo1");
- dcvdd_node = of_parse_phandle(arizona->dev->of_node, "DCVDD-supply", 0);
+ init_node = of_get_child_by_name(np, "ldo1");
+ dcvdd_node = of_parse_phandle(np, "DCVDD-supply", 0);
if (init_node) {
config->of_node = init_node;
@@ -245,6 +255,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
switch (arizona->type) {
case WM5102:
case WM8997:
+ case WM8998:
+ case WM1814:
desc = &arizona_ldo1_hc;
ldo1->init_data = arizona_ldo1_dvfs;
break;
@@ -272,8 +284,6 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
ret = arizona_ldo1_of_get_pdata(arizona, &config, desc);
if (ret < 0)
return ret;
-
- config.ena_gpio_initialized = true;
}
}
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index a9567af7cec0..35de22fdb7a0 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -196,10 +196,10 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
/* secondary switchable output of DCDC1 */
- AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", "dcdc1", 1600, 3400, 100,
+ AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, 1600, 3400, 100,
AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)),
/* LDO regulator internally chained to DCDC5 */
- AXP_DESC(AXP22X, DC5LDO, "dc5ldo", "dcdc5", 700, 1400, 100,
+ AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
AXP_DESC(AXP22X, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
@@ -350,6 +350,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
};
int ret, i, nregulators;
u32 workmode;
+ const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
+ const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
switch (axp20x->variant) {
case AXP202_ID:
@@ -371,8 +373,37 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
axp20x_regulator_parse_dt(pdev);
for (i = 0; i < nregulators; i++) {
- rdev = devm_regulator_register(&pdev->dev, &regulators[i],
- &config);
+ const struct regulator_desc *desc = &regulators[i];
+ struct regulator_desc *new_desc;
+
+ /*
+ * Regulators DC1SW and DC5LDO are connected internally,
+ * so we have to handle their supply names separately.
+ *
+ * We always register the regulators in proper sequence,
+ * so the supply names are correctly read. See the last
+ * part of this loop to see where we save the DT defined
+ * name.
+ */
+ if (regulators == axp22x_regulators) {
+ if (i == AXP22X_DC1SW) {
+ new_desc = devm_kzalloc(&pdev->dev,
+ sizeof(*desc),
+ GFP_KERNEL);
+ *new_desc = regulators[i];
+ new_desc->supply_name = axp22x_dc1_name;
+ desc = new_desc;
+ } else if (i == AXP22X_DC5LDO) {
+ new_desc = devm_kzalloc(&pdev->dev,
+ sizeof(*desc),
+ GFP_KERNEL);
+ *new_desc = regulators[i];
+ new_desc->supply_name = axp22x_dc5_name;
+ desc = new_desc;
+ }
+ }
+
+ rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register %s\n",
regulators[i].name);
@@ -388,6 +419,21 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to set workmode on %s\n",
rdev->desc->name);
}
+
+ /*
+ * Save AXP22X DCDC1 / DCDC5 regulator names for later.
+ */
+ if (regulators == axp22x_regulators) {
+ /* Can we use rdev->constraints->name instead? */
+ if (i == AXP22X_DCDC1)
+ of_property_read_string(rdev->dev.of_node,
+ "regulator-name",
+ &axp22x_dc1_name);
+ else if (i == AXP22X_DCDC5)
+ of_property_read_string(rdev->dev.of_node,
+ "regulator-name",
+ &axp22x_dc5_name);
+ }
}
return 0;
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 628430bdc312..76b01835dcb4 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -244,7 +244,7 @@ static int bcm590xx_get_enable_register(int id)
break;
case BCM590XX_REG_VBUS:
reg = BCM590XX_OTG_CTRL;
- };
+ }
return reg;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 8a34f6acc801..73b7683355cd 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -51,7 +51,6 @@
pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
static DEFINE_MUTEX(regulator_list_mutex);
-static LIST_HEAD(regulator_list);
static LIST_HEAD(regulator_map_list);
static LIST_HEAD(regulator_ena_gpio_list);
static LIST_HEAD(regulator_supply_alias_list);
@@ -59,6 +58,8 @@ static bool has_full_constraints;
static struct dentry *debugfs_root;
+static struct class regulator_class;
+
/*
* struct regulator_map
*
@@ -132,6 +133,45 @@ static bool have_full_constraints(void)
}
/**
+ * regulator_lock_supply - lock a regulator and its supplies
+ * @rdev: regulator source
+ */
+static void regulator_lock_supply(struct regulator_dev *rdev)
+{
+ struct regulator *supply;
+ int i = 0;
+
+ while (1) {
+ mutex_lock_nested(&rdev->mutex, i++);
+ supply = rdev->supply;
+
+ if (!rdev->supply)
+ return;
+
+ rdev = supply->rdev;
+ }
+}
+
+/**
+ * regulator_unlock_supply - unlock a regulator and its supplies
+ * @rdev: regulator source
+ */
+static void regulator_unlock_supply(struct regulator_dev *rdev)
+{
+ struct regulator *supply;
+
+ while (1) {
+ mutex_unlock(&rdev->mutex);
+ supply = rdev->supply;
+
+ if (!rdev->supply)
+ return;
+
+ rdev = supply->rdev;
+ }
+}
+
+/**
* of_get_regulator - get a regulator device node based on supply name
* @dev: Device pointer for the consumer (of regulator) device
* @supply: regulator supply name
@@ -180,7 +220,7 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
return -ENODEV;
}
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
- rdev_err(rdev, "operation not allowed\n");
+ rdev_err(rdev, "voltage operation not allowed\n");
return -EPERM;
}
@@ -240,7 +280,7 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
return -ENODEV;
}
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
- rdev_err(rdev, "operation not allowed\n");
+ rdev_err(rdev, "current operation not allowed\n");
return -EPERM;
}
@@ -277,7 +317,7 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
return -ENODEV;
}
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
- rdev_err(rdev, "operation not allowed\n");
+ rdev_err(rdev, "mode operation not allowed\n");
return -EPERM;
}
@@ -301,7 +341,7 @@ static int regulator_check_drms(struct regulator_dev *rdev)
return -ENODEV;
}
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
- rdev_dbg(rdev, "operation not allowed\n");
+ rdev_dbg(rdev, "drms operation not allowed\n");
return -EPERM;
}
return 0;
@@ -1325,6 +1365,47 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
}
}
+static int of_node_match(struct device *dev, const void *data)
+{
+ return dev->of_node == data;
+}
+
+static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
+{
+ struct device *dev;
+
+ dev = class_find_device(&regulator_class, NULL, np, of_node_match);
+
+ return dev ? dev_to_rdev(dev) : NULL;
+}
+
+static int regulator_match(struct device *dev, const void *data)
+{
+ struct regulator_dev *r = dev_to_rdev(dev);
+
+ return strcmp(rdev_get_name(r), data) == 0;
+}
+
+static struct regulator_dev *regulator_lookup_by_name(const char *name)
+{
+ struct device *dev;
+
+ dev = class_find_device(&regulator_class, NULL, name, regulator_match);
+
+ return dev ? dev_to_rdev(dev) : NULL;
+}
+
+/**
+ * regulator_dev_lookup - lookup a regulator device.
+ * @dev: device for regulator "consumer".
+ * @supply: Supply name or regulator ID.
+ * @ret: 0 on success, -ENODEV if lookup fails permanently, -EPROBE_DEFER if
+ * lookup could succeed in the future.
+ *
+ * If successful, returns a struct regulator_dev that corresponds to the name
+ * @supply and with the embedded struct device refcount incremented by one,
+ * or NULL on failure. The refcount must be dropped by calling put_device().
+ */
static struct regulator_dev *regulator_dev_lookup(struct device *dev,
const char *supply,
int *ret)
@@ -1340,10 +1421,9 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
if (dev && dev->of_node) {
node = of_get_regulator(dev, supply);
if (node) {
- list_for_each_entry(r, &regulator_list, list)
- if (r->dev.parent &&
- node == r->dev.of_node)
- return r;
+ r = of_find_regulator_by_node(node);
+ if (r)
+ return r;
*ret = -EPROBE_DEFER;
return NULL;
} else {
@@ -1361,20 +1441,24 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
if (dev)
devname = dev_name(dev);
- list_for_each_entry(r, &regulator_list, list)
- if (strcmp(rdev_get_name(r), supply) == 0)
- return r;
+ r = regulator_lookup_by_name(supply);
+ if (r)
+ return r;
+ mutex_lock(&regulator_list_mutex);
list_for_each_entry(map, &regulator_map_list, list) {
/* If the mapping has a device set up it must match */
if (map->dev_name &&
(!devname || strcmp(map->dev_name, devname)))
continue;
- if (strcmp(map->supply, supply) == 0)
+ if (strcmp(map->supply, supply) == 0 &&
+ get_device(&map->regulator->dev)) {
+ mutex_unlock(&regulator_list_mutex);
return map->regulator;
+ }
}
-
+ mutex_unlock(&regulator_list_mutex);
return NULL;
}
@@ -1409,6 +1493,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
if (have_full_constraints()) {
r = dummy_regulator_rdev;
+ get_device(&r->dev);
} else {
dev_err(dev, "Failed to resolve %s-supply for %s\n",
rdev->supply_name, rdev->desc->name);
@@ -1418,12 +1503,16 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
/* Recursively resolve the supply of the supply */
ret = regulator_resolve_supply(r);
- if (ret < 0)
+ if (ret < 0) {
+ put_device(&r->dev);
return ret;
+ }
ret = set_supply(rdev, r);
- if (ret < 0)
+ if (ret < 0) {
+ put_device(&r->dev);
return ret;
+ }
/* Cascade always-on state to supply */
if (_regulator_is_enabled(rdev) && rdev->supply) {
@@ -1459,8 +1548,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
else
ret = -EPROBE_DEFER;
- mutex_lock(&regulator_list_mutex);
-
rdev = regulator_dev_lookup(dev, id, &ret);
if (rdev)
goto found;
@@ -1472,7 +1559,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
* succeed, so, quit with appropriate error value
*/
if (ret && ret != -ENODEV)
- goto out;
+ return regulator;
if (!devname)
devname = "deviceless";
@@ -1486,40 +1573,46 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
devname, id);
rdev = dummy_regulator_rdev;
+ get_device(&rdev->dev);
goto found;
/* Don't log an error when called from regulator_get_optional() */
} else if (!have_full_constraints() || exclusive) {
dev_warn(dev, "dummy supplies not allowed\n");
}
- mutex_unlock(&regulator_list_mutex);
return regulator;
found:
if (rdev->exclusive) {
regulator = ERR_PTR(-EPERM);
- goto out;
+ put_device(&rdev->dev);
+ return regulator;
}
if (exclusive && rdev->open_count) {
regulator = ERR_PTR(-EBUSY);
- goto out;
+ put_device(&rdev->dev);
+ return regulator;
}
ret = regulator_resolve_supply(rdev);
if (ret < 0) {
regulator = ERR_PTR(ret);
- goto out;
+ put_device(&rdev->dev);
+ return regulator;
}
- if (!try_module_get(rdev->owner))
- goto out;
+ if (!try_module_get(rdev->owner)) {
+ put_device(&rdev->dev);
+ return regulator;
+ }
regulator = create_regulator(rdev, dev, id);
if (regulator == NULL) {
regulator = ERR_PTR(-ENOMEM);
+ put_device(&rdev->dev);
module_put(rdev->owner);
- goto out;
+ return regulator;
}
rdev->open_count++;
@@ -1533,9 +1626,6 @@ found:
rdev->use_count = 0;
}
-out:
- mutex_unlock(&regulator_list_mutex);
-
return regulator;
}
@@ -1633,6 +1723,7 @@ static void _regulator_put(struct regulator *regulator)
rdev->open_count--;
rdev->exclusive = 0;
+ put_device(&rdev->dev);
mutex_unlock(&rdev->mutex);
kfree(regulator->supply_name);
@@ -2312,6 +2403,40 @@ static int _regulator_is_enabled(struct regulator_dev *rdev)
return rdev->desc->ops->is_enabled(rdev);
}
+static int _regulator_list_voltage(struct regulator *regulator,
+ unsigned selector, int lock)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ const struct regulator_ops *ops = rdev->desc->ops;
+ int ret;
+
+ if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
+ return rdev->desc->fixed_uV;
+
+ if (ops->list_voltage) {
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+ if (lock)
+ mutex_lock(&rdev->mutex);
+ ret = ops->list_voltage(rdev, selector);
+ if (lock)
+ mutex_unlock(&rdev->mutex);
+ } else if (rdev->supply) {
+ ret = _regulator_list_voltage(rdev->supply, selector, lock);
+ } else {
+ return -EINVAL;
+ }
+
+ if (ret > 0) {
+ if (ret < rdev->constraints->min_uV)
+ ret = 0;
+ else if (ret > rdev->constraints->max_uV)
+ ret = 0;
+ }
+
+ return ret;
+}
+
/**
* regulator_is_enabled - is the regulator output enabled
* @regulator: regulator source
@@ -2401,33 +2526,7 @@ EXPORT_SYMBOL_GPL(regulator_count_voltages);
*/
int regulator_list_voltage(struct regulator *regulator, unsigned selector)
{
- struct regulator_dev *rdev = regulator->rdev;
- const struct regulator_ops *ops = rdev->desc->ops;
- int ret;
-
- if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
- return rdev->desc->fixed_uV;
-
- if (ops->list_voltage) {
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
- mutex_lock(&rdev->mutex);
- ret = ops->list_voltage(rdev, selector);
- mutex_unlock(&rdev->mutex);
- } else if (rdev->supply) {
- ret = regulator_list_voltage(rdev->supply, selector);
- } else {
- return -EINVAL;
- }
-
- if (ret > 0) {
- if (ret < rdev->constraints->min_uV)
- ret = 0;
- else if (ret > rdev->constraints->max_uV)
- ret = 0;
- }
-
- return ret;
+ return _regulator_list_voltage(regulator, selector, 1);
}
EXPORT_SYMBOL_GPL(regulator_list_voltage);
@@ -2562,6 +2661,23 @@ int regulator_is_supported_voltage(struct regulator *regulator,
}
EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
+static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV)
+{
+ const struct regulator_desc *desc = rdev->desc;
+
+ if (desc->ops->map_voltage)
+ return desc->ops->map_voltage(rdev, min_uV, max_uV);
+
+ if (desc->ops->list_voltage == regulator_list_voltage_linear)
+ return regulator_map_voltage_linear(rdev, min_uV, max_uV);
+
+ if (desc->ops->list_voltage == regulator_list_voltage_linear_range)
+ return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
+
+ return regulator_map_voltage_iterate(rdev, min_uV, max_uV);
+}
+
static int _regulator_call_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV,
unsigned *selector)
@@ -2650,23 +2766,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
} else if (rdev->desc->ops->set_voltage_sel) {
- if (rdev->desc->ops->map_voltage) {
- ret = rdev->desc->ops->map_voltage(rdev, min_uV,
- max_uV);
- } else {
- if (rdev->desc->ops->list_voltage ==
- regulator_list_voltage_linear)
- ret = regulator_map_voltage_linear(rdev,
- min_uV, max_uV);
- else if (rdev->desc->ops->list_voltage ==
- regulator_list_voltage_linear_range)
- ret = regulator_map_voltage_linear_range(rdev,
- min_uV, max_uV);
- else
- ret = regulator_map_voltage_iterate(rdev,
- min_uV, max_uV);
- }
-
+ ret = regulator_map_voltage(rdev, min_uV, max_uV);
if (ret >= 0) {
best_val = rdev->desc->ops->list_voltage(rdev, ret);
if (min_uV <= best_val && max_uV >= best_val) {
@@ -2717,32 +2817,15 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
return ret;
}
-/**
- * regulator_set_voltage - set regulator output voltage
- * @regulator: regulator source
- * @min_uV: Minimum required voltage in uV
- * @max_uV: Maximum acceptable voltage in uV
- *
- * Sets a voltage regulator to the desired output voltage. This can be set
- * during any regulator state. IOW, regulator can be disabled or enabled.
- *
- * If the regulator is enabled then the voltage will change to the new value
- * immediately otherwise if the regulator is disabled the regulator will
- * output at the new voltage when enabled.
- *
- * NOTE: If the regulator is shared between several devices then the lowest
- * request voltage that meets the system constraints will be used.
- * Regulator system constraints must be set for this regulator before
- * calling this function otherwise this call will fail.
- */
-int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
+static int regulator_set_voltage_unlocked(struct regulator *regulator,
+ int min_uV, int max_uV)
{
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
int old_min_uV, old_max_uV;
int current_uV;
-
- mutex_lock(&rdev->mutex);
+ int best_supply_uV = 0;
+ int supply_change_uV = 0;
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
@@ -2786,17 +2869,95 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
if (ret < 0)
goto out2;
+ if (rdev->supply && (rdev->desc->min_dropout_uV ||
+ !rdev->desc->ops->get_voltage)) {
+ int current_supply_uV;
+ int selector;
+
+ selector = regulator_map_voltage(rdev, min_uV, max_uV);
+ if (selector < 0) {
+ ret = selector;
+ goto out2;
+ }
+
+ best_supply_uV = _regulator_list_voltage(regulator, selector, 0);
+ if (best_supply_uV < 0) {
+ ret = best_supply_uV;
+ goto out2;
+ }
+
+ best_supply_uV += rdev->desc->min_dropout_uV;
+
+ current_supply_uV = _regulator_get_voltage(rdev->supply->rdev);
+ if (current_supply_uV < 0) {
+ ret = current_supply_uV;
+ goto out2;
+ }
+
+ supply_change_uV = best_supply_uV - current_supply_uV;
+ }
+
+ if (supply_change_uV > 0) {
+ ret = regulator_set_voltage_unlocked(rdev->supply,
+ best_supply_uV, INT_MAX);
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
+ ret);
+ goto out2;
+ }
+ }
+
ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
if (ret < 0)
goto out2;
+ if (supply_change_uV < 0) {
+ ret = regulator_set_voltage_unlocked(rdev->supply,
+ best_supply_uV, INT_MAX);
+ if (ret)
+ dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n",
+ ret);
+ /* No need to fail here */
+ ret = 0;
+ }
+
out:
- mutex_unlock(&rdev->mutex);
return ret;
out2:
regulator->min_uV = old_min_uV;
regulator->max_uV = old_max_uV;
- mutex_unlock(&rdev->mutex);
+
+ return ret;
+}
+
+/**
+ * regulator_set_voltage - set regulator output voltage
+ * @regulator: regulator source
+ * @min_uV: Minimum required voltage in uV
+ * @max_uV: Maximum acceptable voltage in uV
+ *
+ * Sets a voltage regulator to the desired output voltage. This can be set
+ * during any regulator state. IOW, regulator can be disabled or enabled.
+ *
+ * If the regulator is enabled then the voltage will change to the new value
+ * immediately otherwise if the regulator is disabled the regulator will
+ * output at the new voltage when enabled.
+ *
+ * NOTE: If the regulator is shared between several devices then the lowest
+ * request voltage that meets the system constraints will be used.
+ * Regulator system constraints must be set for this regulator before
+ * calling this function otherwise this call will fail.
+ */
+int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
+{
+ int ret = 0;
+
+ regulator_lock_supply(regulator->rdev);
+
+ ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV);
+
+ regulator_unlock_supply(regulator->rdev);
+
return ret;
}
EXPORT_SYMBOL_GPL(regulator_set_voltage);
@@ -2949,7 +3110,7 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
ret = rdev->desc->fixed_uV;
} else if (rdev->supply) {
- ret = regulator_get_voltage(rdev->supply);
+ ret = _regulator_get_voltage(rdev->supply->rdev);
} else {
return -EINVAL;
}
@@ -2972,11 +3133,11 @@ int regulator_get_voltage(struct regulator *regulator)
{
int ret;
- mutex_lock(&regulator->rdev->mutex);
+ regulator_lock_supply(regulator->rdev);
ret = _regulator_get_voltage(regulator->rdev);
- mutex_unlock(&regulator->rdev->mutex);
+ regulator_unlock_supply(regulator->rdev);
return ret;
}
@@ -3810,8 +3971,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
}
}
- list_add(&rdev->list, &regulator_list);
-
rdev_init_debugfs(rdev);
out:
mutex_unlock(&regulator_list_mutex);
@@ -3865,6 +4024,19 @@ void regulator_unregister(struct regulator_dev *rdev)
}
EXPORT_SYMBOL_GPL(regulator_unregister);
+static int _regulator_suspend_prepare(struct device *dev, void *data)
+{
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ const suspend_state_t *state = data;
+ int ret;
+
+ mutex_lock(&rdev->mutex);
+ ret = suspend_prepare(rdev, *state);
+ mutex_unlock(&rdev->mutex);
+
+ return ret;
+}
+
/**
* regulator_suspend_prepare - prepare regulators for system wide suspend
* @state: system suspend state
@@ -3874,30 +4046,45 @@ EXPORT_SYMBOL_GPL(regulator_unregister);
*/
int regulator_suspend_prepare(suspend_state_t state)
{
- struct regulator_dev *rdev;
- int ret = 0;
-
/* ON is handled by regulator active state */
if (state == PM_SUSPEND_ON)
return -EINVAL;
- mutex_lock(&regulator_list_mutex);
- list_for_each_entry(rdev, &regulator_list, list) {
+ return class_for_each_device(&regulator_class, NULL, &state,
+ _regulator_suspend_prepare);
+}
+EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
- mutex_lock(&rdev->mutex);
- ret = suspend_prepare(rdev, state);
- mutex_unlock(&rdev->mutex);
+static int _regulator_suspend_finish(struct device *dev, void *data)
+{
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ int ret;
- if (ret < 0) {
- rdev_err(rdev, "failed to prepare\n");
- goto out;
+ mutex_lock(&rdev->mutex);
+ if (rdev->use_count > 0 || rdev->constraints->always_on) {
+ if (!_regulator_is_enabled(rdev)) {
+ ret = _regulator_do_enable(rdev);
+ if (ret)
+ dev_err(dev,
+ "Failed to resume regulator %d\n",
+ ret);
}
+ } else {
+ if (!have_full_constraints())
+ goto unlock;
+ if (!_regulator_is_enabled(rdev))
+ goto unlock;
+
+ ret = _regulator_do_disable(rdev);
+ if (ret)
+ dev_err(dev, "Failed to suspend regulator %d\n", ret);
}
-out:
- mutex_unlock(&regulator_list_mutex);
- return ret;
+unlock:
+ mutex_unlock(&rdev->mutex);
+
+ /* Keep processing regulators in spite of any errors */
+ return 0;
}
-EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
/**
* regulator_suspend_finish - resume regulators from system wide suspend
@@ -3907,33 +4094,8 @@ EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
*/
int regulator_suspend_finish(void)
{
- struct regulator_dev *rdev;
- int ret = 0, error;
-
- mutex_lock(&regulator_list_mutex);
- list_for_each_entry(rdev, &regulator_list, list) {
- mutex_lock(&rdev->mutex);
- if (rdev->use_count > 0 || rdev->constraints->always_on) {
- if (!_regulator_is_enabled(rdev)) {
- error = _regulator_do_enable(rdev);
- if (error)
- ret = error;
- }
- } else {
- if (!have_full_constraints())
- goto unlock;
- if (!_regulator_is_enabled(rdev))
- goto unlock;
-
- error = _regulator_do_disable(rdev);
- if (error)
- ret = error;
- }
-unlock:
- mutex_unlock(&rdev->mutex);
- }
- mutex_unlock(&regulator_list_mutex);
- return ret;
+ return class_for_each_device(&regulator_class, NULL, NULL,
+ _regulator_suspend_finish);
}
EXPORT_SYMBOL_GPL(regulator_suspend_finish);
@@ -4053,14 +4215,35 @@ static const struct file_operations supply_map_fops = {
};
#ifdef CONFIG_DEBUG_FS
+struct summary_data {
+ struct seq_file *s;
+ struct regulator_dev *parent;
+ int level;
+};
+
+static void regulator_summary_show_subtree(struct seq_file *s,
+ struct regulator_dev *rdev,
+ int level);
+
+static int regulator_summary_show_children(struct device *dev, void *data)
+{
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ struct summary_data *summary_data = data;
+
+ if (rdev->supply && rdev->supply->rdev == summary_data->parent)
+ regulator_summary_show_subtree(summary_data->s, rdev,
+ summary_data->level + 1);
+
+ return 0;
+}
+
static void regulator_summary_show_subtree(struct seq_file *s,
struct regulator_dev *rdev,
int level)
{
- struct list_head *list = s->private;
- struct regulator_dev *child;
struct regulation_constraints *c;
struct regulator *consumer;
+ struct summary_data summary_data;
if (!rdev)
return;
@@ -4110,33 +4293,32 @@ static void regulator_summary_show_subtree(struct seq_file *s,
seq_puts(s, "\n");
}
- list_for_each_entry(child, list, list) {
- /* handle only non-root regulators supplied by current rdev */
- if (!child->supply || child->supply->rdev != rdev)
- continue;
+ summary_data.s = s;
+ summary_data.level = level;
+ summary_data.parent = rdev;
- regulator_summary_show_subtree(s, child, level + 1);
- }
+ class_for_each_device(&regulator_class, NULL, &summary_data,
+ regulator_summary_show_children);
}
-static int regulator_summary_show(struct seq_file *s, void *data)
+static int regulator_summary_show_roots(struct device *dev, void *data)
{
- struct list_head *list = s->private;
- struct regulator_dev *rdev;
-
- seq_puts(s, " regulator use open bypass voltage current min max\n");
- seq_puts(s, "-------------------------------------------------------------------------------\n");
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ struct seq_file *s = data;
- mutex_lock(&regulator_list_mutex);
+ if (!rdev->supply)
+ regulator_summary_show_subtree(s, rdev, 0);
- list_for_each_entry(rdev, list, list) {
- if (rdev->supply)
- continue;
+ return 0;
+}
- regulator_summary_show_subtree(s, rdev, 0);
- }
+static int regulator_summary_show(struct seq_file *s, void *data)
+{
+ seq_puts(s, " regulator use open bypass voltage current min max\n");
+ seq_puts(s, "-------------------------------------------------------------------------------\n");
- mutex_unlock(&regulator_list_mutex);
+ class_for_each_device(&regulator_class, NULL, s,
+ regulator_summary_show_roots);
return 0;
}
@@ -4170,7 +4352,7 @@ static int __init regulator_init(void)
&supply_map_fops);
debugfs_create_file("regulator_summary", 0444, debugfs_root,
- &regulator_list, &regulator_summary_fops);
+ NULL, &regulator_summary_fops);
regulator_dummy_init();
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index e628d4c2f2ae..12a25b40e473 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -381,6 +381,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
case DA9053_AA:
case DA9053_BA:
case DA9053_BB:
+ case DA9053_BC:
for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
info = &da9053_regulator_info[i];
if (info->reg_desc.id == id)
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index aed1ad3dc964..536e931eb921 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -698,7 +698,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
rdata->initdata = da9063_matches[i].init_data;
n++;
- };
+ }
*da9063_reg_matches = da9063_matches;
return pdata;
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 250700c853bf..499e437c7e91 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -76,6 +76,9 @@ static void of_get_regulation_constraints(struct device_node *np,
if (of_property_read_bool(np, "regulator-allow-bypass"))
constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
+ if (of_property_read_bool(np, "regulator-allow-set-load"))
+ constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
+
ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
if (!ret) {
if (pval)
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index fc3166dfcbfa..3aca067b9901 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -69,12 +69,6 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
drvdata->state = selector;
- ret = pwm_enable(drvdata->pwm);
- if (ret) {
- dev_err(&rdev->dev, "Failed to enable PWM\n");
- return ret;
- }
-
return 0;
}
@@ -89,6 +83,29 @@ static int pwm_regulator_list_voltage(struct regulator_dev *rdev,
return drvdata->duty_cycle_table[selector].uV;
}
+static int pwm_regulator_enable(struct regulator_dev *dev)
+{
+ struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
+
+ return pwm_enable(drvdata->pwm);
+}
+
+static int pwm_regulator_disable(struct regulator_dev *dev)
+{
+ struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
+
+ pwm_disable(drvdata->pwm);
+
+ return 0;
+}
+
+static int pwm_regulator_is_enabled(struct regulator_dev *dev)
+{
+ struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
+
+ return pwm_is_enabled(drvdata->pwm);
+}
+
/**
* Continuous voltage call-backs
*/
@@ -144,11 +161,17 @@ static struct regulator_ops pwm_regulator_voltage_table_ops = {
.get_voltage_sel = pwm_regulator_get_voltage_sel,
.list_voltage = pwm_regulator_list_voltage,
.map_voltage = regulator_map_voltage_iterate,
+ .enable = pwm_regulator_enable,
+ .disable = pwm_regulator_disable,
+ .is_enabled = pwm_regulator_is_enabled,
};
static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
.get_voltage = pwm_regulator_get_voltage,
.set_voltage = pwm_regulator_set_voltage,
+ .enable = pwm_regulator_enable,
+ .disable = pwm_regulator_disable,
+ .is_enabled = pwm_regulator_is_enabled,
};
static struct regulator_desc pwm_regulator_desc = {
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index 9c6167dd2c8b..6fa0c7d13290 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -36,9 +36,9 @@ struct qcom_rpm_reg {
};
struct rpm_regulator_req {
- u32 key;
- u32 nbytes;
- u32 value;
+ __le32 key;
+ __le32 nbytes;
+ __le32 value;
};
#define RPM_KEY_SWEN 0x6e657773 /* "swen" */
@@ -62,9 +62,9 @@ static int rpm_reg_enable(struct regulator_dev *rdev)
struct rpm_regulator_req req;
int ret;
- req.key = RPM_KEY_SWEN;
- req.nbytes = sizeof(u32);
- req.value = 1;
+ req.key = cpu_to_le32(RPM_KEY_SWEN);
+ req.nbytes = cpu_to_le32(sizeof(u32));
+ req.value = cpu_to_le32(1);
ret = rpm_reg_write_active(vreg, &req, sizeof(req));
if (!ret)
@@ -86,8 +86,8 @@ static int rpm_reg_disable(struct regulator_dev *rdev)
struct rpm_regulator_req req;
int ret;
- req.key = RPM_KEY_SWEN;
- req.nbytes = sizeof(u32);
+ req.key = cpu_to_le32(RPM_KEY_SWEN);
+ req.nbytes = cpu_to_le32(sizeof(u32));
req.value = 0;
ret = rpm_reg_write_active(vreg, &req, sizeof(req));
@@ -113,9 +113,9 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
struct rpm_regulator_req req;
int ret = 0;
- req.key = RPM_KEY_UV;
- req.nbytes = sizeof(u32);
- req.value = min_uV;
+ req.key = cpu_to_le32(RPM_KEY_UV);
+ req.nbytes = cpu_to_le32(sizeof(u32));
+ req.value = cpu_to_le32(min_uV);
ret = rpm_reg_write_active(vreg, &req, sizeof(req));
if (!ret)
@@ -129,9 +129,9 @@ 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;
- req.key = RPM_KEY_MA;
- req.nbytes = sizeof(u32);
- req.value = load_uA;
+ req.key = cpu_to_le32(RPM_KEY_MA);
+ req.nbytes = cpu_to_le32(sizeof(u32));
+ req.value = cpu_to_le32(load_uA / 1000);
return rpm_reg_write_active(vreg, &req, sizeof(req));
}
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
index 3510b3e7330a..ddc4f10e268a 100644
--- a/drivers/regulator/tps6105x-regulator.c
+++ b/drivers/regulator/tps6105x-regulator.c
@@ -14,7 +14,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/core.h>
@@ -33,7 +33,7 @@ static int tps6105x_regulator_enable(struct regulator_dev *rdev)
int ret;
/* Activate voltage mode */
- ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+ ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
TPS6105X_REG0_MODE_MASK,
TPS6105X_REG0_MODE_VOLTAGE << TPS6105X_REG0_MODE_SHIFT);
if (ret)
@@ -48,7 +48,7 @@ static int tps6105x_regulator_disable(struct regulator_dev *rdev)
int ret;
/* Set into shutdown mode */
- ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+ ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
TPS6105X_REG0_MODE_MASK,
TPS6105X_REG0_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
if (ret)
@@ -60,10 +60,10 @@ static int tps6105x_regulator_disable(struct regulator_dev *rdev)
static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev)
{
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
- u8 regval;
+ unsigned int regval;
int ret;
- ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+ ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);
if (ret)
return ret;
regval &= TPS6105X_REG0_MODE_MASK;
@@ -78,10 +78,10 @@ static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev)
static int tps6105x_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
- u8 regval;
+ unsigned int regval;
int ret;
- ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+ ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);
if (ret)
return ret;
@@ -96,7 +96,7 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
int ret;
- ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+ ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
TPS6105X_REG0_VOLTAGE_MASK,
selector << TPS6105X_REG0_VOLTAGE_SHIFT);
if (ret)
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 5cc19b44974a..d2c3d7cc35f5 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -86,6 +86,42 @@
#define TPS65023_MAX_REG_ID TPS65023_LDO_2
+#define TPS65023_REGULATOR_DCDC(_num, _t, _em) \
+ { \
+ .name = "VDCDC"#_num, \
+ .of_match = of_match_ptr("VDCDC"#_num), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .id = TPS65023_DCDC_##_num, \
+ .n_voltages = ARRAY_SIZE(_t), \
+ .ops = &tps65023_dcdc_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .volt_table = _t, \
+ .vsel_reg = TPS65023_REG_DEF_CORE, \
+ .vsel_mask = ARRAY_SIZE(_t) - 1, \
+ .enable_mask = _em, \
+ .enable_reg = TPS65023_REG_REG_CTRL, \
+ .apply_reg = TPS65023_REG_CON_CTRL2, \
+ .apply_bit = TPS65023_REG_CTRL2_GO, \
+ } \
+
+#define TPS65023_REGULATOR_LDO(_num, _t, _vm) \
+ { \
+ .name = "LDO"#_num, \
+ .of_match = of_match_ptr("LDO"#_num), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .id = TPS65023_LDO_##_num, \
+ .n_voltages = ARRAY_SIZE(_t), \
+ .ops = &tps65023_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .volt_table = _t, \
+ .vsel_reg = TPS65023_REG_LDO_CTRL, \
+ .vsel_mask = _vm, \
+ .enable_mask = 1 << (_num), \
+ .enable_reg = TPS65023_REG_REG_CTRL, \
+ } \
+
/* Supported voltage values for regulators */
static const unsigned int VCORE_VSEL_table[] = {
800000, 825000, 850000, 875000,
@@ -124,25 +160,16 @@ static const unsigned int TPS65023_LDO2_VSEL_table[] = {
2500000, 2800000, 3000000, 3300000,
};
-/* Regulator specific details */
-struct tps_info {
- const char *name;
- u8 table_len;
- const unsigned int *table;
-};
-
/* PMIC details */
struct tps_pmic {
- struct regulator_desc desc[TPS65023_NUM_REGULATOR];
struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
- const struct tps_info *info[TPS65023_NUM_REGULATOR];
+ const struct tps_driver_data *driver_data;
struct regmap *regmap;
- u8 core_regulator;
};
/* Struct passed as driver data */
struct tps_driver_data {
- const struct tps_info *info;
+ const struct regulator_desc *desc;
u8 core_regulator;
};
@@ -154,7 +181,7 @@ static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev)
if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
return -EINVAL;
- if (dcdc != tps->core_regulator)
+ if (dcdc != tps->driver_data->core_regulator)
return 0;
return regulator_get_voltage_sel_regmap(dev);
@@ -166,7 +193,7 @@ static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
struct tps_pmic *tps = rdev_get_drvdata(dev);
int dcdc = rdev_get_id(dev);
- if (dcdc != tps->core_regulator)
+ if (dcdc != tps->driver_data->core_regulator)
return -EINVAL;
return regulator_set_voltage_sel_regmap(dev, selector);
@@ -199,30 +226,60 @@ static const struct regmap_config tps65023_regmap_config = {
.val_bits = 8,
};
+static const struct regulator_desc tps65020_regulators[] = {
+ TPS65023_REGULATOR_DCDC(1, DCDC_FIXED_3300000_VSEL_table, 0x20),
+ TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_1800000_VSEL_table, 0x10),
+ TPS65023_REGULATOR_DCDC(3, VCORE_VSEL_table, 0x08),
+ TPS65023_REGULATOR_LDO(1, TPS65020_LDO_VSEL_table, 0x07),
+ TPS65023_REGULATOR_LDO(2, TPS65020_LDO_VSEL_table, 0x70),
+};
+
+static const struct regulator_desc tps65021_regulators[] = {
+ TPS65023_REGULATOR_DCDC(1, DCDC_FIXED_3300000_VSEL_table, 0x20),
+ TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_1800000_VSEL_table, 0x10),
+ TPS65023_REGULATOR_DCDC(3, VCORE_VSEL_table, 0x08),
+ TPS65023_REGULATOR_LDO(1, TPS65023_LDO1_VSEL_table, 0x07),
+ TPS65023_REGULATOR_LDO(2, TPS65023_LDO2_VSEL_table, 0x70),
+};
+
+static const struct regulator_desc tps65023_regulators[] = {
+ TPS65023_REGULATOR_DCDC(1, VCORE_VSEL_table, 0x20),
+ TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_3300000_VSEL_table, 0x10),
+ TPS65023_REGULATOR_DCDC(3, DCDC_FIXED_1800000_VSEL_table, 0x08),
+ TPS65023_REGULATOR_LDO(1, TPS65023_LDO1_VSEL_table, 0x07),
+ TPS65023_REGULATOR_LDO(2, TPS65023_LDO2_VSEL_table, 0x70),
+};
+
+static struct tps_driver_data tps65020_drv_data = {
+ .desc = tps65020_regulators,
+ .core_regulator = TPS65023_DCDC_3,
+};
+
+static struct tps_driver_data tps65021_drv_data = {
+ .desc = tps65021_regulators,
+ .core_regulator = TPS65023_DCDC_3,
+};
+
+static struct tps_driver_data tps65023_drv_data = {
+ .desc = tps65023_regulators,
+ .core_regulator = TPS65023_DCDC_1,
+};
+
static int tps_65023_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct tps_driver_data *drv_data = (void *)id->driver_data;
- const struct tps_info *info = drv_data->info;
+ struct regulator_init_data *init_data = dev_get_platdata(&client->dev);
struct regulator_config config = { };
- struct regulator_init_data *init_data;
- struct regulator_dev *rdev;
struct tps_pmic *tps;
int i;
int error;
- /**
- * init_data points to array of regulator_init structures
- * coming from the board-evm file.
- */
- init_data = dev_get_platdata(&client->dev);
- if (!init_data)
- return -EIO;
-
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
+ tps->driver_data = (struct tps_driver_data *)id->driver_data;
+
tps->regmap = devm_regmap_init_i2c(client, &tps65023_regmap_config);
if (IS_ERR(tps->regmap)) {
error = PTR_ERR(tps->regmap);
@@ -232,58 +289,22 @@ static int tps_65023_probe(struct i2c_client *client,
}
/* common for all regulators */
- tps->core_regulator = drv_data->core_regulator;
-
- for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) {
- /* Store regulator specific information */
- tps->info[i] = info;
-
- tps->desc[i].name = info->name;
- tps->desc[i].id = i;
- tps->desc[i].n_voltages = info->table_len;
- tps->desc[i].volt_table = info->table;
- tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
- &tps65023_ldo_ops : &tps65023_dcdc_ops);
- tps->desc[i].type = REGULATOR_VOLTAGE;
- tps->desc[i].owner = THIS_MODULE;
-
- tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL;
- switch (i) {
- case TPS65023_LDO_1:
- tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
- tps->desc[i].vsel_mask = 0x07;
- tps->desc[i].enable_mask = 1 << 1;
- break;
- case TPS65023_LDO_2:
- tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
- tps->desc[i].vsel_mask = 0x70;
- tps->desc[i].enable_mask = 1 << 2;
- break;
- default: /* DCDCx */
- tps->desc[i].enable_mask =
- 1 << (TPS65023_NUM_REGULATOR - i);
- tps->desc[i].vsel_reg = TPS65023_REG_DEF_CORE;
- tps->desc[i].vsel_mask = info->table_len - 1;
- tps->desc[i].apply_reg = TPS65023_REG_CON_CTRL2;
- tps->desc[i].apply_bit = TPS65023_REG_CTRL2_GO;
- }
+ config.dev = &client->dev;
+ config.driver_data = tps;
+ config.regmap = tps->regmap;
- config.dev = &client->dev;
- config.init_data = init_data;
- config.driver_data = tps;
- config.regmap = tps->regmap;
+ for (i = 0; i < TPS65023_NUM_REGULATOR; i++) {
+ if (init_data)
+ config.init_data = &init_data[i];
/* Register the regulators */
- rdev = devm_regulator_register(&client->dev, &tps->desc[i],
- &config);
- if (IS_ERR(rdev)) {
+ tps->rdev[i] = devm_regulator_register(&client->dev,
+ &tps->driver_data->desc[i], &config);
+ if (IS_ERR(tps->rdev[i])) {
dev_err(&client->dev, "failed to register %s\n",
id->name);
- return PTR_ERR(rdev);
+ return PTR_ERR(tps->rdev[i]);
}
-
- /* Save regulator for cleanup */
- tps->rdev[i] = rdev;
}
i2c_set_clientdata(client, tps);
@@ -296,120 +317,33 @@ static int tps_65023_probe(struct i2c_client *client,
return 0;
}
-static const struct tps_info tps65020_regs[] = {
- {
- .name = "VDCDC1",
- .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
- .table = DCDC_FIXED_3300000_VSEL_table,
- },
- {
- .name = "VDCDC2",
- .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
- .table = DCDC_FIXED_1800000_VSEL_table,
- },
- {
- .name = "VDCDC3",
- .table_len = ARRAY_SIZE(VCORE_VSEL_table),
- .table = VCORE_VSEL_table,
- },
- {
- .name = "LDO1",
- .table_len = ARRAY_SIZE(TPS65020_LDO_VSEL_table),
- .table = TPS65020_LDO_VSEL_table,
- },
- {
- .name = "LDO2",
- .table_len = ARRAY_SIZE(TPS65020_LDO_VSEL_table),
- .table = TPS65020_LDO_VSEL_table,
- },
-};
-
-static const struct tps_info tps65021_regs[] = {
- {
- .name = "VDCDC1",
- .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
- .table = DCDC_FIXED_3300000_VSEL_table,
- },
- {
- .name = "VDCDC2",
- .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
- .table = DCDC_FIXED_1800000_VSEL_table,
- },
- {
- .name = "VDCDC3",
- .table_len = ARRAY_SIZE(VCORE_VSEL_table),
- .table = VCORE_VSEL_table,
- },
- {
- .name = "LDO1",
- .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
- .table = TPS65023_LDO1_VSEL_table,
- },
- {
- .name = "LDO2",
- .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
- .table = TPS65023_LDO2_VSEL_table,
- },
+static const struct of_device_id tps65023_of_match[] = {
+ { .compatible = "ti,tps65020", .data = &tps65020_drv_data},
+ { .compatible = "ti,tps65021", .data = &tps65021_drv_data},
+ { .compatible = "ti,tps65023", .data = &tps65023_drv_data},
+ {},
};
+MODULE_DEVICE_TABLE(of, tps65023_of_match);
-static const struct tps_info tps65023_regs[] = {
- {
- .name = "VDCDC1",
- .table_len = ARRAY_SIZE(VCORE_VSEL_table),
- .table = VCORE_VSEL_table,
- },
- {
- .name = "VDCDC2",
- .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
- .table = DCDC_FIXED_3300000_VSEL_table,
- },
- {
- .name = "VDCDC3",
- .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
- .table = DCDC_FIXED_1800000_VSEL_table,
- },
- {
- .name = "LDO1",
- .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
- .table = TPS65023_LDO1_VSEL_table,
- },
+static const struct i2c_device_id tps_65023_id[] = {
{
- .name = "LDO2",
- .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
- .table = TPS65023_LDO2_VSEL_table,
+ .name = "tps65023",
+ .driver_data = (kernel_ulong_t)&tps65023_drv_data
+ }, {
+ .name = "tps65021",
+ .driver_data = (kernel_ulong_t)&tps65021_drv_data
+ }, {
+ .name = "tps65020",
+ .driver_data = (kernel_ulong_t)&tps65020_drv_data
},
-};
-
-static struct tps_driver_data tps65020_drv_data = {
- .info = tps65020_regs,
- .core_regulator = TPS65023_DCDC_3,
-};
-
-static struct tps_driver_data tps65021_drv_data = {
- .info = tps65021_regs,
- .core_regulator = TPS65023_DCDC_3,
-};
-
-static struct tps_driver_data tps65023_drv_data = {
- .info = tps65023_regs,
- .core_regulator = TPS65023_DCDC_1,
-};
-
-static const struct i2c_device_id tps_65023_id[] = {
- {.name = "tps65023",
- .driver_data = (unsigned long) &tps65023_drv_data},
- {.name = "tps65021",
- .driver_data = (unsigned long) &tps65021_drv_data,},
- {.name = "tps65020",
- .driver_data = (unsigned long) &tps65020_drv_data},
{ },
};
-
MODULE_DEVICE_TABLE(i2c, tps_65023_id);
static struct i2c_driver tps_65023_i2c_driver = {
.driver = {
.name = "tps65023",
+ .of_match_table = of_match_ptr(tps65023_of_match),
},
.probe = tps_65023_probe,
.id_table = tps_65023_id,
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 5b494db9f95c..9d6ea3a4dccd 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -629,7 +629,6 @@ static struct spi_driver pmic_driver = {
.probe = pmic_probe,
.driver = {
.name = "tps6524x",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9d4290617cee..2a524244afec 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -593,6 +593,15 @@ config RTC_DRV_RV3029C2
This driver can also be built as a module. If so, the module
will be called rtc-rv3029c2.
+config RTC_DRV_RV8803
+ tristate "Micro Crystal RV8803"
+ help
+ If you say yes here you get support for the Micro Crystal
+ RV8803 RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-rv8803.
+
config RTC_DRV_S5M
tristate "Samsung S2M/S5M series"
depends on MFD_SEC_CORE
@@ -666,8 +675,8 @@ config RTC_DRV_DS1390
If you say yes here you get support for the
Dallas/Maxim DS1390/93/94 chips.
- This driver only supports the RTC feature, and not other chip
- features such as alarms and trickle charging.
+ This driver supports the RTC feature and trickle charging but not
+ other chip features such as alarms.
This driver can also be built as a module. If so, the module
will be called rtc-ds1390.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index e491eb524434..231f76451615 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
+obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 51407c4c7bd2..24a0af650a1b 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -18,6 +18,7 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/pm_wakeirq.h>
#define AB8500_RTC_SOFF_STAT_REG 0x00
#define AB8500_RTC_CC_CONF_REG 0x01
@@ -493,11 +494,12 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
}
err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
- rtc_alarm_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ rtc_alarm_handler, IRQF_ONESHOT,
"ab8500-rtc", rtc);
if (err < 0)
return err;
+ dev_pm_set_wake_irq(&pdev->dev, irq);
platform_set_drvdata(pdev, rtc);
err = ab8500_sysfs_rtc_register(&pdev->dev);
@@ -513,6 +515,8 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
static int ab8500_rtc_remove(struct platform_device *pdev)
{
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
ab8500_sysfs_rtc_unregister(&pdev->dev);
return 0;
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index cb62e214b52a..b60fd477778f 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -495,6 +495,8 @@ static int at91_rtc_suspend(struct device *dev)
/* this IRQ is shared with DBGU and other hardware which isn't
* necessarily doing PM like we are...
*/
+ at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
+
at91_rtc_imr = at91_rtc_read_imr()
& (AT91_RTC_ALARM|AT91_RTC_SECEV);
if (at91_rtc_imr) {
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index 00a8f7f4f87c..284b587da65c 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -1,15 +1,15 @@
/* rtc-da9063.c - Real time clock device driver for DA9063
- * Copyright (C) 2013-14 Dialog Semiconductor Ltd.
+ * Copyright (C) 2013-2015 Dialog Semiconductor Ltd.
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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 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 library is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
#include <linux/delay.h>
@@ -516,5 +516,5 @@ module_platform_driver(da9063_rtc_driver);
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
MODULE_DESCRIPTION("Real time clock device driver for Dialog DA9063");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DA9063_DRVNAME_RTC);
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index c84f46168a52..c5432bf64e1c 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -546,7 +546,6 @@ static int __exit davinci_rtc_remove(struct platform_device *pdev)
}
static struct platform_driver davinci_rtc_driver = {
- .probe = davinci_rtc_probe,
.remove = __exit_p(davinci_rtc_remove),
.driver = {
.name = "rtc_davinci",
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index baa5d047f9c8..85706a9f82c9 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -772,7 +772,6 @@ static int ds1305_remove(struct spi_device *spi)
static struct spi_driver ds1305_driver = {
.driver.name = "rtc-ds1305",
- .driver.owner = THIS_MODULE,
.probe = ds1305_probe,
.remove = ds1305_remove,
/* REVISIT add suspend/resume */
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index a705e6490808..188006c55ce0 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -718,9 +718,9 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
regs[3] = bin2bcd(t->time.tm_sec);
regs[4] = bin2bcd(t->time.tm_min);
regs[5] = bin2bcd(t->time.tm_hour);
- regs[6] = bin2bcd(t->time.tm_wday) + 1;
+ regs[6] = bin2bcd(t->time.tm_wday + 1);
regs[7] = bin2bcd(t->time.tm_mday);
- regs[8] = bin2bcd(t->time.tm_mon) + 1;
+ regs[8] = bin2bcd(t->time.tm_mon + 1);
/* Clear the alarm 0 interrupt flag. */
regs[6] &= ~MCP794XX_BIT_ALMX_IF;
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index 79a06dd3c185..3d389bd8a289 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -21,6 +21,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/pm.h>
+#include <linux/pm_wakeirq.h>
#include <linux/slab.h>
#define DS1343_DRV_VERSION "01.00"
@@ -663,15 +664,15 @@ static int ds1343_probe(struct spi_device *spi)
if (priv->irq >= 0) {
res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
- ds1343_thread,
- IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ ds1343_thread, IRQF_ONESHOT,
"ds1343", priv);
if (res) {
priv->irq = -1;
dev_err(&spi->dev,
"unable to request irq for rtc ds1343\n");
} else {
- device_set_wakeup_capable(&spi->dev, 1);
+ device_init_wakeup(&spi->dev, true);
+ dev_pm_set_wake_irq(&spi->dev, spi->irq);
}
}
@@ -692,6 +693,8 @@ static int ds1343_remove(struct spi_device *spi)
priv->irqen &= ~RTC_AF;
mutex_unlock(&priv->mutex);
+ dev_pm_clear_wake_irq(&spi->dev);
+ device_init_wakeup(&spi->dev, false);
devm_free_irq(&spi->dev, spi->irq, priv);
}
@@ -731,7 +734,6 @@ static SIMPLE_DEV_PM_OPS(ds1343_pm, ds1343_suspend, ds1343_resume);
static struct spi_driver ds1343_driver = {
.driver = {
.name = "ds1343",
- .owner = THIS_MODULE,
.pm = &ds1343_pm,
},
.probe = ds1343_probe,
diff --git a/drivers/rtc/rtc-ds1347.c b/drivers/rtc/rtc-ds1347.c
index c82b4c050326..641e8e8a0dd7 100644
--- a/drivers/rtc/rtc-ds1347.c
+++ b/drivers/rtc/rtc-ds1347.c
@@ -154,7 +154,6 @@ static int ds1347_probe(struct spi_device *spi)
static struct spi_driver ds1347_driver = {
.driver = {
.name = "ds1347",
- .owner = THIS_MODULE,
},
.probe = ds1347_probe,
};
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index e67bfcb3a1aa..aa0d2c6f1edc 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -20,6 +20,7 @@
#include <linux/spi/spi.h>
#include <linux/bcd.h>
#include <linux/slab.h>
+#include <linux/of.h>
#define DS1390_REG_100THS 0x00
#define DS1390_REG_SECONDS 0x01
@@ -40,11 +41,31 @@
#define DS1390_REG_STATUS 0x0E
#define DS1390_REG_TRICKLE 0x0F
+#define DS1390_TRICKLE_CHARGER_ENABLE 0xA0
+#define DS1390_TRICKLE_CHARGER_250_OHM 0x01
+#define DS1390_TRICKLE_CHARGER_2K_OHM 0x02
+#define DS1390_TRICKLE_CHARGER_4K_OHM 0x03
+#define DS1390_TRICKLE_CHARGER_NO_DIODE 0x04
+#define DS1390_TRICKLE_CHARGER_DIODE 0x08
+
struct ds1390 {
struct rtc_device *rtc;
u8 txrx_buf[9]; /* cmd + 8 registers */
};
+static void ds1390_set_reg(struct device *dev, unsigned char address,
+ unsigned char data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ unsigned char buf[2];
+
+ /* MSB must be '1' to write */
+ buf[0] = address | 0x80;
+ buf[1] = data;
+
+ spi_write(spi, buf, 2);
+}
+
static int ds1390_get_reg(struct device *dev, unsigned char address,
unsigned char *data)
{
@@ -62,11 +83,50 @@ static int ds1390_get_reg(struct device *dev, unsigned char address,
if (status != 0)
return status;
- *data = chip->txrx_buf[1];
+ *data = chip->txrx_buf[0];
return 0;
}
+static void ds1390_trickle_of_init(struct spi_device *spi)
+{
+ u32 ohms = 0;
+ u8 value;
+
+ if (of_property_read_u32(spi->dev.of_node, "trickle-resistor-ohms",
+ &ohms))
+ goto out;
+
+ /* Enable charger */
+ value = DS1390_TRICKLE_CHARGER_ENABLE;
+ if (of_property_read_bool(spi->dev.of_node, "trickle-diode-disable"))
+ value |= DS1390_TRICKLE_CHARGER_NO_DIODE;
+ else
+ value |= DS1390_TRICKLE_CHARGER_DIODE;
+
+ /* Resistor select */
+ switch (ohms) {
+ case 250:
+ value |= DS1390_TRICKLE_CHARGER_250_OHM;
+ break;
+ case 2000:
+ value |= DS1390_TRICKLE_CHARGER_2K_OHM;
+ break;
+ case 4000:
+ value |= DS1390_TRICKLE_CHARGER_4K_OHM;
+ break;
+ default:
+ dev_warn(&spi->dev,
+ "Unsupported ohm value %02ux in dt\n", ohms);
+ return;
+ }
+
+ ds1390_set_reg(&spi->dev, DS1390_REG_TRICKLE, value);
+
+out:
+ return;
+}
+
static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
{
struct spi_device *spi = to_spi_device(dev);
@@ -143,6 +203,9 @@ static int ds1390_probe(struct spi_device *spi)
return res;
}
+ if (spi->dev.of_node)
+ ds1390_trickle_of_init(spi);
+
chip->rtc = devm_rtc_device_register(&spi->dev, "ds1390",
&ds1390_rtc_ops, THIS_MODULE);
if (IS_ERR(chip->rtc)) {
@@ -156,7 +219,6 @@ static int ds1390_probe(struct spi_device *spi)
static struct spi_driver ds1390_driver = {
.driver = {
.name = "rtc-ds1390",
- .owner = THIS_MODULE,
},
.probe = ds1390_probe,
};
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
index 4c9ba5368464..570ab28fc354 100644
--- a/drivers/rtc/rtc-ds3234.c
+++ b/drivers/rtc/rtc-ds3234.c
@@ -159,7 +159,6 @@ static int ds3234_probe(struct spi_device *spi)
static struct spi_driver ds3234_driver = {
.driver = {
.name = "ds3234",
- .owner = THIS_MODULE,
},
.probe = ds3234_probe,
};
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c
index a0462e5430c7..54328d4ac0d3 100644
--- a/drivers/rtc/rtc-isl12057.c
+++ b/drivers/rtc/rtc-isl12057.c
@@ -466,9 +466,8 @@ static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap)
* is for instance the case on ReadyNAS 102, 104 and 2120. On those
* devices with no IRQ driectly connected to the SoC, the RTC chip
* can be forced as a wakeup source by stating that explicitly in
- * the device's .dts file using the "isil,irq2-can-wakeup-machine"
- * boolean property. This will guarantee 'wakealarm' sysfs entry is
- * available on the device.
+ * the device's .dts file using the "wakeup-source" boolean property.
+ * This will guarantee 'wakealarm' sysfs entry is available on the device.
*
* The function below returns 1, i.e. the capability of the chip to
* wakeup the device, based on IRQ availability or if the boolean
@@ -479,8 +478,9 @@ static bool isl12057_can_wakeup_machine(struct device *dev)
{
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
- return (data->irq || of_property_read_bool(dev->of_node,
- "isil,irq2-can-wakeup-machine"));
+ return data->irq || of_property_read_bool(dev->of_node, "wakeup-source")
+ || of_property_read_bool(dev->of_node, /* legacy */
+ "isil,irq2-can-wakeup-machine");
}
#else
static bool isl12057_can_wakeup_machine(struct device *dev)
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index aa3b8f1b34d9..b57a304ff62c 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -638,7 +638,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (client->irq > 0) {
rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
isl1208_rtc_interrupt,
- IRQF_SHARED,
+ IRQF_SHARED | IRQF_ONESHOT,
isl1208_driver.driver.name,
client);
if (!rc) {
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 4698c7e344e4..5ac45fc1a787 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -197,7 +197,6 @@ static int m41t93_probe(struct spi_device *spi)
static struct spi_driver m41t93_driver = {
.driver = {
.name = "rtc-m41t93",
- .owner = THIS_MODULE,
},
.probe = m41t93_probe,
};
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
index 8d800b1bf87b..1f0eb79e69f9 100644
--- a/drivers/rtc/rtc-m41t94.c
+++ b/drivers/rtc/rtc-m41t94.c
@@ -137,7 +137,6 @@ static int m41t94_probe(struct spi_device *spi)
static struct spi_driver m41t94_driver = {
.driver = {
.name = "rtc-m41t94",
- .owner = THIS_MODULE,
},
.probe = m41t94_probe,
};
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index ac3f4191864f..315d09e0f2c1 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -146,7 +146,6 @@ static int max6902_probe(struct spi_device *spi)
static struct spi_driver max6902_driver = {
.driver = {
.name = "rtc-max6902",
- .owner = THIS_MODULE,
},
.probe = max6902_probe,
};
diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c
index 34295bf00416..1c91ce8a6d75 100644
--- a/drivers/rtc/rtc-mcp795.c
+++ b/drivers/rtc/rtc-mcp795.c
@@ -186,7 +186,6 @@ static int mcp795_probe(struct spi_device *spi)
static struct spi_driver mcp795_driver = {
.driver = {
.name = "rtc-mcp795",
- .owner = THIS_MODULE,
},
.probe = mcp795_probe,
};
diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c
index 6fbf9e617151..df39ce02a99d 100644
--- a/drivers/rtc/rtc-opal.c
+++ b/drivers/rtc/rtc-opal.c
@@ -152,10 +152,10 @@ exit:
/* Set Timed Power-On */
static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm)
{
- u64 h_m_s_ms = 0, token;
+ u64 h_m_s_ms = 0;
struct opal_msg msg;
u32 y_m_d = 0;
- int rc;
+ int token, rc;
tm_to_opal(&alarm->time, &y_m_d, &h_m_s_ms);
@@ -199,8 +199,9 @@ static int opal_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
- if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo",
- NULL)) {
+ if (pdev->dev.of_node &&
+ (of_property_read_bool(pdev->dev.of_node, "wakeup-source") ||
+ of_property_read_bool(pdev->dev.of_node, "has-tpo")/* legacy */)) {
device_set_wakeup_capable(&pdev->dev, true);
opal_rtc_ops.read_alarm = opal_get_tpo_time;
opal_rtc_ops.set_alarm = opal_set_tpo_time;
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index 1c47650fe624..ea8a31c91641 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -346,7 +346,6 @@ MODULE_DEVICE_TABLE(of, pcf2123_dt_ids);
static struct spi_driver pcf2123_driver = {
.driver = {
.name = "rtc-pcf2123",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf2123_dt_ids),
},
.probe = pcf2123_probe,
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 4b11d31f7174..629bfdf8c745 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -20,11 +20,12 @@
#include <linux/module.h>
#include <linux/of.h>
-#define DRV_VERSION "0.0.1"
-
#define PCF2127_REG_CTRL1 (0x00) /* Control Register 1 */
#define PCF2127_REG_CTRL2 (0x01) /* Control Register 2 */
+
#define PCF2127_REG_CTRL3 (0x02) /* Control Register 3 */
+#define PCF2127_REG_CTRL3_BLF BIT(2)
+
#define PCF2127_REG_SC (0x03) /* datetime */
#define PCF2127_REG_MN (0x04)
#define PCF2127_REG_HR (0x05)
@@ -39,8 +40,6 @@ static struct i2c_driver pcf2127_driver;
struct pcf2127 {
struct rtc_device *rtc;
- int voltage_low; /* indicates if a low_voltage was detected */
- int oscillator_failed; /* OSF was detected and date is unreliable */
};
/*
@@ -49,7 +48,6 @@ struct pcf2127 {
*/
static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{
- struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
unsigned char buf[10] = { PCF2127_REG_CTRL1 };
/* read registers */
@@ -59,18 +57,15 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
- if (buf[PCF2127_REG_CTRL3] & 0x04) {
- pcf2127->voltage_low = 1;
+ if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
dev_info(&client->dev,
"low voltage detected, check/replace RTC battery.\n");
- }
if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
/*
* no need clear the flag here,
* it will be cleared once the new date is saved
*/
- pcf2127->oscillator_failed = 1;
dev_warn(&client->dev,
"oscillator stop detected, date/time is not reliable\n");
return -EINVAL;
@@ -107,7 +102,6 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
- struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
unsigned char buf[8];
int i = 0, err;
@@ -141,9 +135,6 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
- /* clear OSF flag in client data */
- pcf2127->oscillator_failed = 0;
-
return 0;
}
@@ -151,17 +142,28 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_rtc_ioctl(struct device *dev,
unsigned int cmd, unsigned long arg)
{
- struct pcf2127 *pcf2127 = i2c_get_clientdata(to_i2c_client(dev));
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char buf = PCF2127_REG_CTRL3;
+ int touser;
+ int ret;
switch (cmd) {
case RTC_VL_READ:
- if (pcf2127->voltage_low)
- dev_info(dev, "low voltage detected, check/replace battery\n");
- if (pcf2127->oscillator_failed)
- dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
+ ret = i2c_master_send(client, &buf, 1);
+ if (!ret)
+ ret = -EIO;
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_master_recv(client, &buf, 1);
+ if (!ret)
+ ret = -EIO;
+ if (ret < 0)
+ return ret;
- if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
- sizeof(int)))
+ touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;
+
+ if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
return -EFAULT;
return 0;
default:
@@ -203,8 +205,6 @@ static int pcf2127_probe(struct i2c_client *client,
if (!pcf2127)
return -ENOMEM;
- dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
-
i2c_set_clientdata(client, pcf2127);
pcf2127->rtc = devm_rtc_device_register(&client->dev,
@@ -241,5 +241,4 @@ module_i2c_driver(pcf2127_driver);
MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
MODULE_DESCRIPTION("NXP PCF2127 RTC driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index b6d73dd881f2..63334cbeca41 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -80,13 +80,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
(tm->tm_year >= 100) : (tm->tm_year < 100);
- /* the clock can give out invalid datetime, but we cannot return
- * -EINVAL otherwise hwclock will refuse to set the time on bootup.
- */
- if (rtc_valid_tm(tm) < 0)
- dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
- return 0;
+ return rtc_valid_tm(tm);
}
static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index e569243db57e..c8f95b8e463a 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -14,6 +14,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/clk-provider.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
@@ -40,7 +41,14 @@
#define PCF8563_REG_AMN 0x09 /* alarm */
-#define PCF8563_REG_CLKO 0x0D /* clock out */
+#define PCF8563_REG_CLKO 0x0D /* clock out */
+#define PCF8563_REG_CLKO_FE 0x80 /* clock out enabled */
+#define PCF8563_REG_CLKO_F_MASK 0x03 /* frequenc mask */
+#define PCF8563_REG_CLKO_F_32768HZ 0x00
+#define PCF8563_REG_CLKO_F_1024HZ 0x01
+#define PCF8563_REG_CLKO_F_32HZ 0x02
+#define PCF8563_REG_CLKO_F_1HZ 0x03
+
#define PCF8563_REG_TMRC 0x0E /* timer control */
#define PCF8563_TMRC_ENABLE BIT(7)
#define PCF8563_TMRC_4096 0
@@ -76,6 +84,9 @@ struct pcf8563 {
int voltage_low; /* incicates if a low_voltage was detected */
struct i2c_client *client;
+#ifdef CONFIG_COMMON_CLK
+ struct clk_hw clkout_hw;
+#endif
};
static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
@@ -390,6 +401,158 @@ static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
}
+#ifdef CONFIG_COMMON_CLK
+/*
+ * Handling of the clkout
+ */
+
+#define clkout_hw_to_pcf8563(_hw) container_of(_hw, struct pcf8563, clkout_hw)
+
+static int clkout_rates[] = {
+ 32768,
+ 1024,
+ 32,
+ 1,
+};
+
+static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+ struct i2c_client *client = pcf8563->client;
+ unsigned char buf;
+ int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+ if (ret < 0)
+ return 0;
+
+ buf &= PCF8563_REG_CLKO_F_MASK;
+ return clkout_rates[ret];
+}
+
+static long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+ if (clkout_rates[i] <= rate)
+ return clkout_rates[i];
+
+ return 0;
+}
+
+static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+ struct i2c_client *client = pcf8563->client;
+ unsigned char buf;
+ int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ int i;
+
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+ if (clkout_rates[i] == rate) {
+ buf &= ~PCF8563_REG_CLKO_F_MASK;
+ buf |= i;
+ ret = pcf8563_write_block_data(client,
+ PCF8563_REG_CLKO, 1,
+ &buf);
+ return ret;
+ }
+
+ return -EINVAL;
+}
+
+static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
+{
+ struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+ struct i2c_client *client = pcf8563->client;
+ unsigned char buf;
+ int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+ if (ret < 0)
+ return ret;
+
+ if (enable)
+ buf |= PCF8563_REG_CLKO_FE;
+ else
+ buf &= ~PCF8563_REG_CLKO_FE;
+
+ ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ return ret;
+}
+
+static int pcf8563_clkout_prepare(struct clk_hw *hw)
+{
+ return pcf8563_clkout_control(hw, 1);
+}
+
+static void pcf8563_clkout_unprepare(struct clk_hw *hw)
+{
+ pcf8563_clkout_control(hw, 0);
+}
+
+static int pcf8563_clkout_is_prepared(struct clk_hw *hw)
+{
+ struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+ struct i2c_client *client = pcf8563->client;
+ unsigned char buf;
+ int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+ if (ret < 0)
+ return ret;
+
+ return !!(buf & PCF8563_REG_CLKO_FE);
+}
+
+static const struct clk_ops pcf8563_clkout_ops = {
+ .prepare = pcf8563_clkout_prepare,
+ .unprepare = pcf8563_clkout_unprepare,
+ .is_prepared = pcf8563_clkout_is_prepared,
+ .recalc_rate = pcf8563_clkout_recalc_rate,
+ .round_rate = pcf8563_clkout_round_rate,
+ .set_rate = pcf8563_clkout_set_rate,
+};
+
+static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
+{
+ struct i2c_client *client = pcf8563->client;
+ struct device_node *node = client->dev.of_node;
+ struct clk *clk;
+ struct clk_init_data init;
+ int ret;
+ unsigned char buf;
+
+ /* disable the clkout output */
+ buf = 0;
+ ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ init.name = "pcf8563-clkout";
+ init.ops = &pcf8563_clkout_ops;
+ init.flags = CLK_IS_ROOT;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ pcf8563->clkout_hw.init = &init;
+
+ /* optional override of the clockname */
+ of_property_read_string(node, "clock-output-names", &init.name);
+
+ /* register the clock */
+ clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);
+
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return clk;
+}
+#endif
+
static const struct rtc_class_ops pcf8563_rtc_ops = {
.ioctl = pcf8563_rtc_ioctl,
.read_time = pcf8563_rtc_read_time,
@@ -459,6 +622,11 @@ static int pcf8563_probe(struct i2c_client *client,
}
+#ifdef CONFIG_COMMON_CLK
+ /* register clk in common clk framework */
+ pcf8563_clkout_register_clk(pcf8563);
+#endif
+
/* the pcf8563 alarm only supports a minute accuracy */
pcf8563->rtc->uie_unsupported = 1;
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 41dcb7ddb906..e1687e19c59f 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -23,6 +23,7 @@
#include <linux/io.h>
#include <linux/bcd.h>
#include <linux/delay.h>
+#include <linux/pm_wakeirq.h>
#include <linux/slab.h>
/*
@@ -305,6 +306,8 @@ static int pl031_remove(struct amba_device *adev)
{
struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
+ dev_pm_clear_wake_irq(&adev->dev);
+ device_init_wakeup(&adev->dev, false);
free_irq(adev->irq[0], ldata);
rtc_device_unregister(ldata->rtc);
iounmap(ldata->base);
@@ -370,7 +373,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
}
}
- device_init_wakeup(&adev->dev, 1);
+ device_init_wakeup(&adev->dev, true);
ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
THIS_MODULE);
if (IS_ERR(ldata->rtc)) {
@@ -383,7 +386,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
ret = -EIO;
goto out_no_irq;
}
-
+ dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
return 0;
out_no_irq:
@@ -408,7 +411,6 @@ static struct pl031_vendor_data arm_pl031 = {
.set_alarm = pl031_set_alarm,
.alarm_irq_enable = pl031_alarm_irq_enable,
},
- .irqflags = IRQF_NO_SUSPEND,
};
/* The First ST derivative */
@@ -422,7 +424,6 @@ static struct pl031_vendor_data stv1_pl031 = {
},
.clockwatch = true,
.st_weekday = true,
- .irqflags = IRQF_NO_SUSPEND,
};
/* And the second ST derivative */
@@ -439,8 +440,10 @@ static struct pl031_vendor_data stv2_pl031 = {
/*
* This variant shares the IRQ with another block and must not
* suspend that IRQ line.
+ * TODO check if it shares with IRQF_NO_SUSPEND user, else we can
+ * remove IRQF_COND_SUSPEND
*/
- .irqflags = IRQF_SHARED | IRQF_NO_SUSPEND,
+ .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
};
static struct amba_id pl031_ids[] = {
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index feeedbd82000..83d2bcca6a8f 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -172,7 +172,6 @@ static int r9701_remove(struct spi_device *spi)
static struct spi_driver r9701_driver = {
.driver = {
.name = "rtc-r9701",
- .owner = THIS_MODULE,
},
.probe = r9701_probe,
.remove = r9701_remove,
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
index 090a101c1c81..1162fecab8cf 100644
--- a/drivers/rtc/rtc-rs5c348.c
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -221,7 +221,6 @@ static int rs5c348_probe(struct spi_device *spi)
static struct spi_driver rs5c348_driver = {
.driver = {
.name = "rtc-rs5c348",
- .owner = THIS_MODULE,
},
.probe = rs5c348_probe,
};
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
new file mode 100644
index 000000000000..e7329e21bfe3
--- /dev/null
+++ b/drivers/rtc/rtc-rv8803.c
@@ -0,0 +1,521 @@
+/*
+ * RTC driver for the Micro Crystal RV8803
+ *
+ * Copyright (C) 2015 Micro Crystal SA
+ *
+ * Alexandre Belloni <alexandre.belloni@free-electrons.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/bcd.h>
+#include <linux/bitops.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+#define RV8803_SEC 0x00
+#define RV8803_MIN 0x01
+#define RV8803_HOUR 0x02
+#define RV8803_WEEK 0x03
+#define RV8803_DAY 0x04
+#define RV8803_MONTH 0x05
+#define RV8803_YEAR 0x06
+#define RV8803_RAM 0x07
+#define RV8803_ALARM_MIN 0x08
+#define RV8803_ALARM_HOUR 0x09
+#define RV8803_ALARM_WEEK_OR_DAY 0x0A
+#define RV8803_EXT 0x0D
+#define RV8803_FLAG 0x0E
+#define RV8803_CTRL 0x0F
+
+#define RV8803_EXT_WADA BIT(6)
+
+#define RV8803_FLAG_V1F BIT(0)
+#define RV8803_FLAG_V2F BIT(1)
+#define RV8803_FLAG_AF BIT(3)
+#define RV8803_FLAG_TF BIT(4)
+#define RV8803_FLAG_UF BIT(5)
+
+#define RV8803_CTRL_RESET BIT(0)
+
+#define RV8803_CTRL_EIE BIT(2)
+#define RV8803_CTRL_AIE BIT(3)
+#define RV8803_CTRL_TIE BIT(4)
+#define RV8803_CTRL_UIE BIT(5)
+
+struct rv8803_data {
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+ spinlock_t flags_lock;
+ u8 ctrl;
+};
+
+static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
+{
+ struct i2c_client *client = dev_id;
+ struct rv8803_data *rv8803 = i2c_get_clientdata(client);
+ unsigned long events = 0;
+ u8 flags;
+
+ spin_lock(&rv8803->flags_lock);
+
+ flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ if (flags <= 0) {
+ spin_unlock(&rv8803->flags_lock);
+ return IRQ_NONE;
+ }
+
+ if (flags & RV8803_FLAG_V1F)
+ dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
+
+ if (flags & RV8803_FLAG_V2F)
+ dev_warn(&client->dev, "Voltage low, data loss detected.\n");
+
+ if (flags & RV8803_FLAG_TF) {
+ flags &= ~RV8803_FLAG_TF;
+ rv8803->ctrl &= ~RV8803_CTRL_TIE;
+ events |= RTC_PF;
+ }
+
+ if (flags & RV8803_FLAG_AF) {
+ flags &= ~RV8803_FLAG_AF;
+ rv8803->ctrl &= ~RV8803_CTRL_AIE;
+ events |= RTC_AF;
+ }
+
+ if (flags & RV8803_FLAG_UF) {
+ flags &= ~RV8803_FLAG_UF;
+ rv8803->ctrl &= ~RV8803_CTRL_UIE;
+ events |= RTC_UF;
+ }
+
+ if (events) {
+ rtc_update_irq(rv8803->rtc, 1, events);
+ i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+ i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
+ rv8803->ctrl);
+ }
+
+ spin_unlock(&rv8803->flags_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+ u8 date1[7];
+ u8 date2[7];
+ u8 *date = date1;
+ int ret, flags;
+
+ flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+ if (flags < 0)
+ return flags;
+
+ if (flags & RV8803_FLAG_V2F) {
+ dev_warn(dev, "Voltage low, data is invalid.\n");
+ return -EINVAL;
+ }
+
+ ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
+ 7, date);
+ if (ret != 7)
+ return ret < 0 ? ret : -EIO;
+
+ if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) {
+ ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
+ 7, date2);
+ if (ret != 7)
+ return ret < 0 ? ret : -EIO;
+
+ if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59))
+ date = date2;
+ }
+
+ tm->tm_sec = bcd2bin(date[RV8803_SEC] & 0x7f);
+ tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f);
+ tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f);
+ tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f);
+ tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f);
+ tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1;
+ tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100;
+
+ return rtc_valid_tm(tm);
+}
+
+static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+ u8 date[7];
+ int flags, ret;
+ unsigned long irqflags;
+
+ if ((tm->tm_year < 100) || (tm->tm_year > 199))
+ return -EINVAL;
+
+ date[RV8803_SEC] = bin2bcd(tm->tm_sec);
+ date[RV8803_MIN] = bin2bcd(tm->tm_min);
+ date[RV8803_HOUR] = bin2bcd(tm->tm_hour);
+ date[RV8803_WEEK] = 1 << (tm->tm_wday);
+ date[RV8803_DAY] = bin2bcd(tm->tm_mday);
+ date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1);
+ date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100);
+
+ ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC,
+ 7, date);
+ if (ret < 0)
+ return ret;
+
+ spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+
+ flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+ if (flags < 0) {
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ return flags;
+ }
+
+ ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
+ flags & ~RV8803_FLAG_V2F);
+
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+
+ return ret;
+}
+
+static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+ struct i2c_client *client = rv8803->client;
+ u8 alarmvals[3];
+ int flags, ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN,
+ 3, alarmvals);
+ if (ret != 3)
+ return ret < 0 ? ret : -EIO;
+
+ flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ if (flags < 0)
+ return flags;
+
+ alrm->time.tm_sec = 0;
+ alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
+ alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
+ alrm->time.tm_wday = -1;
+ alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
+ alrm->time.tm_mon = -1;
+ alrm->time.tm_year = -1;
+
+ alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
+ alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
+
+ return 0;
+}
+
+static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+ u8 alarmvals[3];
+ u8 ctrl[2];
+ int ret, err;
+ unsigned long irqflags;
+
+ /* The alarm has no seconds, round up to nearest minute */
+ if (alrm->time.tm_sec) {
+ time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
+
+ alarm_time += 60 - alrm->time.tm_sec;
+ rtc_time64_to_tm(alarm_time, &alrm->time);
+ }
+
+ spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+
+ ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
+ if (ret != 2) {
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ alarmvals[0] = bin2bcd(alrm->time.tm_min);
+ alarmvals[1] = bin2bcd(alrm->time.tm_hour);
+ alarmvals[2] = bin2bcd(alrm->time.tm_mday);
+
+ if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) {
+ rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE);
+ err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
+ rv8803->ctrl);
+ if (err) {
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ return err;
+ }
+ }
+
+ ctrl[1] &= ~RV8803_FLAG_AF;
+ err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ if (err)
+ return err;
+
+ err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN,
+ 3, alarmvals);
+ if (err)
+ return err;
+
+ if (alrm->enabled) {
+ if (rv8803->rtc->uie_rtctimer.enabled)
+ rv8803->ctrl |= RV8803_CTRL_UIE;
+ if (rv8803->rtc->aie_timer.enabled)
+ rv8803->ctrl |= RV8803_CTRL_AIE;
+
+ err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
+ rv8803->ctrl);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+ int ctrl, flags, err;
+ unsigned long irqflags;
+
+ ctrl = rv8803->ctrl;
+
+ if (enabled) {
+ if (rv8803->rtc->uie_rtctimer.enabled)
+ ctrl |= RV8803_CTRL_UIE;
+ if (rv8803->rtc->aie_timer.enabled)
+ ctrl |= RV8803_CTRL_AIE;
+ } else {
+ if (!rv8803->rtc->uie_rtctimer.enabled)
+ ctrl &= ~RV8803_CTRL_UIE;
+ if (!rv8803->rtc->aie_timer.enabled)
+ ctrl &= ~RV8803_CTRL_AIE;
+ }
+
+ spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+ flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ if (flags < 0) {
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ return flags;
+ }
+ flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
+ err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ if (err)
+ return err;
+
+ if (ctrl != rv8803->ctrl) {
+ rv8803->ctrl = ctrl;
+ err = i2c_smbus_write_byte_data(client, RV8803_CTRL,
+ rv8803->ctrl);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev);
+ int flags, ret = 0;
+ unsigned long irqflags;
+
+ switch (cmd) {
+ case RTC_VL_READ:
+ flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ if (flags < 0)
+ return flags;
+
+ if (flags & RV8803_FLAG_V1F)
+ dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
+
+ if (flags & RV8803_FLAG_V2F)
+ dev_warn(&client->dev, "Voltage low, data loss detected.\n");
+
+ flags &= RV8803_FLAG_V1F | RV8803_FLAG_V2F;
+
+ if (copy_to_user((void __user *)arg, &flags, sizeof(int)))
+ return -EFAULT;
+
+ return 0;
+
+ case RTC_VL_CLR:
+ spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+ flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ if (flags < 0) {
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ return flags;
+ }
+
+ flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
+ ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+ spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]);
+ if (ret < 0)
+ return ret;
+
+ return 1;
+}
+
+static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, RV8803_RAM);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = ret;
+
+ return 1;
+}
+
+static struct bin_attribute rv8803_nvram_attr = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = 1,
+ .read = rv8803_nvram_read,
+ .write = rv8803_nvram_write,
+};
+
+static struct rtc_class_ops rv8803_rtc_ops = {
+ .read_time = rv8803_get_time,
+ .set_time = rv8803_set_time,
+ .ioctl = rv8803_ioctl,
+};
+
+static int rv8803_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct rv8803_data *rv8803;
+ int err, flags;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
+ return -EIO;
+ }
+
+ rv8803 = devm_kzalloc(&client->dev, sizeof(struct rv8803_data),
+ GFP_KERNEL);
+ if (!rv8803)
+ return -ENOMEM;
+
+ rv8803->client = client;
+ i2c_set_clientdata(client, rv8803);
+
+ flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ if (flags < 0)
+ return flags;
+
+ if (flags & RV8803_FLAG_V1F)
+ dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
+
+ if (flags & RV8803_FLAG_V2F)
+ dev_warn(&client->dev, "Voltage low, data loss detected.\n");
+
+ if (flags & RV8803_FLAG_AF)
+ dev_warn(&client->dev, "An alarm maybe have been missed.\n");
+
+ if (client->irq > 0) {
+ err = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, rv8803_handle_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "rv8803", client);
+ if (err) {
+ dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
+ client->irq = 0;
+ } else {
+ rv8803_rtc_ops.read_alarm = rv8803_get_alarm;
+ rv8803_rtc_ops.set_alarm = rv8803_set_alarm;
+ rv8803_rtc_ops.alarm_irq_enable = rv8803_alarm_irq_enable;
+ }
+ }
+
+ rv8803->rtc = devm_rtc_device_register(&client->dev, client->name,
+ &rv8803_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rv8803->rtc)) {
+ dev_err(&client->dev, "unable to register the class device\n");
+ return PTR_ERR(rv8803->rtc);
+ }
+
+ err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
+ RV8803_EXT_WADA);
+ if (err)
+ return err;
+
+ err = device_create_bin_file(&client->dev, &rv8803_nvram_attr);
+ if (err)
+ return err;
+
+ rv8803->rtc->max_user_freq = 1;
+
+ return 0;
+}
+
+static int rv8803_remove(struct i2c_client *client)
+{
+ device_remove_bin_file(&client->dev, &rv8803_nvram_attr);
+
+ return 0;
+}
+
+static const struct i2c_device_id rv8803_id[] = {
+ { "rv8803", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rv8803_id);
+
+static struct i2c_driver rv8803_driver = {
+ .driver = {
+ .name = "rtc-rv8803",
+ },
+ .probe = rv8803_probe,
+ .remove = rv8803_remove,
+ .id_table = rv8803_id,
+};
+module_i2c_driver(rv8803_driver);
+
+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
+MODULE_DESCRIPTION("Micro Crystal RV8803 RTC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c
index 6889222f9ed6..de3fe4f8d133 100644
--- a/drivers/rtc/rtc-rx4581.c
+++ b/drivers/rtc/rtc-rx4581.c
@@ -291,7 +291,6 @@ MODULE_DEVICE_TABLE(spi, rx4581_id);
static struct spi_driver rx4581_driver = {
.driver = {
.name = "rtc-rx4581",
- .owner = THIS_MODULE,
},
.probe = rx4581_probe,
.id_table = rx4581_id,
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 24c3d69ce1b9..bd911bafb809 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -65,6 +65,7 @@
static const struct i2c_device_id rx8025_id[] = {
{ "rx8025", 0 },
+ { "rv8803", 1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx8025_id);
@@ -518,9 +519,8 @@ static int rx8025_probe(struct i2c_client *client,
}
rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
- if (!rx8025) {
+ if (!rx8025)
return -ENOMEM;
- }
rx8025->client = client;
i2c_set_clientdata(client, rx8025);
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 7cc8f73a3fe8..ffb860d18701 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -302,6 +302,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct s3c_rtc *info = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
unsigned int alrm_en;
+ int year = tm->tm_year - 100;
dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
@@ -328,6 +329,21 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
}
+ if (year < 100 && year >= 0) {
+ alrm_en |= S3C2410_RTCALM_YEAREN;
+ writeb(bin2bcd(year), info->base + S3C2410_ALMYEAR);
+ }
+
+ if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
+ alrm_en |= S3C2410_RTCALM_MONEN;
+ writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
+ }
+
+ if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
+ alrm_en |= S3C2410_RTCALM_DAYEN;
+ writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE);
+ }
+
dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
writeb(alrm_en, info->base + S3C2410_RTCALM);
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index eb09eddf39b8..ca54d039da31 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -32,8 +32,6 @@
#include <linux/stmp3xxx_rtc_wdt.h>
#define STMP3XXX_RTC_CTRL 0x0
-#define STMP3XXX_RTC_CTRL_SET 0x4
-#define STMP3XXX_RTC_CTRL_CLR 0x8
#define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001
#define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002
#define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004
@@ -52,8 +50,6 @@
#define STMP3XXX_RTC_WATCHDOG 0x50
#define STMP3XXX_RTC_PERSISTENT0 0x60
-#define STMP3XXX_RTC_PERSISTENT0_SET 0x64
-#define STMP3XXX_RTC_PERSISTENT0_CLR 0x68
#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0)
#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN (1 << 1)
#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN (1 << 2)
@@ -179,7 +175,7 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
- rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
return IRQ_HANDLED;
}
@@ -194,15 +190,17 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
if (enabled) {
writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
- rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+ STMP_OFFSET_REG_SET);
writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
- rtc_data->io + STMP3XXX_RTC_CTRL_SET);
+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
} else {
writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
- rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+ STMP_OFFSET_REG_CLR);
writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
- rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
}
return 0;
}
@@ -245,7 +243,7 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
return 0;
writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
- rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
return 0;
}
@@ -334,16 +332,17 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
}
- writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+ writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+ STMP_OFFSET_REG_SET);
writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr,
- rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
- rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
rtc_data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&stmp3xxx_rtc_ops, THIS_MODULE);
@@ -376,7 +375,7 @@ static int stmp3xxx_rtc_resume(struct device *dev)
writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
- rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+ rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
return 0;
}
#endif
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index f73d2f579a7e..a263c10359e1 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -3030,6 +3030,7 @@ static void dasd_setup_queue(struct dasd_block *block)
} else {
max = block->base->discipline->max_blocks << block->s2b_shift;
}
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue);
blk_queue_logical_block_size(block->request_queue,
block->bp_block);
blk_queue_max_hw_sectors(block->request_queue, max);
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index fe07f3139bf6..184b1dbeb554 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -824,8 +824,11 @@ static void flush_all_alias_devices_on_lcu(struct alias_lcu *lcu)
* were waiting for the flush
*/
if (device == list_first_entry(&active,
- struct dasd_device, alias_list))
+ struct dasd_device, alias_list)) {
list_move(&device->alias_list, &lcu->active_devices);
+ private = (struct dasd_eckd_private *) device->private;
+ private->pavgroup = NULL;
+ }
}
spin_unlock_irqrestore(&lcu->lock, flags);
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index c062f1620c58..cb61f300f8b5 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -21,6 +21,7 @@
#include <asm/dasd.h>
#include <asm/debug.h>
+#include <asm/diag.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -76,6 +77,7 @@ static inline int dia250(void *iob, int cmd)
int rc;
rc = 3;
+ diag_stat_inc(DIAG_STAT_X250);
asm volatile(
" diag 2,%2,0x250\n"
"0: ipm %0\n"
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 62a323539226..9083247f55a8 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1032,6 +1032,21 @@ static unsigned char dasd_eckd_path_access(void *conf_data, int conf_len)
return 0;
}
+static void dasd_eckd_clear_conf_data(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private;
+ int i;
+
+ private = (struct dasd_eckd_private *) device->private;
+ private->conf_data = NULL;
+ private->conf_len = 0;
+ for (i = 0; i < 8; i++) {
+ kfree(private->path_conf_data[i]);
+ private->path_conf_data[i] = NULL;
+ }
+}
+
+
static int dasd_eckd_read_conf(struct dasd_device *device)
{
void *conf_data;
@@ -1068,20 +1083,10 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
path_data->opm |= lpm;
continue; /* no error */
}
- /* translate path mask to position in mask */
- pos = 8 - ffs(lpm);
- kfree(private->path_conf_data[pos]);
- if ((__u8 *)private->path_conf_data[pos] ==
- private->conf_data) {
- private->conf_data = NULL;
- private->conf_len = 0;
- conf_data_saved = 0;
- }
- private->path_conf_data[pos] =
- (struct dasd_conf_data *) conf_data;
/* save first valid configuration data */
if (!conf_data_saved) {
- kfree(private->conf_data);
+ /* initially clear previously stored conf_data */
+ dasd_eckd_clear_conf_data(device);
private->conf_data = conf_data;
private->conf_len = conf_len;
if (dasd_eckd_identify_conf_parts(private)) {
@@ -1090,6 +1095,10 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
kfree(conf_data);
continue;
}
+ pos = pathmask_to_pos(lpm);
+ /* store per path conf_data */
+ private->path_conf_data[pos] =
+ (struct dasd_conf_data *) conf_data;
/*
* build device UID that other path data
* can be compared to it
@@ -1147,7 +1156,10 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
path_data->cablepm |= lpm;
continue;
}
-
+ pos = pathmask_to_pos(lpm);
+ /* store per path conf_data */
+ private->path_conf_data[pos] =
+ (struct dasd_conf_data *) conf_data;
path_private.conf_data = NULL;
path_private.conf_len = 0;
}
@@ -1159,7 +1171,12 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
path_data->ppm |= lpm;
break;
}
- path_data->opm |= lpm;
+ if (!path_data->opm) {
+ path_data->opm = lpm;
+ dasd_generic_path_operational(device);
+ } else {
+ path_data->opm |= lpm;
+ }
/*
* if the path is used
* it should not be in one of the negative lists
@@ -4423,7 +4440,12 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
private = (struct dasd_eckd_private *) device->private;
/* Read Configuration Data */
- dasd_eckd_read_conf(device);
+ rc = dasd_eckd_read_conf(device);
+ if (rc) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+ "Read configuration data failed, rc=%d", rc);
+ goto out_err;
+ }
dasd_eckd_get_uid(device, &temp_uid);
/* Generate device unique id */
@@ -4439,13 +4461,18 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
/* register lcu with alias handling, enable PAV if this is a new lcu */
rc = dasd_alias_make_device_known_to_lcu(device);
if (rc)
- return rc;
+ goto out_err;
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr_flags);
dasd_eckd_validate_server(device, cqr_flags);
/* RE-Read Configuration Data */
- dasd_eckd_read_conf(device);
+ rc = dasd_eckd_read_conf(device);
+ if (rc) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+ "Read configuration data failed, rc=%d", rc);
+ goto out_err2;
+ }
/* Read Feature Codes */
dasd_eckd_read_features(device);
@@ -4456,7 +4483,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
if (rc) {
DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
"Read device characteristic failed, rc=%d", rc);
- goto out_err;
+ goto out_err2;
}
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
memcpy(&private->rdc_data, &temp_rdc_data, sizeof(temp_rdc_data));
@@ -4467,6 +4494,8 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
return 0;
+out_err2:
+ dasd_alias_disconnect_device_from_lcu(device);
out_err:
return -1;
}
@@ -4671,7 +4700,7 @@ static struct dasd_conf_data *dasd_eckd_get_ref_conf(struct dasd_device *device,
return conf_data;
}
out:
- return private->path_conf_data[8 - ffs(lpum)];
+ return private->path_conf_data[pathmask_to_pos(lpum)];
}
/*
@@ -4716,7 +4745,7 @@ static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
for (path = 0x80; path; path >>= 1) {
/* initialise data per path */
bitmask = mask;
- pos = 8 - ffs(path);
+ pos = pathmask_to_pos(path);
conf_data = private->path_conf_data[pos];
pos = 8 - ffs(cuir->ned_map);
ned = (char *) &conf_data->neds[pos];
@@ -4937,9 +4966,7 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
((u64 *)cuir)[0], ((u64 *)cuir)[1], ((u64 *)cuir)[2],
((u32 *)cuir)[3]);
ccw_device_get_schid(device->cdev, &sch_id);
- /* get position of path in mask */
- pos = 8 - ffs(lpum);
- /* get channel path descriptor from this position */
+ pos = pathmask_to_pos(lpum);
desc = ccw_device_get_chp_desc(device->cdev, pos);
if (cuir->code == CUIR_QUIESCE) {
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 5ed44fe21380..94a8f4ab57bc 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -27,7 +27,8 @@
static int dcssblk_open(struct block_device *bdev, fmode_t mode);
static void dcssblk_release(struct gendisk *disk, fmode_t mode);
-static void dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static blk_qc_t dcssblk_make_request(struct request_queue *q,
+ struct bio *bio);
static long dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
void __pmem **kaddr, unsigned long *pfn);
@@ -815,7 +816,7 @@ dcssblk_release(struct gendisk *disk, fmode_t mode)
up_write(&dcssblk_devices_sem);
}
-static void
+static blk_qc_t
dcssblk_make_request(struct request_queue *q, struct bio *bio)
{
struct dcssblk_dev_info *dev_info;
@@ -874,9 +875,10 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
bytes_done += bvec.bv_len;
}
bio_endio(bio);
- return;
+ return BLK_QC_T_NONE;
fail:
bio_io_error(bio);
+ return BLK_QC_T_NONE;
}
static long
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 02871f1db562..288f59a4147b 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -181,7 +181,7 @@ static unsigned long xpram_highest_page_index(void)
/*
* Block device make request function.
*/
-static void xpram_make_request(struct request_queue *q, struct bio *bio)
+static blk_qc_t xpram_make_request(struct request_queue *q, struct bio *bio)
{
xpram_device_t *xdev = bio->bi_bdev->bd_disk->private_data;
struct bio_vec bvec;
@@ -223,9 +223,10 @@ static void xpram_make_request(struct request_queue *q, struct bio *bio)
}
}
bio_endio(bio);
- return;
+ return BLK_QC_T_NONE;
fail:
bio_io_error(bio);
+ return BLK_QC_T_NONE;
}
static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c
index 12db8db04cdd..a5ccbf6f0d36 100644
--- a/drivers/s390/char/diag_ftp.c
+++ b/drivers/s390/char/diag_ftp.c
@@ -15,6 +15,7 @@
#include <linux/wait.h>
#include <linux/string.h>
#include <asm/ctl_reg.h>
+#include <asm/diag.h>
#include "hmcdrv_ftp.h"
#include "diag_ftp.h"
@@ -102,6 +103,7 @@ static int diag_ftp_2c4(struct diag_ftp_ldfpl *fpl,
{
int rc;
+ diag_stat_inc(DIAG_STAT_X2C4);
asm volatile(
" diag %[addr],%[cmd],0x2c4\n"
"0: j 2f\n"
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index b7d60306b0bc..fc94bfdceb95 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -229,7 +229,7 @@ static struct mon_msg *mon_next_message(struct mon_private *monpriv)
/******************************************************************************
* IUCV handler *
*****************************************************************************/
-static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
+static void mon_iucv_path_complete(struct iucv_path *path, u8 *ipuser)
{
struct mon_private *monpriv = path->private;
@@ -237,7 +237,7 @@ static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
wake_up(&mon_conn_wait_queue);
}
-static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
+static void mon_iucv_path_severed(struct iucv_path *path, u8 *ipuser)
{
struct mon_private *monpriv = path->private;
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 35a84af875ee..6010cd347a08 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -47,9 +47,9 @@ struct sclp_buffer *
sclp_make_buffer(void *page, unsigned short columns, unsigned short htab)
{
struct sclp_buffer *buffer;
- struct write_sccb *sccb;
+ struct sccb_header *sccb;
- sccb = (struct write_sccb *) page;
+ sccb = (struct sccb_header *) page;
/*
* We keep the struct sclp_buffer structure at the end
* of the sccb page.
@@ -57,24 +57,16 @@ sclp_make_buffer(void *page, unsigned short columns, unsigned short htab)
buffer = ((struct sclp_buffer *) ((addr_t) sccb + PAGE_SIZE)) - 1;
buffer->sccb = sccb;
buffer->retry_count = 0;
- buffer->mto_number = 0;
- buffer->mto_char_sum = 0;
+ buffer->messages = 0;
+ buffer->char_sum = 0;
buffer->current_line = NULL;
buffer->current_length = 0;
buffer->columns = columns;
buffer->htab = htab;
/* initialize sccb */
- memset(sccb, 0, sizeof(struct write_sccb));
- sccb->header.length = sizeof(struct write_sccb);
- sccb->msg_buf.header.length = sizeof(struct msg_buf);
- sccb->msg_buf.header.type = EVTYP_MSG;
- sccb->msg_buf.mdb.header.length = sizeof(struct mdb);
- sccb->msg_buf.mdb.header.type = 1;
- sccb->msg_buf.mdb.header.tag = 0xD4C4C240; /* ebcdic "MDB " */
- sccb->msg_buf.mdb.header.revision_code = 1;
- sccb->msg_buf.mdb.go.length = sizeof(struct go);
- sccb->msg_buf.mdb.go.type = 1;
+ memset(sccb, 0, sizeof(struct sccb_header));
+ sccb->length = sizeof(struct sccb_header);
return buffer;
}
@@ -90,37 +82,49 @@ sclp_unmake_buffer(struct sclp_buffer *buffer)
}
/*
- * Initialize a new Message Text Object (MTO) at the end of the provided buffer
- * with enough room for max_len characters. Return 0 on success.
+ * Initialize a new message the end of the provided buffer with
+ * enough room for max_len characters. Return 0 on success.
*/
static int
sclp_initialize_mto(struct sclp_buffer *buffer, int max_len)
{
- struct write_sccb *sccb;
+ struct sccb_header *sccb;
+ struct msg_buf *msg;
+ struct mdb *mdb;
+ struct go *go;
struct mto *mto;
- int mto_size;
+ int msg_size;
- /* max size of new Message Text Object including message text */
- mto_size = sizeof(struct mto) + max_len;
+ /* max size of new message including message text */
+ msg_size = sizeof(struct msg_buf) + max_len;
/* check if current buffer sccb can contain the mto */
sccb = buffer->sccb;
- if ((MAX_SCCB_ROOM - sccb->header.length) < mto_size)
+ if ((MAX_SCCB_ROOM - sccb->length) < msg_size)
return -ENOMEM;
- /* find address of new message text object */
- mto = (struct mto *)(((addr_t) sccb) + sccb->header.length);
+ msg = (struct msg_buf *)((addr_t) sccb + sccb->length);
+ memset(msg, 0, sizeof(struct msg_buf));
+ msg->header.length = sizeof(struct msg_buf);
+ msg->header.type = EVTYP_MSG;
- /*
- * fill the new Message-Text Object,
- * starting behind the former last byte of the SCCB
- */
- memset(mto, 0, sizeof(struct mto));
+ mdb = &msg->mdb;
+ mdb->header.length = sizeof(struct mdb);
+ mdb->header.type = 1;
+ mdb->header.tag = 0xD4C4C240; /* ebcdic "MDB " */
+ mdb->header.revision_code = 1;
+
+ go = &mdb->go;
+ go->length = sizeof(struct go);
+ go->type = 1;
+
+ mto = &mdb->mto;
mto->length = sizeof(struct mto);
mto->type = 4; /* message text object */
mto->line_type_flags = LNTPFLGS_ENDTEXT; /* end text */
/* set pointer to first byte after struct mto. */
+ buffer->current_msg = msg;
buffer->current_line = (char *) (mto + 1);
buffer->current_length = 0;
@@ -128,45 +132,37 @@ sclp_initialize_mto(struct sclp_buffer *buffer, int max_len)
}
/*
- * Finalize MTO initialized by sclp_initialize_mto(), updating the sizes of
- * MTO, enclosing MDB, event buffer and SCCB.
+ * Finalize message initialized by sclp_initialize_mto(),
+ * updating the sizes of MTO, enclosing MDB, event buffer and SCCB.
*/
static void
sclp_finalize_mto(struct sclp_buffer *buffer)
{
- struct write_sccb *sccb;
- struct mto *mto;
- int str_len, mto_size;
-
- str_len = buffer->current_length;
- buffer->current_line = NULL;
- buffer->current_length = 0;
-
- /* real size of new Message Text Object including message text */
- mto_size = sizeof(struct mto) + str_len;
-
- /* find address of new message text object */
- sccb = buffer->sccb;
- mto = (struct mto *)(((addr_t) sccb) + sccb->header.length);
-
- /* set size of message text object */
- mto->length = mto_size;
+ struct sccb_header *sccb;
+ struct msg_buf *msg;
/*
* update values of sizes
* (SCCB, Event(Message) Buffer, Message Data Block)
*/
- sccb->header.length += mto_size;
- sccb->msg_buf.header.length += mto_size;
- sccb->msg_buf.mdb.header.length += mto_size;
+ sccb = buffer->sccb;
+ msg = buffer->current_msg;
+ msg->header.length += buffer->current_length;
+ msg->mdb.header.length += buffer->current_length;
+ msg->mdb.mto.length += buffer->current_length;
+ sccb->length += msg->header.length;
/*
* count number of buffered messages (= number of Message Text
* Objects) and number of buffered characters
* for the SCCB currently used for buffering and at all
*/
- buffer->mto_number++;
- buffer->mto_char_sum += str_len;
+ buffer->messages++;
+ buffer->char_sum += buffer->current_length;
+
+ buffer->current_line = NULL;
+ buffer->current_length = 0;
+ buffer->current_msg = NULL;
}
/*
@@ -218,7 +214,13 @@ sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count)
break;
case '\a': /* bell, one for several times */
/* set SCLP sound alarm bit in General Object */
- buffer->sccb->msg_buf.mdb.go.general_msg_flags |=
+ if (buffer->current_line == NULL) {
+ rc = sclp_initialize_mto(buffer,
+ buffer->columns);
+ if (rc)
+ return i_msg;
+ }
+ buffer->current_msg->mdb.go.general_msg_flags |=
GNRLMSGFLGS_SNDALRM;
break;
case '\t': /* horizontal tabulator */
@@ -309,11 +311,13 @@ sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count)
int
sclp_buffer_space(struct sclp_buffer *buffer)
{
+ struct sccb_header *sccb;
int count;
- count = MAX_SCCB_ROOM - buffer->sccb->header.length;
+ sccb = buffer->sccb;
+ count = MAX_SCCB_ROOM - sccb->length;
if (buffer->current_line != NULL)
- count -= sizeof(struct mto) + buffer->current_length;
+ count -= sizeof(struct msg_buf) + buffer->current_length;
return count;
}
@@ -325,7 +329,7 @@ sclp_chars_in_buffer(struct sclp_buffer *buffer)
{
int count;
- count = buffer->mto_char_sum;
+ count = buffer->char_sum;
if (buffer->current_line != NULL)
count += buffer->current_length;
return count;
@@ -378,7 +382,7 @@ sclp_writedata_callback(struct sclp_req *request, void *data)
{
int rc;
struct sclp_buffer *buffer;
- struct write_sccb *sccb;
+ struct sccb_header *sccb;
buffer = (struct sclp_buffer *) data;
sccb = buffer->sccb;
@@ -389,7 +393,7 @@ sclp_writedata_callback(struct sclp_req *request, void *data)
return;
}
/* check SCLP response code and choose suitable action */
- switch (sccb->header.response_code) {
+ switch (sccb->response_code) {
case 0x0020 :
/* Normal completion, buffer processed, message(s) sent */
rc = 0;
@@ -403,7 +407,7 @@ sclp_writedata_callback(struct sclp_req *request, void *data)
/* remove processed buffers and requeue rest */
if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
/* not all buffers were processed */
- sccb->header.response_code = 0x0000;
+ sccb->response_code = 0x0000;
buffer->request.status = SCLP_REQ_FILLED;
rc = sclp_add_request(request);
if (rc == 0)
@@ -419,14 +423,14 @@ sclp_writedata_callback(struct sclp_req *request, void *data)
break;
}
/* retry request */
- sccb->header.response_code = 0x0000;
+ sccb->response_code = 0x0000;
buffer->request.status = SCLP_REQ_FILLED;
rc = sclp_add_request(request);
if (rc == 0)
return;
break;
default:
- if (sccb->header.response_code == 0x71f0)
+ if (sccb->response_code == 0x71f0)
rc = -ENOMEM;
else
rc = -EINVAL;
@@ -445,25 +449,19 @@ int
sclp_emit_buffer(struct sclp_buffer *buffer,
void (*callback)(struct sclp_buffer *, int))
{
- struct write_sccb *sccb;
-
/* add current line if there is one */
if (buffer->current_line != NULL)
sclp_finalize_mto(buffer);
/* Are there messages in the output buffer ? */
- if (buffer->mto_number == 0)
+ if (buffer->messages == 0)
return -EIO;
- sccb = buffer->sccb;
- /* Use normal write message */
- sccb->msg_buf.header.type = EVTYP_MSG;
-
buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
buffer->request.status = SCLP_REQ_FILLED;
buffer->request.callback = sclp_writedata_callback;
buffer->request.callback_data = buffer;
- buffer->request.sccb = sccb;
+ buffer->request.sccb = buffer->sccb;
buffer->callback = callback;
return sclp_add_request(&buffer->request);
}
diff --git a/drivers/s390/char/sclp_rw.h b/drivers/s390/char/sclp_rw.h
index 7a7bfc947d97..e3b0290995ba 100644
--- a/drivers/s390/char/sclp_rw.h
+++ b/drivers/s390/char/sclp_rw.h
@@ -45,6 +45,7 @@ struct mdb_header {
struct mdb {
struct mdb_header header;
struct go go;
+ struct mto mto;
} __attribute__((packed));
struct msg_buf {
@@ -52,14 +53,9 @@ struct msg_buf {
struct mdb mdb;
} __attribute__((packed));
-struct write_sccb {
- struct sccb_header header;
- struct msg_buf msg_buf;
-} __attribute__((packed));
-
/* The number of empty mto buffers that can be contained in a single sccb. */
-#define NR_EMPTY_MTO_PER_SCCB ((PAGE_SIZE - sizeof(struct sclp_buffer) - \
- sizeof(struct write_sccb)) / sizeof(struct mto))
+#define NR_EMPTY_MSG_PER_SCCB ((PAGE_SIZE - sizeof(struct sclp_buffer) - \
+ sizeof(struct sccb_header)) / sizeof(struct msg_buf))
/*
* data structure for information about list of SCCBs (only for writing),
@@ -68,7 +64,8 @@ struct write_sccb {
struct sclp_buffer {
struct list_head list; /* list_head for sccb_info chain */
struct sclp_req request;
- struct write_sccb *sccb;
+ void *sccb;
+ struct msg_buf *current_msg;
char *current_line;
int current_length;
int retry_count;
@@ -76,8 +73,8 @@ struct sclp_buffer {
unsigned short columns;
unsigned short htab;
/* statistics about this buffer */
- unsigned int mto_char_sum; /* # chars in sccb */
- unsigned int mto_number; /* # mtos in sccb */
+ unsigned int char_sum; /* # chars in sccb */
+ unsigned int messages; /* # messages in sccb */
/* Callback that is called after reaching final status. */
void (*callback)(struct sclp_buffer *, int);
};
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 003663288e29..3c6e174e19b6 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -84,8 +84,8 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp)
* to change as output buffers get emptied, or if the output flow
* control is acted. This is not an exact number because not every
* character needs the same space in the sccb. The worst case is
- * a string of newlines. Every newlines creates a new mto which
- * needs 8 bytes.
+ * a string of newlines. Every newline creates a new message which
+ * needs 82 bytes.
*/
static int
sclp_tty_write_room (struct tty_struct *tty)
@@ -97,9 +97,9 @@ sclp_tty_write_room (struct tty_struct *tty)
spin_lock_irqsave(&sclp_tty_lock, flags);
count = 0;
if (sclp_ttybuf != NULL)
- count = sclp_buffer_space(sclp_ttybuf) / sizeof(struct mto);
+ count = sclp_buffer_space(sclp_ttybuf) / sizeof(struct msg_buf);
list_for_each(l, &sclp_tty_pages)
- count += NR_EMPTY_MTO_PER_SCCB;
+ count += NR_EMPTY_MSG_PER_SCCB;
spin_unlock_irqrestore(&sclp_tty_lock, flags);
return count;
}
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 9bb48d70957c..799c1524c779 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -99,8 +99,8 @@ static const struct file_operations vmlogrdr_fops = {
};
-static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]);
-static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 *ipuser);
+static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 *ipuser);
static void vmlogrdr_iucv_message_pending(struct iucv_path *,
struct iucv_message *);
@@ -160,7 +160,7 @@ static struct cdev *vmlogrdr_cdev = NULL;
static int recording_class_AB;
-static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
+static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 *ipuser)
{
struct vmlogrdr_priv_t * logptr = path->private;
@@ -171,7 +171,7 @@ static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
}
-static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
+static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 *ipuser)
{
struct vmlogrdr_priv_t * logptr = path->private;
u8 reason = (u8) ipuser[8];
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 548a18916a31..a831d18596a5 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1080,28 +1080,10 @@ void __init chsc_init_cleanup(void)
free_page((unsigned long)sei_page);
}
-int chsc_enable_facility(int operation_code)
+int __chsc_enable_facility(struct chsc_sda_area *sda_area, int operation_code)
{
- unsigned long flags;
int ret;
- struct {
- struct chsc_header request;
- u8 reserved1:4;
- u8 format:4;
- u8 reserved2;
- u16 operation_code;
- u32 reserved3;
- u32 reserved4;
- u32 operation_data_area[252];
- struct chsc_header response;
- u32 reserved5:4;
- u32 format2:4;
- u32 reserved6:24;
- } __attribute__ ((packed)) *sda_area;
- spin_lock_irqsave(&chsc_page_lock, flags);
- memset(chsc_page, 0, PAGE_SIZE);
- sda_area = chsc_page;
sda_area->request.length = 0x0400;
sda_area->request.code = 0x0031;
sda_area->operation_code = operation_code;
@@ -1119,10 +1101,25 @@ int chsc_enable_facility(int operation_code)
default:
ret = chsc_error_from_response(sda_area->response.code);
}
+out:
+ return ret;
+}
+
+int chsc_enable_facility(int operation_code)
+{
+ struct chsc_sda_area *sda_area;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&chsc_page_lock, flags);
+ memset(chsc_page, 0, PAGE_SIZE);
+ sda_area = chsc_page;
+
+ ret = __chsc_enable_facility(sda_area, operation_code);
if (ret != 0)
CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
operation_code, sda_area->response.code);
-out:
+
spin_unlock_irqrestore(&chsc_page_lock, flags);
return ret;
}
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 76c9b50700b2..0de134c3a204 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -115,6 +115,20 @@ struct chsc_scpd {
u8 data[PAGE_SIZE - 20];
} __attribute__ ((packed));
+struct chsc_sda_area {
+ struct chsc_header request;
+ u8 :4;
+ u8 format:4;
+ u8 :8;
+ u16 operation_code;
+ u32 :32;
+ u32 :32;
+ u32 operation_data_area[252];
+ struct chsc_header response;
+ u32 :4;
+ u32 format2:4;
+ u32 :24;
+} __packed __aligned(PAGE_SIZE);
extern int chsc_get_ssd_info(struct subchannel_id schid,
struct chsc_ssd_info *ssd);
@@ -122,6 +136,7 @@ extern int chsc_determine_css_characteristics(void);
extern int chsc_init(void);
extern void chsc_init_cleanup(void);
+int __chsc_enable_facility(struct chsc_sda_area *sda_area, int operation_code);
extern int chsc_enable_facility(int);
struct channel_subsystem;
extern int chsc_secm(struct channel_subsystem *, int);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 07fc5d9e7f10..690b8547e828 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -476,26 +476,6 @@ static int cio_check_devno_blacklisted(struct subchannel *sch)
return 0;
}
-static int cio_validate_io_subchannel(struct subchannel *sch)
-{
- /* Initialization for io subchannels. */
- if (!css_sch_is_valid(&sch->schib))
- return -ENODEV;
-
- /* Devno is valid. */
- return cio_check_devno_blacklisted(sch);
-}
-
-static int cio_validate_msg_subchannel(struct subchannel *sch)
-{
- /* Initialization for message subchannels. */
- if (!css_sch_is_valid(&sch->schib))
- return -ENODEV;
-
- /* Devno is valid. */
- return cio_check_devno_blacklisted(sch);
-}
-
/**
* cio_validate_subchannel - basic validation of subchannel
* @sch: subchannel structure to be filled out
@@ -533,10 +513,11 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
switch (sch->st) {
case SUBCHANNEL_TYPE_IO:
- err = cio_validate_io_subchannel(sch);
- break;
case SUBCHANNEL_TYPE_MSG:
- err = cio_validate_msg_subchannel(sch);
+ if (!css_sch_is_valid(&sch->schib))
+ err = -ENODEV;
+ else
+ err = cio_check_devno_blacklisted(sch);
break;
default:
err = 0;
@@ -826,11 +807,11 @@ static atomic_t chpid_reset_count;
static void s390_reset_chpids_mcck_handler(void)
{
struct crw crw;
- struct mci *mci;
+ union mci mci;
/* Check for pending channel report word. */
- mci = (struct mci *)&S390_lowcore.mcck_interruption_code;
- if (!mci->cp)
+ mci.val = S390_lowcore.mcck_interruption_code;
+ if (!mci.cp)
return;
/* Process channel report words. */
while (stcrw(&crw) == 0) {
@@ -944,18 +925,32 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
{
+ static struct chsc_sda_area sda_area __initdata;
struct subchannel_id schid;
struct schib schib;
schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id;
if (!schid.one)
return -ENODEV;
+
+ if (schid.ssid) {
+ /*
+ * Firmware should have already enabled MSS but whoever started
+ * the kernel might have initiated a channel subsystem reset.
+ * Ensure that MSS is enabled.
+ */
+ memset(&sda_area, 0, sizeof(sda_area));
+ if (__chsc_enable_facility(&sda_area, CHSC_SDA_OC_MSS))
+ return -ENODEV;
+ }
if (stsch_err(schid, &schib))
return -ENODEV;
if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
return -ENODEV;
if (!schib.pmcw.dnv)
return -ENODEV;
+
+ iplinfo->ssid = schid.ssid;
iplinfo->devno = schib.pmcw.dev;
iplinfo->is_qdio = schib.pmcw.qf;
return 0;
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 23054f8fa9fc..b2afad5a5682 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -113,7 +113,6 @@ module_param(format, bint, 0444);
* @readall: read a measurement block in a common format
* @reset: clear the data in the associated measurement block and
* reset its time stamp
- * @align: align an allocated block so that the hardware can use it
*/
struct cmb_operations {
int (*alloc) (struct ccw_device *);
@@ -122,7 +121,6 @@ struct cmb_operations {
u64 (*read) (struct ccw_device *, int);
int (*readall)(struct ccw_device *, struct cmbdata *);
void (*reset) (struct ccw_device *);
- void *(*align) (void *);
/* private: */
struct attribute_group *attr_group;
};
@@ -186,9 +184,8 @@ static inline void cmf_activate(void *area, unsigned int onoff)
static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
unsigned long address)
{
- struct subchannel *sch;
-
- sch = to_subchannel(cdev->dev.parent);
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+ int ret;
sch->config.mme = mme;
sch->config.mbfc = mbfc;
@@ -198,7 +195,15 @@ static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
else
sch->config.mbi = address;
- return cio_commit_config(sch);
+ ret = cio_commit_config(sch);
+ if (!mme && ret == -ENODEV) {
+ /*
+ * The task was to disable measurement block updates but
+ * the subchannel is already gone. Report success.
+ */
+ ret = 0;
+ }
+ return ret;
}
struct set_schib_struct {
@@ -314,7 +319,7 @@ static int cmf_copy_block(struct ccw_device *cdev)
return -EBUSY;
}
cmb_data = cdev->private->cmb;
- hw_block = cmbops->align(cmb_data->hw_block);
+ hw_block = cmb_data->hw_block;
if (!memcmp(cmb_data->last_block, hw_block, cmb_data->size))
/* No need to copy. */
return 0;
@@ -425,7 +430,7 @@ static void cmf_generic_reset(struct ccw_device *cdev)
* Need to reset hw block as well to make the hardware start
* from 0 again.
*/
- memset(cmbops->align(cmb_data->hw_block), 0, cmb_data->size);
+ memset(cmb_data->hw_block, 0, cmb_data->size);
cmb_data->last_update = 0;
}
cdev->private->cmb_start_time = get_tod_clock();
@@ -606,12 +611,6 @@ static void free_cmb(struct ccw_device *cdev)
spin_lock_irq(cdev->ccwlock);
priv = cdev->private;
-
- if (list_empty(&priv->cmb_list)) {
- /* already freed */
- goto out;
- }
-
cmb_data = priv->cmb;
priv->cmb = NULL;
if (cmb_data)
@@ -626,7 +625,6 @@ static void free_cmb(struct ccw_device *cdev)
free_pages((unsigned long)cmb_area.mem, get_order(size));
cmb_area.mem = NULL;
}
-out:
spin_unlock_irq(cdev->ccwlock);
spin_unlock(&cmb_area.lock);
}
@@ -755,11 +753,6 @@ static void reset_cmb(struct ccw_device *cdev)
cmf_generic_reset(cdev);
}
-static void * align_cmb(void *area)
-{
- return area;
-}
-
static struct attribute_group cmf_attr_group;
static struct cmb_operations cmbops_basic = {
@@ -769,7 +762,6 @@ static struct cmb_operations cmbops_basic = {
.read = read_cmb,
.readall = readall_cmb,
.reset = reset_cmb,
- .align = align_cmb,
.attr_group = &cmf_attr_group,
};
@@ -804,64 +796,57 @@ struct cmbe {
u32 device_busy_time;
u32 initial_command_response_time;
u32 reserved[7];
-};
+} __packed __aligned(64);
-/*
- * kmalloc only guarantees 8 byte alignment, but we need cmbe
- * pointers to be naturally aligned. Make sure to allocate
- * enough space for two cmbes.
- */
-static inline struct cmbe *cmbe_align(struct cmbe *c)
-{
- unsigned long addr;
- addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) &
- ~(sizeof (struct cmbe) - sizeof(long));
- return (struct cmbe*)addr;
-}
+static struct kmem_cache *cmbe_cache;
static int alloc_cmbe(struct ccw_device *cdev)
{
- struct cmbe *cmbe;
struct cmb_data *cmb_data;
- int ret;
+ struct cmbe *cmbe;
+ int ret = -ENOMEM;
- cmbe = kzalloc (sizeof (*cmbe) * 2, GFP_KERNEL);
+ cmbe = kmem_cache_zalloc(cmbe_cache, GFP_KERNEL);
if (!cmbe)
- return -ENOMEM;
- cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL);
- if (!cmb_data) {
- ret = -ENOMEM;
+ return ret;
+
+ cmb_data = kzalloc(sizeof(*cmb_data), GFP_KERNEL);
+ if (!cmb_data)
goto out_free;
- }
+
cmb_data->last_block = kzalloc(sizeof(struct cmbe), GFP_KERNEL);
- if (!cmb_data->last_block) {
- ret = -ENOMEM;
+ if (!cmb_data->last_block)
goto out_free;
- }
- cmb_data->size = sizeof(struct cmbe);
- spin_lock_irq(cdev->ccwlock);
- if (cdev->private->cmb) {
- spin_unlock_irq(cdev->ccwlock);
- ret = -EBUSY;
- goto out_free;
- }
+
+ cmb_data->size = sizeof(*cmbe);
cmb_data->hw_block = cmbe;
+
+ spin_lock(&cmb_area.lock);
+ spin_lock_irq(cdev->ccwlock);
+ if (cdev->private->cmb)
+ goto out_unlock;
+
cdev->private->cmb = cmb_data;
- spin_unlock_irq(cdev->ccwlock);
/* activate global measurement if this is the first channel */
- spin_lock(&cmb_area.lock);
if (list_empty(&cmb_area.list))
cmf_activate(NULL, 1);
list_add_tail(&cdev->private->cmb_list, &cmb_area.list);
- spin_unlock(&cmb_area.lock);
+ spin_unlock_irq(cdev->ccwlock);
+ spin_unlock(&cmb_area.lock);
return 0;
+
+out_unlock:
+ spin_unlock_irq(cdev->ccwlock);
+ spin_unlock(&cmb_area.lock);
+ ret = -EBUSY;
out_free:
if (cmb_data)
kfree(cmb_data->last_block);
kfree(cmb_data);
- kfree(cmbe);
+ kmem_cache_free(cmbe_cache, cmbe);
+
return ret;
}
@@ -869,19 +854,21 @@ static void free_cmbe(struct ccw_device *cdev)
{
struct cmb_data *cmb_data;
+ spin_lock(&cmb_area.lock);
spin_lock_irq(cdev->ccwlock);
cmb_data = cdev->private->cmb;
cdev->private->cmb = NULL;
- if (cmb_data)
+ if (cmb_data) {
kfree(cmb_data->last_block);
+ kmem_cache_free(cmbe_cache, cmb_data->hw_block);
+ }
kfree(cmb_data);
- spin_unlock_irq(cdev->ccwlock);
/* deactivate global measurement if this is the last channel */
- spin_lock(&cmb_area.lock);
list_del_init(&cdev->private->cmb_list);
if (list_empty(&cmb_area.list))
cmf_activate(NULL, 0);
+ spin_unlock_irq(cdev->ccwlock);
spin_unlock(&cmb_area.lock);
}
@@ -897,7 +884,7 @@ static int set_cmbe(struct ccw_device *cdev, u32 mme)
return -EINVAL;
}
cmb_data = cdev->private->cmb;
- mba = mme ? (unsigned long) cmbe_align(cmb_data->hw_block) : 0;
+ mba = mme ? (unsigned long) cmb_data->hw_block : 0;
spin_unlock_irqrestore(cdev->ccwlock, flags);
return set_schib_wait(cdev, mme, 1, mba);
@@ -1022,11 +1009,6 @@ static void reset_cmbe(struct ccw_device *cdev)
cmf_generic_reset(cdev);
}
-static void * align_cmbe(void *area)
-{
- return cmbe_align(area);
-}
-
static struct attribute_group cmf_attr_group_ext;
static struct cmb_operations cmbops_extended = {
@@ -1036,7 +1018,6 @@ static struct cmb_operations cmbops_extended = {
.read = read_cmbe,
.readall = readall_cmbe,
.reset = reset_cmbe,
- .align = align_cmbe,
.attr_group = &cmf_attr_group_ext,
};
@@ -1171,23 +1152,28 @@ static ssize_t cmb_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0);
+ struct ccw_device *cdev = to_ccwdev(dev);
+ int enabled;
+
+ spin_lock_irq(cdev->ccwlock);
+ enabled = !!cdev->private->cmb;
+ spin_unlock_irq(cdev->ccwlock);
+
+ return sprintf(buf, "%d\n", enabled);
}
static ssize_t cmb_enable_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t c)
{
- struct ccw_device *cdev;
- int ret;
+ struct ccw_device *cdev = to_ccwdev(dev);
unsigned long val;
+ int ret;
ret = kstrtoul(buf, 16, &val);
if (ret)
return ret;
- cdev = to_ccwdev(dev);
-
switch (val) {
case 0:
ret = disable_cmf(cdev);
@@ -1195,12 +1181,13 @@ static ssize_t cmb_enable_store(struct device *dev,
case 1:
ret = enable_cmf(cdev);
break;
+ default:
+ ret = -EINVAL;
}
- return c;
+ return ret ? ret : c;
}
-
-DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store);
+DEVICE_ATTR_RW(cmb_enable);
int ccw_set_cmf(struct ccw_device *cdev, int enable)
{
@@ -1220,41 +1207,71 @@ int enable_cmf(struct ccw_device *cdev)
{
int ret;
+ device_lock(&cdev->dev);
+ get_device(&cdev->dev);
ret = cmbops->alloc(cdev);
- cmbops->reset(cdev);
if (ret)
- return ret;
+ goto out;
+ cmbops->reset(cdev);
+ ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
+ if (ret) {
+ cmbops->free(cdev);
+ goto out;
+ }
ret = cmbops->set(cdev, 2);
if (ret) {
+ sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group);
cmbops->free(cdev);
- return ret;
}
- ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
- if (!ret)
- return 0;
- cmbops->set(cdev, 0); //FIXME: this can fail
- cmbops->free(cdev);
+out:
+ if (ret)
+ put_device(&cdev->dev);
+
+ device_unlock(&cdev->dev);
return ret;
}
/**
- * disable_cmf() - switch off the channel measurement for a specific device
+ * __disable_cmf() - switch off the channel measurement for a specific device
* @cdev: The ccw device to be disabled
*
* Returns %0 for success or a negative error value.
*
* Context:
- * non-atomic
+ * non-atomic, device_lock() held.
*/
-int disable_cmf(struct ccw_device *cdev)
+int __disable_cmf(struct ccw_device *cdev)
{
int ret;
ret = cmbops->set(cdev, 0);
if (ret)
return ret;
- cmbops->free(cdev);
+
sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group);
+ cmbops->free(cdev);
+ put_device(&cdev->dev);
+
+ return ret;
+}
+
+/**
+ * disable_cmf() - switch off the channel measurement for a specific device
+ * @cdev: The ccw device to be disabled
+ *
+ * Returns %0 for success or a negative error value.
+ *
+ * Context:
+ * non-atomic
+ */
+int disable_cmf(struct ccw_device *cdev)
+{
+ int ret;
+
+ device_lock(&cdev->dev);
+ ret = __disable_cmf(cdev);
+ device_unlock(&cdev->dev);
+
return ret;
}
@@ -1295,10 +1312,32 @@ int cmf_reenable(struct ccw_device *cdev)
return cmbops->set(cdev, 2);
}
+/**
+ * cmf_reactivate() - reactivate measurement block updates
+ *
+ * Use this during resume from hibernate.
+ */
+void cmf_reactivate(void)
+{
+ spin_lock(&cmb_area.lock);
+ if (!list_empty(&cmb_area.list))
+ cmf_activate(cmb_area.mem, 1);
+ spin_unlock(&cmb_area.lock);
+}
+
+static int __init init_cmbe(void)
+{
+ cmbe_cache = kmem_cache_create("cmbe_cache", sizeof(struct cmbe),
+ __alignof__(struct cmbe), 0, NULL);
+
+ return cmbe_cache ? 0 : -ENOMEM;
+}
+
static int __init init_cmf(void)
{
char *format_string;
- char *detect_string = "parameter";
+ char *detect_string;
+ int ret;
/*
* If the user did not give a parameter, see if we are running on a
@@ -1324,15 +1363,18 @@ static int __init init_cmf(void)
case CMF_EXTENDED:
format_string = "extended";
cmbops = &cmbops_extended;
+
+ ret = init_cmbe();
+ if (ret)
+ return ret;
break;
default:
- return 1;
+ return -EINVAL;
}
pr_info("Channel measurement facility initialized using format "
"%s (mode %s)\n", format_string, detect_string);
return 0;
}
-
module_init(init_cmf);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 0268e5fd59b5..489e703dc82d 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -44,7 +44,6 @@ for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
int ret;
init_subchannel_id(&schid);
- ret = -ENODEV;
do {
do {
ret = fn(schid, data);
@@ -703,17 +702,12 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
css->global_pgid.pgid_high.ext_cssid.version = 0x80;
css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
} else {
-#ifdef CONFIG_SMP
css->global_pgid.pgid_high.cpu_addr = stap();
-#else
- css->global_pgid.pgid_high.cpu_addr = 0;
-#endif
}
get_cpu_id(&cpu_id);
css->global_pgid.cpu_id = cpu_id.ident;
css->global_pgid.cpu_model = cpu_id.machine;
css->global_pgid.tod_high = tod_high;
-
}
static void
@@ -1089,6 +1083,7 @@ void channel_subsystem_reinit(void)
if (chp)
chp_update_desc(chp);
}
+ cmf_reactivate();
}
#ifdef CONFIG_PROC_FS
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index dfef5e63cb7b..6aae68412802 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1787,6 +1787,8 @@ static int ccw_device_remove(struct device *dev)
cdev->drv = NULL;
cdev->private->int_class = IRQIO_CIO;
spin_unlock_irq(cdev->ccwlock);
+ __disable_cmf(cdev);
+
return 0;
}
@@ -1797,7 +1799,7 @@ static void ccw_device_shutdown(struct device *dev)
cdev = to_ccwdev(dev);
if (cdev->drv && cdev->drv->shutdown)
cdev->drv->shutdown(cdev);
- disable_cmf(cdev);
+ __disable_cmf(cdev);
}
static int ccw_device_pm_prepare(struct device *dev)
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 8d1d29873172..065b1be98e2c 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -125,11 +125,6 @@ void ccw_device_verify_done(struct ccw_device *, int);
void ccw_device_disband_start(struct ccw_device *);
void ccw_device_disband_done(struct ccw_device *, int);
-void ccw_device_stlck_start(struct ccw_device *, void *, void *, void *);
-void ccw_device_stlck_done(struct ccw_device *, void *, int);
-
-int ccw_device_call_handler(struct ccw_device *);
-
int ccw_device_stlck(struct ccw_device *);
/* Helper function for machine check handling. */
@@ -145,6 +140,7 @@ void ccw_device_set_timeout(struct ccw_device *, int);
void retry_set_schib(struct ccw_device *cdev);
void cmf_retry_copy_block(struct ccw_device *);
int cmf_reenable(struct ccw_device *);
+void cmf_reactivate(void);
int ccw_set_cmf(struct ccw_device *cdev, int enable);
extern struct device_attribute dev_attr_cmb_enable;
#endif
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 83da53c8e54c..92e03b42e661 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -731,6 +731,44 @@ static void ccw_device_boxed_verify(struct ccw_device *cdev,
}
/*
+ * Pass interrupt to device driver.
+ */
+static int ccw_device_call_handler(struct ccw_device *cdev)
+{
+ unsigned int stctl;
+ int ending_status;
+
+ /*
+ * we allow for the device action handler if .
+ * - we received ending status
+ * - the action handler requested to see all interrupts
+ * - we received an intermediate status
+ * - fast notification was requested (primary status)
+ * - unsolicited interrupts
+ */
+ stctl = scsw_stctl(&cdev->private->irb.scsw);
+ ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
+ (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
+ (stctl == SCSW_STCTL_STATUS_PEND);
+ if (!ending_status &&
+ !cdev->private->options.repall &&
+ !(stctl & SCSW_STCTL_INTER_STATUS) &&
+ !(cdev->private->options.fast &&
+ (stctl & SCSW_STCTL_PRIM_STATUS)))
+ return 0;
+
+ if (ending_status)
+ ccw_device_set_timeout(cdev, 0);
+
+ if (cdev->handler)
+ cdev->handler(cdev, cdev->private->intparm,
+ &cdev->private->irb);
+
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+ return 1;
+}
+
+/*
* Got an interrupt for a normal io (state online).
*/
static void
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 6acd0b577694..a69f702a2fcc 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -412,52 +412,6 @@ int ccw_device_resume(struct ccw_device *cdev)
return cio_resume(sch);
}
-/*
- * Pass interrupt to device driver.
- */
-int
-ccw_device_call_handler(struct ccw_device *cdev)
-{
- unsigned int stctl;
- int ending_status;
-
- /*
- * we allow for the device action handler if .
- * - we received ending status
- * - the action handler requested to see all interrupts
- * - we received an intermediate status
- * - fast notification was requested (primary status)
- * - unsolicited interrupts
- */
- stctl = scsw_stctl(&cdev->private->irb.scsw);
- ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
- (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
- (stctl == SCSW_STCTL_STATUS_PEND);
- if (!ending_status &&
- !cdev->private->options.repall &&
- !(stctl & SCSW_STCTL_INTER_STATUS) &&
- !(cdev->private->options.fast &&
- (stctl & SCSW_STCTL_PRIM_STATUS)))
- return 0;
-
- /* Clear pending timers for device driver initiated I/O. */
- if (ending_status)
- ccw_device_set_timeout(cdev, 0);
- /*
- * Now we are ready to call the device driver interrupt handler.
- */
- if (cdev->handler)
- cdev->handler(cdev, cdev->private->intparm,
- &cdev->private->irb);
-
- /*
- * Clear the old and now useless interrupt response block.
- */
- memset(&cdev->private->irb, 0, sizeof(struct irb));
-
- return 1;
-}
-
/**
* ccw_device_get_ciw() - Search for CIW command in extended sense data.
* @cdev: ccw device to inspect
@@ -502,67 +456,6 @@ __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
return sch->lpm;
}
-struct stlck_data {
- struct completion done;
- int rc;
-};
-
-void ccw_device_stlck_done(struct ccw_device *cdev, void *data, int rc)
-{
- struct stlck_data *sdata = data;
-
- sdata->rc = rc;
- complete(&sdata->done);
-}
-
-/*
- * Perform unconditional reserve + release.
- */
-int ccw_device_stlck(struct ccw_device *cdev)
-{
- struct subchannel *sch = to_subchannel(cdev->dev.parent);
- struct stlck_data data;
- u8 *buffer;
- int rc;
-
- /* Check if steal lock operation is valid for this device. */
- if (cdev->drv) {
- if (!cdev->private->options.force)
- return -EINVAL;
- }
- buffer = kzalloc(64, GFP_DMA | GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
- init_completion(&data.done);
- data.rc = -EIO;
- spin_lock_irq(sch->lock);
- rc = cio_enable_subchannel(sch, (u32) (addr_t) sch);
- if (rc)
- goto out_unlock;
- /* Perform operation. */
- cdev->private->state = DEV_STATE_STEAL_LOCK;
- ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
- spin_unlock_irq(sch->lock);
- /* Wait for operation to finish. */
- if (wait_for_completion_interruptible(&data.done)) {
- /* Got a signal. */
- spin_lock_irq(sch->lock);
- ccw_request_cancel(cdev);
- spin_unlock_irq(sch->lock);
- wait_for_completion(&data.done);
- }
- rc = data.rc;
- /* Check results. */
- spin_lock_irq(sch->lock);
- cio_disable_subchannel(sch);
- cdev->private->state = DEV_STATE_BOXED;
-out_unlock:
- spin_unlock_irq(sch->lock);
- kfree(buffer);
-
- return rc;
-}
-
/**
* chp_get_chp_desc - return newly allocated channel-path descriptor
* @cdev: device to obtain the descriptor for
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 37ada05e82a5..da246b67edfe 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -9,9 +9,10 @@
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/bitops.h>
+#include <linux/slab.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -133,7 +134,7 @@ static void spid_build_cp(struct ccw_device *cdev, u8 fn)
{
struct ccw_request *req = &cdev->private->req;
struct ccw1 *cp = cdev->private->iccws;
- int i = 8 - ffs(req->lpm);
+ int i = pathmask_to_pos(req->lpm);
struct pgid *pgid = &cdev->private->pgid[i];
pgid->inf.fc = fn;
@@ -434,7 +435,7 @@ static void snid_build_cp(struct ccw_device *cdev)
{
struct ccw_request *req = &cdev->private->req;
struct ccw1 *cp = cdev->private->iccws;
- int i = 8 - ffs(req->lpm);
+ int i = pathmask_to_pos(req->lpm);
/* Channel program setup. */
cp->cmd_code = CCW_CMD_SENSE_PGID;
@@ -616,6 +617,11 @@ void ccw_device_disband_start(struct ccw_device *cdev)
ccw_request_start(cdev);
}
+struct stlck_data {
+ struct completion done;
+ int rc;
+};
+
static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2)
{
struct ccw_request *req = &cdev->private->req;
@@ -634,7 +640,10 @@ static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2)
static void stlck_callback(struct ccw_device *cdev, void *data, int rc)
{
- ccw_device_stlck_done(cdev, data, rc);
+ struct stlck_data *sdata = data;
+
+ sdata->rc = rc;
+ complete(&sdata->done);
}
/**
@@ -645,11 +654,9 @@ static void stlck_callback(struct ccw_device *cdev, void *data, int rc)
* @buf2: data pointer used in channel program
*
* Execute a channel program on @cdev to release an existing PGID reservation.
- * When finished, call ccw_device_stlck_done with a return code specifying the
- * result.
*/
-void ccw_device_stlck_start(struct ccw_device *cdev, void *data, void *buf1,
- void *buf2)
+static void ccw_device_stlck_start(struct ccw_device *cdev, void *data,
+ void *buf1, void *buf2)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_request *req = &cdev->private->req;
@@ -667,3 +674,50 @@ void ccw_device_stlck_start(struct ccw_device *cdev, void *data, void *buf1,
ccw_request_start(cdev);
}
+/*
+ * Perform unconditional reserve + release.
+ */
+int ccw_device_stlck(struct ccw_device *cdev)
+{
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+ struct stlck_data data;
+ u8 *buffer;
+ int rc;
+
+ /* Check if steal lock operation is valid for this device. */
+ if (cdev->drv) {
+ if (!cdev->private->options.force)
+ return -EINVAL;
+ }
+ buffer = kzalloc(64, GFP_DMA | GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ init_completion(&data.done);
+ data.rc = -EIO;
+ spin_lock_irq(sch->lock);
+ rc = cio_enable_subchannel(sch, (u32) (addr_t) sch);
+ if (rc)
+ goto out_unlock;
+ /* Perform operation. */
+ cdev->private->state = DEV_STATE_STEAL_LOCK;
+ ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
+ spin_unlock_irq(sch->lock);
+ /* Wait for operation to finish. */
+ if (wait_for_completion_interruptible(&data.done)) {
+ /* Got a signal. */
+ spin_lock_irq(sch->lock);
+ ccw_request_cancel(cdev);
+ spin_unlock_irq(sch->lock);
+ wait_for_completion(&data.done);
+ }
+ rc = data.rc;
+ /* Check results. */
+ spin_lock_irq(sch->lock);
+ cio_disable_subchannel(sch);
+ cdev->private->state = DEV_STATE_BOXED;
+out_unlock:
+ spin_unlock_irq(sch->lock);
+ kfree(buffer);
+
+ return rc;
+}
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 848e3b64ea6e..4bb5262f7aee 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -319,6 +319,8 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
int retries = 0, cc;
unsigned long laob = 0;
+ WARN_ON_ONCE(aob && ((queue_type(q) != QDIO_IQDIO_QFMT) ||
+ !q->u.out.use_cq));
if (q->u.out.use_cq && aob != 0) {
fc = QDIO_SIGA_WRITEQ;
laob = aob;
@@ -329,8 +331,6 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
fc |= QDIO_SIGA_QEBSM_FLAG;
}
again:
- WARN_ON_ONCE((aob && queue_type(q) != QDIO_IQDIO_QFMT) ||
- (aob && fc != QDIO_SIGA_WRITEQ));
cc = do_siga_output(schid, q->mask, busy_bit, fc, laob);
/* hipersocket busy condition */
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile
index 771faf7094d6..b8ab18676e69 100644
--- a/drivers/s390/crypto/Makefile
+++ b/drivers/s390/crypto/Makefile
@@ -3,6 +3,9 @@
#
ap-objs := ap_bus.o
-obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o zcrypt_pcicc.o zcrypt_pcixcc.o
-obj-$(CONFIG_ZCRYPT) += zcrypt_pcica.o zcrypt_cex2a.o zcrypt_cex4.o
+# zcrypt_api depends on ap
+obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o
+# msgtype* depend on zcrypt_api
obj-$(CONFIG_ZCRYPT) += zcrypt_msgtype6.o zcrypt_msgtype50.o
+# adapter drivers depend on ap, zcrypt_api and msgtype*
+obj-$(CONFIG_ZCRYPT) += zcrypt_pcixcc.o zcrypt_cex2a.o zcrypt_cex4.o
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index d78b3d629d78..61f768518a34 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -37,6 +37,7 @@
#include <linux/notifier.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
+#include <linux/suspend.h>
#include <asm/reset.h>
#include <asm/airq.h>
#include <linux/atomic.h>
@@ -48,23 +49,6 @@
#include "ap_bus.h"
-/* Some prototypes. */
-static void ap_scan_bus(struct work_struct *);
-static void ap_poll_all(unsigned long);
-static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
-static int ap_poll_thread_start(void);
-static void ap_poll_thread_stop(void);
-static void ap_request_timeout(unsigned long);
-static inline void ap_schedule_poll_timer(void);
-static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
-static int ap_device_remove(struct device *dev);
-static int ap_device_probe(struct device *dev);
-static void ap_interrupt_handler(struct airq_struct *airq);
-static void ap_reset(struct ap_device *ap_dev, unsigned long *flags);
-static void ap_config_timeout(unsigned long ptr);
-static int ap_select_domain(void);
-static void ap_query_configuration(void);
-
/*
* Module description.
*/
@@ -90,19 +74,21 @@ static struct device *ap_root_device = NULL;
static struct ap_config_info *ap_configuration;
static DEFINE_SPINLOCK(ap_device_list_lock);
static LIST_HEAD(ap_device_list);
+static bool initialised;
/*
- * Workqueue & timer for bus rescan.
+ * Workqueue timer for bus rescan.
*/
-static struct workqueue_struct *ap_work_queue;
static struct timer_list ap_config_timer;
static int ap_config_time = AP_CONFIG_TIME;
-static DECLARE_WORK(ap_config_work, ap_scan_bus);
+static void ap_scan_bus(struct work_struct *);
+static DECLARE_WORK(ap_scan_work, ap_scan_bus);
/*
* Tasklet & timer for AP request polling and interrupts
*/
-static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
+static void ap_tasklet_fn(unsigned long);
+static DECLARE_TASKLET(ap_tasklet, ap_tasklet_fn, 0);
static atomic_t ap_poll_requests = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
static struct task_struct *ap_poll_kthread = NULL;
@@ -115,6 +101,8 @@ static unsigned long long poll_timeout = 250000;
/* Suspend flag */
static int ap_suspend_flag;
+/* Maximum domain id */
+static int ap_max_domain_id;
/* Flag to check if domain was set through module parameter domain=. This is
* important when supsend and resume is done in a z/VM environment where the
* domain might change. */
@@ -122,6 +110,8 @@ static int user_set_domain = 0;
static struct bus_type ap_bus_type;
/* Adapter interrupt definitions */
+static void ap_interrupt_handler(struct airq_struct *airq);
+
static int ap_airq_flag;
static struct airq_struct ap_airq = {
@@ -182,44 +172,27 @@ static int ap_configuration_available(void)
/**
* ap_test_queue(): Test adjunct processor queue.
* @qid: The AP queue number
- * @queue_depth: Pointer to queue depth value
- * @device_type: Pointer to device type value
+ * @info: Pointer to queue descriptor
*
* Returns AP queue status structure.
*/
static inline struct ap_queue_status
-ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ap_test_queue(ap_qid_t qid, unsigned long *info)
{
register unsigned long reg0 asm ("0") = qid;
register struct ap_queue_status reg1 asm ("1");
register unsigned long reg2 asm ("2") = 0UL;
+ if (test_facility(15))
+ reg0 |= 1UL << 23; /* set APFT T bit*/
asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
: "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
- *device_type = (int) (reg2 >> 24);
- *queue_depth = (int) (reg2 & 0xff);
+ if (info)
+ *info = reg2;
return reg1;
}
/**
- * ap_query_facilities(): PQAP(TAPQ) query facilities.
- * @qid: The AP queue number
- *
- * Returns content of general register 2 after the PQAP(TAPQ)
- * instruction was called.
- */
-static inline unsigned long ap_query_facilities(ap_qid_t qid)
-{
- register unsigned long reg0 asm ("0") = qid | 0x00800000UL;
- register unsigned long reg1 asm ("1");
- register unsigned long reg2 asm ("2") = 0UL;
-
- asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
- : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
- return reg2;
-}
-
-/**
* ap_reset_queue(): Reset adjunct processor queue.
* @qid: The AP queue number
*
@@ -259,31 +232,19 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
return reg1_out;
}
-static inline struct ap_queue_status
-__ap_query_functions(ap_qid_t qid, unsigned int *functions)
-{
- register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
- register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
- register unsigned long reg2 asm ("2");
-
- asm volatile(
- ".long 0xb2af0000\n" /* PQAP(TAPQ) */
- "0:\n"
- EX_TABLE(0b, 0b)
- : "+d" (reg0), "+d" (reg1), "=d" (reg2)
- :
- : "cc");
-
- *functions = (unsigned int)(reg2 >> 32);
- return reg1;
-}
-
-static inline int __ap_query_configuration(struct ap_config_info *config)
+/**
+ * ap_query_configuration(): Get AP configuration data
+ *
+ * Returns 0 on success, or -EOPNOTSUPP.
+ */
+static inline int ap_query_configuration(void)
{
register unsigned long reg0 asm ("0") = 0x04000000UL;
register unsigned long reg1 asm ("1") = -EINVAL;
- register unsigned char *reg2 asm ("2") = (unsigned char *)config;
+ register void *reg2 asm ("2") = (void *) ap_configuration;
+ if (!ap_configuration)
+ return -EOPNOTSUPP;
asm volatile(
".long 0xb2af0000\n" /* PQAP(QCI) */
"0: la %1,0\n"
@@ -297,39 +258,60 @@ static inline int __ap_query_configuration(struct ap_config_info *config)
}
/**
- * ap_query_functions(): Query supported functions.
- * @qid: The AP queue number
- * @functions: Pointer to functions field.
- *
- * Returns
- * 0 on success.
- * -ENODEV if queue not valid.
- * -EBUSY if device busy.
- * -EINVAL if query function is not supported
+ * ap_init_configuration(): Allocate and query configuration array.
*/
-static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
+static void ap_init_configuration(void)
{
- struct ap_queue_status status;
+ if (!ap_configuration_available())
+ return;
- status = __ap_query_functions(qid, functions);
+ ap_configuration = kzalloc(sizeof(*ap_configuration), GFP_KERNEL);
+ if (!ap_configuration)
+ return;
+ if (ap_query_configuration() != 0) {
+ kfree(ap_configuration);
+ ap_configuration = NULL;
+ return;
+ }
+}
- if (ap_queue_status_invalid_test(&status))
- return -ENODEV;
+/*
+ * ap_test_config(): helper function to extract the nrth bit
+ * within the unsigned int array field.
+ */
+static inline int ap_test_config(unsigned int *field, unsigned int nr)
+{
+ return ap_test_bit((field + (nr >> 5)), (nr & 0x1f));
+}
- switch (status.response_code) {
- case AP_RESPONSE_NORMAL:
- return 0;
- case AP_RESPONSE_Q_NOT_AVAIL:
- case AP_RESPONSE_DECONFIGURED:
- case AP_RESPONSE_CHECKSTOPPED:
- case AP_RESPONSE_INVALID_ADDRESS:
- return -ENODEV;
- case AP_RESPONSE_RESET_IN_PROGRESS:
- case AP_RESPONSE_BUSY:
- case AP_RESPONSE_OTHERWISE_CHANGED:
- default:
- return -EBUSY;
- }
+/*
+ * ap_test_config_card_id(): Test, whether an AP card ID is configured.
+ * @id AP card ID
+ *
+ * Returns 0 if the card is not configured
+ * 1 if the card is configured or
+ * if the configuration information is not available
+ */
+static inline int ap_test_config_card_id(unsigned int id)
+{
+ if (!ap_configuration) /* QCI not supported */
+ return 1;
+ return ap_test_config(ap_configuration->apm, id);
+}
+
+/*
+ * ap_test_config_domain(): Test, whether an AP usage domain is configured.
+ * @domain AP usage domain ID
+ *
+ * Returns 0 if the usage domain is not configured
+ * 1 if the usage domain is configured or
+ * if the configuration information is not available
+ */
+static inline int ap_test_config_domain(unsigned int domain)
+{
+ if (!ap_configuration) /* QCI not supported */
+ return domain < 16;
+ return ap_test_config(ap_configuration->aqm, domain);
}
/**
@@ -354,7 +336,9 @@ static int ap_queue_enable_interruption(struct ap_device *ap_dev, void *ind)
case AP_RESPONSE_DECONFIGURED:
case AP_RESPONSE_CHECKSTOPPED:
case AP_RESPONSE_INVALID_ADDRESS:
- return -ENODEV;
+ pr_err("Registering adapter interrupts for AP %d failed\n",
+ AP_QID_DEVICE(ap_dev->qid));
+ return -EOPNOTSUPP;
case AP_RESPONSE_RESET_IN_PROGRESS:
case AP_RESPONSE_BUSY:
default:
@@ -480,137 +464,560 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
EXPORT_SYMBOL(ap_recv);
/**
- * __ap_schedule_poll_timer(): Schedule poll timer.
- *
- * Set up the timer to run the poll tasklet
+ * ap_query_queue(): Check if an AP queue is available.
+ * @qid: The AP queue number
+ * @queue_depth: Pointer to queue depth value
+ * @device_type: Pointer to device type value
+ * @facilities: Pointer to facility indicator
*/
-static inline void __ap_schedule_poll_timer(void)
+static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type,
+ unsigned int *facilities)
+{
+ struct ap_queue_status status;
+ unsigned long info;
+ int nd;
+
+ if (!ap_test_config_card_id(AP_QID_DEVICE(qid)))
+ return -ENODEV;
+
+ status = ap_test_queue(qid, &info);
+ switch (status.response_code) {
+ case AP_RESPONSE_NORMAL:
+ *queue_depth = (int)(info & 0xff);
+ *device_type = (int)((info >> 24) & 0xff);
+ *facilities = (unsigned int)(info >> 32);
+ /* Update maximum domain id */
+ nd = (info >> 16) & 0xff;
+ if ((info & (1UL << 57)) && nd > 0)
+ ap_max_domain_id = nd;
+ return 0;
+ case AP_RESPONSE_Q_NOT_AVAIL:
+ case AP_RESPONSE_DECONFIGURED:
+ case AP_RESPONSE_CHECKSTOPPED:
+ case AP_RESPONSE_INVALID_ADDRESS:
+ return -ENODEV;
+ case AP_RESPONSE_RESET_IN_PROGRESS:
+ case AP_RESPONSE_OTHERWISE_CHANGED:
+ case AP_RESPONSE_BUSY:
+ return -EBUSY;
+ default:
+ BUG();
+ }
+}
+
+/* State machine definitions and helpers */
+
+static void ap_sm_wait(enum ap_wait wait)
{
ktime_t hr_time;
- spin_lock_bh(&ap_poll_timer_lock);
- if (!hrtimer_is_queued(&ap_poll_timer) && !ap_suspend_flag) {
- hr_time = ktime_set(0, poll_timeout);
- hrtimer_forward_now(&ap_poll_timer, hr_time);
- hrtimer_restart(&ap_poll_timer);
+ switch (wait) {
+ case AP_WAIT_AGAIN:
+ case AP_WAIT_INTERRUPT:
+ if (ap_using_interrupts())
+ break;
+ if (ap_poll_kthread) {
+ wake_up(&ap_poll_wait);
+ break;
+ }
+ /* Fall through */
+ case AP_WAIT_TIMEOUT:
+ spin_lock_bh(&ap_poll_timer_lock);
+ if (!hrtimer_is_queued(&ap_poll_timer)) {
+ hr_time = ktime_set(0, poll_timeout);
+ hrtimer_forward_now(&ap_poll_timer, hr_time);
+ hrtimer_restart(&ap_poll_timer);
+ }
+ spin_unlock_bh(&ap_poll_timer_lock);
+ break;
+ case AP_WAIT_NONE:
+ default:
+ break;
}
- spin_unlock_bh(&ap_poll_timer_lock);
+}
+
+static enum ap_wait ap_sm_nop(struct ap_device *ap_dev)
+{
+ return AP_WAIT_NONE;
}
/**
- * ap_schedule_poll_timer(): Schedule poll timer.
+ * ap_sm_recv(): Receive pending reply messages from an AP device but do
+ * not change the state of the device.
+ * @ap_dev: pointer to the AP device
*
- * Set up the timer to run the poll tasklet
+ * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
*/
-static inline void ap_schedule_poll_timer(void)
+static struct ap_queue_status ap_sm_recv(struct ap_device *ap_dev)
{
- if (ap_using_interrupts())
- return;
- __ap_schedule_poll_timer();
+ struct ap_queue_status status;
+ struct ap_message *ap_msg;
+
+ status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
+ ap_dev->reply->message, ap_dev->reply->length);
+ switch (status.response_code) {
+ case AP_RESPONSE_NORMAL:
+ atomic_dec(&ap_poll_requests);
+ ap_dev->queue_count--;
+ if (ap_dev->queue_count > 0)
+ mod_timer(&ap_dev->timeout,
+ jiffies + ap_dev->drv->request_timeout);
+ list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
+ if (ap_msg->psmid != ap_dev->reply->psmid)
+ continue;
+ list_del_init(&ap_msg->list);
+ ap_dev->pendingq_count--;
+ ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
+ break;
+ }
+ case AP_RESPONSE_NO_PENDING_REPLY:
+ if (!status.queue_empty || ap_dev->queue_count <= 0)
+ break;
+ /* The card shouldn't forget requests but who knows. */
+ atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+ ap_dev->queue_count = 0;
+ list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
+ ap_dev->requestq_count += ap_dev->pendingq_count;
+ ap_dev->pendingq_count = 0;
+ break;
+ default:
+ break;
+ }
+ return status;
}
+/**
+ * ap_sm_read(): Receive pending reply messages from an AP device.
+ * @ap_dev: pointer to the AP device
+ *
+ * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
+ */
+static enum ap_wait ap_sm_read(struct ap_device *ap_dev)
+{
+ struct ap_queue_status status;
+
+ status = ap_sm_recv(ap_dev);
+ switch (status.response_code) {
+ case AP_RESPONSE_NORMAL:
+ if (ap_dev->queue_count > 0)
+ return AP_WAIT_AGAIN;
+ ap_dev->state = AP_STATE_IDLE;
+ return AP_WAIT_NONE;
+ case AP_RESPONSE_NO_PENDING_REPLY:
+ if (ap_dev->queue_count > 0)
+ return AP_WAIT_INTERRUPT;
+ ap_dev->state = AP_STATE_IDLE;
+ return AP_WAIT_NONE;
+ default:
+ ap_dev->state = AP_STATE_BORKED;
+ return AP_WAIT_NONE;
+ }
+}
/**
- * ap_query_queue(): Check if an AP queue is available.
- * @qid: The AP queue number
- * @queue_depth: Pointer to queue depth value
- * @device_type: Pointer to device type value
+ * ap_sm_write(): Send messages from the request queue to an AP device.
+ * @ap_dev: pointer to the AP device
+ *
+ * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
*/
-static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+static enum ap_wait ap_sm_write(struct ap_device *ap_dev)
{
struct ap_queue_status status;
- int t_depth, t_device_type;
+ struct ap_message *ap_msg;
- status = ap_test_queue(qid, &t_depth, &t_device_type);
+ if (ap_dev->requestq_count <= 0)
+ return AP_WAIT_NONE;
+ /* Start the next request on the queue. */
+ ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
+ status = __ap_send(ap_dev->qid, ap_msg->psmid,
+ ap_msg->message, ap_msg->length, ap_msg->special);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
- *queue_depth = t_depth + 1;
- *device_type = t_device_type;
- return 0;
- case AP_RESPONSE_Q_NOT_AVAIL:
- case AP_RESPONSE_DECONFIGURED:
- case AP_RESPONSE_CHECKSTOPPED:
- case AP_RESPONSE_INVALID_ADDRESS:
- return -ENODEV;
+ atomic_inc(&ap_poll_requests);
+ ap_dev->queue_count++;
+ if (ap_dev->queue_count == 1)
+ mod_timer(&ap_dev->timeout,
+ jiffies + ap_dev->drv->request_timeout);
+ list_move_tail(&ap_msg->list, &ap_dev->pendingq);
+ ap_dev->requestq_count--;
+ ap_dev->pendingq_count++;
+ if (ap_dev->queue_count < ap_dev->queue_depth) {
+ ap_dev->state = AP_STATE_WORKING;
+ return AP_WAIT_AGAIN;
+ }
+ /* fall through */
+ case AP_RESPONSE_Q_FULL:
+ ap_dev->state = AP_STATE_QUEUE_FULL;
+ return AP_WAIT_INTERRUPT;
case AP_RESPONSE_RESET_IN_PROGRESS:
- case AP_RESPONSE_OTHERWISE_CHANGED:
- case AP_RESPONSE_BUSY:
- return -EBUSY;
+ ap_dev->state = AP_STATE_RESET_WAIT;
+ return AP_WAIT_TIMEOUT;
+ case AP_RESPONSE_MESSAGE_TOO_BIG:
+ case AP_RESPONSE_REQ_FAC_NOT_INST:
+ list_del_init(&ap_msg->list);
+ ap_dev->requestq_count--;
+ ap_msg->rc = -EINVAL;
+ ap_msg->receive(ap_dev, ap_msg, NULL);
+ return AP_WAIT_AGAIN;
default:
- BUG();
+ ap_dev->state = AP_STATE_BORKED;
+ return AP_WAIT_NONE;
}
}
/**
- * ap_init_queue(): Reset an AP queue.
+ * ap_sm_read_write(): Send and receive messages to/from an AP device.
+ * @ap_dev: pointer to the AP device
+ *
+ * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
+ */
+static enum ap_wait ap_sm_read_write(struct ap_device *ap_dev)
+{
+ return min(ap_sm_read(ap_dev), ap_sm_write(ap_dev));
+}
+
+/**
+ * ap_sm_reset(): Reset an AP queue.
* @qid: The AP queue number
*
* Submit the Reset command to an AP queue.
- * Since the reset is asynchron set the state to 'RESET_IN_PROGRESS'
- * and check later via ap_poll_queue() if the reset is done.
*/
-static int ap_init_queue(struct ap_device *ap_dev)
+static enum ap_wait ap_sm_reset(struct ap_device *ap_dev)
{
struct ap_queue_status status;
status = ap_reset_queue(ap_dev->qid);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
- ap_dev->interrupt = AP_INTR_DISABLED;
- ap_dev->reset = AP_RESET_IN_PROGRESS;
- return 0;
case AP_RESPONSE_RESET_IN_PROGRESS:
+ ap_dev->state = AP_STATE_RESET_WAIT;
+ ap_dev->interrupt = AP_INTR_DISABLED;
+ return AP_WAIT_TIMEOUT;
case AP_RESPONSE_BUSY:
- return -EBUSY;
+ return AP_WAIT_TIMEOUT;
case AP_RESPONSE_Q_NOT_AVAIL:
case AP_RESPONSE_DECONFIGURED:
case AP_RESPONSE_CHECKSTOPPED:
default:
- return -ENODEV;
+ ap_dev->state = AP_STATE_BORKED;
+ return AP_WAIT_NONE;
}
}
/**
- * ap_increase_queue_count(): Arm request timeout.
- * @ap_dev: Pointer to an AP device.
+ * ap_sm_reset_wait(): Test queue for completion of the reset operation
+ * @ap_dev: pointer to the AP device
*
- * Arm request timeout if an AP device was idle and a new request is submitted.
+ * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0.
*/
-static void ap_increase_queue_count(struct ap_device *ap_dev)
+static enum ap_wait ap_sm_reset_wait(struct ap_device *ap_dev)
{
- int timeout = ap_dev->drv->request_timeout;
+ struct ap_queue_status status;
+ unsigned long info;
+
+ if (ap_dev->queue_count > 0)
+ /* Try to read a completed message and get the status */
+ status = ap_sm_recv(ap_dev);
+ else
+ /* Get the status with TAPQ */
+ status = ap_test_queue(ap_dev->qid, &info);
- ap_dev->queue_count++;
- if (ap_dev->queue_count == 1) {
- mod_timer(&ap_dev->timeout, jiffies + timeout);
- ap_dev->reset = AP_RESET_ARMED;
+ switch (status.response_code) {
+ case AP_RESPONSE_NORMAL:
+ if (ap_using_interrupts() &&
+ ap_queue_enable_interruption(ap_dev,
+ ap_airq.lsi_ptr) == 0)
+ ap_dev->state = AP_STATE_SETIRQ_WAIT;
+ else
+ ap_dev->state = (ap_dev->queue_count > 0) ?
+ AP_STATE_WORKING : AP_STATE_IDLE;
+ return AP_WAIT_AGAIN;
+ case AP_RESPONSE_BUSY:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
+ return AP_WAIT_TIMEOUT;
+ case AP_RESPONSE_Q_NOT_AVAIL:
+ case AP_RESPONSE_DECONFIGURED:
+ case AP_RESPONSE_CHECKSTOPPED:
+ default:
+ ap_dev->state = AP_STATE_BORKED;
+ return AP_WAIT_NONE;
}
}
/**
- * ap_decrease_queue_count(): Decrease queue count.
- * @ap_dev: Pointer to an AP device.
+ * ap_sm_setirq_wait(): Test queue for completion of the irq enablement
+ * @ap_dev: pointer to the AP device
*
- * If AP device is still alive, re-schedule request timeout if there are still
- * pending requests.
+ * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0.
*/
-static void ap_decrease_queue_count(struct ap_device *ap_dev)
+static enum ap_wait ap_sm_setirq_wait(struct ap_device *ap_dev)
{
- int timeout = ap_dev->drv->request_timeout;
+ struct ap_queue_status status;
+ unsigned long info;
- ap_dev->queue_count--;
if (ap_dev->queue_count > 0)
- mod_timer(&ap_dev->timeout, jiffies + timeout);
+ /* Try to read a completed message and get the status */
+ status = ap_sm_recv(ap_dev);
else
- /*
- * The timeout timer should to be disabled now - since
- * del_timer_sync() is very expensive, we just tell via the
- * reset flag to ignore the pending timeout timer.
- */
- ap_dev->reset = AP_RESET_IGNORE;
+ /* Get the status with TAPQ */
+ status = ap_test_queue(ap_dev->qid, &info);
+
+ if (status.int_enabled == 1) {
+ /* Irqs are now enabled */
+ ap_dev->interrupt = AP_INTR_ENABLED;
+ ap_dev->state = (ap_dev->queue_count > 0) ?
+ AP_STATE_WORKING : AP_STATE_IDLE;
+ }
+
+ switch (status.response_code) {
+ case AP_RESPONSE_NORMAL:
+ if (ap_dev->queue_count > 0)
+ return AP_WAIT_AGAIN;
+ /* fallthrough */
+ case AP_RESPONSE_NO_PENDING_REPLY:
+ return AP_WAIT_TIMEOUT;
+ default:
+ ap_dev->state = AP_STATE_BORKED;
+ return AP_WAIT_NONE;
+ }
}
/*
+ * AP state machine jump table
+ */
+ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = {
+ [AP_STATE_RESET_START] = {
+ [AP_EVENT_POLL] = ap_sm_reset,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
+ [AP_STATE_RESET_WAIT] = {
+ [AP_EVENT_POLL] = ap_sm_reset_wait,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
+ [AP_STATE_SETIRQ_WAIT] = {
+ [AP_EVENT_POLL] = ap_sm_setirq_wait,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
+ [AP_STATE_IDLE] = {
+ [AP_EVENT_POLL] = ap_sm_write,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
+ [AP_STATE_WORKING] = {
+ [AP_EVENT_POLL] = ap_sm_read_write,
+ [AP_EVENT_TIMEOUT] = ap_sm_reset,
+ },
+ [AP_STATE_QUEUE_FULL] = {
+ [AP_EVENT_POLL] = ap_sm_read,
+ [AP_EVENT_TIMEOUT] = ap_sm_reset,
+ },
+ [AP_STATE_SUSPEND_WAIT] = {
+ [AP_EVENT_POLL] = ap_sm_read,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
+ [AP_STATE_BORKED] = {
+ [AP_EVENT_POLL] = ap_sm_nop,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
+};
+
+static inline enum ap_wait ap_sm_event(struct ap_device *ap_dev,
+ enum ap_event event)
+{
+ return ap_jumptable[ap_dev->state][event](ap_dev);
+}
+
+static inline enum ap_wait ap_sm_event_loop(struct ap_device *ap_dev,
+ enum ap_event event)
+{
+ enum ap_wait wait;
+
+ while ((wait = ap_sm_event(ap_dev, event)) == AP_WAIT_AGAIN)
+ ;
+ return wait;
+}
+
+/**
+ * ap_request_timeout(): Handling of request timeouts
+ * @data: Holds the AP device.
+ *
+ * Handles request timeouts.
+ */
+static void ap_request_timeout(unsigned long data)
+{
+ struct ap_device *ap_dev = (struct ap_device *) data;
+
+ if (ap_suspend_flag)
+ return;
+ spin_lock_bh(&ap_dev->lock);
+ ap_sm_wait(ap_sm_event(ap_dev, AP_EVENT_TIMEOUT));
+ spin_unlock_bh(&ap_dev->lock);
+}
+
+/**
+ * ap_poll_timeout(): AP receive polling for finished AP requests.
+ * @unused: Unused pointer.
+ *
+ * Schedules the AP tasklet using a high resolution timer.
+ */
+static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
+{
+ if (!ap_suspend_flag)
+ tasklet_schedule(&ap_tasklet);
+ return HRTIMER_NORESTART;
+}
+
+/**
+ * ap_interrupt_handler() - Schedule ap_tasklet on interrupt
+ * @airq: pointer to adapter interrupt descriptor
+ */
+static void ap_interrupt_handler(struct airq_struct *airq)
+{
+ inc_irq_stat(IRQIO_APB);
+ if (!ap_suspend_flag)
+ tasklet_schedule(&ap_tasklet);
+}
+
+/**
+ * ap_tasklet_fn(): Tasklet to poll all AP devices.
+ * @dummy: Unused variable
+ *
+ * Poll all AP devices on the bus.
+ */
+static void ap_tasklet_fn(unsigned long dummy)
+{
+ struct ap_device *ap_dev;
+ enum ap_wait wait = AP_WAIT_NONE;
+
+ /* Reset the indicator if interrupts are used. Thus new interrupts can
+ * be received. Doing it in the beginning of the tasklet is therefor
+ * important that no requests on any AP get lost.
+ */
+ if (ap_using_interrupts())
+ xchg(ap_airq.lsi_ptr, 0);
+
+ spin_lock(&ap_device_list_lock);
+ list_for_each_entry(ap_dev, &ap_device_list, list) {
+ spin_lock_bh(&ap_dev->lock);
+ wait = min(wait, ap_sm_event_loop(ap_dev, AP_EVENT_POLL));
+ spin_unlock_bh(&ap_dev->lock);
+ }
+ spin_unlock(&ap_device_list_lock);
+ ap_sm_wait(wait);
+}
+
+/**
+ * ap_poll_thread(): Thread that polls for finished requests.
+ * @data: Unused pointer
+ *
+ * AP bus poll thread. The purpose of this thread is to poll for
+ * finished requests in a loop if there is a "free" cpu - that is
+ * a cpu that doesn't have anything better to do. The polling stops
+ * as soon as there is another task or if all messages have been
+ * delivered.
+ */
+static int ap_poll_thread(void *data)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ set_user_nice(current, MAX_NICE);
+ set_freezable();
+ while (!kthread_should_stop()) {
+ add_wait_queue(&ap_poll_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (ap_suspend_flag ||
+ atomic_read(&ap_poll_requests) <= 0) {
+ schedule();
+ try_to_freeze();
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&ap_poll_wait, &wait);
+ if (need_resched()) {
+ schedule();
+ try_to_freeze();
+ continue;
+ }
+ ap_tasklet_fn(0);
+ } while (!kthread_should_stop());
+ return 0;
+}
+
+static int ap_poll_thread_start(void)
+{
+ int rc;
+
+ if (ap_using_interrupts() || ap_poll_kthread)
+ return 0;
+ mutex_lock(&ap_poll_thread_mutex);
+ ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
+ rc = PTR_RET(ap_poll_kthread);
+ if (rc)
+ ap_poll_kthread = NULL;
+ mutex_unlock(&ap_poll_thread_mutex);
+ return rc;
+}
+
+static void ap_poll_thread_stop(void)
+{
+ if (!ap_poll_kthread)
+ return;
+ mutex_lock(&ap_poll_thread_mutex);
+ kthread_stop(ap_poll_kthread);
+ ap_poll_kthread = NULL;
+ mutex_unlock(&ap_poll_thread_mutex);
+}
+
+/**
+ * ap_queue_message(): Queue a request to an AP device.
+ * @ap_dev: The AP device to queue the message to
+ * @ap_msg: The message that is to be added
+ */
+void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+{
+ /* For asynchronous message handling a valid receive-callback
+ * is required. */
+ BUG_ON(!ap_msg->receive);
+
+ spin_lock_bh(&ap_dev->lock);
+ /* Queue the message. */
+ list_add_tail(&ap_msg->list, &ap_dev->requestq);
+ ap_dev->requestq_count++;
+ ap_dev->total_request_count++;
+ /* Send/receive as many request from the queue as possible. */
+ ap_sm_wait(ap_sm_event_loop(ap_dev, AP_EVENT_POLL));
+ spin_unlock_bh(&ap_dev->lock);
+}
+EXPORT_SYMBOL(ap_queue_message);
+
+/**
+ * ap_cancel_message(): Cancel a crypto request.
+ * @ap_dev: The AP device that has the message queued
+ * @ap_msg: The message that is to be removed
+ *
+ * Cancel a crypto request. This is done by removing the request
+ * from the device pending or request queue. Note that the
+ * request stays on the AP queue. When it finishes the message
+ * reply will be discarded because the psmid can't be found.
+ */
+void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+{
+ struct ap_message *tmp;
+
+ spin_lock_bh(&ap_dev->lock);
+ if (!list_empty(&ap_msg->list)) {
+ list_for_each_entry(tmp, &ap_dev->pendingq, list)
+ if (tmp->psmid == ap_msg->psmid) {
+ ap_dev->pendingq_count--;
+ goto found;
+ }
+ ap_dev->requestq_count--;
+found:
+ list_del_init(&ap_msg->list);
+ }
+ spin_unlock_bh(&ap_dev->lock);
+}
+EXPORT_SYMBOL(ap_cancel_message);
+
+/*
* AP device related attributes.
*/
static ssize_t ap_hwtype_show(struct device *dev,
@@ -690,21 +1097,17 @@ static ssize_t ap_reset_show(struct device *dev,
int rc = 0;
spin_lock_bh(&ap_dev->lock);
- switch (ap_dev->reset) {
- case AP_RESET_IGNORE:
- rc = snprintf(buf, PAGE_SIZE, "No Reset Timer set.\n");
+ switch (ap_dev->state) {
+ case AP_STATE_RESET_START:
+ case AP_STATE_RESET_WAIT:
+ rc = snprintf(buf, PAGE_SIZE, "Reset in progress.\n");
break;
- case AP_RESET_ARMED:
+ case AP_STATE_WORKING:
+ case AP_STATE_QUEUE_FULL:
rc = snprintf(buf, PAGE_SIZE, "Reset Timer armed.\n");
break;
- case AP_RESET_DO:
- rc = snprintf(buf, PAGE_SIZE, "Reset Timer expired.\n");
- break;
- case AP_RESET_IN_PROGRESS:
- rc = snprintf(buf, PAGE_SIZE, "Reset in progress.\n");
- break;
default:
- break;
+ rc = snprintf(buf, PAGE_SIZE, "No Reset Timer set.\n");
}
spin_unlock_bh(&ap_dev->lock);
return rc;
@@ -719,17 +1122,12 @@ static ssize_t ap_interrupt_show(struct device *dev,
int rc = 0;
spin_lock_bh(&ap_dev->lock);
- switch (ap_dev->interrupt) {
- case AP_INTR_DISABLED:
- rc = snprintf(buf, PAGE_SIZE, "Interrupts disabled.\n");
- break;
- case AP_INTR_ENABLED:
- rc = snprintf(buf, PAGE_SIZE, "Interrupts enabled.\n");
- break;
- case AP_INTR_IN_PROGRESS:
+ if (ap_dev->state == AP_STATE_SETIRQ_WAIT)
rc = snprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n");
- break;
- }
+ else if (ap_dev->interrupt == AP_INTR_ENABLED)
+ rc = snprintf(buf, PAGE_SIZE, "Interrupts enabled.\n");
+ else
+ rc = snprintf(buf, PAGE_SIZE, "Interrupts disabled.\n");
spin_unlock_bh(&ap_dev->lock);
return rc;
}
@@ -823,99 +1221,95 @@ static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
return retval;
}
-static int ap_bus_suspend(struct device *dev, pm_message_t state)
+static int ap_dev_suspend(struct device *dev, pm_message_t state)
{
struct ap_device *ap_dev = to_ap_dev(dev);
- unsigned long flags;
-
- if (!ap_suspend_flag) {
- ap_suspend_flag = 1;
-
- /* Disable scanning for devices, thus we do not want to scan
- * for them after removing.
- */
- del_timer_sync(&ap_config_timer);
- if (ap_work_queue != NULL) {
- destroy_workqueue(ap_work_queue);
- ap_work_queue = NULL;
- }
- tasklet_disable(&ap_tasklet);
- }
/* Poll on the device until all requests are finished. */
- do {
- flags = 0;
- spin_lock_bh(&ap_dev->lock);
- __ap_poll_device(ap_dev, &flags);
- spin_unlock_bh(&ap_dev->lock);
- } while ((flags & 1) || (flags & 2));
-
spin_lock_bh(&ap_dev->lock);
- ap_dev->unregistered = 1;
+ ap_dev->state = AP_STATE_SUSPEND_WAIT;
+ while (ap_sm_event(ap_dev, AP_EVENT_POLL) != AP_WAIT_NONE)
+ ;
+ ap_dev->state = AP_STATE_BORKED;
spin_unlock_bh(&ap_dev->lock);
+ return 0;
+}
+static int ap_dev_resume(struct device *dev)
+{
return 0;
}
-static int ap_bus_resume(struct device *dev)
+static void ap_bus_suspend(void)
+{
+ ap_suspend_flag = 1;
+ /*
+ * Disable scanning for devices, thus we do not want to scan
+ * for them after removing.
+ */
+ flush_work(&ap_scan_work);
+ tasklet_disable(&ap_tasklet);
+}
+
+static int __ap_devices_unregister(struct device *dev, void *dummy)
+{
+ device_unregister(dev);
+ return 0;
+}
+
+static void ap_bus_resume(void)
{
- struct ap_device *ap_dev = to_ap_dev(dev);
int rc;
- if (ap_suspend_flag) {
- ap_suspend_flag = 0;
- if (ap_interrupts_available()) {
- if (!ap_using_interrupts()) {
- rc = register_adapter_interrupt(&ap_airq);
- ap_airq_flag = (rc == 0);
- }
- } else {
- if (ap_using_interrupts()) {
- unregister_adapter_interrupt(&ap_airq);
- ap_airq_flag = 0;
- }
- }
- ap_query_configuration();
- if (!user_set_domain) {
- ap_domain_index = -1;
- ap_select_domain();
- }
- init_timer(&ap_config_timer);
- ap_config_timer.function = ap_config_timeout;
- ap_config_timer.data = 0;
- ap_config_timer.expires = jiffies + ap_config_time * HZ;
- add_timer(&ap_config_timer);
- ap_work_queue = create_singlethread_workqueue("kapwork");
- if (!ap_work_queue)
- return -ENOMEM;
- tasklet_enable(&ap_tasklet);
- if (!ap_using_interrupts())
- ap_schedule_poll_timer();
- else
- tasklet_schedule(&ap_tasklet);
- if (ap_thread_flag)
- rc = ap_poll_thread_start();
- else
- rc = 0;
- } else
- rc = 0;
- if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
- spin_lock_bh(&ap_dev->lock);
- ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
- ap_domain_index);
- spin_unlock_bh(&ap_dev->lock);
+ /* Unconditionally remove all AP devices */
+ bus_for_each_dev(&ap_bus_type, NULL, NULL, __ap_devices_unregister);
+ /* Reset thin interrupt setting */
+ if (ap_interrupts_available() && !ap_using_interrupts()) {
+ rc = register_adapter_interrupt(&ap_airq);
+ ap_airq_flag = (rc == 0);
+ }
+ if (!ap_interrupts_available() && ap_using_interrupts()) {
+ unregister_adapter_interrupt(&ap_airq);
+ ap_airq_flag = 0;
}
- queue_work(ap_work_queue, &ap_config_work);
+ /* Reset domain */
+ if (!user_set_domain)
+ ap_domain_index = -1;
+ /* Get things going again */
+ ap_suspend_flag = 0;
+ if (ap_airq_flag)
+ xchg(ap_airq.lsi_ptr, 0);
+ tasklet_enable(&ap_tasklet);
+ queue_work(system_long_wq, &ap_scan_work);
+}
- return rc;
+static int ap_power_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ switch (event) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ ap_bus_suspend();
+ break;
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ ap_bus_resume();
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
}
+static struct notifier_block ap_power_notifier = {
+ .notifier_call = ap_power_event,
+};
static struct bus_type ap_bus_type = {
.name = "ap",
.match = &ap_bus_match,
.uevent = &ap_uevent,
- .suspend = ap_bus_suspend,
- .resume = ap_bus_resume
+ .suspend = ap_dev_suspend,
+ .resume = ap_dev_resume,
};
static int ap_device_probe(struct device *dev)
@@ -925,21 +1319,9 @@ static int ap_device_probe(struct device *dev)
int rc;
ap_dev->drv = ap_drv;
-
- spin_lock_bh(&ap_device_list_lock);
- list_add(&ap_dev->list, &ap_device_list);
- spin_unlock_bh(&ap_device_list_lock);
-
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
- if (rc) {
- spin_lock_bh(&ap_device_list_lock);
- list_del_init(&ap_dev->list);
- spin_unlock_bh(&ap_device_list_lock);
- } else {
- if (ap_dev->reset == AP_RESET_IN_PROGRESS ||
- ap_dev->interrupt == AP_INTR_IN_PROGRESS)
- __ap_schedule_poll_timer();
- }
+ if (rc)
+ ap_dev->drv = NULL;
return rc;
}
@@ -956,12 +1338,14 @@ static void __ap_flush_queue(struct ap_device *ap_dev)
list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
list_del_init(&ap_msg->list);
ap_dev->pendingq_count--;
- ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+ ap_msg->rc = -EAGAIN;
+ ap_msg->receive(ap_dev, ap_msg, NULL);
}
list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
list_del_init(&ap_msg->list);
ap_dev->requestq_count--;
- ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+ ap_msg->rc = -EAGAIN;
+ ap_msg->receive(ap_dev, ap_msg, NULL);
}
}
@@ -991,11 +1375,19 @@ static int ap_device_remove(struct device *dev)
return 0;
}
+static void ap_device_release(struct device *dev)
+{
+ kfree(to_ap_dev(dev));
+}
+
int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
char *name)
{
struct device_driver *drv = &ap_drv->driver;
+ if (!initialised)
+ return -ENODEV;
+
drv->bus = &ap_bus_type;
drv->probe = ap_device_probe;
drv->remove = ap_device_remove;
@@ -1013,60 +1405,16 @@ EXPORT_SYMBOL(ap_driver_unregister);
void ap_bus_force_rescan(void)
{
- /* reconfigure the AP bus rescan timer. */
- mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
+ if (ap_suspend_flag)
+ return;
/* processing a asynchronous bus rescan */
- queue_work(ap_work_queue, &ap_config_work);
- flush_work(&ap_config_work);
+ del_timer(&ap_config_timer);
+ queue_work(system_long_wq, &ap_scan_work);
+ flush_work(&ap_scan_work);
}
EXPORT_SYMBOL(ap_bus_force_rescan);
/*
- * ap_test_config(): helper function to extract the nrth bit
- * within the unsigned int array field.
- */
-static inline int ap_test_config(unsigned int *field, unsigned int nr)
-{
- if (nr > 0xFFu)
- return 0;
- return ap_test_bit((field + (nr >> 5)), (nr & 0x1f));
-}
-
-/*
- * ap_test_config_card_id(): Test, whether an AP card ID is configured.
- * @id AP card ID
- *
- * Returns 0 if the card is not configured
- * 1 if the card is configured or
- * if the configuration information is not available
- */
-static inline int ap_test_config_card_id(unsigned int id)
-{
- if (!ap_configuration)
- return 1;
- return ap_test_config(ap_configuration->apm, id);
-}
-
-/*
- * ap_test_config_domain(): Test, whether an AP usage domain is configured.
- * @domain AP usage domain ID
- *
- * Returns 0 if the usage domain is not configured
- * 1 if the usage domain is configured or
- * if the configuration information is not available
- */
-static inline int ap_test_config_domain(unsigned int domain)
-{
- if (!ap_configuration) /* QCI not supported */
- if (domain < 16)
- return 1; /* then domains 0...15 are configured */
- else
- return 0;
- else
- return ap_test_config(ap_configuration->aqm, domain);
-}
-
-/*
* AP bus attributes.
*/
static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
@@ -1078,21 +1426,20 @@ static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf)
{
- if (ap_configuration != NULL) { /* QCI not supported */
- if (test_facility(76)) { /* format 1 - 256 bit domain field */
- return snprintf(buf, PAGE_SIZE,
- "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+ if (!ap_configuration) /* QCI not supported */
+ return snprintf(buf, PAGE_SIZE, "not supported\n");
+ if (!test_facility(76))
+ /* format 0 - 16 bit domain field */
+ return snprintf(buf, PAGE_SIZE, "%08x%08x\n",
+ ap_configuration->adm[0],
+ ap_configuration->adm[1]);
+ /* format 1 - 256 bit domain field */
+ return snprintf(buf, PAGE_SIZE,
+ "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
ap_configuration->adm[0], ap_configuration->adm[1],
ap_configuration->adm[2], ap_configuration->adm[3],
ap_configuration->adm[4], ap_configuration->adm[5],
ap_configuration->adm[6], ap_configuration->adm[7]);
- } else { /* format 0 - 16 bit domain field */
- return snprintf(buf, PAGE_SIZE, "%08x%08x\n",
- ap_configuration->adm[0], ap_configuration->adm[1]);
- }
- } else {
- return snprintf(buf, PAGE_SIZE, "not supported\n");
- }
}
static BUS_ATTR(ap_control_domain_mask, 0444,
@@ -1119,11 +1466,7 @@ static ssize_t ap_config_time_store(struct bus_type *bus,
if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
return -EINVAL;
ap_config_time = time;
- if (!timer_pending(&ap_config_timer) ||
- !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
- ap_config_timer.expires = jiffies + ap_config_time * HZ;
- add_timer(&ap_config_timer);
- }
+ mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
return count;
}
@@ -1144,9 +1487,8 @@ static ssize_t ap_poll_thread_store(struct bus_type *bus,
if (flag) {
rc = ap_poll_thread_start();
if (rc)
- return rc;
- }
- else
+ count = rc;
+ } else
ap_poll_thread_stop();
return count;
}
@@ -1184,35 +1526,12 @@ static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
{
- ap_qid_t qid;
- int i, nd, max_domain_id = -1;
- unsigned long fbits;
-
- if (ap_configuration) {
- if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS) {
- for (i = 0; i < AP_DEVICES; i++) {
- if (!ap_test_config_card_id(i))
- continue;
- qid = AP_MKQID(i, ap_domain_index);
- fbits = ap_query_facilities(qid);
- if (fbits & (1UL << 57)) {
- /* the N bit is 0, Nd field is filled */
- nd = (int)((fbits & 0x00FF0000UL)>>16);
- if (nd > 0)
- max_domain_id = nd;
- else
- max_domain_id = 15;
- } else {
- /* N bit is 1, max 16 domains */
- max_domain_id = 15;
- }
- break;
- }
- }
- } else {
- /* no APXA support, older machines with max 16 domains */
+ int max_domain_id;
+
+ if (ap_configuration)
+ max_domain_id = ap_max_domain_id ? : -1;
+ else
max_domain_id = 15;
- }
return snprintf(buf, PAGE_SIZE, "%d\n", max_domain_id);
}
@@ -1230,44 +1549,22 @@ static struct bus_attribute *const ap_bus_attrs[] = {
};
/**
- * ap_query_configuration(): Query AP configuration information.
- *
- * Query information of installed cards and configured domains from AP.
- */
-static void ap_query_configuration(void)
-{
- if (ap_configuration_available()) {
- if (!ap_configuration)
- ap_configuration =
- kzalloc(sizeof(struct ap_config_info),
- GFP_KERNEL);
- if (ap_configuration)
- __ap_query_configuration(ap_configuration);
- } else
- ap_configuration = NULL;
-}
-
-/**
* ap_select_domain(): Select an AP domain.
*
* Pick one of the 16 AP domains.
*/
static int ap_select_domain(void)
{
- int queue_depth, device_type, count, max_count, best_domain;
- ap_qid_t qid;
- int rc, i, j;
-
- /* IF APXA isn't installed, only 16 domains could be defined */
- if (!ap_configuration->ap_extended && (ap_domain_index > 15))
- return -EINVAL;
+ int count, max_count, best_domain;
+ struct ap_queue_status status;
+ int i, j;
/*
* We want to use a single domain. Either the one specified with
* the "domain=" parameter or the domain with the maximum number
* of devices.
*/
- if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
+ if (ap_domain_index >= 0)
/* Domain has already been selected. */
return 0;
best_domain = -1;
@@ -1279,9 +1576,8 @@ static int ap_select_domain(void)
for (j = 0; j < AP_DEVICES; j++) {
if (!ap_test_config_card_id(j))
continue;
- qid = AP_MKQID(j, i);
- rc = ap_query_queue(qid, &queue_depth, &device_type);
- if (rc)
+ status = ap_test_queue(AP_MKQID(j, i), NULL);
+ if (status.response_code != AP_RESPONSE_NORMAL)
continue;
count++;
}
@@ -1298,109 +1594,6 @@ static int ap_select_domain(void)
}
/**
- * ap_probe_device_type(): Find the device type of an AP.
- * @ap_dev: pointer to the AP device.
- *
- * Find the device type if query queue returned a device type of 0.
- */
-static int ap_probe_device_type(struct ap_device *ap_dev)
-{
- static unsigned char msg[] = {
- 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
- 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
- 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
- 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xb8,0x05,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,
- 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,0x0a,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
- 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
- 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
- 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
- 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
- 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
- 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
- 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
- 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
- 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
- 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
- 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
- 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
- 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
- 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
- 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
- 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
- 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
- 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
- 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
- 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
- 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
- };
- struct ap_queue_status status;
- unsigned long long psmid;
- char *reply;
- int rc, i;
-
- reply = (void *) get_zeroed_page(GFP_KERNEL);
- if (!reply) {
- rc = -ENOMEM;
- goto out;
- }
-
- status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
- msg, sizeof(msg), 0);
- if (status.response_code != AP_RESPONSE_NORMAL) {
- rc = -ENODEV;
- goto out_free;
- }
-
- /* Wait for the test message to complete. */
- for (i = 0; i < 6; i++) {
- msleep(300);
- status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
- if (status.response_code == AP_RESPONSE_NORMAL &&
- psmid == 0x0102030405060708ULL)
- break;
- }
- if (i < 6) {
- /* Got an answer. */
- if (reply[0] == 0x00 && reply[1] == 0x86)
- ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
- else
- ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
- rc = 0;
- } else
- rc = -ENODEV;
-
-out_free:
- free_page((unsigned long) reply);
-out:
- return rc;
-}
-
-static void ap_interrupt_handler(struct airq_struct *airq)
-{
- inc_irq_stat(IRQIO_APB);
- tasklet_schedule(&ap_tasklet);
-}
-
-/**
* __ap_scan_bus(): Scan the AP bus.
* @dev: Pointer to device
* @data: Pointer to data
@@ -1412,49 +1605,38 @@ static int __ap_scan_bus(struct device *dev, void *data)
return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
}
-static void ap_device_release(struct device *dev)
-{
- struct ap_device *ap_dev = to_ap_dev(dev);
-
- kfree(ap_dev);
-}
-
static void ap_scan_bus(struct work_struct *unused)
{
struct ap_device *ap_dev;
struct device *dev;
ap_qid_t qid;
int queue_depth = 0, device_type = 0;
- unsigned int device_functions;
- int rc, i;
+ unsigned int device_functions = 0;
+ int rc, i, borked;
ap_query_configuration();
- if (ap_select_domain() != 0) {
- return;
- }
+ if (ap_select_domain() != 0)
+ goto out;
+
for (i = 0; i < AP_DEVICES; i++) {
qid = AP_MKQID(i, ap_domain_index);
dev = bus_find_device(&ap_bus_type, NULL,
(void *)(unsigned long)qid,
__ap_scan_bus);
- if (ap_test_config_card_id(i))
- rc = ap_query_queue(qid, &queue_depth, &device_type);
- else
- rc = -ENODEV;
+ rc = ap_query_queue(qid, &queue_depth, &device_type,
+ &device_functions);
if (dev) {
ap_dev = to_ap_dev(dev);
spin_lock_bh(&ap_dev->lock);
- if (rc == -ENODEV || ap_dev->unregistered) {
- spin_unlock_bh(&ap_dev->lock);
- if (ap_dev->unregistered)
- i--;
- device_unregister(dev);
- put_device(dev);
- continue;
- }
+ if (rc == -ENODEV)
+ ap_dev->state = AP_STATE_BORKED;
+ borked = ap_dev->state == AP_STATE_BORKED;
spin_unlock_bh(&ap_dev->lock);
+ if (borked) /* Remove broken device */
+ device_unregister(dev);
put_device(dev);
- continue;
+ if (!borked)
+ continue;
}
if (rc)
continue;
@@ -1462,525 +1644,72 @@ static void ap_scan_bus(struct work_struct *unused)
if (!ap_dev)
break;
ap_dev->qid = qid;
- rc = ap_init_queue(ap_dev);
- if ((rc != 0) && (rc != -EBUSY)) {
- kfree(ap_dev);
- continue;
- }
+ ap_dev->state = AP_STATE_RESET_START;
+ ap_dev->interrupt = AP_INTR_DISABLED;
ap_dev->queue_depth = queue_depth;
- ap_dev->unregistered = 1;
+ ap_dev->raw_hwtype = device_type;
+ ap_dev->device_type = device_type;
+ ap_dev->functions = device_functions;
spin_lock_init(&ap_dev->lock);
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
INIT_LIST_HEAD(&ap_dev->list);
setup_timer(&ap_dev->timeout, ap_request_timeout,
(unsigned long) ap_dev);
- switch (device_type) {
- case 0:
- /* device type probing for old cards */
- if (ap_probe_device_type(ap_dev)) {
- kfree(ap_dev);
- continue;
- }
- break;
- default:
- ap_dev->device_type = device_type;
- }
- ap_dev->raw_hwtype = device_type;
-
- rc = ap_query_functions(qid, &device_functions);
- if (!rc)
- ap_dev->functions = device_functions;
- else
- ap_dev->functions = 0u;
ap_dev->device.bus = &ap_bus_type;
ap_dev->device.parent = ap_root_device;
- if (dev_set_name(&ap_dev->device, "card%02x",
- AP_QID_DEVICE(ap_dev->qid))) {
+ rc = dev_set_name(&ap_dev->device, "card%02x",
+ AP_QID_DEVICE(ap_dev->qid));
+ if (rc) {
kfree(ap_dev);
continue;
}
+ /* Add to list of devices */
+ spin_lock_bh(&ap_device_list_lock);
+ list_add(&ap_dev->list, &ap_device_list);
+ spin_unlock_bh(&ap_device_list_lock);
+ /* Start with a device reset */
+ spin_lock_bh(&ap_dev->lock);
+ ap_sm_wait(ap_sm_event(ap_dev, AP_EVENT_POLL));
+ spin_unlock_bh(&ap_dev->lock);
+ /* Register device */
ap_dev->device.release = ap_device_release;
rc = device_register(&ap_dev->device);
if (rc) {
+ spin_lock_bh(&ap_dev->lock);
+ list_del_init(&ap_dev->list);
+ spin_unlock_bh(&ap_dev->lock);
put_device(&ap_dev->device);
continue;
}
/* Add device attributes. */
rc = sysfs_create_group(&ap_dev->device.kobj,
&ap_dev_attr_group);
- if (!rc) {
- spin_lock_bh(&ap_dev->lock);
- ap_dev->unregistered = 0;
- spin_unlock_bh(&ap_dev->lock);
- }
- else
+ if (rc) {
device_unregister(&ap_dev->device);
- }
-}
-
-static void
-ap_config_timeout(unsigned long ptr)
-{
- queue_work(ap_work_queue, &ap_config_work);
- ap_config_timer.expires = jiffies + ap_config_time * HZ;
- add_timer(&ap_config_timer);
-}
-
-/**
- * ap_poll_read(): Receive pending reply messages from an AP device.
- * @ap_dev: pointer to the AP device
- * @flags: pointer to control flags, bit 2^0 is set if another poll is
- * required, bit 2^1 is set if the poll timer needs to get armed
- *
- * Returns 0 if the device is still present, -ENODEV if not.
- */
-static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
-{
- struct ap_queue_status status;
- struct ap_message *ap_msg;
-
- if (ap_dev->queue_count <= 0)
- return 0;
- status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
- ap_dev->reply->message, ap_dev->reply->length);
- switch (status.response_code) {
- case AP_RESPONSE_NORMAL:
- ap_dev->interrupt = status.int_enabled;
- atomic_dec(&ap_poll_requests);
- ap_decrease_queue_count(ap_dev);
- list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
- if (ap_msg->psmid != ap_dev->reply->psmid)
- continue;
- list_del_init(&ap_msg->list);
- ap_dev->pendingq_count--;
- ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
- break;
- }
- if (ap_dev->queue_count > 0)
- *flags |= 1;
- break;
- case AP_RESPONSE_NO_PENDING_REPLY:
- ap_dev->interrupt = status.int_enabled;
- if (status.queue_empty) {
- /* The card shouldn't forget requests but who knows. */
- atomic_sub(ap_dev->queue_count, &ap_poll_requests);
- ap_dev->queue_count = 0;
- list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
- ap_dev->requestq_count += ap_dev->pendingq_count;
- ap_dev->pendingq_count = 0;
- } else
- *flags |= 2;
- break;
- default:
- return -ENODEV;
- }
- return 0;
-}
-
-/**
- * ap_poll_write(): Send messages from the request queue to an AP device.
- * @ap_dev: pointer to the AP device
- * @flags: pointer to control flags, bit 2^0 is set if another poll is
- * required, bit 2^1 is set if the poll timer needs to get armed
- *
- * Returns 0 if the device is still present, -ENODEV if not.
- */
-static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
-{
- struct ap_queue_status status;
- struct ap_message *ap_msg;
-
- if (ap_dev->requestq_count <= 0 ||
- (ap_dev->queue_count >= ap_dev->queue_depth) ||
- (ap_dev->reset == AP_RESET_IN_PROGRESS))
- return 0;
- /* Start the next request on the queue. */
- ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
- status = __ap_send(ap_dev->qid, ap_msg->psmid,
- ap_msg->message, ap_msg->length, ap_msg->special);
- switch (status.response_code) {
- case AP_RESPONSE_NORMAL:
- atomic_inc(&ap_poll_requests);
- ap_increase_queue_count(ap_dev);
- list_move_tail(&ap_msg->list, &ap_dev->pendingq);
- ap_dev->requestq_count--;
- ap_dev->pendingq_count++;
- if (ap_dev->queue_count < ap_dev->queue_depth &&
- ap_dev->requestq_count > 0)
- *flags |= 1;
- *flags |= 2;
- break;
- case AP_RESPONSE_RESET_IN_PROGRESS:
- __ap_schedule_poll_timer();
- case AP_RESPONSE_Q_FULL:
- *flags |= 2;
- break;
- case AP_RESPONSE_MESSAGE_TOO_BIG:
- case AP_RESPONSE_REQ_FAC_NOT_INST:
- return -EINVAL;
- default:
- return -ENODEV;
- }
- return 0;
-}
-
-/**
- * ap_poll_queue(): Poll AP device for pending replies and send new messages.
- * Check if the queue has a pending reset. In case it's done re-enable
- * interrupts, otherwise reschedule the poll_timer for another attempt.
- * @ap_dev: pointer to the bus device
- * @flags: pointer to control flags, bit 2^0 is set if another poll is
- * required, bit 2^1 is set if the poll timer needs to get armed
- *
- * Poll AP device for pending replies and send new messages. If either
- * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
- * Returns 0.
- */
-static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
-{
- int rc, depth, type;
- struct ap_queue_status status;
-
-
- if (ap_dev->reset == AP_RESET_IN_PROGRESS) {
- status = ap_test_queue(ap_dev->qid, &depth, &type);
- switch (status.response_code) {
- case AP_RESPONSE_NORMAL:
- ap_dev->reset = AP_RESET_IGNORE;
- if (ap_using_interrupts()) {
- rc = ap_queue_enable_interruption(
- ap_dev, ap_airq.lsi_ptr);
- if (!rc)
- ap_dev->interrupt = AP_INTR_IN_PROGRESS;
- else if (rc == -ENODEV) {
- pr_err("Registering adapter interrupts for "
- "AP %d failed\n", AP_QID_DEVICE(ap_dev->qid));
- return rc;
- }
- }
- /* fall through */
- case AP_RESPONSE_BUSY:
- case AP_RESPONSE_RESET_IN_PROGRESS:
- *flags |= AP_POLL_AFTER_TIMEOUT;
- break;
- case AP_RESPONSE_Q_NOT_AVAIL:
- case AP_RESPONSE_DECONFIGURED:
- case AP_RESPONSE_CHECKSTOPPED:
- return -ENODEV;
- default:
- break;
- }
- }
-
- if ((ap_dev->reset != AP_RESET_IN_PROGRESS) &&
- (ap_dev->interrupt == AP_INTR_IN_PROGRESS)) {
- status = ap_test_queue(ap_dev->qid, &depth, &type);
- if (ap_using_interrupts()) {
- if (status.int_enabled == 1)
- ap_dev->interrupt = AP_INTR_ENABLED;
- else
- *flags |= AP_POLL_AFTER_TIMEOUT;
- } else
- ap_dev->interrupt = AP_INTR_DISABLED;
- }
-
- rc = ap_poll_read(ap_dev, flags);
- if (rc)
- return rc;
- return ap_poll_write(ap_dev, flags);
-}
-
-/**
- * __ap_queue_message(): Queue a message to a device.
- * @ap_dev: pointer to the AP device
- * @ap_msg: the message to be queued
- *
- * Queue a message to a device. Returns 0 if successful.
- */
-static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
-{
- struct ap_queue_status status;
-
- if (list_empty(&ap_dev->requestq) &&
- (ap_dev->queue_count < ap_dev->queue_depth) &&
- (ap_dev->reset != AP_RESET_IN_PROGRESS)) {
- status = __ap_send(ap_dev->qid, ap_msg->psmid,
- ap_msg->message, ap_msg->length,
- ap_msg->special);
- switch (status.response_code) {
- case AP_RESPONSE_NORMAL:
- list_add_tail(&ap_msg->list, &ap_dev->pendingq);
- atomic_inc(&ap_poll_requests);
- ap_dev->pendingq_count++;
- ap_increase_queue_count(ap_dev);
- ap_dev->total_request_count++;
- break;
- case AP_RESPONSE_Q_FULL:
- case AP_RESPONSE_RESET_IN_PROGRESS:
- list_add_tail(&ap_msg->list, &ap_dev->requestq);
- ap_dev->requestq_count++;
- ap_dev->total_request_count++;
- return -EBUSY;
- case AP_RESPONSE_REQ_FAC_NOT_INST:
- case AP_RESPONSE_MESSAGE_TOO_BIG:
- ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
- return -EINVAL;
- default: /* Device is gone. */
- ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
- return -ENODEV;
- }
- } else {
- list_add_tail(&ap_msg->list, &ap_dev->requestq);
- ap_dev->requestq_count++;
- ap_dev->total_request_count++;
- return -EBUSY;
- }
- ap_schedule_poll_timer();
- return 0;
-}
-
-void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
-{
- unsigned long flags;
- int rc;
-
- /* For asynchronous message handling a valid receive-callback
- * is required. */
- BUG_ON(!ap_msg->receive);
-
- spin_lock_bh(&ap_dev->lock);
- if (!ap_dev->unregistered) {
- /* Make room on the queue by polling for finished requests. */
- rc = ap_poll_queue(ap_dev, &flags);
- if (!rc)
- rc = __ap_queue_message(ap_dev, ap_msg);
- if (!rc)
- wake_up(&ap_poll_wait);
- if (rc == -ENODEV)
- ap_dev->unregistered = 1;
- } else {
- ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
- rc = -ENODEV;
- }
- spin_unlock_bh(&ap_dev->lock);
- if (rc == -ENODEV)
- device_unregister(&ap_dev->device);
-}
-EXPORT_SYMBOL(ap_queue_message);
-
-/**
- * ap_cancel_message(): Cancel a crypto request.
- * @ap_dev: The AP device that has the message queued
- * @ap_msg: The message that is to be removed
- *
- * Cancel a crypto request. This is done by removing the request
- * from the device pending or request queue. Note that the
- * request stays on the AP queue. When it finishes the message
- * reply will be discarded because the psmid can't be found.
- */
-void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
-{
- struct ap_message *tmp;
-
- spin_lock_bh(&ap_dev->lock);
- if (!list_empty(&ap_msg->list)) {
- list_for_each_entry(tmp, &ap_dev->pendingq, list)
- if (tmp->psmid == ap_msg->psmid) {
- ap_dev->pendingq_count--;
- goto found;
- }
- ap_dev->requestq_count--;
- found:
- list_del_init(&ap_msg->list);
- }
- spin_unlock_bh(&ap_dev->lock);
-}
-EXPORT_SYMBOL(ap_cancel_message);
-
-/**
- * ap_poll_timeout(): AP receive polling for finished AP requests.
- * @unused: Unused pointer.
- *
- * Schedules the AP tasklet using a high resolution timer.
- */
-static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
-{
- tasklet_schedule(&ap_tasklet);
- return HRTIMER_NORESTART;
-}
-
-/**
- * ap_reset(): Reset a not responding AP device.
- * @ap_dev: Pointer to the AP device
- *
- * Reset a not responding AP device and move all requests from the
- * pending queue to the request queue.
- */
-static void ap_reset(struct ap_device *ap_dev, unsigned long *flags)
-{
- int rc;
-
- atomic_sub(ap_dev->queue_count, &ap_poll_requests);
- ap_dev->queue_count = 0;
- list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
- ap_dev->requestq_count += ap_dev->pendingq_count;
- ap_dev->pendingq_count = 0;
- rc = ap_init_queue(ap_dev);
- if (rc == -ENODEV)
- ap_dev->unregistered = 1;
- else
- *flags |= AP_POLL_AFTER_TIMEOUT;
-}
-
-static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
-{
- if (!ap_dev->unregistered) {
- if (ap_poll_queue(ap_dev, flags))
- ap_dev->unregistered = 1;
- if (ap_dev->reset == AP_RESET_DO)
- ap_reset(ap_dev, flags);
- }
- return 0;
-}
-
-/**
- * ap_poll_all(): Poll all AP devices.
- * @dummy: Unused variable
- *
- * Poll all AP devices on the bus in a round robin fashion. Continue
- * polling until bit 2^0 of the control flags is not set. If bit 2^1
- * of the control flags has been set arm the poll timer.
- */
-static void ap_poll_all(unsigned long dummy)
-{
- unsigned long flags;
- struct ap_device *ap_dev;
-
- /* Reset the indicator if interrupts are used. Thus new interrupts can
- * be received. Doing it in the beginning of the tasklet is therefor
- * important that no requests on any AP get lost.
- */
- if (ap_using_interrupts())
- xchg(ap_airq.lsi_ptr, 0);
- do {
- flags = 0;
- spin_lock(&ap_device_list_lock);
- list_for_each_entry(ap_dev, &ap_device_list, list) {
- spin_lock(&ap_dev->lock);
- __ap_poll_device(ap_dev, &flags);
- spin_unlock(&ap_dev->lock);
- }
- spin_unlock(&ap_device_list_lock);
- } while (flags & AP_POLL_IMMEDIATELY);
- if (flags & AP_POLL_AFTER_TIMEOUT)
- __ap_schedule_poll_timer();
-}
-
-/**
- * ap_poll_thread(): Thread that polls for finished requests.
- * @data: Unused pointer
- *
- * AP bus poll thread. The purpose of this thread is to poll for
- * finished requests in a loop if there is a "free" cpu - that is
- * a cpu that doesn't have anything better to do. The polling stops
- * as soon as there is another task or if all messages have been
- * delivered.
- */
-static int ap_poll_thread(void *data)
-{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- int requests;
- struct ap_device *ap_dev;
-
- set_user_nice(current, MAX_NICE);
- while (1) {
- if (ap_suspend_flag)
- return 0;
- if (need_resched()) {
- schedule();
continue;
}
- add_wait_queue(&ap_poll_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- if (kthread_should_stop())
- break;
- requests = atomic_read(&ap_poll_requests);
- if (requests <= 0)
- schedule();
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ap_poll_wait, &wait);
-
- flags = 0;
- spin_lock_bh(&ap_device_list_lock);
- list_for_each_entry(ap_dev, &ap_device_list, list) {
- spin_lock(&ap_dev->lock);
- __ap_poll_device(ap_dev, &flags);
- spin_unlock(&ap_dev->lock);
- }
- spin_unlock_bh(&ap_device_list_lock);
}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ap_poll_wait, &wait);
- return 0;
-}
-
-static int ap_poll_thread_start(void)
-{
- int rc;
-
- if (ap_using_interrupts() || ap_suspend_flag)
- return 0;
- mutex_lock(&ap_poll_thread_mutex);
- if (!ap_poll_kthread) {
- ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
- rc = PTR_RET(ap_poll_kthread);
- if (rc)
- ap_poll_kthread = NULL;
- }
- else
- rc = 0;
- mutex_unlock(&ap_poll_thread_mutex);
- return rc;
-}
-
-static void ap_poll_thread_stop(void)
-{
- mutex_lock(&ap_poll_thread_mutex);
- if (ap_poll_kthread) {
- kthread_stop(ap_poll_kthread);
- ap_poll_kthread = NULL;
- }
- mutex_unlock(&ap_poll_thread_mutex);
+out:
+ mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
}
-/**
- * ap_request_timeout(): Handling of request timeouts
- * @data: Holds the AP device.
- *
- * Handles request timeouts.
- */
-static void ap_request_timeout(unsigned long data)
+static void ap_config_timeout(unsigned long ptr)
{
- struct ap_device *ap_dev = (struct ap_device *) data;
-
- if (ap_dev->reset == AP_RESET_ARMED) {
- ap_dev->reset = AP_RESET_DO;
-
- if (ap_using_interrupts())
- tasklet_schedule(&ap_tasklet);
- }
+ if (ap_suspend_flag)
+ return;
+ queue_work(system_long_wq, &ap_scan_work);
}
static void ap_reset_domain(void)
{
int i;
- if ((ap_domain_index != -1) && (ap_test_config_domain(ap_domain_index)))
- for (i = 0; i < AP_DEVICES; i++)
- ap_reset_queue(AP_MKQID(i, ap_domain_index));
+ if (ap_domain_index == -1 || !ap_test_config_domain(ap_domain_index))
+ return;
+ for (i = 0; i < AP_DEVICES; i++)
+ ap_reset_queue(AP_MKQID(i, ap_domain_index));
}
static void ap_reset_all(void)
@@ -2009,11 +1738,24 @@ static struct reset_call ap_reset_call = {
*/
int __init ap_module_init(void)
{
+ int max_domain_id;
int rc, i;
- if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
- pr_warning("%d is not a valid cryptographic domain\n",
- ap_domain_index);
+ if (ap_instructions_available() != 0) {
+ pr_warn("The hardware system does not support AP instructions\n");
+ return -ENODEV;
+ }
+
+ /* Get AP configuration data if available */
+ ap_init_configuration();
+
+ if (ap_configuration)
+ max_domain_id = ap_max_domain_id ? : (AP_DOMAINS - 1);
+ else
+ max_domain_id = 15;
+ if (ap_domain_index < -1 || ap_domain_index > max_domain_id) {
+ pr_warn("%d is not a valid cryptographic domain\n",
+ ap_domain_index);
return -EINVAL;
}
/* In resume callback we need to know if the user had set the domain.
@@ -2022,11 +1764,6 @@ int __init ap_module_init(void)
if (ap_domain_index >= 0)
user_set_domain = 1;
- if (ap_instructions_available() != 0) {
- pr_warning("The hardware system does not support "
- "AP instructions\n");
- return -ENODEV;
- }
if (ap_interrupts_available()) {
rc = register_adapter_interrupt(&ap_airq);
ap_airq_flag = (rc == 0);
@@ -2050,24 +1787,11 @@ int __init ap_module_init(void)
if (rc)
goto out_bus;
- ap_work_queue = create_singlethread_workqueue("kapwork");
- if (!ap_work_queue) {
- rc = -ENOMEM;
- goto out_root;
- }
-
- ap_query_configuration();
- if (ap_select_domain() == 0)
- ap_scan_bus(NULL);
-
/* Setup the AP bus rescan timer. */
- init_timer(&ap_config_timer);
- ap_config_timer.function = ap_config_timeout;
- ap_config_timer.data = 0;
- ap_config_timer.expires = jiffies + ap_config_time * HZ;
- add_timer(&ap_config_timer);
+ setup_timer(&ap_config_timer, ap_config_timeout, 0);
- /* Setup the high resultion poll timer.
+ /*
+ * Setup the high resultion poll timer.
* If we are running under z/VM adjust polling to z/VM polling rate.
*/
if (MACHINE_IS_VM)
@@ -2083,13 +1807,19 @@ int __init ap_module_init(void)
goto out_work;
}
+ rc = register_pm_notifier(&ap_power_notifier);
+ if (rc)
+ goto out_pm;
+
+ queue_work(system_long_wq, &ap_scan_work);
+ initialised = true;
+
return 0;
+out_pm:
+ ap_poll_thread_stop();
out_work:
- del_timer_sync(&ap_config_timer);
hrtimer_cancel(&ap_poll_timer);
- destroy_workqueue(ap_work_queue);
-out_root:
root_device_unregister(ap_root_device);
out_bus:
while (i--)
@@ -2099,14 +1829,10 @@ out:
unregister_reset_call(&ap_reset_call);
if (ap_using_interrupts())
unregister_adapter_interrupt(&ap_airq);
+ kfree(ap_configuration);
return rc;
}
-static int __ap_match_all(struct device *dev, void *data)
-{
- return 1;
-}
-
/**
* ap_modules_exit(): The module termination code
*
@@ -2115,24 +1841,20 @@ static int __ap_match_all(struct device *dev, void *data)
void ap_module_exit(void)
{
int i;
- struct device *dev;
+ initialised = false;
ap_reset_domain();
ap_poll_thread_stop();
del_timer_sync(&ap_config_timer);
hrtimer_cancel(&ap_poll_timer);
- destroy_workqueue(ap_work_queue);
tasklet_kill(&ap_tasklet);
- while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
- __ap_match_all)))
- {
- device_unregister(dev);
- put_device(dev);
- }
+ bus_for_each_dev(&ap_bus_type, NULL, NULL, __ap_devices_unregister);
for (i = 0; ap_bus_attrs[i]; i++)
bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
+ unregister_pm_notifier(&ap_power_notifier);
root_device_unregister(ap_root_device);
bus_unregister(&ap_bus_type);
+ kfree(ap_configuration);
unregister_reset_call(&ap_reset_call);
if (ap_using_interrupts())
unregister_adapter_interrupt(&ap_airq);
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 00468c8d0781..6adcbdf225d1 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -36,9 +36,6 @@
#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */
#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */
-#define AP_POLL_IMMEDIATELY 1 /* continue running poll tasklet */
-#define AP_POLL_AFTER_TIMEOUT 2 /* run poll tasklet again after timout */
-
extern int ap_domain_index;
/**
@@ -75,21 +72,9 @@ struct ap_queue_status {
unsigned int pad2 : 16;
} __packed;
-#define AP_QUEUE_STATUS_INVALID \
- { 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
-
-static inline
-int ap_queue_status_invalid_test(struct ap_queue_status *status)
-{
- struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
- return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
-}
-#define AP_MAX_BITS 31
static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
{
- if (nr > AP_MAX_BITS)
- return 0;
return (*ptr & (0x80000000u >> nr)) != 0;
}
@@ -132,19 +117,45 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_FUNC_APXA 6
/*
- * AP reset flag states
- */
-#define AP_RESET_IGNORE 0 /* request timeout will be ignored */
-#define AP_RESET_ARMED 1 /* request timeout timer is active */
-#define AP_RESET_DO 2 /* AP reset required */
-#define AP_RESET_IN_PROGRESS 3 /* AP reset in progress */
-
-/*
* AP interrupt states
*/
#define AP_INTR_DISABLED 0 /* AP interrupt disabled */
#define AP_INTR_ENABLED 1 /* AP interrupt enabled */
-#define AP_INTR_IN_PROGRESS 3 /* AP interrupt in progress */
+
+/*
+ * AP device states
+ */
+enum ap_state {
+ AP_STATE_RESET_START,
+ AP_STATE_RESET_WAIT,
+ AP_STATE_SETIRQ_WAIT,
+ AP_STATE_IDLE,
+ AP_STATE_WORKING,
+ AP_STATE_QUEUE_FULL,
+ AP_STATE_SUSPEND_WAIT,
+ AP_STATE_BORKED,
+ NR_AP_STATES
+};
+
+/*
+ * AP device events
+ */
+enum ap_event {
+ AP_EVENT_POLL,
+ AP_EVENT_TIMEOUT,
+ NR_AP_EVENTS
+};
+
+/*
+ * AP wait behaviour
+ */
+enum ap_wait {
+ AP_WAIT_AGAIN, /* retry immediately */
+ AP_WAIT_TIMEOUT, /* wait for timeout */
+ AP_WAIT_INTERRUPT, /* wait for thin interrupt (if available) */
+ AP_WAIT_NONE, /* no wait */
+ NR_AP_WAIT
+};
struct ap_device;
struct ap_message;
@@ -163,20 +174,22 @@ struct ap_driver {
int ap_driver_register(struct ap_driver *, struct module *, char *);
void ap_driver_unregister(struct ap_driver *);
+typedef enum ap_wait (ap_func_t)(struct ap_device *ap_dev);
+
struct ap_device {
struct device device;
struct ap_driver *drv; /* Pointer to AP device driver. */
spinlock_t lock; /* Per device lock. */
struct list_head list; /* private list of all AP devices. */
+ enum ap_state state; /* State of the AP device. */
+
ap_qid_t qid; /* AP queue id. */
int queue_depth; /* AP queue depth.*/
int device_type; /* AP device type. */
int raw_hwtype; /* AP raw hardware type. */
unsigned int functions; /* AP device function bitfield. */
- int unregistered; /* marks AP device as unregistered */
struct timer_list timeout; /* Timer for request timeouts. */
- int reset; /* Reset required after req. timeout. */
int interrupt; /* indicate if interrupts are enabled */
int queue_count; /* # messages currently on AP queue. */
@@ -199,6 +212,7 @@ struct ap_message {
unsigned long long psmid; /* Message id. */
void *message; /* Pointer to message buffer. */
size_t length; /* Message length. */
+ int rc; /* Return code for this message */
void *private; /* ap driver private pointer. */
unsigned int special:1; /* Used for special commands. */
@@ -231,6 +245,7 @@ static inline void ap_init_message(struct ap_message *ap_msg)
{
ap_msg->psmid = 0;
ap_msg->length = 0;
+ ap_msg->rc = 0;
ap_msg->special = 0;
ap_msg->receive = NULL;
}
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 4eb45546a3aa..9f8fa42c062c 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -317,11 +317,9 @@ EXPORT_SYMBOL(zcrypt_device_unregister);
void zcrypt_msgtype_register(struct zcrypt_ops *zops)
{
- if (zops->owner) {
- spin_lock_bh(&zcrypt_ops_list_lock);
- list_add_tail(&zops->list, &zcrypt_ops_list);
- spin_unlock_bh(&zcrypt_ops_list_lock);
- }
+ spin_lock_bh(&zcrypt_ops_list_lock);
+ list_add_tail(&zops->list, &zcrypt_ops_list);
+ spin_unlock_bh(&zcrypt_ops_list_lock);
}
EXPORT_SYMBOL(zcrypt_msgtype_register);
@@ -342,7 +340,7 @@ struct zcrypt_ops *__ops_lookup(unsigned char *name, int variant)
spin_lock_bh(&zcrypt_ops_list_lock);
list_for_each_entry(zops, &zcrypt_ops_list, list) {
if ((zops->variant == variant) &&
- (!strncmp(zops->owner->name, name, MODULE_NAME_LEN))) {
+ (!strncmp(zops->name, name, sizeof(zops->name)))) {
found = 1;
break;
}
@@ -472,8 +470,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
unsigned long long z1, z2, z3;
int rc, copied;
- if (crt->outputdatalength < crt->inputdatalength ||
- (crt->inputdatalength & 1))
+ if (crt->outputdatalength < crt->inputdatalength)
return -EINVAL;
/*
* As long as outputdatalength is big enough, we can set the
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 750876891931..38618f05ad92 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -96,6 +96,7 @@ struct zcrypt_ops {
struct list_head list; /* zcrypt ops list. */
struct module *owner;
int variant;
+ char name[128];
};
struct zcrypt_device {
diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h
index 1f42f103c761..ca0cdbe46368 100644
--- a/drivers/s390/crypto/zcrypt_cca_key.h
+++ b/drivers/s390/crypto/zcrypt_cca_key.h
@@ -291,7 +291,7 @@ static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt,
memset(key, 0, sizeof(*key));
- short_len = crt->inputdatalength / 2;
+ short_len = (crt->inputdatalength + 1) / 2;
long_len = short_len + 8;
pad_len = -(3*long_len + 2*short_len) & 7;
key_len = 3*long_len + 2*short_len + pad_len + crt->inputdatalength;
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c
index 334e282f255b..74edf2934e7c 100644
--- a/drivers/s390/crypto/zcrypt_msgtype50.c
+++ b/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -248,7 +248,7 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev,
unsigned char *p, *q, *dp, *dq, *u, *inp;
mod_len = crt->inputdatalength;
- short_len = mod_len / 2;
+ short_len = (mod_len + 1) / 2;
/*
* CEX2A and CEX3A w/o FW update can handle requests up to
@@ -395,10 +395,8 @@ static void zcrypt_cex2a_receive(struct ap_device *ap_dev,
int length;
/* Copy the reply message to the request message buffer. */
- if (IS_ERR(reply)) {
- memcpy(msg->message, &error_reply, sizeof(error_reply));
- goto out;
- }
+ if (!reply)
+ goto out; /* ap_msg->rc indicates the error */
t80h = reply->message;
if (t80h->type == TYPE80_RSP_CODE) {
if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A)
@@ -449,10 +447,12 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&work);
- if (rc == 0)
- rc = convert_response(zdev, &ap_msg, mex->outputdata,
- mex->outputdatalength);
- else
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response(zdev, &ap_msg, mex->outputdata,
+ mex->outputdatalength);
+ } else
/* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
out_free:
@@ -493,10 +493,12 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&work);
- if (rc == 0)
- rc = convert_response(zdev, &ap_msg, crt->outputdata,
- crt->outputdatalength);
- else
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response(zdev, &ap_msg, crt->outputdata,
+ crt->outputdatalength);
+ } else
/* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
out_free:
@@ -511,6 +513,7 @@ static struct zcrypt_ops zcrypt_msgtype50_ops = {
.rsa_modexpo = zcrypt_cex2a_modexpo,
.rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt,
.owner = THIS_MODULE,
+ .name = MSGTYPE50_NAME,
.variant = MSGTYPE50_VARIANT_DEFAULT,
};
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 46b324ce6c7a..9a2dd472c1cc 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -829,10 +829,8 @@ static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
int length;
/* Copy the reply message to the request message buffer. */
- if (IS_ERR(reply)) {
- memcpy(msg->message, &error_reply, sizeof(error_reply));
- goto out;
- }
+ if (!reply)
+ goto out; /* ap_msg->rc indicates the error */
t86r = reply->message;
if (t86r->hdr.type == TYPE86_RSP_CODE &&
t86r->cprbx.cprb_ver_id == 0x02) {
@@ -880,10 +878,8 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
int length;
/* Copy the reply message to the request message buffer. */
- if (IS_ERR(reply)) {
- memcpy(msg->message, &error_reply, sizeof(error_reply));
- goto out;
- }
+ if (!reply)
+ goto out; /* ap_msg->rc indicates the error */
t86r = reply->message;
if (t86r->hdr.type == TYPE86_RSP_CODE &&
t86r->cprbx.cprb_ver_id == 0x04) {
@@ -935,10 +931,13 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&resp_type.work);
- if (rc == 0)
- rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
- mex->outputdatalength);
- else
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response_ica(zdev, &ap_msg,
+ mex->outputdata,
+ mex->outputdatalength);
+ } else
/* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
out_free:
@@ -976,10 +975,13 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&resp_type.work);
- if (rc == 0)
- rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
- crt->outputdatalength);
- else
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response_ica(zdev, &ap_msg,
+ crt->outputdata,
+ crt->outputdatalength);
+ } else
/* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
out_free:
@@ -1017,9 +1019,11 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&resp_type.work);
- if (rc == 0)
- rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
- else
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
+ } else
/* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
out_free:
@@ -1057,9 +1061,12 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&resp_type.work);
- if (rc == 0)
- rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
- else /* Signal pending. */
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
+ } else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
out_free:
@@ -1096,9 +1103,11 @@ static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible(&resp_type.work);
- if (rc == 0)
- rc = convert_response_rng(zdev, &ap_msg, buffer);
- else
+ if (rc == 0) {
+ rc = ap_msg.rc;
+ if (rc == 0)
+ rc = convert_response_rng(zdev, &ap_msg, buffer);
+ } else
/* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
kfree(ap_msg.message);
@@ -1110,6 +1119,7 @@ static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
*/
static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
.owner = THIS_MODULE,
+ .name = MSGTYPE06_NAME,
.variant = MSGTYPE06_VARIANT_NORNG,
.rsa_modexpo = zcrypt_msgtype6_modexpo,
.rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
@@ -1118,6 +1128,7 @@ static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
static struct zcrypt_ops zcrypt_msgtype6_ops = {
.owner = THIS_MODULE,
+ .name = MSGTYPE06_NAME,
.variant = MSGTYPE06_VARIANT_DEFAULT,
.rsa_modexpo = zcrypt_msgtype6_modexpo,
.rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
@@ -1127,6 +1138,7 @@ static struct zcrypt_ops zcrypt_msgtype6_ops = {
static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = {
.owner = THIS_MODULE,
+ .name = MSGTYPE06_NAME,
.variant = MSGTYPE06_VARIANT_EP11,
.rsa_modexpo = NULL,
.rsa_modexpo_crt = NULL,
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
deleted file mode 100644
index 7a743f4c646c..000000000000
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * zcrypt 2.1.0
- *
- * Copyright IBM Corp. 2001, 2006
- * Author(s): Robert Burroughs
- * Eric Rossman (edrossma@us.ibm.com)
- *
- * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
- * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
- * Ralph Wuerthner <rwuerthn@de.ibm.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, 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 KMSG_COMPONENT "zcrypt"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/atomic.h>
-#include <asm/uaccess.h>
-
-#include "ap_bus.h"
-#include "zcrypt_api.h"
-#include "zcrypt_error.h"
-#include "zcrypt_pcica.h"
-
-#define PCICA_MIN_MOD_SIZE 1 /* 8 bits */
-#define PCICA_MAX_MOD_SIZE 256 /* 2048 bits */
-
-#define PCICA_SPEED_RATING 2800
-
-#define PCICA_MAX_MESSAGE_SIZE 0x3a0 /* sizeof(struct type4_lcr) */
-#define PCICA_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */
-
-#define PCICA_CLEANUP_TIME (15*HZ)
-
-static struct ap_device_id zcrypt_pcica_ids[] = {
- { AP_DEVICE(AP_DEVICE_TYPE_PCICA) },
- { /* end of list */ },
-};
-
-MODULE_DEVICE_TABLE(ap, zcrypt_pcica_ids);
-MODULE_AUTHOR("IBM Corporation");
-MODULE_DESCRIPTION("PCICA Cryptographic Coprocessor device driver, "
- "Copyright IBM Corp. 2001, 2006");
-MODULE_LICENSE("GPL");
-
-static int zcrypt_pcica_probe(struct ap_device *ap_dev);
-static void zcrypt_pcica_remove(struct ap_device *ap_dev);
-static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *,
- struct ap_message *);
-
-static struct ap_driver zcrypt_pcica_driver = {
- .probe = zcrypt_pcica_probe,
- .remove = zcrypt_pcica_remove,
- .ids = zcrypt_pcica_ids,
- .request_timeout = PCICA_CLEANUP_TIME,
-};
-
-/**
- * Convert a ICAMEX message to a type4 MEX message.
- *
- * @zdev: crypto device pointer
- * @zreq: crypto request pointer
- * @mex: pointer to user input data
- *
- * Returns 0 on success or -EFAULT.
- */
-static int ICAMEX_msg_to_type4MEX_msg(struct zcrypt_device *zdev,
- struct ap_message *ap_msg,
- struct ica_rsa_modexpo *mex)
-{
- unsigned char *modulus, *exponent, *message;
- int mod_len;
-
- mod_len = mex->inputdatalength;
-
- if (mod_len <= 128) {
- struct type4_sme *sme = ap_msg->message;
- memset(sme, 0, sizeof(*sme));
- ap_msg->length = sizeof(*sme);
- sme->header.msg_fmt = TYPE4_SME_FMT;
- sme->header.msg_len = sizeof(*sme);
- sme->header.msg_type_code = TYPE4_TYPE_CODE;
- sme->header.request_code = TYPE4_REQU_CODE;
- modulus = sme->modulus + sizeof(sme->modulus) - mod_len;
- exponent = sme->exponent + sizeof(sme->exponent) - mod_len;
- message = sme->message + sizeof(sme->message) - mod_len;
- } else {
- struct type4_lme *lme = ap_msg->message;
- memset(lme, 0, sizeof(*lme));
- ap_msg->length = sizeof(*lme);
- lme->header.msg_fmt = TYPE4_LME_FMT;
- lme->header.msg_len = sizeof(*lme);
- lme->header.msg_type_code = TYPE4_TYPE_CODE;
- lme->header.request_code = TYPE4_REQU_CODE;
- modulus = lme->modulus + sizeof(lme->modulus) - mod_len;
- exponent = lme->exponent + sizeof(lme->exponent) - mod_len;
- message = lme->message + sizeof(lme->message) - mod_len;
- }
-
- if (copy_from_user(modulus, mex->n_modulus, mod_len) ||
- copy_from_user(exponent, mex->b_key, mod_len) ||
- copy_from_user(message, mex->inputdata, mod_len))
- return -EFAULT;
- return 0;
-}
-
-/**
- * Convert a ICACRT message to a type4 CRT message.
- *
- * @zdev: crypto device pointer
- * @zreq: crypto request pointer
- * @crt: pointer to user input data
- *
- * Returns 0 on success or -EFAULT.
- */
-static int ICACRT_msg_to_type4CRT_msg(struct zcrypt_device *zdev,
- struct ap_message *ap_msg,
- struct ica_rsa_modexpo_crt *crt)
-{
- unsigned char *p, *q, *dp, *dq, *u, *inp;
- int mod_len, short_len, long_len;
-
- mod_len = crt->inputdatalength;
- short_len = mod_len / 2;
- long_len = mod_len / 2 + 8;
-
- if (mod_len <= 128) {
- struct type4_scr *scr = ap_msg->message;
- memset(scr, 0, sizeof(*scr));
- ap_msg->length = sizeof(*scr);
- scr->header.msg_type_code = TYPE4_TYPE_CODE;
- scr->header.request_code = TYPE4_REQU_CODE;
- scr->header.msg_fmt = TYPE4_SCR_FMT;
- scr->header.msg_len = sizeof(*scr);
- p = scr->p + sizeof(scr->p) - long_len;
- q = scr->q + sizeof(scr->q) - short_len;
- dp = scr->dp + sizeof(scr->dp) - long_len;
- dq = scr->dq + sizeof(scr->dq) - short_len;
- u = scr->u + sizeof(scr->u) - long_len;
- inp = scr->message + sizeof(scr->message) - mod_len;
- } else {
- struct type4_lcr *lcr = ap_msg->message;
- memset(lcr, 0, sizeof(*lcr));
- ap_msg->length = sizeof(*lcr);
- lcr->header.msg_type_code = TYPE4_TYPE_CODE;
- lcr->header.request_code = TYPE4_REQU_CODE;
- lcr->header.msg_fmt = TYPE4_LCR_FMT;
- lcr->header.msg_len = sizeof(*lcr);
- p = lcr->p + sizeof(lcr->p) - long_len;
- q = lcr->q + sizeof(lcr->q) - short_len;
- dp = lcr->dp + sizeof(lcr->dp) - long_len;
- dq = lcr->dq + sizeof(lcr->dq) - short_len;
- u = lcr->u + sizeof(lcr->u) - long_len;
- inp = lcr->message + sizeof(lcr->message) - mod_len;
- }
-
- if (copy_from_user(p, crt->np_prime, long_len) ||
- copy_from_user(q, crt->nq_prime, short_len) ||
- copy_from_user(dp, crt->bp_key, long_len) ||
- copy_from_user(dq, crt->bq_key, short_len) ||
- copy_from_user(u, crt->u_mult_inv, long_len) ||
- copy_from_user(inp, crt->inputdata, mod_len))
- return -EFAULT;
- return 0;
-}
-
-/**
- * Copy results from a type 84 reply message back to user space.
- *
- * @zdev: crypto device pointer
- * @reply: reply AP message.
- * @data: pointer to user output data
- * @length: size of user output data
- *
- * Returns 0 on success or -EFAULT.
- */
-static int convert_type84(struct zcrypt_device *zdev,
- struct ap_message *reply,
- char __user *outputdata,
- unsigned int outputdatalength)
-{
- struct type84_hdr *t84h = reply->message;
- char *data;
-
- if (t84h->len < sizeof(*t84h) + outputdatalength) {
- /* The result is too short, the PCICA card may not do that.. */
- zdev->online = 0;
- pr_err("Cryptographic device %x failed and was set offline\n",
- zdev->ap_dev->qid);
- ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
- zdev->ap_dev->qid, zdev->online, t84h->code);
- return -EAGAIN; /* repeat the request on a different device. */
- }
- BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE);
- data = reply->message + t84h->len - outputdatalength;
- if (copy_to_user(outputdata, data, outputdatalength))
- return -EFAULT;
- return 0;
-}
-
-static int convert_response(struct zcrypt_device *zdev,
- struct ap_message *reply,
- char __user *outputdata,
- unsigned int outputdatalength)
-{
- /* Response type byte is the second byte in the response. */
- switch (((unsigned char *) reply->message)[1]) {
- case TYPE82_RSP_CODE:
- case TYPE88_RSP_CODE:
- return convert_error(zdev, reply);
- case TYPE84_RSP_CODE:
- return convert_type84(zdev, reply,
- outputdata, outputdatalength);
- default: /* Unknown response type, this should NEVER EVER happen */
- zdev->online = 0;
- pr_err("Cryptographic device %x failed and was set offline\n",
- zdev->ap_dev->qid);
- ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
- zdev->ap_dev->qid, zdev->online);
- return -EAGAIN; /* repeat the request on a different device. */
- }
-}
-
-/**
- * This function is called from the AP bus code after a crypto request
- * "msg" has finished with the reply message "reply".
- * It is called from tasklet context.
- * @ap_dev: pointer to the AP device
- * @msg: pointer to the AP message
- * @reply: pointer to the AP reply message
- */
-static void zcrypt_pcica_receive(struct ap_device *ap_dev,
- struct ap_message *msg,
- struct ap_message *reply)
-{
- static struct error_hdr error_reply = {
- .type = TYPE82_RSP_CODE,
- .reply_code = REP82_ERROR_MACHINE_FAILURE,
- };
- struct type84_hdr *t84h;
- int length;
-
- /* Copy the reply message to the request message buffer. */
- if (IS_ERR(reply)) {
- memcpy(msg->message, &error_reply, sizeof(error_reply));
- goto out;
- }
- t84h = reply->message;
- if (t84h->code == TYPE84_RSP_CODE) {
- length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len);
- memcpy(msg->message, reply->message, length);
- } else
- memcpy(msg->message, reply->message, sizeof error_reply);
-out:
- complete((struct completion *) msg->private);
-}
-
-static atomic_t zcrypt_step = ATOMIC_INIT(0);
-
-/**
- * The request distributor calls this function if it picked the PCICA
- * device to handle a modexpo request.
- * @zdev: pointer to zcrypt_device structure that identifies the
- * PCICA device to the request distributor
- * @mex: pointer to the modexpo request buffer
- */
-static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
- struct ica_rsa_modexpo *mex)
-{
- struct ap_message ap_msg;
- struct completion work;
- int rc;
-
- ap_init_message(&ap_msg);
- ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
- if (!ap_msg.message)
- return -ENOMEM;
- ap_msg.receive = zcrypt_pcica_receive;
- ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
- atomic_inc_return(&zcrypt_step);
- ap_msg.private = &work;
- rc = ICAMEX_msg_to_type4MEX_msg(zdev, &ap_msg, mex);
- if (rc)
- goto out_free;
- init_completion(&work);
- ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible(&work);
- if (rc == 0)
- rc = convert_response(zdev, &ap_msg, mex->outputdata,
- mex->outputdatalength);
- else
- /* Signal pending. */
- ap_cancel_message(zdev->ap_dev, &ap_msg);
-out_free:
- kfree(ap_msg.message);
- return rc;
-}
-
-/**
- * The request distributor calls this function if it picked the PCICA
- * device to handle a modexpo_crt request.
- * @zdev: pointer to zcrypt_device structure that identifies the
- * PCICA device to the request distributor
- * @crt: pointer to the modexpoc_crt request buffer
- */
-static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
- struct ica_rsa_modexpo_crt *crt)
-{
- struct ap_message ap_msg;
- struct completion work;
- int rc;
-
- ap_init_message(&ap_msg);
- ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
- if (!ap_msg.message)
- return -ENOMEM;
- ap_msg.receive = zcrypt_pcica_receive;
- ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
- atomic_inc_return(&zcrypt_step);
- ap_msg.private = &work;
- rc = ICACRT_msg_to_type4CRT_msg(zdev, &ap_msg, crt);
- if (rc)
- goto out_free;
- init_completion(&work);
- ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible(&work);
- if (rc == 0)
- rc = convert_response(zdev, &ap_msg, crt->outputdata,
- crt->outputdatalength);
- else
- /* Signal pending. */
- ap_cancel_message(zdev->ap_dev, &ap_msg);
-out_free:
- kfree(ap_msg.message);
- return rc;
-}
-
-/**
- * The crypto operations for a PCICA card.
- */
-static struct zcrypt_ops zcrypt_pcica_ops = {
- .rsa_modexpo = zcrypt_pcica_modexpo,
- .rsa_modexpo_crt = zcrypt_pcica_modexpo_crt,
-};
-
-/**
- * Probe function for PCICA cards. It always accepts the AP device
- * since the bus_match already checked the hardware type.
- * @ap_dev: pointer to the AP device.
- */
-static int zcrypt_pcica_probe(struct ap_device *ap_dev)
-{
- struct zcrypt_device *zdev;
- int rc;
-
- zdev = zcrypt_device_alloc(PCICA_MAX_RESPONSE_SIZE);
- if (!zdev)
- return -ENOMEM;
- zdev->ap_dev = ap_dev;
- zdev->ops = &zcrypt_pcica_ops;
- zdev->online = 1;
- zdev->user_space_type = ZCRYPT_PCICA;
- zdev->type_string = "PCICA";
- zdev->min_mod_size = PCICA_MIN_MOD_SIZE;
- zdev->max_mod_size = PCICA_MAX_MOD_SIZE;
- zdev->speed_rating = PCICA_SPEED_RATING;
- zdev->max_exp_bit_length = PCICA_MAX_MOD_SIZE;
- ap_dev->reply = &zdev->reply;
- ap_dev->private = zdev;
- rc = zcrypt_device_register(zdev);
- if (rc)
- goto out_free;
- return 0;
-
-out_free:
- ap_dev->private = NULL;
- zcrypt_device_free(zdev);
- return rc;
-}
-
-/**
- * This is called to remove the extended PCICA driver information
- * if an AP device is removed.
- */
-static void zcrypt_pcica_remove(struct ap_device *ap_dev)
-{
- struct zcrypt_device *zdev = ap_dev->private;
-
- zcrypt_device_unregister(zdev);
-}
-
-int __init zcrypt_pcica_init(void)
-{
- return ap_driver_register(&zcrypt_pcica_driver, THIS_MODULE, "pcica");
-}
-
-void zcrypt_pcica_exit(void)
-{
- ap_driver_unregister(&zcrypt_pcica_driver);
-}
-
-module_init(zcrypt_pcica_init);
-module_exit(zcrypt_pcica_exit);
diff --git a/drivers/s390/crypto/zcrypt_pcica.h b/drivers/s390/crypto/zcrypt_pcica.h
deleted file mode 100644
index 9a59155cad51..000000000000
--- a/drivers/s390/crypto/zcrypt_pcica.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * zcrypt 2.1.0
- *
- * Copyright IBM Corp. 2001, 2006
- * Author(s): Robert Burroughs
- * Eric Rossman (edrossma@us.ibm.com)
- *
- * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
- * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.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, 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.
- */
-
-#ifndef _ZCRYPT_PCICA_H_
-#define _ZCRYPT_PCICA_H_
-
-/**
- * The type 4 message family is associated with a PCICA card.
- *
- * The four members of the family are described below.
- *
- * Note that all unsigned char arrays are right-justified and left-padded
- * with zeroes.
- *
- * Note that all reserved fields must be zeroes.
- */
-struct type4_hdr {
- unsigned char reserved1;
- unsigned char msg_type_code; /* 0x04 */
- unsigned short msg_len;
- unsigned char request_code; /* 0x40 */
- unsigned char msg_fmt;
- unsigned short reserved2;
-} __attribute__((packed));
-
-#define TYPE4_TYPE_CODE 0x04
-#define TYPE4_REQU_CODE 0x40
-
-#define TYPE4_SME_FMT 0x00
-#define TYPE4_LME_FMT 0x10
-#define TYPE4_SCR_FMT 0x40
-#define TYPE4_LCR_FMT 0x50
-
-/* Mod-Exp, with a small modulus */
-struct type4_sme {
- struct type4_hdr header;
- unsigned char message[128];
- unsigned char exponent[128];
- unsigned char modulus[128];
-} __attribute__((packed));
-
-/* Mod-Exp, with a large modulus */
-struct type4_lme {
- struct type4_hdr header;
- unsigned char message[256];
- unsigned char exponent[256];
- unsigned char modulus[256];
-} __attribute__((packed));
-
-/* CRT, with a small modulus */
-struct type4_scr {
- struct type4_hdr header;
- unsigned char message[128];
- unsigned char dp[72];
- unsigned char dq[64];
- unsigned char p[72];
- unsigned char q[64];
- unsigned char u[72];
-} __attribute__((packed));
-
-/* CRT, with a large modulus */
-struct type4_lcr {
- struct type4_hdr header;
- unsigned char message[256];
- unsigned char dp[136];
- unsigned char dq[128];
- unsigned char p[136];
- unsigned char q[128];
- unsigned char u[136];
-} __attribute__((packed));
-
-/**
- * The type 84 response family is associated with a PCICA card.
- *
- * Note that all unsigned char arrays are right-justified and left-padded
- * with zeroes.
- *
- * Note that all reserved fields must be zeroes.
- */
-
-struct type84_hdr {
- unsigned char reserved1;
- unsigned char code;
- unsigned short len;
- unsigned char reserved2[4];
-} __attribute__((packed));
-
-#define TYPE84_RSP_CODE 0x84
-
-int zcrypt_pcica_init(void);
-void zcrypt_pcica_exit(void);
-
-#endif /* _ZCRYPT_PCICA_H_ */
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
deleted file mode 100644
index 9f18876f058b..000000000000
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * zcrypt 2.1.0
- *
- * Copyright IBM Corp. 2001, 2006
- * Author(s): Robert Burroughs
- * Eric Rossman (edrossma@us.ibm.com)
- *
- * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
- * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
- * Ralph Wuerthner <rwuerthn@de.ibm.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, 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 KMSG_COMPONENT "zcrypt"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/gfp.h>
-#include <linux/err.h>
-#include <linux/atomic.h>
-#include <asm/uaccess.h>
-
-#include "ap_bus.h"
-#include "zcrypt_api.h"
-#include "zcrypt_error.h"
-#include "zcrypt_pcicc.h"
-#include "zcrypt_cca_key.h"
-
-#define PCICC_MIN_MOD_SIZE 64 /* 512 bits */
-#define PCICC_MAX_MOD_SIZE_OLD 128 /* 1024 bits */
-#define PCICC_MAX_MOD_SIZE 256 /* 2048 bits */
-
-/*
- * PCICC cards need a speed rating of 0. This keeps them at the end of
- * the zcrypt device list (see zcrypt_api.c). PCICC cards are only
- * used if no other cards are present because they are slow and can only
- * cope with PKCS12 padded requests. The logic is queer. PKCS11 padded
- * requests are rejected. The modexpo function encrypts PKCS12 padded data
- * and decrypts any non-PKCS12 padded data (except PKCS11) in the assumption
- * that it's encrypted PKCS12 data. The modexpo_crt function always decrypts
- * the data in the assumption that its PKCS12 encrypted data.
- */
-#define PCICC_SPEED_RATING 0
-
-#define PCICC_MAX_MESSAGE_SIZE 0x710 /* max size type6 v1 crt message */
-#define PCICC_MAX_RESPONSE_SIZE 0x710 /* max size type86 v1 reply */
-
-#define PCICC_CLEANUP_TIME (15*HZ)
-
-static struct ap_device_id zcrypt_pcicc_ids[] = {
- { AP_DEVICE(AP_DEVICE_TYPE_PCICC) },
- { /* end of list */ },
-};
-
-MODULE_DEVICE_TABLE(ap, zcrypt_pcicc_ids);
-MODULE_AUTHOR("IBM Corporation");
-MODULE_DESCRIPTION("PCICC Cryptographic Coprocessor device driver, "
- "Copyright IBM Corp. 2001, 2006");
-MODULE_LICENSE("GPL");
-
-static int zcrypt_pcicc_probe(struct ap_device *ap_dev);
-static void zcrypt_pcicc_remove(struct ap_device *ap_dev);
-static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *,
- struct ap_message *);
-
-static struct ap_driver zcrypt_pcicc_driver = {
- .probe = zcrypt_pcicc_probe,
- .remove = zcrypt_pcicc_remove,
- .ids = zcrypt_pcicc_ids,
- .request_timeout = PCICC_CLEANUP_TIME,
-};
-
-/**
- * The following is used to initialize the CPRB passed to the PCICC card
- * in a type6 message. The 3 fields that must be filled in at execution
- * time are req_parml, rpl_parml and usage_domain. Note that all three
- * fields are *little*-endian. Actually, everything about this interface
- * is ascii/little-endian, since the device has 'Intel inside'.
- *
- * The CPRB is followed immediately by the parm block.
- * The parm block contains:
- * - function code ('PD' 0x5044 or 'PK' 0x504B)
- * - rule block (0x0A00 'PKCS-1.2' or 0x0A00 'ZERO-PAD')
- * - VUD block
- */
-static struct CPRB static_cprb = {
- .cprb_len = cpu_to_le16(0x0070),
- .cprb_ver_id = 0x41,
- .func_id = {0x54,0x32},
- .checkpoint_flag= 0x01,
- .svr_namel = cpu_to_le16(0x0008),
- .svr_name = {'I','C','S','F',' ',' ',' ',' '}
-};
-
-/**
- * Check the message for PKCS11 padding.
- */
-static inline int is_PKCS11_padded(unsigned char *buffer, int length)
-{
- int i;
- if ((buffer[0] != 0x00) || (buffer[1] != 0x01))
- return 0;
- for (i = 2; i < length; i++)
- if (buffer[i] != 0xFF)
- break;
- if (i < 10 || i == length)
- return 0;
- if (buffer[i] != 0x00)
- return 0;
- return 1;
-}
-
-/**
- * Check the message for PKCS12 padding.
- */
-static inline int is_PKCS12_padded(unsigned char *buffer, int length)
-{
- int i;
- if ((buffer[0] != 0x00) || (buffer[1] != 0x02))
- return 0;
- for (i = 2; i < length; i++)
- if (buffer[i] == 0x00)
- break;
- if ((i < 10) || (i == length))
- return 0;
- if (buffer[i] != 0x00)
- return 0;
- return 1;
-}
-
-/**
- * Convert a ICAMEX message to a type6 MEX message.
- *
- * @zdev: crypto device pointer
- * @zreq: crypto request pointer
- * @mex: pointer to user input data
- *
- * Returns 0 on success or -EFAULT.
- */
-static int ICAMEX_msg_to_type6MEX_msg(struct zcrypt_device *zdev,
- struct ap_message *ap_msg,
- struct ica_rsa_modexpo *mex)
-{
- static struct type6_hdr static_type6_hdr = {
- .type = 0x06,
- .offset1 = 0x00000058,
- .agent_id = {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50,
- 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01},
- .function_code = {'P','K'},
- };
- static struct function_and_rules_block static_pke_function_and_rules ={
- .function_code = {'P','K'},
- .ulen = cpu_to_le16(10),
- .only_rule = {'P','K','C','S','-','1','.','2'}
- };
- struct {
- struct type6_hdr hdr;
- struct CPRB cprb;
- struct function_and_rules_block fr;
- unsigned short length;
- char text[0];
- } __attribute__((packed)) *msg = ap_msg->message;
- int vud_len, pad_len, size;
-
- /* VUD.ciphertext */
- if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
- return -EFAULT;
-
- if (is_PKCS11_padded(msg->text, mex->inputdatalength))
- return -EINVAL;
-
- /* static message header and f&r */
- msg->hdr = static_type6_hdr;
- msg->fr = static_pke_function_and_rules;
-
- if (is_PKCS12_padded(msg->text, mex->inputdatalength)) {
- /* strip the padding and adjust the data length */
- pad_len = strnlen(msg->text + 2, mex->inputdatalength - 2) + 3;
- if (pad_len <= 9 || pad_len >= mex->inputdatalength)
- return -ENODEV;
- vud_len = mex->inputdatalength - pad_len;
- memmove(msg->text, msg->text + pad_len, vud_len);
- msg->length = cpu_to_le16(vud_len + 2);
-
- /* Set up key after the variable length text. */
- size = zcrypt_type6_mex_key_en(mex, msg->text + vud_len, 0);
- if (size < 0)
- return size;
- size += sizeof(*msg) + vud_len; /* total size of msg */
- } else {
- vud_len = mex->inputdatalength;
- msg->length = cpu_to_le16(2 + vud_len);
-
- msg->hdr.function_code[1] = 'D';
- msg->fr.function_code[1] = 'D';
-
- /* Set up key after the variable length text. */
- size = zcrypt_type6_mex_key_de(mex, msg->text + vud_len, 0);
- if (size < 0)
- return size;
- size += sizeof(*msg) + vud_len; /* total size of msg */
- }
-
- /* message header, cprb and f&r */
- msg->hdr.ToCardLen1 = (size - sizeof(msg->hdr) + 3) & -4;
- msg->hdr.FromCardLen1 = PCICC_MAX_RESPONSE_SIZE - sizeof(msg->hdr);
-
- msg->cprb = static_cprb;
- msg->cprb.usage_domain[0]= AP_QID_QUEUE(zdev->ap_dev->qid);
- msg->cprb.req_parml = cpu_to_le16(size - sizeof(msg->hdr) -
- sizeof(msg->cprb));
- msg->cprb.rpl_parml = cpu_to_le16(msg->hdr.FromCardLen1);
-
- ap_msg->length = (size + 3) & -4;
- return 0;
-}
-
-/**
- * Convert a ICACRT message to a type6 CRT message.
- *
- * @zdev: crypto device pointer
- * @zreq: crypto request pointer
- * @crt: pointer to user input data
- *
- * Returns 0 on success or -EFAULT.
- */
-static int ICACRT_msg_to_type6CRT_msg(struct zcrypt_device *zdev,
- struct ap_message *ap_msg,
- struct ica_rsa_modexpo_crt *crt)
-{
- static struct type6_hdr static_type6_hdr = {
- .type = 0x06,
- .offset1 = 0x00000058,
- .agent_id = {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50,
- 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01},
- .function_code = {'P','D'},
- };
- static struct function_and_rules_block static_pkd_function_and_rules ={
- .function_code = {'P','D'},
- .ulen = cpu_to_le16(10),
- .only_rule = {'P','K','C','S','-','1','.','2'}
- };
- struct {
- struct type6_hdr hdr;
- struct CPRB cprb;
- struct function_and_rules_block fr;
- unsigned short length;
- char text[0];
- } __attribute__((packed)) *msg = ap_msg->message;
- int size;
-
- /* VUD.ciphertext */
- msg->length = cpu_to_le16(2 + crt->inputdatalength);
- if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
- return -EFAULT;
-
- if (is_PKCS11_padded(msg->text, crt->inputdatalength))
- return -EINVAL;
-
- /* Set up key after the variable length text. */
- size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 0);
- if (size < 0)
- return size;
- size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
-
- /* message header, cprb and f&r */
- msg->hdr = static_type6_hdr;
- msg->hdr.ToCardLen1 = (size - sizeof(msg->hdr) + 3) & -4;
- msg->hdr.FromCardLen1 = PCICC_MAX_RESPONSE_SIZE - sizeof(msg->hdr);
-
- msg->cprb = static_cprb;
- msg->cprb.usage_domain[0] = AP_QID_QUEUE(zdev->ap_dev->qid);
- msg->cprb.req_parml = msg->cprb.rpl_parml =
- cpu_to_le16(size - sizeof(msg->hdr) - sizeof(msg->cprb));
-
- msg->fr = static_pkd_function_and_rules;
-
- ap_msg->length = (size + 3) & -4;
- return 0;
-}
-
-/**
- * Copy results from a type 86 reply message back to user space.
- *
- * @zdev: crypto device pointer
- * @reply: reply AP message.
- * @data: pointer to user output data
- * @length: size of user output data
- *
- * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
- */
-struct type86_reply {
- struct type86_hdr hdr;
- struct type86_fmt2_ext fmt2;
- struct CPRB cprb;
- unsigned char pad[4]; /* 4 byte function code/rules block ? */
- unsigned short length;
- char text[0];
-} __attribute__((packed));
-
-static int convert_type86(struct zcrypt_device *zdev,
- struct ap_message *reply,
- char __user *outputdata,
- unsigned int outputdatalength)
-{
- static unsigned char static_pad[] = {
- 0x00,0x02,
- 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
- 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
- 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
- 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
- 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
- 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
- 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
- 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
- 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
- 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
- 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
- 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
- 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
- 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
- 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
- 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
- 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
- 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
- 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
- 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
- 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
- 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
- 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
- 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
- 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
- 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
- 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
- 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
- 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
- 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
- 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
- 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
- };
- struct type86_reply *msg = reply->message;
- unsigned short service_rc, service_rs;
- unsigned int reply_len, pad_len;
- char *data;
-
- service_rc = le16_to_cpu(msg->cprb.ccp_rtcode);
- if (unlikely(service_rc != 0)) {
- service_rs = le16_to_cpu(msg->cprb.ccp_rscode);
- if (service_rc == 8 && service_rs == 66)
- return -EINVAL;
- if (service_rc == 8 && service_rs == 65)
- return -EINVAL;
- if (service_rc == 8 && service_rs == 770) {
- zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
- return -EAGAIN;
- }
- if (service_rc == 8 && service_rs == 783) {
- zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
- return -EAGAIN;
- }
- if (service_rc == 8 && service_rs == 72)
- return -EINVAL;
- zdev->online = 0;
- pr_err("Cryptographic device %x failed and was set offline\n",
- zdev->ap_dev->qid);
- ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
- zdev->ap_dev->qid, zdev->online,
- msg->hdr.reply_code);
- return -EAGAIN; /* repeat the request on a different device. */
- }
- data = msg->text;
- reply_len = le16_to_cpu(msg->length) - 2;
- if (reply_len > outputdatalength)
- return -EINVAL;
- /*
- * For all encipher requests, the length of the ciphertext (reply_len)
- * will always equal the modulus length. For MEX decipher requests
- * the output needs to get padded. Minimum pad size is 10.
- *
- * Currently, the cases where padding will be added is for:
- * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
- * ZERO-PAD and CRT is only supported for PKD requests)
- * - PCICC, always
- */
- pad_len = outputdatalength - reply_len;
- if (pad_len > 0) {
- if (pad_len < 10)
- return -EINVAL;
- /* 'restore' padding left in the PCICC/PCIXCC card. */
- if (copy_to_user(outputdata, static_pad, pad_len - 1))
- return -EFAULT;
- if (put_user(0, outputdata + pad_len - 1))
- return -EFAULT;
- }
- /* Copy the crypto response to user space. */
- if (copy_to_user(outputdata + pad_len, data, reply_len))
- return -EFAULT;
- return 0;
-}
-
-static int convert_response(struct zcrypt_device *zdev,
- struct ap_message *reply,
- char __user *outputdata,
- unsigned int outputdatalength)
-{
- struct type86_reply *msg = reply->message;
-
- /* Response type byte is the second byte in the response. */
- switch (msg->hdr.type) {
- case TYPE82_RSP_CODE:
- case TYPE88_RSP_CODE:
- return convert_error(zdev, reply);
- case TYPE86_RSP_CODE:
- if (msg->hdr.reply_code)
- return convert_error(zdev, reply);
- if (msg->cprb.cprb_ver_id == 0x01)
- return convert_type86(zdev, reply,
- outputdata, outputdatalength);
- /* no break, incorrect cprb version is an unknown response */
- default: /* Unknown response type, this should NEVER EVER happen */
- zdev->online = 0;
- pr_err("Cryptographic device %x failed and was set offline\n",
- zdev->ap_dev->qid);
- ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
- zdev->ap_dev->qid, zdev->online);
- return -EAGAIN; /* repeat the request on a different device. */
- }
-}
-
-/**
- * This function is called from the AP bus code after a crypto request
- * "msg" has finished with the reply message "reply".
- * It is called from tasklet context.
- * @ap_dev: pointer to the AP device
- * @msg: pointer to the AP message
- * @reply: pointer to the AP reply message
- */
-static void zcrypt_pcicc_receive(struct ap_device *ap_dev,
- struct ap_message *msg,
- struct ap_message *reply)
-{
- static struct error_hdr error_reply = {
- .type = TYPE82_RSP_CODE,
- .reply_code = REP82_ERROR_MACHINE_FAILURE,
- };
- struct type86_reply *t86r;
- int length;
-
- /* Copy the reply message to the request message buffer. */
- if (IS_ERR(reply)) {
- memcpy(msg->message, &error_reply, sizeof(error_reply));
- goto out;
- }
- t86r = reply->message;
- if (t86r->hdr.type == TYPE86_RSP_CODE &&
- t86r->cprb.cprb_ver_id == 0x01) {
- length = sizeof(struct type86_reply) + t86r->length - 2;
- length = min(PCICC_MAX_RESPONSE_SIZE, length);
- memcpy(msg->message, reply->message, length);
- } else
- memcpy(msg->message, reply->message, sizeof error_reply);
-out:
- complete((struct completion *) msg->private);
-}
-
-static atomic_t zcrypt_step = ATOMIC_INIT(0);
-
-/**
- * The request distributor calls this function if it picked the PCICC
- * device to handle a modexpo request.
- * @zdev: pointer to zcrypt_device structure that identifies the
- * PCICC device to the request distributor
- * @mex: pointer to the modexpo request buffer
- */
-static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
- struct ica_rsa_modexpo *mex)
-{
- struct ap_message ap_msg;
- struct completion work;
- int rc;
-
- ap_init_message(&ap_msg);
- ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
- if (!ap_msg.message)
- return -ENOMEM;
- ap_msg.receive = zcrypt_pcicc_receive;
- ap_msg.length = PAGE_SIZE;
- ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
- atomic_inc_return(&zcrypt_step);
- ap_msg.private = &work;
- rc = ICAMEX_msg_to_type6MEX_msg(zdev, &ap_msg, mex);
- if (rc)
- goto out_free;
- init_completion(&work);
- ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible(&work);
- if (rc == 0)
- rc = convert_response(zdev, &ap_msg, mex->outputdata,
- mex->outputdatalength);
- else
- /* Signal pending. */
- ap_cancel_message(zdev->ap_dev, &ap_msg);
-out_free:
- free_page((unsigned long) ap_msg.message);
- return rc;
-}
-
-/**
- * The request distributor calls this function if it picked the PCICC
- * device to handle a modexpo_crt request.
- * @zdev: pointer to zcrypt_device structure that identifies the
- * PCICC device to the request distributor
- * @crt: pointer to the modexpoc_crt request buffer
- */
-static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
- struct ica_rsa_modexpo_crt *crt)
-{
- struct ap_message ap_msg;
- struct completion work;
- int rc;
-
- ap_init_message(&ap_msg);
- ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
- if (!ap_msg.message)
- return -ENOMEM;
- ap_msg.receive = zcrypt_pcicc_receive;
- ap_msg.length = PAGE_SIZE;
- ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
- atomic_inc_return(&zcrypt_step);
- ap_msg.private = &work;
- rc = ICACRT_msg_to_type6CRT_msg(zdev, &ap_msg, crt);
- if (rc)
- goto out_free;
- init_completion(&work);
- ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible(&work);
- if (rc == 0)
- rc = convert_response(zdev, &ap_msg, crt->outputdata,
- crt->outputdatalength);
- else
- /* Signal pending. */
- ap_cancel_message(zdev->ap_dev, &ap_msg);
-out_free:
- free_page((unsigned long) ap_msg.message);
- return rc;
-}
-
-/**
- * The crypto operations for a PCICC card.
- */
-static struct zcrypt_ops zcrypt_pcicc_ops = {
- .rsa_modexpo = zcrypt_pcicc_modexpo,
- .rsa_modexpo_crt = zcrypt_pcicc_modexpo_crt,
-};
-
-/**
- * Probe function for PCICC cards. It always accepts the AP device
- * since the bus_match already checked the hardware type.
- * @ap_dev: pointer to the AP device.
- */
-static int zcrypt_pcicc_probe(struct ap_device *ap_dev)
-{
- struct zcrypt_device *zdev;
- int rc;
-
- zdev = zcrypt_device_alloc(PCICC_MAX_RESPONSE_SIZE);
- if (!zdev)
- return -ENOMEM;
- zdev->ap_dev = ap_dev;
- zdev->ops = &zcrypt_pcicc_ops;
- zdev->online = 1;
- zdev->user_space_type = ZCRYPT_PCICC;
- zdev->type_string = "PCICC";
- zdev->min_mod_size = PCICC_MIN_MOD_SIZE;
- zdev->max_mod_size = PCICC_MAX_MOD_SIZE;
- zdev->speed_rating = PCICC_SPEED_RATING;
- zdev->max_exp_bit_length = PCICC_MAX_MOD_SIZE;
- ap_dev->reply = &zdev->reply;
- ap_dev->private = zdev;
- rc = zcrypt_device_register(zdev);
- if (rc)
- goto out_free;
- return 0;
-
- out_free:
- ap_dev->private = NULL;
- zcrypt_device_free(zdev);
- return rc;
-}
-
-/**
- * This is called to remove the extended PCICC driver information
- * if an AP device is removed.
- */
-static void zcrypt_pcicc_remove(struct ap_device *ap_dev)
-{
- struct zcrypt_device *zdev = ap_dev->private;
-
- zcrypt_device_unregister(zdev);
-}
-
-int __init zcrypt_pcicc_init(void)
-{
- return ap_driver_register(&zcrypt_pcicc_driver, THIS_MODULE, "pcicc");
-}
-
-void zcrypt_pcicc_exit(void)
-{
- ap_driver_unregister(&zcrypt_pcicc_driver);
-}
-
-module_init(zcrypt_pcicc_init);
-module_exit(zcrypt_pcicc_exit);
diff --git a/drivers/s390/crypto/zcrypt_pcicc.h b/drivers/s390/crypto/zcrypt_pcicc.h
deleted file mode 100644
index 7fe27e15075b..000000000000
--- a/drivers/s390/crypto/zcrypt_pcicc.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * zcrypt 2.1.0
- *
- * Copyright IBM Corp. 2001, 2006
- * Author(s): Robert Burroughs
- * Eric Rossman (edrossma@us.ibm.com)
- *
- * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
- * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.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, 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.
- */
-
-#ifndef _ZCRYPT_PCICC_H_
-#define _ZCRYPT_PCICC_H_
-
-/**
- * The type 6 message family is associated with PCICC or PCIXCC cards.
- *
- * It contains a message header followed by a CPRB, both of which
- * are described below.
- *
- * Note that all reserved fields must be zeroes.
- */
-struct type6_hdr {
- unsigned char reserved1; /* 0x00 */
- unsigned char type; /* 0x06 */
- unsigned char reserved2[2]; /* 0x0000 */
- unsigned char right[4]; /* 0x00000000 */
- unsigned char reserved3[2]; /* 0x0000 */
- unsigned char reserved4[2]; /* 0x0000 */
- unsigned char apfs[4]; /* 0x00000000 */
- unsigned int offset1; /* 0x00000058 (offset to CPRB) */
- unsigned int offset2; /* 0x00000000 */
- unsigned int offset3; /* 0x00000000 */
- unsigned int offset4; /* 0x00000000 */
- unsigned char agent_id[16]; /* PCICC: */
- /* 0x0100 */
- /* 0x4343412d4150504c202020 */
- /* 0x010101 */
- /* PCIXCC: */
- /* 0x4341000000000000 */
- /* 0x0000000000000000 */
- unsigned char rqid[2]; /* rqid. internal to 603 */
- unsigned char reserved5[2]; /* 0x0000 */
- unsigned char function_code[2]; /* for PKD, 0x5044 (ascii 'PD') */
- unsigned char reserved6[2]; /* 0x0000 */
- unsigned int ToCardLen1; /* (request CPRB len + 3) & -4 */
- unsigned int ToCardLen2; /* db len 0x00000000 for PKD */
- unsigned int ToCardLen3; /* 0x00000000 */
- unsigned int ToCardLen4; /* 0x00000000 */
- unsigned int FromCardLen1; /* response buffer length */
- unsigned int FromCardLen2; /* db len 0x00000000 for PKD */
- unsigned int FromCardLen3; /* 0x00000000 */
- unsigned int FromCardLen4; /* 0x00000000 */
-} __attribute__((packed));
-
-/**
- * CPRB
- * Note that all shorts, ints and longs are little-endian.
- * All pointer fields are 32-bits long, and mean nothing
- *
- * A request CPRB is followed by a request_parameter_block.
- *
- * The request (or reply) parameter block is organized thus:
- * function code
- * VUD block
- * key block
- */
-struct CPRB {
- unsigned short cprb_len; /* CPRB length */
- unsigned char cprb_ver_id; /* CPRB version id. */
- unsigned char pad_000; /* Alignment pad byte. */
- unsigned char srpi_rtcode[4]; /* SRPI return code LELONG */
- unsigned char srpi_verb; /* SRPI verb type */
- unsigned char flags; /* flags */
- unsigned char func_id[2]; /* function id */
- unsigned char checkpoint_flag; /* */
- unsigned char resv2; /* reserved */
- unsigned short req_parml; /* request parameter buffer */
- /* length 16-bit little endian */
- unsigned char req_parmp[4]; /* request parameter buffer *
- * pointer (means nothing: the *
- * parameter buffer follows *
- * the CPRB). */
- unsigned char req_datal[4]; /* request data buffer */
- /* length ULELONG */
- unsigned char req_datap[4]; /* request data buffer */
- /* pointer */
- unsigned short rpl_parml; /* reply parameter buffer */
- /* length 16-bit little endian */
- unsigned char pad_001[2]; /* Alignment pad bytes. ULESHORT */
- unsigned char rpl_parmp[4]; /* reply parameter buffer *
- * pointer (means nothing: the *
- * parameter buffer follows *
- * the CPRB). */
- unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */
- unsigned char rpl_datap[4]; /* reply data buffer */
- /* pointer */
- unsigned short ccp_rscode; /* server reason code ULESHORT */
- unsigned short ccp_rtcode; /* server return code ULESHORT */
- unsigned char repd_parml[2]; /* replied parameter len ULESHORT*/
- unsigned char mac_data_len[2]; /* Mac Data Length ULESHORT */
- unsigned char repd_datal[4]; /* replied data length ULELONG */
- unsigned char req_pc[2]; /* PC identifier */
- unsigned char res_origin[8]; /* resource origin */
- unsigned char mac_value[8]; /* Mac Value */
- unsigned char logon_id[8]; /* Logon Identifier */
- unsigned char usage_domain[2]; /* cdx */
- unsigned char resv3[18]; /* reserved for requestor */
- unsigned short svr_namel; /* server name length ULESHORT */
- unsigned char svr_name[8]; /* server name */
-} __attribute__((packed));
-
-/**
- * The type 86 message family is associated with PCICC and PCIXCC cards.
- *
- * It contains a message header followed by a CPRB. The CPRB is
- * the same as the request CPRB, which is described above.
- *
- * If format is 1, an error condition exists and no data beyond
- * the 8-byte message header is of interest.
- *
- * The non-error message is shown below.
- *
- * Note that all reserved fields must be zeroes.
- */
-struct type86_hdr {
- unsigned char reserved1; /* 0x00 */
- unsigned char type; /* 0x86 */
- unsigned char format; /* 0x01 (error) or 0x02 (ok) */
- unsigned char reserved2; /* 0x00 */
- unsigned char reply_code; /* reply code (see above) */
- unsigned char reserved3[3]; /* 0x000000 */
-} __attribute__((packed));
-
-#define TYPE86_RSP_CODE 0x86
-#define TYPE86_FMT2 0x02
-
-struct type86_fmt2_ext {
- unsigned char reserved[4]; /* 0x00000000 */
- unsigned char apfs[4]; /* final status */
- unsigned int count1; /* length of CPRB + parameters */
- unsigned int offset1; /* offset to CPRB */
- unsigned int count2; /* 0x00000000 */
- unsigned int offset2; /* db offset 0x00000000 for PKD */
- unsigned int count3; /* 0x00000000 */
- unsigned int offset3; /* 0x00000000 */
- unsigned int count4; /* 0x00000000 */
- unsigned int offset4; /* 0x00000000 */
-} __attribute__((packed));
-
-struct function_and_rules_block {
- unsigned char function_code[2];
- unsigned short ulen;
- unsigned char only_rule[8];
-} __attribute__((packed));
-
-int zcrypt_pcicc_init(void);
-void zcrypt_pcicc_exit(void);
-
-#endif /* _ZCRYPT_PCICC_H_ */
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 33f7040d711d..0ba3a2f81750 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -149,12 +149,11 @@ static struct device_driver netiucv_driver = {
.pm = &netiucv_pm_ops,
};
-static int netiucv_callback_connreq(struct iucv_path *,
- u8 ipvmid[8], u8 ipuser[16]);
-static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
-static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
-static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]);
-static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]);
+static int netiucv_callback_connreq(struct iucv_path *, u8 *, u8 *);
+static void netiucv_callback_connack(struct iucv_path *, u8 *);
+static void netiucv_callback_connrej(struct iucv_path *, u8 *);
+static void netiucv_callback_connsusp(struct iucv_path *, u8 *);
+static void netiucv_callback_connres(struct iucv_path *, u8 *);
static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *);
static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *);
@@ -556,8 +555,8 @@ static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn);
}
-static int netiucv_callback_connreq(struct iucv_path *path,
- u8 ipvmid[8], u8 ipuser[16])
+static int netiucv_callback_connreq(struct iucv_path *path, u8 *ipvmid,
+ u8 *ipuser)
{
struct iucv_connection *conn = path->private;
struct iucv_event ev;
@@ -587,21 +586,21 @@ static int netiucv_callback_connreq(struct iucv_path *path,
return rc;
}
-static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
+static void netiucv_callback_connrej(struct iucv_path *path, u8 *ipuser)
{
struct iucv_connection *conn = path->private;
fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn);
}
-static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16])
+static void netiucv_callback_connsusp(struct iucv_path *path, u8 *ipuser)
{
struct iucv_connection *conn = path->private;
fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn);
}
-static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16])
+static void netiucv_callback_connres(struct iucv_path *path, u8 *ipuser)
{
struct iucv_connection *conn = path->private;
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index ba974a2e409f..1766a20ebcb1 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -18,6 +18,7 @@
#include <linux/bitops.h>
#include <linux/seq_file.h>
#include <linux/ethtool.h>
+#include <linux/hashtable.h>
#include <net/ipv6.h>
#include <net/if_inet6.h>
@@ -663,9 +664,7 @@ struct qeth_card_info {
char mcl_level[QETH_MCL_LENGTH + 1];
int guestlan;
int mac_bits;
- int portname_required;
int portno;
- char portname[9];
enum qeth_card_types type;
enum qeth_link_types link_type;
int is_multicast_different;
@@ -741,11 +740,17 @@ struct qeth_vlan_vid {
unsigned short vid;
};
-struct qeth_mc_mac {
- struct list_head list;
- __u8 mc_addr[MAX_ADDR_LEN];
- unsigned char mc_addrlen;
- int is_vmac;
+enum qeth_mac_disposition {
+ QETH_DISP_MAC_DELETE = 0,
+ QETH_DISP_MAC_DO_NOTHING = 1,
+ QETH_DISP_MAC_ADD = 2,
+};
+
+struct qeth_mac {
+ u8 mac_addr[OSA_ADDR_LEN];
+ u8 is_uc:1;
+ u8 disp_flag:2;
+ struct hlist_node hnode;
};
struct qeth_rx {
@@ -792,7 +797,7 @@ struct qeth_card {
spinlock_t mclock;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct list_head vid_list;
- struct list_head mc_list;
+ DECLARE_HASHTABLE(mac_htable, 4);
struct work_struct kernel_thread_starter;
spinlock_t thread_mask_lock;
unsigned long thread_start_mask;
@@ -969,6 +974,15 @@ int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
void qeth_trace_features(struct qeth_card *);
void qeth_close_dev(struct qeth_card *);
+int qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
+ __u16, long);
+int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16,
+ long,
+ int (*reply_cb)(struct qeth_card *,
+ struct qeth_reply *, unsigned long),
+ void *);
+int qeth_start_ipa_tx_checksum(struct qeth_card *);
+int qeth_set_rx_csum(struct qeth_card *, int);
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 5e20fba37bff..31ac53fa5cee 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1982,14 +1982,6 @@ static void qeth_idx_read_cb(struct qeth_channel *channel,
goto out;
}
-/**
- * * temporary fix for microcode bug
- * * to revert it,replace OR by AND
- * */
- if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
- (card->info.type == QETH_CARD_TYPE_OSD))
- card->info.portname_required = 1;
-
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
if (temp != qeth_peer_func_level(card->info.func_level)) {
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel: function "
@@ -2360,8 +2352,6 @@ static int qeth_ulp_enable(struct qeth_card *card)
&card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
&card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
- memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
- card->info.portname, 9);
rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
qeth_ulp_enable_cb, NULL);
return rc;
@@ -2680,48 +2670,6 @@ out_qdio:
return rc;
}
-static void qeth_print_status_with_portname(struct qeth_card *card)
-{
- char dbf_text[15];
- int i;
-
- sprintf(dbf_text, "%s", card->info.portname + 1);
- for (i = 0; i < 8; i++)
- dbf_text[i] =
- (char) _ebcasc[(__u8) dbf_text[i]];
- dbf_text[8] = 0;
- dev_info(&card->gdev->dev, "Device is a%s card%s%s%s\n"
- "with link type %s (portname: %s)\n",
- qeth_get_cardname(card),
- (card->info.mcl_level[0]) ? " (level: " : "",
- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
- (card->info.mcl_level[0]) ? ")" : "",
- qeth_get_cardname_short(card),
- dbf_text);
-
-}
-
-static void qeth_print_status_no_portname(struct qeth_card *card)
-{
- if (card->info.portname[0])
- dev_info(&card->gdev->dev, "Device is a%s "
- "card%s%s%s\nwith link type %s "
- "(no portname needed by interface).\n",
- qeth_get_cardname(card),
- (card->info.mcl_level[0]) ? " (level: " : "",
- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
- (card->info.mcl_level[0]) ? ")" : "",
- qeth_get_cardname_short(card));
- else
- dev_info(&card->gdev->dev, "Device is a%s "
- "card%s%s%s\nwith link type %s.\n",
- qeth_get_cardname(card),
- (card->info.mcl_level[0]) ? " (level: " : "",
- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
- (card->info.mcl_level[0]) ? ")" : "",
- qeth_get_cardname_short(card));
-}
-
void qeth_print_status_message(struct qeth_card *card)
{
switch (card->info.type) {
@@ -2758,10 +2706,13 @@ void qeth_print_status_message(struct qeth_card *card)
default:
memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
}
- if (card->info.portname_required)
- qeth_print_status_with_portname(card);
- else
- qeth_print_status_no_portname(card);
+ dev_info(&card->gdev->dev,
+ "Device is a%s card%s%s%s\nwith link type %s.\n",
+ qeth_get_cardname(card),
+ (card->info.mcl_level[0]) ? " (level: " : "",
+ (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+ (card->info.mcl_level[0]) ? ")" : "",
+ qeth_get_cardname_short(card));
}
EXPORT_SYMBOL_GPL(qeth_print_status_message);
@@ -5027,13 +4978,11 @@ static void qeth_core_free_card(struct qeth_card *card)
void qeth_trace_features(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 2, "features");
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support);
+ QETH_CARD_HEX(card, 2, &card->options.ipa4, sizeof(card->options.ipa4));
+ QETH_CARD_HEX(card, 2, &card->options.ipa6, sizeof(card->options.ipa6));
+ QETH_CARD_HEX(card, 2, &card->options.adp, sizeof(card->options.adp));
+ QETH_CARD_HEX(card, 2, &card->info.diagass_support,
+ sizeof(card->info.diagass_support));
}
EXPORT_SYMBOL_GPL(qeth_trace_features);
@@ -5132,6 +5081,7 @@ retriable:
}
card->options.ipa4.supported_funcs = 0;
+ card->options.ipa6.supported_funcs = 0;
card->options.adp.supported_funcs = 0;
card->options.sbp.supported_funcs = 0;
card->info.diagass_support = 0;
@@ -5317,6 +5267,102 @@ no_mem:
}
EXPORT_SYMBOL_GPL(qeth_core_get_next_skb);
+static int qeth_setassparms_cb(struct qeth_card *card,
+ struct qeth_reply *reply, unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd;
+
+ 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->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
+ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+ card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
+ QETH_CARD_TEXT_(card, 3, "csum:%d", card->info.csum_mask);
+ }
+ if (cmd->data.setassparms.hdr.assist_no == IPA_OUTBOUND_CHECKSUM &&
+ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+ card->info.tx_csum_mask =
+ cmd->data.setassparms.data.flags_32bit;
+ QETH_CARD_TEXT_(card, 3, "tcsu:%d", card->info.tx_csum_mask);
+ }
+
+ return 0;
+}
+
+static struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
+ enum qeth_ipa_funcs ipa_func,
+ __u16 cmd_code, __u16 len,
+ enum qeth_prot_versions prot)
+{
+ struct qeth_cmd_buffer *iob;
+ struct qeth_ipa_cmd *cmd;
+
+ QETH_CARD_TEXT(card, 4, "getasscm");
+ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
+
+ if (iob) {
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+ cmd->data.setassparms.hdr.assist_no = ipa_func;
+ cmd->data.setassparms.hdr.length = 8 + len;
+ cmd->data.setassparms.hdr.command_code = cmd_code;
+ cmd->data.setassparms.hdr.return_code = 0;
+ cmd->data.setassparms.hdr.seq_no = 0;
+ }
+
+ return iob;
+}
+
+int qeth_send_setassparms(struct qeth_card *card,
+ struct qeth_cmd_buffer *iob, __u16 len, long data,
+ int (*reply_cb)(struct qeth_card *,
+ struct qeth_reply *, unsigned long),
+ void *reply_param)
+{
+ int rc;
+ struct qeth_ipa_cmd *cmd;
+
+ QETH_CARD_TEXT(card, 4, "sendassp");
+
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+ if (len <= sizeof(__u32))
+ cmd->data.setassparms.data.flags_32bit = (__u32) data;
+ else /* (len > sizeof(__u32)) */
+ memcpy(&cmd->data.setassparms.data, (void *) data, len);
+
+ rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_setassparms);
+
+int qeth_send_simple_setassparms(struct qeth_card *card,
+ enum qeth_ipa_funcs ipa_func,
+ __u16 cmd_code, long data)
+{
+ int rc;
+ int length = 0;
+ struct qeth_cmd_buffer *iob;
+
+ QETH_CARD_TEXT(card, 4, "simassp4");
+ if (data)
+ length = sizeof(__u32);
+ iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
+ length, QETH_PROT_IPV4);
+ if (!iob)
+ return -ENOMEM;
+ rc = qeth_send_setassparms(card, iob, length, data,
+ qeth_setassparms_cb, NULL);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms);
+
static void qeth_unregister_dbf_views(void)
{
int x;
@@ -6003,6 +6049,75 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
}
EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
+static int qeth_send_checksum_command(struct qeth_card *card)
+{
+ int rc;
+
+ rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+ IPA_CMD_ASS_START, 0);
+ if (rc) {
+ dev_warn(&card->gdev->dev, "Starting HW checksumming for %s "
+ "failed, using SW checksumming\n",
+ QETH_CARD_IFNAME(card));
+ return rc;
+ }
+ rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+ IPA_CMD_ASS_ENABLE,
+ card->info.csum_mask);
+ if (rc) {
+ dev_warn(&card->gdev->dev, "Enabling HW checksumming for %s "
+ "failed, using SW checksumming\n",
+ QETH_CARD_IFNAME(card));
+ return rc;
+ }
+ return 0;
+}
+
+int qeth_set_rx_csum(struct qeth_card *card, int on)
+{
+ int rc;
+
+ if (on) {
+ rc = qeth_send_checksum_command(card);
+ if (rc)
+ return -EIO;
+ dev_info(&card->gdev->dev,
+ "HW Checksumming (inbound) enabled\n");
+ } else {
+ rc = qeth_send_simple_setassparms(card,
+ IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0);
+ if (rc)
+ return -EIO;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_set_rx_csum);
+
+int qeth_start_ipa_tx_checksum(struct qeth_card *card)
+{
+ int rc = 0;
+
+ if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ return rc;
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_START, 0);
+ if (rc)
+ goto err_out;
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_ENABLE,
+ card->info.tx_csum_mask);
+ if (rc)
+ goto err_out;
+
+ dev_info(&card->gdev->dev, "HW TX Checksumming enabled\n");
+ return rc;
+err_out:
+ dev_warn(&card->gdev->dev, "Enabling HW TX checksumming for %s "
+ "failed, using SW TX checksumming\n", QETH_CARD_IFNAME(card));
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_start_ipa_tx_checksum);
+
static int __init qeth_core_init(void)
{
int rc;
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 423bec56cffa..e6e5b9671bf2 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -153,52 +153,17 @@ static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
static ssize_t qeth_dev_portname_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct qeth_card *card = dev_get_drvdata(dev);
- char portname[9] = {0, };
-
- if (!card)
- return -EINVAL;
-
- if (card->info.portname_required) {
- memcpy(portname, card->info.portname + 1, 8);
- EBCASC(portname, 8);
- return sprintf(buf, "%s\n", portname);
- } else
- return sprintf(buf, "no portname required\n");
+ return sprintf(buf, "no portname required\n");
}
static ssize_t qeth_dev_portname_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;
-
- if (!card)
- return -EINVAL;
-
- mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
- rc = -EPERM;
- goto out;
- }
- tmp = strsep((char **) &buf, "\n");
- if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) {
- rc = -EINVAL;
- goto out;
- }
-
- card->info.portname[0] = strlen(tmp);
- /* for beauty reasons */
- for (i = 1; i < 9; i++)
- card->info.portname[i] = ' ';
- strcpy(card->info.portname + 1, tmp);
- ASCEBC(card->info.portname + 1, 8);
-out:
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
+ dev_warn_once(&card->gdev->dev,
+ "portname is deprecated and is ignored\n");
+ return count;
}
static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index a8556692f632..8f1b091e1732 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -19,7 +19,9 @@
#include <linux/mii.h>
#include <linux/ip.h>
#include <linux/list.h>
-
+#include <linux/hash.h>
+#include <linux/hashtable.h>
+#include <linux/string.h>
#include "qeth_core.h"
#include "qeth_l2.h"
@@ -28,7 +30,7 @@ static int qeth_l2_stop(struct net_device *);
static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *,
enum qeth_ipa_cmds);
-static void qeth_l2_set_multicast_list(struct net_device *);
+static void qeth_l2_set_rx_mode(struct net_device *);
static int qeth_l2_recover(void *);
static void qeth_bridgeport_query_support(struct qeth_card *card);
static void qeth_bridge_state_change(struct qeth_card *card,
@@ -193,49 +195,44 @@ static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
return rc;
}
-static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac)
+static inline u32 qeth_l2_mac_hash(const u8 *addr)
{
- struct qeth_mc_mac *mc;
- int rc;
-
- mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
+ return get_unaligned((u32 *)(&addr[2]));
+}
- if (!mc)
- return;
+static int qeth_l2_write_mac(struct qeth_card *card, struct qeth_mac *mac)
+{
- memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
- mc->mc_addrlen = OSA_ADDR_LEN;
- mc->is_vmac = vmac;
+ int rc;
- if (vmac) {
+ if (mac->is_uc) {
rc = qeth_setdel_makerc(card,
- qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC));
+ qeth_l2_send_setdelmac(card, mac->mac_addr,
+ IPA_CMD_SETVMAC));
} else {
rc = qeth_setdel_makerc(card,
- qeth_l2_send_setgroupmac(card, mac));
+ qeth_l2_send_setgroupmac(card, mac->mac_addr));
}
-
- if (!rc)
- list_add_tail(&mc->list, &card->mc_list);
- else
- kfree(mc);
+ return rc;
}
-static void qeth_l2_del_all_mc(struct qeth_card *card, int del)
+static void qeth_l2_del_all_macs(struct qeth_card *card, int del)
{
- struct qeth_mc_mac *mc, *tmp;
+ struct qeth_mac *mac;
+ struct hlist_node *tmp;
+ int i;
spin_lock_bh(&card->mclock);
- list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
+ hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
if (del) {
- if (mc->is_vmac)
- qeth_l2_send_setdelmac(card, mc->mc_addr,
- IPA_CMD_DELVMAC);
+ if (mac->is_uc)
+ qeth_l2_send_setdelmac(card, mac->mac_addr,
+ IPA_CMD_DELVMAC);
else
- qeth_l2_send_delgroupmac(card, mc->mc_addr);
+ qeth_l2_send_delgroupmac(card, mac->mac_addr);
}
- list_del(&mc->list);
- kfree(mc);
+ hash_del(&mac->hnode);
+ kfree(mac);
}
spin_unlock_bh(&card->mclock);
}
@@ -252,6 +249,23 @@ static inline int qeth_l2_get_cast_type(struct qeth_card *card,
return RTN_UNSPEC;
}
+static inline void qeth_l2_hdr_csum(struct qeth_card *card,
+ struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ /* tcph->check contains already the pseudo hdr checksum
+ * so just set the header flags
+ */
+ if (iph->protocol == IPPROTO_UDP)
+ hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_UDP;
+ hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_CSUM_TRANSP_REQ |
+ QETH_HDR_EXT_CSUM_HDR_REQ;
+ iph->check = 0;
+ if (card->options.performance_stats)
+ card->perf_stats.tx_csum++;
+}
+
static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int cast_type)
{
@@ -386,10 +400,42 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
kfree(tmpid);
}
- qeth_l2_set_multicast_list(card->dev);
+ qeth_l2_set_rx_mode(card->dev);
return rc;
}
+static netdev_features_t qeth_l2_fix_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ QETH_DBF_TEXT(SETUP, 2, "fixfeat");
+ if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ features &= ~NETIF_F_IP_CSUM;
+ if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
+ features &= ~NETIF_F_RXCSUM;
+ QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
+ return features;
+}
+
+static int qeth_l2_set_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ struct qeth_card *card = dev->ml_priv;
+ netdev_features_t changed = dev->features ^ features;
+
+ QETH_DBF_TEXT(SETUP, 2, "setfeat");
+ QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
+
+ if (card->state == CARD_STATE_DOWN ||
+ card->state == CARD_STATE_RECOVER)
+ return 0;
+
+ if (!(changed & NETIF_F_RXCSUM))
+ return 0;
+ return qeth_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0);
+}
+
static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
{
QETH_DBF_TEXT(SETUP , 2, "stopcard");
@@ -411,7 +457,7 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
card->state = CARD_STATE_SOFTSETUP;
}
if (card->state == CARD_STATE_SOFTSETUP) {
- qeth_l2_del_all_mc(card, 0);
+ qeth_l2_del_all_macs(card, 0);
qeth_clear_ipacmd_list(card);
card->state = CARD_STATE_HARDSETUP;
}
@@ -450,11 +496,19 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
case QETH_HEADER_TYPE_LAYER2:
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, skb->dev);
- skb->ip_summed = CHECKSUM_NONE;
+ if ((card->dev->features & NETIF_F_RXCSUM)
+ && ((hdr->hdr.l2.flags[1] &
+ (QETH_HDR_EXT_CSUM_HDR_REQ |
+ QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
+ (QETH_HDR_EXT_CSUM_HDR_REQ |
+ QETH_HDR_EXT_CSUM_TRANSP_REQ)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
if (skb->protocol == htons(ETH_P_802_2))
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
len = skb->len;
- netif_receive_skb(skb);
+ napi_gro_receive(&card->napi, skb);
break;
case QETH_HEADER_TYPE_OSN:
if (card->info.type == QETH_CARD_TYPE_OSN) {
@@ -711,29 +765,91 @@ static void qeth_promisc_to_bridge(struct qeth_card *card)
card->options.sbp.role = role;
card->info.promisc_mode = promisc_mode;
}
+
}
+/* New MAC address is added to the hash table and marked to be written on card
+ * only if there is not in the hash table storage already
+ *
+*/
+static void
+qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha, u8 is_uc)
+{
+ struct qeth_mac *mac;
-static void qeth_l2_set_multicast_list(struct net_device *dev)
+ hash_for_each_possible(card->mac_htable, mac, hnode,
+ qeth_l2_mac_hash(ha->addr)) {
+ if (is_uc == mac->is_uc &&
+ !memcmp(ha->addr, mac->mac_addr, OSA_ADDR_LEN)) {
+ mac->disp_flag = QETH_DISP_MAC_DO_NOTHING;
+ return;
+ }
+ }
+
+ mac = kzalloc(sizeof(struct qeth_mac), GFP_ATOMIC);
+
+ if (!mac)
+ return;
+
+ memcpy(mac->mac_addr, ha->addr, OSA_ADDR_LEN);
+ mac->is_uc = is_uc;
+ mac->disp_flag = QETH_DISP_MAC_ADD;
+
+ hash_add(card->mac_htable, &mac->hnode,
+ qeth_l2_mac_hash(mac->mac_addr));
+
+}
+
+static void qeth_l2_set_rx_mode(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
struct netdev_hw_addr *ha;
+ struct qeth_mac *mac;
+ struct hlist_node *tmp;
+ int i;
+ int rc;
if (card->info.type == QETH_CARD_TYPE_OSN)
- return ;
+ return;
QETH_CARD_TEXT(card, 3, "setmulti");
if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
(card->state != CARD_STATE_UP))
return;
- qeth_l2_del_all_mc(card, 1);
+
spin_lock_bh(&card->mclock);
+
netdev_for_each_mc_addr(ha, dev)
- qeth_l2_add_mc(card, ha->addr, 0);
+ qeth_l2_add_mac(card, ha, 0);
netdev_for_each_uc_addr(ha, dev)
- qeth_l2_add_mc(card, ha->addr, 1);
+ qeth_l2_add_mac(card, ha, 1);
+
+ hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
+ if (mac->disp_flag == QETH_DISP_MAC_DELETE) {
+ if (!mac->is_uc)
+ rc = qeth_l2_send_delgroupmac(card,
+ mac->mac_addr);
+ else {
+ rc = qeth_l2_send_setdelmac(card, mac->mac_addr,
+ IPA_CMD_DELVMAC);
+ }
+
+ hash_del(&mac->hnode);
+ kfree(mac);
+
+ } else if (mac->disp_flag == QETH_DISP_MAC_ADD) {
+ rc = qeth_l2_write_mac(card, mac);
+ if (rc) {
+ hash_del(&mac->hnode);
+ kfree(mac);
+ } else
+ mac->disp_flag = QETH_DISP_MAC_DELETE;
+ } else
+ mac->disp_flag = QETH_DISP_MAC_DELETE;
+ }
spin_unlock_bh(&card->mclock);
+
if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
qeth_setadp_promisc_mode(card);
else
@@ -803,6 +919,8 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
sizeof(struct qeth_hdr));
skb_set_mac_header(new_skb, sizeof(struct qeth_hdr));
qeth_l2_fill_header(card, hdr, new_skb, cast_type);
+ if (new_skb->ip_summed == CHECKSUM_PARTIAL)
+ qeth_l2_hdr_csum(card, hdr, new_skb);
}
}
@@ -915,7 +1033,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
qeth_l2_create_device_attributes(&gdev->dev);
INIT_LIST_HEAD(&card->vid_list);
- INIT_LIST_HEAD(&card->mc_list);
+ hash_init(card->mac_htable);
card->options.layer2 = 1;
card->info.hwtrap = 0;
return 0;
@@ -961,13 +1079,15 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l2_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_rx_mode = qeth_l2_set_multicast_list,
+ .ndo_set_rx_mode = qeth_l2_set_rx_mode,
.ndo_do_ioctl = qeth_l2_do_ioctl,
.ndo_set_mac_address = qeth_l2_set_mac_address,
.ndo_change_mtu = qeth_change_mtu,
.ndo_vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid,
.ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_fix_features = qeth_l2_fix_features,
+ .ndo_set_features = qeth_l2_set_features
};
static int qeth_l2_setup_netdev(struct qeth_card *card)
@@ -997,6 +1117,11 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
(card->info.type != QETH_CARD_TYPE_OSN) ?
&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
+ card->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+ /* Turn on RX offloading per default */
+ card->dev->features |= NETIF_F_RXCSUM;
+ }
card->info.broadcast_capable = 1;
qeth_l2_request_initial_mac(card);
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
@@ -1004,6 +1129,17 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
return register_netdev(card->dev);
}
+static int qeth_l2_start_ipassists(struct qeth_card *card)
+{
+ /* configure isolation level */
+ if (qeth_set_access_ctrl_online(card, 0))
+ return -ENODEV;
+ if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
+ qeth_set_rx_csum(card, 1);
+ qeth_start_ipa_tx_checksum(card);
+ return 0;
+}
+
static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
@@ -1069,12 +1205,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
contin:
if ((card->info.type == QETH_CARD_TYPE_OSD) ||
(card->info.type == QETH_CARD_TYPE_OSX)) {
- /* configure isolation level */
- rc = qeth_set_access_ctrl_online(card, 0);
- if (rc) {
- rc = -ENODEV;
+ if (qeth_l2_start_ipassists(card))
goto out_remove;
- }
}
if (card->info.type != QETH_CARD_TYPE_OSN &&
@@ -1106,7 +1238,7 @@ contin:
rtnl_unlock();
}
/* this also sets saved unicast addresses */
- qeth_l2_set_multicast_list(card->dev);
+ qeth_l2_set_rx_mode(card->dev);
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
@@ -1452,8 +1584,8 @@ static void qeth_bridge_emit_host_event(struct qeth_card *card,
env[i] = str[i]; i++;
}
if (code & IPA_ADDR_CHANGE_CODE_MACADDR) {
- snprintf(str[i], sizeof(str[i]), "MAC=%pM6",
- &addr_lnid->mac);
+ snprintf(str[i], sizeof(str[i]), "MAC=%pM",
+ addr_lnid->mac);
env[i] = str[i]; i++;
}
snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x",
diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c
index 52673cd1db99..692db49e3d2a 100644
--- a/drivers/s390/net/qeth_l2_sys.c
+++ b/drivers/s390/net/qeth_l2_sys.c
@@ -109,7 +109,7 @@ static ssize_t qeth_bridge_port_state_show(struct device *dev,
return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
}
-static DEVICE_ATTR(bridge_state, 0644, qeth_bridge_port_state_show,
+static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
NULL);
static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index a1aaa36e9ebb..543960e96b42 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1065,27 +1065,6 @@ static struct qeth_cmd_buffer *qeth_l3_get_setassparms_cmd(
return iob;
}
-static int qeth_l3_send_setassparms(struct qeth_card *card,
- struct qeth_cmd_buffer *iob, __u16 len, long data,
- int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
- unsigned long),
- void *reply_param)
-{
- int rc;
- struct qeth_ipa_cmd *cmd;
-
- QETH_CARD_TEXT(card, 4, "sendassp");
-
- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
- if (len <= sizeof(__u32))
- cmd->data.setassparms.data.flags_32bit = (__u32) data;
- else /* (len > sizeof(__u32)) */
- memcpy(&cmd->data.setassparms.data, (void *) data, len);
-
- rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
- return rc;
-}
-
#ifdef CONFIG_QETH_IPV6
static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
@@ -1098,31 +1077,12 @@ static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
0, QETH_PROT_IPV6);
if (!iob)
return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob, 0, 0,
+ rc = qeth_send_setassparms(card, iob, 0, 0,
qeth_l3_default_setassparms_cb, NULL);
return rc;
}
#endif
-static int qeth_l3_send_simple_setassparms(struct qeth_card *card,
- enum qeth_ipa_funcs ipa_func, __u16 cmd_code, long data)
-{
- int rc;
- int length = 0;
- struct qeth_cmd_buffer *iob;
-
- QETH_CARD_TEXT(card, 4, "simassp4");
- if (data)
- length = sizeof(__u32);
- iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
- length, QETH_PROT_IPV4);
- if (!iob)
- return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob, length, data,
- qeth_l3_default_setassparms_cb, NULL);
- return rc;
-}
-
static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
{
int rc;
@@ -1135,8 +1095,8 @@ static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
QETH_CARD_IFNAME(card));
return 0;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
- IPA_CMD_ASS_START, 0);
+ rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+ IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
"Starting ARP processing support for %s failed\n",
@@ -1158,7 +1118,7 @@ static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
+ rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1183,7 +1143,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_SOURCE_MAC,
+ rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
IPA_CMD_ASS_START, 0);
if (rc)
dev_warn(&card->gdev->dev,
@@ -1204,7 +1164,7 @@ static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_VLAN_PRIO,
+ rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1229,7 +1189,7 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_MULTICASTING,
+ rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1259,7 +1219,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
QETH_CARD_IFNAME(card));
return rc;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_IPV6,
+ rc = qeth_send_simple_setassparms(card, IPA_IPV6,
IPA_CMD_ASS_START, 3);
if (rc) {
dev_err(&card->gdev->dev,
@@ -1319,7 +1279,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
rc = -EOPNOTSUPP;
goto out;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+ rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev, "Enabling broadcast filtering for "
@@ -1327,7 +1287,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
goto out;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+ rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_CONFIGURE, 1);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1337,7 +1297,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
}
card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
dev_info(&card->gdev->dev, "Broadcast enabled\n");
- rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+ rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_ENABLE, 1);
if (rc) {
dev_warn(&card->gdev->dev, "Setting up broadcast echo "
@@ -1353,84 +1313,18 @@ out:
return rc;
}
-static int qeth_l3_send_checksum_command(struct qeth_card *card)
-{
- int rc;
-
- rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
- IPA_CMD_ASS_START, 0);
- if (rc) {
- dev_warn(&card->gdev->dev, "Starting HW checksumming for %s "
- "failed, using SW checksumming\n",
- QETH_CARD_IFNAME(card));
- return rc;
- }
- rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
- IPA_CMD_ASS_ENABLE,
- card->info.csum_mask);
- if (rc) {
- dev_warn(&card->gdev->dev, "Enabling HW checksumming for %s "
- "failed, using SW checksumming\n",
- QETH_CARD_IFNAME(card));
- return rc;
- }
- return 0;
-}
-
-static int qeth_l3_set_rx_csum(struct qeth_card *card, int on)
-{
- int rc = 0;
-
- if (on) {
- rc = qeth_l3_send_checksum_command(card);
- if (rc)
- return -EIO;
- dev_info(&card->gdev->dev,
- "HW Checksumming (inbound) enabled\n");
- } else {
- rc = qeth_l3_send_simple_setassparms(card,
- IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0);
- if (rc)
- return -EIO;
- }
-
- return 0;
-}
-
-static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
+static void qeth_l3_start_ipa_checksum(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 3, "strtcsum");
-
- if (card->dev->features & NETIF_F_RXCSUM) {
- rtnl_lock();
- /* force set_features call */
- card->dev->features &= ~NETIF_F_RXCSUM;
- netdev_update_features(card->dev);
- rtnl_unlock();
- }
- return 0;
+ if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)
+ && (card->dev->features & NETIF_F_RXCSUM))
+ qeth_set_rx_csum(card, 1);
}
-static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card)
+static void qeth_l3_start_ipa_tx_checksum(struct qeth_card *card)
{
- int rc = 0;
-
- if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
- return rc;
- rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
- IPA_CMD_ASS_START, 0);
- if (rc)
- goto err_out;
- rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
- IPA_CMD_ASS_ENABLE, card->info.tx_csum_mask);
- if (rc)
- goto err_out;
- dev_info(&card->gdev->dev, "HW TX Checksumming enabled\n");
- return rc;
-err_out:
- dev_warn(&card->gdev->dev, "Enabling HW TX checksumming for %s "
- "failed, using SW TX checksumming\n", QETH_CARD_IFNAME(card));
- return rc;
+ QETH_CARD_TEXT(card, 3, "strttxcs");
+ qeth_start_ipa_tx_checksum(card);
}
static int qeth_l3_start_ipa_tso(struct qeth_card *card)
@@ -1445,8 +1339,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card)
QETH_CARD_IFNAME(card));
rc = -EOPNOTSUPP;
} else {
- rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
- IPA_CMD_ASS_START, 0);
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
+ IPA_CMD_ASS_START, 0);
if (rc)
dev_warn(&card->gdev->dev, "Starting outbound TCP "
"segmentation offload for %s failed\n",
@@ -1950,7 +1844,6 @@ static inline int qeth_l3_rebuild_skb(struct qeth_card *card,
skb->ip_summed = CHECKSUM_NONE;
} else
skb->ip_summed = CHECKSUM_NONE;
-
return is_vlan;
}
@@ -2287,7 +2180,7 @@ 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_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+ rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
no_entries);
if (rc) {
@@ -2552,7 +2445,7 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card,
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob,
+ rc = qeth_send_setassparms(card, iob,
sizeof(struct qeth_arp_cache_entry),
(unsigned long) entry,
qeth_l3_default_setassparms_cb, NULL);
@@ -2593,7 +2486,7 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card,
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob,
+ rc = qeth_send_setassparms(card, iob,
12, (unsigned long)buf,
qeth_l3_default_setassparms_cb, NULL);
if (rc) {
@@ -2624,7 +2517,7 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+ rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
if (rc) {
tmp = rc;
@@ -3187,7 +3080,6 @@ static netdev_features_t qeth_l3_fix_features(struct net_device *dev,
features &= ~NETIF_F_TSO;
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
features &= ~NETIF_F_RXCSUM;
-
return features;
}
@@ -3204,7 +3096,7 @@ static int qeth_l3_set_features(struct net_device *dev,
card->state == CARD_STATE_RECOVER)
return 0;
- return qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0);
+ return qeth_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0);
}
static const struct ethtool_ops qeth_l3_ethtool_ops = {
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index d8f990b6b332..a851d34c642b 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -49,7 +49,7 @@ static DEFINE_SPINLOCK(smsg_list_lock);
static LIST_HEAD(smsg_list);
static int iucv_path_connected;
-static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static int smsg_path_pending(struct iucv_path *, u8 *, u8 *);
static void smsg_message_pending(struct iucv_path *, struct iucv_message *);
static struct iucv_handler smsg_handler = {
@@ -57,8 +57,7 @@ static struct iucv_handler smsg_handler = {
.message_pending = smsg_message_pending,
};
-static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8],
- u8 ipuser[16])
+static int smsg_path_pending(struct iucv_path *path, u8 *ipvmid, u8 *ipuser)
{
if (strncmp(ipvmid, "*MSG ", 8) != 0)
return -EINVAL;
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index e9fae30fafda..b2a1a81e6fc8 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -28,6 +28,7 @@
#include <linux/io.h>
#include <linux/kvm_para.h>
#include <linux/notifier.h>
+#include <asm/diag.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/cio.h>
@@ -366,9 +367,9 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
kfree(thinint_area);
}
-static inline long do_kvm_notify(struct subchannel_id schid,
- unsigned long queue_index,
- long cookie)
+static inline long __do_kvm_notify(struct subchannel_id schid,
+ unsigned long queue_index,
+ long cookie)
{
register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY;
register struct subchannel_id __schid asm("2") = schid;
@@ -383,6 +384,14 @@ static inline long do_kvm_notify(struct subchannel_id schid,
return __rc;
}
+static inline long do_kvm_notify(struct subchannel_id schid,
+ unsigned long queue_index,
+ long cookie)
+{
+ diag_stat_inc(DIAG_STAT_X500);
+ return __do_kvm_notify(schid, queue_index, cookie);
+}
+
static bool virtio_ccw_kvm_notify(struct virtqueue *vq)
{
struct virtio_ccw_vq_info *info = vq->priv;
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index a209c3418898..d4c285688ce9 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -325,7 +325,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
tpnt->slave_destroy = NCR_700_slave_destroy;
tpnt->slave_alloc = NCR_700_slave_alloc;
tpnt->change_queue_depth = NCR_700_change_queue_depth;
- tpnt->use_blk_tags = 1;
if(tpnt->name == NULL)
tpnt->name = "53c700";
@@ -1107,7 +1106,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
BUG();
}
if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) {
- struct scsi_cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]);
+ struct scsi_cmnd *SCp;
+
+ SCp = scsi_host_find_tag(SDp->host, hostdata->msgin[2]);
if(unlikely(SCp == NULL)) {
printk(KERN_ERR "scsi%d: (%d:%d) no saved request for tag %d\n",
host->host_no, reselection_id, lun, hostdata->msgin[2]);
@@ -1119,7 +1120,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
"reselection is tag %d, slot %p(%d)\n",
hostdata->msgin[2], slot, slot->tag);
} else {
- struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG);
+ struct scsi_cmnd *SCp;
+
+ SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
if(unlikely(SCp == NULL)) {
sdev_printk(KERN_ERR, SDp,
"no saved request for untagged cmd\n");
@@ -1823,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
slot->tag, slot);
} else {
slot->tag = SCSI_NO_TAG;
- /* must populate current_cmnd for scsi_find_tag to work */
+ /* must populate current_cmnd for scsi_host_find_tag to work */
SCp->device->current_cmnd = SCp;
}
/* sanity check: some of the commands generated by the mid-layer
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 5c74e4c52fe4..867b864f5047 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -2136,7 +2136,7 @@ static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
*
*---------------------------------------------------------------------*/
-static void FPT_SccbMgrTableInitAll()
+static void FPT_SccbMgrTableInitAll(void)
{
unsigned char thisCard;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 95f7a76cfafc..5f692ae40749 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -242,13 +242,6 @@ config SCSI_SCAN_ASYNC
system continues booting, and even probe devices on different
busses in parallel, leading to a significant speed-up.
- If you have built SCSI as modules, enabling this option can
- be a problem as the devices may not have been found by the
- time your system expects them to have been. You can load the
- scsi_wait_scan module to ensure that all scans have completed.
- If you build your SCSI drivers into the kernel, then everything
- will work fine if you say Y here.
-
You can override this choice by specifying "scsi_mod.scan=sync"
or async on the kernel's command line.
@@ -541,7 +534,6 @@ config SCSI_ARCMSR
source "drivers/scsi/esas2r/Kconfig"
source "drivers/scsi/megaraid/Kconfig.megaraid"
-source "drivers/scsi/mpt2sas/Kconfig"
source "drivers/scsi/mpt3sas/Kconfig"
source "drivers/scsi/ufs/Kconfig"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1a8c9b53fafa..c14bca4a9675 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -106,7 +106,6 @@ obj-$(CONFIG_CXLFLASH) += cxlflash/
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
-obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/
obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/
obj-$(CONFIG_SCSI_UFSHCD) += ufs/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 9b3dd6ef6a0b..e4c243748a97 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -259,7 +259,7 @@ MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the"
" 0=off, 1=on");
module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(msi, "IRQ handling."
- " 0=PIC(default), 1=MSI, 2=MSI-X(unsupported, uses MSI)");
+ " 0=PIC(default), 1=MSI, 2=MSI-X)");
module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
" adapter to have it's kernel up and\n"
@@ -570,7 +570,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
- sizeof (struct aac_get_name),
+ sizeof(struct aac_get_name_resp),
FsaNormal,
0, 1,
(fib_callback)get_container_name_callback,
@@ -1052,7 +1052,7 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
- sizeof (struct aac_get_serial),
+ sizeof(struct aac_get_serial_resp),
FsaNormal,
0, 1,
(fib_callback) get_container_serial_callback,
@@ -2977,11 +2977,16 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
return;
BUG_ON(fibptr == NULL);
-
dev = fibptr->dev;
- srbreply = (struct aac_srb_reply *) fib_data(fibptr);
+ scsi_dma_unmap(scsicmd);
+ /* expose physical device if expose_physicald flag is on */
+ if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
+ && expose_physicals > 0)
+ aac_expose_phy_device(scsicmd);
+
+ srbreply = (struct aac_srb_reply *) fib_data(fibptr);
scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */
if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
@@ -2994,147 +2999,157 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
*/
scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
- le32_to_cpu(srbreply->data_xfer_length));
- }
-
- scsi_dma_unmap(scsicmd);
-
- /* expose physical device if expose_physicald flag is on */
- if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
- && expose_physicals > 0)
- aac_expose_phy_device(scsicmd);
+ /*
+ * First check the fib status
+ */
- /*
- * First check the fib status
- */
+ if (le32_to_cpu(srbreply->status) != ST_OK) {
+ int len;
- if (le32_to_cpu(srbreply->status) != ST_OK){
- int len;
- printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
- len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
- SCSI_SENSE_BUFFERSIZE);
- scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
- memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
- }
+ printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
+ len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
+ SCSI_SENSE_BUFFERSIZE);
+ scsicmd->result = DID_ERROR << 16
+ | COMMAND_COMPLETE << 8
+ | SAM_STAT_CHECK_CONDITION;
+ memcpy(scsicmd->sense_buffer,
+ srbreply->sense_data, len);
+ }
- /*
- * Next check the srb status
- */
- switch( (le32_to_cpu(srbreply->srb_status))&0x3f){
- case SRB_STATUS_ERROR_RECOVERY:
- case SRB_STATUS_PENDING:
- case SRB_STATUS_SUCCESS:
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- break;
- case SRB_STATUS_DATA_OVERRUN:
- switch(scsicmd->cmnd[0]){
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- case READ_16:
- case WRITE_16:
- if (le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow) {
- printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
- } else {
- printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
+ /*
+ * Next check the srb status
+ */
+ switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
+ case SRB_STATUS_ERROR_RECOVERY:
+ case SRB_STATUS_PENDING:
+ case SRB_STATUS_SUCCESS:
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ break;
+ case SRB_STATUS_DATA_OVERRUN:
+ switch (scsicmd->cmnd[0]) {
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ case READ_16:
+ case WRITE_16:
+ if (le32_to_cpu(srbreply->data_xfer_length)
+ < scsicmd->underflow)
+ printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
+ else
+ printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
+ scsicmd->result = DID_ERROR << 16
+ | COMMAND_COMPLETE << 8;
+ break;
+ case INQUIRY: {
+ scsicmd->result = DID_OK << 16
+ | COMMAND_COMPLETE << 8;
+ break;
+ }
+ default:
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ break;
}
- scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
break;
- case INQUIRY: {
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ case SRB_STATUS_ABORTED:
+ scsicmd->result = DID_ABORT << 16 | ABORT << 8;
break;
- }
- default:
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ case SRB_STATUS_ABORT_FAILED:
+ /*
+ * Not sure about this one - but assuming the
+ * hba was trying to abort for some reason
+ */
+ scsicmd->result = DID_ERROR << 16 | ABORT << 8;
+ break;
+ case SRB_STATUS_PARITY_ERROR:
+ scsicmd->result = DID_PARITY << 16
+ | MSG_PARITY_ERROR << 8;
+ break;
+ case SRB_STATUS_NO_DEVICE:
+ case SRB_STATUS_INVALID_PATH_ID:
+ case SRB_STATUS_INVALID_TARGET_ID:
+ case SRB_STATUS_INVALID_LUN:
+ case SRB_STATUS_SELECTION_TIMEOUT:
+ scsicmd->result = DID_NO_CONNECT << 16
+ | COMMAND_COMPLETE << 8;
break;
- }
- break;
- case SRB_STATUS_ABORTED:
- scsicmd->result = DID_ABORT << 16 | ABORT << 8;
- break;
- case SRB_STATUS_ABORT_FAILED:
- // Not sure about this one - but assuming the hba was trying to abort for some reason
- scsicmd->result = DID_ERROR << 16 | ABORT << 8;
- break;
- case SRB_STATUS_PARITY_ERROR:
- scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;
- break;
- case SRB_STATUS_NO_DEVICE:
- case SRB_STATUS_INVALID_PATH_ID:
- case SRB_STATUS_INVALID_TARGET_ID:
- case SRB_STATUS_INVALID_LUN:
- case SRB_STATUS_SELECTION_TIMEOUT:
- scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
- break;
- case SRB_STATUS_COMMAND_TIMEOUT:
- case SRB_STATUS_TIMEOUT:
- scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;
- break;
+ case SRB_STATUS_COMMAND_TIMEOUT:
+ case SRB_STATUS_TIMEOUT:
+ scsicmd->result = DID_TIME_OUT << 16
+ | COMMAND_COMPLETE << 8;
+ break;
- case SRB_STATUS_BUSY:
- scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
- break;
+ case SRB_STATUS_BUSY:
+ scsicmd->result = DID_BUS_BUSY << 16
+ | COMMAND_COMPLETE << 8;
+ break;
- case SRB_STATUS_BUS_RESET:
- scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;
- break;
+ case SRB_STATUS_BUS_RESET:
+ scsicmd->result = DID_RESET << 16
+ | COMMAND_COMPLETE << 8;
+ break;
- case SRB_STATUS_MESSAGE_REJECTED:
- scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
- break;
- case SRB_STATUS_REQUEST_FLUSHED:
- case SRB_STATUS_ERROR:
- case SRB_STATUS_INVALID_REQUEST:
- case SRB_STATUS_REQUEST_SENSE_FAILED:
- case SRB_STATUS_NO_HBA:
- case SRB_STATUS_UNEXPECTED_BUS_FREE:
- case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
- case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
- case SRB_STATUS_DELAYED_RETRY:
- case SRB_STATUS_BAD_FUNCTION:
- case SRB_STATUS_NOT_STARTED:
- case SRB_STATUS_NOT_IN_USE:
- case SRB_STATUS_FORCE_ABORT:
- case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
- default:
+ case SRB_STATUS_MESSAGE_REJECTED:
+ scsicmd->result = DID_ERROR << 16
+ | MESSAGE_REJECT << 8;
+ break;
+ case SRB_STATUS_REQUEST_FLUSHED:
+ case SRB_STATUS_ERROR:
+ case SRB_STATUS_INVALID_REQUEST:
+ case SRB_STATUS_REQUEST_SENSE_FAILED:
+ case SRB_STATUS_NO_HBA:
+ case SRB_STATUS_UNEXPECTED_BUS_FREE:
+ case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
+ case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
+ case SRB_STATUS_DELAYED_RETRY:
+ case SRB_STATUS_BAD_FUNCTION:
+ case SRB_STATUS_NOT_STARTED:
+ case SRB_STATUS_NOT_IN_USE:
+ case SRB_STATUS_FORCE_ABORT:
+ case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
+ default:
#ifdef AAC_DETAILED_STATUS_INFO
- printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
- le32_to_cpu(srbreply->srb_status) & 0x3F,
- aac_get_status_string(
- le32_to_cpu(srbreply->srb_status) & 0x3F),
- scsicmd->cmnd[0],
- le32_to_cpu(srbreply->scsi_status));
+ printk(KERN_INFO "aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
+ le32_to_cpu(srbreply->srb_status) & 0x3F,
+ aac_get_status_string(
+ le32_to_cpu(srbreply->srb_status) & 0x3F),
+ scsicmd->cmnd[0],
+ le32_to_cpu(srbreply->scsi_status));
#endif
- if ((scsicmd->cmnd[0] == ATA_12)
- || (scsicmd->cmnd[0] == ATA_16)) {
- if (scsicmd->cmnd[2] & (0x01 << 5)) {
- scsicmd->result = DID_OK << 16
- | COMMAND_COMPLETE << 8;
+ if ((scsicmd->cmnd[0] == ATA_12)
+ || (scsicmd->cmnd[0] == ATA_16)) {
+ if (scsicmd->cmnd[2] & (0x01 << 5)) {
+ scsicmd->result = DID_OK << 16
+ | COMMAND_COMPLETE << 8;
break;
+ } else {
+ scsicmd->result = DID_ERROR << 16
+ | COMMAND_COMPLETE << 8;
+ break;
+ }
} else {
scsicmd->result = DID_ERROR << 16
- | COMMAND_COMPLETE << 8;
+ | COMMAND_COMPLETE << 8;
break;
}
- } else {
- scsicmd->result = DID_ERROR << 16
- | COMMAND_COMPLETE << 8;
- break;
}
- }
- if (le32_to_cpu(srbreply->scsi_status) == SAM_STAT_CHECK_CONDITION) {
- int len;
- scsicmd->result |= SAM_STAT_CHECK_CONDITION;
- len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
- SCSI_SENSE_BUFFERSIZE);
+ if (le32_to_cpu(srbreply->scsi_status)
+ == SAM_STAT_CHECK_CONDITION) {
+ int len;
+
+ scsicmd->result |= SAM_STAT_CHECK_CONDITION;
+ len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
+ SCSI_SENSE_BUFFERSIZE);
#ifdef AAC_DETAILED_STATUS_INFO
- printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
- le32_to_cpu(srbreply->status), len);
+ printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
+ le32_to_cpu(srbreply->status), len);
#endif
- memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
+ memcpy(scsicmd->sense_buffer,
+ srbreply->sense_data, len);
+ }
}
/*
* OR in the scsi status (already shifted up a bit)
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 40fe65c91b41..074878b55a0b 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,7 +12,7 @@
* D E F I N E S
*----------------------------------------------------------------------------*/
-#define AAC_MAX_MSIX 8 /* vectors */
+#define AAC_MAX_MSIX 32 /* vectors */
#define AAC_PCI_MSI_ENABLE 0x8000
enum {
@@ -62,7 +62,7 @@ enum {
#define PMC_GLOBAL_INT_BIT0 0x00000001
#ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 40709
+# define AAC_DRIVER_BUILD 41010
# define AAC_DRIVER_BRANCH "-ms"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@@ -547,6 +547,7 @@ struct adapter_ops
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
int (*adapter_restart)(struct aac_dev *dev, int bled);
+ void (*adapter_start)(struct aac_dev *dev);
/* Transport operations */
int (*adapter_ioremap)(struct aac_dev * dev, u32 size);
irq_handler_t adapter_intr;
@@ -843,6 +844,10 @@ struct src_registers {
&((AEP)->regs.src.bar0->CSR))
#define src_writel(AEP, CSR, value) writel(value, \
&((AEP)->regs.src.bar0->CSR))
+#if defined(writeq)
+#define src_writeq(AEP, CSR, value) writeq(value, \
+ &((AEP)->regs.src.bar0->CSR))
+#endif
#define SRC_ODR_SHIFT 12
#define SRC_IDR_SHIFT 9
@@ -1162,6 +1167,11 @@ struct aac_dev
struct fsa_dev_info *fsa_dev;
struct task_struct *thread;
int cardtype;
+ /*
+ *This lock will protect the two 32-bit
+ *writes to the Inbound Queue
+ */
+ spinlock_t iq_lock;
/*
* The following is the device specific extension.
@@ -1247,6 +1257,9 @@ struct aac_dev
#define aac_adapter_restart(dev,bled) \
(dev)->a_ops.adapter_restart(dev,bled)
+#define aac_adapter_start(dev) \
+ ((dev)->a_ops.adapter_start(dev))
+
#define aac_adapter_ioremap(dev, size) \
(dev)->a_ops.adapter_ioremap(dev, size)
@@ -2097,6 +2110,8 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
#define AAC_OWNER_ERROR_HANDLER 0x103
#define AAC_OWNER_FIRMWARE 0x106
+int aac_acquire_irq(struct aac_dev *dev);
+void aac_free_irq(struct aac_dev *dev);
const char *aac_driverinfo(struct Scsi_Host *);
struct fib *aac_fib_alloc(struct aac_dev *dev);
int aac_fib_setup(struct aac_dev *dev);
@@ -2127,6 +2142,7 @@ int aac_sa_init(struct aac_dev *dev);
int aac_src_init(struct aac_dev *dev);
int aac_srcv_init(struct aac_dev *dev);
int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
+void aac_define_int_mode(struct aac_dev *dev);
unsigned int aac_response_normal(struct aac_queue * q);
unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 45db84ad322f..0e954e37f0b5 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -43,8 +43,6 @@
#include "aacraid.h"
-static void aac_define_int_mode(struct aac_dev *dev);
-
struct aac_common aac_config = {
.irq_mod = 1
};
@@ -338,6 +336,74 @@ static int aac_comm_init(struct aac_dev * dev)
return 0;
}
+void aac_define_int_mode(struct aac_dev *dev)
+{
+ int i, msi_count, min_msix;
+
+ msi_count = i = 0;
+ /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
+ if (dev->max_msix == 0 ||
+ dev->pdev->device == PMC_DEVICE_S6 ||
+ dev->sync_mode) {
+ dev->max_msix = 1;
+ dev->vector_cap =
+ dev->scsi_host_ptr->can_queue +
+ AAC_NUM_MGT_FIB;
+ return;
+ }
+
+ /* Don't bother allocating more MSI-X vectors than cpus */
+ msi_count = min(dev->max_msix,
+ (unsigned int)num_online_cpus());
+
+ dev->max_msix = msi_count;
+
+ if (msi_count > AAC_MAX_MSIX)
+ msi_count = AAC_MAX_MSIX;
+
+ for (i = 0; i < msi_count; i++)
+ dev->msixentry[i].entry = i;
+
+ if (msi_count > 1 &&
+ pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
+ min_msix = 2;
+ i = pci_enable_msix_range(dev->pdev,
+ dev->msixentry,
+ min_msix,
+ msi_count);
+ if (i > 0) {
+ dev->msi_enabled = 1;
+ msi_count = i;
+ } else {
+ dev->msi_enabled = 0;
+ printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
+ dev->name, dev->id, i);
+ }
+ }
+
+ if (!dev->msi_enabled) {
+ msi_count = 1;
+ i = pci_enable_msi(dev->pdev);
+
+ if (!i) {
+ dev->msi_enabled = 1;
+ dev->msi = 1;
+ } else {
+ printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
+ dev->name, dev->id, i);
+ }
+ }
+
+ if (!dev->msi_enabled)
+ dev->max_msix = msi_count = 1;
+ else {
+ if (dev->max_msix > msi_count)
+ dev->max_msix = msi_count;
+ }
+ dev->vector_cap =
+ (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
+ msi_count;
+}
struct aac_dev *aac_init_adapter(struct aac_dev *dev)
{
u32 status[5];
@@ -350,6 +416,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->management_fib_count = 0;
spin_lock_init(&dev->manage_lock);
spin_lock_init(&dev->sync_lock);
+ spin_lock_init(&dev->iq_lock);
dev->max_fib_size = sizeof(struct hw_fib);
dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
- sizeof(struct aac_fibhdr)
@@ -508,79 +575,3 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
return dev;
}
-static void aac_define_int_mode(struct aac_dev *dev)
-{
-
- int i, msi_count;
-
- msi_count = i = 0;
- /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
- if (dev->max_msix == 0 ||
- dev->pdev->device == PMC_DEVICE_S6 ||
- dev->sync_mode) {
- dev->max_msix = 1;
- dev->vector_cap =
- dev->scsi_host_ptr->can_queue +
- AAC_NUM_MGT_FIB;
- return;
- }
-
- msi_count = min(dev->max_msix,
- (unsigned int)num_online_cpus());
-
- dev->max_msix = msi_count;
-
- if (msi_count > AAC_MAX_MSIX)
- msi_count = AAC_MAX_MSIX;
-
- for (i = 0; i < msi_count; i++)
- dev->msixentry[i].entry = i;
-
- if (msi_count > 1 &&
- pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
- i = pci_enable_msix(dev->pdev,
- dev->msixentry,
- msi_count);
- /* Check how many MSIX vectors are allocated */
- if (i >= 0) {
- dev->msi_enabled = 1;
- if (i) {
- msi_count = i;
- if (pci_enable_msix(dev->pdev,
- dev->msixentry,
- msi_count)) {
- dev->msi_enabled = 0;
- printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
- dev->name, dev->id, i);
- }
- }
- } else {
- dev->msi_enabled = 0;
- printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
- dev->name, dev->id, i);
- }
- }
-
- if (!dev->msi_enabled) {
- msi_count = 1;
- i = pci_enable_msi(dev->pdev);
-
- if (!i) {
- dev->msi_enabled = 1;
- dev->msi = 1;
- } else {
- printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
- dev->name, dev->id, i);
- }
- }
-
- if (!dev->msi_enabled)
- dev->max_msix = msi_count = 1;
- else {
- if (dev->max_msix > msi_count)
- dev->max_msix = msi_count;
- }
- dev->vector_cap =
- (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
- msi_count;
-}
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 4da574925284..a1f90fe849c9 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1270,13 +1270,12 @@ retry_next:
static int _aac_reset_adapter(struct aac_dev *aac, int forced)
{
int index, quirks;
- int retval, i;
+ int retval;
struct Scsi_Host *host;
struct scsi_device *dev;
struct scsi_cmnd *command;
struct scsi_cmnd *command_list;
int jafo = 0;
- int cpu;
/*
* Assumptions:
@@ -1339,35 +1338,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
aac->comm_phys = 0;
kfree(aac->queues);
aac->queues = NULL;
- cpu = cpumask_first(cpu_online_mask);
- if (aac->pdev->device == PMC_DEVICE_S6 ||
- aac->pdev->device == PMC_DEVICE_S7 ||
- aac->pdev->device == PMC_DEVICE_S8 ||
- aac->pdev->device == PMC_DEVICE_S9) {
- if (aac->max_msix > 1) {
- for (i = 0; i < aac->max_msix; i++) {
- if (irq_set_affinity_hint(
- aac->msixentry[i].vector,
- NULL)) {
- printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
- aac->name,
- aac->id,
- cpu);
- }
- cpu = cpumask_next(cpu,
- cpu_online_mask);
- free_irq(aac->msixentry[i].vector,
- &(aac->aac_msix[i]));
- }
- pci_disable_msix(aac->pdev);
- } else {
- free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
- }
- } else {
- free_irq(aac->pdev->irq, aac);
- }
- if (aac->msi)
- pci_disable_msi(aac->pdev);
+ aac_free_irq(aac);
kfree(aac->fsa_dev);
aac->fsa_dev = NULL;
quirks = aac_get_driver_ident(index)->quirks;
@@ -1978,3 +1949,83 @@ int aac_command_thread(void *data)
dev->aif_thread = 0;
return 0;
}
+
+int aac_acquire_irq(struct aac_dev *dev)
+{
+ int i;
+ int j;
+ int ret = 0;
+ int cpu;
+
+ cpu = cpumask_first(cpu_online_mask);
+ if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
+ for (i = 0; i < dev->max_msix; i++) {
+ dev->aac_msix[i].vector_no = i;
+ dev->aac_msix[i].dev = dev;
+ if (request_irq(dev->msixentry[i].vector,
+ dev->a_ops.adapter_intr,
+ 0, "aacraid", &(dev->aac_msix[i]))) {
+ printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
+ dev->name, dev->id, i);
+ for (j = 0 ; j < i ; j++)
+ free_irq(dev->msixentry[j].vector,
+ &(dev->aac_msix[j]));
+ pci_disable_msix(dev->pdev);
+ ret = -1;
+ }
+ if (irq_set_affinity_hint(dev->msixentry[i].vector,
+ get_cpu_mask(cpu))) {
+ printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
+ dev->name, dev->id, cpu);
+ }
+ cpu = cpumask_next(cpu, cpu_online_mask);
+ }
+ } else {
+ dev->aac_msix[0].vector_no = 0;
+ dev->aac_msix[0].dev = dev;
+
+ if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
+ IRQF_SHARED, "aacraid",
+ &(dev->aac_msix[0])) < 0) {
+ if (dev->msi)
+ pci_disable_msi(dev->pdev);
+ printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+ dev->name, dev->id);
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+void aac_free_irq(struct aac_dev *dev)
+{
+ int i;
+ int cpu;
+
+ cpu = cpumask_first(cpu_online_mask);
+ if (dev->pdev->device == PMC_DEVICE_S6 ||
+ dev->pdev->device == PMC_DEVICE_S7 ||
+ dev->pdev->device == PMC_DEVICE_S8 ||
+ dev->pdev->device == PMC_DEVICE_S9) {
+ if (dev->max_msix > 1) {
+ for (i = 0; i < dev->max_msix; i++) {
+ if (irq_set_affinity_hint(
+ dev->msixentry[i].vector, NULL)) {
+ printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
+ dev->name, dev->id, cpu);
+ }
+ cpu = cpumask_next(cpu, cpu_online_mask);
+ free_irq(dev->msixentry[i].vector,
+ &(dev->aac_msix[i]));
+ }
+ } else {
+ free_irq(dev->pdev->irq, &(dev->aac_msix[0]));
+ }
+ } else {
+ free_irq(dev->pdev->irq, dev);
+ }
+ if (dev->msi)
+ pci_disable_msi(dev->pdev);
+ else if (dev->max_msix > 1)
+ pci_disable_msix(dev->pdev);
+}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 9eec02733c86..3b6e5c67e853 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1317,6 +1317,154 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
return error;
}
+#if (defined(CONFIG_PM))
+void aac_release_resources(struct aac_dev *aac)
+{
+ int i;
+
+ aac_adapter_disable_int(aac);
+ if (aac->pdev->device == PMC_DEVICE_S6 ||
+ aac->pdev->device == PMC_DEVICE_S7 ||
+ aac->pdev->device == PMC_DEVICE_S8 ||
+ aac->pdev->device == PMC_DEVICE_S9) {
+ if (aac->max_msix > 1) {
+ for (i = 0; i < aac->max_msix; i++)
+ free_irq(aac->msixentry[i].vector,
+ &(aac->aac_msix[i]));
+ } else {
+ free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
+ }
+ } else {
+ free_irq(aac->pdev->irq, aac);
+ }
+ if (aac->msi)
+ pci_disable_msi(aac->pdev);
+ else if (aac->max_msix > 1)
+ pci_disable_msix(aac->pdev);
+
+}
+
+static int aac_acquire_resources(struct aac_dev *dev)
+{
+ int i, j;
+ int instance = dev->id;
+ const char *name = dev->name;
+ unsigned long status;
+ /*
+ * First clear out all interrupts. Then enable the one's that we
+ * can handle.
+ */
+ while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)
+ || status == 0xffffffff)
+ msleep(20);
+
+ aac_adapter_disable_int(dev);
+ aac_adapter_enable_int(dev);
+
+
+ if ((dev->pdev->device == PMC_DEVICE_S7 ||
+ dev->pdev->device == PMC_DEVICE_S8 ||
+ dev->pdev->device == PMC_DEVICE_S9))
+ aac_define_int_mode(dev);
+
+ if (dev->msi_enabled)
+ aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
+
+ if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
+ for (i = 0; i < dev->max_msix; i++) {
+ dev->aac_msix[i].vector_no = i;
+ dev->aac_msix[i].dev = dev;
+
+ if (request_irq(dev->msixentry[i].vector,
+ dev->a_ops.adapter_intr,
+ 0, "aacraid", &(dev->aac_msix[i]))) {
+ printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
+ name, instance, i);
+ for (j = 0 ; j < i ; j++)
+ free_irq(dev->msixentry[j].vector,
+ &(dev->aac_msix[j]));
+ pci_disable_msix(dev->pdev);
+ goto error_iounmap;
+ }
+ }
+ } else {
+ dev->aac_msix[0].vector_no = 0;
+ dev->aac_msix[0].dev = dev;
+
+ if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
+ IRQF_SHARED, "aacraid",
+ &(dev->aac_msix[0])) < 0) {
+ if (dev->msi)
+ pci_disable_msi(dev->pdev);
+ printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+ name, instance);
+ goto error_iounmap;
+ }
+ }
+
+ aac_adapter_enable_int(dev);
+
+ if (!dev->sync_mode)
+ aac_adapter_start(dev);
+ return 0;
+
+error_iounmap:
+ return -1;
+
+}
+static int aac_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+
+ scsi_block_requests(shost);
+ aac_send_shutdown(aac);
+
+ aac_release_resources(aac);
+
+ pci_set_drvdata(pdev, shost);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int aac_resume(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+ int r;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ pci_restore_state(pdev);
+ r = pci_enable_device(pdev);
+
+ if (r)
+ goto fail_device;
+
+ pci_set_master(pdev);
+ if (aac_acquire_resources(aac))
+ goto fail_device;
+ /*
+ * reset this flag to unblock ioctl() as it was set at
+ * aac_send_shutdown() to block ioctls from upperlayer
+ */
+ aac->adapter_shutdown = 0;
+ scsi_unblock_requests(shost);
+
+ return 0;
+
+fail_device:
+ printk(KERN_INFO "%s%d: resume failed.\n", aac->name, aac->id);
+ scsi_host_put(shost);
+ pci_disable_device(pdev);
+ return -ENODEV;
+}
+#endif
+
static void aac_shutdown(struct pci_dev *dev)
{
struct Scsi_Host *shost = pci_get_drvdata(dev);
@@ -1356,6 +1504,10 @@ static struct pci_driver aac_pci_driver = {
.id_table = aac_pci_tbl,
.probe = aac_probe_one,
.remove = aac_remove_one,
+#if (defined(CONFIG_PM))
+ .suspend = aac_suspend,
+ .resume = aac_resume,
+#endif
.shutdown = aac_shutdown,
};
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 9570612b80ce..ac1638069335 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -623,6 +623,7 @@ int _aac_rx_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_check_health = aac_rx_check_health;
dev->a_ops.adapter_restart = aac_rx_restart_adapter;
+ dev->a_ops.adapter_start = aac_rx_start_adapter;
/*
* First clear out all interrupts. Then enable the one's that we
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index e66477c98240..869aea23c041 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -372,6 +372,7 @@ int aac_sa_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
dev->a_ops.adapter_restart = aac_sa_restart_adapter;
+ dev->a_ops.adapter_start = aac_sa_start_adapter;
dev->a_ops.adapter_intr = aac_sa_intr;
dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
dev->a_ops.adapter_ioremap = aac_sa_ioremap;
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index e63cf9f22f36..2aa34ea8ceb1 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -447,6 +447,10 @@ static int aac_src_deliver_message(struct fib *fib)
u32 fibsize;
dma_addr_t address;
struct aac_fib_xporthdr *pFibX;
+#if !defined(writeq)
+ unsigned long flags;
+#endif
+
u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
atomic_inc(&q->numpending);
@@ -511,10 +515,14 @@ static int aac_src_deliver_message(struct fib *fib)
return -EINVAL;
address |= fibsize;
}
-
+#if defined(writeq)
+ src_writeq(dev, MUnit.IQ_L, (u64)address);
+#else
+ spin_lock_irqsave(&fib->dev->iq_lock, flags);
src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff);
src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
-
+ spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
+#endif
return 0;
}
@@ -726,6 +734,7 @@ int aac_src_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_check_health = aac_src_check_health;
dev->a_ops.adapter_restart = aac_src_restart_adapter;
+ dev->a_ops.adapter_start = aac_src_start_adapter;
/*
* First clear out all interrupts. Then enable the one's that we
@@ -741,7 +750,7 @@ int aac_src_init(struct aac_dev *dev)
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
goto error_iounmap;
- dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
+ dev->msi = !pci_enable_msi(dev->pdev);
dev->aac_msix[0].vector_no = 0;
dev->aac_msix[0].dev = dev;
@@ -789,9 +798,7 @@ int aac_srcv_init(struct aac_dev *dev)
unsigned long status;
int restart = 0;
int instance = dev->id;
- int i, j;
const char *name = dev->name;
- int cpu;
dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
dev->a_ops.adapter_comm = aac_src_select_comm;
@@ -892,6 +899,7 @@ int aac_srcv_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_check_health = aac_src_check_health;
dev->a_ops.adapter_restart = aac_src_restart_adapter;
+ dev->a_ops.adapter_start = aac_src_start_adapter;
/*
* First clear out all interrupts. Then enable the one's that we
@@ -908,48 +916,10 @@ int aac_srcv_init(struct aac_dev *dev)
goto error_iounmap;
if (dev->msi_enabled)
aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
- if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
- cpu = cpumask_first(cpu_online_mask);
- for (i = 0; i < dev->max_msix; i++) {
- dev->aac_msix[i].vector_no = i;
- dev->aac_msix[i].dev = dev;
-
- if (request_irq(dev->msixentry[i].vector,
- dev->a_ops.adapter_intr,
- 0,
- "aacraid",
- &(dev->aac_msix[i]))) {
- printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
- name, instance, i);
- for (j = 0 ; j < i ; j++)
- free_irq(dev->msixentry[j].vector,
- &(dev->aac_msix[j]));
- pci_disable_msix(dev->pdev);
- goto error_iounmap;
- }
- if (irq_set_affinity_hint(
- dev->msixentry[i].vector,
- get_cpu_mask(cpu))) {
- printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
- name, instance, cpu);
- }
- cpu = cpumask_next(cpu, cpu_online_mask);
- }
- } else {
- dev->aac_msix[0].vector_no = 0;
- dev->aac_msix[0].dev = dev;
-
- if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
- IRQF_SHARED,
- "aacraid",
- &(dev->aac_msix[0])) < 0) {
- if (dev->msi)
- pci_disable_msi(dev->pdev);
- printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
- name, instance);
- goto error_iounmap;
- }
- }
+
+ if (aac_acquire_irq(dev))
+ goto error_iounmap;
+
dev->dbg_base = dev->base_start;
dev->dbg_base_mapped = dev->base;
dev->dbg_size = dev->base_size;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 4305178e4e01..519f9a4b3dad 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -10819,7 +10819,6 @@ static struct scsi_host_template advansys_template = {
* by enabling clustering, I/O throughput increases as well.
*/
.use_clustering = ENABLE_CLUSTERING,
- .use_blk_tags = 1,
};
static int advansys_wide_init_chip(struct Scsi_Host *shost)
@@ -11211,11 +11210,6 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
/* Set maximum number of queues the adapter can handle. */
shost->can_queue = adv_dvc_varp->max_host_qng;
}
- ret = scsi_init_shared_tag_map(shost, shost->can_queue);
- if (ret) {
- shost_printk(KERN_ERR, shost, "init tag map failed\n");
- goto err_free_dma;
- }
/*
* Set the maximum number of scatter-gather elements the
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index ce96a0be3282..2588b8f84ba0 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -925,7 +925,6 @@ struct scsi_host_template aic79xx_driver_template = {
.slave_configure = ahd_linux_slave_configure,
.target_alloc = ahd_linux_target_alloc,
.target_destroy = ahd_linux_target_destroy,
- .use_blk_tags = 1,
};
/******************************** Bus DMA *************************************/
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index a2f2c774cd6b..b846a4683562 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -812,7 +812,6 @@ struct scsi_host_template aic7xxx_driver_template = {
.slave_configure = ahc_linux_slave_configure,
.target_alloc = ahc_linux_target_alloc,
.target_destroy = ahc_linux_target_destroy,
- .use_blk_tags = 1,
};
/**************************** Tasklet Handler *********************************/
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index f6c336b05d5b..662b2321d1b0 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -73,7 +73,6 @@ static struct scsi_host_template aic94xx_sht = {
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -704,10 +703,10 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha)
{
int err;
+ scsi_remove_host(asd_ha->sas_ha.core.shost);
err = sas_unregister_ha(&asd_ha->sas_ha);
sas_remove_host(asd_ha->sas_ha.core.shost);
- scsi_remove_host(asd_ha->sas_ha.core.shost);
scsi_host_put(asd_ha->sas_ha.core.shost);
kfree(asd_ha->sas_ha.sas_phy);
diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig
index ceaca32e788d..4e7cad272469 100644
--- a/drivers/scsi/be2iscsi/Kconfig
+++ b/drivers/scsi/be2iscsi/Kconfig
@@ -1,9 +1,9 @@
config BE2ISCSI
- tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2"
+ tristate "Emulex 10Gbps iSCSI - BladeEngine 2"
depends on PCI && SCSI && NET
select SCSI_ISCSI_ATTRS
select ISCSI_BOOT_SYSFS
help
- This driver implements the iSCSI functionality for ServerEngines'
+ This driver implements the iSCSI functionality for Emulex
10Gbps Storage adapter - BladeEngine 2.
diff --git a/drivers/scsi/be2iscsi/Makefile b/drivers/scsi/be2iscsi/Makefile
index c11f443e3f83..d0488eaafc25 100644
--- a/drivers/scsi/be2iscsi/Makefile
+++ b/drivers/scsi/be2iscsi/Makefile
@@ -1,5 +1,5 @@
#
-# Makefile to build the iSCSI driver for ServerEngine's BladeEngine.
+# Makefile to build the iSCSI driver for Emulex OneConnect.
#
#
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index 32070099c333..77f992e74726 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 185391a64d4b..2778089b01a5 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index cdfbc5c19cf4..4bfca355fbe4 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 2f0700796842..b7087ba69d8d 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 7a6dbfbccec9..fe0c5143f8e6 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
@@ -50,7 +50,7 @@ static unsigned int enable_msix = 1;
MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
MODULE_VERSION(BUILD_STR);
-MODULE_AUTHOR("Avago Technologies");
+MODULE_AUTHOR("Emulex Corporation");
MODULE_LICENSE("GPL");
module_param(be_iopoll_budget, int, 0);
module_param(enable_msix, int, 0);
@@ -552,7 +552,7 @@ MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
static struct scsi_host_template beiscsi_sht = {
.module = THIS_MODULE,
- .name = "Avago Technologies 10Gbe open-iscsi Initiator Driver",
+ .name = "Emulex 10Gbe open-iscsi Initiator Driver",
.proc_name = DRV_NAME,
.queuecommand = iscsi_queuecommand,
.change_queue_depth = scsi_change_queue_depth,
@@ -1198,14 +1198,16 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
* alloc_wrb_handle - To allocate a wrb handle
* @phba: The hba pointer
* @cid: The cid to use for allocation
+ * @pwrb_context: ptr to ptr to wrb context
*
* This happens under session_lock until submission to chip
*/
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+ struct hwi_wrb_context **pcontext)
{
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
- struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
+ struct wrb_handle *pwrb_handle;
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
phwi_ctrlr = phba->phwi_ctrlr;
@@ -1219,9 +1221,9 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
pwrb_context->alloc_index = 0;
else
pwrb_context->alloc_index++;
- pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
- pwrb_context->alloc_index];
- pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index;
+
+ /* Return the context address */
+ *pcontext = pwrb_context;
} else
pwrb_handle = NULL;
return pwrb_handle;
@@ -3184,7 +3186,7 @@ be_sgl_create_contiguous(void *virtual_address,
{
WARN_ON(!virtual_address);
WARN_ON(!physical_address);
- WARN_ON(!length > 0);
+ WARN_ON(!length);
WARN_ON(!sgl);
sgl->va = virtual_address;
@@ -4678,6 +4680,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_offload_params *params)
{
struct wrb_handle *pwrb_handle;
+ struct hwi_wrb_context *pwrb_context = NULL;
struct beiscsi_hba *phba = beiscsi_conn->phba;
struct iscsi_task *task = beiscsi_conn->task;
struct iscsi_session *session = task->conn->session;
@@ -4692,14 +4695,17 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
beiscsi_cleanup_task(task);
spin_unlock_bh(&session->back_lock);
- pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid);
+ pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid,
+ &pwrb_context);
/* Check for the adapter family */
if (is_chip_be2_be3r(phba))
beiscsi_offload_cxn_v0(params, pwrb_handle,
- phba->init_mem);
+ phba->init_mem,
+ pwrb_context);
else
- beiscsi_offload_cxn_v2(params, pwrb_handle);
+ beiscsi_offload_cxn_v2(params, pwrb_handle,
+ pwrb_context);
be_dws_le_to_cpu(pwrb_handle->pwrb,
sizeof(struct iscsi_target_context_update_wrb));
@@ -4769,7 +4775,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
goto free_hndls;
}
io_task->pwrb_handle = alloc_wrb_handle(phba,
- beiscsi_conn->beiscsi_conn_cid);
+ beiscsi_conn->beiscsi_conn_cid,
+ &io_task->pwrb_context);
if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4803,7 +4810,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
io_task->psgl_handle;
io_task->pwrb_handle =
alloc_wrb_handle(phba,
- beiscsi_conn->beiscsi_conn_cid);
+ beiscsi_conn->beiscsi_conn_cid,
+ &io_task->pwrb_context);
if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO |
@@ -4839,7 +4847,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
}
io_task->pwrb_handle =
alloc_wrb_handle(phba,
- beiscsi_conn->beiscsi_conn_cid);
+ beiscsi_conn->beiscsi_conn_cid,
+ &io_task->pwrb_context);
if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4925,7 +4934,12 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
hwi_write_sgl_v2(pwrb, sg, num_sg, io_task);
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
- io_task->pwrb_handle->nxt_wrb_index);
+ io_task->pwrb_handle->wrb_index);
+ if (io_task->pwrb_context->plast_wrb)
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb,
+ io_task->pwrb_context->plast_wrb,
+ io_task->pwrb_handle->wrb_index);
+ io_task->pwrb_context->plast_wrb = pwrb;
be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
@@ -4982,7 +4996,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
hwi_write_sgl(pwrb, sg, num_sg, io_task);
AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
- io_task->pwrb_handle->nxt_wrb_index);
+ io_task->pwrb_handle->wrb_index);
+ if (io_task->pwrb_context->plast_wrb)
+ AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb,
+ io_task->pwrb_context->plast_wrb,
+ io_task->pwrb_handle->wrb_index);
+ io_task->pwrb_context->plast_wrb = pwrb;
+
be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
@@ -5020,7 +5040,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
task->data_count);
AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
- io_task->pwrb_handle->nxt_wrb_index);
+ io_task->pwrb_handle->wrb_index);
+ if (io_task->pwrb_context->plast_wrb)
+ AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb,
+ io_task->pwrb_context->plast_wrb,
+ io_task->pwrb_handle->wrb_index);
+ io_task->pwrb_context->plast_wrb = pwrb;
+
pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
} else {
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
@@ -5032,7 +5058,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
task->data_count);
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
- io_task->pwrb_handle->nxt_wrb_index);
+ io_task->pwrb_handle->wrb_index);
+ if (io_task->pwrb_context->plast_wrb)
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb,
+ io_task->pwrb_context->plast_wrb,
+ io_task->pwrb_handle->wrb_index);
+ io_task->pwrb_context->plast_wrb = pwrb;
+
pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
}
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index b8c0c7819cb1..5c67c0732241 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
@@ -36,8 +36,8 @@
#include <scsi/scsi_transport_iscsi.h>
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "10.6.0.0"
-#define BE_NAME "Avago Technologies OneConnect" \
+#define BUILD_STR "10.6.0.1"
+#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@@ -502,6 +502,7 @@ struct beiscsi_io_task {
struct sgl_handle *psgl_handle;
struct beiscsi_conn *conn;
struct scsi_cmnd *scsi_cmnd;
+ struct hwi_wrb_context *pwrb_context;
unsigned int cmd_sn;
unsigned int flags;
unsigned short cid;
@@ -833,7 +834,8 @@ struct amap_iscsi_wrb_v2 {
} __packed;
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid);
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+ struct hwi_wrb_context **pcontext);
void
free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
@@ -1044,7 +1046,6 @@ enum hwh_type_enum {
struct wrb_handle {
enum hwh_type_enum type;
unsigned short wrb_index;
- unsigned short nxt_wrb_index;
struct iscsi_task *pio_handle;
struct iscsi_wrb *pwrb;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index ca4016f20e76..aea3e6b9477d 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
@@ -1573,7 +1573,8 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle,
- struct be_mem_descriptor *mem_descr)
+ struct be_mem_descriptor *mem_descr,
+ struct hwi_wrb_context *pwrb_context)
{
struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
@@ -1617,7 +1618,14 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
max_burst_length) / 32]);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
- pwrb, pwrb_handle->nxt_wrb_index);
+ pwrb, pwrb_handle->wrb_index);
+ if (pwrb_context->plast_wrb)
+ AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+ ptr2nextwrb,
+ pwrb_context->plast_wrb,
+ pwrb_handle->wrb_index);
+ pwrb_context->plast_wrb = pwrb;
+
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
session_state, pwrb, 0);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
@@ -1637,7 +1645,8 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
}
void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
- struct wrb_handle *pwrb_handle)
+ struct wrb_handle *pwrb_handle,
+ struct hwi_wrb_context *pwrb_context)
{
struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
@@ -1652,7 +1661,14 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
BE_TGT_CTX_UPDT_CMD);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
ptr2nextwrb,
- pwrb, pwrb_handle->nxt_wrb_index);
+ pwrb, pwrb_handle->wrb_index);
+ if (pwrb_context->plast_wrb)
+ AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+ ptr2nextwrb,
+ pwrb_context->plast_wrb,
+ pwrb_handle->wrb_index);
+ pwrb_context->plast_wrb = pwrb;
+
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
pwrb, pwrb_handle->wrb_index);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index b58a7decbd94..c1dbb690ee27 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2015 Avago Technologies
+ * Copyright (C) 2005 - 2015 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -12,7 +12,7 @@
* Contact Information:
* linux-drivers@avagotech.com
*
- * Avago Technologies
+ * Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
@@ -330,10 +330,13 @@ ssize_t beiscsi_phys_port_disp(struct device *dev,
void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle,
- struct be_mem_descriptor *mem_descr);
+ struct be_mem_descriptor *mem_descr,
+ struct hwi_wrb_context *pwrb_context);
void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
- struct wrb_handle *pwrb_handle);
+ struct wrb_handle *pwrb_handle,
+ struct hwi_wrb_context *pwrb_context);
+
void beiscsi_ue_detect(struct beiscsi_hba *phba);
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *, int num);
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 8367c11d554b..299c6f80d460 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -800,7 +800,6 @@ struct scsi_host_template bfad_im_scsi_host_template = {
.shost_attrs = bfad_im_host_attrs,
.max_sectors = BFAD_MAX_SECTORS,
.vendor_id = BFA_PCI_VENDOR_ID_BROCADE,
- .use_blk_tags = 1,
};
struct scsi_host_template bfad_im_vport_template = {
@@ -822,7 +821,6 @@ struct scsi_host_template bfad_im_vport_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = bfad_im_vport_attrs,
.max_sectors = BFAD_MAX_SECTORS,
- .use_blk_tags = 1,
};
bfa_status_t
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index fe2106c91c08..ac1c0b631aca 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -1,9 +1,9 @@
-/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* 57xx_hsi_bnx2fc.h: QLogic Linux FCoE offload driver.
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
index 097882882649..d401a096dfc7 100644
--- a/drivers/scsi/bnx2fc/Kconfig
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -1,5 +1,5 @@
config SCSI_BNX2X_FCOE
- tristate "QLogic NetXtreme II FCoE support"
+ tristate "QLogic FCoE offload support"
depends on PCI
depends on (IPV6 || IPV6=n)
depends on LIBFC
@@ -9,5 +9,4 @@ config SCSI_BNX2X_FCOE
select NET_VENDOR_BROADCOM
select CNIC
---help---
- This driver supports FCoE offload for the QLogic NetXtreme II
- devices.
+ This driver supports FCoE offload for the QLogic devices.
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 1346e052e03c..499e369eabf0 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -1,7 +1,7 @@
-/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc.h: QLogic Linux FCoE offload driver.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
@@ -65,7 +65,7 @@
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "2.4.2"
+#define BNX2FC_VERSION "2.9.6"
#define PFX "bnx2fc: "
@@ -303,7 +303,6 @@ struct bnx2fc_rport {
#define BNX2FC_FLAG_OFLD_REQ_CMPL 0x5
#define BNX2FC_FLAG_CTX_ALLOC_FAILURE 0x6
#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x7
-#define BNX2FC_FLAG_EXPL_LOGO 0x8
#define BNX2FC_FLAG_DISABLE_FAILED 0x9
#define BNX2FC_FLAG_ENABLED 0xa
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index e147cc7ee36c..5b20efb661a5 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -1,9 +1,9 @@
-/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_constants.h: QLogic Linux FCoE offload driver.
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.c b/drivers/scsi/bnx2fc/bnx2fc_debug.c
index d055df01faa5..c9e0bc7fad3b 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.c
@@ -1,9 +1,9 @@
-/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_debug.c: QLogic Linux FCoE offload driver.
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h
index 2b9006774f37..34fda3e04d27 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h
@@ -1,9 +1,9 @@
-/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_debug.h: QLogic Linux FCoE offload driver.
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index ef355c13ccc4..5beea776b9f5 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -1,10 +1,10 @@
/*
- * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver.
+ * bnx2fc_els.c: QLogic Linux FCoE offload driver.
* This file contains helper routines that handle ELS requests
* and responses.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
@@ -689,8 +689,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
rc = -EINVAL;
goto els_err;
}
- if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
- (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
+ if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
rc = -EINVAL;
goto els_err;
@@ -707,6 +706,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
els_req->cb_func = cb_func;
cb_arg->io_req = els_req;
els_req->cb_arg = cb_arg;
+ els_req->data_xfer_len = data_len;
mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
rc = bnx2fc_init_mp_req(els_req);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index d5cdc4776707..67405c628864 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -1,10 +1,10 @@
-/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_fcoe.c: QLogic Linux FCoE offload driver.
* This file contains the code that interacts with libfc, libfcoe,
* cnic modules to create FCoE instances, send/receive non-offloaded
* FIP/FCoE packets, listen to link events etc.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
@@ -23,16 +23,16 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
#define DRV_MODULE_NAME "bnx2fc"
#define DRV_MODULE_VERSION BNX2FC_VERSION
-#define DRV_MODULE_RELDATE "Dec 11, 2013"
+#define DRV_MODULE_RELDATE "October 15, 2015"
static char version[] =
- "QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+ "QLogic FCoE Driver " DRV_MODULE_NAME \
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
-MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver");
+MODULE_DESCRIPTION("QLogic FCoE Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -856,7 +856,6 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
return;
default:
- printk(KERN_ERR PFX "Unknown netevent %ld", event);
return;
}
@@ -2092,7 +2091,7 @@ static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
{
struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
struct bnx2fc_hba *hba;
- struct cnic_fc_npiv_tbl npiv_tbl;
+ struct cnic_fc_npiv_tbl *npiv_tbl;
struct fc_lport *lport;
if (interface->enabled == false) {
@@ -2124,11 +2123,16 @@ static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
if (!hba->cnic->get_fc_npiv_tbl)
goto done;
- memset(&npiv_tbl, 0, sizeof(npiv_tbl));
- if (hba->cnic->get_fc_npiv_tbl(hba->cnic, &npiv_tbl))
+ npiv_tbl = kzalloc(sizeof(struct cnic_fc_npiv_tbl), GFP_KERNEL);
+ if (!npiv_tbl)
goto done;
- bnx2fc_npiv_create_vports(lport, &npiv_tbl);
+ if (hba->cnic->get_fc_npiv_tbl(hba->cnic, npiv_tbl))
+ goto done_free;
+
+ bnx2fc_npiv_create_vports(lport, npiv_tbl);
+done_free:
+ kfree(npiv_tbl);
done:
return 0;
}
@@ -2863,7 +2867,6 @@ static struct scsi_host_template bnx2fc_shost_template = {
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = BNX2FC_MAX_BDS_PER_CMD,
.max_sectors = 1024,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index c6688d72a846..28c671b609b2 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -1,9 +1,9 @@
-/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_hwi.c: QLogic Linux FCoE offload driver.
* This file contains the code that low level functions that interact
* with 57712 FCoE firmware.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 9ecca8504f60..0002caf687dd 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1,8 +1,8 @@
-/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_io.c: QLogic Linux FCoE offload driver.
* IO manager and SCSI IO processing.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
@@ -40,11 +40,8 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
{
struct bnx2fc_cmd *io_req = container_of(work, struct bnx2fc_cmd,
timeout_work.work);
- struct fc_lport *lport;
- struct fc_rport_priv *rdata;
u8 cmd_type = io_req->cmd_type;
struct bnx2fc_rport *tgt = io_req->tgt;
- int logo_issued;
int rc;
BNX2FC_IO_DBG(io_req, "cmd_timeout, cmd_type = %d,"
@@ -80,25 +77,14 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
io_req->refcount.refcount.counter);
if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
&io_req->req_flags))) {
-
- lport = io_req->port->lport;
- rdata = io_req->tgt->rdata;
- logo_issued = test_and_set_bit(
- BNX2FC_FLAG_EXPL_LOGO,
- &tgt->flags);
+ /*
+ * Cleanup and return original command to
+ * mid-layer.
+ */
+ bnx2fc_initiate_cleanup(io_req);
kref_put(&io_req->refcount, bnx2fc_cmd_release);
spin_unlock_bh(&tgt->tgt_lock);
- /* Explicitly logo the target */
- if (!logo_issued) {
- BNX2FC_IO_DBG(io_req, "Explicit "
- "logo - tgt flags = 0x%lx\n",
- tgt->flags);
-
- mutex_lock(&lport->disc.disc_mutex);
- lport->tt.rport_logoff(rdata);
- mutex_unlock(&lport->disc.disc_mutex);
- }
return;
}
} else {
@@ -116,28 +102,10 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
rc = bnx2fc_initiate_abts(io_req);
if (rc == SUCCESS)
goto done;
- /*
- * Explicitly logo the target if
- * abts initiation fails
- */
- lport = io_req->port->lport;
- rdata = io_req->tgt->rdata;
- logo_issued = test_and_set_bit(
- BNX2FC_FLAG_EXPL_LOGO,
- &tgt->flags);
+
kref_put(&io_req->refcount, bnx2fc_cmd_release);
spin_unlock_bh(&tgt->tgt_lock);
- if (!logo_issued) {
- BNX2FC_IO_DBG(io_req, "Explicit "
- "logo - tgt flags = 0x%lx\n",
- tgt->flags);
-
-
- mutex_lock(&lport->disc.disc_mutex);
- lport->tt.rport_logoff(rdata);
- mutex_unlock(&lport->disc.disc_mutex);
- }
return;
} else {
BNX2FC_IO_DBG(io_req, "IO already in "
@@ -152,22 +120,9 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
if (!test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
&io_req->req_flags)) {
- lport = io_req->port->lport;
- rdata = io_req->tgt->rdata;
- logo_issued = test_and_set_bit(
- BNX2FC_FLAG_EXPL_LOGO,
- &tgt->flags);
kref_put(&io_req->refcount, bnx2fc_cmd_release);
spin_unlock_bh(&tgt->tgt_lock);
- /* Explicitly logo the target */
- if (!logo_issued) {
- BNX2FC_IO_DBG(io_req, "Explicitly logo"
- "(els)\n");
- mutex_lock(&lport->disc.disc_mutex);
- lport->tt.rport_logoff(rdata);
- mutex_unlock(&lport->disc.disc_mutex);
- }
return;
}
} else {
@@ -623,8 +578,12 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
mp_req = (struct bnx2fc_mp_req *)&(io_req->mp_req);
memset(mp_req, 0, sizeof(struct bnx2fc_mp_req));
- mp_req->req_len = sizeof(struct fcp_cmnd);
- io_req->data_xfer_len = mp_req->req_len;
+ if (io_req->cmd_type != BNX2FC_ELS) {
+ mp_req->req_len = sizeof(struct fcp_cmnd);
+ io_req->data_xfer_len = mp_req->req_len;
+ } else
+ mp_req->req_len = io_req->data_xfer_len;
+
mp_req->req_buf = dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
&mp_req->req_buf_dma,
GFP_ATOMIC);
@@ -1108,18 +1067,11 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
}
-int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
+int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req)
{
struct bnx2fc_rport *tgt = io_req->tgt;
- struct fc_rport_priv *rdata = tgt->rdata;
- int logo_issued;
int rc = SUCCESS;
- int wait_cnt = 0;
- BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
- tgt->flags);
- logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
- &tgt->flags);
io_req->wait_for_comp = 1;
bnx2fc_initiate_cleanup(io_req);
@@ -1132,21 +1084,8 @@ int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
* release the reference taken in eh_abort to allow the
* target to re-login after flushing IOs
*/
- kref_put(&io_req->refcount, bnx2fc_cmd_release);
-
- if (!logo_issued) {
- clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
- mutex_lock(&lport->disc.disc_mutex);
- lport->tt.rport_logoff(rdata);
- mutex_unlock(&lport->disc.disc_mutex);
- do {
- msleep(BNX2FC_RELOGIN_WAIT_TIME);
- if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) {
- rc = FAILED;
- break;
- }
- } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags));
- }
+ kref_put(&io_req->refcount, bnx2fc_cmd_release);
+
spin_lock_bh(&tgt->tgt_lock);
return rc;
}
@@ -1248,7 +1187,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
if (cancel_delayed_work(&io_req->timeout_work))
kref_put(&io_req->refcount,
bnx2fc_cmd_release); /* drop timer hold */
- rc = bnx2fc_expl_logo(lport, io_req);
+ rc = bnx2fc_abts_cleanup(io_req);
/* This only occurs when an task abort was requested while ABTS
is in progress. Setting the IO_CLEANUP flag will skip the
RRQ process in the case when the fw generated SCSI_CMD cmpl
@@ -1287,7 +1226,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
/* Let the scsi-ml try to recover this command */
printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
io_req->xid);
- rc = bnx2fc_expl_logo(lport, io_req);
+ rc = bnx2fc_abts_cleanup(io_req);
goto out;
} else {
/*
@@ -1755,7 +1694,10 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
int fcp_rsp_len = 0;
io_req->fcp_status = FC_GOOD;
- io_req->fcp_resid = fcp_rsp->fcp_resid;
+ io_req->fcp_resid = 0;
+ if (rsp_flags & (FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER |
+ FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER))
+ io_req->fcp_resid = fcp_rsp->fcp_resid;
io_req->scsi_comp_flags = rsp_flags;
CMD_SCSI_STATUS(sc_cmd) = io_req->cdb_status =
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index c66c708412a6..08ec318afb99 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -1,9 +1,9 @@
-/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_tgt.c: QLogic Linux FCoE offload driver.
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic 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
@@ -560,12 +560,6 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
(hba->num_ofld_sess == 0)) {
wake_up_interruptible(&hba->shutdown_wait);
}
- if (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags)) {
- printk(KERN_ERR PFX "Relogin to the tgt\n");
- mutex_lock(&lport->disc.disc_mutex);
- lport->tt.rport_login(rdata);
- mutex_unlock(&lport->disc.disc_mutex);
- }
mutex_unlock(&hba->hba_mutex);
break;
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index 2c4562d82dc0..c2a6f9f29427 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -2283,7 +2283,6 @@ struct scsi_host_template csio_fcoe_shost_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = csio_fcoe_lport_attrs,
.max_sectors = CSIO_MAX_SECTOR_SIZE,
- .use_blk_tags = 1,
};
struct scsi_host_template csio_fcoe_shost_vport_template = {
@@ -2303,7 +2302,6 @@ struct scsi_host_template csio_fcoe_shost_vport_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = csio_fcoe_vport_attrs,
.max_sectors = CSIO_MAX_SECTOR_SIZE,
- .use_blk_tags = 1,
};
/*
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild
index 6f095e28a974..961a12f6d318 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb3
+ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb3
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild
index 8290cdaa4652..37458643749b 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
+ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index de6feb8964c9..804806e1cbb4 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -160,7 +160,7 @@ static struct scsi_transport_template *cxgb4i_stt;
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define RCV_BUFSIZ_MASK 0x3FFU
-#define MAX_IMM_TX_PKT_LEN 128
+#define MAX_IMM_TX_PKT_LEN 256
static int push_tx_frames(struct cxgbi_sock *, int);
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 1c56037146e1..c11cd193f896 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -16,10 +16,12 @@
#define _CXLFLASH_COMMON_H
#include <linux/list.h>
+#include <linux/rwsem.h>
#include <linux/types.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
+extern const struct file_operations cxlflash_cxl_fops;
#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */
@@ -78,7 +80,7 @@ enum cxlflash_init_state {
enum cxlflash_state {
STATE_NORMAL, /* Normal running state, everything good */
- STATE_LIMBO, /* Limbo running state, trying to reset/recover */
+ STATE_RESET, /* Reset state, trying to reset/recover */
STATE_FAILTERM /* Failed/terminating state, error out users/threads */
};
@@ -101,29 +103,28 @@ struct cxlflash_cfg {
enum cxlflash_init_state init_state;
enum cxlflash_lr_state lr_state;
int lr_port;
+ atomic_t scan_host_needed;
struct cxl_afu *cxl_afu;
-
- struct pci_pool *cxlflash_cmd_pool;
struct pci_dev *parent_dev;
atomic_t recovery_threads;
struct mutex ctx_recovery_mutex;
struct mutex ctx_tbl_list_mutex;
+ struct rw_semaphore ioctl_rwsem;
struct ctx_info *ctx_tbl[MAX_CONTEXT];
struct list_head ctx_err_recovery; /* contexts w/ recovery pending */
struct file_operations cxl_fops;
- atomic_t num_user_contexts;
-
/* Parameters that are LUN table related */
int last_lun_index[CXLFLASH_NUM_FC_PORTS];
int promote_lun_index;
struct list_head lluns; /* list of llun_info structs */
wait_queue_head_t tmf_waitq;
+ spinlock_t tmf_slock;
bool tmf_active;
- wait_queue_head_t limbo_waitq;
+ wait_queue_head_t reset_waitq;
enum cxlflash_state state;
};
@@ -160,9 +161,9 @@ struct afu {
/* AFU HW */
struct cxl_ioctl_start_work work;
- struct cxlflash_afu_map *afu_map; /* entire MMIO map */
- struct sisl_host_map *host_map; /* MC host map */
- struct sisl_ctrl_map *ctrl_map; /* MC control map */
+ struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */
+ struct sisl_host_map __iomem *host_map; /* MC host map */
+ struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */
ctx_hndl_t ctx_hndl; /* master's context handle */
u64 *hrrq_start;
@@ -175,7 +176,7 @@ struct afu {
u32 cmd_couts; /* Number of command checkouts */
u32 internal_lun; /* User-desired LUN mode for this AFU */
- char version[8];
+ char version[16];
u64 interface_version;
struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */
@@ -184,17 +185,12 @@ struct afu {
static inline u64 lun_to_lunid(u64 lun)
{
- u64 lun_id;
+ __be64 lun_id;
int_to_scsilun(lun, (struct scsi_lun *)&lun_id);
- return swab64(lun_id);
+ return be64_to_cpu(lun_id);
}
-int cxlflash_send_cmd(struct afu *, struct afu_cmd *);
-void cxlflash_wait_resp(struct afu *, struct afu_cmd *);
-int cxlflash_afu_reset(struct cxlflash_cfg *);
-struct afu_cmd *cxlflash_cmd_checkout(struct afu *);
-void cxlflash_cmd_checkin(struct afu_cmd *);
int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8);
void cxlflash_list_init(void);
void cxlflash_term_global_luns(void);
diff --git a/drivers/scsi/cxlflash/lunmgt.c b/drivers/scsi/cxlflash/lunmgt.c
index d98ad0ff64c1..a0923cade6f3 100644
--- a/drivers/scsi/cxlflash/lunmgt.c
+++ b/drivers/scsi/cxlflash/lunmgt.c
@@ -41,7 +41,6 @@ static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid)
}
lli->sdev = sdev;
- lli->newly_created = true;
lli->host_no = sdev->host->host_no;
lli->in_table = false;
@@ -74,24 +73,19 @@ out:
}
/**
- * refresh_local() - find and update local LUN information structure by WWID
+ * lookup_local() - find a local LUN information structure by WWID
* @cfg: Internal structure associated with the host.
* @wwid: WWID associated with LUN.
*
- * When the LUN is found, mark it by updating it's newly_created field.
- *
* Return: Found local lun_info structure on success, NULL on failure
- * If a LUN with the WWID is found in the list, refresh it's state.
*/
-static struct llun_info *refresh_local(struct cxlflash_cfg *cfg, u8 *wwid)
+static struct llun_info *lookup_local(struct cxlflash_cfg *cfg, u8 *wwid)
{
struct llun_info *lli, *temp;
list_for_each_entry_safe(lli, temp, &cfg->lluns, list)
- if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN)) {
- lli->newly_created = false;
+ if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
return lli;
- }
return NULL;
}
@@ -120,7 +114,8 @@ static struct glun_info *lookup_global(u8 *wwid)
*
* The LUN is kept both in a local list (per adapter) and in a global list
* (across all adapters). Certain attributes of the LUN are local to the
- * adapter (such as index, port selection mask etc.).
+ * adapter (such as index, port selection mask, etc.).
+ *
* The block allocation map is shared across all adapters (i.e. associated
* wih the global list). Since different attributes are associated with
* the per adapter and global entries, allocate two separate structures for each
@@ -128,6 +123,8 @@ static struct glun_info *lookup_global(u8 *wwid)
*
* Keep a pointer back from the local to the global entry.
*
+ * This routine assumes the caller holds the global mutex.
+ *
* Return: Found/Allocated local lun_info structure on success, NULL on failure
*/
static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
@@ -137,11 +134,10 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
struct Scsi_Host *shost = sdev->host;
struct cxlflash_cfg *cfg = shost_priv(shost);
- mutex_lock(&global.mutex);
if (unlikely(!wwid))
goto out;
- lli = refresh_local(cfg, wwid);
+ lli = lookup_local(cfg, wwid);
if (lli)
goto out;
@@ -169,7 +165,6 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
list_add(&gli->list, &global.gluns);
out:
- mutex_unlock(&global.mutex);
pr_debug("%s: returning %p\n", __func__, lli);
return lli;
}
@@ -235,10 +230,11 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
u64 flags = manage->hdr.flags;
u32 chan = sdev->channel;
+ mutex_lock(&global.mutex);
lli = find_and_create_lun(sdev, manage->wwid);
pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n",
- __func__, get_unaligned_le64(&manage->wwid[0]),
- get_unaligned_le64(&manage->wwid[8]),
+ __func__, get_unaligned_be64(&manage->wwid[0]),
+ get_unaligned_be64(&manage->wwid[8]),
manage->hdr.flags, lli);
if (unlikely(!lli)) {
rc = -ENOMEM;
@@ -246,21 +242,28 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
}
if (flags & DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE) {
- if (lli->newly_created)
- lli->port_sel = CHAN2PORT(chan);
- else
- lli->port_sel = BOTH_PORTS;
- /* Store off lun in unpacked, AFU-friendly format */
+ /*
+ * Update port selection mask based upon channel, store off LUN
+ * in unpacked, AFU-friendly format, and hang LUN reference in
+ * the sdev.
+ */
+ lli->port_sel |= CHAN2PORT(chan);
lli->lun_id[chan] = lun_to_lunid(sdev->lun);
sdev->hostdata = lli;
} else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) {
if (lli->parent->mode != MODE_NONE)
rc = -EBUSY;
- else
+ else {
sdev->hostdata = NULL;
+ lli->port_sel &= ~CHAN2PORT(chan);
+ }
}
+ pr_debug("%s: port_sel = %08X chan = %u lun_id = %016llX\n", __func__,
+ lli->port_sel, chan, lli->lun_id[chan]);
+
out:
+ mutex_unlock(&global.mutex);
pr_debug("%s: returning rc=%d\n", __func__, rc);
return rc;
}
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 3e3ccf16e7c2..1e5bf0ca81da 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -34,9 +34,8 @@ MODULE_AUTHOR("Manoj N. Kumar <manoj@linux.vnet.ibm.com>");
MODULE_AUTHOR("Matthew R. Ochs <mrochs@linux.vnet.ibm.com>");
MODULE_LICENSE("GPL");
-
/**
- * cxlflash_cmd_checkout() - checks out an AFU command
+ * cmd_checkout() - checks out an AFU command
* @afu: AFU to checkout from.
*
* Commands are checked out in a round-robin fashion. Note that since
@@ -47,7 +46,7 @@ MODULE_LICENSE("GPL");
*
* Return: The checked out command or NULL when command pool is empty.
*/
-struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
+static struct afu_cmd *cmd_checkout(struct afu *afu)
{
int k, dec = CXLFLASH_NUM_CMDS;
struct afu_cmd *cmd;
@@ -58,8 +57,8 @@ struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
cmd = &afu->cmd[k];
if (!atomic_dec_if_positive(&cmd->free)) {
- pr_debug("%s: returning found index=%d\n",
- __func__, cmd->slot);
+ pr_devel("%s: returning found index=%d cmd=%p\n",
+ __func__, cmd->slot, cmd);
memset(cmd->buf, 0, CMD_BUFSIZE);
memset(cmd->rcb.cdb, 0, sizeof(cmd->rcb.cdb));
return cmd;
@@ -70,7 +69,7 @@ struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
}
/**
- * cxlflash_cmd_checkin() - checks in an AFU command
+ * cmd_checkin() - checks in an AFU command
* @cmd: AFU command to checkin.
*
* Safe to pass commands that have already been checked in. Several
@@ -79,7 +78,7 @@ struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
* to avoid clobbering values in the event that the command is checked
* out right away.
*/
-void cxlflash_cmd_checkin(struct afu_cmd *cmd)
+static void cmd_checkin(struct afu_cmd *cmd)
{
cmd->rcb.scp = NULL;
cmd->rcb.timeout = 0;
@@ -93,7 +92,7 @@ void cxlflash_cmd_checkin(struct afu_cmd *cmd)
return;
}
- pr_debug("%s: released cmd %p index=%d\n", __func__, cmd, cmd->slot);
+ pr_devel("%s: released cmd %p index=%d\n", __func__, cmd, cmd->slot);
}
/**
@@ -107,6 +106,7 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
{
struct sisl_ioarcb *ioarcb;
struct sisl_ioasa *ioasa;
+ u32 resid;
if (unlikely(!cmd))
return;
@@ -115,9 +115,10 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
ioasa = &(cmd->sa);
if (ioasa->rc.flags & SISL_RC_FLAGS_UNDERRUN) {
- pr_debug("%s: cmd underrun cmd = %p scp = %p\n",
- __func__, cmd, scp);
- scp->result = (DID_ERROR << 16);
+ resid = ioasa->resid;
+ scsi_set_resid(scp, resid);
+ pr_debug("%s: cmd underrun cmd = %p scp = %p, resid = %d\n",
+ __func__, cmd, scp, resid);
}
if (ioasa->rc.flags & SISL_RC_FLAGS_OVERRUN) {
@@ -127,7 +128,7 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
}
pr_debug("%s: cmd failed afu_rc=%d scsi_rc=%d fc_rc=%d "
- "afu_extra=0x%X, scsi_entra=0x%X, fc_extra=0x%X\n",
+ "afu_extra=0x%X, scsi_extra=0x%X, fc_extra=0x%X\n",
__func__, ioasa->rc.afu_rc, ioasa->rc.scsi_rc,
ioasa->rc.fc_rc, ioasa->afu_extra, ioasa->scsi_extra,
ioasa->fc_extra);
@@ -158,8 +159,7 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
/* If the SISL_RC_FLAGS_OVERRUN flag was set,
* then we will handle this error else where.
* If not then we must handle it here.
- * This is probably an AFU bug. We will
- * attempt a retry to see if that resolves it.
+ * This is probably an AFU bug.
*/
scp->result = (DID_ERROR << 16);
}
@@ -183,7 +183,7 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
/* We have an AFU error */
switch (ioasa->rc.afu_rc) {
case SISL_AFU_RC_NO_CHANNELS:
- scp->result = (DID_MEDIUM_ERROR << 16);
+ scp->result = (DID_NO_CONNECT << 16);
break;
case SISL_AFU_RC_DATA_DMA_ERR:
switch (ioasa->afu_extra) {
@@ -217,7 +217,6 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
static void cmd_complete(struct afu_cmd *cmd)
{
struct scsi_cmnd *scp;
- u32 resid;
ulong lock_flags;
struct afu *afu = cmd->parent;
struct cxlflash_cfg *cfg = afu->parent;
@@ -229,45 +228,179 @@ static void cmd_complete(struct afu_cmd *cmd)
if (cmd->rcb.scp) {
scp = cmd->rcb.scp;
- if (unlikely(cmd->sa.rc.afu_rc ||
- cmd->sa.rc.scsi_rc ||
- cmd->sa.rc.fc_rc))
+ if (unlikely(cmd->sa.ioasc))
process_cmd_err(cmd, scp);
else
scp->result = (DID_OK << 16);
- resid = cmd->sa.resid;
cmd_is_tmf = cmd->cmd_tmf;
- cxlflash_cmd_checkin(cmd); /* Don't use cmd after here */
+ cmd_checkin(cmd); /* Don't use cmd after here */
- pr_debug("%s: calling scsi_set_resid, scp=%p "
- "result=%X resid=%d\n", __func__,
- scp, scp->result, resid);
+ pr_debug_ratelimited("%s: calling scsi_done scp=%p result=%X "
+ "ioasc=%d\n", __func__, scp, scp->result,
+ cmd->sa.ioasc);
- scsi_set_resid(scp, resid);
scsi_dma_unmap(scp);
scp->scsi_done(scp);
if (cmd_is_tmf) {
- spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
+ spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
cfg->tmf_active = false;
wake_up_all_locked(&cfg->tmf_waitq);
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock,
- lock_flags);
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
}
} else
complete(&cmd->cevent);
}
/**
+ * context_reset() - timeout handler for AFU commands
+ * @cmd: AFU command that timed out.
+ *
+ * Sends a reset to the AFU.
+ */
+static void context_reset(struct afu_cmd *cmd)
+{
+ int nretry = 0;
+ u64 rrin = 0x1;
+ u64 room = 0;
+ struct afu *afu = cmd->parent;
+ ulong lock_flags;
+
+ pr_debug("%s: cmd=%p\n", __func__, cmd);
+
+ spin_lock_irqsave(&cmd->slock, lock_flags);
+
+ /* Already completed? */
+ if (cmd->sa.host_use_b[0] & B_DONE) {
+ spin_unlock_irqrestore(&cmd->slock, lock_flags);
+ return;
+ }
+
+ cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT);
+ spin_unlock_irqrestore(&cmd->slock, lock_flags);
+
+ /*
+ * We really want to send this reset at all costs, so spread
+ * out wait time on successive retries for available room.
+ */
+ do {
+ room = readq_be(&afu->host_map->cmd_room);
+ atomic64_set(&afu->room, room);
+ if (room)
+ goto write_rrin;
+ udelay(nretry);
+ } while (nretry++ < MC_ROOM_RETRY_CNT);
+
+ pr_err("%s: no cmd_room to send reset\n", __func__);
+ return;
+
+write_rrin:
+ nretry = 0;
+ writeq_be(rrin, &afu->host_map->ioarrin);
+ do {
+ rrin = readq_be(&afu->host_map->ioarrin);
+ if (rrin != 0x1)
+ break;
+ /* Double delay each time */
+ udelay(2 << nretry);
+ } while (nretry++ < MC_ROOM_RETRY_CNT);
+}
+
+/**
+ * send_cmd() - sends an AFU command
+ * @afu: AFU associated with the host.
+ * @cmd: AFU command to send.
+ *
+ * Return:
+ * 0 on success, SCSI_MLQUEUE_HOST_BUSY on failure
+ */
+static int send_cmd(struct afu *afu, struct afu_cmd *cmd)
+{
+ struct cxlflash_cfg *cfg = afu->parent;
+ struct device *dev = &cfg->dev->dev;
+ int nretry = 0;
+ int rc = 0;
+ u64 room;
+ long newval;
+
+ /*
+ * This routine is used by critical users such an AFU sync and to
+ * send a task management function (TMF). Thus we want to retry a
+ * bit before returning an error. To avoid the performance penalty
+ * of MMIO, we spread the update of 'room' over multiple commands.
+ */
+retry:
+ newval = atomic64_dec_if_positive(&afu->room);
+ if (!newval) {
+ do {
+ room = readq_be(&afu->host_map->cmd_room);
+ atomic64_set(&afu->room, room);
+ if (room)
+ goto write_ioarrin;
+ udelay(nretry);
+ } while (nretry++ < MC_ROOM_RETRY_CNT);
+
+ dev_err(dev, "%s: no cmd_room to send 0x%X\n",
+ __func__, cmd->rcb.cdb[0]);
+
+ goto no_room;
+ } else if (unlikely(newval < 0)) {
+ /* This should be rare. i.e. Only if two threads race and
+ * decrement before the MMIO read is done. In this case
+ * just benefit from the other thread having updated
+ * afu->room.
+ */
+ if (nretry++ < MC_ROOM_RETRY_CNT) {
+ udelay(nretry);
+ goto retry;
+ }
+
+ goto no_room;
+ }
+
+write_ioarrin:
+ writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin);
+out:
+ pr_devel("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd,
+ cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc);
+ return rc;
+
+no_room:
+ afu->read_room = true;
+ schedule_work(&cfg->work_q);
+ rc = SCSI_MLQUEUE_HOST_BUSY;
+ goto out;
+}
+
+/**
+ * wait_resp() - polls for a response or timeout to a sent AFU command
+ * @afu: AFU associated with the host.
+ * @cmd: AFU command that was sent.
+ */
+static void wait_resp(struct afu *afu, struct afu_cmd *cmd)
+{
+ ulong timeout = msecs_to_jiffies(cmd->rcb.timeout * 2 * 1000);
+
+ timeout = wait_for_completion_timeout(&cmd->cevent, timeout);
+ if (!timeout)
+ context_reset(cmd);
+
+ if (unlikely(cmd->sa.ioasc != 0))
+ pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, "
+ "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0],
+ cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc,
+ cmd->sa.rc.fc_rc);
+}
+
+/**
* send_tmf() - sends a Task Management Function (TMF)
* @afu: AFU to checkout from.
* @scp: SCSI command from stack.
* @tmfcmd: TMF command to send.
*
* Return:
- * 0 on success
- * SCSI_MLQUEUE_HOST_BUSY when host is busy
+ * 0 on success, SCSI_MLQUEUE_HOST_BUSY on failure
*/
static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
{
@@ -277,25 +410,27 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
short lflag = 0;
struct Scsi_Host *host = scp->device->host;
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
+ struct device *dev = &cfg->dev->dev;
ulong lock_flags;
int rc = 0;
+ ulong to;
- cmd = cxlflash_cmd_checkout(afu);
+ cmd = cmd_checkout(afu);
if (unlikely(!cmd)) {
- pr_err("%s: could not get a free command\n", __func__);
+ dev_err(dev, "%s: could not get a free command\n", __func__);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
- /* If a Task Management Function is active, do not send one more.
- */
- spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
+ /* When Task Management Function is active do not send another */
+ spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
if (cfg->tmf_active)
- wait_event_interruptible_locked_irq(cfg->tmf_waitq,
- !cfg->tmf_active);
+ wait_event_interruptible_lock_irq(cfg->tmf_waitq,
+ !cfg->tmf_active,
+ cfg->tmf_slock);
cfg->tmf_active = true;
cmd->cmd_tmf = true;
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
cmd->rcb.ctx_id = afu->ctx_hndl;
cmd->rcb.port_sel = port_sel;
@@ -313,18 +448,27 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd));
/* Send the command */
- rc = cxlflash_send_cmd(afu, cmd);
+ rc = send_cmd(afu, cmd);
if (unlikely(rc)) {
- cxlflash_cmd_checkin(cmd);
- spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
+ cmd_checkin(cmd);
+ spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
cfg->tmf_active = false;
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
goto out;
}
- spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
- wait_event_interruptible_locked_irq(cfg->tmf_waitq, !cfg->tmf_active);
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
+ spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
+ to = msecs_to_jiffies(5000);
+ to = wait_event_interruptible_lock_irq_timeout(cfg->tmf_waitq,
+ !cfg->tmf_active,
+ cfg->tmf_slock,
+ to);
+ if (!to) {
+ cfg->tmf_active = false;
+ dev_err(dev, "%s: TMF timed out!\n", __func__);
+ rc = -1;
+ }
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
out:
return rc;
}
@@ -345,15 +489,13 @@ static const char *cxlflash_driver_info(struct Scsi_Host *host)
* @host: SCSI host associated with device.
* @scp: SCSI command to send.
*
- * Return:
- * 0 on success
- * SCSI_MLQUEUE_HOST_BUSY when host is busy
+ * Return: 0 on success, SCSI_MLQUEUE_HOST_BUSY on failure
*/
static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
{
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
struct afu *afu = cfg->afu;
- struct pci_dev *pdev = cfg->dev;
+ struct device *dev = &cfg->dev->dev;
struct afu_cmd *cmd;
u32 port_sel = scp->device->channel + 1;
int nseg, i, ncount;
@@ -362,34 +504,34 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
short lflag = 0;
int rc = 0;
- pr_debug("%s: (scp=%p) %d/%d/%d/%llu cdb=(%08X-%08X-%08X-%08X)\n",
- __func__, scp, host->host_no, scp->device->channel,
- scp->device->id, scp->device->lun,
- get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
+ dev_dbg_ratelimited(dev, "%s: (scp=%p) %d/%d/%d/%llu "
+ "cdb=(%08X-%08X-%08X-%08X)\n",
+ __func__, scp, host->host_no, scp->device->channel,
+ scp->device->id, scp->device->lun,
+ get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
- /* If a Task Management Function is active, wait for it to complete
+ /*
+ * If a Task Management Function is active, wait for it to complete
* before continuing with regular commands.
*/
- spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
+ spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
if (cfg->tmf_active) {
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
switch (cfg->state) {
- case STATE_LIMBO:
- dev_dbg_ratelimited(&cfg->dev->dev, "%s: device in limbo!\n",
- __func__);
+ case STATE_RESET:
+ dev_dbg_ratelimited(dev, "%s: device is in reset!\n", __func__);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
case STATE_FAILTERM:
- dev_dbg_ratelimited(&cfg->dev->dev, "%s: device has failed!\n",
- __func__);
+ dev_dbg_ratelimited(dev, "%s: device has failed!\n", __func__);
scp->result = (DID_NO_CONNECT << 16);
scp->scsi_done(scp);
rc = 0;
@@ -398,9 +540,9 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
break;
}
- cmd = cxlflash_cmd_checkout(afu);
+ cmd = cmd_checkout(afu);
if (unlikely(!cmd)) {
- pr_err("%s: could not get a free command\n", __func__);
+ dev_err(dev, "%s: could not get a free command\n", __func__);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
@@ -422,7 +564,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
nseg = scsi_dma_map(scp);
if (unlikely(nseg < 0)) {
- dev_err(&pdev->dev, "%s: Fail DMA map! nseg=%d\n",
+ dev_err(dev, "%s: Fail DMA map! nseg=%d\n",
__func__, nseg);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
@@ -438,347 +580,34 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb));
/* Send the command */
- rc = cxlflash_send_cmd(afu, cmd);
+ rc = send_cmd(afu, cmd);
if (unlikely(rc)) {
- cxlflash_cmd_checkin(cmd);
+ cmd_checkin(cmd);
scsi_dma_unmap(scp);
}
out:
+ pr_devel("%s: returning rc=%d\n", __func__, rc);
return rc;
}
/**
- * cxlflash_eh_device_reset_handler() - reset a single LUN
- * @scp: SCSI command to send.
- *
- * Return:
- * SUCCESS as defined in scsi/scsi.h
- * FAILED as defined in scsi/scsi.h
- */
-static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp)
-{
- int rc = SUCCESS;
- struct Scsi_Host *host = scp->device->host;
- struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
- struct afu *afu = cfg->afu;
- int rcr = 0;
-
- pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
- "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
- host->host_no, scp->device->channel,
- scp->device->id, scp->device->lun,
- get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
-
- switch (cfg->state) {
- case STATE_NORMAL:
- rcr = send_tmf(afu, scp, TMF_LUN_RESET);
- if (unlikely(rcr))
- rc = FAILED;
- break;
- case STATE_LIMBO:
- wait_event(cfg->limbo_waitq, cfg->state != STATE_LIMBO);
- if (cfg->state == STATE_NORMAL)
- break;
- /* fall through */
- default:
- rc = FAILED;
- break;
- }
-
- pr_debug("%s: returning rc=%d\n", __func__, rc);
- return rc;
-}
-
-/**
- * cxlflash_eh_host_reset_handler() - reset the host adapter
- * @scp: SCSI command from stack identifying host.
- *
- * Return:
- * SUCCESS as defined in scsi/scsi.h
- * FAILED as defined in scsi/scsi.h
- */
-static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
-{
- int rc = SUCCESS;
- int rcr = 0;
- struct Scsi_Host *host = scp->device->host;
- struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
-
- pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
- "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
- host->host_no, scp->device->channel,
- scp->device->id, scp->device->lun,
- get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
- get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
-
- switch (cfg->state) {
- case STATE_NORMAL:
- cfg->state = STATE_LIMBO;
- scsi_block_requests(cfg->host);
- cxlflash_mark_contexts_error(cfg);
- rcr = cxlflash_afu_reset(cfg);
- if (rcr) {
- rc = FAILED;
- cfg->state = STATE_FAILTERM;
- } else
- cfg->state = STATE_NORMAL;
- wake_up_all(&cfg->limbo_waitq);
- scsi_unblock_requests(cfg->host);
- break;
- case STATE_LIMBO:
- wait_event(cfg->limbo_waitq, cfg->state != STATE_LIMBO);
- if (cfg->state == STATE_NORMAL)
- break;
- /* fall through */
- default:
- rc = FAILED;
- break;
- }
-
- pr_debug("%s: returning rc=%d\n", __func__, rc);
- return rc;
-}
-
-/**
- * cxlflash_change_queue_depth() - change the queue depth for the device
- * @sdev: SCSI device destined for queue depth change.
- * @qdepth: Requested queue depth value to set.
- *
- * The requested queue depth is capped to the maximum supported value.
- *
- * Return: The actual queue depth set.
- */
-static int cxlflash_change_queue_depth(struct scsi_device *sdev, int qdepth)
-{
-
- if (qdepth > CXLFLASH_MAX_CMDS_PER_LUN)
- qdepth = CXLFLASH_MAX_CMDS_PER_LUN;
-
- scsi_change_queue_depth(sdev, qdepth);
- return sdev->queue_depth;
-}
-
-/**
- * cxlflash_show_port_status() - queries and presents the current port status
- * @dev: Generic device associated with the host owning the port.
- * @attr: Device attribute representing the port.
- * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
- *
- * Return: The size of the ASCII string returned in @buf.
- */
-static ssize_t cxlflash_show_port_status(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(dev);
- struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
- struct afu *afu = cfg->afu;
-
- char *disp_status;
- int rc;
- u32 port;
- u64 status;
- u64 *fc_regs;
-
- rc = kstrtouint((attr->attr.name + 4), 10, &port);
- if (rc || (port >= NUM_FC_PORTS))
- return 0;
-
- fc_regs = &afu->afu_map->global.fc_regs[port][0];
- status =
- (readq_be(&fc_regs[FC_MTIP_STATUS / 8]) & FC_MTIP_STATUS_MASK);
-
- if (status == FC_MTIP_STATUS_ONLINE)
- disp_status = "online";
- else if (status == FC_MTIP_STATUS_OFFLINE)
- disp_status = "offline";
- else
- disp_status = "unknown";
-
- return snprintf(buf, PAGE_SIZE, "%s\n", disp_status);
-}
-
-/**
- * cxlflash_show_lun_mode() - presents the current LUN mode of the host
- * @dev: Generic device associated with the host.
- * @attr: Device attribute representing the lun mode.
- * @buf: Buffer of length PAGE_SIZE to report back the LUN mode in ASCII.
- *
- * Return: The size of the ASCII string returned in @buf.
- */
-static ssize_t cxlflash_show_lun_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(dev);
- struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
- struct afu *afu = cfg->afu;
-
- return snprintf(buf, PAGE_SIZE, "%u\n", afu->internal_lun);
-}
-
-/**
- * cxlflash_store_lun_mode() - sets the LUN mode of the host
- * @dev: Generic device associated with the host.
- * @attr: Device attribute representing the lun mode.
- * @buf: Buffer of length PAGE_SIZE containing the LUN mode in ASCII.
- * @count: Length of data resizing in @buf.
- *
- * The CXL Flash AFU supports a dummy LUN mode where the external
- * links and storage are not required. Space on the FPGA is used
- * to create 1 or 2 small LUNs which are presented to the system
- * as if they were a normal storage device. This feature is useful
- * during development and also provides manufacturing with a way
- * to test the AFU without an actual device.
- *
- * 0 = external LUN[s] (default)
- * 1 = internal LUN (1 x 64K, 512B blocks, id 0)
- * 2 = internal LUN (1 x 64K, 4K blocks, id 0)
- * 3 = internal LUN (2 x 32K, 512B blocks, ids 0,1)
- * 4 = internal LUN (2 x 32K, 4K blocks, ids 0,1)
- *
- * Return: The size of the ASCII string returned in @buf.
- */
-static ssize_t cxlflash_store_lun_mode(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct Scsi_Host *shost = class_to_shost(dev);
- struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
- struct afu *afu = cfg->afu;
- int rc;
- u32 lun_mode;
-
- rc = kstrtouint(buf, 10, &lun_mode);
- if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) {
- afu->internal_lun = lun_mode;
- cxlflash_afu_reset(cfg);
- scsi_scan_host(cfg->host);
- }
-
- return count;
-}
-
-/**
- * cxlflash_show_ioctl_version() - presents the current ioctl version of the host
- * @dev: Generic device associated with the host.
- * @attr: Device attribute representing the ioctl version.
- * @buf: Buffer of length PAGE_SIZE to report back the ioctl version.
- *
- * Return: The size of the ASCII string returned in @buf.
- */
-static ssize_t cxlflash_show_ioctl_version(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0);
-}
-
-/**
- * cxlflash_show_dev_mode() - presents the current mode of the device
- * @dev: Generic device associated with the device.
- * @attr: Device attribute representing the device mode.
- * @buf: Buffer of length PAGE_SIZE to report back the dev mode in ASCII.
- *
- * Return: The size of the ASCII string returned in @buf.
- */
-static ssize_t cxlflash_show_dev_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
-
- return snprintf(buf, PAGE_SIZE, "%s\n",
- sdev->hostdata ? "superpipe" : "legacy");
-}
-
-/**
* cxlflash_wait_for_pci_err_recovery() - wait for error recovery during probe
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*/
static void cxlflash_wait_for_pci_err_recovery(struct cxlflash_cfg *cfg)
{
struct pci_dev *pdev = cfg->dev;
if (pci_channel_offline(pdev))
- wait_event_timeout(cfg->limbo_waitq,
+ wait_event_timeout(cfg->reset_waitq,
!pci_channel_offline(pdev),
CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT);
}
-/*
- * Host attributes
- */
-static DEVICE_ATTR(port0, S_IRUGO, cxlflash_show_port_status, NULL);
-static DEVICE_ATTR(port1, S_IRUGO, cxlflash_show_port_status, NULL);
-static DEVICE_ATTR(lun_mode, S_IRUGO | S_IWUSR, cxlflash_show_lun_mode,
- cxlflash_store_lun_mode);
-static DEVICE_ATTR(ioctl_version, S_IRUGO, cxlflash_show_ioctl_version, NULL);
-
-static struct device_attribute *cxlflash_host_attrs[] = {
- &dev_attr_port0,
- &dev_attr_port1,
- &dev_attr_lun_mode,
- &dev_attr_ioctl_version,
- NULL
-};
-
-/*
- * Device attributes
- */
-static DEVICE_ATTR(mode, S_IRUGO, cxlflash_show_dev_mode, NULL);
-
-static struct device_attribute *cxlflash_dev_attrs[] = {
- &dev_attr_mode,
- NULL
-};
-
-/*
- * Host template
- */
-static struct scsi_host_template driver_template = {
- .module = THIS_MODULE,
- .name = CXLFLASH_ADAPTER_NAME,
- .info = cxlflash_driver_info,
- .ioctl = cxlflash_ioctl,
- .proc_name = CXLFLASH_NAME,
- .queuecommand = cxlflash_queuecommand,
- .eh_device_reset_handler = cxlflash_eh_device_reset_handler,
- .eh_host_reset_handler = cxlflash_eh_host_reset_handler,
- .change_queue_depth = cxlflash_change_queue_depth,
- .cmd_per_lun = 16,
- .can_queue = CXLFLASH_MAX_CMDS,
- .this_id = -1,
- .sg_tablesize = SG_NONE, /* No scatter gather support. */
- .max_sectors = CXLFLASH_MAX_SECTORS,
- .use_clustering = ENABLE_CLUSTERING,
- .shost_attrs = cxlflash_host_attrs,
- .sdev_attrs = cxlflash_dev_attrs,
-};
-
-/*
- * Device dependent values
- */
-static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS };
-
-/*
- * PCI device binding table
- */
-static struct pci_device_id cxlflash_pci_table[] = {
- {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals},
- {}
-};
-
-MODULE_DEVICE_TABLE(pci, cxlflash_pci_table);
-
/**
* free_mem() - free memory associated with the AFU
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*/
static void free_mem(struct cxlflash_cfg *cfg)
{
@@ -800,7 +629,7 @@ static void free_mem(struct cxlflash_cfg *cfg)
/**
* stop_afu() - stops the AFU command timers and unmaps the MMIO space
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
* Safe to call with AFU in a partially allocated/initialized state.
*/
@@ -814,7 +643,7 @@ static void stop_afu(struct cxlflash_cfg *cfg)
complete(&afu->cmd[i].cevent);
if (likely(afu->afu_map)) {
- cxl_psa_unmap((void *)afu->afu_map);
+ cxl_psa_unmap((void __iomem *)afu->afu_map);
afu->afu_map = NULL;
}
}
@@ -822,7 +651,7 @@ static void stop_afu(struct cxlflash_cfg *cfg)
/**
* term_mc() - terminates the master context
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
* @level: Depth of allocation, where to begin waterfall tear down.
*
* Safe to call with AFU/MC in partially allocated/initialized state.
@@ -831,9 +660,10 @@ static void term_mc(struct cxlflash_cfg *cfg, enum undo_level level)
{
int rc = 0;
struct afu *afu = cfg->afu;
+ struct device *dev = &cfg->dev->dev;
if (!afu || !cfg->mcctx) {
- pr_err("%s: returning from term_mc with NULL afu or MC\n",
+ dev_err(dev, "%s: returning from term_mc with NULL afu or MC\n",
__func__);
return;
}
@@ -857,7 +687,7 @@ static void term_mc(struct cxlflash_cfg *cfg, enum undo_level level)
/**
* term_afu() - terminates the AFU
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
* Safe to call with AFU/MC in partially allocated/initialized state.
*/
@@ -885,11 +715,12 @@ static void cxlflash_remove(struct pci_dev *pdev)
/* If a Task Management Function is active, wait for it to complete
* before continuing with remove.
*/
- spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
+ spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
if (cfg->tmf_active)
- wait_event_interruptible_locked_irq(cfg->tmf_waitq,
- !cfg->tmf_active);
- spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
+ wait_event_interruptible_lock_irq(cfg->tmf_waitq,
+ !cfg->tmf_active,
+ cfg->tmf_slock);
+ spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
cfg->state = STATE_FAILTERM;
cxlflash_stop_term_user_contexts(cfg);
@@ -898,16 +729,16 @@ static void cxlflash_remove(struct pci_dev *pdev)
case INIT_STATE_SCSI:
cxlflash_term_local_luns(cfg);
scsi_remove_host(cfg->host);
- scsi_host_put(cfg->host);
- /* Fall through */
+ /* fall through */
case INIT_STATE_AFU:
term_afu(cfg);
+ cancel_work_sync(&cfg->work_q);
case INIT_STATE_PCI:
pci_release_regions(cfg->dev);
pci_disable_device(pdev);
case INIT_STATE_NONE:
- flush_work(&cfg->work_q);
free_mem(cfg);
+ scsi_host_put(cfg->host);
break;
}
@@ -916,7 +747,7 @@ static void cxlflash_remove(struct pci_dev *pdev)
/**
* alloc_mem() - allocates the AFU and its command pool
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
* A partially allocated state remains on failure.
*
@@ -929,15 +760,14 @@ static int alloc_mem(struct cxlflash_cfg *cfg)
int rc = 0;
int i;
char *buf = NULL;
+ struct device *dev = &cfg->dev->dev;
- /* This allocation is about 12K, i.e. only 1 64k page
- * and upto 4 4k pages
- */
+ /* AFU is ~12k, i.e. only one 64k page or up to four 4k pages */
cfg->afu = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(sizeof(struct afu)));
if (unlikely(!cfg->afu)) {
- pr_err("%s: cannot get %d free pages\n",
- __func__, get_order(sizeof(struct afu)));
+ dev_err(dev, "%s: cannot get %d free pages\n",
+ __func__, get_order(sizeof(struct afu)));
rc = -ENOMEM;
goto out;
}
@@ -948,7 +778,8 @@ static int alloc_mem(struct cxlflash_cfg *cfg)
if (!((u64)buf & (PAGE_SIZE - 1))) {
buf = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
if (unlikely(!buf)) {
- pr_err("%s: Allocate command buffers fail!\n",
+ dev_err(dev,
+ "%s: Allocate command buffers fail!\n",
__func__);
rc = -ENOMEM;
free_mem(cfg);
@@ -967,12 +798,9 @@ out:
/**
* init_pci() - initializes the host as a PCI device
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
- * Return:
- * 0 on success
- * -EIO on unable to communicate with device
- * A return code from the PCI sub-routines
+ * Return: 0 on success, -errno on failure
*/
static int init_pci(struct cxlflash_cfg *cfg)
{
@@ -1052,11 +880,9 @@ out_release_regions:
/**
* init_scsi() - adds the host to the SCSI stack and kicks off host scan
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
- * Return:
- * 0 on success
- * A return code from adding the host
+ * Return: 0 on success, -errno on failure
*/
static int init_scsi(struct cxlflash_cfg *cfg)
{
@@ -1085,7 +911,7 @@ out:
* that the FC link layer has synced, completed the handshaking process, and
* is ready for login to start.
*/
-static void set_port_online(u64 *fc_regs)
+static void set_port_online(__be64 __iomem *fc_regs)
{
u64 cmdcfg;
@@ -1101,7 +927,7 @@ static void set_port_online(u64 *fc_regs)
*
* The provided MMIO region must be mapped prior to call.
*/
-static void set_port_offline(u64 *fc_regs)
+static void set_port_offline(__be64 __iomem *fc_regs)
{
u64 cmdcfg;
@@ -1125,7 +951,7 @@ static void set_port_offline(u64 *fc_regs)
* FALSE (0) when the specified port fails to come online after timeout
* -EINVAL when @delay_us is less than 1000
*/
-static int wait_port_online(u64 *fc_regs, u32 delay_us, u32 nretry)
+static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
{
u64 status;
@@ -1156,7 +982,7 @@ static int wait_port_online(u64 *fc_regs, u32 delay_us, u32 nretry)
* FALSE (0) when the specified port fails to go offline after timeout
* -EINVAL when @delay_us is less than 1000
*/
-static int wait_port_offline(u64 *fc_regs, u32 delay_us, u32 nretry)
+static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
{
u64 status;
@@ -1191,9 +1017,10 @@ static int wait_port_offline(u64 *fc_regs, u32 delay_us, u32 nretry)
* 0 when the WWPN is successfully written and the port comes back online
* -1 when the port fails to go offline or come back up online
*/
-static int afu_set_wwpn(struct afu *afu, int port, u64 *fc_regs, u64 wwpn)
+static int afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs,
+ u64 wwpn)
{
- int ret = 0;
+ int rc = 0;
set_port_offline(fc_regs);
@@ -1201,33 +1028,26 @@ static int afu_set_wwpn(struct afu *afu, int port, u64 *fc_regs, u64 wwpn)
FC_PORT_STATUS_RETRY_CNT)) {
pr_debug("%s: wait on port %d to go offline timed out\n",
__func__, port);
- ret = -1; /* but continue on to leave the port back online */
+ rc = -1; /* but continue on to leave the port back online */
}
- if (ret == 0)
+ if (rc == 0)
writeq_be(wwpn, &fc_regs[FC_PNAME / 8]);
+ /* Always return success after programming WWPN */
+ rc = 0;
+
set_port_online(fc_regs);
if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US,
FC_PORT_STATUS_RETRY_CNT)) {
- pr_debug("%s: wait on port %d to go online timed out\n",
- __func__, port);
- ret = -1;
-
- /*
- * Override for internal lun!!!
- */
- if (afu->internal_lun) {
- pr_debug("%s: Overriding port %d online timeout!!!\n",
- __func__, port);
- ret = 0;
- }
+ pr_err("%s: wait on port %d to go online timed out\n",
+ __func__, port);
}
- pr_debug("%s: returning rc=%d\n", __func__, ret);
+ pr_debug("%s: returning rc=%d\n", __func__, rc);
- return ret;
+ return rc;
}
/**
@@ -1243,7 +1063,7 @@ static int afu_set_wwpn(struct afu *afu, int port, u64 *fc_regs, u64 wwpn)
* the alternate port exclusively while the reset takes place.
* failure to come online is overridden.
*/
-static void afu_link_reset(struct afu *afu, int port, u64 *fc_regs)
+static void afu_link_reset(struct afu *afu, int port, __be64 __iomem *fc_regs)
{
u64 port_sel;
@@ -1280,19 +1100,19 @@ static const struct asyc_intr_info ainfo[] = {
{SISL_ASTATUS_FC0_OTHER, "other error", 0, CLR_FC_ERROR | LINK_RESET},
{SISL_ASTATUS_FC0_LOGO, "target initiated LOGO", 0, 0},
{SISL_ASTATUS_FC0_CRC_T, "CRC threshold exceeded", 0, LINK_RESET},
- {SISL_ASTATUS_FC0_LOGI_R, "login timed out, retrying", 0, 0},
+ {SISL_ASTATUS_FC0_LOGI_R, "login timed out, retrying", 0, LINK_RESET},
{SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR},
- {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, 0},
+ {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST},
{SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0},
- {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0},
+ {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST},
{SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET},
{SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0},
{SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET},
{SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, 0},
{SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR},
- {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, 0},
+ {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST},
{SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0},
- {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0},
+ {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST},
{0x0, "", 0, 0} /* terminator */
};
@@ -1454,47 +1274,46 @@ static irqreturn_t cxlflash_rrq_irq(int irq, void *data)
static irqreturn_t cxlflash_async_err_irq(int irq, void *data)
{
struct afu *afu = (struct afu *)data;
- struct cxlflash_cfg *cfg;
+ struct cxlflash_cfg *cfg = afu->parent;
+ struct device *dev = &cfg->dev->dev;
u64 reg_unmasked;
const struct asyc_intr_info *info;
- struct sisl_global_map *global = &afu->afu_map->global;
+ struct sisl_global_map __iomem *global = &afu->afu_map->global;
u64 reg;
u8 port;
int i;
- cfg = afu->parent;
-
reg = readq_be(&global->regs.aintr_status);
reg_unmasked = (reg & SISL_ASTATUS_UNMASK);
if (reg_unmasked == 0) {
- pr_err("%s: spurious interrupt, aintr_status 0x%016llX\n",
- __func__, reg);
+ dev_err(dev, "%s: spurious interrupt, aintr_status 0x%016llX\n",
+ __func__, reg);
goto out;
}
- /* it is OK to clear AFU status before FC_ERROR */
+ /* FYI, it is 'okay' to clear AFU status before FC_ERROR */
writeq_be(reg_unmasked, &global->regs.aintr_clear);
- /* check each bit that is on */
+ /* Check each bit that is on */
for (i = 0; reg_unmasked; i++, reg_unmasked = (reg_unmasked >> 1)) {
info = find_ainfo(1ULL << i);
- if ((reg_unmasked & 0x1) || !info)
+ if (((reg_unmasked & 0x1) == 0) || !info)
continue;
port = info->port;
- pr_err("%s: FC Port %d -> %s, fc_status 0x%08llX\n",
- __func__, port, info->desc,
+ dev_err(dev, "%s: FC Port %d -> %s, fc_status 0x%08llX\n",
+ __func__, port, info->desc,
readq_be(&global->fc_regs[port][FC_STATUS / 8]));
/*
- * do link reset first, some OTHER errors will set FC_ERROR
+ * Do link reset first, some OTHER errors will set FC_ERROR
* again if cleared before or w/o a reset
*/
if (info->action & LINK_RESET) {
- pr_err("%s: FC Port %d: resetting link\n",
- __func__, port);
+ dev_err(dev, "%s: FC Port %d: resetting link\n",
+ __func__, port);
cfg->lr_state = LINK_RESET_REQUIRED;
cfg->lr_port = port;
schedule_work(&cfg->work_q);
@@ -1504,26 +1323,31 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data)
reg = readq_be(&global->fc_regs[port][FC_ERROR / 8]);
/*
- * since all errors are unmasked, FC_ERROR and FC_ERRCAP
+ * Since all errors are unmasked, FC_ERROR and FC_ERRCAP
* should be the same and tracing one is sufficient.
*/
- pr_err("%s: fc %d: clearing fc_error 0x%08llX\n",
- __func__, port, reg);
+ dev_err(dev, "%s: fc %d: clearing fc_error 0x%08llX\n",
+ __func__, port, reg);
writeq_be(reg, &global->fc_regs[port][FC_ERROR / 8]);
writeq_be(0, &global->fc_regs[port][FC_ERRCAP / 8]);
}
+
+ if (info->action & SCAN_HOST) {
+ atomic_inc(&cfg->scan_host_needed);
+ schedule_work(&cfg->work_q);
+ }
}
out:
- pr_debug("%s: returning rc=%d, afu=%p\n", __func__, IRQ_HANDLED, afu);
+ dev_dbg(dev, "%s: returning IRQ_HANDLED, afu=%p\n", __func__, afu);
return IRQ_HANDLED;
}
/**
* start_context() - starts the master context
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
* Return: A success or failure value from CXL services.
*/
@@ -1541,12 +1365,10 @@ static int start_context(struct cxlflash_cfg *cfg)
/**
* read_vpd() - obtains the WWPNs from VPD
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
* @wwpn: Array of size NUM_FC_PORTS to pass back WWPNs
*
- * Return:
- * 0 on success
- * -ENODEV when VPD or WWPN keywords not found
+ * Return: 0 on success, -errno on failure
*/
static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
{
@@ -1561,7 +1383,7 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
/* Get the VPD data from the device */
vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
if (unlikely(vpd_size <= 0)) {
- pr_err("%s: Unable to read VPD (size = %ld)\n",
+ dev_err(&dev->dev, "%s: Unable to read VPD (size = %ld)\n",
__func__, vpd_size);
rc = -ENODEV;
goto out;
@@ -1571,7 +1393,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size,
PCI_VPD_LRDT_RO_DATA);
if (unlikely(ro_start < 0)) {
- pr_err("%s: VPD Read-only data not found\n", __func__);
+ dev_err(&dev->dev, "%s: VPD Read-only data not found\n",
+ __func__);
rc = -ENODEV;
goto out;
}
@@ -1600,8 +1423,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
i = pci_vpd_find_info_keyword(vpd_data, i, j, wwpn_vpd_tags[k]);
if (unlikely(i < 0)) {
- pr_err("%s: Port %d WWPN not found in VPD\n",
- __func__, k);
+ dev_err(&dev->dev, "%s: Port %d WWPN not found "
+ "in VPD\n", __func__, k);
rc = -ENODEV;
goto out;
}
@@ -1609,7 +1432,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
j = pci_vpd_info_field_size(&vpd_data[i]);
i += PCI_VPD_INFO_FLD_HDR_SIZE;
if (unlikely((i + j > vpd_size) || (j != WWPN_LEN))) {
- pr_err("%s: Port %d WWPN incomplete or VPD corrupt\n",
+ dev_err(&dev->dev, "%s: Port %d WWPN incomplete or "
+ "VPD corrupt\n",
__func__, k);
rc = -ENODEV;
goto out;
@@ -1618,8 +1442,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
memcpy(tmp_buf, &vpd_data[i], WWPN_LEN);
rc = kstrtoul(tmp_buf, WWPN_LEN, (ulong *)&wwpn[k]);
if (unlikely(rc)) {
- pr_err("%s: Fail to convert port %d WWPN to integer\n",
- __func__, k);
+ dev_err(&dev->dev, "%s: Fail to convert port %d WWPN "
+ "to integer\n", __func__, k);
rc = -ENODEV;
goto out;
}
@@ -1631,91 +1455,36 @@ out:
}
/**
- * cxlflash_context_reset() - timeout handler for AFU commands
- * @cmd: AFU command that timed out.
- *
- * Sends a reset to the AFU.
- */
-void cxlflash_context_reset(struct afu_cmd *cmd)
-{
- int nretry = 0;
- u64 rrin = 0x1;
- u64 room = 0;
- struct afu *afu = cmd->parent;
- ulong lock_flags;
-
- pr_debug("%s: cmd=%p\n", __func__, cmd);
-
- spin_lock_irqsave(&cmd->slock, lock_flags);
-
- /* Already completed? */
- if (cmd->sa.host_use_b[0] & B_DONE) {
- spin_unlock_irqrestore(&cmd->slock, lock_flags);
- return;
- }
-
- cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT);
- spin_unlock_irqrestore(&cmd->slock, lock_flags);
-
- /*
- * We really want to send this reset at all costs, so spread
- * out wait time on successive retries for available room.
- */
- do {
- room = readq_be(&afu->host_map->cmd_room);
- atomic64_set(&afu->room, room);
- if (room)
- goto write_rrin;
- udelay(nretry);
- } while (nretry++ < MC_ROOM_RETRY_CNT);
-
- pr_err("%s: no cmd_room to send reset\n", __func__);
- return;
-
-write_rrin:
- nretry = 0;
- writeq_be(rrin, &afu->host_map->ioarrin);
- do {
- rrin = readq_be(&afu->host_map->ioarrin);
- if (rrin != 0x1)
- break;
- /* Double delay each time */
- udelay(2 ^ nretry);
- } while (nretry++ < MC_ROOM_RETRY_CNT);
-}
-
-/**
* init_pcr() - initialize the provisioning and control registers
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
* Also sets up fast access to the mapped registers and initializes AFU
* command fields that never change.
*/
-void init_pcr(struct cxlflash_cfg *cfg)
+static void init_pcr(struct cxlflash_cfg *cfg)
{
struct afu *afu = cfg->afu;
- struct sisl_ctrl_map *ctrl_map;
+ struct sisl_ctrl_map __iomem *ctrl_map;
int i;
for (i = 0; i < MAX_CONTEXT; i++) {
ctrl_map = &afu->afu_map->ctrls[i].ctrl;
- /* disrupt any clients that could be running */
- /* e. g. clients that survived a master restart */
+ /* Disrupt any clients that could be running */
+ /* e.g. clients that survived a master restart */
writeq_be(0, &ctrl_map->rht_start);
writeq_be(0, &ctrl_map->rht_cnt_id);
writeq_be(0, &ctrl_map->ctx_cap);
}
- /* copy frequently used fields into afu */
+ /* Copy frequently used fields into afu */
afu->ctx_hndl = (u16) cxl_process_element(cfg->mcctx);
- /* ctx_hndl is 16 bits in CAIA */
afu->host_map = &afu->afu_map->hosts[afu->ctx_hndl].host;
afu->ctrl_map = &afu->afu_map->ctrls[afu->ctx_hndl].ctrl;
/* Program the Endian Control for the master context */
writeq_be(SISL_ENDIAN_CTRL, &afu->host_map->endian_ctrl);
- /* initialize cmd fields that never change */
+ /* Initialize cmd fields that never change */
for (i = 0; i < CXLFLASH_NUM_CMDS; i++) {
afu->cmd[i].rcb.ctx_id = afu->ctx_hndl;
afu->cmd[i].rcb.msi = SISL_MSI_RRQ_UPDATED;
@@ -1725,11 +1494,12 @@ void init_pcr(struct cxlflash_cfg *cfg)
/**
* init_global() - initialize AFU global registers
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*/
-int init_global(struct cxlflash_cfg *cfg)
+static int init_global(struct cxlflash_cfg *cfg)
{
struct afu *afu = cfg->afu;
+ struct device *dev = &cfg->dev->dev;
u64 wwpn[NUM_FC_PORTS]; /* wwpn of AFU ports */
int i = 0, num_ports = 0;
int rc = 0;
@@ -1737,13 +1507,13 @@ int init_global(struct cxlflash_cfg *cfg)
rc = read_vpd(cfg, &wwpn[0]);
if (rc) {
- pr_err("%s: could not read vpd rc=%d\n", __func__, rc);
+ dev_err(dev, "%s: could not read vpd rc=%d\n", __func__, rc);
goto out;
}
pr_debug("%s: wwpn0=0x%llX wwpn1=0x%llX\n", __func__, wwpn[0], wwpn[1]);
- /* set up RRQ in AFU for master issued cmds */
+ /* Set up RRQ in AFU for master issued cmds */
writeq_be((u64) afu->hrrq_start, &afu->host_map->rrq_start);
writeq_be((u64) afu->hrrq_end, &afu->host_map->rrq_end);
@@ -1756,9 +1526,9 @@ int init_global(struct cxlflash_cfg *cfg)
/* checker on if dual afu */
writeq_be(reg, &afu->afu_map->global.regs.afu_config);
- /* global port select: select either port */
+ /* Global port select: select either port */
if (afu->internal_lun) {
- /* only use port 0 */
+ /* Only use port 0 */
writeq_be(PORT0, &afu->afu_map->global.regs.afu_port_sel);
num_ports = NUM_FC_PORTS - 1;
} else {
@@ -1767,20 +1537,20 @@ int init_global(struct cxlflash_cfg *cfg)
}
for (i = 0; i < num_ports; i++) {
- /* unmask all errors (but they are still masked at AFU) */
+ /* Unmask all errors (but they are still masked at AFU) */
writeq_be(0, &afu->afu_map->global.fc_regs[i][FC_ERRMSK / 8]);
- /* clear CRC error cnt & set a threshold */
+ /* Clear CRC error cnt & set a threshold */
(void)readq_be(&afu->afu_map->global.
fc_regs[i][FC_CNT_CRCERR / 8]);
writeq_be(MC_CRC_THRESH, &afu->afu_map->global.fc_regs[i]
[FC_CRC_THRESH / 8]);
- /* set WWPNs. If already programmed, wwpn[i] is 0 */
+ /* Set WWPNs. If already programmed, wwpn[i] is 0 */
if (wwpn[i] != 0 &&
afu_set_wwpn(afu, i,
&afu->afu_map->global.fc_regs[i][0],
wwpn[i])) {
- pr_err("%s: failed to set WWPN on port %d\n",
+ dev_err(dev, "%s: failed to set WWPN on port %d\n",
__func__, i);
rc = -EIO;
goto out;
@@ -1789,18 +1559,17 @@ int init_global(struct cxlflash_cfg *cfg)
* offline/online transitions and a PLOGI
*/
msleep(100);
-
}
- /* set up master's own CTX_CAP to allow real mode, host translation */
- /* tbls, afu cmds and read/write GSCSI cmds. */
+ /* Set up master's own CTX_CAP to allow real mode, host translation */
+ /* tables, afu cmds and read/write GSCSI cmds. */
/* First, unlock ctx_cap write by reading mbox */
(void)readq_be(&afu->ctrl_map->mbox_r); /* unlock ctx_cap */
writeq_be((SISL_CTX_CAP_REAL_MODE | SISL_CTX_CAP_HOST_XLATE |
SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD |
SISL_CTX_CAP_AFU_CMD | SISL_CTX_CAP_GSCSI_CMD),
&afu->ctrl_map->ctx_cap);
- /* init heartbeat */
+ /* Initialize heartbeat */
afu->hb = readq_be(&afu->afu_map->global.regs.afu_hb);
out:
@@ -1809,7 +1578,7 @@ out:
/**
* start_afu() - initializes and starts the AFU
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*/
static int start_afu(struct cxlflash_cfg *cfg)
{
@@ -1829,7 +1598,10 @@ static int start_afu(struct cxlflash_cfg *cfg)
init_pcr(cfg);
- /* initialize RRQ pointers */
+ /* After an AFU reset, RRQ entries are stale, clear them */
+ memset(&afu->rrq_entry, 0, sizeof(afu->rrq_entry));
+
+ /* Initialize RRQ pointers */
afu->hrrq_start = &afu->rrq_entry[0];
afu->hrrq_end = &afu->rrq_entry[NUM_RRQ_ENTRY - 1];
afu->hrrq_curr = afu->hrrq_start;
@@ -1843,12 +1615,9 @@ static int start_afu(struct cxlflash_cfg *cfg)
/**
* init_mc() - create and register as the master context
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
- * Return:
- * 0 on success
- * -ENOMEM when unable to obtain a context from CXL services
- * A failure value from CXL services.
+ * Return: 0 on success, -errno on failure
*/
static int init_mc(struct cxlflash_cfg *cfg)
{
@@ -1932,15 +1701,12 @@ out:
/**
* init_afu() - setup as master context and start AFU
- * @cxlflash: Internal structure associated with the host.
+ * @cfg: Internal structure associated with the host.
*
* This routine is a higher level of control for configuring the
* AFU on probe and reset paths.
*
- * Return:
- * 0 on success
- * -ENOMEM when unable to map the AFU MMIO space
- * A failure value from internal services.
+ * Return: 0 on success, -errno on failure
*/
static int init_afu(struct cxlflash_cfg *cfg)
{
@@ -1955,36 +1721,38 @@ static int init_afu(struct cxlflash_cfg *cfg)
if (rc) {
dev_err(dev, "%s: call to init_mc failed, rc=%d!\n",
__func__, rc);
- goto err1;
+ goto out;
}
- /* Map the entire MMIO space of the AFU.
- */
+ /* Map the entire MMIO space of the AFU */
afu->afu_map = cxl_psa_map(cfg->mcctx);
if (!afu->afu_map) {
- rc = -ENOMEM;
- term_mc(cfg, UNDO_START);
dev_err(dev, "%s: call to cxl_psa_map failed!\n", __func__);
+ rc = -ENOMEM;
goto err1;
}
- /* don't byte reverse on reading afu_version, else the string form */
- /* will be backwards */
- reg = afu->afu_map->global.regs.afu_version;
- memcpy(afu->version, &reg, 8);
+ /* No byte reverse on reading afu_version or string will be backwards */
+ reg = readq(&afu->afu_map->global.regs.afu_version);
+ memcpy(afu->version, &reg, sizeof(reg));
afu->interface_version =
readq_be(&afu->afu_map->global.regs.interface_version);
- pr_debug("%s: afu version %s, interface version 0x%llX\n",
- __func__, afu->version, afu->interface_version);
+ if ((afu->interface_version + 1) == 0) {
+ pr_err("Back level AFU, please upgrade. AFU version %s "
+ "interface version 0x%llx\n", afu->version,
+ afu->interface_version);
+ rc = -EINVAL;
+ goto err2;
+ }
+
+ pr_debug("%s: afu version %s, interface version 0x%llX\n", __func__,
+ afu->version, afu->interface_version);
rc = start_afu(cfg);
if (rc) {
dev_err(dev, "%s: call to start_afu failed, rc=%d!\n",
__func__, rc);
- term_mc(cfg, UNDO_START);
- cxl_psa_unmap((void *)afu->afu_map);
- afu->afu_map = NULL;
- goto err1;
+ goto err2;
}
afu_err_intr_init(cfg->afu);
@@ -1992,98 +1760,19 @@ static int init_afu(struct cxlflash_cfg *cfg)
/* Restore the LUN mappings */
cxlflash_restore_luntable(cfg);
-err1:
- pr_debug("%s: returning rc=%d\n", __func__, rc);
- return rc;
-}
-
-/**
- * cxlflash_send_cmd() - sends an AFU command
- * @afu: AFU associated with the host.
- * @cmd: AFU command to send.
- *
- * Return:
- * 0 on success
- * -1 on failure
- */
-int cxlflash_send_cmd(struct afu *afu, struct afu_cmd *cmd)
-{
- struct cxlflash_cfg *cfg = afu->parent;
- int nretry = 0;
- int rc = 0;
- u64 room;
- long newval;
-
- /*
- * This routine is used by critical users such an AFU sync and to
- * send a task management function (TMF). Thus we want to retry a
- * bit before returning an error. To avoid the performance penalty
- * of MMIO, we spread the update of 'room' over multiple commands.
- */
-retry:
- newval = atomic64_dec_if_positive(&afu->room);
- if (!newval) {
- do {
- room = readq_be(&afu->host_map->cmd_room);
- atomic64_set(&afu->room, room);
- if (room)
- goto write_ioarrin;
- udelay(nretry);
- } while (nretry++ < MC_ROOM_RETRY_CNT);
-
- pr_err("%s: no cmd_room to send 0x%X\n",
- __func__, cmd->rcb.cdb[0]);
-
- goto no_room;
- } else if (unlikely(newval < 0)) {
- /* This should be rare. i.e. Only if two threads race and
- * decrement before the MMIO read is done. In this case
- * just benefit from the other thread having updated
- * afu->room.
- */
- if (nretry++ < MC_ROOM_RETRY_CNT) {
- udelay(nretry);
- goto retry;
- }
-
- goto no_room;
- }
-
-write_ioarrin:
- writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin);
out:
- pr_debug("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd,
- cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc);
+ pr_debug("%s: returning rc=%d\n", __func__, rc);
return rc;
-no_room:
- afu->read_room = true;
- schedule_work(&cfg->work_q);
- rc = SCSI_MLQUEUE_HOST_BUSY;
+err2:
+ cxl_psa_unmap((void __iomem *)afu->afu_map);
+ afu->afu_map = NULL;
+err1:
+ term_mc(cfg, UNDO_START);
goto out;
}
/**
- * cxlflash_wait_resp() - polls for a response or timeout to a sent AFU command
- * @afu: AFU associated with the host.
- * @cmd: AFU command that was sent.
- */
-void cxlflash_wait_resp(struct afu *afu, struct afu_cmd *cmd)
-{
- ulong timeout = jiffies + (cmd->rcb.timeout * 2 * HZ);
-
- timeout = wait_for_completion_timeout(&cmd->cevent, timeout);
- if (!timeout)
- cxlflash_context_reset(cmd);
-
- if (unlikely(cmd->sa.ioasc != 0))
- pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, "
- "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0],
- cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc,
- cmd->sa.rc.fc_rc);
-}
-
-/**
* cxlflash_afu_sync() - builds and sends an AFU sync command
* @afu: AFU associated with the host.
* @ctx_hndl_u: Identifies context requesting sync.
@@ -2091,7 +1780,7 @@ void cxlflash_wait_resp(struct afu *afu, struct afu_cmd *cmd)
* @mode: Type of sync to issue (lightweight, heavyweight, global).
*
* The AFU can only take 1 sync command at a time. This routine enforces this
- * limitation by using a mutex to provide exlusive access to the AFU during
+ * limitation by using a mutex to provide exclusive access to the AFU during
* the sync. This design point requires calling threads to not be on interrupt
* context due to the possibility of sleeping during concurrent sync operations.
*
@@ -2109,6 +1798,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
res_hndl_t res_hndl_u, u8 mode)
{
struct cxlflash_cfg *cfg = afu->parent;
+ struct device *dev = &cfg->dev->dev;
struct afu_cmd *cmd = NULL;
int rc = 0;
int retry_cnt = 0;
@@ -2121,13 +1811,13 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
mutex_lock(&sync_active);
retry:
- cmd = cxlflash_cmd_checkout(afu);
+ cmd = cmd_checkout(afu);
if (unlikely(!cmd)) {
retry_cnt++;
udelay(1000 * retry_cnt);
if (retry_cnt < MC_RETRY_CNT)
goto retry;
- pr_err("%s: could not get a free command\n", __func__);
+ dev_err(dev, "%s: could not get a free command\n", __func__);
rc = -1;
goto out;
}
@@ -2147,36 +1837,34 @@ retry:
cmd->rcb.cdb[1] = mode;
/* The cdb is aligned, no unaligned accessors required */
- *((u16 *)&cmd->rcb.cdb[2]) = swab16(ctx_hndl_u);
- *((u32 *)&cmd->rcb.cdb[4]) = swab32(res_hndl_u);
+ *((__be16 *)&cmd->rcb.cdb[2]) = cpu_to_be16(ctx_hndl_u);
+ *((__be32 *)&cmd->rcb.cdb[4]) = cpu_to_be32(res_hndl_u);
- rc = cxlflash_send_cmd(afu, cmd);
+ rc = send_cmd(afu, cmd);
if (unlikely(rc))
goto out;
- cxlflash_wait_resp(afu, cmd);
+ wait_resp(afu, cmd);
- /* set on timeout */
+ /* Set on timeout */
if (unlikely((cmd->sa.ioasc != 0) ||
(cmd->sa.host_use_b[0] & B_ERROR)))
rc = -1;
out:
mutex_unlock(&sync_active);
if (cmd)
- cxlflash_cmd_checkin(cmd);
+ cmd_checkin(cmd);
pr_debug("%s: returning rc=%d\n", __func__, rc);
return rc;
}
/**
- * cxlflash_afu_reset() - resets the AFU
- * @cxlflash: Internal structure associated with the host.
+ * afu_reset() - resets the AFU
+ * @cfg: Internal structure associated with the host.
*
- * Return:
- * 0 on success
- * A failure value from internal services.
+ * Return: 0 on success, -errno on failure
*/
-int cxlflash_afu_reset(struct cxlflash_cfg *cfg)
+static int afu_reset(struct cxlflash_cfg *cfg)
{
int rc = 0;
/* Stop the context before the reset. Since the context is
@@ -2192,6 +1880,413 @@ int cxlflash_afu_reset(struct cxlflash_cfg *cfg)
}
/**
+ * cxlflash_eh_device_reset_handler() - reset a single LUN
+ * @scp: SCSI command to send.
+ *
+ * Return:
+ * SUCCESS as defined in scsi/scsi.h
+ * FAILED as defined in scsi/scsi.h
+ */
+static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp)
+{
+ int rc = SUCCESS;
+ struct Scsi_Host *host = scp->device->host;
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
+ struct afu *afu = cfg->afu;
+ int rcr = 0;
+
+ pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
+ "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
+ host->host_no, scp->device->channel,
+ scp->device->id, scp->device->lun,
+ get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
+
+retry:
+ switch (cfg->state) {
+ case STATE_NORMAL:
+ rcr = send_tmf(afu, scp, TMF_LUN_RESET);
+ if (unlikely(rcr))
+ rc = FAILED;
+ break;
+ case STATE_RESET:
+ wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
+ goto retry;
+ default:
+ rc = FAILED;
+ break;
+ }
+
+ pr_debug("%s: returning rc=%d\n", __func__, rc);
+ return rc;
+}
+
+/**
+ * cxlflash_eh_host_reset_handler() - reset the host adapter
+ * @scp: SCSI command from stack identifying host.
+ *
+ * Return:
+ * SUCCESS as defined in scsi/scsi.h
+ * FAILED as defined in scsi/scsi.h
+ */
+static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
+{
+ int rc = SUCCESS;
+ int rcr = 0;
+ struct Scsi_Host *host = scp->device->host;
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
+
+ pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
+ "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
+ host->host_no, scp->device->channel,
+ scp->device->id, scp->device->lun,
+ get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
+ get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
+
+ switch (cfg->state) {
+ case STATE_NORMAL:
+ cfg->state = STATE_RESET;
+ cxlflash_mark_contexts_error(cfg);
+ rcr = afu_reset(cfg);
+ if (rcr) {
+ rc = FAILED;
+ cfg->state = STATE_FAILTERM;
+ } else
+ cfg->state = STATE_NORMAL;
+ wake_up_all(&cfg->reset_waitq);
+ break;
+ case STATE_RESET:
+ wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
+ if (cfg->state == STATE_NORMAL)
+ break;
+ /* fall through */
+ default:
+ rc = FAILED;
+ break;
+ }
+
+ pr_debug("%s: returning rc=%d\n", __func__, rc);
+ return rc;
+}
+
+/**
+ * cxlflash_change_queue_depth() - change the queue depth for the device
+ * @sdev: SCSI device destined for queue depth change.
+ * @qdepth: Requested queue depth value to set.
+ *
+ * The requested queue depth is capped to the maximum supported value.
+ *
+ * Return: The actual queue depth set.
+ */
+static int cxlflash_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+
+ if (qdepth > CXLFLASH_MAX_CMDS_PER_LUN)
+ qdepth = CXLFLASH_MAX_CMDS_PER_LUN;
+
+ scsi_change_queue_depth(sdev, qdepth);
+ return sdev->queue_depth;
+}
+
+/**
+ * cxlflash_show_port_status() - queries and presents the current port status
+ * @port: Desired port for status reporting.
+ * @afu: AFU owning the specified port.
+ * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t cxlflash_show_port_status(u32 port, struct afu *afu, char *buf)
+{
+ char *disp_status;
+ u64 status;
+ __be64 __iomem *fc_regs;
+
+ if (port >= NUM_FC_PORTS)
+ return 0;
+
+ fc_regs = &afu->afu_map->global.fc_regs[port][0];
+ status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
+ status &= FC_MTIP_STATUS_MASK;
+
+ if (status == FC_MTIP_STATUS_ONLINE)
+ disp_status = "online";
+ else if (status == FC_MTIP_STATUS_OFFLINE)
+ disp_status = "offline";
+ else
+ disp_status = "unknown";
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", disp_status);
+}
+
+/**
+ * port0_show() - queries and presents the current status of port 0
+ * @dev: Generic device associated with the host owning the port.
+ * @attr: Device attribute representing the port.
+ * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t port0_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
+ struct afu *afu = cfg->afu;
+
+ return cxlflash_show_port_status(0, afu, buf);
+}
+
+/**
+ * port1_show() - queries and presents the current status of port 1
+ * @dev: Generic device associated with the host owning the port.
+ * @attr: Device attribute representing the port.
+ * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t port1_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
+ struct afu *afu = cfg->afu;
+
+ return cxlflash_show_port_status(1, afu, buf);
+}
+
+/**
+ * lun_mode_show() - presents the current LUN mode of the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the LUN mode.
+ * @buf: Buffer of length PAGE_SIZE to report back the LUN mode in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t lun_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
+ struct afu *afu = cfg->afu;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", afu->internal_lun);
+}
+
+/**
+ * lun_mode_store() - sets the LUN mode of the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the LUN mode.
+ * @buf: Buffer of length PAGE_SIZE containing the LUN mode in ASCII.
+ * @count: Length of data resizing in @buf.
+ *
+ * The CXL Flash AFU supports a dummy LUN mode where the external
+ * links and storage are not required. Space on the FPGA is used
+ * to create 1 or 2 small LUNs which are presented to the system
+ * as if they were a normal storage device. This feature is useful
+ * during development and also provides manufacturing with a way
+ * to test the AFU without an actual device.
+ *
+ * 0 = external LUN[s] (default)
+ * 1 = internal LUN (1 x 64K, 512B blocks, id 0)
+ * 2 = internal LUN (1 x 64K, 4K blocks, id 0)
+ * 3 = internal LUN (2 x 32K, 512B blocks, ids 0,1)
+ * 4 = internal LUN (2 x 32K, 4K blocks, ids 0,1)
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t lun_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
+ struct afu *afu = cfg->afu;
+ int rc;
+ u32 lun_mode;
+
+ rc = kstrtouint(buf, 10, &lun_mode);
+ if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) {
+ afu->internal_lun = lun_mode;
+ afu_reset(cfg);
+ scsi_scan_host(cfg->host);
+ }
+
+ return count;
+}
+
+/**
+ * ioctl_version_show() - presents the current ioctl version of the host
+ * @dev: Generic device associated with the host.
+ * @attr: Device attribute representing the ioctl version.
+ * @buf: Buffer of length PAGE_SIZE to report back the ioctl version.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t ioctl_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0);
+}
+
+/**
+ * cxlflash_show_port_lun_table() - queries and presents the port LUN table
+ * @port: Desired port for status reporting.
+ * @afu: AFU owning the specified port.
+ * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t cxlflash_show_port_lun_table(u32 port,
+ struct afu *afu,
+ char *buf)
+{
+ int i;
+ ssize_t bytes = 0;
+ __be64 __iomem *fc_port;
+
+ if (port >= NUM_FC_PORTS)
+ return 0;
+
+ fc_port = &afu->afu_map->global.fc_port[port][0];
+
+ for (i = 0; i < CXLFLASH_NUM_VLUNS; i++)
+ bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes,
+ "%03d: %016llX\n", i, readq_be(&fc_port[i]));
+ return bytes;
+}
+
+/**
+ * port0_lun_table_show() - presents the current LUN table of port 0
+ * @dev: Generic device associated with the host owning the port.
+ * @attr: Device attribute representing the port.
+ * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t port0_lun_table_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
+ struct afu *afu = cfg->afu;
+
+ return cxlflash_show_port_lun_table(0, afu, buf);
+}
+
+/**
+ * port1_lun_table_show() - presents the current LUN table of port 1
+ * @dev: Generic device associated with the host owning the port.
+ * @attr: Device attribute representing the port.
+ * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t port1_lun_table_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
+ struct afu *afu = cfg->afu;
+
+ return cxlflash_show_port_lun_table(1, afu, buf);
+}
+
+/**
+ * mode_show() - presents the current mode of the device
+ * @dev: Generic device associated with the device.
+ * @attr: Device attribute representing the device mode.
+ * @buf: Buffer of length PAGE_SIZE to report back the dev mode in ASCII.
+ *
+ * Return: The size of the ASCII string returned in @buf.
+ */
+static ssize_t mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ sdev->hostdata ? "superpipe" : "legacy");
+}
+
+/*
+ * Host attributes
+ */
+static DEVICE_ATTR_RO(port0);
+static DEVICE_ATTR_RO(port1);
+static DEVICE_ATTR_RW(lun_mode);
+static DEVICE_ATTR_RO(ioctl_version);
+static DEVICE_ATTR_RO(port0_lun_table);
+static DEVICE_ATTR_RO(port1_lun_table);
+
+static struct device_attribute *cxlflash_host_attrs[] = {
+ &dev_attr_port0,
+ &dev_attr_port1,
+ &dev_attr_lun_mode,
+ &dev_attr_ioctl_version,
+ &dev_attr_port0_lun_table,
+ &dev_attr_port1_lun_table,
+ NULL
+};
+
+/*
+ * Device attributes
+ */
+static DEVICE_ATTR_RO(mode);
+
+static struct device_attribute *cxlflash_dev_attrs[] = {
+ &dev_attr_mode,
+ NULL
+};
+
+/*
+ * Host template
+ */
+static struct scsi_host_template driver_template = {
+ .module = THIS_MODULE,
+ .name = CXLFLASH_ADAPTER_NAME,
+ .info = cxlflash_driver_info,
+ .ioctl = cxlflash_ioctl,
+ .proc_name = CXLFLASH_NAME,
+ .queuecommand = cxlflash_queuecommand,
+ .eh_device_reset_handler = cxlflash_eh_device_reset_handler,
+ .eh_host_reset_handler = cxlflash_eh_host_reset_handler,
+ .change_queue_depth = cxlflash_change_queue_depth,
+ .cmd_per_lun = 16,
+ .can_queue = CXLFLASH_MAX_CMDS,
+ .this_id = -1,
+ .sg_tablesize = SG_NONE, /* No scatter gather support */
+ .max_sectors = CXLFLASH_MAX_SECTORS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .shost_attrs = cxlflash_host_attrs,
+ .sdev_attrs = cxlflash_dev_attrs,
+};
+
+/*
+ * Device dependent values
+ */
+static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS };
+
+/*
+ * PCI device binding table
+ */
+static struct pci_device_id cxlflash_pci_table[] = {
+ {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals},
+ {}
+};
+
+MODULE_DEVICE_TABLE(pci, cxlflash_pci_table);
+
+/**
* cxlflash_worker_thread() - work thread handler for the AFU
* @work: Work structure contained within cxlflash associated with host.
*
@@ -2199,12 +2294,14 @@ int cxlflash_afu_reset(struct cxlflash_cfg *cfg)
* - Link reset which cannot be performed on interrupt context due to
* blocking up to a few seconds
* - Read AFU command room
+ * - Rescan the host
*/
static void cxlflash_worker_thread(struct work_struct *work)
{
struct cxlflash_cfg *cfg = container_of(work, struct cxlflash_cfg,
work_q);
struct afu *afu = cfg->afu;
+ struct device *dev = &cfg->dev->dev;
int port;
ulong lock_flags;
@@ -2218,15 +2315,15 @@ static void cxlflash_worker_thread(struct work_struct *work)
if (cfg->lr_state == LINK_RESET_REQUIRED) {
port = cfg->lr_port;
if (port < 0)
- pr_err("%s: invalid port index %d\n", __func__, port);
+ dev_err(dev, "%s: invalid port index %d\n",
+ __func__, port);
else {
spin_unlock_irqrestore(cfg->host->host_lock,
lock_flags);
/* The reset can block... */
afu_link_reset(afu, port,
- &afu->afu_map->
- global.fc_regs[port][0]);
+ &afu->afu_map->global.fc_regs[port][0]);
spin_lock_irqsave(cfg->host->host_lock, lock_flags);
}
@@ -2239,6 +2336,9 @@ static void cxlflash_worker_thread(struct work_struct *work)
}
spin_unlock_irqrestore(cfg->host->host_lock, lock_flags);
+
+ if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0)
+ scsi_scan_host(cfg->host);
}
/**
@@ -2246,7 +2346,7 @@ static void cxlflash_worker_thread(struct work_struct *work)
* @pdev: PCI device associated with the host.
* @dev_id: PCI device id associated with device.
*
- * Return: 0 on success / non-zero on failure
+ * Return: 0 on success, -errno on failure
*/
static int cxlflash_probe(struct pci_dev *pdev,
const struct pci_device_id *dev_id)
@@ -2281,14 +2381,16 @@ static int cxlflash_probe(struct pci_dev *pdev,
cfg->host = host;
rc = alloc_mem(cfg);
if (rc) {
- dev_err(&pdev->dev, "%s: call to scsi_host_alloc failed!\n",
+ dev_err(&pdev->dev, "%s: call to alloc_mem failed!\n",
__func__);
rc = -ENOMEM;
+ scsi_host_put(cfg->host);
goto out;
}
cfg->init_state = INIT_STATE_NONE;
cfg->dev = pdev;
+ cfg->cxl_fops = cxlflash_cxl_fops;
/*
* The promoted LUNs move to the top of the LUN table. The rest stay
@@ -2301,28 +2403,30 @@ static int cxlflash_probe(struct pci_dev *pdev,
cfg->last_lun_index[1] = CXLFLASH_NUM_VLUNS/2 - 1;
cfg->dev_id = (struct pci_device_id *)dev_id;
- cfg->mcctx = NULL;
init_waitqueue_head(&cfg->tmf_waitq);
- init_waitqueue_head(&cfg->limbo_waitq);
+ init_waitqueue_head(&cfg->reset_waitq);
INIT_WORK(&cfg->work_q, cxlflash_worker_thread);
cfg->lr_state = LINK_RESET_INVALID;
cfg->lr_port = -1;
+ spin_lock_init(&cfg->tmf_slock);
mutex_init(&cfg->ctx_tbl_list_mutex);
mutex_init(&cfg->ctx_recovery_mutex);
+ init_rwsem(&cfg->ioctl_rwsem);
INIT_LIST_HEAD(&cfg->ctx_err_recovery);
INIT_LIST_HEAD(&cfg->lluns);
pci_set_drvdata(pdev, cfg);
- /* Use the special service provided to look up the physical
+ /*
+ * Use the special service provided to look up the physical
* PCI device, since we are called on the probe of the virtual
* PCI host bus (vphb)
*/
phys_dev = cxl_get_phys_dev(pdev);
if (!dev_is_pci(phys_dev)) {
- pr_err("%s: not a pci dev\n", __func__);
+ dev_err(&pdev->dev, "%s: not a pci dev\n", __func__);
rc = -ENODEV;
goto out_remove;
}
@@ -2346,7 +2450,6 @@ static int cxlflash_probe(struct pci_dev *pdev,
}
cfg->init_state = INIT_STATE_AFU;
-
rc = init_scsi(cfg);
if (rc) {
dev_err(&pdev->dev, "%s: call to init_scsi "
@@ -2365,6 +2468,19 @@ out_remove:
}
/**
+ * drain_ioctls() - wait until all currently executing ioctls have completed
+ * @cfg: Internal structure associated with the host.
+ *
+ * Obtain write access to read/write semaphore that wraps ioctl
+ * handling to 'drain' ioctls currently executing.
+ */
+static void drain_ioctls(struct cxlflash_cfg *cfg)
+{
+ down_write(&cfg->ioctl_rwsem);
+ up_write(&cfg->ioctl_rwsem);
+}
+
+/**
* cxlflash_pci_error_detected() - called when a PCI error is detected
* @pdev: PCI device struct.
* @state: PCI channel state.
@@ -2382,21 +2498,19 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
switch (state) {
case pci_channel_io_frozen:
- cfg->state = STATE_LIMBO;
-
- /* Turn off legacy I/O */
+ cfg->state = STATE_RESET;
scsi_block_requests(cfg->host);
+ drain_ioctls(cfg);
rc = cxlflash_mark_contexts_error(cfg);
if (unlikely(rc))
dev_err(dev, "%s: Failed to mark user contexts!(%d)\n",
__func__, rc);
term_mc(cfg, UNDO_START);
stop_afu(cfg);
-
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
cfg->state = STATE_FAILTERM;
- wake_up_all(&cfg->limbo_waitq);
+ wake_up_all(&cfg->reset_waitq);
scsi_unblock_requests(cfg->host);
return PCI_ERS_RESULT_DISCONNECT;
default:
@@ -2443,7 +2557,7 @@ static void cxlflash_pci_resume(struct pci_dev *pdev)
dev_dbg(dev, "%s: pdev=%p\n", __func__, pdev);
cfg->state = STATE_NORMAL;
- wake_up_all(&cfg->limbo_waitq);
+ wake_up_all(&cfg->reset_waitq);
scsi_unblock_requests(cfg->host);
}
@@ -2467,7 +2581,7 @@ static struct pci_driver cxlflash_driver = {
/**
* init_cxlflash() - module entry point
*
- * Return: 0 on success / non-zero on failure
+ * Return: 0 on success, -errno on failure
*/
static int __init init_cxlflash(void)
{
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index cf0e80938b13..60324566c14f 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -99,6 +99,7 @@ struct asyc_intr_info {
u8 action;
#define CLR_FC_ERROR 0x01
#define LINK_RESET 0x02
+#define SCAN_HOST 0x04
};
#ifndef CONFIG_CXL_EEH
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index 63bf394fe78c..0b3366f5e6f6 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -146,7 +146,7 @@ struct sisl_rc {
#define SISL_FC_RC_ABORTFAIL 0x59 /* pending abort completed w/fail */
#define SISL_FC_RC_RESID 0x5A /* ioasa underrun/overrun flags set */
#define SISL_FC_RC_RESIDERR 0x5B /* actual data len does not match SCSI
- reported len, possbly due to dropped
+ reported len, possibly due to dropped
frames */
#define SISL_FC_RC_TGTABORT 0x5C /* command aborted by target */
};
@@ -258,7 +258,7 @@ struct sisl_host_map {
__be64 rrq_start; /* start & end are both inclusive */
__be64 rrq_end; /* write sequence: start followed by end */
__be64 cmd_room;
- __be64 ctx_ctrl; /* least signiifcant byte or b56:63 is LISN# */
+ __be64 ctx_ctrl; /* least significant byte or b56:63 is LISN# */
__be64 mbox_w; /* restricted use */
};
@@ -290,7 +290,7 @@ struct sisl_global_regs {
#define SISL_ASTATUS_FC0_LOGO 0x4000ULL /* b49, target sent FLOGI/PLOGI/LOGO
while logged in */
#define SISL_ASTATUS_FC0_CRC_T 0x2000ULL /* b50, CRC threshold exceeded */
-#define SISL_ASTATUS_FC0_LOGI_R 0x1000ULL /* b51, login state mechine timed out
+#define SISL_ASTATUS_FC0_LOGI_R 0x1000ULL /* b51, login state machine timed out
and retrying */
#define SISL_ASTATUS_FC0_LOGI_F 0x0800ULL /* b52, login failed,
FC_ERROR[19:0] */
@@ -340,7 +340,7 @@ struct sisl_global_regs {
#define SISL_AFUCONF_MBOX_CLR_READ 0x0010ULL
__be64 afu_config;
__be64 rsvd[0xf8];
- __be64 afu_version;
+ __le64 afu_version;
__be64 interface_version;
};
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index f1b62cea75b1..cac2e6a50efd 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -76,7 +76,7 @@ void cxlflash_free_errpage(void)
*
* When the host needs to go down, all users must be quiesced and their
* memory freed. This is accomplished by putting the contexts in error
- * state which will notify the user and let them 'drive' the tear-down.
+ * state which will notify the user and let them 'drive' the tear down.
* Meanwhile, this routine camps until all user contexts have been removed.
*/
void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg)
@@ -100,7 +100,7 @@ void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg)
dev_dbg(dev, "%s: Wait for user contexts to quiesce...\n",
__func__);
- wake_up_all(&cfg->limbo_waitq);
+ wake_up_all(&cfg->reset_waitq);
ssleep(1);
}
}
@@ -162,10 +162,7 @@ struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid,
if (likely(ctxid < MAX_CONTEXT)) {
while (true) {
- rc = mutex_lock_interruptible(&cfg->ctx_tbl_list_mutex);
- if (rc)
- goto out;
-
+ mutex_lock(&cfg->ctx_tbl_list_mutex);
ctxi = cfg->ctx_tbl[ctxid];
if (ctxi)
if ((file && (ctxi->file != file)) ||
@@ -253,7 +250,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
{
struct device *dev = &cfg->dev->dev;
struct afu *afu = cfg->afu;
- struct sisl_ctrl_map *ctrl_map = ctxi->ctrl_map;
+ struct sisl_ctrl_map __iomem *ctrl_map = ctxi->ctrl_map;
int rc = 0;
u64 val;
@@ -283,6 +280,24 @@ out:
* @sdev: SCSI device associated with LUN.
* @lli: LUN destined for capacity request.
*
+ * The READ_CAP16 can take quite a while to complete. Should an EEH occur while
+ * in scsi_execute(), the EEH handler will attempt to recover. As part of the
+ * recovery, the handler drains all currently running ioctls, waiting until they
+ * have completed before proceeding with a reset. As this routine is used on the
+ * ioctl path, this can create a condition where the EEH handler becomes stuck,
+ * infinitely waiting for this ioctl thread. To avoid this behavior, temporarily
+ * unmark this thread as an ioctl thread by releasing the ioctl read semaphore.
+ * This will allow the EEH handler to proceed with a recovery while this thread
+ * is still running. Once the scsi_execute() returns, reacquire the ioctl read
+ * semaphore and check the adapter state in case it changed while inside of
+ * scsi_execute(). The state check will wait if the adapter is still being
+ * recovered or return a failure if the recovery failed. In the event that the
+ * adapter reset failed, simply return the failure as the ioctl would be unable
+ * to continue.
+ *
+ * Note that the above puts a requirement on this routine to only be called on
+ * an ioctl thread.
+ *
* Return: 0 on success, -errno on failure
*/
static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
@@ -296,7 +311,7 @@ static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
int rc = 0;
int result = 0;
int retry_cnt = 0;
- u32 tout = (MC_DISCOVERY_TIMEOUT * HZ);
+ u32 to = CMD_TIMEOUT * HZ;
retry:
cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL);
@@ -314,8 +329,18 @@ retry:
dev_dbg(dev, "%s: %ssending cmd(0x%x)\n", __func__,
retry_cnt ? "re" : "", scsi_cmd[0]);
+ /* Drop the ioctl read semahpore across lengthy call */
+ up_read(&cfg->ioctl_rwsem);
result = scsi_execute(sdev, scsi_cmd, DMA_FROM_DEVICE, cmd_buf,
- CMD_BUFSIZE, sense_buf, tout, 5, 0, NULL);
+ CMD_BUFSIZE, sense_buf, to, CMD_RETRIES, 0, NULL);
+ down_read(&cfg->ioctl_rwsem);
+ rc = check_state(cfg);
+ if (rc) {
+ dev_err(dev, "%s: Failed state! result=0x08%X\n",
+ __func__, result);
+ rc = -ENODEV;
+ goto out;
+ }
if (driver_byte(result) == DRIVER_SENSE) {
result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
@@ -365,8 +390,8 @@ retry:
* as the buffer is allocated on an aligned boundary.
*/
mutex_lock(&gli->mutex);
- gli->max_lba = be64_to_cpu(*((u64 *)&cmd_buf[0]));
- gli->blk_len = be32_to_cpu(*((u32 *)&cmd_buf[8]));
+ gli->max_lba = be64_to_cpu(*((__be64 *)&cmd_buf[0]));
+ gli->blk_len = be32_to_cpu(*((__be32 *)&cmd_buf[8]));
mutex_unlock(&gli->mutex);
out:
@@ -712,7 +737,6 @@ static void destroy_context(struct cxlflash_cfg *cfg,
kfree(ctxi->rht_needs_ws);
kfree(ctxi->rht_lun);
kfree(ctxi);
- atomic_dec_if_positive(&cfg->num_user_contexts);
}
/**
@@ -737,7 +761,7 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg,
struct afu *afu = cfg->afu;
struct ctx_info *ctxi = NULL;
struct llun_info **lli = NULL;
- bool *ws = NULL;
+ u8 *ws = NULL;
struct sisl_rht_entry *rhte;
ctxi = kzalloc(sizeof(*ctxi), GFP_KERNEL);
@@ -769,7 +793,6 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg,
INIT_LIST_HEAD(&ctxi->luns);
INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
- atomic_inc(&cfg->num_user_contexts);
mutex_lock(&ctxi->mutex);
out:
return ctxi;
@@ -880,6 +903,9 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
sys_close(lfd);
}
+ /* Release the sdev reference that bound this LUN to the context */
+ scsi_device_put(sdev);
+
out:
if (put_ctx)
put_context(ctxi);
@@ -1161,10 +1187,7 @@ out:
return rc;
}
-/*
- * Local fops for adapter file descriptor
- */
-static const struct file_operations cxlflash_cxl_fops = {
+const struct file_operations cxlflash_cxl_fops = {
.owner = THIS_MODULE,
.mmap = cxlflash_cxl_mmap,
.release = cxlflash_cxl_release,
@@ -1211,6 +1234,46 @@ static const struct file_operations null_fops = {
};
/**
+ * check_state() - checks and responds to the current adapter state
+ * @cfg: Internal structure associated with the host.
+ *
+ * This routine can block and should only be used on process context.
+ * It assumes that the caller is an ioctl thread and holding the ioctl
+ * read semaphore. This is temporarily let up across the wait to allow
+ * for draining actively running ioctls. Also note that when waking up
+ * from waiting in reset, the state is unknown and must be checked again
+ * before proceeding.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+int check_state(struct cxlflash_cfg *cfg)
+{
+ struct device *dev = &cfg->dev->dev;
+ int rc = 0;
+
+retry:
+ switch (cfg->state) {
+ case STATE_RESET:
+ dev_dbg(dev, "%s: Reset state, going to wait...\n", __func__);
+ up_read(&cfg->ioctl_rwsem);
+ rc = wait_event_interruptible(cfg->reset_waitq,
+ cfg->state != STATE_RESET);
+ down_read(&cfg->ioctl_rwsem);
+ if (unlikely(rc))
+ break;
+ goto retry;
+ case STATE_FAILTERM:
+ dev_dbg(dev, "%s: Failed/Terminating!\n", __func__);
+ rc = -ENODEV;
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+/**
* cxlflash_disk_attach() - attach a LUN to a context
* @sdev: SCSI device associated with LUN.
* @attach: Attach ioctl data structure.
@@ -1243,10 +1306,6 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
int fd = -1;
- /* On first attach set fileops */
- if (atomic_read(&cfg->num_user_contexts) == 0)
- cfg->cxl_fops = cxlflash_cxl_fops;
-
if (attach->num_interrupts > 4) {
dev_dbg(dev, "%s: Cannot support this many interrupts %llu\n",
__func__, attach->num_interrupts);
@@ -1287,11 +1346,17 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
}
}
+ rc = scsi_device_get(sdev);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: Unable to get sdev reference!\n", __func__);
+ goto out;
+ }
+
lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL);
if (unlikely(!lun_access)) {
dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__);
rc = -ENOMEM;
- goto out;
+ goto err0;
}
lun_access->lli = lli;
@@ -1311,21 +1376,21 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
dev_err(dev, "%s: Could not initialize context %p\n",
__func__, ctx);
rc = -ENODEV;
- goto err0;
+ goto err1;
}
ctxid = cxl_process_element(ctx);
if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
rc = -EPERM;
- goto err1;
+ goto err2;
}
file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
if (unlikely(fd < 0)) {
rc = -ENODEV;
dev_err(dev, "%s: Could not get file descriptor\n", __func__);
- goto err1;
+ goto err2;
}
/* Translate read/write O_* flags from fcntl.h to AFU permission bits */
@@ -1335,7 +1400,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(!ctxi)) {
dev_err(dev, "%s: Failed to create context! (%d)\n",
__func__, ctxid);
- goto err2;
+ goto err3;
}
work = &ctxi->work;
@@ -1346,13 +1411,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(rc)) {
dev_dbg(dev, "%s: Could not start context rc=%d\n",
__func__, rc);
- goto err3;
+ goto err4;
}
rc = afu_attach(cfg, ctxi);
if (unlikely(rc)) {
dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc);
- goto err4;
+ goto err5;
}
/*
@@ -1375,7 +1440,8 @@ out_attach:
attach->block_size = gli->blk_len;
attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea);
attach->last_lba = gli->max_lba;
- attach->max_xfer = (sdev->host->max_sectors * 512) / gli->blk_len;
+ attach->max_xfer = sdev->host->max_sectors * MAX_SECTOR_UNIT;
+ attach->max_xfer /= gli->blk_len;
out:
attach->adap_fd = fd;
@@ -1387,13 +1453,13 @@ out:
__func__, ctxid, fd, attach->block_size, rc, attach->last_lba);
return rc;
-err4:
+err5:
cxl_stop_context(ctx);
-err3:
+err4:
put_context(ctxi);
destroy_context(cfg, ctxi);
ctxi = NULL;
-err2:
+err3:
/*
* Here, we're overriding the fops with a dummy all-NULL fops because
* fput() calls the release fop, which will cause us to mistakenly
@@ -1405,10 +1471,12 @@ err2:
fput(file);
put_unused_fd(fd);
fd = -1;
-err1:
+err2:
cxl_release_context(ctx);
-err0:
+err1:
kfree(lun_access);
+err0:
+ scsi_device_put(sdev);
goto out;
}
@@ -1511,41 +1579,6 @@ err1:
}
/**
- * check_state() - checks and responds to the current adapter state
- * @cfg: Internal structure associated with the host.
- *
- * This routine can block and should only be used on process context.
- * Note that when waking up from waiting in limbo, the state is unknown
- * and must be checked again before proceeding.
- *
- * Return: 0 on success, -errno on failure
- */
-static int check_state(struct cxlflash_cfg *cfg)
-{
- struct device *dev = &cfg->dev->dev;
- int rc = 0;
-
-retry:
- switch (cfg->state) {
- case STATE_LIMBO:
- dev_dbg(dev, "%s: Limbo, going to wait...\n", __func__);
- rc = wait_event_interruptible(cfg->limbo_waitq,
- cfg->state != STATE_LIMBO);
- if (unlikely(rc))
- break;
- goto retry;
- case STATE_FAILTERM:
- dev_dbg(dev, "%s: Failed/Terminating!\n", __func__);
- rc = -ENODEV;
- break;
- default:
- break;
- }
-
- return rc;
-}
-
-/**
* cxlflash_afu_recover() - initiates AFU recovery
* @sdev: SCSI device associated with LUN.
* @recover: Recover ioctl data structure.
@@ -1561,10 +1594,10 @@ retry:
* quite possible for this routine to act as the kernel's EEH detection
* source (MMIO read of mbox_r). Because of this, there is a window of
* time where an EEH might have been detected but not yet 'serviced'
- * (callback invoked, causing the device to enter limbo state). To avoid
+ * (callback invoked, causing the device to enter reset state). To avoid
* looping in this routine during that window, a 1 second sleep is in place
* between the time the MMIO failure is detected and the time a wait on the
- * limbo wait queue is attempted via check_state().
+ * reset wait queue is attempted via check_state().
*
* Return: 0 on success, -errno on failure
*/
@@ -1634,9 +1667,14 @@ retry_recover:
/* Test if in error state */
reg = readq_be(&afu->ctrl_map->mbox_r);
if (reg == -1) {
- dev_dbg(dev, "%s: MMIO read fail! Wait for recovery...\n",
- __func__);
- mutex_unlock(&ctxi->mutex);
+ dev_dbg(dev, "%s: MMIO fail, wait for recovery.\n", __func__);
+
+ /*
+ * Before checking the state, put back the context obtained with
+ * get_context() as it is no longer needed and sleep for a short
+ * period of time (see prolog notes).
+ */
+ put_context(ctxi);
ctxi = NULL;
ssleep(1);
rc = check_state(cfg);
@@ -1765,12 +1803,21 @@ static int cxlflash_disk_verify(struct scsi_device *sdev,
* inquiry (i.e. the Unit attention is due to the WWN changing).
*/
if (verify->hint & DK_CXLFLASH_VERIFY_HINT_SENSE) {
+ /* Can't hold mutex across process_sense/read_cap16,
+ * since we could have an intervening EEH event.
+ */
+ ctxi->unavail = true;
+ mutex_unlock(&ctxi->mutex);
rc = process_sense(sdev, verify);
if (unlikely(rc)) {
dev_err(dev, "%s: Failed to validate sense data (%d)\n",
__func__, rc);
+ mutex_lock(&ctxi->mutex);
+ ctxi->unavail = false;
goto out;
}
+ mutex_lock(&ctxi->mutex);
+ ctxi->unavail = false;
}
switch (gli->mode) {
@@ -1955,6 +2002,14 @@ out:
* @cmd: IOCTL command.
* @arg: Userspace ioctl data structure.
*
+ * A read/write semaphore is used to implement a 'drain' of currently
+ * running ioctls. The read semaphore is taken at the beginning of each
+ * ioctl thread and released upon concluding execution. Additionally the
+ * semaphore should be released and then reacquired in any ioctl execution
+ * path which will wait for an event to occur that is outside the scope of
+ * the ioctl (i.e. an adapter reset). To drain the ioctls currently running,
+ * a thread simply needs to acquire the write semaphore.
+ *
* Return: 0 on success, -errno on failure
*/
int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
@@ -1989,6 +2044,9 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{sizeof(struct dk_cxlflash_clone), (sioctl)cxlflash_disk_clone},
};
+ /* Hold read semaphore so we can drain if needed */
+ down_read(&cfg->ioctl_rwsem);
+
/* Restrict command set to physical support only for internal LUN */
if (afu->internal_lun)
switch (cmd) {
@@ -2070,6 +2128,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
/* fall through to exit */
cxlflash_ioctl_exit:
+ up_read(&cfg->ioctl_rwsem);
if (unlikely(rc && known_ioctl))
dev_err(dev, "%s: ioctl %s (%08X) on dev(%d/%d/%d/%llu) "
"returned rc %d\n", __func__,
diff --git a/drivers/scsi/cxlflash/superpipe.h b/drivers/scsi/cxlflash/superpipe.h
index d7dc88bc64a4..bede574bcd77 100644
--- a/drivers/scsi/cxlflash/superpipe.h
+++ b/drivers/scsi/cxlflash/superpipe.h
@@ -28,7 +28,10 @@ extern struct cxlflash_global global;
*/
#define MC_CHUNK_SIZE (1 << MC_RHT_NMASK) /* in LBAs */
-#define MC_DISCOVERY_TIMEOUT 5 /* 5 secs */
+#define CMD_TIMEOUT 30 /* 30 secs */
+#define CMD_RETRIES 5 /* 5 retries for scsi_execute */
+
+#define MAX_SECTOR_UNIT 512 /* max_sector is in 512 byte multiples */
#define CHAN2PORT(_x) ((_x) + 1)
#define PORT2CHAN(_x) ((_x) - 1)
@@ -60,7 +63,6 @@ struct llun_info {
u32 lun_index; /* Index in the LUN table */
u32 host_no; /* host_no from Scsi_host */
u32 port_sel; /* What port to use for this LUN */
- bool newly_created; /* Whether the LUN was just discovered */
bool in_table; /* Whether a LUN table entry was created */
u8 wwid[16]; /* Keep a duplicate copy here? */
@@ -84,17 +86,17 @@ enum ctx_ctrl {
CTX_CTRL_FILE = (1 << 5)
};
-#define ENCODE_CTXID(_ctx, _id) (((((u64)_ctx) & 0xFFFFFFFF0) << 28) | _id)
+#define ENCODE_CTXID(_ctx, _id) (((((u64)_ctx) & 0xFFFFFFFF0ULL) << 28) | _id)
#define DECODE_CTXID(_val) (_val & 0xFFFFFFFF)
struct ctx_info {
- struct sisl_ctrl_map *ctrl_map; /* initialized at startup */
+ struct sisl_ctrl_map __iomem *ctrl_map; /* initialized at startup */
struct sisl_rht_entry *rht_start; /* 1 page (req'd for alignment),
alloc/free on attach/detach */
u32 rht_out; /* Number of checked out RHT entries */
u32 rht_perms; /* User-defined permissions for RHT entries */
struct llun_info **rht_lun; /* Mapping of RHT entries to LUNs */
- bool *rht_needs_ws; /* User-desired write-same function per RHTE */
+ u8 *rht_needs_ws; /* User-desired write-same function per RHTE */
struct cxl_ioctl_start_work work;
u64 ctxid;
@@ -144,4 +146,6 @@ void cxlflash_ba_terminate(struct ba_lun *);
int cxlflash_manage_lun(struct scsi_device *, struct dk_cxlflash_manage_lun *);
+int check_state(struct cxlflash_cfg *);
+
#endif /* ifndef _CXLFLASH_SUPERPIPE_H */
diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c
index 6155cb1d4ed3..a53f583e2d7b 100644
--- a/drivers/scsi/cxlflash/vlun.c
+++ b/drivers/scsi/cxlflash/vlun.c
@@ -132,7 +132,7 @@ static int ba_init(struct ba_lun *ba_lun)
return -ENOMEM;
}
- /* Pass the allocated lun info as a handle to the user */
+ /* Pass the allocated LUN info as a handle to the user */
ba_lun->ba_lun_handle = bali;
pr_debug("%s: Successfully initialized the LUN: "
@@ -165,7 +165,7 @@ static int find_free_range(u32 low,
num_bits = (sizeof(*lam) * BITS_PER_BYTE);
bit_pos = find_first_bit(lam, num_bits);
- pr_devel("%s: Found free bit %llX in lun "
+ pr_devel("%s: Found free bit %llX in LUN "
"map entry %llX at bitmap index = %X\n",
__func__, bit_pos, bali->lun_alloc_map[i],
i);
@@ -400,6 +400,24 @@ static int init_vlun(struct llun_info *lli)
* @lba: Logical block address to start write same.
* @nblks: Number of logical blocks to write same.
*
+ * The SCSI WRITE_SAME16 can take quite a while to complete. Should an EEH occur
+ * while in scsi_execute(), the EEH handler will attempt to recover. As part of
+ * the recovery, the handler drains all currently running ioctls, waiting until
+ * they have completed before proceeding with a reset. As this routine is used
+ * on the ioctl path, this can create a condition where the EEH handler becomes
+ * stuck, infinitely waiting for this ioctl thread. To avoid this behavior,
+ * temporarily unmark this thread as an ioctl thread by releasing the ioctl read
+ * semaphore. This will allow the EEH handler to proceed with a recovery while
+ * this thread is still running. Once the scsi_execute() returns, reacquire the
+ * ioctl read semaphore and check the adapter state in case it changed while
+ * inside of scsi_execute(). The state check will wait if the adapter is still
+ * being recovered or return a failure if the recovery failed. In the event that
+ * the adapter reset failed, simply return the failure as the ioctl would be
+ * unable to continue.
+ *
+ * Note that the above puts a requirement on this routine to only be called on
+ * an ioctl thread.
+ *
* Return: 0 on success, -errno on failure
*/
static int write_same16(struct scsi_device *sdev,
@@ -414,7 +432,7 @@ static int write_same16(struct scsi_device *sdev,
int ws_limit = SISLITE_MAX_WS_BLOCKS;
u64 offset = lba;
int left = nblks;
- u32 tout = sdev->request_queue->rq_timeout;
+ u32 to = sdev->request_queue->rq_timeout;
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata;
struct device *dev = &cfg->dev->dev;
@@ -433,8 +451,20 @@ static int write_same16(struct scsi_device *sdev,
put_unaligned_be32(ws_limit < left ? ws_limit : left,
&scsi_cmd[10]);
+ /* Drop the ioctl read semahpore across lengthy call */
+ up_read(&cfg->ioctl_rwsem);
result = scsi_execute(sdev, scsi_cmd, DMA_TO_DEVICE, cmd_buf,
- CMD_BUFSIZE, sense_buf, tout, 5, 0, NULL);
+ CMD_BUFSIZE, sense_buf, to, CMD_RETRIES,
+ 0, NULL);
+ down_read(&cfg->ioctl_rwsem);
+ rc = check_state(cfg);
+ if (rc) {
+ dev_err(dev, "%s: Failed state! result=0x08%X\n",
+ __func__, result);
+ rc = -ENODEV;
+ goto out;
+ }
+
if (result) {
dev_err_ratelimited(dev, "%s: command failed for "
"offset %lld result=0x%x\n",
@@ -681,14 +711,14 @@ out:
}
/**
- * _cxlflash_vlun_resize() - changes the size of a virtual lun
+ * _cxlflash_vlun_resize() - changes the size of a virtual LUN
* @sdev: SCSI device associated with LUN owning virtual LUN.
* @ctxi: Context owning resources.
* @resize: Resize ioctl data structure.
*
* On successful return, the user is informed of the new size (in blocks)
- * of the virtual lun in last LBA format. When the size of the virtual
- * lun is zero, the last LBA is reflected as -1. See comment in the
+ * of the virtual LUN in last LBA format. When the size of the virtual
+ * LUN is zero, the last LBA is reflected as -1. See comment in the
* prologue for _cxlflash_disk_release() regarding AFU syncs and contexts
* on the error recovery list.
*
@@ -785,7 +815,7 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg)
u32 chan;
u32 lind;
struct afu *afu = cfg->afu;
- struct sisl_global_map *agm = &afu->afu_map->global;
+ struct sisl_global_map __iomem *agm = &afu->afu_map->global;
mutex_lock(&global.mutex);
@@ -830,7 +860,7 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli)
u32 lind;
int rc = 0;
struct afu *afu = cfg->afu;
- struct sisl_global_map *agm = &afu->afu_map->global;
+ struct sisl_global_map __iomem *agm = &afu->afu_map->global;
mutex_lock(&global.mutex);
@@ -885,8 +915,8 @@ out:
* @arg: UVirtual ioctl data structure.
*
* On successful return, the user is informed of the resource handle
- * to be used to identify the virtual lun and the size (in blocks) of
- * the virtual lun in last LBA format. When the size of the virtual lun
+ * to be used to identify the virtual LUN and the size (in blocks) of
+ * the virtual LUN in last LBA format. When the size of the virtual LUN
* is zero, the last LBA is reflected as -1.
*
* Return: 0 on success, -errno on failure
@@ -914,16 +944,9 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size);
+ /* Setup the LUNs block allocator on first call */
mutex_lock(&gli->mutex);
if (gli->mode == MODE_NONE) {
- /* Setup the LUN table and block allocator on first call */
- rc = init_luntable(cfg, lli);
- if (rc) {
- dev_err(dev, "%s: call to init_luntable failed "
- "rc=%d!\n", __func__, rc);
- goto err0;
- }
-
rc = init_vlun(lli);
if (rc) {
dev_err(dev, "%s: call to init_vlun failed rc=%d!\n",
@@ -941,6 +964,13 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
}
mutex_unlock(&gli->mutex);
+ rc = init_luntable(cfg, lli);
+ if (rc) {
+ dev_err(dev, "%s: call to init_luntable failed rc=%d!\n",
+ __func__, rc);
+ goto err1;
+ }
+
ctxi = get_context(cfg, rctxid, lli, 0);
if (unlikely(!ctxi)) {
dev_err(dev, "%s: Bad context! (%llu)\n", __func__, ctxid);
diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c
index 31f8966b2e03..33581ba4386e 100644
--- a/drivers/scsi/esas2r/esas2r_main.c
+++ b/drivers/scsi/esas2r/esas2r_main.c
@@ -256,7 +256,6 @@ static struct scsi_host_template driver_template = {
.proc_name = ESAS2R_DRVR_NAME,
.change_queue_depth = scsi_change_queue_depth,
.max_sectors = 0xFFFF,
- .use_blk_tags = 1,
};
int sgl_page_size = 512;
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 065b25df741b..71cb05b1c3eb 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2694,7 +2694,6 @@ struct scsi_host_template scsi_esp_template = {
.use_clustering = ENABLE_CLUSTERING,
.max_sectors = 0xffff,
.skip_settle_delay = 1,
- .use_blk_tags = 1,
};
EXPORT_SYMBOL(scsi_esp_template);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index d3eb80c46bbe..f4424063b860 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -287,7 +287,6 @@ static struct scsi_host_template fcoe_shost_template = {
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xffff,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -1873,7 +1872,6 @@ static int fcoe_percpu_receive_thread(void *arg)
set_user_nice(current, MIN_NICE);
-retry:
while (!kthread_should_stop()) {
spin_lock_bh(&p->fcoe_rx_list.lock);
@@ -1883,7 +1881,7 @@ retry:
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_bh(&p->fcoe_rx_list.lock);
schedule();
- goto retry;
+ continue;
}
spin_unlock_bh(&p->fcoe_rx_list.lock);
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index bf0bbd42efb5..67669a9e73c1 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -939,6 +939,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
struct sk_buff *skb;
u16 len;
dma_addr_t pa;
+ int r;
len = FC_FRAME_HEADROOM + FC_MAX_FRAME + FC_FRAME_TAILROOM;
skb = dev_alloc_skb(len);
@@ -952,8 +953,19 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
skb_reset_network_header(skb);
skb_put(skb, len);
pa = pci_map_single(fnic->pdev, skb->data, len, PCI_DMA_FROMDEVICE);
+
+ r = pci_dma_mapping_error(fnic->pdev, pa);
+ if (r) {
+ printk(KERN_ERR "PCI mapping failed with error %d\n", r);
+ goto free_skb;
+ }
+
fnic_queue_rq_desc(rq, skb, pa, len);
return 0;
+
+free_skb:
+ kfree_skb(skb);
+ return r;
}
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
@@ -981,6 +993,7 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
struct ethhdr *eth_hdr;
struct vlan_ethhdr *vlan_hdr;
unsigned long flags;
+ int r;
if (!fnic->vlan_hw_insert) {
eth_hdr = (struct ethhdr *)skb_mac_header(skb);
@@ -1003,18 +1016,27 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
pa = pci_map_single(fnic->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
- spin_lock_irqsave(&fnic->wq_lock[0], flags);
- if (!vnic_wq_desc_avail(wq)) {
- pci_unmap_single(fnic->pdev, pa, skb->len, PCI_DMA_TODEVICE);
- spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
- kfree_skb(skb);
- return;
+ r = pci_dma_mapping_error(fnic->pdev, pa);
+ if (r) {
+ printk(KERN_ERR "PCI mapping failed with error %d\n", r);
+ goto free_skb;
}
+ spin_lock_irqsave(&fnic->wq_lock[0], flags);
+ if (!vnic_wq_desc_avail(wq))
+ goto irq_restore;
+
fnic_queue_wq_eth_desc(wq, skb, pa, skb->len,
0 /* hw inserts cos value */,
fnic->vlan_id, 1);
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
+ return;
+
+irq_restore:
+ spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
+ pci_unmap_single(fnic->pdev, pa, skb->len, PCI_DMA_TODEVICE);
+free_skb:
+ kfree_skb(skb);
}
/*
@@ -1071,6 +1093,12 @@ static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
pa = pci_map_single(fnic->pdev, eth_hdr, tot_len, PCI_DMA_TODEVICE);
+ ret = pci_dma_mapping_error(fnic->pdev, pa);
+ if (ret) {
+ printk(KERN_ERR "DMA map failed with error %d\n", ret);
+ goto free_skb_on_err;
+ }
+
if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_SEND,
(char *)eth_hdr, tot_len)) != 0) {
printk(KERN_ERR "fnic ctlr frame trace error!!!");
@@ -1082,15 +1110,17 @@ static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
pci_unmap_single(fnic->pdev, pa,
tot_len, PCI_DMA_TODEVICE);
ret = -1;
- goto fnic_send_frame_end;
+ goto irq_restore;
}
fnic_queue_wq_desc(wq, skb, pa, tot_len, fr_eof(fp),
0 /* hw inserts cos value */,
fnic->vlan_id, 1, 1, 1);
-fnic_send_frame_end:
+
+irq_restore:
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
+free_skb_on_err:
if (ret)
dev_kfree_skb_any(fp_skb(fp));
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 8a0d4d7b3254..58ce9020d69c 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -118,7 +118,6 @@ static struct scsi_host_template fnic_host_template = {
.sg_tablesize = FNIC_MAX_SG_DESC_CNT,
.max_sectors = 0xffff,
.shost_attrs = fnic_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -697,13 +696,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
fnic->fnic_max_tag_id = host->can_queue;
- err = scsi_init_shared_tag_map(host, fnic->fnic_max_tag_id);
- if (err) {
- shost_printk(KERN_ERR, fnic->lport->host,
- "Unable to alloc shared tag map\n");
- goto err_out_dev_close;
- }
-
host->max_lun = fnic->config.luns_per_tgt;
host->max_id = FNIC_MAX_FCP_TARGET;
host->max_cmd_len = FCOE_MAX_CMD_LEN;
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 25436cd2860c..266b909fe854 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -330,6 +330,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
int flags;
u8 exch_flags;
struct scsi_lun fc_lun;
+ int r;
if (sg_count) {
/* For each SGE, create a device desc entry */
@@ -346,6 +347,12 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
io_req->sgl_list,
sizeof(io_req->sgl_list[0]) * sg_count,
PCI_DMA_TODEVICE);
+
+ r = pci_dma_mapping_error(fnic->pdev, io_req->sgl_list_pa);
+ if (r) {
+ printk(KERN_ERR "PCI mapping failed with error %d\n", r);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
}
io_req->sense_buf_pa = pci_map_single(fnic->pdev,
@@ -353,6 +360,15 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
SCSI_SENSE_BUFFERSIZE,
PCI_DMA_FROMDEVICE);
+ r = pci_dma_mapping_error(fnic->pdev, io_req->sense_buf_pa);
+ if (r) {
+ pci_unmap_single(fnic->pdev, io_req->sgl_list_pa,
+ sizeof(io_req->sgl_list[0]) * sg_count,
+ PCI_DMA_TODEVICE);
+ printk(KERN_ERR "PCI mapping failed with error %d\n", r);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
int_to_scsilun(sc->device->lun, &fc_lun);
/* Enqueue the descriptor in the Copy WQ */
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 8bb173e01084..323982fd00c3 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -217,6 +217,13 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
error = scsi_mq_setup_tags(shost);
if (error)
goto fail;
+ } else {
+ shost->bqt = blk_init_tags(shost->can_queue,
+ shost->hostt->tag_alloc_policy);
+ if (!shost->bqt) {
+ error = -ENOMEM;
+ goto fail;
+ }
}
/*
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 40669f8dd0df..6a8f95808ee0 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -41,6 +41,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_eh.h>
+#include <scsi/scsi_transport_sas.h>
#include <scsi/scsi_dbg.h>
#include <linux/cciss_ioctl.h>
#include <linux/string.h>
@@ -54,8 +55,11 @@
#include "hpsa_cmd.h"
#include "hpsa.h"
-/* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */
-#define HPSA_DRIVER_VERSION "3.4.10-0"
+/*
+ * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.'
+ * with an optional trailing '-' followed by a byte value (0-255).
+ */
+#define HPSA_DRIVER_VERSION "3.4.14-0"
#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
#define HPSA "hpsa"
@@ -205,6 +209,16 @@ static struct board_type products[] = {
{0xFFFF103C, "Unknown Smart Array", &SA5_access},
};
+static struct scsi_transport_template *hpsa_sas_transport_template;
+static int hpsa_add_sas_host(struct ctlr_info *h);
+static void hpsa_delete_sas_host(struct ctlr_info *h);
+static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node,
+ struct hpsa_scsi_dev_t *device);
+static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device);
+static struct hpsa_scsi_dev_t
+ *hpsa_find_device_by_sas_rphy(struct ctlr_info *h,
+ struct sas_rphy *rphy);
+
#define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy)
static const struct scsi_cmnd hpsa_cmd_busy;
#define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle)
@@ -230,6 +244,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
int cmd_type);
static void hpsa_free_cmd_pool(struct ctlr_info *h);
#define VPD_PAGE (1 << 8)
+#define HPSA_SIMPLE_ERROR_BITS 0x03
static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
static void hpsa_scan_start(struct Scsi_Host *);
@@ -243,7 +258,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev);
static int hpsa_slave_configure(struct scsi_device *sdev);
static void hpsa_slave_destroy(struct scsi_device *sdev);
-static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
+static void hpsa_update_scsi_devices(struct ctlr_info *h);
static int check_for_unit_attention(struct ctlr_info *h,
struct CommandList *c);
static void check_ioctl_unit_attention(struct ctlr_info *h,
@@ -274,7 +289,10 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
static void hpsa_command_resubmit_worker(struct work_struct *work);
static u32 lockup_detected(struct ctlr_info *h);
static int detect_controller_lockup(struct ctlr_info *h);
-static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device);
+static void hpsa_disable_rld_caching(struct ctlr_info *h);
+static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
+ struct ReportExtendedLUNdata *buf, int bufsize);
+static int hpsa_luns_changed(struct ctlr_info *h);
static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
{
@@ -606,7 +624,7 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
}
static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",
- "1(+0)ADM", "UNKNOWN"
+ "1(+0)ADM", "UNKNOWN", "PHYS DRV"
};
#define HPSA_RAID_0 0
#define HPSA_RAID_4 1
@@ -615,7 +633,13 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",
#define HPSA_RAID_51 4
#define HPSA_RAID_6 5 /* also used for RAID 60 */
#define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */
-#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1)
+#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 2)
+#define PHYSICAL_DRIVE (ARRAY_SIZE(raid_label) - 1)
+
+static inline bool is_logical_device(struct hpsa_scsi_dev_t *device)
+{
+ return !device->physical_device;
+}
static ssize_t raid_level_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -637,7 +661,7 @@ static ssize_t raid_level_show(struct device *dev,
}
/* Is this even a logical drive? */
- if (!is_logical_dev_addr_mode(hdev->scsi3addr)) {
+ if (!is_logical_device(hdev)) {
spin_unlock_irqrestore(&h->lock, flags);
l = snprintf(buf, PAGE_SIZE, "N/A\n");
return l;
@@ -726,7 +750,6 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev,
}
#define MAX_PATHS 8
-#define PATH_STRING_LEN 50
static ssize_t path_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -742,9 +765,7 @@ static ssize_t path_info_show(struct device *dev,
u8 path_map_index = 0;
char *active;
unsigned char phys_connector[2];
- unsigned char path[MAX_PATHS][PATH_STRING_LEN];
- memset(path, 0, MAX_PATHS * PATH_STRING_LEN);
sdev = to_scsi_device(dev);
h = sdev_to_hba(sdev);
spin_lock_irqsave(&h->devlock, flags);
@@ -764,18 +785,19 @@ static ssize_t path_info_show(struct device *dev,
else
continue;
- output_len = snprintf(path[i],
- PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ",
+ output_len += scnprintf(buf + output_len,
+ PAGE_SIZE - output_len,
+ "[%d:%d:%d:%d] %20.20s ",
h->scsi_host->host_no,
hdev->bus, hdev->target, hdev->lun,
scsi_device_type(hdev->devtype));
- if (is_ext_target(h, hdev) ||
- (hdev->devtype == TYPE_RAID) ||
- is_logical_dev_addr_mode(hdev->scsi3addr)) {
- output_len += snprintf(path[i] + output_len,
- PATH_STRING_LEN, "%s\n",
- active);
+ if (hdev->external ||
+ hdev->devtype == TYPE_RAID ||
+ is_logical_device(hdev)) {
+ output_len += snprintf(buf + output_len,
+ PAGE_SIZE - output_len,
+ "%s\n", active);
continue;
}
@@ -787,36 +809,33 @@ static ssize_t path_info_show(struct device *dev,
if (phys_connector[1] < '0')
phys_connector[1] = '0';
if (hdev->phys_connector[i] > 0)
- output_len += snprintf(path[i] + output_len,
- PATH_STRING_LEN,
+ output_len += snprintf(buf + output_len,
+ PAGE_SIZE - output_len,
"PORT: %.2s ",
phys_connector);
- if (hdev->devtype == TYPE_DISK &&
- hdev->expose_state != HPSA_DO_NOT_EXPOSE) {
+ if (hdev->devtype == TYPE_DISK && hdev->expose_device) {
if (box == 0 || box == 0xFF) {
- output_len += snprintf(path[i] + output_len,
- PATH_STRING_LEN,
+ output_len += snprintf(buf + output_len,
+ PAGE_SIZE - output_len,
"BAY: %hhu %s\n",
bay, active);
} else {
- output_len += snprintf(path[i] + output_len,
- PATH_STRING_LEN,
+ output_len += snprintf(buf + output_len,
+ PAGE_SIZE - output_len,
"BOX: %hhu BAY: %hhu %s\n",
box, bay, active);
}
} else if (box != 0 && box != 0xFF) {
- output_len += snprintf(path[i] + output_len,
- PATH_STRING_LEN, "BOX: %hhu %s\n",
+ output_len += snprintf(buf + output_len,
+ PAGE_SIZE - output_len, "BOX: %hhu %s\n",
box, active);
} else
- output_len += snprintf(path[i] + output_len,
- PATH_STRING_LEN, "%s\n", active);
+ output_len += snprintf(buf + output_len,
+ PAGE_SIZE - output_len, "%s\n", active);
}
spin_unlock_irqrestore(&h->devlock, flags);
- return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s",
- path[0], path[1], path[2], path[3],
- path[4], path[5], path[6], path[7]);
+ return output_len;
}
static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
@@ -848,7 +867,6 @@ static struct device_attribute *hpsa_sdev_attrs[] = {
&dev_attr_unique_id,
&dev_attr_hp_ssd_smart_path_enabled,
&dev_attr_path_info,
- &dev_attr_lockup_detected,
NULL,
};
@@ -860,6 +878,7 @@ static struct device_attribute *hpsa_shost_attrs[] = {
&dev_attr_resettable,
&dev_attr_hp_ssd_smart_path_status,
&dev_attr_raid_offload_debug,
+ &dev_attr_lockup_detected,
NULL,
};
@@ -1134,25 +1153,62 @@ static int hpsa_find_target_lun(struct ctlr_info *h,
return !found;
}
-static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h,
+static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h,
struct hpsa_scsi_dev_t *dev, char *description)
{
+#define LABEL_SIZE 25
+ char label[LABEL_SIZE];
+
+ if (h == NULL || h->pdev == NULL || h->scsi_host == NULL)
+ return;
+
+ switch (dev->devtype) {
+ case TYPE_RAID:
+ snprintf(label, LABEL_SIZE, "controller");
+ break;
+ case TYPE_ENCLOSURE:
+ snprintf(label, LABEL_SIZE, "enclosure");
+ break;
+ case TYPE_DISK:
+ if (dev->external)
+ snprintf(label, LABEL_SIZE, "external");
+ else if (!is_logical_dev_addr_mode(dev->scsi3addr))
+ snprintf(label, LABEL_SIZE, "%s",
+ raid_label[PHYSICAL_DRIVE]);
+ else
+ snprintf(label, LABEL_SIZE, "RAID-%s",
+ dev->raid_level > RAID_UNKNOWN ? "?" :
+ raid_label[dev->raid_level]);
+ break;
+ case TYPE_ROM:
+ snprintf(label, LABEL_SIZE, "rom");
+ break;
+ case TYPE_TAPE:
+ snprintf(label, LABEL_SIZE, "tape");
+ break;
+ case TYPE_MEDIUM_CHANGER:
+ snprintf(label, LABEL_SIZE, "changer");
+ break;
+ default:
+ snprintf(label, LABEL_SIZE, "UNKNOWN");
+ break;
+ }
+
dev_printk(level, &h->pdev->dev,
- "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n",
+ "scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n",
h->scsi_host->host_no, dev->bus, dev->target, dev->lun,
description,
scsi_device_type(dev->devtype),
dev->vendor,
dev->model,
- dev->raid_level > RAID_UNKNOWN ?
- "RAID-?" : raid_label[dev->raid_level],
+ label,
dev->offload_config ? '+' : '-',
dev->offload_enabled ? '+' : '-',
- dev->expose_state);
+ dev->expose_device);
}
/* Add an entry into h->dev[] array. */
-static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
+static int hpsa_scsi_add_entry(struct ctlr_info *h,
struct hpsa_scsi_dev_t *device,
struct hpsa_scsi_dev_t *added[], int *nadded)
{
@@ -1221,14 +1277,14 @@ lun_assigned:
added[*nadded] = device;
(*nadded)++;
hpsa_show_dev_msg(KERN_INFO, h, device,
- device->expose_state & HPSA_SCSI_ADD ? "added" : "masked");
+ device->expose_device ? "added" : "masked");
device->offload_to_be_enabled = device->offload_enabled;
device->offload_enabled = 0;
return 0;
}
/* Update an entry in h->dev[] array. */
-static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno,
+static void hpsa_scsi_update_entry(struct ctlr_info *h,
int entry, struct hpsa_scsi_dev_t *new_entry)
{
int offload_enabled;
@@ -1276,7 +1332,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno,
}
/* Replace an entry from h->dev[] array. */
-static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
+static void hpsa_scsi_replace_entry(struct ctlr_info *h,
int entry, struct hpsa_scsi_dev_t *new_entry,
struct hpsa_scsi_dev_t *added[], int *nadded,
struct hpsa_scsi_dev_t *removed[], int *nremoved)
@@ -1304,7 +1360,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
}
/* Remove an entry from h->dev[] array. */
-static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
+static void hpsa_scsi_remove_entry(struct ctlr_info *h, int entry,
struct hpsa_scsi_dev_t *removed[], int *nremoved)
{
/* assumes h->devlock is held */
@@ -1415,6 +1471,9 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
#define DEVICE_CHANGED 1
#define DEVICE_SAME 2
#define DEVICE_UPDATED 3
+ if (needle == NULL)
+ return DEVICE_NOT_FOUND;
+
for (i = 0; i < haystack_size; i++) {
if (haystack[i] == NULL) /* previously removed. */
continue;
@@ -1577,9 +1636,11 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,
if (!logical_drive->offload_config)
continue;
for (j = 0; j < ndevices; j++) {
+ if (dev[j] == NULL)
+ continue;
if (dev[j]->devtype != TYPE_DISK)
continue;
- if (is_logical_dev_addr_mode(dev[j]->scsi3addr))
+ if (is_logical_device(dev[j]))
continue;
if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle)
continue;
@@ -1620,9 +1681,11 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
int i;
for (i = 0; i < ndevices; i++) {
+ if (dev[i] == NULL)
+ continue;
if (dev[i]->devtype != TYPE_DISK)
continue;
- if (!is_logical_dev_addr_mode(dev[i]->scsi3addr))
+ if (!is_logical_device(dev[i]))
continue;
/*
@@ -1638,7 +1701,50 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
}
}
-static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
+static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
+{
+ int rc = 0;
+
+ if (!h->scsi_host)
+ return 1;
+
+ if (is_logical_device(device)) /* RAID */
+ rc = scsi_add_device(h->scsi_host, device->bus,
+ device->target, device->lun);
+ else /* HBA */
+ rc = hpsa_add_sas_device(h->sas_host, device);
+
+ return rc;
+}
+
+static void hpsa_remove_device(struct ctlr_info *h,
+ struct hpsa_scsi_dev_t *device)
+{
+ struct scsi_device *sdev = NULL;
+
+ if (!h->scsi_host)
+ return;
+
+ if (is_logical_device(device)) { /* RAID */
+ sdev = scsi_device_lookup(h->scsi_host, device->bus,
+ device->target, device->lun);
+ if (sdev) {
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ } else {
+ /*
+ * We don't expect to get here. Future commands
+ * to this device will get a selection timeout as
+ * if the device were gone.
+ */
+ hpsa_show_dev_msg(KERN_WARNING, h, device,
+ "didn't find device for removal.");
+ }
+ } else /* HBA */
+ hpsa_remove_sas_device(device);
+}
+
+static void adjust_hpsa_scsi_table(struct ctlr_info *h,
struct hpsa_scsi_dev_t *sd[], int nsds)
{
/* sd contains scsi3 addresses and devtypes, and inquiry
@@ -1650,7 +1756,15 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
unsigned long flags;
struct hpsa_scsi_dev_t **added, **removed;
int nadded, nremoved;
- struct Scsi_Host *sh = NULL;
+
+ /*
+ * A reset can cause a device status to change
+ * re-schedule the scan to see what happened.
+ */
+ if (h->reset_in_progress) {
+ h->drv_req_rescan = 1;
+ return;
+ }
added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL);
removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL);
@@ -1678,19 +1792,18 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry);
if (device_change == DEVICE_NOT_FOUND) {
changes++;
- hpsa_scsi_remove_entry(h, hostno, i,
- removed, &nremoved);
+ hpsa_scsi_remove_entry(h, i, removed, &nremoved);
continue; /* remove ^^^, hence i not incremented */
} else if (device_change == DEVICE_CHANGED) {
changes++;
- hpsa_scsi_replace_entry(h, hostno, i, sd[entry],
+ hpsa_scsi_replace_entry(h, i, sd[entry],
added, &nadded, removed, &nremoved);
/* Set it to NULL to prevent it from being freed
* at the bottom of hpsa_update_scsi_devices()
*/
sd[entry] = NULL;
} else if (device_change == DEVICE_UPDATED) {
- hpsa_scsi_update_entry(h, hostno, i, sd[entry]);
+ hpsa_scsi_update_entry(h, i, sd[entry]);
}
i++;
}
@@ -1718,8 +1831,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
h->ndevices, &entry);
if (device_change == DEVICE_NOT_FOUND) {
changes++;
- if (hpsa_scsi_add_entry(h, hostno, sd[i],
- added, &nadded) != 0)
+ if (hpsa_scsi_add_entry(h, sd[i], added, &nadded) != 0)
break;
sd[i] = NULL; /* prevent from being freed later. */
} else if (device_change == DEVICE_CHANGED) {
@@ -1735,8 +1847,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
/* Now that h->dev[]->phys_disk[] is coherent, we can enable
* any logical drives that need it enabled.
*/
- for (i = 0; i < h->ndevices; i++)
+ for (i = 0; i < h->ndevices; i++) {
+ if (h->dev[i] == NULL)
+ continue;
h->dev[i]->offload_enabled = h->dev[i]->offload_to_be_enabled;
+ }
spin_unlock_irqrestore(&h->devlock, flags);
@@ -1755,47 +1870,37 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
* (or if there are no changes) scsi_scan_host will do it later the
* first time through.
*/
- if (hostno == -1 || !changes)
+ if (!changes)
goto free_and_out;
- sh = h->scsi_host;
/* Notify scsi mid layer of any removed devices */
for (i = 0; i < nremoved; i++) {
- if (removed[i]->expose_state & HPSA_SCSI_ADD) {
- struct scsi_device *sdev =
- scsi_device_lookup(sh, removed[i]->bus,
- removed[i]->target, removed[i]->lun);
- if (sdev != NULL) {
- scsi_remove_device(sdev);
- scsi_device_put(sdev);
- } else {
- /*
- * We don't expect to get here.
- * future cmds to this device will get selection
- * timeout as if the device was gone.
- */
- hpsa_show_dev_msg(KERN_WARNING, h, removed[i],
- "didn't find device for removal.");
- }
- }
+ if (removed[i] == NULL)
+ continue;
+ if (removed[i]->expose_device)
+ hpsa_remove_device(h, removed[i]);
kfree(removed[i]);
removed[i] = NULL;
}
/* Notify scsi mid layer of any added devices */
for (i = 0; i < nadded; i++) {
- if (!(added[i]->expose_state & HPSA_SCSI_ADD))
+ int rc = 0;
+
+ if (added[i] == NULL)
+ continue;
+ if (!(added[i]->expose_device))
continue;
- if (scsi_add_device(sh, added[i]->bus,
- added[i]->target, added[i]->lun) == 0)
+ rc = hpsa_add_device(h, added[i]);
+ if (!rc)
continue;
- hpsa_show_dev_msg(KERN_WARNING, h, added[i],
- "addition failed, device not added.");
+ dev_warn(&h->pdev->dev,
+ "addition failed %d, device not added.", rc);
/* now we have to remove it from h->dev,
* since it didn't get added to scsi mid layer
*/
fixup_botched_add(h, added[i]);
- added[i] = NULL;
+ h->drv_req_rescan = 1;
}
free_and_out:
@@ -1829,11 +1934,24 @@ static int hpsa_slave_alloc(struct scsi_device *sdev)
h = sdev_to_hba(sdev);
spin_lock_irqsave(&h->devlock, flags);
- sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
- sdev_id(sdev), sdev->lun);
- if (likely(sd)) {
+ if (sdev_channel(sdev) == HPSA_PHYSICAL_DEVICE_BUS) {
+ struct scsi_target *starget;
+ struct sas_rphy *rphy;
+
+ starget = scsi_target(sdev);
+ rphy = target_to_rphy(starget);
+ sd = hpsa_find_device_by_sas_rphy(h, rphy);
+ if (sd) {
+ sd->target = sdev_id(sdev);
+ sd->lun = sdev->lun;
+ }
+ } else
+ sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
+ sdev_id(sdev), sdev->lun);
+
+ if (sd && sd->expose_device) {
atomic_set(&sd->ioaccel_cmds_out, 0);
- sdev->hostdata = (sd->expose_state & HPSA_SCSI_ADD) ? sd : NULL;
+ sdev->hostdata = sd;
} else
sdev->hostdata = NULL;
spin_unlock_irqrestore(&h->devlock, flags);
@@ -1847,7 +1965,7 @@ static int hpsa_slave_configure(struct scsi_device *sdev)
int queue_depth;
sd = sdev->hostdata;
- sdev->no_uld_attach = !sd || !(sd->expose_state & HPSA_ULD_ATTACH);
+ sdev->no_uld_attach = !sd || !sd->expose_device;
if (sd)
queue_depth = sd->queue_depth != 0 ?
@@ -1955,7 +2073,7 @@ static int hpsa_map_ioaccel2_sg_chain_block(struct ctlr_info *h,
u32 chain_size;
chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex];
- chain_size = le32_to_cpu(cp->data_len);
+ chain_size = le32_to_cpu(cp->sg[0].length);
temp64 = pci_map_single(h->pdev, chain_block, chain_size,
PCI_DMA_TODEVICE);
if (dma_mapping_error(&h->pdev->dev, temp64)) {
@@ -1976,7 +2094,7 @@ static void hpsa_unmap_ioaccel2_sg_chain_block(struct ctlr_info *h,
chain_sg = cp->sg;
temp64 = le64_to_cpu(chain_sg->address);
- chain_size = le32_to_cpu(cp->data_len);
+ chain_size = le32_to_cpu(cp->sg[0].length);
pci_unmap_single(h->pdev, temp64, chain_size, PCI_DMA_TODEVICE);
}
@@ -2210,7 +2328,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
* the normal I/O path so the controller can handle whatever's
* wrong.
*/
- if (is_logical_dev_addr_mode(dev->scsi3addr) &&
+ if (is_logical_device(dev) &&
c2->error_data.serv_response ==
IOACCEL2_SERV_RESPONSE_FAILURE) {
if (c2->error_data.status ==
@@ -2330,7 +2448,7 @@ static void complete_scsi_command(struct CommandList *cp)
* the normal I/O path so the controller can handle whatever's
* wrong.
*/
- if (is_logical_dev_addr_mode(dev->scsi3addr)) {
+ if (is_logical_device(dev)) {
if (ei->CommandStatus == CMD_IOACCEL_DISABLED)
dev->offload_enabled = 0;
return hpsa_retry_cmd(h, cp);
@@ -2709,9 +2827,8 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
/* fill_cmd can't fail here, no data buffer to map. */
- (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
+ (void) fill_cmd(c, reset_type, h, NULL, 0, 0,
scsi3addr, TYPE_MSG);
- c->Request.CDB[1] = reset_type; /* fill_cmd defaults to LUN reset */
rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT);
if (rc) {
dev_warn(&h->pdev->dev, "Failed to send reset command\n");
@@ -2984,6 +3101,66 @@ out:
return rc;
}
+static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h,
+ unsigned char scsi3addr[], u16 bmic_device_index,
+ struct bmic_sense_subsystem_info *buf, size_t bufsize)
+{
+ int rc = IO_OK;
+ struct CommandList *c;
+ struct ErrorInfo *ei;
+
+ c = cmd_alloc(h);
+
+ rc = fill_cmd(c, BMIC_SENSE_SUBSYSTEM_INFORMATION, h, buf, bufsize,
+ 0, RAID_CTLR_LUNID, TYPE_CMD);
+ if (rc)
+ goto out;
+
+ c->Request.CDB[2] = bmic_device_index & 0xff;
+ c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff;
+
+ rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+ PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+ if (rc)
+ goto out;
+ ei = c->err_info;
+ if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+ hpsa_scsi_interpret_error(h, c);
+ rc = -1;
+ }
+out:
+ cmd_free(h, c);
+ return rc;
+}
+
+static int hpsa_bmic_id_controller(struct ctlr_info *h,
+ struct bmic_identify_controller *buf, size_t bufsize)
+{
+ int rc = IO_OK;
+ struct CommandList *c;
+ struct ErrorInfo *ei;
+
+ c = cmd_alloc(h);
+
+ rc = fill_cmd(c, BMIC_IDENTIFY_CONTROLLER, h, buf, bufsize,
+ 0, RAID_CTLR_LUNID, TYPE_CMD);
+ if (rc)
+ goto out;
+
+ rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+ PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+ if (rc)
+ goto out;
+ ei = c->err_info;
+ if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+ hpsa_scsi_interpret_error(h, c);
+ rc = -1;
+ }
+out:
+ cmd_free(h, c);
+ return rc;
+}
+
static int hpsa_bmic_id_physical_device(struct ctlr_info *h,
unsigned char scsi3addr[], u16 bmic_device_index,
struct bmic_identify_physical_device *buf, size_t bufsize)
@@ -3010,9 +3187,71 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h,
}
out:
cmd_free(h, c);
+
return rc;
}
+static u64 hpsa_get_sas_address_from_report_physical(struct ctlr_info *h,
+ unsigned char *scsi3addr)
+{
+ struct ReportExtendedLUNdata *physdev;
+ u32 nphysicals;
+ u64 sa = 0;
+ int i;
+
+ physdev = kzalloc(sizeof(*physdev), GFP_KERNEL);
+ if (!physdev)
+ return 0;
+
+ if (hpsa_scsi_do_report_phys_luns(h, physdev, sizeof(*physdev))) {
+ dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
+ kfree(physdev);
+ return 0;
+ }
+ nphysicals = get_unaligned_be32(physdev->LUNListLength) / 24;
+
+ for (i = 0; i < nphysicals; i++)
+ if (!memcmp(&physdev->LUN[i].lunid[0], scsi3addr, 8)) {
+ sa = get_unaligned_be64(&physdev->LUN[i].wwid[0]);
+ break;
+ }
+
+ kfree(physdev);
+
+ return sa;
+}
+
+static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr,
+ struct hpsa_scsi_dev_t *dev)
+{
+ int rc;
+ u64 sa = 0;
+
+ if (is_hba_lunid(scsi3addr)) {
+ struct bmic_sense_subsystem_info *ssi;
+
+ ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
+ if (ssi == NULL) {
+ dev_warn(&h->pdev->dev,
+ "%s: out of memory\n", __func__);
+ return;
+ }
+
+ rc = hpsa_bmic_sense_subsystem_information(h,
+ scsi3addr, 0, ssi, sizeof(*ssi));
+ if (rc == 0) {
+ sa = get_unaligned_be64(ssi->primary_world_wide_id);
+ h->sas_address = sa;
+ }
+
+ kfree(ssi);
+ } else
+ sa = hpsa_get_sas_address_from_report_physical(h, scsi3addr);
+
+ dev->sas_address = sa;
+}
+
+/* Get a device id from inquiry page 0x83 */
static int hpsa_vpd_page_supported(struct ctlr_info *h,
unsigned char scsi3addr[], u8 page)
{
@@ -3097,7 +3336,7 @@ out:
/* Get the device id from inquiry page 0x83 */
static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
- unsigned char *device_id, int buflen)
+ unsigned char *device_id, int index, int buflen)
{
int rc;
unsigned char *buf;
@@ -3109,8 +3348,10 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
return -ENOMEM;
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64);
if (rc == 0)
- memcpy(device_id, &buf[8], buflen);
+ memcpy(device_id, &buf[index], buflen);
+
kfree(buf);
+
return rc != 0;
}
@@ -3339,6 +3580,18 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h,
return rc;
}
+static void sanitize_inquiry_string(unsigned char *s, int len)
+{
+ bool terminated = false;
+
+ for (; len > 0; (--len, ++s)) {
+ if (*s == 0)
+ terminated = true;
+ if (terminated || *s < 0x20 || *s > 0x7e)
+ *s = ' ';
+ }
+}
+
static int hpsa_update_device_info(struct ctlr_info *h,
unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
unsigned char *is_OBDR_device)
@@ -3351,10 +3604,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,
unsigned char *inq_buff;
unsigned char *obdr_sig;
+ int rc = 0;
inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
- if (!inq_buff)
+ if (!inq_buff) {
+ rc = -ENOMEM;
goto bail_out;
+ }
/* Do an inquiry to the device to see what it is. */
if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
@@ -3362,9 +3618,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,
/* Inquiry failed (msg printed already) */
dev_err(&h->pdev->dev,
"hpsa_update_device_info: inquiry failed\n");
+ rc = -EIO;
goto bail_out;
}
+ sanitize_inquiry_string(&inq_buff[8], 8);
+ sanitize_inquiry_string(&inq_buff[16], 16);
+
this_device->devtype = (inq_buff[0] & 0x1f);
memcpy(this_device->scsi3addr, scsi3addr, 8);
memcpy(this_device->vendor, &inq_buff[8],
@@ -3373,7 +3633,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,
sizeof(this_device->model));
memset(this_device->device_id, 0,
sizeof(this_device->device_id));
- hpsa_get_device_id(h, scsi3addr, this_device->device_id,
+ hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
sizeof(this_device->device_id));
if (this_device->devtype == TYPE_DISK &&
@@ -3411,7 +3671,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,
bail_out:
kfree(inq_buff);
- return 1;
+ return rc;
}
static void hpsa_update_device_supports_aborts(struct ctlr_info *h,
@@ -3439,115 +3699,39 @@ static void hpsa_update_device_supports_aborts(struct ctlr_info *h,
}
}
-static unsigned char *ext_target_model[] = {
- "MSA2012",
- "MSA2024",
- "MSA2312",
- "MSA2324",
- "P2000 G3 SAS",
- "MSA 2040 SAS",
- NULL,
-};
-
-static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
-{
- int i;
-
- for (i = 0; ext_target_model[i]; i++)
- if (strncmp(device->model, ext_target_model[i],
- strlen(ext_target_model[i])) == 0)
- return 1;
- return 0;
-}
-
-/* Helper function to assign bus, target, lun mapping of devices.
- * Puts non-external target logical volumes on bus 0, external target logical
- * volumes on bus 1, physical devices on bus 2. and the hba on bus 3.
+/*
+ * Helper function to assign bus, target, lun mapping of devices.
* Logical drive target and lun are assigned at this time, but
* physical device lun and target assignment are deferred (assigned
* in hpsa_find_target_lun, called by hpsa_scsi_add_entry.)
- */
+*/
static void figure_bus_target_lun(struct ctlr_info *h,
u8 *lunaddrbytes, struct hpsa_scsi_dev_t *device)
{
- u32 lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
+ u32 lunid = get_unaligned_le32(lunaddrbytes);
if (!is_logical_dev_addr_mode(lunaddrbytes)) {
/* physical device, target and lun filled in later */
if (is_hba_lunid(lunaddrbytes))
- hpsa_set_bus_target_lun(device, 3, 0, lunid & 0x3fff);
+ hpsa_set_bus_target_lun(device,
+ HPSA_HBA_BUS, 0, lunid & 0x3fff);
else
/* defer target, lun assignment for physical devices */
- hpsa_set_bus_target_lun(device, 2, -1, -1);
+ hpsa_set_bus_target_lun(device,
+ HPSA_PHYSICAL_DEVICE_BUS, -1, -1);
return;
}
/* It's a logical device */
- if (is_ext_target(h, device)) {
- /* external target way, put logicals on bus 1
- * and match target/lun numbers box
- * reports, other smart array, bus 0, target 0, match lunid
- */
+ if (device->external) {
hpsa_set_bus_target_lun(device,
- 1, (lunid >> 16) & 0x3fff, lunid & 0x00ff);
+ HPSA_EXTERNAL_RAID_VOLUME_BUS, (lunid >> 16) & 0x3fff,
+ lunid & 0x00ff);
return;
}
- hpsa_set_bus_target_lun(device, 0, 0, lunid & 0x3fff);
+ hpsa_set_bus_target_lun(device, HPSA_RAID_VOLUME_BUS,
+ 0, lunid & 0x3fff);
}
-/*
- * If there is no lun 0 on a target, linux won't find any devices.
- * For the external targets (arrays), we have to manually detect the enclosure
- * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report
- * it for some reason. *tmpdevice is the target we're adding,
- * this_device is a pointer into the current element of currentsd[]
- * that we're building up in update_scsi_devices(), below.
- * lunzerobits is a bitmap that tracks which targets already have a
- * lun 0 assigned.
- * Returns 1 if an enclosure was added, 0 if not.
- */
-static int add_ext_target_dev(struct ctlr_info *h,
- struct hpsa_scsi_dev_t *tmpdevice,
- struct hpsa_scsi_dev_t *this_device, u8 *lunaddrbytes,
- unsigned long lunzerobits[], int *n_ext_target_devs)
-{
- unsigned char scsi3addr[8];
-
- if (test_bit(tmpdevice->target, lunzerobits))
- return 0; /* There is already a lun 0 on this target. */
-
- if (!is_logical_dev_addr_mode(lunaddrbytes))
- return 0; /* It's the logical targets that may lack lun 0. */
-
- if (!is_ext_target(h, tmpdevice))
- return 0; /* Only external target devices have this problem. */
-
- if (tmpdevice->lun == 0) /* if lun is 0, then we have a lun 0. */
- return 0;
-
- memset(scsi3addr, 0, 8);
- scsi3addr[3] = tmpdevice->target;
- if (is_hba_lunid(scsi3addr))
- return 0; /* Don't add the RAID controller here. */
-
- if (is_scsi_rev_5(h))
- return 0; /* p1210m doesn't need to do this. */
-
- if (*n_ext_target_devs >= MAX_EXT_TARGETS) {
- dev_warn(&h->pdev->dev, "Maximum number of external "
- "target devices exceeded. Check your hardware "
- "configuration.");
- return 0;
- }
-
- if (hpsa_update_device_info(h, scsi3addr, this_device, NULL))
- return 0;
- (*n_ext_target_devs)++;
- hpsa_set_bus_target_lun(this_device,
- tmpdevice->bus, tmpdevice->target, 0);
- hpsa_update_device_supports_aborts(h, this_device, scsi3addr);
- set_bit(tmpdevice->target, lunzerobits);
- return 1;
-}
/*
* Get address of physical disk used for an ioaccel2 mode command:
@@ -3577,6 +3761,27 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
return 0;
}
+static int figure_external_status(struct ctlr_info *h, int raid_ctlr_position,
+ int i, int nphysicals, int nlocal_logicals)
+{
+ /* In report logicals, local logicals are listed first,
+ * then any externals.
+ */
+ int logicals_start = nphysicals + (raid_ctlr_position == 0);
+
+ if (i == raid_ctlr_position)
+ return 0;
+
+ if (i < logicals_start)
+ return 0;
+
+ /* i is in logicals range, but still within local logicals */
+ if ((i - nphysicals - (raid_ctlr_position == 0)) < nlocal_logicals)
+ return 0;
+
+ return 1; /* it's an external lun */
+}
+
/*
* Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev,
* logdev. The number of luns in physdev and logdev are returned in
@@ -3650,19 +3855,18 @@ static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position,
/* get physical drive ioaccel handle and queue depth */
static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
struct hpsa_scsi_dev_t *dev,
- u8 *lunaddrbytes,
+ struct ReportExtendedLUNdata *rlep, int rle_index,
struct bmic_identify_physical_device *id_phys)
{
int rc;
- struct ext_report_lun_entry *rle =
- (struct ext_report_lun_entry *) lunaddrbytes;
+ struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
dev->ioaccel_handle = rle->ioaccel_handle;
- if (PHYS_IOACCEL(lunaddrbytes) && dev->ioaccel_handle)
+ if ((rle->device_flags & 0x08) && dev->ioaccel_handle)
dev->hba_ioaccel_enabled = 1;
memset(id_phys, 0, sizeof(*id_phys));
- rc = hpsa_bmic_id_physical_device(h, lunaddrbytes,
- GET_BMIC_DRIVE_NUMBER(lunaddrbytes), id_phys,
+ rc = hpsa_bmic_id_physical_device(h, &rle->lunid[0],
+ GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]), id_phys,
sizeof(*id_phys));
if (!rc)
/* Reserve space for FW operations */
@@ -3673,16 +3877,15 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
DRIVE_CMDS_RESERVED_FOR_FW;
else
dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */
- atomic_set(&dev->ioaccel_cmds_out, 0);
- atomic_set(&dev->reset_cmds_out, 0);
}
static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device,
- u8 *lunaddrbytes,
+ struct ReportExtendedLUNdata *rlep, int rle_index,
struct bmic_identify_physical_device *id_phys)
{
- if (PHYS_IOACCEL(lunaddrbytes)
- && this_device->ioaccel_handle)
+ struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
+
+ if ((rle->device_flags & 0x08) && this_device->ioaccel_handle)
this_device->hba_ioaccel_enabled = 1;
memcpy(&this_device->active_path_index,
@@ -3702,7 +3905,33 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device,
sizeof(this_device->bay));
}
-static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
+/* get number of local logical disks. */
+static int hpsa_set_local_logical_count(struct ctlr_info *h,
+ struct bmic_identify_controller *id_ctlr,
+ u32 *nlocals)
+{
+ int rc;
+
+ if (!id_ctlr) {
+ dev_warn(&h->pdev->dev, "%s: id_ctlr buffer is NULL.\n",
+ __func__);
+ return -ENOMEM;
+ }
+ memset(id_ctlr, 0, sizeof(*id_ctlr));
+ rc = hpsa_bmic_id_controller(h, id_ctlr, sizeof(*id_ctlr));
+ if (!rc)
+ if (id_ctlr->configured_logical_drive_count < 256)
+ *nlocals = id_ctlr->configured_logical_drive_count;
+ else
+ *nlocals = le16_to_cpu(
+ id_ctlr->extended_logical_unit_count);
+ else
+ *nlocals = -1;
+ return rc;
+}
+
+
+static void hpsa_update_scsi_devices(struct ctlr_info *h)
{
/* the idea here is we could get notified
* that some devices have changed, so we do a report
@@ -3717,13 +3946,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
struct ReportExtendedLUNdata *physdev_list = NULL;
struct ReportLUNdata *logdev_list = NULL;
struct bmic_identify_physical_device *id_phys = NULL;
+ struct bmic_identify_controller *id_ctlr = NULL;
u32 nphysicals = 0;
u32 nlogicals = 0;
+ u32 nlocal_logicals = 0;
u32 ndev_allocated = 0;
struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
int ncurrent = 0;
int i, n_ext_target_devs, ndevs_to_allocate;
int raid_ctlr_position;
+ bool physical_device;
DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
@@ -3731,17 +3963,29 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL);
tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL);
+ id_ctlr = kzalloc(sizeof(*id_ctlr), GFP_KERNEL);
if (!currentsd || !physdev_list || !logdev_list ||
- !tmpdevice || !id_phys) {
+ !tmpdevice || !id_phys || !id_ctlr) {
dev_err(&h->pdev->dev, "out of memory\n");
goto out;
}
memset(lunzerobits, 0, sizeof(lunzerobits));
+ h->drv_req_rescan = 0; /* cancel scheduled rescan - we're doing it. */
+
if (hpsa_gather_lun_info(h, physdev_list, &nphysicals,
- logdev_list, &nlogicals))
+ logdev_list, &nlogicals)) {
+ h->drv_req_rescan = 1;
goto out;
+ }
+
+ /* Set number of local logicals (non PTRAID) */
+ if (hpsa_set_local_logical_count(h, id_ctlr, &nlocal_logicals)) {
+ dev_warn(&h->pdev->dev,
+ "%s: Can't determine number of local logical devices.\n",
+ __func__);
+ }
/* We might see up to the maximum number of logical and physical disks
* plus external target devices, and a device for the local RAID
@@ -3762,6 +4006,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
if (!currentsd[i]) {
dev_warn(&h->pdev->dev, "out of memory at %s:%d\n",
__FILE__, __LINE__);
+ h->drv_req_rescan = 1;
goto out;
}
ndev_allocated++;
@@ -3776,49 +4021,74 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
n_ext_target_devs = 0;
for (i = 0; i < nphysicals + nlogicals + 1; i++) {
u8 *lunaddrbytes, is_OBDR = 0;
+ int rc = 0;
+ int phys_dev_index = i - (raid_ctlr_position == 0);
+
+ physical_device = i < nphysicals + (raid_ctlr_position == 0);
/* Figure out where the LUN ID info is coming from */
lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
i, nphysicals, nlogicals, physdev_list, logdev_list);
/* skip masked non-disk devices */
- if (MASKED_DEVICE(lunaddrbytes))
- if (i < nphysicals + (raid_ctlr_position == 0) &&
- NON_DISK_PHYS_DEV(lunaddrbytes))
- continue;
+ if (MASKED_DEVICE(lunaddrbytes) && physical_device &&
+ (physdev_list->LUN[phys_dev_index].device_flags & 0x01))
+ continue;
/* Get device type, vendor, model, device id */
- if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
- &is_OBDR))
- continue; /* skip it if we can't talk to it. */
+ rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
+ &is_OBDR);
+ if (rc == -ENOMEM) {
+ dev_warn(&h->pdev->dev,
+ "Out of memory, rescan deferred.\n");
+ h->drv_req_rescan = 1;
+ goto out;
+ }
+ if (rc) {
+ dev_warn(&h->pdev->dev,
+ "Inquiry failed, skipping device.\n");
+ continue;
+ }
+
+ /* Determine if this is a lun from an external target array */
+ tmpdevice->external =
+ figure_external_status(h, raid_ctlr_position, i,
+ nphysicals, nlocal_logicals);
+
figure_bus_target_lun(h, lunaddrbytes, tmpdevice);
hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes);
this_device = currentsd[ncurrent];
- /*
- * For external target devices, we have to insert a LUN 0 which
- * doesn't show up in CCISS_REPORT_PHYSICAL data, but there
- * is nonetheless an enclosure device there. We have to
- * present that otherwise linux won't find anything if
- * there is no lun 0.
+ /* Turn on discovery_polling if there are ext target devices.
+ * Event-based change notification is unreliable for those.
*/
- if (add_ext_target_dev(h, tmpdevice, this_device,
- lunaddrbytes, lunzerobits,
- &n_ext_target_devs)) {
- ncurrent++;
- this_device = currentsd[ncurrent];
+ if (!h->discovery_polling) {
+ if (tmpdevice->external) {
+ h->discovery_polling = 1;
+ dev_info(&h->pdev->dev,
+ "External target, activate discovery polling.\n");
+ }
}
+
*this_device = *tmpdevice;
+ this_device->physical_device = physical_device;
+
+ /*
+ * Expose all devices except for physical devices that
+ * are masked.
+ */
+ if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device)
+ this_device->expose_device = 0;
+ else
+ this_device->expose_device = 1;
- /* do not expose masked devices */
- if (MASKED_DEVICE(lunaddrbytes) &&
- i < nphysicals + (raid_ctlr_position == 0)) {
- this_device->expose_state = HPSA_DO_NOT_EXPOSE;
- } else {
- this_device->expose_state =
- HPSA_SG_ATTACH | HPSA_ULD_ATTACH;
- }
+
+ /*
+ * Get the SAS address for physical devices that are exposed.
+ */
+ if (this_device->physical_device && this_device->expose_device)
+ hpsa_get_sas_address(h, lunaddrbytes, this_device);
switch (this_device->devtype) {
case TYPE_ROM:
@@ -3833,14 +4103,14 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
ncurrent++;
break;
case TYPE_DISK:
- if (i < nphysicals + (raid_ctlr_position == 0)) {
+ if (this_device->physical_device) {
/* The disk is in HBA mode. */
/* Never use RAID mapper in HBA mode. */
this_device->offload_enabled = 0;
hpsa_get_ioaccel_drive_info(h, this_device,
- lunaddrbytes, id_phys);
- hpsa_get_path_info(this_device, lunaddrbytes,
- id_phys);
+ physdev_list, phys_dev_index, id_phys);
+ hpsa_get_path_info(this_device,
+ physdev_list, phys_dev_index, id_phys);
}
ncurrent++;
break;
@@ -3865,7 +4135,19 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
if (ncurrent >= HPSA_MAX_DEVICES)
break;
}
- adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent);
+
+ if (h->sas_host == NULL) {
+ int rc = 0;
+
+ rc = hpsa_add_sas_host(h);
+ if (rc) {
+ dev_warn(&h->pdev->dev,
+ "Could not add sas host %d\n", rc);
+ goto out;
+ }
+ }
+
+ adjust_hpsa_scsi_table(h, currentsd, ncurrent);
out:
kfree(tmpdevice);
for (i = 0; i < ndev_allocated; i++)
@@ -3873,6 +4155,7 @@ out:
kfree(currentsd);
kfree(physdev_list);
kfree(logdev_list);
+ kfree(id_ctlr);
kfree(id_phys);
}
@@ -3978,19 +4261,14 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)
case READ_6:
case READ_12:
if (*cdb_len == 6) {
- block = (((u32) cdb[2]) << 8) | cdb[3];
+ block = get_unaligned_be16(&cdb[2]);
block_cnt = cdb[4];
+ if (block_cnt == 0)
+ block_cnt = 256;
} else {
BUG_ON(*cdb_len != 12);
- block = (((u32) cdb[2]) << 24) |
- (((u32) cdb[3]) << 16) |
- (((u32) cdb[4]) << 8) |
- cdb[5];
- block_cnt =
- (((u32) cdb[6]) << 24) |
- (((u32) cdb[7]) << 16) |
- (((u32) cdb[8]) << 8) |
- cdb[9];
+ block = get_unaligned_be32(&cdb[2]);
+ block_cnt = get_unaligned_be32(&cdb[6]);
}
if (block_cnt > 0xffff)
return IO_ACCEL_INELIGIBLE;
@@ -4272,6 +4550,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
/* fill in sg elements */
if (use_sg > h->ioaccel_maxsg) {
cp->sg_count = 1;
+ cp->sg[0].length = cpu_to_le32(use_sg * sizeof(cp->sg[0]));
if (hpsa_map_ioaccel2_sg_chain_block(h, cp, c)) {
atomic_dec(&phys_disk->ioaccel_cmds_out);
scsi_dma_unmap(cmd);
@@ -4376,9 +4655,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
case WRITE_6:
is_write = 1;
case READ_6:
- first_block =
- (((u64) cmd->cmnd[2]) << 8) |
- cmd->cmnd[3];
+ first_block = get_unaligned_be16(&cmd->cmnd[2]);
block_cnt = cmd->cmnd[4];
if (block_cnt == 0)
block_cnt = 256;
@@ -4947,7 +5224,7 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
if (unlikely(lockup_detected(h)))
return hpsa_scan_complete(h);
- hpsa_update_scsi_devices(h, h->scsi_host->host_no);
+ hpsa_update_scsi_devices(h);
hpsa_scan_complete(h);
}
@@ -4983,7 +5260,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh,
static int hpsa_scsi_host_alloc(struct ctlr_info *h)
{
struct Scsi_Host *sh;
- int error;
sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
if (sh == NULL) {
@@ -5001,17 +5277,11 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
sh->can_queue = h->nr_cmds - HPSA_NRESERVED_CMDS;
sh->cmd_per_lun = sh->can_queue;
sh->sg_tablesize = h->maxsgentries;
+ sh->transportt = hpsa_sas_transport_template;
sh->hostdata[0] = (unsigned long) h;
sh->irq = h->intr[h->intr_mode];
sh->unique_id = sh->irq;
- error = scsi_init_shared_tag_map(sh, sh->can_queue);
- if (error) {
- dev_err(&h->pdev->dev,
- "%s: scsi_init_shared_tag_map failed for controller %d\n",
- __func__, h->ctlr);
- scsi_host_put(sh);
- return error;
- }
+
h->scsi_host = sh;
return 0;
}
@@ -5167,6 +5437,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
int rc;
struct ctlr_info *h;
struct hpsa_scsi_dev_t *dev;
+ u8 reset_type;
char msg[48];
/* find the controller to which the command to be aborted was sent */
@@ -5205,14 +5476,25 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
if (is_hba_lunid(dev->scsi3addr))
return SUCCESS;
- hpsa_show_dev_msg(KERN_WARNING, h, dev, "resetting");
+ if (is_logical_dev_addr_mode(dev->scsi3addr))
+ reset_type = HPSA_DEVICE_RESET_MSG;
+ else
+ reset_type = HPSA_PHYS_TARGET_RESET;
+
+ sprintf(msg, "resetting %s",
+ reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical ");
+ hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
+
+ h->reset_in_progress = 1;
/* send a reset to the SCSI LUN which the command was sent to */
- rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN,
+ rc = hpsa_do_reset(h, dev, dev->scsi3addr, reset_type,
DEFAULT_REPLY_QUEUE);
- snprintf(msg, sizeof(msg), "reset %s",
- rc == 0 ? "completed successfully" : "failed");
+ sprintf(msg, "reset %s %s",
+ reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical ",
+ rc == 0 ? "completed successfully" : "failed");
hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
+ h->reset_in_progress = 0;
return rc == 0 ? SUCCESS : FAILED;
}
@@ -6270,6 +6552,24 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.CDB[8] = (size >> 8) & 0xFF;
c->Request.CDB[9] = size & 0xFF;
break;
+ case BMIC_SENSE_DIAG_OPTIONS:
+ c->Request.CDBLen = 16;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+ c->Request.Timeout = 0;
+ /* Spec says this should be BMIC_WRITE */
+ c->Request.CDB[0] = BMIC_READ;
+ c->Request.CDB[6] = BMIC_SENSE_DIAG_OPTIONS;
+ break;
+ case BMIC_SET_DIAG_OPTIONS:
+ c->Request.CDBLen = 16;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type,
+ ATTR_SIMPLE, XFER_WRITE);
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = BMIC_WRITE;
+ c->Request.CDB[6] = BMIC_SET_DIAG_OPTIONS;
+ break;
case HPSA_CACHE_FLUSH:
c->Request.CDBLen = 12;
c->Request.type_attr_dir =
@@ -6319,6 +6619,32 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.CDB[7] = (size >> 16) & 0xFF;
c->Request.CDB[8] = (size >> 8) & 0XFF;
break;
+ case BMIC_SENSE_SUBSYSTEM_INFORMATION:
+ c->Request.CDBLen = 10;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = BMIC_READ;
+ c->Request.CDB[6] = BMIC_SENSE_SUBSYSTEM_INFORMATION;
+ c->Request.CDB[7] = (size >> 16) & 0xFF;
+ c->Request.CDB[8] = (size >> 8) & 0XFF;
+ break;
+ case BMIC_IDENTIFY_CONTROLLER:
+ c->Request.CDBLen = 10;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = BMIC_READ;
+ c->Request.CDB[1] = 0;
+ c->Request.CDB[2] = 0;
+ c->Request.CDB[3] = 0;
+ c->Request.CDB[4] = 0;
+ c->Request.CDB[5] = 0;
+ c->Request.CDB[6] = BMIC_IDENTIFY_CONTROLLER;
+ c->Request.CDB[7] = (size >> 16) & 0xFF;
+ c->Request.CDB[8] = (size >> 8) & 0XFF;
+ c->Request.CDB[9] = 0;
+ break;
default:
dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
BUG();
@@ -6327,6 +6653,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
} else if (cmd_type == TYPE_MSG) {
switch (cmd) {
+ case HPSA_PHYS_TARGET_RESET:
+ c->Request.CDBLen = 16;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
+ c->Request.Timeout = 0; /* Don't time out */
+ memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
+ c->Request.CDB[0] = HPSA_RESET;
+ c->Request.CDB[1] = HPSA_TARGET_RESET_TYPE;
+ /* Physical target reset needs no control bytes 4-7*/
+ c->Request.CDB[4] = 0x00;
+ c->Request.CDB[5] = 0x00;
+ c->Request.CDB[6] = 0x00;
+ c->Request.CDB[7] = 0x00;
+ break;
case HPSA_DEVICE_RESET_MSG:
c->Request.CDBLen = 16;
c->Request.type_attr_dir =
@@ -6440,16 +6780,6 @@ static inline void finish_cmd(struct CommandList *c)
complete(c->waiting);
}
-
-static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag)
-{
-#define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1)
-#define HPSA_SIMPLE_ERROR_BITS 0x03
- if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
- return tag & ~HPSA_SIMPLE_ERROR_BITS;
- return tag & ~HPSA_PERF_ERROR_BITS;
-}
-
/* process completion of an indexed ("direct lookup") command */
static inline void process_indexed_cmd(struct ctlr_info *h,
u32 raw_tag)
@@ -7860,6 +8190,11 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
*/
static int hpsa_ctlr_needs_rescan(struct ctlr_info *h)
{
+ if (h->drv_req_rescan) {
+ h->drv_req_rescan = 0;
+ return 1;
+ }
+
if (!(h->fw_support & MISC_FW_EVENT_NOTIFY))
return 0;
@@ -7893,6 +8228,41 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
return 0;
}
+static int hpsa_luns_changed(struct ctlr_info *h)
+{
+ int rc = 1; /* assume there are changes */
+ struct ReportLUNdata *logdev = NULL;
+
+ /* if we can't find out if lun data has changed,
+ * assume that it has.
+ */
+
+ if (!h->lastlogicals)
+ goto out;
+
+ logdev = kzalloc(sizeof(*logdev), GFP_KERNEL);
+ if (!logdev) {
+ dev_warn(&h->pdev->dev,
+ "Out of memory, can't track lun changes.\n");
+ goto out;
+ }
+ if (hpsa_scsi_do_report_luns(h, 1, logdev, sizeof(*logdev), 0)) {
+ dev_warn(&h->pdev->dev,
+ "report luns failed, can't track lun changes.\n");
+ goto out;
+ }
+ if (memcmp(logdev, h->lastlogicals, sizeof(*logdev))) {
+ dev_info(&h->pdev->dev,
+ "Lun changes detected.\n");
+ memcpy(h->lastlogicals, logdev, sizeof(*logdev));
+ goto out;
+ } else
+ rc = 0; /* no changes detected. */
+out:
+ kfree(logdev);
+ return rc;
+}
+
static void hpsa_rescan_ctlr_worker(struct work_struct *work)
{
unsigned long flags;
@@ -7908,6 +8278,19 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work)
hpsa_ack_ctlr_events(h);
hpsa_scan_start(h->scsi_host);
scsi_host_put(h->scsi_host);
+ } else if (h->discovery_polling) {
+ hpsa_disable_rld_caching(h);
+ if (hpsa_luns_changed(h)) {
+ struct Scsi_Host *sh = NULL;
+
+ dev_info(&h->pdev->dev,
+ "driver discovery polling rescan.\n");
+ sh = scsi_host_get(h->scsi_host);
+ if (sh != NULL) {
+ hpsa_scan_start(sh);
+ scsi_host_put(sh);
+ }
+ }
}
spin_lock_irqsave(&h->lock, flags);
if (!h->remove_in_progress)
@@ -8148,6 +8531,8 @@ reinit_after_soft_reset:
/* Enable Accelerated IO path at driver layer */
h->acciopath_status = 1;
+ /* Disable discovery polling.*/
+ h->discovery_polling = 0;
/* Turn the interrupts on so we can service requests */
@@ -8155,6 +8540,11 @@ reinit_after_soft_reset:
hpsa_hba_inquiry(h);
+ h->lastlogicals = kzalloc(sizeof(*(h->lastlogicals)), GFP_KERNEL);
+ if (!h->lastlogicals)
+ dev_info(&h->pdev->dev,
+ "Can't track change to report lun data\n");
+
/* Monitor the controller for firmware lockups */
h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
@@ -8227,6 +8617,71 @@ out:
kfree(flush_buf);
}
+/* Make controller gather fresh report lun data each time we
+ * send down a report luns request
+ */
+static void hpsa_disable_rld_caching(struct ctlr_info *h)
+{
+ u32 *options;
+ struct CommandList *c;
+ int rc;
+
+ /* Don't bother trying to set diag options if locked up */
+ if (unlikely(h->lockup_detected))
+ return;
+
+ options = kzalloc(sizeof(*options), GFP_KERNEL);
+ if (!options) {
+ dev_err(&h->pdev->dev,
+ "Error: failed to disable rld caching, during alloc.\n");
+ return;
+ }
+
+ c = cmd_alloc(h);
+
+ /* first, get the current diag options settings */
+ if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0,
+ RAID_CTLR_LUNID, TYPE_CMD))
+ goto errout;
+
+ rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+ PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+ if ((rc != 0) || (c->err_info->CommandStatus != 0))
+ goto errout;
+
+ /* Now, set the bit for disabling the RLD caching */
+ *options |= HPSA_DIAG_OPTS_DISABLE_RLD_CACHING;
+
+ if (fill_cmd(c, BMIC_SET_DIAG_OPTIONS, h, options, 4, 0,
+ RAID_CTLR_LUNID, TYPE_CMD))
+ goto errout;
+
+ rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+ PCI_DMA_TODEVICE, NO_TIMEOUT);
+ if ((rc != 0) || (c->err_info->CommandStatus != 0))
+ goto errout;
+
+ /* Now verify that it got set: */
+ if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0,
+ RAID_CTLR_LUNID, TYPE_CMD))
+ goto errout;
+
+ rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+ PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+ if ((rc != 0) || (c->err_info->CommandStatus != 0))
+ goto errout;
+
+ if (*options && HPSA_DIAG_OPTS_DISABLE_RLD_CACHING)
+ goto out;
+
+errout:
+ dev_err(&h->pdev->dev,
+ "Error: failed to disable report lun data caching.\n");
+out:
+ cmd_free(h, c);
+ kfree(options);
+}
+
static void hpsa_shutdown(struct pci_dev *pdev)
{
struct ctlr_info *h;
@@ -8292,6 +8747,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
hpsa_free_performant_mode(h); /* init_one 7 */
hpsa_free_sg_chain_blocks(h); /* init_one 6 */
hpsa_free_cmd_pool(h); /* init_one 5 */
+ kfree(h->lastlogicals);
/* hpsa_free_irqs already called via hpsa_shutdown init_one 4 */
@@ -8304,6 +8760,9 @@ static void hpsa_remove_one(struct pci_dev *pdev)
free_percpu(h->lockup_detected); /* init_one 2 */
h->lockup_detected = NULL; /* init_one 2 */
/* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */
+
+ hpsa_delete_sas_host(h);
+
kfree(h); /* init_one 1 */
}
@@ -8766,18 +9225,369 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h)
} while (1);
}
+static struct hpsa_sas_phy *hpsa_alloc_sas_phy(
+ struct hpsa_sas_port *hpsa_sas_port)
+{
+ struct hpsa_sas_phy *hpsa_sas_phy;
+ struct sas_phy *phy;
+
+ hpsa_sas_phy = kzalloc(sizeof(*hpsa_sas_phy), GFP_KERNEL);
+ if (!hpsa_sas_phy)
+ return NULL;
+
+ phy = sas_phy_alloc(hpsa_sas_port->parent_node->parent_dev,
+ hpsa_sas_port->next_phy_index);
+ if (!phy) {
+ kfree(hpsa_sas_phy);
+ return NULL;
+ }
+
+ hpsa_sas_port->next_phy_index++;
+ hpsa_sas_phy->phy = phy;
+ hpsa_sas_phy->parent_port = hpsa_sas_port;
+
+ return hpsa_sas_phy;
+}
+
+static void hpsa_free_sas_phy(struct hpsa_sas_phy *hpsa_sas_phy)
+{
+ struct sas_phy *phy = hpsa_sas_phy->phy;
+
+ sas_port_delete_phy(hpsa_sas_phy->parent_port->port, phy);
+ sas_phy_free(phy);
+ if (hpsa_sas_phy->added_to_port)
+ list_del(&hpsa_sas_phy->phy_list_entry);
+ kfree(hpsa_sas_phy);
+}
+
+static int hpsa_sas_port_add_phy(struct hpsa_sas_phy *hpsa_sas_phy)
+{
+ int rc;
+ struct hpsa_sas_port *hpsa_sas_port;
+ struct sas_phy *phy;
+ struct sas_identify *identify;
+
+ hpsa_sas_port = hpsa_sas_phy->parent_port;
+ phy = hpsa_sas_phy->phy;
+
+ identify = &phy->identify;
+ memset(identify, 0, sizeof(*identify));
+ identify->sas_address = hpsa_sas_port->sas_address;
+ identify->device_type = SAS_END_DEVICE;
+ identify->initiator_port_protocols = SAS_PROTOCOL_STP;
+ identify->target_port_protocols = SAS_PROTOCOL_STP;
+ phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
+ phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
+ phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN;
+ phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN;
+ phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+
+ rc = sas_phy_add(hpsa_sas_phy->phy);
+ if (rc)
+ return rc;
+
+ sas_port_add_phy(hpsa_sas_port->port, hpsa_sas_phy->phy);
+ list_add_tail(&hpsa_sas_phy->phy_list_entry,
+ &hpsa_sas_port->phy_list_head);
+ hpsa_sas_phy->added_to_port = true;
+
+ return 0;
+}
+
+static int
+ hpsa_sas_port_add_rphy(struct hpsa_sas_port *hpsa_sas_port,
+ struct sas_rphy *rphy)
+{
+ struct sas_identify *identify;
+
+ identify = &rphy->identify;
+ identify->sas_address = hpsa_sas_port->sas_address;
+ identify->initiator_port_protocols = SAS_PROTOCOL_STP;
+ identify->target_port_protocols = SAS_PROTOCOL_STP;
+
+ return sas_rphy_add(rphy);
+}
+
+static struct hpsa_sas_port
+ *hpsa_alloc_sas_port(struct hpsa_sas_node *hpsa_sas_node,
+ u64 sas_address)
+{
+ int rc;
+ struct hpsa_sas_port *hpsa_sas_port;
+ struct sas_port *port;
+
+ hpsa_sas_port = kzalloc(sizeof(*hpsa_sas_port), GFP_KERNEL);
+ if (!hpsa_sas_port)
+ return NULL;
+
+ INIT_LIST_HEAD(&hpsa_sas_port->phy_list_head);
+ hpsa_sas_port->parent_node = hpsa_sas_node;
+
+ port = sas_port_alloc_num(hpsa_sas_node->parent_dev);
+ if (!port)
+ goto free_hpsa_port;
+
+ rc = sas_port_add(port);
+ if (rc)
+ goto free_sas_port;
+
+ hpsa_sas_port->port = port;
+ hpsa_sas_port->sas_address = sas_address;
+ list_add_tail(&hpsa_sas_port->port_list_entry,
+ &hpsa_sas_node->port_list_head);
+
+ return hpsa_sas_port;
+
+free_sas_port:
+ sas_port_free(port);
+free_hpsa_port:
+ kfree(hpsa_sas_port);
+
+ return NULL;
+}
+
+static void hpsa_free_sas_port(struct hpsa_sas_port *hpsa_sas_port)
+{
+ struct hpsa_sas_phy *hpsa_sas_phy;
+ struct hpsa_sas_phy *next;
+
+ list_for_each_entry_safe(hpsa_sas_phy, next,
+ &hpsa_sas_port->phy_list_head, phy_list_entry)
+ hpsa_free_sas_phy(hpsa_sas_phy);
+
+ sas_port_delete(hpsa_sas_port->port);
+ list_del(&hpsa_sas_port->port_list_entry);
+ kfree(hpsa_sas_port);
+}
+
+static struct hpsa_sas_node *hpsa_alloc_sas_node(struct device *parent_dev)
+{
+ struct hpsa_sas_node *hpsa_sas_node;
+
+ hpsa_sas_node = kzalloc(sizeof(*hpsa_sas_node), GFP_KERNEL);
+ if (hpsa_sas_node) {
+ hpsa_sas_node->parent_dev = parent_dev;
+ INIT_LIST_HEAD(&hpsa_sas_node->port_list_head);
+ }
+
+ return hpsa_sas_node;
+}
+
+static void hpsa_free_sas_node(struct hpsa_sas_node *hpsa_sas_node)
+{
+ struct hpsa_sas_port *hpsa_sas_port;
+ struct hpsa_sas_port *next;
+
+ if (!hpsa_sas_node)
+ return;
+
+ list_for_each_entry_safe(hpsa_sas_port, next,
+ &hpsa_sas_node->port_list_head, port_list_entry)
+ hpsa_free_sas_port(hpsa_sas_port);
+
+ kfree(hpsa_sas_node);
+}
+
+static struct hpsa_scsi_dev_t
+ *hpsa_find_device_by_sas_rphy(struct ctlr_info *h,
+ struct sas_rphy *rphy)
+{
+ int i;
+ struct hpsa_scsi_dev_t *device;
+
+ for (i = 0; i < h->ndevices; i++) {
+ device = h->dev[i];
+ if (!device->sas_port)
+ continue;
+ if (device->sas_port->rphy == rphy)
+ return device;
+ }
+
+ return NULL;
+}
+
+static int hpsa_add_sas_host(struct ctlr_info *h)
+{
+ int rc;
+ struct device *parent_dev;
+ struct hpsa_sas_node *hpsa_sas_node;
+ struct hpsa_sas_port *hpsa_sas_port;
+ struct hpsa_sas_phy *hpsa_sas_phy;
+
+ parent_dev = &h->scsi_host->shost_gendev;
+
+ hpsa_sas_node = hpsa_alloc_sas_node(parent_dev);
+ if (!hpsa_sas_node)
+ return -ENOMEM;
+
+ hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, h->sas_address);
+ if (!hpsa_sas_port) {
+ rc = -ENODEV;
+ goto free_sas_node;
+ }
+
+ hpsa_sas_phy = hpsa_alloc_sas_phy(hpsa_sas_port);
+ if (!hpsa_sas_phy) {
+ rc = -ENODEV;
+ goto free_sas_port;
+ }
+
+ rc = hpsa_sas_port_add_phy(hpsa_sas_phy);
+ if (rc)
+ goto free_sas_phy;
+
+ h->sas_host = hpsa_sas_node;
+
+ return 0;
+
+free_sas_phy:
+ hpsa_free_sas_phy(hpsa_sas_phy);
+free_sas_port:
+ hpsa_free_sas_port(hpsa_sas_port);
+free_sas_node:
+ hpsa_free_sas_node(hpsa_sas_node);
+
+ return rc;
+}
+
+static void hpsa_delete_sas_host(struct ctlr_info *h)
+{
+ hpsa_free_sas_node(h->sas_host);
+}
+
+static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node,
+ struct hpsa_scsi_dev_t *device)
+{
+ int rc;
+ struct hpsa_sas_port *hpsa_sas_port;
+ struct sas_rphy *rphy;
+
+ hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, device->sas_address);
+ if (!hpsa_sas_port)
+ return -ENOMEM;
+
+ rphy = sas_end_device_alloc(hpsa_sas_port->port);
+ if (!rphy) {
+ rc = -ENODEV;
+ goto free_sas_port;
+ }
+
+ hpsa_sas_port->rphy = rphy;
+ device->sas_port = hpsa_sas_port;
+
+ rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy);
+ if (rc)
+ goto free_sas_port;
+
+ return 0;
+
+free_sas_port:
+ hpsa_free_sas_port(hpsa_sas_port);
+ device->sas_port = NULL;
+
+ return rc;
+}
+
+static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device)
+{
+ if (device->sas_port) {
+ hpsa_free_sas_port(device->sas_port);
+ device->sas_port = NULL;
+ }
+}
+
+static int
+hpsa_sas_get_linkerrors(struct sas_phy *phy)
+{
+ return 0;
+}
+
+static int
+hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
+{
+ return 0;
+}
+
+static int
+hpsa_sas_get_bay_identifier(struct sas_rphy *rphy)
+{
+ return -ENXIO;
+}
+
+static int
+hpsa_sas_phy_reset(struct sas_phy *phy, int hard_reset)
+{
+ return 0;
+}
+
+static int
+hpsa_sas_phy_enable(struct sas_phy *phy, int enable)
+{
+ return 0;
+}
+
+static int
+hpsa_sas_phy_setup(struct sas_phy *phy)
+{
+ return 0;
+}
+
+static void
+hpsa_sas_phy_release(struct sas_phy *phy)
+{
+}
+
+static int
+hpsa_sas_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
+{
+ return -EINVAL;
+}
+
+/* SMP = Serial Management Protocol */
+static int
+hpsa_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
+struct request *req)
+{
+ return -EINVAL;
+}
+
+static struct sas_function_template hpsa_sas_transport_functions = {
+ .get_linkerrors = hpsa_sas_get_linkerrors,
+ .get_enclosure_identifier = hpsa_sas_get_enclosure_identifier,
+ .get_bay_identifier = hpsa_sas_get_bay_identifier,
+ .phy_reset = hpsa_sas_phy_reset,
+ .phy_enable = hpsa_sas_phy_enable,
+ .phy_setup = hpsa_sas_phy_setup,
+ .phy_release = hpsa_sas_phy_release,
+ .set_phy_speed = hpsa_sas_phy_speed,
+ .smp_handler = hpsa_sas_smp_handler,
+};
+
/*
* This is it. Register the PCI driver information for the cards we control
* the OS will call our registered routines when it finds one of our cards.
*/
static int __init hpsa_init(void)
{
- return pci_register_driver(&hpsa_pci_driver);
+ int rc;
+
+ hpsa_sas_transport_template =
+ sas_attach_transport(&hpsa_sas_transport_functions);
+ if (!hpsa_sas_transport_template)
+ return -ENODEV;
+
+ rc = pci_register_driver(&hpsa_pci_driver);
+
+ if (rc)
+ sas_release_transport(hpsa_sas_transport_template);
+
+ return rc;
}
static void __exit hpsa_cleanup(void)
{
pci_unregister_driver(&hpsa_pci_driver);
+ sas_release_transport(hpsa_sas_transport_template);
}
static void __attribute__((unused)) verify_offsets(void)
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 27debb363529..ae5beda1bdb5 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -33,12 +33,38 @@ struct access_method {
unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
};
+/* for SAS hosts and SAS expanders */
+struct hpsa_sas_node {
+ struct device *parent_dev;
+ struct list_head port_list_head;
+};
+
+struct hpsa_sas_port {
+ struct list_head port_list_entry;
+ u64 sas_address;
+ struct sas_port *port;
+ int next_phy_index;
+ struct list_head phy_list_head;
+ struct hpsa_sas_node *parent_node;
+ struct sas_rphy *rphy;
+};
+
+struct hpsa_sas_phy {
+ struct list_head phy_list_entry;
+ struct sas_phy *phy;
+ struct hpsa_sas_port *parent_port;
+ bool added_to_port;
+};
+
struct hpsa_scsi_dev_t {
- int devtype;
+ unsigned int devtype;
int bus, target, lun; /* as presented to the OS */
unsigned char scsi3addr[8]; /* as presented to the HW */
+ u8 physical_device : 1;
+ u8 expose_device;
#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"
unsigned char device_id[16]; /* from inquiry pg. 0x83 */
+ u64 sas_address;
unsigned char vendor[8]; /* bytes 8-15 of inquiry data */
unsigned char model[16]; /* bytes 16-31 of inquiry data */
unsigned char raid_level; /* from inquiry page 0xC1 */
@@ -75,11 +101,8 @@ struct hpsa_scsi_dev_t {
struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES];
int nphysical_disks;
int supports_aborts;
-#define HPSA_DO_NOT_EXPOSE 0x0
-#define HPSA_SG_ATTACH 0x1
-#define HPSA_ULD_ATTACH 0x2
-#define HPSA_SCSI_ADD (HPSA_SG_ATTACH | HPSA_ULD_ATTACH)
- u8 expose_state;
+ struct hpsa_sas_port *sas_port;
+ int external; /* 1-from external array 0-not <0-unknown */
};
struct reply_queue_buffer {
@@ -136,6 +159,7 @@ struct ctlr_info {
char *product_name;
struct pci_dev *pdev;
u32 board_id;
+ u64 sas_address;
void __iomem *vaddr;
unsigned long paddr;
int nr_cmds; /* Number of commands allowed on this controller */
@@ -262,7 +286,10 @@ struct ctlr_info {
spinlock_t offline_device_lock;
struct list_head offline_device_list;
int acciopath_status;
+ int drv_req_rescan;
int raid_offload_debug;
+ int discovery_polling;
+ struct ReportLUNdata *lastlogicals;
int needs_abort_tags_swizzled;
struct workqueue_struct *resubmit_wq;
struct workqueue_struct *rescan_ctlr_wq;
@@ -270,6 +297,8 @@ struct ctlr_info {
wait_queue_head_t abort_cmd_wait_queue;
wait_queue_head_t event_sync_wait_queue;
struct mutex reset_mutex;
+ u8 reset_in_progress;
+ struct hpsa_sas_node *sas_host;
};
struct offline_device_entry {
@@ -283,6 +312,7 @@ struct offline_device_entry {
#define HPSA_RESET_TYPE_BUS 0x01
#define HPSA_RESET_TYPE_TARGET 0x03
#define HPSA_RESET_TYPE_LUN 0x04
+#define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */
#define HPSA_MSG_SEND_RETRY_LIMIT 10
#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000)
@@ -367,6 +397,11 @@ struct offline_device_entry {
#define IOACCEL2_INBOUND_POSTQ_64_LOW 0xd0
#define IOACCEL2_INBOUND_POSTQ_64_HI 0xd4
+#define HPSA_PHYSICAL_DEVICE_BUS 0
+#define HPSA_RAID_VOLUME_BUS 1
+#define HPSA_EXTERNAL_RAID_VOLUME_BUS 2
+#define HPSA_HBA_BUS 3
+
/*
Send the command to the hardware
*/
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 47c756ba8dce..d92ef0d352b5 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -260,8 +260,6 @@ struct ext_report_lun_entry {
u8 wwid[8];
u8 device_type;
u8 device_flags;
-#define NON_DISK_PHYS_DEV(x) ((x)[17] & 0x01)
-#define PHYS_IOACCEL(x) ((x)[17] & 0x08)
u8 lun_count; /* multi-lun device, how many luns */
u8 redundant_paths;
u32 ioaccel_handle; /* ioaccel1 only uses lower 16 bits */
@@ -288,6 +286,11 @@ struct SenseSubsystem_info {
#define BMIC_FLASH_FIRMWARE 0xF7
#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64
#define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15
+#define BMIC_IDENTIFY_CONTROLLER 0x11
+#define BMIC_SET_DIAG_OPTIONS 0xF4
+#define BMIC_SENSE_DIAG_OPTIONS 0xF5
+#define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x40000000
+#define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66
/* Command List Structure */
union SCSI3Addr {
@@ -684,6 +687,16 @@ struct hpsa_pci_info {
u32 board_id;
};
+struct bmic_identify_controller {
+ u8 configured_logical_drive_count; /* offset 0 */
+ u8 pad1[153];
+ __le16 extended_logical_unit_count; /* offset 154 */
+ u8 pad2[136];
+ u8 controller_mode; /* offset 292 */
+ u8 pad3[32];
+};
+
+
struct bmic_identify_physical_device {
u8 scsi_bus; /* SCSI Bus number on controller */
u8 scsi_id; /* SCSI ID on this bus */
@@ -816,5 +829,18 @@ struct bmic_identify_physical_device {
u8 padding[112];
};
+struct bmic_sense_subsystem_info {
+ u8 primary_slot_number;
+ u8 reserved[3];
+ u8 chasis_serial_number[32];
+ u8 primary_world_wide_id[8];
+ u8 primary_array_serial_number[32]; /* NULL terminated */
+ u8 primary_cache_serial_number[32]; /* NULL terminated */
+ u8 reserved_2[8];
+ u8 secondary_array_serial_number[32];
+ u8 secondary_cache_serial_number[32];
+ u8 pad[332];
+};
+
#pragma pack()
#endif /* HPSA_CMD_H */
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 057d27721d5b..6aa317c303e2 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3095,7 +3095,6 @@ static struct scsi_host_template driver_template = {
.max_sectors = IBMVFC_MAX_SECTORS,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = ibmvfc_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 6a41c36b16b0..adfef9db6f1e 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -106,9 +106,9 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(IBMVSCSI_VERSION);
module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(max_id, "Largest ID value for each channel");
+MODULE_PARM_DESC(max_id, "Largest ID value for each channel [Default=64]");
module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(max_channel, "Largest channel value");
+MODULE_PARM_DESC(max_channel, "Largest channel value [Default=3]");
module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds");
module_param_named(max_requests, max_requests, int, S_IRUGO);
@@ -2289,11 +2289,15 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
goto init_pool_failed;
}
- host->max_lun = 8;
+ host->max_lun = IBMVSCSI_MAX_LUN;
host->max_id = max_id;
host->max_channel = max_channel;
host->max_cmd_len = 16;
+ dev_info(dev,
+ "Maximum ID: %d Maximum LUN: %llu Maximum Channel: %d\n",
+ host->max_id, host->max_lun, host->max_channel);
+
if (scsi_add_host(hostdata->host, hostdata->dev))
goto add_host_failed;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 7d64867c5dd1..1067367395cd 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -48,6 +48,7 @@ struct Scsi_Host;
#define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
#define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
#define IBMVSCSI_MAX_CMDS_PER_LUN 64
+#define IBMVSCSI_MAX_LUN 32
/* ------------------------------------------------------------
* Data Structures
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index b62836ddbbee..536cd5a80422 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -6363,15 +6363,19 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
ipr_cmd->scsi_cmd = scsi_cmd;
ipr_cmd->done = ipr_scsi_eh_done;
- if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) {
+ if (ipr_is_gscsi(res)) {
if (scsi_cmd->underflow == 0)
ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK;
- ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
- if (ipr_is_gscsi(res) && res->reset_occurred) {
+ if (res->reset_occurred) {
res->reset_occurred = 0;
ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
}
+ }
+
+ if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) {
+ ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
+
ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR;
if (scsi_cmd->flags & SCMD_TAGGED)
ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK;
@@ -6502,7 +6506,6 @@ static struct scsi_host_template driver_template = {
.shost_attrs = ipr_ioa_attrs,
.sdev_attrs = ipr_dev_attrs,
.proc_name = IPR_NAME,
- .use_blk_tags = 1,
};
/**
@@ -7671,6 +7674,63 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd)
return IPR_RC_JOB_RETURN;
}
+static int ipr_ioa_service_action_failed(struct ipr_cmnd *ipr_cmd)
+{
+ u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
+
+ if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT)
+ return IPR_RC_JOB_CONTINUE;
+
+ return ipr_reset_cmd_failed(ipr_cmd);
+}
+
+static void ipr_build_ioa_service_action(struct ipr_cmnd *ipr_cmd,
+ __be32 res_handle, u8 sa_code)
+{
+ struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+
+ ioarcb->res_handle = res_handle;
+ ioarcb->cmd_pkt.cdb[0] = IPR_IOA_SERVICE_ACTION;
+ ioarcb->cmd_pkt.cdb[1] = sa_code;
+ ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
+}
+
+/**
+ * ipr_ioafp_set_caching_parameters - Issue Set Cache parameters service
+ * action
+ *
+ * Return value:
+ * none
+ **/
+static int ipr_ioafp_set_caching_parameters(struct ipr_cmnd *ipr_cmd)
+{
+ struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data;
+
+ ENTER;
+
+ ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
+
+ if (pageC4->cache_cap[0] & IPR_CAP_SYNC_CACHE) {
+ ipr_build_ioa_service_action(ipr_cmd,
+ cpu_to_be32(IPR_IOA_RES_HANDLE),
+ IPR_IOA_SA_CHANGE_CACHE_PARAMS);
+
+ ioarcb->cmd_pkt.cdb[2] = 0x40;
+
+ ipr_cmd->job_step_failed = ipr_ioa_service_action_failed;
+ ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout,
+ IPR_SET_SUP_DEVICE_TIMEOUT);
+
+ LEAVE;
+ return IPR_RC_JOB_RETURN;
+ }
+
+ LEAVE;
+ return IPR_RC_JOB_CONTINUE;
+}
+
/**
* ipr_ioafp_inquiry - Send an Inquiry to the adapter.
* @ipr_cmd: ipr command struct
@@ -7722,6 +7782,39 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page)
}
/**
+ * ipr_ioafp_pageC4_inquiry - Send a Page 0xC4 Inquiry to the adapter.
+ * @ipr_cmd: ipr command struct
+ *
+ * This function sends a Page 0xC4 inquiry to the adapter
+ * to retrieve software VPD information.
+ *
+ * Return value:
+ * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_ioafp_pageC4_inquiry(struct ipr_cmnd *ipr_cmd)
+{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data;
+ struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data;
+
+ ENTER;
+ ipr_cmd->job_step = ipr_ioafp_set_caching_parameters;
+ memset(pageC4, 0, sizeof(*pageC4));
+
+ if (ipr_inquiry_page_supported(page0, 0xC4)) {
+ ipr_ioafp_inquiry(ipr_cmd, 1, 0xC4,
+ (ioa_cfg->vpd_cbs_dma
+ + offsetof(struct ipr_misc_cbs,
+ pageC4_data)),
+ sizeof(struct ipr_inquiry_pageC4));
+ return IPR_RC_JOB_RETURN;
+ }
+
+ LEAVE;
+ return IPR_RC_JOB_CONTINUE;
+}
+
+/**
* ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter.
* @ipr_cmd: ipr command struct
*
@@ -7738,7 +7831,7 @@ static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd)
struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap;
ENTER;
- ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
+ ipr_cmd->job_step = ipr_ioafp_pageC4_inquiry;
memset(cap, 0, sizeof(*cap));
if (ipr_inquiry_page_supported(page0, 0xD0)) {
@@ -8277,6 +8370,42 @@ static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd)
return IPR_RC_JOB_RETURN;
}
+static int ipr_dump_mailbox_wait(struct ipr_cmnd *ipr_cmd)
+{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+ ENTER;
+
+ if (ioa_cfg->sdt_state != GET_DUMP)
+ return IPR_RC_JOB_RETURN;
+
+ if (!ioa_cfg->sis64 || !ipr_cmd->u.time_left ||
+ (readl(ioa_cfg->regs.sense_interrupt_reg) &
+ IPR_PCII_MAILBOX_STABLE)) {
+
+ if (!ipr_cmd->u.time_left)
+ dev_err(&ioa_cfg->pdev->dev,
+ "Timed out waiting for Mailbox register.\n");
+
+ ioa_cfg->sdt_state = READ_DUMP;
+ ioa_cfg->dump_timeout = 0;
+ if (ioa_cfg->sis64)
+ ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
+ else
+ ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT);
+ ipr_cmd->job_step = ipr_reset_wait_for_dump;
+ schedule_work(&ioa_cfg->work_q);
+
+ } else {
+ ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
+ ipr_reset_start_timer(ipr_cmd,
+ IPR_CHECK_FOR_RESET_TIMEOUT);
+ }
+
+ LEAVE;
+ return IPR_RC_JOB_RETURN;
+}
+
/**
* ipr_reset_restore_cfg_space - Restore PCI config space.
* @ipr_cmd: ipr command struct
@@ -8326,20 +8455,11 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
if (ioa_cfg->in_ioa_bringdown) {
ipr_cmd->job_step = ipr_ioa_bringdown_done;
+ } else if (ioa_cfg->sdt_state == GET_DUMP) {
+ ipr_cmd->job_step = ipr_dump_mailbox_wait;
+ ipr_cmd->u.time_left = IPR_WAIT_FOR_MAILBOX;
} else {
ipr_cmd->job_step = ipr_reset_enable_ioa;
-
- if (GET_DUMP == ioa_cfg->sdt_state) {
- ioa_cfg->sdt_state = READ_DUMP;
- ioa_cfg->dump_timeout = 0;
- if (ioa_cfg->sis64)
- ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
- else
- ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT);
- ipr_cmd->job_step = ipr_reset_wait_for_dump;
- schedule_work(&ioa_cfg->work_q);
- return IPR_RC_JOB_RETURN;
- }
}
LEAVE;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index e4fb17a58649..a34c7a5a995e 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -39,8 +39,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.6.2"
-#define IPR_DRIVER_DATE "(June 11, 2015)"
+#define IPR_DRIVER_VERSION "2.6.3"
+#define IPR_DRIVER_DATE "(October 17, 2015)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -216,6 +216,10 @@
#define IPR_SET_ALL_SUPPORTED_DEVICES 0x80
#define IPR_IOA_SHUTDOWN 0xF7
#define IPR_WR_BUF_DOWNLOAD_AND_SAVE 0x05
+#define IPR_IOA_SERVICE_ACTION 0xD2
+
+/* IOA Service Actions */
+#define IPR_IOA_SA_CHANGE_CACHE_PARAMS 0x14
/*
* Timeouts
@@ -279,6 +283,9 @@
#define IPR_IPL_INIT_STAGE_TIME_MASK 0x0000ffff
#define IPR_PCII_IPL_STAGE_CHANGE (0x80000000 >> 0)
+#define IPR_PCII_MAILBOX_STABLE (0x80000000 >> 4)
+#define IPR_WAIT_FOR_MAILBOX (2 * HZ)
+
#define IPR_PCII_IOA_TRANS_TO_OPER (0x80000000 >> 0)
#define IPR_PCII_IOARCB_XFER_FAILED (0x80000000 >> 3)
#define IPR_PCII_IOA_UNIT_CHECKED (0x80000000 >> 4)
@@ -846,6 +853,16 @@ struct ipr_inquiry_page0 {
u8 page[IPR_INQUIRY_PAGE0_ENTRIES];
}__attribute__((packed));
+struct ipr_inquiry_pageC4 {
+ u8 peri_qual_dev_type;
+ u8 page_code;
+ u8 reserved1;
+ u8 len;
+ u8 cache_cap[4];
+#define IPR_CAP_SYNC_CACHE 0x08
+ u8 reserved2[20];
+} __packed;
+
struct ipr_hostrcb_device_data_entry {
struct ipr_vpd vpd;
struct ipr_res_addr dev_res_addr;
@@ -1319,6 +1336,7 @@ struct ipr_misc_cbs {
struct ipr_inquiry_page0 page0_data;
struct ipr_inquiry_page3 page3_data;
struct ipr_inquiry_cap cap;
+ struct ipr_inquiry_pageC4 pageC4_data;
struct ipr_mode_pages mode_pages;
struct ipr_supported_device supp_dev;
};
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 0dfcabe3ca7c..77128d680e3b 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -170,7 +170,6 @@ static struct scsi_host_template isci_sht = {
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = isci_host_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -272,11 +271,11 @@ static void isci_unregister(struct isci_host *isci_host)
if (!isci_host)
return;
+ shost = to_shost(isci_host);
+ scsi_remove_host(shost);
sas_unregister_ha(&isci_host->sas_ha);
- shost = to_shost(isci_host);
sas_remove_host(shost);
- scsi_remove_host(shost);
scsi_host_put(shost);
}
diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c
index 9fbf78ed821b..c168321b560e 100644
--- a/drivers/scsi/libfc/fc_npiv.c
+++ b/drivers/scsi/libfc/fc_npiv.c
@@ -25,7 +25,7 @@
#include <linux/export.h>
/**
- * fc_vport_create() - Create a new NPIV vport instance
+ * libfc_vport_create() - Create a new NPIV vport instance
* @vport: fc_vport structure from scsi_transport_fc
* @privsize: driver private data size to allocate along with the Scsi_Host
*/
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index a5a56fa31e70..ceee9a3fd9e5 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -495,15 +495,17 @@ struct unsol_rcv_ct_ctx {
#define LPFC_USER_LINK_SPEED_8G 8 /* 8 Gigabaud */
#define LPFC_USER_LINK_SPEED_10G 10 /* 10 Gigabaud */
#define LPFC_USER_LINK_SPEED_16G 16 /* 16 Gigabaud */
-#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_16G
-#define LPFC_USER_LINK_SPEED_BITMAP ((1 << LPFC_USER_LINK_SPEED_16G) | \
+#define LPFC_USER_LINK_SPEED_32G 32 /* 32 Gigabaud */
+#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_32G
+#define LPFC_USER_LINK_SPEED_BITMAP ((1ULL << LPFC_USER_LINK_SPEED_32G) | \
+ (1 << LPFC_USER_LINK_SPEED_16G) | \
(1 << LPFC_USER_LINK_SPEED_10G) | \
(1 << LPFC_USER_LINK_SPEED_8G) | \
(1 << LPFC_USER_LINK_SPEED_4G) | \
(1 << LPFC_USER_LINK_SPEED_2G) | \
(1 << LPFC_USER_LINK_SPEED_1G) | \
(1 << LPFC_USER_LINK_SPEED_AUTO))
-#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16"
+#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32"
enum nemb_type {
nemb_mse = 1,
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index d65bd178d131..f6446d759d7f 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1642,8 +1642,6 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
struct Scsi_Host *shost = class_to_shost(dev);\
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
struct lpfc_hba *phba = vport->phba;\
- uint val = 0;\
- val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n",\
phba->cfg_##attr);\
}
@@ -1808,8 +1806,6 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
{ \
struct Scsi_Host *shost = class_to_shost(dev);\
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
- uint val = 0;\
- val = vport->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
}
@@ -1835,8 +1831,6 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
{ \
struct Scsi_Host *shost = class_to_shost(dev);\
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
- uint val = 0;\
- val = vport->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
}
@@ -3282,15 +3276,20 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
if (val >= 0 && val <= 6) {
prev_val = phba->cfg_topology;
- phba->cfg_topology = val;
if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G &&
val == 4) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"3113 Loop mode not supported at speed %d\n",
- phba->cfg_link_speed);
- phba->cfg_topology = prev_val;
+ val);
return -EINVAL;
}
+ if (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
+ val == 4) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "3114 Loop mode not supported\n");
+ return -EINVAL;
+ }
+ phba->cfg_topology = val;
if (nolip)
return strlen(buf);
@@ -3731,7 +3730,8 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
- ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb))) {
+ ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) ||
+ ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb))) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2879 lpfc_link_speed attribute cannot be set "
"to %d. Speed is not supported by this port.\n",
@@ -5267,6 +5267,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
case LPFC_LINK_SPEED_16GHZ:
fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
break;
+ case LPFC_LINK_SPEED_32GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_32GBIT;
+ break;
default:
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index b705068079c0..05dcc2abd541 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -904,7 +904,6 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
uint32_t evt_req_id = 0;
uint32_t cmd;
- uint32_t len;
struct lpfc_dmabuf *dmabuf = NULL;
struct lpfc_bsg_event *evt;
struct event_data *evt_dat = NULL;
@@ -946,7 +945,6 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
ct_req = (struct lpfc_sli_ct_request *)dmabuf->virt;
evt_req_id = ct_req->FsType;
cmd = ct_req->CommandResponse.bits.CmdRsp;
- len = ct_req->CommandResponse.bits.Size;
if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
lpfc_sli_ringpostbuf_put(phba, pring, dmabuf);
@@ -2988,7 +2986,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
{
struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- struct diag_mode_test *diag_mode;
struct lpfc_bsg_event *evt;
struct event_data *evdat;
struct lpfc_sli *psli = &phba->sli;
@@ -3031,8 +3028,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
rc = -EINVAL;
goto loopback_test_exit;
}
- diag_mode = (struct diag_mode_test *)
- job->request->rqst_data.h_vendor.vendor_cmd;
if ((phba->link_state == LPFC_HBA_ERROR) ||
(psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
@@ -3293,7 +3288,6 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
{
struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- struct get_mgmt_rev *event_req;
struct get_mgmt_rev_reply *event_reply;
int rc = 0;
@@ -3306,9 +3300,6 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
goto job_error;
}
- event_req = (struct get_mgmt_rev *)
- job->request->rqst_data.h_vendor.vendor_cmd;
-
event_reply = (struct get_mgmt_rev_reply *)
job->reply->reply_data.vendor_reply.vendor_rsp;
@@ -4348,7 +4339,6 @@ static int
lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
struct lpfc_dmabuf *dmabuf)
{
- struct lpfc_sli_config_mbox *sli_cfg_mbx;
struct bsg_job_data *dd_data = NULL;
LPFC_MBOXQ_t *pmboxq = NULL;
MAILBOX_t *pmb;
@@ -4362,9 +4352,6 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
phba->mbox_ext_buf_ctx.seqNum++;
nemb_tp = phba->mbox_ext_buf_ctx.nembType;
- sli_cfg_mbx = (struct lpfc_sli_config_mbox *)
- phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
-
dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
if (!dd_data) {
rc = -ENOMEM;
@@ -4606,7 +4593,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
uint32_t transmit_length, receive_length, mode;
struct lpfc_mbx_sli4_config *sli4_config;
struct lpfc_mbx_nembed_cmd *nembed_sge;
- struct mbox_header *header;
struct ulp_bde64 *bde;
uint8_t *ext = NULL;
int rc = 0;
@@ -4804,8 +4790,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* rebuild the command for sli4 using our
* own buffers like we do for biu diags
*/
- header = (struct mbox_header *)
- &pmb->un.varWords[0];
nembed_sge = (struct lpfc_mbx_nembed_cmd *)
&pmb->un.varWords[0];
receive_length = nembed_sge->sge[0].length;
@@ -5048,7 +5032,6 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
IOCB_t *cmd;
int rc = 0;
struct menlo_command *menlo_cmd;
- struct menlo_response *menlo_resp;
struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
int request_nseg;
int reply_nseg;
@@ -5088,9 +5071,6 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
menlo_cmd = (struct menlo_command *)
job->request->rqst_data.h_vendor.vendor_cmd;
- menlo_resp = (struct menlo_response *)
- job->reply->reply_data.vendor_reply.vendor_rsp;
-
/* allocate our bsg tracking structure */
dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
if (!dd_data) {
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index af129966bd11..8fded1f7605f 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -55,6 +55,7 @@
#define HBA_PORTSPEED_10GBIT 0x0004 /* 10 GBit/sec */
#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */
#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */
+#define HBA_PORTSPEED_32GBIT 0x0040 /* 32 GBit/sec */
#define HBA_PORTSPEED_UNKNOWN 0x0800 /* Unknown */
#define FOURBYTES 4
@@ -575,7 +576,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_vport *vport = cmdiocb->vport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
IOCB_t *irsp;
- struct lpfc_dmabuf *bmp;
struct lpfc_dmabuf *outp;
struct lpfc_sli_ct_request *CTrsp;
struct lpfc_nodelist *ndlp;
@@ -588,7 +588,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
cmdiocb->context_un.rsp_iocb = rspiocb;
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
- bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
irsp = &rspiocb->iocb;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
@@ -1733,12 +1732,9 @@ hba_out:
case SLI_MGMT_RPRT:
case SLI_MGMT_RPA:
{
- lpfc_vpd_t *vp;
struct serv_parm *hsp;
int len = 0;
- vp = &phba->vpd;
-
if (cmdcode == SLI_MGMT_RPRT) {
rh = (struct lpfc_fdmi_reg_hba *)
&CtReq->un.PortID;
@@ -1778,6 +1774,8 @@ hba_out:
ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_SPEED);
ad->AttrLen = cpu_to_be16(FOURBYTES + 4);
ae->un.SupportSpeed = 0;
+ if (phba->lmt & LMT_32Gb)
+ ae->un.SupportSpeed |= HBA_PORTSPEED_32GBIT;
if (phba->lmt & LMT_16Gb)
ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT;
if (phba->lmt & LMT_10Gb)
@@ -1821,6 +1819,9 @@ hba_out:
case LPFC_LINK_SPEED_16GHZ:
ae->un.PortSpeed = HBA_PORTSPEED_16GBIT;
break;
+ case LPFC_LINK_SPEED_32GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_32GBIT;
+ break;
default:
ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN;
break;
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 36bf58ba750a..b6fa257ea3e0 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -457,11 +457,9 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mboxq;
struct lpfc_nodelist *ndlp;
- struct serv_parm *sp;
struct lpfc_dmabuf *dmabuf;
int rc = 0;
- sp = &phba->fc_fabparam;
/* move forward in case of SLI4 FC port loopback test and pt2pt mode */
if ((phba->sli_rev == LPFC_SLI_REV4) &&
!(phba->link_flag & LS_LOOPBACK_MODE) &&
@@ -1028,9 +1026,11 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
stop_rr_fcf_flogi:
/* FLOGI failure */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "2858 FLOGI failure Status:x%x/x%x TMO:x%x\n",
+ "2858 FLOGI failure Status:x%x/x%x TMO:x%x "
+ "Data x%x x%x\n",
irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->ulpTimeout);
+ irsp->ulpTimeout, phba->hba_flag,
+ phba->fcf.fcf_flag);
/* Check for retry */
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
@@ -1154,6 +1154,9 @@ stop_rr_fcf_flogi:
}
flogifail:
+ spin_lock_irq(&phba->hbalock);
+ phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
+ spin_unlock_irq(&phba->hbalock);
lpfc_nlp_put(ndlp);
if (!lpfc_error_lost_link(irsp)) {
@@ -1205,14 +1208,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct serv_parm *sp;
IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli_ring *pring;
uint8_t *pcmd;
uint16_t cmdsize;
uint32_t tmo;
int rc;
- pring = &phba->sli.ring[LPFC_ELS_RING];
-
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_FLOGI);
@@ -1454,8 +1454,6 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
void
lpfc_more_plogi(struct lpfc_vport *vport)
{
- int sentplogi;
-
if (vport->num_disc_nodes)
vport->num_disc_nodes--;
@@ -1468,7 +1466,7 @@ lpfc_more_plogi(struct lpfc_vport *vport)
/* Check to see if there are more PLOGIs to be sent */
if (vport->fc_flag & FC_NLP_MORE)
/* go thru NPR nodes and issue any remaining ELS PLOGIs */
- sentplogi = lpfc_els_disc_plogi(vport);
+ lpfc_els_disc_plogi(vport);
return;
}
@@ -1956,16 +1954,12 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
{
struct lpfc_hba *phba = vport->phba;
struct serv_parm *sp;
- IOCB_t *icmd;
struct lpfc_nodelist *ndlp;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
int ret;
- psli = &phba->sli;
-
ndlp = lpfc_findnode_did(vport, did);
if (ndlp && !NLP_CHK_NODE_ACT(ndlp))
ndlp = NULL;
@@ -1977,7 +1971,6 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
if (!elsiocb)
return 1;
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
/* For PLOGI request, remainder of payload is service parameters */
@@ -2034,10 +2027,8 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_vport *vport = cmdiocb->vport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
IOCB_t *irsp;
- struct lpfc_sli *psli;
struct lpfc_nodelist *ndlp;
- psli = &phba->sli;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
@@ -2117,7 +2108,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
PRLI *npr;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
uint8_t *pcmd;
uint16_t cmdsize;
@@ -2128,7 +2118,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!elsiocb)
return 1;
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
/* For PRLI request, remainder of payload is service parameters */
@@ -2413,7 +2402,6 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
ADISC *ap;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
uint8_t *pcmd;
uint16_t cmdsize;
@@ -2424,7 +2412,6 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!elsiocb)
return 1;
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
/* For ADISC request, remainder of payload is service parameters */
@@ -2478,12 +2465,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_vport *vport = ndlp->vport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
IOCB_t *irsp;
- struct lpfc_sli *psli;
struct lpfcMboxq *mbox;
unsigned long flags;
uint32_t skip_recovery = 0;
- psli = &phba->sli;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
@@ -2609,7 +2594,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
uint8_t *pcmd;
uint16_t cmdsize;
@@ -2628,7 +2612,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!elsiocb)
return 1;
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
pcmd += sizeof(uint32_t);
@@ -2742,14 +2725,11 @@ int
lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
{
struct lpfc_hba *phba = vport->phba;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
struct lpfc_nodelist *ndlp;
- psli = &phba->sli;
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
ndlp = lpfc_findnode_did(vport, nportid);
@@ -2776,7 +2756,6 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 1;
}
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = ELS_CMD_SCR;
@@ -2836,9 +2815,7 @@ static int
lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
{
struct lpfc_hba *phba = vport->phba;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
FARP *fp;
uint8_t *pcmd;
uint32_t *lp;
@@ -2846,7 +2823,6 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
struct lpfc_nodelist *ondlp;
struct lpfc_nodelist *ndlp;
- psli = &phba->sli;
cmdsize = (sizeof(uint32_t) + sizeof(FARP));
ndlp = lpfc_findnode_did(vport, nportid);
@@ -2872,7 +2848,6 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 1;
}
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
@@ -3922,13 +3897,11 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
IOCB_t *icmd;
IOCB_t *oldcmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
int rc;
ELS_PKT *els_pkt_ptr;
- psli = &phba->sli;
oldcmd = &oldiocb->iocb;
switch (flag) {
@@ -4061,12 +4034,10 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
IOCB_t *icmd;
IOCB_t *oldcmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
int rc;
- psli = &phba->sli;
cmdsize = 2 * sizeof(uint32_t);
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
ndlp->nlp_DID, ELS_CMD_LS_RJT);
@@ -4212,13 +4183,10 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
IOCB_t *icmd;
IOCB_t *oldcmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
int rc;
- psli = &phba->sli;
-
cmdsize = sizeof(uint32_t) + sizeof(PRLI);
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
@@ -4315,12 +4283,10 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
RNID *rn;
IOCB_t *icmd, *oldcmd;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
int rc;
- psli = &phba->sli;
cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
+ (2 * sizeof(struct lpfc_name));
if (format)
@@ -4447,12 +4413,10 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *elsiocb;
- struct lpfc_sli *psli;
uint8_t *pcmd;
uint16_t cmdsize;
int rc;
- psli = &phba->sli;
cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len;
/* The accumulated length can exceed the BPL_SIZE. For
@@ -4746,6 +4710,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
desc->info.port_speed.speed = cpu_to_be16(rdp_speed);
+ if (phba->lmt & LMT_32Gb)
+ rdp_cap |= RDP_PS_32GB;
if (phba->lmt & LMT_16Gb)
rdp_cap |= RDP_PS_16GB;
if (phba->lmt & LMT_10Gb)
@@ -5181,14 +5147,12 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *pcmd;
- IOCB_t *icmd;
uint8_t *lp;
struct fc_lcb_request_frame *beacon;
struct lpfc_lcb_context *lcb_context;
uint8_t state, rjt_err;
struct ls_rjt stat;
- icmd = &cmdiocb->iocb;
pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
lp = (uint8_t *)pcmd->virt;
beacon = (struct fc_lcb_request_frame *)pcmd->virt;
@@ -5209,7 +5173,6 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
rjt_err = LSRJT_CMD_UNSUPPORTED;
goto rjt;
}
- lcb_context = kmalloc(sizeof(struct lpfc_lcb_context), GFP_KERNEL);
if (phba->hba_flag & HBA_FCOE_MODE) {
rjt_err = LSRJT_CMD_UNSUPPORTED;
@@ -5240,6 +5203,12 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
goto rjt;
}
+ lcb_context = kmalloc(sizeof(*lcb_context), GFP_KERNEL);
+ if (!lcb_context) {
+ rjt_err = LSRJT_UNABLE_TPC;
+ goto rjt;
+ }
+
state = (beacon->lcb_sub_command == LPFC_LCB_ON) ? 1 : 0;
lcb_context->sub_command = beacon->lcb_sub_command;
lcb_context->type = beacon->lcb_type;
@@ -5250,6 +5219,7 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
if (lpfc_sli4_set_beacon(vport, lcb_context, state)) {
lpfc_printf_vlog(ndlp->vport, KERN_ERR,
LOG_ELS, "0193 failed to send mail box");
+ kfree(lcb_context);
lpfc_nlp_put(ndlp);
rjt_err = LSRJT_UNABLE_TPC;
goto rjt;
@@ -5444,7 +5414,7 @@ lpfc_send_rscn_event(struct lpfc_vport *vport,
fc_host_post_vendor_event(shost,
fc_get_event_number(),
- sizeof(struct lpfc_els_event_header) + payload_len,
+ sizeof(struct lpfc_rscn_event_header) + payload_len,
(char *)rscn_event_data,
LPFC_NL_VENDOR_ID);
@@ -5481,13 +5451,11 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *pcmd;
uint32_t *lp, *datap;
- IOCB_t *icmd;
uint32_t payload_len, length, nportid, *cmd;
int rscn_cnt;
int rscn_id = 0, hba_id = 0;
int i;
- icmd = &cmdiocb->iocb;
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt;
@@ -5893,6 +5861,13 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 1;
}
+ /* send our FLOGI first */
+ if (vport->port_state < LPFC_FLOGI) {
+ vport->fc_myDID = 0;
+ lpfc_initial_flogi(vport);
+ vport->fc_myDID = Fabric_DID;
+ }
+
/* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
@@ -5943,12 +5918,10 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
{
struct lpfc_dmabuf *pcmd;
uint32_t *lp;
- IOCB_t *icmd;
RNID *rn;
struct ls_rjt stat;
uint32_t cmd;
- icmd = &cmdiocb->iocb;
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt;
@@ -6259,7 +6232,6 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
{
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mbox;
- struct lpfc_dmabuf *pcmd;
struct ls_rjt stat;
if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
@@ -6267,8 +6239,6 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
/* reject the unsolicited RPS request and done with it */
goto reject_out;
- pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
if (mbox) {
lpfc_read_lnk_stat(phba, mbox);
@@ -6482,7 +6452,6 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
{
struct lpfc_hba *phba = vport->phba;
struct RRQ *els_rrq;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
uint8_t *pcmd;
uint16_t cmdsize;
@@ -6501,7 +6470,6 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!elsiocb)
return 1;
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
/* For RRQ request, remainder of payload is Exchange IDs */
@@ -7374,6 +7342,15 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
"Data: x%x x%x x%x x%x\n",
cmd, did, vport->port_state, vport->fc_flag,
vport->fc_myDID, vport->fc_prevDID);
+
+ /* reject till our FLOGI completes */
+ if ((vport->port_state < LPFC_FABRIC_CFG_LINK) &&
+ (cmd != ELS_CMD_FLOGI)) {
+ rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
+ goto lsrjt;
+ }
+
switch (cmd) {
case ELS_CMD_PLOGI:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -7411,20 +7388,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
rjt_exp = LSEXP_NOTHING_MORE;
break;
}
- /* We get here, and drop thru, if we are PT2PT with
- * another NPort and the other side has initiated
- * the PLOGI before responding to our FLOGI.
- */
- if (phba->sli_rev == LPFC_SLI_REV4 &&
- (phba->fc_topology_changed ||
- vport->fc_myDID != vport->fc_prevDID)) {
- lpfc_unregister_fcf_prep(phba);
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~FC_VFI_REGISTERED;
- spin_unlock_irq(shost->host_lock);
- phba->fc_topology_changed = 0;
- lpfc_issue_reg_vfi(vport);
- }
}
spin_lock_irq(shost->host_lock);
@@ -7655,6 +7618,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
break;
}
+lsrjt:
/* check if need to LS_RJT received ELS cmd */
if (rjt_err) {
memset(&stat, 0, sizeof(stat));
@@ -8428,7 +8392,6 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
- IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
uint8_t *pcmd;
uint16_t cmdsize;
@@ -8439,7 +8402,6 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (!elsiocb)
return 1;
- icmd = &elsiocb->iocb;
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
pcmd += sizeof(uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 759cbebed7c7..bfc2442dd74a 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -800,7 +800,6 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp, *next_ndlp;
- int rc;
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
if (!NLP_CHK_NODE_ACT(ndlp))
@@ -816,10 +815,10 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
if ((phba->sli_rev < LPFC_SLI_REV4) &&
(!remove && ndlp->nlp_type & NLP_FABRIC))
continue;
- rc = lpfc_disc_state_machine(vport, ndlp, NULL,
- remove
- ? NLP_EVT_DEVICE_RM
- : NLP_EVT_DEVICE_RECOVERY);
+ lpfc_disc_state_machine(vport, ndlp, NULL,
+ remove
+ ? NLP_EVT_DEVICE_RM
+ : NLP_EVT_DEVICE_RECOVERY);
}
if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
if (phba->sli_rev == LPFC_SLI_REV4)
@@ -1774,7 +1773,6 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
uint16_t *next_fcf_index)
{
void *virt_addr;
- dma_addr_t phys_addr;
struct lpfc_mbx_sge sge;
struct lpfc_mbx_read_fcf_tbl *read_fcf;
uint32_t shdr_status, shdr_add_status, if_type;
@@ -1785,7 +1783,6 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
* routine only uses a single SGE.
*/
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
- phys_addr = getPaddr(sge.pa_hi, sge.pa_lo);
if (unlikely(!mboxq->sge_array)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
"2524 Failed to get the non-embedded SGE "
@@ -2977,7 +2974,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
MAILBOX_t *mb = &pmb->u.mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
struct lpfc_vport *vport = pmb->vport;
-
+ struct serv_parm *sp = &vport->fc_sparam;
+ uint32_t ed_tov;
/* Check for error */
if (mb->mbxStatus) {
@@ -2992,6 +2990,18 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt,
sizeof (struct serv_parm));
+
+ ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
+ if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
+ ed_tov = (ed_tov + 999999) / 1000000;
+
+ phba->fc_edtov = ed_tov;
+ phba->fc_ratov = (2 * ed_tov) / 1000;
+ if (phba->fc_ratov < FF_DEF_RATOV) {
+ /* RA_TOV should be atleast 10sec for initial flogi */
+ phba->fc_ratov = FF_DEF_RATOV;
+ }
+
lpfc_update_vport_wwn(vport);
if (vport->port_type == LPFC_PHYSICAL_PORT) {
memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn));
@@ -3032,6 +3042,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
case LPFC_LINK_SPEED_8GHZ:
case LPFC_LINK_SPEED_10GHZ:
case LPFC_LINK_SPEED_16GHZ:
+ case LPFC_LINK_SPEED_32GHZ:
phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la);
break;
default:
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 892c5257d87c..2cce88e967ce 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -33,7 +33,7 @@
#define FF_DEF_EDTOV 2000 /* Default E_D_TOV (2000ms) */
#define FF_DEF_ALTOV 15 /* Default AL_TIME (15ms) */
-#define FF_DEF_RATOV 2 /* Default RA_TOV (2s) */
+#define FF_DEF_RATOV 10 /* Default RA_TOV (10s) */
#define FF_DEF_ARBTOV 1900 /* Default ARB_TOV (1900ms) */
#define LPFC_BUF_RING0 64 /* Number of buffers to post to RING
@@ -1400,6 +1400,7 @@ struct lpfc_fdmi_reg_portattr {
#define PCI_DEVICE_ID_LANCER_FC_VF 0xe208
#define PCI_DEVICE_ID_LANCER_FCOE 0xe260
#define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268
+#define PCI_DEVICE_ID_LANCER_G6_FC 0xe300
#define PCI_DEVICE_ID_SAT_SMB 0xf011
#define PCI_DEVICE_ID_SAT_MID 0xf015
#define PCI_DEVICE_ID_RFLY 0xf095
@@ -2075,6 +2076,7 @@ typedef struct {
#define LINK_SPEED_8G 0x8 /* 8 Gigabaud */
#define LINK_SPEED_10G 0x10 /* 10 Gigabaud */
#define LINK_SPEED_16G 0x11 /* 16 Gigabaud */
+#define LINK_SPEED_32G 0x14 /* 32 Gigabaud */
} INIT_LINK_VAR;
@@ -2246,6 +2248,7 @@ typedef struct {
#define LMT_8Gb 0x080
#define LMT_10Gb 0x100
#define LMT_16Gb 0x200
+#define LMT_32Gb 0x400
uint32_t rsvd2;
uint32_t rsvd3;
uint32_t max_xri;
@@ -2727,6 +2730,7 @@ struct lpfc_mbx_read_top {
#define LPFC_LINK_SPEED_8GHZ 0x20
#define LPFC_LINK_SPEED_10GHZ 0x40
#define LPFC_LINK_SPEED_16GHZ 0x80
+#define LPFC_LINK_SPEED_32GHZ 0x90
};
/* Structure for MB Command CLEAR_LA (22) */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index f962118da8ed..db9446c612da 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -699,7 +699,9 @@ lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology,
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G) &&
!(phba->lmt & LMT_10Gb)) ||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) &&
- !(phba->lmt & LMT_16Gb))) {
+ !(phba->lmt & LMT_16Gb)) ||
+ ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_32G) &&
+ !(phba->lmt & LMT_32Gb))) {
/* Reset link speed to auto */
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"1302 Invalid speed for this board:%d "
@@ -2035,7 +2037,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
&& descp && descp[0] != '\0')
return;
- if (phba->lmt & LMT_16Gb)
+ if (phba->lmt & LMT_32Gb)
+ max_speed = 32;
+ else if (phba->lmt & LMT_16Gb)
max_speed = 16;
else if (phba->lmt & LMT_10Gb)
max_speed = 10;
@@ -2229,6 +2233,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
m = (typeof(m)){"OCe15100", "PCIe",
"Obsolete, Unsupported FCoE"};
break;
+ case PCI_DEVICE_ID_LANCER_G6_FC:
+ m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"};
+ break;
case PCI_DEVICE_ID_SKYHAWK:
case PCI_DEVICE_ID_SKYHAWK_VF:
oneConnect = 1;
@@ -2253,7 +2260,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
phba->Port);
else if (max_speed == 0)
snprintf(descp, 255,
- "Emulex %s %s %s ",
+ "Emulex %s %s %s",
m.name, m.bus, m.function);
else
snprintf(descp, 255,
@@ -3491,6 +3498,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
sizeof fc_host_symbolic_name(shost));
fc_host_supported_speeds(shost) = 0;
+ if (phba->lmt & LMT_32Gb)
+ fc_host_supported_speeds(shost) |= FC_PORTSPEED_32GBIT;
if (phba->lmt & LMT_16Gb)
fc_host_supported_speeds(shost) |= FC_PORTSPEED_16GBIT;
if (phba->lmt & LMT_10Gb)
@@ -3854,6 +3863,9 @@ lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code,
case LPFC_FC_LA_SPEED_16G:
port_speed = 16000;
break;
+ case LPFC_FC_LA_SPEED_32G:
+ port_speed = 32000;
+ break;
default:
port_speed = 0;
}
@@ -4982,8 +4994,7 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
}
if (!phba->sli.ring)
- phba->sli.ring = (struct lpfc_sli_ring *)
- kzalloc(LPFC_SLI3_MAX_RING *
+ phba->sli.ring = kzalloc(LPFC_SLI3_MAX_RING *
sizeof(struct lpfc_sli_ring), GFP_KERNEL);
if (!phba->sli.ring)
return -ENOMEM;
@@ -4995,7 +5006,7 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
/* Initialize the host templates the configured values. */
lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
- lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+ lpfc_template_s3.sg_tablesize = phba->cfg_sg_seg_cnt;
/* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */
if (phba->cfg_enable_bg) {
@@ -8679,7 +8690,6 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
#ifdef CONFIG_X86
struct cpuinfo_x86 *cpuinfo;
#endif
- struct cpumask *mask;
uint8_t chann[LPFC_FCP_IO_CHAN_MAX+1];
/* If there is no mapping, just return */
@@ -8773,11 +8783,8 @@ found:
first_cpu = cpu;
/* Now affinitize to the selected CPU */
- mask = &cpup->maskbits;
- cpumask_clear(mask);
- cpumask_set_cpu(cpu, mask);
i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx].
- vector, mask);
+ vector, get_cpu_mask(cpu));
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"3330 Set Affinity: CPU %d channel %d "
@@ -10287,7 +10294,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
struct lpfc_hba *phba;
struct lpfc_vport *vport = NULL;
struct Scsi_Host *shost = NULL;
- int error, ret;
+ int error;
uint32_t cfg_mode, intr_mode;
int adjusted_fcp_io_channel;
@@ -10411,7 +10418,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
/* check for firmware upgrade or downgrade */
if (phba->cfg_request_firmware_upgrade)
- ret = lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
+ lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
/* Check if there are static vports to be created. */
lpfc_create_static_vport(phba);
@@ -11354,6 +11361,8 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
+ PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
@@ -11477,6 +11486,7 @@ lpfc_exit(void)
free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order);
}
kfree(lpfc_used_cpu);
+ idr_destroy(&lpfc_hba_index);
}
module_init(lpfc_init);
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 4abb93a83e0f..f87f90e9b7df 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -289,9 +289,7 @@ lpfc_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb,
struct lpfc_dmabuf *mp)
{
MAILBOX_t *mb;
- struct lpfc_sli *psli;
- psli = &phba->sli;
mb = &pmb->u.mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
@@ -483,13 +481,11 @@ lpfc_init_link(struct lpfc_hba * phba,
LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
{
lpfc_vpd_t *vpd;
- struct lpfc_sli *psli;
MAILBOX_t *mb;
mb = &pmb->u.mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
- psli = &phba->sli;
switch (topology) {
case FLAGS_TOPOLOGY_MODE_LOOP_PT:
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
@@ -510,6 +506,13 @@ lpfc_init_link(struct lpfc_hba * phba,
break;
}
+ if (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
+ mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
+ /* Failover is not tried for Lancer G6 */
+ mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
+ phba->cfg_topology = FLAGS_TOPOLOGY_MODE_PT_PT;
+ }
+
/* Enable asynchronous ABTS responses from firmware */
mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
@@ -543,6 +546,10 @@ lpfc_init_link(struct lpfc_hba * phba,
mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
mb->un.varInitLnk.link_speed = LINK_SPEED_16G;
break;
+ case LPFC_USER_LINK_SPEED_32G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_32G;
+ break;
case LPFC_USER_LINK_SPEED_AUTO:
default:
mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
@@ -585,9 +592,7 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
{
struct lpfc_dmabuf *mp;
MAILBOX_t *mb;
- struct lpfc_sli *psli;
- psli = &phba->sli;
mb = &pmb->u.mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
@@ -2010,7 +2015,6 @@ lpfc_sli4_mbx_read_fcf_rec(struct lpfc_hba *phba,
uint16_t fcf_index)
{
void *virt_addr;
- dma_addr_t phys_addr;
uint8_t *bytep;
struct lpfc_mbx_sge sge;
uint32_t alloc_len, req_len;
@@ -2039,7 +2043,6 @@ lpfc_sli4_mbx_read_fcf_rec(struct lpfc_hba *phba,
* routine only uses a single SGE.
*/
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
- phys_addr = getPaddr(sge.pa_hi, sge.pa_lo);
virt_addr = mboxq->sge_array->addr[0];
read_fcf = (struct lpfc_mbx_read_fcf_tbl *)virt_addr;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index af3b38aba65e..ed9a2c80c4aa 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -820,7 +820,6 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
{
struct lpfc_hba *phba;
LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
- MAILBOX_t *mb;
uint16_t rpi;
phba = vport->phba;
@@ -828,7 +827,6 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!(phba->pport->load_flag & FC_UNLOADING) &&
(evt == NLP_EVT_CMPL_REG_LOGIN) &&
(!pmb->u.mb.mbxStatus)) {
- mb = &pmb->u.mb;
rpi = pmb->u.mb.un.varWords[0];
lpfc_release_rpi(phba, vport, rpi);
}
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index e5eb40d2c512..4679ed4444a7 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1293,7 +1293,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
uint32_t *reftag, uint16_t *apptag, uint32_t new_guard)
{
struct scatterlist *sgpe; /* s/g prot entry */
- struct scatterlist *sgde; /* s/g data entry */
struct lpfc_scsi_buf *lpfc_cmd = NULL;
struct scsi_dif_tuple *src = NULL;
struct lpfc_nodelist *ndlp;
@@ -1309,7 +1308,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
return 0;
sgpe = scsi_prot_sglist(sc);
- sgde = scsi_sglist(sc);
lba = scsi_get_lba(sc);
/* First check if we need to match the LBA */
@@ -1882,7 +1880,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
#endif
uint32_t checking = 1;
uint32_t reftag;
- unsigned blksize;
uint8_t txop, rxop;
status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
@@ -1890,7 +1887,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
goto out;
/* extract some info from the scsi command for pde*/
- blksize = lpfc_cmd_blksize(sc);
reftag = (uint32_t)scsi_get_lba(sc); /* Truncate LBA */
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -2263,7 +2259,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
dma_addr_t physaddr;
int i = 0, num_sge = 0, status;
uint32_t reftag;
- unsigned blksize;
uint8_t txop, rxop;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t rc;
@@ -2277,7 +2272,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
goto out;
/* extract some info from the scsi command for pde*/
- blksize = lpfc_cmd_blksize(sc);
reftag = (uint32_t)scsi_get_lba(sc); /* Truncate LBA */
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -2881,7 +2875,7 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
struct scsi_dif_tuple *src = NULL;
uint8_t *data_src = NULL;
- uint16_t guard_tag, guard_type;
+ uint16_t guard_tag;
uint16_t start_app_tag, app_tag;
uint32_t start_ref_tag, ref_tag;
int prot, protsegcnt;
@@ -2922,7 +2916,6 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
data_len = sgde->length;
if ((data_len & (blksize - 1)) == 0)
chk_guard = 1;
- guard_type = scsi_host_get_guard(cmd->device->host);
src = (struct scsi_dif_tuple *)sg_virt(sgpe);
start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */
@@ -3908,12 +3901,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd;
- int result;
int depth;
unsigned long flags;
struct lpfc_fast_path_event *fast_path_evt;
struct Scsi_Host *shost;
- uint32_t queue_depth, scsi_id;
uint32_t logit = LOG_FCP;
/* Sanity check on return of outstanding command */
@@ -4095,7 +4086,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
lpfc_update_stats(phba, lpfc_cmd);
- result = cmd->result;
if (vport->cfg_max_scsicmpl_time &&
time_after(jiffies, lpfc_cmd->start_time +
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
@@ -4132,8 +4122,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
- queue_depth = cmd->device->queue_depth;
- scsi_id = cmd->device->id;
cmd->scsi_done(cmd);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
@@ -5926,7 +5914,6 @@ struct scsi_host_template lpfc_template_s3 = {
.max_sectors = 0xFFFF,
.vendor_id = LPFC_NL_VENDOR_ID,
.change_queue_depth = scsi_change_queue_depth,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -5952,7 +5939,6 @@ struct scsi_host_template lpfc_template = {
.max_sectors = 0xFFFF,
.vendor_id = LPFC_NL_VENDOR_ID,
.change_queue_depth = scsi_change_queue_depth,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -5976,6 +5962,5 @@ struct scsi_host_template lpfc_vport_template = {
.shost_attrs = lpfc_vport_attrs,
.max_sectors = 0xFFFF,
.change_queue_depth = scsi_change_queue_depth,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 4feb9312a447..f9585cdd8933 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -6696,7 +6696,7 @@ lpfc_mbox_timeout(unsigned long ptr)
* This function checks if any mailbox completions are present on the mailbox
* completion queue.
**/
-bool
+static bool
lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba)
{
@@ -12491,12 +12491,10 @@ lpfc_sli4_fof_intr_handler(int irq, void *dev_id)
struct lpfc_eqe *eqe;
unsigned long iflag;
int ecount = 0;
- uint32_t eqidx;
/* Get the driver's phba structure from the dev_id */
fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)dev_id;
phba = fcp_eq_hdl->phba;
- eqidx = fcp_eq_hdl->idx;
if (unlikely(!phba))
return IRQ_NONE;
@@ -12831,12 +12829,8 @@ out_fail:
static void __iomem *
lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
{
- struct pci_dev *pdev;
-
if (!phba->pcidev)
return NULL;
- else
- pdev = phba->pcidev;
switch (pci_barset) {
case WQ_PCI_BAR_0_AND_1:
@@ -15920,7 +15914,6 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record)
LPFC_MBOXQ_t *mboxq;
uint8_t *bytep;
void *virt_addr;
- dma_addr_t phys_addr;
struct lpfc_mbx_sge sge;
uint32_t alloc_len, req_len;
uint32_t fcfindex;
@@ -15953,7 +15946,6 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record)
* routine only uses a single SGE.
*/
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
- phys_addr = getPaddr(sge.pa_hi, sge.pa_lo);
virt_addr = mboxq->sge_array->addr[0];
/*
* Configure the FCF record for FCFI 0. This is the driver's
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index d1a5b057c6f3..1e916e16ce98 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -454,7 +454,6 @@ struct lpfc_vector_map_info {
uint16_t core_id;
uint16_t irq;
uint16_t channel_id;
- struct cpumask maskbits;
};
#define LPFC_VECTOR_MAP_EMPTY 0xffff
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 6258d3d7722a..ea53aa664759 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "10.7.0.0."
+#define LPFC_DRIVER_VERSION "11.0.0.0."
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 20c37541963f..c0f7c8ce54aa 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -35,8 +35,8 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "06.807.10.00-rc1"
-#define MEGASAS_RELDATE "March 6, 2015"
+#define MEGASAS_VERSION "06.808.16.00-rc1"
+#define MEGASAS_RELDATE "Oct. 8, 2015"
/*
* Device IDs
@@ -52,6 +52,10 @@
#define PCI_DEVICE_ID_LSI_PLASMA 0x002f
#define PCI_DEVICE_ID_LSI_INVADER 0x005d
#define PCI_DEVICE_ID_LSI_FURY 0x005f
+#define PCI_DEVICE_ID_LSI_INTRUDER 0x00ce
+#define PCI_DEVICE_ID_LSI_INTRUDER_24 0x00cf
+#define PCI_DEVICE_ID_LSI_CUTLASS_52 0x0052
+#define PCI_DEVICE_ID_LSI_CUTLASS_53 0x0053
/*
* Intel HBA SSDIDs
@@ -62,6 +66,14 @@
#define MEGARAID_INTEL_RS3MC044_SSDID 0x9381
#define MEGARAID_INTEL_RS3WC080_SSDID 0x9341
#define MEGARAID_INTEL_RS3WC040_SSDID 0x9343
+#define MEGARAID_INTEL_RMS3BC160_SSDID 0x352B
+
+/*
+ * Intruder HBA SSDIDs
+ */
+#define MEGARAID_INTRUDER_SSDID1 0x9371
+#define MEGARAID_INTRUDER_SSDID2 0x9390
+#define MEGARAID_INTRUDER_SSDID3 0x9370
/*
* Intel HBA branding
@@ -78,6 +90,8 @@
"Intel(R) RAID Controller RS3WC080"
#define MEGARAID_INTEL_RS3WC040_BRANDING \
"Intel(R) RAID Controller RS3WC040"
+#define MEGARAID_INTEL_RMS3BC160_BRANDING \
+ "Intel(R) Integrated RAID Module RMS3BC160"
/*
* =====================================
@@ -273,6 +287,16 @@ enum MFI_STAT {
MFI_STAT_INVALID_STATUS = 0xFF
};
+enum mfi_evt_class {
+ MFI_EVT_CLASS_DEBUG = -2,
+ MFI_EVT_CLASS_PROGRESS = -1,
+ MFI_EVT_CLASS_INFO = 0,
+ MFI_EVT_CLASS_WARNING = 1,
+ MFI_EVT_CLASS_CRITICAL = 2,
+ MFI_EVT_CLASS_FATAL = 3,
+ MFI_EVT_CLASS_DEAD = 4
+};
+
/*
* Crash dump related defines
*/
@@ -364,6 +388,8 @@ enum MR_EVT_ARGS {
MR_EVT_ARGS_GENERIC,
};
+
+#define SGE_BUFFER_SIZE 4096
/*
* define constants for device list query options
*/
@@ -394,6 +420,7 @@ enum MR_LD_QUERY_TYPE {
#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
#define MR_EVT_LD_OFFLINE 0x00fc
#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
+#define MR_EVT_CTRL_PROP_CHANGED 0x012f
enum MR_PD_STATE {
MR_PD_STATE_UNCONFIGURED_GOOD = 0x00,
@@ -973,7 +1000,12 @@ struct megasas_ctrl_info {
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
- u32 reserved:12;
+ u32 reserved:7;
+ u32 useSeqNumJbodFP:1;
+ u32 supportExtendedSSCSize:1;
+ u32 supportDiskCacheSettingForSysPDs:1;
+ u32 supportCPLDUpdate:1;
+ u32 supportTTYLogCompression:1;
u32 discardCacheDuringLDDelete:1;
u32 supportSecurityonJBOD:1;
u32 supportCacheBypassModes:1;
@@ -1013,7 +1045,12 @@ struct megasas_ctrl_info {
u32 supportCacheBypassModes:1;
u32 supportSecurityonJBOD:1;
u32 discardCacheDuringLDDelete:1;
- u32 reserved:12;
+ u32 supportTTYLogCompression:1;
+ u32 supportCPLDUpdate:1;
+ u32 supportDiskCacheSettingForSysPDs:1;
+ u32 supportExtendedSSCSize:1;
+ u32 useSeqNumJbodFP:1;
+ u32 reserved:7;
#endif
} adapterOperations3;
@@ -1229,7 +1266,9 @@ union megasas_sgl_frame {
typedef union _MFI_CAPABILITIES {
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
- u32 reserved:25;
+ u32 reserved:23;
+ u32 support_ext_io_size:1;
+ u32 support_ext_queue_depth:1;
u32 security_protocol_cmds_fw:1;
u32 support_core_affinity:1;
u32 support_ndrive_r1_lb:1;
@@ -1245,7 +1284,9 @@ typedef union _MFI_CAPABILITIES {
u32 support_ndrive_r1_lb:1;
u32 support_core_affinity:1;
u32 security_protocol_cmds_fw:1;
- u32 reserved:25;
+ u32 support_ext_queue_depth:1;
+ u32 support_ext_io_size:1;
+ u32 reserved:23;
#endif
} mfi_capabilities;
__le32 reg;
@@ -1690,6 +1731,7 @@ struct megasas_instance {
u32 crash_dump_drv_support;
u32 crash_dump_app_support;
u32 secure_jbod_support;
+ bool use_seqnum_jbod_fp; /* Added for PD sequence */
spinlock_t crashdump_lock;
struct megasas_register_set __iomem *reg_set;
@@ -1748,6 +1790,7 @@ struct megasas_instance {
u8 UnevenSpanSupport;
u8 supportmax256vd;
+ u8 allow_fw_scan;
u16 fw_supported_vd_count;
u16 fw_supported_pd_count;
@@ -1769,7 +1812,9 @@ struct megasas_instance {
struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES];
struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
u64 map_id;
+ u64 pd_seq_map_id;
struct megasas_cmd *map_update_cmd;
+ struct megasas_cmd *jbod_seq_cmd;
unsigned long bar;
long reset_flags;
struct mutex reset_mutex;
@@ -1780,6 +1825,7 @@ struct megasas_instance {
char mpio;
u16 throttlequeuedepth;
u8 mask_interrupts;
+ u16 max_chain_frame_sz;
u8 is_imr;
bool dev_handle;
};
@@ -1985,6 +2031,9 @@ __le16 get_updated_dev_handle(struct megasas_instance *instance,
void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo);
int megasas_get_ctrl_info(struct megasas_instance *instance);
+/* PD sequence */
+int
+megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend);
int megasas_set_crash_dump_params(struct megasas_instance *instance,
u8 crash_buf_state);
void megasas_free_host_crash_buffer(struct megasas_instance *instance);
@@ -2000,5 +2049,6 @@ void __megasas_return_cmd(struct megasas_instance *instance,
void megasas_return_mfi_mpt_pthr(struct megasas_instance *instance,
struct megasas_cmd *cmd_mfi, struct megasas_cmd_fusion *cmd_fusion);
int megasas_cmd_type(struct scsi_cmnd *cmd);
+void megasas_setup_jbod_map(struct megasas_instance *instance);
#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index eaa81e552fd2..97a1c1c33b05 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -135,6 +135,12 @@ static struct pci_device_id megasas_pci_table[] = {
/* Invader */
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)},
/* Fury */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INTRUDER)},
+ /* Intruder */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INTRUDER_24)},
+ /* Intruder 24 port*/
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_52)},
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_53)},
{}
};
@@ -260,6 +266,66 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
}
+static const char *
+format_timestamp(uint32_t timestamp)
+{
+ static char buffer[32];
+
+ if ((timestamp & 0xff000000) == 0xff000000)
+ snprintf(buffer, sizeof(buffer), "boot + %us", timestamp &
+ 0x00ffffff);
+ else
+ snprintf(buffer, sizeof(buffer), "%us", timestamp);
+ return buffer;
+}
+
+static const char *
+format_class(int8_t class)
+{
+ static char buffer[6];
+
+ switch (class) {
+ case MFI_EVT_CLASS_DEBUG:
+ return "debug";
+ case MFI_EVT_CLASS_PROGRESS:
+ return "progress";
+ case MFI_EVT_CLASS_INFO:
+ return "info";
+ case MFI_EVT_CLASS_WARNING:
+ return "WARN";
+ case MFI_EVT_CLASS_CRITICAL:
+ return "CRIT";
+ case MFI_EVT_CLASS_FATAL:
+ return "FATAL";
+ case MFI_EVT_CLASS_DEAD:
+ return "DEAD";
+ default:
+ snprintf(buffer, sizeof(buffer), "%d", class);
+ return buffer;
+ }
+}
+
+/**
+ * megasas_decode_evt: Decode FW AEN event and print critical event
+ * for information.
+ * @instance: Adapter soft state
+ */
+static void
+megasas_decode_evt(struct megasas_instance *instance)
+{
+ struct megasas_evt_detail *evt_detail = instance->evt_detail;
+ union megasas_evt_class_locale class_locale;
+ class_locale.word = le32_to_cpu(evt_detail->cl.word);
+
+ if (class_locale.members.class >= MFI_EVT_CLASS_CRITICAL)
+ dev_info(&instance->pdev->dev, "%d (%s/0x%04x/%s) - %s\n",
+ le32_to_cpu(evt_detail->seq_num),
+ format_timestamp(le32_to_cpu(evt_detail->time_stamp)),
+ (class_locale.members.locale),
+ format_class(class_locale.members.class),
+ evt_detail->description);
+}
+
/**
* The following functions are defined for xscale
* (deviceid : 1064R, PERC5) controllers
@@ -1659,8 +1725,56 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no)
return NULL;
}
+/*
+* megasas_set_dma_alignment - Set DMA alignment for PI enabled VD
+*
+* @sdev: OS provided scsi device
+*
+* Returns void
+*/
+static void megasas_set_dma_alignment(struct scsi_device *sdev)
+{
+ u32 device_id, ld;
+ struct megasas_instance *instance;
+ struct fusion_context *fusion;
+ struct MR_LD_RAID *raid;
+ struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
+
+ instance = megasas_lookup_instance(sdev->host->host_no);
+ fusion = instance->ctrl_context;
+
+ if (!fusion)
+ return;
+
+ if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) {
+ device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL)
+ + sdev->id;
+ local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
+ ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
+ raid = MR_LdRaidGet(ld, local_map_ptr);
+
+ if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER)
+ blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
+ }
+}
+
static int megasas_slave_configure(struct scsi_device *sdev)
{
+ u16 pd_index = 0;
+ struct megasas_instance *instance;
+
+ instance = megasas_lookup_instance(sdev->host->host_no);
+ if (instance->allow_fw_scan) {
+ if (sdev->channel < MEGASAS_MAX_PD_CHANNELS &&
+ sdev->type == TYPE_DISK) {
+ pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
+ sdev->id;
+ if (instance->pd_list[pd_index].driveState !=
+ MR_PD_STATE_SYSTEM)
+ return -ENXIO;
+ }
+ }
+ megasas_set_dma_alignment(sdev);
/*
* The RAID firmware may require extended timeouts.
*/
@@ -1683,8 +1797,8 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
pd_index =
(sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
sdev->id;
- if (instance->pd_list[pd_index].driveState ==
- MR_PD_STATE_SYSTEM) {
+ if ((instance->allow_fw_scan || instance->pd_list[pd_index].driveState ==
+ MR_PD_STATE_SYSTEM)) {
return 0;
}
return -ENXIO;
@@ -1736,10 +1850,7 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
msleep(1000);
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ (instance->ctrl_context)) {
writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
/* Flush */
readl(&instance->reg_set->doorbell);
@@ -2506,10 +2617,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
/*
* First wait for all commands to complete
*/
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ if (instance->ctrl_context)
ret = megasas_reset_fusion(scmd->device->host, 1);
else
ret = megasas_generic_reset(scmd);
@@ -2837,7 +2945,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
struct megasas_header *hdr = &cmd->frame->hdr;
unsigned long flags;
struct fusion_context *fusion = instance->ctrl_context;
- u32 opcode;
+ u32 opcode, status;
/* flag for the retry reset */
cmd->retry_for_fw_reset = 0;
@@ -2945,6 +3053,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
&& (cmd->frame->dcmd.mbox.b[1] == 1)) {
fusion->fast_path_io = 0;
spin_lock_irqsave(instance->host->host_lock, flags);
+ instance->map_update_cmd = NULL;
if (cmd->frame->hdr.cmd_status != 0) {
if (cmd->frame->hdr.cmd_status !=
MFI_STAT_NOT_FOUND)
@@ -2982,6 +3091,27 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
spin_unlock_irqrestore(&poll_aen_lock, flags);
}
+ /* FW has an updated PD sequence */
+ if ((opcode == MR_DCMD_SYSTEM_PD_MAP_GET_INFO) &&
+ (cmd->frame->dcmd.mbox.b[0] == 1)) {
+
+ spin_lock_irqsave(instance->host->host_lock, flags);
+ status = cmd->frame->hdr.cmd_status;
+ instance->jbod_seq_cmd = NULL;
+ megasas_return_cmd(instance, cmd);
+
+ if (status == MFI_STAT_OK) {
+ instance->pd_seq_map_id++;
+ /* Re-register a pd sync seq num cmd */
+ if (megasas_sync_pd_seq_num(instance, true))
+ instance->use_seqnum_jbod_fp = false;
+ } else
+ instance->use_seqnum_jbod_fp = false;
+
+ spin_unlock_irqrestore(instance->host->host_lock, flags);
+ break;
+ }
+
/*
* See if got an event notification
*/
@@ -3348,22 +3478,14 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FURY)) {
+ (instance->ctrl_context))
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
- } else {
+ else
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
&instance->reg_set->inbound_doorbell);
- }
max_wait = MEGASAS_RESET_WAIT_TIME;
cur_state = MFI_STATE_WAIT_HANDSHAKE;
@@ -3374,17 +3496,10 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FURY)) {
+ (instance->ctrl_context))
writel(MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
- } else
+ else
writel(MFI_INIT_HOTPLUG,
&instance->reg_set->inbound_doorbell);
@@ -3401,24 +3516,11 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device
- == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device
- == PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device
- == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device
- == PCI_DEVICE_ID_LSI_FURY)) {
+ (instance->ctrl_context)) {
writel(MFI_RESET_FLAGS,
&instance->reg_set->doorbell);
- if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FURY)) {
+
+ if (instance->ctrl_context) {
for (i = 0; i < (10 * 1000); i += 20) {
if (readl(
&instance->
@@ -3639,11 +3741,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
memset(cmd->frame, 0, total_sz);
cmd->frame->io.context = cpu_to_le32(cmd->index);
cmd->frame->io.pad_0 = 0;
- if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
- (instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) &&
- (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
- (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
- (reset_devices))
+ if (!instance->ctrl_context && reset_devices)
cmd->frame->hdr.cmd = MFI_CMD_INVALID;
}
@@ -4136,11 +4234,21 @@ megasas_get_ctrl_info(struct megasas_instance *instance)
le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
megasas_update_ext_vd_details(instance);
+ instance->use_seqnum_jbod_fp =
+ ctrl_info->adapterOperations3.useSeqNumJbodFP;
instance->is_imr = (ctrl_info->memory_size ? 0 : 1);
dev_info(&instance->pdev->dev,
"controller type\t: %s(%dMB)\n",
instance->is_imr ? "iMR" : "MR",
le16_to_cpu(ctrl_info->memory_size));
+ instance->disableOnlineCtrlReset =
+ ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
+ dev_info(&instance->pdev->dev, "Online Controller Reset(OCR)\t: %s\n",
+ instance->disableOnlineCtrlReset ? "Disabled" : "Enabled");
+ instance->secure_jbod_support =
+ ctrl_info->adapterOperations3.supportSecurityonJBOD;
+ dev_info(&instance->pdev->dev, "Secure JBOD support\t: %s\n",
+ instance->secure_jbod_support ? "Yes" : "No");
}
pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
@@ -4481,6 +4589,62 @@ megasas_destroy_irqs(struct megasas_instance *instance) {
}
/**
+ * megasas_setup_jbod_map - setup jbod map for FP seq_number.
+ * @instance: Adapter soft state
+ * @is_probe: Driver probe check
+ *
+ * Return 0 on success.
+ */
+void
+megasas_setup_jbod_map(struct megasas_instance *instance)
+{
+ int i;
+ struct fusion_context *fusion = instance->ctrl_context;
+ u32 pd_seq_map_sz;
+
+ pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
+ (sizeof(struct MR_PD_CFG_SEQ) * (MAX_PHYSICAL_DEVICES - 1));
+
+ if (reset_devices || !fusion ||
+ !instance->ctrl_info->adapterOperations3.useSeqNumJbodFP) {
+ dev_info(&instance->pdev->dev,
+ "Jbod map is not supported %s %d\n",
+ __func__, __LINE__);
+ instance->use_seqnum_jbod_fp = false;
+ return;
+ }
+
+ if (fusion->pd_seq_sync[0])
+ goto skip_alloc;
+
+ for (i = 0; i < JBOD_MAPS_COUNT; i++) {
+ fusion->pd_seq_sync[i] = dma_alloc_coherent
+ (&instance->pdev->dev, pd_seq_map_sz,
+ &fusion->pd_seq_phys[i], GFP_KERNEL);
+ if (!fusion->pd_seq_sync[i]) {
+ dev_err(&instance->pdev->dev,
+ "Failed to allocate memory from %s %d\n",
+ __func__, __LINE__);
+ if (i == 1) {
+ dma_free_coherent(&instance->pdev->dev,
+ pd_seq_map_sz, fusion->pd_seq_sync[0],
+ fusion->pd_seq_phys[0]);
+ fusion->pd_seq_sync[0] = NULL;
+ }
+ instance->use_seqnum_jbod_fp = false;
+ return;
+ }
+ }
+
+skip_alloc:
+ if (!megasas_sync_pd_seq_num(instance, false) &&
+ !megasas_sync_pd_seq_num(instance, true))
+ instance->use_seqnum_jbod_fp = true;
+ else
+ instance->use_seqnum_jbod_fp = false;
+}
+
+/**
* megasas_init_fw - Initializes the FW
* @instance: Adapter soft state
*
@@ -4498,6 +4662,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
unsigned long bar_list;
int i, loop, fw_msix_count = 0;
struct IOV_111 *iovPtr;
+ struct fusion_context *fusion;
+
+ fusion = instance->ctrl_context;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
@@ -4523,6 +4690,10 @@ static int megasas_init_fw(struct megasas_instance *instance)
case PCI_DEVICE_ID_LSI_PLASMA:
case PCI_DEVICE_ID_LSI_INVADER:
case PCI_DEVICE_ID_LSI_FURY:
+ case PCI_DEVICE_ID_LSI_INTRUDER:
+ case PCI_DEVICE_ID_LSI_INTRUDER_24:
+ case PCI_DEVICE_ID_LSI_CUTLASS_52:
+ case PCI_DEVICE_ID_LSI_CUTLASS_53:
instance->instancet = &megasas_instance_template_fusion;
break;
case PCI_DEVICE_ID_LSI_SAS1078R:
@@ -4541,6 +4712,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
case PCI_DEVICE_ID_DELL_PERC5:
default:
instance->instancet = &megasas_instance_template_xscale;
+ instance->allow_fw_scan = 1;
break;
}
@@ -4575,37 +4747,32 @@ static int megasas_init_fw(struct megasas_instance *instance)
scratch_pad_2 = readl
(&instance->reg_set->outbound_scratch_pad_2);
/* Check max MSI-X vectors */
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) {
- instance->msix_vectors = (scratch_pad_2
- & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
- fw_msix_count = instance->msix_vectors;
- if (msix_vectors)
- instance->msix_vectors =
- min(msix_vectors,
- instance->msix_vectors);
- } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
- || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
- /* Invader/Fury supports more than 8 MSI-X */
- instance->msix_vectors = ((scratch_pad_2
- & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
- >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
- fw_msix_count = instance->msix_vectors;
- /* Save 1-15 reply post index address to local memory
- * Index 0 is already saved from reg offset
- * MPI2_REPLY_POST_HOST_INDEX_OFFSET
- */
- for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
- instance->reply_post_host_index_addr[loop] =
- (u32 __iomem *)
- ((u8 __iomem *)instance->reg_set +
- MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
- + (loop * 0x10));
+ if (fusion) {
+ if (fusion->adapter_type == THUNDERBOLT_SERIES) { /* Thunderbolt Series*/
+ instance->msix_vectors = (scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+ fw_msix_count = instance->msix_vectors;
+ } else { /* Invader series supports more than 8 MSI-x vectors*/
+ instance->msix_vectors = ((scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
+ >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
+ fw_msix_count = instance->msix_vectors;
+ /* Save 1-15 reply post index address to local memory
+ * Index 0 is already saved from reg offset
+ * MPI2_REPLY_POST_HOST_INDEX_OFFSET
+ */
+ for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
+ instance->reply_post_host_index_addr[loop] =
+ (u32 __iomem *)
+ ((u8 __iomem *)instance->reg_set +
+ MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
+ + (loop * 0x10));
+ }
}
if (msix_vectors)
instance->msix_vectors = min(msix_vectors,
instance->msix_vectors);
- } else
+ } else /* MFI adapters */
instance->msix_vectors = 1;
/* Don't bother allocating more MSI-X vectors than cpus */
instance->msix_vectors = min(instance->msix_vectors,
@@ -4626,6 +4793,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
"current msix/online cpus\t: (%d/%d)\n",
instance->msix_vectors, (unsigned int)num_online_cpus());
+ tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+ (unsigned long)instance);
+
if (instance->msix_vectors ?
megasas_setup_irqs_msix(instance, 1) :
megasas_setup_irqs_ioapic(instance))
@@ -4646,13 +4816,13 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (instance->instancet->init_adapter(instance))
goto fail_init_adapter;
- tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
- (unsigned long)instance);
instance->instancet->enable_intr(instance);
dev_err(&instance->pdev->dev, "INIT adapter done\n");
+ megasas_setup_jbod_map(instance);
+
/** for passthrough
* the following function will get the PD LIST.
*/
@@ -4686,8 +4856,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
tmp_sectors = min_t(u32, max_sectors_1, max_sectors_2);
- instance->disableOnlineCtrlReset =
- ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
instance->mpio = ctrl_info->adapterOperations2.mpio;
instance->UnevenSpanSupport =
ctrl_info->adapterOperations2.supportUnevenSpans;
@@ -4700,18 +4868,22 @@ static int megasas_init_fw(struct megasas_instance *instance)
}
if (ctrl_info->host_interface.SRIOV) {
- if (!ctrl_info->adapterOperations2.activePassive)
- instance->PlasmaFW111 = 1;
-
- if (!instance->PlasmaFW111)
- instance->requestorId =
- ctrl_info->iov.requestorId;
- else {
- iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET);
- instance->requestorId = iovPtr->requestorId;
+ instance->requestorId = ctrl_info->iov.requestorId;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) {
+ if (!ctrl_info->adapterOperations2.activePassive)
+ instance->PlasmaFW111 = 1;
+
+ dev_info(&instance->pdev->dev, "SR-IOV: firmware type: %s\n",
+ instance->PlasmaFW111 ? "1.11" : "new");
+
+ if (instance->PlasmaFW111) {
+ iovPtr = (struct IOV_111 *)
+ ((unsigned char *)ctrl_info + IOV_111_OFFSET);
+ instance->requestorId = iovPtr->requestorId;
+ }
}
- dev_warn(&instance->pdev->dev, "I am VF "
- "requestorId %d\n", instance->requestorId);
+ dev_info(&instance->pdev->dev, "SRIOV: VF requestorId %d\n",
+ instance->requestorId);
}
instance->crash_dump_fw_support =
@@ -4732,8 +4904,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
instance->crash_dump_buf = NULL;
}
- instance->secure_jbod_support =
- ctrl_info->adapterOperations3.supportSecurityonJBOD;
dev_info(&instance->pdev->dev,
"pci id\t\t: (0x%04x)/(0x%04x)/(0x%04x)/(0x%04x)\n",
@@ -4743,16 +4913,14 @@ static int megasas_init_fw(struct megasas_instance *instance)
le16_to_cpu(ctrl_info->pci.sub_device_id));
dev_info(&instance->pdev->dev, "unevenspan support : %s\n",
instance->UnevenSpanSupport ? "yes" : "no");
- dev_info(&instance->pdev->dev, "disable ocr : %s\n",
- instance->disableOnlineCtrlReset ? "yes" : "no");
dev_info(&instance->pdev->dev, "firmware crash dump : %s\n",
instance->crash_dump_drv_support ? "yes" : "no");
- dev_info(&instance->pdev->dev, "secure jbod : %s\n",
- instance->secure_jbod_support ? "yes" : "no");
+ dev_info(&instance->pdev->dev, "jbod sync map : %s\n",
+ instance->use_seqnum_jbod_fp ? "yes" : "no");
instance->max_sectors_per_req = instance->max_num_sge *
- PAGE_SIZE / 512;
+ SGE_BUFFER_SIZE / 512;
if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
instance->max_sectors_per_req = tmp_sectors;
@@ -5049,7 +5217,6 @@ static int megasas_start_aen(struct megasas_instance *instance)
static int megasas_io_attach(struct megasas_instance *instance)
{
struct Scsi_Host *host = instance->host;
- u32 error;
/*
* Export parameters required by SCSI mid-layer
@@ -5092,20 +5259,10 @@ static int megasas_io_attach(struct megasas_instance *instance)
host->max_cmd_len = 16;
/* Fusion only supports host reset */
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (instance->ctrl_context) {
host->hostt->eh_device_reset_handler = NULL;
host->hostt->eh_bus_reset_handler = NULL;
}
- error = scsi_init_shared_tag_map(host, host->can_queue);
- if (error) {
- dev_err(&instance->pdev->dev,
- "Failed to shared tag from %s %d\n",
- __func__, __LINE__);
- return -ENODEV;
- }
/*
* Notify the mid-layer about the new controller
@@ -5218,6 +5375,10 @@ static int megasas_probe_one(struct pci_dev *pdev,
case PCI_DEVICE_ID_LSI_PLASMA:
case PCI_DEVICE_ID_LSI_INVADER:
case PCI_DEVICE_ID_LSI_FURY:
+ case PCI_DEVICE_ID_LSI_INTRUDER:
+ case PCI_DEVICE_ID_LSI_INTRUDER_24:
+ case PCI_DEVICE_ID_LSI_CUTLASS_52:
+ case PCI_DEVICE_ID_LSI_CUTLASS_53:
{
instance->ctrl_context_pages =
get_order(sizeof(struct fusion_context));
@@ -5231,6 +5392,11 @@ static int megasas_probe_one(struct pci_dev *pdev,
fusion = instance->ctrl_context;
memset(fusion, 0,
((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA))
+ fusion->adapter_type = THUNDERBOLT_SERIES;
+ else
+ fusion->adapter_type = INVADER_SERIES;
}
break;
default: /* For all other supported controllers */
@@ -5333,10 +5499,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
instance->disableOnlineCtrlReset = 1;
instance->UnevenSpanSupport = 0;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (instance->ctrl_context) {
INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
INIT_WORK(&instance->crash_init, megasas_fusion_crash_dump_wq);
} else
@@ -5416,10 +5579,7 @@ fail_io_attach:
instance->instancet->disable_intr(instance);
megasas_destroy_irqs(instance);
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ if (instance->ctrl_context)
megasas_release_fusion(instance);
else
megasas_release_mfi(instance);
@@ -5506,10 +5666,14 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
if (instance->aen_cmd)
megasas_issue_blocked_abort_cmd(instance,
- instance->aen_cmd, 30);
+ instance->aen_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT);
if (instance->map_update_cmd)
megasas_issue_blocked_abort_cmd(instance,
- instance->map_update_cmd, 30);
+ instance->map_update_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT);
+ if (instance->jbod_seq_cmd)
+ megasas_issue_blocked_abort_cmd(instance,
+ instance->jbod_seq_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT);
+
dcmd = &cmd->frame->dcmd;
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
@@ -5628,12 +5792,7 @@ megasas_resume(struct pci_dev *pdev)
instance->msix_vectors))
goto fail_reenable_msix;
- switch (instance->pdev->device) {
- case PCI_DEVICE_ID_LSI_FUSION:
- case PCI_DEVICE_ID_LSI_PLASMA:
- case PCI_DEVICE_ID_LSI_INVADER:
- case PCI_DEVICE_ID_LSI_FURY:
- {
+ if (instance->ctrl_context) {
megasas_reset_reply_desc(instance);
if (megasas_ioc_init_fusion(instance)) {
megasas_free_cmds(instance);
@@ -5642,14 +5801,11 @@ megasas_resume(struct pci_dev *pdev)
}
if (!megasas_get_map_info(instance))
megasas_sync_map_info(instance);
- }
- break;
- default:
+ } else {
*instance->producer = 0;
*instance->consumer = 0;
if (megasas_issue_init_mfi(instance))
goto fail_init_mfi;
- break;
}
tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
@@ -5674,6 +5830,7 @@ megasas_resume(struct pci_dev *pdev)
}
instance->instancet->enable_intr(instance);
+ megasas_setup_jbod_map(instance);
instance->unload = 0;
/*
@@ -5721,6 +5878,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
struct Scsi_Host *host;
struct megasas_instance *instance;
struct fusion_context *fusion;
+ u32 pd_seq_map_sz;
instance = pci_get_drvdata(pdev);
instance->unload = 1;
@@ -5769,12 +5927,11 @@ static void megasas_detach_one(struct pci_dev *pdev)
if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
- switch (instance->pdev->device) {
- case PCI_DEVICE_ID_LSI_FUSION:
- case PCI_DEVICE_ID_LSI_PLASMA:
- case PCI_DEVICE_ID_LSI_INVADER:
- case PCI_DEVICE_ID_LSI_FURY:
+ if (instance->ctrl_context) {
megasas_release_fusion(instance);
+ pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
+ (sizeof(struct MR_PD_CFG_SEQ) *
+ (MAX_PHYSICAL_DEVICES - 1));
for (i = 0; i < 2 ; i++) {
if (fusion->ld_map[i])
dma_free_coherent(&instance->pdev->dev,
@@ -5784,11 +5941,15 @@ static void megasas_detach_one(struct pci_dev *pdev)
if (fusion->ld_drv_map[i])
free_pages((ulong)fusion->ld_drv_map[i],
fusion->drv_map_pages);
+ if (fusion->pd_seq_sync)
+ dma_free_coherent(&instance->pdev->dev,
+ pd_seq_map_sz,
+ fusion->pd_seq_sync[i],
+ fusion->pd_seq_phys[i]);
}
free_pages((ulong)instance->ctrl_context,
instance->ctrl_context_pages);
- break;
- default:
+ } else {
megasas_release_mfi(instance);
pci_free_consistent(pdev, sizeof(u32),
instance->producer,
@@ -5796,7 +5957,6 @@ static void megasas_detach_one(struct pci_dev *pdev)
pci_free_consistent(pdev, sizeof(u32),
instance->consumer,
instance->consumer_h);
- break;
}
kfree(instance->ctrl_info);
@@ -6316,6 +6476,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
int i;
int error = 0;
compat_uptr_t ptr;
+ unsigned long local_raw_ptr;
+ u32 local_sense_off;
+ u32 local_sense_len;
if (clear_user(ioc, sizeof(*ioc)))
return -EFAULT;
@@ -6333,9 +6496,15 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
* sense_len is not null, so prepare the 64bit value under
* the same condition.
*/
- if (ioc->sense_len) {
+ if (get_user(local_raw_ptr, ioc->frame.raw) ||
+ get_user(local_sense_off, &ioc->sense_off) ||
+ get_user(local_sense_len, &ioc->sense_len))
+ return -EFAULT;
+
+
+ if (local_sense_len) {
void __user **sense_ioc_ptr =
- (void __user **)(ioc->frame.raw + ioc->sense_off);
+ (void __user **)((u8*)local_raw_ptr + local_sense_off);
compat_uptr_t *sense_cioc_ptr =
(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
if (get_user(ptr, sense_cioc_ptr) ||
@@ -6504,6 +6673,7 @@ megasas_aen_polling(struct work_struct *work)
instance->ev = NULL;
host = instance->host;
if (instance->evt_detail) {
+ megasas_decode_evt(instance);
switch (le32_to_cpu(instance->evt_detail->code)) {
case MR_EVT_PD_INSERTED:
@@ -6564,8 +6734,7 @@ megasas_aen_polling(struct work_struct *work)
case MR_EVT_CFG_CLEARED:
case MR_EVT_LD_DELETED:
if (!instance->requestorId ||
- (instance->requestorId &&
- megasas_get_ld_vf_affiliation(instance, 0))) {
+ megasas_get_ld_vf_affiliation(instance, 0)) {
if (megasas_ld_list_query(instance,
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
megasas_get_ld_list(instance);
@@ -6596,8 +6765,7 @@ megasas_aen_polling(struct work_struct *work)
break;
case MR_EVT_LD_CREATED:
if (!instance->requestorId ||
- (instance->requestorId &&
- megasas_get_ld_vf_affiliation(instance, 0))) {
+ megasas_get_ld_vf_affiliation(instance, 0)) {
if (megasas_ld_list_query(instance,
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
megasas_get_ld_list(instance);
@@ -6627,6 +6795,9 @@ megasas_aen_polling(struct work_struct *work)
case MR_EVT_LD_STATE_CHANGE:
doscan = 1;
break;
+ case MR_EVT_CTRL_PROP_CHANGED:
+ megasas_get_ctrl_info(instance);
+ break;
default:
doscan = 0;
break;
@@ -6663,8 +6834,7 @@ megasas_aen_polling(struct work_struct *work)
}
if (!instance->requestorId ||
- (instance->requestorId &&
- megasas_get_ld_vf_affiliation(instance, 0))) {
+ megasas_get_ld_vf_affiliation(instance, 0)) {
if (megasas_ld_list_query(instance,
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
megasas_get_ld_list(instance);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index be57b18675a4..741509b35617 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -741,14 +741,12 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
u8 physArm, span;
u64 row;
u8 retval = TRUE;
- u8 do_invader = 0;
u64 *pdBlock = &io_info->pdBlock;
__le16 *pDevHandle = &io_info->devHandle;
u32 logArm, rowMod, armQ, arm;
+ struct fusion_context *fusion;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
- instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
- do_invader = 1;
+ fusion = instance->ctrl_context;
/*Get row and span from io_info for Uneven Span IO.*/
row = io_info->start_row;
@@ -779,7 +777,8 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
else {
*pDevHandle = cpu_to_le16(MR_PD_INVALID);
if ((raid->level >= 5) &&
- (!do_invader || (do_invader &&
+ ((fusion->adapter_type == THUNDERBOLT_SERIES) ||
+ ((fusion->adapter_type == INVADER_SERIES) &&
(raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
@@ -823,13 +822,12 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
u8 physArm, span;
u64 row;
u8 retval = TRUE;
- u8 do_invader = 0;
u64 *pdBlock = &io_info->pdBlock;
__le16 *pDevHandle = &io_info->devHandle;
+ struct fusion_context *fusion;
+
+ fusion = instance->ctrl_context;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
- instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
- do_invader = 1;
row = mega_div64_32(stripRow, raid->rowDataSize);
@@ -875,7 +873,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
/* set dev handle as invalid. */
*pDevHandle = cpu_to_le16(MR_PD_INVALID);
if ((raid->level >= 5) &&
- (!do_invader || (do_invader &&
+ ((fusion->adapter_type == THUNDERBOLT_SERIES) ||
+ ((fusion->adapter_type == INVADER_SERIES) &&
(raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
@@ -909,6 +908,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
struct RAID_CONTEXT *pRAID_Context,
struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN)
{
+ struct fusion_context *fusion;
struct MR_LD_RAID *raid;
u32 ld, stripSize, stripe_mask;
u64 endLba, endStrip, endRow, start_row, start_strip;
@@ -929,6 +929,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
isRead = io_info->isRead;
io_info->IoforUnevenSpan = 0;
io_info->start_span = SPAN_INVALID;
+ fusion = instance->ctrl_context;
ld = MR_TargetIdToLdGet(ldTgtId, map);
raid = MR_LdRaidGet(ld, map);
@@ -1092,8 +1093,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
cpu_to_le16(raid->fpIoTimeoutForLd ?
raid->fpIoTimeoutForLd :
map->raidMap.fpPdIoTimeoutSec);
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ if (fusion->adapter_type == INVADER_SERIES)
pRAID_Context->regLockFlags = (isRead) ?
raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
else
@@ -1198,10 +1198,6 @@ void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
span_row_width +=
MR_LdSpanPtrGet
(ld, count, map)->spanRowDataSize;
- printk(KERN_INFO "megasas:"
- "span %x rowDataSize %x\n",
- count, MR_LdSpanPtrGet
- (ld, count, map)->spanRowDataSize);
}
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index f0837cc3b163..8d630a552b07 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -316,26 +316,23 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
u32 max_cmd;
struct fusion_context *fusion;
struct megasas_cmd_fusion *cmd;
- u32 total_sz_chain_frame;
fusion = instance->ctrl_context;
max_cmd = instance->max_fw_cmds;
- total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME;
/*
* Use DMA pool facility provided by PCI layer
*/
- fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion",
- instance->pdev,
- total_sz_chain_frame, 4,
- 0);
+ fusion->sg_dma_pool = pci_pool_create("sg_pool_fusion", instance->pdev,
+ instance->max_chain_frame_sz,
+ 4, 0);
if (!fusion->sg_dma_pool) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup request pool fusion\n");
return -ENOMEM;
}
- fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion",
+ fusion->sense_dma_pool = pci_pool_create("sense pool fusion",
instance->pdev,
SCSI_SENSE_BUFFERSIZE, 64, 0);
@@ -605,6 +602,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
int i;
struct megasas_header *frame_hdr;
const char *sys_info;
+ MFI_CAPABILITIES *drv_ops;
fusion = instance->ctrl_context;
@@ -652,20 +650,21 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
init_frame->cmd = MFI_CMD_INIT;
init_frame->cmd_status = 0xFF;
+ drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations);
+
/* driver support Extended MSIX */
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
- init_frame->driver_operations.
- mfi_capabilities.support_additional_msix = 1;
+ if (fusion->adapter_type == INVADER_SERIES)
+ drv_ops->mfi_capabilities.support_additional_msix = 1;
/* driver supports HA / Remote LUN over Fast Path interface */
- init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun
- = 1;
- init_frame->driver_operations.mfi_capabilities.support_max_255lds
- = 1;
- init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb
- = 1;
- init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw
- = 1;
+ drv_ops->mfi_capabilities.support_fp_remote_lun = 1;
+
+ drv_ops->mfi_capabilities.support_max_255lds = 1;
+ drv_ops->mfi_capabilities.support_ndrive_r1_lb = 1;
+ drv_ops->mfi_capabilities.security_protocol_cmds_fw = 1;
+
+ if (instance->max_chain_frame_sz > MEGASAS_CHAIN_FRAME_SZ_MIN)
+ drv_ops->mfi_capabilities.support_ext_io_size = 1;
+
/* Convert capability to LE32 */
cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
@@ -726,6 +725,83 @@ fail_get_cmd:
return ret;
}
+/**
+ * megasas_sync_pd_seq_num - JBOD SEQ MAP
+ * @instance: Adapter soft state
+ * @pend: set to 1, if it is pended jbod map.
+ *
+ * Issue Jbod map to the firmware. If it is pended command,
+ * issue command and return. If it is first instance of jbod map
+ * issue and receive command.
+ */
+int
+megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) {
+ int ret = 0;
+ u32 pd_seq_map_sz;
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ struct fusion_context *fusion = instance->ctrl_context;
+ struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
+ dma_addr_t pd_seq_h;
+
+ pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id & 1)];
+ pd_seq_h = fusion->pd_seq_phys[(instance->pd_seq_map_id & 1)];
+ pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
+ (sizeof(struct MR_PD_CFG_SEQ) *
+ (MAX_PHYSICAL_DEVICES - 1));
+
+ cmd = megasas_get_cmd(instance);
+ if (!cmd) {
+ dev_err(&instance->pdev->dev,
+ "Could not get mfi cmd. Fail from %s %d\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ dcmd = &cmd->frame->dcmd;
+
+ memset(pd_sync, 0, pd_seq_map_sz);
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = cpu_to_le32(pd_seq_map_sz);
+ dcmd->opcode = cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO);
+ dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(pd_seq_h);
+ dcmd->sgl.sge32[0].length = cpu_to_le32(pd_seq_map_sz);
+
+ if (pend) {
+ dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG;
+ dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE);
+ instance->jbod_seq_cmd = cmd;
+ instance->instancet->issue_dcmd(instance, cmd);
+ return 0;
+ }
+
+ dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
+
+ /* Below code is only for non pended DCMD */
+ if (instance->ctrl_context && !instance->mask_interrupts)
+ ret = megasas_issue_blocked_cmd(instance, cmd, 60);
+ else
+ ret = megasas_issue_polled(instance, cmd);
+
+ if (le32_to_cpu(pd_sync->count) > MAX_PHYSICAL_DEVICES) {
+ dev_warn(&instance->pdev->dev,
+ "driver supports max %d JBOD, but FW reports %d\n",
+ MAX_PHYSICAL_DEVICES, le32_to_cpu(pd_sync->count));
+ ret = -EINVAL;
+ }
+
+ if (!ret)
+ instance->pd_seq_map_id++;
+
+ megasas_return_cmd(instance, cmd);
+ return ret;
+}
+
/*
* megasas_get_ld_map_info - Returns FW's ld_map structure
* @instance: Adapter soft state
@@ -961,6 +1037,18 @@ megasas_display_intel_branding(struct megasas_instance *instance)
break;
}
break;
+ case PCI_DEVICE_ID_LSI_CUTLASS_52:
+ case PCI_DEVICE_ID_LSI_CUTLASS_53:
+ switch (instance->pdev->subsystem_device) {
+ case MEGARAID_INTEL_RMS3BC160_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RMS3BC160_BRANDING);
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -977,7 +1065,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
{
struct megasas_register_set __iomem *reg_set;
struct fusion_context *fusion;
- u32 max_cmd;
+ u32 max_cmd, scratch_pad_2;
int i = 0, count;
fusion = instance->ctrl_context;
@@ -1016,15 +1104,40 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
(max_cmd + 1)); /* Extra 1 for SMID 0 */
+ scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2);
+ /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set,
+ * Firmware support extended IO chain frame which is 4 times more than
+ * legacy Firmware.
+ * Legacy Firmware - Frame size is (8 * 128) = 1K
+ * 1M IO Firmware - Frame size is (8 * 128 * 4) = 4K
+ */
+ if (scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK)
+ instance->max_chain_frame_sz =
+ ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
+ MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_1MB_IO;
+ else
+ instance->max_chain_frame_sz =
+ ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
+ MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_256K_IO;
+
+ if (instance->max_chain_frame_sz < MEGASAS_CHAIN_FRAME_SZ_MIN) {
+ dev_warn(&instance->pdev->dev, "frame size %d invalid, fall back to legacy max frame size %d\n",
+ instance->max_chain_frame_sz,
+ MEGASAS_CHAIN_FRAME_SZ_MIN);
+ instance->max_chain_frame_sz = MEGASAS_CHAIN_FRAME_SZ_MIN;
+ }
+
fusion->max_sge_in_main_msg =
- (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
- offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
+ (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE
+ - offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
fusion->max_sge_in_chain =
- MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION);
+ instance->max_chain_frame_sz
+ / sizeof(union MPI2_SGE_IO_UNION);
- instance->max_num_sge = rounddown_pow_of_two(
- fusion->max_sge_in_main_msg + fusion->max_sge_in_chain - 2);
+ instance->max_num_sge =
+ rounddown_pow_of_two(fusion->max_sge_in_main_msg
+ + fusion->max_sge_in_chain - 2);
/* Used for pass thru MFI frame (DCMD) */
fusion->chain_offset_mfi_pthru =
@@ -1186,8 +1299,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
fusion = instance->ctrl_context;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (fusion->adapter_type == INVADER_SERIES) {
struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
sgl_ptr_end->Flags = 0;
@@ -1204,11 +1316,9 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl));
sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl));
sgl_ptr->Flags = 0;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (fusion->adapter_type == INVADER_SERIES)
if (i == sge_count - 1)
sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
- }
sgl_ptr++;
sg_processed = i + 1;
@@ -1217,10 +1327,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
(sge_count > fusion->max_sge_in_main_msg)) {
struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
- if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FURY)) {
+ if (fusion->adapter_type == INVADER_SERIES) {
if ((le16_to_cpu(cmd->io_request->IoFlags) &
MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
@@ -1236,10 +1343,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
sg_chain = sgl_ptr;
/* Prepare chain element */
sg_chain->NextChainOffset = 0;
- if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FURY))
+ if (fusion->adapter_type == INVADER_SERIES)
sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
else
sg_chain->Flags =
@@ -1250,7 +1354,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
sgl_ptr =
(struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
- memset(sgl_ptr, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
+ memset(sgl_ptr, 0, instance->max_chain_frame_sz);
}
}
@@ -1556,8 +1660,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
cmd->request_desc->SCSIIO.RequestFlags =
(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (fusion->adapter_type == INVADER_SERIES) {
if (io_request->RaidContext.regLockFlags ==
REGION_TYPE_UNUSED)
cmd->request_desc->SCSIIO.RequestFlags =
@@ -1582,7 +1685,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
if ((raidLUN[0] == 1) &&
- (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 2)) {
+ (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 1)) {
instance->dev_handle = !(instance->dev_handle);
io_info.devHandle =
local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle];
@@ -1598,8 +1701,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
cmd->request_desc->SCSIIO.RequestFlags =
(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (fusion->adapter_type == INVADER_SERIES) {
if (io_request->RaidContext.regLockFlags ==
REGION_TYPE_UNUSED)
cmd->request_desc->SCSIIO.RequestFlags =
@@ -1722,7 +1824,9 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
u16 timeout_limit;
struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
struct RAID_CONTEXT *pRAID_Context;
+ struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
struct fusion_context *fusion = instance->ctrl_context;
+ pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id - 1) & 1];
device_id = MEGASAS_DEV_INDEX(scmd);
pd_index = MEGASAS_PD_INDEX(scmd);
@@ -1731,16 +1835,38 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
io_request = cmd->io_request;
/* get RAID_Context pointer */
pRAID_Context = &io_request->RaidContext;
+ pRAID_Context->regLockFlags = 0;
+ pRAID_Context->regLockRowLBA = 0;
+ pRAID_Context->regLockLength = 0;
io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
io_request->LUN[1] = scmd->device->lun;
pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD
<< MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
- pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
- pRAID_Context->configSeqNum = 0;
- local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
- io_request->DevHandle =
- local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+ /* If FW supports PD sequence number */
+ if (instance->use_seqnum_jbod_fp &&
+ instance->pd_list[pd_index].driveType == TYPE_DISK) {
+ /* TgtId must be incremented by 255 as jbod seq number is index
+ * below raid map
+ */
+ pRAID_Context->VirtualDiskTgtId =
+ cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1));
+ pRAID_Context->configSeqNum = pd_sync->seq[pd_index].seqNum;
+ io_request->DevHandle = pd_sync->seq[pd_index].devHandle;
+ pRAID_Context->regLockFlags |=
+ (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA);
+ } else if (fusion->fast_path_io) {
+ pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
+ pRAID_Context->configSeqNum = 0;
+ local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
+ io_request->DevHandle =
+ local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+ } else {
+ /* Want to send all IO via FW path */
+ pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
+ pRAID_Context->configSeqNum = 0;
+ io_request->DevHandle = cpu_to_le16(0xFFFF);
+ }
cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
cmd->request_desc->SCSIIO.MSIxIndex =
@@ -1755,22 +1881,16 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
(MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value);
+ pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
} else {
/* system pd Fast Path */
io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
- pRAID_Context->regLockFlags = 0;
- pRAID_Context->regLockRowLBA = 0;
- pRAID_Context->regLockLength = 0;
timeout_limit = (scmd->device->type == TYPE_DISK) ?
255 : 0xFFFF;
pRAID_Context->timeoutValue =
cpu_to_le16((os_timeout_value > timeout_limit) ?
timeout_limit : os_timeout_value);
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
- cmd->request_desc->SCSIIO.RequestFlags |=
- (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
- MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if (fusion->adapter_type == INVADER_SERIES) {
pRAID_Context->Type = MPI2_TYPE_CUDA;
pRAID_Context->nseg = 0x1;
io_request->IoFlags |=
@@ -1796,7 +1916,7 @@ megasas_build_io_fusion(struct megasas_instance *instance,
struct scsi_cmnd *scp,
struct megasas_cmd_fusion *cmd)
{
- u32 sge_count;
+ u16 sge_count;
u8 cmd_type;
struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
@@ -1854,7 +1974,11 @@ megasas_build_io_fusion(struct megasas_instance *instance,
return 1;
}
+ /* numSGE store lower 8 bit of sge_count.
+ * numSGEExt store higher 8 bit of sge_count
+ */
io_request->RaidContext.numSGE = sge_count;
+ io_request->RaidContext.numSGEExt = (u8)(sge_count >> 8);
io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
@@ -2084,10 +2208,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
* pending to be completed
*/
if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
- if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FURY))
+ if (fusion->adapter_type == INVADER_SERIES)
writel(((MSIxIndex & 0x7) << 24) |
fusion->last_reply_idx[MSIxIndex],
instance->reply_post_host_index_addr[MSIxIndex/8]);
@@ -2103,8 +2224,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
return IRQ_NONE;
wmb();
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ if (fusion->adapter_type == INVADER_SERIES)
writel(((MSIxIndex & 0x7) << 24) |
fusion->last_reply_idx[MSIxIndex],
instance->reply_post_host_index_addr[MSIxIndex/8]);
@@ -2227,8 +2347,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
io_req = cmd->io_request;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ if (fusion->adapter_type == INVADER_SERIES) {
struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
(struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
@@ -2248,7 +2367,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
- mpi25_ieee_chain->Length = cpu_to_le32(MEGASAS_MAX_SZ_CHAIN_FRAME);
+ mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz);
return 0;
}
@@ -2384,6 +2503,70 @@ static int
megasas_adp_reset_fusion(struct megasas_instance *instance,
struct megasas_register_set __iomem *regs)
{
+ u32 host_diag, abs_state, retry;
+
+ /* Now try to reset the chip */
+ writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_1ST_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_2ND_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_3RD_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_4TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_5TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_6TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+
+ /* Check that the diag write enable (DRWE) bit is on */
+ host_diag = readl(&instance->reg_set->fusion_host_diag);
+ retry = 0;
+ while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
+ msleep(100);
+ host_diag = readl(&instance->reg_set->fusion_host_diag);
+ if (retry++ == 100) {
+ dev_warn(&instance->pdev->dev,
+ "Host diag unlock failed from %s %d\n",
+ __func__, __LINE__);
+ break;
+ }
+ }
+ if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
+ return -1;
+
+ /* Send chip reset command */
+ writel(host_diag | HOST_DIAG_RESET_ADAPTER,
+ &instance->reg_set->fusion_host_diag);
+ msleep(3000);
+
+ /* Make sure reset adapter bit is cleared */
+ host_diag = readl(&instance->reg_set->fusion_host_diag);
+ retry = 0;
+ while (host_diag & HOST_DIAG_RESET_ADAPTER) {
+ msleep(100);
+ host_diag = readl(&instance->reg_set->fusion_host_diag);
+ if (retry++ == 1000) {
+ dev_warn(&instance->pdev->dev,
+ "Diag reset adapter never cleared %s %d\n",
+ __func__, __LINE__);
+ break;
+ }
+ }
+ if (host_diag & HOST_DIAG_RESET_ADAPTER)
+ return -1;
+
+ abs_state = instance->instancet->read_fw_status_reg(instance->reg_set)
+ & MFI_STATE_MASK;
+ retry = 0;
+
+ while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
+ msleep(100);
+ abs_state = instance->instancet->
+ read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+ }
+ if (abs_state <= MFI_STATE_FW_INIT) {
+ dev_warn(&instance->pdev->dev,
+ "fw state < MFI_STATE_FW_INIT, state = 0x%x %s %d\n",
+ abs_state, __func__, __LINE__);
+ return -1;
+ }
+
return 0;
}
@@ -2512,8 +2695,10 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
continue;
req_desc = megasas_get_request_descriptor
(instance, smid - 1);
- if (req_desc && (cmd_mfi->frame->dcmd.opcode !=
- cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)))
+ if (req_desc && ((cmd_mfi->frame->dcmd.opcode !=
+ cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)) &&
+ (cmd_mfi->frame->dcmd.opcode !=
+ cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO))))
megasas_fire_cmd_fusion(instance, req_desc);
else
megasas_return_cmd(instance, cmd_mfi);
@@ -2547,11 +2732,11 @@ out:
/* Core fusion reset function */
int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
{
- int retval = SUCCESS, i, retry = 0, convert = 0;
+ int retval = SUCCESS, i, convert = 0;
struct megasas_instance *instance;
struct megasas_cmd_fusion *cmd_fusion;
struct fusion_context *fusion;
- u32 host_diag, abs_state, status_reg, reset_adapter;
+ u32 abs_state, status_reg, reset_adapter;
u32 io_timeout_in_crash_mode = 0;
struct scsi_cmnd *scmd_local = NULL;
@@ -2705,82 +2890,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
/* Now try to reset the chip */
for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
- writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
- writel(MPI2_WRSEQ_1ST_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
- writel(MPI2_WRSEQ_2ND_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
- writel(MPI2_WRSEQ_3RD_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
- writel(MPI2_WRSEQ_4TH_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
- writel(MPI2_WRSEQ_5TH_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
- writel(MPI2_WRSEQ_6TH_KEY_VALUE,
- &instance->reg_set->fusion_seq_offset);
-
- /* Check that the diag write enable (DRWE) bit is on */
- host_diag = readl(&instance->reg_set->fusion_host_diag);
- retry = 0;
- while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
- msleep(100);
- host_diag =
- readl(&instance->reg_set->fusion_host_diag);
- if (retry++ == 100) {
- dev_warn(&instance->pdev->dev,
- "Host diag unlock failed! "
- "for scsi%d\n",
- instance->host->host_no);
- break;
- }
- }
- if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
- continue;
- /* Send chip reset command */
- writel(host_diag | HOST_DIAG_RESET_ADAPTER,
- &instance->reg_set->fusion_host_diag);
- msleep(3000);
-
- /* Make sure reset adapter bit is cleared */
- host_diag = readl(&instance->reg_set->fusion_host_diag);
- retry = 0;
- while (host_diag & HOST_DIAG_RESET_ADAPTER) {
- msleep(100);
- host_diag =
- readl(&instance->reg_set->fusion_host_diag);
- if (retry++ == 1000) {
- dev_warn(&instance->pdev->dev,
- "Diag reset adapter never "
- "cleared for scsi%d!\n",
- instance->host->host_no);
- break;
- }
- }
- if (host_diag & HOST_DIAG_RESET_ADAPTER)
+ if (instance->instancet->adp_reset
+ (instance, instance->reg_set))
continue;
- abs_state =
- instance->instancet->read_fw_status_reg(
- instance->reg_set) & MFI_STATE_MASK;
- retry = 0;
-
- while ((abs_state <= MFI_STATE_FW_INIT) &&
- (retry++ < 1000)) {
- msleep(100);
- abs_state =
- instance->instancet->read_fw_status_reg(
- instance->reg_set) & MFI_STATE_MASK;
- }
- if (abs_state <= MFI_STATE_FW_INIT) {
- dev_warn(&instance->pdev->dev, "firmware "
- "state < MFI_STATE_FW_INIT, state = "
- "0x%x for scsi%d\n", abs_state,
- instance->host->host_no);
- continue;
- }
-
/* Wait for FW to become ready */
if (megasas_transition_to_ready(instance, 1)) {
dev_warn(&instance->pdev->dev, "Failed to "
@@ -2816,6 +2930,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
if (!megasas_get_map_info(instance))
megasas_sync_map_info(instance);
+ megasas_setup_jbod_map(instance);
+
clear_bit(MEGASAS_FUSION_IN_RESET,
&instance->reset_flags);
instance->instancet->enable_intr(instance);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index ced6dc0cf8e8..473005c99b44 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -35,8 +35,13 @@
#define _MEGARAID_SAS_FUSION_H_
/* Fusion defines */
-#define MEGASAS_MAX_SZ_CHAIN_FRAME 1024
+#define MEGASAS_CHAIN_FRAME_SZ_MIN 1024
#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
+#define MEGASAS_MAX_CHAIN_SHIFT 5
+#define MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK 0x400000
+#define MEGASAS_MAX_CHAIN_SIZE_MASK 0x3E0
+#define MEGASAS_256K_IO 128
+#define MEGASAS_1MB_IO (MEGASAS_256K_IO * 4)
#define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
#define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0
#define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1
@@ -89,6 +94,12 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
#define MEGASAS_FP_CMD_LEN 16
#define MEGASAS_FUSION_IN_RESET 0
#define THRESHOLD_REPLY_COUNT 50
+#define JBOD_MAPS_COUNT 2
+
+enum MR_FUSION_ADAPTER_TYPE {
+ THUNDERBOLT_SERIES = 0,
+ INVADER_SERIES = 1,
+};
/*
* Raid Context structure which describes MegaRAID specific IO Parameters
@@ -117,7 +128,9 @@ struct RAID_CONTEXT {
u8 numSGE;
__le16 configSeqNum;
u8 spanArm;
- u8 resvd2[3];
+ u8 priority;
+ u8 numSGEExt;
+ u8 resvd2;
};
#define RAID_CTX_SPANARM_ARM_SHIFT (0)
@@ -486,6 +499,7 @@ struct MPI2_IOC_INIT_REQUEST {
#define MAX_PHYSICAL_DEVICES 256
#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101
+#define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102
#define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/
#define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200
#define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200
@@ -789,6 +803,21 @@ struct MR_FW_RAID_MAP_EXT {
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT];
};
+/*
+ * * define MR_PD_CFG_SEQ structure for system PDs
+ * */
+struct MR_PD_CFG_SEQ {
+ __le16 seqNum;
+ __le16 devHandle;
+ u8 reserved[4];
+} __packed;
+
+struct MR_PD_CFG_SEQ_NUM_SYNC {
+ __le32 size;
+ __le32 count;
+ struct MR_PD_CFG_SEQ seq[1];
+} __packed;
+
struct fusion_context {
struct megasas_cmd_fusion **cmd_list;
dma_addr_t req_frames_desc_phys;
@@ -828,9 +857,12 @@ struct fusion_context {
u32 current_map_sz;
u32 drv_map_sz;
u32 drv_map_pages;
+ struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT];
+ dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT];
u8 fast_path_io;
struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT];
LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
+ u8 adapter_type;
};
union desc_value {
diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig
deleted file mode 100644
index 657b45ca04c5..000000000000
--- a/drivers/scsi/mpt2sas/Kconfig
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Kernel configuration file for the MPT2SAS
-#
-# This code is based on drivers/scsi/mpt2sas/Kconfig
-# Copyright (C) 2007-2014 LSI Corporation
-# (mailto:DL-MPTFusionLinux@lsi.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.
-
-# NO WARRANTY
-# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
-# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
-# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
-# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
-# solely responsible for determining the appropriateness of using and
-# distributing the Program and assumes all risks associated with its
-# exercise of rights under this Agreement, including but not limited to
-# the risks and costs of program errors, damage to or loss of data,
-# programs or equipment, and unavailability or interruption of operations.
-
-# DISCLAIMER OF LIABILITY
-# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-config SCSI_MPT2SAS
- tristate "LSI MPT Fusion SAS 2.0 Device Driver"
- depends on PCI && SCSI
- select SCSI_SAS_ATTRS
- select RAID_ATTRS
- ---help---
- This driver supports PCI-Express SAS 6Gb/s Host Adapters.
-
-config SCSI_MPT2SAS_MAX_SGE
- int "LSI MPT Fusion Max number of SG Entries (16 - 128)"
- depends on PCI && SCSI && SCSI_MPT2SAS
- default "128"
- range 16 128
- ---help---
- This option allows you to specify the maximum number of scatter-
- gather entries per I/O. The driver default is 128, which matches
- SAFE_PHYS_SEGMENTS. However, it may decreased down to 16.
- Decreasing this parameter will reduce memory requirements
- on a per controller instance.
-
-config SCSI_MPT2SAS_LOGGING
- bool "LSI MPT Fusion logging facility"
- depends on PCI && SCSI && SCSI_MPT2SAS
- ---help---
- This turns on a logging facility.
diff --git a/drivers/scsi/mpt2sas/Makefile b/drivers/scsi/mpt2sas/Makefile
deleted file mode 100644
index 728f0475711d..000000000000
--- a/drivers/scsi/mpt2sas/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# mpt2sas makefile
-obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas.o
-mpt2sas-y += mpt2sas_base.o \
- mpt2sas_config.o \
- mpt2sas_scsih.o \
- mpt2sas_transport.o \
- mpt2sas_ctl.o
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
deleted file mode 100644
index 7fc6f23bd9dc..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2.h
- * Title: MPI Message independent structures and definitions
- * including System Interface Register Set and
- * scatter/gather formats.
- * Creation Date: June 21, 2006
- *
- * mpi2.h Version: 02.00.35
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT.
- * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT.
- * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT.
- * Moved ReplyPostHostIndex register to offset 0x6C of the
- * MPI2_SYSTEM_INTERFACE_REGS and modified the define for
- * MPI2_REPLY_POST_HOST_INDEX_OFFSET.
- * Added union of request descriptors.
- * Added union of reply descriptors.
- * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added define for MPI2_VERSION_02_00.
- * Fixed the size of the FunctionDependent5 field in the
- * MPI2_DEFAULT_REPLY structure.
- * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT.
- * Removed the MPI-defined Fault Codes and extended the
- * product specific codes up to 0xEFFF.
- * Added a sixth key value for the WriteSequence register
- * and changed the flush value to 0x0.
- * Added message function codes for Diagnostic Buffer Post
- * and Diagnsotic Release.
- * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
- * Moved MPI2_VERSION_UNION from mpi2_ioc.h.
- * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT.
- * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT.
- * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added #defines for marking a reply descriptor as unused.
- * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT.
- * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT.
- * Moved LUN field defines from mpi2_init.h.
- * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT.
- * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT.
- * In all request and reply descriptors, replaced VF_ID
- * field with MSIxIndex field.
- * Removed DevHandle field from
- * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
- * bytes reserved.
- * Added RAID Accelerator functionality.
- * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT.
- * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added MSI-x index mask and shift for Reply Post Host
- * Index register.
- * Added function code for Host Based Discovery Action.
- * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
- * Added defines for product-specific range of message
- * function codes, 0xF0 to 0xFF.
- * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added alternative defines for the SGE Direction bit.
- * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT.
- * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
- * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added MPI2_FUNCTION_SEND_HOST_MESSAGE.
- * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT.
- * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT.
- * 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT.
- * 11-18-11 02.00.23 Bumped MPI2_HEADER_VERSION_UNIT.
- * 02-06-12 02.00.24 Bumped MPI2_HEADER_VERSION_UNIT.
- * 03-29-12 02.00.25 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added Hard Reset delay timings.
- * 07-10-12 02.00.26 Bumped MPI2_HEADER_VERSION_UNIT.
- * 07-26-12 02.00.27 Bumped MPI2_HEADER_VERSION_UNIT.
- * 11-27-12 02.00.28 Bumped MPI2_HEADER_VERSION_UNIT.
- * 12-20-12 02.00.29 Bumped MPI2_HEADER_VERSION_UNIT.
- * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET.
- * 04-09-13 02.00.30 Bumped MPI2_HEADER_VERSION_UNIT.
- * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT.
- * 08-19-13 02.00.32 Bumped MPI2_HEADER_VERSION_UNIT.
- * 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT.
- * 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT.
- * 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_H
-#define MPI2_H
-
-
-/*****************************************************************************
-*
-* MPI Version Definitions
-*
-*****************************************************************************/
-
-#define MPI2_VERSION_MAJOR (0x02)
-#define MPI2_VERSION_MINOR (0x00)
-#define MPI2_VERSION_MAJOR_MASK (0xFF00)
-#define MPI2_VERSION_MAJOR_SHIFT (8)
-#define MPI2_VERSION_MINOR_MASK (0x00FF)
-#define MPI2_VERSION_MINOR_SHIFT (0)
-#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
- MPI2_VERSION_MINOR)
-
-#define MPI2_VERSION_02_00 (0x0200)
-
-/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x23)
-#define MPI2_HEADER_VERSION_DEV (0x00)
-#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
-#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
-#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
-#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
-#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
-
-
-/*****************************************************************************
-*
-* IOC State Definitions
-*
-*****************************************************************************/
-
-#define MPI2_IOC_STATE_RESET (0x00000000)
-#define MPI2_IOC_STATE_READY (0x10000000)
-#define MPI2_IOC_STATE_OPERATIONAL (0x20000000)
-#define MPI2_IOC_STATE_FAULT (0x40000000)
-
-#define MPI2_IOC_STATE_MASK (0xF0000000)
-#define MPI2_IOC_STATE_SHIFT (28)
-
-/* Fault state range for prodcut specific codes */
-#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000)
-#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF)
-
-
-/*****************************************************************************
-*
-* System Interface Register Definitions
-*
-*****************************************************************************/
-
-typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
-{
- U32 Doorbell; /* 0x00 */
- U32 WriteSequence; /* 0x04 */
- U32 HostDiagnostic; /* 0x08 */
- U32 Reserved1; /* 0x0C */
- U32 DiagRWData; /* 0x10 */
- U32 DiagRWAddressLow; /* 0x14 */
- U32 DiagRWAddressHigh; /* 0x18 */
- U32 Reserved2[5]; /* 0x1C */
- U32 HostInterruptStatus; /* 0x30 */
- U32 HostInterruptMask; /* 0x34 */
- U32 DCRData; /* 0x38 */
- U32 DCRAddress; /* 0x3C */
- U32 Reserved3[2]; /* 0x40 */
- U32 ReplyFreeHostIndex; /* 0x48 */
- U32 Reserved4[8]; /* 0x4C */
- U32 ReplyPostHostIndex; /* 0x6C */
- U32 Reserved5; /* 0x70 */
- U32 HCBSize; /* 0x74 */
- U32 HCBAddressLow; /* 0x78 */
- U32 HCBAddressHigh; /* 0x7C */
- U32 Reserved6[16]; /* 0x80 */
- U32 RequestDescriptorPostLow; /* 0xC0 */
- U32 RequestDescriptorPostHigh; /* 0xC4 */
- U32 Reserved7[14]; /* 0xC8 */
-} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS,
- Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t;
-
-/*
- * Defines for working with the Doorbell register.
- */
-#define MPI2_DOORBELL_OFFSET (0x00000000)
-
-/* IOC --> System values */
-#define MPI2_DOORBELL_USED (0x08000000)
-#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000)
-#define MPI2_DOORBELL_WHO_INIT_SHIFT (24)
-#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF)
-#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF)
-
-/* System --> IOC values */
-#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000)
-#define MPI2_DOORBELL_FUNCTION_SHIFT (24)
-#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000)
-#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16)
-
-
-/*
- * Defines for the WriteSequence register
- */
-#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
-#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F)
-#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
-#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
-#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
-#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
-#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
-#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
-#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
-
-/*
- * Defines for the HostDiagnostic register
- */
-#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008)
-
-#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800)
-#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000)
-#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
-
-#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400)
-#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200)
-#define MPI2_DIAG_HCB_MODE (0x00000100)
-#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080)
-#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040)
-#define MPI2_DIAG_RESET_HISTORY (0x00000020)
-#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010)
-#define MPI2_DIAG_RESET_ADAPTER (0x00000004)
-#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002)
-
-/*
- * Offsets for DiagRWData and address
- */
-#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010)
-#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014)
-#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018)
-
-/*
- * Defines for the HostInterruptStatus register
- */
-#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030)
-#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000)
-#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS
-#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000)
-#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008)
-#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001)
-#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS
-
-/*
- * Defines for the HostInterruptMask register
- */
-#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034)
-#define MPI2_HIM_RESET_IRQ_MASK (0x40000000)
-#define MPI2_HIM_REPLY_INT_MASK (0x00000008)
-#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK
-#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001)
-#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK
-
-/*
- * Offsets for DCRData and address
- */
-#define MPI2_DCR_DATA_OFFSET (0x00000038)
-#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C)
-
-/*
- * Offset for the Reply Free Queue
- */
-#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048)
-
-/*
- * Defines for the Reply Descriptor Post Queue
- */
-#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
-#define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF)
-#define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000)
-#define MPI2_RPHI_MSIX_INDEX_SHIFT (24)
-#define MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C) /* MPI v2.5 only */
-
-/*
- * Defines for the HCBSize and address
- */
-#define MPI2_HCB_SIZE_OFFSET (0x00000074)
-#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000)
-#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001)
-
-#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078)
-#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C)
-
-/*
- * Offsets for the Request Queue
- */
-#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0)
-#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4)
-
-
-/* Hard Reset delay timings */
-#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC (50000)
-#define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC (255000)
-#define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC (256000)
-
-/*****************************************************************************
-*
-* Message Descriptors
-*
-*****************************************************************************/
-
-/* Request Descriptors */
-
-/* Default Request Descriptor */
-typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
-{
- U8 RequestFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U16 LMID; /* 0x04 */
- U16 DescriptorTypeDependent; /* 0x06 */
-} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
- Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
-
-/* defines for the RequestFlags field */
-#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
-#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
-#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02)
-#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
-#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08)
-#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A)
-
-#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
-
-
-/* High Priority Request Descriptor */
-typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
-{
- U8 RequestFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U16 LMID; /* 0x04 */
- U16 Reserved1; /* 0x06 */
-} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
- Mpi2HighPriorityRequestDescriptor_t,
- MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
-
-
-/* SCSI IO Request Descriptor */
-typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
-{
- U8 RequestFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U16 LMID; /* 0x04 */
- U16 DevHandle; /* 0x06 */
-} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
- Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
-
-
-/* SCSI Target Request Descriptor */
-typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
-{
- U8 RequestFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U16 LMID; /* 0x04 */
- U16 IoIndex; /* 0x06 */
-} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
- Mpi2SCSITargetRequestDescriptor_t,
- MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
-
-
-/* RAID Accelerator Request Descriptor */
-typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
- U8 RequestFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U16 LMID; /* 0x04 */
- U16 Reserved; /* 0x06 */
-} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
- Mpi2RAIDAcceleratorRequestDescriptor_t,
- MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t;
-
-
-/* union of Request Descriptors */
-typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
-{
- MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
- MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
- MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
- MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
- MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
- U64 Words;
-} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
- Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t;
-
-
-/* Reply Descriptors */
-
-/* Default Reply Descriptor */
-typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
-{
- U8 ReplyFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 DescriptorTypeDependent1; /* 0x02 */
- U32 DescriptorTypeDependent2; /* 0x04 */
-} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
- Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
-
-/* defines for the ReplyFlags field */
-#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
-#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
-#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01)
-#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02)
-#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03)
-#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05)
-#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
-
-/* values for marking a reply descriptor as unused */
-#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF)
-#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF)
-
-/* Address Reply Descriptor */
-typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
-{
- U8 ReplyFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U32 ReplyFrameAddress; /* 0x04 */
-} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
- Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
-
-#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00)
-
-
-/* SCSI IO Success Reply Descriptor */
-typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
-{
- U8 ReplyFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U16 TaskTag; /* 0x04 */
- U16 Reserved1; /* 0x06 */
-} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
- Mpi2SCSIIOSuccessReplyDescriptor_t,
- MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
-
-
-/* TargetAssist Success Reply Descriptor */
-typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
-{
- U8 ReplyFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U8 SequenceNumber; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 IoIndex; /* 0x06 */
-} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
- Mpi2TargetAssistSuccessReplyDescriptor_t,
- MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
-
-
-/* Target Command Buffer Reply Descriptor */
-typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
-{
- U8 ReplyFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U8 VP_ID; /* 0x02 */
- U8 Flags; /* 0x03 */
- U16 InitiatorDevHandle; /* 0x04 */
- U16 IoIndex; /* 0x06 */
-} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
- Mpi2TargetCommandBufferReplyDescriptor_t,
- MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
-
-/* defines for Flags field */
-#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F)
-
-
-/* RAID Accelerator Success Reply Descriptor */
-typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
- U8 ReplyFlags; /* 0x00 */
- U8 MSIxIndex; /* 0x01 */
- U16 SMID; /* 0x02 */
- U32 Reserved; /* 0x04 */
-} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
- Mpi2RAIDAcceleratorSuccessReplyDescriptor_t,
- MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
-
-
-/* union of Reply Descriptors */
-typedef union _MPI2_REPLY_DESCRIPTORS_UNION
-{
- MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
- MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
- MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
- MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
- MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
- MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
- U64 Words;
-} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
-Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
-
-
-
-/*****************************************************************************
-*
-* Message Functions
-*
-*****************************************************************************/
-
-#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
-#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) /* SCSI Task Management */
-#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */
-#define MPI2_FUNCTION_IOC_FACTS (0x03) /* IOC Facts */
-#define MPI2_FUNCTION_CONFIG (0x04) /* Configuration */
-#define MPI2_FUNCTION_PORT_FACTS (0x05) /* Port Facts */
-#define MPI2_FUNCTION_PORT_ENABLE (0x06) /* Port Enable */
-#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) /* Event Notification */
-#define MPI2_FUNCTION_EVENT_ACK (0x08) /* Event Acknowledge */
-#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) /* FW Download */
-#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) /* Target Assist */
-#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) /* Target Status Send */
-#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) /* Target Mode Abort */
-#define MPI2_FUNCTION_FW_UPLOAD (0x12) /* FW Upload */
-#define MPI2_FUNCTION_RAID_ACTION (0x15) /* RAID Action */
-#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) /* SCSI IO RAID Passthrough */
-#define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */
-#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */
-#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */
-#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */
-#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */
-#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */
-#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */
-#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */
-#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */
-#define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) /* RAID Accelerator*/
-/* Host Based Discovery Action */
-#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F)
-/* Power Management Control */
-#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30)
-/* Send Host Message */
-#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31)
-/* beginning of product-specific range */
-#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0)
-/* end of product-specific range */
-#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF)
-
-
-
-
-/* Doorbell functions */
-#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40)
-#define MPI2_FUNCTION_HANDSHAKE (0x42)
-
-
-/*****************************************************************************
-*
-* IOC Status Values
-*
-*****************************************************************************/
-
-/* mask for IOCStatus status value */
-#define MPI2_IOCSTATUS_MASK (0x7FFF)
-
-/****************************************************************************
-* Common IOCStatus values for all replies
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_SUCCESS (0x0000)
-#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001)
-#define MPI2_IOCSTATUS_BUSY (0x0002)
-#define MPI2_IOCSTATUS_INVALID_SGL (0x0003)
-#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004)
-#define MPI2_IOCSTATUS_INVALID_VPID (0x0005)
-#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006)
-#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007)
-#define MPI2_IOCSTATUS_INVALID_STATE (0x0008)
-#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009)
-
-/****************************************************************************
-* Config IOCStatus values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020)
-#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021)
-#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022)
-#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023)
-#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024)
-#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025)
-
-/****************************************************************************
-* SCSI IO Reply
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040)
-#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042)
-#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043)
-#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044)
-#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045)
-#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046)
-#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047)
-#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048)
-#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049)
-#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A)
-#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B)
-#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
-
-/****************************************************************************
-* For use by SCSI Initiator and SCSI Target end-to-end data protection
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D)
-#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E)
-#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
-
-/****************************************************************************
-* SCSI Target values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062)
-#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063)
-#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064)
-#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065)
-#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
-#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
-#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
-#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
-#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
-#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
-
-/****************************************************************************
-* Serial Attached SCSI values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
-#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091)
-
-/****************************************************************************
-* Diagnostic Buffer Post / Diagnostic Release values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0)
-
-/****************************************************************************
-* RAID Accelerator values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0)
-
-/****************************************************************************
-* IOCStatus flag to indicate that log info is available
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000)
-
-/****************************************************************************
-* IOCLogInfo Types
-****************************************************************************/
-
-#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000)
-#define MPI2_IOCLOGINFO_TYPE_SHIFT (28)
-#define MPI2_IOCLOGINFO_TYPE_NONE (0x0)
-#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1)
-#define MPI2_IOCLOGINFO_TYPE_FC (0x2)
-#define MPI2_IOCLOGINFO_TYPE_SAS (0x3)
-#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4)
-#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF)
-
-
-/*****************************************************************************
-*
-* Standard Message Structures
-*
-*****************************************************************************/
-
-/****************************************************************************
-* Request Message Header for all request messages
-****************************************************************************/
-
-typedef struct _MPI2_REQUEST_HEADER
-{
- U16 FunctionDependent1; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 FunctionDependent2; /* 0x04 */
- U8 FunctionDependent3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
-} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER,
- MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t;
-
-
-/****************************************************************************
-* Default Reply
-****************************************************************************/
-
-typedef struct _MPI2_DEFAULT_REPLY
-{
- U16 FunctionDependent1; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 FunctionDependent2; /* 0x04 */
- U8 FunctionDependent3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U16 FunctionDependent5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY,
- MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t;
-
-
-/* common version structure/union used in messages and configuration pages */
-
-typedef struct _MPI2_VERSION_STRUCT
-{
- U8 Dev; /* 0x00 */
- U8 Unit; /* 0x01 */
- U8 Minor; /* 0x02 */
- U8 Major; /* 0x03 */
-} MPI2_VERSION_STRUCT;
-
-typedef union _MPI2_VERSION_UNION
-{
- MPI2_VERSION_STRUCT Struct;
- U32 Word;
-} MPI2_VERSION_UNION;
-
-
-/* LUN field defines, common to many structures */
-#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF)
-#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000)
-#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF)
-#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000)
-#define MPI2_LUN_LEVEL_1_WORD (0xFF00)
-#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00)
-
-
-/*****************************************************************************
-*
-* Fusion-MPT MPI Scatter Gather Elements
-*
-*****************************************************************************/
-
-/****************************************************************************
-* MPI Simple Element structures
-****************************************************************************/
-
-typedef struct _MPI2_SGE_SIMPLE32
-{
- U32 FlagsLength;
- U32 Address;
-} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32,
- Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t;
-
-typedef struct _MPI2_SGE_SIMPLE64
-{
- U32 FlagsLength;
- U64 Address;
-} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64,
- Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t;
-
-typedef struct _MPI2_SGE_SIMPLE_UNION
-{
- U32 FlagsLength;
- union
- {
- U32 Address32;
- U64 Address64;
- } u;
-} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
- Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
-
-
-/****************************************************************************
-* MPI Chain Element structures
-****************************************************************************/
-
-typedef struct _MPI2_SGE_CHAIN32
-{
- U16 Length;
- U8 NextChainOffset;
- U8 Flags;
- U32 Address;
-} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32,
- Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t;
-
-typedef struct _MPI2_SGE_CHAIN64
-{
- U16 Length;
- U8 NextChainOffset;
- U8 Flags;
- U64 Address;
-} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64,
- Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t;
-
-typedef struct _MPI2_SGE_CHAIN_UNION
-{
- U16 Length;
- U8 NextChainOffset;
- U8 Flags;
- union
- {
- U32 Address32;
- U64 Address64;
- } u;
-} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
- Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
-
-
-/****************************************************************************
-* MPI Transaction Context Element structures
-****************************************************************************/
-
-typedef struct _MPI2_SGE_TRANSACTION32
-{
- U8 Reserved;
- U8 ContextSize;
- U8 DetailsLength;
- U8 Flags;
- U32 TransactionContext[1];
- U32 TransactionDetails[1];
-} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32,
- Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t;
-
-typedef struct _MPI2_SGE_TRANSACTION64
-{
- U8 Reserved;
- U8 ContextSize;
- U8 DetailsLength;
- U8 Flags;
- U32 TransactionContext[2];
- U32 TransactionDetails[1];
-} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64,
- Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t;
-
-typedef struct _MPI2_SGE_TRANSACTION96
-{
- U8 Reserved;
- U8 ContextSize;
- U8 DetailsLength;
- U8 Flags;
- U32 TransactionContext[3];
- U32 TransactionDetails[1];
-} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96,
- Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t;
-
-typedef struct _MPI2_SGE_TRANSACTION128
-{
- U8 Reserved;
- U8 ContextSize;
- U8 DetailsLength;
- U8 Flags;
- U32 TransactionContext[4];
- U32 TransactionDetails[1];
-} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128,
- Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128;
-
-typedef struct _MPI2_SGE_TRANSACTION_UNION
-{
- U8 Reserved;
- U8 ContextSize;
- U8 DetailsLength;
- U8 Flags;
- union
- {
- U32 TransactionContext32[1];
- U32 TransactionContext64[2];
- U32 TransactionContext96[3];
- U32 TransactionContext128[4];
- } u;
- U32 TransactionDetails[1];
-} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION,
- Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t;
-
-
-/****************************************************************************
-* MPI SGE union for IO SGL's
-****************************************************************************/
-
-typedef struct _MPI2_MPI_SGE_IO_UNION
-{
- union
- {
- MPI2_SGE_SIMPLE_UNION Simple;
- MPI2_SGE_CHAIN_UNION Chain;
- } u;
-} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION,
- Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t;
-
-
-/****************************************************************************
-* MPI SGE union for SGL's with Simple and Transaction elements
-****************************************************************************/
-
-typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION
-{
- union
- {
- MPI2_SGE_SIMPLE_UNION Simple;
- MPI2_SGE_TRANSACTION_UNION Transaction;
- } u;
-} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
- Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t;
-
-
-/****************************************************************************
-* All MPI SGE types union
-****************************************************************************/
-
-typedef struct _MPI2_MPI_SGE_UNION
-{
- union
- {
- MPI2_SGE_SIMPLE_UNION Simple;
- MPI2_SGE_CHAIN_UNION Chain;
- MPI2_SGE_TRANSACTION_UNION Transaction;
- } u;
-} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION,
- Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t;
-
-
-/****************************************************************************
-* MPI SGE field definition and masks
-****************************************************************************/
-
-/* Flags field bit definitions */
-
-#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80)
-#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40)
-#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30)
-#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08)
-#define MPI2_SGE_FLAGS_DIRECTION (0x04)
-#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02)
-#define MPI2_SGE_FLAGS_END_OF_LIST (0x01)
-
-#define MPI2_SGE_FLAGS_SHIFT (24)
-
-#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF)
-#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF)
-
-/* Element Type */
-
-#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00)
-#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10)
-#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30)
-#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30)
-
-/* Address location */
-
-#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00)
-
-/* Direction */
-
-#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00)
-#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04)
-
-#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST)
-#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC)
-
-/* Address Size */
-
-#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00)
-#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
-
-/* Context Size */
-
-#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00)
-#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02)
-#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04)
-#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06)
-
-#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000)
-#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16)
-
-/****************************************************************************
-* MPI SGE operation Macros
-****************************************************************************/
-
-/* SIMPLE FlagsLength manipulations... */
-#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
-#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT)
-#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK)
-#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
-
-#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l))
-
-#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
-#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength)
-#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l)
-
-/* CAUTION - The following are READ-MODIFY-WRITE! */
-#define MPI2_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f)
-#define MPI2_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_SGE_LENGTH(l)
-
-#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT)
-
-
-/*****************************************************************************
-*
-* Fusion-MPT IEEE Scatter Gather Elements
-*
-*****************************************************************************/
-
-/****************************************************************************
-* IEEE Simple Element structures
-****************************************************************************/
-
-typedef struct _MPI2_IEEE_SGE_SIMPLE32
-{
- U32 Address;
- U32 FlagsLength;
-} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
- Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
-
-typedef struct _MPI2_IEEE_SGE_SIMPLE64
-{
- U64 Address;
- U32 Length;
- U16 Reserved1;
- U8 Reserved2;
- U8 Flags;
-} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
- Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
-
-typedef union _MPI2_IEEE_SGE_SIMPLE_UNION
-{
- MPI2_IEEE_SGE_SIMPLE32 Simple32;
- MPI2_IEEE_SGE_SIMPLE64 Simple64;
-} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
- Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
-
-
-/****************************************************************************
-* IEEE Chain Element structures
-****************************************************************************/
-
-typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
-
-typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
-
-typedef union _MPI2_IEEE_SGE_CHAIN_UNION
-{
- MPI2_IEEE_SGE_CHAIN32 Chain32;
- MPI2_IEEE_SGE_CHAIN64 Chain64;
-} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
- Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
-
-
-/****************************************************************************
-* All IEEE SGE types union
-****************************************************************************/
-
-typedef struct _MPI2_IEEE_SGE_UNION
-{
- union
- {
- MPI2_IEEE_SGE_SIMPLE_UNION Simple;
- MPI2_IEEE_SGE_CHAIN_UNION Chain;
- } u;
-} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION,
- Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t;
-
-
-/****************************************************************************
-* IEEE SGE field definitions and masks
-****************************************************************************/
-
-/* Flags field bit definitions */
-
-#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80)
-
-#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24)
-
-#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF)
-
-/* Element Type */
-
-#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00)
-#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
-
-/* Data Location Address Space */
-
-#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
-#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
- /* IEEE Simple Element only */
-#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
- /* IEEE Simple Element only */
-#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
-#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
- /* IEEE Simple Element only */
-#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03)
- /* IEEE Chain Element only */
-#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \
- (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) /* typo in name */
-
-/****************************************************************************
-* IEEE SGE operation Macros
-****************************************************************************/
-
-/* SIMPLE FlagsLength manipulations... */
-#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
-#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
-#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
-
-#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l))
-
-#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
-#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
-#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l)
-
-/* CAUTION - The following are READ-MODIFY-WRITE! */
-#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f)
-#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l)
-
-
-
-
-/*****************************************************************************
-*
-* Fusion-MPT MPI/IEEE Scatter Gather Unions
-*
-*****************************************************************************/
-
-typedef union _MPI2_SIMPLE_SGE_UNION
-{
- MPI2_SGE_SIMPLE_UNION MpiSimple;
- MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
-} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION,
- Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t;
-
-
-typedef union _MPI2_SGE_IO_UNION
-{
- MPI2_SGE_SIMPLE_UNION MpiSimple;
- MPI2_SGE_CHAIN_UNION MpiChain;
- MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
- MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
-} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
- Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
-
-
-/****************************************************************************
-*
-* Values for SGLFlags field, used in many request messages with an SGL
-*
-****************************************************************************/
-
-/* values for MPI SGL Data Location Address Space subfield */
-#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C)
-#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00)
-#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04)
-#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08)
-#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C)
-/* values for SGL Type subfield */
-#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03)
-#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00)
-#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01)
-#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02)
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
deleted file mode 100644
index ee8d2d695d55..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ /dev/null
@@ -1,3068 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_cnfg.h
- * Title: MPI Configuration messages and pages
- * Creation Date: November 10, 2006
- *
- * mpi2_cnfg.h Version: 02.00.29
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags.
- * Added Manufacturing Page 11.
- * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
- * define.
- * 06-26-07 02.00.02 Adding generic structure for product-specific
- * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
- * Rework of BIOS Page 2 configuration page.
- * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
- * forms.
- * Added configuration pages IOC Page 8 and Driver
- * Persistent Mapping Page 0.
- * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated
- * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
- * RAID Physical Disk Pages 0 and 1, RAID Configuration
- * Page 0).
- * Added new value for AccessStatus field of SAS Device
- * Page 0 (_SATA_NEEDS_INITIALIZATION).
- * 10-31-07 02.00.04 Added missing SEPDevHandle field to
- * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for
- * NVDATA.
- * Modified IOC Page 7 to use masks and added field for
- * SASBroadcastPrimitiveMasks.
- * Added MPI2_CONFIG_PAGE_BIOS_4.
- * Added MPI2_CONFIG_PAGE_LOG_0.
- * 02-29-08 02.00.06 Modified various names to make them 32-character unique.
- * Added SAS Device IDs.
- * Updated Integrated RAID configuration pages including
- * Manufacturing Page 4, IOC Page 6, and RAID Configuration
- * Page 0.
- * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
- * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
- * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
- * Added missing MaxNumRoutedSasAddresses field to
- * MPI2_CONFIG_PAGE_EXPANDER_0.
- * Added SAS Port Page 0.
- * Modified structure layout for
- * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
- * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
- * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
- * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
- * to 0x000000FF.
- * Added two new values for the Physical Disk Coercion Size
- * bits in the Flags field of Manufacturing Page 4.
- * Added product-specific Manufacturing pages 16 to 31.
- * Modified Flags bits for controlling write cache on SATA
- * drives in IO Unit Page 1.
- * Added new bit to AdditionalControlFlags of SAS IO Unit
- * Page 1 to control Invalid Topology Correction.
- * Added additional defines for RAID Volume Page 0
- * VolumeStatusFlags field.
- * Modified meaning of RAID Volume Page 0 VolumeSettings
- * define for auto-configure of hot-swap drives.
- * Added SupportedPhysDisks field to RAID Volume Page 1 and
- * added related defines.
- * Added PhysDiskAttributes field (and related defines) to
- * RAID Physical Disk Page 0.
- * Added MPI2_SAS_PHYINFO_PHY_VACANT define.
- * Added three new DiscoveryStatus bits for SAS IO Unit
- * Page 0 and SAS Expander Page 0.
- * Removed multiplexing information from SAS IO Unit pages.
- * Added BootDeviceWaitTime field to SAS IO Unit Page 4.
- * Removed Zone Address Resolved bit from PhyInfo and from
- * Expander Page 0 Flags field.
- * Added two new AccessStatus values to SAS Device Page 0
- * for indicating routing problems. Added 3 reserved words
- * to this page.
- * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3.
- * Inserted missing reserved field into structure for IOC
- * Page 6.
- * Added more pending task bits to RAID Volume Page 0
- * VolumeStatusFlags defines.
- * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
- * Added a new DiscoveryStatus bit for SAS IO Unit Page 0
- * and SAS Expander Page 0 to flag a downstream initiator
- * when in simplified routing mode.
- * Removed SATA Init Failure defines for DiscoveryStatus
- * fields of SAS IO Unit Page 0 and SAS Expander Page 0.
- * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
- * Added PortGroups, DmaGroup, and ControlGroup fields to
- * SAS Device Page 0.
- * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO
- * Unit Page 6.
- * Added expander reduced functionality data to SAS
- * Expander Page 0.
- * Added SAS PHY Page 2 and SAS PHY Page 3.
- * 07-30-09 02.00.12 Added IO Unit Page 7.
- * Added new device ids.
- * Added SAS IO Unit Page 5.
- * Added partial and slumber power management capable flags
- * to SAS Device Page 0 Flags field.
- * Added PhyInfo defines for power condition.
- * Added Ethernet configuration pages.
- * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
- * Added SAS PHY Page 4 structure and defines.
- * 02-10-10 02.00.14 Modified the comments for the configuration page
- * structures that contain an array of data. The host
- * should use the "count" field in the page data (e.g. the
- * NumPhys field) to determine the number of valid elements
- * in the array.
- * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines.
- * Added PowerManagementCapabilities to IO Unit Page 7.
- * Added PortWidthModGroup field to
- * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS.
- * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
- * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
- * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
- * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
- * define.
- * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
- * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
- * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing)
- * defines.
- * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to
- * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
- * the Pinout field.
- * Added BoardTemperature and BoardTemperatureUnits fields
- * to MPI2_CONFIG_PAGE_IO_UNIT_7.
- * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
- * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
- * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST.
- * Added IO Unit Page 8, IO Unit Page 9,
- * and IO Unit Page 10.
- * Added SASNotifyPrimitiveMasks field to
- * MPI2_CONFIG_PAGE_IOC_7.
- * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec).
- * 05-25-11 02.00.20 Cleaned up a few comments.
- * 08-24-11 02.00.21 Marked the IO Unit Page 7 PowerManagementCapabilities
- * for PCIe link as obsolete.
- * Added SpinupFlags field containing a Disable Spin-up
- * bit to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of
- * SAS IO Unit Page 4.
- * 11-18-11 02.00.22 Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT.
- * Added UEFIVersion field to BIOS Page 1 and defined new
- * BiosOptions bits.
- * 11-27-12 02.00.23 Added MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER.
- * Added MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID.
- * 12-20-12 02.00.24 Marked MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION as
- * obsolete for MPI v2.5 and later.
- * Added some defines for 12G SAS speeds.
- * 04-09-13 02.00.25 Added MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK.
- * Fixed MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS to
- * match the specification.
- * 12-05-13 02.00.27 Added MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL for
- * MPI2_CONFIG_PAGE_MAN_7.
- * Added EnclosureLevel and ConnectorName fields to
- * MPI2_CONFIG_PAGE_SAS_DEV_0.
- * Added MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID for
- * MPI2_CONFIG_PAGE_SAS_DEV_0.
- * Added EnclosureLevel field to
- * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- * Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for
- * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- * 01-08-14 02.00.28 Added more defines for the BiosOptions field of
- * MPI2_CONFIG_PAGE_BIOS_1.
- * 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and
- * more defines for the BiosOptions field.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_CNFG_H
-#define MPI2_CNFG_H
-
-/*****************************************************************************
-* Configuration Page Header and defines
-*****************************************************************************/
-
-/* Config Page Header */
-typedef struct _MPI2_CONFIG_PAGE_HEADER
-{
- U8 PageVersion; /* 0x00 */
- U8 PageLength; /* 0x01 */
- U8 PageNumber; /* 0x02 */
- U8 PageType; /* 0x03 */
-} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER,
- Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t;
-
-typedef union _MPI2_CONFIG_PAGE_HEADER_UNION
-{
- MPI2_CONFIG_PAGE_HEADER Struct;
- U8 Bytes[4];
- U16 Word16[2];
- U32 Word32;
-} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
- Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion;
-
-/* Extended Config Page Header */
-typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER
-{
- U8 PageVersion; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 PageNumber; /* 0x02 */
- U8 PageType; /* 0x03 */
- U16 ExtPageLength; /* 0x04 */
- U8 ExtPageType; /* 0x06 */
- U8 Reserved2; /* 0x07 */
-} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
- MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
- Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t;
-
-typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
-{
- MPI2_CONFIG_PAGE_HEADER Struct;
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
- U8 Bytes[8];
- U16 Word16[4];
- U32 Word32[2];
-} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
- Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion;
-
-
-/* PageType field values */
-#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00)
-#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10)
-#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20)
-#define MPI2_CONFIG_PAGEATTR_MASK (0xF0)
-
-#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00)
-#define MPI2_CONFIG_PAGETYPE_IOC (0x01)
-#define MPI2_CONFIG_PAGETYPE_BIOS (0x02)
-#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08)
-#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09)
-#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A)
-#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F)
-#define MPI2_CONFIG_PAGETYPE_MASK (0x0F)
-
-#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF)
-
-
-/* ExtPageType field values */
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13)
-#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14)
-#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15)
-#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16)
-#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
-#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
-#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
-
-
-/*****************************************************************************
-* PageAddress defines
-*****************************************************************************/
-
-/* RAID Volume PageAddress format */
-#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
-#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000)
-
-#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF)
-
-
-/* RAID Physical Disk PageAddress format */
-#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000)
-#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000)
-#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000)
-
-#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF)
-#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF)
-
-
-/* SAS Expander PageAddress format */
-#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000)
-#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000)
-#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000)
-
-#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF)
-#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000)
-#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16)
-
-
-/* SAS Device PageAddress format */
-#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
-#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000)
-
-#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF)
-
-
-/* SAS PHY PageAddress format */
-#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000)
-#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000)
-
-#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF)
-#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF)
-
-
-/* SAS Port PageAddress format */
-#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000)
-#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000)
-
-#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF)
-
-
-/* SAS Enclosure PageAddress format */
-#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
-#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000)
-
-#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
-
-
-/* RAID Configuration PageAddress format */
-#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000)
-#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000)
-#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000)
-
-#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF)
-
-
-/* Driver Persistent Mapping PageAddress format */
-#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000)
-
-#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000)
-#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16)
-#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF)
-
-
-/* Ethernet PageAddress format */
-#define MPI2_ETHERNET_PGAD_FORM_MASK (0xF0000000)
-#define MPI2_ETHERNET_PGAD_FORM_IF_NUM (0x00000000)
-
-#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF)
-
-
-
-/****************************************************************************
-* Configuration messages
-****************************************************************************/
-
-/* Configuration Request Message */
-typedef struct _MPI2_CONFIG_REQUEST
-{
- U8 Action; /* 0x00 */
- U8 SGLFlags; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 ExtPageLength; /* 0x04 */
- U8 ExtPageType; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U8 Reserved2; /* 0x0C */
- U8 ProxyVF_ID; /* 0x0D */
- U16 Reserved4; /* 0x0E */
- U32 Reserved3; /* 0x10 */
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
- U32 PageAddress; /* 0x18 */
- MPI2_SGE_IO_UNION PageBufferSGE; /* 0x1C */
-} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST,
- Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t;
-
-/* values for the Action field */
-#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00)
-#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01)
-#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02)
-#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03)
-#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04)
-#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05)
-#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06)
-#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* Config Reply Message */
-typedef struct _MPI2_CONFIG_REPLY
-{
- U8 Action; /* 0x00 */
- U8 SGLFlags; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 ExtPageLength; /* 0x04 */
- U8 ExtPageType; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U16 Reserved2; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
-} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY,
- Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t;
-
-
-
-/*****************************************************************************
-*
-* C o n f i g u r a t i o n P a g e s
-*
-*****************************************************************************/
-
-/****************************************************************************
-* Manufacturing Config pages
-****************************************************************************/
-
-#define MPI2_MFGPAGE_VENDORID_LSI (0x1000)
-
-/* SAS */
-#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070)
-#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072)
-#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074)
-#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076)
-#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077)
-#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064)
-#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065)
-
-#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E)
-
-#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080)
-#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081)
-#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082)
-#define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083)
-#define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084)
-#define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085)
-#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086)
-#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087)
-#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E)
-
-
-
-
-/* Manufacturing Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_0
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 ChipName[16]; /* 0x04 */
- U8 ChipRevision[8]; /* 0x14 */
- U8 BoardName[16]; /* 0x1C */
- U8 BoardAssembly[16]; /* 0x2C */
- U8 BoardTracerNumber[16]; /* 0x3C */
-} MPI2_CONFIG_PAGE_MAN_0,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0,
- Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t;
-
-#define MPI2_MANUFACTURING0_PAGEVERSION (0x00)
-
-
-/* Manufacturing Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_1
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 VPD[256]; /* 0x04 */
-} MPI2_CONFIG_PAGE_MAN_1,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1,
- Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t;
-
-#define MPI2_MANUFACTURING1_PAGEVERSION (0x00)
-
-
-typedef struct _MPI2_CHIP_REVISION_ID
-{
- U16 DeviceID; /* 0x00 */
- U8 PCIRevisionID; /* 0x02 */
- U8 Reserved; /* 0x03 */
-} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID,
- Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t;
-
-
-/* Manufacturing Page 2 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check Header.PageLength at runtime.
- */
-#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
-#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_2
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */
- U32 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */
-} MPI2_CONFIG_PAGE_MAN_2,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2,
- Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t;
-
-#define MPI2_MANUFACTURING2_PAGEVERSION (0x00)
-
-
-/* Manufacturing Page 3 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check Header.PageLength at runtime.
- */
-#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
-#define MPI2_MAN_PAGE_3_INFO_WORDS (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_3
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */
- U32 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */
-} MPI2_CONFIG_PAGE_MAN_3,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3,
- Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t;
-
-#define MPI2_MANUFACTURING3_PAGEVERSION (0x00)
-
-
-/* Manufacturing Page 4 */
-
-typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS
-{
- U8 PowerSaveFlags; /* 0x00 */
- U8 InternalOperationsSleepTime; /* 0x01 */
- U8 InternalOperationsRunTime; /* 0x02 */
- U8 HostIdleTime; /* 0x03 */
-} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
- MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
- Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t;
-
-/* defines for the PowerSaveFlags field */
-#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03)
-#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00)
-#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01)
-#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02)
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_4
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Flags; /* 0x08 */
- U8 InquirySize; /* 0x0C */
- U8 Reserved2; /* 0x0D */
- U16 Reserved3; /* 0x0E */
- U8 InquiryData[56]; /* 0x10 */
- U32 RAID0VolumeSettings; /* 0x48 */
- U32 RAID1EVolumeSettings; /* 0x4C */
- U32 RAID1VolumeSettings; /* 0x50 */
- U32 RAID10VolumeSettings; /* 0x54 */
- U32 Reserved4; /* 0x58 */
- U32 Reserved5; /* 0x5C */
- MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /* 0x60 */
- U8 MaxOCEDisks; /* 0x64 */
- U8 ResyncRate; /* 0x65 */
- U16 DataScrubDuration; /* 0x66 */
- U8 MaxHotSpares; /* 0x68 */
- U8 MaxPhysDisksPerVol; /* 0x69 */
- U8 MaxPhysDisks; /* 0x6A */
- U8 MaxVolumes; /* 0x6B */
-} MPI2_CONFIG_PAGE_MAN_4,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4,
- Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t;
-
-#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A)
-
-/* Manufacturing Page 4 Flags field */
-#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000)
-#define MPI2_MANPAGE4_METADATA_512MB (0x00000000)
-
-#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000)
-#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000)
-#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000)
-
-#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00)
-#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000)
-#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400)
-#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800)
-#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00)
-
-#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300)
-#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000)
-#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100)
-#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200)
-
-#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080)
-#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040)
-#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020)
-#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010)
-#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008)
-#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004)
-#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002)
-#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001)
-
-
-/* Manufacturing Page 5 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
-#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1)
-#endif
-
-typedef struct _MPI2_MANUFACTURING5_ENTRY
-{
- U64 WWID; /* 0x00 */
- U64 DeviceName; /* 0x08 */
-} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY,
- Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t;
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_5
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 NumPhys; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- U32 Reserved3; /* 0x08 */
- U32 Reserved4; /* 0x0C */
- MPI2_MANUFACTURING5_ENTRY Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */
-} MPI2_CONFIG_PAGE_MAN_5,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5,
- Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t;
-
-#define MPI2_MANUFACTURING5_PAGEVERSION (0x03)
-
-
-/* Manufacturing Page 6 */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_6
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 ProductSpecificInfo;/* 0x04 */
-} MPI2_CONFIG_PAGE_MAN_6,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6,
- Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t;
-
-#define MPI2_MANUFACTURING6_PAGEVERSION (0x00)
-
-
-/* Manufacturing Page 7 */
-
-typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
-{
- U32 Pinout; /* 0x00 */
- U8 Connector[16]; /* 0x04 */
- U8 Location; /* 0x14 */
- U8 ReceptacleID; /* 0x15 */
- U16 Slot; /* 0x16 */
- U32 Reserved2; /* 0x18 */
-} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
- Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
-
-/* defines for the Pinout field */
-#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00)
-#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8)
-
-#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF)
-#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00)
-#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01)
-#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02)
-#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04)
-#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05)
-#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06)
-#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08)
-#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09)
-#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A)
-#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
-#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
-#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
-
-/* defines for the Location field */
-#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
-#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02)
-#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04)
-#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08)
-#define MPI2_MANPAGE7_LOCATION_AUTO (0x10)
-#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20)
-#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
-#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_7
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Reserved2; /* 0x08 */
- U32 Flags; /* 0x0C */
- U8 EnclosureName[16]; /* 0x10 */
- U8 NumPhys; /* 0x20 */
- U8 Reserved3; /* 0x21 */
- U16 Reserved4; /* 0x22 */
- MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */
-} MPI2_CONFIG_PAGE_MAN_7,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
- Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
-
-#define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
-
-/* defines for the Flags field */
-#define MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL (0x00000008)
-#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002)
-#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
-
-
-/*
- * Generic structure to use for product-specific manufacturing pages
- * (currently Manufacturing Page 8 through Manufacturing Page 31).
- */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_PS
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 ProductSpecificInfo;/* 0x04 */
-} MPI2_CONFIG_PAGE_MAN_PS,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS,
- Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t;
-
-#define MPI2_MANUFACTURING8_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING9_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING10_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING11_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING12_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING13_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING14_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING15_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING16_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING17_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING18_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING19_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING20_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING21_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING22_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING23_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING24_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING25_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING26_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING27_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING28_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING29_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING30_PAGEVERSION (0x00)
-#define MPI2_MANUFACTURING31_PAGEVERSION (0x00)
-
-
-/****************************************************************************
-* IO Unit Config Pages
-****************************************************************************/
-
-/* IO Unit Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U64 UniqueValue; /* 0x04 */
- MPI2_VERSION_UNION NvdataVersionDefault; /* 0x08 */
- MPI2_VERSION_UNION NvdataVersionPersistent; /* 0x0A */
-} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
- Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t;
-
-#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02)
-
-
-/* IO Unit Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Flags; /* 0x04 */
-} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
- Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t;
-
-#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04)
-
-/* IO Unit Page 1 Flags defines */
-#define MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK (0x00004000)
-#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800)
-#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600)
-#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9)
-#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000)
-#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200)
-#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400)
-#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
-#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040)
-#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
-#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004)
-
-
-/* IO Unit Page 3 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for GPIOCount at runtime.
- */
-#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
-#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 GPIOCount; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- U16 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */
-} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
- Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t;
-
-#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01)
-
-/* defines for IO Unit Page 3 GPIOVal field */
-#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC)
-#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2)
-#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000)
-#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001)
-
-
-/* IO Unit Page 5 */
-
-/*
- * Upper layer code (drivers, utilities, etc.) should leave this define set to
- * one and check the value returned for NumDmaEngines at runtime.
- */
-#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
-#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U64 RaidAcceleratorBufferBaseAddress; /* 0x04 */
- U64 RaidAcceleratorBufferSize; /* 0x0C */
- U64 RaidAcceleratorControlBaseAddress; /* 0x14 */
- U8 RAControlSize; /* 0x1C */
- U8 NumDmaEngines; /* 0x1D */
- U8 RAMinControlSize; /* 0x1E */
- U8 RAMaxControlSize; /* 0x1F */
- U32 Reserved1; /* 0x20 */
- U32 Reserved2; /* 0x24 */
- U32 Reserved3; /* 0x28 */
- U32 DmaEngineCapabilities
- [MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /* 0x2C */
-} MPI2_CONFIG_PAGE_IO_UNIT_5, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
- Mpi2IOUnitPage5_t, MPI2_POINTER pMpi2IOUnitPage5_t;
-
-#define MPI2_IOUNITPAGE5_PAGEVERSION (0x00)
-
-/* defines for IO Unit Page 5 DmaEngineCapabilities field */
-#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFFFF0000)
-#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16)
-
-#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008)
-#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004)
-#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002)
-#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001)
-
-
-/* IO Unit Page 6 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U16 Flags; /* 0x04 */
- U8 RAHostControlSize; /* 0x06 */
- U8 Reserved0; /* 0x07 */
- U64 RaidAcceleratorHostControlBaseAddress; /* 0x08 */
- U32 Reserved1; /* 0x10 */
- U32 Reserved2; /* 0x14 */
- U32 Reserved3; /* 0x18 */
-} MPI2_CONFIG_PAGE_IO_UNIT_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_6,
- Mpi2IOUnitPage6_t, MPI2_POINTER pMpi2IOUnitPage6_t;
-
-#define MPI2_IOUNITPAGE6_PAGEVERSION (0x00)
-
-/* defines for IO Unit Page 6 Flags field */
-#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001)
-
-
-/* IO Unit Page 7 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U16 Reserved1; /* 0x04 */
- U8 PCIeWidth; /* 0x06 */
- U8 PCIeSpeed; /* 0x07 */
- U32 ProcessorState; /* 0x08 */
- U32 PowerManagementCapabilities; /* 0x0C */
- U16 IOCTemperature; /* 0x10 */
- U8 IOCTemperatureUnits; /* 0x12 */
- U8 IOCSpeed; /* 0x13 */
- U16 BoardTemperature; /* 0x14 */
- U8 BoardTemperatureUnits; /* 0x16 */
- U8 Reserved3; /* 0x17 */
- U32 Reserved4; /* 0x18 */
- U32 Reserved5; /* 0x1C */
- U32 Reserved6; /* 0x20 */
- U32 Reserved7; /* 0x24 */
-} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
- Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
-
-#define MPI2_IOUNITPAGE7_PAGEVERSION (0x04)
-
-/* defines for IO Unit Page 7 PCIeWidth field */
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01)
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02)
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04)
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08)
-
-/* defines for IO Unit Page 7 PCIeSpeed field */
-#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00)
-#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01)
-#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02)
-
-/* defines for IO Unit Page 7 ProcessorState field */
-#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F)
-#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND (0)
-
-#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT (0x00)
-#define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01)
-#define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02)
-
-/* defines for IO Unit Page 7 PowerManagementCapabilities field */
-#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400)
-#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200)
-#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100)
-#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) /* obsolete */
-#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) /* obsolete */
-
-/* defines for IO Unit Page 7 IOCTemperatureUnits field */
-#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00)
-#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01)
-#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02)
-
-/* defines for IO Unit Page 7 IOCSpeed field */
-#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL (0x01)
-#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF (0x02)
-#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04)
-#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08)
-
-/* defines for IO Unit Page 7 BoardTemperatureUnits field */
-#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00)
-#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01)
-#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02)
-
-/* IO Unit Page 8 */
-
-#define MPI2_IOUNIT8_NUM_THRESHOLDS (4)
-
-typedef struct _MPI2_IOUNIT8_SENSOR {
- U16 Flags; /* 0x00 */
- U16 Reserved1; /* 0x02 */
- U16
- Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /* 0x04 */
- U32 Reserved2; /* 0x0C */
- U32 Reserved3; /* 0x10 */
- U32 Reserved4; /* 0x14 */
-} MPI2_IOUNIT8_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT8_SENSOR,
-Mpi2IOUnit8Sensor_t, MPI2_POINTER pMpi2IOUnit8Sensor_t;
-
-/* defines for IO Unit Page 8 Sensor Flags field */
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008)
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004)
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002)
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumSensors at runtime.
- */
-#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
-#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Reserved2; /* 0x08 */
- U8 NumSensors; /* 0x0C */
- U8 PollingInterval; /* 0x0D */
- U16 Reserved3; /* 0x0E */
- MPI2_IOUNIT8_SENSOR
- Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/* 0x10 */
-} MPI2_CONFIG_PAGE_IO_UNIT_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
-Mpi2IOUnitPage8_t, MPI2_POINTER pMpi2IOUnitPage8_t;
-
-#define MPI2_IOUNITPAGE8_PAGEVERSION (0x00)
-
-
-/* IO Unit Page 9 */
-
-typedef struct _MPI2_IOUNIT9_SENSOR {
- U16 CurrentTemperature; /* 0x00 */
- U16 Reserved1; /* 0x02 */
- U8 Flags; /* 0x04 */
- U8 Reserved2; /* 0x05 */
- U16 Reserved3; /* 0x06 */
- U32 Reserved4; /* 0x08 */
- U32 Reserved5; /* 0x0C */
-} MPI2_IOUNIT9_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT9_SENSOR,
-Mpi2IOUnit9Sensor_t, MPI2_POINTER pMpi2IOUnit9Sensor_t;
-
-/* defines for IO Unit Page 9 Sensor Flags field */
-#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumSensors at runtime.
- */
-#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
-#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Reserved2; /* 0x08 */
- U8 NumSensors; /* 0x0C */
- U8 Reserved4; /* 0x0D */
- U16 Reserved3; /* 0x0E */
- MPI2_IOUNIT9_SENSOR
- Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/* 0x10 */
-} MPI2_CONFIG_PAGE_IO_UNIT_9, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
-Mpi2IOUnitPage9_t, MPI2_POINTER pMpi2IOUnitPage9_t;
-
-#define MPI2_IOUNITPAGE9_PAGEVERSION (0x00)
-
-
-/* IO Unit Page 10 */
-
-typedef struct _MPI2_IOUNIT10_FUNCTION {
- U8 CreditPercent; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
-} MPI2_IOUNIT10_FUNCTION, MPI2_POINTER PTR_MPI2_IOUNIT10_FUNCTION,
-Mpi2IOUnit10Function_t, MPI2_POINTER pMpi2IOUnit10Function_t;
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumFunctions at runtime.
- */
-#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
-#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 NumFunctions; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- U32 Reserved3; /* 0x08 */
- U32 Reserved4; /* 0x0C */
- MPI2_IOUNIT10_FUNCTION
- Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/* 0x10 */
-} MPI2_CONFIG_PAGE_IO_UNIT_10, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
-Mpi2IOUnitPage10_t, MPI2_POINTER pMpi2IOUnitPage10_t;
-
-#define MPI2_IOUNITPAGE10_PAGEVERSION (0x01)
-
-
-
-/****************************************************************************
-* IOC Config Pages
-****************************************************************************/
-
-/* IOC Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_0
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Reserved2; /* 0x08 */
- U16 VendorID; /* 0x0C */
- U16 DeviceID; /* 0x0E */
- U8 RevisionID; /* 0x10 */
- U8 Reserved3; /* 0x11 */
- U16 Reserved4; /* 0x12 */
- U32 ClassCode; /* 0x14 */
- U16 SubsystemVendorID; /* 0x18 */
- U16 SubsystemID; /* 0x1A */
-} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0,
- Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t;
-
-#define MPI2_IOCPAGE0_PAGEVERSION (0x02)
-
-
-/* IOC Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_1
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Flags; /* 0x04 */
- U32 CoalescingTimeout; /* 0x08 */
- U8 CoalescingDepth; /* 0x0C */
- U8 PCISlotNum; /* 0x0D */
- U8 PCIBusNum; /* 0x0E */
- U8 PCIDomainSegment; /* 0x0F */
- U32 Reserved1; /* 0x10 */
- U32 Reserved2; /* 0x14 */
-} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1,
- Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t;
-
-#define MPI2_IOCPAGE1_PAGEVERSION (0x05)
-
-/* defines for IOC Page 1 Flags field */
-#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001)
-
-#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF)
-#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF)
-#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF)
-
-/* IOC Page 6 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_6
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 CapabilitiesFlags; /* 0x04 */
- U8 MaxDrivesRAID0; /* 0x08 */
- U8 MaxDrivesRAID1; /* 0x09 */
- U8 MaxDrivesRAID1E; /* 0x0A */
- U8 MaxDrivesRAID10; /* 0x0B */
- U8 MinDrivesRAID0; /* 0x0C */
- U8 MinDrivesRAID1; /* 0x0D */
- U8 MinDrivesRAID1E; /* 0x0E */
- U8 MinDrivesRAID10; /* 0x0F */
- U32 Reserved1; /* 0x10 */
- U8 MaxGlobalHotSpares; /* 0x14 */
- U8 MaxPhysDisks; /* 0x15 */
- U8 MaxVolumes; /* 0x16 */
- U8 MaxConfigs; /* 0x17 */
- U8 MaxOCEDisks; /* 0x18 */
- U8 Reserved2; /* 0x19 */
- U16 Reserved3; /* 0x1A */
- U32 SupportedStripeSizeMapRAID0; /* 0x1C */
- U32 SupportedStripeSizeMapRAID1E; /* 0x20 */
- U32 SupportedStripeSizeMapRAID10; /* 0x24 */
- U32 Reserved4; /* 0x28 */
- U32 Reserved5; /* 0x2C */
- U16 DefaultMetadataSize; /* 0x30 */
- U16 Reserved6; /* 0x32 */
- U16 MaxBadBlockTableEntries; /* 0x34 */
- U16 Reserved7; /* 0x36 */
- U32 IRNvsramVersion; /* 0x38 */
-} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6,
- Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t;
-
-#define MPI2_IOCPAGE6_PAGEVERSION (0x05)
-
-/* defines for IOC Page 6 CapabilitiesFlags */
-#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT (0x00000020)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002)
-#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001)
-
-
-/* IOC Page 7 */
-
-#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4)
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_7
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
- U16 SASBroadcastPrimitiveMasks; /* 0x18 */
- U16 SASNotifyPrimitiveMasks; /* 0x1A */
- U32 Reserved3; /* 0x1C */
-} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
- Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
-
-#define MPI2_IOCPAGE7_PAGEVERSION (0x02)
-
-
-/* IOC Page 8 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_8
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 NumDevsPerEnclosure; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- U16 MaxPersistentEntries; /* 0x08 */
- U16 MaxNumPhysicalMappedIDs; /* 0x0A */
- U16 Flags; /* 0x0C */
- U16 Reserved3; /* 0x0E */
- U16 IRVolumeMappingFlags; /* 0x10 */
- U16 Reserved4; /* 0x12 */
- U32 Reserved5; /* 0x14 */
-} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8,
- Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t;
-
-#define MPI2_IOCPAGE8_PAGEVERSION (0x00)
-
-/* defines for IOC Page 8 Flags field */
-#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020)
-#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010)
-
-#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E)
-#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000)
-#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002)
-
-#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001)
-#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000)
-
-/* defines for IOC Page 8 IRVolumeMappingFlags */
-#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003)
-#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000)
-#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001)
-
-
-/****************************************************************************
-* BIOS Config Pages
-****************************************************************************/
-
-/* BIOS Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_1
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 BiosOptions; /* 0x04 */
- U32 IOCSettings; /* 0x08 */
- U8 SSUTimeout; /* 0x0C */
- U8 Reserved1; /* 0x0D */
- U16 Reserved2; /* 0x0E */
- U32 DeviceSettings; /* 0x10 */
- U16 NumberOfDevices; /* 0x14 */
- U16 UEFIVersion; /* 0x16 */
- U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */
- U16 IOTimeoutSequential; /* 0x1A */
- U16 IOTimeoutOther; /* 0x1C */
- U16 IOTimeoutBlockDevicesRM; /* 0x1E */
-} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1,
- Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t;
-
-#define MPI2_BIOSPAGE1_PAGEVERSION (0x07)
-
-/* values for BIOS Page 1 BiosOptions field */
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL (0x00000000)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE (0x00000800)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_LWWID (0x00001000)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_PSENS (0x00001800)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_ESPHY (0x00002000)
-
-#define MPI2_BIOSPAGE1_OPTIONS_X86_DISABLE_BIOS (0x00000400)
-
-#define MPI2_BIOSPAGE1_OPTIONS_MASK_REGISTRATION_UEFI_BSD (0x00000300)
-#define MPI2_BIOSPAGE1_OPTIONS_USE_BIT0_REGISTRATION_UEFI_BSD (0x00000000)
-#define MPI2_BIOSPAGE1_OPTIONS_FULL_REGISTRATION_UEFI_BSD (0x00000100)
-#define MPI2_BIOSPAGE1_OPTIONS_ADAPTER_REGISTRATION_UEFI_BSD (0x00000200)
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_REGISTRATION_UEFI_BSD (0x00000300)
-
-#define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0)
-#define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000)
-
-#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006)
-#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000)
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002)
-#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004)
-
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
-
-/* values for BIOS Page 1 IOCSettings field */
-#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
-#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
-#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
-
-#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0)
-#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000)
-#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040)
-#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080)
-
-#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030)
-#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000)
-#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010)
-#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020)
-#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030)
-
-#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008)
-
-/* values for BIOS Page 1 DeviceSettings field */
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
-
-/* defines for BIOS Page 1 UEFIVersion field */
-#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK (0xFF00)
-#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT (8)
-#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK (0x00FF)
-#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT (0)
-
-
-
-/* BIOS Page 2 */
-
-typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER
-{
- U32 Reserved1; /* 0x00 */
- U32 Reserved2; /* 0x04 */
- U32 Reserved3; /* 0x08 */
- U32 Reserved4; /* 0x0C */
- U32 Reserved5; /* 0x10 */
- U32 Reserved6; /* 0x14 */
-} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
- MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
- Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t;
-
-typedef struct _MPI2_BOOT_DEVICE_SAS_WWID
-{
- U64 SASAddress; /* 0x00 */
- U8 LUN[8]; /* 0x08 */
- U32 Reserved1; /* 0x10 */
- U32 Reserved2; /* 0x14 */
-} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID,
- Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t;
-
-typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT
-{
- U64 EnclosureLogicalID; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U32 Reserved2; /* 0x0C */
- U16 SlotNumber; /* 0x10 */
- U16 Reserved3; /* 0x12 */
- U32 Reserved4; /* 0x14 */
-} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
- MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
- Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t;
-
-typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME
-{
- U64 DeviceName; /* 0x00 */
- U8 LUN[8]; /* 0x08 */
- U32 Reserved1; /* 0x10 */
- U32 Reserved2; /* 0x14 */
-} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
- Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t;
-
-typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE
-{
- MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder;
- MPI2_BOOT_DEVICE_SAS_WWID SasWwid;
- MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
- MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName;
-} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
- Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t;
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_2
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Reserved2; /* 0x08 */
- U32 Reserved3; /* 0x0C */
- U32 Reserved4; /* 0x10 */
- U32 Reserved5; /* 0x14 */
- U32 Reserved6; /* 0x18 */
- U8 ReqBootDeviceForm; /* 0x1C */
- U8 Reserved7; /* 0x1D */
- U16 Reserved8; /* 0x1E */
- MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /* 0x20 */
- U8 ReqAltBootDeviceForm; /* 0x38 */
- U8 Reserved9; /* 0x39 */
- U16 Reserved10; /* 0x3A */
- MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /* 0x3C */
- U8 CurrentBootDeviceForm; /* 0x58 */
- U8 Reserved11; /* 0x59 */
- U16 Reserved12; /* 0x5A */
- MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /* 0x58 */
-} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2,
- Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t;
-
-#define MPI2_BIOSPAGE2_PAGEVERSION (0x04)
-
-/* values for BIOS Page 2 BootDeviceForm fields */
-#define MPI2_BIOSPAGE2_FORM_MASK (0x0F)
-#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00)
-#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05)
-#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
-#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07)
-
-
-/* BIOS Page 3 */
-
-typedef struct _MPI2_ADAPTER_INFO
-{
- U8 PciBusNumber; /* 0x00 */
- U8 PciDeviceAndFunctionNumber; /* 0x01 */
- U16 AdapterFlags; /* 0x02 */
-} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO,
- Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t;
-
-#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001)
-#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002)
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_3
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 GlobalFlags; /* 0x04 */
- U32 BiosVersion; /* 0x08 */
- MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */
- U32 Reserved1; /* 0x1C */
-} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3,
- Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t;
-
-#define MPI2_BIOSPAGE3_PAGEVERSION (0x00)
-
-/* values for BIOS Page 3 GlobalFlags */
-#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002)
-#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004)
-#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010)
-
-#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0)
-#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000)
-#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020)
-#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040)
-
-
-/* BIOS Page 4 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
-#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1)
-#endif
-
-typedef struct _MPI2_BIOS4_ENTRY
-{
- U64 ReassignmentWWID; /* 0x00 */
- U64 ReassignmentDeviceName; /* 0x08 */
-} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY,
- Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t;
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_4
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 NumPhys; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- MPI2_BIOS4_ENTRY Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /* 0x08 */
-} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4,
- Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t;
-
-#define MPI2_BIOSPAGE4_PAGEVERSION (0x01)
-
-
-/****************************************************************************
-* RAID Volume Config Pages
-****************************************************************************/
-
-/* RAID Volume Page 0 */
-
-typedef struct _MPI2_RAIDVOL0_PHYS_DISK
-{
- U8 RAIDSetNum; /* 0x00 */
- U8 PhysDiskMap; /* 0x01 */
- U8 PhysDiskNum; /* 0x02 */
- U8 Reserved; /* 0x03 */
-} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK,
- Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t;
-
-/* defines for the PhysDiskMap field */
-#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01)
-#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02)
-
-typedef struct _MPI2_RAIDVOL0_SETTINGS
-{
- U16 Settings; /* 0x00 */
- U8 HotSparePool; /* 0x01 */
- U8 Reserved; /* 0x02 */
-} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS,
- Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t;
-
-/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
-#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01)
-#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02)
-#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04)
-#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08)
-#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10)
-#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20)
-#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40)
-#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80)
-
-/* RAID Volume Page 0 VolumeSettings defines */
-#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008)
-#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
-
-#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003)
-#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000)
-#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001)
-#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhysDisks at runtime.
- */
-#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
-#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U16 DevHandle; /* 0x04 */
- U8 VolumeState; /* 0x06 */
- U8 VolumeType; /* 0x07 */
- U32 VolumeStatusFlags; /* 0x08 */
- MPI2_RAIDVOL0_SETTINGS VolumeSettings; /* 0x0C */
- U64 MaxLBA; /* 0x10 */
- U32 StripeSize; /* 0x18 */
- U16 BlockSize; /* 0x1C */
- U16 Reserved1; /* 0x1E */
- U8 SupportedPhysDisks; /* 0x20 */
- U8 ResyncRate; /* 0x21 */
- U16 DataScrubDuration; /* 0x22 */
- U8 NumPhysDisks; /* 0x24 */
- U8 Reserved2; /* 0x25 */
- U8 Reserved3; /* 0x26 */
- U8 InactiveStatus; /* 0x27 */
- MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */
-} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
- Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t;
-
-#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A)
-
-/* values for RAID VolumeState */
-#define MPI2_RAID_VOL_STATE_MISSING (0x00)
-#define MPI2_RAID_VOL_STATE_FAILED (0x01)
-#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02)
-#define MPI2_RAID_VOL_STATE_ONLINE (0x03)
-#define MPI2_RAID_VOL_STATE_DEGRADED (0x04)
-#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05)
-
-/* values for RAID VolumeType */
-#define MPI2_RAID_VOL_TYPE_RAID0 (0x00)
-#define MPI2_RAID_VOL_TYPE_RAID1E (0x01)
-#define MPI2_RAID_VOL_TYPE_RAID1 (0x02)
-#define MPI2_RAID_VOL_TYPE_RAID10 (0x05)
-#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF)
-
-/* values for RAID Volume Page 0 VolumeStatusFlags field */
-#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080)
-#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020)
-#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008)
-#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004)
-#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002)
-#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001)
-
-/* values for RAID Volume Page 0 SupportedPhysDisks field */
-#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08)
-#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04)
-#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02)
-#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01)
-
-/* values for RAID Volume Page 0 InactiveStatus field */
-#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
-#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01)
-#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02)
-#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03)
-#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04)
-#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05)
-#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06)
-
-
-/* RAID Volume Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U16 DevHandle; /* 0x04 */
- U16 Reserved0; /* 0x06 */
- U8 GUID[24]; /* 0x08 */
- U8 Name[16]; /* 0x20 */
- U64 WWID; /* 0x30 */
- U32 Reserved1; /* 0x38 */
- U32 Reserved2; /* 0x3C */
-} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
- Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t;
-
-#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03)
-
-
-/****************************************************************************
-* RAID Physical Disk Config Pages
-****************************************************************************/
-
-/* RAID Physical Disk Page 0 */
-
-typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS
-{
- U16 Reserved1; /* 0x00 */
- U8 HotSparePool; /* 0x02 */
- U8 Reserved2; /* 0x03 */
-} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
- Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t;
-
-/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
-
-typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA
-{
- U8 VendorID[8]; /* 0x00 */
- U8 ProductID[16]; /* 0x08 */
- U8 ProductRevLevel[4]; /* 0x18 */
- U8 SerialNum[32]; /* 0x1C */
-} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
- MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
- Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t;
-
-typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U16 DevHandle; /* 0x04 */
- U8 Reserved1; /* 0x06 */
- U8 PhysDiskNum; /* 0x07 */
- MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /* 0x08 */
- U32 Reserved2; /* 0x0C */
- MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /* 0x10 */
- U32 Reserved3; /* 0x4C */
- U8 PhysDiskState; /* 0x50 */
- U8 OfflineReason; /* 0x51 */
- U8 IncompatibleReason; /* 0x52 */
- U8 PhysDiskAttributes; /* 0x53 */
- U32 PhysDiskStatusFlags; /* 0x54 */
- U64 DeviceMaxLBA; /* 0x58 */
- U64 HostMaxLBA; /* 0x60 */
- U64 CoercedMaxLBA; /* 0x68 */
- U16 BlockSize; /* 0x70 */
- U16 Reserved5; /* 0x72 */
- U32 Reserved6; /* 0x74 */
-} MPI2_CONFIG_PAGE_RD_PDISK_0,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
- Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t;
-
-#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05)
-
-/* PhysDiskState defines */
-#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00)
-#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01)
-#define MPI2_RAID_PD_STATE_OFFLINE (0x02)
-#define MPI2_RAID_PD_STATE_ONLINE (0x03)
-#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04)
-#define MPI2_RAID_PD_STATE_DEGRADED (0x05)
-#define MPI2_RAID_PD_STATE_REBUILDING (0x06)
-#define MPI2_RAID_PD_STATE_OPTIMAL (0x07)
-
-/* OfflineReason defines */
-#define MPI2_PHYSDISK0_ONLINE (0x00)
-#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01)
-#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03)
-#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04)
-#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05)
-#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06)
-#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF)
-
-/* IncompatibleReason defines */
-#define MPI2_PHYSDISK0_COMPATIBLE (0x00)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF)
-
-/* PhysDiskAttributes defines */
-#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C)
-#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08)
-#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04)
-
-#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03)
-#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02)
-#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01)
-
-/* PhysDiskStatusFlags defines */
-#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040)
-#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020)
-#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010)
-#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000)
-#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
-#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004)
-#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002)
-#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001)
-
-
-/* RAID Physical Disk Page 1 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhysDiskPaths at runtime.
- */
-#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
-#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1)
-#endif
-
-typedef struct _MPI2_RAIDPHYSDISK1_PATH
-{
- U16 DevHandle; /* 0x00 */
- U16 Reserved1; /* 0x02 */
- U64 WWID; /* 0x04 */
- U64 OwnerWWID; /* 0x0C */
- U8 OwnerIdentifier; /* 0x14 */
- U8 Reserved2; /* 0x15 */
- U16 Flags; /* 0x16 */
-} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH,
- Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t;
-
-/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
-#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004)
-#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002)
-#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001)
-
-typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
-{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U8 NumPhysDiskPaths; /* 0x04 */
- U8 PhysDiskNum; /* 0x05 */
- U16 Reserved1; /* 0x06 */
- U32 Reserved2; /* 0x08 */
- MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */
-} MPI2_CONFIG_PAGE_RD_PDISK_1,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
- Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t;
-
-#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02)
-
-
-/****************************************************************************
-* values for fields used by several types of SAS Config Pages
-****************************************************************************/
-
-/* values for NegotiatedLinkRates fields */
-#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0)
-#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4)
-#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F)
-/* link rates used for Negotiated Physical and Logical Link Rate */
-#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00)
-#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01)
-#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02)
-#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03)
-#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04)
-#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05)
-#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06)
-#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08)
-#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
-#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
-
-
-/* values for AttachedPhyInfo fields */
-#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040)
-#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020)
-#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010)
-
-#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F)
-#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000)
-#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001)
-#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002)
-#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003)
-#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004)
-#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005)
-#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006)
-#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007)
-#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008)
-
-
-/* values for PhyInfo fields */
-#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000)
-
-#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000)
-#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27)
-#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000)
-#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000)
-#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000)
-
-#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000)
-#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000)
-#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000)
-#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000)
-#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000)
-#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000)
-
-#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000)
-#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000)
-#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000)
-#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000)
-#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000)
-#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000)
-#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000)
-#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000)
-#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000)
-#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000)
-
-#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000)
-#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
-#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000)
-#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000)
-
-#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00)
-#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8)
-
-#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0)
-#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000)
-#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010)
-#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020)
-
-
-/* values for SAS ProgrammedLinkRate fields */
-#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0)
-#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00)
-#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80)
-#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90)
-#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0)
-#define MPI25_SAS_PRATE_MAX_RATE_12_0 (0xB0)
-#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F)
-#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00)
-#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08)
-#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09)
-#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A)
-
-
-/* values for SAS HwLinkRate fields */
-#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0)
-#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80)
-#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90)
-#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0)
-#define MPI25_SAS_HWRATE_MAX_RATE_12_0 (0xB0)
-#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F)
-#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08)
-#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09)
-#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A)
-
-
-
-/****************************************************************************
-* SAS IO Unit Config Pages
-****************************************************************************/
-
-/* SAS IO Unit Page 0 */
-
-typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA
-{
- U8 Port; /* 0x00 */
- U8 PortFlags; /* 0x01 */
- U8 PhyFlags; /* 0x02 */
- U8 NegotiatedLinkRate; /* 0x03 */
- U32 ControllerPhyDeviceInfo;/* 0x04 */
- U16 AttachedDevHandle; /* 0x08 */
- U16 ControllerDevHandle; /* 0x0A */
- U32 DiscoveryStatus; /* 0x0C */
- U32 Reserved; /* 0x10 */
-} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
- Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t;
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
-#define MPI2_SAS_IOUNIT0_PHY_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U8 NumPhys; /* 0x0C */
- U8 Reserved2; /* 0x0D */
- U16 Reserved3; /* 0x0E */
- MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /* 0x10 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_0,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
- Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t;
-
-#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05)
-
-/* values for SAS IO Unit Page 0 PortFlags */
-#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08)
-#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01)
-
-/* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10)
-#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
-
-/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
-
-/* values for SAS IO Unit Page 0 DiscoveryStatus */
-#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
-#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
-#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000)
-#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
-#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000)
-#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
-#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
-#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000)
-#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
-#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
-#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400)
-#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
-#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100)
-#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080)
-#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040)
-#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020)
-#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010)
-#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004)
-#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002)
-#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001)
-
-
-/* SAS IO Unit Page 1 */
-
-typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA
-{
- U8 Port; /* 0x00 */
- U8 PortFlags; /* 0x01 */
- U8 PhyFlags; /* 0x02 */
- U8 MaxMinLinkRate; /* 0x03 */
- U32 ControllerPhyDeviceInfo; /* 0x04 */
- U16 MaxTargetPortConnectTime; /* 0x08 */
- U16 Reserved1; /* 0x0A */
-} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
- Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t;
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
-#define MPI2_SAS_IOUNIT1_PHY_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U16 ControlFlags; /* 0x08 */
- U16 SASNarrowMaxQueueDepth; /* 0x0A */
- U16 AdditionalControlFlags; /* 0x0C */
- U16 SASWideMaxQueueDepth; /* 0x0E */
- U8 NumPhys; /* 0x10 */
- U8 SATAMaxQDepth; /* 0x11 */
- U8 ReportDeviceMissingDelay; /* 0x12 */
- U8 IODeviceMissingDelay; /* 0x13 */
- MPI2_SAS_IO_UNIT1_PHY_DATA PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /* 0x14 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_1,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
- Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t;
-
-#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09)
-
-/* values for SAS IO Unit Page 1 ControlFlags */
-#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
-
-#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
-#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
-#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0)
-#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1)
-#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2)
-
-#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
-#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008)
-#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
-#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
-#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
-
-/* values for SAS IO Unit Page 1 AdditionalControlFlags */
-#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080)
-#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
-#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020)
-#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010)
-#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008)
-#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004)
-#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002)
-#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
-
-/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
-#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F)
-#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80)
-
-/* values for SAS IO Unit Page 1 PortFlags */
-#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
-
-/* values for SAS IO Unit Page 1 PhyFlags */
-#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10)
-#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
-
-/* values for SAS IO Unit Page 1 MaxMinLinkRate */
-#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0)
-#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80)
-#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90)
-#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0)
-#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F)
-#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08)
-#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09)
-#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A)
-
-/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
-
-
-/* SAS IO Unit Page 4 */
-
-typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP
-{
- U8 MaxTargetSpinup; /* 0x00 */
- U8 SpinupDelay; /* 0x01 */
- U8 SpinupFlags; /* 0x02 */
- U8 Reserved1; /* 0x03 */
-} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
- Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t;
-
-/* defines for SAS IO Unit Page 4 SpinupFlags */
-#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG (0x01)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
-#define MPI2_SAS_IOUNIT4_PHY_MAX (4)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- MPI2_SAS_IOUNIT4_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */
- U32 Reserved1; /* 0x18 */
- U32 Reserved2; /* 0x1C */
- U32 Reserved3; /* 0x20 */
- U8 BootDeviceWaitTime; /* 0x24 */
- U8 Reserved4; /* 0x25 */
- U16 Reserved5; /* 0x26 */
- U8 NumPhys; /* 0x28 */
- U8 PEInitialSpinupDelay; /* 0x29 */
- U8 PEReplyDelay; /* 0x2A */
- U8 Flags; /* 0x2B */
- U8 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /* 0x2C */
-} MPI2_CONFIG_PAGE_SASIOUNIT_4,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
- Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t;
-
-#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02)
-
-/* defines for Flags field */
-#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01)
-
-/* defines for PHY field */
-#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03)
-
-
-/* SAS IO Unit Page 5 */
-
-typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS {
- U8 ControlFlags; /* 0x00 */
- U8 PortWidthModGroup; /* 0x01 */
- U16 InactivityTimerExponent; /* 0x02 */
- U8 SATAPartialTimeout; /* 0x04 */
- U8 Reserved2; /* 0x05 */
- U8 SATASlumberTimeout; /* 0x06 */
- U8 Reserved3; /* 0x07 */
- U8 SASPartialTimeout; /* 0x08 */
- U8 Reserved4; /* 0x09 */
- U8 SASSlumberTimeout; /* 0x0A */
- U8 Reserved5; /* 0x0B */
-} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
- MPI2_POINTER PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
- Mpi2SasIOUnit5PhyPmSettings_t, MPI2_POINTER pMpi2SasIOUnit5PhyPmSettings_t;
-
-/* defines for ControlFlags field */
-#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE (0x08)
-#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE (0x04)
-#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02)
-#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01)
-
-/* defines for PortWidthModeGroup field */
-#define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF)
-
-/* defines for InactivityTimerExponent field */
-#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12)
-#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL (0x0700)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL (8)
-#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER (0x0070)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER (4)
-#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL (0x0007)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL (0)
-
-#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS (7)
-#define MPI2_SASIOUNIT5_ITE_ONE_SECOND (6)
-#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS (5)
-#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS (4)
-#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND (3)
-#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS (2)
-#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS (1)
-#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
-#define MPI2_SAS_IOUNIT5_PHY_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 NumPhys; /* 0x08 */
- U8 Reserved1; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U32 Reserved3; /* 0x0C */
- MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS SASPhyPowerManagementSettings
- [MPI2_SAS_IOUNIT5_PHY_MAX]; /* 0x10 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_5,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
- Mpi2SasIOUnitPage5_t, MPI2_POINTER pMpi2SasIOUnitPage5_t;
-
-#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01)
-
-
-/* SAS IO Unit Page 6 */
-
-typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS {
- U8 CurrentStatus; /* 0x00 */
- U8 CurrentModulation; /* 0x01 */
- U8 CurrentUtilization; /* 0x02 */
- U8 Reserved1; /* 0x03 */
- U32 Reserved2; /* 0x04 */
-} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
- MPI2_POINTER PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
- Mpi2SasIOUnit6PortWidthModGroupStatus_t,
- MPI2_POINTER pMpi2SasIOUnit6PortWidthModGroupStatus_t;
-
-/* defines for CurrentStatus field */
-#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00)
-#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01)
-#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02)
-#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03)
-#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04)
-#define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05)
-#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06)
-#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07)
-
-/* defines for CurrentModulation field */
-#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00)
-#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01)
-#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02)
-#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumGroups at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
-#define MPI2_SAS_IOUNIT6_GROUP_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U32 Reserved2; /* 0x0C */
- U8 NumGroups; /* 0x10 */
- U8 Reserved3; /* 0x11 */
- U16 Reserved4; /* 0x12 */
- MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
- PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /* 0x14 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_6,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
- Mpi2SasIOUnitPage6_t, MPI2_POINTER pMpi2SasIOUnitPage6_t;
-
-#define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00)
-
-
-/* SAS IO Unit Page 7 */
-
-typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS {
- U8 Flags; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U8 Threshold75Pct; /* 0x04 */
- U8 Threshold50Pct; /* 0x05 */
- U8 Threshold25Pct; /* 0x06 */
- U8 Reserved3; /* 0x07 */
-} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
- MPI2_POINTER PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
- Mpi2SasIOUnit7PortWidthModGroupSettings_t,
- MPI2_POINTER pMpi2SasIOUnit7PortWidthModGroupSettings_t;
-
-/* defines for Flags field */
-#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01)
-
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumGroups at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
-#define MPI2_SAS_IOUNIT7_GROUP_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 SamplingInterval; /* 0x08 */
- U8 WindowLength; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U32 Reserved2; /* 0x0C */
- U32 Reserved3; /* 0x10 */
- U8 NumGroups; /* 0x14 */
- U8 Reserved4; /* 0x15 */
- U16 Reserved5; /* 0x16 */
- MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
- PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX]; /* 0x18 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_7,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
- Mpi2SasIOUnitPage7_t, MPI2_POINTER pMpi2SasIOUnitPage7_t;
-
-#define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00)
-
-
-/* SAS IO Unit Page 8 */
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U32 PowerManagementCapabilities;/* 0x0C */
- U32 Reserved2; /* 0x10 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_8,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8,
- Mpi2SasIOUnitPage8_t, MPI2_POINTER pMpi2SasIOUnitPage8_t;
-
-#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00)
-
-/* defines for PowerManagementCapabilities field */
-#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001)
-
-
-
-/* SAS IO Unit Page 16 */
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U64 TimeStamp; /* 0x08 */
- U32 Reserved1; /* 0x10 */
- U32 Reserved2; /* 0x14 */
- U32 FastPathPendedRequests; /* 0x18 */
- U32 FastPathUnPendedRequests; /* 0x1C */
- U32 FastPathHostRequestStarts; /* 0x20 */
- U32 FastPathFirmwareRequestStarts; /* 0x24 */
- U32 FastPathHostCompletions; /* 0x28 */
- U32 FastPathFirmwareCompletions; /* 0x2C */
- U32 NonFastPathRequestStarts; /* 0x30 */
- U32 NonFastPathHostCompletions; /* 0x30 */
-} MPI2_CONFIG_PAGE_SASIOUNIT16,
-MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT16,
-Mpi2SasIOUnitPage16_t, MPI2_POINTER pMpi2SasIOUnitPage16_t;
-
-#define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00)
-
-
-/****************************************************************************
-* SAS Expander Config Pages
-****************************************************************************/
-
-/* SAS Expander Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 PhysicalPort; /* 0x08 */
- U8 ReportGenLength; /* 0x09 */
- U16 EnclosureHandle; /* 0x0A */
- U64 SASAddress; /* 0x0C */
- U32 DiscoveryStatus; /* 0x14 */
- U16 DevHandle; /* 0x18 */
- U16 ParentDevHandle; /* 0x1A */
- U16 ExpanderChangeCount; /* 0x1C */
- U16 ExpanderRouteIndexes; /* 0x1E */
- U8 NumPhys; /* 0x20 */
- U8 SASLevel; /* 0x21 */
- U16 Flags; /* 0x22 */
- U16 STPBusInactivityTimeLimit; /* 0x24 */
- U16 STPMaxConnectTimeLimit; /* 0x26 */
- U16 STP_SMP_NexusLossTime; /* 0x28 */
- U16 MaxNumRoutedSasAddresses; /* 0x2A */
- U64 ActiveZoneManagerSASAddress;/* 0x2C */
- U16 ZoneLockInactivityLimit; /* 0x34 */
- U16 Reserved1; /* 0x36 */
- U8 TimeToReducedFunc; /* 0x38 */
- U8 InitialTimeToReducedFunc; /* 0x39 */
- U8 MaxReducedFuncTime; /* 0x3A */
- U8 Reserved2; /* 0x3B */
-} MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
- Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t;
-
-#define MPI2_SASEXPANDER0_PAGEVERSION (0x06)
-
-/* values for SAS Expander Page 0 DiscoveryStatus field */
-#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
-#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
-#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000)
-#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
-#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000)
-#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
-#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
-#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000)
-#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
-#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800)
-#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400)
-#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200)
-#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100)
-#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080)
-#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040)
-#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020)
-#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010)
-#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004)
-#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002)
-#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
-
-/* values for SAS Expander Page 0 Flags field */
-#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000)
-#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000)
-#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800)
-#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400)
-#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200)
-#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100)
-#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080)
-#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010)
-#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004)
-#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002)
-#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001)
-
-
-/* SAS Expander Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 PhysicalPort; /* 0x08 */
- U8 Reserved1; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U8 NumPhys; /* 0x0C */
- U8 Phy; /* 0x0D */
- U16 NumTableEntriesProgrammed; /* 0x0E */
- U8 ProgrammedLinkRate; /* 0x10 */
- U8 HwLinkRate; /* 0x11 */
- U16 AttachedDevHandle; /* 0x12 */
- U32 PhyInfo; /* 0x14 */
- U32 AttachedDeviceInfo; /* 0x18 */
- U16 ExpanderDevHandle; /* 0x1C */
- U8 ChangeCount; /* 0x1E */
- U8 NegotiatedLinkRate; /* 0x1F */
- U8 PhyIdentifier; /* 0x20 */
- U8 AttachedPhyIdentifier; /* 0x21 */
- U8 Reserved3; /* 0x22 */
- U8 DiscoveryInfo; /* 0x23 */
- U32 AttachedPhyInfo; /* 0x24 */
- U8 ZoneGroup; /* 0x28 */
- U8 SelfConfigStatus; /* 0x29 */
- U16 Reserved4; /* 0x2A */
-} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
- Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t;
-
-#define MPI2_SASEXPANDER1_PAGEVERSION (0x02)
-
-/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
-
-/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
-
-/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
-
-/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
-
-/* values for SAS Expander Page 1 DiscoveryInfo field */
-#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04)
-#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02)
-#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01)
-
-/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
-
-/****************************************************************************
-* SAS Device Config Pages
-****************************************************************************/
-
-/* SAS Device Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U16 Slot; /* 0x08 */
- U16 EnclosureHandle; /* 0x0A */
- U64 SASAddress; /* 0x0C */
- U16 ParentDevHandle; /* 0x14 */
- U8 PhyNum; /* 0x16 */
- U8 AccessStatus; /* 0x17 */
- U16 DevHandle; /* 0x18 */
- U8 AttachedPhyIdentifier; /* 0x1A */
- U8 ZoneGroup; /* 0x1B */
- U32 DeviceInfo; /* 0x1C */
- U16 Flags; /* 0x20 */
- U8 PhysicalPort; /* 0x22 */
- U8 MaxPortConnections; /* 0x23 */
- U64 DeviceName; /* 0x24 */
- U8 PortGroups; /* 0x2C */
- U8 DmaGroup; /* 0x2D */
- U8 ControlGroup; /* 0x2E */
- U8 EnclosureLevel; /* 0x2F */
- U8 ConnectorName[4]; /* 0x30 */
- U32 Reserved3; /* 0x34 */
-} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
- Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t;
-
-#define MPI2_SASDEVICE0_PAGEVERSION (0x09)
-
-/* values for SAS Device Page 0 AccessStatus field */
-#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04)
-#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05)
-#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06)
-#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07)
-/* specific values for SATA Init failures */
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F)
-
-/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
-
-/* values for SAS Device Page 0 Flags field */
-#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE (0x8000)
-#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000)
-#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
-#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
-#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
-#define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002)
-#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
-
-
-/* SAS Device Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U64 SASAddress; /* 0x0C */
- U32 Reserved2; /* 0x14 */
- U16 DevHandle; /* 0x18 */
- U16 Reserved3; /* 0x1A */
- U8 InitialRegDeviceFIS[20];/* 0x1C */
-} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
- Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t;
-
-#define MPI2_SASDEVICE1_PAGEVERSION (0x01)
-
-
-/****************************************************************************
-* SAS PHY Config Pages
-****************************************************************************/
-
-/* SAS PHY Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U16 OwnerDevHandle; /* 0x08 */
- U16 Reserved1; /* 0x0A */
- U16 AttachedDevHandle; /* 0x0C */
- U8 AttachedPhyIdentifier; /* 0x0E */
- U8 Reserved2; /* 0x0F */
- U32 AttachedPhyInfo; /* 0x10 */
- U8 ProgrammedLinkRate; /* 0x14 */
- U8 HwLinkRate; /* 0x15 */
- U8 ChangeCount; /* 0x16 */
- U8 Flags; /* 0x17 */
- U32 PhyInfo; /* 0x18 */
- U8 NegotiatedLinkRate; /* 0x1C */
- U8 Reserved3; /* 0x1D */
- U16 Reserved4; /* 0x1E */
-} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
- Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t;
-
-#define MPI2_SASPHY0_PAGEVERSION (0x03)
-
-/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
-
-/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
-
-/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
-
-/* values for SAS PHY Page 0 Flags field */
-#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
-
-/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
-
-
-/* SAS PHY Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U32 InvalidDwordCount; /* 0x0C */
- U32 RunningDisparityErrorCount; /* 0x10 */
- U32 LossDwordSynchCount; /* 0x14 */
- U32 PhyResetProblemCount; /* 0x18 */
-} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
- Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t;
-
-#define MPI2_SASPHY1_PAGEVERSION (0x01)
-
-
-/* SAS PHY Page 2 */
-
-typedef struct _MPI2_SASPHY2_PHY_EVENT {
- U8 PhyEventCode; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 PhyEventInfo; /* 0x04 */
-} MPI2_SASPHY2_PHY_EVENT, MPI2_POINTER PTR_MPI2_SASPHY2_PHY_EVENT,
- Mpi2SasPhy2PhyEvent_t, MPI2_POINTER pMpi2SasPhy2PhyEvent_t;
-
-/* use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */
-
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhyEvents at runtime.
- */
-#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
-#define MPI2_SASPHY2_PHY_EVENT_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U8 NumPhyEvents; /* 0x0C */
- U8 Reserved2; /* 0x0D */
- U16 Reserved3; /* 0x0E */
- MPI2_SASPHY2_PHY_EVENT PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX];
- /* 0x10 */
-} MPI2_CONFIG_PAGE_SAS_PHY_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
- Mpi2SasPhyPage2_t, MPI2_POINTER pMpi2SasPhyPage2_t;
-
-#define MPI2_SASPHY2_PAGEVERSION (0x00)
-
-
-/* SAS PHY Page 3 */
-
-typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
- U8 PhyEventCode; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U8 CounterType; /* 0x04 */
- U8 ThresholdWindow; /* 0x05 */
- U8 TimeUnits; /* 0x06 */
- U8 Reserved3; /* 0x07 */
- U32 EventThreshold; /* 0x08 */
- U16 ThresholdFlags; /* 0x0C */
- U16 Reserved4; /* 0x0E */
-} MPI2_SASPHY3_PHY_EVENT_CONFIG, MPI2_POINTER PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG,
- Mpi2SasPhy3PhyEventConfig_t, MPI2_POINTER pMpi2SasPhy3PhyEventConfig_t;
-
-/* values for PhyEventCode field */
-#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00)
-#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01)
-#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02)
-#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03)
-#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04)
-#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05)
-#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06)
-#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20)
-#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21)
-#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22)
-#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23)
-#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24)
-#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25)
-#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26)
-#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27)
-#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28)
-#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29)
-#define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A)
-#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B)
-#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C)
-#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D)
-#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E)
-#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40)
-#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41)
-#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42)
-#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43)
-#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44)
-#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45)
-#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50)
-#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51)
-#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52)
-#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60)
-#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61)
-#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63)
-#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0)
-#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1)
-#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2)
-
-/* values for the CounterType field */
-#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00)
-#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01)
-#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02)
-
-/* values for the TimeUnits field */
-#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00)
-#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01)
-#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02)
-#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03)
-
-/* values for the ThresholdFlags field */
-#define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002)
-#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhyEvents at runtime.
- */
-#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
-#define MPI2_SASPHY3_PHY_EVENT_MAX (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U8 NumPhyEvents; /* 0x0C */
- U8 Reserved2; /* 0x0D */
- U16 Reserved3; /* 0x0E */
- MPI2_SASPHY3_PHY_EVENT_CONFIG PhyEventConfig
- [MPI2_SASPHY3_PHY_EVENT_MAX]; /* 0x10 */
-} MPI2_CONFIG_PAGE_SAS_PHY_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
- Mpi2SasPhyPage3_t, MPI2_POINTER pMpi2SasPhyPage3_t;
-
-#define MPI2_SASPHY3_PAGEVERSION (0x00)
-
-
-/* SAS PHY Page 4 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U16 Reserved1; /* 0x08 */
- U8 Reserved2; /* 0x0A */
- U8 Flags; /* 0x0B */
- U8 InitialFrame[28]; /* 0x0C */
-} MPI2_CONFIG_PAGE_SAS_PHY_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_4,
- Mpi2SasPhyPage4_t, MPI2_POINTER pMpi2SasPhyPage4_t;
-
-#define MPI2_SASPHY4_PAGEVERSION (0x00)
-
-/* values for the Flags field */
-#define MPI2_SASPHY4_FLAGS_FRAME_VALID (0x02)
-#define MPI2_SASPHY4_FLAGS_SATA_FRAME (0x01)
-
-
-
-
-/****************************************************************************
-* SAS Port Config Pages
-****************************************************************************/
-
-/* SAS Port Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 PortNumber; /* 0x08 */
- U8 PhysicalPort; /* 0x09 */
- U8 PortWidth; /* 0x0A */
- U8 PhysicalPortWidth; /* 0x0B */
- U8 ZoneGroup; /* 0x0C */
- U8 Reserved1; /* 0x0D */
- U16 Reserved2; /* 0x0E */
- U64 SASAddress; /* 0x10 */
- U32 DeviceInfo; /* 0x18 */
- U32 Reserved3; /* 0x1C */
- U32 Reserved4; /* 0x20 */
-} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
- Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t;
-
-#define MPI2_SASPORT0_PAGEVERSION (0x00)
-
-/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
-
-
-/****************************************************************************
-* SAS Enclosure Config Pages
-****************************************************************************/
-
-/* SAS Enclosure Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U64 EnclosureLogicalID; /* 0x0C */
- U16 Flags; /* 0x14 */
- U16 EnclosureHandle; /* 0x16 */
- U16 NumSlots; /* 0x18 */
- U16 StartSlot; /* 0x1A */
- U8 Reserved2; /* 0x1C */
- U8 EnclosureLevel; /* 0x1D */
- U16 SEPDevHandle; /* 0x1E */
- U32 Reserved3; /* 0x20 */
- U32 Reserved4; /* 0x24 */
-} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
- Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t;
-
-#define MPI2_SASENCLOSURE0_PAGEVERSION (0x04)
-
-/* values for SAS Enclosure Page 0 Flags field */
-#define MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
-
-
-/****************************************************************************
-* Log Config Page
-****************************************************************************/
-
-/* Log Page 0 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumLogEntries at runtime.
- */
-#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
-#define MPI2_LOG_0_NUM_LOG_ENTRIES (1)
-#endif
-
-#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C)
-
-typedef struct _MPI2_LOG_0_ENTRY
-{
- U64 TimeStamp; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U16 LogSequence; /* 0x0C */
- U16 LogEntryQualifier; /* 0x0E */
- U8 VP_ID; /* 0x10 */
- U8 VF_ID; /* 0x11 */
- U16 Reserved2; /* 0x12 */
- U8 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */
-} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY,
- Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t;
-
-/* values for Log Page 0 LogEntry LogEntryQualifier field */
-#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000)
-#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001)
-#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002)
-#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000)
-#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF)
-
-typedef struct _MPI2_CONFIG_PAGE_LOG_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U32 Reserved2; /* 0x0C */
- U16 NumLogEntries; /* 0x10 */
- U16 Reserved3; /* 0x12 */
- MPI2_LOG_0_ENTRY LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */
-} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0,
- Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t;
-
-#define MPI2_LOG_0_PAGEVERSION (0x02)
-
-
-/****************************************************************************
-* RAID Config Page
-****************************************************************************/
-
-/* RAID Page 0 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumElements at runtime.
- */
-#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
-#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1)
-#endif
-
-typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT
-{
- U16 ElementFlags; /* 0x00 */
- U16 VolDevHandle; /* 0x02 */
- U8 HotSparePool; /* 0x04 */
- U8 PhysDiskNum; /* 0x05 */
- U16 PhysDiskDevHandle; /* 0x06 */
-} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
- MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
- Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t;
-
-/* values for the ElementFlags field */
-#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F)
-#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000)
-#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001)
-#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002)
-#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003)
-
-
-typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 NumHotSpares; /* 0x08 */
- U8 NumPhysDisks; /* 0x09 */
- U8 NumVolumes; /* 0x0A */
- U8 ConfigNum; /* 0x0B */
- U32 Flags; /* 0x0C */
- U8 ConfigGUID[24]; /* 0x10 */
- U32 Reserved1; /* 0x28 */
- U8 NumElements; /* 0x2C */
- U8 Reserved2; /* 0x2D */
- U16 Reserved3; /* 0x2E */
- MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */
-} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
- Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t;
-
-#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00)
-
-/* values for RAID Configuration Page 0 Flags field */
-#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001)
-
-
-/****************************************************************************
-* Driver Persistent Mapping Config Pages
-****************************************************************************/
-
-/* Driver Persistent Mapping Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY
-{
- U64 PhysicalIdentifier; /* 0x00 */
- U16 MappingInformation; /* 0x08 */
- U16 DeviceIndex; /* 0x0A */
- U32 PhysicalBitsMapping; /* 0x0C */
- U32 Reserved1; /* 0x10 */
-} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
- Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t;
-
-typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0
-{
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /* 0x08 */
-} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
- Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t;
-
-#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00)
-
-/* values for Driver Persistent Mapping Page 0 MappingInformation field */
-#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0)
-#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4)
-#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F)
-
-
-/****************************************************************************
-* Ethernet Config Pages
-****************************************************************************/
-
-/* Ethernet Page 0 */
-
-/* IP address (union of IPv4 and IPv6) */
-typedef union _MPI2_ETHERNET_IP_ADDR {
- U32 IPv4Addr;
- U32 IPv6Addr[4];
-} MPI2_ETHERNET_IP_ADDR, MPI2_POINTER PTR_MPI2_ETHERNET_IP_ADDR,
- Mpi2EthernetIpAddr_t, MPI2_POINTER pMpi2EthernetIpAddr_t;
-
-#define MPI2_ETHERNET_HOST_NAME_LENGTH (32)
-
-typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U8 NumInterfaces; /* 0x08 */
- U8 Reserved0; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U32 Status; /* 0x0C */
- U8 MediaState; /* 0x10 */
- U8 Reserved2; /* 0x11 */
- U16 Reserved3; /* 0x12 */
- U8 MacAddress[6]; /* 0x14 */
- U8 Reserved4; /* 0x1A */
- U8 Reserved5; /* 0x1B */
- MPI2_ETHERNET_IP_ADDR IpAddress; /* 0x1C */
- MPI2_ETHERNET_IP_ADDR SubnetMask; /* 0x2C */
- MPI2_ETHERNET_IP_ADDR GatewayIpAddress; /* 0x3C */
- MPI2_ETHERNET_IP_ADDR DNS1IpAddress; /* 0x4C */
- MPI2_ETHERNET_IP_ADDR DNS2IpAddress; /* 0x5C */
- MPI2_ETHERNET_IP_ADDR DhcpIpAddress; /* 0x6C */
- U8 HostName
- [MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */
-} MPI2_CONFIG_PAGE_ETHERNET_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_0,
- Mpi2EthernetPage0_t, MPI2_POINTER pMpi2EthernetPage0_t;
-
-#define MPI2_ETHERNETPAGE0_PAGEVERSION (0x00)
-
-/* values for Ethernet Page 0 Status field */
-#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE (0x80000000)
-#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE (0x40000000)
-#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED (0x20000000)
-#define MPI2_ETHPG0_STATUS_DEFAULT_IF (0x00000100)
-#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED (0x00000080)
-#define MPI2_ETHPG0_STATUS_TELNET_ENABLED (0x00000040)
-#define MPI2_ETHPG0_STATUS_SSH2_ENABLED (0x00000020)
-#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED (0x00000010)
-#define MPI2_ETHPG0_STATUS_IPV6_ENABLED (0x00000008)
-#define MPI2_ETHPG0_STATUS_IPV4_ENABLED (0x00000004)
-#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES (0x00000002)
-#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED (0x00000001)
-
-/* values for Ethernet Page 0 MediaState field */
-#define MPI2_ETHPG0_MS_DUPLEX_MASK (0x80)
-#define MPI2_ETHPG0_MS_HALF_DUPLEX (0x00)
-#define MPI2_ETHPG0_MS_FULL_DUPLEX (0x80)
-
-#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK (0x07)
-#define MPI2_ETHPG0_MS_NOT_CONNECTED (0x00)
-#define MPI2_ETHPG0_MS_10MBIT (0x01)
-#define MPI2_ETHPG0_MS_100MBIT (0x02)
-#define MPI2_ETHPG0_MS_1GBIT (0x03)
-
-
-/* Ethernet Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 Reserved0; /* 0x08 */
- U32 Flags; /* 0x0C */
- U8 MediaState; /* 0x10 */
- U8 Reserved1; /* 0x11 */
- U16 Reserved2; /* 0x12 */
- U8 MacAddress[6]; /* 0x14 */
- U8 Reserved3; /* 0x1A */
- U8 Reserved4; /* 0x1B */
- MPI2_ETHERNET_IP_ADDR StaticIpAddress; /* 0x1C */
- MPI2_ETHERNET_IP_ADDR StaticSubnetMask; /* 0x2C */
- MPI2_ETHERNET_IP_ADDR StaticGatewayIpAddress; /* 0x3C */
- MPI2_ETHERNET_IP_ADDR StaticDNS1IpAddress; /* 0x4C */
- MPI2_ETHERNET_IP_ADDR StaticDNS2IpAddress; /* 0x5C */
- U32 Reserved5; /* 0x6C */
- U32 Reserved6; /* 0x70 */
- U32 Reserved7; /* 0x74 */
- U32 Reserved8; /* 0x78 */
- U8 HostName
- [MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */
-} MPI2_CONFIG_PAGE_ETHERNET_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_1,
- Mpi2EthernetPage1_t, MPI2_POINTER pMpi2EthernetPage1_t;
-
-#define MPI2_ETHERNETPAGE1_PAGEVERSION (0x00)
-
-/* values for Ethernet Page 1 Flags field */
-#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF (0x00000100)
-#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD (0x00000080)
-#define MPI2_ETHPG1_FLAG_ENABLE_TELNET (0x00000040)
-#define MPI2_ETHPG1_FLAG_ENABLE_SSH2 (0x00000020)
-#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT (0x00000010)
-#define MPI2_ETHPG1_FLAG_ENABLE_IPV6 (0x00000008)
-#define MPI2_ETHPG1_FLAG_ENABLE_IPV4 (0x00000004)
-#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES (0x00000002)
-#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF (0x00000001)
-
-/* values for Ethernet Page 1 MediaState field */
-#define MPI2_ETHPG1_MS_DUPLEX_MASK (0x80)
-#define MPI2_ETHPG1_MS_HALF_DUPLEX (0x00)
-#define MPI2_ETHPG1_MS_FULL_DUPLEX (0x80)
-
-#define MPI2_ETHPG1_MS_DATA_RATE_MASK (0x07)
-#define MPI2_ETHPG1_MS_DATA_RATE_AUTO (0x00)
-#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT (0x01)
-#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT (0x02)
-#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03)
-
-
-/****************************************************************************
-* Extended Manufacturing Config Pages
-****************************************************************************/
-
-/*
- * Generic structure to use for product-specific extended manufacturing pages
- * (currently Extended Manufacturing Page 40 through Extended Manufacturing
- * Page 60).
- */
-
-typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
- MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
- U32 ProductSpecificInfo; /* 0x08 */
-} MPI2_CONFIG_PAGE_EXT_MAN_PS,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
- Mpi2ExtManufacturingPagePS_t,
- MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
-
-/* PageVersion should be provided by product-specific code */
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
deleted file mode 100644
index eea1a16b13ec..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_init.h
- * Title: MPI SCSI initiator mode messages and structures
- * Creation Date: June 23, 2006
- *
- * mpi2_init.h Version: 02.00.15
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t.
- * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines.
- * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention.
- * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
- * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t.
- * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO
- * Control field Task Attribute flags.
- * Moved LUN field defines to mpi2.h because they are
- * common to many structures.
- * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to
- * Query Asynchronous Event.
- * Defined two new bits in the SlotStatus field of the SCSI
- * Enclosure Processor Request and Reply.
- * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for
- * both SCSI IO Error Reply and SCSI Task Management Reply.
- * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
- * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
- * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it.
- * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request.
- * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
- * 02-06-12 02.00.13 Added alternate defines for Task Priority / Command
- * Priority to match SAM-4.
- * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION.
- * 04-09-13 02.00.15 Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY,
- * replacing the Reserved4 field.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_INIT_H
-#define MPI2_INIT_H
-
-/*****************************************************************************
-*
-* SCSI Initiator Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-* SCSI IO messages and associated structures
-****************************************************************************/
-
-typedef struct
-{
- U8 CDB[20]; /* 0x00 */
- U32 PrimaryReferenceTag; /* 0x14 */
- U16 PrimaryApplicationTag; /* 0x18 */
- U16 PrimaryApplicationTagMask; /* 0x1A */
- U32 TransferLength; /* 0x1C */
-} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
- Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
-
-typedef union
-{
- U8 CDB32[32];
- MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
- MPI2_SGE_SIMPLE_UNION SGE;
-} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
- Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
-
-/* SCSI IO Request Message */
-typedef struct _MPI2_SCSI_IO_REQUEST
-{
- U16 DevHandle; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved1; /* 0x04 */
- U8 Reserved2; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U32 SenseBufferLowAddress; /* 0x0C */
- U16 SGLFlags; /* 0x10 */
- U8 SenseBufferLength; /* 0x12 */
- U8 Reserved4; /* 0x13 */
- U8 SGLOffset0; /* 0x14 */
- U8 SGLOffset1; /* 0x15 */
- U8 SGLOffset2; /* 0x16 */
- U8 SGLOffset3; /* 0x17 */
- U32 SkipCount; /* 0x18 */
- U32 DataLength; /* 0x1C */
- U32 BidirectionalDataLength; /* 0x20 */
- U16 IoFlags; /* 0x24 */
- U16 EEDPFlags; /* 0x26 */
- U32 EEDPBlockSize; /* 0x28 */
- U32 SecondaryReferenceTag; /* 0x2C */
- U16 SecondaryApplicationTag; /* 0x30 */
- U16 ApplicationTagTranslationMask; /* 0x32 */
- U8 LUN[8]; /* 0x34 */
- U32 Control; /* 0x3C */
- MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
-
-#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */
- MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
-#endif
-
- MPI2_SGE_IO_UNION SGL; /* 0x60 */
-
-} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
- Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
-
-/* SCSI IO MsgFlags bits */
-
-/* MsgFlags for SenseBufferAddressSpace */
-#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C)
-#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00)
-#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04)
-#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08)
-#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C)
-
-/* SCSI IO SGLFlags bits */
-
-/* base values for Data Location Address Space */
-#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C)
-#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00)
-#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04)
-#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08)
-#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C)
-
-/* base values for Type */
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03)
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00)
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01)
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02)
-
-/* shift values for each sub-field */
-#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12)
-#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8)
-#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
-#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
-
-/* number of SGLOffset fields */
-#define MPI2_SCSIIO_NUM_SGLOFFSETS (4)
-
-/* SCSI IO IoFlags bits */
-
-/* Large CDB Address Space */
-#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000)
-#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000)
-#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000)
-#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000)
-#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000)
-
-#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000)
-#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800)
-#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400)
-#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
-#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF)
-
-/* SCSI IO EEDPFlags bits */
-
-#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000)
-
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
-
-#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008)
-
-#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007)
-#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001)
-#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
-#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
-#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007)
-
-/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
-
-/* SCSI IO Control bits */
-#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000)
-#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26)
-
-#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000)
-#define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24)
-#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000)
-#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
-#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
-#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000)
-
-#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800)
-#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11)
-/* alternate name for the previous field; called Command Priority in SAM-4 */
-#define MPI2_SCSIIO_CONTROL_CMDPRI_MASK (0x00007800)
-#define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT (11)
-
-#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700)
-#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000)
-#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100)
-#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200)
-#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400)
-
-#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0)
-#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000)
-#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040)
-#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080)
-
-
-/* SCSI IO Error Reply Message */
-typedef struct _MPI2_SCSI_IO_REPLY
-{
- U16 DevHandle; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved1; /* 0x04 */
- U8 Reserved2; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U8 SCSIStatus; /* 0x0C */
- U8 SCSIState; /* 0x0D */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 TransferCount; /* 0x14 */
- U32 SenseCount; /* 0x18 */
- U32 ResponseInfo; /* 0x1C */
- U16 TaskTag; /* 0x20 */
- U16 SCSIStatusQualifier; /* 0x22 */
- U32 BidirectionalTransferCount; /* 0x24 */
- U32 Reserved5; /* 0x28 */
- U32 Reserved6; /* 0x2C */
-} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY,
- Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t;
-
-/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
-
-#define MPI2_SCSI_STATUS_GOOD (0x00)
-#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02)
-#define MPI2_SCSI_STATUS_CONDITION_MET (0x04)
-#define MPI2_SCSI_STATUS_BUSY (0x08)
-#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10)
-#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14)
-#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18)
-#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /* obsolete */
-#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28)
-#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30)
-#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40)
-
-/* SCSI IO Reply SCSIState flags */
-
-#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10)
-#define MPI2_SCSI_STATE_TERMINATED (0x08)
-#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04)
-#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02)
-#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01)
-
-/* masks and shifts for the ResponseInfo field */
-
-#define MPI2_SCSI_RI_MASK_REASONCODE (0x000000FF)
-#define MPI2_SCSI_RI_SHIFT_REASONCODE (0)
-
-#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF)
-
-
-/****************************************************************************
-* SCSI Task Management messages
-****************************************************************************/
-
-/* SCSI Task Management Request Message */
-typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
-{
- U16 DevHandle; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U8 Reserved1; /* 0x04 */
- U8 TaskType; /* 0x05 */
- U8 Reserved2; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U8 LUN[8]; /* 0x0C */
- U32 Reserved4[7]; /* 0x14 */
- U16 TaskMID; /* 0x30 */
- U16 Reserved5; /* 0x32 */
-} MPI2_SCSI_TASK_MANAGE_REQUEST,
- MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
- Mpi2SCSITaskManagementRequest_t,
- MPI2_POINTER pMpi2SCSITaskManagementRequest_t;
-
-/* TaskType values */
-
-#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01)
-#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02)
-#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03)
-#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
-#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
-#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
-#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08)
-#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09)
-#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A)
-
-/* obsolete TaskType name */
-#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \
- (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
-
-/* MsgFlags bits */
-
-#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
-#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
-#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
-#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
-
-#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01)
-
-
-
-/* SCSI Task Management Reply Message */
-typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY
-{
- U16 DevHandle; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U8 ResponseCode; /* 0x04 */
- U8 TaskType; /* 0x05 */
- U8 Reserved1; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U16 Reserved3; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 TerminationCount; /* 0x14 */
- U32 ResponseInfo; /* 0x18 */
-} MPI2_SCSI_TASK_MANAGE_REPLY,
- MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
- Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t;
-
-/* ResponseCode values */
-
-#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
-#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
-#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
-#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05)
-#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
-#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
-#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A)
-#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
-
-/* masks and shifts for the ResponseInfo field */
-
-#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE (0x000000FF)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE (0)
-#define MPI2_SCSITASKMGMT_RI_MASK_ARI2 (0x0000FF00)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2 (8)
-#define MPI2_SCSITASKMGMT_RI_MASK_ARI1 (0x00FF0000)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1 (16)
-#define MPI2_SCSITASKMGMT_RI_MASK_ARI0 (0xFF000000)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0 (24)
-
-
-/****************************************************************************
-* SCSI Enclosure Processor messages
-****************************************************************************/
-
-/* SCSI Enclosure Processor Request Message */
-typedef struct _MPI2_SEP_REQUEST
-{
- U16 DevHandle; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U8 Action; /* 0x04 */
- U8 Flags; /* 0x05 */
- U8 Reserved1; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U32 SlotStatus; /* 0x0C */
- U32 Reserved3; /* 0x10 */
- U32 Reserved4; /* 0x14 */
- U32 Reserved5; /* 0x18 */
- U16 Slot; /* 0x1C */
- U16 EnclosureHandle; /* 0x1E */
-} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST,
- Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t;
-
-/* Action defines */
-#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00)
-#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01)
-
-/* Flags defines */
-#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00)
-#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
-
-/* SlotStatus defines */
-#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
-#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
-#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
-#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100)
-#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080)
-#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
-#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010)
-#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008)
-#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004)
-#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002)
-#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001)
-
-
-/* SCSI Enclosure Processor Reply Message */
-typedef struct _MPI2_SEP_REPLY
-{
- U16 DevHandle; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U8 Action; /* 0x04 */
- U8 Flags; /* 0x05 */
- U8 Reserved1; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U16 Reserved3; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 SlotStatus; /* 0x14 */
- U32 Reserved4; /* 0x18 */
- U16 Slot; /* 0x1C */
- U16 EnclosureHandle; /* 0x1E */
-} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY,
- Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t;
-
-/* SlotStatus defines */
-#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
-#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
-#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
-#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100)
-#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080)
-#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
-#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010)
-#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008)
-#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004)
-#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002)
-#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001)
-
-
-#endif
-
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
deleted file mode 100644
index b02de48be204..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ /dev/null
@@ -1,1708 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_ioc.h
- * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
- * Creation Date: October 11, 2006
- *
- * mpi2_ioc.h Version: 02.00.24
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to
- * MaxTargets.
- * Added TotalImageSize field to FWDownload Request.
- * Added reserved words to FWUpload Request.
- * 06-26-07 02.00.02 Added IR Configuration Change List Event.
- * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit
- * request and replaced it with
- * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
- * Replaced the MinReplyQueueDepth field of the IOCFacts
- * reply with MaxReplyDescriptorPostQueueDepth.
- * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
- * depth for the Reply Descriptor Post Queue.
- * Added SASAddress field to Initiator Device Table
- * Overflow Event data.
- * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
- * for SAS Initiator Device Status Change Event data.
- * Modified Reason Code defines for SAS Topology Change
- * List Event data, including adding a bit for PHY Vacant
- * status, and adding a mask for the Reason Code.
- * Added define for
- * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
- * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
- * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of
- * the IOCFacts Reply.
- * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- * Moved MPI2_VERSION_UNION to mpi2.h.
- * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
- * instead of enables, and added SASBroadcastPrimitiveMasks
- * field.
- * Added Log Entry Added Event and related structure.
- * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
- * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
- * Added MaxVolumes and MaxPersistentEntries fields to
- * IOCFacts reply.
- * Added ProtocalFlags and IOCCapabilities fields to
- * MPI2_FW_IMAGE_HEADER.
- * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
- * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
- * a U16 (from a U32).
- * Removed extra 's' from EventMasks name.
- * 06-27-08 02.00.08 Fixed an offset in a comment.
- * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
- * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
- * renamed MinReplyFrameSize to ReplyFrameSize.
- * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
- * Added two new RAIDOperation values for Integrated RAID
- * Operations Status Event data.
- * Added four new IR Configuration Change List Event data
- * ReasonCode values.
- * Added two new ReasonCode defines for SAS Device Status
- * Change Event data.
- * Added three new DiscoveryStatus bits for the SAS
- * Discovery event data.
- * Added Multiplexing Status Change bit to the PhyStatus
- * field of the SAS Topology Change List event data.
- * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
- * BootFlags are now product-specific.
- * Added defines for the indivdual signature bytes
- * for MPI2_INIT_IMAGE_FOOTER.
- * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
- * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
- * define.
- * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
- * define.
- * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
- * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
- * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
- * Added two new reason codes for SAS Device Status Change
- * Event.
- * Added new event: SAS PHY Counter.
- * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure.
- * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- * Added new product id family for 2208.
- * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
- * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
- * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
- * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
- * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
- * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
- * Added Host Based Discovery Phy Event data.
- * Added defines for ProductID Product field
- * (MPI2_FW_HEADER_PID_).
- * Modified values for SAS ProductID Family
- * (MPI2_FW_HEADER_PID_FAMILY_).
- * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines.
- * Added PowerManagementControl Request structures and
- * defines.
- * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete.
- * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
- * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
- * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added
- * SASNotifyPrimitiveMasks field to
- * MPI2_EVENT_NOTIFICATION_REQUEST.
- * Added Temperature Threshold Event.
- * Added Host Message Event.
- * Added Send Host Message request and reply.
- * 05-25-11 02.00.18 For Extended Image Header, added
- * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and
- * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines.
- * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define.
- * 08-24-11 02.00.19 Added PhysicalPort field to
- * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure.
- * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete.
- * 03-29-12 02.00.21 Added a product specific range to event values.
- * 07-26-12 02.00.22 Added MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE.
- * Added ElapsedSeconds field to
- * MPI2_EVENT_DATA_IR_OPERATION_STATUS.
- * 08-19-13 02.00.23 For IOCInit, added MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE
- * and MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY.
- * Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE.
- * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY.
- * Added Encrypted Hash Extended Image.
- * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_IOC_H
-#define MPI2_IOC_H
-
-/*****************************************************************************
-*
-* IOC Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-* IOCInit message
-****************************************************************************/
-
-/* IOCInit Request message */
-typedef struct _MPI2_IOC_INIT_REQUEST
-{
- U8 WhoInit; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 MsgVersion; /* 0x0C */
- U16 HeaderVersion; /* 0x0E */
- U32 Reserved5; /* 0x10 */
- U16 Reserved6; /* 0x14 */
- U8 Reserved7; /* 0x16 */
- U8 HostMSIxVectors; /* 0x17 */
- U16 Reserved8; /* 0x18 */
- U16 SystemRequestFrameSize; /* 0x1A */
- U16 ReplyDescriptorPostQueueDepth; /* 0x1C */
- U16 ReplyFreeQueueDepth; /* 0x1E */
- U32 SenseBufferAddressHigh; /* 0x20 */
- U32 SystemReplyAddressHigh; /* 0x24 */
- U64 SystemRequestFrameBaseAddress; /* 0x28 */
- U64 ReplyDescriptorPostQueueAddress;/* 0x30 */
- U64 ReplyFreeQueueAddress; /* 0x38 */
- U64 TimeStamp; /* 0x40 */
-} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
- Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
-
-/* WhoInit values */
-#define MPI2_WHOINIT_NOT_INITIALIZED (0x00)
-#define MPI2_WHOINIT_SYSTEM_BIOS (0x01)
-#define MPI2_WHOINIT_ROM_BIOS (0x02)
-#define MPI2_WHOINIT_PCI_PEER (0x03)
-#define MPI2_WHOINIT_HOST_DRIVER (0x04)
-#define MPI2_WHOINIT_MANUFACTURER (0x05)
-
-/* MsgFlags */
-#define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE (0x01)
-
-/* MsgVersion */
-#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00)
-#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8)
-#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF)
-#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0)
-
-/* HeaderVersion */
-#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00)
-#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8)
-#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF)
-#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0)
-
-/* minimum depth for a Reply Descriptor Post Queue */
-#define MPI2_RDPQ_DEPTH_MIN (16)
-
-/* Reply Descriptor Post Queue Array Entry */
-typedef struct _MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
- U64 RDPQBaseAddress; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U32 Reserved2; /* 0x0C */
-} MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY,
-MPI2_POINTER PTR_MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY,
-Mpi2IOCInitRDPQArrayEntry, MPI2_POINTER pMpi2IOCInitRDPQArrayEntry;
-
-/* IOCInit Reply message */
-typedef struct _MPI2_IOC_INIT_REPLY
-{
- U8 WhoInit; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY,
- Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t;
-
-
-/****************************************************************************
-* IOCFacts message
-****************************************************************************/
-
-/* IOCFacts Request message */
-typedef struct _MPI2_IOC_FACTS_REQUEST
-{
- U16 Reserved1; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
-} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST,
- Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t;
-
-
-/* IOCFacts Reply message */
-typedef struct _MPI2_IOC_FACTS_REPLY
-{
- U16 MsgVersion; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 HeaderVersion; /* 0x04 */
- U8 IOCNumber; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U16 IOCExceptions; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U8 MaxChainDepth; /* 0x14 */
- U8 WhoInit; /* 0x15 */
- U8 NumberOfPorts; /* 0x16 */
- U8 MaxMSIxVectors; /* 0x17 */
- U16 RequestCredit; /* 0x18 */
- U16 ProductID; /* 0x1A */
- U32 IOCCapabilities; /* 0x1C */
- MPI2_VERSION_UNION FWVersion; /* 0x20 */
- U16 IOCRequestFrameSize; /* 0x24 */
- U16 Reserved3; /* 0x26 */
- U16 MaxInitiators; /* 0x28 */
- U16 MaxTargets; /* 0x2A */
- U16 MaxSasExpanders; /* 0x2C */
- U16 MaxEnclosures; /* 0x2E */
- U16 ProtocolFlags; /* 0x30 */
- U16 HighPriorityCredit; /* 0x32 */
- U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */
- U8 ReplyFrameSize; /* 0x36 */
- U8 MaxVolumes; /* 0x37 */
- U16 MaxDevHandle; /* 0x38 */
- U16 MaxPersistentEntries; /* 0x3A */
- U16 MinDevHandle; /* 0x3C */
- U16 Reserved4; /* 0x3E */
-} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY,
- Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t;
-
-/* MsgVersion */
-#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
-#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8)
-#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
-#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0)
-
-/* HeaderVersion */
-#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00)
-#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8)
-#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF)
-#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
-
-/* IOCExceptions */
-#define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200)
-#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100)
-
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060)
-
-#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010)
-#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008)
-#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
-#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
-#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
-
-/* defines for WhoInit field are after the IOCInit Request */
-
-/* ProductID field uses MPI2_FW_HEADER_PID_ */
-
-/* IOCCapabilities */
-#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000)
-#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000)
-#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000)
-#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000)
-#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000)
-#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000)
-#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800)
-#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
-#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080)
-#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040)
-#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
-#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
-#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
-#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
-
-/* ProtocolFlags */
-#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
-#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
-
-
-/****************************************************************************
-* PortFacts message
-****************************************************************************/
-
-/* PortFacts Request message */
-typedef struct _MPI2_PORT_FACTS_REQUEST
-{
- U16 Reserved1; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 PortNumber; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
-} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST,
- Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t;
-
-/* PortFacts Reply message */
-typedef struct _MPI2_PORT_FACTS_REPLY
-{
- U16 Reserved1; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 PortNumber; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U16 Reserved4; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U8 Reserved5; /* 0x14 */
- U8 PortType; /* 0x15 */
- U16 Reserved6; /* 0x16 */
- U16 MaxPostedCmdBuffers; /* 0x18 */
- U16 Reserved7; /* 0x1A */
-} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY,
- Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t;
-
-/* PortType values */
-#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00)
-#define MPI2_PORTFACTS_PORTTYPE_FC (0x10)
-#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20)
-#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30)
-#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31)
-
-
-/****************************************************************************
-* PortEnable message
-****************************************************************************/
-
-/* PortEnable Request message */
-typedef struct _MPI2_PORT_ENABLE_REQUEST
-{
- U16 Reserved1; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U8 Reserved2; /* 0x04 */
- U8 PortFlags; /* 0x05 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
-} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST,
- Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t;
-
-
-/* PortEnable Reply message */
-typedef struct _MPI2_PORT_ENABLE_REPLY
-{
- U16 Reserved1; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U8 Reserved2; /* 0x04 */
- U8 PortFlags; /* 0x05 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY,
- Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t;
-
-
-/****************************************************************************
-* EventNotification message
-****************************************************************************/
-
-/* EventNotification Request message */
-#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4)
-
-typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
-{
- U16 Reserved1; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U32 Reserved5; /* 0x0C */
- U32 Reserved6; /* 0x10 */
- U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
- U16 SASBroadcastPrimitiveMasks; /* 0x24 */
- U16 SASNotifyPrimitiveMasks; /* 0x26 */
- U32 Reserved8; /* 0x28 */
-} MPI2_EVENT_NOTIFICATION_REQUEST,
- MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
- Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t;
-
-
-/* EventNotification Reply message */
-typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
-{
- U16 EventDataLength; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved1; /* 0x04 */
- U8 AckRequired; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U16 Reserved3; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U16 Event; /* 0x14 */
- U16 Reserved4; /* 0x16 */
- U32 EventContext; /* 0x18 */
- U32 EventData[1]; /* 0x1C */
-} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY,
- Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t;
-
-/* AckRequired */
-#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00)
-#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01)
-
-/* Event */
-#define MPI2_EVENT_LOG_DATA (0x0001)
-#define MPI2_EVENT_STATE_CHANGE (0x0002)
-#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005)
-#define MPI2_EVENT_EVENT_CHANGE (0x000A)
-#define MPI2_EVENT_TASK_SET_FULL (0x000E) /* obsolete */
-#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F)
-#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014)
-#define MPI2_EVENT_SAS_DISCOVERY (0x0016)
-#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017)
-#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018)
-#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019)
-#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C)
-#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D)
-#define MPI2_EVENT_IR_VOLUME (0x001E)
-#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F)
-#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020)
-#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021)
-#define MPI2_EVENT_SAS_PHY_COUNTER (0x0022)
-#define MPI2_EVENT_GPIO_INTERRUPT (0x0023)
-#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024)
-#define MPI2_EVENT_SAS_QUIESCE (0x0025)
-#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026)
-#define MPI2_EVENT_TEMP_THRESHOLD (0x0027)
-#define MPI2_EVENT_HOST_MESSAGE (0x0028)
-#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E)
-#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F)
-
-/* Log Entry Added Event data */
-
-/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
-#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C)
-
-typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED
-{
- U64 TimeStamp; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U16 LogSequence; /* 0x0C */
- U16 LogEntryQualifier; /* 0x0E */
- U8 VP_ID; /* 0x10 */
- U8 VF_ID; /* 0x11 */
- U16 Reserved2; /* 0x12 */
- U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */
-} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
- Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t;
-
-/* GPIO Interrupt Event data */
-
-typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT {
- U8 GPIONum; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
-} MPI2_EVENT_DATA_GPIO_INTERRUPT,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
- Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t;
-
-/* Temperature Threshold Event data */
-
-typedef struct _MPI2_EVENT_DATA_TEMPERATURE {
- U16 Status; /* 0x00 */
- U8 SensorNum; /* 0x02 */
- U8 Reserved1; /* 0x03 */
- U16 CurrentTemperature; /* 0x04 */
- U16 Reserved2; /* 0x06 */
- U32 Reserved3; /* 0x08 */
- U32 Reserved4; /* 0x0C */
-} MPI2_EVENT_DATA_TEMPERATURE,
-MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE,
-Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t;
-
-/* Temperature Threshold Event data Status bits */
-#define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008)
-#define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004)
-#define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002)
-#define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001)
-
-
-/* Host Message Event data */
-
-typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE {
- U8 SourceVF_ID; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 Reserved3; /* 0x04 */
- U32 HostData[1]; /* 0x08 */
-} MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE,
-Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t;
-
-
-/* Hard Reset Received Event data */
-
-typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
-{
- U8 Reserved1; /* 0x00 */
- U8 Port; /* 0x01 */
- U16 Reserved2; /* 0x02 */
-} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
- Mpi2EventDataHardResetReceived_t,
- MPI2_POINTER pMpi2EventDataHardResetReceived_t;
-
-/* Task Set Full Event data */
-/* this event is obsolete */
-
-typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
-{
- U16 DevHandle; /* 0x00 */
- U16 CurrentDepth; /* 0x02 */
-} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
- Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t;
-
-
-/* SAS Device Status Change Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
-{
- U16 TaskTag; /* 0x00 */
- U8 ReasonCode; /* 0x02 */
- U8 PhysicalPort; /* 0x03 */
- U8 ASC; /* 0x04 */
- U8 ASCQ; /* 0x05 */
- U16 DevHandle; /* 0x06 */
- U32 Reserved2; /* 0x08 */
- U64 SASAddress; /* 0x0C */
- U8 LUN[8]; /* 0x14 */
-} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
- Mpi2EventDataSasDeviceStatusChange_t,
- MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t;
-
-/* SAS Device Status Change Event data ReasonCode values */
-#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12)
-
-
-/* Integrated RAID Operation Status Event data */
-
-typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS
-{
- U16 VolDevHandle; /* 0x00 */
- U16 Reserved1; /* 0x02 */
- U8 RAIDOperation; /* 0x04 */
- U8 PercentComplete; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- U32 ElapsedSeconds; /* 0x08 */
-} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
- Mpi2EventDataIrOperationStatus_t,
- MPI2_POINTER pMpi2EventDataIrOperationStatus_t;
-
-/* Integrated RAID Operation Status Event data RAIDOperation values */
-#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00)
-#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01)
-#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02)
-#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03)
-#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04)
-
-
-/* Integrated RAID Volume Event data */
-
-typedef struct _MPI2_EVENT_DATA_IR_VOLUME
-{
- U16 VolDevHandle; /* 0x00 */
- U8 ReasonCode; /* 0x02 */
- U8 Reserved1; /* 0x03 */
- U32 NewValue; /* 0x04 */
- U32 PreviousValue; /* 0x08 */
-} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME,
- Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t;
-
-/* Integrated RAID Volume Event data ReasonCode values */
-#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01)
-#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02)
-#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03)
-
-
-/* Integrated RAID Physical Disk Event data */
-
-typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK
-{
- U16 Reserved1; /* 0x00 */
- U8 ReasonCode; /* 0x02 */
- U8 PhysDiskNum; /* 0x03 */
- U16 PhysDiskDevHandle; /* 0x04 */
- U16 Reserved2; /* 0x06 */
- U16 Slot; /* 0x08 */
- U16 EnclosureHandle; /* 0x0A */
- U32 NewValue; /* 0x0C */
- U32 PreviousValue; /* 0x10 */
-} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
- Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t;
-
-/* Integrated RAID Physical Disk Event data ReasonCode values */
-#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01)
-#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02)
-#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03)
-
-
-/* Integrated RAID Configuration Change List Event data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumElements at runtime.
- */
-#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
-#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1)
-#endif
-
-typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT
-{
- U16 ElementFlags; /* 0x00 */
- U16 VolDevHandle; /* 0x02 */
- U8 ReasonCode; /* 0x04 */
- U8 PhysDiskNum; /* 0x05 */
- U16 PhysDiskDevHandle; /* 0x06 */
-} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
- Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t;
-
-/* IR Configuration Change List Event data ElementFlags values */
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F)
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000)
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002)
-
-/* IR Configuration Change List Event data ReasonCode values */
-#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01)
-#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02)
-#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03)
-#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04)
-#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05)
-#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06)
-#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07)
-#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08)
-#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09)
-
-typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST
-{
- U8 NumElements; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 Reserved2; /* 0x02 */
- U8 ConfigNum; /* 0x03 */
- U32 Flags; /* 0x04 */
- MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */
-} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
- Mpi2EventDataIrConfigChangeList_t,
- MPI2_POINTER pMpi2EventDataIrConfigChangeList_t;
-
-/* IR Configuration Change List Event data Flags values */
-#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001)
-
-
-/* SAS Discovery Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY
-{
- U8 Flags; /* 0x00 */
- U8 ReasonCode; /* 0x01 */
- U8 PhysicalPort; /* 0x02 */
- U8 Reserved1; /* 0x03 */
- U32 DiscoveryStatus; /* 0x04 */
-} MPI2_EVENT_DATA_SAS_DISCOVERY,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
- Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t;
-
-/* SAS Discovery Event data Flags values */
-#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02)
-#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01)
-
-/* SAS Discovery Event data ReasonCode values */
-#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01)
-#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02)
-
-/* SAS Discovery Event data DiscoveryStatus values */
-#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
-#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000)
-#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000)
-#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
-#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000)
-#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
-#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
-#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000)
-#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
-#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800)
-#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400)
-#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200)
-#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100)
-#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080)
-#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040)
-#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020)
-#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010)
-#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004)
-#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002)
-#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001)
-
-
-/* SAS Broadcast Primitive Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
-{
- U8 PhyNum; /* 0x00 */
- U8 Port; /* 0x01 */
- U8 PortWidth; /* 0x02 */
- U8 Primitive; /* 0x03 */
-} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
- Mpi2EventDataSasBroadcastPrimitive_t,
- MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t;
-
-/* defines for the Primitive field */
-#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01)
-#define MPI2_EVENT_PRIMITIVE_SES (0x02)
-#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03)
-#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04)
-#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05)
-#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06)
-#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07)
-#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08)
-
-/* SAS Notify Primitive Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE {
- U8 PhyNum; /* 0x00 */
- U8 Port; /* 0x01 */
- U8 Reserved1; /* 0x02 */
- U8 Primitive; /* 0x03 */
-} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
-MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
-Mpi2EventDataSasNotifyPrimitive_t,
-MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t;
-
-/* defines for the Primitive field */
-#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01)
-#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02)
-#define MPI2_EVENT_NOTIFY_RESERVED1 (0x03)
-#define MPI2_EVENT_NOTIFY_RESERVED2 (0x04)
-
-
-/* SAS Initiator Device Status Change Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
-{
- U8 ReasonCode; /* 0x00 */
- U8 PhysicalPort; /* 0x01 */
- U16 DevHandle; /* 0x02 */
- U64 SASAddress; /* 0x04 */
-} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
- Mpi2EventDataSasInitDevStatusChange_t,
- MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t;
-
-/* SAS Initiator Device Status Change event ReasonCode values */
-#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01)
-#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02)
-
-
-/* SAS Initiator Device Table Overflow Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
-{
- U16 MaxInit; /* 0x00 */
- U16 CurrentInit; /* 0x02 */
- U64 SASAddress; /* 0x04 */
-} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
- Mpi2EventDataSasInitTableOverflow_t,
- MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t;
-
-
-/* SAS Topology Change List Event data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumEntries at runtime.
- */
-#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
-#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1)
-#endif
-
-typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY
-{
- U16 AttachedDevHandle; /* 0x00 */
- U8 LinkRate; /* 0x02 */
- U8 PhyStatus; /* 0x03 */
-} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
- Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t;
-
-typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
-{
- U16 EnclosureHandle; /* 0x00 */
- U16 ExpanderDevHandle; /* 0x02 */
- U8 NumPhys; /* 0x04 */
- U8 Reserved1; /* 0x05 */
- U16 Reserved2; /* 0x06 */
- U8 NumEntries; /* 0x08 */
- U8 StartPhyNum; /* 0x09 */
- U8 ExpStatus; /* 0x0A */
- U8 PhysicalPort; /* 0x0B */
- MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/
-} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
- Mpi2EventDataSasTopologyChangeList_t,
- MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t;
-
-/* values for the ExpStatus field */
-#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00)
-#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01)
-#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02)
-#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03)
-#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04)
-
-/* defines for the LinkRate field */
-#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0)
-#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4)
-#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F)
-#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0)
-
-#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00)
-#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01)
-#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02)
-#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03)
-#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04)
-#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05)
-#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06)
-#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08)
-#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
-#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
-
-/* values for the PhyStatus field */
-#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80)
-#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10)
-/* values for the PhyStatus ReasonCode sub-field */
-#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F)
-#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01)
-#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02)
-#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03)
-#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04)
-#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05)
-
-
-/* SAS Enclosure Device Status Change Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
-{
- U16 EnclosureHandle; /* 0x00 */
- U8 ReasonCode; /* 0x02 */
- U8 PhysicalPort; /* 0x03 */
- U64 EnclosureLogicalID; /* 0x04 */
- U16 NumSlots; /* 0x0C */
- U16 StartSlot; /* 0x0E */
- U32 PhyBits; /* 0x10 */
-} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
- Mpi2EventDataSasEnclDevStatusChange_t,
- MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t;
-
-/* SAS Enclosure Device Status Change event ReasonCode values */
-#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01)
-#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02)
-
-
-/* SAS PHY Counter Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER {
- U64 TimeStamp; /* 0x00 */
- U32 Reserved1; /* 0x08 */
- U8 PhyEventCode; /* 0x0C */
- U8 PhyNum; /* 0x0D */
- U16 Reserved2; /* 0x0E */
- U32 PhyEventInfo; /* 0x10 */
- U8 CounterType; /* 0x14 */
- U8 ThresholdWindow; /* 0x15 */
- U8 TimeUnits; /* 0x16 */
- U8 Reserved3; /* 0x17 */
- U32 EventThreshold; /* 0x18 */
- U16 ThresholdFlags; /* 0x1C */
- U16 Reserved4; /* 0x1E */
-} MPI2_EVENT_DATA_SAS_PHY_COUNTER,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER,
- Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t;
-
-/* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the
- * PhyEventCode field
- * use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the
- * CounterType field
- * use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the
- * TimeUnits field
- * use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the
- * ThresholdFlags field
- * */
-
-
-/* SAS Quiesce Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE {
- U8 ReasonCode; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 Reserved3; /* 0x04 */
-} MPI2_EVENT_DATA_SAS_QUIESCE,
- MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE,
- Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t;
-
-/* SAS Quiesce Event data ReasonCode values */
-#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01)
-#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02)
-
-
-/* Host Based Discovery Phy Event data */
-
-typedef struct _MPI2_EVENT_HBD_PHY_SAS {
- U8 Flags; /* 0x00 */
- U8 NegotiatedLinkRate; /* 0x01 */
- U8 PhyNum; /* 0x02 */
- U8 PhysicalPort; /* 0x03 */
- U32 Reserved1; /* 0x04 */
- U8 InitialFrame[28]; /* 0x08 */
-} MPI2_EVENT_HBD_PHY_SAS, MPI2_POINTER PTR_MPI2_EVENT_HBD_PHY_SAS,
- Mpi2EventHbdPhySas_t, MPI2_POINTER pMpi2EventHbdPhySas_t;
-
-/* values for the Flags field */
-#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02)
-#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01)
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h for
- * the NegotiatedLinkRate field */
-
-typedef union _MPI2_EVENT_HBD_DESCRIPTOR {
- MPI2_EVENT_HBD_PHY_SAS Sas;
-} MPI2_EVENT_HBD_DESCRIPTOR, MPI2_POINTER PTR_MPI2_EVENT_HBD_DESCRIPTOR,
- Mpi2EventHbdDescriptor_t, MPI2_POINTER pMpi2EventHbdDescriptor_t;
-
-typedef struct _MPI2_EVENT_DATA_HBD_PHY {
- U8 DescriptorType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 Reserved3; /* 0x04 */
- MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /* 0x08 */
-} MPI2_EVENT_DATA_HBD_PHY, MPI2_POINTER PTR_MPI2_EVENT_DATA_HBD_PHY,
- Mpi2EventDataHbdPhy_t, MPI2_POINTER pMpi2EventDataMpi2EventDataHbdPhy_t;
-
-/* values for the DescriptorType field */
-#define MPI2_EVENT_HBD_DT_SAS (0x01)
-
-
-
-/****************************************************************************
-* EventAck message
-****************************************************************************/
-
-/* EventAck Request message */
-typedef struct _MPI2_EVENT_ACK_REQUEST
-{
- U16 Reserved1; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Event; /* 0x0C */
- U16 Reserved5; /* 0x0E */
- U32 EventContext; /* 0x10 */
-} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST,
- Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t;
-
-
-/* EventAck Reply message */
-typedef struct _MPI2_EVENT_ACK_REPLY
-{
- U16 Reserved1; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY,
- Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t;
-
-
-/****************************************************************************
-* SendHostMessage message
-****************************************************************************/
-
-/* SendHostMessage Request message */
-typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST {
- U16 HostDataLength; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved1; /* 0x04 */
- U8 Reserved2; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U8 Reserved4; /* 0x0C */
- U8 DestVF_ID; /* 0x0D */
- U16 Reserved5; /* 0x0E */
- U32 Reserved6; /* 0x10 */
- U32 Reserved7; /* 0x14 */
- U32 Reserved8; /* 0x18 */
- U32 Reserved9; /* 0x1C */
- U32 Reserved10; /* 0x20 */
- U32 HostData[1]; /* 0x24 */
-} MPI2_SEND_HOST_MESSAGE_REQUEST,
-MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST,
-Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t;
-
-
-/* SendHostMessage Reply message */
-typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY {
- U16 HostDataLength; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved1; /* 0x04 */
- U8 Reserved2; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U16 Reserved4; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY,
-Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t;
-
-
-/****************************************************************************
-* FWDownload message
-****************************************************************************/
-
-/* FWDownload Request message */
-typedef struct _MPI2_FW_DOWNLOAD_REQUEST
-{
- U8 ImageType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U32 TotalImageSize; /* 0x0C */
- U32 Reserved5; /* 0x10 */
- MPI2_MPI_SGE_UNION SGL; /* 0x14 */
-} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST,
- Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest;
-
-#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01)
-
-#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01)
-#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02)
-#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06)
-#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07)
-#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08)
-#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
-#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
-#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
-#define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY (0x0C)
-#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
-
-/* FWDownload TransactionContext Element */
-typedef struct _MPI2_FW_DOWNLOAD_TCSGE
-{
- U8 Reserved1; /* 0x00 */
- U8 ContextSize; /* 0x01 */
- U8 DetailsLength; /* 0x02 */
- U8 Flags; /* 0x03 */
- U32 Reserved2; /* 0x04 */
- U32 ImageOffset; /* 0x08 */
- U32 ImageSize; /* 0x0C */
-} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE,
- Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t;
-
-/* FWDownload Reply message */
-typedef struct _MPI2_FW_DOWNLOAD_REPLY
-{
- U8 ImageType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY,
- Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t;
-
-
-/****************************************************************************
-* FWUpload message
-****************************************************************************/
-
-/* FWUpload Request message */
-typedef struct _MPI2_FW_UPLOAD_REQUEST
-{
- U8 ImageType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U32 Reserved5; /* 0x0C */
- U32 Reserved6; /* 0x10 */
- MPI2_MPI_SGE_UNION SGL; /* 0x14 */
-} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST,
- Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t;
-
-#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00)
-#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01)
-#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02)
-#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
-#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06)
-#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07)
-#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08)
-#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09)
-#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
-#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
-
-typedef struct _MPI2_FW_UPLOAD_TCSGE
-{
- U8 Reserved1; /* 0x00 */
- U8 ContextSize; /* 0x01 */
- U8 DetailsLength; /* 0x02 */
- U8 Flags; /* 0x03 */
- U32 Reserved2; /* 0x04 */
- U32 ImageOffset; /* 0x08 */
- U32 ImageSize; /* 0x0C */
-} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE,
- Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t;
-
-/* FWUpload Reply message */
-typedef struct _MPI2_FW_UPLOAD_REPLY
-{
- U8 ImageType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 ActualImageSize; /* 0x14 */
-} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY,
- Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t;
-
-
-/* FW Image Header */
-typedef struct _MPI2_FW_IMAGE_HEADER
-{
- U32 Signature; /* 0x00 */
- U32 Signature0; /* 0x04 */
- U32 Signature1; /* 0x08 */
- U32 Signature2; /* 0x0C */
- MPI2_VERSION_UNION MPIVersion; /* 0x10 */
- MPI2_VERSION_UNION FWVersion; /* 0x14 */
- MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */
- MPI2_VERSION_UNION PackageVersion; /* 0x1C */
- U16 VendorID; /* 0x20 */
- U16 ProductID; /* 0x22 */
- U16 ProtocolFlags; /* 0x24 */
- U16 Reserved26; /* 0x26 */
- U32 IOCCapabilities; /* 0x28 */
- U32 ImageSize; /* 0x2C */
- U32 NextImageHeaderOffset; /* 0x30 */
- U32 Checksum; /* 0x34 */
- U32 Reserved38; /* 0x38 */
- U32 Reserved3C; /* 0x3C */
- U32 Reserved40; /* 0x40 */
- U32 Reserved44; /* 0x44 */
- U32 Reserved48; /* 0x48 */
- U32 Reserved4C; /* 0x4C */
- U32 Reserved50; /* 0x50 */
- U32 Reserved54; /* 0x54 */
- U32 Reserved58; /* 0x58 */
- U32 Reserved5C; /* 0x5C */
- U32 Reserved60; /* 0x60 */
- U32 FirmwareVersionNameWhat; /* 0x64 */
- U8 FirmwareVersionName[32]; /* 0x68 */
- U32 VendorNameWhat; /* 0x88 */
- U8 VendorName[32]; /* 0x8C */
- U32 PackageNameWhat; /* 0x88 */
- U8 PackageName[32]; /* 0x8C */
- U32 ReservedD0; /* 0xD0 */
- U32 ReservedD4; /* 0xD4 */
- U32 ReservedD8; /* 0xD8 */
- U32 ReservedDC; /* 0xDC */
- U32 ReservedE0; /* 0xE0 */
- U32 ReservedE4; /* 0xE4 */
- U32 ReservedE8; /* 0xE8 */
- U32 ReservedEC; /* 0xEC */
- U32 ReservedF0; /* 0xF0 */
- U32 ReservedF4; /* 0xF4 */
- U32 ReservedF8; /* 0xF8 */
- U32 ReservedFC; /* 0xFC */
-} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER,
- Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t;
-
-/* Signature field */
-#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00)
-#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000)
-#define MPI2_FW_HEADER_SIGNATURE (0xEA000000)
-
-/* Signature0 field */
-#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04)
-#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A)
-
-/* Signature1 field */
-#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
-#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5)
-
-/* Signature2 field */
-#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C)
-#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA)
-
-
-/* defines for using the ProductID field */
-#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000)
-#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000)
-
-#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00)
-#define MPI2_FW_HEADER_PID_PROD_A (0x0000)
-#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200)
-#define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700)
-
-
-#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF)
-/* SAS */
-#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013)
-#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014)
-
-/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
-
-/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
-
-
-#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C)
-#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30)
-#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64)
-
-#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840)
-
-#define MPI2_FW_HEADER_SIZE (0x100)
-
-
-/* Extended Image Header */
-typedef struct _MPI2_EXT_IMAGE_HEADER
-
-{
- U8 ImageType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 Checksum; /* 0x04 */
- U32 ImageSize; /* 0x08 */
- U32 NextImageHeaderOffset; /* 0x0C */
- U32 PackageVersion; /* 0x10 */
- U32 Reserved3; /* 0x14 */
- U32 Reserved4; /* 0x18 */
- U32 Reserved5; /* 0x1C */
- U8 IdentifyString[32]; /* 0x20 */
-} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER,
- Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t;
-
-/* useful offsets */
-#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00)
-#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08)
-#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C)
-
-#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40)
-
-/* defines for the ImageType field */
-#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00)
-#define MPI2_EXT_IMAGE_TYPE_FW (0x01)
-#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03)
-#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04)
-#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05)
-#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06)
-#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07)
-#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08)
-#define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09)
-#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80)
-#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF)
-#define MPI2_EXT_IMAGE_TYPE_MAX \
- (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC) /* deprecated */
-
-
-
-/* FLASH Layout Extended Image Data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check RegionsPerLayout at runtime.
- */
-#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
-#define MPI2_FLASH_NUMBER_OF_REGIONS (1)
-#endif
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumberOfLayouts at runtime.
- */
-#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
-#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1)
-#endif
-
-typedef struct _MPI2_FLASH_REGION
-{
- U8 RegionType; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 RegionOffset; /* 0x04 */
- U32 RegionSize; /* 0x08 */
- U32 Reserved3; /* 0x0C */
-} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION,
- Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t;
-
-typedef struct _MPI2_FLASH_LAYOUT
-{
- U32 FlashSize; /* 0x00 */
- U32 Reserved1; /* 0x04 */
- U32 Reserved2; /* 0x08 */
- U32 Reserved3; /* 0x0C */
- MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */
-} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT,
- Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t;
-
-typedef struct _MPI2_FLASH_LAYOUT_DATA
-{
- U8 ImageRevision; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 SizeOfRegion; /* 0x02 */
- U8 Reserved2; /* 0x03 */
- U16 NumberOfLayouts; /* 0x04 */
- U16 RegionsPerLayout; /* 0x06 */
- U16 MinimumSectorAlignment; /* 0x08 */
- U16 Reserved3; /* 0x0A */
- U32 Reserved4; /* 0x0C */
- MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */
-} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA,
- Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t;
-
-/* defines for the RegionType field */
-#define MPI2_FLASH_REGION_UNUSED (0x00)
-#define MPI2_FLASH_REGION_FIRMWARE (0x01)
-#define MPI2_FLASH_REGION_BIOS (0x02)
-#define MPI2_FLASH_REGION_NVDATA (0x03)
-#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05)
-#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06)
-#define MPI2_FLASH_REGION_CONFIG_1 (0x07)
-#define MPI2_FLASH_REGION_CONFIG_2 (0x08)
-#define MPI2_FLASH_REGION_MEGARAID (0x09)
-#define MPI2_FLASH_REGION_INIT (0x0A)
-
-/* ImageRevision */
-#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
-
-
-
-/* Supported Devices Extended Image Data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumberOfDevices at runtime.
- */
-#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
-#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1)
-#endif
-
-typedef struct _MPI2_SUPPORTED_DEVICE
-{
- U16 DeviceID; /* 0x00 */
- U16 VendorID; /* 0x02 */
- U16 DeviceIDMask; /* 0x04 */
- U16 Reserved1; /* 0x06 */
- U8 LowPCIRev; /* 0x08 */
- U8 HighPCIRev; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U32 Reserved3; /* 0x0C */
-} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE,
- Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t;
-
-typedef struct _MPI2_SUPPORTED_DEVICES_DATA
-{
- U8 ImageRevision; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 NumberOfDevices; /* 0x02 */
- U8 Reserved2; /* 0x03 */
- U32 Reserved3; /* 0x04 */
- MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */
-} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA,
- Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t;
-
-/* ImageRevision */
-#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00)
-
-
-/* Init Extended Image Data */
-
-typedef struct _MPI2_INIT_IMAGE_FOOTER
-
-{
- U32 BootFlags; /* 0x00 */
- U32 ImageSize; /* 0x04 */
- U32 Signature0; /* 0x08 */
- U32 Signature1; /* 0x0C */
- U32 Signature2; /* 0x10 */
- U32 ResetVector; /* 0x14 */
-} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER,
- Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t;
-
-/* defines for the BootFlags field */
-#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00)
-
-/* defines for the ImageSize field */
-#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04)
-
-/* defines for the Signature0 field */
-#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08)
-#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA)
-
-/* defines for the Signature1 field */
-#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C)
-#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5)
-
-/* defines for the Signature2 field */
-#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10)
-#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A)
-
-/* Signature fields as individual bytes */
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A)
-
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5)
-
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A)
-
-/* defines for the ResetVector field */
-#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14)
-
-
-/* Encrypted Hash Extended Image Data */
-
-typedef struct _MPI25_ENCRYPTED_HASH_ENTRY {
- U8 HashImageType; /* 0x00 */
- U8 HashAlgorithm; /* 0x01 */
- U8 EncryptionAlgorithm; /* 0x02 */
- U8 Reserved1; /* 0x03 */
- U32 Reserved2; /* 0x04 */
- U32 EncryptedHash[1]; /* 0x08 */
-} MPI25_ENCRYPTED_HASH_ENTRY, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_ENTRY,
-Mpi25EncryptedHashEntry_t, MPI2_POINTER pMpi25EncryptedHashEntry_t;
-
-/* values for HashImageType */
-#define MPI25_HASH_IMAGE_TYPE_UNUSED (0x00)
-#define MPI25_HASH_IMAGE_TYPE_FIRMWARE (0x01)
-#define MPI25_HASH_IMAGE_TYPE_BIOS (0x02)
-
-/* values for HashAlgorithm */
-#define MPI25_HASH_ALGORITHM_UNUSED (0x00)
-#define MPI25_HASH_ALGORITHM_SHA256 (0x01)
-
-/* values for EncryptionAlgorithm */
-#define MPI25_ENCRYPTION_ALG_UNUSED (0x00)
-#define MPI25_ENCRYPTION_ALG_RSA256 (0x01)
-
-typedef struct _MPI25_ENCRYPTED_HASH_DATA {
- U8 ImageVersion; /* 0x00 */
- U8 NumHash; /* 0x01 */
- U16 Reserved1; /* 0x02 */
- U32 Reserved2; /* 0x04 */
- MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[1]; /* 0x08 */
-} MPI25_ENCRYPTED_HASH_DATA, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_DATA,
-Mpi25EncryptedHashData_t, MPI2_POINTER pMpi25EncryptedHashData_t;
-
-/****************************************************************************
-* PowerManagementControl message
-****************************************************************************/
-
-/* PowerManagementControl Request message */
-typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST {
- U8 Feature; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U8 Parameter1; /* 0x0C */
- U8 Parameter2; /* 0x0D */
- U8 Parameter3; /* 0x0E */
- U8 Parameter4; /* 0x0F */
- U32 Reserved5; /* 0x10 */
- U32 Reserved6; /* 0x14 */
-} MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST,
- Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t;
-
-/* defines for the Feature field */
-#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01)
-#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02)
-#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /* obsolete */
-#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04)
-#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80)
-#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF)
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */
-/* Parameter1 contains a PHY number */
-/* Parameter2 indicates power condition action using these defines */
-#define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01)
-#define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02)
-#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03)
-/* Parameter3 and Parameter4 are reserved */
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION
- * Feature */
-/* Parameter1 contains SAS port width modulation group number */
-/* Parameter2 indicates IOC action using these defines */
-#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01)
-#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02)
-#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03)
-/* Parameter3 indicates desired modulation level using these defines */
-#define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00)
-#define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01)
-#define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02)
-#define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03)
-/* Parameter4 is reserved */
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */
-/* Parameter1 indicates desired PCIe link speed using these defines */
-#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /* obsolete */
-/* Parameter2 indicates desired PCIe link width using these defines */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /* obsolete */
-/* Parameter3 and Parameter4 are reserved */
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */
-/* Parameter1 indicates desired IOC hardware clock speed using these defines */
-#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01)
-#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02)
-#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04)
-#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08)
-/* Parameter2, Parameter3, and Parameter4 are reserved */
-
-
-/* PowerManagementControl Reply message */
-typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY {
- U8 Feature; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY,
- Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t;
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
deleted file mode 100644
index 7efa58ff0d34..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_raid.h
- * Title: MPI Integrated RAID messages and structures
- * Creation Date: April 26, 2007
- *
- * mpi2_raid.h Version: 02.00.10
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 08-31-07 02.00.01 Modifications to RAID Action request and reply,
- * including the Actions and ActionData.
- * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
- * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
- * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
- * can be sized by the build environment.
- * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of
- * VolumeCreationFlags and marked the old one as obsolete.
- * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
- * 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with
- * related structures and defines.
- * Added product-specific range to RAID Action values.
- * 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN.
- * 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR.
- * Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define.
- * 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_RAID_H
-#define MPI2_RAID_H
-
-/*****************************************************************************
-*
-* Integrated RAID Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-* RAID Action messages
-****************************************************************************/
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_CREATE_VOLUME action */
-#define MPI25_RAID_ACTION_ADATA_ALLOW_PI (0x80000000)
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
-#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
-#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001)
-
-/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
-#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001)
-
-/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
-typedef struct _MPI2_RAID_ACTION_RATE_DATA
-{
- U8 RateToChange; /* 0x00 */
- U8 RateOrMode; /* 0x01 */
- U16 DataScrubDuration; /* 0x02 */
-} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
- Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
-
-#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00)
-#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01)
-#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02)
-
-/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
-typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
-{
- U8 RAIDFunction; /* 0x00 */
- U8 Flags; /* 0x01 */
- U16 Reserved1; /* 0x02 */
-} MPI2_RAID_ACTION_START_RAID_FUNCTION,
- MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
- Mpi2RaidActionStartRaidFunction_t,
- MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
-
-/* defines for the RAIDFunction field */
-#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00)
-#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
-#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02)
-
-/* defines for the Flags field */
-#define MPI2_RAID_ACTION_START_NEW (0x00)
-#define MPI2_RAID_ACTION_START_RESUME (0x01)
-
-/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
-typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
-{
- U8 RAIDFunction; /* 0x00 */
- U8 Flags; /* 0x01 */
- U16 Reserved1; /* 0x02 */
-} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
- MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
- Mpi2RaidActionStopRaidFunction_t,
- MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
-
-/* defines for the RAIDFunction field */
-#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00)
-#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01)
-#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02)
-
-/* defines for the Flags field */
-#define MPI2_RAID_ACTION_STOP_ABORT (0x00)
-#define MPI2_RAID_ACTION_STOP_PAUSE (0x01)
-
-/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
-typedef struct _MPI2_RAID_ACTION_HOT_SPARE
-{
- U8 HotSparePool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 DevHandle; /* 0x02 */
-} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
- Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
-
-/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
-typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
-{
- U8 Flags; /* 0x00 */
- U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */
- U16 Reserved1; /* 0x02 */
-} MPI2_RAID_ACTION_FW_UPDATE_MODE,
- MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
- Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
-#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00)
-#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01)
-
-typedef union _MPI2_RAID_ACTION_DATA
-{
- U32 Word;
- MPI2_RAID_ACTION_RATE_DATA Rates;
- MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
- MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
- MPI2_RAID_ACTION_HOT_SPARE HotSpare;
- MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
-} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
- Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
-
-
-/* RAID Action Request Message */
-typedef struct _MPI2_RAID_ACTION_REQUEST
-{
- U8 Action; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 VolDevHandle; /* 0x04 */
- U8 PhysDiskNum; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U32 Reserved3; /* 0x0C */
- MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */
- MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */
-} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
- Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
-
-/* RAID Action request Action values */
-
-#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01)
-#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02)
-#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03)
-#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04)
-#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05)
-#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A)
-#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B)
-#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F)
-#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11)
-#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
-#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17)
-#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18)
-#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19)
-#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C)
-#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D)
-#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E)
-#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20)
-#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21)
-#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22)
-#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23)
-#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24)
-#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80)
-#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF)
-
-/* RAID Volume Creation Structure */
-
-/*
- * The following define can be customized for the targeted product.
- */
-#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
-#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1)
-#endif
-
-typedef struct _MPI2_RAID_VOLUME_PHYSDISK
-{
- U8 RAIDSetNum; /* 0x00 */
- U8 PhysDiskMap; /* 0x01 */
- U16 PhysDiskDevHandle; /* 0x02 */
-} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
- Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
-
-/* defines for the PhysDiskMap field */
-#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01)
-#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02)
-
-typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
-{
- U8 NumPhysDisks; /* 0x00 */
- U8 VolumeType; /* 0x01 */
- U16 Reserved1; /* 0x02 */
- U32 VolumeCreationFlags; /* 0x04 */
- U32 VolumeSettings; /* 0x08 */
- U8 Reserved2; /* 0x0C */
- U8 ResyncRate; /* 0x0D */
- U16 DataScrubDuration; /* 0x0E */
- U64 VolumeMaxLBA; /* 0x10 */
- U32 StripeSize; /* 0x18 */
- U8 Name[16]; /* 0x1C */
- MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
-} MPI2_RAID_VOLUME_CREATION_STRUCT,
- MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
- Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
-
-/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
-
-/* defines for the VolumeCreationFlags field */
-#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000)
-#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004)
-#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002)
-#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001)
-/* The following is an obsolete define.
- * It must be shifted left 24 bits in order to set the proper bit.
- */
-#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
-
-
-/* RAID Online Capacity Expansion Structure */
-
-typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
-{
- U32 Flags; /* 0x00 */
- U16 DevHandle0; /* 0x04 */
- U16 Reserved1; /* 0x06 */
- U16 DevHandle1; /* 0x08 */
- U16 Reserved2; /* 0x0A */
-} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
- MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
- Mpi2RaidOnlineCapacityExpansion_t,
- MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
-
-/* RAID Compatibility Input Structure */
-
-typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT {
- U16 SourceDevHandle; /* 0x00 */
- U16 CandidateDevHandle; /* 0x02 */
- U32 Flags; /* 0x04 */
- U32 Reserved1; /* 0x08 */
- U32 Reserved2; /* 0x0C */
-} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
-MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
-Mpi2RaidCompatibilityInputStruct_t,
-MPI2_POINTER pMpi2RaidCompatibilityInputStruct_t;
-
-/* defines for RAID Compatibility Structure Flags field */
-#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002)
-#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001)
-
-
-/* RAID Volume Indicator Structure */
-
-typedef struct _MPI2_RAID_VOL_INDICATOR
-{
- U64 TotalBlocks; /* 0x00 */
- U64 BlocksRemaining; /* 0x08 */
- U32 Flags; /* 0x10 */
- U32 ElapsedSeconds; /* 0x14 */
-} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
- Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
-
-/* defines for RAID Volume Indicator Flags field */
-#define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID (0x80000000)
-
-#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F)
-#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000)
-#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
-#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
-#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
-#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004)
-
-/* RAID Compatibility Result Structure */
-
-typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT {
- U8 State; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U16 Reserved2; /* 0x02 */
- U32 GenericAttributes; /* 0x04 */
- U32 OEMSpecificAttributes; /* 0x08 */
- U32 Reserved3; /* 0x0C */
- U32 Reserved4; /* 0x10 */
-} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
-MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
-Mpi2RaidCompatibilityResultStruct_t,
-MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t;
-
-/* defines for RAID Compatibility Result Structure State field */
-#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00)
-#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01)
-
-/* defines for RAID Compatibility Result Structure GenericAttributes field */
-#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010)
-
-#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C)
-#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008)
-#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004)
-
-#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003)
-#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002)
-#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001)
-
-/* RAID Action Reply ActionData union */
-typedef union _MPI2_RAID_ACTION_REPLY_DATA
-{
- U32 Word[6];
- MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
- U16 VolDevHandle;
- U8 VolumeState;
- U8 PhysDiskNum;
- MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult;
-} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
- Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
-
-/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
-
-
-/* RAID Action Reply Message */
-typedef struct _MPI2_RAID_ACTION_REPLY
-{
- U8 Action; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 VolDevHandle; /* 0x04 */
- U8 PhysDiskNum; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved2; /* 0x0A */
- U16 Reserved3; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */
-} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
- Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
deleted file mode 100644
index 45b6fa10b803..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_sas.h
- * Title: MPI Serial Attached SCSI structures and definitions
- * Creation Date: February 9, 2007
- *
- * mpi2_sas.h Version: 02.00.05
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit
- * Control Request.
- * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control
- * Request.
- * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
- * to MPI2_SGE_IO_UNION since it supports chained SGLs.
- * 05-12-10 02.00.04 Modified some comments.
- * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_SAS_H
-#define MPI2_SAS_H
-
-/*
- * Values for SASStatus.
- */
-#define MPI2_SASSTATUS_SUCCESS (0x00)
-#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01)
-#define MPI2_SASSTATUS_INVALID_FRAME (0x02)
-#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03)
-#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
-#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
-#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
-#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
-#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
-#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
-#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
-#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
-#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
-#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
-#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
-#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
-#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
-#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11)
-#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
-#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
-#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
-
-
-/*
- * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
- * data and SAS Configuration pages.
- */
-#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000)
-#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
-#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
-#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
-#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
-#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
-#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
-#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
-#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
-#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
-#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
-#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
-
-#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
-#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
-#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
-#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
-#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
-
-
-/*****************************************************************************
-*
-* SAS Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-* SMP Passthrough messages
-****************************************************************************/
-
-/* SMP Passthrough Request Message */
-typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
-{
- U8 PassthroughFlags; /* 0x00 */
- U8 PhysicalPort; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 RequestDataLength; /* 0x04 */
- U8 SGLFlags; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U32 Reserved2; /* 0x0C */
- U64 SASAddress; /* 0x10 */
- U32 Reserved3; /* 0x18 */
- U32 Reserved4; /* 0x1C */
- MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */
-} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
- Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
-
-/* values for PassthroughFlags field */
-#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* SMP Passthrough Reply Message */
-typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
-{
- U8 PassthroughFlags; /* 0x00 */
- U8 PhysicalPort; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 ResponseDataLength; /* 0x04 */
- U8 SGLFlags; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U8 Reserved2; /* 0x0C */
- U8 SASStatus; /* 0x0D */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 Reserved3; /* 0x14 */
- U8 ResponseData[4]; /* 0x18 */
-} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
- Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
-
-/* values for PassthroughFlags field */
-#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
-
-/* values for SASStatus field are at the top of this file */
-
-
-/****************************************************************************
-* SATA Passthrough messages
-****************************************************************************/
-
-/* SATA Passthrough Request Message */
-typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
-{
- U16 DevHandle; /* 0x00 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 PassthroughFlags; /* 0x04 */
- U8 SGLFlags; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U32 Reserved2; /* 0x0C */
- U32 Reserved3; /* 0x10 */
- U32 Reserved4; /* 0x14 */
- U32 DataLength; /* 0x18 */
- U8 CommandFIS[20]; /* 0x1C */
- MPI2_SGE_IO_UNION SGL; /* 0x30 */
-} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
- Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
-
-/* values for PassthroughFlags field */
-#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* SATA Passthrough Reply Message */
-typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
-{
- U16 DevHandle; /* 0x00 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 PassthroughFlags; /* 0x04 */
- U8 SGLFlags; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved1; /* 0x0A */
- U8 Reserved2; /* 0x0C */
- U8 SASStatus; /* 0x0D */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U8 StatusFIS[20]; /* 0x14 */
- U32 StatusControlRegisters; /* 0x28 */
- U32 TransferCount; /* 0x2C */
-} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
- Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
-
-/* values for SASStatus field are at the top of this file */
-
-
-/****************************************************************************
-* SAS IO Unit Control messages
-****************************************************************************/
-
-/* SAS IO Unit Control Request Message */
-typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
-{
- U8 Operation; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 DevHandle; /* 0x04 */
- U8 IOCParameter; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U16 Reserved4; /* 0x0C */
- U8 PhyNum; /* 0x0E */
- U8 PrimFlags; /* 0x0F */
- U32 Primitive; /* 0x10 */
- U8 LookupMethod; /* 0x14 */
- U8 Reserved5; /* 0x15 */
- U16 SlotNumber; /* 0x16 */
- U64 LookupAddress; /* 0x18 */
- U32 IOCParameterValue; /* 0x20 */
- U32 Reserved7; /* 0x24 */
- U32 Reserved8; /* 0x28 */
-} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
- MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
- Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
-
-/* values for the Operation field */
-#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
-#define MPI2_SAS_OP_PHY_LINK_RESET (0x06)
-#define MPI2_SAS_OP_PHY_HARD_RESET (0x07)
-#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
-#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A)
-#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
-#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
-#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D)
-#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E)
-#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F)
-#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14)
-#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15)
-#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
-
-/* values for the PrimFlags field */
-#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08)
-#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02)
-#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01)
-
-/* values for the LookupMethod field */
-#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01)
-#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02)
-#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
-
-
-/* SAS IO Unit Control Reply Message */
-typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
-{
- U8 Operation; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 DevHandle; /* 0x04 */
- U8 IOCParameter; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved3; /* 0x0A */
- U16 Reserved4; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_SAS_IOUNIT_CONTROL_REPLY,
- MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
- Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
-
-
-#endif
-
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
deleted file mode 100644
index 659b8ac83ceb..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_tool.h
- * Title: MPI diagnostic tool structures and definitions
- * Creation Date: March 26, 2007
- *
- * mpi2_tool.h Version: 02.00.12
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release
- * structures and defines.
- * 02-29-08 02.00.02 Modified various names to make them 32-character unique.
- * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool.
- * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request
- * and reply messages.
- * Added MPI2_DIAG_BUF_TYPE_EXTENDED.
- * Incremented MPI2_DIAG_BUF_TYPE_COUNT.
- * 05-12-10 02.00.05 Added Diagnostic Data Upload tool.
- * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer
- * Post Request.
- * 05-25-11 02.00.07 Added Flags field and related defines to
- * MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST.
- * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that
- * it uses MPI Chain SGE as well as MPI Simple SGE.
- * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info.
- * 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_TOOL_H
-#define MPI2_TOOL_H
-
-/*****************************************************************************
-*
-* Toolbox Messages
-*
-*****************************************************************************/
-
-/* defines for the Tools */
-#define MPI2_TOOLBOX_CLEAN_TOOL (0x00)
-#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01)
-#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02)
-#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03)
-#define MPI2_TOOLBOX_BEACON_TOOL (0x05)
-#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06)
-#define MPI2_TOOLBOX_TEXT_DISPLAY_TOOL (0x07)
-
-
-/****************************************************************************
-* Toolbox reply
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_REPLY
-{
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY,
- Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t;
-
-
-/****************************************************************************
-* Toolbox Clean Tool request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST
-{
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U32 Flags; /* 0x0C */
- } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
- Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t;
-
-/* values for the Flags field */
-#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000)
-#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000)
-#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000)
-#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000)
-#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000)
-#define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000)
-#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000)
-#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000)
-#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004)
-#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002)
-#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001)
-
-
-/****************************************************************************
-* Toolbox Memory Move request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- MPI2_SGE_SIMPLE_UNION SGL; /* 0x0C */
-} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
- Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t;
-
-
-/****************************************************************************
-* Toolbox Diagnostic Data Upload request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U8 SGLFlags; /* 0x0C */
- U8 Reserved5; /* 0x0D */
- U16 Reserved6; /* 0x0E */
- U32 Flags; /* 0x10 */
- U32 DataLength; /* 0x14 */
- MPI2_SGE_SIMPLE_UNION SGL; /* 0x18 */
-} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
-MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
-Mpi2ToolboxDiagDataUploadRequest_t,
-MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t;
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER {
- U32 DiagDataLength; /* 00h */
- U8 FormatCode; /* 04h */
- U8 Reserved1; /* 05h */
- U16 Reserved2; /* 06h */
-} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
-Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_t;
-
-
-/****************************************************************************
-* Toolbox ISTWI Read Write Tool
-****************************************************************************/
-
-/* Toolbox ISTWI Read Write Tool request message */
-typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U32 Reserved5; /* 0x0C */
- U32 Reserved6; /* 0x10 */
- U8 DevIndex; /* 0x14 */
- U8 Action; /* 0x15 */
- U8 SGLFlags; /* 0x16 */
- U8 Flags; /* 0x17 */
- U16 TxDataLength; /* 0x18 */
- U16 RxDataLength; /* 0x1A */
- U32 Reserved8; /* 0x1C */
- U32 Reserved9; /* 0x20 */
- U32 Reserved10; /* 0x24 */
- U32 Reserved11; /* 0x28 */
- U32 Reserved12; /* 0x2C */
- MPI2_SGE_SIMPLE_UNION SGL; /* 0x30 */
-} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
- MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
- Mpi2ToolboxIstwiReadWriteRequest_t,
- MPI2_POINTER pMpi2ToolboxIstwiReadWriteRequest_t;
-
-/* values for the Action field */
-#define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01)
-#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02)
-#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03)
-#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10)
-#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11)
-#define MPI2_TOOL_ISTWI_ACTION_RESET (0x12)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-/* values for the Flags field */
-#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE (0x80)
-#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07)
-
-/* Toolbox ISTWI Read Write Tool reply message */
-typedef struct _MPI2_TOOLBOX_ISTWI_REPLY {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U8 DevIndex; /* 0x14 */
- U8 Action; /* 0x15 */
- U8 IstwiStatus; /* 0x16 */
- U8 Reserved6; /* 0x17 */
- U16 TxDataCount; /* 0x18 */
- U16 RxDataCount; /* 0x1A */
-} MPI2_TOOLBOX_ISTWI_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_REPLY,
- Mpi2ToolboxIstwiReply_t, MPI2_POINTER pMpi2ToolboxIstwiReply_t;
-
-
-/****************************************************************************
-* Toolbox Beacon Tool request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_BEACON_REQUEST
-{
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U8 Reserved5; /* 0x0C */
- U8 PhysicalPort; /* 0x0D */
- U8 Reserved6; /* 0x0E */
- U8 Flags; /* 0x0F */
-} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST,
- Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t;
-
-/* values for the Flags field */
-#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00)
-#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01)
-
-
-/****************************************************************************
-* Toolbox Diagnostic CLI Tool
-****************************************************************************/
-
-#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C)
-
-/* MPI v2.0 Toolbox Diagnostic CLI Tool request message */
-typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U8 SGLFlags; /* 0x0C */
- U8 Reserved5; /* 0x0D */
- U16 Reserved6; /* 0x0E */
- U32 DataLength; /* 0x10 */
- U8 DiagnosticCliCommand
- [MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH]; /* 0x14 */
- MPI2_MPI_SGE_IO_UNION SGL; /* 0x70 */
-} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
- MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
- Mpi2ToolboxDiagnosticCliRequest_t,
- MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t;
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* Toolbox Diagnostic CLI Tool reply message */
-typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 ReturnedDataLength; /* 0x14 */
-} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY,
- MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY,
- Mpi2ToolboxDiagnosticCliReply_t,
- MPI2_POINTER pMpi2ToolboxDiagnosticCliReply_t;
-
-
-/****************************************************************************
-* Toolbox Console Text Display Tool
-****************************************************************************/
-
-/* Toolbox Console Text Display Tool request message */
-typedef struct _MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST {
- U8 Tool; /* 0x00 */
- U8 Reserved1; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U8 Console; /* 0x0C */
- U8 Flags; /* 0x0D */
- U16 Reserved6; /* 0x0E */
- U8 TextToDisplay[4]; /* 0x10 */
-} MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST,
-MPI2_POINTER PTR_MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST,
-Mpi2ToolboxTextDisplayRequest_t,
-MPI2_POINTER pMpi2ToolboxTextDisplayRequest_t;
-
-/* defines for the Console field */
-#define MPI2_TOOLBOX_CONSOLE_TYPE_MASK (0xF0)
-#define MPI2_TOOLBOX_CONSOLE_TYPE_DEFAULT (0x00)
-#define MPI2_TOOLBOX_CONSOLE_TYPE_UART (0x10)
-#define MPI2_TOOLBOX_CONSOLE_TYPE_ETHERNET (0x20)
-
-#define MPI2_TOOLBOX_CONSOLE_NUMBER_MASK (0x0F)
-
-/* defines for the Flags field */
-#define MPI2_TOOLBOX_CONSOLE_FLAG_TIMESTAMP (0x01)
-
-
-
-/*****************************************************************************
-*
-* Diagnostic Buffer Messages
-*
-*****************************************************************************/
-
-
-/****************************************************************************
-* Diagnostic Buffer Post request
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST
-{
- U8 ExtendedType; /* 0x00 */
- U8 BufferType; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U64 BufferAddress; /* 0x0C */
- U32 BufferLength; /* 0x14 */
- U32 Reserved5; /* 0x18 */
- U32 Reserved6; /* 0x1C */
- U32 Flags; /* 0x20 */
- U32 ProductSpecific[23]; /* 0x24 */
-} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
- Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t;
-
-/* values for the ExtendedType field */
-#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION (0x02)
-
-/* values for the BufferType field */
-#define MPI2_DIAG_BUF_TYPE_TRACE (0x00)
-#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01)
-#define MPI2_DIAG_BUF_TYPE_EXTENDED (0x02)
-/* count of the number of buffer types */
-#define MPI2_DIAG_BUF_TYPE_COUNT (0x03)
-
-/* values for the Flags field */
-#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL (0x00000002)
-#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE (0x00000001)
-
-
-/****************************************************************************
-* Diagnostic Buffer Post reply
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_BUFFER_POST_REPLY
-{
- U8 ExtendedType; /* 0x00 */
- U8 BufferType; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
- U32 TransferLength; /* 0x14 */
-} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY,
- Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t;
-
-
-/****************************************************************************
-* Diagnostic Release request
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_RELEASE_REQUEST
-{
- U8 Reserved1; /* 0x00 */
- U8 BufferType; /* 0x01 */
- U8 ChainOffset; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
-} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST,
- Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t;
-
-
-/****************************************************************************
-* Diagnostic Buffer Post reply
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_RELEASE_REPLY
-{
- U8 Reserved1; /* 0x00 */
- U8 BufferType; /* 0x01 */
- U8 MsgLength; /* 0x02 */
- U8 Function; /* 0x03 */
- U16 Reserved2; /* 0x04 */
- U8 Reserved3; /* 0x06 */
- U8 MsgFlags; /* 0x07 */
- U8 VP_ID; /* 0x08 */
- U8 VF_ID; /* 0x09 */
- U16 Reserved4; /* 0x0A */
- U16 Reserved5; /* 0x0C */
- U16 IOCStatus; /* 0x0E */
- U32 IOCLogInfo; /* 0x10 */
-} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY,
- Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t;
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_type.h b/drivers/scsi/mpt2sas/mpi/mpi2_type.h
deleted file mode 100644
index 6b0dcdd02f68..000000000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_type.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- * Name: mpi2_type.h
- * Title: MPI basic type definitions
- * Creation Date: August 16, 2006
- *
- * mpi2_type.h Version: 02.00.00
- *
- * Version History
- * ---------------
- *
- * Date Version Description
- * -------- -------- ------------------------------------------------------
- * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
- * --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_TYPE_H
-#define MPI2_TYPE_H
-
-
-/*******************************************************************************
- * Define MPI2_POINTER if it hasn't already been defined. By default
- * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
- * a far pointer by defining MPI2_POINTER as "far *" before this header file is
- * included.
- */
-#ifndef MPI2_POINTER
-#define MPI2_POINTER *
-#endif
-
-/* the basic types may have already been included by mpi_type.h */
-#ifndef MPI_TYPE_H
-/*****************************************************************************
-*
-* Basic Types
-*
-*****************************************************************************/
-
-typedef u8 U8;
-typedef __le16 U16;
-typedef __le32 U32;
-typedef __le64 U64 __attribute__((aligned(4)));
-
-/*****************************************************************************
-*
-* Pointer Types
-*
-*****************************************************************************/
-
-typedef U8 *PU8;
-typedef U16 *PU16;
-typedef U32 *PU32;
-typedef U64 *PU64;
-
-#endif
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
deleted file mode 100644
index c167911221e9..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ /dev/null
@@ -1,4899 +0,0 @@
-/*
- * This is the Fusion MPT base driver providing common API layer interface
- * for access to MPT (Message Passing Technology) firmware.
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/sort.h>
-#include <linux/io.h>
-#include <linux/time.h>
-#include <linux/kthread.h>
-#include <linux/aer.h>
-
-#include "mpt2sas_base.h"
-
-static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
-
-#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
-
-#define MAX_HBA_QUEUE_DEPTH 30000
-#define MAX_CHAIN_DEPTH 100000
-static int max_queue_depth = -1;
-module_param(max_queue_depth, int, 0);
-MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
-
-static int max_sgl_entries = -1;
-module_param(max_sgl_entries, int, 0);
-MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
-
-static int msix_disable = -1;
-module_param(msix_disable, int, 0);
-MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
-
-static int max_msix_vectors = -1;
-module_param(max_msix_vectors, int, 0);
-MODULE_PARM_DESC(max_msix_vectors, " max msix vectors ");
-
-static int mpt2sas_fwfault_debug;
-MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
- "and halt firmware - (default=0)");
-
-static int disable_discovery = -1;
-module_param(disable_discovery, int, 0);
-MODULE_PARM_DESC(disable_discovery, " disable discovery ");
-
-static int
-_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
-
-static int
-_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
-
-/**
- * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
- *
- */
-static int
-_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
-{
- int ret = param_set_int(val, kp);
- struct MPT2SAS_ADAPTER *ioc;
-
- if (ret)
- return ret;
-
- /* global ioc spinlock to protect controller list on list operations */
- printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug);
- spin_lock(&gioc_lock);
- list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
- ioc->fwfault_debug = mpt2sas_fwfault_debug;
- spin_unlock(&gioc_lock);
- return 0;
-}
-
-module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
- param_get_int, &mpt2sas_fwfault_debug, 0644);
-
-/**
- * mpt2sas_remove_dead_ioc_func - kthread context to remove dead ioc
- * @arg: input argument, used to derive ioc
- *
- * Return 0 if controller is removed from pci subsystem.
- * Return -1 for other case.
- */
-static int mpt2sas_remove_dead_ioc_func(void *arg)
-{
- struct MPT2SAS_ADAPTER *ioc = (struct MPT2SAS_ADAPTER *)arg;
- struct pci_dev *pdev;
-
- if ((ioc == NULL))
- return -1;
-
- pdev = ioc->pdev;
- if ((pdev == NULL))
- return -1;
- pci_stop_and_remove_bus_device_locked(pdev);
- return 0;
-}
-
-
-/**
- * _base_fault_reset_work - workq handling ioc fault conditions
- * @work: input argument, used to derive ioc
- * Context: sleep.
- *
- * Return nothing.
- */
-static void
-_base_fault_reset_work(struct work_struct *work)
-{
- struct MPT2SAS_ADAPTER *ioc =
- container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
- unsigned long flags;
- u32 doorbell;
- int rc;
- struct task_struct *p;
-
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery || ioc->pci_error_recovery)
- goto rearm_timer;
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-
- doorbell = mpt2sas_base_get_iocstate(ioc, 0);
- if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) {
- printk(MPT2SAS_INFO_FMT "%s : SAS host is non-operational !!!!\n",
- ioc->name, __func__);
-
- /* It may be possible that EEH recovery can resolve some of
- * pci bus failure issues rather removing the dead ioc function
- * by considering controller is in a non-operational state. So
- * here priority is given to the EEH recovery. If it doesn't
- * not resolve this issue, mpt2sas driver will consider this
- * controller to non-operational state and remove the dead ioc
- * function.
- */
- if (ioc->non_operational_loop++ < 5) {
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock,
- flags);
- goto rearm_timer;
- }
-
- /*
- * Call _scsih_flush_pending_cmds callback so that we flush all
- * pending commands back to OS. This call is required to aovid
- * deadlock at block layer. Dead IOC will fail to do diag reset,
- * and this call is safe since dead ioc will never return any
- * command back from HW.
- */
- ioc->schedule_dead_ioc_flush_running_cmds(ioc);
- /*
- * Set remove_host flag early since kernel thread will
- * take some time to execute.
- */
- ioc->remove_host = 1;
- /*Remove the Dead Host */
- p = kthread_run(mpt2sas_remove_dead_ioc_func, ioc,
- "mpt2sas_dead_ioc_%d", ioc->id);
- if (IS_ERR(p)) {
- printk(MPT2SAS_ERR_FMT
- "%s: Running mpt2sas_dead_ioc thread failed !!!!\n",
- ioc->name, __func__);
- } else {
- printk(MPT2SAS_ERR_FMT
- "%s: Running mpt2sas_dead_ioc thread success !!!!\n",
- ioc->name, __func__);
- }
-
- return; /* don't rearm timer */
- }
-
- ioc->non_operational_loop = 0;
-
- if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
- __func__, (rc == 0) ? "success" : "failed");
- doorbell = mpt2sas_base_get_iocstate(ioc, 0);
- if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
- mpt2sas_base_fault_info(ioc, doorbell &
- MPI2_DOORBELL_DATA_MASK);
- }
-
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- rearm_timer:
- if (ioc->fault_reset_work_q)
- queue_delayed_work(ioc->fault_reset_work_q,
- &ioc->fault_reset_work,
- msecs_to_jiffies(FAULT_POLLING_INTERVAL));
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-}
-
-/**
- * mpt2sas_base_start_watchdog - start the fault_reset_work_q
- * @ioc: per adapter object
- * Context: sleep.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
-{
- unsigned long flags;
-
- if (ioc->fault_reset_work_q)
- return;
-
- /* initialize fault polling */
- INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
- snprintf(ioc->fault_reset_work_q_name,
- sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
- ioc->fault_reset_work_q =
- create_singlethread_workqueue(ioc->fault_reset_work_q_name);
- if (!ioc->fault_reset_work_q) {
- printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
- ioc->name, __func__, __LINE__);
- return;
- }
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->fault_reset_work_q)
- queue_delayed_work(ioc->fault_reset_work_q,
- &ioc->fault_reset_work,
- msecs_to_jiffies(FAULT_POLLING_INTERVAL));
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-}
-
-/**
- * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
- * @ioc: per adapter object
- * Context: sleep.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
-{
- unsigned long flags;
- struct workqueue_struct *wq;
-
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- wq = ioc->fault_reset_work_q;
- ioc->fault_reset_work_q = NULL;
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
- if (wq) {
- if (!cancel_delayed_work_sync(&ioc->fault_reset_work))
- flush_workqueue(wq);
- destroy_workqueue(wq);
- }
-}
-
-/**
- * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
- * @ioc: per adapter object
- * @fault_code: fault code
- *
- * Return nothing.
- */
-void
-mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
-{
- printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
- ioc->name, fault_code);
-}
-
-/**
- * mpt2sas_halt_firmware - halt's mpt controller firmware
- * @ioc: per adapter object
- *
- * For debugging timeout related issues. Writing 0xCOFFEE00
- * to the doorbell register will halt controller firmware. With
- * the purpose to stop both driver and firmware, the enduser can
- * obtain a ring buffer from controller UART.
- */
-void
-mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
-{
- u32 doorbell;
-
- if (!ioc->fwfault_debug)
- return;
-
- dump_stack();
-
- doorbell = readl(&ioc->chip->Doorbell);
- if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
- mpt2sas_base_fault_info(ioc , doorbell);
- else {
- writel(0xC0FFEE00, &ioc->chip->Doorbell);
- printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
- "timeout\n", ioc->name);
- }
-
- panic("panic in %s\n", __func__);
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _base_sas_ioc_info - verbose translation of the ioc status
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @request_hdr: request mf
- *
- * Return nothing.
- */
-static void
-_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
- MPI2RequestHeader_t *request_hdr)
-{
- u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- char *desc = NULL;
- u16 frame_sz;
- char *func_str = NULL;
-
- /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
- if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
- request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
- request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
- return;
-
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- return;
-
- switch (ioc_status) {
-
-/****************************************************************************
-* Common IOCStatus values for all replies
-****************************************************************************/
-
- case MPI2_IOCSTATUS_INVALID_FUNCTION:
- desc = "invalid function";
- break;
- case MPI2_IOCSTATUS_BUSY:
- desc = "busy";
- break;
- case MPI2_IOCSTATUS_INVALID_SGL:
- desc = "invalid sgl";
- break;
- case MPI2_IOCSTATUS_INTERNAL_ERROR:
- desc = "internal error";
- break;
- case MPI2_IOCSTATUS_INVALID_VPID:
- desc = "invalid vpid";
- break;
- case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
- desc = "insufficient resources";
- break;
- case MPI2_IOCSTATUS_INVALID_FIELD:
- desc = "invalid field";
- break;
- case MPI2_IOCSTATUS_INVALID_STATE:
- desc = "invalid state";
- break;
- case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
- desc = "op state not supported";
- break;
-
-/****************************************************************************
-* Config IOCStatus values
-****************************************************************************/
-
- case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
- desc = "config invalid action";
- break;
- case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
- desc = "config invalid type";
- break;
- case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
- desc = "config invalid page";
- break;
- case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
- desc = "config invalid data";
- break;
- case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
- desc = "config no defaults";
- break;
- case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
- desc = "config cant commit";
- break;
-
-/****************************************************************************
-* SCSI IO Reply
-****************************************************************************/
-
- case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
- case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
- case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
- case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
- case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
- case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
- case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
- case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
- case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
- case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
- case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
- case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
- break;
-
-/****************************************************************************
-* For use by SCSI Initiator and SCSI Target end-to-end data protection
-****************************************************************************/
-
- case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
- desc = "eedp guard error";
- break;
- case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
- desc = "eedp ref tag error";
- break;
- case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
- desc = "eedp app tag error";
- break;
-
-/****************************************************************************
-* SCSI Target values
-****************************************************************************/
-
- case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
- desc = "target invalid io index";
- break;
- case MPI2_IOCSTATUS_TARGET_ABORTED:
- desc = "target aborted";
- break;
- case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
- desc = "target no conn retryable";
- break;
- case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
- desc = "target no connection";
- break;
- case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
- desc = "target xfer count mismatch";
- break;
- case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
- desc = "target data offset error";
- break;
- case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
- desc = "target too much write data";
- break;
- case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
- desc = "target iu too short";
- break;
- case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
- desc = "target ack nak timeout";
- break;
- case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
- desc = "target nak received";
- break;
-
-/****************************************************************************
-* Serial Attached SCSI values
-****************************************************************************/
-
- case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
- desc = "smp request failed";
- break;
- case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
- desc = "smp data overrun";
- break;
-
-/****************************************************************************
-* Diagnostic Buffer Post / Diagnostic Release values
-****************************************************************************/
-
- case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
- desc = "diagnostic released";
- break;
- default:
- break;
- }
-
- if (!desc)
- return;
-
- switch (request_hdr->Function) {
- case MPI2_FUNCTION_CONFIG:
- frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
- func_str = "config_page";
- break;
- case MPI2_FUNCTION_SCSI_TASK_MGMT:
- frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
- func_str = "task_mgmt";
- break;
- case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
- frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
- func_str = "sas_iounit_ctl";
- break;
- case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
- frame_sz = sizeof(Mpi2SepRequest_t);
- func_str = "enclosure";
- break;
- case MPI2_FUNCTION_IOC_INIT:
- frame_sz = sizeof(Mpi2IOCInitRequest_t);
- func_str = "ioc_init";
- break;
- case MPI2_FUNCTION_PORT_ENABLE:
- frame_sz = sizeof(Mpi2PortEnableRequest_t);
- func_str = "port_enable";
- break;
- case MPI2_FUNCTION_SMP_PASSTHROUGH:
- frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
- func_str = "smp_passthru";
- break;
- default:
- frame_sz = 32;
- func_str = "unknown";
- break;
- }
-
- printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
- " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
-
- _debug_dump_mf(request_hdr, frame_sz/4);
-}
-
-/**
- * _base_display_event_data - verbose translation of firmware asyn events
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- *
- * Return nothing.
- */
-static void
-_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventNotificationReply_t *mpi_reply)
-{
- char *desc = NULL;
- u16 event;
-
- if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
- return;
-
- event = le16_to_cpu(mpi_reply->Event);
-
- switch (event) {
- case MPI2_EVENT_LOG_DATA:
- desc = "Log Data";
- break;
- case MPI2_EVENT_STATE_CHANGE:
- desc = "Status Change";
- break;
- case MPI2_EVENT_HARD_RESET_RECEIVED:
- desc = "Hard Reset Received";
- break;
- case MPI2_EVENT_EVENT_CHANGE:
- desc = "Event Change";
- break;
- case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
- desc = "Device Status Change";
- break;
- case MPI2_EVENT_IR_OPERATION_STATUS:
- if (!ioc->hide_ir_msg)
- desc = "IR Operation Status";
- break;
- case MPI2_EVENT_SAS_DISCOVERY:
- {
- Mpi2EventDataSasDiscovery_t *event_data =
- (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData;
- printk(MPT2SAS_INFO_FMT "Discovery: (%s)", ioc->name,
- (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
- "start" : "stop");
- if (event_data->DiscoveryStatus)
- printk("discovery_status(0x%08x)",
- le32_to_cpu(event_data->DiscoveryStatus));
- printk("\n");
- return;
- }
- case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
- desc = "SAS Broadcast Primitive";
- break;
- case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
- desc = "SAS Init Device Status Change";
- break;
- case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
- desc = "SAS Init Table Overflow";
- break;
- case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
- desc = "SAS Topology Change List";
- break;
- case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
- desc = "SAS Enclosure Device Status Change";
- break;
- case MPI2_EVENT_IR_VOLUME:
- if (!ioc->hide_ir_msg)
- desc = "IR Volume";
- break;
- case MPI2_EVENT_IR_PHYSICAL_DISK:
- if (!ioc->hide_ir_msg)
- desc = "IR Physical Disk";
- break;
- case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
- if (!ioc->hide_ir_msg)
- desc = "IR Configuration Change List";
- break;
- case MPI2_EVENT_LOG_ENTRY_ADDED:
- if (!ioc->hide_ir_msg)
- desc = "Log Entry Added";
- break;
- case MPI2_EVENT_TEMP_THRESHOLD:
- desc = "Temperature Threshold";
- break;
- }
-
- if (!desc)
- return;
-
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
-}
-#endif
-
-/**
- * _base_sas_log_info - verbose translation of firmware log info
- * @ioc: per adapter object
- * @log_info: log info
- *
- * Return nothing.
- */
-static void
-_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
-{
- union loginfo_type {
- u32 loginfo;
- struct {
- u32 subcode:16;
- u32 code:8;
- u32 originator:4;
- u32 bus_type:4;
- } dw;
- };
- union loginfo_type sas_loginfo;
- char *originator_str = NULL;
-
- sas_loginfo.loginfo = log_info;
- if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
- return;
-
- /* each nexus loss loginfo */
- if (log_info == 0x31170000)
- return;
-
- /* eat the loginfos associated with task aborts */
- if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info ==
- 0x31140000 || log_info == 0x31130000))
- return;
-
- switch (sas_loginfo.dw.originator) {
- case 0:
- originator_str = "IOP";
- break;
- case 1:
- originator_str = "PL";
- break;
- case 2:
- if (!ioc->hide_ir_msg)
- originator_str = "IR";
- else
- originator_str = "WarpDrive";
- break;
- }
-
- printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
- "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
- originator_str, sas_loginfo.dw.code,
- sas_loginfo.dw.subcode);
-}
-
-/**
- * _base_display_reply_info -
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Return nothing.
- */
-static void
-_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
- u16 ioc_status;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (unlikely(!mpi_reply)) {
- printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
- (ioc->logging_level & MPT_DEBUG_REPLY)) {
- _base_sas_ioc_info(ioc , mpi_reply,
- mpt2sas_base_get_msg_frame(ioc, smid));
- }
-#endif
- if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
- _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
-}
-
-/**
- * mpt2sas_base_done - base internal command completion routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-u8
-mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
- return 1;
-
- if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
-
- ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
- if (mpi_reply) {
- ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
- memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
- }
- ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
-
- complete(&ioc->base_cmds.done);
- return 1;
-}
-
-/**
- * _base_async_event - main callback handler for firmware asyn events
- * @ioc: per adapter object
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Returns void.
- */
-static void
-_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
-{
- Mpi2EventNotificationReply_t *mpi_reply;
- Mpi2EventAckRequest_t *ack_request;
- u16 smid;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (!mpi_reply)
- return;
- if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
- return;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- _base_display_event_data(ioc, mpi_reply);
-#endif
- if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
- goto out;
- smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- goto out;
- }
-
- ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
- memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
- ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
- ack_request->Event = mpi_reply->Event;
- ack_request->EventContext = mpi_reply->EventContext;
- ack_request->VF_ID = 0; /* TODO */
- ack_request->VP_ID = 0;
- mpt2sas_base_put_smid_default(ioc, smid);
-
- out:
-
- /* scsih callback handler */
- mpt2sas_scsih_event_callback(ioc, msix_index, reply);
-
- /* ctl callback handler */
- mpt2sas_ctl_event_callback(ioc, msix_index, reply);
-
- return;
-}
-
-/**
- * _base_get_cb_idx - obtain the callback index
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return callback index.
- */
-static u8
-_base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- int i;
- u8 cb_idx;
-
- if (smid < ioc->hi_priority_smid) {
- i = smid - 1;
- cb_idx = ioc->scsi_lookup[i].cb_idx;
- } else if (smid < ioc->internal_smid) {
- i = smid - ioc->hi_priority_smid;
- cb_idx = ioc->hpr_lookup[i].cb_idx;
- } else if (smid <= ioc->hba_queue_depth) {
- i = smid - ioc->internal_smid;
- cb_idx = ioc->internal_lookup[i].cb_idx;
- } else
- cb_idx = 0xFF;
- return cb_idx;
-}
-
-/**
- * _base_mask_interrupts - disable interrupts
- * @ioc: per adapter object
- *
- * Disabling ResetIRQ, Reply and Doorbell Interrupts
- *
- * Return nothing.
- */
-static void
-_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
-{
- u32 him_register;
-
- ioc->mask_interrupts = 1;
- him_register = readl(&ioc->chip->HostInterruptMask);
- him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
- writel(him_register, &ioc->chip->HostInterruptMask);
- readl(&ioc->chip->HostInterruptMask);
-}
-
-/**
- * _base_unmask_interrupts - enable interrupts
- * @ioc: per adapter object
- *
- * Enabling only Reply Interrupts
- *
- * Return nothing.
- */
-static void
-_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
-{
- u32 him_register;
-
- him_register = readl(&ioc->chip->HostInterruptMask);
- him_register &= ~MPI2_HIM_RIM;
- writel(him_register, &ioc->chip->HostInterruptMask);
- ioc->mask_interrupts = 0;
-}
-
-union reply_descriptor {
- u64 word;
- struct {
- u32 low;
- u32 high;
- } u;
-};
-
-/**
- * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
- * @irq: irq number (not used)
- * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
- * @r: pt_regs pointer (not used)
- *
- * Return IRQ_HANDLE if processed, else IRQ_NONE.
- */
-static irqreturn_t
-_base_interrupt(int irq, void *bus_id)
-{
- struct adapter_reply_queue *reply_q = bus_id;
- union reply_descriptor rd;
- u32 completed_cmds;
- u8 request_desript_type;
- u16 smid;
- u8 cb_idx;
- u32 reply;
- u8 msix_index = reply_q->msix_index;
- struct MPT2SAS_ADAPTER *ioc = reply_q->ioc;
- Mpi2ReplyDescriptorsUnion_t *rpf;
- u8 rc;
-
- if (ioc->mask_interrupts)
- return IRQ_NONE;
-
- if (!atomic_add_unless(&reply_q->busy, 1, 1))
- return IRQ_NONE;
-
- rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index];
- request_desript_type = rpf->Default.ReplyFlags
- & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
- if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
- atomic_dec(&reply_q->busy);
- return IRQ_NONE;
- }
-
- completed_cmds = 0;
- cb_idx = 0xFF;
- do {
- rd.word = le64_to_cpu(rpf->Words);
- if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
- goto out;
- reply = 0;
- smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
- if (request_desript_type ==
- MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
- reply = le32_to_cpu
- (rpf->AddressReply.ReplyFrameAddress);
- if (reply > ioc->reply_dma_max_address ||
- reply < ioc->reply_dma_min_address)
- reply = 0;
- } else if (request_desript_type ==
- MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
- goto next;
- else if (request_desript_type ==
- MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
- goto next;
- if (smid) {
- cb_idx = _base_get_cb_idx(ioc, smid);
- if ((likely(cb_idx < MPT_MAX_CALLBACKS))
- && (likely(mpt_callbacks[cb_idx] != NULL))) {
- rc = mpt_callbacks[cb_idx](ioc, smid,
- msix_index, reply);
- if (reply)
- _base_display_reply_info(ioc, smid,
- msix_index, reply);
- if (rc)
- mpt2sas_base_free_smid(ioc, smid);
- }
- }
- if (!smid)
- _base_async_event(ioc, msix_index, reply);
-
- /* reply free queue handling */
- if (reply) {
- ioc->reply_free_host_index =
- (ioc->reply_free_host_index ==
- (ioc->reply_free_queue_depth - 1)) ?
- 0 : ioc->reply_free_host_index + 1;
- ioc->reply_free[ioc->reply_free_host_index] =
- cpu_to_le32(reply);
- wmb();
- writel(ioc->reply_free_host_index,
- &ioc->chip->ReplyFreeHostIndex);
- }
-
- next:
-
- rpf->Words = cpu_to_le64(ULLONG_MAX);
- reply_q->reply_post_host_index =
- (reply_q->reply_post_host_index ==
- (ioc->reply_post_queue_depth - 1)) ? 0 :
- reply_q->reply_post_host_index + 1;
- request_desript_type =
- reply_q->reply_post_free[reply_q->reply_post_host_index].
- Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
- completed_cmds++;
- if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
- goto out;
- if (!reply_q->reply_post_host_index)
- rpf = reply_q->reply_post_free;
- else
- rpf++;
- } while (1);
-
- out:
-
- if (!completed_cmds) {
- atomic_dec(&reply_q->busy);
- return IRQ_NONE;
- }
- wmb();
- if (ioc->is_warpdrive) {
- writel(reply_q->reply_post_host_index,
- ioc->reply_post_host_index[msix_index]);
- atomic_dec(&reply_q->busy);
- return IRQ_HANDLED;
- }
- writel(reply_q->reply_post_host_index | (msix_index <<
- MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex);
- atomic_dec(&reply_q->busy);
- return IRQ_HANDLED;
-}
-
-/**
- * _base_is_controller_msix_enabled - is controller support muli-reply queues
- * @ioc: per adapter object
- *
- */
-static inline int
-_base_is_controller_msix_enabled(struct MPT2SAS_ADAPTER *ioc)
-{
- return (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable;
-}
-
-/**
- * mpt2sas_base_flush_reply_queues - flushing the MSIX reply queues
- * @ioc: per adapter object
- * Context: ISR conext
- *
- * Called when a Task Management request has completed. We want
- * to flush the other reply queues so all the outstanding IO has been
- * completed back to OS before we process the TM completetion.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc)
-{
- struct adapter_reply_queue *reply_q;
-
- /* If MSIX capability is turned off
- * then multi-queues are not enabled
- */
- if (!_base_is_controller_msix_enabled(ioc))
- return;
-
- list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
- if (ioc->shost_recovery)
- return;
- /* TMs are on msix_index == 0 */
- if (reply_q->msix_index == 0)
- continue;
- _base_interrupt(reply_q->vector, (void *)reply_q);
- }
-}
-
-/**
- * mpt2sas_base_release_callback_handler - clear interrupt callback handler
- * @cb_idx: callback index
- *
- * Return nothing.
- */
-void
-mpt2sas_base_release_callback_handler(u8 cb_idx)
-{
- mpt_callbacks[cb_idx] = NULL;
-}
-
-/**
- * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
- * @cb_func: callback function
- *
- * Returns cb_func.
- */
-u8
-mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
-{
- u8 cb_idx;
-
- for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
- if (mpt_callbacks[cb_idx] == NULL)
- break;
-
- mpt_callbacks[cb_idx] = cb_func;
- return cb_idx;
-}
-
-/**
- * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
- *
- * Return nothing.
- */
-void
-mpt2sas_base_initialize_callback_handler(void)
-{
- u8 cb_idx;
-
- for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
- mpt2sas_base_release_callback_handler(cb_idx);
-}
-
-/**
- * mpt2sas_base_build_zero_len_sge - build zero length sg entry
- * @ioc: per adapter object
- * @paddr: virtual address for SGE
- *
- * Create a zero length scatter gather entry to insure the IOCs hardware has
- * something to use if the target device goes brain dead and tries
- * to send data even when none is asked for.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
-{
- u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
- MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
- MPI2_SGE_FLAGS_SHIFT);
- ioc->base_add_sg_single(paddr, flags_length, -1);
-}
-
-/**
- * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
- * @paddr: virtual address for SGE
- * @flags_length: SGE flags and data transfer length
- * @dma_addr: Physical address
- *
- * Return nothing.
- */
-static void
-_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
-{
- Mpi2SGESimple32_t *sgel = paddr;
-
- flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
- MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
- sgel->FlagsLength = cpu_to_le32(flags_length);
- sgel->Address = cpu_to_le32(dma_addr);
-}
-
-
-/**
- * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
- * @paddr: virtual address for SGE
- * @flags_length: SGE flags and data transfer length
- * @dma_addr: Physical address
- *
- * Return nothing.
- */
-static void
-_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
-{
- Mpi2SGESimple64_t *sgel = paddr;
-
- flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
- MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
- sgel->FlagsLength = cpu_to_le32(flags_length);
- sgel->Address = cpu_to_le64(dma_addr);
-}
-
-#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
-
-/**
- * _base_config_dma_addressing - set dma addressing
- * @ioc: per adapter object
- * @pdev: PCI device struct
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
-{
- struct sysinfo s;
- u64 consistent_dma_mask;
-
- if (ioc->dma_mask)
- consistent_dma_mask = DMA_BIT_MASK(64);
- else
- consistent_dma_mask = DMA_BIT_MASK(32);
-
- if (sizeof(dma_addr_t) > 4) {
- const uint64_t required_mask =
- dma_get_required_mask(&pdev->dev);
- if ((required_mask > DMA_BIT_MASK(32)) &&
- !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
- !pci_set_consistent_dma_mask(pdev, consistent_dma_mask)) {
- ioc->base_add_sg_single = &_base_add_sg_single_64;
- ioc->sge_size = sizeof(Mpi2SGESimple64_t);
- ioc->dma_mask = 64;
- goto out;
- }
- }
-
- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
- && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
- ioc->base_add_sg_single = &_base_add_sg_single_32;
- ioc->sge_size = sizeof(Mpi2SGESimple32_t);
- ioc->dma_mask = 32;
- } else
- return -ENODEV;
-
- out:
- si_meminfo(&s);
- printk(MPT2SAS_INFO_FMT
- "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n",
- ioc->name, ioc->dma_mask, convert_to_kb(s.totalram));
-
- return 0;
-}
-
-static int
-_base_change_consistent_dma_mask(struct MPT2SAS_ADAPTER *ioc,
- struct pci_dev *pdev)
-{
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
- return -ENODEV;
- }
- return 0;
-}
-/**
- * _base_check_enable_msix - checks MSIX capabable.
- * @ioc: per adapter object
- *
- * Check to see if card is capable of MSIX, and set number
- * of available msix vectors
- */
-static int
-_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
-{
- int base;
- u16 message_control;
-
-
- /* Check whether controller SAS2008 B0 controller,
- if it is SAS2008 B0 controller use IO-APIC instead of MSIX */
- if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
- ioc->pdev->revision == 0x01) {
- return -EINVAL;
- }
-
- base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
- if (!base) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
- "supported\n", ioc->name));
- return -EINVAL;
- }
-
- /* get msix vector count */
- /* NUMA_IO not supported for older controllers */
- if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 ||
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 ||
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 ||
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 ||
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 ||
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 ||
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2)
- ioc->msix_vector_count = 1;
- else {
- pci_read_config_word(ioc->pdev, base + 2, &message_control);
- ioc->msix_vector_count = (message_control & 0x3FF) + 1;
- }
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
- "vector_count(%d)\n", ioc->name, ioc->msix_vector_count));
-
- return 0;
-}
-
-/**
- * _base_free_irq - free irq
- * @ioc: per adapter object
- *
- * Freeing respective reply_queue from the list.
- */
-static void
-_base_free_irq(struct MPT2SAS_ADAPTER *ioc)
-{
- struct adapter_reply_queue *reply_q, *next;
-
- if (list_empty(&ioc->reply_queue_list))
- return;
-
- list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
- list_del(&reply_q->list);
- irq_set_affinity_hint(reply_q->vector, NULL);
- free_cpumask_var(reply_q->affinity_hint);
- synchronize_irq(reply_q->vector);
- free_irq(reply_q->vector, reply_q);
- kfree(reply_q);
- }
-}
-
-/**
- * _base_request_irq - request irq
- * @ioc: per adapter object
- * @index: msix index into vector table
- * @vector: irq vector
- *
- * Inserting respective reply_queue into the list.
- */
-static int
-_base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector)
-{
- struct adapter_reply_queue *reply_q;
- int r;
-
- reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
- if (!reply_q) {
- printk(MPT2SAS_ERR_FMT "unable to allocate memory %d!\n",
- ioc->name, (int)sizeof(struct adapter_reply_queue));
- return -ENOMEM;
- }
- reply_q->ioc = ioc;
- reply_q->msix_index = index;
- reply_q->vector = vector;
-
- if (!alloc_cpumask_var(&reply_q->affinity_hint, GFP_KERNEL))
- return -ENOMEM;
- cpumask_clear(reply_q->affinity_hint);
-
- atomic_set(&reply_q->busy, 0);
- if (ioc->msix_enable)
- snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
- MPT2SAS_DRIVER_NAME, ioc->id, index);
- else
- snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
- MPT2SAS_DRIVER_NAME, ioc->id);
- r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
- reply_q);
- if (r) {
- printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
- reply_q->name, vector);
- kfree(reply_q);
- return -EBUSY;
- }
-
- INIT_LIST_HEAD(&reply_q->list);
- list_add_tail(&reply_q->list, &ioc->reply_queue_list);
- return 0;
-}
-
-/**
- * _base_assign_reply_queues - assigning msix index for each cpu
- * @ioc: per adapter object
- *
- * The enduser would need to set the affinity via /proc/irq/#/smp_affinity
- *
- * It would nice if we could call irq_set_affinity, however it is not
- * an exported symbol
- */
-static void
-_base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc)
-{
- unsigned int cpu, nr_cpus, nr_msix, index = 0;
- struct adapter_reply_queue *reply_q;
-
- if (!_base_is_controller_msix_enabled(ioc))
- return;
-
- memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
-
- nr_cpus = num_online_cpus();
- nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
- ioc->facts.MaxMSIxVectors);
- if (!nr_msix)
- return;
-
- cpu = cpumask_first(cpu_online_mask);
-
- list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-
- unsigned int i, group = nr_cpus / nr_msix;
-
- if (cpu >= nr_cpus)
- break;
-
- if (index < nr_cpus % nr_msix)
- group++;
-
- for (i = 0 ; i < group ; i++) {
- ioc->cpu_msix_table[cpu] = index;
- cpumask_or(reply_q->affinity_hint,
- reply_q->affinity_hint, get_cpu_mask(cpu));
- cpu = cpumask_next(cpu, cpu_online_mask);
- }
-
- if (irq_set_affinity_hint(reply_q->vector,
- reply_q->affinity_hint))
- dinitprintk(ioc, pr_info(MPT2SAS_FMT
- "error setting affinity hint for irq vector %d\n",
- ioc->name, reply_q->vector));
- index++;
- }
-}
-
-/**
- * _base_disable_msix - disables msix
- * @ioc: per adapter object
- *
- */
-static void
-_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
-{
- if (ioc->msix_enable) {
- pci_disable_msix(ioc->pdev);
- ioc->msix_enable = 0;
- }
-}
-
-/**
- * _base_enable_msix - enables msix, failback to io_apic
- * @ioc: per adapter object
- *
- */
-static int
-_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
-{
- struct msix_entry *entries, *a;
- int r;
- int i;
- u8 try_msix = 0;
-
- if (msix_disable == -1 || msix_disable == 0)
- try_msix = 1;
-
- if (!try_msix)
- goto try_ioapic;
-
- if (_base_check_enable_msix(ioc) != 0)
- goto try_ioapic;
-
- ioc->reply_queue_count = min_t(int, ioc->cpu_count,
- ioc->msix_vector_count);
-
- if (!ioc->rdpq_array_enable && max_msix_vectors == -1)
- max_msix_vectors = 8;
-
- if (max_msix_vectors > 0) {
- ioc->reply_queue_count = min_t(int, max_msix_vectors,
- ioc->reply_queue_count);
- ioc->msix_vector_count = ioc->reply_queue_count;
- } else if (max_msix_vectors == 0)
- goto try_ioapic;
-
- printk(MPT2SAS_INFO_FMT
- "MSI-X vectors supported: %d, no of cores: %d, max_msix_vectors: %d\n",
- ioc->name, ioc->msix_vector_count, ioc->cpu_count, max_msix_vectors);
-
- entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
- GFP_KERNEL);
- if (!entries) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "kcalloc "
- "failed @ at %s:%d/%s() !!!\n", ioc->name, __FILE__,
- __LINE__, __func__));
- goto try_ioapic;
- }
-
- for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++)
- a->entry = i;
-
- r = pci_enable_msix_exact(ioc->pdev, entries, ioc->reply_queue_count);
- if (r) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT
- "pci_enable_msix_exact failed (r=%d) !!!\n", ioc->name, r));
- kfree(entries);
- goto try_ioapic;
- }
-
- ioc->msix_enable = 1;
- for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) {
- r = _base_request_irq(ioc, i, a->vector);
- if (r) {
- _base_free_irq(ioc);
- _base_disable_msix(ioc);
- kfree(entries);
- goto try_ioapic;
- }
- }
-
- kfree(entries);
- return 0;
-
-/* failback to io_apic interrupt routing */
- try_ioapic:
-
- ioc->reply_queue_count = 1;
- r = _base_request_irq(ioc, 0, ioc->pdev->irq);
-
- return r;
-}
-
-/**
- * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
- * @ioc: per adapter object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
-{
- struct pci_dev *pdev = ioc->pdev;
- u32 memap_sz;
- u32 pio_sz;
- int i, r = 0;
- u64 pio_chip = 0;
- u64 chip_phys = 0;
- struct adapter_reply_queue *reply_q;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",
- ioc->name, __func__));
-
- ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
- if (pci_enable_device_mem(pdev)) {
- printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
- "failed\n", ioc->name);
- ioc->bars = 0;
- return -ENODEV;
- }
-
-
- if (pci_request_selected_regions(pdev, ioc->bars,
- MPT2SAS_DRIVER_NAME)) {
- printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
- "failed\n", ioc->name);
- ioc->bars = 0;
- r = -ENODEV;
- goto out_fail;
- }
-
- /* AER (Advanced Error Reporting) hooks */
- pci_enable_pcie_error_reporting(pdev);
-
- pci_set_master(pdev);
-
- if (_base_config_dma_addressing(ioc, pdev) != 0) {
- printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
- ioc->name, pci_name(pdev));
- r = -ENODEV;
- goto out_fail;
- }
-
- for (i = 0, memap_sz = 0, pio_sz = 0; (i < DEVICE_COUNT_RESOURCE) &&
- (!memap_sz || !pio_sz); i++) {
- if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
- if (pio_sz)
- continue;
- pio_chip = (u64)pci_resource_start(pdev, i);
- pio_sz = pci_resource_len(pdev, i);
- } else {
- if (memap_sz)
- continue;
- /* verify memory resource is valid before using */
- if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
- ioc->chip_phys = pci_resource_start(pdev, i);
- chip_phys = (u64)ioc->chip_phys;
- memap_sz = pci_resource_len(pdev, i);
- ioc->chip = ioremap(ioc->chip_phys, memap_sz);
- }
- }
- }
-
- if (ioc->chip == NULL) {
- printk(MPT2SAS_ERR_FMT "unable to map adapter memory! "
- "or resource not found\n", ioc->name);
- r = -EINVAL;
- goto out_fail;
- }
-
- _base_mask_interrupts(ioc);
-
- r = _base_get_ioc_facts(ioc, CAN_SLEEP);
- if (r)
- goto out_fail;
-
- if (!ioc->rdpq_array_enable_assigned) {
- ioc->rdpq_array_enable = ioc->rdpq_array_capable;
- ioc->rdpq_array_enable_assigned = 1;
- }
-
- r = _base_enable_msix(ioc);
- if (r)
- goto out_fail;
-
- list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
- printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
- reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
- "IO-APIC enabled"), reply_q->vector);
-
- printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
- ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
- printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
- ioc->name, (unsigned long long)pio_chip, pio_sz);
-
- /* Save PCI configuration state for recovery from PCI AER/EEH errors */
- pci_save_state(pdev);
-
- return 0;
-
- out_fail:
- if (ioc->chip_phys)
- iounmap(ioc->chip);
- ioc->chip_phys = 0;
- pci_release_selected_regions(ioc->pdev, ioc->bars);
- pci_disable_pcie_error_reporting(pdev);
- pci_disable_device(pdev);
- return r;
-}
-
-/**
- * mpt2sas_base_get_msg_frame - obtain request mf pointer
- * @ioc: per adapter object
- * @smid: system request message index(smid zero is invalid)
- *
- * Returns virt pointer to message frame.
- */
-void *
-mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- return (void *)(ioc->request + (smid * ioc->request_sz));
-}
-
-/**
- * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns virt pointer to sense buffer.
- */
-void *
-mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
-}
-
-/**
- * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns phys pointer to the low 32bit address of the sense buffer.
- */
-__le32
-mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- return cpu_to_le32(ioc->sense_dma +
- ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
-}
-
-/**
- * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
- * @ioc: per adapter object
- * @phys_addr: lower 32 physical addr of the reply
- *
- * Converts 32bit lower physical addr into a virt address.
- */
-void *
-mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
-{
- if (!phys_addr)
- return NULL;
- return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
-}
-
-/**
- * mpt2sas_base_get_smid - obtain a free smid from internal queue
- * @ioc: per adapter object
- * @cb_idx: callback index
- *
- * Returns smid (zero is invalid)
- */
-u16
-mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
-{
- unsigned long flags;
- struct request_tracker *request;
- u16 smid;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- if (list_empty(&ioc->internal_free_list)) {
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
- ioc->name, __func__);
- return 0;
- }
-
- request = list_entry(ioc->internal_free_list.next,
- struct request_tracker, tracker_list);
- request->cb_idx = cb_idx;
- smid = request->smid;
- list_del(&request->tracker_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return smid;
-}
-
-/**
- * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
- * @ioc: per adapter object
- * @cb_idx: callback index
- * @scmd: pointer to scsi command object
- *
- * Returns smid (zero is invalid)
- */
-u16
-mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
- struct scsi_cmnd *scmd)
-{
- unsigned long flags;
- struct scsiio_tracker *request;
- u16 smid;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- if (list_empty(&ioc->free_list)) {
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
- ioc->name, __func__);
- return 0;
- }
-
- request = list_entry(ioc->free_list.next,
- struct scsiio_tracker, tracker_list);
- request->scmd = scmd;
- request->cb_idx = cb_idx;
- smid = request->smid;
- list_del(&request->tracker_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return smid;
-}
-
-/**
- * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
- * @ioc: per adapter object
- * @cb_idx: callback index
- *
- * Returns smid (zero is invalid)
- */
-u16
-mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
-{
- unsigned long flags;
- struct request_tracker *request;
- u16 smid;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- if (list_empty(&ioc->hpr_free_list)) {
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return 0;
- }
-
- request = list_entry(ioc->hpr_free_list.next,
- struct request_tracker, tracker_list);
- request->cb_idx = cb_idx;
- smid = request->smid;
- list_del(&request->tracker_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return smid;
-}
-
-
-/**
- * mpt2sas_base_free_smid - put smid back on free_list
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return nothing.
- */
-void
-mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- unsigned long flags;
- int i;
- struct chain_tracker *chain_req, *next;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- if (smid < ioc->hi_priority_smid) {
- /* scsiio queue */
- i = smid - 1;
- if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
- list_for_each_entry_safe(chain_req, next,
- &ioc->scsi_lookup[i].chain_list, tracker_list) {
- list_del_init(&chain_req->tracker_list);
- list_add(&chain_req->tracker_list,
- &ioc->free_chain_list);
- }
- }
- ioc->scsi_lookup[i].cb_idx = 0xFF;
- ioc->scsi_lookup[i].scmd = NULL;
- ioc->scsi_lookup[i].direct_io = 0;
- list_add(&ioc->scsi_lookup[i].tracker_list,
- &ioc->free_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
- /*
- * See _wait_for_commands_to_complete() call with regards
- * to this code.
- */
- if (ioc->shost_recovery && ioc->pending_io_count) {
- if (ioc->pending_io_count == 1)
- wake_up(&ioc->reset_wq);
- ioc->pending_io_count--;
- }
- return;
- } else if (smid < ioc->internal_smid) {
- /* hi-priority */
- i = smid - ioc->hi_priority_smid;
- ioc->hpr_lookup[i].cb_idx = 0xFF;
- list_add(&ioc->hpr_lookup[i].tracker_list,
- &ioc->hpr_free_list);
- } else if (smid <= ioc->hba_queue_depth) {
- /* internal queue */
- i = smid - ioc->internal_smid;
- ioc->internal_lookup[i].cb_idx = 0xFF;
- list_add(&ioc->internal_lookup[i].tracker_list,
- &ioc->internal_free_list);
- }
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-}
-
-/**
- * _base_writeq - 64 bit write to MMIO
- * @ioc: per adapter object
- * @b: data payload
- * @addr: address in MMIO space
- * @writeq_lock: spin lock
- *
- * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
- * care of 32 bit environment where its not quarenteed to send the entire word
- * in one transfer.
- */
-#ifndef writeq
-static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
- spinlock_t *writeq_lock)
-{
- unsigned long flags;
- __u64 data_out = cpu_to_le64(b);
-
- spin_lock_irqsave(writeq_lock, flags);
- writel((u32)(data_out), addr);
- writel((u32)(data_out >> 32), (addr + 4));
- spin_unlock_irqrestore(writeq_lock, flags);
-}
-#else
-static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
- spinlock_t *writeq_lock)
-{
- writeq(cpu_to_le64(b), addr);
-}
-#endif
-
-static inline u8
-_base_get_msix_index(struct MPT2SAS_ADAPTER *ioc)
-{
- return ioc->cpu_msix_table[raw_smp_processor_id()];
-}
-
-/**
- * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
- * @ioc: per adapter object
- * @smid: system request message index
- * @handle: device handle
- *
- * Return nothing.
- */
-void
-mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
-{
- Mpi2RequestDescriptorUnion_t descriptor;
- u64 *request = (u64 *)&descriptor;
-
-
- descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
- descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
- descriptor.SCSIIO.SMID = cpu_to_le16(smid);
- descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
- descriptor.SCSIIO.LMID = 0;
- _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
- &ioc->scsi_lookup_lock);
-}
-
-
-/**
- * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return nothing.
- */
-void
-mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- Mpi2RequestDescriptorUnion_t descriptor;
- u64 *request = (u64 *)&descriptor;
-
- descriptor.HighPriority.RequestFlags =
- MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
- descriptor.HighPriority.MSIxIndex = 0;
- descriptor.HighPriority.SMID = cpu_to_le16(smid);
- descriptor.HighPriority.LMID = 0;
- descriptor.HighPriority.Reserved1 = 0;
- _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
- &ioc->scsi_lookup_lock);
-}
-
-/**
- * mpt2sas_base_put_smid_default - Default, primarily used for config pages
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return nothing.
- */
-void
-mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- Mpi2RequestDescriptorUnion_t descriptor;
- u64 *request = (u64 *)&descriptor;
-
- descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
- descriptor.Default.MSIxIndex = _base_get_msix_index(ioc);
- descriptor.Default.SMID = cpu_to_le16(smid);
- descriptor.Default.LMID = 0;
- descriptor.Default.DescriptorTypeDependent = 0;
- _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
- &ioc->scsi_lookup_lock);
-}
-
-/**
- * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
- * @ioc: per adapter object
- * @smid: system request message index
- * @io_index: value used to track the IO
- *
- * Return nothing.
- */
-void
-mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- u16 io_index)
-{
- Mpi2RequestDescriptorUnion_t descriptor;
- u64 *request = (u64 *)&descriptor;
-
- descriptor.SCSITarget.RequestFlags =
- MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
- descriptor.SCSITarget.MSIxIndex = _base_get_msix_index(ioc);
- descriptor.SCSITarget.SMID = cpu_to_le16(smid);
- descriptor.SCSITarget.LMID = 0;
- descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
- _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
- &ioc->scsi_lookup_lock);
-}
-
-/**
- * _base_display_dell_branding - Disply branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
-{
- char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
-
- if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
- return;
-
- memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
- switch (ioc->pdev->subsystem_device) {
- case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
- strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
- strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
- strncpy(dell_branding,
- MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
- strncpy(dell_branding,
- MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
- strncpy(dell_branding,
- MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- case MPT2SAS_DELL_PERC_H200_SSDID:
- strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- case MPT2SAS_DELL_6GBPS_SAS_SSDID:
- strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
- MPT2SAS_DELL_BRANDING_SIZE - 1);
- break;
- default:
- sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
- break;
- }
-
- printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
- " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
- ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
- ioc->pdev->subsystem_device);
-}
-
-/**
- * _base_display_intel_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
-{
- if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
- return;
-
- switch (ioc->pdev->device) {
- case MPI2_MFGPAGE_DEVID_SAS2008:
- switch (ioc->pdev->subsystem_device) {
- case MPT2SAS_INTEL_RMS2LL080_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS2LL080_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS2LL040_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS2LL040_BRANDING);
- break;
- case MPT2SAS_INTEL_SSD910_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_SSD910_BRANDING);
- break;
- default:
- break;
- }
- case MPI2_MFGPAGE_DEVID_SAS2308_2:
- switch (ioc->pdev->subsystem_device) {
- case MPT2SAS_INTEL_RS25GB008_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RS25GB008_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS25JB080_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS25JB080_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS25JB040_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS25JB040_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS25KB080_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS25KB080_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS25KB040_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS25KB040_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS25LB040_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS25LB040_BRANDING);
- break;
- case MPT2SAS_INTEL_RMS25LB080_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_INTEL_RMS25LB080_BRANDING);
- break;
- default:
- break;
- }
- default:
- break;
- }
-}
-
-/**
- * _base_display_hp_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc)
-{
- if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID)
- return;
-
- switch (ioc->pdev->device) {
- case MPI2_MFGPAGE_DEVID_SAS2004:
- switch (ioc->pdev->subsystem_device) {
- case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
- break;
- default:
- break;
- }
- case MPI2_MFGPAGE_DEVID_SAS2308_2:
- switch (ioc->pdev->subsystem_device) {
- case MPT2SAS_HP_2_4_INTERNAL_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_HP_2_4_INTERNAL_BRANDING);
- break;
- case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
- break;
- case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
- break;
- case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
- printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
- break;
- default:
- break;
- }
- default:
- break;
- }
-}
-
-/**
- * _base_display_ioc_capabilities - Disply IOC's capabilities.
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
-{
- int i = 0;
- char desc[16];
- u32 iounit_pg1_flags;
- u32 bios_version;
-
- bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
- strncpy(desc, ioc->manu_pg0.ChipName, 16);
- printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
- "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
- ioc->name, desc,
- (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
- (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
- (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
- ioc->facts.FWVersion.Word & 0x000000FF,
- ioc->pdev->revision,
- (bios_version & 0xFF000000) >> 24,
- (bios_version & 0x00FF0000) >> 16,
- (bios_version & 0x0000FF00) >> 8,
- bios_version & 0x000000FF);
-
- _base_display_dell_branding(ioc);
- _base_display_intel_branding(ioc);
- _base_display_hp_branding(ioc);
-
- printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
-
- if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
- printk("Initiator");
- i++;
- }
-
- if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
- printk("%sTarget", i ? "," : "");
- i++;
- }
-
- i = 0;
- printk("), ");
- printk("Capabilities=(");
-
- if (!ioc->hide_ir_msg) {
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
- printk("Raid");
- i++;
- }
- }
-
- if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
- printk("%sTLR", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
- printk("%sMulticast", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
- printk("%sBIDI Target", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
- printk("%sEEDP", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
- printk("%sSnapshot Buffer", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
- printk("%sDiag Trace Buffer", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
- printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
- i++;
- }
-
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
- printk("%sTask Set Full", i ? "," : "");
- i++;
- }
-
- iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
- if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
- printk("%sNCQ", i ? "," : "");
- i++;
- }
-
- printk(")\n");
-}
-
-/**
- * mpt2sas_base_update_missing_delay - change the missing delay timers
- * @ioc: per adapter object
- * @device_missing_delay: amount of time till device is reported missing
- * @io_missing_delay: interval IO is returned when there is a missing device
- *
- * Return nothing.
- *
- * Passed on the command line, this function will modify the device missing
- * delay, as well as the io missing delay. This should be called at driver
- * load time.
- */
-void
-mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
- u16 device_missing_delay, u8 io_missing_delay)
-{
- u16 dmd, dmd_new, dmd_orignal;
- u8 io_missing_delay_original;
- u16 sz;
- Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
- Mpi2ConfigReply_t mpi_reply;
- u8 num_phys = 0;
- u16 ioc_status;
-
- mpt2sas_config_get_number_hba_phys(ioc, &num_phys);
- if (!num_phys)
- return;
-
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
- sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg1) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
- sas_iounit_pg1, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
-
- /* device missing delay */
- dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
- if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
- dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
- else
- dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
- dmd_orignal = dmd;
- if (device_missing_delay > 0x7F) {
- dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
- device_missing_delay;
- dmd = dmd / 16;
- dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
- } else
- dmd = device_missing_delay;
- sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
-
- /* io missing delay */
- io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
- sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
-
- if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
- sz)) {
- if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
- dmd_new = (dmd &
- MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
- else
- dmd_new =
- dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
- printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), "
- "new(%d)\n", ioc->name, dmd_orignal, dmd_new);
- printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), "
- "new(%d)\n", ioc->name, io_missing_delay_original,
- io_missing_delay);
- ioc->device_missing_delay = dmd_new;
- ioc->io_missing_delay = io_missing_delay;
- }
-
-out:
- kfree(sas_iounit_pg1);
-}
-
-/**
- * _base_static_config_pages - static start of day config pages
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2ConfigReply_t mpi_reply;
- u32 iounit_pg1_flags;
-
- mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
- if (ioc->ir_firmware)
- mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
- &ioc->manu_pg10);
- mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
- mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
- mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
- mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
- mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
- mpt2sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8);
- _base_display_ioc_capabilities(ioc);
-
- /*
- * Enable task_set_full handling in iounit_pg1 when the
- * facts capabilities indicate that its supported.
- */
- iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
- if ((ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
- iounit_pg1_flags &=
- ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
- else
- iounit_pg1_flags |=
- MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
- ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
- mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
-
- if (ioc->iounit_pg8.NumSensors)
- ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors;
-}
-
-/**
- * _base_release_memory_pools - release memory
- * @ioc: per adapter object
- *
- * Free memory allocated from _base_allocate_memory_pools.
- *
- * Return nothing.
- */
-static void
-_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
-{
- int i = 0;
- struct reply_post_struct *rps;
-
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- if (ioc->request) {
- pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
- ioc->request, ioc->request_dma);
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)"
- ": free\n", ioc->name, ioc->request));
- ioc->request = NULL;
- }
-
- if (ioc->sense) {
- pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
- if (ioc->sense_dma_pool)
- pci_pool_destroy(ioc->sense_dma_pool);
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)"
- ": free\n", ioc->name, ioc->sense));
- ioc->sense = NULL;
- }
-
- if (ioc->reply) {
- pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
- if (ioc->reply_dma_pool)
- pci_pool_destroy(ioc->reply_dma_pool);
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)"
- ": free\n", ioc->name, ioc->reply));
- ioc->reply = NULL;
- }
-
- if (ioc->reply_free) {
- pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
- ioc->reply_free_dma);
- if (ioc->reply_free_dma_pool)
- pci_pool_destroy(ioc->reply_free_dma_pool);
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool"
- "(0x%p): free\n", ioc->name, ioc->reply_free));
- ioc->reply_free = NULL;
- }
-
- if (ioc->reply_post) {
- do {
- rps = &ioc->reply_post[i];
- if (rps->reply_post_free) {
- pci_pool_free(
- ioc->reply_post_free_dma_pool,
- rps->reply_post_free,
- rps->reply_post_free_dma);
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "reply_post_free_pool(0x%p): free\n",
- ioc->name, rps->reply_post_free));
- rps->reply_post_free = NULL;
- }
- } while (ioc->rdpq_array_enable &&
- (++i < ioc->reply_queue_count));
-
- if (ioc->reply_post_free_dma_pool)
- pci_pool_destroy(ioc->reply_post_free_dma_pool);
- kfree(ioc->reply_post);
- }
-
- if (ioc->config_page) {
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "config_page(0x%p): free\n", ioc->name,
- ioc->config_page));
- pci_free_consistent(ioc->pdev, ioc->config_page_sz,
- ioc->config_page, ioc->config_page_dma);
- }
-
- if (ioc->scsi_lookup) {
- free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages);
- ioc->scsi_lookup = NULL;
- }
- kfree(ioc->hpr_lookup);
- kfree(ioc->internal_lookup);
- if (ioc->chain_lookup) {
- for (i = 0; i < ioc->chain_depth; i++) {
- if (ioc->chain_lookup[i].chain_buffer)
- pci_pool_free(ioc->chain_dma_pool,
- ioc->chain_lookup[i].chain_buffer,
- ioc->chain_lookup[i].chain_buffer_dma);
- }
- if (ioc->chain_dma_pool)
- pci_pool_destroy(ioc->chain_dma_pool);
- free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
- ioc->chain_lookup = NULL;
- }
-}
-
-
-/**
- * _base_allocate_memory_pools - allocate start of day memory pools
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 success, anything else error
- */
-static int
-_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- struct mpt2sas_facts *facts;
- u16 max_sge_elements;
- u16 chains_needed_per_io;
- u32 sz, total_sz, reply_post_free_sz;
- u32 retry_sz;
- u16 max_request_credit;
- int i;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- retry_sz = 0;
- facts = &ioc->facts;
-
- /* command line tunables for max sgl entries */
- if (max_sgl_entries != -1) {
- ioc->shost->sg_tablesize = min_t(unsigned short,
- max_sgl_entries, SCSI_MAX_SG_CHAIN_SEGMENTS);
- if (ioc->shost->sg_tablesize > MPT2SAS_SG_DEPTH)
- printk(MPT2SAS_WARN_FMT
- "sg_tablesize(%u) is bigger than kernel defined"
- " SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name,
- ioc->shost->sg_tablesize, MPT2SAS_SG_DEPTH);
- } else {
- ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH;
- }
-
- /* command line tunables for max controller queue depth */
- if (max_queue_depth != -1 && max_queue_depth != 0) {
- max_request_credit = min_t(u16, max_queue_depth +
- ioc->hi_priority_depth + ioc->internal_depth,
- facts->RequestCredit);
- if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
- max_request_credit = MAX_HBA_QUEUE_DEPTH;
- } else
- max_request_credit = min_t(u16, facts->RequestCredit,
- MAX_HBA_QUEUE_DEPTH);
-
- ioc->hba_queue_depth = max_request_credit;
- ioc->hi_priority_depth = facts->HighPriorityCredit;
- ioc->internal_depth = ioc->hi_priority_depth + 5;
-
- /* request frame size */
- ioc->request_sz = facts->IOCRequestFrameSize * 4;
-
- /* reply frame size */
- ioc->reply_sz = facts->ReplyFrameSize * 4;
-
- retry_allocation:
- total_sz = 0;
- /* calculate number of sg elements left over in the 1st frame */
- max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
- sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size);
- ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size;
-
- /* now do the same for a chain buffer */
- max_sge_elements = ioc->request_sz - ioc->sge_size;
- ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size;
-
- ioc->chain_offset_value_for_main_message =
- ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) +
- (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4;
-
- /*
- * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
- */
- chains_needed_per_io = ((ioc->shost->sg_tablesize -
- ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
- + 1;
- if (chains_needed_per_io > facts->MaxChainDepth) {
- chains_needed_per_io = facts->MaxChainDepth;
- ioc->shost->sg_tablesize = min_t(u16,
- ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
- * chains_needed_per_io), ioc->shost->sg_tablesize);
- }
- ioc->chains_needed_per_io = chains_needed_per_io;
-
- /* reply free queue sizing - taking into account for 64 FW events */
- ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
-
- /* calculate reply descriptor post queue depth */
- ioc->reply_post_queue_depth = ioc->hba_queue_depth +
- ioc->reply_free_queue_depth + 1;
- /* align the reply post queue on the next 16 count boundary */
- if (ioc->reply_post_queue_depth % 16)
- ioc->reply_post_queue_depth += 16 -
- (ioc->reply_post_queue_depth % 16);
-
-
- if (ioc->reply_post_queue_depth >
- facts->MaxReplyDescriptorPostQueueDepth) {
- ioc->reply_post_queue_depth =
- facts->MaxReplyDescriptorPostQueueDepth -
- (facts->MaxReplyDescriptorPostQueueDepth % 16);
- ioc->hba_queue_depth =
- ((ioc->reply_post_queue_depth - 64) / 2) - 1;
- ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
- }
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
- "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
- "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
- ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
- ioc->chains_needed_per_io));
-
- /* reply post queue, 16 byte align */
- reply_post_free_sz = ioc->reply_post_queue_depth *
- sizeof(Mpi2DefaultReplyDescriptor_t);
-
- sz = reply_post_free_sz;
- if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable)
- sz *= ioc->reply_queue_count;
-
- ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ?
- (ioc->reply_queue_count):1,
- sizeof(struct reply_post_struct), GFP_KERNEL);
-
- if (!ioc->reply_post) {
- printk(MPT2SAS_ERR_FMT "reply_post_free pool: kcalloc failed\n",
- ioc->name);
- goto out;
- }
- ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
- ioc->pdev, sz, 16, 0);
- if (!ioc->reply_post_free_dma_pool) {
- printk(MPT2SAS_ERR_FMT
- "reply_post_free pool: pci_pool_create failed\n",
- ioc->name);
- goto out;
- }
- i = 0;
- do {
- ioc->reply_post[i].reply_post_free =
- pci_pool_alloc(ioc->reply_post_free_dma_pool,
- GFP_KERNEL,
- &ioc->reply_post[i].reply_post_free_dma);
- if (!ioc->reply_post[i].reply_post_free) {
- printk(MPT2SAS_ERR_FMT
- "reply_post_free pool: pci_pool_alloc failed\n",
- ioc->name);
- goto out;
- }
- memset(ioc->reply_post[i].reply_post_free, 0, sz);
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "reply post free pool (0x%p): depth(%d),"
- "element_size(%d), pool_size(%d kB)\n", ioc->name,
- ioc->reply_post[i].reply_post_free,
- ioc->reply_post_queue_depth, 8, sz/1024));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "reply_post_free_dma = (0x%llx)\n", ioc->name,
- (unsigned long long)
- ioc->reply_post[i].reply_post_free_dma));
- total_sz += sz;
- } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
-
- if (ioc->dma_mask == 64) {
- if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
- printk(MPT2SAS_WARN_FMT
- "no suitable consistent DMA mask for %s\n",
- ioc->name, pci_name(ioc->pdev));
- goto out;
- }
- }
-
- ioc->scsiio_depth = ioc->hba_queue_depth -
- ioc->hi_priority_depth - ioc->internal_depth;
-
- /* set the scsi host can_queue depth
- * with some internal commands that could be outstanding
- */
- ioc->shost->can_queue = ioc->scsiio_depth;
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
- "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
-
- /* contiguous pool for request and chains, 16 byte align, one extra "
- * "frame for smid=0
- */
- ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
- sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
-
- /* hi-priority queue */
- sz += (ioc->hi_priority_depth * ioc->request_sz);
-
- /* internal queue */
- sz += (ioc->internal_depth * ioc->request_sz);
-
- ioc->request_dma_sz = sz;
- ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
- if (!ioc->request) {
- printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
- "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
- "total(%d kB)\n", ioc->name, ioc->hba_queue_depth,
- ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
- if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH)
- goto out;
- retry_sz += 64;
- ioc->hba_queue_depth = max_request_credit - retry_sz;
- goto retry_allocation;
- }
-
- if (retry_sz)
- printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
- "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
- "total(%d kb)\n", ioc->name, ioc->hba_queue_depth,
- ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
-
-
- /* hi-priority queue */
- ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) *
- ioc->request_sz);
- ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) *
- ioc->request_sz);
-
- /* internal queue */
- ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth *
- ioc->request_sz);
- ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
- ioc->request_sz);
-
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
- "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
- ioc->request, ioc->hba_queue_depth, ioc->request_sz,
- (ioc->hba_queue_depth * ioc->request_sz)/1024));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
- ioc->name, (unsigned long long) ioc->request_dma));
- total_sz += sz;
-
- sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
- ioc->scsi_lookup_pages = get_order(sz);
- ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
- GFP_KERNEL, ioc->scsi_lookup_pages);
- if (!ioc->scsi_lookup) {
- printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, "
- "sz(%d)\n", ioc->name, (int)sz);
- goto out;
- }
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): "
- "depth(%d)\n", ioc->name, ioc->request,
- ioc->scsiio_depth));
-
- ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
- sz = ioc->chain_depth * sizeof(struct chain_tracker);
- ioc->chain_pages = get_order(sz);
-
- ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
- GFP_KERNEL, ioc->chain_pages);
- if (!ioc->chain_lookup) {
- printk(MPT2SAS_ERR_FMT "chain_lookup: get_free_pages failed, "
- "sz(%d)\n", ioc->name, (int)sz);
- goto out;
- }
- ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
- ioc->request_sz, 16, 0);
- if (!ioc->chain_dma_pool) {
- printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
- "failed\n", ioc->name);
- goto out;
- }
- for (i = 0; i < ioc->chain_depth; i++) {
- ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
- ioc->chain_dma_pool , GFP_KERNEL,
- &ioc->chain_lookup[i].chain_buffer_dma);
- if (!ioc->chain_lookup[i].chain_buffer) {
- ioc->chain_depth = i;
- goto chain_done;
- }
- total_sz += ioc->request_sz;
- }
-chain_done:
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
- "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
- ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
- ioc->request_sz))/1024));
-
- /* initialize hi-priority queue smid's */
- ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
- sizeof(struct request_tracker), GFP_KERNEL);
- if (!ioc->hpr_lookup) {
- printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n",
- ioc->name);
- goto out;
- }
- ioc->hi_priority_smid = ioc->scsiio_depth + 1;
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): "
- "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority,
- ioc->hi_priority_depth, ioc->hi_priority_smid));
-
- /* initialize internal queue smid's */
- ioc->internal_lookup = kcalloc(ioc->internal_depth,
- sizeof(struct request_tracker), GFP_KERNEL);
- if (!ioc->internal_lookup) {
- printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n",
- ioc->name);
- goto out;
- }
- ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth;
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): "
- "depth(%d), start smid(%d)\n", ioc->name, ioc->internal,
- ioc->internal_depth, ioc->internal_smid));
-
- /* sense buffers, 4 byte align */
- sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
- ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
- 0);
- if (!ioc->sense_dma_pool) {
- printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n",
- ioc->name);
- goto out;
- }
- ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
- &ioc->sense_dma);
- if (!ioc->sense) {
- printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n",
- ioc->name);
- goto out;
- }
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
- "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
- SCSI_SENSE_BUFFERSIZE, sz/1024));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n",
- ioc->name, (unsigned long long)ioc->sense_dma));
- total_sz += sz;
-
- /* reply pool, 4 byte align */
- sz = ioc->reply_free_queue_depth * ioc->reply_sz;
- ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
- 0);
- if (!ioc->reply_dma_pool) {
- printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n",
- ioc->name);
- goto out;
- }
- ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
- &ioc->reply_dma);
- if (!ioc->reply) {
- printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n",
- ioc->name);
- goto out;
- }
- ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
- ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
- "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
- ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n",
- ioc->name, (unsigned long long)ioc->reply_dma));
- total_sz += sz;
-
- /* reply free queue, 16 byte align */
- sz = ioc->reply_free_queue_depth * 4;
- ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
- ioc->pdev, sz, 16, 0);
- if (!ioc->reply_free_dma_pool) {
- printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create "
- "failed\n", ioc->name);
- goto out;
- }
- ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
- &ioc->reply_free_dma);
- if (!ioc->reply_free) {
- printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc "
- "failed\n", ioc->name);
- goto out;
- }
- memset(ioc->reply_free, 0, sz);
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): "
- "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
- ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma"
- "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
- total_sz += sz;
-
- ioc->config_page_sz = 512;
- ioc->config_page = pci_alloc_consistent(ioc->pdev,
- ioc->config_page_sz, &ioc->config_page_dma);
- if (!ioc->config_page) {
- printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
- "failed\n", ioc->name);
- goto out;
- }
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
- "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
- "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
- total_sz += ioc->config_page_sz;
-
- printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
- ioc->name, total_sz/1024);
- printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
- "Max Controller Queue Depth(%d)\n",
- ioc->name, ioc->shost->can_queue, facts->RequestCredit);
- printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
- ioc->name, ioc->shost->sg_tablesize);
- return 0;
-
- out:
- return -ENOMEM;
-}
-
-
-/**
- * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
- * @ioc: Pointer to MPT_ADAPTER structure
- * @cooked: Request raw or cooked IOC state
- *
- * Returns all IOC Doorbell register bits if cooked==0, else just the
- * Doorbell bits in MPI_IOC_STATE_MASK.
- */
-u32
-mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
-{
- u32 s, sc;
-
- s = readl(&ioc->chip->Doorbell);
- sc = s & MPI2_IOC_STATE_MASK;
- return cooked ? sc : s;
-}
-
-/**
- * _base_wait_on_iocstate - waiting on a particular ioc state
- * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
- int sleep_flag)
-{
- u32 count, cntdn;
- u32 current_state;
-
- count = 0;
- cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
- do {
- current_state = mpt2sas_base_get_iocstate(ioc, 1);
- if (current_state == ioc_state)
- return 0;
- if (count && current_state == MPI2_IOC_STATE_FAULT)
- break;
- if (sleep_flag == CAN_SLEEP)
- msleep(1);
- else
- udelay(500);
- count++;
- } while (--cntdn);
-
- return current_state;
-}
-
-/**
- * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
- * a write to the doorbell)
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
- */
-static int
-_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
- int sleep_flag)
-{
- u32 cntdn, count;
- u32 int_status;
-
- count = 0;
- cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
- do {
- int_status = readl(&ioc->chip->HostInterruptStatus);
- if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "successful count(%d), timeout(%d)\n", ioc->name,
- __func__, count, timeout));
- return 0;
- }
- if (sleep_flag == CAN_SLEEP)
- msleep(1);
- else
- udelay(500);
- count++;
- } while (--cntdn);
-
- printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
- "int_status(%x)!\n", ioc->name, __func__, count, int_status);
- return -EFAULT;
-}
-
-/**
- * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
- * doorbell.
- */
-static int
-_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
- int sleep_flag)
-{
- u32 cntdn, count;
- u32 int_status;
- u32 doorbell;
-
- count = 0;
- cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
- do {
- int_status = readl(&ioc->chip->HostInterruptStatus);
- if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "successful count(%d), timeout(%d)\n", ioc->name,
- __func__, count, timeout));
- return 0;
- } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
- doorbell = readl(&ioc->chip->Doorbell);
- if ((doorbell & MPI2_IOC_STATE_MASK) ==
- MPI2_IOC_STATE_FAULT) {
- mpt2sas_base_fault_info(ioc , doorbell);
- return -EFAULT;
- }
- } else if (int_status == 0xFFFFFFFF)
- goto out;
-
- if (sleep_flag == CAN_SLEEP)
- msleep(1);
- else
- udelay(500);
- count++;
- } while (--cntdn);
-
- out:
- printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
- "int_status(%x)!\n", ioc->name, __func__, count, int_status);
- return -EFAULT;
-}
-
-/**
- * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
- int sleep_flag)
-{
- u32 cntdn, count;
- u32 doorbell_reg;
-
- count = 0;
- cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
- do {
- doorbell_reg = readl(&ioc->chip->Doorbell);
- if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "successful count(%d), timeout(%d)\n", ioc->name,
- __func__, count, timeout));
- return 0;
- }
- if (sleep_flag == CAN_SLEEP)
- msleep(1);
- else
- udelay(500);
- count++;
- } while (--cntdn);
-
- printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
- "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
- return -EFAULT;
-}
-
-/**
- * _base_send_ioc_reset - send doorbell reset
- * @ioc: per adapter object
- * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout,
- int sleep_flag)
-{
- u32 ioc_state;
- int r = 0;
-
- if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
- printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n",
- ioc->name, __func__);
- return -EFAULT;
- }
-
- if (!(ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
- return -EFAULT;
-
- printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name);
-
- writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
- &ioc->chip->Doorbell);
- if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
- r = -EFAULT;
- goto out;
- }
- ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
- timeout, sleep_flag);
- if (ioc_state) {
- printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
- " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
- r = -EFAULT;
- goto out;
- }
- out:
- printk(MPT2SAS_INFO_FMT "message unit reset: %s\n",
- ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
- return r;
-}
-
-/**
- * _base_handshake_req_reply_wait - send request thru doorbell interface
- * @ioc: per adapter object
- * @request_bytes: request length
- * @request: pointer having request payload
- * @reply_bytes: reply length
- * @reply: pointer to reply payload
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
- u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
-{
- MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
- int i;
- u8 failed;
- u16 dummy;
- __le32 *mfp;
-
- /* make sure doorbell is not in use */
- if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
- printk(MPT2SAS_ERR_FMT "doorbell is in use "
- " (line=%d)\n", ioc->name, __LINE__);
- return -EFAULT;
- }
-
- /* clear pending doorbell interrupts from previous state changes */
- if (readl(&ioc->chip->HostInterruptStatus) &
- MPI2_HIS_IOC2SYS_DB_STATUS)
- writel(0, &ioc->chip->HostInterruptStatus);
-
- /* send message to ioc */
- writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
- ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
- &ioc->chip->Doorbell);
-
- if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
- printk(MPT2SAS_ERR_FMT "doorbell handshake "
- "int failed (line=%d)\n", ioc->name, __LINE__);
- return -EFAULT;
- }
- writel(0, &ioc->chip->HostInterruptStatus);
-
- if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
- printk(MPT2SAS_ERR_FMT "doorbell handshake "
- "ack failed (line=%d)\n", ioc->name, __LINE__);
- return -EFAULT;
- }
-
- /* send message 32-bits at a time */
- for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
- writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
- if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
- failed = 1;
- }
-
- if (failed) {
- printk(MPT2SAS_ERR_FMT "doorbell handshake "
- "sending request failed (line=%d)\n", ioc->name, __LINE__);
- return -EFAULT;
- }
-
- /* now wait for the reply */
- if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
- printk(MPT2SAS_ERR_FMT "doorbell handshake "
- "int failed (line=%d)\n", ioc->name, __LINE__);
- return -EFAULT;
- }
-
- /* read the first two 16-bits, it gives the total length of the reply */
- reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
- & MPI2_DOORBELL_DATA_MASK);
- writel(0, &ioc->chip->HostInterruptStatus);
- if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
- printk(MPT2SAS_ERR_FMT "doorbell handshake "
- "int failed (line=%d)\n", ioc->name, __LINE__);
- return -EFAULT;
- }
- reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
- & MPI2_DOORBELL_DATA_MASK);
- writel(0, &ioc->chip->HostInterruptStatus);
-
- for (i = 2; i < default_reply->MsgLength * 2; i++) {
- if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
- printk(MPT2SAS_ERR_FMT "doorbell "
- "handshake int failed (line=%d)\n", ioc->name,
- __LINE__);
- return -EFAULT;
- }
- if (i >= reply_bytes/2) /* overflow case */
- dummy = readl(&ioc->chip->Doorbell);
- else
- reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
- & MPI2_DOORBELL_DATA_MASK);
- writel(0, &ioc->chip->HostInterruptStatus);
- }
-
- _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
- if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
- " (line=%d)\n", ioc->name, __LINE__));
- }
- writel(0, &ioc->chip->HostInterruptStatus);
-
- if (ioc->logging_level & MPT_DEBUG_INIT) {
- mfp = (__le32 *)reply;
- printk(KERN_INFO "\toffset:data\n");
- for (i = 0; i < reply_bytes/4; i++)
- printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
- le32_to_cpu(mfp[i]));
- }
- return 0;
-}
-
-/**
- * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
- * @ioc: per adapter object
- * @mpi_reply: the reply payload from FW
- * @mpi_request: the request payload sent to FW
- *
- * The SAS IO Unit Control Request message allows the host to perform low-level
- * operations, such as resets on the PHYs of the IO Unit, also allows the host
- * to obtain the IOC assigned device handles for a device if it has other
- * identifying information about the device, in addition allows the host to
- * remove IOC resources associated with the device.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
- Mpi2SasIoUnitControlReply_t *mpi_reply,
- Mpi2SasIoUnitControlRequest_t *mpi_request)
-{
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- bool issue_reset = false;
- int rc;
- void *request;
- u16 wait_state_count;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- mutex_lock(&ioc->base_cmds.mutex);
-
- if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- rc = 0;
- ioc->base_cmds.status = MPT2_CMD_PENDING;
- request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->base_cmds.smid = smid;
- memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
- if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
- mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
- ioc->ioc_link_reset_in_progress = 1;
- init_completion(&ioc->base_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
- msecs_to_jiffies(10000));
- if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
- mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
- ioc->ioc_link_reset_in_progress)
- ioc->ioc_link_reset_in_progress = 0;
- if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SasIoUnitControlRequest_t)/4);
- if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
- issue_reset = true;
- goto issue_host_reset;
- }
- if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
- memcpy(mpi_reply, ioc->base_cmds.reply,
- sizeof(Mpi2SasIoUnitControlReply_t));
- else
- memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- goto out;
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- rc = -EFAULT;
- out:
- mutex_unlock(&ioc->base_cmds.mutex);
- return rc;
-}
-
-
-/**
- * mpt2sas_base_scsi_enclosure_processor - sending request to sep device
- * @ioc: per adapter object
- * @mpi_reply: the reply payload from FW
- * @mpi_request: the request payload sent to FW
- *
- * The SCSI Enclosure Processor request message causes the IOC to
- * communicate with SES devices to control LED status signals.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
- Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
-{
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- bool issue_reset = false;
- int rc;
- void *request;
- u16 wait_state_count;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- mutex_lock(&ioc->base_cmds.mutex);
-
- if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- rc = 0;
- ioc->base_cmds.status = MPT2_CMD_PENDING;
- request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->base_cmds.smid = smid;
- memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
- init_completion(&ioc->base_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
- msecs_to_jiffies(10000));
- if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SepRequest_t)/4);
- if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
- issue_reset = true;
- goto issue_host_reset;
- }
- if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
- memcpy(mpi_reply, ioc->base_cmds.reply,
- sizeof(Mpi2SepReply_t));
- else
- memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- goto out;
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- rc = -EFAULT;
- out:
- mutex_unlock(&ioc->base_cmds.mutex);
- return rc;
-}
-
-/**
- * _base_get_port_facts - obtain port facts reply and save in ioc
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
-{
- Mpi2PortFactsRequest_t mpi_request;
- Mpi2PortFactsReply_t mpi_reply;
- struct mpt2sas_port_facts *pfacts;
- int mpi_reply_sz, mpi_request_sz, r;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
- mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
- memset(&mpi_request, 0, mpi_request_sz);
- mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
- mpi_request.PortNumber = port;
- r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
- (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
-
- if (r != 0) {
- printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
- ioc->name, __func__, r);
- return r;
- }
-
- pfacts = &ioc->pfacts[port];
- memset(pfacts, 0, sizeof(struct mpt2sas_port_facts));
- pfacts->PortNumber = mpi_reply.PortNumber;
- pfacts->VP_ID = mpi_reply.VP_ID;
- pfacts->VF_ID = mpi_reply.VF_ID;
- pfacts->MaxPostedCmdBuffers =
- le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
-
- return 0;
-}
-
-/**
- * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL
- * @ioc: per adapter object
- * @timeout:
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_wait_for_iocstate(struct MPT2SAS_ADAPTER *ioc, int timeout,
- int sleep_flag)
-{
- u32 ioc_state, doorbell;
- int rc;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- if (ioc->pci_error_recovery)
- return 0;
-
- doorbell = mpt2sas_base_get_iocstate(ioc, 0);
- ioc_state = doorbell & MPI2_IOC_STATE_MASK;
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
- ioc->name, __func__, ioc_state));
-
- switch (ioc_state) {
- case MPI2_IOC_STATE_READY:
- case MPI2_IOC_STATE_OPERATIONAL:
- return 0;
- }
-
- if (doorbell & MPI2_DOORBELL_USED) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
- "unexpected doorbell activ!e\n", ioc->name));
- goto issue_diag_reset;
- }
-
- if (ioc_state == MPI2_IOC_STATE_FAULT) {
- mpt2sas_base_fault_info(ioc, doorbell &
- MPI2_DOORBELL_DATA_MASK);
- goto issue_diag_reset;
- }
-
- ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
- timeout, sleep_flag);
- if (ioc_state) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed going to ready state (ioc_state=0x%x)\n",
- ioc->name, __func__, ioc_state);
- return -EFAULT;
- }
-
- issue_diag_reset:
- rc = _base_diag_reset(ioc, sleep_flag);
- return rc;
-}
-
-/**
- * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- Mpi2IOCFactsRequest_t mpi_request;
- Mpi2IOCFactsReply_t mpi_reply;
- struct mpt2sas_facts *facts;
- int mpi_reply_sz, mpi_request_sz, r;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- r = _base_wait_for_iocstate(ioc, 10, sleep_flag);
- if (r) {
- printk(MPT2SAS_ERR_FMT "%s: failed getting to correct state\n",
- ioc->name, __func__);
- return r;
- }
-
- mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
- mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
- memset(&mpi_request, 0, mpi_request_sz);
- mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
- r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
- (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
-
- if (r != 0) {
- printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
- ioc->name, __func__, r);
- return r;
- }
-
- facts = &ioc->facts;
- memset(facts, 0, sizeof(struct mpt2sas_facts));
- facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
- facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
- facts->VP_ID = mpi_reply.VP_ID;
- facts->VF_ID = mpi_reply.VF_ID;
- facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
- facts->MaxChainDepth = mpi_reply.MaxChainDepth;
- facts->WhoInit = mpi_reply.WhoInit;
- facts->NumberOfPorts = mpi_reply.NumberOfPorts;
- facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
- facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
- facts->MaxReplyDescriptorPostQueueDepth =
- le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
- facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
- facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
- if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
- ioc->ir_firmware = 1;
- if ((facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE))
- ioc->rdpq_array_capable = 1;
- facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
- facts->IOCRequestFrameSize =
- le16_to_cpu(mpi_reply.IOCRequestFrameSize);
- facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
- facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
- ioc->shost->max_id = -1;
- facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
- facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
- facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
- facts->HighPriorityCredit =
- le16_to_cpu(mpi_reply.HighPriorityCredit);
- facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
- facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
- "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
- facts->MaxChainDepth));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
- "reply frame size(%d)\n", ioc->name,
- facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
- return 0;
-}
-
-/**
- * _base_send_ioc_init - send ioc_init to firmware
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- Mpi2IOCInitRequest_t mpi_request;
- Mpi2IOCInitReply_t mpi_reply;
- int i, r = 0;
- struct timeval current_time;
- u16 ioc_status;
- u32 reply_post_free_array_sz = 0;
- Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL;
- dma_addr_t reply_post_free_array_dma;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
- mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
- mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
- mpi_request.VF_ID = 0; /* TODO */
- mpi_request.VP_ID = 0;
- mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
- mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
-
- if (_base_is_controller_msix_enabled(ioc))
- mpi_request.HostMSIxVectors = ioc->reply_queue_count;
- mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
- mpi_request.ReplyDescriptorPostQueueDepth =
- cpu_to_le16(ioc->reply_post_queue_depth);
- mpi_request.ReplyFreeQueueDepth =
- cpu_to_le16(ioc->reply_free_queue_depth);
-
- mpi_request.SenseBufferAddressHigh =
- cpu_to_le32((u64)ioc->sense_dma >> 32);
- mpi_request.SystemReplyAddressHigh =
- cpu_to_le32((u64)ioc->reply_dma >> 32);
- mpi_request.SystemRequestFrameBaseAddress =
- cpu_to_le64((u64)ioc->request_dma);
- mpi_request.ReplyFreeQueueAddress =
- cpu_to_le64((u64)ioc->reply_free_dma);
-
- if (ioc->rdpq_array_enable) {
- reply_post_free_array_sz = ioc->reply_queue_count *
- sizeof(Mpi2IOCInitRDPQArrayEntry);
- reply_post_free_array = pci_alloc_consistent(ioc->pdev,
- reply_post_free_array_sz, &reply_post_free_array_dma);
- if (!reply_post_free_array) {
- printk(MPT2SAS_ERR_FMT
- "reply_post_free_array: pci_alloc_consistent failed\n",
- ioc->name);
- r = -ENOMEM;
- goto out;
- }
- memset(reply_post_free_array, 0, reply_post_free_array_sz);
- for (i = 0; i < ioc->reply_queue_count; i++)
- reply_post_free_array[i].RDPQBaseAddress =
- cpu_to_le64(
- (u64)ioc->reply_post[i].reply_post_free_dma);
- mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE;
- mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le64((u64)reply_post_free_array_dma);
- } else {
- mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma);
- }
-
- /* This time stamp specifies number of milliseconds
- * since epoch ~ midnight January 1, 1970.
- */
- do_gettimeofday(&current_time);
- mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 +
- (current_time.tv_usec / 1000));
-
- if (ioc->logging_level & MPT_DEBUG_INIT) {
- __le32 *mfp;
- int i;
-
- mfp = (__le32 *)&mpi_request;
- printk(KERN_INFO "\toffset:data\n");
- for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
- printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
- le32_to_cpu(mfp[i]));
- }
-
- r = _base_handshake_req_reply_wait(ioc,
- sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
- sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
- sleep_flag);
-
- if (r != 0) {
- printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
- ioc->name, __func__, r);
- goto out;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
- mpi_reply.IOCLogInfo) {
- printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
- r = -EIO;
- }
-
-out:
- if (reply_post_free_array)
- pci_free_consistent(ioc->pdev, reply_post_free_array_sz,
- reply_post_free_array,
- reply_post_free_array_dma);
- return r;
-}
-
-/**
- * mpt2sas_port_enable_done - command completion routine for port enable
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-u8
-mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
- u16 ioc_status;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
- return 1;
-
- if (ioc->port_enable_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
-
- ioc->port_enable_cmds.status |= MPT2_CMD_COMPLETE;
- if (mpi_reply) {
- ioc->port_enable_cmds.status |= MPT2_CMD_REPLY_VALID;
- memcpy(ioc->port_enable_cmds.reply, mpi_reply,
- mpi_reply->MsgLength*4);
- }
- ioc->port_enable_cmds.status &= ~MPT2_CMD_PENDING;
-
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- ioc->port_enable_failed = 1;
-
- if (ioc->is_driver_loading) {
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
- mpt2sas_port_enable_complete(ioc);
- return 1;
- } else {
- ioc->start_scan_failed = ioc_status;
- ioc->start_scan = 0;
- return 1;
- }
- }
- complete(&ioc->port_enable_cmds.done);
- return 1;
-}
-
-
-/**
- * _base_send_port_enable - send port_enable(discovery stuff) to firmware
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- Mpi2PortEnableRequest_t *mpi_request;
- Mpi2PortEnableReply_t *mpi_reply;
- unsigned long timeleft;
- int r = 0;
- u16 smid;
- u16 ioc_status;
-
- printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
-
- if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
- printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
- ioc->name, __func__);
- return -EAGAIN;
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- return -EAGAIN;
- }
-
- ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->port_enable_cmds.smid = smid;
- memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
- mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
-
- init_completion(&ioc->port_enable_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
- 300*HZ);
- if (!(ioc->port_enable_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2PortEnableRequest_t)/4);
- if (ioc->port_enable_cmds.status & MPT2_CMD_RESET)
- r = -EFAULT;
- else
- r = -ETIME;
- goto out;
- }
- mpi_reply = ioc->port_enable_cmds.reply;
-
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "%s: failed with (ioc_status=0x%08x)\n",
- ioc->name, __func__, ioc_status);
- r = -EFAULT;
- goto out;
- }
- out:
- ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
- printk(MPT2SAS_INFO_FMT "port enable: %s\n", ioc->name, ((r == 0) ?
- "SUCCESS" : "FAILED"));
- return r;
-}
-
-/**
- * mpt2sas_port_enable - initiate firmware discovery (don't wait for reply)
- * @ioc: per adapter object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2PortEnableRequest_t *mpi_request;
- u16 smid;
-
- printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
-
- if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
- printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
- ioc->name, __func__);
- return -EAGAIN;
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- return -EAGAIN;
- }
-
- ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->port_enable_cmds.smid = smid;
- memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
- mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
-
- mpt2sas_base_put_smid_default(ioc, smid);
- return 0;
-}
-
-/**
- * _base_determine_wait_on_discovery - desposition
- * @ioc: per adapter object
- *
- * Decide whether to wait on discovery to complete. Used to either
- * locate boot device, or report volumes ahead of physical devices.
- *
- * Returns 1 for wait, 0 for don't wait
- */
-static int
-_base_determine_wait_on_discovery(struct MPT2SAS_ADAPTER *ioc)
-{
- /* We wait for discovery to complete if IR firmware is loaded.
- * The sas topology events arrive before PD events, so we need time to
- * turn on the bit in ioc->pd_handles to indicate PD
- * Also, it maybe required to report Volumes ahead of physical
- * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set.
- */
- if (ioc->ir_firmware)
- return 1;
-
- /* if no Bios, then we don't need to wait */
- if (!ioc->bios_pg3.BiosVersion)
- return 0;
-
- /* Bios is present, then we drop down here.
- *
- * If there any entries in the Bios Page 2, then we wait
- * for discovery to complete.
- */
-
- /* Current Boot Device */
- if ((ioc->bios_pg2.CurrentBootDeviceForm &
- MPI2_BIOSPAGE2_FORM_MASK) ==
- MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
- /* Request Boot Device */
- (ioc->bios_pg2.ReqBootDeviceForm &
- MPI2_BIOSPAGE2_FORM_MASK) ==
- MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
- /* Alternate Request Boot Device */
- (ioc->bios_pg2.ReqAltBootDeviceForm &
- MPI2_BIOSPAGE2_FORM_MASK) ==
- MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED)
- return 0;
-
- return 1;
-}
-
-
-/**
- * _base_unmask_events - turn on notification for this event
- * @ioc: per adapter object
- * @event: firmware event
- *
- * The mask is stored in ioc->event_masks.
- */
-static void
-_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
-{
- u32 desired_event;
-
- if (event >= 128)
- return;
-
- desired_event = (1 << (event % 32));
-
- if (event < 32)
- ioc->event_masks[0] &= ~desired_event;
- else if (event < 64)
- ioc->event_masks[1] &= ~desired_event;
- else if (event < 96)
- ioc->event_masks[2] &= ~desired_event;
- else if (event < 128)
- ioc->event_masks[3] &= ~desired_event;
-}
-
-/**
- * _base_event_notification - send event notification
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- Mpi2EventNotificationRequest_t *mpi_request;
- unsigned long timeleft;
- u16 smid;
- int r = 0;
- int i;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
- printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
- ioc->name, __func__);
- return -EAGAIN;
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- return -EAGAIN;
- }
- ioc->base_cmds.status = MPT2_CMD_PENDING;
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->base_cmds.smid = smid;
- memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
- mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
- for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
- mpi_request->EventMasks[i] =
- cpu_to_le32(ioc->event_masks[i]);
- init_completion(&ioc->base_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
- if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2EventNotificationRequest_t)/4);
- if (ioc->base_cmds.status & MPT2_CMD_RESET)
- r = -EFAULT;
- else
- r = -ETIME;
- } else
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
- ioc->name, __func__));
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- return r;
-}
-
-/**
- * mpt2sas_base_validate_event_type - validating event types
- * @ioc: per adapter object
- * @event: firmware event
- *
- * This will turn on firmware event notification when application
- * ask for that event. We don't mask events that are already enabled.
- */
-void
-mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
-{
- int i, j;
- u32 event_mask, desired_event;
- u8 send_update_to_fw;
-
- for (i = 0, send_update_to_fw = 0; i <
- MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
- event_mask = ~event_type[i];
- desired_event = 1;
- for (j = 0; j < 32; j++) {
- if (!(event_mask & desired_event) &&
- (ioc->event_masks[i] & desired_event)) {
- ioc->event_masks[i] &= ~desired_event;
- send_update_to_fw = 1;
- }
- desired_event = (desired_event << 1);
- }
- }
-
- if (!send_update_to_fw)
- return;
-
- mutex_lock(&ioc->base_cmds.mutex);
- _base_event_notification(ioc, CAN_SLEEP);
- mutex_unlock(&ioc->base_cmds.mutex);
-}
-
-/**
- * _base_diag_reset - the "big hammer" start of day reset
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- u32 host_diagnostic;
- u32 ioc_state;
- u32 count;
- u32 hcb_size;
-
- printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",
- ioc->name));
-
- count = 0;
- do {
- /* Write magic sequence to WriteSequence register
- * Loop until in diagnostic mode
- */
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic "
- "sequence\n", ioc->name));
- writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
- writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
- writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
- writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
- writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
- writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
- writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
-
- /* wait 100 msec */
- if (sleep_flag == CAN_SLEEP)
- msleep(100);
- else
- mdelay(100);
-
- if (count++ > 20)
- goto out;
-
- host_diagnostic = readl(&ioc->chip->HostDiagnostic);
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic "
- "sequence: count(%d), host_diagnostic(0x%08x)\n",
- ioc->name, count, host_diagnostic));
-
- } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
-
- hcb_size = readl(&ioc->chip->HCBSize);
-
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n",
- ioc->name));
- writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
- &ioc->chip->HostDiagnostic);
-
- /* This delay allows the chip PCIe hardware time to finish reset tasks*/
- if (sleep_flag == CAN_SLEEP)
- msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
- else
- mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
-
- /* Approximately 300 second max wait */
- for (count = 0; count < (300000000 /
- MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC); count++) {
-
- host_diagnostic = readl(&ioc->chip->HostDiagnostic);
-
- if (host_diagnostic == 0xFFFFFFFF)
- goto out;
- if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
- break;
-
- /* Wait to pass the second read delay window */
- if (sleep_flag == CAN_SLEEP)
- msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
- /1000);
- else
- mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
- /1000);
- }
-
- if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
-
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter "
- "assuming the HCB Address points to good F/W\n",
- ioc->name));
- host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
- host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
- writel(host_diagnostic, &ioc->chip->HostDiagnostic);
-
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT
- "re-enable the HCDW\n", ioc->name));
- writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
- &ioc->chip->HCBSize);
- }
-
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n",
- ioc->name));
- writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
- &ioc->chip->HostDiagnostic);
-
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the "
- "diagnostic register\n", ioc->name));
- writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
-
- drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the "
- "READY state\n", ioc->name));
- ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
- sleep_flag);
- if (ioc_state) {
- printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
- " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
- goto out;
- }
-
- printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
- return 0;
-
- out:
- printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name);
- return -EFAULT;
-}
-
-/**
- * _base_make_ioc_ready - put controller in READY state
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- * @type: FORCE_BIG_HAMMER or SOFT_RESET
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
- enum reset_type type)
-{
- u32 ioc_state;
- int rc;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- if (ioc->pci_error_recovery)
- return 0;
-
- ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
- ioc->name, __func__, ioc_state));
-
- if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
- return 0;
-
- if (ioc_state & MPI2_DOORBELL_USED) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
- "active!\n", ioc->name));
- goto issue_diag_reset;
- }
-
- if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- mpt2sas_base_fault_info(ioc, ioc_state &
- MPI2_DOORBELL_DATA_MASK);
- goto issue_diag_reset;
- }
-
- if (type == FORCE_BIG_HAMMER)
- goto issue_diag_reset;
-
- if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
- if (!(_base_send_ioc_reset(ioc,
- MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
- ioc->ioc_reset_count++;
- return 0;
- }
-
- issue_diag_reset:
- rc = _base_diag_reset(ioc, CAN_SLEEP);
- ioc->ioc_reset_count++;
- return rc;
-}
-
-/**
- * _base_make_ioc_operational - put controller in OPERATIONAL state
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- int r, i;
- unsigned long flags;
- u32 reply_address;
- u16 smid;
- struct _tr_list *delayed_tr, *delayed_tr_next;
- u8 hide_flag;
- struct adapter_reply_queue *reply_q;
- long reply_post_free;
- u32 reply_post_free_sz, index = 0;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- /* clean the delayed target reset list */
- list_for_each_entry_safe(delayed_tr, delayed_tr_next,
- &ioc->delayed_tr_list, list) {
- list_del(&delayed_tr->list);
- kfree(delayed_tr);
- }
-
- list_for_each_entry_safe(delayed_tr, delayed_tr_next,
- &ioc->delayed_tr_volume_list, list) {
- list_del(&delayed_tr->list);
- kfree(delayed_tr);
- }
-
- /* initialize the scsi lookup free list */
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- INIT_LIST_HEAD(&ioc->free_list);
- smid = 1;
- for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
- INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
- ioc->scsi_lookup[i].cb_idx = 0xFF;
- ioc->scsi_lookup[i].smid = smid;
- ioc->scsi_lookup[i].scmd = NULL;
- ioc->scsi_lookup[i].direct_io = 0;
- list_add_tail(&ioc->scsi_lookup[i].tracker_list,
- &ioc->free_list);
- }
-
- /* hi-priority queue */
- INIT_LIST_HEAD(&ioc->hpr_free_list);
- smid = ioc->hi_priority_smid;
- for (i = 0; i < ioc->hi_priority_depth; i++, smid++) {
- ioc->hpr_lookup[i].cb_idx = 0xFF;
- ioc->hpr_lookup[i].smid = smid;
- list_add_tail(&ioc->hpr_lookup[i].tracker_list,
- &ioc->hpr_free_list);
- }
-
- /* internal queue */
- INIT_LIST_HEAD(&ioc->internal_free_list);
- smid = ioc->internal_smid;
- for (i = 0; i < ioc->internal_depth; i++, smid++) {
- ioc->internal_lookup[i].cb_idx = 0xFF;
- ioc->internal_lookup[i].smid = smid;
- list_add_tail(&ioc->internal_lookup[i].tracker_list,
- &ioc->internal_free_list);
- }
-
- /* chain pool */
- INIT_LIST_HEAD(&ioc->free_chain_list);
- for (i = 0; i < ioc->chain_depth; i++)
- list_add_tail(&ioc->chain_lookup[i].tracker_list,
- &ioc->free_chain_list);
-
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
- /* initialize Reply Free Queue */
- for (i = 0, reply_address = (u32)ioc->reply_dma ;
- i < ioc->reply_free_queue_depth ; i++, reply_address +=
- ioc->reply_sz)
- ioc->reply_free[i] = cpu_to_le32(reply_address);
-
- /* initialize reply queues */
- if (ioc->is_driver_loading)
- _base_assign_reply_queues(ioc);
-
- /* initialize Reply Post Free Queue */
- reply_post_free_sz = ioc->reply_post_queue_depth *
- sizeof(Mpi2DefaultReplyDescriptor_t);
- reply_post_free = (long)ioc->reply_post[index].reply_post_free;
- list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
- reply_q->reply_post_host_index = 0;
- reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
- reply_post_free;
- for (i = 0; i < ioc->reply_post_queue_depth; i++)
- reply_q->reply_post_free[i].Words =
- cpu_to_le64(ULLONG_MAX);
- if (!_base_is_controller_msix_enabled(ioc))
- goto skip_init_reply_post_free_queue;
- /*
- * If RDPQ is enabled, switch to the next allocation.
- * Otherwise advance within the contiguous region.
- */
- if (ioc->rdpq_array_enable)
- reply_post_free = (long)
- ioc->reply_post[++index].reply_post_free;
- else
- reply_post_free += reply_post_free_sz;
- }
- skip_init_reply_post_free_queue:
-
- r = _base_send_ioc_init(ioc, sleep_flag);
- if (r)
- return r;
-
- /* initialize reply free host index */
- ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
- writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
-
- /* initialize reply post host index */
- list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
- writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT,
- &ioc->chip->ReplyPostHostIndex);
- if (!_base_is_controller_msix_enabled(ioc))
- goto skip_init_reply_post_host_index;
- }
-
- skip_init_reply_post_host_index:
-
- _base_unmask_interrupts(ioc);
-
- r = _base_event_notification(ioc, sleep_flag);
- if (r)
- return r;
-
- if (sleep_flag == CAN_SLEEP)
- _base_static_config_pages(ioc);
-
-
- if (ioc->is_driver_loading) {
- if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
- == 0x80) {
- hide_flag = (u8) (
- le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) &
- MFG_PAGE10_HIDE_SSDS_MASK);
- if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
- ioc->mfg_pg10_hide_flag = hide_flag;
- }
- ioc->wait_for_discovery_to_complete =
- _base_determine_wait_on_discovery(ioc);
- return r; /* scan_start and scan_finished support */
- }
- r = _base_send_port_enable(ioc, sleep_flag);
- if (r)
- return r;
-
- return r;
-}
-
-/**
- * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap)
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-void
-mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
-{
- struct pci_dev *pdev = ioc->pdev;
-
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- /* synchronizing freeing resource with pci_access_mutex lock */
- mutex_lock(&ioc->pci_access_mutex);
- if (ioc->chip_phys && ioc->chip) {
- _base_mask_interrupts(ioc);
- ioc->shost_recovery = 1;
- _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
- ioc->shost_recovery = 0;
- }
-
- _base_free_irq(ioc);
- _base_disable_msix(ioc);
-
- if (ioc->chip_phys && ioc->chip)
- iounmap(ioc->chip);
- ioc->chip_phys = 0;
-
- if (pci_is_enabled(pdev)) {
- pci_release_selected_regions(ioc->pdev, ioc->bars);
- pci_disable_pcie_error_reporting(pdev);
- pci_disable_device(pdev);
- }
- mutex_unlock(&ioc->pci_access_mutex);
- return;
-}
-
-/**
- * mpt2sas_base_attach - attach controller instance
- * @ioc: per adapter object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
-{
- int r, i;
- int cpu_id, last_cpu_id = 0;
-
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- /* setup cpu_msix_table */
- ioc->cpu_count = num_online_cpus();
- for_each_online_cpu(cpu_id)
- last_cpu_id = cpu_id;
- ioc->cpu_msix_table_sz = last_cpu_id + 1;
- ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
- ioc->reply_queue_count = 1;
- if (!ioc->cpu_msix_table) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
- "cpu_msix_table failed!!!\n", ioc->name));
- r = -ENOMEM;
- goto out_free_resources;
- }
-
- if (ioc->is_warpdrive) {
- ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
- sizeof(resource_size_t *), GFP_KERNEL);
- if (!ioc->reply_post_host_index) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation "
- "for cpu_msix_table failed!!!\n", ioc->name));
- r = -ENOMEM;
- goto out_free_resources;
- }
- }
-
- ioc->rdpq_array_enable_assigned = 0;
- ioc->dma_mask = 0;
- r = mpt2sas_base_map_resources(ioc);
- if (r)
- goto out_free_resources;
-
- if (ioc->is_warpdrive) {
- ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
- &ioc->chip->ReplyPostHostIndex;
-
- for (i = 1; i < ioc->cpu_msix_table_sz; i++)
- ioc->reply_post_host_index[i] =
- (resource_size_t __iomem *)
- ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
- * 4)));
- }
-
- pci_set_drvdata(ioc->pdev, ioc->shost);
- r = _base_get_ioc_facts(ioc, CAN_SLEEP);
- if (r)
- goto out_free_resources;
-
- r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
- if (r)
- goto out_free_resources;
-
- ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
- sizeof(struct mpt2sas_port_facts), GFP_KERNEL);
- if (!ioc->pfacts) {
- r = -ENOMEM;
- goto out_free_resources;
- }
-
- for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
- r = _base_get_port_facts(ioc, i, CAN_SLEEP);
- if (r)
- goto out_free_resources;
- }
-
- r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
- if (r)
- goto out_free_resources;
-
- init_waitqueue_head(&ioc->reset_wq);
- /* allocate memory pd handle bitmask list */
- ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
- if (ioc->facts.MaxDevHandle % 8)
- ioc->pd_handles_sz++;
- ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
- GFP_KERNEL);
- if (!ioc->pd_handles) {
- r = -ENOMEM;
- goto out_free_resources;
- }
- ioc->blocking_handles = kzalloc(ioc->pd_handles_sz,
- GFP_KERNEL);
- if (!ioc->blocking_handles) {
- r = -ENOMEM;
- goto out_free_resources;
- }
- ioc->fwfault_debug = mpt2sas_fwfault_debug;
-
- /* base internal command bits */
- mutex_init(&ioc->base_cmds.mutex);
- ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-
- /* port_enable command bits */
- ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
-
- /* transport internal command bits */
- ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
- mutex_init(&ioc->transport_cmds.mutex);
-
- /* scsih internal command bits */
- ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
- mutex_init(&ioc->scsih_cmds.mutex);
-
- /* task management internal command bits */
- ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- mutex_init(&ioc->tm_cmds.mutex);
-
- /* config page internal command bits */
- ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- mutex_init(&ioc->config_cmds.mutex);
-
- /* ctl module internal command bits */
- ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
- ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- mutex_init(&ioc->ctl_cmds.mutex);
-
- if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
- !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
- !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
- !ioc->ctl_cmds.sense) {
- r = -ENOMEM;
- goto out_free_resources;
- }
-
- if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
- !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
- !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) {
- r = -ENOMEM;
- goto out_free_resources;
- }
-
- for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
- ioc->event_masks[i] = -1;
-
- /* here we enable the events we care about */
- _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
- _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
- _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
- _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
- _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
- _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
- _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
- _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
- _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
- _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
- _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD);
- r = _base_make_ioc_operational(ioc, CAN_SLEEP);
- if (r)
- goto out_free_resources;
-
- ioc->non_operational_loop = 0;
-
- return 0;
-
- out_free_resources:
-
- ioc->remove_host = 1;
- mpt2sas_base_free_resources(ioc);
- _base_release_memory_pools(ioc);
- pci_set_drvdata(ioc->pdev, NULL);
- kfree(ioc->cpu_msix_table);
- if (ioc->is_warpdrive)
- kfree(ioc->reply_post_host_index);
- kfree(ioc->pd_handles);
- kfree(ioc->blocking_handles);
- kfree(ioc->tm_cmds.reply);
- kfree(ioc->transport_cmds.reply);
- kfree(ioc->scsih_cmds.reply);
- kfree(ioc->config_cmds.reply);
- kfree(ioc->base_cmds.reply);
- kfree(ioc->port_enable_cmds.reply);
- kfree(ioc->ctl_cmds.reply);
- kfree(ioc->ctl_cmds.sense);
- kfree(ioc->pfacts);
- ioc->ctl_cmds.reply = NULL;
- ioc->base_cmds.reply = NULL;
- ioc->tm_cmds.reply = NULL;
- ioc->scsih_cmds.reply = NULL;
- ioc->transport_cmds.reply = NULL;
- ioc->config_cmds.reply = NULL;
- ioc->pfacts = NULL;
- return r;
-}
-
-
-/**
- * mpt2sas_base_detach - remove controller instance
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-void
-mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
-{
-
- dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- mpt2sas_base_stop_watchdog(ioc);
- mpt2sas_base_free_resources(ioc);
- _base_release_memory_pools(ioc);
- pci_set_drvdata(ioc->pdev, NULL);
- kfree(ioc->cpu_msix_table);
- if (ioc->is_warpdrive)
- kfree(ioc->reply_post_host_index);
- kfree(ioc->pd_handles);
- kfree(ioc->blocking_handles);
- kfree(ioc->pfacts);
- kfree(ioc->ctl_cmds.reply);
- kfree(ioc->ctl_cmds.sense);
- kfree(ioc->base_cmds.reply);
- kfree(ioc->port_enable_cmds.reply);
- kfree(ioc->tm_cmds.reply);
- kfree(ioc->transport_cmds.reply);
- kfree(ioc->scsih_cmds.reply);
- kfree(ioc->config_cmds.reply);
-}
-
-/**
- * _base_reset_handler - reset callback handler (for base)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- *
- * Return nothing.
- */
-static void
-_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
- mpt2sas_scsih_reset_handler(ioc, reset_phase);
- mpt2sas_ctl_reset_handler(ioc, reset_phase);
- switch (reset_phase) {
- case MPT2_IOC_PRE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
- break;
- case MPT2_IOC_AFTER_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
- if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {
- ioc->transport_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid);
- complete(&ioc->transport_cmds.done);
- }
- if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
- ioc->base_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
- complete(&ioc->base_cmds.done);
- }
- if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
- ioc->port_enable_failed = 1;
- ioc->port_enable_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->port_enable_cmds.smid);
- if (ioc->is_driver_loading) {
- ioc->start_scan_failed =
- MPI2_IOCSTATUS_INTERNAL_ERROR;
- ioc->start_scan = 0;
- ioc->port_enable_cmds.status =
- MPT2_CMD_NOT_USED;
- } else
- complete(&ioc->port_enable_cmds.done);
-
- }
- if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
- ioc->config_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
- ioc->config_cmds.smid = USHRT_MAX;
- complete(&ioc->config_cmds.done);
- }
- break;
- case MPT2_IOC_DONE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
- break;
- }
-}
-
-/**
- * _wait_for_commands_to_complete - reset controller
- * @ioc: Pointer to MPT_ADAPTER structure
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * This function waiting(3s) for all pending commands to complete
- * prior to putting controller in reset.
- */
-static void
-_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
- u32 ioc_state;
- unsigned long flags;
- u16 i;
-
- ioc->pending_io_count = 0;
- if (sleep_flag != CAN_SLEEP)
- return;
-
- ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
- if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
- return;
-
- /* pending command count */
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- for (i = 0; i < ioc->scsiio_depth; i++)
- if (ioc->scsi_lookup[i].cb_idx != 0xFF)
- ioc->pending_io_count++;
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
- if (!ioc->pending_io_count)
- return;
-
- /* wait for pending commands to complete */
- wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
-}
-
-/**
- * mpt2sas_base_hard_reset_handler - reset controller
- * @ioc: Pointer to MPT_ADAPTER structure
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- * @type: FORCE_BIG_HAMMER or SOFT_RESET
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
- enum reset_type type)
-{
- int r;
- unsigned long flags;
-
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
-
- if (ioc->pci_error_recovery) {
- printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
- ioc->name, __func__);
- r = 0;
- goto out_unlocked;
- }
-
- if (mpt2sas_fwfault_debug)
- mpt2sas_halt_firmware(ioc);
-
- /* TODO - What we really should be doing is pulling
- * out all the code associated with NO_SLEEP; its never used.
- * That is legacy code from mpt fusion driver, ported over.
- * I will leave this BUG_ON here for now till its been resolved.
- */
- BUG_ON(sleep_flag == NO_SLEEP);
-
- /* wait for an active reset in progress to complete */
- if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
- do {
- ssleep(1);
- } while (ioc->shost_recovery == 1);
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
- __func__));
- return ioc->ioc_reset_in_progress_status;
- }
-
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- ioc->shost_recovery = 1;
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-
- _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
- _wait_for_commands_to_complete(ioc, sleep_flag);
- _base_mask_interrupts(ioc);
- r = _base_make_ioc_ready(ioc, sleep_flag, type);
- if (r)
- goto out;
- _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
-
- /* If this hard reset is called while port enable is active, then
- * there is no reason to call make_ioc_operational
- */
- if (ioc->is_driver_loading && ioc->port_enable_failed) {
- ioc->remove_host = 1;
- r = -EFAULT;
- goto out;
- }
-
- r = _base_get_ioc_facts(ioc, CAN_SLEEP);
- if (r)
- goto out;
-
- if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable)
- panic("%s: Issue occurred with flashing controller firmware."
- "Please reboot the system and ensure that the correct"
- " firmware version is running\n", ioc->name);
-
- r = _base_make_ioc_operational(ioc, sleep_flag);
- if (!r)
- _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
- out:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n",
- ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
-
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- ioc->ioc_reset_in_progress_status = r;
- ioc->shost_recovery = 0;
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
- mutex_unlock(&ioc->reset_in_progress_mutex);
-
- out_unlocked:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
- __func__));
- return r;
-}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
deleted file mode 100644
index 97ea360c6920..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- * This is the Fusion MPT base driver providing common API layer interface
- * for access to MPT (Message Passing Technology) firmware.
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_base.h
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#ifndef MPT2SAS_BASE_H_INCLUDED
-#define MPT2SAS_BASE_H_INCLUDED
-
-#include "mpi/mpi2_type.h"
-#include "mpi/mpi2.h"
-#include "mpi/mpi2_ioc.h"
-#include "mpi/mpi2_cnfg.h"
-#include "mpi/mpi2_init.h"
-#include "mpi/mpi2_raid.h"
-#include "mpi/mpi2_tool.h"
-#include "mpi/mpi2_sas.h"
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_transport_sas.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_eh.h>
-
-#include "mpt2sas_debug.h"
-
-/* driver versioning info */
-#define MPT2SAS_DRIVER_NAME "mpt2sas"
-#define MPT2SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
-#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "20.100.00.00"
-#define MPT2SAS_MAJOR_VERSION 20
-#define MPT2SAS_MINOR_VERSION 100
-#define MPT2SAS_BUILD_VERSION 00
-#define MPT2SAS_RELEASE_VERSION 00
-
-/*
- * Set MPT2SAS_SG_DEPTH value based on user input.
- */
-#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE
-#if CONFIG_SCSI_MPT2SAS_MAX_SGE < 16
-#define MPT2SAS_SG_DEPTH 16
-#elif CONFIG_SCSI_MPT2SAS_MAX_SGE > 128
-#define MPT2SAS_SG_DEPTH 128
-#else
-#define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE
-#endif
-#else
-#define MPT2SAS_SG_DEPTH 128 /* MAX_HW_SEGMENTS */
-#endif
-
-
-/*
- * Generic Defines
- */
-#define MPT2SAS_SATA_QUEUE_DEPTH 32
-#define MPT2SAS_SAS_QUEUE_DEPTH 254
-#define MPT2SAS_RAID_QUEUE_DEPTH 128
-
-#define MPT_NAME_LENGTH 32 /* generic length of strings */
-#define MPT_STRING_LENGTH 64
-
-#define MPT_MAX_CALLBACKS 16
-
-
-#define CAN_SLEEP 1
-#define NO_SLEEP 0
-
-#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
-
-#define MPI2_HIM_MASK 0xFFFFFFFF /* mask every bit*/
-
-#define MPT2SAS_INVALID_DEVICE_HANDLE 0xFFFF
-
-
-/*
- * reset phases
- */
-#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */
-#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */
-#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */
-
-/*
- * logging format
- */
-#define MPT2SAS_FMT "%s: "
-#define MPT2SAS_INFO_FMT KERN_INFO MPT2SAS_FMT
-#define MPT2SAS_NOTE_FMT KERN_NOTICE MPT2SAS_FMT
-#define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT
-#define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT
-
-/*
- * Dell HBA branding
- */
-#define MPT2SAS_DELL_BRANDING_SIZE 32
-
-#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA"
-#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter"
-#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated"
-#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular"
-#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded"
-#define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200"
-#define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS"
-
-/*
- * Dell HBA SSDIDs
- */
-#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C
-#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D
-#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E
-#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F
-#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20
-#define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21
-#define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22
-
-/*
- * Intel HBA branding
- */
-#define MPT2SAS_INTEL_RMS25JB080_BRANDING \
- "Intel(R) Integrated RAID Module RMS25JB080"
-#define MPT2SAS_INTEL_RMS25JB040_BRANDING \
- "Intel(R) Integrated RAID Module RMS25JB040"
-#define MPT2SAS_INTEL_RMS25KB080_BRANDING \
- "Intel(R) Integrated RAID Module RMS25KB080"
-#define MPT2SAS_INTEL_RMS25KB040_BRANDING \
- "Intel(R) Integrated RAID Module RMS25KB040"
-#define MPT2SAS_INTEL_RMS25LB040_BRANDING \
- "Intel(R) Integrated RAID Module RMS25LB040"
-#define MPT2SAS_INTEL_RMS25LB080_BRANDING \
- "Intel(R) Integrated RAID Module RMS25LB080"
-#define MPT2SAS_INTEL_RMS2LL080_BRANDING \
- "Intel Integrated RAID Module RMS2LL080"
-#define MPT2SAS_INTEL_RMS2LL040_BRANDING \
- "Intel Integrated RAID Module RMS2LL040"
-#define MPT2SAS_INTEL_RS25GB008_BRANDING \
- "Intel(R) RAID Controller RS25GB008"
-#define MPT2SAS_INTEL_SSD910_BRANDING \
- "Intel(R) SSD 910 Series"
-/*
- * Intel HBA SSDIDs
- */
-#define MPT2SAS_INTEL_RMS25JB080_SSDID 0x3516
-#define MPT2SAS_INTEL_RMS25JB040_SSDID 0x3517
-#define MPT2SAS_INTEL_RMS25KB080_SSDID 0x3518
-#define MPT2SAS_INTEL_RMS25KB040_SSDID 0x3519
-#define MPT2SAS_INTEL_RMS25LB040_SSDID 0x351A
-#define MPT2SAS_INTEL_RMS25LB080_SSDID 0x351B
-#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E
-#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F
-#define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000
-#define MPT2SAS_INTEL_SSD910_SSDID 0x3700
-
-/*
- * HP HBA branding
- */
-#define MPT2SAS_HP_3PAR_SSVID 0x1590
-#define MPT2SAS_HP_2_4_INTERNAL_BRANDING "HP H220 Host Bus Adapter"
-#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING "HP H221 Host Bus Adapter"
-#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING "HP H222 Host Bus Adapter"
-#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING "HP H220i Host Bus Adapter"
-#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING "HP H210i Host Bus Adapter"
-
-/*
- * HO HBA SSDIDs
- */
-#define MPT2SAS_HP_2_4_INTERNAL_SSDID 0x0041
-#define MPT2SAS_HP_2_4_EXTERNAL_SSDID 0x0042
-#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID 0x0043
-#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044
-#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046
-
-/*
- * WarpDrive Specific Log codes
- */
-
-#define MPT2_WARPDRIVE_LOGENTRY (0x8002)
-#define MPT2_WARPDRIVE_LC_SSDT (0x41)
-#define MPT2_WARPDRIVE_LC_SSDLW (0x43)
-#define MPT2_WARPDRIVE_LC_SSDLF (0x44)
-#define MPT2_WARPDRIVE_LC_BRMF (0x4D)
-
-/*
- * per target private data
- */
-#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01
-#define MPT_TARGET_FLAGS_VOLUME 0x02
-#define MPT_TARGET_FLAGS_DELETED 0x04
-
-/**
- * struct MPT2SAS_TARGET - starget private hostdata
- * @starget: starget object
- * @sas_address: target sas address
- * @raid_device: raid_device pointer to access volume data
- * @handle: device handle
- * @num_luns: number luns
- * @flags: MPT_TARGET_FLAGS_XXX flags
- * @deleted: target flaged for deletion
- * @tm_busy: target is busy with TM request.
- * @sdev: The sas_device associated with this target
- */
-struct MPT2SAS_TARGET {
- struct scsi_target *starget;
- u64 sas_address;
- struct _raid_device *raid_device;
- u16 handle;
- int num_luns;
- u32 flags;
- u8 deleted;
- u8 tm_busy;
- struct _sas_device *sdev;
-};
-
-
-/*
- * per device private data
- */
-#define MPT_DEVICE_FLAGS_INIT 0x01
-#define MPT_DEVICE_TLR_ON 0x02
-
-/**
- * struct MPT2SAS_DEVICE - sdev private hostdata
- * @sas_target: starget private hostdata
- * @lun: lun number
- * @flags: MPT_DEVICE_XXX flags
- * @configured_lun: lun is configured
- * @block: device is in SDEV_BLOCK state
- * @tlr_snoop_check: flag used in determining whether to disable TLR
- */
-
-/* OEM Identifiers */
-#define MFG10_OEM_ID_INVALID (0x00000000)
-#define MFG10_OEM_ID_DELL (0x00000001)
-#define MFG10_OEM_ID_FSC (0x00000002)
-#define MFG10_OEM_ID_SUN (0x00000003)
-#define MFG10_OEM_ID_IBM (0x00000004)
-
-/* GENERIC Flags 0*/
-#define MFG10_GF0_OCE_DISABLED (0x00000001)
-#define MFG10_GF0_R1E_DRIVE_COUNT (0x00000002)
-#define MFG10_GF0_R10_DISPLAY (0x00000004)
-#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008)
-#define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010)
-
-/* OEM Specific Flags will come from OEM specific header files */
-typedef struct _MPI2_CONFIG_PAGE_MAN_10 {
- MPI2_CONFIG_PAGE_HEADER Header; /* 00h */
- U8 OEMIdentifier; /* 04h */
- U8 Reserved1; /* 05h */
- U16 Reserved2; /* 08h */
- U32 Reserved3; /* 0Ch */
- U32 GenericFlags0; /* 10h */
- U32 GenericFlags1; /* 14h */
- U32 Reserved4; /* 18h */
- U32 OEMSpecificFlags0; /* 1Ch */
- U32 OEMSpecificFlags1; /* 20h */
- U32 Reserved5[18]; /* 24h-60h*/
-} MPI2_CONFIG_PAGE_MAN_10,
- MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10,
- Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t;
-
-#define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003)
-#define MFG_PAGE10_HIDE_ALL_DISKS (0x00)
-#define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01)
-#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02)
-
-
-struct MPT2SAS_DEVICE {
- struct MPT2SAS_TARGET *sas_target;
- unsigned int lun;
- u32 flags;
- u8 configured_lun;
- u8 block;
- u8 tlr_snoop_check;
-};
-
-#define MPT2_CMD_NOT_USED 0x8000 /* free */
-#define MPT2_CMD_COMPLETE 0x0001 /* completed */
-#define MPT2_CMD_PENDING 0x0002 /* pending */
-#define MPT2_CMD_REPLY_VALID 0x0004 /* reply is valid */
-#define MPT2_CMD_RESET 0x0008 /* host reset dropped the command */
-
-/**
- * struct _internal_cmd - internal commands struct
- * @mutex: mutex
- * @done: completion
- * @reply: reply message pointer
- * @sense: sense data
- * @status: MPT2_CMD_XXX status
- * @smid: system message id
- */
-struct _internal_cmd {
- struct mutex mutex;
- struct completion done;
- void *reply;
- void *sense;
- u16 status;
- u16 smid;
-};
-
-
-/**
- * struct _sas_device - attached device information
- * @list: sas device list
- * @starget: starget object
- * @sas_address: device sas address
- * @device_name: retrieved from the SAS IDENTIFY frame.
- * @handle: device handle
- * @sas_address_parent: sas address of parent expander or sas host
- * @enclosure_handle: enclosure handle
- * @enclosure_logical_id: enclosure logical identifier
- * @volume_handle: volume handle (valid when hidden raid member)
- * @volume_wwid: volume unique identifier
- * @device_info: bitfield provides detailed info about the device
- * @id: target id
- * @channel: target channel
- * @slot: number number
- * @phy: phy identifier provided in sas device page 0
- * @responding: used in _scsih_sas_device_mark_responding
- * @pfa_led_on: flag for PFA LED status
- */
-struct _sas_device {
- struct list_head list;
- struct scsi_target *starget;
- u64 sas_address;
- u64 device_name;
- u16 handle;
- u64 sas_address_parent;
- u16 enclosure_handle;
- u64 enclosure_logical_id;
- u16 volume_handle;
- u64 volume_wwid;
- u32 device_info;
- int id;
- int channel;
- u16 slot;
- u8 phy;
- u8 responding;
- u8 pfa_led_on;
- struct kref refcount;
-};
-
-static inline void sas_device_get(struct _sas_device *s)
-{
- kref_get(&s->refcount);
-}
-
-static inline void sas_device_free(struct kref *r)
-{
- kfree(container_of(r, struct _sas_device, refcount));
-}
-
-static inline void sas_device_put(struct _sas_device *s)
-{
- kref_put(&s->refcount, sas_device_free);
-}
-
-/**
- * struct _raid_device - raid volume link list
- * @list: sas device list
- * @starget: starget object
- * @sdev: scsi device struct (volumes are single lun)
- * @wwid: unique identifier for the volume
- * @handle: device handle
- * @block_size: Block size of the volume
- * @id: target id
- * @channel: target channel
- * @volume_type: the raid level
- * @device_info: bitfield provides detailed info about the hidden components
- * @num_pds: number of hidden raid components
- * @responding: used in _scsih_raid_device_mark_responding
- * @percent_complete: resync percent complete
- * @direct_io_enabled: Whether direct io to PDs are allowed or not
- * @stripe_exponent: X where 2powX is the stripe sz in blocks
- * @block_exponent: X where 2powX is the block sz in bytes
- * @max_lba: Maximum number of LBA in the volume
- * @stripe_sz: Stripe Size of the volume
- * @device_info: Device info of the volume member disk
- * @pd_handle: Array of handles of the physical drives for direct I/O in le16
- */
-#define MPT_MAX_WARPDRIVE_PDS 8
-struct _raid_device {
- struct list_head list;
- struct scsi_target *starget;
- struct scsi_device *sdev;
- u64 wwid;
- u16 handle;
- u16 block_sz;
- int id;
- int channel;
- u8 volume_type;
- u8 num_pds;
- u8 responding;
- u8 percent_complete;
- u8 direct_io_enabled;
- u8 stripe_exponent;
- u8 block_exponent;
- u64 max_lba;
- u32 stripe_sz;
- u32 device_info;
- u16 pd_handle[MPT_MAX_WARPDRIVE_PDS];
-};
-
-/**
- * struct _boot_device - boot device info
- * @is_raid: flag to indicate whether this is volume
- * @device: holds pointer for either struct _sas_device or
- * struct _raid_device
- */
-struct _boot_device {
- u8 is_raid;
- void *device;
-};
-
-/**
- * struct _sas_port - wide/narrow sas port information
- * @port_list: list of ports belonging to expander
- * @num_phys: number of phys belonging to this port
- * @remote_identify: attached device identification
- * @rphy: sas transport rphy object
- * @port: sas transport wide/narrow port object
- * @phy_list: _sas_phy list objects belonging to this port
- */
-struct _sas_port {
- struct list_head port_list;
- u8 num_phys;
- struct sas_identify remote_identify;
- struct sas_rphy *rphy;
- struct sas_port *port;
- struct list_head phy_list;
-};
-
-/**
- * struct _sas_phy - phy information
- * @port_siblings: list of phys belonging to a port
- * @identify: phy identification
- * @remote_identify: attached device identification
- * @phy: sas transport phy object
- * @phy_id: unique phy id
- * @handle: device handle for this phy
- * @attached_handle: device handle for attached device
- * @phy_belongs_to_port: port has been created for this phy
- */
-struct _sas_phy {
- struct list_head port_siblings;
- struct sas_identify identify;
- struct sas_identify remote_identify;
- struct sas_phy *phy;
- u8 phy_id;
- u16 handle;
- u16 attached_handle;
- u8 phy_belongs_to_port;
-};
-
-/**
- * struct _sas_node - sas_host/expander information
- * @list: list of expanders
- * @parent_dev: parent device class
- * @num_phys: number phys belonging to this sas_host/expander
- * @sas_address: sas address of this sas_host/expander
- * @handle: handle for this sas_host/expander
- * @sas_address_parent: sas address of parent expander or sas host
- * @enclosure_handle: handle for this a member of an enclosure
- * @device_info: bitwise defining capabilities of this sas_host/expander
- * @responding: used in _scsih_expander_device_mark_responding
- * @phy: a list of phys that make up this sas_host/expander
- * @sas_port_list: list of ports attached to this sas_host/expander
- */
-struct _sas_node {
- struct list_head list;
- struct device *parent_dev;
- u8 num_phys;
- u64 sas_address;
- u16 handle;
- u64 sas_address_parent;
- u16 enclosure_handle;
- u64 enclosure_logical_id;
- u8 responding;
- struct _sas_phy *phy;
- struct list_head sas_port_list;
-};
-
-/**
- * enum reset_type - reset state
- * @FORCE_BIG_HAMMER: issue diagnostic reset
- * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
- */
-enum reset_type {
- FORCE_BIG_HAMMER,
- SOFT_RESET,
-};
-
-/**
- * struct chain_tracker - firmware chain tracker
- * @chain_buffer: chain buffer
- * @chain_buffer_dma: physical address
- * @tracker_list: list of free request (ioc->free_chain_list)
- */
-struct chain_tracker {
- void *chain_buffer;
- dma_addr_t chain_buffer_dma;
- struct list_head tracker_list;
-};
-
-/**
- * struct scsiio_tracker - scsi mf request tracker
- * @smid: system message id
- * @scmd: scsi request pointer
- * @cb_idx: callback index
- * @direct_io: To indicate whether I/O is direct (WARPDRIVE)
- * @chain_list: list of chains associated to this IO
- * @tracker_list: list of free request (ioc->free_list)
- */
-struct scsiio_tracker {
- u16 smid;
- struct scsi_cmnd *scmd;
- u8 cb_idx;
- u8 direct_io;
- struct list_head chain_list;
- struct list_head tracker_list;
-};
-
-/**
- * struct request_tracker - firmware request tracker
- * @smid: system message id
- * @cb_idx: callback index
- * @tracker_list: list of free request (ioc->free_list)
- */
-struct request_tracker {
- u16 smid;
- u8 cb_idx;
- struct list_head tracker_list;
-};
-
-/**
- * struct _tr_list - target reset list
- * @handle: device handle
- * @state: state machine
- */
-struct _tr_list {
- struct list_head list;
- u16 handle;
- u16 state;
-};
-
-typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
-
-/**
- * struct adapter_reply_queue - the reply queue struct
- * @ioc: per adapter object
- * @msix_index: msix index into vector table
- * @vector: irq vector
- * @reply_post_host_index: head index in the pool where FW completes IO
- * @reply_post_free: reply post base virt address
- * @name: the name registered to request_irq()
- * @busy: isr is actively processing replies on another cpu
- * @list: this list
-*/
-struct adapter_reply_queue {
- struct MPT2SAS_ADAPTER *ioc;
- u8 msix_index;
- unsigned int vector;
- u32 reply_post_host_index;
- Mpi2ReplyDescriptorsUnion_t *reply_post_free;
- char name[MPT_NAME_LENGTH];
- atomic_t busy;
- cpumask_var_t affinity_hint;
- struct list_head list;
-};
-
-/* IOC Facts and Port Facts converted from little endian to cpu */
-union mpi2_version_union {
- MPI2_VERSION_STRUCT Struct;
- u32 Word;
-};
-
-struct mpt2sas_facts {
- u16 MsgVersion;
- u16 HeaderVersion;
- u8 IOCNumber;
- u8 VP_ID;
- u8 VF_ID;
- u16 IOCExceptions;
- u16 IOCStatus;
- u32 IOCLogInfo;
- u8 MaxChainDepth;
- u8 WhoInit;
- u8 NumberOfPorts;
- u8 MaxMSIxVectors;
- u16 RequestCredit;
- u16 ProductID;
- u32 IOCCapabilities;
- union mpi2_version_union FWVersion;
- u16 IOCRequestFrameSize;
- u16 Reserved3;
- u16 MaxInitiators;
- u16 MaxTargets;
- u16 MaxSasExpanders;
- u16 MaxEnclosures;
- u16 ProtocolFlags;
- u16 HighPriorityCredit;
- u16 MaxReplyDescriptorPostQueueDepth;
- u8 ReplyFrameSize;
- u8 MaxVolumes;
- u16 MaxDevHandle;
- u16 MaxPersistentEntries;
- u16 MinDevHandle;
-};
-
-struct mpt2sas_port_facts {
- u8 PortNumber;
- u8 VP_ID;
- u8 VF_ID;
- u8 PortType;
- u16 MaxPostedCmdBuffers;
-};
-
-struct reply_post_struct {
- Mpi2ReplyDescriptorsUnion_t *reply_post_free;
- dma_addr_t reply_post_free_dma;
-};
-
-/**
- * enum mutex_type - task management mutex type
- * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
- * @TM_MUTEX_ON: mutex is required
- */
-enum mutex_type {
- TM_MUTEX_OFF = 0,
- TM_MUTEX_ON = 1,
-};
-
-typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc);
-/**
- * struct MPT2SAS_ADAPTER - per adapter struct
- * @list: ioc_list
- * @shost: shost object
- * @id: unique adapter id
- * @cpu_count: number online cpus
- * @name: generic ioc string
- * @tmp_string: tmp string used for logging
- * @pdev: pci pdev object
- * @chip: memory mapped register space
- * @chip_phys: physical addrss prior to mapping
- * @logging_level: see mpt2sas_debug.h
- * @fwfault_debug: debuging FW timeouts
- * @ir_firmware: IR firmware present
- * @bars: bitmask of BAR's that must be configured
- * @mask_interrupts: ignore interrupt
- * @dma_mask: used to set the consistent dma mask
- * @fault_reset_work_q_name: fw fault work queue
- * @fault_reset_work_q: ""
- * @fault_reset_work: ""
- * @firmware_event_name: fw event work queue
- * @firmware_event_thread: ""
- * @fw_events_off: flag to turn off fw event handling
- * @fw_event_lock:
- * @fw_event_list: list of fw events
- * @aen_event_read_flag: event log was read
- * @broadcast_aen_busy: broadcast aen waiting to be serviced
- * @shost_recovery: host reset in progress
- * @ioc_reset_in_progress_lock:
- * @ioc_link_reset_in_progress: phy/hard reset in progress
- * @ignore_loginfos: ignore loginfos during task management
- * @remove_host: flag for when driver unloads, to avoid sending dev resets
- * @pci_error_recovery: flag to prevent ioc access until slot reset completes
- * @wait_for_discovery_to_complete: flag set at driver load time when
- * waiting on reporting devices
- * @is_driver_loading: flag set at driver load time
- * @port_enable_failed: flag set when port enable has failed
- * @start_scan: flag set from scan_start callback, cleared from _mpt2sas_fw_work
- * @start_scan_failed: means port enable failed, return's the ioc_status
- * @msix_enable: flag indicating msix is enabled
- * @msix_vector_count: number msix vectors
- * @cpu_msix_table: table for mapping cpus to msix index
- * @cpu_msix_table_sz: table size
- * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
- * @scsi_io_cb_idx: shost generated commands
- * @tm_cb_idx: task management commands
- * @scsih_cb_idx: scsih internal commands
- * @transport_cb_idx: transport internal commands
- * @ctl_cb_idx: clt internal commands
- * @base_cb_idx: base internal commands
- * @config_cb_idx: base internal commands
- * @tm_tr_cb_idx : device removal target reset handshake
- * @tm_tr_volume_cb_idx : volume removal target reset
- * @base_cmds:
- * @transport_cmds:
- * @scsih_cmds:
- * @tm_cmds:
- * @ctl_cmds:
- * @config_cmds:
- * @base_add_sg_single: handler for either 32/64 bit sgl's
- * @event_type: bits indicating which events to log
- * @event_context: unique id for each logged event
- * @event_log: event log pointer
- * @event_masks: events that are masked
- * @facts: static facts data
- * @pfacts: static port facts data
- * @manu_pg0: static manufacturing page 0
- * @manu_pg10: static manufacturing page 10
- * @bios_pg2: static bios page 2
- * @bios_pg3: static bios page 3
- * @ioc_pg8: static ioc page 8
- * @iounit_pg0: static iounit page 0
- * @iounit_pg1: static iounit page 1
- * @iounit_pg8: static iounit page 8
- * @sas_hba: sas host object
- * @sas_expander_list: expander object list
- * @sas_node_lock:
- * @sas_device_list: sas device object list
- * @sas_device_init_list: sas device object list (used only at init time)
- * @sas_device_lock:
- * @io_missing_delay: time for IO completed by fw when PDR enabled
- * @device_missing_delay: time for device missing by fw when PDR enabled
- * @sas_id : used for setting volume target IDs
- * @blocking_handles: bitmask used to identify which devices need blocking
- * @pd_handles : bitmask for PD handles
- * @pd_handles_sz : size of pd_handle bitmask
- * @config_page_sz: config page size
- * @config_page: reserve memory for config page payload
- * @config_page_dma:
- * @hba_queue_depth: hba request queue depth
- * @sge_size: sg element size for either 32/64 bit
- * @scsiio_depth: SCSI_IO queue depth
- * @request_sz: per request frame size
- * @request: pool of request frames
- * @request_dma:
- * @request_dma_sz:
- * @scsi_lookup: firmware request tracker list
- * @scsi_lookup_lock:
- * @free_list: free list of request
- * @chain: pool of chains
- * @pending_io_count:
- * @reset_wq:
- * @chain_dma:
- * @max_sges_in_main_message: number sg elements in main message
- * @max_sges_in_chain_message: number sg elements per chain
- * @chains_needed_per_io: max chains per io
- * @chain_offset_value_for_main_message: location 1st sg in main
- * @chain_depth: total chains allocated
- * @hi_priority_smid:
- * @hi_priority:
- * @hi_priority_dma:
- * @hi_priority_depth:
- * @hpr_lookup:
- * @hpr_free_list:
- * @internal_smid:
- * @internal:
- * @internal_dma:
- * @internal_depth:
- * @internal_lookup:
- * @internal_free_list:
- * @sense: pool of sense
- * @sense_dma:
- * @sense_dma_pool:
- * @reply_depth: hba reply queue depth:
- * @reply_sz: per reply frame size:
- * @reply: pool of replys:
- * @reply_dma:
- * @reply_dma_pool:
- * @reply_free_queue_depth: reply free depth
- * @reply_free: pool for reply free queue (32 bit addr)
- * @reply_free_dma:
- * @reply_free_dma_pool:
- * @reply_free_host_index: tail index in pool to insert free replys
- * @reply_post_queue_depth: reply post queue depth
- * @reply_post_struct: struct for reply_post_free physical & virt address
- * @rdpq_array_capable: FW supports multiple reply queue addresses in ioc_init
- * @rdpq_array_enable: rdpq_array support is enabled in the driver
- * @rdpq_array_enable_assigned: this ensures that rdpq_array_enable flag
- * is assigned only ones
- * @reply_queue_count: number of reply queue's
- * @reply_queue_list: link list contaning the reply queue info
- * @reply_post_host_index: head index in the pool where FW completes IO
- * @delayed_tr_list: target reset link list
- * @delayed_tr_volume_list: volume target reset link list
- * @@temp_sensors_count: flag to carry the number of temperature sensors
- * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and
- * pci resource handling. PCI resource freeing will lead to free
- * vital hardware/memory resource, which might be in use by cli/sysfs
- * path functions resulting in Null pointer reference followed by kernel
- * crash. To avoid the above race condition we use mutex syncrhonization
- * which ensures the syncrhonization between cli/sysfs_show path
- */
-struct MPT2SAS_ADAPTER {
- struct list_head list;
- struct Scsi_Host *shost;
- u8 id;
- int cpu_count;
- char name[MPT_NAME_LENGTH];
- char tmp_string[MPT_STRING_LENGTH];
- struct pci_dev *pdev;
- Mpi2SystemInterfaceRegs_t __iomem *chip;
- resource_size_t chip_phys;
- int logging_level;
- int fwfault_debug;
- u8 ir_firmware;
- int bars;
- u8 mask_interrupts;
- int dma_mask;
-
- /* fw fault handler */
- char fault_reset_work_q_name[20];
- struct workqueue_struct *fault_reset_work_q;
- struct delayed_work fault_reset_work;
-
- /* fw event handler */
- char firmware_event_name[20];
- struct workqueue_struct *firmware_event_thread;
- spinlock_t fw_event_lock;
- struct list_head fw_event_list;
-
- /* misc flags */
- int aen_event_read_flag;
- u8 broadcast_aen_busy;
- u16 broadcast_aen_pending;
- u8 shost_recovery;
-
- struct mutex reset_in_progress_mutex;
- spinlock_t ioc_reset_in_progress_lock;
- u8 ioc_link_reset_in_progress;
- u8 ioc_reset_in_progress_status;
-
- u8 ignore_loginfos;
- u8 remove_host;
- u8 pci_error_recovery;
- u8 wait_for_discovery_to_complete;
- struct completion port_enable_done;
- u8 is_driver_loading;
- u8 port_enable_failed;
-
- u8 start_scan;
- u16 start_scan_failed;
-
- u8 msix_enable;
- u16 msix_vector_count;
- u8 *cpu_msix_table;
- resource_size_t __iomem **reply_post_host_index;
- u16 cpu_msix_table_sz;
- u32 ioc_reset_count;
- MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
- u32 non_operational_loop;
-
- /* internal commands, callback index */
- u8 scsi_io_cb_idx;
- u8 tm_cb_idx;
- u8 transport_cb_idx;
- u8 scsih_cb_idx;
- u8 ctl_cb_idx;
- u8 base_cb_idx;
- u8 port_enable_cb_idx;
- u8 config_cb_idx;
- u8 tm_tr_cb_idx;
- u8 tm_tr_volume_cb_idx;
- u8 tm_sas_control_cb_idx;
- struct _internal_cmd base_cmds;
- struct _internal_cmd port_enable_cmds;
- struct _internal_cmd transport_cmds;
- struct _internal_cmd scsih_cmds;
- struct _internal_cmd tm_cmds;
- struct _internal_cmd ctl_cmds;
- struct _internal_cmd config_cmds;
-
- MPT_ADD_SGE base_add_sg_single;
-
- /* event log */
- u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
- u32 event_context;
- void *event_log;
- u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
-
- /* static config pages */
- struct mpt2sas_facts facts;
- struct mpt2sas_port_facts *pfacts;
- Mpi2ManufacturingPage0_t manu_pg0;
- Mpi2BiosPage2_t bios_pg2;
- Mpi2BiosPage3_t bios_pg3;
- Mpi2IOCPage8_t ioc_pg8;
- Mpi2IOUnitPage0_t iounit_pg0;
- Mpi2IOUnitPage1_t iounit_pg1;
- Mpi2IOUnitPage8_t iounit_pg8;
-
- struct _boot_device req_boot_device;
- struct _boot_device req_alt_boot_device;
- struct _boot_device current_boot_device;
-
- /* sas hba, expander, and device list */
- struct _sas_node sas_hba;
- struct list_head sas_expander_list;
- spinlock_t sas_node_lock;
- struct list_head sas_device_list;
- struct list_head sas_device_init_list;
- spinlock_t sas_device_lock;
- struct list_head raid_device_list;
- spinlock_t raid_device_lock;
- u8 io_missing_delay;
- u16 device_missing_delay;
- int sas_id;
- void *blocking_handles;
- void *pd_handles;
- u16 pd_handles_sz;
-
- /* config page */
- u16 config_page_sz;
- void *config_page;
- dma_addr_t config_page_dma;
-
- /* scsiio request */
- u16 hba_queue_depth;
- u16 sge_size;
- u16 scsiio_depth;
- u16 request_sz;
- u8 *request;
- dma_addr_t request_dma;
- u32 request_dma_sz;
- struct scsiio_tracker *scsi_lookup;
- ulong scsi_lookup_pages;
- spinlock_t scsi_lookup_lock;
- struct list_head free_list;
- int pending_io_count;
- wait_queue_head_t reset_wq;
-
- /* chain */
- struct chain_tracker *chain_lookup;
- struct list_head free_chain_list;
- struct dma_pool *chain_dma_pool;
- ulong chain_pages;
- u16 max_sges_in_main_message;
- u16 max_sges_in_chain_message;
- u16 chains_needed_per_io;
- u16 chain_offset_value_for_main_message;
- u32 chain_depth;
-
- /* hi-priority queue */
- u16 hi_priority_smid;
- u8 *hi_priority;
- dma_addr_t hi_priority_dma;
- u16 hi_priority_depth;
- struct request_tracker *hpr_lookup;
- struct list_head hpr_free_list;
-
- /* internal queue */
- u16 internal_smid;
- u8 *internal;
- dma_addr_t internal_dma;
- u16 internal_depth;
- struct request_tracker *internal_lookup;
- struct list_head internal_free_list;
-
- /* sense */
- u8 *sense;
- dma_addr_t sense_dma;
- struct dma_pool *sense_dma_pool;
-
- /* reply */
- u16 reply_sz;
- u8 *reply;
- dma_addr_t reply_dma;
- u32 reply_dma_max_address;
- u32 reply_dma_min_address;
- struct dma_pool *reply_dma_pool;
-
- /* reply free queue */
- u16 reply_free_queue_depth;
- __le32 *reply_free;
- dma_addr_t reply_free_dma;
- struct dma_pool *reply_free_dma_pool;
- u32 reply_free_host_index;
-
- /* reply post queue */
- u16 reply_post_queue_depth;
- struct reply_post_struct *reply_post;
- u8 rdpq_array_capable;
- u8 rdpq_array_enable;
- u8 rdpq_array_enable_assigned;
- struct dma_pool *reply_post_free_dma_pool;
- u8 reply_queue_count;
- struct list_head reply_queue_list;
-
- struct list_head delayed_tr_list;
- struct list_head delayed_tr_volume_list;
- u8 temp_sensors_count;
-
- /* diag buffer support */
- u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
- u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
- dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
- u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
- u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
- Mpi2ManufacturingPage10_t manu_pg10;
- u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
- u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
- u32 ring_buffer_offset;
- u32 ring_buffer_sz;
- u8 is_warpdrive;
- u8 hide_ir_msg;
- u8 mfg_pg10_hide_flag;
- u8 hide_drives;
-
- struct mutex pci_access_mutex;
-};
-
-typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply);
-
-
-/* base shared API */
-extern struct list_head mpt2sas_ioc_list;
-/* spinlock on list operations over IOCs
- * Case: when multiple warpdrive cards(IOCs) are in use
- * Each IOC will added to the ioc list stucture on initialization.
- * Watchdog threads run at regular intervals to check IOC for any
- * fault conditions which will trigger the dead_ioc thread to
- * deallocate pci resource, resulting deleting the IOC netry from list,
- * this deletion need to protected by spinlock to enusre that
- * ioc removal is syncrhonized, if not synchronized it might lead to
- * list_del corruption as the ioc list is traversed in cli path
- */
-extern spinlock_t gioc_lock;
-void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc);
-
-int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
-int mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc);
-int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
- enum reset_type type);
-
-void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr);
-__le32 mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc,
- u16 smid);
-void mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc);
-
-/* hi-priority queue */
-u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
-u16 mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
- struct scsi_cmnd *scmd);
-
-u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
-void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- u16 handle);
-void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- u16 io_index);
-void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-void mpt2sas_base_initialize_callback_handler(void);
-u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func);
-void mpt2sas_base_release_callback_handler(u8 cb_idx);
-
-u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply);
-u8 mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- u8 msix_index, u32 reply);
-void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr);
-
-u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked);
-
-void mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code);
-int mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
- Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t
- *mpi_request);
-int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
- Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
-void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type);
-
-void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
-
-void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
- u16 device_missing_delay, u8 io_missing_delay);
-
-int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
-
-/* scsih shared API */
-void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
- u32 reply);
-int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- uint channel, uint id, uint lun, u8 type, u16 smid_task,
- ulong timeout, enum mutex_type m_type);
-void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
-void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
-void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-void mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address);
-struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
- u16 handle);
-struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
- *ioc, u64 sas_address);
-struct _sas_device *mpt2sas_get_sdev_by_addr(
- struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-struct _sas_device *__mpt2sas_get_sdev_by_addr(
- struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-
-void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
-
-/* config shared API */
-u8 mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply);
-int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys);
-int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
-int mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page);
-int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2BiosPage2_t *config_page);
-int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2BiosPage3_t *config_page);
-int mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2IOUnitPage0_t *config_page);
-int mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz);
-int mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2IOUnitPage1_t *config_page);
-int mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2IOUnitPage1_t *config_page);
-int mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page);
-int mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz);
-int mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz);
-int mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz);
-int mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2IOCPage8_t *config_page);
-int mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, u16 handle);
-int mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number);
-int mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number);
-int mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 *num_pds);
-int mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, u32 handle, u16 sz);
-int mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
- u32 form_specific);
-int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
- u16 *volume_handle);
-int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
- u64 *wwid);
-/* ctl shared API */
-extern struct device_attribute *mpt2sas_host_attrs[];
-extern struct device_attribute *mpt2sas_dev_attrs[];
-void mpt2sas_ctl_init(void);
-void mpt2sas_ctl_exit(void);
-u8 mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply);
-void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
-void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
- u32 reply);
-void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventNotificationReply_t *mpi_reply);
-
-void mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc,
- u8 bits_to_regsiter);
-
-/* transport shared API */
-u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply);
-struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc,
- u16 handle, u64 sas_address);
-void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
- u64 sas_address_parent);
-int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
- *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
-int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
- *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev);
-void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
-extern struct sas_function_template mpt2sas_transport_functions;
-extern struct scsi_transport_template *mpt2sas_transport_template;
-extern int scsi_internal_device_block(struct scsi_device *sdev);
-extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc,
- u8 msix_index, u32 reply);
-extern int scsi_internal_device_unblock(struct scsi_device *sdev,
- enum scsi_device_state new_state);
-
-#endif /* MPT2SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
deleted file mode 100644
index c43815b1a485..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ /dev/null
@@ -1,1527 +0,0 @@
-/*
- * This module provides common API for accessing firmware configuration pages
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/blkdev.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "mpt2sas_base.h"
-
-/* local definitions */
-
-/* Timeout for config page request (in seconds) */
-#define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15
-
-/* Common sgl flags for READING a config page. */
-#define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
- | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
-
-/* Common sgl flags for WRITING a config page. */
-#define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
- | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
- << MPI2_SGE_FLAGS_SHIFT)
-
-/**
- * struct config_request - obtain dma memory via routine
- * @sz: size
- * @page: virt pointer
- * @page_dma: phys pointer
- *
- */
-struct config_request{
- u16 sz;
- void *page;
- dma_addr_t page_dma;
-};
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _config_display_some_debug - debug routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @calling_function_name: string pass from calling function
- * @mpi_reply: reply message frame
- * Context: none.
- *
- * Function for displaying debug info helpful when debugging issues
- * in this module.
- */
-static void
-_config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
-{
- Mpi2ConfigRequest_t *mpi_request;
- char *desc = NULL;
-
- if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
- return;
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
- case MPI2_CONFIG_PAGETYPE_IO_UNIT:
- desc = "io_unit";
- break;
- case MPI2_CONFIG_PAGETYPE_IOC:
- desc = "ioc";
- break;
- case MPI2_CONFIG_PAGETYPE_BIOS:
- desc = "bios";
- break;
- case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
- desc = "raid_volume";
- break;
- case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
- desc = "manufaucturing";
- break;
- case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
- desc = "physdisk";
- break;
- case MPI2_CONFIG_PAGETYPE_EXTENDED:
- switch (mpi_request->ExtPageType) {
- case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
- desc = "sas_io_unit";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
- desc = "sas_expander";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
- desc = "sas_device";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
- desc = "sas_phy";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_LOG:
- desc = "log";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
- desc = "enclosure";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
- desc = "raid_config";
- break;
- case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
- desc = "driver_mapping";
- break;
- }
- break;
- }
-
- if (!desc)
- return;
-
- printk(MPT2SAS_INFO_FMT "%s: %s(%d), action(%d), form(0x%08x), "
- "smid(%d)\n", ioc->name, calling_function_name, desc,
- mpi_request->Header.PageNumber, mpi_request->Action,
- le32_to_cpu(mpi_request->PageAddress), smid);
-
- if (!mpi_reply)
- return;
-
- if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
- printk(MPT2SAS_INFO_FMT
- "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo));
-}
-#endif
-
-/**
- * _config_alloc_config_dma_memory - obtain physical memory
- * @ioc: per adapter object
- * @mem: struct config_request
- *
- * A wrapper for obtaining dma-able memory for config page request.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
- struct config_request *mem)
-{
- int r = 0;
-
- if (mem->sz > ioc->config_page_sz) {
- mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
- &mem->page_dma, GFP_KERNEL);
- if (!mem->page) {
- printk(MPT2SAS_ERR_FMT "%s: dma_alloc_coherent"
- " failed asking for (%d) bytes!!\n",
- ioc->name, __func__, mem->sz);
- r = -ENOMEM;
- }
- } else { /* use tmp buffer if less than 512 bytes */
- mem->page = ioc->config_page;
- mem->page_dma = ioc->config_page_dma;
- }
- return r;
-}
-
-/**
- * _config_free_config_dma_memory - wrapper to free the memory
- * @ioc: per adapter object
- * @mem: struct config_request
- *
- * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static void
-_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
- struct config_request *mem)
-{
- if (mem->sz > ioc->config_page_sz)
- dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
- mem->page_dma);
-}
-
-/**
- * mpt2sas_config_done - config page completion routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: none.
- *
- * The callback handler when using _config_request.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-u8
-mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
-
- if (ioc->config_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
- if (ioc->config_cmds.smid != smid)
- return 1;
- ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (mpi_reply) {
- ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID;
- memcpy(ioc->config_cmds.reply, mpi_reply,
- mpi_reply->MsgLength*4);
- }
- ioc->config_cmds.status &= ~MPT2_CMD_PENDING;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
-#endif
- ioc->config_cmds.smid = USHRT_MAX;
- complete(&ioc->config_cmds.done);
- return 1;
-}
-
-/**
- * _config_request - main routine for sending config page requests
- * @ioc: per adapter object
- * @mpi_request: request message frame
- * @mpi_reply: reply mf payload returned from firmware
- * @timeout: timeout in seconds
- * @config_page: contents of the config page
- * @config_page_sz: size of config page
- * Context: sleep
- *
- * A generic API for config page requests to firmware.
- *
- * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling
- * this API.
- *
- * The callback index is set inside `ioc->config_cb_idx.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
- *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
- void *config_page, u16 config_page_sz)
-{
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- Mpi2ConfigRequest_t *config_request;
- int r;
- u8 retry_count, issue_host_reset = 0;
- u16 wait_state_count;
- struct config_request mem;
-
- mutex_lock(&ioc->config_cmds.mutex);
- if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
- ioc->name, __func__);
- mutex_unlock(&ioc->config_cmds.mutex);
- return -EAGAIN;
- }
-
- retry_count = 0;
- memset(&mem, 0, sizeof(struct config_request));
-
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
-
- if (config_page) {
- mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
- mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
- mpi_request->Header.PageType = mpi_reply->Header.PageType;
- mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
- mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
- mpi_request->ExtPageType = mpi_reply->ExtPageType;
- if (mpi_request->Header.PageLength)
- mem.sz = mpi_request->Header.PageLength * 4;
- else
- mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
- r = _config_alloc_config_dma_memory(ioc, &mem);
- if (r != 0)
- goto out;
- if (mpi_request->Action ==
- MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
- mpi_request->Action ==
- MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
- ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
- MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
- mem.page_dma);
- memcpy(mem.page, config_page, min_t(u16, mem.sz,
- config_page_sz));
- } else {
- memset(config_page, 0, config_page_sz);
- ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
- MPT2_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
- }
- }
-
- retry_config:
- if (retry_count) {
- if (retry_count > 2) { /* attempt only 2 retries */
- r = -EFAULT;
- goto free_mem;
- }
- printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
- ioc->name, __func__, retry_count);
- }
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- r = -EFAULT;
- goto free_mem;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
- if (wait_state_count)
- printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
- ioc->name, __func__);
-
- smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- r = -EAGAIN;
- goto free_mem;
- }
-
- r = 0;
- memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
- ioc->config_cmds.status = MPT2_CMD_PENDING;
- config_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->config_cmds.smid = smid;
- memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- _config_display_some_debug(ioc, smid, "config_request", NULL);
-#endif
- init_completion(&ioc->config_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
- timeout*HZ);
- if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2ConfigRequest_t)/4);
- retry_count++;
- if (ioc->config_cmds.smid == smid)
- mpt2sas_base_free_smid(ioc, smid);
- if ((ioc->shost_recovery) || (ioc->config_cmds.status &
- MPT2_CMD_RESET) || ioc->pci_error_recovery)
- goto retry_config;
- issue_host_reset = 1;
- r = -EFAULT;
- goto free_mem;
- }
-
- if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
- memcpy(mpi_reply, ioc->config_cmds.reply,
- sizeof(Mpi2ConfigReply_t));
- if (retry_count)
- printk(MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n",
- ioc->name, __func__, retry_count);
- if (config_page && mpi_request->Action ==
- MPI2_CONFIG_ACTION_PAGE_READ_CURRENT)
- memcpy(config_page, mem.page, min_t(u16, mem.sz,
- config_page_sz));
- free_mem:
- if (config_page)
- _config_free_config_dma_memory(ioc, &mem);
- out:
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->config_cmds.mutex);
-
- if (issue_host_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- return r;
-}
-
-/**
- * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
- mpi_request.Header.PageNumber = 10;
- mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_bios_pg2 - obtain bios page 2
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
- mpi_request.Header.PageNumber = 2;
- mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_bios_pg3 - obtain bios page 3
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2BiosPage3_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
- mpi_request.Header.PageNumber = 3;
- mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_set_iounit_pg1 - set iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg3 - obtain iounit page 3
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
- mpi_request.Header.PageNumber = 3;
- mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg8 - obtain iounit page 8
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
- mpi_request.Header.PageNumber = 8;
- mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
- mpi_request.Header.PageNumber = 8;
- mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: device handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
- mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
- mpi_request.Header.PageNumber = 0;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: device handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
- mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
- mpi_request.Header.PageNumber = 1;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host
- * @ioc: per adapter object
- * @num_phys: pointer returned with the number of phys
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
- u16 ioc_status;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasIOUnitPage0_t config_page;
-
- *num_phys = 0;
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
- sizeof(Mpi2SasIOUnitPage0_t));
- if (!r) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
- *num_phys = config_page.NumPhys;
- }
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Calling function should call config_get_number_hba_phys prior to
- * this function, so enough memory is allocated for config_page.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Calling function should call config_get_number_hba_phys prior to
- * this function, so enough memory is allocated for config_page.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_set_sas_iounit_pg1 - send sas iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Calling function should call config_get_number_hba_phys prior to
- * this function, so enough memory is allocated for config_page.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_expander_pg0 - obtain expander page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: expander handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_expander_pg1 - obtain expander page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @phy_number: phy number
- * @handle: expander handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
- u16 handle)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress =
- cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
- (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: expander handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_phy_pg0 - obtain phy page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @phy_number: phy number
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress =
- cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_phy_pg1 - obtain phy page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @phy_number: phy number
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress =
- cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: volume handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
- u32 handle)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
- mpi_request.Header.PageNumber = 1;
- mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume
- * @ioc: per adapter object
- * @handle: volume handle
- * @num_pds: returns pds count
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- u8 *num_pds)
-{
- Mpi2ConfigRequest_t mpi_request;
- Mpi2RaidVolPage0_t config_page;
- Mpi2ConfigReply_t mpi_reply;
- int r;
- u16 ioc_status;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- *num_pds = 0;
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress =
- cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
- sizeof(Mpi2RaidVolPage0_t));
- if (!r) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
- *num_pds = config_page.NumPhysDisks;
- }
-
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: volume handle
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
- Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
- u32 handle, u16 sz)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | handle);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
- * @form_specific: specific to the form
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
- *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
- u32 form_specific)
-{
- Mpi2ConfigRequest_t mpi_request;
- int r;
-
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
- mpi_request.Header.PageNumber = 0;
- mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.PageAddress = cpu_to_le32(form | form_specific);
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- r = _config_request(ioc, &mpi_request, mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- sizeof(*config_page));
- out:
- return r;
-}
-
-/**
- * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components
- * @ioc: per adapter object
- * @pd_handle: phys disk handle
- * @volume_handle: volume handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
- u16 *volume_handle)
-{
- Mpi2RaidConfigurationPage0_t *config_page = NULL;
- Mpi2ConfigRequest_t mpi_request;
- Mpi2ConfigReply_t mpi_reply;
- int r, i, config_page_sz;
- u16 ioc_status;
- int config_num;
- u16 element_type;
- u16 phys_disk_dev_handle;
-
- *volume_handle = 0;
- memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
- mpi_request.Function = MPI2_FUNCTION_CONFIG;
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
- mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
- mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
- mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
- mpi_request.Header.PageNumber = 0;
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
- if (r)
- goto out;
-
- mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
- config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
- config_page = kmalloc(config_page_sz, GFP_KERNEL);
- if (!config_page) {
- r = -1;
- goto out;
- }
- config_num = 0xff;
- while (1) {
- mpi_request.PageAddress = cpu_to_le32(config_num +
- MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
- r = _config_request(ioc, &mpi_request, &mpi_reply,
- MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
- config_page_sz);
- if (r)
- goto out;
- r = -1;
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- goto out;
- for (i = 0; i < config_page->NumElements; i++) {
- element_type = le16_to_cpu(config_page->
- ConfigElement[i].ElementFlags) &
- MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
- if (element_type ==
- MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
- element_type ==
- MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
- phys_disk_dev_handle =
- le16_to_cpu(config_page->ConfigElement[i].
- PhysDiskDevHandle);
- if (phys_disk_dev_handle == pd_handle) {
- *volume_handle =
- le16_to_cpu(config_page->
- ConfigElement[i].VolDevHandle);
- r = 0;
- goto out;
- }
- } else if (element_type ==
- MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
- *volume_handle = 0;
- r = 0;
- goto out;
- }
- }
- config_num = config_page->ConfigNum;
- }
- out:
- kfree(config_page);
- return r;
-}
-
-/**
- * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle
- * @ioc: per adapter object
- * @volume_handle: volume handle
- * @wwid: volume wwid
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
- u64 *wwid)
-{
- Mpi2ConfigReply_t mpi_reply;
- Mpi2RaidVolPage1_t raid_vol_pg1;
-
- *wwid = 0;
- if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
- &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
- volume_handle))) {
- *wwid = le64_to_cpu(raid_vol_pg1.WWID);
- return 0;
- } else
- return -1;
-}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
deleted file mode 100644
index 3694b63bd993..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ /dev/null
@@ -1,3101 +0,0 @@
-/*
- * Management Module Support for MPT (Message Passing Technology) based
- * controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/compat.h>
-#include <linux/poll.h>
-
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-#include "mpt2sas_base.h"
-#include "mpt2sas_ctl.h"
-
-static DEFINE_MUTEX(_ctl_mutex);
-static struct fasync_struct *async_queue;
-static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
-
-static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type,
- u8 *issue_reset);
-
-/**
- * enum block_state - blocking state
- * @NON_BLOCKING: non blocking
- * @BLOCKING: blocking
- *
- * These states are for ioctls that need to wait for a response
- * from firmware, so they probably require sleep.
- */
-enum block_state {
- NON_BLOCKING,
- BLOCKING,
-};
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _ctl_sas_device_find_by_handle - sas device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-static struct _sas_device *
-_ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _sas_device *sas_device, *r;
-
- r = NULL;
- list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
- if (sas_device->handle != handle)
- continue;
- r = sas_device;
- goto out;
- }
-
- out:
- return r;
-}
-
-/**
- * _ctl_display_some_debug - debug routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @calling_function_name: string pass from calling function
- * @mpi_reply: reply message frame
- * Context: none.
- *
- * Function for displaying debug info helpful when debugging issues
- * in this module.
- */
-static void
-_ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
-{
- Mpi2ConfigRequest_t *mpi_request;
- char *desc = NULL;
-
- if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
- return;
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- switch (mpi_request->Function) {
- case MPI2_FUNCTION_SCSI_IO_REQUEST:
- {
- Mpi2SCSIIORequest_t *scsi_request =
- (Mpi2SCSIIORequest_t *)mpi_request;
-
- snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
- "scsi_io, cmd(0x%02x), cdb_len(%d)",
- scsi_request->CDB.CDB32[0],
- le16_to_cpu(scsi_request->IoFlags) & 0xF);
- desc = ioc->tmp_string;
- break;
- }
- case MPI2_FUNCTION_SCSI_TASK_MGMT:
- desc = "task_mgmt";
- break;
- case MPI2_FUNCTION_IOC_INIT:
- desc = "ioc_init";
- break;
- case MPI2_FUNCTION_IOC_FACTS:
- desc = "ioc_facts";
- break;
- case MPI2_FUNCTION_CONFIG:
- {
- Mpi2ConfigRequest_t *config_request =
- (Mpi2ConfigRequest_t *)mpi_request;
-
- snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
- "config, type(0x%02x), ext_type(0x%02x), number(%d)",
- (config_request->Header.PageType &
- MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
- config_request->Header.PageNumber);
- desc = ioc->tmp_string;
- break;
- }
- case MPI2_FUNCTION_PORT_FACTS:
- desc = "port_facts";
- break;
- case MPI2_FUNCTION_PORT_ENABLE:
- desc = "port_enable";
- break;
- case MPI2_FUNCTION_EVENT_NOTIFICATION:
- desc = "event_notification";
- break;
- case MPI2_FUNCTION_FW_DOWNLOAD:
- desc = "fw_download";
- break;
- case MPI2_FUNCTION_FW_UPLOAD:
- desc = "fw_upload";
- break;
- case MPI2_FUNCTION_RAID_ACTION:
- desc = "raid_action";
- break;
- case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
- {
- Mpi2SCSIIORequest_t *scsi_request =
- (Mpi2SCSIIORequest_t *)mpi_request;
-
- snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
- "raid_pass, cmd(0x%02x), cdb_len(%d)",
- scsi_request->CDB.CDB32[0],
- le16_to_cpu(scsi_request->IoFlags) & 0xF);
- desc = ioc->tmp_string;
- break;
- }
- case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
- desc = "sas_iounit_cntl";
- break;
- case MPI2_FUNCTION_SATA_PASSTHROUGH:
- desc = "sata_pass";
- break;
- case MPI2_FUNCTION_DIAG_BUFFER_POST:
- desc = "diag_buffer_post";
- break;
- case MPI2_FUNCTION_DIAG_RELEASE:
- desc = "diag_release";
- break;
- case MPI2_FUNCTION_SMP_PASSTHROUGH:
- desc = "smp_passthrough";
- break;
- }
-
- if (!desc)
- return;
-
- printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n",
- ioc->name, calling_function_name, desc, smid);
-
- if (!mpi_reply)
- return;
-
- if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
- printk(MPT2SAS_INFO_FMT
- "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo));
-
- if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
- mpi_request->Function ==
- MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
- Mpi2SCSIIOReply_t *scsi_reply =
- (Mpi2SCSIIOReply_t *)mpi_reply;
- struct _sas_device *sas_device = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _ctl_sas_device_find_by_handle(ioc,
- le16_to_cpu(scsi_reply->DevHandle));
- if (sas_device) {
- printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
- "phy(%d)\n", ioc->name, (unsigned long long)
- sas_device->sas_address, sas_device->phy);
- printk(MPT2SAS_WARN_FMT
- "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
- ioc->name, sas_device->enclosure_logical_id,
- sas_device->slot);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
- printk(MPT2SAS_INFO_FMT
- "\tscsi_state(0x%02x), scsi_status"
- "(0x%02x)\n", ioc->name,
- scsi_reply->SCSIState,
- scsi_reply->SCSIStatus);
- }
-}
-#endif
-
-/**
- * mpt2sas_ctl_done - ctl module completion routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: none.
- *
- * The callback handler when using ioc->ctl_cb_idx.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-u8
-mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
- Mpi2SCSIIOReply_t *scsiio_reply;
- const void *sense_data;
- u32 sz;
-
- if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
- if (ioc->ctl_cmds.smid != smid)
- return 1;
- ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE;
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (mpi_reply) {
- memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
- ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID;
- /* get sense data */
- if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
- mpi_reply->Function ==
- MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
- scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply;
- if (scsiio_reply->SCSIState &
- MPI2_SCSI_STATE_AUTOSENSE_VALID) {
- sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
- le32_to_cpu(scsiio_reply->SenseCount));
- sense_data = mpt2sas_base_get_sense_buffer(ioc,
- smid);
- memcpy(ioc->ctl_cmds.sense, sense_data, sz);
- }
- }
- }
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
-#endif
- ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING;
- complete(&ioc->ctl_cmds.done);
- return 1;
-}
-
-/**
- * _ctl_check_event_type - determines when an event needs logging
- * @ioc: per adapter object
- * @event: firmware event
- *
- * The bitmask in ioc->event_type[] indicates which events should be
- * be saved in the driver event_log. This bitmask is set by application.
- *
- * Returns 1 when event should be captured, or zero means no match.
- */
-static int
-_ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event)
-{
- u16 i;
- u32 desired_event;
-
- if (event >= 128 || !event || !ioc->event_log)
- return 0;
-
- desired_event = (1 << (event % 32));
- if (!desired_event)
- desired_event = 1;
- i = event / 32;
- return desired_event & ioc->event_type[i];
-}
-
-/**
- * mpt2sas_ctl_add_to_event_log - add event
- * @ioc: per adapter object
- * @mpi_reply: reply message frame
- *
- * Return nothing.
- */
-void
-mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventNotificationReply_t *mpi_reply)
-{
- struct MPT2_IOCTL_EVENTS *event_log;
- u16 event;
- int i;
- u32 sz, event_data_sz;
- u8 send_aen = 0;
-
- if (!ioc->event_log)
- return;
-
- event = le16_to_cpu(mpi_reply->Event);
-
- if (_ctl_check_event_type(ioc, event)) {
-
- /* insert entry into circular event_log */
- i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE;
- event_log = ioc->event_log;
- event_log[i].event = event;
- event_log[i].context = ioc->event_context++;
-
- event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
- sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE);
- memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE);
- memcpy(event_log[i].data, mpi_reply->EventData, sz);
- send_aen = 1;
- }
-
- /* This aen_event_read_flag flag is set until the
- * application has read the event log.
- * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
- */
- if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
- (send_aen && !ioc->aen_event_read_flag)) {
- ioc->aen_event_read_flag = 1;
- wake_up_interruptible(&ctl_poll_wait);
- if (async_queue)
- kill_fasync(&async_queue, SIGIO, POLL_IN);
- }
-}
-
-/**
- * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time)
- * @ioc: per adapter object
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: interrupt.
- *
- * This function merely adds a new work task into ioc->firmware_event_thread.
- * The tasks are worked from _firmware_event_work in user context.
- *
- * Returns void.
- */
-void
-mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
- u32 reply)
-{
- Mpi2EventNotificationReply_t *mpi_reply;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (unlikely(!mpi_reply)) {
- printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
- mpt2sas_ctl_add_to_event_log(ioc, mpi_reply);
- return;
-}
-
-/**
- * _ctl_verify_adapter - validates ioc_number passed from application
- * @ioc: per adapter object
- * @iocpp: The ioc pointer is returned in this.
- *
- * Return (-1) means error, else ioc_number.
- */
-static int
-_ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
-{
- struct MPT2SAS_ADAPTER *ioc;
- /* global ioc lock to protect controller on list operations */
- spin_lock(&gioc_lock);
- list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
- if (ioc->id != ioc_number)
- continue;
- spin_unlock(&gioc_lock);
- *iocpp = ioc;
- return ioc_number;
- }
- spin_unlock(&gioc_lock);
- *iocpp = NULL;
- return -1;
-}
-
-/**
- * mpt2sas_ctl_reset_handler - reset callback handler (for ctl)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- */
-void
-mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
- int i;
- u8 issue_reset;
-
- switch (reset_phase) {
- case MPT2_IOC_PRE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
- for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
- if (!(ioc->diag_buffer_status[i] &
- MPT2_DIAG_BUFFER_IS_REGISTERED))
- continue;
- if ((ioc->diag_buffer_status[i] &
- MPT2_DIAG_BUFFER_IS_RELEASED))
- continue;
- _ctl_send_release(ioc, i, &issue_reset);
- }
- break;
- case MPT2_IOC_AFTER_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
- if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) {
- ioc->ctl_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
- complete(&ioc->ctl_cmds.done);
- }
- break;
- case MPT2_IOC_DONE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
-
- for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
- if (!(ioc->diag_buffer_status[i] &
- MPT2_DIAG_BUFFER_IS_REGISTERED))
- continue;
- if ((ioc->diag_buffer_status[i] &
- MPT2_DIAG_BUFFER_IS_RELEASED))
- continue;
- ioc->diag_buffer_status[i] |=
- MPT2_DIAG_BUFFER_IS_DIAG_RESET;
- }
- break;
- }
-}
-
-/**
- * _ctl_fasync -
- * @fd -
- * @filep -
- * @mode -
- *
- * Called when application request fasyn callback handler.
- */
-static int
-_ctl_fasync(int fd, struct file *filep, int mode)
-{
- return fasync_helper(fd, filep, mode, &async_queue);
-}
-
-/**
- * _ctl_poll -
- * @file -
- * @wait -
- *
- */
-static unsigned int
-_ctl_poll(struct file *filep, poll_table *wait)
-{
- struct MPT2SAS_ADAPTER *ioc;
-
- poll_wait(filep, &ctl_poll_wait, wait);
-
- /* global ioc lock to protect controller on list operations */
- spin_lock(&gioc_lock);
- list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
- if (ioc->aen_event_read_flag) {
- spin_unlock(&gioc_lock);
- return POLLIN | POLLRDNORM;
- }
- }
- spin_unlock(&gioc_lock);
- return 0;
-}
-
-/**
- * _ctl_set_task_mid - assign an active smid to tm request
- * @ioc: per adapter object
- * @karg - (struct mpt2_ioctl_command)
- * @tm_request - pointer to mf from user space
- *
- * Returns 0 when an smid if found, else fail.
- * during failure, the reply frame is filled.
- */
-static int
-_ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
- Mpi2SCSITaskManagementRequest_t *tm_request)
-{
- u8 found = 0;
- u16 i;
- u16 handle;
- struct scsi_cmnd *scmd;
- struct MPT2SAS_DEVICE *priv_data;
- unsigned long flags;
- Mpi2SCSITaskManagementReply_t *tm_reply;
- u32 sz;
- u32 lun;
- char *desc = NULL;
-
- if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
- desc = "abort_task";
- else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
- desc = "query_task";
- else
- return 0;
-
- lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
-
- handle = le16_to_cpu(tm_request->DevHandle);
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- for (i = ioc->scsiio_depth; i && !found; i--) {
- scmd = ioc->scsi_lookup[i - 1].scmd;
- if (scmd == NULL || scmd->device == NULL ||
- scmd->device->hostdata == NULL)
- continue;
- if (lun != scmd->device->lun)
- continue;
- priv_data = scmd->device->hostdata;
- if (priv_data->sas_target == NULL)
- continue;
- if (priv_data->sas_target->handle != handle)
- continue;
- tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
- found = 1;
- }
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
- if (!found) {
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name,
- desc, le16_to_cpu(tm_request->DevHandle), lun));
- tm_reply = ioc->ctl_cmds.reply;
- tm_reply->DevHandle = tm_request->DevHandle;
- tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
- tm_reply->TaskType = tm_request->TaskType;
- tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
- tm_reply->VP_ID = tm_request->VP_ID;
- tm_reply->VF_ID = tm_request->VF_ID;
- sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
- if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
- sz))
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- return 1;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name,
- desc, le16_to_cpu(tm_request->DevHandle), lun,
- le16_to_cpu(tm_request->TaskMID)));
- return 0;
-}
-
-/**
- * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode
- * @ioc: per adapter object
- * @karg - (struct mpt2_ioctl_command)
- * @mf - pointer to mf in user space
- */
-static long
-_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command karg,
- void __user *mf)
-{
- MPI2RequestHeader_t *mpi_request = NULL, *request;
- MPI2DefaultReply_t *mpi_reply;
- u32 ioc_state;
- u16 ioc_status;
- u16 smid;
- unsigned long timeout, timeleft;
- u8 issue_reset;
- u32 sz;
- void *psge;
- void *data_out = NULL;
- dma_addr_t data_out_dma;
- size_t data_out_sz = 0;
- void *data_in = NULL;
- dma_addr_t data_in_dma;
- size_t data_in_sz = 0;
- u32 sgl_flags;
- long ret;
- u16 wait_state_count;
-
- issue_reset = 0;
-
- if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
- ioc->name, __func__);
- ret = -EAGAIN;
- goto out;
- }
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- ret = -EFAULT;
- goto out;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
- if (wait_state_count)
- printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
- ioc->name, __func__);
-
- mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL);
- if (!mpi_request) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a memory for "
- "mpi_request\n", ioc->name, __func__);
- ret = -ENOMEM;
- goto out;
- }
-
- /* Check for overflow and wraparound */
- if (karg.data_sge_offset * 4 > ioc->request_sz ||
- karg.data_sge_offset > (UINT_MAX / 4)) {
- ret = -EINVAL;
- goto out;
- }
-
- /* copy in request message frame from user */
- if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
- __func__);
- ret = -EFAULT;
- goto out;
- }
-
- if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
- smid = mpt2sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- ret = -EAGAIN;
- goto out;
- }
- } else {
-
- smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- ret = -EAGAIN;
- goto out;
- }
- }
-
- ret = 0;
- ioc->ctl_cmds.status = MPT2_CMD_PENDING;
- memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
- request = mpt2sas_base_get_msg_frame(ioc, smid);
- memcpy(request, mpi_request, karg.data_sge_offset*4);
- ioc->ctl_cmds.smid = smid;
- data_out_sz = karg.data_out_size;
- data_in_sz = karg.data_in_size;
-
- if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
- mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
- if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
- le16_to_cpu(mpi_request->FunctionDependent1) >
- ioc->facts.MaxDevHandle) {
- ret = -EINVAL;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
- }
-
- /* obtain dma-able memory for data transfer */
- if (data_out_sz) /* WRITE */ {
- data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
- &data_out_dma);
- if (!data_out) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- ret = -ENOMEM;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
- if (copy_from_user(data_out, karg.data_out_buf_ptr,
- data_out_sz)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- ret = -EFAULT;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
- }
-
- if (data_in_sz) /* READ */ {
- data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
- &data_in_dma);
- if (!data_in) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- ret = -ENOMEM;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
- }
-
- /* add scatter gather elements */
- psge = (void *)request + (karg.data_sge_offset*4);
-
- if (!data_out_sz && !data_in_sz) {
- mpt2sas_base_build_zero_len_sge(ioc, psge);
- } else if (data_out_sz && data_in_sz) {
- /* WRITE sgel first */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- data_out_sz, data_out_dma);
-
- /* incr sgel */
- psge += ioc->sge_size;
-
- /* READ sgel last */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- data_in_sz, data_in_dma);
- } else if (data_out_sz) /* WRITE */ {
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- data_out_sz, data_out_dma);
- } else if (data_in_sz) /* READ */ {
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- data_in_sz, data_in_dma);
- }
-
- /* send command to firmware */
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
-#endif
-
- init_completion(&ioc->ctl_cmds.done);
- switch (mpi_request->Function) {
- case MPI2_FUNCTION_SCSI_IO_REQUEST:
- case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
- {
- Mpi2SCSIIORequest_t *scsiio_request =
- (Mpi2SCSIIORequest_t *)request;
- scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
- scsiio_request->SenseBufferLowAddress =
- mpt2sas_base_get_sense_buffer_dma(ioc, smid);
- memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
- if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
- mpt2sas_base_put_smid_scsi_io(ioc, smid,
- le16_to_cpu(mpi_request->FunctionDependent1));
- else
- mpt2sas_base_put_smid_default(ioc, smid);
- break;
- }
- case MPI2_FUNCTION_SCSI_TASK_MGMT:
- {
- Mpi2SCSITaskManagementRequest_t *tm_request =
- (Mpi2SCSITaskManagementRequest_t *)request;
-
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
- "handle(0x%04x), task_type(0x%02x)\n", ioc->name,
- le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
-
- if (tm_request->TaskType ==
- MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
- tm_request->TaskType ==
- MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
- if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
- }
-
- mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu(
- tm_request->DevHandle));
- mpt2sas_base_put_smid_hi_priority(ioc, smid);
- break;
- }
- case MPI2_FUNCTION_SMP_PASSTHROUGH:
- {
- Mpi2SmpPassthroughRequest_t *smp_request =
- (Mpi2SmpPassthroughRequest_t *)mpi_request;
- u8 *data;
-
- /* ioc determines which port to use */
- smp_request->PhysicalPort = 0xFF;
- if (smp_request->PassthroughFlags &
- MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
- data = (u8 *)&smp_request->SGL;
- else {
- if (unlikely(data_out == NULL)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- mpt2sas_base_free_smid(ioc, smid);
- ret = -EINVAL;
- goto out;
- }
- data = data_out;
- }
-
- if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
- ioc->ioc_link_reset_in_progress = 1;
- ioc->ignore_loginfos = 1;
- }
- mpt2sas_base_put_smid_default(ioc, smid);
- break;
- }
- case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
- {
- Mpi2SasIoUnitControlRequest_t *sasiounit_request =
- (Mpi2SasIoUnitControlRequest_t *)mpi_request;
-
- if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
- || sasiounit_request->Operation ==
- MPI2_SAS_OP_PHY_LINK_RESET) {
- ioc->ioc_link_reset_in_progress = 1;
- ioc->ignore_loginfos = 1;
- }
- mpt2sas_base_put_smid_default(ioc, smid);
- break;
- }
- default:
- mpt2sas_base_put_smid_default(ioc, smid);
- break;
- }
-
- if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT)
- timeout = MPT2_IOCTL_DEFAULT_TIMEOUT;
- else
- timeout = karg.timeout;
- timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
- timeout*HZ);
- if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
- Mpi2SCSITaskManagementRequest_t *tm_request =
- (Mpi2SCSITaskManagementRequest_t *)mpi_request;
- mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
- tm_request->DevHandle));
- } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
- mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
- ioc->ioc_link_reset_in_progress) {
- ioc->ioc_link_reset_in_progress = 0;
- ioc->ignore_loginfos = 0;
- }
- if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
- __func__);
- _debug_dump_mf(mpi_request, karg.data_sge_offset);
- if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- mpi_reply = ioc->ctl_cmds.reply;
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
- (ioc->logging_level & MPT_DEBUG_TM)) {
- Mpi2SCSITaskManagementReply_t *tm_reply =
- (Mpi2SCSITaskManagementReply_t *)mpi_reply;
-
- printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
- "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
- "TerminationCount(0x%08x)\n", ioc->name,
- le16_to_cpu(tm_reply->IOCStatus),
- le32_to_cpu(tm_reply->IOCLogInfo),
- le32_to_cpu(tm_reply->TerminationCount));
- }
-#endif
- /* copy out xdata to user */
- if (data_in_sz) {
- if (copy_to_user(karg.data_in_buf_ptr, data_in,
- data_in_sz)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- ret = -ENODATA;
- goto out;
- }
- }
-
- /* copy out reply message frame to user */
- if (karg.max_reply_bytes) {
- sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
- if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
- sz)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- ret = -ENODATA;
- goto out;
- }
- }
-
- /* copy out sense to user */
- if (karg.max_sense_bytes && (mpi_request->Function ==
- MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
- MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
- sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
- if (copy_to_user(karg.sense_data_ptr,
- ioc->ctl_cmds.sense, sz)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- ret = -ENODATA;
- goto out;
- }
- }
-
- issue_host_reset:
- if (issue_reset) {
- ret = -ENODATA;
- if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
- mpi_request->Function ==
- MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
- mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) {
- printk(MPT2SAS_INFO_FMT "issue target reset: handle "
- "= (0x%04x)\n", ioc->name,
- le16_to_cpu(mpi_request->FunctionDependent1));
- mpt2sas_halt_firmware(ioc);
- mpt2sas_scsih_issue_tm(ioc,
- le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
- 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
- TM_MUTEX_ON);
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- } else
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- }
-
- out:
-
- /* free memory associated with sg buffers */
- if (data_in)
- pci_free_consistent(ioc->pdev, data_in_sz, data_in,
- data_in_dma);
-
- if (data_out)
- pci_free_consistent(ioc->pdev, data_out_sz, data_out,
- data_out_dma);
-
- kfree(mpi_request);
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- return ret;
-}
-
-/**
- * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_getiocinfo(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_ioctl_iocinfo karg;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
-
- memset(&karg, 0 , sizeof(karg));
- if (ioc->is_warpdrive)
- karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200;
- else
- karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
- if (ioc->pfacts)
- karg.port_number = ioc->pfacts[0].PortNumber;
- karg.hw_rev = ioc->pdev->revision;
- karg.pci_id = ioc->pdev->device;
- karg.subsystem_device = ioc->pdev->subsystem_device;
- karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
- karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
- karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
- karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
- karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
- karg.firmware_version = ioc->facts.FWVersion.Word;
- strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME);
- strcat(karg.driver_version, "-");
- strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
- karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
-
- if (copy_to_user(arg, &karg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
- return 0;
-}
-
-/**
- * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_eventquery(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_ioctl_eventquery karg;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
-
- karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE;
- memcpy(karg.event_types, ioc->event_type,
- MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
-
- if (copy_to_user(arg, &karg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
- return 0;
-}
-
-/**
- * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_eventenable(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_ioctl_eventenable karg;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
-
- if (ioc->event_log)
- return 0;
- memcpy(ioc->event_type, karg.event_types,
- MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
- mpt2sas_base_validate_event_type(ioc, ioc->event_type);
-
- /* initialize event_log */
- ioc->event_context = 0;
- ioc->aen_event_read_flag = 0;
- ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE,
- sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL);
- if (!ioc->event_log) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -ENOMEM;
- }
- return 0;
-}
-
-/**
- * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_eventreport(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_ioctl_eventreport karg;
- u32 number_bytes, max_events, max;
- struct mpt2_ioctl_eventreport __user *uarg = arg;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
-
- number_bytes = karg.hdr.max_data_size -
- sizeof(struct mpt2_ioctl_header);
- max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS);
- max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events);
-
- /* If fewer than 1 event is requested, there must have
- * been some type of error.
- */
- if (!max || !ioc->event_log)
- return -ENODATA;
-
- number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS);
- if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- /* reset flag so SIGIO can restart */
- ioc->aen_event_read_flag = 0;
- return 0;
-}
-
-/**
- * _ctl_do_reset - main handler for MPT2HARDRESET opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_do_reset(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_ioctl_diag_reset karg;
- int retval;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- if (ioc->shost_recovery || ioc->pci_error_recovery ||
- ioc->is_driver_loading)
- return -EAGAIN;
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
-
- retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- printk(MPT2SAS_INFO_FMT "host reset: %s\n",
- ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
- return 0;
-}
-
-/**
- * _ctl_btdh_search_sas_device - searching for sas device
- * @ioc: per adapter object
- * @btdh: btdh ioctl payload
- */
-static int
-_ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc,
- struct mpt2_ioctl_btdh_mapping *btdh)
-{
- struct _sas_device *sas_device;
- unsigned long flags;
- int rc = 0;
-
- if (list_empty(&ioc->sas_device_list))
- return rc;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
- if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
- btdh->handle == sas_device->handle) {
- btdh->bus = sas_device->channel;
- btdh->id = sas_device->id;
- rc = 1;
- goto out;
- } else if (btdh->bus == sas_device->channel && btdh->id ==
- sas_device->id && btdh->handle == 0xFFFF) {
- btdh->handle = sas_device->handle;
- rc = 1;
- goto out;
- }
- }
- out:
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return rc;
-}
-
-/**
- * _ctl_btdh_search_raid_device - searching for raid device
- * @ioc: per adapter object
- * @btdh: btdh ioctl payload
- */
-static int
-_ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
- struct mpt2_ioctl_btdh_mapping *btdh)
-{
- struct _raid_device *raid_device;
- unsigned long flags;
- int rc = 0;
-
- if (list_empty(&ioc->raid_device_list))
- return rc;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
- if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
- btdh->handle == raid_device->handle) {
- btdh->bus = raid_device->channel;
- btdh->id = raid_device->id;
- rc = 1;
- goto out;
- } else if (btdh->bus == raid_device->channel && btdh->id ==
- raid_device->id && btdh->handle == 0xFFFF) {
- btdh->handle = raid_device->handle;
- rc = 1;
- goto out;
- }
- }
- out:
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- return rc;
-}
-
-/**
- * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_btdh_mapping(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_ioctl_btdh_mapping karg;
- int rc;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- rc = _ctl_btdh_search_sas_device(ioc, &karg);
- if (!rc)
- _ctl_btdh_search_raid_device(ioc, &karg);
-
- if (copy_to_user(arg, &karg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
- return 0;
-}
-
-/**
- * _ctl_diag_capability - return diag buffer capability
- * @ioc: per adapter object
- * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
- *
- * returns 1 when diag buffer support is enabled in firmware
- */
-static u8
-_ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
-{
- u8 rc = 0;
-
- switch (buffer_type) {
- case MPI2_DIAG_BUF_TYPE_TRACE:
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
- rc = 1;
- break;
- case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
- rc = 1;
- break;
- case MPI2_DIAG_BUF_TYPE_EXTENDED:
- if (ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
- rc = 1;
- }
-
- return rc;
-}
-
-/**
- * _ctl_diag_register_2 - wrapper for registering diag buffer support
- * @ioc: per adapter object
- * @diag_register: the diag_register struct passed in from user space
- *
- */
-static long
-_ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
- struct mpt2_diag_register *diag_register)
-{
- int rc, i;
- void *request_data = NULL;
- dma_addr_t request_data_dma;
- u32 request_data_sz = 0;
- Mpi2DiagBufferPostRequest_t *mpi_request;
- Mpi2DiagBufferPostReply_t *mpi_reply;
- u8 buffer_type;
- unsigned long timeleft;
- u16 smid;
- u16 ioc_status;
- u8 issue_reset = 0;
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- buffer_type = diag_register->buffer_type;
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if (ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) {
- printk(MPT2SAS_ERR_FMT "%s: already has a registered "
- "buffer for buffer_type(0x%02x)\n", ioc->name, __func__,
- buffer_type);
- return -EINVAL;
- }
-
- if (diag_register->requested_buffer_size % 4) {
- printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
- "is not 4 byte aligned\n", ioc->name, __func__);
- return -EINVAL;
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- rc = 0;
- ioc->ctl_cmds.status = MPT2_CMD_PENDING;
- memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->ctl_cmds.smid = smid;
-
- request_data = ioc->diag_buffer[buffer_type];
- request_data_sz = diag_register->requested_buffer_size;
- ioc->unique_id[buffer_type] = diag_register->unique_id;
- ioc->diag_buffer_status[buffer_type] = 0;
- memcpy(ioc->product_specific[buffer_type],
- diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS);
- ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
-
- if (request_data) {
- request_data_dma = ioc->diag_buffer_dma[buffer_type];
- if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
- pci_free_consistent(ioc->pdev,
- ioc->diag_buffer_sz[buffer_type],
- request_data, request_data_dma);
- request_data = NULL;
- }
- }
-
- if (request_data == NULL) {
- ioc->diag_buffer_sz[buffer_type] = 0;
- ioc->diag_buffer_dma[buffer_type] = 0;
- request_data = pci_alloc_consistent(
- ioc->pdev, request_data_sz, &request_data_dma);
- if (request_data == NULL) {
- printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"
- " for diag buffers, requested size(%d)\n",
- ioc->name, __func__, request_data_sz);
- mpt2sas_base_free_smid(ioc, smid);
- return -ENOMEM;
- }
- ioc->diag_buffer[buffer_type] = request_data;
- ioc->diag_buffer_sz[buffer_type] = request_data_sz;
- ioc->diag_buffer_dma[buffer_type] = request_data_dma;
- }
-
- mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
- mpi_request->BufferType = diag_register->buffer_type;
- mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
- mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
- mpi_request->BufferLength = cpu_to_le32(request_data_sz);
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(0x%p), "
- "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
- (unsigned long long)request_data_dma,
- le32_to_cpu(mpi_request->BufferLength)));
-
- for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
- mpi_request->ProductSpecific[i] =
- cpu_to_le32(ioc->product_specific[buffer_type][i]);
-
- init_completion(&ioc->ctl_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
- MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
-
- if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
- __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2DiagBufferPostRequest_t)/4);
- if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- /* process the completed Reply Message Frame */
- if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
-
- mpi_reply = ioc->ctl_cmds.reply;
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
- ioc->diag_buffer_status[buffer_type] |=
- MPT2_DIAG_BUFFER_IS_REGISTERED;
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
- ioc->name, __func__));
- } else {
- printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
- "log_info(0x%08x)\n", ioc->name, __func__,
- ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
- rc = -EFAULT;
- }
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
-
- out:
-
- if (rc && request_data)
- pci_free_consistent(ioc->pdev, request_data_sz,
- request_data, request_data_dma);
-
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- return rc;
-}
-
-/**
- * mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time
- * @ioc: per adapter object
- * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
- *
- * This is called when command line option diag_buffer_enable is enabled
- * at driver load time.
- */
-void
-mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
-{
- struct mpt2_diag_register diag_register;
-
- memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
-
- if (bits_to_register & 1) {
- printk(MPT2SAS_INFO_FMT "registering trace buffer support\n",
- ioc->name);
- diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
- /* register for 1MB buffers */
- diag_register.requested_buffer_size = (1024 * 1024);
- diag_register.unique_id = 0x7075900;
- _ctl_diag_register_2(ioc, &diag_register);
- }
-
- if (bits_to_register & 2) {
- printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n",
- ioc->name);
- diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
- /* register for 2MB buffers */
- diag_register.requested_buffer_size = 2 * (1024 * 1024);
- diag_register.unique_id = 0x7075901;
- _ctl_diag_register_2(ioc, &diag_register);
- }
-
- if (bits_to_register & 4) {
- printk(MPT2SAS_INFO_FMT "registering extended buffer support\n",
- ioc->name);
- diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
- /* register for 2MB buffers */
- diag_register.requested_buffer_size = 2 * (1024 * 1024);
- diag_register.unique_id = 0x7075901;
- _ctl_diag_register_2(ioc, &diag_register);
- }
-}
-
-/**
- * _ctl_diag_register - application register with driver
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- *
- * This will allow the driver to setup any required buffers that will be
- * needed by firmware to communicate with the driver.
- */
-static long
-_ctl_diag_register(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_diag_register karg;
- long rc;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- rc = _ctl_diag_register_2(ioc, &karg);
- return rc;
-}
-
-/**
- * _ctl_diag_unregister - application unregister with driver
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- *
- * This will allow the driver to cleanup any memory allocated for diag
- * messages and to free up any resources.
- */
-static long
-_ctl_diag_unregister(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_diag_unregister karg;
- void *request_data;
- dma_addr_t request_data_dma;
- u32 request_data_sz;
- u8 buffer_type;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- buffer_type = karg.unique_id & 0x000000ff;
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
- "registered\n", ioc->name, __func__, buffer_type);
- return -EINVAL;
- }
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been "
- "released\n", ioc->name, __func__, buffer_type);
- return -EINVAL;
- }
-
- if (karg.unique_id != ioc->unique_id[buffer_type]) {
- printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
- "registered\n", ioc->name, __func__, karg.unique_id);
- return -EINVAL;
- }
-
- request_data = ioc->diag_buffer[buffer_type];
- if (!request_data) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -ENOMEM;
- }
-
- request_data_sz = ioc->diag_buffer_sz[buffer_type];
- request_data_dma = ioc->diag_buffer_dma[buffer_type];
- pci_free_consistent(ioc->pdev, request_data_sz,
- request_data, request_data_dma);
- ioc->diag_buffer[buffer_type] = NULL;
- ioc->diag_buffer_status[buffer_type] = 0;
- return 0;
-}
-
-/**
- * _ctl_diag_query - query relevant info associated with diag buffers
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- *
- * The application will send only buffer_type and unique_id. Driver will
- * inspect unique_id first, if valid, fill in all the info. If unique_id is
- * 0x00, the driver will return info specified by Buffer Type.
- */
-static long
-_ctl_diag_query(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_diag_query karg;
- void *request_data;
- int i;
- u8 buffer_type;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- karg.application_flags = 0;
- buffer_type = karg.buffer_type;
-
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
- "registered\n", ioc->name, __func__, buffer_type);
- return -EINVAL;
- }
-
- if (karg.unique_id & 0xffffff00) {
- if (karg.unique_id != ioc->unique_id[buffer_type]) {
- printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
- "registered\n", ioc->name, __func__,
- karg.unique_id);
- return -EINVAL;
- }
- }
-
- request_data = ioc->diag_buffer[buffer_type];
- if (!request_data) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -ENOMEM;
- }
-
- if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED)
- karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
- MPT2_APP_FLAGS_BUFFER_VALID);
- else
- karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
- MPT2_APP_FLAGS_BUFFER_VALID |
- MPT2_APP_FLAGS_FW_BUFFER_ACCESS);
-
- for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
- karg.product_specific[i] =
- ioc->product_specific[buffer_type][i];
-
- karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
- karg.driver_added_buffer_size = 0;
- karg.unique_id = ioc->unique_id[buffer_type];
- karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
-
- if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) {
- printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query "
- "data @ %p\n", ioc->name, __func__, arg);
- return -EFAULT;
- }
- return 0;
-}
-
-/**
- * _ctl_send_release - Diag Release Message
- * @ioc: per adapter object
- * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
- * @issue_reset - specifies whether host reset is required.
- *
- */
-static int
-_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
-{
- Mpi2DiagReleaseRequest_t *mpi_request;
- Mpi2DiagReleaseReply_t *mpi_reply;
- u16 smid;
- u16 ioc_status;
- u32 ioc_state;
- int rc;
- unsigned long timeleft;
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- rc = 0;
- *issue_reset = 0;
-
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "skipping due to FAULT state\n", ioc->name,
- __func__));
- rc = -EAGAIN;
- goto out;
- }
-
- if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- ioc->ctl_cmds.status = MPT2_CMD_PENDING;
- memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->ctl_cmds.smid = smid;
-
- mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
- mpi_request->BufferType = buffer_type;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
-
- init_completion(&ioc->ctl_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
- MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
-
- if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
- __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2DiagReleaseRequest_t)/4);
- if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
- *issue_reset = 1;
- rc = -EFAULT;
- goto out;
- }
-
- /* process the completed Reply Message Frame */
- if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
-
- mpi_reply = ioc->ctl_cmds.reply;
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
- ioc->diag_buffer_status[buffer_type] |=
- MPT2_DIAG_BUFFER_IS_RELEASED;
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
- ioc->name, __func__));
- } else {
- printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
- "log_info(0x%08x)\n", ioc->name, __func__,
- ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
- rc = -EFAULT;
- }
-
- out:
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- return rc;
-}
-
-/**
- * _ctl_diag_release - request to send Diag Release Message to firmware
- * @arg - user space buffer containing ioctl content
- *
- * This allows ownership of the specified buffer to returned to the driver,
- * allowing an application to read the buffer without fear that firmware is
- * overwritting information in the buffer.
- */
-static long
-_ctl_diag_release(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_diag_release karg;
- void *request_data;
- int rc;
- u8 buffer_type;
- u8 issue_reset = 0;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- buffer_type = karg.unique_id & 0x000000ff;
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
- "registered\n", ioc->name, __func__, buffer_type);
- return -EINVAL;
- }
-
- if (karg.unique_id != ioc->unique_id[buffer_type]) {
- printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
- "registered\n", ioc->name, __func__, karg.unique_id);
- return -EINVAL;
- }
-
- if (ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_RELEASED) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
- "is already released\n", ioc->name, __func__,
- buffer_type);
- return 0;
- }
-
- request_data = ioc->diag_buffer[buffer_type];
-
- if (!request_data) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -ENOMEM;
- }
-
- /* buffers were released by due to host reset */
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_DIAG_RESET)) {
- ioc->diag_buffer_status[buffer_type] |=
- MPT2_DIAG_BUFFER_IS_RELEASED;
- ioc->diag_buffer_status[buffer_type] &=
- ~MPT2_DIAG_BUFFER_IS_DIAG_RESET;
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
- "was released due to host reset\n", ioc->name, __func__,
- buffer_type);
- return 0;
- }
-
- rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
-
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
-
- return rc;
-}
-
-/**
- * _ctl_diag_read_buffer - request for copy of the diag buffer
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_diag_read_buffer(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
- struct mpt2_diag_read_buffer karg;
- struct mpt2_diag_read_buffer __user *uarg = arg;
- void *request_data, *diag_data;
- Mpi2DiagBufferPostRequest_t *mpi_request;
- Mpi2DiagBufferPostReply_t *mpi_reply;
- int rc, i;
- u8 buffer_type;
- unsigned long timeleft, request_size, copy_size;
- u16 smid;
- u16 ioc_status;
- u8 issue_reset = 0;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
- __func__));
-
- buffer_type = karg.unique_id & 0x000000ff;
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if (karg.unique_id != ioc->unique_id[buffer_type]) {
- printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
- "registered\n", ioc->name, __func__, karg.unique_id);
- return -EINVAL;
- }
-
- request_data = ioc->diag_buffer[buffer_type];
- if (!request_data) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -ENOMEM;
- }
-
- request_size = ioc->diag_buffer_sz[buffer_type];
-
- if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
- printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
- "or bytes_to_read are not 4 byte aligned\n", ioc->name,
- __func__);
- return -EINVAL;
- }
-
- if (karg.starting_offset > request_size)
- return -EINVAL;
-
- diag_data = (void *)(request_data + karg.starting_offset);
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
- "offset(%d), sz(%d)\n", ioc->name, __func__,
- diag_data, karg.starting_offset, karg.bytes_to_read));
-
- /* Truncate data on requests that are too large */
- if ((diag_data + karg.bytes_to_read < diag_data) ||
- (diag_data + karg.bytes_to_read > request_data + request_size))
- copy_size = request_size - karg.starting_offset;
- else
- copy_size = karg.bytes_to_read;
-
- if (copy_to_user((void __user *)uarg->diagnostic_data,
- diag_data, copy_size)) {
- printk(MPT2SAS_ERR_FMT "%s: Unable to write "
- "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
- __func__, diag_data);
- return -EFAULT;
- }
-
- if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0)
- return 0;
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type));
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "buffer_type(0x%02x) is still registered\n", ioc->name,
- __func__, buffer_type));
- return 0;
- }
- /* Get a free request frame and save the message context.
- */
-
- if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- rc = 0;
- ioc->ctl_cmds.status = MPT2_CMD_PENDING;
- memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->ctl_cmds.smid = smid;
-
- mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
- mpi_request->BufferType = buffer_type;
- mpi_request->BufferLength =
- cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
- mpi_request->BufferAddress =
- cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
- for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
- mpi_request->ProductSpecific[i] =
- cpu_to_le32(ioc->product_specific[buffer_type][i]);
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
-
- init_completion(&ioc->ctl_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
- MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
-
- if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
- __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2DiagBufferPostRequest_t)/4);
- if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- /* process the completed Reply Message Frame */
- if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
-
- mpi_reply = ioc->ctl_cmds.reply;
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
- ioc->diag_buffer_status[buffer_type] |=
- MPT2_DIAG_BUFFER_IS_REGISTERED;
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
- ioc->name, __func__));
- } else {
- printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
- "log_info(0x%08x)\n", ioc->name, __func__,
- ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
- rc = -EFAULT;
- }
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
-
- out:
-
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- return rc;
-}
-
-
-#ifdef CONFIG_COMPAT
-/**
- * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
- * @ioc: per adapter object
- * @cmd - ioctl opcode
- * @arg - (struct mpt2_ioctl_command32)
- *
- * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
- */
-static long
-_ctl_compat_mpt_command(struct MPT2SAS_ADAPTER *ioc, unsigned cmd,
- void __user *arg)
-{
- struct mpt2_ioctl_command32 karg32;
- struct mpt2_ioctl_command32 __user *uarg;
- struct mpt2_ioctl_command karg;
-
- if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
- return -EINVAL;
-
- uarg = (struct mpt2_ioctl_command32 __user *) arg;
-
- if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
- karg.hdr.ioc_number = karg32.hdr.ioc_number;
- karg.hdr.port_number = karg32.hdr.port_number;
- karg.hdr.max_data_size = karg32.hdr.max_data_size;
- karg.timeout = karg32.timeout;
- karg.max_reply_bytes = karg32.max_reply_bytes;
- karg.data_in_size = karg32.data_in_size;
- karg.data_out_size = karg32.data_out_size;
- karg.max_sense_bytes = karg32.max_sense_bytes;
- karg.data_sge_offset = karg32.data_sge_offset;
- karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
- karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
- karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
- karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
- return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
-}
-#endif
-
-/**
- * _ctl_ioctl_main - main ioctl entry point
- * @file - (struct file)
- * @cmd - ioctl opcode
- * @arg -
- * compat - handles 32 bit applications in 64bit os
- */
-static long
-_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
- u8 compat)
-{
- struct MPT2SAS_ADAPTER *ioc;
- struct mpt2_ioctl_header ioctl_header;
- enum block_state state;
- long ret = -EINVAL;
-
- /* get IOCTL header */
- if (copy_from_user(&ioctl_header, (char __user *)arg,
- sizeof(struct mpt2_ioctl_header))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
- /* pci_access_mutex lock acquired by ioctl path */
- mutex_lock(&ioc->pci_access_mutex);
- if (ioc->shost_recovery || ioc->pci_error_recovery ||
- ioc->is_driver_loading || ioc->remove_host) {
- ret = -EAGAIN;
- goto out_unlock_pciaccess;
- }
-
- state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
- if (state == NON_BLOCKING) {
- if (!mutex_trylock(&ioc->ctl_cmds.mutex)) {
- ret = -EAGAIN;
- goto out_unlock_pciaccess;
- }
- } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
- ret = -ERESTARTSYS;
- goto out_unlock_pciaccess;
- }
-
- switch (cmd) {
- case MPT2IOCINFO:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
- ret = _ctl_getiocinfo(ioc, arg);
- break;
-#ifdef CONFIG_COMPAT
- case MPT2COMMAND32:
-#endif
- case MPT2COMMAND:
- {
- struct mpt2_ioctl_command __user *uarg;
- struct mpt2_ioctl_command karg;
-#ifdef CONFIG_COMPAT
- if (compat) {
- ret = _ctl_compat_mpt_command(ioc, cmd, arg);
- break;
- }
-#endif
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- ret = -EFAULT;
- break;
- }
-
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
- uarg = arg;
- ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
- }
- break;
- }
- case MPT2EVENTQUERY:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
- ret = _ctl_eventquery(ioc, arg);
- break;
- case MPT2EVENTENABLE:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
- ret = _ctl_eventenable(ioc, arg);
- break;
- case MPT2EVENTREPORT:
- ret = _ctl_eventreport(ioc, arg);
- break;
- case MPT2HARDRESET:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
- ret = _ctl_do_reset(ioc, arg);
- break;
- case MPT2BTDHMAPPING:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
- ret = _ctl_btdh_mapping(ioc, arg);
- break;
- case MPT2DIAGREGISTER:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
- ret = _ctl_diag_register(ioc, arg);
- break;
- case MPT2DIAGUNREGISTER:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
- ret = _ctl_diag_unregister(ioc, arg);
- break;
- case MPT2DIAGQUERY:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
- ret = _ctl_diag_query(ioc, arg);
- break;
- case MPT2DIAGRELEASE:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
- ret = _ctl_diag_release(ioc, arg);
- break;
- case MPT2DIAGREADBUFFER:
- if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
- ret = _ctl_diag_read_buffer(ioc, arg);
- break;
- default:
-
- dctlprintk(ioc, printk(MPT2SAS_INFO_FMT
- "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
- break;
- }
-
- mutex_unlock(&ioc->ctl_cmds.mutex);
-out_unlock_pciaccess:
- mutex_unlock(&ioc->pci_access_mutex);
- return ret;
-}
-
-/**
- * _ctl_ioctl - main ioctl entry point (unlocked)
- * @file - (struct file)
- * @cmd - ioctl opcode
- * @arg -
- */
-static long
-_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- long ret;
-
- ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
- return ret;
-}
-#ifdef CONFIG_COMPAT
-/**
- * _ctl_ioctl_compat - main ioctl entry point (compat)
- * @file -
- * @cmd -
- * @arg -
- *
- * This routine handles 32 bit applications in 64bit os.
- */
-static long
-_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
-{
- long ret;
-
- ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
- return ret;
-}
-#endif
-
-/* scsi host attributes */
-
-/**
- * _ctl_version_fw_show - firmware version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
- (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
- (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
- (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
- ioc->facts.FWVersion.Word & 0x000000FF);
-}
-static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
-
-/**
- * _ctl_version_bios_show - bios version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
-
- return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
- (version & 0xFF000000) >> 24,
- (version & 0x00FF0000) >> 16,
- (version & 0x0000FF00) >> 8,
- version & 0x000000FF);
-}
-static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
-
-/**
- * _ctl_version_mpi_show - MPI (message passing interface) version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
- ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
-}
-static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
-
-/**
- * _ctl_version_product_show - product name
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
-}
-static DEVICE_ATTR(version_product, S_IRUGO,
- _ctl_version_product_show, NULL);
-
-/**
- * _ctl_version_nvdata_persistent_show - ndvata persistent version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_nvdata_persistent_show(struct device *cdev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%08xh\n",
- le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
-}
-static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
- _ctl_version_nvdata_persistent_show, NULL);
-
-/**
- * _ctl_version_nvdata_default_show - nvdata default version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_nvdata_default_show(struct device *cdev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%08xh\n",
- le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
-}
-static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
- _ctl_version_nvdata_default_show, NULL);
-
-/**
- * _ctl_board_name_show - board name
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
-}
-static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
-
-/**
- * _ctl_board_assembly_show - board assembly name
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
-}
-static DEVICE_ATTR(board_assembly, S_IRUGO,
- _ctl_board_assembly_show, NULL);
-
-/**
- * _ctl_board_tracer_show - board tracer number
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
-}
-static DEVICE_ATTR(board_tracer, S_IRUGO,
- _ctl_board_tracer_show, NULL);
-
-/**
- * _ctl_io_delay_show - io missing delay
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is for firmware implemention for deboucing device
- * removal events.
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
-}
-static DEVICE_ATTR(io_delay, S_IRUGO,
- _ctl_io_delay_show, NULL);
-
-/**
- * _ctl_device_delay_show - device missing delay
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is for firmware implemention for deboucing device
- * removal events.
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
-}
-static DEVICE_ATTR(device_delay, S_IRUGO,
- _ctl_device_delay_show, NULL);
-
-/**
- * _ctl_fw_queue_depth_show - global credits
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is firmware queue depth limit
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
-}
-static DEVICE_ATTR(fw_queue_depth, S_IRUGO,
- _ctl_fw_queue_depth_show, NULL);
-
-/**
- * _ctl_sas_address_show - sas address
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is the controller sas address
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
- (unsigned long long)ioc->sas_hba.sas_address);
-}
-static DEVICE_ATTR(host_sas_address, S_IRUGO,
- _ctl_host_sas_address_show, NULL);
-
-/**
- * _ctl_logging_level_show - logging level
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read/write' shost attribute.
- */
-static ssize_t
-_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
-}
-static ssize_t
-_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- int val = 0;
-
- if (sscanf(buf, "%x", &val) != 1)
- return -EINVAL;
-
- ioc->logging_level = val;
- printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name,
- ioc->logging_level);
- return strlen(buf);
-}
-static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
- _ctl_logging_level_show, _ctl_logging_level_store);
-
-/* device attributes */
-/*
- * _ctl_fwfault_debug_show - show/store fwfault_debug
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * mpt2sas_fwfault_debug is command line option
- * A sysfs 'read/write' shost attribute.
- */
-static ssize_t
-_ctl_fwfault_debug_show(struct device *cdev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
-}
-static ssize_t
-_ctl_fwfault_debug_store(struct device *cdev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- int val = 0;
-
- if (sscanf(buf, "%d", &val) != 1)
- return -EINVAL;
-
- ioc->fwfault_debug = val;
- printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name,
- ioc->fwfault_debug);
- return strlen(buf);
-}
-static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
- _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
-
-
-/**
- * _ctl_ioc_reset_count_show - ioc reset count
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is firmware queue depth limit
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count);
-}
-static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
- _ctl_ioc_reset_count_show, NULL);
-
-/**
- * _ctl_ioc_reply_queue_count_show - number of reply queues
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is number of reply queues
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_ioc_reply_queue_count_show(struct device *cdev,
- struct device_attribute *attr, char *buf)
-{
- u8 reply_queue_count;
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- if ((ioc->facts.IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
- reply_queue_count = ioc->reply_queue_count;
- else
- reply_queue_count = 1;
- return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
-}
-static DEVICE_ATTR(reply_queue_count, S_IRUGO,
- _ctl_ioc_reply_queue_count_show, NULL);
-
-/**
- * _ctl_BRM_status_show - Backup Rail Monitor Status
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is number of reply queues
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
- Mpi2ConfigReply_t mpi_reply;
- u16 backup_rail_monitor_status = 0;
- u16 ioc_status;
- int sz;
- ssize_t rc = 0;
-
- if (!ioc->is_warpdrive) {
- printk(MPT2SAS_ERR_FMT "%s: BRM attribute is only for"\
- "warpdrive\n", ioc->name, __func__);
- goto out;
- }
- /* pci_access_mutex lock acquired by sysfs show path */
- mutex_lock(&ioc->pci_access_mutex);
- if (ioc->pci_error_recovery || ioc->remove_host) {
- mutex_unlock(&ioc->pci_access_mutex);
- return 0;
- }
-
- /* allocate upto GPIOVal 36 entries */
- sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
- io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
- if (!io_unit_pg3) {
- printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"\
- "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz);
- goto out;
- }
-
- if (mpt2sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
- 0) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed reading iounit_pg3\n", ioc->name,
- __func__);
- goto out;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "%s: iounit_pg3 failed with"\
- "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status);
- goto out;
- }
-
- if (io_unit_pg3->GPIOCount < 25) {
- printk(MPT2SAS_ERR_FMT "%s: iounit_pg3->GPIOCount less than"\
- "25 entries, detected (%d) entries\n", ioc->name, __func__,
- io_unit_pg3->GPIOCount);
- goto out;
- }
-
- /* BRM status is in bit zero of GPIOVal[24] */
- backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
- rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
-
- out:
- kfree(io_unit_pg3);
- mutex_unlock(&ioc->pci_access_mutex);
- return rc;
-}
-static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL);
-
-struct DIAG_BUFFER_START {
- __le32 Size;
- __le32 DiagVersion;
- u8 BufferType;
- u8 Reserved[3];
- __le32 Reserved1;
- __le32 Reserved2;
- __le32 Reserved3;
-};
-/**
- * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_host_trace_buffer_size_show(struct device *cdev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- u32 size = 0;
- struct DIAG_BUFFER_START *request_data;
-
- if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
- printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
- "registered\n", ioc->name, __func__);
- return 0;
- }
-
- if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
- "registered\n", ioc->name, __func__);
- return 0;
- }
-
- request_data = (struct DIAG_BUFFER_START *)
- ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
- if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
- le32_to_cpu(request_data->DiagVersion) == 0x01000000) &&
- le32_to_cpu(request_data->Reserved3) == 0x4742444c)
- size = le32_to_cpu(request_data->Size);
-
- ioc->ring_buffer_sz = size;
- return snprintf(buf, PAGE_SIZE, "%d\n", size);
-}
-static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
- _ctl_host_trace_buffer_size_show, NULL);
-
-/**
- * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read/write' shost attribute.
- *
- * You will only be able to read 4k bytes of ring buffer at a time.
- * In order to read beyond 4k bytes, you will have to write out the
- * offset to the same attribute, it will move the pointer.
- */
-static ssize_t
-_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- void *request_data;
- u32 size;
-
- if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
- printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
- "registered\n", ioc->name, __func__);
- return 0;
- }
-
- if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
- "registered\n", ioc->name, __func__);
- return 0;
- }
-
- if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
- return 0;
-
- size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
- size = (size > PAGE_SIZE) ? PAGE_SIZE : size;
- request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
- memcpy(buf, request_data, size);
- return size;
-}
-
-static ssize_t
-_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- int val = 0;
-
- if (sscanf(buf, "%d", &val) != 1)
- return -EINVAL;
-
- ioc->ring_buffer_offset = val;
- return strlen(buf);
-}
-static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
- _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
-
-/*****************************************/
-
-/**
- * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read/write' shost attribute.
- *
- * This is a mechnism to post/release host_trace_buffers
- */
-static ssize_t
-_ctl_host_trace_buffer_enable_show(struct device *cdev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
- ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0))
- return snprintf(buf, PAGE_SIZE, "off\n");
- else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_RELEASED))
- return snprintf(buf, PAGE_SIZE, "release\n");
- else
- return snprintf(buf, PAGE_SIZE, "post\n");
-}
-
-static ssize_t
-_ctl_host_trace_buffer_enable_store(struct device *cdev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct Scsi_Host *shost = class_to_shost(cdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- char str[10] = "";
- struct mpt2_diag_register diag_register;
- u8 issue_reset = 0;
-
- if (sscanf(buf, "%9s", str) != 1)
- return -EINVAL;
-
- if (!strcmp(str, "post")) {
- /* exit out if host buffers are already posted */
- if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
- (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) &&
- ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_RELEASED) == 0))
- goto out;
- memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
- printk(MPT2SAS_INFO_FMT "posting host trace buffers\n",
- ioc->name);
- diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
- diag_register.requested_buffer_size = (1024 * 1024);
- diag_register.unique_id = 0x7075900;
- ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
- _ctl_diag_register_2(ioc, &diag_register);
- } else if (!strcmp(str, "release")) {
- /* exit out if host buffers are already released */
- if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
- goto out;
- if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)
- goto out;
- if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
- MPT2_DIAG_BUFFER_IS_RELEASED))
- goto out;
- printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n",
- ioc->name);
- _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset);
- }
-
- out:
- return strlen(buf);
-}
-static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
- _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store);
-
-struct device_attribute *mpt2sas_host_attrs[] = {
- &dev_attr_version_fw,
- &dev_attr_version_bios,
- &dev_attr_version_mpi,
- &dev_attr_version_product,
- &dev_attr_version_nvdata_persistent,
- &dev_attr_version_nvdata_default,
- &dev_attr_board_name,
- &dev_attr_board_assembly,
- &dev_attr_board_tracer,
- &dev_attr_io_delay,
- &dev_attr_device_delay,
- &dev_attr_logging_level,
- &dev_attr_fwfault_debug,
- &dev_attr_fw_queue_depth,
- &dev_attr_host_sas_address,
- &dev_attr_ioc_reset_count,
- &dev_attr_host_trace_buffer_size,
- &dev_attr_host_trace_buffer,
- &dev_attr_host_trace_buffer_enable,
- &dev_attr_reply_queue_count,
- &dev_attr_BRM_status,
- NULL,
-};
-
-/**
- * _ctl_device_sas_address_show - sas address
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is the sas address for the target
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
-
- return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
- (unsigned long long)sas_device_priv_data->sas_target->sas_address);
-}
-static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
-
-/**
- * _ctl_device_handle_show - device handle
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is the firmware assigned device handle
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- sas_device_priv_data->sas_target->handle);
-}
-static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
-
-struct device_attribute *mpt2sas_dev_attrs[] = {
- &dev_attr_sas_address,
- &dev_attr_sas_device_handle,
- NULL,
-};
-
-static const struct file_operations ctl_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = _ctl_ioctl,
- .poll = _ctl_poll,
- .fasync = _ctl_fasync,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = _ctl_ioctl_compat,
-#endif
- .llseek = noop_llseek,
-};
-
-static struct miscdevice ctl_dev = {
- .minor = MPT2SAS_MINOR,
- .name = MPT2SAS_DEV_NAME,
- .fops = &ctl_fops,
-};
-
-/**
- * mpt2sas_ctl_init - main entry point for ctl.
- *
- */
-void
-mpt2sas_ctl_init(void)
-{
- async_queue = NULL;
- if (misc_register(&ctl_dev) < 0)
- printk(KERN_ERR "%s can't register misc device [minor=%d]\n",
- MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
-
- init_waitqueue_head(&ctl_poll_wait);
-}
-
-/**
- * mpt2sas_ctl_exit - exit point for ctl
- *
- */
-void
-mpt2sas_ctl_exit(void)
-{
- struct MPT2SAS_ADAPTER *ioc;
- int i;
-
- list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
-
- /* free memory associated to diag buffers */
- for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
- if (!ioc->diag_buffer[i])
- continue;
- pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
- ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
- ioc->diag_buffer[i] = NULL;
- ioc->diag_buffer_status[i] = 0;
- }
-
- kfree(ioc->event_log);
- }
- misc_deregister(&ctl_dev);
-}
-
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
deleted file mode 100644
index 46b2fc5b74af..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Management Module Support for MPT (Message Passing Technology) based
- * controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#ifndef MPT2SAS_CTL_H_INCLUDED
-#define MPT2SAS_CTL_H_INCLUDED
-
-#ifdef __KERNEL__
-#include <linux/miscdevice.h>
-#endif
-
-#define MPT2SAS_DEV_NAME "mpt2ctl"
-#define MPT2_MAGIC_NUMBER 'L'
-#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
-
-/**
- * IOCTL opcodes
- */
-#define MPT2IOCINFO _IOWR(MPT2_MAGIC_NUMBER, 17, \
- struct mpt2_ioctl_iocinfo)
-#define MPT2COMMAND _IOWR(MPT2_MAGIC_NUMBER, 20, \
- struct mpt2_ioctl_command)
-#ifdef CONFIG_COMPAT
-#define MPT2COMMAND32 _IOWR(MPT2_MAGIC_NUMBER, 20, \
- struct mpt2_ioctl_command32)
-#endif
-#define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \
- struct mpt2_ioctl_eventquery)
-#define MPT2EVENTENABLE _IOWR(MPT2_MAGIC_NUMBER, 22, \
- struct mpt2_ioctl_eventenable)
-#define MPT2EVENTREPORT _IOWR(MPT2_MAGIC_NUMBER, 23, \
- struct mpt2_ioctl_eventreport)
-#define MPT2HARDRESET _IOWR(MPT2_MAGIC_NUMBER, 24, \
- struct mpt2_ioctl_diag_reset)
-#define MPT2BTDHMAPPING _IOWR(MPT2_MAGIC_NUMBER, 31, \
- struct mpt2_ioctl_btdh_mapping)
-
-/* diag buffer support */
-#define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \
- struct mpt2_diag_register)
-#define MPT2DIAGRELEASE _IOWR(MPT2_MAGIC_NUMBER, 27, \
- struct mpt2_diag_release)
-#define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \
- struct mpt2_diag_unregister)
-#define MPT2DIAGQUERY _IOWR(MPT2_MAGIC_NUMBER, 29, \
- struct mpt2_diag_query)
-#define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \
- struct mpt2_diag_read_buffer)
-
-/**
- * struct mpt2_ioctl_header - main header structure
- * @ioc_number - IOC unit number
- * @port_number - IOC port number
- * @max_data_size - maximum number bytes to transfer on read
- */
-struct mpt2_ioctl_header {
- uint32_t ioc_number;
- uint32_t port_number;
- uint32_t max_data_size;
-};
-
-/**
- * struct mpt2_ioctl_diag_reset - diagnostic reset
- * @hdr - generic header
- */
-struct mpt2_ioctl_diag_reset {
- struct mpt2_ioctl_header hdr;
-};
-
-
-/**
- * struct mpt2_ioctl_pci_info - pci device info
- * @device - pci device id
- * @function - pci function id
- * @bus - pci bus id
- * @segment_id - pci segment id
- */
-struct mpt2_ioctl_pci_info {
- union {
- struct {
- uint32_t device:5;
- uint32_t function:3;
- uint32_t bus:24;
- } bits;
- uint32_t word;
- } u;
- uint32_t segment_id;
-};
-
-
-#define MPT2_IOCTL_INTERFACE_SCSI (0x00)
-#define MPT2_IOCTL_INTERFACE_FC (0x01)
-#define MPT2_IOCTL_INTERFACE_FC_IP (0x02)
-#define MPT2_IOCTL_INTERFACE_SAS (0x03)
-#define MPT2_IOCTL_INTERFACE_SAS2 (0x04)
-#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05)
-#define MPT2_IOCTL_VERSION_LENGTH (32)
-
-/**
- * struct mpt2_ioctl_iocinfo - generic controller info
- * @hdr - generic header
- * @adapter_type - type of adapter (spi, fc, sas)
- * @port_number - port number
- * @pci_id - PCI Id
- * @hw_rev - hardware revision
- * @sub_system_device - PCI subsystem Device ID
- * @sub_system_vendor - PCI subsystem Vendor ID
- * @rsvd0 - reserved
- * @firmware_version - firmware version
- * @bios_version - BIOS version
- * @driver_version - driver version - 32 ASCII characters
- * @rsvd1 - reserved
- * @scsi_id - scsi id of adapter 0
- * @rsvd2 - reserved
- * @pci_information - pci info (2nd revision)
- */
-struct mpt2_ioctl_iocinfo {
- struct mpt2_ioctl_header hdr;
- uint32_t adapter_type;
- uint32_t port_number;
- uint32_t pci_id;
- uint32_t hw_rev;
- uint32_t subsystem_device;
- uint32_t subsystem_vendor;
- uint32_t rsvd0;
- uint32_t firmware_version;
- uint32_t bios_version;
- uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
- uint8_t rsvd1;
- uint8_t scsi_id;
- uint16_t rsvd2;
- struct mpt2_ioctl_pci_info pci_information;
-};
-
-
-/* number of event log entries */
-#define MPT2SAS_CTL_EVENT_LOG_SIZE (50)
-
-/**
- * struct mpt2_ioctl_eventquery - query event count and type
- * @hdr - generic header
- * @event_entries - number of events returned by get_event_report
- * @rsvd - reserved
- * @event_types - type of events currently being captured
- */
-struct mpt2_ioctl_eventquery {
- struct mpt2_ioctl_header hdr;
- uint16_t event_entries;
- uint16_t rsvd;
- uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
-};
-
-/**
- * struct mpt2_ioctl_eventenable - enable/disable event capturing
- * @hdr - generic header
- * @event_types - toggle off/on type of events to be captured
- */
-struct mpt2_ioctl_eventenable {
- struct mpt2_ioctl_header hdr;
- uint32_t event_types[4];
-};
-
-#define MPT2_EVENT_DATA_SIZE (192)
-/**
- * struct MPT2_IOCTL_EVENTS -
- * @event - the event that was reported
- * @context - unique value for each event assigned by driver
- * @data - event data returned in fw reply message
- */
-struct MPT2_IOCTL_EVENTS {
- uint32_t event;
- uint32_t context;
- uint8_t data[MPT2_EVENT_DATA_SIZE];
-};
-
-/**
- * struct mpt2_ioctl_eventreport - returing event log
- * @hdr - generic header
- * @event_data - (see struct MPT2_IOCTL_EVENTS)
- */
-struct mpt2_ioctl_eventreport {
- struct mpt2_ioctl_header hdr;
- struct MPT2_IOCTL_EVENTS event_data[1];
-};
-
-/**
- * struct mpt2_ioctl_command - generic mpt firmware passthru ioctl
- * @hdr - generic header
- * @timeout - command timeout in seconds. (if zero then use driver default
- * value).
- * @reply_frame_buf_ptr - reply location
- * @data_in_buf_ptr - destination for read
- * @data_out_buf_ptr - data source for write
- * @sense_data_ptr - sense data location
- * @max_reply_bytes - maximum number of reply bytes to be sent to app.
- * @data_in_size - number bytes for data transfer in (read)
- * @data_out_size - number bytes for data transfer out (write)
- * @max_sense_bytes - maximum number of bytes for auto sense buffers
- * @data_sge_offset - offset in words from the start of the request message to
- * the first SGL
- * @mf[1];
- */
-struct mpt2_ioctl_command {
- struct mpt2_ioctl_header hdr;
- uint32_t timeout;
- void __user *reply_frame_buf_ptr;
- void __user *data_in_buf_ptr;
- void __user *data_out_buf_ptr;
- void __user *sense_data_ptr;
- uint32_t max_reply_bytes;
- uint32_t data_in_size;
- uint32_t data_out_size;
- uint32_t max_sense_bytes;
- uint32_t data_sge_offset;
- uint8_t mf[1];
-};
-
-#ifdef CONFIG_COMPAT
-struct mpt2_ioctl_command32 {
- struct mpt2_ioctl_header hdr;
- uint32_t timeout;
- uint32_t reply_frame_buf_ptr;
- uint32_t data_in_buf_ptr;
- uint32_t data_out_buf_ptr;
- uint32_t sense_data_ptr;
- uint32_t max_reply_bytes;
- uint32_t data_in_size;
- uint32_t data_out_size;
- uint32_t max_sense_bytes;
- uint32_t data_sge_offset;
- uint8_t mf[1];
-};
-#endif
-
-/**
- * struct mpt2_ioctl_btdh_mapping - mapping info
- * @hdr - generic header
- * @id - target device identification number
- * @bus - SCSI bus number that the target device exists on
- * @handle - device handle for the target device
- * @rsvd - reserved
- *
- * To obtain a bus/id the application sets
- * handle to valid handle, and bus/id to 0xFFFF.
- *
- * To obtain the device handle the application sets
- * bus/id valid value, and the handle to 0xFFFF.
- */
-struct mpt2_ioctl_btdh_mapping {
- struct mpt2_ioctl_header hdr;
- uint32_t id;
- uint32_t bus;
- uint16_t handle;
- uint16_t rsvd;
-};
-
-
-/* status bits for ioc->diag_buffer_status */
-#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
-#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
-#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04)
-
-/* application flags for mpt2_diag_register, mpt2_diag_query */
-#define MPT2_APP_FLAGS_APP_OWNED (0x0001)
-#define MPT2_APP_FLAGS_BUFFER_VALID (0x0002)
-#define MPT2_APP_FLAGS_FW_BUFFER_ACCESS (0x0004)
-
-/* flags for mpt2_diag_read_buffer */
-#define MPT2_FLAGS_REREGISTER (0x0001)
-
-#define MPT2_PRODUCT_SPECIFIC_DWORDS 23
-
-/**
- * struct mpt2_diag_register - application register with driver
- * @hdr - generic header
- * @reserved -
- * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
- * @application_flags - misc flags
- * @diagnostic_flags - specifies flags affecting command processing
- * @product_specific - product specific information
- * @requested_buffer_size - buffers size in bytes
- * @unique_id - tag specified by application that is used to signal ownership
- * of the buffer.
- *
- * This will allow the driver to setup any required buffers that will be
- * needed by firmware to communicate with the driver.
- */
-struct mpt2_diag_register {
- struct mpt2_ioctl_header hdr;
- uint8_t reserved;
- uint8_t buffer_type;
- uint16_t application_flags;
- uint32_t diagnostic_flags;
- uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
- uint32_t requested_buffer_size;
- uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_unregister - application unregister with driver
- * @hdr - generic header
- * @unique_id - tag uniquely identifies the buffer to be unregistered
- *
- * This will allow the driver to cleanup any memory allocated for diag
- * messages and to free up any resources.
- */
-struct mpt2_diag_unregister {
- struct mpt2_ioctl_header hdr;
- uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_query - query relevant info associated with diag buffers
- * @hdr - generic header
- * @reserved -
- * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
- * @application_flags - misc flags
- * @diagnostic_flags - specifies flags affecting command processing
- * @product_specific - product specific information
- * @total_buffer_size - diag buffer size in bytes
- * @driver_added_buffer_size - size of extra space appended to end of buffer
- * @unique_id - unique id associated with this buffer.
- *
- * The application will send only buffer_type and unique_id. Driver will
- * inspect unique_id first, if valid, fill in all the info. If unique_id is
- * 0x00, the driver will return info specified by Buffer Type.
- */
-struct mpt2_diag_query {
- struct mpt2_ioctl_header hdr;
- uint8_t reserved;
- uint8_t buffer_type;
- uint16_t application_flags;
- uint32_t diagnostic_flags;
- uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
- uint32_t total_buffer_size;
- uint32_t driver_added_buffer_size;
- uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_release - request to send Diag Release Message to firmware
- * @hdr - generic header
- * @unique_id - tag uniquely identifies the buffer to be released
- *
- * This allows ownership of the specified buffer to returned to the driver,
- * allowing an application to read the buffer without fear that firmware is
- * overwritting information in the buffer.
- */
-struct mpt2_diag_release {
- struct mpt2_ioctl_header hdr;
- uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_read_buffer - request for copy of the diag buffer
- * @hdr - generic header
- * @status -
- * @reserved -
- * @flags - misc flags
- * @starting_offset - starting offset within drivers buffer where to start
- * reading data at into the specified application buffer
- * @bytes_to_read - number of bytes to copy from the drivers buffer into the
- * application buffer starting at starting_offset.
- * @unique_id - unique id associated with this buffer.
- * @diagnostic_data - data payload
- */
-struct mpt2_diag_read_buffer {
- struct mpt2_ioctl_header hdr;
- uint8_t status;
- uint8_t reserved;
- uint16_t flags;
- uint32_t starting_offset;
- uint32_t bytes_to_read;
- uint32_t unique_id;
- uint32_t diagnostic_data[1];
-};
-
-#endif /* MPT2SAS_CTL_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
deleted file mode 100644
index 277120d45648..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_debug.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Logging Support for MPT (Message Passing Technology) based controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#ifndef MPT2SAS_DEBUG_H_INCLUDED
-#define MPT2SAS_DEBUG_H_INCLUDED
-
-#define MPT_DEBUG 0x00000001
-#define MPT_DEBUG_MSG_FRAME 0x00000002
-#define MPT_DEBUG_SG 0x00000004
-#define MPT_DEBUG_EVENTS 0x00000008
-#define MPT_DEBUG_EVENT_WORK_TASK 0x00000010
-#define MPT_DEBUG_INIT 0x00000020
-#define MPT_DEBUG_EXIT 0x00000040
-#define MPT_DEBUG_FAIL 0x00000080
-#define MPT_DEBUG_TM 0x00000100
-#define MPT_DEBUG_REPLY 0x00000200
-#define MPT_DEBUG_HANDSHAKE 0x00000400
-#define MPT_DEBUG_CONFIG 0x00000800
-#define MPT_DEBUG_DL 0x00001000
-#define MPT_DEBUG_RESET 0x00002000
-#define MPT_DEBUG_SCSI 0x00004000
-#define MPT_DEBUG_IOCTL 0x00008000
-#define MPT_DEBUG_CSMISAS 0x00010000
-#define MPT_DEBUG_SAS 0x00020000
-#define MPT_DEBUG_TRANSPORT 0x00040000
-#define MPT_DEBUG_TASK_SET_FULL 0x00080000
-
-#define MPT_DEBUG_TARGET_MODE 0x00100000
-
-
-/*
- * CONFIG_SCSI_MPT2SAS_LOGGING - enabled in Kconfig
- */
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \
-{ \
- if (IOC->logging_level & BITS) \
- CMD; \
-}
-#else
-#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
-#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
-
-
-/*
- * debug macros
- */
-
-#define dprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG)
-
-#define dsgprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG)
-
-#define devtprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS)
-
-#define dewtprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK)
-
-#define dinitprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT)
-
-#define dexitprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT)
-
-#define dfailprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL)
-
-#define dtmprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM)
-
-#define dreplyprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY)
-
-#define dhsprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE)
-
-#define dcprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG)
-
-#define ddlprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL)
-
-#define drsprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET)
-
-#define dsprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI)
-
-#define dctlprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
-
-#define dcsmisasprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS)
-
-#define dsasprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS)
-
-#define dsastransport(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
-
-#define dmfprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME)
-
-#define dtsfprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL)
-
-#define dtransportprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT)
-
-#define dTMprintk(IOC, CMD) \
- MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TARGET_MODE)
-
-/* inline functions for dumping debug data*/
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _debug_dump_mf - print message frame contents
- * @mpi_request: pointer to message frame
- * @sz: number of dwords
- */
-static inline void
-_debug_dump_mf(void *mpi_request, int sz)
-{
- int i;
- __le32 *mfp = (__le32 *)mpi_request;
-
- printk(KERN_INFO "mf:\n\t");
- for (i = 0; i < sz; i++) {
- if (i && ((i % 8) == 0))
- printk("\n\t");
- printk("%08x ", le32_to_cpu(mfp[i]));
- }
- printk("\n");
-}
-#else
-#define _debug_dump_mf(mpi_request, sz)
-#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
-
-#endif /* MPT2SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
deleted file mode 100644
index 0ad09b2bff9c..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ /dev/null
@@ -1,8855 +0,0 @@
-/*
- * Scsi Host Layer for MPT (Message Passing Technology) based controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/blkdev.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/aer.h>
-#include <linux/raid_class.h>
-#include <linux/slab.h>
-
-#include <asm/unaligned.h>
-
-#include "mpt2sas_base.h"
-
-MODULE_AUTHOR(MPT2SAS_AUTHOR);
-MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MPT2SAS_DRIVER_VERSION);
-
-#define RAID_CHANNEL 1
-
-/* forward proto's */
-static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_expander);
-static void _firmware_event_work(struct work_struct *work);
-
-static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-
-static void _scsih_scan_start(struct Scsi_Host *shost);
-static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
-
-/* global parameters */
-LIST_HEAD(mpt2sas_ioc_list);
-/* global ioc lock for list operations */
-DEFINE_SPINLOCK(gioc_lock);
-/* local parameters */
-static u8 scsi_io_cb_idx = -1;
-static u8 tm_cb_idx = -1;
-static u8 ctl_cb_idx = -1;
-static u8 base_cb_idx = -1;
-static u8 port_enable_cb_idx = -1;
-static u8 transport_cb_idx = -1;
-static u8 scsih_cb_idx = -1;
-static u8 config_cb_idx = -1;
-static int mpt_ids;
-
-static u8 tm_tr_cb_idx = -1 ;
-static u8 tm_tr_volume_cb_idx = -1 ;
-static u8 tm_sas_control_cb_idx = -1;
-
-/* command line options */
-static u32 logging_level;
-MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
- "(default=0)");
-
-static ushort max_sectors = 0xFFFF;
-module_param(max_sectors, ushort, 0);
-MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767");
-
-static int missing_delay[2] = {-1, -1};
-module_param_array(missing_delay, int, NULL, 0);
-MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
-
-/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
-#define MPT2SAS_MAX_LUN (16895)
-static int max_lun = MPT2SAS_MAX_LUN;
-module_param(max_lun, int, 0);
-MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
-
-/* diag_buffer_enable is bitwise
- * bit 0 set = TRACE
- * bit 1 set = SNAPSHOT
- * bit 2 set = EXTENDED
- *
- * Either bit can be set, or both
- */
-static int diag_buffer_enable = -1;
-module_param(diag_buffer_enable, int, 0);
-MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
- "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
-
-static int disable_discovery = -1;
-module_param(disable_discovery, int, 0);
-MODULE_PARM_DESC(disable_discovery, " disable discovery ");
-
-/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
-static int prot_mask = 0;
-module_param(prot_mask, int, 0);
-MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
-
-/**
- * struct sense_info - common structure for obtaining sense keys
- * @skey: sense key
- * @asc: additional sense code
- * @ascq: additional sense code qualifier
- */
-struct sense_info {
- u8 skey;
- u8 asc;
- u8 ascq;
-};
-
-
-#define MPT2SAS_TURN_ON_PFA_LED (0xFFFC)
-#define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD)
-#define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
-/**
- * struct fw_event_work - firmware event struct
- * @list: link list framework
- * @work: work object (ioc->fault_reset_work_q)
- * @cancel_pending_work: flag set during reset handling
- * @ioc: per adapter object
- * @device_handle: device handle
- * @VF_ID: virtual function id
- * @VP_ID: virtual port id
- * @ignore: flag meaning this event has been marked to ignore
- * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
- * @event_data: reply event data payload follows
- *
- * This object stored on ioc->fw_event_list.
- */
-struct fw_event_work {
- struct list_head list;
- u8 cancel_pending_work;
- struct delayed_work delayed_work;
- struct MPT2SAS_ADAPTER *ioc;
- u16 device_handle;
- u8 VF_ID;
- u8 VP_ID;
- u8 ignore;
- u16 event;
- struct kref refcount;
- char event_data[0] __aligned(4);
-};
-
-static void fw_event_work_free(struct kref *r)
-{
- kfree(container_of(r, struct fw_event_work, refcount));
-}
-
-static void fw_event_work_get(struct fw_event_work *fw_work)
-{
- kref_get(&fw_work->refcount);
-}
-
-static void fw_event_work_put(struct fw_event_work *fw_work)
-{
- kref_put(&fw_work->refcount, fw_event_work_free);
-}
-
-static struct fw_event_work *alloc_fw_event_work(int len)
-{
- struct fw_event_work *fw_event;
-
- fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC);
- if (!fw_event)
- return NULL;
-
- kref_init(&fw_event->refcount);
- return fw_event;
-}
-
-/* raid transport support */
-static struct raid_template *mpt2sas_raid_template;
-
-/**
- * struct _scsi_io_transfer - scsi io transfer
- * @handle: sas device handle (assigned by firmware)
- * @is_raid: flag set for hidden raid components
- * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
- * @data_length: data transfer length
- * @data_dma: dma pointer to data
- * @sense: sense data
- * @lun: lun number
- * @cdb_length: cdb length
- * @cdb: cdb contents
- * @timeout: timeout for this command
- * @VF_ID: virtual function id
- * @VP_ID: virtual port id
- * @valid_reply: flag set for reply message
- * @sense_length: sense length
- * @ioc_status: ioc status
- * @scsi_state: scsi state
- * @scsi_status: scsi staus
- * @log_info: log information
- * @transfer_length: data length transfer when there is a reply message
- *
- * Used for sending internal scsi commands to devices within this module.
- * Refer to _scsi_send_scsi_io().
- */
-struct _scsi_io_transfer {
- u16 handle;
- u8 is_raid;
- enum dma_data_direction dir;
- u32 data_length;
- dma_addr_t data_dma;
- u8 sense[SCSI_SENSE_BUFFERSIZE];
- u32 lun;
- u8 cdb_length;
- u8 cdb[32];
- u8 timeout;
- u8 VF_ID;
- u8 VP_ID;
- u8 valid_reply;
- /* the following bits are only valid when 'valid_reply = 1' */
- u32 sense_length;
- u16 ioc_status;
- u8 scsi_state;
- u8 scsi_status;
- u32 log_info;
- u32 transfer_length;
-};
-
-/*
- * The pci device ids are defined in mpi/mpi2_cnfg.h.
- */
-static struct pci_device_id scsih_pci_table[] = {
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
- PCI_ANY_ID, PCI_ANY_ID },
- /* Falcon ~ 2008*/
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
- PCI_ANY_ID, PCI_ANY_ID },
- /* Liberator ~ 2108 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
- PCI_ANY_ID, PCI_ANY_ID },
- /* Meteor ~ 2116 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
- PCI_ANY_ID, PCI_ANY_ID },
- /* Thunderbolt ~ 2208 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
- PCI_ANY_ID, PCI_ANY_ID },
- /* Mustang ~ 2308 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
- PCI_ANY_ID, PCI_ANY_ID },
- /* SSS6200 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
- PCI_ANY_ID, PCI_ANY_ID },
- {0} /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, scsih_pci_table);
-
-/**
- * _scsih_set_debug_level - global setting of ioc->logging_level.
- *
- * Note: The logging levels are defined in mpt2sas_debug.h.
- */
-static int
-_scsih_set_debug_level(const char *val, struct kernel_param *kp)
-{
- int ret = param_set_int(val, kp);
- struct MPT2SAS_ADAPTER *ioc;
-
- if (ret)
- return ret;
-
- printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level);
- spin_lock(&gioc_lock);
- list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
- ioc->logging_level = logging_level;
- spin_unlock(&gioc_lock);
- return 0;
-}
-module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
- &logging_level, 0644);
-
-/**
- * _scsih_srch_boot_sas_address - search based on sas_address
- * @sas_address: sas address
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static inline int
-_scsih_srch_boot_sas_address(u64 sas_address,
- Mpi2BootDeviceSasWwid_t *boot_device)
-{
- return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
-}
-
-/**
- * _scsih_srch_boot_device_name - search based on device name
- * @device_name: device name specified in INDENTIFY fram
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static inline int
-_scsih_srch_boot_device_name(u64 device_name,
- Mpi2BootDeviceDeviceName_t *boot_device)
-{
- return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
-}
-
-/**
- * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
- * @enclosure_logical_id: enclosure logical id
- * @slot_number: slot number
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static inline int
-_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
- Mpi2BootDeviceEnclosureSlot_t *boot_device)
-{
- return (enclosure_logical_id == le64_to_cpu(boot_device->
- EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
- SlotNumber)) ? 1 : 0;
-}
-
-/**
- * _scsih_is_boot_device - search for matching boot device.
- * @sas_address: sas address
- * @device_name: device name specified in INDENTIFY fram
- * @enclosure_logical_id: enclosure logical id
- * @slot_number: slot number
- * @form: specifies boot device form
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static int
-_scsih_is_boot_device(u64 sas_address, u64 device_name,
- u64 enclosure_logical_id, u16 slot, u8 form,
- Mpi2BiosPage2BootDevice_t *boot_device)
-{
- int rc = 0;
-
- switch (form) {
- case MPI2_BIOSPAGE2_FORM_SAS_WWID:
- if (!sas_address)
- break;
- rc = _scsih_srch_boot_sas_address(
- sas_address, &boot_device->SasWwid);
- break;
- case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
- if (!enclosure_logical_id)
- break;
- rc = _scsih_srch_boot_encl_slot(
- enclosure_logical_id,
- slot, &boot_device->EnclosureSlot);
- break;
- case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
- if (!device_name)
- break;
- rc = _scsih_srch_boot_device_name(
- device_name, &boot_device->DeviceName);
- break;
- case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
- break;
- }
-
- return rc;
-}
-
-/**
- * _scsih_get_sas_address - set the sas_address for given device handle
- * @handle: device handle
- * @sas_address: sas address
- *
- * Returns 0 success, non-zero when failure
- */
-static int
-_scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- u64 *sas_address)
-{
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u32 ioc_status;
- *sas_address = 0;
-
- if (handle <= ioc->sas_hba.num_phys) {
- *sas_address = ioc->sas_hba.sas_address;
- return 0;
- }
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- return -ENXIO;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
- *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
- return 0;
- }
-
- /* we hit this becuase the given parent handle doesn't exist */
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- return -ENXIO;
- /* else error case */
- printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), "
- "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
- __FILE__, __LINE__, __func__);
- return -EIO;
-}
-
-/**
- * _scsih_determine_boot_device - determine boot device.
- * @ioc: per adapter object
- * @device: either sas_device or raid_device object
- * @is_raid: [flag] 1 = raid object, 0 = sas object
- *
- * Determines whether this device should be first reported device to
- * to scsi-ml or sas transport, this purpose is for persistent boot device.
- * There are primary, alternate, and current entries in bios page 2. The order
- * priority is primary, alternate, then current. This routine saves
- * the corresponding device object and is_raid flag in the ioc object.
- * The saved data to be used later in _scsih_probe_boot_devices().
- */
-static void
-_scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
- void *device, u8 is_raid)
-{
- struct _sas_device *sas_device;
- struct _raid_device *raid_device;
- u64 sas_address;
- u64 device_name;
- u64 enclosure_logical_id;
- u16 slot;
-
- /* only process this function when driver loads */
- if (!ioc->is_driver_loading)
- return;
-
- /* no Bios, return immediately */
- if (!ioc->bios_pg3.BiosVersion)
- return;
-
- if (!is_raid) {
- sas_device = device;
- sas_address = sas_device->sas_address;
- device_name = sas_device->device_name;
- enclosure_logical_id = sas_device->enclosure_logical_id;
- slot = sas_device->slot;
- } else {
- raid_device = device;
- sas_address = raid_device->wwid;
- device_name = 0;
- enclosure_logical_id = 0;
- slot = 0;
- }
-
- if (!ioc->req_boot_device.device) {
- if (_scsih_is_boot_device(sas_address, device_name,
- enclosure_logical_id, slot,
- (ioc->bios_pg2.ReqBootDeviceForm &
- MPI2_BIOSPAGE2_FORM_MASK),
- &ioc->bios_pg2.RequestedBootDevice)) {
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s: req_boot_device(0x%016llx)\n",
- ioc->name, __func__,
- (unsigned long long)sas_address));
- ioc->req_boot_device.device = device;
- ioc->req_boot_device.is_raid = is_raid;
- }
- }
-
- if (!ioc->req_alt_boot_device.device) {
- if (_scsih_is_boot_device(sas_address, device_name,
- enclosure_logical_id, slot,
- (ioc->bios_pg2.ReqAltBootDeviceForm &
- MPI2_BIOSPAGE2_FORM_MASK),
- &ioc->bios_pg2.RequestedAltBootDevice)) {
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s: req_alt_boot_device(0x%016llx)\n",
- ioc->name, __func__,
- (unsigned long long)sas_address));
- ioc->req_alt_boot_device.device = device;
- ioc->req_alt_boot_device.is_raid = is_raid;
- }
- }
-
- if (!ioc->current_boot_device.device) {
- if (_scsih_is_boot_device(sas_address, device_name,
- enclosure_logical_id, slot,
- (ioc->bios_pg2.CurrentBootDeviceForm &
- MPI2_BIOSPAGE2_FORM_MASK),
- &ioc->bios_pg2.CurrentBootDevice)) {
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s: current_boot_device(0x%016llx)\n",
- ioc->name, __func__,
- (unsigned long long)sas_address));
- ioc->current_boot_device.device = device;
- ioc->current_boot_device.is_raid = is_raid;
- }
- }
-}
-
-static struct _sas_device *
-__mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc,
- struct MPT2SAS_TARGET *tgt_priv)
-{
- struct _sas_device *ret;
-
- assert_spin_locked(&ioc->sas_device_lock);
-
- ret = tgt_priv->sdev;
- if (ret)
- sas_device_get(ret);
-
- return ret;
-}
-
-static struct _sas_device *
-mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc,
- struct MPT2SAS_TARGET *tgt_priv)
-{
- struct _sas_device *ret;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- ret = __mpt2sas_get_sdev_from_target(ioc, tgt_priv);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- return ret;
-}
-
-
-struct _sas_device *
-__mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address)
-{
- struct _sas_device *sas_device;
-
- assert_spin_locked(&ioc->sas_device_lock);
-
- list_for_each_entry(sas_device, &ioc->sas_device_list, list)
- if (sas_device->sas_address == sas_address)
- goto found_device;
-
- list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
- if (sas_device->sas_address == sas_address)
- goto found_device;
-
- return NULL;
-
-found_device:
- sas_device_get(sas_device);
- return sas_device;
-}
-
-/**
- * mpt2sas_get_sdev_by_addr - sas device search
- * @ioc: per adapter object
- * @sas_address: sas address
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-struct _sas_device *
-mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address)
-{
- struct _sas_device *sas_device;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- return sas_device;
-}
-
-static struct _sas_device *
-__mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _sas_device *sas_device;
-
- assert_spin_locked(&ioc->sas_device_lock);
-
- list_for_each_entry(sas_device, &ioc->sas_device_list, list)
- if (sas_device->handle == handle)
- goto found_device;
-
- list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
- if (sas_device->handle == handle)
- goto found_device;
-
- return NULL;
-
-found_device:
- sas_device_get(sas_device);
- return sas_device;
-}
-
-/**
- * mpt2sas_get_sdev_by_handle - sas device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-static struct _sas_device *
-mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _sas_device *sas_device;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- return sas_device;
-}
-
-/**
- * _scsih_sas_device_remove - remove sas_device from list.
- * @ioc: per adapter object
- * @sas_device: the sas_device object
- * Context: This function will acquire ioc->sas_device_lock.
- *
- * If sas_device is on the list, remove it and decrement its reference count.
- */
-static void
-_scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device)
-{
- unsigned long flags;
-
- if (!sas_device)
- return;
-
- /*
- * The lock serializes access to the list, but we still need to verify
- * that nobody removed the entry while we were waiting on the lock.
- */
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- if (!list_empty(&sas_device->list)) {
- list_del_init(&sas_device->list);
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-
-/**
- * _scsih_sas_device_add - insert sas_device to the list.
- * @ioc: per adapter object
- * @sas_device: the sas_device object
- * Context: This function will acquire ioc->sas_device_lock.
- *
- * Adding new object to the ioc->sas_device_list.
- */
-static void
-_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device)
-{
- unsigned long flags;
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
- "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device->handle, (unsigned long long)sas_device->sas_address));
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device_get(sas_device);
- list_add_tail(&sas_device->list, &ioc->sas_device_list);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
- sas_device->sas_address_parent)) {
- _scsih_sas_device_remove(ioc, sas_device);
- } else if (!sas_device->starget) {
- /* When asyn scanning is enabled, its not possible to remove
- * devices while scanning is turned on due to an oops in
- * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
- */
- if (!ioc->is_driver_loading) {
- mpt2sas_transport_port_remove(ioc,
- sas_device->sas_address,
- sas_device->sas_address_parent);
- _scsih_sas_device_remove(ioc, sas_device);
- }
- }
-}
-
-/**
- * _scsih_sas_device_init_add - insert sas_device to the list.
- * @ioc: per adapter object
- * @sas_device: the sas_device object
- * Context: This function will acquire ioc->sas_device_lock.
- *
- * Adding new object at driver load time to the ioc->sas_device_init_list.
- */
-static void
-_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device)
-{
- unsigned long flags;
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
- "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device->handle, (unsigned long long)sas_device->sas_address));
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device_get(sas_device);
- list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
- _scsih_determine_boot_device(ioc, sas_device, 0);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-/**
- * _scsih_raid_device_find_by_id - raid device search
- * @ioc: per adapter object
- * @id: sas device target id
- * @channel: sas device channel
- * Context: Calling function should acquire ioc->raid_device_lock
- *
- * This searches for raid_device based on target id, then return raid_device
- * object.
- */
-static struct _raid_device *
-_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel)
-{
- struct _raid_device *raid_device, *r;
-
- r = NULL;
- list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
- if (raid_device->id == id && raid_device->channel == channel) {
- r = raid_device;
- goto out;
- }
- }
-
- out:
- return r;
-}
-
-/**
- * _scsih_raid_device_find_by_handle - raid device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->raid_device_lock
- *
- * This searches for raid_device based on handle, then return raid_device
- * object.
- */
-static struct _raid_device *
-_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _raid_device *raid_device, *r;
-
- r = NULL;
- list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
- if (raid_device->handle != handle)
- continue;
- r = raid_device;
- goto out;
- }
-
- out:
- return r;
-}
-
-/**
- * _scsih_raid_device_find_by_wwid - raid device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->raid_device_lock
- *
- * This searches for raid_device based on wwid, then return raid_device
- * object.
- */
-static struct _raid_device *
-_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid)
-{
- struct _raid_device *raid_device, *r;
-
- r = NULL;
- list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
- if (raid_device->wwid != wwid)
- continue;
- r = raid_device;
- goto out;
- }
-
- out:
- return r;
-}
-
-/**
- * _scsih_raid_device_add - add raid_device object
- * @ioc: per adapter object
- * @raid_device: raid_device object
- *
- * This is added to the raid_device_list link list.
- */
-static void
-_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
- struct _raid_device *raid_device)
-{
- unsigned long flags;
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
- "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
- raid_device->handle, (unsigned long long)raid_device->wwid));
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- list_add_tail(&raid_device->list, &ioc->raid_device_list);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * _scsih_raid_device_remove - delete raid_device object
- * @ioc: per adapter object
- * @raid_device: raid_device object
- *
- */
-static void
-_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
- struct _raid_device *raid_device)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- list_del(&raid_device->list);
- kfree(raid_device);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * mpt2sas_scsih_expander_find_by_handle - expander device search
- * @ioc: per adapter object
- * @handle: expander handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for expander device based on handle, then returns the
- * sas_node object.
- */
-struct _sas_node *
-mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _sas_node *sas_expander, *r;
-
- r = NULL;
- list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
- if (sas_expander->handle != handle)
- continue;
- r = sas_expander;
- goto out;
- }
- out:
- return r;
-}
-
-/**
- * mpt2sas_scsih_expander_find_by_sas_address - expander device search
- * @ioc: per adapter object
- * @sas_address: sas address
- * Context: Calling function should acquire ioc->sas_node_lock.
- *
- * This searches for expander device based on sas_address, then returns the
- * sas_node object.
- */
-struct _sas_node *
-mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address)
-{
- struct _sas_node *sas_expander, *r;
-
- r = NULL;
- list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
- if (sas_expander->sas_address != sas_address)
- continue;
- r = sas_expander;
- goto out;
- }
- out:
- return r;
-}
-
-/**
- * _scsih_expander_node_add - insert expander device to the list.
- * @ioc: per adapter object
- * @sas_expander: the sas_device object
- * Context: This function will acquire ioc->sas_node_lock.
- *
- * Adding new object to the ioc->sas_expander_list.
- *
- * Return nothing.
- */
-static void
-_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_expander)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-}
-
-/**
- * _scsih_is_end_device - determines if device is an end device
- * @device_info: bitfield providing information about the device.
- * Context: none
- *
- * Returns 1 if end device.
- */
-static int
-_scsih_is_end_device(u32 device_info)
-{
- if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
- ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
- (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
- (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
- return 1;
- else
- return 0;
-}
-
-/**
- * _scsih_scsi_lookup_get - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- */
-static struct scsi_cmnd *
-_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- return ioc->scsi_lookup[smid - 1].scmd;
-}
-
-/**
- * _scsih_scsi_lookup_get_clear - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- * Then will derefrence the stored scmd pointer.
- */
-static inline struct scsi_cmnd *
-_scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- unsigned long flags;
- struct scsi_cmnd *scmd;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- scmd = ioc->scsi_lookup[smid - 1].scmd;
- ioc->scsi_lookup[smid - 1].scmd = NULL;
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
- return scmd;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_scmd - scmd lookup
- * @ioc: per adapter object
- * @smid: system request message index
- * @scmd: pointer to scsi command object
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a scmd pointer in the scsi_lookup array,
- * returning the revelent smid. A returned value of zero means invalid.
- */
-static u16
-_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
- *scmd)
-{
- u16 smid;
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- smid = 0;
- for (i = 0; i < ioc->scsiio_depth; i++) {
- if (ioc->scsi_lookup[i].scmd == scmd) {
- smid = ioc->scsi_lookup[i].smid;
- goto out;
- }
- }
- out:
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return smid;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_target - search for matching channel:id
- * @ioc: per adapter object
- * @id: target id
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
- int channel)
-{
- u8 found;
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- found = 0;
- for (i = 0 ; i < ioc->scsiio_depth; i++) {
- if (ioc->scsi_lookup[i].scmd &&
- (ioc->scsi_lookup[i].scmd->device->id == id &&
- ioc->scsi_lookup[i].scmd->device->channel == channel)) {
- found = 1;
- goto out;
- }
- }
- out:
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return found;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
- * @ioc: per adapter object
- * @id: target id
- * @lun: lun number
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id:lun in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
- unsigned int lun, int channel)
-{
- u8 found;
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- found = 0;
- for (i = 0 ; i < ioc->scsiio_depth; i++) {
- if (ioc->scsi_lookup[i].scmd &&
- (ioc->scsi_lookup[i].scmd->device->id == id &&
- ioc->scsi_lookup[i].scmd->device->channel == channel &&
- ioc->scsi_lookup[i].scmd->device->lun == lun)) {
- found = 1;
- goto out;
- }
- }
- out:
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return found;
-}
-
-/**
- * _scsih_get_chain_buffer_tracker - obtain chain tracker
- * @ioc: per adapter object
- * @smid: smid associated to an IO request
- *
- * Returns chain tracker(from ioc->free_chain_list)
- */
-static struct chain_tracker *
-_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- struct chain_tracker *chain_req;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- if (list_empty(&ioc->free_chain_list)) {
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not "
- "available\n", ioc->name));
- return NULL;
- }
- chain_req = list_entry(ioc->free_chain_list.next,
- struct chain_tracker, tracker_list);
- list_del_init(&chain_req->tracker_list);
- list_add_tail(&chain_req->tracker_list,
- &ioc->scsi_lookup[smid - 1].chain_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- return chain_req;
-}
-
-/**
- * _scsih_build_scatter_gather - main sg creation routine
- * @ioc: per adapter object
- * @scmd: scsi command
- * @smid: system request message index
- * Context: none.
- *
- * The main routine that builds scatter gather table from a given
- * scsi request sent via the .queuecommand main handler.
- *
- * Returns 0 success, anything else error
- */
-static int
-_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
- struct scsi_cmnd *scmd, u16 smid)
-{
- Mpi2SCSIIORequest_t *mpi_request;
- dma_addr_t chain_dma;
- struct scatterlist *sg_scmd;
- void *sg_local, *chain;
- u32 chain_offset;
- u32 chain_length;
- u32 chain_flags;
- int sges_left;
- u32 sges_in_segment;
- u32 sgl_flags;
- u32 sgl_flags_last_element;
- u32 sgl_flags_end_buffer;
- struct chain_tracker *chain_req;
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-
- /* init scatter gather flags */
- sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
- if (scmd->sc_data_direction == DMA_TO_DEVICE)
- sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
- sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
- << MPI2_SGE_FLAGS_SHIFT;
- sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
- << MPI2_SGE_FLAGS_SHIFT;
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-
- sg_scmd = scsi_sglist(scmd);
- sges_left = scsi_dma_map(scmd);
- if (sges_left < 0) {
- sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
- " failed: request for %d bytes!\n", scsi_bufflen(scmd));
- return -ENOMEM;
- }
-
- sg_local = &mpi_request->SGL;
- sges_in_segment = ioc->max_sges_in_main_message;
- if (sges_left <= sges_in_segment)
- goto fill_in_last_segment;
-
- mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
- (sges_in_segment * ioc->sge_size))/4;
-
- /* fill in main message segment when there is a chain following */
- while (sges_in_segment) {
- if (sges_in_segment == 1)
- ioc->base_add_sg_single(sg_local,
- sgl_flags_last_element | sg_dma_len(sg_scmd),
- sg_dma_address(sg_scmd));
- else
- ioc->base_add_sg_single(sg_local, sgl_flags |
- sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
- sg_scmd = sg_next(sg_scmd);
- sg_local += ioc->sge_size;
- sges_left--;
- sges_in_segment--;
- }
-
- /* initializing the chain flags and pointers */
- chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
- chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
- if (!chain_req)
- return -1;
- chain = chain_req->chain_buffer;
- chain_dma = chain_req->chain_buffer_dma;
- do {
- sges_in_segment = (sges_left <=
- ioc->max_sges_in_chain_message) ? sges_left :
- ioc->max_sges_in_chain_message;
- chain_offset = (sges_left == sges_in_segment) ?
- 0 : (sges_in_segment * ioc->sge_size)/4;
- chain_length = sges_in_segment * ioc->sge_size;
- if (chain_offset) {
- chain_offset = chain_offset <<
- MPI2_SGE_CHAIN_OFFSET_SHIFT;
- chain_length += ioc->sge_size;
- }
- ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
- chain_length, chain_dma);
- sg_local = chain;
- if (!chain_offset)
- goto fill_in_last_segment;
-
- /* fill in chain segments */
- while (sges_in_segment) {
- if (sges_in_segment == 1)
- ioc->base_add_sg_single(sg_local,
- sgl_flags_last_element |
- sg_dma_len(sg_scmd),
- sg_dma_address(sg_scmd));
- else
- ioc->base_add_sg_single(sg_local, sgl_flags |
- sg_dma_len(sg_scmd),
- sg_dma_address(sg_scmd));
- sg_scmd = sg_next(sg_scmd);
- sg_local += ioc->sge_size;
- sges_left--;
- sges_in_segment--;
- }
-
- chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
- if (!chain_req)
- return -1;
- chain = chain_req->chain_buffer;
- chain_dma = chain_req->chain_buffer_dma;
- } while (1);
-
-
- fill_in_last_segment:
-
- /* fill the last segment */
- while (sges_left) {
- if (sges_left == 1)
- ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
- sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
- else
- ioc->base_add_sg_single(sg_local, sgl_flags |
- sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
- sg_scmd = sg_next(sg_scmd);
- sg_local += ioc->sge_size;
- sges_left--;
- }
-
- return 0;
-}
-
-/**
- * _scsih_change_queue_depth - setting device queue depth
- * @sdev: scsi device struct
- * @qdepth: requested queue depth
- *
- * Returns queue depth.
- */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
-{
- struct Scsi_Host *shost = sdev->host;
- int max_depth;
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct _sas_device *sas_device;
- unsigned long flags;
-
- max_depth = shost->can_queue;
-
- /* limit max device queue for SATA to 32 */
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- goto not_sata;
- sas_target_priv_data = sas_device_priv_data->sas_target;
- if (!sas_target_priv_data)
- goto not_sata;
- if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
- goto not_sata;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data);
- if (sas_device) {
- if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- max_depth = MPT2SAS_SATA_QUEUE_DEPTH;
-
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- not_sata:
- if (!sdev->tagged_supported)
- max_depth = 1;
- if (qdepth > max_depth)
- qdepth = max_depth;
- return scsi_change_queue_depth(sdev, qdepth);
-}
-
-/**
- * _scsih_target_alloc - target add routine
- * @starget: scsi target struct
- *
- * Returns 0 if ok. Any other return is assumed to be an error and
- * the device is ignored.
- */
-static int
-_scsih_target_alloc(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(&starget->dev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct _sas_device *sas_device;
- struct _raid_device *raid_device;
- unsigned long flags;
- struct sas_rphy *rphy;
-
- sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
- GFP_KERNEL);
- if (!sas_target_priv_data)
- return -ENOMEM;
-
- starget->hostdata = sas_target_priv_data;
- sas_target_priv_data->starget = starget;
- sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
-
- /* RAID volumes */
- if (starget->channel == RAID_CHANNEL) {
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
- starget->channel);
- if (raid_device) {
- sas_target_priv_data->handle = raid_device->handle;
- sas_target_priv_data->sas_address = raid_device->wwid;
- sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
- if (ioc->is_warpdrive)
- sas_target_priv_data->raid_device = raid_device;
- raid_device->starget = starget;
- }
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- return 0;
- }
-
- /* sas/sata devices */
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- rphy = dev_to_rphy(starget->dev.parent);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- rphy->identify.sas_address);
-
- if (sas_device) {
- sas_target_priv_data->handle = sas_device->handle;
- sas_target_priv_data->sas_address = sas_device->sas_address;
- sas_target_priv_data->sdev = sas_device;
- sas_device->starget = starget;
- sas_device->id = starget->id;
- sas_device->channel = starget->channel;
- if (test_bit(sas_device->handle, ioc->pd_handles))
- sas_target_priv_data->flags |=
- MPT_TARGET_FLAGS_RAID_COMPONENT;
-
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- return 0;
-}
-
-/**
- * _scsih_target_destroy - target destroy routine
- * @starget: scsi target struct
- *
- * Returns nothing.
- */
-static void
-_scsih_target_destroy(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(&starget->dev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct _sas_device *sas_device;
- struct _raid_device *raid_device;
- unsigned long flags;
- struct sas_rphy *rphy;
-
- sas_target_priv_data = starget->hostdata;
- if (!sas_target_priv_data)
- return;
-
- if (starget->channel == RAID_CHANNEL) {
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
- starget->channel);
- if (raid_device) {
- raid_device->starget = NULL;
- raid_device->sdev = NULL;
- }
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- goto out;
- }
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- rphy = dev_to_rphy(starget->dev.parent);
- sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data);
- if (sas_device && (sas_device->starget == starget) &&
- (sas_device->id == starget->id) &&
- (sas_device->channel == starget->channel))
- sas_device->starget = NULL;
-
- if (sas_device) {
- /*
- * Corresponding get() is in _scsih_target_alloc()
- */
- sas_target_priv_data->sdev = NULL;
- sas_device_put(sas_device);
-
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- out:
- kfree(sas_target_priv_data);
- starget->hostdata = NULL;
-}
-
-/**
- * _scsih_slave_alloc - device add routine
- * @sdev: scsi device struct
- *
- * Returns 0 if ok. Any other return is assumed to be an error and
- * the device is ignored.
- */
-static int
-_scsih_slave_alloc(struct scsi_device *sdev)
-{
- struct Scsi_Host *shost;
- struct MPT2SAS_ADAPTER *ioc;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_target *starget;
- struct _raid_device *raid_device;
- struct _sas_device *sas_device;
- unsigned long flags;
-
- sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
- GFP_KERNEL);
- if (!sas_device_priv_data)
- return -ENOMEM;
-
- sas_device_priv_data->lun = sdev->lun;
- sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
-
- starget = scsi_target(sdev);
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->num_luns++;
- sas_device_priv_data->sas_target = sas_target_priv_data;
- sdev->hostdata = sas_device_priv_data;
- if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
- sdev->no_uld_attach = 1;
-
- shost = dev_to_shost(&starget->dev);
- ioc = shost_priv(shost);
- if (starget->channel == RAID_CHANNEL) {
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_id(ioc,
- starget->id, starget->channel);
- if (raid_device)
- raid_device->sdev = sdev; /* raid is single lun */
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- }
-
- if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- sas_target_priv_data->sas_address);
- if (sas_device && (sas_device->starget == NULL)) {
- sdev_printk(KERN_INFO, sdev,
- "%s : sas_device->starget set to starget @ %d\n",
- __func__, __LINE__);
- sas_device->starget = starget;
- }
-
- if (sas_device)
- sas_device_put(sas_device);
-
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- }
-
- return 0;
-}
-
-/**
- * _scsih_slave_destroy - device destroy routine
- * @sdev: scsi device struct
- *
- * Returns nothing.
- */
-static void
-_scsih_slave_destroy(struct scsi_device *sdev)
-{
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct scsi_target *starget;
- struct Scsi_Host *shost;
- struct MPT2SAS_ADAPTER *ioc;
- struct _sas_device *sas_device;
- unsigned long flags;
-
- if (!sdev->hostdata)
- return;
-
- starget = scsi_target(sdev);
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->num_luns--;
-
- shost = dev_to_shost(&starget->dev);
- ioc = shost_priv(shost);
-
- if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_from_target(ioc,
- sas_target_priv_data);
- if (sas_device && !sas_target_priv_data->num_luns)
- sas_device->starget = NULL;
-
- if (sas_device)
- sas_device_put(sas_device);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- }
-
- kfree(sdev->hostdata);
- sdev->hostdata = NULL;
-}
-
-/**
- * _scsih_display_sata_capabilities - sata capabilities
- * @ioc: per adapter object
- * @handle: device handle
- * @sdev: scsi device struct
- */
-static void
-_scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
- u16 handle, struct scsi_device *sdev)
-{
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasDevicePage0_t sas_device_pg0;
- u32 ioc_status;
- u16 flags;
- u32 device_info;
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- flags = le16_to_cpu(sas_device_pg0.Flags);
- device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-
- sdev_printk(KERN_INFO, sdev,
- "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
- "sw_preserve(%s)\n",
- (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
- (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
- (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
- "n",
- (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
- (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
- (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
-}
-
-/**
- * _scsih_is_raid - return boolean indicating device is raid volume
- * @dev the device struct object
- */
-static int
-_scsih_is_raid(struct device *dev)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
-
- if (ioc->is_warpdrive)
- return 0;
- return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
-}
-
-/**
- * _scsih_get_resync - get raid volume resync percent complete
- * @dev the device struct object
- */
-static void
-_scsih_get_resync(struct device *dev)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
- static struct _raid_device *raid_device;
- unsigned long flags;
- Mpi2RaidVolPage0_t vol_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u32 volume_status_flags;
- u8 percent_complete;
- u16 handle;
-
- percent_complete = 0;
- handle = 0;
- if (ioc->is_warpdrive)
- goto out;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
- sdev->channel);
- if (raid_device) {
- handle = raid_device->handle;
- percent_complete = raid_device->percent_complete;
- }
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
- if (!handle)
- goto out;
-
- if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
- sizeof(Mpi2RaidVolPage0_t))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- percent_complete = 0;
- goto out;
- }
-
- volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
- if (!(volume_status_flags &
- MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
- percent_complete = 0;
-
- out:
- raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
-}
-
-/**
- * _scsih_get_state - get raid volume level
- * @dev the device struct object
- */
-static void
-_scsih_get_state(struct device *dev)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
- static struct _raid_device *raid_device;
- unsigned long flags;
- Mpi2RaidVolPage0_t vol_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u32 volstate;
- enum raid_state state = RAID_STATE_UNKNOWN;
- u16 handle = 0;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
- sdev->channel);
- if (raid_device)
- handle = raid_device->handle;
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
- if (!raid_device)
- goto out;
-
- if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
- sizeof(Mpi2RaidVolPage0_t))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
-
- volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
- if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
- state = RAID_STATE_RESYNCING;
- goto out;
- }
-
- switch (vol_pg0.VolumeState) {
- case MPI2_RAID_VOL_STATE_OPTIMAL:
- case MPI2_RAID_VOL_STATE_ONLINE:
- state = RAID_STATE_ACTIVE;
- break;
- case MPI2_RAID_VOL_STATE_DEGRADED:
- state = RAID_STATE_DEGRADED;
- break;
- case MPI2_RAID_VOL_STATE_FAILED:
- case MPI2_RAID_VOL_STATE_MISSING:
- state = RAID_STATE_OFFLINE;
- break;
- }
- out:
- raid_set_state(mpt2sas_raid_template, dev, state);
-}
-
-/**
- * _scsih_set_level - set raid level
- * @sdev: scsi device struct
- * @volume_type: volume type
- */
-static void
-_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
-{
- enum raid_level level = RAID_LEVEL_UNKNOWN;
-
- switch (volume_type) {
- case MPI2_RAID_VOL_TYPE_RAID0:
- level = RAID_LEVEL_0;
- break;
- case MPI2_RAID_VOL_TYPE_RAID10:
- level = RAID_LEVEL_10;
- break;
- case MPI2_RAID_VOL_TYPE_RAID1E:
- level = RAID_LEVEL_1E;
- break;
- case MPI2_RAID_VOL_TYPE_RAID1:
- level = RAID_LEVEL_1;
- break;
- }
-
- raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level);
-}
-
-/**
- * _scsih_get_volume_capabilities - volume capabilities
- * @ioc: per adapter object
- * @sas_device: the raid_device object
- *
- * Returns 0 for success, else 1
- */
-static int
-_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
- struct _raid_device *raid_device)
-{
- Mpi2RaidVolPage0_t *vol_pg0;
- Mpi2RaidPhysDiskPage0_t pd_pg0;
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u16 sz;
- u8 num_pds;
-
- if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
- &num_pds)) || !num_pds) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
- __func__));
- return 1;
- }
-
- raid_device->num_pds = num_pds;
- sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
- sizeof(Mpi2RaidVol0PhysDisk_t));
- vol_pg0 = kzalloc(sz, GFP_KERNEL);
- if (!vol_pg0) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
- __func__));
- return 1;
- }
-
- if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
- __func__));
- kfree(vol_pg0);
- return 1;
- }
-
- raid_device->volume_type = vol_pg0->VolumeType;
-
- /* figure out what the underlying devices are by
- * obtaining the device_info bits for the 1st device
- */
- if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
- &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
- vol_pg0->PhysDisk[0].PhysDiskNum))) {
- if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
- &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
- le16_to_cpu(pd_pg0.DevHandle)))) {
- raid_device->device_info =
- le32_to_cpu(sas_device_pg0.DeviceInfo);
- }
- }
-
- kfree(vol_pg0);
- return 0;
-}
-/**
- * _scsih_disable_ddio - Disable direct I/O for all the volumes
- * @ioc: per adapter object
- */
-static void
-_scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2RaidVolPage1_t vol_pg1;
- Mpi2ConfigReply_t mpi_reply;
- struct _raid_device *raid_device;
- u16 handle;
- u16 ioc_status;
- unsigned long flags;
-
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
- &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- break;
- handle = le16_to_cpu(vol_pg1.DevHandle);
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- if (raid_device)
- raid_device->direct_io_enabled = 0;
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- }
- return;
-}
-
-
-/**
- * _scsih_get_num_volumes - Get number of volumes in the ioc
- * @ioc: per adapter object
- */
-static u8
-_scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2RaidVolPage1_t vol_pg1;
- Mpi2ConfigReply_t mpi_reply;
- u16 handle;
- u8 vol_cnt = 0;
- u16 ioc_status;
-
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
- &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- break;
- vol_cnt++;
- handle = le16_to_cpu(vol_pg1.DevHandle);
- }
- return vol_cnt;
-}
-
-
-/**
- * _scsih_init_warpdrive_properties - Set properties for warpdrive direct I/O.
- * @ioc: per adapter object
- * @raid_device: the raid_device object
- */
-static void
-_scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
- struct _raid_device *raid_device)
-{
- Mpi2RaidVolPage0_t *vol_pg0;
- Mpi2RaidPhysDiskPage0_t pd_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u16 sz;
- u8 num_pds, count;
- unsigned long stripe_sz, block_sz;
- u8 stripe_exp, block_exp;
- u64 dev_max_lba;
-
- if (!ioc->is_warpdrive)
- return;
-
- if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "globally as drives are exposed\n", ioc->name);
- return;
- }
- if (_scsih_get_num_volumes(ioc) > 1) {
- _scsih_disable_ddio(ioc);
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "globally as number of drives > 1\n", ioc->name);
- return;
- }
- if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
- &num_pds)) || !num_pds) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "Failure in computing number of drives\n", ioc->name);
- return;
- }
-
- sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
- sizeof(Mpi2RaidVol0PhysDisk_t));
- vol_pg0 = kzalloc(sz, GFP_KERNEL);
- if (!vol_pg0) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "Memory allocation failure for RVPG0\n", ioc->name);
- return;
- }
-
- if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "Failure in retrieving RVPG0\n", ioc->name);
- kfree(vol_pg0);
- return;
- }
-
- /*
- * WARPDRIVE:If number of physical disks in a volume exceeds the max pds
- * assumed for WARPDRIVE, disable direct I/O
- */
- if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
- printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled "
- "for the drive with handle(0x%04x): num_mem=%d, "
- "max_mem_allowed=%d\n", ioc->name, raid_device->handle,
- num_pds, MPT_MAX_WARPDRIVE_PDS);
- kfree(vol_pg0);
- return;
- }
- for (count = 0; count < num_pds; count++) {
- if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
- &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
- vol_pg0->PhysDisk[count].PhysDiskNum) ||
- le16_to_cpu(pd_pg0.DevHandle) ==
- MPT2SAS_INVALID_DEVICE_HANDLE) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
- "disabled for the drive with handle(0x%04x) member"
- "handle retrieval failed for member number=%d\n",
- ioc->name, raid_device->handle,
- vol_pg0->PhysDisk[count].PhysDiskNum);
- goto out_error;
- }
- /* Disable direct I/O if member drive lba exceeds 4 bytes */
- dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA);
- if (dev_max_lba >> 32) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
- "disabled for the drive with handle(0x%04x) member"
- "handle (0x%04x) unsupported max lba 0x%016llx\n",
- ioc->name, raid_device->handle,
- le16_to_cpu(pd_pg0.DevHandle),
- (unsigned long long)dev_max_lba);
- goto out_error;
- }
-
- raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
- }
-
- /*
- * Assumption for WD: Direct I/O is not supported if the volume is
- * not RAID0
- */
- if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "for the drive with handle(0x%04x): type=%d, "
- "s_sz=%uK, blk_size=%u\n", ioc->name,
- raid_device->handle, raid_device->volume_type,
- (le32_to_cpu(vol_pg0->StripeSize) *
- le16_to_cpu(vol_pg0->BlockSize)) / 1024,
- le16_to_cpu(vol_pg0->BlockSize));
- goto out_error;
- }
-
- stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
- stripe_exp = find_first_bit(&stripe_sz, 32);
- if (stripe_exp == 32) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "for the drive with handle(0x%04x) invalid stripe sz %uK\n",
- ioc->name, raid_device->handle,
- (le32_to_cpu(vol_pg0->StripeSize) *
- le16_to_cpu(vol_pg0->BlockSize)) / 1024);
- goto out_error;
- }
- raid_device->stripe_exponent = stripe_exp;
- block_sz = le16_to_cpu(vol_pg0->BlockSize);
- block_exp = find_first_bit(&block_sz, 16);
- if (block_exp == 16) {
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
- "for the drive with handle(0x%04x) invalid block sz %u\n",
- ioc->name, raid_device->handle,
- le16_to_cpu(vol_pg0->BlockSize));
- goto out_error;
- }
- raid_device->block_exponent = block_exp;
- raid_device->direct_io_enabled = 1;
-
- printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive"
- " with handle(0x%04x)\n", ioc->name, raid_device->handle);
- /*
- * WARPDRIVE: Though the following fields are not used for direct IO,
- * stored for future purpose:
- */
- raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
- raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
- raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
-
-
- kfree(vol_pg0);
- return;
-
-out_error:
- raid_device->direct_io_enabled = 0;
- for (count = 0; count < num_pds; count++)
- raid_device->pd_handle[count] = 0;
- kfree(vol_pg0);
- return;
-}
-
-/**
- * _scsih_enable_tlr - setting TLR flags
- * @ioc: per adapter object
- * @sdev: scsi device struct
- *
- * Enabling Transaction Layer Retries for tape devices when
- * vpd page 0x90 is present
- *
- */
-static void
-_scsih_enable_tlr(struct MPT2SAS_ADAPTER *ioc, struct scsi_device *sdev)
-{
- /* only for TAPE */
- if (sdev->type != TYPE_TAPE)
- return;
-
- if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
- return;
-
- sas_enable_tlr(sdev);
- sdev_printk(KERN_INFO, sdev, "TLR %s\n",
- sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
- return;
-
-}
-
-/**
- * _scsih_slave_configure - device configure routine.
- * @sdev: scsi device struct
- *
- * Returns 0 if ok. Any other return is assumed to be an error and
- * the device is ignored.
- */
-static int
-_scsih_slave_configure(struct scsi_device *sdev)
-{
- struct Scsi_Host *shost = sdev->host;
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct _sas_device *sas_device;
- struct _raid_device *raid_device;
- unsigned long flags;
- int qdepth;
- u8 ssp_target = 0;
- char *ds = "";
- char *r_level = "";
- u16 handle, volume_handle = 0;
- u64 volume_wwid = 0;
-
- qdepth = 1;
- sas_device_priv_data = sdev->hostdata;
- sas_device_priv_data->configured_lun = 1;
- sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
- sas_target_priv_data = sas_device_priv_data->sas_target;
- handle = sas_target_priv_data->handle;
-
- /* raid volume handling */
- if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (!raid_device) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
- __LINE__, __func__));
- return 1;
- }
-
- if (_scsih_get_volume_capabilities(ioc, raid_device)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
- __LINE__, __func__));
- return 1;
- }
- /*
- * WARPDRIVE: Initialize the required data for Direct IO
- */
- _scsih_init_warpdrive_properties(ioc, raid_device);
-
- /* RAID Queue Depth Support
- * IS volume = underlying qdepth of drive type, either
- * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
- * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH)
- */
- if (raid_device->device_info &
- MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
- qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
- ds = "SSP";
- } else {
- qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
- if (raid_device->device_info &
- MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- ds = "SATA";
- else
- ds = "STP";
- }
-
- switch (raid_device->volume_type) {
- case MPI2_RAID_VOL_TYPE_RAID0:
- r_level = "RAID0";
- break;
- case MPI2_RAID_VOL_TYPE_RAID1E:
- qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
- if (ioc->manu_pg10.OEMIdentifier &&
- (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
- MFG10_GF0_R10_DISPLAY) &&
- !(raid_device->num_pds % 2))
- r_level = "RAID10";
- else
- r_level = "RAID1E";
- break;
- case MPI2_RAID_VOL_TYPE_RAID1:
- qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
- r_level = "RAID1";
- break;
- case MPI2_RAID_VOL_TYPE_RAID10:
- qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
- r_level = "RAID10";
- break;
- case MPI2_RAID_VOL_TYPE_UNKNOWN:
- default:
- qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
- r_level = "RAIDX";
- break;
- }
-
- if (!ioc->hide_ir_msg)
- sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
- "wwid(0x%016llx), pd_count(%d), type(%s)\n",
- r_level, raid_device->handle,
- (unsigned long long)raid_device->wwid,
- raid_device->num_pds, ds);
- _scsih_change_queue_depth(sdev, qdepth);
- /* raid transport support */
- if (!ioc->is_warpdrive)
- _scsih_set_level(sdev, raid_device->volume_type);
- return 0;
- }
-
- /* non-raid handling */
- if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
- if (mpt2sas_config_get_volume_handle(ioc, handle,
- &volume_handle)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__));
- return 1;
- }
- if (volume_handle && mpt2sas_config_get_volume_wwid(ioc,
- volume_handle, &volume_wwid)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__));
- return 1;
- }
- }
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- sas_device_priv_data->sas_target->sas_address);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
- __LINE__, __func__));
- return 1;
- }
- sas_device->volume_handle = volume_handle;
- sas_device->volume_wwid = volume_wwid;
- if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
- qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
- ssp_target = 1;
- ds = "SSP";
- } else {
- qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
- if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
- ds = "STP";
- else if (sas_device->device_info &
- MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- ds = "SATA";
- }
- sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
- "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
- ds, sas_device->handle,
- (unsigned long long)sas_device->sas_address,
- sas_device->phy,
- (unsigned long long)sas_device->device_name);
- sdev_printk(KERN_INFO, sdev, "%s: "
- "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
- (unsigned long long) sas_device->enclosure_logical_id,
- sas_device->slot);
-
- sas_device_put(sas_device);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!ssp_target)
- _scsih_display_sata_capabilities(ioc, handle, sdev);
-
- _scsih_change_queue_depth(sdev, qdepth);
-
- if (ssp_target) {
- sas_read_port_mode_page(sdev);
- _scsih_enable_tlr(ioc, sdev);
- }
-
- return 0;
-}
-
-/**
- * _scsih_bios_param - fetch head, sector, cylinder info for a disk
- * @sdev: scsi device struct
- * @bdev: pointer to block device context
- * @capacity: device size (in 512 byte sectors)
- * @params: three element array to place output:
- * params[0] number of heads (max 255)
- * params[1] number of sectors (max 63)
- * params[2] number of cylinders
- *
- * Return nothing.
- */
-static int
-_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
- sector_t capacity, int params[])
-{
- int heads;
- int sectors;
- sector_t cylinders;
- ulong dummy;
-
- heads = 64;
- sectors = 32;
-
- dummy = heads * sectors;
- cylinders = capacity;
- sector_div(cylinders, dummy);
-
- /*
- * Handle extended translation size for logical drives
- * > 1Gb
- */
- if ((ulong)capacity >= 0x200000) {
- heads = 255;
- sectors = 63;
- dummy = heads * sectors;
- cylinders = capacity;
- sector_div(cylinders, dummy);
- }
-
- /* return result */
- params[0] = heads;
- params[1] = sectors;
- params[2] = cylinders;
-
- return 0;
-}
-
-/**
- * _scsih_response_code - translation of device response code
- * @ioc: per adapter object
- * @response_code: response code returned by the device
- *
- * Return nothing.
- */
-static void
-_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
-{
- char *desc;
-
- switch (response_code) {
- case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
- desc = "task management request completed";
- break;
- case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
- desc = "invalid frame";
- break;
- case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
- desc = "task management request not supported";
- break;
- case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
- desc = "task management request failed";
- break;
- case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
- desc = "task management request succeeded";
- break;
- case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
- desc = "invalid lun";
- break;
- case 0xA:
- desc = "overlapped tag attempted";
- break;
- case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
- desc = "task queued, however not sent to target";
- break;
- default:
- desc = "unknown";
- break;
- }
- printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n",
- ioc->name, response_code, desc);
-}
-
-/**
- * _scsih_tm_done - tm completion routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: none.
- *
- * The callback handler when using scsih_issue_tm.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
-
- if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
- if (ioc->tm_cmds.smid != smid)
- return 1;
- mpt2sas_base_flush_reply_queues(ioc);
- ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (mpi_reply) {
- memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
- ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID;
- }
- ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
- complete(&ioc->tm_cmds.done);
- return 1;
-}
-
-/**
- * mpt2sas_scsih_set_tm_flag - set per target tm_busy
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During taskmangement request, we need to freeze the device queue.
- */
-void
-mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
- u8 skip = 0;
-
- shost_for_each_device(sdev, ioc->shost) {
- if (skip)
- continue;
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- continue;
- if (sas_device_priv_data->sas_target->handle == handle) {
- sas_device_priv_data->sas_target->tm_busy = 1;
- skip = 1;
- ioc->ignore_loginfos = 1;
- }
- }
-}
-
-/**
- * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During taskmangement request, we need to freeze the device queue.
- */
-void
-mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
- u8 skip = 0;
-
- shost_for_each_device(sdev, ioc->shost) {
- if (skip)
- continue;
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- continue;
- if (sas_device_priv_data->sas_target->handle == handle) {
- sas_device_priv_data->sas_target->tm_busy = 0;
- skip = 1;
- ioc->ignore_loginfos = 0;
- }
- }
-}
-
-
-/**
- * mpt2sas_scsih_issue_tm - main routine for sending tm requests
- * @ioc: per adapter struct
- * @device_handle: device handle
- * @channel: the channel assigned by the OS
- * @id: the id assigned by the OS
- * @lun: lun number
- * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
- * @smid_task: smid assigned to the task
- * @timeout: timeout in seconds
- * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
- * Context: user
- *
- * A generic API for sending task management requests to firmware.
- *
- * The callback index is set inside `ioc->tm_cb_idx`.
- *
- * Return SUCCESS or FAILED.
- */
-int
-mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
- uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
- enum mutex_type m_type)
-{
- Mpi2SCSITaskManagementRequest_t *mpi_request;
- Mpi2SCSITaskManagementReply_t *mpi_reply;
- u16 smid = 0;
- u32 ioc_state;
- unsigned long timeleft;
- struct scsiio_tracker *scsi_lookup = NULL;
- int rc;
-
- if (m_type == TM_MUTEX_ON)
- mutex_lock(&ioc->tm_cmds.mutex);
- if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
- __func__, ioc->name);
- rc = FAILED;
- goto err_out;
- }
-
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
- printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
- __func__, ioc->name);
- rc = FAILED;
- goto err_out;
- }
-
- ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
- if (ioc_state & MPI2_DOORBELL_USED) {
- dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
- "active!\n", ioc->name));
- rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- rc = (!rc) ? SUCCESS : FAILED;
- goto err_out;
- }
-
- if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- mpt2sas_base_fault_info(ioc, ioc_state &
- MPI2_DOORBELL_DATA_MASK);
- rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- rc = (!rc) ? SUCCESS : FAILED;
- goto err_out;
- }
-
- smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = FAILED;
- goto err_out;
- }
-
- if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
- scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
-
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
- " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
- smid_task));
- ioc->tm_cmds.status = MPT2_CMD_PENDING;
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->tm_cmds.smid = smid;
- memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
- memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
- mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
- mpi_request->DevHandle = cpu_to_le16(handle);
- mpi_request->TaskType = type;
- mpi_request->TaskMID = cpu_to_le16(smid_task);
- int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
- mpt2sas_scsih_set_tm_flag(ioc, handle);
- init_completion(&ioc->tm_cmds.done);
- mpt2sas_base_put_smid_hi_priority(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
- if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SCSITaskManagementRequest_t)/4);
- if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
- rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- rc = (!rc) ? SUCCESS : FAILED;
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- mpt2sas_scsih_clear_tm_flag(ioc, handle);
- goto err_out;
- }
- }
-
- if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) {
- mpi_reply = ioc->tm_cmds.reply;
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: "
- "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo),
- le32_to_cpu(mpi_reply->TerminationCount)));
- if (ioc->logging_level & MPT_DEBUG_TM) {
- _scsih_response_code(ioc, mpi_reply->ResponseCode);
- if (mpi_reply->IOCStatus)
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SCSITaskManagementRequest_t)/4);
- }
- }
-
- switch (type) {
- case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
- rc = SUCCESS;
- if (scsi_lookup->scmd == NULL)
- break;
- rc = FAILED;
- break;
-
- case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
- if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
- rc = FAILED;
- else
- rc = SUCCESS;
- break;
-
- case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
- case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
- if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
- rc = FAILED;
- else
- rc = SUCCESS;
- break;
- case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
- rc = SUCCESS;
- break;
- default:
- rc = FAILED;
- break;
- }
-
- mpt2sas_scsih_clear_tm_flag(ioc, handle);
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- if (m_type == TM_MUTEX_ON)
- mutex_unlock(&ioc->tm_cmds.mutex);
-
- return rc;
-
- err_out:
- if (m_type == TM_MUTEX_ON)
- mutex_unlock(&ioc->tm_cmds.mutex);
- return rc;
-}
-
-/**
- * _scsih_tm_display_info - displays info about the device
- * @ioc: per adapter struct
- * @scmd: pointer to scsi command object
- *
- * Called by task management callback handlers.
- */
-static void
-_scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
-{
- struct scsi_target *starget = scmd->device->sdev_target;
- struct MPT2SAS_TARGET *priv_target = starget->hostdata;
- struct _sas_device *sas_device = NULL;
- unsigned long flags;
- char *device_str = NULL;
-
- if (!priv_target)
- return;
- if (ioc->hide_ir_msg)
- device_str = "WarpDrive";
- else
- device_str = "volume";
-
- scsi_print_command(scmd);
- if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
- starget_printk(KERN_INFO, starget, "%s handle(0x%04x), "
- "%s wwid(0x%016llx)\n", device_str, priv_target->handle,
- device_str, (unsigned long long)priv_target->sas_address);
- } else {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_from_target(ioc, priv_target);
- if (sas_device) {
- if (priv_target->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT) {
- starget_printk(KERN_INFO, starget,
- "volume handle(0x%04x), "
- "volume wwid(0x%016llx)\n",
- sas_device->volume_handle,
- (unsigned long long)sas_device->volume_wwid);
- }
- starget_printk(KERN_INFO, starget,
- "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
- sas_device->handle,
- (unsigned long long)sas_device->sas_address,
- sas_device->phy);
- starget_printk(KERN_INFO, starget,
- "enclosure_logical_id(0x%016llx), slot(%d)\n",
- (unsigned long long)sas_device->enclosure_logical_id,
- sas_device->slot);
-
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- }
-}
-
-/**
- * _scsih_abort - eh threads main abort routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_abort(struct scsi_cmnd *scmd)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- u16 smid;
- u16 handle;
- int r;
-
- sdev_printk(KERN_INFO, scmd->device, "attempting task abort! "
- "scmd(%p)\n", scmd);
- _scsih_tm_display_info(ioc, scmd);
-
- sas_device_priv_data = scmd->device->hostdata;
- if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
- sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
- "scmd(%p)\n", scmd);
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- r = SUCCESS;
- goto out;
- }
-
- /* search for the command */
- smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
- if (!smid) {
- scmd->result = DID_RESET << 16;
- r = SUCCESS;
- goto out;
- }
-
- /* for hidden raid components and volumes this is not supported */
- if (sas_device_priv_data->sas_target->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT ||
- sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
- scmd->result = DID_RESET << 16;
- r = FAILED;
- goto out;
- }
-
- mpt2sas_halt_firmware(ioc);
-
- handle = sas_device_priv_data->sas_target->handle;
- r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
- scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON);
-
- out:
- sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
- ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
- return r;
-}
-
-/**
- * _scsih_dev_reset - eh threads main device reset routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_dev_reset(struct scsi_cmnd *scmd)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct _sas_device *sas_device = NULL;
- u16 handle;
- int r;
-
- struct scsi_target *starget = scmd->device->sdev_target;
- struct MPT2SAS_TARGET *target_priv_data = starget->hostdata;
-
- starget_printk(KERN_INFO, starget, "attempting device reset! "
- "scmd(%p)\n", scmd);
- _scsih_tm_display_info(ioc, scmd);
-
- sas_device_priv_data = scmd->device->hostdata;
- if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
- starget_printk(KERN_INFO, starget, "device been deleted! "
- "scmd(%p)\n", scmd);
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- r = SUCCESS;
- goto out;
- }
-
- /* for hidden raid components obtain the volume_handle */
- handle = 0;
- if (sas_device_priv_data->sas_target->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT) {
- sas_device = mpt2sas_get_sdev_from_target(ioc,
- target_priv_data);
- if (sas_device)
- handle = sas_device->volume_handle;
- } else
- handle = sas_device_priv_data->sas_target->handle;
-
- if (!handle) {
- scmd->result = DID_RESET << 16;
- r = FAILED;
- goto out;
- }
-
- r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
- scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON);
-
- out:
- sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
- ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
- if (sas_device)
- sas_device_put(sas_device);
-
- return r;
-}
-
-/**
- * _scsih_target_reset - eh threads main target reset routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_target_reset(struct scsi_cmnd *scmd)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct _sas_device *sas_device = NULL;
- u16 handle;
- int r;
- struct scsi_target *starget = scmd->device->sdev_target;
- struct MPT2SAS_TARGET *target_priv_data = starget->hostdata;
-
- starget_printk(KERN_INFO, starget, "attempting target reset! "
- "scmd(%p)\n", scmd);
- _scsih_tm_display_info(ioc, scmd);
-
- sas_device_priv_data = scmd->device->hostdata;
- if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
- starget_printk(KERN_INFO, starget, "target been deleted! "
- "scmd(%p)\n", scmd);
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- r = SUCCESS;
- goto out;
- }
-
- /* for hidden raid components obtain the volume_handle */
- handle = 0;
- if (sas_device_priv_data->sas_target->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT) {
- sas_device = mpt2sas_get_sdev_from_target(ioc,
- target_priv_data);
- if (sas_device)
- handle = sas_device->volume_handle;
- } else
- handle = sas_device_priv_data->sas_target->handle;
-
- if (!handle) {
- scmd->result = DID_RESET << 16;
- r = FAILED;
- goto out;
- }
-
- r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
- scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
- 30, TM_MUTEX_ON);
-
- out:
- starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
- ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
- if (sas_device)
- sas_device_put(sas_device);
-
- return r;
-}
-
-/**
- * _scsih_host_reset - eh threads main host reset routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_host_reset(struct scsi_cmnd *scmd)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
- int r, retval;
-
- printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n",
- ioc->name, scmd);
- scsi_print_command(scmd);
-
- if (ioc->is_driver_loading) {
- printk(MPT2SAS_INFO_FMT "Blocking the host reset\n",
- ioc->name);
- r = FAILED;
- goto out;
- }
-
- retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- r = (retval < 0) ? FAILED : SUCCESS;
-
- out:
- printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n",
- ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
- return r;
-}
-
-/**
- * _scsih_fw_event_add - insert and queue up fw_event
- * @ioc: per adapter object
- * @fw_event: object describing the event
- * Context: This function will acquire ioc->fw_event_lock.
- *
- * This adds the firmware event object into link list, then queues it up to
- * be processed from user context.
- *
- * Return nothing.
- */
-static void
-_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
-{
- unsigned long flags;
-
- if (ioc->firmware_event_thread == NULL)
- return;
-
- spin_lock_irqsave(&ioc->fw_event_lock, flags);
- fw_event_work_get(fw_event);
- list_add_tail(&fw_event->list, &ioc->fw_event_list);
- INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work);
- fw_event_work_get(fw_event);
- queue_delayed_work(ioc->firmware_event_thread,
- &fw_event->delayed_work, 0);
- spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-}
-
-/**
- * _scsih_fw_event_del_from_list - delete fw_event from the list
- * @ioc: per adapter object
- * @fw_event: object describing the event
- * Context: This function will acquire ioc->fw_event_lock.
- *
- * If the fw_event is on the fw_event_list, remove it and do a put.
- *
- * Return nothing.
- */
-static void
-_scsih_fw_event_del_from_list(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
- *fw_event)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->fw_event_lock, flags);
- if (!list_empty(&fw_event->list)) {
- list_del_init(&fw_event->list);
- fw_event_work_put(fw_event);
- }
- spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-}
-
-/**
- * _scsih_error_recovery_delete_devices - remove devices not responding
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
-{
- struct fw_event_work *fw_event;
-
- if (ioc->is_driver_loading)
- return;
-
- fw_event = alloc_fw_event_work(0);
- if (!fw_event)
- return;
-
- fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
- fw_event->ioc = ioc;
- _scsih_fw_event_add(ioc, fw_event);
- fw_event_work_put(fw_event);
-}
-
-/**
- * mpt2sas_port_enable_complete - port enable completed (fake event)
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-void
-mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
-{
- struct fw_event_work *fw_event;
-
- fw_event = alloc_fw_event_work(0);
- if (!fw_event)
- return;
- fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
- fw_event->ioc = ioc;
- _scsih_fw_event_add(ioc, fw_event);
- fw_event_work_put(fw_event);
-}
-
-static struct fw_event_work *dequeue_next_fw_event(struct MPT2SAS_ADAPTER *ioc)
-{
- unsigned long flags;
- struct fw_event_work *fw_event = NULL;
-
- spin_lock_irqsave(&ioc->fw_event_lock, flags);
- if (!list_empty(&ioc->fw_event_list)) {
- fw_event = list_first_entry(&ioc->fw_event_list,
- struct fw_event_work, list);
- list_del_init(&fw_event->list);
- }
- spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-
- return fw_event;
-}
-
-/**
- * _scsih_fw_event_cleanup_queue - cleanup event queue
- * @ioc: per adapter object
- *
- * Walk the firmware event queue, either killing timers, or waiting
- * for outstanding events to complete
- *
- * Return nothing.
- */
-static void
-_scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
-{
- struct fw_event_work *fw_event;
-
- if (list_empty(&ioc->fw_event_list) ||
- !ioc->firmware_event_thread || in_interrupt())
- return;
-
- while ((fw_event = dequeue_next_fw_event(ioc))) {
- /*
- * Wait on the fw_event to complete. If this returns 1, then
- * the event was never executed, and we need a put for the
- * reference the delayed_work had on the fw_event.
- *
- * If it did execute, we wait for it to finish, and the put will
- * happen from _firmware_event_work()
- */
- if (cancel_delayed_work_sync(&fw_event->delayed_work))
- fw_event_work_put(fw_event);
-
- fw_event_work_put(fw_event);
- }
-}
-
-/**
- * _scsih_ublock_io_all_device - unblock every device
- * @ioc: per adapter object
- *
- * change the device state from block to running
- */
-static void
-_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, ioc->shost) {
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- continue;
- if (!sas_device_priv_data->block)
- continue;
- sas_device_priv_data->block = 0;
- dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
- "handle(0x%04x)\n",
- sas_device_priv_data->sas_target->handle));
- scsi_internal_device_unblock(sdev, SDEV_RUNNING);
- }
-}
-/**
- * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During device pull we need to appropiately set the sdev state.
- */
-static void
-_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, ioc->shost) {
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- continue;
- if (!sas_device_priv_data->block)
- continue;
- if (sas_device_priv_data->sas_target->sas_address ==
- sas_address) {
- dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
- MPT2SAS_INFO_FMT "SDEV_RUNNING: "
- "sas address(0x%016llx)\n", ioc->name,
- (unsigned long long)sas_address));
- sas_device_priv_data->block = 0;
- scsi_internal_device_unblock(sdev, SDEV_RUNNING);
- }
- }
-}
-
-/**
- * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During device pull we need to appropiately set the sdev state.
- */
-static void
-_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, ioc->shost) {
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- continue;
- if (sas_device_priv_data->block)
- continue;
- sas_device_priv_data->block = 1;
- dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
- "handle(0x%04x)\n",
- sas_device_priv_data->sas_target->handle));
- scsi_internal_device_block(sdev);
- }
-}
-
-
-/**
- * _scsih_block_io_device - set the device state to SDEV_BLOCK
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During device pull we need to appropiately set the sdev state.
- */
-static void
-_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, ioc->shost) {
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
- continue;
- if (sas_device_priv_data->block)
- continue;
- if (sas_device_priv_data->sas_target->handle == handle) {
- dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
- MPT2SAS_INFO_FMT "SDEV_BLOCK: "
- "handle(0x%04x)\n", ioc->name, handle));
- sas_device_priv_data->block = 1;
- scsi_internal_device_block(sdev);
- }
- }
-}
-
-/**
- * _scsih_block_io_to_children_attached_to_ex
- * @ioc: per adapter object
- * @sas_expander: the sas_device object
- *
- * This routine set sdev state to SDEV_BLOCK for all devices
- * attached to this expander. This function called when expander is
- * pulled.
- */
-static void
-_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_expander)
-{
- struct _sas_port *mpt2sas_port;
- struct _sas_device *sas_device;
- struct _sas_node *expander_sibling;
- unsigned long flags;
-
- if (!sas_expander)
- return;
-
- list_for_each_entry(mpt2sas_port,
- &sas_expander->sas_port_list, port_list) {
- if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- mpt2sas_port->remote_identify.sas_address);
- if (sas_device) {
- set_bit(sas_device->handle,
- ioc->blocking_handles);
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- }
- }
-
- list_for_each_entry(mpt2sas_port,
- &sas_expander->sas_port_list, port_list) {
-
- if (mpt2sas_port->remote_identify.device_type ==
- SAS_EDGE_EXPANDER_DEVICE ||
- mpt2sas_port->remote_identify.device_type ==
- SAS_FANOUT_EXPANDER_DEVICE) {
- expander_sibling =
- mpt2sas_scsih_expander_find_by_sas_address(
- ioc, mpt2sas_port->remote_identify.sas_address);
- _scsih_block_io_to_children_attached_to_ex(ioc,
- expander_sibling);
- }
- }
-}
-
-/**
- * _scsih_block_io_to_children_attached_directly
- * @ioc: per adapter object
- * @event_data: topology change event data
- *
- * This routine set sdev state to SDEV_BLOCK for all devices
- * direct attached during device pull.
- */
-static void
-_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataSasTopologyChangeList_t *event_data)
-{
- int i;
- u16 handle;
- u16 reason_code;
- u8 phy_number;
-
- for (i = 0; i < event_data->NumEntries; i++) {
- handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
- if (!handle)
- continue;
- phy_number = event_data->StartPhyNum + i;
- reason_code = event_data->PHY[i].PhyStatus &
- MPI2_EVENT_SAS_TOPO_RC_MASK;
- if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
- _scsih_block_io_device(ioc, handle);
- }
-}
-
-/**
- * _scsih_tm_tr_send - send task management request
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt time.
- *
- * This code is to initiate the device removal handshake protocol
- * with controller firmware. This function will issue target reset
- * using high priority request queue. It will send a sas iounit
- * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
- *
- * This is designed to send muliple task management request at the same
- * time to the fifo. If the fifo is full, we will append the request,
- * and process it in a future completion.
- */
-static void
-_scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- Mpi2SCSITaskManagementRequest_t *mpi_request;
- u16 smid;
- struct _sas_device *sas_device = NULL;
- struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
- u64 sas_address = 0;
- unsigned long flags;
- struct _tr_list *delayed_tr;
- u32 ioc_state;
-
- if (ioc->remove_host) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
- "removed: handle(0x%04x)\n", __func__, ioc->name, handle));
- return;
- } else if (ioc->pci_error_recovery) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
- "error recovery: handle(0x%04x)\n", __func__, ioc->name,
- handle));
- return;
- }
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
- "operational: handle(0x%04x)\n", __func__, ioc->name,
- handle));
- return;
- }
-
- /* if PD, then return */
- if (test_bit(handle, ioc->pd_handles))
- return;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device && sas_device->starget &&
- sas_device->starget->hostdata) {
- sas_target_priv_data = sas_device->starget->hostdata;
- sas_target_priv_data->deleted = 1;
- sas_address = sas_device->sas_address;
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (sas_target_priv_data) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
- "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
- (unsigned long long)sas_address));
- _scsih_ublock_io_device(ioc, sas_address);
- sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
- }
-
- smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
- if (!smid) {
- delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
- if (!delayed_tr)
- goto out;
- INIT_LIST_HEAD(&delayed_tr->list);
- delayed_tr->handle = handle;
- list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "DELAYED:tr:handle(0x%04x), (open)\n",
- ioc->name, handle));
- goto out;
- }
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
- "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
- ioc->tm_tr_cb_idx));
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
- mpi_request->DevHandle = cpu_to_le16(handle);
- mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
- mpt2sas_base_put_smid_hi_priority(ioc, smid);
-out:
- if (sas_device)
- sas_device_put(sas_device);
-}
-
-
-
-/**
- * _scsih_sas_control_complete - completion routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: interrupt time.
- *
- * This is the sas iounit control completion routine.
- * This code is part of the code to initiate the device removal
- * handshake protocol with controller firmware.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- u8 msix_index, u32 reply)
-{
- Mpi2SasIoUnitControlReply_t *mpi_reply =
- mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (likely(mpi_reply)) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "sc_complete:handle(0x%04x), (open) "
- "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
- le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo)));
- } else {
- printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- }
- return 1;
-}
-
-/**
- * _scsih_tm_tr_volume_send - send target reset request for volumes
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt time.
- *
- * This is designed to send muliple task management request at the same
- * time to the fifo. If the fifo is full, we will append the request,
- * and process it in a future completion.
- */
-static void
-_scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- Mpi2SCSITaskManagementRequest_t *mpi_request;
- u16 smid;
- struct _tr_list *delayed_tr;
-
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
- "progress!\n", __func__, ioc->name));
- return;
- }
-
- smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
- if (!smid) {
- delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
- if (!delayed_tr)
- return;
- INIT_LIST_HEAD(&delayed_tr->list);
- delayed_tr->handle = handle;
- list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "DELAYED:tr:handle(0x%04x), (open)\n",
- ioc->name, handle));
- return;
- }
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
- "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
- ioc->tm_tr_volume_cb_idx));
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
- mpi_request->DevHandle = cpu_to_le16(handle);
- mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
- mpt2sas_base_put_smid_hi_priority(ioc, smid);
-}
-
-/**
- * _scsih_tm_volume_tr_complete - target reset completion
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: interrupt time.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
- u8 msix_index, u32 reply)
-{
- u16 handle;
- Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
- Mpi2SCSITaskManagementReply_t *mpi_reply =
- mpt2sas_base_get_reply_virt_addr(ioc, reply);
-
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
- "progress!\n", __func__, ioc->name));
- return 1;
- }
- if (unlikely(!mpi_reply)) {
- printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return 1;
- }
- mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
- handle = le16_to_cpu(mpi_request_tm->DevHandle);
- if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
- dewtprintk(ioc, printk("spurious interrupt: "
- "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle,
- le16_to_cpu(mpi_reply->DevHandle), smid));
- return 0;
- }
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
- "loginfo(0x%08x), completed(%d)\n", ioc->name,
- handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo),
- le32_to_cpu(mpi_reply->TerminationCount)));
-
- return _scsih_check_for_pending_tm(ioc, smid);
-}
-
-/**
- * _scsih_tm_tr_complete -
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: interrupt time.
- *
- * This is the target reset completion routine.
- * This code is part of the code to initiate the device removal
- * handshake protocol with controller firmware.
- * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- u16 handle;
- Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
- Mpi2SCSITaskManagementReply_t *mpi_reply =
- mpt2sas_base_get_reply_virt_addr(ioc, reply);
- Mpi2SasIoUnitControlRequest_t *mpi_request;
- u16 smid_sas_ctrl;
- u32 ioc_state;
-
- if (ioc->remove_host) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
- "removed\n", __func__, ioc->name));
- return 1;
- } else if (ioc->pci_error_recovery) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
- "error recovery\n", __func__, ioc->name));
- return 1;
- }
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
- "operational\n", __func__, ioc->name));
- return 1;
- }
- if (unlikely(!mpi_reply)) {
- printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return 1;
- }
- mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
- handle = le16_to_cpu(mpi_request_tm->DevHandle);
- if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "spurious interrupt: "
- "handle(0x%04x:0x%04x), smid(%d)!!!\n", ioc->name, handle,
- le16_to_cpu(mpi_reply->DevHandle), smid));
- return 0;
- }
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
- "loginfo(0x%08x), completed(%d)\n", ioc->name,
- handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo),
- le32_to_cpu(mpi_reply->TerminationCount)));
-
- smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
- if (!smid_sas_ctrl) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- return 1;
- }
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sc_send:handle(0x%04x), "
- "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid_sas_ctrl,
- ioc->tm_sas_control_cb_idx));
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl);
- memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
- mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
- mpi_request->DevHandle = mpi_request_tm->DevHandle;
- mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl);
-
- return _scsih_check_for_pending_tm(ioc, smid);
-}
-
-/**
- * _scsih_check_for_pending_tm - check for pending task management
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * This will check delayed target reset list, and feed the
- * next reqeust.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- struct _tr_list *delayed_tr;
-
- if (!list_empty(&ioc->delayed_tr_volume_list)) {
- delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
- struct _tr_list, list);
- mpt2sas_base_free_smid(ioc, smid);
- _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
- list_del(&delayed_tr->list);
- kfree(delayed_tr);
- return 0;
- }
-
- if (!list_empty(&ioc->delayed_tr_list)) {
- delayed_tr = list_entry(ioc->delayed_tr_list.next,
- struct _tr_list, list);
- mpt2sas_base_free_smid(ioc, smid);
- _scsih_tm_tr_send(ioc, delayed_tr->handle);
- list_del(&delayed_tr->list);
- kfree(delayed_tr);
- return 0;
- }
-
- return 1;
-}
-
-/**
- * _scsih_check_topo_delete_events - sanity check on topo events
- * @ioc: per adapter object
- * @event_data: the event data payload
- *
- * This routine added to better handle cable breaker.
- *
- * This handles the case where driver receives multiple expander
- * add and delete events in a single shot. When there is a delete event
- * the routine will void any pending add events waiting in the event queue.
- *
- * Return nothing.
- */
-static void
-_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataSasTopologyChangeList_t *event_data)
-{
- struct fw_event_work *fw_event;
- Mpi2EventDataSasTopologyChangeList_t *local_event_data;
- u16 expander_handle;
- struct _sas_node *sas_expander;
- unsigned long flags;
- int i, reason_code;
- u16 handle;
-
- for (i = 0 ; i < event_data->NumEntries; i++) {
- handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
- if (!handle)
- continue;
- reason_code = event_data->PHY[i].PhyStatus &
- MPI2_EVENT_SAS_TOPO_RC_MASK;
- if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
- _scsih_tm_tr_send(ioc, handle);
- }
-
- expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
- if (expander_handle < ioc->sas_hba.num_phys) {
- _scsih_block_io_to_children_attached_directly(ioc, event_data);
- return;
- }
- if (event_data->ExpStatus ==
- MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
- /* put expander attached devices into blocking state */
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
- expander_handle);
- _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- do {
- handle = find_first_bit(ioc->blocking_handles,
- ioc->facts.MaxDevHandle);
- if (handle < ioc->facts.MaxDevHandle)
- _scsih_block_io_device(ioc, handle);
- } while (test_and_clear_bit(handle, ioc->blocking_handles));
- } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
- _scsih_block_io_to_children_attached_directly(ioc, event_data);
-
- if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
- return;
-
- /* mark ignore flag for pending events */
- spin_lock_irqsave(&ioc->fw_event_lock, flags);
- list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
- if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
- fw_event->ignore)
- continue;
- local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
- fw_event->event_data;
- if (local_event_data->ExpStatus ==
- MPI2_EVENT_SAS_TOPO_ES_ADDED ||
- local_event_data->ExpStatus ==
- MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
- if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
- expander_handle) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "setting ignoring flag\n", ioc->name));
- fw_event->ignore = 1;
- }
- }
- }
- spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-}
-
-/**
- * _scsih_set_volume_delete_flag - setting volume delete flag
- * @ioc: per adapter object
- * @handle: device handle
- *
- * This
- * Return nothing.
- */
-static void
-_scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _raid_device *raid_device;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- if (raid_device && raid_device->starget &&
- raid_device->starget->hostdata) {
- sas_target_priv_data =
- raid_device->starget->hostdata;
- sas_target_priv_data->deleted = 1;
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "setting delete flag: handle(0x%04x), "
- "wwid(0x%016llx)\n", ioc->name, handle,
- (unsigned long long) raid_device->wwid));
- }
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
- * @handle: input handle
- * @a: handle for volume a
- * @b: handle for volume b
- *
- * IR firmware only supports two raid volumes. The purpose of this
- * routine is to set the volume handle in either a or b. When the given
- * input handle is non-zero, or when a and b have not been set before.
- */
-static void
-_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
-{
- if (!handle || handle == *a || handle == *b)
- return;
- if (!*a)
- *a = handle;
- else if (!*b)
- *b = handle;
-}
-
-/**
- * _scsih_check_ir_config_unhide_events - check for UNHIDE events
- * @ioc: per adapter object
- * @event_data: the event data payload
- * Context: interrupt time.
- *
- * This routine will send target reset to volume, followed by target
- * resets to the PDs. This is called when a PD has been removed, or
- * volume has been deleted or removed. When the target reset is sent
- * to volume, the PD target resets need to be queued to start upon
- * completion of the volume target reset.
- *
- * Return nothing.
- */
-static void
-_scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataIrConfigChangeList_t *event_data)
-{
- Mpi2EventIrConfigElement_t *element;
- int i;
- u16 handle, volume_handle, a, b;
- struct _tr_list *delayed_tr;
-
- a = 0;
- b = 0;
-
- if (ioc->is_warpdrive)
- return;
-
- /* Volume Resets for Deleted or Removed */
- element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
- for (i = 0; i < event_data->NumElements; i++, element++) {
- if (element->ReasonCode ==
- MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
- element->ReasonCode ==
- MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
- volume_handle = le16_to_cpu(element->VolDevHandle);
- _scsih_set_volume_delete_flag(ioc, volume_handle);
- _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
- }
- }
-
- /* Volume Resets for UNHIDE events */
- element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
- for (i = 0; i < event_data->NumElements; i++, element++) {
- if (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
- continue;
- if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
- volume_handle = le16_to_cpu(element->VolDevHandle);
- _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
- }
- }
-
- if (a)
- _scsih_tm_tr_volume_send(ioc, a);
- if (b)
- _scsih_tm_tr_volume_send(ioc, b);
-
- /* PD target resets */
- element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
- for (i = 0; i < event_data->NumElements; i++, element++) {
- if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
- continue;
- handle = le16_to_cpu(element->PhysDiskDevHandle);
- volume_handle = le16_to_cpu(element->VolDevHandle);
- clear_bit(handle, ioc->pd_handles);
- if (!volume_handle)
- _scsih_tm_tr_send(ioc, handle);
- else if (volume_handle == a || volume_handle == b) {
- delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
- BUG_ON(!delayed_tr);
- INIT_LIST_HEAD(&delayed_tr->list);
- delayed_tr->handle = handle;
- list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
- handle));
- } else
- _scsih_tm_tr_send(ioc, handle);
- }
-}
-
-
-/**
- * _scsih_check_volume_delete_events - set delete flag for volumes
- * @ioc: per adapter object
- * @event_data: the event data payload
- * Context: interrupt time.
- *
- * This will handle the case when the cable connected to entire volume is
- * pulled. We will take care of setting the deleted flag so normal IO will
- * not be sent.
- *
- * Return nothing.
- */
-static void
-_scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataIrVolume_t *event_data)
-{
- u32 state;
-
- if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
- return;
- state = le32_to_cpu(event_data->NewValue);
- if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
- MPI2_RAID_VOL_STATE_FAILED)
- _scsih_set_volume_delete_flag(ioc,
- le16_to_cpu(event_data->VolDevHandle));
-}
-
-/**
- * _scsih_temp_threshold_events - display temperature threshold exceeded events
- * @ioc: per adapter object
- * @event_data: the temp threshold event data
- * Context: interrupt time.
- *
- * Return nothing.
- */
-static void
-_scsih_temp_threshold_events(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataTemperature_t *event_data)
-{
- if (ioc->temp_sensors_count >= event_data->SensorNum) {
- printk(MPT2SAS_ERR_FMT "Temperature Threshold flags %s%s%s%s"
- " exceeded for Sensor: %d !!!\n", ioc->name,
- ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ",
- ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ",
- ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ",
- ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ",
- event_data->SensorNum);
- printk(MPT2SAS_ERR_FMT "Current Temp In Celsius: %d\n",
- ioc->name, event_data->CurrentTemperature);
- }
-}
-
-/**
- * _scsih_flush_running_cmds - completing outstanding commands.
- * @ioc: per adapter object
- *
- * The flushing out of all pending scmd commands following host reset,
- * where all IO is dropped to the floor.
- *
- * Return nothing.
- */
-static void
-_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
-{
- struct scsi_cmnd *scmd;
- u16 smid;
- u16 count = 0;
-
- for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
- scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
- if (!scmd)
- continue;
- count++;
- mpt2sas_base_free_smid(ioc, smid);
- scsi_dma_unmap(scmd);
- if (ioc->pci_error_recovery)
- scmd->result = DID_NO_CONNECT << 16;
- else
- scmd->result = DID_RESET << 16;
- scmd->scsi_done(scmd);
- }
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n",
- ioc->name, count));
-}
-
-/**
- * _scsih_setup_eedp - setup MPI request for EEDP transfer
- * @scmd: pointer to scsi command object
- * @mpi_request: pointer to the SCSI_IO reqest message frame
- *
- * Supporting protection 1 and 3.
- *
- * Returns nothing
- */
-static void
-_scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request)
-{
- u16 eedp_flags;
- unsigned char prot_op = scsi_get_prot_op(scmd);
- unsigned char prot_type = scsi_get_prot_type(scmd);
-
- if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
- return;
-
- if (prot_op == SCSI_PROT_READ_STRIP)
- eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
- else if (prot_op == SCSI_PROT_WRITE_INSERT)
- eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
- else
- return;
-
- switch (prot_type) {
- case SCSI_PROT_DIF_TYPE1:
- case SCSI_PROT_DIF_TYPE2:
-
- /*
- * enable ref/guard checking
- * auto increment ref tag
- */
- eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
- mpi_request->CDB.EEDP32.PrimaryReferenceTag =
- cpu_to_be32(scsi_get_lba(scmd));
- break;
-
- case SCSI_PROT_DIF_TYPE3:
-
- /*
- * enable guard checking
- */
- eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
- break;
- }
- mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size);
- mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
-}
-
-/**
- * _scsih_eedp_error_handling - return sense code for EEDP errors
- * @scmd: pointer to scsi command object
- * @ioc_status: ioc status
- *
- * Returns nothing
- */
-static void
-_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
-{
- u8 ascq;
-
- switch (ioc_status) {
- case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
- ascq = 0x01;
- break;
- case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
- ascq = 0x02;
- break;
- case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
- ascq = 0x03;
- break;
- default:
- ascq = 0x00;
- break;
- }
-
- scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10, ascq);
- scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
- SAM_STAT_CHECK_CONDITION;
-}
-
-/**
- * _scsih_scsi_direct_io_get - returns direct io flag
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- */
-static inline u8
-_scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- return ioc->scsi_lookup[smid - 1].direct_io;
-}
-
-/**
- * _scsih_scsi_direct_io_set - sets direct io flag
- * @ioc: per adapter object
- * @smid: system request message index
- * @direct_io: Zero or non-zero value to set in the direct_io flag
- *
- * Returns Nothing.
- */
-static inline void
-_scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
-{
- ioc->scsi_lookup[smid - 1].direct_io = direct_io;
-}
-
-
-/**
- * _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
- * @ioc: per adapter object
- * @scmd: pointer to scsi command object
- * @raid_device: pointer to raid device data structure
- * @mpi_request: pointer to the SCSI_IO reqest message frame
- * @smid: system request message index
- *
- * Returns nothing
- */
-static void
-_scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
- struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
- u16 smid)
-{
- sector_t v_lba, p_lba, stripe_off, column, io_size;
- u32 stripe_sz, stripe_exp;
- u8 num_pds, cmd = scmd->cmnd[0];
-
- if (cmd != READ_10 && cmd != WRITE_10 &&
- cmd != READ_16 && cmd != WRITE_16)
- return;
-
- if (cmd == READ_10 || cmd == WRITE_10)
- v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]);
- else
- v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]);
-
- io_size = scsi_bufflen(scmd) >> raid_device->block_exponent;
-
- if (v_lba + io_size - 1 > raid_device->max_lba)
- return;
-
- stripe_sz = raid_device->stripe_sz;
- stripe_exp = raid_device->stripe_exponent;
- stripe_off = v_lba & (stripe_sz - 1);
-
- /* Return unless IO falls within a stripe */
- if (stripe_off + io_size > stripe_sz)
- return;
-
- num_pds = raid_device->num_pds;
- p_lba = v_lba >> stripe_exp;
- column = sector_div(p_lba, num_pds);
- p_lba = (p_lba << stripe_exp) + stripe_off;
-
- mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]);
-
- if (cmd == READ_10 || cmd == WRITE_10)
- put_unaligned_be32(lower_32_bits(p_lba),
- &mpi_request->CDB.CDB32[2]);
- else
- put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]);
-
- _scsih_scsi_direct_io_set(ioc, smid, 1);
-}
-
-/**
- * _scsih_qcmd - main scsi request entry point
- * @scmd: pointer to scsi command object
- * @done: function pointer to be invoked on completion
- *
- * The callback index is set inside `ioc->scsi_io_cb_idx`.
- *
- * Returns 0 on success. If there's a failure, return either:
- * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
- * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
- */
-static int
-_scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct _raid_device *raid_device;
- Mpi2SCSIIORequest_t *mpi_request;
- u32 mpi_control;
- u16 smid;
-
- sas_device_priv_data = scmd->device->hostdata;
- if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- return 0;
- }
-
- if (ioc->pci_error_recovery || ioc->remove_host) {
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- return 0;
- }
-
- sas_target_priv_data = sas_device_priv_data->sas_target;
- /* invalid device handle */
- if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- return 0;
- }
-
- /* host recovery or link resets sent via IOCTLs */
- if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
- return SCSI_MLQUEUE_HOST_BUSY;
- /* device busy with task management */
- else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
- return SCSI_MLQUEUE_DEVICE_BUSY;
- /* device has been deleted */
- else if (sas_target_priv_data->deleted) {
- scmd->result = DID_NO_CONNECT << 16;
- scmd->scsi_done(scmd);
- return 0;
- }
-
- if (scmd->sc_data_direction == DMA_FROM_DEVICE)
- mpi_control = MPI2_SCSIIO_CONTROL_READ;
- else if (scmd->sc_data_direction == DMA_TO_DEVICE)
- mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
- else
- mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
-
- /* set tags */
- mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
-
- /* Make sure Device is not raid volume.
- * We do not expose raid functionality to upper layer for warpdrive.
- */
- if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
- sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
- mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
-
- smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- goto out;
- }
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
- _scsih_setup_eedp(scmd, mpi_request);
- if (scmd->cmd_len == 32)
- mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
- mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
- if (sas_device_priv_data->sas_target->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT)
- mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
- else
- mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
- mpi_request->DevHandle =
- cpu_to_le16(sas_device_priv_data->sas_target->handle);
- mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
- mpi_request->Control = cpu_to_le32(mpi_control);
- mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
- mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
- mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
- mpi_request->SenseBufferLowAddress =
- mpt2sas_base_get_sense_buffer_dma(ioc, smid);
- mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
- mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI +
- MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR);
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
- int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
- mpi_request->LUN);
- memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
-
- if (!mpi_request->DataLength) {
- mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL);
- } else {
- if (_scsih_build_scatter_gather(ioc, scmd, smid)) {
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
- }
-
- raid_device = sas_target_priv_data->raid_device;
- if (raid_device && raid_device->direct_io_enabled)
- _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
- smid);
-
- if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST))
- mpt2sas_base_put_smid_scsi_io(ioc, smid,
- le16_to_cpu(mpi_request->DevHandle));
- else
- mpt2sas_base_put_smid_default(ioc, smid);
- return 0;
-
- out:
- return SCSI_MLQUEUE_HOST_BUSY;
-}
-
-/**
- * _scsih_normalize_sense - normalize descriptor and fixed format sense data
- * @sense_buffer: sense data returned by target
- * @data: normalized skey/asc/ascq
- *
- * Return nothing.
- */
-static void
-_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
-{
- if ((sense_buffer[0] & 0x7F) >= 0x72) {
- /* descriptor format */
- data->skey = sense_buffer[1] & 0x0F;
- data->asc = sense_buffer[2];
- data->ascq = sense_buffer[3];
- } else {
- /* fixed format */
- data->skey = sense_buffer[2] & 0x0F;
- data->asc = sense_buffer[12];
- data->ascq = sense_buffer[13];
- }
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request
- * @ioc: per adapter object
- * @scmd: pointer to scsi command object
- * @mpi_reply: reply mf payload returned from firmware
- *
- * scsi_status - SCSI Status code returned from target device
- * scsi_state - state info associated with SCSI_IO determined by ioc
- * ioc_status - ioc supplied status info
- *
- * Return nothing.
- */
-static void
-_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
- Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
-{
- u32 response_info;
- u8 *response_bytes;
- u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- u8 scsi_state = mpi_reply->SCSIState;
- u8 scsi_status = mpi_reply->SCSIStatus;
- char *desc_ioc_state = NULL;
- char *desc_scsi_status = NULL;
- char *desc_scsi_state = ioc->tmp_string;
- u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
- struct _sas_device *sas_device = NULL;
- struct scsi_target *starget = scmd->device->sdev_target;
- struct MPT2SAS_TARGET *priv_target = starget->hostdata;
- char *device_str = NULL;
-
- if (!priv_target)
- return;
-
- if (ioc->hide_ir_msg)
- device_str = "WarpDrive";
- else
- device_str = "volume";
-
- if (log_info == 0x31170000)
- return;
-
- switch (ioc_status) {
- case MPI2_IOCSTATUS_SUCCESS:
- desc_ioc_state = "success";
- break;
- case MPI2_IOCSTATUS_INVALID_FUNCTION:
- desc_ioc_state = "invalid function";
- break;
- case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
- desc_ioc_state = "scsi recovered error";
- break;
- case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
- desc_ioc_state = "scsi invalid dev handle";
- break;
- case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
- desc_ioc_state = "scsi device not there";
- break;
- case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
- desc_ioc_state = "scsi data overrun";
- break;
- case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
- desc_ioc_state = "scsi data underrun";
- break;
- case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
- desc_ioc_state = "scsi io data error";
- break;
- case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
- desc_ioc_state = "scsi protocol error";
- break;
- case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
- desc_ioc_state = "scsi task terminated";
- break;
- case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
- desc_ioc_state = "scsi residual mismatch";
- break;
- case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
- desc_ioc_state = "scsi task mgmt failed";
- break;
- case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
- desc_ioc_state = "scsi ioc terminated";
- break;
- case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
- desc_ioc_state = "scsi ext terminated";
- break;
- case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
- desc_ioc_state = "eedp guard error";
- break;
- case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
- desc_ioc_state = "eedp ref tag error";
- break;
- case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
- desc_ioc_state = "eedp app tag error";
- break;
- default:
- desc_ioc_state = "unknown";
- break;
- }
-
- switch (scsi_status) {
- case MPI2_SCSI_STATUS_GOOD:
- desc_scsi_status = "good";
- break;
- case MPI2_SCSI_STATUS_CHECK_CONDITION:
- desc_scsi_status = "check condition";
- break;
- case MPI2_SCSI_STATUS_CONDITION_MET:
- desc_scsi_status = "condition met";
- break;
- case MPI2_SCSI_STATUS_BUSY:
- desc_scsi_status = "busy";
- break;
- case MPI2_SCSI_STATUS_INTERMEDIATE:
- desc_scsi_status = "intermediate";
- break;
- case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
- desc_scsi_status = "intermediate condmet";
- break;
- case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
- desc_scsi_status = "reservation conflict";
- break;
- case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
- desc_scsi_status = "command terminated";
- break;
- case MPI2_SCSI_STATUS_TASK_SET_FULL:
- desc_scsi_status = "task set full";
- break;
- case MPI2_SCSI_STATUS_ACA_ACTIVE:
- desc_scsi_status = "aca active";
- break;
- case MPI2_SCSI_STATUS_TASK_ABORTED:
- desc_scsi_status = "task aborted";
- break;
- default:
- desc_scsi_status = "unknown";
- break;
- }
-
- desc_scsi_state[0] = '\0';
- if (!scsi_state)
- desc_scsi_state = " ";
- if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
- strcat(desc_scsi_state, "response info ");
- if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
- strcat(desc_scsi_state, "state terminated ");
- if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
- strcat(desc_scsi_state, "no status ");
- if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
- strcat(desc_scsi_state, "autosense failed ");
- if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
- strcat(desc_scsi_state, "autosense valid ");
-
- scsi_print_command(scmd);
-
- if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
- printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
- device_str, (unsigned long long)priv_target->sas_address);
- } else {
- sas_device = mpt2sas_get_sdev_from_target(ioc, priv_target);
- if (sas_device) {
- printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
- "phy(%d)\n", ioc->name, sas_device->sas_address,
- sas_device->phy);
- printk(MPT2SAS_WARN_FMT
- "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
- ioc->name, sas_device->enclosure_logical_id,
- sas_device->slot);
-
- sas_device_put(sas_device);
- }
- }
-
- printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), "
- "smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle),
- desc_ioc_state, ioc_status, smid);
- printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), "
- "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow,
- scsi_get_resid(scmd));
- printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), "
- "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag),
- le32_to_cpu(mpi_reply->TransferCount), scmd->result);
- printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), "
- "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status,
- scsi_status, desc_scsi_state, scsi_state);
-
- if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
- struct sense_info data;
- _scsih_normalize_sense(scmd->sense_buffer, &data);
- printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: "
- "[0x%02x,0x%02x,0x%02x], count(%d)\n", ioc->name, data.skey,
- data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
- }
-
- if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
- response_info = le32_to_cpu(mpi_reply->ResponseInfo);
- response_bytes = (u8 *)&response_info;
- _scsih_response_code(ioc, response_bytes[0]);
- }
-}
-#endif
-
-/**
- * _scsih_turn_on_pfa_led - illuminate PFA LED
- * @ioc: per adapter object
- * @handle: device handle
- * Context: process
- *
- * Return nothing.
- */
-static void
-_scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- Mpi2SepReply_t mpi_reply;
- Mpi2SepRequest_t mpi_request;
- struct _sas_device *sas_device;
-
- sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
- if (!sas_device)
- return;
-
- memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
- mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
- mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
- mpi_request.SlotStatus =
- cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
- mpi_request.DevHandle = cpu_to_le16(handle);
- mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
- if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
- &mpi_request)) != 0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- goto out;
- }
- sas_device->pfa_led_on = 1;
-
-
- if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
- le32_to_cpu(mpi_reply.IOCLogInfo)));
- goto out;
- }
-out:
- sas_device_put(sas_device);
-}
-
-/**
- * _scsih_turn_off_pfa_led - turn off PFA LED
- * @ioc: per adapter object
- * @sas_device: sas device whose PFA LED has to turned off
- * Context: process
- *
- * Return nothing.
- */
-static void
-_scsih_turn_off_pfa_led(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device)
-{
- Mpi2SepReply_t mpi_reply;
- Mpi2SepRequest_t mpi_request;
-
- memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
- mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
- mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
- mpi_request.SlotStatus = 0;
- mpi_request.Slot = cpu_to_le16(sas_device->slot);
- mpi_request.DevHandle = 0;
- mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
- mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
- if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
- &mpi_request)) != 0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- return;
- }
-
- if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: "
- "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name,
- le16_to_cpu(mpi_reply.IOCStatus),
- le32_to_cpu(mpi_reply.IOCLogInfo)));
- return;
- }
-}
-
-/**
- * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt.
- *
- * Return nothing.
- */
-static void
-_scsih_send_event_to_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct fw_event_work *fw_event;
-
- fw_event = alloc_fw_event_work(0);
- if (!fw_event)
- return;
- fw_event->event = MPT2SAS_TURN_ON_PFA_LED;
- fw_event->device_handle = handle;
- fw_event->ioc = ioc;
- _scsih_fw_event_add(ioc, fw_event);
- fw_event_work_put(fw_event);
-}
-
-/**
- * _scsih_smart_predicted_fault - process smart errors
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt.
- *
- * Return nothing.
- */
-static void
-_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct scsi_target *starget;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- Mpi2EventNotificationReply_t *event_reply;
- Mpi2EventDataSasDeviceStatusChange_t *event_data;
- struct _sas_device *sas_device;
- ssize_t sz;
- unsigned long flags;
-
- /* only handle non-raid devices */
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
- if (!sas_device) {
- goto out_unlock;
- }
- starget = sas_device->starget;
- sas_target_priv_data = starget->hostdata;
-
- if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
- ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
- goto out_unlock;
-
- starget_printk(KERN_WARNING, starget, "predicted fault\n");
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
- _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
-
- /* insert into event log */
- sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
- sizeof(Mpi2EventDataSasDeviceStatusChange_t);
- event_reply = kzalloc(sz, GFP_ATOMIC);
- if (!event_reply) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
-
- event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
- event_reply->Event =
- cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
- event_reply->MsgLength = sz/4;
- event_reply->EventDataLength =
- cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
- event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
- event_reply->EventData;
- event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
- event_data->ASC = 0x5D;
- event_data->DevHandle = cpu_to_le16(handle);
- event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
- mpt2sas_ctl_add_to_event_log(ioc, event_reply);
- kfree(event_reply);
-out:
- if (sas_device)
- sas_device_put(sas_device);
- return;
-
-out_unlock:
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- goto out;
-}
-
-/**
- * _scsih_io_done - scsi request callback
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Callback handler when using _scsih_qcmd.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
-{
- Mpi2SCSIIORequest_t *mpi_request;
- Mpi2SCSIIOReply_t *mpi_reply;
- struct scsi_cmnd *scmd;
- u16 ioc_status;
- u32 xfer_cnt;
- u8 scsi_state;
- u8 scsi_status;
- u32 log_info;
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- u32 response_code = 0;
- unsigned long flags;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
- if (scmd == NULL)
- return 1;
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-
- if (mpi_reply == NULL) {
- scmd->result = DID_OK << 16;
- goto out;
- }
-
- sas_device_priv_data = scmd->device->hostdata;
- if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
- sas_device_priv_data->sas_target->deleted) {
- scmd->result = DID_NO_CONNECT << 16;
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
- /*
- * WARPDRIVE: If direct_io is set then it is directIO,
- * the failed direct I/O should be redirected to volume
- */
- if (_scsih_scsi_direct_io_get(ioc, smid) &&
- ((ioc_status & MPI2_IOCSTATUS_MASK)
- != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- ioc->scsi_lookup[smid - 1].scmd = scmd;
- _scsih_scsi_direct_io_set(ioc, smid, 0);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
- mpi_request->DevHandle =
- cpu_to_le16(sas_device_priv_data->sas_target->handle);
- mpt2sas_base_put_smid_scsi_io(ioc, smid,
- sas_device_priv_data->sas_target->handle);
- return 0;
- }
-
-
- /* turning off TLR */
- scsi_state = mpi_reply->SCSIState;
- if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
- response_code =
- le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
- if (!sas_device_priv_data->tlr_snoop_check) {
- sas_device_priv_data->tlr_snoop_check++;
- /* Make sure Device is not raid volume.
- * We do not expose raid functionality to upper layer for warpdrive.
- */
- if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
- sas_is_tlr_enabled(scmd->device) &&
- response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
- sas_disable_tlr(scmd->device);
- sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
- }
- }
-
- xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
- scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
- if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
- log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
- else
- log_info = 0;
- ioc_status &= MPI2_IOCSTATUS_MASK;
- scsi_status = mpi_reply->SCSIStatus;
-
- if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
- (scsi_status == MPI2_SCSI_STATUS_BUSY ||
- scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
- scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
- ioc_status = MPI2_IOCSTATUS_SUCCESS;
- }
-
- if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
- struct sense_info data;
- const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
- smid);
- u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
- le32_to_cpu(mpi_reply->SenseCount));
- memcpy(scmd->sense_buffer, sense_data, sz);
- _scsih_normalize_sense(scmd->sense_buffer, &data);
- /* failure prediction threshold exceeded */
- if (data.asc == 0x5D)
- _scsih_smart_predicted_fault(ioc,
- le16_to_cpu(mpi_reply->DevHandle));
- }
-
- switch (ioc_status) {
- case MPI2_IOCSTATUS_BUSY:
- case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
- scmd->result = SAM_STAT_BUSY;
- break;
-
- case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
- scmd->result = DID_NO_CONNECT << 16;
- break;
-
- case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
- if (sas_device_priv_data->block) {
- scmd->result = DID_TRANSPORT_DISRUPTED << 16;
- goto out;
- }
- if (log_info == 0x32010081) {
- scmd->result = DID_RESET << 16;
- break;
- }
- scmd->result = DID_SOFT_ERROR << 16;
- break;
- case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
- case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
- scmd->result = DID_RESET << 16;
- break;
-
- case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
- if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
- scmd->result = DID_SOFT_ERROR << 16;
- else
- scmd->result = (DID_OK << 16) | scsi_status;
- break;
-
- case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
- scmd->result = (DID_OK << 16) | scsi_status;
-
- if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
- break;
-
- if (xfer_cnt < scmd->underflow) {
- if (scsi_status == SAM_STAT_BUSY)
- scmd->result = SAM_STAT_BUSY;
- else
- scmd->result = DID_SOFT_ERROR << 16;
- } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
- MPI2_SCSI_STATE_NO_SCSI_STATUS))
- scmd->result = DID_SOFT_ERROR << 16;
- else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
- scmd->result = DID_RESET << 16;
- else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
- mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
- mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
- scmd->result = (DRIVER_SENSE << 24) |
- SAM_STAT_CHECK_CONDITION;
- scmd->sense_buffer[0] = 0x70;
- scmd->sense_buffer[2] = ILLEGAL_REQUEST;
- scmd->sense_buffer[12] = 0x20;
- scmd->sense_buffer[13] = 0;
- }
- break;
-
- case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
- scsi_set_resid(scmd, 0);
- case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
- case MPI2_IOCSTATUS_SUCCESS:
- scmd->result = (DID_OK << 16) | scsi_status;
- if (response_code ==
- MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
- (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
- MPI2_SCSI_STATE_NO_SCSI_STATUS)))
- scmd->result = DID_SOFT_ERROR << 16;
- else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
- scmd->result = DID_RESET << 16;
- break;
-
- case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
- case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
- case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
- _scsih_eedp_error_handling(scmd, ioc_status);
- break;
- case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
- case MPI2_IOCSTATUS_INVALID_FUNCTION:
- case MPI2_IOCSTATUS_INVALID_SGL:
- case MPI2_IOCSTATUS_INTERNAL_ERROR:
- case MPI2_IOCSTATUS_INVALID_FIELD:
- case MPI2_IOCSTATUS_INVALID_STATE:
- case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
- case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
- default:
- scmd->result = DID_SOFT_ERROR << 16;
- break;
-
- }
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
- _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
-#endif
-
- out:
- scsi_dma_unmap(scmd);
- scmd->scsi_done(scmd);
- return 1;
-}
-
-/**
- * _scsih_sas_host_refresh - refreshing sas host object contents
- * @ioc: per adapter object
- * Context: user
- *
- * During port enable, fw will send topology events for every device. Its
- * possible that the handles may change from the previous setting, so this
- * code keeping handles updating if changed.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
-{
- u16 sz;
- u16 ioc_status;
- int i;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
- u16 attached_handle;
- u8 link_rate;
-
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
- "updating handles for sas_host(0x%016llx)\n",
- ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
-
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
- * sizeof(Mpi2SasIOUnit0PhyData_t));
- sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
- sas_iounit_pg0, sz)) != 0)
- goto out;
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- goto out;
- for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
- link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
- if (i == 0)
- ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
- PhyData[0].ControllerDevHandle);
- ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
- attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
- AttachedDevHandle);
- if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
- link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
- mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
- attached_handle, i, link_rate);
- }
- out:
- kfree(sas_iounit_pg0);
-}
-
-/**
- * _scsih_sas_host_add - create sas host object
- * @ioc: per adapter object
- *
- * Creating host side data object, stored in ioc->sas_hba
- *
- * Return nothing.
- */
-static void
-_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
-{
- int i;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
- Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
- Mpi2SasPhyPage0_t phy_pg0;
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
- u16 ioc_status;
- u16 sz;
- u16 device_missing_delay;
-
- mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
- if (!ioc->sas_hba.num_phys) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- /* sas_iounit page 0 */
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit0PhyData_t));
- sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
- if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
- sas_iounit_pg0, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
-
- /* sas_iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
- sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg1) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
- sas_iounit_pg1, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
-
- ioc->io_missing_delay =
- le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay);
- device_missing_delay =
- le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay);
- if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
- ioc->device_missing_delay = (device_missing_delay &
- MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
- else
- ioc->device_missing_delay = device_missing_delay &
- MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
-
- ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
- ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
- sizeof(struct _sas_phy), GFP_KERNEL);
- if (!ioc->sas_hba.phy) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
- if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
- i))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
-
- if (i == 0)
- ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
- PhyData[0].ControllerDevHandle);
- ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
- ioc->sas_hba.phy[i].phy_id = i;
- mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
- phy_pg0, ioc->sas_hba.parent_dev);
- }
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out;
- }
- ioc->sas_hba.enclosure_handle =
- le16_to_cpu(sas_device_pg0.EnclosureHandle);
- ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
- printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), "
- "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle,
- (unsigned long long) ioc->sas_hba.sas_address,
- ioc->sas_hba.num_phys) ;
-
- if (ioc->sas_hba.enclosure_handle) {
- if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0,
- MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- ioc->sas_hba.enclosure_handle))) {
- ioc->sas_hba.enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
- }
- }
-
- out:
- kfree(sas_iounit_pg1);
- kfree(sas_iounit_pg0);
-}
-
-/**
- * _scsih_expander_add - creating expander object
- * @ioc: per adapter object
- * @handle: expander handle
- *
- * Creating expander object, stored in ioc->sas_expander_list.
- *
- * Return 0 for success, else error.
- */
-static int
-_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _sas_node *sas_expander;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2ExpanderPage0_t expander_pg0;
- Mpi2ExpanderPage1_t expander_pg1;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
- u32 ioc_status;
- u16 parent_handle;
- u64 sas_address, sas_address_parent = 0;
- int i;
- unsigned long flags;
- struct _sas_port *mpt2sas_port = NULL;
- int rc = 0;
-
- if (!handle)
- return -1;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery)
- return -1;
-
- if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
- MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- /* handle out of order topology events */
- parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
- if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
- != 0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
- if (sas_address_parent != ioc->sas_hba.sas_address) {
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
- sas_address_parent);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (!sas_expander) {
- rc = _scsih_expander_add(ioc, parent_handle);
- if (rc != 0)
- return rc;
- }
- }
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_address = le64_to_cpu(expander_pg0.SASAddress);
- sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
- sas_address);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- if (sas_expander)
- return 0;
-
- sas_expander = kzalloc(sizeof(struct _sas_node),
- GFP_KERNEL);
- if (!sas_expander) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- sas_expander->handle = handle;
- sas_expander->num_phys = expander_pg0.NumPhys;
- sas_expander->sas_address_parent = sas_address_parent;
- sas_expander->sas_address = sas_address;
-
- printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
- " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
- handle, parent_handle, (unsigned long long)
- sas_expander->sas_address, sas_expander->num_phys);
-
- if (!sas_expander->num_phys)
- goto out_fail;
- sas_expander->phy = kcalloc(sas_expander->num_phys,
- sizeof(struct _sas_phy), GFP_KERNEL);
- if (!sas_expander->phy) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -1;
- goto out_fail;
- }
-
- INIT_LIST_HEAD(&sas_expander->sas_port_list);
- mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
- sas_address_parent);
- if (!mpt2sas_port) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -1;
- goto out_fail;
- }
- sas_expander->parent_dev = &mpt2sas_port->rphy->dev;
-
- for (i = 0 ; i < sas_expander->num_phys ; i++) {
- if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
- &expander_pg1, i, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -1;
- goto out_fail;
- }
- sas_expander->phy[i].handle = handle;
- sas_expander->phy[i].phy_id = i;
-
- if ((mpt2sas_transport_add_expander_phy(ioc,
- &sas_expander->phy[i], expander_pg1,
- sas_expander->parent_dev))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -1;
- goto out_fail;
- }
- }
-
- if (sas_expander->enclosure_handle) {
- if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- sas_expander->enclosure_handle))) {
- sas_expander->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
- }
- }
-
- _scsih_expander_node_add(ioc, sas_expander);
- return 0;
-
- out_fail:
-
- if (mpt2sas_port)
- mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
- sas_address_parent);
- kfree(sas_expander);
- return rc;
-}
-
-/**
- * _scsih_done - scsih callback handler.
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Callback handler when sending internal generated message frames.
- * The callback index passed is `ioc->scsih_cb_idx`
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-static u8
-_scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
- if (ioc->scsih_cmds.smid != smid)
- return 1;
- ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE;
- if (mpi_reply) {
- memcpy(ioc->scsih_cmds.reply, mpi_reply,
- mpi_reply->MsgLength*4);
- ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID;
- }
- ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING;
- complete(&ioc->scsih_cmds.done);
- return 1;
-}
-
-/**
- * mpt2sas_expander_remove - removing expander object
- * @ioc: per adapter object
- * @sas_address: expander sas_address
- *
- * Return nothing.
- */
-void
-mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
-{
- struct _sas_node *sas_expander;
- unsigned long flags;
-
- if (ioc->shost_recovery)
- return;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
- sas_address);
- if (sas_expander)
- list_del(&sas_expander->list);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (sas_expander)
- _scsih_expander_node_remove(ioc, sas_expander);
-}
-
-/**
- * _scsih_check_access_status - check access flags
- * @ioc: per adapter object
- * @sas_address: sas address
- * @handle: sas device handle
- * @access_flags: errors returned during discovery of the device
- *
- * Return 0 for success, else failure
- */
-static u8
-_scsih_check_access_status(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
- u16 handle, u8 access_status)
-{
- u8 rc = 1;
- char *desc = NULL;
-
- switch (access_status) {
- case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
- case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
- rc = 0;
- break;
- case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
- desc = "sata capability failed";
- break;
- case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
- desc = "sata affiliation conflict";
- break;
- case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
- desc = "route not addressable";
- break;
- case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
- desc = "smp error not addressable";
- break;
- case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
- desc = "device blocked";
- break;
- case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
- case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
- desc = "sata initialization failed";
- break;
- default:
- desc = "unknown";
- break;
- }
-
- if (!rc)
- return 0;
-
- printk(MPT2SAS_ERR_FMT "discovery errors(%s): sas_address(0x%016llx), "
- "handle(0x%04x)\n", ioc->name, desc,
- (unsigned long long)sas_address, handle);
- return rc;
-}
-
-static void
-_scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasDevicePage0_t sas_device_pg0;
- struct _sas_device *sas_device;
- u32 ioc_status;
- unsigned long flags;
- u64 sas_address;
- struct scsi_target *starget;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- u32 device_info;
-
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
- return;
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- return;
-
- /* check if this is end device */
- device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
- if (!(_scsih_is_end_device(device_info)))
- return;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- sas_address);
-
- if (!sas_device) {
- printk(MPT2SAS_ERR_FMT "device is not present "
- "handle(0x%04x), no sas_device!!!\n", ioc->name, handle);
- goto out_unlock;
- }
-
- if (unlikely(sas_device->handle != handle)) {
- starget = sas_device->starget;
- sas_target_priv_data = starget->hostdata;
- starget_printk(KERN_INFO, starget, "handle changed from(0x%04x)"
- " to (0x%04x)!!!\n", sas_device->handle, handle);
- sas_target_priv_data->handle = handle;
- sas_device->handle = handle;
- }
-
- /* check if device is present */
- if (!(le16_to_cpu(sas_device_pg0.Flags) &
- MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
- printk(MPT2SAS_ERR_FMT "device is not present "
- "handle(0x%04x), flags!!!\n", ioc->name, handle);
- goto out_unlock;
- }
-
- /* check if there were any issues with discovery */
- if (_scsih_check_access_status(ioc, sas_address, handle,
- sas_device_pg0.AccessStatus))
- goto out_unlock;
-
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- _scsih_ublock_io_device(ioc, sas_address);
- if (sas_device)
- sas_device_put(sas_device);
- return;
-
-out_unlock:
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
- sas_device_put(sas_device);
-}
-
-/**
- * _scsih_add_device - creating sas device object
- * @ioc: per adapter object
- * @handle: sas device handle
- * @phy_num: phy number end device attached to
- * @is_pd: is this hidden raid component
- *
- * Creating end device object, stored in ioc->sas_device_list.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
-{
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
- struct _sas_device *sas_device;
- u32 ioc_status;
- __le64 sas_address;
- u32 device_info;
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-
- /* check if device is present */
- if (!(le16_to_cpu(sas_device_pg0.Flags) &
- MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n",
- ioc->name, le16_to_cpu(sas_device_pg0.Flags));
- return -1;
- }
-
- /* check if there were any issues with discovery */
- if (_scsih_check_access_status(ioc, sas_address, handle,
- sas_device_pg0.AccessStatus))
- return -1;
-
- /* check if this is end device */
- device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
- if (!(_scsih_is_end_device(device_info))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- sas_device = mpt2sas_get_sdev_by_addr(ioc,
- sas_address);
-
- if (sas_device) {
- sas_device_put(sas_device);
- return 0;
- }
-
- sas_device = kzalloc(sizeof(struct _sas_device),
- GFP_KERNEL);
- if (!sas_device) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
-
- kref_init(&sas_device->refcount);
- sas_device->handle = handle;
- if (_scsih_get_sas_address(ioc, le16_to_cpu
- (sas_device_pg0.ParentDevHandle),
- &sas_device->sas_address_parent) != 0)
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- sas_device->enclosure_handle =
- le16_to_cpu(sas_device_pg0.EnclosureHandle);
- sas_device->slot =
- le16_to_cpu(sas_device_pg0.Slot);
- sas_device->device_info = device_info;
- sas_device->sas_address = sas_address;
- sas_device->phy = sas_device_pg0.PhyNum;
-
- /* get enclosure_logical_id */
- if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
- ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- sas_device->enclosure_handle)))
- sas_device->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-
- /* get device name */
- sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
-
- if (ioc->wait_for_discovery_to_complete)
- _scsih_sas_device_init_add(ioc, sas_device);
- else
- _scsih_sas_device_add(ioc, sas_device);
-
- sas_device_put(sas_device);
- return 0;
-}
-
-/**
- * _scsih_remove_device - removing sas device object
- * @ioc: per adapter object
- * @sas_device_delete: the sas_device object
- *
- * Return nothing.
- */
-static void
-_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device)
-{
- struct MPT2SAS_TARGET *sas_target_priv_data;
-
- if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
- (sas_device->pfa_led_on)) {
- _scsih_turn_off_pfa_led(ioc, sas_device);
- sas_device->pfa_led_on = 0;
- }
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: "
- "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device->handle, (unsigned long long)
- sas_device->sas_address));
-
- if (sas_device->starget && sas_device->starget->hostdata) {
- sas_target_priv_data = sas_device->starget->hostdata;
- sas_target_priv_data->deleted = 1;
- _scsih_ublock_io_device(ioc, sas_device->sas_address);
- sas_target_priv_data->handle =
- MPT2SAS_INVALID_DEVICE_HANDLE;
- }
-
- if (!ioc->hide_drives)
- mpt2sas_transport_port_remove(ioc,
- sas_device->sas_address,
- sas_device->sas_address_parent);
-
- printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
- "(0x%016llx)\n", ioc->name, sas_device->handle,
- (unsigned long long) sas_device->sas_address);
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: "
- "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device->handle, (unsigned long long)
- sas_device->sas_address));
-}
-/**
- * _scsih_device_remove_by_handle - removing device object by handle
- * @ioc: per adapter object
- * @handle: device handle
- *
- * Return nothing.
- */
-static void
-_scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _sas_device *sas_device;
- unsigned long flags;
-
- if (ioc->shost_recovery)
- return;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device) {
- list_del_init(&sas_device->list);
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (sas_device) {
- _scsih_remove_device(ioc, sas_device);
- sas_device_put(sas_device);
- }
-}
-
-/**
- * mpt2sas_device_remove_by_sas_address - removing device object by sas address
- * @ioc: per adapter object
- * @sas_address: device sas_address
- *
- * Return nothing.
- */
-void
-mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address)
-{
- struct _sas_device *sas_device;
- unsigned long flags;
-
- if (ioc->shost_recovery)
- return;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc, sas_address);
- if (sas_device) {
- list_del_init(&sas_device->list);
- sas_device_put(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (sas_device) {
- _scsih_remove_device(ioc, sas_device);
- sas_device_put(sas_device);
- }
-}
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_topology_change_event_debug - debug for topology event
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- */
-static void
-_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataSasTopologyChangeList_t *event_data)
-{
- int i;
- u16 handle;
- u16 reason_code;
- u8 phy_number;
- char *status_str = NULL;
- u8 link_rate, prev_link_rate;
-
- switch (event_data->ExpStatus) {
- case MPI2_EVENT_SAS_TOPO_ES_ADDED:
- status_str = "add";
- break;
- case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
- status_str = "remove";
- break;
- case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
- case 0:
- status_str = "responding";
- break;
- case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
- status_str = "remove delay";
- break;
- default:
- status_str = "unknown status";
- break;
- }
- printk(MPT2SAS_INFO_FMT "sas topology change: (%s)\n",
- ioc->name, status_str);
- printk(KERN_INFO "\thandle(0x%04x), enclosure_handle(0x%04x) "
- "start_phy(%02d), count(%d)\n",
- le16_to_cpu(event_data->ExpanderDevHandle),
- le16_to_cpu(event_data->EnclosureHandle),
- event_data->StartPhyNum, event_data->NumEntries);
- for (i = 0; i < event_data->NumEntries; i++) {
- handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
- if (!handle)
- continue;
- phy_number = event_data->StartPhyNum + i;
- reason_code = event_data->PHY[i].PhyStatus &
- MPI2_EVENT_SAS_TOPO_RC_MASK;
- switch (reason_code) {
- case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
- status_str = "target add";
- break;
- case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
- status_str = "target remove";
- break;
- case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
- status_str = "delay target remove";
- break;
- case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
- status_str = "link rate change";
- break;
- case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
- status_str = "target responding";
- break;
- default:
- status_str = "unknown";
- break;
- }
- link_rate = event_data->PHY[i].LinkRate >> 4;
- prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
- printk(KERN_INFO "\tphy(%02d), attached_handle(0x%04x): %s:"
- " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
- handle, status_str, link_rate, prev_link_rate);
-
- }
-}
-#endif
-
-/**
- * _scsih_sas_topology_change_event - handle topology changes
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- */
-static void
-_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- int i;
- u16 parent_handle, handle;
- u16 reason_code;
- u8 phy_number, max_phys;
- struct _sas_node *sas_expander;
- u64 sas_address;
- unsigned long flags;
- u8 link_rate, prev_link_rate;
- Mpi2EventDataSasTopologyChangeList_t *event_data =
- (Mpi2EventDataSasTopologyChangeList_t *)
- fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
- _scsih_sas_topology_change_event_debug(ioc, event_data);
-#endif
-
- if (ioc->remove_host || ioc->pci_error_recovery)
- return;
-
- if (!ioc->sas_hba.num_phys)
- _scsih_sas_host_add(ioc);
- else
- _scsih_sas_host_refresh(ioc);
-
- if (fw_event->ignore) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring expander "
- "event\n", ioc->name));
- return;
- }
-
- parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
-
- /* handle expander add */
- if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
- if (_scsih_expander_add(ioc, parent_handle) != 0)
- return;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
- parent_handle);
- if (sas_expander) {
- sas_address = sas_expander->sas_address;
- max_phys = sas_expander->num_phys;
- } else if (parent_handle < ioc->sas_hba.num_phys) {
- sas_address = ioc->sas_hba.sas_address;
- max_phys = ioc->sas_hba.num_phys;
- } else {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- /* handle siblings events */
- for (i = 0; i < event_data->NumEntries; i++) {
- if (fw_event->ignore) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring "
- "expander event\n", ioc->name));
- return;
- }
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery)
- return;
- phy_number = event_data->StartPhyNum + i;
- if (phy_number >= max_phys)
- continue;
- reason_code = event_data->PHY[i].PhyStatus &
- MPI2_EVENT_SAS_TOPO_RC_MASK;
- if ((event_data->PHY[i].PhyStatus &
- MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
- MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
- continue;
- handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
- if (!handle)
- continue;
- link_rate = event_data->PHY[i].LinkRate >> 4;
- prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
- switch (reason_code) {
- case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
-
- if (ioc->shost_recovery)
- break;
-
- if (link_rate == prev_link_rate)
- break;
-
- mpt2sas_transport_update_links(ioc, sas_address,
- handle, phy_number, link_rate);
-
- if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
- break;
-
- _scsih_check_device(ioc, handle);
- break;
- case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
-
- if (ioc->shost_recovery)
- break;
-
- mpt2sas_transport_update_links(ioc, sas_address,
- handle, phy_number, link_rate);
-
- _scsih_add_device(ioc, handle, phy_number, 0);
- break;
- case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
-
- _scsih_device_remove_by_handle(ioc, handle);
- break;
- }
- }
-
- /* handle expander removal */
- if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
- sas_expander)
- mpt2sas_expander_remove(ioc, sas_address);
-
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_device_status_change_event_debug - debug for device event
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataSasDeviceStatusChange_t *event_data)
-{
- char *reason_str = NULL;
-
- switch (event_data->ReasonCode) {
- case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
- reason_str = "smart data";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
- reason_str = "unsupported device discovered";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
- reason_str = "internal device reset";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
- reason_str = "internal task abort";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
- reason_str = "internal task abort set";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
- reason_str = "internal clear task set";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
- reason_str = "internal query task";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
- reason_str = "sata init failure";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
- reason_str = "internal device reset complete";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
- reason_str = "internal task abort complete";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
- reason_str = "internal async notification";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
- reason_str = "expander reduced functionality";
- break;
- case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
- reason_str = "expander reduced functionality complete";
- break;
- default:
- reason_str = "unknown reason";
- break;
- }
- printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
- "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
- ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
- (unsigned long long)le64_to_cpu(event_data->SASAddress),
- le16_to_cpu(event_data->TaskTag));
- if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
- printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
- event_data->ASC, event_data->ASCQ);
- printk(KERN_INFO "\n");
-}
-#endif
-
-/**
- * _scsih_sas_device_status_change_event - handle device status change
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- struct MPT2SAS_TARGET *target_priv_data;
- struct _sas_device *sas_device;
- u64 sas_address;
- unsigned long flags;
- Mpi2EventDataSasDeviceStatusChange_t *event_data =
- (Mpi2EventDataSasDeviceStatusChange_t *)
- fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
- _scsih_sas_device_status_change_event_debug(ioc,
- event_data);
-#endif
-
- /* In MPI Revision K (0xC), the internal device reset complete was
- * implemented, so avoid setting tm_busy flag for older firmware.
- */
- if ((ioc->facts.HeaderVersion >> 8) < 0xC)
- return;
-
- if (event_data->ReasonCode !=
- MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
- event_data->ReasonCode !=
- MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
- return;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_address = le64_to_cpu(event_data->SASAddress);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- sas_address);
-
- if (!sas_device || !sas_device->starget)
- goto out;
-
- target_priv_data = sas_device->starget->hostdata;
- if (!target_priv_data)
- goto out;
-
- if (event_data->ReasonCode ==
- MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
- target_priv_data->tm_busy = 1;
- else
- target_priv_data->tm_busy = 0;
-
-out:
- if (sas_device)
- sas_device_put(sas_device);
-
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataSasEnclDevStatusChange_t *event_data)
-{
- char *reason_str = NULL;
-
- switch (event_data->ReasonCode) {
- case MPI2_EVENT_SAS_ENCL_RC_ADDED:
- reason_str = "enclosure add";
- break;
- case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
- reason_str = "enclosure remove";
- break;
- default:
- reason_str = "unknown reason";
- break;
- }
-
- printk(MPT2SAS_INFO_FMT "enclosure status change: (%s)\n"
- "\thandle(0x%04x), enclosure logical id(0x%016llx)"
- " number slots(%d)\n", ioc->name, reason_str,
- le16_to_cpu(event_data->EnclosureHandle),
- (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
- le16_to_cpu(event_data->StartSlot));
-}
-#endif
-
-/**
- * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
- _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
- (Mpi2EventDataSasEnclDevStatusChange_t *)
- fw_event->event_data);
-#endif
-}
-
-/**
- * _scsih_sas_broadcast_primitive_event - handle broadcast events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- struct scsi_cmnd *scmd;
- struct scsi_device *sdev;
- u16 smid, handle;
- u32 lun;
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- u32 termination_count;
- u32 query_count;
- Mpi2SCSITaskManagementReply_t *mpi_reply;
- Mpi2EventDataSasBroadcastPrimitive_t *event_data =
- (Mpi2EventDataSasBroadcastPrimitive_t *)
- fw_event->event_data;
- u16 ioc_status;
- unsigned long flags;
- int r;
- u8 max_retries = 0;
- u8 task_abort_retries;
-
- mutex_lock(&ioc->tm_cmds.mutex);
- pr_info(MPT2SAS_FMT
- "%s: enter: phy number(%d), width(%d)\n",
- ioc->name, __func__, event_data->PhyNum,
- event_data->PortWidth);
-
- _scsih_block_io_all_device(ioc);
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- mpi_reply = ioc->tm_cmds.reply;
-broadcast_aen_retry:
-
- /* sanity checks for retrying this loop */
- if (max_retries++ == 5) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
- ioc->name, __func__));
- goto out;
- } else if (max_retries > 1)
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
- ioc->name, __func__, max_retries - 1));
-
- termination_count = 0;
- query_count = 0;
- for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
- if (ioc->shost_recovery)
- goto out;
- scmd = _scsih_scsi_lookup_get(ioc, smid);
- if (!scmd)
- continue;
- sdev = scmd->device;
- sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
- continue;
- /* skip hidden raid components */
- if (sas_device_priv_data->sas_target->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT)
- continue;
- /* skip volumes */
- if (sas_device_priv_data->sas_target->flags &
- MPT_TARGET_FLAGS_VOLUME)
- continue;
-
- handle = sas_device_priv_data->sas_target->handle;
- lun = sas_device_priv_data->lun;
- query_count++;
-
- if (ioc->shost_recovery)
- goto out;
-
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
- MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30,
- TM_MUTEX_OFF);
- if (r == FAILED) {
- sdev_printk(KERN_WARNING, sdev,
- "mpt2sas_scsih_issue_tm: FAILED when sending "
- "QUERY_TASK: scmd(%p)\n", scmd);
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- goto broadcast_aen_retry;
- }
- ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
- & MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
- "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
- scmd);
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- goto broadcast_aen_retry;
- }
-
- /* see if IO is still owned by IOC and target */
- if (mpi_reply->ResponseCode ==
- MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
- mpi_reply->ResponseCode ==
- MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- continue;
- }
- task_abort_retries = 0;
- tm_retry:
- if (task_abort_retries++ == 60) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s: ABORT_TASK: giving up\n", ioc->name,
- __func__));
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- goto broadcast_aen_retry;
- }
-
- if (ioc->shost_recovery)
- goto out_no_lock;
-
- r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
- sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
- TM_MUTEX_OFF);
- if (r == FAILED) {
- sdev_printk(KERN_WARNING, sdev,
- "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
- "scmd(%p)\n", scmd);
- goto tm_retry;
- }
-
- if (task_abort_retries > 1)
- sdev_printk(KERN_WARNING, sdev,
- "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
- " scmd(%p)\n",
- task_abort_retries - 1, scmd);
-
- termination_count += le32_to_cpu(mpi_reply->TerminationCount);
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- }
-
- if (ioc->broadcast_aen_pending) {
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
- " pending AEN\n", ioc->name, __func__));
- ioc->broadcast_aen_pending = 0;
- goto broadcast_aen_retry;
- }
-
- out:
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- out_no_lock:
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s - exit, query_count = %d termination_count = %d\n",
- ioc->name, __func__, query_count, termination_count));
-
- ioc->broadcast_aen_busy = 0;
- if (!ioc->shost_recovery)
- _scsih_ublock_io_all_device(ioc);
- mutex_unlock(&ioc->tm_cmds.mutex);
-}
-
-/**
- * _scsih_sas_discovery_event - handle discovery events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- Mpi2EventDataSasDiscovery_t *event_data =
- (Mpi2EventDataSasDiscovery_t *)
- fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
- printk(MPT2SAS_INFO_FMT "discovery event: (%s)", ioc->name,
- (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
- "start" : "stop");
- if (event_data->DiscoveryStatus)
- printk("discovery_status(0x%08x)",
- le32_to_cpu(event_data->DiscoveryStatus));
- printk("\n");
- }
-#endif
-
- if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
- !ioc->sas_hba.num_phys) {
- if (disable_discovery > 0 && ioc->shost_recovery) {
- /* Wait for the reset to complete */
- while (ioc->shost_recovery)
- ssleep(1);
- }
- _scsih_sas_host_add(ioc);
- }
-}
-
-/**
- * _scsih_reprobe_lun - reprobing lun
- * @sdev: scsi device struct
- * @no_uld_attach: sdev->no_uld_attach flag setting
- *
- **/
-static void
-_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
-{
- int rc;
-
- sdev->no_uld_attach = no_uld_attach ? 1 : 0;
- sdev_printk(KERN_INFO, sdev, "%s raid component\n",
- sdev->no_uld_attach ? "hidding" : "exposing");
- rc = scsi_device_reprobe(sdev);
-}
-
-/**
- * _scsih_sas_volume_add - add new volume
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventIrConfigElement_t *element)
-{
- struct _raid_device *raid_device;
- unsigned long flags;
- u64 wwid;
- u16 handle = le16_to_cpu(element->VolDevHandle);
- int rc;
-
- mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
- if (!wwid) {
- printk(MPT2SAS_ERR_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- return;
- }
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
- if (raid_device)
- return;
-
- raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
- if (!raid_device) {
- printk(MPT2SAS_ERR_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- return;
- }
-
- raid_device->id = ioc->sas_id++;
- raid_device->channel = RAID_CHANNEL;
- raid_device->handle = handle;
- raid_device->wwid = wwid;
- _scsih_raid_device_add(ioc, raid_device);
- if (!ioc->wait_for_discovery_to_complete) {
- rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
- raid_device->id, 0);
- if (rc)
- _scsih_raid_device_remove(ioc, raid_device);
- } else {
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- _scsih_determine_boot_device(ioc, raid_device, 1);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- }
-}
-
-/**
- * _scsih_sas_volume_delete - delete volume
- * @ioc: per adapter object
- * @handle: volume device handle
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
- struct _raid_device *raid_device;
- unsigned long flags;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct scsi_target *starget = NULL;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- if (raid_device) {
- if (raid_device->starget) {
- starget = raid_device->starget;
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->deleted = 1;
- }
- printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
- "(0x%016llx)\n", ioc->name, raid_device->handle,
- (unsigned long long) raid_device->wwid);
- list_del(&raid_device->list);
- kfree(raid_device);
- }
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (starget)
- scsi_remove_target(&starget->dev);
-}
-
-/**
- * _scsih_sas_pd_expose - expose pd component to /dev/sdX
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventIrConfigElement_t *element)
-{
- struct _sas_device *sas_device;
- struct scsi_target *starget = NULL;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- unsigned long flags;
- u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device) {
- sas_device->volume_handle = 0;
- sas_device->volume_wwid = 0;
- clear_bit(handle, ioc->pd_handles);
- if (sas_device->starget && sas_device->starget->hostdata) {
- starget = sas_device->starget;
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->flags &=
- ~MPT_TARGET_FLAGS_RAID_COMPONENT;
- }
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- return;
-
- /* exposing raid component */
- if (starget)
- starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
-
- sas_device_put(sas_device);
-}
-
-/**
- * _scsih_sas_pd_hide - hide pd component from /dev/sdX
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventIrConfigElement_t *element)
-{
- struct _sas_device *sas_device;
- struct scsi_target *starget = NULL;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- unsigned long flags;
- u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
- u16 volume_handle = 0;
- u64 volume_wwid = 0;
-
- mpt2sas_config_get_volume_handle(ioc, handle, &volume_handle);
- if (volume_handle)
- mpt2sas_config_get_volume_wwid(ioc, volume_handle,
- &volume_wwid);
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device) {
- set_bit(handle, ioc->pd_handles);
- if (sas_device->starget && sas_device->starget->hostdata) {
- starget = sas_device->starget;
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->flags |=
- MPT_TARGET_FLAGS_RAID_COMPONENT;
- sas_device->volume_handle = volume_handle;
- sas_device->volume_wwid = volume_wwid;
- }
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- return;
-
- /* hiding raid component */
- if (starget)
- starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
-
- sas_device_put(sas_device);
-}
-
-/**
- * _scsih_sas_pd_delete - delete pd component
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventIrConfigElement_t *element)
-{
- u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
-
- _scsih_device_remove_by_handle(ioc, handle);
-}
-
-/**
- * _scsih_sas_pd_add - remove pd component
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventIrConfigElement_t *element)
-{
- struct _sas_device *sas_device;
- u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasDevicePage0_t sas_device_pg0;
- u32 ioc_status;
- u64 sas_address;
- u16 parent_handle;
-
- set_bit(handle, ioc->pd_handles);
-
- sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device) {
- sas_device_put(sas_device);
- return;
- }
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
- if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
- mpt2sas_transport_update_links(ioc, sas_address, handle,
- sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
-
- _scsih_add_device(ioc, handle, 0, 1);
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataIrConfigChangeList_t *event_data)
-{
- Mpi2EventIrConfigElement_t *element;
- u8 element_type;
- int i;
- char *reason_str = NULL, *element_str = NULL;
-
- element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-
- printk(MPT2SAS_INFO_FMT "raid config change: (%s), elements(%d)\n",
- ioc->name, (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
- "foreign" : "native", event_data->NumElements);
- for (i = 0; i < event_data->NumElements; i++, element++) {
- switch (element->ReasonCode) {
- case MPI2_EVENT_IR_CHANGE_RC_ADDED:
- reason_str = "add";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
- reason_str = "remove";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
- reason_str = "no change";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_HIDE:
- reason_str = "hide";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
- reason_str = "unhide";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
- reason_str = "volume_created";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
- reason_str = "volume_deleted";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
- reason_str = "pd_created";
- break;
- case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
- reason_str = "pd_deleted";
- break;
- default:
- reason_str = "unknown reason";
- break;
- }
- element_type = le16_to_cpu(element->ElementFlags) &
- MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
- switch (element_type) {
- case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
- element_str = "volume";
- break;
- case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
- element_str = "phys disk";
- break;
- case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
- element_str = "hot spare";
- break;
- default:
- element_str = "unknown element";
- break;
- }
- printk(KERN_INFO "\t(%s:%s), vol handle(0x%04x), "
- "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
- reason_str, le16_to_cpu(element->VolDevHandle),
- le16_to_cpu(element->PhysDiskDevHandle),
- element->PhysDiskNum);
- }
-}
-#endif
-
-/**
- * _scsih_sas_ir_config_change_event - handle ir configuration change events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- Mpi2EventIrConfigElement_t *element;
- int i;
- u8 foreign_config;
- Mpi2EventDataIrConfigChangeList_t *event_data =
- (Mpi2EventDataIrConfigChangeList_t *)
- fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
- && !ioc->hide_ir_msg)
- _scsih_sas_ir_config_change_event_debug(ioc, event_data);
-
-#endif
-
- if (ioc->shost_recovery)
- return;
-
- foreign_config = (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
-
- element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
- for (i = 0; i < event_data->NumElements; i++, element++) {
-
- switch (element->ReasonCode) {
- case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
- case MPI2_EVENT_IR_CHANGE_RC_ADDED:
- if (!foreign_config)
- _scsih_sas_volume_add(ioc, element);
- break;
- case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
- case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
- if (!foreign_config)
- _scsih_sas_volume_delete(ioc,
- le16_to_cpu(element->VolDevHandle));
- break;
- case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
- if (!ioc->is_warpdrive)
- _scsih_sas_pd_hide(ioc, element);
- break;
- case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
- if (!ioc->is_warpdrive)
- _scsih_sas_pd_expose(ioc, element);
- break;
- case MPI2_EVENT_IR_CHANGE_RC_HIDE:
- if (!ioc->is_warpdrive)
- _scsih_sas_pd_add(ioc, element);
- break;
- case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
- if (!ioc->is_warpdrive)
- _scsih_sas_pd_delete(ioc, element);
- break;
- }
- }
-}
-
-/**
- * _scsih_sas_ir_volume_event - IR volume event
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- u64 wwid;
- unsigned long flags;
- struct _raid_device *raid_device;
- u16 handle;
- u32 state;
- int rc;
- Mpi2EventDataIrVolume_t *event_data =
- (Mpi2EventDataIrVolume_t *)
- fw_event->event_data;
-
- if (ioc->shost_recovery)
- return;
-
- if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
- return;
-
- handle = le16_to_cpu(event_data->VolDevHandle);
- state = le32_to_cpu(event_data->NewValue);
- if (!ioc->hide_ir_msg)
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
- "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
- le32_to_cpu(event_data->PreviousValue), state));
-
- switch (state) {
- case MPI2_RAID_VOL_STATE_MISSING:
- case MPI2_RAID_VOL_STATE_FAILED:
- _scsih_sas_volume_delete(ioc, handle);
- break;
-
- case MPI2_RAID_VOL_STATE_ONLINE:
- case MPI2_RAID_VOL_STATE_DEGRADED:
- case MPI2_RAID_VOL_STATE_OPTIMAL:
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
- if (raid_device)
- break;
-
- mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
- if (!wwid) {
- printk(MPT2SAS_ERR_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- break;
- }
-
- raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
- if (!raid_device) {
- printk(MPT2SAS_ERR_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__);
- break;
- }
-
- raid_device->id = ioc->sas_id++;
- raid_device->channel = RAID_CHANNEL;
- raid_device->handle = handle;
- raid_device->wwid = wwid;
- _scsih_raid_device_add(ioc, raid_device);
- rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
- raid_device->id, 0);
- if (rc)
- _scsih_raid_device_remove(ioc, raid_device);
- break;
-
- case MPI2_RAID_VOL_STATE_INITIALIZING:
- default:
- break;
- }
-}
-
-/**
- * _scsih_sas_ir_physical_disk_event - PD event
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- u16 handle, parent_handle;
- u32 state;
- struct _sas_device *sas_device;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasDevicePage0_t sas_device_pg0;
- u32 ioc_status;
- Mpi2EventDataIrPhysicalDisk_t *event_data =
- (Mpi2EventDataIrPhysicalDisk_t *)
- fw_event->event_data;
- u64 sas_address;
-
- if (ioc->shost_recovery)
- return;
-
- if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
- return;
-
- handle = le16_to_cpu(event_data->PhysDiskDevHandle);
- state = le32_to_cpu(event_data->NewValue);
-
- if (!ioc->hide_ir_msg)
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
- "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
- le32_to_cpu(event_data->PreviousValue), state));
-
- switch (state) {
- case MPI2_RAID_PD_STATE_ONLINE:
- case MPI2_RAID_PD_STATE_DEGRADED:
- case MPI2_RAID_PD_STATE_REBUILDING:
- case MPI2_RAID_PD_STATE_OPTIMAL:
- case MPI2_RAID_PD_STATE_HOT_SPARE:
-
- if (!ioc->is_warpdrive)
- set_bit(handle, ioc->pd_handles);
-
- sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device) {
- sas_device_put(sas_device);
- return;
- }
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
- &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
- handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
- if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
- mpt2sas_transport_update_links(ioc, sas_address, handle,
- sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
-
- _scsih_add_device(ioc, handle, 0, 1);
-
- break;
-
- case MPI2_RAID_PD_STATE_OFFLINE:
- case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
- case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
- default:
- break;
- }
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
- Mpi2EventDataIrOperationStatus_t *event_data)
-{
- char *reason_str = NULL;
-
- switch (event_data->RAIDOperation) {
- case MPI2_EVENT_IR_RAIDOP_RESYNC:
- reason_str = "resync";
- break;
- case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
- reason_str = "online capacity expansion";
- break;
- case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
- reason_str = "consistency check";
- break;
- case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
- reason_str = "background init";
- break;
- case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
- reason_str = "make data consistent";
- break;
- }
-
- if (!reason_str)
- return;
-
- printk(MPT2SAS_INFO_FMT "raid operational status: (%s)"
- "\thandle(0x%04x), percent complete(%d)\n",
- ioc->name, reason_str,
- le16_to_cpu(event_data->VolDevHandle),
- event_data->PercentComplete);
-}
-#endif
-
-/**
- * _scsih_sas_ir_operation_status_event - handle RAID operation events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
- struct fw_event_work *fw_event)
-{
- Mpi2EventDataIrOperationStatus_t *event_data =
- (Mpi2EventDataIrOperationStatus_t *)
- fw_event->event_data;
- static struct _raid_device *raid_device;
- unsigned long flags;
- u16 handle;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
- if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
- && !ioc->hide_ir_msg)
- _scsih_sas_ir_operation_status_event_debug(ioc,
- event_data);
-#endif
-
- /* code added for raid transport support */
- if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- handle = le16_to_cpu(event_data->VolDevHandle);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- if (raid_device)
- raid_device->percent_complete =
- event_data->PercentComplete;
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- }
-}
-
-/**
- * _scsih_prep_device_scan - initialize parameters prior to device scan
- * @ioc: per adapter object
- *
- * Set the deleted flag prior to device scan. If the device is found during
- * the scan, then we clear the deleted flag.
- */
-static void
-_scsih_prep_device_scan(struct MPT2SAS_ADAPTER *ioc)
-{
- struct MPT2SAS_DEVICE *sas_device_priv_data;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, ioc->shost) {
- sas_device_priv_data = sdev->hostdata;
- if (sas_device_priv_data && sas_device_priv_data->sas_target)
- sas_device_priv_data->sas_target->deleted = 1;
- }
-}
-
-/**
- * _scsih_mark_responding_sas_device - mark a sas_devices as responding
- * @ioc: per adapter object
- * @sas_address: sas address
- * @slot: enclosure slot id
- * @handle: device handle
- *
- * After host reset, find out whether devices are still responding.
- * Used in _scsi_remove_unresponsive_sas_devices.
- *
- * Return nothing.
- */
-static void
-_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
- u16 slot, u16 handle)
-{
- struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
- struct scsi_target *starget;
- struct _sas_device *sas_device;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
- if (sas_device->sas_address == sas_address &&
- sas_device->slot == slot) {
- sas_device->responding = 1;
- starget = sas_device->starget;
- if (starget && starget->hostdata) {
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->tm_busy = 0;
- sas_target_priv_data->deleted = 0;
- } else
- sas_target_priv_data = NULL;
- if (starget)
- starget_printk(KERN_INFO, starget,
- "handle(0x%04x), sas_addr(0x%016llx), "
- "enclosure logical id(0x%016llx), "
- "slot(%d)\n", handle,
- (unsigned long long)sas_device->sas_address,
- (unsigned long long)
- sas_device->enclosure_logical_id,
- sas_device->slot);
- if (sas_device->handle == handle)
- goto out;
- printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
- sas_device->handle);
- sas_device->handle = handle;
- if (sas_target_priv_data)
- sas_target_priv_data->handle = handle;
- goto out;
- }
- }
- out:
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-/**
- * _scsih_search_responding_sas_devices -
- * @ioc: per adapter object
- *
- * After host reset, find out whether devices are still responding.
- * If not remove.
- *
- * Return nothing.
- */
-static void
-_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u16 ioc_status;
- __le64 sas_address;
- u16 handle;
- u32 device_info;
- u16 slot;
-
- printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
-
- if (list_empty(&ioc->sas_device_list))
- goto out;
-
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
- &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
- handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- break;
- handle = le16_to_cpu(sas_device_pg0.DevHandle);
- device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
- if (!(_scsih_is_end_device(device_info)))
- continue;
- sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
- slot = le16_to_cpu(sas_device_pg0.Slot);
- _scsih_mark_responding_sas_device(ioc, sas_address, slot,
- handle);
- }
-out:
- printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
- ioc->name);
-}
-
-/**
- * _scsih_mark_responding_raid_device - mark a raid_device as responding
- * @ioc: per adapter object
- * @wwid: world wide identifier for raid volume
- * @handle: device handle
- *
- * After host reset, find out whether devices are still responding.
- * Used in _scsi_remove_unresponsive_raid_devices.
- *
- * Return nothing.
- */
-static void
-_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
- u16 handle)
-{
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct scsi_target *starget;
- struct _raid_device *raid_device;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
- if (raid_device->wwid == wwid && raid_device->starget) {
- starget = raid_device->starget;
- if (starget && starget->hostdata) {
- sas_target_priv_data = starget->hostdata;
- sas_target_priv_data->deleted = 0;
- } else
- sas_target_priv_data = NULL;
- raid_device->responding = 1;
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- starget_printk(KERN_INFO, raid_device->starget,
- "handle(0x%04x), wwid(0x%016llx)\n", handle,
- (unsigned long long)raid_device->wwid);
- /*
- * WARPDRIVE: The handles of the PDs might have changed
- * across the host reset so re-initialize the
- * required data for Direct IO
- */
- _scsih_init_warpdrive_properties(ioc, raid_device);
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- if (raid_device->handle == handle) {
- spin_unlock_irqrestore(&ioc->raid_device_lock,
- flags);
- return;
- }
- printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
- raid_device->handle);
- raid_device->handle = handle;
- if (sas_target_priv_data)
- sas_target_priv_data->handle = handle;
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- return;
- }
- }
-
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * _scsih_search_responding_raid_devices -
- * @ioc: per adapter object
- *
- * After host reset, find out whether devices are still responding.
- * If not remove.
- *
- * Return nothing.
- */
-static void
-_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2RaidVolPage1_t volume_pg1;
- Mpi2RaidVolPage0_t volume_pg0;
- Mpi2RaidPhysDiskPage0_t pd_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u16 ioc_status;
- u16 handle;
- u8 phys_disk_num;
-
- if (!ioc->ir_firmware)
- return;
-
- printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
- ioc->name);
-
- if (list_empty(&ioc->raid_device_list))
- goto out;
-
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
- &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- break;
- handle = le16_to_cpu(volume_pg1.DevHandle);
-
- if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
- &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
- sizeof(Mpi2RaidVolPage0_t)))
- continue;
-
- if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
- volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
- volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
- _scsih_mark_responding_raid_device(ioc,
- le64_to_cpu(volume_pg1.WWID), handle);
- }
-
- /* refresh the pd_handles */
- if (!ioc->is_warpdrive) {
- phys_disk_num = 0xFF;
- memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
- while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
- &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
- phys_disk_num))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- break;
- phys_disk_num = pd_pg0.PhysDiskNum;
- handle = le16_to_cpu(pd_pg0.DevHandle);
- set_bit(handle, ioc->pd_handles);
- }
- }
-out:
- printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
- "complete\n", ioc->name);
-}
-
-/**
- * _scsih_mark_responding_expander - mark a expander as responding
- * @ioc: per adapter object
- * @sas_address: sas address
- * @handle:
- *
- * After host reset, find out whether devices are still responding.
- * Used in _scsi_remove_unresponsive_expanders.
- *
- * Return nothing.
- */
-static void
-_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
- u16 handle)
-{
- struct _sas_node *sas_expander;
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
- if (sas_expander->sas_address != sas_address)
- continue;
- sas_expander->responding = 1;
- if (sas_expander->handle == handle)
- goto out;
- printk(KERN_INFO "\texpander(0x%016llx): handle changed"
- " from(0x%04x) to (0x%04x)!!!\n",
- (unsigned long long)sas_expander->sas_address,
- sas_expander->handle, handle);
- sas_expander->handle = handle;
- for (i = 0 ; i < sas_expander->num_phys ; i++)
- sas_expander->phy[i].handle = handle;
- goto out;
- }
- out:
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-}
-
-/**
- * _scsih_search_responding_expanders -
- * @ioc: per adapter object
- *
- * After host reset, find out whether devices are still responding.
- * If not remove.
- *
- * Return nothing.
- */
-static void
-_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2ExpanderPage0_t expander_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u16 ioc_status;
- u64 sas_address;
- u16 handle;
-
- printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
-
- if (list_empty(&ioc->sas_expander_list))
- goto out;
-
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
- MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
- break;
-
- handle = le16_to_cpu(expander_pg0.DevHandle);
- sas_address = le64_to_cpu(expander_pg0.SASAddress);
- printk(KERN_INFO "\texpander present: handle(0x%04x), "
- "sas_addr(0x%016llx)\n", handle,
- (unsigned long long)sas_address);
- _scsih_mark_responding_expander(ioc, sas_address, handle);
- }
-
- out:
- printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
-}
-
-/**
- * _scsih_remove_unresponding_sas_devices - removing unresponding devices
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
-{
- struct _sas_device *sas_device, *sas_device_next;
- struct _sas_node *sas_expander, *sas_expander_next;
- struct _raid_device *raid_device, *raid_device_next;
- struct list_head tmp_list;
- unsigned long flags;
- LIST_HEAD(head);
-
- printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
- ioc->name);
-
- /* removing unresponding end devices */
- printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n",
- ioc->name);
-
- /*
- * Iterate, pulling off devices marked as non-responding. We become the
- * owner for the reference the list had on any object we prune.
- */
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- list_for_each_entry_safe(sas_device, sas_device_next,
- &ioc->sas_device_list, list) {
- if (!sas_device->responding)
- list_move_tail(&sas_device->list, &head);
- else
- sas_device->responding = 0;
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- /*
- * Now, uninitialize and remove the unresponding devices we pruned.
- */
- list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
- _scsih_remove_device(ioc, sas_device);
- list_del_init(&sas_device->list);
- sas_device_put(sas_device);
- }
-
- /* removing unresponding volumes */
- if (ioc->ir_firmware) {
- printk(MPT2SAS_INFO_FMT "removing unresponding devices: "
- "volumes\n", ioc->name);
- list_for_each_entry_safe(raid_device, raid_device_next,
- &ioc->raid_device_list, list) {
- if (!raid_device->responding)
- _scsih_sas_volume_delete(ioc,
- raid_device->handle);
- else
- raid_device->responding = 0;
- }
- }
- /* removing unresponding expanders */
- printk(MPT2SAS_INFO_FMT "removing unresponding devices: expanders\n",
- ioc->name);
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- INIT_LIST_HEAD(&tmp_list);
- list_for_each_entry_safe(sas_expander, sas_expander_next,
- &ioc->sas_expander_list, list) {
- if (!sas_expander->responding)
- list_move_tail(&sas_expander->list, &tmp_list);
- else
- sas_expander->responding = 0;
- }
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
- list) {
- list_del(&sas_expander->list);
- _scsih_expander_node_remove(ioc, sas_expander);
- }
- printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
- ioc->name);
- /* unblock devices */
- _scsih_ublock_io_all_device(ioc);
-}
-
-static void
-_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_expander, u16 handle)
-{
- Mpi2ExpanderPage1_t expander_pg1;
- Mpi2ConfigReply_t mpi_reply;
- int i;
-
- for (i = 0 ; i < sas_expander->num_phys ; i++) {
- if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
- &expander_pg1, i, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
- le16_to_cpu(expander_pg1.AttachedDevHandle), i,
- expander_pg1.NegotiatedLinkRate >> 4);
- }
-}
-
-/**
- * _scsih_scan_for_devices_after_reset - scan for devices after host reset
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2ExpanderPage0_t expander_pg0;
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2RaidVolPage1_t volume_pg1;
- Mpi2RaidVolPage0_t volume_pg0;
- Mpi2RaidPhysDiskPage0_t pd_pg0;
- Mpi2EventIrConfigElement_t element;
- Mpi2ConfigReply_t mpi_reply;
- u8 phys_disk_num;
- u16 ioc_status;
- u16 handle, parent_handle;
- u64 sas_address;
- struct _sas_device *sas_device;
- struct _sas_node *expander_device;
- static struct _raid_device *raid_device;
- u8 retry_count;
- unsigned long flags;
-
- printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
-
- _scsih_sas_host_refresh(ioc);
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n",
- ioc->name);
- /* expanders */
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
- MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: "
- "ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, ioc_status,
- le32_to_cpu(mpi_reply.IOCLogInfo));
- break;
- }
- handle = le16_to_cpu(expander_pg0.DevHandle);
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- expander_device = mpt2sas_scsih_expander_find_by_sas_address(
- ioc, le64_to_cpu(expander_pg0.SASAddress));
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (expander_device)
- _scsih_refresh_expander_links(ioc, expander_device,
- handle);
- else {
- printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: "
- "handle (0x%04x), sas_addr(0x%016llx)\n",
- ioc->name, handle, (unsigned long long)
- le64_to_cpu(expander_pg0.SASAddress));
- _scsih_expander_add(ioc, handle);
- printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: "
- "handle (0x%04x), sas_addr(0x%016llx)\n",
- ioc->name, handle, (unsigned long long)
- le64_to_cpu(expander_pg0.SASAddress));
- }
- }
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n",
- ioc->name);
-
- if (!ioc->ir_firmware)
- goto skip_to_sas;
-
- printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name);
- /* phys disk */
- phys_disk_num = 0xFF;
- while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
- &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
- phys_disk_num))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:"
- "ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, ioc_status,
- le32_to_cpu(mpi_reply.IOCLogInfo));
- break;
- }
- phys_disk_num = pd_pg0.PhysDiskNum;
- handle = le16_to_cpu(pd_pg0.DevHandle);
- sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
- if (sas_device) {
- sas_device_put(sas_device);
- continue;
- }
- if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
- &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
- handle) != 0)
- continue;
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan "
- "ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, ioc_status,
- le32_to_cpu(mpi_reply.IOCLogInfo));
- break;
- }
- parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
- if (!_scsih_get_sas_address(ioc, parent_handle,
- &sas_address)) {
- printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: "
- " handle (0x%04x), sas_addr(0x%016llx)\n",
- ioc->name, handle, (unsigned long long)
- le64_to_cpu(sas_device_pg0.SASAddress));
- mpt2sas_transport_update_links(ioc, sas_address,
- handle, sas_device_pg0.PhyNum,
- MPI2_SAS_NEG_LINK_RATE_1_5);
- set_bit(handle, ioc->pd_handles);
- retry_count = 0;
- /* This will retry adding the end device.
- * _scsih_add_device() will decide on retries and
- * return "1" when it should be retried
- */
- while (_scsih_add_device(ioc, handle, retry_count++,
- 1)) {
- ssleep(1);
- }
- printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: "
- " handle (0x%04x), sas_addr(0x%016llx)\n",
- ioc->name, handle, (unsigned long long)
- le64_to_cpu(sas_device_pg0.SASAddress));
- }
- }
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n",
- ioc->name);
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name);
- /* volumes */
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
- &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
- "ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, ioc_status,
- le32_to_cpu(mpi_reply.IOCLogInfo));
- break;
- }
- handle = le16_to_cpu(volume_pg1.DevHandle);
- spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_wwid(ioc,
- le64_to_cpu(volume_pg1.WWID));
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (raid_device)
- continue;
- if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
- &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
- sizeof(Mpi2RaidVolPage0_t)))
- continue;
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
- "ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, ioc_status,
- le32_to_cpu(mpi_reply.IOCLogInfo));
- break;
- }
- if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
- volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
- volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
- memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
- element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
- element.VolDevHandle = volume_pg1.DevHandle;
- printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: "
- " handle (0x%04x)\n", ioc->name,
- volume_pg1.DevHandle);
- _scsih_sas_volume_add(ioc, &element);
- printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: "
- " handle (0x%04x)\n", ioc->name,
- volume_pg1.DevHandle);
- }
- }
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n",
- ioc->name);
-
- skip_to_sas:
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n",
- ioc->name);
- /* sas devices */
- handle = 0xFFFF;
- while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
- &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
- handle))) {
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:"
- " ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, ioc_status,
- le32_to_cpu(mpi_reply.IOCLogInfo));
- break;
- }
- handle = le16_to_cpu(sas_device_pg0.DevHandle);
- if (!(_scsih_is_end_device(
- le32_to_cpu(sas_device_pg0.DeviceInfo))))
- continue;
- sas_device = mpt2sas_get_sdev_by_addr(ioc,
- le64_to_cpu(sas_device_pg0.SASAddress));
- if (sas_device) {
- sas_device_put(sas_device);
- continue;
- }
- parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
- if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
- printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: "
- "handle (0x%04x), sas_addr(0x%016llx)\n",
- ioc->name, handle, (unsigned long long)
- le64_to_cpu(sas_device_pg0.SASAddress));
- mpt2sas_transport_update_links(ioc, sas_address, handle,
- sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
- retry_count = 0;
- /* This will retry adding the end device.
- * _scsih_add_device() will decide on retries and
- * return "1" when it should be retried
- */
- while (_scsih_add_device(ioc, handle, retry_count++,
- 0)) {
- ssleep(1);
- }
- printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: "
- "handle (0x%04x), sas_addr(0x%016llx)\n",
- ioc->name, handle, (unsigned long long)
- le64_to_cpu(sas_device_pg0.SASAddress));
- }
- }
-
- printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n",
- ioc->name);
-
- printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
-}
-
-
-/**
- * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- *
- * Return nothing.
- */
-void
-mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
- switch (reset_phase) {
- case MPT2_IOC_PRE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
- break;
- case MPT2_IOC_AFTER_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
- if (ioc->scsih_cmds.status & MPT2_CMD_PENDING) {
- ioc->scsih_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
- complete(&ioc->scsih_cmds.done);
- }
- if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
- ioc->tm_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
- complete(&ioc->tm_cmds.done);
- }
- _scsih_fw_event_cleanup_queue(ioc);
- _scsih_flush_running_cmds(ioc);
- break;
- case MPT2_IOC_DONE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
- "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
- _scsih_sas_host_refresh(ioc);
- _scsih_prep_device_scan(ioc);
- _scsih_search_responding_sas_devices(ioc);
- _scsih_search_responding_raid_devices(ioc);
- _scsih_search_responding_expanders(ioc);
- if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
- !ioc->sas_hba.num_phys)) {
- _scsih_prep_device_scan(ioc);
- _scsih_search_responding_sas_devices(ioc);
- _scsih_search_responding_raid_devices(ioc);
- _scsih_search_responding_expanders(ioc);
- _scsih_error_recovery_delete_devices(ioc);
- }
- break;
- }
-}
-
-/**
- * _firmware_event_work - delayed task for processing firmware events
- * @ioc: per adapter object
- * @work: equal to the fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_firmware_event_work(struct work_struct *work)
-{
- struct fw_event_work *fw_event = container_of(work,
- struct fw_event_work, delayed_work.work);
- struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
-
- _scsih_fw_event_del_from_list(ioc, fw_event);
-
- /* the queue is being flushed so ignore this event */
- if (ioc->remove_host || ioc->pci_error_recovery) {
- fw_event_work_put(fw_event);
- return;
- }
-
- switch (fw_event->event) {
- case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
- while (scsi_host_in_recovery(ioc->shost) ||
- ioc->shost_recovery) {
- /*
- * If we're unloading, bail. Otherwise, this can become
- * an infinite loop.
- */
- if (ioc->remove_host)
- goto out;
-
- ssleep(1);
- }
- _scsih_remove_unresponding_sas_devices(ioc);
- _scsih_scan_for_devices_after_reset(ioc);
- break;
- case MPT2SAS_PORT_ENABLE_COMPLETE:
- ioc->start_scan = 0;
-
- if (missing_delay[0] != -1 && missing_delay[1] != -1)
- mpt2sas_base_update_missing_delay(ioc, missing_delay[0],
- missing_delay[1]);
-
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
- "from worker thread\n", ioc->name));
- break;
- case MPT2SAS_TURN_ON_PFA_LED:
- _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
- break;
- case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
- _scsih_sas_topology_change_event(ioc, fw_event);
- break;
- case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
- _scsih_sas_device_status_change_event(ioc,
- fw_event);
- break;
- case MPI2_EVENT_SAS_DISCOVERY:
- _scsih_sas_discovery_event(ioc,
- fw_event);
- break;
- case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
- _scsih_sas_broadcast_primitive_event(ioc,
- fw_event);
- break;
- case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
- _scsih_sas_enclosure_dev_status_change_event(ioc,
- fw_event);
- break;
- case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
- _scsih_sas_ir_config_change_event(ioc, fw_event);
- break;
- case MPI2_EVENT_IR_VOLUME:
- _scsih_sas_ir_volume_event(ioc, fw_event);
- break;
- case MPI2_EVENT_IR_PHYSICAL_DISK:
- _scsih_sas_ir_physical_disk_event(ioc, fw_event);
- break;
- case MPI2_EVENT_IR_OPERATION_STATUS:
- _scsih_sas_ir_operation_status_event(ioc, fw_event);
- break;
- }
-out:
- fw_event_work_put(fw_event);
-}
-
-/**
- * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
- * @ioc: per adapter object
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- * Context: interrupt.
- *
- * This function merely adds a new work task into ioc->firmware_event_thread.
- * The tasks are worked from _firmware_event_work in user context.
- *
- * Returns void.
- */
-void
-mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
- u32 reply)
-{
- struct fw_event_work *fw_event;
- Mpi2EventNotificationReply_t *mpi_reply;
- u16 event;
- u16 sz;
-
- /* events turned off due to host reset or driver unloading */
- if (ioc->remove_host || ioc->pci_error_recovery)
- return;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-
- if (unlikely(!mpi_reply)) {
- printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- event = le16_to_cpu(mpi_reply->Event);
-
- switch (event) {
- /* handle these */
- case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
- {
- Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
- (Mpi2EventDataSasBroadcastPrimitive_t *)
- mpi_reply->EventData;
-
- if (baen_data->Primitive !=
- MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
- return;
-
- if (ioc->broadcast_aen_busy) {
- ioc->broadcast_aen_pending++;
- return;
- } else
- ioc->broadcast_aen_busy = 1;
- break;
- }
-
- case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
- _scsih_check_topo_delete_events(ioc,
- (Mpi2EventDataSasTopologyChangeList_t *)
- mpi_reply->EventData);
- break;
- case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
- _scsih_check_ir_config_unhide_events(ioc,
- (Mpi2EventDataIrConfigChangeList_t *)
- mpi_reply->EventData);
- break;
- case MPI2_EVENT_IR_VOLUME:
- _scsih_check_volume_delete_events(ioc,
- (Mpi2EventDataIrVolume_t *)
- mpi_reply->EventData);
- break;
- case MPI2_EVENT_LOG_ENTRY_ADDED:
- {
- Mpi2EventDataLogEntryAdded_t *log_entry;
- __le32 *log_code;
-
- if (!ioc->is_warpdrive)
- break;
-
- log_entry = (Mpi2EventDataLogEntryAdded_t *)
- mpi_reply->EventData;
- log_code = (__le32 *)log_entry->LogData;
-
- if (le16_to_cpu(log_entry->LogEntryQualifier)
- != MPT2_WARPDRIVE_LOGENTRY)
- break;
-
- switch (le32_to_cpu(*log_code)) {
- case MPT2_WARPDRIVE_LC_SSDT:
- printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
- "IO Throttling has occurred in the WarpDrive "
- "subsystem. Check WarpDrive documentation for "
- "additional details.\n", ioc->name);
- break;
- case MPT2_WARPDRIVE_LC_SSDLW:
- printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
- "Program/Erase Cycles for the WarpDrive subsystem "
- "in degraded range. Check WarpDrive documentation "
- "for additional details.\n", ioc->name);
- break;
- case MPT2_WARPDRIVE_LC_SSDLF:
- printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
- "There are no Program/Erase Cycles for the "
- "WarpDrive subsystem. The storage device will be "
- "in read-only mode. Check WarpDrive documentation "
- "for additional details.\n", ioc->name);
- break;
- case MPT2_WARPDRIVE_LC_BRMF:
- printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
- "The Backup Rail Monitor has failed on the "
- "WarpDrive subsystem. Check WarpDrive "
- "documentation for additional details.\n",
- ioc->name);
- break;
- }
-
- break;
- }
- case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
- case MPI2_EVENT_IR_OPERATION_STATUS:
- case MPI2_EVENT_SAS_DISCOVERY:
- case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
- case MPI2_EVENT_IR_PHYSICAL_DISK:
- break;
-
- case MPI2_EVENT_TEMP_THRESHOLD:
- _scsih_temp_threshold_events(ioc,
- (Mpi2EventDataTemperature_t *)
- mpi_reply->EventData);
- break;
-
- default: /* ignore the rest */
- return;
- }
-
- sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
- fw_event = alloc_fw_event_work(sz);
- if (!fw_event) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return;
- }
-
- memcpy(fw_event->event_data, mpi_reply->EventData, sz);
- fw_event->ioc = ioc;
- fw_event->VF_ID = mpi_reply->VF_ID;
- fw_event->VP_ID = mpi_reply->VP_ID;
- fw_event->event = event;
- _scsih_fw_event_add(ioc, fw_event);
- fw_event_work_put(fw_event);
- return;
-}
-
-/* shost template */
-static struct scsi_host_template scsih_driver_template = {
- .module = THIS_MODULE,
- .name = "Fusion MPT SAS Host",
- .proc_name = MPT2SAS_DRIVER_NAME,
- .queuecommand = _scsih_qcmd,
- .target_alloc = _scsih_target_alloc,
- .slave_alloc = _scsih_slave_alloc,
- .slave_configure = _scsih_slave_configure,
- .target_destroy = _scsih_target_destroy,
- .slave_destroy = _scsih_slave_destroy,
- .scan_finished = _scsih_scan_finished,
- .scan_start = _scsih_scan_start,
- .change_queue_depth = _scsih_change_queue_depth,
- .eh_abort_handler = _scsih_abort,
- .eh_device_reset_handler = _scsih_dev_reset,
- .eh_target_reset_handler = _scsih_target_reset,
- .eh_host_reset_handler = _scsih_host_reset,
- .bios_param = _scsih_bios_param,
- .can_queue = 1,
- .this_id = -1,
- .sg_tablesize = MPT2SAS_SG_DEPTH,
- .max_sectors = 32767,
- .cmd_per_lun = 7,
- .use_clustering = ENABLE_CLUSTERING,
- .shost_attrs = mpt2sas_host_attrs,
- .sdev_attrs = mpt2sas_dev_attrs,
- .track_queue_depth = 1,
-};
-
-/**
- * _scsih_expander_node_remove - removing expander device from list.
- * @ioc: per adapter object
- * @sas_expander: the sas_device object
- * Context: Calling function should acquire ioc->sas_node_lock.
- *
- * Removing object and freeing associated memory from the
- * ioc->sas_expander_list.
- *
- * Return nothing.
- */
-static void
-_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_expander)
-{
- struct _sas_port *mpt2sas_port, *next;
-
- /* remove sibling ports attached to this expander */
- list_for_each_entry_safe(mpt2sas_port, next,
- &sas_expander->sas_port_list, port_list) {
- if (ioc->shost_recovery)
- return;
- if (mpt2sas_port->remote_identify.device_type ==
- SAS_END_DEVICE)
- mpt2sas_device_remove_by_sas_address(ioc,
- mpt2sas_port->remote_identify.sas_address);
- else if (mpt2sas_port->remote_identify.device_type ==
- SAS_EDGE_EXPANDER_DEVICE ||
- mpt2sas_port->remote_identify.device_type ==
- SAS_FANOUT_EXPANDER_DEVICE)
- mpt2sas_expander_remove(ioc,
- mpt2sas_port->remote_identify.sas_address);
- }
-
- mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
- sas_expander->sas_address_parent);
-
- printk(MPT2SAS_INFO_FMT "expander_remove: handle"
- "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
- sas_expander->handle, (unsigned long long)
- sas_expander->sas_address);
-
- kfree(sas_expander->phy);
- kfree(sas_expander);
-}
-
-/**
- * _scsih_ir_shutdown - IR shutdown notification
- * @ioc: per adapter object
- *
- * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
- * the host system is shutting down.
- *
- * Return nothing.
- */
-static void
-_scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
-{
- Mpi2RaidActionRequest_t *mpi_request;
- Mpi2RaidActionReply_t *mpi_reply;
- u16 smid;
-
- /* is IR firmware build loaded ? */
- if (!ioc->ir_firmware)
- return;
-
- mutex_lock(&ioc->scsih_cmds.mutex);
-
- if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n",
- ioc->name, __func__);
- goto out;
- }
- ioc->scsih_cmds.status = MPT2_CMD_PENDING;
-
- smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
- goto out;
- }
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->scsih_cmds.smid = smid;
- memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
-
- mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
- mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
-
- if (!ioc->hide_ir_msg)
- printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
- init_completion(&ioc->scsih_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
-
- if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- goto out;
- }
-
- if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
- mpi_reply = ioc->scsih_cmds.reply;
-
- if (!ioc->hide_ir_msg)
- printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
- "ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo));
- }
-
- out:
- ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->scsih_cmds.mutex);
-}
-
-/**
- * _scsih_shutdown - routine call during system shutdown
- * @pdev: PCI device struct
- *
- * Return nothing.
- */
-static void
-_scsih_shutdown(struct pci_dev *pdev)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct workqueue_struct *wq;
- unsigned long flags;
-
- ioc->remove_host = 1;
- _scsih_fw_event_cleanup_queue(ioc);
-
- spin_lock_irqsave(&ioc->fw_event_lock, flags);
- wq = ioc->firmware_event_thread;
- ioc->firmware_event_thread = NULL;
- spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
- if (wq)
- destroy_workqueue(wq);
-
- _scsih_ir_shutdown(ioc);
- mpt2sas_base_detach(ioc);
-}
-
-/**
- * _scsih_remove - detach and remove add host
- * @pdev: PCI device struct
- *
- * Routine called when unloading the driver.
- * Return nothing.
- */
-static void
-_scsih_remove(struct pci_dev *pdev)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct _sas_port *mpt2sas_port, *next_port;
- struct _raid_device *raid_device, *next;
- struct MPT2SAS_TARGET *sas_target_priv_data;
- struct workqueue_struct *wq;
- unsigned long flags;
-
- ioc->remove_host = 1;
- _scsih_fw_event_cleanup_queue(ioc);
-
- spin_lock_irqsave(&ioc->fw_event_lock, flags);
- wq = ioc->firmware_event_thread;
- ioc->firmware_event_thread = NULL;
- spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
- if (wq)
- destroy_workqueue(wq);
-
- /* release all the volumes */
- _scsih_ir_shutdown(ioc);
- list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
- list) {
- if (raid_device->starget) {
- sas_target_priv_data =
- raid_device->starget->hostdata;
- sas_target_priv_data->deleted = 1;
- scsi_remove_target(&raid_device->starget->dev);
- }
- printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
- "(0x%016llx)\n", ioc->name, raid_device->handle,
- (unsigned long long) raid_device->wwid);
- _scsih_raid_device_remove(ioc, raid_device);
- }
-
- /* free ports attached to the sas_host */
- list_for_each_entry_safe(mpt2sas_port, next_port,
- &ioc->sas_hba.sas_port_list, port_list) {
- if (mpt2sas_port->remote_identify.device_type ==
- SAS_END_DEVICE)
- mpt2sas_device_remove_by_sas_address(ioc,
- mpt2sas_port->remote_identify.sas_address);
- else if (mpt2sas_port->remote_identify.device_type ==
- SAS_EDGE_EXPANDER_DEVICE ||
- mpt2sas_port->remote_identify.device_type ==
- SAS_FANOUT_EXPANDER_DEVICE)
- mpt2sas_expander_remove(ioc,
- mpt2sas_port->remote_identify.sas_address);
- }
-
- /* free phys attached to the sas_host */
- if (ioc->sas_hba.num_phys) {
- kfree(ioc->sas_hba.phy);
- ioc->sas_hba.phy = NULL;
- ioc->sas_hba.num_phys = 0;
- }
-
- sas_remove_host(shost);
- scsi_remove_host(shost);
- mpt2sas_base_detach(ioc);
- spin_lock(&gioc_lock);
- list_del(&ioc->list);
- spin_unlock(&gioc_lock);
- scsi_host_put(shost);
-}
-
-/**
- * _scsih_probe_boot_devices - reports 1st device
- * @ioc: per adapter object
- *
- * If specified in bios page 2, this routine reports the 1st
- * device scsi-ml or sas transport for persistent boot device
- * purposes. Please refer to function _scsih_determine_boot_device()
- */
-static void
-_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
-{
- u8 is_raid;
- void *device;
- struct _sas_device *sas_device;
- struct _raid_device *raid_device;
- u16 handle;
- u64 sas_address_parent;
- u64 sas_address;
- unsigned long flags;
- int rc;
-
- /* no Bios, return immediately */
- if (!ioc->bios_pg3.BiosVersion)
- return;
-
- device = NULL;
- is_raid = 0;
- if (ioc->req_boot_device.device) {
- device = ioc->req_boot_device.device;
- is_raid = ioc->req_boot_device.is_raid;
- } else if (ioc->req_alt_boot_device.device) {
- device = ioc->req_alt_boot_device.device;
- is_raid = ioc->req_alt_boot_device.is_raid;
- } else if (ioc->current_boot_device.device) {
- device = ioc->current_boot_device.device;
- is_raid = ioc->current_boot_device.is_raid;
- }
-
- if (!device)
- return;
-
- if (is_raid) {
- raid_device = device;
- rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
- raid_device->id, 0);
- if (rc)
- _scsih_raid_device_remove(ioc, raid_device);
- } else {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = device;
- handle = sas_device->handle;
- sas_address_parent = sas_device->sas_address_parent;
- sas_address = sas_device->sas_address;
- list_move_tail(&sas_device->list, &ioc->sas_device_list);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (ioc->hide_drives)
- return;
- if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
- sas_device->sas_address_parent)) {
- _scsih_sas_device_remove(ioc, sas_device);
- } else if (!sas_device->starget) {
- if (!ioc->is_driver_loading) {
- mpt2sas_transport_port_remove(ioc,
- sas_address,
- sas_address_parent);
- _scsih_sas_device_remove(ioc, sas_device);
- }
- }
- }
-}
-
-/**
- * _scsih_probe_raid - reporting raid volumes to scsi-ml
- * @ioc: per adapter object
- *
- * Called during initial loading of the driver.
- */
-static void
-_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
-{
- struct _raid_device *raid_device, *raid_next;
- int rc;
-
- list_for_each_entry_safe(raid_device, raid_next,
- &ioc->raid_device_list, list) {
- if (raid_device->starget)
- continue;
- rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
- raid_device->id, 0);
- if (rc)
- _scsih_raid_device_remove(ioc, raid_device);
- }
-}
-
-static struct _sas_device *get_next_sas_device(struct MPT2SAS_ADAPTER *ioc)
-{
- struct _sas_device *sas_device = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- if (!list_empty(&ioc->sas_device_init_list)) {
- sas_device = list_first_entry(&ioc->sas_device_init_list,
- struct _sas_device, list);
- sas_device_get(sas_device);
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- return sas_device;
-}
-
-static void sas_device_make_active(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
-
- /*
- * Since we dropped the lock during the call to port_add(), we need to
- * be careful here that somebody else didn't move or delete this item
- * while we were busy with other things.
- *
- * If it was on the list, we need a put() for the reference the list
- * had. Either way, we need a get() for the destination list.
- */
- if (!list_empty(&sas_device->list)) {
- list_del_init(&sas_device->list);
- sas_device_put(sas_device);
- }
-
- sas_device_get(sas_device);
- list_add_tail(&sas_device->list, &ioc->sas_device_list);
-
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-/**
- * _scsih_probe_sas - reporting sas devices to sas transport
- * @ioc: per adapter object
- *
- * Called during initial loading of the driver.
- */
-static void
-_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
-{
- struct _sas_device *sas_device;
-
- if (ioc->hide_drives)
- return;
-
- while ((sas_device = get_next_sas_device(ioc))) {
- if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
- sas_device->sas_address_parent)) {
- _scsih_sas_device_remove(ioc, sas_device);
- sas_device_put(sas_device);
- continue;
- } else if (!sas_device->starget) {
- if (!ioc->is_driver_loading) {
- mpt2sas_transport_port_remove(ioc,
- sas_device->sas_address,
- sas_device->sas_address_parent);
- _scsih_sas_device_remove(ioc, sas_device);
- sas_device_put(sas_device);
- continue;
- }
- }
-
- sas_device_make_active(ioc, sas_device);
- sas_device_put(sas_device);
- }
-}
-
-/**
- * _scsih_probe_devices - probing for devices
- * @ioc: per adapter object
- *
- * Called during initial loading of the driver.
- */
-static void
-_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
-{
- u16 volume_mapping_flags;
-
- if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
- return; /* return when IOC doesn't support initiator mode */
-
- _scsih_probe_boot_devices(ioc);
-
- if (ioc->ir_firmware) {
- volume_mapping_flags =
- le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
- MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
- if (volume_mapping_flags ==
- MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
- _scsih_probe_raid(ioc);
- _scsih_probe_sas(ioc);
- } else {
- _scsih_probe_sas(ioc);
- _scsih_probe_raid(ioc);
- }
- } else
- _scsih_probe_sas(ioc);
-}
-
-
-/**
- * _scsih_scan_start - scsi lld callback for .scan_start
- * @shost: SCSI host pointer
- *
- * The shost has the ability to discover targets on its own instead
- * of scanning the entire bus. In our implemention, we will kick off
- * firmware discovery.
- */
-static void
-_scsih_scan_start(struct Scsi_Host *shost)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- int rc;
-
- if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
- mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
-
- if (disable_discovery > 0)
- return;
-
- ioc->start_scan = 1;
- rc = mpt2sas_port_enable(ioc);
-
- if (rc != 0)
- printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
-}
-
-/**
- * _scsih_scan_finished - scsi lld callback for .scan_finished
- * @shost: SCSI host pointer
- * @time: elapsed time of the scan in jiffies
- *
- * This function will be called periodically until it returns 1 with the
- * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
- * we wait for firmware discovery to complete, then return 1.
- */
-static int
-_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- if (disable_discovery > 0) {
- ioc->is_driver_loading = 0;
- ioc->wait_for_discovery_to_complete = 0;
- return 1;
- }
-
- if (time >= (300 * HZ)) {
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
- printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
- "(timeout=300s)\n", ioc->name);
- ioc->is_driver_loading = 0;
- return 1;
- }
-
- if (ioc->start_scan)
- return 0;
-
- if (ioc->start_scan_failed) {
- printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
- "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
- ioc->is_driver_loading = 0;
- ioc->wait_for_discovery_to_complete = 0;
- ioc->remove_host = 1;
- return 1;
- }
-
- printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
- ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-
- if (ioc->wait_for_discovery_to_complete) {
- ioc->wait_for_discovery_to_complete = 0;
- _scsih_probe_devices(ioc);
- }
- mpt2sas_base_start_watchdog(ioc);
- ioc->is_driver_loading = 0;
- return 1;
-}
-
-
-/**
- * _scsih_probe - attach and add scsi host
- * @pdev: PCI device struct
- * @id: pci device id
- *
- * Returns 0 success, anything else error.
- */
-static int
-_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct MPT2SAS_ADAPTER *ioc;
- struct Scsi_Host *shost;
- int rv;
-
- shost = scsi_host_alloc(&scsih_driver_template,
- sizeof(struct MPT2SAS_ADAPTER));
- if (!shost)
- return -ENODEV;
-
- /* init local params */
- ioc = shost_priv(shost);
- memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER));
- INIT_LIST_HEAD(&ioc->list);
- spin_lock(&gioc_lock);
- list_add_tail(&ioc->list, &mpt2sas_ioc_list);
- spin_unlock(&gioc_lock);
- ioc->shost = shost;
- ioc->id = mpt_ids++;
- sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
- ioc->pdev = pdev;
- if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) {
- ioc->is_warpdrive = 1;
- ioc->hide_ir_msg = 1;
- } else
- ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
- ioc->scsi_io_cb_idx = scsi_io_cb_idx;
- ioc->tm_cb_idx = tm_cb_idx;
- ioc->ctl_cb_idx = ctl_cb_idx;
- ioc->base_cb_idx = base_cb_idx;
- ioc->port_enable_cb_idx = port_enable_cb_idx;
- ioc->transport_cb_idx = transport_cb_idx;
- ioc->scsih_cb_idx = scsih_cb_idx;
- ioc->config_cb_idx = config_cb_idx;
- ioc->tm_tr_cb_idx = tm_tr_cb_idx;
- ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
- ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
- ioc->logging_level = logging_level;
- ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
- /* misc semaphores and spin locks */
- mutex_init(&ioc->reset_in_progress_mutex);
- /* initializing pci_access_mutex lock */
- mutex_init(&ioc->pci_access_mutex);
- spin_lock_init(&ioc->ioc_reset_in_progress_lock);
- spin_lock_init(&ioc->scsi_lookup_lock);
- spin_lock_init(&ioc->sas_device_lock);
- spin_lock_init(&ioc->sas_node_lock);
- spin_lock_init(&ioc->fw_event_lock);
- spin_lock_init(&ioc->raid_device_lock);
-
- INIT_LIST_HEAD(&ioc->sas_device_list);
- INIT_LIST_HEAD(&ioc->sas_device_init_list);
- INIT_LIST_HEAD(&ioc->sas_expander_list);
- INIT_LIST_HEAD(&ioc->fw_event_list);
- INIT_LIST_HEAD(&ioc->raid_device_list);
- INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
- INIT_LIST_HEAD(&ioc->delayed_tr_list);
- INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
- INIT_LIST_HEAD(&ioc->reply_queue_list);
-
- /* init shost parameters */
- shost->max_cmd_len = 32;
- shost->max_lun = max_lun;
- shost->transportt = mpt2sas_transport_template;
- shost->unique_id = ioc->id;
-
- if (max_sectors != 0xFFFF) {
- if (max_sectors < 64) {
- shost->max_sectors = 64;
- printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
- "for max_sectors, range is 64 to 32767. Assigning "
- "value of 64.\n", ioc->name, max_sectors);
- } else if (max_sectors > 32767) {
- shost->max_sectors = 32767;
- printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
- "for max_sectors, range is 64 to 8192. Assigning "
- "default value of 32767.\n", ioc->name,
- max_sectors);
- } else {
- shost->max_sectors = max_sectors & 0xFFFE;
- printk(MPT2SAS_INFO_FMT "The max_sectors value is "
- "set to %d\n", ioc->name, shost->max_sectors);
- }
- }
-
- /* register EEDP capabilities with SCSI layer */
- if (prot_mask)
- scsi_host_set_prot(shost, prot_mask);
- else
- 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);
-
- /* event thread */
- snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
- "fw_event%d", ioc->id);
- ioc->firmware_event_thread = create_singlethread_workqueue(
- ioc->firmware_event_name);
- if (!ioc->firmware_event_thread) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rv = -ENODEV;
- goto out_thread_fail;
- }
-
- ioc->is_driver_loading = 1;
- if ((mpt2sas_base_attach(ioc))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rv = -ENODEV;
- goto out_attach_fail;
- }
-
- if (ioc->is_warpdrive) {
- if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
- ioc->hide_drives = 0;
- else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
- ioc->hide_drives = 1;
- else {
- if (_scsih_get_num_volumes(ioc))
- ioc->hide_drives = 1;
- else
- ioc->hide_drives = 0;
- }
- } else
- ioc->hide_drives = 0;
-
- rv = scsi_add_host(shost, &pdev->dev);
- if (rv) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out_add_shost_fail;
- }
-
- scsi_scan_host(shost);
-
- return 0;
-
- out_add_shost_fail:
- mpt2sas_base_detach(ioc);
- out_attach_fail:
- destroy_workqueue(ioc->firmware_event_thread);
- out_thread_fail:
- spin_lock(&gioc_lock);
- list_del(&ioc->list);
- spin_unlock(&gioc_lock);
- scsi_host_put(shost);
- return rv;
-}
-
-#ifdef CONFIG_PM
-/**
- * _scsih_suspend - power management suspend main entry point
- * @pdev: PCI device struct
- * @state: PM state change to (usually PCI_D3)
- *
- * Returns 0 success, anything else error.
- */
-static int
-_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- pci_power_t device_state;
-
- mpt2sas_base_stop_watchdog(ioc);
- scsi_block_requests(shost);
- _scsih_ir_shutdown(ioc);
- device_state = pci_choose_state(pdev, state);
- printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
- "operating state [D%d]\n", ioc->name, pdev,
- pci_name(pdev), device_state);
-
- mpt2sas_base_free_resources(ioc);
- pci_save_state(pdev);
- pci_set_power_state(pdev, device_state);
- return 0;
-}
-
-/**
- * _scsih_resume - power management resume main entry point
- * @pdev: PCI device struct
- *
- * Returns 0 success, anything else error.
- */
-static int
-_scsih_resume(struct pci_dev *pdev)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- pci_power_t device_state = pdev->current_state;
- int r;
-
- printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
- "operating state [D%d]\n", ioc->name, pdev,
- pci_name(pdev), device_state);
-
- pci_set_power_state(pdev, PCI_D0);
- pci_enable_wake(pdev, PCI_D0, 0);
- pci_restore_state(pdev);
- ioc->pdev = pdev;
- r = mpt2sas_base_map_resources(ioc);
- if (r)
- return r;
-
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
- scsi_unblock_requests(shost);
- mpt2sas_base_start_watchdog(ioc);
- return 0;
-}
-#endif /* CONFIG_PM */
-
-/**
- * _scsih_pci_error_detected - Called when a PCI error is detected.
- * @pdev: PCI device struct
- * @state: PCI channel state
- *
- * Description: Called when a PCI error is detected.
- *
- * Return value:
- * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
- */
-static pci_ers_result_t
-_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- printk(MPT2SAS_INFO_FMT "PCI error: detected callback, state(%d)!!\n",
- ioc->name, state);
-
- switch (state) {
- case pci_channel_io_normal:
- return PCI_ERS_RESULT_CAN_RECOVER;
- case pci_channel_io_frozen:
- /* Fatal error, prepare for slot reset */
- ioc->pci_error_recovery = 1;
- scsi_block_requests(ioc->shost);
- mpt2sas_base_stop_watchdog(ioc);
- mpt2sas_base_free_resources(ioc);
- return PCI_ERS_RESULT_NEED_RESET;
- case pci_channel_io_perm_failure:
- /* Permanent error, prepare for device removal */
- ioc->pci_error_recovery = 1;
- mpt2sas_base_stop_watchdog(ioc);
- _scsih_flush_running_cmds(ioc);
- return PCI_ERS_RESULT_DISCONNECT;
- }
- return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * _scsih_pci_slot_reset - Called when PCI slot has been reset.
- * @pdev: PCI device struct
- *
- * Description: This routine is called by the pci error recovery
- * code after the PCI slot has been reset, just before we
- * should resume normal operations.
- */
-static pci_ers_result_t
-_scsih_pci_slot_reset(struct pci_dev *pdev)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- int rc;
-
- printk(MPT2SAS_INFO_FMT "PCI error: slot reset callback!!\n",
- ioc->name);
-
- ioc->pci_error_recovery = 0;
- ioc->pdev = pdev;
- pci_restore_state(pdev);
- rc = mpt2sas_base_map_resources(ioc);
- if (rc)
- return PCI_ERS_RESULT_DISCONNECT;
-
-
- rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
-
- printk(MPT2SAS_WARN_FMT "hard reset: %s\n", ioc->name,
- (rc == 0) ? "success" : "failed");
-
- if (!rc)
- return PCI_ERS_RESULT_RECOVERED;
- else
- return PCI_ERS_RESULT_DISCONNECT;
-}
-
-/**
- * _scsih_pci_resume() - resume normal ops after PCI reset
- * @pdev: pointer to PCI device
- *
- * Called when the error recovery driver tells us that its
- * OK to resume normal operation. Use completion to allow
- * halted scsi ops to resume.
- */
-static void
-_scsih_pci_resume(struct pci_dev *pdev)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- printk(MPT2SAS_INFO_FMT "PCI error: resume callback!!\n", ioc->name);
-
- pci_cleanup_aer_uncorrect_error_status(pdev);
- mpt2sas_base_start_watchdog(ioc);
- scsi_unblock_requests(ioc->shost);
-}
-
-/**
- * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
- * @pdev: pointer to PCI device
- */
-static pci_ers_result_t
-_scsih_pci_mmio_enabled(struct pci_dev *pdev)
-{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
- printk(MPT2SAS_INFO_FMT "PCI error: mmio enabled callback!!\n",
- ioc->name);
-
- /* TODO - dump whatever for debugging purposes */
-
- /* Request a slot reset. */
- return PCI_ERS_RESULT_NEED_RESET;
-}
-
-static const struct pci_error_handlers _scsih_err_handler = {
- .error_detected = _scsih_pci_error_detected,
- .mmio_enabled = _scsih_pci_mmio_enabled,
- .slot_reset = _scsih_pci_slot_reset,
- .resume = _scsih_pci_resume,
-};
-
-static struct pci_driver scsih_driver = {
- .name = MPT2SAS_DRIVER_NAME,
- .id_table = scsih_pci_table,
- .probe = _scsih_probe,
- .remove = _scsih_remove,
- .shutdown = _scsih_shutdown,
- .err_handler = &_scsih_err_handler,
-#ifdef CONFIG_PM
- .suspend = _scsih_suspend,
- .resume = _scsih_resume,
-#endif
-};
-
-/* raid transport support */
-static struct raid_function_template mpt2sas_raid_functions = {
- .cookie = &scsih_driver_template,
- .is_raid = _scsih_is_raid,
- .get_resync = _scsih_get_resync,
- .get_state = _scsih_get_state,
-};
-
-/**
- * _scsih_init - main entry point for this driver.
- *
- * Returns 0 success, anything else error.
- */
-static int __init
-_scsih_init(void)
-{
- int error;
-
- mpt_ids = 0;
- printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
- MPT2SAS_DRIVER_VERSION);
-
- mpt2sas_transport_template =
- sas_attach_transport(&mpt2sas_transport_functions);
- if (!mpt2sas_transport_template)
- return -ENODEV;
- /* raid transport support */
- mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions);
- if (!mpt2sas_raid_template) {
- sas_release_transport(mpt2sas_transport_template);
- return -ENODEV;
- }
-
- mpt2sas_base_initialize_callback_handler();
-
- /* queuecommand callback hander */
- scsi_io_cb_idx = mpt2sas_base_register_callback_handler(_scsih_io_done);
-
- /* task management callback handler */
- tm_cb_idx = mpt2sas_base_register_callback_handler(_scsih_tm_done);
-
- /* base internal commands callback handler */
- base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
- port_enable_cb_idx = mpt2sas_base_register_callback_handler(
- mpt2sas_port_enable_done);
-
- /* transport internal commands callback handler */
- transport_cb_idx = mpt2sas_base_register_callback_handler(
- mpt2sas_transport_done);
-
- /* scsih internal commands callback handler */
- scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done);
-
- /* configuration page API internal commands callback handler */
- config_cb_idx = mpt2sas_base_register_callback_handler(
- mpt2sas_config_done);
-
- /* ctl module callback handler */
- ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done);
-
- tm_tr_cb_idx = mpt2sas_base_register_callback_handler(
- _scsih_tm_tr_complete);
-
- tm_tr_volume_cb_idx = mpt2sas_base_register_callback_handler(
- _scsih_tm_volume_tr_complete);
-
- tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler(
- _scsih_sas_control_complete);
-
- mpt2sas_ctl_init();
-
- error = pci_register_driver(&scsih_driver);
- if (error) {
- /* raid transport support */
- raid_class_release(mpt2sas_raid_template);
- sas_release_transport(mpt2sas_transport_template);
- }
-
- return error;
-}
-
-/**
- * _scsih_exit - exit point for this driver (when it is a module).
- *
- * Returns 0 success, anything else error.
- */
-static void __exit
-_scsih_exit(void)
-{
- printk(KERN_INFO "mpt2sas version %s unloading\n",
- MPT2SAS_DRIVER_VERSION);
-
- pci_unregister_driver(&scsih_driver);
-
- mpt2sas_ctl_exit();
-
- mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
- mpt2sas_base_release_callback_handler(tm_cb_idx);
- mpt2sas_base_release_callback_handler(base_cb_idx);
- mpt2sas_base_release_callback_handler(port_enable_cb_idx);
- mpt2sas_base_release_callback_handler(transport_cb_idx);
- mpt2sas_base_release_callback_handler(scsih_cb_idx);
- mpt2sas_base_release_callback_handler(config_cb_idx);
- mpt2sas_base_release_callback_handler(ctl_cb_idx);
-
- mpt2sas_base_release_callback_handler(tm_tr_cb_idx);
- mpt2sas_base_release_callback_handler(tm_tr_volume_cb_idx);
- mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx);
-
- /* raid transport support */
- raid_class_release(mpt2sas_raid_template);
- sas_release_transport(mpt2sas_transport_template);
-
-}
-
-module_init(_scsih_init);
-module_exit(_scsih_exit);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
deleted file mode 100644
index af868009395d..000000000000
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ /dev/null
@@ -1,2173 +0,0 @@
-/*
- * SAS Transport Layer for MPT (Message Passing Technology) based controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
- * Copyright (C) 2007-2014 LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- * (mailto: MPT-FusionLinux.pdl@avagotech.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.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_transport_sas.h>
-#include <scsi/scsi_dbg.h>
-
-#include "mpt2sas_base.h"
-/**
- * _transport_sas_node_find_by_sas_address - sas node search
- * @ioc: per adapter object
- * @sas_address: sas address of expander or sas host
- * Context: Calling function should acquire ioc->sas_node_lock.
- *
- * Search for either hba phys or expander device based on handle, then returns
- * the sas_node object.
- */
-static struct _sas_node *
-_transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address)
-{
- if (ioc->sas_hba.sas_address == sas_address)
- return &ioc->sas_hba;
- else
- return mpt2sas_scsih_expander_find_by_sas_address(ioc,
- sas_address);
-}
-
-/**
- * _transport_convert_phy_link_rate -
- * @link_rate: link rate returned from mpt firmware
- *
- * Convert link_rate from mpi fusion into sas_transport form.
- */
-static enum sas_linkrate
-_transport_convert_phy_link_rate(u8 link_rate)
-{
- enum sas_linkrate rc;
-
- switch (link_rate) {
- case MPI2_SAS_NEG_LINK_RATE_1_5:
- rc = SAS_LINK_RATE_1_5_GBPS;
- break;
- case MPI2_SAS_NEG_LINK_RATE_3_0:
- rc = SAS_LINK_RATE_3_0_GBPS;
- break;
- case MPI2_SAS_NEG_LINK_RATE_6_0:
- rc = SAS_LINK_RATE_6_0_GBPS;
- break;
- case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
- rc = SAS_PHY_DISABLED;
- break;
- case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
- rc = SAS_LINK_RATE_FAILED;
- break;
- case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
- rc = SAS_SATA_PORT_SELECTOR;
- break;
- case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
- rc = SAS_PHY_RESET_IN_PROGRESS;
- break;
- default:
- case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
- case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
- rc = SAS_LINK_RATE_UNKNOWN;
- break;
- }
- return rc;
-}
-
-/**
- * _transport_set_identify - set identify for phys and end devices
- * @ioc: per adapter object
- * @handle: device handle
- * @identify: sas identify info
- *
- * Populates sas identify info.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- struct sas_identify *identify)
-{
- Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u32 device_info;
- u32 ioc_status;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery) {
- printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
- __func__, ioc->name);
- return -EFAULT;
- }
-
- if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-
- ioc->name, __FILE__, __LINE__, __func__);
- return -ENXIO;
- }
-
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
- "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
- __FILE__, __LINE__, __func__);
- return -EIO;
- }
-
- memset(identify, 0, sizeof(struct sas_identify));
- device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-
- /* sas_address */
- identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-
- /* phy number of the parent device this device is linked to */
- identify->phy_identifier = sas_device_pg0.PhyNum;
-
- /* device_type */
- switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
- case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
- identify->device_type = SAS_PHY_UNUSED;
- break;
- case MPI2_SAS_DEVICE_INFO_END_DEVICE:
- identify->device_type = SAS_END_DEVICE;
- break;
- case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
- identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
- break;
- case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
- identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
- break;
- }
-
- /* initiator_port_protocols */
- if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
- identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
- if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
- identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
- if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
- identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
- if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
- identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
-
- /* target_port_protocols */
- if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
- identify->target_port_protocols |= SAS_PROTOCOL_SSP;
- if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
- identify->target_port_protocols |= SAS_PROTOCOL_STP;
- if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
- identify->target_port_protocols |= SAS_PROTOCOL_SMP;
- if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- identify->target_port_protocols |= SAS_PROTOCOL_SATA;
-
- return 0;
-}
-
-/**
- * mpt2sas_transport_done - internal transport layer callback handler.
- * @ioc: per adapter object
- * @smid: system request message index
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Callback handler when sending internal generated transport cmds.
- * The callback index passed is `ioc->transport_cb_idx`
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- * 0 means the mf is freed from this function.
- */
-u8
-mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
- u32 reply)
-{
- MPI2DefaultReply_t *mpi_reply;
-
- mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
- if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
- return 1;
- if (ioc->transport_cmds.smid != smid)
- return 1;
- ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
- if (mpi_reply) {
- memcpy(ioc->transport_cmds.reply, mpi_reply,
- mpi_reply->MsgLength*4);
- ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
- }
- ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
- complete(&ioc->transport_cmds.done);
- return 1;
-}
-
-/* report manufacture request structure */
-struct rep_manu_request{
- u8 smp_frame_type;
- u8 function;
- u8 reserved;
- u8 request_length;
-};
-
-/* report manufacture reply structure */
-struct rep_manu_reply{
- u8 smp_frame_type; /* 0x41 */
- u8 function; /* 0x01 */
- u8 function_result;
- u8 response_length;
- u16 expander_change_count;
- u8 reserved0[2];
- u8 sas_format;
- u8 reserved2[3];
- u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
- u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
- u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
- u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
- u16 component_id;
- u8 component_revision_id;
- u8 reserved3;
- u8 vendor_specific[8];
-};
-
-/**
- * _transport_expander_report_manufacture - obtain SMP report_manufacture
- * @ioc: per adapter object
- * @sas_address: expander sas address
- * @edev: the sas_expander_device object
- *
- * Fills in the sas_expander_device object when SMP port is created.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address, struct sas_expander_device *edev)
-{
- Mpi2SmpPassthroughRequest_t *mpi_request;
- Mpi2SmpPassthroughReply_t *mpi_reply;
- struct rep_manu_reply *manufacture_reply;
- struct rep_manu_request *manufacture_request;
- int rc;
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- void *psge;
- u32 sgl_flags;
- u8 issue_reset = 0;
- void *data_out = NULL;
- dma_addr_t data_out_dma;
- u32 sz;
- u16 wait_state_count;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery) {
- printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
- __func__, ioc->name);
- return -EFAULT;
- }
-
- mutex_lock(&ioc->transport_cmds.mutex);
-
- if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
- ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
- if (wait_state_count)
- printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
- ioc->name, __func__);
-
- smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- rc = 0;
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->transport_cmds.smid = smid;
-
- sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
- data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
-
- if (!data_out) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- rc = -ENOMEM;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
-
- manufacture_request = data_out;
- manufacture_request->smp_frame_type = 0x40;
- manufacture_request->function = 1;
- manufacture_request->reserved = 0;
- manufacture_request->request_length = 0;
-
- memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
- mpi_request->PhysicalPort = 0xFF;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
- mpi_request->SASAddress = cpu_to_le64(sas_address);
- mpi_request->RequestDataLength =
- cpu_to_le16(sizeof(struct rep_manu_request));
- psge = &mpi_request->SGL;
-
- /* WRITE sgel first */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- sizeof(struct rep_manu_request), data_out_dma);
-
- /* incr sgel */
- psge += ioc->sge_size;
-
- /* READ sgel last */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- sizeof(struct rep_manu_reply), data_out_dma +
- sizeof(struct rep_manu_request));
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
- "send to sas_addr(0x%016llx)\n", ioc->name,
- (unsigned long long)sas_address));
- init_completion(&ioc->transport_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
- 10*HZ);
-
- if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SmpPassthroughRequest_t)/4);
- if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
- "complete\n", ioc->name));
-
- if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
- u8 *tmp;
-
- mpi_reply = ioc->transport_cmds.reply;
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "report_manufacture - reply data transfer size(%d)\n",
- ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
-
- if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
- sizeof(struct rep_manu_reply))
- goto out;
-
- manufacture_reply = data_out + sizeof(struct rep_manu_request);
- strncpy(edev->vendor_id, manufacture_reply->vendor_id,
- SAS_EXPANDER_VENDOR_ID_LEN);
- strncpy(edev->product_id, manufacture_reply->product_id,
- SAS_EXPANDER_PRODUCT_ID_LEN);
- strncpy(edev->product_rev, manufacture_reply->product_rev,
- SAS_EXPANDER_PRODUCT_REV_LEN);
- edev->level = manufacture_reply->sas_format & 1;
- if (edev->level) {
- strncpy(edev->component_vendor_id,
- manufacture_reply->component_vendor_id,
- SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
- tmp = (u8 *)&manufacture_reply->component_id;
- edev->component_id = tmp[0] << 8 | tmp[1];
- edev->component_revision_id =
- manufacture_reply->component_revision_id;
- }
- } else
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "report_manufacture - no reply\n", ioc->name));
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- out:
- ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
- if (data_out)
- pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
-
- mutex_unlock(&ioc->transport_cmds.mutex);
- return rc;
-}
-
-/**
- * _transport_delete_port - helper function to removing a port
- * @ioc: per adapter object
- * @mpt2sas_port: mpt2sas per port object
- *
- * Returns nothing.
- */
-static void
-_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_port *mpt2sas_port)
-{
- u64 sas_address = mpt2sas_port->remote_identify.sas_address;
- enum sas_device_type device_type =
- mpt2sas_port->remote_identify.device_type;
-
- dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
- "remove: sas_addr(0x%016llx)\n",
- (unsigned long long) sas_address);
-
- ioc->logging_level |= MPT_DEBUG_TRANSPORT;
- if (device_type == SAS_END_DEVICE)
- mpt2sas_device_remove_by_sas_address(ioc, sas_address);
- else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
- device_type == SAS_FANOUT_EXPANDER_DEVICE)
- mpt2sas_expander_remove(ioc, sas_address);
- ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
-}
-
-/**
- * _transport_delete_phy - helper function to removing single phy from port
- * @ioc: per adapter object
- * @mpt2sas_port: mpt2sas per port object
- * @mpt2sas_phy: mpt2sas per phy object
- *
- * Returns nothing.
- */
-static void
-_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
-{
- u64 sas_address = mpt2sas_port->remote_identify.sas_address;
-
- dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
- "remove: sas_addr(0x%016llx), phy(%d)\n",
- (unsigned long long) sas_address, mpt2sas_phy->phy_id);
-
- list_del(&mpt2sas_phy->port_siblings);
- mpt2sas_port->num_phys--;
- sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
- mpt2sas_phy->phy_belongs_to_port = 0;
-}
-
-/**
- * _transport_add_phy - helper function to adding single phy to port
- * @ioc: per adapter object
- * @mpt2sas_port: mpt2sas per port object
- * @mpt2sas_phy: mpt2sas per phy object
- *
- * Returns nothing.
- */
-static void
-_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
- struct _sas_phy *mpt2sas_phy)
-{
- u64 sas_address = mpt2sas_port->remote_identify.sas_address;
-
- dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
- "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
- sas_address, mpt2sas_phy->phy_id);
-
- list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
- mpt2sas_port->num_phys++;
- sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
- mpt2sas_phy->phy_belongs_to_port = 1;
-}
-
-/**
- * _transport_add_phy_to_an_existing_port - adding new phy to existing port
- * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @mpt2sas_phy: mpt2sas per phy object
- * @sas_address: sas address of device/expander were phy needs to be added to
- *
- * Returns nothing.
- */
-static void
-_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
-struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
-{
- struct _sas_port *mpt2sas_port;
- struct _sas_phy *phy_srch;
-
- if (mpt2sas_phy->phy_belongs_to_port == 1)
- return;
-
- list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
- port_list) {
- if (mpt2sas_port->remote_identify.sas_address !=
- sas_address)
- continue;
- list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
- port_siblings) {
- if (phy_srch == mpt2sas_phy)
- return;
- }
- _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
- return;
- }
-
-}
-
-/**
- * _transport_del_phy_from_an_existing_port - delete phy from existing port
- * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @mpt2sas_phy: mpt2sas per phy object
- *
- * Returns nothing.
- */
-static void
-_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
-{
- struct _sas_port *mpt2sas_port, *next;
- struct _sas_phy *phy_srch;
-
- if (mpt2sas_phy->phy_belongs_to_port == 0)
- return;
-
- list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
- port_list) {
- list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
- port_siblings) {
- if (phy_srch != mpt2sas_phy)
- continue;
- if (mpt2sas_port->num_phys == 1)
- _transport_delete_port(ioc, mpt2sas_port);
- else
- _transport_delete_phy(ioc, mpt2sas_port,
- mpt2sas_phy);
- return;
- }
- }
-}
-
-/**
- * _transport_sanity_check - sanity check when adding a new port
- * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @sas_address: sas address of device being added
- *
- * See the explanation above from _transport_delete_duplicate_port
- */
-static void
-_transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
- u64 sas_address)
-{
- int i;
-
- for (i = 0; i < sas_node->num_phys; i++) {
- if (sas_node->phy[i].remote_identify.sas_address != sas_address)
- continue;
- if (sas_node->phy[i].phy_belongs_to_port == 1)
- _transport_del_phy_from_an_existing_port(ioc, sas_node,
- &sas_node->phy[i]);
- }
-}
-
-/**
- * mpt2sas_transport_port_add - insert port to the list
- * @ioc: per adapter object
- * @handle: handle of attached device
- * @sas_address: sas address of parent expander or sas host
- * Context: This function will acquire ioc->sas_node_lock.
- *
- * Adding new port object to the sas_node->sas_port_list.
- *
- * Returns mpt2sas_port.
- */
-struct _sas_port *
-mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- u64 sas_address)
-{
- struct _sas_phy *mpt2sas_phy, *next;
- struct _sas_port *mpt2sas_port;
- unsigned long flags;
- struct _sas_node *sas_node;
- struct sas_rphy *rphy;
- int i;
- struct sas_port *port;
-
- mpt2sas_port = kzalloc(sizeof(struct _sas_port),
- GFP_KERNEL);
- if (!mpt2sas_port) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return NULL;
- }
-
- INIT_LIST_HEAD(&mpt2sas_port->port_list);
- INIT_LIST_HEAD(&mpt2sas_port->phy_list);
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- if (!sas_node) {
- printk(MPT2SAS_ERR_FMT "%s: Could not find "
- "parent sas_address(0x%016llx)!\n", ioc->name,
- __func__, (unsigned long long)sas_address);
- goto out_fail;
- }
-
- if ((_transport_set_identify(ioc, handle,
- &mpt2sas_port->remote_identify))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out_fail;
- }
-
- if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out_fail;
- }
-
- _transport_sanity_check(ioc, sas_node,
- mpt2sas_port->remote_identify.sas_address);
-
- for (i = 0; i < sas_node->num_phys; i++) {
- if (sas_node->phy[i].remote_identify.sas_address !=
- mpt2sas_port->remote_identify.sas_address)
- continue;
- list_add_tail(&sas_node->phy[i].port_siblings,
- &mpt2sas_port->phy_list);
- mpt2sas_port->num_phys++;
- }
-
- if (!mpt2sas_port->num_phys) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out_fail;
- }
-
- port = sas_port_alloc_num(sas_node->parent_dev);
- if ((sas_port_add(port))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- goto out_fail;
- }
-
- list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
- port_siblings) {
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
- ", sas_addr(0x%016llx), phy(%d)\n", handle,
- (unsigned long long)
- mpt2sas_port->remote_identify.sas_address,
- mpt2sas_phy->phy_id);
- sas_port_add_phy(port, mpt2sas_phy->phy);
- mpt2sas_phy->phy_belongs_to_port = 1;
- }
-
- mpt2sas_port->port = port;
- if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
- rphy = sas_end_device_alloc(port);
- else
- rphy = sas_expander_alloc(port,
- mpt2sas_port->remote_identify.device_type);
-
- rphy->identify = mpt2sas_port->remote_identify;
- if ((sas_rphy_add(rphy))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- }
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
- "sas_addr(0x%016llx)\n", handle,
- (unsigned long long)
- mpt2sas_port->remote_identify.sas_address);
- mpt2sas_port->rphy = rphy;
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- /* fill in report manufacture */
- if (mpt2sas_port->remote_identify.device_type ==
- MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
- mpt2sas_port->remote_identify.device_type ==
- MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
- _transport_expander_report_manufacture(ioc,
- mpt2sas_port->remote_identify.sas_address,
- rphy_to_expander_device(rphy));
-
- return mpt2sas_port;
-
- out_fail:
- list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
- port_siblings)
- list_del(&mpt2sas_phy->port_siblings);
- kfree(mpt2sas_port);
- return NULL;
-}
-
-/**
- * mpt2sas_transport_port_remove - remove port from the list
- * @ioc: per adapter object
- * @sas_address: sas address of attached device
- * @sas_address_parent: sas address of parent expander or sas host
- * Context: This function will acquire ioc->sas_node_lock.
- *
- * Removing object and freeing associated memory from the
- * ioc->sas_port_list.
- *
- * Return nothing.
- */
-void
-mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
- u64 sas_address_parent)
-{
- int i;
- unsigned long flags;
- struct _sas_port *mpt2sas_port, *next;
- struct _sas_node *sas_node;
- u8 found = 0;
- struct _sas_phy *mpt2sas_phy, *next_phy;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_node = _transport_sas_node_find_by_sas_address(ioc,
- sas_address_parent);
- if (!sas_node) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return;
- }
- list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
- port_list) {
- if (mpt2sas_port->remote_identify.sas_address != sas_address)
- continue;
- found = 1;
- list_del(&mpt2sas_port->port_list);
- goto out;
- }
- out:
- if (!found) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return;
- }
-
- for (i = 0; i < sas_node->num_phys; i++) {
- if (sas_node->phy[i].remote_identify.sas_address == sas_address)
- memset(&sas_node->phy[i].remote_identify, 0 ,
- sizeof(struct sas_identify));
- }
-
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- list_for_each_entry_safe(mpt2sas_phy, next_phy,
- &mpt2sas_port->phy_list, port_siblings) {
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
- "remove: sas_addr(0x%016llx), phy(%d)\n",
- (unsigned long long)
- mpt2sas_port->remote_identify.sas_address,
- mpt2sas_phy->phy_id);
- mpt2sas_phy->phy_belongs_to_port = 0;
- sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
- list_del(&mpt2sas_phy->port_siblings);
- }
- sas_port_delete(mpt2sas_port->port);
- kfree(mpt2sas_port);
-}
-
-/**
- * mpt2sas_transport_add_host_phy - report sas_host phy to transport
- * @ioc: per adapter object
- * @mpt2sas_phy: mpt2sas per phy object
- * @phy_pg0: sas phy page 0
- * @parent_dev: parent device class object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
- *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
-{
- struct sas_phy *phy;
- int phy_index = mpt2sas_phy->phy_id;
-
-
- INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
- phy = sas_phy_alloc(parent_dev, phy_index);
- if (!phy) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
- if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
- &mpt2sas_phy->identify))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
- phy->identify = mpt2sas_phy->identify;
- mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
- if (mpt2sas_phy->attached_handle)
- _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
- &mpt2sas_phy->remote_identify);
- phy->identify.phy_identifier = mpt2sas_phy->phy_id;
- phy->negotiated_linkrate = _transport_convert_phy_link_rate(
- phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
- phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
- phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
- phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
- phy_pg0.HwLinkRate >> 4);
- phy->minimum_linkrate = _transport_convert_phy_link_rate(
- phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
- phy->maximum_linkrate = _transport_convert_phy_link_rate(
- phy_pg0.ProgrammedLinkRate >> 4);
-
- if ((sas_phy_add(phy))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- sas_phy_free(phy);
- return -1;
- }
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &phy->dev,
- "add: handle(0x%04x), sas_addr(0x%016llx)\n"
- "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
- mpt2sas_phy->handle, (unsigned long long)
- mpt2sas_phy->identify.sas_address,
- mpt2sas_phy->attached_handle,
- (unsigned long long)
- mpt2sas_phy->remote_identify.sas_address);
- mpt2sas_phy->phy = phy;
- return 0;
-}
-
-
-/**
- * mpt2sas_transport_add_expander_phy - report expander phy to transport
- * @ioc: per adapter object
- * @mpt2sas_phy: mpt2sas per phy object
- * @expander_pg1: expander page 1
- * @parent_dev: parent device class object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
- *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
-{
- struct sas_phy *phy;
- int phy_index = mpt2sas_phy->phy_id;
-
- INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
- phy = sas_phy_alloc(parent_dev, phy_index);
- if (!phy) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
- if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
- &mpt2sas_phy->identify))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -1;
- }
- phy->identify = mpt2sas_phy->identify;
- mpt2sas_phy->attached_handle =
- le16_to_cpu(expander_pg1.AttachedDevHandle);
- if (mpt2sas_phy->attached_handle)
- _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
- &mpt2sas_phy->remote_identify);
- phy->identify.phy_identifier = mpt2sas_phy->phy_id;
- phy->negotiated_linkrate = _transport_convert_phy_link_rate(
- expander_pg1.NegotiatedLinkRate &
- MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
- phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
- expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
- phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
- expander_pg1.HwLinkRate >> 4);
- phy->minimum_linkrate = _transport_convert_phy_link_rate(
- expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
- phy->maximum_linkrate = _transport_convert_phy_link_rate(
- expander_pg1.ProgrammedLinkRate >> 4);
-
- if ((sas_phy_add(phy))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- sas_phy_free(phy);
- return -1;
- }
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &phy->dev,
- "add: handle(0x%04x), sas_addr(0x%016llx)\n"
- "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
- mpt2sas_phy->handle, (unsigned long long)
- mpt2sas_phy->identify.sas_address,
- mpt2sas_phy->attached_handle,
- (unsigned long long)
- mpt2sas_phy->remote_identify.sas_address);
- mpt2sas_phy->phy = phy;
- return 0;
-}
-
-/**
- * mpt2sas_transport_update_links - refreshing phy link changes
- * @ioc: per adapter object
- * @sas_address: sas address of parent expander or sas host
- * @handle: attached device handle
- * @phy_numberv: phy number
- * @link_rate: new link rate
- *
- * Returns nothing.
- */
-void
-mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
- u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
-{
- unsigned long flags;
- struct _sas_node *sas_node;
- struct _sas_phy *mpt2sas_phy;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery)
- return;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
- if (!sas_node) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return;
- }
-
- mpt2sas_phy = &sas_node->phy[phy_number];
- mpt2sas_phy->attached_handle = handle;
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
- _transport_set_identify(ioc, handle,
- &mpt2sas_phy->remote_identify);
- _transport_add_phy_to_an_existing_port(ioc, sas_node,
- mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
- } else
- memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
- sas_identify));
-
- if (mpt2sas_phy->phy)
- mpt2sas_phy->phy->negotiated_linkrate =
- _transport_convert_phy_link_rate(link_rate);
-
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
- "refresh: parent sas_addr(0x%016llx),\n"
- "\tlink_rate(0x%02x), phy(%d)\n"
- "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
- (unsigned long long)sas_address,
- link_rate, phy_number, handle, (unsigned long long)
- mpt2sas_phy->remote_identify.sas_address);
-}
-
-static inline void *
-phy_to_ioc(struct sas_phy *phy)
-{
- struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
- return shost_priv(shost);
-}
-
-static inline void *
-rphy_to_ioc(struct sas_rphy *rphy)
-{
- struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
- return shost_priv(shost);
-}
-
-
-/* report phy error log structure */
-struct phy_error_log_request{
- u8 smp_frame_type; /* 0x40 */
- u8 function; /* 0x11 */
- u8 allocated_response_length;
- u8 request_length; /* 02 */
- u8 reserved_1[5];
- u8 phy_identifier;
- u8 reserved_2[2];
-};
-
-/* report phy error log reply structure */
-struct phy_error_log_reply{
- u8 smp_frame_type; /* 0x41 */
- u8 function; /* 0x11 */
- u8 function_result;
- u8 response_length;
- __be16 expander_change_count;
- u8 reserved_1[3];
- u8 phy_identifier;
- u8 reserved_2[2];
- __be32 invalid_dword;
- __be32 running_disparity_error;
- __be32 loss_of_dword_sync;
- __be32 phy_reset_problem;
-};
-
-/**
- * _transport_get_expander_phy_error_log - return expander counters
- * @ioc: per adapter object
- * @phy: The sas phy object
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
- struct sas_phy *phy)
-{
- Mpi2SmpPassthroughRequest_t *mpi_request;
- Mpi2SmpPassthroughReply_t *mpi_reply;
- struct phy_error_log_request *phy_error_log_request;
- struct phy_error_log_reply *phy_error_log_reply;
- int rc;
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- void *psge;
- u32 sgl_flags;
- u8 issue_reset = 0;
- void *data_out = NULL;
- dma_addr_t data_out_dma;
- u32 sz;
- u16 wait_state_count;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery) {
- printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
- __func__, ioc->name);
- return -EFAULT;
- }
-
- mutex_lock(&ioc->transport_cmds.mutex);
-
- if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
- ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
- if (wait_state_count)
- printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
- ioc->name, __func__);
-
- smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->transport_cmds.smid = smid;
-
- sz = sizeof(struct phy_error_log_request) +
- sizeof(struct phy_error_log_reply);
- data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
- if (!data_out) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- rc = -ENOMEM;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
-
- rc = -EINVAL;
- memset(data_out, 0, sz);
- phy_error_log_request = data_out;
- phy_error_log_request->smp_frame_type = 0x40;
- phy_error_log_request->function = 0x11;
- phy_error_log_request->request_length = 2;
- phy_error_log_request->allocated_response_length = 0;
- phy_error_log_request->phy_identifier = phy->number;
-
- memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
- mpi_request->PhysicalPort = 0xFF;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
- mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
- mpi_request->RequestDataLength =
- cpu_to_le16(sizeof(struct phy_error_log_request));
- psge = &mpi_request->SGL;
-
- /* WRITE sgel first */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- sizeof(struct phy_error_log_request), data_out_dma);
-
- /* incr sgel */
- psge += ioc->sge_size;
-
- /* READ sgel last */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- sizeof(struct phy_error_log_reply), data_out_dma +
- sizeof(struct phy_error_log_request));
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
- "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
- (unsigned long long)phy->identify.sas_address, phy->number));
- init_completion(&ioc->transport_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
- 10*HZ);
-
- if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SmpPassthroughRequest_t)/4);
- if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
- "complete\n", ioc->name));
-
- if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-
- mpi_reply = ioc->transport_cmds.reply;
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "phy_error_log - reply data transfer size(%d)\n",
- ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
-
- if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
- sizeof(struct phy_error_log_reply))
- goto out;
-
- phy_error_log_reply = data_out +
- sizeof(struct phy_error_log_request);
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "phy_error_log - function_result(%d)\n",
- ioc->name, phy_error_log_reply->function_result));
-
- phy->invalid_dword_count =
- be32_to_cpu(phy_error_log_reply->invalid_dword);
- phy->running_disparity_error_count =
- be32_to_cpu(phy_error_log_reply->running_disparity_error);
- phy->loss_of_dword_sync_count =
- be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
- phy->phy_reset_problem_count =
- be32_to_cpu(phy_error_log_reply->phy_reset_problem);
- rc = 0;
- } else
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "phy_error_log - no reply\n", ioc->name));
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- out:
- ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
- if (data_out)
- pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
-
- mutex_unlock(&ioc->transport_cmds.mutex);
- return rc;
-}
-
-/**
- * _transport_get_linkerrors - return phy counters for both hba and expanders
- * @phy: The sas phy object
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_transport_get_linkerrors(struct sas_phy *phy)
-{
- struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
- unsigned long flags;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasPhyPage1_t phy_pg1;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- if (_transport_sas_node_find_by_sas_address(ioc,
- phy->identify.sas_address) == NULL) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return -EINVAL;
- }
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- if (phy->identify.sas_address != ioc->sas_hba.sas_address)
- return _transport_get_expander_phy_error_log(ioc, phy);
-
- /* get hba phy error logs */
- if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
- phy->number))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -ENXIO;
- }
-
- if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
- printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
- "(0x%04x), loginfo(0x%08x)\n", ioc->name,
- phy->number, le16_to_cpu(mpi_reply.IOCStatus),
- le32_to_cpu(mpi_reply.IOCLogInfo));
-
- phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
- phy->running_disparity_error_count =
- le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
- phy->loss_of_dword_sync_count =
- le32_to_cpu(phy_pg1.LossDwordSynchCount);
- phy->phy_reset_problem_count =
- le32_to_cpu(phy_pg1.PhyResetProblemCount);
- return 0;
-}
-
-/**
- * _transport_get_enclosure_identifier -
- * @phy: The sas phy object
- *
- * Obtain the enclosure logical id for an expander.
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
-{
- struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
- struct _sas_device *sas_device;
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- rphy->identify.sas_address);
- if (sas_device) {
- *identifier = sas_device->enclosure_logical_id;
- rc = 0;
- sas_device_put(sas_device);
- } else {
- *identifier = 0;
- rc = -ENXIO;
- }
-
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return rc;
-}
-
-/**
- * _transport_get_bay_identifier -
- * @phy: The sas phy object
- *
- * Returns the slot id for a device that resides inside an enclosure.
- */
-static int
-_transport_get_bay_identifier(struct sas_rphy *rphy)
-{
- struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
- struct _sas_device *sas_device;
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = __mpt2sas_get_sdev_by_addr(ioc,
- rphy->identify.sas_address);
- if (sas_device) {
- rc = sas_device->slot;
- sas_device_put(sas_device);
- } else {
- rc = -ENXIO;
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return rc;
-}
-
-/* phy control request structure */
-struct phy_control_request{
- u8 smp_frame_type; /* 0x40 */
- u8 function; /* 0x91 */
- u8 allocated_response_length;
- u8 request_length; /* 0x09 */
- u16 expander_change_count;
- u8 reserved_1[3];
- u8 phy_identifier;
- u8 phy_operation;
- u8 reserved_2[13];
- u64 attached_device_name;
- u8 programmed_min_physical_link_rate;
- u8 programmed_max_physical_link_rate;
- u8 reserved_3[6];
-};
-
-/* phy control reply structure */
-struct phy_control_reply{
- u8 smp_frame_type; /* 0x41 */
- u8 function; /* 0x11 */
- u8 function_result;
- u8 response_length;
-};
-
-#define SMP_PHY_CONTROL_LINK_RESET (0x01)
-#define SMP_PHY_CONTROL_HARD_RESET (0x02)
-#define SMP_PHY_CONTROL_DISABLE (0x03)
-
-/**
- * _transport_expander_phy_control - expander phy control
- * @ioc: per adapter object
- * @phy: The sas phy object
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
- struct sas_phy *phy, u8 phy_operation)
-{
- Mpi2SmpPassthroughRequest_t *mpi_request;
- Mpi2SmpPassthroughReply_t *mpi_reply;
- struct phy_control_request *phy_control_request;
- struct phy_control_reply *phy_control_reply;
- int rc;
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- void *psge;
- u32 sgl_flags;
- u8 issue_reset = 0;
- void *data_out = NULL;
- dma_addr_t data_out_dma;
- u32 sz;
- u16 wait_state_count;
-
- if (ioc->shost_recovery) {
- printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
- __func__, ioc->name);
- return -EFAULT;
- }
-
- mutex_lock(&ioc->transport_cmds.mutex);
-
- if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
- ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto out;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
- if (wait_state_count)
- printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
- ioc->name, __func__);
-
- smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto out;
- }
-
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->transport_cmds.smid = smid;
-
- sz = sizeof(struct phy_control_request) +
- sizeof(struct phy_control_reply);
- data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
- if (!data_out) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
- __LINE__, __func__);
- rc = -ENOMEM;
- mpt2sas_base_free_smid(ioc, smid);
- goto out;
- }
-
- rc = -EINVAL;
- memset(data_out, 0, sz);
- phy_control_request = data_out;
- phy_control_request->smp_frame_type = 0x40;
- phy_control_request->function = 0x91;
- phy_control_request->request_length = 9;
- phy_control_request->allocated_response_length = 0;
- phy_control_request->phy_identifier = phy->number;
- phy_control_request->phy_operation = phy_operation;
- phy_control_request->programmed_min_physical_link_rate =
- phy->minimum_linkrate << 4;
- phy_control_request->programmed_max_physical_link_rate =
- phy->maximum_linkrate << 4;
-
- memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
- mpi_request->PhysicalPort = 0xFF;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
- mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
- mpi_request->RequestDataLength =
- cpu_to_le16(sizeof(struct phy_error_log_request));
- psge = &mpi_request->SGL;
-
- /* WRITE sgel first */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- sizeof(struct phy_control_request), data_out_dma);
-
- /* incr sgel */
- psge += ioc->sge_size;
-
- /* READ sgel last */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- ioc->base_add_sg_single(psge, sgl_flags |
- sizeof(struct phy_control_reply), data_out_dma +
- sizeof(struct phy_control_request));
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
- "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
- (unsigned long long)phy->identify.sas_address, phy->number,
- phy_operation));
-
- init_completion(&ioc->transport_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
- 10*HZ);
-
- if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s: timeout\n",
- ioc->name, __func__);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SmpPassthroughRequest_t)/4);
- if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
- "complete\n", ioc->name));
-
- if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-
- mpi_reply = ioc->transport_cmds.reply;
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "phy_control - reply data transfer size(%d)\n",
- ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
-
- if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
- sizeof(struct phy_control_reply))
- goto out;
-
- phy_control_reply = data_out +
- sizeof(struct phy_control_request);
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "phy_control - function_result(%d)\n",
- ioc->name, phy_control_reply->function_result));
-
- rc = 0;
- } else
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "phy_control - no reply\n", ioc->name));
-
- issue_host_reset:
- if (issue_reset)
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- out:
- ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
- if (data_out)
- pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
-
- mutex_unlock(&ioc->transport_cmds.mutex);
- return rc;
-}
-
-/**
- * _transport_phy_reset -
- * @phy: The sas phy object
- * @hard_reset:
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_phy_reset(struct sas_phy *phy, int hard_reset)
-{
- struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
- Mpi2SasIoUnitControlReply_t mpi_reply;
- Mpi2SasIoUnitControlRequest_t mpi_request;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- if (_transport_sas_node_find_by_sas_address(ioc,
- phy->identify.sas_address) == NULL) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return -EINVAL;
- }
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- /* handle expander phys */
- if (phy->identify.sas_address != ioc->sas_hba.sas_address)
- return _transport_expander_phy_control(ioc, phy,
- (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
- SMP_PHY_CONTROL_LINK_RESET);
-
- /* handle hba phys */
- memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
- mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
- mpi_request.Operation = hard_reset ?
- MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
- mpi_request.PhyNum = phy->number;
-
- if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- return -ENXIO;
- }
-
- if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
- printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
- "(0x%04x), loginfo(0x%08x)\n", ioc->name,
- phy->number, le16_to_cpu(mpi_reply.IOCStatus),
- le32_to_cpu(mpi_reply.IOCLogInfo));
-
- return 0;
-}
-
-/**
- * _transport_phy_enable - enable/disable phys
- * @phy: The sas phy object
- * @enable: enable phy when true
- *
- * Only support sas_host direct attached phys.
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_phy_enable(struct sas_phy *phy, int enable)
-{
- struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
- Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
- Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
- Mpi2ConfigReply_t mpi_reply;
- u16 ioc_status;
- u16 sz;
- int rc = 0;
- unsigned long flags;
- int i, discovery_active;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- if (_transport_sas_node_find_by_sas_address(ioc,
- phy->identify.sas_address) == NULL) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return -EINVAL;
- }
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- /* handle expander phys */
- if (phy->identify.sas_address != ioc->sas_hba.sas_address)
- return _transport_expander_phy_control(ioc, phy,
- (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
- SMP_PHY_CONTROL_DISABLE);
-
- /* handle hba phys */
-
- /* read sas_iounit page 0 */
- sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit0PhyData_t));
- sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg0) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENOMEM;
- goto out;
- }
- if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
- sas_iounit_pg0, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENXIO;
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -EIO;
- goto out;
- }
-
- /* unable to enable/disable phys when when discovery is active */
- for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
- if (sas_iounit_pg0->PhyData[i].PortFlags &
- MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
- printk(MPT2SAS_ERR_FMT "discovery is active on "
- "port = %d, phy = %d: unable to enable/disable "
- "phys, try again later!\n", ioc->name,
- sas_iounit_pg0->PhyData[i].Port, i);
- discovery_active = 1;
- }
- }
-
- if (discovery_active) {
- rc = -EAGAIN;
- goto out;
- }
-
- /* read sas_iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
- sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg1) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENOMEM;
- goto out;
- }
- if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
- sas_iounit_pg1, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENXIO;
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -EIO;
- goto out;
- }
- /* copy Port/PortFlags/PhyFlags from page 0 */
- for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
- sas_iounit_pg1->PhyData[i].Port =
- sas_iounit_pg0->PhyData[i].Port;
- sas_iounit_pg1->PhyData[i].PortFlags =
- (sas_iounit_pg0->PhyData[i].PortFlags &
- MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
- sas_iounit_pg1->PhyData[i].PhyFlags =
- (sas_iounit_pg0->PhyData[i].PhyFlags &
- (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
- MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
- }
- if (enable)
- sas_iounit_pg1->PhyData[phy->number].PhyFlags
- &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
- else
- sas_iounit_pg1->PhyData[phy->number].PhyFlags
- |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
-
- mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
-
- /* link reset */
- if (enable)
- _transport_phy_reset(phy, 0);
-
- out:
- kfree(sas_iounit_pg1);
- kfree(sas_iounit_pg0);
- return rc;
-}
-
-/**
- * _transport_phy_speed - set phy min/max link rates
- * @phy: The sas phy object
- * @rates: rates defined in sas_phy_linkrates
- *
- * Only support sas_host direct attached phys.
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
-{
- struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
- Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
- Mpi2SasPhyPage0_t phy_pg0;
- Mpi2ConfigReply_t mpi_reply;
- u16 ioc_status;
- u16 sz;
- int i;
- int rc = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- if (_transport_sas_node_find_by_sas_address(ioc,
- phy->identify.sas_address) == NULL) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return -EINVAL;
- }
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
- if (!rates->minimum_linkrate)
- rates->minimum_linkrate = phy->minimum_linkrate;
- else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
- rates->minimum_linkrate = phy->minimum_linkrate_hw;
-
- if (!rates->maximum_linkrate)
- rates->maximum_linkrate = phy->maximum_linkrate;
- else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
- rates->maximum_linkrate = phy->maximum_linkrate_hw;
-
- /* handle expander phys */
- if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
- phy->minimum_linkrate = rates->minimum_linkrate;
- phy->maximum_linkrate = rates->maximum_linkrate;
- return _transport_expander_phy_control(ioc, phy,
- SMP_PHY_CONTROL_LINK_RESET);
- }
-
- /* handle hba phys */
-
- /* sas_iounit page 1 */
- sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
- sizeof(Mpi2SasIOUnit1PhyData_t));
- sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
- if (!sas_iounit_pg1) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENOMEM;
- goto out;
- }
- if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
- sas_iounit_pg1, sz))) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENXIO;
- goto out;
- }
- ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
- MPI2_IOCSTATUS_MASK;
- if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -EIO;
- goto out;
- }
-
- for (i = 0; i < ioc->sas_hba.num_phys; i++) {
- if (phy->number != i) {
- sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
- (ioc->sas_hba.phy[i].phy->minimum_linkrate +
- (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
- } else {
- sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
- (rates->minimum_linkrate +
- (rates->maximum_linkrate << 4));
- }
- }
-
- if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
- sz)) {
- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
- ioc->name, __FILE__, __LINE__, __func__);
- rc = -ENXIO;
- goto out;
- }
-
- /* link reset */
- _transport_phy_reset(phy, 0);
-
- /* read phy page 0, then update the rates in the sas transport phy */
- if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
- phy->number)) {
- phy->minimum_linkrate = _transport_convert_phy_link_rate(
- phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
- phy->maximum_linkrate = _transport_convert_phy_link_rate(
- phy_pg0.ProgrammedLinkRate >> 4);
- phy->negotiated_linkrate = _transport_convert_phy_link_rate(
- phy_pg0.NegotiatedLinkRate &
- MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
- }
-
- out:
- kfree(sas_iounit_pg1);
- return rc;
-}
-
-
-/**
- * _transport_smp_handler - transport portal for smp passthru
- * @shost: shost object
- * @rphy: sas transport rphy object
- * @req:
- *
- * This used primarily for smp_utils.
- * Example:
- * smp_rep_general /sys/class/bsg/expander-5:0
- */
-static int
-_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
- struct request *req)
-{
- struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- Mpi2SmpPassthroughRequest_t *mpi_request;
- Mpi2SmpPassthroughReply_t *mpi_reply;
- int rc;
- u16 smid;
- u32 ioc_state;
- unsigned long timeleft;
- void *psge;
- u32 sgl_flags;
- u8 issue_reset = 0;
- dma_addr_t dma_addr_in = 0;
- dma_addr_t dma_addr_out = 0;
- dma_addr_t pci_dma_in = 0;
- dma_addr_t pci_dma_out = 0;
- void *pci_addr_in = NULL;
- void *pci_addr_out = NULL;
- u16 wait_state_count;
- struct request *rsp = req->next_rq;
- struct bio_vec bvec;
- struct bvec_iter iter;
-
- if (!rsp) {
- printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
- "missing\n", ioc->name, __func__);
- return -EINVAL;
- }
- if (ioc->shost_recovery || ioc->pci_error_recovery) {
- printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
- __func__, ioc->name);
- return -EFAULT;
- }
-
- rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
- if (rc)
- return rc;
-
- if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
- printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
- __func__);
- rc = -EAGAIN;
- goto out;
- }
- ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
- /* Check if the request is split across multiple segments */
- if (bio_multiple_segments(req->bio)) {
- u32 offset = 0;
-
- /* Allocate memory and copy the request */
- pci_addr_out = pci_alloc_consistent(ioc->pdev,
- blk_rq_bytes(req), &pci_dma_out);
- if (!pci_addr_out) {
- printk(MPT2SAS_INFO_FMT "%s(): PCI Addr out = NULL\n",
- ioc->name, __func__);
- rc = -ENOMEM;
- goto out;
- }
-
- bio_for_each_segment(bvec, req->bio, iter) {
- memcpy(pci_addr_out + offset,
- page_address(bvec.bv_page) + bvec.bv_offset,
- bvec.bv_len);
- offset += bvec.bv_len;
- }
- } else {
- dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
- blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
- if (!dma_addr_out) {
- printk(MPT2SAS_INFO_FMT "%s(): DMA Addr out = NULL\n",
- ioc->name, __func__);
- rc = -ENOMEM;
- goto free_pci;
- }
- }
-
- /* Check if the response needs to be populated across
- * multiple segments */
- if (bio_multiple_segments(rsp->bio)) {
- pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
- &pci_dma_in);
- if (!pci_addr_in) {
- printk(MPT2SAS_INFO_FMT "%s(): PCI Addr in = NULL\n",
- ioc->name, __func__);
- rc = -ENOMEM;
- goto unmap;
- }
- } else {
- dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
- blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
- if (!dma_addr_in) {
- printk(MPT2SAS_INFO_FMT "%s(): DMA Addr in = NULL\n",
- ioc->name, __func__);
- rc = -ENOMEM;
- goto unmap;
- }
- }
-
- wait_state_count = 0;
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
- if (wait_state_count++ == 10) {
- printk(MPT2SAS_ERR_FMT
- "%s: failed due to ioc not operational\n",
- ioc->name, __func__);
- rc = -EFAULT;
- goto unmap;
- }
- ssleep(1);
- ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
- printk(MPT2SAS_INFO_FMT "%s: waiting for "
- "operational state(count=%d)\n", ioc->name,
- __func__, wait_state_count);
- }
- if (wait_state_count)
- printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
- ioc->name, __func__);
-
- smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
- if (!smid) {
- printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
- ioc->name, __func__);
- rc = -EAGAIN;
- goto unmap;
- }
-
- rc = 0;
- mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
- ioc->transport_cmds.smid = smid;
-
- memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
- mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
- mpi_request->PhysicalPort = 0xFF;
- mpi_request->VF_ID = 0; /* TODO */
- mpi_request->VP_ID = 0;
- mpi_request->SASAddress = (rphy) ?
- cpu_to_le64(rphy->identify.sas_address) :
- cpu_to_le64(ioc->sas_hba.sas_address);
- mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
- psge = &mpi_request->SGL;
-
- /* WRITE sgel first */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- if (bio_multiple_segments(req->bio)) {
- ioc->base_add_sg_single(psge, sgl_flags |
- (blk_rq_bytes(req) - 4), pci_dma_out);
- } else {
- ioc->base_add_sg_single(psge, sgl_flags |
- (blk_rq_bytes(req) - 4), dma_addr_out);
- }
-
- /* incr sgel */
- psge += ioc->sge_size;
-
- /* READ sgel last */
- sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
- MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST);
- sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- if (bio_multiple_segments(rsp->bio)) {
- ioc->base_add_sg_single(psge, sgl_flags |
- (blk_rq_bytes(rsp) + 4), pci_dma_in);
- } else {
- ioc->base_add_sg_single(psge, sgl_flags |
- (blk_rq_bytes(rsp) + 4), dma_addr_in);
- }
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
- "sending smp request\n", ioc->name, __func__));
-
- init_completion(&ioc->transport_cmds.done);
- mpt2sas_base_put_smid_default(ioc, smid);
- timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
- 10*HZ);
-
- if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
- printk(MPT2SAS_ERR_FMT "%s : timeout\n",
- __func__, ioc->name);
- _debug_dump_mf(mpi_request,
- sizeof(Mpi2SmpPassthroughRequest_t)/4);
- if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
- }
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
- "complete\n", ioc->name, __func__));
-
- if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-
- mpi_reply = ioc->transport_cmds.reply;
-
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s - reply data transfer size(%d)\n",
- ioc->name, __func__,
- le16_to_cpu(mpi_reply->ResponseDataLength)));
-
- memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
- req->sense_len = sizeof(*mpi_reply);
- req->resid_len = 0;
- rsp->resid_len -=
- le16_to_cpu(mpi_reply->ResponseDataLength);
- /* check if the resp needs to be copied from the allocated
- * pci mem */
- if (bio_multiple_segments(rsp->bio)) {
- u32 offset = 0;
- u32 bytes_to_copy =
- le16_to_cpu(mpi_reply->ResponseDataLength);
- bio_for_each_segment(bvec, rsp->bio, iter) {
- if (bytes_to_copy <= bvec.bv_len) {
- memcpy(page_address(bvec.bv_page) +
- bvec.bv_offset, pci_addr_in +
- offset, bytes_to_copy);
- break;
- } else {
- memcpy(page_address(bvec.bv_page) +
- bvec.bv_offset, pci_addr_in +
- offset, bvec.bv_len);
- bytes_to_copy -= bvec.bv_len;
- }
- offset += bvec.bv_len;
- }
- }
- } else {
- dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
- "%s - no reply\n", ioc->name, __func__));
- rc = -ENXIO;
- }
-
- issue_host_reset:
- if (issue_reset) {
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
- FORCE_BIG_HAMMER);
- rc = -ETIMEDOUT;
- }
-
- unmap:
- if (dma_addr_out)
- pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
- PCI_DMA_BIDIRECTIONAL);
- if (dma_addr_in)
- pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
- PCI_DMA_BIDIRECTIONAL);
-
- free_pci:
- if (pci_addr_out)
- pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
- pci_dma_out);
-
- if (pci_addr_in)
- pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
- pci_dma_in);
-
- out:
- ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->transport_cmds.mutex);
- return rc;
-}
-
-struct sas_function_template mpt2sas_transport_functions = {
- .get_linkerrors = _transport_get_linkerrors,
- .get_enclosure_identifier = _transport_get_enclosure_identifier,
- .get_bay_identifier = _transport_get_bay_identifier,
- .phy_reset = _transport_phy_reset,
- .phy_enable = _transport_phy_enable,
- .set_phy_speed = _transport_phy_speed,
- .smp_handler = _transport_smp_handler,
-};
-
-struct scsi_transport_template *mpt2sas_transport_template;
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig
index 4d235dd741bf..29061467cc17 100644
--- a/drivers/scsi/mpt3sas/Kconfig
+++ b/drivers/scsi/mpt3sas/Kconfig
@@ -41,15 +41,15 @@
# USA.
config SCSI_MPT3SAS
- tristate "LSI MPT Fusion SAS 3.0 Device Driver"
+ tristate "LSI MPT Fusion SAS 3.0 & SAS 2.0 Device Driver"
depends on PCI && SCSI
select SCSI_SAS_ATTRS
select RAID_ATTRS
---help---
This driver supports PCI-Express SAS 12Gb/s Host Adapters.
-config SCSI_MPT3SAS_MAX_SGE
- int "LSI MPT Fusion Max number of SG Entries (16 - 256)"
+config SCSI_MPT2SAS_MAX_SGE
+ int "LSI MPT Fusion SAS 2.0 Max number of SG Entries (16 - 256)"
depends on PCI && SCSI && SCSI_MPT3SAS
default "128"
range 16 256
@@ -60,8 +60,14 @@ config SCSI_MPT3SAS_MAX_SGE
can be 256. However, it may decreased down to 16. Decreasing this
parameter will reduce memory requirements on a per controller instance.
-config SCSI_MPT3SAS_LOGGING
- bool "LSI MPT Fusion logging facility"
+config SCSI_MPT3SAS_MAX_SGE
+ int "LSI MPT Fusion SAS 3.0 Max number of SG Entries (16 - 256)"
depends on PCI && SCSI && SCSI_MPT3SAS
+ default "128"
+ range 16 256
---help---
- This turns on a logging facility.
+ This option allows you to specify the maximum number of scatter-
+ gather entries per I/O. The driver default is 128, which matches
+ MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this
+ can be 256. However, it may decreased down to 16. Decreasing this
+ parameter will reduce memory requirements on a per controller instance.
diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile
index efb0c4c2e310..b7643f596c1e 100644
--- a/drivers/scsi/mpt3sas/Makefile
+++ b/drivers/scsi/mpt3sas/Makefile
@@ -5,4 +5,5 @@ mpt3sas-y += mpt3sas_base.o \
mpt3sas_scsih.o \
mpt3sas_transport.o \
mpt3sas_ctl.o \
- mpt3sas_trigger_diag.o
+ mpt3sas_trigger_diag.o \
+ mpt3sas_warpdrive.o
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index d4f1dcdb8361..11393ebf1a68 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -108,9 +108,12 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
if (ret)
return ret;
+ /* global ioc spinlock to protect controller list on list operations */
pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug);
+ spin_lock(&gioc_lock);
list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
ioc->fwfault_debug = mpt3sas_fwfault_debug;
+ spin_unlock(&gioc_lock);
return 0;
}
module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug,
@@ -157,7 +160,7 @@ _base_fault_reset_work(struct work_struct *work)
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery)
+ if (ioc->shost_recovery || ioc->pci_error_recovery)
goto rearm_timer;
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
@@ -166,6 +169,20 @@ _base_fault_reset_work(struct work_struct *work)
pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n",
ioc->name);
+ /* It may be possible that EEH recovery can resolve some of
+ * pci bus failure issues rather removing the dead ioc function
+ * by considering controller is in a non-operational state. So
+ * here priority is given to the EEH recovery. If it doesn't
+ * not resolve this issue, mpt3sas driver will consider this
+ * controller to non-operational state and remove the dead ioc
+ * function.
+ */
+ if (ioc->non_operational_loop++ < 5) {
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock,
+ flags);
+ goto rearm_timer;
+ }
+
/*
* Call _scsih_flush_pending_cmds callback so that we flush all
* pending commands back to OS. This call is required to aovid
@@ -181,7 +198,7 @@ _base_fault_reset_work(struct work_struct *work)
ioc->remove_host = 1;
/*Remove the Dead Host */
p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc,
- "mpt3sas_dead_ioc_%d", ioc->id);
+ "%s_dead_ioc_%d", ioc->driver_name, ioc->id);
if (IS_ERR(p))
pr_err(MPT3SAS_FMT
"%s: Running mpt3sas_dead_ioc thread failed !!!!\n",
@@ -193,6 +210,8 @@ _base_fault_reset_work(struct work_struct *work)
return; /* don't rearm timer */
}
+ ioc->non_operational_loop = 0;
+
if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) {
rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
@@ -235,7 +254,8 @@ mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc)
INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
snprintf(ioc->fault_reset_work_q_name,
- sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+ sizeof(ioc->fault_reset_work_q_name), "poll_%s%d_status",
+ ioc->driver_name, ioc->id);
ioc->fault_reset_work_q =
create_singlethread_workqueue(ioc->fault_reset_work_q_name);
if (!ioc->fault_reset_work_q) {
@@ -324,7 +344,6 @@ mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc)
panic("panic in %s\n", __func__);
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _base_sas_ioc_info - verbose translation of the ioc status
* @ioc: per adapter object
@@ -578,7 +597,8 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
desc = "Device Status Change";
break;
case MPI2_EVENT_IR_OPERATION_STATUS:
- desc = "IR Operation Status";
+ if (!ioc->hide_ir_msg)
+ desc = "IR Operation Status";
break;
case MPI2_EVENT_SAS_DISCOVERY:
{
@@ -609,16 +629,20 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
desc = "SAS Enclosure Device Status Change";
break;
case MPI2_EVENT_IR_VOLUME:
- desc = "IR Volume";
+ if (!ioc->hide_ir_msg)
+ desc = "IR Volume";
break;
case MPI2_EVENT_IR_PHYSICAL_DISK:
- desc = "IR Physical Disk";
+ if (!ioc->hide_ir_msg)
+ desc = "IR Physical Disk";
break;
case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
- desc = "IR Configuration Change List";
+ if (!ioc->hide_ir_msg)
+ desc = "IR Configuration Change List";
break;
case MPI2_EVENT_LOG_ENTRY_ADDED:
- desc = "Log Entry Added";
+ if (!ioc->hide_ir_msg)
+ desc = "Log Entry Added";
break;
case MPI2_EVENT_TEMP_THRESHOLD:
desc = "Temperature Threshold";
@@ -630,7 +654,6 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc);
}
-#endif
/**
* _base_sas_log_info - verbose translation of firmware log info
@@ -675,7 +698,10 @@ _base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info)
originator_str = "PL";
break;
case 2:
- originator_str = "IR";
+ if (!ioc->hide_ir_msg)
+ originator_str = "IR";
+ else
+ originator_str = "WarpDrive";
break;
}
@@ -710,13 +736,13 @@ _base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
return;
}
ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+
if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
(ioc->logging_level & MPT_DEBUG_REPLY)) {
_base_sas_ioc_info(ioc , mpi_reply,
mpt3sas_base_get_msg_frame(ioc, smid));
}
-#endif
+
if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
loginfo = le32_to_cpu(mpi_reply->IOCLogInfo);
_base_sas_log_info(ioc, loginfo);
@@ -783,9 +809,9 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
return 1;
if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
return 1;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+
_base_display_event_data(ioc, mpi_reply);
-#endif
+
if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
goto out;
smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
@@ -1009,6 +1035,12 @@ _base_interrupt(int irq, void *bus_id)
}
wmb();
+ if (ioc->is_warpdrive) {
+ writel(reply_q->reply_post_host_index,
+ ioc->reply_post_host_index[msix_index]);
+ atomic_dec(&reply_q->busy);
+ return IRQ_HANDLED;
+ }
/* Update Reply Post Host Index.
* For those HBA's which support combined reply queue feature
@@ -1320,6 +1352,149 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
}
/**
+ * _base_build_sg_scmd - main sg creation routine
+ * @ioc: per adapter object
+ * @scmd: scsi command
+ * @smid: system request message index
+ * Context: none.
+ *
+ * The main routine that builds scatter gather table from a given
+ * scsi request sent via the .queuecommand main handler.
+ *
+ * Returns 0 success, anything else error
+ */
+static int
+_base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
+ struct scsi_cmnd *scmd, u16 smid)
+{
+ Mpi2SCSIIORequest_t *mpi_request;
+ dma_addr_t chain_dma;
+ struct scatterlist *sg_scmd;
+ void *sg_local, *chain;
+ u32 chain_offset;
+ u32 chain_length;
+ u32 chain_flags;
+ int sges_left;
+ u32 sges_in_segment;
+ u32 sgl_flags;
+ u32 sgl_flags_last_element;
+ u32 sgl_flags_end_buffer;
+ struct chain_tracker *chain_req;
+
+ mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+
+ /* init scatter gather flags */
+ sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
+ if (scmd->sc_data_direction == DMA_TO_DEVICE)
+ sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
+ sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
+ << MPI2_SGE_FLAGS_SHIFT;
+ sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
+ MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
+ << MPI2_SGE_FLAGS_SHIFT;
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+
+ sg_scmd = scsi_sglist(scmd);
+ sges_left = scsi_dma_map(scmd);
+ if (sges_left < 0) {
+ sdev_printk(KERN_ERR, scmd->device,
+ "pci_map_sg failed: request for %d bytes!\n",
+ scsi_bufflen(scmd));
+ return -ENOMEM;
+ }
+
+ sg_local = &mpi_request->SGL;
+ sges_in_segment = ioc->max_sges_in_main_message;
+ if (sges_left <= sges_in_segment)
+ goto fill_in_last_segment;
+
+ mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
+ (sges_in_segment * ioc->sge_size))/4;
+
+ /* fill in main message segment when there is a chain following */
+ while (sges_in_segment) {
+ if (sges_in_segment == 1)
+ ioc->base_add_sg_single(sg_local,
+ sgl_flags_last_element | sg_dma_len(sg_scmd),
+ sg_dma_address(sg_scmd));
+ else
+ ioc->base_add_sg_single(sg_local, sgl_flags |
+ sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+ sg_scmd = sg_next(sg_scmd);
+ sg_local += ioc->sge_size;
+ sges_left--;
+ sges_in_segment--;
+ }
+
+ /* initializing the chain flags and pointers */
+ chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
+ chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+ if (!chain_req)
+ return -1;
+ chain = chain_req->chain_buffer;
+ chain_dma = chain_req->chain_buffer_dma;
+ do {
+ sges_in_segment = (sges_left <=
+ ioc->max_sges_in_chain_message) ? sges_left :
+ ioc->max_sges_in_chain_message;
+ chain_offset = (sges_left == sges_in_segment) ?
+ 0 : (sges_in_segment * ioc->sge_size)/4;
+ chain_length = sges_in_segment * ioc->sge_size;
+ if (chain_offset) {
+ chain_offset = chain_offset <<
+ MPI2_SGE_CHAIN_OFFSET_SHIFT;
+ chain_length += ioc->sge_size;
+ }
+ ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
+ chain_length, chain_dma);
+ sg_local = chain;
+ if (!chain_offset)
+ goto fill_in_last_segment;
+
+ /* fill in chain segments */
+ while (sges_in_segment) {
+ if (sges_in_segment == 1)
+ ioc->base_add_sg_single(sg_local,
+ sgl_flags_last_element |
+ sg_dma_len(sg_scmd),
+ sg_dma_address(sg_scmd));
+ else
+ ioc->base_add_sg_single(sg_local, sgl_flags |
+ sg_dma_len(sg_scmd),
+ sg_dma_address(sg_scmd));
+ sg_scmd = sg_next(sg_scmd);
+ sg_local += ioc->sge_size;
+ sges_left--;
+ sges_in_segment--;
+ }
+
+ chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+ if (!chain_req)
+ return -1;
+ chain = chain_req->chain_buffer;
+ chain_dma = chain_req->chain_buffer_dma;
+ } while (1);
+
+
+ fill_in_last_segment:
+
+ /* fill the last segment */
+ while (sges_left) {
+ if (sges_left == 1)
+ ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
+ sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+ else
+ ioc->base_add_sg_single(sg_local, sgl_flags |
+ sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+ sg_scmd = sg_next(sg_scmd);
+ sg_local += ioc->sge_size;
+ sges_left--;
+ }
+
+ return 0;
+}
+
+/**
* _base_build_sg_scmd_ieee - main sg creation routine for IEEE format
* @ioc: per adapter object
* @scmd: scsi command
@@ -1571,6 +1746,14 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc)
int base;
u16 message_control;
+ /* Check whether controller SAS2008 B0 controller,
+ * if it is SAS2008 B0 controller use IO-APIC instead of MSIX
+ */
+ if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
+ ioc->pdev->revision == SAS2_PCI_DEVICE_B0_REVISION) {
+ return -EINVAL;
+ }
+
base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
if (!base) {
dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n",
@@ -1579,9 +1762,19 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc)
}
/* get msix vector count */
-
- pci_read_config_word(ioc->pdev, base + 2, &message_control);
- ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+ /* NUMA_IO not supported for older controllers */
+ if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2)
+ ioc->msix_vector_count = 1;
+ else {
+ pci_read_config_word(ioc->pdev, base + 2, &message_control);
+ ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+ }
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"msix is supported, vector_count(%d)\n",
ioc->name, ioc->msix_vector_count));
@@ -1643,10 +1836,10 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
atomic_set(&reply_q->busy, 0);
if (ioc->msix_enable)
snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
- MPT3SAS_DRIVER_NAME, ioc->id, index);
+ ioc->driver_name, ioc->id, index);
else
snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
- MPT3SAS_DRIVER_NAME, ioc->id);
+ ioc->driver_name, ioc->id);
r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
reply_q);
if (r) {
@@ -1872,7 +2065,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
if (pci_request_selected_regions(pdev, ioc->bars,
- MPT3SAS_DRIVER_NAME)) {
+ ioc->driver_name)) {
pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n",
ioc->name);
ioc->bars = 0;
@@ -2158,6 +2351,7 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
}
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
+ ioc->scsi_lookup[i].direct_io = 0;
list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list);
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
@@ -2318,143 +2512,261 @@ mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
}
/**
- * _base_display_intel_branding - Display branding string
+ * _base_display_OEMs_branding - Display branding string
* @ioc: per adapter object
*
* Return nothing.
*/
static void
-_base_display_intel_branding(struct MPT3SAS_ADAPTER *ioc)
+_base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc)
{
if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
return;
- switch (ioc->pdev->device) {
- case MPI25_MFGPAGE_DEVID_SAS3008:
- switch (ioc->pdev->subsystem_device) {
- case MPT3SAS_INTEL_RMS3JC080_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_INTEL_RMS3JC080_BRANDING);
- break;
-
- case MPT3SAS_INTEL_RS3GC008_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_INTEL_RS3GC008_BRANDING);
- break;
- case MPT3SAS_INTEL_RS3FC044_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_INTEL_RS3FC044_BRANDING);
- break;
- case MPT3SAS_INTEL_RS3UC080_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_INTEL_RS3UC080_BRANDING);
+ switch (ioc->pdev->subsystem_vendor) {
+ case PCI_VENDOR_ID_INTEL:
+ switch (ioc->pdev->device) {
+ case MPI2_MFGPAGE_DEVID_SAS2008:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_INTEL_RMS2LL080_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS2LL080_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS2LL040_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS2LL040_BRANDING);
+ break;
+ case MPT2SAS_INTEL_SSD910_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_SSD910_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Intel(R) Controller: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
+ case MPI2_MFGPAGE_DEVID_SAS2308_2:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_INTEL_RS25GB008_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RS25GB008_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25JB080_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25JB080_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25JB040_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25JB040_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25KB080_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25KB080_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25KB040_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25KB040_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25LB040_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25LB040_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25LB080_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25LB080_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Intel(R) Controller: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
+ case MPI25_MFGPAGE_DEVID_SAS3008:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT3SAS_INTEL_RMS3JC080_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_INTEL_RMS3JC080_BRANDING);
+ break;
+
+ case MPT3SAS_INTEL_RS3GC008_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_INTEL_RS3GC008_BRANDING);
+ break;
+ case MPT3SAS_INTEL_RS3FC044_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_INTEL_RS3FC044_BRANDING);
+ break;
+ case MPT3SAS_INTEL_RS3UC080_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_INTEL_RS3UC080_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Intel(R) Controller: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
break;
default:
pr_info(MPT3SAS_FMT
- "Intel(R) Controller: Subsystem ID: 0x%X\n",
- ioc->name, ioc->pdev->subsystem_device);
+ "Intel(R) Controller: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
break;
}
break;
- default:
- pr_info(MPT3SAS_FMT
- "Intel(R) Controller: Subsystem ID: 0x%X\n",
- ioc->name, ioc->pdev->subsystem_device);
- break;
- }
-}
-
-
-
-/**
- * _base_display_dell_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_dell_branding(struct MPT3SAS_ADAPTER *ioc)
-{
- if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
- return;
-
- switch (ioc->pdev->device) {
- case MPI25_MFGPAGE_DEVID_SAS3008:
- switch (ioc->pdev->subsystem_device) {
- case MPT3SAS_DELL_12G_HBA_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_DELL_12G_HBA_BRANDING);
+ case PCI_VENDOR_ID_DELL:
+ switch (ioc->pdev->device) {
+ case MPI2_MFGPAGE_DEVID_SAS2008:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING);
+ break;
+ case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING);
+ break;
+ case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING);
+ break;
+ case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING);
+ break;
+ case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING);
+ break;
+ case MPT2SAS_DELL_PERC_H200_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_PERC_H200_BRANDING);
+ break;
+ case MPT2SAS_DELL_6GBPS_SAS_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_DELL_6GBPS_SAS_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Dell 6Gbps HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
+ break;
+ case MPI25_MFGPAGE_DEVID_SAS3008:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT3SAS_DELL_12G_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_DELL_12G_HBA_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Dell 12Gbps HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
break;
default:
pr_info(MPT3SAS_FMT
- "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name,
+ "Dell HBA: Subsystem ID: 0x%X\n", ioc->name,
ioc->pdev->subsystem_device);
break;
}
break;
- default:
- pr_info(MPT3SAS_FMT
- "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name,
- ioc->pdev->subsystem_device);
- break;
- }
-}
-
-/**
- * _base_display_cisco_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_cisco_branding(struct MPT3SAS_ADAPTER *ioc)
-{
- if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_CISCO)
- return;
-
- switch (ioc->pdev->device) {
- case MPI25_MFGPAGE_DEVID_SAS3008:
- switch (ioc->pdev->subsystem_device) {
- case MPT3SAS_CISCO_12G_8E_HBA_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_CISCO_12G_8E_HBA_BRANDING);
- break;
- case MPT3SAS_CISCO_12G_8I_HBA_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_CISCO_12G_8I_HBA_BRANDING);
+ case PCI_VENDOR_ID_CISCO:
+ switch (ioc->pdev->device) {
+ case MPI25_MFGPAGE_DEVID_SAS3008:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT3SAS_CISCO_12G_8E_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_CISCO_12G_8E_HBA_BRANDING);
+ break;
+ case MPT3SAS_CISCO_12G_8I_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_CISCO_12G_8I_HBA_BRANDING);
+ break;
+ case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
break;
- case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ case MPI25_MFGPAGE_DEVID_SAS3108_1:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING);
+ break;
+ case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING
+ );
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
break;
default:
pr_info(MPT3SAS_FMT
- "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
- ioc->name, ioc->pdev->subsystem_device);
+ "Cisco SAS HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
break;
}
break;
- case MPI25_MFGPAGE_DEVID_SAS3108_1:
- switch (ioc->pdev->subsystem_device) {
- case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING);
- break;
- case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID:
- pr_info(MPT3SAS_FMT "%s\n", ioc->name,
- MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING);
- break;
+ case MPT2SAS_HP_3PAR_SSVID:
+ switch (ioc->pdev->device) {
+ case MPI2_MFGPAGE_DEVID_SAS2004:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
+ case MPI2_MFGPAGE_DEVID_SAS2308_2:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_HP_2_4_INTERNAL_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_HP_2_4_INTERNAL_BRANDING);
+ break;
+ case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
+ break;
+ case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
+ break;
+ case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
+ pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
+ break;
+ default:
+ pr_info(MPT3SAS_FMT
+ "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
+ break;
+ }
default:
pr_info(MPT3SAS_FMT
- "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
- ioc->name, ioc->pdev->subsystem_device);
+ "HP SAS HBA: Subsystem ID: 0x%X\n",
+ ioc->name, ioc->pdev->subsystem_device);
break;
}
- break;
default:
- pr_info(MPT3SAS_FMT
- "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
- ioc->name, ioc->pdev->subsystem_device);
break;
}
}
@@ -2488,9 +2800,7 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
(bios_version & 0x0000FF00) >> 8,
bios_version & 0x000000FF);
- _base_display_intel_branding(ioc);
- _base_display_dell_branding(ioc);
- _base_display_cisco_branding(ioc);
+ _base_display_OEMs_branding(ioc);
pr_info(MPT3SAS_FMT "Protocol=(", ioc->name);
@@ -2508,10 +2818,12 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
pr_info("), ");
pr_info("Capabilities=(");
- if (ioc->facts.IOCCapabilities &
+ if (!ioc->hide_ir_msg) {
+ if (ioc->facts.IOCCapabilities &
MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
pr_info("Raid");
i++;
+ }
}
if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
@@ -2852,18 +3164,22 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
/* command line tunables for max sgl entries */
if (max_sgl_entries != -1)
sg_tablesize = max_sgl_entries;
- else
- sg_tablesize = MPT3SAS_SG_DEPTH;
+ else {
+ if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+ sg_tablesize = MPT2SAS_SG_DEPTH;
+ else
+ sg_tablesize = MPT3SAS_SG_DEPTH;
+ }
- if (sg_tablesize < MPT3SAS_MIN_PHYS_SEGMENTS)
- sg_tablesize = MPT3SAS_MIN_PHYS_SEGMENTS;
- else if (sg_tablesize > MPT3SAS_MAX_PHYS_SEGMENTS) {
+ if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
+ sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
+ else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
sg_tablesize = min_t(unsigned short, sg_tablesize,
SCSI_MAX_SG_CHAIN_SEGMENTS);
pr_warn(MPT3SAS_FMT
"sg_tablesize(%u) is bigger than kernel"
" defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name,
- sg_tablesize, MPT3SAS_MAX_PHYS_SEGMENTS);
+ sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
}
ioc->shost->sg_tablesize = sg_tablesize;
@@ -4021,7 +4337,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
mpi_request.VF_ID = 0; /* TODO */
mpi_request.VP_ID = 0;
- mpi_request.MsgVersion = cpu_to_le16(MPI25_VERSION);
+ mpi_request.MsgVersion = cpu_to_le16(ioc->hba_mpi_version_belonged);
mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
if (_base_is_controller_msix_enabled(ioc))
@@ -4655,6 +4971,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
u32 reply_address;
u16 smid;
struct _tr_list *delayed_tr, *delayed_tr_next;
+ u8 hide_flag;
struct adapter_reply_queue *reply_q;
long reply_post_free;
u32 reply_post_free_sz, index = 0;
@@ -4685,6 +5002,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].smid = smid;
ioc->scsi_lookup[i].scmd = NULL;
+ ioc->scsi_lookup[i].direct_io = 0;
list_add_tail(&ioc->scsi_lookup[i].tracker_list,
&ioc->free_list);
}
@@ -4787,6 +5105,16 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
if (ioc->is_driver_loading) {
+
+ if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
+ == 0x80) {
+ hide_flag = (u8) (
+ le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) &
+ MFG_PAGE10_HIDE_SSDS_MASK);
+ if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
+ ioc->mfg_pg10_hide_flag = hide_flag;
+ }
+
ioc->wait_for_discovery_to_complete =
_base_determine_wait_on_discovery(ioc);
@@ -4812,6 +5140,8 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
+ /* synchronizing freeing resource with pci_access_mutex lock */
+ mutex_lock(&ioc->pci_access_mutex);
if (ioc->chip_phys && ioc->chip) {
_base_mask_interrupts(ioc);
ioc->shost_recovery = 1;
@@ -4820,6 +5150,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
}
mpt3sas_base_unmap_resources(ioc);
+ mutex_unlock(&ioc->pci_access_mutex);
return;
}
@@ -4834,7 +5165,6 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
{
int r, i;
int cpu_id, last_cpu_id = 0;
- u8 revision;
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -4854,19 +5184,16 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
goto out_free_resources;
}
- /* Check whether the controller revision is C0 or above.
- * only C0 and above revision controllers support 96 MSI-X vectors.
- */
- revision = ioc->pdev->revision;
-
- if ((ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3004 ||
- ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3008 ||
- ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_1 ||
- ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_2 ||
- ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_5 ||
- ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_6) &&
- (revision >= 0x02))
- ioc->msix96_vector = 1;
+ if (ioc->is_warpdrive) {
+ ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
+ sizeof(resource_size_t *), GFP_KERNEL);
+ if (!ioc->reply_post_host_index) {
+ dfailprintk(ioc, pr_info(MPT3SAS_FMT "allocation "
+ "for cpu_msix_table failed!!!\n", ioc->name));
+ r = -ENOMEM;
+ goto out_free_resources;
+ }
+ }
ioc->rdpq_array_enable_assigned = 0;
ioc->dma_mask = 0;
@@ -4874,23 +5201,41 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
if (r)
goto out_free_resources;
+ if (ioc->is_warpdrive) {
+ ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
+ &ioc->chip->ReplyPostHostIndex;
+
+ for (i = 1; i < ioc->cpu_msix_table_sz; i++)
+ ioc->reply_post_host_index[i] =
+ (resource_size_t __iomem *)
+ ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+ * 4)));
+ }
pci_set_drvdata(ioc->pdev, ioc->shost);
r = _base_get_ioc_facts(ioc, CAN_SLEEP);
if (r)
goto out_free_resources;
- /*
- * In SAS3.0,
- * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and
- * Target Status - all require the IEEE formated scatter gather
- * elements.
- */
-
- ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
- ioc->build_sg = &_base_build_sg_ieee;
- ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
- ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
+ switch (ioc->hba_mpi_version_belonged) {
+ case MPI2_VERSION:
+ ioc->build_sg_scmd = &_base_build_sg_scmd;
+ ioc->build_sg = &_base_build_sg;
+ ioc->build_zero_len_sge = &_base_build_zero_len_sge;
+ break;
+ case MPI25_VERSION:
+ /*
+ * In SAS3.0,
+ * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and
+ * Target Status - all require the IEEE formated scatter gather
+ * elements.
+ */
+ ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
+ ioc->build_sg = &_base_build_sg_ieee;
+ ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
+ ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
+ break;
+ }
/*
* These function pointers for other requests that don't
@@ -5006,6 +5351,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
if (r)
goto out_free_resources;
+ ioc->non_operational_loop = 0;
return 0;
out_free_resources:
@@ -5016,6 +5362,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
_base_release_memory_pools(ioc);
pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->cpu_msix_table);
+ if (ioc->is_warpdrive)
+ kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
kfree(ioc->blocking_handles);
kfree(ioc->tm_cmds.reply);
@@ -5055,6 +5403,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
_base_release_memory_pools(ioc);
pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->cpu_msix_table);
+ if (ioc->is_warpdrive)
+ kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
kfree(ioc->blocking_handles);
kfree(ioc->pfacts);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index f0e462b0880d..5ad271efbd45 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -63,6 +63,8 @@
#include <scsi/scsi_transport_sas.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_eh.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
#include "mpt3sas_debug.h"
#include "mpt3sas_trigger_diag.h"
@@ -71,23 +73,37 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "09.100.00.00"
+#define MPT3SAS_DRIVER_VERSION "09.102.00.00"
#define MPT3SAS_MAJOR_VERSION 9
-#define MPT3SAS_MINOR_VERSION 100
+#define MPT3SAS_MINOR_VERSION 102
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
+#define MPT2SAS_DRIVER_NAME "mpt2sas"
+#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
+#define MPT2SAS_DRIVER_VERSION "20.102.00.00"
+#define MPT2SAS_MAJOR_VERSION 20
+#define MPT2SAS_MINOR_VERSION 102
+#define MPT2SAS_BUILD_VERSION 0
+#define MPT2SAS_RELEASE_VERSION 00
+
/*
* Set MPT3SAS_SG_DEPTH value based on user input.
*/
-#define MPT3SAS_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS
-#define MPT3SAS_MIN_PHYS_SEGMENTS 16
+#define MPT_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS
+#define MPT_MIN_PHYS_SEGMENTS 16
+
#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE
#define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE
#else
-#define MPT3SAS_SG_DEPTH MPT3SAS_MAX_PHYS_SEGMENTS
+#define MPT3SAS_SG_DEPTH MPT_MAX_PHYS_SEGMENTS
#endif
+#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE
+#define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE
+#else
+#define MPT2SAS_SG_DEPTH MPT_MAX_PHYS_SEGMENTS
+#endif
/*
* Generic Defines
@@ -124,6 +140,16 @@
#define MPT3SAS_FMT "%s: "
/*
+ * WarpDrive Specific Log codes
+ */
+
+#define MPT2_WARPDRIVE_LOGENTRY (0x8002)
+#define MPT2_WARPDRIVE_LC_SSDT (0x41)
+#define MPT2_WARPDRIVE_LC_SSDLW (0x43)
+#define MPT2_WARPDRIVE_LC_SSDLF (0x44)
+#define MPT2_WARPDRIVE_LC_BRMF (0x4D)
+
+/*
* per target private data
*/
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01
@@ -131,9 +157,33 @@
#define MPT_TARGET_FLAGS_DELETED 0x04
#define MPT_TARGET_FASTPATH_IO 0x08
+#define SAS2_PCI_DEVICE_B0_REVISION (0x01)
+#define SAS3_PCI_DEVICE_C0_REVISION (0x02)
+
/*
* Intel HBA branding
*/
+#define MPT2SAS_INTEL_RMS25JB080_BRANDING \
+ "Intel(R) Integrated RAID Module RMS25JB080"
+#define MPT2SAS_INTEL_RMS25JB040_BRANDING \
+ "Intel(R) Integrated RAID Module RMS25JB040"
+#define MPT2SAS_INTEL_RMS25KB080_BRANDING \
+ "Intel(R) Integrated RAID Module RMS25KB080"
+#define MPT2SAS_INTEL_RMS25KB040_BRANDING \
+ "Intel(R) Integrated RAID Module RMS25KB040"
+#define MPT2SAS_INTEL_RMS25LB040_BRANDING \
+ "Intel(R) Integrated RAID Module RMS25LB040"
+#define MPT2SAS_INTEL_RMS25LB080_BRANDING \
+ "Intel(R) Integrated RAID Module RMS25LB080"
+#define MPT2SAS_INTEL_RMS2LL080_BRANDING \
+ "Intel Integrated RAID Module RMS2LL080"
+#define MPT2SAS_INTEL_RMS2LL040_BRANDING \
+ "Intel Integrated RAID Module RMS2LL040"
+#define MPT2SAS_INTEL_RS25GB008_BRANDING \
+ "Intel(R) RAID Controller RS25GB008"
+#define MPT2SAS_INTEL_SSD910_BRANDING \
+ "Intel(R) SSD 910 Series"
+
#define MPT3SAS_INTEL_RMS3JC080_BRANDING \
"Intel(R) Integrated RAID Module RMS3JC080"
#define MPT3SAS_INTEL_RS3GC008_BRANDING \
@@ -146,33 +196,62 @@
/*
* Intel HBA SSDIDs
*/
-#define MPT3SAS_INTEL_RMS3JC080_SSDID 0x3521
-#define MPT3SAS_INTEL_RS3GC008_SSDID 0x3522
-#define MPT3SAS_INTEL_RS3FC044_SSDID 0x3523
-#define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524
+#define MPT2SAS_INTEL_RMS25JB080_SSDID 0x3516
+#define MPT2SAS_INTEL_RMS25JB040_SSDID 0x3517
+#define MPT2SAS_INTEL_RMS25KB080_SSDID 0x3518
+#define MPT2SAS_INTEL_RMS25KB040_SSDID 0x3519
+#define MPT2SAS_INTEL_RMS25LB040_SSDID 0x351A
+#define MPT2SAS_INTEL_RMS25LB080_SSDID 0x351B
+#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E
+#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F
+#define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000
+#define MPT2SAS_INTEL_SSD910_SSDID 0x3700
+
+#define MPT3SAS_INTEL_RMS3JC080_SSDID 0x3521
+#define MPT3SAS_INTEL_RS3GC008_SSDID 0x3522
+#define MPT3SAS_INTEL_RS3FC044_SSDID 0x3523
+#define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524
/*
* Dell HBA branding
*/
+#define MPT2SAS_DELL_BRANDING_SIZE 32
+
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA"
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter"
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated"
+#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular"
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded"
+#define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200"
+#define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS"
+
#define MPT3SAS_DELL_12G_HBA_BRANDING \
"Dell 12Gbps HBA"
/*
* Dell HBA SSDIDs
*/
-#define MPT3SAS_DELL_12G_HBA_SSDID 0x1F46
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E
+#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20
+#define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21
+#define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22
+
+#define MPT3SAS_DELL_12G_HBA_SSDID 0x1F46
/*
* Cisco HBA branding
*/
#define MPT3SAS_CISCO_12G_8E_HBA_BRANDING \
- "Cisco 9300-8E 12G SAS HBA"
+ "Cisco 9300-8E 12G SAS HBA"
#define MPT3SAS_CISCO_12G_8I_HBA_BRANDING \
- "Cisco 9300-8i 12G SAS HBA"
+ "Cisco 9300-8i 12G SAS HBA"
#define MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING \
- "Cisco 12G Modular SAS Pass through Controller"
+ "Cisco 12G Modular SAS Pass through Controller"
#define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING \
- "UCS C3X60 12G SAS Pass through Controller"
+ "UCS C3X60 12G SAS Pass through Controller"
/*
* Cisco HBA SSSDIDs
*/
@@ -189,6 +268,31 @@
#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04)
/*
+ * HP HBA branding
+ */
+#define MPT2SAS_HP_3PAR_SSVID 0x1590
+
+#define MPT2SAS_HP_2_4_INTERNAL_BRANDING \
+ "HP H220 Host Bus Adapter"
+#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING \
+ "HP H221 Host Bus Adapter"
+#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING \
+ "HP H222 Host Bus Adapter"
+#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING \
+ "HP H220i Host Bus Adapter"
+#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING \
+ "HP H210i Host Bus Adapter"
+
+/*
+ * HO HBA SSDIDs
+ */
+#define MPT2SAS_HP_2_4_INTERNAL_SSDID 0x0041
+#define MPT2SAS_HP_2_4_EXTERNAL_SSDID 0x0042
+#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID 0x0043
+#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044
+#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046
+
+/*
* Combined Reply Queue constants,
* There are twelve Supplemental Reply Post Host Index Registers
* and each register is at offset 0x10 bytes from the previous one.
@@ -243,20 +347,24 @@ struct Mpi2ManufacturingPage11_t {
* struct MPT3SAS_TARGET - starget private hostdata
* @starget: starget object
* @sas_address: target sas address
+ * @raid_device: raid_device pointer to access volume data
* @handle: device handle
* @num_luns: number luns
* @flags: MPT_TARGET_FLAGS_XXX flags
* @deleted: target flaged for deletion
* @tm_busy: target is busy with TM request.
+ * @sdev: The sas_device associated with this target
*/
struct MPT3SAS_TARGET {
struct scsi_target *starget;
u64 sas_address;
+ struct _raid_device *raid_device;
u16 handle;
int num_luns;
u32 flags;
u8 deleted;
u8 tm_busy;
+ struct _sas_device *sdev;
};
@@ -266,6 +374,11 @@ struct MPT3SAS_TARGET {
#define MPT_DEVICE_FLAGS_INIT 0x01
#define MPT_DEVICE_TLR_ON 0x02
+#define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003)
+#define MFG_PAGE10_HIDE_ALL_DISKS (0x00)
+#define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01)
+#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02)
+
/**
* struct MPT3SAS_DEVICE - sdev private hostdata
* @sas_target: starget private hostdata
@@ -358,8 +471,24 @@ struct _sas_device {
u8 pend_sas_rphy_add;
u8 enclosure_level;
u8 connector_name[4];
+ struct kref refcount;
};
+static inline void sas_device_get(struct _sas_device *s)
+{
+ kref_get(&s->refcount);
+}
+
+static inline void sas_device_free(struct kref *r)
+{
+ kfree(container_of(r, struct _sas_device, refcount));
+}
+
+static inline void sas_device_put(struct _sas_device *s)
+{
+ kref_put(&s->refcount, sas_device_free);
+}
+
/**
* struct _raid_device - raid volume link list
* @list: sas device list
@@ -367,6 +496,7 @@ struct _sas_device {
* @sdev: scsi device struct (volumes are single lun)
* @wwid: unique identifier for the volume
* @handle: device handle
+ * @block_size: Block size of the volume
* @id: target id
* @channel: target channel
* @volume_type: the raid level
@@ -374,6 +504,13 @@ struct _sas_device {
* @num_pds: number of hidden raid components
* @responding: used in _scsih_raid_device_mark_responding
* @percent_complete: resync percent complete
+ * @direct_io_enabled: Whether direct io to PDs are allowed or not
+ * @stripe_exponent: X where 2powX is the stripe sz in blocks
+ * @block_exponent: X where 2powX is the block sz in bytes
+ * @max_lba: Maximum number of LBA in the volume
+ * @stripe_sz: Stripe Size of the volume
+ * @device_info: Device info of the volume member disk
+ * @pd_handle: Array of handles of the physical drives for direct I/O in le16
*/
#define MPT_MAX_WARPDRIVE_PDS 8
struct _raid_device {
@@ -382,13 +519,20 @@ struct _raid_device {
struct scsi_device *sdev;
u64 wwid;
u16 handle;
+ u16 block_sz;
int id;
int channel;
u8 volume_type;
u8 num_pds;
u8 responding;
u8 percent_complete;
+ u8 direct_io_enabled;
+ u8 stripe_exponent;
+ u8 block_exponent;
+ u64 max_lba;
+ u32 stripe_sz;
u32 device_info;
+ u16 pd_handle[MPT_MAX_WARPDRIVE_PDS];
};
/**
@@ -497,12 +641,14 @@ struct chain_tracker {
* @smid: system message id
* @scmd: scsi request pointer
* @cb_idx: callback index
+ * @direct_io: To indicate whether I/O is direct (WARPDRIVE)
* @tracker_list: list of free request (ioc->free_list)
*/
struct scsiio_tracker {
u16 smid;
struct scsi_cmnd *scmd;
u8 cb_idx;
+ u8 direct_io;
struct list_head chain_list;
struct list_head tracker_list;
};
@@ -775,7 +921,13 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @replyPostRegisterIndex: index of next position in Reply Desc Post Queue
* @delayed_tr_list: target reset link list
* @delayed_tr_volume_list: volume target reset link list
- * @@temp_sensors_count: flag to carry the number of temperature sensors
+ * @temp_sensors_count: flag to carry the number of temperature sensors
+ * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and
+ * pci resource handling. PCI resource freeing will lead to free
+ * vital hardware/memory resource, which might be in use by cli/sysfs
+ * path functions resulting in Null pointer reference followed by kernel
+ * crash. To avoid the above race condition we use mutex syncrhonization
+ * which ensures the syncrhonization between cli/sysfs_show path.
*/
struct MPT3SAS_ADAPTER {
struct list_head list;
@@ -783,6 +935,7 @@ struct MPT3SAS_ADAPTER {
u8 id;
int cpu_count;
char name[MPT_NAME_LENGTH];
+ char driver_name[MPT_NAME_LENGTH];
char tmp_string[MPT_STRING_LENGTH];
struct pci_dev *pdev;
Mpi2SystemInterfaceRegs_t __iomem *chip;
@@ -829,8 +982,10 @@ struct MPT3SAS_ADAPTER {
u16 msix_vector_count;
u8 *cpu_msix_table;
u16 cpu_msix_table_sz;
+ resource_size_t __iomem **reply_post_host_index;
u32 ioc_reset_count;
MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
+ u32 non_operational_loop;
/* internal commands, callback index */
u8 scsi_io_cb_idx;
@@ -859,6 +1014,7 @@ struct MPT3SAS_ADAPTER {
MPT_BUILD_SG build_sg;
MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge;
u16 sge_size_ieee;
+ u16 hba_mpi_version_belonged;
/* function ptr for MPI sg elements only */
MPT_BUILD_SG build_sg_mpi;
@@ -987,6 +1143,7 @@ struct MPT3SAS_ADAPTER {
struct list_head delayed_tr_list;
struct list_head delayed_tr_volume_list;
u8 temp_sensors_count;
+ struct mutex pci_access_mutex;
/* diag buffer support */
u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
@@ -998,6 +1155,10 @@ struct MPT3SAS_ADAPTER {
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
u32 ring_buffer_offset;
u32 ring_buffer_sz;
+ u8 is_warpdrive;
+ u8 hide_ir_msg;
+ u8 mfg_pg10_hide_flag;
+ u8 hide_drives;
spinlock_t diag_trigger_lock;
u8 diag_trigger_active;
struct SL_WH_MASTER_TRIGGER_T diag_trigger_master;
@@ -1012,6 +1173,19 @@ typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
/* base shared API */
extern struct list_head mpt3sas_ioc_list;
+extern char driver_name[MPT_NAME_LENGTH];
+/* spinlock on list operations over IOCs
+ * Case: when multiple warpdrive cards(IOCs) are in use
+ * Each IOC will added to the ioc list structure on initialization.
+ * Watchdog threads run at regular intervals to check IOC for any
+ * fault conditions which will trigger the dead_ioc thread to
+ * deallocate pci resource, resulting deleting the IOC netry from list,
+ * this deletion need to protected by spinlock to enusre that
+ * ioc removal is syncrhonized, if not synchronized it might lead to
+ * list_del corruption as the ioc list is traversed in cli path.
+ */
+extern spinlock_t gioc_lock;
+
void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc);
@@ -1090,10 +1264,14 @@ struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
struct MPT3SAS_ADAPTER *ioc, u16 handle);
struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address(
struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
-struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address(
- struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+struct _sas_device *mpt3sas_get_sdev_by_addr(
+ struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+struct _sas_device *__mpt3sas_get_sdev_by_addr(
+ struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
+struct _raid_device *
+mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle);
/* config shared API */
u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
@@ -1133,6 +1311,8 @@ int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
u16 sz);
int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
*mpi_reply, Mpi2IOUnitPage1_t *config_page);
+int mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz);
int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
*mpi_reply, Mpi2IOUnitPage1_t *config_page);
int mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
@@ -1177,8 +1357,8 @@ int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc,
/* ctl shared API */
extern struct device_attribute *mpt3sas_host_attrs[];
extern struct device_attribute *mpt3sas_dev_attrs[];
-void mpt3sas_ctl_init(void);
-void mpt3sas_ctl_exit(void);
+void mpt3sas_ctl_init(ushort hbas_to_enumerate);
+void mpt3sas_ctl_exit(ushort hbas_to_enumerate);
u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
@@ -1193,6 +1373,7 @@ int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
u8 *issue_reset);
/* transport shared API */
+extern struct scsi_transport_template *mpt3sas_transport_template;
u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc,
@@ -1224,4 +1405,18 @@ void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key,
u8 asc, u8 ascq);
void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status,
u32 loginfo);
+
+/* warpdrive APIs */
+u8 mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
+ struct _raid_device *raid_device);
+u8
+mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void
+mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io);
+void
+mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+ struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
+ u16 smid);
+
#endif /* MPT3SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
index e45c4613ef0c..a6914ec99cc0 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -83,7 +83,6 @@ struct config_request {
dma_addr_t page_dma;
};
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _config_display_some_debug - debug routine
* @ioc: per adapter object
@@ -173,7 +172,6 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo));
}
-#endif
/**
* _config_alloc_config_dma_memory - obtain physical memory
@@ -255,9 +253,7 @@ mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
mpi_reply->MsgLength*4);
}
ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
-#endif
ioc->config_cmds.smid = USHRT_MAX;
complete(&ioc->config_cmds.done);
return 1;
@@ -387,9 +383,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
config_request = mpt3sas_base_get_msg_frame(ioc, smid);
ioc->config_cmds.smid = smid;
memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
_config_display_some_debug(ioc, smid, "config_request", NULL);
-#endif
init_completion(&ioc->config_cmds.done);
mpt3sas_base_put_smid_default(ioc, smid);
timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
@@ -872,6 +866,42 @@ mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
}
/**
+ * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+ mpi_request.Header.PageNumber = 3;
+ mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
+ ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+ out:
+ return r;
+}
+
+/**
* mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 080c8a76d23d..d8366b056b70 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -78,7 +78,6 @@ enum block_state {
BLOCKING,
};
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _ctl_sas_device_find_by_handle - sas device search
* @ioc: per adapter object
@@ -254,8 +253,6 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
}
}
-#endif
-
/**
* mpt3sas_ctl_done - ctl module completion routine
* @ioc: per adapter object
@@ -302,9 +299,7 @@ mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
}
}
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
_ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
-#endif
ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING;
complete(&ioc->ctl_cmds.done);
return 1;
@@ -414,20 +409,31 @@ mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
* _ctl_verify_adapter - validates ioc_number passed from application
* @ioc: per adapter object
* @iocpp: The ioc pointer is returned in this.
+ * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
+ * MPI25_VERSION for mpt3ctl ioctl device.
*
* Return (-1) means error, else ioc_number.
*/
static int
-_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp)
+_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp,
+ int mpi_version)
{
struct MPT3SAS_ADAPTER *ioc;
-
+ /* global ioc lock to protect controller on list operations */
+ spin_lock(&gioc_lock);
list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
if (ioc->id != ioc_number)
continue;
+ /* Check whether this ioctl command is from right
+ * ioctl device or not, if not continue the search.
+ */
+ if (ioc->hba_mpi_version_belonged != mpi_version)
+ continue;
+ spin_unlock(&gioc_lock);
*iocpp = ioc;
return ioc_number;
}
+ spin_unlock(&gioc_lock);
*iocpp = NULL;
return -1;
}
@@ -497,7 +503,7 @@ mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
*
* Called when application request fasyn callback handler.
*/
-static int
+int
_ctl_fasync(int fd, struct file *filep, int mode)
{
return fasync_helper(fd, filep, mode, &async_queue);
@@ -509,17 +515,22 @@ _ctl_fasync(int fd, struct file *filep, int mode)
* @wait -
*
*/
-static unsigned int
+unsigned int
_ctl_poll(struct file *filep, poll_table *wait)
{
struct MPT3SAS_ADAPTER *ioc;
poll_wait(filep, &ctl_poll_wait, wait);
+ /* global ioc lock to protect controller on list operations */
+ spin_lock(&gioc_lock);
list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
- if (ioc->aen_event_read_flag)
+ if (ioc->aen_event_read_flag) {
+ spin_unlock(&gioc_lock);
return POLLIN | POLLRDNORM;
+ }
}
+ spin_unlock(&gioc_lock);
return 0;
}
@@ -759,9 +770,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
psge = (void *)request + (karg.data_sge_offset*4);
/* send command to firmware */
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
_ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
-#endif
init_completion(&ioc->ctl_cmds.done);
switch (mpi_request->Function) {
@@ -916,7 +925,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
mpi_reply = ioc->ctl_cmds.reply;
ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
(ioc->logging_level & MPT_DEBUG_TM)) {
Mpi2SCSITaskManagementReply_t *tm_reply =
@@ -929,7 +937,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
le32_to_cpu(tm_reply->IOCLogInfo),
le32_to_cpu(tm_reply->TerminationCount));
}
-#endif
+
/* copy out xdata to user */
if (data_in_sz) {
if (copy_to_user(karg.data_in_buf_ptr, data_in,
@@ -1023,7 +1031,6 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
__func__));
memset(&karg, 0 , sizeof(karg));
- karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
if (ioc->pfacts)
karg.port_number = ioc->pfacts[0].PortNumber;
karg.hw_rev = ioc->pdev->revision;
@@ -1035,9 +1042,21 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
karg.firmware_version = ioc->facts.FWVersion.Word;
- strcpy(karg.driver_version, MPT3SAS_DRIVER_NAME);
+ strcpy(karg.driver_version, ioc->driver_name);
strcat(karg.driver_version, "-");
- strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
+ switch (ioc->hba_mpi_version_belonged) {
+ case MPI2_VERSION:
+ if (ioc->is_warpdrive)
+ karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200;
+ else
+ karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
+ strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
+ break;
+ case MPI25_VERSION:
+ karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
+ strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
+ break;
+ }
karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
if (copy_to_user(arg, &karg, sizeof(karg))) {
@@ -2181,12 +2200,14 @@ _ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
* _ctl_ioctl_main - main ioctl entry point
* @file - (struct file)
* @cmd - ioctl opcode
- * @arg -
- * compat - handles 32 bit applications in 64bit os
+ * @arg - user space data buffer
+ * @compat - handles 32 bit applications in 64bit os
+ * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
+ * MPI25_VERSION for mpt3ctl ioctl device.
*/
static long
_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
- u8 compat)
+ u8 compat, u16 mpi_version)
{
struct MPT3SAS_ADAPTER *ioc;
struct mpt3_ioctl_header ioctl_header;
@@ -2201,19 +2222,29 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
return -EFAULT;
}
- if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
+ if (_ctl_verify_adapter(ioctl_header.ioc_number,
+ &ioc, mpi_version) == -1 || !ioc)
return -ENODEV;
+ /* pci_access_mutex lock acquired by ioctl path */
+ mutex_lock(&ioc->pci_access_mutex);
+
if (ioc->shost_recovery || ioc->pci_error_recovery ||
- ioc->is_driver_loading)
- return -EAGAIN;
+ ioc->is_driver_loading || ioc->remove_host) {
+ ret = -EAGAIN;
+ goto out_unlock_pciaccess;
+ }
state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
if (state == NON_BLOCKING) {
- if (!mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
+ if (!mutex_trylock(&ioc->ctl_cmds.mutex)) {
+ ret = -EAGAIN;
+ goto out_unlock_pciaccess;
+ }
+ } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
+ ret = -ERESTARTSYS;
+ goto out_unlock_pciaccess;
+ }
switch (cmd) {
@@ -2294,39 +2325,78 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
}
mutex_unlock(&ioc->ctl_cmds.mutex);
+out_unlock_pciaccess:
+ mutex_unlock(&ioc->pci_access_mutex);
return ret;
}
/**
- * _ctl_ioctl - main ioctl entry point (unlocked)
+ * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked)
* @file - (struct file)
* @cmd - ioctl opcode
* @arg -
*/
-static long
+long
_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
+ /* pass MPI25_VERSION value, to indicate that this ioctl cmd
+ * came from mpt3ctl ioctl device.
+ */
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI25_VERSION);
return ret;
}
+/**
+ * _ctl_mpt2_ioctl - mpt2ctl main ioctl entry point (unlocked)
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg -
+ */
+long
+_ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+
+ /* pass MPI2_VERSION value, to indicate that this ioctl cmd
+ * came from mpt2ctl ioctl device.
+ */
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI2_VERSION);
+ return ret;
+}
#ifdef CONFIG_COMPAT
/**
- * _ctl_ioctl_compat - main ioctl entry point (compat)
+ *_ ctl_ioctl_compat - main ioctl entry point (compat)
* @file -
* @cmd -
* @arg -
*
* This routine handles 32 bit applications in 64bit os.
*/
-static long
+long
_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
{
long ret;
- ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI25_VERSION);
+ return ret;
+}
+
+/**
+ *_ ctl_mpt2_ioctl_compat - main ioctl entry point (compat)
+ * @file -
+ * @cmd -
+ * @arg -
+ *
+ * This routine handles 32 bit applications in 64bit os.
+ */
+long
+_ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
+{
+ long ret;
+
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI2_VERSION);
return ret;
}
#endif
@@ -2713,6 +2783,82 @@ _ctl_ioc_reply_queue_count_show(struct device *cdev,
static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show,
NULL);
+/**
+ * _ctl_BRM_status_show - Backup Rail Monitor Status
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is number of reply queues
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 backup_rail_monitor_status = 0;
+ u16 ioc_status;
+ int sz;
+ ssize_t rc = 0;
+
+ if (!ioc->is_warpdrive) {
+ pr_err(MPT3SAS_FMT "%s: BRM attribute is only for"
+ " warpdrive\n", ioc->name, __func__);
+ goto out;
+ }
+ /* pci_access_mutex lock acquired by sysfs show path */
+ mutex_lock(&ioc->pci_access_mutex);
+ if (ioc->pci_error_recovery || ioc->remove_host) {
+ mutex_unlock(&ioc->pci_access_mutex);
+ return 0;
+ }
+
+ /* allocate upto GPIOVal 36 entries */
+ sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
+ io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
+ if (!io_unit_pg3) {
+ pr_err(MPT3SAS_FMT "%s: failed allocating memory "
+ "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz);
+ goto out;
+ }
+
+ if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
+ 0) {
+ pr_err(MPT3SAS_FMT
+ "%s: failed reading iounit_pg3\n", ioc->name,
+ __func__);
+ goto out;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ pr_err(MPT3SAS_FMT "%s: iounit_pg3 failed with "
+ "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status);
+ goto out;
+ }
+
+ if (io_unit_pg3->GPIOCount < 25) {
+ pr_err(MPT3SAS_FMT "%s: iounit_pg3->GPIOCount less than "
+ "25 entries, detected (%d) entries\n", ioc->name, __func__,
+ io_unit_pg3->GPIOCount);
+ goto out;
+ }
+
+ /* BRM status is in bit zero of GPIOVal[24] */
+ backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
+ rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
+
+ out:
+ kfree(io_unit_pg3);
+ mutex_unlock(&ioc->pci_access_mutex);
+ return rc;
+}
+static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL);
+
struct DIAG_BUFFER_START {
__le32 Size;
__le32 DiagVersion;
@@ -3165,6 +3311,7 @@ struct device_attribute *mpt3sas_host_attrs[] = {
&dev_attr_diag_trigger_event,
&dev_attr_diag_trigger_scsi,
&dev_attr_diag_trigger_mpi,
+ &dev_attr_BRM_status,
NULL,
};
@@ -3218,6 +3365,7 @@ struct device_attribute *mpt3sas_dev_attrs[] = {
NULL,
};
+/* file operations table for mpt3ctl device */
static const struct file_operations ctl_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = _ctl_ioctl,
@@ -3228,23 +3376,53 @@ static const struct file_operations ctl_fops = {
#endif
};
+/* file operations table for mpt2ctl device */
+static const struct file_operations ctl_gen2_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = _ctl_mpt2_ioctl,
+ .poll = _ctl_poll,
+ .fasync = _ctl_fasync,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = _ctl_mpt2_ioctl_compat,
+#endif
+};
+
static struct miscdevice ctl_dev = {
.minor = MPT3SAS_MINOR,
.name = MPT3SAS_DEV_NAME,
.fops = &ctl_fops,
};
+static struct miscdevice gen2_ctl_dev = {
+ .minor = MPT2SAS_MINOR,
+ .name = MPT2SAS_DEV_NAME,
+ .fops = &ctl_gen2_fops,
+};
+
/**
* mpt3sas_ctl_init - main entry point for ctl.
*
*/
void
-mpt3sas_ctl_init(void)
+mpt3sas_ctl_init(ushort hbas_to_enumerate)
{
async_queue = NULL;
- if (misc_register(&ctl_dev) < 0)
- pr_err("%s can't register misc device [minor=%d]\n",
- MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
+
+ /* Don't register mpt3ctl ioctl device if
+ * hbas_to_enumarate is one.
+ */
+ if (hbas_to_enumerate != 1)
+ if (misc_register(&ctl_dev) < 0)
+ pr_err("%s can't register misc device [minor=%d]\n",
+ MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
+
+ /* Don't register mpt3ctl ioctl device if
+ * hbas_to_enumarate is two.
+ */
+ if (hbas_to_enumerate != 2)
+ if (misc_register(&gen2_ctl_dev) < 0)
+ pr_err("%s can't register misc device [minor=%d]\n",
+ MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
init_waitqueue_head(&ctl_poll_wait);
}
@@ -3254,7 +3432,7 @@ mpt3sas_ctl_init(void)
*
*/
void
-mpt3sas_ctl_exit(void)
+mpt3sas_ctl_exit(ushort hbas_to_enumerate)
{
struct MPT3SAS_ADAPTER *ioc;
int i;
@@ -3279,5 +3457,8 @@ mpt3sas_ctl_exit(void)
kfree(ioc->event_log);
}
- misc_deregister(&ctl_dev);
+ if (hbas_to_enumerate != 1)
+ misc_deregister(&ctl_dev);
+ if (hbas_to_enumerate != 2)
+ misc_deregister(&gen2_ctl_dev);
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
index aee99ce67e54..89408356d252 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
@@ -50,10 +50,13 @@
#include <linux/miscdevice.h>
#endif
-
+#ifndef MPT2SAS_MINOR
+#define MPT2SAS_MINOR (MPT_MINOR + 1)
+#endif
#ifndef MPT3SAS_MINOR
#define MPT3SAS_MINOR (MPT_MINOR + 2)
#endif
+#define MPT2SAS_DEV_NAME "mpt2ctl"
#define MPT3SAS_DEV_NAME "mpt3ctl"
#define MPT3_MAGIC_NUMBER 'L'
#define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
@@ -138,6 +141,7 @@ struct mpt3_ioctl_pci_info {
#define MPT2_IOCTL_INTERFACE_FC_IP (0x02)
#define MPT2_IOCTL_INTERFACE_SAS (0x03)
#define MPT2_IOCTL_INTERFACE_SAS2 (0x04)
+#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05)
#define MPT3_IOCTL_INTERFACE_SAS3 (0x06)
#define MPT2_IOCTL_VERSION_LENGTH (32)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_debug.h b/drivers/scsi/mpt3sas/mpt3sas_debug.h
index 4e8a63fdb304..cceeb2c16e64 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_debug.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_debug.h
@@ -68,20 +68,11 @@
#define MPT_DEBUG_TRIGGER_DIAG 0x00200000
-/*
- * CONFIG_SCSI_MPT3SAS_LOGGING - enabled in Kconfig
- */
-
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \
{ \
if (IOC->logging_level & BITS) \
CMD; \
}
-#else
-#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
-#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
-
/*
* debug macros
@@ -153,7 +144,7 @@
/* inline functions for dumping debug data*/
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+
/**
* _debug_dump_mf - print message frame contents
* @mpi_request: pointer to message frame
@@ -211,10 +202,5 @@ _debug_dump_config(void *mpi_request, int sz)
}
pr_info("\n");
}
-#else
-#define _debug_dump_mf(mpi_request, sz)
-#define _debug_dump_reply(mpi_request, sz)
-#define _debug_dump_config(mpi_request, sz)
-#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
#endif /* MPT3SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8ccef38523fa..d95206b7e116 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -54,14 +54,10 @@
#include <linux/interrupt.h>
#include <linux/aer.h>
#include <linux/raid_class.h>
+#include <asm/unaligned.h>
#include "mpt3sas_base.h"
-MODULE_AUTHOR(MPT3SAS_AUTHOR);
-MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
-
#define RAID_CHANNEL 1
/* forward proto's */
static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
@@ -75,11 +71,16 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
-static void _scsih_scan_start(struct Scsi_Host *shost);
-static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
-
/* global parameters */
LIST_HEAD(mpt3sas_ioc_list);
+/* global ioc lock for list operations */
+DEFINE_SPINLOCK(gioc_lock);
+
+MODULE_AUTHOR(MPT3SAS_AUTHOR);
+MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
+MODULE_ALIAS("mpt2sas");
/* local parameters */
static u8 scsi_io_cb_idx = -1;
@@ -90,7 +91,8 @@ static u8 port_enable_cb_idx = -1;
static u8 transport_cb_idx = -1;
static u8 scsih_cb_idx = -1;
static u8 config_cb_idx = -1;
-static int mpt_ids;
+static int mpt2_ids;
+static int mpt3_ids;
static u8 tm_tr_cb_idx = -1 ;
static u8 tm_tr_volume_cb_idx = -1 ;
@@ -117,8 +119,12 @@ static u64 max_lun = MPT3SAS_MAX_LUN;
module_param(max_lun, ullong, 0);
MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
-
-
+static ushort hbas_to_enumerate;
+module_param(hbas_to_enumerate, ushort, 0);
+MODULE_PARM_DESC(hbas_to_enumerate,
+ " 0 - enumerates both SAS 2.0 & SAS 3.0 generation HBAs\n \
+ 1 - enumerates only SAS 2.0 generation HBAs\n \
+ 2 - enumerates only SAS 3.0 generation HBAs (default=0)");
/* diag_buffer_enable is bitwise
* bit 0 set = TRACE
@@ -143,8 +149,8 @@ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
/* raid transport support */
-
-static struct raid_template *mpt3sas_raid_template;
+struct raid_template *mpt3sas_raid_template;
+struct raid_template *mpt2sas_raid_template;
/**
@@ -191,11 +197,36 @@ struct fw_event_work {
u8 VP_ID;
u8 ignore;
u16 event;
+ struct kref refcount;
char event_data[0] __aligned(4);
};
-/* raid transport support */
-static struct raid_template *mpt3sas_raid_template;
+static void fw_event_work_free(struct kref *r)
+{
+ kfree(container_of(r, struct fw_event_work, refcount));
+}
+
+static void fw_event_work_get(struct fw_event_work *fw_work)
+{
+ kref_get(&fw_work->refcount);
+}
+
+static void fw_event_work_put(struct fw_event_work *fw_work)
+{
+ kref_put(&fw_work->refcount, fw_event_work_free);
+}
+
+static struct fw_event_work *alloc_fw_event_work(int len)
+{
+ struct fw_event_work *fw_event;
+
+ fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC);
+ if (!fw_event)
+ return NULL;
+
+ kref_init(&fw_event->refcount);
+ return fw_event;
+}
/**
* struct _scsi_io_transfer - scsi io transfer
@@ -245,28 +276,6 @@ struct _scsi_io_transfer {
u32 transfer_length;
};
-/*
- * The pci device ids are defined in mpi/mpi2_cnfg.h.
- */
-static const struct pci_device_id scsih_pci_table[] = {
- /* Fury ~ 3004 and 3008 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
- PCI_ANY_ID, PCI_ANY_ID },
- /* Invader ~ 3108 */
- { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
- PCI_ANY_ID, PCI_ANY_ID },
- { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
- PCI_ANY_ID, PCI_ANY_ID },
- {0} /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, scsih_pci_table);
-
/**
* _scsih_set_debug_level - global setting of ioc->logging_level.
*
@@ -282,8 +291,10 @@ _scsih_set_debug_level(const char *val, struct kernel_param *kp)
return ret;
pr_info("setting logging_level(0x%08x)\n", logging_level);
+ spin_lock(&gioc_lock);
list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
ioc->logging_level = logging_level;
+ spin_unlock(&gioc_lock);
return 0;
}
module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
@@ -518,8 +529,61 @@ _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
}
}
+static struct _sas_device *
+__mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
+ struct MPT3SAS_TARGET *tgt_priv)
+{
+ struct _sas_device *ret;
+
+ assert_spin_locked(&ioc->sas_device_lock);
+
+ ret = tgt_priv->sdev;
+ if (ret)
+ sas_device_get(ret);
+
+ return ret;
+}
+
+static struct _sas_device *
+mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
+ struct MPT3SAS_TARGET *tgt_priv)
+{
+ struct _sas_device *ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ return ret;
+}
+
+
+struct _sas_device *
+__mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
+ u64 sas_address)
+{
+ struct _sas_device *sas_device;
+
+ assert_spin_locked(&ioc->sas_device_lock);
+
+ list_for_each_entry(sas_device, &ioc->sas_device_list, list)
+ if (sas_device->sas_address == sas_address)
+ goto found_device;
+
+ list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
+ if (sas_device->sas_address == sas_address)
+ goto found_device;
+
+ return NULL;
+
+found_device:
+ sas_device_get(sas_device);
+ return sas_device;
+}
+
/**
- * mpt3sas_scsih_sas_device_find_by_sas_address - sas device search
+ * mpt3sas_get_sdev_by_addr - sas device search
* @ioc: per adapter object
* @sas_address: sas address
* Context: Calling function should acquire ioc->sas_device_lock
@@ -528,24 +592,44 @@ _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
* object.
*/
struct _sas_device *
-mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
u64 sas_address)
{
struct _sas_device *sas_device;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
+ sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ return sas_device;
+}
+
+static struct _sas_device *
+__mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_device *sas_device;
+
+ assert_spin_locked(&ioc->sas_device_lock);
list_for_each_entry(sas_device, &ioc->sas_device_list, list)
- if (sas_device->sas_address == sas_address)
- return sas_device;
+ if (sas_device->handle == handle)
+ goto found_device;
list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
- if (sas_device->sas_address == sas_address)
- return sas_device;
+ if (sas_device->handle == handle)
+ goto found_device;
return NULL;
+
+found_device:
+ sas_device_get(sas_device);
+ return sas_device;
}
/**
- * _scsih_sas_device_find_by_handle - sas device search
+ * mpt3sas_get_sdev_by_handle - sas device search
* @ioc: per adapter object
* @handle: sas device handle (assigned by firmware)
* Context: Calling function should acquire ioc->sas_device_lock
@@ -554,19 +638,16 @@ mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
* object.
*/
static struct _sas_device *
-_scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _sas_device *sas_device;
+ unsigned long flags;
- list_for_each_entry(sas_device, &ioc->sas_device_list, list)
- if (sas_device->handle == handle)
- return sas_device;
-
- list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
- if (sas_device->handle == handle)
- return sas_device;
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return NULL;
+ return sas_device;
}
/**
@@ -575,7 +656,7 @@ _scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
* @sas_device: the sas_device object
* Context: This function will acquire ioc->sas_device_lock.
*
- * Removing object and freeing associated memory from the ioc->sas_device_list.
+ * If sas_device is on the list, remove it and decrement its reference count.
*/
static void
_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
@@ -602,9 +683,15 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
ioc->name, sas_device->enclosure_level,
sas_device->connector_name);
+ /*
+ * The lock serializes access to the list, but we still need to verify
+ * that nobody removed the entry while we were waiting on the lock.
+ */
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- list_del(&sas_device->list);
- kfree(sas_device);
+ if (!list_empty(&sas_device->list)) {
+ list_del_init(&sas_device->list);
+ sas_device_put(sas_device);
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
@@ -625,12 +712,16 @@ _scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
return;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- if (sas_device)
- list_del(&sas_device->list);
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
+ if (sas_device) {
+ list_del_init(&sas_device->list);
+ sas_device_put(sas_device);
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
+ if (sas_device) {
_scsih_remove_device(ioc, sas_device);
+ sas_device_put(sas_device);
+ }
}
/**
@@ -651,13 +742,16 @@ mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
return;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_address);
- if (sas_device)
- list_del(&sas_device->list);
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address);
+ if (sas_device) {
+ list_del_init(&sas_device->list);
+ sas_device_put(sas_device);
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
+ if (sas_device) {
_scsih_remove_device(ioc, sas_device);
+ sas_device_put(sas_device);
+ }
}
/**
@@ -692,6 +786,7 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
sas_device->enclosure_level, sas_device->connector_name));
spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device_get(sas_device);
list_add_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -745,6 +840,7 @@ _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
sas_device->connector_name));
spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device_get(sas_device);
list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
_scsih_determine_boot_device(ioc, sas_device, 0);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -778,7 +874,7 @@ _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
}
/**
- * _scsih_raid_device_find_by_handle - raid device search
+ * mpt3sas_raid_device_find_by_handle - raid device search
* @ioc: per adapter object
* @handle: sas device handle (assigned by firmware)
* Context: Calling function should acquire ioc->raid_device_lock
@@ -786,8 +882,8 @@ _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
* This searches for raid_device based on handle, then return raid_device
* object.
*/
-static struct _raid_device *
-_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+struct _raid_device *
+mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _raid_device *raid_device, *r;
@@ -1095,14 +1191,14 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
}
/**
- * _scsih_change_queue_depth - setting device queue depth
+ * scsih_change_queue_depth - setting device queue depth
* @sdev: scsi device struct
* @qdepth: requested queue depth
*
* Returns queue depth.
*/
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+int
+scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct Scsi_Host *shost = sdev->host;
int max_depth;
@@ -1123,12 +1219,15 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
goto not_sata;
if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
goto not_sata;
+
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_device_priv_data->sas_target->sas_address);
- if (sas_device && sas_device->device_info &
- MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
+ sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
+ if (sas_device) {
+ if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
+
+ sas_device_put(sas_device);
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
not_sata:
@@ -1141,14 +1240,14 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
}
/**
- * _scsih_target_alloc - target add routine
+ * scsih_target_alloc - target add routine
* @starget: scsi target struct
*
* Returns 0 if ok. Any other return is assumed to be an error and
* the device is ignored.
*/
-static int
-_scsih_target_alloc(struct scsi_target *starget)
+int
+scsih_target_alloc(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1176,7 +1275,9 @@ _scsih_target_alloc(struct scsi_target *starget)
sas_target_priv_data->handle = raid_device->handle;
sas_target_priv_data->sas_address = raid_device->wwid;
sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
- raid_device->starget = starget;
+ sas_target_priv_data->raid_device = raid_device;
+ if (ioc->is_warpdrive)
+ raid_device->starget = starget;
}
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
return 0;
@@ -1185,12 +1286,13 @@ _scsih_target_alloc(struct scsi_target *starget)
/* sas/sata devices */
spin_lock_irqsave(&ioc->sas_device_lock, flags);
rphy = dev_to_rphy(starget->dev.parent);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
rphy->identify.sas_address);
if (sas_device) {
sas_target_priv_data->handle = sas_device->handle;
sas_target_priv_data->sas_address = sas_device->sas_address;
+ sas_target_priv_data->sdev = sas_device;
sas_device->starget = starget;
sas_device->id = starget->id;
sas_device->channel = starget->channel;
@@ -1206,13 +1308,13 @@ _scsih_target_alloc(struct scsi_target *starget)
}
/**
- * _scsih_target_destroy - target destroy routine
+ * scsih_target_destroy - target destroy routine
* @starget: scsi target struct
*
* Returns nothing.
*/
-static void
-_scsih_target_destroy(struct scsi_target *starget)
+void
+scsih_target_destroy(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1240,13 +1342,21 @@ _scsih_target_destroy(struct scsi_target *starget)
spin_lock_irqsave(&ioc->sas_device_lock, flags);
rphy = dev_to_rphy(starget->dev.parent);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- rphy->identify.sas_address);
+ sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
if (sas_device && (sas_device->starget == starget) &&
(sas_device->id == starget->id) &&
(sas_device->channel == starget->channel))
sas_device->starget = NULL;
+ if (sas_device) {
+ /*
+ * Corresponding get() is in _scsih_target_alloc()
+ */
+ sas_target_priv_data->sdev = NULL;
+ sas_device_put(sas_device);
+
+ sas_device_put(sas_device);
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
out:
@@ -1255,14 +1365,14 @@ _scsih_target_destroy(struct scsi_target *starget)
}
/**
- * _scsih_slave_alloc - device add routine
+ * scsih_slave_alloc - device add routine
* @sdev: scsi device struct
*
* Returns 0 if ok. Any other return is assumed to be an error and
* the device is ignored.
*/
-static int
-_scsih_slave_alloc(struct scsi_device *sdev)
+int
+scsih_slave_alloc(struct scsi_device *sdev)
{
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
@@ -1302,14 +1412,18 @@ _scsih_slave_alloc(struct scsi_device *sdev)
if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
sas_target_priv_data->sas_address);
if (sas_device && (sas_device->starget == NULL)) {
sdev_printk(KERN_INFO, sdev,
"%s : sas_device->starget set to starget @ %d\n",
- __func__, __LINE__);
+ __func__, __LINE__);
sas_device->starget = starget;
}
+
+ if (sas_device)
+ sas_device_put(sas_device);
+
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
@@ -1317,13 +1431,13 @@ _scsih_slave_alloc(struct scsi_device *sdev)
}
/**
- * _scsih_slave_destroy - device destroy routine
+ * scsih_slave_destroy - device destroy routine
* @sdev: scsi device struct
*
* Returns nothing.
*/
-static void
-_scsih_slave_destroy(struct scsi_device *sdev)
+void
+scsih_slave_destroy(struct scsi_device *sdev)
{
struct MPT3SAS_TARGET *sas_target_priv_data;
struct scsi_target *starget;
@@ -1344,10 +1458,13 @@ _scsih_slave_destroy(struct scsi_device *sdev)
if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_target_priv_data->sas_address);
+ sas_device = __mpt3sas_get_sdev_from_target(ioc,
+ sas_target_priv_data);
if (sas_device && !sas_target_priv_data->num_luns)
sas_device->starget = NULL;
+
+ if (sas_device)
+ sas_device_put(sas_device);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
@@ -1409,23 +1526,26 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
*/
/**
- * _scsih_is_raid - return boolean indicating device is raid volume
+ * scsih_is_raid - return boolean indicating device is raid volume
* @dev the device struct object
*/
-static int
-_scsih_is_raid(struct device *dev)
+int
+scsih_is_raid(struct device *dev)
{
struct scsi_device *sdev = to_scsi_device(dev);
+ struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
+ if (ioc->is_warpdrive)
+ return 0;
return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
}
/**
- * _scsih_get_resync - get raid volume resync percent complete
+ * scsih_get_resync - get raid volume resync percent complete
* @dev the device struct object
*/
-static void
-_scsih_get_resync(struct device *dev)
+void
+scsih_get_resync(struct device *dev)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
@@ -1439,6 +1559,9 @@ _scsih_get_resync(struct device *dev)
percent_complete = 0;
handle = 0;
+ if (ioc->is_warpdrive)
+ goto out;
+
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
sdev->channel);
@@ -1466,15 +1589,18 @@ _scsih_get_resync(struct device *dev)
percent_complete = 0;
out:
- raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
+ if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+ raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
+ if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
+ raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
}
/**
- * _scsih_get_state - get raid volume level
+ * scsih_get_state - get raid volume level
* @dev the device struct object
*/
-static void
-_scsih_get_state(struct device *dev)
+void
+scsih_get_state(struct device *dev)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
@@ -1524,7 +1650,10 @@ _scsih_get_state(struct device *dev)
break;
}
out:
- raid_set_state(mpt3sas_raid_template, dev, state);
+ if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+ raid_set_state(mpt2sas_raid_template, dev, state);
+ if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
+ raid_set_state(mpt3sas_raid_template, dev, state);
}
/**
@@ -1533,7 +1662,8 @@ _scsih_get_state(struct device *dev)
* @volume_type: volume type
*/
static void
-_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
+_scsih_set_level(struct MPT3SAS_ADAPTER *ioc,
+ struct scsi_device *sdev, u8 volume_type)
{
enum raid_level level = RAID_LEVEL_UNKNOWN;
@@ -1552,7 +1682,12 @@ _scsih_set_level(struct scsi_device *sdev, u8 volume_type)
break;
}
- raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level);
+ if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+ raid_set_level(mpt2sas_raid_template,
+ &sdev->sdev_gendev, level);
+ if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
+ raid_set_level(mpt3sas_raid_template,
+ &sdev->sdev_gendev, level);
}
@@ -1622,8 +1757,6 @@ _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
return 0;
}
-
-
/**
* _scsih_enable_tlr - setting TLR flags
* @ioc: per adapter object
@@ -1652,14 +1785,14 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
}
/**
- * _scsih_slave_configure - device configure routine.
+ * scsih_slave_configure - device configure routine.
* @sdev: scsi device struct
*
* Returns 0 if ok. Any other return is assumed to be an error and
* the device is ignored.
*/
-static int
-_scsih_slave_configure(struct scsi_device *sdev)
+int
+scsih_slave_configure(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1686,7 +1819,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device) {
dfailprintk(ioc, pr_warn(MPT3SAS_FMT
@@ -1702,6 +1835,10 @@ _scsih_slave_configure(struct scsi_device *sdev)
return 1;
}
+ /*
+ * WARPDRIVE: Initialize the required data for Direct IO
+ */
+ mpt3sas_init_warpdrive_properties(ioc, raid_device);
/* RAID Queue Depth Support
* IS volume = underlying qdepth of drive type, either
@@ -1750,17 +1887,19 @@ _scsih_slave_configure(struct scsi_device *sdev)
break;
}
- sdev_printk(KERN_INFO, sdev,
- "%s: handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
- r_level, raid_device->handle,
- (unsigned long long)raid_device->wwid,
- raid_device->num_pds, ds);
-
+ if (!ioc->hide_ir_msg)
+ sdev_printk(KERN_INFO, sdev,
+ "%s: handle(0x%04x), wwid(0x%016llx),"
+ " pd_count(%d), type(%s)\n",
+ r_level, raid_device->handle,
+ (unsigned long long)raid_device->wwid,
+ raid_device->num_pds, ds);
- _scsih_change_queue_depth(sdev, qdepth);
+ scsih_change_queue_depth(sdev, qdepth);
-/* raid transport support */
- _scsih_set_level(sdev, raid_device->volume_type);
+ /* raid transport support */
+ if (!ioc->is_warpdrive)
+ _scsih_set_level(ioc, sdev, raid_device->volume_type);
return 0;
}
@@ -1783,7 +1922,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
}
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
sas_device_priv_data->sas_target->sas_address);
if (!sas_device) {
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -1823,13 +1962,14 @@ _scsih_slave_configure(struct scsi_device *sdev)
ds, sas_device->enclosure_level,
sas_device->connector_name);
+ sas_device_put(sas_device);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (!ssp_target)
_scsih_display_sata_capabilities(ioc, handle, sdev);
- _scsih_change_queue_depth(sdev, qdepth);
+ scsih_change_queue_depth(sdev, qdepth);
if (ssp_target) {
sas_read_port_mode_page(sdev);
@@ -1840,7 +1980,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
}
/**
- * _scsih_bios_param - fetch head, sector, cylinder info for a disk
+ * scsih_bios_param - fetch head, sector, cylinder info for a disk
* @sdev: scsi device struct
* @bdev: pointer to block device context
* @capacity: device size (in 512 byte sectors)
@@ -1851,8 +1991,8 @@ _scsih_slave_configure(struct scsi_device *sdev)
*
* Return nothing.
*/
-static int
-_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+int
+scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int params[])
{
int heads;
@@ -2209,7 +2349,10 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
if (!priv_target)
return;
- device_str = "volume";
+ if (ioc->hide_ir_msg)
+ device_str = "WarpDrive";
+ else
+ device_str = "volume";
scsi_print_command(scmd);
if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
@@ -2219,8 +2362,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
device_str, (unsigned long long)priv_target->sas_address);
} else {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- priv_target->sas_address);
+ sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target);
if (sas_device) {
if (priv_target->flags &
MPT_TARGET_FLAGS_RAID_COMPONENT) {
@@ -2246,19 +2388,21 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
"enclosure level(0x%04x),connector name(%s)\n",
sas_device->enclosure_level,
sas_device->connector_name);
+
+ sas_device_put(sas_device);
}
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
}
/**
- * _scsih_abort - eh threads main abort routine
+ * scsih_abort - eh threads main abort routine
* @scmd: pointer to scsi command object
*
* Returns SUCCESS if command aborted else FAILED
*/
-static int
-_scsih_abort(struct scsi_cmnd *scmd)
+int
+scsih_abort(struct scsi_cmnd *scmd)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -2311,21 +2455,23 @@ _scsih_abort(struct scsi_cmnd *scmd)
}
/**
- * _scsih_dev_reset - eh threads main device reset routine
+ * scsih_dev_reset - eh threads main device reset routine
* @scmd: pointer to scsi command object
*
* Returns SUCCESS if command aborted else FAILED
*/
-static int
-_scsih_dev_reset(struct scsi_cmnd *scmd)
+int
+scsih_dev_reset(struct scsi_cmnd *scmd)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT3SAS_DEVICE *sas_device_priv_data;
- struct _sas_device *sas_device;
- unsigned long flags;
+ struct _sas_device *sas_device = NULL;
u16 handle;
int r;
+ struct scsi_target *starget = scmd->device->sdev_target;
+ struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
+
sdev_printk(KERN_INFO, scmd->device,
"attempting device reset! scmd(%p)\n", scmd);
_scsih_tm_display_info(ioc, scmd);
@@ -2344,12 +2490,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
handle = 0;
if (sas_device_priv_data->sas_target->flags &
MPT_TARGET_FLAGS_RAID_COMPONENT) {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc,
- sas_device_priv_data->sas_target->handle);
+ sas_device = mpt3sas_get_sdev_from_target(ioc,
+ target_priv_data);
if (sas_device)
handle = sas_device->volume_handle;
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
} else
handle = sas_device_priv_data->sas_target->handle;
@@ -2366,25 +2510,29 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+ if (sas_device)
+ sas_device_put(sas_device);
+
return r;
}
/**
- * _scsih_target_reset - eh threads main target reset routine
+ * scsih_target_reset - eh threads main target reset routine
* @scmd: pointer to scsi command object
*
* Returns SUCCESS if command aborted else FAILED
*/
-static int
-_scsih_target_reset(struct scsi_cmnd *scmd)
+int
+scsih_target_reset(struct scsi_cmnd *scmd)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT3SAS_DEVICE *sas_device_priv_data;
- struct _sas_device *sas_device;
- unsigned long flags;
+ struct _sas_device *sas_device = NULL;
u16 handle;
int r;
struct scsi_target *starget = scmd->device->sdev_target;
+ struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
scmd);
@@ -2404,12 +2552,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
handle = 0;
if (sas_device_priv_data->sas_target->flags &
MPT_TARGET_FLAGS_RAID_COMPONENT) {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc,
- sas_device_priv_data->sas_target->handle);
+ sas_device = mpt3sas_get_sdev_from_target(ioc,
+ target_priv_data);
if (sas_device)
handle = sas_device->volume_handle;
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
} else
handle = sas_device_priv_data->sas_target->handle;
@@ -2426,18 +2572,22 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
out:
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+ if (sas_device)
+ sas_device_put(sas_device);
+
return r;
}
/**
- * _scsih_host_reset - eh threads main host reset routine
+ * scsih_host_reset - eh threads main host reset routine
* @scmd: pointer to scsi command object
*
* Returns SUCCESS if command aborted else FAILED
*/
-static int
-_scsih_host_reset(struct scsi_cmnd *scmd)
+int
+scsih_host_reset(struct scsi_cmnd *scmd)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
int r, retval;
@@ -2483,32 +2633,36 @@ _scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
return;
spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ fw_event_work_get(fw_event);
INIT_LIST_HEAD(&fw_event->list);
list_add_tail(&fw_event->list, &ioc->fw_event_list);
INIT_WORK(&fw_event->work, _firmware_event_work);
+ fw_event_work_get(fw_event);
queue_work(ioc->firmware_event_thread, &fw_event->work);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
/**
- * _scsih_fw_event_free - delete fw_event
+ * _scsih_fw_event_del_from_list - delete fw_event from the list
* @ioc: per adapter object
* @fw_event: object describing the event
* Context: This function will acquire ioc->fw_event_lock.
*
- * This removes firmware event object from link list, frees associated memory.
+ * If the fw_event is on the fw_event_list, remove it and do a put.
*
* Return nothing.
*/
static void
-_scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
+_scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
*fw_event)
{
unsigned long flags;
spin_lock_irqsave(&ioc->fw_event_lock, flags);
- list_del(&fw_event->list);
- kfree(fw_event);
+ if (!list_empty(&fw_event->list)) {
+ list_del_init(&fw_event->list);
+ fw_event_work_put(fw_event);
+ }
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -2525,17 +2679,19 @@ mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
{
struct fw_event_work *fw_event;
+ u16 sz;
if (ioc->is_driver_loading)
return;
- fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data),
- GFP_ATOMIC);
+ sz = sizeof(*event_data);
+ fw_event = alloc_fw_event_work(sz);
if (!fw_event)
return;
fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
fw_event->ioc = ioc;
memcpy(fw_event->event_data, event_data, sizeof(*event_data));
_scsih_fw_event_add(ioc, fw_event);
+ fw_event_work_put(fw_event);
}
/**
@@ -2551,12 +2707,13 @@ _scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
if (ioc->is_driver_loading)
return;
- fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+ fw_event = alloc_fw_event_work(0);
if (!fw_event)
return;
fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
fw_event->ioc = ioc;
_scsih_fw_event_add(ioc, fw_event);
+ fw_event_work_put(fw_event);
}
/**
@@ -2570,12 +2727,29 @@ mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
{
struct fw_event_work *fw_event;
- fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+ fw_event = alloc_fw_event_work(0);
if (!fw_event)
return;
fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
fw_event->ioc = ioc;
_scsih_fw_event_add(ioc, fw_event);
+ fw_event_work_put(fw_event);
+}
+
+static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+ struct fw_event_work *fw_event = NULL;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ if (!list_empty(&ioc->fw_event_list)) {
+ fw_event = list_first_entry(&ioc->fw_event_list,
+ struct fw_event_work, list);
+ list_del_init(&fw_event->list);
+ }
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+
+ return fw_event;
}
/**
@@ -2590,17 +2764,25 @@ mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
static void
_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
{
- struct fw_event_work *fw_event, *next;
+ struct fw_event_work *fw_event;
if (list_empty(&ioc->fw_event_list) ||
!ioc->firmware_event_thread || in_interrupt())
return;
- list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
- if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
- _scsih_fw_event_free(ioc, fw_event);
- continue;
- }
+ while ((fw_event = dequeue_next_fw_event(ioc))) {
+ /*
+ * Wait on the fw_event to complete. If this returns 1, then
+ * the event was never executed, and we need a put for the
+ * reference the delayed_work had on the fw_event.
+ *
+ * If it did execute, we wait for it to finish, and the put will
+ * happen from _firmware_event_work()
+ */
+ if (cancel_delayed_work_sync(&fw_event->delayed_work))
+ fw_event_work_put(fw_event);
+
+ fw_event_work_put(fw_event);
}
}
@@ -2763,7 +2945,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
struct scsi_device *sdev;
struct _sas_device *sas_device;
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
if (!sas_device)
return;
@@ -2779,6 +2961,8 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
continue;
_scsih_internal_device_block(sdev, sas_device_priv_data);
}
+
+ sas_device_put(sas_device);
}
/**
@@ -2807,12 +2991,13 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
if (mpt3sas_port->remote_identify.device_type ==
SAS_END_DEVICE) {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device =
- mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- mpt3sas_port->remote_identify.sas_address);
- if (sas_device)
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
+ mpt3sas_port->remote_identify.sas_address);
+ if (sas_device) {
set_bit(sas_device->handle,
- ioc->blocking_handles);
+ ioc->blocking_handles);
+ sas_device_put(sas_device);
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
}
@@ -2880,7 +3065,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
Mpi2SCSITaskManagementRequest_t *mpi_request;
u16 smid;
- struct _sas_device *sas_device;
+ struct _sas_device *sas_device = NULL;
struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
u64 sas_address = 0;
unsigned long flags;
@@ -2913,7 +3098,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
return;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
if (sas_device && sas_device->starget &&
sas_device->starget->hostdata) {
sas_target_priv_data = sas_device->starget->hostdata;
@@ -2947,14 +3132,14 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
if (!smid) {
delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
if (!delayed_tr)
- return;
+ goto out;
INIT_LIST_HEAD(&delayed_tr->list);
delayed_tr->handle = handle;
list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"DELAYED:tr:handle(0x%04x), (open)\n",
ioc->name, handle));
- return;
+ goto out;
}
dewtprintk(ioc, pr_info(MPT3SAS_FMT
@@ -2968,6 +3153,10 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
mpt3sas_base_put_smid_hi_priority(ioc, smid);
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
+
+out:
+ if (sas_device)
+ sas_device_put(sas_device);
}
/**
@@ -3337,7 +3526,7 @@ _scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
unsigned long flags;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
if (raid_device && raid_device->starget &&
raid_device->starget->hostdata) {
sas_target_priv_data =
@@ -3398,6 +3587,9 @@ _scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
a = 0;
b = 0;
+ if (ioc->is_warpdrive)
+ return;
+
/* Volume Resets for Deleted or Removed */
element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
for (i = 0; i < event_data->NumElements; i++, element++) {
@@ -3634,8 +3826,9 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
}
+
/**
- * _scsih_qcmd - main scsi request entry point
+ * scsih_qcmd - main scsi request entry point
* @scmd: pointer to scsi command object
* @done: function pointer to be invoked on completion
*
@@ -3645,21 +3838,20 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
* SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
* SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
*/
-static int
-_scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+int
+scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct MPT3SAS_DEVICE *sas_device_priv_data;
struct MPT3SAS_TARGET *sas_target_priv_data;
+ struct _raid_device *raid_device;
Mpi2SCSIIORequest_t *mpi_request;
u32 mpi_control;
u16 smid;
u16 handle;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_SCSI)
scsi_print_command(scmd);
-#endif
sas_device_priv_data = scmd->device->hostdata;
if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
@@ -3709,7 +3901,11 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
/* set tags */
mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
- if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
+ /* Make sure Device is not raid volume.
+ * We do not expose raid functionality to upper layer for warpdrive.
+ */
+ if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)
+ && (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
scmd->cmd_len != 32)
mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
@@ -3752,13 +3948,19 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
} else
ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
+ raid_device = sas_target_priv_data->raid_device;
+ if (raid_device && raid_device->direct_io_enabled)
+ mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request,
+ smid);
+
if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
MPI25_SCSIIO_IOFLAGS_FAST_PATH);
mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
} else
- mpt3sas_base_put_smid_scsi_io(ioc, smid, handle);
+ mpt3sas_base_put_smid_scsi_io(ioc, smid,
+ le16_to_cpu(mpi_request->DevHandle));
} else
mpt3sas_base_put_smid_default(ioc, smid);
return 0;
@@ -3790,7 +3992,6 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
}
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
* @ioc: per adapter object
@@ -3818,14 +4019,16 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
char *desc_scsi_state = ioc->tmp_string;
u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
struct _sas_device *sas_device = NULL;
- unsigned long flags;
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT3SAS_TARGET *priv_target = starget->hostdata;
char *device_str = NULL;
if (!priv_target)
return;
- device_str = "volume";
+ if (ioc->hide_ir_msg)
+ device_str = "WarpDrive";
+ else
+ device_str = "volume";
if (log_info == 0x31170000)
return;
@@ -3946,9 +4149,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
device_str, (unsigned long long)priv_target->sas_address);
} else {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- priv_target->sas_address);
+ sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
if (sas_device) {
pr_warn(MPT3SAS_FMT
"\tsas_address(0x%016llx), phy(%d)\n",
@@ -3967,8 +4168,9 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
" connector name( %s)\n", ioc->name,
sas_device->enclosure_level,
sas_device->connector_name);
+
+ sas_device_put(sas_device);
}
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
pr_warn(MPT3SAS_FMT
@@ -4003,7 +4205,6 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
_scsih_response_code(ioc, response_bytes[0]);
}
}
-#endif
/**
* _scsih_turn_on_pfa_led - illuminate PFA LED
@@ -4020,7 +4221,7 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Mpi2SepRequest_t mpi_request;
struct _sas_device *sas_device;
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
if (!sas_device)
return;
@@ -4035,7 +4236,7 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
&mpi_request)) != 0) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
__FILE__, __LINE__, __func__);
- return;
+ goto out;
}
sas_device->pfa_led_on = 1;
@@ -4044,9 +4245,12 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
"enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
le32_to_cpu(mpi_reply.IOCLogInfo)));
- return;
+ goto out;
}
+out:
+ sas_device_put(sas_device);
}
+
/**
* _scsih_turn_off_pfa_led - turn off Fault LED
* @ioc: per adapter object
@@ -4085,6 +4289,7 @@ _scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
return;
}
}
+
/**
* _scsih_send_event_to_turn_on_pfa_led - fire delayed event
* @ioc: per adapter object
@@ -4098,13 +4303,14 @@ _scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct fw_event_work *fw_event;
- fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+ fw_event = alloc_fw_event_work(0);
if (!fw_event)
return;
fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
fw_event->device_handle = handle;
fw_event->ioc = ioc;
_scsih_fw_event_add(ioc, fw_event);
+ fw_event_work_put(fw_event);
}
/**
@@ -4128,19 +4334,17 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
/* only handle non-raid devices */
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
+ if (!sas_device)
+ goto out_unlock;
+
starget = sas_device->starget;
sas_target_priv_data = starget->hostdata;
if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
- ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
+ goto out_unlock;
+
if (sas_device->enclosure_handle != 0)
starget_printk(KERN_INFO, starget, "predicted fault, "
"enclosure logical id(0x%016llx), slot(%d)\n",
@@ -4163,7 +4367,7 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
if (!event_reply) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
- return;
+ goto out;
}
event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
@@ -4180,6 +4384,14 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
mpt3sas_ctl_add_to_event_log(ioc, event_reply);
kfree(event_reply);
+out:
+ if (sas_device)
+ sas_device_put(sas_device);
+ return;
+
+out_unlock:
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ goto out;
}
/**
@@ -4207,6 +4419,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
u32 log_info;
struct MPT3SAS_DEVICE *sas_device_priv_data;
u32 response_code = 0;
+ unsigned long flags;
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
@@ -4228,6 +4441,24 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
}
ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
+ /*
+ * WARPDRIVE: If direct_io is set then it is directIO,
+ * the failed direct I/O should be redirected to volume
+ */
+ if (mpt3sas_scsi_direct_io_get(ioc, smid) &&
+ ((ioc_status & MPI2_IOCSTATUS_MASK)
+ != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ ioc->scsi_lookup[smid - 1].scmd = scmd;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ mpt3sas_scsi_direct_io_set(ioc, smid, 0);
+ memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
+ mpi_request->DevHandle =
+ cpu_to_le16(sas_device_priv_data->sas_target->handle);
+ mpt3sas_base_put_smid_scsi_io(ioc, smid,
+ sas_device_priv_data->sas_target->handle);
+ return 0;
+ }
/* turning off TLR */
scsi_state = mpi_reply->SCSIState;
if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
@@ -4235,10 +4466,13 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
if (!sas_device_priv_data->tlr_snoop_check) {
sas_device_priv_data->tlr_snoop_check++;
- if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
- response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
- sas_device_priv_data->flags &=
- ~MPT_DEVICE_TLR_ON;
+ if (!ioc->is_warpdrive &&
+ !scsih_is_raid(&scmd->device->sdev_gendev) &&
+ sas_is_tlr_enabled(scmd->device) &&
+ response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
+ sas_disable_tlr(scmd->device);
+ sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
+ }
}
xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
@@ -4271,13 +4505,11 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
le16_to_cpu(mpi_reply->DevHandle));
mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
(scmd->sense_buffer[2] == MEDIUM_ERROR) ||
(scmd->sense_buffer[2] == HARDWARE_ERROR)))
_scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
-#endif
}
switch (ioc_status) {
case MPI2_IOCSTATUS_BUSY:
@@ -4384,10 +4616,8 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
_scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
-#endif
out:
@@ -4933,13 +5163,11 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
sas_address);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ if (!sas_device)
+ goto out_unlock;
if (unlikely(sas_device->handle != handle)) {
starget = sas_device->starget;
@@ -4967,20 +5195,25 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
pr_err(MPT3SAS_FMT
"device is not present handle(0x%04x), flags!!!\n",
ioc->name, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
+ goto out_unlock;
}
/* check if there were any issues with discovery */
if (_scsih_check_access_status(ioc, sas_address, handle,
- sas_device_pg0.AccessStatus)) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ sas_device_pg0.AccessStatus))
+ goto out_unlock;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
_scsih_ublock_io_device(ioc, sas_address);
+ if (sas_device)
+ sas_device_put(sas_device);
+ return;
+
+out_unlock:
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_device)
+ sas_device_put(sas_device);
}
/**
@@ -5005,7 +5238,6 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
u32 ioc_status;
u64 sas_address;
u32 device_info;
- unsigned long flags;
if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
@@ -5041,13 +5273,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
sas_device_pg0.AccessStatus))
return -1;
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (sas_device)
+ sas_device = mpt3sas_get_sdev_by_addr(ioc,
+ sas_address);
+ if (sas_device) {
+ sas_device_put(sas_device);
return -1;
+ }
sas_device = kzalloc(sizeof(struct _sas_device),
GFP_KERNEL);
@@ -5057,6 +5288,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
return 0;
}
+ kref_init(&sas_device->refcount);
sas_device->handle = handle;
if (_scsih_get_sas_address(ioc,
le16_to_cpu(sas_device_pg0.ParentDevHandle),
@@ -5098,6 +5330,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
else
_scsih_sas_device_add(ioc, sas_device);
+ sas_device_put(sas_device);
return 0;
}
@@ -5144,7 +5377,9 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
sas_target_priv_data->handle =
MPT3SAS_INVALID_DEVICE_HANDLE;
}
- mpt3sas_transport_port_remove(ioc,
+
+ if (!ioc->hide_drives)
+ mpt3sas_transport_port_remove(ioc,
sas_device->sas_address,
sas_device->sas_address_parent);
@@ -5180,11 +5415,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
"%s: exit: enclosure level(0x%04x), connector name(%s)\n",
ioc->name, __func__, sas_device->enclosure_level,
sas_device->connector_name));
-
- kfree(sas_device);
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _scsih_sas_topology_change_event_debug - debug for topology event
* @ioc: per adapter object
@@ -5262,7 +5494,6 @@ _scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
}
}
-#endif
/**
* _scsih_sas_topology_change_event - handle topology changes
@@ -5287,10 +5518,8 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
(Mpi2EventDataSasTopologyChangeList_t *)
fw_event->event_data;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
_scsih_sas_topology_change_event_debug(ioc, event_data);
-#endif
if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
return 0;
@@ -5396,7 +5625,6 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
return 0;
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _scsih_sas_device_status_change_event_debug - debug for device event
* @event_data: event data payload
@@ -5464,7 +5692,6 @@ _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
event_data->ASC, event_data->ASCQ);
pr_info("\n");
}
-#endif
/**
* _scsih_sas_device_status_change_event - handle device status change
@@ -5486,11 +5713,9 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
(Mpi2EventDataSasDeviceStatusChange_t *)
fw_event->event_data;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
_scsih_sas_device_status_change_event_debug(ioc,
event_data);
-#endif
/* In MPI Revision K (0xC), the internal device reset complete was
* implemented, so avoid setting tm_busy flag for older firmware.
@@ -5506,29 +5731,30 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_address = le64_to_cpu(event_data->SASAddress);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
sas_address);
- if (!sas_device || !sas_device->starget) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ if (!sas_device || !sas_device->starget)
+ goto out;
target_priv_data = sas_device->starget->hostdata;
- if (!target_priv_data) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ if (!target_priv_data)
+ goto out;
if (event_data->ReasonCode ==
MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
target_priv_data->tm_busy = 1;
else
target_priv_data->tm_busy = 0;
+
+out:
+ if (sas_device)
+ sas_device_put(sas_device);
+
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
* event
@@ -5563,7 +5789,6 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
(unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
le16_to_cpu(event_data->StartSlot));
}
-#endif
/**
* _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
@@ -5577,12 +5802,10 @@ static void
_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
struct fw_event_work *fw_event)
{
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
_scsih_sas_enclosure_dev_status_change_event_debug(ioc,
(Mpi2EventDataSasEnclDevStatusChange_t *)
fw_event->event_data);
-#endif
}
/**
@@ -5762,17 +5985,15 @@ _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
Mpi2EventDataSasDiscovery_t *event_data =
(Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
(event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
"start" : "stop");
- if (event_data->DiscoveryStatus)
- pr_info("discovery_status(0x%08x)",
- le32_to_cpu(event_data->DiscoveryStatus));
- pr_info("\n");
+ if (event_data->DiscoveryStatus)
+ pr_info("discovery_status(0x%08x)",
+ le32_to_cpu(event_data->DiscoveryStatus));
+ pr_info("\n");
}
-#endif
if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
!ioc->sas_hba.num_phys) {
@@ -5804,6 +6025,8 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
u16 ioc_status;
u32 log_info;
+ if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+ return rc;
mutex_lock(&ioc->scsih_cmds.mutex);
@@ -5971,7 +6194,7 @@ _scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
struct scsi_target *starget = NULL;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
if (raid_device) {
if (raid_device->starget) {
starget = raid_device->starget;
@@ -6008,7 +6231,7 @@ _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
if (sas_device) {
sas_device->volume_handle = 0;
sas_device->volume_wwid = 0;
@@ -6027,6 +6250,8 @@ _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
/* exposing raid component */
if (starget)
starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
+
+ sas_device_put(sas_device);
}
/**
@@ -6055,7 +6280,7 @@ _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
&volume_wwid);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
if (sas_device) {
set_bit(handle, ioc->pd_handles);
if (sas_device->starget && sas_device->starget->hostdata) {
@@ -6073,8 +6298,11 @@ _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
/* hiding raid component */
_scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+
if (starget)
starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
+
+ sas_device_put(sas_device);
}
/**
@@ -6107,7 +6335,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
struct _sas_device *sas_device;
- unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
@@ -6117,11 +6344,10 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
set_bit(handle, ioc->pd_handles);
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
if (sas_device) {
_scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+ sas_device_put(sas_device);
return;
}
@@ -6149,7 +6375,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
_scsih_add_device(ioc, handle, 0, 1);
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
* @ioc: per adapter object
@@ -6229,7 +6454,6 @@ _scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
element->PhysDiskNum);
}
}
-#endif
/**
* _scsih_sas_ir_config_change_event - handle ir configuration change events
@@ -6250,18 +6474,16 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
(Mpi2EventDataIrConfigChangeList_t *)
fw_event->event_data;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
+ (!ioc->hide_ir_msg))
_scsih_sas_ir_config_change_event_debug(ioc, event_data);
-#endif
-
foreign_config = (le32_to_cpu(event_data->Flags) &
MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
- if (ioc->shost_recovery) {
-
+ if (ioc->shost_recovery &&
+ ioc->hba_mpi_version_belonged != MPI2_VERSION) {
for (i = 0; i < event_data->NumElements; i++, element++) {
if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
_scsih_ir_fastpath(ioc,
@@ -6270,6 +6492,7 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
}
return;
}
+
for (i = 0; i < event_data->NumElements; i++, element++) {
switch (element->ReasonCode) {
@@ -6285,16 +6508,20 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
le16_to_cpu(element->VolDevHandle));
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
- _scsih_sas_pd_hide(ioc, element);
+ if (!ioc->is_warpdrive)
+ _scsih_sas_pd_hide(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
- _scsih_sas_pd_expose(ioc, element);
+ if (!ioc->is_warpdrive)
+ _scsih_sas_pd_expose(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_HIDE:
- _scsih_sas_pd_add(ioc, element);
+ if (!ioc->is_warpdrive)
+ _scsih_sas_pd_add(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
- _scsih_sas_pd_delete(ioc, element);
+ if (!ioc->is_warpdrive)
+ _scsih_sas_pd_delete(ioc, element);
break;
}
}
@@ -6329,10 +6556,11 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
handle = le16_to_cpu(event_data->VolDevHandle);
state = le32_to_cpu(event_data->NewValue);
- dewtprintk(ioc, pr_info(MPT3SAS_FMT
- "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
- ioc->name, __func__, handle,
- le32_to_cpu(event_data->PreviousValue), state));
+ if (!ioc->hide_ir_msg)
+ dewtprintk(ioc, pr_info(MPT3SAS_FMT
+ "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
+ ioc->name, __func__, handle,
+ le32_to_cpu(event_data->PreviousValue), state));
switch (state) {
case MPI2_RAID_VOL_STATE_MISSING:
case MPI2_RAID_VOL_STATE_FAILED:
@@ -6344,7 +6572,7 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
case MPI2_RAID_VOL_STATE_OPTIMAL:
spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (raid_device)
@@ -6398,7 +6626,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
u16 handle, parent_handle;
u32 state;
struct _sas_device *sas_device;
- unsigned long flags;
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
u32 ioc_status;
@@ -6415,10 +6642,12 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
handle = le16_to_cpu(event_data->PhysDiskDevHandle);
state = le32_to_cpu(event_data->NewValue);
- dewtprintk(ioc, pr_info(MPT3SAS_FMT
- "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
- ioc->name, __func__, handle,
+ if (!ioc->hide_ir_msg)
+ dewtprintk(ioc, pr_info(MPT3SAS_FMT
+ "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
+ ioc->name, __func__, handle,
le32_to_cpu(event_data->PreviousValue), state));
+
switch (state) {
case MPI2_RAID_PD_STATE_ONLINE:
case MPI2_RAID_PD_STATE_DEGRADED:
@@ -6426,13 +6655,14 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
case MPI2_RAID_PD_STATE_OPTIMAL:
case MPI2_RAID_PD_STATE_HOT_SPARE:
- set_bit(handle, ioc->pd_handles);
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!ioc->is_warpdrive)
+ set_bit(handle, ioc->pd_handles);
- if (sas_device)
+ sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
+ if (sas_device) {
+ sas_device_put(sas_device);
return;
+ }
if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
&sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
@@ -6467,7 +6697,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
}
}
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
/**
* _scsih_sas_ir_operation_status_event_debug - debug for IR op event
* @ioc: per adapter object
@@ -6509,7 +6738,6 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
le16_to_cpu(event_data->VolDevHandle),
event_data->PercentComplete);
}
-#endif
/**
* _scsih_sas_ir_operation_status_event - handle RAID operation events
@@ -6530,18 +6758,17 @@ _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
unsigned long flags;
u16 handle;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
- if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
+ (!ioc->hide_ir_msg))
_scsih_sas_ir_operation_status_event_debug(ioc,
event_data);
-#endif
/* code added for raid transport support */
if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
spin_lock_irqsave(&ioc->raid_device_lock, flags);
handle = le16_to_cpu(event_data->VolDevHandle);
- raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
if (raid_device)
raid_device->percent_complete =
event_data->PercentComplete;
@@ -6703,7 +6930,7 @@ static void
_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
u16 handle)
{
- struct MPT3SAS_TARGET *sas_target_priv_data;
+ struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
struct scsi_target *starget;
struct _raid_device *raid_device;
unsigned long flags;
@@ -6722,6 +6949,13 @@ _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
starget_printk(KERN_INFO, raid_device->starget,
"handle(0x%04x), wwid(0x%016llx)\n", handle,
(unsigned long long)raid_device->wwid);
+
+ /*
+ * WARPDRIVE: The handles of the PDs might have changed
+ * across the host reset so re-initialize the
+ * required data for Direct IO
+ */
+ mpt3sas_init_warpdrive_properties(ioc, raid_device);
spin_lock_irqsave(&ioc->raid_device_lock, flags);
if (raid_device->handle == handle) {
spin_unlock_irqrestore(&ioc->raid_device_lock,
@@ -6791,6 +7025,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
}
/* refresh the pd_handles */
+ if (!ioc->is_warpdrive) {
phys_disk_num = 0xFF;
memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
@@ -6804,6 +7039,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
handle = le16_to_cpu(pd_pg0.DevHandle);
set_bit(handle, ioc->pd_handles);
}
+ }
out:
pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
ioc->name);
@@ -6906,6 +7142,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
struct _raid_device *raid_device, *raid_device_next;
struct list_head tmp_list;
unsigned long flags;
+ LIST_HEAD(head);
pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
ioc->name);
@@ -6913,14 +7150,28 @@ _scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
/* removing unresponding end devices */
pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
ioc->name);
+ /*
+ * Iterate, pulling off devices marked as non-responding. We become the
+ * owner for the reference the list had on any object we prune.
+ */
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
if (!sas_device->responding)
- mpt3sas_device_remove_by_sas_address(ioc,
- sas_device->sas_address);
+ list_move_tail(&sas_device->list, &head);
else
sas_device->responding = 0;
}
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ /*
+ * Now, uninitialize and remove the unresponding devices we pruned.
+ */
+ list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
+ _scsih_remove_device(ioc, sas_device);
+ list_del_init(&sas_device->list);
+ sas_device_put(sas_device);
+ }
/* removing unresponding volumes */
if (ioc->ir_firmware) {
@@ -7074,11 +7325,11 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
}
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
+ sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
+ if (sas_device) {
+ sas_device_put(sas_device);
continue;
+ }
if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
&sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
handle) != 0)
@@ -7199,12 +7450,12 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
if (!(_scsih_is_end_device(
le32_to_cpu(sas_device_pg0.DeviceInfo))))
continue;
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = mpt3sas_get_sdev_by_addr(ioc,
le64_to_cpu(sas_device_pg0.SASAddress));
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
+ if (sas_device) {
+ sas_device_put(sas_device);
continue;
+ }
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
@@ -7296,10 +7547,11 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
static void
_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
{
+ _scsih_fw_event_del_from_list(ioc, fw_event);
+
/* the queue is being flushed so ignore this event */
- if (ioc->remove_host ||
- ioc->pci_error_recovery) {
- _scsih_fw_event_free(ioc, fw_event);
+ if (ioc->remove_host || ioc->pci_error_recovery) {
+ fw_event_work_put(fw_event);
return;
}
@@ -7310,8 +7562,16 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
fw_event->event_data);
break;
case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
- while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
+ while (scsi_host_in_recovery(ioc->shost) ||
+ ioc->shost_recovery) {
+ /*
+ * If we're unloading, bail. Otherwise, this can become
+ * an infinite loop.
+ */
+ if (ioc->remove_host)
+ goto out;
ssleep(1);
+ }
_scsih_remove_unresponding_sas_devices(ioc);
_scsih_scan_for_devices_after_reset(ioc);
break;
@@ -7356,7 +7616,8 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
_scsih_sas_ir_operation_status_event(ioc, fw_event);
break;
}
- _scsih_fw_event_free(ioc, fw_event);
+out:
+ fw_event_work_put(fw_event);
}
/**
@@ -7453,7 +7714,53 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
(Mpi2EventDataIrVolume_t *)
mpi_reply->EventData);
break;
+ case MPI2_EVENT_LOG_ENTRY_ADDED:
+ {
+ Mpi2EventDataLogEntryAdded_t *log_entry;
+ u32 *log_code;
+
+ if (!ioc->is_warpdrive)
+ break;
+
+ log_entry = (Mpi2EventDataLogEntryAdded_t *)
+ mpi_reply->EventData;
+ log_code = (u32 *)log_entry->LogData;
+ if (le16_to_cpu(log_entry->LogEntryQualifier)
+ != MPT2_WARPDRIVE_LOGENTRY)
+ break;
+
+ switch (le32_to_cpu(*log_code)) {
+ case MPT2_WARPDRIVE_LC_SSDT:
+ pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
+ "IO Throttling has occurred in the WarpDrive "
+ "subsystem. Check WarpDrive documentation for "
+ "additional details.\n", ioc->name);
+ break;
+ case MPT2_WARPDRIVE_LC_SSDLW:
+ pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
+ "Program/Erase Cycles for the WarpDrive subsystem "
+ "in degraded range. Check WarpDrive documentation "
+ "for additional details.\n", ioc->name);
+ break;
+ case MPT2_WARPDRIVE_LC_SSDLF:
+ pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
+ "There are no Program/Erase Cycles for the "
+ "WarpDrive subsystem. The storage device will be "
+ "in read-only mode. Check WarpDrive documentation "
+ "for additional details.\n", ioc->name);
+ break;
+ case MPT2_WARPDRIVE_LC_BRMF:
+ pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
+ "The Backup Rail Monitor has failed on the "
+ "WarpDrive subsystem. Check WarpDrive "
+ "documentation for additional details.\n",
+ ioc->name);
+ break;
+ }
+
+ break;
+ }
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
case MPI2_EVENT_IR_OPERATION_STATUS:
case MPI2_EVENT_SAS_DISCOVERY:
@@ -7472,7 +7779,7 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
}
sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
- fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
+ fw_event = alloc_fw_event_work(sz);
if (!fw_event) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -7485,39 +7792,10 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
fw_event->VP_ID = mpi_reply->VP_ID;
fw_event->event = event;
_scsih_fw_event_add(ioc, fw_event);
+ fw_event_work_put(fw_event);
return 1;
}
-/* shost template */
-static struct scsi_host_template scsih_driver_template = {
- .module = THIS_MODULE,
- .name = "Fusion MPT SAS Host",
- .proc_name = MPT3SAS_DRIVER_NAME,
- .queuecommand = _scsih_qcmd,
- .target_alloc = _scsih_target_alloc,
- .slave_alloc = _scsih_slave_alloc,
- .slave_configure = _scsih_slave_configure,
- .target_destroy = _scsih_target_destroy,
- .slave_destroy = _scsih_slave_destroy,
- .scan_finished = _scsih_scan_finished,
- .scan_start = _scsih_scan_start,
- .change_queue_depth = _scsih_change_queue_depth,
- .eh_abort_handler = _scsih_abort,
- .eh_device_reset_handler = _scsih_dev_reset,
- .eh_target_reset_handler = _scsih_target_reset,
- .eh_host_reset_handler = _scsih_host_reset,
- .bios_param = _scsih_bios_param,
- .can_queue = 1,
- .this_id = -1,
- .sg_tablesize = MPT3SAS_SG_DEPTH,
- .max_sectors = 32767,
- .cmd_per_lun = 7,
- .use_clustering = ENABLE_CLUSTERING,
- .shost_attrs = mpt3sas_host_attrs,
- .sdev_attrs = mpt3sas_dev_attrs,
- .track_queue_depth = 1,
-};
-
/**
* _scsih_expander_node_remove - removing expander device from list.
* @ioc: per adapter object
@@ -7613,7 +7891,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
- pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
+ if (!ioc->hide_ir_msg)
+ pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
init_completion(&ioc->scsih_cmds.done);
mpt3sas_base_put_smid_default(ioc, smid);
wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
@@ -7626,10 +7905,11 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
mpi_reply = ioc->scsih_cmds.reply;
- pr_info(MPT3SAS_FMT
- "IR shutdown (complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo));
+ if (!ioc->hide_ir_msg)
+ pr_info(MPT3SAS_FMT "IR shutdown "
+ "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo));
}
out:
@@ -7638,13 +7918,13 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
}
/**
- * _scsih_remove - detach and remove add host
+ * scsih_remove - detach and remove add host
* @pdev: PCI device struct
*
* Routine called when unloading the driver.
* Return nothing.
*/
-static void _scsih_remove(struct pci_dev *pdev)
+void scsih_remove(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7705,18 +7985,20 @@ static void _scsih_remove(struct pci_dev *pdev)
sas_remove_host(shost);
scsi_remove_host(shost);
mpt3sas_base_detach(ioc);
+ spin_lock(&gioc_lock);
list_del(&ioc->list);
+ spin_unlock(&gioc_lock);
scsi_host_put(shost);
}
/**
- * _scsih_shutdown - routine call during system shutdown
+ * scsih_shutdown - routine call during system shutdown
* @pdev: PCI device struct
*
* Return nothing.
*/
-static void
-_scsih_shutdown(struct pci_dev *pdev)
+void
+scsih_shutdown(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7794,6 +8076,8 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
list_move_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (ioc->hide_drives)
+ return;
if (!mpt3sas_transport_port_add(ioc, handle,
sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
@@ -7831,6 +8115,48 @@ _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
}
}
+static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc)
+{
+ struct _sas_device *sas_device = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ if (!list_empty(&ioc->sas_device_init_list)) {
+ sas_device = list_first_entry(&ioc->sas_device_init_list,
+ struct _sas_device, list);
+ sas_device_get(sas_device);
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ return sas_device;
+}
+
+static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc,
+ struct _sas_device *sas_device)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+
+ /*
+ * Since we dropped the lock during the call to port_add(), we need to
+ * be careful here that somebody else didn't move or delete this item
+ * while we were busy with other things.
+ *
+ * If it was on the list, we need a put() for the reference the list
+ * had. Either way, we need a get() for the destination list.
+ */
+ if (!list_empty(&sas_device->list)) {
+ list_del_init(&sas_device->list);
+ sas_device_put(sas_device);
+ }
+
+ sas_device_get(sas_device);
+ list_add_tail(&sas_device->list, &ioc->sas_device_list);
+
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
/**
* _scsih_probe_sas - reporting sas devices to sas transport
* @ioc: per adapter object
@@ -7840,17 +8166,16 @@ _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
static void
_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
{
- struct _sas_device *sas_device, *next;
- unsigned long flags;
+ struct _sas_device *sas_device;
- /* SAS Device List */
- list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
- list) {
+ if (ioc->hide_drives)
+ return;
+ while ((sas_device = get_next_sas_device(ioc))) {
if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
sas_device->sas_address_parent)) {
- list_del(&sas_device->list);
- kfree(sas_device);
+ _scsih_sas_device_remove(ioc, sas_device);
+ sas_device_put(sas_device);
continue;
} else if (!sas_device->starget) {
/*
@@ -7863,15 +8188,13 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
mpt3sas_transport_port_remove(ioc,
sas_device->sas_address,
sas_device->sas_address_parent);
- list_del(&sas_device->list);
- kfree(sas_device);
+ _scsih_sas_device_remove(ioc, sas_device);
+ sas_device_put(sas_device);
continue;
}
}
-
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- list_move_tail(&sas_device->list, &ioc->sas_device_list);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ sas_device_make_active(ioc, sas_device);
+ sas_device_put(sas_device);
}
}
@@ -7908,15 +8231,15 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
}
/**
- * _scsih_scan_start - scsi lld callback for .scan_start
+ * scsih_scan_start - scsi lld callback for .scan_start
* @shost: SCSI host pointer
*
* The shost has the ability to discover targets on its own instead
* of scanning the entire bus. In our implemention, we will kick off
* firmware discovery.
*/
-static void
-_scsih_scan_start(struct Scsi_Host *shost)
+void
+scsih_scan_start(struct Scsi_Host *shost)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
int rc;
@@ -7934,7 +8257,7 @@ _scsih_scan_start(struct Scsi_Host *shost)
}
/**
- * _scsih_scan_finished - scsi lld callback for .scan_finished
+ * scsih_scan_finished - scsi lld callback for .scan_finished
* @shost: SCSI host pointer
* @time: elapsed time of the scan in jiffies
*
@@ -7942,8 +8265,8 @@ _scsih_scan_start(struct Scsi_Host *shost)
* scsi_host and the elapsed time of the scan in jiffies. In our implemention,
* we wait for firmware discovery to complete, then return 1.
*/
-static int
-_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
+int
+scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7987,6 +8310,124 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
return 1;
}
+/* shost template for SAS 2.0 HBA devices */
+static struct scsi_host_template mpt2sas_driver_template = {
+ .module = THIS_MODULE,
+ .name = "Fusion MPT SAS Host",
+ .proc_name = MPT2SAS_DRIVER_NAME,
+ .queuecommand = scsih_qcmd,
+ .target_alloc = scsih_target_alloc,
+ .slave_alloc = scsih_slave_alloc,
+ .slave_configure = scsih_slave_configure,
+ .target_destroy = scsih_target_destroy,
+ .slave_destroy = scsih_slave_destroy,
+ .scan_finished = scsih_scan_finished,
+ .scan_start = scsih_scan_start,
+ .change_queue_depth = scsih_change_queue_depth,
+ .eh_abort_handler = scsih_abort,
+ .eh_device_reset_handler = scsih_dev_reset,
+ .eh_target_reset_handler = scsih_target_reset,
+ .eh_host_reset_handler = scsih_host_reset,
+ .bios_param = scsih_bios_param,
+ .can_queue = 1,
+ .this_id = -1,
+ .sg_tablesize = MPT2SAS_SG_DEPTH,
+ .max_sectors = 32767,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+ .shost_attrs = mpt3sas_host_attrs,
+ .sdev_attrs = mpt3sas_dev_attrs,
+ .track_queue_depth = 1,
+};
+
+/* raid transport support for SAS 2.0 HBA devices */
+static struct raid_function_template mpt2sas_raid_functions = {
+ .cookie = &mpt2sas_driver_template,
+ .is_raid = scsih_is_raid,
+ .get_resync = scsih_get_resync,
+ .get_state = scsih_get_state,
+};
+
+/* shost template for SAS 3.0 HBA devices */
+static struct scsi_host_template mpt3sas_driver_template = {
+ .module = THIS_MODULE,
+ .name = "Fusion MPT SAS Host",
+ .proc_name = MPT3SAS_DRIVER_NAME,
+ .queuecommand = scsih_qcmd,
+ .target_alloc = scsih_target_alloc,
+ .slave_alloc = scsih_slave_alloc,
+ .slave_configure = scsih_slave_configure,
+ .target_destroy = scsih_target_destroy,
+ .slave_destroy = scsih_slave_destroy,
+ .scan_finished = scsih_scan_finished,
+ .scan_start = scsih_scan_start,
+ .change_queue_depth = scsih_change_queue_depth,
+ .eh_abort_handler = scsih_abort,
+ .eh_device_reset_handler = scsih_dev_reset,
+ .eh_target_reset_handler = scsih_target_reset,
+ .eh_host_reset_handler = scsih_host_reset,
+ .bios_param = scsih_bios_param,
+ .can_queue = 1,
+ .this_id = -1,
+ .sg_tablesize = MPT3SAS_SG_DEPTH,
+ .max_sectors = 32767,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+ .shost_attrs = mpt3sas_host_attrs,
+ .sdev_attrs = mpt3sas_dev_attrs,
+ .track_queue_depth = 1,
+};
+
+/* raid transport support for SAS 3.0 HBA devices */
+static struct raid_function_template mpt3sas_raid_functions = {
+ .cookie = &mpt3sas_driver_template,
+ .is_raid = scsih_is_raid,
+ .get_resync = scsih_get_resync,
+ .get_state = scsih_get_state,
+};
+
+/**
+ * _scsih_determine_hba_mpi_version - determine in which MPI version class
+ * this device belongs to.
+ * @pdev: PCI device struct
+ *
+ * return MPI2_VERSION for SAS 2.0 HBA devices,
+ * MPI25_VERSION for SAS 3.0 HBA devices.
+ */
+u16
+_scsih_determine_hba_mpi_version(struct pci_dev *pdev)
+{
+
+ switch (pdev->device) {
+ case MPI2_MFGPAGE_DEVID_SSS6200:
+ case MPI2_MFGPAGE_DEVID_SAS2004:
+ case MPI2_MFGPAGE_DEVID_SAS2008:
+ case MPI2_MFGPAGE_DEVID_SAS2108_1:
+ case MPI2_MFGPAGE_DEVID_SAS2108_2:
+ case MPI2_MFGPAGE_DEVID_SAS2108_3:
+ case MPI2_MFGPAGE_DEVID_SAS2116_1:
+ case MPI2_MFGPAGE_DEVID_SAS2116_2:
+ case MPI2_MFGPAGE_DEVID_SAS2208_1:
+ case MPI2_MFGPAGE_DEVID_SAS2208_2:
+ case MPI2_MFGPAGE_DEVID_SAS2208_3:
+ case MPI2_MFGPAGE_DEVID_SAS2208_4:
+ case MPI2_MFGPAGE_DEVID_SAS2208_5:
+ case MPI2_MFGPAGE_DEVID_SAS2208_6:
+ case MPI2_MFGPAGE_DEVID_SAS2308_1:
+ case MPI2_MFGPAGE_DEVID_SAS2308_2:
+ case MPI2_MFGPAGE_DEVID_SAS2308_3:
+ return MPI2_VERSION;
+ case MPI25_MFGPAGE_DEVID_SAS3004:
+ case MPI25_MFGPAGE_DEVID_SAS3008:
+ case MPI25_MFGPAGE_DEVID_SAS3108_1:
+ case MPI25_MFGPAGE_DEVID_SAS3108_2:
+ case MPI25_MFGPAGE_DEVID_SAS3108_5:
+ case MPI25_MFGPAGE_DEVID_SAS3108_6:
+ return MPI25_VERSION;
+ }
+ return 0;
+}
+
/**
* _scsih_probe - attach and add scsi host
* @pdev: PCI device struct
@@ -7994,26 +8435,72 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
*
* Returns 0 success, anything else error.
*/
-static int
+int
_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct MPT3SAS_ADAPTER *ioc;
- struct Scsi_Host *shost;
+ struct Scsi_Host *shost = NULL;
int rv;
+ u16 hba_mpi_version;
- shost = scsi_host_alloc(&scsih_driver_template,
- sizeof(struct MPT3SAS_ADAPTER));
- if (!shost)
+ /* Determine in which MPI version class this pci device belongs */
+ hba_mpi_version = _scsih_determine_hba_mpi_version(pdev);
+ if (hba_mpi_version == 0)
return -ENODEV;
- /* init local params */
- ioc = shost_priv(shost);
- memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+ /* Enumerate only SAS 2.0 HBA's if hbas_to_enumerate is one,
+ * for other generation HBA's return with -ENODEV
+ */
+ if ((hbas_to_enumerate == 1) && (hba_mpi_version != MPI2_VERSION))
+ return -ENODEV;
+
+ /* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two,
+ * for other generation HBA's return with -ENODEV
+ */
+ if ((hbas_to_enumerate == 2) && (hba_mpi_version != MPI25_VERSION))
+ return -ENODEV;
+
+ switch (hba_mpi_version) {
+ case MPI2_VERSION:
+ /* Use mpt2sas driver host template for SAS 2.0 HBA's */
+ shost = scsi_host_alloc(&mpt2sas_driver_template,
+ sizeof(struct MPT3SAS_ADAPTER));
+ if (!shost)
+ return -ENODEV;
+ ioc = shost_priv(shost);
+ memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+ ioc->hba_mpi_version_belonged = hba_mpi_version;
+ ioc->id = mpt2_ids++;
+ sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
+ if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
+ ioc->is_warpdrive = 1;
+ ioc->hide_ir_msg = 1;
+ } else
+ ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
+ break;
+ case MPI25_VERSION:
+ /* Use mpt3sas driver host template for SAS 3.0 HBA's */
+ shost = scsi_host_alloc(&mpt3sas_driver_template,
+ sizeof(struct MPT3SAS_ADAPTER));
+ if (!shost)
+ return -ENODEV;
+ ioc = shost_priv(shost);
+ memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+ ioc->hba_mpi_version_belonged = hba_mpi_version;
+ ioc->id = mpt3_ids++;
+ sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME);
+ if (pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION)
+ ioc->msix96_vector = 1;
+ break;
+ default:
+ return -ENODEV;
+ }
+
INIT_LIST_HEAD(&ioc->list);
+ spin_lock(&gioc_lock);
list_add_tail(&ioc->list, &mpt3sas_ioc_list);
+ spin_unlock(&gioc_lock);
ioc->shost = shost;
- ioc->id = mpt_ids++;
- sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id);
ioc->pdev = pdev;
ioc->scsi_io_cb_idx = scsi_io_cb_idx;
ioc->tm_cb_idx = tm_cb_idx;
@@ -8030,6 +8517,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
/* misc semaphores and spin locks */
mutex_init(&ioc->reset_in_progress_mutex);
+ /* initializing pci_access_mutex lock */
+ mutex_init(&ioc->pci_access_mutex);
spin_lock_init(&ioc->ioc_reset_in_progress_lock);
spin_lock_init(&ioc->scsi_lookup_lock);
spin_lock_init(&ioc->sas_device_lock);
@@ -8048,6 +8537,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
INIT_LIST_HEAD(&ioc->reply_queue_list);
+ sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id);
+
/* init shost parameters */
shost->max_cmd_len = 32;
shost->max_lun = max_lun;
@@ -8086,7 +8577,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* event thread */
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
- "fw_event%d", ioc->id);
+ "fw_event_%s%d", ioc->driver_name, ioc->id);
ioc->firmware_event_thread = alloc_ordered_workqueue(
ioc->firmware_event_name, WQ_MEM_RECLAIM);
if (!ioc->firmware_event_thread) {
@@ -8103,6 +8594,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rv = -ENODEV;
goto out_attach_fail;
}
+
+ if (ioc->is_warpdrive) {
+ if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
+ ioc->hide_drives = 0;
+ else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
+ ioc->hide_drives = 1;
+ else {
+ if (mpt3sas_get_num_volumes(ioc))
+ ioc->hide_drives = 1;
+ else
+ ioc->hide_drives = 0;
+ }
+ } else
+ ioc->hide_drives = 0;
+
rv = scsi_add_host(shost, &pdev->dev);
if (rv) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
@@ -8117,21 +8623,23 @@ out_add_shost_fail:
out_attach_fail:
destroy_workqueue(ioc->firmware_event_thread);
out_thread_fail:
+ spin_lock(&gioc_lock);
list_del(&ioc->list);
+ spin_unlock(&gioc_lock);
scsi_host_put(shost);
return rv;
}
#ifdef CONFIG_PM
/**
- * _scsih_suspend - power management suspend main entry point
+ * scsih_suspend - power management suspend main entry point
* @pdev: PCI device struct
* @state: PM state change to (usually PCI_D3)
*
* Returns 0 success, anything else error.
*/
-static int
-_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
+int
+scsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8152,13 +8660,13 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
}
/**
- * _scsih_resume - power management resume main entry point
+ * scsih_resume - power management resume main entry point
* @pdev: PCI device struct
*
* Returns 0 success, anything else error.
*/
-static int
-_scsih_resume(struct pci_dev *pdev)
+int
+scsih_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8185,7 +8693,7 @@ _scsih_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
/**
- * _scsih_pci_error_detected - Called when a PCI error is detected.
+ * scsih_pci_error_detected - Called when a PCI error is detected.
* @pdev: PCI device struct
* @state: PCI channel state
*
@@ -8194,8 +8702,8 @@ _scsih_resume(struct pci_dev *pdev)
* Return value:
* PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
*/
-static pci_ers_result_t
-_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+pci_ers_result_t
+scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8224,15 +8732,15 @@ _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
}
/**
- * _scsih_pci_slot_reset - Called when PCI slot has been reset.
+ * scsih_pci_slot_reset - Called when PCI slot has been reset.
* @pdev: PCI device struct
*
* Description: This routine is called by the pci error recovery
* code after the PCI slot has been reset, just before we
* should resume normal operations.
*/
-static pci_ers_result_t
-_scsih_pci_slot_reset(struct pci_dev *pdev)
+pci_ers_result_t
+scsih_pci_slot_reset(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8261,15 +8769,15 @@ _scsih_pci_slot_reset(struct pci_dev *pdev)
}
/**
- * _scsih_pci_resume() - resume normal ops after PCI reset
+ * scsih_pci_resume() - resume normal ops after PCI reset
* @pdev: pointer to PCI device
*
* Called when the error recovery driver tells us that its
* OK to resume normal operation. Use completion to allow
* halted scsi ops to resume.
*/
-static void
-_scsih_pci_resume(struct pci_dev *pdev)
+void
+scsih_pci_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8282,11 +8790,11 @@ _scsih_pci_resume(struct pci_dev *pdev)
}
/**
- * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
+ * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
* @pdev: pointer to PCI device
*/
-static pci_ers_result_t
-_scsih_pci_mmio_enabled(struct pci_dev *pdev)
+pci_ers_result_t
+scsih_pci_mmio_enabled(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8300,61 +8808,99 @@ _scsih_pci_mmio_enabled(struct pci_dev *pdev)
return PCI_ERS_RESULT_NEED_RESET;
}
-/* raid transport support */
-static struct raid_function_template mpt3sas_raid_functions = {
- .cookie = &scsih_driver_template,
- .is_raid = _scsih_is_raid,
- .get_resync = _scsih_get_resync,
- .get_state = _scsih_get_state,
+/*
+ * The pci device ids are defined in mpi/mpi2_cnfg.h.
+ */
+static const struct pci_device_id mpt3sas_pci_table[] = {
+ /* Spitfire ~ 2004 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Falcon ~ 2008 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Liberator ~ 2108 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Meteor ~ 2116 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Thunderbolt ~ 2208 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Mustang ~ 2308 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* SSS6200 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Fury ~ 3004 and 3008 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Invader ~ 3108 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
+ PCI_ANY_ID, PCI_ANY_ID },
+ {0} /* Terminating entry */
};
+MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
-static struct pci_error_handlers _scsih_err_handler = {
- .error_detected = _scsih_pci_error_detected,
- .mmio_enabled = _scsih_pci_mmio_enabled,
- .slot_reset = _scsih_pci_slot_reset,
- .resume = _scsih_pci_resume,
+static struct pci_error_handlers _mpt3sas_err_handler = {
+ .error_detected = scsih_pci_error_detected,
+ .mmio_enabled = scsih_pci_mmio_enabled,
+ .slot_reset = scsih_pci_slot_reset,
+ .resume = scsih_pci_resume,
};
-static struct pci_driver scsih_driver = {
+static struct pci_driver mpt3sas_driver = {
.name = MPT3SAS_DRIVER_NAME,
- .id_table = scsih_pci_table,
+ .id_table = mpt3sas_pci_table,
.probe = _scsih_probe,
- .remove = _scsih_remove,
- .shutdown = _scsih_shutdown,
- .err_handler = &_scsih_err_handler,
+ .remove = scsih_remove,
+ .shutdown = scsih_shutdown,
+ .err_handler = &_mpt3sas_err_handler,
#ifdef CONFIG_PM
- .suspend = _scsih_suspend,
- .resume = _scsih_resume,
+ .suspend = scsih_suspend,
+ .resume = scsih_resume,
#endif
};
-
/**
- * _scsih_init - main entry point for this driver.
+ * scsih_init - main entry point for this driver.
*
* Returns 0 success, anything else error.
*/
-static int __init
-_scsih_init(void)
+int
+scsih_init(void)
{
- int error;
-
- mpt_ids = 0;
-
- pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
- MPT3SAS_DRIVER_VERSION);
-
- mpt3sas_transport_template =
- sas_attach_transport(&mpt3sas_transport_functions);
- if (!mpt3sas_transport_template)
- return -ENODEV;
-
-/* raid transport support */
- mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions);
- if (!mpt3sas_raid_template) {
- sas_release_transport(mpt3sas_transport_template);
- return -ENODEV;
- }
+ mpt2_ids = 0;
+ mpt3_ids = 0;
mpt3sas_base_initialize_callback_handler();
@@ -8392,33 +8938,17 @@ _scsih_init(void)
tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
_scsih_sas_control_complete);
- mpt3sas_ctl_init();
-
- error = pci_register_driver(&scsih_driver);
- if (error) {
- /* raid transport support */
- raid_class_release(mpt3sas_raid_template);
- sas_release_transport(mpt3sas_transport_template);
- }
-
- return error;
+ return 0;
}
/**
- * _scsih_exit - exit point for this driver (when it is a module).
+ * scsih_exit - exit point for this driver (when it is a module).
*
* Returns 0 success, anything else error.
*/
-static void __exit
-_scsih_exit(void)
+void
+scsih_exit(void)
{
- pr_info("mpt3sas version %s unloading\n",
- MPT3SAS_DRIVER_VERSION);
-
- mpt3sas_ctl_exit();
-
- pci_unregister_driver(&scsih_driver);
-
mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
mpt3sas_base_release_callback_handler(tm_cb_idx);
@@ -8434,9 +8964,86 @@ _scsih_exit(void)
mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
/* raid transport support */
- raid_class_release(mpt3sas_raid_template);
+ if (hbas_to_enumerate != 1)
+ raid_class_release(mpt3sas_raid_template);
+ if (hbas_to_enumerate != 2)
+ raid_class_release(mpt2sas_raid_template);
sas_release_transport(mpt3sas_transport_template);
}
-module_init(_scsih_init);
-module_exit(_scsih_exit);
+/**
+ * _mpt3sas_init - main entry point for this driver.
+ *
+ * Returns 0 success, anything else error.
+ */
+static int __init
+_mpt3sas_init(void)
+{
+ int error;
+
+ pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
+ MPT3SAS_DRIVER_VERSION);
+
+ mpt3sas_transport_template =
+ sas_attach_transport(&mpt3sas_transport_functions);
+ if (!mpt3sas_transport_template)
+ return -ENODEV;
+
+ /* No need attach mpt3sas raid functions template
+ * if hbas_to_enumarate value is one.
+ */
+ if (hbas_to_enumerate != 1) {
+ mpt3sas_raid_template =
+ raid_class_attach(&mpt3sas_raid_functions);
+ if (!mpt3sas_raid_template) {
+ sas_release_transport(mpt3sas_transport_template);
+ return -ENODEV;
+ }
+ }
+
+ /* No need to attach mpt2sas raid functions template
+ * if hbas_to_enumarate value is two
+ */
+ if (hbas_to_enumerate != 2) {
+ mpt2sas_raid_template =
+ raid_class_attach(&mpt2sas_raid_functions);
+ if (!mpt2sas_raid_template) {
+ sas_release_transport(mpt3sas_transport_template);
+ return -ENODEV;
+ }
+ }
+
+ error = scsih_init();
+ if (error) {
+ scsih_exit();
+ return error;
+ }
+
+ mpt3sas_ctl_init(hbas_to_enumerate);
+
+ error = pci_register_driver(&mpt3sas_driver);
+ if (error)
+ scsih_exit();
+
+ return error;
+}
+
+/**
+ * _mpt3sas_exit - exit point for this driver (when it is a module).
+ *
+ */
+static void __exit
+_mpt3sas_exit(void)
+{
+ pr_info("mpt3sas version %s unloading\n",
+ MPT3SAS_DRIVER_VERSION);
+
+ pci_unregister_driver(&mpt3sas_driver);
+
+ mpt3sas_ctl_exit(hbas_to_enumerate);
+
+ scsih_exit();
+}
+
+module_init(_mpt3sas_init);
+module_exit(_mpt3sas_exit);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 70fd019e7ee5..ca36d7ea0964 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -734,7 +734,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
rphy->identify = mpt3sas_port->remote_identify;
if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = mpt3sas_get_sdev_by_addr(ioc,
mpt3sas_port->remote_identify.sas_address);
if (!sas_device) {
dfailprintk(ioc, printk(MPT3SAS_FMT
@@ -750,8 +750,10 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
ioc->name, __FILE__, __LINE__, __func__);
}
- if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
+ if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
sas_device->pend_sas_rphy_add = 0;
+ sas_device_put(sas_device);
+ }
if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
dev_printk(KERN_INFO, &rphy->dev,
@@ -1324,15 +1326,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
int rc;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
rphy->identify.sas_address);
if (sas_device) {
*identifier = sas_device->enclosure_logical_id;
rc = 0;
+ sas_device_put(sas_device);
} else {
*identifier = 0;
rc = -ENXIO;
}
+
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return rc;
}
@@ -1352,12 +1356,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
int rc;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device = __mpt3sas_get_sdev_by_addr(ioc,
rphy->identify.sas_address);
- if (sas_device)
+ if (sas_device) {
rc = sas_device->slot;
- else
+ sas_device_put(sas_device);
+ } else {
rc = -ENXIO;
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return rc;
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
new file mode 100644
index 000000000000..540bd5005149
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
@@ -0,0 +1,344 @@
+/*
+ * Scsi Host Layer for MPT (Message Passing Technology) based controllers
+ *
+ * Copyright (C) 2012-2014 LSI Corporation
+ * Copyright (C) 2013-2015 Avago Technologies
+ * (mailto: MPT-FusionLinux.pdl@avagotech.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.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#include "mpt3sas_base.h"
+
+/**
+ * _warpdrive_disable_ddio - Disable direct I/O for all the volumes
+ * @ioc: per adapter object
+ */
+static void
+_warpdrive_disable_ddio(struct MPT3SAS_ADAPTER *ioc)
+{
+ Mpi2RaidVolPage1_t vol_pg1;
+ Mpi2ConfigReply_t mpi_reply;
+ struct _raid_device *raid_device;
+ u16 handle;
+ u16 ioc_status;
+ unsigned long flags;
+
+ handle = 0xFFFF;
+ while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+ &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ handle = le16_to_cpu(vol_pg1.DevHandle);
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
+ if (raid_device)
+ raid_device->direct_io_enabled = 0;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ }
+ return;
+}
+
+
+/**
+ * mpt3sas_get_num_volumes - Get number of volumes in the ioc
+ * @ioc: per adapter object
+ */
+u8
+mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc)
+{
+ Mpi2RaidVolPage1_t vol_pg1;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 handle;
+ u8 vol_cnt = 0;
+ u16 ioc_status;
+
+ handle = 0xFFFF;
+ while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+ &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ vol_cnt++;
+ handle = le16_to_cpu(vol_pg1.DevHandle);
+ }
+ return vol_cnt;
+}
+
+
+/**
+ * mpt3sas_init_warpdrive_properties - Set properties for warpdrive direct I/O.
+ * @ioc: per adapter object
+ * @raid_device: the raid_device object
+ */
+void
+mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
+ struct _raid_device *raid_device)
+{
+ Mpi2RaidVolPage0_t *vol_pg0;
+ Mpi2RaidPhysDiskPage0_t pd_pg0;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 sz;
+ u8 num_pds, count;
+ unsigned long stripe_sz, block_sz;
+ u8 stripe_exp, block_exp;
+ u64 dev_max_lba;
+
+ if (!ioc->is_warpdrive)
+ return;
+
+ if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "globally as drives are exposed\n", ioc->name);
+ return;
+ }
+ if (mpt3sas_get_num_volumes(ioc) > 1) {
+ _warpdrive_disable_ddio(ioc);
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "globally as number of drives > 1\n", ioc->name);
+ return;
+ }
+ if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
+ &num_pds)) || !num_pds) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "Failure in computing number of drives\n", ioc->name);
+ return;
+ }
+
+ sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
+ sizeof(Mpi2RaidVol0PhysDisk_t));
+ vol_pg0 = kzalloc(sz, GFP_KERNEL);
+ if (!vol_pg0) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "Memory allocation failure for RVPG0\n", ioc->name);
+ return;
+ }
+
+ if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
+ MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "Failure in retrieving RVPG0\n", ioc->name);
+ kfree(vol_pg0);
+ return;
+ }
+
+ /*
+ * WARPDRIVE:If number of physical disks in a volume exceeds the max pds
+ * assumed for WARPDRIVE, disable direct I/O
+ */
+ if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
+ pr_warn(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "for the drive with handle(0x%04x): num_mem=%d, "
+ "max_mem_allowed=%d\n", ioc->name, raid_device->handle,
+ num_pds, MPT_MAX_WARPDRIVE_PDS);
+ kfree(vol_pg0);
+ return;
+ }
+ for (count = 0; count < num_pds; count++) {
+ if (mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+ &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
+ vol_pg0->PhysDisk[count].PhysDiskNum) ||
+ pd_pg0.DevHandle == MPT3SAS_INVALID_DEVICE_HANDLE) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is "
+ "disabled for the drive with handle(0x%04x) member"
+ "handle retrieval failed for member number=%d\n",
+ ioc->name, raid_device->handle,
+ vol_pg0->PhysDisk[count].PhysDiskNum);
+ goto out_error;
+ }
+ /* Disable direct I/O if member drive lba exceeds 4 bytes */
+ dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA);
+ if (dev_max_lba >> 32) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is "
+ "disabled for the drive with handle(0x%04x) member"
+ " handle (0x%04x) unsupported max lba 0x%016llx\n",
+ ioc->name, raid_device->handle,
+ le16_to_cpu(pd_pg0.DevHandle),
+ (unsigned long long)dev_max_lba);
+ goto out_error;
+ }
+
+ raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
+ }
+
+ /*
+ * Assumption for WD: Direct I/O is not supported if the volume is
+ * not RAID0
+ */
+ if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "for the drive with handle(0x%04x): type=%d, "
+ "s_sz=%uK, blk_size=%u\n", ioc->name,
+ raid_device->handle, raid_device->volume_type,
+ (le32_to_cpu(vol_pg0->StripeSize) *
+ le16_to_cpu(vol_pg0->BlockSize)) / 1024,
+ le16_to_cpu(vol_pg0->BlockSize));
+ goto out_error;
+ }
+
+ stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
+ stripe_exp = find_first_bit(&stripe_sz, 32);
+ if (stripe_exp == 32) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "for the drive with handle(0x%04x) invalid stripe sz %uK\n",
+ ioc->name, raid_device->handle,
+ (le32_to_cpu(vol_pg0->StripeSize) *
+ le16_to_cpu(vol_pg0->BlockSize)) / 1024);
+ goto out_error;
+ }
+ raid_device->stripe_exponent = stripe_exp;
+ block_sz = le16_to_cpu(vol_pg0->BlockSize);
+ block_exp = find_first_bit(&block_sz, 16);
+ if (block_exp == 16) {
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+ "for the drive with handle(0x%04x) invalid block sz %u\n",
+ ioc->name, raid_device->handle,
+ le16_to_cpu(vol_pg0->BlockSize));
+ goto out_error;
+ }
+ raid_device->block_exponent = block_exp;
+ raid_device->direct_io_enabled = 1;
+
+ pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is Enabled for the drive"
+ " with handle(0x%04x)\n", ioc->name, raid_device->handle);
+ /*
+ * WARPDRIVE: Though the following fields are not used for direct IO,
+ * stored for future purpose:
+ */
+ raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
+ raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
+ raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
+
+
+ kfree(vol_pg0);
+ return;
+
+out_error:
+ raid_device->direct_io_enabled = 0;
+ for (count = 0; count < num_pds; count++)
+ raid_device->pd_handle[count] = 0;
+ kfree(vol_pg0);
+ return;
+}
+
+/**
+ * mpt3sas_scsi_direct_io_get - returns direct io flag
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns the smid stored scmd pointer.
+ */
+inline u8
+mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+ return ioc->scsi_lookup[smid - 1].direct_io;
+}
+
+/**
+ * mpt3sas_scsi_direct_io_set - sets direct io flag
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @direct_io: Zero or non-zero value to set in the direct_io flag
+ *
+ * Returns Nothing.
+ */
+inline void
+mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
+{
+ ioc->scsi_lookup[smid - 1].direct_io = direct_io;
+}
+
+/**
+ * mpt3sas_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ * @raid_device: pointer to raid device data structure
+ * @mpi_request: pointer to the SCSI_IO reqest message frame
+ * @smid: system request message index
+ *
+ * Returns nothing
+ */
+void
+mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+ struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
+ u16 smid)
+{
+ sector_t v_lba, p_lba, stripe_off, column, io_size;
+ u32 stripe_sz, stripe_exp;
+ u8 num_pds, cmd = scmd->cmnd[0];
+
+ if (cmd != READ_10 && cmd != WRITE_10 &&
+ cmd != READ_16 && cmd != WRITE_16)
+ return;
+
+ if (cmd == READ_10 || cmd == WRITE_10)
+ v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]);
+ else
+ v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]);
+
+ io_size = scsi_bufflen(scmd) >> raid_device->block_exponent;
+
+ if (v_lba + io_size - 1 > raid_device->max_lba)
+ return;
+
+ stripe_sz = raid_device->stripe_sz;
+ stripe_exp = raid_device->stripe_exponent;
+ stripe_off = v_lba & (stripe_sz - 1);
+
+ /* Return unless IO falls within a stripe */
+ if (stripe_off + io_size > stripe_sz)
+ return;
+
+ num_pds = raid_device->num_pds;
+ p_lba = v_lba >> stripe_exp;
+ column = sector_div(p_lba, num_pds);
+ p_lba = (p_lba << stripe_exp) + stripe_off;
+ mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]);
+
+ if (cmd == READ_10 || cmd == WRITE_10)
+ put_unaligned_be32(lower_32_bits(p_lba),
+ &mpi_request->CDB.CDB32[2]);
+ else
+ put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]);
+
+ mpt3sas_scsi_direct_io_set(ioc, smid, 1);
+}
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index e2d555c1bffc..90fdf0e859e3 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -65,7 +65,6 @@ static struct scsi_host_template mvs_sht = {
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = mvst_host_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -641,9 +640,9 @@ static void mvs_pci_remove(struct pci_dev *pdev)
tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
#endif
+ scsi_remove_host(mvi->shost);
sas_unregister_ha(sha);
sas_remove_host(mvi->shost);
- scsi_remove_host(mvi->shost);
MVS_CHIP_DISP->interrupt_disable(mvi);
free_irq(mvi->pdev->irq, sha);
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 454536c49315..9c780740fb82 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -887,6 +887,8 @@ static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
struct mvs_slot_info *slot, u32 slot_idx)
{
+ if (!slot)
+ return;
if (!slot->task)
return;
if (!sas_protocol_ata(task->task_proto))
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index 3e6b866759fe..02360de6b7e0 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -31,6 +31,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/ktime.h>
#include <linux/blkdev.h>
#include <linux/io.h>
#include <scsi/scsi.h>
@@ -858,8 +859,8 @@ static void mvumi_hs_build_page(struct mvumi_hba *mhba,
struct mvumi_hs_page2 *hs_page2;
struct mvumi_hs_page4 *hs_page4;
struct mvumi_hs_page3 *hs_page3;
- struct timeval time;
- unsigned int local_time;
+ u64 time;
+ u64 local_time;
switch (hs_header->page_code) {
case HS_PAGE_HOST_INFO:
@@ -877,9 +878,8 @@ static void mvumi_hs_build_page(struct mvumi_hba *mhba,
hs_page2->slot_number = 0;
hs_page2->intr_level = 0;
hs_page2->intr_vector = 0;
- do_gettimeofday(&time);
- local_time = (unsigned int) (time.tv_sec -
- (sys_tz.tz_minuteswest * 60));
+ time = ktime_get_real_seconds();
+ local_time = (time - (sys_tz.tz_minuteswest * 60));
hs_page2->seconds_since1970 = local_time;
hs_header->checksum = mvumi_calculate_checksum(hs_header,
hs_header->frame_length);
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index f14ec6e042b9..199527dbaaa1 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -51,6 +51,8 @@ enum chip_flavors {
chip_8076,
chip_8077,
chip_8006,
+ chip_8070,
+ chip_8072
};
enum phy_speed {
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 5c0356fb6310..062ab34b86f8 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -58,6 +58,8 @@ static const struct pm8001_chip_info pm8001_chips[] = {
[chip_8076] = {0, 16, &pm8001_80xx_dispatch,},
[chip_8077] = {0, 16, &pm8001_80xx_dispatch,},
[chip_8006] = {0, 16, &pm8001_80xx_dispatch,},
+ [chip_8070] = {0, 8, &pm8001_80xx_dispatch,},
+ [chip_8072] = {0, 16, &pm8001_80xx_dispatch,},
};
static int pm8001_id;
@@ -88,7 +90,6 @@ static struct scsi_host_template pm8001_sht = {
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = pm8001_host_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -480,7 +481,8 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
#ifdef PM8001_USE_TASKLET
/* Tasklet for non msi-x interrupt handler */
- if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+ if ((!pdev->msix_cap || !pci_msi_enabled())
+ || (pm8001_ha->chip_id == chip_8001))
tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
(unsigned long)&(pm8001_ha->irq_vector[0]));
else
@@ -634,6 +636,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
payload.minor_function = 0;
payload.length = 128;
}
+ } else if ((pm8001_ha->chip_id == chip_8070 ||
+ pm8001_ha->chip_id == chip_8072) &&
+ pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
+ payload.minor_function = 4;
+ payload.length = 4096;
} else {
payload.minor_function = 1;
payload.length = 4096;
@@ -660,6 +667,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
else if (deviceid == 0x0042)
pm8001_ha->sas_addr[j] =
payload.func_specific[0x010 + i];
+ } else if ((pm8001_ha->chip_id == chip_8070 ||
+ pm8001_ha->chip_id == chip_8072) &&
+ pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
+ pm8001_ha->sas_addr[j] =
+ payload.func_specific[0x010 + i];
} else
pm8001_ha->sas_addr[j] =
payload.func_specific[0x804 + i];
@@ -720,6 +732,153 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
return 0;
}
+struct pm8001_mpi3_phy_pg_trx_config {
+ u32 LaneLosCfg;
+ u32 LanePgaCfg1;
+ u32 LanePisoCfg1;
+ u32 LanePisoCfg2;
+ u32 LanePisoCfg3;
+ u32 LanePisoCfg4;
+ u32 LanePisoCfg5;
+ u32 LanePisoCfg6;
+ u32 LaneBctCtrl;
+};
+
+/**
+ * pm8001_get_internal_phy_settings : Retrieves the internal PHY settings
+ * @pm8001_ha : our adapter
+ * @phycfg : PHY config page to populate
+ */
+static
+void pm8001_get_internal_phy_settings(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_mpi3_phy_pg_trx_config *phycfg)
+{
+ phycfg->LaneLosCfg = 0x00000132;
+ phycfg->LanePgaCfg1 = 0x00203949;
+ phycfg->LanePisoCfg1 = 0x000000FF;
+ phycfg->LanePisoCfg2 = 0xFF000001;
+ phycfg->LanePisoCfg3 = 0xE7011300;
+ phycfg->LanePisoCfg4 = 0x631C40C0;
+ phycfg->LanePisoCfg5 = 0xF8102036;
+ phycfg->LanePisoCfg6 = 0xF74A1000;
+ phycfg->LaneBctCtrl = 0x00FB33F8;
+}
+
+/**
+ * pm8001_get_external_phy_settings : Retrieves the external PHY settings
+ * @pm8001_ha : our adapter
+ * @phycfg : PHY config page to populate
+ */
+static
+void pm8001_get_external_phy_settings(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_mpi3_phy_pg_trx_config *phycfg)
+{
+ phycfg->LaneLosCfg = 0x00000132;
+ phycfg->LanePgaCfg1 = 0x00203949;
+ phycfg->LanePisoCfg1 = 0x000000FF;
+ phycfg->LanePisoCfg2 = 0xFF000001;
+ phycfg->LanePisoCfg3 = 0xE7011300;
+ phycfg->LanePisoCfg4 = 0x63349140;
+ phycfg->LanePisoCfg5 = 0xF8102036;
+ phycfg->LanePisoCfg6 = 0xF80D9300;
+ phycfg->LaneBctCtrl = 0x00FB33F8;
+}
+
+/**
+ * pm8001_get_phy_mask : Retrieves the mask that denotes if a PHY is int/ext
+ * @pm8001_ha : our adapter
+ * @phymask : The PHY mask
+ */
+static
+void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask)
+{
+ switch (pm8001_ha->pdev->subsystem_device) {
+ case 0x0070: /* H1280 - 8 external 0 internal */
+ case 0x0072: /* H12F0 - 16 external 0 internal */
+ *phymask = 0x0000;
+ break;
+
+ case 0x0071: /* H1208 - 0 external 8 internal */
+ case 0x0073: /* H120F - 0 external 16 internal */
+ *phymask = 0xFFFF;
+ break;
+
+ case 0x0080: /* H1244 - 4 external 4 internal */
+ *phymask = 0x00F0;
+ break;
+
+ case 0x0081: /* H1248 - 4 external 8 internal */
+ *phymask = 0x0FF0;
+ break;
+
+ case 0x0082: /* H1288 - 8 external 8 internal */
+ *phymask = 0xFF00;
+ break;
+
+ default:
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("Unknown subsystem device=0x%.04x",
+ pm8001_ha->pdev->subsystem_device));
+ }
+}
+
+/**
+ * pm8001_set_phy_settings_ven_117c_12Gb : Configure ATTO 12Gb PHY settings
+ * @pm8001_ha : our adapter
+ */
+static
+int pm8001_set_phy_settings_ven_117c_12G(struct pm8001_hba_info *pm8001_ha)
+{
+ struct pm8001_mpi3_phy_pg_trx_config phycfg_int;
+ struct pm8001_mpi3_phy_pg_trx_config phycfg_ext;
+ int phymask = 0;
+ int i = 0;
+
+ memset(&phycfg_int, 0, sizeof(phycfg_int));
+ memset(&phycfg_ext, 0, sizeof(phycfg_ext));
+
+ pm8001_get_internal_phy_settings(pm8001_ha, &phycfg_int);
+ pm8001_get_external_phy_settings(pm8001_ha, &phycfg_ext);
+ pm8001_get_phy_mask(pm8001_ha, &phymask);
+
+ for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+ if (phymask & (1 << i)) {/* Internal PHY */
+ pm8001_set_phy_profile_single(pm8001_ha, i,
+ sizeof(phycfg_int) / sizeof(u32),
+ (u32 *)&phycfg_int);
+
+ } else { /* External PHY */
+ pm8001_set_phy_profile_single(pm8001_ha, i,
+ sizeof(phycfg_ext) / sizeof(u32),
+ (u32 *)&phycfg_ext);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * pm8001_configure_phy_settings : Configures PHY settings based on vendor ID.
+ * @pm8001_ha : our hba.
+ */
+static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
+{
+ switch (pm8001_ha->pdev->subsystem_vendor) {
+ case PCI_VENDOR_ID_ATTO:
+ if (pm8001_ha->pdev->device == 0x0042) /* 6Gb */
+ return 0;
+ else
+ return pm8001_set_phy_settings_ven_117c_12G(pm8001_ha);
+
+ case PCI_VENDOR_ID_ADAPTEC2:
+ case 0:
+ return 0;
+
+ default:
+ return pm8001_get_phy_settings_info(pm8001_ha);
+ }
+}
+
#ifdef PM8001_USE_MSIX
/**
* pm8001_setup_msix - enable MSI-X interrupt
@@ -792,7 +951,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
pdev = pm8001_ha->pdev;
#ifdef PM8001_USE_MSIX
- if (pdev->msix_cap)
+ if (pdev->msix_cap && pci_msi_enabled())
return pm8001_setup_msix(pm8001_ha);
else {
PM8001_INIT_DBG(pm8001_ha,
@@ -803,6 +962,8 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
intx:
/* initialize the INT-X interrupt */
+ pm8001_ha->irq_vector[0].irq_id = 0;
+ pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
return rc;
@@ -902,12 +1063,9 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
pm8001_init_sas_add(pm8001_ha);
/* phy setting support for motherboard controller */
- if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 &&
- pdev->subsystem_vendor != 0) {
- rc = pm8001_get_phy_settings_info(pm8001_ha);
- if (rc)
- goto err_out_shost;
- }
+ if (pm8001_configure_phy_settings(pm8001_ha))
+ goto err_out_shost;
+
pm8001_post_sas_ha_init(shost, chip);
rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
if (rc)
@@ -937,10 +1095,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
struct pm8001_hba_info *pm8001_ha;
int i, j;
pm8001_ha = sha->lldd_ha;
+ scsi_remove_host(pm8001_ha->shost);
sas_unregister_ha(sha);
sas_remove_host(pm8001_ha->shost);
list_del(&pm8001_ha->list);
- scsi_remove_host(pm8001_ha->shost);
PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
@@ -956,7 +1114,8 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
#endif
#ifdef PM8001_USE_TASKLET
/* For non-msix and msix interrupts */
- if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+ if ((!pdev->msix_cap || !pci_msi_enabled()) ||
+ (pm8001_ha->chip_id == chip_8001))
tasklet_kill(&pm8001_ha->tasklet[0]);
else
for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
@@ -1005,7 +1164,8 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
#endif
#ifdef PM8001_USE_TASKLET
/* For non-msix and msix interrupts */
- if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+ if ((!pdev->msix_cap || !pci_msi_enabled()) ||
+ (pm8001_ha->chip_id == chip_8001))
tasklet_kill(&pm8001_ha->tasklet[0]);
else
for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
@@ -1074,7 +1234,8 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
goto err_out_disable;
#ifdef PM8001_USE_TASKLET
/* Tasklet for non msi-x interrupt handler */
- if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+ if ((!pdev->msix_cap || !pci_msi_enabled()) ||
+ (pm8001_ha->chip_id == chip_8001))
tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
(unsigned long)&(pm8001_ha->irq_vector[0]));
else
@@ -1087,6 +1248,19 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
for (i = 1; i < pm8001_ha->number_of_intr; i++)
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
}
+
+ /* Chip documentation for the 8070 and 8072 SPCv */
+ /* states that a 500ms minimum delay is required */
+ /* before issuing commands. Otherwise, the firmare */
+ /* will enter an unrecoverable state. */
+
+ if (pm8001_ha->chip_id == chip_8070 ||
+ pm8001_ha->chip_id == chip_8072) {
+ mdelay(500);
+ }
+
+ /* Spin up the PHYs */
+
pm8001_ha->flags = PM8001F_RUN_TIME;
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
pm8001_ha->phy[i].enable_completion = &completion;
@@ -1165,6 +1339,20 @@ static struct pci_device_id pm8001_pci_table[] = {
PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 },
{ PCI_VENDOR_ID_ADAPTEC2, 0x8074,
PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 },
+ { PCI_VENDOR_ID_ATTO, 0x8070,
+ PCI_VENDOR_ID_ATTO, 0x0070, 0, 0, chip_8070 },
+ { PCI_VENDOR_ID_ATTO, 0x8070,
+ PCI_VENDOR_ID_ATTO, 0x0071, 0, 0, chip_8070 },
+ { PCI_VENDOR_ID_ATTO, 0x8072,
+ PCI_VENDOR_ID_ATTO, 0x0072, 0, 0, chip_8072 },
+ { PCI_VENDOR_ID_ATTO, 0x8072,
+ PCI_VENDOR_ID_ATTO, 0x0073, 0, 0, chip_8072 },
+ { PCI_VENDOR_ID_ATTO, 0x8070,
+ PCI_VENDOR_ID_ATTO, 0x0080, 0, 0, chip_8070 },
+ { PCI_VENDOR_ID_ATTO, 0x8072,
+ PCI_VENDOR_ID_ATTO, 0x0081, 0, 0, chip_8072 },
+ { PCI_VENDOR_ID_ATTO, 0x8072,
+ PCI_VENDOR_ID_ATTO, 0x0082, 0, 0, chip_8072 },
{} /* terminate list */
};
@@ -1220,7 +1408,7 @@ MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
MODULE_DESCRIPTION(
- "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077 "
+ "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077/8070/8072 "
"SAS/SATA controller driver");
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index e2e97db38ae8..6628cc38316c 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -106,7 +106,9 @@ do { \
#define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
#define IS_SPCV_12G(dev) ((dev->device == 0X8074) \
|| (dev->device == 0X8076) \
- || (dev->device == 0X8077))
+ || (dev->device == 0X8077) \
+ || (dev->device == 0X8070) \
+ || (dev->device == 0X8072))
#define PM8001_NAME_LENGTH 32/* generic length of strings */
extern struct list_head hba_list;
@@ -708,6 +710,8 @@ int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
u32 length, u8 *buf);
+void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
+ u32 phy, u32 length, u32 *buf);
int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
ssize_t pm80xx_get_fatal_dump(struct device *cdev,
struct device_attribute *attr, char *buf);
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 9a389f1508de..eb4fee61df72 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1267,6 +1267,8 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
/* check iButton feature support for motherboard controller */
if (pm8001_ha->pdev->subsystem_vendor !=
PCI_VENDOR_ID_ADAPTEC2 &&
+ pm8001_ha->pdev->subsystem_vendor !=
+ PCI_VENDOR_ID_ATTO &&
pm8001_ha->pdev->subsystem_vendor != 0) {
ibutton0 = pm8001_cr32(pm8001_ha, 0,
MSGU_HOST_SCRATCH_PAD_6);
@@ -4576,6 +4578,38 @@ void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
}
PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n"));
}
+
+void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
+ u32 phy, u32 length, u32 *buf)
+{
+ u32 tag, opc;
+ int rc, i;
+ struct set_phy_profile_req payload;
+ struct inbound_queue_table *circularQ;
+
+ memset(&payload, 0, sizeof(payload));
+
+ rc = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (rc)
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Invalid tag"));
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ opc = OPC_INB_SET_PHY_PROFILE;
+
+ payload.tag = cpu_to_le32(tag);
+ payload.ppc_phyid = (((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8)
+ | (phy & 0xFF));
+
+ for (i = 0; i < length; i++)
+ payload.reserved[i] = cpu_to_le32(*(buf + i));
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ if (rc)
+ pm8001_tag_free(pm8001_ha, tag);
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("PHY %d settings applied", phy));
+}
const struct pm8001_dispatch pm8001_80xx_dispatch = {
.name = "pmc80xx",
.chip_init = pm80xx_chip_init,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index ed31d8cc6266..b2a88200fe54 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -45,6 +45,7 @@
#include <asm/processor.h>
#include <linux/libata.h>
#include <linux/mutex.h>
+#include <linux/ktime.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
@@ -4254,7 +4255,6 @@ static struct scsi_host_template pmcraid_host_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = pmcraid_host_attrs,
.proc_name = PMCRAID_DRIVER_NAME,
- .use_blk_tags = 1,
};
/*
@@ -5563,11 +5563,9 @@ static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd)
__be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN);
struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl;
- struct timeval tv;
__le64 timestamp;
- do_gettimeofday(&tv);
- timestamp = tv.tv_sec * 1000;
+ timestamp = ktime_get_real_seconds() * 1000;
pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp);
pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index c2dd17b1d26f..bfa9a64c316b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -267,7 +267,6 @@ struct scsi_host_template qla2xxx_driver_template = {
.shost_attrs = qla2x00_host_attrs,
.supported_mode = MODE_INITIATOR,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index ac65cb7b4886..3ba2e9564b9a 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -43,8 +43,6 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include "qla_def.h"
#include "qla_target.h"
@@ -729,23 +727,23 @@ static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl,
#define DEF_QLA_TPG_ATTRIB(name) \
\
-static ssize_t tcm_qla2xxx_tpg_attrib_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
+static ssize_t tcm_qla2xxx_tpg_attrib_##name##_show( \
+ struct config_item *item, char *page) \
{ \
+ struct se_portal_group *se_tpg = attrib_to_tpg(item); \
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \
struct tcm_qla2xxx_tpg, se_tpg); \
\
return sprintf(page, "%u\n", tpg->tpg_attrib.name); \
} \
\
-static ssize_t tcm_qla2xxx_tpg_attrib_store_##name( \
- struct se_portal_group *se_tpg, \
- const char *page, \
- size_t count) \
+static ssize_t tcm_qla2xxx_tpg_attrib_##name##_store( \
+ struct config_item *item, const char *page, size_t count) \
{ \
+ struct se_portal_group *se_tpg = attrib_to_tpg(item); \
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \
struct tcm_qla2xxx_tpg, se_tpg); \
+ struct tcm_qla2xxx_tpg_attrib *a = &tpg->tpg_attrib; \
unsigned long val; \
int ret; \
\
@@ -755,81 +753,39 @@ static ssize_t tcm_qla2xxx_tpg_attrib_store_##name( \
" ret: %d\n", ret); \
return -EINVAL; \
} \
- ret = tcm_qla2xxx_set_attrib_##name(tpg, val); \
- \
- return (!ret) ? count : -EINVAL; \
-}
-
-#define DEF_QLA_TPG_ATTR_BOOL(_name) \
- \
-static int tcm_qla2xxx_set_attrib_##_name( \
- struct tcm_qla2xxx_tpg *tpg, \
- unsigned long val) \
-{ \
- struct tcm_qla2xxx_tpg_attrib *a = &tpg->tpg_attrib; \
\
if ((val != 0) && (val != 1)) { \
pr_err("Illegal boolean value %lu\n", val); \
return -EINVAL; \
} \
\
- a->_name = val; \
- return 0; \
-}
-
-#define QLA_TPG_ATTR(_name, _mode) \
- TF_TPG_ATTRIB_ATTR(tcm_qla2xxx, _name, _mode);
+ a->name = val; \
+ \
+ return count; \
+} \
+CONFIGFS_ATTR(tcm_qla2xxx_tpg_attrib_, name)
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_generate_node_acls
- */
-DEF_QLA_TPG_ATTR_BOOL(generate_node_acls);
DEF_QLA_TPG_ATTRIB(generate_node_acls);
-QLA_TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR);
-
-/*
- Define tcm_qla2xxx_attrib_s_cache_dynamic_acls
- */
-DEF_QLA_TPG_ATTR_BOOL(cache_dynamic_acls);
DEF_QLA_TPG_ATTRIB(cache_dynamic_acls);
-QLA_TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR);
-
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_demo_mode_write_protect
- */
-DEF_QLA_TPG_ATTR_BOOL(demo_mode_write_protect);
DEF_QLA_TPG_ATTRIB(demo_mode_write_protect);
-QLA_TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR);
-
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_prod_mode_write_protect
- */
-DEF_QLA_TPG_ATTR_BOOL(prod_mode_write_protect);
DEF_QLA_TPG_ATTRIB(prod_mode_write_protect);
-QLA_TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR);
-
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_demo_mode_login_only
- */
-DEF_QLA_TPG_ATTR_BOOL(demo_mode_login_only);
DEF_QLA_TPG_ATTRIB(demo_mode_login_only);
-QLA_TPG_ATTR(demo_mode_login_only, S_IRUGO | S_IWUSR);
static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = {
- &tcm_qla2xxx_tpg_attrib_generate_node_acls.attr,
- &tcm_qla2xxx_tpg_attrib_cache_dynamic_acls.attr,
- &tcm_qla2xxx_tpg_attrib_demo_mode_write_protect.attr,
- &tcm_qla2xxx_tpg_attrib_prod_mode_write_protect.attr,
- &tcm_qla2xxx_tpg_attrib_demo_mode_login_only.attr,
+ &tcm_qla2xxx_tpg_attrib_attr_generate_node_acls,
+ &tcm_qla2xxx_tpg_attrib_attr_cache_dynamic_acls,
+ &tcm_qla2xxx_tpg_attrib_attr_demo_mode_write_protect,
+ &tcm_qla2xxx_tpg_attrib_attr_prod_mode_write_protect,
+ &tcm_qla2xxx_tpg_attrib_attr_demo_mode_login_only,
NULL,
};
/* End items for tcm_qla2xxx_tpg_attrib_cit */
-static ssize_t tcm_qla2xxx_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_qla2xxx_tpg_enable_show(struct config_item *item,
+ char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
@@ -865,11 +821,10 @@ static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)
complete(&base_tpg->tpg_base_comp);
}
-static ssize_t tcm_qla2xxx_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_qla2xxx_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
unsigned long op;
@@ -909,22 +864,16 @@ static ssize_t tcm_qla2xxx_tpg_store_enable(
return count;
}
-TF_TPG_BASE_ATTR(tcm_qla2xxx, enable, S_IRUGO | S_IWUSR);
-
-static ssize_t tcm_qla2xxx_tpg_show_dynamic_sessions(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_qla2xxx_tpg_dynamic_sessions_show(struct config_item *item,
+ char *page)
{
- return target_show_dynamic_sessions(se_tpg, page);
+ return target_show_dynamic_sessions(to_tpg(item), page);
}
-TF_TPG_BASE_ATTR_RO(tcm_qla2xxx, dynamic_sessions);
-
-static ssize_t tcm_qla2xxx_tpg_store_fabric_prot_type(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
unsigned long val;
@@ -943,21 +892,24 @@ static ssize_t tcm_qla2xxx_tpg_store_fabric_prot_type(
return count;
}
-static ssize_t tcm_qla2xxx_tpg_show_fabric_prot_type(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_show(struct config_item *item,
+ char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type);
}
-TF_TPG_BASE_ATTR(tcm_qla2xxx, fabric_prot_type, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR_WO(tcm_qla2xxx_tpg_, enable);
+CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions);
+CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type);
static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = {
- &tcm_qla2xxx_tpg_enable.attr,
- &tcm_qla2xxx_tpg_dynamic_sessions.attr,
- &tcm_qla2xxx_tpg_fabric_prot_type.attr,
+ &tcm_qla2xxx_tpg_attr_enable,
+ &tcm_qla2xxx_tpg_attr_dynamic_sessions,
+ &tcm_qla2xxx_tpg_attr_fabric_prot_type,
NULL,
};
@@ -1030,18 +982,16 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg)
kfree(tpg);
}
-static ssize_t tcm_qla2xxx_npiv_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_qla2xxx_npiv_tpg_enable_show(struct config_item *item,
+ char *page)
{
- return tcm_qla2xxx_tpg_show_enable(se_tpg, page);
+ return tcm_qla2xxx_tpg_enable_show(item, page);
}
-static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_qla2xxx_npiv_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
struct tcm_qla2xxx_lport, lport_wwn);
@@ -1077,10 +1027,10 @@ static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
return count;
}
-TF_TPG_BASE_ATTR(tcm_qla2xxx_npiv, enable, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(tcm_qla2xxx_npiv_tpg_, enable);
static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = {
- &tcm_qla2xxx_npiv_tpg_enable.attr,
+ &tcm_qla2xxx_npiv_tpg_attr_enable,
NULL,
};
@@ -1783,9 +1733,8 @@ static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn)
}
-static ssize_t tcm_qla2xxx_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t tcm_qla2xxx_wwn_version_show(struct config_item *item,
+ char *page)
{
return sprintf(page,
"TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on "
@@ -1793,10 +1742,10 @@ static ssize_t tcm_qla2xxx_wwn_show_attr_version(
utsname()->machine);
}
-TF_WWN_ATTR_RO(tcm_qla2xxx, version);
+CONFIGFS_ATTR_RO(tcm_qla2xxx_wwn_, version);
static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = {
- &tcm_qla2xxx_wwn_version.attr,
+ &tcm_qla2xxx_wwn_attr_version,
NULL,
};
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 7c3365864242..ae87d6c19f17 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -12,7 +12,7 @@
#include "ql4_glbl.h"
#include "ql4_inline.h"
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#define TIMEOUT_100_MS 100
#define MASK(n) DMA_BIT_MASK(n)
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 6d25879d87c8..01c3610a60cf 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -212,7 +212,6 @@ static struct scsi_host_template qla4xxx_driver_template = {
.shost_attrs = qla4xxx_host_attrs,
.host_reset = qla4xxx_host_reset,
.vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
- .use_blk_tags = 1,
};
static struct iscsi_transport qla4xxx_iscsi_transport = {
@@ -8697,13 +8696,6 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev,
host->can_queue = MAX_SRBS ;
host->transportt = qla4xxx_scsi_transport;
- ret = scsi_init_shared_tag_map(host, MAX_SRBS);
- if (ret) {
- ql4_printk(KERN_WARNING, ha,
- "%s: scsi_init_shared_tag_map failed\n", __func__);
- goto probe_failed;
- }
-
pci_set_drvdata(pdev, ha);
ret = scsi_add_host(host, &pdev->dev);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 207d6a7a1bd0..d07fb653f5dc 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -616,32 +616,11 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
*/
int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
{
- unsigned long flags;
-
- if (depth <= 0)
- goto out;
-
- spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-
- /*
- * Check to see if the queue is managed by the block layer.
- * If it is, and we fail to adjust the depth, exit.
- *
- * Do not resize the tag map if it is a host wide share bqt,
- * because the size should be the hosts's can_queue. If there
- * is more IO than the LLD's can_queue (so there are not enuogh
- * tags) request_fn's host queue ready check will handle it.
- */
- if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
- if (blk_queue_tagged(sdev->request_queue) &&
- blk_queue_resize_tags(sdev->request_queue, depth) != 0)
- goto out_unlock;
+ if (depth > 0) {
+ sdev->queue_depth = depth;
+ wmb();
}
- sdev->queue_depth = depth;
-out_unlock:
- spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-out:
return sdev->queue_depth;
}
EXPORT_SYMBOL(scsi_change_queue_depth);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 9f77d23239a2..2c1160c7ec92 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -390,25 +390,57 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
/**
- * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
+ * scsi_dev_info_list_find - find a matching dev_info list entry.
* @vendor: vendor string
* @model: model (product) string
* @key: specify list to use
*
* Description:
- * Remove and destroy one dev_info entry for @vendor, @model
+ * Finds the first dev_info entry matching @vendor, @model
* in list specified by @key.
*
- * Returns: 0 OK, -error on failure.
+ * Returns: pointer to matching entry, or ERR_PTR on failure.
**/
-int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
+static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
+ const char *model, int key)
{
- struct scsi_dev_info_list *devinfo, *found = NULL;
+ struct scsi_dev_info_list *devinfo;
struct scsi_dev_info_list_table *devinfo_table =
scsi_devinfo_lookup_by_key(key);
+ size_t vmax, mmax;
+ const char *vskip, *mskip;
if (IS_ERR(devinfo_table))
- return PTR_ERR(devinfo_table);
+ return (struct scsi_dev_info_list *) devinfo_table;
+
+ /* Prepare for "compatible" matches */
+
+ /*
+ * XXX why skip leading spaces? If an odd INQUIRY
+ * value, that should have been part of the
+ * scsi_static_device_list[] entry, such as " FOO"
+ * rather than "FOO". Since this code is already
+ * here, and we don't know what device it is
+ * trying to work with, leave it as-is.
+ */
+ vmax = 8; /* max length of vendor */
+ vskip = vendor;
+ while (vmax > 0 && *vskip == ' ') {
+ vmax--;
+ vskip++;
+ }
+ /* Also skip trailing spaces */
+ while (vmax > 0 && vskip[vmax - 1] == ' ')
+ --vmax;
+
+ mmax = 16; /* max length of model */
+ mskip = model;
+ while (mmax > 0 && *mskip == ' ') {
+ mmax--;
+ mskip++;
+ }
+ while (mmax > 0 && mskip[mmax - 1] == ' ')
+ --mmax;
list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
dev_info_list) {
@@ -416,61 +448,48 @@ int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
/*
* Behave like the older version of get_device_flags.
*/
- size_t max;
- /*
- * XXX why skip leading spaces? If an odd INQUIRY
- * value, that should have been part of the
- * scsi_static_device_list[] entry, such as " FOO"
- * rather than "FOO". Since this code is already
- * here, and we don't know what device it is
- * trying to work with, leave it as-is.
- */
- max = 8; /* max length of vendor */
- while ((max > 0) && *vendor == ' ') {
- max--;
- vendor++;
- }
- /*
- * XXX removing the following strlen() would be
- * good, using it means that for a an entry not in
- * the list, we scan every byte of every vendor
- * listed in scsi_static_device_list[], and never match
- * a single one (and still have to compare at
- * least the first byte of each vendor).
- */
- if (memcmp(devinfo->vendor, vendor,
- min(max, strlen(devinfo->vendor))))
+ if (memcmp(devinfo->vendor, vskip, vmax) ||
+ devinfo->vendor[vmax])
continue;
- /*
- * Skip spaces again.
- */
- max = 16; /* max length of model */
- while ((max > 0) && *model == ' ') {
- max--;
- model++;
- }
- if (memcmp(devinfo->model, model,
- min(max, strlen(devinfo->model))))
+ if (memcmp(devinfo->model, mskip, mmax) ||
+ devinfo->model[mmax])
continue;
- found = devinfo;
+ return devinfo;
} else {
if (!memcmp(devinfo->vendor, vendor,
sizeof(devinfo->vendor)) &&
!memcmp(devinfo->model, model,
sizeof(devinfo->model)))
- found = devinfo;
+ return devinfo;
}
- if (found)
- break;
}
- if (found) {
- list_del(&found->dev_info_list);
- kfree(found);
- return 0;
- }
+ return ERR_PTR(-ENOENT);
+}
+
+/**
+ * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
+ * @vendor: vendor string
+ * @model: model (product) string
+ * @key: specify list to use
+ *
+ * Description:
+ * Remove and destroy one dev_info entry for @vendor, @model
+ * in list specified by @key.
+ *
+ * Returns: 0 OK, -error on failure.
+ **/
+int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
+{
+ struct scsi_dev_info_list *found;
- return -ENOENT;
+ found = scsi_dev_info_list_find(vendor, model, key);
+ if (IS_ERR(found))
+ return PTR_ERR(found);
+
+ list_del(&found->dev_info_list);
+ kfree(found);
+ return 0;
}
EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
@@ -565,64 +584,16 @@ int scsi_get_device_flags_keyed(struct scsi_device *sdev,
int key)
{
struct scsi_dev_info_list *devinfo;
- struct scsi_dev_info_list_table *devinfo_table;
+ int err;
- devinfo_table = scsi_devinfo_lookup_by_key(key);
+ devinfo = scsi_dev_info_list_find(vendor, model, key);
+ if (!IS_ERR(devinfo))
+ return devinfo->flags;
- if (IS_ERR(devinfo_table))
- return PTR_ERR(devinfo_table);
+ err = PTR_ERR(devinfo);
+ if (err != -ENOENT)
+ return err;
- list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
- dev_info_list) {
- if (devinfo->compatible) {
- /*
- * Behave like the older version of get_device_flags.
- */
- size_t max;
- /*
- * XXX why skip leading spaces? If an odd INQUIRY
- * value, that should have been part of the
- * scsi_static_device_list[] entry, such as " FOO"
- * rather than "FOO". Since this code is already
- * here, and we don't know what device it is
- * trying to work with, leave it as-is.
- */
- max = 8; /* max length of vendor */
- while ((max > 0) && *vendor == ' ') {
- max--;
- vendor++;
- }
- /*
- * XXX removing the following strlen() would be
- * good, using it means that for a an entry not in
- * the list, we scan every byte of every vendor
- * listed in scsi_static_device_list[], and never match
- * a single one (and still have to compare at
- * least the first byte of each vendor).
- */
- if (memcmp(devinfo->vendor, vendor,
- min(max, strlen(devinfo->vendor))))
- continue;
- /*
- * Skip spaces again.
- */
- max = 16; /* max length of model */
- while ((max > 0) && *model == ' ') {
- max--;
- model++;
- }
- if (memcmp(devinfo->model, model,
- min(max, strlen(devinfo->model))))
- continue;
- return devinfo->flags;
- } else {
- if (!memcmp(devinfo->vendor, vendor,
- sizeof(devinfo->vendor)) &&
- !memcmp(devinfo->model, model,
- sizeof(devinfo->model)))
- return devinfo->flags;
- }
- }
/* nothing found, return nothing */
if (key != SCSI_DEVINFO_GLOBAL)
return 0;
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 0a2168e69bbc..e7649ed3f667 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -226,16 +226,20 @@ int scsi_dh_add_device(struct scsi_device *sdev)
drv = scsi_dh_find_driver(sdev);
if (drv)
- devinfo = scsi_dh_lookup(drv);
+ devinfo = __scsi_dh_lookup(drv);
if (devinfo)
err = scsi_dh_handler_attach(sdev, devinfo);
return err;
}
-void scsi_dh_remove_device(struct scsi_device *sdev)
+void scsi_dh_release_device(struct scsi_device *sdev)
{
if (sdev->handler)
scsi_dh_handler_detach(sdev);
+}
+
+void scsi_dh_remove_device(struct scsi_device *sdev)
+{
device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 66a96cd98b97..984ddcb4786d 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1970,7 +1970,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
struct request *req;
/*
- * blk_get_request with GFP_KERNEL (__GFP_WAIT) sleeps until a
+ * blk_get_request with GFP_KERNEL (__GFP_RECLAIM) sleeps until a
* request becomes available
*/
req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 126a48c6431e..dd8ad2a44510 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -222,13 +222,13 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
int write = (data_direction == DMA_TO_DEVICE);
int ret = DRIVER_ERROR << 24;
- req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
+ req = blk_get_request(sdev->request_queue, write, __GFP_RECLAIM);
if (IS_ERR(req))
return ret;
blk_rq_set_block_pc(req);
if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
- buffer, bufflen, __GFP_WAIT))
+ buffer, bufflen, __GFP_RECLAIM))
goto out;
req->cmd_len = COMMAND_SIZE(cmd[0]);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 644bb7339b55..4d01cdb1b348 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -173,9 +173,11 @@ extern struct async_domain scsi_sd_probe_domain;
/* scsi_dh.c */
#ifdef CONFIG_SCSI_DH
int scsi_dh_add_device(struct scsi_device *sdev);
+void scsi_dh_release_device(struct scsi_device *sdev);
void scsi_dh_remove_device(struct scsi_device *sdev);
#else
static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; }
+static inline void scsi_dh_release_device(struct scsi_device *sdev) { }
static inline void scsi_dh_remove_device(struct scsi_device *sdev) { }
#endif
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f9f3f8203d42..83245391e956 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -55,6 +55,7 @@
* Default timeout
*/
#define SCSI_TIMEOUT (2*HZ)
+#define SCSI_REPORT_LUNS_TIMEOUT (30*HZ)
/*
* Prefix values for the SCSI id's (stored in sysfs name field)
@@ -274,8 +275,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
sdev->request_queue->queuedata = sdev;
- if (!shost_use_blk_mq(sdev->host) &&
- (shost->bqt || shost->hostt->use_blk_tags)) {
+ if (!shost_use_blk_mq(sdev->host)) {
blk_queue_init_tags(sdev->request_queue,
sdev->host->cmd_per_lun, shost->bqt,
shost->hostt->tag_alloc_policy);
@@ -1383,7 +1383,7 @@ retry:
result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
lun_data, length, &sshdr,
- SCSI_TIMEOUT + 4 * HZ, 3, NULL);
+ SCSI_REPORT_LUNS_TIMEOUT, 3, NULL);
SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
"scsi scan: REPORT LUNS"
@@ -1712,8 +1712,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
return NULL;
if (shost->async_scan) {
- shost_printk(KERN_INFO, shost, "%s called twice\n", __func__);
- dump_stack();
+ shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__);
return NULL;
}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index b333389f248f..8d2312239ae0 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -399,6 +399,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
sdev = container_of(work, struct scsi_device, ew.work);
+ scsi_dh_release_device(sdev);
+
parent = sdev->sdev_gendev.parent;
spin_lock_irqsave(sdev->host->host_lock, flags);
@@ -773,6 +775,29 @@ static struct bin_attribute dev_attr_vpd_##_page = { \
sdev_vpd_pg_attr(pg83);
sdev_vpd_pg_attr(pg80);
+static ssize_t show_inquiry(struct file *filep, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (!sdev->inquiry)
+ return -EINVAL;
+
+ return memory_read_from_buffer(buf, count, &off, sdev->inquiry,
+ sdev->inquiry_len);
+}
+
+static struct bin_attribute dev_attr_inquiry = {
+ .attr = {
+ .name = "inquiry",
+ .mode = S_IRUGO,
+ },
+ .size = 0,
+ .read = show_inquiry,
+};
+
static ssize_t
show_iostat_counterbits(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -898,7 +923,7 @@ sdev_store_queue_ramp_up_period(struct device *dev,
return -EINVAL;
sdev->queue_ramp_up_period = msecs_to_jiffies(period);
- return period;
+ return count;
}
static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
@@ -957,6 +982,7 @@ static struct attribute *scsi_sdev_attrs[] = {
static struct bin_attribute *scsi_sdev_bin_attrs[] = {
&dev_attr_vpd_pg83,
&dev_attr_vpd_pg80,
+ &dev_attr_inquiry,
NULL
};
static struct attribute_group scsi_sdev_attr_group = {
@@ -1084,9 +1110,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
device_unregister(&sdev->sdev_dev);
transport_remove_device(dev);
scsi_dh_remove_device(sdev);
- device_del(dev);
- } else
- put_device(&sdev->sdev_dev);
+ }
/*
* Stop accepting new requests and wait until all queuecommand() and
@@ -1097,6 +1121,16 @@ void __scsi_remove_device(struct scsi_device *sdev)
blk_cleanup_queue(sdev->request_queue);
cancel_work_sync(&sdev->requeue_work);
+ /*
+ * Remove the device after blk_cleanup_queue() has been called such
+ * a possible bdi_register() call with the same name occurs after
+ * blk_cleanup_queue() has called bdi_destroy().
+ */
+ if (sdev->is_visible)
+ device_del(dev);
+ else
+ put_device(&sdev->sdev_dev);
+
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
transport_destroy_device(dev);
@@ -1158,31 +1192,23 @@ static void __scsi_remove_target(struct scsi_target *starget)
void scsi_remove_target(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev->parent);
- struct scsi_target *starget, *last = NULL;
+ struct scsi_target *starget;
unsigned long flags;
- /* remove targets being careful to lookup next entry before
- * deleting the last
- */
+restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(starget, &shost->__targets, siblings) {
if (starget->state == STARGET_DEL)
continue;
if (starget->dev.parent == dev || &starget->dev == dev) {
- /* assuming new targets arrive at the end */
kref_get(&starget->reap_ref);
spin_unlock_irqrestore(shost->host_lock, flags);
- if (last)
- scsi_target_reap(last);
- last = starget;
__scsi_remove_target(starget);
- spin_lock_irqsave(shost->host_lock, flags);
+ scsi_target_reap(starget);
+ goto restart;
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (last)
- scsi_target_reap(last);
}
EXPORT_SYMBOL(scsi_remove_target);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3f370228bf31..54519804c46a 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -51,6 +51,7 @@
#include <linux/async.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
+#include <linux/pr.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
@@ -204,6 +205,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
buffer_data[2] &= ~0x05;
buffer_data[2] |= wce << 2 | rcd;
sp = buffer_data[0] & 0x80 ? 1 : 0;
+ buffer_data[0] &= ~0x80;
if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
SD_MAX_RETRIES, &data, &sshdr)) {
@@ -1535,6 +1537,100 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
}
#endif
+static char sd_pr_type(enum pr_type type)
+{
+ switch (type) {
+ case PR_WRITE_EXCLUSIVE:
+ return 0x01;
+ case PR_EXCLUSIVE_ACCESS:
+ return 0x03;
+ case PR_WRITE_EXCLUSIVE_REG_ONLY:
+ return 0x05;
+ case PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ return 0x06;
+ case PR_WRITE_EXCLUSIVE_ALL_REGS:
+ return 0x07;
+ case PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ return 0x08;
+ default:
+ return 0;
+ }
+};
+
+static int sd_pr_command(struct block_device *bdev, u8 sa,
+ u64 key, u64 sa_key, u8 type, u8 flags)
+{
+ struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
+ struct scsi_sense_hdr sshdr;
+ int result;
+ u8 cmd[16] = { 0, };
+ u8 data[24] = { 0, };
+
+ cmd[0] = PERSISTENT_RESERVE_OUT;
+ cmd[1] = sa;
+ cmd[2] = type;
+ put_unaligned_be32(sizeof(data), &cmd[5]);
+
+ put_unaligned_be64(key, &data[0]);
+ put_unaligned_be64(sa_key, &data[8]);
+ data[20] = flags;
+
+ result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data),
+ &sshdr, SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+
+ if ((driver_byte(result) & DRIVER_SENSE) &&
+ (scsi_sense_valid(&sshdr))) {
+ sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result);
+ scsi_print_sense_hdr(sdev, NULL, &sshdr);
+ }
+
+ return result;
+}
+
+static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
+ u32 flags)
+{
+ if (flags & ~PR_FL_IGNORE_KEY)
+ return -EOPNOTSUPP;
+ return sd_pr_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00,
+ old_key, new_key, 0,
+ (1 << 0) /* APTPL */ |
+ (1 << 2) /* ALL_TG_PT */);
+}
+
+static int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
+ u32 flags)
+{
+ if (flags)
+ return -EOPNOTSUPP;
+ return sd_pr_command(bdev, 0x01, key, 0, sd_pr_type(type), 0);
+}
+
+static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+{
+ return sd_pr_command(bdev, 0x02, key, 0, sd_pr_type(type), 0);
+}
+
+static int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
+ enum pr_type type, bool abort)
+{
+ return sd_pr_command(bdev, abort ? 0x05 : 0x04, old_key, new_key,
+ sd_pr_type(type), 0);
+}
+
+static int sd_pr_clear(struct block_device *bdev, u64 key)
+{
+ return sd_pr_command(bdev, 0x03, key, 0, 0, 0);
+}
+
+static const struct pr_ops sd_pr_ops = {
+ .pr_register = sd_pr_register,
+ .pr_reserve = sd_pr_reserve,
+ .pr_release = sd_pr_release,
+ .pr_preempt = sd_pr_preempt,
+ .pr_clear = sd_pr_clear,
+};
+
static const struct block_device_operations sd_fops = {
.owner = THIS_MODULE,
.open = sd_open,
@@ -1547,6 +1643,7 @@ static const struct block_device_operations sd_fops = {
.check_events = sd_check_events,
.revalidate_disk = sd_revalidate_disk,
.unlock_native_capacity = sd_unlock_native_capacity,
+ .pr_ops = &sd_pr_ops,
};
/**
@@ -3068,7 +3165,6 @@ static void scsi_disk_release(struct device *dev)
ida_remove(&sd_index_ida, sdkp->index);
spin_unlock(&sd_index_lock);
- blk_integrity_unregister(disk);
disk->private_data = NULL;
put_disk(disk);
put_device(&sdkp->device->sdev_gendev);
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 5c06d292b94c..987bf392c336 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -43,6 +43,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
struct scsi_device *sdp = sdkp->device;
struct gendisk *disk = sdkp->disk;
u8 type = sdkp->protection_type;
+ struct blk_integrity bi;
int dif, dix;
dif = scsi_host_dif_capable(sdp->host, type);
@@ -55,39 +56,43 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
if (!dix)
return;
+ memset(&bi, 0, sizeof(bi));
+
/* Enable DMA of protection information */
if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) {
if (type == SD_DIF_TYPE3_PROTECTION)
- blk_integrity_register(disk, &t10_pi_type3_ip);
+ bi.profile = &t10_pi_type3_ip;
else
- blk_integrity_register(disk, &t10_pi_type1_ip);
+ bi.profile = &t10_pi_type1_ip;
- disk->integrity->flags |= BLK_INTEGRITY_IP_CHECKSUM;
+ bi.flags |= BLK_INTEGRITY_IP_CHECKSUM;
} else
if (type == SD_DIF_TYPE3_PROTECTION)
- blk_integrity_register(disk, &t10_pi_type3_crc);
+ bi.profile = &t10_pi_type3_crc;
else
- blk_integrity_register(disk, &t10_pi_type1_crc);
+ bi.profile = &t10_pi_type1_crc;
+ bi.tuple_size = sizeof(struct t10_pi_tuple);
sd_printk(KERN_NOTICE, sdkp,
- "Enabling DIX %s protection\n", disk->integrity->name);
+ "Enabling DIX %s protection\n", bi.profile->name);
- /* Signal to block layer that we support sector tagging */
if (dif && type) {
-
- disk->integrity->flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
+ bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
if (!sdkp->ATO)
- return;
+ goto out;
if (type == SD_DIF_TYPE3_PROTECTION)
- disk->integrity->tag_size = sizeof(u16) + sizeof(u32);
+ bi.tag_size = sizeof(u16) + sizeof(u32);
else
- disk->integrity->tag_size = sizeof(u16);
+ bi.tag_size = sizeof(u16);
sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n",
- disk->integrity->tag_size);
+ bi.tag_size);
}
+
+out:
+ blk_integrity_register(disk, &bi);
}
/*
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9d7b7db75e4b..503ab8b46c0b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -787,8 +787,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return k; /* probably out of space --> ENOMEM */
}
if (atomic_read(&sdp->detaching)) {
- if (srp->bio)
+ if (srp->bio) {
+ if (srp->rq->cmd != srp->rq->__cmd)
+ kfree(srp->rq->cmd);
+
blk_end_request_all(srp->rq, -EIO);
+ srp->rq = NULL;
+ }
+
sg_finish_rem_req(srp);
return -ENODEV;
}
diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c
index b2b87cef00fc..2b3c25371d76 100644
--- a/drivers/scsi/snic/snic_main.c
+++ b/drivers/scsi/snic/snic_main.c
@@ -124,7 +124,6 @@ static struct scsi_host_template snic_host_template = {
.sg_tablesize = SNIC_MAX_SG_DESC_CNT,
.max_sectors = 0x800,
.shost_attrs = snic_attrs,
- .use_blk_tags = 1,
.track_queue_depth = 1,
.cmd_size = sizeof(struct snic_internal_io_state),
.proc_name = "snic_scsi",
@@ -533,15 +532,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
snic->max_tag_id = shost->can_queue;
- ret = scsi_init_shared_tag_map(shost, snic->max_tag_id);
- if (ret) {
- SNIC_HOST_ERR(shost,
- "Unable to alloc shared tag map. %d\n",
- ret);
-
- goto err_dev_close;
- }
-
shost->max_lun = snic->config.luns_per_tgt;
shost->max_id = SNIC_MAX_TARGET;
diff --git a/drivers/scsi/snic/snic_trc.c b/drivers/scsi/snic/snic_trc.c
index 28a40a7ade38..f00ebf4717e0 100644
--- a/drivers/scsi/snic/snic_trc.c
+++ b/drivers/scsi/snic/snic_trc.c
@@ -148,7 +148,7 @@ snic_trc_init(void)
trc->max_idx = (tbuf_sz / SNIC_TRC_ENTRY_SZ);
trc->rd_idx = trc->wr_idx = 0;
- trc->enable = 1;
+ trc->enable = true;
SNIC_INFO("Trace Facility Enabled.\n Trace Buffer SZ %lu Pages.\n",
tbuf_sz / PAGE_SIZE);
ret = 0;
@@ -169,7 +169,7 @@ snic_trc_free(void)
{
struct snic_trc *trc = &snic_glob->trc;
- trc->enable = 0;
+ trc->enable = false;
snic_trc_debugfs_term();
if (trc->buf) {
diff --git a/drivers/scsi/snic/snic_trc.h b/drivers/scsi/snic/snic_trc.h
index 427faee5f97e..b37f8867bfde 100644
--- a/drivers/scsi/snic/snic_trc.h
+++ b/drivers/scsi/snic/snic_trc.h
@@ -45,7 +45,7 @@ struct snic_trc {
u32 max_idx; /* Max Index into trace buffer */
u32 rd_idx;
u32 wr_idx;
- u32 enable; /* Control Variable for Tracing */
+ bool enable; /* Control Variable for Tracing */
struct dentry *trc_enable; /* debugfs file object */
struct dentry *trc_file;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index b37b9b00c4b4..e0a1e52a04e7 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4452,11 +4452,41 @@ static ssize_t version_show(struct device_driver *ddd, char *buf)
}
static DRIVER_ATTR_RO(version);
+#if DEBUG
+static ssize_t debug_flag_store(struct device_driver *ddp,
+ const char *buf, size_t count)
+{
+/* We only care what the first byte of the data is the rest is unused.
+ * if it's a '1' we turn on debug and if it's a '0' we disable it. All
+ * other values have -EINVAL returned if they are passed in.
+ */
+ if (count > 0) {
+ if (buf[0] == '0') {
+ debugging = NO_DEBUG;
+ return count;
+ } else if (buf[0] == '1') {
+ debugging = 1;
+ return count;
+ }
+ }
+ return -EINVAL;
+}
+
+static ssize_t debug_flag_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", debugging);
+}
+static DRIVER_ATTR_RW(debug_flag);
+#endif
+
static struct attribute *st_drv_attrs[] = {
&driver_attr_try_direct_io.attr,
&driver_attr_fixed_buffer_size.attr,
&driver_attr_max_sg_segs.attr,
&driver_attr_version.attr,
+#if DEBUG
+ &driver_attr_debug_flag.attr,
+#endif
NULL,
};
ATTRIBUTE_GROUPS(st_drv);
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 98a62bc15069..2de28d7a0b04 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -25,6 +25,7 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/ktime.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
@@ -362,14 +363,6 @@ MODULE_DESCRIPTION("Promise Technology SuperTrak EX Controllers");
MODULE_LICENSE("GPL");
MODULE_VERSION(ST_DRIVER_VERSION);
-static void stex_gettime(__le64 *time)
-{
- struct timeval tv;
-
- do_gettimeofday(&tv);
- *time = cpu_to_le64(tv.tv_sec);
-}
-
static struct status_msg *stex_get_status(struct st_hba *hba)
{
struct status_msg *status = hba->status_buffer + hba->status_tail;
@@ -1002,7 +995,7 @@ static int stex_common_handshake(struct st_hba *hba)
h->req_cnt = cpu_to_le16(hba->rq_count+1);
h->status_sz = cpu_to_le16(sizeof(struct status_msg));
h->status_cnt = cpu_to_le16(hba->sts_count+1);
- stex_gettime(&h->hosttime);
+ h->hosttime = cpu_to_le64(ktime_get_real_seconds());
h->partner_type = HMU_PARTNER_TYPE;
if (hba->extra_offset) {
h->extra_offset = cpu_to_le32(hba->extra_offset);
@@ -1076,7 +1069,7 @@ static int stex_ss_handshake(struct st_hba *hba)
h->req_cnt = cpu_to_le16(hba->rq_count+1);
h->status_sz = cpu_to_le16(sizeof(struct status_msg));
h->status_cnt = cpu_to_le16(hba->sts_count+1);
- stex_gettime(&h->hosttime);
+ h->hosttime = cpu_to_le64(ktime_get_real_seconds());
h->partner_type = HMU_PARTNER_TYPE;
h->extra_offset = h->extra_size = 0;
scratch_size = (hba->sts_count+1)*sizeof(u32);
@@ -1374,7 +1367,6 @@ static struct scsi_host_template driver_template = {
.eh_abort_handler = stex_abort,
.eh_host_reset_handler = stex_reset,
.this_id = -1,
- .use_blk_tags = 1,
};
static struct pci_device_id stex_pci_tbl[] = {
@@ -1659,13 +1651,6 @@ static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto out_free_irq;
- err = scsi_init_shared_tag_map(host, host->can_queue);
- if (err) {
- printk(KERN_ERR DRV_NAME "(%s): init shared queue failed\n",
- pci_name(pdev));
- goto out_free_irq;
- }
-
pci_set_drvdata(pdev, hba);
err = scsi_add_host(host, &pdev->dev);
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 40c43aeb4ff3..3fba42ad9fb8 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -349,11 +349,14 @@ enum storvsc_request_type {
*/
#define SRB_STATUS_AUTOSENSE_VALID 0x80
+#define SRB_STATUS_QUEUE_FROZEN 0x40
#define SRB_STATUS_INVALID_LUN 0x20
#define SRB_STATUS_SUCCESS 0x01
#define SRB_STATUS_ABORTED 0x02
#define SRB_STATUS_ERROR 0x04
+#define SRB_STATUS(status) \
+ (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
/*
* This is the end of Protocol specific defines.
*/
@@ -393,9 +396,6 @@ static void storvsc_on_channel_callback(void *context);
struct storvsc_cmd_request {
struct scsi_cmnd *cmd;
- unsigned int bounce_sgl_count;
- struct scatterlist *bounce_sgl;
-
struct hv_device *device;
/* Synchronize the request/response if needed */
@@ -586,241 +586,6 @@ get_in_err:
}
-static void destroy_bounce_buffer(struct scatterlist *sgl,
- unsigned int sg_count)
-{
- int i;
- struct page *page_buf;
-
- for (i = 0; i < sg_count; i++) {
- page_buf = sg_page((&sgl[i]));
- if (page_buf != NULL)
- __free_page(page_buf);
- }
-
- kfree(sgl);
-}
-
-static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
-{
- int i;
-
- /* No need to check */
- if (sg_count < 2)
- return -1;
-
- /* We have at least 2 sg entries */
- for (i = 0; i < sg_count; i++) {
- if (i == 0) {
- /* make sure 1st one does not have hole */
- if (sgl[i].offset + sgl[i].length != PAGE_SIZE)
- return i;
- } else if (i == sg_count - 1) {
- /* make sure last one does not have hole */
- if (sgl[i].offset != 0)
- return i;
- } else {
- /* make sure no hole in the middle */
- if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0)
- return i;
- }
- }
- return -1;
-}
-
-static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
- unsigned int sg_count,
- unsigned int len,
- int write)
-{
- int i;
- int num_pages;
- struct scatterlist *bounce_sgl;
- struct page *page_buf;
- unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
-
- num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
-
- bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
- if (!bounce_sgl)
- return NULL;
-
- sg_init_table(bounce_sgl, num_pages);
- for (i = 0; i < num_pages; i++) {
- page_buf = alloc_page(GFP_ATOMIC);
- if (!page_buf)
- goto cleanup;
- sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
- }
-
- return bounce_sgl;
-
-cleanup:
- destroy_bounce_buffer(bounce_sgl, num_pages);
- return NULL;
-}
-
-/* Assume the original sgl has enough room */
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
- struct scatterlist *bounce_sgl,
- unsigned int orig_sgl_count,
- unsigned int bounce_sgl_count)
-{
- int i;
- int j = 0;
- unsigned long src, dest;
- unsigned int srclen, destlen, copylen;
- unsigned int total_copied = 0;
- unsigned long bounce_addr = 0;
- unsigned long dest_addr = 0;
- unsigned long flags;
- struct scatterlist *cur_dest_sgl;
- struct scatterlist *cur_src_sgl;
-
- local_irq_save(flags);
- cur_dest_sgl = orig_sgl;
- cur_src_sgl = bounce_sgl;
- for (i = 0; i < orig_sgl_count; i++) {
- dest_addr = (unsigned long)
- kmap_atomic(sg_page(cur_dest_sgl)) +
- cur_dest_sgl->offset;
- dest = dest_addr;
- destlen = cur_dest_sgl->length;
-
- if (bounce_addr == 0)
- bounce_addr = (unsigned long)kmap_atomic(
- sg_page(cur_src_sgl));
-
- while (destlen) {
- src = bounce_addr + cur_src_sgl->offset;
- srclen = cur_src_sgl->length - cur_src_sgl->offset;
-
- copylen = min(srclen, destlen);
- memcpy((void *)dest, (void *)src, copylen);
-
- total_copied += copylen;
- cur_src_sgl->offset += copylen;
- destlen -= copylen;
- dest += copylen;
-
- if (cur_src_sgl->offset == cur_src_sgl->length) {
- /* full */
- kunmap_atomic((void *)bounce_addr);
- j++;
-
- /*
- * It is possible that the number of elements
- * in the bounce buffer may not be equal to
- * the number of elements in the original
- * scatter list. Handle this correctly.
- */
-
- if (j == bounce_sgl_count) {
- /*
- * We are done; cleanup and return.
- */
- kunmap_atomic((void *)(dest_addr -
- cur_dest_sgl->offset));
- local_irq_restore(flags);
- return total_copied;
- }
-
- /* if we need to use another bounce buffer */
- if (destlen || i != orig_sgl_count - 1) {
- cur_src_sgl = sg_next(cur_src_sgl);
- bounce_addr = (unsigned long)
- kmap_atomic(
- sg_page(cur_src_sgl));
- }
- } else if (destlen == 0 && i == orig_sgl_count - 1) {
- /* unmap the last bounce that is < PAGE_SIZE */
- kunmap_atomic((void *)bounce_addr);
- }
- }
-
- kunmap_atomic((void *)(dest_addr - cur_dest_sgl->offset));
- cur_dest_sgl = sg_next(cur_dest_sgl);
- }
-
- local_irq_restore(flags);
-
- return total_copied;
-}
-
-/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
-static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
- struct scatterlist *bounce_sgl,
- unsigned int orig_sgl_count)
-{
- int i;
- int j = 0;
- unsigned long src, dest;
- unsigned int srclen, destlen, copylen;
- unsigned int total_copied = 0;
- unsigned long bounce_addr = 0;
- unsigned long src_addr = 0;
- unsigned long flags;
- struct scatterlist *cur_src_sgl;
- struct scatterlist *cur_dest_sgl;
-
- local_irq_save(flags);
-
- cur_src_sgl = orig_sgl;
- cur_dest_sgl = bounce_sgl;
-
- for (i = 0; i < orig_sgl_count; i++) {
- src_addr = (unsigned long)
- kmap_atomic(sg_page(cur_src_sgl)) +
- cur_src_sgl->offset;
- src = src_addr;
- srclen = cur_src_sgl->length;
-
- if (bounce_addr == 0)
- bounce_addr = (unsigned long)
- kmap_atomic(sg_page(cur_dest_sgl));
-
- while (srclen) {
- /* assume bounce offset always == 0 */
- dest = bounce_addr + cur_dest_sgl->length;
- destlen = PAGE_SIZE - cur_dest_sgl->length;
-
- copylen = min(srclen, destlen);
- memcpy((void *)dest, (void *)src, copylen);
-
- total_copied += copylen;
- cur_dest_sgl->length += copylen;
- srclen -= copylen;
- src += copylen;
-
- if (cur_dest_sgl->length == PAGE_SIZE) {
- /* full..move to next entry */
- kunmap_atomic((void *)bounce_addr);
- bounce_addr = 0;
- j++;
- }
-
- /* if we need to use another bounce buffer */
- if (srclen && bounce_addr == 0) {
- cur_dest_sgl = sg_next(cur_dest_sgl);
- bounce_addr = (unsigned long)
- kmap_atomic(
- sg_page(cur_dest_sgl));
- }
-
- }
-
- kunmap_atomic((void *)(src_addr - cur_src_sgl->offset));
- cur_src_sgl = sg_next(cur_src_sgl);
- }
-
- if (bounce_addr)
- kunmap_atomic((void *)bounce_addr);
-
- local_irq_restore(flags);
-
- return total_copied;
-}
-
static void handle_sc_creation(struct vmbus_channel *new_sc)
{
struct hv_device *device = new_sc->primary_channel->device_obj;
@@ -1096,7 +861,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
void (*process_err_fn)(struct work_struct *work);
bool do_work = false;
- switch (vm_srb->srb_status) {
+ switch (SRB_STATUS(vm_srb->srb_status)) {
case SRB_STATUS_ERROR:
/*
* If there is an error; offline the device since all
@@ -1171,15 +936,6 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
host = stor_dev->host;
vm_srb = &cmd_request->vstor_packet.vm_srb;
- if (cmd_request->bounce_sgl_count) {
- if (vm_srb->data_in == READ_TYPE)
- copy_from_bounce_buffer(scsi_sglist(scmnd),
- cmd_request->bounce_sgl,
- scsi_sg_count(scmnd),
- cmd_request->bounce_sgl_count);
- destroy_bounce_buffer(cmd_request->bounce_sgl,
- cmd_request->bounce_sgl_count);
- }
scmnd->result = vm_srb->scsi_status;
@@ -1474,6 +1230,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ));
+ /* Ensure there are no gaps in presented sgls */
+ blk_queue_virt_boundary(sdevice->request_queue, PAGE_SIZE - 1);
+
sdevice->no_write_same = 1;
/*
@@ -1647,8 +1406,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
vm_srb->win8_extension.time_out_value = 60;
vm_srb->win8_extension.srb_flags |=
- (SRB_FLAGS_QUEUE_ACTION_ENABLE |
- SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
+ SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
/* Build the SRB */
switch (scmnd->sc_data_direction) {
@@ -1692,40 +1450,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
payload_sz = sizeof(cmd_request->mpb);
if (sg_count) {
- /* check if we need to bounce the sgl */
- if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
- cmd_request->bounce_sgl =
- create_bounce_buffer(sgl, sg_count,
- length,
- vm_srb->data_in);
- if (!cmd_request->bounce_sgl)
- return SCSI_MLQUEUE_HOST_BUSY;
-
- cmd_request->bounce_sgl_count =
- ALIGN(length, PAGE_SIZE) >> PAGE_SHIFT;
-
- if (vm_srb->data_in == WRITE_TYPE)
- copy_to_bounce_buffer(sgl,
- cmd_request->bounce_sgl, sg_count);
-
- sgl = cmd_request->bounce_sgl;
- sg_count = cmd_request->bounce_sgl_count;
- }
-
-
if (sg_count > MAX_PAGE_BUFFER_COUNT) {
payload_sz = (sg_count * sizeof(void *) +
sizeof(struct vmbus_packet_mpb_array));
payload = kmalloc(payload_sz, GFP_ATOMIC);
- if (!payload) {
- if (cmd_request->bounce_sgl_count)
- destroy_bounce_buffer(
- cmd_request->bounce_sgl,
- cmd_request->bounce_sgl_count);
-
- return SCSI_MLQUEUE_DEVICE_BUSY;
- }
+ if (!payload)
+ return SCSI_MLQUEUE_DEVICE_BUSY;
}
payload->range.len = length;
@@ -1754,11 +1485,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
if (ret == -EAGAIN) {
/* no more space */
-
- if (cmd_request->bounce_sgl_count)
- destroy_bounce_buffer(cmd_request->bounce_sgl,
- cmd_request->bounce_sgl_count);
-
return SCSI_MLQUEUE_DEVICE_BUSY;
}
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e94538362536..5f4530744e0a 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -72,7 +72,7 @@ config SCSI_UFSHCD_PLATFORM
If unsure, say N.
config SCSI_UFS_QCOM
- bool "QCOM specific hooks to UFS controller platform driver"
+ tristate "QCOM specific hooks to UFS controller platform driver"
depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
select PHY_QCOM_UFS
help
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 4cdffa46d401..4f38d008bfb4 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -19,16 +19,44 @@
#include <linux/phy/phy-qcom-ufs.h>
#include "ufshcd.h"
+#include "ufshcd-pltfrm.h"
#include "unipro.h"
#include "ufs-qcom.h"
#include "ufshci.h"
+#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \
+ (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+
+enum {
+ TSTBUS_UAWM,
+ TSTBUS_UARM,
+ TSTBUS_TXUC,
+ TSTBUS_RXUC,
+ TSTBUS_DFC,
+ TSTBUS_TRLUT,
+ TSTBUS_TMRLUT,
+ TSTBUS_OCSC,
+ TSTBUS_UTP_HCI,
+ TSTBUS_COMBINED,
+ TSTBUS_WRAPPER,
+ TSTBUS_UNIPRO,
+ TSTBUS_MAX,
+};
static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
-static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result);
-static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
- const char *speed_mode);
static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
+static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
+static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
+ u32 clk_cycles);
+
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+ char *prefix)
+{
+ print_hex_dump(KERN_ERR, prefix,
+ len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+ 16, 4, (void __force *)hba->mmio_base + offset,
+ len * 4, false);
+}
static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
{
@@ -149,13 +177,14 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host)
err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
&host->tx_l1_sync_clk);
+
out:
return err;
}
static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
u32 tx_lanes;
int err = 0;
@@ -181,7 +210,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
do {
err = ufshcd_dme_get(hba,
- UIC_ARG_MIB(MPHY_TX_FSM_STATE), &tx_fsm_val);
+ UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+ UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+ &tx_fsm_val);
if (err || tx_fsm_val == TX_FSM_HIBERN8)
break;
@@ -195,7 +226,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
*/
if (time_after(jiffies, timeout))
err = ufshcd_dme_get(hba,
- UIC_ARG_MIB(MPHY_TX_FSM_STATE), &tx_fsm_val);
+ UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+ UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+ &tx_fsm_val);
if (err) {
dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
@@ -209,9 +242,18 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
return err;
}
+static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
+{
+ ufshcd_rmwl(host->hba, QUNIPRO_SEL,
+ ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
+ REG_UFS_CFG1);
+ /* make sure above configuration is applied before we return */
+ mb();
+}
+
static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
int ret = 0;
bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
@@ -223,9 +265,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
usleep_range(1000, 1100);
ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
+
if (ret) {
- dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n",
- __func__, ret);
+ dev_err(hba->dev,
+ "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
+ __func__, ret);
goto out;
}
@@ -246,9 +290,12 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
ret = ufs_qcom_phy_is_pcs_ready(phy);
if (ret)
- dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n",
+ dev_err(hba->dev,
+ "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n",
__func__, ret);
+ ufs_qcom_select_unipro_mode(host);
+
out:
return ret;
}
@@ -271,9 +318,10 @@ static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba)
mb();
}
-static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
+static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
int err = 0;
switch (status) {
@@ -301,13 +349,13 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
}
/**
- * Returns non-zero for success (which rate of core_clk) and 0
- * in case of a failure
+ * Returns zero for success and non-zero in case of a failure
*/
-static unsigned long
-ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
+static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
+ u32 hs, u32 rate, bool update_link_startup_timer)
{
- struct ufs_qcom_host *host = hba->priv;
+ int ret = 0;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct ufs_clk_info *clki;
u32 core_clk_period_in_ns;
u32 tx_clk_cycles_per_us = 0;
@@ -324,11 +372,13 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
static u32 hs_fr_table_rA[][2] = {
{UFS_HS_G1, 0x1F},
{UFS_HS_G2, 0x3e},
+ {UFS_HS_G3, 0x7D},
};
static u32 hs_fr_table_rB[][2] = {
{UFS_HS_G1, 0x24},
{UFS_HS_G2, 0x49},
+ {UFS_HS_G3, 0x92},
};
/*
@@ -356,7 +406,17 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
core_clk_rate = DEFAULT_CLK_RATE_HZ;
core_clk_cycles_per_us = core_clk_rate / USEC_PER_SEC;
- ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US);
+ if (ufshcd_readl(hba, REG_UFS_SYS1CLK_1US) != core_clk_cycles_per_us) {
+ ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US);
+ /*
+ * make sure above write gets applied before we return from
+ * this function.
+ */
+ mb();
+ }
+
+ if (ufs_qcom_cap_qunipro(host))
+ goto out;
core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate;
core_clk_period_in_ns <<= OFFSET_CLK_NS_REG;
@@ -406,35 +466,59 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
goto out_error;
}
- /* this register 2 fields shall be written at once */
- ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us,
- REG_UFS_TX_SYMBOL_CLK_NS_US);
+ if (ufshcd_readl(hba, REG_UFS_TX_SYMBOL_CLK_NS_US) !=
+ (core_clk_period_in_ns | tx_clk_cycles_per_us)) {
+ /* this register 2 fields shall be written at once */
+ ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us,
+ REG_UFS_TX_SYMBOL_CLK_NS_US);
+ /*
+ * make sure above write gets applied before we return from
+ * this function.
+ */
+ mb();
+ }
+
+ if (update_link_startup_timer) {
+ ufshcd_writel(hba, ((core_clk_rate / MSEC_PER_SEC) * 100),
+ REG_UFS_PA_LINK_STARTUP_TIMER);
+ /*
+ * make sure that this configuration is applied before
+ * we return
+ */
+ mb();
+ }
goto out;
out_error:
- core_clk_rate = 0;
+ ret = -EINVAL;
out:
- return core_clk_rate;
+ return ret;
}
-static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, bool status)
+static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
{
- unsigned long core_clk_rate = 0;
- u32 core_clk_cycles_per_100ms;
+ int err = 0;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
switch (status) {
case PRE_CHANGE:
- core_clk_rate = ufs_qcom_cfg_timers(hba, UFS_PWM_G1,
- SLOWAUTO_MODE, 0);
- if (!core_clk_rate) {
+ if (ufs_qcom_cfg_timers(hba, UFS_PWM_G1, SLOWAUTO_MODE,
+ 0, true)) {
dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n",
__func__);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
- core_clk_cycles_per_100ms =
- (core_clk_rate / MSEC_PER_SEC) * 100;
- ufshcd_writel(hba, core_clk_cycles_per_100ms,
- REG_UFS_PA_LINK_STARTUP_TIMER);
+
+ if (ufs_qcom_cap_qunipro(host))
+ /*
+ * set unipro core clock cycles to 150 & clear clock
+ * divider
+ */
+ err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba,
+ 150);
+
break;
case POST_CHANGE:
ufs_qcom_link_startup_post_change(hba);
@@ -443,12 +527,13 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, bool status)
break;
}
- return 0;
+out:
+ return err;
}
static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
int ret = 0;
@@ -470,8 +555,10 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
* If UniPro link is not active, PHY ref_clk, main PHY analog power
* rail and low noise analog power rail for PLL can be switched off.
*/
- if (!ufs_qcom_is_link_active(hba))
+ if (!ufs_qcom_is_link_active(hba)) {
+ ufs_qcom_disable_lane_clks(host);
phy_power_off(phy);
+ }
out:
return ret;
@@ -479,7 +566,7 @@ out:
static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
int err;
@@ -490,6 +577,10 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
goto out;
}
+ err = ufs_qcom_enable_lane_clks(host);
+ if (err)
+ goto out;
+
hba->is_sys_suspended = false;
out:
@@ -594,6 +685,81 @@ static int ufs_qcom_get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param,
return 0;
}
+#ifdef CONFIG_MSM_BUS_SCALING
+static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
+ const char *speed_mode)
+{
+ struct device *dev = host->hba->dev;
+ struct device_node *np = dev->of_node;
+ int err;
+ const char *key = "qcom,bus-vector-names";
+
+ if (!speed_mode) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN"))
+ err = of_property_match_string(np, key, "MAX");
+ else
+ err = of_property_match_string(np, key, speed_mode);
+
+out:
+ if (err < 0)
+ dev_err(dev, "%s: Invalid %s mode %d\n",
+ __func__, speed_mode, err);
+ return err;
+}
+
+static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
+{
+ int gear = max_t(u32, p->gear_rx, p->gear_tx);
+ int lanes = max_t(u32, p->lane_rx, p->lane_tx);
+ int pwr;
+
+ /* default to PWM Gear 1, Lane 1 if power mode is not initialized */
+ if (!gear)
+ gear = 1;
+
+ if (!lanes)
+ lanes = 1;
+
+ if (!p->pwr_rx && !p->pwr_tx) {
+ pwr = SLOWAUTO_MODE;
+ snprintf(result, BUS_VECTOR_NAME_LEN, "MIN");
+ } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE ||
+ p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) {
+ pwr = FAST_MODE;
+ snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS",
+ p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes);
+ } else {
+ pwr = SLOW_MODE;
+ snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d",
+ "PWM", gear, lanes);
+ }
+}
+
+static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
+{
+ int err = 0;
+
+ if (vote != host->bus_vote.curr_vote) {
+ err = msm_bus_scale_client_update_request(
+ host->bus_vote.client_handle, vote);
+ if (err) {
+ dev_err(host->hba->dev,
+ "%s: msm_bus_scale_client_update_request() failed: bus_client_handle=0x%x, vote=%d, err=%d\n",
+ __func__, host->bus_vote.client_handle,
+ vote, err);
+ goto out;
+ }
+
+ host->bus_vote.curr_vote = vote;
+ }
+out:
+ return err;
+}
+
static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
{
int vote;
@@ -615,13 +781,137 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
return err;
}
+static ssize_t
+show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ host->bus_vote.is_max_bw_needed);
+}
+
+static ssize_t
+store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ uint32_t value;
+
+ if (!kstrtou32(buf, 0, &value)) {
+ host->bus_vote.is_max_bw_needed = !!value;
+ ufs_qcom_update_bus_bw_vote(host);
+ }
+
+ return count;
+}
+
+static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
+{
+ int err;
+ struct msm_bus_scale_pdata *bus_pdata;
+ struct device *dev = host->hba->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct device_node *np = dev->of_node;
+
+ bus_pdata = msm_bus_cl_get_pdata(pdev);
+ if (!bus_pdata) {
+ dev_err(dev, "%s: failed to get bus vectors\n", __func__);
+ err = -ENODATA;
+ goto out;
+ }
+
+ err = of_property_count_strings(np, "qcom,bus-vector-names");
+ if (err < 0 || err != bus_pdata->num_usecases) {
+ dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n",
+ __func__, err);
+ goto out;
+ }
+
+ host->bus_vote.client_handle = msm_bus_scale_register_client(bus_pdata);
+ if (!host->bus_vote.client_handle) {
+ dev_err(dev, "%s: msm_bus_scale_register_client failed\n",
+ __func__);
+ err = -EFAULT;
+ goto out;
+ }
+
+ /* cache the vote index for minimum and maximum bandwidth */
+ host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN");
+ host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX");
+
+ host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw;
+ host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw;
+ sysfs_attr_init(&host->bus_vote.max_bus_bw.attr);
+ host->bus_vote.max_bus_bw.attr.name = "max_bus_bw";
+ host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
+ err = device_create_file(dev, &host->bus_vote.max_bus_bw);
+out:
+ return err;
+}
+#else /* CONFIG_MSM_BUS_SCALING */
+static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+
+static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
+{
+ return 0;
+}
+
+static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+#endif /* CONFIG_MSM_BUS_SCALING */
+
+static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
+{
+ if (host->dev_ref_clk_ctrl_mmio &&
+ (enable ^ host->is_dev_ref_clk_enabled)) {
+ u32 temp = readl_relaxed(host->dev_ref_clk_ctrl_mmio);
+
+ if (enable)
+ temp |= host->dev_ref_clk_en_mask;
+ else
+ temp &= ~host->dev_ref_clk_en_mask;
+
+ /*
+ * If we are here to disable this clock it might be immediately
+ * after entering into hibern8 in which case we need to make
+ * sure that device ref_clk is active at least 1us after the
+ * hibern8 enter.
+ */
+ if (!enable)
+ udelay(1);
+
+ writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio);
+
+ /* ensure that ref_clk is enabled/disabled before we return */
+ wmb();
+
+ /*
+ * If we call hibern8 exit after this, we need to make sure that
+ * device ref_clk is stable for at least 1us before the hibern8
+ * exit command.
+ */
+ if (enable)
+ udelay(1);
+
+ host->is_dev_ref_clk_enabled = enable;
+ }
+}
+
static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
- bool status,
+ enum ufs_notify_change_status status,
struct ufs_pa_layer_attr *dev_max_params,
struct ufs_pa_layer_attr *dev_req_params)
{
u32 val;
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
struct ufs_qcom_dev_params ufs_qcom_cap;
int ret = 0;
@@ -649,6 +939,20 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
ufs_qcom_cap.desired_working_mode =
UFS_QCOM_LIMIT_DESIRED_MODE;
+ if (host->hw_ver.major == 0x1) {
+ /*
+ * HS-G3 operations may not reliably work on legacy QCOM
+ * UFS host controller hardware even though capability
+ * exchange during link startup phase may end up
+ * negotiating maximum supported gear as G3.
+ * Hence downgrade the maximum supported gear to HS-G2.
+ */
+ if (ufs_qcom_cap.hs_tx_gear > UFS_HS_G2)
+ ufs_qcom_cap.hs_tx_gear = UFS_HS_G2;
+ if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G2)
+ ufs_qcom_cap.hs_rx_gear = UFS_HS_G2;
+ }
+
ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap,
dev_max_params,
dev_req_params);
@@ -660,9 +964,9 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
break;
case POST_CHANGE:
- if (!ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
+ if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
dev_req_params->pwr_rx,
- dev_req_params->hs_rate)) {
+ dev_req_params->hs_rate, false)) {
dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n",
__func__);
/*
@@ -696,7 +1000,7 @@ out:
static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
if (host->hw_ver.major == 0x1)
return UFSHCI_VERSION_11;
@@ -715,7 +1019,7 @@ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
*/
static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
if (host->hw_ver.major == 0x01) {
hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
@@ -724,10 +1028,11 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
if (host->hw_ver.minor == 0x0001 && host->hw_ver.step == 0x0001)
hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR;
+
+ hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
}
if (host->hw_ver.major >= 0x2) {
- hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION;
if (!ufs_qcom_cap_qunipro(host))
@@ -740,79 +1045,29 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
static void ufs_qcom_set_caps(struct ufs_hba *hba)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- if (host->hw_ver.major >= 0x2)
- host->caps = UFS_QCOM_CAP_QUNIPRO;
-}
-
-static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
- const char *speed_mode)
-{
- struct device *dev = host->hba->dev;
- struct device_node *np = dev->of_node;
- int err;
- const char *key = "qcom,bus-vector-names";
-
- if (!speed_mode) {
- err = -EINVAL;
- goto out;
- }
-
- if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN"))
- err = of_property_match_string(np, key, "MAX");
- else
- err = of_property_match_string(np, key, speed_mode);
-
-out:
- if (err < 0)
- dev_err(dev, "%s: Invalid %s mode %d\n",
- __func__, speed_mode, err);
- return err;
-}
-
-static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
-{
- int err = 0;
-
- if (vote != host->bus_vote.curr_vote)
- host->bus_vote.curr_vote = vote;
-
- return err;
-}
-
-static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
-{
- int gear = max_t(u32, p->gear_rx, p->gear_tx);
- int lanes = max_t(u32, p->lane_rx, p->lane_tx);
- int pwr;
-
- /* default to PWM Gear 1, Lane 1 if power mode is not initialized */
- if (!gear)
- gear = 1;
-
- if (!lanes)
- lanes = 1;
+ hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
+ hba->caps |= UFSHCD_CAP_CLK_SCALING;
+ hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
- if (!p->pwr_rx && !p->pwr_tx) {
- pwr = SLOWAUTO_MODE;
- snprintf(result, BUS_VECTOR_NAME_LEN, "MIN");
- } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE ||
- p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) {
- pwr = FAST_MODE;
- snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS",
- p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes);
- } else {
- pwr = SLOW_MODE;
- snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d",
- "PWM", gear, lanes);
+ if (host->hw_ver.major >= 0x2) {
+ host->caps = UFS_QCOM_CAP_QUNIPRO |
+ UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE;
}
}
+/**
+ * ufs_qcom_setup_clocks - enables/disable clocks
+ * @hba: host controller instance
+ * @on: If true, enable clocks else disable them.
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
{
- struct ufs_qcom_host *host = hba->priv;
- int err = 0;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ int err;
int vote = 0;
/*
@@ -835,20 +1090,18 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
ufs_qcom_phy_disable_iface_clk(host->generic_phy);
goto out;
}
- /* enable the device ref clock */
- ufs_qcom_phy_enable_dev_ref_clk(host->generic_phy);
vote = host->bus_vote.saved_vote;
if (vote == host->bus_vote.min_bw_vote)
ufs_qcom_update_bus_bw_vote(host);
+
} else {
+
/* M-PHY RMMI interface clocks can be turned off */
ufs_qcom_phy_disable_iface_clk(host->generic_phy);
- if (!ufs_qcom_is_link_active(hba)) {
- /* turn off UFS local PHY ref_clk */
- ufs_qcom_phy_disable_ref_clk(host->generic_phy);
+ if (!ufs_qcom_is_link_active(hba))
/* disable device ref_clk */
- ufs_qcom_phy_disable_dev_ref_clk(host->generic_phy);
- }
+ ufs_qcom_dev_ref_clk_ctrl(host, false);
+
vote = host->bus_vote.min_bw_vote;
}
@@ -861,68 +1114,17 @@ out:
return err;
}
-static ssize_t
-show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- struct ufs_qcom_host *host = hba->priv;
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- host->bus_vote.is_max_bw_needed);
-}
-
-static ssize_t
-store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- struct ufs_qcom_host *host = hba->priv;
- uint32_t value;
-
- if (!kstrtou32(buf, 0, &value)) {
- host->bus_vote.is_max_bw_needed = !!value;
- ufs_qcom_update_bus_bw_vote(host);
- }
-
- return count;
-}
-
-static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
-{
- int err;
- struct device *dev = host->hba->dev;
- struct device_node *np = dev->of_node;
-
- err = of_property_count_strings(np, "qcom,bus-vector-names");
- if (err < 0 ) {
- dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n",
- __func__, err);
- goto out;
- }
-
- /* cache the vote index for minimum and maximum bandwidth */
- host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN");
- host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX");
-
- host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw;
- host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw;
- sysfs_attr_init(&host->bus_vote.max_bus_bw.attr);
- host->bus_vote.max_bus_bw.attr.name = "max_bus_bw";
- host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
- err = device_create_file(dev, &host->bus_vote.max_bus_bw);
-out:
- return err;
-}
-
#define ANDROID_BOOT_DEV_MAX 30
static char android_boot_dev[ANDROID_BOOT_DEV_MAX];
-static int get_android_boot_dev(char *str)
+
+#ifndef MODULE
+static int __init get_android_boot_dev(char *str)
{
strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX);
return 1;
}
__setup("androidboot.bootdevice=", get_android_boot_dev);
+#endif
/**
* ufs_qcom_init - bind phy with controller
@@ -938,7 +1140,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
{
int err;
struct device *dev = hba->dev;
+ struct platform_device *pdev = to_platform_device(dev);
struct ufs_qcom_host *host;
+ struct resource *res;
if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev)))
return -ENODEV;
@@ -950,9 +1154,15 @@ static int ufs_qcom_init(struct ufs_hba *hba)
goto out;
}
+ /* Make a two way bind between the qcom host and the hba */
host->hba = hba;
- hba->priv = (void *)host;
+ ufshcd_set_variant(hba, host);
+ /*
+ * voting/devoting device ref_clk source is time consuming hence
+ * skip devoting it during aggressive clock gating. This clock
+ * will still be gated off during runtime suspend.
+ */
host->generic_phy = devm_phy_get(dev, "ufsphy");
if (IS_ERR(host->generic_phy)) {
@@ -968,6 +1178,30 @@ static int ufs_qcom_init(struct ufs_hba *hba)
ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
&host->hw_ver.minor, &host->hw_ver.step);
+ /*
+ * for newer controllers, device reference clock control bit has
+ * moved inside UFS controller register address space itself.
+ */
+ if (host->hw_ver.major >= 0x02) {
+ host->dev_ref_clk_ctrl_mmio = hba->mmio_base + REG_UFS_CFG1;
+ host->dev_ref_clk_en_mask = BIT(26);
+ } else {
+ /* "dev_ref_clk_ctrl_mem" is optional resource */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ host->dev_ref_clk_ctrl_mmio =
+ devm_ioremap_resource(dev, res);
+ if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) {
+ dev_warn(dev,
+ "%s: could not map dev_ref_clk_ctrl_mmio, err %ld\n",
+ __func__,
+ PTR_ERR(host->dev_ref_clk_ctrl_mmio));
+ host->dev_ref_clk_ctrl_mmio = NULL;
+ }
+ host->dev_ref_clk_en_mask = BIT(5);
+ }
+ }
+
/* update phy revision information before calling phy_init() */
ufs_qcom_phy_save_controller_version(host->generic_phy,
host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step);
@@ -984,14 +1218,20 @@ static int ufs_qcom_init(struct ufs_hba *hba)
ufs_qcom_set_caps(hba);
ufs_qcom_advertise_quirks(hba);
- hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING;
- hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
-
ufs_qcom_setup_clocks(hba, true);
if (hba->dev->id < MAX_UFS_QCOM_HOSTS)
ufs_qcom_hosts[hba->dev->id] = host;
+ host->dbg_print_en |= UFS_QCOM_DEFAULT_DBG_PRINT_EN;
+ ufs_qcom_get_default_testbus_cfg(host);
+ err = ufs_qcom_testbus_config(host);
+ if (err) {
+ dev_warn(dev, "%s: failed to configure the testbus %d\n",
+ __func__, err);
+ err = 0;
+ }
+
goto out;
out_disable_phy:
@@ -1000,40 +1240,266 @@ out_unregister_bus:
phy_exit(host->generic_phy);
out_host_free:
devm_kfree(dev, host);
- hba->priv = NULL;
+ ufshcd_set_variant(hba, NULL);
out:
return err;
}
static void ufs_qcom_exit(struct ufs_hba *hba)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
ufs_qcom_disable_lane_clks(host);
phy_power_off(host->generic_phy);
}
-static
-void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
+static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
+ u32 clk_cycles)
+{
+ int err;
+ u32 core_clk_ctrl_reg;
+
+ if (clk_cycles > DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK)
+ return -EINVAL;
+
+ err = ufshcd_dme_get(hba,
+ UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+ &core_clk_ctrl_reg);
+ if (err)
+ goto out;
+
+ core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK;
+ core_clk_ctrl_reg |= clk_cycles;
+
+ /* Clear CORE_CLK_DIV_EN */
+ core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT;
+
+ err = ufshcd_dme_set(hba,
+ UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+ core_clk_ctrl_reg);
+out:
+ return err;
+}
+
+static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba)
+{
+ /* nothing to do as of now */
+ return 0;
+}
+
+static int ufs_qcom_clk_scale_up_post_change(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ if (!ufs_qcom_cap_qunipro(host))
+ return 0;
+
+ /* set unipro core clock cycles to 150 and clear clock divider */
+ return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 150);
+}
+
+static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ int err;
+ u32 core_clk_ctrl_reg;
+
+ if (!ufs_qcom_cap_qunipro(host))
+ return 0;
+
+ err = ufshcd_dme_get(hba,
+ UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+ &core_clk_ctrl_reg);
+
+ /* make sure CORE_CLK_DIV_EN is cleared */
+ if (!err &&
+ (core_clk_ctrl_reg & DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT)) {
+ core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT;
+ err = ufshcd_dme_set(hba,
+ UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+ core_clk_ctrl_reg);
+ }
+
+ return err;
+}
+
+static int ufs_qcom_clk_scale_down_post_change(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ if (!ufs_qcom_cap_qunipro(host))
+ return 0;
+
+ /* set unipro core clock cycles to 75 and clear clock divider */
+ return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 75);
+}
+
+static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
+ bool scale_up, enum ufs_notify_change_status status)
{
- struct ufs_qcom_host *host = hba->priv;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params;
+ int err = 0;
- if (!dev_req_params)
- return;
+ if (status == PRE_CHANGE) {
+ if (scale_up)
+ err = ufs_qcom_clk_scale_up_pre_change(hba);
+ else
+ err = ufs_qcom_clk_scale_down_pre_change(hba);
+ } else {
+ if (scale_up)
+ err = ufs_qcom_clk_scale_up_post_change(hba);
+ else
+ err = ufs_qcom_clk_scale_down_post_change(hba);
- ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
- dev_req_params->pwr_rx,
- dev_req_params->hs_rate);
+ if (err || !dev_req_params)
+ goto out;
+
+ ufs_qcom_cfg_timers(hba,
+ dev_req_params->gear_rx,
+ dev_req_params->pwr_rx,
+ dev_req_params->hs_rate,
+ false);
+ ufs_qcom_update_bus_bw_vote(host);
+ }
+
+out:
+ return err;
}
+static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
+{
+ /* provide a legal default configuration */
+ host->testbus.select_major = TSTBUS_UAWM;
+ host->testbus.select_minor = 1;
+}
+
+static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host)
+{
+ if (host->testbus.select_major >= TSTBUS_MAX) {
+ dev_err(host->hba->dev,
+ "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n",
+ __func__, host->testbus.select_major);
+ return false;
+ }
+
+ /*
+ * Not performing check for each individual select_major
+ * mappings of select_minor, since there is no harm in
+ * configuring a non-existent select_minor
+ */
+ if (host->testbus.select_minor > 0x1F) {
+ dev_err(host->hba->dev,
+ "%s: 0x%05X is not a legal testbus option\n",
+ __func__, host->testbus.select_minor);
+ return false;
+ }
+
+ return true;
+}
+
+int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
+{
+ int reg;
+ int offset;
+ u32 mask = TEST_BUS_SUB_SEL_MASK;
+
+ if (!host)
+ return -EINVAL;
+
+ if (!ufs_qcom_testbus_cfg_is_ok(host))
+ return -EPERM;
+
+ switch (host->testbus.select_major) {
+ case TSTBUS_UAWM:
+ reg = UFS_TEST_BUS_CTRL_0;
+ offset = 24;
+ break;
+ case TSTBUS_UARM:
+ reg = UFS_TEST_BUS_CTRL_0;
+ offset = 16;
+ break;
+ case TSTBUS_TXUC:
+ reg = UFS_TEST_BUS_CTRL_0;
+ offset = 8;
+ break;
+ case TSTBUS_RXUC:
+ reg = UFS_TEST_BUS_CTRL_0;
+ offset = 0;
+ break;
+ case TSTBUS_DFC:
+ reg = UFS_TEST_BUS_CTRL_1;
+ offset = 24;
+ break;
+ case TSTBUS_TRLUT:
+ reg = UFS_TEST_BUS_CTRL_1;
+ offset = 16;
+ break;
+ case TSTBUS_TMRLUT:
+ reg = UFS_TEST_BUS_CTRL_1;
+ offset = 8;
+ break;
+ case TSTBUS_OCSC:
+ reg = UFS_TEST_BUS_CTRL_1;
+ offset = 0;
+ break;
+ case TSTBUS_WRAPPER:
+ reg = UFS_TEST_BUS_CTRL_2;
+ offset = 16;
+ break;
+ case TSTBUS_COMBINED:
+ reg = UFS_TEST_BUS_CTRL_2;
+ offset = 8;
+ break;
+ case TSTBUS_UTP_HCI:
+ reg = UFS_TEST_BUS_CTRL_2;
+ offset = 0;
+ break;
+ case TSTBUS_UNIPRO:
+ reg = UFS_UNIPRO_CFG;
+ offset = 1;
+ break;
+ /*
+ * No need for a default case, since
+ * ufs_qcom_testbus_cfg_is_ok() checks that the configuration
+ * is legal
+ */
+ }
+ mask <<= offset;
+
+ pm_runtime_get_sync(host->hba->dev);
+ ufshcd_hold(host->hba, false);
+ ufshcd_rmwl(host->hba, TEST_BUS_SEL,
+ (u32)host->testbus.select_major << 19,
+ REG_UFS_CFG1);
+ ufshcd_rmwl(host->hba, mask,
+ (u32)host->testbus.select_minor << offset,
+ reg);
+ ufshcd_release(host->hba);
+ pm_runtime_put_sync(host->hba->dev);
+
+ return 0;
+}
+
+static void ufs_qcom_testbus_read(struct ufs_hba *hba)
+{
+ ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+ ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
+ "HCI Vendor Specific Registers ");
+
+ ufs_qcom_testbus_read(hba);
+}
/**
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
*
* The variant operations configure the necessary controller and PHY
* handshake during initialization.
*/
-static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
+static struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.name = "qcom",
.init = ufs_qcom_init,
.exit = ufs_qcom_exit,
@@ -1045,5 +1511,66 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.pwr_change_notify = ufs_qcom_pwr_change_notify,
.suspend = ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+ .dbg_register_dump = ufs_qcom_dump_dbg_regs,
+};
+
+/**
+ * ufs_qcom_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Return zero for success and non-zero for failure
+ */
+static int ufs_qcom_probe(struct platform_device *pdev)
+{
+ int err;
+ struct device *dev = &pdev->dev;
+
+ /* Perform generic probe */
+ err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops);
+ if (err)
+ dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
+
+ return err;
+}
+
+/**
+ * ufs_qcom_remove - set driver_data of the device to NULL
+ * @pdev: pointer to platform device handle
+ *
+ * Always return 0
+ */
+static int ufs_qcom_remove(struct platform_device *pdev)
+{
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&(pdev)->dev);
+ ufshcd_remove(hba);
+ return 0;
+}
+
+static const struct of_device_id ufs_qcom_of_match[] = {
+ { .compatible = "qcom,ufshc"},
+ {},
+};
+
+static const struct dev_pm_ops ufs_qcom_pm_ops = {
+ .suspend = ufshcd_pltfrm_suspend,
+ .resume = ufshcd_pltfrm_resume,
+ .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
+ .runtime_resume = ufshcd_pltfrm_runtime_resume,
+ .runtime_idle = ufshcd_pltfrm_runtime_idle,
};
-EXPORT_SYMBOL(ufs_hba_qcom_vops);
+
+static struct platform_driver ufs_qcom_pltform = {
+ .probe = ufs_qcom_probe,
+ .remove = ufs_qcom_remove,
+ .shutdown = ufshcd_pltfrm_shutdown,
+ .driver = {
+ .name = "ufshcd-qcom",
+ .pm = &ufs_qcom_pm_ops,
+ .of_match_table = of_match_ptr(ufs_qcom_of_match),
+ },
+};
+module_platform_driver(ufs_qcom_pltform);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index db2c0a00e846..36249b35f858 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -35,8 +35,8 @@
#define UFS_QCOM_LIMIT_NUM_LANES_RX 2
#define UFS_QCOM_LIMIT_NUM_LANES_TX 2
-#define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G2
-#define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G2
+#define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G3
+#define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G3
#define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4
#define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4
#define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE
@@ -58,6 +58,21 @@ enum {
REG_UFS_CFG2 = 0xE0,
REG_UFS_HW_VERSION = 0xE4,
+ UFS_TEST_BUS = 0xE8,
+ UFS_TEST_BUS_CTRL_0 = 0xEC,
+ UFS_TEST_BUS_CTRL_1 = 0xF0,
+ UFS_TEST_BUS_CTRL_2 = 0xF4,
+ UFS_UNIPRO_CFG = 0xF8,
+
+ /*
+ * QCOM UFS host controller vendor specific registers
+ * added in HW Version 3.0.0
+ */
+ UFS_AH8_CFG = 0xFC,
+};
+
+/* QCOM UFS host controller vendor specific debug registers */
+enum {
UFS_DBG_RD_REG_UAWM = 0x100,
UFS_DBG_RD_REG_UARM = 0x200,
UFS_DBG_RD_REG_TXUC = 0x300,
@@ -73,6 +88,14 @@ enum {
UFS_UFS_DBG_RD_EDTL_RAM = 0x1900,
};
+#define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x)
+#define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x)
+
+/* bit definitions for REG_UFS_CFG1 register */
+#define QUNIPRO_SEL UFS_BIT(0)
+#define TEST_BUS_EN BIT(18)
+#define TEST_BUS_SEL GENMASK(22, 19)
+
/* bit definitions for REG_UFS_CFG2 register */
#define UAWM_HW_CGC_EN (1 << 0)
#define UARM_HW_CGC_EN (1 << 1)
@@ -83,6 +106,9 @@ enum {
#define TMRLUT_HW_CGC_EN (1 << 6)
#define OCSC_HW_CGC_EN (1 << 7)
+/* bit definition for UFS_UFS_TEST_BUS_CTRL_n */
+#define TEST_BUS_SUB_SEL_MASK 0x1F /* All XXX_SEL fields are 5 bits wide */
+
#define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\
TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\
DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\
@@ -106,6 +132,21 @@ enum ufs_qcom_phy_init_type {
UFS_PHY_INIT_CFG_RESTORE,
};
+/* QCOM UFS debug print bit mask */
+#define UFS_QCOM_DBG_PRINT_REGS_EN BIT(0)
+#define UFS_QCOM_DBG_PRINT_ICE_REGS_EN BIT(1)
+#define UFS_QCOM_DBG_PRINT_TEST_BUS_EN BIT(2)
+
+#define UFS_QCOM_DBG_PRINT_ALL \
+ (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_ICE_REGS_EN | \
+ UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+
+/* QUniPro Vendor specific attributes */
+#define DME_VS_CORE_CLK_CTRL 0xD002
+/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
+#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
+#define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK 0xFF
+
static inline void
ufs_qcom_get_controller_revision(struct ufs_hba *hba,
u8 *major, u16 *minor, u16 *step)
@@ -157,8 +198,13 @@ struct ufs_hw_version {
u16 minor;
u8 major;
};
-struct ufs_qcom_host {
+struct ufs_qcom_testbus {
+ u8 select_major;
+ u8 select_minor;
+};
+
+struct ufs_qcom_host {
/*
* Set this capability if host controller supports the QUniPro mode
* and if driver wants the Host controller to operate in QUniPro mode.
@@ -166,6 +212,12 @@ struct ufs_qcom_host {
* controller supports the QUniPro mode.
*/
#define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0)
+
+ /*
+ * Set this capability if host controller can retain the secure
+ * configuration even after UFS controller core power collapse.
+ */
+ #define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE UFS_BIT(1)
u32 caps;
struct phy *generic_phy;
@@ -178,13 +230,23 @@ struct ufs_qcom_host {
struct clk *tx_l1_sync_clk;
bool is_lane_clks_enabled;
+ void __iomem *dev_ref_clk_ctrl_mmio;
+ bool is_dev_ref_clk_enabled;
struct ufs_hw_version hw_ver;
+
+ u32 dev_ref_clk_en_mask;
+
+ /* Bitmask for enabling debug prints */
+ u32 dbg_print_en;
+ struct ufs_qcom_testbus testbus;
};
#define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba)
#define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba)
#define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba)
+int ufs_qcom_testbus_config(struct ufs_qcom_host *host);
+
static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
{
if (host->caps & UFS_QCOM_CAP_QUNIPRO)
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 7db9564f507d..9714f2a8b329 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -38,20 +38,7 @@
#include <linux/of.h>
#include "ufshcd.h"
-
-static const struct of_device_id ufs_of_match[];
-static struct ufs_hba_variant_ops *get_variant_ops(struct device *dev)
-{
- if (dev->of_node) {
- const struct of_device_id *match;
-
- match = of_match_node(ufs_of_match, dev->of_node);
- if (match)
- return (struct ufs_hba_variant_ops *)match->data;
- }
-
- return NULL;
-}
+#include "ufshcd-pltfrm.h"
static int ufshcd_parse_clock_info(struct ufs_hba *hba)
{
@@ -245,10 +232,11 @@ out:
* Returns 0 if successful
* Returns non-zero otherwise
*/
-static int ufshcd_pltfrm_suspend(struct device *dev)
+int ufshcd_pltfrm_suspend(struct device *dev)
{
return ufshcd_system_suspend(dev_get_drvdata(dev));
}
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_suspend);
/**
* ufshcd_pltfrm_resume - resume power management function
@@ -257,43 +245,47 @@ static int ufshcd_pltfrm_suspend(struct device *dev)
* Returns 0 if successful
* Returns non-zero otherwise
*/
-static int ufshcd_pltfrm_resume(struct device *dev)
+int ufshcd_pltfrm_resume(struct device *dev)
{
return ufshcd_system_resume(dev_get_drvdata(dev));
}
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_resume);
-static int ufshcd_pltfrm_runtime_suspend(struct device *dev)
+int ufshcd_pltfrm_runtime_suspend(struct device *dev)
{
return ufshcd_runtime_suspend(dev_get_drvdata(dev));
}
-static int ufshcd_pltfrm_runtime_resume(struct device *dev)
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_suspend);
+
+int ufshcd_pltfrm_runtime_resume(struct device *dev)
{
return ufshcd_runtime_resume(dev_get_drvdata(dev));
}
-static int ufshcd_pltfrm_runtime_idle(struct device *dev)
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_resume);
+
+int ufshcd_pltfrm_runtime_idle(struct device *dev)
{
return ufshcd_runtime_idle(dev_get_drvdata(dev));
}
-#else /* !CONFIG_PM */
-#define ufshcd_pltfrm_suspend NULL
-#define ufshcd_pltfrm_resume NULL
-#define ufshcd_pltfrm_runtime_suspend NULL
-#define ufshcd_pltfrm_runtime_resume NULL
-#define ufshcd_pltfrm_runtime_idle NULL
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_idle);
+
#endif /* CONFIG_PM */
-static void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
+void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
{
ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev));
}
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown);
/**
- * ufshcd_pltfrm_probe - probe routine of the driver
+ * ufshcd_pltfrm_init - probe routine of the driver
* @pdev: pointer to Platform device handle
+ * @vops: pointer to variant ops
*
* Returns 0 on success, non-zero value on failure
*/
-static int ufshcd_pltfrm_probe(struct platform_device *pdev)
+int ufshcd_pltfrm_init(struct platform_device *pdev,
+ struct ufs_hba_variant_ops *vops)
{
struct ufs_hba *hba;
void __iomem *mmio_base;
@@ -321,19 +313,19 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
goto out;
}
- hba->vops = get_variant_ops(&pdev->dev);
+ hba->vops = vops;
err = ufshcd_parse_clock_info(hba);
if (err) {
dev_err(&pdev->dev, "%s: clock parse failed %d\n",
__func__, err);
- goto out;
+ goto dealloc_host;
}
err = ufshcd_parse_regulator_info(hba);
if (err) {
dev_err(&pdev->dev, "%s: regulator init failed %d\n",
__func__, err);
- goto out;
+ goto dealloc_host;
}
pm_runtime_set_active(&pdev->dev);
@@ -352,50 +344,12 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
out_disable_rpm:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
+dealloc_host:
+ ufshcd_dealloc_host(hba);
out:
return err;
}
-
-/**
- * ufshcd_pltfrm_remove - remove platform driver routine
- * @pdev: pointer to platform device handle
- *
- * Returns 0 on success, non-zero value on failure
- */
-static int ufshcd_pltfrm_remove(struct platform_device *pdev)
-{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- pm_runtime_get_sync(&(pdev)->dev);
- ufshcd_remove(hba);
- return 0;
-}
-
-static const struct of_device_id ufs_of_match[] = {
- { .compatible = "jedec,ufs-1.1"},
- {},
-};
-
-static const struct dev_pm_ops ufshcd_dev_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
-};
-
-static struct platform_driver ufshcd_pltfrm_driver = {
- .probe = ufshcd_pltfrm_probe,
- .remove = ufshcd_pltfrm_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
- .driver = {
- .name = "ufshcd",
- .pm = &ufshcd_dev_pm_ops,
- .of_match_table = ufs_of_match,
- },
-};
-
-module_platform_driver(ufshcd_pltfrm_driver);
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init);
MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.h b/drivers/scsi/ufs/ufshcd-pltfrm.h
new file mode 100644
index 000000000000..df64c4180340
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2015, 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 and
+ * only 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.
+ *
+ */
+
+#ifndef UFSHCD_PLTFRM_H_
+#define UFSHCD_PLTFRM_H_
+
+#include "ufshcd.h"
+
+int ufshcd_pltfrm_init(struct platform_device *pdev,
+ struct ufs_hba_variant_ops *vops);
+void ufshcd_pltfrm_shutdown(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+
+int ufshcd_pltfrm_suspend(struct device *dev);
+int ufshcd_pltfrm_resume(struct device *dev);
+int ufshcd_pltfrm_runtime_suspend(struct device *dev);
+int ufshcd_pltfrm_runtime_resume(struct device *dev);
+int ufshcd_pltfrm_runtime_idle(struct device *dev);
+
+#else /* !CONFIG_PM */
+
+#define ufshcd_pltfrm_suspend NULL
+#define ufshcd_pltfrm_resume NULL
+#define ufshcd_pltfrm_runtime_suspend NULL
+#define ufshcd_pltfrm_runtime_resume NULL
+#define ufshcd_pltfrm_runtime_idle NULL
+
+#endif /* CONFIG_PM */
+
+#endif /* UFSHCD_PLTFRM_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b0ade73f8c6a..85cd2564c157 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -271,10 +271,8 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
*/
static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
{
- if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) {
- if (hba->vops && hba->vops->get_ufs_hci_version)
- return hba->vops->get_ufs_hci_version(hba);
- }
+ if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION)
+ return ufshcd_vops_get_ufs_hci_version(hba);
return ufshcd_readl(hba, REG_UFS_VERSION);
}
@@ -627,6 +625,7 @@ start:
out:
return rc;
}
+EXPORT_SYMBOL_GPL(ufshcd_hold);
static void ufshcd_gate_work(struct work_struct *work)
{
@@ -714,6 +713,7 @@ void ufshcd_release(struct ufs_hba *hba)
__ufshcd_release(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
}
+EXPORT_SYMBOL_GPL(ufshcd_release);
static ssize_t ufshcd_clkgate_delay_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -2473,9 +2473,8 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
dev_err(hba->dev,
"%s: power mode change failed %d\n", __func__, ret);
} else {
- if (hba->vops && hba->vops->pwr_change_notify)
- hba->vops->pwr_change_notify(hba,
- POST_CHANGE, NULL, pwr_mode);
+ ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
+ pwr_mode);
memcpy(&hba->pwr_info, pwr_mode,
sizeof(struct ufs_pa_layer_attr));
@@ -2495,10 +2494,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
struct ufs_pa_layer_attr final_params = { 0 };
int ret;
- if (hba->vops && hba->vops->pwr_change_notify)
- hba->vops->pwr_change_notify(hba,
- PRE_CHANGE, desired_pwr_mode, &final_params);
- else
+ ret = ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE,
+ desired_pwr_mode, &final_params);
+
+ if (ret)
memcpy(&final_params, desired_pwr_mode, sizeof(final_params));
ret = ufshcd_change_power_mode(hba, &final_params);
@@ -2647,8 +2646,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
/* UniPro link is disabled at this point */
ufshcd_set_link_off(hba);
- if (hba->vops && hba->vops->hce_enable_notify)
- hba->vops->hce_enable_notify(hba, PRE_CHANGE);
+ ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
/* start controller initialization sequence */
ufshcd_hba_start(hba);
@@ -2681,8 +2679,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
/* enable UIC related interrupts */
ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
- if (hba->vops && hba->vops->hce_enable_notify)
- hba->vops->hce_enable_notify(hba, POST_CHANGE);
+ ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
return 0;
}
@@ -2735,8 +2732,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
int retries = DME_LINKSTARTUP_RETRIES;
do {
- if (hba->vops && hba->vops->link_startup_notify)
- hba->vops->link_startup_notify(hba, PRE_CHANGE);
+ ufshcd_vops_link_startup_notify(hba, PRE_CHANGE);
ret = ufshcd_dme_link_startup(hba);
@@ -2767,11 +2763,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
}
/* Include any host controller configuration via UIC commands */
- if (hba->vops && hba->vops->link_startup_notify) {
- ret = hba->vops->link_startup_notify(hba, POST_CHANGE);
- if (ret)
- goto out;
- }
+ ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
+ if (ret)
+ goto out;
ret = ufshcd_make_hba_operational(hba);
out:
@@ -4355,7 +4349,6 @@ static struct scsi_host_template ufshcd_driver_template = {
.cmd_per_lun = UFSHCD_CMD_PER_LUN,
.can_queue = UFSHCD_CAN_QUEUE,
.max_host_blocked = 1,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -4578,8 +4571,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
}
}
- if (hba->vops && hba->vops->setup_clocks)
- ret = hba->vops->setup_clocks(hba, on);
+ ret = ufshcd_vops_setup_clocks(hba, on);
out:
if (ret) {
list_for_each_entry(clki, head, list) {
@@ -4645,27 +4637,22 @@ static int ufshcd_variant_hba_init(struct ufs_hba *hba)
if (!hba->vops)
goto out;
- if (hba->vops->init) {
- err = hba->vops->init(hba);
- if (err)
- goto out;
- }
+ err = ufshcd_vops_init(hba);
+ if (err)
+ goto out;
- if (hba->vops->setup_regulators) {
- err = hba->vops->setup_regulators(hba, true);
- if (err)
- goto out_exit;
- }
+ err = ufshcd_vops_setup_regulators(hba, true);
+ if (err)
+ goto out_exit;
goto out;
out_exit:
- if (hba->vops->exit)
- hba->vops->exit(hba);
+ ufshcd_vops_exit(hba);
out:
if (err)
dev_err(hba->dev, "%s: variant %s init failed err %d\n",
- __func__, hba->vops ? hba->vops->name : "", err);
+ __func__, ufshcd_get_var_name(hba), err);
return err;
}
@@ -4674,14 +4661,11 @@ static void ufshcd_variant_hba_exit(struct ufs_hba *hba)
if (!hba->vops)
return;
- if (hba->vops->setup_clocks)
- hba->vops->setup_clocks(hba, false);
+ ufshcd_vops_setup_clocks(hba, false);
- if (hba->vops->setup_regulators)
- hba->vops->setup_regulators(hba, false);
+ ufshcd_vops_setup_regulators(hba, false);
- if (hba->vops->exit)
- hba->vops->exit(hba);
+ ufshcd_vops_exit(hba);
}
static int ufshcd_hba_init(struct ufs_hba *hba)
@@ -5058,17 +5042,13 @@ disable_clks:
* vendor specific host controller register space call them before the
* host clocks are ON.
*/
- if (hba->vops && hba->vops->suspend) {
- ret = hba->vops->suspend(hba, pm_op);
- if (ret)
- goto set_link_active;
- }
+ ret = ufshcd_vops_suspend(hba, pm_op);
+ if (ret)
+ goto set_link_active;
- if (hba->vops && hba->vops->setup_clocks) {
- ret = hba->vops->setup_clocks(hba, false);
- if (ret)
- goto vops_resume;
- }
+ ret = ufshcd_vops_setup_clocks(hba, false);
+ if (ret)
+ goto vops_resume;
if (!ufshcd_is_link_active(hba))
ufshcd_setup_clocks(hba, false);
@@ -5079,7 +5059,7 @@ disable_clks:
hba->clk_gating.state = CLKS_OFF;
/*
* Disable the host irq as host controller as there won't be any
- * host controller trasanction expected till resume.
+ * host controller transaction expected till resume.
*/
ufshcd_disable_irq(hba);
/* Put the host controller in low power mode if possible */
@@ -5087,8 +5067,7 @@ disable_clks:
goto out;
vops_resume:
- if (hba->vops && hba->vops->resume)
- hba->vops->resume(hba, pm_op);
+ ufshcd_vops_resume(hba, pm_op);
set_link_active:
ufshcd_vreg_set_hpm(hba);
if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
@@ -5144,11 +5123,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
* vendor specific host controller register space call them when the
* host clocks are ON.
*/
- if (hba->vops && hba->vops->resume) {
- ret = hba->vops->resume(hba, pm_op);
- if (ret)
- goto disable_vreg;
- }
+ ret = ufshcd_vops_resume(hba, pm_op);
+ if (ret)
+ goto disable_vreg;
if (ufshcd_is_link_hibern8(hba)) {
ret = ufshcd_uic_hibern8_exit(hba);
@@ -5189,8 +5166,7 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
set_old_link_state:
ufshcd_link_state_transition(hba, old_link_state, 0);
vendor_suspend:
- if (hba->vops && hba->vops->suspend)
- hba->vops->suspend(hba, pm_op);
+ ufshcd_vops_suspend(hba, pm_op);
disable_vreg:
ufshcd_vreg_set_lpm(hba);
disable_irq_and_vops_clks:
@@ -5373,6 +5349,16 @@ void ufshcd_remove(struct ufs_hba *hba)
EXPORT_SYMBOL_GPL(ufshcd_remove);
/**
+ * ufshcd_dealloc_host - deallocate Host Bus Adapter (HBA)
+ * @hba: pointer to Host Bus Adapter (HBA)
+ */
+void ufshcd_dealloc_host(struct ufs_hba *hba)
+{
+ scsi_host_put(hba->host);
+}
+EXPORT_SYMBOL_GPL(ufshcd_dealloc_host);
+
+/**
* ufshcd_set_dma_mask - Set dma mask based on the controller
* addressing capability
* @hba: per adapter instance
@@ -5433,6 +5419,10 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
if (!head || list_empty(head))
goto out;
+ ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE);
+ if (ret)
+ return ret;
+
list_for_each_entry(clki, head, list) {
if (!IS_ERR_OR_NULL(clki->clk)) {
if (scale_up && clki->max_freq) {
@@ -5463,8 +5453,9 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
dev_dbg(hba->dev, "%s: clk: %s, rate: %lu\n", __func__,
clki->name, clk_get_rate(clki->clk));
}
- if (hba->vops->clk_scale_notify)
- hba->vops->clk_scale_notify(hba);
+
+ ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE);
+
out:
return ret;
}
@@ -5619,13 +5610,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
hba->is_irq_enabled = true;
}
- /* Enable SCSI tag mapping */
- err = scsi_init_shared_tag_map(host, host->can_queue);
- if (err) {
- dev_err(hba->dev, "init shared queue failed\n");
- goto exit_gating;
- }
-
err = scsi_add_host(host, hba->dev);
if (err) {
dev_err(hba->dev, "scsi_add_host failed\n");
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index c40a0e78a6c4..2570d9477b37 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -223,8 +223,10 @@ struct ufs_clk_info {
bool enabled;
};
-#define PRE_CHANGE 0
-#define POST_CHANGE 1
+enum ufs_notify_change_status {
+ PRE_CHANGE,
+ POST_CHANGE,
+};
struct ufs_pa_layer_attr {
u32 gear_rx;
@@ -259,22 +261,28 @@ struct ufs_pwr_mode_info {
* to be set.
* @suspend: called during host controller PM callback
* @resume: called during host controller PM callback
+ * @dbg_register_dump: used to dump controller debug information
*/
struct ufs_hba_variant_ops {
const char *name;
int (*init)(struct ufs_hba *);
void (*exit)(struct ufs_hba *);
u32 (*get_ufs_hci_version)(struct ufs_hba *);
- void (*clk_scale_notify)(struct ufs_hba *);
- int (*setup_clocks)(struct ufs_hba *, bool);
+ int (*clk_scale_notify)(struct ufs_hba *, bool,
+ enum ufs_notify_change_status);
+ int (*setup_clocks)(struct ufs_hba *, bool);
int (*setup_regulators)(struct ufs_hba *, bool);
- int (*hce_enable_notify)(struct ufs_hba *, bool);
- int (*link_startup_notify)(struct ufs_hba *, bool);
+ int (*hce_enable_notify)(struct ufs_hba *,
+ enum ufs_notify_change_status);
+ int (*link_startup_notify)(struct ufs_hba *,
+ enum ufs_notify_change_status);
int (*pwr_change_notify)(struct ufs_hba *,
- bool, struct ufs_pa_layer_attr *,
+ enum ufs_notify_change_status status,
+ struct ufs_pa_layer_attr *,
struct ufs_pa_layer_attr *);
int (*suspend)(struct ufs_hba *, enum ufs_pm_op);
int (*resume)(struct ufs_hba *, enum ufs_pm_op);
+ void (*dbg_register_dump)(struct ufs_hba *hba);
};
/* clock gating state */
@@ -576,6 +584,7 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
}
int ufshcd_alloc_host(struct device *, struct ufs_hba **);
+void ufshcd_dealloc_host(struct ufs_hba *);
int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int);
void ufshcd_remove(struct ufs_hba *);
@@ -594,6 +603,27 @@ static inline void check_upiu_size(void)
GENERAL_UPIU_REQUEST_SIZE + QUERY_DESC_MAX_SIZE);
}
+/**
+ * ufshcd_set_variant - set variant specific data to the hba
+ * @hba - per adapter instance
+ * @variant - pointer to variant specific data
+ */
+static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant)
+{
+ BUG_ON(!hba);
+ hba->priv = variant;
+}
+
+/**
+ * ufshcd_get_variant - get variant specific data from the hba
+ * @hba - per adapter instance
+ */
+static inline void *ufshcd_get_variant(struct ufs_hba *hba)
+{
+ BUG_ON(!hba);
+ return hba->priv;
+}
+
extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
extern int ufshcd_runtime_resume(struct ufs_hba *hba);
extern int ufshcd_runtime_idle(struct ufs_hba *hba);
@@ -653,4 +683,109 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
+
+/* Wrapper functions for safely calling variant operations */
+static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
+{
+ if (hba->vops)
+ return hba->vops->name;
+ return "";
+}
+
+static inline int ufshcd_vops_init(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->init)
+ return hba->vops->init(hba);
+
+ return 0;
+}
+
+static inline void ufshcd_vops_exit(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->exit)
+ return hba->vops->exit(hba);
+}
+
+static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->get_ufs_hci_version)
+ return hba->vops->get_ufs_hci_version(hba);
+
+ return ufshcd_readl(hba, REG_UFS_VERSION);
+}
+
+static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba,
+ bool up, enum ufs_notify_change_status status)
+{
+ if (hba->vops && hba->vops->clk_scale_notify)
+ return hba->vops->clk_scale_notify(hba, up, status);
+ return 0;
+}
+
+static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on)
+{
+ if (hba->vops && hba->vops->setup_clocks)
+ return hba->vops->setup_clocks(hba, on);
+ return 0;
+}
+
+static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status)
+{
+ if (hba->vops && hba->vops->setup_regulators)
+ return hba->vops->setup_regulators(hba, status);
+
+ return 0;
+}
+
+static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba,
+ bool status)
+{
+ if (hba->vops && hba->vops->hce_enable_notify)
+ return hba->vops->hce_enable_notify(hba, status);
+
+ return 0;
+}
+static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba,
+ bool status)
+{
+ if (hba->vops && hba->vops->link_startup_notify)
+ return hba->vops->link_startup_notify(hba, status);
+
+ return 0;
+}
+
+static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
+ bool status,
+ struct ufs_pa_layer_attr *dev_max_params,
+ struct ufs_pa_layer_attr *dev_req_params)
+{
+ if (hba->vops && hba->vops->pwr_change_notify)
+ return hba->vops->pwr_change_notify(hba, status,
+ dev_max_params, dev_req_params);
+
+ return -ENOTSUPP;
+}
+
+static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+ if (hba->vops && hba->vops->suspend)
+ return hba->vops->suspend(hba, op);
+
+ return 0;
+}
+
+static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+ if (hba->vops && hba->vops->resume)
+ return hba->vops->resume(hba, op);
+
+ return 0;
+}
+
+static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->dbg_register_dump)
+ hba->vops->dbg_register_dump(hba);
+}
+
#endif /* End of Header */
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c
index 25abd4eb7d10..91a003011acf 100644
--- a/drivers/sh/pm_runtime.c
+++ b/drivers/sh/pm_runtime.c
@@ -34,7 +34,7 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
static int __init sh_pm_runtime_init(void)
{
- if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
+ if (IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
if (!of_find_compatible_node(NULL, NULL,
"renesas,cpg-mstp-clocks"))
return 0;
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 96ddecb92254..4e853ed2c82b 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,7 +1,9 @@
menu "SOC (System On Chip) specific Drivers"
+source "drivers/soc/brcmstb/Kconfig"
source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
+source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/ti/Kconfig"
source "drivers/soc/versatile/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 0b12d777d3c4..f2ba2e932ae1 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,9 +2,11 @@
# Makefile for the Linux Kernel SOC specific device drivers.
#
+obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
obj-$(CONFIG_MACH_DOVE) += dove/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
new file mode 100644
index 000000000000..39cab3bd544d
--- /dev/null
+++ b/drivers/soc/brcmstb/Kconfig
@@ -0,0 +1,9 @@
+menuconfig SOC_BRCMSTB
+ bool "Broadcom STB SoC drivers"
+ depends on ARM
+ help
+ Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
+ This option alone enables only some support code, while the drivers
+ can be enabled individually within this menu.
+
+ If unsure, say N.
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile
new file mode 100644
index 000000000000..9120b2715d3e
--- /dev/null
+++ b/drivers/soc/brcmstb/Makefile
@@ -0,0 +1 @@
+obj-y += common.o biuctrl.o
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/brcmstb/biuctrl.c
new file mode 100644
index 000000000000..9049c076f9a1
--- /dev/null
+++ b/drivers/soc/brcmstb/biuctrl.c
@@ -0,0 +1,116 @@
+/*
+ * Broadcom STB SoCs Bus Unit Interface controls
+ *
+ * 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 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.
+ */
+
+#define pr_fmt(fmt) "brcmstb: " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#define CPU_CREDIT_REG_OFFSET 0x184
+#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
+
+static void __iomem *cpubiuctrl_base;
+static bool mcp_wr_pairing_en;
+
+static int __init mcp_write_pairing_set(void)
+{
+ u32 creds = 0;
+
+ if (!cpubiuctrl_base)
+ return -1;
+
+ creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+ if (mcp_wr_pairing_en) {
+ pr_info("MCP: Enabling write pairing\n");
+ writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
+ cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+ } else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
+ pr_info("MCP: Disabling write pairing\n");
+ writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
+ cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+ } else {
+ pr_info("MCP: Write pairing already disabled\n");
+ }
+
+ return 0;
+}
+
+static int __init setup_hifcpubiuctrl_regs(void)
+{
+ struct device_node *np;
+ int ret = 0;
+
+ np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
+ if (!np) {
+ pr_err("missing BIU control node\n");
+ return -ENODEV;
+ }
+
+ cpubiuctrl_base = of_iomap(np, 0);
+ if (!cpubiuctrl_base) {
+ pr_err("failed to remap BIU control base\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
+out:
+ of_node_put(np);
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static u32 cpu_credit_reg_dump; /* for save/restore */
+
+static int brcmstb_cpu_credit_reg_suspend(void)
+{
+ if (cpubiuctrl_base)
+ cpu_credit_reg_dump =
+ readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+ return 0;
+}
+
+static void brcmstb_cpu_credit_reg_resume(void)
+{
+ if (cpubiuctrl_base)
+ writel_relaxed(cpu_credit_reg_dump,
+ cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+}
+
+static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
+ .suspend = brcmstb_cpu_credit_reg_suspend,
+ .resume = brcmstb_cpu_credit_reg_resume,
+};
+#endif
+
+
+void __init brcmstb_biuctrl_init(void)
+{
+ int ret;
+
+ setup_hifcpubiuctrl_regs();
+
+ ret = mcp_write_pairing_set();
+ if (ret) {
+ pr_err("MCP: Unable to disable write pairing!\n");
+ return;
+ }
+
+#ifdef CONFIG_PM_SLEEP
+ register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
+#endif
+}
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
new file mode 100644
index 000000000000..c262c029b1b8
--- /dev/null
+++ b/drivers/soc/brcmstb/common.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ * Copyright © 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 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.
+ */
+
+#include <linux/of.h>
+
+#include <soc/brcmstb/common.h>
+
+static const struct of_device_id brcmstb_machine_match[] = {
+ { .compatible = "brcm,brcmstb", },
+ { }
+};
+
+bool soc_is_brcmstb(void)
+{
+ struct device_node *root;
+
+ root = of_find_node_by_path("/");
+ if (!root)
+ return false;
+
+ return of_match_node(brcmstb_machine_match, root) != NULL;
+}
diff --git a/drivers/soc/dove/pmu.c b/drivers/soc/dove/pmu.c
index 052aecf29893..abd087917f80 100644
--- a/drivers/soc/dove/pmu.c
+++ b/drivers/soc/dove/pmu.c
@@ -396,7 +396,6 @@ int __init dove_init_pmu(void)
__pmu_domain_register(domain, np);
}
- pm_genpd_poweroff_unused();
/* Loss of the interrupt controller is not a fatal error. */
parent_irq = irq_of_parse_and_map(pmu->of_node, 0);
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 8bc7b41b09fd..105597a885cb 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -725,10 +725,6 @@ static int pwrap_init(struct pmic_wrapper *wrp)
pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
- pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
- pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
- pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
- pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
if (pwrap_is_mt8135(wrp)) {
/* enable pwrap events and pwrap bridge in AP side */
@@ -896,6 +892,12 @@ static int pwrap_probe(struct platform_device *pdev)
return -ENODEV;
}
+ /* Initialize watchdog, may not be done by the bootloader */
+ pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+ pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+ pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
+
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
"mt-pmic-pwrap", wrp);
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 164a7d8439b1..4d4203c896c4 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -54,12 +54,16 @@
#define PWR_STATUS_USB BIT(25)
enum clk_id {
+ MT8173_CLK_NONE,
MT8173_CLK_MM,
MT8173_CLK_MFG,
- MT8173_CLK_NONE,
- MT8173_CLK_MAX = MT8173_CLK_NONE,
+ MT8173_CLK_VENC,
+ MT8173_CLK_VENC_LT,
+ MT8173_CLK_MAX,
};
+#define MAX_CLKS 2
+
struct scp_domain_data {
const char *name;
u32 sta_mask;
@@ -67,7 +71,8 @@ struct scp_domain_data {
u32 sram_pdn_bits;
u32 sram_pdn_ack_bits;
u32 bus_prot_mask;
- enum clk_id clk_id;
+ enum clk_id clk_id[MAX_CLKS];
+ bool active_wakeup;
};
static const struct scp_domain_data scp_domain_data[] __initconst = {
@@ -77,7 +82,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VDE_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
- .clk_id = MT8173_CLK_MM,
+ .clk_id = {MT8173_CLK_MM},
},
[MT8173_POWER_DOMAIN_VENC] = {
.name = "venc",
@@ -85,7 +90,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VEN_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
- .clk_id = MT8173_CLK_MM,
+ .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
},
[MT8173_POWER_DOMAIN_ISP] = {
.name = "isp",
@@ -93,7 +98,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_ISP_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
- .clk_id = MT8173_CLK_MM,
+ .clk_id = {MT8173_CLK_MM},
},
[MT8173_POWER_DOMAIN_MM] = {
.name = "mm",
@@ -101,7 +106,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_DIS_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
- .clk_id = MT8173_CLK_MM,
+ .clk_id = {MT8173_CLK_MM},
.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
MT8173_TOP_AXI_PROT_EN_MM_M1,
},
@@ -111,7 +116,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VEN2_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
- .clk_id = MT8173_CLK_MM,
+ .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT},
},
[MT8173_POWER_DOMAIN_AUDIO] = {
.name = "audio",
@@ -119,7 +124,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_AUDIO_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
- .clk_id = MT8173_CLK_NONE,
+ .clk_id = {MT8173_CLK_NONE},
},
[MT8173_POWER_DOMAIN_USB] = {
.name = "usb",
@@ -127,7 +132,8 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_USB_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
- .clk_id = MT8173_CLK_NONE,
+ .clk_id = {MT8173_CLK_NONE},
+ .active_wakeup = true,
},
[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
.name = "mfg_async",
@@ -135,7 +141,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = 0,
- .clk_id = MT8173_CLK_MFG,
+ .clk_id = {MT8173_CLK_MFG},
},
[MT8173_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d",
@@ -143,7 +149,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_2D_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
- .clk_id = MT8173_CLK_NONE,
+ .clk_id = {MT8173_CLK_NONE},
},
[MT8173_POWER_DOMAIN_MFG] = {
.name = "mfg",
@@ -151,7 +157,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_PWR_CON,
.sram_pdn_bits = GENMASK(13, 8),
.sram_pdn_ack_bits = GENMASK(21, 16),
- .clk_id = MT8173_CLK_NONE,
+ .clk_id = {MT8173_CLK_NONE},
.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
MT8173_TOP_AXI_PROT_EN_MFG_M0 |
MT8173_TOP_AXI_PROT_EN_MFG_M1 |
@@ -166,12 +172,13 @@ struct scp;
struct scp_domain {
struct generic_pm_domain genpd;
struct scp *scp;
- struct clk *clk;
+ struct clk *clk[MAX_CLKS];
u32 sta_mask;
void __iomem *ctl_addr;
u32 sram_pdn_bits;
u32 sram_pdn_ack_bits;
u32 bus_prot_mask;
+ bool active_wakeup;
};
struct scp {
@@ -212,11 +219,16 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
u32 val;
int ret;
+ int i;
+
+ for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
+ ret = clk_prepare_enable(scpd->clk[i]);
+ if (ret) {
+ for (--i; i >= 0; i--)
+ clk_disable_unprepare(scpd->clk[i]);
- if (scpd->clk) {
- ret = clk_prepare_enable(scpd->clk);
- if (ret)
goto err_clk;
+ }
}
val = readl(ctl_addr);
@@ -282,7 +294,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
return 0;
err_pwr_ack:
- clk_disable_unprepare(scpd->clk);
+ for (i = MAX_CLKS - 1; i >= 0; i--) {
+ if (scpd->clk[i])
+ clk_disable_unprepare(scpd->clk[i]);
+ }
err_clk:
dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
@@ -299,6 +314,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
u32 pdn_ack = scpd->sram_pdn_ack_bits;
u32 val;
int ret;
+ int i;
if (scpd->bus_prot_mask) {
ret = mtk_infracfg_set_bus_protection(scp->infracfg,
@@ -360,8 +376,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
expired = true;
}
- if (scpd->clk)
- clk_disable_unprepare(scpd->clk);
+ for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
+ clk_disable_unprepare(scpd->clk[i]);
return 0;
@@ -371,11 +387,22 @@ out:
return ret;
}
+static bool scpsys_active_wakeup(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ struct scp_domain *scpd;
+
+ genpd = pd_to_genpd(dev->pm_domain);
+ scpd = container_of(genpd, struct scp_domain, genpd);
+
+ return scpd->active_wakeup;
+}
+
static int __init scpsys_probe(struct platform_device *pdev)
{
struct genpd_onecell_data *pd_data;
struct resource *res;
- int i, ret;
+ int i, j, ret;
struct scp *scp;
struct clk *clk[MT8173_CLK_MAX];
@@ -405,6 +432,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
if (IS_ERR(clk[MT8173_CLK_MFG]))
return PTR_ERR(clk[MT8173_CLK_MFG]);
+ clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc");
+ if (IS_ERR(clk[MT8173_CLK_VENC]))
+ return PTR_ERR(clk[MT8173_CLK_VENC]);
+
+ clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt");
+ if (IS_ERR(clk[MT8173_CLK_VENC_LT]))
+ return PTR_ERR(clk[MT8173_CLK_VENC_LT]);
+
scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"infracfg");
if (IS_ERR(scp->infracfg)) {
@@ -428,12 +463,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
scpd->sram_pdn_bits = data->sram_pdn_bits;
scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
scpd->bus_prot_mask = data->bus_prot_mask;
- if (data->clk_id != MT8173_CLK_NONE)
- scpd->clk = clk[data->clk_id];
+ scpd->active_wakeup = data->active_wakeup;
+ for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
+ scpd->clk[j] = clk[data->clk_id[j]];
genpd->name = data->name;
genpd->power_off = scpsys_power_off;
genpd->power_on = scpsys_power_on;
+ genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
/*
* Initially turn on all domains to make the domains usable
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index ba47b70f4d85..eec76141d9b9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -19,6 +19,15 @@ config QCOM_PM
modes. It interface with various system drivers to put the cores in
low power modes.
+config QCOM_SMEM
+ tristate "Qualcomm Shared Memory Manager (SMEM)"
+ depends on ARCH_QCOM
+ depends on HWSPINLOCK
+ help
+ Say y here to enable support for the Qualcomm Shared Memory Manager.
+ The driver provides an interface to items in a heap shared among all
+ processors in a Qualcomm platform.
+
config QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
depends on QCOM_SMEM
@@ -40,11 +49,3 @@ config QCOM_SMD_RPM
Say M here if you want to include support for the Qualcomm RPM as a
module. This will build a module called "qcom-smd-rpm".
-
-config QCOM_SMEM
- tristate "Qualcomm Shared Memory Manager (SMEM)"
- depends on ARCH_QCOM
- help
- Say y here to enable support for the Qualcomm Shared Memory Manager.
- The driver provides an interface to items in a heap shared among all
- processors in a Qualcomm platform.
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 1392ccf14a20..2969321e1b09 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <linux/io.h>
#include <linux/interrupt.h>
+#include <linux/slab.h>
#include <linux/soc/qcom/smd.h>
#include <linux/soc/qcom/smd-rpm.h>
@@ -44,8 +45,8 @@ struct qcom_smd_rpm {
* @length: length of the payload
*/
struct qcom_rpm_header {
- u32 service_type;
- u32 length;
+ __le32 service_type;
+ __le32 length;
};
/**
@@ -57,11 +58,11 @@ struct qcom_rpm_header {
* @data_len: length of the payload following this header
*/
struct qcom_rpm_request {
- u32 msg_id;
- u32 flags;
- u32 type;
- u32 id;
- u32 data_len;
+ __le32 msg_id;
+ __le32 flags;
+ __le32 type;
+ __le32 id;
+ __le32 data_len;
};
/**
@@ -74,10 +75,10 @@ struct qcom_rpm_request {
* Multiple of these messages can be stacked in an rpm message.
*/
struct qcom_rpm_message {
- u32 msg_type;
- u32 length;
+ __le32 msg_type;
+ __le32 length;
union {
- u32 msg_id;
+ __le32 msg_id;
u8 message[0];
};
};
@@ -104,30 +105,34 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
static unsigned msg_id = 1;
int left;
int ret;
-
struct {
struct qcom_rpm_header hdr;
struct qcom_rpm_request req;
- u8 payload[count];
- } pkt;
+ u8 payload[];
+ } *pkt;
+ size_t size = sizeof(*pkt) + count;
/* SMD packets to the RPM may not exceed 256 bytes */
- if (WARN_ON(sizeof(pkt) >= 256))
+ if (WARN_ON(size >= 256))
return -EINVAL;
+ pkt = kmalloc(size, GFP_KERNEL);
+ if (!pkt)
+ return -ENOMEM;
+
mutex_lock(&rpm->lock);
- pkt.hdr.service_type = RPM_SERVICE_TYPE_REQUEST;
- pkt.hdr.length = sizeof(struct qcom_rpm_request) + count;
+ pkt->hdr.service_type = cpu_to_le32(RPM_SERVICE_TYPE_REQUEST);
+ pkt->hdr.length = cpu_to_le32(sizeof(struct qcom_rpm_request) + count);
- pkt.req.msg_id = msg_id++;
- pkt.req.flags = BIT(state);
- pkt.req.type = type;
- pkt.req.id = id;
- pkt.req.data_len = count;
- memcpy(pkt.payload, buf, count);
+ pkt->req.msg_id = cpu_to_le32(msg_id++);
+ pkt->req.flags = cpu_to_le32(state);
+ pkt->req.type = cpu_to_le32(type);
+ pkt->req.id = cpu_to_le32(id);
+ pkt->req.data_len = cpu_to_le32(count);
+ memcpy(pkt->payload, buf, count);
- ret = qcom_smd_send(rpm->rpm_channel, &pkt, sizeof(pkt));
+ ret = qcom_smd_send(rpm->rpm_channel, pkt, size);
if (ret)
goto out;
@@ -138,6 +143,7 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
ret = rpm->ack_status;
out:
+ kfree(pkt);
mutex_unlock(&rpm->lock);
return ret;
}
@@ -148,27 +154,29 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
size_t count)
{
const struct qcom_rpm_header *hdr = data;
+ size_t hdr_length = le32_to_cpu(hdr->length);
const struct qcom_rpm_message *msg;
struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev);
const u8 *buf = data + sizeof(struct qcom_rpm_header);
- const u8 *end = buf + hdr->length;
+ const u8 *end = buf + hdr_length;
char msgbuf[32];
int status = 0;
- u32 len;
+ u32 len, msg_length;
- if (hdr->service_type != RPM_SERVICE_TYPE_REQUEST ||
- hdr->length < sizeof(struct qcom_rpm_message)) {
+ if (le32_to_cpu(hdr->service_type) != RPM_SERVICE_TYPE_REQUEST ||
+ hdr_length < sizeof(struct qcom_rpm_message)) {
dev_err(&qsdev->dev, "invalid request\n");
return 0;
}
while (buf < end) {
msg = (struct qcom_rpm_message *)buf;
- switch (msg->msg_type) {
+ msg_length = le32_to_cpu(msg->length);
+ switch (le32_to_cpu(msg->msg_type)) {
case RPM_MSG_TYPE_MSG_ID:
break;
case RPM_MSG_TYPE_ERR:
- len = min_t(u32, ALIGN(msg->length, 4), sizeof(msgbuf));
+ len = min_t(u32, ALIGN(msg_length, 4), sizeof(msgbuf));
memcpy_fromio(msgbuf, msg->message, len);
msgbuf[len - 1] = 0;
@@ -179,7 +187,7 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
break;
}
- buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg->length, 4);
+ buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg_length, 4);
}
rpm->ack_status = status;
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
index a6155c917d52..86b598cff91a 100644
--- a/drivers/soc/qcom/smd.c
+++ b/drivers/soc/qcom/smd.c
@@ -65,7 +65,9 @@
*/
struct smd_channel_info;
+struct smd_channel_info_pair;
struct smd_channel_info_word;
+struct smd_channel_info_word_pair;
#define SMD_ALLOC_TBL_COUNT 2
#define SMD_ALLOC_TBL_SIZE 64
@@ -85,8 +87,8 @@ static const struct {
.fifo_base_id = 338
},
{
- .alloc_tbl_id = 14,
- .info_base_id = 266,
+ .alloc_tbl_id = 266,
+ .info_base_id = 138,
.fifo_base_id = 202,
},
};
@@ -151,10 +153,8 @@ enum smd_channel_state {
* @name: name of the channel
* @state: local state of the channel
* @remote_state: remote state of the channel
- * @tx_info: byte aligned outgoing channel info
- * @rx_info: byte aligned incoming channel info
- * @tx_info_word: word aligned outgoing channel info
- * @rx_info_word: word aligned incoming channel info
+ * @info: byte aligned outgoing/incoming channel info
+ * @info_word: word aligned outgoing/incoming channel info
* @tx_lock: lock to make writes to the channel mutually exclusive
* @fblockread_event: wakeup event tied to tx fBLOCKREADINTR
* @tx_fifo: pointer to the outgoing ring buffer
@@ -175,11 +175,8 @@ struct qcom_smd_channel {
enum smd_channel_state state;
enum smd_channel_state remote_state;
- struct smd_channel_info *tx_info;
- struct smd_channel_info *rx_info;
-
- struct smd_channel_info_word *tx_info_word;
- struct smd_channel_info_word *rx_info_word;
+ struct smd_channel_info_pair *info;
+ struct smd_channel_info_word_pair *info_word;
struct mutex tx_lock;
wait_queue_head_t fblockread_event;
@@ -215,7 +212,7 @@ struct qcom_smd {
* Format of the smd_info smem items, for byte aligned channels.
*/
struct smd_channel_info {
- u32 state;
+ __le32 state;
u8 fDSR;
u8 fCTS;
u8 fCD;
@@ -224,46 +221,104 @@ struct smd_channel_info {
u8 fTAIL;
u8 fSTATE;
u8 fBLOCKREADINTR;
- u32 tail;
- u32 head;
+ __le32 tail;
+ __le32 head;
+};
+
+struct smd_channel_info_pair {
+ struct smd_channel_info tx;
+ struct smd_channel_info rx;
};
/*
* Format of the smd_info smem items, for word aligned channels.
*/
struct smd_channel_info_word {
- u32 state;
- u32 fDSR;
- u32 fCTS;
- u32 fCD;
- u32 fRI;
- u32 fHEAD;
- u32 fTAIL;
- u32 fSTATE;
- u32 fBLOCKREADINTR;
- u32 tail;
- u32 head;
+ __le32 state;
+ __le32 fDSR;
+ __le32 fCTS;
+ __le32 fCD;
+ __le32 fRI;
+ __le32 fHEAD;
+ __le32 fTAIL;
+ __le32 fSTATE;
+ __le32 fBLOCKREADINTR;
+ __le32 tail;
+ __le32 head;
};
-#define GET_RX_CHANNEL_INFO(channel, param) \
- (channel->rx_info_word ? \
- channel->rx_info_word->param : \
- channel->rx_info->param)
-
-#define SET_RX_CHANNEL_INFO(channel, param, value) \
- (channel->rx_info_word ? \
- (channel->rx_info_word->param = value) : \
- (channel->rx_info->param = value))
-
-#define GET_TX_CHANNEL_INFO(channel, param) \
- (channel->tx_info_word ? \
- channel->tx_info_word->param : \
- channel->tx_info->param)
+struct smd_channel_info_word_pair {
+ struct smd_channel_info_word tx;
+ struct smd_channel_info_word rx;
+};
-#define SET_TX_CHANNEL_INFO(channel, param, value) \
- (channel->tx_info_word ? \
- (channel->tx_info_word->param = value) : \
- (channel->tx_info->param = value))
+#define GET_RX_CHANNEL_FLAG(channel, param) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
+ channel->info_word ? \
+ le32_to_cpu(channel->info_word->rx.param) : \
+ channel->info->rx.param; \
+ })
+
+#define GET_RX_CHANNEL_INFO(channel, param) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
+ le32_to_cpu(channel->info_word ? \
+ channel->info_word->rx.param : \
+ channel->info->rx.param); \
+ })
+
+#define SET_RX_CHANNEL_FLAG(channel, param, value) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
+ if (channel->info_word) \
+ channel->info_word->rx.param = cpu_to_le32(value); \
+ else \
+ channel->info->rx.param = value; \
+ })
+
+#define SET_RX_CHANNEL_INFO(channel, param, value) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
+ if (channel->info_word) \
+ channel->info_word->rx.param = cpu_to_le32(value); \
+ else \
+ channel->info->rx.param = cpu_to_le32(value); \
+ })
+
+#define GET_TX_CHANNEL_FLAG(channel, param) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
+ channel->info_word ? \
+ le32_to_cpu(channel->info_word->tx.param) : \
+ channel->info->tx.param; \
+ })
+
+#define GET_TX_CHANNEL_INFO(channel, param) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
+ le32_to_cpu(channel->info_word ? \
+ channel->info_word->tx.param : \
+ channel->info->tx.param); \
+ })
+
+#define SET_TX_CHANNEL_FLAG(channel, param, value) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
+ if (channel->info_word) \
+ channel->info_word->tx.param = cpu_to_le32(value); \
+ else \
+ channel->info->tx.param = value; \
+ })
+
+#define SET_TX_CHANNEL_INFO(channel, param, value) \
+ ({ \
+ BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
+ if (channel->info_word) \
+ channel->info_word->tx.param = cpu_to_le32(value); \
+ else \
+ channel->info->tx.param = cpu_to_le32(value); \
+ })
/**
* struct qcom_smd_alloc_entry - channel allocation entry
@@ -274,9 +329,9 @@ struct smd_channel_info_word {
*/
struct qcom_smd_alloc_entry {
u8 name[20];
- u32 cid;
- u32 flags;
- u32 ref_count;
+ __le32 cid;
+ __le32 flags;
+ __le32 ref_count;
} __packed;
#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff
@@ -305,14 +360,14 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
{
SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
- SET_TX_CHANNEL_INFO(channel, fDSR, 0);
- SET_TX_CHANNEL_INFO(channel, fCTS, 0);
- SET_TX_CHANNEL_INFO(channel, fCD, 0);
- SET_TX_CHANNEL_INFO(channel, fRI, 0);
- SET_TX_CHANNEL_INFO(channel, fHEAD, 0);
- SET_TX_CHANNEL_INFO(channel, fTAIL, 0);
- SET_TX_CHANNEL_INFO(channel, fSTATE, 1);
- SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1);
+ SET_TX_CHANNEL_FLAG(channel, fDSR, 0);
+ SET_TX_CHANNEL_FLAG(channel, fCTS, 0);
+ SET_TX_CHANNEL_FLAG(channel, fCD, 0);
+ SET_TX_CHANNEL_FLAG(channel, fRI, 0);
+ SET_TX_CHANNEL_FLAG(channel, fHEAD, 0);
+ SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
+ SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
+ SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
SET_TX_CHANNEL_INFO(channel, head, 0);
SET_TX_CHANNEL_INFO(channel, tail, 0);
@@ -350,12 +405,12 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state);
- SET_TX_CHANNEL_INFO(channel, fDSR, is_open);
- SET_TX_CHANNEL_INFO(channel, fCTS, is_open);
- SET_TX_CHANNEL_INFO(channel, fCD, is_open);
+ SET_TX_CHANNEL_FLAG(channel, fDSR, is_open);
+ SET_TX_CHANNEL_FLAG(channel, fCTS, is_open);
+ SET_TX_CHANNEL_FLAG(channel, fCD, is_open);
SET_TX_CHANNEL_INFO(channel, state, state);
- SET_TX_CHANNEL_INFO(channel, fSTATE, 1);
+ SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
channel->state = state;
qcom_smd_signal_channel(channel);
@@ -364,20 +419,15 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
/*
* Copy count bytes of data using 32bit accesses, if that's required.
*/
-static void smd_copy_to_fifo(void __iomem *_dst,
- const void *_src,
+static void smd_copy_to_fifo(void __iomem *dst,
+ const void *src,
size_t count,
bool word_aligned)
{
- u32 *dst = (u32 *)_dst;
- u32 *src = (u32 *)_src;
-
if (word_aligned) {
- count /= sizeof(u32);
- while (count--)
- writel_relaxed(*src++, dst++);
+ __iowrite32_copy(dst, src, count / sizeof(u32));
} else {
- memcpy_toio(_dst, _src, count);
+ memcpy_toio(dst, src, count);
}
}
@@ -395,7 +445,7 @@ static void smd_copy_from_fifo(void *_dst,
if (word_aligned) {
count /= sizeof(u32);
while (count--)
- *dst++ = readl_relaxed(src++);
+ *dst++ = __raw_readl(src++);
} else {
memcpy_fromio(_dst, _src, count);
}
@@ -412,7 +462,7 @@ static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel,
unsigned tail;
size_t len;
- word_aligned = channel->rx_info_word != NULL;
+ word_aligned = channel->info_word;
tail = GET_RX_CHANNEL_INFO(channel, tail);
len = min_t(size_t, count, channel->fifo_size - tail);
@@ -491,7 +541,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
{
bool need_state_scan = false;
int remote_state;
- u32 pktlen;
+ __le32 pktlen;
int avail;
int ret;
@@ -502,10 +552,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
need_state_scan = true;
}
/* Indicate that we have seen any state change */
- SET_RX_CHANNEL_INFO(channel, fSTATE, 0);
+ SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
/* Signal waiting qcom_smd_send() about the interrupt */
- if (!GET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR))
+ if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR))
wake_up_interruptible(&channel->fblockread_event);
/* Don't consume any data until we've opened the channel */
@@ -513,7 +563,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
goto out;
/* Indicate that we've seen the new data */
- SET_RX_CHANNEL_INFO(channel, fHEAD, 0);
+ SET_RX_CHANNEL_FLAG(channel, fHEAD, 0);
/* Consume data */
for (;;) {
@@ -522,7 +572,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
- channel->pkt_size = pktlen;
+ channel->pkt_size = le32_to_cpu(pktlen);
} else if (channel->pkt_size && avail >= channel->pkt_size) {
ret = qcom_smd_channel_recv_single(channel);
if (ret)
@@ -533,10 +583,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
}
/* Indicate that we have seen and updated tail */
- SET_RX_CHANNEL_INFO(channel, fTAIL, 1);
+ SET_RX_CHANNEL_FLAG(channel, fTAIL, 1);
/* Signal the remote that we've consumed the data (if requested) */
- if (!GET_RX_CHANNEL_INFO(channel, fBLOCKREADINTR)) {
+ if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) {
/* Ensure ordering of channel info updates */
wmb();
@@ -627,7 +677,7 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
unsigned head;
size_t len;
- word_aligned = channel->tx_info_word != NULL;
+ word_aligned = channel->info_word;
head = GET_TX_CHANNEL_INFO(channel, head);
len = min_t(size_t, count, channel->fifo_size - head);
@@ -665,12 +715,16 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
*/
int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
{
- u32 hdr[5] = {len,};
+ __le32 hdr[5] = { cpu_to_le32(len), };
int tlen = sizeof(hdr) + len;
int ret;
/* Word aligned channels only accept word size aligned data */
- if (channel->rx_info_word != NULL && len % 4)
+ if (channel->info_word && len % 4)
+ return -EINVAL;
+
+ /* Reject packets that are too big */
+ if (tlen >= channel->fifo_size)
return -EINVAL;
ret = mutex_lock_interruptible(&channel->tx_lock);
@@ -683,7 +737,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
goto out;
}
- SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0);
+ SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
ret = wait_event_interruptible(channel->fblockread_event,
qcom_smd_get_tx_avail(channel) >= tlen ||
@@ -691,15 +745,15 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
if (ret)
goto out;
- SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1);
+ SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
}
- SET_TX_CHANNEL_INFO(channel, fTAIL, 0);
+ SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
qcom_smd_write_fifo(channel, data, len);
- SET_TX_CHANNEL_INFO(channel, fHEAD, 1);
+ SET_TX_CHANNEL_FLAG(channel, fHEAD, 1);
/* Ensure ordering of channel info updates */
wmb();
@@ -727,6 +781,19 @@ static struct qcom_smd_driver *to_smd_driver(struct device *dev)
static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv)
{
+ struct qcom_smd_device *qsdev = to_smd_device(dev);
+ struct qcom_smd_driver *qsdrv = container_of(drv, struct qcom_smd_driver, driver);
+ const struct qcom_smd_id *match = qsdrv->smd_match_table;
+ const char *name = qsdev->channel->name;
+
+ if (match) {
+ while (match->name[0]) {
+ if (!strcmp(match->name, name))
+ return 1;
+ match++;
+ }
+ }
+
return of_driver_match_device(dev, drv);
}
@@ -854,10 +921,8 @@ static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
for_each_available_child_of_node(edge_node, child) {
key = "qcom,smd-channels";
ret = of_property_read_string(child, key, &name);
- if (ret) {
- of_node_put(child);
+ if (ret)
continue;
- }
if (strcmp(name, channel) == 0)
return child;
@@ -880,19 +945,17 @@ static int qcom_smd_create_device(struct qcom_smd_channel *channel)
if (channel->qsdev)
return -EEXIST;
- node = qcom_smd_match_channel(edge->of_node, channel->name);
- if (!node) {
- dev_dbg(smd->dev, "no match for '%s'\n", channel->name);
- return -ENXIO;
- }
-
dev_dbg(smd->dev, "registering '%s'\n", channel->name);
qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL);
if (!qsdev)
return -ENOMEM;
- dev_set_name(&qsdev->dev, "%s.%s", edge->of_node->name, node->name);
+ node = qcom_smd_match_channel(edge->of_node, channel->name);
+ dev_set_name(&qsdev->dev, "%s.%s",
+ edge->of_node->name,
+ node ? node->name : channel->name);
+
qsdev->dev.parent = smd->dev;
qsdev->dev.bus = &qcom_smd_bus;
qsdev->dev.release = qcom_smd_release_device;
@@ -978,21 +1041,20 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
spin_lock_init(&channel->recv_lock);
init_waitqueue_head(&channel->fblockread_event);
- ret = qcom_smem_get(edge->remote_pid, smem_info_item, (void **)&info,
- &info_size);
- if (ret)
+ info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size);
+ if (IS_ERR(info)) {
+ ret = PTR_ERR(info);
goto free_name_and_channel;
+ }
/*
* Use the size of the item to figure out which channel info struct to
* use.
*/
if (info_size == 2 * sizeof(struct smd_channel_info_word)) {
- channel->tx_info_word = info;
- channel->rx_info_word = info + sizeof(struct smd_channel_info_word);
+ channel->info_word = info;
} else if (info_size == 2 * sizeof(struct smd_channel_info)) {
- channel->tx_info = info;
- channel->rx_info = info + sizeof(struct smd_channel_info);
+ channel->info = info;
} else {
dev_err(smd->dev,
"channel info of size %zu not supported\n", info_size);
@@ -1000,10 +1062,11 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
goto free_name_and_channel;
}
- ret = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_base,
- &fifo_size);
- if (ret)
+ fifo_base = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_size);
+ if (IS_ERR(fifo_base)) {
+ ret = PTR_ERR(fifo_base);
goto free_name_and_channel;
+ }
/* The channel consist of a rx and tx fifo of equal size */
fifo_size /= 2;
@@ -1040,20 +1103,19 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
unsigned long flags;
unsigned fifo_id;
unsigned info_id;
- int ret;
int tbl;
int i;
+ u32 eflags, cid;
for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
- ret = qcom_smem_get(edge->remote_pid,
- smem_items[tbl].alloc_tbl_id,
- (void **)&alloc_tbl,
- NULL);
- if (ret < 0)
+ alloc_tbl = qcom_smem_get(edge->remote_pid,
+ smem_items[tbl].alloc_tbl_id, NULL);
+ if (IS_ERR(alloc_tbl))
continue;
for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
entry = &alloc_tbl[i];
+ eflags = le32_to_cpu(entry->flags);
if (test_bit(i, edge->allocated[tbl]))
continue;
@@ -1063,14 +1125,15 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
if (!entry->name[0])
continue;
- if (!(entry->flags & SMD_CHANNEL_FLAGS_PACKET))
+ if (!(eflags & SMD_CHANNEL_FLAGS_PACKET))
continue;
- if ((entry->flags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
+ if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
continue;
- info_id = smem_items[tbl].info_base_id + entry->cid;
- fifo_id = smem_items[tbl].fifo_base_id + entry->cid;
+ cid = le32_to_cpu(entry->cid);
+ info_id = smem_items[tbl].info_base_id + cid;
+ fifo_id = smem_items[tbl].fifo_base_id + cid;
channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
if (IS_ERR(channel))
@@ -1227,11 +1290,12 @@ static int qcom_smd_probe(struct platform_device *pdev)
int num_edges;
int ret;
int i = 0;
+ void *p;
/* Wait for smem */
- ret = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL, NULL);
- if (ret == -EPROBE_DEFER)
- return ret;
+ p = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL);
+ if (PTR_ERR(p) == -EPROBE_DEFER)
+ return PTR_ERR(p);
num_edges = of_get_available_child_count(pdev->dev.of_node);
array_size = sizeof(*smd) + num_edges * sizeof(struct qcom_smd_edge);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 52365188a1c2..19019aa092e8 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -92,9 +92,9 @@
* @params: parameters to the command
*/
struct smem_proc_comm {
- u32 command;
- u32 status;
- u32 params[2];
+ __le32 command;
+ __le32 status;
+ __le32 params[2];
};
/**
@@ -106,10 +106,10 @@ struct smem_proc_comm {
* the default region. bits 0,1 are reserved
*/
struct smem_global_entry {
- u32 allocated;
- u32 offset;
- u32 size;
- u32 aux_base; /* bits 1:0 reserved */
+ __le32 allocated;
+ __le32 offset;
+ __le32 size;
+ __le32 aux_base; /* bits 1:0 reserved */
};
#define AUX_BASE_MASK 0xfffffffc
@@ -125,11 +125,11 @@ struct smem_global_entry {
*/
struct smem_header {
struct smem_proc_comm proc_comm[4];
- u32 version[32];
- u32 initialized;
- u32 free_offset;
- u32 available;
- u32 reserved;
+ __le32 version[32];
+ __le32 initialized;
+ __le32 free_offset;
+ __le32 available;
+ __le32 reserved;
struct smem_global_entry toc[SMEM_ITEM_COUNT];
};
@@ -143,12 +143,12 @@ struct smem_header {
* @reserved: reserved entries for later use
*/
struct smem_ptable_entry {
- u32 offset;
- u32 size;
- u32 flags;
- u16 host0;
- u16 host1;
- u32 reserved[8];
+ __le32 offset;
+ __le32 size;
+ __le32 flags;
+ __le16 host0;
+ __le16 host1;
+ __le32 reserved[8];
};
/**
@@ -160,13 +160,14 @@ struct smem_ptable_entry {
* @entry: list of @smem_ptable_entry for the @num_entries partitions
*/
struct smem_ptable {
- u32 magic;
- u32 version;
- u32 num_entries;
- u32 reserved[5];
+ u8 magic[4];
+ __le32 version;
+ __le32 num_entries;
+ __le32 reserved[5];
struct smem_ptable_entry entry[];
};
-#define SMEM_PTABLE_MAGIC 0x434f5424 /* "$TOC" */
+
+static const u8 SMEM_PTABLE_MAGIC[] = { 0x24, 0x54, 0x4f, 0x43 }; /* "$TOC" */
/**
* struct smem_partition_header - header of the partitions
@@ -181,15 +182,16 @@ struct smem_ptable {
* @reserved: for now reserved entries
*/
struct smem_partition_header {
- u32 magic;
- u16 host0;
- u16 host1;
- u32 size;
- u32 offset_free_uncached;
- u32 offset_free_cached;
- u32 reserved[3];
+ u8 magic[4];
+ __le16 host0;
+ __le16 host1;
+ __le32 size;
+ __le32 offset_free_uncached;
+ __le32 offset_free_cached;
+ __le32 reserved[3];
};
-#define SMEM_PART_MAGIC 0x54525024 /* "$PRT" */
+
+static const u8 SMEM_PART_MAGIC[] = { 0x24, 0x50, 0x52, 0x54 };
/**
* struct smem_private_entry - header of each item in the private partition
@@ -201,12 +203,12 @@ struct smem_partition_header {
* @reserved: for now reserved entry
*/
struct smem_private_entry {
- u16 canary;
- u16 item;
- u32 size; /* includes padding bytes */
- u16 padding_data;
- u16 padding_hdr;
- u32 reserved;
+ u16 canary; /* bytes are the same so no swapping needed */
+ __le16 item;
+ __le32 size; /* includes padding bytes */
+ __le16 padding_data;
+ __le16 padding_hdr;
+ __le32 reserved;
};
#define SMEM_PRIVATE_CANARY 0xa5a5
@@ -242,6 +244,45 @@ struct qcom_smem {
struct smem_region regions[0];
};
+static struct smem_private_entry *
+phdr_to_last_private_entry(struct smem_partition_header *phdr)
+{
+ void *p = phdr;
+
+ return p + le32_to_cpu(phdr->offset_free_uncached);
+}
+
+static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr)
+{
+ void *p = phdr;
+
+ return p + le32_to_cpu(phdr->offset_free_cached);
+}
+
+static struct smem_private_entry *
+phdr_to_first_private_entry(struct smem_partition_header *phdr)
+{
+ void *p = phdr;
+
+ return p + sizeof(*phdr);
+}
+
+static struct smem_private_entry *
+private_entry_next(struct smem_private_entry *e)
+{
+ void *p = e;
+
+ return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) +
+ le32_to_cpu(e->size);
+}
+
+static void *entry_to_item(struct smem_private_entry *e)
+{
+ void *p = e;
+
+ return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
+}
+
/* Pointer to the one and only smem handle */
static struct qcom_smem *__smem;
@@ -254,16 +295,16 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
size_t size)
{
struct smem_partition_header *phdr;
- struct smem_private_entry *hdr;
+ struct smem_private_entry *hdr, *end;
size_t alloc_size;
- void *p;
+ void *cached;
phdr = smem->partitions[host];
+ hdr = phdr_to_first_private_entry(phdr);
+ end = phdr_to_last_private_entry(phdr);
+ cached = phdr_to_first_cached_entry(phdr);
- p = (void *)phdr + sizeof(*phdr);
- while (p < (void *)phdr + phdr->offset_free_uncached) {
- hdr = p;
-
+ while (hdr < end) {
if (hdr->canary != SMEM_PRIVATE_CANARY) {
dev_err(smem->dev,
"Found invalid canary in host %d partition\n",
@@ -271,24 +312,23 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
return -EINVAL;
}
- if (hdr->item == item)
+ if (le16_to_cpu(hdr->item) == item)
return -EEXIST;
- p += sizeof(*hdr) + hdr->padding_hdr + hdr->size;
+ hdr = private_entry_next(hdr);
}
/* Check that we don't grow into the cached region */
alloc_size = sizeof(*hdr) + ALIGN(size, 8);
- if (p + alloc_size >= (void *)phdr + phdr->offset_free_cached) {
+ if ((void *)hdr + alloc_size >= cached) {
dev_err(smem->dev, "Out of memory\n");
return -ENOSPC;
}
- hdr = p;
hdr->canary = SMEM_PRIVATE_CANARY;
- hdr->item = item;
- hdr->size = ALIGN(size, 8);
- hdr->padding_data = hdr->size - size;
+ hdr->item = cpu_to_le16(item);
+ hdr->size = cpu_to_le32(ALIGN(size, 8));
+ hdr->padding_data = cpu_to_le16(le32_to_cpu(hdr->size) - size);
hdr->padding_hdr = 0;
/*
@@ -297,7 +337,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
* gets a consistent view of the linked list.
*/
wmb();
- phdr->offset_free_uncached += alloc_size;
+ le32_add_cpu(&phdr->offset_free_uncached, alloc_size);
return 0;
}
@@ -318,11 +358,11 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
return -EEXIST;
size = ALIGN(size, 8);
- if (WARN_ON(size > header->available))
+ if (WARN_ON(size > le32_to_cpu(header->available)))
return -ENOMEM;
entry->offset = header->free_offset;
- entry->size = size;
+ entry->size = cpu_to_le32(size);
/*
* Ensure the header is consistent before we mark the item allocated,
@@ -330,10 +370,10 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
* even though they do not take the spinlock on read.
*/
wmb();
- entry->allocated = 1;
+ entry->allocated = cpu_to_le32(1);
- header->free_offset += size;
- header->available -= size;
+ le32_add_cpu(&header->free_offset, size);
+ le32_add_cpu(&header->available, -size);
return 0;
}
@@ -378,10 +418,9 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
}
EXPORT_SYMBOL(qcom_smem_alloc);
-static int qcom_smem_get_global(struct qcom_smem *smem,
- unsigned item,
- void **ptr,
- size_t *size)
+static void *qcom_smem_get_global(struct qcom_smem *smem,
+ unsigned item,
+ size_t *size)
{
struct smem_header *header;
struct smem_region *area;
@@ -390,100 +429,94 @@ static int qcom_smem_get_global(struct qcom_smem *smem,
unsigned i;
if (WARN_ON(item >= SMEM_ITEM_COUNT))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
header = smem->regions[0].virt_base;
entry = &header->toc[item];
if (!entry->allocated)
- return -ENXIO;
+ return ERR_PTR(-ENXIO);
- if (ptr != NULL) {
- aux_base = entry->aux_base & AUX_BASE_MASK;
+ aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK;
- for (i = 0; i < smem->num_regions; i++) {
- area = &smem->regions[i];
+ for (i = 0; i < smem->num_regions; i++) {
+ area = &smem->regions[i];
- if (area->aux_base == aux_base || !aux_base) {
- *ptr = area->virt_base + entry->offset;
- break;
- }
+ if (area->aux_base == aux_base || !aux_base) {
+ if (size != NULL)
+ *size = le32_to_cpu(entry->size);
+ return area->virt_base + le32_to_cpu(entry->offset);
}
}
- if (size != NULL)
- *size = entry->size;
- return 0;
+ return ERR_PTR(-ENOENT);
}
-static int qcom_smem_get_private(struct qcom_smem *smem,
- unsigned host,
- unsigned item,
- void **ptr,
- size_t *size)
+static void *qcom_smem_get_private(struct qcom_smem *smem,
+ unsigned host,
+ unsigned item,
+ size_t *size)
{
struct smem_partition_header *phdr;
- struct smem_private_entry *hdr;
- void *p;
+ struct smem_private_entry *e, *end;
phdr = smem->partitions[host];
+ e = phdr_to_first_private_entry(phdr);
+ end = phdr_to_last_private_entry(phdr);
- p = (void *)phdr + sizeof(*phdr);
- while (p < (void *)phdr + phdr->offset_free_uncached) {
- hdr = p;
-
- if (hdr->canary != SMEM_PRIVATE_CANARY) {
+ while (e < end) {
+ if (e->canary != SMEM_PRIVATE_CANARY) {
dev_err(smem->dev,
"Found invalid canary in host %d partition\n",
host);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
- if (hdr->item == item) {
- if (ptr != NULL)
- *ptr = p + sizeof(*hdr) + hdr->padding_hdr;
-
+ if (le16_to_cpu(e->item) == item) {
if (size != NULL)
- *size = hdr->size - hdr->padding_data;
+ *size = le32_to_cpu(e->size) -
+ le16_to_cpu(e->padding_data);
- return 0;
+ return entry_to_item(e);
}
- p += sizeof(*hdr) + hdr->padding_hdr + hdr->size;
+ e = private_entry_next(e);
}
- return -ENOENT;
+ return ERR_PTR(-ENOENT);
}
/**
* qcom_smem_get() - resolve ptr of size of a smem item
* @host: the remote processor, or -1
* @item: smem item handle
- * @ptr: pointer to be filled out with address of the item
* @size: pointer to be filled out with size of the item
*
- * Looks up pointer and size of a smem item.
+ * Looks up smem item and returns pointer to it. Size of smem
+ * item is returned in @size.
*/
-int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size)
+void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
{
unsigned long flags;
int ret;
+ void *ptr = ERR_PTR(-EPROBE_DEFER);
if (!__smem)
- return -EPROBE_DEFER;
+ return ptr;
ret = hwspin_lock_timeout_irqsave(__smem->hwlock,
HWSPINLOCK_TIMEOUT,
&flags);
if (ret)
- return ret;
+ return ERR_PTR(ret);
if (host < SMEM_HOST_COUNT && __smem->partitions[host])
- ret = qcom_smem_get_private(__smem, host, item, ptr, size);
+ ptr = qcom_smem_get_private(__smem, host, item, size);
else
- ret = qcom_smem_get_global(__smem, item, ptr, size);
+ ptr = qcom_smem_get_global(__smem, item, size);
hwspin_unlock_irqrestore(__smem->hwlock, &flags);
- return ret;
+
+ return ptr;
}
EXPORT_SYMBOL(qcom_smem_get);
@@ -506,10 +539,11 @@ int qcom_smem_get_free_space(unsigned host)
if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
phdr = __smem->partitions[host];
- ret = phdr->offset_free_cached - phdr->offset_free_uncached;
+ ret = le32_to_cpu(phdr->offset_free_cached) -
+ le32_to_cpu(phdr->offset_free_uncached);
} else {
header = __smem->regions[0].virt_base;
- ret = header->available;
+ ret = le32_to_cpu(header->available);
}
return ret;
@@ -518,13 +552,11 @@ EXPORT_SYMBOL(qcom_smem_get_free_space);
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
{
- unsigned *versions;
+ __le32 *versions;
size_t size;
- int ret;
- ret = qcom_smem_get_global(smem, SMEM_ITEM_VERSION,
- (void **)&versions, &size);
- if (ret < 0) {
+ versions = qcom_smem_get_global(smem, SMEM_ITEM_VERSION, &size);
+ if (IS_ERR(versions)) {
dev_err(smem->dev, "Unable to read the version item\n");
return -ENOENT;
}
@@ -534,7 +566,7 @@ static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
return -EINVAL;
}
- return versions[SMEM_MASTER_SBL_VERSION_INDEX];
+ return le32_to_cpu(versions[SMEM_MASTER_SBL_VERSION_INDEX]);
}
static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
@@ -544,35 +576,38 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
struct smem_ptable_entry *entry;
struct smem_ptable *ptable;
unsigned remote_host;
+ u32 version, host0, host1;
int i;
ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K;
- if (ptable->magic != SMEM_PTABLE_MAGIC)
+ if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic)))
return 0;
- if (ptable->version != 1) {
+ version = le32_to_cpu(ptable->version);
+ if (version != 1) {
dev_err(smem->dev,
- "Unsupported partition header version %d\n",
- ptable->version);
+ "Unsupported partition header version %d\n", version);
return -EINVAL;
}
- for (i = 0; i < ptable->num_entries; i++) {
+ for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
entry = &ptable->entry[i];
+ host0 = le16_to_cpu(entry->host0);
+ host1 = le16_to_cpu(entry->host1);
- if (entry->host0 != local_host && entry->host1 != local_host)
+ if (host0 != local_host && host1 != local_host)
continue;
- if (!entry->offset)
+ if (!le32_to_cpu(entry->offset))
continue;
- if (!entry->size)
+ if (!le32_to_cpu(entry->size))
continue;
- if (entry->host0 == local_host)
- remote_host = entry->host1;
+ if (host0 == local_host)
+ remote_host = host1;
else
- remote_host = entry->host0;
+ remote_host = host0;
if (remote_host >= SMEM_HOST_COUNT) {
dev_err(smem->dev,
@@ -588,21 +623,24 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return -EINVAL;
}
- header = smem->regions[0].virt_base + entry->offset;
+ header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
+ host0 = le16_to_cpu(header->host0);
+ host1 = le16_to_cpu(header->host1);
- if (header->magic != SMEM_PART_MAGIC) {
+ if (memcmp(header->magic, SMEM_PART_MAGIC,
+ sizeof(header->magic))) {
dev_err(smem->dev,
"Partition %d has invalid magic\n", i);
return -EINVAL;
}
- if (header->host0 != local_host && header->host1 != local_host) {
+ if (host0 != local_host && host1 != local_host) {
dev_err(smem->dev,
"Partition %d hosts are invalid\n", i);
return -EINVAL;
}
- if (header->host0 != remote_host && header->host1 != remote_host) {
+ if (host0 != remote_host && host1 != remote_host) {
dev_err(smem->dev,
"Partition %d hosts are invalid\n", i);
return -EINVAL;
@@ -614,7 +652,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return -EINVAL;
}
- if (header->offset_free_uncached > header->size) {
+ if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) {
dev_err(smem->dev,
"Partition %d has invalid free pointer\n", i);
return -EINVAL;
@@ -626,37 +664,47 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return 0;
}
-static int qcom_smem_count_mem_regions(struct platform_device *pdev)
+static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
+ const char *name, int i)
{
- struct resource *res;
- int num_regions = 0;
- int i;
-
- for (i = 0; i < pdev->num_resources; i++) {
- res = &pdev->resource[i];
+ struct device_node *np;
+ struct resource r;
+ int ret;
- if (resource_type(res) == IORESOURCE_MEM)
- num_regions++;
+ np = of_parse_phandle(dev->of_node, name, 0);
+ if (!np) {
+ dev_err(dev, "No %s specified\n", name);
+ return -EINVAL;
}
- return num_regions;
+ ret = of_address_to_resource(np, 0, &r);
+ of_node_put(np);
+ if (ret)
+ return ret;
+
+ smem->regions[i].aux_base = (u32)r.start;
+ smem->regions[i].size = resource_size(&r);
+ smem->regions[i].virt_base = devm_ioremap_nocache(dev, r.start,
+ resource_size(&r));
+ if (!smem->regions[i].virt_base)
+ return -ENOMEM;
+
+ return 0;
}
static int qcom_smem_probe(struct platform_device *pdev)
{
struct smem_header *header;
- struct device_node *np;
struct qcom_smem *smem;
- struct resource *res;
- struct resource r;
size_t array_size;
- int num_regions = 0;
+ int num_regions;
int hwlock_id;
u32 version;
int ret;
- int i;
- num_regions = qcom_smem_count_mem_regions(pdev) + 1;
+ num_regions = 1;
+ if (of_find_property(pdev->dev.of_node, "qcom,rpm-msg-ram", NULL))
+ num_regions++;
array_size = num_regions * sizeof(struct smem_region);
smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL);
@@ -666,39 +714,17 @@ static int qcom_smem_probe(struct platform_device *pdev)
smem->dev = &pdev->dev;
smem->num_regions = num_regions;
- np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
- if (!np) {
- dev_err(&pdev->dev, "No memory-region specified\n");
- return -EINVAL;
- }
-
- ret = of_address_to_resource(np, 0, &r);
- of_node_put(np);
+ ret = qcom_smem_map_memory(smem, &pdev->dev, "memory-region", 0);
if (ret)
return ret;
- smem->regions[0].aux_base = (u32)r.start;
- smem->regions[0].size = resource_size(&r);
- smem->regions[0].virt_base = devm_ioremap_nocache(&pdev->dev,
- r.start,
- resource_size(&r));
- if (!smem->regions[0].virt_base)
- return -ENOMEM;
-
- for (i = 1; i < num_regions; i++) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, i - 1);
-
- smem->regions[i].aux_base = (u32)res->start;
- smem->regions[i].size = resource_size(res);
- smem->regions[i].virt_base = devm_ioremap_nocache(&pdev->dev,
- res->start,
- resource_size(res));
- if (!smem->regions[i].virt_base)
- return -ENOMEM;
- }
+ if (num_regions > 1 && (ret = qcom_smem_map_memory(smem, &pdev->dev,
+ "qcom,rpm-msg-ram", 1)))
+ return ret;
header = smem->regions[0].virt_base;
- if (header->initialized != 1 || header->reserved) {
+ if (le32_to_cpu(header->initialized) != 1 ||
+ le32_to_cpu(header->reserved)) {
dev_err(&pdev->dev, "SMEM is not initialized by SBL\n");
return -EINVAL;
}
@@ -730,8 +756,8 @@ static int qcom_smem_probe(struct platform_device *pdev)
static int qcom_smem_remove(struct platform_device *pdev)
{
- __smem = NULL;
hwspin_lock_free(__smem->hwlock);
+ __smem = NULL;
return 0;
}
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
new file mode 100644
index 000000000000..7140ff825598
--- /dev/null
+++ b/drivers/soc/rockchip/Kconfig
@@ -0,0 +1,18 @@
+if ARCH_ROCKCHIP || COMPILE_TEST
+
+#
+# Rockchip Soc drivers
+#
+config ROCKCHIP_PM_DOMAINS
+ bool "Rockchip generic power domain"
+ depends on PM
+ select PM_GENERIC_DOMAINS
+ help
+ Say y here to enable power domain support.
+ In order to meet high performance and low power requirements, a power
+ management unit is designed or saving power when RK3288 in low power
+ mode. The RK3288 PMU is dedicated for managing the power of the whole chip.
+
+ If unsure, say N.
+
+endif
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 000000000000..3d73d0672d22
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
+#
+# Rockchip Soc drivers
+#
+obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
new file mode 100644
index 000000000000..534c58937a56
--- /dev/null
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -0,0 +1,490 @@
+/*
+ * Rockchip Generic power domain support.
+ *
+ * Copyright (c) 2015 ROCKCHIP, Co. 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/io.h>
+#include <linux/err.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/power/rk3288-power.h>
+
+struct rockchip_domain_info {
+ int pwr_mask;
+ int status_mask;
+ int req_mask;
+ int idle_mask;
+ int ack_mask;
+};
+
+struct rockchip_pmu_info {
+ u32 pwr_offset;
+ u32 status_offset;
+ u32 req_offset;
+ u32 idle_offset;
+ u32 ack_offset;
+
+ u32 core_pwrcnt_offset;
+ u32 gpu_pwrcnt_offset;
+
+ unsigned int core_power_transition_time;
+ unsigned int gpu_power_transition_time;
+
+ int num_domains;
+ const struct rockchip_domain_info *domain_info;
+};
+
+struct rockchip_pm_domain {
+ struct generic_pm_domain genpd;
+ const struct rockchip_domain_info *info;
+ struct rockchip_pmu *pmu;
+ int num_clks;
+ struct clk *clks[];
+};
+
+struct rockchip_pmu {
+ struct device *dev;
+ struct regmap *regmap;
+ const struct rockchip_pmu_info *info;
+ struct mutex mutex; /* mutex lock for pmu */
+ struct genpd_onecell_data genpd_data;
+ struct generic_pm_domain *domains[];
+};
+
+#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
+
+#define DOMAIN(pwr, status, req, idle, ack) \
+{ \
+ .pwr_mask = BIT(pwr), \
+ .status_mask = BIT(status), \
+ .req_mask = BIT(req), \
+ .idle_mask = BIT(idle), \
+ .ack_mask = BIT(ack), \
+}
+
+#define DOMAIN_RK3288(pwr, status, req) \
+ DOMAIN(pwr, status, req, req, (req) + 16)
+
+static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
+{
+ struct rockchip_pmu *pmu = pd->pmu;
+ const struct rockchip_domain_info *pd_info = pd->info;
+ unsigned int val;
+
+ regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
+ return (val & pd_info->idle_mask) == pd_info->idle_mask;
+}
+
+static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
+ bool idle)
+{
+ const struct rockchip_domain_info *pd_info = pd->info;
+ struct rockchip_pmu *pmu = pd->pmu;
+ unsigned int val;
+
+ regmap_update_bits(pmu->regmap, pmu->info->req_offset,
+ pd_info->req_mask, idle ? -1U : 0);
+
+ dsb(sy);
+
+ do {
+ regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
+ } while ((val & pd_info->ack_mask) != (idle ? pd_info->ack_mask : 0));
+
+ while (rockchip_pmu_domain_is_idle(pd) != idle)
+ cpu_relax();
+
+ return 0;
+}
+
+static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
+{
+ struct rockchip_pmu *pmu = pd->pmu;
+ unsigned int val;
+
+ regmap_read(pmu->regmap, pmu->info->status_offset, &val);
+
+ /* 1'b0: power on, 1'b1: power off */
+ return !(val & pd->info->status_mask);
+}
+
+static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
+ bool on)
+{
+ struct rockchip_pmu *pmu = pd->pmu;
+
+ regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
+ pd->info->pwr_mask, on ? 0 : -1U);
+
+ dsb(sy);
+
+ while (rockchip_pmu_domain_is_on(pd) != on)
+ cpu_relax();
+}
+
+static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
+{
+ int i;
+
+ mutex_lock(&pd->pmu->mutex);
+
+ if (rockchip_pmu_domain_is_on(pd) != power_on) {
+ for (i = 0; i < pd->num_clks; i++)
+ clk_enable(pd->clks[i]);
+
+ if (!power_on) {
+ /* FIXME: add code to save AXI_QOS */
+
+ /* if powering down, idle request to NIU first */
+ rockchip_pmu_set_idle_request(pd, true);
+ }
+
+ rockchip_do_pmu_set_power_domain(pd, power_on);
+
+ if (power_on) {
+ /* if powering up, leave idle mode */
+ rockchip_pmu_set_idle_request(pd, false);
+
+ /* FIXME: add code to restore AXI_QOS */
+ }
+
+ for (i = pd->num_clks - 1; i >= 0; i--)
+ clk_disable(pd->clks[i]);
+ }
+
+ mutex_unlock(&pd->pmu->mutex);
+ return 0;
+}
+
+static int rockchip_pd_power_on(struct generic_pm_domain *domain)
+{
+ struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+
+ return rockchip_pd_power(pd, true);
+}
+
+static int rockchip_pd_power_off(struct generic_pm_domain *domain)
+{
+ struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+
+ return rockchip_pd_power(pd, false);
+}
+
+static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
+ struct device *dev)
+{
+ struct clk *clk;
+ int i;
+ int error;
+
+ dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
+
+ error = pm_clk_create(dev);
+ if (error) {
+ dev_err(dev, "pm_clk_create failed %d\n", error);
+ return error;
+ }
+
+ i = 0;
+ while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
+ dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
+ error = pm_clk_add_clk(dev, clk);
+ if (error) {
+ dev_err(dev, "pm_clk_add_clk failed %d\n", error);
+ clk_put(clk);
+ pm_clk_destroy(dev);
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
+ struct device *dev)
+{
+ dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
+
+ pm_clk_destroy(dev);
+}
+
+static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
+ struct device_node *node)
+{
+ const struct rockchip_domain_info *pd_info;
+ struct rockchip_pm_domain *pd;
+ struct clk *clk;
+ int clk_cnt;
+ int i;
+ u32 id;
+ int error;
+
+ error = of_property_read_u32(node, "reg", &id);
+ if (error) {
+ dev_err(pmu->dev,
+ "%s: failed to retrieve domain id (reg): %d\n",
+ node->name, error);
+ return -EINVAL;
+ }
+
+ if (id >= pmu->info->num_domains) {
+ dev_err(pmu->dev, "%s: invalid domain id %d\n",
+ node->name, id);
+ return -EINVAL;
+ }
+
+ pd_info = &pmu->info->domain_info[id];
+ if (!pd_info) {
+ dev_err(pmu->dev, "%s: undefined domain id %d\n",
+ node->name, id);
+ return -EINVAL;
+ }
+
+ clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+ pd = devm_kzalloc(pmu->dev,
+ sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
+ GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ pd->info = pd_info;
+ pd->pmu = pmu;
+
+ for (i = 0; i < clk_cnt; i++) {
+ clk = of_clk_get(node, i);
+ if (IS_ERR(clk)) {
+ error = PTR_ERR(clk);
+ dev_err(pmu->dev,
+ "%s: failed to get clk at index %d: %d\n",
+ node->name, i, error);
+ goto err_out;
+ }
+
+ error = clk_prepare(clk);
+ if (error) {
+ dev_err(pmu->dev,
+ "%s: failed to prepare clk %pC (index %d): %d\n",
+ node->name, clk, i, error);
+ clk_put(clk);
+ goto err_out;
+ }
+
+ pd->clks[pd->num_clks++] = clk;
+
+ dev_dbg(pmu->dev, "added clock '%pC' to domain '%s'\n",
+ clk, node->name);
+ }
+
+ error = rockchip_pd_power(pd, true);
+ if (error) {
+ dev_err(pmu->dev,
+ "failed to power on domain '%s': %d\n",
+ node->name, error);
+ goto err_out;
+ }
+
+ pd->genpd.name = node->name;
+ pd->genpd.power_off = rockchip_pd_power_off;
+ pd->genpd.power_on = rockchip_pd_power_on;
+ pd->genpd.attach_dev = rockchip_pd_attach_dev;
+ pd->genpd.detach_dev = rockchip_pd_detach_dev;
+ pd->genpd.flags = GENPD_FLAG_PM_CLK;
+ pm_genpd_init(&pd->genpd, NULL, false);
+
+ pmu->genpd_data.domains[id] = &pd->genpd;
+ return 0;
+
+err_out:
+ while (--i >= 0) {
+ clk_unprepare(pd->clks[i]);
+ clk_put(pd->clks[i]);
+ }
+ return error;
+}
+
+static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
+{
+ int i;
+
+ for (i = 0; i < pd->num_clks; i++) {
+ clk_unprepare(pd->clks[i]);
+ clk_put(pd->clks[i]);
+ }
+
+ /* protect the zeroing of pm->num_clks */
+ mutex_lock(&pd->pmu->mutex);
+ pd->num_clks = 0;
+ mutex_unlock(&pd->pmu->mutex);
+
+ /* devm will free our memory */
+}
+
+static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
+{
+ struct generic_pm_domain *genpd;
+ struct rockchip_pm_domain *pd;
+ int i;
+
+ for (i = 0; i < pmu->genpd_data.num_domains; i++) {
+ genpd = pmu->genpd_data.domains[i];
+ if (genpd) {
+ pd = to_rockchip_pd(genpd);
+ rockchip_pm_remove_one_domain(pd);
+ }
+ }
+
+ /* devm will free our memory */
+}
+
+static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
+ u32 domain_reg_offset,
+ unsigned int count)
+{
+ /* First configure domain power down transition count ... */
+ regmap_write(pmu->regmap, domain_reg_offset, count);
+ /* ... and then power up count. */
+ regmap_write(pmu->regmap, domain_reg_offset + 4, count);
+}
+
+static int rockchip_pm_domain_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *node;
+ struct device *parent;
+ struct rockchip_pmu *pmu;
+ const struct of_device_id *match;
+ const struct rockchip_pmu_info *pmu_info;
+ int error;
+
+ if (!np) {
+ dev_err(dev, "device tree node not found\n");
+ return -ENODEV;
+ }
+
+ match = of_match_device(dev->driver->of_match_table, dev);
+ if (!match || !match->data) {
+ dev_err(dev, "missing pmu data\n");
+ return -EINVAL;
+ }
+
+ pmu_info = match->data;
+
+ pmu = devm_kzalloc(dev,
+ sizeof(*pmu) +
+ pmu_info->num_domains * sizeof(pmu->domains[0]),
+ GFP_KERNEL);
+ if (!pmu)
+ return -ENOMEM;
+
+ pmu->dev = &pdev->dev;
+ mutex_init(&pmu->mutex);
+
+ pmu->info = pmu_info;
+
+ pmu->genpd_data.domains = pmu->domains;
+ pmu->genpd_data.num_domains = pmu_info->num_domains;
+
+ parent = dev->parent;
+ if (!parent) {
+ dev_err(dev, "no parent for syscon devices\n");
+ return -ENODEV;
+ }
+
+ pmu->regmap = syscon_node_to_regmap(parent->of_node);
+
+ /*
+ * Configure power up and down transition delays for CORE
+ * and GPU domains.
+ */
+ rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
+ pmu_info->core_power_transition_time);
+ rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
+ pmu_info->gpu_power_transition_time);
+
+ error = -ENODEV;
+
+ for_each_available_child_of_node(np, node) {
+ error = rockchip_pm_add_one_domain(pmu, node);
+ if (error) {
+ dev_err(dev, "failed to handle node %s: %d\n",
+ node->name, error);
+ goto err_out;
+ }
+ }
+
+ if (error) {
+ dev_dbg(dev, "no power domains defined\n");
+ goto err_out;
+ }
+
+ of_genpd_add_provider_onecell(np, &pmu->genpd_data);
+
+ return 0;
+
+err_out:
+ rockchip_pm_domain_cleanup(pmu);
+ return error;
+}
+
+static const struct rockchip_domain_info rk3288_pm_domains[] = {
+ [RK3288_PD_VIO] = DOMAIN_RK3288(7, 7, 4),
+ [RK3288_PD_HEVC] = DOMAIN_RK3288(14, 10, 9),
+ [RK3288_PD_VIDEO] = DOMAIN_RK3288(8, 8, 3),
+ [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2),
+};
+
+static const struct rockchip_pmu_info rk3288_pmu = {
+ .pwr_offset = 0x08,
+ .status_offset = 0x0c,
+ .req_offset = 0x10,
+ .idle_offset = 0x14,
+ .ack_offset = 0x14,
+
+ .core_pwrcnt_offset = 0x34,
+ .gpu_pwrcnt_offset = 0x3c,
+
+ .core_power_transition_time = 24, /* 1us */
+ .gpu_power_transition_time = 24, /* 1us */
+
+ .num_domains = ARRAY_SIZE(rk3288_pm_domains),
+ .domain_info = rk3288_pm_domains,
+};
+
+static const struct of_device_id rockchip_pm_domain_dt_match[] = {
+ {
+ .compatible = "rockchip,rk3288-power-controller",
+ .data = (void *)&rk3288_pmu,
+ },
+ { /* sentinel */ },
+};
+
+static struct platform_driver rockchip_pm_domain_driver = {
+ .probe = rockchip_pm_domain_probe,
+ .driver = {
+ .name = "rockchip-pm-domain",
+ .of_match_table = rockchip_pm_domain_dt_match,
+ /*
+ * We can't forcibly eject devices form power domain,
+ * so we can't really remove power domains once they
+ * were added.
+ */
+ .suppress_bind_attrs = true,
+ },
+};
+
+static int __init rockchip_pm_domain_drv_register(void)
+{
+ return platform_driver_register(&rockchip_pm_domain_driver);
+}
+postcore_initcall(rockchip_pm_domain_drv_register);
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h
index 51da2341280d..6ff936cacb70 100644
--- a/drivers/soc/ti/knav_qmss.h
+++ b/drivers/soc/ti/knav_qmss.h
@@ -135,9 +135,10 @@ struct knav_pdsp_info {
};
void __iomem *intd;
u32 __iomem *iram;
- const char *firmware;
u32 id;
struct list_head list;
+ bool loaded;
+ bool started;
};
struct knav_qmgr_info {
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index ef6f69db0bd0..d2d48f2802bc 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -261,6 +261,10 @@ static int knav_range_setup_acc_irq(struct knav_range_info *range,
if (old && !new) {
dev_dbg(kdev->dev, "setup-acc-irq: freeing %s for channel %s\n",
acc->name, acc->name);
+ ret = irq_set_affinity_hint(irq, NULL);
+ if (ret)
+ dev_warn(range->kdev->dev,
+ "Failed to set IRQ affinity\n");
free_irq(irq, range);
}
@@ -482,8 +486,8 @@ struct knav_range_ops knav_acc_range_ops = {
* Return 0 on success or error
*/
int knav_init_acc_range(struct knav_device *kdev,
- struct device_node *node,
- struct knav_range_info *range)
+ struct device_node *node,
+ struct knav_range_info *range)
{
struct knav_acc_channel *acc;
struct knav_pdsp_info *pdsp;
@@ -526,6 +530,12 @@ int knav_init_acc_range(struct knav_device *kdev,
return -EINVAL;
}
+ if (!pdsp->started) {
+ dev_err(kdev->dev, "pdsp id %d not started for range %s\n",
+ info->pdsp_id, range->name);
+ return -ENODEV;
+ }
+
info->pdsp = pdsp;
channels = range->num_queues;
if (of_get_property(node, "multi-queue", NULL)) {
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index 6d8646db52cc..f3a0b6a4b54e 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -68,6 +68,12 @@ static DEFINE_MUTEX(knav_dev_lock);
idx < (kdev)->num_queues_in_use; \
idx++, inst = knav_queue_idx_to_inst(kdev, idx))
+/* All firmware file names end up here. List the firmware file names below.
+ * Newest followed by older ones. Search is done from start of the array
+ * until a firmware file is found.
+ */
+const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"};
+
/**
* knav_queue_notify: qmss queue notfier call
*
@@ -1439,7 +1445,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
struct device *dev = kdev->dev;
struct knav_pdsp_info *pdsp;
struct device_node *child;
- int ret;
for_each_child_of_node(pdsps, child) {
pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL);
@@ -1448,17 +1453,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
return -ENOMEM;
}
pdsp->name = knav_queue_find_name(child);
- ret = of_property_read_string(child, "firmware",
- &pdsp->firmware);
- if (ret < 0 || !pdsp->firmware) {
- dev_err(dev, "unknown firmware for pdsp %s\n",
- pdsp->name);
- devm_kfree(dev, pdsp);
- continue;
- }
- dev_dbg(dev, "pdsp name %s fw name :%s\n", pdsp->name,
- pdsp->firmware);
-
pdsp->iram =
knav_queue_map_reg(kdev, child,
KNAV_QUEUE_PDSP_IRAM_REG_INDEX);
@@ -1489,9 +1483,9 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
}
of_property_read_u32(child, "id", &pdsp->id);
list_add_tail(&pdsp->list, &kdev->pdsps);
- dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p, firmware %s\n",
+ dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p\n",
pdsp->name, pdsp->command, pdsp->iram, pdsp->regs,
- pdsp->intd, pdsp->firmware);
+ pdsp->intd);
}
return 0;
}
@@ -1510,6 +1504,8 @@ static int knav_queue_stop_pdsp(struct knav_device *kdev,
dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name);
return ret;
}
+ pdsp->loaded = false;
+ pdsp->started = false;
return 0;
}
@@ -1518,14 +1514,29 @@ static int knav_queue_load_pdsp(struct knav_device *kdev,
{
int i, ret, fwlen;
const struct firmware *fw;
+ bool found = false;
u32 *fwdata;
- ret = request_firmware(&fw, pdsp->firmware, kdev->dev);
- if (ret) {
- dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n",
- pdsp->firmware, pdsp->name);
- return ret;
+ for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) {
+ if (knav_acc_firmwares[i]) {
+ ret = request_firmware(&fw,
+ knav_acc_firmwares[i],
+ kdev->dev);
+ if (!ret) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ dev_err(kdev->dev, "failed to get firmware for pdsp\n");
+ return -ENODEV;
}
+
+ dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n",
+ knav_acc_firmwares[i]);
+
writel_relaxed(pdsp->id + 1, pdsp->command + 0x18);
/* download the firmware */
fwdata = (u32 *)fw->data;
@@ -1583,16 +1594,24 @@ static int knav_queue_start_pdsps(struct knav_device *kdev)
int ret;
knav_queue_stop_pdsps(kdev);
- /* now load them all */
+ /* now load them all. We return success even if pdsp
+ * is not loaded as acc channels are optional on having
+ * firmware availability in the system. We set the loaded
+ * and stated flag and when initialize the acc range, check
+ * it and init the range only if pdsp is started.
+ */
for_each_pdsp(kdev, pdsp) {
ret = knav_queue_load_pdsp(kdev, pdsp);
- if (ret < 0)
- return ret;
+ if (!ret)
+ pdsp->loaded = true;
}
for_each_pdsp(kdev, pdsp) {
- ret = knav_queue_start_pdsp(kdev, pdsp);
- WARN_ON(ret);
+ if (pdsp->loaded) {
+ ret = knav_queue_start_pdsp(kdev, pdsp);
+ if (!ret)
+ pdsp->started = true;
+ }
}
return 0;
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4887f317ea58..8b9c2a38d1cc 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -88,6 +88,17 @@ config SPI_BCM2835
is for the regular SPI controller. Slave mode operation is not also
not supported.
+config SPI_BCM2835AUX
+ tristate "BCM2835 SPI auxiliary controller"
+ depends on ARCH_BCM2835 || COMPILE_TEST
+ depends on GPIOLIB
+ help
+ This selects a driver for the Broadcom BCM2835 SPI aux master.
+
+ The BCM2835 contains two types of SPI master controller; the
+ "universal SPI master", and the regular SPI controller.
+ This driver is for the universal/auxiliary SPI controller.
+
config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN && !BF60x
@@ -125,7 +136,7 @@ config SPI_BCM53XX
config SPI_BCM63XX
tristate "Broadcom BCM63xx SPI controller"
- depends on BCM63XX
+ depends on BCM63XX || COMPILE_TEST
help
Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
@@ -304,7 +315,7 @@ config SPI_FSL_SPI
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
select REGMAP_MMIO
- depends on SOC_VF610 || SOC_LS1021A || COMPILE_TEST
+ depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
help
This enables support for the Freescale DSPI controller in master
mode. VF610 platform uses the controller.
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 6a7f6f9d0d1c..31fb7fb2a0b6 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
+obj-$(CONFIG_SPI_BCM2835AUX) += spi-bcm2835aux.o
obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index bf1f9b32c597..6165bf21d427 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -240,14 +240,9 @@ static int ath79_spi_probe(struct platform_device *pdev)
sp->bitbang.flags = SPI_CS_HIGH;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENOENT;
- goto err_put_master;
- }
-
- sp->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
- if (!sp->base) {
- ret = -ENXIO;
+ sp->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(sp->base)) {
+ ret = PTR_ERR(sp->base);
goto err_put_master;
}
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 63318e2afba1..aebad36391c9 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -773,7 +773,8 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
*plen = len;
- if (atmel_spi_dma_slave_config(as, &slave_config, 8))
+ if (atmel_spi_dma_slave_config(as, &slave_config,
+ xfer->bits_per_word))
goto err_exit;
/* Send both scatterlists */
@@ -871,14 +872,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
* Calculate the lowest divider that satisfies the
* constraint, assuming div32/fdiv/mbz == 0.
*/
- if (xfer->speed_hz)
- scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
- else
- /*
- * This can happend if max_speed is null.
- * In this case, we set the lowest possible speed
- */
- scbr = 0xff;
+ scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
/*
* If the resulting divider doesn't fit into the
@@ -1300,14 +1294,12 @@ static int atmel_spi_one_transfer(struct spi_master *master,
return -EINVAL;
}
- if (xfer->bits_per_word) {
- asd = spi->controller_state;
- bits = (asd->csr >> 4) & 0xf;
- if (bits != xfer->bits_per_word - 8) {
- dev_dbg(&spi->dev,
+ asd = spi->controller_state;
+ bits = (asd->csr >> 4) & 0xf;
+ if (bits != xfer->bits_per_word - 8) {
+ dev_dbg(&spi->dev,
"you can't yet change bits_per_word in transfers\n");
- return -ENOPROTOOPT;
- }
+ return -ENOPROTOOPT;
}
/*
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
index f45e085c01a6..afd239d6dec1 100644
--- a/drivers/spi/spi-au1550.c
+++ b/drivers/spi/spi-au1550.c
@@ -233,13 +233,12 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
unsigned bpw, hz;
u32 cfg, stat;
- bpw = spi->bits_per_word;
- hz = spi->max_speed_hz;
if (t) {
- if (t->bits_per_word)
- bpw = t->bits_per_word;
- if (t->speed_hz)
- hz = t->speed_hz;
+ bpw = t->bits_per_word;
+ hz = t->speed_hz;
+ } else {
+ bpw = spi->bits_per_word;
+ hz = spi->max_speed_hz;
}
if (!hz)
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 3e8eeb23d4e9..cf04960cc3e6 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -777,7 +777,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
goto out_master_put;
}
- bs->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ bs->irq = platform_get_irq(pdev, 0);
if (bs->irq <= 0) {
dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
err = bs->irq ? bs->irq : -ENODEV;
@@ -786,6 +786,12 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
clk_prepare_enable(bs->clk);
+ bcm2835_dma_init(master, &pdev->dev);
+
+ /* initialise the hardware with the default polarities */
+ bcm2835_wr(bs, BCM2835_SPI_CS,
+ BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
dev_name(&pdev->dev), master);
if (err) {
@@ -793,12 +799,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
goto out_clk_disable;
}
- bcm2835_dma_init(master, &pdev->dev);
-
- /* initialise the hardware with the default polarities */
- bcm2835_wr(bs, BCM2835_SPI_CS,
- BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
-
err = devm_spi_register_master(&pdev->dev, master);
if (err) {
dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
new file mode 100644
index 000000000000..7de6f8472a81
--- /dev/null
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -0,0 +1,512 @@
+/*
+ * Driver for Broadcom BCM2835 auxiliary SPI Controllers
+ *
+ * the driver does not rely on the native chipselects at all
+ * but only uses the gpio type chipselects
+ *
+ * Based on: spi-bcm2835.c
+ *
+ * Copyright (C) 2015 Martin Sperl
+ *
+ * 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/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spinlock.h>
+
+/*
+ * spi register defines
+ *
+ * note there is garbage in the "official" documentation,
+ * so some data is taken from the file:
+ * brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/aux_io.h
+ * inside of:
+ * http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz
+ */
+
+/* SPI register offsets */
+#define BCM2835_AUX_SPI_CNTL0 0x00
+#define BCM2835_AUX_SPI_CNTL1 0x04
+#define BCM2835_AUX_SPI_STAT 0x08
+#define BCM2835_AUX_SPI_PEEK 0x0C
+#define BCM2835_AUX_SPI_IO 0x20
+#define BCM2835_AUX_SPI_TXHOLD 0x30
+
+/* Bitfields in CNTL0 */
+#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000
+#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF
+#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20
+#define BCM2835_AUX_SPI_CNTL0_CS 0x000E0000
+#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000
+#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000
+#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
+#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800
+#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400
+#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200
+#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100
+#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080
+#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
+#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F
+
+/* Bitfields in CNTL1 */
+#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700
+#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080
+#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040
+#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002
+#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001
+
+/* Bitfields in STAT */
+#define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000
+#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000
+#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400
+#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200
+#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100
+#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080
+#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040
+#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F
+
+/* timeout values */
+#define BCM2835_AUX_SPI_POLLING_LIMIT_US 30
+#define BCM2835_AUX_SPI_POLLING_JIFFIES 2
+
+#define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
+ | SPI_NO_CS)
+
+struct bcm2835aux_spi {
+ void __iomem *regs;
+ struct clk *clk;
+ int irq;
+ u32 cntl[2];
+ const u8 *tx_buf;
+ u8 *rx_buf;
+ int tx_len;
+ int rx_len;
+ int pending;
+};
+
+static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg)
+{
+ return readl(bs->regs + reg);
+}
+
+static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg,
+ u32 val)
+{
+ writel(val, bs->regs + reg);
+}
+
+static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs)
+{
+ u32 data;
+ int count = min(bs->rx_len, 3);
+
+ data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
+ if (bs->rx_buf) {
+ switch (count) {
+ case 4:
+ *bs->rx_buf++ = (data >> 24) & 0xff;
+ /* fallthrough */
+ case 3:
+ *bs->rx_buf++ = (data >> 16) & 0xff;
+ /* fallthrough */
+ case 2:
+ *bs->rx_buf++ = (data >> 8) & 0xff;
+ /* fallthrough */
+ case 1:
+ *bs->rx_buf++ = (data >> 0) & 0xff;
+ /* fallthrough - no default */
+ }
+ }
+ bs->rx_len -= count;
+ bs->pending -= count;
+}
+
+static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
+{
+ u32 data;
+ u8 byte;
+ int count;
+ int i;
+
+ /* gather up to 3 bytes to write to the FIFO */
+ count = min(bs->tx_len, 3);
+ data = 0;
+ for (i = 0; i < count; i++) {
+ byte = bs->tx_buf ? *bs->tx_buf++ : 0;
+ data |= byte << (8 * (2 - i));
+ }
+
+ /* and set the variable bit-length */
+ data |= (count * 8) << 24;
+
+ /* and decrement length */
+ bs->tx_len -= count;
+ bs->pending += count;
+
+ /* write to the correct TX-register */
+ if (bs->tx_len)
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data);
+ else
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data);
+}
+
+static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
+{
+ /* disable spi clearing fifo and interrupts */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0,
+ BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
+}
+
+static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+{
+ struct spi_master *master = dev_id;
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+ irqreturn_t ret = IRQ_NONE;
+
+ /* check if we have data to read */
+ while (bs->rx_len &&
+ (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+ BCM2835_AUX_SPI_STAT_RX_EMPTY))) {
+ bcm2835aux_rd_fifo(bs);
+ ret = IRQ_HANDLED;
+ }
+
+ /* check if we have data to write */
+ while (bs->tx_len &&
+ (bs->pending < 12) &&
+ (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+ BCM2835_AUX_SPI_STAT_TX_FULL))) {
+ bcm2835aux_wr_fifo(bs);
+ ret = IRQ_HANDLED;
+ }
+
+ /* and check if we have reached "done" */
+ while (bs->rx_len &&
+ (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+ BCM2835_AUX_SPI_STAT_BUSY))) {
+ bcm2835aux_rd_fifo(bs);
+ ret = IRQ_HANDLED;
+ }
+
+ /* and if rx_len is 0 then wake up completion and disable spi */
+ if (!bs->rx_len) {
+ bcm2835aux_spi_reset_hw(bs);
+ complete(&master->xfer_completion);
+ }
+
+ /* and return */
+ return ret;
+}
+
+static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+ /* enable interrupts */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
+ BCM2835_AUX_SPI_CNTL1_TXEMPTY |
+ BCM2835_AUX_SPI_CNTL1_IDLE);
+
+ /* and wait for finish... */
+ return 1;
+}
+
+static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+ /* fill in registers and fifos before enabling interrupts */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+ /* fill in tx fifo with data before enabling interrupts */
+ while ((bs->tx_len) &&
+ (bs->pending < 12) &&
+ (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+ BCM2835_AUX_SPI_STAT_TX_FULL))) {
+ bcm2835aux_wr_fifo(bs);
+ }
+
+ /* now run the interrupt mode */
+ return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
+}
+
+static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+ unsigned long timeout;
+ u32 stat;
+
+ /* configure spi */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+ /* set the timeout */
+ timeout = jiffies + BCM2835_AUX_SPI_POLLING_JIFFIES;
+
+ /* loop until finished the transfer */
+ while (bs->rx_len) {
+ /* read status */
+ stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
+
+ /* fill in tx fifo with remaining data */
+ if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) {
+ bcm2835aux_wr_fifo(bs);
+ continue;
+ }
+
+ /* read data from fifo for both cases */
+ if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) {
+ bcm2835aux_rd_fifo(bs);
+ continue;
+ }
+ if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) {
+ bcm2835aux_rd_fifo(bs);
+ continue;
+ }
+
+ /* there is still data pending to read check the timeout */
+ if (bs->rx_len && time_after(jiffies, timeout)) {
+ dev_dbg_ratelimited(&spi->dev,
+ "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode\n",
+ jiffies - timeout,
+ bs->tx_len, bs->rx_len);
+ /* forward to interrupt handler */
+ return __bcm2835aux_spi_transfer_one_irq(master,
+ spi, tfr);
+ }
+ }
+
+ /* Transfer complete - reset SPI HW */
+ bcm2835aux_spi_reset_hw(bs);
+
+ /* and return without waiting for completion */
+ return 0;
+}
+
+static int bcm2835aux_spi_transfer_one(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+ unsigned long spi_hz, clk_hz, speed;
+ unsigned long spi_used_hz;
+ unsigned long long xfer_time_us;
+
+ /* calculate the registers to handle
+ *
+ * note that we use the variable data mode, which
+ * is not optimal for longer transfers as we waste registers
+ * resulting (potentially) in more interrupts when transferring
+ * more than 12 bytes
+ */
+ bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
+ BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
+ BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
+ bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
+
+ /* set clock */
+ spi_hz = tfr->speed_hz;
+ clk_hz = clk_get_rate(bs->clk);
+
+ if (spi_hz >= clk_hz / 2) {
+ speed = 0;
+ } else if (spi_hz) {
+ speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
+ if (speed > BCM2835_AUX_SPI_CNTL0_SPEED_MAX)
+ speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
+ } else { /* the slowest we can go */
+ speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
+ }
+ bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
+
+ spi_used_hz = clk_hz / (2 * (speed + 1));
+
+ /* handle all the modes */
+ if (spi->mode & SPI_CPOL)
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
+ if (spi->mode & SPI_CPHA)
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
+ BCM2835_AUX_SPI_CNTL0_CPHA_IN;
+
+ /* set transmit buffers and length */
+ bs->tx_buf = tfr->tx_buf;
+ bs->rx_buf = tfr->rx_buf;
+ bs->tx_len = tfr->len;
+ bs->rx_len = tfr->len;
+ bs->pending = 0;
+
+ /* calculate the estimated time in us the transfer runs
+ * note that there are are 2 idle clocks after each
+ * chunk getting transferred - in our case the chunk size
+ * is 3 bytes, so we approximate this by 9 bits/byte
+ */
+ xfer_time_us = tfr->len * 9 * 1000000;
+ do_div(xfer_time_us, spi_used_hz);
+
+ /* run in polling mode for short transfers */
+ if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
+ return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
+
+ /* run in interrupt mode for all others */
+ return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
+}
+
+static void bcm2835aux_spi_handle_err(struct spi_master *master,
+ struct spi_message *msg)
+{
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+ bcm2835aux_spi_reset_hw(bs);
+}
+
+static int bcm2835aux_spi_probe(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct bcm2835aux_spi *bs;
+ struct resource *res;
+ unsigned long clk_hz;
+ int err;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+ if (!master) {
+ dev_err(&pdev->dev, "spi_alloc_master() failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, master);
+ master->mode_bits = BCM2835_AUX_SPI_MODE_BITS;
+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->num_chipselect = -1;
+ master->transfer_one = bcm2835aux_spi_transfer_one;
+ master->handle_err = bcm2835aux_spi_handle_err;
+ master->dev.of_node = pdev->dev.of_node;
+
+ bs = spi_master_get_devdata(master);
+
+ /* the main area */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ bs->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(bs->regs)) {
+ err = PTR_ERR(bs->regs);
+ goto out_master_put;
+ }
+
+ bs->clk = devm_clk_get(&pdev->dev, NULL);
+ if ((!bs->clk) || (IS_ERR(bs->clk))) {
+ err = PTR_ERR(bs->clk);
+ dev_err(&pdev->dev, "could not get clk: %d\n", err);
+ goto out_master_put;
+ }
+
+ bs->irq = platform_get_irq(pdev, 0);
+ if (bs->irq <= 0) {
+ dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
+ err = bs->irq ? bs->irq : -ENODEV;
+ goto out_master_put;
+ }
+
+ /* this also enables the HW block */
+ err = clk_prepare_enable(bs->clk);
+ if (err) {
+ dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
+ goto out_master_put;
+ }
+
+ /* just checking if the clock returns a sane value */
+ clk_hz = clk_get_rate(bs->clk);
+ if (!clk_hz) {
+ dev_err(&pdev->dev, "clock returns 0 Hz\n");
+ err = -ENODEV;
+ goto out_clk_disable;
+ }
+
+ /* reset SPI-HW block */
+ bcm2835aux_spi_reset_hw(bs);
+
+ err = devm_request_irq(&pdev->dev, bs->irq,
+ bcm2835aux_spi_interrupt,
+ IRQF_SHARED,
+ dev_name(&pdev->dev), master);
+ if (err) {
+ dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
+ goto out_clk_disable;
+ }
+
+ err = devm_spi_register_master(&pdev->dev, master);
+ if (err) {
+ dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
+ goto out_clk_disable;
+ }
+
+ return 0;
+
+out_clk_disable:
+ clk_disable_unprepare(bs->clk);
+out_master_put:
+ spi_master_put(master);
+ return err;
+}
+
+static int bcm2835aux_spi_remove(struct platform_device *pdev)
+{
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+ bcm2835aux_spi_reset_hw(bs);
+
+ /* disable the HW block by releasing the clock */
+ clk_disable_unprepare(bs->clk);
+
+ return 0;
+}
+
+static const struct of_device_id bcm2835aux_spi_match[] = {
+ { .compatible = "brcm,bcm2835-aux-spi", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, bcm2835aux_spi_match);
+
+static struct platform_driver bcm2835aux_spi_driver = {
+ .driver = {
+ .name = "spi-bcm2835aux",
+ .of_match_table = bcm2835aux_spi_match,
+ },
+ .probe = bcm2835aux_spi_probe,
+ .remove = bcm2835aux_spi_remove,
+};
+module_platform_driver(bcm2835aux_spi_driver);
+
+MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux");
+MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c
index 1520554978a3..cc3f938f0a6b 100644
--- a/drivers/spi/spi-bcm53xx.c
+++ b/drivers/spi/spi-bcm53xx.c
@@ -247,28 +247,19 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
if (err) {
spi_master_put(master);
bcma_set_drvdata(core, NULL);
- goto out;
+ return err;
}
/* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
spi_new_device(master, &bcm53xx_info);
-out:
- return err;
-}
-
-static void bcm53xxspi_bcma_remove(struct bcma_device *core)
-{
- struct bcm53xxspi *b53spi = bcma_get_drvdata(core);
-
- spi_unregister_master(b53spi->master);
+ return 0;
}
static struct bcma_driver bcm53xxspi_bcma_driver = {
.name = KBUILD_MODNAME,
.id_table = bcm53xxspi_bcma_tbl,
.probe = bcm53xxspi_bcma_probe,
- .remove = bcm53xxspi_bcma_remove,
};
/**************************************************
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index e73e2b052c9c..06858e04ec59 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -27,10 +27,117 @@
#include <linux/err.h>
#include <linux/pm_runtime.h>
-#include <bcm63xx_dev_spi.h>
+/* BCM 6338/6348 SPI core */
+#define SPI_6348_RSET_SIZE 64
+#define SPI_6348_CMD 0x00 /* 16-bits register */
+#define SPI_6348_INT_STATUS 0x02
+#define SPI_6348_INT_MASK_ST 0x03
+#define SPI_6348_INT_MASK 0x04
+#define SPI_6348_ST 0x05
+#define SPI_6348_CLK_CFG 0x06
+#define SPI_6348_FILL_BYTE 0x07
+#define SPI_6348_MSG_TAIL 0x09
+#define SPI_6348_RX_TAIL 0x0b
+#define SPI_6348_MSG_CTL 0x40 /* 8-bits register */
+#define SPI_6348_MSG_CTL_WIDTH 8
+#define SPI_6348_MSG_DATA 0x41
+#define SPI_6348_MSG_DATA_SIZE 0x3f
+#define SPI_6348_RX_DATA 0x80
+#define SPI_6348_RX_DATA_SIZE 0x3f
+
+/* BCM 3368/6358/6262/6368 SPI core */
+#define SPI_6358_RSET_SIZE 1804
+#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
+#define SPI_6358_MSG_CTL_WIDTH 16
+#define SPI_6358_MSG_DATA 0x02
+#define SPI_6358_MSG_DATA_SIZE 0x21e
+#define SPI_6358_RX_DATA 0x400
+#define SPI_6358_RX_DATA_SIZE 0x220
+#define SPI_6358_CMD 0x700 /* 16-bits register */
+#define SPI_6358_INT_STATUS 0x702
+#define SPI_6358_INT_MASK_ST 0x703
+#define SPI_6358_INT_MASK 0x704
+#define SPI_6358_ST 0x705
+#define SPI_6358_CLK_CFG 0x706
+#define SPI_6358_FILL_BYTE 0x707
+#define SPI_6358_MSG_TAIL 0x709
+#define SPI_6358_RX_TAIL 0x70B
+
+/* Shared SPI definitions */
+
+/* Message configuration */
+#define SPI_FD_RW 0x00
+#define SPI_HD_W 0x01
+#define SPI_HD_R 0x02
+#define SPI_BYTE_CNT_SHIFT 0
+#define SPI_6348_MSG_TYPE_SHIFT 6
+#define SPI_6358_MSG_TYPE_SHIFT 14
+
+/* Command */
+#define SPI_CMD_NOOP 0x00
+#define SPI_CMD_SOFT_RESET 0x01
+#define SPI_CMD_HARD_RESET 0x02
+#define SPI_CMD_START_IMMEDIATE 0x03
+#define SPI_CMD_COMMAND_SHIFT 0
+#define SPI_CMD_COMMAND_MASK 0x000f
+#define SPI_CMD_DEVICE_ID_SHIFT 4
+#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
+#define SPI_CMD_ONE_BYTE_SHIFT 11
+#define SPI_CMD_ONE_WIRE_SHIFT 12
+#define SPI_DEV_ID_0 0
+#define SPI_DEV_ID_1 1
+#define SPI_DEV_ID_2 2
+#define SPI_DEV_ID_3 3
+
+/* Interrupt mask */
+#define SPI_INTR_CMD_DONE 0x01
+#define SPI_INTR_RX_OVERFLOW 0x02
+#define SPI_INTR_TX_UNDERFLOW 0x04
+#define SPI_INTR_TX_OVERFLOW 0x08
+#define SPI_INTR_RX_UNDERFLOW 0x10
+#define SPI_INTR_CLEAR_ALL 0x1f
+
+/* Status */
+#define SPI_RX_EMPTY 0x02
+#define SPI_CMD_BUSY 0x04
+#define SPI_SERIAL_BUSY 0x08
+
+/* Clock configuration */
+#define SPI_CLK_20MHZ 0x00
+#define SPI_CLK_0_391MHZ 0x01
+#define SPI_CLK_0_781MHZ 0x02 /* default */
+#define SPI_CLK_1_563MHZ 0x03
+#define SPI_CLK_3_125MHZ 0x04
+#define SPI_CLK_6_250MHZ 0x05
+#define SPI_CLK_12_50MHZ 0x06
+#define SPI_CLK_MASK 0x07
+#define SPI_SSOFFTIME_MASK 0x38
+#define SPI_SSOFFTIME_SHIFT 3
+#define SPI_BYTE_SWAP 0x80
+
+enum bcm63xx_regs_spi {
+ SPI_CMD,
+ SPI_INT_STATUS,
+ SPI_INT_MASK_ST,
+ SPI_INT_MASK,
+ SPI_ST,
+ SPI_CLK_CFG,
+ SPI_FILL_BYTE,
+ SPI_MSG_TAIL,
+ SPI_RX_TAIL,
+ SPI_MSG_CTL,
+ SPI_MSG_DATA,
+ SPI_RX_DATA,
+ SPI_MSG_TYPE_SHIFT,
+ SPI_MSG_CTL_WIDTH,
+ SPI_MSG_DATA_SIZE,
+};
#define BCM63XX_SPI_MAX_PREPEND 15
+#define BCM63XX_SPI_MAX_CS 8
+#define BCM63XX_SPI_BUS_NUM 0
+
struct bcm63xx_spi {
struct completion done;
@@ -38,6 +145,7 @@ struct bcm63xx_spi {
int irq;
/* Platform data */
+ const unsigned long *reg_offsets;
unsigned fifo_size;
unsigned int msg_type_shift;
unsigned int msg_ctl_width;
@@ -51,27 +159,35 @@ struct bcm63xx_spi {
};
static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
- unsigned int offset)
+ unsigned int offset)
{
- return bcm_readb(bs->regs + bcm63xx_spireg(offset));
+ return readb(bs->regs + bs->reg_offsets[offset]);
}
static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
unsigned int offset)
{
- return bcm_readw(bs->regs + bcm63xx_spireg(offset));
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ return ioread16be(bs->regs + bs->reg_offsets[offset]);
+#else
+ return readw(bs->regs + bs->reg_offsets[offset]);
+#endif
}
static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
u8 value, unsigned int offset)
{
- bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
+ writeb(value, bs->regs + bs->reg_offsets[offset]);
}
static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
u16 value, unsigned int offset)
{
- bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ iowrite16be(value, bs->regs + bs->reg_offsets[offset]);
+#else
+ writew(value, bs->regs + bs->reg_offsets[offset]);
+#endif
}
static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
@@ -122,7 +238,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
u16 msg_ctl;
u16 cmd;
- u8 rx_tail;
unsigned int i, timeout = 0, prepend_len = 0, len = 0;
struct spi_transfer *t = first;
bool do_rx = false;
@@ -314,18 +429,71 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static const unsigned long bcm6348_spi_reg_offsets[] = {
+ [SPI_CMD] = SPI_6348_CMD,
+ [SPI_INT_STATUS] = SPI_6348_INT_STATUS,
+ [SPI_INT_MASK_ST] = SPI_6348_INT_MASK_ST,
+ [SPI_INT_MASK] = SPI_6348_INT_MASK,
+ [SPI_ST] = SPI_6348_ST,
+ [SPI_CLK_CFG] = SPI_6348_CLK_CFG,
+ [SPI_FILL_BYTE] = SPI_6348_FILL_BYTE,
+ [SPI_MSG_TAIL] = SPI_6348_MSG_TAIL,
+ [SPI_RX_TAIL] = SPI_6348_RX_TAIL,
+ [SPI_MSG_CTL] = SPI_6348_MSG_CTL,
+ [SPI_MSG_DATA] = SPI_6348_MSG_DATA,
+ [SPI_RX_DATA] = SPI_6348_RX_DATA,
+ [SPI_MSG_TYPE_SHIFT] = SPI_6348_MSG_TYPE_SHIFT,
+ [SPI_MSG_CTL_WIDTH] = SPI_6348_MSG_CTL_WIDTH,
+ [SPI_MSG_DATA_SIZE] = SPI_6348_MSG_DATA_SIZE,
+};
+
+static const unsigned long bcm6358_spi_reg_offsets[] = {
+ [SPI_CMD] = SPI_6358_CMD,
+ [SPI_INT_STATUS] = SPI_6358_INT_STATUS,
+ [SPI_INT_MASK_ST] = SPI_6358_INT_MASK_ST,
+ [SPI_INT_MASK] = SPI_6358_INT_MASK,
+ [SPI_ST] = SPI_6358_ST,
+ [SPI_CLK_CFG] = SPI_6358_CLK_CFG,
+ [SPI_FILL_BYTE] = SPI_6358_FILL_BYTE,
+ [SPI_MSG_TAIL] = SPI_6358_MSG_TAIL,
+ [SPI_RX_TAIL] = SPI_6358_RX_TAIL,
+ [SPI_MSG_CTL] = SPI_6358_MSG_CTL,
+ [SPI_MSG_DATA] = SPI_6358_MSG_DATA,
+ [SPI_RX_DATA] = SPI_6358_RX_DATA,
+ [SPI_MSG_TYPE_SHIFT] = SPI_6358_MSG_TYPE_SHIFT,
+ [SPI_MSG_CTL_WIDTH] = SPI_6358_MSG_CTL_WIDTH,
+ [SPI_MSG_DATA_SIZE] = SPI_6358_MSG_DATA_SIZE,
+};
+
+static const struct platform_device_id bcm63xx_spi_dev_match[] = {
+ {
+ .name = "bcm6348-spi",
+ .driver_data = (unsigned long)bcm6348_spi_reg_offsets,
+ },
+ {
+ .name = "bcm6358-spi",
+ .driver_data = (unsigned long)bcm6358_spi_reg_offsets,
+ },
+ {
+ },
+};
static int bcm63xx_spi_probe(struct platform_device *pdev)
{
struct resource *r;
+ const unsigned long *bcm63xx_spireg;
struct device *dev = &pdev->dev;
- struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
int irq;
struct spi_master *master;
struct clk *clk;
struct bcm63xx_spi *bs;
int ret;
+ if (!pdev->id_entry->driver_data)
+ return -EINVAL;
+
+ bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
+
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq\n");
@@ -359,7 +527,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
bs->irq = irq;
bs->clk = clk;
- bs->fifo_size = pdata->fifo_size;
+ bs->reg_offsets = bcm63xx_spireg;
+ bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE];
ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
pdev->name, master);
@@ -368,26 +537,16 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
goto out_err;
}
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->num_chipselect;
+ master->bus_num = BCM63XX_SPI_BUS_NUM;
+ master->num_chipselect = BCM63XX_SPI_MAX_CS;
master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->auto_runtime_pm = true;
- bs->msg_type_shift = pdata->msg_type_shift;
- bs->msg_ctl_width = pdata->msg_ctl_width;
- bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
- bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
-
- switch (bs->msg_ctl_width) {
- case 8:
- case 16:
- break;
- default:
- dev_err(dev, "unsupported MSG_CTL width: %d\n",
- bs->msg_ctl_width);
- goto out_err;
- }
+ bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
+ bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
+ bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
+ bs->rx_io = (const u8 *)(bs->regs + bs->reg_offsets[SPI_RX_DATA]);
/* Initialize hardware */
ret = clk_prepare_enable(bs->clk);
@@ -467,6 +626,7 @@ static struct platform_driver bcm63xx_spi_driver = {
.name = "bcm63xx-spi",
.pm = &bcm63xx_spi_pm_ops,
},
+ .id_table = bcm63xx_spi_dev_match,
.probe = bcm63xx_spi_probe,
.remove = bcm63xx_spi_remove,
};
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
index a78693189f45..6c967555a56a 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -352,10 +352,7 @@ bfin_sport_spi_pump_transfers(unsigned long data)
transfer = drv_data->cur_transfer;
chip = drv_data->cur_chip;
- if (transfer->speed_hz)
- transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
- else
- transfer_speed = chip->baud;
+ transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
bfin_write(&drv_data->regs->tclkdiv, transfer_speed);
SSYNC();
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index a3d65b4f4944..1e91325bf39c 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -661,11 +661,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
message->state = RUNNING_STATE;
dma_config = 0;
- /* Speed setup (surely valid because already checked) */
- if (transfer->speed_hz)
- bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
- else
- bfin_write(&drv_data->regs->baud, chip->baud);
+ bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
bfin_spi_cs_active(drv_data, chip);
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index 840a4984d365..3aa9e6e3dac8 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -24,6 +24,8 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
+#define SPI_BITBANG_CS_DELAY 100
+
/*----------------------------------------------------------------------*/
@@ -180,7 +182,6 @@ int spi_bitbang_setup(struct spi_device *spi)
{
struct spi_bitbang_cs *cs = spi->controller_state;
struct spi_bitbang *bitbang;
- unsigned long flags;
bitbang = spi_master_get_devdata(spi->master);
@@ -210,12 +211,12 @@ int spi_bitbang_setup(struct spi_device *spi)
*/
/* deselect chip (low or high) */
- spin_lock_irqsave(&bitbang->lock, flags);
+ mutex_lock(&bitbang->lock);
if (!bitbang->busy) {
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(cs->nsecs);
}
- spin_unlock_irqrestore(&bitbang->lock, flags);
+ mutex_unlock(&bitbang->lock);
return 0;
}
@@ -255,122 +256,39 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
static int spi_bitbang_prepare_hardware(struct spi_master *spi)
{
struct spi_bitbang *bitbang;
- unsigned long flags;
bitbang = spi_master_get_devdata(spi);
- spin_lock_irqsave(&bitbang->lock, flags);
+ mutex_lock(&bitbang->lock);
bitbang->busy = 1;
- spin_unlock_irqrestore(&bitbang->lock, flags);
+ mutex_unlock(&bitbang->lock);
return 0;
}
static int spi_bitbang_transfer_one(struct spi_master *master,
- struct spi_message *m)
+ struct spi_device *spi,
+ struct spi_transfer *transfer)
{
- struct spi_bitbang *bitbang;
- unsigned nsecs;
- struct spi_transfer *t = NULL;
- unsigned cs_change;
- int status;
- int do_setup = -1;
- struct spi_device *spi = m->spi;
-
- bitbang = spi_master_get_devdata(master);
-
- /* FIXME this is made-up ... the correct value is known to
- * word-at-a-time bitbang code, and presumably chipselect()
- * should enforce these requirements too?
- */
- nsecs = 100;
-
- cs_change = 1;
- status = 0;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
-
- /* override speed or wordsize? */
- if (t->speed_hz || t->bits_per_word)
- do_setup = 1;
-
- /* init (-1) or override (1) transfer params */
- if (do_setup != 0) {
- if (bitbang->setup_transfer) {
- status = bitbang->setup_transfer(spi, t);
- if (status < 0)
- break;
- }
- if (do_setup == -1)
- do_setup = 0;
- }
-
- /* set up default clock polarity, and activate chip;
- * this implicitly updates clock and spi modes as
- * previously recorded for this device via setup().
- * (and also deselects any other chip that might be
- * selected ...)
- */
- if (cs_change) {
- bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
- ndelay(nsecs);
- }
- cs_change = t->cs_change;
- if (!t->tx_buf && !t->rx_buf && t->len) {
- status = -EINVAL;
- break;
- }
-
- /* transfer data. the lower level code handles any
- * new dma mappings it needs. our caller always gave
- * us dma-safe buffers.
- */
- if (t->len) {
- /* REVISIT dma API still needs a designated
- * DMA_ADDR_INVALID; ~0 might be better.
- */
- if (!m->is_dma_mapped)
- t->rx_dma = t->tx_dma = 0;
- status = bitbang->txrx_bufs(spi, t);
- }
- if (status > 0)
- m->actual_length += status;
- if (status != t->len) {
- /* always report some kind of error */
- if (status >= 0)
- status = -EREMOTEIO;
- break;
- }
- status = 0;
+ struct spi_bitbang *bitbang = spi_master_get_devdata(master);
+ int status = 0;
- /* protocol tweaks before next transfer */
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (cs_change &&
- !list_is_last(&t->transfer_list, &m->transfers)) {
- /* sometimes a short mid-message deselect of the chip
- * may be needed to terminate a mode or command
- */
- ndelay(nsecs);
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
+ if (bitbang->setup_transfer) {
+ status = bitbang->setup_transfer(spi, transfer);
+ if (status < 0)
+ goto out;
}
- m->status = status;
+ if (transfer->len)
+ status = bitbang->txrx_bufs(spi, transfer);
- /* normally deactivate chipselect ... unless no error and
- * cs_change has hinted that the next message will probably
- * be for this chip too.
- */
- if (!(status == 0 && cs_change)) {
- ndelay(nsecs);
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
+ if (status == transfer->len)
+ status = 0;
+ else if (status >= 0)
+ status = -EREMOTEIO;
- spi_finalize_current_message(master);
+out:
+ spi_finalize_current_transfer(master);
return status;
}
@@ -378,17 +296,32 @@ static int spi_bitbang_transfer_one(struct spi_master *master,
static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
{
struct spi_bitbang *bitbang;
- unsigned long flags;
bitbang = spi_master_get_devdata(spi);
- spin_lock_irqsave(&bitbang->lock, flags);
+ mutex_lock(&bitbang->lock);
bitbang->busy = 0;
- spin_unlock_irqrestore(&bitbang->lock, flags);
+ mutex_unlock(&bitbang->lock);
return 0;
}
+static void spi_bitbang_set_cs(struct spi_device *spi, bool enable)
+{
+ struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master);
+
+ /* SPI core provides CS high / low, but bitbang driver
+ * expects CS active
+ * spi device driver takes care of handling SPI_CS_HIGH
+ */
+ enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
+
+ ndelay(SPI_BITBANG_CS_DELAY);
+ bitbang->chipselect(spi, enable ? BITBANG_CS_ACTIVE :
+ BITBANG_CS_INACTIVE);
+ ndelay(SPI_BITBANG_CS_DELAY);
+}
+
/*----------------------------------------------------------------------*/
/**
@@ -427,7 +360,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
if (!master || !bitbang->chipselect)
return -EINVAL;
- spin_lock_init(&bitbang->lock);
+ mutex_init(&bitbang->lock);
if (!master->mode_bits)
master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
@@ -437,7 +370,8 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
- master->transfer_one_message = spi_bitbang_transfer_one;
+ master->transfer_one = spi_bitbang_transfer_one;
+ master->set_cs = spi_bitbang_set_cs;
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index 688956ff5095..23f6fffd75e1 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -420,19 +420,20 @@ static int mcfqspi_probe(struct platform_device *pdev)
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);
+ pm_runtime_enable(&pdev->dev);
status = devm_spi_register_master(&pdev->dev, master);
if (status) {
dev_dbg(&pdev->dev, "spi_register_master failed\n");
goto fail2;
}
- pm_runtime_enable(&pdev->dev);
dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
return 0;
fail2:
+ pm_runtime_disable(&pdev->dev);
mcfqspi_cs_teardown(mcfqspi);
fail1:
clk_disable(mcfqspi->clk);
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index a85d863d4a44..7d3af3eacf57 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -215,18 +215,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
struct davinci_spi_config *spicfg = spi->controller_data;
u8 chip_sel = spi->chip_select;
u16 spidat1 = CS_DEFAULT;
- bool gpio_chipsel = false;
- int gpio;
dspi = spi_master_get_devdata(spi->master);
pdata = &dspi->pdata;
- if (spi->cs_gpio >= 0) {
- /* SPI core parse and update master->cs_gpio */
- gpio_chipsel = true;
- gpio = spi->cs_gpio;
- }
-
/* program delay transfers if tx_delay is non zero */
if (spicfg->wdelay)
spidat1 |= SPIDAT1_WDEL;
@@ -235,11 +227,12 @@ 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 (gpio_chipsel) {
+ if (spi->cs_gpio >= 0) {
if (value == BITBANG_CS_ACTIVE)
- gpio_set_value(gpio, spi->mode & SPI_CS_HIGH);
+ gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH);
else
- gpio_set_value(gpio, !(spi->mode & SPI_CS_HIGH));
+ gpio_set_value(spi->cs_gpio,
+ !(spi->mode & SPI_CS_HIGH));
} else {
if (value == BITBANG_CS_ACTIVE) {
spidat1 |= SPIDAT1_CSHOLD_MASK;
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 7edede6e024b..a6d7029a85ac 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
+#include <linux/property.h>
#include "spi-dw.h"
@@ -74,13 +75,11 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->max_freq = clk_get_rate(dwsmmio->clk);
- of_property_read_u32(pdev->dev.of_node, "reg-io-width",
- &dws->reg_io_width);
+ device_property_read_u32(&pdev->dev, "reg-io-width", &dws->reg_io_width);
num_cs = 4;
- if (pdev->dev.of_node)
- of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
+ device_property_read_u32(&pdev->dev, "num-cs", &num_cs);
dws->num_cs = num_cs;
diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 6d331e0db331..332ccb0539a7 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -23,11 +23,6 @@
#define DRIVER_NAME "dw_spi_pci"
-struct dw_spi_pci {
- struct pci_dev *pdev;
- struct dw_spi dws;
-};
-
struct spi_pci_desc {
int (*setup)(struct dw_spi *);
u16 num_cs;
@@ -48,7 +43,6 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = {
static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- struct dw_spi_pci *dwpci;
struct dw_spi *dws;
struct spi_pci_desc *desc = (struct spi_pci_desc *)ent->driver_data;
int pci_bar = 0;
@@ -58,14 +52,10 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- dwpci = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_pci),
- GFP_KERNEL);
- if (!dwpci)
+ dws = devm_kzalloc(&pdev->dev, sizeof(*dws), GFP_KERNEL);
+ if (!dws)
return -ENOMEM;
- dwpci->pdev = pdev;
- dws = &dwpci->dws;
-
/* Get basic io resource and map it */
dws->paddr = pci_resource_start(pdev, pci_bar);
@@ -74,7 +64,6 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return ret;
dws->regs = pcim_iomap_table(pdev)[pci_bar];
-
dws->irq = pdev->irq;
/*
@@ -99,7 +88,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return ret;
/* PCI hook and SPI hook use the same drv data */
- pci_set_drvdata(pdev, dwpci);
+ pci_set_drvdata(pdev, dws);
dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
pdev->vendor, pdev->device);
@@ -109,26 +98,26 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static void spi_pci_remove(struct pci_dev *pdev)
{
- struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+ struct dw_spi *dws = pci_get_drvdata(pdev);
- dw_spi_remove_host(&dwpci->dws);
+ dw_spi_remove_host(dws);
}
#ifdef CONFIG_PM_SLEEP
static int spi_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
- struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+ struct dw_spi *dws = pci_get_drvdata(pdev);
- return dw_spi_suspend_host(&dwpci->dws);
+ return dw_spi_suspend_host(dws);
}
static int spi_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
- struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+ struct dw_spi *dws = pci_get_drvdata(pdev);
- return dw_spi_resume_host(&dwpci->dws);
+ return dw_spi_resume_host(dws);
}
#endif
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 4fbfcdc5cb24..882cd6618cd5 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -30,19 +30,13 @@
/* Slave spi_dev related */
struct chip_data {
- u16 cr0;
u8 cs; /* chip select pin */
- u8 n_bytes; /* current is a 1/2/4 byte op */
u8 tmode; /* TR/TO/RO/EEPROM */
u8 type; /* SPI/SSP/MicroWire */
u8 poll_mode; /* 1 means use poll mode */
- u32 dma_width;
- u32 rx_threshold;
- u32 tx_threshold;
u8 enable_dma;
- u8 bits_per_word;
u16 clk_div; /* baud rate divider */
u32 speed_hz; /* baud rate */
void (*cs_control)(u32 command);
@@ -289,14 +283,11 @@ static int dw_spi_transfer_one(struct spi_master *master,
struct chip_data *chip = spi_get_ctldata(spi);
u8 imask = 0;
u16 txlevel = 0;
- u16 clk_div = 0;
- u32 speed = 0;
- u32 cr0 = 0;
+ u16 clk_div;
+ u32 cr0;
int ret;
dws->dma_mapped = 0;
- dws->n_bytes = chip->n_bytes;
- dws->dma_width = chip->dma_width;
dws->tx = (void *)transfer->tx_buf;
dws->tx_end = dws->tx + transfer->len;
@@ -306,37 +297,30 @@ static int dw_spi_transfer_one(struct spi_master *master,
spi_enable_chip(dws, 0);
- cr0 = chip->cr0;
-
/* Handle per transfer options for bpw and speed */
- if (transfer->speed_hz) {
- speed = chip->speed_hz;
-
- if ((transfer->speed_hz != speed) || !chip->clk_div) {
- speed = transfer->speed_hz;
-
- /* clk_div doesn't support odd number */
- clk_div = (dws->max_freq / speed + 1) & 0xfffe;
+ if (transfer->speed_hz != chip->speed_hz) {
+ /* clk_div doesn't support odd number */
+ clk_div = (dws->max_freq / transfer->speed_hz + 1) & 0xfffe;
- chip->speed_hz = speed;
- chip->clk_div = clk_div;
+ chip->speed_hz = transfer->speed_hz;
+ chip->clk_div = clk_div;
- spi_set_clk(dws, chip->clk_div);
- }
+ spi_set_clk(dws, chip->clk_div);
}
- if (transfer->bits_per_word) {
- if (transfer->bits_per_word == 8) {
- dws->n_bytes = 1;
- dws->dma_width = 1;
- } else if (transfer->bits_per_word == 16) {
- dws->n_bytes = 2;
- dws->dma_width = 2;
- }
- cr0 = (transfer->bits_per_word - 1)
- | (chip->type << SPI_FRF_OFFSET)
- | (spi->mode << SPI_MODE_OFFSET)
- | (chip->tmode << SPI_TMOD_OFFSET);
+ if (transfer->bits_per_word == 8) {
+ dws->n_bytes = 1;
+ dws->dma_width = 1;
+ } else if (transfer->bits_per_word == 16) {
+ dws->n_bytes = 2;
+ dws->dma_width = 2;
+ } else {
+ return -EINVAL;
}
+ /* Default SPI mode is SCPOL = 0, SCPH = 0 */
+ cr0 = (transfer->bits_per_word - 1)
+ | (chip->type << SPI_FRF_OFFSET)
+ | (spi->mode << SPI_MODE_OFFSET)
+ | (chip->tmode << SPI_TMOD_OFFSET);
/*
* Adjust transfer mode if necessary. Requires platform dependent
@@ -439,34 +423,9 @@ static int dw_spi_setup(struct spi_device *spi)
chip->poll_mode = chip_info->poll_mode;
chip->type = chip_info->type;
-
- chip->rx_threshold = 0;
- chip->tx_threshold = 0;
- }
-
- if (spi->bits_per_word == 8) {
- chip->n_bytes = 1;
- chip->dma_width = 1;
- } else if (spi->bits_per_word == 16) {
- chip->n_bytes = 2;
- chip->dma_width = 2;
- }
- chip->bits_per_word = spi->bits_per_word;
-
- if (!spi->max_speed_hz) {
- dev_err(&spi->dev, "No max speed HZ parameter\n");
- return -EINVAL;
}
chip->tmode = 0; /* Tx & Rx */
- /* Default SPI mode is SCPOL = 0, SCPH = 0 */
- chip->cr0 = (chip->bits_per_word - 1)
- | (chip->type << SPI_FRF_OFFSET)
- | (spi->mode << SPI_MODE_OFFSET)
- | (chip->tmode << SPI_TMOD_OFFSET);
-
- if (spi->mode & SPI_LOOP)
- chip->cr0 |= 1 << SPI_SRL_OFFSET;
if (gpio_is_valid(spi->cs_gpio)) {
ret = gpio_direction_output(spi->cs_gpio,
@@ -524,13 +483,12 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
dws->master = master;
dws->type = SSI_MOTO_SPI;
dws->dma_inited = 0;
- dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+ dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
- ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
- dws->name, master);
+ ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, master);
if (ret < 0) {
- dev_err(&master->dev, "can not get IRQ\n");
+ dev_err(dev, "can not get IRQ\n");
goto err_free_master;
}
@@ -573,6 +531,7 @@ err_dma_exit:
if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws);
spi_enable_chip(dws, 0);
+ free_irq(dws->irq, master);
err_free_master:
spi_master_put(master);
return ret;
@@ -581,28 +540,27 @@ EXPORT_SYMBOL_GPL(dw_spi_add_host);
void dw_spi_remove_host(struct dw_spi *dws)
{
- if (!dws)
- return;
dw_spi_debugfs_remove(dws);
if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws);
- spi_enable_chip(dws, 0);
- /* Disable clk */
- spi_set_clk(dws, 0);
+
+ spi_shutdown_chip(dws);
+
+ free_irq(dws->irq, dws->master);
}
EXPORT_SYMBOL_GPL(dw_spi_remove_host);
int dw_spi_suspend_host(struct dw_spi *dws)
{
- int ret = 0;
+ int ret;
ret = spi_master_suspend(dws->master);
if (ret)
return ret;
- spi_enable_chip(dws, 0);
- spi_set_clk(dws, 0);
- return ret;
+
+ spi_shutdown_chip(dws);
+ return 0;
}
EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index b75ed327d5a2..35589a270468 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -225,6 +225,12 @@ static inline void spi_reset_chip(struct dw_spi *dws)
spi_enable_chip(dws, 1);
}
+static inline void spi_shutdown_chip(struct dw_spi *dws)
+{
+ spi_enable_chip(dws, 0);
+ spi_set_clk(dws, 0);
+}
+
/*
* Each SPI slave device to work with dw_api controller should
* has such a structure claiming its working mode (poll or PIO/DMA),
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 86bcdd68c1fe..59a11437db70 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -409,9 +409,6 @@ static int dspi_transfer_one_message(struct spi_master *master,
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
dspi->cur_chip->ctar_val);
- if (transfer->speed_hz)
- regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
- dspi->cur_chip->ctar_val);
trans_mode = dspi->devtype_data->trans_mode;
switch (trans_mode) {
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f9deb84e4e55..0e5723ab47f0 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -336,13 +336,20 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
if (config->mode & SPI_CPHA)
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
+ else
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
if (config->mode & SPI_CPOL) {
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
+ } else {
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
}
if (config->mode & SPI_CS_HIGH)
cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
+ else
+ cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 1e75341689a6..c3ec46cd9f91 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -302,11 +302,9 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
cs_change = 1;
status = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->bits_per_word || t->speed_hz) {
- status = mpc512x_psc_spi_transfer_setup(spi, t);
- if (status < 0)
- break;
- }
+ status = mpc512x_psc_spi_transfer_setup(spi, t);
+ if (status < 0)
+ break;
if (cs_change)
mpc512x_psc_spi_activate_cs(spi);
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index ecb6c58238c4..563954a61424 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -20,6 +20,7 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/platform_data/spi-mt65xx.h>
#include <linux/pm_runtime.h>
@@ -84,7 +85,8 @@ struct mtk_spi_compatible {
struct mtk_spi {
void __iomem *base;
u32 state;
- u32 pad_sel;
+ int pad_num;
+ u32 *pad_sel;
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
@@ -131,10 +133,28 @@ static void mtk_spi_reset(struct mtk_spi *mdata)
writel(reg_val, mdata->base + SPI_CMD_REG);
}
-static void mtk_spi_config(struct mtk_spi *mdata,
- struct mtk_chip_config *chip_config)
+static int mtk_spi_prepare_message(struct spi_master *master,
+ struct spi_message *msg)
{
+ u16 cpha, cpol;
u32 reg_val;
+ struct spi_device *spi = msg->spi;
+ struct mtk_chip_config *chip_config = spi->controller_data;
+ struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+ cpha = spi->mode & SPI_CPHA ? 1 : 0;
+ cpol = spi->mode & SPI_CPOL ? 1 : 0;
+
+ reg_val = readl(mdata->base + SPI_CMD_REG);
+ if (cpha)
+ reg_val |= SPI_CMD_CPHA;
+ else
+ reg_val &= ~SPI_CMD_CPHA;
+ if (cpol)
+ reg_val |= SPI_CMD_CPOL;
+ else
+ reg_val &= ~SPI_CMD_CPOL;
+ writel(reg_val, mdata->base + SPI_CMD_REG);
reg_val = readl(mdata->base + SPI_CMD_REG);
@@ -170,38 +190,8 @@ static void mtk_spi_config(struct mtk_spi *mdata,
/* pad select */
if (mdata->dev_comp->need_pad_sel)
- writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG);
-}
-
-static int mtk_spi_prepare_message(struct spi_master *master,
- struct spi_message *msg)
-{
- u32 reg_val;
- u8 cpha, cpol;
- struct mtk_chip_config *chip_config;
- struct spi_device *spi = msg->spi;
- struct mtk_spi *mdata = spi_master_get_devdata(master);
-
- cpha = spi->mode & SPI_CPHA ? 1 : 0;
- cpol = spi->mode & SPI_CPOL ? 1 : 0;
-
- reg_val = readl(mdata->base + SPI_CMD_REG);
- if (cpha)
- reg_val |= SPI_CMD_CPHA;
- else
- reg_val &= ~SPI_CMD_CPHA;
- if (cpol)
- reg_val |= SPI_CMD_CPOL;
- else
- reg_val &= ~SPI_CMD_CPOL;
- writel(reg_val, mdata->base + SPI_CMD_REG);
-
- chip_config = spi->controller_data;
- if (!chip_config) {
- chip_config = (void *)&mtk_default_chip_info;
- spi->controller_data = chip_config;
- }
- mtk_spi_config(mdata, chip_config);
+ writel(mdata->pad_sel[spi->chip_select],
+ mdata->base + SPI_PAD_SEL_REG);
return 0;
}
@@ -413,6 +403,19 @@ static bool mtk_spi_can_dma(struct spi_master *master,
return xfer->len > MTK_SPI_MAX_FIFO_SIZE;
}
+static int mtk_spi_setup(struct spi_device *spi)
+{
+ struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
+
+ if (!spi->controller_data)
+ spi->controller_data = (void *)&mtk_default_chip_info;
+
+ if (mdata->dev_comp->need_pad_sel)
+ gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+
+ return 0;
+}
+
static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
{
u32 cmd, reg_val, cnt;
@@ -484,7 +487,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
struct mtk_spi *mdata;
const struct of_device_id *of_id;
struct resource *res;
- int irq, ret;
+ int i, irq, ret;
master = spi_alloc_master(&pdev->dev, sizeof(*mdata));
if (!master) {
@@ -500,6 +503,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
master->prepare_message = mtk_spi_prepare_message;
master->transfer_one = mtk_spi_transfer_one;
master->can_dma = mtk_spi_can_dma;
+ master->setup = mtk_spi_setup;
of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
if (!of_id) {
@@ -514,21 +518,34 @@ static int mtk_spi_probe(struct platform_device *pdev)
master->flags = SPI_MASTER_MUST_TX;
if (mdata->dev_comp->need_pad_sel) {
- ret = of_property_read_u32(pdev->dev.of_node,
- "mediatek,pad-select",
- &mdata->pad_sel);
- if (ret) {
- dev_err(&pdev->dev, "failed to read pad select: %d\n",
- ret);
+ mdata->pad_num = of_property_count_u32_elems(
+ pdev->dev.of_node,
+ "mediatek,pad-select");
+ if (mdata->pad_num < 0) {
+ dev_err(&pdev->dev,
+ "No 'mediatek,pad-select' property\n");
+ ret = -EINVAL;
goto err_put_master;
}
- if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) {
- dev_err(&pdev->dev, "wrong pad-select: %u\n",
- mdata->pad_sel);
- ret = -EINVAL;
+ mdata->pad_sel = devm_kmalloc_array(&pdev->dev, mdata->pad_num,
+ sizeof(u32), GFP_KERNEL);
+ if (!mdata->pad_sel) {
+ ret = -ENOMEM;
goto err_put_master;
}
+
+ for (i = 0; i < mdata->pad_num; i++) {
+ of_property_read_u32_index(pdev->dev.of_node,
+ "mediatek,pad-select",
+ i, &mdata->pad_sel[i]);
+ if (mdata->pad_sel[i] > MT8173_SPI_MAX_PAD_SEL) {
+ dev_err(&pdev->dev, "wrong pad-sel[%d]: %u\n",
+ i, mdata->pad_sel[i]);
+ ret = -EINVAL;
+ goto err_put_master;
+ }
+ }
}
platform_set_drvdata(pdev, master);
@@ -606,6 +623,26 @@ static int mtk_spi_probe(struct platform_device *pdev)
goto err_put_master;
}
+ if (mdata->dev_comp->need_pad_sel) {
+ if (mdata->pad_num != master->num_chipselect) {
+ dev_err(&pdev->dev,
+ "pad_num does not match num_chipselect(%d != %d)\n",
+ mdata->pad_num, master->num_chipselect);
+ ret = -EINVAL;
+ goto err_put_master;
+ }
+
+ for (i = 0; i < master->num_chipselect; i++) {
+ ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
+ dev_name(&pdev->dev));
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't get CS GPIO %i\n", i);
+ goto err_put_master;
+ }
+ }
+ }
+
return 0;
err_disable_clk:
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index 76656a77ec12..b5911282a611 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -207,8 +207,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
struct tiny_spi *hw = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node;
unsigned int i;
- const __be32 *val;
- int len;
+ u32 val;
if (!np)
return 0;
@@ -226,13 +225,10 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
return -ENODEV;
}
hw->bitbang.master->dev.of_node = pdev->dev.of_node;
- val = of_get_property(pdev->dev.of_node,
- "clock-frequency", &len);
- if (val && len >= sizeof(__be32))
- hw->freq = be32_to_cpup(val);
- val = of_get_property(pdev->dev.of_node, "baud-width", &len);
- if (val && len >= sizeof(__be32))
- hw->baudwidth = be32_to_cpup(val);
+ if (!of_property_read_u32(np, "clock-frequency", &val))
+ hw->freq = val;
+ if (!of_property_read_u32(np, "baud-width", &val))
+ hw->baudwidth = val;
return 0;
}
#else /* !CONFIG_OF */
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
index e99d6a93d394..07e4ce8273df 100644
--- a/drivers/spi/spi-octeon.c
+++ b/drivers/spi/spi-octeon.c
@@ -65,7 +65,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
cpha = mode & SPI_CPHA;
cpol = mode & SPI_CPOL;
- speed_hz = xfer->speed_hz ? : spi->max_speed_hz;
+ speed_hz = xfer->speed_hz;
clkdiv = octeon_get_io_clock_rate() / (2 * speed_hz);
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
index 35b332dacb13..76a8425be227 100644
--- a/drivers/spi/spi-omap-100k.c
+++ b/drivers/spi/spi-omap-100k.c
@@ -244,12 +244,12 @@ static int omap1_spi100k_setup_transfer(struct spi_device *spi,
{
struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master);
struct omap1_spi100k_cs *cs = spi->controller_state;
- u8 word_len = spi->bits_per_word;
+ u8 word_len;
- if (t != NULL && t->bits_per_word)
+ if (t != NULL)
word_len = t->bits_per_word;
- if (!word_len)
- word_len = 8;
+ else
+ word_len = spi->bits_per_word;
if (spi->bits_per_word > 32)
return -EINVAL;
@@ -302,7 +302,6 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
struct spi_device *spi = m->spi;
struct spi_transfer *t = NULL;
int cs_active = 0;
- int par_override = 0;
int status = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
@@ -310,14 +309,9 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
status = -EINVAL;
break;
}
- if (par_override || t->speed_hz || t->bits_per_word) {
- par_override = 1;
- status = omap1_spi100k_setup_transfer(spi, t);
- if (status < 0)
- break;
- if (!t->speed_hz && !t->bits_per_word)
- par_override = 0;
- }
+ status = omap1_spi100k_setup_transfer(spi, t);
+ if (status < 0)
+ break;
if (!cs_active) {
omap1_spi100k_force_cs(spi100k, 1);
@@ -347,11 +341,7 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
}
}
- /* Restore defaults if they were overriden */
- if (par_override) {
- par_override = 0;
- status = omap1_spi100k_setup_transfer(spi, NULL);
- }
+ status = omap1_spi100k_setup_transfer(spi, NULL);
if (cs_active)
omap1_spi100k_force_cs(spi100k, 0);
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
index 55576db31549..ce8dbdbce312 100644
--- a/drivers/spi/spi-omap-uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -205,7 +205,7 @@ static void uwire_chipselect(struct spi_device *spi, int value)
static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
{
unsigned len = t->len;
- unsigned bits = t->bits_per_word ? : spi->bits_per_word;
+ unsigned bits = t->bits_per_word;
unsigned bytes;
u16 val, w;
int status = 0;
@@ -344,9 +344,10 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
/* assume it's already enabled */
rate = clk_get_rate(uwire->ck);
- hz = spi->max_speed_hz;
- if (t != NULL && t->speed_hz)
+ if (t != NULL)
hz = t->speed_hz;
+ else
+ hz = spi->max_speed_hz;
if (!hz) {
pr_debug("%s: zero speed?\n", dev_name(&spi->dev));
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 3d09e0b69b73..1f8903d356e5 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1217,6 +1217,33 @@ out:
return status;
}
+static int omap2_mcspi_prepare_message(struct spi_master *master,
+ struct spi_message *msg)
+{
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+ struct omap2_mcspi_regs *ctx = &mcspi->ctx;
+ struct omap2_mcspi_cs *cs;
+
+ /* Only a single channel can have the FORCE bit enabled
+ * in its chconf0 register.
+ * Scan all channels and disable them except the current one.
+ * A FORCE can remain from a last transfer having cs_change enabled
+ */
+ list_for_each_entry(cs, &ctx->cs, node) {
+ if (msg->spi->controller_state == cs)
+ continue;
+
+ if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE)) {
+ cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
+ writel_relaxed(cs->chconf0,
+ cs->base + OMAP2_MCSPI_CHCONF0);
+ readl_relaxed(cs->base + OMAP2_MCSPI_CHCONF0);
+ }
+ }
+
+ return 0;
+}
+
static int omap2_mcspi_transfer_one(struct spi_master *master,
struct spi_device *spi, struct spi_transfer *t)
{
@@ -1344,6 +1371,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->setup = omap2_mcspi_setup;
master->auto_runtime_pm = true;
+ master->prepare_message = omap2_mcspi_prepare_message;
master->transfer_one = omap2_mcspi_transfer_one;
master->set_cs = omap2_mcspi_set_cs;
master->cleanup = omap2_mcspi_cleanup;
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index 54fb984a3e17..dd3d0a218d8b 100644
--- a/drivers/spi/spi-ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -210,12 +210,12 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
if (in_8(&hw->regs->cdm) != cdm)
out_8(&hw->regs->cdm, cdm);
- spin_lock(&hw->bitbang.lock);
+ mutex_lock(&hw->bitbang.lock);
if (!hw->bitbang.busy) {
hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
/* Need to ndelay here? */
}
- spin_unlock(&hw->bitbang.lock);
+ mutex_unlock(&hw->bitbang.lock);
return 0;
}
diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
index 66a173939be8..bd8b369a343c 100644
--- a/drivers/spi/spi-pxa2xx-dma.c
+++ b/drivers/spi/spi-pxa2xx-dma.c
@@ -344,10 +344,6 @@ void pxa2xx_spi_dma_release(struct driver_data *drv_data)
}
}
-void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
-{
-}
-
int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word, u32 *burst_code,
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index a8ef38ebb9c9..b25dc71b0ea9 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/
+#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
@@ -61,9 +62,13 @@ MODULE_ALIAS("platform:pxa2xx-spi");
| QUARK_X1000_SSCR1_TFT \
| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
-#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
-#define SPI_CS_CONTROL_SW_MODE BIT(0)
-#define SPI_CS_CONTROL_CS_HIGH BIT(1)
+#define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
+#define LPSS_CS_CONTROL_SW_MODE BIT(0)
+#define LPSS_CS_CONTROL_CS_HIGH BIT(1)
+#define LPSS_CS_CONTROL_CS_SEL_SHIFT 8
+#define LPSS_CS_CONTROL_CS_SEL_MASK (3 << LPSS_CS_CONTROL_CS_SEL_SHIFT)
+#define LPSS_CAPS_CS_EN_SHIFT 9
+#define LPSS_CAPS_CS_EN_MASK (0xf << LPSS_CAPS_CS_EN_SHIFT)
struct lpss_config {
/* LPSS offset from drv_data->ioaddr */
@@ -72,6 +77,7 @@ struct lpss_config {
int reg_general;
int reg_ssp;
int reg_cs_ctrl;
+ int reg_capabilities;
/* FIFO thresholds */
u32 rx_threshold;
u32 tx_threshold_lo;
@@ -85,6 +91,7 @@ static const struct lpss_config lpss_platforms[] = {
.reg_general = 0x08,
.reg_ssp = 0x0c,
.reg_cs_ctrl = 0x18,
+ .reg_capabilities = -1,
.rx_threshold = 64,
.tx_threshold_lo = 160,
.tx_threshold_hi = 224,
@@ -94,6 +101,7 @@ static const struct lpss_config lpss_platforms[] = {
.reg_general = 0x08,
.reg_ssp = 0x0c,
.reg_cs_ctrl = 0x18,
+ .reg_capabilities = -1,
.rx_threshold = 64,
.tx_threshold_lo = 160,
.tx_threshold_hi = 224,
@@ -103,10 +111,21 @@ static const struct lpss_config lpss_platforms[] = {
.reg_general = -1,
.reg_ssp = 0x20,
.reg_cs_ctrl = 0x24,
+ .reg_capabilities = 0xfc,
.rx_threshold = 1,
.tx_threshold_lo = 32,
.tx_threshold_hi = 56,
},
+ { /* LPSS_BXT_SSP */
+ .offset = 0x200,
+ .reg_general = -1,
+ .reg_ssp = 0x20,
+ .reg_cs_ctrl = 0x24,
+ .reg_capabilities = 0xfc,
+ .rx_threshold = 1,
+ .tx_threshold_lo = 16,
+ .tx_threshold_hi = 48,
+ },
};
static inline const struct lpss_config
@@ -121,6 +140,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
case LPSS_LPT_SSP:
case LPSS_BYT_SSP:
case LPSS_SPT_SSP:
+ case LPSS_BXT_SSP:
return true;
default:
return false;
@@ -249,7 +269,9 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
drv_data->lpss_base = drv_data->ioaddr + config->offset;
/* Enable software chip select control */
- value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
+ value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
+ value &= ~(LPSS_CS_CONTROL_SW_MODE | LPSS_CS_CONTROL_CS_HIGH);
+ value |= LPSS_CS_CONTROL_SW_MODE | LPSS_CS_CONTROL_CS_HIGH;
__lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
/* Enable multiblock DMA transfers */
@@ -259,7 +281,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
if (config->reg_general >= 0) {
value = __lpss_ssp_read_priv(drv_data,
config->reg_general);
- value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
+ value |= LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE;
__lpss_ssp_write_priv(drv_data,
config->reg_general, value);
}
@@ -269,15 +291,34 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
{
const struct lpss_config *config;
- u32 value;
+ u32 value, cs;
config = lpss_get_config(drv_data);
value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
- if (enable)
- value &= ~SPI_CS_CONTROL_CS_HIGH;
- else
- value |= SPI_CS_CONTROL_CS_HIGH;
+ if (enable) {
+ cs = drv_data->cur_msg->spi->chip_select;
+ cs <<= LPSS_CS_CONTROL_CS_SEL_SHIFT;
+ if (cs != (value & LPSS_CS_CONTROL_CS_SEL_MASK)) {
+ /*
+ * When switching another chip select output active
+ * the output must be selected first and wait 2 ssp_clk
+ * cycles before changing state to active. Otherwise
+ * a short glitch will occur on the previous chip
+ * select since output select is latched but state
+ * control is not.
+ */
+ value &= ~LPSS_CS_CONTROL_CS_SEL_MASK;
+ value |= cs;
+ __lpss_ssp_write_priv(drv_data,
+ config->reg_cs_ctrl, value);
+ ndelay(1000000000 /
+ (drv_data->master->max_speed_hz / 2));
+ }
+ value &= ~LPSS_CS_CONTROL_CS_HIGH;
+ } else {
+ value |= LPSS_CS_CONTROL_CS_HIGH;
+ }
__lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
}
@@ -734,7 +775,7 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
mul = (1 << 24) >> 1;
/* Calculate initial quot */
- q1 = DIV_ROUND_CLOSEST(fref1, rate);
+ q1 = DIV_ROUND_UP(fref1, rate);
/* Scale q1 if it's too big */
if (q1 > 256) {
@@ -759,7 +800,7 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
/* Case 2 */
- q2 = DIV_ROUND_CLOSEST(fref2, rate);
+ q2 = DIV_ROUND_UP(fref2, rate);
r2 = abs(fref2 / q2 - rate);
/*
@@ -778,13 +819,13 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
mul = (1 << 24) * 2 / 5;
}
- /* Check case 3 only If the divisor is big enough */
+ /* Check case 3 only if the divisor is big enough */
if (fref / rate >= 80) {
u64 fssp;
u32 m;
/* Calculate initial quot */
- q1 = DIV_ROUND_CLOSEST(fref, rate);
+ q1 = DIV_ROUND_UP(fref, rate);
m = (1 << 24) / q1;
/* Get the remainder */
@@ -806,7 +847,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->max_clk_rate;
+ unsigned long ssp_clk = drv_data->master->max_speed_hz;
const struct ssp_device *ssp = drv_data->ssp;
rate = min_t(int, ssp_clk, rate);
@@ -818,8 +859,9 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
}
static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
- struct chip_data *chip, int rate)
+ int rate)
{
+ struct chip_data *chip = drv_data->cur_chip;
unsigned int clk_div;
switch (drv_data->ssp_type) {
@@ -922,52 +964,55 @@ static void pump_transfers(unsigned long data)
drv_data->read = drv_data->rx ? chip->read : null_reader;
/* Change speed and bit per word on a per transfer */
- cr0 = chip->cr0;
- if (transfer->speed_hz || transfer->bits_per_word) {
-
- bits = chip->bits_per_word;
- speed = chip->speed_hz;
-
- if (transfer->speed_hz)
- speed = transfer->speed_hz;
-
- if (transfer->bits_per_word)
- bits = transfer->bits_per_word;
-
- clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, speed);
-
- if (bits <= 8) {
- drv_data->n_bytes = 1;
- drv_data->read = drv_data->read != null_reader ?
- u8_reader : null_reader;
- drv_data->write = drv_data->write != null_writer ?
- u8_writer : null_writer;
- } else if (bits <= 16) {
- drv_data->n_bytes = 2;
- drv_data->read = drv_data->read != null_reader ?
- u16_reader : null_reader;
- drv_data->write = drv_data->write != null_writer ?
- u16_writer : null_writer;
- } else if (bits <= 32) {
- drv_data->n_bytes = 4;
- drv_data->read = drv_data->read != null_reader ?
- u32_reader : null_reader;
- drv_data->write = drv_data->write != null_writer ?
- u32_writer : null_writer;
- }
- /* if bits/word is changed in dma mode, then must check the
- * thresholds and burst also */
- if (chip->enable_dma) {
- if (pxa2xx_spi_set_dma_burst_and_threshold(chip,
- message->spi,
- bits, &dma_burst,
- &dma_thresh))
- dev_warn_ratelimited(&message->spi->dev,
- "pump_transfers: DMA burst size reduced to match bits_per_word\n");
- }
-
- cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
+ bits = transfer->bits_per_word;
+ speed = transfer->speed_hz;
+
+ clk_div = pxa2xx_ssp_get_clk_div(drv_data, speed);
+
+ if (bits <= 8) {
+ drv_data->n_bytes = 1;
+ drv_data->read = drv_data->read != null_reader ?
+ u8_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u8_writer : null_writer;
+ } else if (bits <= 16) {
+ drv_data->n_bytes = 2;
+ drv_data->read = drv_data->read != null_reader ?
+ u16_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u16_writer : null_writer;
+ } else if (bits <= 32) {
+ drv_data->n_bytes = 4;
+ drv_data->read = drv_data->read != null_reader ?
+ u32_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u32_writer : null_writer;
}
+ /*
+ * if bits/word is changed in dma mode, then must check the
+ * thresholds and burst also
+ */
+ if (chip->enable_dma) {
+ if (pxa2xx_spi_set_dma_burst_and_threshold(chip,
+ message->spi,
+ bits, &dma_burst,
+ &dma_thresh))
+ dev_warn_ratelimited(&message->spi->dev,
+ "pump_transfers: DMA burst size reduced to match bits_per_word\n");
+ }
+
+ /* NOTE: PXA25x_SSP _could_ use external clocking ... */
+ 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",
+ drv_data->master->max_speed_hz
+ / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)),
+ chip->enable_dma ? "DMA" : "PIO");
+ else
+ dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
+ drv_data->master->max_speed_hz / 2
+ / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)),
+ chip->enable_dma ? "DMA" : "PIO");
message->state = RUNNING_STATE;
@@ -1111,7 +1156,6 @@ static int setup(struct spi_device *spi)
struct chip_data *chip;
const struct lpss_config *config;
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned int clk_div;
uint tx_thres, tx_hi_thres, rx_thres;
switch (drv_data->ssp_type) {
@@ -1123,6 +1167,7 @@ static int setup(struct spi_device *spi)
case LPSS_LPT_SSP:
case LPSS_BYT_SSP:
case LPSS_SPT_SSP:
+ case LPSS_BXT_SSP:
config = lpss_get_config(drv_data);
tx_thres = config->tx_threshold_lo;
tx_hi_thres = config->tx_threshold_hi;
@@ -1203,11 +1248,6 @@ static int setup(struct spi_device *spi)
}
}
- clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, spi->max_speed_hz);
- chip->speed_hz = spi->max_speed_hz;
-
- chip->cr0 = pxa2xx_configure_sscr0(drv_data, clk_div,
- spi->bits_per_word);
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
chip->threshold = (QUARK_X1000_SSCR1_RxTresh(rx_thres)
@@ -1228,18 +1268,6 @@ static int setup(struct spi_device *spi)
if (spi->mode & SPI_LOOP)
chip->cr1 |= SSCR1_LBM;
- /* NOTE: PXA25x_SSP _could_ use external clocking ... */
- if (!pxa25x_ssp_comp(drv_data))
- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
- drv_data->max_clk_rate
- / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
- chip->enable_dma ? "DMA" : "PIO");
- else
- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
- drv_data->max_clk_rate / 2
- / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
- chip->enable_dma ? "DMA" : "PIO");
-
if (spi->bits_per_word <= 8) {
chip->n_bytes = 1;
chip->read = u8_reader;
@@ -1249,13 +1277,10 @@ static int setup(struct spi_device *spi)
chip->read = u16_reader;
chip->write = u16_writer;
} else if (spi->bits_per_word <= 32) {
- if (!is_quark_x1000_ssp(drv_data))
- chip->cr0 |= SSCR0_EDSS;
chip->n_bytes = 4;
chip->read = u32_reader;
chip->write = u32_writer;
}
- chip->bits_per_word = spi->bits_per_word;
spi_set_ctldata(spi, chip);
@@ -1279,6 +1304,7 @@ static void cleanup(struct spi_device *spi)
kfree(chip);
}
+#ifdef CONFIG_PCI
#ifdef CONFIG_ACPI
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
@@ -1292,6 +1318,23 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
+static int pxa2xx_spi_get_port_id(struct acpi_device *adev)
+{
+ unsigned int devid;
+ int port_id = -1;
+
+ if (adev && adev->pnp.unique_id &&
+ !kstrtouint(adev->pnp.unique_id, 0, &devid))
+ port_id = devid;
+ return port_id;
+}
+#else /* !CONFIG_ACPI */
+static int pxa2xx_spi_get_port_id(struct acpi_device *adev)
+{
+ return -1;
+}
+#endif
+
/*
* PCI IDs of compound devices that integrate both host controller and private
* integrated DMA engine. Please note these are not used in module
@@ -1304,6 +1347,14 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
+ /* BXT */
+ { PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP },
+ { PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP },
+ { PCI_VDEVICE(INTEL, 0x0ac6), LPSS_BXT_SSP },
+ /* APL */
+ { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
+ { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
+ { PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP },
{ },
};
@@ -1318,7 +1369,7 @@ static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
}
static struct pxa2xx_spi_master *
-pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
+pxa2xx_spi_init_pdata(struct platform_device *pdev)
{
struct pxa2xx_spi_master *pdata;
struct acpi_device *adev;
@@ -1326,18 +1377,18 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
struct resource *res;
const struct acpi_device_id *adev_id = NULL;
const struct pci_device_id *pcidev_id = NULL;
- int devid, type;
+ int type;
- if (!ACPI_HANDLE(&pdev->dev) ||
- acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
- return NULL;
+ adev = ACPI_COMPANION(&pdev->dev);
if (dev_is_pci(pdev->dev.parent))
pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match,
to_pci_dev(pdev->dev.parent));
- else
+ else if (adev)
adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
&pdev->dev);
+ else
+ return NULL;
if (adev_id)
type = (int)adev_id->driver_data;
@@ -1371,10 +1422,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
ssp->irq = platform_get_irq(pdev, 0);
ssp->type = type;
ssp->pdev = pdev;
-
- ssp->port_id = -1;
- if (adev->pnp.unique_id && !kstrtoint(adev->pnp.unique_id, 0, &devid))
- ssp->port_id = devid;
+ ssp->port_id = pxa2xx_spi_get_port_id(adev);
pdata->num_chipselect = 1;
pdata->enable_dma = true;
@@ -1382,9 +1430,9 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
return pdata;
}
-#else
+#else /* !CONFIG_PCI */
static inline struct pxa2xx_spi_master *
-pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
+pxa2xx_spi_init_pdata(struct platform_device *pdev)
{
return NULL;
}
@@ -1397,12 +1445,13 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
struct spi_master *master;
struct driver_data *drv_data;
struct ssp_device *ssp;
+ const struct lpss_config *config;
int status;
u32 tmp;
platform_info = dev_get_platdata(dev);
if (!platform_info) {
- platform_info = pxa2xx_spi_acpi_get_pdata(pdev);
+ platform_info = pxa2xx_spi_init_pdata(pdev);
if (!platform_info) {
dev_err(&pdev->dev, "missing platform data\n");
return -ENODEV;
@@ -1436,7 +1485,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
master->bus_num = ssp->port_id;
- master->num_chipselect = platform_info->num_chipselect;
master->dma_alignment = DMA_ALIGNMENT;
master->cleanup = cleanup;
master->setup = setup;
@@ -1489,7 +1537,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
/* Enable SOC clock */
clk_prepare_enable(ssp->clk);
- drv_data->max_clk_rate = clk_get_rate(ssp->clk);
+ master->max_speed_hz = clk_get_rate(ssp->clk);
/* Load default SSP configuration */
pxa2xx_spi_write(drv_data, SSCR0, 0);
@@ -1522,6 +1570,19 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
if (is_lpss_ssp(drv_data))
lpss_ssp_setup(drv_data);
+ if (is_lpss_ssp(drv_data)) {
+ lpss_ssp_setup(drv_data);
+ config = lpss_get_config(drv_data);
+ if (config->reg_capabilities >= 0) {
+ tmp = __lpss_ssp_read_priv(drv_data,
+ config->reg_capabilities);
+ tmp &= LPSS_CAPS_CS_EN_MASK;
+ tmp >>= LPSS_CAPS_CS_EN_SHIFT;
+ platform_info->num_chipselect = ffz(tmp);
+ }
+ }
+ master->num_chipselect = platform_info->num_chipselect;
+
tasklet_init(&drv_data->pump_transfers, pump_transfers,
(unsigned long)drv_data);
@@ -1614,8 +1675,6 @@ static int pxa2xx_spi_resume(struct device *dev)
struct ssp_device *ssp = drv_data->ssp;
int status = 0;
- pxa2xx_spi_dma_resume(drv_data);
-
/* Enable the SSP clock */
if (!pm_runtime_suspended(dev))
clk_prepare_enable(ssp->clk);
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 0a9b6390a817..58efa98313aa 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -46,9 +46,6 @@ struct driver_data {
u32 clear_sr;
u32 mask_sr;
- /* Maximun clock rate */
- unsigned long max_clk_rate;
-
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
@@ -86,10 +83,8 @@ struct driver_data {
};
struct chip_data {
- u32 cr0;
u32 cr1;
u32 dds_rate;
- u32 psp;
u32 timeout;
u8 n_bytes;
u32 dma_burst_size;
@@ -98,8 +93,6 @@ struct chip_data {
u16 lpss_rx_threshold;
u16 lpss_tx_threshold;
u8 enable_dma;
- u8 bits_per_word;
- u32 speed_hz;
union {
int gpio_cs;
unsigned int frm;
@@ -175,7 +168,6 @@ extern int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst);
extern void pxa2xx_spi_dma_start(struct driver_data *drv_data);
extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data);
extern void pxa2xx_spi_dma_release(struct driver_data *drv_data);
-extern void pxa2xx_spi_dma_resume(struct driver_data *drv_data);
extern int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word,
@@ -196,7 +188,6 @@ static inline int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
return 0;
}
static inline void pxa2xx_spi_dma_release(struct driver_data *drv_data) {}
-static inline void pxa2xx_spi_dma_resume(struct driver_data *drv_data) {}
static inline int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word,
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index f36bc320a807..4e7d1bfed7e6 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -198,12 +198,12 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
if (ret)
return ret;
- spin_lock(&hw->bitbang.lock);
+ mutex_lock(&hw->bitbang.lock);
if (!hw->bitbang.busy) {
hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
/* need to ndelay for 0.5 clocktick ? */
}
- spin_unlock(&hw->bitbang.lock);
+ mutex_unlock(&hw->bitbang.lock);
return 0;
}
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index cd1cfac0447f..8e86e7f6663a 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -32,6 +32,7 @@
#define MAX_SPI_PORTS 6
#define S3C64XX_SPI_QUIRK_POLL (1 << 0)
#define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1)
+#define AUTOSUSPEND_TIMEOUT 2000
/* Registers and bit-fields */
@@ -682,7 +683,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
/* Only BPW and Speed may change across transfers */
bpw = xfer->bits_per_word;
- speed = xfer->speed_hz ? : spi->max_speed_hz;
+ speed = xfer->speed_hz;
if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
sdd->cur_bpw = bpw;
@@ -859,13 +860,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
}
}
- pm_runtime_put(&sdd->pdev->dev);
+ pm_runtime_mark_last_busy(&sdd->pdev->dev);
+ pm_runtime_put_autosuspend(&sdd->pdev->dev);
if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
return 0;
setup_exit:
- pm_runtime_put(&sdd->pdev->dev);
+ pm_runtime_mark_last_busy(&sdd->pdev->dev);
+ pm_runtime_put_autosuspend(&sdd->pdev->dev);
/* setup() returns with device de-selected */
if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
@@ -1162,6 +1165,12 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
goto err2;
}
+ pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
/* Setup Deufult Mode */
s3c64xx_spi_hwinit(sdd, sdd->port_id);
@@ -1180,9 +1189,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
sdd->regs + S3C64XX_SPI_INT_EN);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
ret = devm_spi_register_master(&pdev->dev, master);
if (ret != 0) {
dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret);
@@ -1195,9 +1201,16 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1,
sdd->rx_dma.dmach, sdd->tx_dma.dmach);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
return 0;
err3:
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+
clk_disable_unprepare(sdd->src_clk);
err2:
clk_disable_unprepare(sdd->clk);
@@ -1212,7 +1225,7 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
@@ -1220,6 +1233,10 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
clk_disable_unprepare(sdd->clk);
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+
return 0;
}
@@ -1233,10 +1250,9 @@ static int s3c64xx_spi_suspend(struct device *dev)
if (ret)
return ret;
- if (!pm_runtime_suspended(dev)) {
- clk_disable_unprepare(sdd->clk);
- clk_disable_unprepare(sdd->src_clk);
- }
+ ret = pm_runtime_force_suspend(dev);
+ if (ret < 0)
+ return ret;
sdd->cur_speed = 0; /* Output Clock is stopped */
@@ -1248,14 +1264,14 @@ static int s3c64xx_spi_resume(struct device *dev)
struct spi_master *master = dev_get_drvdata(dev);
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+ int ret;
if (sci->cfg_gpio)
sci->cfg_gpio();
- if (!pm_runtime_suspended(dev)) {
- clk_prepare_enable(sdd->src_clk);
- clk_prepare_enable(sdd->clk);
- }
+ ret = pm_runtime_force_resume(dev);
+ if (ret < 0)
+ return ret;
s3c64xx_spi_hwinit(sdd, sdd->port_id);
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index aa6d284131e0..64318fcfacf2 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -39,8 +39,6 @@ struct ti_qspi_regs {
};
struct ti_qspi {
- struct completion transfer_complete;
-
/* list synchronization */
struct mutex list_lock;
@@ -62,10 +60,6 @@ struct ti_qspi {
#define QSPI_PID (0x0)
#define QSPI_SYSCONFIG (0x10)
-#define QSPI_INTR_STATUS_RAW_SET (0x20)
-#define QSPI_INTR_STATUS_ENABLED_CLEAR (0x24)
-#define QSPI_INTR_ENABLE_SET_REG (0x28)
-#define QSPI_INTR_ENABLE_CLEAR_REG (0x2c)
#define QSPI_SPI_CLOCK_CNTRL_REG (0x40)
#define QSPI_SPI_DC_REG (0x44)
#define QSPI_SPI_CMD_REG (0x48)
@@ -97,7 +91,6 @@ struct ti_qspi {
#define QSPI_RD_DUAL (3 << 16)
#define QSPI_RD_QUAD (7 << 16)
#define QSPI_INVAL (4 << 16)
-#define QSPI_WC_CMD_INT_EN (1 << 14)
#define QSPI_FLEN(n) ((n - 1) << 0)
#define QSPI_WLEN_MAX_BITS 128
#define QSPI_WLEN_MAX_BYTES 16
@@ -106,10 +99,6 @@ struct ti_qspi {
#define BUSY 0x01
#define WC 0x02
-/* INTERRUPT REGISTER */
-#define QSPI_WC_INT_EN (1 << 1)
-#define QSPI_WC_INT_DISABLE (1 << 1)
-
/* Device Control */
#define QSPI_DD(m, n) (m << (3 + n * 8))
#define QSPI_CKPHA(n) (1 << (2 + n * 8))
@@ -217,6 +206,24 @@ static inline u32 qspi_is_busy(struct ti_qspi *qspi)
return stat & BUSY;
}
+static inline int ti_qspi_poll_wc(struct ti_qspi *qspi)
+{
+ u32 stat;
+ unsigned long timeout = jiffies + QSPI_COMPLETION_TIMEOUT;
+
+ do {
+ stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG);
+ if (stat & WC)
+ return 0;
+ cpu_relax();
+ } while (time_after(timeout, jiffies));
+
+ stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG);
+ if (stat & WC)
+ return 0;
+ return -ETIMEDOUT;
+}
+
static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
{
int wlen, count, xfer_len;
@@ -275,8 +282,7 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
}
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
- if (!wait_for_completion_timeout(&qspi->transfer_complete,
- QSPI_COMPLETION_TIMEOUT)) {
+ if (ti_qspi_poll_wc(qspi)) {
dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT;
}
@@ -315,8 +321,7 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
return -EBUSY;
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
- if (!wait_for_completion_timeout(&qspi->transfer_complete,
- QSPI_COMPLETION_TIMEOUT)) {
+ if (ti_qspi_poll_wc(qspi)) {
dev_err(qspi->dev, "read timed out\n");
return -ETIMEDOUT;
}
@@ -388,9 +393,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
qspi->cmd = 0;
qspi->cmd |= QSPI_EN_CS(spi->chip_select);
qspi->cmd |= QSPI_FLEN(frame_length);
- qspi->cmd |= QSPI_WC_CMD_INT_EN;
- ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG);
ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG);
mutex_lock(&qspi->list_lock);
@@ -410,39 +413,13 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
mutex_unlock(&qspi->list_lock);
+ ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG);
m->status = status;
spi_finalize_current_message(master);
- ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG);
-
return status;
}
-static irqreturn_t ti_qspi_isr(int irq, void *dev_id)
-{
- struct ti_qspi *qspi = dev_id;
- u16 int_stat;
- u32 stat;
-
- irqreturn_t ret = IRQ_HANDLED;
-
- int_stat = ti_qspi_read(qspi, QSPI_INTR_STATUS_ENABLED_CLEAR);
- stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG);
-
- if (!int_stat) {
- dev_dbg(qspi->dev, "No IRQ triggered\n");
- ret = IRQ_NONE;
- goto out;
- }
-
- ti_qspi_write(qspi, QSPI_WC_INT_DISABLE,
- QSPI_INTR_STATUS_ENABLED_CLEAR);
- if (stat & WC)
- complete(&qspi->transfer_complete);
-out:
- return ret;
-}
-
static int ti_qspi_runtime_resume(struct device *dev)
{
struct ti_qspi *qspi;
@@ -551,22 +528,12 @@ static int ti_qspi_probe(struct platform_device *pdev)
}
}
- ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0,
- dev_name(&pdev->dev), qspi);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
- irq);
- goto free_master;
- }
-
qspi->fclk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(qspi->fclk)) {
ret = PTR_ERR(qspi->fclk);
dev_err(&pdev->dev, "could not get clk: %d\n", ret);
}
- init_completion(&qspi->transfer_complete);
-
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, QSPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_enable(&pdev->dev);
@@ -587,18 +554,7 @@ free_master:
static int ti_qspi_remove(struct platform_device *pdev)
{
- struct ti_qspi *qspi = platform_get_drvdata(pdev);
- int ret;
-
- ret = pm_runtime_get_sync(qspi->dev);
- if (ret < 0) {
- dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
- return ret;
- }
-
- ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
-
- pm_runtime_put(qspi->dev);
+ pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c
index daf5aa1c24c3..c6ae775289e5 100644
--- a/drivers/spi/spi-tle62x0.c
+++ b/drivers/spi/spi-tle62x0.c
@@ -307,7 +307,6 @@ static int tle62x0_remove(struct spi_device *spi)
static struct spi_driver tle62x0_driver = {
.driver = {
.name = "tle62x0",
- .owner = THIS_MODULE,
},
.probe = tle62x0_probe,
.remove = tle62x0_remove,
diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c
index 9190124b6d90..d69f8f8f3fa6 100644
--- a/drivers/spi/spi-txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -181,7 +181,7 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
u32 data;
unsigned int len = t->len;
unsigned int wsize;
- u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+ u32 speed_hz = t->speed_hz;
u8 bits_per_word = t->bits_per_word;
wsize = bits_per_word >> 3; /* in bytes */
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index a339c1e9997a..3009121173cd 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -270,6 +270,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
while (remaining_words) {
int n_words, tx_words, rx_words;
+ u32 sr;
n_words = min(remaining_words, xspi->buffer_size);
@@ -284,24 +285,33 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
if (use_irq) {
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
wait_for_completion(&xspi->done);
- } else
- while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) &
- XSPI_SR_TX_EMPTY_MASK))
- ;
-
- /* A transmit has just completed. Process received data and
- * check for more data to transmit. Always inhibit the
- * transmitter while the Isr refills the transmit register/FIFO,
- * or make sure it is stopped if we're done.
- */
- if (use_irq)
+ /* A transmit has just completed. Process received data
+ * and check for more data to transmit. Always inhibit
+ * the transmitter while the Isr refills the transmit
+ * register/FIFO, or make sure it is stopped if we're
+ * done.
+ */
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
- xspi->regs + XSPI_CR_OFFSET);
+ xspi->regs + XSPI_CR_OFFSET);
+ sr = XSPI_SR_TX_EMPTY_MASK;
+ } else
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
/* Read out all the data from the Rx FIFO */
rx_words = n_words;
- while (rx_words--)
- xilinx_spi_rx(xspi);
+ while (rx_words) {
+ if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) {
+ xilinx_spi_rx(xspi);
+ rx_words--;
+ continue;
+ }
+
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+ if (!(sr & XSPI_SR_RX_EMPTY_MASK)) {
+ xilinx_spi_rx(xspi);
+ rx_words--;
+ }
+ }
remaining_words -= n_words;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a5f53de813d3..e2415be209d5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -123,6 +123,28 @@ SPI_STATISTICS_SHOW(bytes, "%llu");
SPI_STATISTICS_SHOW(bytes_rx, "%llu");
SPI_STATISTICS_SHOW(bytes_tx, "%llu");
+#define SPI_STATISTICS_TRANSFER_BYTES_HISTO(index, number) \
+ SPI_STATISTICS_SHOW_NAME(transfer_bytes_histo##index, \
+ "transfer_bytes_histo_" number, \
+ transfer_bytes_histo[index], "%lu")
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(0, "0-1");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(1, "2-3");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(2, "4-7");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(3, "8-15");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(4, "16-31");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(5, "32-63");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(6, "64-127");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(7, "128-255");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(8, "256-511");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(9, "512-1023");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(10, "1024-2047");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(11, "2048-4095");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(12, "4096-8191");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(13, "8192-16383");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+");
+
static struct attribute *spi_dev_attrs[] = {
&dev_attr_modalias.attr,
NULL,
@@ -143,6 +165,23 @@ static struct attribute *spi_device_statistics_attrs[] = {
&dev_attr_spi_device_bytes.attr,
&dev_attr_spi_device_bytes_rx.attr,
&dev_attr_spi_device_bytes_tx.attr,
+ &dev_attr_spi_device_transfer_bytes_histo0.attr,
+ &dev_attr_spi_device_transfer_bytes_histo1.attr,
+ &dev_attr_spi_device_transfer_bytes_histo2.attr,
+ &dev_attr_spi_device_transfer_bytes_histo3.attr,
+ &dev_attr_spi_device_transfer_bytes_histo4.attr,
+ &dev_attr_spi_device_transfer_bytes_histo5.attr,
+ &dev_attr_spi_device_transfer_bytes_histo6.attr,
+ &dev_attr_spi_device_transfer_bytes_histo7.attr,
+ &dev_attr_spi_device_transfer_bytes_histo8.attr,
+ &dev_attr_spi_device_transfer_bytes_histo9.attr,
+ &dev_attr_spi_device_transfer_bytes_histo10.attr,
+ &dev_attr_spi_device_transfer_bytes_histo11.attr,
+ &dev_attr_spi_device_transfer_bytes_histo12.attr,
+ &dev_attr_spi_device_transfer_bytes_histo13.attr,
+ &dev_attr_spi_device_transfer_bytes_histo14.attr,
+ &dev_attr_spi_device_transfer_bytes_histo15.attr,
+ &dev_attr_spi_device_transfer_bytes_histo16.attr,
NULL,
};
@@ -168,6 +207,23 @@ static struct attribute *spi_master_statistics_attrs[] = {
&dev_attr_spi_master_bytes.attr,
&dev_attr_spi_master_bytes_rx.attr,
&dev_attr_spi_master_bytes_tx.attr,
+ &dev_attr_spi_master_transfer_bytes_histo0.attr,
+ &dev_attr_spi_master_transfer_bytes_histo1.attr,
+ &dev_attr_spi_master_transfer_bytes_histo2.attr,
+ &dev_attr_spi_master_transfer_bytes_histo3.attr,
+ &dev_attr_spi_master_transfer_bytes_histo4.attr,
+ &dev_attr_spi_master_transfer_bytes_histo5.attr,
+ &dev_attr_spi_master_transfer_bytes_histo6.attr,
+ &dev_attr_spi_master_transfer_bytes_histo7.attr,
+ &dev_attr_spi_master_transfer_bytes_histo8.attr,
+ &dev_attr_spi_master_transfer_bytes_histo9.attr,
+ &dev_attr_spi_master_transfer_bytes_histo10.attr,
+ &dev_attr_spi_master_transfer_bytes_histo11.attr,
+ &dev_attr_spi_master_transfer_bytes_histo12.attr,
+ &dev_attr_spi_master_transfer_bytes_histo13.attr,
+ &dev_attr_spi_master_transfer_bytes_histo14.attr,
+ &dev_attr_spi_master_transfer_bytes_histo15.attr,
+ &dev_attr_spi_master_transfer_bytes_histo16.attr,
NULL,
};
@@ -186,10 +242,15 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
struct spi_master *master)
{
unsigned long flags;
+ int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1;
+
+ if (l2len < 0)
+ l2len = 0;
spin_lock_irqsave(&stats->lock, flags);
stats->transfers++;
+ stats->transfer_bytes_histo[l2len]++;
stats->bytes += xfer->len;
if ((xfer->tx_buf) &&
@@ -270,15 +331,24 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
static int spi_drv_probe(struct device *dev)
{
const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+ struct spi_device *spi = to_spi_device(dev);
int ret;
ret = of_clk_set_defaults(dev->of_node, false);
if (ret)
return ret;
+ if (dev->of_node) {
+ spi->irq = of_irq_get(dev->of_node, 0);
+ if (spi->irq == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (spi->irq < 0)
+ spi->irq = 0;
+ }
+
ret = dev_pm_domain_attach(dev, true);
if (ret != -EPROBE_DEFER) {
- ret = sdrv->probe(to_spi_device(dev));
+ ret = sdrv->probe(spi);
if (ret)
dev_pm_domain_detach(dev, true);
}
@@ -305,12 +375,15 @@ static void spi_drv_shutdown(struct device *dev)
}
/**
- * spi_register_driver - register a SPI driver
+ * __spi_register_driver - register a SPI driver
* @sdrv: the driver to register
* Context: can sleep
+ *
+ * Return: zero on success, else a negative error code.
*/
-int spi_register_driver(struct spi_driver *sdrv)
+int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)
{
+ sdrv->driver.owner = owner;
sdrv->driver.bus = &spi_bus_type;
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe;
@@ -320,7 +393,7 @@ int spi_register_driver(struct spi_driver *sdrv)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
-EXPORT_SYMBOL_GPL(spi_register_driver);
+EXPORT_SYMBOL_GPL(__spi_register_driver);
/*-------------------------------------------------------------------------*/
@@ -359,7 +432,7 @@ static DEFINE_MUTEX(board_lock);
* needs to discard the spi_device without adding it, then it should
* call spi_dev_put() on it.
*
- * Returns a pointer to the new device, or NULL.
+ * Return: a pointer to the new device, or NULL.
*/
struct spi_device *spi_alloc_device(struct spi_master *master)
{
@@ -418,7 +491,7 @@ static int spi_dev_check(struct device *dev, void *data)
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
- * Returns 0 on success; negative errno on failure
+ * Return: 0 on success; negative errno on failure
*/
int spi_add_device(struct spi_device *spi)
{
@@ -491,7 +564,7 @@ EXPORT_SYMBOL_GPL(spi_add_device);
* this is exported so that for example a USB or parport based adapter
* driver could add devices (which it would learn about out-of-band).
*
- * Returns the new device, or NULL.
+ * Return: the new device, or NULL.
*/
struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
@@ -563,6 +636,8 @@ static void spi_match_master_to_boardinfo(struct spi_master *master,
*
* The board info passed can safely be __initdata ... but be careful of
* any embedded pointers (platform_data, etc), they're copied as-is.
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
@@ -597,7 +672,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
if (spi->mode & SPI_CS_HIGH)
enable = !enable;
- if (spi->cs_gpio >= 0)
+ if (gpio_is_valid(spi->cs_gpio))
gpio_set_value(spi->cs_gpio, !enable);
else if (spi->master->set_cs)
spi->master->set_cs(spi, !enable);
@@ -1140,6 +1215,8 @@ static int spi_init_queue(struct spi_master *master)
*
* If there are more messages in the queue, the next message is returned from
* this call.
+ *
+ * Return: the next message in the queue, else NULL if the queue is empty.
*/
struct spi_message *spi_get_next_queued_message(struct spi_master *master)
{
@@ -1303,6 +1380,8 @@ static int __spi_queued_transfer(struct spi_device *spi,
* spi_queued_transfer - transfer function for queued transfers
* @spi: spi device which is requesting transfer
* @msg: spi message which is to handled is queued to driver queue
+ *
+ * Return: zero on success, else a negative error code.
*/
static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
{
@@ -1433,9 +1512,6 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc)
}
spi->max_speed_hz = value;
- /* IRQ */
- spi->irq = irq_of_parse_and_map(nc, 0);
-
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;
@@ -1605,12 +1681,13 @@ static struct class spi_master_class = {
* only ones directly touching chip registers. It's how they allocate
* an spi_master structure, prior to calling spi_register_master().
*
- * This must be called from context that can sleep. It returns the SPI
- * master structure on success, else NULL.
+ * This must be called from context that can sleep.
*
* The caller is responsible for assigning the bus number and initializing
* the master's methods before calling spi_register_master(); and (after errors
* adding the device) calling spi_master_put() to prevent a memory leak.
+ *
+ * Return: the SPI master structure on success, else NULL.
*/
struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
{
@@ -1694,6 +1771,8 @@ static int of_spi_register_master(struct spi_master *master)
* success, else a negative error code (dropping the master's refcount).
* After a successful return, the caller is responsible for calling
* spi_unregister_master().
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_register_master(struct spi_master *master)
{
@@ -1787,6 +1866,8 @@ static void devm_spi_unregister(struct device *dev, void *res)
*
* Register a SPI device as with spi_register_master() which will
* automatically be unregister
+ *
+ * Return: zero on success, else a negative error code.
*/
int devm_spi_register_master(struct device *dev, struct spi_master *master)
{
@@ -1892,6 +1973,8 @@ static int __spi_master_match(struct device *dev, const void *data)
* arch init time. It returns a refcounted pointer to the relevant
* spi_master (which the caller must release), or NULL if there is
* no such master registered.
+ *
+ * Return: the SPI master structure on success, else NULL.
*/
struct spi_master *spi_busnum_to_master(u16 bus_num)
{
@@ -1945,11 +2028,13 @@ static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_w
* that the underlying controller or its driver does not support. For
* example, not all hardware supports wire transfers using nine bit words,
* LSB-first wire encoding, or active-high chipselects.
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_setup(struct spi_device *spi)
{
unsigned bad_bits, ugly_bits;
- int status = 0;
+ int status;
/* check mode to prevent that DUAL and QUAD set at the same time
*/
@@ -1986,17 +2071,18 @@ int spi_setup(struct spi_device *spi)
if (!spi->bits_per_word)
spi->bits_per_word = 8;
- if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word))
- return -EINVAL;
+ status = __spi_validate_bits_per_word(spi->master, spi->bits_per_word);
+ if (status)
+ return status;
if (!spi->max_speed_hz)
spi->max_speed_hz = spi->master->max_speed_hz;
- spi_set_cs(spi, false);
-
if (spi->master->setup)
status = spi->master->setup(spi);
+ spi_set_cs(spi, false);
+
dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n",
(int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
(spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
@@ -2162,6 +2248,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
* no other spi_message queued to that device will be processed.
* (This rule applies equally to all the synchronous transfer calls,
* which are wrappers around this core asynchronous primitive.)
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_async(struct spi_device *spi, struct spi_message *message)
{
@@ -2214,6 +2302,8 @@ EXPORT_SYMBOL_GPL(spi_async);
* no other spi_message queued to that device will be processed.
* (This rule applies equally to all the synchronous transfer calls,
* which are wrappers around this core asynchronous primitive.)
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_async_locked(struct spi_device *spi, struct spi_message *message)
{
@@ -2329,7 +2419,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
* Also, the caller is guaranteeing that the memory associated with the
* message will not be freed before this call returns.
*
- * It returns zero on success, else a negative error code.
+ * Return: zero on success, else a negative error code.
*/
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
@@ -2351,7 +2441,7 @@ EXPORT_SYMBOL_GPL(spi_sync);
* SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must
* be released by a spi_bus_unlock call when the exclusive access is over.
*
- * It returns zero on success, else a negative error code.
+ * Return: zero on success, else a negative error code.
*/
int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
{
@@ -2372,7 +2462,7 @@ EXPORT_SYMBOL_GPL(spi_sync_locked);
* exclusive access is over. Data transfer must be done by spi_sync_locked
* and spi_async_locked calls when the SPI bus lock is held.
*
- * It returns zero on success, else a negative error code.
+ * Return: always zero.
*/
int spi_bus_lock(struct spi_master *master)
{
@@ -2401,7 +2491,7 @@ EXPORT_SYMBOL_GPL(spi_bus_lock);
* This call releases an SPI bus lock previously obtained by an spi_bus_lock
* call.
*
- * It returns zero on success, else a negative error code.
+ * Return: always zero.
*/
int spi_bus_unlock(struct spi_master *master)
{
@@ -2436,6 +2526,8 @@ static u8 *buf;
* portable code should never use this for more than 32 bytes.
* Performance-sensitive or bulk transfer code should instead use
* spi_{async,sync}() calls with dma-safe buffers.
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_write_then_read(struct spi_device *spi,
const void *txbuf, unsigned n_tx,
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ef008e52f953..91a0fcd72423 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -788,7 +788,6 @@ static int spidev_remove(struct spi_device *spi)
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(spidev_dt_ids),
},
.probe = spidev_probe,
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 4a3cf9ba152f..be822f7a9ce6 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -168,11 +168,6 @@ struct pmic_arb_ver_ops {
u32 (*irq_clear)(u8 n);
};
-static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset)
-{
- return readl_relaxed(dev->rd_base + offset);
-}
-
static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
u32 offset, u32 val)
{
@@ -193,7 +188,7 @@ static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
*/
static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
{
- u32 data = pmic_arb_base_read(dev, reg);
+ u32 data = __raw_readl(dev->rd_base + reg);
memcpy(buf, &data, (bc & 3) + 1);
}
@@ -208,7 +203,7 @@ pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc)
{
u32 data = 0;
memcpy(&data, buf, (bc & 3) + 1);
- pmic_arb_base_write(dev, reg, data);
+ __raw_writel(data, dev->wr_base + reg);
}
static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
@@ -365,7 +360,7 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
opc = PMIC_ARB_OP_EXT_WRITE;
else if (opc >= 0x30 && opc <= 0x37)
opc = PMIC_ARB_OP_EXT_WRITEL;
- else if (opc >= 0x80 && opc <= 0xFF)
+ else if (opc >= 0x80)
opc = PMIC_ARB_OP_ZERO_WRITE;
else
return -EINVAL;
@@ -657,7 +652,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
intspec[0], intspec[1], intspec[2]);
- if (d->of_node != controller)
+ if (irq_domain_get_of_node(d) != controller)
return -EINVAL;
if (intsize != 4)
return -EINVAL;
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 11467e17bdd8..6b3da1bb0d63 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -560,12 +560,13 @@ EXPORT_SYMBOL_GPL(spmi_controller_remove);
* This API will register the client driver with the SPMI framework.
* It is typically called from the driver's module-init function.
*/
-int spmi_driver_register(struct spmi_driver *sdrv)
+int __spmi_driver_register(struct spmi_driver *sdrv, struct module *owner)
{
sdrv->driver.bus = &spmi_bus_type;
+ sdrv->driver.owner = owner;
return driver_register(&sdrv->driver);
}
-EXPORT_SYMBOL_GPL(spmi_driver_register);
+EXPORT_SYMBOL_GPL(__spmi_driver_register);
static void __exit spmi_exit(void)
{
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index f0d22cdb51cd..149214beeda9 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -80,6 +80,15 @@ config SSB_SDIOHOST
If unsure, say N
+config SSB_HOST_SOC
+ bool "Support for SSB bus on SoC"
+ depends on SSB
+ help
+ Host interface for a SSB directly mapped into memory. This is
+ for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
+
+ If unsure, say N
+
config SSB_SILENT
bool "No SSB kernel messages"
depends on SSB && EXPERT
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index b1ddc116d387..64a09681cee0 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
# host support
ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
-ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
+ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o
ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
+ssb-$(CONFIG_SSB_HOST_SOC) += host_soc.o
# built-in drivers
ssb-y += driver_chipcommon.o
diff --git a/drivers/ssb/bridge_pcmcia_80211.c b/drivers/ssb/bridge_pcmcia_80211.c
new file mode 100644
index 000000000000..d70568ea02d5
--- /dev/null
+++ b/drivers/ssb/bridge_pcmcia_80211.c
@@ -0,0 +1,128 @@
+/*
+ * Broadcom 43xx PCMCIA-SSB bridge module
+ *
+ * Copyright (c) 2007 Michael Buesch <m@bues.ch>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/ssb/ssb.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include "ssb_private.h"
+
+static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
+ PCMCIA_DEVICE_NULL,
+};
+
+MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
+
+static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
+{
+ struct ssb_bus *ssb;
+ int err = -ENOMEM;
+ int res = 0;
+
+ ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
+ if (!ssb)
+ goto out_error;
+
+ err = -ENODEV;
+
+ dev->config_flags |= CONF_ENABLE_IRQ;
+
+ dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
+ WIN_USE_WAIT;
+ dev->resource[2]->start = 0;
+ dev->resource[2]->end = SSB_CORE_SIZE;
+ res = pcmcia_request_window(dev, dev->resource[2], 250);
+ if (res != 0)
+ goto err_kfree_ssb;
+
+ res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
+ if (res != 0)
+ goto err_disable;
+
+ if (!dev->irq)
+ goto err_disable;
+
+ res = pcmcia_enable_device(dev);
+ if (res != 0)
+ goto err_disable;
+
+ err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
+ if (err)
+ goto err_disable;
+ dev->priv = ssb;
+
+ return 0;
+
+err_disable:
+ pcmcia_disable_device(dev);
+err_kfree_ssb:
+ kfree(ssb);
+out_error:
+ ssb_err("Initialization failed (%d, %d)\n", res, err);
+ return err;
+}
+
+static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
+{
+ struct ssb_bus *ssb = dev->priv;
+
+ ssb_bus_unregister(ssb);
+ pcmcia_disable_device(dev);
+ kfree(ssb);
+ dev->priv = NULL;
+}
+
+#ifdef CONFIG_PM
+static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
+{
+ struct ssb_bus *ssb = dev->priv;
+
+ return ssb_bus_suspend(ssb);
+}
+
+static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
+{
+ struct ssb_bus *ssb = dev->priv;
+
+ return ssb_bus_resume(ssb);
+}
+#else /* CONFIG_PM */
+# define ssb_host_pcmcia_suspend NULL
+# define ssb_host_pcmcia_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pcmcia_driver ssb_host_pcmcia_driver = {
+ .owner = THIS_MODULE,
+ .name = "ssb-pcmcia",
+ .id_table = ssb_host_pcmcia_tbl,
+ .probe = ssb_host_pcmcia_probe,
+ .remove = ssb_host_pcmcia_remove,
+ .suspend = ssb_host_pcmcia_suspend,
+ .resume = ssb_host_pcmcia_resume,
+};
+
+/*
+ * These are not module init/exit functions!
+ * The module_pcmcia_driver() helper cannot be used here.
+ */
+int ssb_host_pcmcia_init(void)
+{
+ return pcmcia_register_driver(&ssb_host_pcmcia_driver);
+}
+
+void ssb_host_pcmcia_exit(void)
+{
+ pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
+}
diff --git a/drivers/ssb/host_soc.c b/drivers/ssb/host_soc.c
new file mode 100644
index 000000000000..c809f255af34
--- /dev/null
+++ b/drivers/ssb/host_soc.c
@@ -0,0 +1,173 @@
+/*
+ * Sonics Silicon Backplane SoC host related functions.
+ * Subsystem core
+ *
+ * Copyright 2005, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/ssb/ssb.h>
+
+#include "ssb_private.h"
+
+static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ return readb(bus->mmio + offset);
+}
+
+static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ return readw(bus->mmio + offset);
+}
+
+static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ return readl(bus->mmio + offset);
+}
+
+#ifdef CONFIG_SSB_BLOCKIO
+static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ struct ssb_bus *bus = dev->bus;
+ void __iomem *addr;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ addr = bus->mmio + offset;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ u8 *buf = buffer;
+
+ while (count) {
+ *buf = __raw_readb(addr);
+ buf++;
+ count--;
+ }
+ break;
+ }
+ case sizeof(u16): {
+ __le16 *buf = buffer;
+
+ SSB_WARN_ON(count & 1);
+ while (count) {
+ *buf = (__force __le16)__raw_readw(addr);
+ buf++;
+ count -= 2;
+ }
+ break;
+ }
+ case sizeof(u32): {
+ __le32 *buf = buffer;
+
+ SSB_WARN_ON(count & 3);
+ while (count) {
+ *buf = (__force __le32)__raw_readl(addr);
+ buf++;
+ count -= 4;
+ }
+ break;
+ }
+ default:
+ SSB_WARN_ON(1);
+ }
+}
+#endif /* CONFIG_SSB_BLOCKIO */
+
+static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ writeb(value, bus->mmio + offset);
+}
+
+static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ writew(value, bus->mmio + offset);
+}
+
+static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
+{
+ struct ssb_bus *bus = dev->bus;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ writel(value, bus->mmio + offset);
+}
+
+#ifdef CONFIG_SSB_BLOCKIO
+static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ struct ssb_bus *bus = dev->bus;
+ void __iomem *addr;
+
+ offset += dev->core_index * SSB_CORE_SIZE;
+ addr = bus->mmio + offset;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ const u8 *buf = buffer;
+
+ while (count) {
+ __raw_writeb(*buf, addr);
+ buf++;
+ count--;
+ }
+ break;
+ }
+ case sizeof(u16): {
+ const __le16 *buf = buffer;
+
+ SSB_WARN_ON(count & 1);
+ while (count) {
+ __raw_writew((__force u16)(*buf), addr);
+ buf++;
+ count -= 2;
+ }
+ break;
+ }
+ case sizeof(u32): {
+ const __le32 *buf = buffer;
+
+ SSB_WARN_ON(count & 3);
+ while (count) {
+ __raw_writel((__force u32)(*buf), addr);
+ buf++;
+ count -= 4;
+ }
+ break;
+ }
+ default:
+ SSB_WARN_ON(1);
+ }
+}
+#endif /* CONFIG_SSB_BLOCKIO */
+
+/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
+const struct ssb_bus_ops ssb_host_soc_ops = {
+ .read8 = ssb_host_soc_read8,
+ .read16 = ssb_host_soc_read16,
+ .read32 = ssb_host_soc_read32,
+ .write8 = ssb_host_soc_write8,
+ .write16 = ssb_host_soc_write16,
+ .write32 = ssb_host_soc_write32,
+#ifdef CONFIG_SSB_BLOCKIO
+ .block_read = ssb_host_soc_block_read,
+ .block_write = ssb_host_soc_block_write,
+#endif
+};
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index a48a7439a206..5d1e9a0fc389 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -596,166 +596,6 @@ error:
return err;
}
-static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
-{
- struct ssb_bus *bus = dev->bus;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- return readb(bus->mmio + offset);
-}
-
-static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
-{
- struct ssb_bus *bus = dev->bus;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- return readw(bus->mmio + offset);
-}
-
-static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
-{
- struct ssb_bus *bus = dev->bus;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- return readl(bus->mmio + offset);
-}
-
-#ifdef CONFIG_SSB_BLOCKIO
-static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
- size_t count, u16 offset, u8 reg_width)
-{
- struct ssb_bus *bus = dev->bus;
- void __iomem *addr;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- addr = bus->mmio + offset;
-
- switch (reg_width) {
- case sizeof(u8): {
- u8 *buf = buffer;
-
- while (count) {
- *buf = __raw_readb(addr);
- buf++;
- count--;
- }
- break;
- }
- case sizeof(u16): {
- __le16 *buf = buffer;
-
- SSB_WARN_ON(count & 1);
- while (count) {
- *buf = (__force __le16)__raw_readw(addr);
- buf++;
- count -= 2;
- }
- break;
- }
- case sizeof(u32): {
- __le32 *buf = buffer;
-
- SSB_WARN_ON(count & 3);
- while (count) {
- *buf = (__force __le32)__raw_readl(addr);
- buf++;
- count -= 4;
- }
- break;
- }
- default:
- SSB_WARN_ON(1);
- }
-}
-#endif /* CONFIG_SSB_BLOCKIO */
-
-static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
-{
- struct ssb_bus *bus = dev->bus;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- writeb(value, bus->mmio + offset);
-}
-
-static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
-{
- struct ssb_bus *bus = dev->bus;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- writew(value, bus->mmio + offset);
-}
-
-static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
-{
- struct ssb_bus *bus = dev->bus;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- writel(value, bus->mmio + offset);
-}
-
-#ifdef CONFIG_SSB_BLOCKIO
-static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
- size_t count, u16 offset, u8 reg_width)
-{
- struct ssb_bus *bus = dev->bus;
- void __iomem *addr;
-
- offset += dev->core_index * SSB_CORE_SIZE;
- addr = bus->mmio + offset;
-
- switch (reg_width) {
- case sizeof(u8): {
- const u8 *buf = buffer;
-
- while (count) {
- __raw_writeb(*buf, addr);
- buf++;
- count--;
- }
- break;
- }
- case sizeof(u16): {
- const __le16 *buf = buffer;
-
- SSB_WARN_ON(count & 1);
- while (count) {
- __raw_writew((__force u16)(*buf), addr);
- buf++;
- count -= 2;
- }
- break;
- }
- case sizeof(u32): {
- const __le32 *buf = buffer;
-
- SSB_WARN_ON(count & 3);
- while (count) {
- __raw_writel((__force u32)(*buf), addr);
- buf++;
- count -= 4;
- }
- break;
- }
- default:
- SSB_WARN_ON(1);
- }
-}
-#endif /* CONFIG_SSB_BLOCKIO */
-
-/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
-static const struct ssb_bus_ops ssb_ssb_ops = {
- .read8 = ssb_ssb_read8,
- .read16 = ssb_ssb_read16,
- .read32 = ssb_ssb_read32,
- .write8 = ssb_ssb_write8,
- .write16 = ssb_ssb_write16,
- .write32 = ssb_ssb_write32,
-#ifdef CONFIG_SSB_BLOCKIO
- .block_read = ssb_ssb_block_read,
- .block_write = ssb_ssb_block_write,
-#endif
-};
-
static int ssb_fetch_invariants(struct ssb_bus *bus,
ssb_invariants_func_t get_invariants)
{
@@ -876,7 +716,6 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci)
return err;
}
-EXPORT_SYMBOL(ssb_bus_pcibus_register);
#endif /* CONFIG_SSB_PCIHOST */
#ifdef CONFIG_SSB_PCMCIAHOST
@@ -898,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
return err;
}
-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
#ifdef CONFIG_SSB_SDIOHOST
@@ -923,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
+#ifdef CONFIG_SSB_HOST_SOC
int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
ssb_invariants_func_t get_invariants)
{
int err;
bus->bustype = SSB_BUSTYPE_SSB;
- bus->ops = &ssb_ssb_ops;
+ bus->ops = &ssb_host_soc_ops;
err = ssb_bus_register(bus, get_invariants, baseaddr);
if (!err) {
@@ -939,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
return err;
}
+#endif
int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
{
@@ -1465,6 +1305,12 @@ static int __init ssb_modinit(void)
/* don't fail SSB init because of this */
err = 0;
}
+ err = ssb_host_pcmcia_init();
+ if (err) {
+ ssb_err("PCMCIA host initialization failed\n");
+ /* don't fail SSB init because of this */
+ err = 0;
+ }
err = ssb_gige_init();
if (err) {
ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
@@ -1482,6 +1328,7 @@ fs_initcall(ssb_modinit);
static void __exit ssb_modexit(void)
{
ssb_gige_exit();
+ ssb_host_pcmcia_exit();
b43_pci_ssb_bridge_exit();
bus_unregister(&ssb_bustype);
}
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index b413e0187087..f03422bbf087 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -147,8 +147,7 @@ error:
return err;
}
-int ssb_pcmcia_switch_core(struct ssb_bus *bus,
- struct ssb_device *dev)
+static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
{
int err;
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index b2d36f7736c5..2278e43614bd 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -200,7 +200,7 @@ out:
}
/* host must be already claimed */
-int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
+static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
{
u8 coreidx = dev->core_index;
u32 sbaddr;
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index eb507a50a564..15bfd5c7d2d7 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -85,8 +85,6 @@ static inline int ssb_pci_init(struct ssb_bus *bus)
/* pcmcia.c */
#ifdef CONFIG_SSB_PCMCIAHOST
-extern int ssb_pcmcia_switch_core(struct ssb_bus *bus,
- struct ssb_device *dev);
extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
u8 coreidx);
extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
@@ -96,13 +94,10 @@ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
extern void ssb_pcmcia_exit(struct ssb_bus *bus);
extern int ssb_pcmcia_init(struct ssb_bus *bus);
+extern int ssb_host_pcmcia_init(void);
+extern void ssb_host_pcmcia_exit(void);
extern const struct ssb_bus_ops ssb_pcmcia_ops;
#else /* CONFIG_SSB_PCMCIAHOST */
-static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus,
- struct ssb_device *dev)
-{
- return 0;
-}
static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
u8 coreidx)
{
@@ -124,6 +119,13 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
{
return 0;
}
+static inline int ssb_host_pcmcia_init(void)
+{
+ return 0;
+}
+static inline void ssb_host_pcmcia_exit(void)
+{
+}
#endif /* CONFIG_SSB_PCMCIAHOST */
/* sdio.c */
@@ -132,9 +134,7 @@ extern int ssb_sdio_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv);
extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
-extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
-extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
extern void ssb_sdio_exit(struct ssb_bus *bus);
extern int ssb_sdio_init(struct ssb_bus *bus);
@@ -144,19 +144,10 @@ static inline u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset)
{
return 0;
}
-static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
- struct ssb_device *dev)
-{
- return 0;
-}
static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
{
return 0;
}
-static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
-{
- return 0;
-}
static inline void ssb_sdio_exit(struct ssb_bus *bus)
{
}
@@ -166,6 +157,13 @@ static inline int ssb_sdio_init(struct ssb_bus *bus)
}
#endif /* CONFIG_SSB_SDIOHOST */
+/**************************************************
+ * host_soc.c
+ **************************************************/
+
+#ifdef CONFIG_SSB_HOST_SOC
+extern const struct ssb_bus_ops ssb_host_soc_ops;
+#endif
/* scan.c */
extern const char *ssb_core_name(u16 coreid);
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 39d950584c9f..5d3b86a33857 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -62,8 +62,6 @@ source "drivers/staging/xgifb/Kconfig"
source "drivers/staging/emxx_udc/Kconfig"
-source "drivers/staging/ft1000/Kconfig"
-
source "drivers/staging/speakup/Kconfig"
source "drivers/staging/ste_rmi4/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index e4f33d91872b..30918edef5e3 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_SM750) += sm750fb/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
-obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_MFD_NVEC) += nvec/
diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c
index a402fdaf54ca..9a978d21785e 100644
--- a/drivers/staging/android/ion/compat_ion.c
+++ b/drivers/staging/android/ion/compat_ion.c
@@ -137,7 +137,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
- if (data == NULL)
+ if (!data)
return -EFAULT;
err = compat_get_ion_allocation_data(data32, data);
@@ -156,7 +156,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
- if (data == NULL)
+ if (!data)
return -EFAULT;
err = compat_get_ion_handle_data(data32, data);
@@ -173,7 +173,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
- if (data == NULL)
+ if (!data)
return -EFAULT;
err = compat_get_ion_custom_data(data32, data);
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index e97a2c32ed78..ca15a87f6fd3 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -56,7 +56,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap,
vaddr = vmap(pages, npages, VM_MAP, pgprot);
vfree(pages);
- if (vaddr == NULL)
+ if (!vaddr)
return ERR_PTR(-ENOMEM);
return vaddr;
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index ada724aab3d5..d4c3e5512dd5 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -27,7 +27,7 @@
#include "ion_priv.h"
static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN |
- __GFP_NORETRY) & ~__GFP_WAIT;
+ __GFP_NORETRY) & ~__GFP_DIRECT_RECLAIM;
static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN);
static const unsigned int orders[] = {8, 4, 0};
static const int num_orders = ARRAY_SIZE(orders);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index e679d8432810..8b5a4a82d8b8 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -43,7 +43,7 @@
#include <linux/profile.h>
#include <linux/notifier.h>
-static uint32_t lowmem_debug_level = 1;
+static u32 lowmem_debug_level = 1;
static short lowmem_adj[6] = {
0,
1,
@@ -105,8 +105,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
}
lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n",
- sc->nr_to_scan, sc->gfp_mask, other_free,
- other_file, min_score_adj);
+ sc->nr_to_scan, sc->gfp_mask, other_free,
+ other_file, min_score_adj);
if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
lowmem_print(5, "lowmem_scan %lu, %x, return 0\n",
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
index f83e00c78051..e0c1acb2ba69 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -43,7 +43,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
return NULL;
obj = kzalloc(size, GFP_KERNEL);
- if (obj == NULL)
+ if (!obj)
return NULL;
kref_init(&obj->kref);
@@ -130,7 +130,7 @@ struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size)
return NULL;
pt = kzalloc(size, GFP_KERNEL);
- if (pt == NULL)
+ if (!pt)
return NULL;
spin_lock_irqsave(&obj->child_list_lock, flags);
@@ -155,7 +155,7 @@ static struct sync_fence *sync_fence_alloc(int size, const char *name)
struct sync_fence *fence;
fence = kzalloc(size, GFP_KERNEL);
- if (fence == NULL)
+ if (!fence)
return NULL;
fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops,
@@ -193,7 +193,7 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
struct sync_fence *fence;
fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name);
- if (fence == NULL)
+ if (!fence)
return NULL;
fence->num_fences = 1;
@@ -215,7 +215,7 @@ struct sync_fence *sync_fence_fdget(int fd)
{
struct file *file = fget(fd);
- if (file == NULL)
+ if (!file)
return NULL;
if (file->f_op != &sync_fence_fops)
@@ -262,7 +262,7 @@ struct sync_fence *sync_fence_merge(const char *name,
unsigned long size = offsetof(struct sync_fence, cbs[num_fences]);
fence = sync_fence_alloc(size, name);
- if (fence == NULL)
+ if (!fence)
return NULL;
atomic_set(&fence->status, num_fences);
@@ -313,7 +313,7 @@ struct sync_fence *sync_fence_merge(const char *name,
EXPORT_SYMBOL(sync_fence_merge);
int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
- int wake_flags, void *key)
+ int wake_flags, void *key)
{
struct sync_fence_waiter *wait;
@@ -353,7 +353,7 @@ int sync_fence_wait_async(struct sync_fence *fence,
EXPORT_SYMBOL(sync_fence_wait_async);
int sync_fence_cancel_async(struct sync_fence *fence,
- struct sync_fence_waiter *waiter)
+ struct sync_fence_waiter *waiter)
{
unsigned long flags;
int ret = 0;
@@ -583,14 +583,14 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
}
fence2 = sync_fence_fdget(data.fd2);
- if (fence2 == NULL) {
+ if (!fence2) {
err = -ENOENT;
goto err_put_fd;
}
data.name[sizeof(data.name) - 1] = '\0';
fence3 = sync_fence_merge(data.name, fence, fence2);
- if (fence3 == NULL) {
+ if (!fence3) {
err = -ENOMEM;
goto err_put_fence2;
}
@@ -666,7 +666,7 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence,
size = 4096;
data = kzalloc(size, GFP_KERNEL);
- if (data == NULL)
+ if (!data)
return -ENOMEM;
strlcpy(data->name, fence->name, sizeof(data->name));
diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c
index ce11726f1a6c..bcd9924d4631 100644
--- a/drivers/staging/android/timed_gpio.c
+++ b/drivers/staging/android/timed_gpio.c
@@ -25,7 +25,6 @@
#include "timed_output.h"
#include "timed_gpio.h"
-
struct timed_gpio_data {
struct timed_output_dev dev;
struct hrtimer timer;
@@ -76,8 +75,8 @@ static void gpio_enable(struct timed_output_dev *dev, int value)
value = data->max_timeout;
hrtimer_start(&data->timer,
- ktime_set(value / 1000, (value % 1000) * 1000000),
- HRTIMER_MODE_REL);
+ ktime_set(value / 1000, (value % 1000) * 1000000),
+ HRTIMER_MODE_REL);
}
spin_unlock_irqrestore(&data->lock, flags);
@@ -94,8 +93,8 @@ static int timed_gpio_probe(struct platform_device *pdev)
return -EBUSY;
gpio_data = devm_kzalloc(&pdev->dev,
- sizeof(struct timed_gpio_data) * pdata->num_gpios,
- GFP_KERNEL);
+ sizeof(*gpio_data) * pdata->num_gpios,
+ GFP_KERNEL);
if (!gpio_data)
return -ENOMEM;
@@ -104,7 +103,7 @@ static int timed_gpio_probe(struct platform_device *pdev)
gpio_dat = &gpio_data[i];
hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
+ HRTIMER_MODE_REL);
gpio_dat->timer.function = gpio_timer_func;
spin_lock_init(&gpio_dat->lock);
diff --git a/drivers/staging/board/board.c b/drivers/staging/board/board.c
index 3eb5eb8f069c..965afc79aadd 100644
--- a/drivers/staging/board/board.c
+++ b/drivers/staging/board/board.c
@@ -187,6 +187,9 @@ int __init board_staging_register_device(const struct board_staging_dev *dev)
for (i = 0; i < dev->nclocks; i++)
board_staging_register_clock(&dev->clocks[i]);
+ if (dev->domain)
+ board_staging_add_dev_domain(pdev, dev->domain);
+
error = platform_device_register(pdev);
if (error) {
pr_err("Failed to register device %s (%d)\n", pdev->name,
@@ -194,9 +197,6 @@ int __init board_staging_register_device(const struct board_staging_dev *dev)
return error;
}
- if (dev->domain)
- board_staging_add_dev_domain(pdev, dev->domain);
-
return error;
}
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index ac0f01007abd..945c85a10793 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -737,15 +737,23 @@ config COMEDI_ADL_PCI9118
called adl_pci9118.
config COMEDI_ADV_PCI1710
- tristate "Advantech PCI-171x, PCI-1720 and PCI-1731 support"
+ tristate "Advantech PCI-171x and PCI-1731 support"
select COMEDI_8254
---help---
Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
- PCI-1713, PCI-1720 and PCI-1731
+ PCI-1713 and PCI-1731
To compile this driver as a module, choose M here: the module will be
called adv_pci1710.
+config COMEDI_ADV_PCI1720
+ tristate "Advantech PCI-1720 support"
+ ---help---
+ Enable support for Advantech PCI-1720 Analog Output board.
+
+ To compile this driver as a module, choose M here: the module will be
+ called adv_pci1720.
+
config COMEDI_ADV_PCI1723
tristate "Advantech PCI-1723 support"
---help---
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index aae94815b593..b63dd2ef78b5 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -425,6 +425,24 @@ unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
}
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan);
+static unsigned int __comedi_nscans_left(struct comedi_subdevice *s,
+ unsigned int nscans)
+{
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ unsigned int scans_left = 0;
+
+ if (async->scans_done < cmd->stop_arg)
+ scans_left = cmd->stop_arg - async->scans_done;
+
+ if (nscans > scans_left)
+ nscans = scans_left;
+ }
+ return nscans;
+}
+
/**
* comedi_nscans_left() - Return the number of scans left in the command
* @s: COMEDI subdevice.
@@ -442,25 +460,12 @@ EXPORT_SYMBOL_GPL(comedi_bytes_per_scan);
unsigned int comedi_nscans_left(struct comedi_subdevice *s,
unsigned int nscans)
{
- struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
-
if (nscans == 0) {
unsigned int nbytes = comedi_buf_read_n_available(s);
nscans = nbytes / comedi_bytes_per_scan(s);
}
-
- if (cmd->stop_src == TRIG_COUNT) {
- unsigned int scans_left = 0;
-
- if (async->scans_done < cmd->stop_arg)
- scans_left = cmd->stop_arg - async->scans_done;
-
- if (nscans > scans_left)
- nscans = scans_left;
- }
- return nscans;
+ return __comedi_nscans_left(s, nscans);
}
EXPORT_SYMBOL_GPL(comedi_nscans_left);
@@ -479,9 +484,8 @@ unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
struct comedi_cmd *cmd = &async->cmd;
if (cmd->stop_src == TRIG_COUNT) {
- /* +1 to force comedi_nscans_left() to return the scans left */
- unsigned int nscans = (nsamples / cmd->scan_end_arg) + 1;
- unsigned int scans_left = comedi_nscans_left(s, nscans);
+ unsigned int nscans = nsamples / cmd->scan_end_arg;
+ unsigned int scans_left = __comedi_nscans_left(s, nscans);
unsigned int scan_pos =
comedi_bytes_to_samples(s, async->scan_progress);
unsigned long long samples_left = 0;
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index c3b8f2d7611b..94c179bea71e 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o
obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o
obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o
obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o
+obj-$(CONFIG_COMEDI_ADV_PCI1720) += adv_pci1720.o
obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o
obj-$(CONFIG_COMEDI_ADV_PCI1724) += adv_pci1724.o
obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index e5e0e1c4e50b..4437ea3abe8d 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -83,12 +83,6 @@
#include "amcc_s5933.h"
#include "comedi_8254.h"
-#define IORANGE_9118 64 /* I hope */
-#define PCI9118_CHANLEN 255 /*
- * len of chanlist, some source say 256,
- * but reality looks like 255 :-(
- */
-
/*
* PCI BAR2 Register map (dev->iobase)
*/
@@ -141,8 +135,6 @@
#define STOP_AI_EXT 0x02 /* stop measure on external trigger */
#define STOP_AI_INT 0x08 /* stop measure on internal trigger */
-#define PCI9118_HALF_FIFO_SZ (1024 / 2)
-
static const struct comedi_lrange pci9118_ai_range = {
8, {
BIP_RANGE(5),
@@ -169,11 +161,6 @@ static const struct comedi_lrange pci9118hg_ai_range = {
}
};
-#define PCI9118_BIPOLAR_RANGES 4 /*
- * used for test on mixture
- * of BIP/UNI ranges
- */
-
enum pci9118_boardid {
BOARD_PCI9118DG,
BOARD_PCI9118HG,
@@ -296,51 +283,44 @@ static void pci9118_ai_reset_fifo(struct comedi_device *dev)
outl(0, dev->iobase + PCI9118_FIFO_RESET_REG);
}
-static int check_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s, int n_chan,
- unsigned int *chanlist, int frontadd, int backadd)
+static int pci9118_ai_check_chanlist(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
struct pci9118_private *devpriv = dev->private;
- unsigned int i, differencial = 0, bipolar = 0;
+ unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
+ unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
+ int i;
- /* correct channel and range number check itself comedi/range.c */
- if (n_chan < 1) {
- dev_err(dev->class_dev, "range/channel list is empty!\n");
+ /* single channel scans are always ok */
+ if (cmd->chanlist_len == 1)
return 0;
- }
- if ((frontadd + n_chan + backadd) > s->len_chanlist) {
- dev_err(dev->class_dev,
- "range/channel list is too long for actual configuration!\n");
- return 0;
- }
- if (CR_AREF(chanlist[0]) == AREF_DIFF)
- differencial = 1; /* all input must be diff */
- if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
- bipolar = 1; /* all input must be bipolar */
- if (n_chan > 1)
- for (i = 1; i < n_chan; i++) { /* check S.E/diff */
- if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
- (differencial)) {
- dev_err(dev->class_dev,
- "Differential and single ended inputs can't be mixed!\n");
- return 0;
- }
- if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
- (bipolar)) {
- dev_err(dev->class_dev,
- "Bipolar and unipolar ranges can't be mixed!\n");
- return 0;
- }
- if (!devpriv->usemux && differencial &&
- (CR_CHAN(chanlist[i]) >= (s->n_chan / 2))) {
- dev_err(dev->class_dev,
- "AREF_DIFF is only available for the first 8 channels!\n");
- return 0;
- }
+ for (i = 1; i < cmd->chanlist_len; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+ unsigned int range = CR_RANGE(cmd->chanlist[i]);
+ unsigned int aref = CR_AREF(cmd->chanlist[i]);
+
+ if (aref != aref0) {
+ dev_err(dev->class_dev,
+ "Differential and single ended inputs can't be mixed!\n");
+ return -EINVAL;
+ }
+ if (comedi_range_is_bipolar(s, range) !=
+ comedi_range_is_bipolar(s, range0)) {
+ dev_err(dev->class_dev,
+ "Bipolar and unipolar ranges can't be mixed!\n");
+ return -EINVAL;
}
+ if (!devpriv->usemux && aref == AREF_DIFF &&
+ (chan >= (s->n_chan / 2))) {
+ dev_err(dev->class_dev,
+ "AREF_DIFF is only available for the first 8 channels!\n");
+ return -EINVAL;
+ }
+ }
- return 1;
+ return 0;
}
static void pci9118_set_chanlist(struct comedi_device *dev,
@@ -406,8 +386,8 @@ static void pci9118_set_chanlist(struct comedi_device *dev,
/* udelay(100); important delay, or first sample will be crippled */
}
-static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev,
- unsigned int next_buf)
+static void pci9118_ai_mode4_switch(struct comedi_device *dev,
+ unsigned int next_buf)
{
struct pci9118_private *devpriv = dev->private;
struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[next_buf];
@@ -421,9 +401,9 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev,
outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
}
-static unsigned int valid_samples_in_act_dma_buf(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int n_raw_samples)
+static unsigned int pci9118_ai_samples_ready(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int n_raw_samples)
{
struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
@@ -477,7 +457,7 @@ static unsigned int valid_samples_in_act_dma_buf(struct comedi_device *dev,
return n_samples;
}
-static void move_block_from_dma(struct comedi_device *dev,
+static void pci9118_ai_dma_xfer(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned short *dma_buffer,
unsigned int n_raw_samples)
@@ -623,10 +603,11 @@ static void pci9118_ai_munge(struct comedi_device *dev,
unsigned short *array = data;
unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
unsigned int i;
+ __be16 *barray = data;
for (i = 0; i < num_samples; i++) {
if (devpriv->usedma)
- array[i] = be16_to_cpu(array[i]);
+ array[i] = be16_to_cpu(barray[i]);
if (s->maxdata == 0xffff)
array[i] ^= 0x8000;
else
@@ -634,8 +615,8 @@ static void pci9118_ai_munge(struct comedi_device *dev,
}
}
-static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static void pci9118_ai_get_onesample(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
@@ -651,8 +632,8 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
}
}
-static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static void pci9118_ai_get_dma(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
@@ -662,21 +643,19 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
bool more_dma;
/* determine whether more DMA buffers to do after this one */
- n_valid = valid_samples_in_act_dma_buf(dev, s, n_all);
+ n_valid = pci9118_ai_samples_ready(dev, s, n_all);
more_dma = n_valid < comedi_nsamples_left(s, n_valid + 1);
/* switch DMA buffers and restart DMA if double buffering */
if (more_dma && devpriv->dma_doublebuf) {
devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
pci9118_amcc_setup_dma(dev, devpriv->dma_actbuf);
- if (devpriv->ai_do == 4) {
- interrupt_pci9118_ai_mode4_switch(dev,
- devpriv->dma_actbuf);
- }
+ if (devpriv->ai_do == 4)
+ pci9118_ai_mode4_switch(dev, devpriv->dma_actbuf);
}
if (n_all)
- move_block_from_dma(dev, s, dmabuf->virt, n_all);
+ pci9118_ai_dma_xfer(dev, s, dmabuf->virt, n_all);
if (!devpriv->ai_neverending) {
if (s->async->scans_done >= cmd->stop_arg)
@@ -690,7 +669,7 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
if (more_dma && !devpriv->dma_doublebuf) {
pci9118_amcc_setup_dma(dev, 0);
if (devpriv->ai_do == 4)
- interrupt_pci9118_ai_mode4_switch(dev, 0);
+ pci9118_ai_mode4_switch(dev, 0);
}
}
@@ -779,9 +758,9 @@ static irqreturn_t pci9118_interrupt(int irq, void *d)
}
if (devpriv->usedma)
- interrupt_pci9118_ai_dma(dev, s);
+ pci9118_ai_get_dma(dev, s);
else
- interrupt_pci9118_ai_onesample(dev, s);
+ pci9118_ai_get_onesample(dev, s);
interrupt_exit:
comedi_handle_events(dev, s);
@@ -823,10 +802,11 @@ static int pci9118_ai_setup_dma(struct comedi_device *dev,
struct comedi_cmd *cmd = &s->async->cmd;
struct pci9118_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
struct pci9118_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
- unsigned int dmalen0, dmalen1, i;
+ unsigned int dmalen0 = dmabuf0->size;
+ unsigned int dmalen1 = dmabuf1->size;
+ unsigned int scan_bytes = devpriv->ai_n_realscanlen *
+ comedi_bytes_per_sample(s);
- dmalen0 = dmabuf0->size;
- dmalen1 = dmabuf1->size;
/* isn't output buff smaller that our DMA buff? */
if (dmalen0 > s->async->prealloc_bufsz) {
/* align to 32bit down */
@@ -839,15 +819,15 @@ static int pci9118_ai_setup_dma(struct comedi_device *dev,
/* we want wake up every scan? */
if (devpriv->ai_flags & CMDF_WAKE_EOS) {
- if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
+ if (dmalen0 < scan_bytes) {
/* uff, too short DMA buffer, disable EOS support! */
devpriv->ai_flags &= (~CMDF_WAKE_EOS);
dev_info(dev->class_dev,
"WAR: DMA0 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
- dmalen0, devpriv->ai_n_realscanlen << 1);
+ dmalen0, scan_bytes);
} else {
/* short first DMA buffer to one scan */
- dmalen0 = devpriv->ai_n_realscanlen << 1;
+ dmalen0 = scan_bytes;
if (dmalen0 < 4) {
dev_info(dev->class_dev,
"ERR: DMA0 buf len bug? (%d<4)\n",
@@ -857,15 +837,15 @@ static int pci9118_ai_setup_dma(struct comedi_device *dev,
}
}
if (devpriv->ai_flags & CMDF_WAKE_EOS) {
- if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
+ if (dmalen1 < scan_bytes) {
/* uff, too short DMA buffer, disable EOS support! */
devpriv->ai_flags &= (~CMDF_WAKE_EOS);
dev_info(dev->class_dev,
"WAR: DMA1 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
- dmalen1, devpriv->ai_n_realscanlen << 1);
+ dmalen1, scan_bytes);
} else {
/* short second DMA buffer to one scan */
- dmalen1 = devpriv->ai_n_realscanlen << 1;
+ dmalen1 = scan_bytes;
if (dmalen1 < 4) {
dev_info(dev->class_dev,
"ERR: DMA1 buf len bug? (%d<4)\n",
@@ -877,45 +857,39 @@ static int pci9118_ai_setup_dma(struct comedi_device *dev,
/* transfer without CMDF_WAKE_EOS */
if (!(devpriv->ai_flags & CMDF_WAKE_EOS)) {
+ unsigned int tmp;
+
/* if it's possible then align DMA buffers to length of scan */
- i = dmalen0;
- dmalen0 =
- (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
- (devpriv->ai_n_realscanlen << 1);
+ tmp = dmalen0;
+ dmalen0 = (dmalen0 / scan_bytes) * scan_bytes;
dmalen0 &= ~3L;
if (!dmalen0)
- dmalen0 = i; /* uff. very long scan? */
- i = dmalen1;
- dmalen1 =
- (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
- (devpriv->ai_n_realscanlen << 1);
+ dmalen0 = tmp; /* uff. very long scan? */
+ tmp = dmalen1;
+ dmalen1 = (dmalen1 / scan_bytes) * scan_bytes;
dmalen1 &= ~3L;
if (!dmalen1)
- dmalen1 = i; /* uff. very long scan? */
+ dmalen1 = tmp; /* uff. very long scan? */
/*
* if measure isn't neverending then test, if it fits whole
* into one or two DMA buffers
*/
if (!devpriv->ai_neverending) {
+ unsigned long long scanlen;
+
+ scanlen = (unsigned long long)scan_bytes *
+ cmd->stop_arg;
+
/* fits whole measure into one DMA buffer? */
- if (dmalen0 >
- ((devpriv->ai_n_realscanlen << 1) *
- cmd->stop_arg)) {
- dmalen0 =
- (devpriv->ai_n_realscanlen << 1) *
- cmd->stop_arg;
+ if (dmalen0 > scanlen) {
+ dmalen0 = scanlen;
dmalen0 &= ~3L;
- } else { /*
- * fits whole measure into
- * two DMA buffer?
- */
- if (dmalen1 >
- ((devpriv->ai_n_realscanlen << 1) *
- cmd->stop_arg - dmalen0))
- dmalen1 =
- (devpriv->ai_n_realscanlen << 1) *
- cmd->stop_arg - dmalen0;
- dmalen1 &= ~3L;
+ } else {
+ /* fits whole measure into two DMA buffer? */
+ if (dmalen1 > (scanlen - dmalen0)) {
+ dmalen1 = scanlen - dmalen0;
+ dmalen1 &= ~3L;
+ }
}
}
}
@@ -945,6 +919,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
struct comedi_8254 *pacer = dev->pacer;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int addchans = 0;
+ unsigned int scanlen;
devpriv->ai12_startstop = 0;
devpriv->ai_flags = cmd->flags;
@@ -1030,19 +1005,20 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
}
/* well, we now know what must be all added */
- devpriv->ai_n_realscanlen = /*
- * what we must take from card in real
- * to have cmd->scan_end_arg on output?
- */
- (devpriv->ai_add_front + cmd->chanlist_len +
- devpriv->ai_add_back) * (cmd->scan_end_arg /
- cmd->chanlist_len);
-
- /* check and setup channel list */
- if (!check_channel_list(dev, s, cmd->chanlist_len,
- cmd->chanlist, devpriv->ai_add_front,
- devpriv->ai_add_back))
+ scanlen = devpriv->ai_add_front + cmd->chanlist_len +
+ devpriv->ai_add_back;
+ /*
+ * what we must take from card in real to have cmd->scan_end_arg
+ * on output?
+ */
+ devpriv->ai_n_realscanlen = scanlen *
+ (cmd->scan_end_arg / cmd->chanlist_len);
+
+ if (scanlen > s->len_chanlist) {
+ dev_err(dev->class_dev,
+ "range/channel list is too long for actual configuration!\n");
return -EINVAL;
+ }
/*
* Configure analog input and load the chanlist.
@@ -1205,9 +1181,6 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
err |= -EINVAL;
- if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
- err |= -EINVAL;
-
if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
(!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
err |= -EINVAL;
@@ -1315,10 +1288,13 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
if (err)
return 4;
+ /* Step 5: check channel list if it exists */
+
if (cmd->chanlist)
- if (!check_channel_list(dev, s, cmd->chanlist_len,
- cmd->chanlist, 0, 0))
- return 5; /* incorrect channels list */
+ err |= pci9118_ai_check_chanlist(dev, s, cmd);
+
+ if (err)
+ return 5;
return 0;
}
@@ -1608,7 +1584,7 @@ static int pci9118_common_attach(struct comedi_device *dev,
if (dev->irq) {
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
- s->len_chanlist = PCI9118_CHANLEN;
+ s->len_chanlist = 255;
s->do_cmdtest = pci9118_ai_cmdtest;
s->do_cmd = pci9118_ai_cmd;
s->cancel = pci9118_ai_cancel;
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 399c511cfe0a..45d7f42312ec 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -11,8 +11,9 @@
* Driver: adv_pci1710
* Description: Comedi driver for Advantech PCI-1710 series boards
* Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG, PCI-1711,
- * PCI-1713, PCI-1720, PCI-1731
+ * PCI-1713, PCI-1731
* Author: Michal Dobes <dobes@tesnet.cz>
+ * Updated: Fri, 29 Oct 2015 17:19:35 -0700
* Status: works
*
* Configuration options: not applicable, uses PCI auto config
@@ -62,16 +63,6 @@
#define PCI171X_DO_REG 0x10 /* W: digital outputs */
#define PCI171X_TIMER_BASE 0x18 /* R/W: 8254 timer */
-/*
- * PCI-1720 only has analog outputs and has a different
- * register map (dev->iobase)
- */
-#define PCI1720_DA_REG(x) (0x00 + ((x) * 2)) /* W: D/A registers */
-#define PCI1720_RANGE_REG 0x08 /* R/W: D/A range register */
-#define PCI1720_SYNC_REG 0x09 /* W: D/A synchronized output */
-#define PCI1720_SYNC_CTRL_REG 0x0f /* R/W: D/A synchronized control */
-#define PCI1720_SYNC_CTRL_SC0 BIT(0) /* set synchronous output mode */
-
static const struct comedi_lrange range_pci1710_3 = {
9, {
BIP_RANGE(5),
@@ -122,15 +113,6 @@ static const struct comedi_lrange range_pci17x1 = {
static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };
-static const struct comedi_lrange pci1720_ao_range = {
- 4, {
- UNI_RANGE(5),
- UNI_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(10)
- }
-};
-
static const struct comedi_lrange pci171x_ao_range = {
2, {
UNI_RANGE(5),
@@ -143,7 +125,6 @@ enum pci1710_boardid {
BOARD_PCI1710HG,
BOARD_PCI1711,
BOARD_PCI1713,
- BOARD_PCI1720,
BOARD_PCI1731,
};
@@ -153,7 +134,6 @@ struct boardtype {
const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
const char *rangecode_ai; /* range codes for programming */
unsigned int is_pci1713:1;
- unsigned int is_pci1720:1;
unsigned int has_irq:1;
unsigned int has_large_fifo:1; /* 4K or 1K FIFO */
unsigned int has_diff_ai:1;
@@ -207,11 +187,6 @@ static const struct boardtype boardtypes[] = {
.has_large_fifo = 1,
.has_diff_ai = 1,
},
- [BOARD_PCI1720] = {
- .name = "pci1720",
- .is_pci1720 = 1,
- .has_ao = 1,
- },
[BOARD_PCI1731] = {
.name = "pci1731",
.n_aichan = 16,
@@ -465,36 +440,6 @@ static int pci171x_do_insn_bits(struct comedi_device *dev,
return insn->n;
}
-static int pci1720_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct pci1710_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned int range = CR_RANGE(insn->chanspec);
- unsigned int val;
- int i;
-
- val = devpriv->da_ranges & (~(0x03 << (chan << 1)));
- val |= (range << (chan << 1));
- if (val != devpriv->da_ranges) {
- outb(val, dev->iobase + PCI1720_RANGE_REG);
- devpriv->da_ranges = val;
- }
-
- val = s->readback[chan];
- for (i = 0; i < insn->n; i++) {
- val = data[i];
- outw(val, dev->iobase + PCI1720_DA_REG(chan));
- outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */
- }
-
- s->readback[chan] = val;
-
- return insn->n;
-}
-
static int pci171x_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -790,7 +735,7 @@ static int pci171x_insn_counter_config(struct comedi_device *dev,
return insn->n;
}
-static int pci171x_reset(struct comedi_device *dev)
+static int pci1710_reset(struct comedi_device *dev)
{
const struct boardtype *board = dev->board_ptr;
struct pci1710_private *devpriv = dev->private;
@@ -815,33 +760,6 @@ static int pci171x_reset(struct comedi_device *dev)
return 0;
}
-static int pci1720_reset(struct comedi_device *dev)
-{
- struct pci1710_private *devpriv = dev->private;
- /* set synchronous output mode */
- outb(PCI1720_SYNC_CTRL_SC0, dev->iobase + PCI1720_SYNC_CTRL_REG);
- devpriv->da_ranges = 0xAA;
- /* set all ranges to +/-5V and outputs to 0V */
- outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE_REG);
- outw(0x0800, dev->iobase + PCI1720_DA_REG(0));
- outw(0x0800, dev->iobase + PCI1720_DA_REG(1));
- outw(0x0800, dev->iobase + PCI1720_DA_REG(2));
- outw(0x0800, dev->iobase + PCI1720_DA_REG(3));
- outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */
-
- return 0;
-}
-
-static int pci1710_reset(struct comedi_device *dev)
-{
- const struct boardtype *board = dev->board_ptr;
-
- if (board->is_pci1720)
- return pci1720_reset(dev);
-
- return pci171x_reset(dev);
-}
-
static int pci1710_auto_attach(struct comedi_device *dev,
unsigned long context)
{
@@ -922,29 +840,15 @@ static int pci1710_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 2;
s->maxdata = 0x0fff;
- if (board->is_pci1720) {
- s->n_chan = 4;
- s->range_table = &pci1720_ao_range;
- s->insn_write = pci1720_ao_insn_write;
- } else {
- s->n_chan = 2;
- s->range_table = &pci171x_ao_range;
- s->insn_write = pci171x_ao_insn_write;
- }
+ s->range_table = &pci171x_ao_range;
+ s->insn_write = pci171x_ao_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
- /* initialize the readback values to match the board reset */
- if (board->is_pci1720) {
- int i;
-
- for (i = 0; i < s->n_chan; i++)
- s->readback[i] = 0x0800;
- }
-
subdev++;
}
@@ -1063,7 +967,6 @@ static const struct pci_device_id adv_pci1710_pci_table[] = {
},
{ PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 },
{ PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 },
- { PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 },
{ PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 },
{ 0 }
};
diff --git a/drivers/staging/comedi/drivers/adv_pci1720.c b/drivers/staging/comedi/drivers/adv_pci1720.c
new file mode 100644
index 000000000000..4830a1c93d15
--- /dev/null
+++ b/drivers/staging/comedi/drivers/adv_pci1720.c
@@ -0,0 +1,195 @@
+/*
+ * COMEDI driver for Advantech PCI-1720U
+ * Copyright (c) 2015 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Separated from the adv_pci1710 driver written by:
+ * Michal Dobes <dobes@tesnet.cz>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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.
+ */
+
+/*
+ * Driver: adv_pci1720
+ * Description: 4-channel Isolated D/A Output board
+ * Devices: [Advantech] PCI-7120U (adv_pci1720)
+ * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
+ * Updated: Fri, 29 Oct 2015 17:19:35 -0700
+ * Status: untested
+ *
+ * Configuration options: not applicable, uses PCI auto config
+ *
+ * The PCI-1720 has 4 isolated 12-bit analog output channels with multiple
+ * output ranges. It also has a BoardID switch to allow differentiating
+ * multiple boards in the system.
+ *
+ * The analog outputs can operate in two modes, immediate and synchronized.
+ * This driver currently does not support the synchronized output mode.
+ *
+ * Jumpers JP1 to JP4 are used to set the current sink ranges for each
+ * analog output channel. In order to use the current sink ranges, the
+ * unipolar 5V range must be used. The voltage output and sink output for
+ * each channel is available on the connector as separate pins.
+ *
+ * Jumper JP5 controls the "hot" reset state of the analog outputs.
+ * Depending on its setting, the analog outputs will either keep the
+ * last settings and output values or reset to the default state after
+ * a "hot" reset. The default state for all channels is uniploar 5V range
+ * and all the output values are 0V. To allow this feature to work, the
+ * analog outputs are not "reset" when the driver attaches.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include "../comedi_pci.h"
+
+/*
+ * PCI BAR2 Register map (dev->iobase)
+ */
+#define PCI1720_AO_LSB_REG(x) (0x00 + ((x) * 2))
+#define PCI1720_AO_MSB_REG(x) (0x01 + ((x) * 2))
+#define PCI1720_AO_RANGE_REG 0x08
+#define PCI1720_AO_RANGE(c, r) (((r) & 0x3) << ((c) * 2))
+#define PCI1720_AO_RANGE_MASK(c) PCI1720_AO_RANGE((c), 0x3)
+#define PCI1720_SYNC_REG 0x09
+#define PCI1720_SYNC_CTRL_REG 0x0f
+#define PCI1720_SYNC_CTRL_SC0 BIT(0)
+#define PCI1720_BOARDID_REG 0x14
+
+static const struct comedi_lrange pci1720_ao_range = {
+ 4, {
+ UNI_RANGE(5),
+ UNI_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(10)
+ }
+};
+
+static int pci1720_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val;
+ int i;
+
+ /* set the channel range and polarity */
+ val = inb(dev->iobase + PCI1720_AO_RANGE_REG);
+ val &= ~PCI1720_AO_RANGE_MASK(chan);
+ val |= PCI1720_AO_RANGE(chan, range);
+ outb(val, dev->iobase + PCI1720_AO_RANGE_REG);
+
+ val = s->readback[chan];
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+
+ outb(val & 0xff, dev->iobase + PCI1720_AO_LSB_REG(chan));
+ outb((val >> 8) & 0xff, dev->iobase + PCI1720_AO_MSB_REG(chan));
+
+ /* conversion time is 2us (500 kHz throughput) */
+ usleep_range(2, 100);
+ }
+
+ s->readback[chan] = val;
+
+ return insn->n;
+}
+
+static int pci1720_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = inb(dev->iobase + PCI1720_BOARDID_REG);
+
+ return insn->n;
+}
+
+static int pci1720_auto_attach(struct comedi_device *dev,
+ unsigned long context)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct comedi_subdevice *s;
+ int ret;
+
+ ret = comedi_pci_enable(dev);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 2);
+
+ ret = comedi_alloc_subdevices(dev, 2);
+ if (ret)
+ return ret;
+
+ /* Analog Output subdevice */
+ s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0x0fff;
+ s->range_table = &pci1720_ao_range;
+ s->insn_write = pci1720_ao_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ /* Digital Input subdevice (BoardID SW1) */
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pci1720_di_insn_bits;
+
+ /* disable synchronized output, channels update when written */
+ outb(0, dev->iobase + PCI1720_SYNC_CTRL_REG);
+
+ return 0;
+}
+
+static struct comedi_driver adv_pci1720_driver = {
+ .driver_name = "adv_pci1720",
+ .module = THIS_MODULE,
+ .auto_attach = pci1720_auto_attach,
+ .detach = comedi_pci_detach,
+};
+
+static int adv_pci1720_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ return comedi_pci_auto_config(dev, &adv_pci1720_driver,
+ id->driver_data);
+}
+
+static const struct pci_device_id adv_pci1720_pci_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, adv_pci1720_pci_table);
+
+static struct pci_driver adv_pci1720_pci_driver = {
+ .name = "adv_pci1720",
+ .id_table = adv_pci1720_pci_table,
+ .probe = adv_pci1720_pci_probe,
+ .remove = comedi_pci_auto_unconfig,
+};
+module_comedi_pci_driver(adv_pci1720_driver, adv_pci1720_pci_driver);
+
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_DESCRIPTION("Comedi driver for Advantech PCI-1720 Analog Output board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 4aa2742641c0..3cd008acb657 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -97,6 +97,11 @@
#define PCIDAS_CTRL_LADFUL BIT(13) /* fifo overflow / clear */
#define PCIDAS_CTRL_DAEMI BIT(14) /* dac fifo empty int status / clear */
+#define PCIDAS_CTRL_AI_INT (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI | \
+ PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \
+ PCIDAS_CTRL_LADFUL)
+#define PCIDAS_CTRL_AO_INT (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI)
+
#define PCIDAS_AI_REG 0x02 /* ADC CHANNEL MUX AND CONTROL reg */
#define PCIDAS_AI_FIRST(x) ((x) & 0xf)
#define PCIDAS_AI_LAST(x) (((x) & 0xf) << 4)
@@ -308,16 +313,9 @@ struct cb_pcidas_private {
/* fifo buffers */
unsigned short ai_buffer[AI_BUFFER_SIZE];
unsigned short ao_buffer[AO_BUFFER_SIZE];
- unsigned int calibration_source;
+ unsigned int calib_src;
};
-static inline unsigned int cal_enable_bits(struct comedi_device *dev)
-{
- struct cb_pcidas_private *devpriv = dev->private;
-
- return PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calibration_source);
-}
-
static int cb_pcidas_ai_eoc(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -347,7 +345,7 @@ static int cb_pcidas_ai_insn_read(struct comedi_device *dev,
/* enable calibration input if appropriate */
if (insn->chanspec & CR_ALT_SOURCE) {
- outw(cal_enable_bits(dev),
+ outw(PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src),
devpriv->pcibar1 + PCIDAS_CALIB_REG);
chan = 0;
} else {
@@ -402,7 +400,7 @@ static int cb_pcidas_ai_insn_config(struct comedi_device *dev,
source);
return -EINVAL;
}
- devpriv->calibration_source = source;
+ devpriv->calib_src = source;
break;
default:
return -EINVAL;
@@ -419,7 +417,9 @@ static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device *dev,
struct cb_pcidas_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val = s->readback[chan];
unsigned long flags;
+ int i;
/* set channel and range */
spin_lock_irqsave(&dev->spinlock, flags);
@@ -429,11 +429,12 @@ static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device *dev,
outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* remember value for readback */
- s->readback[chan] = data[0];
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+ outw(val, devpriv->pcibar4 + PCIDAS_AO_DATA_REG(chan));
+ }
- /* send data */
- outw(data[0], devpriv->pcibar4 + PCIDAS_AO_DATA_REG(chan));
+ s->readback[chan] = val;
return insn->n;
}
@@ -447,7 +448,9 @@ static int cb_pcidas_ao_fifo_insn_write(struct comedi_device *dev,
struct cb_pcidas_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val = s->readback[chan];
unsigned long flags;
+ int i;
/* clear dac fifo */
outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
@@ -461,11 +464,12 @@ static int cb_pcidas_ao_fifo_insn_write(struct comedi_device *dev,
outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* remember value for readback */
- s->readback[chan] = data[0];
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+ outw(val, devpriv->pcibar4 + PCIDAS_AO_FIFO_REG);
+ }
- /* send data */
- outw(data[0], devpriv->pcibar4 + PCIDAS_AO_FIFO_REG);
+ s->readback[chan] = val;
return insn->n;
}
@@ -527,9 +531,10 @@ static void cb_pcidas_calib_write(struct comedi_device *dev,
bool trimpot)
{
struct cb_pcidas_private *devpriv = dev->private;
- unsigned int calib_bits = cal_enable_bits(dev);
+ unsigned int calib_bits;
unsigned int bit;
+ calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
if (trimpot) {
/* select trimpot */
calib_bits |= PCIDAS_CALIB_TRIM_SEL;
@@ -547,7 +552,7 @@ static void cb_pcidas_calib_write(struct comedi_device *dev,
}
udelay(1);
- calib_bits = cal_enable_bits(dev);
+ calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
if (!trimpot) {
/* select caldac */
@@ -585,7 +590,7 @@ static void cb_pcidas_dac08_write(struct comedi_device *dev, unsigned int val)
{
struct cb_pcidas_private *devpriv = dev->private;
- val |= cal_enable_bits(dev);
+ val |= PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
/* latch the new value into the caldac */
outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
@@ -1086,7 +1091,6 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
return 0;
}
-/* cancel analog output command */
static int cb_pcidas_ao_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -1106,22 +1110,19 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev,
return 0;
}
-static void cb_pcidas_ao_interrupt(struct comedi_device *dev,
- unsigned int status)
+static unsigned int cb_pcidas_ao_interrupt(struct comedi_device *dev,
+ unsigned int status)
{
const struct cb_pcidas_board *board = dev->board_ptr;
struct cb_pcidas_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->write_subdev;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned long flags;
+ unsigned int irq_clr = 0;
if (status & PCIDAS_CTRL_DAEMI) {
- /* clear dac empty interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->ctrl | PCIDAS_CTRL_DAEMI,
- devpriv->pcibar1 + PCIDAS_CTRL_REG);
- spin_unlock_irqrestore(&dev->spinlock, flags);
+ irq_clr |= PCIDAS_CTRL_DAEMI;
+
if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) {
if (cmd->stop_src == TRIG_COUNT &&
async->scans_done >= cmd->stop_arg) {
@@ -1132,59 +1133,33 @@ static void cb_pcidas_ao_interrupt(struct comedi_device *dev,
}
}
} else if (status & PCIDAS_CTRL_DAHFI) {
- cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
+ irq_clr |= PCIDAS_CTRL_DAHFI;
- /* clear half-full interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->ctrl | PCIDAS_CTRL_DAHFI,
- devpriv->pcibar1 + PCIDAS_CTRL_REG);
- spin_unlock_irqrestore(&dev->spinlock, flags);
+ cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
}
comedi_handle_events(dev, s);
+
+ return irq_clr;
}
-static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
+static unsigned int cb_pcidas_ai_interrupt(struct comedi_device *dev,
+ unsigned int status)
{
- struct comedi_device *dev = d;
const struct cb_pcidas_board *board = dev->board_ptr;
struct cb_pcidas_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_async *async;
- struct comedi_cmd *cmd;
- int status, s5933_status;
- int half_fifo = board->fifo_size / 2;
- unsigned int num_samples, i;
- static const int timeout = 10000;
- unsigned long flags;
-
- if (!dev->attached)
- return IRQ_NONE;
-
- async = s->async;
- cmd = &async->cmd;
-
- s5933_status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
-
- if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
- return IRQ_NONE;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ unsigned int irq_clr = 0;
- /* make sure mailbox 4 is empty */
- inl_p(devpriv->amcc + AMCC_OP_REG_IMB4);
- /* clear interrupt on amcc s5933 */
- outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
- devpriv->amcc + AMCC_OP_REG_INTCSR);
+ if (status & PCIDAS_CTRL_ADHFI) {
+ unsigned int num_samples;
- status = inw(devpriv->pcibar1 + PCIDAS_CTRL_REG);
+ irq_clr |= PCIDAS_CTRL_INT_CLR;
- /* check for analog output interrupt */
- if (status & (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI))
- cb_pcidas_ao_interrupt(dev, status);
- /* check for analog input interrupts */
- /* if fifo half-full */
- if (status & PCIDAS_CTRL_ADHFI) {
- /* read data */
- num_samples = comedi_nsamples_left(s, half_fifo);
+ /* FIFO is half-full - read data */
+ num_samples = comedi_nsamples_left(s, board->fifo_size / 2);
insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG,
devpriv->ai_buffer, num_samples);
comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
@@ -1192,15 +1167,13 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
if (cmd->stop_src == TRIG_COUNT &&
async->scans_done >= cmd->stop_arg)
async->events |= COMEDI_CB_EOA;
-
- /* clear half-full interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->ctrl | PCIDAS_CTRL_INT_CLR,
- devpriv->pcibar1 + PCIDAS_CTRL_REG);
- spin_unlock_irqrestore(&dev->spinlock, flags);
- /* else if fifo not empty */
} else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) {
- for (i = 0; i < timeout; i++) {
+ unsigned int i;
+
+ irq_clr |= PCIDAS_CTRL_INT_CLR;
+
+ /* FIFO is not empty - read data until empty or timeoout */
+ for (i = 0; i < 10000; i++) {
unsigned short val;
/* break if fifo is empty */
@@ -1216,33 +1189,67 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
break;
}
}
- /* clear not-empty interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->ctrl | PCIDAS_CTRL_INT_CLR,
- devpriv->pcibar1 + PCIDAS_CTRL_REG);
- spin_unlock_irqrestore(&dev->spinlock, flags);
} else if (status & PCIDAS_CTRL_EOAI) {
+ irq_clr |= PCIDAS_CTRL_EOAI;
+
dev_err(dev->class_dev,
"bug! encountered end of acquisition interrupt?\n");
- /* clear EOA interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->ctrl | PCIDAS_CTRL_EOAI,
- devpriv->pcibar1 + PCIDAS_CTRL_REG);
- spin_unlock_irqrestore(&dev->spinlock, flags);
}
+
/* check for fifo overflow */
if (status & PCIDAS_CTRL_LADFUL) {
+ irq_clr |= PCIDAS_CTRL_LADFUL;
+
dev_err(dev->class_dev, "fifo overflow\n");
- /* clear overflow interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->ctrl | PCIDAS_CTRL_LADFUL,
- devpriv->pcibar1 + PCIDAS_CTRL_REG);
- spin_unlock_irqrestore(&dev->spinlock, flags);
async->events |= COMEDI_CB_ERROR;
}
comedi_handle_events(dev, s);
+ return irq_clr;
+}
+
+static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ struct cb_pcidas_private *devpriv = dev->private;
+ unsigned int irq_clr = 0;
+ unsigned int amcc_status;
+ unsigned int status;
+
+ if (!dev->attached)
+ return IRQ_NONE;
+
+ amcc_status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ if ((INTCSR_INTR_ASSERTED & amcc_status) == 0)
+ return IRQ_NONE;
+
+ /* make sure mailbox 4 is empty */
+ inl_p(devpriv->amcc + AMCC_OP_REG_IMB4);
+ /* clear interrupt on amcc s5933 */
+ outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
+ devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ status = inw(devpriv->pcibar1 + PCIDAS_CTRL_REG);
+
+ /* handle analog output interrupts */
+ if (status & PCIDAS_CTRL_AO_INT)
+ irq_clr |= cb_pcidas_ao_interrupt(dev, status);
+
+ /* handle analog input interrupts */
+ if (status & PCIDAS_CTRL_AI_INT)
+ irq_clr |= cb_pcidas_ai_interrupt(dev, status);
+
+ if (irq_clr) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->spinlock, flags);
+ outw(devpriv->ctrl | irq_clr,
+ devpriv->pcibar1 + PCIDAS_CTRL_REG);
+ spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+
return IRQ_HANDLED;
}
@@ -1496,5 +1503,5 @@ static struct pci_driver cb_pcidas_pci_driver = {
module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 80d613c0fbc6..4ab186669f0c 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -1,49 +1,49 @@
/*
- comedi/drivers/comedi_test.c
+ * comedi/drivers/comedi_test.c
+ *
+ * Generates fake waveform signals that can be read through
+ * the command interface. It does _not_ read from any board;
+ * it just generates deterministic waveforms.
+ * Useful for various testing purposes.
+ *
+ * Copyright (C) 2002 Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>
+ * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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.
+ */
- Generates fake waveform signals that can be read through
- the command interface. It does _not_ read from any board;
- it just generates deterministic waveforms.
- Useful for various testing purposes.
-
- Copyright (C) 2002 Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>
- Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.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.
-*/
/*
-Driver: comedi_test
-Description: generates fake waveforms
-Author: Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>, Frank Mori Hess
- <fmhess@users.sourceforge.net>, ds
-Devices:
-Status: works
-Updated: Sat, 16 Mar 2002 17:34:48 -0800
-
-This driver is mainly for testing purposes, but can also be used to
-generate sample waveforms on systems that don't have data acquisition
-hardware.
-
-Configuration options:
- [0] - Amplitude in microvolts for fake waveforms (default 1 volt)
- [1] - Period in microseconds for fake waveforms (default 0.1 sec)
-
-Generates a sawtooth wave on channel 0, square wave on channel 1, additional
-waveforms could be added to other channels (currently they return flatline
-zero volts).
-
-*/
+ * Driver: comedi_test
+ * Description: generates fake waveforms
+ * Author: Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>, Frank Mori Hess
+ * <fmhess@users.sourceforge.net>, ds
+ * Devices:
+ * Status: works
+ * Updated: Sat, 16 Mar 2002 17:34:48 -0800
+ *
+ * This driver is mainly for testing purposes, but can also be used to
+ * generate sample waveforms on systems that don't have data acquisition
+ * hardware.
+ *
+ * Configuration options:
+ * [0] - Amplitude in microvolts for fake waveforms (default 1 volt)
+ * [1] - Period in microseconds for fake waveforms (default 0.1 sec)
+ *
+ * Generates a sawtooth wave on channel 0, square wave on channel 1, additional
+ * waveforms could be added to other channels (currently they return flatline
+ * zero volts).
+ */
#include <linux/module.h>
#include "../comedidev.h"
@@ -52,30 +52,31 @@ zero volts).
#include <linux/timer.h>
#include <linux/ktime.h>
+#include <linux/jiffies.h>
#define N_CHANS 8
enum waveform_state_bits {
- WAVEFORM_AI_RUNNING = 0
+ WAVEFORM_AI_RUNNING,
+ WAVEFORM_AO_RUNNING
};
/* Data unique to this driver */
struct waveform_private {
- struct timer_list timer;
- ktime_t last; /* time last timer interrupt occurred */
- unsigned int uvolt_amplitude; /* waveform amplitude in microvolts */
- unsigned long usec_period; /* waveform period in microseconds */
- unsigned long usec_current; /* current time (mod waveform period) */
- unsigned long usec_remainder; /* usec since last scan */
+ struct timer_list ai_timer; /* timer for AI commands */
+ u64 ai_convert_time; /* time of next AI conversion in usec */
+ unsigned int wf_amplitude; /* waveform amplitude in microvolts */
+ unsigned int wf_period; /* waveform period in microseconds */
+ unsigned int wf_current; /* current time in waveform period */
unsigned long state_bits;
- unsigned int scan_period; /* scan period in usec */
- unsigned int convert_period; /* conversion period in usec */
- unsigned int ao_loopbacks[N_CHANS];
+ unsigned int ai_scan_period; /* AI scan period in usec */
+ unsigned int ai_convert_period; /* AI conversion period in usec */
+ struct timer_list ao_timer; /* timer for AO commands */
+ u64 ao_last_scan_time; /* time of previous AO scan in usec */
+ unsigned int ao_scan_period; /* AO scan period in usec */
+ unsigned short ao_loopbacks[N_CHANS];
};
-/* 1000 nanosec in a microsec */
-static const int nano_per_micro = 1000;
-
/* fake analog input ranges */
static const struct comedi_lrange waveform_ai_ranges = {
2, {
@@ -86,7 +87,7 @@ static const struct comedi_lrange waveform_ai_ranges = {
static unsigned short fake_sawtooth(struct comedi_device *dev,
unsigned int range_index,
- unsigned long current_time)
+ unsigned int current_time)
{
struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
@@ -97,21 +98,28 @@ static unsigned short fake_sawtooth(struct comedi_device *dev,
u64 binary_amplitude;
binary_amplitude = s->maxdata;
- binary_amplitude *= devpriv->uvolt_amplitude;
+ binary_amplitude *= devpriv->wf_amplitude;
do_div(binary_amplitude, krange->max - krange->min);
- current_time %= devpriv->usec_period;
value = current_time;
value *= binary_amplitude * 2;
- do_div(value, devpriv->usec_period);
- value -= binary_amplitude; /* get rid of sawtooth's dc offset */
+ do_div(value, devpriv->wf_period);
+ value += offset;
+ /* get rid of sawtooth's dc offset and clamp value */
+ if (value < binary_amplitude) {
+ value = 0; /* negative saturation */
+ } else {
+ value -= binary_amplitude;
+ if (value > s->maxdata)
+ value = s->maxdata; /* positive saturation */
+ }
- return offset + value;
+ return value;
}
static unsigned short fake_squarewave(struct comedi_device *dev,
unsigned int range_index,
- unsigned long current_time)
+ unsigned int current_time)
{
struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
@@ -119,21 +127,29 @@ static unsigned short fake_squarewave(struct comedi_device *dev,
u64 value;
const struct comedi_krange *krange =
&s->range_table->range[range_index];
- current_time %= devpriv->usec_period;
value = s->maxdata;
- value *= devpriv->uvolt_amplitude;
+ value *= devpriv->wf_amplitude;
do_div(value, krange->max - krange->min);
- if (current_time < devpriv->usec_period / 2)
- value *= -1;
+ /* get one of two values for square-wave and clamp */
+ if (current_time < devpriv->wf_period / 2) {
+ if (offset < value)
+ value = 0; /* negative saturation */
+ else
+ value = offset - value;
+ } else {
+ value += offset;
+ if (value > s->maxdata)
+ value = s->maxdata; /* positive saturation */
+ }
- return offset + value;
+ return value;
}
static unsigned short fake_flatline(struct comedi_device *dev,
unsigned int range_index,
- unsigned long current_time)
+ unsigned int current_time)
{
return dev->read_subdev->maxdata / 2;
}
@@ -141,7 +157,7 @@ static unsigned short fake_flatline(struct comedi_device *dev,
/* generates a different waveform depending on what channel is read */
static unsigned short fake_waveform(struct comedi_device *dev,
unsigned int channel, unsigned int range,
- unsigned long current_time)
+ unsigned int current_time)
{
enum {
SAWTOOTH_CHAN,
@@ -160,58 +176,62 @@ static unsigned short fake_waveform(struct comedi_device *dev,
}
/*
- This is the background routine used to generate arbitrary data.
- It should run in the background; therefore it is scheduled by
- a timer mechanism.
-*/
-static void waveform_ai_interrupt(unsigned long arg)
+ * This is the background routine used to generate arbitrary data.
+ * It should run in the background; therefore it is scheduled by
+ * a timer mechanism.
+ */
+static void waveform_ai_timer(unsigned long arg)
{
struct comedi_device *dev = (struct comedi_device *)arg;
struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned int i, j;
- /* all times in microsec */
- unsigned long elapsed_time;
- unsigned int num_scans;
- ktime_t now;
+ u64 now;
+ unsigned int nsamples;
+ unsigned int time_increment;
/* check command is still active */
if (!test_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits))
return;
- now = ktime_get();
-
- elapsed_time = ktime_to_us(ktime_sub(now, devpriv->last));
- devpriv->last = now;
- num_scans =
- (devpriv->usec_remainder + elapsed_time) / devpriv->scan_period;
- devpriv->usec_remainder =
- (devpriv->usec_remainder + elapsed_time) % devpriv->scan_period;
-
- num_scans = comedi_nscans_left(s, num_scans);
- for (i = 0; i < num_scans; i++) {
- for (j = 0; j < cmd->chanlist_len; j++) {
- unsigned short sample;
-
- sample = fake_waveform(dev, CR_CHAN(cmd->chanlist[j]),
- CR_RANGE(cmd->chanlist[j]),
- devpriv->usec_current +
- i * devpriv->scan_period +
- j * devpriv->convert_period);
- comedi_buf_write_samples(s, &sample, 1);
+ now = ktime_to_us(ktime_get());
+ nsamples = comedi_nsamples_left(s, UINT_MAX);
+
+ while (nsamples && devpriv->ai_convert_time < now) {
+ unsigned int chanspec = cmd->chanlist[async->cur_chan];
+ unsigned short sample;
+
+ sample = fake_waveform(dev, CR_CHAN(chanspec),
+ CR_RANGE(chanspec), devpriv->wf_current);
+ if (comedi_buf_write_samples(s, &sample, 1) == 0)
+ goto overrun;
+ time_increment = devpriv->ai_convert_period;
+ if (async->scan_progress == 0) {
+ /* done last conversion in scan, so add dead time */
+ time_increment += devpriv->ai_scan_period -
+ devpriv->ai_convert_period *
+ cmd->scan_end_arg;
}
+ devpriv->wf_current += time_increment;
+ if (devpriv->wf_current >= devpriv->wf_period)
+ devpriv->wf_current %= devpriv->wf_period;
+ devpriv->ai_convert_time += time_increment;
+ nsamples--;
}
- devpriv->usec_current += elapsed_time;
- devpriv->usec_current %= devpriv->usec_period;
-
- if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) {
async->events |= COMEDI_CB_EOA;
- else
- mod_timer(&devpriv->timer, jiffies + 1);
+ } else {
+ if (devpriv->ai_convert_time > now)
+ time_increment = devpriv->ai_convert_time - now;
+ else
+ time_increment = 1;
+ mod_timer(&devpriv->ai_timer,
+ jiffies + usecs_to_jiffies(time_increment));
+ }
+overrun:
comedi_handle_events(dev, s);
}
@@ -220,12 +240,13 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- unsigned int arg;
+ unsigned int arg, limit;
/* Step 1 : check if triggers are trivially valid */
err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
- err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= comedi_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_TIMER);
err |= comedi_check_trigger_src(&cmd->convert_src,
TRIG_NOW | TRIG_TIMER);
err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
@@ -241,6 +262,9 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
/* Step 2b : and mutually compatible */
+ if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
+ err |= -EINVAL; /* scan period would be 0 */
+
if (err)
return 2;
@@ -248,18 +272,20 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
- if (cmd->convert_src == TRIG_NOW)
+ if (cmd->convert_src == TRIG_NOW) {
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+ } else { /* cmd->convert_src == TRIG_TIMER */
+ if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+ NSEC_PER_USEC);
+ }
+ }
- if (cmd->scan_begin_src == TRIG_TIMER) {
+ if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ } else { /* cmd->scan_begin_src == TRIG_TIMER */
err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
- nano_per_micro);
- if (cmd->convert_src == TRIG_TIMER) {
- err |= comedi_check_trigger_arg_min(&cmd->
- scan_begin_arg,
- cmd->convert_arg *
- cmd->chanlist_len);
- }
+ NSEC_PER_USEC);
}
err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
@@ -268,7 +294,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
if (cmd->stop_src == TRIG_COUNT)
err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
- else /* TRIG_NONE */
+ else /* cmd->stop_src == TRIG_NONE */
err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
if (err)
@@ -276,21 +302,34 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
/* step 4: fix up any arguments */
- if (cmd->scan_begin_src == TRIG_TIMER) {
- arg = cmd->scan_begin_arg;
- /* round to nearest microsec */
- arg = nano_per_micro *
- ((arg + (nano_per_micro / 2)) / nano_per_micro);
- err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
- }
if (cmd->convert_src == TRIG_TIMER) {
+ /* round convert_arg to nearest microsecond */
arg = cmd->convert_arg;
- /* round to nearest microsec */
- arg = nano_per_micro *
- ((arg + (nano_per_micro / 2)) / nano_per_micro);
+ arg = min(arg,
+ rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC));
+ arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC);
+ if (cmd->scan_begin_arg == TRIG_TIMER) {
+ /* limit convert_arg to keep scan_begin_arg in range */
+ limit = UINT_MAX / cmd->scan_end_arg;
+ limit = rounddown(limit, (unsigned int)NSEC_PER_SEC);
+ arg = min(arg, limit);
+ }
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
}
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ /* round scan_begin_arg to nearest microsecond */
+ arg = cmd->scan_begin_arg;
+ arg = min(arg,
+ rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC));
+ arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC);
+ if (cmd->convert_src == TRIG_TIMER) {
+ /* but ensure scan_begin_arg is large enough */
+ arg = max(arg, cmd->convert_arg * cmd->scan_end_arg);
+ }
+ err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+ }
+
if (err)
return 4;
@@ -302,6 +341,8 @@ static int waveform_ai_cmd(struct comedi_device *dev,
{
struct waveform_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int first_convert_time;
+ u64 wf_current;
if (cmd->flags & CMDF_PRIORITY) {
dev_err(dev->class_dev,
@@ -309,24 +350,48 @@ static int waveform_ai_cmd(struct comedi_device *dev,
return -1;
}
- devpriv->scan_period = cmd->scan_begin_arg / nano_per_micro;
-
if (cmd->convert_src == TRIG_NOW)
- devpriv->convert_period = 0;
- else /* TRIG_TIMER */
- devpriv->convert_period = cmd->convert_arg / nano_per_micro;
+ devpriv->ai_convert_period = 0;
+ else /* cmd->convert_src == TRIG_TIMER */
+ devpriv->ai_convert_period = cmd->convert_arg / NSEC_PER_USEC;
+
+ if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ devpriv->ai_scan_period = devpriv->ai_convert_period *
+ cmd->scan_end_arg;
+ } else { /* cmd->scan_begin_src == TRIG_TIMER */
+ devpriv->ai_scan_period = cmd->scan_begin_arg / NSEC_PER_USEC;
+ }
- devpriv->last = ktime_get();
- devpriv->usec_current =
- ((u32)ktime_to_us(devpriv->last)) % devpriv->usec_period;
- devpriv->usec_remainder = 0;
+ /*
+ * Simulate first conversion to occur at convert period after
+ * conversion timer starts. If scan_begin_src is TRIG_FOLLOW, assume
+ * the conversion timer starts immediately. If scan_begin_src is
+ * TRIG_TIMER, assume the conversion timer starts after the scan
+ * period.
+ */
+ first_convert_time = devpriv->ai_convert_period;
+ if (cmd->scan_begin_src == TRIG_TIMER)
+ first_convert_time += devpriv->ai_scan_period;
+ devpriv->ai_convert_time = ktime_to_us(ktime_get()) +
+ first_convert_time;
+
+ /* Determine time within waveform period at time of conversion. */
+ wf_current = devpriv->ai_convert_time;
+ devpriv->wf_current = do_div(wf_current, devpriv->wf_period);
+
+ /*
+ * Schedule timer to expire just after first conversion time.
+ * Seem to need an extra jiffy here, otherwise timer expires slightly
+ * early!
+ */
+ devpriv->ai_timer.expires =
+ jiffies + usecs_to_jiffies(devpriv->ai_convert_period) + 1;
- devpriv->timer.expires = jiffies + 1;
/* mark command as active */
smp_mb__before_atomic();
set_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits);
smp_mb__after_atomic();
- add_timer(&devpriv->timer);
+ add_timer(&devpriv->ai_timer);
return 0;
}
@@ -339,7 +404,7 @@ static int waveform_ai_cancel(struct comedi_device *dev,
clear_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits);
smp_mb__after_atomic();
/* cannot call del_timer_sync() as may be called from timer routine */
- del_timer(&devpriv->timer);
+ del_timer(&devpriv->ai_timer);
return 0;
}
@@ -356,6 +421,201 @@ static int waveform_ai_insn_read(struct comedi_device *dev,
return insn->n;
}
+/*
+ * This is the background routine to handle AO commands, scheduled by
+ * a timer mechanism.
+ */
+static void waveform_ao_timer(unsigned long arg)
+{
+ struct comedi_device *dev = (struct comedi_device *)arg;
+ struct waveform_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->write_subdev;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ u64 now;
+ u64 scans_since;
+ unsigned int scans_avail = 0;
+
+ /* check command is still active */
+ if (!test_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits))
+ return;
+
+ /* determine number of scan periods since last time */
+ now = ktime_to_us(ktime_get());
+ scans_since = now - devpriv->ao_last_scan_time;
+ do_div(scans_since, devpriv->ao_scan_period);
+ if (scans_since) {
+ unsigned int i;
+
+ /* determine scans in buffer, limit to scans to do this time */
+ scans_avail = comedi_nscans_left(s, 0);
+ if (scans_avail > scans_since)
+ scans_avail = scans_since;
+ if (scans_avail) {
+ /* skip all but the last scan to save processing time */
+ if (scans_avail > 1) {
+ unsigned int skip_bytes, nbytes;
+
+ skip_bytes =
+ comedi_samples_to_bytes(s, cmd->scan_end_arg *
+ (scans_avail - 1));
+ nbytes = comedi_buf_read_alloc(s, skip_bytes);
+ comedi_buf_read_free(s, nbytes);
+ comedi_inc_scan_progress(s, nbytes);
+ if (nbytes < skip_bytes) {
+ /* unexpected underrun! (cancelled?) */
+ async->events |= COMEDI_CB_OVERFLOW;
+ goto underrun;
+ }
+ }
+ /* output the last scan */
+ for (i = 0; i < cmd->scan_end_arg; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+
+ if (comedi_buf_read_samples(s,
+ &devpriv->
+ ao_loopbacks[chan],
+ 1) == 0) {
+ /* unexpected underrun! (cancelled?) */
+ async->events |= COMEDI_CB_OVERFLOW;
+ goto underrun;
+ }
+ }
+ /* advance time of last scan */
+ devpriv->ao_last_scan_time +=
+ (u64)scans_avail * devpriv->ao_scan_period;
+ }
+ }
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ } else if (scans_avail < scans_since) {
+ async->events |= COMEDI_CB_OVERFLOW;
+ } else {
+ unsigned int time_inc = devpriv->ao_last_scan_time +
+ devpriv->ao_scan_period - now;
+
+ mod_timer(&devpriv->ao_timer,
+ jiffies + usecs_to_jiffies(time_inc));
+ }
+
+underrun:
+ comedi_handle_events(dev, s);
+}
+
+static int waveform_ao_inttrig_start(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int trig_num)
+{
+ struct waveform_private *devpriv = dev->private;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+
+ if (trig_num != cmd->start_arg)
+ return -EINVAL;
+
+ async->inttrig = NULL;
+
+ devpriv->ao_last_scan_time = ktime_to_us(ktime_get());
+ devpriv->ao_timer.expires =
+ jiffies + usecs_to_jiffies(devpriv->ao_scan_period);
+
+ /* mark command as active */
+ smp_mb__before_atomic();
+ set_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits);
+ smp_mb__after_atomic();
+ add_timer(&devpriv->ao_timer);
+
+ return 1;
+}
+
+static int waveform_ao_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
+{
+ int err = 0;
+ unsigned int arg;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
+ err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+
+ if (err)
+ return 1;
+
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= comedi_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
+
+ if (err)
+ return 2;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+ NSEC_PER_USEC);
+ err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+ err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+ err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+ cmd->chanlist_len);
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
+ else /* cmd->stop_src == TRIG_NONE */
+ err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ /* round scan_begin_arg to nearest microsecond */
+ arg = cmd->scan_begin_arg;
+ arg = min(arg, rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC));
+ arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC);
+ err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int waveform_ao_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct waveform_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+
+ if (cmd->flags & CMDF_PRIORITY) {
+ dev_err(dev->class_dev,
+ "commands at RT priority not supported in this driver\n");
+ return -1;
+ }
+
+ devpriv->ao_scan_period = cmd->scan_begin_arg / NSEC_PER_USEC;
+ s->async->inttrig = waveform_ao_inttrig_start;
+ return 0;
+}
+
+static int waveform_ao_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct waveform_private *devpriv = dev->private;
+
+ s->async->inttrig = NULL;
+ /* mark command as no longer active */
+ clear_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits);
+ smp_mb__after_atomic();
+ /* cannot call del_timer_sync() as may be called from timer routine */
+ del_timer(&devpriv->ao_timer);
+ return 0;
+}
+
static int waveform_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -389,8 +649,8 @@ static int waveform_attach(struct comedi_device *dev,
if (period <= 0)
period = 100000; /* 0.1 sec */
- devpriv->uvolt_amplitude = amplitude;
- devpriv->usec_period = period;
+ devpriv->wf_amplitude = amplitude;
+ devpriv->wf_period = period;
ret = comedi_alloc_subdevices(dev, 2);
if (ret)
@@ -414,23 +674,28 @@ static int waveform_attach(struct comedi_device *dev,
dev->write_subdev = s;
/* analog output subdevice (loopback) */
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
s->n_chan = N_CHANS;
s->maxdata = 0xffff;
s->range_table = &waveform_ai_ranges;
+ s->len_chanlist = s->n_chan;
s->insn_write = waveform_ao_insn_write;
+ s->insn_read = waveform_ai_insn_read; /* do same as AI insn_read */
+ s->do_cmd = waveform_ao_cmd;
+ s->do_cmdtest = waveform_ao_cmdtest;
+ s->cancel = waveform_ao_cancel;
/* Our default loopback value is just a 0V flatline */
for (i = 0; i < s->n_chan; i++)
devpriv->ao_loopbacks[i] = s->maxdata / 2;
- setup_timer(&devpriv->timer, waveform_ai_interrupt,
- (unsigned long)dev);
+ setup_timer(&devpriv->ai_timer, waveform_ai_timer, (unsigned long)dev);
+ setup_timer(&devpriv->ao_timer, waveform_ao_timer, (unsigned long)dev);
dev_info(dev->class_dev,
- "%s: %i microvolt, %li microsecond waveform attached\n",
+ "%s: %u microvolt, %u microsecond waveform attached\n",
dev->board_name,
- devpriv->uvolt_amplitude, devpriv->usec_period);
+ devpriv->wf_amplitude, devpriv->wf_period);
return 0;
}
@@ -439,8 +704,10 @@ static void waveform_detach(struct comedi_device *dev)
{
struct waveform_private *devpriv = dev->private;
- if (devpriv)
- del_timer_sync(&devpriv->timer);
+ if (devpriv) {
+ del_timer_sync(&devpriv->ai_timer);
+ del_timer_sync(&devpriv->ao_timer);
+ }
}
static struct comedi_driver waveform_driver = {
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 611b0a3ef5d7..57ab6680e3ae 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -713,12 +713,8 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
return result;
s = &dev->subdevices[2];
- result = subdev_8255_init(dev, s, daqboard2000_8255_cb,
- dioP2ExpansionIO8Bit);
- if (result)
- return result;
-
- return 0;
+ return subdev_8255_init(dev, s, daqboard2000_8255_cb,
+ dioP2ExpansionIO8Bit);
}
static void daqboard2000_detach(struct comedi_device *dev)
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 056bca9c67d5..fd8e0b76f764 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -801,9 +801,10 @@ static void das16_ai_munge(struct comedi_device *dev,
unsigned short *data = array;
unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
unsigned int i;
+ __le16 *buf = array;
for (i = 0; i < num_samples; i++) {
- data[i] = le16_to_cpu(data[i]);
+ data[i] = le16_to_cpu(buf[i]);
if (s->maxdata == 0x0fff)
data[i] >>= 4;
data[i] &= s->maxdata;
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 6cc304a4c59b..cbb44fc6940b 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -1516,13 +1516,17 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned short *array = data;
unsigned int *larray = data;
unsigned int i;
+#ifdef PCIDMA
+ __le16 *barray = data;
+ __le32 *blarray = data;
+#endif
for (i = 0; i < nsamples; i++) {
#ifdef PCIDMA
if (s->subdev_flags & SDF_LSAMPL)
- larray[i] = le32_to_cpu(larray[i]);
+ larray[i] = le32_to_cpu(blarray[i]);
else
- array[i] = le16_to_cpu(array[i]);
+ array[i] = le16_to_cpu(barray[i]);
#endif
if (s->subdev_flags & SDF_LSAMPL)
larray[i] += devpriv->ai_offset[chan_index];
@@ -2574,6 +2578,9 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes);
unsigned short *array = data;
unsigned int i;
+#ifdef PCIDMA
+ __le16 buf, *barray = data;
+#endif
for (i = 0; i < nsamples; i++) {
unsigned int range = CR_RANGE(cmd->chanlist[chan_index]);
@@ -2586,10 +2593,11 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
if (comedi_range_is_bipolar(s, range))
val = comedi_offset_munge(s, val);
#ifdef PCIDMA
- val = cpu_to_le16(val);
-#endif
+ buf = cpu_to_le16(val);
+ barray[i] = buf;
+#else
array[i] = val;
-
+#endif
chan_index++;
chan_index %= cmd->chanlist_len;
}
diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
index c20c51bef3e7..b74e44ec521a 100644
--- a/drivers/staging/comedi/drivers/ni_tio.c
+++ b/drivers/staging/comedi/drivers/ni_tio.c
@@ -167,15 +167,15 @@ static inline unsigned GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant)
}
}
-static int ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev)
+static bool ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev)
{
switch (counter_dev->variant) {
case ni_gpct_variant_e_series:
default:
- return 0;
+ return false;
case ni_gpct_variant_m_series:
case ni_gpct_variant_660x:
- return 1;
+ return true;
}
}
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
index ca64126618ed..bad355100825 100644
--- a/drivers/staging/dgap/dgap.c
+++ b/drivers/staging/dgap/dgap.c
@@ -140,21 +140,21 @@ struct board_id {
};
static struct board_id dgap_ids[] = {
- { PPCM, PCI_DEV_XEM_NAME, 64, (T_PCXM|T_PCLITE|T_PCIBUS) },
- { PCX, PCI_DEV_CX_NAME, 128, (T_CX|T_PCIBUS) },
- { PCX, PCI_DEV_CX_IBM_NAME, 128, (T_CX|T_PCIBUS) },
- { PEPC, PCI_DEV_EPCJ_NAME, 224, (T_EPC|T_PCIBUS) },
- { APORT2_920P, PCI_DEV_920_2_NAME, 2, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { APORT4_920P, PCI_DEV_920_4_NAME, 4, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { APORT8_920P, PCI_DEV_920_8_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PAPORT8, PCI_DEV_XR_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PAPORT8, PCI_DEV_XRJ_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PAPORT8, PCI_DEV_XR_422_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PAPORT8, PCI_DEV_XR_IBM_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PAPORT8, PCI_DEV_XR_SAIP_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PAPORT8, PCI_DEV_XR_BULL_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { APORT8_920P, PCI_DEV_920_8_HP_NAME, 8, (T_PCXR|T_PCLITE|T_PCIBUS) },
- { PPCM, PCI_DEV_XEM_HP_NAME, 64, (T_PCXM|T_PCLITE|T_PCIBUS) },
+ {PPCM, PCI_DEV_XEM_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)},
+ {PCX, PCI_DEV_CX_NAME, 128, (T_CX | T_PCIBUS) },
+ {PCX, PCI_DEV_CX_IBM_NAME, 128, (T_CX | T_PCIBUS) },
+ {PEPC, PCI_DEV_EPCJ_NAME, 224, (T_EPC | T_PCIBUS) },
+ {APORT2_920P, PCI_DEV_920_2_NAME, 2, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {APORT4_920P, PCI_DEV_920_4_NAME, 4, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {APORT8_920P, PCI_DEV_920_8_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PAPORT8, PCI_DEV_XR_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PAPORT8, PCI_DEV_XRJ_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PAPORT8, PCI_DEV_XR_422_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PAPORT8, PCI_DEV_XR_IBM_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PAPORT8, PCI_DEV_XR_SAIP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PAPORT8, PCI_DEV_XR_BULL_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {APORT8_920P, PCI_DEV_920_8_HP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
+ {PPCM, PCI_DEV_XEM_HP_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)},
{0,} /* 0 terminated list. */
};
@@ -514,7 +514,6 @@ static uint dgap_config_get_num_prts(struct board_t *bd)
return 0;
for (p = bd->bd_config; p; p = p->next) {
-
switch (p->type) {
case BNODE:
/*
@@ -547,7 +546,6 @@ static char *dgap_create_config_string(struct board_t *bd, char *string)
}
for (p = bd->bd_config; p; p = p->next) {
-
switch (p->type) {
case LNODE:
*ptr = '\0';
@@ -933,8 +931,8 @@ static int dgap_parsefile(char **in)
brd->u.board.conc1++;
conc_type = dgap_gettok(in);
- if (conc_type == 0 || (conc_type != CX &&
- conc_type != EPC)) {
+ if (conc_type == 0 ||
+ (conc_type != CX && conc_type != EPC)) {
pr_err("failed to set a type of concentratros");
return -1;
}
@@ -974,8 +972,8 @@ static int dgap_parsefile(char **in)
brd->u.board.module1++;
module_type = dgap_gettok(in);
- if (module_type == 0 || (module_type != PORTS &&
- module_type != MODEM)) {
+ if (module_type == 0 ||
+ (module_type != PORTS && module_type != MODEM)) {
pr_err("failed to set a type of module");
return -1;
}
@@ -1353,8 +1351,7 @@ static int dgap_remap(struct board_t *brd)
if (!request_mem_region(brd->membase, 0x200000, "dgap"))
return -ENOMEM;
- if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000,
- "dgap"))
+ if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap"))
goto err_req_mem;
brd->re_map_membase = ioremap(brd->membase, 0x200000);
@@ -1392,7 +1389,7 @@ static void dgap_unmap(struct board_t *brd)
* the Linux line discipline way.
*/
static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
- unsigned char *fbuf, int *len)
+ unsigned char *fbuf, int *len)
{
int l = *len;
int count = 0;
@@ -1415,7 +1412,7 @@ static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
case 0:
/* No FF seen yet */
- if (c == (unsigned char) '\377')
+ if (c == (unsigned char)'\377')
/* delete this character from stream */
ch->pscan_state = 1;
else {
@@ -1427,7 +1424,7 @@ static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
case 1:
/* first FF seen */
- if (c == (unsigned char) '\377') {
+ if (c == (unsigned char)'\377') {
/* doubled ff, transform to single ff */
*cout++ = c;
*fout++ = TTY_NORMAL;
@@ -1446,7 +1443,6 @@ static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
*cout++ = c;
if (ch->pscan_savechar == 0x0) {
-
if (c == 0x0) {
ch->ch_err_break++;
*fout++ = TTY_BREAK;
@@ -1513,15 +1509,15 @@ static void dgap_input(struct channel_t *ch)
rmask = ch->ch_rsize - 1;
- head = readw(&(bs->rx_head));
+ head = readw(&bs->rx_head);
head &= rmask;
- tail = readw(&(bs->rx_tail));
+ tail = readw(&bs->rx_tail);
tail &= rmask;
data_len = (head - tail) & rmask;
if (data_len == 0) {
- writeb(1, &(bs->idata));
+ writeb(1, &bs->idata);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
return;
@@ -1536,9 +1532,8 @@ static void dgap_input(struct channel_t *ch)
!(ch->ch_tun.un_flags & UN_ISOPEN) ||
!(tp->termios.c_cflag & CREAD) ||
(ch->ch_tun.un_flags & UN_CLOSING)) {
-
- writew(head, &(bs->rx_tail));
- writeb(1, &(bs->idata));
+ writew(head, &bs->rx_tail);
+ writeb(1, &bs->idata);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
return;
@@ -1548,7 +1543,7 @@ static void dgap_input(struct channel_t *ch)
* If we are throttled, simply don't read any data.
*/
if (ch->ch_flags & CH_RXBLOCK) {
- writeb(1, &(bs->idata));
+ writeb(1, &bs->idata);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
return;
@@ -1557,10 +1552,10 @@ static void dgap_input(struct channel_t *ch)
/*
* Ignore oruns.
*/
- tmpchar = readb(&(bs->orun));
+ tmpchar = readb(&bs->orun);
if (tmpchar) {
ch->ch_err_overrun++;
- writeb(0, &(bs->orun));
+ writeb(0, &bs->orun);
}
/* Decide how much data we can send into the tty layer */
@@ -1595,13 +1590,13 @@ static void dgap_input(struct channel_t *ch)
* space to put the data right now.
*/
if (!ld->ops->receive_buf) {
- writew(head, &(bs->rx_tail));
+ writew(head, &bs->rx_tail);
len = 0;
}
}
if (len <= 0) {
- writeb(1, &(bs->idata));
+ writeb(1, &bs->idata);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
if (ld)
@@ -1618,7 +1613,6 @@ static void dgap_input(struct channel_t *ch)
* of data the card actually has pending...
*/
while (n) {
-
s = ((head >= tail) ? head : ch->ch_rsize) - tail;
s = min(s, n);
@@ -1635,8 +1629,8 @@ static void dgap_input(struct channel_t *ch)
tail &= rmask;
}
- writew(tail, &(bs->rx_tail));
- writeb(1, &(bs->idata));
+ writew(tail, &bs->rx_tail);
+ writeb(1, &bs->idata);
ch->ch_rxcount += len;
/*
@@ -1654,7 +1648,7 @@ static void dgap_input(struct channel_t *ch)
len = tty_buffer_request_room(tp->port, len);
tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
- ch->ch_bd->flipflagbuf, len);
+ ch->ch_bd->flipflagbuf, len);
} else {
len = tty_buffer_request_room(tp->port, len);
tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
@@ -1668,7 +1662,6 @@ static void dgap_input(struct channel_t *ch)
if (ld)
tty_ldisc_deref(ld);
-
}
static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch,
@@ -1739,7 +1732,6 @@ static void dgap_carrier(struct channel_t *ch)
* Test for a VIRTUAL carrier transition to HIGH.
*/
if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
-
/*
* When carrier rises, wake any threads waiting
* for carrier in the open routine.
@@ -1753,7 +1745,6 @@ static void dgap_carrier(struct channel_t *ch)
* Test for a PHYSICAL carrier transition to HIGH.
*/
if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
-
/*
* When carrier rises, wake any threads waiting
* for carrier in the open routine.
@@ -1775,7 +1766,6 @@ static void dgap_carrier(struct channel_t *ch)
if ((virt_carrier == 0) &&
((ch->ch_flags & CH_CD) != 0) &&
(phys_carrier == 0)) {
-
/*
* When carrier drops:
*
@@ -1846,11 +1836,11 @@ static int dgap_event(struct board_t *bd)
return -EIO;
}
- eaddr = (struct ev_t __iomem *) (vaddr + EVBUF);
+ eaddr = (struct ev_t __iomem *)(vaddr + EVBUF);
/* Get our head and tail */
- head = readw(&(eaddr->ev_head));
- tail = readw(&(eaddr->ev_tail));
+ head = readw(&eaddr->ev_head);
+ tail = readw(&eaddr->ev_tail);
/*
* Forget it if pointers out of range.
@@ -1867,7 +1857,6 @@ static int dgap_event(struct board_t *bd)
* Loop to process all the events in the buffer.
*/
while (tail != head) {
-
/*
* Get interrupt information.
*/
@@ -1910,7 +1899,6 @@ static int dgap_event(struct board_t *bd)
* Process received data.
*/
if (reason & IFDATA) {
-
/*
* ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
* input could send some data to ld, which in turn
@@ -1927,7 +1915,7 @@ static int dgap_event(struct board_t *bd)
if (ch->ch_flags & CH_RACTIVE)
ch->ch_flags |= CH_RENABLE;
else
- writeb(1, &(bs->idata));
+ writeb(1, &bs->idata);
if (ch->ch_flags & CH_RWAIT) {
ch->ch_flags &= ~CH_RWAIT;
@@ -1949,7 +1937,6 @@ static int dgap_event(struct board_t *bd)
* Process break.
*/
if (reason & IFBREAK) {
-
if (ch->ch_tun.un_tty) {
/* A break has been indicated */
ch->ch_err_break++;
@@ -1995,7 +1982,7 @@ next:
tail = (tail + 4) & (EVMAX - EVSTART - 4);
}
- writew(tail, &(eaddr->ev_tail));
+ writew(tail, &eaddr->ev_tail);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
return 0;
@@ -2006,7 +1993,7 @@ next:
*/
static void dgap_poll_tasklet(unsigned long data)
{
- struct board_t *bd = (struct board_t *) data;
+ struct board_t *bd = (struct board_t *)data;
ulong lock_flags;
char __iomem *vaddr;
u16 head, tail;
@@ -2025,7 +2012,6 @@ static void dgap_poll_tasklet(unsigned long data)
* If board is ready, parse deeper to see if there is anything to do.
*/
if (bd->state == BOARD_READY) {
-
struct ev_t __iomem *eaddr;
if (!bd->re_map_membase) {
@@ -2040,11 +2026,11 @@ static void dgap_poll_tasklet(unsigned long data)
if (!bd->nasync)
goto out;
- eaddr = (struct ev_t __iomem *) (vaddr + EVBUF);
+ eaddr = (struct ev_t __iomem *)(vaddr + EVBUF);
/* Get our head and tail */
- head = readw(&(eaddr->ev_head));
- tail = readw(&(eaddr->ev_tail));
+ head = readw(&eaddr->ev_head);
+ tail = readw(&eaddr->ev_tail);
/*
* If there is an event pending. Go service it.
@@ -2174,7 +2160,7 @@ static struct board_t *dgap_found_board(struct pci_dev *pdev, int id,
/* init our poll helper tasklet */
tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet,
- (unsigned long) brd);
+ (unsigned long)brd);
ret = dgap_remap(brd);
if (ret)
@@ -2269,14 +2255,13 @@ static void dgap_poll_handler(ulong dummy)
*/
if ((dgap_numboards == 1) || (num_online_cpus() <= 1)) {
for (i = 0; i < dgap_numboards; i++) {
-
brd = dgap_board[i];
if (brd->state == BOARD_FAILED)
continue;
if (!brd->intr_running)
/* Call the real board poller directly */
- dgap_poll_tasklet((unsigned long) brd);
+ dgap_poll_tasklet((unsigned long)brd);
}
} else {
/*
@@ -2329,7 +2314,7 @@ schedule_poller:
new_time = dgap_poll_time - jiffies;
- if ((ulong) new_time >= 2 * dgap_poll_tick) {
+ if ((ulong)new_time >= 2 * dgap_poll_tick) {
dgap_poll_time =
jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
}
@@ -2356,7 +2341,7 @@ schedule_poller:
*
*=======================================================================*/
static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
- u8 byte2, uint ncmds)
+ u8 byte2, uint ncmds)
{
char __iomem *vaddr;
struct __iomem cm_t *cm_addr;
@@ -2383,8 +2368,8 @@ static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
if (!vaddr)
return;
- cm_addr = (struct cm_t __iomem *) (vaddr + CMDBUF);
- head = readw(&(cm_addr->cm_head));
+ cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF);
+ head = readw(&cm_addr->cm_head);
/*
* Forget it if pointers out of range.
@@ -2398,13 +2383,13 @@ static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
* Put the data in the circular command buffer.
*/
writeb(cmd, (vaddr + head + CMDSTART + 0));
- writeb((u8) ch->ch_portnum, (vaddr + head + CMDSTART + 1));
+ writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1));
writeb(byte1, (vaddr + head + CMDSTART + 2));
writeb(byte2, (vaddr + head + CMDSTART + 3));
head = (head + 4) & (CMDMAX - CMDSTART - 4);
- writew(head, &(cm_addr->cm_head));
+ writew(head, &cm_addr->cm_head);
/*
* Wait if necessary before updating the head
@@ -2413,9 +2398,8 @@ static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
* is outlandish, declare the FEP dead.
*/
for (count = dgap_count ;;) {
-
- head = readw(&(cm_addr->cm_head));
- tail = readw(&(cm_addr->cm_tail));
+ head = readw(&cm_addr->cm_head);
+ tail = readw(&cm_addr->cm_tail);
n = (head - tail) & (CMDMAX - CMDSTART - 4);
@@ -2467,8 +2451,8 @@ static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds)
if (!vaddr)
return;
- cm_addr = (struct cm_t __iomem *) (vaddr + CMDBUF);
- head = readw(&(cm_addr->cm_head));
+ cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF);
+ head = readw(&cm_addr->cm_head);
/*
* Forget it if pointers out of range.
@@ -2482,12 +2466,12 @@ static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds)
* Put the data in the circular command buffer.
*/
writeb(cmd, (vaddr + head + CMDSTART + 0));
- writeb((u8) ch->ch_portnum, (vaddr + head + CMDSTART + 1));
- writew((u16) word, (vaddr + head + CMDSTART + 2));
+ writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1));
+ writew((u16)word, (vaddr + head + CMDSTART + 2));
head = (head + 4) & (CMDMAX - CMDSTART - 4);
- writew(head, &(cm_addr->cm_head));
+ writew(head, &cm_addr->cm_head);
/*
* Wait if necessary before updating the head
@@ -2496,9 +2480,8 @@ static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds)
* is outlandish, declare the FEP dead.
*/
for (count = dgap_count ;;) {
-
- head = readw(&(cm_addr->cm_head));
- tail = readw(&(cm_addr->cm_tail));
+ head = readw(&cm_addr->cm_head);
+ tail = readw(&cm_addr->cm_tail);
n = (head - tail) & (CMDMAX - CMDSTART - 4);
@@ -2550,8 +2533,8 @@ static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
if (!vaddr)
return;
- cm_addr = (struct cm_t __iomem *) (vaddr + CMDBUF);
- head = readw(&(cm_addr->cm_head));
+ cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF);
+ head = readw(&cm_addr->cm_head);
/*
* Forget it if pointers out of range.
@@ -2566,23 +2549,23 @@ static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
*/
/* Write an FF to tell the FEP that we want an extended command */
- writeb((u8) 0xff, (vaddr + head + CMDSTART + 0));
+ writeb((u8)0xff, (vaddr + head + CMDSTART + 0));
- writeb((u8) ch->ch_portnum, (vaddr + head + CMDSTART + 1));
- writew((u16) cmd, (vaddr + head + CMDSTART + 2));
+ writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1));
+ writew((u16)cmd, (vaddr + head + CMDSTART + 2));
/*
* If the second part of the command won't fit,
* put it at the beginning of the circular buffer.
*/
if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03)))
- writew((u16) word, (vaddr + CMDSTART));
+ writew((u16)word, (vaddr + CMDSTART));
else
- writew((u16) word, (vaddr + head + CMDSTART + 4));
+ writew((u16)word, (vaddr + head + CMDSTART + 4));
head = (head + 8) & (CMDMAX - CMDSTART - 4);
- writew(head, &(cm_addr->cm_head));
+ writew(head, &cm_addr->cm_head);
/*
* Wait if necessary before updating the head
@@ -2591,9 +2574,8 @@ static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
* is outlandish, declare the FEP dead.
*/
for (count = dgap_count ;;) {
-
- head = readw(&(cm_addr->cm_head));
- tail = readw(&(cm_addr->cm_tail));
+ head = readw(&cm_addr->cm_head);
+ tail = readw(&cm_addr->cm_tail);
n = (head - tail) & (CMDMAX - CMDSTART - 4);
@@ -2631,7 +2613,7 @@ static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
* Check parameters.
*/
bs = ch->ch_bs;
- head = readw(&(bs->tx_head));
+ head = readw(&bs->tx_head);
/*
* If pointers are out of range, just return.
@@ -2663,7 +2645,7 @@ static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
memcpy_toio(taddr, buf, n);
head += cnt;
- writew(head, &(bs->tx_head));
+ writew(head, &bs->tx_head);
}
/*
@@ -2711,19 +2693,18 @@ static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
* If baud rate is zero, flush queues, and set mval to drop DTR.
*/
if ((ch->ch_c_cflag & (CBAUD)) == 0) {
-
/* flush rx */
- head = readw(&(ch->ch_bs->rx_head));
- writew(head, &(ch->ch_bs->rx_tail));
+ head = readw(&ch->ch_bs->rx_head);
+ writew(head, &ch->ch_bs->rx_tail);
/* flush tx */
- head = readw(&(ch->ch_bs->tx_head));
- writew(head, &(ch->ch_bs->tx_tail));
+ head = readw(&ch->ch_bs->tx_head);
+ writew(head, &ch->ch_bs->tx_tail);
ch->ch_flags |= (CH_BAUD0);
/* Drop RTS and DTR */
- ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
+ ch->ch_mval &= ~(D_RTS(ch) | D_DTR(ch));
mval = D_DTR(ch) | D_RTS(ch);
ch->ch_baud_info = 0;
@@ -2744,7 +2725,7 @@ static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
/* Handle transition from B0 */
if (ch->ch_flags & CH_BAUD0) {
ch->ch_flags &= ~(CH_BAUD0);
- ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+ ch->ch_mval |= (D_RTS(ch) | D_DTR(ch));
}
mval = D_DTR(ch) | D_RTS(ch);
@@ -2878,19 +2859,19 @@ static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
cflag &= 0xffff;
if (cflag != ch->ch_fepcflag) {
- ch->ch_fepcflag = (u16) (cflag & 0xffff);
+ ch->ch_fepcflag = (u16)(cflag & 0xffff);
/*
* Okay to have channel and board
* locks held calling this
*/
- dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
+ dgap_cmdw(ch, SCFLAG, (u16)cflag, 0);
}
/* Handle transition from B0 */
if (ch->ch_flags & CH_BAUD0) {
ch->ch_flags &= ~(CH_BAUD0);
- ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+ ch->ch_mval |= (D_RTS(ch) | D_DTR(ch));
}
mval = D_DTR(ch) | D_RTS(ch);
}
@@ -2925,7 +2906,7 @@ static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
ch->ch_fepiflag = iflag;
/* Okay to have channel and board locks held calling this */
- dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
+ dgap_cmdw(ch, SIFLAG, (u16)ch->ch_fepiflag, 0);
}
/*
@@ -2950,7 +2931,7 @@ static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
ch->ch_hflow = hflow;
/* Okay to have channel and board locks held calling this */
- dgap_cmdb(ch, SHFLOW, (u8) hflow, 0xff, 0);
+ dgap_cmdb(ch, SHFLOW, (u8)hflow, 0xff, 0);
}
/*
@@ -2978,13 +2959,13 @@ static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
ch->ch_mostat = mval;
/* Okay to have channel and board locks held calling this */
- dgap_cmdb(ch, SMODEM, (u8) mval, D_RTS(ch)|D_DTR(ch), 0);
+ dgap_cmdb(ch, SMODEM, (u8)mval, D_RTS(ch) | D_DTR(ch), 0);
}
/*
* Read modem signals, and then call carrier function.
*/
- ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
+ ch->ch_mistat = readb(&ch->ch_bs->m_stat);
dgap_carrier(ch);
/*
@@ -3029,7 +3010,7 @@ static int dgap_block_til_ready(struct tty_struct *tty, struct file *file,
int sleep_on_un_flags;
if (!tty || tty->magic != TTY_MAGIC || !file || !ch ||
- ch->magic != DGAP_CHANNEL_MAGIC)
+ ch->magic != DGAP_CHANNEL_MAGIC)
return -EIO;
un = tty->driver_data;
@@ -3042,7 +3023,6 @@ static int dgap_block_til_ready(struct tty_struct *tty, struct file *file,
/* Loop forever */
while (1) {
-
sleep_on_un_flags = 0;
/*
@@ -3069,7 +3049,6 @@ static int dgap_block_til_ready(struct tty_struct *tty, struct file *file,
*/
if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) &
UN_CLOSING)) {
-
/*
* Our conditions to leave cleanly and happily:
* 1) NONBLOCKING on the tty is set.
@@ -3178,15 +3157,15 @@ static void dgap_tty_flush_buffer(struct tty_struct *tty)
spin_lock_irqsave(&ch->ch_lock, lock_flags2);
ch->ch_flags &= ~CH_STOP;
- head = readw(&(ch->ch_bs->tx_head));
- dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+ head = readw(&ch->ch_bs->tx_head);
+ dgap_cmdw(ch, FLUSHTX, (u16)head, 0);
dgap_cmdw(ch, RESUMETX, 0, 0);
- if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
- ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+ if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) {
+ ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY);
wake_up_interruptible(&ch->ch_tun.un_flags_wait);
}
- if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
- ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+ if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) {
+ ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY);
wake_up_interruptible(&ch->ch_pun.un_flags_wait);
}
@@ -3272,15 +3251,15 @@ static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
tmask = (ch->ch_tsize - 1);
/* Get Transmit queue pointers */
- thead = readw(&(bs->tx_head)) & tmask;
- ttail = readw(&(bs->tx_tail)) & tmask;
+ thead = readw(&bs->tx_head) & tmask;
+ ttail = readw(&bs->tx_tail) & tmask;
/* Get tbusy flag */
- tbusy = readb(&(bs->tbusy));
+ tbusy = readb(&bs->tbusy);
/* Get Command queue pointers */
- chead = readw(&(ch->ch_cm->cm_head));
- ctail = readw(&(ch->ch_cm->cm_tail));
+ chead = readw(&ch->ch_cm->cm_head);
+ ctail = readw(&ch->ch_cm->cm_tail);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3316,7 +3295,7 @@ static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
if (tbusy != 0) {
spin_lock_irqsave(&ch->ch_lock, lock_flags);
un->un_flags |= UN_EMPTY;
- writeb(1, &(bs->iempty));
+ writeb(1, &bs->iempty);
spin_unlock_irqrestore(&ch->ch_lock,
lock_flags);
}
@@ -3353,7 +3332,6 @@ static int dgap_wait_for_drain(struct tty_struct *tty)
/* Loop until data is drained */
while (count != 0) {
-
count = dgap_tty_chars_in_buffer(tty);
if (count == 0)
@@ -3362,7 +3340,7 @@ static int dgap_wait_for_drain(struct tty_struct *tty)
/* Set flag waiting for drain */
spin_lock_irqsave(&ch->ch_lock, lock_flags);
un->un_flags |= UN_EMPTY;
- writeb(1, &(bs->iempty));
+ writeb(1, &bs->iempty);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
/* Go to sleep till we get woken up */
@@ -3441,13 +3419,13 @@ static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
if ((event & UN_LOW) != 0) {
if ((un->un_flags & UN_LOW) == 0) {
un->un_flags |= UN_LOW;
- writeb(1, &(bs->ilow));
+ writeb(1, &bs->ilow);
}
}
if ((event & UN_LOW) != 0) {
if ((un->un_flags & UN_EMPTY) == 0) {
un->un_flags |= UN_EMPTY;
- writeb(1, &(bs->iempty));
+ writeb(1, &bs->iempty);
}
}
}
@@ -3484,8 +3462,8 @@ static int dgap_tty_write_room(struct tty_struct *tty)
spin_lock_irqsave(&ch->ch_lock, lock_flags);
tmask = ch->ch_tsize - 1;
- head = readw(&(bs->tx_head)) & tmask;
- tail = readw(&(bs->tx_tail)) & tmask;
+ head = readw(&bs->tx_head) & tmask;
+ tail = readw(&bs->tx_tail) & tmask;
ret = tail - head - 1;
if (ret < 0)
@@ -3530,7 +3508,7 @@ static int dgap_tty_write_room(struct tty_struct *tty)
* In here exists all the Transparent Print magic as well.
*/
static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
- int count)
+ int count)
{
struct channel_t *ch;
struct un_t *un;
@@ -3596,8 +3574,8 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
*/
if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
dgap_wmove(ch, ch->ch_digi.digi_onstr,
- (int) ch->ch_digi.digi_onlen);
- head = readw(&(bs->tx_head)) & tmask;
+ (int)ch->ch_digi.digi_onlen);
+ head = readw(&bs->tx_head) & tmask;
ch->ch_flags |= CH_PRON;
}
@@ -3607,8 +3585,8 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
*/
if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
dgap_wmove(ch, ch->ch_digi.digi_offstr,
- (int) ch->ch_digi.digi_offlen);
- head = readw(&(bs->tx_head)) & tmask;
+ (int)ch->ch_digi.digi_offlen);
+ head = readw(&bs->tx_head) & tmask;
ch->ch_flags &= ~CH_PRON;
}
@@ -3625,29 +3603,27 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
n -= remain;
vaddr = ch->ch_taddr + head;
- memcpy_toio(vaddr, (u8 *) buf, remain);
+ memcpy_toio(vaddr, (u8 *)buf, remain);
head = ch->ch_tstart;
buf += remain;
}
if (n > 0) {
-
/*
* Move rest of data.
*/
vaddr = ch->ch_taddr + head;
remain = n;
- memcpy_toio(vaddr, (u8 *) buf, remain);
+ memcpy_toio(vaddr, (u8 *)buf, remain);
head += remain;
-
}
if (count) {
ch->ch_txcount += count;
head &= tmask;
- writew(head, &(bs->tx_head));
+ writew(head, &bs->tx_head);
}
dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
@@ -3660,15 +3636,15 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
* Otherwise turn it off right now.
*/
if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
- tail = readw(&(bs->tx_tail)) & tmask;
+ tail = readw(&bs->tx_tail) & tmask;
if (tail != head) {
un->un_flags |= UN_EMPTY;
- writeb(1, &(bs->iempty));
+ writeb(1, &bs->iempty);
} else {
dgap_wmove(ch, ch->ch_digi.digi_offstr,
- (int) ch->ch_digi.digi_offlen);
- head = readw(&(bs->tx_head)) & tmask;
+ (int)ch->ch_digi.digi_offlen);
+ head = readw(&bs->tx_head) & tmask;
ch->ch_flags &= ~CH_PRON;
}
}
@@ -3724,7 +3700,7 @@ static int dgap_tty_tiocmget(struct tty_struct *tty)
spin_lock_irqsave(&ch->ch_lock, lock_flags);
- mstat = readb(&(ch->ch_bs->m_stat));
+ mstat = readb(&ch->ch_bs->m_stat);
/* Append any outbound signals that might be pending... */
mstat |= ch->ch_mostat;
@@ -3754,7 +3730,7 @@ static int dgap_tty_tiocmget(struct tty_struct *tty)
* Set modem signals, called by ld.
*/
static int dgap_tty_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
struct board_t *bd;
struct channel_t *ch;
@@ -3853,7 +3829,7 @@ static int dgap_tty_send_break(struct tty_struct *tty, int msec)
#if 0
dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
#endif
- dgap_cmdw(ch, SBREAK, (u16) msec, 0);
+ dgap_cmdw(ch, SBREAK, (u16)msec, 0);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3935,7 +3911,7 @@ static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
spin_lock_irqsave(&ch->ch_lock, lock_flags);
- mstat = readb(&(ch->ch_bs->m_stat));
+ mstat = readb(&ch->ch_bs->m_stat);
/* Append any outbound signals that might be pending... */
mstat |= ch->ch_mostat;
@@ -4005,7 +3981,7 @@ static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd,
break;
case TIOCMSET:
- ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
+ ch->ch_mforce = D_DTR(ch) | D_RTS(ch);
if (arg & TIOCM_RTS)
ch->ch_mval |= D_RTS(ch);
@@ -4147,7 +4123,7 @@ static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
memset(&tmp, 0, sizeof(tmp));
spin_lock_irqsave(&ch->ch_lock, lock_flags);
- tmp = readw(&(ch->ch_bs->edelay));
+ tmp = readw(&ch->ch_bs->edelay);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
@@ -4175,7 +4151,7 @@ static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd,
spin_lock_irqsave(&bd->bd_lock, lock_flags);
spin_lock_irqsave(&ch->ch_lock, lock_flags2);
- writew((u16) new_digi, &(ch->ch_bs->edelay));
+ writew((u16)new_digi, &ch->ch_bs->edelay);
dgap_param(ch, bd, un->un_type);
@@ -4227,7 +4203,6 @@ static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd,
return -EFAULT;
if (bd->bd_flags & BD_FEP5PLUS) {
-
spin_lock_irqsave(&bd->bd_lock, lock_flags);
spin_lock_irqsave(&ch->ch_lock, lock_flags2);
@@ -4246,7 +4221,7 @@ static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd,
* dgap_set_termios()
*/
static void dgap_tty_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios)
+ struct ktermios *old_termios)
{
struct board_t *bd;
struct channel_t *ch;
@@ -4319,7 +4294,6 @@ static void dgap_tty_throttle(struct tty_struct *tty)
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
}
static void dgap_tty_unthrottle(struct tty_struct *tty)
@@ -4410,7 +4384,7 @@ static int dgap_tty_open(struct tty_struct *tty, struct file *file)
* sleep waiting for it to happen or they cancel the open.
*/
rc = wait_event_interruptible(brd->state_wait,
- (brd->state & BOARD_READY));
+ (brd->state & BOARD_READY));
if (rc)
return rc;
@@ -4478,15 +4452,14 @@ static int dgap_tty_open(struct tty_struct *tty, struct file *file)
* Initialize if neither terminal or printer is open.
*/
if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
-
ch->ch_mforce = 0;
ch->ch_mval = 0;
/*
* Flush input queue.
*/
- head = readw(&(bs->rx_head));
- writew(head, &(bs->rx_tail));
+ head = readw(&bs->rx_head);
+ writew(head, &bs->rx_tail);
ch->ch_flags = 0;
ch->pscan_state = 0;
@@ -4595,7 +4568,6 @@ static void dgap_tty_close(struct tty_struct *tty, struct file *file)
*/
if ((ch->ch_open_count == 0) &&
!(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
-
ch->ch_flags &= ~(CH_RXBLOCK);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
@@ -4616,15 +4588,15 @@ static void dgap_tty_close(struct tty_struct *tty, struct file *file)
* If we have HUPCL set, lower DTR and RTS
*/
if (ch->ch_c_cflag & HUPCL) {
- ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
- dgap_cmdb(ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0);
+ ch->ch_mostat &= ~(D_RTS(ch) | D_DTR(ch));
+ dgap_cmdb(ch, SMODEM, 0, D_DTR(ch) | D_RTS(ch), 0);
/*
* Go to sleep to ensure RTS/DTR
* have been dropped for modems to see it.
*/
spin_unlock_irqrestore(&ch->ch_lock,
- lock_flags);
+ lock_flags);
/* .25 second delay for dropping RTS/DTR */
schedule_timeout_interruptible(msecs_to_jiffies(250));
@@ -4635,7 +4607,6 @@ static void dgap_tty_close(struct tty_struct *tty, struct file *file)
ch->pscan_state = 0;
ch->pscan_savechar = 0;
ch->ch_baud_info = 0;
-
}
/*
@@ -4643,7 +4614,7 @@ static void dgap_tty_close(struct tty_struct *tty, struct file *file)
*/
if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
dgap_wmove(ch, ch->ch_digi.digi_offstr,
- (int) ch->ch_digi.digi_offlen);
+ (int)ch->ch_digi.digi_offlen);
ch->ch_flags &= ~CH_PRON;
}
@@ -4778,7 +4749,7 @@ static void dgap_tty_flush_chars(struct tty_struct *tty)
* The usual assortment of ioctl's
*/
static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
struct board_t *bd;
struct channel_t *ch;
@@ -4787,7 +4758,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
u16 head;
ulong lock_flags = 0;
ulong lock_flags2 = 0;
- void __user *uarg = (void __user *) arg;
+ void __user *uarg = (void __user *)arg;
if (!tty || tty->magic != TTY_MAGIC)
return -ENODEV;
@@ -4814,9 +4785,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
}
switch (cmd) {
-
/* Here are all the standard ioctl's that we MUST implement */
-
case TCSBRK:
/*
* TCSBRK is SVID version: non-zero arg --> no break
@@ -4841,7 +4810,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
spin_lock_irqsave(&ch->ch_lock, lock_flags2);
if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP))
- dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+ dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -4868,7 +4837,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
spin_lock_irqsave(&bd->bd_lock, lock_flags);
spin_lock_irqsave(&ch->ch_lock, lock_flags2);
- dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+ dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -4895,7 +4864,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
spin_lock_irqsave(&bd->bd_lock, lock_flags);
spin_lock_irqsave(&ch->ch_lock, lock_flags2);
- dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+ dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0);
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -4919,13 +4888,13 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
return put_user(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long __user *) arg);
+ (unsigned long __user *)arg);
case TIOCSSOFTCAR:
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- rc = get_user(arg, (unsigned long __user *) arg);
+ rc = get_user(arg, (unsigned long __user *)arg);
if (rc)
return rc;
@@ -4974,9 +4943,9 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
if (!(un->un_type == DGAP_PRINT)) {
- head = readw(&(ch->ch_bs->rx_head));
- writew(head, &(ch->ch_bs->rx_tail));
- writeb(0, &(ch->ch_bs->orun));
+ head = readw(&ch->ch_bs->rx_head);
+ writew(head, &ch->ch_bs->rx_tail);
+ writeb(0, &ch->ch_bs->orun);
}
}
@@ -4989,15 +4958,15 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
}
ch->ch_flags &= ~CH_STOP;
- head = readw(&(ch->ch_bs->tx_head));
- dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+ head = readw(&ch->ch_bs->tx_head);
+ dgap_cmdw(ch, FLUSHTX, (u16)head, 0);
dgap_cmdw(ch, RESUMETX, 0, 0);
- if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
- ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+ if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) {
+ ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY);
wake_up_interruptible(&ch->ch_tun.un_flags_wait);
}
- if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
- ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+ if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) {
+ ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY);
wake_up_interruptible(&ch->ch_pun.un_flags_wait);
}
if (waitqueue_active(&tty->write_wait))
@@ -5025,8 +4994,8 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
if (cmd == TCSETSF) {
/* flush rx */
ch->ch_flags &= ~CH_STOP;
- head = readw(&(ch->ch_bs->rx_head));
- writew(head, &(ch->ch_bs->rx_tail));
+ head = readw(&ch->ch_bs->rx_head);
+ writew(head, &ch->ch_bs->rx_tail);
}
/* now wait for all the output to drain */
@@ -5066,7 +5035,6 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
}
switch (arg) {
-
case TCOON:
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -5104,7 +5072,6 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
/* set information for ditty */
if (cmd == (DIGI_SETAW)) {
-
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
rc = dgap_wait_for_drain(tty);
@@ -5839,14 +5806,12 @@ static ssize_t dgap_tty_name_show(struct device *d,
cn = ch->ch_portnum;
for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
if ((cptr->type == BNODE) &&
((cptr->u.board.type == APORT2_920P) ||
(cptr->u.board.type == APORT4_920P) ||
(cptr->u.board.type == APORT8_920P) ||
(cptr->u.board.type == PAPORT4) ||
(cptr->u.board.type == PAPORT8))) {
-
found = TRUE;
if (cptr->u.board.v_start)
starto = cptr->u.board.start;
@@ -5875,7 +5840,6 @@ static ssize_t dgap_tty_name_show(struct device *d,
}
if (cptr->type == CNODE) {
-
for (i = 0; i < cptr->u.conc.nport; i++) {
if (cn != (i + ncount))
continue;
@@ -5892,7 +5856,6 @@ static ssize_t dgap_tty_name_show(struct device *d,
}
if (cptr->type == MNODE) {
-
for (i = 0; i < cptr->u.module.nport; i++) {
if (cn != (i + ncount))
continue;
@@ -5936,31 +5899,31 @@ static struct attribute *dgap_sysfs_tty_entries[] = {
static void dgap_create_ports_sysfiles(struct board_t *bd)
{
dev_set_drvdata(&bd->pdev->dev, bd);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
- device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_state);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_baud);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
+ device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount);
}
/* removes all the sys files created for that port */
static void dgap_remove_ports_sysfiles(struct board_t *bd)
{
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
- device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_state);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
+ device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount);
}
/*
@@ -6021,7 +5984,7 @@ static int dgap_test_bios(struct board_t *brd)
brd->wait_for_bios = 0;
while (brd->wait_for_bios < 1000) {
/* Check to see if BIOS thinks board is good. (GD). */
- if (word == *(u16 *) "GD")
+ if (word == *(u16 *)"GD")
return 0;
msleep_interruptible(10);
brd->wait_for_bios++;
@@ -6032,7 +5995,7 @@ static int dgap_test_bios(struct board_t *brd)
err1 = readw(addr + SEQUENCE);
err2 = readw(addr + ERROR);
dev_warn(&brd->pdev->dev, "%s failed diagnostics. Error #(%x,%x).\n",
- brd->name, err1, err2);
+ brd->name, err1, err2);
brd->state = BOARD_FAILED;
brd->dpastatus = BD_NOBIOS;
@@ -6082,7 +6045,6 @@ static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len)
writel(0xbfc01004, (addr + 0xc34));
writel(0x3, (addr + 0xc30));
-
}
/*
@@ -6108,12 +6070,12 @@ static int dgap_test_fep(struct board_t *brd)
brd->wait_for_fep = 0;
while (brd->wait_for_fep < 500) {
/* Check to see if FEP is up and running now. */
- if (word == *(u16 *) "OS") {
+ if (word == *(u16 *)"OS") {
/*
* Check to see if the board can support FEP5+ commands.
*/
word = readw(addr + FEP5_PLUS);
- if (word == *(u16 *) "5A")
+ if (word == *(u16 *)"5A")
brd->bd_flags |= BD_FEP5PLUS;
return 0;
@@ -6157,7 +6119,6 @@ static void dgap_do_reset_board(struct board_t *brd)
if (check == FEPRST)
break;
udelay(10);
-
}
if (i > 1000) {
dev_warn(&brd->pdev->dev,
@@ -6200,8 +6161,8 @@ static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len)
vaddr = brd->re_map_membase;
- offset = readw((u16 *) (vaddr + DOWNREQ));
- to_dp = (struct downld_t *) (vaddr + (int) offset);
+ offset = readw((u16 *)(vaddr + DOWNREQ));
+ to_dp = (struct downld_t *)(vaddr + (int)offset);
memcpy_toio(to_dp, uaddr, len);
/* Tell card we have data for it */
@@ -6254,7 +6215,6 @@ static void dgap_get_vpd(struct board_t *brd)
* the first 2 bytes (header) should be 0x55, 0xAA
*/
if (byte1 == 0x55 && byte2 == 0xAA) {
-
base_offset = 0;
/*
@@ -6262,7 +6222,6 @@ static void dgap_get_vpd(struct board_t *brd)
* for the VPD offset.
*/
while (base_offset <= EXPANSION_ROM_SIZE) {
-
/*
* Lots of magic numbers here.
*
@@ -6406,7 +6365,6 @@ static void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
return;
dev_set_drvdata(c, un);
-
}
static void dgap_remove_tty_sysfs(struct device *c)
@@ -6442,7 +6400,6 @@ static int dgap_tty_register_ports(struct board_t *brd)
ch = brd->channels[0];
for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
-
struct device *classp;
classp = tty_port_register_device(&brd->serial_ports[i],
@@ -6546,7 +6503,6 @@ static int dgap_request_irq(struct board_t *brd)
* Set up our interrupt handler if we are set to do interrupts.
*/
if (dgap_config_get_useintr(brd) && brd->irq) {
-
rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
if (!rc)
@@ -6574,7 +6530,7 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
if (fw_info[card_type].conf_name) {
ret = request_firmware(&fw, fw_info[card_type].conf_name,
- &pdev->dev);
+ &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "config file %s not found\n",
fw_info[card_type].conf_name);
@@ -6627,7 +6583,7 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
if (fw_info[card_type].bios_name) {
ret = request_firmware(&fw, fw_info[card_type].bios_name,
- &pdev->dev);
+ &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "bios file %s not found\n",
fw_info[card_type].bios_name);
@@ -6644,7 +6600,7 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
if (fw_info[card_type].fep_name) {
ret = request_firmware(&fw, fw_info[card_type].fep_name,
- &pdev->dev);
+ &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "dgap: fep file %s not found\n",
fw_info[card_type].fep_name);
@@ -6665,7 +6621,7 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
* is requesting a concentrator image from us.
*/
if ((bd->type == PCX) || (bd->type == PEPC)) {
- chk_addr = (u16 *) (vaddr + DOWNREQ);
+ chk_addr = (u16 *)(vaddr + DOWNREQ);
/* Nonzero if FEP is requesting concentrator image. */
check = readw(chk_addr);
vaddr = brd->re_map_membase;
@@ -6673,14 +6629,14 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
if (fw_info[card_type].con_name && check && vaddr) {
ret = request_firmware(&fw, fw_info[card_type].con_name,
- &pdev->dev);
+ &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "conc file %s not found\n",
fw_info[card_type].con_name);
return ret;
}
/* Put concentrator firmware loading code here */
- offset = readw((u16 *) (vaddr + DOWNREQ));
+ offset = readw((u16 *)(vaddr + DOWNREQ));
memcpy_toio(offset, fw->data, fw->size);
dgap_do_conc_load(brd, (char *)fw->data, fw->size)
@@ -6763,14 +6719,13 @@ static int dgap_tty_init(struct board_t *brd)
ch = brd->channels[0];
vaddr = brd->re_map_membase;
- bs = (struct bs_t __iomem *) ((ulong) vaddr + CHANBUF);
- cm = (struct cm_t __iomem *) ((ulong) vaddr + CMDBUF);
+ bs = (struct bs_t __iomem *)((ulong)vaddr + CHANBUF);
+ cm = (struct cm_t __iomem *)((ulong)vaddr + CMDBUF);
brd->bd_bs = bs;
/* Set up channel variables */
for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
-
spin_lock_init(&ch->ch_lock);
/* Store all our magic numbers */
@@ -6804,12 +6759,12 @@ static int dgap_tty_init(struct board_t *brd)
ch->ch_dsr = DM_DSR;
}
- ch->ch_taddr = vaddr + (ioread16(&(ch->ch_bs->tx_seg)) << 4);
- ch->ch_raddr = vaddr + (ioread16(&(ch->ch_bs->rx_seg)) << 4);
+ ch->ch_taddr = vaddr + (ioread16(&ch->ch_bs->tx_seg) << 4);
+ ch->ch_raddr = vaddr + (ioread16(&ch->ch_bs->rx_seg) << 4);
ch->ch_tx_win = 0;
ch->ch_rx_win = 0;
- ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
- ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
+ ch->ch_tsize = readw(&ch->ch_bs->tx_max) + 1;
+ ch->ch_rsize = readw(&ch->ch_bs->rx_max) + 1;
ch->ch_tstart = 0;
ch->ch_rstart = 0;
@@ -6827,7 +6782,7 @@ static int dgap_tty_init(struct board_t *brd)
dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
- ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
+ ch->ch_mistat = readb(&ch->ch_bs->m_stat);
init_waitqueue_head(&ch->ch_flags_wait);
init_waitqueue_head(&ch->ch_tun.un_flags_wait);
@@ -6835,18 +6790,18 @@ static int dgap_tty_init(struct board_t *brd)
/* Turn on all modem interrupts for now */
modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
- writeb(modem, &(ch->ch_bs->m_int));
+ writeb(modem, &ch->ch_bs->m_int);
/*
* Set edelay to 0 if interrupts are turned on,
* otherwise set edelay to the usual 100.
*/
if (brd->intr_used)
- writew(0, &(ch->ch_bs->edelay));
+ writew(0, &ch->ch_bs->edelay);
else
- writew(100, &(ch->ch_bs->edelay));
+ writew(100, &ch->ch_bs->edelay);
- writeb(1, &(ch->ch_bs->idata));
+ writeb(1, &ch->ch_bs->idata);
}
return 0;
@@ -7038,8 +6993,8 @@ static int dgap_start(void)
}
device = device_create(dgap_class, NULL,
- MKDEV(DIGI_DGAP_MAJOR, 0),
- NULL, "dgap_mgmt");
+ MKDEV(DIGI_DGAP_MAJOR, 0),
+ NULL, "dgap_mgmt");
if (IS_ERR(device)) {
rc = PTR_ERR(device);
goto failed_device;
diff --git a/drivers/staging/dgnc/dgnc_utils.c b/drivers/staging/dgnc/dgnc_utils.c
index f76de82908d3..95272f4765fc 100644
--- a/drivers/staging/dgnc/dgnc_utils.c
+++ b/drivers/staging/dgnc/dgnc_utils.c
@@ -1,7 +1,6 @@
#include <linux/tty.h>
#include <linux/sched.h>
#include "dgnc_utils.h"
-#include "digi.h"
/*
* dgnc_ms_sleep()
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 049274738a2e..4e6c16af40fc 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -211,7 +211,7 @@ static u32 _nbu2ss_get_begin_ram_address(struct nbu2ss_udc *udc)
}
if ((data >> 16) > last_ram_adr)
- last_ram_adr = data>>16;
+ last_ram_adr = data >> 16;
}
return last_ram_adr + use_ram_size;
@@ -1267,7 +1267,7 @@ static int _nbu2ss_start_transfer(
/* EPn */
if (ep->direct == USB_DIR_OUT) {
/* OUT */
- if (bflag == FALSE)
+ if (!bflag)
nret = _nbu2ss_epn_out_transfer(udc, ep, req);
} else {
/* IN */
@@ -1509,7 +1509,7 @@ static inline int _nbu2ss_req_feature(struct nbu2ss_udc *udc, bool bset)
if (0x0000 == (wIndex & 0xFF70)) {
if (selector == USB_ENDPOINT_HALT) {
ep_adrs = wIndex & 0xFF;
- if (bset == FALSE) {
+ if (!bset) {
_nbu2ss_endpoint_toggle_reset(
udc, ep_adrs);
}
@@ -1756,7 +1756,7 @@ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc)
}
}
- if (bcall_back == FALSE) {
+ if (!bcall_back) {
if (udc->ep0state == EP0_IN_STATUS_PHASE) {
if (nret >= 0) {
/*--------------------------------------*/
@@ -2044,7 +2044,7 @@ static inline void _nbu2ss_epn_in_dma_int(
preq = &req->req;
- if (req->dma_flag == FALSE)
+ if (!req->dma_flag)
return;
preq->actual += req->div_len;
@@ -2756,7 +2756,7 @@ static int nbu2ss_ep_queue(
bflag = list_empty(&ep->queue);
list_add_tail(&req->queue, &ep->queue);
- if ((bflag != FALSE) && (ep->stalled == FALSE)) {
+ if (bflag && !ep->stalled) {
result = _nbu2ss_start_transfer(udc, ep, req, FALSE);
if (result < 0) {
diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c
index dc7d304fccc6..085e9872c46d 100644
--- a/drivers/staging/fbtft/fb_st7789v.c
+++ b/drivers/staging/fbtft/fb_st7789v.c
@@ -15,9 +15,11 @@
*/
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
@@ -30,14 +32,6 @@
/**
* enum st7789v_command - ST7789V display controller commands
*
- * @SLPOUT: sleep out
- * @DISPOFF: display off
- * @DISPON: display on
- * @CASET: column address set
- * @RASET: row address set
- * @RAMRW: memory write
- * @MADCTL: memory data access control
- * @COLMOD: interface pixel format
* @PORCTRL: porch setting
* @GCTRL: gate control
* @VCOMS: VCOM setting
@@ -54,16 +48,10 @@
*
* Note that the ST7789V display controller offers quite a few more commands
* which have been omitted from this list as they are not used at the moment.
+ * Furthermore, commands that are compliant with the MIPI DCS have been left
+ * out as well to avoid duplicate entries.
*/
enum st7789v_command {
- SLPOUT = 0x11,
- DISPOFF = 0x28,
- DISPON = 0x29,
- CASET = 0x2A,
- RASET = 0x2B,
- RAMRW = 0x2C,
- MADCTL = 0x36,
- COLMOD = 0x3A,
PORCTRL = 0xB2,
GCTRL = 0xB7,
VCOMS = 0xBB,
@@ -82,78 +70,66 @@ enum st7789v_command {
#define MADCTL_MY BIT(7) /* bitmask for page address order */
/**
- * default_init_sequence - default initialization sequence for ST7789V
+ * init_display() - initialize the display controller
*
- * Most of the commands in this init sequence set their parameters to the
+ * @par: FBTFT parameter object
+ *
+ * Most of the commands in this init function set their parameters to the
* same default values which are already in place after the display has been
* powered up. (The main exception to this rule is the pixel format which
* would default to 18 instead of 16 bit per pixel.)
* Nonetheless, this sequence can be used as a template for concrete
* displays which usually need some adjustments.
+ *
+ * Return: 0 on success, < 0 if error occurred.
*/
-static int default_init_sequence[] = {
+static int init_display(struct fbtft_par *par)
+{
/* turn off sleep mode */
- -1, SLPOUT,
- -2, 120,
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
+ mdelay(120);
/* set pixel format to RGB-565 */
- -1, COLMOD, 0x05,
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
- -1, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22,
+ write_reg(par, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22);
/*
* VGH = 13.26V
* VGL = -10.43V
*/
- -1, GCTRL, 0x35,
+ write_reg(par, GCTRL, 0x35);
/*
* VDV and VRH register values come from command write
* (instead of NVM)
*/
- -1, VDVVRHEN, 0x01, 0xFF,
+ write_reg(par, VDVVRHEN, 0x01, 0xFF);
/*
* VAP = 4.1V + (VCOM + VCOM offset + 0.5 * VDV)
* VAN = -4.1V + (VCOM + VCOM offset + 0.5 * VDV)
*/
- -1, VRHS, 0x0B,
+ write_reg(par, VRHS, 0x0B);
/* VDV = 0V */
- -1, VDVS, 0x20,
+ write_reg(par, VDVS, 0x20);
/* VCOM = 0.9V */
- -1, VCOMS, 0x20,
+ write_reg(par, VCOMS, 0x20);
/* VCOM offset = 0V */
- -1, VCMOFSET, 0x20,
+ write_reg(par, VCMOFSET, 0x20);
/*
* AVDD = 6.8V
* AVCL = -4.8V
* VDS = 2.3V
*/
- -1, PWCTRL1, 0xA4, 0xA1,
-
- -1, DISPON,
-
- -3,
-};
+ write_reg(par, PWCTRL1, 0xA4, 0xA1);
-/**
- * set_addr_win() - configure display area to use
- *
- * @par: FBTFT parameter object
- * @xs: first active pixel of x-axis
- * @ys: first active pixel of y-axis
- * @xe: last active pixel of x-axis
- * @ye: last active pixel of y-axis
- */
-static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
-{
- write_reg(par, CASET, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
- write_reg(par, RASET, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
- write_reg(par, RAMRW);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
+ return 0;
}
/**
@@ -184,7 +160,7 @@ static int set_var(struct fbtft_par *par)
default:
return -EINVAL;
}
- write_reg(par, MADCTL, madctl_par);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, madctl_par);
return 0;
}
@@ -256,9 +232,9 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves)
static int blank(struct fbtft_par *par, bool on)
{
if (on)
- write_reg(par, DISPOFF);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
else
- write_reg(par, DISPON);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
return 0;
}
@@ -266,12 +242,11 @@ static struct fbtft_display display = {
.regwidth = 8,
.width = 240,
.height = 320,
- .init_sequence = default_init_sequence,
.gamma_num = 2,
.gamma_len = 14,
.gamma = DEFAULT_GAMMA,
.fbtftops = {
- .set_addr_win = set_addr_win,
+ .init_display = init_display,
.set_var = set_var,
.set_gamma = set_gamma,
.blank = blank,
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index 20e69f0b5cb0..3ccdec94fee7 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -327,7 +327,6 @@ MODULE_DEVICE_TABLE(of, dt_ids); \
static struct spi_driver fbtft_driver_spi_driver = { \
.driver = { \
.name = _name, \
- .owner = THIS_MODULE, \
.of_match_table = of_match_ptr(dt_ids), \
}, \
.probe = fbtft_driver_probe_spi, \
diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c
index 0e501d093251..071f79bd19f3 100644
--- a/drivers/staging/fbtft/fbtft_device.c
+++ b/drivers/staging/fbtft/fbtft_device.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
@@ -132,11 +133,11 @@ static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
static int cberry28_init_sequence[] = {
/* turn off sleep mode */
- -1, 0x11,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 120,
/* set pixel format to RGB-565 */
- -1, 0x3A, 0x05,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT,
-1, 0xB2, 0x0C, 0x0C, 0x00, 0x33, 0x33,
@@ -161,20 +162,20 @@ static int cberry28_init_sequence[] = {
/* VDV = 0V */
-1, 0xC4, 0x20,
- /* VCOM = 0.875V */
- -1, 0xBB, 0x1F,
+ /* VCOM = 0.675V */
+ -1, 0xBB, 0x17,
/* VCOM offset = 0V */
-1, 0xC5, 0x20,
/*
- * AVDD = 6.6V
+ * AVDD = 6.8V
* AVCL = -4.8V
* VDS = 2.3V
*/
- -1, 0xD0, 0xA4, 0x61,
+ -1, 0xD0, 0xA4, 0xA1,
- -1, 0x29,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
-3,
};
diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c
index 704b78c78f13..ce0d254148e4 100644
--- a/drivers/staging/fbtft/flexfb.c
+++ b/drivers/staging/fbtft/flexfb.c
@@ -573,7 +573,6 @@ static int flexfb_remove_pdev(struct platform_device *pdev)
static struct spi_driver flexfb_spi_driver = {
.driver = {
.name = DRVNAME,
- .owner = THIS_MODULE,
},
.probe = flexfb_probe_spi,
.remove = flexfb_remove_spi,
diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
index a9ead0d7f9c3..2c4cd70b4cbb 100644
--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
+++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
@@ -482,7 +482,7 @@ int __init dprc_driver_init(void)
return fsl_mc_driver_register(&dprc_driver);
}
-void __exit dprc_driver_exit(void)
+void dprc_driver_exit(void)
{
fsl_mc_driver_unregister(&dprc_driver);
}
diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
index 2c4cc794be7a..c706f778626e 100644
--- a/drivers/staging/fsl-mc/include/mc-private.h
+++ b/drivers/staging/fsl-mc/include/mc-private.h
@@ -103,7 +103,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev);
int __init dprc_driver_init(void);
-void __exit dprc_driver_exit(void);
+void dprc_driver_exit(void);
int __init fsl_mc_allocator_driver_init(void);
diff --git a/drivers/staging/ft1000/Kconfig b/drivers/staging/ft1000/Kconfig
deleted file mode 100644
index c54b4e83d6e9..000000000000
--- a/drivers/staging/ft1000/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-config FT1000
- tristate "Drivers for Flarion ft1000 devices"
-
-if FT1000
-
-config FT1000_USB
- tristate "Driver for ft1000 usb devices."
- depends on USB
- depends on NET
- help
- Say Y if you want to have support for Qleadtek FLASH-OFDM USB Modem [LR7F04],
- Qleadtek Express Card or Leadtek Multi-band modem HSDPA.
-
-config FT1000_PCMCIA
- tristate "Driver for ft1000 pcmcia device."
- depends on PCMCIA
- depends on NET
- help
- Say Y if you want to have support for Flarion card also called
- Multimedia Net Card.
-
-endif
diff --git a/drivers/staging/ft1000/Makefile b/drivers/staging/ft1000/Makefile
deleted file mode 100644
index 3e987770a142..000000000000
--- a/drivers/staging/ft1000/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_FT1000_USB) += ft1000-usb/
-obj-$(CONFIG_FT1000_PCMCIA) += ft1000-pcmcia/
-
diff --git a/drivers/staging/ft1000/TODO b/drivers/staging/ft1000/TODO
deleted file mode 100644
index 1d346bc4f443..000000000000
--- a/drivers/staging/ft1000/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO:
- - checkpatch.pl cleanups
- - coding style
- - sparse fixes
- - adapt to latest usb and pcmcia api changes
- - change firmware loading for usb driver to proper kernel method (request_firmware)
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-Cc: Marek Belisko <marek.belisko@gmail.com>
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/Makefile b/drivers/staging/ft1000/ft1000-pcmcia/Makefile
deleted file mode 100644
index 715de3f00e33..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_FT1000_PCMCIA) = ft1000_pcmcia.o
-ft1000_pcmcia-y := ft1000_hw.o ft1000_dnld.o ft1000_cs.o
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/boot.h b/drivers/staging/ft1000/ft1000-pcmcia/boot.h
deleted file mode 100644
index e4a698528520..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/boot.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, 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. 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.
- ---------------------------------------------------------------------------
-
- File: boot.h
-
- Description: boatloader
-
- History:
- 1/11/05 Whc Ported to Linux.
-
- ---------------------------------------------------------------------------*/
-#ifndef _BOOTH_
-#define _BOOTH_
-
-/* Official bootloader */
-static unsigned char bootimage[] = {
- 0x00, 0x00, 0x01, 0x5E, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0xD7,
- 0x00, 0x00, 0x01, 0x5E, 0x46, 0xB3,
- 0xE6, 0x02, 0x00, 0x98, 0xE6, 0x8C,
- 0x00, 0x98, 0xFB, 0x92, 0xFF, 0xFF,
- 0x98, 0xFB, 0x94, 0xFF, 0xFF, 0x98,
- 0xFB, 0x06, 0x08, 0x00, 0x98, 0xFB,
- 0x96, 0x84, 0x00, 0x98, 0xFB, 0x08,
- 0x1C, 0x00, 0x98, 0xFB, 0x51, 0x25,
- 0x10, 0x1C, 0x00, 0xE6, 0x51, 0x01,
- 0x07, 0xFD, 0x4C, 0xFF, 0x20, 0xF5,
- 0x51, 0x02, 0x20, 0x08, 0x00, 0x4C,
- 0xFF, 0x20, 0x3C, 0x00, 0xC0, 0x64,
- 0x98, 0xC0, 0x66, 0x98, 0xC0, 0x68,
- 0x98, 0xC0, 0x6A, 0x98, 0xC0, 0x6C,
- 0x98, 0x90, 0x08, 0x90, 0x09, 0x90,
- 0x0A, 0x90, 0x0B, 0x90, 0x0C, 0x90,
- 0x0D, 0x90, 0x0E, 0x90, 0x0F, 0x90,
- 0x04, 0x90, 0x06, 0xFB, 0x51, 0x22,
- 0x16, 0x08, 0x03, 0xFB, 0x51, 0x52,
- 0x16, 0x08, 0x04, 0xFB, 0x51, 0x24,
- 0x2B, 0x08, 0x06, 0xFB, 0x51, 0x54,
- 0x2B, 0x08, 0x07, 0xFB, 0x51, 0x24,
- 0x2B, 0x08, 0x09, 0xFB, 0x51, 0x54,
- 0x2B, 0x08, 0x0A, 0xFB, 0x51, 0x12,
- 0x16, 0x08, 0x0C, 0xFB, 0x51, 0x52,
- 0x16, 0x08, 0x0D, 0x78, 0x00, 0x00,
- 0x00, 0x16, 0x00, 0x00, 0xEC, 0x31,
- 0xAE, 0x00, 0x00, 0x81, 0x4C, 0x0F,
- 0xE6, 0x43, 0xFF, 0xEC, 0x31, 0x4E,
- 0x00, 0x00, 0x91, 0xEC, 0x31, 0xAE,
- 0x00, 0x00, 0x91, 0x4C, 0x0F, 0xE6,
- 0x43, 0xFF, 0xEC, 0x31, 0x5E, 0x00,
- 0x00, 0xA1, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xA6, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xAC, 0x3C, 0x00, 0xEB, 0x31,
- 0x08, 0x00, 0x00, 0xA8, 0x76, 0xFE,
- 0xFE, 0x08, 0xEB, 0x31, 0x08, 0x20,
- 0x00, 0x00, 0x76, 0xFF, 0xFF, 0x18,
- 0xED, 0x31, 0x08, 0x20, 0x00, 0x00,
- 0x26, 0x10, 0x04, 0x10, 0xF5, 0x3C,
- 0x01, 0x3C, 0x00, 0x08, 0x01, 0x12,
- 0x3C, 0x11, 0x3C, 0x00, 0x08, 0x01,
- 0x0B, 0x08, 0x00, 0x6D, 0xEC, 0x31,
- 0xAE, 0x20, 0x00, 0x06, 0xED, 0x4D,
- 0x08, 0x00, 0x00, 0x67, 0x80, 0x6F,
- 0x00, 0x01, 0x0B, 0x6F, 0x00, 0x02,
- 0x2E, 0x76, 0xEE, 0x01, 0x48, 0x06,
- 0x01, 0x39, 0xED, 0x4D, 0x18, 0x00,
- 0x02, 0xED, 0x4D, 0x08, 0x00, 0x04,
- 0x14, 0x06, 0xA4, 0xED, 0x31, 0x22,
- 0x00, 0x00, 0xAC, 0x76, 0xEE, 0x07,
- 0x48, 0x6D, 0x22, 0x01, 0x1E, 0x08,
- 0x01, 0x58, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xAC, 0x06, 0xFF, 0xBA, 0x3C,
- 0x00, 0xEB, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0x3C, 0x30, 0xEB, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0x04,
- 0x10, 0xF7, 0xED, 0x31, 0x08, 0x00,
- 0x00, 0xA2, 0x91, 0x00, 0x9C, 0x3C,
- 0x80, 0xEB, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0x3C, 0x20, 0xEB, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0x04,
- 0x10, 0xF7, 0xED, 0x31, 0x08, 0x20,
- 0x00, 0x04, 0x42, 0x10, 0x90, 0x08,
- 0xEC, 0x31, 0xAE, 0x20, 0x00, 0x06,
- 0xA4, 0x41, 0x08, 0x00, 0xB6, 0xED,
- 0x41, 0x28, 0x7D, 0xFF, 0xFF, 0x22,
- 0xB3, 0x40, 0x98, 0x2A, 0x32, 0xEB,
- 0x41, 0x28, 0xB4, 0x43, 0xFC, 0x05,
- 0xFF, 0xE6, 0xA0, 0x31, 0x20, 0x00,
- 0x06, 0xEB, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0x3C, 0x20, 0xEB, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0x04,
- 0x10, 0xF7, 0xED, 0x31, 0x08, 0x20,
- 0x00, 0x04, 0x42, 0x10, 0x90, 0x08,
- 0xEC, 0x31, 0xAE, 0x20, 0x00, 0x06,
- 0xA4, 0x41, 0x08, 0x00, 0x68, 0xED,
- 0x41, 0x28, 0x7D, 0xFF, 0xFF, 0x22,
- 0xB3, 0x40, 0x98, 0x2A, 0x32, 0xEB,
- 0x41, 0x28, 0xB4, 0x43, 0xFC, 0x05,
- 0xFF, 0xE6, 0x48, 0x04, 0xEB, 0x31,
- 0x08, 0x20, 0x00, 0x04, 0xEB, 0x31,
- 0x18, 0x20, 0x00, 0x02, 0x3C, 0x11,
- 0xEB, 0x31, 0x18, 0x20, 0x00, 0x00,
- 0xED, 0x31, 0x08, 0x20, 0x00, 0x00,
- 0x04, 0x10, 0xF7, 0xED, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x66, 0x00, 0x6F,
- 0x00, 0x01, 0x16, 0x76, 0xEE, 0x06,
- 0x48, 0x4A, 0x1E, 0x48, 0x04, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x04, 0xEB,
- 0x31, 0x08, 0x00, 0x00, 0xA4, 0x48,
- 0x04, 0xED, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0xEB, 0x31, 0x08, 0x00, 0x00,
- 0xA2, 0x48, 0x04, 0x20, 0x20, 0x4A,
- 0x7C, 0x46, 0x82, 0x50, 0x05, 0x50,
- 0x15, 0xB5, 0x1E, 0x98, 0xED, 0x31,
- 0x08, 0x00, 0x00, 0xA8, 0x10, 0x47,
- 0x3B, 0x2C, 0x01, 0xDB, 0x40, 0x11,
- 0x98, 0xC1, 0x1E, 0x98, 0x10, 0x07,
- 0x30, 0xF9, 0x40, 0x07, 0x18, 0x98,
- 0x2A, 0x10, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xA8, 0xA4, 0x1E, 0x98, 0xBB,
- 0x1E, 0x98, 0x50, 0x14, 0x50, 0x04,
- 0x46, 0x83, 0x48, 0x04, 0x02, 0x01,
- 0x00, 0x50, 0x05, 0x50, 0x15, 0x10,
- 0x87, 0x3F, 0x90, 0x2B, 0x18, 0x01,
- 0x00, 0xC0, 0x31, 0x00, 0x00, 0xAE,
- 0xDF, 0x41, 0x00, 0x08, 0x00, 0x1A,
- 0x42, 0x11, 0x67, 0x01, 0xDF, 0x41,
- 0x02, 0x08, 0x00, 0x10, 0x42, 0x11,
- 0x62, 0x01, 0xB4, 0x43, 0x4A, 0x68,
- 0x50, 0x14, 0x50, 0x04, 0x24, 0x10,
- 0x48, 0x04, 0xF2, 0x31, 0x00, 0x01,
- 0x00, 0x00, 0xAE, 0xF6, 0x31, 0x00,
- 0x01, 0x00, 0x00, 0xAE, 0x62, 0xE4,
- 0xE5, 0x61, 0x04, 0x48, 0x04, 0xE5,
- 0x63, 0x05, 0x48, 0x04, 0x20, 0x20,
- 0x00, 0x00, 0x00, 0x00
-};
-
-#endif
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
deleted file mode 100644
index e1861cf5de73..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, 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. 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.
- ---------------------------------------------------------------------------
- Description: Common structures and defines
- ---------------------------------------------------------------------------*/
-#ifndef _FT1000H_
-#define _FT1000H_
-
-#include "../ft1000.h"
-
-#define FT1000_DRV_VER 0x01010300
-
-#define FT1000_DPRAM_BASE 0x0000 /* Dual Port RAM starting offset */
-
-/*
- * Maximum number of occurrence of pseudo header errors before resetting PC
- * Card.
- */
-#define MAX_PH_ERR 300
-
-#define SUCCESS 0x00
-#define FAILURE 0x01
-
-struct ft1000_pcmcia {
- int PktIntfErr;
- u16 packetseqnum;
- void *link;
-};
-
-struct pcmcia_device;
-struct net_device;
-struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset);
-void stop_ft1000_card(struct net_device *dev);
-int card_download(struct net_device *dev, const u8 *pFileStart,
- size_t FileLength);
-
-u16 ft1000_read_dpram(struct net_device *dev, int offset);
-void card_bootload(struct net_device *dev);
-u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index);
-u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
-void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value);
-
-/* Read the value of a given ASIC register. */
-static inline u16 ft1000_read_reg(struct net_device *dev, u16 offset)
-{
- return inw(dev->base_addr + offset);
-}
-
-/* Set the value of a given ASIC register. */
-static inline void ft1000_write_reg(struct net_device *dev, u16 offset,
- u16 value)
-{
- outw(value, dev->base_addr + offset);
-}
-
-#endif
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img
deleted file mode 100644
index aad3c80d07c8..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img
+++ /dev/null
Binary files differ
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
deleted file mode 100644
index e5cc5bedf031..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
- Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
- Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds.
-
- This file was modified to support the Flarion Flash OFDM NIC Device
- by Wai Chan (w.chan@flarion.com).
-
- Port for kernel 2.6 created by Patrik Ostrihon (patrik.ostrihon@pwc.sk)
-
- 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-/*====================================================================*/
-
-MODULE_AUTHOR("Wai Chan");
-MODULE_DESCRIPTION("FT1000 PCMCIA driver");
-MODULE_LICENSE("GPL");
-
-/*====================================================================*/
-
-static int ft1000_config(struct pcmcia_device *link);
-static void ft1000_detach(struct pcmcia_device *link);
-static int ft1000_attach(struct pcmcia_device *link);
-
-#include "ft1000.h"
-
-/*====================================================================*/
-
-static void ft1000_reset(struct pcmcia_device *link)
-{
- pcmcia_reset_card(link->socket);
-}
-
-static int ft1000_attach(struct pcmcia_device *link)
-{
- link->priv = NULL;
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- return ft1000_config(link);
-}
-
-static void ft1000_detach(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- if (dev)
- stop_ft1000_card(dev);
-
- pcmcia_disable_device(link);
- free_netdev(dev);
-}
-
-static int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
-{
- return pcmcia_request_io(link);
-}
-
-/*======================================================================
-
- ft1000_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
- ======================================================================*/
-
-static int ft1000_config(struct pcmcia_device *link)
-{
- int ret;
-
- dev_dbg(&link->dev, "ft1000_cs: ft1000_config(0x%p)\n", link);
-
- /* setup IO window */
- ret = pcmcia_loop_config(link, ft1000_confcheck, NULL);
- if (ret) {
- dev_err(&link->dev, "Could not configure pcmcia\n");
- return -ENODEV;
- }
-
- /* configure device */
- ret = pcmcia_enable_device(link);
- if (ret) {
- dev_err(&link->dev, "Could not enable pcmcia\n");
- goto failed;
- }
-
- link->priv = init_ft1000_card(link, &ft1000_reset);
- if (!link->priv) {
- dev_err(&link->dev, "Could not register as network device\n");
- goto failed;
- }
-
- /* Finally, report what we've done */
-
- return 0;
-failed:
- pcmcia_disable_device(link);
- return -ENODEV;
-}
-
-static int ft1000_suspend(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- if (link->open)
- netif_device_detach(dev);
- return 0;
-}
-
-static int ft1000_resume(struct pcmcia_device *link)
-{
- return 0;
-}
-
-/*====================================================================*/
-
-static const struct pcmcia_device_id ft1000_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x0100),
- PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1000),
- PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1300),
- PCMCIA_DEVICE_NULL,
-};
-
-MODULE_DEVICE_TABLE(pcmcia, ft1000_ids);
-
-static struct pcmcia_driver ft1000_cs_driver = {
- .owner = THIS_MODULE,
- .name = "ft1000_cs",
- .probe = ft1000_attach,
- .remove = ft1000_detach,
- .id_table = ft1000_ids,
- .suspend = ft1000_suspend,
- .resume = ft1000_resume,
-};
-
-module_pcmcia_driver(ft1000_cs_driver);
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
deleted file mode 100644
index 612ac0bd3756..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, 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. 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.
- --------------------------------------------------------------------------
-
- Description: This module will handshake with the DSP bootloader to
- download the DSP runtime image.
-
- ---------------------------------------------------------------------------*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define __KERNEL_SYSCALLS__
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/unistd.h>
-#include <linux/netdevice.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-
-#include "ft1000.h"
-#include "boot.h"
-
-#define MAX_DSP_WAIT_LOOPS 100
-#define DSP_WAIT_SLEEP_TIME 1 /* 1 millisecond */
-
-#define MAX_LENGTH 0x7f0
-
-#define DWNLD_MAG_HANDSHAKE_LOC 0x00
-#define DWNLD_MAG_TYPE_LOC 0x01
-#define DWNLD_MAG_SIZE_LOC 0x02
-#define DWNLD_MAG_PS_HDR_LOC 0x03
-
-#define DWNLD_HANDSHAKE_LOC 0x02
-#define DWNLD_TYPE_LOC 0x04
-#define DWNLD_SIZE_MSW_LOC 0x06
-#define DWNLD_SIZE_LSW_LOC 0x08
-#define DWNLD_PS_HDR_LOC 0x0A
-
-#define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
-#define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */
-#define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */
-#define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */
-
-#define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
-#define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
-
-#define REQUEST_CODE_LENGTH 0x0000
-#define REQUEST_RUN_ADDRESS 0x0001
-#define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */
-#define REQUEST_DONE_BL 0x0003
-#define REQUEST_DONE_CL 0x0004
-#define REQUEST_VERSION_INFO 0x0005
-#define REQUEST_CODE_BY_VERSION 0x0006
-#define REQUEST_MAILBOX_DATA 0x0007
-#define REQUEST_FILE_CHECKSUM 0x0008
-
-#define STATE_START_DWNLD 0x01
-#define STATE_BOOT_DWNLD 0x02
-#define STATE_CODE_DWNLD 0x03
-#define STATE_DONE_DWNLD 0x04
-#define STATE_SECTION_PROV 0x05
-#define STATE_DONE_PROV 0x06
-#define STATE_DONE_FILE 0x07
-
-struct dsp_file_hdr {
- u32 version_id; /* Version ID of this image format. */
- u32 package_id; /* Package ID of code release. */
- u32 build_date; /* Date/time stamp when file was built. */
- u32 commands_offset; /* Offset to attached commands in Pseudo Hdr format. */
- u32 loader_offset; /* Offset to bootloader code. */
- u32 loader_code_address; /* Start address of bootloader. */
- u32 loader_code_end; /* Where bootloader code ends. */
- u32 loader_code_size;
- u32 version_data_offset; /* Offset were scrambled version data begins. */
- u32 version_data_size; /* Size, in words, of scrambled version data. */
- u32 nDspImages; /* Number of DSP images in file. */
-} __packed;
-
-struct dsp_image_info {
- u32 coff_date; /* Date/time when DSP Coff image was built. */
- u32 begin_offset; /* Offset in file where image begins. */
- u32 end_offset; /* Offset in file where image begins. */
- u32 run_address; /* On chip Start address of DSP code. */
- u32 image_size; /* Size of image. */
- u32 version; /* Embedded version # of DSP code. */
- unsigned short checksum; /* Dsp File checksum */
- unsigned short pad1;
-} __packed;
-
-void card_bootload(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u32 *pdata;
- u32 size;
- u32 i;
- u32 templong;
-
- netdev_dbg(dev, "card_bootload is called\n");
-
- pdata = (u32 *)bootimage;
- size = sizeof(bootimage);
-
- /* check for odd word */
- if (size & 0x0003)
- size += 4;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
-
- /* need to set i/o base address initially and hardware will autoincrement */
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_BASE);
- /* write bytes */
- for (i = 0; i < (size >> 2); i++) {
- templong = *pdata++;
- outl(templong, dev->base_addr + FT1000_REG_MAG_DPDATA);
- }
-
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-static u16 get_handshake(struct net_device *dev, u16 expected_value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 handshake;
- u32 tempx;
- int loopcnt;
-
- loopcnt = 0;
- while (loopcnt < MAX_DSP_WAIT_LOOPS) {
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_HANDSHAKE_LOC);
-
- handshake = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- } else {
- tempx =
- ntohl(ft1000_read_dpram_mag_32
- (dev, DWNLD_MAG_HANDSHAKE_LOC));
- handshake = (u16)tempx;
- }
-
- if ((handshake == expected_value)
- || (handshake == HANDSHAKE_RESET_VALUE)) {
- return handshake;
- }
- loopcnt++;
- mdelay(DSP_WAIT_SLEEP_TIME);
-
- }
-
- return HANDSHAKE_TIMEOUT_VALUE;
-
-}
-
-static void put_handshake(struct net_device *dev, u16 handshake_value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u32 tempx;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_HANDSHAKE_LOC);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, handshake_value); /* Handshake */
- } else {
- tempx = (u32)handshake_value;
- tempx = ntohl(tempx);
- ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx); /* Handshake */
- }
-}
-
-static u16 get_request_type(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 request_type;
- u32 tempx;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, DWNLD_TYPE_LOC);
- request_type = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- } else {
- tempx = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_TYPE_LOC);
- tempx = ntohl(tempx);
- request_type = (u16)tempx;
- }
-
- return request_type;
-
-}
-
-static long get_request_value(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- long value;
- u16 w_val;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_MSW_LOC);
-
- w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
-
- value = (long)(w_val << 16);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_LSW_LOC);
-
- w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
-
- value = (long)(value | w_val);
- } else {
- value = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC);
- value = ntohl(value);
- }
-
- return value;
-
-}
-
-static void put_request_value(struct net_device *dev, long lvalue)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 size;
- u32 tempx;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- size = (u16) (lvalue >> 16);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_MSW_LOC);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
-
- size = (u16) (lvalue);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_LSW_LOC);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
- } else {
- tempx = ntohl(lvalue);
- ft1000_write_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC, tempx); /* Handshake */
- }
-
-}
-
-static u16 hdr_checksum(struct pseudo_hdr *pHdr)
-{
- u16 *usPtr = (u16 *)pHdr;
- u16 chksum;
-
- chksum = (((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
- usPtr[4]) ^ usPtr[5]) ^ usPtr[6];
-
- return chksum;
-}
-
-int card_download(struct net_device *dev, const u8 *pFileStart,
- size_t FileLength)
-{
- struct ft1000_info *info = netdev_priv(dev);
- int Status = SUCCESS;
- u32 uiState;
- u16 handshake;
- struct pseudo_hdr *pHdr;
- u16 usHdrLength;
- long word_length;
- u16 request;
- u16 temp;
- struct prov_record *pprov_record;
- u8 *pbuffer;
- struct dsp_file_hdr *pFileHdr5;
- struct dsp_image_info *pDspImageInfoV6 = NULL;
- long requested_version;
- bool bGoodVersion = false;
- struct drv_msg *pMailBoxData;
- u16 *pUsData = NULL;
- u16 *pUsFile = NULL;
- u8 *pUcFile = NULL;
- u8 *pBootEnd = NULL;
- u8 *pCodeEnd = NULL;
- int imageN;
- long file_version;
- long loader_code_address = 0;
- long loader_code_size = 0;
- long run_address = 0;
- long run_size = 0;
- unsigned long flags;
- unsigned long templong;
- unsigned long image_chksum = 0;
-
- file_version = *(long *)pFileStart;
- if (file_version != 6) {
- pr_err("unsupported firmware version %ld\n", file_version);
- Status = FAILURE;
- }
-
- uiState = STATE_START_DWNLD;
-
- pFileHdr5 = (struct dsp_file_hdr *)pFileStart;
-
- pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->loader_offset);
- pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->loader_offset);
- pBootEnd = (u8 *) ((long)pFileStart + pFileHdr5->loader_code_end);
- loader_code_address = pFileHdr5->loader_code_address;
- loader_code_size = pFileHdr5->loader_code_size;
- bGoodVersion = false;
-
- while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) {
-
- switch (uiState) {
- case STATE_START_DWNLD:
-
- handshake = get_handshake(dev, HANDSHAKE_DSP_BL_READY);
-
- if (handshake == HANDSHAKE_DSP_BL_READY)
- put_handshake(dev, HANDSHAKE_DRIVER_READY);
- else
- Status = FAILURE;
-
- uiState = STATE_BOOT_DWNLD;
-
- break;
-
- case STATE_BOOT_DWNLD:
- handshake = get_handshake(dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- request = get_request_type(dev);
- switch (request) {
- case REQUEST_RUN_ADDRESS:
- put_request_value(dev,
- loader_code_address);
- break;
- case REQUEST_CODE_LENGTH:
- put_request_value(dev,
- loader_code_size);
- break;
- case REQUEST_DONE_BL:
- /* Reposition ptrs to beginning of code section */
- pUsFile = (u16 *) ((long)pBootEnd);
- pUcFile = (u8 *) ((long)pBootEnd);
- uiState = STATE_CODE_DWNLD;
- break;
- case REQUEST_CODE_SEGMENT:
- word_length = get_request_value(dev);
- if (word_length > MAX_LENGTH) {
- Status = FAILURE;
- break;
- }
- if ((word_length * 2 + (long)pUcFile) >
- (long)pBootEnd) {
- /*
- * Error, beyond boot code range.
- */
- Status = FAILURE;
- break;
- }
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock,
- flags);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsFile++;
- templong |=
- (*pUsFile++ << 16);
- pUcFile += 4;
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- spin_unlock_irqrestore(&info->
- dpram_lock,
- flags);
- break;
- default:
- Status = FAILURE;
- break;
- }
- put_handshake(dev, HANDSHAKE_RESPONSE);
- } else {
- Status = FAILURE;
- }
-
- break;
-
- case STATE_CODE_DWNLD:
- handshake = get_handshake(dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- request = get_request_type(dev);
- switch (request) {
- case REQUEST_FILE_CHECKSUM:
- netdev_dbg(dev,
- "ft1000_dnld: REQUEST_FOR_CHECKSUM\n");
- put_request_value(dev, image_chksum);
- break;
- case REQUEST_RUN_ADDRESS:
- if (bGoodVersion) {
- put_request_value(dev,
- run_address);
- } else {
- Status = FAILURE;
- break;
- }
- break;
- case REQUEST_CODE_LENGTH:
- if (bGoodVersion) {
- put_request_value(dev,
- run_size);
- } else {
- Status = FAILURE;
- break;
- }
- break;
- case REQUEST_DONE_CL:
- /* Reposition ptrs to beginning of provisioning section */
- pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->commands_offset);
- pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->commands_offset);
- uiState = STATE_DONE_DWNLD;
- break;
- case REQUEST_CODE_SEGMENT:
- if (!bGoodVersion) {
- Status = FAILURE;
- break;
- }
- word_length = get_request_value(dev);
- if (word_length > MAX_LENGTH) {
- Status = FAILURE;
- break;
- }
- if ((word_length * 2 + (long)pUcFile) >
- (long)pCodeEnd) {
- /*
- * Error, beyond boot code range.
- */
- Status = FAILURE;
- break;
- }
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsFile++;
- templong |=
- (*pUsFile++ << 16);
- pUcFile += 4;
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- break;
-
- case REQUEST_MAILBOX_DATA:
- /* Convert length from byte count to word count. Make sure we round up. */
- word_length =
- (long)(info->DSPInfoBlklen + 1) / 2;
- put_request_value(dev, word_length);
- pMailBoxData =
- (struct drv_msg *)&info->DSPInfoBlk[0];
- pUsData =
- (u16 *)&pMailBoxData->data[0];
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock,
- flags);
- if (file_version == 5) {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_ADDR,
- DWNLD_PS_HDR_LOC);
-
- for (; word_length > 0; word_length--) { /* In words */
- temp = ntohs(*pUsData);
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_DATA,
- temp);
- pUsData++;
- }
- } else {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
-
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsData++;
- templong |=
- (*pUsData++ << 16);
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- }
- spin_unlock_irqrestore(&info->
- dpram_lock,
- flags);
- break;
-
- case REQUEST_VERSION_INFO:
- word_length =
- pFileHdr5->version_data_size;
- put_request_value(dev, word_length);
- pUsFile =
- (u16 *) ((long)pFileStart +
- pFileHdr5->
- version_data_offset);
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock,
- flags);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong =
- ntohs(*pUsFile++);
- temp =
- ntohs(*pUsFile++);
- templong |=
- (temp << 16);
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- spin_unlock_irqrestore(&info->
- dpram_lock,
- flags);
- break;
-
- case REQUEST_CODE_BY_VERSION:
- bGoodVersion = false;
- requested_version =
- get_request_value(dev);
- pDspImageInfoV6 =
- (struct dsp_image_info *) ((long)
- pFileStart
- +
- sizeof
- (struct dsp_file_hdr));
- for (imageN = 0;
- imageN <
- pFileHdr5->nDspImages;
- imageN++) {
- temp = (u16)
- (pDspImageInfoV6->
- version);
- templong = temp;
- temp = (u16)
- (pDspImageInfoV6->
- version >> 16);
- templong |=
- (temp << 16);
- if (templong ==
- requested_version) {
- bGoodVersion =
- true;
- pUsFile =
- (u16
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- begin_offset);
- pUcFile =
- (u8
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- begin_offset);
- pCodeEnd =
- (u8
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- end_offset);
- run_address =
- pDspImageInfoV6->
- run_address;
- run_size =
- pDspImageInfoV6->
- image_size;
- image_chksum =
- (u32)
- pDspImageInfoV6->
- checksum;
- netdev_dbg(dev,
- "ft1000_dnld: image_chksum = 0x%8x\n",
- (unsigned
- int)
- image_chksum);
- break;
- }
- pDspImageInfoV6++;
- }
- if (!bGoodVersion) {
- /*
- * Error, beyond boot code range.
- */
- Status = FAILURE;
- break;
- }
- break;
-
- default:
- Status = FAILURE;
- break;
- }
- put_handshake(dev, HANDSHAKE_RESPONSE);
- } else {
- Status = FAILURE;
- }
-
- break;
-
- case STATE_DONE_DWNLD:
- if (((unsigned long)(pUcFile) - (unsigned long) pFileStart) >=
- (unsigned long)FileLength) {
- uiState = STATE_DONE_FILE;
- break;
- }
-
- pHdr = (struct pseudo_hdr *)pUsFile;
-
- if (pHdr->portdest == 0x80 /* DspOAM */
- && (pHdr->portsrc == 0x00 /* Driver */
- || pHdr->portsrc == 0x10 /* FMM */)) {
- uiState = STATE_SECTION_PROV;
- } else {
- netdev_dbg(dev,
- "Download error: Bad Port IDs in Pseudo Record\n");
- netdev_dbg(dev, "\t Port Source = 0x%2.2x\n",
- pHdr->portsrc);
- netdev_dbg(dev, "\t Port Destination = 0x%2.2x\n",
- pHdr->portdest);
- Status = FAILURE;
- }
-
- break;
-
- case STATE_SECTION_PROV:
-
- pHdr = (struct pseudo_hdr *)pUcFile;
-
- if (pHdr->checksum == hdr_checksum(pHdr)) {
- if (pHdr->portdest != 0x80 /* Dsp OAM */) {
- uiState = STATE_DONE_PROV;
- break;
- }
- usHdrLength = ntohs(pHdr->length); /* Byte length for PROV records */
-
- /* Get buffer for provisioning data */
- pbuffer =
- kmalloc(usHdrLength + sizeof(struct pseudo_hdr),
- GFP_ATOMIC);
- if (pbuffer) {
- memcpy(pbuffer, pUcFile,
- (u32) (usHdrLength +
- sizeof(struct pseudo_hdr)));
- /* link provisioning data */
- pprov_record =
- kmalloc(sizeof(struct prov_record),
- GFP_ATOMIC);
- if (pprov_record) {
- pprov_record->pprov_data =
- pbuffer;
- list_add_tail(&pprov_record->
- list,
- &info->prov_list);
- /* Move to next entry if available */
- pUcFile =
- (u8 *)((unsigned long) pUcFile +
- (unsigned long) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
- if ((unsigned long) (pUcFile) -
- (unsigned long) (pFileStart) >=
- (unsigned long)FileLength) {
- uiState =
- STATE_DONE_FILE;
- }
- } else {
- kfree(pbuffer);
- Status = FAILURE;
- }
- } else {
- Status = FAILURE;
- }
- } else {
- /* Checksum did not compute */
- Status = FAILURE;
- }
-
- break;
-
- case STATE_DONE_PROV:
- uiState = STATE_DONE_FILE;
- break;
-
- default:
- Status = FAILURE;
- break;
- } /* End Switch */
-
- } /* End while */
-
- return Status;
-
-}
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
deleted file mode 100644
index eecfa377054d..000000000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
+++ /dev/null
@@ -1,2068 +0,0 @@
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
- Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
- Copyright (C) 2006 ProWeb Consulting, a.s, 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. 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.
- -------------------------------------------------------------------------*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/ioport.h>
-#include <linux/wait.h>
-#include <linux/vmalloc.h>
-
-#include <linux/firmware.h>
-#include <linux/ethtool.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
-#include <pcmcia/ds.h>
-
-#include <linux/delay.h>
-#include "ft1000.h"
-
-static const struct firmware *fw_entry;
-
-static void ft1000_hbchk(u_long data);
-static struct timer_list poll_timer = {
- .function = ft1000_hbchk
-};
-
-static u16 cmdbuffer[1024];
-static u8 tempbuffer[1600];
-static u8 ft1000_card_present;
-static u8 flarion_ft1000_cnt;
-
-static irqreturn_t ft1000_interrupt(int irq, void *dev_id);
-static void ft1000_enable_interrupts(struct net_device *dev);
-static void ft1000_disable_interrupts(struct net_device *dev);
-
-/* new kernel */
-MODULE_AUTHOR("");
-MODULE_DESCRIPTION("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("FT1000");
-
-#define MAX_RCV_LOOP 100
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_fifo_len
- Description: This function will read the ASIC Uplink FIFO status register
- which will return the number of bytes remaining in the Uplink FIFO.
- Sixteen bytes are subtracted to make sure that the ASIC does not
- reach its threshold.
- Input:
- dev - network device structure
- Output:
- value - number of bytes available in the ASIC Uplink FIFO.
-
- -------------------------------------------------------------------------*/
-static inline u16 ft1000_read_fifo_len(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- if (info->AsicID == ELECTRABUZZ_ID)
- return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
- else
- return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_dpram
- Description: This function will read the specific area of dpram
- (Electrabuzz ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- Output:
- value - value of dpram
-
- -------------------------------------------------------------------------*/
-u16 ft1000_read_dpram(struct net_device *dev, int offset)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u16 data;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- return data;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_write_dpram
- Description: This function will write to a specific area of dpram
- (Electrabuzz ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- value - value to write
- Output:
- none.
-
- -------------------------------------------------------------------------*/
-static inline void ft1000_write_dpram(struct net_device *dev,
- int offset, u16 value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_dpram_mag_16
- Description: This function will read the specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- Output:
- value - value of dpram
-
- -------------------------------------------------------------------------*/
-u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u16 data;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- /* check if we want to read upper or lower 32-bit word */
- if (Index)
- data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL);
- else
- data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH);
-
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- return data;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_write_dpram_mag_16
- Description: This function will write to a specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- value - value to write
- Output:
- none.
-
- -------------------------------------------------------------------------*/
-static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
- int offset, u16 value, int Index)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- if (Index)
- ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value);
- else
- ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value);
-
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_dpram_mag_32
- Description: This function will read the specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- Output:
- value - value of dpram
-
- -------------------------------------------------------------------------*/
-u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u32 data;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- return data;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_write_dpram_mag_32
- Description: This function will write to a specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- value - value to write
- Output:
- none.
-
- -------------------------------------------------------------------------*/
-void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_enable_interrupts
- Description: This function will enable interrupts base on the current
- interrupt mask.
- Input:
- dev - device structure
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_enable_interrupts(struct net_device *dev)
-{
- u16 tempword;
-
- ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_DEFAULT_MASK);
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
- pr_debug("current interrupt enable mask = 0x%x\n", tempword);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_disable_interrupts
- Description: This function will disable all interrupts.
- Input:
- dev - device structure
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_disable_interrupts(struct net_device *dev)
-{
- u16 tempword;
-
- ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_MASK_ALL);
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
- pr_debug("current interrupt enable mask = 0x%x\n", tempword);
-}
-
-/*---------------------------------------------------------------------------
- Function: ft1000_read_dsp_timer
- Description: This function reads the DSP timer and stores its value in the
- DSP_TIME field of the ft1000_info struct passed as argument
- Input:
- dev - device structure
- info - ft1000_info structure
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_read_dsp_timer(struct net_device *dev,
- struct ft1000_info *info)
-{
- if (info->AsicID == ELECTRABUZZ_ID) {
- info->DSP_TIME[0] = ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
- info->DSP_TIME[1] = ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
- info->DSP_TIME[2] = ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
- info->DSP_TIME[3] = ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
- } else {
- info->DSP_TIME[0] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
- FT1000_MAG_DSP_TIMER0_INDX);
- info->DSP_TIME[1] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
- FT1000_MAG_DSP_TIMER1_INDX);
- info->DSP_TIME[2] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
- FT1000_MAG_DSP_TIMER2_INDX);
- info->DSP_TIME[3] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
- FT1000_MAG_DSP_TIMER3_INDX);
- }
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_reset_asic
- Description: This function will call the Card Service function to reset the
- ASIC.
- Input:
- dev - device structure
- Output:
- none
-
- -------------------------------------------------------------------------*/
-static void ft1000_reset_asic(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_pcmcia *pcmcia = info->priv;
- u16 tempword;
-
- (*info->ft1000_reset) (pcmcia->link);
-
- /*
- * Let's use the register provided by the Magnemite ASIC to reset the
- * ASIC and DSP.
- */
- if (info->AsicID == MAGNEMITE_ID) {
- ft1000_write_reg(dev, FT1000_REG_RESET,
- DSP_RESET_BIT | ASIC_RESET_BIT);
- }
- mdelay(1);
- if (info->AsicID == ELECTRABUZZ_ID) {
- /* set watermark to -1 in order to not generate an interrupt */
- ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff);
- } else {
- /* set watermark to -1 in order to not generate an interrupt */
- ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff);
- }
- /* clear interrupts */
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
- ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
-
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_reset_card
- Description: This function will reset the card
- Input:
- dev - device structure
- Output:
- status - false (card reset fail)
- true (card reset successful)
-
- -------------------------------------------------------------------------*/
-static int ft1000_reset_card(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 tempword;
- int i;
- unsigned long flags;
- struct prov_record *ptr;
- struct prov_record *tmp;
-
- info->CardReady = 0;
- info->ProgConStat = 0;
- info->squeseqnum = 0;
- ft1000_disable_interrupts(dev);
-
- /* del_timer(&poll_timer); */
-
- /* Make sure we free any memory reserve for provisioning */
- list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
- pr_debug("deleting provisioning record\n");
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- pr_debug("resetting DSP\n");
- ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
- } else {
- pr_debug("resetting ASIC and DSP\n");
- ft1000_write_reg(dev, FT1000_REG_RESET,
- DSP_RESET_BIT | ASIC_RESET_BIT);
- }
-
- /* Copy DSP session record into info block if this is not a coldstart */
- if (ft1000_card_present == 1) {
- spin_lock_irqsave(&info->dpram_lock, flags);
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC; i++) {
- info->DSPSess.Rec[i] =
- ft1000_read_reg(dev,
- FT1000_REG_DPRAM_DATA);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
- info->DSPSess.MagRec[i] =
- inl(dev->base_addr
- + FT1000_REG_MAG_DPDATA);
- }
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
- }
-
- pr_debug("resetting ASIC\n");
- mdelay(10);
- /* reset ASIC */
- ft1000_reset_asic(dev);
-
- pr_debug("downloading dsp image\n");
-
- if (info->AsicID == MAGNEMITE_ID) {
- /* Put dsp in reset and take ASIC out of reset */
- pr_debug("Put DSP in reset and take ASIC out of reset\n");
- ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
-
- /* Setting MAGNEMITE ASIC to big endian mode */
- ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE);
- /* Download bootloader */
- card_bootload(dev);
-
- /* Take DSP out of reset */
- ft1000_write_reg(dev, FT1000_REG_RESET, 0);
- /* FLARION_DSP_ACTIVE; */
- mdelay(10);
- pr_debug("Take DSP out of reset\n");
-
- /*
- * Wait for 0xfefe indicating dsp ready before starting
- * download
- */
- for (i = 0; i < 50; i++) {
- tempword = ft1000_read_dpram_mag_16(dev,
- FT1000_MAG_DPRAM_FEFE,
- FT1000_MAG_DPRAM_FEFE_INDX);
- if (tempword == 0xfefe)
- break;
- mdelay(20);
- }
-
- if (i == 50) {
- pr_debug("No FEFE detected from DSP\n");
- return false;
- }
-
- } else {
- /* Take DSP out of reset */
- ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT);
- mdelay(10);
- }
-
- if (card_download(dev, fw_entry->data, fw_entry->size)) {
- pr_debug("card download unsuccessful\n");
- return false;
- }
- pr_debug("card download successful\n");
-
- mdelay(10);
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- /*
- * Need to initialize the FIFO length counter to zero in order
- * to sync up with the DSP
- */
- info->fifo_cnt = 0;
- ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt);
- /* Initialize DSP heartbeat area to ho */
- ft1000_write_dpram(dev, FT1000_HI_HO, ho);
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- pr_debug("hi_ho value = 0x%x\n", tempword);
- } else {
- /* Initialize DSP heartbeat area to ho */
- ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag,
- FT1000_MAG_HI_HO_INDX);
- tempword =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX);
- pr_debug("hi_ho value = 0x%x\n", tempword);
- }
-
- info->CardReady = 1;
- ft1000_enable_interrupts(dev);
-
- /* Schedule heartbeat process to run every 2 seconds */
- /* poll_timer.expires = jiffies + (2*HZ); */
- /* poll_timer.data = (u_long)dev; */
- /* add_timer(&poll_timer); */
-
- return true;
-
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_chkcard
- Description: This function will check if the device is presently available on
- the system.
- Input:
- dev - device structure
- Output:
- status - false (device is not present)
- true (device is present)
-
- -------------------------------------------------------------------------*/
-static int ft1000_chkcard(struct net_device *dev)
-{
- u16 tempword;
-
- /*
- * Mask register is used to check for device presence since it is never
- * set to zero.
- */
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
- if (tempword == 0) {
- pr_debug("IMASK = 0 Card not detected\n");
- return false;
- }
- /*
- * The system will return the value of 0xffff for the version register
- * if the device is not present.
- */
- tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
- if (tempword == 0xffff) {
- pr_debug("Version = 0xffff Card not detected\n");
- return false;
- }
- return true;
-}
-
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_hbchk
- Description: This function will perform the heart beat check of the DSP as
- well as the ASIC.
- Input:
- dev - device structure
- Output:
- none
-
- -------------------------------------------------------------------------*/
-static void ft1000_hbchk(u_long data)
-{
- struct net_device *dev = (struct net_device *)data;
-
- struct ft1000_info *info;
- u16 tempword;
-
- info = netdev_priv(dev);
-
- if (info->CardReady == 1) {
- /* Perform dsp heartbeat check */
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- } else {
- tempword =
- ntohs(ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
- pr_debug("hi_ho value = 0x%x\n", tempword);
- /* Let's perform another check if ho is not detected */
- if (tempword != ho) {
- if (info->AsicID == ELECTRABUZZ_ID)
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- else
- tempword = ntohs(ft1000_read_dpram_mag_16(dev,
- FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
- if (tempword != ho) {
- pr_info("heartbeat failed - no ho detected\n");
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_HB_INFO;
- if (ft1000_reset_card(dev) == 0) {
- pr_info("Hardware Failure Detected - PC Card disabled\n");
- info->ProgConStat = 0xff;
- return;
- }
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2*HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
- return;
- }
-
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- /* Let's check doorbell again if fail */
- if (tempword & FT1000_DB_HB)
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
-
- if (tempword & FT1000_DB_HB) {
- pr_info("heartbeat doorbell not clear by firmware\n");
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_HB_INFO;
- if (ft1000_reset_card(dev) == 0) {
- pr_info("Hardware Failure Detected - PC Card disabled\n");
- info->ProgConStat = 0xff;
- return;
- }
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2*HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
- return;
- }
- /*
- * Set dedicated area to hi and ring appropriate doorbell
- * according to hi/ho heartbeat protocol
- */
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_dpram(dev, FT1000_HI_HO, hi);
- } else {
- ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag,
- FT1000_MAG_HI_HO_INDX);
- }
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- } else {
- tempword =
- ntohs(ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
- /* Let's write hi again if fail */
- if (tempword != hi) {
- if (info->AsicID == ELECTRABUZZ_ID)
- ft1000_write_dpram(dev, FT1000_HI_HO, hi);
- else
- ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO,
- hi_mag, FT1000_MAG_HI_HO_INDX);
-
- if (info->AsicID == ELECTRABUZZ_ID)
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- else
- tempword = ntohs(ft1000_read_dpram_mag_16(dev,
- FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
-
- if (tempword != hi) {
- pr_info("heartbeat failed - cannot write hi into DPRAM\n");
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_HB_INFO;
- if (ft1000_reset_card(dev) == 0) {
- pr_info("Hardware Failure Detected - PC Card disabled\n");
- info->ProgConStat = 0xff;
- return;
- }
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2*HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
- return;
- }
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_HB);
-
- }
-
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2 * HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_send_cmd
- Description:
- Input:
- Output:
-
- -------------------------------------------------------------------------*/
-static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size,
- u16 qtype)
-{
- struct ft1000_info *info = netdev_priv(dev);
- int i;
- u16 tempword;
- unsigned long flags;
-
- size += sizeof(struct pseudo_hdr);
- /* check for odd byte and increment to 16-bit word align value */
- if ((size & 0x0001))
- size++;
- pr_debug("total length = %d\n", size);
- pr_debug("length = %d\n", ntohs(*ptempbuffer));
- /*
- * put message into slow queue area
- * All messages are in the form total_len + pseudo header + message body
- */
- spin_lock_irqsave(&info->dpram_lock, flags);
-
- /* Make sure SLOWQ doorbell is clear */
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- i = 0;
- while (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- i++;
- if (i == 10) {
- spin_unlock_irqrestore(&info->dpram_lock, flags);
- return;
- }
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- }
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_TX_BASE);
- /* Write total length to dpram */
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
- /* Write pseudo header and messgae body */
- for (i = 0; i < (size >> 1); i++) {
- pr_debug("data %d = 0x%x\n", i, *ptempbuffer);
- tempword = htons(*ptempbuffer++);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, tempword);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_TX_BASE);
- /* Write total length to dpram */
- ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size));
- /* Write pseudo header and messgae body */
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_TX_BASE + 1);
- for (i = 0; i < (size >> 2); i++) {
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++,
- dev->base_addr + FT1000_REG_MAG_DPDATAL);
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++,
- dev->base_addr + FT1000_REG_MAG_DPDATAH);
- }
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAL);
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAH);
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- /* ring doorbell to notify DSP that we have a message ready */
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_receive_cmd
- Description: This function will read a message from the dpram area.
- Input:
- dev - network device structure
- pbuffer - caller supply address to buffer
- pnxtph - pointer to next pseudo header
- Output:
- Status = 0 (unsuccessful)
- = 1 (successful)
-
- -------------------------------------------------------------------------*/
-static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer,
- int maxsz, u16 *pnxtph)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 size;
- u16 *ppseudohdr;
- int i;
- u16 tempword;
- unsigned long flags;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- size = ft1000_read_dpram(dev, *pnxtph)
- + sizeof(struct pseudo_hdr);
- } else {
- size = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_PH_LEN,
- FT1000_MAG_PH_LEN_INDX))
- + sizeof(struct pseudo_hdr);
- }
- if (size > maxsz) {
- pr_debug("Invalid command length = %d\n", size);
- return false;
- }
- ppseudohdr = (u16 *)pbuffer;
- spin_lock_irqsave(&info->dpram_lock, flags);
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE + 2);
- for (i = 0; i <= (size >> 1); i++) {
- tempword =
- ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- *pbuffer++ = ntohs(tempword);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE);
- *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
- pr_debug("received data = 0x%x\n", *pbuffer);
- pbuffer++;
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE + 1);
- for (i = 0; i <= (size >> 2); i++) {
- *pbuffer =
- inw(dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- pbuffer++;
- *pbuffer =
- inw(dev->base_addr +
- FT1000_REG_MAG_DPDATAH);
- pbuffer++;
- }
- /* copy odd aligned word */
- *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
- pr_debug("received data = 0x%x\n", *pbuffer);
- pbuffer++;
- *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
- pr_debug("received data = 0x%x\n", *pbuffer);
- pbuffer++;
- }
- if (size & 0x0001) {
- /* copy odd byte from fifo */
- tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- *pbuffer = ntohs(tempword);
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- /*
- * Check if pseudo header checksum is good
- * Calculate pseudo header checksum
- */
- tempword = *ppseudohdr++;
- for (i = 1; i < 7; i++)
- tempword ^= *ppseudohdr++;
- if (tempword != *ppseudohdr) {
- pr_debug("Pseudo header checksum mismatch\n");
- /* Drop this message */
- return false;
- }
- return true;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_proc_drvmsg
- Description: This function will process the various driver messages.
- Input:
- dev - device structure
- pnxtph - pointer to next pseudo header
- Output:
- none
-
- -------------------------------------------------------------------------*/
-static void ft1000_proc_drvmsg(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 msgtype;
- u16 tempword;
- struct media_msg *pmediamsg;
- struct dsp_init_msg *pdspinitmsg;
- struct drv_msg *pdrvmsg;
- u16 len;
- u16 i;
- struct prov_record *ptr;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- struct timeval tv;
- union {
- u8 byte[2];
- u16 wrd;
- } convert;
-
- if (info->AsicID == ELECTRABUZZ_ID)
- tempword = FT1000_DPRAM_RX_BASE+2;
- else
- tempword = FT1000_DPRAM_MAG_RX_BASE;
-
- if (ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword)) {
-
- /*
- * Get the message type which is total_len + PSEUDO header
- * + msgtype + message body
- */
- pdrvmsg = (struct drv_msg *)&cmdbuffer[0];
- msgtype = ntohs(pdrvmsg->type);
- pr_debug("Command message type = 0x%x\n", msgtype);
- switch (msgtype) {
- case DSP_PROVISION:
- pr_debug("Got a provisioning request message from DSP\n");
- mdelay(25);
- while (list_empty(&info->prov_list) == 0) {
- pr_debug("Sending a provisioning message\n");
- /* Make sure SLOWQ doorbell is clear */
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DOORBELL);
- i = 0;
- while (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(5);
- i++;
- if (i == 10)
- break;
- }
- ptr = list_entry(info->prov_list.next,
- struct prov_record, list);
- len = *(u16 *)ptr->pprov_data;
- len = htons(len);
-
- pmsg = (u16 *)ptr->pprov_data;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- pr_debug("checksum = 0x%x\n",
- ppseudo_hdr->checksum);
- for (i = 1; i < 7; i++) {
- ppseudo_hdr->checksum ^= *pmsg++;
- pr_debug("checksum = 0x%x\n",
- ppseudo_hdr->checksum);
- }
-
- ft1000_send_cmd(dev, (u16 *)ptr->pprov_data,
- len, SLOWQ_TYPE);
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
- /*
- * Indicate adapter is ready to take application
- * messages after all provisioning messages are sent
- */
- info->CardReady = 1;
- break;
- case MEDIA_STATE:
- pmediamsg = (struct media_msg *)&cmdbuffer[0];
- if (info->ProgConStat != 0xFF) {
- if (pmediamsg->state) {
- pr_debug("Media is up\n");
- if (info->mediastate == 0) {
- netif_carrier_on(dev);
- netif_wake_queue(dev);
- info->mediastate = 1;
- do_gettimeofday(&tv);
- info->ConTm = tv.tv_sec;
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- info->ConTm = 0;
- }
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- info->ConTm = 0;
- }
- }
- break;
- case DSP_INIT_MSG:
- pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[0];
- memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
- pr_debug("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
- info->DspVer[0], info->DspVer[1],
- info->DspVer[2], info->DspVer[3]);
- memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
- HWSERNUMSZ);
- memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
- memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
- dev->dev_addr[0] = info->eui64[0];
- dev->dev_addr[1] = info->eui64[1];
- dev->dev_addr[2] = info->eui64[2];
- dev->dev_addr[3] = info->eui64[5];
- dev->dev_addr[4] = info->eui64[6];
- dev->dev_addr[5] = info->eui64[7];
-
- if (ntohs(pdspinitmsg->length) ==
- (sizeof(struct dsp_init_msg) - 20)) {
- memcpy(info->ProductMode,
- pdspinitmsg->ProductMode, MODESZ);
- memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
- CALVERSZ);
- memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
- CALDATESZ);
- pr_debug("RFCalVer = 0x%2x 0x%2x\n",
- info->RfCalVer[0], info->RfCalVer[1]);
- }
-
- break;
- case DSP_STORE_INFO:
- pr_debug("Got DSP_STORE_INFO\n");
- tempword = ntohs(pdrvmsg->length);
- info->DSPInfoBlklen = tempword;
- if (tempword < (MAX_DSP_SESS_REC - 4)) {
- pmsg = (u16 *)&pdrvmsg->data[0];
- for (i = 0; i < ((tempword + 1) / 2); i++) {
- pr_debug("dsp info data = 0x%x\n",
- *pmsg);
- info->DSPInfoBlk[i + 10] = *pmsg++;
- }
- }
- break;
- case DSP_GET_INFO:
- pr_debug("Got DSP_GET_INFO\n");
- /*
- * copy dsp info block to dsp
- * allow any outstanding ioctl to finish
- */
- mdelay(10);
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- mdelay(10);
- }
-
- if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
- /*
- * Put message into Slow Queue
- * Form Pseudo header
- */
- pmsg = (u16 *)info->DSPInfoBlk;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- ppseudo_hdr->length =
- htons(info->DSPInfoBlklen + 4);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- info->DSPInfoBlk[8] = 0x7200;
- info->DSPInfoBlk[9] =
- htons(info->DSPInfoBlklen);
- ft1000_send_cmd(dev, info->DSPInfoBlk,
- (u16)(info->DSPInfoBlklen+4),
- 0);
- }
-
- break;
- case GET_DRV_ERR_RPT_MSG:
- pr_debug("Got GET_DRV_ERR_RPT_MSG\n");
- /*
- * copy driver error message to dsp
- * allow any outstanding ioctl to finish
- */
- mdelay(10);
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- mdelay(10);
- }
-
- if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
- /*
- * Put message into Slow Queue
- * Form Pseudo header
- */
- pmsg = (u16 *)&tempbuffer[0];
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- ppseudo_hdr->length = htons(0x0012);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- pmsg = (u16 *)&tempbuffer[16];
- *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
- *pmsg++ = htons(0x000e);
- *pmsg++ = htons(info->DSP_TIME[0]);
- *pmsg++ = htons(info->DSP_TIME[1]);
- *pmsg++ = htons(info->DSP_TIME[2]);
- *pmsg++ = htons(info->DSP_TIME[3]);
- convert.byte[0] = info->DspVer[0];
- convert.byte[1] = info->DspVer[1];
- *pmsg++ = convert.wrd;
- convert.byte[0] = info->DspVer[2];
- convert.byte[1] = info->DspVer[3];
- *pmsg++ = convert.wrd;
- *pmsg++ = htons(info->DrvErrNum);
-
- ft1000_send_cmd(dev, (u16 *)&tempbuffer[0],
- (u16)(0x0012), 0);
- info->DrvErrNum = 0;
- }
-
- break;
- default:
- break;
- }
- }
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_parse_dpram_msg
- Description: This function will parse the message received from the DSP
- via the DPRAM interface.
- Input:
- dev - device structure
- Output:
- status - FAILURE
- SUCCESS
-
- -------------------------------------------------------------------------*/
-static int ft1000_parse_dpram_msg(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 doorbell;
- u16 portid;
- u16 nxtph;
- u16 total_len;
- int i = 0;
- unsigned long flags;
-
- doorbell = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- pr_debug("Doorbell = 0x%x\n", doorbell);
-
- if (doorbell & FT1000_ASIC_RESET_REQ) {
- /* Copy DSP session record from info block */
- spin_lock_irqsave(&info->dpram_lock, flags);
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC; i++) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA,
- info->DSPSess.Rec[i]);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
- outl(info->DSPSess.MagRec[i],
- dev->base_addr + FT1000_REG_MAG_DPDATA);
- }
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- /* clear ASIC RESET request */
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_ASIC_RESET_REQ);
- pr_debug("Got an ASIC RESET Request\n");
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_ASIC_RESET_DSP);
-
- if (info->AsicID == MAGNEMITE_ID) {
- /* Setting MAGNEMITE ASIC to big endian mode */
- ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
- HOST_INTF_BE);
- }
- }
-
- if (doorbell & FT1000_DSP_ASIC_RESET) {
- pr_debug("Got a dsp ASIC reset message\n");
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_DSP_ASIC_RESET);
- udelay(200);
- return SUCCESS;
- }
-
- if (doorbell & FT1000_DB_DPRAM_RX) {
- pr_debug("Got a slow queue message\n");
- nxtph = FT1000_DPRAM_RX_BASE + 2;
- if (info->AsicID == ELECTRABUZZ_ID) {
- total_len =
- ft1000_read_dpram(dev, FT1000_DPRAM_RX_BASE);
- } else {
- total_len =
- ntohs(ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_TOTAL_LEN,
- FT1000_MAG_TOTAL_LEN_INDX));
- }
- pr_debug("total length = %d\n", total_len);
- if ((total_len < MAX_CMD_SQSIZE)
- && (total_len > sizeof(struct pseudo_hdr))) {
- total_len += nxtph;
- /*
- * ft1000_read_reg will return a value that needs to be
- * byteswap in order to get DSP_QID_OFFSET.
- */
- if (info->AsicID == ELECTRABUZZ_ID) {
- portid = (ft1000_read_dpram(dev, DSP_QID_OFFSET
- + FT1000_DPRAM_RX_BASE + 2)
- >> 8) & 0xff;
- } else {
- portid =
- ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_PORT_ID,
- FT1000_MAG_PORT_ID_INDX) & 0xff;
- }
- pr_debug("DSP_QID = 0x%x\n", portid);
-
- if (portid == DRIVERID) {
- /*
- * We are assumming one driver message from the
- * DSP at a time.
- */
- ft1000_proc_drvmsg(dev);
- }
- }
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_RX);
- }
-
- if (doorbell & FT1000_DB_COND_RESET) {
- /* Reset ASIC and DSP */
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_CONDRESET_INFO;
- pr_debug("DSP conditional reset requested\n");
- ft1000_reset_card(dev);
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_DB_COND_RESET);
- }
- /* let's clear any unexpected doorbells from DSP */
- doorbell =
- doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ |
- FT1000_DB_COND_RESET | 0xff00);
- if (doorbell) {
- pr_debug("Clearing unexpected doorbell = 0x%x\n", doorbell);
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, doorbell);
- }
-
- return SUCCESS;
-
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_flush_fifo
- Description: This function will flush one packet from the downlink
- FIFO.
- Input:
- dev - device structure
- drv_err - driver error causing the flush fifo
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_pcmcia *pcmcia = info->priv;
- u16 i;
- u32 templong;
- u16 tempword;
-
- if (pcmcia->PktIntfErr > MAX_PH_ERR) {
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DrvErrNum;
- ft1000_reset_card(dev);
- return;
- }
- /* Flush corrupted pkt from FIFO */
- i = 0;
- do {
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword =
- ft1000_read_reg(dev, FT1000_REG_DFIFO);
- tempword =
- ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
- } else {
- templong =
- inl(dev->base_addr + FT1000_REG_MAG_DFR);
- tempword =
- inw(dev->base_addr + FT1000_REG_MAG_DFSR);
- }
- i++;
- /*
- * This should never happen unless the ASIC is broken.
- * We must reset to recover.
- */
- if ((i > 2048) || (tempword == 0)) {
- ft1000_read_dsp_timer(dev, info);
- if (tempword == 0) {
- /*
- * Let's check if ASIC reads are still ok by
- * reading the Mask register which is never zero
- * at this point of the code.
- */
- tempword =
- inw(dev->base_addr +
- FT1000_REG_SUP_IMASK);
- if (tempword == 0) {
- /*
- * This indicates that we can not
- * communicate with the ASIC
- */
- info->DrvErrNum = FIFO_FLUSH_BADCNT;
- } else {
- /*
- * Let's assume that we really flush
- * the FIFO
- */
- pcmcia->PktIntfErr++;
- return;
- }
- } else {
- info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
- }
- return;
- }
- tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
- } while ((tempword & 0x03) != 0x03);
- if (info->AsicID == ELECTRABUZZ_ID) {
- i++;
- pr_debug("Flushing FIFO complete = %x\n", tempword);
- /* Flush last word in FIFO. */
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- /* Update FIFO counter for DSP */
- i = i * 2;
- pr_debug("Flush Data byte count to dsp = %d\n", i);
- info->fifo_cnt += i;
- ft1000_write_dpram(dev, FT1000_FIFO_LEN,
- info->fifo_cnt);
- } else {
- pr_debug("Flushing FIFO complete = %x\n", tempword);
- /* Flush last word in FIFO */
- templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
- tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
- pr_debug("FT1000_REG_SUP_STAT = 0x%x\n", tempword);
- tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
- pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
- }
- if (DrvErrNum)
- pcmcia->PktIntfErr++;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_copy_up_pkt
- Description: This function will pull Flarion packets out of the Downlink
- FIFO and convert it to an ethernet packet. The ethernet packet will
- then be deliver to the TCP/IP stack.
- Input:
- dev - device structure
- Output:
- status - FAILURE
- SUCCESS
-
- -------------------------------------------------------------------------*/
-static int ft1000_copy_up_pkt(struct net_device *dev)
-{
- u16 tempword;
- struct ft1000_info *info = netdev_priv(dev);
- u16 len;
- struct sk_buff *skb;
- u16 i;
- u8 *pbuffer = NULL;
- u8 *ptemp = NULL;
- u16 chksum;
- u32 *ptemplong;
- u32 templong;
-
- /* Read length */
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- len = tempword;
- } else {
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- len = ntohs(tempword);
- }
- chksum = tempword;
- pr_debug("Number of Bytes in FIFO = %d\n", len);
-
- if (len > ENET_MAX_SIZE) {
- pr_debug("size of ethernet packet invalid\n");
- if (info->AsicID == MAGNEMITE_ID) {
- /* Read High word to complete 32 bit access */
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- }
- ft1000_flush_fifo(dev, DSP_PKTLEN_INFO);
- info->stats.rx_errors++;
- return FAILURE;
- }
-
- skb = dev_alloc_skb(len + 12 + 2);
-
- if (skb == NULL) {
- /* Read High word to complete 32 bit access */
- if (info->AsicID == MAGNEMITE_ID)
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
-
- ft1000_flush_fifo(dev, 0);
- info->stats.rx_errors++;
- return FAILURE;
- }
- pbuffer = (u8 *)skb_put(skb, len + 12);
-
- /* Pseudo header */
- if (info->AsicID == ELECTRABUZZ_ID) {
- for (i = 1; i < 7; i++) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- chksum ^= tempword;
- }
- /* read checksum value */
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- } else {
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- /* read checksum value */
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- }
-
- if (chksum != tempword) {
- pr_debug("Packet checksum mismatch 0x%x 0x%x\n",
- chksum, tempword);
- ft1000_flush_fifo(dev, DSP_PKTPHCKSUM_INFO);
- info->stats.rx_errors++;
- kfree_skb(skb);
- return FAILURE;
- }
- /* subtract the number of bytes read already */
- ptemp = pbuffer;
-
- /* fake MAC address */
- *pbuffer++ = dev->dev_addr[0];
- *pbuffer++ = dev->dev_addr[1];
- *pbuffer++ = dev->dev_addr[2];
- *pbuffer++ = dev->dev_addr[3];
- *pbuffer++ = dev->dev_addr[4];
- *pbuffer++ = dev->dev_addr[5];
- *pbuffer++ = 0x00;
- *pbuffer++ = 0x07;
- *pbuffer++ = 0x35;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xfe;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- for (i = 0; i < len / 2; i++) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- *pbuffer++ = (u8) (tempword >> 8);
- *pbuffer++ = (u8)tempword;
- if (ft1000_chkcard(dev) == false) {
- kfree_skb(skb);
- return FAILURE;
- }
- }
-
- /* Need to read one more word if odd byte */
- if (len & 0x0001) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- *pbuffer++ = (u8) (tempword >> 8);
- }
- } else {
- ptemplong = (u32 *)pbuffer;
- for (i = 0; i < len / 4; i++) {
- templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
- pr_debug("Data = 0x%8x\n", templong);
- *ptemplong++ = templong;
- }
-
- /* Need to read one more word if odd align. */
- if (len & 0x0003) {
- templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
- pr_debug("Data = 0x%8x\n", templong);
- *ptemplong++ = templong;
- }
-
- }
-
- pr_debug("Data passed to Protocol layer:\n");
- for (i = 0; i < len + 12; i++)
- pr_debug("Protocol Data: 0x%x\n", *ptemp++);
-
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
-
- info->stats.rx_packets++;
- /* Add on 12 bytes for MAC address which was removed */
- info->stats.rx_bytes += (len + 12);
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- /* track how many bytes have been read from FIFO - round up to
- * 16 bit word */
- tempword = len + 16;
- if (tempword & 0x01)
- tempword++;
- info->fifo_cnt += tempword;
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_FIFO_LEN);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, info->fifo_cnt);
- }
-
- return SUCCESS;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_copy_down_pkt
- Description: This function will take an ethernet packet and convert it to
- a Flarion packet prior to sending it to the ASIC Downlink
- FIFO.
- Input:
- dev - device structure
- packet - address of ethernet packet
- len - length of IP packet
- Output:
- status - FAILURE
- SUCCESS
-
- -------------------------------------------------------------------------*/
-static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_pcmcia *pcmcia = info->priv;
- union {
- struct pseudo_hdr blk;
- u16 buff[sizeof(struct pseudo_hdr) >> 1];
- u8 buffc[sizeof(struct pseudo_hdr)];
- } pseudo;
- int i;
- u32 *plong;
-
- /* Check if there is room on the FIFO */
- if (len > ft1000_read_fifo_len(dev)) {
- udelay(10);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev)) {
- pr_debug("Transmit FIFO is full - pkt drop\n");
- info->stats.tx_errors++;
- return SUCCESS;
- }
- }
- /* Create pseudo header and send pseudo/ip to hardware */
- if (info->AsicID == ELECTRABUZZ_ID)
- pseudo.blk.length = len;
- else
- pseudo.blk.length = ntohs(len);
-
- pseudo.blk.source = DSPID; /* Need to swap to get in correct
- order */
- pseudo.blk.destination = HOSTID;
- pseudo.blk.portdest = NETWORKID; /* Need to swap to get in
- correct order */
- pseudo.blk.portsrc = DSPAIRID;
- pseudo.blk.sh_str_id = 0;
- pseudo.blk.control = 0;
- pseudo.blk.rsvd1 = 0;
- pseudo.blk.seq_num = 0;
- pseudo.blk.rsvd2 = pcmcia->packetseqnum++;
- pseudo.blk.qos_class = 0;
- /* Calculate pseudo header checksum */
- pseudo.blk.checksum = pseudo.buff[0];
- for (i = 1; i < 7; i++)
- pseudo.blk.checksum ^= pseudo.buff[i];
-
- /* Production Mode */
- if (info->AsicID == ELECTRABUZZ_ID) {
- /* copy first word to UFIFO_BEG reg */
- ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]);
- pr_debug("data 0 BEG = 0x%04x\n", pseudo.buff[0]);
-
- /* copy subsequent words to UFIFO_MID reg */
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]);
- pr_debug("data 1 MID = 0x%04x\n", pseudo.buff[1]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[2]);
- pr_debug("data 2 MID = 0x%04x\n", pseudo.buff[2]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[3]);
- pr_debug("data 3 MID = 0x%04x\n", pseudo.buff[3]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[4]);
- pr_debug("data 4 MID = 0x%04x\n", pseudo.buff[4]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[5]);
- pr_debug("data 5 MID = 0x%04x\n", pseudo.buff[5]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[6]);
- pr_debug("data 6 MID = 0x%04x\n", pseudo.buff[6]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[7]);
- pr_debug("data 7 MID = 0x%04x\n", pseudo.buff[7]);
-
- /* Write PPP type + IP Packet into Downlink FIFO */
- for (i = 0; i < (len >> 1) - 1; i++) {
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
- htons(*packet));
- pr_debug("data %d MID = 0x%04x\n",
- i + 8, htons(*packet));
- packet++;
- }
-
- /* Check for odd byte */
- if (len & 0x0001) {
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
- htons(*packet));
- pr_debug("data MID = 0x%04x\n", htons(*packet));
- packet++;
- ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
- htons(*packet));
- pr_debug("data %d MID = 0x%04x\n",
- i + 8, htons(*packet));
- } else {
- ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
- htons(*packet));
- pr_debug("data %d MID = 0x%04x\n",
- i + 8, htons(*packet));
- }
- } else {
- outl(*(u32 *)&pseudo.buff[0],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[0]);
- outl(*(u32 *)&pseudo.buff[2],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[2]);
- outl(*(u32 *)&pseudo.buff[4],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[4]);
- outl(*(u32 *)&pseudo.buff[6],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[6]);
-
- plong = (u32 *)packet;
- /* Write PPP type + IP Packet into Downlink FIFO */
- for (i = 0; i < (len >> 2); i++)
- outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
-
- /* Check for odd alignment */
- if (len & 0x0003) {
- pr_debug("data = 0x%8x\n", *plong);
- outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
- }
- outl(1, dev->base_addr + FT1000_REG_MAG_UFER);
- }
-
- info->stats.tx_packets++;
- /* Add 14 bytes for MAC address plus ethernet type */
- info->stats.tx_bytes += (len + 14);
- return SUCCESS;
-}
-
-static struct net_device_stats *ft1000_stats(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- return &info->stats;
-}
-
-static int ft1000_open(struct net_device *dev)
-{
- ft1000_reset_card(dev);
-
- /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP
- * and ASIC */
- init_timer(&poll_timer);
- poll_timer.expires = jiffies + (2 * HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
-
- return 0;
-}
-
-static int ft1000_close(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- info->CardReady = 0;
- del_timer(&poll_timer);
-
- if (ft1000_card_present == 1) {
- pr_debug("Media is down\n");
- netif_stop_queue(dev);
-
- ft1000_disable_interrupts(dev);
- ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
-
- /* reset ASIC */
- ft1000_reset_asic(dev);
- }
- return 0;
-}
-
-static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u8 *pdata;
-
- if (skb == NULL) {
- pr_debug("skb == NULL!!!\n");
- return 0;
- }
-
- pr_debug("length of packet = %d\n", skb->len);
-
- pdata = (u8 *)skb->data;
-
- if (info->mediastate == 0) {
- /* Drop packet is mediastate is down */
- pr_debug("mediastate is down\n");
- return SUCCESS;
- }
-
- if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
- /* Drop packet which has invalid size */
- pr_debug("invalid ethernet length\n");
- return SUCCESS;
- }
- ft1000_copy_down_pkt(dev, (u16 *) (pdata + ENET_HEADER_SIZE - 2),
- skb->len - ENET_HEADER_SIZE + 2);
-
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct ft1000_info *info = netdev_priv(dev);
- u16 tempword;
- u16 inttype;
- int cnt;
-
- if (info->CardReady == 0) {
- ft1000_disable_interrupts(dev);
- return IRQ_HANDLED;
- }
-
- if (ft1000_chkcard(dev) == false) {
- ft1000_disable_interrupts(dev);
- return IRQ_HANDLED;
- }
-
- ft1000_disable_interrupts(dev);
-
- /* Read interrupt type */
- inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
-
- /* Make sure we process all interrupt before leaving the ISR due to the
- * edge trigger interrupt type */
- while (inttype) {
- if (inttype & ISR_DOORBELL_PEND)
- ft1000_parse_dpram_msg(dev);
-
- if (inttype & ISR_RCV) {
- pr_debug("Data in FIFO\n");
-
- cnt = 0;
- do {
- /* Check if we have packets in the Downlink
- * FIFO */
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DFIFO_STAT);
- } else {
- tempword = ft1000_read_reg(dev,
- FT1000_REG_MAG_DFSR);
- }
- if (!(tempword & 0x1f))
- break;
- ft1000_copy_up_pkt(dev);
- cnt++;
- } while (cnt < MAX_RCV_LOOP);
-
- }
- /* clear interrupts */
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
- ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
-
- /* Read interrupt type */
- inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register after clear = 0x%x\n",
- inttype);
- }
- ft1000_enable_interrupts(dev);
- return IRQ_HANDLED;
-}
-
-void stop_ft1000_card(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct prov_record *ptr;
- struct prov_record *tmp;
- /* int cnt; */
-
- info->CardReady = 0;
- ft1000_card_present = 0;
- netif_stop_queue(dev);
- ft1000_disable_interrupts(dev);
-
- /* Make sure we free any memory reserve for provisioning */
- list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
-
- kfree(info->priv);
-
- if (info->registered) {
- unregister_netdev(dev);
- info->registered = 0;
- }
-
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, 256);
- release_firmware(fw_entry);
- flarion_ft1000_cnt--;
-
-}
-
-static void ft1000_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct ft1000_info *ft_info;
-
- ft_info = netdev_priv(dev);
-
- strlcpy(info->driver, "ft1000", sizeof(info->driver));
- snprintf(info->bus_info, sizeof(info->bus_info), "PCMCIA 0x%lx",
- dev->base_addr);
- snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d.%d.%d",
- ft_info->DspVer[0], ft_info->DspVer[1], ft_info->DspVer[2],
- ft_info->DspVer[3]);
-}
-
-static u32 ft1000_get_link(struct net_device *dev)
-{
- struct ft1000_info *info;
-
- info = netdev_priv(dev);
- return info->mediastate;
-}
-
-static const struct ethtool_ops ops = {
- .get_drvinfo = ft1000_get_drvinfo,
- .get_link = ft1000_get_link
-};
-
-struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset)
-{
- struct ft1000_info *info;
- struct ft1000_pcmcia *pcmcia;
- struct net_device *dev;
-
- static const struct net_device_ops ft1000ops = {
- .ndo_open = &ft1000_open,
- .ndo_stop = &ft1000_close,
- .ndo_start_xmit = &ft1000_start_xmit,
- .ndo_get_stats = &ft1000_stats,
- };
-
- pr_debug("irq = %d, port = 0x%04llx\n",
- link->irq, (unsigned long long)link->resource[0]->start);
-
- flarion_ft1000_cnt++;
-
- if (flarion_ft1000_cnt > 1) {
- flarion_ft1000_cnt--;
-
- dev_info(&link->dev,
- "This driver can not support more than one instance\n");
- return NULL;
- }
-
- dev = alloc_etherdev(sizeof(struct ft1000_info));
- if (!dev) {
- dev_err(&link->dev, "Failed to allocate etherdev\n");
- return NULL;
- }
-
- SET_NETDEV_DEV(dev, &link->dev);
- info = netdev_priv(dev);
-
- memset(info, 0, sizeof(struct ft1000_info));
-
- pr_debug("address of dev = 0x%p\n", dev);
- pr_debug("address of dev info = 0x%p\n", info);
- pr_debug("device name = %s\n", dev->name);
-
- memset(&info->stats, 0, sizeof(struct net_device_stats));
-
- info->priv = kzalloc(sizeof(struct ft1000_pcmcia), GFP_KERNEL);
- pcmcia = info->priv;
- pcmcia->link = link;
-
- spin_lock_init(&info->dpram_lock);
- info->DrvErrNum = 0;
- info->registered = 1;
- info->ft1000_reset = ft1000_reset;
- info->mediastate = 0;
- info->fifo_cnt = 0;
- info->CardReady = 0;
- info->DSP_TIME[0] = 0;
- info->DSP_TIME[1] = 0;
- info->DSP_TIME[2] = 0;
- info->DSP_TIME[3] = 0;
- flarion_ft1000_cnt = 0;
-
- INIT_LIST_HEAD(&info->prov_list);
-
- info->squeseqnum = 0;
-
- /* dev->hard_start_xmit = &ft1000_start_xmit; */
- /* dev->get_stats = &ft1000_stats; */
- /* dev->open = &ft1000_open; */
- /* dev->stop = &ft1000_close; */
-
- dev->netdev_ops = &ft1000ops;
-
- pr_debug("device name = %s\n", dev->name);
-
- dev->irq = link->irq;
- dev->base_addr = link->resource[0]->start;
- if (pcmcia_get_mac_from_cis(link, dev)) {
- netdev_err(dev, "Could not read mac address\n");
- goto err_dev;
- }
-
- if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name,
- dev)) {
- netdev_err(dev, "Could not request_irq\n");
- goto err_dev;
- }
-
- if (request_region(dev->base_addr, 256, dev->name) == NULL) {
- netdev_err(dev, "Could not request_region\n");
- goto err_irq;
- }
-
- if (register_netdev(dev)) {
- pr_debug("Could not register netdev\n");
- goto err_reg;
- }
-
- info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
- if (info->AsicID == ELECTRABUZZ_ID) {
- pr_debug("ELECTRABUZZ ASIC\n");
- if (request_firmware(&fw_entry, "ft1000.img",
- &link->dev) != 0) {
- pr_info("Could not open ft1000.img\n");
- goto err_unreg;
- }
- } else {
- pr_debug("MAGNEMITE ASIC\n");
- if (request_firmware(&fw_entry, "ft2000.img",
- &link->dev) != 0) {
- pr_info("Could not open ft2000.img\n");
- goto err_unreg;
- }
- }
-
- ft1000_enable_interrupts(dev);
-
- ft1000_card_present = 1;
- dev->ethtool_ops = &ops;
- pr_info("%s: addr 0x%04lx irq %d, MAC addr %pM\n",
- dev->name, dev->base_addr, dev->irq, dev->dev_addr);
- return dev;
-
-err_unreg:
- unregister_netdev(dev);
-err_reg:
- release_region(dev->base_addr, 256);
-err_irq:
- free_irq(dev->irq, dev);
-err_dev:
- free_netdev(dev);
- return NULL;
-}
diff --git a/drivers/staging/ft1000/ft1000-usb/Makefile b/drivers/staging/ft1000/ft1000-usb/Makefile
deleted file mode 100644
index 7c4b78456254..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_FT1000_USB) += ft1000.o
-
-ft1000-y := ft1000_debug.o ft1000_download.o ft1000_hw.o ft1000_usb.o
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
deleted file mode 100644
index f241a3a5a684..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- *---------------------------------------------------------------------------
- * FT1000 driver for Flarion Flash OFDM NIC Device
- *
- * Copyright (C) 2006 Flarion Technologies, 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. 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.
- *---------------------------------------------------------------------------
- *
- * File: ft1000_chdev.c
- *
- * Description: Custom character device dispatch routines.
- *
- * History:
- * 8/29/02 Whc Ported to Linux.
- * 6/05/06 Whc Porting to Linux 2.6.9
- *
- *---------------------------------------------------------------------------
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-
-#include <linux/ioctl.h>
-#include <linux/debugfs.h>
-#include "ft1000_usb.h"
-
-static int ft1000_flarion_cnt;
-
-static int ft1000_open(struct inode *inode, struct file *file);
-static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait);
-static long ft1000_ioctl(struct file *file, unsigned int command,
- unsigned long argument);
-static int ft1000_release(struct inode *inode, struct file *file);
-
-/* List to free receive command buffer pool */
-struct list_head freercvpool;
-
-/* lock to arbitrate free buffer list for receive command data */
-spinlock_t free_buff_lock;
-
-int numofmsgbuf;
-
-/*
- * Table of entry-point routines for char device
- */
-static const struct file_operations ft1000fops = {
- .unlocked_ioctl = ft1000_ioctl,
- .poll = ft1000_poll_dev,
- .open = ft1000_open,
- .release = ft1000_release,
- .llseek = no_llseek,
-};
-
-/*
- ---------------------------------------------------------------------------
- * Function: ft1000_get_buffer
- *
- * Parameters:
- *
- * Returns:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist)
-{
- unsigned long flags;
- struct dpram_blk *ptr;
-
- spin_lock_irqsave(&free_buff_lock, flags);
- /* Check if buffer is available */
- if (list_empty(bufflist)) {
- pr_debug("No more buffer - %d\n", numofmsgbuf);
- ptr = NULL;
- } else {
- numofmsgbuf--;
- ptr = list_entry(bufflist->next, struct dpram_blk, list);
- list_del(&ptr->list);
- /* pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
- }
- spin_unlock_irqrestore(&free_buff_lock, flags);
-
- return ptr;
-}
-
-
-
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_free_buffer
- *
- * Parameters:
- *
- * Returns:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&free_buff_lock, flags);
- /* Put memory back to list */
- list_add_tail(&pdpram_blk->list, plist);
- numofmsgbuf++;
- /*pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
- spin_unlock_irqrestore(&free_buff_lock, flags);
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_CreateDevice
- *
- * Parameters: dev - pointer to adapter object
- *
- * Returns: 0 if successful
- *
- * Description: Creates a private char device.
- *
- * Notes: Only called by init_module().
- *
- *---------------------------------------------------------------------------
- */
-int ft1000_create_dev(struct ft1000_usb *dev)
-{
- int result;
- int i;
- struct dentry *dir, *file;
- struct ft1000_debug_dirs *tmp;
-
- /* make a new device name */
- sprintf(dev->DeviceName, "%s%d", "FT1000_", dev->CardNumber);
-
- pr_debug("number of instance = %d\n", ft1000_flarion_cnt);
- pr_debug("DeviceCreated = %x\n", dev->DeviceCreated);
-
- if (dev->DeviceCreated) {
- pr_debug("\"%s\" already registered\n", dev->DeviceName);
- return -EIO;
- }
-
-
- /* register the device */
- pr_debug("\"%s\" debugfs device registration\n", dev->DeviceName);
-
- tmp = kmalloc(sizeof(struct ft1000_debug_dirs), GFP_KERNEL);
- if (tmp == NULL) {
- result = -1;
- goto fail;
- }
-
- dir = debugfs_create_dir(dev->DeviceName, NULL);
- if (IS_ERR(dir)) {
- result = PTR_ERR(dir);
- goto debug_dir_fail;
- }
-
- file = debugfs_create_file("device", S_IRUGO | S_IWUSR, dir,
- dev, &ft1000fops);
- if (IS_ERR(file)) {
- result = PTR_ERR(file);
- goto debug_file_fail;
- }
-
- tmp->dent = dir;
- tmp->file = file;
- tmp->int_number = dev->CardNumber;
- list_add(&tmp->list, &dev->nodes.list);
-
- pr_debug("registered debugfs directory \"%s\"\n", dev->DeviceName);
-
- /* initialize application information */
- dev->appcnt = 0;
- for (i = 0; i < MAX_NUM_APP; i++) {
- dev->app_info[i].nTxMsg = 0;
- dev->app_info[i].nRxMsg = 0;
- dev->app_info[i].nTxMsgReject = 0;
- dev->app_info[i].nRxMsgMiss = 0;
- dev->app_info[i].fileobject = NULL;
- dev->app_info[i].app_id = i+1;
- dev->app_info[i].DspBCMsgFlag = 0;
- dev->app_info[i].NumOfMsg = 0;
- init_waitqueue_head(&dev->app_info[i].wait_dpram_msg);
- INIT_LIST_HEAD(&dev->app_info[i].app_sqlist);
- }
-
- dev->DeviceCreated = TRUE;
- ft1000_flarion_cnt++;
-
- return 0;
-
-debug_file_fail:
- debugfs_remove(dir);
-debug_dir_fail:
- kfree(tmp);
-fail:
- return result;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_DestroyDeviceDEBUG
- *
- * Parameters: dev - pointer to adapter object
- *
- * Description: Destroys a private char device.
- *
- * Notes: Only called by cleanup_module().
- *
- *---------------------------------------------------------------------------
- */
-void ft1000_destroy_dev(struct net_device *netdev)
-{
- struct ft1000_info *info = netdev_priv(netdev);
- struct ft1000_usb *dev = info->priv;
- int i;
- struct dpram_blk *pdpram_blk;
- struct dpram_blk *ptr;
- struct list_head *pos, *q;
- struct ft1000_debug_dirs *dir;
-
- if (dev->DeviceCreated) {
- ft1000_flarion_cnt--;
- list_for_each_safe(pos, q, &dev->nodes.list) {
- dir = list_entry(pos, struct ft1000_debug_dirs, list);
- if (dir->int_number == dev->CardNumber) {
- debugfs_remove(dir->file);
- debugfs_remove(dir->dent);
- list_del(pos);
- kfree(dir);
- }
- }
- pr_debug("unregistered device \"%s\"\n", dev->DeviceName);
-
- /* Make sure we free any memory reserve for slow Queue */
- for (i = 0; i < MAX_NUM_APP; i++) {
- while (list_empty(&dev->app_info[i].app_sqlist) == 0) {
- pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next,
- struct dpram_blk, list);
- list_del(&pdpram_blk->list);
- ft1000_free_buffer(pdpram_blk, &freercvpool);
-
- }
- wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
- }
-
- /* Remove buffer allocated for receive command data */
- if (ft1000_flarion_cnt == 0) {
- while (list_empty(&freercvpool) == 0) {
- ptr = list_entry(freercvpool.next, struct dpram_blk, list);
- list_del(&ptr->list);
- kfree(ptr->pbuffer);
- kfree(ptr);
- }
- }
- dev->DeviceCreated = FALSE;
- }
-
-
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_open
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-static int ft1000_open(struct inode *inode, struct file *file)
-{
- struct ft1000_info *info;
- struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
- int i, num;
-
- num = MINOR(inode->i_rdev) & 0xf;
- pr_debug("minor number=%d\n", num);
-
- info = file->private_data = netdev_priv(dev->net);
-
- pr_debug("f_owner = %p number of application = %d\n",
- &file->f_owner, dev->appcnt);
-
- /* Check if maximum number of application exceeded */
- if (dev->appcnt > MAX_NUM_APP) {
- pr_debug("Maximum number of application exceeded\n");
- return -EACCES;
- }
-
- /* Search for available application info block */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (dev->app_info[i].fileobject == NULL)
- break;
- }
-
- /* Fail due to lack of application info block */
- if (i == MAX_NUM_APP) {
- pr_debug("Could not find an application info block\n");
- return -EACCES;
- }
-
- dev->appcnt++;
- dev->app_info[i].fileobject = &file->f_owner;
- dev->app_info[i].nTxMsg = 0;
- dev->app_info[i].nRxMsg = 0;
- dev->app_info[i].nTxMsgReject = 0;
- dev->app_info[i].nRxMsgMiss = 0;
-
- nonseekable_open(inode, file);
- return 0;
-}
-
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_poll_dev
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-
-static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
-{
- struct net_device *netdev = file->private_data;
- struct ft1000_info *info = netdev_priv(netdev);
- struct ft1000_usb *dev = info->priv;
- int i;
-
- if (ft1000_flarion_cnt == 0) {
- pr_debug("called with ft1000_flarion_cnt value zero\n");
- return -EBADF;
- }
-
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (dev->app_info[i].fileobject == &file->f_owner) {
- /* pr_debug("Message is for AppId = %d\n", dev->app_info[i].app_id); */
- break;
- }
- }
-
- /* Could not find application info block */
- if (i == MAX_NUM_APP) {
- pr_debug("Could not find application info block\n");
- return -EACCES;
- }
-
- if (list_empty(&dev->app_info[i].app_sqlist) == 0) {
- pr_debug("Message detected in slow queue\n");
- return(POLLIN | POLLRDNORM | POLLPRI);
- }
-
- poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
- /* pr_debug("Polling for data from DSP\n"); */
-
- return 0;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_ioctl
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-static long ft1000_ioctl(struct file *file, unsigned int command,
- unsigned long argument)
-{
- void __user *argp = (void __user *)argument;
- struct ft1000_info *info;
- struct ft1000_usb *ft1000dev;
- int result = 0;
- int cmd;
- int i;
- u16 tempword;
- unsigned long flags;
- struct timeval tv;
- struct IOCTL_GET_VER get_ver_data;
- struct IOCTL_GET_DSP_STAT get_stat_data;
- u8 ConnectionMsg[] = {
- 0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
- 0x00, 0x01, 0x00, 0x00
- };
-
- unsigned short ledStat = 0;
- unsigned short conStat = 0;
-
- if (ft1000_flarion_cnt == 0) {
- pr_debug("called with ft1000_flarion_cnt of zero\n");
- return -EBADF;
- }
-
- /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
-
- info = file->private_data;
- ft1000dev = info->priv;
- cmd = _IOC_NR(command);
- /* pr_debug("cmd = 0x%x\n", cmd); */
-
- /* process the command */
- switch (cmd) {
- case IOCTL_REGISTER_CMD:
- pr_debug("IOCTL_FT1000_REGISTER called\n");
- result = get_user(tempword, (__u16 __user *)argp);
- if (result) {
- pr_debug("result = %d failed to get_user\n", result);
- break;
- }
- if (tempword == DSPBCMSGID) {
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
- ft1000dev->app_info[i].DspBCMsgFlag = 1;
- pr_debug("Registered for broadcast messages\n");
- break;
- }
- }
- }
- break;
-
- case IOCTL_GET_VER_CMD:
- pr_debug("IOCTL_FT1000_GET_VER called\n");
-
- get_ver_data.drv_ver = FT1000_DRV_VER;
-
- if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- break;
- }
-
- pr_debug("driver version = 0x%x\n",
- (unsigned int)get_ver_data.drv_ver);
-
- break;
- case IOCTL_CONNECT:
- /* Connect Message */
- pr_debug("IOCTL_FT1000_CONNECT\n");
- ConnectionMsg[79] = 0xfc;
- result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
-
- break;
- case IOCTL_DISCONNECT:
- /* Disconnect Message */
- pr_debug("IOCTL_FT1000_DISCONNECT\n");
- ConnectionMsg[79] = 0xfd;
- result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
- break;
- case IOCTL_GET_DSP_STAT_CMD:
- /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
- memset(&get_stat_data, 0, sizeof(get_stat_data));
- memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
- memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
- memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
- memcpy(get_stat_data.eui64, info->eui64, EUISZ);
-
- if (info->ProgConStat != 0xFF) {
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED,
- (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
- get_stat_data.LedStat = ntohs(ledStat);
- pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE,
- (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
- get_stat_data.ConStat = ntohs(conStat);
- pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
- } else {
- get_stat_data.ConStat = 0x0f;
- }
-
-
- get_stat_data.nTxPkts = info->stats.tx_packets;
- get_stat_data.nRxPkts = info->stats.rx_packets;
- get_stat_data.nTxBytes = info->stats.tx_bytes;
- get_stat_data.nRxBytes = info->stats.rx_bytes;
- do_gettimeofday(&tv);
- get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
- pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
- if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- break;
- }
- pr_debug("GET_DSP_STAT succeed\n");
- break;
- case IOCTL_SET_DPRAM_CMD:
- {
- struct IOCTL_DPRAM_BLK *dpram_data = NULL;
- /* struct IOCTL_DPRAM_COMMAND dpram_command; */
- u16 qtype;
- u16 msgsz;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- u16 total_len;
- u16 app_index;
- u16 status;
-
- /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
-
-
- if (ft1000_flarion_cnt == 0)
- return -EBADF;
-
- if (ft1000dev->DrvMsgPend)
- return -ENOTTY;
-
- if (ft1000dev->fProvComplete == 0)
- return -EACCES;
-
- ft1000dev->fAppMsgPend = true;
-
- if (info->CardReady) {
-
- /* pr_debug("try to SET_DPRAM\n"); */
-
- /* Get the length field to see how many bytes to copy */
- result = get_user(msgsz, (__u16 __user *)argp);
- if (result)
- break;
- msgsz = ntohs(msgsz);
- /* pr_debug("length of message = %d\n", msgsz); */
-
- if (msgsz > MAX_CMD_SQSIZE) {
- pr_debug("bad message length = %d\n", msgsz);
- result = -EINVAL;
- break;
- }
-
- result = -ENOMEM;
- dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
- if (!dpram_data)
- break;
-
- if (copy_from_user(dpram_data, argp, msgsz+2)) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- } else {
- /* Check if this message came from a registered application */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner)
- break;
- }
- if (i == MAX_NUM_APP) {
- pr_debug("No matching application fileobject\n");
- result = -EINVAL;
- kfree(dpram_data);
- break;
- }
- app_index = i;
-
- /* Check message qtype type which is the lower byte within qos_class */
- qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
- /* pr_debug("qtype = %d\n", qtype); */
- if (!qtype) {
- /* Put message into Slow Queue */
- /* Only put a message into the DPRAM if msg doorbell is available */
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
- if (tempword & FT1000_DB_DPRAM_TX) {
- /* Suspend for 2ms and try again due to DSP doorbell busy */
- mdelay(2);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- /* Suspend for 1ms and try again due to DSP doorbell busy */
- mdelay(1);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- /* Suspend for 3ms and try again due to DSP doorbell busy */
- mdelay(3);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- pr_debug("Doorbell not available\n");
- result = -ENOTTY;
- kfree(dpram_data);
- break;
- }
- }
- }
- }
- }
-
- /*pr_debug("finished reading register\n"); */
-
- /* Make sure we are within the limits of the slow queue memory limitation */
- if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
- /* Need to put sequence number plus new checksum for message */
- pmsg = (u16 *)&dpram_data->pseudohdr;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- total_len = msgsz+2;
- if (total_len & 0x1)
- total_len++;
-
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
- for (i = 1; i < 7; i++) {
- ppseudo_hdr->checksum ^= *pmsg++;
- /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
- }
- pmsg++;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- result = card_send_command(ft1000dev, dpram_data, total_len+2);
-
-
- ft1000dev->app_info[app_index].nTxMsg++;
- } else {
- result = -EINVAL;
- }
- }
- }
- } else {
- pr_debug("Card not ready take messages\n");
- result = -EACCES;
- }
- kfree(dpram_data);
-
- }
- break;
- case IOCTL_GET_DPRAM_CMD:
- {
- struct dpram_blk *pdpram_blk;
- struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
- int msglen;
-
- /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
-
- if (ft1000_flarion_cnt == 0)
- return -EBADF;
-
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
- /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
- break;
- }
- }
-
- /* Could not find application info block */
- if (i == MAX_NUM_APP) {
- pr_debug("Could not find application info block\n");
- result = -EBADF;
- break;
- }
-
- result = 0;
- pioctl_dpram = argp;
- if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
- /* pr_debug("Message detected in slow queue\n"); */
- spin_lock_irqsave(&free_buff_lock, flags);
- pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next,
- struct dpram_blk, list);
- list_del(&pdpram_blk->list);
- ft1000dev->app_info[i].NumOfMsg--;
- /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
- spin_unlock_irqrestore(&free_buff_lock, flags);
- msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
- result = get_user(msglen, &pioctl_dpram->total_len);
- if (result)
- break;
- msglen = htons(msglen);
- /* pr_debug("msg length = %x\n", msglen); */
- if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- break;
- }
-
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- result = msglen;
- }
- /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
- }
- break;
-
- default:
- pr_debug("unknown command: 0x%x\n", command);
- result = -ENOTTY;
- break;
- }
- ft1000dev->fAppMsgPend = false;
- return result;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_release
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-static int ft1000_release(struct inode *inode, struct file *file)
-{
- struct ft1000_info *info;
- struct net_device *dev;
- struct ft1000_usb *ft1000dev;
- int i;
- struct dpram_blk *pdpram_blk;
- struct dpram_blk *tmp;
-
- dev = file->private_data;
- info = netdev_priv(dev);
- ft1000dev = info->priv;
-
- if (ft1000_flarion_cnt == 0) {
- ft1000dev->appcnt--;
- return -EBADF;
- }
-
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
- /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
- break;
- }
- }
-
- if (i == MAX_NUM_APP)
- return 0;
-
- list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
- pr_debug("Remove and free memory queue up on slow queue\n");
- list_del(&pdpram_blk->list);
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- }
-
- /* initialize application information */
- ft1000dev->appcnt--;
- pr_debug("appcnt = %d\n", ft1000dev->appcnt);
- ft1000dev->app_info[i].fileobject = NULL;
-
- return 0;
-}
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
deleted file mode 100644
index cf850212f4b6..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/*
- * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
- *
- * This file is part of Express Card USB Driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include "ft1000_usb.h"
-
-
-#define DWNLD_HANDSHAKE_LOC 0x02
-#define DWNLD_TYPE_LOC 0x04
-#define DWNLD_SIZE_MSW_LOC 0x06
-#define DWNLD_SIZE_LSW_LOC 0x08
-#define DWNLD_PS_HDR_LOC 0x0A
-
-#define MAX_DSP_WAIT_LOOPS 40
-#define DSP_WAIT_SLEEP_TIME 1000 /* 1 millisecond */
-#define DSP_WAIT_DISPATCH_LVL 50 /* 50 usec */
-
-#define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
-#define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */
-#define HANDSHAKE_RESET_VALUE_USB 0xFE7E /* When DSP requests startover */
-#define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_DSP_BL_READY_USB 0xFE7E /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */
-#define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */
-
-#define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
-#define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
-
-#define REQUEST_CODE_LENGTH 0x0000
-#define REQUEST_RUN_ADDRESS 0x0001
-#define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */
-#define REQUEST_DONE_BL 0x0003
-#define REQUEST_DONE_CL 0x0004
-#define REQUEST_VERSION_INFO 0x0005
-#define REQUEST_CODE_BY_VERSION 0x0006
-#define REQUEST_MAILBOX_DATA 0x0007
-#define REQUEST_FILE_CHECKSUM 0x0008
-
-#define STATE_START_DWNLD 0x01
-#define STATE_BOOT_DWNLD 0x02
-#define STATE_CODE_DWNLD 0x03
-#define STATE_DONE_DWNLD 0x04
-#define STATE_SECTION_PROV 0x05
-#define STATE_DONE_PROV 0x06
-#define STATE_DONE_FILE 0x07
-
-#define MAX_LENGTH 0x7f0
-
-/* Temporary download mechanism for Magnemite */
-#define DWNLD_MAG_TYPE_LOC 0x00
-#define DWNLD_MAG_LEN_LOC 0x01
-#define DWNLD_MAG_ADDR_LOC 0x02
-#define DWNLD_MAG_CHKSUM_LOC 0x03
-#define DWNLD_MAG_VAL_LOC 0x04
-
-#define HANDSHAKE_MAG_DSP_BL_READY 0xFEFE0000 /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_MAG_DSP_ENTRY 0x01000000 /* Dsp writes this to request for entry address */
-#define HANDSHAKE_MAG_DSP_DATA 0x02000000 /* Dsp writes this to request for data block */
-#define HANDSHAKE_MAG_DSP_DONE 0x03000000 /* Dsp writes this to indicate download done */
-
-#define HANDSHAKE_MAG_DRV_READY 0xFFFF0000 /* Driver writes this to indicate ready to download */
-#define HANDSHAKE_MAG_DRV_DATA 0x02FECDAB /* Driver writes this to indicate data available to DSP */
-#define HANDSHAKE_MAG_DRV_ENTRY 0x01FECDAB /* Driver writes this to indicate entry point to DSP */
-
-#define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1
-
-
-/* New Magnemite downloader */
-#define DWNLD_MAG1_HANDSHAKE_LOC 0x00
-#define DWNLD_MAG1_TYPE_LOC 0x01
-#define DWNLD_MAG1_SIZE_LOC 0x02
-#define DWNLD_MAG1_PS_HDR_LOC 0x03
-
-struct dsp_file_hdr {
- long version_id; /* Version ID of this image format. */
- long package_id; /* Package ID of code release. */
- long build_date; /* Date/time stamp when file was built. */
- long commands_offset; /* Offset to attached commands in Pseudo Hdr format. */
- long loader_offset; /* Offset to bootloader code. */
- long loader_code_address; /* Start address of bootloader. */
- long loader_code_end; /* Where bootloader code ends. */
- long loader_code_size;
- long version_data_offset; /* Offset were scrambled version data begins. */
- long version_data_size; /* Size, in words, of scrambled version data. */
- long nDspImages; /* Number of DSP images in file. */
-};
-
-struct dsp_image_info {
- long coff_date; /* Date/time when DSP Coff image was built. */
- long begin_offset; /* Offset in file where image begins. */
- long end_offset; /* Offset in file where image begins. */
- long run_address; /* On chip Start address of DSP code. */
- long image_size; /* Size of image. */
- long version; /* Embedded version # of DSP code. */
- unsigned short checksum; /* DSP File checksum */
- unsigned short pad1;
-} __packed;
-
-
-/* checks if the doorbell register is cleared */
-static int check_usb_db(struct ft1000_usb *ft1000dev)
-{
- int loopcnt;
- u16 temp;
- int status;
-
- loopcnt = 0;
-
- while (loopcnt < 10) {
- status = ft1000_read_register(ft1000dev, &temp,
- FT1000_REG_DOORBELL);
- pr_debug("read FT1000_REG_DOORBELL value is %x\n", temp);
- if (temp & 0x0080) {
- pr_debug("Got checkusb doorbell\n");
- status = ft1000_write_register(ft1000dev, 0x0080,
- FT1000_REG_DOORBELL);
- status = ft1000_write_register(ft1000dev, 0x0100,
- FT1000_REG_DOORBELL);
- status = ft1000_write_register(ft1000dev, 0x8000,
- FT1000_REG_DOORBELL);
- break;
- }
- loopcnt++;
- usleep_range(10000, 11000);
-
- }
-
- loopcnt = 0;
- while (loopcnt < 20) {
- status = ft1000_read_register(ft1000dev, &temp,
- FT1000_REG_DOORBELL);
- pr_debug("Doorbell = 0x%x\n", temp);
- if (temp & 0x8000) {
- loopcnt++;
- usleep_range(10000, 11000);
- } else {
- pr_debug("door bell is cleared, return 0\n");
- return 0;
- }
- }
-
- return -1;
-}
-
-/* gets the handshake and compares it with the expected value */
-static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value)
-{
- u16 handshake;
- int loopcnt;
- int status = 0;
-
- loopcnt = 0;
-
- while (loopcnt < 100) {
- /* Need to clear downloader doorbell if Hartley ASIC */
- status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_RX,
- FT1000_REG_DOORBELL);
- if (ft1000dev->fcodeldr) {
- pr_debug("fcodeldr is %d\n", ft1000dev->fcodeldr);
- ft1000dev->fcodeldr = 0;
- status = check_usb_db(ft1000dev);
- if (status != 0) {
- pr_debug("check_usb_db failed\n");
- break;
- }
- status = ft1000_write_register(ft1000dev,
- FT1000_DB_DNLD_RX,
- FT1000_REG_DOORBELL);
- }
-
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC,
- (u8 *)&handshake, 1);
- handshake = ntohs(handshake);
-
- if (status)
- return HANDSHAKE_TIMEOUT_VALUE;
-
- if ((handshake == expected_value) ||
- (handshake == HANDSHAKE_RESET_VALUE_USB)) {
- return handshake;
- }
- loopcnt++;
- usleep_range(10000, 11000);
- }
-
- return HANDSHAKE_TIMEOUT_VALUE;
-}
-
-/* write the handshake value to the handshake location */
-static void put_handshake(struct ft1000_usb *ft1000dev, u16 handshake_value)
-{
- u32 tempx;
- u16 tempword;
- int status;
-
- tempx = (u32)handshake_value;
- tempx = ntohl(tempx);
-
- tempword = (u16)(tempx & 0xffff);
- status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
- tempword, 0);
- tempword = (u16)(tempx >> 16);
- status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
- tempword, 1);
- status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
- FT1000_REG_DOORBELL);
-}
-
-static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value)
-{
- u16 handshake;
- int loopcnt;
- u16 temp;
- int status = 0;
-
- loopcnt = 0;
- handshake = 0;
-
- while (loopcnt < 100) {
- if (ft1000dev->usbboot == 2) {
- status = ft1000_read_dpram32(ft1000dev, 0,
- (u8 *)&ft1000dev->tempbuf[0], 64);
- for (temp = 0; temp < 16; temp++) {
- pr_debug("tempbuf %d = 0x%x\n",
- temp, ft1000dev->tempbuf[temp]);
- }
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC,
- (u8 *)&handshake, 1);
- pr_debug("handshake from read_dpram16 = 0x%x\n",
- handshake);
- if (ft1000dev->dspalive == ft1000dev->tempbuf[6]) {
- handshake = 0;
- } else {
- handshake = ft1000dev->tempbuf[1];
- ft1000dev->dspalive =
- ft1000dev->tempbuf[6];
- }
- } else {
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC,
- (u8 *)&handshake, 1);
- }
-
- loopcnt++;
- usleep_range(10000, 11000);
- handshake = ntohs(handshake);
- if ((handshake == expected_value) ||
- (handshake == HANDSHAKE_RESET_VALUE_USB))
- return handshake;
- }
-
- return HANDSHAKE_TIMEOUT_VALUE;
-}
-
-static void put_handshake_usb(struct ft1000_usb *ft1000dev, u16 handshake_value)
-{
- int i;
-
- for (i = 0; i < 1000; i++)
- ;
-}
-
-static u16 get_request_type(struct ft1000_usb *ft1000dev)
-{
- u16 request_type;
- int status;
- u16 tempword;
- u32 tempx;
-
- if (ft1000dev->bootmode == 1) {
- status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempx);
- tempx = ntohl(tempx);
- } else {
- tempx = 0;
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempword, 1);
- tempx |= (tempword << 16);
- tempx = ntohl(tempx);
- }
- request_type = (u16)tempx;
-
- return request_type;
-}
-
-static u16 get_request_type_usb(struct ft1000_usb *ft1000dev)
-{
- u16 request_type;
- int status;
- u16 tempword;
- u32 tempx;
-
- if (ft1000dev->bootmode == 1) {
- status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempx);
- tempx = ntohl(tempx);
- } else {
- if (ft1000dev->usbboot == 2) {
- tempx = ft1000dev->tempbuf[2];
- tempword = ft1000dev->tempbuf[3];
- } else {
- tempx = 0;
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempword, 1);
- }
- tempx |= (tempword << 16);
- tempx = ntohl(tempx);
- }
- request_type = (u16)tempx;
-
- return request_type;
-}
-
-static long get_request_value(struct ft1000_usb *ft1000dev)
-{
- u32 value;
- u16 tempword;
- int status;
-
- if (ft1000dev->bootmode == 1) {
- status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_SIZE_LOC,
- (u8 *)&value);
- value = ntohl(value);
- } else {
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_SIZE_LOC,
- (u8 *)&tempword, 0);
- value = tempword;
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_SIZE_LOC,
- (u8 *)&tempword, 1);
- value |= (tempword << 16);
- value = ntohl(value);
- }
-
- return value;
-}
-
-
-/* writes a value to DWNLD_MAG1_SIZE_LOC */
-static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue)
-{
- u32 tempx;
- int status;
-
- tempx = ntohl(lvalue);
- status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
- (u8 *)&tempx);
-}
-
-
-
-/* returns the checksum of the pseudo header */
-static u16 hdr_checksum(struct pseudo_hdr *pHdr)
-{
- u16 *usPtr = (u16 *)pHdr;
- u16 chksum;
-
-
- chksum = (((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
- usPtr[4]) ^ usPtr[5]) ^ usPtr[6];
-
- return chksum;
-}
-
-static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (buff_w[i] != buff_r[i + offset])
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static int write_dpram32_and_check(struct ft1000_usb *ft1000dev,
- u16 tempbuffer[], u16 dpram)
-{
- int status;
- u16 resultbuffer[64];
- int i;
-
- for (i = 0; i < 10; i++) {
- status = ft1000_write_dpram32(ft1000dev, dpram,
- (u8 *)&tempbuffer[0], 64);
- if (status == 0) {
- /* Work around for ASIC bit stuffing problem. */
- if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
- status = ft1000_write_dpram32(ft1000dev,
- dpram+12, (u8 *)&tempbuffer[24],
- 64);
- }
- /* Let's check the data written */
- status = ft1000_read_dpram32(ft1000dev, dpram,
- (u8 *)&resultbuffer[0], 64);
- if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
- if (check_buffers(tempbuffer, resultbuffer, 28,
- 0)) {
- pr_debug("DPRAM write failed 1 during bootloading\n");
- usleep_range(9000, 11000);
- break;
- }
- status = ft1000_read_dpram32(ft1000dev,
- dpram+12,
- (u8 *)&resultbuffer[0], 64);
-
- if (check_buffers(tempbuffer, resultbuffer, 16,
- 24)) {
- pr_debug("DPRAM write failed 2 during bootloading\n");
- usleep_range(9000, 11000);
- break;
- }
- } else {
- if (check_buffers(tempbuffer, resultbuffer, 32,
- 0)) {
- pr_debug("DPRAM write failed 3 during bootloading\n");
- usleep_range(9000, 11000);
- break;
- }
- }
- if (status == 0)
- break;
- }
- }
- return status;
-}
-
-/* writes a block of DSP image to DPRAM
- * Parameters: struct ft1000_usb - device structure
- * u16 **pUsFile - DSP image file pointer in u16
- * u8 **pUcFile - DSP image file pointer in u8
- * long word_length - length of the buffer to be written to DPRAM
- */
-static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile,
- long word_length)
-{
- int status = 0;
- u16 dpram;
- int loopcnt, i;
- u16 tempword;
- u16 tempbuffer[64];
-
- /*pr_debug("start word_length = %d\n",(int)word_length); */
- dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
- tempword = *(*pUsFile);
- (*pUsFile)++;
- status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
- tempword = *(*pUsFile);
- (*pUsFile)++;
- status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
-
- *pUcFile = *pUcFile + 4;
- word_length--;
- tempword = (u16)word_length;
- word_length = (word_length / 16) + 1;
- for (; word_length > 0; word_length--) { /* In words */
- loopcnt = 0;
- for (i = 0; i < 32; i++) {
- if (tempword != 0) {
- tempbuffer[i++] = *(*pUsFile);
- (*pUsFile)++;
- tempbuffer[i] = *(*pUsFile);
- (*pUsFile)++;
- *pUcFile = *pUcFile + 4;
- loopcnt++;
- tempword--;
- } else {
- tempbuffer[i++] = 0;
- tempbuffer[i] = 0;
- }
- }
-
- /*pr_debug("loopcnt is %d\n", loopcnt); */
- /*pr_debug("write_blk: bootmode = %d\n", bootmode); */
- /*pr_debug("write_blk: dpram = %x\n", dpram); */
- if (ft1000dev->bootmode == 0) {
- if (dpram >= 0x3F4)
- status = ft1000_write_dpram32(ft1000dev, dpram,
- (u8 *)&tempbuffer[0], 8);
- else
- status = ft1000_write_dpram32(ft1000dev, dpram,
- (u8 *)&tempbuffer[0], 64);
- } else {
- status = write_dpram32_and_check(ft1000dev, tempbuffer,
- dpram);
- if (status != 0) {
- pr_debug("Write failed tempbuffer[31] = 0x%x\n",
- tempbuffer[31]);
- break;
- }
- }
- dpram = dpram + loopcnt;
- }
- return status;
-}
-
-static void usb_dnld_complete(struct urb *urb)
-{
- /* pr_debug("****** usb_dnld_complete\n"); */
-}
-
-/* writes a block of DSP image to DPRAM
- * Parameters: struct ft1000_usb - device structure
- * u16 **pUsFile - DSP image file pointer in u16
- * u8 **pUcFile - DSP image file pointer in u8
- * long word_length - length of the buffer to be written to DPRAM
- */
-static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
- u8 **pUcFile, long word_length)
-{
- int byte_length;
-
- byte_length = word_length * 4;
-
- if (byte_length && ((byte_length % 64) == 0))
- byte_length += 4;
-
- if (byte_length < 64)
- byte_length = 68;
-
- usb_init_urb(ft1000dev->tx_urb);
- memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
- usb_fill_bulk_urb(ft1000dev->tx_urb,
- ft1000dev->dev,
- usb_sndbulkpipe(ft1000dev->dev,
- ft1000dev->bulk_out_endpointAddr),
- ft1000dev->tx_buf, byte_length, usb_dnld_complete,
- ft1000dev);
-
- usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
-
- *pUsFile = *pUsFile + (word_length << 1);
- *pUcFile = *pUcFile + (word_length << 2);
-
- return 0;
-}
-
-static int scram_start_dwnld(struct ft1000_usb *ft1000dev, u16 *hshake,
- u32 *state)
-{
- int status = 0;
-
- if (ft1000dev->usbboot)
- *hshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY);
- else
- *hshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY);
- if (*hshake == HANDSHAKE_DSP_BL_READY) {
- pr_debug("handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
- put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY);
- } else if (*hshake == HANDSHAKE_TIMEOUT_VALUE) {
- status = -ETIMEDOUT;
- } else {
- pr_debug("Download error: Handshake failed\n");
- status = -ENETRESET;
- }
- *state = STATE_BOOT_DWNLD;
- return status;
-}
-
-static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file,
- u8 **c_file, const u8 *endpoint, bool boot_case)
-{
- long word_length;
- int status = 0;
-
- word_length = get_request_value(ft1000dev);
- /*pr_debug("word_length = 0x%x\n", (int)word_length); */
- /*NdisMSleep (100); */
- if (word_length > MAX_LENGTH) {
- pr_debug("Download error: Max length exceeded\n");
- return -1;
- }
- if ((word_length * 2 + (long)c_file) > (long)endpoint) {
- /* Error, beyond boot code range.*/
- pr_debug("Download error: Requested len=%d exceeds BOOT code boundary\n",
- (int)word_length);
- return -1;
- }
- if (word_length & 0x1)
- word_length++;
- word_length = word_length / 2;
-
- if (boot_case) {
- status = write_blk(ft1000dev, s_file, c_file, word_length);
- /*pr_debug("write_blk returned %d\n", status); */
- } else {
- status = write_blk_fifo(ft1000dev, s_file, c_file, word_length);
- if (ft1000dev->usbboot == 0)
- ft1000dev->usbboot++;
- if (ft1000dev->usbboot == 1)
- status |= ft1000_write_dpram16(ft1000dev,
- DWNLD_MAG1_PS_HDR_LOC, 0, 0);
- }
- return status;
-}
-
-/* Scramble downloader for Harley based ASIC via USB interface */
-int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
- u32 FileLength)
-{
- int status = 0;
- u32 state;
- u16 handshake;
- struct pseudo_hdr *pseudo_header;
- u16 pseudo_header_len;
- long word_length;
- u16 request;
- u16 temp;
-
- struct dsp_file_hdr *file_hdr;
- struct dsp_image_info *dsp_img_info = NULL;
- long requested_version;
- bool correct_version;
- struct drv_msg *mailbox_data;
- u16 *data = NULL;
- u16 *s_file = NULL;
- u8 *c_file = NULL;
- u8 *boot_end = NULL, *code_end = NULL;
- int image;
- long loader_code_address, loader_code_size = 0;
- long run_address = 0, run_size = 0;
-
- u32 templong;
- u32 image_chksum = 0;
-
- u16 dpram = 0;
- u8 *pbuffer;
- struct prov_record *pprov_record;
- struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
-
- ft1000dev->fcodeldr = 0;
- ft1000dev->usbboot = 0;
- ft1000dev->dspalive = 0xffff;
-
- /*
- * Get version id of file, at first 4 bytes of file, for newer files.
- */
-
- state = STATE_START_DWNLD;
-
- file_hdr = pFileStart;
-
- ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
-
- s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
- c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
-
- boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
-
- loader_code_address = file_hdr->loader_code_address;
- loader_code_size = file_hdr->loader_code_size;
- correct_version = false;
-
- while ((status == 0) && (state != STATE_DONE_FILE)) {
- switch (state) {
- case STATE_START_DWNLD:
- status = scram_start_dwnld(ft1000dev, &handshake,
- &state);
- break;
-
- case STATE_BOOT_DWNLD:
- pr_debug("STATE_BOOT_DWNLD\n");
- ft1000dev->bootmode = 1;
- handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- request = get_request_type(ft1000dev);
- switch (request) {
- case REQUEST_RUN_ADDRESS:
- pr_debug("REQUEST_RUN_ADDRESS\n");
- put_request_value(ft1000dev,
- loader_code_address);
- break;
- case REQUEST_CODE_LENGTH:
- pr_debug("REQUEST_CODE_LENGTH\n");
- put_request_value(ft1000dev,
- loader_code_size);
- break;
- case REQUEST_DONE_BL:
- pr_debug("REQUEST_DONE_BL\n");
- /* Reposition ptrs to beginning of code section */
- s_file = (u16 *) (boot_end);
- c_file = (u8 *) (boot_end);
- /* pr_debug("download:s_file = 0x%8x\n", (int)s_file); */
- /* pr_debug("FT1000:download:c_file = 0x%8x\n", (int)c_file); */
- state = STATE_CODE_DWNLD;
- ft1000dev->fcodeldr = 1;
- break;
- case REQUEST_CODE_SEGMENT:
- status = request_code_segment(ft1000dev,
- &s_file, &c_file,
- boot_end,
- true);
- break;
- default:
- pr_debug("Download error: Bad request type=%d in BOOT download state\n",
- request);
- status = -1;
- break;
- }
- if (ft1000dev->usbboot)
- put_handshake_usb(ft1000dev,
- HANDSHAKE_RESPONSE);
- else
- put_handshake(ft1000dev,
- HANDSHAKE_RESPONSE);
- } else {
- pr_debug("Download error: Handshake failed\n");
- status = -1;
- }
-
- break;
-
- case STATE_CODE_DWNLD:
- /* pr_debug("STATE_CODE_DWNLD\n"); */
- ft1000dev->bootmode = 0;
- if (ft1000dev->usbboot)
- handshake =
- get_handshake_usb(ft1000dev,
- HANDSHAKE_REQUEST);
- else
- handshake =
- get_handshake(ft1000dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- if (ft1000dev->usbboot)
- request =
- get_request_type_usb(ft1000dev);
- else
- request = get_request_type(ft1000dev);
- switch (request) {
- case REQUEST_FILE_CHECKSUM:
- pr_debug("image_chksum = 0x%8x\n",
- image_chksum);
- put_request_value(ft1000dev,
- image_chksum);
- break;
- case REQUEST_RUN_ADDRESS:
- pr_debug("REQUEST_RUN_ADDRESS\n");
- if (correct_version) {
- pr_debug("run_address = 0x%8x\n",
- (int)run_address);
- put_request_value(ft1000dev,
- run_address);
- } else {
- pr_debug("Download error: Got Run address request before image offset request\n");
- status = -1;
- break;
- }
- break;
- case REQUEST_CODE_LENGTH:
- pr_debug("REQUEST_CODE_LENGTH\n");
- if (correct_version) {
- pr_debug("run_size = 0x%8x\n",
- (int)run_size);
- put_request_value(ft1000dev,
- run_size);
- } else {
- pr_debug("Download error: Got Size request before image offset request\n");
- status = -1;
- break;
- }
- break;
- case REQUEST_DONE_CL:
- ft1000dev->usbboot = 3;
- /* Reposition ptrs to beginning of provisioning section */
- s_file =
- (u16 *) (pFileStart +
- file_hdr->commands_offset);
- c_file =
- (u8 *) (pFileStart +
- file_hdr->commands_offset);
- state = STATE_DONE_DWNLD;
- break;
- case REQUEST_CODE_SEGMENT:
- /* pr_debug("REQUEST_CODE_SEGMENT - CODELOADER\n"); */
- if (!correct_version) {
- pr_debug("Download error: Got Code Segment request before image offset request\n");
- status = -1;
- break;
- }
-
- status = request_code_segment(ft1000dev,
- &s_file, &c_file,
- code_end,
- false);
-
- break;
-
- case REQUEST_MAILBOX_DATA:
- pr_debug("REQUEST_MAILBOX_DATA\n");
- /* Convert length from byte count to word count. Make sure we round up. */
- word_length =
- (long)(pft1000info->DSPInfoBlklen +
- 1) / 2;
- put_request_value(ft1000dev,
- word_length);
- mailbox_data =
- (struct drv_msg *)&(pft1000info->
- DSPInfoBlk[0]);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
-
- data = (u16 *)&mailbox_data->data[0];
- dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
- if (word_length & 0x1)
- word_length++;
-
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
-
- templong = *data++;
- templong |= (*data++ << 16);
- status =
- fix_ft1000_write_dpram32
- (ft1000dev, dpram++,
- (u8 *)&templong);
-
- }
- break;
-
- case REQUEST_VERSION_INFO:
- pr_debug("REQUEST_VERSION_INFO\n");
- word_length =
- file_hdr->version_data_size;
- put_request_value(ft1000dev,
- word_length);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
-
- s_file =
- (u16 *) (pFileStart +
- file_hdr->
- version_data_offset);
-
- dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
- if (word_length & 0x1)
- word_length++;
-
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
-
- templong = ntohs(*s_file++);
- temp = ntohs(*s_file++);
- templong |= (temp << 16);
- status =
- fix_ft1000_write_dpram32
- (ft1000dev, dpram++,
- (u8 *)&templong);
-
- }
- break;
-
- case REQUEST_CODE_BY_VERSION:
- pr_debug("REQUEST_CODE_BY_VERSION\n");
- correct_version = false;
- requested_version =
- get_request_value(ft1000dev);
-
- dsp_img_info =
- (struct dsp_image_info *)(pFileStart
- +
- sizeof
- (struct
- dsp_file_hdr));
-
- for (image = 0;
- image < file_hdr->nDspImages;
- image++) {
-
- if (dsp_img_info->version ==
- requested_version) {
- correct_version = true;
- pr_debug("correct_version is TRUE\n");
- s_file =
- (u16 *) (pFileStart
- +
- dsp_img_info->
- begin_offset);
- c_file =
- (u8 *) (pFileStart +
- dsp_img_info->
- begin_offset);
- code_end =
- (u8 *) (pFileStart +
- dsp_img_info->
- end_offset);
- run_address =
- dsp_img_info->
- run_address;
- run_size =
- dsp_img_info->
- image_size;
- image_chksum =
- (u32)dsp_img_info->
- checksum;
- break;
- }
- dsp_img_info++;
-
- } /* end of for */
-
- if (!correct_version) {
- /*
- * Error, beyond boot code range.
- */
- pr_debug("Download error: Bad Version Request = 0x%x.\n",
- (int)requested_version);
- status = -1;
- break;
- }
- break;
-
- default:
- pr_debug("Download error: Bad request type=%d in CODE download state.\n",
- request);
- status = -1;
- break;
- }
- if (ft1000dev->usbboot)
- put_handshake_usb(ft1000dev,
- HANDSHAKE_RESPONSE);
- else
- put_handshake(ft1000dev,
- HANDSHAKE_RESPONSE);
- } else {
- pr_debug("Download error: Handshake failed\n");
- status = -1;
- }
-
- break;
-
- case STATE_DONE_DWNLD:
- pr_debug("Code loader is done...\n");
- state = STATE_SECTION_PROV;
- break;
-
- case STATE_SECTION_PROV:
- pr_debug("STATE_SECTION_PROV\n");
- pseudo_header = (struct pseudo_hdr *)c_file;
-
- if (pseudo_header->checksum ==
- hdr_checksum(pseudo_header)) {
- if (pseudo_header->portdest !=
- 0x80 /* Dsp OAM */) {
- state = STATE_DONE_PROV;
- break;
- }
- pseudo_header_len = ntohs(pseudo_header->length); /* Byte length for PROV records */
-
- /* Get buffer for provisioning data */
- pbuffer =
- kmalloc(pseudo_header_len +
- sizeof(struct pseudo_hdr),
- GFP_ATOMIC);
- if (pbuffer) {
- memcpy(pbuffer, c_file,
- (u32) (pseudo_header_len +
- sizeof(struct
- pseudo_hdr)));
- /* link provisioning data */
- pprov_record =
- kmalloc(sizeof(struct prov_record),
- GFP_ATOMIC);
- if (pprov_record) {
- pprov_record->pprov_data =
- pbuffer;
- list_add_tail(&pprov_record->
- list,
- &pft1000info->
- prov_list);
- /* Move to next entry if available */
- c_file =
- (u8 *) ((unsigned long)
- c_file +
- (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
- if ((unsigned long)(c_file) -
- (unsigned long)(pFileStart)
- >=
- (unsigned long)FileLength) {
- state = STATE_DONE_FILE;
- }
- } else {
- kfree(pbuffer);
- status = -1;
- }
- } else {
- status = -1;
- }
- } else {
- /* Checksum did not compute */
- status = -1;
- }
- pr_debug("after STATE_SECTION_PROV, state = %d, status= %d\n",
- state, status);
- break;
-
- case STATE_DONE_PROV:
- pr_debug("STATE_DONE_PROV\n");
- state = STATE_DONE_FILE;
- break;
-
- default:
- status = -1;
- break;
- } /* End Switch */
-
- if (status != 0)
- break;
-
-/****
- // Check if Card is present
- status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK);
- if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) {
- break;
- }
-
- status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID);
- if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) {
- break;
- }
-****/
-
- } /* End while */
-
- pr_debug("Download exiting with status = 0x%8x\n", status);
- ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
- FT1000_REG_DOORBELL);
-
- return status;
-}
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
deleted file mode 100644
index 9ea32cea2c03..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
+++ /dev/null
@@ -1,1586 +0,0 @@
-/* CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
- *
- *
- * This file is part of Express Card USB Driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include "ft1000_usb.h"
-#include <linux/types.h>
-
-#define HARLEY_READ_REGISTER 0x0
-#define HARLEY_WRITE_REGISTER 0x01
-#define HARLEY_READ_DPRAM_32 0x02
-#define HARLEY_READ_DPRAM_LOW 0x03
-#define HARLEY_READ_DPRAM_HIGH 0x04
-#define HARLEY_WRITE_DPRAM_32 0x05
-#define HARLEY_WRITE_DPRAM_LOW 0x06
-#define HARLEY_WRITE_DPRAM_HIGH 0x07
-
-#define HARLEY_READ_OPERATION 0xc1
-#define HARLEY_WRITE_OPERATION 0x41
-
-#if 0
-#define JDEBUG
-#endif
-
-static int ft1000_submit_rx_urb(struct ft1000_info *info);
-
-static u8 tempbuffer[1600];
-
-#define MAX_RCV_LOOP 100
-
-/* send a control message via USB interface synchronously
- * Parameters: ft1000_usb - device structure
- * pipe - usb control message pipe
- * request - control request
- * requesttype - control message request type
- * value - value to be written or 0
- * index - register index
- * data - data buffer to hold the read/write values
- * size - data size
- * timeout - control message time out value
- */
-static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe,
- u8 request, u8 requesttype, u16 value, u16 index,
- void *data, u16 size, int timeout)
-{
- int ret;
-
- if ((ft1000dev == NULL) || (ft1000dev->dev == NULL)) {
- pr_debug("ft1000dev or ft1000dev->dev == NULL, failure\n");
- return -ENODEV;
- }
-
- ret = usb_control_msg(ft1000dev->dev, pipe, request, requesttype,
- value, index, data, size, timeout);
-
- if (ret > 0)
- ret = 0;
-
- return ret;
-}
-
-/* returns the value in a register */
-int ft1000_read_register(struct ft1000_usb *ft1000dev, u16 *Data,
- u16 nRegIndx)
-{
- int ret = 0;
-
- ret = ft1000_control(ft1000dev,
- usb_rcvctrlpipe(ft1000dev->dev, 0),
- HARLEY_READ_REGISTER,
- HARLEY_READ_OPERATION,
- 0,
- nRegIndx,
- Data,
- 2,
- USB_CTRL_GET_TIMEOUT);
-
- return ret;
-}
-
-/* writes the value in a register */
-int ft1000_write_register(struct ft1000_usb *ft1000dev, u16 value,
- u16 nRegIndx)
-{
- int ret = 0;
-
- ret = ft1000_control(ft1000dev,
- usb_sndctrlpipe(ft1000dev->dev, 0),
- HARLEY_WRITE_REGISTER,
- HARLEY_WRITE_OPERATION,
- value,
- nRegIndx,
- NULL,
- 0,
- USB_CTRL_SET_TIMEOUT);
-
- return ret;
-}
-
-/* read a number of bytes from DPRAM */
-int ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer,
- u16 cnt)
-{
- int ret = 0;
-
- ret = ft1000_control(ft1000dev,
- usb_rcvctrlpipe(ft1000dev->dev, 0),
- HARLEY_READ_DPRAM_32,
- HARLEY_READ_OPERATION,
- 0,
- indx,
- buffer,
- cnt,
- USB_CTRL_GET_TIMEOUT);
-
- return ret;
-}
-
-/* writes into DPRAM a number of bytes */
-int ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer,
- u16 cnt)
-{
- int ret = 0;
-
- if (cnt % 4)
- cnt += cnt - (cnt % 4);
-
- ret = ft1000_control(ft1000dev,
- usb_sndctrlpipe(ft1000dev->dev, 0),
- HARLEY_WRITE_DPRAM_32,
- HARLEY_WRITE_OPERATION,
- 0,
- indx,
- buffer,
- cnt,
- USB_CTRL_SET_TIMEOUT);
-
- return ret;
-}
-
-/* read 16 bits from DPRAM */
-int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer,
- u8 highlow)
-{
- int ret = 0;
- u8 request;
-
- if (highlow == 0)
- request = HARLEY_READ_DPRAM_LOW;
- else
- request = HARLEY_READ_DPRAM_HIGH;
-
- ret = ft1000_control(ft1000dev,
- usb_rcvctrlpipe(ft1000dev->dev, 0),
- request,
- HARLEY_READ_OPERATION,
- 0,
- indx,
- buffer,
- 2,
- USB_CTRL_GET_TIMEOUT);
-
- return ret;
-}
-
-/* write into DPRAM a number of bytes */
-int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value,
- u8 highlow)
-{
- int ret = 0;
- u8 request;
-
- if (highlow == 0)
- request = HARLEY_WRITE_DPRAM_LOW;
- else
- request = HARLEY_WRITE_DPRAM_HIGH;
-
- ret = ft1000_control(ft1000dev,
- usb_sndctrlpipe(ft1000dev->dev, 0),
- request,
- HARLEY_WRITE_OPERATION,
- value,
- indx,
- NULL,
- 0,
- USB_CTRL_SET_TIMEOUT);
-
- return ret;
-}
-
-/* read DPRAM 4 words at a time */
-int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx,
- u8 *buffer)
-{
- u8 buf[16];
- u16 pos;
- int ret = 0;
-
- pos = (indx / 4) * 4;
- ret = ft1000_read_dpram32(ft1000dev, pos, buf, 16);
-
- if (ret == 0) {
- pos = (indx % 4) * 4;
- *buffer++ = buf[pos++];
- *buffer++ = buf[pos++];
- *buffer++ = buf[pos++];
- *buffer++ = buf[pos++];
- } else {
- pr_debug("DPRAM32 Read failed\n");
- *buffer++ = 0;
- *buffer++ = 0;
- *buffer++ = 0;
- *buffer++ = 0;
- }
-
- return ret;
-}
-
-
-/* Description: This function write to DPRAM 4 words at a time */
-int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer)
-{
- u16 pos1;
- u16 pos2;
- u16 i;
- u8 buf[32];
- u8 resultbuffer[32];
- u8 *pdata;
- int ret = 0;
-
- pos1 = (indx / 4) * 4;
- pdata = buffer;
- ret = ft1000_read_dpram32(ft1000dev, pos1, buf, 16);
-
- if (ret == 0) {
- pos2 = (indx % 4)*4;
- buf[pos2++] = *buffer++;
- buf[pos2++] = *buffer++;
- buf[pos2++] = *buffer++;
- buf[pos2++] = *buffer++;
- ret = ft1000_write_dpram32(ft1000dev, pos1, buf, 16);
- } else {
- pr_debug("DPRAM32 Read failed\n");
- return ret;
- }
-
- ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16);
-
- if (ret == 0) {
- buffer = pdata;
- for (i = 0; i < 16; i++) {
- if (buf[i] != resultbuffer[i])
- ret = -1;
- }
- }
-
- if (ret == -1) {
- ret = ft1000_write_dpram32(ft1000dev, pos1,
- (u8 *)&tempbuffer[0], 16);
- ret = ft1000_read_dpram32(ft1000dev, pos1,
- (u8 *)&resultbuffer[0], 16);
- if (ret == 0) {
- buffer = pdata;
- for (i = 0; i < 16; i++) {
- if (tempbuffer[i] != resultbuffer[i]) {
- ret = -1;
- pr_debug("Failed to write\n");
- }
- }
- }
- }
-
- return ret;
-}
-
-/* reset or activate the DSP */
-static void card_reset_dsp(struct ft1000_usb *ft1000dev, bool value)
-{
- int status = 0;
- u16 tempword;
-
- status = ft1000_write_register(ft1000dev, HOST_INTF_BE,
- FT1000_REG_SUP_CTRL);
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_SUP_CTRL);
-
- if (value) {
- pr_debug("Reset DSP\n");
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- tempword |= DSP_RESET_BIT;
- status = ft1000_write_register(ft1000dev, tempword,
- FT1000_REG_RESET);
- } else {
- pr_debug("Activate DSP\n");
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- tempword |= DSP_ENCRYPTED;
- tempword &= ~DSP_UNENCRYPTED;
- status = ft1000_write_register(ft1000dev, tempword,
- FT1000_REG_RESET);
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- tempword &= ~EFUSE_MEM_DISABLE;
- tempword &= ~DSP_RESET_BIT;
- status = ft1000_write_register(ft1000dev, tempword,
- FT1000_REG_RESET);
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- }
-}
-
-/* send a command to ASIC
- * Parameters: ft1000_usb - device structure
- * ptempbuffer - command buffer
- * size - command buffer size
- */
-int card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer,
- int size)
-{
- int ret;
- unsigned short temp;
- unsigned char *commandbuf;
-
- pr_debug("enter card_send_command... size=%d\n", size);
-
- ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
- if (ret)
- return ret;
-
- commandbuf = kmalloc(size + 2, GFP_KERNEL);
- if (!commandbuf)
- return -ENOMEM;
- memcpy((void *)commandbuf + 2, ptempbuffer, size);
-
- if (temp & 0x0100)
- usleep_range(900, 1100);
-
- /* check for odd word */
- size = size + 2;
-
- /* Must force to be 32 bit aligned */
- if (size % 4)
- size += 4 - (size % 4);
-
- ret = ft1000_write_dpram32(ft1000dev, 0, commandbuf, size);
- if (ret)
- return ret;
- usleep_range(900, 1100);
- ret = ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX,
- FT1000_REG_DOORBELL);
- if (ret)
- return ret;
- usleep_range(900, 1100);
-
- ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
-
-#if 0
- if ((temp & 0x0100) == 0)
- pr_debug("Message sent\n");
-#endif
- return ret;
-}
-
-/* load or reload the DSP */
-int dsp_reload(struct ft1000_usb *ft1000dev)
-{
- int status;
- u16 tempword;
- u32 templong;
-
- struct ft1000_info *pft1000info;
-
- pft1000info = netdev_priv(ft1000dev->net);
-
- pft1000info->CardReady = 0;
-
- /* Program Interrupt Mask register */
- status = ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_SUP_IMASK);
-
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
- tempword |= ASIC_RESET_BIT;
- status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET);
- msleep(1000);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
- pr_debug("Reset Register = 0x%x\n", tempword);
-
- /* Toggle DSP reset */
- card_reset_dsp(ft1000dev, 1);
- msleep(1000);
- card_reset_dsp(ft1000dev, 0);
- msleep(1000);
-
- status = ft1000_write_register(ft1000dev, HOST_INTF_BE,
- FT1000_REG_SUP_CTRL);
-
- /* Let's check for FEFE */
- status =
- ft1000_read_dpram32(ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX,
- (u8 *)&templong, 4);
- pr_debug("templong (fefe) = 0x%8x\n", templong);
-
- /* call codeloader */
- status = scram_dnldr(ft1000dev, pFileStart, FileLength);
-
- if (status != 0)
- return -EIO;
-
- msleep(1000);
-
- return 0;
-}
-
-/* call the Card Service function to reset the ASIC. */
-static void ft1000_reset_asic(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_usb *ft1000dev = info->priv;
- u16 tempword;
-
- /* Let's use the register provided by the Magnemite ASIC to reset the
- * ASIC and DSP.
- */
- ft1000_write_register(ft1000dev, DSP_RESET_BIT | ASIC_RESET_BIT,
- FT1000_REG_RESET);
-
- mdelay(1);
-
- /* set watermark to -1 in order to not generate an interrupt */
- ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_MAG_WATERMARK);
-
- /* clear interrupts */
- ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
- ft1000_write_register(ft1000dev, tempword, FT1000_REG_SUP_ISR);
- ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
-}
-
-static int ft1000_reset_card(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_usb *ft1000dev = info->priv;
- u16 tempword;
- struct prov_record *ptr;
- struct prov_record *tmp;
-
- ft1000dev->fCondResetPend = true;
- info->CardReady = 0;
- ft1000dev->fProvComplete = false;
-
- /* Make sure we free any memory reserve for provisioning */
- list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
- pr_debug("deleting provisioning record\n");
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
-
- pr_debug("reset asic\n");
- ft1000_reset_asic(dev);
-
- pr_debug("call dsp_reload\n");
- dsp_reload(ft1000dev);
-
- pr_debug("dsp reload successful\n");
-
- mdelay(10);
-
- /* Initialize DSP heartbeat area */
- ft1000_write_dpram16(ft1000dev, FT1000_MAG_HI_HO, ho_mag,
- FT1000_MAG_HI_HO_INDX);
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (u8 *)&tempword,
- FT1000_MAG_HI_HO_INDX);
- pr_debug("hi_ho value = 0x%x\n", tempword);
-
- info->CardReady = 1;
-
- ft1000dev->fCondResetPend = false;
-
- return TRUE;
-}
-
-/* callback function when a urb is transmitted */
-static void ft1000_usb_transmit_complete(struct urb *urb)
-{
-
- struct ft1000_usb *ft1000dev = urb->context;
-
- if (urb->status)
- pr_err("%s: TX status %d\n", ft1000dev->net->name, urb->status);
-
- netif_wake_queue(ft1000dev->net);
-}
-
-/* take an ethernet packet and convert it to a Flarion
- * packet prior to sending it to the ASIC Downlink FIFO.
- */
-static int ft1000_copy_down_pkt(struct net_device *netdev, u8 *packet, u16 len)
-{
- struct ft1000_info *pInfo = netdev_priv(netdev);
- struct ft1000_usb *pFt1000Dev = pInfo->priv;
-
- int count, ret;
- u8 *t;
- struct pseudo_hdr hdr;
-
- if (!pInfo->CardReady) {
- pr_debug("Card Not Ready\n");
- return -ENODEV;
- }
-
- count = sizeof(struct pseudo_hdr) + len;
- if (count > MAX_BUF_SIZE) {
- pr_debug("Message Size Overflow! size = %d\n", count);
- return -EINVAL;
- }
-
- if (count % 4)
- count = count + (4 - (count % 4));
-
- memset(&hdr, 0, sizeof(struct pseudo_hdr));
-
- hdr.length = ntohs(count);
- hdr.source = 0x10;
- hdr.destination = 0x20;
- hdr.portdest = 0x20;
- hdr.portsrc = 0x10;
- hdr.sh_str_id = 0x91;
- hdr.control = 0x00;
-
- hdr.checksum = hdr.length ^ hdr.source ^ hdr.destination ^
- hdr.portdest ^ hdr.portsrc ^ hdr.sh_str_id ^ hdr.control;
-
- memcpy(&pFt1000Dev->tx_buf[0], &hdr, sizeof(hdr));
- memcpy(&pFt1000Dev->tx_buf[sizeof(struct pseudo_hdr)], packet, len);
-
- netif_stop_queue(netdev);
-
- usb_fill_bulk_urb(pFt1000Dev->tx_urb,
- pFt1000Dev->dev,
- usb_sndbulkpipe(pFt1000Dev->dev,
- pFt1000Dev->bulk_out_endpointAddr),
- pFt1000Dev->tx_buf, count,
- ft1000_usb_transmit_complete, pFt1000Dev);
-
- t = (u8 *)pFt1000Dev->tx_urb->transfer_buffer;
-
- ret = usb_submit_urb(pFt1000Dev->tx_urb, GFP_ATOMIC);
-
- if (ret) {
- pr_debug("failed tx_urb %d\n", ret);
- return ret;
- }
- pInfo->stats.tx_packets++;
- pInfo->stats.tx_bytes += (len + 14);
-
- return 0;
-}
-
-/* transmit an ethernet packet
- * Parameters: skb - socket buffer to be sent
- * dev - network device
- */
-static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ft1000_info *pInfo = netdev_priv(dev);
- struct ft1000_usb *pFt1000Dev = pInfo->priv;
- u8 *pdata;
- int maxlen, pipe;
-
- if (skb == NULL) {
- pr_debug("skb == NULL!!!\n");
- return NETDEV_TX_OK;
- }
-
- if (pFt1000Dev->status & FT1000_STATUS_CLOSING) {
- pr_debug("network driver is closed, return\n");
- goto err;
- }
-
- pipe = usb_sndbulkpipe(pFt1000Dev->dev,
- pFt1000Dev->bulk_out_endpointAddr);
- maxlen = usb_maxpacket(pFt1000Dev->dev, pipe, usb_pipeout(pipe));
-
- pdata = (u8 *)skb->data;
-
- if (pInfo->mediastate == 0) {
- /* Drop packet is mediastate is down */
- pr_debug("mediastate is down\n");
- goto err;
- }
-
- if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
- /* Drop packet which has invalid size */
- pr_debug("invalid ethernet length\n");
- goto err;
- }
-
- ft1000_copy_down_pkt(dev, pdata + ENET_HEADER_SIZE - 2,
- skb->len - ENET_HEADER_SIZE + 2);
-
-err:
- dev_kfree_skb(skb);
-
- return NETDEV_TX_OK;
-}
-
-/* open the network driver */
-static int ft1000_open(struct net_device *dev)
-{
- struct ft1000_info *pInfo = netdev_priv(dev);
- struct ft1000_usb *pFt1000Dev = pInfo->priv;
- struct timeval tv;
-
- pr_debug("ft1000_open is called for card %d\n", pFt1000Dev->CardNumber);
-
- pInfo->stats.rx_bytes = 0;
- pInfo->stats.tx_bytes = 0;
- pInfo->stats.rx_packets = 0;
- pInfo->stats.tx_packets = 0;
- do_gettimeofday(&tv);
- pInfo->ConTm = tv.tv_sec;
- pInfo->ProgConStat = 0;
-
- netif_start_queue(dev);
-
- netif_carrier_on(dev);
-
- return ft1000_submit_rx_urb(pInfo);
-}
-
-static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- return &(info->stats);
-}
-
-static const struct net_device_ops ftnet_ops = {
- .ndo_open = &ft1000_open,
- .ndo_stop = &ft1000_close,
- .ndo_start_xmit = &ft1000_start_xmit,
- .ndo_get_stats = &ft1000_netdev_stats,
-};
-
-/* initialize the network device */
-static int ft1000_reset(void *dev)
-{
- ft1000_reset_card(dev);
- return 0;
-}
-
-int init_ft1000_netdev(struct ft1000_usb *ft1000dev)
-{
- struct net_device *netdev;
- struct ft1000_info *pInfo = NULL;
- struct dpram_blk *pdpram_blk;
- int i, ret_val;
- struct list_head *cur, *tmp;
- char card_nr[2];
- u8 gCardIndex = 0;
-
- netdev = alloc_etherdev(sizeof(struct ft1000_info));
- if (!netdev) {
- pr_debug("can not allocate network device\n");
- return -ENOMEM;
- }
-
- pInfo = netdev_priv(netdev);
-
- memset(pInfo, 0, sizeof(struct ft1000_info));
-
- dev_alloc_name(netdev, netdev->name);
-
- pr_debug("network device name is %s\n", netdev->name);
-
- if (strncmp(netdev->name, "eth", 3) == 0) {
- card_nr[0] = netdev->name[3];
- card_nr[1] = '\0';
- ret_val = kstrtou8(card_nr, 10, &gCardIndex);
- if (ret_val) {
- netdev_err(ft1000dev->net, "Can't parse netdev\n");
- goto err_net;
- }
-
- ft1000dev->CardNumber = gCardIndex;
- pr_debug("card number = %d\n", ft1000dev->CardNumber);
- } else {
- netdev_err(ft1000dev->net, "ft1000: Invalid device name\n");
- ret_val = -ENXIO;
- goto err_net;
- }
-
- memset(&pInfo->stats, 0, sizeof(struct net_device_stats));
-
- spin_lock_init(&pInfo->dpram_lock);
- pInfo->priv = ft1000dev;
- pInfo->DrvErrNum = 0;
- pInfo->registered = 1;
- pInfo->ft1000_reset = ft1000_reset;
- pInfo->mediastate = 0;
- pInfo->fifo_cnt = 0;
- ft1000dev->DeviceCreated = FALSE;
- pInfo->CardReady = 0;
- pInfo->DSP_TIME[0] = 0;
- pInfo->DSP_TIME[1] = 0;
- pInfo->DSP_TIME[2] = 0;
- pInfo->DSP_TIME[3] = 0;
- ft1000dev->fAppMsgPend = false;
- ft1000dev->fCondResetPend = false;
- ft1000dev->usbboot = 0;
- ft1000dev->dspalive = 0;
- memset(&ft1000dev->tempbuf[0], 0, sizeof(ft1000dev->tempbuf));
-
- INIT_LIST_HEAD(&pInfo->prov_list);
-
- INIT_LIST_HEAD(&ft1000dev->nodes.list);
-
- netdev->netdev_ops = &ftnet_ops;
-
- ft1000dev->net = netdev;
-
- pr_debug("Initialize free_buff_lock and freercvpool\n");
- spin_lock_init(&free_buff_lock);
-
- /* initialize a list of buffers to be use for queuing
- * up receive command data
- */
- INIT_LIST_HEAD(&freercvpool);
-
- /* create list of free buffers */
- for (i = 0; i < NUM_OF_FREE_BUFFERS; i++) {
- /* Get memory for DPRAM_DATA link list */
- pdpram_blk = kmalloc(sizeof(struct dpram_blk), GFP_KERNEL);
- if (pdpram_blk == NULL) {
- ret_val = -ENOMEM;
- goto err_free;
- }
- /* Get a block of memory to store command data */
- pdpram_blk->pbuffer = kmalloc(MAX_CMD_SQSIZE, GFP_KERNEL);
- if (pdpram_blk->pbuffer == NULL) {
- ret_val = -ENOMEM;
- kfree(pdpram_blk);
- goto err_free;
- }
- /* link provisioning data */
- list_add_tail(&pdpram_blk->list, &freercvpool);
- }
- numofmsgbuf = NUM_OF_FREE_BUFFERS;
-
- return 0;
-
-err_free:
- list_for_each_safe(cur, tmp, &freercvpool) {
- pdpram_blk = list_entry(cur, struct dpram_blk, list);
- list_del(&pdpram_blk->list);
- kfree(pdpram_blk->pbuffer);
- kfree(pdpram_blk);
- }
-err_net:
- free_netdev(netdev);
- return ret_val;
-}
-
-/* register the network driver */
-int reg_ft1000_netdev(struct ft1000_usb *ft1000dev,
- struct usb_interface *intf)
-{
- struct net_device *netdev;
- struct ft1000_info *pInfo;
- int rc;
-
- netdev = ft1000dev->net;
- pInfo = netdev_priv(ft1000dev->net);
-
- ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID);
-
- usb_set_intfdata(intf, pInfo);
- SET_NETDEV_DEV(netdev, &intf->dev);
-
- rc = register_netdev(netdev);
- if (rc) {
- pr_debug("could not register network device\n");
- free_netdev(netdev);
- return rc;
- }
-
- ft1000_create_dev(ft1000dev);
-
- pInfo->CardReady = 1;
-
- return 0;
-}
-
-/* take a packet from the FIFO up link and
- * convert it into an ethernet packet and deliver it to the IP stack
- */
-static int ft1000_copy_up_pkt(struct urb *urb)
-{
- struct ft1000_info *info = urb->context;
- struct ft1000_usb *ft1000dev = info->priv;
- struct net_device *net = ft1000dev->net;
-
- u16 tempword;
- u16 len;
- u16 lena;
- struct sk_buff *skb;
- u16 i;
- u8 *pbuffer = NULL;
- u8 *ptemp = NULL;
- u16 *chksum;
-
- if (ft1000dev->status & FT1000_STATUS_CLOSING) {
- pr_debug("network driver is closed, return\n");
- return 0;
- }
- /* Read length */
- len = urb->transfer_buffer_length;
- lena = urb->actual_length;
-
- chksum = (u16 *)ft1000dev->rx_buf;
-
- tempword = *chksum++;
- for (i = 1; i < 7; i++)
- tempword ^= *chksum++;
-
- if (tempword != *chksum) {
- info->stats.rx_errors++;
- ft1000_submit_rx_urb(info);
- return -1;
- }
-
- skb = dev_alloc_skb(len + 12 + 2);
-
- if (skb == NULL) {
- info->stats.rx_errors++;
- ft1000_submit_rx_urb(info);
- return -1;
- }
-
- pbuffer = (u8 *)skb_put(skb, len + 12);
-
- /* subtract the number of bytes read already */
- ptemp = pbuffer;
-
- /* fake MAC address */
- *pbuffer++ = net->dev_addr[0];
- *pbuffer++ = net->dev_addr[1];
- *pbuffer++ = net->dev_addr[2];
- *pbuffer++ = net->dev_addr[3];
- *pbuffer++ = net->dev_addr[4];
- *pbuffer++ = net->dev_addr[5];
- *pbuffer++ = 0x00;
- *pbuffer++ = 0x07;
- *pbuffer++ = 0x35;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xfe;
-
- memcpy(pbuffer, ft1000dev->rx_buf + sizeof(struct pseudo_hdr),
- len - sizeof(struct pseudo_hdr));
-
- skb->dev = net;
-
- skb->protocol = eth_type_trans(skb, net);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
-
- info->stats.rx_packets++;
- /* Add on 12 bytes for MAC address which was removed */
- info->stats.rx_bytes += (lena + 12);
-
- ft1000_submit_rx_urb(info);
-
- return 0;
-}
-
-
-/* the receiving function of the network driver */
-static int ft1000_submit_rx_urb(struct ft1000_info *info)
-{
- int result;
- struct ft1000_usb *pFt1000Dev = info->priv;
-
- if (pFt1000Dev->status & FT1000_STATUS_CLOSING) {
- pr_debug("network driver is closed, return\n");
- return -ENODEV;
- }
-
- usb_fill_bulk_urb(pFt1000Dev->rx_urb,
- pFt1000Dev->dev,
- usb_rcvbulkpipe(pFt1000Dev->dev,
- pFt1000Dev->bulk_in_endpointAddr),
- pFt1000Dev->rx_buf, MAX_BUF_SIZE,
- (usb_complete_t)ft1000_copy_up_pkt, info);
-
- result = usb_submit_urb(pFt1000Dev->rx_urb, GFP_ATOMIC);
-
- if (result) {
- pr_err("submitting rx_urb %d failed\n", result);
- return result;
- }
-
- return 0;
-}
-
-/* close the network driver */
-int ft1000_close(struct net_device *net)
-{
- struct ft1000_info *pInfo = netdev_priv(net);
- struct ft1000_usb *ft1000dev = pInfo->priv;
-
- ft1000dev->status |= FT1000_STATUS_CLOSING;
-
- pr_debug("pInfo=%p, ft1000dev=%p\n", pInfo, ft1000dev);
- netif_carrier_off(net);
- netif_stop_queue(net);
- ft1000dev->status &= ~FT1000_STATUS_CLOSING;
-
- pInfo->ProgConStat = 0xff;
-
- return 0;
-}
-
-/* check if the device is presently available on the system. */
-static int ft1000_chkcard(struct ft1000_usb *dev)
-{
- u16 tempword;
- int status;
-
- if (dev->fCondResetPend) {
- pr_debug("Card is being reset, return FALSE\n");
- return TRUE;
- }
- /* Mask register is used to check for device presence since it is never
- * set to zero.
- */
- status = ft1000_read_register(dev, &tempword, FT1000_REG_SUP_IMASK);
- if (tempword == 0) {
- pr_debug("IMASK = 0 Card not detected\n");
- return FALSE;
- }
- /* The system will return the value of 0xffff for the version register
- * if the device is not present.
- */
- status = ft1000_read_register(dev, &tempword, FT1000_REG_ASIC_ID);
- if (tempword != 0x1b01) {
- dev->status |= FT1000_STATUS_CLOSING;
- pr_debug("Version = 0xffff Card not detected\n");
- return FALSE;
- }
- return TRUE;
-}
-
-/* read a message from the dpram area.
- * Input:
- * dev - network device structure
- * pbuffer - caller supply address to buffer
- */
-static bool ft1000_receive_cmd(struct ft1000_usb *dev, u16 *pbuffer,
- int maxsz)
-{
- u16 size;
- int ret;
- u16 *ppseudohdr;
- int i;
- u16 tempword;
-
- ret =
- ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (u8 *)&size,
- FT1000_MAG_PH_LEN_INDX);
- size = ntohs(size) + PSEUDOSZ;
- if (size > maxsz) {
- pr_debug("Invalid command length = %d\n", size);
- return FALSE;
- }
- ppseudohdr = (u16 *)pbuffer;
- ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE,
- FT1000_REG_DPRAM_ADDR);
- ret =
- ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
- pbuffer++;
- ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE + 1,
- FT1000_REG_DPRAM_ADDR);
- for (i = 0; i <= (size >> 2); i++) {
- ret =
- ft1000_read_register(dev, pbuffer,
- FT1000_REG_MAG_DPDATAL);
- pbuffer++;
- ret =
- ft1000_read_register(dev, pbuffer,
- FT1000_REG_MAG_DPDATAH);
- pbuffer++;
- }
- /* copy odd aligned word */
- ret =
- ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL);
-
- pbuffer++;
- ret =
- ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
-
- pbuffer++;
- if (size & 0x0001) {
- /* copy odd byte from fifo */
- ret =
- ft1000_read_register(dev, &tempword,
- FT1000_REG_DPRAM_DATA);
- *pbuffer = ntohs(tempword);
- }
- /* Check if pseudo header checksum is good
- * Calculate pseudo header checksum
- */
- tempword = *ppseudohdr++;
- for (i = 1; i < 7; i++)
- tempword ^= *ppseudohdr++;
-
- if (tempword != *ppseudohdr)
- return FALSE;
-
- return TRUE;
-}
-
-static int ft1000_dsp_prov(void *arg)
-{
- struct ft1000_usb *dev = (struct ft1000_usb *)arg;
- struct ft1000_info *info = netdev_priv(dev->net);
- u16 tempword;
- u16 len;
- u16 i = 0;
- struct prov_record *ptr;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- int status;
- u16 TempShortBuf[256];
-
- while (list_empty(&info->prov_list) == 0) {
- pr_debug("DSP Provisioning List Entry\n");
-
- /* Check if doorbell is available */
- pr_debug("check if doorbell is cleared\n");
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (status) {
- pr_debug("ft1000_read_register error\n");
- break;
- }
-
- while (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- i++;
- if (i == 10) {
- pr_debug("message drop\n");
- return -1;
- }
- ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- }
-
- if (!(tempword & FT1000_DB_DPRAM_TX)) {
- pr_debug("*** Provision Data Sent to DSP\n");
-
- /* Send provisioning data */
- ptr = list_entry(info->prov_list.next,
- struct prov_record, list);
- len = *(u16 *)ptr->pprov_data;
- len = htons(len);
- len += PSEUDOSZ;
-
- pmsg = (u16 *)ptr->pprov_data;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- TempShortBuf[0] = 0;
- TempShortBuf[1] = htons(len);
- memcpy(&TempShortBuf[2], ppseudo_hdr, len);
-
- status =
- ft1000_write_dpram32(dev, 0,
- (u8 *)&TempShortBuf[0],
- (unsigned short)(len + 2));
- status =
- ft1000_write_register(dev, FT1000_DB_DPRAM_TX,
- FT1000_REG_DOORBELL);
-
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
- usleep_range(9000, 11000);
- }
-
- pr_debug("DSP Provisioning List Entry finished\n");
-
- msleep(100);
-
- dev->fProvComplete = true;
- info->CardReady = 1;
-
- return 0;
-}
-
-static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size)
-{
- struct ft1000_info *info = netdev_priv(dev->net);
- u16 msgtype;
- u16 tempword;
- struct media_msg *pmediamsg;
- struct dsp_init_msg *pdspinitmsg;
- struct drv_msg *pdrvmsg;
- u16 i;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- int status;
- union {
- u8 byte[2];
- u16 wrd;
- } convert;
-
- char *cmdbuffer = kmalloc(1600, GFP_KERNEL);
-
- if (!cmdbuffer)
- return -ENOMEM;
-
- status = ft1000_read_dpram32(dev, 0x200, cmdbuffer, size);
-
-#ifdef JDEBUG
- print_hex_dump_debug("cmdbuffer: ", HEX_DUMP_OFFSET, 16, 1,
- cmdbuffer, size, true);
-#endif
- pdrvmsg = (struct drv_msg *)&cmdbuffer[2];
- msgtype = ntohs(pdrvmsg->type);
- pr_debug("Command message type = 0x%x\n", msgtype);
- switch (msgtype) {
- case MEDIA_STATE:{
- pr_debug("Command message type = MEDIA_STATE\n");
- pmediamsg = (struct media_msg *)&cmdbuffer[0];
- if (info->ProgConStat != 0xFF) {
- if (pmediamsg->state) {
- pr_debug("Media is up\n");
- if (info->mediastate == 0) {
- if (dev->NetDevRegDone)
- netif_wake_queue(dev->net);
- info->mediastate = 1;
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- if (dev->NetDevRegDone)
- info->ConTm = 0;
- }
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- info->ConTm = 0;
- }
- }
- break;
- }
- case DSP_INIT_MSG:{
- pr_debug("Command message type = DSP_INIT_MSG\n");
- pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[2];
- memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
- pr_debug("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
- info->DspVer[0], info->DspVer[1], info->DspVer[2],
- info->DspVer[3]);
- memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
- HWSERNUMSZ);
- memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
- memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
- pr_debug("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n",
- info->eui64[0], info->eui64[1], info->eui64[2],
- info->eui64[3], info->eui64[4], info->eui64[5],
- info->eui64[6], info->eui64[7]);
- dev->net->dev_addr[0] = info->eui64[0];
- dev->net->dev_addr[1] = info->eui64[1];
- dev->net->dev_addr[2] = info->eui64[2];
- dev->net->dev_addr[3] = info->eui64[5];
- dev->net->dev_addr[4] = info->eui64[6];
- dev->net->dev_addr[5] = info->eui64[7];
-
- if (ntohs(pdspinitmsg->length) ==
- (sizeof(struct dsp_init_msg) - 20)) {
- memcpy(info->ProductMode, pdspinitmsg->ProductMode,
- MODESZ);
- memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, CALVERSZ);
- memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
- CALDATESZ);
- pr_debug("RFCalVer = 0x%2x 0x%2x\n",
- info->RfCalVer[0], info->RfCalVer[1]);
- }
- break;
- }
- case DSP_PROVISION:{
- pr_debug("Command message type = DSP_PROVISION\n");
-
- /* kick off dspprov routine to start provisioning
- * Send provisioning data to DSP
- */
- if (list_empty(&info->prov_list) == 0) {
- dev->fProvComplete = false;
- status = ft1000_dsp_prov(dev);
- if (status != 0)
- goto out;
- } else {
- dev->fProvComplete = true;
- status = ft1000_write_register(dev, FT1000_DB_HB,
- FT1000_REG_DOORBELL);
- pr_debug("No more DSP provisioning data in dsp image\n");
- }
- pr_debug("DSP PROVISION is done\n");
- break;
- }
- case DSP_STORE_INFO:{
- pr_debug("Command message type = DSP_STORE_INFO");
- tempword = ntohs(pdrvmsg->length);
- info->DSPInfoBlklen = tempword;
- if (tempword < (MAX_DSP_SESS_REC - 4)) {
- pmsg = (u16 *)&pdrvmsg->data[0];
- for (i = 0; i < ((tempword + 1) / 2); i++) {
- pr_debug("dsp info data = 0x%x\n", *pmsg);
- info->DSPInfoBlk[i + 10] = *pmsg++;
- }
- } else {
- info->DSPInfoBlklen = 0;
- }
- break;
- }
- case DSP_GET_INFO:{
- pr_debug("Got DSP_GET_INFO\n");
- /* copy dsp info block to dsp */
- dev->DrvMsgPend = 1;
- /* allow any outstanding ioctl to finish */
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- break;
- }
- }
- /* Put message into Slow Queue Form Pseudo header */
- pmsg = (u16 *)info->DSPInfoBlk;
- *pmsg++ = 0;
- *pmsg++ = htons(info->DSPInfoBlklen + 20 + info->DSPInfoBlklen);
- ppseudo_hdr =
- (struct pseudo_hdr *)(u16 *)&info->DSPInfoBlk[2];
- ppseudo_hdr->length = htons(info->DSPInfoBlklen + 4
- + info->DSPInfoBlklen);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- info->DSPInfoBlk[10] = 0x7200;
- info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen);
- status = ft1000_write_dpram32(dev, 0,
- (u8 *)&info->DSPInfoBlk[0],
- (unsigned short)(info->DSPInfoBlklen + 22));
- status = ft1000_write_register(dev, FT1000_DB_DPRAM_TX,
- FT1000_REG_DOORBELL);
- dev->DrvMsgPend = 0;
- break;
- }
- case GET_DRV_ERR_RPT_MSG:{
- pr_debug("Got GET_DRV_ERR_RPT_MSG\n");
- /* copy driver error message to dsp */
- dev->DrvMsgPend = 1;
- /* allow any outstanding ioctl to finish */
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- mdelay(10);
- }
- if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
- /* Put message into Slow Queue Form Pseudo header */
- pmsg = (u16 *)&tempbuffer[0];
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- ppseudo_hdr->length = htons(0x0012);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- pmsg = (u16 *)&tempbuffer[16];
- *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
- *pmsg++ = htons(0x000e);
- *pmsg++ = htons(info->DSP_TIME[0]);
- *pmsg++ = htons(info->DSP_TIME[1]);
- *pmsg++ = htons(info->DSP_TIME[2]);
- *pmsg++ = htons(info->DSP_TIME[3]);
- convert.byte[0] = info->DspVer[0];
- convert.byte[1] = info->DspVer[1];
- *pmsg++ = convert.wrd;
- convert.byte[0] = info->DspVer[2];
- convert.byte[1] = info->DspVer[3];
- *pmsg++ = convert.wrd;
- *pmsg++ = htons(info->DrvErrNum);
-
- status = card_send_command(dev,
- (unsigned char *)&tempbuffer[0],
- (u16)(0x0012 + PSEUDOSZ));
- if (status)
- goto out;
- info->DrvErrNum = 0;
- }
- dev->DrvMsgPend = 0;
- break;
- }
- default:
- break;
- }
-
- status = 0;
-out:
- kfree(cmdbuffer);
- return status;
-}
-
-/* Check which application has registered for dsp broadcast messages */
-static int dsp_broadcast_msg_id(struct ft1000_usb *dev)
-{
- struct dpram_blk *pdpram_blk;
- unsigned long flags;
- int i;
-
- for (i = 0; i < MAX_NUM_APP; i++) {
- if ((dev->app_info[i].DspBCMsgFlag)
- && (dev->app_info[i].fileobject)
- && (dev->app_info[i].NumOfMsg
- < MAX_MSG_LIMIT)) {
- pdpram_blk = ft1000_get_buffer(&freercvpool);
- if (pdpram_blk == NULL) {
- pr_debug("Out of memory in free receive command pool\n");
- dev->app_info[i].nRxMsgMiss++;
- return -1;
- }
- if (ft1000_receive_cmd(dev, pdpram_blk->pbuffer,
- MAX_CMD_SQSIZE)) {
- /* Put message into the
- * appropriate application block
- */
- dev->app_info[i].nRxMsg++;
- spin_lock_irqsave(&free_buff_lock, flags);
- list_add_tail(&pdpram_blk->list,
- &dev->app_info[i] .app_sqlist);
- dev->app_info[i].NumOfMsg++;
- spin_unlock_irqrestore(&free_buff_lock, flags);
- wake_up_interruptible(&dev->app_info[i]
- .wait_dpram_msg);
- } else {
- dev->app_info[i].nRxMsgMiss++;
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- pr_debug("ft1000_get_buffer NULL\n");
- return -1;
- }
- }
- }
- return 0;
-}
-
-static int handle_misc_portid(struct ft1000_usb *dev)
-{
- struct dpram_blk *pdpram_blk;
- int i;
-
- pdpram_blk = ft1000_get_buffer(&freercvpool);
- if (pdpram_blk == NULL) {
- pr_debug("Out of memory in free receive command pool\n");
- return -1;
- }
- if (!ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE))
- goto exit_failure;
-
- /* Search for correct application block */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (dev->app_info[i].app_id == ((struct pseudo_hdr *)
- pdpram_blk->pbuffer)->portdest)
- break;
- }
- if (i == MAX_NUM_APP) {
- pr_debug("No application matching id = %d\n",
- ((struct pseudo_hdr *)pdpram_blk->pbuffer)->portdest);
- goto exit_failure;
- } else if (dev->app_info[i].NumOfMsg > MAX_MSG_LIMIT) {
- goto exit_failure;
- } else {
- dev->app_info[i].nRxMsg++;
- /* Put message into the appropriate application block */
- list_add_tail(&pdpram_blk->list, &dev->app_info[i].app_sqlist);
- dev->app_info[i].NumOfMsg++;
- }
- return 0;
-
-exit_failure:
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- return -1;
-}
-
-int ft1000_poll(void *dev_id)
-{
- struct ft1000_usb *dev = (struct ft1000_usb *)dev_id;
- struct ft1000_info *info = netdev_priv(dev->net);
- u16 tempword;
- int status;
- u16 size;
- int i;
- u16 data;
- u16 modulo;
- u16 portid;
-
- if (ft1000_chkcard(dev) == FALSE) {
- pr_debug("failed\n");
- return -1;
- }
- status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
- if (!status) {
- if (tempword & FT1000_DB_DPRAM_RX) {
- status = ft1000_read_dpram16(dev,
- 0x200, (u8 *)&data, 0);
- size = ntohs(data) + 16 + 2;
- if (size % 4) {
- modulo = 4 - (size % 4);
- size = size + modulo;
- }
- status = ft1000_read_dpram16(dev, 0x201,
- (u8 *)&portid, 1);
- portid &= 0xff;
- if (size < MAX_CMD_SQSIZE) {
- switch (portid) {
- case DRIVERID:
- pr_debug("FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n");
- status = ft1000_proc_drvmsg(dev, size);
- if (status != 0)
- return status;
- break;
- case DSPBCMSGID:
- status = dsp_broadcast_msg_id(dev);
- break;
- default:
- status = handle_misc_portid(dev);
- break;
- }
- } else
- pr_debug("Invalid total length for SlowQ = %d\n",
- size);
- status = ft1000_write_register(dev,
- FT1000_DB_DPRAM_RX,
- FT1000_REG_DOORBELL);
- } else if (tempword & FT1000_DSP_ASIC_RESET) {
- /* Let's reset the ASIC from the Host side as well */
- status = ft1000_write_register(dev, ASIC_RESET_BIT,
- FT1000_REG_RESET);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_RESET);
- i = 0;
- while (tempword & ASIC_RESET_BIT) {
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_RESET);
- usleep_range(9000, 11000);
- i++;
- if (i == 100)
- break;
- }
- if (i == 100) {
- pr_debug("Unable to reset ASIC\n");
- return 0;
- }
- usleep_range(9000, 11000);
- /* Program WMARK register */
- status = ft1000_write_register(dev, 0x600,
- FT1000_REG_MAG_WATERMARK);
- /* clear ASIC reset doorbell */
- status = ft1000_write_register(dev,
- FT1000_DSP_ASIC_RESET,
- FT1000_REG_DOORBELL);
- usleep_range(9000, 11000);
- } else if (tempword & FT1000_ASIC_RESET_REQ) {
- pr_debug("FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n");
- /* clear ASIC reset request from DSP */
- status = ft1000_write_register(dev,
- FT1000_ASIC_RESET_REQ,
- FT1000_REG_DOORBELL);
- status = ft1000_write_register(dev, HOST_INTF_BE,
- FT1000_REG_SUP_CTRL);
- /* copy dsp session record from Adapter block */
- status = ft1000_write_dpram32(dev, 0,
- (u8 *)&info->DSPSess.Rec[0], 1024);
- status = ft1000_write_register(dev, 0x600,
- FT1000_REG_MAG_WATERMARK);
- /* ring doorbell to tell DSP that
- * ASIC is out of reset
- */
- status = ft1000_write_register(dev,
- FT1000_ASIC_RESET_DSP,
- FT1000_REG_DOORBELL);
- } else if (tempword & FT1000_DB_COND_RESET) {
- pr_debug("FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n");
- if (!dev->fAppMsgPend) {
- /* Reset ASIC and DSP */
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER0,
- (u8 *)&info->DSP_TIME[0],
- FT1000_MAG_DSP_TIMER0_INDX);
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER1,
- (u8 *)&info->DSP_TIME[1],
- FT1000_MAG_DSP_TIMER1_INDX);
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER2,
- (u8 *)&info->DSP_TIME[2],
- FT1000_MAG_DSP_TIMER2_INDX);
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER3,
- (u8 *)&info->DSP_TIME[3],
- FT1000_MAG_DSP_TIMER3_INDX);
- info->CardReady = 0;
- info->DrvErrNum = DSP_CONDRESET_INFO;
- pr_debug("DSP conditional reset requested\n");
- info->ft1000_reset(dev->net);
- } else {
- dev->fProvComplete = false;
- dev->fCondResetPend = true;
- }
- ft1000_write_register(dev, FT1000_DB_COND_RESET,
- FT1000_REG_DOORBELL);
- }
- }
- return 0;
-}
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
deleted file mode 100644
index e9472bebda0b..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- *---------------------------------------------------------------------------
- * FT1000 driver for Flarion Flash OFDM NIC Device
- *
- * Copyright (C) 2002 Flarion Technologies, 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. 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.
- *---------------------------------------------------------------------------
- *
- * File: ft1000_ioctl.h
- *
- * Description: Common structures and defines relating to IOCTL
- *
- * History:
- * 11/5/02 Whc Created.
- *
- *---------------------------------------------------------------------------
- */
-#ifndef _FT1000IOCTLH_
-#define _FT1000IOCTLH_
-
-struct IOCTL_GET_VER {
- unsigned long drv_ver;
-} __packed;
-
-/* Data structure for Dsp statistics */
-struct IOCTL_GET_DSP_STAT {
- unsigned char DspVer[DSPVERSZ]; /* DSP version number */
- unsigned char HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
- unsigned char Sku[SKUSZ]; /* SKU */
- unsigned char eui64[EUISZ]; /* EUI64 */
- unsigned short ConStat; /* Connection Status */
- /* Bits 0-3 = Connection Status Field */
- /* 0000=Idle (Disconnect) */
- /* 0001=Searching */
- /* 0010=Active (Connected) */
- /* 0011=Waiting for L2 down */
- /* 0100=Sleep */
- unsigned short LedStat; /* Led Status */
- /* Bits 0-3 = Signal Strength Field */
- /* 0000 = -105dBm to -92dBm */
- /* 0001 = -92dBm to -85dBm */
- /* 0011 = -85dBm to -75dBm */
- /* 0111 = -75dBm to -50dBm */
- /* 1111 = -50dBm to 0dBm */
- /* Bits 4-7 = Reserved */
- /* Bits 8-11 = SNR Field */
- /* 0000 = <2dB */
- /* 0001 = 2dB to 8dB */
- /* 0011 = 8dB to 15dB */
- /* 0111 = 15dB to 22dB */
- /* 1111 = >22dB */
- /* Bits 12-15 = Reserved */
- unsigned long nTxPkts; /* Number of packets transmitted
- * from host to dsp
- */
- unsigned long nRxPkts; /* Number of packets received from
- * dsp to host
- */
- unsigned long nTxBytes; /* Number of bytes transmitted
- * from host to dsp
- */
- unsigned long nRxBytes; /* Number of bytes received from
- * dsp to host
- */
- unsigned long ConTm; /* Current session connection time
- * in seconds
- */
- unsigned char CalVer[CALVERSZ]; /* Proprietary Calibration
- * Version
- */
- unsigned char CalDate[CALDATESZ]; /* Proprietary Calibration Date */
-} __packed;
-
-/* Data structure for Dual Ported RAM messaging between Host and Dsp */
-struct IOCTL_DPRAM_BLK {
- unsigned short total_len;
- struct pseudo_hdr pseudohdr;
- unsigned char buffer[1780];
-} __packed;
-
-struct IOCTL_DPRAM_COMMAND {
- unsigned short extra;
- struct IOCTL_DPRAM_BLK dpram_blk;
-} __packed;
-
-/*
- * Custom IOCTL command codes
- */
-#define FT1000_MAGIC_CODE 'F'
-
-#define IOCTL_REGISTER_CMD 0
-#define IOCTL_SET_DPRAM_CMD 3
-#define IOCTL_GET_DPRAM_CMD 4
-#define IOCTL_GET_DSP_STAT_CMD 6
-#define IOCTL_GET_VER_CMD 7
-#define IOCTL_CONNECT 10
-#define IOCTL_DISCONNECT 11
-
-#define IOCTL_FT1000_GET_DSP_STAT _IOR(FT1000_MAGIC_CODE, \
- IOCTL_GET_DSP_STAT_CMD, \
- struct IOCTL_GET_DSP_STAT)
-#define IOCTL_FT1000_GET_VER _IOR(FT1000_MAGIC_CODE, IOCTL_GET_VER_CMD, \
- struct IOCTL_GET_VER)
-#define IOCTL_FT1000_CONNECT _IO(FT1000_MAGIC_CODE, IOCTL_CONNECT)
-#define IOCTL_FT1000_DISCONNECT _IO(FT1000_MAGIC_CODE, IOCTL_DISCONNECT)
-#define IOCTL_FT1000_SET_DPRAM _IOW(FT1000_MAGIC_CODE, IOCTL_SET_DPRAM_CMD, \
- struct IOCTL_DPRAM_BLK)
-#define IOCTL_FT1000_GET_DPRAM _IOR(FT1000_MAGIC_CODE, IOCTL_GET_DPRAM_CMD, \
- struct IOCTL_DPRAM_BLK)
-#define IOCTL_FT1000_REGISTER _IOW(FT1000_MAGIC_CODE, IOCTL_REGISTER_CMD, \
- unsigned short *)
-
-#endif /* _FT1000IOCTLH_ */
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
deleted file mode 100644
index d1ba0b827a55..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*=====================================================
- * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
- *
- *
- * This file is part of Express Card USB Driver
- *====================================================
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/firmware.h>
-#include "ft1000_usb.h"
-
-#include <linux/kthread.h>
-
-MODULE_DESCRIPTION("FT1000 EXPRESS CARD DRIVER");
-MODULE_LICENSE("Dual MPL/GPL");
-MODULE_SUPPORTED_DEVICE("QFT FT1000 Express Cards");
-
-void *pFileStart;
-size_t FileLength;
-
-#define VENDOR_ID 0x1291 /* Qualcomm vendor id */
-#define PRODUCT_ID 0x11 /* fake product id */
-
-/* table of devices that work with this driver */
-static struct usb_device_id id_table[] = {
- {USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
- {},
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static bool gPollingfailed;
-static int ft1000_poll_thread(void *arg)
-{
- int ret;
-
- while (!kthread_should_stop()) {
- usleep_range(10000, 11000);
- if (!gPollingfailed) {
- ret = ft1000_poll(arg);
- if (ret != 0) {
- pr_debug("polling failed\n");
- gPollingfailed = true;
- }
- }
- }
- return 0;
-}
-
-static int ft1000_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- struct usb_device *dev;
- unsigned numaltsetting;
- int i, ret = 0, size;
-
- struct ft1000_usb *ft1000dev;
- struct ft1000_info *pft1000info = NULL;
- const struct firmware *dsp_fw;
-
- ft1000dev = kzalloc(sizeof(struct ft1000_usb), GFP_KERNEL);
- if (!ft1000dev)
- return -ENOMEM;
-
- dev = interface_to_usbdev(interface);
- pr_debug("usb device descriptor info - number of configuration is %d\n",
- dev->descriptor.bNumConfigurations);
-
- ft1000dev->dev = dev;
- ft1000dev->status = 0;
- ft1000dev->net = NULL;
- ft1000dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- ft1000dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ft1000dev->tx_urb || !ft1000dev->rx_urb) {
- ret = -ENOMEM;
- goto err_fw;
- }
-
- numaltsetting = interface->num_altsetting;
- pr_debug("number of alt settings is: %d\n", numaltsetting);
- iface_desc = interface->cur_altsetting;
- pr_debug("number of endpoints is: %d\n",
- iface_desc->desc.bNumEndpoints);
- pr_debug("descriptor type is: %d\n", iface_desc->desc.bDescriptorType);
- pr_debug("interface number is: %d\n",
- iface_desc->desc.bInterfaceNumber);
- pr_debug("alternatesetting is: %d\n",
- iface_desc->desc.bAlternateSetting);
- pr_debug("interface class is: %d\n", iface_desc->desc.bInterfaceClass);
- pr_debug("control endpoint info:\n");
- pr_debug("descriptor0 type -- %d\n",
- iface_desc->endpoint[0].desc.bmAttributes);
- pr_debug("descriptor1 type -- %d\n",
- iface_desc->endpoint[1].desc.bmAttributes);
- pr_debug("descriptor2 type -- %d\n",
- iface_desc->endpoint[2].desc.bmAttributes);
-
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- endpoint =
- (struct usb_endpoint_descriptor *)&iface_desc->
- endpoint[i].desc;
- pr_debug("endpoint %d\n", i);
- pr_debug("bEndpointAddress=%x, bmAttributes=%x\n",
- endpoint->bEndpointAddress, endpoint->bmAttributes);
- if (usb_endpoint_is_bulk_in(endpoint)) {
- ft1000dev->bulk_in_endpointAddr =
- endpoint->bEndpointAddress;
- pr_debug("in: %d\n", endpoint->bEndpointAddress);
- }
-
- if (usb_endpoint_is_bulk_in(endpoint)) {
- ft1000dev->bulk_out_endpointAddr =
- endpoint->bEndpointAddress;
- pr_debug("out: %d\n", endpoint->bEndpointAddress);
- }
- }
-
- pr_debug("bulk_in=%d, bulk_out=%d\n",
- ft1000dev->bulk_in_endpointAddr,
- ft1000dev->bulk_out_endpointAddr);
-
- ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev);
- if (ret < 0) {
- dev_err(interface->usb_dev, "Error request_firmware()\n");
- goto err_fw;
- }
-
- size = max_t(uint, dsp_fw->size, 4096);
- pFileStart = kmalloc(size, GFP_KERNEL);
-
- if (!pFileStart) {
- release_firmware(dsp_fw);
- ret = -ENOMEM;
- goto err_fw;
- }
-
- memcpy(pFileStart, dsp_fw->data, dsp_fw->size);
- FileLength = dsp_fw->size;
- release_firmware(dsp_fw);
-
- pr_debug("start downloading dsp image...\n");
-
- ret = init_ft1000_netdev(ft1000dev);
- if (ret)
- goto err_load;
-
- pft1000info = netdev_priv(ft1000dev->net);
-
- pr_debug("pft1000info=%p\n", pft1000info);
- ret = dsp_reload(ft1000dev);
- if (ret) {
- dev_err(interface->usb_dev,
- "Problem with DSP image loading\n");
- goto err_load;
- }
-
- gPollingfailed = false;
- ft1000dev->pPollThread =
- kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll");
-
- if (IS_ERR(ft1000dev->pPollThread)) {
- ret = PTR_ERR(ft1000dev->pPollThread);
- goto err_load;
- }
-
- msleep(500);
-
- while (!pft1000info->CardReady) {
- if (gPollingfailed) {
- ret = -EIO;
- goto err_thread;
- }
- msleep(100);
- pr_debug("Waiting for Card Ready\n");
- }
-
- pr_debug("Card Ready!!!! Registering network device\n");
-
- ret = reg_ft1000_netdev(ft1000dev, interface);
- if (ret)
- goto err_thread;
-
- ft1000dev->NetDevRegDone = 1;
-
- return 0;
-
-err_thread:
- kthread_stop(ft1000dev->pPollThread);
-err_load:
- kfree(pFileStart);
-err_fw:
- usb_free_urb(ft1000dev->rx_urb);
- usb_free_urb(ft1000dev->tx_urb);
- kfree(ft1000dev);
- return ret;
-}
-
-static void ft1000_disconnect(struct usb_interface *interface)
-{
- struct ft1000_info *pft1000info;
- struct ft1000_usb *ft1000dev;
-
- pft1000info = (struct ft1000_info *)usb_get_intfdata(interface);
- pr_debug("In disconnect pft1000info=%p\n", pft1000info);
-
- if (pft1000info) {
- ft1000dev = pft1000info->priv;
- if (ft1000dev->pPollThread)
- kthread_stop(ft1000dev->pPollThread);
-
- pr_debug("threads are terminated\n");
-
- if (ft1000dev->net) {
- pr_debug("destroy char driver\n");
- ft1000_destroy_dev(ft1000dev->net);
- unregister_netdev(ft1000dev->net);
- pr_debug("network device unregistered\n");
- free_netdev(ft1000dev->net);
-
- }
-
- usb_free_urb(ft1000dev->rx_urb);
- usb_free_urb(ft1000dev->tx_urb);
-
- pr_debug("urb freed\n");
-
- kfree(ft1000dev);
- }
- kfree(pFileStart);
-}
-
-static struct usb_driver ft1000_usb_driver = {
- .name = "ft1000usb",
- .probe = ft1000_probe,
- .disconnect = ft1000_disconnect,
- .id_table = id_table,
-};
-
-module_usb_driver(ft1000_usb_driver);
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
deleted file mode 100644
index 9b5050fcbb66..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifndef _FT1000_USB_H_
-#define _FT1000_USB_H_
-
-#include "../ft1000.h"
-#include "ft1000_ioctl.h"
-#define FT1000_DRV_VER 0x01010403
-
-#define MAX_NUM_APP 6
-#define MAX_MSG_LIMIT 200
-#define NUM_OF_FREE_BUFFERS 1500
-
-#define PSEUDOSZ 16
-
-struct app_info_block {
- u32 nTxMsg; /* DPRAM msg sent to DSP with app_id */
- u32 nRxMsg; /* DPRAM msg rcv from dsp with app_id */
- u32 nTxMsgReject; /* DPRAM msg rejected due to DSP doorbell
- * set
- */
- u32 nRxMsgMiss; /* DPRAM msg dropped due to overflow */
- struct fown_struct *fileobject;/* Application's file object */
- u16 app_id; /* Application id */
- int DspBCMsgFlag;
- int NumOfMsg; /* number of messages queued up */
- wait_queue_head_t wait_dpram_msg;
- struct list_head app_sqlist; /* link list of msgs for applicaton on
- * slow queue
- */
-} __packed;
-
-#define FALSE 0
-#define TRUE 1
-
-#define FT1000_STATUS_CLOSING 0x01
-
-#define DSPBCMSGID 0x10
-
-/* Electrabuzz specific DPRAM mapping */
-/* this is used by ft1000_usb driver - isn't that a bug? */
-#undef FT1000_DPRAM_RX_BASE
-#define FT1000_DPRAM_RX_BASE 0x1800 /* RX AREA (SlowQ) */
-
-/* MEMORY MAP FOR MAGNEMITE */
-/* the indexes are swapped comparing to PCMCIA - is it OK or a bug? */
-#undef FT1000_MAG_DSP_LED_INDX
-#define FT1000_MAG_DSP_LED_INDX 0x1 /* dsp led status for PAD
- * device
- */
-#undef FT1000_MAG_DSP_CON_STATE_INDX
-#define FT1000_MAG_DSP_CON_STATE_INDX 0x0 /* DSP Connection Status Info */
-
-/* Maximum times trying to get ASIC out of reset */
-#define MAX_ASIC_RESET_CNT 20
-
-#define MAX_BUF_SIZE 4096
-
-struct ft1000_debug_dirs {
- struct list_head list;
- struct dentry *dent;
- struct dentry *file;
- int int_number;
-};
-
-struct ft1000_usb {
- struct usb_device *dev;
- struct net_device *net;
-
- u32 status;
-
- struct urb *rx_urb;
- struct urb *tx_urb;
-
- u8 tx_buf[MAX_BUF_SIZE];
- u8 rx_buf[MAX_BUF_SIZE];
-
- u8 bulk_in_endpointAddr;
- u8 bulk_out_endpointAddr;
-
- struct task_struct *pPollThread;
- unsigned char fcodeldr;
- unsigned char bootmode;
- unsigned char usbboot;
- unsigned short dspalive;
- bool fProvComplete;
- bool fCondResetPend;
- bool fAppMsgPend;
- int DeviceCreated;
- int NetDevRegDone;
- u8 CardNumber;
- u8 DeviceName[15];
- struct ft1000_debug_dirs nodes;
- spinlock_t fifo_lock;
- int appcnt;
- struct app_info_block app_info[MAX_NUM_APP];
- u16 DrvMsgPend;
- unsigned short tempbuf[32];
-} __packed;
-
-
-struct dpram_blk {
- struct list_head list;
- u16 *pbuffer;
-} __packed;
-
-int ft1000_read_register(struct ft1000_usb *ft1000dev,
- u16 *Data, u16 nRegIndx);
-int ft1000_write_register(struct ft1000_usb *ft1000dev,
- u16 value, u16 nRegIndx);
-int ft1000_read_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer, u16 cnt);
-int ft1000_write_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer, u16 cnt);
-int ft1000_read_dpram16(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer, u8 highlow);
-int ft1000_write_dpram16(struct ft1000_usb *ft1000dev,
- u16 indx, u16 value, u8 highlow);
-int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer);
-int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer);
-
-extern void *pFileStart;
-extern size_t FileLength;
-extern int numofmsgbuf;
-
-int ft1000_close(struct net_device *dev);
-int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
- u32 FileLength);
-
-extern struct list_head freercvpool;
-
-/* lock to arbitrate free buffer list for receive command data */
-extern spinlock_t free_buff_lock;
-
-int ft1000_create_dev(struct ft1000_usb *dev);
-void ft1000_destroy_dev(struct net_device *dev);
-int card_send_command(struct ft1000_usb *ft1000dev,
- void *ptempbuffer, int size);
-
-struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist);
-void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist);
-
-int dsp_reload(struct ft1000_usb *ft1000dev);
-int init_ft1000_netdev(struct ft1000_usb *ft1000dev);
-struct usb_interface;
-int reg_ft1000_netdev(struct ft1000_usb *ft1000dev,
- struct usb_interface *intf);
-int ft1000_poll(void *dev_id);
-
-#endif /* _FT1000_USB_H_ */
diff --git a/drivers/staging/ft1000/ft1000-usb/ft3000.img b/drivers/staging/ft1000/ft1000-usb/ft3000.img
deleted file mode 100644
index 7bef6bd3680a..000000000000
--- a/drivers/staging/ft1000/ft1000-usb/ft3000.img
+++ /dev/null
Binary files differ
diff --git a/drivers/staging/ft1000/ft1000.h b/drivers/staging/ft1000/ft1000.h
deleted file mode 100644
index 8a2e4caa532d..000000000000
--- a/drivers/staging/ft1000/ft1000.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Common structures and definitions for FT1000 Flarion Flash OFDM PCMCIA and
- * USB devices.
- *
- * Originally copyright (c) 2002 Flarion Technologies
- *
- */
-
-#define DSPVERSZ 4
-#define HWSERNUMSZ 16
-#define SKUSZ 20
-#define EUISZ 8
-#define MODESZ 2
-#define CALVERSZ 2
-#define CALDATESZ 6
-
-#define ELECTRABUZZ_ID 0 /* ASIC ID for Electrabuzz */
-#define MAGNEMITE_ID 0x1a01 /* ASIC ID for Magnemite */
-
-/* MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE */
-#define FT1000_REG_DPRAM_ADDR 0x000E /* DPADR - Dual Port Ram Indirect
- * Address Register
- */
-#define FT1000_REG_SUP_CTRL 0x0020 /* HCTR - Host Control Register */
-#define FT1000_REG_SUP_STAT 0x0022 /* HSTAT - Host Status Register */
-#define FT1000_REG_RESET 0x0024 /* HCTR - Host Control Register */
-#define FT1000_REG_SUP_ISR 0x0026 /* HISR - Host Interrupt Status
- * Register
- */
-#define FT1000_REG_SUP_IMASK 0x0028 /* HIMASK - Host Interrupt Mask */
-#define FT1000_REG_DOORBELL 0x002a /* DBELL - Door Bell Register */
-#define FT1000_REG_ASIC_ID 0x002e /* ASICID - ASIC Identification
- * Number
- */
-
-/* MEMORY MAP FOR ELECTRABUZZ ASIC */
-#define FT1000_REG_UFIFO_STAT 0x0000 /* UFSR - Uplink FIFO status register */
-#define FT1000_REG_UFIFO_BEG 0x0002 /* UFBR - Uplink FIFO beginning
- * register
- */
-#define FT1000_REG_UFIFO_MID 0x0004 /* UFMR - Uplink FIFO middle register */
-#define FT1000_REG_UFIFO_END 0x0006 /* UFER - Uplink FIFO end register */
-#define FT1000_REG_DFIFO_STAT 0x0008 /* DFSR - Downlink FIFO status
- * register
- */
-#define FT1000_REG_DFIFO 0x000A /* DFR - Downlink FIFO Register */
-#define FT1000_REG_DPRAM_DATA 0x000C /* DPRAM - Dual Port Indirect
- * Data Register
- */
-#define FT1000_REG_WATERMARK 0x0010 /* WMARK - Watermark Register */
-
-/* MEMORY MAP FOR MAGNEMITE */
-#define FT1000_REG_MAG_UFDR 0x0000 /* UFDR - Uplink FIFO Data
- * Register (32-bits)
- */
-#define FT1000_REG_MAG_UFDRL 0x0000 /* UFDRL - Uplink FIFO Data
- * Register low-word (16-bits)
- */
-#define FT1000_REG_MAG_UFDRH 0x0002 /* UFDRH - Uplink FIFO Data Register
- * high-word (16-bits)
- */
-#define FT1000_REG_MAG_UFER 0x0004 /* UFER - Uplink FIFO End Register */
-#define FT1000_REG_MAG_UFSR 0x0006 /* UFSR - Uplink FIFO Status Register */
-#define FT1000_REG_MAG_DFR 0x0008 /* DFR - Downlink FIFO Register
- * (32-bits)
- */
-#define FT1000_REG_MAG_DFRL 0x0008 /* DFRL - Downlink FIFO Register
- * low-word (16-bits)
- */
-#define FT1000_REG_MAG_DFRH 0x000a /* DFRH - Downlink FIFO Register
- * high-word (16-bits)
- */
-#define FT1000_REG_MAG_DFSR 0x000c /* DFSR - Downlink FIFO Status
- * Register
- */
-#define FT1000_REG_MAG_DPDATA 0x0010 /* DPDATA - Dual Port RAM Indirect
- * Data Register (32-bits)
- */
-#define FT1000_REG_MAG_DPDATAL 0x0010 /* DPDATAL - Dual Port RAM Indirect
- * Data Register low-word (16-bits)
- */
-#define FT1000_REG_MAG_DPDATAH 0x0012 /* DPDATAH - Dual Port RAM Indirect Data
- * Register high-word (16-bits)
- */
-#define FT1000_REG_MAG_WATERMARK 0x002c /* WMARK - Watermark Register */
-#define FT1000_REG_MAG_VERSION 0x0030 /* LLC Version */
-
-/* Reserved Dual Port RAM offsets for Electrabuzz */
-#define FT1000_DPRAM_TX_BASE 0x0002 /* Host to PC Card Messaging Area */
-#define FT1000_DPRAM_RX_BASE 0x0800 /* PC Card to Host Messaging Area */
-#define FT1000_FIFO_LEN 0x07FC /* total length for DSP FIFO tracking */
-#define FT1000_HI_HO 0x07FE /* heartbeat with HI/HO */
-#define FT1000_DSP_STATUS 0x0FFE /* dsp status - non-zero is a request
- * to reset dsp
- */
-#define FT1000_DSP_LED 0x0FFA /* dsp led status for PAD device */
-#define FT1000_DSP_CON_STATE 0x0FF8 /* DSP Connection Status Info */
-#define FT1000_DPRAM_FEFE 0x0002 /* location for dsp ready indicator */
-#define FT1000_DSP_TIMER0 0x1FF0 /* Timer Field from Basestation */
-#define FT1000_DSP_TIMER1 0x1FF2 /* Timer Field from Basestation */
-#define FT1000_DSP_TIMER2 0x1FF4 /* Timer Field from Basestation */
-#define FT1000_DSP_TIMER3 0x1FF6 /* Timer Field from Basestation */
-
-/* Reserved Dual Port RAM offsets for Magnemite */
-#define FT1000_DPRAM_MAG_TX_BASE 0x0000 /* Host to PC Card
- * Messaging Area
- */
-#define FT1000_DPRAM_MAG_RX_BASE 0x0200 /* PC Card to Host
- * Messaging Area
- */
-
-#define FT1000_MAG_FIFO_LEN 0x1FF /* total length for DSP
- * FIFO tracking
- */
-#define FT1000_MAG_FIFO_LEN_INDX 0x1 /* low-word index */
-#define FT1000_MAG_HI_HO 0x1FF /* heartbeat with HI/HO */
-#define FT1000_MAG_HI_HO_INDX 0x0 /* high-word index */
-#define FT1000_MAG_DSP_LED 0x3FE /* dsp led status for
- * PAD device
- */
-#define FT1000_MAG_DSP_LED_INDX 0x0 /* dsp led status for
- * PAD device
- */
-#define FT1000_MAG_DSP_CON_STATE 0x3FE /* DSP Connection Status Info */
-#define FT1000_MAG_DSP_CON_STATE_INDX 0x1 /* DSP Connection Status Info */
-#define FT1000_MAG_DPRAM_FEFE 0x000 /* location for dsp ready
- * indicator
- */
-#define FT1000_MAG_DPRAM_FEFE_INDX 0x0 /* location for dsp ready
- * indicator
- */
-#define FT1000_MAG_DSP_TIMER0 0x3FC /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER0_INDX 0x1
-#define FT1000_MAG_DSP_TIMER1 0x3FC /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER1_INDX 0x0
-#define FT1000_MAG_DSP_TIMER2 0x3FD /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER2_INDX 0x1
-#define FT1000_MAG_DSP_TIMER3 0x3FD /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER3_INDX 0x0
-#define FT1000_MAG_TOTAL_LEN 0x200
-#define FT1000_MAG_TOTAL_LEN_INDX 0x1
-#define FT1000_MAG_PH_LEN 0x200
-#define FT1000_MAG_PH_LEN_INDX 0x0
-#define FT1000_MAG_PORT_ID 0x201
-#define FT1000_MAG_PORT_ID_INDX 0x0
-
-#define HOST_INTF_LE 0x0 /* Host interface little endian mode */
-#define HOST_INTF_BE 0x1 /* Host interface big endian mode */
-
-/* FT1000 to Host Doorbell assignments */
-#define FT1000_DB_DPRAM_RX 0x0001 /* this value indicates that DSP
- * has data for host in DPRAM
- */
-#define FT1000_DB_DNLD_RX 0x0002 /* Downloader handshake doorbell */
-#define FT1000_ASIC_RESET_REQ 0x0004 /* DSP requesting host to
- * reset the ASIC
- */
-#define FT1000_DSP_ASIC_RESET 0x0008 /* DSP indicating host that
- * it will reset the ASIC
- */
-#define FT1000_DB_COND_RESET 0x0010 /* DSP request for a card reset. */
-
-/* Host to FT1000 Doorbell assignments */
-#define FT1000_DB_DPRAM_TX 0x0100 /* this value indicates that host
- * has data for DSP in DPRAM.
- */
-#define FT1000_DB_DNLD_TX 0x0200 /* Downloader handshake doorbell */
-#define FT1000_ASIC_RESET_DSP 0x0400 /* Responds to FT1000_ASIC_RESET_REQ */
-#define FT1000_DB_HB 0x1000 /* Indicates that supervisor has a
- * heartbeat message for DSP.
- */
-
-#define hi 0x6869 /* PC Card heartbeat values */
-#define ho 0x686f /* PC Card heartbeat values */
-
-/* Magnemite specific defines */
-#define hi_mag 0x6968 /* Byte swap hi to avoid
- * additional system call
- */
-#define ho_mag 0x6f68 /* Byte swap ho to avoid
- * additional system call
- */
-
-/* Bit field definitions for Host Interrupt Status Register */
-/* Indicate the cause of an interrupt. */
-#define ISR_EMPTY 0x00 /* no bits set */
-#define ISR_DOORBELL_ACK 0x01 /* Doorbell acknowledge from DSP */
-#define ISR_DOORBELL_PEND 0x02 /* Doorbell pending from DSP */
-#define ISR_RCV 0x04 /* Packet available in Downlink FIFO */
-#define ISR_WATERMARK 0x08 /* Watermark requirements satisfied */
-
-/* Bit field definition for Host Interrupt Mask */
-#define ISR_MASK_NONE 0x0000 /* no bits set */
-#define ISR_MASK_DOORBELL_ACK 0x0001 /* Doorbell acknowledge mask */
-#define ISR_MASK_DOORBELL_PEND 0x0002 /* Doorbell pending mask */
-#define ISR_MASK_RCV 0x0004 /* Downlink Packet available mask */
-#define ISR_MASK_WATERMARK 0x0008 /* Watermark interrupt mask */
-#define ISR_MASK_ALL 0xffff /* Mask all interrupts */
-/* Default interrupt mask
- * (Enable Doorbell pending and Packet available interrupts)
- */
-#define ISR_DEFAULT_MASK 0x7ff9
-
-/* Bit field definition for Host Control Register */
-#define DSP_RESET_BIT 0x0001 /* Bit field to control
- * dsp reset state
- */
- /* (0 = out of reset 1 = reset) */
-#define ASIC_RESET_BIT 0x0002 /* Bit field to control
- * ASIC reset state
- */
- /* (0 = out of reset 1 = reset) */
-#define DSP_UNENCRYPTED 0x0004
-#define DSP_ENCRYPTED 0x0008
-#define EFUSE_MEM_DISABLE 0x0040
-
-/* Application specific IDs */
-#define DSPID 0x20
-#define HOSTID 0x10
-#define DSPAIRID 0x90
-#define DRIVERID 0x00
-#define NETWORKID 0x20
-
-/* Size of DPRAM Message */
-#define MAX_CMD_SQSIZE 1780
-
-#define ENET_MAX_SIZE 1514
-#define ENET_HEADER_SIZE 14
-
-#define SLOWQ_TYPE 0
-#define FASTQ_TYPE 1
-
-#define MAX_DSP_SESS_REC 1024
-
-#define DSP_QID_OFFSET 4
-
-/* Driver message types */
-#define MEDIA_STATE 0x0010
-#define TIME_UPDATE 0x0020
-#define DSP_PROVISION 0x0030
-#define DSP_INIT_MSG 0x0050
-#define DSP_HIBERNATE 0x0060
-#define DSP_STORE_INFO 0x0070
-#define DSP_GET_INFO 0x0071
-#define GET_DRV_ERR_RPT_MSG 0x0073
-#define RSP_DRV_ERR_RPT_MSG 0x0074
-
-/* Driver Error Messages for DSP */
-#define DSP_HB_INFO 0x7ef0
-#define DSP_FIFO_INFO 0x7ef1
-#define DSP_CONDRESET_INFO 0x7ef2
-#define DSP_CMDLEN_INFO 0x7ef3
-#define DSP_CMDPHCKSUM_INFO 0x7ef4
-#define DSP_PKTPHCKSUM_INFO 0x7ef5
-#define DSP_PKTLEN_INFO 0x7ef6
-#define DSP_USER_RESET 0x7ef7
-#define FIFO_FLUSH_MAXLIMIT 0x7ef8
-#define FIFO_FLUSH_BADCNT 0x7ef9
-#define FIFO_ZERO_LEN 0x7efa
-
-/* Pseudo Header structure */
-struct pseudo_hdr {
- unsigned short length; /* length of msg body */
- unsigned char source; /* hardware source id */
- /* Host = 0x10 */
- /* Dsp = 0x20 */
- unsigned char destination; /* hardware destination id
- * (refer to source)
- */
- unsigned char portdest; /* software destination port id */
- /* Host = 0x00 */
- /* Applicaton Broadcast = 0x10 */
- /* Network Stack = 0x20 */
- /* Dsp OAM = 0x80 */
- /* Dsp Airlink = 0x90 */
- /* Dsp Loader = 0xa0 */
- /* Dsp MIP = 0xb0 */
- unsigned char portsrc; /* software source port id
- * (refer to portdest)
- */
- unsigned short sh_str_id; /* not used */
- unsigned char control; /* not used */
- unsigned char rsvd1;
- unsigned char seq_num; /* message sequence number */
- unsigned char rsvd2;
- unsigned short qos_class; /* not used */
- unsigned short checksum; /* pseudo header checksum */
-} __packed;
-
-struct drv_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u8 data[0];
-} __packed;
-
-struct media_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u16 state;
- u32 ip_addr;
- u32 net_mask;
- u32 gateway;
- u32 dns_1;
- u32 dns_2;
-} __packed;
-
-struct dsp_init_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u8 DspVer[DSPVERSZ]; /* DSP version number */
- u8 HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
- u8 Sku[SKUSZ]; /* SKU */
- u8 eui64[EUISZ]; /* EUI64 */
- u8 ProductMode[MODESZ]; /* Product Mode (Market/Production) */
- u8 RfCalVer[CALVERSZ]; /* Rf Calibration version */
- u8 RfCalDate[CALDATESZ]; /* Rf Calibration date */
-} __packed;
-
-struct prov_record {
- struct list_head list;
- u8 *pprov_data;
-};
-
-struct ft1000_info {
- void *priv;
- struct net_device_stats stats;
- u16 DrvErrNum;
- u16 AsicID;
- int CardReady;
- int registered;
- int mediastate;
- u8 squeseqnum; /* sequence number on slow queue */
- spinlock_t dpram_lock;
- u16 fifo_cnt;
- u8 DspVer[DSPVERSZ]; /* DSP version number */
- u8 HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
- u8 Sku[SKUSZ]; /* SKU */
- u8 eui64[EUISZ]; /* EUI64 */
- time_t ConTm; /* Connection Time */
- u8 ProductMode[MODESZ];
- u8 RfCalVer[CALVERSZ];
- u8 RfCalDate[CALDATESZ];
- u16 DSP_TIME[4];
- u16 LedStat;
- u16 ConStat;
- u16 ProgConStat;
- struct list_head prov_list;
- u16 DSPInfoBlklen;
- int (*ft1000_reset)(void *);
- u16 DSPInfoBlk[MAX_DSP_SESS_REC];
- union {
- u16 Rec[MAX_DSP_SESS_REC];
- u32 MagRec[MAX_DSP_SESS_REC/2];
- } DSPSess;
-};
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index b3ea4bb54e2c..b676c486cb18 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -893,11 +893,10 @@ static void fwserial_destroy(struct kref *kref)
kfree(serial);
}
-void fwtty_port_put(struct fwtty_port *port)
+static void fwtty_port_put(struct fwtty_port *port)
{
kref_put(&port->serial->kref, fwserial_destroy);
}
-EXPORT_SYMBOL(fwtty_port_put);
static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on)
{
diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h
index 787aa4f3a41b..e13fe33a6897 100644
--- a/drivers/staging/fwserial/fwserial.h
+++ b/drivers/staging/fwserial/fwserial.h
@@ -342,16 +342,6 @@ static const char loop_dev_name[] = "fwloop";
extern struct tty_driver *fwtty_driver;
struct fwtty_port *fwtty_port_get(unsigned index);
-void fwtty_port_put(struct fwtty_port *port);
-
-static inline void fwtty_bind_console(struct fwtty_port *port,
- struct fwconsole_ops *fwcon_ops,
- void *data)
-{
- port->con_data = data;
- port->fwcon_ops = fwcon_ops;
-}
-
/*
* Returns the max send async payload size in bytes based on the unit device
* link speed. Self-limiting asynchronous bandwidth (via reducing the payload)
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
index 8a55ec1e5331..17d148f6e02c 100644
--- a/drivers/staging/gdm724x/gdm_lte.c
+++ b/drivers/staging/gdm724x/gdm_lte.c
@@ -162,11 +162,11 @@ static int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type)
skb_reserve(skb_out, NET_IP_ALIGN);
memcpy(skb_put(skb_out, mac_header_len), mac_header_data,
- mac_header_len);
+ mac_header_len);
memcpy(skb_put(skb_out, sizeof(struct arphdr)), arp_out,
- sizeof(struct arphdr));
+ sizeof(struct arphdr));
memcpy(skb_put(skb_out, sizeof(struct arpdata)), arp_data_out,
- sizeof(struct arpdata));
+ sizeof(struct arpdata));
skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
skb_out->dev = skb_in->dev;
@@ -300,13 +300,13 @@ static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
memcpy(&ipv6_out, ipv6_in, sizeof(struct ipv6hdr));
memcpy(ipv6_out.saddr.in6_u.u6_addr8, &na.target_address, 16);
memcpy(ipv6_out.daddr.in6_u.u6_addr8,
- ipv6_in->saddr.in6_u.u6_addr8, 16);
+ ipv6_in->saddr.in6_u.u6_addr8, 16);
ipv6_out.payload_len = htons(sizeof(struct icmp6hdr) +
sizeof(struct neighbour_advertisement));
memcpy(icmp_na, &icmp6_out, sizeof(struct icmp6hdr));
memcpy(icmp_na + sizeof(struct icmp6hdr), &na,
- sizeof(struct neighbour_advertisement));
+ sizeof(struct neighbour_advertisement));
icmp6_out.icmp6_cksum = icmp6_checksum(&ipv6_out,
(u16 *)icmp_na, sizeof(icmp_na));
@@ -326,13 +326,13 @@ static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
skb_reserve(skb_out, NET_IP_ALIGN);
memcpy(skb_put(skb_out, mac_header_len), mac_header_data,
- mac_header_len);
+ mac_header_len);
memcpy(skb_put(skb_out, sizeof(struct ipv6hdr)), &ipv6_out,
- sizeof(struct ipv6hdr));
+ sizeof(struct ipv6hdr));
memcpy(skb_put(skb_out, sizeof(struct icmp6hdr)), &icmp6_out,
- sizeof(struct icmp6hdr));
+ sizeof(struct icmp6hdr));
memcpy(skb_put(skb_out, sizeof(struct neighbour_advertisement)), &na,
- sizeof(struct neighbour_advertisement));
+ sizeof(struct neighbour_advertisement));
skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
skb_out->dev = skb_in->dev;
@@ -530,7 +530,7 @@ static int gdm_lte_event_send(struct net_device *dev, char *buf, int len)
}
static void gdm_lte_event_rcv(struct net_device *dev, u16 type,
- void *msg, int len)
+ void *msg, int len)
{
struct nic *nic = netdev_priv(dev);
@@ -555,7 +555,7 @@ int gdm_lte_event_init(void)
void gdm_lte_event_exit(void)
{
if (lte_event.sock && --lte_event.ref_cnt == 0) {
- netlink_exit(lte_event.sock);
+ sock_release(lte_event.sock->sk_socket);
lte_event.sock = NULL;
}
}
@@ -572,7 +572,7 @@ static u8 find_dev_index(u32 nic_type)
}
static void gdm_lte_netif_rx(struct net_device *dev, char *buf,
- int len, int flagged_nic_type)
+ int len, int flagged_nic_type)
{
u32 nic_type;
struct nic *nic;
@@ -697,9 +697,9 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
u8 index;
hci_len = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev),
- multi_sdu->len);
+ multi_sdu->len);
num_packet = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev),
- multi_sdu->num_packet);
+ multi_sdu->num_packet);
for (i = 0; i < num_packet; i++) {
sdu = (struct sdu *)data;
@@ -724,12 +724,12 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
if (index < MAX_NIC_TYPE) {
dev = phy_dev->dev[index];
gdm_lte_netif_rx(dev, (char *)sdu->data,
- (int)(hci_len-12), nic_type);
+ (int)(hci_len - 12), nic_type);
} else {
pr_err("rx sdu invalid nic_type :%x\n", nic_type);
}
- data += ((hci_len+3) & 0xfffc) + HCI_HEADER_SIZE;
+ data += ((hci_len + 3) & 0xfffc) + HCI_HEADER_SIZE;
}
}
@@ -772,10 +772,10 @@ static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len)
return ret;
cmd_evt = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev),
- hci->cmd_evt);
+ hci->cmd_evt);
dev = phy_dev->dev[0];
- if (dev == NULL)
+ if (!dev)
return 0;
switch (cmd_evt) {
@@ -839,7 +839,7 @@ static struct net_device_ops gdm_netdev_ops = {
static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00};
static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest,
- u8 *mac_address, u8 index)
+ u8 *mac_address, u8 index)
{
/* Form the dev_addr */
if (!mac_address)
@@ -850,7 +850,7 @@ static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest,
/* The last byte of the mac address
* should be less than or equal to 0xFC
*/
- dev_addr[ETH_ALEN-1] += index;
+ dev_addr[ETH_ALEN - 1] += index;
/* Create random nic src and copy the first
* 3 bytes to be the same as dev_addr
@@ -938,7 +938,7 @@ void unregister_lte_device(struct phy_dev *phy_dev)
for (index = 0; index < MAX_NIC_TYPE; index++) {
net = phy_dev->dev[index];
- if (net == NULL)
+ if (!net)
continue;
unregister_netdev(net);
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
index 07de99cf473e..445f83615575 100644
--- a/drivers/staging/gdm724x/gdm_mux.c
+++ b/drivers/staging/gdm724x/gdm_mux.c
@@ -48,7 +48,6 @@ static const struct usb_device_id id_table[] = {
{}
};
-
MODULE_DEVICE_TABLE(usb, id_table);
static int packet_type_to_index(u16 packetType)
@@ -67,7 +66,7 @@ static struct mux_tx *alloc_mux_tx(int len)
{
struct mux_tx *t = NULL;
- t = kzalloc(sizeof(struct mux_tx), GFP_ATOMIC);
+ t = kzalloc(sizeof(*t), GFP_ATOMIC);
if (!t)
return NULL;
@@ -96,7 +95,7 @@ static struct mux_rx *alloc_mux_rx(void)
{
struct mux_rx *r = NULL;
- r = kzalloc(sizeof(struct mux_rx), GFP_KERNEL);
+ r = kzalloc(sizeof(*r), GFP_KERNEL);
if (!r)
return NULL;
@@ -150,7 +149,6 @@ static void put_rx_struct(struct rx_cxt *rx, struct mux_rx *r)
spin_unlock_irqrestore(&rx->free_list_lock, flags);
}
-
static int up_to_host(struct mux_rx *r)
{
struct mux_dev *mux_dev = r->mux_dev;
@@ -271,7 +269,7 @@ static void gdm_mux_rcv_complete(struct urb *urb)
if (urb->status) {
if (mux_dev->usb_state == PM_NORMAL)
dev_err(&urb->dev->dev, "%s: urb status error %d\n",
- __func__, urb->status);
+ __func__, urb->status);
put_rx_struct(rx, r);
} else {
r->len = r->urb->actual_length;
@@ -388,8 +386,8 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index,
mux_header->payload_size = __cpu_to_le32((u32)len);
mux_header->packet_type = __cpu_to_le16(packet_type[tty_index]);
- memcpy(t->buf+MUX_HEADER_SIZE, data, len);
- memset(t->buf+MUX_HEADER_SIZE+len, 0, total_len - MUX_HEADER_SIZE -
+ memcpy(t->buf + MUX_HEADER_SIZE, data, len);
+ memset(t->buf + MUX_HEADER_SIZE + len, 0, total_len - MUX_HEADER_SIZE -
len);
t->len = total_len;
@@ -474,7 +472,6 @@ static void release_usb(struct mux_dev *mux_dev)
spin_unlock_irqrestore(&rx->to_host_lock, flags);
}
-
static int init_usb(struct mux_dev *mux_dev)
{
struct mux_rx *r;
@@ -492,7 +489,7 @@ static int init_usb(struct mux_dev *mux_dev)
for (i = 0; i < MAX_ISSUE_NUM * 2; i++) {
r = alloc_mux_rx();
- if (r == NULL) {
+ if (!r) {
ret = -ENOMEM;
break;
}
@@ -526,11 +523,11 @@ static int gdm_mux_probe(struct usb_interface *intf,
if (bInterfaceNumber != 2)
return -ENODEV;
- mux_dev = kzalloc(sizeof(struct mux_dev), GFP_KERNEL);
+ mux_dev = kzalloc(sizeof(*mux_dev), GFP_KERNEL);
if (!mux_dev)
return -ENOMEM;
- tty_dev = kzalloc(sizeof(struct tty_dev), GFP_KERNEL);
+ tty_dev = kzalloc(sizeof(*tty_dev), GFP_KERNEL);
if (!tty_dev) {
ret = -ENOMEM;
goto err_free_mux;
@@ -612,7 +609,6 @@ static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg)
mux_dev->usb_state = PM_SUSPEND;
-
spin_lock_irqsave(&rx->submit_list_lock, flags);
list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
rx_submit_list) {
@@ -662,7 +658,7 @@ static int __init gdm_usb_mux_init(void)
{
mux_rx_wq = create_workqueue("mux_rx_wq");
- if (mux_rx_wq == NULL) {
+ if (!mux_rx_wq) {
pr_err("work queue create fail\n");
return -1;
}
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
index 655f7688d039..e2c0f228f369 100644
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -88,7 +88,7 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
mutex_lock(&gdm_table_lock);
gdm = gdm_table[i][j];
- if (gdm == NULL) {
+ if (!gdm) {
mutex_unlock(&gdm_table_lock);
return -ENODEV;
}
@@ -193,7 +193,7 @@ static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf,
sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE :
remain;
gdm_tty_send(gdm,
- (void *)(buf+sent_len),
+ (void *)(buf + sent_len),
sending_len,
gdm->index,
gdm_tty_send_complete,
@@ -226,7 +226,7 @@ int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device)
for (i = 0; i < TTY_MAX_COUNT; i++) {
- gdm = kmalloc(sizeof(struct gdm), GFP_KERNEL);
+ gdm = kmalloc(sizeof(*gdm), GFP_KERNEL);
if (!gdm)
return -ENOMEM;
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
index 9ceba147d390..92ea1a16afff 100644
--- a/drivers/staging/gdm724x/gdm_usb.c
+++ b/drivers/staging/gdm724x/gdm_usb.c
@@ -63,7 +63,7 @@ static void do_rx(struct work_struct *work);
static int gdm_usb_recv(void *priv_dev,
int (*cb)(void *cb_data,
- void *data, int len, int context),
+ void *data, int len, int context),
void *cb_data,
int context);
@@ -80,7 +80,7 @@ static int request_mac_address(struct lte_udev *udev)
hci->data[0] = MAC_ADDRESS;
ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), buf, 5,
- &actual, 1000);
+ &actual, 1000);
udev->request_mac_addr = 1;
@@ -92,7 +92,7 @@ static struct usb_tx *alloc_tx_struct(int len)
struct usb_tx *t = NULL;
int ret = 0;
- t = kzalloc(sizeof(struct usb_tx), GFP_ATOMIC);
+ t = kzalloc(sizeof(*t), GFP_ATOMIC);
if (!t) {
ret = -ENOMEM;
goto out;
@@ -125,7 +125,7 @@ static struct usb_tx_sdu *alloc_tx_sdu_struct(void)
{
struct usb_tx_sdu *t_sdu;
- t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_KERNEL);
+ t_sdu = kzalloc(sizeof(*t_sdu), GFP_KERNEL);
if (!t_sdu)
return NULL;
@@ -183,7 +183,7 @@ static struct usb_rx *alloc_rx_struct(void)
struct usb_rx *r = NULL;
int ret = 0;
- r = kmalloc(sizeof(struct usb_rx), GFP_KERNEL);
+ r = kmalloc(sizeof(*r), GFP_KERNEL);
if (!r) {
ret = -ENOMEM;
goto out;
@@ -338,7 +338,7 @@ static int init_usb(struct lte_udev *udev)
for (i = 0; i < MAX_NUM_SDU_BUF; i++) {
t_sdu = alloc_tx_sdu_struct();
- if (t_sdu == NULL) {
+ if (!t_sdu) {
ret = -ENOMEM;
goto fail;
}
@@ -347,9 +347,9 @@ static int init_usb(struct lte_udev *udev)
tx->avail_count++;
}
- for (i = 0; i < MAX_RX_SUBMIT_COUNT*2; i++) {
+ for (i = 0; i < MAX_RX_SUBMIT_COUNT * 2; i++) {
r = alloc_rx_struct();
- if (r == NULL) {
+ if (!r) {
ret = -ENOMEM;
goto fail;
}
@@ -376,7 +376,7 @@ static int set_mac_address(u8 *data, void *arg)
memcpy(mac_address, tlv->data, tlv->len);
if (register_lte_device(phy_dev,
- &udev->intf->dev, mac_address) < 0)
+ &udev->intf->dev, mac_address) < 0)
pr_err("register lte device failed\n");
udev->request_mac_addr = 0;
@@ -406,7 +406,7 @@ static void do_rx(struct work_struct *work)
break;
}
r = list_entry(rx->to_host_list.next,
- struct usb_rx, to_host_list);
+ struct usb_rx, to_host_list);
list_del(&r->to_host_list);
spin_unlock_irqrestore(&rx->to_host_lock, flags);
@@ -481,7 +481,7 @@ static void gdm_usb_rcv_complete(struct urb *urb)
} else {
if (urb->status && udev->usb_state == PM_NORMAL)
dev_err(&urb->dev->dev, "%s: urb status error %d\n",
- __func__, urb->status);
+ __func__, urb->status);
put_rx_struct(rx, r);
}
@@ -491,7 +491,7 @@ static void gdm_usb_rcv_complete(struct urb *urb)
static int gdm_usb_recv(void *priv_dev,
int (*cb)(void *cb_data,
- void *data, int len, int context),
+ void *data, int len, int context),
void *cb_data,
int context)
{
@@ -576,7 +576,7 @@ static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len)
{
int ret = 0;
- if (!(len%512))
+ if (!(len % 512))
len++;
usb_fill_bulk_urb(t->urb,
@@ -682,7 +682,7 @@ static void do_tx(struct work_struct *work)
}
t = alloc_tx_struct(TX_BUF_SIZE);
- if (t == NULL) {
+ if (!t) {
spin_unlock_irqrestore(&tx->lock, flags);
return;
}
@@ -711,8 +711,8 @@ static void do_tx(struct work_struct *work)
#define SDU_PARAM_LEN 12
static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
- unsigned int dftEpsId, unsigned int epsId,
- void (*cb)(void *data), void *cb_data,
+ unsigned int dftEpsId, unsigned int epsId,
+ void (*cb)(void *data), void *cb_data,
int dev_idx, int nic_type)
{
struct lte_udev *udev = priv_dev;
@@ -732,7 +732,7 @@ static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
t_sdu = get_tx_sdu_struct(tx, &no_spc);
spin_unlock_irqrestore(&tx->lock, flags);
- if (t_sdu == NULL) {
+ if (!t_sdu) {
pr_err("sdu send - free list empty\n");
return TX_NO_SPC;
}
@@ -745,7 +745,7 @@ static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
} else {
send_len = len - ETH_HLEN;
send_len += SDU_PARAM_LEN;
- memcpy(sdu->data, data+ETH_HLEN, len-ETH_HLEN);
+ memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN);
}
sdu->len = gdm_cpu_to_dev16(&udev->gdm_ed, send_len);
@@ -769,7 +769,7 @@ static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
}
static int gdm_usb_hci_send(void *priv_dev, void *data, int len,
- void (*cb)(void *data), void *cb_data)
+ void (*cb)(void *data), void *cb_data)
{
struct lte_udev *udev = priv_dev;
struct tx_cxt *tx = &udev->tx;
@@ -782,7 +782,7 @@ static int gdm_usb_hci_send(void *priv_dev, void *data, int len,
}
t = alloc_tx_struct(len);
- if (t == NULL) {
+ if (!t) {
pr_err("hci_send - out of memory\n");
return -ENOMEM;
}
@@ -810,7 +810,7 @@ static struct gdm_endian *gdm_usb_get_endian(void *priv_dev)
}
static int gdm_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+ const struct usb_device_id *id)
{
int ret = 0;
struct phy_dev *phy_dev = NULL;
@@ -830,11 +830,11 @@ static int gdm_usb_probe(struct usb_interface *intf,
return -ENODEV;
}
- phy_dev = kzalloc(sizeof(struct phy_dev), GFP_KERNEL);
+ phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
if (!phy_dev)
return -ENOMEM;
- udev = kzalloc(sizeof(struct lte_udev), GFP_KERNEL);
+ udev = kzalloc(sizeof(*udev), GFP_KERNEL);
if (!udev) {
ret = -ENOMEM;
goto err_udev;
@@ -1006,11 +1006,11 @@ static int __init gdm_usb_lte_init(void)
}
usb_tx_wq = create_workqueue("usb_tx_wq");
- if (usb_tx_wq == NULL)
+ if (!usb_tx_wq)
return -1;
usb_rx_wq = create_workqueue("usb_rx_wq");
- if (usb_rx_wq == NULL)
+ if (!usb_rx_wq)
return -1;
return usb_register(&gdm_usb_lte_driver);
diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c
index 59a18304ef4a..9d8347769e88 100644
--- a/drivers/staging/gdm724x/netlink_k.c
+++ b/drivers/staging/gdm724x/netlink_k.c
@@ -34,8 +34,8 @@ static struct semaphore netlink_mutex;
#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN)
#define ND_NLMSG_DATA(nlh) ((void *)((char *)NLMSG_DATA(nlh) + \
ND_IFINDEX_LEN))
-#define ND_NLMSG_S_LEN(len) (len+ND_IFINDEX_LEN)
-#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len-ND_IFINDEX_LEN)
+#define ND_NLMSG_S_LEN(len) (len + ND_IFINDEX_LEN)
+#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len - ND_IFINDEX_LEN)
#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh)
#define ND_MAX_MSG_LEN (1024 * 32)
@@ -107,11 +107,6 @@ struct sock *netlink_init(int unit,
return sock;
}
-void netlink_exit(struct sock *sock)
-{
- sock_release(sock->sk_socket);
-}
-
int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
{
static u32 seq;
@@ -122,7 +117,7 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
if (group > ND_MAX_GROUP)
return -EINVAL;
- if (!netlink_has_listeners(sock, group+1))
+ if (!netlink_has_listeners(sock, group + 1))
return -ESRCH;
skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
@@ -136,14 +131,14 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
NETLINK_CB(skb).portid = 0;
NETLINK_CB(skb).dst_group = 0;
- ret = netlink_broadcast(sock, skb, 0, group+1, GFP_ATOMIC);
+ ret = netlink_broadcast(sock, skb, 0, group + 1, GFP_ATOMIC);
if (!ret)
return len;
if (ret != -ESRCH)
pr_err("nl broadcast g=%d, t=%d, l=%d, r=%d\n",
group, type, len, ret);
- else if (netlink_has_listeners(sock, group+1))
+ else if (netlink_has_listeners(sock, group + 1))
return -EAGAIN;
return ret;
diff --git a/drivers/staging/gdm724x/netlink_k.h b/drivers/staging/gdm724x/netlink_k.h
index 589486d76714..7cf979b3f826 100644
--- a/drivers/staging/gdm724x/netlink_k.h
+++ b/drivers/staging/gdm724x/netlink_k.h
@@ -19,7 +19,6 @@
struct sock *netlink_init(int unit,
void (*cb)(struct net_device *dev, u16 type, void *msg, int len));
-void netlink_exit(struct sock *sock);
int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len);
#endif /* _NETLINK_K_H_ */
diff --git a/drivers/staging/gdm72xx/gdm_qos.c b/drivers/staging/gdm72xx/gdm_qos.c
index 81feffa5784a..cad347a05d18 100644
--- a/drivers/staging/gdm72xx/gdm_qos.c
+++ b/drivers/staging/gdm72xx/gdm_qos.c
@@ -101,7 +101,7 @@ void gdm_qos_init(void *nic_ptr)
}
qcb->qos_list_cnt = 0;
- qcb->qos_null_idx = QOS_MAX-1;
+ qcb->qos_null_idx = QOS_MAX - 1;
qcb->qos_limit_size = 255;
spin_lock_init(&qcb->qos_lock);
@@ -128,7 +128,7 @@ void gdm_qos_release_list(void *nic_ptr)
}
qcb->qos_list_cnt = 0;
- qcb->qos_null_idx = QOS_MAX-1;
+ qcb->qos_null_idx = QOS_MAX - 1;
for (i = 0; i < QOS_MAX; i++) {
list_for_each_entry_safe(entry, n, &qcb->qos_list[i], list) {
@@ -143,18 +143,18 @@ static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port)
{
int i;
- if (csr->classifier_rule_en&IPTYPEOFSERVICE) {
+ if (csr->classifier_rule_en & IPTYPEOFSERVICE) {
if (((stream[1] & csr->ip2s_mask) < csr->ip2s_lo) ||
((stream[1] & csr->ip2s_mask) > csr->ip2s_hi))
return 1;
}
- if (csr->classifier_rule_en&PROTOCOL) {
+ if (csr->classifier_rule_en & PROTOCOL) {
if (stream[9] != csr->protocol)
return 1;
}
- if (csr->classifier_rule_en&IPMASKEDSRCADDRESS) {
+ if (csr->classifier_rule_en & IPMASKEDSRCADDRESS) {
for (i = 0; i < 4; i++) {
if ((stream[12 + i] & csr->ipsrc_addrmask[i]) !=
(csr->ipsrc_addr[i] & csr->ipsrc_addrmask[i]))
@@ -162,7 +162,7 @@ static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port)
}
}
- if (csr->classifier_rule_en&IPMASKEDDSTADDRESS) {
+ if (csr->classifier_rule_en & IPMASKEDDSTADDRESS) {
for (i = 0; i < 4; i++) {
if ((stream[16 + i] & csr->ipdst_addrmask[i]) !=
(csr->ipdst_addr[i] & csr->ipdst_addrmask[i]))
@@ -170,14 +170,14 @@ static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port)
}
}
- if (csr->classifier_rule_en&PROTOCOLSRCPORTRANGE) {
- i = ((port[0]<<8)&0xff00)+port[1];
+ if (csr->classifier_rule_en & PROTOCOLSRCPORTRANGE) {
+ i = ((port[0] << 8) & 0xff00) + port[1];
if ((i < csr->srcport_lo) || (i > csr->srcport_hi))
return 1;
}
- if (csr->classifier_rule_en&PROTOCOLDSTPORTRANGE) {
- i = ((port[2]<<8)&0xff00)+port[3];
+ if (csr->classifier_rule_en & PROTOCOLDSTPORTRANGE) {
+ i = ((port[2] << 8) & 0xff00) + port[3];
if ((i < csr->dstport_lo) || (i > csr->dstport_hi))
return 1;
}
@@ -193,7 +193,7 @@ static int get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph)
if (!iph || !tcpudph)
return -1;
- ip_ver = (iph[0]>>4)&0xf;
+ ip_ver = (iph[0] >> 4) & 0xf;
if (ip_ver != 4)
return -1;
@@ -342,17 +342,17 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
if (sub_cmd_evt == QOS_REPORT) {
spin_lock_irqsave(&qcb->qos_lock, flags);
for (i = 0; i < qcb->qos_list_cnt; i++) {
- sfid = ((buf[(i*5)+6]<<24)&0xff000000);
- sfid += ((buf[(i*5)+7]<<16)&0xff0000);
- sfid += ((buf[(i*5)+8]<<8)&0xff00);
- sfid += (buf[(i*5)+9]);
+ sfid = ((buf[(i*5) + 6] << 24) & 0xff000000);
+ sfid += ((buf[(i*5) + 7] << 16) & 0xff0000);
+ sfid += ((buf[(i*5) + 8] << 8) & 0xff00);
+ sfid += (buf[(i*5) + 9]);
index = get_csr(qcb, sfid, 0);
if (index == -1) {
spin_unlock_irqrestore(&qcb->qos_lock, flags);
netdev_err(nic->netdev, "QoS ERROR: No SF\n");
return;
}
- qcb->csr[index].qos_buf_count = buf[(i*5)+10];
+ qcb->csr[index].qos_buf_count = buf[(i*5) + 10];
}
extract_qos_list(nic, &send_list);
@@ -363,9 +363,9 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
/* sub_cmd_evt == QOS_ADD || sub_cmd_evt == QOS_CHANG_DEL */
pos = 6;
- sfid = ((buf[pos++]<<24)&0xff000000);
- sfid += ((buf[pos++]<<16)&0xff0000);
- sfid += ((buf[pos++]<<8)&0xff00);
+ sfid = ((buf[pos++] << 24) & 0xff000000);
+ sfid += ((buf[pos++] << 16) & 0xff0000);
+ sfid += ((buf[pos++] << 8) & 0xff00);
sfid += (buf[pos++]);
index = get_csr(qcb, sfid, 1);
@@ -382,7 +382,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
spin_lock_irqsave(&qcb->qos_lock, flags);
qcb->csr[index].sfid = sfid;
- qcb->csr[index].classifier_rule_en = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].classifier_rule_en = ((buf[pos++] << 8) & 0xff00);
qcb->csr[index].classifier_rule_en += buf[pos++];
if (qcb->csr[index].classifier_rule_en == 0)
qcb->qos_null_idx = index;
@@ -406,16 +406,16 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
qcb->csr[index].ipdst_addr[1] = buf[pos++];
qcb->csr[index].ipdst_addr[2] = buf[pos++];
qcb->csr[index].ipdst_addr[3] = buf[pos++];
- qcb->csr[index].srcport_lo = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].srcport_lo = ((buf[pos++] << 8) & 0xff00);
qcb->csr[index].srcport_lo += buf[pos++];
- qcb->csr[index].srcport_hi = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].srcport_hi = ((buf[pos++] << 8) & 0xff00);
qcb->csr[index].srcport_hi += buf[pos++];
- qcb->csr[index].dstport_lo = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].dstport_lo = ((buf[pos++] << 8) & 0xff00);
qcb->csr[index].dstport_lo += buf[pos++];
- qcb->csr[index].dstport_hi = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].dstport_hi = ((buf[pos++] << 8) & 0xff00);
qcb->csr[index].dstport_hi += buf[pos++];
- qcb->qos_limit_size = 254/qcb->qos_list_cnt;
+ qcb->qos_limit_size = 254 / qcb->qos_list_cnt;
spin_unlock_irqrestore(&qcb->qos_lock, flags);
} else if (sub_cmd_evt == QOS_CHANGE_DEL) {
netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n",
@@ -426,7 +426,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
spin_lock_irqsave(&qcb->qos_lock, flags);
qcb->csr[index].enabled = false;
qcb->qos_list_cnt--;
- qcb->qos_limit_size = 254/qcb->qos_list_cnt;
+ qcb->qos_limit_size = 254 / qcb->qos_list_cnt;
list_for_each_entry_safe(entry, n, &qcb->qos_list[index],
list) {
diff --git a/drivers/staging/gdm72xx/gdm_wimax.c b/drivers/staging/gdm72xx/gdm_wimax.c
index d9ddced96e19..b8eea21f2655 100644
--- a/drivers/staging/gdm72xx/gdm_wimax.c
+++ b/drivers/staging/gdm72xx/gdm_wimax.c
@@ -84,11 +84,6 @@ static inline struct evt_entry *alloc_event_entry(void)
return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC);
}
-static inline void free_event_entry(struct evt_entry *e)
-{
- kfree(e);
-}
-
static struct evt_entry *get_event_entry(void)
{
struct evt_entry *e;
@@ -180,11 +175,11 @@ static void gdm_wimax_event_exit(void)
list_for_each_entry_safe(e, temp, &wm_event.evtq, list) {
list_del(&e->list);
- free_event_entry(e);
+ kfree(e);
}
list_for_each_entry_safe(e, temp, &wm_event.freeq, list) {
list_del(&e->list);
- free_event_entry(e);
+ kfree(e);
}
spin_unlock_irqrestore(&wm_event.evt_lock, flags);
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 10db685813c9..06c0b75ed26a 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -235,7 +235,6 @@ static int adis16201_remove(struct spi_device *spi)
static struct spi_driver adis16201_driver = {
.driver = {
.name = "adis16201",
- .owner = THIS_MODULE,
},
.probe = adis16201_probe,
.remove = adis16201_remove,
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index fb593d23d5bc..de5b84ac842b 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -203,7 +203,6 @@ static int adis16203_remove(struct spi_device *spi)
static struct spi_driver adis16203_driver = {
.driver = {
.name = "adis16203",
- .owner = THIS_MODULE,
},
.probe = adis16203_probe,
.remove = adis16203_remove,
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index ea0ac2467ac2..20a9df64f1ed 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -241,7 +241,6 @@ static int adis16204_remove(struct spi_device *spi)
static struct spi_driver adis16204_driver = {
.driver = {
.name = "adis16204",
- .owner = THIS_MODULE,
},
.probe = adis16204_probe,
.remove = adis16204_remove,
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index d1dc1a3cb3ce..8b42bf8c3f60 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -235,7 +235,6 @@ static int adis16209_remove(struct spi_device *spi)
static struct spi_driver adis16209_driver = {
.driver = {
.name = "adis16209",
- .owner = THIS_MODULE,
},
.probe = adis16209_probe,
.remove = adis16209_remove,
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index e46a91c69a31..d0165218b60c 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -482,7 +482,6 @@ static int adis16220_remove(struct spi_device *spi)
static struct spi_driver adis16220_driver = {
.driver = {
.name = "adis16220",
- .owner = THIS_MODULE,
},
.probe = adis16220_probe,
.remove = adis16220_remove,
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index cb074e864408..1b5b685a8691 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -288,7 +288,6 @@ static int adis16240_remove(struct spi_device *spi)
static struct spi_driver adis16240_driver = {
.driver = {
.name = "adis16240",
- .owner = THIS_MODULE,
},
.probe = adis16240_probe,
.remove = adis16240_remove,
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index ebcab56c81b9..7939ae6378d7 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -406,8 +406,10 @@ static int lis3l02dq_initial_setup(struct iio_dev *indio_dev)
goto err_ret;
}
- /* Read back to check this has worked acts as loose test of correct
- * chip */
+ /*
+ * Read back to check this has worked acts as loose test of correct
+ * chip
+ */
ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
&valtest);
@@ -565,7 +567,7 @@ static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
{
u8 val;
int ret;
- u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
+ u8 mask = (1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING)));
ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
@@ -620,7 +622,7 @@ static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
u8 val, control;
u8 currentlyset;
bool changed = false;
- u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
+ u8 mask = (1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING)));
mutex_lock(&indio_dev->mlock);
/* read current control */
@@ -800,7 +802,6 @@ static int lis3l02dq_remove(struct spi_device *spi)
static struct spi_driver lis3l02dq_driver = {
.driver = {
.name = "lis3l02dq",
- .owner = THIS_MODULE,
},
.probe = lis3l02dq_probe,
.remove = lis3l02dq_remove,
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 1a0651cb2691..50c162e0c31f 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -69,25 +69,25 @@ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array)
mutex_lock(&st->buf_lock);
- for (i = 0; i < ARRAY_SIZE(read_all_tx_array)/4; i++)
+ for (i = 0; i < ARRAY_SIZE(read_all_tx_array) / 4; i++)
if (test_bit(i, indio_dev->active_scan_mask)) {
/* lower byte */
- xfers[j].tx_buf = st->tx + 2*j;
- st->tx[2*j] = read_all_tx_array[i*4];
- st->tx[2*j + 1] = 0;
+ xfers[j].tx_buf = st->tx + (2 * j);
+ st->tx[2 * j] = read_all_tx_array[i * 4];
+ st->tx[2 * j + 1] = 0;
if (rx_array)
- xfers[j].rx_buf = rx_array + j*2;
+ xfers[j].rx_buf = rx_array + (j * 2);
xfers[j].bits_per_word = 8;
xfers[j].len = 2;
xfers[j].cs_change = 1;
j++;
/* upper byte */
- xfers[j].tx_buf = st->tx + 2*j;
- st->tx[2*j] = read_all_tx_array[i*4 + 2];
- st->tx[2*j + 1] = 0;
+ xfers[j].tx_buf = st->tx + (2 * j);
+ st->tx[2 * j] = read_all_tx_array[i * 4 + 2];
+ st->tx[2 * j + 1] = 0;
if (rx_array)
- xfers[j].rx_buf = rx_array + j*2;
+ xfers[j].rx_buf = rx_array + (j * 2);
xfers[j].bits_per_word = 8;
xfers[j].len = 2;
xfers[j].cs_change = 1;
@@ -127,11 +127,11 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
return ret;
}
for (i = 0; i < scan_count; i++)
- data[i] = combine_8_to_16(rx_array[i*4+1],
- rx_array[i*4+3]);
+ data[i] = combine_8_to_16(rx_array[i * 4 + 1],
+ rx_array[i * 4 + 3]);
kfree(rx_array);
- return i*sizeof(data[0]);
+ return i * sizeof(data[0]);
}
static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index b614f272b5f4..02e930c55570 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -88,7 +88,7 @@ int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
}
int sca3000_read_data_short(struct sca3000_state *st,
- uint8_t reg_address_high,
+ u8 reg_address_high,
int len)
{
struct spi_transfer xfer[2] = {
@@ -165,10 +165,9 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
* Lock must be held.
**/
static int sca3000_write_ctrl_reg(struct sca3000_state *st,
- uint8_t sel,
+ u8 sel,
uint8_t val)
{
-
int ret;
ret = sca3000_reg_lock_on(st);
@@ -374,7 +373,6 @@ error_ret:
return ret;
}
-
/*
* Not even vaguely standard attributes so defined here rather than
* in the relevant IIO core headers
@@ -471,12 +469,13 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
return ret;
}
*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
- *val = ((*val) << (sizeof(*val)*8 - 13)) >>
- (sizeof(*val)*8 - 13);
+ *val = ((*val) << (sizeof(*val) * 8 - 13)) >>
+ (sizeof(*val) * 8 - 13);
} else {
/* get the temperature when available */
ret = sca3000_read_data_short(st,
- SCA3000_REG_ADDR_TEMP_MSB, 2);
+ SCA3000_REG_ADDR_TEMP_MSB,
+ 2);
if (ret < 0) {
mutex_unlock(&st->lock);
return ret;
@@ -511,8 +510,8 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
* at all.
**/
static ssize_t sca3000_read_av_freq(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
@@ -529,26 +528,27 @@ static ssize_t sca3000_read_av_freq(struct device *dev,
case SCA3000_MEAS_MODE_NORMAL:
len += sprintf(buf + len, "%d %d %d\n",
st->info->measurement_mode_freq,
- st->info->measurement_mode_freq/2,
- st->info->measurement_mode_freq/4);
+ st->info->measurement_mode_freq / 2,
+ st->info->measurement_mode_freq / 4);
break;
case SCA3000_MEAS_MODE_OP_1:
len += sprintf(buf + len, "%d %d %d\n",
st->info->option_mode_1_freq,
- st->info->option_mode_1_freq/2,
- st->info->option_mode_1_freq/4);
+ st->info->option_mode_1_freq / 2,
+ st->info->option_mode_1_freq / 4);
break;
case SCA3000_MEAS_MODE_OP_2:
len += sprintf(buf + len, "%d %d %d\n",
st->info->option_mode_2_freq,
- st->info->option_mode_2_freq/2,
- st->info->option_mode_2_freq/4);
+ st->info->option_mode_2_freq / 2,
+ st->info->option_mode_2_freq / 4);
break;
}
return len;
error_ret:
return ret;
}
+
/**
* __sca3000_get_base_freq() obtain mode specific base frequency
*
@@ -582,8 +582,8 @@ error_ret:
* sca3000_read_frequency() sysfs interface to get the current frequency
**/
static ssize_t sca3000_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
@@ -605,10 +605,10 @@ static ssize_t sca3000_read_frequency(struct device *dev,
len = sprintf(buf, "%d\n", base_freq);
break;
case 0x01:
- len = sprintf(buf, "%d\n", base_freq/2);
+ len = sprintf(buf, "%d\n", base_freq / 2);
break;
case 0x02:
- len = sprintf(buf, "%d\n", base_freq/4);
+ len = sprintf(buf, "%d\n", base_freq / 4);
break;
}
@@ -623,9 +623,9 @@ error_ret:
* sca3000_set_frequency() sysfs interface to set the current frequency
**/
static ssize_t sca3000_set_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
@@ -650,9 +650,9 @@ static ssize_t sca3000_set_frequency(struct device *dev,
/* clear the bits */
ctrlval &= ~0x03;
- if (val == base_freq/2) {
+ if (val == base_freq / 2) {
ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2;
- } else if (val == base_freq/4) {
+ } else if (val == base_freq / 4) {
ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4;
} else if (val != base_freq) {
ret = -EINVAL;
@@ -849,9 +849,9 @@ static int sca3000_read_event_config(struct iio_dev *indio_dev,
if (ret)
goto error_ret;
- if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET)
+ if ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET) {
ret = 0;
- else {
+ } else {
ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
if (ret < 0)
goto error_ret;
@@ -863,6 +863,7 @@ error_ret:
return ret;
}
+
/**
* sca3000_query_free_fall_mode() is free fall mode enabled
**/
@@ -979,14 +980,14 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
if (ret)
goto exit_point;
/* if off and should be on */
- if ((st->mo_det_use_count)
- && ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET))
+ if ((st->mo_det_use_count) &&
+ ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET))
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
(st->rx[0] & ~protect_mask)
| SCA3000_MEAS_MODE_MOT_DET);
/* if on and should be off */
- else if (!(st->mo_det_use_count)
- && ((st->rx[0] & protect_mask) == SCA3000_MEAS_MODE_MOT_DET))
+ else if (!(st->mo_det_use_count) &&
+ ((st->rx[0] & protect_mask) == SCA3000_MEAS_MODE_MOT_DET))
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
(st->rx[0] & ~protect_mask));
exit_point:
@@ -997,14 +998,14 @@ exit_point:
/* Free fall detector related event attribute */
static IIO_DEVICE_ATTR_NAMED(accel_xayaz_mag_falling_en,
- in_accel_x&y&z_mag_falling_en,
+ in_accel_x & y & z_mag_falling_en,
S_IRUGO | S_IWUSR,
sca3000_query_free_fall_mode,
sca3000_set_free_fall_mode,
0);
static IIO_CONST_ATTR_NAMED(accel_xayaz_mag_falling_period,
- in_accel_x&y&z_mag_falling_period,
+ in_accel_x & y & z_mag_falling_period,
"0.226");
static struct attribute *sca3000_event_attributes[] = {
@@ -1196,7 +1197,6 @@ MODULE_DEVICE_TABLE(spi, sca3000_id);
static struct spi_driver sca3000_driver = {
.driver = {
.name = "sca3000",
- .owner = THIS_MODULE,
},
.probe = sca3000_probe,
.remove = sca3000_remove,
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 23685e74917e..20b878d35ea2 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -34,9 +34,9 @@
*/
static int sca3000_read_data(struct sca3000_state *st,
- uint8_t reg_address_high,
- u8 **rx_p,
- int len)
+ u8 reg_address_high,
+ u8 **rx_p,
+ int len)
{
int ret;
struct spi_transfer xfer[2] = {
@@ -106,7 +106,7 @@ static int sca3000_read_first_n_hw_rb(struct iio_buffer *r,
* i.e. number of time points * number of channels.
*/
if (count > num_available * bytes_per_sample)
- num_read = num_available*bytes_per_sample;
+ num_read = num_available * bytes_per_sample;
else
num_read = count;
@@ -116,7 +116,7 @@ static int sca3000_read_first_n_hw_rb(struct iio_buffer *r,
if (ret)
goto error_ret;
- for (i = 0; i < num_read; i++)
+ for (i = 0; i < num_read / sizeof(u16); i++)
*(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i);
if (copy_to_user(buf, rx, num_read))
@@ -160,9 +160,9 @@ static ssize_t sca3000_query_ring_int(struct device *dev,
* sca3000_set_ring_int() set state of ring status interrupt
**/
static ssize_t sca3000_set_ring_int(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
@@ -208,7 +208,7 @@ static ssize_t sca3000_show_buffer_scale(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
- return sprintf(buf, "0.%06d\n", 4*st->info->scale);
+ return sprintf(buf, "0.%06d\n", 4 * st->info->scale);
}
static IIO_DEVICE_ATTR(in_accel_scale,
@@ -267,7 +267,7 @@ int sca3000_configure_ring(struct iio_dev *indio_dev)
struct iio_buffer *buffer;
buffer = sca3000_rb_allocate(indio_dev);
- if (buffer == NULL)
+ if (!buffer)
return -ENOMEM;
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
@@ -307,6 +307,7 @@ error_ret:
return ret;
}
+
/**
* sca3000_hw_ring_preenable() hw ring buffer preenable function
*
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 5b87049cd3f9..bb40f3728742 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -707,7 +707,6 @@ MODULE_DEVICE_TABLE(spi, ad7192_id);
static struct spi_driver ad7192_driver = {
.driver = {
.name = "ad7192",
- .owner = THIS_MODULE,
},
.probe = ad7192_probe,
.remove = ad7192_remove,
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index 45df714cc83a..35acb1a4669b 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -974,7 +974,6 @@ MODULE_DEVICE_TABLE(spi, ad7280_id);
static struct spi_driver ad7280_driver = {
.driver = {
.name = "ad7280",
- .owner = THIS_MODULE,
},
.probe = ad7280_probe,
.remove = ad7280_remove,
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
index b88f8825797d..cbb36317200e 100644
--- a/drivers/staging/iio/adc/ad7606_spi.c
+++ b/drivers/staging/iio/adc/ad7606_spi.c
@@ -103,7 +103,6 @@ MODULE_DEVICE_TABLE(spi, ad7606_id);
static struct spi_driver ad7606_driver = {
.driver = {
.name = "ad7606",
- .owner = THIS_MODULE,
.pm = AD7606_SPI_PM_OPS,
},
.probe = ad7606_spi_probe,
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index 498e86b71ae7..1439cfdbb09c 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -254,7 +254,6 @@ MODULE_DEVICE_TABLE(spi, ad7780_id);
static struct spi_driver ad7780_driver = {
.driver = {
.name = "ad7780",
- .owner = THIS_MODULE,
},
.probe = ad7780_probe,
.remove = ad7780_remove,
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index b3dec7060d40..c8e156646528 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -59,6 +59,7 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
{
struct spi_device *spi_dev = chip->spi_dev;
int ret = 0;
+ __be16 buf;
gpio_set_value(chip->rdwr_pin, 1);
gpio_set_value(chip->rdwr_pin, 0);
@@ -82,13 +83,13 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
gpio_set_value(chip->rdwr_pin, 0);
gpio_set_value(chip->rdwr_pin, 1);
- ret = spi_read(spi_dev, (u8 *)data, sizeof(*data));
+ ret = spi_read(spi_dev, &buf, sizeof(*data));
if (ret < 0) {
dev_err(&spi_dev->dev, "SPI data read error\n");
return ret;
}
- *data = be16_to_cpu(*data);
+ *data = be16_to_cpu(buf);
return ret;
}
@@ -431,7 +432,6 @@ MODULE_DEVICE_TABLE(spi, ad7816_id);
static struct spi_driver ad7816_driver = {
.driver = {
.name = "ad7816",
- .owner = THIS_MODULE,
},
.probe = ad7816_probe,
.id_table = ad7816_id,
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index d11c54b72186..b51f237cd817 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -76,7 +76,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock);
- clk_enable(info->clk);
+ clk_prepare_enable(info->clk);
/* Measurement setup */
__raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm,
LPC32XX_ADC_SELECT(info->adc_base));
@@ -84,7 +84,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
__raw_writel(AD_PDN_CTRL | AD_STROBE,
LPC32XX_ADC_CTRL(info->adc_base));
wait_for_completion(&info->completion); /* set by ISR */
- clk_disable(info->clk);
+ clk_disable_unprepare(info->clk);
*val = info->value;
mutex_unlock(&indio_dev->mlock);
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 1f25027b7b61..5f1375c465e6 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -930,11 +930,12 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_OFFSET:
if (chan->type == IIO_TEMP) {
/* The calculated value from the ADC is in Kelvin, we
- * want Celsius for hwmon so the offset is
- * -272.15 * scale
+ * want Celsius for hwmon so the offset is -273.15
+ * The offset is applied before scaling so it is
+ * actually -213.15 * 4 / 1.012 = -1079.644268
*/
- *val = -1075;
- *val2 = 691699;
+ *val = -1079;
+ *val2 = 644268;
return IIO_VAL_INT_PLUS_MICRO;
}
diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
index e480abb72e4a..5cd22743e140 100644
--- a/drivers/staging/iio/addac/adt7316-spi.c
+++ b/drivers/staging/iio/addac/adt7316-spi.c
@@ -132,7 +132,6 @@ static struct spi_driver adt7316_driver = {
.driver = {
.name = "adt7316",
.pm = ADT7316_PM_OPS,
- .owner = THIS_MODULE,
},
.probe = adt7316_spi_probe,
.id_table = adt7316_spi_id,
diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
index 636a7ee4a508..e8d0ff2d5c9b 100644
--- a/drivers/staging/iio/cdc/ad7150.c
+++ b/drivers/staging/iio/cdc/ad7150.c
@@ -219,7 +219,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev,
u64 event_code;
/* Something must always be turned on */
- if (state == 0)
+ if (!state)
return -EINVAL;
event_code = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, type, dir);
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
index c3d5531f73c2..485d0a5af53c 100644
--- a/drivers/staging/iio/cdc/ad7152.c
+++ b/drivers/staging/iio/cdc/ad7152.c
@@ -290,7 +290,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev,
ret = 0;
break;
case IIO_CHAN_INFO_SCALE:
- if (val != 0) {
+ if (val) {
ret = -EINVAL;
goto out;
}
diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index a861fe0149b1..2b65faa6296a 100644
--- a/drivers/staging/iio/frequency/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -339,7 +339,6 @@ MODULE_DEVICE_TABLE(spi, ad9832_id);
static struct spi_driver ad9832_driver = {
.driver = {
.name = "ad9832",
- .owner = THIS_MODULE,
},
.probe = ad9832_probe,
.remove = ad9832_remove,
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index d02bb44fb8fc..6464f2cbe94b 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -111,7 +111,7 @@ static ssize_t ad9834_write(struct device *dev,
break;
case AD9834_FSEL:
case AD9834_PSEL:
- if (val == 0) {
+ if (!val) {
st->control &= ~(this_attr->address | AD9834_PIN_SW);
} else if (val == 1) {
st->control |= this_attr->address;
@@ -446,7 +446,6 @@ MODULE_DEVICE_TABLE(spi, ad9834_id);
static struct spi_driver ad9834_driver = {
.driver = {
.name = "ad9834",
- .owner = THIS_MODULE,
},
.probe = ad9834_probe,
.remove = ad9834_remove,
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index 4c5869dd8223..ab816a215eb8 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -67,7 +67,7 @@ static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val)
* starts to place data MSB first on the DOUT line at
* the 6th falling edge of SCLK
*/
- if (ret == 0)
+ if (!ret)
*val = ((st->buf[0] & 0x3) << 12) |
(st->buf[1] << 4) |
((st->buf[2] >> 4) & 0xF);
@@ -89,11 +89,13 @@ static int adis16060_read_raw(struct iio_dev *indio_dev,
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
ret = adis16060_spi_write(indio_dev, chan->address);
- if (ret < 0) {
- mutex_unlock(&indio_dev->mlock);
- return ret;
- }
+ if (ret < 0)
+ goto out_unlock;
+
ret = adis16060_spi_read(indio_dev, &tval);
+ if (ret < 0)
+ goto out_unlock;
+
mutex_unlock(&indio_dev->mlock);
*val = tval;
return IIO_VAL_INT;
@@ -108,6 +110,10 @@ static int adis16060_read_raw(struct iio_dev *indio_dev,
}
return -EINVAL;
+
+out_unlock:
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
}
static const struct iio_info adis16060_info = {
@@ -202,7 +208,6 @@ static int adis16060_w_remove(struct spi_device *spi)
static struct spi_driver adis16060_r_driver = {
.driver = {
.name = "adis16060_r",
- .owner = THIS_MODULE,
},
.probe = adis16060_r_probe,
};
@@ -210,7 +215,6 @@ static struct spi_driver adis16060_r_driver = {
static struct spi_driver adis16060_w_driver = {
.driver = {
.name = "adis16060_w",
- .owner = THIS_MODULE,
},
.probe = adis16060_w_probe,
.remove = adis16060_w_remove,
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index c18109c55497..10c43dda0f5a 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -644,7 +644,8 @@ static void ad5933_work(struct work_struct *work)
struct ad5933_state *st = container_of(work,
struct ad5933_state, work.work);
struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
- signed short buf[2];
+ __be16 buf[2];
+ int val[2];
unsigned char status;
mutex_lock(&indio_dev->mlock);
@@ -668,12 +669,12 @@ static void ad5933_work(struct work_struct *work)
scan_count * 2, (u8 *)buf);
if (scan_count == 2) {
- buf[0] = be16_to_cpu(buf[0]);
- buf[1] = be16_to_cpu(buf[1]);
+ val[0] = be16_to_cpu(buf[0]);
+ val[1] = be16_to_cpu(buf[1]);
} else {
- buf[0] = be16_to_cpu(buf[0]);
+ val[0] = be16_to_cpu(buf[0]);
}
- iio_push_to_buffers(indio_dev, buf);
+ iio_push_to_buffers(indio_dev, val);
} else {
/* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies);
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 019ba5245c23..bbf7e35cbc7d 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -117,12 +117,10 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip,
{
int i, ret;
unsigned int int_time, new_int_time;
- struct isl29018_scale new_scale;
for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) {
if (utime == isl29018_int_utimes[chip->type][i]) {
new_int_time = i;
- new_scale = isl29018_scales[new_int_time][0];
break;
}
}
@@ -370,7 +368,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_INT_TIME:
if (chan->type == IIO_LIGHT) {
- if (val != 0) {
+ if (val) {
mutex_unlock(&chip->lock);
return -EINVAL;
}
@@ -716,7 +714,7 @@ static int isl29018_probe(struct i2c_client *client,
int dev_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
- if (indio_dev == NULL) {
+ if (!indio_dev) {
dev_err(&client->dev, "iio allocation fails\n");
return -ENOMEM;
}
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index df602038a4bd..3100d960fe2c 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -263,7 +263,7 @@ static int taos_get_lux(struct iio_dev *indio_dev)
if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation))
goto return_max;
- if (ch0 == 0) {
+ if (!ch0) {
/* have no data, so return LAST VALUE */
ret = chip->als_cur_info.lux = 0;
goto out_unlock;
@@ -415,7 +415,7 @@ static int taos_chip_on(struct iio_dev *indio_dev)
/* determine als integration register */
als_count = (chip->taos_settings.als_time * 100 + 135) / 270;
- if (als_count == 0)
+ if (!als_count)
als_count = 1; /* ensure at least one cycle */
/* convert back to time (encompasses overrides) */
@@ -499,7 +499,7 @@ static ssize_t taos_power_state_store(struct device *dev,
if (kstrtoint(buf, 0, &value))
return -EINVAL;
- if (value == 0)
+ if (!value)
taos_chip_off(indio_dev);
else
taos_chip_on(indio_dev);
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
index bf9627ea2ffb..9dfd04855a1b 100644
--- a/drivers/staging/iio/light/tsl2x7x_core.c
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
@@ -403,7 +403,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
goto return_max;
}
- if (ch0 == 0) {
+ if (!ch0) {
/* have no data, so return LAST VALUE */
ret = chip->als_cur_info.lux;
goto out_unlock;
@@ -678,7 +678,7 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev)
/* determine als integration register */
als_count = (chip->tsl2x7x_settings.als_time * 100 + 135) / 270;
- if (als_count == 0)
+ if (!als_count)
als_count = 1; /* ensure at least one cycle */
/* convert back to time (encompasses overrides) */
@@ -825,7 +825,7 @@ void tsl2x7x_prox_calculate(int *data, int length,
int sample_sum;
int tmp;
- if (length == 0)
+ if (!length)
length = 1;
sample_sum = 0;
diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c
index 4aab0228a195..394bc141a1b0 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_core.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_core.c
@@ -334,7 +334,7 @@ static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
{
int i;
- if (val != 0)
+ if (val)
return -EINVAL;
for (i = 0; i < data->variant->n_regval_to_nanoscale; i++)
diff --git a/drivers/staging/iio/magnetometer/hmc5843_spi.c b/drivers/staging/iio/magnetometer/hmc5843_spi.c
index 1549192c0dec..8be198058ea2 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_spi.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_spi.c
@@ -88,7 +88,6 @@ static struct spi_driver hmc5843_driver = {
.driver = {
.name = "hmc5843",
.pm = HMC5843_PM_OPS,
- .owner = THIS_MODULE,
},
.id_table = hmc5843_id,
.probe = hmc5843_spi_probe,
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 3d2e50cfe9a3..f129039bece3 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -406,7 +406,7 @@ static ssize_t ade7753_write_frequency(struct device *dev,
ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
- if (val == 0)
+ if (!val)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
@@ -534,7 +534,6 @@ static int ade7753_remove(struct spi_device *spi)
static struct spi_driver ade7753_driver = {
.driver = {
.name = "ade7753",
- .owner = THIS_MODULE,
},
.probe = ade7753_probe,
.remove = ade7753_remove,
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 8552c76cbbe7..1e950685e12f 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -438,7 +438,7 @@ static ssize_t ade7754_write_frequency(struct device *dev,
ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
- if (val == 0)
+ if (!val)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
@@ -575,7 +575,6 @@ static int ade7754_remove(struct spi_device *spi)
static struct spi_driver ade7754_driver = {
.driver = {
.name = "ade7754",
- .owner = THIS_MODULE,
},
.probe = ade7754_probe,
.remove = ade7754_remove,
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 38838085824f..0db23e4d1852 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -904,7 +904,6 @@ MODULE_DEVICE_TABLE(spi, ade7758_id);
static struct spi_driver ade7758_driver = {
.driver = {
.name = "ade7758",
- .owner = THIS_MODULE,
},
.probe = ade7758_probe,
.remove = ade7758_remove,
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index 23e739207027..684e612a88b9 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -377,7 +377,7 @@ static ssize_t ade7759_write_frequency(struct device *dev,
ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
- if (val == 0)
+ if (!val)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
@@ -490,7 +490,6 @@ static int ade7759_remove(struct spi_device *spi)
static struct spi_driver ade7759_driver = {
.driver = {
.name = "ade7759",
- .owner = THIS_MODULE,
},
.probe = ade7759_probe,
.remove = ade7759_remove,
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 9b255a5f62c3..2413052c5bfb 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -278,7 +278,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
- if (indio_dev == NULL)
+ if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
@@ -314,7 +314,6 @@ MODULE_DEVICE_TABLE(spi, ade7854_id);
static struct spi_driver ade7854_driver = {
.driver = {
.name = "ade7854",
- .owner = THIS_MODULE,
},
.probe = ade7854_spi_probe,
.remove = ade7854_spi_remove,
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index c17893b4918c..595e711d35a6 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -155,7 +155,6 @@ MODULE_DEVICE_TABLE(spi, ad2s1200_id);
static struct spi_driver ad2s1200_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
},
.probe = ad2s1200_probe,
.id_table = ad2s1200_id,
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 3bd65f5c9cf5..d97aa2827412 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -735,7 +735,6 @@ MODULE_DEVICE_TABLE(spi, ad2s1210_id);
static struct spi_driver ad2s1210_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
},
.probe = ad2s1210_probe,
.remove = ad2s1210_remove,
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index c57a29616223..5b1c0db33e7f 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -100,7 +100,6 @@ MODULE_DEVICE_TABLE(spi, ad2s90_id);
static struct spi_driver ad2s90_driver = {
.driver = {
.name = "ad2s90",
- .owner = THIS_MODULE,
},
.probe = ad2s90_probe,
.id_table = ad2s90_id,
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 9fe48ef11473..035dd456d7d6 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -100,7 +100,7 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
if (enabled)
disable_gptimers(st->t->bit);
- if (val == 0)
+ if (!val)
return count;
val = get_sclk() / val;
@@ -125,7 +125,7 @@ static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
unsigned int period = get_gptimer_period(st->t->id);
unsigned long val;
- if (period == 0)
+ if (!period)
val = 0;
else
val = get_sclk() / get_gptimer_period(st->t->id);
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 2db885750fb8..00d139331261 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -39,7 +39,7 @@ static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state)
dev_dbg(&trig_info->rtc->dev, "trigger frequency is %u\n",
trig_info->frequency);
ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
- if (ret == 0)
+ if (!ret)
trig_info->state = state;
return ret;
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h
index 385ced15c742..4d74e8af5088 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h
@@ -152,8 +152,6 @@ extern struct miscdevice libcfs_dev;
extern char lnet_upcall[1024];
extern char lnet_debug_log_upcall[1024];
-extern void libcfs_init_nidstrings(void);
-
extern struct cfs_psdev_ops libcfs_psdev_ops;
extern struct cfs_wi_sched *cfs_sched_rehash;
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
index c40814591189..f14db92346ba 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
@@ -41,6 +41,9 @@
#ifndef __LIBCFS_HASH_H__
#define __LIBCFS_HASH_H__
+
+#include <linux/hash.h>
+
/*
* Knuth recommends primes in approximately golden ratio to the maximum
* integer representable by a machine word for multiplicative hashing.
@@ -56,22 +59,13 @@
/* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
#define CFS_GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001ULL
-/*
- * Ideally we would use HAVE_HASH_LONG for this, but on linux we configure
- * the linux kernel and user space at the same time, so we need to differentiate
- * between them explicitly. If this is not needed on other architectures, then
- * we'll need to move the functions to architecture specific headers.
- */
-
-#include <linux/hash.h>
-
/** disable debug */
-#define CFS_HASH_DEBUG_NONE 0
+#define CFS_HASH_DEBUG_NONE 0
/** record hash depth and output to console when it's too deep,
* computing overhead is low but consume more memory */
-#define CFS_HASH_DEBUG_1 1
+#define CFS_HASH_DEBUG_1 1
/** expensive, check key validation */
-#define CFS_HASH_DEBUG_2 2
+#define CFS_HASH_DEBUG_2 2
#define CFS_HASH_DEBUG_LEVEL CFS_HASH_DEBUG_NONE
@@ -88,10 +82,10 @@ union cfs_hash_lock {
* cfs_hash_bucket is a container of:
* - lock, counter ...
* - array of hash-head starting from hsb_head[0], hash-head can be one of
- * . cfs_hash_head_t
- * . cfs_hash_head_dep_t
- * . cfs_hash_dhead_t
- * . cfs_hash_dhead_dep_t
+ * . struct cfs_hash_head
+ * . struct cfs_hash_head_dep
+ * . struct cfs_hash_dhead
+ * . struct cfs_hash_dhead_dep
* which depends on requirement of user
* - some extra bytes (caller can require it while creating hash)
*/
@@ -108,16 +102,18 @@ struct cfs_hash_bucket {
* cfs_hash bucket descriptor, it's normally in stack of caller
*/
struct cfs_hash_bd {
- struct cfs_hash_bucket *bd_bucket; /**< address of bucket */
- unsigned int bd_offset; /**< offset in bucket */
+ /* address of bucket */
+ struct cfs_hash_bucket *bd_bucket;
+ /* offset in bucket */
+ unsigned int bd_offset;
};
-#define CFS_HASH_NAME_LEN 16 /**< default name length */
-#define CFS_HASH_BIGNAME_LEN 64 /**< bigname for param tree */
+#define CFS_HASH_NAME_LEN 16 /**< default name length */
+#define CFS_HASH_BIGNAME_LEN 64 /**< bigname for param tree */
-#define CFS_HASH_BKT_BITS 3 /**< default bits of bucket */
-#define CFS_HASH_BITS_MAX 30 /**< max bits of bucket */
-#define CFS_HASH_BITS_MIN CFS_HASH_BKT_BITS
+#define CFS_HASH_BKT_BITS 3 /**< default bits of bucket */
+#define CFS_HASH_BITS_MAX 30 /**< max bits of bucket */
+#define CFS_HASH_BITS_MIN CFS_HASH_BKT_BITS
/**
* common hash attributes.
@@ -133,41 +129,41 @@ enum cfs_hash_tag {
*/
CFS_HASH_NO_LOCK = 1 << 0,
/** no bucket lock, use one spinlock to protect the whole hash */
- CFS_HASH_NO_BKTLOCK = 1 << 1,
+ CFS_HASH_NO_BKTLOCK = 1 << 1,
/** rwlock to protect bucket */
- CFS_HASH_RW_BKTLOCK = 1 << 2,
+ CFS_HASH_RW_BKTLOCK = 1 << 2,
/** spinlock to protect bucket */
- CFS_HASH_SPIN_BKTLOCK = 1 << 3,
+ CFS_HASH_SPIN_BKTLOCK = 1 << 3,
/** always add new item to tail */
- CFS_HASH_ADD_TAIL = 1 << 4,
+ CFS_HASH_ADD_TAIL = 1 << 4,
/** hash-table doesn't have refcount on item */
- CFS_HASH_NO_ITEMREF = 1 << 5,
+ CFS_HASH_NO_ITEMREF = 1 << 5,
/** big name for param-tree */
CFS_HASH_BIGNAME = 1 << 6,
/** track global count */
CFS_HASH_COUNTER = 1 << 7,
/** rehash item by new key */
- CFS_HASH_REHASH_KEY = 1 << 8,
+ CFS_HASH_REHASH_KEY = 1 << 8,
/** Enable dynamic hash resizing */
- CFS_HASH_REHASH = 1 << 9,
+ CFS_HASH_REHASH = 1 << 9,
/** can shrink hash-size */
- CFS_HASH_SHRINK = 1 << 10,
+ CFS_HASH_SHRINK = 1 << 10,
/** assert hash is empty on exit */
- CFS_HASH_ASSERT_EMPTY = 1 << 11,
+ CFS_HASH_ASSERT_EMPTY = 1 << 11,
/** record hlist depth */
- CFS_HASH_DEPTH = 1 << 12,
+ CFS_HASH_DEPTH = 1 << 12,
/**
* rehash is always scheduled in a different thread, so current
* change on hash table is non-blocking
*/
- CFS_HASH_NBLK_CHANGE = 1 << 13,
+ CFS_HASH_NBLK_CHANGE = 1 << 13,
/** NB, we typed hs_flags as __u16, please change it
* if you need to extend >=16 flags */
};
/** most used attributes */
-#define CFS_HASH_DEFAULT (CFS_HASH_RW_BKTLOCK | \
- CFS_HASH_COUNTER | CFS_HASH_REHASH)
+#define CFS_HASH_DEFAULT (CFS_HASH_RW_BKTLOCK | \
+ CFS_HASH_COUNTER | CFS_HASH_REHASH)
/**
* cfs_hash is a hash-table implementation for general purpose, it can support:
@@ -211,68 +207,68 @@ enum cfs_hash_tag {
struct cfs_hash {
/** serialize with rehash, or serialize all operations if
* the hash-table has CFS_HASH_NO_BKTLOCK */
- union cfs_hash_lock hs_lock;
+ union cfs_hash_lock hs_lock;
/** hash operations */
- struct cfs_hash_ops *hs_ops;
+ struct cfs_hash_ops *hs_ops;
/** hash lock operations */
- struct cfs_hash_lock_ops *hs_lops;
+ struct cfs_hash_lock_ops *hs_lops;
/** hash list operations */
- struct cfs_hash_hlist_ops *hs_hops;
+ struct cfs_hash_hlist_ops *hs_hops;
/** hash buckets-table */
- struct cfs_hash_bucket **hs_buckets;
+ struct cfs_hash_bucket **hs_buckets;
/** total number of items on this hash-table */
- atomic_t hs_count;
+ atomic_t hs_count;
/** hash flags, see cfs_hash_tag for detail */
- __u16 hs_flags;
+ __u16 hs_flags;
/** # of extra-bytes for bucket, for user saving extended attributes */
- __u16 hs_extra_bytes;
+ __u16 hs_extra_bytes;
/** wants to iterate */
- __u8 hs_iterating;
+ __u8 hs_iterating;
/** hash-table is dying */
- __u8 hs_exiting;
+ __u8 hs_exiting;
/** current hash bits */
- __u8 hs_cur_bits;
+ __u8 hs_cur_bits;
/** min hash bits */
- __u8 hs_min_bits;
+ __u8 hs_min_bits;
/** max hash bits */
- __u8 hs_max_bits;
+ __u8 hs_max_bits;
/** bits for rehash */
- __u8 hs_rehash_bits;
+ __u8 hs_rehash_bits;
/** bits for each bucket */
- __u8 hs_bkt_bits;
+ __u8 hs_bkt_bits;
/** resize min threshold */
- __u16 hs_min_theta;
+ __u16 hs_min_theta;
/** resize max threshold */
- __u16 hs_max_theta;
+ __u16 hs_max_theta;
/** resize count */
- __u32 hs_rehash_count;
+ __u32 hs_rehash_count;
/** # of iterators (caller of cfs_hash_for_each_*) */
- __u32 hs_iterators;
+ __u32 hs_iterators;
/** rehash workitem */
- cfs_workitem_t hs_rehash_wi;
+ cfs_workitem_t hs_rehash_wi;
/** refcount on this hash table */
- atomic_t hs_refcount;
+ atomic_t hs_refcount;
/** rehash buckets-table */
- struct cfs_hash_bucket **hs_rehash_buckets;
+ struct cfs_hash_bucket **hs_rehash_buckets;
#if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1
/** serialize debug members */
spinlock_t hs_dep_lock;
/** max depth */
- unsigned int hs_dep_max;
+ unsigned int hs_dep_max;
/** id of the deepest bucket */
- unsigned int hs_dep_bkt;
+ unsigned int hs_dep_bkt;
/** offset in the deepest bucket */
- unsigned int hs_dep_off;
+ unsigned int hs_dep_off;
/** bits when we found the max depth */
- unsigned int hs_dep_bits;
+ unsigned int hs_dep_bits;
/** workitem to output max depth */
- cfs_workitem_t hs_dep_wi;
+ cfs_workitem_t hs_dep_wi;
#endif
/** name of htable */
- char hs_name[0];
+ char hs_name[0];
};
-typedef struct cfs_hash_lock_ops {
+struct cfs_hash_lock_ops {
/** lock the hash table */
void (*hs_lock)(union cfs_hash_lock *lock, int exclusive);
/** unlock the hash table */
@@ -281,24 +277,26 @@ typedef struct cfs_hash_lock_ops {
void (*hs_bkt_lock)(union cfs_hash_lock *lock, int exclusive);
/** unlock the hash bucket */
void (*hs_bkt_unlock)(union cfs_hash_lock *lock, int exclusive);
-} cfs_hash_lock_ops_t;
+};
-typedef struct cfs_hash_hlist_ops {
+struct cfs_hash_hlist_ops {
/** return hlist_head of hash-head of @bd */
- struct hlist_head *(*hop_hhead)(struct cfs_hash *hs, struct cfs_hash_bd *bd);
+ struct hlist_head *(*hop_hhead)(struct cfs_hash *hs,
+ struct cfs_hash_bd *bd);
/** return hash-head size */
int (*hop_hhead_size)(struct cfs_hash *hs);
/** add @hnode to hash-head of @bd */
- int (*hop_hnode_add)(struct cfs_hash *hs,
- struct cfs_hash_bd *bd, struct hlist_node *hnode);
+ int (*hop_hnode_add)(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ struct hlist_node *hnode);
/** remove @hnode from hash-head of @bd */
- int (*hop_hnode_del)(struct cfs_hash *hs,
- struct cfs_hash_bd *bd, struct hlist_node *hnode);
-} cfs_hash_hlist_ops_t;
+ int (*hop_hnode_del)(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ struct hlist_node *hnode);
+};
-typedef struct cfs_hash_ops {
+struct cfs_hash_ops {
/** return hashed value from @key */
- unsigned (*hs_hash)(struct cfs_hash *hs, const void *key, unsigned mask);
+ unsigned (*hs_hash)(struct cfs_hash *hs, const void *key,
+ unsigned mask);
/** return key address of @hnode */
void * (*hs_key)(struct hlist_node *hnode);
/** copy key from @hnode to @key */
@@ -315,17 +313,18 @@ typedef struct cfs_hash_ops {
/** release refcount of item */
void (*hs_put)(struct cfs_hash *hs, struct hlist_node *hnode);
/** release refcount of item, always called with holding bucket-lock */
- void (*hs_put_locked)(struct cfs_hash *hs, struct hlist_node *hnode);
+ void (*hs_put_locked)(struct cfs_hash *hs,
+ struct hlist_node *hnode);
/** it's called before removing of @hnode */
void (*hs_exit)(struct cfs_hash *hs, struct hlist_node *hnode);
-} cfs_hash_ops_t;
+};
/** total number of buckets in @hs */
-#define CFS_HASH_NBKT(hs) \
+#define CFS_HASH_NBKT(hs) \
(1U << ((hs)->hs_cur_bits - (hs)->hs_bkt_bits))
/** total number of buckets in @hs while rehashing */
-#define CFS_HASH_RH_NBKT(hs) \
+#define CFS_HASH_RH_NBKT(hs) \
(1U << ((hs)->hs_rehash_bits - (hs)->hs_bkt_bits))
/** number of hlist for in bucket */
@@ -430,19 +429,22 @@ cfs_hash_with_nblk_change(struct cfs_hash *hs)
static inline int
cfs_hash_is_exiting(struct cfs_hash *hs)
-{ /* cfs_hash_destroy is called */
+{
+ /* cfs_hash_destroy is called */
return hs->hs_exiting;
}
static inline int
cfs_hash_is_rehashing(struct cfs_hash *hs)
-{ /* rehash is launched */
+{
+ /* rehash is launched */
return hs->hs_rehash_bits != 0;
}
static inline int
cfs_hash_is_iterating(struct cfs_hash *hs)
-{ /* someone is calling cfs_hash_for_each_* */
+{
+ /* someone is calling cfs_hash_for_each_* */
return hs->hs_iterating || hs->hs_iterators != 0;
}
@@ -546,22 +548,26 @@ static inline void cfs_hash_bd_unlock(struct cfs_hash *hs,
* operations on cfs_hash bucket (bd: bucket descriptor),
* they are normally for hash-table without rehash
*/
-void cfs_hash_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bd);
+void cfs_hash_bd_get(struct cfs_hash *hs, const void *key,
+ struct cfs_hash_bd *bd);
-static inline void cfs_hash_bd_get_and_lock(struct cfs_hash *hs, const void *key,
- struct cfs_hash_bd *bd, int excl)
+static inline void
+cfs_hash_bd_get_and_lock(struct cfs_hash *hs, const void *key,
+ struct cfs_hash_bd *bd, int excl)
{
cfs_hash_bd_get(hs, key, bd);
cfs_hash_bd_lock(hs, bd, excl);
}
-static inline unsigned cfs_hash_bd_index_get(struct cfs_hash *hs, struct cfs_hash_bd *bd)
+static inline unsigned
+cfs_hash_bd_index_get(struct cfs_hash *hs, struct cfs_hash_bd *bd)
{
return bd->bd_offset | (bd->bd_bucket->hsb_index << hs->hs_bkt_bits);
}
-static inline void cfs_hash_bd_index_set(struct cfs_hash *hs,
- unsigned index, struct cfs_hash_bd *bd)
+static inline void
+cfs_hash_bd_index_set(struct cfs_hash *hs, unsigned index,
+ struct cfs_hash_bd *bd)
{
bd->bd_bucket = hs->hs_buckets[index >> hs->hs_bkt_bits];
bd->bd_offset = index & (CFS_HASH_BKT_NHLIST(hs) - 1U);
@@ -611,67 +617,66 @@ void cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
void cfs_hash_bd_del_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode);
void cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old,
- struct cfs_hash_bd *bd_new, struct hlist_node *hnode);
+ struct cfs_hash_bd *bd_new,
+ struct hlist_node *hnode);
-static inline int cfs_hash_bd_dec_and_lock(struct cfs_hash *hs, struct cfs_hash_bd *bd,
- atomic_t *condition)
+static inline int
+cfs_hash_bd_dec_and_lock(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ atomic_t *condition)
{
LASSERT(cfs_hash_with_spin_bktlock(hs));
- return atomic_dec_and_lock(condition,
- &bd->bd_bucket->hsb_lock.spin);
+ return atomic_dec_and_lock(condition, &bd->bd_bucket->hsb_lock.spin);
}
-static inline struct hlist_head *cfs_hash_bd_hhead(struct cfs_hash *hs,
- struct cfs_hash_bd *bd)
+static inline struct hlist_head *
+cfs_hash_bd_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
{
return hs->hs_hops->hop_hhead(hs, bd);
}
-struct hlist_node *cfs_hash_bd_lookup_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bd, const void *key);
-struct hlist_node *cfs_hash_bd_peek_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bd, const void *key);
-struct hlist_node *cfs_hash_bd_findadd_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bd, const void *key,
- struct hlist_node *hnode,
- int insist_add);
-struct hlist_node *cfs_hash_bd_finddel_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bd, const void *key,
- struct hlist_node *hnode);
+struct hlist_node *
+cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ const void *key);
+struct hlist_node *
+cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ const void *key);
/**
* operations on cfs_hash bucket (bd: bucket descriptor),
* they are safe for hash-table with rehash
*/
-void cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bds);
-void cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl);
-void cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl);
+void cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key,
+ struct cfs_hash_bd *bds);
+void cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds,
+ int excl);
+void cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds,
+ int excl);
-static inline void cfs_hash_dual_bd_get_and_lock(struct cfs_hash *hs, const void *key,
- struct cfs_hash_bd *bds, int excl)
+static inline void
+cfs_hash_dual_bd_get_and_lock(struct cfs_hash *hs, const void *key,
+ struct cfs_hash_bd *bds, int excl)
{
cfs_hash_dual_bd_get(hs, key, bds);
cfs_hash_dual_bd_lock(hs, bds, excl);
}
-struct hlist_node *cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bds,
- const void *key);
-struct hlist_node *cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bds,
- const void *key,
- struct hlist_node *hnode,
- int insist_add);
-struct hlist_node *cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bds,
- const void *key,
- struct hlist_node *hnode);
+struct hlist_node *
+cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
+ const void *key);
+struct hlist_node *
+cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
+ const void *key, struct hlist_node *hnode,
+ int insist_add);
+struct hlist_node *
+cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
+ const void *key, struct hlist_node *hnode);
/* Hash init/cleanup functions */
-struct cfs_hash *cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
- unsigned bkt_bits, unsigned extra_bytes,
- unsigned min_theta, unsigned max_theta,
- cfs_hash_ops_t *ops, unsigned flags);
+struct cfs_hash *
+cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
+ unsigned bkt_bits, unsigned extra_bytes,
+ unsigned min_theta, unsigned max_theta,
+ struct cfs_hash_ops *ops, unsigned flags);
struct cfs_hash *cfs_hash_getref(struct cfs_hash *hs);
void cfs_hash_putref(struct cfs_hash *hs);
@@ -685,28 +690,39 @@ void *cfs_hash_findadd_unique(struct cfs_hash *hs, const void *key,
struct hlist_node *hnode);
/* Hash deletion functions */
-void *cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode);
+void *cfs_hash_del(struct cfs_hash *hs, const void *key,
+ struct hlist_node *hnode);
void *cfs_hash_del_key(struct cfs_hash *hs, const void *key);
/* Hash lookup/for_each functions */
#define CFS_HASH_LOOP_HOG 1024
-typedef int (*cfs_hash_for_each_cb_t)(struct cfs_hash *hs, struct cfs_hash_bd *bd,
- struct hlist_node *node, void *data);
-void *cfs_hash_lookup(struct cfs_hash *hs, const void *key);
-void cfs_hash_for_each(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data);
-void cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data);
-int cfs_hash_for_each_nolock(struct cfs_hash *hs,
- cfs_hash_for_each_cb_t, void *data);
-int cfs_hash_for_each_empty(struct cfs_hash *hs,
- cfs_hash_for_each_cb_t, void *data);
-void cfs_hash_for_each_key(struct cfs_hash *hs, const void *key,
- cfs_hash_for_each_cb_t, void *data);
+typedef int (*cfs_hash_for_each_cb_t)(struct cfs_hash *hs,
+ struct cfs_hash_bd *bd,
+ struct hlist_node *node,
+ void *data);
+void *
+cfs_hash_lookup(struct cfs_hash *hs, const void *key);
+void
+cfs_hash_for_each(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data);
+void
+cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data);
+int
+cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t,
+ void *data);
+int
+cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t,
+ void *data);
+void
+cfs_hash_for_each_key(struct cfs_hash *hs, const void *key,
+ cfs_hash_for_each_cb_t, void *data);
typedef int (*cfs_hash_cond_opt_cb_t)(void *obj, void *data);
-void cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t, void *data);
+void
+cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t, void *data);
-void cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex,
- cfs_hash_for_each_cb_t, void *data);
+void
+cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex,
+ cfs_hash_for_each_cb_t, void *data);
int cfs_hash_is_empty(struct cfs_hash *hs);
__u64 cfs_hash_size_get(struct cfs_hash *hs);
@@ -734,7 +750,7 @@ static inline void
cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode)
{
- struct cfs_hash_bd bds[2];
+ struct cfs_hash_bd bds[2];
cfs_hash_dual_bd_get(hs, cfs_hash_key(hs, hnode), bds);
LASSERT(bds[0].bd_bucket == bd->bd_bucket ||
@@ -753,9 +769,9 @@ cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd,
#endif /* CFS_HASH_DEBUG_LEVEL */
-#define CFS_HASH_THETA_BITS 10
-#define CFS_HASH_MIN_THETA (1U << (CFS_HASH_THETA_BITS - 1))
-#define CFS_HASH_MAX_THETA (1U << (CFS_HASH_THETA_BITS + 1))
+#define CFS_HASH_THETA_BITS 10
+#define CFS_HASH_MIN_THETA (1U << (CFS_HASH_THETA_BITS - 1))
+#define CFS_HASH_MAX_THETA (1U << (CFS_HASH_THETA_BITS + 1))
/* Return integer component of theta */
static inline int __cfs_hash_theta_int(int theta)
@@ -776,7 +792,8 @@ static inline int __cfs_hash_theta(struct cfs_hash *hs)
CFS_HASH_THETA_BITS) >> hs->hs_cur_bits;
}
-static inline void __cfs_hash_set_theta(struct cfs_hash *hs, int min, int max)
+static inline void
+__cfs_hash_set_theta(struct cfs_hash *hs, int min, int max)
{
LASSERT(min < max);
hs->hs_min_theta = (__u16)min;
@@ -823,20 +840,20 @@ cfs_hash_u64_hash(const __u64 key, unsigned mask)
}
/** iterate over all buckets in @bds (array of struct cfs_hash_bd) */
-#define cfs_hash_for_each_bd(bds, n, i) \
+#define cfs_hash_for_each_bd(bds, n, i) \
for (i = 0; i < n && (bds)[i].bd_bucket != NULL; i++)
/** iterate over all buckets of @hs */
-#define cfs_hash_for_each_bucket(hs, bd, pos) \
- for (pos = 0; \
- pos < CFS_HASH_NBKT(hs) && \
+#define cfs_hash_for_each_bucket(hs, bd, pos) \
+ for (pos = 0; \
+ pos < CFS_HASH_NBKT(hs) && \
((bd)->bd_bucket = (hs)->hs_buckets[pos]) != NULL; pos++)
/** iterate over all hlist of bucket @bd */
-#define cfs_hash_bd_for_each_hlist(hs, bd, hlist) \
- for ((bd)->bd_offset = 0; \
- (bd)->bd_offset < CFS_HASH_BKT_NHLIST(hs) && \
- (hlist = cfs_hash_bd_hhead(hs, bd)) != NULL; \
+#define cfs_hash_bd_for_each_hlist(hs, bd, hlist) \
+ for ((bd)->bd_offset = 0; \
+ (bd)->bd_offset < CFS_HASH_BKT_NHLIST(hs) && \
+ (hlist = cfs_hash_bd_hhead(hs, bd)) != NULL; \
(bd)->bd_offset++)
/* !__LIBCFS__HASH_H__ */
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h
index a989d2666230..41f3d810aea4 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h
@@ -91,7 +91,7 @@ typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg);
/* Kernel methods */
int libcfs_kkuc_msg_put(struct file *fp, void *payload);
int libcfs_kkuc_group_put(int group, void *payload);
-int libcfs_kkuc_group_add(struct file *fp, int uid, int group,
+int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group,
__u32 data);
int libcfs_kkuc_group_rem(int uid, int group);
int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
index 6af733de69ca..d6273e143324 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
@@ -95,7 +95,7 @@ do { \
do { \
LASSERT(!in_interrupt() || \
((size) <= LIBCFS_VMALLOC_SIZE && \
- ((mask) & __GFP_WAIT) == 0)); \
+ !gfpflags_allow_blocking(mask))); \
} while (0)
#define LIBCFS_ALLOC_POST(ptr, size) \
@@ -185,8 +185,6 @@ int libcfs_debug_cleanup(void);
int libcfs_debug_clear_buffer(void);
int libcfs_debug_mark_buffer(const char *text);
-void libcfs_debug_set_level(unsigned int debug_level);
-
/*
* allocate per-cpu-partition data, returned value is an array of pointers,
* variable can be indexed by CPU ID.
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
index 478e9582ff54..d8d2e7dc212e 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
@@ -83,6 +83,8 @@ int cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res);
int cfs_str2num_check(char *str, int nob, unsigned *num,
unsigned min, unsigned max);
int cfs_expr_list_match(__u32 value, struct cfs_expr_list *expr_list);
+int cfs_expr_list_print(char *buffer, int count,
+ struct cfs_expr_list *expr_list);
int cfs_expr_list_values(struct cfs_expr_list *expr_list,
int max, __u32 **values);
static inline void
@@ -98,8 +100,5 @@ void cfs_expr_list_free(struct cfs_expr_list *expr_list);
int cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
struct cfs_expr_list **elpp);
void cfs_expr_list_free_list(struct list_head *list);
-int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
-int cfs_ip_addr_match(__u32 addr, struct list_head *list);
-void cfs_ip_addr_free(struct list_head *list);
#endif
diff --git a/drivers/staging/lustre/include/linux/lnet/nidstr.h b/drivers/staging/lustre/include/linux/lnet/nidstr.h
index a627be9fcdd0..46ad9147ad2a 100644
--- a/drivers/staging/lustre/include/linux/lnet/nidstr.h
+++ b/drivers/staging/lustre/include/linux/lnet/nidstr.h
@@ -57,21 +57,58 @@ struct list_head;
#define LNET_NIDSTR_COUNT 1024 /* # of nidstrings */
#define LNET_NIDSTR_SIZE 32 /* size of each one (see below for usage) */
-int libcfs_isknown_lnd(int type);
-char *libcfs_lnd2modname(int type);
-char *libcfs_lnd2str(int type);
+/* support decl needed by both kernel and user space */
+char *libcfs_next_nidstring(void);
+int libcfs_isknown_lnd(__u32 lnd);
+char *libcfs_lnd2modname(__u32 lnd);
+char *libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size);
+static inline char *libcfs_lnd2str(__u32 lnd)
+{
+ return libcfs_lnd2str_r(lnd, libcfs_next_nidstring(),
+ LNET_NIDSTR_SIZE);
+}
int libcfs_str2lnd(const char *str);
-char *libcfs_net2str(__u32 net);
-char *libcfs_nid2str(lnet_nid_t nid);
+char *libcfs_net2str_r(__u32 net, char *buf, size_t buf_size);
+static inline char *libcfs_net2str(__u32 net)
+{
+ return libcfs_net2str_r(net, libcfs_next_nidstring(),
+ LNET_NIDSTR_SIZE);
+}
+char *libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size);
+static inline char *libcfs_nid2str(lnet_nid_t nid)
+{
+ return libcfs_nid2str_r(nid, libcfs_next_nidstring(),
+ LNET_NIDSTR_SIZE);
+}
__u32 libcfs_str2net(const char *str);
lnet_nid_t libcfs_str2nid(const char *str);
int libcfs_str2anynid(lnet_nid_t *nid, const char *str);
char *libcfs_id2str(lnet_process_id_t id);
void cfs_free_nidlist(struct list_head *list);
int cfs_parse_nidlist(char *str, int len, struct list_head *list);
+int cfs_print_nidlist(char *buffer, int count, struct list_head *list);
int cfs_match_nid(lnet_nid_t nid, struct list_head *list);
+
+int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
+int cfs_ip_addr_match(__u32 addr, struct list_head *list);
bool cfs_nidrange_is_contiguous(struct list_head *nidlist);
void cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
char *max_nid, size_t nidstr_length);
+struct netstrfns {
+ __u32 nf_type;
+ char *nf_name;
+ char *nf_modname;
+ void (*nf_addr2str)(__u32 addr, char *str, size_t size);
+ int (*nf_str2addr)(const char *str, int nob, __u32 *addr);
+ int (*nf_parse_addrlist)(char *str, int len,
+ struct list_head *list);
+ int (*nf_print_addrlist)(char *buffer, int count,
+ struct list_head *list);
+ int (*nf_match_addr)(__u32 addr, struct list_head *list);
+ bool (*nf_is_contiguous)(struct list_head *nidlist);
+ void (*nf_min_max)(struct list_head *nidlist, __u32 *min_nid,
+ __u32 *max_nid);
+};
+
#endif /* _LNET_NIDSTRINGS_H */
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
index c2cc4e446b22..de0f85f8a2f9 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
@@ -2154,23 +2154,23 @@ static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
if (rc != 0)
return rc;
- LIBCFS_ALLOC(hdev->ibh_mrs, 1 * sizeof(*hdev->ibh_mrs));
- if (hdev->ibh_mrs == NULL) {
- CERROR("Failed to allocate MRs table\n");
- return -ENOMEM;
- }
+ LIBCFS_ALLOC(hdev->ibh_mrs, 1 * sizeof(*hdev->ibh_mrs));
+ if (hdev->ibh_mrs == NULL) {
+ CERROR("Failed to allocate MRs table\n");
+ return -ENOMEM;
+ }
- hdev->ibh_mrs[0] = NULL;
- hdev->ibh_nmrs = 1;
+ hdev->ibh_mrs[0] = NULL;
+ hdev->ibh_nmrs = 1;
- mr = ib_get_dma_mr(hdev->ibh_pd, acflags);
- if (IS_ERR(mr)) {
- CERROR("Failed ib_get_dma_mr : %ld\n", PTR_ERR(mr));
- kiblnd_hdev_cleanup_mrs(hdev);
- return PTR_ERR(mr);
- }
+ mr = ib_get_dma_mr(hdev->ibh_pd, acflags);
+ if (IS_ERR(mr)) {
+ CERROR("Failed ib_get_dma_mr : %ld\n", PTR_ERR(mr));
+ kiblnd_hdev_cleanup_mrs(hdev);
+ return PTR_ERR(mr);
+ }
- hdev->ibh_mrs[0] = mr;
+ hdev->ibh_mrs[0] = mr;
return 0;
}
@@ -2865,7 +2865,7 @@ static int __init kiblnd_module_init(void)
return 0;
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Kernel OpenIB gen2 LND v2.00");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
index 5f78b42b427a..263db37de7c8 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
@@ -123,7 +123,9 @@ extern kib_tunables_t kiblnd_tunables;
IBLND_CREDIT_HIGHWATER_V1 : \
*kiblnd_tunables.kib_peercredits_hiw) /* when eagerly to return credits */
-#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(cb, dev, ps, qpt)
+#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(&init_net, \
+ cb, dev, \
+ ps, qpt)
static inline int
kiblnd_concurrent_sends_v1(void)
@@ -504,7 +506,7 @@ typedef struct kib_tx /* transmit message */
__u64 tx_msgaddr; /* message buffer (I/O addr) */
DECLARE_PCI_UNMAP_ADDR(tx_msgunmap); /* for dma_unmap_single() */
int tx_nwrq; /* # send work items */
- struct ib_send_wr *tx_wrq; /* send work items... */
+ struct ib_rdma_wr *tx_wrq; /* send work items... */
struct ib_sge *tx_sge; /* ...and their memory */
kib_rdma_desc_t *tx_rd; /* rdma descriptor */
int tx_nfrags; /* # entries in... */
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
index 8989e36091fb..260750354a41 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
@@ -838,7 +838,7 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit)
/* close_conn will launch failover */
rc = -ENETDOWN;
} else {
- rc = ib_post_send(conn->ibc_cmid->qp, tx->tx_wrq, &bad_wrq);
+ rc = ib_post_send(conn->ibc_cmid->qp, &tx->tx_wrq->wr, &bad_wrq);
}
conn->ibc_last_send = jiffies;
@@ -1012,7 +1012,7 @@ kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob)
{
kib_hca_dev_t *hdev = tx->tx_pool->tpo_hdev;
struct ib_sge *sge = &tx->tx_sge[tx->tx_nwrq];
- struct ib_send_wr *wrq = &tx->tx_wrq[tx->tx_nwrq];
+ struct ib_rdma_wr *wrq = &tx->tx_wrq[tx->tx_nwrq];
int nob = offsetof(kib_msg_t, ibm_u) + body_nob;
struct ib_mr *mr;
@@ -1031,12 +1031,12 @@ kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob)
memset(wrq, 0, sizeof(*wrq));
- wrq->next = NULL;
- wrq->wr_id = kiblnd_ptr2wreqid(tx, IBLND_WID_TX);
- wrq->sg_list = sge;
- wrq->num_sge = 1;
- wrq->opcode = IB_WR_SEND;
- wrq->send_flags = IB_SEND_SIGNALED;
+ wrq->wr.next = NULL;
+ wrq->wr.wr_id = kiblnd_ptr2wreqid(tx, IBLND_WID_TX);
+ wrq->wr.sg_list = sge;
+ wrq->wr.num_sge = 1;
+ wrq->wr.opcode = IB_WR_SEND;
+ wrq->wr.send_flags = IB_SEND_SIGNALED;
tx->tx_nwrq++;
}
@@ -1048,7 +1048,7 @@ kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type,
kib_msg_t *ibmsg = tx->tx_msg;
kib_rdma_desc_t *srcrd = tx->tx_rd;
struct ib_sge *sge = &tx->tx_sge[0];
- struct ib_send_wr *wrq = &tx->tx_wrq[0];
+ struct ib_rdma_wr *wrq = &tx->tx_wrq[0], *next;
int rc = resid;
int srcidx;
int dstidx;
@@ -1094,16 +1094,17 @@ kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type,
sge->length = wrknob;
wrq = &tx->tx_wrq[tx->tx_nwrq];
+ next = wrq + 1;
- wrq->next = wrq + 1;
- wrq->wr_id = kiblnd_ptr2wreqid(tx, IBLND_WID_RDMA);
- wrq->sg_list = sge;
- wrq->num_sge = 1;
- wrq->opcode = IB_WR_RDMA_WRITE;
- wrq->send_flags = 0;
+ wrq->wr.next = &next->wr;
+ wrq->wr.wr_id = kiblnd_ptr2wreqid(tx, IBLND_WID_RDMA);
+ wrq->wr.sg_list = sge;
+ wrq->wr.num_sge = 1;
+ wrq->wr.opcode = IB_WR_RDMA_WRITE;
+ wrq->wr.send_flags = 0;
- wrq->wr.rdma.remote_addr = kiblnd_rd_frag_addr(dstrd, dstidx);
- wrq->wr.rdma.rkey = kiblnd_rd_frag_key(dstrd, dstidx);
+ wrq->remote_addr = kiblnd_rd_frag_addr(dstrd, dstidx);
+ wrq->rkey = kiblnd_rd_frag_key(dstrd, dstidx);
srcidx = kiblnd_rd_consume_frag(srcrd, srcidx, wrknob);
dstidx = kiblnd_rd_consume_frag(dstrd, dstidx, wrknob);
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
index 1967c21aefe9..ebde0369edc8 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
@@ -1838,7 +1838,6 @@ ksocknal_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
ksocknal_launch_all_connections_locked(peer);
write_unlock_bh(glock);
- return;
}
static void
@@ -2260,9 +2259,8 @@ ksocknal_base_shutdown(void)
case SOCKNAL_INIT_ALL:
case SOCKNAL_INIT_DATA:
LASSERT(ksocknal_data.ksnd_peers != NULL);
- for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) {
+ for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++)
LASSERT(list_empty(&ksocknal_data.ksnd_peers[i]));
- }
LASSERT(list_empty(&ksocknal_data.ksnd_nets));
LASSERT(list_empty(&ksocknal_data.ksnd_enomem_conns));
@@ -2623,8 +2621,8 @@ ksocknal_enumerate_interfaces(ksock_net_t *net)
net->ksnn_interfaces[j].ksni_ipaddr = ip;
net->ksnn_interfaces[j].ksni_netmask = mask;
- strncpy(&net->ksnn_interfaces[j].ksni_name[0],
- names[i], IFNAMSIZ);
+ strlcpy(net->ksnn_interfaces[j].ksni_name,
+ names[i], sizeof(net->ksnn_interfaces[j].ksni_name));
j++;
}
@@ -2807,8 +2805,9 @@ ksocknal_startup(lnet_ni_t *ni)
goto fail_1;
}
- strncpy(&net->ksnn_interfaces[i].ksni_name[0],
- ni->ni_interfaces[i], IFNAMSIZ);
+ strlcpy(net->ksnn_interfaces[i].ksni_name,
+ ni->ni_interfaces[i],
+ sizeof(net->ksnn_interfaces[i].ksni_name));
}
net->ksnn_ninterfaces = i;
}
@@ -2870,7 +2869,7 @@ ksocknal_module_init(void)
return 0;
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Kernel TCP Socket LND v3.0.0");
MODULE_LICENSE("GPL");
MODULE_VERSION("3.0.0");
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
index b349847f9cf9..f4fa72550657 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
@@ -679,6 +679,9 @@ int ksocknal_lib_recv_kiov(ksock_conn_t *conn);
int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem,
int *rxmem, int *nagle);
+void ksocknal_read_callback(ksock_conn_t *conn);
+void ksocknal_write_callback(ksock_conn_t *conn);
+
int ksocknal_tunables_init(void);
void ksocknal_lib_csum_tx(ksock_tx_t *tx);
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c
index 679785b0209c..04a4653c549a 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c
@@ -580,8 +580,6 @@ ksocknal_lib_push_conn(ksock_conn_t *conn)
ksocknal_connsock_decref(conn);
}
-extern void ksocknal_read_callback(ksock_conn_t *conn);
-extern void ksocknal_write_callback(ksock_conn_t *conn);
/*
* socket call back in Linux
*/
diff --git a/drivers/staging/lustre/lnet/lnet/Makefile b/drivers/staging/lustre/lnet/lnet/Makefile
index 52492fb10f85..e276fe2bf8f3 100644
--- a/drivers/staging/lustre/lnet/lnet/Makefile
+++ b/drivers/staging/lustre/lnet/lnet/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_LNET) += lnet.o
-lnet-y := api-ni.o config.o \
+lnet-y := api-ni.o config.o nidstrings.o \
lib-me.o lib-msg.o lib-eq.o lib-md.o lib-ptl.o \
lib-socket.o lib-move.o module.o lo.o \
router.o router_proc.o acceptor.o peer.o
diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c
index 53ad5ef4cde4..284150f53f7d 100644
--- a/drivers/staging/lustre/lnet/lnet/api-ni.c
+++ b/drivers/staging/lustre/lnet/lnet/api-ni.c
@@ -263,7 +263,7 @@ static void lnet_assert_wire_constants(void)
}
static lnd_t *
-lnet_find_lnd_by_type(int type)
+lnet_find_lnd_by_type(__u32 type)
{
lnd_t *lnd;
struct list_head *tmp;
@@ -272,7 +272,7 @@ lnet_find_lnd_by_type(int type)
list_for_each(tmp, &the_lnet.ln_lnds) {
lnd = list_entry(tmp, lnd_t, lnd_list);
- if ((int)lnd->lnd_type == type)
+ if (lnd->lnd_type == type)
return lnd;
}
@@ -356,15 +356,6 @@ lnet_counters_reset(void)
}
EXPORT_SYMBOL(lnet_counters_reset);
-static __u64
-lnet_create_interface_cookie(void)
-{
- /* NB the interface cookie in wire handles guards against delayed
- * replies and ACKs appearing valid after reboot.
- */
- return ktime_get_ns();
-}
-
static char *
lnet_res_type2str(int type)
{
@@ -553,8 +544,11 @@ lnet_prepare(lnet_pid_t requested_pid)
rc = lnet_create_remote_nets_table();
if (rc != 0)
goto failed;
-
- the_lnet.ln_interface_cookie = lnet_create_interface_cookie();
+ /*
+ * NB the interface cookie in wire handles guards against delayed
+ * replies and ACKs appearing valid after reboot.
+ */
+ the_lnet.ln_interface_cookie = ktime_get_ns();
the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(),
sizeof(lnet_counters_t));
@@ -962,7 +956,7 @@ lnet_startup_lndnis(void)
struct list_head nilist;
int i;
int rc = 0;
- int lnd_type;
+ __u32 lnd_type;
int nicount = 0;
char *nets = lnet_get_networks();
diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c
index b09a438c49d6..5390ee9963ab 100644
--- a/drivers/staging/lustre/lnet/lnet/config.c
+++ b/drivers/staging/lustre/lnet/lnet/config.c
@@ -650,8 +650,8 @@ lnet_parse_route(char *str, int *im_a_router)
INIT_LIST_HEAD(&nets);
/* save a copy of the string for error messages */
- strncpy(cmd, str, sizeof(cmd) - 1);
- cmd[sizeof(cmd) - 1] = 0;
+ strncpy(cmd, str, sizeof(cmd));
+ cmd[sizeof(cmd) - 1] = '\0';
sep = str;
for (;;) {
@@ -824,7 +824,7 @@ lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip)
for (rc = i = 0; !rc && i < nip; i++)
rc = cfs_ip_addr_match(ipaddrs[i], &list);
- cfs_ip_addr_free(&list);
+ cfs_expr_list_free_list(&list);
return rc;
}
@@ -972,11 +972,13 @@ lnet_splitnets(char *source, struct list_head *nets)
return 0;
offset += (int)(sep - tb->ltb_text);
- tb2 = lnet_new_text_buf(strlen(sep));
+ len = strlen(sep);
+ tb2 = lnet_new_text_buf(len);
if (tb2 == NULL)
return -ENOMEM;
- strcpy(tb2->ltb_text, sep);
+ strncpy(tb2->ltb_text, sep, len);
+ tb2->ltb_text[len] = '\0';
list_add_tail(&tb2->ltb_list, nets);
tb = tb2;
@@ -1021,8 +1023,8 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
tb = list_entry(raw_entries.next, struct lnet_text_buf_t,
ltb_list);
- strncpy(source, tb->ltb_text, sizeof(source)-1);
- source[sizeof(source)-1] = 0;
+ strncpy(source, tb->ltb_text, sizeof(source));
+ source[sizeof(source)-1] = '\0';
/* replace ltb_text with the network(s) add on match */
rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip);
@@ -1103,12 +1105,6 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
return count;
}
-static void
-lnet_ipaddr_free_enumeration(__u32 *ipaddrs, int nip)
-{
- LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
-}
-
static int
lnet_ipaddr_enumerate(__u32 **ipaddrsp)
{
@@ -1169,7 +1165,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp)
rc = nip;
}
}
- lnet_ipaddr_free_enumeration(ipaddrs, nif);
+ LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
}
return nip;
}
@@ -1195,7 +1191,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets)
}
rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip);
- lnet_ipaddr_free_enumeration(ipaddrs, nip);
+ LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
if (rc < 0) {
LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc);
diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c
index 576201a8390c..ac2fdf05a5fd 100644
--- a/drivers/staging/lustre/lnet/lnet/module.c
+++ b/drivers/staging/lustre/lnet/lnet/module.c
@@ -146,7 +146,7 @@ fini_lnet(void)
lnet_fini();
}
-MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("LNet v3.1");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0.0");
diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c
new file mode 100644
index 000000000000..80f585afa259
--- /dev/null
+++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c
@@ -0,0 +1,1260 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be 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 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2012, Intel Corporation.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lnet/lnet/nidstrings.c
+ *
+ * Author: Phil Schwan <phil@clusterfs.com>
+ */
+
+#define DEBUG_SUBSYSTEM S_LNET
+
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lnet.h"
+
+/* max value for numeric network address */
+#define MAX_NUMERIC_VALUE 0xffffffff
+
+#define IPSTRING_LENGTH 16
+
+/* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
+ * consistent in all conversion functions. Some code fragments are copied
+ * around for the sake of clarity...
+ */
+
+/* CAVEAT EMPTOR! Racey temporary buffer allocation!
+ * Choose the number of nidstrings to support the MAXIMUM expected number of
+ * concurrent users. If there are more, the returned string will be volatile.
+ * NB this number must allow for a process to be descheduled for a timeslice
+ * between getting its string and using it.
+ */
+
+static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
+static int libcfs_nidstring_idx;
+
+static DEFINE_SPINLOCK(libcfs_nidstring_lock);
+
+static struct netstrfns *libcfs_namenum2netstrfns(const char *name);
+
+char *
+libcfs_next_nidstring(void)
+{
+ char *str;
+ unsigned long flags;
+
+ spin_lock_irqsave(&libcfs_nidstring_lock, flags);
+
+ str = libcfs_nidstrings[libcfs_nidstring_idx++];
+ if (libcfs_nidstring_idx == ARRAY_SIZE(libcfs_nidstrings))
+ libcfs_nidstring_idx = 0;
+
+ spin_unlock_irqrestore(&libcfs_nidstring_lock, flags);
+ return str;
+}
+EXPORT_SYMBOL(libcfs_next_nidstring);
+
+/**
+ * Nid range list syntax.
+ * \verbatim
+ *
+ * <nidlist> :== <nidrange> [ ' ' <nidrange> ]
+ * <nidrange> :== <addrrange> '@' <net>
+ * <addrrange> :== '*' |
+ * <ipaddr_range> |
+ * <cfs_expr_list>
+ * <ipaddr_range> :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
+ * <cfs_expr_list>
+ * <cfs_expr_list> :== <number> |
+ * <expr_list>
+ * <expr_list> :== '[' <range_expr> [ ',' <range_expr>] ']'
+ * <range_expr> :== <number> |
+ * <number> '-' <number> |
+ * <number> '-' <number> '/' <number>
+ * <net> :== <netname> | <netname><number>
+ * <netname> :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" |
+ * "vib" | "ra" | "elan" | "mx" | "ptl"
+ * \endverbatim
+ */
+
+/**
+ * Structure to represent \<nidrange\> token of the syntax.
+ *
+ * One of this is created for each \<net\> parsed.
+ */
+struct nidrange {
+ /**
+ * Link to list of this structures which is built on nid range
+ * list parsing.
+ */
+ struct list_head nr_link;
+ /**
+ * List head for addrrange::ar_link.
+ */
+ struct list_head nr_addrranges;
+ /**
+ * Flag indicating that *@<net> is found.
+ */
+ int nr_all;
+ /**
+ * Pointer to corresponding element of libcfs_netstrfns.
+ */
+ struct netstrfns *nr_netstrfns;
+ /**
+ * Number of network. E.g. 5 if \<net\> is "elan5".
+ */
+ int nr_netnum;
+};
+
+/**
+ * Structure to represent \<addrrange\> token of the syntax.
+ */
+struct addrrange {
+ /**
+ * Link to nidrange::nr_addrranges.
+ */
+ struct list_head ar_link;
+ /**
+ * List head for cfs_expr_list::el_list.
+ */
+ struct list_head ar_numaddr_ranges;
+};
+
+/**
+ * Parses \<addrrange\> token on the syntax.
+ *
+ * Allocates struct addrrange and links to \a nidrange via
+ * (nidrange::nr_addrranges)
+ *
+ * \retval 0 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
+ * \retval -errno otherwise
+ */
+static int
+parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
+{
+ struct addrrange *addrrange;
+
+ if (src->ls_len == 1 && src->ls_str[0] == '*') {
+ nidrange->nr_all = 1;
+ return 0;
+ }
+
+ LIBCFS_ALLOC(addrrange, sizeof(struct addrrange));
+ if (addrrange == NULL)
+ return -ENOMEM;
+ list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
+ INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
+
+ return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str,
+ src->ls_len,
+ &addrrange->ar_numaddr_ranges);
+}
+
+/**
+ * Finds or creates struct nidrange.
+ *
+ * Checks if \a src is a valid network name, looks for corresponding
+ * nidrange on the ist of nidranges (\a nidlist), creates new struct
+ * nidrange if it is not found.
+ *
+ * \retval pointer to struct nidrange matching network specified via \a src
+ * \retval NULL if \a src does not match any network
+ */
+static struct nidrange *
+add_nidrange(const struct cfs_lstr *src,
+ struct list_head *nidlist)
+{
+ struct netstrfns *nf;
+ struct nidrange *nr;
+ int endlen;
+ unsigned netnum;
+
+ if (src->ls_len >= LNET_NIDSTR_SIZE)
+ return NULL;
+
+ nf = libcfs_namenum2netstrfns(src->ls_str);
+ if (nf == NULL)
+ return NULL;
+ endlen = src->ls_len - strlen(nf->nf_name);
+ if (endlen == 0)
+ /* network name only, e.g. "elan" or "tcp" */
+ netnum = 0;
+ else {
+ /* e.g. "elan25" or "tcp23", refuse to parse if
+ * network name is not appended with decimal or
+ * hexadecimal number */
+ if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
+ endlen, &netnum, 0, MAX_NUMERIC_VALUE))
+ return NULL;
+ }
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ if (nr->nr_netstrfns != nf)
+ continue;
+ if (nr->nr_netnum != netnum)
+ continue;
+ return nr;
+ }
+
+ LIBCFS_ALLOC(nr, sizeof(struct nidrange));
+ if (nr == NULL)
+ return NULL;
+ list_add_tail(&nr->nr_link, nidlist);
+ INIT_LIST_HEAD(&nr->nr_addrranges);
+ nr->nr_netstrfns = nf;
+ nr->nr_all = 0;
+ nr->nr_netnum = netnum;
+
+ return nr;
+}
+
+/**
+ * Parses \<nidrange\> token of the syntax.
+ *
+ * \retval 1 if \a src parses to \<addrrange\> '@' \<net\>
+ * \retval 0 otherwise
+ */
+static int
+parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist)
+{
+ struct cfs_lstr addrrange;
+ struct cfs_lstr net;
+ struct cfs_lstr tmp;
+ struct nidrange *nr;
+
+ tmp = *src;
+ if (cfs_gettok(src, '@', &addrrange) == 0)
+ goto failed;
+
+ if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
+ goto failed;
+
+ nr = add_nidrange(&net, nidlist);
+ if (nr == NULL)
+ goto failed;
+
+ if (parse_addrange(&addrrange, nr) != 0)
+ goto failed;
+
+ return 1;
+failed:
+ CWARN("can't parse nidrange: \"%.*s\"\n", tmp.ls_len, tmp.ls_str);
+ return 0;
+}
+
+/**
+ * Frees addrrange structures of \a list.
+ *
+ * For each struct addrrange structure found on \a list it frees
+ * cfs_expr_list list attached to it and frees the addrrange itself.
+ *
+ * \retval none
+ */
+static void
+free_addrranges(struct list_head *list)
+{
+ while (!list_empty(list)) {
+ struct addrrange *ar;
+
+ ar = list_entry(list->next, struct addrrange, ar_link);
+
+ cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
+ list_del(&ar->ar_link);
+ LIBCFS_FREE(ar, sizeof(struct addrrange));
+ }
+}
+
+/**
+ * Frees nidrange strutures of \a list.
+ *
+ * For each struct nidrange structure found on \a list it frees
+ * addrrange list attached to it and frees the nidrange itself.
+ *
+ * \retval none
+ */
+void
+cfs_free_nidlist(struct list_head *list)
+{
+ struct list_head *pos, *next;
+ struct nidrange *nr;
+
+ list_for_each_safe(pos, next, list) {
+ nr = list_entry(pos, struct nidrange, nr_link);
+ free_addrranges(&nr->nr_addrranges);
+ list_del(pos);
+ LIBCFS_FREE(nr, sizeof(struct nidrange));
+ }
+}
+EXPORT_SYMBOL(cfs_free_nidlist);
+
+/**
+ * Parses nid range list.
+ *
+ * Parses with rigorous syntax and overflow checking \a str into
+ * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of
+ * structures and links that structure to \a nidlist. The resulting
+ * list can be used to match a NID againts set of NIDS defined by \a
+ * str.
+ * \see cfs_match_nid
+ *
+ * \retval 1 on success
+ * \retval 0 otherwise
+ */
+int
+cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
+{
+ struct cfs_lstr src;
+ struct cfs_lstr res;
+ int rc;
+
+ src.ls_str = str;
+ src.ls_len = len;
+ INIT_LIST_HEAD(nidlist);
+ while (src.ls_str) {
+ rc = cfs_gettok(&src, ' ', &res);
+ if (rc == 0) {
+ cfs_free_nidlist(nidlist);
+ return 0;
+ }
+ rc = parse_nidrange(&res, nidlist);
+ if (rc == 0) {
+ cfs_free_nidlist(nidlist);
+ return 0;
+ }
+ }
+ return 1;
+}
+EXPORT_SYMBOL(cfs_parse_nidlist);
+
+/**
+ * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
+ *
+ * \see cfs_parse_nidlist()
+ *
+ * \retval 1 on match
+ * \retval 0 otherwises
+ */
+int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
+{
+ struct nidrange *nr;
+ struct addrrange *ar;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid)))
+ continue;
+ if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid)))
+ continue;
+ if (nr->nr_all)
+ return 1;
+ list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
+ if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid),
+ &ar->ar_numaddr_ranges))
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(cfs_match_nid);
+
+/**
+ * Print the network part of the nidrange \a nr into the specified \a buffer.
+ *
+ * \retval number of characters written
+ */
+static int
+cfs_print_network(char *buffer, int count, struct nidrange *nr)
+{
+ struct netstrfns *nf = nr->nr_netstrfns;
+
+ if (nr->nr_netnum == 0)
+ return scnprintf(buffer, count, "@%s", nf->nf_name);
+ else
+ return scnprintf(buffer, count, "@%s%u",
+ nf->nf_name, nr->nr_netnum);
+}
+
+/**
+ * Print a list of addrrange (\a addrranges) into the specified \a buffer.
+ * At max \a count characters can be printed into \a buffer.
+ *
+ * \retval number of characters written
+ */
+static int
+cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges,
+ struct nidrange *nr)
+{
+ int i = 0;
+ struct addrrange *ar;
+ struct netstrfns *nf = nr->nr_netstrfns;
+
+ list_for_each_entry(ar, addrranges, ar_link) {
+ if (i != 0)
+ i += scnprintf(buffer + i, count - i, " ");
+ i += nf->nf_print_addrlist(buffer + i, count - i,
+ &ar->ar_numaddr_ranges);
+ i += cfs_print_network(buffer + i, count - i, nr);
+ }
+ return i;
+}
+
+/**
+ * Print a list of nidranges (\a nidlist) into the specified \a buffer.
+ * At max \a count characters can be printed into \a buffer.
+ * Nidranges are separated by a space character.
+ *
+ * \retval number of characters written
+ */
+int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
+{
+ int i = 0;
+ struct nidrange *nr;
+
+ if (count <= 0)
+ return 0;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ if (i != 0)
+ i += scnprintf(buffer + i, count - i, " ");
+
+ if (nr->nr_all != 0) {
+ LASSERT(list_empty(&nr->nr_addrranges));
+ i += scnprintf(buffer + i, count - i, "*");
+ i += cfs_print_network(buffer + i, count - i, nr);
+ } else {
+ i += cfs_print_addrranges(buffer + i, count - i,
+ &nr->nr_addrranges, nr);
+ }
+ }
+ return i;
+}
+EXPORT_SYMBOL(cfs_print_nidlist);
+
+/**
+ * Determines minimum and maximum addresses for a single
+ * numeric address range
+ *
+ * \param ar
+ * \param min_nid
+ * \param max_nid
+ */
+static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid,
+ __u32 *max_nid)
+{
+ struct cfs_expr_list *el;
+ struct cfs_range_expr *re;
+ __u32 tmp_ip_addr = 0;
+ unsigned int min_ip[4] = {0};
+ unsigned int max_ip[4] = {0};
+ int re_count = 0;
+
+ list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
+ list_for_each_entry(re, &el->el_exprs, re_link) {
+ min_ip[re_count] = re->re_lo;
+ max_ip[re_count] = re->re_hi;
+ re_count++;
+ }
+ }
+
+ tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) |
+ (min_ip[2] << 8) | min_ip[3]);
+
+ if (min_nid != NULL)
+ *min_nid = tmp_ip_addr;
+
+ tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) |
+ (max_ip[2] << 8) | max_ip[3]);
+
+ if (max_nid != NULL)
+ *max_nid = tmp_ip_addr;
+}
+
+/**
+ * Determines minimum and maximum addresses for a single
+ * numeric address range
+ *
+ * \param ar
+ * \param min_nid
+ * \param max_nid
+ */
+static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid,
+ __u32 *max_nid)
+{
+ struct cfs_expr_list *el;
+ struct cfs_range_expr *re;
+ unsigned int min_addr = 0;
+ unsigned int max_addr = 0;
+
+ list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
+ list_for_each_entry(re, &el->el_exprs, re_link) {
+ if (re->re_lo < min_addr || min_addr == 0)
+ min_addr = re->re_lo;
+ if (re->re_hi > max_addr)
+ max_addr = re->re_hi;
+ }
+ }
+
+ if (min_nid != NULL)
+ *min_nid = min_addr;
+ if (max_nid != NULL)
+ *max_nid = max_addr;
+}
+
+/**
+ * Determines whether an expression list in an nidrange contains exactly
+ * one contiguous address range. Calls the correct netstrfns for the LND
+ *
+ * \param *nidlist
+ *
+ * \retval true if contiguous
+ * \retval false if not contiguous
+ */
+bool cfs_nidrange_is_contiguous(struct list_head *nidlist)
+{
+ struct nidrange *nr;
+ struct netstrfns *nf = NULL;
+ char *lndname = NULL;
+ int netnum = -1;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ nf = nr->nr_netstrfns;
+ if (lndname == NULL)
+ lndname = nf->nf_name;
+ if (netnum == -1)
+ netnum = nr->nr_netnum;
+
+ if (strcmp(lndname, nf->nf_name) != 0 ||
+ netnum != nr->nr_netnum)
+ return false;
+ }
+
+ if (nf == NULL)
+ return false;
+
+ if (!nf->nf_is_contiguous(nidlist))
+ return false;
+
+ return true;
+}
+EXPORT_SYMBOL(cfs_nidrange_is_contiguous);
+
+/**
+ * Determines whether an expression list in an num nidrange contains exactly
+ * one contiguous address range.
+ *
+ * \param *nidlist
+ *
+ * \retval true if contiguous
+ * \retval false if not contiguous
+ */
+static bool cfs_num_is_contiguous(struct list_head *nidlist)
+{
+ struct nidrange *nr;
+ struct addrrange *ar;
+ struct cfs_expr_list *el;
+ struct cfs_range_expr *re;
+ int last_hi = 0;
+ __u32 last_end_nid = 0;
+ __u32 current_start_nid = 0;
+ __u32 current_end_nid = 0;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+ cfs_num_ar_min_max(ar, &current_start_nid,
+ &current_end_nid);
+ if (last_end_nid != 0 &&
+ (current_start_nid - last_end_nid != 1))
+ return false;
+ last_end_nid = current_end_nid;
+ list_for_each_entry(el, &ar->ar_numaddr_ranges,
+ el_link) {
+ list_for_each_entry(re, &el->el_exprs,
+ re_link) {
+ if (re->re_stride > 1)
+ return false;
+ else if (last_hi != 0 &&
+ re->re_hi - last_hi != 1)
+ return false;
+ last_hi = re->re_hi;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Determines whether an expression list in an ip nidrange contains exactly
+ * one contiguous address range.
+ *
+ * \param *nidlist
+ *
+ * \retval true if contiguous
+ * \retval false if not contiguous
+ */
+static bool cfs_ip_is_contiguous(struct list_head *nidlist)
+{
+ struct nidrange *nr;
+ struct addrrange *ar;
+ struct cfs_expr_list *el;
+ struct cfs_range_expr *re;
+ int expr_count;
+ int last_hi = 255;
+ int last_diff = 0;
+ __u32 last_end_nid = 0;
+ __u32 current_start_nid = 0;
+ __u32 current_end_nid = 0;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+ last_hi = 255;
+ last_diff = 0;
+ cfs_ip_ar_min_max(ar, &current_start_nid,
+ &current_end_nid);
+ if (last_end_nid != 0 &&
+ (current_start_nid - last_end_nid != 1))
+ return false;
+ last_end_nid = current_end_nid;
+ list_for_each_entry(el, &ar->ar_numaddr_ranges,
+ el_link) {
+ expr_count = 0;
+ list_for_each_entry(re, &el->el_exprs,
+ re_link) {
+ expr_count++;
+ if (re->re_stride > 1 ||
+ (last_diff > 0 && last_hi != 255) ||
+ (last_diff > 0 && last_hi == 255 &&
+ re->re_lo > 0))
+ return false;
+ last_hi = re->re_hi;
+ last_diff = re->re_hi - re->re_lo;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Takes a linked list of nidrange expressions, determines the minimum
+ * and maximum nid and creates appropriate nid structures
+ *
+ * \param *nidlist
+ * \param *min_nid
+ * \param *max_nid
+ */
+void cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
+ char *max_nid, size_t nidstr_length)
+{
+ struct nidrange *nr;
+ struct netstrfns *nf = NULL;
+ int netnum = -1;
+ __u32 min_addr;
+ __u32 max_addr;
+ char *lndname = NULL;
+ char min_addr_str[IPSTRING_LENGTH];
+ char max_addr_str[IPSTRING_LENGTH];
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ nf = nr->nr_netstrfns;
+ lndname = nf->nf_name;
+ if (netnum == -1)
+ netnum = nr->nr_netnum;
+
+ nf->nf_min_max(nidlist, &min_addr, &max_addr);
+ }
+ nf->nf_addr2str(min_addr, min_addr_str, sizeof(min_addr_str));
+ nf->nf_addr2str(max_addr, max_addr_str, sizeof(max_addr_str));
+
+ snprintf(min_nid, nidstr_length, "%s@%s%d", min_addr_str, lndname,
+ netnum);
+ snprintf(max_nid, nidstr_length, "%s@%s%d", max_addr_str, lndname,
+ netnum);
+}
+EXPORT_SYMBOL(cfs_nidrange_find_min_max);
+
+/**
+ * Determines the min and max NID values for num LNDs
+ *
+ * \param *nidlist
+ * \param *min_nid
+ * \param *max_nid
+ */
+static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid,
+ __u32 *max_nid)
+{
+ struct nidrange *nr;
+ struct addrrange *ar;
+ unsigned int tmp_min_addr = 0;
+ unsigned int tmp_max_addr = 0;
+ unsigned int min_addr = 0;
+ unsigned int max_addr = 0;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+ cfs_num_ar_min_max(ar, &tmp_min_addr,
+ &tmp_max_addr);
+ if (tmp_min_addr < min_addr || min_addr == 0)
+ min_addr = tmp_min_addr;
+ if (tmp_max_addr > max_addr)
+ max_addr = tmp_min_addr;
+ }
+ }
+ *max_nid = max_addr;
+ *min_nid = min_addr;
+}
+
+/**
+ * Takes an nidlist and determines the minimum and maximum
+ * ip addresses.
+ *
+ * \param *nidlist
+ * \param *min_nid
+ * \param *max_nid
+ */
+static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid,
+ __u32 *max_nid)
+{
+ struct nidrange *nr;
+ struct addrrange *ar;
+ __u32 tmp_min_ip_addr = 0;
+ __u32 tmp_max_ip_addr = 0;
+ __u32 min_ip_addr = 0;
+ __u32 max_ip_addr = 0;
+
+ list_for_each_entry(nr, nidlist, nr_link) {
+ list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+ cfs_ip_ar_min_max(ar, &tmp_min_ip_addr,
+ &tmp_max_ip_addr);
+ if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0)
+ min_ip_addr = tmp_min_ip_addr;
+ if (tmp_max_ip_addr > max_ip_addr)
+ max_ip_addr = tmp_max_ip_addr;
+ }
+ }
+
+ if (min_nid != NULL)
+ *min_nid = min_ip_addr;
+ if (max_nid != NULL)
+ *max_nid = max_ip_addr;
+}
+
+static int
+libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
+{
+ *addr = 0;
+ return 1;
+}
+
+static void
+libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
+{
+ snprintf(str, size, "%u.%u.%u.%u",
+ (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+ (addr >> 8) & 0xff, addr & 0xff);
+}
+
+/* CAVEAT EMPTOR XscanfX
+ * I use "%n" at the end of a sscanf format to detect trailing junk. However
+ * sscanf may return immediately if it sees the terminating '0' in a string, so
+ * I initialise the %n variable to the expected length. If sscanf sets it;
+ * fine, if it doesn't, then the scan ended at the end of the string, which is
+ * fine too :) */
+static int
+libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
+{
+ unsigned int a;
+ unsigned int b;
+ unsigned int c;
+ unsigned int d;
+ int n = nob; /* XscanfX */
+
+ /* numeric IP? */
+ if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
+ n == nob &&
+ (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
+ (c & ~0xff) == 0 && (d & ~0xff) == 0) {
+ *addr = ((a<<24)|(b<<16)|(c<<8)|d);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Used by lnet/config.c so it can't be static */
+int
+cfs_ip_addr_parse(char *str, int len, struct list_head *list)
+{
+ struct cfs_expr_list *el;
+ struct cfs_lstr src;
+ int rc;
+ int i;
+
+ src.ls_str = str;
+ src.ls_len = len;
+ i = 0;
+
+ while (src.ls_str != NULL) {
+ struct cfs_lstr res;
+
+ if (!cfs_gettok(&src, '.', &res)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el);
+ if (rc != 0)
+ goto out;
+
+ list_add_tail(&el->el_link, list);
+ i++;
+ }
+
+ if (i == 4)
+ return 0;
+
+ rc = -EINVAL;
+out:
+ cfs_expr_list_free_list(list);
+
+ return rc;
+}
+
+static int
+libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
+{
+ int i = 0, j = 0;
+ struct cfs_expr_list *el;
+
+ list_for_each_entry(el, list, el_link) {
+ LASSERT(j++ < 4);
+ if (i != 0)
+ i += scnprintf(buffer + i, count - i, ".");
+ i += cfs_expr_list_print(buffer + i, count - i, el);
+ }
+ return i;
+}
+
+/**
+ * Matches address (\a addr) against address set encoded in \a list.
+ *
+ * \retval 1 if \a addr matches
+ * \retval 0 otherwise
+ */
+int
+cfs_ip_addr_match(__u32 addr, struct list_head *list)
+{
+ struct cfs_expr_list *el;
+ int i = 0;
+
+ list_for_each_entry_reverse(el, list, el_link) {
+ if (!cfs_expr_list_match(addr & 0xff, el))
+ return 0;
+ addr >>= 8;
+ i++;
+ }
+
+ return i == 4;
+}
+
+static void
+libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
+{
+ snprintf(str, size, "%u", addr);
+}
+
+static int
+libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
+{
+ int n;
+
+ n = nob;
+ if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
+ return 1;
+
+ n = nob;
+ if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
+ return 1;
+
+ n = nob;
+ if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Nf_parse_addrlist method for networks using numeric addresses.
+ *
+ * Examples of such networks are gm and elan.
+ *
+ * \retval 0 if \a str parsed to numeric address
+ * \retval errno otherwise
+ */
+static int
+libcfs_num_parse(char *str, int len, struct list_head *list)
+{
+ struct cfs_expr_list *el;
+ int rc;
+
+ rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
+ if (rc == 0)
+ list_add_tail(&el->el_link, list);
+
+ return rc;
+}
+
+static int
+libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
+{
+ int i = 0, j = 0;
+ struct cfs_expr_list *el;
+
+ list_for_each_entry(el, list, el_link) {
+ LASSERT(j++ < 1);
+ i += cfs_expr_list_print(buffer + i, count - i, el);
+ }
+ return i;
+}
+
+/*
+ * Nf_match_addr method for networks using numeric addresses
+ *
+ * \retval 1 on match
+ * \retval 0 otherwise
+ */
+static int
+libcfs_num_match(__u32 addr, struct list_head *numaddr)
+{
+ struct cfs_expr_list *el;
+
+ LASSERT(!list_empty(numaddr));
+ el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
+
+ return cfs_expr_list_match(addr, el);
+}
+
+static struct netstrfns libcfs_netstrfns[] = {
+ { .nf_type = LOLND,
+ .nf_name = "lo",
+ .nf_modname = "klolnd",
+ .nf_addr2str = libcfs_decnum_addr2str,
+ .nf_str2addr = libcfs_lo_str2addr,
+ .nf_parse_addrlist = libcfs_num_parse,
+ .nf_print_addrlist = libcfs_num_addr_range_print,
+ .nf_match_addr = libcfs_num_match,
+ .nf_is_contiguous = cfs_num_is_contiguous,
+ .nf_min_max = cfs_num_min_max },
+ { .nf_type = SOCKLND,
+ .nf_name = "tcp",
+ .nf_modname = "ksocklnd",
+ .nf_addr2str = libcfs_ip_addr2str,
+ .nf_str2addr = libcfs_ip_str2addr,
+ .nf_parse_addrlist = cfs_ip_addr_parse,
+ .nf_print_addrlist = libcfs_ip_addr_range_print,
+ .nf_match_addr = cfs_ip_addr_match,
+ .nf_is_contiguous = cfs_ip_is_contiguous,
+ .nf_min_max = cfs_ip_min_max },
+ { .nf_type = O2IBLND,
+ .nf_name = "o2ib",
+ .nf_modname = "ko2iblnd",
+ .nf_addr2str = libcfs_ip_addr2str,
+ .nf_str2addr = libcfs_ip_str2addr,
+ .nf_parse_addrlist = cfs_ip_addr_parse,
+ .nf_print_addrlist = libcfs_ip_addr_range_print,
+ .nf_match_addr = cfs_ip_addr_match,
+ .nf_is_contiguous = cfs_ip_is_contiguous,
+ .nf_min_max = cfs_ip_min_max },
+ { .nf_type = GNILND,
+ .nf_name = "gni",
+ .nf_modname = "kgnilnd",
+ .nf_addr2str = libcfs_decnum_addr2str,
+ .nf_str2addr = libcfs_num_str2addr,
+ .nf_parse_addrlist = libcfs_num_parse,
+ .nf_print_addrlist = libcfs_num_addr_range_print,
+ .nf_match_addr = libcfs_num_match,
+ .nf_is_contiguous = cfs_num_is_contiguous,
+ .nf_min_max = cfs_num_min_max },
+ { .nf_type = GNIIPLND,
+ .nf_name = "gip",
+ .nf_modname = "kgnilnd",
+ .nf_addr2str = libcfs_ip_addr2str,
+ .nf_str2addr = libcfs_ip_str2addr,
+ .nf_parse_addrlist = cfs_ip_addr_parse,
+ .nf_print_addrlist = libcfs_ip_addr_range_print,
+ .nf_match_addr = cfs_ip_addr_match,
+ .nf_is_contiguous = cfs_ip_is_contiguous,
+ .nf_min_max = cfs_ip_min_max },
+};
+
+static const size_t libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns);
+
+static struct netstrfns *
+libcfs_lnd2netstrfns(__u32 lnd)
+{
+ int i;
+
+ for (i = 0; i < libcfs_nnetstrfns; i++)
+ if (lnd == libcfs_netstrfns[i].nf_type)
+ return &libcfs_netstrfns[i];
+
+ return NULL;
+}
+
+static struct netstrfns *
+libcfs_namenum2netstrfns(const char *name)
+{
+ struct netstrfns *nf;
+ int i;
+
+ for (i = 0; i < libcfs_nnetstrfns; i++) {
+ nf = &libcfs_netstrfns[i];
+ if (!strncmp(name, nf->nf_name, strlen(nf->nf_name)))
+ return nf;
+ }
+ return NULL;
+}
+
+static struct netstrfns *
+libcfs_name2netstrfns(const char *name)
+{
+ int i;
+
+ for (i = 0; i < libcfs_nnetstrfns; i++)
+ if (!strcmp(libcfs_netstrfns[i].nf_name, name))
+ return &libcfs_netstrfns[i];
+
+ return NULL;
+}
+
+int
+libcfs_isknown_lnd(__u32 lnd)
+{
+ return libcfs_lnd2netstrfns(lnd) != NULL;
+}
+EXPORT_SYMBOL(libcfs_isknown_lnd);
+
+char *
+libcfs_lnd2modname(__u32 lnd)
+{
+ struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
+
+ return (nf == NULL) ? NULL : nf->nf_modname;
+}
+EXPORT_SYMBOL(libcfs_lnd2modname);
+
+int
+libcfs_str2lnd(const char *str)
+{
+ struct netstrfns *nf = libcfs_name2netstrfns(str);
+
+ if (nf != NULL)
+ return nf->nf_type;
+
+ return -1;
+}
+EXPORT_SYMBOL(libcfs_str2lnd);
+
+char *
+libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size)
+{
+ struct netstrfns *nf;
+
+ nf = libcfs_lnd2netstrfns(lnd);
+ if (nf == NULL)
+ snprintf(buf, buf_size, "?%u?", lnd);
+ else
+ snprintf(buf, buf_size, "%s", nf->nf_name);
+
+ return buf;
+}
+EXPORT_SYMBOL(libcfs_lnd2str_r);
+
+char *
+libcfs_net2str_r(__u32 net, char *buf, size_t buf_size)
+{
+ __u32 nnum = LNET_NETNUM(net);
+ __u32 lnd = LNET_NETTYP(net);
+ struct netstrfns *nf;
+
+ nf = libcfs_lnd2netstrfns(lnd);
+ if (nf == NULL)
+ snprintf(buf, buf_size, "<%u:%u>", lnd, nnum);
+ else if (nnum == 0)
+ snprintf(buf, buf_size, "%s", nf->nf_name);
+ else
+ snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum);
+
+ return buf;
+}
+EXPORT_SYMBOL(libcfs_net2str_r);
+
+char *
+libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size)
+{
+ __u32 addr = LNET_NIDADDR(nid);
+ __u32 net = LNET_NIDNET(nid);
+ __u32 nnum = LNET_NETNUM(net);
+ __u32 lnd = LNET_NETTYP(net);
+ struct netstrfns *nf;
+
+ if (nid == LNET_NID_ANY) {
+ strncpy(buf, "<?>", buf_size);
+ buf[buf_size - 1] = '\0';
+ return buf;
+ }
+
+ nf = libcfs_lnd2netstrfns(lnd);
+ if (nf == NULL)
+ snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum);
+ else {
+ size_t addr_len;
+
+ nf->nf_addr2str(addr, buf, buf_size);
+ addr_len = strlen(buf);
+ if (nnum == 0)
+ snprintf(buf + addr_len, buf_size - addr_len, "@%s",
+ nf->nf_name);
+ else
+ snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
+ nf->nf_name, nnum);
+ }
+
+ return buf;
+}
+EXPORT_SYMBOL(libcfs_nid2str_r);
+
+static struct netstrfns *
+libcfs_str2net_internal(const char *str, __u32 *net)
+{
+ struct netstrfns *uninitialized_var(nf);
+ int nob;
+ unsigned int netnum;
+ int i;
+
+ for (i = 0; i < libcfs_nnetstrfns; i++) {
+ nf = &libcfs_netstrfns[i];
+ if (!strncmp(str, nf->nf_name, strlen(nf->nf_name)))
+ break;
+ }
+
+ if (i == libcfs_nnetstrfns)
+ return NULL;
+
+ nob = strlen(nf->nf_name);
+
+ if (strlen(str) == (unsigned int)nob) {
+ netnum = 0;
+ } else {
+ if (nf->nf_type == LOLND) /* net number not allowed */
+ return NULL;
+
+ str += nob;
+ i = strlen(str);
+ if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
+ i != (int)strlen(str))
+ return NULL;
+ }
+
+ *net = LNET_MKNET(nf->nf_type, netnum);
+ return nf;
+}
+
+__u32
+libcfs_str2net(const char *str)
+{
+ __u32 net;
+
+ if (libcfs_str2net_internal(str, &net) != NULL)
+ return net;
+
+ return LNET_NIDNET(LNET_NID_ANY);
+}
+EXPORT_SYMBOL(libcfs_str2net);
+
+lnet_nid_t
+libcfs_str2nid(const char *str)
+{
+ const char *sep = strchr(str, '@');
+ struct netstrfns *nf;
+ __u32 net;
+ __u32 addr;
+
+ if (sep != NULL) {
+ nf = libcfs_str2net_internal(sep + 1, &net);
+ if (nf == NULL)
+ return LNET_NID_ANY;
+ } else {
+ sep = str + strlen(str);
+ net = LNET_MKNET(SOCKLND, 0);
+ nf = libcfs_lnd2netstrfns(SOCKLND);
+ LASSERT(nf != NULL);
+ }
+
+ if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
+ return LNET_NID_ANY;
+
+ return LNET_MKNID(net, addr);
+}
+EXPORT_SYMBOL(libcfs_str2nid);
+
+char *
+libcfs_id2str(lnet_process_id_t id)
+{
+ char *str = libcfs_next_nidstring();
+
+ if (id.pid == LNET_PID_ANY) {
+ snprintf(str, LNET_NIDSTR_SIZE,
+ "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
+ return str;
+ }
+
+ snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
+ ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
+ (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
+ return str;
+}
+EXPORT_SYMBOL(libcfs_id2str);
+
+int
+libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
+{
+ if (!strcmp(str, "*")) {
+ *nidp = LNET_NID_ANY;
+ return 1;
+ }
+
+ *nidp = libcfs_str2nid(str);
+ return *nidp != LNET_NID_ANY;
+}
+EXPORT_SYMBOL(libcfs_str2anynid);
diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c
index 4b5677025cd5..4ea651c6db3a 100644
--- a/drivers/staging/lustre/lnet/lnet/router.c
+++ b/drivers/staging/lustre/lnet/lnet/router.c
@@ -235,7 +235,7 @@ lnet_find_net_locked(__u32 net)
static void lnet_shuffle_seed(void)
{
static int seeded;
- int lnd_type, seed[2];
+ __u32 lnd_type, seed[2];
struct timespec64 ts;
lnet_ni_t *ni;
struct list_head *tmp;
@@ -1245,7 +1245,7 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt)
for (i = 0; i < npages; i++) {
page = alloc_pages_node(
cfs_cpt_spread_node(lnet_cpt_table(), cpt),
- __GFP_ZERO | GFP_IOFS, 0);
+ GFP_KERNEL | __GFP_ZERO, 0);
if (page == NULL) {
while (--i >= 0)
__free_page(rb->rb_kiov[i].kiov_page);
diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c
index 0605c651f797..0f262267e01e 100644
--- a/drivers/staging/lustre/lnet/selftest/brw_test.c
+++ b/drivers/staging/lustre/lnet/selftest/brw_test.c
@@ -358,7 +358,7 @@ out:
}
static void
-brw_server_rpc_done(srpc_server_rpc_t *rpc)
+brw_server_rpc_done(struct srpc_server_rpc *rpc)
{
srpc_bulk_t *blk = rpc->srpc_bulk;
@@ -378,7 +378,7 @@ brw_server_rpc_done(srpc_server_rpc_t *rpc)
}
static int
-brw_bulk_ready(srpc_server_rpc_t *rpc, int status)
+brw_bulk_ready(struct srpc_server_rpc *rpc, int status)
{
__u64 magic = BRW_MAGIC;
srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c
index 817396638652..556c837cf62c 100644
--- a/drivers/staging/lustre/lnet/selftest/conctl.c
+++ b/drivers/staging/lustre/lnet/selftest/conctl.c
@@ -441,7 +441,7 @@ lst_group_info_ioctl(lstio_group_info_args_t *args)
if (args->lstio_grp_dentsp != NULL &&
(copy_to_user(args->lstio_grp_idxp, &index, sizeof(index)) ||
copy_to_user(args->lstio_grp_ndentp, &ndent, sizeof(ndent))))
- rc = -EFAULT;
+ return -EFAULT;
return 0;
}
diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c
index 0060ff64f88e..1066c70434b1 100644
--- a/drivers/staging/lustre/lnet/selftest/conrpc.c
+++ b/drivers/staging/lustre/lnet/selftest/conrpc.c
@@ -612,8 +612,8 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop,
msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst;
msrq->mksn_sid = console_session.ses_id;
msrq->mksn_force = console_session.ses_force;
- strncpy(msrq->mksn_name, console_session.ses_name,
- strlen(console_session.ses_name));
+ strlcpy(msrq->mksn_name, console_session.ses_name,
+ sizeof(msrq->mksn_name));
break;
case LST_TRANS_SESEND:
@@ -860,7 +860,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats,
bulk->bk_iovs[i].kiov_offset = 0;
bulk->bk_iovs[i].kiov_len = len;
bulk->bk_iovs[i].kiov_page =
- alloc_page(GFP_IOFS);
+ alloc_page(GFP_KERNEL);
if (bulk->bk_iovs[i].kiov_page == NULL) {
lstcon_rpc_put(*crpc);
diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c
index d315dd44ae3b..5619fc430e8d 100644
--- a/drivers/staging/lustre/lnet/selftest/console.c
+++ b/drivers/staging/lustre/lnet/selftest/console.c
@@ -277,12 +277,6 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp)
return -ENOENT;
}
-static void
-lstcon_group_put(lstcon_group_t *grp)
-{
- lstcon_group_decref(grp);
-}
-
static int
lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id,
lstcon_ndlink_t **ndlpp, int create)
@@ -324,8 +318,6 @@ lstcon_group_ndlink_move(lstcon_group_t *old,
list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
list_add_tail(&ndl->ndl_link, &new->grp_ndl_list);
new->grp_nnode++;
-
- return;
}
static void
@@ -436,7 +428,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp,
}
if (rc != 0) {
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
}
@@ -445,7 +437,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp,
tmp, lstcon_sesrpc_condition, &trans);
if (rc != 0) {
CERROR("Can't create transaction: %d\n", rc);
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
}
@@ -460,7 +452,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp,
lstcon_rpc_trans_destroy(trans);
lstcon_group_move(tmp, grp);
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
}
@@ -510,12 +502,12 @@ lstcon_group_nodes_remove(lstcon_group_t *grp,
lstcon_rpc_trans_destroy(trans);
/* release nodes anyway, because we can't rollback status */
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
error:
lstcon_group_move(tmp, grp);
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
}
@@ -529,7 +521,7 @@ lstcon_group_add(char *name)
rc = (lstcon_group_find(name, &grp) == 0) ? -EEXIST : 0;
if (rc != 0) {
/* find a group with same name */
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -563,14 +555,14 @@ lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up,
if (grp->grp_ref > 2) {
/* referred by other threads or test */
CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return -EBUSY;
}
rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -591,7 +583,7 @@ lstcon_group_del(char *name)
if (grp->grp_ref > 2) {
/* referred by others threads or test */
CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return -EBUSY;
}
@@ -600,7 +592,7 @@ lstcon_group_del(char *name)
grp, lstcon_sesrpc_condition, &trans);
if (rc != 0) {
CERROR("Can't create transaction: %d\n", rc);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -608,10 +600,10 @@ lstcon_group_del(char *name)
lstcon_rpc_trans_destroy(trans);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
/* -ref for session, it's destroyed,
* status can't be rolled back, destroy group anyway */
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -631,7 +623,7 @@ lstcon_group_clean(char *name, int args)
if (grp->grp_ref > 2) {
/* referred by test */
CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return -EBUSY;
}
@@ -640,10 +632,10 @@ lstcon_group_clean(char *name, int args)
lstcon_group_drain(grp, args);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
/* release empty group */
if (list_empty(&grp->grp_ndl_list))
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return 0;
}
@@ -664,16 +656,16 @@ lstcon_nodes_remove(char *name, int count,
if (grp->grp_ref > 2) {
/* referred by test */
CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return -EBUSY;
}
rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
/* release empty group */
if (list_empty(&grp->grp_ndl_list))
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -694,7 +686,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up)
if (grp->grp_ref > 2) {
/* referred by test */
CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return -EBUSY;
}
@@ -705,7 +697,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up)
if (rc != 0) {
/* local error, return */
CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -715,7 +707,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up)
lstcon_rpc_trans_destroy(trans);
/* -ref for me */
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -797,7 +789,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p,
/* verbose query */
rc = lstcon_nodes_getent(&grp->grp_ndl_list,
index_p, count_p, dents_up);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -806,7 +798,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p,
LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t));
if (gentp == NULL) {
CERROR("Can't allocate ndlist_ent\n");
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return -ENOMEM;
}
@@ -819,7 +811,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p,
LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t));
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return 0;
}
@@ -1096,8 +1088,8 @@ lstcon_batch_destroy(lstcon_batch_t *bat)
list_del(&test->tes_link);
- lstcon_group_put(test->tes_src_grp);
- lstcon_group_put(test->tes_dst_grp);
+ lstcon_group_decref(test->tes_src_grp);
+ lstcon_group_decref(test->tes_dst_grp);
LIBCFS_FREE(test, offsetof(lstcon_test_t,
tes_param[test->tes_paramlen]));
@@ -1352,10 +1344,10 @@ out:
LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen]));
if (dst_grp != NULL)
- lstcon_group_put(dst_grp);
+ lstcon_group_decref(dst_grp);
if (src_grp != NULL)
- lstcon_group_put(src_grp);
+ lstcon_group_decref(src_grp);
return rc;
}
@@ -1518,7 +1510,7 @@ lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up)
rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -1556,13 +1548,13 @@ lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
}
if (rc != 0) {
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
}
rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
- lstcon_group_put(tmp);
+ lstcon_group_decref(tmp);
return rc;
}
@@ -1629,7 +1621,7 @@ lstcon_group_debug(int timeout, char *name,
rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
timeout, result_up);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -1666,14 +1658,14 @@ lstcon_nodes_debug(int timeout,
}
if (rc != 0) {
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
timeout, result_up);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
return rc;
}
@@ -1739,7 +1731,8 @@ lstcon_session_new(char *name, int key, unsigned feats,
console_session.ses_feats_updated = 0;
console_session.ses_timeout = (timeout <= 0) ?
LST_CONSOLE_TIMEOUT : timeout;
- strcpy(console_session.ses_name, name);
+ strlcpy(console_session.ses_name, name,
+ sizeof(console_session.ses_name));
rc = lstcon_batch_add(LST_DEFAULT_BATCH);
if (rc != 0)
@@ -1847,7 +1840,7 @@ lstcon_session_end(void)
lstcon_group_t, grp_link);
LASSERT(grp->grp_ref == 1);
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
}
/* all nodes should be released */
@@ -1891,7 +1884,7 @@ lstcon_session_feats_check(unsigned feats)
}
static int
-lstcon_acceptor_handle(srpc_server_rpc_t *rpc)
+lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
{
srpc_msg_t *rep = &rpc->srpc_replymsg;
srpc_msg_t *req = &rpc->srpc_reqstbuf->buf_msg;
@@ -1959,14 +1952,15 @@ lstcon_acceptor_handle(srpc_server_rpc_t *rpc)
if (grp->grp_userland == 0)
grp->grp_userland = 1;
- strcpy(jrep->join_session, console_session.ses_name);
+ strlcpy(jrep->join_session, console_session.ses_name,
+ sizeof(jrep->join_session));
jrep->join_timeout = console_session.ses_timeout;
jrep->join_status = 0;
out:
rep->msg_ses_feats = console_session.ses_features;
if (grp != NULL)
- lstcon_group_put(grp);
+ lstcon_group_decref(grp);
mutex_unlock(&console_session.ses_mutex);
diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c
index f18e50036809..1a2da7430190 100644
--- a/drivers/staging/lustre/lnet/selftest/framework.c
+++ b/drivers/staging/lustre/lnet/selftest/framework.c
@@ -111,7 +111,7 @@ static struct smoketest_framework {
spinlock_t fw_lock; /* serialise */
sfw_session_t *fw_session; /* _the_ session */
int fw_shuttingdown; /* shutdown in progress */
- srpc_server_rpc_t *fw_active_srpc; /* running RPC */
+ struct srpc_server_rpc *fw_active_srpc;/* running RPC */
} sfw_data;
/* forward ref's */
@@ -722,7 +722,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg)
}
static int
-sfw_add_test_instance(sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
+sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc)
{
srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg;
srpc_test_reqst_t *req = &msg->msg_body.tes_reqst;
@@ -1091,7 +1091,7 @@ sfw_query_batch(sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply)
}
void
-sfw_free_pages(srpc_server_rpc_t *rpc)
+sfw_free_pages(struct srpc_server_rpc *rpc)
{
srpc_free_bulk(rpc->srpc_bulk);
rpc->srpc_bulk = NULL;
@@ -1112,7 +1112,7 @@ sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len,
}
static int
-sfw_add_test(srpc_server_rpc_t *rpc)
+sfw_add_test(struct srpc_server_rpc *rpc)
{
sfw_session_t *sn = sfw_data.fw_session;
srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply;
diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c
index 162f9d330496..86de68033f85 100644
--- a/drivers/staging/lustre/lnet/selftest/rpc.c
+++ b/drivers/staging/lustre/lnet/selftest/rpc.c
@@ -146,7 +146,7 @@ srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink)
int nob;
pg = alloc_pages_node(cfs_cpt_spread_node(lnet_cpt_table(), cpt),
- GFP_IOFS, 0);
+ GFP_KERNEL, 0);
if (pg == NULL) {
CERROR("Can't allocate page %d of %d\n", i, bulk_npg);
srpc_free_bulk(bk);
@@ -445,15 +445,6 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len,
}
static int
-srpc_post_active_rqtbuf(lnet_process_id_t peer, int service, void *buf,
- int len, lnet_handle_md_t *mdh, srpc_event_t *ev)
-{
- return srpc_post_active_rdma(srpc_serv_portal(service), service,
- buf, len, LNET_MD_OP_PUT, peer,
- LNET_NID_ANY, mdh, ev);
-}
-
-static int
srpc_post_passive_rqtbuf(int service, int local, void *buf, int len,
lnet_handle_md_t *mdh, srpc_event_t *ev)
{
@@ -798,9 +789,11 @@ srpc_send_request(srpc_client_rpc_t *rpc)
ev->ev_data = rpc;
ev->ev_type = SRPC_REQUEST_SENT;
- rc = srpc_post_active_rqtbuf(rpc->crpc_dest, rpc->crpc_service,
- &rpc->crpc_reqstmsg, sizeof(srpc_msg_t),
- &rpc->crpc_reqstmdh, ev);
+ rc = srpc_post_active_rdma(srpc_serv_portal(rpc->crpc_service),
+ rpc->crpc_service, &rpc->crpc_reqstmsg,
+ sizeof(srpc_msg_t), LNET_MD_OP_PUT,
+ rpc->crpc_dest, LNET_NID_ANY,
+ &rpc->crpc_reqstmdh, ev);
if (rc != 0) {
LASSERT(rc == -ENOMEM);
ev->ev_fired = 1; /* no more event expected */
@@ -866,7 +859,7 @@ srpc_prepare_bulk(srpc_client_rpc_t *rpc)
}
static int
-srpc_do_bulk(srpc_server_rpc_t *rpc)
+srpc_do_bulk(struct srpc_server_rpc *rpc)
{
srpc_event_t *ev = &rpc->srpc_ev;
srpc_bulk_t *bk = rpc->srpc_bulk;
@@ -894,7 +887,7 @@ srpc_do_bulk(srpc_server_rpc_t *rpc)
/* only called from srpc_handle_rpc */
static void
-srpc_server_rpc_done(srpc_server_rpc_t *rpc, int status)
+srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status)
{
struct srpc_service_cd *scd = rpc->srpc_scd;
struct srpc_service *sv = scd->scd_svc;
@@ -1404,7 +1397,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
struct srpc_service_cd *scd;
srpc_event_t *rpcev = ev->md.user_ptr;
srpc_client_rpc_t *crpc;
- srpc_server_rpc_t *srpc;
+ struct srpc_server_rpc *srpc;
srpc_buffer_t *buffer;
srpc_service_t *sv;
srpc_msg_t *msg;
diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h
index 8a77d3fdfa54..870498339538 100644
--- a/drivers/staging/lustre/lnet/selftest/selftest.h
+++ b/drivers/staging/lustre/lnet/selftest/selftest.h
@@ -182,7 +182,7 @@ typedef struct swi_workitem {
} swi_workitem_t;
/* server-side state of a RPC */
-typedef struct srpc_server_rpc {
+struct srpc_server_rpc {
/* chain on srpc_service::*_rpcq */
struct list_head srpc_list;
struct srpc_service_cd *srpc_scd;
@@ -198,7 +198,7 @@ typedef struct srpc_server_rpc {
unsigned int srpc_aborted; /* being given up */
int srpc_status;
void (*srpc_done)(struct srpc_server_rpc *);
-} srpc_server_rpc_t;
+};
/* client-side state of a RPC */
typedef struct srpc_client_rpc {
@@ -318,8 +318,8 @@ typedef struct srpc_service {
* - sv_handler: process incoming RPC request
* - sv_bulk_ready: notify bulk data
*/
- int (*sv_handler) (srpc_server_rpc_t *);
- int (*sv_bulk_ready) (srpc_server_rpc_t *, int);
+ int (*sv_handler)(struct srpc_server_rpc *);
+ int (*sv_bulk_ready)(struct srpc_server_rpc *, int);
} srpc_service_t;
typedef struct {
@@ -423,9 +423,9 @@ void sfw_abort_rpc(srpc_client_rpc_t *rpc);
void sfw_post_rpc(srpc_client_rpc_t *rpc);
void sfw_client_rpc_done(srpc_client_rpc_t *rpc);
void sfw_unpack_message(srpc_msg_t *msg);
-void sfw_free_pages(srpc_server_rpc_t *rpc);
+void sfw_free_pages(struct srpc_server_rpc *rpc);
void sfw_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i);
-int sfw_alloc_pages(srpc_server_rpc_t *rpc, int cpt, int npages, int len,
+int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len,
int sink);
int sfw_make_session (srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply);
@@ -440,7 +440,7 @@ void srpc_free_bulk(srpc_bulk_t *bk);
srpc_bulk_t *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len,
int sink);
int srpc_send_rpc(swi_workitem_t *wi);
-int srpc_send_reply(srpc_server_rpc_t *rpc);
+int srpc_send_reply(struct srpc_server_rpc *rpc);
int srpc_add_service(srpc_service_t *sv);
int srpc_remove_service(srpc_service_t *sv);
void srpc_shutdown_service(srpc_service_t *sv);
@@ -585,7 +585,7 @@ swi_state2str (int state)
do { \
int __I = 2; \
while (!(cond)) { \
- CDEBUG(IS_PO2(++__I) ? D_WARNING : D_NET, \
+ CDEBUG(is_power_of_2(++__I) ? D_WARNING : D_NET, \
fmt, ## __VA_ARGS__); \
spin_unlock(&(lock)); \
\
diff --git a/drivers/staging/lustre/lustre/fid/fid_internal.h b/drivers/staging/lustre/lustre/fid/fid_internal.h
index 84daee1154dc..b79a813977cf 100644
--- a/drivers/staging/lustre/lustre/fid/fid_internal.h
+++ b/drivers/staging/lustre/lustre/fid/fid_internal.h
@@ -44,8 +44,6 @@
#include "../../include/linux/libcfs/libcfs.h"
/* Functions used internally in module. */
-int seq_client_alloc_super(struct lu_client_seq *seq,
- const struct lu_env *env);
extern struct lprocfs_vars seq_client_debugfs_list[];
diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c
index 7c45e7479087..fe7c39afd1d9 100644
--- a/drivers/staging/lustre/lustre/fid/fid_request.c
+++ b/drivers/staging/lustre/lustre/fid/fid_request.c
@@ -142,27 +142,6 @@ out_req:
return rc;
}
-/* Request sequence-controller node to allocate new super-sequence. */
-int seq_client_alloc_super(struct lu_client_seq *seq,
- const struct lu_env *env)
-{
- int rc;
-
- mutex_lock(&seq->lcs_mutex);
-
- /* Check whether the connection to seq controller has been
- * setup (lcs_exp != NULL) */
- if (!seq->lcs_exp) {
- mutex_unlock(&seq->lcs_mutex);
- return -EINPROGRESS;
- }
-
- rc = seq_client_rpc(seq, &seq->lcs_space,
- SEQ_ALLOC_SUPER, "super");
- mutex_unlock(&seq->lcs_mutex);
- return rc;
-}
-
/* Request sequence-controller node to allocate new meta-sequence. */
static int seq_client_alloc_meta(const struct lu_env *env,
struct lu_client_seq *seq)
@@ -483,7 +462,7 @@ static void __exit fid_mod_exit(void)
ldebugfs_remove(&seq_debugfs_dir);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre FID Module");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1.0");
diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c
index 446917484637..baa04074a61f 100644
--- a/drivers/staging/lustre/lustre/fld/fld_cache.c
+++ b/drivers/staging/lustre/lustre/fld/fld_cache.c
@@ -121,8 +121,8 @@ void fld_cache_fini(struct fld_cache *cache)
/**
* delete given node from list.
*/
-void fld_cache_entry_delete(struct fld_cache *cache,
- struct fld_cache_entry *node)
+static void fld_cache_entry_delete(struct fld_cache *cache,
+ struct fld_cache_entry *node)
{
list_del(&node->fce_list);
list_del(&node->fce_lru);
@@ -377,8 +377,8 @@ struct fld_cache_entry
* This function handles all cases of merging and breaking up of
* ranges.
*/
-int fld_cache_insert_nolock(struct fld_cache *cache,
- struct fld_cache_entry *f_new)
+static int fld_cache_insert_nolock(struct fld_cache *cache,
+ struct fld_cache_entry *f_new)
{
struct fld_cache_entry *f_curr;
struct fld_cache_entry *n;
@@ -444,36 +444,10 @@ int fld_cache_insert(struct fld_cache *cache,
return rc;
}
-void fld_cache_delete_nolock(struct fld_cache *cache,
- const struct lu_seq_range *range)
-{
- struct fld_cache_entry *flde;
- struct fld_cache_entry *tmp;
- struct list_head *head;
-
- head = &cache->fci_entries_head;
- list_for_each_entry_safe(flde, tmp, head, fce_list) {
- /* add list if next is end of list */
- if (range->lsr_start == flde->fce_range.lsr_start ||
- (range->lsr_end == flde->fce_range.lsr_end &&
- range->lsr_flags == flde->fce_range.lsr_flags)) {
- fld_cache_entry_delete(cache, flde);
- break;
- }
- }
-}
-
/**
* Delete FLD entry in FLD cache.
*
*/
-void fld_cache_delete(struct fld_cache *cache,
- const struct lu_seq_range *range)
-{
- write_lock(&cache->fci_lock);
- fld_cache_delete_nolock(cache, range);
- write_unlock(&cache->fci_lock);
-}
struct fld_cache_entry
*fld_cache_entry_lookup_nolock(struct fld_cache *cache,
diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h
index fbb232de6c74..959b8e6bba95 100644
--- a/drivers/staging/lustre/lustre/fld/fld_internal.h
+++ b/drivers/staging/lustre/lustre/fld/fld_internal.h
@@ -156,20 +156,11 @@ int fld_cache_insert(struct fld_cache *cache,
struct fld_cache_entry
*fld_cache_entry_create(const struct lu_seq_range *range);
-int fld_cache_insert_nolock(struct fld_cache *cache,
- struct fld_cache_entry *f_new);
-void fld_cache_delete(struct fld_cache *cache,
- const struct lu_seq_range *range);
-void fld_cache_delete_nolock(struct fld_cache *cache,
- const struct lu_seq_range *range);
int fld_cache_lookup(struct fld_cache *cache,
const u64 seq, struct lu_seq_range *range);
struct fld_cache_entry*
fld_cache_entry_lookup(struct fld_cache *cache, struct lu_seq_range *range);
-void fld_cache_entry_delete(struct fld_cache *cache,
- struct fld_cache_entry *node);
-void fld_dump_cache_entries(struct fld_cache *cache);
struct fld_cache_entry
*fld_cache_entry_lookup_nolock(struct fld_cache *cache,
diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c
index 3fd91bc77da5..469df685f392 100644
--- a/drivers/staging/lustre/lustre/fld/fld_request.c
+++ b/drivers/staging/lustre/lustre/fld/fld_request.c
@@ -501,7 +501,7 @@ static void __exit fld_mod_exit(void)
ldebugfs_remove(&fld_debugfs_dir);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre FLD");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h
index 6e4112986664..f18c0c75ef1e 100644
--- a/drivers/staging/lustre/lustre/include/lprocfs_status.h
+++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h
@@ -594,8 +594,6 @@ int lprocfs_rd_connect_flags(struct seq_file *m, void *data);
struct adaptive_timeout;
int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at);
int lprocfs_rd_timeouts(struct seq_file *m, void *data);
-int lprocfs_wr_timeouts(struct file *file, const char __user *buffer,
- unsigned long count, void *data);
int lprocfs_wr_ping(struct file *file, const char __user *buffer,
size_t count, loff_t *off);
int lprocfs_wr_import(struct file *file, const char __user *buffer,
@@ -626,19 +624,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
int lprocfs_single_release(struct inode *, struct file *);
int lprocfs_seq_release(struct inode *, struct file *);
-/* You must use these macros when you want to refer to
- * the import in a client obd_device for a lprocfs entry */
-#define LPROCFS_CLIMP_CHECK(obd) do { \
- typecheck(struct obd_device *, obd); \
- down_read(&(obd)->u.cli.cl_sem); \
- if ((obd)->u.cli.cl_import == NULL) { \
- up_read(&(obd)->u.cli.cl_sem); \
- return -ENODEV; \
- } \
-} while (0)
-#define LPROCFS_CLIMP_EXIT(obd) \
- up_read(&(obd)->u.cli.cl_sem)
-
/* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only
proc entries; otherwise, you will define name##_seq_write function also for
a read-write proc entry, and then call LPROC_SEQ_SEQ instead. Finally,
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_lfsck_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_lfsck_user.h
deleted file mode 100644
index 1c87a61a7fc1..000000000000
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_lfsck_user.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
-
- * This program is distributed in the hope that it will be 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 for more details. A copy is
- * included in the COPYING file that accompanied this code.
-
- * 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
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * lustre/include/lustre/lustre_lfsck_user.h
- *
- * Lustre LFSCK userspace interfaces.
- *
- * Author: Fan Yong <yong.fan@whamcloud.com>
- */
-
-#ifndef _LUSTRE_LFSCK_USER_H
-# define _LUSTRE_LFSCK_USER_H
-
-enum lfsck_param_flags {
- /* Reset LFSCK iterator position to the device beginning. */
- LPF_RESET = 0x0001,
-
- /* Exit when fail. */
- LPF_FAILOUT = 0x0002,
-
- /* Dryrun mode, only check without modification */
- LPF_DRYRUN = 0x0004,
-};
-
-enum lfsck_type {
- /* For MDT-OST consistency check/repair. */
- LT_LAYOUT = 0x0001,
-
- /* For MDT-MDT consistency check/repair. */
- LT_DNE = 0x0002,
-
- /* For FID-in-dirent and linkEA consistency check/repair. */
- LT_NAMESPACE = 0x0004,
-};
-
-#define LFSCK_VERSION_V1 1
-#define LFSCK_VERSION_V2 2
-
-#define LFSCK_TYPES_ALL ((__u16)(~0))
-#define LFSCK_TYPES_DEF ((__u16)0)
-#define LFSCK_TYPES_SUPPORTED LT_NAMESPACE
-
-#define LFSCK_SPEED_NO_LIMIT 0
-#define LFSCK_SPEED_LIMIT_DEF LFSCK_SPEED_NO_LIMIT
-
-enum lfsck_start_valid {
- LSV_SPEED_LIMIT = 0x00000001,
- LSV_ERROR_HANDLE = 0x00000002,
- LSV_DRYRUN = 0x00000004,
-};
-
-/* Arguments for starting lfsck. */
-struct lfsck_start {
- /* Which arguments are valid, see 'enum lfsck_start_valid'. */
- __u32 ls_valid;
-
- /* How many items can be scanned at most per second. */
- __u32 ls_speed_limit;
-
- /* For compatibility between user space tools and kernel service. */
- __u16 ls_version;
-
- /* Which LFSCK components to be (have been) started. */
- __u16 ls_active;
-
- /* Flags for the LFSCK, see 'enum lfsck_param_flags'. */
- __u16 ls_flags;
-
- /* For 64-bits aligned. */
- __u16 ls_padding;
-};
-
-#endif /* _LUSTRE_LFSCK_USER_H */
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
index 286e96af608b..80f8ec529424 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
@@ -312,7 +312,7 @@ struct lov_user_ost_data_v1 { /* per-stripe data structure */
struct ost_id l_ost_oi; /* OST object ID */
__u32 l_ost_gen; /* generation of this OST index */
__u32 l_ost_idx; /* OST index in LOV */
-} __attribute__((packed));
+} __packed;
#define lov_user_md lov_user_md_v1
struct lov_user_md_v1 { /* LOV EA user data (host-endian) */
@@ -344,7 +344,7 @@ struct lov_user_md_v3 { /* LOV EA user data (host-endian) */
};
char lmm_pool_name[LOV_MAXPOOLNAME]; /* pool name */
struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */
-} __attribute__((packed));
+} __packed;
static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic)
{
@@ -364,12 +364,12 @@ static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic)
struct lov_user_mds_data_v1 {
lstat_t lmd_st; /* MDS stat struct */
struct lov_user_md_v1 lmd_lmm; /* LOV EA V1 user data */
-} __attribute__((packed));
+} __packed;
struct lov_user_mds_data_v3 {
lstat_t lmd_st; /* MDS stat struct */
struct lov_user_md_v3 lmd_lmm; /* LOV EA V3 user data */
-} __attribute__((packed));
+} __packed;
#endif
/* keep this to be the same size as lov_user_ost_data_v1 */
@@ -766,7 +766,7 @@ struct changelog_rec {
};
lustre_fid cr_pfid; /**< parent fid */
char cr_name[0]; /**< last element */
-} __attribute__((packed));
+} __packed;
/* changelog_ext_rec is 2*sizeof(lu_fid) bigger than changelog_rec, to save
* space, only rename uses changelog_ext_rec, while others use changelog_rec to
@@ -788,7 +788,7 @@ struct changelog_ext_rec {
lustre_fid cr_sfid; /**< source fid, or zero */
lustre_fid cr_spfid; /**< source parent fid, or zero */
char cr_name[0]; /**< last element */
-} __attribute__((packed));
+} __packed;
#define CHANGELOG_REC_EXTENDED(rec) \
(((rec)->cr_flags & CLF_VERMASK) == CLF_EXT_VERSION)
@@ -894,7 +894,7 @@ static inline char *hsm_progress_state2name(enum hsm_progress_states s)
struct hsm_extent {
__u64 offset;
__u64 length;
-} __attribute__((packed));
+} __packed;
/**
* Current HSM states of a Lustre file.
@@ -978,7 +978,7 @@ struct hsm_request {
struct hsm_user_item {
lustre_fid hui_fid;
struct hsm_extent hui_extent;
-} __attribute__((packed));
+} __packed;
struct hsm_user_request {
struct hsm_request hur_request;
@@ -986,7 +986,7 @@ struct hsm_user_request {
/* extra data blob at end of struct (after all
* hur_user_items), only use helpers to access it
*/
-} __attribute__((packed));
+} __packed;
/** Return pointer to data field in a hsm user request */
static inline void *hur_data(struct hsm_user_request *hur)
@@ -1052,7 +1052,7 @@ struct hsm_action_item {
__u64 hai_cookie; /* action cookie from coordinator */
__u64 hai_gid; /* grouplock id */
char hai_data[0]; /* variable length */
-} __attribute__((packed));
+} __packed;
/*
* helper function which print in hexa the first bytes of
@@ -1096,7 +1096,7 @@ struct hsm_action_list {
char hal_fsname[0]; /* null-terminated */
/* struct hsm_action_item[hal_count] follows, aligned on 8-byte
boundaries. See hai_zero */
-} __attribute__((packed));
+} __packed;
#ifndef HAVE_CFS_SIZE_ROUND
static inline int cfs_size_round (int val)
diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h
index 5e1ac129a681..7c6933ffc9c1 100644
--- a/drivers/staging/lustre/lustre/include/lustre_disk.h
+++ b/drivers/staging/lustre/lustre/include/lustre_disk.h
@@ -68,6 +68,7 @@
everything as string options */
#define LMD_MAGIC 0xbdacbd03
+#define LMD_PARAMS_MAXLEN 4096
/* gleaned from the mount command - no persistent info here */
struct lustre_mount_data {
diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h
index 0e75a15fe0d4..138479a9edc1 100644
--- a/drivers/staging/lustre/lustre/include/lustre_dlm.h
+++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h
@@ -872,8 +872,6 @@ struct ldlm_resource {
*/
struct mutex lr_lvb_mutex;
int lr_lvb_len;
- /** protected by lr_lock */
- void *lr_lvb_data;
/** When the resource was considered as contended. */
unsigned long lr_contention_time;
diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h
index 5d3b2df02321..1de0c4d6f7f7 100644
--- a/drivers/staging/lustre/lustre/include/lustre_log.h
+++ b/drivers/staging/lustre/lustre/include/lustre_log.h
@@ -80,37 +80,6 @@ struct cat_handle_data {
struct llog_handle *chd_next_log; /* llog to be used next */
};
-static inline void logid_to_fid(struct llog_logid *id, struct lu_fid *fid)
-{
- /* For compatibility purposes we identify pre-OSD (~< 2.3.51 MDS)
- * logid's by non-zero ogen (inode generation) and convert them
- * into IGIF */
- if (id->lgl_ogen == 0) {
- fid->f_seq = id->lgl_oi.oi.oi_seq;
- fid->f_oid = id->lgl_oi.oi.oi_id;
- fid->f_ver = 0;
- } else {
- lu_igif_build(fid, id->lgl_oi.oi.oi_id, id->lgl_ogen);
- }
-}
-
-static inline void fid_to_logid(struct lu_fid *fid, struct llog_logid *id)
-{
- id->lgl_oi.oi.oi_seq = fid->f_seq;
- id->lgl_oi.oi.oi_id = fid->f_oid;
- id->lgl_ogen = 0;
-}
-
-static inline void logid_set_id(struct llog_logid *log_id, __u64 id)
-{
- log_id->lgl_oi.oi.oi_id = id;
-}
-
-static inline __u64 logid_id(struct llog_logid *log_id)
-{
- return log_id->lgl_oi.oi.oi_id;
-}
-
struct llog_handle;
/* llog.c - general API */
@@ -286,19 +255,6 @@ struct llog_ctxt {
#define LLOG_PROC_BREAK 0x0001
#define LLOG_DEL_RECORD 0x0002
-static inline int llog_obd2ops(struct llog_ctxt *ctxt,
- struct llog_operations **lop)
-{
- if (ctxt == NULL)
- return -ENOTCONN;
-
- *lop = ctxt->loc_logops;
- if (*lop == NULL)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
static inline int llog_handle2ops(struct llog_handle *loghandle,
struct llog_operations **lop)
{
@@ -309,18 +265,6 @@ static inline int llog_handle2ops(struct llog_handle *loghandle,
return 0;
}
-static inline int llog_data_len(int len)
-{
- return cfs_size_round(len);
-}
-
-static inline int llog_get_size(struct llog_handle *loghandle)
-{
- if (loghandle && loghandle->lgh_hdr)
- return loghandle->lgh_hdr->llh_count;
- return 0;
-}
-
static inline struct llog_ctxt *llog_ctxt_get(struct llog_ctxt *ctxt)
{
atomic_inc(&ctxt->loc_refcount);
@@ -421,40 +365,6 @@ static inline int llog_next_block(const struct lu_env *env,
return rc;
}
-static inline int llog_prev_block(const struct lu_env *env,
- struct llog_handle *loghandle,
- int prev_idx, void *buf, int len)
-{
- struct llog_operations *lop;
- int rc;
-
- rc = llog_handle2ops(loghandle, &lop);
- if (rc)
- return rc;
- if (lop->lop_prev_block == NULL)
- return -EOPNOTSUPP;
-
- rc = lop->lop_prev_block(env, loghandle, prev_idx, buf, len);
- return rc;
-}
-
-static inline int llog_connect(struct llog_ctxt *ctxt,
- struct llog_logid *logid, struct llog_gen *gen,
- struct obd_uuid *uuid)
-{
- struct llog_operations *lop;
- int rc;
-
- rc = llog_obd2ops(ctxt, &lop);
- if (rc)
- return rc;
- if (lop->lop_connect == NULL)
- return -EOPNOTSUPP;
-
- rc = lop->lop_connect(ctxt, logid, gen, uuid);
- return rc;
-}
-
/* llog.c */
int llog_declare_write_rec(const struct lu_env *env,
struct llog_handle *handle,
diff --git a/drivers/staging/lustre/lustre/include/lustre_sec.h b/drivers/staging/lustre/lustre/include/lustre_sec.h
index aaadf098989f..dd1033be6bfa 100644
--- a/drivers/staging/lustre/lustre/include/lustre_sec.h
+++ b/drivers/staging/lustre/lustre/include/lustre_sec.h
@@ -322,7 +322,7 @@ struct sptlrpc_rule_set {
};
int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr);
-int sptlrpc_flavor_has_bulk(struct sptlrpc_flavor *flvr);
+bool sptlrpc_flavor_has_bulk(struct sptlrpc_flavor *flvr);
static inline void sptlrpc_rule_set_init(struct sptlrpc_rule_set *set)
{
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index 5e93afca3435..5c90b59cf0db 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -963,123 +963,123 @@ struct md_enqueue_info {
};
struct obd_ops {
- struct module *o_owner;
- int (*o_iocontrol)(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg);
- int (*o_get_info)(const struct lu_env *env, struct obd_export *,
- __u32 keylen, void *key, __u32 *vallen, void *val,
- struct lov_stripe_md *lsm);
- int (*o_set_info_async)(const struct lu_env *, struct obd_export *,
- __u32 keylen, void *key,
- __u32 vallen, void *val,
- struct ptlrpc_request_set *set);
- int (*o_attach)(struct obd_device *dev, u32 len, void *data);
- int (*o_detach)(struct obd_device *dev);
- int (*o_setup)(struct obd_device *dev, struct lustre_cfg *cfg);
- int (*o_precleanup)(struct obd_device *dev,
- enum obd_cleanup_stage cleanup_stage);
- int (*o_cleanup)(struct obd_device *dev);
- int (*o_process_config)(struct obd_device *dev, u32 len, void *data);
- int (*o_postrecov)(struct obd_device *dev);
- int (*o_add_conn)(struct obd_import *imp, struct obd_uuid *uuid,
- int priority);
- int (*o_del_conn)(struct obd_import *imp, struct obd_uuid *uuid);
+ struct module *owner;
+ int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len,
+ void *karg, void *uarg);
+ int (*get_info)(const struct lu_env *env, struct obd_export *,
+ __u32 keylen, void *key, __u32 *vallen, void *val,
+ struct lov_stripe_md *lsm);
+ int (*set_info_async)(const struct lu_env *, struct obd_export *,
+ __u32 keylen, void *key,
+ __u32 vallen, void *val,
+ struct ptlrpc_request_set *set);
+ int (*attach)(struct obd_device *dev, u32 len, void *data);
+ int (*detach)(struct obd_device *dev);
+ int (*setup)(struct obd_device *dev, struct lustre_cfg *cfg);
+ int (*precleanup)(struct obd_device *dev,
+ enum obd_cleanup_stage cleanup_stage);
+ int (*cleanup)(struct obd_device *dev);
+ int (*process_config)(struct obd_device *dev, u32 len, void *data);
+ int (*postrecov)(struct obd_device *dev);
+ int (*add_conn)(struct obd_import *imp, struct obd_uuid *uuid,
+ int priority);
+ int (*del_conn)(struct obd_import *imp, struct obd_uuid *uuid);
/* connect to the target device with given connection
* data. @ocd->ocd_connect_flags is modified to reflect flags actually
* granted by the target, which are guaranteed to be a subset of flags
* asked for. If @ocd == NULL, use default parameters. */
- int (*o_connect)(const struct lu_env *env,
- struct obd_export **exp, struct obd_device *src,
- struct obd_uuid *cluuid, struct obd_connect_data *ocd,
+ int (*connect)(const struct lu_env *env,
+ struct obd_export **exp, struct obd_device *src,
+ struct obd_uuid *cluuid, struct obd_connect_data *ocd,
+ void *localdata);
+ int (*reconnect)(const struct lu_env *env,
+ struct obd_export *exp, struct obd_device *src,
+ struct obd_uuid *cluuid,
+ struct obd_connect_data *ocd,
void *localdata);
- int (*o_reconnect)(const struct lu_env *env,
- struct obd_export *exp, struct obd_device *src,
- struct obd_uuid *cluuid,
- struct obd_connect_data *ocd,
- void *localdata);
- int (*o_disconnect)(struct obd_export *exp);
+ int (*disconnect)(struct obd_export *exp);
/* Initialize/finalize fids infrastructure. */
- int (*o_fid_init)(struct obd_device *obd,
- struct obd_export *exp, enum lu_cli_type type);
- int (*o_fid_fini)(struct obd_device *obd);
+ int (*fid_init)(struct obd_device *obd,
+ struct obd_export *exp, enum lu_cli_type type);
+ int (*fid_fini)(struct obd_device *obd);
/* Allocate new fid according to passed @hint. */
- int (*o_fid_alloc)(struct obd_export *exp, struct lu_fid *fid,
- struct md_op_data *op_data);
+ int (*fid_alloc)(struct obd_export *exp, struct lu_fid *fid,
+ struct md_op_data *op_data);
/*
* Object with @fid is getting deleted, we may want to do something
* about this.
*/
- int (*o_statfs)(const struct lu_env *, struct obd_export *exp,
- struct obd_statfs *osfs, __u64 max_age, __u32 flags);
- int (*o_statfs_async)(struct obd_export *exp, struct obd_info *oinfo,
- __u64 max_age, struct ptlrpc_request_set *set);
- int (*o_packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt,
- struct lov_stripe_md *mem_src);
- int (*o_unpackmd)(struct obd_export *exp,
- struct lov_stripe_md **mem_tgt,
- struct lov_mds_md *disk_src, int disk_len);
- int (*o_preallocate)(struct lustre_handle *, u32 *req, u64 *ids);
- int (*o_create)(const struct lu_env *env, struct obd_export *exp,
- struct obdo *oa, struct lov_stripe_md **ea,
- struct obd_trans_info *oti);
- int (*o_destroy)(const struct lu_env *env, struct obd_export *exp,
- struct obdo *oa, struct lov_stripe_md *ea,
- struct obd_trans_info *oti, struct obd_export *md_exp);
- int (*o_setattr)(const struct lu_env *, struct obd_export *exp,
- struct obd_info *oinfo, struct obd_trans_info *oti);
- int (*o_setattr_async)(struct obd_export *exp, struct obd_info *oinfo,
- struct obd_trans_info *oti,
- struct ptlrpc_request_set *rqset);
- int (*o_getattr)(const struct lu_env *env, struct obd_export *exp,
- struct obd_info *oinfo);
- int (*o_getattr_async)(struct obd_export *exp, struct obd_info *oinfo,
- struct ptlrpc_request_set *set);
- int (*o_adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm,
- u64 size, int shrink);
- int (*o_preprw)(const struct lu_env *env, int cmd,
- struct obd_export *exp, struct obdo *oa, int objcount,
- struct obd_ioobj *obj, struct niobuf_remote *remote,
- int *nr_pages, struct niobuf_local *local,
- struct obd_trans_info *oti);
- int (*o_commitrw)(const struct lu_env *env, int cmd,
- struct obd_export *exp, struct obdo *oa,
- int objcount, struct obd_ioobj *obj,
- struct niobuf_remote *remote, int pages,
- struct niobuf_local *local,
- struct obd_trans_info *oti, int rc);
- int (*o_find_cbdata)(struct obd_export *, struct lov_stripe_md *,
- ldlm_iterator_t it, void *data);
- int (*o_init_export)(struct obd_export *exp);
- int (*o_destroy_export)(struct obd_export *exp);
+ int (*statfs)(const struct lu_env *, struct obd_export *exp,
+ struct obd_statfs *osfs, __u64 max_age, __u32 flags);
+ int (*statfs_async)(struct obd_export *exp, struct obd_info *oinfo,
+ __u64 max_age, struct ptlrpc_request_set *set);
+ int (*packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt,
+ struct lov_stripe_md *mem_src);
+ int (*unpackmd)(struct obd_export *exp,
+ struct lov_stripe_md **mem_tgt,
+ struct lov_mds_md *disk_src, int disk_len);
+ int (*preallocate)(struct lustre_handle *, u32 *req, u64 *ids);
+ int (*create)(const struct lu_env *env, struct obd_export *exp,
+ struct obdo *oa, struct lov_stripe_md **ea,
+ struct obd_trans_info *oti);
+ int (*destroy)(const struct lu_env *env, struct obd_export *exp,
+ struct obdo *oa, struct lov_stripe_md *ea,
+ struct obd_trans_info *oti, struct obd_export *md_exp);
+ int (*setattr)(const struct lu_env *, struct obd_export *exp,
+ struct obd_info *oinfo, struct obd_trans_info *oti);
+ int (*setattr_async)(struct obd_export *exp, struct obd_info *oinfo,
+ struct obd_trans_info *oti,
+ struct ptlrpc_request_set *rqset);
+ int (*getattr)(const struct lu_env *env, struct obd_export *exp,
+ struct obd_info *oinfo);
+ int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo,
+ struct ptlrpc_request_set *set);
+ int (*adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm,
+ u64 size, int shrink);
+ int (*preprw)(const struct lu_env *env, int cmd,
+ struct obd_export *exp, struct obdo *oa, int objcount,
+ struct obd_ioobj *obj, struct niobuf_remote *remote,
+ int *nr_pages, struct niobuf_local *local,
+ struct obd_trans_info *oti);
+ int (*commitrw)(const struct lu_env *env, int cmd,
+ struct obd_export *exp, struct obdo *oa,
+ int objcount, struct obd_ioobj *obj,
+ struct niobuf_remote *remote, int pages,
+ struct niobuf_local *local,
+ struct obd_trans_info *oti, int rc);
+ int (*find_cbdata)(struct obd_export *, struct lov_stripe_md *,
+ ldlm_iterator_t it, void *data);
+ int (*init_export)(struct obd_export *exp);
+ int (*destroy_export)(struct obd_export *exp);
/* metadata-only methods */
- int (*o_import_event)(struct obd_device *, struct obd_import *,
- enum obd_import_event);
+ int (*import_event)(struct obd_device *, struct obd_import *,
+ enum obd_import_event);
- int (*o_notify)(struct obd_device *obd, struct obd_device *watched,
- enum obd_notify_event ev, void *data);
+ int (*notify)(struct obd_device *obd, struct obd_device *watched,
+ enum obd_notify_event ev, void *data);
- int (*o_health_check)(const struct lu_env *env, struct obd_device *);
- struct obd_uuid *(*o_get_uuid)(struct obd_export *exp);
+ int (*health_check)(const struct lu_env *env, struct obd_device *);
+ struct obd_uuid *(*get_uuid)(struct obd_export *exp);
/* quota methods */
- int (*o_quotacheck)(struct obd_device *, struct obd_export *,
- struct obd_quotactl *);
- int (*o_quotactl)(struct obd_device *, struct obd_export *,
+ int (*quotacheck)(struct obd_device *, struct obd_export *,
struct obd_quotactl *);
+ int (*quotactl)(struct obd_device *, struct obd_export *,
+ struct obd_quotactl *);
/* pools methods */
- int (*o_pool_new)(struct obd_device *obd, char *poolname);
- int (*o_pool_del)(struct obd_device *obd, char *poolname);
- int (*o_pool_add)(struct obd_device *obd, char *poolname,
- char *ostname);
- int (*o_pool_rem)(struct obd_device *obd, char *poolname,
- char *ostname);
- void (*o_getref)(struct obd_device *obd);
- void (*o_putref)(struct obd_device *obd);
+ int (*pool_new)(struct obd_device *obd, char *poolname);
+ int (*pool_del)(struct obd_device *obd, char *poolname);
+ int (*pool_add)(struct obd_device *obd, char *poolname,
+ char *ostname);
+ int (*pool_rem)(struct obd_device *obd, char *poolname,
+ char *ostname);
+ void (*getref)(struct obd_device *obd);
+ void (*putref)(struct obd_device *obd);
/*
* NOTE: If adding ops, add another LPROCFS_OBD_OP_INIT() line
* to lprocfs_alloc_obd_stats() in obdclass/lprocfs_status.c.
@@ -1124,89 +1124,89 @@ struct md_open_data {
struct lookup_intent;
struct md_ops {
- int (*m_getstatus)(struct obd_export *, struct lu_fid *);
- int (*m_null_inode)(struct obd_export *, const struct lu_fid *);
- int (*m_find_cbdata)(struct obd_export *, const struct lu_fid *,
- ldlm_iterator_t, void *);
- int (*m_close)(struct obd_export *, struct md_op_data *,
- struct md_open_data *, struct ptlrpc_request **);
- int (*m_create)(struct obd_export *, struct md_op_data *,
- const void *, int, int, __u32, __u32, cfs_cap_t,
- __u64, struct ptlrpc_request **);
- int (*m_done_writing)(struct obd_export *, struct md_op_data *,
- struct md_open_data *);
- int (*m_enqueue)(struct obd_export *, struct ldlm_enqueue_info *,
- struct lookup_intent *, struct md_op_data *,
- struct lustre_handle *, void *, int,
- struct ptlrpc_request **, __u64);
- int (*m_getattr)(struct obd_export *, struct md_op_data *,
- struct ptlrpc_request **);
- int (*m_getattr_name)(struct obd_export *, struct md_op_data *,
- struct ptlrpc_request **);
- int (*m_intent_lock)(struct obd_export *, struct md_op_data *,
- void *, int, struct lookup_intent *, int,
- struct ptlrpc_request **,
- ldlm_blocking_callback, __u64);
- int (*m_link)(struct obd_export *, struct md_op_data *,
+ int (*getstatus)(struct obd_export *, struct lu_fid *);
+ int (*null_inode)(struct obd_export *, const struct lu_fid *);
+ int (*find_cbdata)(struct obd_export *, const struct lu_fid *,
+ ldlm_iterator_t, void *);
+ int (*close)(struct obd_export *, struct md_op_data *,
+ struct md_open_data *, struct ptlrpc_request **);
+ int (*create)(struct obd_export *, struct md_op_data *,
+ const void *, int, int, __u32, __u32, cfs_cap_t,
+ __u64, struct ptlrpc_request **);
+ int (*done_writing)(struct obd_export *, struct md_op_data *,
+ struct md_open_data *);
+ int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *,
+ struct lookup_intent *, struct md_op_data *,
+ struct lustre_handle *, void *, int,
+ struct ptlrpc_request **, __u64);
+ int (*getattr)(struct obd_export *, struct md_op_data *,
+ struct ptlrpc_request **);
+ int (*getattr_name)(struct obd_export *, struct md_op_data *,
+ struct ptlrpc_request **);
+ int (*intent_lock)(struct obd_export *, struct md_op_data *,
+ void *, int, struct lookup_intent *, int,
+ struct ptlrpc_request **,
+ ldlm_blocking_callback, __u64);
+ int (*link)(struct obd_export *, struct md_op_data *,
+ struct ptlrpc_request **);
+ int (*rename)(struct obd_export *, struct md_op_data *,
+ const char *, int, const char *, int,
struct ptlrpc_request **);
- int (*m_rename)(struct obd_export *, struct md_op_data *,
- const char *, int, const char *, int,
- struct ptlrpc_request **);
- int (*m_is_subdir)(struct obd_export *, const struct lu_fid *,
- const struct lu_fid *,
+ int (*is_subdir)(struct obd_export *, const struct lu_fid *,
+ const struct lu_fid *,
struct ptlrpc_request **);
- int (*m_setattr)(struct obd_export *, struct md_op_data *, void *,
- int, void *, int, struct ptlrpc_request **,
+ int (*setattr)(struct obd_export *, struct md_op_data *, void *,
+ int, void *, int, struct ptlrpc_request **,
struct md_open_data **mod);
- int (*m_sync)(struct obd_export *, const struct lu_fid *,
+ int (*sync)(struct obd_export *, const struct lu_fid *,
+ struct ptlrpc_request **);
+ int (*readpage)(struct obd_export *, struct md_op_data *,
+ struct page **, struct ptlrpc_request **);
+
+ int (*unlink)(struct obd_export *, struct md_op_data *,
struct ptlrpc_request **);
- int (*m_readpage)(struct obd_export *, struct md_op_data *,
- struct page **, struct ptlrpc_request **);
- int (*m_unlink)(struct obd_export *, struct md_op_data *,
+ int (*setxattr)(struct obd_export *, const struct lu_fid *,
+ u64, const char *, const char *, int, int, int, __u32,
struct ptlrpc_request **);
- int (*m_setxattr)(struct obd_export *, const struct lu_fid *,
- u64, const char *, const char *, int, int, int, __u32,
- struct ptlrpc_request **);
-
- int (*m_getxattr)(struct obd_export *, const struct lu_fid *,
- u64, const char *, const char *, int, int, int,
- struct ptlrpc_request **);
+ int (*getxattr)(struct obd_export *, const struct lu_fid *,
+ u64, const char *, const char *, int, int, int,
+ struct ptlrpc_request **);
- int (*m_init_ea_size)(struct obd_export *, int, int, int, int);
+ int (*init_ea_size)(struct obd_export *, int, int, int, int);
- int (*m_get_lustre_md)(struct obd_export *, struct ptlrpc_request *,
- struct obd_export *, struct obd_export *,
- struct lustre_md *);
+ int (*get_lustre_md)(struct obd_export *, struct ptlrpc_request *,
+ struct obd_export *, struct obd_export *,
+ struct lustre_md *);
- int (*m_free_lustre_md)(struct obd_export *, struct lustre_md *);
+ int (*free_lustre_md)(struct obd_export *, struct lustre_md *);
- int (*m_set_open_replay_data)(struct obd_export *,
- struct obd_client_handle *,
- struct lookup_intent *);
- int (*m_clear_open_replay_data)(struct obd_export *,
- struct obd_client_handle *);
- int (*m_set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *);
+ int (*set_open_replay_data)(struct obd_export *,
+ struct obd_client_handle *,
+ struct lookup_intent *);
+ int (*clear_open_replay_data)(struct obd_export *,
+ struct obd_client_handle *);
+ int (*set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *);
- ldlm_mode_t (*m_lock_match)(struct obd_export *, __u64,
- const struct lu_fid *, ldlm_type_t,
- ldlm_policy_data_t *, ldlm_mode_t,
- struct lustre_handle *);
+ ldlm_mode_t (*lock_match)(struct obd_export *, __u64,
+ const struct lu_fid *, ldlm_type_t,
+ ldlm_policy_data_t *, ldlm_mode_t,
+ struct lustre_handle *);
- int (*m_cancel_unused)(struct obd_export *, const struct lu_fid *,
- ldlm_policy_data_t *, ldlm_mode_t,
- ldlm_cancel_flags_t flags, void *opaque);
+ int (*cancel_unused)(struct obd_export *, const struct lu_fid *,
+ ldlm_policy_data_t *, ldlm_mode_t,
+ ldlm_cancel_flags_t flags, void *opaque);
- int (*m_get_remote_perm)(struct obd_export *, const struct lu_fid *,
- __u32, struct ptlrpc_request **);
+ int (*get_remote_perm)(struct obd_export *, const struct lu_fid *,
+ __u32, struct ptlrpc_request **);
- int (*m_intent_getattr_async)(struct obd_export *,
- struct md_enqueue_info *,
- struct ldlm_enqueue_info *);
+ int (*intent_getattr_async)(struct obd_export *,
+ struct md_enqueue_info *,
+ struct ldlm_enqueue_info *);
- int (*m_revalidate_lock)(struct obd_export *, struct lookup_intent *,
- struct lu_fid *, __u64 *bits);
+ int (*revalidate_lock)(struct obd_export *, struct lookup_intent *,
+ struct lu_fid *, __u64 *bits);
/*
* NOTE: If adding ops, add another LPROCFS_MD_OP_INIT() line to
diff --git a/drivers/staging/lustre/lustre/include/obd_cache.h b/drivers/staging/lustre/lustre/include/obd_cache.h
deleted file mode 100644
index b5e1155e5cd3..000000000000
--- a/drivers/staging/lustre/lustre/include/obd_cache.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be 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 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#ifndef _OBD_CACHE_H__
-#define _OBD_CACHE_H__
-
-#endif
diff --git a/drivers/staging/lustre/lustre/include/obd_cksum.h b/drivers/staging/lustre/lustre/include/obd_cksum.h
index a0099d71773a..01db60405393 100644
--- a/drivers/staging/lustre/lustre/include/obd_cksum.h
+++ b/drivers/staging/lustre/lustre/include/obd_cksum.h
@@ -133,29 +133,6 @@ static inline cksum_type_t cksum_types_supported_client(void)
return ret;
}
-/* Server uses algos that perform at 50% or better of the Adler */
-static inline cksum_type_t cksum_types_supported_server(void)
-{
- int base_speed;
- cksum_type_t ret = OBD_CKSUM_ADLER;
-
- CDEBUG(D_INFO, "Crypto hash speed: crc %d, crc32c %d, adler %d\n",
- cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32)),
- cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32C)),
- cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_ADLER)));
-
- base_speed = cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_ADLER)) / 2;
-
- if (cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32C)) >=
- base_speed)
- ret |= OBD_CKSUM_CRC32C;
- if (cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32)) >=
- base_speed)
- ret |= OBD_CKSUM_CRC32;
-
- return ret;
-}
-
/* Select the best checksum algorithm among those supplied in the cksum_types
* input.
*
diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h
index bf2bde5e6896..0b7e90ac7818 100644
--- a/drivers/staging/lustre/lustre/include/obd_class.h
+++ b/drivers/staging/lustre/lustre/include/obd_class.h
@@ -251,6 +251,16 @@ static inline enum obd_option exp_flags_from_obd(struct obd_device *obd)
0);
}
+static inline int lprocfs_climp_check(struct obd_device *obd)
+{
+ down_read(&(obd)->u.cli.cl_sem);
+ if (!(obd)->u.cli.cl_import) {
+ up_read(&(obd)->u.cli.cl_sem);
+ return -ENODEV;
+ }
+ return 0;
+}
+
struct inode;
struct lu_attr;
struct obdo;
@@ -260,8 +270,8 @@ void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj);
void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid);
#define OBT(dev) (dev)->obd_type
-#define OBP(dev, op) (dev)->obd_type->typ_dt_ops->o_ ## op
-#define MDP(dev, op) (dev)->obd_type->typ_md_ops->m_ ## op
+#define OBP(dev, op) (dev)->obd_type->typ_dt_ops->op
+#define MDP(dev, op) (dev)->obd_type->typ_md_ops->op
#define CTXTP(ctxt, op) (ctxt)->loc_logops->lop_##op
/* Ensure obd_setup: used for cleanup which must be called
@@ -291,9 +301,9 @@ static inline int obd_check_dev_active(struct obd_device *obd)
}
#define OBD_COUNTER_OFFSET(op) \
- ((offsetof(struct obd_ops, o_ ## op) - \
- offsetof(struct obd_ops, o_iocontrol)) \
- / sizeof(((struct obd_ops *)(0))->o_iocontrol))
+ ((offsetof(struct obd_ops, op) - \
+ offsetof(struct obd_ops, iocontrol)) \
+ / sizeof(((struct obd_ops *)(0))->iocontrol))
#define OBD_COUNTER_INCREMENT(obdx, op) \
if ((obdx)->obd_stats != NULL) { \
@@ -314,9 +324,9 @@ static inline int obd_check_dev_active(struct obd_device *obd)
}
#define MD_COUNTER_OFFSET(op) \
- ((offsetof(struct md_ops, m_ ## op) - \
- offsetof(struct md_ops, m_getstatus)) \
- / sizeof(((struct md_ops *)(0))->m_getstatus))
+ ((offsetof(struct md_ops, op) - \
+ offsetof(struct md_ops, getstatus)) \
+ / sizeof(((struct md_ops *)(0))->getstatus))
#define MD_COUNTER_INCREMENT(obdx, op) \
if ((obd)->md_stats != NULL) { \
@@ -1726,16 +1736,6 @@ void obd_cleanup_caches(void);
/* support routines */
extern struct kmem_cache *obdo_cachep;
-#define OBDO_ALLOC(ptr) \
-do { \
- OBD_SLAB_ALLOC_PTR_GFP((ptr), obdo_cachep, GFP_NOFS); \
-} while (0)
-
-#define OBDO_FREE(ptr) \
-do { \
- OBD_SLAB_FREE_PTR((ptr), obdo_cachep); \
-} while (0)
-
static inline void obdo2fid(struct obdo *oa, struct lu_fid *fid)
{
/* something here */
diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h
index abc53f115fb6..a22a5308fb48 100644
--- a/drivers/staging/lustre/lustre/include/obd_support.h
+++ b/drivers/staging/lustre/lustre/include/obd_support.h
@@ -514,82 +514,7 @@ do { \
POISON_PTR(ptr); \
} while (0)
-/* we memset() the slab object to 0 when allocation succeeds, so DO NOT
- * HAVE A CTOR THAT DOES ANYTHING. its work will be cleared here. we'd
- * love to assert on that, but slab.c keeps kmem_cache_s all to itself. */
-
-#define __OBD_SLAB_ALLOC_VERBOSE(ptr, slab, cptab, cpt, size, type) \
-do { \
- LASSERT(ergo((type) != GFP_ATOMIC, !in_interrupt())); \
- (ptr) = (cptab) == NULL ? \
- kmem_cache_alloc(slab, type | __GFP_ZERO) : \
- kmem_cache_alloc_node(slab, type | __GFP_ZERO, \
- cfs_cpt_spread_node(cptab, cpt)); \
-} while (0)
-
-#define OBD_SLAB_ALLOC_GFP(ptr, slab, size, flags) \
- __OBD_SLAB_ALLOC_VERBOSE(ptr, slab, NULL, 0, size, flags)
-#define OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, size, flags) \
- __OBD_SLAB_ALLOC_VERBOSE(ptr, slab, cptab, cpt, size, flags)
-
-#define OBD_SLAB_FREE(ptr, slab, size) \
-do { \
- kmem_cache_free(slab, ptr); \
- POISON_PTR(ptr); \
-} while (0)
-
-#define OBD_SLAB_ALLOC(ptr, slab, size) \
- OBD_SLAB_ALLOC_GFP(ptr, slab, size, GFP_NOFS)
-
-#define OBD_SLAB_CPT_ALLOC(ptr, slab, cptab, cpt, size) \
- OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, size, GFP_NOFS)
-
-#define OBD_SLAB_ALLOC_PTR(ptr, slab) \
- OBD_SLAB_ALLOC(ptr, slab, sizeof(*(ptr)))
-
-#define OBD_SLAB_CPT_ALLOC_PTR(ptr, slab, cptab, cpt) \
- OBD_SLAB_CPT_ALLOC(ptr, slab, cptab, cpt, sizeof(*(ptr)))
-
-#define OBD_SLAB_ALLOC_PTR_GFP(ptr, slab, flags) \
- OBD_SLAB_ALLOC_GFP(ptr, slab, sizeof(*(ptr)), flags)
-
-#define OBD_SLAB_CPT_ALLOC_PTR_GFP(ptr, slab, cptab, cpt, flags) \
- OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, sizeof(*(ptr)), flags)
-
-#define OBD_SLAB_FREE_PTR(ptr, slab) \
- OBD_SLAB_FREE((ptr), (slab), sizeof(*(ptr)))
-
#define KEY_IS(str) \
(keylen >= (sizeof(str)-1) && memcmp(key, str, (sizeof(str)-1)) == 0)
-/* Wrapper for contiguous page frame allocation */
-#define __OBD_PAGE_ALLOC_VERBOSE(ptr, cptab, cpt, gfp_mask) \
-do { \
- (ptr) = (cptab) == NULL ? \
- alloc_page(gfp_mask) : \
- alloc_pages_node(cfs_cpt_spread_node(cptab, cpt), gfp_mask, 0);\
- if (ptr) { \
- CDEBUG(D_MALLOC, "alloc_pages '" #ptr "': %d page(s) / " \
- "%llu bytes at %p.\n", \
- (int)1, \
- (__u64)(1 << PAGE_CACHE_SHIFT), ptr); \
- } \
-} while (0)
-
-#define OBD_PAGE_ALLOC(ptr, gfp_mask) \
- __OBD_PAGE_ALLOC_VERBOSE(ptr, NULL, 0, gfp_mask)
-#define OBD_PAGE_CPT_ALLOC(ptr, cptab, cpt, gfp_mask) \
- __OBD_PAGE_ALLOC_VERBOSE(ptr, cptab, cpt, gfp_mask)
-
-#define OBD_PAGE_FREE(ptr) \
-do { \
- LASSERT(ptr); \
- CDEBUG(D_MALLOC, "free_pages '" #ptr "': %d page(s) / %llu bytes " \
- "at %p.\n", \
- (int)1, (__u64)(1 << PAGE_CACHE_SHIFT), \
- ptr); \
- __free_page(ptr); \
- (ptr) = (void *)0xdeadbeef; \
-} while (0)
-
#endif
diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
index ef2e2667cabd..12c7f0e669d4 100644
--- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
+++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
@@ -116,7 +116,7 @@ void *ccc_key_init(const struct lu_context *ctx, struct lu_context_key *key)
{
struct ccc_thread_info *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, ccc_thread_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(ccc_thread_kmem, GFP_NOFS | __GFP_ZERO);
if (info == NULL)
info = ERR_PTR(-ENOMEM);
return info;
@@ -127,7 +127,7 @@ void ccc_key_fini(const struct lu_context *ctx,
{
struct ccc_thread_info *info = data;
- OBD_SLAB_FREE_PTR(info, ccc_thread_kmem);
+ kmem_cache_free(ccc_thread_kmem, info);
}
void *ccc_session_key_init(const struct lu_context *ctx,
@@ -135,7 +135,7 @@ void *ccc_session_key_init(const struct lu_context *ctx,
{
struct ccc_session *session;
- OBD_SLAB_ALLOC_PTR_GFP(session, ccc_session_kmem, GFP_NOFS);
+ session = kmem_cache_alloc(ccc_session_kmem, GFP_NOFS | __GFP_ZERO);
if (session == NULL)
session = ERR_PTR(-ENOMEM);
return session;
@@ -146,7 +146,7 @@ void ccc_session_key_fini(const struct lu_context *ctx,
{
struct ccc_session *session = data;
- OBD_SLAB_FREE_PTR(session, ccc_session_kmem);
+ kmem_cache_free(ccc_session_kmem, session);
}
struct lu_context_key ccc_key = {
@@ -251,7 +251,7 @@ int ccc_req_init(const struct lu_env *env, struct cl_device *dev,
struct ccc_req *vrq;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(vrq, ccc_req_kmem, GFP_NOFS);
+ vrq = kmem_cache_alloc(ccc_req_kmem, GFP_NOFS | __GFP_ZERO);
if (vrq != NULL) {
cl_req_slice_add(req, &vrq->crq_cl, dev, &ccc_req_ops);
result = 0;
@@ -327,7 +327,7 @@ struct lu_object *ccc_object_alloc(const struct lu_env *env,
struct ccc_object *vob;
struct lu_object *obj;
- OBD_SLAB_ALLOC_PTR_GFP(vob, ccc_object_kmem, GFP_NOFS);
+ vob = kmem_cache_alloc(ccc_object_kmem, GFP_NOFS | __GFP_ZERO);
if (vob != NULL) {
struct cl_object_header *hdr;
@@ -383,7 +383,7 @@ void ccc_object_free(const struct lu_env *env, struct lu_object *obj)
lu_object_fini(obj);
lu_object_header_fini(obj->lo_header);
- OBD_SLAB_FREE_PTR(vob, ccc_object_kmem);
+ kmem_cache_free(ccc_object_kmem, vob);
}
int ccc_lock_init(const struct lu_env *env,
@@ -396,7 +396,7 @@ int ccc_lock_init(const struct lu_env *env,
CLOBINVRNT(env, obj, ccc_object_invariant(obj));
- OBD_SLAB_ALLOC_PTR_GFP(clk, ccc_lock_kmem, GFP_NOFS);
+ clk = kmem_cache_alloc(ccc_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (clk != NULL) {
cl_lock_slice_add(lock, &clk->clk_cl, obj, lkops);
result = 0;
@@ -427,7 +427,7 @@ static void ccc_object_size_lock(struct cl_object *obj)
{
struct inode *inode = ccc_object_inode(obj);
- cl_isize_lock(inode);
+ ll_inode_size_lock(inode);
cl_object_attr_lock(obj);
}
@@ -436,7 +436,7 @@ static void ccc_object_size_unlock(struct cl_object *obj)
struct inode *inode = ccc_object_inode(obj);
cl_object_attr_unlock(obj);
- cl_isize_unlock(inode);
+ ll_inode_size_unlock(inode);
}
/*****************************************************************************
@@ -511,7 +511,7 @@ void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice)
{
struct ccc_lock *clk = cl2ccc_lock(slice);
- OBD_SLAB_FREE_PTR(clk, ccc_lock_kmem);
+ kmem_cache_free(ccc_lock_kmem, clk);
}
int ccc_lock_enqueue(const struct lu_env *env,
@@ -804,7 +804,7 @@ void ccc_req_completion(const struct lu_env *env,
cl_stats_tally(slice->crs_dev, slice->crs_req->crq_type, ioret);
vrq = cl2ccc_req(slice);
- OBD_SLAB_FREE_PTR(vrq, ccc_req_kmem);
+ kmem_cache_free(ccc_req_kmem, vrq);
}
/**
diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c
index 3d2d85ba8a26..a2ea8e5b93d8 100644
--- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c
+++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c
@@ -96,18 +96,6 @@ static inline int extent_equal(struct interval_node_extent *e1,
return (e1->start == e2->start) && (e1->end == e2->end);
}
-static inline int node_compare(struct interval_node *n1,
- struct interval_node *n2)
-{
- return extent_compare(&n1->in_extent, &n2->in_extent);
-}
-
-static inline int node_equal(struct interval_node *n1,
- struct interval_node *n2)
-{
- return extent_equal(&n1->in_extent, &n2->in_extent);
-}
-
static inline __u64 max_u64(__u64 x, __u64 y)
{
return x > y ? x : y;
@@ -278,14 +266,14 @@ struct interval_node *interval_insert(struct interval_node *node,
p = root;
while (*p) {
parent = *p;
- if (node_equal(parent, node))
+ if (extent_equal(&parent->in_extent, &node->in_extent))
return parent;
/* max_high field must be updated after each iteration */
if (parent->in_max_high < interval_high(node))
parent->in_max_high = interval_high(node);
- if (node_compare(node, parent) < 0)
+ if (extent_compare(&node->in_extent, &parent->in_extent) < 0)
p = &parent->in_left;
else
p = &parent->in_right;
@@ -294,7 +282,8 @@ struct interval_node *interval_insert(struct interval_node *node,
/* link node into the tree */
node->in_parent = parent;
node->in_color = INTERVAL_RED;
- node->in_left = node->in_right = NULL;
+ node->in_left = NULL;
+ node->in_right = NULL;
*p = node;
interval_insert_color(node, root);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
index 57b997dc42f5..9c70f31ea56e 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
@@ -112,7 +112,7 @@ struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock)
struct ldlm_interval *node;
LASSERT(lock->l_resource->lr_type == LDLM_EXTENT);
- OBD_SLAB_ALLOC_PTR_GFP(node, ldlm_interval_slab, GFP_NOFS);
+ node = kmem_cache_alloc(ldlm_interval_slab, GFP_NOFS | __GFP_ZERO);
if (node == NULL)
return NULL;
@@ -126,7 +126,7 @@ void ldlm_interval_free(struct ldlm_interval *node)
if (node) {
LASSERT(list_empty(&node->li_group));
LASSERT(!interval_is_intree(&node->li_node));
- OBD_SLAB_FREE(node, ldlm_interval_slab, sizeof(*node));
+ kmem_cache_free(ldlm_interval_slab, node);
}
}
@@ -149,7 +149,7 @@ static inline int lock_mode_to_index(ldlm_mode_t mode)
int index;
LASSERT(mode != 0);
- LASSERT(IS_PO2(mode));
+ LASSERT(is_power_of_2(mode));
for (index = -1; mode; index++)
mode >>= 1;
LASSERT(index < LCK_MODE_NUM);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
index 1600375f74b6..7f8c70056ffd 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
@@ -392,7 +392,7 @@ static void lock_handle_addref(void *lock)
static void lock_handle_free(void *lock, int size)
{
LASSERT(size == sizeof(struct ldlm_lock));
- OBD_SLAB_FREE(lock, ldlm_lock_slab, size);
+ kmem_cache_free(ldlm_lock_slab, lock);
}
static struct portals_handle_ops lock_handle_ops = {
@@ -415,7 +415,7 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_resource *resource)
if (resource == NULL)
LBUG();
- OBD_SLAB_ALLOC_PTR_GFP(lock, ldlm_lock_slab, GFP_NOFS);
+ lock = kmem_cache_alloc(ldlm_lock_slab, GFP_NOFS | __GFP_ZERO);
if (lock == NULL)
return NULL;
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
index 92c21fd47f86..e59b2864180f 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
@@ -176,11 +176,6 @@ enum {
LDLM_POOL_LAST_STAT
};
-static inline struct ldlm_namespace *ldlm_pl2ns(struct ldlm_pool *pl)
-{
- return container_of(pl, struct ldlm_namespace, ns_pool);
-}
-
/**
* Calculates suggested grant_step in % of available locks for passed
* \a period. This is later used in grant_plan calculations.
@@ -213,22 +208,6 @@ static inline int ldlm_pool_t2gsp(unsigned int t)
}
/**
- * Returns current \a pl limit.
- */
-static __u32 ldlm_pool_get_limit(struct ldlm_pool *pl)
-{
- return atomic_read(&pl->pl_limit);
-}
-
-/**
- * Sets passed \a limit to \a pl.
- */
-static void ldlm_pool_set_limit(struct ldlm_pool *pl, __u32 limit)
-{
- atomic_set(&pl->pl_limit, limit);
-}
-
-/**
* Recalculates next stats on passed \a pl.
*
* \pre ->pl_lock is locked.
@@ -254,7 +233,8 @@ static void ldlm_pool_recalc_stats(struct ldlm_pool *pl)
}
/**
- * Sets SLV and Limit from ldlm_pl2ns(pl)->ns_obd tp passed \a pl.
+ * Sets SLV and Limit from container_of(pl, struct ldlm_namespace,
+ * ns_pool)->ns_obd tp passed \a pl.
*/
static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl)
{
@@ -264,11 +244,12 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl)
* Get new SLV and Limit from obd which is updated with coming
* RPCs.
*/
- obd = ldlm_pl2ns(pl)->ns_obd;
+ obd = container_of(pl, struct ldlm_namespace,
+ ns_pool)->ns_obd;
LASSERT(obd != NULL);
read_lock(&obd->obd_pool_lock);
pl->pl_server_lock_volume = obd->obd_pool_slv;
- ldlm_pool_set_limit(pl, obd->obd_pool_limit);
+ atomic_set(&pl->pl_limit, obd->obd_pool_limit);
read_unlock(&obd->obd_pool_lock);
}
@@ -304,7 +285,8 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl)
/*
* Do not cancel locks in case lru resize is disabled for this ns.
*/
- if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) {
+ if (!ns_connect_lru_resize(container_of(pl, struct ldlm_namespace,
+ ns_pool))) {
ret = 0;
goto out;
}
@@ -315,7 +297,8 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl)
* It may be called when SLV has changed much, this is why we do not
* take into account pl->pl_recalc_time here.
*/
- ret = ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR);
+ ret = ldlm_cancel_lru(container_of(pl, struct ldlm_namespace, ns_pool),
+ 0, LCF_ASYNC, LDLM_CANCEL_LRUR);
out:
spin_lock(&pl->pl_lock);
@@ -341,7 +324,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
struct ldlm_namespace *ns;
int unused;
- ns = ldlm_pl2ns(pl);
+ ns = container_of(pl, struct ldlm_namespace, ns_pool);
/*
* Do not cancel locks in case lru resize is disabled for this ns.
@@ -453,7 +436,7 @@ static int lprocfs_pool_state_seq_show(struct seq_file *m, void *unused)
spin_lock(&pl->pl_lock);
slv = pl->pl_server_lock_volume;
clv = pl->pl_client_lock_volume;
- limit = ldlm_pool_get_limit(pl);
+ limit = atomic_read(&pl->pl_limit);
granted = atomic_read(&pl->pl_granted);
grant_rate = atomic_read(&pl->pl_grant_rate);
cancel_rate = atomic_read(&pl->pl_cancel_rate);
@@ -558,7 +541,8 @@ static struct kobj_type ldlm_pl_ktype = {
static int ldlm_pool_sysfs_init(struct ldlm_pool *pl)
{
- struct ldlm_namespace *ns = ldlm_pl2ns(pl);
+ struct ldlm_namespace *ns = container_of(pl, struct ldlm_namespace,
+ ns_pool);
int err;
init_completion(&pl->pl_kobj_unregister);
@@ -570,7 +554,8 @@ static int ldlm_pool_sysfs_init(struct ldlm_pool *pl)
static int ldlm_pool_debugfs_init(struct ldlm_pool *pl)
{
- struct ldlm_namespace *ns = ldlm_pl2ns(pl);
+ struct ldlm_namespace *ns = container_of(pl, struct ldlm_namespace,
+ ns_pool);
struct dentry *debugfs_ns_parent;
struct lprocfs_vars pool_vars[2];
char *var_name = NULL;
@@ -685,7 +670,7 @@ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns,
snprintf(pl->pl_name, sizeof(pl->pl_name), "ldlm-pool-%s-%d",
ldlm_ns_name(ns), idx);
- ldlm_pool_set_limit(pl, 1);
+ atomic_set(&pl->pl_limit, 1);
pl->pl_server_lock_volume = 0;
pl->pl_ops = &ldlm_cli_pool_ops;
pl->pl_recalc_period = LDLM_POOL_CLI_DEF_RECALC_PERIOD;
@@ -1005,7 +990,6 @@ static int ldlm_pools_recalc(ldlm_side_t client)
}
return time;
}
-EXPORT_SYMBOL(ldlm_pools_recalc);
static int ldlm_pools_thread_main(void *arg)
{
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index e09f2cdb1fbc..b55a4f0eb1d5 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -531,26 +531,26 @@ static void ldlm_res_hop_put(struct cfs_hash *hs, struct hlist_node *hnode)
ldlm_resource_putref(res);
}
-static cfs_hash_ops_t ldlm_ns_hash_ops = {
+static struct cfs_hash_ops ldlm_ns_hash_ops = {
.hs_hash = ldlm_res_hop_hash,
- .hs_key = ldlm_res_hop_key,
+ .hs_key = ldlm_res_hop_key,
.hs_keycmp = ldlm_res_hop_keycmp,
.hs_keycpy = NULL,
.hs_object = ldlm_res_hop_object,
- .hs_get = ldlm_res_hop_get_locked,
+ .hs_get = ldlm_res_hop_get_locked,
.hs_put_locked = ldlm_res_hop_put_locked,
- .hs_put = ldlm_res_hop_put
+ .hs_put = ldlm_res_hop_put
};
-static cfs_hash_ops_t ldlm_ns_fid_hash_ops = {
+static struct cfs_hash_ops ldlm_ns_fid_hash_ops = {
.hs_hash = ldlm_res_hop_fid_hash,
- .hs_key = ldlm_res_hop_key,
+ .hs_key = ldlm_res_hop_key,
.hs_keycmp = ldlm_res_hop_keycmp,
.hs_keycpy = NULL,
.hs_object = ldlm_res_hop_object,
- .hs_get = ldlm_res_hop_get_locked,
+ .hs_get = ldlm_res_hop_get_locked,
.hs_put_locked = ldlm_res_hop_put_locked,
- .hs_put = ldlm_res_hop_put
+ .hs_put = ldlm_res_hop_put
};
struct ldlm_ns_hash_def {
@@ -560,7 +560,7 @@ struct ldlm_ns_hash_def {
/** hash bits */
unsigned nsd_all_bits;
/** hash operations */
- cfs_hash_ops_t *nsd_hops;
+ struct cfs_hash_ops *nsd_hops;
};
static struct ldlm_ns_hash_def ldlm_ns_hash_defs[] = {
@@ -1031,7 +1031,7 @@ static struct ldlm_resource *ldlm_resource_new(void)
struct ldlm_resource *res;
int idx;
- OBD_SLAB_ALLOC_PTR_GFP(res, ldlm_resource_slab, GFP_NOFS);
+ res = kmem_cache_alloc(ldlm_resource_slab, GFP_NOFS | __GFP_ZERO);
if (res == NULL)
return NULL;
@@ -1124,7 +1124,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
lu_ref_fini(&res->lr_reference);
/* We have taken lr_lvb_mutex. Drop it. */
mutex_unlock(&res->lr_lvb_mutex);
- OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res));
+ kmem_cache_free(ldlm_resource_slab, res);
res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
/* Synchronize with regard to resource creation. */
@@ -1154,8 +1154,6 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n",
ns->ns_obd->obd_name, name->name[0],
name->name[1], rc);
- kfree(res->lr_lvb_data);
- res->lr_lvb_data = NULL;
res->lr_lvb_len = rc;
mutex_unlock(&res->lr_lvb_mutex);
ldlm_resource_putref(res);
@@ -1218,7 +1216,7 @@ int ldlm_resource_putref(struct ldlm_resource *res)
cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
ns->ns_lvbo->lvbo_free(res);
- OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res));
+ kmem_cache_free(ldlm_resource_slab, res);
return 1;
}
return 0;
@@ -1248,7 +1246,7 @@ int ldlm_resource_putref_locked(struct ldlm_resource *res)
*/
if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
ns->ns_lvbo->lvbo_free(res);
- OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res));
+ kmem_cache_free(ldlm_resource_slab, res);
cfs_hash_bd_lock(ns->ns_rs_hash, &bd, 1);
return 1;
diff --git a/drivers/staging/lustre/lustre/libcfs/Makefile b/drivers/staging/lustre/lustre/libcfs/Makefile
index ec98f44a10dd..03d3f3d7b1f8 100644
--- a/drivers/staging/lustre/lustre/libcfs/Makefile
+++ b/drivers/staging/lustre/lustre/libcfs/Makefile
@@ -10,7 +10,7 @@ libcfs-linux-objs += linux-mem.o
libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs))
-libcfs-all-objs := debug.o fail.o nidstrings.o module.o tracefile.o \
+libcfs-all-objs := debug.o fail.o module.o tracefile.o \
libcfs_string.o hash.o kernel_user_comm.o \
prng.o workitem.o libcfs_cpu.o \
libcfs_mem.o libcfs_lock.o
diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c
index 1d1c67164418..e56785a48242 100644
--- a/drivers/staging/lustre/lustre/libcfs/debug.c
+++ b/drivers/staging/lustre/lustre/libcfs/debug.c
@@ -94,17 +94,14 @@ static struct kernel_param_ops param_ops_debugmb = {
static unsigned int libcfs_debug_mb;
module_param(libcfs_debug_mb, debugmb, 0644);
MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size.");
-EXPORT_SYMBOL(libcfs_debug_mb);
unsigned int libcfs_printk = D_CANTMASK;
module_param(libcfs_printk, uint, 0644);
MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask");
-EXPORT_SYMBOL(libcfs_printk);
unsigned int libcfs_console_ratelimit = 1;
module_param(libcfs_console_ratelimit, uint, 0644);
MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)");
-EXPORT_SYMBOL(libcfs_console_ratelimit);
static int param_set_delay_minmax(const char *val,
const struct kernel_param *kp,
@@ -135,9 +132,7 @@ static int param_get_delay(char *buffer, const struct kernel_param *kp)
}
unsigned int libcfs_console_max_delay;
-EXPORT_SYMBOL(libcfs_console_max_delay);
unsigned int libcfs_console_min_delay;
-EXPORT_SYMBOL(libcfs_console_min_delay);
static int param_set_console_max_delay(const char *val,
const struct kernel_param *kp)
@@ -207,10 +202,8 @@ static struct kernel_param_ops param_ops_uintpos = {
unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
module_param(libcfs_console_backoff, uintpos, 0644);
MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor");
-EXPORT_SYMBOL(libcfs_console_backoff);
unsigned int libcfs_debug_binary = 1;
-EXPORT_SYMBOL(libcfs_debug_binary);
unsigned int libcfs_stack = 3 * THREAD_SIZE / 4;
EXPORT_SYMBOL(libcfs_stack);
@@ -221,7 +214,6 @@ EXPORT_SYMBOL(libcfs_catastrophe);
unsigned int libcfs_panic_on_lbug = 1;
module_param(libcfs_panic_on_lbug, uint, 0644);
MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG");
-EXPORT_SYMBOL(libcfs_panic_on_lbug);
static wait_queue_head_t debug_ctlwq;
@@ -512,9 +504,9 @@ int libcfs_debug_init(unsigned long bufsize)
}
if (libcfs_debug_file_path != NULL) {
- strncpy(libcfs_debug_file_path_arr,
- libcfs_debug_file_path, PATH_MAX-1);
- libcfs_debug_file_path_arr[PATH_MAX - 1] = '\0';
+ strlcpy(libcfs_debug_file_path_arr,
+ libcfs_debug_file_path,
+ sizeof(libcfs_debug_file_path_arr));
}
/* If libcfs_debug_mb is set to an invalid value or uninitialized
@@ -572,5 +564,3 @@ void libcfs_debug_set_level(unsigned int debug_level)
debug_level);
libcfs_debug = debug_level;
}
-
-EXPORT_SYMBOL(libcfs_debug_set_level);
diff --git a/drivers/staging/lustre/lustre/libcfs/fail.c b/drivers/staging/lustre/lustre/libcfs/fail.c
index d39fecebd12d..ea059b012a66 100644
--- a/drivers/staging/lustre/lustre/libcfs/fail.c
+++ b/drivers/staging/lustre/lustre/libcfs/fail.c
@@ -126,7 +126,7 @@ int __cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set)
int ret;
ret = __cfs_fail_check_set(id, value, set);
- if (ret) {
+ if (ret && likely(ms > 0)) {
CERROR("cfs_fail_timeout id %x sleeping for %dms\n",
id, ms);
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c
index 6f4c7d47fa33..d285117af3ad 100644
--- a/drivers/staging/lustre/lustre/libcfs/hash.c
+++ b/drivers/staging/lustre/lustre/libcfs/hash.c
@@ -106,9 +106,9 @@
* Now we support both locked iteration & lockless iteration of hash
* table. Also, user can break the iteration by return 1 in callback.
*/
+#include <linux/seq_file.h>
#include "../../include/linux/libcfs/libcfs.h"
-#include <linux/seq_file.h>
#if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1
static unsigned int warn_on_depth = 8;
@@ -159,51 +159,51 @@ cfs_hash_rw_unlock(union cfs_hash_lock *lock, int exclusive)
}
/** No lock hash */
-static cfs_hash_lock_ops_t cfs_hash_nl_lops = {
+static struct cfs_hash_lock_ops cfs_hash_nl_lops = {
.hs_lock = cfs_hash_nl_lock,
- .hs_unlock = cfs_hash_nl_unlock,
- .hs_bkt_lock = cfs_hash_nl_lock,
- .hs_bkt_unlock = cfs_hash_nl_unlock,
+ .hs_unlock = cfs_hash_nl_unlock,
+ .hs_bkt_lock = cfs_hash_nl_lock,
+ .hs_bkt_unlock = cfs_hash_nl_unlock,
};
/** no bucket lock, one spinlock to protect everything */
-static cfs_hash_lock_ops_t cfs_hash_nbl_lops = {
+static struct cfs_hash_lock_ops cfs_hash_nbl_lops = {
.hs_lock = cfs_hash_spin_lock,
- .hs_unlock = cfs_hash_spin_unlock,
- .hs_bkt_lock = cfs_hash_nl_lock,
- .hs_bkt_unlock = cfs_hash_nl_unlock,
+ .hs_unlock = cfs_hash_spin_unlock,
+ .hs_bkt_lock = cfs_hash_nl_lock,
+ .hs_bkt_unlock = cfs_hash_nl_unlock,
};
/** spin bucket lock, rehash is enabled */
-static cfs_hash_lock_ops_t cfs_hash_bkt_spin_lops = {
+static struct cfs_hash_lock_ops cfs_hash_bkt_spin_lops = {
.hs_lock = cfs_hash_rw_lock,
- .hs_unlock = cfs_hash_rw_unlock,
- .hs_bkt_lock = cfs_hash_spin_lock,
- .hs_bkt_unlock = cfs_hash_spin_unlock,
+ .hs_unlock = cfs_hash_rw_unlock,
+ .hs_bkt_lock = cfs_hash_spin_lock,
+ .hs_bkt_unlock = cfs_hash_spin_unlock,
};
/** rw bucket lock, rehash is enabled */
-static cfs_hash_lock_ops_t cfs_hash_bkt_rw_lops = {
+static struct cfs_hash_lock_ops cfs_hash_bkt_rw_lops = {
.hs_lock = cfs_hash_rw_lock,
- .hs_unlock = cfs_hash_rw_unlock,
- .hs_bkt_lock = cfs_hash_rw_lock,
- .hs_bkt_unlock = cfs_hash_rw_unlock,
+ .hs_unlock = cfs_hash_rw_unlock,
+ .hs_bkt_lock = cfs_hash_rw_lock,
+ .hs_bkt_unlock = cfs_hash_rw_unlock,
};
/** spin bucket lock, rehash is disabled */
-static cfs_hash_lock_ops_t cfs_hash_nr_bkt_spin_lops = {
+static struct cfs_hash_lock_ops cfs_hash_nr_bkt_spin_lops = {
.hs_lock = cfs_hash_nl_lock,
- .hs_unlock = cfs_hash_nl_unlock,
- .hs_bkt_lock = cfs_hash_spin_lock,
- .hs_bkt_unlock = cfs_hash_spin_unlock,
+ .hs_unlock = cfs_hash_nl_unlock,
+ .hs_bkt_lock = cfs_hash_spin_lock,
+ .hs_bkt_unlock = cfs_hash_spin_unlock,
};
/** rw bucket lock, rehash is disabled */
-static cfs_hash_lock_ops_t cfs_hash_nr_bkt_rw_lops = {
+static struct cfs_hash_lock_ops cfs_hash_nr_bkt_rw_lops = {
.hs_lock = cfs_hash_nl_lock,
- .hs_unlock = cfs_hash_nl_unlock,
- .hs_bkt_lock = cfs_hash_rw_lock,
- .hs_bkt_unlock = cfs_hash_rw_unlock,
+ .hs_unlock = cfs_hash_nl_unlock,
+ .hs_bkt_lock = cfs_hash_rw_lock,
+ .hs_bkt_unlock = cfs_hash_rw_unlock,
};
static void
@@ -239,21 +239,22 @@ cfs_hash_lock_setup(struct cfs_hash *hs)
* Simple hash head without depth tracking
* new element is always added to head of hlist
*/
-typedef struct {
+struct cfs_hash_head {
struct hlist_head hh_head; /**< entries list */
-} cfs_hash_head_t;
+};
static int
cfs_hash_hh_hhead_size(struct cfs_hash *hs)
{
- return sizeof(cfs_hash_head_t);
+ return sizeof(struct cfs_hash_head);
}
static struct hlist_head *
cfs_hash_hh_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
{
- cfs_hash_head_t *head = (cfs_hash_head_t *)&bd->bd_bucket->hsb_head[0];
+ struct cfs_hash_head *head;
+ head = (struct cfs_hash_head *)&bd->bd_bucket->hsb_head[0];
return &head[bd->bd_offset].hh_head;
}
@@ -277,23 +278,23 @@ cfs_hash_hh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
* Simple hash head with depth tracking
* new element is always added to head of hlist
*/
-typedef struct {
+struct cfs_hash_head_dep {
struct hlist_head hd_head; /**< entries list */
- unsigned int hd_depth; /**< list length */
-} cfs_hash_head_dep_t;
+ unsigned int hd_depth; /**< list length */
+};
static int
cfs_hash_hd_hhead_size(struct cfs_hash *hs)
{
- return sizeof(cfs_hash_head_dep_t);
+ return sizeof(struct cfs_hash_head_dep);
}
static struct hlist_head *
cfs_hash_hd_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
{
- cfs_hash_head_dep_t *head;
+ struct cfs_hash_head_dep *head;
- head = (cfs_hash_head_dep_t *)&bd->bd_bucket->hsb_head[0];
+ head = (struct cfs_hash_head_dep *)&bd->bd_bucket->hsb_head[0];
return &head[bd->bd_offset].hd_head;
}
@@ -301,8 +302,10 @@ static int
cfs_hash_hd_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode)
{
- cfs_hash_head_dep_t *hh = container_of(cfs_hash_hd_hhead(hs, bd),
- cfs_hash_head_dep_t, hd_head);
+ struct cfs_hash_head_dep *hh;
+
+ hh = container_of(cfs_hash_hd_hhead(hs, bd),
+ struct cfs_hash_head_dep, hd_head);
hlist_add_head(hnode, &hh->hd_head);
return ++hh->hd_depth;
}
@@ -311,8 +314,10 @@ static int
cfs_hash_hd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode)
{
- cfs_hash_head_dep_t *hh = container_of(cfs_hash_hd_hhead(hs, bd),
- cfs_hash_head_dep_t, hd_head);
+ struct cfs_hash_head_dep *hh;
+
+ hh = container_of(cfs_hash_hd_hhead(hs, bd),
+ struct cfs_hash_head_dep, hd_head);
hlist_del_init(hnode);
return --hh->hd_depth;
}
@@ -321,23 +326,23 @@ cfs_hash_hd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
* double links hash head without depth tracking
* new element is always added to tail of hlist
*/
-typedef struct {
+struct cfs_hash_dhead {
struct hlist_head dh_head; /**< entries list */
- struct hlist_node *dh_tail; /**< the last entry */
-} cfs_hash_dhead_t;
+ struct hlist_node *dh_tail; /**< the last entry */
+};
static int
cfs_hash_dh_hhead_size(struct cfs_hash *hs)
{
- return sizeof(cfs_hash_dhead_t);
+ return sizeof(struct cfs_hash_dhead);
}
static struct hlist_head *
cfs_hash_dh_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
{
- cfs_hash_dhead_t *head;
+ struct cfs_hash_dhead *head;
- head = (cfs_hash_dhead_t *)&bd->bd_bucket->hsb_head[0];
+ head = (struct cfs_hash_dhead *)&bd->bd_bucket->hsb_head[0];
return &head[bd->bd_offset].dh_head;
}
@@ -345,9 +350,10 @@ static int
cfs_hash_dh_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode)
{
- cfs_hash_dhead_t *dh = container_of(cfs_hash_dh_hhead(hs, bd),
- cfs_hash_dhead_t, dh_head);
+ struct cfs_hash_dhead *dh;
+ dh = container_of(cfs_hash_dh_hhead(hs, bd),
+ struct cfs_hash_dhead, dh_head);
if (dh->dh_tail != NULL) /* not empty */
hlist_add_behind(hnode, dh->dh_tail);
else /* empty list */
@@ -360,9 +366,10 @@ static int
cfs_hash_dh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnd)
{
- cfs_hash_dhead_t *dh = container_of(cfs_hash_dh_hhead(hs, bd),
- cfs_hash_dhead_t, dh_head);
+ struct cfs_hash_dhead *dh;
+ dh = container_of(cfs_hash_dh_hhead(hs, bd),
+ struct cfs_hash_dhead, dh_head);
if (hnd->next == NULL) { /* it's the tail */
dh->dh_tail = (hnd->pprev == &dh->dh_head.first) ? NULL :
container_of(hnd->pprev, struct hlist_node, next);
@@ -375,24 +382,24 @@ cfs_hash_dh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
* double links hash head with depth tracking
* new element is always added to tail of hlist
*/
-typedef struct {
+struct cfs_hash_dhead_dep {
struct hlist_head dd_head; /**< entries list */
- struct hlist_node *dd_tail; /**< the last entry */
- unsigned int dd_depth; /**< list length */
-} cfs_hash_dhead_dep_t;
+ struct hlist_node *dd_tail; /**< the last entry */
+ unsigned int dd_depth; /**< list length */
+};
static int
cfs_hash_dd_hhead_size(struct cfs_hash *hs)
{
- return sizeof(cfs_hash_dhead_dep_t);
+ return sizeof(struct cfs_hash_dhead_dep);
}
static struct hlist_head *
cfs_hash_dd_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
{
- cfs_hash_dhead_dep_t *head;
+ struct cfs_hash_dhead_dep *head;
- head = (cfs_hash_dhead_dep_t *)&bd->bd_bucket->hsb_head[0];
+ head = (struct cfs_hash_dhead_dep *)&bd->bd_bucket->hsb_head[0];
return &head[bd->bd_offset].dd_head;
}
@@ -400,9 +407,10 @@ static int
cfs_hash_dd_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode)
{
- cfs_hash_dhead_dep_t *dh = container_of(cfs_hash_dd_hhead(hs, bd),
- cfs_hash_dhead_dep_t, dd_head);
+ struct cfs_hash_dhead_dep *dh;
+ dh = container_of(cfs_hash_dd_hhead(hs, bd),
+ struct cfs_hash_dhead_dep, dd_head);
if (dh->dd_tail != NULL) /* not empty */
hlist_add_behind(hnode, dh->dd_tail);
else /* empty list */
@@ -415,9 +423,10 @@ static int
cfs_hash_dd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnd)
{
- cfs_hash_dhead_dep_t *dh = container_of(cfs_hash_dd_hhead(hs, bd),
- cfs_hash_dhead_dep_t, dd_head);
+ struct cfs_hash_dhead_dep *dh;
+ dh = container_of(cfs_hash_dd_hhead(hs, bd),
+ struct cfs_hash_dhead_dep, dd_head);
if (hnd->next == NULL) { /* it's the tail */
dh->dd_tail = (hnd->pprev == &dh->dd_head.first) ? NULL :
container_of(hnd->pprev, struct hlist_node, next);
@@ -426,32 +435,32 @@ cfs_hash_dd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
return --dh->dd_depth;
}
-static cfs_hash_hlist_ops_t cfs_hash_hh_hops = {
- .hop_hhead = cfs_hash_hh_hhead,
- .hop_hhead_size = cfs_hash_hh_hhead_size,
- .hop_hnode_add = cfs_hash_hh_hnode_add,
- .hop_hnode_del = cfs_hash_hh_hnode_del,
+static struct cfs_hash_hlist_ops cfs_hash_hh_hops = {
+ .hop_hhead = cfs_hash_hh_hhead,
+ .hop_hhead_size = cfs_hash_hh_hhead_size,
+ .hop_hnode_add = cfs_hash_hh_hnode_add,
+ .hop_hnode_del = cfs_hash_hh_hnode_del,
};
-static cfs_hash_hlist_ops_t cfs_hash_hd_hops = {
- .hop_hhead = cfs_hash_hd_hhead,
- .hop_hhead_size = cfs_hash_hd_hhead_size,
- .hop_hnode_add = cfs_hash_hd_hnode_add,
- .hop_hnode_del = cfs_hash_hd_hnode_del,
+static struct cfs_hash_hlist_ops cfs_hash_hd_hops = {
+ .hop_hhead = cfs_hash_hd_hhead,
+ .hop_hhead_size = cfs_hash_hd_hhead_size,
+ .hop_hnode_add = cfs_hash_hd_hnode_add,
+ .hop_hnode_del = cfs_hash_hd_hnode_del,
};
-static cfs_hash_hlist_ops_t cfs_hash_dh_hops = {
- .hop_hhead = cfs_hash_dh_hhead,
- .hop_hhead_size = cfs_hash_dh_hhead_size,
- .hop_hnode_add = cfs_hash_dh_hnode_add,
- .hop_hnode_del = cfs_hash_dh_hnode_del,
+static struct cfs_hash_hlist_ops cfs_hash_dh_hops = {
+ .hop_hhead = cfs_hash_dh_hhead,
+ .hop_hhead_size = cfs_hash_dh_hhead_size,
+ .hop_hnode_add = cfs_hash_dh_hnode_add,
+ .hop_hnode_del = cfs_hash_dh_hnode_del,
};
-static cfs_hash_hlist_ops_t cfs_hash_dd_hops = {
- .hop_hhead = cfs_hash_dd_hhead,
- .hop_hhead_size = cfs_hash_dd_hhead_size,
- .hop_hnode_add = cfs_hash_dd_hnode_add,
- .hop_hnode_del = cfs_hash_dd_hnode_del,
+static struct cfs_hash_hlist_ops cfs_hash_dd_hops = {
+ .hop_hhead = cfs_hash_dd_hhead,
+ .hop_hhead_size = cfs_hash_dd_hhead_size,
+ .hop_hnode_add = cfs_hash_dd_hnode_add,
+ .hop_hnode_del = cfs_hash_dd_hnode_del,
};
static void
@@ -520,7 +529,7 @@ void
cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode)
{
- int rc;
+ int rc;
rc = hs->hs_hops->hop_hnode_add(hs, bd, hnode);
cfs_hash_bd_dep_record(hs, bd, rc);
@@ -563,7 +572,7 @@ cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old,
{
struct cfs_hash_bucket *obkt = bd_old->bd_bucket;
struct cfs_hash_bucket *nbkt = bd_new->bd_bucket;
- int rc;
+ int rc;
if (cfs_hash_bd_compare(bd_old, bd_new) == 0)
return;
@@ -584,46 +593,45 @@ cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old,
if (unlikely(nbkt->hsb_version == 0))
nbkt->hsb_version++;
}
-EXPORT_SYMBOL(cfs_hash_bd_move_locked);
enum {
/** always set, for sanity (avoid ZERO intent) */
- CFS_HS_LOOKUP_MASK_FIND = BIT(0),
+ CFS_HS_LOOKUP_MASK_FIND = BIT(0),
/** return entry with a ref */
- CFS_HS_LOOKUP_MASK_REF = BIT(1),
+ CFS_HS_LOOKUP_MASK_REF = BIT(1),
/** add entry if not existing */
- CFS_HS_LOOKUP_MASK_ADD = BIT(2),
+ CFS_HS_LOOKUP_MASK_ADD = BIT(2),
/** delete entry, ignore other masks */
- CFS_HS_LOOKUP_MASK_DEL = BIT(3),
+ CFS_HS_LOOKUP_MASK_DEL = BIT(3),
};
-typedef enum cfs_hash_lookup_intent {
+enum cfs_hash_lookup_intent {
/** return item w/o refcount */
- CFS_HS_LOOKUP_IT_PEEK = CFS_HS_LOOKUP_MASK_FIND,
+ CFS_HS_LOOKUP_IT_PEEK = CFS_HS_LOOKUP_MASK_FIND,
/** return item with refcount */
- CFS_HS_LOOKUP_IT_FIND = (CFS_HS_LOOKUP_MASK_FIND |
- CFS_HS_LOOKUP_MASK_REF),
+ CFS_HS_LOOKUP_IT_FIND = (CFS_HS_LOOKUP_MASK_FIND |
+ CFS_HS_LOOKUP_MASK_REF),
/** return item w/o refcount if existed, otherwise add */
- CFS_HS_LOOKUP_IT_ADD = (CFS_HS_LOOKUP_MASK_FIND |
- CFS_HS_LOOKUP_MASK_ADD),
+ CFS_HS_LOOKUP_IT_ADD = (CFS_HS_LOOKUP_MASK_FIND |
+ CFS_HS_LOOKUP_MASK_ADD),
/** return item with refcount if existed, otherwise add */
- CFS_HS_LOOKUP_IT_FINDADD = (CFS_HS_LOOKUP_IT_FIND |
- CFS_HS_LOOKUP_MASK_ADD),
+ CFS_HS_LOOKUP_IT_FINDADD = (CFS_HS_LOOKUP_IT_FIND |
+ CFS_HS_LOOKUP_MASK_ADD),
/** delete if existed */
- CFS_HS_LOOKUP_IT_FINDDEL = (CFS_HS_LOOKUP_MASK_FIND |
- CFS_HS_LOOKUP_MASK_DEL)
-} cfs_hash_lookup_intent_t;
+ CFS_HS_LOOKUP_IT_FINDDEL = (CFS_HS_LOOKUP_MASK_FIND |
+ CFS_HS_LOOKUP_MASK_DEL)
+};
static struct hlist_node *
cfs_hash_bd_lookup_intent(struct cfs_hash *hs, struct cfs_hash_bd *bd,
const void *key, struct hlist_node *hnode,
- cfs_hash_lookup_intent_t intent)
+ enum cfs_hash_lookup_intent intent)
{
- struct hlist_head *hhead = cfs_hash_bd_hhead(hs, bd);
- struct hlist_node *ehnode;
- struct hlist_node *match;
- int intent_add = (intent & CFS_HS_LOOKUP_MASK_ADD) != 0;
+ struct hlist_head *hhead = cfs_hash_bd_hhead(hs, bd);
+ struct hlist_node *ehnode;
+ struct hlist_node *match;
+ int intent_add = (intent & CFS_HS_LOOKUP_MASK_ADD) != 0;
/* with this function, we can avoid a lot of useless refcount ops,
* which are expensive atomic operations most time. */
@@ -656,7 +664,8 @@ cfs_hash_bd_lookup_intent(struct cfs_hash *hs, struct cfs_hash_bd *bd,
}
struct hlist_node *
-cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const void *key)
+cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ const void *key)
{
return cfs_hash_bd_lookup_intent(hs, bd, key, NULL,
CFS_HS_LOOKUP_IT_FIND);
@@ -664,40 +673,20 @@ cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const voi
EXPORT_SYMBOL(cfs_hash_bd_lookup_locked);
struct hlist_node *
-cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const void *key)
+cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
+ const void *key)
{
return cfs_hash_bd_lookup_intent(hs, bd, key, NULL,
CFS_HS_LOOKUP_IT_PEEK);
}
EXPORT_SYMBOL(cfs_hash_bd_peek_locked);
-struct hlist_node *
-cfs_hash_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
- const void *key, struct hlist_node *hnode,
- int noref)
-{
- return cfs_hash_bd_lookup_intent(hs, bd, key, hnode,
- (!noref * CFS_HS_LOOKUP_MASK_REF) |
- CFS_HS_LOOKUP_IT_ADD);
-}
-EXPORT_SYMBOL(cfs_hash_bd_findadd_locked);
-
-struct hlist_node *
-cfs_hash_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
- const void *key, struct hlist_node *hnode)
-{
- /* hnode can be NULL, we find the first item with @key */
- return cfs_hash_bd_lookup_intent(hs, bd, key, hnode,
- CFS_HS_LOOKUP_IT_FINDDEL);
-}
-EXPORT_SYMBOL(cfs_hash_bd_finddel_locked);
-
static void
cfs_hash_multi_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds,
unsigned n, int excl)
{
struct cfs_hash_bucket *prev = NULL;
- int i;
+ int i;
/**
* bds must be ascendantly ordered by bd->bd_bucket->hsb_index.
@@ -720,7 +709,7 @@ cfs_hash_multi_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds,
unsigned n, int excl)
{
struct cfs_hash_bucket *prev = NULL;
- int i;
+ int i;
cfs_hash_for_each_bd(bds, n, i) {
if (prev != bds[i].bd_bucket) {
@@ -734,8 +723,8 @@ static struct hlist_node *
cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
unsigned n, const void *key)
{
- struct hlist_node *ehnode;
- unsigned i;
+ struct hlist_node *ehnode;
+ unsigned i;
cfs_hash_for_each_bd(bds, n, i) {
ehnode = cfs_hash_bd_lookup_intent(hs, &bds[i], key, NULL,
@@ -747,13 +736,13 @@ cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
}
static struct hlist_node *
-cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs,
- struct cfs_hash_bd *bds, unsigned n, const void *key,
+cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
+ unsigned n, const void *key,
struct hlist_node *hnode, int noref)
{
- struct hlist_node *ehnode;
- int intent;
- unsigned i;
+ struct hlist_node *ehnode;
+ int intent;
+ unsigned i;
LASSERT(hnode != NULL);
intent = (!noref * CFS_HS_LOOKUP_MASK_REF) | CFS_HS_LOOKUP_IT_PEEK;
@@ -768,7 +757,7 @@ cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs,
if (i == 1) { /* only one bucket */
cfs_hash_bd_add_locked(hs, &bds[0], hnode);
} else {
- struct cfs_hash_bd mybd;
+ struct cfs_hash_bd mybd;
cfs_hash_bd_get(hs, key, &mybd);
cfs_hash_bd_add_locked(hs, &mybd, hnode);
@@ -782,8 +771,8 @@ cfs_hash_multi_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
unsigned n, const void *key,
struct hlist_node *hnode)
{
- struct hlist_node *ehnode;
- unsigned i;
+ struct hlist_node *ehnode;
+ unsigned int i;
cfs_hash_for_each_bd(bds, n, i) {
ehnode = cfs_hash_bd_lookup_intent(hs, &bds[i], key, hnode,
@@ -797,7 +786,7 @@ cfs_hash_multi_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
static void
cfs_hash_bd_order(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2)
{
- int rc;
+ int rc;
if (bd2->bd_bucket == NULL)
return;
@@ -822,7 +811,8 @@ cfs_hash_bd_order(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2)
}
void
-cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bds)
+cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key,
+ struct cfs_hash_bd *bds)
{
/* NB: caller should hold hs_lock.rw if REHASH is set */
cfs_hash_bd_from_key(hs, hs->hs_buckets,
@@ -839,21 +829,18 @@ cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *b
cfs_hash_bd_order(&bds[0], &bds[1]);
}
-EXPORT_SYMBOL(cfs_hash_dual_bd_get);
void
cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl)
{
cfs_hash_multi_bd_lock(hs, bds, 2, excl);
}
-EXPORT_SYMBOL(cfs_hash_dual_bd_lock);
void
cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl)
{
cfs_hash_multi_bd_unlock(hs, bds, 2, excl);
}
-EXPORT_SYMBOL(cfs_hash_dual_bd_unlock);
struct hlist_node *
cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
@@ -861,7 +848,6 @@ cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
{
return cfs_hash_multi_bd_lookup_locked(hs, bds, 2, key);
}
-EXPORT_SYMBOL(cfs_hash_dual_bd_lookup_locked);
struct hlist_node *
cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
@@ -871,7 +857,6 @@ cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
return cfs_hash_multi_bd_findadd_locked(hs, bds, 2, key,
hnode, noref);
}
-EXPORT_SYMBOL(cfs_hash_dual_bd_findadd_locked);
struct hlist_node *
cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
@@ -879,13 +864,12 @@ cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
{
return cfs_hash_multi_bd_finddel_locked(hs, bds, 2, key, hnode);
}
-EXPORT_SYMBOL(cfs_hash_dual_bd_finddel_locked);
static void
cfs_hash_buckets_free(struct cfs_hash_bucket **buckets,
int bkt_size, int prev_size, int size)
{
- int i;
+ int i;
for (i = prev_size; i < size; i++) {
if (buckets[i] != NULL)
@@ -905,7 +889,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
unsigned int old_size, unsigned int new_size)
{
struct cfs_hash_bucket **new_bkts;
- int i;
+ int i;
LASSERT(old_size == 0 || old_bkts != NULL);
@@ -923,7 +907,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
for (i = old_size; i < new_size; i++) {
struct hlist_head *hhead;
- struct cfs_hash_bd bd;
+ struct cfs_hash_bd bd;
LIBCFS_ALLOC(new_bkts[i], cfs_hash_bkt_size(hs));
if (new_bkts[i] == NULL) {
@@ -960,7 +944,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
* @max_bits - Maximum allowed hash table resize, in bits
* @ops - Registered hash table operations
* @flags - CFS_HASH_REHASH enable synamic hash resizing
- * - CFS_HASH_SORT enable chained hash sort
+ * - CFS_HASH_SORT enable chained hash sort
*/
static int cfs_hash_rehash_worker(cfs_workitem_t *wi);
@@ -968,10 +952,10 @@ static int cfs_hash_rehash_worker(cfs_workitem_t *wi);
static int cfs_hash_dep_print(cfs_workitem_t *wi)
{
struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi);
- int dep;
- int bkt;
- int off;
- int bits;
+ int dep;
+ int bkt;
+ int off;
+ int bits;
spin_lock(&hs->hs_dep_lock);
dep = hs->hs_dep_max;
@@ -1019,10 +1003,10 @@ struct cfs_hash *
cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
unsigned bkt_bits, unsigned extra_bytes,
unsigned min_theta, unsigned max_theta,
- cfs_hash_ops_t *ops, unsigned flags)
+ struct cfs_hash_ops *ops, unsigned flags)
{
struct cfs_hash *hs;
- int len;
+ int len;
CLASSERT(CFS_HASH_THETA_BITS < 15);
@@ -1053,8 +1037,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
if (hs == NULL)
return NULL;
- strncpy(hs->hs_name, name, len);
- hs->hs_name[len - 1] = '\0';
+ strlcpy(hs->hs_name, name, len);
hs->hs_flags = flags;
atomic_set(&hs->hs_refcount, 1);
@@ -1068,7 +1051,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
hs->hs_max_bits = (__u8)max_bits;
hs->hs_bkt_bits = (__u8)bkt_bits;
- hs->hs_ops = ops;
+ hs->hs_ops = ops;
hs->hs_extra_bytes = extra_bytes;
hs->hs_rehash_bits = 0;
cfs_wi_init(&hs->hs_rehash_wi, hs, cfs_hash_rehash_worker);
@@ -1093,10 +1076,10 @@ EXPORT_SYMBOL(cfs_hash_create);
static void
cfs_hash_destroy(struct cfs_hash *hs)
{
- struct hlist_node *hnode;
- struct hlist_node *pos;
- struct cfs_hash_bd bd;
- int i;
+ struct hlist_node *hnode;
+ struct hlist_node *pos;
+ struct cfs_hash_bd bd;
+ int i;
LASSERT(hs != NULL);
LASSERT(!cfs_hash_is_exiting(hs) &&
@@ -1214,8 +1197,8 @@ cfs_hash_rehash_inline(struct cfs_hash *hs)
void
cfs_hash_add(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
{
- struct cfs_hash_bd bd;
- int bits;
+ struct cfs_hash_bd bd;
+ int bits;
LASSERT(hlist_unhashed(hnode));
@@ -1239,8 +1222,8 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key,
struct hlist_node *hnode, int noref)
{
struct hlist_node *ehnode;
- struct cfs_hash_bd bds[2];
- int bits = 0;
+ struct cfs_hash_bd bds[2];
+ int bits = 0;
LASSERT(hlist_unhashed(hnode));
@@ -1252,7 +1235,7 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key,
hnode, noref);
cfs_hash_dual_bd_unlock(hs, bds, 1);
- if (ehnode == hnode) /* new item added */
+ if (ehnode == hnode) /* new item added */
bits = cfs_hash_rehash_bits(hs);
cfs_hash_unlock(hs, 0);
if (bits > 0)
@@ -1267,7 +1250,8 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key,
* Returns 0 on success or -EALREADY on key collisions.
*/
int
-cfs_hash_add_unique(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
+cfs_hash_add_unique(struct cfs_hash *hs, const void *key,
+ struct hlist_node *hnode)
{
return cfs_hash_find_or_add(hs, key, hnode, 1) != hnode ?
-EALREADY : 0;
@@ -1300,9 +1284,9 @@ EXPORT_SYMBOL(cfs_hash_findadd_unique);
void *
cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
{
- void *obj = NULL;
- int bits = 0;
- struct cfs_hash_bd bds[2];
+ void *obj = NULL;
+ int bits = 0;
+ struct cfs_hash_bd bds[2];
cfs_hash_lock(hs, 0);
cfs_hash_dual_bd_get_and_lock(hs, key, bds, 1);
@@ -1355,9 +1339,9 @@ EXPORT_SYMBOL(cfs_hash_del_key);
void *
cfs_hash_lookup(struct cfs_hash *hs, const void *key)
{
- void *obj = NULL;
- struct hlist_node *hnode;
- struct cfs_hash_bd bds[2];
+ void *obj = NULL;
+ struct hlist_node *hnode;
+ struct cfs_hash_bd bds[2];
cfs_hash_lock(hs, 0);
cfs_hash_dual_bd_get_and_lock(hs, key, bds, 0);
@@ -1374,7 +1358,8 @@ cfs_hash_lookup(struct cfs_hash *hs, const void *key)
EXPORT_SYMBOL(cfs_hash_lookup);
static void
-cfs_hash_for_each_enter(struct cfs_hash *hs) {
+cfs_hash_for_each_enter(struct cfs_hash *hs)
+{
LASSERT(!cfs_hash_is_exiting(hs));
if (!cfs_hash_with_rehash(hs))
@@ -1399,7 +1384,8 @@ cfs_hash_for_each_enter(struct cfs_hash *hs) {
}
static void
-cfs_hash_for_each_exit(struct cfs_hash *hs) {
+cfs_hash_for_each_exit(struct cfs_hash *hs)
+{
int remained;
int bits;
@@ -1430,14 +1416,15 @@ cfs_hash_for_each_exit(struct cfs_hash *hs) {
*/
static __u64
cfs_hash_for_each_tight(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
- void *data, int remove_safe) {
- struct hlist_node *hnode;
- struct hlist_node *pos;
- struct cfs_hash_bd bd;
- __u64 count = 0;
- int excl = !!remove_safe;
- int loop = 0;
- int i;
+ void *data, int remove_safe)
+{
+ struct hlist_node *hnode;
+ struct hlist_node *pos;
+ struct cfs_hash_bd bd;
+ __u64 count = 0;
+ int excl = !!remove_safe;
+ int loop = 0;
+ int i;
cfs_hash_for_each_enter(hs);
@@ -1480,16 +1467,16 @@ cfs_hash_for_each_tight(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
return count;
}
-typedef struct {
- cfs_hash_cond_opt_cb_t func;
- void *arg;
-} cfs_hash_cond_arg_t;
+struct cfs_hash_cond_arg {
+ cfs_hash_cond_opt_cb_t func;
+ void *arg;
+};
static int
cfs_hash_cond_del_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct hlist_node *hnode, void *data)
{
- cfs_hash_cond_arg_t *cond = data;
+ struct cfs_hash_cond_arg *cond = data;
if (cond->func(cfs_hash_object(hs, hnode), cond->arg))
cfs_hash_bd_del_locked(hs, bd, hnode);
@@ -1504,9 +1491,9 @@ cfs_hash_cond_del_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
void
cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data)
{
- cfs_hash_cond_arg_t arg = {
- .func = func,
- .arg = data,
+ struct cfs_hash_cond_arg arg = {
+ .func = func,
+ .arg = data,
};
cfs_hash_for_each_tight(hs, cfs_hash_cond_del_locked, &arg, 1);
@@ -1514,16 +1501,17 @@ cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data)
EXPORT_SYMBOL(cfs_hash_cond_del);
void
-cfs_hash_for_each(struct cfs_hash *hs,
- cfs_hash_for_each_cb_t func, void *data)
+cfs_hash_for_each(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
+ void *data)
{
cfs_hash_for_each_tight(hs, func, data, 0);
}
EXPORT_SYMBOL(cfs_hash_for_each);
void
-cfs_hash_for_each_safe(struct cfs_hash *hs,
- cfs_hash_for_each_cb_t func, void *data) {
+cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
+ void *data)
+{
cfs_hash_for_each_tight(hs, func, data, 1);
}
EXPORT_SYMBOL(cfs_hash_for_each_safe);
@@ -1572,15 +1560,16 @@ EXPORT_SYMBOL(cfs_hash_size_get);
*/
static int
cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
- void *data) {
+ void *data)
+{
struct hlist_node *hnode;
struct hlist_node *tmp;
- struct cfs_hash_bd bd;
- __u32 version;
- int count = 0;
- int stop_on_change;
- int rc;
- int i;
+ struct cfs_hash_bd bd;
+ __u32 version;
+ int count = 0;
+ int stop_on_change;
+ int rc;
+ int i;
stop_on_change = cfs_hash_with_rehash_key(hs) ||
!cfs_hash_with_no_itemref(hs) ||
@@ -1636,8 +1625,9 @@ cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
}
int
-cfs_hash_for_each_nolock(struct cfs_hash *hs,
- cfs_hash_for_each_cb_t func, void *data) {
+cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
+ void *data)
+{
if (cfs_hash_with_no_lock(hs) ||
cfs_hash_with_rehash_key(hs) ||
!cfs_hash_with_no_itemref(hs))
@@ -1668,9 +1658,10 @@ EXPORT_SYMBOL(cfs_hash_for_each_nolock);
* the required locking is in place to prevent concurrent insertions.
*/
int
-cfs_hash_for_each_empty(struct cfs_hash *hs,
- cfs_hash_for_each_cb_t func, void *data) {
- unsigned i = 0;
+cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
+ void *data)
+{
+ unsigned i = 0;
if (cfs_hash_with_no_lock(hs))
return -EOPNOTSUPP;
@@ -1694,9 +1685,9 @@ void
cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex,
cfs_hash_for_each_cb_t func, void *data)
{
- struct hlist_head *hhead;
- struct hlist_node *hnode;
- struct cfs_hash_bd bd;
+ struct hlist_head *hhead;
+ struct hlist_node *hnode;
+ struct cfs_hash_bd bd;
cfs_hash_for_each_enter(hs);
cfs_hash_lock(hs, 0);
@@ -1712,7 +1703,7 @@ cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex,
break;
}
cfs_hash_bd_unlock(hs, &bd, 0);
- out:
+out:
cfs_hash_unlock(hs, 0);
cfs_hash_for_each_exit(hs);
}
@@ -1727,10 +1718,11 @@ EXPORT_SYMBOL(cfs_hash_hlist_for_each);
*/
void
cfs_hash_for_each_key(struct cfs_hash *hs, const void *key,
- cfs_hash_for_each_cb_t func, void *data) {
- struct hlist_node *hnode;
- struct cfs_hash_bd bds[2];
- unsigned i;
+ cfs_hash_for_each_cb_t func, void *data)
+{
+ struct hlist_node *hnode;
+ struct cfs_hash_bd bds[2];
+ unsigned int i;
cfs_hash_lock(hs, 0);
@@ -1768,7 +1760,7 @@ EXPORT_SYMBOL(cfs_hash_for_each_key);
void
cfs_hash_rehash_cancel_locked(struct cfs_hash *hs)
{
- int i;
+ int i;
/* need hold cfs_hash_lock(hs, 1) */
LASSERT(cfs_hash_with_rehash(hs) &&
@@ -1792,7 +1784,6 @@ cfs_hash_rehash_cancel_locked(struct cfs_hash *hs)
cfs_hash_lock(hs, 1);
}
}
-EXPORT_SYMBOL(cfs_hash_rehash_cancel_locked);
void
cfs_hash_rehash_cancel(struct cfs_hash *hs)
@@ -1801,12 +1792,11 @@ cfs_hash_rehash_cancel(struct cfs_hash *hs)
cfs_hash_rehash_cancel_locked(hs);
cfs_hash_unlock(hs, 1);
}
-EXPORT_SYMBOL(cfs_hash_rehash_cancel);
int
cfs_hash_rehash(struct cfs_hash *hs, int do_rehash)
{
- int rc;
+ int rc;
LASSERT(cfs_hash_with_rehash(hs) && !cfs_hash_with_no_lock(hs));
@@ -1831,17 +1821,16 @@ cfs_hash_rehash(struct cfs_hash *hs, int do_rehash)
return cfs_hash_rehash_worker(&hs->hs_rehash_wi);
}
-EXPORT_SYMBOL(cfs_hash_rehash);
static int
cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old)
{
- struct cfs_hash_bd new;
- struct hlist_head *hhead;
- struct hlist_node *hnode;
- struct hlist_node *pos;
- void *key;
- int c = 0;
+ struct cfs_hash_bd new;
+ struct hlist_head *hhead;
+ struct hlist_node *hnode;
+ struct hlist_node *pos;
+ void *key;
+ int c = 0;
/* hold cfs_hash_lock(hs, 1), so don't need any bucket lock */
cfs_hash_bd_for_each_hlist(hs, old, hhead) {
@@ -1867,17 +1856,17 @@ cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old)
static int
cfs_hash_rehash_worker(cfs_workitem_t *wi)
{
- struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_rehash_wi);
+ struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_rehash_wi);
struct cfs_hash_bucket **bkts;
- struct cfs_hash_bd bd;
- unsigned int old_size;
- unsigned int new_size;
- int bsize;
- int count = 0;
- int rc = 0;
- int i;
+ struct cfs_hash_bd bd;
+ unsigned int old_size;
+ unsigned int new_size;
+ int bsize;
+ int count = 0;
+ int rc = 0;
+ int i;
- LASSERT (hs != NULL && cfs_hash_with_rehash(hs));
+ LASSERT(hs != NULL && cfs_hash_with_rehash(hs));
cfs_hash_lock(hs, 0);
LASSERT(cfs_hash_is_rehashing(hs));
@@ -1949,7 +1938,7 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi)
hs->hs_rehash_buckets = NULL;
hs->hs_cur_bits = hs->hs_rehash_bits;
- out:
+out:
hs->hs_rehash_bits = 0;
if (rc == -ESRCH) /* never be scheduled again */
cfs_wi_exit(cfs_sched_rehash, wi);
@@ -1977,9 +1966,9 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi)
void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key,
void *new_key, struct hlist_node *hnode)
{
- struct cfs_hash_bd bds[3];
- struct cfs_hash_bd old_bds[2];
- struct cfs_hash_bd new_bd;
+ struct cfs_hash_bd bds[3];
+ struct cfs_hash_bd old_bds[2];
+ struct cfs_hash_bd new_bd;
LASSERT(!hlist_unhashed(hnode));
@@ -2005,7 +1994,7 @@ void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key,
}
/* overwrite key inside locks, otherwise may screw up with
* other operations, i.e: rehash */
- cfs_hash_keycpy(hs, new_key, hnode);
+ cfs_hash_keycpy(hs, hnode, new_key);
cfs_hash_multi_bd_unlock(hs, bds, 3, 1);
cfs_hash_unlock(hs, 0);
@@ -2045,12 +2034,12 @@ cfs_hash_full_nbkt(struct cfs_hash *hs)
void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m)
{
- int dist[8] = { 0, };
- int maxdep = -1;
- int maxdepb = -1;
- int total = 0;
- int theta;
- int i;
+ int dist[8] = { 0, };
+ int maxdep = -1;
+ int maxdepb = -1;
+ int total = 0;
+ int theta;
+ int i;
cfs_hash_lock(hs, 0);
theta = __cfs_hash_theta(hs);
@@ -2076,11 +2065,11 @@ void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m)
* If you hash function results in a non-uniform hash the will
* be observable by outlier bucks in the distribution histogram.
*
- * Uniform hash distribution: 128/128/0/0/0/0/0/0
- * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1
+ * Uniform hash distribution: 128/128/0/0/0/0/0/0
+ * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1
*/
for (i = 0; i < cfs_hash_full_nbkt(hs); i++) {
- struct cfs_hash_bd bd;
+ struct cfs_hash_bd bd;
bd.bd_bucket = cfs_hash_full_bkts(hs)[i];
cfs_hash_bd_lock(hs, &bd, 0);
diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
index ad661a33a211..d8230aec9a2b 100644
--- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
+++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
@@ -110,7 +110,8 @@ static DECLARE_RWSEM(kg_sem);
* @param uid identifier for this receiver
* @param group group number
*/
-int libcfs_kkuc_group_add(struct file *filp, int uid, int group, __u32 data)
+int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group,
+ __u32 data)
{
struct kkuc_reg *reg;
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c b/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
index f4e08daba4d9..27cf86106363 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
@@ -134,7 +134,6 @@ cfs_percpt_current(void *vars)
return arr->va_ptrs[cpt];
}
-EXPORT_SYMBOL(cfs_percpt_current);
void *
cfs_percpt_index(void *vars, int idx)
@@ -146,7 +145,6 @@ cfs_percpt_index(void *vars, int idx)
LASSERT(idx >= 0 && idx < arr->va_count);
return arr->va_ptrs[idx];
}
-EXPORT_SYMBOL(cfs_percpt_index);
/*
* free variable array, see more detail in cfs_array_alloc
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
index efe5e667a2e5..d40be5396769 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
@@ -214,6 +214,7 @@ cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res)
res->ls_len = end - res->ls_str + 1;
return 1;
}
+EXPORT_SYMBOL(cfs_gettok);
/**
* Converts string to integer.
@@ -242,6 +243,7 @@ cfs_str2num_check(char *str, int nob, unsigned *num,
return (*num >= min && *num <= max);
}
+EXPORT_SYMBOL(cfs_str2num_check);
/**
* Parses \<range_expr\> token of the syntax. If \a bracketed is false,
@@ -321,6 +323,73 @@ cfs_range_expr_parse(struct cfs_lstr *src, unsigned min, unsigned max,
}
/**
+ * Print the range expression \a re into specified \a buffer.
+ * If \a bracketed is true, expression does not need additional
+ * brackets.
+ *
+ * \retval number of characters written
+ */
+static int
+cfs_range_expr_print(char *buffer, int count, struct cfs_range_expr *expr,
+ bool bracketed)
+{
+ int i;
+ char s[] = "[";
+ char e[] = "]";
+
+ if (bracketed)
+ s[0] = e[0] = '\0';
+
+ if (expr->re_lo == expr->re_hi)
+ i = scnprintf(buffer, count, "%u", expr->re_lo);
+ else if (expr->re_stride == 1)
+ i = scnprintf(buffer, count, "%s%u-%u%s",
+ s, expr->re_lo, expr->re_hi, e);
+ else
+ i = scnprintf(buffer, count, "%s%u-%u/%u%s",
+ s, expr->re_lo, expr->re_hi,
+ expr->re_stride, e);
+ return i;
+}
+
+/**
+ * Print a list of range expressions (\a expr_list) into specified \a buffer.
+ * If the list contains several expressions, separate them with comma
+ * and surround the list with brackets.
+ *
+ * \retval number of characters written
+ */
+int
+cfs_expr_list_print(char *buffer, int count, struct cfs_expr_list *expr_list)
+{
+ struct cfs_range_expr *expr;
+ int i = 0, j = 0;
+ int numexprs = 0;
+
+ if (count <= 0)
+ return 0;
+
+ list_for_each_entry(expr, &expr_list->el_exprs, re_link)
+ numexprs++;
+
+ if (numexprs > 1)
+ i += scnprintf(buffer + i, count - i, "[");
+
+ list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+ if (j++ != 0)
+ i += scnprintf(buffer + i, count - i, ",");
+ i += cfs_range_expr_print(buffer + i, count - i, expr,
+ numexprs > 1);
+ }
+
+ if (numexprs > 1)
+ i += scnprintf(buffer + i, count - i, "]");
+
+ return i;
+}
+EXPORT_SYMBOL(cfs_expr_list_print);
+
+/**
* Matches value (\a value) against ranges expression list \a expr_list.
*
* \retval 1 if \a value matches
@@ -339,6 +408,7 @@ cfs_expr_list_match(__u32 value, struct cfs_expr_list *expr_list)
return 0;
}
+EXPORT_SYMBOL(cfs_expr_list_match);
/**
* Convert express list (\a expr_list) to an array of all matched values
@@ -412,8 +482,8 @@ EXPORT_SYMBOL(cfs_expr_list_free);
/**
* Parses \<cfs_expr_list\> token of the syntax.
*
- * \retval 1 if \a str parses to \<number\> | \<expr_list\>
- * \retval 0 otherwise
+ * \retval 0 if \a str parses to \<number\> | \<expr_list\>
+ * \retval -errno otherwise
*/
int
cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
@@ -491,72 +561,4 @@ cfs_expr_list_free_list(struct list_head *list)
cfs_expr_list_free(el);
}
}
-
-int
-cfs_ip_addr_parse(char *str, int len, struct list_head *list)
-{
- struct cfs_expr_list *el;
- struct cfs_lstr src;
- int rc;
- int i;
-
- src.ls_str = str;
- src.ls_len = len;
- i = 0;
-
- while (src.ls_str != NULL) {
- struct cfs_lstr res;
-
- if (!cfs_gettok(&src, '.', &res)) {
- rc = -EINVAL;
- goto out;
- }
-
- rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el);
- if (rc != 0)
- goto out;
-
- list_add_tail(&el->el_link, list);
- i++;
- }
-
- if (i == 4)
- return 0;
-
- rc = -EINVAL;
- out:
- cfs_expr_list_free_list(list);
-
- return rc;
-}
-EXPORT_SYMBOL(cfs_ip_addr_parse);
-
-/**
- * Matches address (\a addr) against address set encoded in \a list.
- *
- * \retval 1 if \a addr matches
- * \retval 0 otherwise
- */
-int
-cfs_ip_addr_match(__u32 addr, struct list_head *list)
-{
- struct cfs_expr_list *el;
- int i = 0;
-
- list_for_each_entry_reverse(el, list, el_link) {
- if (!cfs_expr_list_match(addr & 0xff, el))
- return 0;
- addr >>= 8;
- i++;
- }
-
- return i == 4;
-}
-EXPORT_SYMBOL(cfs_ip_addr_match);
-
-void
-cfs_ip_addr_free(struct list_head *list)
-{
- cfs_expr_list_free_list(list);
-}
-EXPORT_SYMBOL(cfs_ip_addr_free);
+EXPORT_SYMBOL(cfs_expr_list_free_list);
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
index 209736454d06..58a4034be1b8 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
@@ -78,23 +78,6 @@ struct cfs_cpt_data {
static struct cfs_cpt_data cpt_data;
-static void cfs_cpu_core_siblings(int cpu, cpumask_t *mask)
-{
- /* return cpumask of cores in the same socket */
- cpumask_copy(mask, topology_core_cpumask(cpu));
-}
-
-/* return cpumask of HTs in the same core */
-static void cfs_cpu_ht_siblings(int cpu, cpumask_t *mask)
-{
- cpumask_copy(mask, topology_sibling_cpumask(cpu));
-}
-
-static void cfs_node_to_cpumask(int node, cpumask_t *mask)
-{
- cpumask_copy(mask, cpumask_of_node(node));
-}
-
void
cfs_cpt_table_free(struct cfs_cpt_table *cptab)
{
@@ -426,7 +409,7 @@ cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt, int node)
mutex_lock(&cpt_data.cpt_mutex);
mask = cpt_data.cpt_cpumask;
- cfs_node_to_cpumask(node, mask);
+ cpumask_copy(mask, cpumask_of_node(node));
rc = cfs_cpt_set_cpumask(cptab, cpt, mask);
@@ -450,7 +433,7 @@ cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node)
mutex_lock(&cpt_data.cpt_mutex);
mask = cpt_data.cpt_cpumask;
- cfs_node_to_cpumask(node, mask);
+ cpumask_copy(mask, cpumask_of_node(node));
cfs_cpt_unset_cpumask(cptab, cpt, mask);
@@ -643,7 +626,7 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
cpu = cpumask_first(node);
/* get cpumask for cores in the same socket */
- cfs_cpu_core_siblings(cpu, socket);
+ cpumask_copy(socket, topology_core_cpumask(cpu));
cpumask_and(socket, socket, node);
LASSERT(!cpumask_empty(socket));
@@ -652,7 +635,7 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
int i;
/* get cpumask for hts in the same core */
- cfs_cpu_ht_siblings(cpu, core);
+ cpumask_copy(core, topology_sibling_cpumask(cpu));
cpumask_and(core, core, node);
LASSERT(!cpumask_empty(core));
@@ -769,7 +752,7 @@ cfs_cpt_table_create(int ncpt)
}
for_each_online_node(i) {
- cfs_node_to_cpumask(i, mask);
+ cpumask_copy(mask, cpumask_of_node(i));
while (!cpumask_empty(mask)) {
struct cfs_cpu_partition *part;
@@ -968,7 +951,8 @@ cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
mutex_lock(&cpt_data.cpt_mutex);
/* if all HTs in a core are offline, it may break affinity */
- cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask);
+ cpumask_copy(cpt_data.cpt_cpumask,
+ topology_sibling_cpumask(cpu));
warn = cpumask_any_and(cpt_data.cpt_cpumask,
cpu_online_mask) >= nr_cpu_ids;
mutex_unlock(&cpt_data.cpt_mutex);
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c
index 5d8d8b79fa1f..db0572733712 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c
@@ -37,11 +37,6 @@
#define CHKSUM_BLOCK_SIZE 1
#define CHKSUM_DIGEST_SIZE 4
-static u32 __adler32(u32 cksum, unsigned char const *p, size_t len)
-{
- return zlib_adler32(cksum, p, len);
-}
-
static int adler32_cra_init(struct crypto_tfm *tfm)
{
u32 *key = crypto_tfm_ctx(tfm);
@@ -79,14 +74,14 @@ static int adler32_update(struct shash_desc *desc, const u8 *data,
{
u32 *cksump = shash_desc_ctx(desc);
- *cksump = __adler32(*cksump, data, len);
+ *cksump = zlib_adler32(*cksump, data, len);
return 0;
}
static int __adler32_finup(u32 *cksump, const u8 *data, unsigned int len,
u8 *out)
{
- *(u32 *)out = __adler32(*cksump, data, len);
+ *(u32 *)out = zlib_adler32(*cksump, data, len);
return 0;
}
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
index 8689ea757c99..59c7bf3cbc1f 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
@@ -195,6 +195,5 @@ void libcfs_unregister_panic_notifier(void)
atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier);
}
-EXPORT_SYMBOL(libcfs_run_upcall);
EXPORT_SYMBOL(libcfs_run_lbug_upcall);
EXPORT_SYMBOL(lbug_with_loc);
diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c
index 0d9b223e71d6..96d9d4651a51 100644
--- a/drivers/staging/lustre/lustre/libcfs/module.c
+++ b/drivers/staging/lustre/lustre/libcfs/module.c
@@ -62,7 +62,7 @@
#include "../../include/linux/lnet/lnet.h"
#include "tracefile.h"
-MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Portals v3.1");
MODULE_LICENSE("GPL");
@@ -319,7 +319,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *a
struct libcfs_ioctl_data *data;
int err = 0;
- LIBCFS_ALLOC_GFP(buf, 1024, GFP_IOFS);
+ LIBCFS_ALLOC_GFP(buf, 1024, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
@@ -392,7 +392,7 @@ static int __proc_dobitmasks(void *data, int write,
} else {
rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
if (rc < 0) {
- cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
+ kfree(tmpstr);
return rc;
}
@@ -402,7 +402,7 @@ static int __proc_dobitmasks(void *data, int write,
*mask |= D_EMERG;
}
- cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
+ kfree(tmpstr);
return rc;
}
@@ -701,8 +701,6 @@ static int init_libcfs_module(void)
{
int rc;
- libcfs_init_nidstrings();
-
rc = libcfs_debug_init(5 * 1024 * 1024);
if (rc < 0) {
pr_err("LustreError: libcfs_debug_init: %d\n", rc);
diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c
deleted file mode 100644
index 087449f4e6c1..000000000000
--- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be 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 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/libcfs/nidstrings.c
- *
- * Author: Phil Schwan <phil@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include "../../include/linux/libcfs/libcfs.h"
-#include "../../include/linux/lnet/lnet.h"
-
-/* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
- * consistent in all conversion functions. Some code fragments are copied
- * around for the sake of clarity...
- */
-
-/* CAVEAT EMPTOR! Racey temporary buffer allocation!
- * Choose the number of nidstrings to support the MAXIMUM expected number of
- * concurrent users. If there are more, the returned string will be volatile.
- * NB this number must allow for a process to be descheduled for a timeslice
- * between getting its string and using it.
- */
-
-static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
-static int libcfs_nidstring_idx;
-
-static spinlock_t libcfs_nidstring_lock;
-
-void libcfs_init_nidstrings(void)
-{
- spin_lock_init(&libcfs_nidstring_lock);
-}
-
-static char *
-libcfs_next_nidstring(void)
-{
- char *str;
- unsigned long flags;
-
- spin_lock_irqsave(&libcfs_nidstring_lock, flags);
-
- str = libcfs_nidstrings[libcfs_nidstring_idx++];
- if (libcfs_nidstring_idx == ARRAY_SIZE(libcfs_nidstrings))
- libcfs_nidstring_idx = 0;
-
- spin_unlock_irqrestore(&libcfs_nidstring_lock, flags);
- return str;
-}
-
-static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
-{
- *addr = 0;
- return 1;
-}
-
-static void libcfs_ip_addr2str(__u32 addr, char *str)
-{
- snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff);
-}
-
-static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
-{
- unsigned int a;
- unsigned int b;
- unsigned int c;
- unsigned int d;
- int n = nob; /* XscanfX */
-
- /* numeric IP? */
- if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
- n == nob &&
- (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
- (c & ~0xff) == 0 && (d & ~0xff) == 0) {
- *addr = ((a<<24)|(b<<16)|(c<<8)|d);
- return 1;
- }
-
- return 0;
-}
-
-static void libcfs_decnum_addr2str(__u32 addr, char *str)
-{
- snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
-}
-
-static void libcfs_hexnum_addr2str(__u32 addr, char *str)
-{
- snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
-}
-
-static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
-{
- int n;
-
- n = nob;
- if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
- return 1;
-
- n = nob;
- if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
- return 1;
-
- n = nob;
- if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
- return 1;
-
- return 0;
-}
-
-/**
- * Nf_parse_addrlist method for networks using numeric addresses.
- *
- * Examples of such networks are gm and elan.
- *
- * \retval 0 if \a str parsed to numeric address
- * \retval errno otherwise
- */
-static int
-libcfs_num_parse(char *str, int len, struct list_head *list)
-{
- struct cfs_expr_list *el;
- int rc;
-
- rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
- if (rc == 0)
- list_add_tail(&el->el_link, list);
-
- return rc;
-}
-
-/*
- * Nf_match_addr method for networks using numeric addresses
- *
- * \retval 1 on match
- * \retval 0 otherwise
- */
-static int
-libcfs_num_match(__u32 addr, struct list_head *numaddr)
-{
- struct cfs_expr_list *el;
-
- LASSERT(!list_empty(numaddr));
- el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
-
- return cfs_expr_list_match(addr, el);
-}
-
-struct netstrfns {
- int nf_type;
- char *nf_name;
- char *nf_modname;
- void (*nf_addr2str)(__u32 addr, char *str);
- int (*nf_str2addr)(const char *str, int nob, __u32 *addr);
- int (*nf_parse_addrlist)(char *str, int len,
- struct list_head *list);
- int (*nf_match_addr)(__u32 addr, struct list_head *list);
-};
-
-static struct netstrfns libcfs_netstrfns[] = {
- {/* .nf_type */ LOLND,
- /* .nf_name */ "lo",
- /* .nf_modname */ "klolnd",
- /* .nf_addr2str */ libcfs_decnum_addr2str,
- /* .nf_str2addr */ libcfs_lo_str2addr,
- /* .nf_parse_addr*/ libcfs_num_parse,
- /* .nf_match_addr*/ libcfs_num_match},
- {/* .nf_type */ SOCKLND,
- /* .nf_name */ "tcp",
- /* .nf_modname */ "ksocklnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ O2IBLND,
- /* .nf_name */ "o2ib",
- /* .nf_modname */ "ko2iblnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ CIBLND,
- /* .nf_name */ "cib",
- /* .nf_modname */ "kciblnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ OPENIBLND,
- /* .nf_name */ "openib",
- /* .nf_modname */ "kopeniblnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ IIBLND,
- /* .nf_name */ "iib",
- /* .nf_modname */ "kiiblnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ VIBLND,
- /* .nf_name */ "vib",
- /* .nf_modname */ "kviblnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ RALND,
- /* .nf_name */ "ra",
- /* .nf_modname */ "kralnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ QSWLND,
- /* .nf_name */ "elan",
- /* .nf_modname */ "kqswlnd",
- /* .nf_addr2str */ libcfs_decnum_addr2str,
- /* .nf_str2addr */ libcfs_num_str2addr,
- /* .nf_parse_addrlist*/ libcfs_num_parse,
- /* .nf_match_addr*/ libcfs_num_match},
- {/* .nf_type */ GMLND,
- /* .nf_name */ "gm",
- /* .nf_modname */ "kgmlnd",
- /* .nf_addr2str */ libcfs_hexnum_addr2str,
- /* .nf_str2addr */ libcfs_num_str2addr,
- /* .nf_parse_addrlist*/ libcfs_num_parse,
- /* .nf_match_addr*/ libcfs_num_match},
- {/* .nf_type */ MXLND,
- /* .nf_name */ "mx",
- /* .nf_modname */ "kmxlnd",
- /* .nf_addr2str */ libcfs_ip_addr2str,
- /* .nf_str2addr */ libcfs_ip_str2addr,
- /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
- /* .nf_match_addr*/ cfs_ip_addr_match},
- {/* .nf_type */ PTLLND,
- /* .nf_name */ "ptl",
- /* .nf_modname */ "kptllnd",
- /* .nf_addr2str */ libcfs_decnum_addr2str,
- /* .nf_str2addr */ libcfs_num_str2addr,
- /* .nf_parse_addrlist*/ libcfs_num_parse,
- /* .nf_match_addr*/ libcfs_num_match},
- {/* .nf_type */ GNILND,
- /* .nf_name */ "gni",
- /* .nf_modname */ "kgnilnd",
- /* .nf_addr2str */ libcfs_decnum_addr2str,
- /* .nf_str2addr */ libcfs_num_str2addr,
- /* .nf_parse_addrlist*/ libcfs_num_parse,
- /* .nf_match_addr*/ libcfs_num_match},
- /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */
- {/* .nf_type */ -1},
-};
-
-static const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns);
-
-/* CAVEAT EMPTOR XscanfX
- * I use "%n" at the end of a sscanf format to detect trailing junk. However
- * sscanf may return immediately if it sees the terminating '0' in a string, so
- * I initialise the %n variable to the expected length. If sscanf sets it;
- * fine, if it doesn't, then the scan ended at the end of the string, which is
- * fine too :) */
-
-static struct netstrfns *
-libcfs_lnd2netstrfns(int lnd)
-{
- int i;
-
- if (lnd >= 0)
- for (i = 0; i < libcfs_nnetstrfns; i++)
- if (lnd == libcfs_netstrfns[i].nf_type)
- return &libcfs_netstrfns[i];
-
- return NULL;
-}
-
-static struct netstrfns *
-libcfs_namenum2netstrfns(const char *name)
-{
- struct netstrfns *nf;
- int i;
-
- for (i = 0; i < libcfs_nnetstrfns; i++) {
- nf = &libcfs_netstrfns[i];
- if (nf->nf_type >= 0 &&
- !strncmp(name, nf->nf_name, strlen(nf->nf_name)))
- return nf;
- }
- return NULL;
-}
-
-static struct netstrfns *
-libcfs_name2netstrfns(const char *name)
-{
- int i;
-
- for (i = 0; i < libcfs_nnetstrfns; i++)
- if (libcfs_netstrfns[i].nf_type >= 0 &&
- !strcmp(libcfs_netstrfns[i].nf_name, name))
- return &libcfs_netstrfns[i];
-
- return NULL;
-}
-
-int
-libcfs_isknown_lnd(int type)
-{
- return libcfs_lnd2netstrfns(type) != NULL;
-}
-EXPORT_SYMBOL(libcfs_isknown_lnd);
-
-char *
-libcfs_lnd2modname(int lnd)
-{
- struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
-
- return (nf == NULL) ? NULL : nf->nf_modname;
-}
-EXPORT_SYMBOL(libcfs_lnd2modname);
-
-char *
-libcfs_lnd2str(int lnd)
-{
- char *str;
- struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
-
- if (nf != NULL)
- return nf->nf_name;
-
- str = libcfs_next_nidstring();
- snprintf(str, LNET_NIDSTR_SIZE, "?%d?", lnd);
- return str;
-}
-EXPORT_SYMBOL(libcfs_lnd2str);
-
-int
-libcfs_str2lnd(const char *str)
-{
- struct netstrfns *nf = libcfs_name2netstrfns(str);
-
- if (nf != NULL)
- return nf->nf_type;
-
- return -1;
-}
-EXPORT_SYMBOL(libcfs_str2lnd);
-
-char *
-libcfs_net2str(__u32 net)
-{
- int lnd = LNET_NETTYP(net);
- int num = LNET_NETNUM(net);
- struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
- char *str = libcfs_next_nidstring();
-
- if (nf == NULL)
- snprintf(str, LNET_NIDSTR_SIZE, "<%d:%d>", lnd, num);
- else if (num == 0)
- snprintf(str, LNET_NIDSTR_SIZE, "%s", nf->nf_name);
- else
- snprintf(str, LNET_NIDSTR_SIZE, "%s%d", nf->nf_name, num);
-
- return str;
-}
-EXPORT_SYMBOL(libcfs_net2str);
-
-char *
-libcfs_nid2str(lnet_nid_t nid)
-{
- __u32 addr = LNET_NIDADDR(nid);
- __u32 net = LNET_NIDNET(nid);
- int lnd = LNET_NETTYP(net);
- int nnum = LNET_NETNUM(net);
- struct netstrfns *nf;
- char *str;
- int nob;
-
- if (nid == LNET_NID_ANY)
- return "<?>";
-
- nf = libcfs_lnd2netstrfns(lnd);
- str = libcfs_next_nidstring();
-
- if (nf == NULL)
- snprintf(str, LNET_NIDSTR_SIZE, "%x@<%d:%d>", addr, lnd, nnum);
- else {
- nf->nf_addr2str(addr, str);
- nob = strlen(str);
- if (nnum == 0)
- snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s",
- nf->nf_name);
- else
- snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%d",
- nf->nf_name, nnum);
- }
-
- return str;
-}
-EXPORT_SYMBOL(libcfs_nid2str);
-
-static struct netstrfns *
-libcfs_str2net_internal(const char *str, __u32 *net)
-{
- struct netstrfns *uninitialized_var(nf);
- int nob;
- unsigned int netnum;
- int i;
-
- for (i = 0; i < libcfs_nnetstrfns; i++) {
- nf = &libcfs_netstrfns[i];
- if (nf->nf_type >= 0 &&
- !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
- break;
- }
-
- if (i == libcfs_nnetstrfns)
- return NULL;
-
- nob = strlen(nf->nf_name);
-
- if (strlen(str) == (unsigned int)nob) {
- netnum = 0;
- } else {
- if (nf->nf_type == LOLND) /* net number not allowed */
- return NULL;
-
- str += nob;
- i = strlen(str);
- if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
- i != (int)strlen(str))
- return NULL;
- }
-
- *net = LNET_MKNET(nf->nf_type, netnum);
- return nf;
-}
-
-__u32
-libcfs_str2net(const char *str)
-{
- __u32 net;
-
- if (libcfs_str2net_internal(str, &net) != NULL)
- return net;
-
- return LNET_NIDNET(LNET_NID_ANY);
-}
-EXPORT_SYMBOL(libcfs_str2net);
-
-lnet_nid_t
-libcfs_str2nid(const char *str)
-{
- const char *sep = strchr(str, '@');
- struct netstrfns *nf;
- __u32 net;
- __u32 addr;
-
- if (sep != NULL) {
- nf = libcfs_str2net_internal(sep + 1, &net);
- if (nf == NULL)
- return LNET_NID_ANY;
- } else {
- sep = str + strlen(str);
- net = LNET_MKNET(SOCKLND, 0);
- nf = libcfs_lnd2netstrfns(SOCKLND);
- LASSERT(nf != NULL);
- }
-
- if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
- return LNET_NID_ANY;
-
- return LNET_MKNID(net, addr);
-}
-EXPORT_SYMBOL(libcfs_str2nid);
-
-char *
-libcfs_id2str(lnet_process_id_t id)
-{
- char *str = libcfs_next_nidstring();
-
- if (id.pid == LNET_PID_ANY) {
- snprintf(str, LNET_NIDSTR_SIZE,
- "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
- return str;
- }
-
- snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
- ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
- (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
- return str;
-}
-EXPORT_SYMBOL(libcfs_id2str);
-
-int
-libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
-{
- if (!strcmp(str, "*")) {
- *nidp = LNET_NID_ANY;
- return 1;
- }
-
- *nidp = libcfs_str2nid(str);
- return *nidp != LNET_NID_ANY;
-}
-EXPORT_SYMBOL(libcfs_str2anynid);
-
-/**
- * Nid range list syntax.
- * \verbatim
- *
- * <nidlist> :== <nidrange> [ ' ' <nidrange> ]
- * <nidrange> :== <addrrange> '@' <net>
- * <addrrange> :== '*' |
- * <ipaddr_range> |
- * <cfs_expr_list>
- * <ipaddr_range> :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
- * <cfs_expr_list>
- * <cfs_expr_list> :== <number> |
- * <expr_list>
- * <expr_list> :== '[' <range_expr> [ ',' <range_expr>] ']'
- * <range_expr> :== <number> |
- * <number> '-' <number> |
- * <number> '-' <number> '/' <number>
- * <net> :== <netname> | <netname><number>
- * <netname> :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" |
- * "vib" | "ra" | "elan" | "mx" | "ptl"
- * \endverbatim
- */
-
-/**
- * Structure to represent \<nidrange\> token of the syntax.
- *
- * One of this is created for each \<net\> parsed.
- */
-struct nidrange {
- /**
- * Link to list of this structures which is built on nid range
- * list parsing.
- */
- struct list_head nr_link;
- /**
- * List head for addrrange::ar_link.
- */
- struct list_head nr_addrranges;
- /**
- * Flag indicating that *@<net> is found.
- */
- int nr_all;
- /**
- * Pointer to corresponding element of libcfs_netstrfns.
- */
- struct netstrfns *nr_netstrfns;
- /**
- * Number of network. E.g. 5 if \<net\> is "elan5".
- */
- int nr_netnum;
-};
-
-/**
- * Structure to represent \<addrrange\> token of the syntax.
- */
-struct addrrange {
- /**
- * Link to nidrange::nr_addrranges.
- */
- struct list_head ar_link;
- /**
- * List head for cfs_expr_list::el_list.
- */
- struct list_head ar_numaddr_ranges;
-};
-
-/**
- * Parses \<addrrange\> token on the syntax.
- *
- * Allocates struct addrrange and links to \a nidrange via
- * (nidrange::nr_addrranges)
- *
- * \retval 1 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
- * \retval 0 otherwise
- */
-static int
-parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
-{
- struct addrrange *addrrange;
-
- if (src->ls_len == 1 && src->ls_str[0] == '*') {
- nidrange->nr_all = 1;
- return 1;
- }
-
- LIBCFS_ALLOC(addrrange, sizeof(struct addrrange));
- if (addrrange == NULL)
- return 0;
- list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
- INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
-
- return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str,
- src->ls_len,
- &addrrange->ar_numaddr_ranges);
-}
-
-/**
- * Finds or creates struct nidrange.
- *
- * Checks if \a src is a valid network name, looks for corresponding
- * nidrange on the ist of nidranges (\a nidlist), creates new struct
- * nidrange if it is not found.
- *
- * \retval pointer to struct nidrange matching network specified via \a src
- * \retval NULL if \a src does not match any network
- */
-static struct nidrange *
-add_nidrange(const struct cfs_lstr *src,
- struct list_head *nidlist)
-{
- struct netstrfns *nf;
- struct nidrange *nr;
- int endlen;
- unsigned netnum;
-
- if (src->ls_len >= LNET_NIDSTR_SIZE)
- return NULL;
-
- nf = libcfs_namenum2netstrfns(src->ls_str);
- if (nf == NULL)
- return NULL;
- endlen = src->ls_len - strlen(nf->nf_name);
- if (endlen == 0)
- /* network name only, e.g. "elan" or "tcp" */
- netnum = 0;
- else {
- /* e.g. "elan25" or "tcp23", refuse to parse if
- * network name is not appended with decimal or
- * hexadecimal number */
- if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
- endlen, &netnum, 0, MAX_NUMERIC_VALUE))
- return NULL;
- }
-
- list_for_each_entry(nr, nidlist, nr_link) {
- if (nr->nr_netstrfns != nf)
- continue;
- if (nr->nr_netnum != netnum)
- continue;
- return nr;
- }
-
- LIBCFS_ALLOC(nr, sizeof(struct nidrange));
- if (nr == NULL)
- return NULL;
- list_add_tail(&nr->nr_link, nidlist);
- INIT_LIST_HEAD(&nr->nr_addrranges);
- nr->nr_netstrfns = nf;
- nr->nr_all = 0;
- nr->nr_netnum = netnum;
-
- return nr;
-}
-
-/**
- * Parses \<nidrange\> token of the syntax.
- *
- * \retval 1 if \a src parses to \<addrrange\> '@' \<net\>
- * \retval 0 otherwise
- */
-static int
-parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist)
-{
- struct cfs_lstr addrrange;
- struct cfs_lstr net;
- struct cfs_lstr tmp;
- struct nidrange *nr;
-
- tmp = *src;
- if (cfs_gettok(src, '@', &addrrange) == 0)
- goto failed;
-
- if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
- goto failed;
-
- nr = add_nidrange(&net, nidlist);
- if (nr == NULL)
- goto failed;
-
- if (parse_addrange(&addrrange, nr) != 0)
- goto failed;
-
- return 1;
- failed:
- CWARN("can't parse nidrange: \"%.*s\"\n", tmp.ls_len, tmp.ls_str);
- return 0;
-}
-
-/**
- * Frees addrrange structures of \a list.
- *
- * For each struct addrrange structure found on \a list it frees
- * cfs_expr_list list attached to it and frees the addrrange itself.
- *
- * \retval none
- */
-static void
-free_addrranges(struct list_head *list)
-{
- while (!list_empty(list)) {
- struct addrrange *ar;
-
- ar = list_entry(list->next, struct addrrange, ar_link);
-
- cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
- list_del(&ar->ar_link);
- LIBCFS_FREE(ar, sizeof(struct addrrange));
- }
-}
-
-/**
- * Frees nidrange strutures of \a list.
- *
- * For each struct nidrange structure found on \a list it frees
- * addrrange list attached to it and frees the nidrange itself.
- *
- * \retval none
- */
-void
-cfs_free_nidlist(struct list_head *list)
-{
- struct list_head *pos, *next;
- struct nidrange *nr;
-
- list_for_each_safe(pos, next, list) {
- nr = list_entry(pos, struct nidrange, nr_link);
- free_addrranges(&nr->nr_addrranges);
- list_del(pos);
- LIBCFS_FREE(nr, sizeof(struct nidrange));
- }
-}
-EXPORT_SYMBOL(cfs_free_nidlist);
-
-/**
- * Parses nid range list.
- *
- * Parses with rigorous syntax and overflow checking \a str into
- * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of
- * structures and links that structure to \a nidlist. The resulting
- * list can be used to match a NID againts set of NIDS defined by \a
- * str.
- * \see cfs_match_nid
- *
- * \retval 1 on success
- * \retval 0 otherwise
- */
-int
-cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
-{
- struct cfs_lstr src;
- struct cfs_lstr res;
- int rc;
-
- src.ls_str = str;
- src.ls_len = len;
- INIT_LIST_HEAD(nidlist);
- while (src.ls_str) {
- rc = cfs_gettok(&src, ' ', &res);
- if (rc == 0) {
- cfs_free_nidlist(nidlist);
- return 0;
- }
- rc = parse_nidrange(&res, nidlist);
- if (rc == 0) {
- cfs_free_nidlist(nidlist);
- return 0;
- }
- }
- return 1;
-}
-EXPORT_SYMBOL(cfs_parse_nidlist);
-
-/**
- * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
- *
- * \see cfs_parse_nidlist()
- *
- * \retval 1 on match
- * \retval 0 otherwises
- */
-int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
-{
- struct nidrange *nr;
- struct addrrange *ar;
-
- list_for_each_entry(nr, nidlist, nr_link) {
- if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid)))
- continue;
- if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid)))
- continue;
- if (nr->nr_all)
- return 1;
- list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
- if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid),
- &ar->ar_numaddr_ranges))
- return 1;
- }
- return 0;
-}
-EXPORT_SYMBOL(cfs_match_nid);
diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c
index 973c7c209dfc..65c4f1ab0de8 100644
--- a/drivers/staging/lustre/lustre/libcfs/tracefile.c
+++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c
@@ -199,7 +199,6 @@ static void cfs_tcd_shrink(struct cfs_trace_cpu_data *tcd)
pgcount + 1, tcd->tcd_cur_pages);
INIT_LIST_HEAD(&pc.pc_pages);
- spin_lock_init(&pc.pc_lock);
list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages, linkage) {
if (pgcount-- == 0)
@@ -451,7 +450,7 @@ console:
cfs_print_to_console(&header, mask,
string_buf, needed, file, msgdata->msg_fn);
- cfs_trace_put_console_buffer(string_buf);
+ put_cpu();
}
if (cdls != NULL && cdls->cdls_count != 0) {
@@ -465,7 +464,7 @@ console:
cfs_print_to_console(&header, mask,
string_buf, needed, file, msgdata->msg_fn);
- cfs_trace_put_console_buffer(string_buf);
+ put_cpu();
cdls->cdls_count = 0;
}
@@ -522,7 +521,6 @@ static void collect_pages_on_all_cpus(struct page_collection *pc)
struct cfs_trace_cpu_data *tcd;
int i, cpu;
- spin_lock(&pc->pc_lock);
for_each_possible_cpu(cpu) {
cfs_tcd_for_each_type_lock(tcd, i, cpu) {
list_splice_init(&tcd->tcd_pages, &pc->pc_pages);
@@ -534,7 +532,6 @@ static void collect_pages_on_all_cpus(struct page_collection *pc)
}
}
}
- spin_unlock(&pc->pc_lock);
}
static void collect_pages(struct page_collection *pc)
@@ -555,7 +552,6 @@ static void put_pages_back_on_all_cpus(struct page_collection *pc)
struct cfs_trace_page *tmp;
int i, cpu;
- spin_lock(&pc->pc_lock);
for_each_possible_cpu(cpu) {
cfs_tcd_for_each_type_lock(tcd, i, cpu) {
cur_head = tcd->tcd_pages.next;
@@ -573,7 +569,6 @@ static void put_pages_back_on_all_cpus(struct page_collection *pc)
}
}
}
- spin_unlock(&pc->pc_lock);
}
static void put_pages_back(struct page_collection *pc)
@@ -592,7 +587,6 @@ static void put_pages_on_tcd_daemon_list(struct page_collection *pc,
struct cfs_trace_page *tage;
struct cfs_trace_page *tmp;
- spin_lock(&pc->pc_lock);
list_for_each_entry_safe(tage, tmp, &pc->pc_pages, linkage) {
__LASSERT_TAGE_INVARIANT(tage);
@@ -616,7 +610,6 @@ static void put_pages_on_tcd_daemon_list(struct page_collection *pc,
tcd->tcd_cur_daemon_pages--;
}
}
- spin_unlock(&pc->pc_lock);
}
static void put_pages_on_daemon_list(struct page_collection *pc)
@@ -636,8 +629,6 @@ void cfs_trace_debug_print(void)
struct cfs_trace_page *tage;
struct cfs_trace_page *tmp;
- spin_lock_init(&pc.pc_lock);
-
pc.pc_want_daemon_pages = 1;
collect_pages(&pc);
list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) {
@@ -692,7 +683,6 @@ int cfs_tracefile_dump_all_pages(char *filename)
goto out;
}
- spin_lock_init(&pc.pc_lock);
pc.pc_want_daemon_pages = 1;
collect_pages(&pc);
if (list_empty(&pc.pc_pages)) {
@@ -739,8 +729,6 @@ void cfs_trace_flush_pages(void)
struct cfs_trace_page *tage;
struct cfs_trace_page *tmp;
- spin_lock_init(&pc.pc_lock);
-
pc.pc_want_daemon_pages = 1;
collect_pages(&pc);
list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) {
@@ -810,18 +798,13 @@ int cfs_trace_allocate_string_buffer(char **str, int nob)
if (nob > 2 * PAGE_CACHE_SIZE) /* string must be "sensible" */
return -EINVAL;
- *str = kmalloc(nob, GFP_IOFS | __GFP_ZERO);
+ *str = kmalloc(nob, GFP_KERNEL | __GFP_ZERO);
if (*str == NULL)
return -ENOMEM;
return 0;
}
-void cfs_trace_free_string_buffer(char *str, int nob)
-{
- kfree(str);
-}
-
int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob)
{
char *str;
@@ -842,7 +825,7 @@ int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob)
}
rc = cfs_tracefile_dump_all_pages(str);
out:
- cfs_trace_free_string_buffer(str, usr_str_nob + 1);
+ kfree(str);
return rc;
}
@@ -898,7 +881,7 @@ int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob)
if (rc == 0)
rc = cfs_trace_daemon_command(str);
- cfs_trace_free_string_buffer(str, usr_str_nob + 1);
+ kfree(str);
return rc;
}
@@ -970,7 +953,6 @@ static int tracefiled(void *arg)
/* we're started late enough that we pick up init's fs context */
/* this is so broken in uml? what on earth is going on? */
- spin_lock_init(&pc.pc_lock);
complete(&tctl->tctl_start);
while (1) {
@@ -1170,7 +1152,6 @@ static void cfs_trace_cleanup(void)
struct page_collection pc;
INIT_LIST_HEAD(&pc.pc_pages);
- spin_lock_init(&pc.pc_lock);
trace_cleanup_on_all_cpus();
diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.h b/drivers/staging/lustre/lustre/libcfs/tracefile.h
index cb7a3963589f..6b37798336f2 100644
--- a/drivers/staging/lustre/lustre/libcfs/tracefile.h
+++ b/drivers/staging/lustre/lustre/libcfs/tracefile.h
@@ -70,7 +70,6 @@ int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
int cfs_trace_copyout_string(char __user *usr_buffer, int usr_buffer_nob,
const char *knl_str, char *append);
int cfs_trace_allocate_string_buffer(char **str, int nob);
-void cfs_trace_free_string_buffer(char *str, int nob);
int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob);
int cfs_trace_daemon_command(char *str);
int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob);
@@ -196,14 +195,6 @@ extern union cfs_trace_data_union (*cfs_trace_data[TCD_MAX_TYPES])[NR_CPUS];
struct page_collection {
struct list_head pc_pages;
/*
- * spin-lock protecting ->pc_pages. It is taken by smp_call_function()
- * call-back functions. XXX nikita: Which is horrible: all processors
- * receive NMI at the same time only to be serialized by this
- * lock. Probably ->pc_pages should be replaced with an array of
- * NR_CPUS elements accessed locklessly.
- */
- spinlock_t pc_lock;
- /*
* if this flag is set, collect_pages() will spill both
* ->tcd_daemon_pages and ->tcd_pages to the ->pc_pages. Otherwise,
* only ->tcd_pages are spilled.
@@ -279,12 +270,6 @@ cfs_trace_get_console_buffer(void)
return cfs_trace_console_buffers[i][j];
}
-static inline void
-cfs_trace_put_console_buffer(char *buffer)
-{
- put_cpu();
-}
-
static inline struct cfs_trace_cpu_data *
cfs_trace_get_tcd(void)
{
diff --git a/drivers/staging/lustre/lustre/libcfs/workitem.c b/drivers/staging/lustre/lustre/libcfs/workitem.c
index e1143a566ac4..b57acbfb061b 100644
--- a/drivers/staging/lustre/lustre/libcfs/workitem.c
+++ b/drivers/staging/lustre/lustre/libcfs/workitem.c
@@ -225,7 +225,9 @@ cfs_wi_scheduler (void *arg)
/* CPT affinity scheduler? */
if (sched->ws_cptab != NULL)
- cfs_cpt_bind(sched->ws_cptab, sched->ws_cpt);
+ if (cfs_cpt_bind(sched->ws_cptab, sched->ws_cpt) != 0)
+ CWARN("Failed to bind %s on CPT %d\n",
+ sched->ws_name, sched->ws_cpt);
spin_lock(&cfs_wi_data.wi_glock);
@@ -325,7 +327,7 @@ cfs_wi_sched_destroy(struct cfs_wi_sched *sched)
spin_lock(&cfs_wi_data.wi_glock);
while (sched->ws_nthreads > 0) {
- CDEBUG(IS_PO2(++i) ? D_WARNING : D_NET,
+ CDEBUG(is_power_of_2(++i) ? D_WARNING : D_NET,
"waiting for %d threads of WI sched[%s] to terminate\n",
sched->ws_nthreads, sched->ws_name);
@@ -360,8 +362,8 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
if (sched == NULL)
return -ENOMEM;
- strncpy(sched->ws_name, name, CFS_WS_NAME_LEN);
- sched->ws_name[CFS_WS_NAME_LEN - 1] = '\0';
+ strlcpy(sched->ws_name, name, CFS_WS_NAME_LEN);
+
sched->ws_cptab = cptab;
sched->ws_cpt = cpt;
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 0fe0c7135b73..5c2ef92809e6 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -224,7 +224,7 @@ static int ll_dir_filler(void *_hash, struct page *page0)
prefetchw(&page->flags);
ret = add_to_page_cache_lru(page, inode->i_mapping, offset,
- GFP_KERNEL);
+ GFP_NOFS);
if (ret == 0) {
unlock_page(page);
} else {
@@ -239,12 +239,6 @@ static int ll_dir_filler(void *_hash, struct page *page0)
return rc;
}
-static void ll_check_page(struct inode *dir, struct page *page)
-{
- /* XXX: check page format later */
- SetPageChecked(page);
-}
-
void ll_release_page(struct page *page, int remove)
{
kunmap(page);
@@ -432,7 +426,8 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash,
goto fail;
}
if (!PageChecked(page))
- ll_check_page(dir, page);
+ /* XXX: check page format later */
+ SetPageChecked(page);
if (PageError(page)) {
CERROR("page error: "DFID" at %llu: rc %d\n",
PFID(ll_inode2fid(dir)), hash, -5);
@@ -641,7 +636,7 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string)
if (!msp)
return -ENOMEM;
- strncpy(msp->mgs_param, string, MGS_PARAM_MAXLEN);
+ strlcpy(msp->mgs_param, string, sizeof(msp->mgs_param));
rc = obd_set_info_async(NULL, mgc, sizeof(KEY_SET_INFO), KEY_SET_INFO,
sizeof(struct mgs_send_param), msp, NULL);
if (rc)
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index ad02f2b9e590..02f27593013e 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -64,7 +64,7 @@ static struct ll_file_data *ll_file_data_get(void)
{
struct ll_file_data *fd;
- OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, GFP_NOFS);
+ fd = kmem_cache_alloc(ll_file_data_slab, GFP_NOFS | __GFP_ZERO);
if (fd == NULL)
return NULL;
fd->fd_write_failed = false;
@@ -74,7 +74,7 @@ static struct ll_file_data *ll_file_data_get(void)
static void ll_file_data_put(struct ll_file_data *fd)
{
if (fd != NULL)
- OBD_SLAB_FREE_PTR(fd, ll_file_data_slab);
+ kmem_cache_free(ll_file_data_slab, fd);
}
void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data,
@@ -1260,7 +1260,7 @@ static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, u32 ost_idx)
int rc = 0;
struct lov_stripe_md *lsm = NULL, *lsm2;
- OBDO_ALLOC(oa);
+ oa = kmem_cache_alloc(obdo_cachep, GFP_NOFS | __GFP_ZERO);
if (oa == NULL)
return -ENOMEM;
@@ -1295,7 +1295,7 @@ static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, u32 ost_idx)
goto out;
out:
ccc_inode_lsm_put(inode, lsm);
- OBDO_FREE(oa);
+ kmem_cache_free(obdo_cachep, oa);
return rc;
}
@@ -2750,13 +2750,9 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL,
op_data, &lockh, &flock, 0, NULL /* req */, flags);
- if ((file_lock->fl_flags & FL_FLOCK) &&
- (rc == 0 || file_lock->fl_type == F_UNLCK))
- rc2 = flock_lock_file_wait(file, file_lock);
- if ((file_lock->fl_flags & FL_POSIX) &&
- (rc == 0 || file_lock->fl_type == F_UNLCK) &&
+ if ((rc == 0 || file_lock->fl_type == F_UNLCK) &&
!(flags & LDLM_FL_TEST_LOCK))
- rc2 = posix_lock_file_wait(file, file_lock);
+ rc2 = locks_lock_file_wait(file, file_lock);
if (rc2 && file_lock->fl_type != F_UNLCK) {
einfo.ei_mode = LCK_NL;
diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c
index e31cad82d5af..3f348a3aad43 100644
--- a/drivers/staging/lustre/lustre/llite/llite_close.c
+++ b/drivers/staging/lustre/lustre/llite/llite_close.c
@@ -221,7 +221,7 @@ int ll_som_update(struct inode *inode, struct md_op_data *op_data)
inode->i_ino, inode->i_generation,
lli->lli_flags);
- OBDO_ALLOC(oa);
+ oa = kmem_cache_alloc(obdo_cachep, GFP_NOFS | __GFP_ZERO);
if (!oa) {
CERROR("can't allocate memory for Size-on-MDS update.\n");
return -ENOMEM;
@@ -252,7 +252,7 @@ int ll_som_update(struct inode *inode, struct md_op_data *op_data)
NULL, 0, NULL, 0, &request, NULL);
ptlrpc_req_finished(request);
- OBDO_FREE(oa);
+ kmem_cache_free(obdo_cachep, oa);
return rc;
}
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index 9096d311e45d..157c32840e06 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -1285,16 +1285,6 @@ static inline struct ll_file_data *cl_iattr2fd(struct inode *inode,
return LUSTRE_FPRIVATE(attr->ia_file);
}
-static inline void cl_isize_lock(struct inode *inode)
-{
- ll_inode_size_lock(inode);
-}
-
-static inline void cl_isize_unlock(struct inode *inode)
-{
- ll_inode_size_unlock(inode);
-}
-
static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms)
{
LASSERT(mutex_is_locked(&ll_i2info(inode)->lli_size_mutex));
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index e874e631e006..4a8c759fef42 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -1776,7 +1776,8 @@ int ll_iocontrol(struct inode *inode, struct file *file,
return 0;
}
- OBDO_ALLOC(oinfo.oi_oa);
+ oinfo.oi_oa = kmem_cache_alloc(obdo_cachep,
+ GFP_NOFS | __GFP_ZERO);
if (!oinfo.oi_oa) {
ccc_inode_lsm_put(inode, lsm);
return -ENOMEM;
@@ -1788,7 +1789,7 @@ int ll_iocontrol(struct inode *inode, struct file *file,
OBD_MD_FLGROUP;
obdo_set_parent_fid(oinfo.oi_oa, &ll_i2info(inode)->lli_fid);
rc = obd_setattr_rqset(sbi->ll_dt_exp, &oinfo, NULL);
- OBDO_FREE(oinfo.oi_oa);
+ kmem_cache_free(obdo_cachep, oinfo.oi_oa);
ccc_inode_lsm_put(inode, lsm);
if (rc && rc != -EPERM && rc != -EACCES)
diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c
index e6974c36276d..420d39123877 100644
--- a/drivers/staging/lustre/lustre/llite/lloop.c
+++ b/drivers/staging/lustre/lustre/llite/lloop.c
@@ -333,7 +333,7 @@ static unsigned int loop_get_bio(struct lloop_device *lo, struct bio **req)
return count;
}
-static void loop_make_request(struct request_queue *q, struct bio *old_bio)
+static blk_qc_t loop_make_request(struct request_queue *q, struct bio *old_bio)
{
struct lloop_device *lo = q->queuedata;
int rw = bio_rw(old_bio);
@@ -364,9 +364,10 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
goto err;
}
loop_add_bio(lo, old_bio);
- return;
+ return BLK_QC_T_NONE;
err:
bio_io_error(old_bio);
+ return BLK_QC_T_NONE;
}
static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio)
@@ -876,6 +877,6 @@ module_exit(lloop_exit);
module_param(max_loop, int, 0444);
MODULE_PARM_DESC(max_loop, "maximum of lloop_device");
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre virtual block device");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index 2ee7d31d78ae..2ca22001a534 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -903,7 +903,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
}
LASSERT(rc >= sizeof(*lsm));
- OBDO_ALLOC(oa);
+ oa = kmem_cache_alloc(obdo_cachep, GFP_NOFS | __GFP_ZERO);
if (oa == NULL) {
rc = -ENOMEM;
goto out_free_memmd;
@@ -933,7 +933,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
POSTID(&lsm->lsm_oi), rc);
out_free_memmd:
obd_free_memmd(ll_i2dtexp(dir), &lsm);
- OBDO_FREE(oa);
+ kmem_cache_free(obdo_cachep, oa);
out:
return rc;
}
diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c
index dc33055acf3b..fe4a72268e3a 100644
--- a/drivers/staging/lustre/lustre/llite/remote_perm.c
+++ b/drivers/staging/lustre/lustre/llite/remote_perm.c
@@ -61,7 +61,7 @@ static inline struct ll_remote_perm *alloc_ll_remote_perm(void)
{
struct ll_remote_perm *lrp;
- OBD_SLAB_ALLOC_PTR_GFP(lrp, ll_remote_perm_cachep, GFP_KERNEL);
+ lrp = kmem_cache_alloc(ll_remote_perm_cachep, GFP_KERNEL | __GFP_ZERO);
if (lrp)
INIT_HLIST_NODE(&lrp->lrp_list);
return lrp;
@@ -74,7 +74,7 @@ static inline void free_ll_remote_perm(struct ll_remote_perm *lrp)
if (!hlist_unhashed(&lrp->lrp_list))
hlist_del(&lrp->lrp_list);
- OBD_SLAB_FREE(lrp, ll_remote_perm_cachep, sizeof(*lrp));
+ kmem_cache_free(ll_remote_perm_cachep, lrp);
}
static struct hlist_head *alloc_rmtperm_hash(void)
@@ -82,9 +82,7 @@ static struct hlist_head *alloc_rmtperm_hash(void)
struct hlist_head *hash;
int i;
- OBD_SLAB_ALLOC_GFP(hash, ll_rmtperm_hash_cachep,
- REMOTE_PERM_HASHSIZE * sizeof(*hash),
- GFP_IOFS);
+ hash = kmem_cache_alloc(ll_rmtperm_hash_cachep, GFP_NOFS | __GFP_ZERO);
if (!hash)
return NULL;
@@ -106,8 +104,7 @@ void free_rmtperm_hash(struct hlist_head *hash)
for (i = 0; i < REMOTE_PERM_HASHSIZE; i++)
hlist_for_each_entry_safe(lrp, next, hash + i, lrp_list)
free_ll_remote_perm(lrp);
- OBD_SLAB_FREE(hash, ll_rmtperm_hash_cachep,
- REMOTE_PERM_HASHSIZE * sizeof(*hash));
+ kmem_cache_free(ll_rmtperm_hash_cachep, hash);
}
static inline int remote_perm_hashfunc(uid_t uid)
diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c
index dae1f9caf0db..7a9fafc67693 100644
--- a/drivers/staging/lustre/lustre/llite/super25.c
+++ b/drivers/staging/lustre/lustre/llite/super25.c
@@ -53,7 +53,7 @@ static struct inode *ll_alloc_inode(struct super_block *sb)
struct ll_inode_info *lli;
ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_ALLOC_INODE, 1);
- OBD_SLAB_ALLOC_PTR_GFP(lli, ll_inode_cachep, GFP_NOFS);
+ lli = kmem_cache_alloc(ll_inode_cachep, GFP_NOFS | __GFP_ZERO);
if (lli == NULL)
return NULL;
@@ -66,7 +66,7 @@ static void ll_inode_destroy_callback(struct rcu_head *head)
struct inode *inode = container_of(head, struct inode, i_rcu);
struct ll_inode_info *ptr = ll_i2info(inode);
- OBD_SLAB_FREE_PTR(ptr, ll_inode_cachep);
+ kmem_cache_free(ll_inode_cachep, ptr);
}
static void ll_destroy_inode(struct inode *inode)
@@ -205,7 +205,7 @@ static void __exit exit_lustre_lite(void)
kmem_cache_destroy(ll_file_data_slab);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Lite Client File System");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c
index 9f7449fadb80..d16d6cfce81a 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_dev.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c
@@ -79,7 +79,7 @@ static void *vvp_key_init(const struct lu_context *ctx,
{
struct vvp_thread_info *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, vvp_thread_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(vvp_thread_kmem, GFP_NOFS | __GFP_ZERO);
if (info == NULL)
info = ERR_PTR(-ENOMEM);
return info;
@@ -90,7 +90,7 @@ static void vvp_key_fini(const struct lu_context *ctx,
{
struct vvp_thread_info *info = data;
- OBD_SLAB_FREE_PTR(info, vvp_thread_kmem);
+ kmem_cache_free(vvp_thread_kmem, info);
}
static void *vvp_session_key_init(const struct lu_context *ctx,
@@ -98,7 +98,7 @@ static void *vvp_session_key_init(const struct lu_context *ctx,
{
struct vvp_session *session;
- OBD_SLAB_ALLOC_PTR_GFP(session, vvp_session_kmem, GFP_NOFS);
+ session = kmem_cache_alloc(vvp_session_kmem, GFP_NOFS | __GFP_ZERO);
if (session == NULL)
session = ERR_PTR(-ENOMEM);
return session;
@@ -109,7 +109,7 @@ static void vvp_session_key_fini(const struct lu_context *ctx,
{
struct vvp_session *session = data;
- OBD_SLAB_FREE_PTR(session, vvp_session_kmem);
+ kmem_cache_free(vvp_session_kmem, session);
}
struct lu_context_key vvp_key = {
diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c
index 819d3867183c..e1e599ceb173 100644
--- a/drivers/staging/lustre/lustre/llite/xattr_cache.c
+++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c
@@ -115,7 +115,7 @@ static int ll_xattr_cache_add(struct list_head *cache,
return -EPROTO;
}
- OBD_SLAB_ALLOC_PTR_GFP(xattr, xattr_kmem, GFP_NOFS);
+ xattr = kmem_cache_alloc(xattr_kmem, GFP_NOFS | __GFP_ZERO);
if (xattr == NULL) {
CDEBUG(D_CACHE, "failed to allocate xattr\n");
return -ENOMEM;
@@ -141,7 +141,7 @@ static int ll_xattr_cache_add(struct list_head *cache,
err_value:
kfree(xattr->xe_name);
err_name:
- OBD_SLAB_FREE_PTR(xattr, xattr_kmem);
+ kmem_cache_free(xattr_kmem, xattr);
return -ENOMEM;
}
@@ -165,7 +165,7 @@ static int ll_xattr_cache_del(struct list_head *cache,
list_del(&xattr->xe_list);
kfree(xattr->xe_name);
kfree(xattr->xe_value);
- OBD_SLAB_FREE_PTR(xattr, xattr_kmem);
+ kmem_cache_free(xattr_kmem, xattr);
return 0;
}
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
index eebe45bdceb6..3c585aea5bb8 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
@@ -156,11 +156,11 @@ out:
* IT_OPEN is intended to open (and create, possible) an object. Parent (pid)
* may be split dir.
*/
-int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
- void *lmm, int lmmsize, struct lookup_intent *it,
- int flags, struct ptlrpc_request **reqp,
- ldlm_blocking_callback cb_blocking,
- __u64 extra_lock_flags)
+static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
+ void *lmm, int lmmsize, struct lookup_intent *it,
+ int flags, struct ptlrpc_request **reqp,
+ ldlm_blocking_callback cb_blocking,
+ __u64 extra_lock_flags)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
@@ -239,11 +239,12 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
/*
* Handler for: getattr, lookup and revalidate cases.
*/
-int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
- void *lmm, int lmmsize, struct lookup_intent *it,
- int flags, struct ptlrpc_request **reqp,
- ldlm_blocking_callback cb_blocking,
- __u64 extra_lock_flags)
+static int lmv_intent_lookup(struct obd_export *exp,
+ struct md_op_data *op_data,
+ void *lmm, int lmmsize, struct lookup_intent *it,
+ int flags, struct ptlrpc_request **reqp,
+ ldlm_blocking_callback cb_blocking,
+ __u64 extra_lock_flags)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h
index b808728daee7..467cfb3e7fca 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h
+++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h
@@ -56,20 +56,6 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
ldlm_blocking_callback cb_blocking,
__u64 extra_lock_flags);
-int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
- void *lmm, int lmmsize, struct lookup_intent *it,
- int flags, struct ptlrpc_request **reqp,
- ldlm_blocking_callback cb_blocking,
- __u64 extra_lock_flags);
-
-int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
- void *lmm, int lmmsize, struct lookup_intent *it,
- int flags, struct ptlrpc_request **reqp,
- ldlm_blocking_callback cb_blocking,
- __u64 extra_lock_flags);
-
-int lmv_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *,
- void *, int);
int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds);
int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds);
int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index 635a93cc94de..a4de9a3fd847 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -2744,55 +2744,55 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp,
}
static struct obd_ops lmv_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = lmv_setup,
- .o_cleanup = lmv_cleanup,
- .o_precleanup = lmv_precleanup,
- .o_process_config = lmv_process_config,
- .o_connect = lmv_connect,
- .o_disconnect = lmv_disconnect,
- .o_statfs = lmv_statfs,
- .o_get_info = lmv_get_info,
- .o_set_info_async = lmv_set_info_async,
- .o_packmd = lmv_packmd,
- .o_unpackmd = lmv_unpackmd,
- .o_notify = lmv_notify,
- .o_get_uuid = lmv_get_uuid,
- .o_iocontrol = lmv_iocontrol,
- .o_quotacheck = lmv_quotacheck,
- .o_quotactl = lmv_quotactl
+ .owner = THIS_MODULE,
+ .setup = lmv_setup,
+ .cleanup = lmv_cleanup,
+ .precleanup = lmv_precleanup,
+ .process_config = lmv_process_config,
+ .connect = lmv_connect,
+ .disconnect = lmv_disconnect,
+ .statfs = lmv_statfs,
+ .get_info = lmv_get_info,
+ .set_info_async = lmv_set_info_async,
+ .packmd = lmv_packmd,
+ .unpackmd = lmv_unpackmd,
+ .notify = lmv_notify,
+ .get_uuid = lmv_get_uuid,
+ .iocontrol = lmv_iocontrol,
+ .quotacheck = lmv_quotacheck,
+ .quotactl = lmv_quotactl
};
static struct md_ops lmv_md_ops = {
- .m_getstatus = lmv_getstatus,
- .m_null_inode = lmv_null_inode,
- .m_find_cbdata = lmv_find_cbdata,
- .m_close = lmv_close,
- .m_create = lmv_create,
- .m_done_writing = lmv_done_writing,
- .m_enqueue = lmv_enqueue,
- .m_getattr = lmv_getattr,
- .m_getxattr = lmv_getxattr,
- .m_getattr_name = lmv_getattr_name,
- .m_intent_lock = lmv_intent_lock,
- .m_link = lmv_link,
- .m_rename = lmv_rename,
- .m_setattr = lmv_setattr,
- .m_setxattr = lmv_setxattr,
- .m_sync = lmv_sync,
- .m_readpage = lmv_readpage,
- .m_unlink = lmv_unlink,
- .m_init_ea_size = lmv_init_ea_size,
- .m_cancel_unused = lmv_cancel_unused,
- .m_set_lock_data = lmv_set_lock_data,
- .m_lock_match = lmv_lock_match,
- .m_get_lustre_md = lmv_get_lustre_md,
- .m_free_lustre_md = lmv_free_lustre_md,
- .m_set_open_replay_data = lmv_set_open_replay_data,
- .m_clear_open_replay_data = lmv_clear_open_replay_data,
- .m_get_remote_perm = lmv_get_remote_perm,
- .m_intent_getattr_async = lmv_intent_getattr_async,
- .m_revalidate_lock = lmv_revalidate_lock
+ .getstatus = lmv_getstatus,
+ .null_inode = lmv_null_inode,
+ .find_cbdata = lmv_find_cbdata,
+ .close = lmv_close,
+ .create = lmv_create,
+ .done_writing = lmv_done_writing,
+ .enqueue = lmv_enqueue,
+ .getattr = lmv_getattr,
+ .getxattr = lmv_getxattr,
+ .getattr_name = lmv_getattr_name,
+ .intent_lock = lmv_intent_lock,
+ .link = lmv_link,
+ .rename = lmv_rename,
+ .setattr = lmv_setattr,
+ .setxattr = lmv_setxattr,
+ .sync = lmv_sync,
+ .readpage = lmv_readpage,
+ .unlink = lmv_unlink,
+ .init_ea_size = lmv_init_ea_size,
+ .cancel_unused = lmv_cancel_unused,
+ .set_lock_data = lmv_set_lock_data,
+ .lock_match = lmv_lock_match,
+ .get_lustre_md = lmv_get_lustre_md,
+ .free_lustre_md = lmv_free_lustre_md,
+ .set_open_replay_data = lmv_set_open_replay_data,
+ .clear_open_replay_data = lmv_clear_open_replay_data,
+ .get_remote_perm = lmv_get_remote_perm,
+ .intent_getattr_async = lmv_intent_getattr_async,
+ .revalidate_lock = lmv_revalidate_lock
};
static int __init lmv_init(void)
@@ -2812,7 +2812,7 @@ static void lmv_exit(void)
class_unregister_type(LUSTRE_LMV_NAME);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c
index 6f89c194d51f..2e8b566458f6 100644
--- a/drivers/staging/lustre/lustre/lov/lov_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lov_dev.c
@@ -124,7 +124,7 @@ static void lov_req_completion(const struct lu_env *env,
struct lov_req *lr;
lr = cl2lov_req(slice);
- OBD_SLAB_FREE_PTR(lr, lov_req_kmem);
+ kmem_cache_free(lov_req_kmem, lr);
}
static const struct cl_req_operations lov_req_ops = {
@@ -142,7 +142,7 @@ static void *lov_key_init(const struct lu_context *ctx,
{
struct lov_thread_info *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, lov_thread_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(lov_thread_kmem, GFP_NOFS | __GFP_ZERO);
if (info != NULL)
INIT_LIST_HEAD(&info->lti_closure.clc_list);
else
@@ -156,7 +156,7 @@ static void lov_key_fini(const struct lu_context *ctx,
struct lov_thread_info *info = data;
LINVRNT(list_empty(&info->lti_closure.clc_list));
- OBD_SLAB_FREE_PTR(info, lov_thread_kmem);
+ kmem_cache_free(lov_thread_kmem, info);
}
struct lu_context_key lov_key = {
@@ -170,7 +170,7 @@ static void *lov_session_key_init(const struct lu_context *ctx,
{
struct lov_session *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, lov_session_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(lov_session_kmem, GFP_NOFS | __GFP_ZERO);
if (info == NULL)
info = ERR_PTR(-ENOMEM);
return info;
@@ -181,7 +181,7 @@ static void lov_session_key_fini(const struct lu_context *ctx,
{
struct lov_session *info = data;
- OBD_SLAB_FREE_PTR(info, lov_session_kmem);
+ kmem_cache_free(lov_session_kmem, info);
}
struct lu_context_key lov_session_key = {
@@ -261,7 +261,7 @@ static int lov_req_init(const struct lu_env *env, struct cl_device *dev,
struct lov_req *lr;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(lr, lov_req_kmem, GFP_NOFS);
+ lr = kmem_cache_alloc(lov_req_kmem, GFP_NOFS | __GFP_ZERO);
if (lr != NULL) {
cl_req_slice_add(req, &lr->lr_cl, dev, &lov_req_ops);
result = 0;
diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c
index 3f51b573e1fb..34c1346f0dc7 100644
--- a/drivers/staging/lustre/lustre/lov/lov_ea.c
+++ b/drivers/staging/lustre/lustre/lov/lov_ea.c
@@ -100,7 +100,7 @@ struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size)
return NULL;
for (i = 0; i < stripe_count; i++) {
- OBD_SLAB_ALLOC_PTR_GFP(loi, lov_oinfo_slab, GFP_NOFS);
+ loi = kmem_cache_alloc(lov_oinfo_slab, GFP_NOFS | __GFP_ZERO);
if (loi == NULL)
goto err;
lsm->lsm_oinfo[i] = loi;
@@ -110,7 +110,7 @@ struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size)
err:
while (--i >= 0)
- OBD_SLAB_FREE(lsm->lsm_oinfo[i], lov_oinfo_slab, sizeof(*loi));
+ kmem_cache_free(lov_oinfo_slab, lsm->lsm_oinfo[i]);
kvfree(lsm);
return NULL;
}
@@ -121,8 +121,7 @@ void lsm_free_plain(struct lov_stripe_md *lsm)
int i;
for (i = 0; i < stripe_count; i++)
- OBD_SLAB_FREE(lsm->lsm_oinfo[i], lov_oinfo_slab,
- sizeof(struct lov_oinfo));
+ kmem_cache_free(lov_oinfo_slab, lsm->lsm_oinfo[i]);
kvfree(lsm);
}
diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h
index bdee0a6f3d4e..b8028735e568 100644
--- a/drivers/staging/lustre/lustre/lov/lov_internal.h
+++ b/drivers/staging/lustre/lustre/lov/lov_internal.h
@@ -151,23 +151,10 @@ int lov_stripe_number(struct lov_stripe_md *lsm, u64 lov_off);
/* lov_qos.c */
#define LOV_USES_ASSIGNED_STRIPE 0
#define LOV_USES_DEFAULT_STRIPE 1
-int qos_add_tgt(struct obd_device *obd, __u32 index);
-int qos_del_tgt(struct obd_device *obd, struct lov_tgt_desc *tgt);
-void qos_shrink_lsm(struct lov_request_set *set);
-int qos_prep_create(struct obd_export *exp, struct lov_request_set *set);
-void qos_update(struct lov_obd *lov);
-void qos_statfs_done(struct lov_obd *lov);
-void qos_statfs_update(struct obd_device *obd, __u64 max_age, int wait);
-int qos_remedy_create(struct lov_request_set *set, struct lov_request *req);
/* lov_request.c */
-void lov_set_add_req(struct lov_request *req, struct lov_request_set *set);
-int lov_set_finished(struct lov_request_set *set, int idempotent);
-void lov_update_set(struct lov_request_set *set,
- struct lov_request *req, int rc);
int lov_update_common_set(struct lov_request_set *set,
struct lov_request *req, int rc);
-int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx);
int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
struct lov_request_set **reqset);
int lov_fini_getattr_set(struct lov_request_set *set);
@@ -184,8 +171,6 @@ int lov_update_setattr_set(struct lov_request_set *set,
int lov_fini_setattr_set(struct lov_request_set *set);
int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
struct lov_request_set **reqset);
-void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs,
- int success);
int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,
int success);
int lov_fini_statfs_set(struct lov_request_set *set);
@@ -234,7 +219,7 @@ void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars);
extern struct lu_device_type lov_device_type;
/* pools */
-extern cfs_hash_ops_t pool_hash_operations;
+extern struct cfs_hash_ops pool_hash_operations;
/* ost_pool methods */
int lov_ost_pool_init(struct ost_pool *op, unsigned int count);
int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count);
diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c
index 1a26496d844b..d866791d7b22 100644
--- a/drivers/staging/lustre/lustre/lov/lov_lock.c
+++ b/drivers/staging/lustre/lustre/lov/lov_lock.c
@@ -144,7 +144,7 @@ static struct cl_lock *lov_sublock_alloc(const struct lu_env *env,
LASSERT(idx < lck->lls_nr);
- OBD_SLAB_ALLOC_PTR_GFP(link, lov_lock_link_kmem, GFP_NOFS);
+ link = kmem_cache_alloc(lov_lock_link_kmem, GFP_NOFS | __GFP_ZERO);
if (link != NULL) {
struct lov_sublock_env *subenv;
struct lov_lock_sub *lls;
@@ -173,7 +173,7 @@ static struct cl_lock *lov_sublock_alloc(const struct lu_env *env,
if (!IS_ERR(sublock))
*out = link;
else
- OBD_SLAB_FREE_PTR(link, lov_lock_link_kmem);
+ kmem_cache_free(lov_lock_link_kmem, link);
} else
sublock = ERR_PTR(-ENOMEM);
return sublock;
@@ -444,7 +444,7 @@ static void lov_lock_fini(const struct lu_env *env,
LASSERT(lck->lls_sub[i].sub_lock == NULL);
kvfree(lck->lls_sub);
}
- OBD_SLAB_FREE_PTR(lck, lov_lock_kmem);
+ kmem_cache_free(lov_lock_kmem, lck);
}
static int lov_lock_enqueue_wait(const struct lu_env *env,
@@ -518,7 +518,7 @@ static int lov_sublock_fill(const struct lu_env *env, struct cl_lock *parent,
lck->lls_sub[idx].sub_lock == NULL) {
lov_sublock_adopt(env, lck, sublock, idx, link);
} else {
- OBD_SLAB_FREE_PTR(link, lov_lock_link_kmem);
+ kmem_cache_free(lov_lock_link_kmem, link);
/* other thread allocated sub-lock, or enqueue is no
* longer going on */
cl_lock_mutex_put(env, parent);
@@ -1027,7 +1027,7 @@ void lov_lock_unlink(const struct lu_env *env,
lck->lls_nr_filled--;
lu_ref_del(&parent->cll_reference, "lov-child", sub->lss_cl.cls_lock);
cl_lock_put(env, parent);
- OBD_SLAB_FREE_PTR(link, lov_lock_link_kmem);
+ kmem_cache_free(lov_lock_link_kmem, link);
}
struct lov_lock_link *lov_lock_link_find(const struct lu_env *env,
@@ -1139,7 +1139,7 @@ int lov_lock_init_raid0(const struct lu_env *env, struct cl_object *obj,
struct lov_lock *lck;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(lck, lov_lock_kmem, GFP_NOFS);
+ lck = kmem_cache_alloc(lov_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (lck != NULL) {
cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_lock_ops);
result = lov_lock_sub_init(env, lck, io);
@@ -1153,7 +1153,7 @@ static void lov_empty_lock_fini(const struct lu_env *env,
{
struct lov_lock *lck = cl2lov_lock(slice);
- OBD_SLAB_FREE_PTR(lck, lov_lock_kmem);
+ kmem_cache_free(lov_lock_kmem, lck);
}
static int lov_empty_lock_print(const struct lu_env *env, void *cookie,
@@ -1175,7 +1175,7 @@ int lov_lock_init_empty(const struct lu_env *env, struct cl_object *obj,
struct lov_lock *lck;
int result = -ENOMEM;
- OBD_SLAB_ALLOC_PTR_GFP(lck, lov_lock_kmem, GFP_NOFS);
+ lck = kmem_cache_alloc(lov_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (lck != NULL) {
cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_empty_lock_ops);
lck->lls_orig = lock->cll_descr;
diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c
index c3be0b5ca627..b52609aead4c 100644
--- a/drivers/staging/lustre/lustre/lov/lov_obd.c
+++ b/drivers/staging/lustre/lustre/lov/lov_obd.c
@@ -914,14 +914,12 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg,
obd_str2uuid(&obd_uuid, lustre_cfg_buf(lcfg, 1));
- if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", indexp) != 1) {
- rc = -EINVAL;
+ rc = kstrtoint(lustre_cfg_buf(lcfg, 2), 10, indexp);
+ if (rc < 0)
goto out;
- }
- if (sscanf(lustre_cfg_buf(lcfg, 3), "%d", genp) != 1) {
- rc = -EINVAL;
+ rc = kstrtoint(lustre_cfg_buf(lcfg, 3), 10, genp);
+ if (rc < 0)
goto out;
- }
index = *indexp;
gen = *genp;
if (cmd == LCFG_LOV_ADD_OBD)
@@ -2101,11 +2099,10 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp,
}
for (i = 0; i < count; i++, val = (char *)val + incr) {
- if (next_id) {
+ if (next_id)
tgt = lov->lov_tgts[((struct obd_id_info *)val)->idx];
- } else {
+ else
tgt = lov->lov_tgts[i];
- }
/* OST was disconnected */
if (!tgt || !tgt->ltd_exp)
continue;
@@ -2280,35 +2277,35 @@ out:
}
static struct obd_ops lov_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = lov_setup,
- .o_precleanup = lov_precleanup,
- .o_cleanup = lov_cleanup,
- /*.o_process_config = lov_process_config,*/
- .o_connect = lov_connect,
- .o_disconnect = lov_disconnect,
- .o_statfs = lov_statfs,
- .o_statfs_async = lov_statfs_async,
- .o_packmd = lov_packmd,
- .o_unpackmd = lov_unpackmd,
- .o_create = lov_create,
- .o_destroy = lov_destroy,
- .o_getattr_async = lov_getattr_async,
- .o_setattr_async = lov_setattr_async,
- .o_adjust_kms = lov_adjust_kms,
- .o_find_cbdata = lov_find_cbdata,
- .o_iocontrol = lov_iocontrol,
- .o_get_info = lov_get_info,
- .o_set_info_async = lov_set_info_async,
- .o_notify = lov_notify,
- .o_pool_new = lov_pool_new,
- .o_pool_rem = lov_pool_remove,
- .o_pool_add = lov_pool_add,
- .o_pool_del = lov_pool_del,
- .o_getref = lov_getref,
- .o_putref = lov_putref,
- .o_quotactl = lov_quotactl,
- .o_quotacheck = lov_quotacheck,
+ .owner = THIS_MODULE,
+ .setup = lov_setup,
+ .precleanup = lov_precleanup,
+ .cleanup = lov_cleanup,
+ /*.process_config = lov_process_config,*/
+ .connect = lov_connect,
+ .disconnect = lov_disconnect,
+ .statfs = lov_statfs,
+ .statfs_async = lov_statfs_async,
+ .packmd = lov_packmd,
+ .unpackmd = lov_unpackmd,
+ .create = lov_create,
+ .destroy = lov_destroy,
+ .getattr_async = lov_getattr_async,
+ .setattr_async = lov_setattr_async,
+ .adjust_kms = lov_adjust_kms,
+ .find_cbdata = lov_find_cbdata,
+ .iocontrol = lov_iocontrol,
+ .get_info = lov_get_info,
+ .set_info_async = lov_set_info_async,
+ .notify = lov_notify,
+ .pool_new = lov_pool_new,
+ .pool_rem = lov_pool_remove,
+ .pool_add = lov_pool_add,
+ .pool_del = lov_pool_del,
+ .getref = lov_getref,
+ .putref = lov_putref,
+ .quotactl = lov_quotactl,
+ .quotacheck = lov_quotacheck,
};
struct kmem_cache *lov_oinfo_slab;
@@ -2355,7 +2352,7 @@ static void /*__exit*/ lov_exit(void)
lu_kmem_fini(lov_caches);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(LUSTRE_VERSION_STRING);
diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c
index 1837bbff76bf..c7ff817bb6fb 100644
--- a/drivers/staging/lustre/lustre/lov/lov_object.c
+++ b/drivers/staging/lustre/lustre/lov/lov_object.c
@@ -808,7 +808,7 @@ static void lov_object_free(const struct lu_env *env, struct lu_object *obj)
LOV_2DISPATCH_VOID(lov, llo_fini, env, lov, &lov->u);
lu_object_fini(obj);
- OBD_SLAB_FREE_PTR(lov, lov_object_kmem);
+ kmem_cache_free(lov_object_kmem, lov);
}
static int lov_object_print(const struct lu_env *env, void *cookie,
@@ -891,7 +891,7 @@ struct lu_object *lov_object_alloc(const struct lu_env *env,
struct lov_object *lov;
struct lu_object *obj;
- OBD_SLAB_ALLOC_PTR_GFP(lov, lov_object_kmem, GFP_NOFS);
+ lov = kmem_cache_alloc(lov_object_kmem, GFP_NOFS | __GFP_ZERO);
if (lov != NULL) {
obj = lov2lu(lov);
lu_object_init(obj, NULL, dev);
diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c
index 2234321025d5..b43ce6cd64c2 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pool.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pool.c
@@ -142,12 +142,12 @@ static void pool_hashrefcount_put_locked(struct cfs_hash *hs,
lov_pool_putref_locked(pool);
}
-cfs_hash_ops_t pool_hash_operations = {
+struct cfs_hash_ops pool_hash_operations = {
.hs_hash = pool_hashfn,
- .hs_key = pool_key,
+ .hs_key = pool_key,
.hs_keycmp = pool_hashkey_keycmp,
.hs_object = pool_hashobject,
- .hs_get = pool_hashrefcount_get,
+ .hs_get = pool_hashrefcount_get,
.hs_put_locked = pool_hashrefcount_put_locked,
};
@@ -412,8 +412,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname)
if (!new_pool)
return -ENOMEM;
- strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME);
- new_pool->pool_name[LOV_MAXPOOLNAME] = '\0';
+ strlcpy(new_pool->pool_name, poolname, sizeof(new_pool->pool_name));
new_pool->pool_lobd = obd;
/* ref count init to 1 because when created a pool is always used
* up to deletion
diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c
index 104c92ace682..bb1a03fef60d 100644
--- a/drivers/staging/lustre/lustre/lov/lov_request.c
+++ b/drivers/staging/lustre/lustre/lov/lov_request.c
@@ -67,14 +67,14 @@ void lov_finish_set(struct lov_request_set *set)
list_del_init(&req->rq_link);
if (req->rq_oi.oi_oa)
- OBDO_FREE(req->rq_oi.oi_oa);
+ kmem_cache_free(obdo_cachep, req->rq_oi.oi_oa);
kfree(req->rq_oi.oi_osfs);
kfree(req);
}
kfree(set);
}
-int lov_set_finished(struct lov_request_set *set, int idempotent)
+static int lov_set_finished(struct lov_request_set *set, int idempotent)
{
int completes = atomic_read(&set->set_completes);
@@ -89,8 +89,8 @@ int lov_set_finished(struct lov_request_set *set, int idempotent)
return 0;
}
-void lov_update_set(struct lov_request_set *set,
- struct lov_request *req, int rc)
+static void lov_update_set(struct lov_request_set *set,
+ struct lov_request *req, int rc)
{
req->rq_complete = 1;
req->rq_rc = rc;
@@ -118,7 +118,8 @@ int lov_update_common_set(struct lov_request_set *set,
return rc;
}
-void lov_set_add_req(struct lov_request *req, struct lov_request_set *set)
+static void lov_set_add_req(struct lov_request *req,
+ struct lov_request_set *set)
{
list_add_tail(&req->rq_link, &set->set_list);
set->set_count++;
@@ -144,7 +145,7 @@ static int lov_check_set(struct lov_obd *lov, int idx)
* If the OSC has not yet had a chance to connect to the OST the first time,
* wait once for it to connect instead of returning an error.
*/
-int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx)
+static int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx)
{
wait_queue_head_t waitq;
struct l_wait_info lwi;
@@ -202,7 +203,7 @@ static int common_attr_done(struct lov_request_set *set)
if (!atomic_read(&set->set_success))
return -EIO;
- OBDO_ALLOC(tmp_oa);
+ tmp_oa = kmem_cache_alloc(obdo_cachep, GFP_NOFS | __GFP_ZERO);
if (tmp_oa == NULL) {
rc = -ENOMEM;
goto out;
@@ -236,7 +237,7 @@ static int common_attr_done(struct lov_request_set *set)
memcpy(set->set_oi->oi_oa, tmp_oa, sizeof(*set->set_oi->oi_oa));
out:
if (tmp_oa)
- OBDO_FREE(tmp_oa);
+ kmem_cache_free(obdo_cachep, tmp_oa);
return rc;
}
@@ -309,7 +310,8 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
req->rq_stripe = i;
req->rq_idx = loi->loi_ost_idx;
- OBDO_ALLOC(req->rq_oi.oi_oa);
+ req->rq_oi.oi_oa = kmem_cache_alloc(obdo_cachep,
+ GFP_NOFS | __GFP_ZERO);
if (req->rq_oi.oi_oa == NULL) {
kfree(req);
rc = -ENOMEM;
@@ -391,7 +393,8 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
req->rq_stripe = i;
req->rq_idx = loi->loi_ost_idx;
- OBDO_ALLOC(req->rq_oi.oi_oa);
+ req->rq_oi.oi_oa = kmem_cache_alloc(obdo_cachep,
+ GFP_NOFS | __GFP_ZERO);
if (req->rq_oi.oi_oa == NULL) {
kfree(req);
rc = -ENOMEM;
@@ -506,7 +509,8 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
req->rq_stripe = i;
req->rq_idx = loi->loi_ost_idx;
- OBDO_ALLOC(req->rq_oi.oi_oa);
+ req->rq_oi.oi_oa = kmem_cache_alloc(obdo_cachep,
+ GFP_NOFS | __GFP_ZERO);
if (req->rq_oi.oi_oa == NULL) {
kfree(req);
rc = -ENOMEM;
@@ -588,8 +592,9 @@ int lov_fini_statfs_set(struct lov_request_set *set)
return rc;
}
-void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs,
- int success)
+static void lov_update_statfs(struct obd_statfs *osfs,
+ struct obd_statfs *lov_sfs,
+ int success)
{
int shift = 0, quit = 0;
__u64 tmp;
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c
index 8cbbfb03c849..8bc04c8d3d60 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c
@@ -56,7 +56,7 @@ static void lovsub_req_completion(const struct lu_env *env,
struct lovsub_req *lsr;
lsr = cl2lovsub_req(slice);
- OBD_SLAB_FREE_PTR(lsr, lovsub_req_kmem);
+ kmem_cache_free(lovsub_req_kmem, lsr);
}
/**
@@ -146,7 +146,7 @@ static int lovsub_req_init(const struct lu_env *env, struct cl_device *dev,
struct lovsub_req *lsr;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(lsr, lovsub_req_kmem, GFP_NOFS);
+ lsr = kmem_cache_alloc(lovsub_req_kmem, GFP_NOFS | __GFP_ZERO);
if (lsr != NULL) {
cl_req_slice_add(req, &lsr->lsrq_cl, dev, &lovsub_req_ops);
result = 0;
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_lock.c b/drivers/staging/lustre/lustre/lov/lovsub_lock.c
index 62b696d25d81..1a3e30a14895 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_lock.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_lock.c
@@ -59,7 +59,7 @@ static void lovsub_lock_fini(const struct lu_env *env,
lsl = cl2lovsub_lock(slice);
LASSERT(list_empty(&lsl->lss_parents));
- OBD_SLAB_FREE_PTR(lsl, lovsub_lock_kmem);
+ kmem_cache_free(lovsub_lock_kmem, lsl);
}
static void lovsub_parent_lock(const struct lu_env *env, struct lov_lock *lov)
@@ -453,7 +453,7 @@ int lovsub_lock_init(const struct lu_env *env, struct cl_object *obj,
struct lovsub_lock *lsk;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(lsk, lovsub_lock_kmem, GFP_NOFS);
+ lsk = kmem_cache_alloc(lovsub_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (lsk != NULL) {
INIT_LIST_HEAD(&lsk->lss_parents);
cl_lock_slice_add(lock, &lsk->lss_cl, obj, &lovsub_lock_ops);
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c
index f2d885212f19..d775e28d4097 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_object.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c
@@ -91,7 +91,7 @@ static void lovsub_object_free(const struct lu_env *env, struct lu_object *obj)
lu_object_fini(obj);
lu_object_header_fini(&los->lso_header.coh_lu);
- OBD_SLAB_FREE_PTR(los, lovsub_object_kmem);
+ kmem_cache_free(lovsub_object_kmem, los);
}
static int lovsub_object_print(const struct lu_env *env, void *cookie,
@@ -143,7 +143,7 @@ struct lu_object *lovsub_object_alloc(const struct lu_env *env,
struct lovsub_object *los;
struct lu_object *obj;
- OBD_SLAB_ALLOC_PTR_GFP(los, lovsub_object_kmem, GFP_NOFS);
+ los = kmem_cache_alloc(lovsub_object_kmem, GFP_NOFS | __GFP_ZERO);
if (los != NULL) {
struct cl_object_header *hdr;
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h
index 29b46f754726..df50bdbcde19 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h
+++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h
@@ -44,7 +44,6 @@ void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars);
void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid,
__u64 valid, int ea_size, __u32 suppgid, int flags);
-int mdc_pack_req(struct ptlrpc_request *req, int version, int opc);
void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid,
const struct lu_fid *cfid, int flags);
void mdc_swap_layouts_pack(struct ptlrpc_request *req,
@@ -62,7 +61,6 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
__u32 mode, __u64 rdev, __u64 flags, const void *data,
int datalen);
void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data);
-void mdc_getxattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data);
void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data);
void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
const char *old, int oldlen, const char *new, int newlen);
@@ -97,25 +95,12 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid,
/* mdc/mdc_request.c */
int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
struct md_op_data *op_data);
-
-int mdc_open(struct obd_export *exp, u64 ino, int type, int flags,
- struct lov_mds_md *lmm, int lmm_size, struct lustre_handle *fh,
- struct ptlrpc_request **);
-
struct obd_client_handle;
-int mdc_get_lustre_md(struct obd_export *md_exp, struct ptlrpc_request *req,
- struct obd_export *dt_exp, struct obd_export *lmv_exp,
- struct lustre_md *md);
-
-int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md);
-
int mdc_set_open_replay_data(struct obd_export *exp,
struct obd_client_handle *och,
struct lookup_intent *it);
-int mdc_clear_open_replay_data(struct obd_export *exp,
- struct obd_client_handle *och);
void mdc_commit_open(struct ptlrpc_request *req);
void mdc_replay_open(struct ptlrpc_request *req);
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 16a5a10d371e..294c05084b97 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -447,9 +447,11 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md)
#define mdc_unpack_acl(req, md) 0
#endif
-int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
- struct obd_export *dt_exp, struct obd_export *md_exp,
- struct lustre_md *md)
+static int mdc_get_lustre_md(struct obd_export *exp,
+ struct ptlrpc_request *req,
+ struct obd_export *dt_exp,
+ struct obd_export *md_exp,
+ struct lustre_md *md)
{
struct req_capsule *pill = &req->rq_pill;
int rc;
@@ -573,7 +575,7 @@ out:
return rc;
}
-int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
+static int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
{
return 0;
}
@@ -737,8 +739,8 @@ static void mdc_free_open(struct md_open_data *mod)
ptlrpc_request_committed(mod->mod_close_req, committed);
}
-int mdc_clear_open_replay_data(struct obd_export *exp,
- struct obd_client_handle *och)
+static int mdc_clear_open_replay_data(struct obd_export *exp,
+ struct obd_client_handle *och)
{
struct md_open_data *mod = och->och_mod;
@@ -2460,59 +2462,59 @@ static int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
}
static struct obd_ops mdc_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = mdc_setup,
- .o_precleanup = mdc_precleanup,
- .o_cleanup = mdc_cleanup,
- .o_add_conn = client_import_add_conn,
- .o_del_conn = client_import_del_conn,
- .o_connect = client_connect_import,
- .o_disconnect = client_disconnect_export,
- .o_iocontrol = mdc_iocontrol,
- .o_set_info_async = mdc_set_info_async,
- .o_statfs = mdc_statfs,
- .o_fid_init = client_fid_init,
- .o_fid_fini = client_fid_fini,
- .o_fid_alloc = mdc_fid_alloc,
- .o_import_event = mdc_import_event,
- .o_get_info = mdc_get_info,
- .o_process_config = mdc_process_config,
- .o_get_uuid = mdc_get_uuid,
- .o_quotactl = mdc_quotactl,
- .o_quotacheck = mdc_quotacheck
+ .owner = THIS_MODULE,
+ .setup = mdc_setup,
+ .precleanup = mdc_precleanup,
+ .cleanup = mdc_cleanup,
+ .add_conn = client_import_add_conn,
+ .del_conn = client_import_del_conn,
+ .connect = client_connect_import,
+ .disconnect = client_disconnect_export,
+ .iocontrol = mdc_iocontrol,
+ .set_info_async = mdc_set_info_async,
+ .statfs = mdc_statfs,
+ .fid_init = client_fid_init,
+ .fid_fini = client_fid_fini,
+ .fid_alloc = mdc_fid_alloc,
+ .import_event = mdc_import_event,
+ .get_info = mdc_get_info,
+ .process_config = mdc_process_config,
+ .get_uuid = mdc_get_uuid,
+ .quotactl = mdc_quotactl,
+ .quotacheck = mdc_quotacheck
};
static struct md_ops mdc_md_ops = {
- .m_getstatus = mdc_getstatus,
- .m_null_inode = mdc_null_inode,
- .m_find_cbdata = mdc_find_cbdata,
- .m_close = mdc_close,
- .m_create = mdc_create,
- .m_done_writing = mdc_done_writing,
- .m_enqueue = mdc_enqueue,
- .m_getattr = mdc_getattr,
- .m_getattr_name = mdc_getattr_name,
- .m_intent_lock = mdc_intent_lock,
- .m_link = mdc_link,
- .m_is_subdir = mdc_is_subdir,
- .m_rename = mdc_rename,
- .m_setattr = mdc_setattr,
- .m_setxattr = mdc_setxattr,
- .m_getxattr = mdc_getxattr,
- .m_sync = mdc_sync,
- .m_readpage = mdc_readpage,
- .m_unlink = mdc_unlink,
- .m_cancel_unused = mdc_cancel_unused,
- .m_init_ea_size = mdc_init_ea_size,
- .m_set_lock_data = mdc_set_lock_data,
- .m_lock_match = mdc_lock_match,
- .m_get_lustre_md = mdc_get_lustre_md,
- .m_free_lustre_md = mdc_free_lustre_md,
- .m_set_open_replay_data = mdc_set_open_replay_data,
- .m_clear_open_replay_data = mdc_clear_open_replay_data,
- .m_get_remote_perm = mdc_get_remote_perm,
- .m_intent_getattr_async = mdc_intent_getattr_async,
- .m_revalidate_lock = mdc_revalidate_lock
+ .getstatus = mdc_getstatus,
+ .null_inode = mdc_null_inode,
+ .find_cbdata = mdc_find_cbdata,
+ .close = mdc_close,
+ .create = mdc_create,
+ .done_writing = mdc_done_writing,
+ .enqueue = mdc_enqueue,
+ .getattr = mdc_getattr,
+ .getattr_name = mdc_getattr_name,
+ .intent_lock = mdc_intent_lock,
+ .link = mdc_link,
+ .is_subdir = mdc_is_subdir,
+ .rename = mdc_rename,
+ .setattr = mdc_setattr,
+ .setxattr = mdc_setxattr,
+ .getxattr = mdc_getxattr,
+ .sync = mdc_sync,
+ .readpage = mdc_readpage,
+ .unlink = mdc_unlink,
+ .cancel_unused = mdc_cancel_unused,
+ .init_ea_size = mdc_init_ea_size,
+ .set_lock_data = mdc_set_lock_data,
+ .lock_match = mdc_lock_match,
+ .get_lustre_md = mdc_get_lustre_md,
+ .free_lustre_md = mdc_free_lustre_md,
+ .set_open_replay_data = mdc_set_open_replay_data,
+ .clear_open_replay_data = mdc_clear_open_replay_data,
+ .get_remote_perm = mdc_get_remote_perm,
+ .intent_getattr_async = mdc_intent_getattr_async,
+ .revalidate_lock = mdc_revalidate_lock
};
static int __init mdc_init(void)
@@ -2530,7 +2532,7 @@ static void /*__exit*/ mdc_exit(void)
class_unregister_type(LUSTRE_MDC_NAME);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Metadata Client");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c
index 7315733bc5b0..2c4884727626 100644
--- a/drivers/staging/lustre/lustre/mgc/mgc_request.c
+++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c
@@ -440,8 +440,12 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
struct obd_import *imp;
struct obd_connect_data *ocd;
struct config_llog_data *cld;
+ int rc;
+
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
- LPROCFS_CLIMP_CHECK(obd);
imp = obd->u.cli.cl_import;
ocd = &imp->imp_connect_data;
@@ -459,7 +463,7 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
}
spin_unlock(&config_list_lock);
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
@@ -1108,7 +1112,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc,
LASSERT(cfg->cfg_instance != NULL);
LASSERT(cfg->cfg_sb == cfg->cfg_instance);
- inst = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
+ inst = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
if (!inst)
return -ENOMEM;
@@ -1304,14 +1308,14 @@ static int mgc_process_recover_log(struct obd_device *obd,
if (cfg->cfg_last_idx == 0) /* the first time */
nrpages = CONFIG_READ_NRPAGES_INIT;
- pages = kcalloc(nrpages, sizeof(*pages), GFP_NOFS);
+ pages = kcalloc(nrpages, sizeof(*pages), GFP_KERNEL);
if (pages == NULL) {
rc = -ENOMEM;
goto out;
}
for (i = 0; i < nrpages; i++) {
- pages[i] = alloc_page(GFP_IOFS);
+ pages[i] = alloc_page(GFP_KERNEL);
if (pages[i] == NULL) {
rc = -ENOMEM;
goto out;
@@ -1462,7 +1466,7 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
if (cld->cld_cfg.cfg_sb)
lsi = s2lsi(cld->cld_cfg.cfg_sb);
- env = kzalloc(sizeof(*env), GFP_NOFS);
+ env = kzalloc(sizeof(*env), GFP_KERNEL);
if (!env)
return -ENOMEM;
@@ -1694,20 +1698,20 @@ out:
}
static struct obd_ops mgc_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = mgc_setup,
- .o_precleanup = mgc_precleanup,
- .o_cleanup = mgc_cleanup,
- .o_add_conn = client_import_add_conn,
- .o_del_conn = client_import_del_conn,
- .o_connect = client_connect_import,
- .o_disconnect = client_disconnect_export,
- /* .o_enqueue = mgc_enqueue, */
- /* .o_iocontrol = mgc_iocontrol, */
- .o_set_info_async = mgc_set_info_async,
- .o_get_info = mgc_get_info,
- .o_import_event = mgc_import_event,
- .o_process_config = mgc_process_config,
+ .owner = THIS_MODULE,
+ .setup = mgc_setup,
+ .precleanup = mgc_precleanup,
+ .cleanup = mgc_cleanup,
+ .add_conn = client_import_add_conn,
+ .del_conn = client_import_del_conn,
+ .connect = client_connect_import,
+ .disconnect = client_disconnect_export,
+ /* .enqueue = mgc_enqueue, */
+ /* .iocontrol = mgc_iocontrol, */
+ .set_info_async = mgc_set_info_async,
+ .get_info = mgc_get_info,
+ .import_event = mgc_import_event,
+ .process_config = mgc_process_config,
};
static int __init mgc_init(void)
@@ -1721,7 +1725,7 @@ static void /*__exit*/ mgc_exit(void)
class_unregister_type(LUSTRE_MGC_NAME);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Management Client");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
index 4338aeed1f60..1836dc01499a 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
@@ -270,7 +270,7 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock)
lu_ref_fini(&lock->cll_reference);
lu_ref_fini(&lock->cll_holders);
mutex_destroy(&lock->cll_guard);
- OBD_SLAB_FREE_PTR(lock, cl_lock_kmem);
+ kmem_cache_free(cl_lock_kmem, lock);
}
/**
@@ -361,7 +361,7 @@ static struct cl_lock *cl_lock_alloc(const struct lu_env *env,
struct cl_lock *lock;
struct lu_object_header *head;
- OBD_SLAB_ALLOC_PTR_GFP(lock, cl_lock_kmem, GFP_NOFS);
+ lock = kmem_cache_alloc(cl_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (lock != NULL) {
atomic_set(&lock->cll_ref, 1);
lock->cll_descr = *descr;
@@ -687,7 +687,7 @@ EXPORT_SYMBOL(cl_lock_mutex_get);
*
* \see cl_lock_mutex_get()
*/
-int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock)
+static int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock)
{
int result;
@@ -705,7 +705,6 @@ int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock)
result = -EBUSY;
return result;
}
-EXPORT_SYMBOL(cl_lock_mutex_try);
/**
{* Unlocks cl_lock object.
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c
index a29540360fd5..a1a6024220ff 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c
@@ -586,12 +586,12 @@ static void cl_env_hops_noop(struct cfs_hash *hs, struct hlist_node *hn)
LASSERT(cle->ce_magic == &cl_env_init0);
}
-static cfs_hash_ops_t cl_env_hops = {
+static struct cfs_hash_ops cl_env_hops = {
.hs_hash = cl_env_hops_hash,
- .hs_key = cl_env_hops_obj,
+ .hs_key = cl_env_hops_obj,
.hs_keycmp = cl_env_hops_keycmp,
.hs_object = cl_env_hops_obj,
- .hs_get = cl_env_hops_noop,
+ .hs_get = cl_env_hops_noop,
.hs_put_locked = cl_env_hops_noop,
};
@@ -661,7 +661,7 @@ static struct lu_env *cl_env_new(__u32 ctx_tags, __u32 ses_tags, void *debug)
struct lu_env *env;
struct cl_env *cle;
- OBD_SLAB_ALLOC_PTR_GFP(cle, cl_env_kmem, GFP_NOFS);
+ cle = kmem_cache_alloc(cl_env_kmem, GFP_NOFS | __GFP_ZERO);
if (cle != NULL) {
int rc;
@@ -680,7 +680,7 @@ static struct lu_env *cl_env_new(__u32 ctx_tags, __u32 ses_tags, void *debug)
lu_env_fini(env);
}
if (rc != 0) {
- OBD_SLAB_FREE_PTR(cle, cl_env_kmem);
+ kmem_cache_free(cl_env_kmem, cle);
env = ERR_PTR(rc);
} else {
CL_ENV_INC(create);
@@ -696,7 +696,7 @@ static void cl_env_fini(struct cl_env *cle)
CL_ENV_DEC(total);
lu_context_fini(&cle->ce_lu.le_ctx);
lu_context_fini(&cle->ce_ses);
- OBD_SLAB_FREE_PTR(cle, cl_env_kmem);
+ kmem_cache_free(cl_env_kmem, cle);
}
static inline struct cl_env *cl_env_container(struct lu_env *env)
diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c
index 3e9c24684690..beb59f009cbe 100644
--- a/drivers/staging/lustre/lustre/obdclass/class_obd.c
+++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c
@@ -576,7 +576,7 @@ static void cleanup_obdclass(void)
obd_zombie_impexp_stop();
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION);
MODULE_LICENSE("GPL");
MODULE_VERSION(LUSTRE_VERSION_STRING);
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index ab0748b1765b..26f54f950350 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -68,7 +68,7 @@ static struct obd_device *obd_device_alloc(void)
{
struct obd_device *obd;
- OBD_SLAB_ALLOC_PTR_GFP(obd, obd_device_cachep, GFP_NOFS);
+ obd = kmem_cache_alloc(obd_device_cachep, GFP_NOFS | __GFP_ZERO);
if (obd != NULL)
obd->obd_magic = OBD_DEVICE_MAGIC;
return obd;
@@ -85,7 +85,7 @@ static void obd_device_free(struct obd_device *obd)
LBUG();
}
lu_ref_fini(&obd->obd_reference);
- OBD_SLAB_FREE_PTR(obd, obd_device_cachep);
+ kmem_cache_free(obd_device_cachep, obd);
}
static struct obd_type *class_search_type(const char *name)
@@ -132,7 +132,7 @@ static struct obd_type *class_get_type(const char *name)
if (type) {
spin_lock(&type->obd_type_lock);
type->typ_refcnt++;
- try_module_get(type->typ_dt_ops->o_owner);
+ try_module_get(type->typ_dt_ops->owner);
spin_unlock(&type->obd_type_lock);
}
return type;
@@ -143,7 +143,7 @@ void class_put_type(struct obd_type *type)
LASSERT(type);
spin_lock(&type->obd_type_lock);
type->typ_refcnt--;
- module_put(type->typ_dt_ops->o_owner);
+ module_put(type->typ_dt_ops->owner);
spin_unlock(&type->obd_type_lock);
}
EXPORT_SYMBOL(class_put_type);
@@ -155,7 +155,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
struct lu_device_type *ldt)
{
struct obd_type *type;
- int rc = 0;
+ int rc;
/* sanity check */
LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME);
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index 3228feed4747..dda5ad105f2e 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -489,16 +489,20 @@ int lprocfs_rd_server_uuid(struct seq_file *m, void *data)
struct obd_device *obd = data;
struct obd_import *imp;
char *imp_state_name = NULL;
+ int rc;
LASSERT(obd != NULL);
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
imp = obd->u.cli.cl_import;
imp_state_name = ptlrpc_import_state_name(imp->imp_state);
seq_printf(m, "%s\t%s%s\n",
obd2cli_tgt(obd), imp_state_name,
imp->imp_deactive ? "\tDEACTIVATED" : "");
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
@@ -508,17 +512,21 @@ int lprocfs_rd_conn_uuid(struct seq_file *m, void *data)
{
struct obd_device *obd = data;
struct ptlrpc_connection *conn;
+ int rc;
LASSERT(obd != NULL);
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
conn = obd->u.cli.cl_import->imp_connection;
if (conn && obd->u.cli.cl_import)
seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
else
seq_puts(m, "<none>\n");
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
@@ -610,6 +618,7 @@ static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep
int lprocfs_rd_import(struct seq_file *m, void *data)
{
+ char nidstr[LNET_NIDSTR_SIZE];
struct lprocfs_counter ret;
struct lprocfs_counter_header *header;
struct obd_device *obd = data;
@@ -618,9 +627,13 @@ int lprocfs_rd_import(struct seq_file *m, void *data)
int j;
int k;
int rw = 0;
+ int rc;
LASSERT(obd != NULL);
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
imp = obd->u.cli.cl_import;
seq_printf(m,
@@ -647,18 +660,23 @@ int lprocfs_rd_import(struct seq_file *m, void *data)
spin_lock(&imp->imp_lock);
j = 0;
list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
- seq_printf(m, "%s%s", j ? ", " : "",
- libcfs_nid2str(conn->oic_conn->c_peer.nid));
+ libcfs_nid2str_r(conn->oic_conn->c_peer.nid,
+ nidstr, sizeof(nidstr));
+ seq_printf(m, "%s%s", j ? ", " : "", nidstr);
j++;
}
+ if (imp->imp_connection != NULL)
+ libcfs_nid2str_r(imp->imp_connection->c_peer.nid,
+ nidstr, sizeof(nidstr));
+ else
+ strncpy(nidstr, "<none>", sizeof(nidstr));
seq_printf(m,
"]\n"
" current_connection: %s\n"
" connection_attempts: %u\n"
" generation: %u\n"
" in-progress_invalidations: %u\n",
- imp->imp_connection == NULL ? "<none>" :
- libcfs_nid2str(imp->imp_connection->c_peer.nid),
+ nidstr,
imp->imp_conn_cnt,
imp->imp_generation,
atomic_read(&imp->imp_inval_count));
@@ -750,7 +768,7 @@ int lprocfs_rd_import(struct seq_file *m, void *data)
}
out_climp:
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
EXPORT_SYMBOL(lprocfs_rd_import);
@@ -759,10 +777,13 @@ int lprocfs_rd_state(struct seq_file *m, void *data)
{
struct obd_device *obd = data;
struct obd_import *imp;
- int j, k;
+ int j, k, rc;
LASSERT(obd != NULL);
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
imp = obd->u.cli.cl_import;
seq_printf(m, "current_state: %s\n",
@@ -778,7 +799,7 @@ int lprocfs_rd_state(struct seq_file *m, void *data)
ptlrpc_import_state_name(ish->ish_state));
}
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
EXPORT_SYMBOL(lprocfs_rd_state);
@@ -802,10 +823,13 @@ int lprocfs_rd_timeouts(struct seq_file *m, void *data)
unsigned int cur, worst;
time64_t now, worstt;
struct dhms ts;
- int i;
+ int i, rc;
LASSERT(obd != NULL);
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
imp = obd->u.cli.cl_import;
now = ktime_get_real_seconds();
@@ -836,7 +860,7 @@ int lprocfs_rd_timeouts(struct seq_file *m, void *data)
lprocfs_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
}
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
EXPORT_SYMBOL(lprocfs_rd_timeouts);
@@ -845,13 +869,17 @@ int lprocfs_rd_connect_flags(struct seq_file *m, void *data)
{
struct obd_device *obd = data;
__u64 flags;
+ int rc;
+
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
- LPROCFS_CLIMP_CHECK(obd);
flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
seq_printf(m, "flags=%#llx\n", flags);
obd_connect_seq_flags2str(m, flags, "\n");
seq_printf(m, "\n");
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
EXPORT_SYMBOL(lprocfs_rd_connect_flags);
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
index 0d15bd5b05b7..0193608a930a 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
@@ -916,12 +916,12 @@ static void lu_obj_hop_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
LBUG(); /* we should never called it */
}
-cfs_hash_ops_t lu_site_hash_ops = {
+struct cfs_hash_ops lu_site_hash_ops = {
.hs_hash = lu_obj_hop_hash,
- .hs_key = lu_obj_hop_key,
+ .hs_key = lu_obj_hop_key,
.hs_keycmp = lu_obj_hop_keycmp,
.hs_object = lu_obj_hop_object,
- .hs_get = lu_obj_hop_get,
+ .hs_get = lu_obj_hop_get,
.hs_put_locked = lu_obj_hop_put_locked,
};
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
index 38e5e13c7fde..c231e0da0e2a 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
@@ -47,7 +47,7 @@
#include "llog_internal.h"
-static cfs_hash_ops_t uuid_hash_ops;
+static struct cfs_hash_ops uuid_hash_ops;
/*********** string parsing utils *********/
@@ -1316,10 +1316,13 @@ static int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf,
if (lcfg->lcfg_num)
ptr += snprintf(ptr, end-ptr, "num=%#08x ", lcfg->lcfg_num);
- if (lcfg->lcfg_nid)
+ if (lcfg->lcfg_nid) {
+ char nidstr[LNET_NIDSTR_SIZE];
+
+ libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr));
ptr += snprintf(ptr, end-ptr, "nid=%s(%#llx)\n ",
- libcfs_nid2str(lcfg->lcfg_nid),
- lcfg->lcfg_nid);
+ nidstr, lcfg->lcfg_nid);
+ }
if (lcfg->lcfg_command == LCFG_MARKER) {
struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
@@ -1470,11 +1473,11 @@ uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
class_export_put(exp);
}
-static cfs_hash_ops_t uuid_hash_ops = {
+static struct cfs_hash_ops uuid_hash_ops = {
.hs_hash = uuid_hash,
- .hs_key = uuid_key,
+ .hs_key = uuid_key,
.hs_keycmp = uuid_keycmp,
.hs_object = uuid_export_object,
- .hs_get = uuid_export_get,
+ .hs_get = uuid_export_get,
.hs_put_locked = uuid_export_put_locked,
};
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index 149c83813583..7617c57d16e0 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -209,9 +209,10 @@ int lustre_start_mgc(struct super_block *sb)
struct obd_uuid *uuid;
class_uuid_t uuidc;
lnet_nid_t nid;
+ char nidstr[LNET_NIDSTR_SIZE];
char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
char *ptr;
- int rc = 0, i = 0, j, len;
+ int rc = 0, i = 0, j;
LASSERT(lsi->lsi_lmd);
@@ -226,9 +227,9 @@ int lustre_start_mgc(struct super_block *sb)
mutex_lock(&mgc_start_lock);
- len = strlen(LUSTRE_MGC_OBDNAME) + strlen(libcfs_nid2str(nid)) + 1;
+ libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
mgcname = kasprintf(GFP_NOFS,
- "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
+ "%s%s", LUSTRE_MGC_OBDNAME, nidstr);
niduuid = kasprintf(GFP_NOFS, "%s_%x", mgcname, i);
if (!mgcname || !niduuid) {
rc = -ENOMEM;
@@ -891,7 +892,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
}
lmd->lmd_magic = LMD_MAGIC;
- lmd->lmd_params = kzalloc(4096, GFP_NOFS);
+ lmd->lmd_params = kzalloc(LMD_PARAMS_MAXLEN, GFP_NOFS);
if (!lmd->lmd_params)
return -ENOMEM;
lmd->lmd_params[0] = '\0';
@@ -977,7 +978,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
goto invalid;
clear++;
} else if (strncmp(s1, "param=", 6) == 0) {
- int length;
+ size_t length, params_length;
char *tail = strchr(s1 + 6, ',');
if (tail == NULL)
@@ -985,8 +986,12 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
else
length = tail - s1;
length -= 6;
+ params_length = strlen(lmd->lmd_params);
+ if (params_length + length + 1 >= LMD_PARAMS_MAXLEN)
+ return -E2BIG;
strncat(lmd->lmd_params, s1 + 6, length);
- strcat(lmd->lmd_params, " ");
+ lmd->lmd_params[params_length + length] = '\0';
+ strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN);
clear++;
} else if (strncmp(s1, "osd=", 4) == 0) {
rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4);
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index ef9cb31ecb57..14ac56bb0d77 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -337,7 +337,7 @@ static void echo_lock_fini(const struct lu_env *env,
struct echo_lock *ecl = cl2echo_lock(slice);
LASSERT(list_empty(&ecl->el_chain));
- OBD_SLAB_FREE_PTR(ecl, echo_lock_kmem);
+ kmem_cache_free(echo_lock_kmem, ecl);
}
static void echo_lock_delete(const struct lu_env *env,
@@ -396,7 +396,7 @@ static int echo_lock_init(const struct lu_env *env,
{
struct echo_lock *el;
- OBD_SLAB_ALLOC_PTR_GFP(el, echo_lock_kmem, GFP_NOFS);
+ el = kmem_cache_alloc(echo_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (el != NULL) {
cl_lock_slice_add(lock, &el->el_cl, obj, &echo_lock_ops);
el->el_object = cl2echo_obj(obj);
@@ -530,7 +530,7 @@ static void echo_object_free(const struct lu_env *env, struct lu_object *obj)
if (eco->eo_lsm)
echo_free_memmd(eco->eo_dev, &eco->eo_lsm);
- OBD_SLAB_FREE_PTR(eco, echo_object_kmem);
+ kmem_cache_free(echo_object_kmem, eco);
}
static int echo_object_print(const struct lu_env *env, void *cookie,
@@ -567,7 +567,7 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env,
/* we're the top dev. */
LASSERT(hdr == NULL);
- OBD_SLAB_ALLOC_PTR_GFP(eco, echo_object_kmem, GFP_NOFS);
+ eco = kmem_cache_alloc(echo_object_kmem, GFP_NOFS | __GFP_ZERO);
if (eco != NULL) {
struct cl_object_header *hdr = &eco->eo_hdr;
@@ -630,7 +630,7 @@ static void *echo_thread_key_init(const struct lu_context *ctx,
{
struct echo_thread_info *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, echo_thread_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(echo_thread_kmem, GFP_NOFS | __GFP_ZERO);
if (info == NULL)
info = ERR_PTR(-ENOMEM);
return info;
@@ -641,7 +641,7 @@ static void echo_thread_key_fini(const struct lu_context *ctx,
{
struct echo_thread_info *info = data;
- OBD_SLAB_FREE_PTR(info, echo_thread_kmem);
+ kmem_cache_free(echo_thread_kmem, info);
}
static void echo_thread_key_exit(const struct lu_context *ctx,
@@ -661,7 +661,7 @@ static void *echo_session_key_init(const struct lu_context *ctx,
{
struct echo_session_info *session;
- OBD_SLAB_ALLOC_PTR_GFP(session, echo_session_kmem, GFP_NOFS);
+ session = kmem_cache_alloc(echo_session_kmem, GFP_NOFS | __GFP_ZERO);
if (session == NULL)
session = ERR_PTR(-ENOMEM);
return session;
@@ -672,7 +672,7 @@ static void echo_session_key_fini(const struct lu_context *ctx,
{
struct echo_session_info *session = data;
- OBD_SLAB_FREE_PTR(session, echo_session_kmem);
+ kmem_cache_free(echo_session_kmem, session);
}
static void echo_session_key_exit(const struct lu_context *ctx,
@@ -1562,7 +1562,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
(oa->o_valid & OBD_MD_FLFLAGS) != 0 &&
(oa->o_flags & OBD_FL_DEBUG_CHECK) != 0);
- gfp_mask = ((ostid_id(&oa->o_oi) & 2) == 0) ? GFP_IOFS : GFP_HIGHUSER;
+ gfp_mask = ((ostid_id(&oa->o_oi) & 2) == 0) ? GFP_KERNEL : GFP_HIGHUSER;
LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ);
LASSERT(lsm != NULL);
@@ -1595,7 +1595,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
LASSERT(pgp->pg == NULL); /* for cleanup */
rc = -ENOMEM;
- OBD_PAGE_ALLOC(pgp->pg, gfp_mask);
+ pgp->pg = alloc_page(gfp_mask);
if (pgp->pg == NULL)
goto out;
@@ -1631,7 +1631,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
if (vrc != 0 && rc == 0)
rc = vrc;
}
- OBD_PAGE_FREE(pgp->pg);
+ __free_page(pgp->pg);
}
kfree(pga);
kfree(pages);
@@ -2128,10 +2128,10 @@ static int echo_client_disconnect(struct obd_export *exp)
}
static struct obd_ops echo_client_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_iocontrol = echo_client_iocontrol,
- .o_connect = echo_client_connect,
- .o_disconnect = echo_client_disconnect
+ .owner = THIS_MODULE,
+ .iocontrol = echo_client_iocontrol,
+ .connect = echo_client_connect,
+ .disconnect = echo_client_disconnect
};
static int echo_client_init(void)
@@ -2170,7 +2170,7 @@ static void /*__exit*/ obdecho_exit(void)
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Testing Echo OBD driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(LUSTRE_VERSION_STRING);
diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c
index cdc7f889564e..c4d44e70f1d7 100644
--- a/drivers/staging/lustre/lustre/osc/lproc_osc.c
+++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c
@@ -61,7 +61,9 @@ static ssize_t active_store(struct kobject *kobj, struct attribute *attr,
unsigned long val;
rc = kstrtoul(buffer, 10, &val);
- if (rc < 0)
+ if (rc)
+ return rc;
+ if (val > 1)
return -ERANGE;
/* opposite senses */
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index b552a5611fdf..b1d1a87f05e3 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -346,7 +346,7 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj)
{
struct osc_extent *ext;
- OBD_SLAB_ALLOC_PTR_GFP(ext, osc_extent_kmem, GFP_IOFS);
+ ext = kmem_cache_alloc(osc_extent_kmem, GFP_NOFS | __GFP_ZERO);
if (ext == NULL)
return NULL;
@@ -365,7 +365,7 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj)
static void osc_extent_free(struct osc_extent *ext)
{
- OBD_SLAB_FREE_PTR(ext, osc_extent_kmem);
+ kmem_cache_free(osc_extent_kmem, ext);
}
static struct osc_extent *osc_extent_get(struct osc_extent *ext)
diff --git a/drivers/staging/lustre/lustre/osc/osc_dev.c b/drivers/staging/lustre/lustre/osc/osc_dev.c
index 91fdec44792b..69b523c0f570 100644
--- a/drivers/staging/lustre/lustre/osc/osc_dev.c
+++ b/drivers/staging/lustre/lustre/osc/osc_dev.c
@@ -122,7 +122,7 @@ static void *osc_key_init(const struct lu_context *ctx,
{
struct osc_thread_info *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, osc_thread_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(osc_thread_kmem, GFP_NOFS | __GFP_ZERO);
if (info == NULL)
info = ERR_PTR(-ENOMEM);
return info;
@@ -133,7 +133,7 @@ static void osc_key_fini(const struct lu_context *ctx,
{
struct osc_thread_info *info = data;
- OBD_SLAB_FREE_PTR(info, osc_thread_kmem);
+ kmem_cache_free(osc_thread_kmem, info);
}
struct lu_context_key osc_key = {
@@ -147,7 +147,7 @@ static void *osc_session_init(const struct lu_context *ctx,
{
struct osc_session *info;
- OBD_SLAB_ALLOC_PTR_GFP(info, osc_session_kmem, GFP_NOFS);
+ info = kmem_cache_alloc(osc_session_kmem, GFP_NOFS | __GFP_ZERO);
if (info == NULL)
info = ERR_PTR(-ENOMEM);
return info;
@@ -158,7 +158,7 @@ static void osc_session_fini(const struct lu_context *ctx,
{
struct osc_session *info = data;
- OBD_SLAB_FREE_PTR(info, osc_session_kmem);
+ kmem_cache_free(osc_session_kmem, info);
}
struct lu_context_key osc_session_key = {
diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h
index 5ed30ecc84e3..db2ee9c23b42 100644
--- a/drivers/staging/lustre/lustre/osc/osc_internal.h
+++ b/drivers/staging/lustre/lustre/osc/osc_internal.h
@@ -89,11 +89,6 @@ struct osc_cache_waiter {
int ocw_rc;
};
-int osc_create(const struct lu_env *env, struct obd_export *exp,
- struct obdo *oa, struct lov_stripe_md **ea,
- struct obd_trans_info *oti);
-int osc_real_create(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md **ea, struct obd_trans_info *oti);
void osc_wake_cache_waiters(struct client_obd *cli);
int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes);
void osc_update_next_shrink(struct client_obd *cli);
@@ -137,7 +132,6 @@ int osc_lru_shrink(struct client_obd *cli, int target);
extern spinlock_t osc_ast_guard;
-int osc_cleanup(struct obd_device *obd);
int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg);
int lproc_osc_attach_seqstat(struct obd_device *dev);
diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c
index 3a4200fa8b6f..d413496c0f63 100644
--- a/drivers/staging/lustre/lustre/osc/osc_io.c
+++ b/drivers/staging/lustre/lustre/osc/osc_io.c
@@ -700,7 +700,7 @@ static void osc_req_completion(const struct lu_env *env,
struct osc_req *or;
or = cl2osc_req(slice);
- OBD_SLAB_FREE_PTR(or, osc_req_kmem);
+ kmem_cache_free(osc_req_kmem, or);
}
/**
@@ -803,7 +803,7 @@ int osc_req_init(const struct lu_env *env, struct cl_device *dev,
struct osc_req *or;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(or, osc_req_kmem, GFP_NOFS);
+ or = kmem_cache_alloc(osc_req_kmem, GFP_NOFS | __GFP_ZERO);
if (or != NULL) {
cl_req_slice_add(req, &or->or_cl, dev, &osc_req_ops);
result = 0;
diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c
index 70b1b43f692b..194490dcaca9 100644
--- a/drivers/staging/lustre/lustre/osc/osc_lock.c
+++ b/drivers/staging/lustre/lustre/osc/osc_lock.c
@@ -251,7 +251,7 @@ static void osc_lock_fini(const struct lu_env *env,
LASSERT(atomic_read(&ols->ols_pageref) == 0 ||
atomic_read(&ols->ols_pageref) == _PAGEREF_MAGIC);
- OBD_SLAB_FREE_PTR(ols, osc_lock_kmem);
+ kmem_cache_free(osc_lock_kmem, ols);
}
static void osc_lock_build_policy(const struct lu_env *env,
@@ -1555,7 +1555,7 @@ int osc_lock_init(const struct lu_env *env,
struct osc_lock *clk;
int result;
- OBD_SLAB_ALLOC_PTR_GFP(clk, osc_lock_kmem, GFP_NOFS);
+ clk = kmem_cache_alloc(osc_lock_kmem, GFP_NOFS | __GFP_ZERO);
if (clk != NULL) {
__u32 enqflags = lock->cll_descr.cld_enq_flags;
diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c
index acffab954ad7..ba57f8df5c7f 100644
--- a/drivers/staging/lustre/lustre/osc/osc_object.c
+++ b/drivers/staging/lustre/lustre/osc/osc_object.c
@@ -122,7 +122,7 @@ static void osc_object_free(const struct lu_env *env, struct lu_object *obj)
LASSERT(atomic_read(&osc->oo_nr_writes) == 0);
lu_object_fini(obj);
- OBD_SLAB_FREE_PTR(osc, osc_object_kmem);
+ kmem_cache_free(osc_object_kmem, osc);
}
int osc_lvb_print(const struct lu_env *env, void *cookie,
@@ -255,7 +255,7 @@ struct lu_object *osc_object_alloc(const struct lu_env *env,
struct osc_object *osc;
struct lu_object *obj;
- OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS);
+ osc = kmem_cache_alloc(osc_object_kmem, GFP_NOFS | __GFP_ZERO);
if (osc != NULL) {
obj = osc2lu(osc);
lu_object_init(obj, NULL, dev);
diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c
index 3b32928eb4fc..199783103f71 100644
--- a/drivers/staging/lustre/lustre/osc/osc_quota.c
+++ b/drivers/staging/lustre/lustre/osc/osc_quota.c
@@ -35,7 +35,7 @@ static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
{
struct osc_quota_info *oqi;
- OBD_SLAB_ALLOC_PTR(oqi, osc_quota_kmem);
+ oqi = kmem_cache_alloc(osc_quota_kmem, GFP_NOFS | __GFP_ZERO);
if (oqi != NULL)
oqi->oqi_id = id;
@@ -104,7 +104,7 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
/* race with others? */
if (rc == -EALREADY) {
rc = 0;
- OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
+ kmem_cache_free(osc_quota_kmem, oqi);
}
CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
@@ -120,7 +120,7 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
&qid[type]);
if (oqi)
- OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
+ kmem_cache_free(osc_quota_kmem, oqi);
CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
cli->cl_import->imp_obd->obd_name,
@@ -186,14 +186,14 @@ oqi_exit(struct cfs_hash *hs, struct hlist_node *hnode)
oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
- OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
+ kmem_cache_free(osc_quota_kmem, oqi);
}
#define HASH_QUOTA_BKT_BITS 5
#define HASH_QUOTA_CUR_BITS 5
#define HASH_QUOTA_MAX_BITS 15
-static cfs_hash_ops_t quota_hash_ops = {
+static struct cfs_hash_ops quota_hash_ops = {
.hs_hash = oqi_hashfn,
.hs_keycmp = oqi_keycmp,
.hs_key = oqi_key,
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index 32c9713d47eb..d6c1447f6bd9 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -104,7 +104,7 @@ struct osc_enqueue_args {
static void osc_release_ppga(struct brw_page **ppga, u32 count);
static int brw_interpret(const struct lu_env *env,
struct ptlrpc_request *req, void *data, int rc);
-int osc_cleanup(struct obd_device *obd);
+static int osc_cleanup(struct obd_device *obd);
/* Pack OSC object metadata for disk storage (LE byte order). */
static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
@@ -431,8 +431,9 @@ static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
oinfo->oi_cb_up, oinfo, rqset);
}
-int osc_real_create(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md **ea, struct obd_trans_info *oti)
+static int osc_real_create(struct obd_export *exp, struct obdo *oa,
+ struct lov_stripe_md **ea,
+ struct obd_trans_info *oti)
{
struct ptlrpc_request *req;
struct ost_body *body;
@@ -689,9 +690,9 @@ static int osc_can_send_destroy(struct client_obd *cli)
return 0;
}
-int osc_create(const struct lu_env *env, struct obd_export *exp,
- struct obdo *oa, struct lov_stripe_md **ea,
- struct obd_trans_info *oti)
+static int osc_create(const struct lu_env *env, struct obd_export *exp,
+ struct obdo *oa, struct lov_stripe_md **ea,
+ struct obd_trans_info *oti)
{
int rc = 0;
@@ -878,7 +879,7 @@ static int osc_shrink_grant_interpret(const struct lu_env *env,
LASSERT(body);
osc_update_grant(cli, body);
out:
- OBDO_FREE(oa);
+ kmem_cache_free(obdo_cachep, oa);
return rc;
}
@@ -1547,8 +1548,8 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
if (body->oa.o_valid & OBD_MD_FLCKSUM) {
static int cksum_counter;
__u32 server_cksum = body->oa.o_cksum;
- char *via;
- char *router;
+ char *via = "";
+ char *router = "";
cksum_type_t cksum_type;
cksum_type = cksum_type_unpack(body->oa.o_valid&OBD_MD_FLFLAGS ?
@@ -1557,9 +1558,7 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
aa->aa_ppga, OST_READ,
cksum_type);
- if (peer->nid == req->rq_bulk->bd_sender) {
- via = router = "";
- } else {
+ if (peer->nid != req->rq_bulk->bd_sender) {
via = " via ";
router = libcfs_nid2str(req->rq_bulk->bd_sender);
}
@@ -1789,7 +1788,7 @@ static int brw_interpret(const struct lu_env *env,
}
cl_object_put(env, obj);
}
- OBDO_FREE(aa->aa_oa);
+ kmem_cache_free(obdo_cachep, aa->aa_oa);
cl_req_completion(env, aa->aa_clerq, rc < 0 ? rc :
req->rq_bulk->bd_nob_transferred);
@@ -1877,7 +1876,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
goto out;
}
- OBDO_ALLOC(oa);
+ oa = kmem_cache_alloc(obdo_cachep, GFP_NOFS | __GFP_ZERO);
if (oa == NULL) {
rc = -ENOMEM;
goto out;
@@ -2005,7 +2004,7 @@ out:
LASSERT(req == NULL);
if (oa)
- OBDO_FREE(oa);
+ kmem_cache_free(obdo_cachep, oa);
kfree(pga);
/* this should happen rarely and is pretty bad, it makes the
* pending list not follow the dirty order */
@@ -2917,7 +2916,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args));
aa = ptlrpc_req_async_args(req);
- OBDO_ALLOC(oa);
+ oa = kmem_cache_alloc(obdo_cachep, GFP_NOFS | __GFP_ZERO);
if (!oa) {
ptlrpc_req_finished(req);
return -ENOMEM;
@@ -3257,33 +3256,33 @@ static int osc_process_config(struct obd_device *obd, u32 len, void *buf)
}
struct obd_ops osc_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = osc_setup,
- .o_precleanup = osc_precleanup,
- .o_cleanup = osc_cleanup,
- .o_add_conn = client_import_add_conn,
- .o_del_conn = client_import_del_conn,
- .o_connect = client_connect_import,
- .o_reconnect = osc_reconnect,
- .o_disconnect = osc_disconnect,
- .o_statfs = osc_statfs,
- .o_statfs_async = osc_statfs_async,
- .o_packmd = osc_packmd,
- .o_unpackmd = osc_unpackmd,
- .o_create = osc_create,
- .o_destroy = osc_destroy,
- .o_getattr = osc_getattr,
- .o_getattr_async = osc_getattr_async,
- .o_setattr = osc_setattr,
- .o_setattr_async = osc_setattr_async,
- .o_find_cbdata = osc_find_cbdata,
- .o_iocontrol = osc_iocontrol,
- .o_get_info = osc_get_info,
- .o_set_info_async = osc_set_info_async,
- .o_import_event = osc_import_event,
- .o_process_config = osc_process_config,
- .o_quotactl = osc_quotactl,
- .o_quotacheck = osc_quotacheck,
+ .owner = THIS_MODULE,
+ .setup = osc_setup,
+ .precleanup = osc_precleanup,
+ .cleanup = osc_cleanup,
+ .add_conn = client_import_add_conn,
+ .del_conn = client_import_del_conn,
+ .connect = client_connect_import,
+ .reconnect = osc_reconnect,
+ .disconnect = osc_disconnect,
+ .statfs = osc_statfs,
+ .statfs_async = osc_statfs_async,
+ .packmd = osc_packmd,
+ .unpackmd = osc_unpackmd,
+ .create = osc_create,
+ .destroy = osc_destroy,
+ .getattr = osc_getattr,
+ .getattr_async = osc_getattr_async,
+ .setattr = osc_setattr,
+ .setattr_async = osc_setattr_async,
+ .find_cbdata = osc_find_cbdata,
+ .iocontrol = osc_iocontrol,
+ .get_info = osc_get_info,
+ .set_info_async = osc_set_info_async,
+ .import_event = osc_import_event,
+ .process_config = osc_process_config,
+ .quotactl = osc_quotactl,
+ .quotacheck = osc_quotacheck,
};
extern struct lu_kmem_descr osc_caches[];
@@ -3359,7 +3358,7 @@ static void /*__exit*/ osc_exit(void)
ptlrpc_free_rq_pool(osc_rq_pool);
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Object Storage Client (OSC)");
MODULE_LICENSE("GPL");
MODULE_VERSION(LUSTRE_VERSION_STRING);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index 9bf13d7096a8..a9f1bf536da9 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -72,9 +72,11 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid)
lnet_process_id_t peer;
int err;
- /* ptlrpc_uuid_to_peer() initializes its 2nd parameter
- * before accessing its values. */
- /* coverity[uninit_use_in_call] */
+ /*
+ * ptlrpc_uuid_to_peer() initializes its 2nd parameter
+ * before accessing its values.
+ * coverity[uninit_use_in_call]
+ */
err = ptlrpc_uuid_to_peer(uuid, &peer, &self);
if (err != 0) {
CNETERR("cannot find peer %s!\n", uuid->uuid);
@@ -117,8 +119,10 @@ struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw,
desc->bd_md_count = 0;
LASSERT(max_brw > 0);
desc->bd_md_max_brw = min(max_brw, PTLRPC_BULK_OPS_COUNT);
- /* PTLRPC_BULK_OPS_COUNT is the compile-time transfer limit for this
- * node. Negotiated ocd_brw_size will always be <= this number. */
+ /*
+ * PTLRPC_BULK_OPS_COUNT is the compile-time transfer limit for this
+ * node. Negotiated ocd_brw_size will always be <= this number.
+ */
for (i = 0; i < PTLRPC_BULK_OPS_COUNT; i++)
LNetInvalidateHandle(&desc->bd_mds[i]);
@@ -223,8 +227,9 @@ void ptlrpc_at_set_req_timeout(struct ptlrpc_request *req)
LASSERT(req->rq_import);
if (AT_OFF) {
- /* non-AT settings */
- /**
+ /*
+ * non-AT settings
+ *
* \a imp_server_timeout means this is reverse import and
* we send (currently only) ASTs to the client and cannot afford
* to wait too long for the reply, otherwise the other client
@@ -240,11 +245,15 @@ void ptlrpc_at_set_req_timeout(struct ptlrpc_request *req)
serv_est = at_get(&at->iat_service_estimate[idx]);
req->rq_timeout = at_est2timeout(serv_est);
}
- /* We could get even fancier here, using history to predict increased
- loading... */
+ /*
+ * We could get even fancier here, using history to predict increased
+ * loading...
+ */
- /* Let the server know what this RPC timeout is by putting it in the
- reqmsg*/
+ /*
+ * Let the server know what this RPC timeout is by putting it in the
+ * reqmsg
+ */
lustre_msg_set_timeout(req->rq_reqmsg, req->rq_timeout);
}
EXPORT_SYMBOL(ptlrpc_at_set_req_timeout);
@@ -261,8 +270,10 @@ static void ptlrpc_at_adj_service(struct ptlrpc_request *req,
at = &req->rq_import->imp_at;
idx = import_at_get_index(req->rq_import, req->rq_request_portal);
- /* max service estimates are tracked on the server side,
- so just keep minimal history here */
+ /*
+ * max service estimates are tracked on the server side,
+ * so just keep minimal history here
+ */
oldse = at_measured(&at->iat_service_estimate[idx], serv_est);
if (oldse != 0)
CDEBUG(D_ADAPTTO, "The RPC service estimate for %s ptl %d has changed from %d to %d\n",
@@ -287,7 +298,8 @@ static void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req,
LASSERT(req->rq_import);
if (service_time > now - req->rq_sent + 3) {
- /* bz16408, however, this can also happen if early reply
+ /*
+ * bz16408, however, this can also happen if early reply
* is lost and client RPC is expired and resent, early reply
* or reply of original RPC can still be fit in reply buffer
* of resent RPC, now client is measuring time from the
@@ -376,8 +388,10 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
spin_lock(&req->rq_lock);
olddl = req->rq_deadline;
- /* server assumes it now has rq_timeout from when it sent the
- * early reply, so client should give it at least that long. */
+ /*
+ * server assumes it now has rq_timeout from when it sent the
+ * early reply, so client should give it at least that long.
+ */
req->rq_deadline = ktime_get_real_seconds() + req->rq_timeout +
ptlrpc_at_get_net_latency(req);
@@ -409,13 +423,13 @@ struct ptlrpc_request *ptlrpc_request_cache_alloc(gfp_t flags)
{
struct ptlrpc_request *req;
- OBD_SLAB_ALLOC_PTR_GFP(req, request_cache, flags);
+ req = kmem_cache_alloc(request_cache, flags | __GFP_ZERO);
return req;
}
void ptlrpc_request_cache_free(struct ptlrpc_request *req)
{
- OBD_SLAB_FREE_PTR(req, request_cache);
+ kmem_cache_free(request_cache, req);
}
/**
@@ -503,8 +517,10 @@ ptlrpc_init_rq_pool(int num_rq, int msgsize,
if (!pool)
return NULL;
- /* Request next power of two for the allocation, because internally
- kernel would do exactly this */
+ /*
+ * Request next power of two for the allocation, because internally
+ * kernel would do exactly this
+ */
spin_lock_init(&pool->prp_lock);
INIT_LIST_HEAD(&pool->prp_req_list);
@@ -531,10 +547,12 @@ ptlrpc_prep_req_from_pool(struct ptlrpc_request_pool *pool)
spin_lock(&pool->prp_lock);
- /* See if we have anything in a pool, and bail out if nothing,
+ /*
+ * See if we have anything in a pool, and bail out if nothing,
* in writeout path, where this matters, this is safe to do, because
* nothing is lost in this case, and when some in-flight requests
- * complete, this code will be called again. */
+ * complete, this code will be called again.
+ */
if (unlikely(list_empty(&pool->prp_req_list))) {
spin_unlock(&pool->prp_lock);
return NULL;
@@ -665,7 +683,8 @@ int ptlrpc_request_pack(struct ptlrpc_request *request,
if (rc)
return rc;
- /* For some old 1.8 clients (< 1.8.7), they will LASSERT the size of
+ /*
+ * For some old 1.8 clients (< 1.8.7), they will LASSERT the size of
* ptlrpc_body sent from server equal to local ptlrpc_body size, so we
* have to send old ptlrpc_body to keep interoperability with these
* clients.
@@ -936,8 +955,10 @@ void ptlrpc_set_add_req(struct ptlrpc_request_set *set,
lustre_msg_set_jobid(req->rq_reqmsg, NULL);
if (set->set_producer != NULL)
- /* If the request set has a producer callback, the RPC must be
- * sent straight away */
+ /*
+ * If the request set has a producer callback, the RPC must be
+ * sent straight away
+ */
ptlrpc_send_new_req(req);
}
EXPORT_SYMBOL(ptlrpc_set_add_req);
@@ -957,9 +978,7 @@ void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc,
LASSERT(test_bit(LIOD_STOP, &pc->pc_flags) == 0);
spin_lock(&set->set_new_req_lock);
- /*
- * The set takes over the caller's request reference.
- */
+ /* The set takes over the caller's request reference. */
req->rq_set = set;
req->rq_queued_time = cfs_time_current();
list_add_tail(&req->rq_set_chain, &set->set_new_requests);
@@ -970,9 +989,11 @@ void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc,
if (count == 1) {
wake_up(&set->set_waitq);
- /* XXX: It maybe unnecessary to wakeup all the partners. But to
+ /*
+ * XXX: It maybe unnecessary to wakeup all the partners. But to
* guarantee the async RPC can be processed ASAP, we have
- * no other better choice. It maybe fixed in future. */
+ * no other better choice. It maybe fixed in future.
+ */
for (i = 0; i < pc->pc_npartners; i++)
wake_up(&pc->pc_partners[i]->pc_set->set_waitq);
}
@@ -1060,8 +1081,10 @@ static int ptlrpc_console_allow(struct ptlrpc_request *req)
LASSERT(req->rq_reqmsg != NULL);
opc = lustre_msg_get_opc(req->rq_reqmsg);
- /* Suppress particular reconnect errors which are to be expected. No
- * errors are suppressed for the initial connection on an import */
+ /*
+ * Suppress particular reconnect errors which are to be expected. No
+ * errors are suppressed for the initial connection on an import
+ */
if ((lustre_handle_is_used(&req->rq_import->imp_remote_handle)) &&
(opc == OST_CONNECT || opc == MDS_CONNECT || opc == MGS_CONNECT)) {
@@ -1156,10 +1179,11 @@ static int after_reply(struct ptlrpc_request *req)
}
sptlrpc_cli_free_repbuf(req);
- /* Pass the required reply buffer size (include
- * space for early reply).
- * NB: no need to roundup because alloc_repbuf
- * will roundup it */
+ /*
+ * Pass the required reply buffer size (include space for early
+ * reply). NB: no need to round up because alloc_repbuf will
+ * round it up
+ */
req->rq_replen = req->rq_nob_received;
req->rq_nob_received = 0;
spin_lock(&req->rq_lock);
@@ -1178,9 +1202,7 @@ static int after_reply(struct ptlrpc_request *req)
return rc;
}
- /*
- * Security layer unwrap might ask resend this request.
- */
+ /* Security layer unwrap might ask resend this request. */
if (req->rq_resend)
return 0;
@@ -1201,18 +1223,19 @@ static int after_reply(struct ptlrpc_request *req)
/* allocate new xid to avoid reply reconstruction */
if (!req->rq_bulk) {
- /* new xid is already allocated for bulk in
- * ptlrpc_check_set() */
+ /* new xid is already allocated for bulk in ptlrpc_check_set() */
req->rq_xid = ptlrpc_next_xid();
DEBUG_REQ(D_RPCTRACE, req, "Allocating new xid for resend on EINPROGRESS");
}
/* Readjust the timeout for current conditions */
ptlrpc_at_set_req_timeout(req);
- /* delay resend to give a chance to the server to get ready.
+ /*
+ * delay resend to give a chance to the server to get ready.
* The delay is increased by 1s on every resend and is capped to
* the current request timeout (i.e. obd_timeout if AT is off,
- * or AT service time x 125% + 5s, see at_est2timeout) */
+ * or AT service time x 125% + 5s, see at_est2timeout)
+ */
if (req->rq_nr_resend > req->rq_timeout)
req->rq_sent = now + req->rq_timeout;
else
@@ -1268,9 +1291,7 @@ static int after_reply(struct ptlrpc_request *req)
ldlm_cli_update_pool(req);
}
- /*
- * Store transno in reqmsg for replay.
- */
+ /* Store transno in reqmsg for replay. */
if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)) {
req->rq_transno = lustre_msg_get_transno(req->rq_repmsg);
lustre_msg_set_transno(req->rq_reqmsg, req->rq_transno);
@@ -1286,22 +1307,22 @@ static int after_reply(struct ptlrpc_request *req)
(req->rq_transno >
lustre_msg_get_last_committed(req->rq_repmsg) ||
req->rq_replay)) {
- /** version recovery */
+ /* version recovery */
ptlrpc_save_versions(req);
ptlrpc_retain_replayable_request(req, imp);
} else if (req->rq_commit_cb != NULL &&
list_empty(&req->rq_replay_list)) {
- /* NB: don't call rq_commit_cb if it's already on
+ /*
+ * NB: don't call rq_commit_cb if it's already on
* rq_replay_list, ptlrpc_free_committed() will call
- * it later, see LU-3618 for details */
+ * it later, see LU-3618 for details
+ */
spin_unlock(&imp->imp_lock);
req->rq_commit_cb(req);
spin_lock(&imp->imp_lock);
}
- /*
- * Replay-enabled imports return commit-status information.
- */
+ /* Replay-enabled imports return commit-status information. */
if (lustre_msg_get_last_committed(req->rq_repmsg)) {
imp->imp_peer_committed_transno =
lustre_msg_get_last_committed(req->rq_repmsg);
@@ -1420,8 +1441,10 @@ static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set)
remaining = atomic_read(&set->set_remaining);
- /* populate the ->set_requests list with requests until we
- * reach the maximum number of RPCs in flight for this set */
+ /*
+ * populate the ->set_requests list with requests until we
+ * reach the maximum number of RPCs in flight for this set
+ */
while (atomic_read(&set->set_remaining) < set->set_max_inflight) {
rc = set->set_producer(set, set->set_producer_arg);
if (rc == -ENOENT) {
@@ -1461,7 +1484,8 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
int unregistered = 0;
int rc = 0;
- /* This schedule point is mainly for the ptlrpcd caller of this
+ /*
+ * This schedule point is mainly for the ptlrpcd caller of this
* function. Most ptlrpc sets are not long-lived and unbounded
* in length, but at the least the set used by the ptlrpcd is.
* Since the processing time is unbounded, we need to insert an
@@ -1520,8 +1544,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
OBD_FAIL_ONCE);
}
- /*
- * Move to next phase if reply was successfully
+ /* Move to next phase if reply was successfully
* unlinked.
*/
ptlrpc_rqphase_move(req, req->rq_next_phase);
@@ -1535,15 +1558,11 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
if (req->rq_phase == RQ_PHASE_INTERPRET)
goto interpret;
- /*
- * Note that this also will start async reply unlink.
- */
+ /* Note that this also will start async reply unlink. */
if (req->rq_net_err && !req->rq_timedout) {
ptlrpc_expire_one_request(req, 1);
- /*
- * Check if we still need to wait for unlink.
- */
+ /* Check if we still need to wait for unlink. */
if (ptlrpc_client_recv_or_unlink(req) ||
ptlrpc_client_bulk_active(req))
continue;
@@ -1568,7 +1587,8 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
goto interpret;
}
- /* ptlrpc_set_wait->l_wait_event sets lwi_allow_intr
+ /*
+ * ptlrpc_set_wait->l_wait_event sets lwi_allow_intr
* so it sets rq_intr regardless of individual rpc
* timeouts. The synchronous IO waiting path sets
* rq_intr irrespective of whether ptlrpcd
@@ -1595,8 +1615,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
spin_lock(&imp->imp_lock);
if (ptlrpc_import_delay_req(imp, req,
&status)) {
- /* put on delay list - only if we wait
- * recovery finished - before send */
+ /*
+ * put on delay list - only if we wait
+ * recovery finished - before send
+ */
list_del_init(&req->rq_list);
list_add_tail(&req->rq_list,
&imp->
@@ -1632,8 +1654,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
spin_unlock(&req->rq_lock);
if (req->rq_timedout || req->rq_resend) {
- /* This is re-sending anyways,
- * let's mark req as resend. */
+ /* This is re-sending anyway, let's mark req as resend. */
spin_lock(&req->rq_lock);
req->rq_resend = 1;
spin_unlock(&req->rq_lock);
@@ -1711,8 +1732,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
spin_unlock(&req->rq_lock);
- /* unlink from net because we are going to
- * swab in-place of reply buffer */
+ /*
+ * unlink from net because we are going to
+ * swab in-place of reply buffer
+ */
unregistered = ptlrpc_unregister_reply(req, 1);
if (!unregistered)
continue;
@@ -1721,7 +1744,8 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
if (req->rq_resend)
continue;
- /* If there is no bulk associated with this request,
+ /*
+ * If there is no bulk associated with this request,
* then we're done and should let the interpreter
* process the reply. Similarly if the RPC returned
* an error, and therefore the bulk will never arrive.
@@ -1739,10 +1763,12 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
continue;
if (req->rq_bulk->bd_failure) {
- /* The RPC reply arrived OK, but the bulk screwed
+ /*
+ * The RPC reply arrived OK, but the bulk screwed
* up! Dead weird since the server told us the RPC
* was good after getting the REPLY for her GET or
- * the ACK for her PUT. */
+ * the ACK for her PUT.
+ */
DEBUG_REQ(D_ERROR, req, "bulk transfer failed");
req->rq_status = -EIO;
}
@@ -1752,8 +1778,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
interpret:
LASSERT(req->rq_phase == RQ_PHASE_INTERPRET);
- /* This moves to "unregistering" phase we need to wait for
- * reply unlink. */
+ /*
+ * This moves to "unregistering" phase we need to wait for
+ * reply unlink.
+ */
if (!unregistered && !ptlrpc_unregister_reply(req, 1)) {
/* start async bulk unlink too */
ptlrpc_unregister_bulk(req, 1);
@@ -1763,8 +1791,7 @@ interpret:
if (!ptlrpc_unregister_bulk(req, 1))
continue;
- /* When calling interpret receiving already should be
- * finished. */
+ /* When calling interpret receive should already be finished. */
LASSERT(!req->rq_receiving_reply);
ptlrpc_req_interpret(env, req, req->rq_status);
@@ -1783,10 +1810,12 @@ interpret:
lustre_msg_get_opc(req->rq_reqmsg));
spin_lock(&imp->imp_lock);
- /* Request already may be not on sending or delaying list. This
+ /*
+ * Request already may be not on sending or delaying list. This
* may happen in the case of marking it erroneous for the case
* ptlrpc_import_delay_req(req, status) find it impossible to
- * allow sending this rpc and returns *status != 0. */
+ * allow sending this rpc and returns *status != 0.
+ */
if (!list_empty(&req->rq_list)) {
list_del_init(&req->rq_list);
atomic_dec(&imp->imp_inflight);
@@ -1801,8 +1830,10 @@ interpret:
if (ptlrpc_set_producer(set) > 0)
force_timer_recalc = 1;
- /* free the request that has just been completed
- * in order not to pollute set->set_requests */
+ /*
+ * free the request that has just been completed
+ * in order not to pollute set->set_requests
+ */
list_del_init(&req->rq_set_chain);
spin_lock(&req->rq_lock);
req->rq_set = NULL;
@@ -1818,8 +1849,10 @@ interpret:
}
}
- /* move completed request at the head of list so it's easier for
- * caller to find them */
+ /*
+ * move completed request at the head of list so it's easier for
+ * caller to find them
+ */
list_splice(&comp_reqs, &set->set_requests);
/* If we hit an error, we want to recover promptly. */
@@ -1869,8 +1902,10 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
if (imp->imp_dlm_fake)
return 1;
- /* If this request is for recovery or other primordial tasks,
- * then error it out here. */
+ /*
+ * If this request is for recovery or other primordial tasks,
+ * then error it out here.
+ */
if (req->rq_ctx_init || req->rq_ctx_fini ||
req->rq_send_state != LUSTRE_IMP_FULL ||
imp->imp_obd->obd_no_recov) {
@@ -1884,8 +1919,10 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
return 1;
}
- /* if a request can't be resent we can't wait for an answer after
- the timeout */
+ /*
+ * if a request can't be resent we can't wait for an answer after
+ * the timeout
+ */
if (ptlrpc_no_resend(req)) {
DEBUG_REQ(D_RPCTRACE, req, "TIMEOUT-NORESEND:");
rc = 1;
@@ -1909,9 +1946,7 @@ int ptlrpc_expired_set(void *data)
LASSERT(set != NULL);
- /*
- * A timeout expired. See which reqs it applies to...
- */
+ /* A timeout expired. See which reqs it applies to... */
list_for_each(tmp, &set->set_requests) {
struct ptlrpc_request *req =
list_entry(tmp, struct ptlrpc_request,
@@ -1931,8 +1966,10 @@ int ptlrpc_expired_set(void *data)
req->rq_deadline > now) /* not expired */
continue;
- /* Deal with this guy. Do it asynchronously to not block
- * ptlrpcd thread. */
+ /*
+ * Deal with this guy. Do it asynchronously to not block
+ * ptlrpcd thread.
+ */
ptlrpc_expire_one_request(req, 1);
}
@@ -1996,23 +2033,17 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set)
list_for_each(tmp, &set->set_requests) {
req = list_entry(tmp, struct ptlrpc_request, rq_set_chain);
- /*
- * Request in-flight?
- */
+ /* Request in-flight? */
if (!(((req->rq_phase == RQ_PHASE_RPC) && !req->rq_waiting) ||
(req->rq_phase == RQ_PHASE_BULK) ||
(req->rq_phase == RQ_PHASE_NEW)))
continue;
- /*
- * Already timed out.
- */
+ /* Already timed out. */
if (req->rq_timedout)
continue;
- /*
- * Waiting for ctx.
- */
+ /* Waiting for ctx. */
if (req->rq_wait_ctx)
continue;
@@ -2061,8 +2092,10 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
do {
timeout = ptlrpc_set_next_timeout(set);
- /* wait until all complete, interrupted, or an in-flight
- * req times out */
+ /*
+ * wait until all complete, interrupted, or an in-flight
+ * req times out
+ */
CDEBUG(D_RPCTRACE, "set %p going to sleep for %d seconds\n",
set, timeout);
@@ -2087,18 +2120,22 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
rc = l_wait_event(set->set_waitq, ptlrpc_check_set(NULL, set), &lwi);
- /* LU-769 - if we ignored the signal because it was already
+ /*
+ * LU-769 - if we ignored the signal because it was already
* pending when we started, we need to handle it now or we risk
- * it being ignored forever */
+ * it being ignored forever
+ */
if (rc == -ETIMEDOUT && !lwi.lwi_allow_intr &&
cfs_signal_pending()) {
sigset_t blocked_sigs =
cfs_block_sigsinv(LUSTRE_FATAL_SIGS);
- /* In fact we only interrupt for the "fatal" signals
+ /*
+ * In fact we only interrupt for the "fatal" signals
* like SIGINT or SIGKILL. We still ignore less
* important signals since ptlrpc set is not easily
- * reentrant from userspace again */
+ * reentrant from userspace again
+ */
if (cfs_signal_pending())
ptlrpc_interrupted_set(set);
cfs_restore_sigs(blocked_sigs);
@@ -2106,13 +2143,15 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
LASSERT(rc == 0 || rc == -EINTR || rc == -ETIMEDOUT);
- /* -EINTR => all requests have been flagged rq_intr so next
+ /*
+ * -EINTR => all requests have been flagged rq_intr so next
* check completes.
* -ETIMEDOUT => someone timed out. When all reqs have
* timed out, signals are enabled allowing completion with
* EINTR.
* I don't really care if we go once more round the loop in
- * the error cases -eeb. */
+ * the error cases -eeb.
+ */
if (rc == 0 && atomic_read(&set->set_remaining) == 0) {
list_for_each(tmp, &set->set_requests) {
req = list_entry(tmp, struct ptlrpc_request,
@@ -2178,8 +2217,10 @@ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked)
req_capsule_fini(&request->rq_pill);
- /* We must take it off the imp_replay_list first. Otherwise, we'll set
- * request->rq_reqmsg to NULL while osc_close is dereferencing it. */
+ /*
+ * We must take it off the imp_replay_list first. Otherwise, we'll set
+ * request->rq_reqmsg to NULL while osc_close is dereferencing it.
+ */
if (request->rq_import != NULL) {
if (!locked)
spin_lock(&request->rq_import->imp_lock);
@@ -2280,40 +2321,28 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
wait_queue_head_t *wq;
struct l_wait_info lwi;
- /*
- * Might sleep.
- */
+ /* Might sleep. */
LASSERT(!in_interrupt());
- /*
- * Let's setup deadline for reply unlink.
- */
+ /* Let's setup deadline for reply unlink. */
if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) &&
async && request->rq_reply_deadline == 0)
request->rq_reply_deadline = ktime_get_real_seconds()+LONG_UNLINK;
- /*
- * Nothing left to do.
- */
+ /* Nothing left to do. */
if (!ptlrpc_client_recv_or_unlink(request))
return 1;
LNetMDUnlink(request->rq_reply_md_h);
- /*
- * Let's check it once again.
- */
+ /* Let's check it once again. */
if (!ptlrpc_client_recv_or_unlink(request))
return 1;
- /*
- * Move to "Unregistering" phase as reply was not unlinked yet.
- */
+ /* Move to "Unregistering" phase as reply was not unlinked yet. */
ptlrpc_rqphase_move(request, RQ_PHASE_UNREGISTERING);
- /*
- * Do not wait for unlink to finish.
- */
+ /* Do not wait for unlink to finish. */
if (async)
return 0;
@@ -2328,8 +2357,10 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
wq = &request->rq_reply_waitq;
for (;;) {
- /* Network access will complete in finite time but the HUGE
- * timeout lets us CWARN for visibility of sluggish NALs */
+ /*
+ * Network access will complete in finite time but the HUGE
+ * timeout lets us CWARN for visibility of sluggish NALs
+ */
lwi = LWI_TIMEOUT_INTERVAL(cfs_time_seconds(LONG_UNLINK),
cfs_time_seconds(1), NULL, NULL);
rc = l_wait_event(*wq, !ptlrpc_client_recv_or_unlink(request),
@@ -2472,8 +2503,10 @@ void ptlrpc_resend_req(struct ptlrpc_request *req)
DEBUG_REQ(D_HA, req, "going to resend");
spin_lock(&req->rq_lock);
- /* Request got reply but linked to the import list still.
- Let ptlrpc_check_set() to process it. */
+ /*
+ * Request got reply but linked to the import list still.
+ * Let ptlrpc_check_set() to process it.
+ */
if (ptlrpc_client_replied(req)) {
spin_unlock(&req->rq_lock);
DEBUG_REQ(D_HA, req, "it has reply, so skip it");
@@ -2525,8 +2558,10 @@ void ptlrpc_retain_replayable_request(struct ptlrpc_request *req,
LBUG();
}
- /* clear this for new requests that were resent as well
- as resent replayed requests. */
+ /*
+ * clear this for new requests that were resent as well
+ * as resent replayed requests.
+ */
lustre_msg_clear_flags(req->rq_reqmsg, MSG_RESENT);
/* don't re-add requests that have been replayed */
@@ -2543,7 +2578,8 @@ void ptlrpc_retain_replayable_request(struct ptlrpc_request *req,
list_entry(tmp, struct ptlrpc_request,
rq_replay_list);
- /* We may have duplicate transnos if we create and then
+ /*
+ * We may have duplicate transnos if we create and then
* open a file, or for closes retained if to match creating
* opens, so use req->rq_xid as a secondary key.
* (See bugs 684, 685, and 428.)
@@ -2728,8 +2764,10 @@ int ptlrpc_replay_req(struct ptlrpc_request *req)
/* Readjust the timeout for current conditions */
ptlrpc_at_set_req_timeout(req);
- /* Tell server the net_latency, so the server can calculate how long
- * it should wait for next replay */
+ /*
+ * Tell server the net_latency, so the server can calculate how long
+ * it should wait for next replay
+ */
lustre_msg_set_service_time(req->rq_reqmsg,
ptlrpc_at_get_net_latency(req));
DEBUG_REQ(D_HA, req, "REPLAY");
@@ -2749,13 +2787,15 @@ void ptlrpc_abort_inflight(struct obd_import *imp)
{
struct list_head *tmp, *n;
- /* Make sure that no new requests get processed for this import.
+ /*
+ * Make sure that no new requests get processed for this import.
* ptlrpc_{queue,set}_wait must (and does) hold imp_lock while testing
* this flag and then putting requests on sending_list or delayed_list.
*/
spin_lock(&imp->imp_lock);
- /* XXX locking? Maybe we should remove each request with the list
+ /*
+ * XXX locking? Maybe we should remove each request with the list
* locked? Also, how do we know if the requests on the list are
* being freed at this time?
*/
@@ -2789,8 +2829,10 @@ void ptlrpc_abort_inflight(struct obd_import *imp)
spin_unlock(&req->rq_lock);
}
- /* Last chance to free reqs left on the replay list, but we
- * will still leak reqs that haven't committed. */
+ /*
+ * Last chance to free reqs left on the replay list, but we
+ * will still leak reqs that haven't committed.
+ */
if (imp->imp_replayable)
ptlrpc_free_committed(imp);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c
index 1ba1f5f2eeaa..da1f0b1ac3e3 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/connection.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c
@@ -42,7 +42,7 @@
#include "ptlrpc_internal.h"
static struct cfs_hash *conn_hash;
-static cfs_hash_ops_t conn_hash_ops;
+static struct cfs_hash_ops conn_hash_ops;
struct ptlrpc_connection *
ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self,
@@ -230,12 +230,12 @@ conn_exit(struct cfs_hash *hs, struct hlist_node *hnode)
kfree(conn);
}
-static cfs_hash_ops_t conn_hash_ops = {
+static struct cfs_hash_ops conn_hash_ops = {
.hs_hash = conn_hashfn,
.hs_keycmp = conn_keycmp,
- .hs_key = conn_key,
+ .hs_key = conn_key,
.hs_object = conn_object,
- .hs_get = conn_get,
+ .hs_get = conn_get,
.hs_put_locked = conn_put_locked,
.hs_exit = conn_exit,
};
diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
index 415817c423dd..2aecab21e3e1 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
@@ -909,8 +909,11 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, srhi->srhi_seq);
if (rc == 0) {
+ char nidstr[LNET_NIDSTR_SIZE];
+
req = srhi->srhi_req;
+ libcfs_nid2str_r(req->rq_self, nidstr, sizeof(nidstr));
/* Print common req fields.
* CAVEAT EMPTOR: we're racing with the service handler
* here. The request could contain any old crap, so you
@@ -918,14 +921,14 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
* parser. Currently I only print stuff here I know is OK
* to look at coz it was set up in request_in_callback()!!! */
seq_printf(s, "%lld:%s:%s:x%llu:%d:%s:%lld:%lds(%+lds) ",
- req->rq_history_seq, libcfs_nid2str(req->rq_self),
+ req->rq_history_seq, nidstr,
libcfs_id2str(req->rq_peer), req->rq_xid,
req->rq_reqlen, ptlrpc_rqphase2str(req),
(s64)req->rq_arrival_time.tv_sec,
(long)(req->rq_sent - req->rq_arrival_time.tv_sec),
(long)(req->rq_sent - req->rq_deadline));
if (svc->srv_ops.so_req_printer == NULL)
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
else
svc->srv_ops.so_req_printer(s, srhi->srhi_req);
}
@@ -1189,9 +1192,12 @@ int lprocfs_wr_ping(struct file *file, const char __user *buffer,
struct ptlrpc_request *req;
int rc;
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
req = ptlrpc_prep_ping(obd->u.cli.cl_import);
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
if (req == NULL)
return -ENOMEM;
@@ -1278,10 +1284,14 @@ int lprocfs_rd_pinger_recov(struct seq_file *m, void *n)
{
struct obd_device *obd = m->private;
struct obd_import *imp = obd->u.cli.cl_import;
+ int rc;
+
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
- LPROCFS_CLIMP_CHECK(obd);
seq_printf(m, "%d\n", !imp->imp_no_pinger_recover);
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return 0;
}
@@ -1302,11 +1312,14 @@ int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer,
if (val != 0 && val != 1)
return -ERANGE;
- LPROCFS_CLIMP_CHECK(obd);
+ rc = lprocfs_climp_check(obd);
+ if (rc)
+ return rc;
+
spin_lock(&imp->imp_lock);
imp->imp_no_pinger_recover = !val;
spin_unlock(&imp->imp_lock);
- LPROCFS_CLIMP_EXIT(obd);
+ up_read(&obd->u.cli.cl_sem);
return count;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
index ab6c4580f91c..833ed944125e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
@@ -73,7 +73,6 @@ void ptlrpc_request_handle_notconn(struct ptlrpc_request *);
void lustre_assert_wire_constants(void);
int ptlrpc_import_in_recovery(struct obd_import *imp);
int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt);
-void ptlrpc_handle_failed_import(struct obd_import *imp);
int ptlrpc_replay_next(struct obd_import *imp, int *inflight);
void ptlrpc_initiate_recovery(struct obd_import *imp);
@@ -88,8 +87,6 @@ void ptlrpc_ldebugfs_register_service(struct dentry *debugfs_entry,
struct ptlrpc_service *svc);
void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc);
void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount);
-void ptlrpc_lprocfs_do_request_stat(struct ptlrpc_request *req,
- long q_usec, long work_usec);
/* NRS */
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
index 9deeb244166f..c4f1d0f5deb2 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
@@ -160,7 +160,7 @@ static void __exit ptlrpc_exit(void)
ptlrpc_connection_fini();
}
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Request Processor and Lock Management");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0.0");
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
index ce036a1ac466..ac87aa12bd7e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
@@ -422,6 +422,7 @@ static int ptlrpcd(void *arg)
complete(&pc->pc_starting);
/*
+
* This mainloop strongly resembles ptlrpc_set_wait() except that our
* set never completes. ptlrpcd_check() calls ptlrpc_check_set() when
* there are requests in the set. New requests come in on the set's
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c
index 34d133075302..39f5261c9854 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c
@@ -2261,14 +2261,14 @@ EXPORT_SYMBOL(sec2target_str);
/*
* return true if the bulk data is protected
*/
-int sptlrpc_flavor_has_bulk(struct sptlrpc_flavor *flvr)
+bool sptlrpc_flavor_has_bulk(struct sptlrpc_flavor *flvr)
{
switch (SPTLRPC_FLVR_BULK_SVC(flvr->sf_rpc)) {
case SPTLRPC_BULK_SVC_INTG:
case SPTLRPC_BULK_SVC_PRIV:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
EXPORT_SYMBOL(sptlrpc_flavor_has_bulk);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
index fca9aa162e31..7a206705865b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
@@ -83,8 +83,7 @@ int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr)
return 0;
}
- strncpy(buf, str, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
+ strlcpy(buf, str, sizeof(buf));
bulk = strchr(buf, '-');
if (bulk)
@@ -257,7 +256,6 @@ static int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *rset)
rset->srs_nslot = nslot;
return 0;
}
-EXPORT_SYMBOL(sptlrpc_rule_set_expand);
static inline int rule_spec_dir(struct sptlrpc_rule *rule)
{
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
index fb55e5941445..19fcb1cb8231 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.c
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.c
@@ -179,14 +179,13 @@
#define BCM2048_DEFAULT_TIMEOUT 1500
#define BCM2048_AUTO_SEARCH_TIMEOUT 3000
-
#define BCM2048_FREQDEV_UNIT 10000
#define BCM2048_FREQV4L2_MULTI 625
#define dev_to_v4l2(f) ((f * BCM2048_FREQDEV_UNIT) / BCM2048_FREQV4L2_MULTI)
#define v4l2_to_dev(f) ((f * BCM2048_FREQV4L2_MULTI) / BCM2048_FREQDEV_UNIT)
-#define msb(x) ((u8)((u16) x >> 8))
-#define lsb(x) ((u8)((u16) x & 0x00FF))
+#define msb(x) ((u8)((u16)x >> 8))
+#define lsb(x) ((u8)((u16)x & 0x00FF))
#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb)
#define BCM2048_DEFAULT_POWERING_DELAY 20
@@ -348,7 +347,7 @@ static struct region_info region_configs[] = {
* I2C Interface read / write
*/
static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg,
- unsigned int value)
+ unsigned int value)
{
struct i2c_client *client = bdev->client;
u8 data[2];
@@ -370,7 +369,7 @@ static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg,
}
static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg,
- u8 *value)
+ u8 *value)
{
struct i2c_client *client = bdev->client;
@@ -385,7 +384,7 @@ static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg,
}
static int bcm2048_recv_duples(struct bcm2048_device *bdev, unsigned int reg,
- u8 *value, u8 duples)
+ u8 *value, u8 duples)
{
struct i2c_client *client = bdev->client;
struct i2c_adapter *adap = client->adapter;
@@ -436,7 +435,7 @@ static int bcm2048_set_power_state(struct bcm2048_device *bdev, u8 power)
*/
if (power)
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM,
- bdev->cache_fm_rds_system);
+ bdev->cache_fm_rds_system);
msleep(BCM2048_DEFAULT_POWERING_DELAY);
if (!power)
@@ -475,17 +474,17 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on)
bdev->rds_state = BCM2048_RDS_ON;
flags = BCM2048_RDS_FLAG_FIFO_WLINE;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1,
- flags);
+ flags);
} else {
flags = 0;
bdev->rds_state = 0;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1,
- flags);
+ flags);
memset(&bdev->rds_info, 0, sizeof(bdev->rds_info));
}
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM,
- bdev->cache_fm_rds_system);
+ bdev->cache_fm_rds_system);
return err;
}
@@ -545,14 +544,14 @@ static int bcm2048_set_fm_automatic_stereo_mono(struct bcm2048_device *bdev,
bdev->cache_fm_ctrl |= BCM2048_STEREO_MONO_AUTO_SELECT;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL,
- bdev->cache_fm_ctrl);
+ bdev->cache_fm_ctrl);
mutex_unlock(&bdev->mutex);
return err;
}
static int bcm2048_set_fm_hi_lo_injection(struct bcm2048_device *bdev,
- u8 hi_lo)
+ u8 hi_lo)
{
int err;
@@ -564,7 +563,7 @@ static int bcm2048_set_fm_hi_lo_injection(struct bcm2048_device *bdev,
bdev->cache_fm_ctrl |= BCM2048_HI_LO_INJECTION;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL,
- bdev->cache_fm_ctrl);
+ bdev->cache_fm_ctrl);
mutex_unlock(&bdev->mutex);
return err;
@@ -592,7 +591,7 @@ static int bcm2048_set_fm_frequency(struct bcm2048_device *bdev, u32 frequency)
int err;
if (frequency < bdev->region_info.bottom_frequency ||
- frequency > bdev->region_info.top_frequency)
+ frequency > bdev->region_info.top_frequency)
return -EDOM;
frequency -= BCM2048_FREQUENCY_BASE;
@@ -601,7 +600,7 @@ static int bcm2048_set_fm_frequency(struct bcm2048_device *bdev, u32 frequency)
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ0, lsb(frequency));
err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ1,
- msb(frequency));
+ msb(frequency));
if (!err)
bdev->frequency = frequency;
@@ -613,7 +612,7 @@ static int bcm2048_set_fm_frequency(struct bcm2048_device *bdev, u32 frequency)
static int bcm2048_get_fm_frequency(struct bcm2048_device *bdev)
{
int err;
- u8 lsb, msb;
+ u8 lsb = 0, msb = 0;
mutex_lock(&bdev->mutex);
@@ -632,12 +631,12 @@ static int bcm2048_get_fm_frequency(struct bcm2048_device *bdev)
}
static int bcm2048_set_fm_af_frequency(struct bcm2048_device *bdev,
- u32 frequency)
+ u32 frequency)
{
int err;
if (frequency < bdev->region_info.bottom_frequency ||
- frequency > bdev->region_info.top_frequency)
+ frequency > bdev->region_info.top_frequency)
return -EDOM;
frequency -= BCM2048_FREQUENCY_BASE;
@@ -645,9 +644,9 @@ static int bcm2048_set_fm_af_frequency(struct bcm2048_device *bdev,
mutex_lock(&bdev->mutex);
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ0,
- lsb(frequency));
+ lsb(frequency));
err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ1,
- msb(frequency));
+ msb(frequency));
if (!err)
bdev->frequency = frequency;
@@ -658,7 +657,7 @@ static int bcm2048_set_fm_af_frequency(struct bcm2048_device *bdev,
static int bcm2048_get_fm_af_frequency(struct bcm2048_device *bdev)
{
int err;
- u8 lsb, msb;
+ u8 lsb = 0, msb = 0;
mutex_lock(&bdev->mutex);
@@ -692,7 +691,7 @@ static int bcm2048_set_fm_deemphasis(struct bcm2048_device *bdev, int d)
bdev->cache_fm_audio_ctrl0 |= deemphasis;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
- bdev->cache_fm_audio_ctrl0);
+ bdev->cache_fm_audio_ctrl0);
if (!err)
bdev->region_info.deemphasis = d;
@@ -740,7 +739,7 @@ static int bcm2048_set_region(struct bcm2048_device *bdev, u8 region)
bdev->cache_fm_ctrl &= ~BCM2048_BAND_SELECT;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL,
- bdev->cache_fm_ctrl);
+ bdev->cache_fm_ctrl);
if (err) {
mutex_unlock(&bdev->mutex);
goto done;
@@ -748,7 +747,7 @@ static int bcm2048_set_region(struct bcm2048_device *bdev, u8 region)
mutex_unlock(&bdev->mutex);
if (bdev->frequency < region_configs[region].bottom_frequency ||
- bdev->frequency > region_configs[region].top_frequency)
+ bdev->frequency > region_configs[region].top_frequency)
new_frequency = region_configs[region].bottom_frequency;
if (new_frequency > 0) {
@@ -759,7 +758,7 @@ static int bcm2048_set_region(struct bcm2048_device *bdev, u8 region)
}
err = bcm2048_set_fm_deemphasis(bdev,
- region_configs[region].deemphasis);
+ region_configs[region].deemphasis);
done:
return err;
@@ -786,10 +785,10 @@ static int bcm2048_set_mute(struct bcm2048_device *bdev, u16 mute)
if (mute)
bdev->cache_fm_audio_ctrl0 |= (BCM2048_RF_MUTE |
- BCM2048_MANUAL_MUTE);
+ BCM2048_MANUAL_MUTE);
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
- bdev->cache_fm_audio_ctrl0);
+ bdev->cache_fm_audio_ctrl0);
if (!err)
bdev->mute_state = mute;
@@ -807,7 +806,7 @@ static int bcm2048_get_mute(struct bcm2048_device *bdev)
if (bdev->power_state) {
err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
- &value);
+ &value);
if (!err)
err = value & (BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE);
} else {
@@ -826,11 +825,11 @@ static int bcm2048_set_audio_route(struct bcm2048_device *bdev, u8 route)
route &= (BCM2048_AUDIO_ROUTE_DAC | BCM2048_AUDIO_ROUTE_I2S);
bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_AUDIO_ROUTE_DAC |
- BCM2048_AUDIO_ROUTE_I2S);
+ BCM2048_AUDIO_ROUTE_I2S);
bdev->cache_fm_audio_ctrl0 |= route;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
- bdev->cache_fm_audio_ctrl0);
+ bdev->cache_fm_audio_ctrl0);
mutex_unlock(&bdev->mutex);
return err;
@@ -849,7 +848,7 @@ static int bcm2048_get_audio_route(struct bcm2048_device *bdev)
if (!err)
return value & (BCM2048_AUDIO_ROUTE_DAC |
- BCM2048_AUDIO_ROUTE_I2S);
+ BCM2048_AUDIO_ROUTE_I2S);
return err;
}
@@ -865,7 +864,7 @@ static int bcm2048_set_dac_output(struct bcm2048_device *bdev, u8 channels)
bdev->cache_fm_audio_ctrl0 |= channels;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
- bdev->cache_fm_audio_ctrl0);
+ bdev->cache_fm_audio_ctrl0);
mutex_unlock(&bdev->mutex);
return err;
@@ -884,13 +883,13 @@ static int bcm2048_get_dac_output(struct bcm2048_device *bdev)
if (!err)
return value & (BCM2048_DAC_OUTPUT_LEFT |
- BCM2048_DAC_OUTPUT_RIGHT);
+ BCM2048_DAC_OUTPUT_RIGHT);
return err;
}
static int bcm2048_set_fm_search_rssi_threshold(struct bcm2048_device *bdev,
- u8 threshold)
+ u8 threshold)
{
int err;
@@ -901,7 +900,7 @@ static int bcm2048_set_fm_search_rssi_threshold(struct bcm2048_device *bdev,
bdev->cache_fm_search_ctrl0 |= threshold;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0,
- bdev->cache_fm_search_ctrl0);
+ bdev->cache_fm_search_ctrl0);
mutex_unlock(&bdev->mutex);
return err;
@@ -937,7 +936,7 @@ static int bcm2048_set_fm_search_mode_direction(struct bcm2048_device *bdev,
bdev->cache_fm_search_ctrl0 |= BCM2048_SEARCH_DIRECTION;
err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0,
- bdev->cache_fm_search_ctrl0);
+ bdev->cache_fm_search_ctrl0);
mutex_unlock(&bdev->mutex);
return err;
@@ -961,7 +960,7 @@ static int bcm2048_get_fm_search_mode_direction(struct bcm2048_device *bdev)
}
static int bcm2048_set_fm_search_tune_mode(struct bcm2048_device *bdev,
- u8 mode)
+ u8 mode)
{
int err, timeout, restart_rds = 0;
u8 value, flags;
@@ -1024,7 +1023,7 @@ static int bcm2048_get_fm_search_tune_mode(struct bcm2048_device *bdev)
mutex_lock(&bdev->mutex);
err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE,
- &value);
+ &value);
mutex_unlock(&bdev->mutex);
@@ -1040,10 +1039,10 @@ static int bcm2048_set_rds_b_block_mask(struct bcm2048_device *bdev, u16 mask)
mutex_lock(&bdev->mutex);
- err = bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_BLKB_MASK0, lsb(mask));
- err |= bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_BLKB_MASK1, msb(mask));
+ err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MASK0,
+ lsb(mask));
+ err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MASK1,
+ msb(mask));
mutex_unlock(&bdev->mutex);
return err;
@@ -1052,14 +1051,12 @@ static int bcm2048_set_rds_b_block_mask(struct bcm2048_device *bdev, u16 mask)
static int bcm2048_get_rds_b_block_mask(struct bcm2048_device *bdev)
{
int err;
- u8 lsb, msb;
+ u8 lsb = 0, msb = 0;
mutex_lock(&bdev->mutex);
- err = bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_BLKB_MASK0, &lsb);
- err |= bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_BLKB_MASK1, &msb);
+ err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MASK0, &lsb);
+ err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MASK1, &msb);
mutex_unlock(&bdev->mutex);
@@ -1070,16 +1067,16 @@ static int bcm2048_get_rds_b_block_mask(struct bcm2048_device *bdev)
}
static int bcm2048_set_rds_b_block_match(struct bcm2048_device *bdev,
- u16 match)
+ u16 match)
{
int err;
mutex_lock(&bdev->mutex);
- err = bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_BLKB_MATCH0, lsb(match));
- err |= bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_BLKB_MATCH1, msb(match));
+ err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH0,
+ lsb(match));
+ err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH1,
+ msb(match));
mutex_unlock(&bdev->mutex);
return err;
@@ -1088,14 +1085,12 @@ static int bcm2048_set_rds_b_block_match(struct bcm2048_device *bdev,
static int bcm2048_get_rds_b_block_match(struct bcm2048_device *bdev)
{
int err;
- u8 lsb, msb;
+ u8 lsb = 0, msb = 0;
mutex_lock(&bdev->mutex);
- err = bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_BLKB_MATCH0, &lsb);
- err |= bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_BLKB_MATCH1, &msb);
+ err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH0, &lsb);
+ err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH1, &msb);
mutex_unlock(&bdev->mutex);
@@ -1111,10 +1106,8 @@ static int bcm2048_set_rds_pi_mask(struct bcm2048_device *bdev, u16 mask)
mutex_lock(&bdev->mutex);
- err = bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_PI_MASK0, lsb(mask));
- err |= bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_PI_MASK1, msb(mask));
+ err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MASK0, lsb(mask));
+ err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MASK1, msb(mask));
mutex_unlock(&bdev->mutex);
return err;
@@ -1123,14 +1116,12 @@ static int bcm2048_set_rds_pi_mask(struct bcm2048_device *bdev, u16 mask)
static int bcm2048_get_rds_pi_mask(struct bcm2048_device *bdev)
{
int err;
- u8 lsb, msb;
+ u8 lsb = 0, msb = 0;
mutex_lock(&bdev->mutex);
- err = bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_PI_MASK0, &lsb);
- err |= bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_PI_MASK1, &msb);
+ err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MASK0, &lsb);
+ err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MASK1, &msb);
mutex_unlock(&bdev->mutex);
@@ -1146,10 +1137,10 @@ static int bcm2048_set_rds_pi_match(struct bcm2048_device *bdev, u16 match)
mutex_lock(&bdev->mutex);
- err = bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_PI_MATCH0, lsb(match));
- err |= bcm2048_send_command(bdev,
- BCM2048_I2C_RDS_PI_MATCH1, msb(match));
+ err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MATCH0,
+ lsb(match));
+ err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MATCH1,
+ msb(match));
mutex_unlock(&bdev->mutex);
return err;
@@ -1158,14 +1149,12 @@ static int bcm2048_set_rds_pi_match(struct bcm2048_device *bdev, u16 match)
static int bcm2048_get_rds_pi_match(struct bcm2048_device *bdev)
{
int err;
- u8 lsb, msb;
+ u8 lsb = 0, msb = 0;
mutex_lock(&bdev->mutex);
- err = bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_PI_MATCH0, &lsb);
- err |= bcm2048_recv_command(bdev,
- BCM2048_I2C_RDS_PI_MATCH1, &msb);
+ err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MATCH0, &lsb);
+ err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MATCH1, &msb);
mutex_unlock(&bdev->mutex);
@@ -1181,10 +1170,8 @@ static int bcm2048_set_fm_rds_mask(struct bcm2048_device *bdev, u16 mask)
mutex_lock(&bdev->mutex);
- err = bcm2048_send_command(bdev,
- BCM2048_I2C_FM_RDS_MASK0, lsb(mask));
- err |= bcm2048_send_command(bdev,
- BCM2048_I2C_FM_RDS_MASK1, msb(mask));
+ err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK0, lsb(mask));
+ err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, msb(mask));
mutex_unlock(&bdev->mutex);
return err;
@@ -1193,7 +1180,7 @@ static int bcm2048_set_fm_rds_mask(struct bcm2048_device *bdev, u16 mask)
static int bcm2048_get_fm_rds_mask(struct bcm2048_device *bdev)
{
int err;
- u8 value0, value1;
+ u8 value0 = 0, value1 = 0;
mutex_lock(&bdev->mutex);
@@ -1211,7 +1198,7 @@ static int bcm2048_get_fm_rds_mask(struct bcm2048_device *bdev)
static int bcm2048_get_fm_rds_flags(struct bcm2048_device *bdev)
{
int err;
- u8 value0, value1;
+ u8 value0 = 0, value1 = 0;
mutex_lock(&bdev->mutex);
@@ -1239,19 +1226,19 @@ static int bcm2048_get_region_top_frequency(struct bcm2048_device *bdev)
static int bcm2048_set_fm_best_tune_mode(struct bcm2048_device *bdev, u8 mode)
{
int err;
- u8 value;
+ u8 value = 0;
mutex_lock(&bdev->mutex);
/* Perform read as the manual indicates */
err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE,
- &value);
+ &value);
value &= ~BCM2048_BEST_TUNE_MODE;
if (mode)
value |= BCM2048_BEST_TUNE_MODE;
err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE,
- value);
+ value);
mutex_unlock(&bdev->mutex);
return err;
@@ -1265,7 +1252,7 @@ static int bcm2048_get_fm_best_tune_mode(struct bcm2048_device *bdev)
mutex_lock(&bdev->mutex);
err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE,
- &value);
+ &value);
mutex_unlock(&bdev->mutex);
@@ -1352,7 +1339,7 @@ static int bcm2048_checkrev(struct bcm2048_device *bdev)
if (!err) {
dev_info(&bdev->client->dev, "BCM2048 Version 0x%x\n",
- version);
+ version);
return version;
}
@@ -1362,7 +1349,7 @@ static int bcm2048_checkrev(struct bcm2048_device *bdev)
static int bcm2048_get_rds_rt(struct bcm2048_device *bdev, char *data)
{
int err = 0, i, j = 0, ce = 0, cr = 0;
- char data_buffer[BCM2048_MAX_RDS_RT+1];
+ char data_buffer[BCM2048_MAX_RDS_RT + 1];
mutex_lock(&bdev->mutex);
@@ -1412,7 +1399,7 @@ unlock:
static int bcm2048_get_rds_ps(struct bcm2048_device *bdev, char *data)
{
int err = 0, i, j = 0;
- char data_buffer[BCM2048_MAX_RDS_PS+1];
+ char data_buffer[BCM2048_MAX_RDS_PS + 1];
mutex_lock(&bdev->mutex);
@@ -1448,12 +1435,10 @@ static void bcm2048_parse_rds_pi(struct bcm2048_device *bdev)
u16 pi;
for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) {
-
/* Block A match, only data without crc errors taken */
if (bdev->rds_info.radio_text[i] == BCM2048_RDS_BLOCK_A) {
-
- pi = (bdev->rds_info.radio_text[i+1] << 8) +
- bdev->rds_info.radio_text[i+2];
+ pi = (bdev->rds_info.radio_text[i + 1] << 8) +
+ bdev->rds_info.radio_text[i + 2];
if (!bdev->rds_info.rds_pi) {
bdev->rds_info.rds_pi = pi;
@@ -1478,20 +1463,21 @@ static int bcm2048_rds_block_crc(struct bcm2048_device *bdev, int i)
}
static void bcm2048_parse_rds_rt_block(struct bcm2048_device *bdev, int i,
- int index, int crc)
+ int index, int crc)
{
/* Good data will overwrite poor data */
if (crc) {
if (!bdev->rds_info.rds_rt[index])
bdev->rds_info.rds_rt[index] =
- bdev->rds_info.radio_text[i+1];
- if (!bdev->rds_info.rds_rt[index+1])
- bdev->rds_info.rds_rt[index+1] =
- bdev->rds_info.radio_text[i+2];
+ bdev->rds_info.radio_text[i + 1];
+ if (!bdev->rds_info.rds_rt[index + 1])
+ bdev->rds_info.rds_rt[index + 1] =
+ bdev->rds_info.radio_text[i + 2];
} else {
- bdev->rds_info.rds_rt[index] = bdev->rds_info.radio_text[i+1];
- bdev->rds_info.rds_rt[index+1] =
- bdev->rds_info.radio_text[i+2];
+ bdev->rds_info.rds_rt[index] =
+ bdev->rds_info.radio_text[i + 1];
+ bdev->rds_info.rds_rt[index + 1] =
+ bdev->rds_info.radio_text[i + 2];
}
}
@@ -1505,18 +1491,17 @@ static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i)
return -EIO;
if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
- BCM2048_RDS_BLOCK_B) {
-
- rt_id = bdev->rds_info.radio_text[i+1] &
+ BCM2048_RDS_BLOCK_B) {
+ rt_id = bdev->rds_info.radio_text[i + 1] &
BCM2048_RDS_BLOCK_MASK;
- rt_group_b = bdev->rds_info.radio_text[i+1] &
+ rt_group_b = bdev->rds_info.radio_text[i + 1] &
BCM2048_RDS_GROUP_AB_MASK;
- rt_ab = bdev->rds_info.radio_text[i+2] &
+ rt_ab = bdev->rds_info.radio_text[i + 2] &
BCM2048_RDS_RT_AB_MASK;
if (rt_group_b != bdev->rds_info.rds_rt_group_b) {
memset(bdev->rds_info.rds_rt, 0,
- sizeof(bdev->rds_info.rds_rt));
+ sizeof(bdev->rds_info.rds_rt));
bdev->rds_info.rds_rt_group_b = rt_group_b;
}
@@ -1524,11 +1509,11 @@ static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i)
/* A to B or (vice versa), means: clear screen */
if (rt_ab != bdev->rds_info.rds_rt_ab) {
memset(bdev->rds_info.rds_rt, 0,
- sizeof(bdev->rds_info.rds_rt));
+ sizeof(bdev->rds_info.rds_rt));
bdev->rds_info.rds_rt_ab = rt_ab;
}
- index = bdev->rds_info.radio_text[i+2] &
+ index = bdev->rds_info.radio_text[i + 2] &
BCM2048_RDS_RT_INDEX;
if (bdev->rds_info.rds_rt_group_b)
@@ -1544,7 +1529,7 @@ static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i)
}
static int bcm2048_parse_rt_match_c(struct bcm2048_device *bdev, int i,
- int index)
+ int index)
{
int crc;
@@ -1567,7 +1552,7 @@ static int bcm2048_parse_rt_match_c(struct bcm2048_device *bdev, int i,
}
static void bcm2048_parse_rt_match_d(struct bcm2048_device *bdev, int i,
- int index)
+ int index)
{
int crc;
@@ -1579,8 +1564,8 @@ static void bcm2048_parse_rt_match_d(struct bcm2048_device *bdev, int i,
BUG_ON((index+4) >= BCM2048_MAX_RDS_RT);
if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
- BCM2048_RDS_BLOCK_D)
- bcm2048_parse_rds_rt_block(bdev, i, index+2, crc);
+ BCM2048_RDS_BLOCK_D)
+ bcm2048_parse_rds_rt_block(bdev, i, index + 2, crc);
}
static void bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
@@ -1588,7 +1573,6 @@ static void bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0;
for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) {
-
if (match_b) {
match_b = 0;
index = bcm2048_parse_rt_match_b(bdev, i);
@@ -1607,40 +1591,41 @@ static void bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
}
/* Skip erroneous blocks due to messed up A block altogether */
- if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK)
- == BCM2048_RDS_BLOCK_A) {
+ if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+ BCM2048_RDS_BLOCK_A) {
crc = bcm2048_rds_block_crc(bdev, i);
if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
continue;
- /* Syncronize to a good RDS PI */
- if (((bdev->rds_info.radio_text[i+1] << 8) +
- bdev->rds_info.radio_text[i+2]) ==
- bdev->rds_info.rds_pi)
- match_b = 1;
+ /* Synchronize to a good RDS PI */
+ if (((bdev->rds_info.radio_text[i + 1] << 8) +
+ bdev->rds_info.radio_text[i + 2]) ==
+ bdev->rds_info.rds_pi)
+ match_b = 1;
}
}
}
static void bcm2048_parse_rds_ps_block(struct bcm2048_device *bdev, int i,
- int index, int crc)
+ int index, int crc)
{
/* Good data will overwrite poor data */
if (crc) {
if (!bdev->rds_info.rds_ps[index])
bdev->rds_info.rds_ps[index] =
- bdev->rds_info.radio_text[i+1];
- if (!bdev->rds_info.rds_ps[index+1])
- bdev->rds_info.rds_ps[index+1] =
- bdev->rds_info.radio_text[i+2];
+ bdev->rds_info.radio_text[i + 1];
+ if (!bdev->rds_info.rds_ps[index + 1])
+ bdev->rds_info.rds_ps[index + 1] =
+ bdev->rds_info.radio_text[i + 2];
} else {
- bdev->rds_info.rds_ps[index] = bdev->rds_info.radio_text[i+1];
- bdev->rds_info.rds_ps[index+1] =
- bdev->rds_info.radio_text[i+2];
+ bdev->rds_info.rds_ps[index] =
+ bdev->rds_info.radio_text[i + 1];
+ bdev->rds_info.rds_ps[index + 1] =
+ bdev->rds_info.radio_text[i + 2];
}
}
static int bcm2048_parse_ps_match_c(struct bcm2048_device *bdev, int i,
- int index)
+ int index)
{
int crc;
@@ -1650,14 +1635,14 @@ static int bcm2048_parse_ps_match_c(struct bcm2048_device *bdev, int i,
return 0;
if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
- BCM2048_RDS_BLOCK_C)
+ BCM2048_RDS_BLOCK_C)
return 1;
return 0;
}
static void bcm2048_parse_ps_match_d(struct bcm2048_device *bdev, int i,
- int index)
+ int index)
{
int crc;
@@ -1667,7 +1652,7 @@ static void bcm2048_parse_ps_match_d(struct bcm2048_device *bdev, int i,
return;
if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
- BCM2048_RDS_BLOCK_D)
+ BCM2048_RDS_BLOCK_D)
bcm2048_parse_rds_ps_block(bdev, i, index, crc);
}
@@ -1682,10 +1667,10 @@ static int bcm2048_parse_ps_match_b(struct bcm2048_device *bdev, int i)
/* Block B Radio PS match */
if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
- BCM2048_RDS_BLOCK_B) {
- ps_id = bdev->rds_info.radio_text[i+1] &
+ BCM2048_RDS_BLOCK_B) {
+ ps_id = bdev->rds_info.radio_text[i + 1] &
BCM2048_RDS_BLOCK_MASK;
- ps_group = bdev->rds_info.radio_text[i+1] &
+ ps_group = bdev->rds_info.radio_text[i + 1] &
BCM2048_RDS_GROUP_AB_MASK;
/*
@@ -1709,7 +1694,7 @@ static int bcm2048_parse_ps_match_b(struct bcm2048_device *bdev, int i)
}
if (ps_id == BCM2048_RDS_PS) {
- index = bdev->rds_info.radio_text[i+2] &
+ index = bdev->rds_info.radio_text[i + 2] &
BCM2048_RDS_PS_INDEX;
index <<= 1;
return index;
@@ -1724,7 +1709,6 @@ static void bcm2048_parse_rds_ps(struct bcm2048_device *bdev)
int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0;
for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) {
-
if (match_b) {
match_b = 0;
index = bcm2048_parse_ps_match_b(bdev, i);
@@ -1743,16 +1727,16 @@ static void bcm2048_parse_rds_ps(struct bcm2048_device *bdev)
}
/* Skip erroneous blocks due to messed up A block altogether */
- if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK)
- == BCM2048_RDS_BLOCK_A) {
+ if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+ BCM2048_RDS_BLOCK_A) {
crc = bcm2048_rds_block_crc(bdev, i);
if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
continue;
- /* Syncronize to a good RDS PI */
- if (((bdev->rds_info.radio_text[i+1] << 8) +
- bdev->rds_info.radio_text[i+2]) ==
- bdev->rds_info.rds_pi)
- match_b = 1;
+ /* Synchronize to a good RDS PI */
+ if (((bdev->rds_info.radio_text[i + 1] << 8) +
+ bdev->rds_info.radio_text[i + 2]) ==
+ bdev->rds_info.rds_pi)
+ match_b = 1;
}
}
}
@@ -1764,7 +1748,7 @@ static void bcm2048_rds_fifo_receive(struct bcm2048_device *bdev)
mutex_lock(&bdev->mutex);
err = bcm2048_recv_duples(bdev, BCM2048_I2C_RDS_DATA,
- bdev->rds_info.radio_text, bdev->fifo_size);
+ bdev->rds_info.radio_text, bdev->fifo_size);
if (err != 2) {
dev_err(&bdev->client->dev, "RDS Read problem\n");
mutex_unlock(&bdev->mutex);
@@ -1801,8 +1785,8 @@ static int bcm2048_get_rds_data(struct bcm2048_device *bdev, char *data)
}
for (i = 0; i < bdev->rds_info.text_len; i++) {
- p += sprintf(data_buffer+p, "%x ",
- bdev->rds_info.radio_text[i]);
+ p += sprintf(data_buffer + p, "%x ",
+ bdev->rds_info.radio_text[i]);
}
memcpy(data, data_buffer, p);
@@ -1829,7 +1813,7 @@ static int bcm2048_init(struct bcm2048_device *bdev)
goto exit;
err = bcm2048_set_dac_output(bdev, BCM2048_DAC_OUTPUT_LEFT |
- BCM2048_DAC_OUTPUT_RIGHT);
+ BCM2048_DAC_OUTPUT_RIGHT);
exit:
return err;
@@ -1913,7 +1897,7 @@ unlock:
static void bcm2048_work(struct work_struct *work)
{
struct bcm2048_device *bdev;
- u8 flag_lsb, flag_msb, flags;
+ u8 flag_lsb = 0, flag_msb = 0, flags;
bdev = container_of(work, struct bcm2048_device, work);
bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &flag_lsb);
@@ -1921,7 +1905,6 @@ static void bcm2048_work(struct work_struct *work)
if (flag_lsb & (BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED |
BCM2048_FM_FLAG_SEARCH_TUNE_FAIL)) {
-
if (flag_lsb & BCM2048_FM_FLAG_SEARCH_TUNE_FAIL)
bdev->scan_state = BCM2048_SCAN_FAIL;
else
@@ -1935,7 +1918,7 @@ static void bcm2048_work(struct work_struct *work)
if (bdev->rds_state) {
flags = BCM2048_RDS_FLAG_FIFO_WLINE;
bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1,
- flags);
+ flags);
}
bdev->rds_data_available = 1;
bdev->rd_index = 0; /* new data, new start */
@@ -2074,7 +2057,7 @@ property_str_read(rds_rt, (BCM2048_MAX_RDS_RT + 1))
property_str_read(rds_ps, (BCM2048_MAX_RDS_PS + 1))
property_read(fm_rds_flags, unsigned int, "%u")
-property_str_read(rds_data, BCM2048_MAX_RDS_RADIO_TEXT*5)
+property_str_read(rds_data, BCM2048_MAX_RDS_RADIO_TEXT * 5)
property_read(region_bottom_frequency, unsigned int, "%u")
property_read(region_top_frequency, unsigned int, "%u")
@@ -2084,70 +2067,70 @@ DEFINE_SYSFS_PROPERTY(region, unsigned, int, "%u", 0)
static struct device_attribute attrs[] = {
__ATTR(power_state, S_IRUGO | S_IWUSR, bcm2048_power_state_read,
- bcm2048_power_state_write),
+ bcm2048_power_state_write),
__ATTR(mute, S_IRUGO | S_IWUSR, bcm2048_mute_read,
- bcm2048_mute_write),
+ bcm2048_mute_write),
__ATTR(audio_route, S_IRUGO | S_IWUSR, bcm2048_audio_route_read,
- bcm2048_audio_route_write),
+ bcm2048_audio_route_write),
__ATTR(dac_output, S_IRUGO | S_IWUSR, bcm2048_dac_output_read,
- bcm2048_dac_output_write),
+ bcm2048_dac_output_write),
__ATTR(fm_hi_lo_injection, S_IRUGO | S_IWUSR,
- bcm2048_fm_hi_lo_injection_read,
- bcm2048_fm_hi_lo_injection_write),
+ bcm2048_fm_hi_lo_injection_read,
+ bcm2048_fm_hi_lo_injection_write),
__ATTR(fm_frequency, S_IRUGO | S_IWUSR, bcm2048_fm_frequency_read,
- bcm2048_fm_frequency_write),
+ bcm2048_fm_frequency_write),
__ATTR(fm_af_frequency, S_IRUGO | S_IWUSR,
- bcm2048_fm_af_frequency_read,
- bcm2048_fm_af_frequency_write),
+ bcm2048_fm_af_frequency_read,
+ bcm2048_fm_af_frequency_write),
__ATTR(fm_deemphasis, S_IRUGO | S_IWUSR, bcm2048_fm_deemphasis_read,
- bcm2048_fm_deemphasis_write),
+ bcm2048_fm_deemphasis_write),
__ATTR(fm_rds_mask, S_IRUGO | S_IWUSR, bcm2048_fm_rds_mask_read,
- bcm2048_fm_rds_mask_write),
+ bcm2048_fm_rds_mask_write),
__ATTR(fm_best_tune_mode, S_IRUGO | S_IWUSR,
- bcm2048_fm_best_tune_mode_read,
- bcm2048_fm_best_tune_mode_write),
+ bcm2048_fm_best_tune_mode_read,
+ bcm2048_fm_best_tune_mode_write),
__ATTR(fm_search_rssi_threshold, S_IRUGO | S_IWUSR,
- bcm2048_fm_search_rssi_threshold_read,
- bcm2048_fm_search_rssi_threshold_write),
+ bcm2048_fm_search_rssi_threshold_read,
+ bcm2048_fm_search_rssi_threshold_write),
__ATTR(fm_search_mode_direction, S_IRUGO | S_IWUSR,
- bcm2048_fm_search_mode_direction_read,
- bcm2048_fm_search_mode_direction_write),
+ bcm2048_fm_search_mode_direction_read,
+ bcm2048_fm_search_mode_direction_write),
__ATTR(fm_search_tune_mode, S_IRUGO | S_IWUSR,
- bcm2048_fm_search_tune_mode_read,
- bcm2048_fm_search_tune_mode_write),
+ bcm2048_fm_search_tune_mode_read,
+ bcm2048_fm_search_tune_mode_write),
__ATTR(rds, S_IRUGO | S_IWUSR, bcm2048_rds_read,
- bcm2048_rds_write),
+ bcm2048_rds_write),
__ATTR(rds_b_block_mask, S_IRUGO | S_IWUSR,
- bcm2048_rds_b_block_mask_read,
- bcm2048_rds_b_block_mask_write),
+ bcm2048_rds_b_block_mask_read,
+ bcm2048_rds_b_block_mask_write),
__ATTR(rds_b_block_match, S_IRUGO | S_IWUSR,
- bcm2048_rds_b_block_match_read,
- bcm2048_rds_b_block_match_write),
+ bcm2048_rds_b_block_match_read,
+ bcm2048_rds_b_block_match_write),
__ATTR(rds_pi_mask, S_IRUGO | S_IWUSR, bcm2048_rds_pi_mask_read,
- bcm2048_rds_pi_mask_write),
+ bcm2048_rds_pi_mask_write),
__ATTR(rds_pi_match, S_IRUGO | S_IWUSR, bcm2048_rds_pi_match_read,
- bcm2048_rds_pi_match_write),
+ bcm2048_rds_pi_match_write),
__ATTR(rds_wline, S_IRUGO | S_IWUSR, bcm2048_rds_wline_read,
- bcm2048_rds_wline_write),
+ bcm2048_rds_wline_write),
__ATTR(rds_pi, S_IRUGO, bcm2048_rds_pi_read, NULL),
__ATTR(rds_rt, S_IRUGO, bcm2048_rds_rt_read, NULL),
__ATTR(rds_ps, S_IRUGO, bcm2048_rds_ps_read, NULL),
__ATTR(fm_rds_flags, S_IRUGO, bcm2048_fm_rds_flags_read, NULL),
__ATTR(region_bottom_frequency, S_IRUGO,
- bcm2048_region_bottom_frequency_read, NULL),
+ bcm2048_region_bottom_frequency_read, NULL),
__ATTR(region_top_frequency, S_IRUGO,
- bcm2048_region_top_frequency_read, NULL),
+ bcm2048_region_top_frequency_read, NULL),
__ATTR(fm_carrier_error, S_IRUGO,
- bcm2048_fm_carrier_error_read, NULL),
+ bcm2048_fm_carrier_error_read, NULL),
__ATTR(fm_rssi, S_IRUGO,
- bcm2048_fm_rssi_read, NULL),
+ bcm2048_fm_rssi_read, NULL),
__ATTR(region, S_IRUGO | S_IWUSR, bcm2048_region_read,
- bcm2048_region_write),
+ bcm2048_region_write),
__ATTR(rds_data, S_IRUGO, bcm2048_rds_data_read, NULL),
};
static int bcm2048_sysfs_unregister_properties(struct bcm2048_device *bdev,
- int size)
+ int size)
{
int i;
@@ -2165,7 +2148,7 @@ static int bcm2048_sysfs_register_properties(struct bcm2048_device *bdev)
for (i = 0; i < ARRAY_SIZE(attrs); i++) {
if (device_create_file(&bdev->client->dev, &attrs[i]) != 0) {
dev_err(&bdev->client->dev,
- "could not register sysfs entry\n");
+ "could not register sysfs entry\n");
err = -EBUSY;
bcm2048_sysfs_unregister_properties(bdev, i);
break;
@@ -2175,7 +2158,6 @@ static int bcm2048_sysfs_register_properties(struct bcm2048_device *bdev)
return err;
}
-
static int bcm2048_fops_open(struct file *file)
{
struct bcm2048_device *bdev = video_drvdata(file);
@@ -2197,7 +2179,7 @@ static int bcm2048_fops_release(struct file *file)
}
static unsigned int bcm2048_fops_poll(struct file *file,
- struct poll_table_struct *pts)
+ struct poll_table_struct *pts)
{
struct bcm2048_device *bdev = video_drvdata(file);
int retval = 0;
@@ -2211,7 +2193,7 @@ static unsigned int bcm2048_fops_poll(struct file *file,
}
static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
struct bcm2048_device *bdev = video_drvdata(file);
int i;
@@ -2229,7 +2211,7 @@ static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
}
/* interruptible_sleep_on(&bdev->read_queue); */
if (wait_event_interruptible(bdev->read_queue,
- bdev->rds_data_available) < 0) {
+ bdev->rds_data_available) < 0) {
retval = -EINTR;
goto done;
}
@@ -2245,13 +2227,16 @@ static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
while (i < count) {
unsigned char tmpbuf[3];
- tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2];
- tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1];
- tmpbuf[i+2] = (bdev->rds_info.radio_text[bdev->rd_index + i] & 0xf0) >> 4;
- if ((bdev->rds_info.radio_text[bdev->rd_index+i] &
- BCM2048_RDS_CRC_MASK) == BCM2048_RDS_CRC_UNRECOVARABLE)
- tmpbuf[i+2] |= 0x80;
- if (copy_to_user(buf+i, tmpbuf, 3)) {
+ tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index + i + 2];
+ tmpbuf[i + 1] =
+ bdev->rds_info.radio_text[bdev->rd_index + i + 1];
+ tmpbuf[i + 2] =
+ (bdev->rds_info.radio_text[bdev->rd_index + i] &
+ 0xf0) >> 4;
+ if ((bdev->rds_info.radio_text[bdev->rd_index + i] &
+ BCM2048_RDS_CRC_MASK) == BCM2048_RDS_CRC_UNRECOVARABLE)
+ tmpbuf[i + 2] |= 0x80;
+ if (copy_to_user(buf + i, tmpbuf, 3)) {
retval = -EFAULT;
break;
}
@@ -2319,7 +2304,7 @@ static struct v4l2_queryctrl bcm2048_v4l2_queryctrl[] = {
};
static int bcm2048_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
+ struct v4l2_capability *capability)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
@@ -2337,7 +2322,7 @@ static int bcm2048_vidioc_querycap(struct file *file, void *priv,
}
static int bcm2048_vidioc_g_input(struct file *filp, void *priv,
- unsigned int *i)
+ unsigned int *i)
{
*i = 0;
@@ -2345,7 +2330,7 @@ static int bcm2048_vidioc_g_input(struct file *filp, void *priv,
}
static int bcm2048_vidioc_s_input(struct file *filp, void *priv,
- unsigned int i)
+ unsigned int i)
{
if (i)
return -EINVAL;
@@ -2354,7 +2339,7 @@ static int bcm2048_vidioc_s_input(struct file *filp, void *priv,
}
static int bcm2048_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
+ struct v4l2_queryctrl *qc)
{
int i;
@@ -2369,7 +2354,7 @@ static int bcm2048_vidioc_queryctrl(struct file *file, void *priv,
}
static int bcm2048_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
+ struct v4l2_control *ctrl)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
int err = 0;
@@ -2389,7 +2374,7 @@ static int bcm2048_vidioc_g_ctrl(struct file *file, void *priv,
}
static int bcm2048_vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
+ struct v4l2_control *ctrl)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
int err = 0;
@@ -2417,7 +2402,7 @@ static int bcm2048_vidioc_s_ctrl(struct file *file, void *priv,
}
static int bcm2048_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
+ struct v4l2_audio *audio)
{
if (audio->index > 1)
return -EINVAL;
@@ -2429,7 +2414,7 @@ static int bcm2048_vidioc_g_audio(struct file *file, void *priv,
}
static int bcm2048_vidioc_s_audio(struct file *file, void *priv,
- const struct v4l2_audio *audio)
+ const struct v4l2_audio *audio)
{
if (audio->index != 0)
return -EINVAL;
@@ -2438,7 +2423,7 @@ static int bcm2048_vidioc_s_audio(struct file *file, void *priv,
}
static int bcm2048_vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
+ struct v4l2_tuner *tuner)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
s8 f_error;
@@ -2493,7 +2478,7 @@ static int bcm2048_vidioc_g_tuner(struct file *file, void *priv,
}
static int bcm2048_vidioc_s_tuner(struct file *file, void *priv,
- const struct v4l2_tuner *tuner)
+ const struct v4l2_tuner *tuner)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
@@ -2507,7 +2492,7 @@ static int bcm2048_vidioc_s_tuner(struct file *file, void *priv,
}
static int bcm2048_vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
+ struct v4l2_frequency *freq)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
int err = 0;
@@ -2528,7 +2513,7 @@ static int bcm2048_vidioc_g_frequency(struct file *file, void *priv,
}
static int bcm2048_vidioc_s_frequency(struct file *file, void *priv,
- const struct v4l2_frequency *freq)
+ const struct v4l2_frequency *freq)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
int err;
@@ -2546,7 +2531,7 @@ static int bcm2048_vidioc_s_frequency(struct file *file, void *priv,
}
static int bcm2048_vidioc_s_hw_freq_seek(struct file *file, void *priv,
- const struct v4l2_hw_freq_seek *seek)
+ const struct v4l2_hw_freq_seek *seek)
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
int err;
@@ -2559,7 +2544,7 @@ static int bcm2048_vidioc_s_hw_freq_seek(struct file *file, void *priv,
err = bcm2048_set_fm_search_mode_direction(bdev, seek->seek_upward);
err |= bcm2048_set_fm_search_tune_mode(bdev,
- BCM2048_FM_AUTO_SEARCH_MODE);
+ BCM2048_FM_AUTO_SEARCH_MODE);
return err;
}
@@ -2594,7 +2579,7 @@ static struct video_device bcm2048_viddev_template = {
* I2C driver interface
*/
static int bcm2048_i2c_driver_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct bcm2048_device *bdev;
int err;
@@ -2613,8 +2598,8 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client,
if (client->irq) {
err = request_irq(client->irq,
- bcm2048_handler, IRQF_TRIGGER_FALLING,
- client->name, bdev);
+ bcm2048_handler, IRQF_TRIGGER_FALLING,
+ client->name, bdev);
if (err < 0) {
dev_err(&client->dev, "Could not request IRQ\n");
goto free_bdev;
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 87048a14c34d..0fdff91624fd 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -428,8 +428,8 @@ vpfe_video_get_next_buffer(struct vpfe_video_device *video)
struct vpfe_cap_buffer, list);
list_del(&video->next_frm->list);
- video->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
- return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb, 0);
+ video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0);
}
/* schedule the next buffer which is available on dma queue */
@@ -448,8 +448,8 @@ void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video)
video->cur_frm = video->next_frm;
list_del(&video->next_frm->list);
- video->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
- addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb, 0);
+ video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0);
video->ops->queue(vpfe_dev, addr);
video->state = VPFE_VIDEO_BUFFER_QUEUED;
}
@@ -460,7 +460,7 @@ void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video)
struct vpfe_device *vpfe_dev = video->vpfe_dev;
unsigned long addr;
- addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0);
addr += video->field_off;
video->ops->queue(vpfe_dev, addr);
}
@@ -470,8 +470,8 @@ void vpfe_video_process_buffer_complete(struct vpfe_video_device *video)
{
struct vpfe_pipeline *pipe = &video->pipe;
- v4l2_get_timestamp(&video->cur_frm->vb.v4l2_buf.timestamp);
- vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&video->cur_frm->vb.timestamp);
+ vb2_buffer_done(&video->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
video->cur_frm = video->next_frm;
}
@@ -1078,7 +1078,7 @@ vpfe_g_dv_timings(struct file *file, void *fh,
* the buffer nbuffers and buffer size
*/
static int
-vpfe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vpfe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -1138,12 +1138,13 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb)
static void vpfe_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
/* Get the file handle object and device object */
struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
struct vpfe_video_device *video = fh->video;
struct vpfe_device *vpfe_dev = video->vpfe_dev;
struct vpfe_pipeline *pipe = &video->pipe;
- struct vpfe_cap_buffer *buf = container_of(vb,
+ struct vpfe_cap_buffer *buf = container_of(vbuf,
struct vpfe_cap_buffer, vb);
unsigned long flags;
unsigned long empty;
@@ -1203,10 +1204,10 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
/* Remove buffer from the buffer queue */
list_del(&video->cur_frm->list);
/* Mark state of the current frame to active */
- video->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+ video->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
/* Initialize field_id and started member */
video->field_id = 0;
- addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0);
video->ops->queue(vpfe_dev, addr);
video->state = VPFE_VIDEO_BUFFER_QUEUED;
@@ -1214,10 +1215,12 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret) {
struct vpfe_cap_buffer *buf, *tmp;
- vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
list_for_each_entry_safe(buf, tmp, &video->dma_queue, list) {
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
goto unlock_out;
}
@@ -1234,7 +1237,8 @@ streamoff:
static int vpfe_buffer_init(struct vb2_buffer *vb)
{
- struct vpfe_cap_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vpfe_cap_buffer *buf = container_of(vbuf,
struct vpfe_cap_buffer, vb);
INIT_LIST_HEAD(&buf->list);
@@ -1249,13 +1253,14 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */
if (video->cur_frm == video->next_frm) {
- vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
} else {
if (video->cur_frm != NULL)
- vb2_buffer_done(&video->cur_frm->vb,
+ vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
if (video->next_frm != NULL)
- vb2_buffer_done(&video->next_frm->vb,
+ vb2_buffer_done(&video->next_frm->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
}
@@ -1263,16 +1268,18 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
video->next_frm = list_entry(video->dma_queue.next,
struct vpfe_cap_buffer, list);
list_del(&video->next_frm->list);
- vb2_buffer_done(&video->next_frm->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&video->next_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
}
}
static void vpfe_buf_cleanup(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
struct vpfe_video_device *video = fh->video;
struct vpfe_device *vpfe_dev = video->vpfe_dev;
- struct vpfe_cap_buffer *buf = container_of(vb,
+ struct vpfe_cap_buffer *buf = container_of(vbuf,
struct vpfe_cap_buffer, vb);
v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buf_cleanup\n");
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h
index 1b1b6c4a56b7..673cefe3ef61 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.h
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.h
@@ -22,6 +22,7 @@
#ifndef _DAVINCI_VPFE_VIDEO_H
#define _DAVINCI_VPFE_VIDEO_H
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
struct vpfe_device;
@@ -72,7 +73,7 @@ struct vpfe_pipeline {
container_of(vdev, struct vpfe_video_device, video_dev)
struct vpfe_cap_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c
index bc78da014c33..f2dca69c2bc0 100644
--- a/drivers/staging/media/lirc/lirc_sasem.c
+++ b/drivers/staging/media/lirc/lirc_sasem.c
@@ -181,7 +181,7 @@ static void deregister_from_lirc(struct sasem_context *context)
if (retval)
dev_err(&context->dev->dev,
"%s: unable to deregister from lirc (%d)\n",
- __func__, retval);
+ __func__, retval);
else
dev_info(&context->dev->dev,
"Deregistered Sasem driver (minor:%d)\n", minor);
diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
index 465796a686c4..64a7b2fc5289 100644
--- a/drivers/staging/media/lirc/lirc_serial.c
+++ b/drivers/staging/media/lirc/lirc_serial.c
@@ -109,17 +109,9 @@ static bool iommap;
static int ioshift;
static bool softcarrier = true;
static bool share_irq;
-static bool debug;
static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */
static bool txsense; /* 0 = active high, 1 = active low */
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
- fmt, ## args); \
- } while (0)
-
/* forward declarations */
static long send_pulse_irdeo(unsigned long length);
static long send_pulse_homebrew(unsigned long length);
@@ -352,10 +344,9 @@ static int init_timing_params(unsigned int new_duty_cycle,
/* Derive pulse and space from the period */
pulse_width = period * duty_cycle / 100;
space_width = period - pulse_width;
- dprintk("in init_timing_params, freq=%d, duty_cycle=%d, "
- "clk/jiffy=%ld, pulse=%ld, space=%ld\n",
- freq, duty_cycle, __this_cpu_read(cpu_info.loops_per_jiffy),
- pulse_width, space_width);
+ pr_debug("in init_timing_params, freq=%d, duty_cycle=%d, clk/jiffy=%ld, pulse=%ld, space=%ld, conv_us_to_clocks=%ld\n",
+ freq, duty_cycle, __this_cpu_read(cpu_info.loops_per_jiffy),
+ pulse_width, space_width, conv_us_to_clocks);
return 0;
}
#else /* ! USE_RDTSC */
@@ -377,8 +368,8 @@ static int init_timing_params(unsigned int new_duty_cycle,
period = 256 * 1000000L / freq;
pulse_width = period * duty_cycle / 100;
space_width = period - pulse_width;
- dprintk("in init_timing_params, freq=%d pulse=%ld, space=%ld\n",
- freq, pulse_width, space_width);
+ pr_debug("in init_timing_params, freq=%d pulse=%ld, space=%ld\n",
+ freq, pulse_width, space_width);
return 0;
}
#endif /* USE_RDTSC */
@@ -500,7 +491,7 @@ static void rbwrite(int l)
{
if (lirc_buffer_full(&rbuf)) {
/* no new signals will be accepted */
- dprintk("Buffer overrun\n");
+ pr_debug("Buffer overrun\n");
return;
}
lirc_buffer_write(&rbuf, (void *)&l);
@@ -790,7 +781,7 @@ static int lirc_serial_probe(struct platform_device *dev)
dev_info(&dev->dev, "Manually using active %s receiver\n",
sense ? "low" : "high");
- dprintk("Interrupt %d, port %04x obtained\n", irq, io);
+ dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);
return 0;
}
@@ -895,7 +886,7 @@ static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
return -ENOIOCTLCMD;
case LIRC_SET_SEND_DUTY_CYCLE:
- dprintk("SET_SEND_DUTY_CYCLE\n");
+ pr_debug("SET_SEND_DUTY_CYCLE\n");
if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE))
return -ENOIOCTLCMD;
@@ -907,7 +898,7 @@ static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
return init_timing_params(value, freq);
case LIRC_SET_SEND_CARRIER:
- dprintk("SET_SEND_CARRIER\n");
+ pr_debug("SET_SEND_CARRIER\n");
if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER))
return -ENOIOCTLCMD;
@@ -1102,7 +1093,7 @@ static void __exit lirc_serial_exit_module(void)
{
lirc_unregister_driver(driver.minor);
lirc_serial_exit();
- dprintk("cleaned up module\n");
+ pr_debug("cleaned up module\n");
}
@@ -1153,6 +1144,3 @@ MODULE_PARM_DESC(txsense, "Sense of transmitter circuit"
module_param(softcarrier, bool, S_IRUGO);
MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
index 9bfb725b9986..aa76ccda5b42 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -151,7 +151,7 @@ int omap4iss_get_external_info(struct iss_pipeline *pipe,
ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler,
V4L2_CID_PIXEL_RATE);
- if (ctrl == NULL) {
+ if (!ctrl) {
dev_warn(iss->dev, "no pixel rate control in subdev %s\n",
pipe->external->name);
return -EPIPE;
@@ -422,7 +422,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
? media_entity_to_v4l2_subdev(entity) : NULL;
- if (entity->use_count == 0 && change > 0 && subdev != NULL) {
+ if (entity->use_count == 0 && change > 0 && subdev) {
int ret;
ret = v4l2_subdev_call(subdev, core, s_power, 1);
@@ -433,7 +433,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
entity->use_count += change;
WARN_ON(entity->use_count < 0);
- if (entity->use_count == 0 && change < 0 && subdev != NULL)
+ if (entity->use_count == 0 && change < 0 && subdev)
v4l2_subdev_call(subdev, core, s_power, 0);
return 0;
@@ -469,8 +469,8 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
media_entity_graph_walk_start(&graph, first);
- while ((first = media_entity_graph_walk_next(&graph))
- && first != entity)
+ while ((first = media_entity_graph_walk_next(&graph)) &&
+ first != entity)
if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
iss_pipeline_pm_power_one(first, -change);
@@ -541,7 +541,7 @@ static int iss_pipeline_link_notify(struct media_link *link, u32 flags,
}
if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
- (flags & MEDIA_LNK_FL_ENABLED)) {
+ (flags & MEDIA_LNK_FL_ENABLED)) {
ret = iss_pipeline_pm_power(source, sink_use);
if (ret < 0)
return ret;
@@ -590,7 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
break;
pad = media_entity_remote_pad(pad);
- if (pad == NULL ||
+ if (!pad ||
media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
break;
@@ -658,7 +658,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
break;
pad = media_entity_remote_pad(pad);
- if (pad == NULL ||
+ if (!pad ||
media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
break;
@@ -919,7 +919,7 @@ static int __iss_subclk_update(struct iss_device *iss)
}
int omap4iss_subclk_enable(struct iss_device *iss,
- enum iss_subclk_resource res)
+ enum iss_subclk_resource res)
{
iss->subclk_resources |= res;
@@ -927,7 +927,7 @@ int omap4iss_subclk_enable(struct iss_device *iss,
}
int omap4iss_subclk_disable(struct iss_device *iss,
- enum iss_subclk_resource res)
+ enum iss_subclk_resource res)
{
iss->subclk_resources &= ~res;
@@ -1050,7 +1050,7 @@ struct iss_device *omap4iss_get(struct iss_device *iss)
{
struct iss_device *__iss = iss;
- if (iss == NULL)
+ if (!iss)
return NULL;
mutex_lock(&iss->iss_mutex);
@@ -1065,7 +1065,7 @@ struct iss_device *omap4iss_get(struct iss_device *iss)
iss_enable_interrupts(iss);
out:
- if (__iss != NULL)
+ if (__iss)
iss->ref_count++;
mutex_unlock(&iss->iss_mutex);
@@ -1080,7 +1080,7 @@ out:
*/
void omap4iss_put(struct iss_device *iss)
{
- if (iss == NULL)
+ if (!iss)
return;
mutex_lock(&iss->iss_mutex);
@@ -1137,12 +1137,12 @@ static void iss_unregister_entities(struct iss_device *iss)
*/
static struct v4l2_subdev *
iss_register_subdev_group(struct iss_device *iss,
- struct iss_subdev_i2c_board_info *board_info)
+ struct iss_subdev_i2c_board_info *board_info)
{
struct v4l2_subdev *sensor = NULL;
unsigned int first;
- if (board_info->board_info == NULL)
+ if (!board_info->board_info)
return NULL;
for (first = 1; board_info->board_info; ++board_info, first = 0) {
@@ -1150,7 +1150,7 @@ iss_register_subdev_group(struct iss_device *iss,
struct i2c_adapter *adapter;
adapter = i2c_get_adapter(board_info->i2c_adapter_id);
- if (adapter == NULL) {
+ if (!adapter) {
dev_err(iss->dev,
"%s: Unable to get I2C adapter %d for device %s\n",
__func__, board_info->i2c_adapter_id,
@@ -1160,7 +1160,7 @@ iss_register_subdev_group(struct iss_device *iss,
subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
board_info->board_info, NULL);
- if (subdev == NULL) {
+ if (!subdev) {
dev_err(iss->dev, "Unable to register subdev %s\n",
board_info->board_info->type);
continue;
@@ -1228,7 +1228,7 @@ static int iss_register_entities(struct iss_device *iss)
unsigned int pad;
sensor = iss_register_subdev_group(iss, subdevs->subdevs);
- if (sensor == NULL)
+ if (!sensor)
continue;
sensor->host_priv = subdevs;
@@ -1369,7 +1369,7 @@ static int iss_probe(struct platform_device *pdev)
unsigned int i;
int ret;
- if (pdata == NULL)
+ if (!pdata)
return -EINVAL;
iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
@@ -1406,7 +1406,7 @@ static int iss_probe(struct platform_device *pdev)
if (ret < 0)
goto error;
- if (omap4iss_get(iss) == NULL)
+ if (!omap4iss_get(iss))
goto error;
ret = iss_reset(iss);
@@ -1440,12 +1440,13 @@ static int iss_probe(struct platform_device *pdev)
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));
/* Interrupt */
- iss->irq_num = platform_get_irq(pdev, 0);
- if (iss->irq_num <= 0) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
dev_err(iss->dev, "No IRQ resource\n");
ret = -ENODEV;
goto error_iss;
}
+ iss->irq_num = ret;
if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
"OMAP4 ISS", iss)) {
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index bc83f8246101..c6e6d47ac57f 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -658,7 +658,7 @@ static void csi2_isr_buffer(struct iss_csi2_device *csi2)
* Let video queue operation restart engine if there is an underrun
* condition.
*/
- if (buffer == NULL)
+ if (!buffer)
return;
csi2_set_outaddr(csi2, buffer->iss_addr);
@@ -979,7 +979,7 @@ static int csi2_get_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
fmt->format = *format;
@@ -1001,7 +1001,7 @@ static int csi2_set_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
csi2_try_format(csi2, cfg, fmt->pad, &fmt->format, fmt->which);
diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h
index 3b37978a3bdf..f2f5343b4a80 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.h
+++ b/drivers/staging/media/omap4iss/iss_csi2.h
@@ -116,8 +116,8 @@ struct iss_csi2_ctrl_cfg {
#define CSI2_PAD_SOURCE 1
#define CSI2_PADS_NUM 2
-#define CSI2_OUTPUT_IPIPEIF (1 << 0)
-#define CSI2_OUTPUT_MEMORY (1 << 1)
+#define CSI2_OUTPUT_IPIPEIF BIT(0)
+#define CSI2_OUTPUT_MEMORY BIT(1)
struct iss_csi2_device {
struct v4l2_subdev subdev;
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c
index f94a59299a83..dd0abeffd893 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.c
+++ b/drivers/staging/media/omap4iss/iss_ipipe.c
@@ -247,8 +247,8 @@ ipipe_try_format(struct iss_ipipe_device *ipipe,
* return -EINVAL or zero on success
*/
static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
switch (code->pad) {
case IPIPE_PAD_SINK:
@@ -274,8 +274,8 @@ static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt format;
@@ -320,7 +320,7 @@ static int ipipe_get_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
fmt->format = *format;
@@ -344,7 +344,7 @@ static int ipipe_set_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which);
@@ -353,18 +353,18 @@ static int ipipe_set_format(struct v4l2_subdev *sd,
/* Propagate the format from sink to source */
if (fmt->pad == IPIPE_PAD_SINK) {
format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP,
- fmt->which);
+ fmt->which);
*format = fmt->format;
ipipe_try_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP, format,
- fmt->which);
+ fmt->which);
}
return 0;
}
static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link,
- struct v4l2_subdev_format *source_fmt,
- struct v4l2_subdev_format *sink_fmt)
+ struct v4l2_subdev_format *source_fmt,
+ struct v4l2_subdev_format *sink_fmt)
{
/* Check if the two ends match */
if (source_fmt->format.width != sink_fmt->format.width ||
@@ -440,8 +440,8 @@ static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = {
* return -EINVAL or zero on success
*/
static int ipipe_link_setup(struct media_entity *entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags)
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
@@ -528,7 +528,7 @@ void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe)
}
int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
- struct v4l2_device *vdev)
+ struct v4l2_device *vdev)
{
int ret;
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h
index c22d9041f2a5..d5b441d9cb31 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.h
+++ b/drivers/staging/media/omap4iss/iss_ipipe.h
@@ -21,7 +21,7 @@ enum ipipe_input_entity {
IPIPE_INPUT_IPIPEIF,
};
-#define IPIPE_OUTPUT_VP (1 << 0)
+#define IPIPE_OUTPUT_VP BIT(0)
/* Sink and source IPIPE pads */
#define IPIPE_PAD_SINK 0
@@ -58,7 +58,7 @@ struct iss_ipipe_device {
struct iss_device;
int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
- struct v4l2_device *vdev);
+ struct v4l2_device *vdev);
void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe);
int omap4iss_ipipe_init(struct iss_device *iss);
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
index c0da13d55865..5f9e449e7007 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.c
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
@@ -115,7 +115,7 @@ static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr)
{
struct iss_device *iss = to_iss_device(ipipeif);
- /* Save address splitted in Base Address H & L */
+ /* Save address split in Base Address H & L */
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADU,
(addr >> (16 + 5)) & ISIF_CADU_MASK);
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADL,
@@ -233,7 +233,7 @@ static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif)
ipipeif_write_enable(ipipeif, 0);
buffer = omap4iss_video_buffer_next(&ipipeif->video_out);
- if (buffer == NULL)
+ if (!buffer)
return;
ipipeif_set_outaddr(ipipeif, buffer->iss_addr);
@@ -446,8 +446,8 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
* return -EINVAL or zero on success
*/
static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
@@ -480,8 +480,8 @@ static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt format;
@@ -526,7 +526,7 @@ static int ipipeif_get_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
fmt->format = *format;
@@ -550,7 +550,7 @@ static int ipipeif_set_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which);
@@ -570,7 +570,7 @@ static int ipipeif_set_format(struct v4l2_subdev *sd,
fmt->which);
*format = fmt->format;
ipipeif_try_format(ipipeif, cfg, IPIPEIF_PAD_SOURCE_VP, format,
- fmt->which);
+ fmt->which);
}
return 0;
@@ -656,8 +656,8 @@ static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
* return -EINVAL or zero on success
*/
static int ipipeif_link_setup(struct media_entity *entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags)
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -778,7 +778,7 @@ void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif)
}
int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif,
- struct v4l2_device *vdev)
+ struct v4l2_device *vdev)
{
int ret;
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h
index cbdccb982eee..c6bd96d9656c 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.h
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.h
@@ -22,8 +22,8 @@ enum ipipeif_input_entity {
IPIPEIF_INPUT_CSI2B
};
-#define IPIPEIF_OUTPUT_MEMORY (1 << 0)
-#define IPIPEIF_OUTPUT_VP (1 << 1)
+#define IPIPEIF_OUTPUT_MEMORY BIT(0)
+#define IPIPEIF_OUTPUT_VP BIT(1)
/* Sink and source IPIPEIF pads */
#define IPIPEIF_PAD_SINK 0
@@ -80,13 +80,13 @@ struct iss_device;
int omap4iss_ipipeif_init(struct iss_device *iss);
void omap4iss_ipipeif_cleanup(struct iss_device *iss);
int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif,
- struct v4l2_device *vdev);
+ struct v4l2_device *vdev);
void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif);
int omap4iss_ipipeif_busy(struct iss_ipipeif_device *ipipeif);
void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events);
void omap4iss_ipipeif_restore_context(struct iss_device *iss);
void omap4iss_ipipeif_max_rate(struct iss_ipipeif_device *ipipeif,
- unsigned int *max_rate);
+ unsigned int *max_rate);
#endif /* OMAP4_ISS_IPIPEIF_H */
diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h
index d2b6b6ae9174..cb415e898aca 100644
--- a/drivers/staging/media/omap4iss/iss_regs.h
+++ b/drivers/staging/media/omap4iss/iss_regs.h
@@ -22,21 +22,21 @@
#define ISS_HL_SYSCONFIG_IDLEMODE_FORCEIDLE 0x0
#define ISS_HL_SYSCONFIG_IDLEMODE_NOIDLE 0x1
#define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE 0x2
-#define ISS_HL_SYSCONFIG_SOFTRESET (1 << 0)
+#define ISS_HL_SYSCONFIG_SOFTRESET BIT(0)
#define ISS_HL_IRQSTATUS_RAW(i) (0x20 + (0x10 * (i)))
#define ISS_HL_IRQSTATUS(i) (0x24 + (0x10 * (i)))
#define ISS_HL_IRQENABLE_SET(i) (0x28 + (0x10 * (i)))
#define ISS_HL_IRQENABLE_CLR(i) (0x2c + (0x10 * (i)))
-#define ISS_HL_IRQ_HS_VS (1 << 17)
-#define ISS_HL_IRQ_SIMCOP(i) (1 << (12 + (i)))
-#define ISS_HL_IRQ_BTE (1 << 11)
-#define ISS_HL_IRQ_CBUFF (1 << 10)
-#define ISS_HL_IRQ_CCP2(i) (1 << ((i) > 3 ? 16 : 14 + (i)))
-#define ISS_HL_IRQ_CSIB (1 << 5)
-#define ISS_HL_IRQ_CSIA (1 << 4)
-#define ISS_HL_IRQ_ISP(i) (1 << (i))
+#define ISS_HL_IRQ_HS_VS BIT(17)
+#define ISS_HL_IRQ_SIMCOP(i) BIT(12 + (i))
+#define ISS_HL_IRQ_BTE BIT(11)
+#define ISS_HL_IRQ_CBUFF BIT(10)
+#define ISS_HL_IRQ_CCP2(i) BIT((i) > 3 ? 16 : 14 + (i))
+#define ISS_HL_IRQ_CSIB BIT(5)
+#define ISS_HL_IRQ_CSIA BIT(4)
+#define ISS_HL_IRQ_ISP(i) BIT(i)
#define ISS_CTRL 0x80
#define ISS_CTRL_CLK_DIV_MASK (3 << 4)
@@ -46,24 +46,24 @@
#define ISS_CTRL_SYNC_DETECT_VS_RAISING (3 << 0)
#define ISS_CLKCTRL 0x84
-#define ISS_CLKCTRL_VPORT2_CLK (1 << 30)
-#define ISS_CLKCTRL_VPORT1_CLK (1 << 29)
-#define ISS_CLKCTRL_VPORT0_CLK (1 << 28)
-#define ISS_CLKCTRL_CCP2 (1 << 4)
-#define ISS_CLKCTRL_CSI2_B (1 << 3)
-#define ISS_CLKCTRL_CSI2_A (1 << 2)
-#define ISS_CLKCTRL_ISP (1 << 1)
-#define ISS_CLKCTRL_SIMCOP (1 << 0)
+#define ISS_CLKCTRL_VPORT2_CLK BIT(30)
+#define ISS_CLKCTRL_VPORT1_CLK BIT(29)
+#define ISS_CLKCTRL_VPORT0_CLK BIT(28)
+#define ISS_CLKCTRL_CCP2 BIT(4)
+#define ISS_CLKCTRL_CSI2_B BIT(3)
+#define ISS_CLKCTRL_CSI2_A BIT(2)
+#define ISS_CLKCTRL_ISP BIT(1)
+#define ISS_CLKCTRL_SIMCOP BIT(0)
#define ISS_CLKSTAT 0x88
-#define ISS_CLKSTAT_VPORT2_CLK (1 << 30)
-#define ISS_CLKSTAT_VPORT1_CLK (1 << 29)
-#define ISS_CLKSTAT_VPORT0_CLK (1 << 28)
-#define ISS_CLKSTAT_CCP2 (1 << 4)
-#define ISS_CLKSTAT_CSI2_B (1 << 3)
-#define ISS_CLKSTAT_CSI2_A (1 << 2)
-#define ISS_CLKSTAT_ISP (1 << 1)
-#define ISS_CLKSTAT_SIMCOP (1 << 0)
+#define ISS_CLKSTAT_VPORT2_CLK BIT(30)
+#define ISS_CLKSTAT_VPORT1_CLK BIT(29)
+#define ISS_CLKSTAT_VPORT0_CLK BIT(28)
+#define ISS_CLKSTAT_CCP2 BIT(4)
+#define ISS_CLKSTAT_CSI2_B BIT(3)
+#define ISS_CLKSTAT_CSI2_A BIT(2)
+#define ISS_CLKSTAT_ISP BIT(1)
+#define ISS_CLKSTAT_SIMCOP BIT(0)
#define ISS_PM_STATUS 0x8c
#define ISS_PM_STATUS_CBUFF_PM_MASK (3 << 12)
@@ -75,15 +75,15 @@
#define ISS_PM_STATUS_CSI2_A_PM_MASK (3 << 0)
#define REGISTER0 0x0
-#define REGISTER0_HSCLOCKCONFIG (1 << 24)
+#define REGISTER0_HSCLOCKCONFIG BIT(24)
#define REGISTER0_THS_TERM_MASK (0xff << 8)
#define REGISTER0_THS_TERM_SHIFT 8
#define REGISTER0_THS_SETTLE_MASK (0xff << 0)
#define REGISTER0_THS_SETTLE_SHIFT 0
#define REGISTER1 0x4
-#define REGISTER1_RESET_DONE_CTRLCLK (1 << 29)
-#define REGISTER1_CLOCK_MISS_DETECTOR_STATUS (1 << 25)
+#define REGISTER1_RESET_DONE_CTRLCLK BIT(29)
+#define REGISTER1_CLOCK_MISS_DETECTOR_STATUS BIT(25)
#define REGISTER1_TCLK_TERM_MASK (0x3f << 18)
#define REGISTER1_TCLK_TERM_SHIFT 18
#define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT 10
@@ -103,20 +103,20 @@
#define CSI2_SYSCONFIG_AUTO_IDLE (1 << 0)
#define CSI2_SYSSTATUS 0x14
-#define CSI2_SYSSTATUS_RESET_DONE (1 << 0)
+#define CSI2_SYSSTATUS_RESET_DONE BIT(0)
#define CSI2_IRQSTATUS 0x18
#define CSI2_IRQENABLE 0x1c
/* Shared bits across CSI2_IRQENABLE and IRQSTATUS */
-#define CSI2_IRQ_OCP_ERR (1 << 14)
-#define CSI2_IRQ_SHORT_PACKET (1 << 13)
-#define CSI2_IRQ_ECC_CORRECTION (1 << 12)
-#define CSI2_IRQ_ECC_NO_CORRECTION (1 << 11)
-#define CSI2_IRQ_COMPLEXIO_ERR (1 << 9)
-#define CSI2_IRQ_FIFO_OVF (1 << 8)
-#define CSI2_IRQ_CONTEXT0 (1 << 0)
+#define CSI2_IRQ_OCP_ERR BIT(14)
+#define CSI2_IRQ_SHORT_PACKET BIT(13)
+#define CSI2_IRQ_ECC_CORRECTION BIT(12)
+#define CSI2_IRQ_ECC_NO_CORRECTION BIT(11)
+#define CSI2_IRQ_COMPLEXIO_ERR BIT(9)
+#define CSI2_IRQ_FIFO_OVF BIT(8)
+#define CSI2_IRQ_CONTEXT0 BIT(0)
#define CSI2_CTRL 0x40
#define CSI2_CTRL_MFLAG_LEVH_MASK (7 << 20)
@@ -164,55 +164,55 @@
#define CSI2_COMPLEXIO_IRQENABLE 0x60
/* Shared bits across CSI2_COMPLEXIO_IRQENABLE and IRQSTATUS */
-#define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT (1 << 26)
-#define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER (1 << 25)
-#define CSI2_COMPLEXIO_IRQ_STATEULPM5 (1 << 24)
-#define CSI2_COMPLEXIO_IRQ_STATEULPM4 (1 << 23)
-#define CSI2_COMPLEXIO_IRQ_STATEULPM3 (1 << 22)
-#define CSI2_COMPLEXIO_IRQ_STATEULPM2 (1 << 21)
-#define CSI2_COMPLEXIO_IRQ_STATEULPM1 (1 << 20)
-#define CSI2_COMPLEXIO_IRQ_ERRCONTROL5 (1 << 19)
-#define CSI2_COMPLEXIO_IRQ_ERRCONTROL4 (1 << 18)
-#define CSI2_COMPLEXIO_IRQ_ERRCONTROL3 (1 << 17)
-#define CSI2_COMPLEXIO_IRQ_ERRCONTROL2 (1 << 16)
-#define CSI2_COMPLEXIO_IRQ_ERRCONTROL1 (1 << 15)
-#define CSI2_COMPLEXIO_IRQ_ERRESC5 (1 << 14)
-#define CSI2_COMPLEXIO_IRQ_ERRESC4 (1 << 13)
-#define CSI2_COMPLEXIO_IRQ_ERRESC3 (1 << 12)
-#define CSI2_COMPLEXIO_IRQ_ERRESC2 (1 << 11)
-#define CSI2_COMPLEXIO_IRQ_ERRESC1 (1 << 10)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 (1 << 9)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 (1 << 8)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 (1 << 7)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 (1 << 6)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 (1 << 5)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTHS5 (1 << 4)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTHS4 (1 << 3)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTHS3 (1 << 2)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTHS2 (1 << 1)
-#define CSI2_COMPLEXIO_IRQ_ERRSOTHS1 (1 << 0)
+#define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT BIT(26)
+#define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER BIT(25)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM5 BIT(24)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM4 BIT(23)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM3 BIT(22)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM2 BIT(21)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM1 BIT(20)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL5 BIT(19)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL4 BIT(18)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL3 BIT(17)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL2 BIT(16)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL1 BIT(15)
+#define CSI2_COMPLEXIO_IRQ_ERRESC5 BIT(14)
+#define CSI2_COMPLEXIO_IRQ_ERRESC4 BIT(13)
+#define CSI2_COMPLEXIO_IRQ_ERRESC3 BIT(12)
+#define CSI2_COMPLEXIO_IRQ_ERRESC2 BIT(11)
+#define CSI2_COMPLEXIO_IRQ_ERRESC1 BIT(10)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 BIT(9)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 BIT(8)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 BIT(7)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 BIT(6)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 BIT(5)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS5 BIT(4)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS4 BIT(3)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS3 BIT(2)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS2 BIT(1)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS1 BIT(0)
#define CSI2_DBG_P 0x68
#define CSI2_TIMING 0x6c
-#define CSI2_TIMING_FORCE_RX_MODE_IO1 (1 << 15)
-#define CSI2_TIMING_STOP_STATE_X16_IO1 (1 << 14)
-#define CSI2_TIMING_STOP_STATE_X4_IO1 (1 << 13)
+#define CSI2_TIMING_FORCE_RX_MODE_IO1 BIT(15)
+#define CSI2_TIMING_STOP_STATE_X16_IO1 BIT(14)
+#define CSI2_TIMING_STOP_STATE_X4_IO1 BIT(13)
#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1fff << 0)
#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT 0
#define CSI2_CTX_CTRL1(i) (0x70 + (0x20 * i))
-#define CSI2_CTX_CTRL1_GENERIC (1 << 30)
+#define CSI2_CTX_CTRL1_GENERIC BIT(30)
#define CSI2_CTX_CTRL1_TRANSCODE (0xf << 24)
#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xff << 16)
#define CSI2_CTX_CTRL1_COUNT_MASK (0xff << 8)
#define CSI2_CTX_CTRL1_COUNT_SHIFT 8
-#define CSI2_CTX_CTRL1_EOF_EN (1 << 7)
-#define CSI2_CTX_CTRL1_EOL_EN (1 << 6)
-#define CSI2_CTX_CTRL1_CS_EN (1 << 5)
-#define CSI2_CTX_CTRL1_COUNT_UNLOCK (1 << 4)
-#define CSI2_CTX_CTRL1_PING_PONG (1 << 3)
-#define CSI2_CTX_CTRL1_CTX_EN (1 << 0)
+#define CSI2_CTX_CTRL1_EOF_EN BIT(7)
+#define CSI2_CTX_CTRL1_EOL_EN BIT(6)
+#define CSI2_CTX_CTRL1_CS_EN BIT(5)
+#define CSI2_CTX_CTRL1_COUNT_UNLOCK BIT(4)
+#define CSI2_CTX_CTRL1_PING_PONG BIT(3)
+#define CSI2_CTX_CTRL1_CTX_EN BIT(0)
#define CSI2_CTX_CTRL2(i) (0x74 + (0x20 * i))
#define CSI2_CTX_CTRL2_FRAME_MASK (0xffff << 16)
@@ -244,14 +244,14 @@
(0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT)
/* Shared bits across CSI2_CTX_IRQENABLE and IRQSTATUS */
-#define CSI2_CTX_IRQ_ECC_CORRECTION (1 << 8)
-#define CSI2_CTX_IRQ_LINE_NUMBER (1 << 7)
-#define CSI2_CTX_IRQ_FRAME_NUMBER (1 << 6)
-#define CSI2_CTX_IRQ_CS (1 << 5)
-#define CSI2_CTX_IRQ_LE (1 << 3)
-#define CSI2_CTX_IRQ_LS (1 << 2)
-#define CSI2_CTX_IRQ_FE (1 << 1)
-#define CSI2_CTX_IRQ_FS (1 << 0)
+#define CSI2_CTX_IRQ_ECC_CORRECTION BIT(8)
+#define CSI2_CTX_IRQ_LINE_NUMBER BIT(7)
+#define CSI2_CTX_IRQ_FRAME_NUMBER BIT(6)
+#define CSI2_CTX_IRQ_CS BIT(5)
+#define CSI2_CTX_IRQ_LE BIT(3)
+#define CSI2_CTX_IRQ_LS BIT(2)
+#define CSI2_CTX_IRQ_FE BIT(1)
+#define CSI2_CTX_IRQ_FS BIT(0)
/* ISS BTE */
#define BTE_CTRL (0x0030)
@@ -272,49 +272,49 @@
#define ISP5_IRQENABLE_CLR(i) (0x0030 + (0x10 * (i)))
/* Bits shared for ISP5_IRQ* registers */
-#define ISP5_IRQ_OCP_ERR (1 << 31)
-#define ISP5_IRQ_IPIPE_INT_DPC_RNEW1 (1 << 29)
-#define ISP5_IRQ_IPIPE_INT_DPC_RNEW0 (1 << 28)
-#define ISP5_IRQ_IPIPE_INT_DPC_INIT (1 << 27)
-#define ISP5_IRQ_IPIPE_INT_EOF (1 << 25)
-#define ISP5_IRQ_H3A_INT_EOF (1 << 24)
-#define ISP5_IRQ_RSZ_INT_EOF1 (1 << 23)
-#define ISP5_IRQ_RSZ_INT_EOF0 (1 << 22)
-#define ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR (1 << 19)
-#define ISP5_IRQ_RSZ_FIFO_OVF (1 << 18)
-#define ISP5_IRQ_RSZ_INT_CYC_RSZB (1 << 17)
-#define ISP5_IRQ_RSZ_INT_CYC_RSZA (1 << 16)
-#define ISP5_IRQ_RSZ_INT_DMA (1 << 15)
-#define ISP5_IRQ_RSZ_INT_LAST_PIX (1 << 14)
-#define ISP5_IRQ_RSZ_INT_REG (1 << 13)
-#define ISP5_IRQ_H3A_INT (1 << 12)
-#define ISP5_IRQ_AF_INT (1 << 11)
-#define ISP5_IRQ_AEW_INT (1 << 10)
-#define ISP5_IRQ_IPIPEIF_IRQ (1 << 9)
-#define ISP5_IRQ_IPIPE_INT_HST (1 << 8)
-#define ISP5_IRQ_IPIPE_INT_BSC (1 << 7)
-#define ISP5_IRQ_IPIPE_INT_DMA (1 << 6)
-#define ISP5_IRQ_IPIPE_INT_LAST_PIX (1 << 5)
-#define ISP5_IRQ_IPIPE_INT_REG (1 << 4)
-#define ISP5_IRQ_ISIF_INT(i) (1 << (i))
+#define ISP5_IRQ_OCP_ERR BIT(31)
+#define ISP5_IRQ_IPIPE_INT_DPC_RNEW1 BIT(29)
+#define ISP5_IRQ_IPIPE_INT_DPC_RNEW0 BIT(28)
+#define ISP5_IRQ_IPIPE_INT_DPC_INIT BIT(27)
+#define ISP5_IRQ_IPIPE_INT_EOF BIT(25)
+#define ISP5_IRQ_H3A_INT_EOF BIT(24)
+#define ISP5_IRQ_RSZ_INT_EOF1 BIT(23)
+#define ISP5_IRQ_RSZ_INT_EOF0 BIT(22)
+#define ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR BIT(19)
+#define ISP5_IRQ_RSZ_FIFO_OVF BIT(18)
+#define ISP5_IRQ_RSZ_INT_CYC_RSZB BIT(17)
+#define ISP5_IRQ_RSZ_INT_CYC_RSZA BIT(16)
+#define ISP5_IRQ_RSZ_INT_DMA BIT(15)
+#define ISP5_IRQ_RSZ_INT_LAST_PIX BIT(14)
+#define ISP5_IRQ_RSZ_INT_REG BIT(13)
+#define ISP5_IRQ_H3A_INT BIT(12)
+#define ISP5_IRQ_AF_INT BIT(11)
+#define ISP5_IRQ_AEW_INT BIT(10)
+#define ISP5_IRQ_IPIPEIF_IRQ BIT(9)
+#define ISP5_IRQ_IPIPE_INT_HST BIT(8)
+#define ISP5_IRQ_IPIPE_INT_BSC BIT(7)
+#define ISP5_IRQ_IPIPE_INT_DMA BIT(6)
+#define ISP5_IRQ_IPIPE_INT_LAST_PIX BIT(5)
+#define ISP5_IRQ_IPIPE_INT_REG BIT(4)
+#define ISP5_IRQ_ISIF_INT(i) BIT(i)
#define ISP5_CTRL (0x006c)
-#define ISP5_CTRL_MSTANDBY (1 << 24)
-#define ISP5_CTRL_VD_PULSE_EXT (1 << 23)
-#define ISP5_CTRL_MSTANDBY_WAIT (1 << 20)
-#define ISP5_CTRL_BL_CLK_ENABLE (1 << 15)
-#define ISP5_CTRL_ISIF_CLK_ENABLE (1 << 14)
-#define ISP5_CTRL_H3A_CLK_ENABLE (1 << 13)
-#define ISP5_CTRL_RSZ_CLK_ENABLE (1 << 12)
-#define ISP5_CTRL_IPIPE_CLK_ENABLE (1 << 11)
-#define ISP5_CTRL_IPIPEIF_CLK_ENABLE (1 << 10)
-#define ISP5_CTRL_SYNC_ENABLE (1 << 9)
-#define ISP5_CTRL_PSYNC_CLK_SEL (1 << 8)
+#define ISP5_CTRL_MSTANDBY BIT(24)
+#define ISP5_CTRL_VD_PULSE_EXT BIT(23)
+#define ISP5_CTRL_MSTANDBY_WAIT BIT(20)
+#define ISP5_CTRL_BL_CLK_ENABLE BIT(15)
+#define ISP5_CTRL_ISIF_CLK_ENABLE BIT(14)
+#define ISP5_CTRL_H3A_CLK_ENABLE BIT(13)
+#define ISP5_CTRL_RSZ_CLK_ENABLE BIT(12)
+#define ISP5_CTRL_IPIPE_CLK_ENABLE BIT(11)
+#define ISP5_CTRL_IPIPEIF_CLK_ENABLE BIT(10)
+#define ISP5_CTRL_SYNC_ENABLE BIT(9)
+#define ISP5_CTRL_PSYNC_CLK_SEL BIT(8)
/* ISS ISP ISIF register offsets */
#define ISIF_SYNCEN (0x0000)
-#define ISIF_SYNCEN_DWEN (1 << 1)
-#define ISIF_SYNCEN_SYEN (1 << 0)
+#define ISIF_SYNCEN_DWEN BIT(1)
+#define ISIF_SYNCEN_SYEN BIT(0)
#define ISIF_MODESET (0x0004)
#define ISIF_MODESET_INPMOD_MASK (3 << 12)
@@ -338,7 +338,7 @@
#define ISIF_LNV_MASK (0x7fff)
#define ISIF_HSIZE (0x0034)
-#define ISIF_HSIZE_ADCR (1 << 12)
+#define ISIF_HSIZE_ADCR BIT(12)
#define ISIF_HSIZE_HSIZE_MASK (0xfff)
#define ISIF_CADU (0x003c)
@@ -373,7 +373,7 @@
#define ISIF_CGAMMAWD_GWDI(bpp) ((16 - (bpp)) << 1)
#define ISIF_CCDCFG (0x0088)
-#define ISIF_CCDCFG_Y8POS (1 << 11)
+#define ISIF_CCDCFG_Y8POS BIT(11)
/* ISS ISP IPIPEIF register offsets */
#define IPIPEIF_ENABLE (0x0000)
@@ -391,22 +391,22 @@
#define IPIPEIF_CFG1_INPSRC2_SDRAM_YUV (3 << 2)
#define IPIPEIF_CFG2 (0x0030)
-#define IPIPEIF_CFG2_YUV8P (1 << 7)
-#define IPIPEIF_CFG2_YUV8 (1 << 6)
-#define IPIPEIF_CFG2_YUV16 (1 << 3)
-#define IPIPEIF_CFG2_VDPOL (1 << 2)
-#define IPIPEIF_CFG2_HDPOL (1 << 1)
-#define IPIPEIF_CFG2_INTSW (1 << 0)
+#define IPIPEIF_CFG2_YUV8P BIT(7)
+#define IPIPEIF_CFG2_YUV8 BIT(6)
+#define IPIPEIF_CFG2_YUV16 BIT(3)
+#define IPIPEIF_CFG2_VDPOL BIT(2)
+#define IPIPEIF_CFG2_HDPOL BIT(1)
+#define IPIPEIF_CFG2_INTSW BIT(0)
#define IPIPEIF_CLKDIV (0x0040)
/* ISS ISP IPIPE register offsets */
#define IPIPE_SRC_EN (0x0000)
-#define IPIPE_SRC_EN_EN (1 << 0)
+#define IPIPE_SRC_EN_EN BIT(0)
#define IPIPE_SRC_MODE (0x0004)
-#define IPIPE_SRC_MODE_WRT (1 << 1)
-#define IPIPE_SRC_MODE_OST (1 << 0)
+#define IPIPE_SRC_MODE_WRT BIT(1)
+#define IPIPE_SRC_MODE_OST BIT(0)
#define IPIPE_SRC_FMT (0x0008)
#define IPIPE_SRC_FMT_RAW2YUV (0 << 0)
@@ -449,13 +449,13 @@
#define IPIPE_SRC_STA (0x0024)
#define IPIPE_GCK_MMR (0x0028)
-#define IPIPE_GCK_MMR_REG (1 << 0)
+#define IPIPE_GCK_MMR_REG BIT(0)
#define IPIPE_GCK_PIX (0x002c)
-#define IPIPE_GCK_PIX_G3 (1 << 3)
-#define IPIPE_GCK_PIX_G2 (1 << 2)
-#define IPIPE_GCK_PIX_G1 (1 << 1)
-#define IPIPE_GCK_PIX_G0 (1 << 0)
+#define IPIPE_GCK_PIX_G3 BIT(3)
+#define IPIPE_GCK_PIX_G2 BIT(2)
+#define IPIPE_GCK_PIX_G1 BIT(1)
+#define IPIPE_GCK_PIX_G0 BIT(0)
#define IPIPE_DPC_LUT_EN (0x0034)
#define IPIPE_DPC_LUT_SEL (0x0038)
@@ -633,8 +633,8 @@
#define IPIPE_YUV_OFT_CR (0x02c4)
#define IPIPE_YUV_PHS (0x02c8)
-#define IPIPE_YUV_PHS_LPF (1 << 1)
-#define IPIPE_YUV_PHS_POS (1 << 0)
+#define IPIPE_YUV_PHS_LPF BIT(1)
+#define IPIPE_YUV_PHS_POS BIT(0)
#define IPIPE_YEE_EN (0x02d4)
#define IPIPE_YEE_TYP (0x02d8)
@@ -739,8 +739,8 @@
/* ISS ISP Resizer register offsets */
#define RSZ_REVISION (0x0000)
#define RSZ_SYSCONFIG (0x0004)
-#define RSZ_SYSCONFIG_RSZB_CLK_EN (1 << 9)
-#define RSZ_SYSCONFIG_RSZA_CLK_EN (1 << 8)
+#define RSZ_SYSCONFIG_RSZB_CLK_EN BIT(9)
+#define RSZ_SYSCONFIG_RSZA_CLK_EN BIT(8)
#define RSZ_IN_FIFO_CTRL (0x000c)
#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1ff << 16)
@@ -752,18 +752,18 @@
#define RSZ_FRACDIV_MASK (0xffff)
#define RSZ_SRC_EN (0x0020)
-#define RSZ_SRC_EN_SRC_EN (1 << 0)
+#define RSZ_SRC_EN_SRC_EN BIT(0)
#define RSZ_SRC_MODE (0x0024)
-#define RSZ_SRC_MODE_OST (1 << 0)
-#define RSZ_SRC_MODE_WRT (1 << 1)
+#define RSZ_SRC_MODE_OST BIT(0)
+#define RSZ_SRC_MODE_WRT BIT(1)
#define RSZ_SRC_FMT0 (0x0028)
-#define RSZ_SRC_FMT0_BYPASS (1 << 1)
-#define RSZ_SRC_FMT0_SEL (1 << 0)
+#define RSZ_SRC_FMT0_BYPASS BIT(1)
+#define RSZ_SRC_FMT0_SEL BIT(0)
#define RSZ_SRC_FMT1 (0x002c)
-#define RSZ_SRC_FMT1_IN420 (1 << 1)
+#define RSZ_SRC_FMT1_IN420 BIT(1)
#define RSZ_SRC_VPS (0x0030)
#define RSZ_SRC_VSZ (0x0034)
@@ -773,10 +773,10 @@
#define RSZ_DMA_RZB (0x0044)
#define RSZ_DMA_STA (0x0048)
#define RSZ_GCK_MMR (0x004c)
-#define RSZ_GCK_MMR_MMR (1 << 0)
+#define RSZ_GCK_MMR_MMR BIT(0)
#define RSZ_GCK_SDR (0x0054)
-#define RSZ_GCK_SDR_CORE (1 << 0)
+#define RSZ_GCK_SDR_CORE BIT(0)
#define RSZ_IRQ_RZA (0x0058)
#define RSZ_IRQ_RZA_MASK (0x1fff)
@@ -790,12 +790,12 @@
#define RSZ_YUV_C_MAX (0x006c)
#define RSZ_SEQ (0x0074)
-#define RSZ_SEQ_HRVB (1 << 2)
-#define RSZ_SEQ_HRVA (1 << 0)
+#define RSZ_SEQ_HRVB BIT(2)
+#define RSZ_SEQ_HRVA BIT(0)
#define RZA_EN (0x0078)
#define RZA_MODE (0x007c)
-#define RZA_MODE_ONE_SHOT (1 << 0)
+#define RZA_MODE_ONE_SHOT BIT(0)
#define RZA_420 (0x0080)
#define RZA_I_VPS (0x0084)
@@ -859,10 +859,10 @@
#define RZB_SDR_C_PTR_E (0x0194)
/* Shared Bitmasks between RZA & RZB */
-#define RSZ_EN_EN (1 << 0)
+#define RSZ_EN_EN BIT(0)
-#define RSZ_420_CEN (1 << 1)
-#define RSZ_420_YEN (1 << 0)
+#define RSZ_420_CEN BIT(1)
+#define RSZ_420_YEN BIT(0)
#define RSZ_I_VPS_MASK (0x1fff)
@@ -878,8 +878,8 @@
#define RSZ_V_DIF_MASK (0x3fff)
-#define RSZ_V_TYP_C (1 << 1)
-#define RSZ_V_TYP_Y (1 << 0)
+#define RSZ_V_TYP_C BIT(1)
+#define RSZ_V_TYP_Y BIT(0)
#define RSZ_V_LPF_C_MASK (0x3f << 6)
#define RSZ_V_LPF_C_SHIFT 6
@@ -890,14 +890,14 @@
#define RSZ_H_DIF_MASK (0x3fff)
-#define RSZ_H_TYP_C (1 << 1)
-#define RSZ_H_TYP_Y (1 << 0)
+#define RSZ_H_TYP_C BIT(1)
+#define RSZ_H_TYP_Y BIT(0)
#define RSZ_H_LPF_C_MASK (0x3f << 6)
#define RSZ_H_LPF_C_SHIFT 6
#define RSZ_H_LPF_Y_MASK (0x3f << 0)
#define RSZ_H_LPF_Y_SHIFT 0
-#define RSZ_DWN_EN_DWN_EN (1 << 0)
+#define RSZ_DWN_EN_DWN_EN BIT(0)
#endif /* _OMAP4_ISS_REGS_H_ */
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
index 5030cf3cd34c..9c8180bba77e 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.c
+++ b/drivers/staging/media/omap4iss/iss_resizer.c
@@ -143,7 +143,7 @@ static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr)
informat = &resizer->formats[RESIZER_PAD_SINK];
outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM];
- /* Save address splitted in Base Address H & L */
+ /* Save address split in Base Address H & L */
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_H,
(addr >> 16) & 0xffff);
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_L,
@@ -168,7 +168,7 @@ static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr)
c_addr |= addr & 0x7f;
}
- /* Save address splitted in Base Address H & L */
+ /* Save address split in Base Address H & L */
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_H,
(c_addr >> 16) & 0xffff);
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_L,
@@ -274,7 +274,7 @@ static void resizer_isr_buffer(struct iss_resizer_device *resizer)
resizer_enable(resizer, 0);
buffer = omap4iss_video_buffer_next(&resizer->video_out);
- if (buffer == NULL)
+ if (!buffer)
return;
resizer_set_outaddr(resizer, buffer->iss_addr);
@@ -482,7 +482,6 @@ resizer_try_format(struct iss_resizer_device *resizer,
fmt->width &= ~15;
fmt->height = clamp_t(u32, height, 32, fmt->height);
break;
-
}
fmt->colorspace = V4L2_COLORSPACE_JPEG;
@@ -497,8 +496,8 @@ resizer_try_format(struct iss_resizer_device *resizer,
* return -EINVAL or zero on success
*/
static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
@@ -542,8 +541,8 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
}
static int resizer_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt format;
@@ -588,7 +587,7 @@ static int resizer_get_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __resizer_get_format(resizer, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
fmt->format = *format;
@@ -612,7 +611,7 @@ static int resizer_set_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
format = __resizer_get_format(resizer, cfg, fmt->pad, fmt->which);
- if (format == NULL)
+ if (!format)
return -EINVAL;
resizer_try_format(resizer, cfg, fmt->pad, &fmt->format, fmt->which);
@@ -625,7 +624,7 @@ static int resizer_set_format(struct v4l2_subdev *sd,
fmt->which);
*format = fmt->format;
resizer_try_format(resizer, cfg, RESIZER_PAD_SOURCE_MEM, format,
- fmt->which);
+ fmt->which);
}
return 0;
@@ -711,8 +710,8 @@ static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
* return -EINVAL or zero on success
*/
static int resizer_link_setup(struct media_entity *entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags)
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
@@ -734,7 +733,6 @@ static int resizer_link_setup(struct media_entity *entity,
else if (remote->entity == &iss->ipipe.subdev.entity)
resizer->input = RESIZER_INPUT_IPIPE;
-
break;
case RESIZER_PAD_SOURCE_MEM | MEDIA_ENT_T_DEVNODE:
@@ -822,7 +820,7 @@ void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer)
}
int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer,
- struct v4l2_device *vdev)
+ struct v4l2_device *vdev)
{
int ret;
diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h
index 3727498b06a3..1e145abafc65 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.h
+++ b/drivers/staging/media/omap4iss/iss_resizer.h
@@ -22,7 +22,7 @@ enum resizer_input_entity {
RESIZER_INPUT_IPIPEIF
};
-#define RESIZER_OUTPUT_MEMORY (1 << 0)
+#define RESIZER_OUTPUT_MEMORY BIT(0)
/* Sink and source RESIZER pads */
#define RESIZER_PAD_SINK 0
@@ -63,13 +63,13 @@ struct iss_device;
int omap4iss_resizer_init(struct iss_device *iss);
void omap4iss_resizer_cleanup(struct iss_device *iss);
int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer,
- struct v4l2_device *vdev);
+ struct v4l2_device *vdev);
void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer);
int omap4iss_resizer_busy(struct iss_resizer_device *resizer);
void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events);
void omap4iss_resizer_restore_context(struct iss_device *iss);
void omap4iss_resizer_max_rate(struct iss_resizer_device *resizer,
- unsigned int *max_rate);
+ unsigned int *max_rate);
#endif /* OMAP4_ISS_RESIZER_H */
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index 40405d8710a6..2a0158bb4974 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -25,7 +25,6 @@
#include "iss_video.h"
#include "iss.h"
-
/* -----------------------------------------------------------------------------
* Helper functions
*/
@@ -191,7 +190,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
remote = media_entity_remote_pad(&video->pad);
- if (remote == NULL ||
+ if (!remote ||
media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
return NULL;
@@ -241,7 +240,7 @@ __iss_video_get_format(struct iss_video *video,
int ret;
subdev = iss_video_remote_subdev(video, &pad);
- if (subdev == NULL)
+ if (!subdev)
return -EINVAL;
memset(&fmt, 0, sizeof(fmt));
@@ -288,7 +287,7 @@ iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh)
*/
static int iss_video_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *count, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -311,7 +310,8 @@ static int iss_video_queue_setup(struct vb2_queue *vq,
static void iss_video_buf_cleanup(struct vb2_buffer *vb)
{
- struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb);
if (buffer->iss_addr)
buffer->iss_addr = 0;
@@ -319,8 +319,9 @@ static void iss_video_buf_cleanup(struct vb2_buffer *vb)
static int iss_video_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
- struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
+ struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb);
struct iss_video *video = vfh->video;
unsigned long size = vfh->format.fmt.pix.sizeimage;
dma_addr_t addr;
@@ -342,9 +343,10 @@ static int iss_video_buf_prepare(struct vb2_buffer *vb)
static void iss_video_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
struct iss_video *video = vfh->video;
- struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
+ struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb);
struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
unsigned long flags;
bool empty;
@@ -420,7 +422,6 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
enum iss_pipeline_state state;
struct iss_buffer *buf;
unsigned long flags;
- struct timespec ts;
spin_lock_irqsave(&video->qlock, flags);
if (WARN_ON(list_empty(&video->dmaqueue))) {
@@ -433,9 +434,7 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
list_del(&buf->list);
spin_unlock_irqrestore(&video->qlock, flags);
- ktime_get_ts(&ts);
- buf->vb.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
- buf->vb.v4l2_buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ v4l2_get_timestamp(&buf->vb.timestamp);
/* Do frame number propagation only if this is the output video node.
* Frame number either comes from the CSI receivers or it gets
@@ -444,12 +443,12 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
* first, so the input number might lag behind by 1 in some cases.
*/
if (video == pipe->output && !pipe->do_propagation)
- buf->vb.v4l2_buf.sequence =
+ buf->vb.sequence =
atomic_inc_return(&pipe->frame_number);
else
- buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number);
+ buf->vb.sequence = atomic_read(&pipe->frame_number);
- vb2_buffer_done(&buf->vb, pipe->error ?
+ vb2_buffer_done(&buf->vb.vb2_buf, pipe->error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
pipe->error = false;
@@ -471,7 +470,7 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
return NULL;
}
- if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
+ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input) {
spin_lock(&pipe->lock);
pipe->state &= ~ISS_PIPELINE_STREAM;
spin_unlock(&pipe->lock);
@@ -480,7 +479,7 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
list);
spin_unlock_irqrestore(&video->qlock, flags);
- buf->vb.state = VB2_BUF_STATE_ACTIVE;
+ buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
return buf;
}
@@ -503,7 +502,7 @@ void omap4iss_video_cancel_stream(struct iss_video *video)
buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
vb2_queue_error(video->queue);
@@ -624,7 +623,7 @@ iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
return -EINVAL;
subdev = iss_video_remote_subdev(video, &pad);
- if (subdev == NULL)
+ if (!subdev)
return -EINVAL;
iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
@@ -806,7 +805,7 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
pipe->input = far_end;
pipe->output = video;
} else {
- if (far_end == NULL) {
+ if (!far_end) {
ret = -EPIPE;
goto err_iss_video_check_format;
}
@@ -841,7 +840,7 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
* to the stream on command. In memory-to-memory mode, it will be
* started when buffers are queued on both the input and output.
*/
- if (pipe->input == NULL) {
+ if (!pipe->input) {
unsigned long flags;
ret = omap4iss_pipeline_set_stream(pipe,
@@ -974,14 +973,14 @@ static int iss_video_open(struct file *file)
int ret = 0;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (handle == NULL)
+ if (!handle)
return -ENOMEM;
v4l2_fh_init(&handle->vfh, &video->video);
v4l2_fh_add(&handle->vfh);
/* If this is the first user, initialise the pipeline. */
- if (omap4iss_get(video->iss) == NULL) {
+ if (!omap4iss_get(video->iss)) {
ret = -EBUSY;
goto done;
}
@@ -1116,7 +1115,7 @@ int omap4iss_video_init(struct iss_video *video, const char *name)
mutex_init(&video->stream_lock);
/* Initialize the video device. */
- if (video->ops == NULL)
+ if (!video->ops)
video->ops = &iss_video_dummy_ops;
video->video.fops = &iss_video_fops;
diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h
index f11fce2cb977..41532eda1277 100644
--- a/drivers/staging/media/omap4iss/iss_video.h
+++ b/drivers/staging/media/omap4iss/iss_video.h
@@ -18,7 +18,7 @@
#include <media/media-entity.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#define ISS_VIDEO_DRIVER_NAME "issvideo"
@@ -117,12 +117,12 @@ static inline int iss_pipeline_ready(struct iss_pipeline *pipe)
*/
struct iss_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
dma_addr_t iss_addr;
};
-#define to_iss_buffer(buf) container_of(buf, struct iss_buffer, buffer)
+#define to_iss_buffer(buf) container_of(buf, struct iss_buffer, vb)
enum iss_video_dmaqueue_flags {
/* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */
diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c
index 49411b722f19..dc3fb25b52aa 100644
--- a/drivers/staging/most/aim-cdev/cdev.c
+++ b/drivers/staging/most/aim-cdev/cdev.c
@@ -32,7 +32,6 @@ static struct most_aim cdev_aim;
struct aim_channel {
wait_queue_head_t wq;
- wait_queue_head_t poll_wq;
struct cdev cdev;
struct device *dev;
struct mutex io_mutex;
@@ -47,6 +46,7 @@ struct aim_channel {
atomic_t access_ref;
struct list_head list;
};
+
#define to_channel(d) container_of(d, struct aim_channel, cdev)
static struct list_head channel_list;
static spinlock_t ch_list_lock;
@@ -87,8 +87,8 @@ static int aim_open(struct inode *inode, struct file *filp)
filp->private_data = channel;
if (((channel->cfg->direction == MOST_CH_RX) &&
- ((filp->f_flags & O_ACCMODE) != O_RDONLY))
- || ((channel->cfg->direction == MOST_CH_TX) &&
+ ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
+ ((channel->cfg->direction == MOST_CH_TX) &&
((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
pr_info("WARN: Access flags mismatch\n");
return -EACCES;
@@ -100,7 +100,7 @@ static int aim_open(struct inode *inode, struct file *filp)
}
ret = most_start_channel(channel->iface, channel->channel_id,
- &cdev_aim);
+ &cdev_aim);
if (ret)
atomic_dec(&channel->access_ref);
return ret;
@@ -232,8 +232,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
channel->keep_mbo = false;
goto start_copy;
}
- while ((!kfifo_out(&channel->fifo, &mbo, 1))
- && (channel->dev)) {
+ while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) {
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(channel->wq,
@@ -283,7 +282,7 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait)
struct aim_channel *c = filp->private_data;
unsigned int mask = 0;
- poll_wait(filp, &c->poll_wq, wait);
+ poll_wait(filp, &c->wq, wait);
if (c->cfg->direction == MOST_CH_RX) {
if (!kfifo_is_empty(&c->fifo))
@@ -459,7 +458,6 @@ static int aim_probe(struct most_interface *iface, int channel_id,
goto error_alloc_kfifo;
}
init_waitqueue_head(&channel->wq);
- init_waitqueue_head(&channel->poll_wq);
mutex_init(&channel->io_mutex);
spin_lock_irqsave(&ch_list_lock, cl_flags);
list_add_tail(&channel->list, &channel_list);
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index 5f0ea9b79a3d..3c7beb03871d 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -24,7 +24,6 @@
#include "mostcore.h"
#include "networking.h"
-
#define MEP_HDR_LEN 8
#define MDP_HDR_LEN 16
#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
@@ -47,8 +46,6 @@
#define HB(value) ((u8)((u16)(value) >> 8))
#define LB(value) ((u8)(value))
-
-
#define EXTRACT_BIT_SET(bitset_name, value) \
(((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
@@ -81,7 +78,6 @@ static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
static struct spinlock list_lock;
static struct most_aim aim;
-
static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
{
u8 *buff = mbo->virt_address;
@@ -432,7 +428,7 @@ static int aim_rx_data(struct mbo *mbo)
const u32 zero = 0;
struct net_dev_context *nd;
char *buf = mbo->virt_address;
- uint32_t len = mbo->processed_length;
+ u32 len = mbo->processed_length;
struct sk_buff *skb;
struct net_device *dev;
diff --git a/drivers/staging/most/aim-network/networking.h b/drivers/staging/most/aim-network/networking.h
index 1b8b434fabb0..6f346d410525 100644
--- a/drivers/staging/most/aim-network/networking.h
+++ b/drivers/staging/most/aim-network/networking.h
@@ -15,9 +15,7 @@
#include "mostcore.h"
-
void most_deliver_netinfo(struct most_interface *iface,
unsigned char link_stat, unsigned char *mac_addr);
-
#endif
diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c
index 4d3376340daa..9c645801cff4 100644
--- a/drivers/staging/most/aim-sound/sound.c
+++ b/drivers/staging/most/aim-sound/sound.c
@@ -470,7 +470,6 @@ static struct snd_pcm_ops pcm_ops = {
.mmap = snd_pcm_lib_mmap_vmalloc,
};
-
static int split_arg_list(char *buf, char **card_name, char **pcm_format)
{
*card_name = strsep(&buf, ".");
diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c
index 345a82437311..13abf7c275a4 100644
--- a/drivers/staging/most/aim-v4l2/video.c
+++ b/drivers/staging/most/aim-v4l2/video.c
@@ -29,7 +29,6 @@
#include "mostcore.h"
-
#define V4L2_AIM_MAX_INPUT 1
static struct most_aim aim_info;
@@ -60,11 +59,9 @@ struct aim_fh {
u32 offs;
};
-
static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
static struct spinlock list_lock;
-
static inline bool data_ready(struct most_video_dev *mdev)
{
return !list_empty(&mdev->pending_mbos);
@@ -75,7 +72,6 @@ static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
return list_first_entry(&mdev->pending_mbos, struct mbo, list);
}
-
static int aim_vdev_open(struct file *filp)
{
int ret;
@@ -92,7 +88,7 @@ static int aim_vdev_open(struct file *filp)
return -EINVAL;
}
- fh = kzalloc(sizeof(struct aim_fh), GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
if (!fh)
return -ENOMEM;
@@ -243,28 +239,6 @@ static void aim_set_format_struct(struct v4l2_format *f)
static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
struct v4l2_format *format)
{
-#if 0
- u32 const pixfmt = format->fmt.pix.pixelformat;
- const char *fmt;
-
- if (pixfmt != V4L2_PIX_FMT_MPEG) {
- if (cmd == VIDIOC_TRY_FMT)
- fmt = KERN_ERR "try %c%c%c%c failed\n";
- else
- fmt = KERN_ERR "set %c%c%c%c failed\n";
- } else {
- if (cmd == VIDIOC_TRY_FMT)
- fmt = KERN_ERR "try %c%c%c%c\n";
- else
- fmt = KERN_ERR "set %c%c%c%c\n";
- }
- printk(fmt,
- (pixfmt) & 255,
- (pixfmt >> 8) & 255,
- (pixfmt >> 16) & 255,
- (pixfmt >> 24) & 255);
-#endif
-
if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
return -EINVAL;
@@ -276,7 +250,6 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
return 0;
}
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -496,7 +469,6 @@ static void aim_unregister_videodev(struct most_video_dev *mdev)
video_unregister_device(mdev->vdev);
}
-
static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
{
struct most_video_dev *mdev =
diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h
index 314f7de2be73..5a713df1d1d4 100644
--- a/drivers/staging/most/hdm-dim2/dim2_errors.h
+++ b/drivers/staging/most/hdm-dim2/dim2_errors.h
@@ -19,7 +19,6 @@
extern "C" {
#endif
-
/**
* MOST DIM errors.
*/
@@ -59,7 +58,6 @@ enum dim_errors_t {
DIM_ERR_OVERFLOW,
};
-
#ifdef __cplusplus
}
#endif
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
index 81dd8de57e4f..172257596f1f 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.c
@@ -19,7 +19,6 @@
#include "dim2_reg.h"
#include <linux/stddef.h>
-
/*
* The number of frames per sub-buffer for synchronous channels.
* Allowed values: 1, 2, 4, 8, 16, 32, 64.
@@ -51,7 +50,6 @@
*/
#define DBR_MAP_SIZE 2
-
/* -------------------------------------------------------------------------- */
/* not configurable area */
@@ -60,10 +58,9 @@
#define MLB_CAT 0x80
#define AHB_CAT 0x88
-#define DBR_SIZE (16*1024) /* specified by IP */
+#define DBR_SIZE (16 * 1024) /* specified by IP */
#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE)
-
/* -------------------------------------------------------------------------- */
/* generic helper functions and macros */
@@ -77,11 +74,10 @@ static inline u32 bit_mask(u8 position)
static inline bool dim_on_error(u8 error_id, const char *error_message)
{
- DIMCB_OnError(error_id, error_message);
+ dimcb_on_error(error_id, error_message);
return false;
}
-
/* -------------------------------------------------------------------------- */
/* types and local variables */
@@ -94,7 +90,6 @@ struct lld_global_vars_t {
static struct lld_global_vars_t g = { false };
-
/* -------------------------------------------------------------------------- */
static int dbr_get_mask_size(u16 size)
@@ -156,44 +151,44 @@ static void free_dbr(int offs, int size)
static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
{
- DIMCB_IoWrite(&g.dim2->MADR, ctr_addr);
+ dimcb_io_write(&g.dim2->MADR, ctr_addr);
/* wait till transfer is completed */
- while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1)
+ while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
continue;
- DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */
+ dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */
- return DIMCB_IoRead((&g.dim2->MDAT0) + mdat_idx);
+ return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx);
}
static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
{
enum { MADR_WNR_BIT = 31 };
- DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */
+ dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */
if (mask[0] != 0)
- DIMCB_IoWrite(&g.dim2->MDAT0, value[0]);
+ dimcb_io_write(&g.dim2->MDAT0, value[0]);
if (mask[1] != 0)
- DIMCB_IoWrite(&g.dim2->MDAT1, value[1]);
+ dimcb_io_write(&g.dim2->MDAT1, value[1]);
if (mask[2] != 0)
- DIMCB_IoWrite(&g.dim2->MDAT2, value[2]);
+ dimcb_io_write(&g.dim2->MDAT2, value[2]);
if (mask[3] != 0)
- DIMCB_IoWrite(&g.dim2->MDAT3, value[3]);
+ dimcb_io_write(&g.dim2->MDAT3, value[3]);
- DIMCB_IoWrite(&g.dim2->MDWE0, mask[0]);
- DIMCB_IoWrite(&g.dim2->MDWE1, mask[1]);
- DIMCB_IoWrite(&g.dim2->MDWE2, mask[2]);
- DIMCB_IoWrite(&g.dim2->MDWE3, mask[3]);
+ dimcb_io_write(&g.dim2->MDWE0, mask[0]);
+ dimcb_io_write(&g.dim2->MDWE1, mask[1]);
+ dimcb_io_write(&g.dim2->MDWE2, mask[2]);
+ dimcb_io_write(&g.dim2->MDWE3, mask[3]);
- DIMCB_IoWrite(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr);
+ dimcb_io_write(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr);
/* wait till transfer is completed */
- while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1)
+ while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
continue;
- DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */
+ dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */
}
static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
@@ -327,7 +322,6 @@ static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
}
-
static void dim2_clear_ctram(void)
{
u32 ctr_addr;
@@ -347,15 +341,15 @@ static void dim2_configure_channel(
dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe);
/* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
- DIMCB_IoWrite(&g.dim2->ACMR0,
- DIMCB_IoRead(&g.dim2->ACMR0) | bit_mask(ch_addr));
+ dimcb_io_write(&g.dim2->ACMR0,
+ dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr));
}
static void dim2_clear_channel(u8 ch_addr)
{
/* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
- DIMCB_IoWrite(&g.dim2->ACMR0,
- DIMCB_IoRead(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
+ dimcb_io_write(&g.dim2->ACMR0,
+ dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
dim2_clear_cat(AHB_CAT, ch_addr);
dim2_clear_adt(ch_addr);
@@ -461,20 +455,20 @@ static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
static void dim2_cleanup(void)
{
/* disable MediaLB */
- DIMCB_IoWrite(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
+ dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
dim2_clear_ctram();
/* disable mlb_int interrupt */
- DIMCB_IoWrite(&g.dim2->MIEN, 0);
+ dimcb_io_write(&g.dim2->MIEN, 0);
/* clear status for all dma channels */
- DIMCB_IoWrite(&g.dim2->ACSR0, 0xFFFFFFFF);
- DIMCB_IoWrite(&g.dim2->ACSR1, 0xFFFFFFFF);
+ dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF);
+ dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF);
/* mask interrupts for all channels */
- DIMCB_IoWrite(&g.dim2->ACMR0, 0);
- DIMCB_IoWrite(&g.dim2->ACMR1, 0);
+ dimcb_io_write(&g.dim2->ACMR0, 0);
+ dimcb_io_write(&g.dim2->ACMR1, 0);
}
static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
@@ -482,39 +476,23 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
dim2_cleanup();
/* configure and enable MediaLB */
- DIMCB_IoWrite(&g.dim2->MLBC0,
- enable_6pin << MLBC0_MLBPEN_BIT |
- mlb_clock << MLBC0_MLBCLK_SHIFT |
- MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT |
- true << MLBC0_MLBEN_BIT);
+ dimcb_io_write(&g.dim2->MLBC0,
+ enable_6pin << MLBC0_MLBPEN_BIT |
+ mlb_clock << MLBC0_MLBCLK_SHIFT |
+ MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT |
+ true << MLBC0_MLBEN_BIT);
/* activate all HBI channels */
- DIMCB_IoWrite(&g.dim2->HCMR0, 0xFFFFFFFF);
- DIMCB_IoWrite(&g.dim2->HCMR1, 0xFFFFFFFF);
+ dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF);
+ dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF);
/* enable HBI */
- DIMCB_IoWrite(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
+ dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
/* configure DMA */
- DIMCB_IoWrite(&g.dim2->ACTL,
- ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
- true << ACTL_SCE_BIT);
-
-#if 0
- DIMCB_IoWrite(&g.dim2->MIEN,
- bit_mask(MIEN_CTX_BREAK_BIT) |
- bit_mask(MIEN_CTX_PE_BIT) |
- bit_mask(MIEN_CTX_DONE_BIT) |
- bit_mask(MIEN_CRX_BREAK_BIT) |
- bit_mask(MIEN_CRX_PE_BIT) |
- bit_mask(MIEN_CRX_DONE_BIT) |
- bit_mask(MIEN_ATX_BREAK_BIT) |
- bit_mask(MIEN_ATX_PE_BIT) |
- bit_mask(MIEN_ATX_DONE_BIT) |
- bit_mask(MIEN_ARX_BREAK_BIT) |
- bit_mask(MIEN_ARX_PE_BIT) |
- bit_mask(MIEN_ARX_DONE_BIT));
-#endif
+ dimcb_io_write(&g.dim2->ACTL,
+ ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
+ true << ACTL_SCE_BIT);
}
static bool dim2_is_mlb_locked(void)
@@ -522,15 +500,14 @@ static bool dim2_is_mlb_locked(void)
u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
bit_mask(MLBC1_LOCKERR_BIT);
- u32 const c1 = DIMCB_IoRead(&g.dim2->MLBC1);
+ u32 const c1 = dimcb_io_read(&g.dim2->MLBC1);
u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
- DIMCB_IoWrite(&g.dim2->MLBC1, c1 & nda_mask);
- return (DIMCB_IoRead(&g.dim2->MLBC1) & mask1) == 0 &&
- (DIMCB_IoRead(&g.dim2->MLBC0) & mask0) != 0;
+ dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask);
+ return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 &&
+ (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0;
}
-
/* -------------------------------------------------------------------------- */
/* channel help routines */
@@ -554,12 +531,11 @@ static inline bool service_channel(u8 ch_addr, u8 idx)
}
/* clear channel status bit */
- DIMCB_IoWrite(&g.dim2->ACSR0, bit_mask(ch_addr));
+ dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
return true;
}
-
/* -------------------------------------------------------------------------- */
/* channel init routines */
@@ -671,11 +647,10 @@ static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
return true;
}
-
/* -------------------------------------------------------------------------- */
/* API */
-u8 DIM_Startup(void *dim_base_address, u32 mlb_clock)
+u8 dim_startup(void *dim_base_address, u32 mlb_clock)
{
g.dim_is_initialized = false;
@@ -688,7 +663,8 @@ u8 DIM_Startup(void *dim_base_address, u32 mlb_clock)
return DIM_INIT_ERR_MLB_CLOCK;
g.dim2 = dim_base_address;
- g.dbr_map[0] = g.dbr_map[1] = 0;
+ g.dbr_map[0] = 0;
+ g.dbr_map[1] = 0;
dim2_initialize(mlb_clock >= 3, mlb_clock);
@@ -697,13 +673,13 @@ u8 DIM_Startup(void *dim_base_address, u32 mlb_clock)
return DIM_NO_ERROR;
}
-void DIM_Shutdown(void)
+void dim_shutdown(void)
{
g.dim_is_initialized = false;
dim2_cleanup();
}
-bool DIM_GetLockState(void)
+bool dim_get_lock_state(void)
{
return dim2_is_mlb_locked();
}
@@ -730,7 +706,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
return DIM_NO_ERROR;
}
-u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size)
+u16 dim_norm_ctrl_async_buffer_size(u16 buf_size)
{
return norm_ctrl_async_buffer_size(buf_size);
}
@@ -741,7 +717,7 @@ u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size)
*
* Returns non-zero correct buffer size or zero by error.
*/
-u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length)
+u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
{
if (!check_packet_length(packet_length))
return 0;
@@ -755,7 +731,7 @@ u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length)
*
* Returns non-zero correct buffer size or zero by error.
*/
-u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame)
+u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
{
if (!check_bytes_per_frame(bytes_per_frame))
return 0;
@@ -763,22 +739,22 @@ u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame)
return norm_sync_buffer_size(buf_size, bytes_per_frame);
}
-u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 max_buffer_size)
+u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size)
{
return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
max_buffer_size);
}
-u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 max_buffer_size)
+u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size)
{
return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
max_buffer_size);
}
-u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 packet_length)
+u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 packet_length)
{
if (!g.dim_is_initialized || !ch)
return DIM_ERR_DRIVER_NOT_INITIALIZED;
@@ -802,8 +778,8 @@ u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
return DIM_NO_ERROR;
}
-u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 bytes_per_frame)
+u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 bytes_per_frame)
{
if (!g.dim_is_initialized || !ch)
return DIM_ERR_DRIVER_NOT_INITIALIZED;
@@ -827,7 +803,7 @@ u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
return DIM_NO_ERROR;
}
-u8 DIM_DestroyChannel(struct dim_channel *ch)
+u8 dim_destroy_channel(struct dim_channel *ch)
{
if (!g.dim_is_initialized || !ch)
return DIM_ERR_DRIVER_NOT_INITIALIZED;
@@ -840,7 +816,7 @@ u8 DIM_DestroyChannel(struct dim_channel *ch)
return DIM_NO_ERROR;
}
-void DIM_ServiceIrq(struct dim_channel *const *channels)
+void dim_service_irq(struct dim_channel *const *channels)
{
bool state_changed;
@@ -874,11 +850,11 @@ void DIM_ServiceIrq(struct dim_channel *const *channels)
} while (state_changed);
/* clear pending Interrupts */
- DIMCB_IoWrite(&g.dim2->MS0, 0);
- DIMCB_IoWrite(&g.dim2->MS1, 0);
+ dimcb_io_write(&g.dim2->MS0, 0);
+ dimcb_io_write(&g.dim2->MS1, 0);
}
-u8 DIM_ServiceChannel(struct dim_channel *ch)
+u8 dim_service_channel(struct dim_channel *ch)
{
if (!g.dim_is_initialized || !ch)
return DIM_ERR_DRIVER_NOT_INITIALIZED;
@@ -886,8 +862,8 @@ u8 DIM_ServiceChannel(struct dim_channel *ch)
return channel_service(ch);
}
-struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
- struct dim_ch_state_t *state_ptr)
+struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
+ struct dim_ch_state_t *state_ptr)
{
if (!ch || !state_ptr)
return NULL;
@@ -898,7 +874,8 @@ struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
return state_ptr;
}
-bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size)
+bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
+ u16 buffer_size)
{
if (!ch)
return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
@@ -907,7 +884,7 @@ bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size)
return channel_start(ch, buffer_addr, buffer_size);
}
-bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number)
+bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number)
{
if (!ch)
return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h
index ebb7d87a45fc..48cdd9c8cde1 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.h
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.h
@@ -17,7 +17,6 @@
#include <linux/types.h>
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -66,51 +65,49 @@ struct dim_channel {
u16 done_sw_buffers_number; /*< Done software buffers number. */
};
+u8 dim_startup(void *dim_base_address, u32 mlb_clock);
-u8 DIM_Startup(void *dim_base_address, u32 mlb_clock);
-
-void DIM_Shutdown(void);
-
-bool DIM_GetLockState(void);
+void dim_shutdown(void);
-u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size);
+bool dim_get_lock_state(void);
-u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length);
+u16 dim_norm_ctrl_async_buffer_size(u16 buf_size);
-u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame);
+u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length);
-u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 max_buffer_size);
+u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame);
-u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 max_buffer_size);
+u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size);
-u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 packet_length);
+u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size);
-u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
- u16 bytes_per_frame);
+u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 packet_length);
-u8 DIM_DestroyChannel(struct dim_channel *ch);
+u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 bytes_per_frame);
-void DIM_ServiceIrq(struct dim_channel *const *channels);
+u8 dim_destroy_channel(struct dim_channel *ch);
-u8 DIM_ServiceChannel(struct dim_channel *ch);
+void dim_service_irq(struct dim_channel *const *channels);
-struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
- struct dim_ch_state_t *dim_ch_state_ptr);
+u8 dim_service_channel(struct dim_channel *ch);
-bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr,
- u16 buffer_size);
+struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
+ struct dim_ch_state_t *state_ptr);
-bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number);
+bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
+ u16 buffer_size);
-u32 DIMCB_IoRead(u32 *ptr32);
+bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number);
-void DIMCB_IoWrite(u32 *ptr32, u32 value);
+u32 dimcb_io_read(u32 *ptr32);
-void DIMCB_OnError(u8 error_id, const char *error_message);
+void dimcb_io_write(u32 *ptr32, u32 value);
+void dimcb_on_error(u8 error_id, const char *error_message);
#ifdef __cplusplus
}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
index 58a85146b429..327d738c7194 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c
@@ -37,7 +37,7 @@
#define MAX_BUFFERS_PACKET 32
#define MAX_BUFFERS_STREAMING 32
#define MAX_BUF_SIZE_PACKET 2048
-#define MAX_BUF_SIZE_STREAMING (8*1024)
+#define MAX_BUF_SIZE_STREAMING (8 * 1024)
/* command line parameter to select clock speed */
static char *clock_speed;
@@ -73,8 +73,8 @@ struct hdm_channel {
char name[sizeof "caNNN"];
bool is_initialized;
struct dim_channel ch;
- struct list_head pending_list; /* before DIM_EnqueueBuffer() */
- struct list_head started_list; /* after DIM_EnqueueBuffer() */
+ struct list_head pending_list; /* before dim_enqueue_buffer() */
+ struct list_head started_list; /* after dim_enqueue_buffer() */
enum most_channel_direction direction;
enum most_channel_data_type data_type;
};
@@ -128,40 +128,40 @@ bool dim2_sysfs_get_state_cb(void)
unsigned long flags;
spin_lock_irqsave(&dim_lock, flags);
- state = DIM_GetLockState();
+ state = dim_get_lock_state();
spin_unlock_irqrestore(&dim_lock, flags);
return state;
}
/**
- * DIMCB_IoRead - callback from HAL to read an I/O register
+ * dimcb_io_read - callback from HAL to read an I/O register
* @ptr32: register address
*/
-u32 DIMCB_IoRead(u32 *ptr32)
+u32 dimcb_io_read(u32 *ptr32)
{
return __raw_readl(ptr32);
}
/**
- * DIMCB_IoWrite - callback from HAL to write value to an I/O register
+ * dimcb_io_write - callback from HAL to write value to an I/O register
* @ptr32: register address
* @value: value to write
*/
-void DIMCB_IoWrite(u32 *ptr32, u32 value)
+void dimcb_io_write(u32 *ptr32, u32 value)
{
__raw_writel(value, ptr32);
}
/**
- * DIMCB_OnError - callback from HAL to report miscommunication between
+ * dimcb_on_error - callback from HAL to report miscommunication between
* HDM and HAL
* @error_id: Error ID
* @error_message: Error message. Some text in a free format
*/
-void DIMCB_OnError(u8 error_id, const char *error_message)
+void dimcb_on_error(u8 error_id, const char *error_message)
{
- pr_err("DIMCB_OnError: error_id - %d, error_message - %s\n", error_id,
+ pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id,
error_message);
}
@@ -202,9 +202,9 @@ static int startup_dim(struct platform_device *pdev)
if (dev->clk_speed == -1) {
pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n");
dev->clk_speed = CLK_3072FS;
- } else
+ } else {
pr_info("Selected clock speed: %s\n", clock_speed);
-
+ }
if (pdata && pdata->init) {
int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
@@ -212,9 +212,9 @@ static int startup_dim(struct platform_device *pdev)
return ret;
}
- hal_ret = DIM_Startup(dev->io_base, dev->clk_speed);
+ hal_ret = dim_startup(dev->io_base, dev->clk_speed);
if (hal_ret != DIM_NO_ERROR) {
- pr_err("DIM_Startup failed: %d\n", hal_ret);
+ pr_err("dim_startup failed: %d\n", hal_ret);
if (pdata && pdata->destroy)
pdata->destroy(pdata);
return -ENODEV;
@@ -246,7 +246,7 @@ static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
return -EAGAIN;
}
- if (!DIM_GetChannelState(&hdm_ch->ch, &st)->ready) {
+ if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) {
spin_unlock_irqrestore(&dim_lock, flags);
return -EAGAIN;
}
@@ -255,7 +255,7 @@ static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
buf_size = mbo->buffer_length;
BUG_ON(mbo->bus_address == 0);
- if (!DIM_EnqueueBuffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
+ if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
list_del(head->next);
spin_unlock_irqrestore(&dim_lock, flags);
mbo->processed_length = 0;
@@ -340,13 +340,13 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
spin_lock_irqsave(&dim_lock, flags);
- done_buffers = DIM_GetChannelState(&hdm_ch->ch, &st)->done_buffers;
+ done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers;
if (!done_buffers) {
spin_unlock_irqrestore(&dim_lock, flags);
return;
}
- if (!DIM_DetachBuffers(&hdm_ch->ch, done_buffers)) {
+ if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) {
spin_unlock_irqrestore(&dim_lock, flags);
return;
}
@@ -371,7 +371,6 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
if (hdm_ch->data_type == MOST_CH_ASYNC &&
hdm_ch->direction == MOST_CH_RX &&
PACKET_IS_NET_INFO(data)) {
-
retrieve_netinfo(dev, mbo);
spin_lock_irqsave(&dim_lock, flags);
@@ -380,12 +379,12 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
} else {
if (hdm_ch->data_type == MOST_CH_CONTROL ||
hdm_ch->data_type == MOST_CH_ASYNC) {
-
u32 const data_size =
(u32)data[0] * 256 + data[1] + 2;
mbo->processed_length =
- min(data_size, (u32)mbo->buffer_length);
+ min_t(u32, data_size,
+ mbo->buffer_length);
} else {
mbo->processed_length = mbo->buffer_length;
}
@@ -398,7 +397,7 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
}
static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
- struct dim_channel **buffer)
+ struct dim_channel **buffer)
{
int idx = 0;
int ch_idx;
@@ -429,7 +428,7 @@ static void dim2_tasklet_fn(unsigned long data)
continue;
spin_lock_irqsave(&dim_lock, flags);
- DIM_ServiceChannel(&(dev->hch[ch_idx].ch));
+ dim_service_channel(&dev->hch[ch_idx].ch);
spin_unlock_irqrestore(&dim_lock, flags);
service_done_flag(dev, ch_idx);
@@ -453,7 +452,7 @@ static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
unsigned long flags;
spin_lock_irqsave(&dim_lock, flags);
- DIM_ServiceIrq(get_active_channels(dev, buffer));
+ dim_service_irq(get_active_channels(dev, buffer));
spin_unlock_irqrestore(&dim_lock, flags);
#if !defined(ENABLE_HDM_TEST)
@@ -535,7 +534,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
switch (ccfg->data_type) {
case MOST_CH_CONTROL:
- new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
+ new_size = dim_norm_ctrl_async_buffer_size(buf_size);
if (new_size == 0) {
pr_err("%s: too small buffer size\n", hdm_ch->name);
return -EINVAL;
@@ -545,11 +544,11 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
pr_warn("%s: fixed buffer size (%d -> %d)\n",
hdm_ch->name, buf_size, new_size);
spin_lock_irqsave(&dim_lock, flags);
- hal_ret = DIM_InitControl(&hdm_ch->ch, is_tx, ch_addr,
- buf_size);
+ hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr,
+ buf_size);
break;
case MOST_CH_ASYNC:
- new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
+ new_size = dim_norm_ctrl_async_buffer_size(buf_size);
if (new_size == 0) {
pr_err("%s: too small buffer size\n", hdm_ch->name);
return -EINVAL;
@@ -559,10 +558,10 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
pr_warn("%s: fixed buffer size (%d -> %d)\n",
hdm_ch->name, buf_size, new_size);
spin_lock_irqsave(&dim_lock, flags);
- hal_ret = DIM_InitAsync(&hdm_ch->ch, is_tx, ch_addr, buf_size);
+ hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, buf_size);
break;
case MOST_CH_ISOC_AVP:
- new_size = DIM_NormIsocBufferSize(buf_size, sub_size);
+ new_size = dim_norm_isoc_buffer_size(buf_size, sub_size);
if (new_size == 0) {
pr_err("%s: invalid sub-buffer size or too small buffer size\n",
hdm_ch->name);
@@ -573,10 +572,10 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
pr_warn("%s: fixed buffer size (%d -> %d)\n",
hdm_ch->name, buf_size, new_size);
spin_lock_irqsave(&dim_lock, flags);
- hal_ret = DIM_InitIsoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+ hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
break;
case MOST_CH_SYNC:
- new_size = DIM_NormSyncBufferSize(buf_size, sub_size);
+ new_size = dim_norm_sync_buffer_size(buf_size, sub_size);
if (new_size == 0) {
pr_err("%s: invalid sub-buffer size or too small buffer size\n",
hdm_ch->name);
@@ -587,7 +586,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
pr_warn("%s: fixed buffer size (%d -> %d)\n",
hdm_ch->name, buf_size, new_size);
spin_lock_irqsave(&dim_lock, flags);
- hal_ret = DIM_InitSync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+ hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
break;
default:
pr_err("%s: configure failed, bad channel type: %d\n",
@@ -707,7 +706,7 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx)
return -EPERM;
spin_lock_irqsave(&dim_lock, flags);
- hal_ret = DIM_DestroyChannel(&hdm_ch->ch);
+ hal_ret = dim_destroy_channel(&hdm_ch->ch);
hdm_ch->is_initialized = false;
if (ch_idx == dev->atx_idx)
dev->atx_idx = -1;
@@ -884,7 +883,7 @@ static int dim2_remove(struct platform_device *pdev)
unsigned long flags;
spin_lock_irqsave(&dim_lock, flags);
- DIM_Shutdown();
+ dim_shutdown();
spin_unlock_irqrestore(&dim_lock, flags);
if (pdata && pdata->destroy)
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
index 476f66f4c566..bcf6a79f6744 100644
--- a/drivers/staging/most/hdm-dim2/dim2_reg.h
+++ b/drivers/staging/most/hdm-dim2/dim2_reg.h
@@ -21,7 +21,6 @@
extern "C" {
#endif
-
struct dim2_regs {
/* 0x00 */ u32 MLBC0;
/* 0x01 */ u32 rsvd0[1];
@@ -67,8 +66,7 @@ struct dim2_regs {
/* 0xF7 */ u32 ACMR1;
};
-
-#define DIM2_MASK(n) (~((~(u32)0)<<(n)))
+#define DIM2_MASK(n) (~((~(u32)0) << (n)))
enum {
MLBC0_MLBLK_BIT = 7,
@@ -168,7 +166,6 @@ enum {
CAT_CL_MASK = DIM2_MASK(6)
};
-
#ifdef __cplusplus
}
#endif
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
index e719691035b0..b71dd027ebc7 100644
--- a/drivers/staging/most/hdm-dim2/dim2_sysfs.h
+++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
@@ -16,10 +16,8 @@
#ifndef DIM2_SYSFS_H
#define DIM2_SYSFS_H
-
#include <linux/kobject.h>
-
struct medialb_bus {
struct kobject kobj_group;
};
@@ -35,5 +33,4 @@ void dim2_sysfs_destroy(struct medialb_bus *bus);
*/
bool dim2_sysfs_get_state_cb(void);
-
#endif /* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
index 2cce1e572e48..ba0263bb3d12 100644
--- a/drivers/staging/most/hdm-i2c/hdm_i2c.c
+++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c
@@ -35,7 +35,6 @@ enum { CH_RX, CH_TX, NUM_CHANNELS };
#define list_first_mbo(ptr) \
list_first_entry(ptr, struct mbo, list)
-
/* IRQ / Polling option */
static bool polling_req;
module_param(polling_req, bool, S_IRUGO);
@@ -93,10 +92,9 @@ static int configure_channel(struct most_interface *most_iface,
return -EPERM;
}
- if (channel_config->direction == MOST_CH_RX) {
- if (dev->polling_mode)
- schedule_delayed_work(&dev->rx.dwork,
- msecs_to_jiffies(MSEC_PER_SEC / 4));
+ if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) {
+ schedule_delayed_work(&dev->rx.dwork,
+ msecs_to_jiffies(MSEC_PER_SEC / 4));
}
dev->is_open[ch_idx] = true;
@@ -198,7 +196,7 @@ static void do_rx_work(struct hdm_i2c *dev)
struct mbo *mbo;
unsigned char msg[MAX_BUF_SIZE_CONTROL];
int ret, ch_idx = CH_RX;
- uint16_t pml, data_size;
+ u16 pml, data_size;
/* Read PML (2 bytes) */
ret = i2c_master_recv(dev->client, msg, 2);
@@ -270,8 +268,9 @@ static void pending_rx_work(struct work_struct *work)
schedule_delayed_work(&dev->rx.dwork,
msecs_to_jiffies(MSEC_PER_SEC
/ scan_rate));
- } else
+ } else {
enable_irq(dev->client->irq);
+ }
}
/*
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
index 0bf38c454362..41690f801fb8 100644
--- a/drivers/staging/most/hdm-usb/hdm_usb.c
+++ b/drivers/staging/most/hdm-usb/hdm_usb.c
@@ -77,6 +77,7 @@ struct buf_anchor {
struct list_head list;
struct completion urb_compl;
};
+
#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj)
/**
@@ -88,6 +89,7 @@ struct most_dci_obj {
struct kobject kobj;
struct usb_device *usb_device;
};
+
#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
/**
@@ -131,6 +133,7 @@ struct most_dev {
struct timer_list link_stat_timer;
struct work_struct poll_work_obj;
};
+
#define to_mdev(d) container_of(d, struct most_dev, iface)
#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
@@ -246,10 +249,11 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
if (cfg->packets_per_xact == 0) {
pr_warn("Misconfig: Packets per XACT zero\n");
frame_size = 0;
- } else if (cfg->packets_per_xact == 0xFF)
+ } else if (cfg->packets_per_xact == 0xFF) {
frame_size = (USB_MTU / sub_size) * sub_size;
- else
+ } else {
frame_size = cfg->packets_per_xact * sub_size;
+ }
break;
default:
pr_warn("Query frame size of non-streaming channel\n");
@@ -983,8 +987,8 @@ struct most_dci_attribute {
const char *buf,
size_t count);
};
-#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
+#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
/**
* dci_attr_show - show function for dci object
@@ -1235,11 +1239,10 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
num_endpoints = usb_iface_desc->desc.bNumEndpoints;
mutex_init(&mdev->io_mutex);
INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
- init_timer(&mdev->link_stat_timer);
+ setup_timer(&mdev->link_stat_timer, link_stat_timer_handler,
+ (unsigned long)mdev);
mdev->usb_device = usb_dev;
- mdev->link_stat_timer.function = link_stat_timer_handler;
- mdev->link_stat_timer.data = (unsigned long)mdev;
mdev->link_stat_timer.expires = jiffies + (2 * HZ);
mdev->iface.mod = hdm_usb_fops.owner;
@@ -1413,7 +1416,7 @@ static int __init hdm_usb_init(void)
return -EIO;
}
schedule_usb_work = create_workqueue("hdmu_work");
- if (schedule_usb_work == NULL) {
+ if (!schedule_usb_work) {
pr_err("could not create workqueue\n");
usb_deregister(&hdm_usb);
return -ENOMEM;
diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c
index 0efc3911aaa4..ed1ed25b6d1d 100644
--- a/drivers/staging/most/mostcore/core.c
+++ b/drivers/staging/most/mostcore/core.c
@@ -49,7 +49,7 @@ struct most_c_obj {
struct completion cleanup;
atomic_t mbo_ref;
atomic_t mbo_nq_level;
- uint16_t channel_id;
+ u16 channel_id;
bool is_poisoned;
struct mutex start_mutex;
int is_starving;
@@ -69,6 +69,7 @@ struct most_c_obj {
struct mutex stop_task_mutex;
wait_queue_head_t hdm_fifo_wq;
};
+
#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
struct most_inst_obj {
@@ -80,6 +81,7 @@ struct most_inst_obj {
struct kobject kobj;
struct list_head list;
};
+
#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
/**
@@ -115,6 +117,7 @@ struct most_c_attr {
const char *buf,
size_t count);
};
+
#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
#define MOST_CHNL_ATTR(_name, _mode, _show, _store) \
@@ -247,8 +250,8 @@ static void most_channel_release(struct kobject *kobj)
}
static ssize_t show_available_directions(struct most_c_obj *c,
- struct most_c_attr *attr,
- char *buf)
+ struct most_c_attr *attr,
+ char *buf)
{
unsigned int i = c->channel_id;
@@ -331,7 +334,6 @@ static ssize_t show_channel_starving(struct most_c_obj *c,
return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
}
-
#define create_show_channel_attribute(val) \
static MOST_CHNL_ATTR(val, S_IRUGO, show_##val, NULL)
@@ -397,11 +399,11 @@ static ssize_t store_set_direction(struct most_c_obj *c,
const char *buf,
size_t count)
{
- if (!strcmp(buf, "dir_rx\n"))
+ if (!strcmp(buf, "dir_rx\n")) {
c->cfg.direction = MOST_CH_RX;
- else if (!strcmp(buf, "dir_tx\n"))
+ } else if (!strcmp(buf, "dir_tx\n")) {
c->cfg.direction = MOST_CH_TX;
- else {
+ } else {
pr_info("WARN: invalid attribute settings\n");
return -EINVAL;
}
@@ -428,15 +430,15 @@ static ssize_t store_set_datatype(struct most_c_obj *c,
const char *buf,
size_t count)
{
- if (!strcmp(buf, "control\n"))
+ if (!strcmp(buf, "control\n")) {
c->cfg.data_type = MOST_CH_CONTROL;
- else if (!strcmp(buf, "async\n"))
+ } else if (!strcmp(buf, "async\n")) {
c->cfg.data_type = MOST_CH_ASYNC;
- else if (!strcmp(buf, "sync\n"))
+ } else if (!strcmp(buf, "sync\n")) {
c->cfg.data_type = MOST_CH_SYNC;
- else if (!strcmp(buf, "isoc_avp\n"))
+ } else if (!strcmp(buf, "isoc_avp\n")) {
c->cfg.data_type = MOST_CH_ISOC_AVP;
- else {
+ } else {
pr_info("WARN: invalid attribute settings\n");
return -EINVAL;
}
@@ -493,7 +495,6 @@ create_channel_attribute(set_datatype);
create_channel_attribute(set_subbuffer_size);
create_channel_attribute(set_packets_per_xact);
-
/**
* most_channel_def_attrs - array of default attributes of channel object
*/
@@ -598,6 +599,7 @@ struct most_inst_attribute {
const char *buf,
size_t count);
};
+
#define to_instance_attr(a) \
container_of(a, struct most_inst_attribute, attr)
@@ -720,7 +722,6 @@ static struct kobj_type most_inst_ktype = {
static struct kset *most_inst_kset;
-
/**
* create_most_inst_obj - creates an instance object
* @name: name of the object to be created
@@ -780,11 +781,11 @@ struct most_aim_obj {
char add_link[STRING_SIZE];
char remove_link[STRING_SIZE];
};
+
#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
static struct list_head aim_list;
-
/**
* struct most_aim_attribute - to access the attributes of AIM object
* @attr: attributes of an AIM
@@ -801,6 +802,7 @@ struct most_aim_attribute {
const char *buf,
size_t count);
};
+
#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
/**
@@ -1120,7 +1122,6 @@ static void destroy_most_aim_obj(struct most_aim_obj *p)
kobject_put(&p->kobj);
}
-
/* ___ ___
* ___C O R E___
*/
@@ -1183,8 +1184,8 @@ static int hdm_enqueue_thread(void *data)
while (likely(!kthread_should_stop())) {
wait_event_interruptible(c->hdm_fifo_wq,
- (mbo = get_hdm_mbo(c))
- || kthread_should_stop());
+ (mbo = get_hdm_mbo(c)) ||
+ kthread_should_stop());
if (unlikely(!mbo))
continue;
@@ -1449,7 +1450,6 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
}
EXPORT_SYMBOL_GPL(most_get_mbo);
-
/**
* most_put_mbo - return buffer to pool
* @mbo: buffer object
@@ -1587,8 +1587,7 @@ out:
return 0;
error:
- if (iface->mod)
- module_put(iface->mod);
+ module_put(iface->mod);
modref--;
mutex_unlock(&c->start_mutex);
return ret;
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
index e148b324331a..bda3850d5435 100644
--- a/drivers/staging/most/mostcore/mostcore.h
+++ b/drivers/staging/most/mostcore/mostcore.h
@@ -60,7 +60,6 @@ enum most_channel_data_type {
MOST_CH_SYNC = 1 << 5,
};
-
enum mbo_status_flags {
/* MBO was processed successfully (data was send or received )*/
MBO_SUCCESS = 0,
@@ -317,5 +316,4 @@ int most_start_channel(struct most_interface *iface, int channel_idx,
int most_stop_channel(struct most_interface *iface, int channel_idx,
struct most_aim *);
-
#endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
index cf982288f68e..47bb56f1f8c0 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -145,7 +145,7 @@ static int spinand_read_id(struct spi_device *spi_nand, u8 *id)
* Once the status turns to be ready, the other status bits also are
* valid status bits.
*/
-static int spinand_read_status(struct spi_device *spi_nand, uint8_t *status)
+static int spinand_read_status(struct spi_device *spi_nand, u8 *status)
{
struct spinand_cmd cmd = {0};
int ret;
@@ -186,6 +186,7 @@ static int wait_till_ready(struct spi_device *spi_nand)
return -1;
}
+
/**
* spinand_get_otp- send command 0xf to read the SPI Nand OTP register
* Description:
@@ -321,7 +322,7 @@ static int spinand_read_page_to_cache(struct spi_device *spi_nand, u16 page_id)
* No tRd delay.
*/
static int spinand_read_from_cache(struct spi_device *spi_nand, u16 page_id,
- u16 byte_id, u16 len, u8 *rbuf)
+ u16 byte_id, u16 len, u8 *rbuf)
{
struct spinand_cmd cmd = {0};
u16 column;
@@ -352,7 +353,7 @@ static int spinand_read_from_cache(struct spi_device *spi_nand, u16 page_id,
* Poll to read status to wait for tRD time.
*/
static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
- u16 offset, u16 len, u8 *rbuf)
+ u16 offset, u16 len, u8 *rbuf)
{
int ret;
u8 status = 0;
@@ -374,14 +375,14 @@ static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
ret = spinand_read_status(spi_nand, &status);
if (ret < 0) {
dev_err(&spi_nand->dev,
- "err %d read status register\n", ret);
+ "err %d read status register\n", ret);
return ret;
}
if ((status & STATUS_OIP_MASK) == STATUS_READY) {
if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {
dev_err(&spi_nand->dev, "ecc error, page=%d\n",
- page_id);
+ page_id);
return 0;
}
break;
@@ -419,7 +420,8 @@ static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
* Since it is writing the data to cache, there is no tPROG time.
*/
static int spinand_program_data_to_cache(struct spi_device *spi_nand,
- u16 page_id, u16 byte_id, u16 len, u8 *wbuf)
+ u16 page_id, u16 byte_id,
+ u16 len, u8 *wbuf)
{
struct spinand_cmd cmd = {0};
u16 column;
@@ -473,11 +475,11 @@ static int spinand_program_execute(struct spi_device *spi_nand, u16 page_id)
* Poll to wait for the tPROG time to finish the transaction.
*/
static int spinand_program_page(struct spi_device *spi_nand,
- u16 page_id, u16 offset, u16 len, u8 *buf)
+ u16 page_id, u16 offset, u16 len, u8 *buf)
{
int retval;
u8 status = 0;
- uint8_t *wbuf;
+ u8 *wbuf;
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
unsigned int i, j;
@@ -507,7 +509,7 @@ static int spinand_program_page(struct spi_device *spi_nand,
dev_err(&spi_nand->dev, "wait timedout!!!\n");
retval = spinand_program_data_to_cache(spi_nand, page_id,
- offset, len, wbuf);
+ offset, len, wbuf);
if (retval < 0)
return retval;
retval = spinand_program_execute(spi_nand, page_id);
@@ -517,8 +519,7 @@ static int spinand_program_page(struct spi_device *spi_nand,
retval = spinand_read_status(spi_nand, &status);
if (retval < 0) {
dev_err(&spi_nand->dev,
- "error %d reading status register\n",
- retval);
+ "error %d reading status register\n", retval);
return retval;
}
@@ -593,8 +594,7 @@ static int spinand_erase_block(struct spi_device *spi_nand, u16 block_id)
retval = spinand_read_status(spi_nand, &status);
if (retval < 0) {
dev_err(&spi_nand->dev,
- "error %d reading status register\n",
- (int)retval);
+ "error %d reading status register\n", retval);
return retval;
}
@@ -612,9 +612,11 @@ static int spinand_erase_block(struct spi_device *spi_nand, u16 block_id)
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
static int spinand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip,
+ const u8 *buf, int oob_required,
+ int page)
{
- const uint8_t *p = buf;
+ const u8 *p = buf;
int eccsize = chip->ecc.size;
int eccsteps = chip->ecc.steps;
@@ -624,11 +626,11 @@ static int spinand_write_page_hwecc(struct mtd_info *mtd,
}
static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
+ u8 *buf, int oob_required, int page)
{
int retval;
u8 status;
- uint8_t *p = buf;
+ u8 *p = buf;
int eccsize = chip->ecc.size;
int eccsteps = chip->ecc.steps;
struct spinand_info *info = (struct spinand_info *)chip->priv;
@@ -643,8 +645,7 @@ static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
retval = spinand_read_status(info->spi, &status);
if (retval < 0) {
dev_err(&mtd->dev,
- "error %d reading status register\n",
- retval);
+ "error %d reading status register\n", retval);
return retval;
}
@@ -659,7 +660,6 @@ static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
}
}
return 0;
-
}
#endif
@@ -667,7 +667,7 @@ static void spinand_select_chip(struct mtd_info *mtd, int dev)
{
}
-static uint8_t spinand_read_byte(struct mtd_info *mtd)
+static u8 spinand_read_byte(struct mtd_info *mtd)
{
struct spinand_state *state = mtd_to_state(mtd);
u8 data;
@@ -677,7 +677,6 @@ static uint8_t spinand_read_byte(struct mtd_info *mtd)
return data;
}
-
static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct spinand_info *info = (struct spinand_info *)chip->priv;
@@ -695,8 +694,7 @@ static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip)
retval = spinand_read_status(info->spi, &status);
if (retval < 0) {
dev_err(&mtd->dev,
- "error %d reading status register\n",
- retval);
+ "error %d reading status register\n", retval);
return retval;
}
@@ -708,16 +706,15 @@ static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip)
return 0;
}
-static void spinand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+static void spinand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
-
struct spinand_state *state = mtd_to_state(mtd);
memcpy(state->buf + state->buf_ptr, buf, len);
state->buf_ptr += len;
}
-static void spinand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+static void spinand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
struct spinand_state *state = mtd_to_state(mtd);
@@ -738,14 +735,14 @@ static void spinand_reset(struct spi_device *spi_nand)
pr_info("spinand reset failed!\n");
/* elapse 1ms before issuing any other command */
- udelay(1000);
+ usleep_range(1000, 2000);
if (wait_till_ready(spi_nand))
dev_err(&spi_nand->dev, "wait timedout!\n");
}
static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
- int column, int page)
+ int column, int page)
{
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
struct spinand_info *info = (struct spinand_info *)chip->priv;
@@ -791,7 +788,7 @@ static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
case NAND_CMD_PAGEPROG:
spinand_program_page(info->spi, state->row, state->col,
- state->buf_ptr, state->buf);
+ state->buf_ptr, state->buf);
break;
case NAND_CMD_STATUS:
spinand_get_otp(info->spi, state->buf);
@@ -804,7 +801,7 @@ static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (wait_till_ready(info->spi))
dev_err(&info->spi->dev, "WAIT timedout!!!\n");
/* a minimum of 250us must elapse before issuing RESET cmd*/
- udelay(250);
+ usleep_range(250, 1000);
spinand_reset(info->spi);
break;
default:
@@ -839,6 +836,7 @@ static int spinand_lock_block(struct spi_device *spi_nand, u8 lock)
return ret;
}
+
/*
* spinand_probe - [spinand Interface]
* @spi_nand: registered device driver.
@@ -855,7 +853,7 @@ static int spinand_probe(struct spi_device *spi_nand)
struct mtd_part_parser_data ppdata;
info = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_info),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!info)
return -ENOMEM;
@@ -864,7 +862,7 @@ static int spinand_probe(struct spi_device *spi_nand)
spinand_lock_block(spi_nand, BL_ALL_UNLOCKED);
state = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_state),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!state)
return -ENOMEM;
@@ -875,7 +873,7 @@ static int spinand_probe(struct spi_device *spi_nand)
return -ENOMEM;
chip = devm_kzalloc(&spi_nand->dev, sizeof(struct nand_chip),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!chip)
return -ENOMEM;
@@ -912,8 +910,7 @@ static int spinand_probe(struct spi_device *spi_nand)
dev_set_drvdata(&spi_nand->dev, mtd);
mtd->priv = chip;
- mtd->name = dev_name(&spi_nand->dev);
- mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &spi_nand->dev;
mtd->oobsize = 64;
if (nand_scan(mtd, 1))
@@ -949,7 +946,6 @@ MODULE_DEVICE_TABLE(of, spinand_dt);
static struct spi_driver spinand_driver = {
.driver = {
.name = "mt29f",
- .owner = THIS_MODULE,
.of_match_table = spinand_dt,
},
.probe = spinand_probe,
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.h b/drivers/staging/mt29f_spinand/mt29f_spinand.h
index 6c8e413b5b63..ae62975cf44a 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.h
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.h
@@ -44,19 +44,19 @@
/* status */
#define STATUS_OIP_MASK 0x01
-#define STATUS_READY (0 << 0)
-#define STATUS_BUSY (1 << 0)
+#define STATUS_READY 0
+#define STATUS_BUSY BIT(0)
#define STATUS_E_FAIL_MASK 0x04
-#define STATUS_E_FAIL (1 << 2)
+#define STATUS_E_FAIL BIT(2)
#define STATUS_P_FAIL_MASK 0x08
-#define STATUS_P_FAIL (1 << 3)
+#define STATUS_P_FAIL BIT(3)
#define STATUS_ECC_MASK 0x30
-#define STATUS_ECC_1BIT_CORRECTED (1 << 4)
-#define STATUS_ECC_ERROR (2 << 4)
-#define STATUS_ECC_RESERVED (3 << 4)
+#define STATUS_ECC_1BIT_CORRECTED BIT(4)
+#define STATUS_ECC_ERROR BIT(5)
+#define STATUS_ECC_RESERVED (BIT(5) | BIT(4))
/*ECC enable defines*/
#define OTP_ECC_MASK 0x10
@@ -84,8 +84,8 @@ struct spinand_info {
};
struct spinand_state {
- uint32_t col;
- uint32_t row;
+ u32 col;
+ u32 row;
int buf_ptr;
u8 *buf;
};
diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c
index e914147d7379..7806c2bc3af3 100644
--- a/drivers/staging/netlogic/platform_net.c
+++ b/drivers/staging/netlogic/platform_net.c
@@ -58,7 +58,6 @@
#define MAX_NUM_XLS_GMAC 8
#define MAX_NUM_XLR_GMAC 4
-
static u32 xlr_gmac_offsets[] = {
NETLOGIC_IO_GMAC_0_OFFSET, NETLOGIC_IO_GMAC_1_OFFSET,
NETLOGIC_IO_GMAC_2_OFFSET, NETLOGIC_IO_GMAC_3_OFFSET,
diff --git a/drivers/staging/nvec/README b/drivers/staging/nvec/README
index 9a320b7fdbe6..0e2d5c4c875f 100644
--- a/drivers/staging/nvec/README
+++ b/drivers/staging/nvec/README
@@ -1,4 +1,4 @@
-NVEC: An NVidia compliant Embedded Controller Protocol Implemenation
+NVEC: An NVidia compliant Embedded Controller Protocol Implementation
This is an implementation of the NVEC protocol used to communicate with an
embedded controller (EC) via I2C bus. The EC is an I2C master while the host
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 164634d61ac5..4ae44a5168f9 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -40,18 +40,18 @@
#include "nvec.h"
#define I2C_CNFG 0x00
-#define I2C_CNFG_PACKET_MODE_EN (1<<10)
-#define I2C_CNFG_NEW_MASTER_SFM (1<<11)
+#define I2C_CNFG_PACKET_MODE_EN (1 << 10)
+#define I2C_CNFG_NEW_MASTER_SFM (1 << 11)
#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12
#define I2C_SL_CNFG 0x20
-#define I2C_SL_NEWSL (1<<2)
-#define I2C_SL_NACK (1<<1)
-#define I2C_SL_RESP (1<<0)
-#define I2C_SL_IRQ (1<<3)
-#define END_TRANS (1<<4)
-#define RCVD (1<<2)
-#define RNW (1<<1)
+#define I2C_SL_NEWSL (1 << 2)
+#define I2C_SL_NACK (1 << 1)
+#define I2C_SL_RESP (1 << 0)
+#define I2C_SL_IRQ (1 << 3)
+#define END_TRANS (1 << 4)
+#define RCVD (1 << 2)
+#define RNW (1 << 1)
#define I2C_SL_RCVD 0x24
#define I2C_SL_STATUS 0x28
@@ -710,7 +710,6 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
status & RCVD ? " RCVD" : "",
status & RNW ? " RNW" : "");
-
/*
* TODO: A correct fix needs to be found for this.
*
@@ -741,7 +740,7 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec)
writel(I2C_SL_NEWSL, nvec->base + I2C_SL_CNFG);
writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT);
- writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1);
+ writel(nvec->i2c_addr >> 1, nvec->base + I2C_SL_ADDR1);
writel(0, nvec->base + I2C_SL_ADDR2);
enable_irq(nvec->irq);
diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
index 61940284311c..6f2871784ba5 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -3216,9 +3216,9 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
* Allocate a structure to use for our private list of
* isochronous packets.
*/
- iso_packet = kmalloc(urb->number_of_packets *
- sizeof(struct cvmx_usb_iso_packet),
- GFP_ATOMIC);
+ iso_packet = kmalloc_array(urb->number_of_packets,
+ sizeof(struct cvmx_usb_iso_packet),
+ GFP_ATOMIC);
if (iso_packet) {
int i;
/* Fill the list with the data from the URB */
diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h
index 716400588af0..07bd2b87f6a0 100644
--- a/drivers/staging/octeon/ethernet-defines.h
+++ b/drivers/staging/octeon/ethernet-defines.h
@@ -40,7 +40,6 @@
#define FAU_TOTAL_TX_TO_CLEAN (CVMX_FAU_REG_END - sizeof(u32))
#define FAU_NUM_PACKET_BUFFERS_TO_FREE (FAU_TOTAL_TX_TO_CLEAN - sizeof(u32))
-#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS+1)
-
+#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS + 1)
#endif /* __ETHERNET_DEFINES_H__ */
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 3a5d8f53831c..c053c4a47a7e 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -549,7 +549,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
/* Get a work queue entry */
cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
- if (unlikely(work == NULL)) {
+ if (unlikely(!work)) {
printk_ratelimited("%s: Failed to allocate a work queue entry\n",
dev->name);
priv->stats.tx_dropped++;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index d78fd7b5c74c..f69fb5cc7cb8 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -678,7 +678,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
}
cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
- if (cvm_oct_poll_queue == NULL) {
+ if (!cvm_oct_poll_queue) {
pr_err("octeon-ethernet: Cannot create workqueue");
return -ENOMEM;
}
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index b47da2b44689..79ac19246548 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -71,7 +71,7 @@
#define KEYPAD_BUFFER 64
/* poll the keyboard this every second */
-#define INPUT_POLL_TIME (HZ/50)
+#define INPUT_POLL_TIME (HZ / 50)
/* a key starts to repeat after this times INPUT_POLL_TIME */
#define KEYPAD_REP_START (10)
/* a key repeats this times INPUT_POLL_TIME */
@@ -576,7 +576,6 @@ static int keypad_enabled = NOT_SET;
module_param(keypad_enabled, int, 0000);
MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
-
static const unsigned char *lcd_char_conv;
/* for some LCD drivers (ks0074) we need a charset conversion table. */
@@ -826,7 +825,8 @@ static void lcd_write_cmd_s(int cmd)
lcd_send_serial(0x1F); /* R/W=W, RS=0 */
lcd_send_serial(cmd & 0x0F);
lcd_send_serial((cmd >> 4) & 0x0F);
- udelay(40); /* the shortest command takes at least 40 us */
+ /* the shortest command takes at least 40 us */
+ usleep_range(40, 100);
spin_unlock_irq(&pprt_lock);
}
@@ -837,7 +837,8 @@ static void lcd_write_data_s(int data)
lcd_send_serial(0x5F); /* R/W=W, RS=1 */
lcd_send_serial(data & 0x0F);
lcd_send_serial((data >> 4) & 0x0F);
- udelay(40); /* the shortest data takes at least 40 us */
+ /* the shortest data takes at least 40 us */
+ usleep_range(40, 100);
spin_unlock_irq(&pprt_lock);
}
@@ -847,19 +848,20 @@ static void lcd_write_cmd_p8(int cmd)
spin_lock_irq(&pprt_lock);
/* present the data to the data port */
w_dtr(pprt, cmd);
- udelay(20); /* maintain the data during 20 us before the strobe */
+ /* maintain the data during 20 us before the strobe */
+ usleep_range(20, 100);
bits.e = BIT_SET;
bits.rs = BIT_CLR;
bits.rw = BIT_CLR;
set_ctrl_bits();
- udelay(40); /* maintain the strobe during 40 us */
+ usleep_range(40, 100); /* maintain the strobe during 40 us */
bits.e = BIT_CLR;
set_ctrl_bits();
- udelay(120); /* the shortest command takes at least 120 us */
+ usleep_range(120, 500); /* the shortest command takes at least 120 us */
spin_unlock_irq(&pprt_lock);
}
@@ -869,19 +871,20 @@ static void lcd_write_data_p8(int data)
spin_lock_irq(&pprt_lock);
/* present the data to the data port */
w_dtr(pprt, data);
- udelay(20); /* maintain the data during 20 us before the strobe */
+ /* maintain the data during 20 us before the strobe */
+ usleep_range(20, 100);
bits.e = BIT_SET;
bits.rs = BIT_SET;
bits.rw = BIT_CLR;
set_ctrl_bits();
- udelay(40); /* maintain the strobe during 40 us */
+ usleep_range(40, 100); /* maintain the strobe during 40 us */
bits.e = BIT_CLR;
set_ctrl_bits();
- udelay(45); /* the shortest data takes at least 45 us */
+ usleep_range(45, 100); /* the shortest data takes at least 45 us */
spin_unlock_irq(&pprt_lock);
}
@@ -891,7 +894,7 @@ static void lcd_write_cmd_tilcd(int cmd)
spin_lock_irq(&pprt_lock);
/* present the data to the control port */
w_ctr(pprt, cmd);
- udelay(60);
+ usleep_range(60, 120);
spin_unlock_irq(&pprt_lock);
}
@@ -901,7 +904,7 @@ static void lcd_write_data_tilcd(int data)
spin_lock_irq(&pprt_lock);
/* present the data to the data port */
w_dtr(pprt, data);
- udelay(60);
+ usleep_range(60, 120);
spin_unlock_irq(&pprt_lock);
}
@@ -944,7 +947,7 @@ static void lcd_clear_fast_s(void)
lcd_send_serial(0x5F); /* R/W=W, RS=1 */
lcd_send_serial(' ' & 0x0F);
lcd_send_serial((' ' >> 4) & 0x0F);
- udelay(40); /* the shortest data takes at least 40 us */
+ usleep_range(40, 100); /* the shortest data takes at least 40 us */
}
spin_unlock_irq(&pprt_lock);
@@ -968,7 +971,7 @@ static void lcd_clear_fast_p8(void)
w_dtr(pprt, ' ');
/* maintain the data during 20 us before the strobe */
- udelay(20);
+ usleep_range(20, 100);
bits.e = BIT_SET;
bits.rs = BIT_SET;
@@ -976,13 +979,13 @@ static void lcd_clear_fast_p8(void)
set_ctrl_bits();
/* maintain the strobe during 40 us */
- udelay(40);
+ usleep_range(40, 100);
bits.e = BIT_CLR;
set_ctrl_bits();
/* the shortest data takes at least 45 us */
- udelay(45);
+ usleep_range(45, 100);
}
spin_unlock_irq(&pprt_lock);
@@ -1004,7 +1007,7 @@ static void lcd_clear_fast_tilcd(void)
for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) {
/* present the data to the data port */
w_dtr(pprt, ' ');
- udelay(60);
+ usleep_range(60, 120);
}
spin_unlock_irq(&pprt_lock);
@@ -1119,8 +1122,8 @@ static inline int handle_lcd_special_code(void)
case '*':
/* flash back light using the keypad timer */
if (scan_timer.function) {
- if (lcd.light_tempo == 0
- && ((lcd.flags & LCD_FLAG_L) == 0))
+ if (lcd.light_tempo == 0 &&
+ ((lcd.flags & LCD_FLAG_L) == 0))
lcd_backlight(1);
lcd.light_tempo = FLASH_LIGHT_TEMPO;
}
@@ -2008,14 +2011,14 @@ static void panel_scan_timer(void)
if (lcd.enabled && lcd.initialized) {
if (keypressed) {
- if (lcd.light_tempo == 0
- && ((lcd.flags & LCD_FLAG_L) == 0))
+ if (lcd.light_tempo == 0 &&
+ ((lcd.flags & LCD_FLAG_L) == 0))
lcd_backlight(1);
lcd.light_tempo = FLASH_LIGHT_TEMPO;
} else if (lcd.light_tempo > 0) {
lcd.light_tempo--;
- if (lcd.light_tempo == 0
- && ((lcd.flags & LCD_FLAG_L) == 0))
+ if (lcd.light_tempo == 0 &&
+ ((lcd.flags & LCD_FLAG_L) == 0))
lcd_backlight(0);
}
}
diff --git a/drivers/staging/rdma/amso1100/c2.c b/drivers/staging/rdma/amso1100/c2.c
index 35ac536b2d45..b46ebd1ae15a 100644
--- a/drivers/staging/rdma/amso1100/c2.c
+++ b/drivers/staging/rdma/amso1100/c2.c
@@ -87,11 +87,6 @@ static struct pci_device_id c2_pci_table[] = {
MODULE_DEVICE_TABLE(pci, c2_pci_table);
-static void c2_print_macaddr(struct net_device *netdev)
-{
- pr_debug("%s: MAC %pM, IRQ %u\n", netdev->name, netdev->dev_addr, netdev->irq);
-}
-
static void c2_set_rxbufsize(struct c2_port *c2_port)
{
struct net_device *netdev = c2_port->netdev;
@@ -116,7 +111,8 @@ static int c2_tx_ring_alloc(struct c2_ring *tx_ring, void *vaddr,
struct c2_element *elem;
int i;
- tx_ring->start = kmalloc(sizeof(*elem) * tx_ring->count, GFP_KERNEL);
+ tx_ring->start = kmalloc_array(tx_ring->count, sizeof(*elem),
+ GFP_KERNEL);
if (!tx_ring->start)
return -ENOMEM;
@@ -165,7 +161,8 @@ static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr,
struct c2_element *elem;
int i;
- rx_ring->start = kmalloc(sizeof(*elem) * rx_ring->count, GFP_KERNEL);
+ rx_ring->start = kmalloc_array(rx_ring->count, sizeof(*elem),
+ GFP_KERNEL);
if (!rx_ring->start)
return -ENOMEM;
@@ -908,7 +905,8 @@ static struct net_device *c2_devinit(struct c2_dev *c2dev,
/* Validate the MAC address */
if (!is_valid_ether_addr(netdev->dev_addr)) {
pr_debug("Invalid MAC Address\n");
- c2_print_macaddr(netdev);
+ pr_debug("%s: MAC %pM, IRQ %u\n", netdev->name,
+ netdev->dev_addr, netdev->irq);
free_netdev(netdev);
return NULL;
}
@@ -1142,7 +1140,8 @@ static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
}
/* Print out the MAC address */
- c2_print_macaddr(netdev);
+ pr_debug("%s: MAC %pM, IRQ %u\n", netdev->name, netdev->dev_addr,
+ netdev->irq);
ret = c2_rnic_init(c2dev);
if (ret) {
diff --git a/drivers/staging/rdma/amso1100/c2.h b/drivers/staging/rdma/amso1100/c2.h
index d619d735838b..21b565a91fd6 100644
--- a/drivers/staging/rdma/amso1100/c2.h
+++ b/drivers/staging/rdma/amso1100/c2.h
@@ -476,72 +476,72 @@ static inline int c2_errno(void *reply)
}
/* Device */
-extern int c2_register_device(struct c2_dev *c2dev);
-extern void c2_unregister_device(struct c2_dev *c2dev);
-extern int c2_rnic_init(struct c2_dev *c2dev);
-extern void c2_rnic_term(struct c2_dev *c2dev);
-extern void c2_rnic_interrupt(struct c2_dev *c2dev);
-extern int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
-extern int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
+int c2_register_device(struct c2_dev *c2dev);
+void c2_unregister_device(struct c2_dev *c2dev);
+int c2_rnic_init(struct c2_dev *c2dev);
+void c2_rnic_term(struct c2_dev *c2dev);
+void c2_rnic_interrupt(struct c2_dev *c2dev);
+int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
+int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
/* QPs */
-extern int c2_alloc_qp(struct c2_dev *c2dev, struct c2_pd *pd,
+int c2_alloc_qp(struct c2_dev *c2dev, struct c2_pd *pd,
struct ib_qp_init_attr *qp_attrs, struct c2_qp *qp);
-extern void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp);
-extern struct ib_qp *c2_get_qp(struct ib_device *device, int qpn);
-extern int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp);
+struct ib_qp *c2_get_qp(struct ib_device *device, int qpn);
+int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
struct ib_qp_attr *attr, int attr_mask);
-extern int c2_qp_set_read_limits(struct c2_dev *c2dev, struct c2_qp *qp,
+int c2_qp_set_read_limits(struct c2_dev *c2dev, struct c2_qp *qp,
int ord, int ird);
-extern int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
+int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
struct ib_send_wr **bad_wr);
-extern int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
+int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
struct ib_recv_wr **bad_wr);
-extern void c2_init_qp_table(struct c2_dev *c2dev);
-extern void c2_cleanup_qp_table(struct c2_dev *c2dev);
-extern void c2_set_qp_state(struct c2_qp *, int);
-extern struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn);
+void c2_init_qp_table(struct c2_dev *c2dev);
+void c2_cleanup_qp_table(struct c2_dev *c2dev);
+void c2_set_qp_state(struct c2_qp *, int);
+struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn);
/* PDs */
-extern int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd);
-extern void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd);
-extern int c2_init_pd_table(struct c2_dev *c2dev);
-extern void c2_cleanup_pd_table(struct c2_dev *c2dev);
+int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd);
+void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd);
+int c2_init_pd_table(struct c2_dev *c2dev);
+void c2_cleanup_pd_table(struct c2_dev *c2dev);
/* CQs */
-extern int c2_init_cq(struct c2_dev *c2dev, int entries,
+int c2_init_cq(struct c2_dev *c2dev, int entries,
struct c2_ucontext *ctx, struct c2_cq *cq);
-extern void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq);
-extern void c2_cq_event(struct c2_dev *c2dev, u32 mq_index);
-extern void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index);
-extern int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
-extern int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
+void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq);
+void c2_cq_event(struct c2_dev *c2dev, u32 mq_index);
+void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index);
+int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
+int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
/* CM */
-extern int c2_llp_connect(struct iw_cm_id *cm_id,
+int c2_llp_connect(struct iw_cm_id *cm_id,
struct iw_cm_conn_param *iw_param);
-extern int c2_llp_accept(struct iw_cm_id *cm_id,
+int c2_llp_accept(struct iw_cm_id *cm_id,
struct iw_cm_conn_param *iw_param);
-extern int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata,
+int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata,
u8 pdata_len);
-extern int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog);
-extern int c2_llp_service_destroy(struct iw_cm_id *cm_id);
+int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog);
+int c2_llp_service_destroy(struct iw_cm_id *cm_id);
/* MM */
-extern int c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list,
+int c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list,
int page_size, int pbl_depth, u32 length,
u32 off, u64 *va, enum c2_acf acf,
struct c2_mr *mr);
-extern int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index);
+int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index);
/* AE */
-extern void c2_ae_event(struct c2_dev *c2dev, u32 mq_index);
+void c2_ae_event(struct c2_dev *c2dev, u32 mq_index);
/* MQSP Allocator */
-extern int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask,
+int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask,
struct sp_chunk **root);
-extern void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root);
-extern __be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root);
+__be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
dma_addr_t *dma_addr, gfp_t gfp_mask);
-extern void c2_free_mqsp(__be16* mqsp);
+void c2_free_mqsp(__be16* mqsp);
#endif
diff --git a/drivers/staging/rdma/amso1100/c2_cm.c b/drivers/staging/rdma/amso1100/c2_cm.c
index 23bfa94fbd4e..f8dbdb9e0f66 100644
--- a/drivers/staging/rdma/amso1100/c2_cm.c
+++ b/drivers/staging/rdma/amso1100/c2_cm.c
@@ -278,10 +278,7 @@ int c2_llp_service_destroy(struct iw_cm_id *cm_id)
err = -ENOMEM;
goto bail0;
}
- if ((err = c2_errno(reply)) != 0)
- goto bail1;
- bail1:
vq_repbuf_free(c2dev, reply);
bail0:
vq_req_free(c2dev, vq_req);
diff --git a/drivers/staging/rdma/amso1100/c2_mq.h b/drivers/staging/rdma/amso1100/c2_mq.h
index fc1b9a7cec4b..8e1b4d13409e 100644
--- a/drivers/staging/rdma/amso1100/c2_mq.h
+++ b/drivers/staging/rdma/amso1100/c2_mq.h
@@ -93,14 +93,14 @@ static __inline__ int c2_mq_full(struct c2_mq *q)
return q->priv == (be16_to_cpu(*q->shared) + q->q_size - 1) % q->q_size;
}
-extern void c2_mq_lconsume(struct c2_mq *q, u32 wqe_count);
-extern void *c2_mq_alloc(struct c2_mq *q);
-extern void c2_mq_produce(struct c2_mq *q);
-extern void *c2_mq_consume(struct c2_mq *q);
-extern void c2_mq_free(struct c2_mq *q);
-extern void c2_mq_req_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size,
+void c2_mq_lconsume(struct c2_mq *q, u32 wqe_count);
+void *c2_mq_alloc(struct c2_mq *q);
+void c2_mq_produce(struct c2_mq *q);
+void *c2_mq_consume(struct c2_mq *q);
+void c2_mq_free(struct c2_mq *q);
+void c2_mq_req_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size,
u8 __iomem *pool_start, u16 __iomem *peer, u32 type);
-extern void c2_mq_rep_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size,
+void c2_mq_rep_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size,
u8 *pool_start, u16 __iomem *peer, u32 type);
#endif /* _C2_MQ_H_ */
diff --git a/drivers/staging/rdma/amso1100/c2_provider.c b/drivers/staging/rdma/amso1100/c2_provider.c
index 25632158a52a..a092ac743c72 100644
--- a/drivers/staging/rdma/amso1100/c2_provider.c
+++ b/drivers/staging/rdma/amso1100/c2_provider.c
@@ -462,7 +462,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
shift = ffs(c2mr->umem->page_size) - 1;
n = c2mr->umem->nmap;
- pages = kmalloc(n * sizeof(u64), GFP_KERNEL);
+ pages = kmalloc_array(n, sizeof(u64), GFP_KERNEL);
if (!pages) {
err = -ENOMEM;
goto err;
@@ -620,12 +620,9 @@ static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
static int c2_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{
- int err;
-
pr_debug("%s:%u\n", __func__, __LINE__);
- err = c2_llp_reject(cm_id, pdata, pdata_len);
- return err;
+ return c2_llp_reject(cm_id, pdata, pdata_len);
}
static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
@@ -642,12 +639,9 @@ static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
static int c2_service_destroy(struct iw_cm_id *cm_id)
{
- int err;
pr_debug("%s:%u\n", __func__, __LINE__);
- err = c2_llp_service_destroy(cm_id);
-
- return err;
+ return c2_llp_service_destroy(cm_id);
}
static int c2_pseudo_up(struct net_device *netdev)
diff --git a/drivers/staging/rdma/amso1100/c2_qp.c b/drivers/staging/rdma/amso1100/c2_qp.c
index e0a7aff0eb2a..ca364dbe369c 100644
--- a/drivers/staging/rdma/amso1100/c2_qp.c
+++ b/drivers/staging/rdma/amso1100/c2_qp.c
@@ -860,9 +860,9 @@ int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
flags |= SQ_READ_FENCE;
}
wr.sqwr.rdma_write.remote_stag =
- cpu_to_be32(ib_wr->wr.rdma.rkey);
+ cpu_to_be32(rdma_wr(ib_wr)->rkey);
wr.sqwr.rdma_write.remote_to =
- cpu_to_be64(ib_wr->wr.rdma.remote_addr);
+ cpu_to_be64(rdma_wr(ib_wr)->remote_addr);
err = move_sgl((struct c2_data_addr *)
& (wr.sqwr.rdma_write.data),
ib_wr->sg_list,
@@ -889,9 +889,9 @@ int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
wr.sqwr.rdma_read.local_to =
cpu_to_be64(ib_wr->sg_list->addr);
wr.sqwr.rdma_read.remote_stag =
- cpu_to_be32(ib_wr->wr.rdma.rkey);
+ cpu_to_be32(rdma_wr(ib_wr)->rkey);
wr.sqwr.rdma_read.remote_to =
- cpu_to_be64(ib_wr->wr.rdma.remote_addr);
+ cpu_to_be64(rdma_wr(ib_wr)->remote_addr);
wr.sqwr.rdma_read.length =
cpu_to_be32(ib_wr->sg_list->length);
break;
diff --git a/drivers/staging/rdma/amso1100/c2_rnic.c b/drivers/staging/rdma/amso1100/c2_rnic.c
index d3c0f77767d9..5e65c6d07ca4 100644
--- a/drivers/staging/rdma/amso1100/c2_rnic.c
+++ b/drivers/staging/rdma/amso1100/c2_rnic.c
@@ -81,7 +81,6 @@
static int c2_adapter_init(struct c2_dev *c2dev)
{
struct c2wr_init_req wr;
- int err;
memset(&wr, 0, sizeof(wr));
c2_wr_set_id(&wr, CCWR_INIT);
@@ -94,9 +93,7 @@ static int c2_adapter_init(struct c2_dev *c2dev)
wr.q2_host_msg_pool = cpu_to_be64(c2dev->aeq.host_dma);
/* Post the init message */
- err = vq_send_wr(c2dev, (union c2wr *) & wr);
-
- return err;
+ return vq_send_wr(c2dev, (union c2wr *) & wr);
}
/*
diff --git a/drivers/staging/rdma/amso1100/c2_vq.h b/drivers/staging/rdma/amso1100/c2_vq.h
index 33805627a607..c1f6cef60213 100644
--- a/drivers/staging/rdma/amso1100/c2_vq.h
+++ b/drivers/staging/rdma/amso1100/c2_vq.h
@@ -47,17 +47,17 @@ struct c2_vq_req {
struct c2_qp *qp;
};
-extern int vq_init(struct c2_dev *c2dev);
-extern void vq_term(struct c2_dev *c2dev);
+int vq_init(struct c2_dev *c2dev);
+void vq_term(struct c2_dev *c2dev);
-extern struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev);
-extern void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *req);
-extern void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *req);
-extern void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *req);
-extern int vq_send_wr(struct c2_dev *c2dev, union c2wr * wr);
+struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev);
+void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *req);
+void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *req);
+void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *req);
+int vq_send_wr(struct c2_dev *c2dev, union c2wr * wr);
-extern void *vq_repbuf_alloc(struct c2_dev *c2dev);
-extern void vq_repbuf_free(struct c2_dev *c2dev, void *reply);
+void *vq_repbuf_alloc(struct c2_dev *c2dev);
+void vq_repbuf_free(struct c2_dev *c2dev, void *reply);
-extern int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req);
+int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req);
#endif /* _C2_VQ_H_ */
diff --git a/drivers/staging/rdma/ehca/ehca_av.c b/drivers/staging/rdma/ehca/ehca_av.c
index 465926319f3d..fd7b6d044ec1 100644
--- a/drivers/staging/rdma/ehca/ehca_av.c
+++ b/drivers/staging/rdma/ehca/ehca_av.c
@@ -105,6 +105,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
if (ehca_static_rate < 0) {
u32 ipd;
+
if (ehca_calc_ipd(shca, ah_attr->port_num,
ah_attr->static_rate, &ipd)) {
ret = -EINVAL;
@@ -128,6 +129,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
int rc;
struct ib_port_attr port_attr;
union ib_gid gid;
+
memset(&port_attr, 0, sizeof(port_attr));
rc = ehca_query_port(pd->device, ah_attr->port_num,
&port_attr);
@@ -192,6 +194,7 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
int rc;
struct ib_port_attr port_attr;
union ib_gid gid;
+
memset(&port_attr, 0, sizeof(port_attr));
rc = ehca_query_port(ah->device, ah_attr->port_num,
&port_attr);
diff --git a/drivers/staging/rdma/ehca/ehca_reqs.c b/drivers/staging/rdma/ehca/ehca_reqs.c
index 47f94984353d..10e2074384f5 100644
--- a/drivers/staging/rdma/ehca/ehca_reqs.c
+++ b/drivers/staging/rdma/ehca/ehca_reqs.c
@@ -110,19 +110,19 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
/* need ib_mad struct */
#include <rdma/ib_mad.h>
-static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
+static void trace_ud_wr(const struct ib_ud_wr *ud_wr)
{
int idx;
int j;
- while (send_wr) {
- struct ib_mad_hdr *mad_hdr = send_wr->wr.ud.mad_hdr;
- struct ib_sge *sge = send_wr->sg_list;
- ehca_gen_dbg("send_wr#%x wr_id=%lx num_sge=%x "
- "send_flags=%x opcode=%x", idx, send_wr->wr_id,
- send_wr->num_sge, send_wr->send_flags,
- send_wr->opcode);
+ while (ud_wr) {
+ struct ib_mad_hdr *mad_hdr = ud_wrmad_hdr;
+ struct ib_sge *sge = ud_wr->wr.sg_list;
+ ehca_gen_dbg("ud_wr#%x wr_id=%lx num_sge=%x "
+ "send_flags=%x opcode=%x", idx, ud_wr->wr.wr_id,
+ ud_wr->wr.num_sge, ud_wr->wr.send_flags,
+ ud_wr->.wr.opcode);
if (mad_hdr) {
- ehca_gen_dbg("send_wr#%x mad_hdr base_version=%x "
+ ehca_gen_dbg("ud_wr#%x mad_hdr base_version=%x "
"mgmt_class=%x class_version=%x method=%x "
"status=%x class_specific=%x tid=%lx "
"attr_id=%x resv=%x attr_mod=%x",
@@ -134,33 +134,33 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
mad_hdr->resv,
mad_hdr->attr_mod);
}
- for (j = 0; j < send_wr->num_sge; j++) {
+ for (j = 0; j < ud_wr->wr.num_sge; j++) {
u8 *data = __va(sge->addr);
- ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x "
+ ehca_gen_dbg("ud_wr#%x sge#%x addr=%p length=%x "
"lkey=%x",
idx, j, data, sge->length, sge->lkey);
/* assume length is n*16 */
- ehca_dmp(data, sge->length, "send_wr#%x sge#%x",
+ ehca_dmp(data, sge->length, "ud_wr#%x sge#%x",
idx, j);
sge++;
} /* eof for j */
idx++;
- send_wr = send_wr->next;
- } /* eof while send_wr */
+ ud_wr = ud_wr(ud_wr->wr.next);
+ } /* eof while ud_wr */
}
#endif /* DEBUG_GSI_SEND_WR */
static inline int ehca_write_swqe(struct ehca_qp *qp,
struct ehca_wqe *wqe_p,
- const struct ib_send_wr *send_wr,
+ struct ib_send_wr *send_wr,
u32 sq_map_idx,
int hidden)
{
u32 idx;
u64 dma_length;
struct ehca_av *my_av;
- u32 remote_qkey = send_wr->wr.ud.remote_qkey;
+ u32 remote_qkey;
struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx];
if (unlikely((send_wr->num_sge < 0) ||
@@ -223,20 +223,21 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
/* no break is intential here */
case IB_QPT_UD:
/* IB 1.2 spec C10-15 compliance */
- if (send_wr->wr.ud.remote_qkey & 0x80000000)
+ remote_qkey = ud_wr(send_wr)->remote_qkey;
+ if (remote_qkey & 0x80000000)
remote_qkey = qp->qkey;
- wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8;
+ wqe_p->destination_qp_number = ud_wr(send_wr)->remote_qpn << 8;
wqe_p->local_ee_context_qkey = remote_qkey;
- if (unlikely(!send_wr->wr.ud.ah)) {
- ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
+ if (unlikely(!ud_wr(send_wr)->ah)) {
+ ehca_gen_err("ud_wr(send_wr) is NULL. qp=%p", qp);
return -EINVAL;
}
- if (unlikely(send_wr->wr.ud.remote_qpn == 0)) {
+ if (unlikely(ud_wr(send_wr)->remote_qpn == 0)) {
ehca_gen_err("dest QP# is 0. qp=%x", qp->real_qp_num);
return -EINVAL;
}
- my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah);
+ my_av = container_of(ud_wr(send_wr)->ah, struct ehca_av, ib_ah);
wqe_p->u.ud_av.ud_av = my_av->av;
/*
@@ -255,9 +256,9 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
qp->qp_type == IB_QPT_GSI)
wqe_p->u.ud_av.ud_av.pmtu = 1;
if (qp->qp_type == IB_QPT_GSI) {
- wqe_p->pkeyi = send_wr->wr.ud.pkey_index;
+ wqe_p->pkeyi = ud_wr(send_wr)->pkey_index;
#ifdef DEBUG_GSI_SEND_WR
- trace_send_wr_ud(send_wr);
+ trace_ud_wr(ud_wr(send_wr));
#endif /* DEBUG_GSI_SEND_WR */
}
break;
@@ -269,8 +270,8 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
case IB_QPT_RC:
/* TODO: atomic not implemented */
wqe_p->u.nud.remote_virtual_address =
- send_wr->wr.rdma.remote_addr;
- wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey;
+ rdma_wr(send_wr)->remote_addr;
+ wqe_p->u.nud.rkey = rdma_wr(send_wr)->rkey;
/*
* omitted checking of IB_SEND_INLINE
diff --git a/drivers/staging/rdma/hfi1/chip.c b/drivers/staging/rdma/hfi1/chip.c
index 46ebc381a792..dc6915947c78 100644
--- a/drivers/staging/rdma/hfi1/chip.c
+++ b/drivers/staging/rdma/hfi1/chip.c
@@ -121,8 +121,8 @@ struct flag_table {
#define SEC_SC_HALTED 0x4 /* per-context only */
#define SEC_SPC_FREEZE 0x8 /* per-HFI only */
-#define VL15CTXT 1
#define MIN_KERNEL_KCTXTS 2
+#define FIRST_KERNEL_KCTXT 1
#define NUM_MAP_REGS 32
/* Bit offset into the GUID which carries HFI id information */
@@ -1530,6 +1530,14 @@ static u64 access_sw_kmem_wait(const struct cntr_entry *entry,
return dd->verbs_dev.n_kmem_wait;
}
+static u64 access_sw_send_schedule(const struct cntr_entry *entry,
+ void *context, int vl, int mode, u64 data)
+{
+ struct hfi1_devdata *dd = (struct hfi1_devdata *)context;
+
+ return dd->verbs_dev.n_send_schedule;
+}
+
#define def_access_sw_cpu(cntr) \
static u64 access_sw_cpu_##cntr(const struct cntr_entry *entry, \
void *context, int vl, int mode, u64 data) \
@@ -1720,6 +1728,8 @@ static struct cntr_entry dev_cntrs[DEV_CNTR_LAST] = {
access_sw_pio_wait),
[C_SW_KMEM_WAIT] = CNTR_ELEM("KmemWait", 0, 0, CNTR_NORMAL,
access_sw_kmem_wait),
+[C_SW_SEND_SCHED] = CNTR_ELEM("SendSched", 0, 0, CNTR_NORMAL,
+ access_sw_send_schedule),
};
static struct cntr_entry port_cntrs[PORT_CNTR_LAST] = {
@@ -2215,9 +2225,7 @@ static void update_rcverr_timer(unsigned long opaque)
static int init_rcverr(struct hfi1_devdata *dd)
{
- init_timer(&dd->rcverr_timer);
- dd->rcverr_timer.function = update_rcverr_timer;
- dd->rcverr_timer.data = (unsigned long) dd;
+ setup_timer(&dd->rcverr_timer, update_rcverr_timer, (unsigned long)dd);
/* Assume the hardware counter has been reset */
dd->rcv_ovfl_cnt = 0;
return mod_timer(&dd->rcverr_timer, jiffies + HZ * RCVERR_CHECK_TIME);
@@ -4416,7 +4424,7 @@ static void is_rcv_avail_int(struct hfi1_devdata *dd, unsigned int source)
rcd = dd->rcd[source];
if (rcd) {
if (source < dd->first_user_ctxt)
- rcd->do_interrupt(rcd);
+ rcd->do_interrupt(rcd, 0);
else
handle_user_interrupt(rcd);
return; /* OK */
@@ -4582,23 +4590,106 @@ static irqreturn_t sdma_interrupt(int irq, void *data)
}
/*
- * NOTE: this routine expects to be on its own MSI-X interrupt. If
- * multiple receive contexts share the same MSI-X interrupt, then this
- * routine must check for who received it.
+ * Clear the receive interrupt, forcing the write and making sure
+ * we have data from the chip, pushing everything in front of it
+ * back to the host.
+ */
+static inline void clear_recv_intr(struct hfi1_ctxtdata *rcd)
+{
+ struct hfi1_devdata *dd = rcd->dd;
+ u32 addr = CCE_INT_CLEAR + (8 * rcd->ireg);
+
+ mmiowb(); /* make sure everything before is written */
+ write_csr(dd, addr, rcd->imask);
+ /* force the above write on the chip and get a value back */
+ (void)read_csr(dd, addr);
+}
+
+/* force the receive interrupt */
+static inline void force_recv_intr(struct hfi1_ctxtdata *rcd)
+{
+ write_csr(rcd->dd, CCE_INT_FORCE + (8 * rcd->ireg), rcd->imask);
+}
+
+/* return non-zero if a packet is present */
+static inline int check_packet_present(struct hfi1_ctxtdata *rcd)
+{
+ if (!HFI1_CAP_IS_KSET(DMA_RTAIL))
+ return (rcd->seq_cnt ==
+ rhf_rcv_seq(rhf_to_cpu(get_rhf_addr(rcd))));
+
+ /* else is RDMA rtail */
+ return (rcd->head != get_rcvhdrtail(rcd));
+}
+
+/*
+ * Receive packet IRQ handler. This routine expects to be on its own IRQ.
+ * This routine will try to handle packets immediately (latency), but if
+ * it finds too many, it will invoke the thread handler (bandwitdh). The
+ * chip receive interupt is *not* cleared down until this or the thread (if
+ * invoked) is finished. The intent is to avoid extra interrupts while we
+ * are processing packets anyway.
*/
static irqreturn_t receive_context_interrupt(int irq, void *data)
{
struct hfi1_ctxtdata *rcd = data;
struct hfi1_devdata *dd = rcd->dd;
+ int disposition;
+ int present;
trace_hfi1_receive_interrupt(dd, rcd->ctxt);
this_cpu_inc(*dd->int_counter);
- /* clear the interrupt */
- write_csr(rcd->dd, CCE_INT_CLEAR + (8*rcd->ireg), rcd->imask);
+ /* receive interrupt remains blocked while processing packets */
+ disposition = rcd->do_interrupt(rcd, 0);
+
+ /*
+ * Too many packets were seen while processing packets in this
+ * IRQ handler. Invoke the handler thread. The receive interrupt
+ * remains blocked.
+ */
+ if (disposition == RCV_PKT_LIMIT)
+ return IRQ_WAKE_THREAD;
+
+ /*
+ * The packet processor detected no more packets. Clear the receive
+ * interrupt and recheck for a packet packet that may have arrived
+ * after the previous check and interrupt clear. If a packet arrived,
+ * force another interrupt.
+ */
+ clear_recv_intr(rcd);
+ present = check_packet_present(rcd);
+ if (present)
+ force_recv_intr(rcd);
+
+ return IRQ_HANDLED;
+}
- /* handle the interrupt */
- rcd->do_interrupt(rcd);
+/*
+ * Receive packet thread handler. This expects to be invoked with the
+ * receive interrupt still blocked.
+ */
+static irqreturn_t receive_context_thread(int irq, void *data)
+{
+ struct hfi1_ctxtdata *rcd = data;
+ int present;
+
+ /* receive interrupt is still blocked from the IRQ handler */
+ (void)rcd->do_interrupt(rcd, 1);
+
+ /*
+ * The packet processor will only return if it detected no more
+ * packets. Hold IRQs here so we can safely clear the interrupt and
+ * recheck for a packet that may have arrived after the previous
+ * check and the interrupt clear. If a packet arrived, force another
+ * interrupt.
+ */
+ local_irq_disable();
+ clear_recv_intr(rcd);
+ present = check_packet_present(rcd);
+ if (present)
+ force_recv_intr(rcd);
+ local_irq_enable();
return IRQ_HANDLED;
}
@@ -4683,13 +4774,25 @@ int read_lcb_csr(struct hfi1_devdata *dd, u32 addr, u64 *data)
*/
static int write_lcb_via_8051(struct hfi1_devdata *dd, u32 addr, u64 data)
{
+ u32 regno;
+ int ret;
- if (acquire_lcb_access(dd, 0) == 0) {
- write_csr(dd, addr, data);
- release_lcb_access(dd, 0);
- return 0;
+ if (dd->icode == ICODE_FUNCTIONAL_SIMULATOR ||
+ (dd->dc8051_ver < dc8051_ver(0, 20))) {
+ if (acquire_lcb_access(dd, 0) == 0) {
+ write_csr(dd, addr, data);
+ release_lcb_access(dd, 0);
+ return 0;
+ }
+ return -EBUSY;
}
- return -EBUSY;
+
+ /* register is an index of LCB registers: (offset - base) / 8 */
+ regno = (addr - DC_LCB_CFG_RUN) >> 3;
+ ret = do_8051_command(dd, HCMD_WRITE_LCB_CSR, regno, &data);
+ if (ret != HCMD_SUCCESS)
+ return -EBUSY;
+ return 0;
}
/*
@@ -4771,6 +4874,26 @@ static int do_8051_command(
*/
/*
+ * When writing a LCB CSR, out_data contains the full value to
+ * to be written, while in_data contains the relative LCB
+ * address in 7:0. Do the work here, rather than the caller,
+ * of distrubting the write data to where it needs to go:
+ *
+ * Write data
+ * 39:00 -> in_data[47:8]
+ * 47:40 -> DC8051_CFG_EXT_DEV_0.RETURN_CODE
+ * 63:48 -> DC8051_CFG_EXT_DEV_0.RSP_DATA
+ */
+ if (type == HCMD_WRITE_LCB_CSR) {
+ in_data |= ((*out_data) & 0xffffffffffull) << 8;
+ reg = ((((*out_data) >> 40) & 0xff) <<
+ DC_DC8051_CFG_EXT_DEV_0_RETURN_CODE_SHIFT)
+ | ((((*out_data) >> 48) & 0xffff) <<
+ DC_DC8051_CFG_EXT_DEV_0_RSP_DATA_SHIFT);
+ write_csr(dd, DC_DC8051_CFG_EXT_DEV_0, reg);
+ }
+
+ /*
* Do two writes: the first to stabilize the type and req_data, the
* second to activate.
*/
@@ -5407,6 +5530,8 @@ static int set_local_link_attributes(struct hfi1_pportdata *ppd)
if (ppd->link_speed_enabled & OPA_LINK_SPEED_12_5G)
ppd->local_tx_rate |= 1;
}
+
+ enable_lane_tx = 0xF; /* enable all four lanes */
ret = write_tx_settings(dd, enable_lane_tx, tx_polarity_inversion,
rx_polarity_inversion, ppd->local_tx_rate);
if (ret != HCMD_SUCCESS)
@@ -5716,8 +5841,7 @@ void init_qsfp(struct hfi1_pportdata *ppd)
u64 qsfp_mask;
if (loopback == LOOPBACK_SERDES || loopback == LOOPBACK_LCB ||
- ppd->dd->icode == ICODE_FUNCTIONAL_SIMULATOR ||
- !HFI1_CAP_IS_KSET(QSFP_ENABLED)) {
+ ppd->dd->icode == ICODE_FUNCTIONAL_SIMULATOR) {
ppd->driver_link_ready = 1;
return;
}
@@ -6205,7 +6329,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
if (do_wait) {
/* it can take a while for the link to go down */
- ret = wait_phy_linkstate(dd, PLS_OFFLINE, 5000);
+ ret = wait_phy_linkstate(dd, PLS_OFFLINE, 10000);
if (ret < 0)
return ret;
}
@@ -7656,11 +7780,22 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, int ctxt)
& RCV_TID_CTRL_TID_BASE_INDEX_MASK)
<< RCV_TID_CTRL_TID_BASE_INDEX_SHIFT);
write_kctxt_csr(dd, ctxt, RCV_TID_CTRL, reg);
- if (ctxt == VL15CTXT)
- write_csr(dd, RCV_VL15, VL15CTXT);
+ if (ctxt == HFI1_CTRL_CTXT)
+ write_csr(dd, RCV_VL15, HFI1_CTRL_CTXT);
}
if (op & HFI1_RCVCTRL_CTXT_DIS) {
write_csr(dd, RCV_VL15, 0);
+ /*
+ * When receive context is being disabled turn on tail
+ * update with a dummy tail address and then disable
+ * receive context.
+ */
+ if (dd->rcvhdrtail_dummy_physaddr) {
+ write_kctxt_csr(dd, ctxt, RCV_HDR_TAIL_ADDR,
+ dd->rcvhdrtail_dummy_physaddr);
+ rcvctrl |= RCV_CTXT_CTRL_TAIL_UPD_SMASK;
+ }
+
rcvctrl &= ~RCV_CTXT_CTRL_ENABLE_SMASK;
}
if (op & HFI1_RCVCTRL_INTRAVAIL_ENB)
@@ -7730,10 +7865,11 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, int ctxt)
if (op & (HFI1_RCVCTRL_TAILUPD_DIS | HFI1_RCVCTRL_CTXT_DIS))
/*
* If the context has been disabled and the Tail Update has
- * been cleared, clear the RCV_HDR_TAIL_ADDR CSR so
- * it doesn't contain an address that is invalid.
+ * been cleared, set the RCV_HDR_TAIL_ADDR CSR to dummy address
+ * so it doesn't contain an address that is invalid.
*/
- write_kctxt_csr(dd, ctxt, RCV_HDR_TAIL_ADDR, 0);
+ write_kctxt_csr(dd, ctxt, RCV_HDR_TAIL_ADDR,
+ dd->rcvhdrtail_dummy_physaddr);
}
u32 hfi1_read_cntrs(struct hfi1_devdata *dd, loff_t pos, char **namep,
@@ -8156,9 +8292,8 @@ static int init_cntrs(struct hfi1_devdata *dd)
struct hfi1_pportdata *ppd;
/* set up the stats timer; the add_timer is done at the end */
- init_timer(&dd->synth_stats_timer);
- dd->synth_stats_timer.function = update_synth_timer;
- dd->synth_stats_timer.data = (unsigned long) dd;
+ setup_timer(&dd->synth_stats_timer, update_synth_timer,
+ (unsigned long)dd);
/***********************/
/* per device counters */
@@ -8694,7 +8829,7 @@ static void clean_up_interrupts(struct hfi1_devdata *dd)
/* turn off interrupts */
if (dd->num_msix_entries) {
/* MSI-X */
- hfi1_nomsix(dd);
+ pci_disable_msix(dd->pcidev);
} else {
/* INTx */
disable_intx(dd->pcidev);
@@ -8749,12 +8884,6 @@ static void remap_sdma_interrupts(struct hfi1_devdata *dd,
msix_intr);
}
-static void remap_receive_available_interrupt(struct hfi1_devdata *dd,
- int rx, int msix_intr)
-{
- remap_intr(dd, IS_RCVAVAIL_START + rx, msix_intr);
-}
-
static int request_intx_irq(struct hfi1_devdata *dd)
{
int ret;
@@ -8779,7 +8908,7 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
int first_general, last_general;
int first_sdma, last_sdma;
int first_rx, last_rx;
- int first_cpu, restart_cpu, curr_cpu;
+ int first_cpu, curr_cpu;
int rcv_cpu, sdma_cpu;
int i, ret = 0, possible;
int ht;
@@ -8818,22 +8947,19 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
topology_sibling_cpumask(cpumask_first(local_mask)));
for (i = possible/ht; i < possible; i++)
cpumask_clear_cpu(i, def);
- /* reset possible */
- possible = cpumask_weight(def);
/* def now has full cores on chosen node*/
first_cpu = cpumask_first(def);
if (nr_cpu_ids >= first_cpu)
first_cpu++;
- restart_cpu = first_cpu;
- curr_cpu = restart_cpu;
+ curr_cpu = first_cpu;
- for (i = first_cpu; i < dd->n_krcv_queues + first_cpu; i++) {
+ /* One context is reserved as control context */
+ for (i = first_cpu; i < dd->n_krcv_queues + first_cpu - 1; i++) {
cpumask_clear_cpu(curr_cpu, def);
cpumask_set_cpu(curr_cpu, rcv);
- if (curr_cpu >= possible)
- curr_cpu = restart_cpu;
- else
- curr_cpu++;
+ curr_cpu = cpumask_next(curr_cpu, def);
+ if (curr_cpu >= nr_cpu_ids)
+ break;
}
/* def mask has non-rcv, rcv has recv mask */
rcv_cpu = cpumask_first(rcv);
@@ -8850,6 +8976,7 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
struct hfi1_msix_entry *me = &dd->msix_entries[i];
const char *err_info;
irq_handler_t handler;
+ irq_handler_t thread = NULL;
void *arg;
int idx;
struct hfi1_ctxtdata *rcd = NULL;
@@ -8886,11 +9013,12 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
rcd->imask = ((u64)1) <<
((IS_RCVAVAIL_START+idx) % 64);
handler = receive_context_interrupt;
+ thread = receive_context_thread;
arg = rcd;
snprintf(me->name, sizeof(me->name),
DRIVER_NAME"_%d kctxt%d", dd->unit, idx);
err_info = "receive context";
- remap_receive_available_interrupt(dd, idx, i);
+ remap_intr(dd, IS_RCVAVAIL_START + idx, i);
} else {
/* not in our expected range - complain, then
ignore it */
@@ -8904,7 +9032,8 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
/* make sure the name is terminated */
me->name[sizeof(me->name)-1] = 0;
- ret = request_irq(me->msix.vector, handler, 0, me->name, arg);
+ ret = request_threaded_irq(me->msix.vector, handler, thread, 0,
+ me->name, arg);
if (ret) {
dd_dev_err(dd,
"unable to allocate %s interrupt, vector %d, index %d, err %d\n",
@@ -8924,17 +9053,26 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
if (handler == sdma_interrupt) {
dd_dev_info(dd, "sdma engine %d cpu %d\n",
sde->this_idx, sdma_cpu);
+ sde->cpu = sdma_cpu;
cpumask_set_cpu(sdma_cpu, dd->msix_entries[i].mask);
sdma_cpu = cpumask_next(sdma_cpu, def);
if (sdma_cpu >= nr_cpu_ids)
sdma_cpu = cpumask_first(def);
} else if (handler == receive_context_interrupt) {
- dd_dev_info(dd, "rcv ctxt %d cpu %d\n",
- rcd->ctxt, rcv_cpu);
- cpumask_set_cpu(rcv_cpu, dd->msix_entries[i].mask);
- rcv_cpu = cpumask_next(rcv_cpu, rcv);
- if (rcv_cpu >= nr_cpu_ids)
- rcv_cpu = cpumask_first(rcv);
+ dd_dev_info(dd, "rcv ctxt %d cpu %d\n", rcd->ctxt,
+ (rcd->ctxt == HFI1_CTRL_CTXT) ?
+ cpumask_first(def) : rcv_cpu);
+ if (rcd->ctxt == HFI1_CTRL_CTXT) {
+ /* map to first default */
+ cpumask_set_cpu(cpumask_first(def),
+ dd->msix_entries[i].mask);
+ } else {
+ cpumask_set_cpu(rcv_cpu,
+ dd->msix_entries[i].mask);
+ rcv_cpu = cpumask_next(rcv_cpu, rcv);
+ if (rcv_cpu >= nr_cpu_ids)
+ rcv_cpu = cpumask_first(rcv);
+ }
} else {
/* otherwise first def */
dd_dev_info(dd, "%s cpu %d\n",
@@ -9067,11 +9205,18 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
/*
* Kernel contexts: (to be fixed later):
* - min or 2 or 1 context/numa
- * - Context 0 - default/errors
- * - Context 1 - VL15
+ * - Context 0 - control context (VL15/multicast/error)
+ * - Context 1 - default context
*/
if (n_krcvqs)
- num_kernel_contexts = n_krcvqs + MIN_KERNEL_KCTXTS;
+ /*
+ * Don't count context 0 in n_krcvqs since
+ * is isn't used for normal verbs traffic.
+ *
+ * krcvqs will reflect number of kernel
+ * receive contexts above 0.
+ */
+ num_kernel_contexts = n_krcvqs + MIN_KERNEL_KCTXTS - 1;
else
num_kernel_contexts = num_online_nodes();
num_kernel_contexts =
@@ -9327,8 +9472,6 @@ static void reset_cce_csrs(struct hfi1_devdata *dd)
/* set ASIC CSRs to chip reset defaults */
static void reset_asic_csrs(struct hfi1_devdata *dd)
{
- static DEFINE_MUTEX(asic_mutex);
- static int called;
int i;
/*
@@ -9338,15 +9481,8 @@ static void reset_asic_csrs(struct hfi1_devdata *dd)
* a known first load do the reset and blocking all others.
*/
- /*
- * These CSRs should only be reset once - the first one here will
- * do the work. Use a mutex so that a non-first caller waits until
- * the first is finished before it can proceed.
- */
- mutex_lock(&asic_mutex);
- if (called)
- goto done;
- called = 1;
+ if (!(dd->flags & HFI1_DO_INIT_ASIC))
+ return;
if (dd->icode != ICODE_FPGA_EMULATION) {
/* emulation does not have an SBus - leave these alone */
@@ -9366,8 +9502,11 @@ static void reset_asic_csrs(struct hfi1_devdata *dd)
for (i = 0; i < ASIC_NUM_SCRATCH; i++)
write_csr(dd, ASIC_CFG_SCRATCH + (8 * i), 0);
write_csr(dd, ASIC_CFG_MUTEX, 0); /* this will clear it */
+
+ /* We might want to retain this state across FLR if we ever use it */
write_csr(dd, ASIC_CFG_DRV_STR, 0);
- write_csr(dd, ASIC_CFG_THERM_POLL_EN, 0);
+
+ /* ASIC_CFG_THERM_POLL_EN leave alone */
/* ASIC_STS_THERM read-only */
/* ASIC_CFG_RESET leave alone */
@@ -9413,9 +9552,6 @@ static void reset_asic_csrs(struct hfi1_devdata *dd)
/* this also writes a NOP command, clearing paging mode */
write_csr(dd, ASIC_EEP_ADDR_CMD, 0);
write_csr(dd, ASIC_EEP_DATA, 0);
-
-done:
- mutex_unlock(&asic_mutex);
}
/* set MISC CSRs to chip reset defaults */
@@ -9827,6 +9963,7 @@ static void init_chip(struct hfi1_devdata *dd)
restore_pci_variables(dd);
}
+ reset_asic_csrs(dd);
} else {
dd_dev_info(dd, "Resetting CSRs with writes\n");
reset_cce_csrs(dd);
@@ -9837,24 +9974,22 @@ static void init_chip(struct hfi1_devdata *dd)
}
/* clear the DC reset */
write_csr(dd, CCE_DC_CTRL, 0);
+
/* Set the LED off */
if (is_a0(dd))
setextled(dd, 0);
/*
* Clear the QSFP reset.
- * A0 leaves the out lines floating on power on, then on an FLR
- * enforces a 0 on all out pins. The driver does not touch
+ * An FLR enforces a 0 on all out pins. The driver does not touch
* ASIC_QSFPn_OUT otherwise. This leaves RESET_N low and
- * anything plugged constantly in reset, if it pays attention
+ * anything plugged constantly in reset, if it pays attention
* to RESET_N.
- * A prime example of this is SiPh. For now, set all pins high.
+ * Prime examples of this are optical cables. Set all pins high.
* I2CCLK and I2CDAT will change per direction, and INT_N and
* MODPRS_N are input only and their value is ignored.
*/
- if (is_a0(dd)) {
- write_csr(dd, ASIC_QSFP1_OUT, 0x1f);
- write_csr(dd, ASIC_QSFP2_OUT, 0x1f);
- }
+ write_csr(dd, ASIC_QSFP1_OUT, 0x1f);
+ write_csr(dd, ASIC_QSFP2_OUT, 0x1f);
}
static void init_early_variables(struct hfi1_devdata *dd)
@@ -9930,12 +10065,6 @@ static void init_qpmap_table(struct hfi1_devdata *dd,
u64 ctxt = first_ctxt;
for (i = 0; i < 256;) {
- if (ctxt == VL15CTXT) {
- ctxt++;
- if (ctxt > last_ctxt)
- ctxt = first_ctxt;
- continue;
- }
reg |= ctxt << (8 * (i % 8));
i++;
ctxt++;
@@ -10048,19 +10177,13 @@ static void init_qos(struct hfi1_devdata *dd, u32 first_ctxt)
/* Enable RSM */
add_rcvctrl(dd, RCV_CTRL_RCV_RSM_ENABLE_SMASK);
kfree(rsmmap);
- /* map everything else (non-VL15) to context 0 */
- init_qpmap_table(
- dd,
- 0,
- 0);
+ /* map everything else to first context */
+ init_qpmap_table(dd, FIRST_KERNEL_KCTXT, MIN_KERNEL_KCTXTS - 1);
dd->qos_shift = n + 1;
return;
bail:
dd->qos_shift = 1;
- init_qpmap_table(
- dd,
- dd->n_krcv_queues > MIN_KERNEL_KCTXTS ? MIN_KERNEL_KCTXTS : 0,
- dd->n_krcv_queues - 1);
+ init_qpmap_table(dd, FIRST_KERNEL_KCTXT, dd->n_krcv_queues - 1);
}
static void init_rxe(struct hfi1_devdata *dd)
@@ -10332,7 +10455,7 @@ static void asic_should_init(struct hfi1_devdata *dd)
}
/**
- * Allocate an initialize the device structure for the hfi.
+ * Allocate and initialize the device structure for the hfi.
* @dev: the pci_dev for hfi1_ib device
* @ent: pci_device_id struct for this dev
*
@@ -10488,6 +10611,12 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
else if (dd->rcv_intr_timeout_csr == 0 && rcv_intr_timeout)
dd->rcv_intr_timeout_csr = 1;
+ /* needs to be done before we look for the peer device */
+ read_guid(dd);
+
+ /* should this device init the ASIC block? */
+ asic_should_init(dd);
+
/* obtain chip sizes, reset chip CSRs */
init_chip(dd);
@@ -10496,11 +10625,6 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
if (ret)
goto bail_cleanup;
- /* needs to be done before we look for the peer device */
- read_guid(dd);
-
- asic_should_init(dd);
-
/* read in firmware */
ret = hfi1_firmware_init(dd);
if (ret)
@@ -10715,6 +10839,9 @@ static int thermal_init(struct hfi1_devdata *dd)
acquire_hw_mutex(dd);
dd_dev_info(dd, "Initializing thermal sensor\n");
+ /* Disable polling of thermal readings */
+ write_csr(dd, ASIC_CFG_THERM_POLL_EN, 0x0);
+ msleep(100);
/* Thermal Sensor Initialization */
/* Step 1: Reset the Thermal SBus Receiver */
ret = sbus_request_slow(dd, SBUS_THERMAL, 0x0,
diff --git a/drivers/staging/rdma/hfi1/chip.h b/drivers/staging/rdma/hfi1/chip.h
index f89a432c7334..d74aed8ccc18 100644
--- a/drivers/staging/rdma/hfi1/chip.h
+++ b/drivers/staging/rdma/hfi1/chip.h
@@ -235,6 +235,7 @@
#define HCMD_MISC 0x05
#define HCMD_READ_LCB_IDLE_MSG 0x06
#define HCMD_READ_LCB_CSR 0x07
+#define HCMD_WRITE_LCB_CSR 0x08
#define HCMD_INTERFACE_TEST 0xff
/* DC_DC8051_CFG_HOST_CMD_1.RETURN_CODE - 8051 host command return */
@@ -609,6 +610,7 @@ static inline void write_uctxt_csr(struct hfi1_devdata *dd, int ctxt,
u64 create_pbc(struct hfi1_pportdata *ppd, u64, int, u32, u32);
/* firmware.c */
+#define SBUS_MASTER_BROADCAST 0xfd
#define NUM_PCIE_SERDES 16 /* number of PCIe serdes on the SBus */
extern const u8 pcie_serdes_broadcast[];
extern const u8 pcie_pcs_addrs[2][NUM_PCIE_SERDES];
@@ -786,6 +788,7 @@ enum {
C_SW_VTX_WAIT,
C_SW_PIO_WAIT,
C_SW_KMEM_WAIT,
+ C_SW_SEND_SCHED,
DEV_CNTR_LAST /* Must be kept last */
};
diff --git a/drivers/staging/rdma/hfi1/common.h b/drivers/staging/rdma/hfi1/common.h
index 5f2293729cf9..5dd92720faae 100644
--- a/drivers/staging/rdma/hfi1/common.h
+++ b/drivers/staging/rdma/hfi1/common.h
@@ -132,13 +132,14 @@
* HFI1_CAP_RESERVED_MASK bits.
*/
#define HFI1_CAP_WRITABLE_MASK (HFI1_CAP_SDMA_AHG | \
- HFI1_CAP_HDRSUPP | \
- HFI1_CAP_MULTI_PKT_EGR | \
- HFI1_CAP_NODROP_RHQ_FULL | \
- HFI1_CAP_NODROP_EGR_FULL | \
- HFI1_CAP_ALLOW_PERM_JKEY | \
- HFI1_CAP_STATIC_RATE_CTRL | \
- HFI1_CAP_PRINT_UNIMPL)
+ HFI1_CAP_HDRSUPP | \
+ HFI1_CAP_MULTI_PKT_EGR | \
+ HFI1_CAP_NODROP_RHQ_FULL | \
+ HFI1_CAP_NODROP_EGR_FULL | \
+ HFI1_CAP_ALLOW_PERM_JKEY | \
+ HFI1_CAP_STATIC_RATE_CTRL | \
+ HFI1_CAP_PRINT_UNIMPL | \
+ HFI1_CAP_TID_UNMAP)
/*
* A set of capability bits that are "global" and are not allowed to be
* set in the user bitmask.
@@ -147,7 +148,6 @@
HFI1_CAP_USE_SDMA_HEAD | \
HFI1_CAP_EXTENDED_PSN | \
HFI1_CAP_PRINT_UNIMPL | \
- HFI1_CAP_QSFP_ENABLED | \
HFI1_CAP_NO_INTEGRITY | \
HFI1_CAP_PKEY_CHECK) << \
HFI1_CAP_USER_SHIFT)
@@ -163,7 +163,6 @@
HFI1_CAP_SDMA | \
HFI1_CAP_PRINT_UNIMPL | \
HFI1_CAP_STATIC_RATE_CTRL | \
- HFI1_CAP_QSFP_ENABLED | \
HFI1_CAP_PKEY_CHECK | \
HFI1_CAP_MULTI_PKT_EGR | \
HFI1_CAP_EXTENDED_PSN | \
@@ -206,7 +205,7 @@
* to the driver itself, not the software interfaces it supports.
*/
#ifndef HFI1_DRIVER_VERSION_BASE
-#define HFI1_DRIVER_VERSION_BASE "0.9-248"
+#define HFI1_DRIVER_VERSION_BASE "0.9-294"
#endif
/* create the final driver version string */
diff --git a/drivers/staging/rdma/hfi1/diag.c b/drivers/staging/rdma/hfi1/diag.c
index 88414d720469..0aaad7412842 100644
--- a/drivers/staging/rdma/hfi1/diag.c
+++ b/drivers/staging/rdma/hfi1/diag.c
@@ -1618,14 +1618,12 @@ int snoop_recv_handler(struct hfi1_packet *packet)
/*
* Handle snooping and capturing packets when sdma is being used.
*/
-int snoop_send_dma_handler(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc)
+int snoop_send_dma_handler(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc)
{
- pr_alert("Snooping/Capture of Send DMA Packets Is Not Supported!\n");
+ pr_alert("Snooping/Capture of Send DMA Packets Is Not Supported!\n");
snoop_dbg("Unsupported Operation");
- return hfi1_verbs_send_dma(qp, ibhdr, hdrwords, ss, len, plen, dwords,
- 0);
+ return hfi1_verbs_send_dma(qp, ps, 0);
}
/*
@@ -1633,12 +1631,16 @@ int snoop_send_dma_handler(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr,
* bypass packets. The only way to send a bypass packet currently is to use the
* diagpkt interface. When that interface is enable snoop/capture is not.
*/
-int snoop_send_pio_handler(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc)
+int snoop_send_pio_handler(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc)
{
- struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+ struct ahg_ib_header *ahdr = qp->s_hdr;
+ u32 hdrwords = qp->s_hdrwords;
+ struct hfi1_sge_state *ss = qp->s_cur_sge;
+ u32 len = qp->s_cur_size;
+ u32 dwords = (len + 3) >> 2;
+ u32 plen = hdrwords + dwords + 2; /* includes pbc */
+ struct hfi1_pportdata *ppd = ps->ppd;
struct snoop_packet *s_packet = NULL;
u32 *hdr = (u32 *)&ahdr->ibh;
u32 length = 0;
@@ -1783,8 +1785,7 @@ int snoop_send_pio_handler(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
break;
}
out:
- return hfi1_verbs_send_pio(qp, ahdr, hdrwords, ss, len, plen, dwords,
- md.u.pbc);
+ return hfi1_verbs_send_pio(qp, ps, md.u.pbc);
}
/*
diff --git a/drivers/staging/rdma/hfi1/driver.c b/drivers/staging/rdma/hfi1/driver.c
index c0a59001e5cd..4c52e785de68 100644
--- a/drivers/staging/rdma/hfi1/driver.c
+++ b/drivers/staging/rdma/hfi1/driver.c
@@ -302,6 +302,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
qp_num = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK;
if (lid < HFI1_MULTICAST_LID_BASE) {
struct hfi1_qp *qp;
+ unsigned long flags;
rcu_read_lock();
qp = hfi1_lookup_qpn(ibp, qp_num);
@@ -314,7 +315,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
* Handle only RC QPs - for other QP types drop error
* packet.
*/
- spin_lock(&qp->r_lock);
+ spin_lock_irqsave(&qp->r_lock, flags);
/* Check for valid receive state. */
if (!(ib_hfi1_state_ops[qp->state] &
@@ -335,7 +336,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
break;
}
- spin_unlock(&qp->r_lock);
+ spin_unlock_irqrestore(&qp->r_lock, flags);
rcu_read_unlock();
} /* Unicast QP */
} /* Valid packet with TIDErr */
@@ -426,8 +427,7 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
packet->rcd = rcd;
packet->updegr = 0;
packet->etail = -1;
- packet->rhf_addr = (__le32 *) rcd->rcvhdrq + rcd->head +
- rcd->dd->rhf_offset;
+ packet->rhf_addr = get_rhf_addr(rcd);
packet->rhf = rhf_to_cpu(packet->rhf_addr);
packet->rhqoff = rcd->head;
packet->numpkt = 0;
@@ -436,59 +436,58 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
#ifndef CONFIG_PRESCAN_RXQ
static void prescan_rxq(struct hfi1_packet *packet) {}
-#else /* CONFIG_PRESCAN_RXQ */
+#else /* !CONFIG_PRESCAN_RXQ */
static int prescan_receive_queue;
static void process_ecn(struct hfi1_qp *qp, struct hfi1_ib_header *hdr,
struct hfi1_other_headers *ohdr,
- u64 rhf, struct ib_grh *grh)
+ u64 rhf, u32 bth1, struct ib_grh *grh)
{
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- u32 bth1;
+ u32 rqpn = 0;
+ u16 rlid;
u8 sc5, svc_type;
- int is_fecn, is_becn;
switch (qp->ibqp.qp_type) {
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
case IB_QPT_UD:
+ rlid = be16_to_cpu(hdr->lrh[3]);
+ rqpn = be32_to_cpu(ohdr->u.ud.deth[1]) & HFI1_QPN_MASK;
svc_type = IB_CC_SVCTYPE_UD;
break;
- case IB_QPT_UC: /* LATER */
- case IB_QPT_RC: /* LATER */
+ case IB_QPT_UC:
+ rlid = qp->remote_ah_attr.dlid;
+ rqpn = qp->remote_qpn;
+ svc_type = IB_CC_SVCTYPE_UC;
+ break;
+ case IB_QPT_RC:
+ rlid = qp->remote_ah_attr.dlid;
+ rqpn = qp->remote_qpn;
+ svc_type = IB_CC_SVCTYPE_RC;
+ break;
default:
return;
}
- is_fecn = (be32_to_cpu(ohdr->bth[1]) >> HFI1_FECN_SHIFT) &
- HFI1_FECN_MASK;
- is_becn = (be32_to_cpu(ohdr->bth[1]) >> HFI1_BECN_SHIFT) &
- HFI1_BECN_MASK;
-
sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf;
if (rhf_dc_info(rhf))
sc5 |= 0x10;
- if (is_fecn) {
- u32 src_qpn = be32_to_cpu(ohdr->u.ud.deth[1]) & HFI1_QPN_MASK;
+ if (bth1 & HFI1_FECN_SMASK) {
u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]);
u16 dlid = be16_to_cpu(hdr->lrh[1]);
- u16 slid = be16_to_cpu(hdr->lrh[3]);
- return_cnp(ibp, qp, src_qpn, pkey, dlid, slid, sc5, grh);
+ return_cnp(ibp, qp, rqpn, pkey, dlid, rlid, sc5, grh);
}
- if (is_becn) {
+ if (bth1 & HFI1_BECN_SMASK) {
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
- u32 lqpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK;
+ u32 lqpn = bth1 & HFI1_QPN_MASK;
u8 sl = ibp->sc_to_sl[sc5];
- process_becn(ppd, sl, 0, lqpn, 0, svc_type);
+ process_becn(ppd, sl, rlid, lqpn, rqpn, svc_type);
}
-
- /* turn off BECN, or FECN */
- bth1 = be32_to_cpu(ohdr->bth[1]);
- bth1 &= ~(HFI1_FECN_MASK << HFI1_FECN_SHIFT);
- bth1 &= ~(HFI1_BECN_MASK << HFI1_BECN_SHIFT);
- ohdr->bth[1] = cpu_to_be32(bth1);
}
struct ps_mdata {
@@ -508,38 +507,51 @@ static inline void init_ps_mdata(struct ps_mdata *mdata,
mdata->rcd = rcd;
mdata->rsize = packet->rsize;
mdata->maxcnt = packet->maxcnt;
+ mdata->ps_head = packet->rhqoff;
- if (rcd->ps_state.initialized == 0) {
- mdata->ps_head = packet->rhqoff;
- rcd->ps_state.initialized++;
- } else
- mdata->ps_head = rcd->ps_state.ps_head;
-
- if (HFI1_CAP_IS_KSET(DMA_RTAIL)) {
- mdata->ps_tail = packet->hdrqtail;
- mdata->ps_seq = 0; /* not used with DMA_RTAIL */
+ if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) {
+ mdata->ps_tail = get_rcvhdrtail(rcd);
+ if (rcd->ctxt == HFI1_CTRL_CTXT)
+ mdata->ps_seq = rcd->seq_cnt;
+ else
+ mdata->ps_seq = 0; /* not used with DMA_RTAIL */
} else {
mdata->ps_tail = 0; /* used only with DMA_RTAIL*/
mdata->ps_seq = rcd->seq_cnt;
}
}
-static inline int ps_done(struct ps_mdata *mdata, u64 rhf)
+static inline int ps_done(struct ps_mdata *mdata, u64 rhf,
+ struct hfi1_ctxtdata *rcd)
{
- if (HFI1_CAP_IS_KSET(DMA_RTAIL))
+ if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL))
return mdata->ps_head == mdata->ps_tail;
return mdata->ps_seq != rhf_rcv_seq(rhf);
}
-static inline void update_ps_mdata(struct ps_mdata *mdata)
+static inline int ps_skip(struct ps_mdata *mdata, u64 rhf,
+ struct hfi1_ctxtdata *rcd)
{
- struct hfi1_ctxtdata *rcd = mdata->rcd;
+ /*
+ * Control context can potentially receive an invalid rhf.
+ * Drop such packets.
+ */
+ if ((rcd->ctxt == HFI1_CTRL_CTXT) && (mdata->ps_head != mdata->ps_tail))
+ return mdata->ps_seq != rhf_rcv_seq(rhf);
+
+ return 0;
+}
+static inline void update_ps_mdata(struct ps_mdata *mdata,
+ struct hfi1_ctxtdata *rcd)
+{
mdata->ps_head += mdata->rsize;
- if (mdata->ps_head > mdata->maxcnt)
+ if (mdata->ps_head >= mdata->maxcnt)
mdata->ps_head = 0;
- rcd->ps_state.ps_head = mdata->ps_head;
- if (!HFI1_CAP_IS_KSET(DMA_RTAIL)) {
+
+ /* Control context must do seq counting */
+ if (!HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ||
+ (rcd->ctxt == HFI1_CTRL_CTXT)) {
if (++mdata->ps_seq > 13)
mdata->ps_seq = 1;
}
@@ -571,13 +583,16 @@ static void prescan_rxq(struct hfi1_packet *packet)
struct hfi1_other_headers *ohdr;
struct ib_grh *grh = NULL;
u64 rhf = rhf_to_cpu(rhf_addr);
- u32 etype = rhf_rcv_type(rhf), qpn;
+ u32 etype = rhf_rcv_type(rhf), qpn, bth1;
int is_ecn = 0;
u8 lnh;
- if (ps_done(&mdata, rhf))
+ if (ps_done(&mdata, rhf, rcd))
break;
+ if (ps_skip(&mdata, rhf, rcd))
+ goto next;
+
if (etype != RHF_RCV_TYPE_IB)
goto next;
@@ -593,15 +608,13 @@ static void prescan_rxq(struct hfi1_packet *packet)
} else
goto next; /* just in case */
- is_ecn |= be32_to_cpu(ohdr->bth[1]) &
- (HFI1_FECN_MASK << HFI1_FECN_SHIFT);
- is_ecn |= be32_to_cpu(ohdr->bth[1]) &
- (HFI1_BECN_MASK << HFI1_BECN_SHIFT);
+ bth1 = be32_to_cpu(ohdr->bth[1]);
+ is_ecn = !!(bth1 & (HFI1_FECN_SMASK | HFI1_BECN_SMASK));
if (!is_ecn)
goto next;
- qpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK;
+ qpn = bth1 & HFI1_QPN_MASK;
rcu_read_lock();
qp = hfi1_lookup_qpn(ibp, qpn);
@@ -610,18 +623,45 @@ static void prescan_rxq(struct hfi1_packet *packet)
goto next;
}
- process_ecn(qp, hdr, ohdr, rhf, grh);
+ process_ecn(qp, hdr, ohdr, rhf, bth1, grh);
rcu_read_unlock();
+
+ /* turn off BECN, FECN */
+ bth1 &= ~(HFI1_FECN_SMASK | HFI1_BECN_SMASK);
+ ohdr->bth[1] = cpu_to_be32(bth1);
next:
- update_ps_mdata(&mdata);
+ update_ps_mdata(&mdata, rcd);
}
}
-#endif /* CONFIG_PRESCAN_RXQ */
-#define RCV_PKT_OK 0x0
-#define RCV_PKT_MAX 0x1
+static inline int skip_rcv_packet(struct hfi1_packet *packet, int thread)
+{
+ int ret = RCV_PKT_OK;
-static inline int process_rcv_packet(struct hfi1_packet *packet)
+ /* Set up for the next packet */
+ packet->rhqoff += packet->rsize;
+ if (packet->rhqoff >= packet->maxcnt)
+ packet->rhqoff = 0;
+
+ packet->numpkt++;
+ if (unlikely((packet->numpkt & (MAX_PKT_RECV - 1)) == 0)) {
+ if (thread) {
+ cond_resched();
+ } else {
+ ret = RCV_PKT_LIMIT;
+ this_cpu_inc(*packet->rcd->dd->rcv_limit);
+ }
+ }
+
+ packet->rhf_addr = (__le32 *)packet->rcd->rcvhdrq + packet->rhqoff +
+ packet->rcd->dd->rhf_offset;
+ packet->rhf = rhf_to_cpu(packet->rhf_addr);
+
+ return ret;
+}
+#endif /* CONFIG_PRESCAN_RXQ */
+
+static inline int process_rcv_packet(struct hfi1_packet *packet, int thread)
{
int ret = RCV_PKT_OK;
@@ -663,9 +703,13 @@ static inline int process_rcv_packet(struct hfi1_packet *packet)
if (packet->rhqoff >= packet->maxcnt)
packet->rhqoff = 0;
- if (packet->numpkt == MAX_PKT_RECV) {
- ret = RCV_PKT_MAX;
- this_cpu_inc(*packet->rcd->dd->rcv_limit);
+ if (unlikely((packet->numpkt & (MAX_PKT_RECV - 1)) == 0)) {
+ if (thread) {
+ cond_resched();
+ } else {
+ ret = RCV_PKT_LIMIT;
+ this_cpu_inc(*packet->rcd->dd->rcv_limit);
+ }
}
packet->rhf_addr = (__le32 *) packet->rcd->rcvhdrq + packet->rhqoff +
@@ -720,8 +764,8 @@ static inline void process_rcv_qp_work(struct hfi1_packet *packet)
*/
list_for_each_entry_safe(qp, nqp, &rcd->qp_wait_list, rspwait) {
list_del_init(&qp->rspwait);
- if (qp->r_flags & HFI1_R_RSP_NAK) {
- qp->r_flags &= ~HFI1_R_RSP_NAK;
+ if (qp->r_flags & HFI1_R_RSP_DEFERED_ACK) {
+ qp->r_flags &= ~HFI1_R_RSP_DEFERED_ACK;
hfi1_send_rc_ack(rcd, qp, 0);
}
if (qp->r_flags & HFI1_R_RSP_SEND) {
@@ -742,64 +786,69 @@ static inline void process_rcv_qp_work(struct hfi1_packet *packet)
/*
* Handle receive interrupts when using the no dma rtail option.
*/
-void handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd)
+int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd, int thread)
{
u32 seq;
- int last = 0;
+ int last = RCV_PKT_OK;
struct hfi1_packet packet;
init_packet(rcd, &packet);
seq = rhf_rcv_seq(packet.rhf);
- if (seq != rcd->seq_cnt)
+ if (seq != rcd->seq_cnt) {
+ last = RCV_PKT_DONE;
goto bail;
+ }
prescan_rxq(&packet);
- while (!last) {
- last = process_rcv_packet(&packet);
+ while (last == RCV_PKT_OK) {
+ last = process_rcv_packet(&packet, thread);
seq = rhf_rcv_seq(packet.rhf);
if (++rcd->seq_cnt > 13)
rcd->seq_cnt = 1;
if (seq != rcd->seq_cnt)
- last = 1;
+ last = RCV_PKT_DONE;
process_rcv_update(last, &packet);
}
process_rcv_qp_work(&packet);
bail:
finish_packet(&packet);
+ return last;
}
-void handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd)
+int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd, int thread)
{
u32 hdrqtail;
- int last = 0;
+ int last = RCV_PKT_OK;
struct hfi1_packet packet;
init_packet(rcd, &packet);
hdrqtail = get_rcvhdrtail(rcd);
- if (packet.rhqoff == hdrqtail)
+ if (packet.rhqoff == hdrqtail) {
+ last = RCV_PKT_DONE;
goto bail;
+ }
smp_rmb(); /* prevent speculative reads of dma'ed hdrq */
prescan_rxq(&packet);
- while (!last) {
- last = process_rcv_packet(&packet);
+ while (last == RCV_PKT_OK) {
+ last = process_rcv_packet(&packet, thread);
if (packet.rhqoff == hdrqtail)
- last = 1;
+ last = RCV_PKT_DONE;
process_rcv_update(last, &packet);
}
process_rcv_qp_work(&packet);
bail:
finish_packet(&packet);
-
+ return last;
}
static inline void set_all_nodma_rtail(struct hfi1_devdata *dd)
{
int i;
- for (i = 0; i < dd->first_user_ctxt; i++)
+ for (i = HFI1_CTRL_CTXT + 1; i < dd->first_user_ctxt; i++)
dd->rcd[i]->do_interrupt =
&handle_receive_interrupt_nodma_rtail;
}
@@ -808,7 +857,7 @@ static inline void set_all_dma_rtail(struct hfi1_devdata *dd)
{
int i;
- for (i = 0; i < dd->first_user_ctxt; i++)
+ for (i = HFI1_CTRL_CTXT + 1; i < dd->first_user_ctxt; i++)
dd->rcd[i]->do_interrupt =
&handle_receive_interrupt_dma_rtail;
}
@@ -820,32 +869,50 @@ static inline void set_all_dma_rtail(struct hfi1_devdata *dd)
* Called from interrupt handler for errors or receive interrupt.
* This is the slow path interrupt handler.
*/
-void handle_receive_interrupt(struct hfi1_ctxtdata *rcd)
+int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread)
{
-
struct hfi1_devdata *dd = rcd->dd;
u32 hdrqtail;
- int last = 0, needset = 1;
+ int needset, last = RCV_PKT_OK;
struct hfi1_packet packet;
+ int skip_pkt = 0;
+
+ /* Control context will always use the slow path interrupt handler */
+ needset = (rcd->ctxt == HFI1_CTRL_CTXT) ? 0 : 1;
init_packet(rcd, &packet);
- if (!HFI1_CAP_IS_KSET(DMA_RTAIL)) {
+ if (!HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) {
u32 seq = rhf_rcv_seq(packet.rhf);
- if (seq != rcd->seq_cnt)
+ if (seq != rcd->seq_cnt) {
+ last = RCV_PKT_DONE;
goto bail;
+ }
hdrqtail = 0;
} else {
hdrqtail = get_rcvhdrtail(rcd);
- if (packet.rhqoff == hdrqtail)
+ if (packet.rhqoff == hdrqtail) {
+ last = RCV_PKT_DONE;
goto bail;
+ }
smp_rmb(); /* prevent speculative reads of dma'ed hdrq */
+
+ /*
+ * Control context can potentially receive an invalid
+ * rhf. Drop such packets.
+ */
+ if (rcd->ctxt == HFI1_CTRL_CTXT) {
+ u32 seq = rhf_rcv_seq(packet.rhf);
+
+ if (seq != rcd->seq_cnt)
+ skip_pkt = 1;
+ }
}
prescan_rxq(&packet);
- while (!last) {
+ while (last == RCV_PKT_OK) {
if (unlikely(dd->do_drop && atomic_xchg(&dd->drop_packet,
DROP_PACKET_OFF) == DROP_PACKET_ON)) {
@@ -858,17 +925,20 @@ void handle_receive_interrupt(struct hfi1_ctxtdata *rcd)
dd->rhf_offset;
packet.rhf = rhf_to_cpu(packet.rhf_addr);
+ } else if (skip_pkt) {
+ last = skip_rcv_packet(&packet, thread);
+ skip_pkt = 0;
} else {
- last = process_rcv_packet(&packet);
+ last = process_rcv_packet(&packet, thread);
}
- if (!HFI1_CAP_IS_KSET(DMA_RTAIL)) {
+ if (!HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) {
u32 seq = rhf_rcv_seq(packet.rhf);
if (++rcd->seq_cnt > 13)
rcd->seq_cnt = 1;
if (seq != rcd->seq_cnt)
- last = 1;
+ last = RCV_PKT_DONE;
if (needset) {
dd_dev_info(dd,
"Switching to NO_DMA_RTAIL\n");
@@ -877,7 +947,20 @@ void handle_receive_interrupt(struct hfi1_ctxtdata *rcd)
}
} else {
if (packet.rhqoff == hdrqtail)
- last = 1;
+ last = RCV_PKT_DONE;
+ /*
+ * Control context can potentially receive an invalid
+ * rhf. Drop such packets.
+ */
+ if (rcd->ctxt == HFI1_CTRL_CTXT) {
+ u32 seq = rhf_rcv_seq(packet.rhf);
+
+ if (++rcd->seq_cnt > 13)
+ rcd->seq_cnt = 1;
+ if (!last && (seq != rcd->seq_cnt))
+ skip_pkt = 1;
+ }
+
if (needset) {
dd_dev_info(dd,
"Switching to DMA_RTAIL\n");
@@ -897,6 +980,7 @@ bail:
* if no packets were processed.
*/
finish_packet(&packet);
+ return last;
}
/*
@@ -1062,9 +1146,9 @@ void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int val)
*/
if (atomic_inc_return(&ppd->led_override_timer_active) == 1) {
/* Need to start timer */
- init_timer(&ppd->led_override_timer);
- ppd->led_override_timer.function = run_led_override;
- ppd->led_override_timer.data = (unsigned long) ppd;
+ setup_timer(&ppd->led_override_timer, run_led_override,
+ (unsigned long)ppd);
+
ppd->led_override_timer.expires = jiffies + 1;
add_timer(&ppd->led_override_timer);
} else {
@@ -1152,20 +1236,20 @@ void handle_eflags(struct hfi1_packet *packet)
struct hfi1_ctxtdata *rcd = packet->rcd;
u32 rte = rhf_rcv_type_err(packet->rhf);
- dd_dev_err(rcd->dd,
- "receive context %d: rhf 0x%016llx, errs [ %s%s%s%s%s%s%s%s] rte 0x%x\n",
- rcd->ctxt, packet->rhf,
- packet->rhf & RHF_K_HDR_LEN_ERR ? "k_hdr_len " : "",
- packet->rhf & RHF_DC_UNC_ERR ? "dc_unc " : "",
- packet->rhf & RHF_DC_ERR ? "dc " : "",
- packet->rhf & RHF_TID_ERR ? "tid " : "",
- packet->rhf & RHF_LEN_ERR ? "len " : "",
- packet->rhf & RHF_ECC_ERR ? "ecc " : "",
- packet->rhf & RHF_VCRC_ERR ? "vcrc " : "",
- packet->rhf & RHF_ICRC_ERR ? "icrc " : "",
- rte);
-
rcv_hdrerr(rcd, rcd->ppd, packet);
+ if (rhf_err_flags(packet->rhf))
+ dd_dev_err(rcd->dd,
+ "receive context %d: rhf 0x%016llx, errs [ %s%s%s%s%s%s%s%s] rte 0x%x\n",
+ rcd->ctxt, packet->rhf,
+ packet->rhf & RHF_K_HDR_LEN_ERR ? "k_hdr_len " : "",
+ packet->rhf & RHF_DC_UNC_ERR ? "dc_unc " : "",
+ packet->rhf & RHF_DC_ERR ? "dc " : "",
+ packet->rhf & RHF_TID_ERR ? "tid " : "",
+ packet->rhf & RHF_LEN_ERR ? "len " : "",
+ packet->rhf & RHF_ECC_ERR ? "ecc " : "",
+ packet->rhf & RHF_VCRC_ERR ? "vcrc " : "",
+ packet->rhf & RHF_ICRC_ERR ? "icrc " : "",
+ rte);
}
/*
diff --git a/drivers/staging/rdma/hfi1/file_ops.c b/drivers/staging/rdma/hfi1/file_ops.c
index cbaf4f734add..22037ce984c8 100644
--- a/drivers/staging/rdma/hfi1/file_ops.c
+++ b/drivers/staging/rdma/hfi1/file_ops.c
@@ -47,20 +47,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
-#include <linux/pci.h>
#include <linux/poll.h>
#include <linux/cdev.h>
-#include <linux/swap.h>
#include <linux/vmalloc.h>
-#include <linux/highmem.h>
#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <asm/pgtable.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/cred.h>
-#include <linux/uio.h>
#include "hfi.h"
#include "pio.h"
@@ -68,6 +58,7 @@
#include "common.h"
#include "trace.h"
#include "user_sdma.h"
+#include "user_exp_rcv.h"
#include "eprom.h"
#undef pr_fmt
@@ -170,18 +161,6 @@ enum mmap_types {
HFI1_MMAP_TOKEN_SET(SUBCTXT, subctxt) | \
HFI1_MMAP_TOKEN_SET(OFFSET, (offset_in_page(addr))))
-#define EXP_TID_SET(field, value) \
- (((value) & EXP_TID_TID##field##_MASK) << \
- EXP_TID_TID##field##_SHIFT)
-#define EXP_TID_CLEAR(tid, field) { \
- (tid) &= ~(EXP_TID_TID##field##_MASK << \
- EXP_TID_TID##field##_SHIFT); \
- }
-#define EXP_TID_RESET(tid, field, value) do { \
- EXP_TID_CLEAR(tid, field); \
- (tid) |= EXP_TID_SET(field, value); \
- } while (0)
-
#define dbg(fmt, ...) \
pr_info(fmt, ##__VA_ARGS__)
@@ -204,7 +183,8 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data,
size_t count, loff_t *offset)
{
const struct hfi1_cmd __user *ucmd;
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_cmd cmd;
struct hfi1_user_info uinfo;
struct hfi1_tid_info tinfo;
@@ -338,17 +318,17 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data,
ret = exp_tid_free(fp, &tinfo);
break;
case HFI1_CMD_RECV_CTRL:
- ret = manage_rcvq(uctxt, subctxt_fp(fp), (int)user_val);
+ ret = manage_rcvq(uctxt, fd->subctxt, (int)user_val);
break;
case HFI1_CMD_POLL_TYPE:
uctxt->poll_type = (typeof(uctxt->poll_type))user_val;
break;
case HFI1_CMD_ACK_EVENT:
- ret = user_event_ack(uctxt, subctxt_fp(fp), user_val);
+ ret = user_event_ack(uctxt, fd->subctxt, user_val);
break;
case HFI1_CMD_SET_PKEY:
if (HFI1_CAP_IS_USET(PKEY_CHECK))
- ret = set_ctxt_pkey(uctxt, subctxt_fp(fp), user_val);
+ ret = set_ctxt_pkey(uctxt, fd->subctxt, user_val);
else
ret = -EPERM;
break;
@@ -431,13 +411,13 @@ bail:
static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
{
- struct hfi1_user_sdma_pkt_q *pq;
- struct hfi1_user_sdma_comp_q *cq;
+ struct hfi1_filedata *fd = kiocb->ki_filp->private_data;
+ struct hfi1_user_sdma_pkt_q *pq = fd->pq;
+ struct hfi1_user_sdma_comp_q *cq = fd->cq;
int ret = 0, done = 0, reqs = 0;
unsigned long dim = from->nr_segs;
- if (!user_sdma_comp_fp(kiocb->ki_filp) ||
- !user_sdma_pkt_fp(kiocb->ki_filp)) {
+ if (!cq || !pq) {
ret = -EIO;
goto done;
}
@@ -448,10 +428,7 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
}
hfi1_cdbg(SDMA, "SDMA request from %u:%u (%lu)",
- ctxt_fp(kiocb->ki_filp)->ctxt, subctxt_fp(kiocb->ki_filp),
- dim);
- pq = user_sdma_pkt_fp(kiocb->ki_filp);
- cq = user_sdma_comp_fp(kiocb->ki_filp);
+ fd->uctxt->ctxt, fd->subctxt, dim);
if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) {
ret = -ENOSPC;
@@ -476,7 +453,8 @@ done:
static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
{
- struct hfi1_ctxtdata *uctxt;
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd;
unsigned long flags, pfn;
u64 token = vma->vm_pgoff << PAGE_SHIFT,
@@ -486,7 +464,6 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
int ret = 0;
u16 ctxt;
- uctxt = ctxt_fp(fp);
if (!is_valid_mmap(token) || !uctxt ||
!(vma->vm_flags & VM_SHARED)) {
ret = -EINVAL;
@@ -496,7 +473,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
ctxt = HFI1_MMAP_TOKEN_GET(CTXT, token);
subctxt = HFI1_MMAP_TOKEN_GET(SUBCTXT, token);
type = HFI1_MMAP_TOKEN_GET(TYPE, token);
- if (ctxt != uctxt->ctxt || subctxt != subctxt_fp(fp)) {
+ if (ctxt != uctxt->ctxt || subctxt != fd->subctxt) {
ret = -EINVAL;
goto done;
}
@@ -607,9 +584,9 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
* Use the page where this context's flags are. User level
* knows where it's own bitmap is within the page.
*/
- memaddr = ((unsigned long)dd->events +
- ((uctxt->ctxt - dd->first_user_ctxt) *
- HFI1_MAX_SHARED_CTXTS)) & PAGE_MASK;
+ memaddr = (unsigned long)(dd->events +
+ ((uctxt->ctxt - dd->first_user_ctxt) *
+ HFI1_MAX_SHARED_CTXTS)) & PAGE_MASK;
memlen = PAGE_SIZE;
/*
* v3.7 removes VM_RESERVED but the effect is kept by
@@ -660,13 +637,12 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
vmf = 1;
break;
case SDMA_COMP: {
- struct hfi1_user_sdma_comp_q *cq;
+ struct hfi1_user_sdma_comp_q *cq = fd->cq;
- if (!user_sdma_comp_fp(fp)) {
+ if (!cq) {
ret = -EFAULT;
goto done;
}
- cq = user_sdma_comp_fp(fp);
memaddr = (u64)cq->comps;
memlen = ALIGN(sizeof(*cq->comps) * cq->nentries, PAGE_SIZE);
flags |= VM_IO | VM_DONTEXPAND;
@@ -680,16 +656,16 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
if ((vma->vm_end - vma->vm_start) != memlen) {
hfi1_cdbg(PROC, "%u:%u Memory size mismatch %lu:%lu",
- uctxt->ctxt, subctxt_fp(fp),
+ uctxt->ctxt, fd->subctxt,
(vma->vm_end - vma->vm_start), memlen);
ret = -EINVAL;
goto done;
}
vma->vm_flags = flags;
- dd_dev_info(dd,
- "%s: %u:%u type:%u io/vf:%d/%d, addr:0x%llx, len:%lu(%lu), flags:0x%lx\n",
- __func__, ctxt, subctxt, type, mapio, vmf, memaddr, memlen,
+ hfi1_cdbg(PROC,
+ "%u:%u type:%u io/vf:%d/%d, addr:0x%llx, len:%lu(%lu), flags:0x%lx\n",
+ ctxt, subctxt, type, mapio, vmf, memaddr, memlen,
vma->vm_end - vma->vm_start, vma->vm_flags);
pfn = (unsigned long)(memaddr >> PAGE_SHIFT);
if (vmf) {
@@ -730,7 +706,7 @@ static unsigned int hfi1_poll(struct file *fp, struct poll_table_struct *pt)
struct hfi1_ctxtdata *uctxt;
unsigned pollflag;
- uctxt = ctxt_fp(fp);
+ uctxt = ((struct hfi1_filedata *)fp->private_data)->uctxt;
if (!uctxt)
pollflag = POLLERR;
else if (uctxt->poll_type == HFI1_POLL_TYPE_URGENT)
@@ -874,6 +850,14 @@ done:
return ret;
}
+/* return true if the device available for general use */
+static int usable_device(struct hfi1_devdata *dd)
+{
+ struct hfi1_pportdata *ppd = dd->pport;
+
+ return driver_lstate(ppd) == IB_PORT_ACTIVE;
+}
+
static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo,
int devno, unsigned alg)
{
@@ -903,7 +887,11 @@ static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo,
for (dev = 0; dev < devmax; dev++) {
pdd = hfi1_lookup(dev);
- if (pdd && pdd->freectxts &&
+ if (!pdd)
+ continue;
+ if (!usable_device(pdd))
+ continue;
+ if (pdd->freectxts &&
pdd->freectxts > free) {
dd = pdd;
free = pdd->freectxts;
@@ -912,7 +900,11 @@ static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo,
} else {
for (dev = 0; dev < devmax; dev++) {
pdd = hfi1_lookup(dev);
- if (pdd && pdd->freectxts) {
+ if (!pdd)
+ continue;
+ if (!usable_device(pdd))
+ continue;
+ if (pdd->freectxts) {
dd = pdd;
break;
}
@@ -930,13 +922,13 @@ static int find_shared_ctxt(struct file *fp,
{
int devmax, ndev, i;
int ret = 0;
+ struct hfi1_filedata *fd = fp->private_data;
devmax = hfi1_count_units(NULL, NULL);
for (ndev = 0; ndev < devmax; ndev++) {
struct hfi1_devdata *dd = hfi1_lookup(ndev);
- /* device portion of usable() */
if (!(dd && (dd->flags & HFI1_PRESENT) && dd->kregbase))
continue;
for (i = dd->first_user_ctxt; i < dd->num_rcv_contexts; i++) {
@@ -948,6 +940,7 @@ static int find_shared_ctxt(struct file *fp,
/* Skip ctxt if it doesn't match the requested one */
if (memcmp(uctxt->uuid, uinfo->uuid,
sizeof(uctxt->uuid)) ||
+ uctxt->jkey != generate_jkey(current_uid()) ||
uctxt->subctxt_id != uinfo->subctxt_id ||
uctxt->subctxt_cnt != uinfo->subctxt_cnt)
continue;
@@ -958,10 +951,10 @@ static int find_shared_ctxt(struct file *fp,
ret = -EINVAL;
goto done;
}
- ctxt_fp(fp) = uctxt;
- subctxt_fp(fp) = uctxt->cnt++;
- uctxt->subpid[subctxt_fp(fp)] = current->pid;
- uctxt->active_slaves |= 1 << subctxt_fp(fp);
+ fd->uctxt = uctxt;
+ fd->subctxt = uctxt->cnt++;
+ uctxt->subpid[fd->subctxt] = current->pid;
+ uctxt->active_slaves |= 1 << fd->subctxt;
ret = 1;
goto done;
}
@@ -974,6 +967,7 @@ done:
static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
struct hfi1_user_info *uinfo)
{
+ struct hfi1_filedata *fd = fp->private_data;
struct hfi1_ctxtdata *uctxt;
unsigned ctxt;
int ret;
@@ -1010,8 +1004,8 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
if (!uctxt->sc)
return -ENOMEM;
- dbg("allocated send context %u(%u)\n", uctxt->sc->sw_index,
- uctxt->sc->hw_context);
+ hfi1_cdbg(PROC, "allocated send context %u(%u)\n", uctxt->sc->sw_index,
+ uctxt->sc->hw_context);
ret = sc_enable(uctxt->sc);
if (ret)
return ret;
@@ -1021,7 +1015,7 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
* This has to be done here so the rest of the sub-contexts find the
* proper master.
*/
- if (uinfo->subctxt_cnt && !subctxt_fp(fp)) {
+ if (uinfo->subctxt_cnt && !fd->subctxt) {
ret = init_subctxts(uctxt, uinfo);
/*
* On error, we don't need to disable and de-allocate the
@@ -1041,7 +1035,7 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
spin_lock_init(&uctxt->sdma_qlock);
hfi1_stats.sps_ctxts++;
dd->freectxts--;
- ctxt_fp(fp) = uctxt;
+ fd->uctxt = uctxt;
return 0;
}
@@ -1105,7 +1099,8 @@ static int user_init(struct file *fp)
{
int ret;
unsigned int rcvctrl_ops = 0;
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
/* make sure that the context has already been setup */
if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags)) {
@@ -1117,7 +1112,7 @@ static int user_init(struct file *fp)
* Subctxts don't need to initialize anything since master
* has done it.
*/
- if (subctxt_fp(fp)) {
+ if (fd->subctxt) {
ret = wait_event_interruptible(uctxt->wait,
!test_bit(HFI1_CTXT_MASTER_UNINIT,
&uctxt->event_flags));
@@ -1177,8 +1172,8 @@ done:
static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
{
struct hfi1_ctxt_info cinfo;
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
int ret = 0;
memset(&cinfo, 0, sizeof(cinfo));
@@ -1188,7 +1183,7 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
cinfo.num_active = hfi1_count_active_units();
cinfo.unit = uctxt->dd->unit;
cinfo.ctxt = uctxt->ctxt;
- cinfo.subctxt = subctxt_fp(fp);
+ cinfo.subctxt = fd->subctxt;
cinfo.rcvtids = roundup(uctxt->egrbufs.alloced,
uctxt->dd->rcv_entries.group_size) +
uctxt->expected_count;
@@ -1200,10 +1195,10 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
cinfo.egrtids = uctxt->egrbufs.alloced;
cinfo.rcvhdrq_cnt = uctxt->rcvhdrq_cnt;
cinfo.rcvhdrq_entsize = uctxt->rcvhdrqentsize << 2;
- cinfo.sdma_ring_size = user_sdma_comp_fp(fp)->nentries;
+ cinfo.sdma_ring_size = fd->cq->nentries;
cinfo.rcvegr_size = uctxt->egrbufs.rcvtid_size;
- trace_hfi1_ctxt_info(uctxt->dd, uctxt->ctxt, subctxt_fp(fp), cinfo);
+ trace_hfi1_ctxt_info(uctxt->dd, uctxt->ctxt, fd->subctxt, cinfo);
if (copy_to_user(ubase, &cinfo, sizeof(cinfo)))
ret = -EFAULT;
done:
@@ -1212,7 +1207,8 @@ done:
static int setup_ctxt(struct file *fp)
{
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
int ret = 0;
@@ -1221,7 +1217,7 @@ static int setup_ctxt(struct file *fp)
* programming of eager buffers. This is done if context sharing
* is not requested or by the master process.
*/
- if (!uctxt->subctxt_cnt || !subctxt_fp(fp)) {
+ if (!uctxt->subctxt_cnt || !fd->subctxt) {
ret = hfi1_init_ctxt(uctxt->sc);
if (ret)
goto done;
@@ -1233,7 +1229,7 @@ static int setup_ctxt(struct file *fp)
ret = hfi1_setup_eagerbufs(uctxt);
if (ret)
goto done;
- if (uctxt->subctxt_cnt && !subctxt_fp(fp)) {
+ if (uctxt->subctxt_cnt && !fd->subctxt) {
ret = setup_subctxt(uctxt);
if (ret)
goto done;
@@ -1276,7 +1272,7 @@ static int setup_ctxt(struct file *fp)
uctxt->tidusemap[uctxt->tidmapcnt - 1] =
~((1ULL << (uctxt->numtidgroups %
BITS_PER_LONG)) - 1);
- trace_hfi1_exp_tid_map(uctxt->ctxt, subctxt_fp(fp), 0,
+ trace_hfi1_exp_tid_map(uctxt->ctxt, fd->subctxt, 0,
uctxt->tidusemap, uctxt->tidmapcnt);
}
ret = hfi1_user_sdma_alloc_queues(uctxt, fp);
@@ -1291,7 +1287,8 @@ done:
static int get_base_info(struct file *fp, void __user *ubase, __u32 len)
{
struct hfi1_base_info binfo;
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
ssize_t sz;
unsigned offset;
@@ -1313,50 +1310,50 @@ static int get_base_info(struct file *fp, void __user *ubase, __u32 len)
offset = ((u64)uctxt->sc->hw_free -
(u64)dd->cr_base[uctxt->numa_id].va) % PAGE_SIZE;
binfo.sc_credits_addr = HFI1_MMAP_TOKEN(PIO_CRED, uctxt->ctxt,
- subctxt_fp(fp), offset);
+ fd->subctxt, offset);
binfo.pio_bufbase = HFI1_MMAP_TOKEN(PIO_BUFS, uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
uctxt->sc->base_addr);
binfo.pio_bufbase_sop = HFI1_MMAP_TOKEN(PIO_BUFS_SOP,
uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
uctxt->sc->base_addr);
binfo.rcvhdr_bufbase = HFI1_MMAP_TOKEN(RCV_HDRQ, uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
uctxt->rcvhdrq);
binfo.rcvegr_bufbase = HFI1_MMAP_TOKEN(RCV_EGRBUF, uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
uctxt->egrbufs.rcvtids[0].phys);
binfo.sdma_comp_bufbase = HFI1_MMAP_TOKEN(SDMA_COMP, uctxt->ctxt,
- subctxt_fp(fp), 0);
+ fd->subctxt, 0);
/*
* user regs are at
* (RXE_PER_CONTEXT_USER + (ctxt * RXE_PER_CONTEXT_SIZE))
*/
binfo.user_regbase = HFI1_MMAP_TOKEN(UREGS, uctxt->ctxt,
- subctxt_fp(fp), 0);
+ fd->subctxt, 0);
offset = offset_in_page((((uctxt->ctxt - dd->first_user_ctxt) *
- HFI1_MAX_SHARED_CTXTS) + subctxt_fp(fp)) *
+ HFI1_MAX_SHARED_CTXTS) + fd->subctxt) *
sizeof(*dd->events));
binfo.events_bufbase = HFI1_MMAP_TOKEN(EVENTS, uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
offset);
binfo.status_bufbase = HFI1_MMAP_TOKEN(STATUS, uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
dd->status);
if (HFI1_CAP_IS_USET(DMA_RTAIL))
binfo.rcvhdrtail_base = HFI1_MMAP_TOKEN(RTAIL, uctxt->ctxt,
- subctxt_fp(fp), 0);
+ fd->subctxt, 0);
if (uctxt->subctxt_cnt) {
binfo.subctxt_uregbase = HFI1_MMAP_TOKEN(SUBCTXT_UREGS,
uctxt->ctxt,
- subctxt_fp(fp), 0);
+ fd->subctxt, 0);
binfo.subctxt_rcvhdrbuf = HFI1_MMAP_TOKEN(SUBCTXT_RCV_HDRQ,
uctxt->ctxt,
- subctxt_fp(fp), 0);
+ fd->subctxt, 0);
binfo.subctxt_rcvegrbuf = HFI1_MMAP_TOKEN(SUBCTXT_EGRBUF,
uctxt->ctxt,
- subctxt_fp(fp), 0);
+ fd->subctxt, 0);
}
sz = (len < sizeof(binfo)) ? len : sizeof(binfo);
if (copy_to_user(ubase, &binfo, sz))
@@ -1367,7 +1364,8 @@ static int get_base_info(struct file *fp, void __user *ubase, __u32 len)
static unsigned int poll_urgent(struct file *fp,
struct poll_table_struct *pt)
{
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
unsigned pollflag;
@@ -1389,7 +1387,8 @@ static unsigned int poll_urgent(struct file *fp,
static unsigned int poll_next(struct file *fp,
struct poll_table_struct *pt)
{
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
unsigned pollflag;
@@ -1561,7 +1560,8 @@ static inline unsigned num_free_groups(unsigned long map, u16 *start)
static int exp_tid_setup(struct file *fp, struct hfi1_tid_info *tinfo)
{
int ret = 0;
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
unsigned tid, mapped = 0, npages, ngroups, exp_groups,
tidpairs = uctxt->expected_count / 2;
@@ -1717,7 +1717,7 @@ static int exp_tid_setup(struct file *fp, struct hfi1_tid_info *tinfo)
pages[pmapped], 0,
tidsize, PCI_DMA_FROMDEVICE);
trace_hfi1_exp_rcv_set(uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
tid, vaddr,
phys[pmapped],
pages[pmapped]);
@@ -1762,7 +1762,7 @@ static int exp_tid_setup(struct file *fp, struct hfi1_tid_info *tinfo)
(((useidx & 0xffffff) << 16) |
((bitidx + bits_used) & 0xffffff)));
}
- trace_hfi1_exp_tid_map(uctxt->ctxt, subctxt_fp(fp), 0, uctxt->tidusemap,
+ trace_hfi1_exp_tid_map(uctxt->ctxt, fd->subctxt, 0, uctxt->tidusemap,
uctxt->tidmapcnt);
done:
@@ -1791,7 +1791,8 @@ bail:
static int exp_tid_free(struct file *fp, struct hfi1_tid_info *tinfo)
{
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
unsigned long tidmap[uctxt->tidmapcnt];
struct page **pages;
@@ -1827,7 +1828,7 @@ static int exp_tid_free(struct file *fp, struct hfi1_tid_info *tinfo)
hfi1_put_tid(dd, tid, PT_INVALID,
0, 0);
trace_hfi1_exp_rcv_free(uctxt->ctxt,
- subctxt_fp(fp),
+ fd->subctxt,
tid, phys[i],
pages[i]);
pci_unmap_page(dd->pcidev, phys[i],
@@ -1844,7 +1845,7 @@ static int exp_tid_free(struct file *fp, struct hfi1_tid_info *tinfo)
map &= ~(1ULL<<bitidx);
}
}
- trace_hfi1_exp_tid_map(uctxt->ctxt, subctxt_fp(fp), 1, uctxt->tidusemap,
+ trace_hfi1_exp_tid_map(uctxt->ctxt, fd->subctxt, 1, uctxt->tidusemap,
uctxt->tidmapcnt);
done:
return ret;
diff --git a/drivers/staging/rdma/hfi1/firmware.c b/drivers/staging/rdma/hfi1/firmware.c
index 5c2f2ed8f224..f3112821cf47 100644
--- a/drivers/staging/rdma/hfi1/firmware.c
+++ b/drivers/staging/rdma/hfi1/firmware.c
@@ -924,9 +924,6 @@ static int load_8051_firmware(struct hfi1_devdata *dd,
return 0;
}
-/* SBus Master broadcast address */
-#define SBUS_MASTER_BROADCAST 0xfd
-
/*
* Write the SBus request register
*
@@ -1239,34 +1236,20 @@ int load_firmware(struct hfi1_devdata *dd)
{
int ret;
- if (fw_sbus_load || fw_fabric_serdes_load) {
+ if (fw_fabric_serdes_load) {
ret = acquire_hw_mutex(dd);
if (ret)
return ret;
set_sbus_fast_mode(dd);
- /*
- * The SBus contains part of the fabric firmware and so must
- * also be downloaded.
- */
- if (fw_sbus_load) {
- turn_off_spicos(dd, SPICO_SBUS);
- ret = load_sbus_firmware(dd, &fw_sbus);
- if (ret)
- goto clear;
- }
-
- if (fw_fabric_serdes_load) {
- set_serdes_broadcast(dd, all_fabric_serdes_broadcast,
- fabric_serdes_broadcast[dd->hfi1_id],
- fabric_serdes_addrs[dd->hfi1_id],
- NUM_FABRIC_SERDES);
- turn_off_spicos(dd, SPICO_FABRIC);
- ret = load_fabric_serdes_firmware(dd, &fw_fabric);
- }
+ set_serdes_broadcast(dd, all_fabric_serdes_broadcast,
+ fabric_serdes_broadcast[dd->hfi1_id],
+ fabric_serdes_addrs[dd->hfi1_id],
+ NUM_FABRIC_SERDES);
+ turn_off_spicos(dd, SPICO_FABRIC);
+ ret = load_fabric_serdes_firmware(dd, &fw_fabric);
-clear:
clear_sbus_fast_mode(dd);
release_hw_mutex(dd);
if (ret)
@@ -1614,6 +1597,10 @@ done:
*/
void read_guid(struct hfi1_devdata *dd)
{
+ /* Take the DC out of reset to get a valid GUID value */
+ write_csr(dd, CCE_DC_CTRL, 0);
+ (void) read_csr(dd, CCE_DC_CTRL);
+
dd->base_guid = read_csr(dd, DC_DC8051_CFG_LOCAL_GUID);
dd_dev_info(dd, "GUID %llx",
(unsigned long long)dd->base_guid);
diff --git a/drivers/staging/rdma/hfi1/hfi.h b/drivers/staging/rdma/hfi1/hfi.h
index a35213e9b500..54ed6b36c1a7 100644
--- a/drivers/staging/rdma/hfi1/hfi.h
+++ b/drivers/staging/rdma/hfi1/hfi.h
@@ -100,6 +100,12 @@ extern unsigned long hfi1_cap_mask;
HFI1_CAP_MISC_MASK)
/*
+ * Control context is always 0 and handles the error packets.
+ * It also handles the VL15 and multicast packets.
+ */
+#define HFI1_CTRL_CTXT 0
+
+/*
* per driver stats, either not device nor port-specific, or
* summed over all of the devices and ports.
* They are described by name via ipathfs filesystem, so layout
@@ -139,15 +145,6 @@ extern const struct pci_error_handlers hfi1_pci_err_handler;
struct hfi1_opcode_stats_perctx;
#endif
-/*
- * struct ps_state keeps state associated with RX queue "prescanning"
- * (prescanning for FECNs, and BECNs), if prescanning is in use.
- */
-struct ps_state {
- u32 ps_head;
- int initialized;
-};
-
struct ctxt_eager_bufs {
ssize_t size; /* total size of eager buffers */
u32 count; /* size of buffers array */
@@ -243,7 +240,7 @@ struct hfi1_ctxtdata {
/* chip offset of PIO buffers for this ctxt */
u32 piobufs;
/* per-context configuration flags */
- u16 flags;
+ u32 flags;
/* per-context event flags for fileops/intr communication */
unsigned long event_flags;
/* WAIT_RCV that timed out, no interrupt */
@@ -302,10 +299,6 @@ struct hfi1_ctxtdata {
struct list_head sdma_queues;
spinlock_t sdma_qlock;
-#ifdef CONFIG_PRESCAN_RXQ
- struct ps_state ps_state;
-#endif /* CONFIG_PRESCAN_RXQ */
-
/*
* The interrupt handler for a particular receive context can vary
* throughout it's lifetime. This is not a lock protected data member so
@@ -313,7 +306,7 @@ struct hfi1_ctxtdata {
* be valid. Worst case is we process an extra interrupt and up to 64
* packets with the wrong interrupt handler.
*/
- void (*do_interrupt)(struct hfi1_ctxtdata *rcd);
+ int (*do_interrupt)(struct hfi1_ctxtdata *rcd, int threaded);
};
/*
@@ -1061,12 +1054,10 @@ struct hfi1_devdata {
* Handlers for outgoing data so that snoop/capture does not
* have to have its hooks in the send path
*/
- int (*process_pio_send)(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr,
- u32 hdrwords, struct hfi1_sge_state *ss,
- u32 len, u32 plen, u32 dwords, u64 pbc);
- int (*process_dma_send)(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr,
- u32 hdrwords, struct hfi1_sge_state *ss,
- u32 len, u32 plen, u32 dwords, u64 pbc);
+ int (*process_pio_send)(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc);
+ int (*process_dma_send)(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc);
void (*pio_inline_send)(struct hfi1_devdata *dd, struct pio_buf *pbuf,
u64 pbc, const void *from, size_t count);
@@ -1084,6 +1075,10 @@ struct hfi1_devdata {
/* Save the enabled LCB error bits */
u64 lcb_err_en;
u8 dc_shutdown;
+
+ /* receive context tail dummy address */
+ __le64 *rcvhdrtail_dummy_kvaddr;
+ dma_addr_t rcvhdrtail_dummy_physaddr;
};
/* 8051 firmware version helper */
@@ -1130,9 +1125,21 @@ void hfi1_init_pportdata(struct pci_dev *, struct hfi1_pportdata *,
struct hfi1_devdata *, u8, u8);
void hfi1_free_ctxtdata(struct hfi1_devdata *, struct hfi1_ctxtdata *);
-void handle_receive_interrupt(struct hfi1_ctxtdata *);
-void handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd);
-void handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd);
+int handle_receive_interrupt(struct hfi1_ctxtdata *, int);
+int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *, int);
+int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *, int);
+
+/* receive packet handler dispositions */
+#define RCV_PKT_OK 0x0 /* keep going */
+#define RCV_PKT_LIMIT 0x1 /* stop, hit limit, start thread */
+#define RCV_PKT_DONE 0x2 /* stop, no more packets detected */
+
+/* calculate the current RHF address */
+static inline __le32 *get_rhf_addr(struct hfi1_ctxtdata *rcd)
+{
+ return (__le32 *)rcd->rcvhdrq + rcd->head + rcd->dd->rhf_offset;
+}
+
int hfi1_reset_device(int);
/* return the driver's idea of the logical OPA port state */
@@ -1402,27 +1409,13 @@ void reset_link_credits(struct hfi1_devdata *dd);
void assign_remote_cm_au_table(struct hfi1_devdata *dd, u8 vcu);
int snoop_recv_handler(struct hfi1_packet *packet);
-int snoop_send_dma_handler(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc);
-int snoop_send_pio_handler(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc);
+int snoop_send_dma_handler(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc);
+int snoop_send_pio_handler(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc);
void snoop_inline_pio_send(struct hfi1_devdata *dd, struct pio_buf *pbuf,
u64 pbc, const void *from, size_t count);
-/* for use in system calls, where we want to know device type, etc. */
-#define ctxt_fp(fp) \
- (((struct hfi1_filedata *)(fp)->private_data)->uctxt)
-#define subctxt_fp(fp) \
- (((struct hfi1_filedata *)(fp)->private_data)->subctxt)
-#define tidcursor_fp(fp) \
- (((struct hfi1_filedata *)(fp)->private_data)->tidcursor)
-#define user_sdma_pkt_fp(fp) \
- (((struct hfi1_filedata *)(fp)->private_data)->pq)
-#define user_sdma_comp_fp(fp) \
- (((struct hfi1_filedata *)(fp)->private_data)->cq)
-
static inline struct hfi1_devdata *dd_from_ppd(struct hfi1_pportdata *ppd)
{
return ppd->dd;
@@ -1600,7 +1593,6 @@ void hfi1_pcie_flr(struct hfi1_devdata *);
int pcie_speeds(struct hfi1_devdata *);
void request_msix(struct hfi1_devdata *, u32 *, struct hfi1_msix_entry *);
void hfi1_enable_intx(struct pci_dev *);
-void hfi1_nomsix(struct hfi1_devdata *);
void restore_pci_variables(struct hfi1_devdata *dd);
int do_pcie_gen3_transition(struct hfi1_devdata *dd);
int parse_platform_config(struct hfi1_devdata *dd);
diff --git a/drivers/staging/rdma/hfi1/init.c b/drivers/staging/rdma/hfi1/init.c
index cd1508ec0914..1c8286f4c00c 100644
--- a/drivers/staging/rdma/hfi1/init.c
+++ b/drivers/staging/rdma/hfi1/init.c
@@ -60,6 +60,7 @@
#include "hfi.h"
#include "device.h"
#include "common.h"
+#include "trace.h"
#include "mad.h"
#include "sdma.h"
#include "debugfs.h"
@@ -89,7 +90,7 @@ MODULE_PARM_DESC(
u8 krcvqs[RXE_NUM_DATA_VL];
int krcvqsset;
module_param_array(krcvqs, byte, &krcvqsset, S_IRUGO);
-MODULE_PARM_DESC(krcvqs, "Array of the number of kernel receive queues by VL");
+MODULE_PARM_DESC(krcvqs, "Array of the number of non-control kernel receive queues by VL");
/* computed based on above array */
unsigned n_krcvqs;
@@ -129,6 +130,9 @@ int hfi1_create_ctxts(struct hfi1_devdata *dd)
int ret;
int local_node_id = pcibus_to_node(dd->pcidev->bus);
+ /* Control context has to be always 0 */
+ BUILD_BUG_ON(HFI1_CTRL_CTXT != 0);
+
if (local_node_id < 0)
local_node_id = numa_node_id();
dd->assigned_node_id = local_node_id;
@@ -158,6 +162,10 @@ int hfi1_create_ctxts(struct hfi1_devdata *dd)
HFI1_CAP_KGET(NODROP_RHQ_FULL) |
HFI1_CAP_KGET(NODROP_EGR_FULL) |
HFI1_CAP_KGET(DMA_RTAIL);
+
+ /* Control context must use DMA_RTAIL */
+ if (rcd->ctxt == HFI1_CTRL_CTXT)
+ rcd->flags |= HFI1_CAP_DMA_RTAIL;
rcd->seq_cnt = 1;
rcd->sc = sc_alloc(dd, SC_ACK, rcd->rcvhdrqentsize, dd->node);
@@ -208,7 +216,7 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt)
if (rcd) {
u32 rcvtids, max_entries;
- dd_dev_info(dd, "%s: setting up context %u\n", __func__, ctxt);
+ hfi1_cdbg(PROC, "setting up context %u\n", ctxt);
INIT_LIST_HEAD(&rcd->qp_wait_list);
rcd->ppd = ppd;
@@ -279,8 +287,9 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt)
rcd->ctxt);
rcd->egrbufs.count = MAX_EAGER_ENTRIES;
}
- dd_dev_info(dd, "ctxt%u: max Eager buffer RcvArray entries: %u\n",
- rcd->ctxt, rcd->egrbufs.count);
+ hfi1_cdbg(PROC,
+ "ctxt%u: max Eager buffer RcvArray entries: %u\n",
+ rcd->ctxt, rcd->egrbufs.count);
/*
* Allocate array that will hold the eager buffer accounting
@@ -308,8 +317,8 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt)
*/
if (rcd->egrbufs.size < hfi1_max_mtu) {
rcd->egrbufs.size = __roundup_pow_of_two(hfi1_max_mtu);
- dd_dev_info(dd,
- "ctxt%u: eager bufs size too small. Adjusting to %zu\n",
+ hfi1_cdbg(PROC,
+ "ctxt%u: eager bufs size too small. Adjusting to %zu\n",
rcd->ctxt, rcd->egrbufs.size);
}
rcd->egrbufs.rcvtid_size = HFI1_MAX_EAGER_BUFFER_SIZE;
@@ -413,6 +422,7 @@ static enum hrtimer_restart cca_timer_fn(struct hrtimer *t)
int sl;
u16 ccti, ccti_timer, ccti_min;
struct cc_state *cc_state;
+ unsigned long flags;
cca_timer = container_of(t, struct cca_timer, hrtimer);
ppd = cca_timer->ppd;
@@ -436,7 +446,7 @@ static enum hrtimer_restart cca_timer_fn(struct hrtimer *t)
ccti_min = cc_state->cong_setting.entries[sl].ccti_min;
ccti_timer = cc_state->cong_setting.entries[sl].ccti_timer;
- spin_lock(&ppd->cca_timer_lock);
+ spin_lock_irqsave(&ppd->cca_timer_lock, flags);
ccti = cca_timer->ccti;
@@ -445,7 +455,7 @@ static enum hrtimer_restart cca_timer_fn(struct hrtimer *t)
set_link_ipg(ppd);
}
- spin_unlock(&ppd->cca_timer_lock);
+ spin_unlock_irqrestore(&ppd->cca_timer_lock, flags);
rcu_read_unlock();
@@ -600,20 +610,19 @@ static int create_workqueues(struct hfi1_devdata *dd)
for (pidx = 0; pidx < dd->num_pports; ++pidx) {
ppd = dd->pport + pidx;
if (!ppd->hfi1_wq) {
- char wq_name[8]; /* 3 + 2 + 1 + 1 + 1 */
-
- snprintf(wq_name, sizeof(wq_name), "hfi%d_%d",
- dd->unit, pidx);
ppd->hfi1_wq =
- create_singlethread_workqueue(wq_name);
+ alloc_workqueue(
+ "hfi%d_%d",
+ WQ_SYSFS | WQ_HIGHPRI | WQ_CPU_INTENSIVE,
+ dd->num_sdma,
+ dd->unit, pidx);
if (!ppd->hfi1_wq)
goto wq_error;
}
}
return 0;
wq_error:
- pr_err("create_singlethread_workqueue failed for port %d\n",
- pidx + 1);
+ pr_err("alloc_workqueue failed for port %d\n", pidx + 1);
for (pidx = 0; pidx < dd->num_pports; ++pidx) {
ppd = dd->pport + pidx;
if (ppd->hfi1_wq) {
@@ -690,6 +699,18 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit)
if (ret)
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_physaddr,
+ GFP_KERNEL);
+
+ if (!dd->rcvhdrtail_dummy_kvaddr) {
+ dd_dev_err(dd, "cannot allocate dummy tail memory\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
/* dd->rcd can be NULL if early initialization failed */
for (i = 0; dd->rcd && i < dd->first_user_ctxt; ++i) {
/*
@@ -1265,6 +1286,14 @@ static void cleanup_device_data(struct hfi1_devdata *dd)
tmp = dd->rcd;
dd->rcd = NULL;
spin_unlock_irqrestore(&dd->uctxt_lock, flags);
+
+ if (dd->rcvhdrtail_dummy_kvaddr) {
+ dma_free_coherent(&dd->pcidev->dev, sizeof(u64),
+ (void *)dd->rcvhdrtail_dummy_kvaddr,
+ dd->rcvhdrtail_dummy_physaddr);
+ dd->rcvhdrtail_dummy_kvaddr = NULL;
+ }
+
for (ctxt = 0; tmp && ctxt < dd->num_rcv_contexts; ctxt++) {
struct hfi1_ctxtdata *rcd = tmp[ctxt];
@@ -1520,6 +1549,14 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
reg = (dd->rcvhdrsize & RCV_HDR_SIZE_HDR_SIZE_MASK)
<< RCV_HDR_SIZE_HDR_SIZE_SHIFT;
write_kctxt_csr(dd, rcd->ctxt, RCV_HDR_SIZE, reg);
+
+ /*
+ * Program dummy tail address for every receive context
+ * before enabling any receive context
+ */
+ write_kctxt_csr(dd, rcd->ctxt, RCV_HDR_TAIL_ADDR,
+ dd->rcvhdrtail_dummy_physaddr);
+
return 0;
bail_free:
@@ -1559,7 +1596,7 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
* heavy filesystem activity makes these fail, and we can
* use compound pages.
*/
- gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP;
+ gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP;
/*
* The minimum size of the eager buffers is a groups of MTU-sized
@@ -1659,9 +1696,11 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
rcd->egrbufs.numbufs = idx;
rcd->egrbufs.size = alloced_bytes;
- dd_dev_info(dd, "ctxt%u: Alloced %u rcv tid entries @ %uKB, total %zuKB\n",
- rcd->ctxt, rcd->egrbufs.alloced, rcd->egrbufs.rcvtid_size,
- rcd->egrbufs.size);
+ hfi1_cdbg(PROC,
+ "ctxt%u: Alloced %u rcv tid entries @ %uKB, total %zuKB\n",
+ rcd->ctxt, rcd->egrbufs.alloced, rcd->egrbufs.rcvtid_size,
+ rcd->egrbufs.size);
+
/*
* Set the contexts rcv array head update threshold to the closest
@@ -1682,13 +1721,14 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
rcd->expected_count = MAX_TID_PAIR_ENTRIES * 2;
rcd->expected_base = rcd->eager_base + egrtop;
- dd_dev_info(dd, "ctxt%u: eager:%u, exp:%u, egrbase:%u, expbase:%u\n",
- rcd->ctxt, rcd->egrbufs.alloced, rcd->expected_count,
- rcd->eager_base, rcd->expected_base);
+ hfi1_cdbg(PROC, "ctxt%u: eager:%u, exp:%u, egrbase:%u, expbase:%u\n",
+ rcd->ctxt, rcd->egrbufs.alloced, rcd->expected_count,
+ rcd->eager_base, rcd->expected_base);
if (!hfi1_rcvbuf_validate(rcd->egrbufs.rcvtid_size, PT_EAGER, &order)) {
- dd_dev_err(dd, "ctxt%u: current Eager buffer size is invalid %u\n",
- rcd->ctxt, rcd->egrbufs.rcvtid_size);
+ hfi1_cdbg(PROC,
+ "ctxt%u: current Eager buffer size is invalid %u\n",
+ rcd->ctxt, rcd->egrbufs.rcvtid_size);
ret = -EINVAL;
goto bail;
}
diff --git a/drivers/staging/rdma/hfi1/iowait.h b/drivers/staging/rdma/hfi1/iowait.h
index fa361b405851..e8ba5606d08d 100644
--- a/drivers/staging/rdma/hfi1/iowait.h
+++ b/drivers/staging/rdma/hfi1/iowait.h
@@ -150,12 +150,14 @@ static inline void iowait_init(
* iowait_schedule() - initialize wait structure
* @wait: wait struct to schedule
* @wq: workqueue for schedule
+ * @cpu: cpu
*/
static inline void iowait_schedule(
struct iowait *wait,
- struct workqueue_struct *wq)
+ struct workqueue_struct *wq,
+ int cpu)
{
- queue_work(wq, &wait->iowork);
+ queue_work_on(cpu, wq, &wait->iowork);
}
/**
diff --git a/drivers/staging/rdma/hfi1/keys.c b/drivers/staging/rdma/hfi1/keys.c
index f6eff177ace1..cb4e6087dfdb 100644
--- a/drivers/staging/rdma/hfi1/keys.c
+++ b/drivers/staging/rdma/hfi1/keys.c
@@ -354,58 +354,3 @@ bail:
rcu_read_unlock();
return 0;
}
-
-/*
- * Initialize the memory region specified by the work request.
- */
-int hfi1_fast_reg_mr(struct hfi1_qp *qp, struct ib_send_wr *wr)
-{
- struct hfi1_lkey_table *rkt = &to_idev(qp->ibqp.device)->lk_table;
- struct hfi1_pd *pd = to_ipd(qp->ibqp.pd);
- struct hfi1_mregion *mr;
- u32 rkey = wr->wr.fast_reg.rkey;
- unsigned i, n, m;
- int ret = -EINVAL;
- unsigned long flags;
- u64 *page_list;
- size_t ps;
-
- spin_lock_irqsave(&rkt->lock, flags);
- if (pd->user || rkey == 0)
- goto bail;
-
- mr = rcu_dereference_protected(
- rkt->table[(rkey >> (32 - hfi1_lkey_table_size))],
- lockdep_is_held(&rkt->lock));
- if (unlikely(mr == NULL || qp->ibqp.pd != mr->pd))
- goto bail;
-
- if (wr->wr.fast_reg.page_list_len > mr->max_segs)
- goto bail;
-
- ps = 1UL << wr->wr.fast_reg.page_shift;
- if (wr->wr.fast_reg.length > ps * wr->wr.fast_reg.page_list_len)
- goto bail;
-
- mr->user_base = wr->wr.fast_reg.iova_start;
- mr->iova = wr->wr.fast_reg.iova_start;
- mr->lkey = rkey;
- mr->length = wr->wr.fast_reg.length;
- mr->access_flags = wr->wr.fast_reg.access_flags;
- page_list = wr->wr.fast_reg.page_list->page_list;
- m = 0;
- n = 0;
- for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
- mr->map[m]->segs[n].vaddr = (void *) page_list[i];
- mr->map[m]->segs[n].length = ps;
- if (++n == HFI1_SEGSZ) {
- m++;
- n = 0;
- }
- }
-
- ret = 0;
-bail:
- spin_unlock_irqrestore(&rkt->lock, flags);
- return ret;
-}
diff --git a/drivers/staging/rdma/hfi1/mad.c b/drivers/staging/rdma/hfi1/mad.c
index 1de282c989b0..a1225651005c 100644
--- a/drivers/staging/rdma/hfi1/mad.c
+++ b/drivers/staging/rdma/hfi1/mad.c
@@ -3257,7 +3257,7 @@ static int __subn_get_opa_hfi1_cong_log(struct opa_smp *smp, u32 am,
return reply((struct ib_mad_hdr *)smp);
}
- spin_lock(&ppd->cc_log_lock);
+ spin_lock_irq(&ppd->cc_log_lock);
cong_log->log_type = OPA_CC_LOG_TYPE_HFI;
cong_log->congestion_flags = 0;
@@ -3300,7 +3300,7 @@ static int __subn_get_opa_hfi1_cong_log(struct opa_smp *smp, u32 am,
sizeof(ppd->threshold_cong_event_map));
ppd->threshold_event_counter = 0;
- spin_unlock(&ppd->cc_log_lock);
+ spin_unlock_irq(&ppd->cc_log_lock);
if (resp_len)
*resp_len += sizeof(struct opa_hfi1_cong_log);
@@ -3458,7 +3458,7 @@ static int __subn_get_opa_led_info(struct opa_smp *smp, u32 am, u8 *data,
u32 nport = OPA_AM_NPORT(am);
u64 reg;
- if (nport != 1 || OPA_AM_PORTNUM(am)) {
+ if (nport != 1) {
smp->status |= IB_SMP_INVALID_FIELD;
return reply((struct ib_mad_hdr *)smp);
}
@@ -3483,7 +3483,7 @@ static int __subn_set_opa_led_info(struct opa_smp *smp, u32 am, u8 *data,
u32 nport = OPA_AM_NPORT(am);
int on = !!(be32_to_cpu(p->rsvd_led_mask) & OPA_LED_MASK);
- if (nport != 1 || OPA_AM_PORTNUM(am)) {
+ if (nport != 1) {
smp->status |= IB_SMP_INVALID_FIELD;
return reply((struct ib_mad_hdr *)smp);
}
diff --git a/drivers/staging/rdma/hfi1/mr.c b/drivers/staging/rdma/hfi1/mr.c
index 0208fc200c1a..568f185a022d 100644
--- a/drivers/staging/rdma/hfi1/mr.c
+++ b/drivers/staging/rdma/hfi1/mr.c
@@ -344,9 +344,10 @@ out:
/*
* Allocate a memory region usable with the
- * IB_WR_FAST_REG_MR send work request.
+ * IB_WR_REG_MR send work request.
*
* Return the memory region on success, otherwise return an errno.
+ * FIXME: IB_WR_REG_MR is not supported
*/
struct ib_mr *hfi1_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
@@ -364,36 +365,6 @@ struct ib_mr *hfi1_alloc_mr(struct ib_pd *pd,
return &mr->ibmr;
}
-struct ib_fast_reg_page_list *
-hfi1_alloc_fast_reg_page_list(struct ib_device *ibdev, int page_list_len)
-{
- unsigned size = page_list_len * sizeof(u64);
- struct ib_fast_reg_page_list *pl;
-
- if (size > PAGE_SIZE)
- return ERR_PTR(-EINVAL);
-
- pl = kzalloc(sizeof(*pl), GFP_KERNEL);
- if (!pl)
- return ERR_PTR(-ENOMEM);
-
- pl->page_list = kzalloc(size, GFP_KERNEL);
- if (!pl->page_list)
- goto err_free;
-
- return pl;
-
-err_free:
- kfree(pl);
- return ERR_PTR(-ENOMEM);
-}
-
-void hfi1_free_fast_reg_page_list(struct ib_fast_reg_page_list *pl)
-{
- kfree(pl->page_list);
- kfree(pl);
-}
-
/**
* hfi1_alloc_fmr - allocate a fast memory region
* @pd: the protection domain for this memory region
diff --git a/drivers/staging/rdma/hfi1/pcie.c b/drivers/staging/rdma/hfi1/pcie.c
index ac5653c0f65e..0b7eafb0fc70 100644
--- a/drivers/staging/rdma/hfi1/pcie.c
+++ b/drivers/staging/rdma/hfi1/pcie.c
@@ -426,14 +426,6 @@ void request_msix(struct hfi1_devdata *dd, u32 *nent,
tune_pcie_caps(dd);
}
-/*
- * Disable MSI-X.
- */
-void hfi1_nomsix(struct hfi1_devdata *dd)
-{
- pci_disable_msix(dd->pcidev);
-}
-
void hfi1_enable_intx(struct pci_dev *pdev)
{
/* first, turn on INTx */
@@ -475,8 +467,18 @@ static void tune_pcie_caps(struct hfi1_devdata *dd)
{
struct pci_dev *parent;
u16 rc_mpss, rc_mps, ep_mpss, ep_mps;
- u16 rc_mrrs, ep_mrrs, max_mrrs;
+ u16 rc_mrrs, ep_mrrs, max_mrrs, ectl;
+ /*
+ * Turn on extended tags in DevCtl in case the BIOS has turned it off
+ * to improve WFR SDMA bandwidth
+ */
+ pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &ectl);
+ if (!(ectl & PCI_EXP_DEVCTL_EXT_TAG)) {
+ dd_dev_info(dd, "Enabling PCIe extended tags\n");
+ ectl |= PCI_EXP_DEVCTL_EXT_TAG;
+ pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl);
+ }
/* Find out supported and configured values for parent (root) */
parent = dd->pcidev->bus->self;
if (!pci_is_root_bus(parent->bus)) {
@@ -946,9 +948,11 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd)
__func__);
}
+retry:
+ /* the SBus download will reset the spico for thermal */
+
/* step 3: download SBus Master firmware */
/* step 4: download PCIe Gen3 SerDes firmware */
-retry:
dd_dev_info(dd, "%s: downloading firmware\n", __func__);
ret = load_pcie_firmware(dd);
if (ret)
@@ -1187,6 +1191,7 @@ retry:
/* clear the DC reset */
write_csr(dd, CCE_DC_CTRL, 0);
+
/* Set the LED off */
if (is_a0(dd))
setextled(dd, 0);
diff --git a/drivers/staging/rdma/hfi1/pio.c b/drivers/staging/rdma/hfi1/pio.c
index 67dd93a6888c..eab58c12d915 100644
--- a/drivers/staging/rdma/hfi1/pio.c
+++ b/drivers/staging/rdma/hfi1/pio.c
@@ -815,15 +815,16 @@ struct send_context *sc_alloc(struct hfi1_devdata *dd, int type,
}
}
- dd_dev_info(dd,
- "Send context %u(%u) %s group %u credits %u credit_ctrl 0x%llx threshold %u\n",
- sw_index,
- hw_context,
- sc_type_name(type),
- sc->group,
- sc->credits,
- sc->credit_ctrl,
- thresh);
+ hfi1_cdbg(PIO,
+ "Send context %u(%u) %s group %u credits %u credit_ctrl 0x%llx threshold %u\n",
+ sw_index,
+ hw_context,
+ sc_type_name(type),
+ sc->group,
+ sc->credits,
+ sc->credit_ctrl,
+ thresh);
+
return sc;
}
@@ -922,10 +923,12 @@ void sc_disable(struct send_context *sc)
static void sc_wait_for_packet_egress(struct send_context *sc, int pause)
{
struct hfi1_devdata *dd = sc->dd;
- u64 reg;
+ u64 reg = 0;
+ u64 reg_prev;
u32 loop = 0;
while (1) {
+ reg_prev = reg;
reg = read_csr(dd, sc->hw_context * 8 +
SEND_EGRESS_CTXT_STATUS);
/* done if egress is stopped */
@@ -934,11 +937,17 @@ static void sc_wait_for_packet_egress(struct send_context *sc, int pause)
reg = packet_occupancy(reg);
if (reg == 0)
break;
- if (loop > 100) {
+ /* counter is reset if occupancy count changes */
+ if (reg != reg_prev)
+ loop = 0;
+ if (loop > 500) {
+ /* timed out - bounce the link */
dd_dev_err(dd,
- "%s: context %u(%u) timeout waiting for packets to egress, remaining count %u\n",
+ "%s: context %u(%u) timeout waiting for packets to egress, remaining count %u, bouncing link\n",
__func__, sc->sw_index,
sc->hw_context, (u32)reg);
+ queue_work(dd->pport->hfi1_wq,
+ &dd->pport->link_bounce_work);
break;
}
loop++;
diff --git a/drivers/staging/rdma/hfi1/qp.c b/drivers/staging/rdma/hfi1/qp.c
index df1fa56eaf85..ce036810d576 100644
--- a/drivers/staging/rdma/hfi1/qp.c
+++ b/drivers/staging/rdma/hfi1/qp.c
@@ -378,6 +378,7 @@ static void reset_qp(struct hfi1_qp *qp, enum ib_qp_type type)
}
qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
qp->r_nak_state = 0;
+ qp->r_adefered = 0;
qp->r_aflags = 0;
qp->r_flags = 0;
qp->s_head = 0;
@@ -422,7 +423,7 @@ static void clear_mr_refs(struct hfi1_qp *qp, int clr_sends)
if (qp->ibqp.qp_type == IB_QPT_UD ||
qp->ibqp.qp_type == IB_QPT_SMI ||
qp->ibqp.qp_type == IB_QPT_GSI)
- atomic_dec(&to_iah(wqe->wr.wr.ud.ah)->refcount);
+ atomic_dec(&to_iah(wqe->ud_wr.ah)->refcount);
if (++qp->s_last >= qp->s_size)
qp->s_last = 0;
}
@@ -617,7 +618,7 @@ int hfi1_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int mig = 0;
int ret;
u32 pmtu = 0; /* for gcc warning only */
- struct hfi1_devdata *dd;
+ struct hfi1_devdata *dd = dd_from_dev(dev);
spin_lock_irq(&qp->r_lock);
spin_lock(&qp->s_lock);
@@ -631,23 +632,35 @@ int hfi1_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
goto inval;
if (attr_mask & IB_QP_AV) {
+ u8 sc;
+
if (attr->ah_attr.dlid >= HFI1_MULTICAST_LID_BASE)
goto inval;
if (hfi1_check_ah(qp->ibqp.device, &attr->ah_attr))
goto inval;
+ sc = ah_to_sc(ibqp->device, &attr->ah_attr);
+ if (!qp_to_sdma_engine(qp, sc) &&
+ dd->flags & HFI1_HAS_SEND_DMA)
+ goto inval;
}
if (attr_mask & IB_QP_ALT_PATH) {
+ u8 sc;
+
if (attr->alt_ah_attr.dlid >= HFI1_MULTICAST_LID_BASE)
goto inval;
if (hfi1_check_ah(qp->ibqp.device, &attr->alt_ah_attr))
goto inval;
- if (attr->alt_pkey_index >= hfi1_get_npkeys(dd_from_dev(dev)))
+ if (attr->alt_pkey_index >= hfi1_get_npkeys(dd))
+ goto inval;
+ sc = ah_to_sc(ibqp->device, &attr->alt_ah_attr);
+ if (!qp_to_sdma_engine(qp, sc) &&
+ dd->flags & HFI1_HAS_SEND_DMA)
goto inval;
}
if (attr_mask & IB_QP_PKEY_INDEX)
- if (attr->pkey_index >= hfi1_get_npkeys(dd_from_dev(dev)))
+ if (attr->pkey_index >= hfi1_get_npkeys(dd))
goto inval;
if (attr_mask & IB_QP_MIN_RNR_TIMER)
@@ -792,6 +805,8 @@ int hfi1_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
qp->remote_ah_attr = attr->ah_attr;
qp->s_srate = attr->ah_attr.static_rate;
qp->srate_mbps = ib_rate_to_mbps(qp->s_srate);
+ qp->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr);
+ qp->s_sde = qp_to_sdma_engine(qp, qp->s_sc);
}
if (attr_mask & IB_QP_ALT_PATH) {
@@ -806,6 +821,8 @@ int hfi1_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
qp->port_num = qp->alt_ah_attr.port_num;
qp->s_pkey_index = qp->s_alt_pkey_index;
qp->s_flags |= HFI1_S_AHG_CLEAR;
+ qp->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr);
+ qp->s_sde = qp_to_sdma_engine(qp, qp->s_sc);
}
}
@@ -1528,9 +1545,6 @@ struct sdma_engine *qp_to_sdma_engine(struct hfi1_qp *qp, u8 sc5)
if (!(dd->flags & HFI1_HAS_SEND_DMA))
return NULL;
switch (qp->ibqp.qp_type) {
- case IB_QPT_UC:
- case IB_QPT_RC:
- break;
case IB_QPT_SMI:
return NULL;
default:
@@ -1685,3 +1699,25 @@ void qp_comm_est(struct hfi1_qp *qp)
qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
}
}
+
+/*
+ * Switch to alternate path.
+ * The QP s_lock should be held and interrupts disabled.
+ */
+void hfi1_migrate_qp(struct hfi1_qp *qp)
+{
+ struct ib_event ev;
+
+ qp->s_mig_state = IB_MIG_MIGRATED;
+ qp->remote_ah_attr = qp->alt_ah_attr;
+ qp->port_num = qp->alt_ah_attr.port_num;
+ qp->s_pkey_index = qp->s_alt_pkey_index;
+ qp->s_flags |= HFI1_S_AHG_CLEAR;
+ qp->s_sc = ah_to_sc(qp->ibqp.device, &qp->remote_ah_attr);
+ qp->s_sde = qp_to_sdma_engine(qp, qp->s_sc);
+
+ ev.device = qp->ibqp.device;
+ ev.element.qp = &qp->ibqp;
+ ev.event = IB_EVENT_PATH_MIG;
+ qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
+}
diff --git a/drivers/staging/rdma/hfi1/qp.h b/drivers/staging/rdma/hfi1/qp.h
index 6b505859b59c..94fd748a00a6 100644
--- a/drivers/staging/rdma/hfi1/qp.h
+++ b/drivers/staging/rdma/hfi1/qp.h
@@ -52,6 +52,7 @@
#include <linux/hash.h>
#include "verbs.h"
+#include "sdma.h"
#define QPN_MAX (1 << 24)
#define QPNMAP_ENTRIES (QPN_MAX / PAGE_SIZE / BITS_PER_BYTE)
@@ -117,6 +118,19 @@ static inline struct hfi1_qp *hfi1_lookup_qpn(struct hfi1_ibport *ibp,
}
/**
+ * clear_ahg - reset ahg status in qp
+ * @qp - qp pointer
+ */
+static inline void clear_ahg(struct hfi1_qp *qp)
+{
+ qp->s_hdr->ahgcount = 0;
+ qp->s_flags &= ~(HFI1_S_AHG_VALID | HFI1_S_AHG_CLEAR);
+ if (qp->s_sde && qp->s_ahgidx >= 0)
+ sdma_ahg_free(qp->s_sde, qp->s_ahgidx);
+ qp->s_ahgidx = -1;
+}
+
+/**
* hfi1_error_qp - put a QP into the error state
* @qp: the QP to put into the error state
* @err: the receive completion error to signal if a RWQE is active
@@ -232,4 +246,41 @@ void qp_iter_print(struct seq_file *s, struct qp_iter *iter);
*/
void qp_comm_est(struct hfi1_qp *qp);
+/**
+ * _hfi1_schedule_send - schedule progress
+ * @qp: the QP
+ *
+ * This schedules qp progress w/o regard to the s_flags.
+ *
+ * It is only used in the post send, which doesn't hold
+ * the s_lock.
+ */
+static inline void _hfi1_schedule_send(struct hfi1_qp *qp)
+{
+ struct hfi1_ibport *ibp =
+ to_iport(qp->ibqp.device, qp->port_num);
+ struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+ struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);
+
+ iowait_schedule(&qp->s_iowait, ppd->hfi1_wq,
+ qp->s_sde ?
+ qp->s_sde->cpu :
+ cpumask_first(cpumask_of_node(dd->assigned_node_id)));
+}
+
+/**
+ * hfi1_schedule_send - schedule progress
+ * @qp: the QP
+ *
+ * This schedules qp progress and caller should hold
+ * the s_lock.
+ */
+static inline void hfi1_schedule_send(struct hfi1_qp *qp)
+{
+ if (hfi1_send_ok(qp))
+ _hfi1_schedule_send(qp);
+}
+
+void hfi1_migrate_qp(struct hfi1_qp *qp);
+
#endif /* _QP_H */
diff --git a/drivers/staging/rdma/hfi1/qsfp.c b/drivers/staging/rdma/hfi1/qsfp.c
index 3138936157db..6326a915d7fd 100644
--- a/drivers/staging/rdma/hfi1/qsfp.c
+++ b/drivers/staging/rdma/hfi1/qsfp.c
@@ -403,16 +403,11 @@ static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
int qsfp_mod_present(struct hfi1_pportdata *ppd)
{
- if (HFI1_CAP_IS_KSET(QSFP_ENABLED)) {
- struct hfi1_devdata *dd = ppd->dd;
- u64 reg;
+ struct hfi1_devdata *dd = ppd->dd;
+ u64 reg;
- reg = read_csr(dd,
- dd->hfi1_id ? ASIC_QSFP2_IN : ASIC_QSFP1_IN);
- return !(reg & QSFP_HFI0_MODPRST_N);
- }
- /* always return cable present */
- return 1;
+ reg = read_csr(dd, dd->hfi1_id ? ASIC_QSFP2_IN : ASIC_QSFP1_IN);
+ return !(reg & QSFP_HFI0_MODPRST_N);
}
/*
@@ -480,7 +475,7 @@ int qsfp_dump(struct hfi1_pportdata *ppd, char *buf, int len)
u8 *cache = &ppd->qsfp_info.cache[0];
u8 bin_buff[QSFP_DUMP_CHUNK];
char lenstr[6];
- int sofar, ret;
+ int sofar;
int bidx = 0;
u8 *atten = &cache[QSFP_ATTEN_OFFS];
u8 *vendor_oui = &cache[QSFP_VOUI_OFFS];
@@ -541,6 +536,5 @@ int qsfp_dump(struct hfi1_pportdata *ppd, char *buf, int len)
bidx += QSFP_DUMP_CHUNK;
}
}
- ret = sofar;
- return ret;
+ return sofar;
}
diff --git a/drivers/staging/rdma/hfi1/rc.c b/drivers/staging/rdma/hfi1/rc.c
index 1e9caebb0281..6f4a155f7931 100644
--- a/drivers/staging/rdma/hfi1/rc.c
+++ b/drivers/staging/rdma/hfi1/rc.c
@@ -404,9 +404,9 @@ int hfi1_make_rc_req(struct hfi1_qp *qp)
goto bail;
}
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
hwords += sizeof(struct ib_reth) / sizeof(u32);
wqe->lpsn = wqe->psn;
@@ -455,9 +455,9 @@ int hfi1_make_rc_req(struct hfi1_qp *qp)
wqe->lpsn = qp->s_next_psn++;
}
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
qp->s_state = OP(RDMA_READ_REQUEST);
hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32);
@@ -488,21 +488,21 @@ int hfi1_make_rc_req(struct hfi1_qp *qp)
if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
qp->s_state = OP(COMPARE_SWAP);
ohdr->u.atomic_eth.swap_data = cpu_to_be64(
- wqe->wr.wr.atomic.swap);
+ wqe->atomic_wr.swap);
ohdr->u.atomic_eth.compare_data = cpu_to_be64(
- wqe->wr.wr.atomic.compare_add);
+ wqe->atomic_wr.compare_add);
} else {
qp->s_state = OP(FETCH_ADD);
ohdr->u.atomic_eth.swap_data = cpu_to_be64(
- wqe->wr.wr.atomic.compare_add);
+ wqe->atomic_wr.compare_add);
ohdr->u.atomic_eth.compare_data = 0;
}
ohdr->u.atomic_eth.vaddr[0] = cpu_to_be32(
- wqe->wr.wr.atomic.remote_addr >> 32);
+ wqe->atomic_wr.remote_addr >> 32);
ohdr->u.atomic_eth.vaddr[1] = cpu_to_be32(
- wqe->wr.wr.atomic.remote_addr);
+ wqe->atomic_wr.remote_addr);
ohdr->u.atomic_eth.rkey = cpu_to_be32(
- wqe->wr.wr.atomic.rkey);
+ wqe->atomic_wr.rkey);
hwords += sizeof(struct ib_atomic_eth) / sizeof(u32);
ss = NULL;
len = 0;
@@ -629,9 +629,9 @@ int hfi1_make_rc_req(struct hfi1_qp *qp)
*/
len = (delta_psn(qp->s_psn, wqe->psn)) * pmtu;
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len);
+ cpu_to_be64(wqe->rdma_wr.remote_addr + len);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(wqe->length - len);
qp->s_state = OP(RDMA_READ_REQUEST);
hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32);
@@ -697,6 +697,7 @@ void hfi1_send_rc_ack(struct hfi1_ctxtdata *rcd, struct hfi1_qp *qp,
struct pio_buf *pbuf;
struct hfi1_ib_header hdr;
struct hfi1_other_headers *ohdr;
+ unsigned long flags;
/* Don't send ACK or NAK if a RDMA read or atomic is pending. */
if (qp->s_flags & HFI1_S_RESP_PENDING)
@@ -771,7 +772,7 @@ void hfi1_send_rc_ack(struct hfi1_ctxtdata *rcd, struct hfi1_qp *qp,
queue_ack:
this_cpu_inc(*ibp->rc_qacks);
- spin_lock(&qp->s_lock);
+ spin_lock_irqsave(&qp->s_lock, flags);
qp->s_flags |= HFI1_S_ACK_PENDING | HFI1_S_RESP_PENDING;
qp->s_nak_state = qp->r_nak_state;
qp->s_ack_psn = qp->r_ack_psn;
@@ -780,7 +781,7 @@ queue_ack:
/* Schedule the send tasklet. */
hfi1_schedule_send(qp);
- spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->s_lock, flags);
}
/**
@@ -926,6 +927,7 @@ static void rc_timeout(unsigned long arg)
ibp->n_rc_timeouts++;
qp->s_flags &= ~HFI1_S_TIMER;
del_timer(&qp->s_timer);
+ trace_hfi1_rc_timeout(qp, qp->s_last_psn + 1);
restart_rc(qp, qp->s_last_psn + 1, 1);
hfi1_schedule_send(qp);
}
@@ -1152,7 +1154,7 @@ static struct hfi1_swqe *do_rc_completion(struct hfi1_qp *qp,
*
* This is called from rc_rcv_resp() to process an incoming RC ACK
* for the given QP.
- * Called at interrupt level with the QP s_lock held.
+ * May be called at interrupt level, with the QP s_lock held.
* Returns 1 if OK, 0 if current operation should be aborted (NAK).
*/
static int do_rc_ack(struct hfi1_qp *qp, u32 aeth, u32 psn, int opcode,
@@ -1441,6 +1443,8 @@ static void rc_rcv_resp(struct hfi1_ibport *ibp,
spin_lock_irqsave(&qp->s_lock, flags);
+ trace_hfi1_rc_ack(qp, psn);
+
/* Ignore invalid responses. */
if (cmp_psn(psn, qp->s_next_psn) >= 0)
goto ack_done;
@@ -1604,6 +1608,27 @@ bail:
return;
}
+static inline void rc_defered_ack(struct hfi1_ctxtdata *rcd,
+ struct hfi1_qp *qp)
+{
+ if (list_empty(&qp->rspwait)) {
+ qp->r_flags |= HFI1_R_RSP_DEFERED_ACK;
+ atomic_inc(&qp->refcount);
+ list_add_tail(&qp->rspwait, &rcd->qp_wait_list);
+ }
+}
+
+static inline void rc_cancel_ack(struct hfi1_qp *qp)
+{
+ qp->r_adefered = 0;
+ if (list_empty(&qp->rspwait))
+ return;
+ list_del_init(&qp->rspwait);
+ qp->r_flags &= ~HFI1_R_RSP_DEFERED_ACK;
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+}
+
/**
* rc_rcv_error - process an incoming duplicate or error RC packet
* @ohdr: the other headers for this packet
@@ -1629,6 +1654,7 @@ static noinline int rc_rcv_error(struct hfi1_other_headers *ohdr, void *data,
u8 i, prev;
int old_req;
+ trace_hfi1_rc_rcv_error(qp, psn);
if (diff > 0) {
/*
* Packet sequence error.
@@ -1645,11 +1671,7 @@ static noinline int rc_rcv_error(struct hfi1_other_headers *ohdr, void *data,
* in the receive queue have been processed.
* Otherwise, we end up propagating congestion.
*/
- if (list_empty(&qp->rspwait)) {
- qp->r_flags |= HFI1_R_RSP_NAK;
- atomic_inc(&qp->refcount);
- list_add_tail(&qp->rspwait, &rcd->qp_wait_list);
- }
+ rc_defered_ack(rcd, qp);
}
goto done;
}
@@ -1835,11 +1857,12 @@ static void log_cca_event(struct hfi1_pportdata *ppd, u8 sl, u32 rlid,
u32 lqpn, u32 rqpn, u8 svc_type)
{
struct opa_hfi1_cong_log_event_internal *cc_event;
+ unsigned long flags;
if (sl >= OPA_MAX_SLS)
return;
- spin_lock(&ppd->cc_log_lock);
+ spin_lock_irqsave(&ppd->cc_log_lock, flags);
ppd->threshold_cong_event_map[sl/8] |= 1 << (sl % 8);
ppd->threshold_event_counter++;
@@ -1855,7 +1878,7 @@ static void log_cca_event(struct hfi1_pportdata *ppd, u8 sl, u32 rlid,
/* keep timestamp in units of 1.024 usec */
cc_event->timestamp = ktime_to_ns(ktime_get()) / 1024;
- spin_unlock(&ppd->cc_log_lock);
+ spin_unlock_irqrestore(&ppd->cc_log_lock, flags);
}
void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
@@ -1865,6 +1888,7 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
u16 ccti, ccti_incr, ccti_timer, ccti_limit;
u8 trigger_threshold;
struct cc_state *cc_state;
+ unsigned long flags;
if (sl >= OPA_MAX_SLS)
return;
@@ -1887,7 +1911,7 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
trigger_threshold =
cc_state->cong_setting.entries[sl].trigger_threshold;
- spin_lock(&ppd->cca_timer_lock);
+ spin_lock_irqsave(&ppd->cca_timer_lock, flags);
if (cca_timer->ccti < ccti_limit) {
if (cca_timer->ccti + ccti_incr <= ccti_limit)
@@ -1897,7 +1921,7 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
set_link_ipg(ppd);
}
- spin_unlock(&ppd->cca_timer_lock);
+ spin_unlock_irqrestore(&ppd->cca_timer_lock, flags);
ccti = cca_timer->ccti;
@@ -1924,7 +1948,7 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
*
* This is called from qp_rcv() to process an incoming RC packet
* for the given QP.
- * Called at interrupt level.
+ * May be called at interrupt level.
*/
void hfi1_rc_rcv(struct hfi1_packet *packet)
{
@@ -1971,7 +1995,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
}
psn = be32_to_cpu(ohdr->bth[2]);
- opcode = bth0 >> 24;
+ opcode = (bth0 >> 24) & 0xff;
/*
* Process responses (ACKs) before anything else. Note that the
@@ -2322,19 +2346,29 @@ send_last:
qp->r_ack_psn = psn;
qp->r_nak_state = 0;
/* Send an ACK if requested or required. */
- if (psn & (1 << 31))
- goto send_ack;
+ if (psn & IB_BTH_REQ_ACK) {
+ if (packet->numpkt == 0) {
+ rc_cancel_ack(qp);
+ goto send_ack;
+ }
+ if (qp->r_adefered >= HFI1_PSN_CREDIT) {
+ rc_cancel_ack(qp);
+ goto send_ack;
+ }
+ if (unlikely(is_fecn)) {
+ rc_cancel_ack(qp);
+ goto send_ack;
+ }
+ qp->r_adefered++;
+ rc_defered_ack(rcd, qp);
+ }
return;
rnr_nak:
qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer;
qp->r_ack_psn = qp->r_psn;
/* Queue RNR NAK for later */
- if (list_empty(&qp->rspwait)) {
- qp->r_flags |= HFI1_R_RSP_NAK;
- atomic_inc(&qp->refcount);
- list_add_tail(&qp->rspwait, &rcd->qp_wait_list);
- }
+ rc_defered_ack(rcd, qp);
return;
nack_op_err:
@@ -2342,11 +2376,7 @@ nack_op_err:
qp->r_nak_state = IB_NAK_REMOTE_OPERATIONAL_ERROR;
qp->r_ack_psn = qp->r_psn;
/* Queue NAK for later */
- if (list_empty(&qp->rspwait)) {
- qp->r_flags |= HFI1_R_RSP_NAK;
- atomic_inc(&qp->refcount);
- list_add_tail(&qp->rspwait, &rcd->qp_wait_list);
- }
+ rc_defered_ack(rcd, qp);
return;
nack_inv_unlck:
@@ -2356,11 +2386,7 @@ nack_inv:
qp->r_nak_state = IB_NAK_INVALID_REQUEST;
qp->r_ack_psn = qp->r_psn;
/* Queue NAK for later */
- if (list_empty(&qp->rspwait)) {
- qp->r_flags |= HFI1_R_RSP_NAK;
- atomic_inc(&qp->refcount);
- list_add_tail(&qp->rspwait, &rcd->qp_wait_list);
- }
+ rc_defered_ack(rcd, qp);
return;
nack_acc_unlck:
@@ -2384,19 +2410,19 @@ void hfi1_rc_hdrerr(
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
int diff;
u32 opcode;
- u32 psn;
+ u32 psn, bth0;
/* Check for GRH */
ohdr = &hdr->u.oth;
if (has_grh)
ohdr = &hdr->u.l.oth;
- opcode = be32_to_cpu(ohdr->bth[0]);
- if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
+ bth0 = be32_to_cpu(ohdr->bth[0]);
+ if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
return;
psn = be32_to_cpu(ohdr->bth[2]);
- opcode >>= 24;
+ opcode = (bth0 >> 24) & 0xff;
/* Only deal with RDMA Writes for now */
if (opcode < IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) {
@@ -2414,13 +2440,7 @@ void hfi1_rc_hdrerr(
* Otherwise, we end up
* propagating congestion.
*/
- if (list_empty(&qp->rspwait)) {
- qp->r_flags |= HFI1_R_RSP_NAK;
- atomic_inc(&qp->refcount);
- list_add_tail(
- &qp->rspwait,
- &rcd->qp_wait_list);
- }
+ rc_defered_ack(rcd, qp);
} /* Out of sequence NAK */
} /* QP Request NAKs */
}
diff --git a/drivers/staging/rdma/hfi1/ruc.c b/drivers/staging/rdma/hfi1/ruc.c
index a4115288db66..317bf6ff46a8 100644
--- a/drivers/staging/rdma/hfi1/ruc.c
+++ b/drivers/staging/rdma/hfi1/ruc.c
@@ -241,26 +241,6 @@ bail:
return ret;
}
-/*
- * Switch to alternate path.
- * The QP s_lock should be held and interrupts disabled.
- */
-void hfi1_migrate_qp(struct hfi1_qp *qp)
-{
- struct ib_event ev;
-
- qp->s_mig_state = IB_MIG_MIGRATED;
- qp->remote_ah_attr = qp->alt_ah_attr;
- qp->port_num = qp->alt_ah_attr.port_num;
- qp->s_pkey_index = qp->s_alt_pkey_index;
- qp->s_flags |= HFI1_S_AHG_CLEAR;
-
- ev.device = qp->ibqp.device;
- ev.element.qp = &qp->ibqp;
- ev.event = IB_EVENT_PATH_MIG;
- qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
-}
-
static __be64 get_sguid(struct hfi1_ibport *ibp, unsigned index)
{
if (!index) {
@@ -481,8 +461,8 @@ again:
if (wqe->length == 0)
break;
if (unlikely(!hfi1_rkey_ok(qp, &qp->r_sge.sge, wqe->length,
- wqe->wr.wr.rdma.remote_addr,
- wqe->wr.wr.rdma.rkey,
+ wqe->rdma_wr.remote_addr,
+ wqe->rdma_wr.rkey,
IB_ACCESS_REMOTE_WRITE)))
goto acc_err;
qp->r_sge.sg_list = NULL;
@@ -494,8 +474,8 @@ again:
if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
goto inv_err;
if (unlikely(!hfi1_rkey_ok(qp, &sqp->s_sge.sge, wqe->length,
- wqe->wr.wr.rdma.remote_addr,
- wqe->wr.wr.rdma.rkey,
+ wqe->rdma_wr.remote_addr,
+ wqe->rdma_wr.rkey,
IB_ACCESS_REMOTE_READ)))
goto acc_err;
release = 0;
@@ -512,18 +492,18 @@ again:
if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC)))
goto inv_err;
if (unlikely(!hfi1_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64),
- wqe->wr.wr.atomic.remote_addr,
- wqe->wr.wr.atomic.rkey,
+ wqe->atomic_wr.remote_addr,
+ wqe->atomic_wr.rkey,
IB_ACCESS_REMOTE_ATOMIC)))
goto acc_err;
/* Perform atomic OP and save result. */
maddr = (atomic64_t *) qp->r_sge.sge.vaddr;
- sdata = wqe->wr.wr.atomic.compare_add;
+ sdata = wqe->atomic_wr.compare_add;
*(u64 *) sqp->s_sge.sge.vaddr =
(wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ?
(u64) atomic64_add_return(sdata, maddr) - sdata :
(u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr,
- sdata, wqe->wr.wr.atomic.swap);
+ sdata, wqe->atomic_wr.swap);
hfi1_put_mr(qp->r_sge.sge.mr);
qp->r_sge.num_sge = 0;
goto send_comp;
@@ -695,19 +675,6 @@ u32 hfi1_make_grh(struct hfi1_ibport *ibp, struct ib_grh *hdr,
return sizeof(struct ib_grh) / sizeof(u32);
}
-/*
- * free_ahg - clear ahg from QP
- */
-void clear_ahg(struct hfi1_qp *qp)
-{
- qp->s_hdr->ahgcount = 0;
- qp->s_flags &= ~(HFI1_S_AHG_VALID | HFI1_S_AHG_CLEAR);
- if (qp->s_sde)
- sdma_ahg_free(qp->s_sde, qp->s_ahgidx);
- qp->s_ahgidx = -1;
- qp->s_sde = NULL;
-}
-
#define BTH2_OFFSET (offsetof(struct hfi1_pio_header, hdr.u.oth.bth[2]) / 4)
/**
@@ -727,11 +694,8 @@ static inline void build_ahg(struct hfi1_qp *qp, u32 npsn)
clear_ahg(qp);
if (!(qp->s_flags & HFI1_S_AHG_VALID)) {
/* first middle that needs copy */
- if (qp->s_ahgidx < 0) {
- if (!qp->s_sde)
- qp->s_sde = qp_to_sdma_engine(qp, qp->s_sc);
+ if (qp->s_ahgidx < 0)
qp->s_ahgidx = sdma_ahg_alloc(qp->s_sde);
- }
if (qp->s_ahgidx >= 0) {
qp->s_ahgpsn = npsn;
qp->s_hdr->tx_flags |= SDMA_TXREQ_F_AHG_COPY;
@@ -774,7 +738,6 @@ void hfi1_make_ruc_header(struct hfi1_qp *qp, struct hfi1_other_headers *ohdr,
u16 lrh0;
u32 nwords;
u32 extra_bytes;
- u8 sc5;
u32 bth1;
/* Construct the header. */
@@ -788,9 +751,7 @@ void hfi1_make_ruc_header(struct hfi1_qp *qp, struct hfi1_other_headers *ohdr,
lrh0 = HFI1_LRH_GRH;
middle = 0;
}
- sc5 = ibp->sl_to_sc[qp->remote_ah_attr.sl];
- lrh0 |= (sc5 & 0xf) << 12 | (qp->remote_ah_attr.sl & 0xf) << 4;
- qp->s_sc = sc5;
+ lrh0 |= (qp->s_sc & 0xf) << 12 | (qp->remote_ah_attr.sl & 0xf) << 4;
/*
* reset s_hdr/AHG fields
*
@@ -833,6 +794,9 @@ void hfi1_make_ruc_header(struct hfi1_qp *qp, struct hfi1_other_headers *ohdr,
ohdr->bth[2] = cpu_to_be32(bth2);
}
+/* when sending, force a reschedule every one of these periods */
+#define SEND_RESCHED_TIMEOUT (5 * HZ) /* 5s in jiffies */
+
/**
* hfi1_do_send - perform a send on a QP
* @work: contains a pointer to the QP
@@ -845,15 +809,20 @@ void hfi1_do_send(struct work_struct *work)
{
struct iowait *wait = container_of(work, struct iowait, iowork);
struct hfi1_qp *qp = container_of(wait, struct hfi1_qp, s_iowait);
- struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+ struct hfi1_pkt_state ps;
int (*make_req)(struct hfi1_qp *qp);
unsigned long flags;
+ unsigned long timeout;
+
+ ps.dev = to_idev(qp->ibqp.device);
+ ps.ibp = to_iport(qp->ibqp.device, qp->port_num);
+ ps.ppd = ppd_from_ibp(ps.ibp);
if ((qp->ibqp.qp_type == IB_QPT_RC ||
qp->ibqp.qp_type == IB_QPT_UC) &&
!loopback &&
- (qp->remote_ah_attr.dlid & ~((1 << ppd->lmc) - 1)) == ppd->lid) {
+ (qp->remote_ah_attr.dlid & ~((1 << ps.ppd->lmc) - 1)) ==
+ ps.ppd->lid) {
ruc_loopback(qp);
return;
}
@@ -877,6 +846,7 @@ void hfi1_do_send(struct work_struct *work)
spin_unlock_irqrestore(&qp->s_lock, flags);
+ timeout = jiffies + SEND_RESCHED_TIMEOUT;
do {
/* Check for a constructed packet to be sent. */
if (qp->s_hdrwords != 0) {
@@ -884,12 +854,18 @@ void hfi1_do_send(struct work_struct *work)
* If the packet cannot be sent now, return and
* the send tasklet will be woken up later.
*/
- if (hfi1_verbs_send(qp, qp->s_hdr, qp->s_hdrwords,
- qp->s_cur_sge, qp->s_cur_size))
+ if (hfi1_verbs_send(qp, &ps))
break;
/* Record that s_hdr is empty. */
qp->s_hdrwords = 0;
}
+
+ /* allow other tasks to run */
+ if (unlikely(time_after(jiffies, timeout))) {
+ cond_resched();
+ ps.ppd->dd->verbs_dev.n_send_schedule++;
+ timeout = jiffies + SEND_RESCHED_TIMEOUT;
+ }
} while (make_req(qp));
}
@@ -913,7 +889,7 @@ void hfi1_send_complete(struct hfi1_qp *qp, struct hfi1_swqe *wqe,
if (qp->ibqp.qp_type == IB_QPT_UD ||
qp->ibqp.qp_type == IB_QPT_SMI ||
qp->ibqp.qp_type == IB_QPT_GSI)
- atomic_dec(&to_iah(wqe->wr.wr.ud.ah)->refcount);
+ atomic_dec(&to_iah(wqe->ud_wr.ah)->refcount);
/* See ch. 11.2.4.1 and 10.7.3.1 */
if (!(qp->s_flags & HFI1_S_SIGNAL_REQ_WR) ||
diff --git a/drivers/staging/rdma/hfi1/sdma.c b/drivers/staging/rdma/hfi1/sdma.c
index 63ab72102183..90b7072a9969 100644
--- a/drivers/staging/rdma/hfi1/sdma.c
+++ b/drivers/staging/rdma/hfi1/sdma.c
@@ -55,6 +55,7 @@
#include <linux/bitops.h>
#include <linux/timer.h>
#include <linux/vmalloc.h>
+#include <linux/highmem.h>
#include "hfi.h"
#include "common.h"
@@ -64,7 +65,8 @@
#include "trace.h"
/* must be a power of 2 >= 64 <= 32768 */
-#define SDMA_DESCQ_CNT 1024
+#define SDMA_DESCQ_CNT 2048
+#define SDMA_DESC_INTR 64
#define INVALID_TAIL 0xffff
static uint sdma_descq_cnt = SDMA_DESCQ_CNT;
@@ -79,6 +81,10 @@ uint mod_num_sdma;
module_param_named(num_sdma, mod_num_sdma, uint, S_IRUGO);
MODULE_PARM_DESC(num_sdma, "Set max number SDMA engines to use");
+static uint sdma_desct_intr = SDMA_DESC_INTR;
+module_param_named(desct_intr, sdma_desct_intr, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(desct_intr, "Number of SDMA descriptor before interrupt");
+
#define SDMA_WAIT_BATCH_SIZE 20
/* max wait time for a SDMA engine to indicate it has halted */
#define SDMA_ERR_HALT_TIMEOUT 10 /* ms */
@@ -230,7 +236,6 @@ static void sdma_hw_clean_up_task(unsigned long);
static void sdma_put(struct sdma_state *);
static void sdma_set_state(struct sdma_engine *, enum sdma_states);
static void sdma_start_hw_clean_up(struct sdma_engine *);
-static void sdma_start_sw_clean_up(struct sdma_engine *);
static void sdma_sw_clean_up_task(unsigned long);
static void sdma_sendctrl(struct sdma_engine *, unsigned);
static void init_sdma_regs(struct sdma_engine *, u32, uint);
@@ -303,17 +308,26 @@ static void sdma_wait_for_packet_egress(struct sdma_engine *sde,
u64 off = 8 * sde->this_idx;
struct hfi1_devdata *dd = sde->dd;
int lcnt = 0;
+ u64 reg_prev;
+ u64 reg = 0;
while (1) {
- u64 reg = read_csr(dd, off + SEND_EGRESS_SEND_DMA_STATUS);
+ reg_prev = reg;
+ reg = read_csr(dd, off + SEND_EGRESS_SEND_DMA_STATUS);
reg &= SDMA_EGRESS_PACKET_OCCUPANCY_SMASK;
reg >>= SDMA_EGRESS_PACKET_OCCUPANCY_SHIFT;
if (reg == 0)
break;
- if (lcnt++ > 100) {
- dd_dev_err(dd, "%s: engine %u timeout waiting for packets to egress, remaining count %u\n",
+ /* counter is reest if accupancy count changes */
+ if (reg != reg_prev)
+ lcnt = 0;
+ if (lcnt++ > 500) {
+ /* timed out - bounce the link */
+ dd_dev_err(dd, "%s: engine %u timeout waiting for packets to egress, remaining count %u, bouncing link\n",
__func__, sde->this_idx, (u32)reg);
+ queue_work(dd->pport->hfi1_wq,
+ &dd->pport->link_bounce_work);
break;
}
udelay(1);
@@ -369,16 +383,17 @@ static void sdma_flush(struct sdma_engine *sde)
{
struct sdma_txreq *txp, *txp_next;
LIST_HEAD(flushlist);
+ unsigned long flags;
/* flush from head to tail */
sdma_flush_descq(sde);
- spin_lock(&sde->flushlist_lock);
+ spin_lock_irqsave(&sde->flushlist_lock, flags);
/* copy flush list */
list_for_each_entry_safe(txp, txp_next, &sde->flushlist, list) {
list_del_init(&txp->list);
list_add_tail(&txp->list, &flushlist);
}
- spin_unlock(&sde->flushlist_lock);
+ spin_unlock_irqrestore(&sde->flushlist_lock, flags);
/* flush from flush list */
list_for_each_entry_safe(txp, txp_next, &flushlist, list) {
int drained = 0;
@@ -454,12 +469,6 @@ static void sdma_err_halt_wait(struct work_struct *work)
sdma_process_event(sde, sdma_event_e15_hw_halt_done);
}
-static void sdma_start_err_halt_wait(struct sdma_engine *sde)
-{
- schedule_work(&sde->err_halt_worker);
-}
-
-
static void sdma_err_progress_check_schedule(struct sdma_engine *sde)
{
if (!is_bx(sde->dd) && HFI1_CAP_IS_KSET(SDMA_AHG)) {
@@ -666,11 +675,6 @@ static void sdma_start_hw_clean_up(struct sdma_engine *sde)
tasklet_hi_schedule(&sde->sdma_hw_clean_up_task);
}
-static void sdma_start_sw_clean_up(struct sdma_engine *sde)
-{
- tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
-}
-
static void sdma_set_state(struct sdma_engine *sde,
enum sdma_states next_state)
{
@@ -762,18 +766,19 @@ struct sdma_engine *sdma_select_engine_vl(
struct sdma_engine *rval;
if (WARN_ON(vl > 8))
- return NULL;
+ return &dd->per_sdma[0];
rcu_read_lock();
m = rcu_dereference(dd->sdma_map);
if (unlikely(!m)) {
rcu_read_unlock();
- return NULL;
+ return &dd->per_sdma[0];
}
e = m->map[vl & m->mask];
rval = e->sde[selector & e->mask];
rcu_read_unlock();
+ rval = !rval ? &dd->per_sdma[0] : rval;
trace_hfi1_sdma_engine_select(dd, selector, vl, rval->this_idx);
return rval;
}
@@ -1036,6 +1041,9 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
return -ENOMEM;
idle_cnt = ns_to_cclock(dd, idle_cnt);
+ if (!sdma_desct_intr)
+ sdma_desct_intr = SDMA_DESC_INTR;
+
/* Allocate memory for SendDMA descriptor FIFOs */
for (this_idx = 0; this_idx < num_engines; ++this_idx) {
sde = &dd->per_sdma[this_idx];
@@ -1094,10 +1102,8 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
sde->progress_check_head = 0;
- init_timer(&sde->err_progress_check_timer);
- sde->err_progress_check_timer.function =
- sdma_err_progress_check;
- sde->err_progress_check_timer.data = (unsigned long)sde;
+ setup_timer(&sde->err_progress_check_timer,
+ sdma_err_progress_check, (unsigned long)sde);
sde->descq = dma_zalloc_coherent(
&dd->pcidev->dev,
@@ -1538,7 +1544,7 @@ void sdma_engine_interrupt(struct sdma_engine *sde, u64 status)
{
trace_hfi1_sdma_engine_interrupt(sde, status);
write_seqlock(&sde->head_lock);
- sdma_set_desc_cnt(sde, sde->descq_cnt / 2);
+ sdma_set_desc_cnt(sde, sdma_desct_intr);
sdma_make_progress(sde, status);
write_sequnlock(&sde->head_lock);
}
@@ -1857,7 +1863,7 @@ static void dump_sdma_state(struct sdma_engine *sde)
}
#define SDE_FMT \
- "SDE %u STE %s C 0x%llx S 0x%016llx E 0x%llx T(HW) 0x%llx T(SW) 0x%x H(HW) 0x%llx H(SW) 0x%x H(D) 0x%llx DM 0x%llx GL 0x%llx R 0x%llx LIS 0x%llx AHGI 0x%llx TXT %u TXH %u DT %u DH %u FLNE %d DQF %u SLC 0x%llx\n"
+ "SDE %u CPU %d STE %s C 0x%llx S 0x%016llx E 0x%llx T(HW) 0x%llx T(SW) 0x%x H(HW) 0x%llx H(SW) 0x%x H(D) 0x%llx DM 0x%llx GL 0x%llx R 0x%llx LIS 0x%llx AHGI 0x%llx TXT %u TXH %u DT %u DH %u FLNE %d DQF %u SLC 0x%llx\n"
/**
* sdma_seqfile_dump_sde() - debugfs dump of sde
* @s: seq file
@@ -1877,6 +1883,7 @@ void sdma_seqfile_dump_sde(struct seq_file *s, struct sdma_engine *sde)
head = sde->descq_head & sde->sdma_mask;
tail = ACCESS_ONCE(sde->descq_tail) & sde->sdma_mask;
seq_printf(s, SDE_FMT, sde->this_idx,
+ sde->cpu,
sdma_state_name(sde->state.current_state),
(unsigned long long)read_sde_csr(sde, SD(CTRL)),
(unsigned long long)read_sde_csr(sde, SD(STATUS)),
@@ -2291,7 +2298,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
case sdma_event_e50_hw_cleaned:
break;
case sdma_event_e60_hw_halted:
- sdma_start_err_halt_wait(sde);
+ schedule_work(&sde->err_halt_worker);
break;
case sdma_event_e70_go_idle:
ss->go_s99_running = 0;
@@ -2372,7 +2379,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
break;
case sdma_event_e60_hw_halted:
sdma_set_state(sde, sdma_state_s50_hw_halt_wait);
- sdma_start_err_halt_wait(sde);
+ schedule_work(&sde->err_halt_worker);
break;
case sdma_event_e70_go_idle:
break;
@@ -2435,7 +2442,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
switch (event) {
case sdma_event_e00_go_hw_down:
sdma_set_state(sde, sdma_state_s00_hw_down);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e10_go_hw_start:
break;
@@ -2477,13 +2484,13 @@ static void __sdma_process_event(struct sdma_engine *sde,
switch (event) {
case sdma_event_e00_go_hw_down:
sdma_set_state(sde, sdma_state_s00_hw_down);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e10_go_hw_start:
break;
case sdma_event_e15_hw_halt_done:
sdma_set_state(sde, sdma_state_s30_sw_clean_up_wait);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e25_hw_clean_up_done:
break;
@@ -2495,7 +2502,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
case sdma_event_e50_hw_cleaned:
break;
case sdma_event_e60_hw_halted:
- sdma_start_err_halt_wait(sde);
+ schedule_work(&sde->err_halt_worker);
break;
case sdma_event_e70_go_idle:
ss->go_s99_running = 0;
@@ -2518,13 +2525,13 @@ static void __sdma_process_event(struct sdma_engine *sde,
switch (event) {
case sdma_event_e00_go_hw_down:
sdma_set_state(sde, sdma_state_s00_hw_down);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e10_go_hw_start:
break;
case sdma_event_e15_hw_halt_done:
sdma_set_state(sde, sdma_state_s30_sw_clean_up_wait);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e25_hw_clean_up_done:
break;
@@ -2536,7 +2543,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
case sdma_event_e50_hw_cleaned:
break;
case sdma_event_e60_hw_halted:
- sdma_start_err_halt_wait(sde);
+ schedule_work(&sde->err_halt_worker);
break;
case sdma_event_e70_go_idle:
ss->go_s99_running = 0;
@@ -2558,7 +2565,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
switch (event) {
case sdma_event_e00_go_hw_down:
sdma_set_state(sde, sdma_state_s00_hw_down);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e10_go_hw_start:
break;
@@ -2582,7 +2589,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
break;
case sdma_event_e81_hw_frozen:
sdma_set_state(sde, sdma_state_s82_freeze_sw_clean);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e82_hw_unfreeze:
break;
@@ -2597,7 +2604,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
switch (event) {
case sdma_event_e00_go_hw_down:
sdma_set_state(sde, sdma_state_s00_hw_down);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e10_go_hw_start:
break;
@@ -2641,7 +2648,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
switch (event) {
case sdma_event_e00_go_hw_down:
sdma_set_state(sde, sdma_state_s00_hw_down);
- sdma_start_sw_clean_up(sde);
+ tasklet_hi_schedule(&sde->sdma_sw_clean_up_task);
break;
case sdma_event_e10_go_hw_start:
break;
@@ -2664,7 +2671,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
* progress check
*/
sdma_set_state(sde, sdma_state_s50_hw_halt_wait);
- sdma_start_err_halt_wait(sde);
+ schedule_work(&sde->err_halt_worker);
break;
case sdma_event_e70_go_idle:
sdma_set_state(sde, sdma_state_s60_idle_halt_wait);
@@ -2697,27 +2704,134 @@ static void __sdma_process_event(struct sdma_engine *sde,
* of descriptors in the sdma_txreq is exhausted.
*
* The code will bump the allocation up to the max
- * of MAX_DESC (64) descriptors. There doesn't seem
- * much point in an interim step.
+ * of MAX_DESC (64) descriptors. There doesn't seem
+ * much point in an interim step. The last descriptor
+ * is reserved for coalesce buffer in order to support
+ * cases where input packet has >MAX_DESC iovecs.
*
*/
-int _extend_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
+static int _extend_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
{
int i;
+ /* Handle last descriptor */
+ if (unlikely((tx->num_desc == (MAX_DESC - 1)))) {
+ /* if tlen is 0, it is for padding, release last descriptor */
+ if (!tx->tlen) {
+ tx->desc_limit = MAX_DESC;
+ } else if (!tx->coalesce_buf) {
+ /* allocate coalesce buffer with space for padding */
+ tx->coalesce_buf = kmalloc(tx->tlen + sizeof(u32),
+ GFP_ATOMIC);
+ if (!tx->coalesce_buf)
+ return -ENOMEM;
+
+ tx->coalesce_idx = 0;
+ }
+ return 0;
+ }
+
+ if (unlikely(tx->num_desc == MAX_DESC))
+ return -ENOMEM;
+
tx->descp = kmalloc_array(
MAX_DESC,
sizeof(struct sdma_desc),
GFP_ATOMIC);
if (!tx->descp)
return -ENOMEM;
- tx->desc_limit = MAX_DESC;
+
+ /* reserve last descriptor for coalescing */
+ tx->desc_limit = MAX_DESC - 1;
/* copy ones already built */
for (i = 0; i < tx->num_desc; i++)
tx->descp[i] = tx->descs[i];
return 0;
}
+/*
+ * ext_coal_sdma_tx_descs() - extend or coalesce sdma tx descriptors
+ *
+ * This is called once the initial nominal allocation of descriptors
+ * in the sdma_txreq is exhausted.
+ *
+ * This function calls _extend_sdma_tx_descs to extend or allocate
+ * coalesce buffer. If there is a allocated coalesce buffer, it will
+ * copy the input packet data into the coalesce buffer. It also adds
+ * coalesce buffer descriptor once whe whole packet is received.
+ *
+ * Return:
+ * <0 - error
+ * 0 - coalescing, don't populate descriptor
+ * 1 - continue with populating descriptor
+ */
+int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx,
+ int type, void *kvaddr, struct page *page,
+ unsigned long offset, u16 len)
+{
+ int pad_len, rval;
+ dma_addr_t addr;
+
+ rval = _extend_sdma_tx_descs(dd, tx);
+ if (rval) {
+ sdma_txclean(dd, tx);
+ return rval;
+ }
+
+ /* If coalesce buffer is allocated, copy data into it */
+ if (tx->coalesce_buf) {
+ if (type == SDMA_MAP_NONE) {
+ sdma_txclean(dd, tx);
+ return -EINVAL;
+ }
+
+ if (type == SDMA_MAP_PAGE) {
+ kvaddr = kmap(page);
+ kvaddr += offset;
+ } else if (WARN_ON(!kvaddr)) {
+ sdma_txclean(dd, tx);
+ return -EINVAL;
+ }
+
+ memcpy(tx->coalesce_buf + tx->coalesce_idx, kvaddr, len);
+ tx->coalesce_idx += len;
+ if (type == SDMA_MAP_PAGE)
+ kunmap(page);
+
+ /* If there is more data, return */
+ if (tx->tlen - tx->coalesce_idx)
+ return 0;
+
+ /* Whole packet is received; add any padding */
+ pad_len = tx->packet_len & (sizeof(u32) - 1);
+ if (pad_len) {
+ pad_len = sizeof(u32) - pad_len;
+ memset(tx->coalesce_buf + tx->coalesce_idx, 0, pad_len);
+ /* padding is taken care of for coalescing case */
+ tx->packet_len += pad_len;
+ tx->tlen += pad_len;
+ }
+
+ /* dma map the coalesce buffer */
+ addr = dma_map_single(&dd->pcidev->dev,
+ tx->coalesce_buf,
+ tx->tlen,
+ DMA_TO_DEVICE);
+
+ if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
+ sdma_txclean(dd, tx);
+ return -ENOSPC;
+ }
+
+ /* Add descriptor for coalesce buffer */
+ tx->desc_limit = MAX_DESC;
+ return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx,
+ addr, tx->tlen);
+ }
+
+ return 1;
+}
+
/* Update sdes when the lmc changes */
void sdma_update_lmc(struct hfi1_devdata *dd, u64 mask, u32 lid)
{
@@ -2743,13 +2857,15 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
{
int rval = 0;
+ tx->num_desc++;
if ((unlikely(tx->num_desc == tx->desc_limit))) {
rval = _extend_sdma_tx_descs(dd, tx);
- if (rval)
+ if (rval) {
+ sdma_txclean(dd, tx);
return rval;
+ }
}
- /* finish the one just added */
- tx->num_desc++;
+ /* finish the one just added */
make_tx_sdma_desc(
tx,
SDMA_MAP_NONE,
diff --git a/drivers/staging/rdma/hfi1/sdma.h b/drivers/staging/rdma/hfi1/sdma.h
index 496086903891..85701eed1585 100644
--- a/drivers/staging/rdma/hfi1/sdma.h
+++ b/drivers/staging/rdma/hfi1/sdma.h
@@ -352,6 +352,8 @@ struct sdma_txreq {
/* private: */
void *coalesce_buf;
/* private: */
+ u16 coalesce_idx;
+ /* private: */
struct iowait *wait;
/* private: */
callback_t complete;
@@ -408,8 +410,6 @@ struct sdma_engine {
u64 idle_mask;
u64 progress_mask;
/* private: */
- struct workqueue_struct *wq;
- /* private: */
volatile __le64 *head_dma; /* DMA'ed by chip */
/* private: */
dma_addr_t head_phys;
@@ -424,6 +424,8 @@ struct sdma_engine {
u32 sdma_mask;
/* private */
struct sdma_state state;
+ /* private */
+ int cpu;
/* private: */
u8 sdma_shift;
/* private: */
@@ -735,7 +737,9 @@ static inline void make_tx_sdma_desc(
}
/* helper to extend txreq */
-int _extend_sdma_tx_descs(struct hfi1_devdata *, struct sdma_txreq *);
+int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx,
+ int type, void *kvaddr, struct page *page,
+ unsigned long offset, u16 len);
int _pad_sdma_tx_descs(struct hfi1_devdata *, struct sdma_txreq *);
void sdma_txclean(struct hfi1_devdata *, struct sdma_txreq *);
@@ -762,11 +766,6 @@ static inline int _sdma_txadd_daddr(
{
int rval = 0;
- if ((unlikely(tx->num_desc == tx->desc_limit))) {
- rval = _extend_sdma_tx_descs(dd, tx);
- if (rval)
- return rval;
- }
make_tx_sdma_desc(
tx,
type,
@@ -798,9 +797,7 @@ static inline int _sdma_txadd_daddr(
*
* Return:
* 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't
- * extend descriptor array or couldn't allocate coalesce
- * buffer.
- *
+ * extend/coalesce descriptor array
*/
static inline int sdma_txadd_page(
struct hfi1_devdata *dd,
@@ -809,17 +806,28 @@ static inline int sdma_txadd_page(
unsigned long offset,
u16 len)
{
- dma_addr_t addr =
- dma_map_page(
- &dd->pcidev->dev,
- page,
- offset,
- len,
- DMA_TO_DEVICE);
+ dma_addr_t addr;
+ int rval;
+
+ if ((unlikely(tx->num_desc == tx->desc_limit))) {
+ rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_PAGE,
+ NULL, page, offset, len);
+ if (rval <= 0)
+ return rval;
+ }
+
+ addr = dma_map_page(
+ &dd->pcidev->dev,
+ page,
+ offset,
+ len,
+ DMA_TO_DEVICE);
+
if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
sdma_txclean(dd, tx);
return -ENOSPC;
}
+
return _sdma_txadd_daddr(
dd, SDMA_MAP_PAGE, tx, addr, len);
}
@@ -846,6 +854,15 @@ static inline int sdma_txadd_daddr(
dma_addr_t addr,
u16 len)
{
+ int rval;
+
+ if ((unlikely(tx->num_desc == tx->desc_limit))) {
+ rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_NONE,
+ NULL, NULL, 0, 0);
+ if (rval <= 0)
+ return rval;
+ }
+
return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, tx, addr, len);
}
@@ -862,7 +879,7 @@ static inline int sdma_txadd_daddr(
* The mapping/unmapping of the kvaddr and len is automatically handled.
*
* Return:
- * 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't extend
+ * 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't extend/coalesce
* descriptor array
*/
static inline int sdma_txadd_kvaddr(
@@ -871,16 +888,27 @@ static inline int sdma_txadd_kvaddr(
void *kvaddr,
u16 len)
{
- dma_addr_t addr =
- dma_map_single(
- &dd->pcidev->dev,
- kvaddr,
- len,
- DMA_TO_DEVICE);
+ dma_addr_t addr;
+ int rval;
+
+ if ((unlikely(tx->num_desc == tx->desc_limit))) {
+ rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_SINGLE,
+ kvaddr, NULL, 0, len);
+ if (rval <= 0)
+ return rval;
+ }
+
+ addr = dma_map_single(
+ &dd->pcidev->dev,
+ kvaddr,
+ len,
+ DMA_TO_DEVICE);
+
if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
sdma_txclean(dd, tx);
return -ENOSPC;
}
+
return _sdma_txadd_daddr(
dd, SDMA_MAP_SINGLE, tx, addr, len);
}
@@ -962,7 +990,9 @@ static inline void sdma_iowait_schedule(
struct sdma_engine *sde,
struct iowait *wait)
{
- iowait_schedule(wait, sde->wq);
+ struct hfi1_pportdata *ppd = sde->dd->pport;
+
+ iowait_schedule(wait, ppd->hfi1_wq, sde->cpu);
}
/* for use by interrupt handling */
diff --git a/drivers/staging/rdma/hfi1/trace.c b/drivers/staging/rdma/hfi1/trace.c
index 70ad7b9fc1ce..f55b75194847 100644
--- a/drivers/staging/rdma/hfi1/trace.c
+++ b/drivers/staging/rdma/hfi1/trace.c
@@ -126,13 +126,13 @@ const char *parse_everbs_hdrs(
case OP(RC, ACKNOWLEDGE):
trace_seq_printf(p, AETH_PRN,
be32_to_cpu(eh->aeth) >> 24,
- be32_to_cpu(eh->aeth) & HFI1_QPN_MASK);
+ be32_to_cpu(eh->aeth) & HFI1_MSN_MASK);
break;
/* aeth + atomicacketh */
case OP(RC, ATOMIC_ACKNOWLEDGE):
trace_seq_printf(p, AETH_PRN " " ATOMICACKETH_PRN,
(be32_to_cpu(eh->at.aeth) >> 24) & 0xff,
- be32_to_cpu(eh->at.aeth) & HFI1_QPN_MASK,
+ be32_to_cpu(eh->at.aeth) & HFI1_MSN_MASK,
(unsigned long long)ib_u64_get(eh->at.atomic_ack_eth));
break;
/* atomiceth */
diff --git a/drivers/staging/rdma/hfi1/trace.h b/drivers/staging/rdma/hfi1/trace.h
index d7851c0a0171..57430295c404 100644
--- a/drivers/staging/rdma/hfi1/trace.h
+++ b/drivers/staging/rdma/hfi1/trace.h
@@ -1252,37 +1252,61 @@ TRACE_EVENT(hfi1_sdma_state,
#undef TRACE_SYSTEM
#define TRACE_SYSTEM hfi1_rc
-DECLARE_EVENT_CLASS(hfi1_sdma_rc,
+DECLARE_EVENT_CLASS(hfi1_rc_template,
TP_PROTO(struct hfi1_qp *qp, u32 psn),
TP_ARGS(qp, psn),
TP_STRUCT__entry(
DD_DEV_ENTRY(dd_from_ibdev(qp->ibqp.device))
__field(u32, qpn)
- __field(u32, flags)
+ __field(u32, s_flags)
__field(u32, psn)
- __field(u32, sending_psn)
- __field(u32, sending_hpsn)
+ __field(u32, s_psn)
+ __field(u32, s_next_psn)
+ __field(u32, s_sending_psn)
+ __field(u32, s_sending_hpsn)
+ __field(u32, r_psn)
),
TP_fast_assign(
DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device))
__entry->qpn = qp->ibqp.qp_num;
- __entry->flags = qp->s_flags;
+ __entry->s_flags = qp->s_flags;
__entry->psn = psn;
- __entry->sending_psn = qp->s_sending_psn;
- __entry->sending_hpsn = qp->s_sending_hpsn;
+ __entry->s_psn = qp->s_psn;
+ __entry->s_next_psn = qp->s_next_psn;
+ __entry->s_sending_psn = qp->s_sending_psn;
+ __entry->s_sending_hpsn = qp->s_sending_hpsn;
+ __entry->r_psn = qp->r_psn;
),
TP_printk(
- "[%s] qpn 0x%x flags 0x%x psn 0x%x sending_psn 0x%x sending_hpsn 0x%x",
+ "[%s] qpn 0x%x s_flags 0x%x psn 0x%x s_psn 0x%x s_next_psn 0x%x s_sending_psn 0x%x sending_hpsn 0x%x r_psn 0x%x",
__get_str(dev),
__entry->qpn,
- __entry->flags,
+ __entry->s_flags,
__entry->psn,
- __entry->sending_psn,
- __entry->sending_psn
+ __entry->s_psn,
+ __entry->s_next_psn,
+ __entry->s_sending_psn,
+ __entry->s_sending_hpsn,
+ __entry->r_psn
)
);
-DEFINE_EVENT(hfi1_sdma_rc, hfi1_rc_sendcomplete,
+DEFINE_EVENT(hfi1_rc_template, hfi1_rc_sendcomplete,
+ TP_PROTO(struct hfi1_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_rc_ack,
+ TP_PROTO(struct hfi1_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_rc_timeout,
+ TP_PROTO(struct hfi1_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_rc_rcv_error,
TP_PROTO(struct hfi1_qp *qp, u32 psn),
TP_ARGS(qp, psn)
);
diff --git a/drivers/staging/rdma/hfi1/uc.c b/drivers/staging/rdma/hfi1/uc.c
index b536f397737c..4f2a7889a852 100644
--- a/drivers/staging/rdma/hfi1/uc.c
+++ b/drivers/staging/rdma/hfi1/uc.c
@@ -147,9 +147,9 @@ int hfi1_make_uc_req(struct hfi1_qp *qp)
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
hwords += sizeof(struct ib_reth) / 4;
if (len > pmtu) {
@@ -268,7 +268,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
u32 tlen = packet->tlen;
struct hfi1_qp *qp = packet->qp;
struct hfi1_other_headers *ohdr = packet->ohdr;
- u32 opcode;
+ u32 bth0, opcode;
u32 hdrsize = packet->hlen;
u32 psn;
u32 pad;
@@ -278,10 +278,9 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
int has_grh = rcv_flags & HFI1_HAS_GRH;
int ret;
u32 bth1;
- struct ib_grh *grh = NULL;
- opcode = be32_to_cpu(ohdr->bth[0]);
- if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
+ bth0 = be32_to_cpu(ohdr->bth[0]);
+ if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
return;
bth1 = be32_to_cpu(ohdr->bth[1]);
@@ -303,6 +302,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
}
if (bth1 & HFI1_FECN_SMASK) {
+ struct ib_grh *grh = NULL;
u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]);
u16 slid = be16_to_cpu(hdr->lrh[3]);
u16 dlid = be16_to_cpu(hdr->lrh[1]);
@@ -310,13 +310,16 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
u8 sc5;
sc5 = ibp->sl_to_sc[qp->remote_ah_attr.sl];
+ if (has_grh)
+ grh = &hdr->u.l.grh;
- return_cnp(ibp, qp, src_qp, pkey, dlid, slid, sc5, grh);
+ return_cnp(ibp, qp, src_qp, pkey, dlid, slid, sc5,
+ grh);
}
}
psn = be32_to_cpu(ohdr->bth[2]);
- opcode >>= 24;
+ opcode = (bth0 >> 24) & 0xff;
/* Compare the PSN verses the expected PSN. */
if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) {
diff --git a/drivers/staging/rdma/hfi1/ud.c b/drivers/staging/rdma/hfi1/ud.c
index d40d1a1e10aa..54ff1f5416d4 100644
--- a/drivers/staging/rdma/hfi1/ud.c
+++ b/drivers/staging/rdma/hfi1/ud.c
@@ -80,7 +80,7 @@ static void ud_loopback(struct hfi1_qp *sqp, struct hfi1_swqe *swqe)
rcu_read_lock();
- qp = hfi1_lookup_qpn(ibp, swqe->wr.wr.ud.remote_qpn);
+ qp = hfi1_lookup_qpn(ibp, swqe->ud_wr.remote_qpn);
if (!qp) {
ibp->n_pkt_drops++;
rcu_read_unlock();
@@ -98,7 +98,7 @@ static void ud_loopback(struct hfi1_qp *sqp, struct hfi1_swqe *swqe)
goto drop;
}
- ah_attr = &to_iah(swqe->wr.wr.ud.ah)->attr;
+ ah_attr = &to_iah(swqe->ud_wr.ah)->attr;
ppd = ppd_from_ibp(ibp);
if (qp->ibqp.qp_num > 1) {
@@ -128,8 +128,8 @@ static void ud_loopback(struct hfi1_qp *sqp, struct hfi1_swqe *swqe)
if (qp->ibqp.qp_num) {
u32 qkey;
- qkey = (int)swqe->wr.wr.ud.remote_qkey < 0 ?
- sqp->qkey : swqe->wr.wr.ud.remote_qkey;
+ qkey = (int)swqe->ud_wr.remote_qkey < 0 ?
+ sqp->qkey : swqe->ud_wr.remote_qkey;
if (unlikely(qkey != qp->qkey)) {
u16 lid;
@@ -234,7 +234,7 @@ static void ud_loopback(struct hfi1_qp *sqp, struct hfi1_swqe *swqe)
if (qp->ibqp.qp_type == IB_QPT_GSI || qp->ibqp.qp_type == IB_QPT_SMI) {
if (sqp->ibqp.qp_type == IB_QPT_GSI ||
sqp->ibqp.qp_type == IB_QPT_SMI)
- wc.pkey_index = swqe->wr.wr.ud.pkey_index;
+ wc.pkey_index = swqe->ud_wr.pkey_index;
else
wc.pkey_index = sqp->s_pkey_index;
} else {
@@ -309,7 +309,7 @@ int hfi1_make_ud_req(struct hfi1_qp *qp)
/* Construct the header. */
ibp = to_iport(qp->ibqp.device, qp->port_num);
ppd = ppd_from_ibp(ibp);
- ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr;
+ ah_attr = &to_iah(wqe->ud_wr.ah)->attr;
if (ah_attr->dlid < HFI1_MULTICAST_LID_BASE ||
ah_attr->dlid == HFI1_PERMISSIVE_LID) {
lid = ah_attr->dlid & ~((1 << ppd->lmc) - 1);
@@ -383,6 +383,7 @@ int hfi1_make_ud_req(struct hfi1_qp *qp)
lrh0 |= (sc5 & 0xf) << 12;
qp->s_sc = sc5;
}
+ qp->s_sde = qp_to_sdma_engine(qp, qp->s_sc);
qp->s_hdr->ibh.lrh[0] = cpu_to_be16(lrh0);
qp->s_hdr->ibh.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */
qp->s_hdr->ibh.lrh[2] =
@@ -401,18 +402,18 @@ int hfi1_make_ud_req(struct hfi1_qp *qp)
bth0 |= IB_BTH_SOLICITED;
bth0 |= extra_bytes << 20;
if (qp->ibqp.qp_type == IB_QPT_GSI || qp->ibqp.qp_type == IB_QPT_SMI)
- bth0 |= hfi1_get_pkey(ibp, wqe->wr.wr.ud.pkey_index);
+ bth0 |= hfi1_get_pkey(ibp, wqe->ud_wr.pkey_index);
else
bth0 |= hfi1_get_pkey(ibp, qp->s_pkey_index);
ohdr->bth[0] = cpu_to_be32(bth0);
- ohdr->bth[1] = cpu_to_be32(wqe->wr.wr.ud.remote_qpn);
+ ohdr->bth[1] = cpu_to_be32(wqe->ud_wr.remote_qpn);
ohdr->bth[2] = cpu_to_be32(mask_psn(qp->s_next_psn++));
/*
* Qkeys with the high order bit set mean use the
* qkey from the QP context instead of the WR (see 10.2.5).
*/
- ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->wr.wr.ud.remote_qkey < 0 ?
- qp->qkey : wqe->wr.wr.ud.remote_qkey);
+ ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->ud_wr.remote_qkey < 0 ?
+ qp->qkey : wqe->ud_wr.remote_qkey);
ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
/* disarm any ahg */
qp->s_hdr->ahgcount = 0;
diff --git a/drivers/staging/rdma/hfi1/user_exp_rcv.h b/drivers/staging/rdma/hfi1/user_exp_rcv.h
new file mode 100644
index 000000000000..4f4876e1d353
--- /dev/null
+++ b/drivers/staging/rdma/hfi1/user_exp_rcv.h
@@ -0,0 +1,74 @@
+#ifndef _HFI1_USER_EXP_RCV_H
+#define _HFI1_USER_EXP_RCV_H
+/*
+ *
+ * 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 Corporation.
+ *
+ * This program 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.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of 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.
+ *
+ */
+
+#define EXP_TID_TIDLEN_MASK 0x7FFULL
+#define EXP_TID_TIDLEN_SHIFT 0
+#define EXP_TID_TIDCTRL_MASK 0x3ULL
+#define EXP_TID_TIDCTRL_SHIFT 20
+#define EXP_TID_TIDIDX_MASK 0x3FFULL
+#define EXP_TID_TIDIDX_SHIFT 22
+#define EXP_TID_GET(tid, field) \
+ (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK)
+
+#define EXP_TID_SET(field, value) \
+ (((value) & EXP_TID_TID##field##_MASK) << \
+ EXP_TID_TID##field##_SHIFT)
+#define EXP_TID_CLEAR(tid, field) ({ \
+ (tid) &= ~(EXP_TID_TID##field##_MASK << \
+ EXP_TID_TID##field##_SHIFT); \
+ })
+#define EXP_TID_RESET(tid, field, value) do { \
+ EXP_TID_CLEAR(tid, field); \
+ (tid) |= EXP_TID_SET(field, (value)); \
+ } while (0)
+
+#endif /* _HFI1_USER_EXP_RCV_H */
diff --git a/drivers/staging/rdma/hfi1/user_sdma.c b/drivers/staging/rdma/hfi1/user_sdma.c
index 10ab8073d3f2..41408f82afe8 100644
--- a/drivers/staging/rdma/hfi1/user_sdma.c
+++ b/drivers/staging/rdma/hfi1/user_sdma.c
@@ -146,7 +146,8 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12
#define KDETH_OM_MAX_SIZE (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1))
/* Last packet in the request */
-#define USER_SDMA_TXREQ_FLAGS_LAST_PKT (1 << 0)
+#define TXREQ_FLAGS_REQ_LAST_PKT BIT(0)
+#define TXREQ_FLAGS_IOVEC_LAST_PKT BIT(0)
#define SDMA_REQ_IN_USE 0
#define SDMA_REQ_FOR_THREAD 1
@@ -155,9 +156,9 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12
#define SDMA_REQ_HAS_ERROR 4
#define SDMA_REQ_DONE_ERROR 5
-#define SDMA_PKT_Q_INACTIVE (1 << 0)
-#define SDMA_PKT_Q_ACTIVE (1 << 1)
-#define SDMA_PKT_Q_DEFERRED (1 << 2)
+#define SDMA_PKT_Q_INACTIVE BIT(0)
+#define SDMA_PKT_Q_ACTIVE BIT(1)
+#define SDMA_PKT_Q_DEFERRED BIT(2)
/*
* Maximum retry attempts to submit a TX request
@@ -249,13 +250,22 @@ struct user_sdma_request {
unsigned long flags;
};
+/*
+ * A single txreq could span up to 3 physical pages when the MTU
+ * is sufficiently large (> 4K). Each of the IOV pointers also
+ * needs it's own set of flags so the vector has been handled
+ * independently of each other.
+ */
struct user_sdma_txreq {
/* Packet header for the txreq */
struct hfi1_pkt_header hdr;
struct sdma_txreq txreq;
struct user_sdma_request *req;
- struct user_sdma_iovec *iovec1;
- struct user_sdma_iovec *iovec2;
+ struct {
+ struct user_sdma_iovec *vec;
+ u8 flags;
+ } iovecs[3];
+ int idx;
u16 flags;
unsigned busycount;
u64 seqnum;
@@ -294,21 +304,6 @@ static int defer_packet_queue(
unsigned seq);
static void activate_packet_queue(struct iowait *, int);
-static inline int iovec_may_free(struct user_sdma_iovec *iovec,
- void (*free)(struct user_sdma_iovec *))
-{
- if (ACCESS_ONCE(iovec->offset) == iovec->iov.iov_len) {
- free(iovec);
- return 1;
- }
- return 0;
-}
-
-static inline void iovec_set_complete(struct user_sdma_iovec *iovec)
-{
- iovec->offset = iovec->iov.iov_len;
-}
-
static int defer_packet_queue(
struct sdma_engine *sde,
struct iowait *wait,
@@ -357,6 +352,7 @@ static void sdma_kmem_cache_ctor(void *obj)
int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
{
+ struct hfi1_filedata *fd;
int ret = 0;
unsigned memsize;
char buf[64];
@@ -370,6 +366,8 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
goto done;
}
+ fd = fp->private_data;
+
if (!hfi1_sdma_comp_ring_size) {
ret = -EINVAL;
goto done;
@@ -389,7 +387,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
INIT_LIST_HEAD(&pq->list);
pq->dd = dd;
pq->ctxt = uctxt->ctxt;
- pq->subctxt = subctxt_fp(fp);
+ pq->subctxt = fd->subctxt;
pq->n_max_reqs = hfi1_sdma_comp_ring_size;
pq->state = SDMA_PKT_Q_INACTIVE;
atomic_set(&pq->n_reqs, 0);
@@ -398,7 +396,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
activate_packet_queue);
pq->reqidx = 0;
snprintf(buf, 64, "txreq-kmem-cache-%u-%u-%u", dd->unit, uctxt->ctxt,
- subctxt_fp(fp));
+ fd->subctxt);
pq->txreq_cache = kmem_cache_create(buf,
sizeof(struct user_sdma_txreq),
L1_CACHE_BYTES,
@@ -409,7 +407,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
uctxt->ctxt);
goto pq_txreq_nomem;
}
- user_sdma_pkt_fp(fp) = pq;
+ fd->pq = pq;
cq = kzalloc(sizeof(*cq), GFP_KERNEL);
if (!cq)
goto cq_nomem;
@@ -421,7 +419,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
goto cq_comps_nomem;
cq->nentries = hfi1_sdma_comp_ring_size;
- user_sdma_comp_fp(fp) = cq;
+ fd->cq = cq;
spin_lock_irqsave(&uctxt->sdma_qlock, flags);
list_add(&pq->list, &uctxt->sdma_queues);
@@ -436,7 +434,7 @@ pq_txreq_nomem:
kfree(pq->reqs);
pq_reqs_nomem:
kfree(pq);
- user_sdma_pkt_fp(fp) = NULL;
+ fd->pq = NULL;
pq_nomem:
ret = -ENOMEM;
done:
@@ -490,9 +488,10 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
unsigned long dim, unsigned long *count)
{
int ret = 0, i = 0, sent;
- struct hfi1_ctxtdata *uctxt = ctxt_fp(fp);
- struct hfi1_user_sdma_pkt_q *pq = user_sdma_pkt_fp(fp);
- struct hfi1_user_sdma_comp_q *cq = user_sdma_comp_fp(fp);
+ struct hfi1_filedata *fd = fp->private_data;
+ struct hfi1_ctxtdata *uctxt = fd->uctxt;
+ struct hfi1_user_sdma_pkt_q *pq = fd->pq;
+ struct hfi1_user_sdma_comp_q *cq = fd->cq;
struct hfi1_devdata *dd = pq->dd;
unsigned long idx = 0;
u8 pcount = initial_pkt_count;
@@ -504,7 +503,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
hfi1_cdbg(
SDMA,
"[%u:%u:%u] First vector not big enough for header %lu/%lu",
- dd->unit, uctxt->ctxt, subctxt_fp(fp),
+ dd->unit, uctxt->ctxt, fd->subctxt,
iovec[idx].iov_len, sizeof(info) + sizeof(req->hdr));
ret = -EINVAL;
goto done;
@@ -512,15 +511,15 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
ret = copy_from_user(&info, iovec[idx].iov_base, sizeof(info));
if (ret) {
hfi1_cdbg(SDMA, "[%u:%u:%u] Failed to copy info QW (%d)",
- dd->unit, uctxt->ctxt, subctxt_fp(fp), ret);
+ dd->unit, uctxt->ctxt, fd->subctxt, ret);
ret = -EFAULT;
goto done;
}
- trace_hfi1_sdma_user_reqinfo(dd, uctxt->ctxt, subctxt_fp(fp),
+ trace_hfi1_sdma_user_reqinfo(dd, uctxt->ctxt, fd->subctxt,
(u16 *)&info);
if (cq->comps[info.comp_idx].status == QUEUED) {
hfi1_cdbg(SDMA, "[%u:%u:%u] Entry %u is in QUEUED state",
- dd->unit, uctxt->ctxt, subctxt_fp(fp),
+ dd->unit, uctxt->ctxt, fd->subctxt,
info.comp_idx);
ret = -EBADSLT;
goto done;
@@ -528,7 +527,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
if (!info.fragsize) {
hfi1_cdbg(SDMA,
"[%u:%u:%u:%u] Request does not specify fragsize",
- dd->unit, uctxt->ctxt, subctxt_fp(fp), info.comp_idx);
+ dd->unit, uctxt->ctxt, fd->subctxt, info.comp_idx);
ret = -EINVAL;
goto done;
}
@@ -537,7 +536,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
* "allocate" the request entry.
*/
hfi1_cdbg(SDMA, "[%u:%u:%u] Using req/comp entry %u\n", dd->unit,
- uctxt->ctxt, subctxt_fp(fp), info.comp_idx);
+ uctxt->ctxt, fd->subctxt, info.comp_idx);
req = pq->reqs + info.comp_idx;
memset(req, 0, sizeof(*req));
/* Mark the request as IN_USE before we start filling it in. */
@@ -664,7 +663,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
/* Have to select the engine */
req->sde = sdma_select_engine_vl(dd,
- (u32)(uctxt->ctxt + subctxt_fp(fp)),
+ (u32)(uctxt->ctxt + fd->subctxt),
vl);
if (!req->sde || !sdma_running(req->sde)) {
ret = -ECOMM;
@@ -825,11 +824,11 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
tx->flags = 0;
tx->req = req;
tx->busycount = 0;
- tx->iovec1 = NULL;
- tx->iovec2 = NULL;
+ tx->idx = -1;
+ memset(tx->iovecs, 0, sizeof(tx->iovecs));
if (req->seqnum == req->info.npkts - 1)
- tx->flags |= USER_SDMA_TXREQ_FLAGS_LAST_PKT;
+ tx->flags |= TXREQ_FLAGS_REQ_LAST_PKT;
/*
* Calculate the payload size - this is min of the fragment
@@ -858,7 +857,7 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
goto free_tx;
}
- tx->iovec1 = iovec;
+ tx->iovecs[++tx->idx].vec = iovec;
datalen = compute_data_length(req, tx);
if (!datalen) {
SDMA_DBG(req,
@@ -948,10 +947,17 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
iovec->pages[pageidx],
offset, len);
if (ret) {
+ int i;
+
dd_dev_err(pq->dd,
"SDMA txreq add page failed %d\n",
ret);
- iovec_set_complete(iovec);
+ /* Mark all assigned vectors as complete so they
+ * are unpinned in the callback. */
+ for (i = tx->idx; i >= 0; i--) {
+ tx->iovecs[i].flags |=
+ TXREQ_FLAGS_IOVEC_LAST_PKT;
+ }
goto free_txreq;
}
iov_offset += len;
@@ -959,8 +965,11 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
data_sent += len;
if (unlikely(queued < datalen &&
pageidx == iovec->npages &&
- req->iov_idx < req->data_iovs - 1)) {
+ req->iov_idx < req->data_iovs - 1 &&
+ tx->idx < ARRAY_SIZE(tx->iovecs))) {
iovec->offset += iov_offset;
+ tx->iovecs[tx->idx].flags |=
+ TXREQ_FLAGS_IOVEC_LAST_PKT;
iovec = &req->iovs[++req->iov_idx];
if (!iovec->pages) {
ret = pin_vector_pages(req, iovec);
@@ -968,8 +977,7 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
goto free_txreq;
}
iov_offset = 0;
- tx->iovec2 = iovec;
-
+ tx->iovecs[++tx->idx].vec = iovec;
}
}
/*
@@ -981,11 +989,15 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
req->tidoffset += datalen;
req->sent += data_sent;
if (req->data_len) {
- if (tx->iovec1 && !tx->iovec2)
- tx->iovec1->offset += iov_offset;
- else if (tx->iovec2)
- tx->iovec2->offset += iov_offset;
+ tx->iovecs[tx->idx].vec->offset += iov_offset;
+ /* If we've reached the end of the io vector, mark it
+ * so the callback can unpin the pages and free it. */
+ if (tx->iovecs[tx->idx].vec->offset ==
+ tx->iovecs[tx->idx].vec->iov.iov_len)
+ tx->iovecs[tx->idx].flags |=
+ TXREQ_FLAGS_IOVEC_LAST_PKT;
}
+
/*
* It is important to increment this here as it is used to
* generate the BTH.PSN and, therefore, can't be bulk-updated
@@ -1214,7 +1226,7 @@ static int set_txreq_header(struct user_sdma_request *req,
req->seqnum));
/* Set ACK request on last packet */
- if (unlikely(tx->flags & USER_SDMA_TXREQ_FLAGS_LAST_PKT))
+ if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT))
hdr->bth[2] |= cpu_to_be32(1UL<<31);
/* Set the new offset */
@@ -1246,7 +1258,7 @@ static int set_txreq_header(struct user_sdma_request *req,
KDETH_SET(hdr->kdeth.ver_tid_offset, TID,
EXP_TID_GET(tidval, IDX));
/* Clear KDETH.SH only on the last packet */
- if (unlikely(tx->flags & USER_SDMA_TXREQ_FLAGS_LAST_PKT))
+ if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT))
KDETH_SET(hdr->kdeth.ver_tid_offset, SH, 0);
/*
* Set the KDETH.OFFSET and KDETH.OM based on size of
@@ -1290,7 +1302,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
/* BTH.PSN and BTH.A */
val32 = (be32_to_cpu(hdr->bth[2]) + req->seqnum) &
(HFI1_CAP_IS_KSET(EXTENDED_PSN) ? 0x7fffffff : 0xffffff);
- if (unlikely(tx->flags & USER_SDMA_TXREQ_FLAGS_LAST_PKT))
+ if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT))
val32 |= 1UL << 31;
AHG_HEADER_SET(req->ahg, diff, 6, 0, 16, cpu_to_be16(val32 >> 16));
AHG_HEADER_SET(req->ahg, diff, 6, 16, 16, cpu_to_be16(val32 & 0xffff));
@@ -1331,7 +1343,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
val = cpu_to_le16(((EXP_TID_GET(tidval, CTRL) & 0x3) << 10) |
(EXP_TID_GET(tidval, IDX) & 0x3ff));
/* Clear KDETH.SH on last packet */
- if (unlikely(tx->flags & USER_SDMA_TXREQ_FLAGS_LAST_PKT)) {
+ if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT)) {
val |= cpu_to_le16(KDETH_GET(hdr->kdeth.ver_tid_offset,
INTR) >> 16);
val &= cpu_to_le16(~(1U << 13));
@@ -1358,10 +1370,16 @@ static void user_sdma_txreq_cb(struct sdma_txreq *txreq, int status,
if (unlikely(!req || !pq))
return;
- if (tx->iovec1)
- iovec_may_free(tx->iovec1, unpin_vector_pages);
- if (tx->iovec2)
- iovec_may_free(tx->iovec2, unpin_vector_pages);
+ /* If we have any io vectors associated with this txreq,
+ * check whether they need to be 'freed'. */
+ if (tx->idx != -1) {
+ int i;
+
+ for (i = tx->idx; i >= 0; i--) {
+ if (tx->iovecs[i].flags & TXREQ_FLAGS_IOVEC_LAST_PKT)
+ unpin_vector_pages(tx->iovecs[i].vec);
+ }
+ }
tx_seqnum = tx->seqnum;
kmem_cache_free(pq->txreq_cache, tx);
diff --git a/drivers/staging/rdma/hfi1/user_sdma.h b/drivers/staging/rdma/hfi1/user_sdma.h
index fa4422553e23..0046ffa774fe 100644
--- a/drivers/staging/rdma/hfi1/user_sdma.h
+++ b/drivers/staging/rdma/hfi1/user_sdma.h
@@ -52,15 +52,7 @@
#include "common.h"
#include "iowait.h"
-
-#define EXP_TID_TIDLEN_MASK 0x7FFULL
-#define EXP_TID_TIDLEN_SHIFT 0
-#define EXP_TID_TIDCTRL_MASK 0x3ULL
-#define EXP_TID_TIDCTRL_SHIFT 20
-#define EXP_TID_TIDIDX_MASK 0x7FFULL
-#define EXP_TID_TIDIDX_SHIFT 22
-#define EXP_TID_GET(tid, field) \
- (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK)
+#include "user_exp_rcv.h"
extern uint extended_psn;
diff --git a/drivers/staging/rdma/hfi1/verbs.c b/drivers/staging/rdma/hfi1/verbs.c
index 45f291fd3236..ef0feaa684a4 100644
--- a/drivers/staging/rdma/hfi1/verbs.c
+++ b/drivers/staging/rdma/hfi1/verbs.c
@@ -129,6 +129,9 @@ static void verbs_sdma_complete(
int status,
int drained);
+/* Length of buffer to create verbs txreq cache name */
+#define TXREQ_NAME_LEN 24
+
/*
* Note that it is OK to post send work requests in the SQE and ERR
* states; hfi1_do_send() will process them and generate error
@@ -159,6 +162,8 @@ static inline struct hfi1_ucontext *to_iucontext(struct ib_ucontext
return container_of(ibucontext, struct hfi1_ucontext, ibucontext);
}
+static inline void _hfi1_schedule_send(struct hfi1_qp *qp);
+
/*
* Translate ib_wr_opcode into ib_wc_opcode.
*/
@@ -380,9 +385,7 @@ static int post_one_send(struct hfi1_qp *qp, struct ib_send_wr *wr)
* undefined operations.
* Make sure buffer is large enough to hold the result for atomics.
*/
- if (wr->opcode == IB_WR_FAST_REG_MR) {
- return -EINVAL;
- } else if (qp->ibqp.qp_type == IB_QPT_UC) {
+ if (qp->ibqp.qp_type == IB_QPT_UC) {
if ((unsigned) wr->opcode >= IB_WR_RDMA_READ)
return -EINVAL;
} else if (qp->ibqp.qp_type != IB_QPT_RC) {
@@ -391,7 +394,7 @@ static int post_one_send(struct hfi1_qp *qp, struct ib_send_wr *wr)
wr->opcode != IB_WR_SEND_WITH_IMM)
return -EINVAL;
/* Check UD destination address PD */
- if (qp->ibqp.pd != wr->wr.ud.ah->pd)
+ if (qp->ibqp.pd != ud_wr(wr)->ah->pd)
return -EINVAL;
} else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD)
return -EINVAL;
@@ -412,7 +415,21 @@ static int post_one_send(struct hfi1_qp *qp, struct ib_send_wr *wr)
rkt = &to_idev(qp->ibqp.device)->lk_table;
pd = to_ipd(qp->ibqp.pd);
wqe = get_swqe_ptr(qp, qp->s_head);
- wqe->wr = *wr;
+
+
+ if (qp->ibqp.qp_type != IB_QPT_UC &&
+ qp->ibqp.qp_type != IB_QPT_RC)
+ memcpy(&wqe->ud_wr, ud_wr(wr), sizeof(wqe->ud_wr));
+ else if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE ||
+ wr->opcode == IB_WR_RDMA_READ)
+ memcpy(&wqe->rdma_wr, rdma_wr(wr), sizeof(wqe->rdma_wr));
+ else if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+ wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+ memcpy(&wqe->atomic_wr, atomic_wr(wr), sizeof(wqe->atomic_wr));
+ else
+ memcpy(&wqe->wr, wr, sizeof(wqe->wr));
+
wqe->length = 0;
j = 0;
if (wr->num_sge) {
@@ -438,7 +455,7 @@ static int post_one_send(struct hfi1_qp *qp, struct ib_send_wr *wr)
if (wqe->length > 0x80000000U)
goto bail_inval_free;
} else {
- struct hfi1_ah *ah = to_iah(wr->wr.ud.ah);
+ struct hfi1_ah *ah = to_iah(ud_wr(wr)->ah);
atomic_inc(&ah->refcount);
}
@@ -494,9 +511,9 @@ static int post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
nreq++;
}
bail:
- if (nreq && !call_send)
- hfi1_schedule_send(qp);
spin_unlock_irqrestore(&qp->s_lock, flags);
+ if (nreq && !call_send)
+ _hfi1_schedule_send(qp);
if (nreq && call_send)
hfi1_do_send(&qp->s_iowait.iowork);
return err;
@@ -597,6 +614,7 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
u32 tlen = packet->tlen;
struct hfi1_pportdata *ppd = rcd->ppd;
struct hfi1_ibport *ibp = &ppd->ibport_data;
+ unsigned long flags;
u32 qp_num;
int lnh;
u8 opcode;
@@ -639,10 +657,10 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
goto drop;
list_for_each_entry_rcu(p, &mcast->qp_list, list) {
packet->qp = p->qp;
- spin_lock(&packet->qp->r_lock);
+ spin_lock_irqsave(&packet->qp->r_lock, flags);
if (likely((qp_ok(opcode, packet))))
opcode_handler_tbl[opcode](packet);
- spin_unlock(&packet->qp->r_lock);
+ spin_unlock_irqrestore(&packet->qp->r_lock, flags);
}
/*
* Notify hfi1_multicast_detach() if it is waiting for us
@@ -657,10 +675,10 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
rcu_read_unlock();
goto drop;
}
- spin_lock(&packet->qp->r_lock);
+ spin_lock_irqsave(&packet->qp->r_lock, flags);
if (likely((qp_ok(opcode, packet))))
opcode_handler_tbl[opcode](packet);
- spin_unlock(&packet->qp->r_lock);
+ spin_unlock_irqrestore(&packet->qp->r_lock, flags);
rcu_read_unlock();
}
return;
@@ -983,17 +1001,19 @@ bail_txadd:
return ret;
}
-int hfi1_verbs_send_dma(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc)
+int hfi1_verbs_send_dma(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc)
{
- struct hfi1_ibdev *dev = to_idev(qp->ibqp.device);
- struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+ struct ahg_ib_header *ahdr = qp->s_hdr;
+ u32 hdrwords = qp->s_hdrwords;
+ struct hfi1_sge_state *ss = qp->s_cur_sge;
+ u32 len = qp->s_cur_size;
+ u32 plen = hdrwords + ((len + 3) >> 2) + 2; /* includes pbc */
+ struct hfi1_ibdev *dev = ps->dev;
+ struct hfi1_pportdata *ppd = ps->ppd;
struct verbs_txreq *tx;
struct sdma_txreq *stx;
u64 pbc_flags = 0;
- struct sdma_engine *sde;
u8 sc5 = qp->s_sc;
int ret;
@@ -1014,12 +1034,7 @@ int hfi1_verbs_send_dma(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
if (IS_ERR(tx))
goto bail_tx;
- if (!qp->s_hdr->sde) {
- tx->sde = sde = qp_to_sdma_engine(qp, sc5);
- if (!sde)
- goto bail_no_sde;
- } else
- tx->sde = sde = qp->s_hdr->sde;
+ tx->sde = qp->s_sde;
if (likely(pbc == 0)) {
u32 vl = sc_to_vlt(dd_from_ibdev(qp->ibqp.device), sc5);
@@ -1034,17 +1049,15 @@ int hfi1_verbs_send_dma(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
if (qp->s_rdma_mr)
qp->s_rdma_mr = NULL;
tx->hdr_dwords = hdrwords + 2;
- ret = build_verbs_tx_desc(sde, ss, len, tx, ahdr, pbc);
+ ret = build_verbs_tx_desc(tx->sde, ss, len, tx, ahdr, pbc);
if (unlikely(ret))
goto bail_build;
trace_output_ibhdr(dd_from_ibdev(qp->ibqp.device), &ahdr->ibh);
- ret = sdma_send_txreq(sde, &qp->s_iowait, &tx->txreq);
+ ret = sdma_send_txreq(tx->sde, &qp->s_iowait, &tx->txreq);
if (unlikely(ret == -ECOMM))
goto bail_ecomm;
return ret;
-bail_no_sde:
- hfi1_put_txreq(tx);
bail_ecomm:
/* The current one got "sent" */
return 0;
@@ -1110,12 +1123,16 @@ struct send_context *qp_to_send_context(struct hfi1_qp *qp, u8 sc5)
return dd->vld[vl].sc;
}
-int hfi1_verbs_send_pio(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc)
+int hfi1_verbs_send_pio(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc)
{
- struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+ struct ahg_ib_header *ahdr = qp->s_hdr;
+ u32 hdrwords = qp->s_hdrwords;
+ struct hfi1_sge_state *ss = qp->s_cur_sge;
+ u32 len = qp->s_cur_size;
+ u32 dwords = (len + 3) >> 2;
+ u32 plen = hdrwords + dwords + 2; /* includes pbc */
+ struct hfi1_pportdata *ppd = ps->ppd;
u32 *hdr = (u32 *)&ahdr->ibh;
u64 pbc_flags = 0;
u32 sc5;
@@ -1287,23 +1304,18 @@ bad:
/**
* hfi1_verbs_send - send a packet
* @qp: the QP to send on
- * @ahdr: the packet header
- * @hdrwords: the number of 32-bit words in the header
- * @ss: the SGE to send
- * @len: the length of the packet in bytes
+ * @ps: the state of the packet to send
*
* Return zero if packet is sent or queued OK.
* Return non-zero and clear qp->s_flags HFI1_S_BUSY otherwise.
*/
-int hfi1_verbs_send(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len)
+int hfi1_verbs_send(struct hfi1_qp *qp, struct hfi1_pkt_state *ps)
{
struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);
- u32 plen;
+ struct ahg_ib_header *ahdr = qp->s_hdr;
int ret;
int pio = 0;
unsigned long flags = 0;
- u32 dwords = (len + 3) >> 2;
/*
* VL15 packets (IB_QPT_SMI) will always use PIO, so we
@@ -1334,23 +1346,16 @@ int hfi1_verbs_send(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
return -EINVAL;
}
- /*
- * Calculate the send buffer trigger address.
- * The +2 counts for the pbc control qword
- */
- plen = hdrwords + dwords + 2;
-
if (pio) {
- ret = dd->process_pio_send(
- qp, ahdr, hdrwords, ss, len, plen, dwords, 0);
+ ret = dd->process_pio_send(qp, ps, 0);
} else {
#ifdef CONFIG_SDMA_VERBOSITY
dd_dev_err(dd, "CONFIG SDMA %s:%d %s()\n",
slashstrip(__FILE__), __LINE__, __func__);
- dd_dev_err(dd, "SDMA hdrwords = %u, len = %u\n", hdrwords, len);
+ dd_dev_err(dd, "SDMA hdrwords = %u, len = %u\n", qp->s_hdrwords,
+ qp->s_cur_size);
#endif
- ret = dd->process_dma_send(
- qp, ahdr, hdrwords, ss, len, plen, dwords, 0);
+ ret = dd->process_dma_send(qp, ps, 0);
}
return ret;
@@ -1904,6 +1909,7 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
int ret;
size_t lcpysz = IB_DEVICE_NAME_MAX;
u16 descq_cnt;
+ char buf[TXREQ_NAME_LEN];
ret = hfi1_qp_init(dev);
if (ret)
@@ -1957,8 +1963,9 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
descq_cnt = sdma_get_descq_cnt();
+ snprintf(buf, sizeof(buf), "hfi1_%u_vtxreq_cache", dd->unit);
/* SLAB_HWCACHE_ALIGN for AHG */
- dev->verbs_txreq_cache = kmem_cache_create("hfi1_vtxreq_cache",
+ dev->verbs_txreq_cache = kmem_cache_create(buf,
sizeof(struct verbs_txreq),
0, SLAB_HWCACHE_ALIGN,
verbs_txreq_kmem_cache_ctor);
@@ -2049,8 +2056,6 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
ibdev->reg_user_mr = hfi1_reg_user_mr;
ibdev->dereg_mr = hfi1_dereg_mr;
ibdev->alloc_mr = hfi1_alloc_mr;
- ibdev->alloc_fast_reg_page_list = hfi1_alloc_fast_reg_page_list;
- ibdev->free_fast_reg_page_list = hfi1_free_fast_reg_page_list;
ibdev->alloc_fmr = hfi1_alloc_fmr;
ibdev->map_phys_fmr = hfi1_map_phys_fmr;
ibdev->unmap_fmr = hfi1_unmap_fmr;
@@ -2119,28 +2124,43 @@ void hfi1_unregister_ib_device(struct hfi1_devdata *dd)
vfree(dev->lk_table.table);
}
-/*
- * This must be called with s_lock held.
- */
-void hfi1_schedule_send(struct hfi1_qp *qp)
-{
- if (hfi1_send_ok(qp)) {
- struct hfi1_ibport *ibp =
- to_iport(qp->ibqp.device, qp->port_num);
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
-
- iowait_schedule(&qp->s_iowait, ppd->hfi1_wq);
- }
-}
-
void hfi1_cnp_rcv(struct hfi1_packet *packet)
{
struct hfi1_ibport *ibp = &packet->rcd->ppd->ibport_data;
-
- if (packet->qp->ibqp.qp_type == IB_QPT_UC)
- hfi1_uc_rcv(packet);
- else if (packet->qp->ibqp.qp_type == IB_QPT_UD)
- hfi1_ud_rcv(packet);
- else
+ struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+ struct hfi1_ib_header *hdr = packet->hdr;
+ struct hfi1_qp *qp = packet->qp;
+ u32 lqpn, rqpn = 0;
+ u16 rlid = 0;
+ u8 sl, sc5, sc4_bit, svc_type;
+ bool sc4_set = has_sc4_bit(packet);
+
+ switch (packet->qp->ibqp.qp_type) {
+ case IB_QPT_UC:
+ rlid = qp->remote_ah_attr.dlid;
+ rqpn = qp->remote_qpn;
+ svc_type = IB_CC_SVCTYPE_UC;
+ break;
+ case IB_QPT_RC:
+ rlid = qp->remote_ah_attr.dlid;
+ rqpn = qp->remote_qpn;
+ svc_type = IB_CC_SVCTYPE_RC;
+ break;
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ svc_type = IB_CC_SVCTYPE_UD;
+ break;
+ default:
ibp->n_pkt_drops++;
+ return;
+ }
+
+ sc4_bit = sc4_set << 4;
+ sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf;
+ sc5 |= sc4_bit;
+ sl = ibp->sc_to_sl[sc5];
+ lqpn = qp->ibqp.qp_num;
+
+ process_becn(ppd, sl, rlid, lqpn, rqpn, svc_type);
}
diff --git a/drivers/staging/rdma/hfi1/verbs.h b/drivers/staging/rdma/hfi1/verbs.h
index ed903a93baf7..7e27531c430a 100644
--- a/drivers/staging/rdma/hfi1/verbs.h
+++ b/drivers/staging/rdma/hfi1/verbs.h
@@ -120,9 +120,9 @@ struct hfi1_packet;
#define HFI1_VENDOR_IPG cpu_to_be16(0xFFA0)
-#define IB_BTH_REQ_ACK (1 << 31)
-#define IB_BTH_SOLICITED (1 << 23)
-#define IB_BTH_MIG_REQ (1 << 22)
+#define IB_BTH_REQ_ACK BIT(31)
+#define IB_BTH_SOLICITED BIT(23)
+#define IB_BTH_MIG_REQ BIT(22)
#define IB_GRH_VERSION 6
#define IB_GRH_VERSION_MASK 0xF
@@ -348,7 +348,12 @@ struct hfi1_mr {
* in qp->s_max_sge.
*/
struct hfi1_swqe {
- struct ib_send_wr wr; /* don't use wr.sg_list */
+ union {
+ struct ib_send_wr wr; /* don't use wr.sg_list */
+ struct ib_rdma_wr rdma_wr;
+ struct ib_atomic_wr atomic_wr;
+ struct ib_ud_wr ud_wr;
+ };
u32 psn; /* first packet sequence number */
u32 lpsn; /* last packet sequence number */
u32 ssn; /* send sequence number */
@@ -436,7 +441,8 @@ struct hfi1_qp {
struct hfi1_swqe *s_wq; /* send work queue */
struct hfi1_mmap_info *ip;
struct ahg_ib_header *s_hdr; /* next packet header to send */
- u8 s_sc; /* SC[0..4] for next packet */
+ /* sc for UC/RC QPs - based on ah for UD */
+ u8 s_sc;
unsigned long timeout_jiffies; /* computed from timeout */
enum ib_mtu path_mtu;
@@ -484,6 +490,7 @@ struct hfi1_qp {
u32 r_psn; /* expected rcv packet sequence number */
u32 r_msn; /* message sequence number */
+ u8 r_adefered; /* number of acks defered */
u8 r_state; /* opcode of last packet received */
u8 r_flags;
u8 r_head_ack_queue; /* index into s_ack_queue[] */
@@ -539,6 +546,16 @@ struct hfi1_qp {
};
/*
+ * This structure is used to hold commonly lookedup and computed values during
+ * the send engine progress.
+ */
+struct hfi1_pkt_state {
+ struct hfi1_ibdev *dev;
+ struct hfi1_ibport *ibp;
+ struct hfi1_pportdata *ppd;
+};
+
+/*
* Atomic bit definitions for r_aflags.
*/
#define HFI1_R_WRID_VALID 0
@@ -547,11 +564,13 @@ struct hfi1_qp {
/*
* Bit definitions for r_flags.
*/
-#define HFI1_R_REUSE_SGE 0x01
-#define HFI1_R_RDMAR_SEQ 0x02
-#define HFI1_R_RSP_NAK 0x04
-#define HFI1_R_RSP_SEND 0x08
-#define HFI1_R_COMM_EST 0x10
+#define HFI1_R_REUSE_SGE 0x01
+#define HFI1_R_RDMAR_SEQ 0x02
+/* defer ack until end of interrupt session */
+#define HFI1_R_RSP_DEFERED_ACK 0x04
+/* relay ack to send engine */
+#define HFI1_R_RSP_SEND 0x08
+#define HFI1_R_COMM_EST 0x10
/*
* Bit definitions for s_flags.
@@ -754,6 +773,7 @@ struct hfi1_ibdev {
u64 n_piowait;
u64 n_txwait;
u64 n_kmem_wait;
+ u64 n_send_schedule;
u32 n_pds_allocated; /* number of PDs allocated for device */
spinlock_t n_pds_lock;
@@ -840,7 +860,6 @@ static inline int hfi1_send_ok(struct hfi1_qp *qp)
/*
* This must be called with s_lock held.
*/
-void hfi1_schedule_send(struct hfi1_qp *qp);
void hfi1_bad_pqkey(struct hfi1_ibport *ibp, __be16 trap_num, u32 key, u32 sl,
u32 qp1, u32 qp2, __be16 lid1, __be16 lid2);
void hfi1_cap_mask_chg(struct hfi1_ibport *ibp);
@@ -921,8 +940,7 @@ int hfi1_mcast_tree_empty(struct hfi1_ibport *ibp);
struct verbs_txreq;
void hfi1_put_txreq(struct verbs_txreq *tx);
-int hfi1_verbs_send(struct hfi1_qp *qp, struct ahg_ib_header *ahdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len);
+int hfi1_verbs_send(struct hfi1_qp *qp, struct hfi1_pkt_state *ps);
void hfi1_copy_sge(struct hfi1_sge_state *ss, void *data, u32 length,
int release);
@@ -1020,13 +1038,6 @@ struct ib_mr *hfi1_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_entries);
-struct ib_fast_reg_page_list *hfi1_alloc_fast_reg_page_list(
- struct ib_device *ibdev, int page_list_len);
-
-void hfi1_free_fast_reg_page_list(struct ib_fast_reg_page_list *pl);
-
-int hfi1_fast_reg_mr(struct hfi1_qp *qp, struct ib_send_wr *wr);
-
struct ib_fmr *hfi1_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
struct ib_fmr_attr *fmr_attr);
@@ -1070,16 +1081,12 @@ int hfi1_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
int hfi1_get_rwqe(struct hfi1_qp *qp, int wr_id_only);
-void hfi1_migrate_qp(struct hfi1_qp *qp);
-
int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_ib_header *hdr,
int has_grh, struct hfi1_qp *qp, u32 bth0);
u32 hfi1_make_grh(struct hfi1_ibport *ibp, struct ib_grh *hdr,
struct ib_global_route *grh, u32 hwords, u32 nwords);
-void clear_ahg(struct hfi1_qp *qp);
-
void hfi1_make_ruc_header(struct hfi1_qp *qp, struct hfi1_other_headers *ohdr,
u32 bth0, u32 bth2, int middle);
@@ -1104,13 +1111,11 @@ void hfi1_ib_rcv(struct hfi1_packet *packet);
unsigned hfi1_get_npkeys(struct hfi1_devdata *);
-int hfi1_verbs_send_dma(struct hfi1_qp *qp, struct ahg_ib_header *hdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc);
+int hfi1_verbs_send_dma(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc);
-int hfi1_verbs_send_pio(struct hfi1_qp *qp, struct ahg_ib_header *hdr,
- u32 hdrwords, struct hfi1_sge_state *ss, u32 len,
- u32 plen, u32 dwords, u64 pbc);
+int hfi1_verbs_send_pio(struct hfi1_qp *qp, struct hfi1_pkt_state *ps,
+ u64 pbc);
struct send_context *qp_to_send_context(struct hfi1_qp *qp, u8 sc5);
diff --git a/drivers/staging/rdma/ipath/ipath_driver.c b/drivers/staging/rdma/ipath/ipath_driver.c
index 46d98980d66a..2ab22f98e3ba 100644
--- a/drivers/staging/rdma/ipath/ipath_driver.c
+++ b/drivers/staging/rdma/ipath/ipath_driver.c
@@ -33,7 +33,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
#include <linux/pci.h>
@@ -2307,10 +2306,9 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
*/
if (atomic_inc_return(&dd->ipath_led_override_timer_active) == 1) {
/* Need to start timer */
- init_timer(&dd->ipath_led_override_timer);
- dd->ipath_led_override_timer.function =
- ipath_run_led_override;
- dd->ipath_led_override_timer.data = (unsigned long) dd;
+ setup_timer(&dd->ipath_led_override_timer,
+ ipath_run_led_override, (unsigned long)dd);
+
dd->ipath_led_override_timer.expires = jiffies + 1;
add_timer(&dd->ipath_led_override_timer);
} else
diff --git a/drivers/staging/rdma/ipath/ipath_file_ops.c b/drivers/staging/rdma/ipath/ipath_file_ops.c
index c796a51faa9c..6187b848b3ca 100644
--- a/drivers/staging/rdma/ipath/ipath_file_ops.c
+++ b/drivers/staging/rdma/ipath/ipath_file_ops.c
@@ -905,7 +905,7 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
* heavy filesystem activity makes these fail, and we can
* use compound pages.
*/
- gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP;
+ gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP;
egrcnt = dd->ipath_rcvegrcnt;
/* TID number offset for this port */
@@ -917,15 +917,15 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
chunk = pd->port_rcvegrbuf_chunks;
egrperchunk = pd->port_rcvegrbufs_perchunk;
size = pd->port_rcvegrbuf_size;
- pd->port_rcvegrbuf = kmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]),
- GFP_KERNEL);
+ pd->port_rcvegrbuf = kmalloc_array(chunk, sizeof(pd->port_rcvegrbuf[0]),
+ GFP_KERNEL);
if (!pd->port_rcvegrbuf) {
ret = -ENOMEM;
goto bail;
}
pd->port_rcvegrbuf_phys =
- kmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]),
- GFP_KERNEL);
+ kmalloc_array(chunk, sizeof(pd->port_rcvegrbuf_phys[0]),
+ GFP_KERNEL);
if (!pd->port_rcvegrbuf_phys) {
ret = -ENOMEM;
goto bail_rcvegrbuf;
@@ -2046,7 +2046,6 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
static int ipath_close(struct inode *in, struct file *fp)
{
- int ret = 0;
struct ipath_filedata *fd;
struct ipath_portdata *pd;
struct ipath_devdata *dd;
@@ -2158,7 +2157,7 @@ static int ipath_close(struct inode *in, struct file *fp)
bail:
kfree(fd);
- return ret;
+ return 0;
}
static int ipath_port_info(struct ipath_portdata *pd, u16 subport,
diff --git a/drivers/staging/rdma/ipath/ipath_init_chip.c b/drivers/staging/rdma/ipath/ipath_init_chip.c
index 4aea99c7e6f8..a5eea199f733 100644
--- a/drivers/staging/rdma/ipath/ipath_init_chip.c
+++ b/drivers/staging/rdma/ipath/ipath_init_chip.c
@@ -950,9 +950,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
* set up stats retrieval timer, even if we had errors
* in last portion of setup
*/
- init_timer(&dd->ipath_stats_timer);
- dd->ipath_stats_timer.function = ipath_get_faststats;
- dd->ipath_stats_timer.data = (unsigned long) dd;
+ setup_timer(&dd->ipath_stats_timer, ipath_get_faststats,
+ (unsigned long)dd);
/* every 5 seconds; */
dd->ipath_stats_timer.expires = jiffies + 5 * HZ;
/* takes ~16 seconds to overflow at full IB 4x bandwdith */
@@ -965,9 +964,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
ret = setup_sdma(dd);
/* Set up HoL state */
- init_timer(&dd->ipath_hol_timer);
- dd->ipath_hol_timer.function = ipath_hol_event;
- dd->ipath_hol_timer.data = (unsigned long)dd;
+ setup_timer(&dd->ipath_hol_timer, ipath_hol_event, (unsigned long)dd);
+
dd->ipath_hol_state = IPATH_HOL_UP;
done:
@@ -988,11 +986,9 @@ done:
* to an alternate if necessary and possible
*/
if (!reinit) {
- init_timer(&dd->ipath_intrchk_timer);
- dd->ipath_intrchk_timer.function =
- verify_interrupt;
- dd->ipath_intrchk_timer.data =
- (unsigned long) dd;
+ setup_timer(&dd->ipath_intrchk_timer,
+ verify_interrupt,
+ (unsigned long)dd);
}
dd->ipath_intrchk_timer.expires = jiffies + HZ/2;
add_timer(&dd->ipath_intrchk_timer);
diff --git a/drivers/staging/rdma/ipath/ipath_intr.c b/drivers/staging/rdma/ipath/ipath_intr.c
index e56897108722..0403fa28ed8d 100644
--- a/drivers/staging/rdma/ipath/ipath_intr.c
+++ b/drivers/staging/rdma/ipath/ipath_intr.c
@@ -33,7 +33,6 @@
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/sched.h>
#include "ipath_kernel.h"
#include "ipath_verbs.h"
diff --git a/drivers/staging/rdma/ipath/ipath_kernel.h b/drivers/staging/rdma/ipath/ipath_kernel.h
index f0f947122779..66c934a5f839 100644
--- a/drivers/staging/rdma/ipath/ipath_kernel.h
+++ b/drivers/staging/rdma/ipath/ipath_kernel.h
@@ -44,6 +44,7 @@
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/scatterlist.h>
+#include <linux/sched.h>
#include <asm/io.h>
#include <rdma/ib_verbs.h>
@@ -162,7 +163,7 @@ struct ipath_portdata {
struct pid *port_pid;
struct pid *port_subpid[INFINIPATH_MAX_SUBPORT];
/* same size as task_struct .comm[] */
- char port_comm[16];
+ char port_comm[TASK_COMM_LEN];
/* pkeys set by this use of this port */
u16 port_pkeys[4];
/* so file ops can get at unit */
diff --git a/drivers/staging/rdma/ipath/ipath_qp.c b/drivers/staging/rdma/ipath/ipath_qp.c
index b2c67662081b..280cd2d638e4 100644
--- a/drivers/staging/rdma/ipath/ipath_qp.c
+++ b/drivers/staging/rdma/ipath/ipath_qp.c
@@ -32,7 +32,6 @@
*/
#include <linux/err.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
diff --git a/drivers/staging/rdma/ipath/ipath_rc.c b/drivers/staging/rdma/ipath/ipath_rc.c
index 79b3dbc97179..d4aa53574e57 100644
--- a/drivers/staging/rdma/ipath/ipath_rc.c
+++ b/drivers/staging/rdma/ipath/ipath_rc.c
@@ -350,9 +350,9 @@ int ipath_make_rc_req(struct ipath_qp *qp)
goto bail;
}
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
hwords += sizeof(struct ib_reth) / sizeof(u32);
wqe->lpsn = wqe->psn;
@@ -401,9 +401,9 @@ int ipath_make_rc_req(struct ipath_qp *qp)
wqe->lpsn = qp->s_next_psn++;
}
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
qp->s_state = OP(RDMA_READ_REQUEST);
hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32);
@@ -433,21 +433,21 @@ int ipath_make_rc_req(struct ipath_qp *qp)
if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
qp->s_state = OP(COMPARE_SWAP);
ohdr->u.atomic_eth.swap_data = cpu_to_be64(
- wqe->wr.wr.atomic.swap);
+ wqe->atomic_wr.swap);
ohdr->u.atomic_eth.compare_data = cpu_to_be64(
- wqe->wr.wr.atomic.compare_add);
+ wqe->atomic_wr.compare_add);
} else {
qp->s_state = OP(FETCH_ADD);
ohdr->u.atomic_eth.swap_data = cpu_to_be64(
- wqe->wr.wr.atomic.compare_add);
+ wqe->atomic_wr.compare_add);
ohdr->u.atomic_eth.compare_data = 0;
}
ohdr->u.atomic_eth.vaddr[0] = cpu_to_be32(
- wqe->wr.wr.atomic.remote_addr >> 32);
+ wqe->atomic_wr.remote_addr >> 32);
ohdr->u.atomic_eth.vaddr[1] = cpu_to_be32(
- wqe->wr.wr.atomic.remote_addr);
+ wqe->atomic_wr.remote_addr);
ohdr->u.atomic_eth.rkey = cpu_to_be32(
- wqe->wr.wr.atomic.rkey);
+ wqe->atomic_wr.rkey);
hwords += sizeof(struct ib_atomic_eth) / sizeof(u32);
ss = NULL;
len = 0;
@@ -567,9 +567,9 @@ int ipath_make_rc_req(struct ipath_qp *qp)
ipath_init_restart(qp, wqe);
len = ((qp->s_psn - wqe->psn) & IPATH_PSN_MASK) * pmtu;
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len);
+ cpu_to_be64(wqe->rdma_wr.remote_addr + len);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len);
qp->s_state = OP(RDMA_READ_REQUEST);
hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32);
diff --git a/drivers/staging/rdma/ipath/ipath_ruc.c b/drivers/staging/rdma/ipath/ipath_ruc.c
index 1f95bbaf7602..e541a01f1f61 100644
--- a/drivers/staging/rdma/ipath/ipath_ruc.c
+++ b/drivers/staging/rdma/ipath/ipath_ruc.c
@@ -31,7 +31,6 @@
* SOFTWARE.
*/
-#include <linux/sched.h>
#include <linux/spinlock.h>
#include "ipath_verbs.h"
@@ -353,8 +352,8 @@ again:
if (wqe->length == 0)
break;
if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length,
- wqe->wr.wr.rdma.remote_addr,
- wqe->wr.wr.rdma.rkey,
+ wqe->rdma_wr.remote_addr,
+ wqe->rdma_wr.rkey,
IB_ACCESS_REMOTE_WRITE)))
goto acc_err;
break;
@@ -363,8 +362,8 @@ again:
if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
goto inv_err;
if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
- wqe->wr.wr.rdma.remote_addr,
- wqe->wr.wr.rdma.rkey,
+ wqe->rdma_wr.remote_addr,
+ wqe->rdma_wr.rkey,
IB_ACCESS_REMOTE_READ)))
goto acc_err;
qp->r_sge.sge = wqe->sg_list[0];
@@ -377,18 +376,18 @@ again:
if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC)))
goto inv_err;
if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
- wqe->wr.wr.atomic.remote_addr,
- wqe->wr.wr.atomic.rkey,
+ wqe->atomic_wr.remote_addr,
+ wqe->atomic_wr.rkey,
IB_ACCESS_REMOTE_ATOMIC)))
goto acc_err;
/* Perform atomic OP and save result. */
maddr = (atomic64_t *) qp->r_sge.sge.vaddr;
- sdata = wqe->wr.wr.atomic.compare_add;
+ sdata = wqe->atomic_wr.compare_add;
*(u64 *) sqp->s_sge.sge.vaddr =
(wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ?
(u64) atomic64_add_return(sdata, maddr) - sdata :
(u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr,
- sdata, wqe->wr.wr.atomic.swap);
+ sdata, wqe->atomic_wr.swap);
goto send_comp;
default:
diff --git a/drivers/staging/rdma/ipath/ipath_sdma.c b/drivers/staging/rdma/ipath/ipath_sdma.c
index 17a517766ad2..1ffc06abf9da 100644
--- a/drivers/staging/rdma/ipath/ipath_sdma.c
+++ b/drivers/staging/rdma/ipath/ipath_sdma.c
@@ -400,9 +400,9 @@ static int alloc_sdma(struct ipath_devdata *dd)
}
dd->ipath_sdma_head_dma[0] = 0;
- init_timer(&dd->ipath_sdma_vl15_timer);
- dd->ipath_sdma_vl15_timer.function = vl15_watchdog_timeout;
- dd->ipath_sdma_vl15_timer.data = (unsigned long)dd;
+ setup_timer(&dd->ipath_sdma_vl15_timer, vl15_watchdog_timeout,
+ (unsigned long)dd);
+
atomic_set(&dd->ipath_sdma_vl15_count, 0);
goto done;
diff --git a/drivers/staging/rdma/ipath/ipath_uc.c b/drivers/staging/rdma/ipath/ipath_uc.c
index 22e60998f1a7..0246b30280b9 100644
--- a/drivers/staging/rdma/ipath/ipath_uc.c
+++ b/drivers/staging/rdma/ipath/ipath_uc.c
@@ -126,9 +126,9 @@ int ipath_make_uc_req(struct ipath_qp *qp)
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
ohdr->u.rc.reth.vaddr =
- cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =
- cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ cpu_to_be32(wqe->rdma_wr.rkey);
ohdr->u.rc.reth.length = cpu_to_be32(len);
hwords += sizeof(struct ib_reth) / 4;
if (len > pmtu) {
diff --git a/drivers/staging/rdma/ipath/ipath_ud.c b/drivers/staging/rdma/ipath/ipath_ud.c
index e8a2a915251e..385d9410a51e 100644
--- a/drivers/staging/rdma/ipath/ipath_ud.c
+++ b/drivers/staging/rdma/ipath/ipath_ud.c
@@ -31,7 +31,6 @@
* SOFTWARE.
*/
-#include <linux/sched.h>
#include <rdma/ib_smi.h>
#include "ipath_verbs.h"
@@ -65,7 +64,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
u32 rlen;
u32 length;
- qp = ipath_lookup_qpn(&dev->qp_table, swqe->wr.wr.ud.remote_qpn);
+ qp = ipath_lookup_qpn(&dev->qp_table, swqe->ud_wr.remote_qpn);
if (!qp || !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) {
dev->n_pkt_drops++;
goto done;
@@ -77,8 +76,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
* qkey from the QP context instead of the WR (see 10.2.5).
*/
if (unlikely(qp->ibqp.qp_num &&
- ((int) swqe->wr.wr.ud.remote_qkey < 0 ?
- sqp->qkey : swqe->wr.wr.ud.remote_qkey) != qp->qkey)) {
+ ((int) swqe->ud_wr.remote_qkey < 0 ?
+ sqp->qkey : swqe->ud_wr.remote_qkey) != qp->qkey)) {
/* XXX OK to lose a count once in a while. */
dev->qkey_violations++;
dev->n_pkt_drops++;
@@ -175,7 +174,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
} else
spin_unlock_irqrestore(&rq->lock, flags);
- ah_attr = &to_iah(swqe->wr.wr.ud.ah)->attr;
+ ah_attr = &to_iah(swqe->ud_wr.ah)->attr;
if (ah_attr->ah_flags & IB_AH_GRH) {
ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh));
wc.wc_flags |= IB_WC_GRH;
@@ -225,7 +224,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
wc.port_num = 1;
/* Signal completion event if the solicited bit is set. */
ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
- swqe->wr.send_flags & IB_SEND_SOLICITED);
+ swqe->ud_wr.wr.send_flags & IB_SEND_SOLICITED);
drop:
if (atomic_dec_and_test(&qp->refcount))
wake_up(&qp->wait);
@@ -280,7 +279,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
next_cur = 0;
/* Construct the header. */
- ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr;
+ ah_attr = &to_iah(wqe->ud_wr.ah)->attr;
if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE) {
if (ah_attr->dlid != IPATH_PERMISSIVE_LID)
dev->n_multicast_xmit++;
@@ -322,7 +321,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
qp->s_wqe = wqe;
qp->s_sge.sge = wqe->sg_list[0];
qp->s_sge.sg_list = wqe->sg_list + 1;
- qp->s_sge.num_sge = wqe->wr.num_sge;
+ qp->s_sge.num_sge = wqe->ud_wr.wr.num_sge;
if (ah_attr->ah_flags & IB_AH_GRH) {
/* Header size in 32-bit words. */
@@ -340,9 +339,9 @@ int ipath_make_ud_req(struct ipath_qp *qp)
lrh0 = IPATH_LRH_BTH;
ohdr = &qp->s_hdr.u.oth;
}
- if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ if (wqe->ud_wr.wr.opcode == IB_WR_SEND_WITH_IMM) {
qp->s_hdrwords++;
- ohdr->u.ud.imm_data = wqe->wr.ex.imm_data;
+ ohdr->u.ud.imm_data = wqe->ud_wr.wr.ex.imm_data;
bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
} else
bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
@@ -360,7 +359,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
qp->s_hdr.lrh[3] = cpu_to_be16(lid);
} else
qp->s_hdr.lrh[3] = IB_LID_PERMISSIVE;
- if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ if (wqe->ud_wr.wr.send_flags & IB_SEND_SOLICITED)
bth0 |= 1 << 23;
bth0 |= extra_bytes << 20;
bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPATH_DEFAULT_P_KEY :
@@ -372,14 +371,14 @@ int ipath_make_ud_req(struct ipath_qp *qp)
ohdr->bth[1] = ah_attr->dlid >= IPATH_MULTICAST_LID_BASE &&
ah_attr->dlid != IPATH_PERMISSIVE_LID ?
cpu_to_be32(IPATH_MULTICAST_QPN) :
- cpu_to_be32(wqe->wr.wr.ud.remote_qpn);
+ cpu_to_be32(wqe->ud_wr.remote_qpn);
ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPATH_PSN_MASK);
/*
* Qkeys with the high order bit set mean use the
* qkey from the QP context instead of the WR (see 10.2.5).
*/
- ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->wr.wr.ud.remote_qkey < 0 ?
- qp->qkey : wqe->wr.wr.ud.remote_qkey);
+ ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->ud_wr.remote_qkey < 0 ?
+ qp->qkey : wqe->ud_wr.remote_qkey);
ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
done:
diff --git a/drivers/staging/rdma/ipath/ipath_user_pages.c b/drivers/staging/rdma/ipath/ipath_user_pages.c
index 1da1252dcdb3..d29b4daf61f8 100644
--- a/drivers/staging/rdma/ipath/ipath_user_pages.c
+++ b/drivers/staging/rdma/ipath/ipath_user_pages.c
@@ -34,7 +34,6 @@
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/slab.h>
-#include <linux/sched.h>
#include "ipath_kernel.h"
diff --git a/drivers/staging/rdma/ipath/ipath_user_sdma.c b/drivers/staging/rdma/ipath/ipath_user_sdma.c
index e82b3ee2dbe0..8c12e3cccc58 100644
--- a/drivers/staging/rdma/ipath/ipath_user_sdma.c
+++ b/drivers/staging/rdma/ipath/ipath_user_sdma.c
@@ -33,7 +33,6 @@
#include <linux/types.h>
#include <linux/device.h>
#include <linux/dmapool.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/highmem.h>
diff --git a/drivers/staging/rdma/ipath/ipath_verbs.c b/drivers/staging/rdma/ipath/ipath_verbs.c
index 40f7f059f6b2..1778dee13f99 100644
--- a/drivers/staging/rdma/ipath/ipath_verbs.c
+++ b/drivers/staging/rdma/ipath/ipath_verbs.c
@@ -374,7 +374,7 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr)
wr->opcode != IB_WR_SEND_WITH_IMM)
goto bail_inval;
/* Check UD destination address PD */
- if (qp->ibqp.pd != wr->wr.ud.ah->pd)
+ if (qp->ibqp.pd != ud_wr(wr)->ah->pd)
goto bail_inval;
} else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD)
goto bail_inval;
@@ -395,7 +395,20 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr)
}
wqe = get_swqe_ptr(qp, qp->s_head);
- wqe->wr = *wr;
+
+ if (qp->ibqp.qp_type != IB_QPT_UC &&
+ qp->ibqp.qp_type != IB_QPT_RC)
+ memcpy(&wqe->ud_wr, ud_wr(wr), sizeof(wqe->ud_wr));
+ else if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE ||
+ wr->opcode == IB_WR_RDMA_READ)
+ memcpy(&wqe->rdma_wr, rdma_wr(wr), sizeof(wqe->rdma_wr));
+ else if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+ wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+ memcpy(&wqe->atomic_wr, atomic_wr(wr), sizeof(wqe->atomic_wr));
+ else
+ memcpy(&wqe->wr, wr, sizeof(wqe->wr));
+
wqe->length = 0;
if (wr->num_sge) {
acc = wr->opcode >= IB_WR_RDMA_READ ?
@@ -1956,9 +1969,8 @@ static int enable_timer(struct ipath_devdata *dd)
dd->ipath_gpio_mask);
}
- init_timer(&dd->verbs_timer);
- dd->verbs_timer.function = __verbs_timer;
- dd->verbs_timer.data = (unsigned long)dd;
+ setup_timer(&dd->verbs_timer, __verbs_timer, (unsigned long)dd);
+
dd->verbs_timer.expires = jiffies + 1;
add_timer(&dd->verbs_timer);
@@ -2025,8 +2037,8 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
dev = &idev->ibdev;
if (dd->ipath_sdma_descq_cnt) {
- tx = kmalloc(dd->ipath_sdma_descq_cnt * sizeof *tx,
- GFP_KERNEL);
+ tx = kmalloc_array(dd->ipath_sdma_descq_cnt, sizeof *tx,
+ GFP_KERNEL);
if (tx == NULL) {
ret = -ENOMEM;
goto err_tx;
diff --git a/drivers/staging/rdma/ipath/ipath_verbs.h b/drivers/staging/rdma/ipath/ipath_verbs.h
index ec167e545e15..0a90a56870ab 100644
--- a/drivers/staging/rdma/ipath/ipath_verbs.h
+++ b/drivers/staging/rdma/ipath/ipath_verbs.h
@@ -277,7 +277,13 @@ struct ipath_mr {
* in qp->s_max_sge.
*/
struct ipath_swqe {
- struct ib_send_wr wr; /* don't use wr.sg_list */
+ union {
+ struct ib_send_wr wr; /* don't use wr.sg_list */
+ struct ib_ud_wr ud_wr;
+ struct ib_rdma_wr rdma_wr;
+ struct ib_atomic_wr atomic_wr;
+ };
+
u32 psn; /* first packet sequence number */
u32 lpsn; /* last packet sequence number */
u32 ssn; /* send sequence number */
diff --git a/drivers/staging/rdma/ipath/ipath_verbs_mcast.c b/drivers/staging/rdma/ipath/ipath_verbs_mcast.c
index 6216ea923853..72d476fa5b8f 100644
--- a/drivers/staging/rdma/ipath/ipath_verbs_mcast.c
+++ b/drivers/staging/rdma/ipath/ipath_verbs_mcast.c
@@ -32,7 +32,6 @@
*/
#include <linux/rculist.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include "ipath_verbs.h"
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 5c45f8a8c2cf..e5d29fe9d446 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -1240,11 +1240,6 @@ int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
return 0;
}
-static void update_bcn_fixed_ie(struct adapter *padapter)
-{
- DBG_88E("%s\n", __func__);
-}
-
static void update_bcn_erpinfo_ie(struct adapter *padapter)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
@@ -1279,31 +1274,6 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter)
}
}
-static void update_bcn_htcap_ie(struct adapter *padapter)
-{
- DBG_88E("%s\n", __func__);
-}
-
-static void update_bcn_htinfo_ie(struct adapter *padapter)
-{
- DBG_88E("%s\n", __func__);
-}
-
-static void update_bcn_rsn_ie(struct adapter *padapter)
-{
- DBG_88E("%s\n", __func__);
-}
-
-static void update_bcn_wpa_ie(struct adapter *padapter)
-{
- DBG_88E("%s\n", __func__);
-}
-
-static void update_bcn_wmm_ie(struct adapter *padapter)
-{
- DBG_88E("%s\n", __func__);
-}
-
static void update_bcn_wps_ie(struct adapter *padapter)
{
u8 *pwps_ie = NULL, *pwps_ie_src;
@@ -1354,22 +1324,12 @@ static void update_bcn_wps_ie(struct adapter *padapter)
kfree(pbackup_remainder_ie);
}
-static void update_bcn_p2p_ie(struct adapter *padapter)
-{
-}
-
static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
{
DBG_88E("%s\n", __func__);
- if (!memcmp(RTW_WPA_OUI, oui, 4))
- update_bcn_wpa_ie(padapter);
- else if (!memcmp(WMM_OUI, oui, 4))
- update_bcn_wmm_ie(padapter);
- else if (!memcmp(WPS_OUI, oui, 4))
+ if (!memcmp(WPS_OUI, oui, 4))
update_bcn_wps_ie(padapter);
- else if (!memcmp(P2P_OUI, oui, 4))
- update_bcn_p2p_ie(padapter);
else
DBG_88E("unknown OUI type!\n");
}
@@ -1391,24 +1351,12 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
spin_lock_bh(&pmlmepriv->bcn_update_lock);
switch (ie_id) {
- case 0xFF:
- update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
- break;
case _TIM_IE_:
update_BCNTIM(padapter);
break;
case _ERPINFO_IE_:
update_bcn_erpinfo_ie(padapter);
break;
- case _HT_CAPABILITY_IE_:
- update_bcn_htcap_ie(padapter);
- break;
- case _RSN_IE_2_:
- update_bcn_rsn_ie(padapter);
- break;
- case _HT_ADD_INFO_IE_:
- update_bcn_htinfo_ie(padapter);
- break;
case _VENDOR_SPECIFIC_IE_:
update_bcn_vendor_spec_ie(padapter, oui);
break;
@@ -1795,7 +1743,7 @@ int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset)
plist = plist->next;
issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
- psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
+ psta->expire_to = min_t(unsigned int, pstapriv->expire_to * 2, 5);
}
spin_unlock_bh(&pstapriv->asoc_list_lock);
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 9b7026e7d55b..433b926ceae7 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -201,23 +201,20 @@ _next:
if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
pcmd->res = H2C_DROPPED;
- goto post_process;
- }
-
- if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
- cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
-
- if (cmd_hdl) {
- ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
- pcmd->res = ret;
- }
} else {
- pcmd->res = H2C_PARAMETERS_ERROR;
- }
+ if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
+ cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
- cmd_hdl = NULL;
+ if (cmd_hdl) {
+ ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
+ pcmd->res = ret;
+ }
+ } else {
+ pcmd->res = H2C_PARAMETERS_ERROR;
+ }
-post_process:
+ cmd_hdl = NULL;
+ }
/* call callback function for post-processed */
if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
@@ -242,15 +239,11 @@ post_process:
pcmdpriv->cmdthd_running = false;
/* free all cmd_obj resources */
- do {
- pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
- if (pcmd == NULL)
- break;
-
+ while ((pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue))) {
/* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */
rtw_free_cmd_obj(pcmd);
- } while (1);
+ }
up(&pcmdpriv->terminate_cmdthread_sema);
@@ -570,31 +563,19 @@ u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra n
struct setopmode_parm *psetop;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
-
ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (ph2c == NULL) {
- res = false;
- goto exit;
- }
psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
-
- if (psetop == NULL) {
+ if (!ph2c || !psetop) {
kfree(ph2c);
- res = false;
- goto exit;
+ kfree(psetop);
+ return false;
}
init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
psetop->mode = (u8)networktype;
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-
- return res;
+ return rtw_enqueue_cmd(pcmdpriv, ph2c);
}
u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
@@ -607,28 +588,16 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct sta_info *sta = (struct sta_info *)psta;
- u8 res = _SUCCESS;
-
ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (ph2c == NULL) {
- res = _FAIL;
- goto exit;
- }
-
psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
- if (psetstakey_para == NULL) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
- if (psetstakey_rsp == NULL) {
+
+ if (!ph2c || !psetstakey_para || !psetstakey_rsp) {
kfree(ph2c);
kfree(psetstakey_para);
- res = _FAIL;
- goto exit;
+ kfree(psetstakey_rsp);
+ return _FAIL;
}
init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
@@ -650,12 +619,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
/* jeff: set this because at least sw key is ready */
padapter->securitypriv.busetkipkey = true;
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-
- return res;
+ return rtw_enqueue_cmd(pcmdpriv, ph2c);
}
u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
@@ -1086,31 +1050,19 @@ u8 rtw_ps_cmd(struct adapter *padapter)
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
-
ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
- if (ppscmd == NULL) {
- res = _FAIL;
- goto exit;
- }
-
pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
- if (pdrvextra_cmd_parm == NULL) {
+ if (!ppscmd || !pdrvextra_cmd_parm) {
kfree(ppscmd);
- res = _FAIL;
- goto exit;
+ kfree(pdrvextra_cmd_parm);
+ return _FAIL;
}
pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
pdrvextra_cmd_parm->pbuf = NULL;
init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
- res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
-
-exit:
-
-
- return res;
+ return rtw_enqueue_cmd(pcmdpriv, ppscmd);
}
#ifdef CONFIG_88EU_AP_MODE
diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c
index 993c7db87a1a..2c4afb80fc64 100644
--- a/drivers/staging/rtl8188eu/core/rtw_debug.c
+++ b/drivers/staging/rtl8188eu/core/rtw_debug.c
@@ -594,8 +594,7 @@ int proc_set_rx_signal(struct file *file, const char __user *buffer,
if (is_signal_dbg && num != 2)
return count;
- signal_strength = signal_strength > 100 ? 100 : signal_strength;
- signal_strength = signal_strength < 0 ? 0 : signal_strength;
+ signal_strength = clamp(signal_strength, 0, 100);
padapter->recvpriv.is_signal_dbg = is_signal_dbg;
padapter->recvpriv.signal_strength_dbg = signal_strength;
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
index 7b99ea91a9e6..2320fb11af24 100644
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -224,7 +224,7 @@ static void efuse_read_phymap_from_txpktbuf(
)
{
u16 dbg_addr = 0;
- u32 start = 0, passing_time = 0;
+ unsigned long start = 0;
u8 reg_0x143 = 0;
u32 lo32 = 0, hi32 = 0;
u16 len = 0, count = 0;
@@ -248,7 +248,7 @@ static void efuse_read_phymap_from_txpktbuf(
usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
start = jiffies;
while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
- (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
+ jiffies_to_msecs(jiffies - start) < 1000) {
DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106));
usleep_range(1000, 2000);
}
@@ -268,7 +268,7 @@ static void efuse_read_phymap_from_txpktbuf(
aaa = le16_to_cpup((__le16 *)&lo32);
len = le16_to_cpu(*((__le16 *)&lo32));
- limit = (len-2 < limit) ? len-2 : limit;
+ limit = min_t(u16, len-2, limit);
DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
@@ -396,7 +396,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
- if (!(word_en&BIT0)) {
+ if (!(word_en & BIT(0))) {
tmpaddr = start_addr;
efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
@@ -404,9 +404,9 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
- badworden &= (~BIT0);
+ badworden &= (~BIT(0));
}
- if (!(word_en&BIT1)) {
+ if (!(word_en & BIT(1))) {
tmpaddr = start_addr;
efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
@@ -414,9 +414,9 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
- badworden &= (~BIT1);
+ badworden &= (~BIT(1));
}
- if (!(word_en&BIT2)) {
+ if (!(word_en & BIT(2))) {
tmpaddr = start_addr;
efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
@@ -424,9 +424,9 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
- badworden &= (~BIT2);
+ badworden &= (~BIT(2));
}
- if (!(word_en&BIT3)) {
+ if (!(word_en & BIT(3))) {
tmpaddr = start_addr;
efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
@@ -434,7 +434,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
- badworden &= (~BIT3);
+ badworden &= (~BIT(3));
}
return badworden;
}
@@ -738,18 +738,18 @@ static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
u8 match_word_en = 0x0F; /* default all words are disabled */
/* check if the same words are enabled both target and current PG packet */
- if (((pTargetPkt->word_en & BIT0) == 0) &&
- ((pCurPkt->word_en & BIT0) == 0))
- match_word_en &= ~BIT0; /* enable word 0 */
- if (((pTargetPkt->word_en & BIT1) == 0) &&
- ((pCurPkt->word_en & BIT1) == 0))
- match_word_en &= ~BIT1; /* enable word 1 */
- if (((pTargetPkt->word_en & BIT2) == 0) &&
- ((pCurPkt->word_en & BIT2) == 0))
- match_word_en &= ~BIT2; /* enable word 2 */
- if (((pTargetPkt->word_en & BIT3) == 0) &&
- ((pCurPkt->word_en & BIT3) == 0))
- match_word_en &= ~BIT3; /* enable word 3 */
+ if (((pTargetPkt->word_en & BIT(0)) == 0) &&
+ ((pCurPkt->word_en & BIT(0)) == 0))
+ match_word_en &= ~BIT(0); /* enable word 0 */
+ if (((pTargetPkt->word_en & BIT(1)) == 0) &&
+ ((pCurPkt->word_en & BIT(1)) == 0))
+ match_word_en &= ~BIT(1); /* enable word 1 */
+ if (((pTargetPkt->word_en & BIT(2)) == 0) &&
+ ((pCurPkt->word_en & BIT(2)) == 0))
+ match_word_en &= ~BIT(2); /* enable word 2 */
+ if (((pTargetPkt->word_en & BIT(3)) == 0) &&
+ ((pCurPkt->word_en & BIT(3)) == 0))
+ match_word_en &= ~BIT(3); /* enable word 3 */
*pWden = match_word_en;
@@ -961,19 +961,19 @@ u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
*/
void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
{
- if (!(word_en&BIT(0))) {
+ if (!(word_en & BIT(0))) {
targetdata[0] = sourdata[0];
targetdata[1] = sourdata[1];
}
- if (!(word_en&BIT(1))) {
+ if (!(word_en & BIT(1))) {
targetdata[2] = sourdata[2];
targetdata[3] = sourdata[3];
}
- if (!(word_en&BIT(2))) {
+ if (!(word_en & BIT(2))) {
targetdata[4] = sourdata[4];
targetdata[5] = sourdata[5];
}
- if (!(word_en&BIT(3))) {
+ if (!(word_en & BIT(3))) {
targetdata[6] = sourdata[6];
targetdata[7] = sourdata[7];
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index 82d4e888ca63..742b29c590df 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -1392,6 +1392,6 @@ static const char *_action_public_str[] = {
const char *action_public_str(u8 action)
{
- action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
+ action = min_t(u8, action, ACT_PUBLIC_MAX);
return _action_public_str[action];
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
index 22f5b45f5f7f..cf60717a6c19 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
@@ -27,13 +27,6 @@
extern void indicate_wx_scan_complete_event(struct adapter *padapter);
-#define IS_MAC_ADDRESS_BROADCAST(addr) \
-(\
- ((addr[0] == 0xff) && (addr[1] == 0xff) && \
- (addr[2] == 0xff) && (addr[3] == 0xff) && \
- (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \
-)
-
u8 rtw_do_join(struct adapter *padapter)
{
struct list_head *plist, *phead;
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index 2b917a18e228..abab854e6889 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -163,7 +163,8 @@ exit:
static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
{
- u32 curr_time, delta_time;
+ unsigned long curr_time;
+ u32 delta_time;
u32 lifetime = SCANQUEUE_LIFETIME;
struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
@@ -272,7 +273,7 @@ int rtw_if_up(struct adapter *padapter)
void rtw_generate_random_ibss(u8 *pibss)
{
- u32 curtime = jiffies;
+ unsigned long curtime = jiffies;
pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
pibss[1] = 0x11;
@@ -365,20 +366,13 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
phead = get_list_head(scanned_queue);
- plist = phead->next;
-
- while (1) {
- if (phead == plist)
- break;
-
+ for (plist = phead->next; plist != phead; plist = plist->next) {
pwlan = container_of(plist, struct wlan_network, list);
if (!pwlan->fixed) {
if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
oldest = pwlan;
}
-
- plist = plist->next;
}
return oldest;
}
@@ -878,14 +872,14 @@ inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
void rtw_scan_abort(struct adapter *adapter)
{
- u32 start;
+ unsigned long start;
struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
start = jiffies;
pmlmeext->scan_abort = true;
while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
- rtw_get_passing_time_ms(start) <= 200) {
+ jiffies_to_msecs(jiffies - start) <= 200) {
if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
break;
DBG_88E(FUNC_NDEV_FMT"fw_state=_FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
@@ -1474,6 +1468,7 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
, struct wlan_network **candidate, struct wlan_network *competitor)
{
int updated = false;
+ unsigned long since_scan;
struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv);
@@ -1494,7 +1489,8 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
goto exit;
if (pmlmepriv->to_roaming) {
- if (rtw_get_passing_time_ms((u32)competitor->last_scanned) >= RTW_SCAN_RESULT_EXPIRE ||
+ since_scan = jiffies - competitor->last_scanned;
+ if (jiffies_to_msecs(since_scan) >= RTW_SCAN_RESULT_EXPIRE ||
is_same_ess(&competitor->network, &pmlmepriv->cur_network.network) == false)
goto exit;
}
@@ -1709,8 +1705,8 @@ int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
unsigned int ielength = 0;
unsigned int i, j;
- i = 12; /* after the fixed IE */
- while (i < in_len) {
+ /* i = 12; after the fixed IE */
+ for (i = 12; i < in_len; i += (in_ie[i + 1] + 2) /* to the next IE element */) {
ielength = initial_out_len;
if (in_ie[i] == 0xDD && in_ie[i+2] == 0x00 && in_ie[i+3] == 0x50 && in_ie[i+4] == 0xF2 && in_ie[i+5] == 0x02 && i+5 < in_len) {
@@ -1726,7 +1722,6 @@ int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
out_ie[initial_out_len + 8] = 0x00;
break;
}
- i += (in_ie[i+1]+2); /* to the next IE element */
}
return ielength;
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index e15c198abbe3..3eca6874b6df 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -418,7 +418,7 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms)
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
/* DS parameter set */
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
@@ -578,7 +578,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da)
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
/* DS parameter set */
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
@@ -609,7 +609,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da)
return;
}
-static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
+static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, bool wait_ack)
{
int ret = _FAIL;
struct xmit_frame *pmgntframe;
@@ -702,22 +702,16 @@ exit:
return ret;
}
-static inline void issue_probereq(struct adapter *padapter,
- struct ndis_802_11_ssid *pssid, u8 *da)
-{
- _issue_probereq(padapter, pssid, da, false);
-}
-
static int issue_probereq_ex(struct adapter *padapter,
struct ndis_802_11_ssid *pssid, u8 *da,
int try_cnt, int wait_ms)
{
int ret;
int i = 0;
- u32 start = jiffies;
+ unsigned long start = jiffies;
do {
- ret = _issue_probereq(padapter, pssid, da, wait_ms > 0 ? true : false);
+ ret = issue_probereq(padapter, pssid, da, wait_ms > 0 ? true : false);
i++;
@@ -738,11 +732,13 @@ static int issue_probereq_ex(struct adapter *padapter,
if (da)
DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
else
DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
}
exit:
return ret;
@@ -1181,7 +1177,7 @@ static void issue_assocreq(struct adapter *padapter)
}
/* vendor specific IE, such as WPA, WMM, WPS */
- for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength; i += (pIE->Length + 2)) {
pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
switch (pIE->ElementID) {
@@ -1202,7 +1198,6 @@ static void issue_assocreq(struct adapter *padapter)
default:
break;
}
- i += (pIE->Length + 2);
}
if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
@@ -1300,7 +1295,7 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow
{
int ret;
int i = 0;
- u32 start = jiffies;
+ unsigned long start = jiffies;
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
@@ -1330,11 +1325,13 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow
if (da)
DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
else
DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
}
exit:
return ret;
@@ -1425,7 +1422,7 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int
{
int ret;
int i = 0;
- u32 start = jiffies;
+ unsigned long start = jiffies;
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
@@ -1455,11 +1452,13 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int
if (da)
DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
else
DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
}
exit:
return ret;
@@ -1537,7 +1536,7 @@ static int issue_deauth_ex(struct adapter *padapter, u8 *da,
{
int ret;
int i = 0;
- u32 start = jiffies;
+ unsigned long start = jiffies;
do {
ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? true : false);
@@ -1560,11 +1559,13 @@ static int issue_deauth_ex(struct adapter *padapter, u8 *da,
if (da)
DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
else
DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
}
exit:
return ret;
@@ -1966,7 +1967,7 @@ unsigned int send_beacon(struct adapter *padapter)
int issue = 0;
int poll = 0;
- u32 start = jiffies;
+ unsigned long start = jiffies;
rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
do {
@@ -1982,13 +1983,16 @@ unsigned int send_beacon(struct adapter *padapter)
if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
return _FAIL;
if (!bxmitok) {
- DBG_88E("%s fail! %u ms\n", __func__, rtw_get_passing_time_ms(start));
+ DBG_88E("%s fail! %u ms\n", __func__,
+ jiffies_to_msecs(jiffies - start));
return _FAIL;
} else {
- u32 passing_time = rtw_get_passing_time_ms(start);
+ u32 passing_time = jiffies_to_msecs(jiffies - start);
if (passing_time > 100 || issue > 3)
- DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, rtw_get_passing_time_ms(start));
+ DBG_88E("%s success, issue:%d, poll:%d, %u ms\n",
+ __func__, issue, poll,
+ jiffies_to_msecs(jiffies - start));
return _SUCCESS;
}
}
@@ -2030,24 +2034,28 @@ static void site_survey(struct adapter *padapter)
for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
/* todo: to issue two probe req??? */
- issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
+ issue_probereq(padapter,
+ &(pmlmeext->sitesurvey_res.ssid[i]),
+ NULL, false);
/* msleep(SURVEY_TO>>1); */
- issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
+ issue_probereq(padapter,
+ &(pmlmeext->sitesurvey_res.ssid[i]),
+ NULL, false);
}
}
if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
/* todo: to issue two probe req??? */
- issue_probereq(padapter, NULL, NULL);
+ issue_probereq(padapter, NULL, NULL, false);
/* msleep(SURVEY_TO>>1); */
- issue_probereq(padapter, NULL, NULL);
+ issue_probereq(padapter, NULL, NULL, false);
}
if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
/* todo: to issue two probe req??? */
- issue_probereq(padapter, NULL, NULL);
+ issue_probereq(padapter, NULL, NULL, false);
/* msleep(SURVEY_TO>>1); */
- issue_probereq(padapter, NULL, NULL);
+ issue_probereq(padapter, NULL, NULL, false);
}
}
@@ -3239,7 +3247,7 @@ static unsigned int OnAssocReq(struct adapter *padapter,
pstat->flags |= WLAN_STA_WPS;
copy_len = 0;
} else {
- copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len+2);
+ copy_len = min_t(int, wpa_ie_len + 2, sizeof(pstat->wpa_ie));
}
if (copy_len > 0)
memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
@@ -4821,9 +4829,18 @@ void linked_status_chk(struct adapter *padapter)
} else {
if (rx_chk != _SUCCESS) {
if (pmlmeext->retry == 0) {
- issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
- issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
- issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
+ issue_probereq(padapter,
+ &pmlmeinfo->network.Ssid,
+ pmlmeinfo->network.MacAddress,
+ false);
+ issue_probereq(padapter,
+ &pmlmeinfo->network.Ssid,
+ pmlmeinfo->network.MacAddress,
+ false);
+ issue_probereq(padapter,
+ &pmlmeinfo->network.Ssid,
+ pmlmeinfo->network.MacAddress,
+ false);
}
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
index 9765946466ab..5e1ef9fdcf47 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -348,7 +348,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
static u8 PS_RDY_CHECK(struct adapter *padapter)
{
- u32 curr_time, delta_time;
+ unsigned long curr_time, delta_time;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
@@ -418,7 +418,7 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a
*/
s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
{
- u32 start_time;
+ unsigned long start_time;
u8 bAwake = false;
s32 err = 0;
@@ -435,7 +435,7 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
break;
}
- if (rtw_get_passing_time_ms(start_time) > delay_ms) {
+ if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
err = -1;
DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
break;
@@ -561,24 +561,24 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
unsigned long expires;
+ unsigned long start;
int ret = _SUCCESS;
expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
if (time_before(pwrpriv->ips_deny_time, expires))
pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
-{
- u32 start = jiffies;
+ start = jiffies;
if (pwrpriv->ps_processing) {
DBG_88E("%s wait ps_processing...\n", __func__);
- while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
+ while (pwrpriv->ps_processing &&
+ jiffies_to_msecs(jiffies - start) <= 3000)
usleep_range(1000, 3000);
if (pwrpriv->ps_processing)
DBG_88E("%s wait ps_processing timeout\n", __func__);
else
DBG_88E("%s wait ps_processing done\n", __func__);
}
-}
/* System suspend is not allowed to wakeup */
if ((!pwrpriv->bInternalAutoSuspend) && (pwrpriv->bInSuspend)) {
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index cb90ad5f6143..110b8c0b6cd7 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -1277,7 +1277,7 @@ static int validate_recv_frame(struct adapter *adapter,
int i;
DBG_88E("#############################\n");
- for (i = 0; i < 64; i = i+8)
+ for (i = 0; i < 64; i += 8)
DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
*(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
DBG_88E("#############################\n");
@@ -1286,7 +1286,7 @@ static int validate_recv_frame(struct adapter *adapter,
int i;
DBG_88E("#############################\n");
- for (i = 0; i < 64; i = i+8)
+ for (i = 0; i < 64; i += 8)
DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
*(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
DBG_88E("#############################\n");
@@ -1296,7 +1296,7 @@ static int validate_recv_frame(struct adapter *adapter,
int i;
DBG_88E("#############################\n");
- for (i = 0; i < 64; i = i+8)
+ for (i = 0; i < 64; i += 8)
DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
*(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
DBG_88E("#############################\n");
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index 3bb40a7fe3ce..59b443255a90 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -1227,7 +1227,7 @@ unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
unsigned int i, num_of_rate;
unsigned int mask = 0;
- num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz;
+ num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
for (i = 0; i < num_of_rate; i++) {
if ((*(ptn + i)) & 0x80)
@@ -1241,7 +1241,7 @@ unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz)
unsigned int i, num_of_rate;
unsigned int mask = 0;
- num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz;
+ num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
for (i = 0; i < num_of_rate; i++)
mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index cabb810369bd..e778132b73dc 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -641,7 +641,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
if (pattrib->psta)
stainfo = pattrib->psta;
else
- stainfo = rtw_get_stainfo(&padapter->stapriv , &pattrib->ra[0]);
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
@@ -1702,12 +1702,12 @@ u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
return addr;
}
-static void do_queue_select(struct adapter *padapter, struct pkt_attrib *pattrib)
+static void do_queue_select(struct adapter *padapter, struct pkt_attrib *pattrib)
{
u8 qsel;
qsel = pattrib->priority;
- RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("### do_queue_select priority=%d , qsel = %d\n", pattrib->priority , qsel));
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("### do_queue_select priority=%d , qsel = %d\n", pattrib->priority, qsel));
pattrib->qsel = qsel;
}
@@ -2186,11 +2186,6 @@ void rtw_sctx_done_err(struct submit_ctx **sctx, int status)
}
}
-void rtw_sctx_done(struct submit_ctx **sctx)
-{
- rtw_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
-}
-
int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms)
{
struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c
index 4eb982bdbfc0..f58a8222c899 100644
--- a/drivers/staging/rtl8188eu/hal/bb_cfg.c
+++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c
@@ -500,53 +500,55 @@ static u32 array_phy_reg_pg_8188e[] = {
};
-static void store_pwrindex_offset(struct adapter *Adapter, u32 regaddr, u32 bitmask, u32 data)
+static void store_pwrindex_offset(struct adapter *adapter,
+ u32 regaddr, u32 bitmask, u32 data)
{
- struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
- u8 pwrGrpCnt = hal_data->pwrGroupCnt;
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(adapter);
+ u32 * const power_level_offset =
+ hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt];
if (regaddr == rTxAGC_A_Rate18_06)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][0] = data;
+ power_level_offset[0] = data;
if (regaddr == rTxAGC_A_Rate54_24)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][1] = data;
+ power_level_offset[1] = data;
if (regaddr == rTxAGC_A_CCK1_Mcs32)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][6] = data;
+ power_level_offset[6] = data;
if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][7] = data;
+ power_level_offset[7] = data;
if (regaddr == rTxAGC_A_Mcs03_Mcs00)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][2] = data;
+ power_level_offset[2] = data;
if (regaddr == rTxAGC_A_Mcs07_Mcs04)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][3] = data;
+ power_level_offset[3] = data;
if (regaddr == rTxAGC_A_Mcs11_Mcs08)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][4] = data;
+ power_level_offset[4] = data;
if (regaddr == rTxAGC_A_Mcs15_Mcs12) {
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][5] = data;
+ power_level_offset[5] = data;
if (hal_data->rf_type == RF_1T1R)
hal_data->pwrGroupCnt++;
}
if (regaddr == rTxAGC_B_Rate18_06)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][8] = data;
+ power_level_offset[8] = data;
if (regaddr == rTxAGC_B_Rate54_24)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][9] = data;
+ power_level_offset[9] = data;
if (regaddr == rTxAGC_B_CCK1_55_Mcs32)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][14] = data;
+ power_level_offset[14] = data;
if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][15] = data;
+ power_level_offset[15] = data;
if (regaddr == rTxAGC_B_Mcs03_Mcs00)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][10] = data;
+ power_level_offset[10] = data;
if (regaddr == rTxAGC_B_Mcs07_Mcs04)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][11] = data;
+ power_level_offset[11] = data;
if (regaddr == rTxAGC_B_Mcs11_Mcs08)
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][12] = data;
+ power_level_offset[12] = data;
if (regaddr == rTxAGC_B_Mcs15_Mcs12) {
- hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][13] = data;
+ power_level_offset[13] = data;
if (hal_data->rf_type != RF_1T1R)
hal_data->pwrGroupCnt++;
}
}
static void rtl_addr_delay(struct adapter *adapt,
- u32 addr, u32 bit_mask, u32 data)
+ u32 addr, u32 bit_mask, u32 data)
{
switch (addr) {
case 0xfe:
@@ -589,15 +591,15 @@ static bool config_bb_with_pgheader(struct adapter *adapt)
return true;
}
-static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *Adapter)
+static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter)
{
- struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(adapter);
struct bb_reg_def *reg[4];
- reg[RF_PATH_A] = &(hal_data->PHYRegDef[RF_PATH_A]);
- reg[RF_PATH_B] = &(hal_data->PHYRegDef[RF_PATH_B]);
- reg[RF_PATH_C] = &(hal_data->PHYRegDef[RF_PATH_C]);
- reg[RF_PATH_D] = &(hal_data->PHYRegDef[RF_PATH_D]);
+ reg[RF_PATH_A] = &hal_data->PHYRegDef[RF_PATH_A];
+ reg[RF_PATH_B] = &hal_data->PHYRegDef[RF_PATH_B];
+ reg[RF_PATH_C] = &hal_data->PHYRegDef[RF_PATH_C];
+ reg[RF_PATH_D] = &hal_data->PHYRegDef[RF_PATH_D];
reg[RF_PATH_A]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
reg[RF_PATH_B]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
@@ -680,13 +682,13 @@ static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *Adapter)
static bool config_parafile(struct adapter *adapt)
{
- struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(adapt);
+ struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt);
struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
set_baseband_phy_config(adapt);
/* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
- if (!pEEPROM->bautoload_fail_flag) {
+ if (!eeprom->bautoload_fail_flag) {
hal_data->pwrGroupCnt = 0;
config_bb_with_pgheader(adapt);
}
@@ -705,18 +707,21 @@ bool rtl88eu_phy_bb_config(struct adapter *adapt)
/* Enable BB and RF */
regval = usb_read16(adapt, REG_SYS_FUNC_EN);
- usb_write16(adapt, REG_SYS_FUNC_EN, (u16)(regval|BIT13|BIT0|BIT1));
+ usb_write16(adapt, REG_SYS_FUNC_EN,
+ (u16)(regval | BIT(13) | BIT(0) | BIT(1)));
- usb_write8(adapt, REG_RF_CTRL, RF_EN|RF_RSTB|RF_SDMRSTB);
+ usb_write8(adapt, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
- usb_write8(adapt, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+ usb_write8(adapt, REG_SYS_FUNC_EN, FEN_USBA |
+ FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
/* Config BB and AGC */
rtstatus = config_parafile(adapt);
/* write 0x24[16:11] = 0x24[22:17] = crystal_cap */
crystal_cap = hal_data->CrystalCap & 0x3F;
- phy_set_bb_reg(adapt, REG_AFE_XTAL_CTRL, 0x7ff800, (crystal_cap | (crystal_cap << 6)));
+ phy_set_bb_reg(adapt, REG_AFE_XTAL_CTRL, 0x7ff800,
+ (crystal_cap | (crystal_cap << 6)));
return rtstatus;
}
diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c
index a71c54295508..4d72537644b3 100644
--- a/drivers/staging/rtl8188eu/hal/fw.c
+++ b/drivers/staging/rtl8188eu/hal/fw.c
@@ -58,43 +58,31 @@ static void _rtl88e_fw_block_write(struct adapter *adapt,
const u8 *buffer, u32 size)
{
u32 blk_sz = sizeof(u32);
- u8 *buf_ptr = (u8 *)buffer;
- u32 *pu4BytePtr = (u32 *)buffer;
- u32 i, offset, blk_cnt, remain;
+ const u8 *byte_buffer;
+ const u32 *dword_buffer = (u32 *)buffer;
+ u32 i, write_address, blk_cnt, remain;
blk_cnt = size / blk_sz;
remain = size % blk_sz;
- for (i = 0; i < blk_cnt; i++) {
- offset = i * blk_sz;
- usb_write32(adapt, (FW_8192C_START_ADDRESS + offset),
- *(pu4BytePtr + i));
- }
+ write_address = FW_8192C_START_ADDRESS;
- if (remain) {
- offset = blk_cnt * blk_sz;
- buf_ptr += offset;
- for (i = 0; i < remain; i++) {
- usb_write8(adapt, (FW_8192C_START_ADDRESS +
- offset + i), *(buf_ptr + i));
- }
- }
+ for (i = 0; i < blk_cnt; i++, write_address += blk_sz)
+ usb_write32(adapt, write_address, dword_buffer[i]);
+
+ byte_buffer = buffer + blk_cnt * blk_sz;
+ for (i = 0; i < remain; i++, write_address++)
+ usb_write8(adapt, write_address, byte_buffer[i]);
}
static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
{
- u32 fwlen = *pfwlen;
- u8 remain = (u8)(fwlen % 4);
+ u32 i;
- remain = (remain == 0) ? 0 : (4 - remain);
+ for (i = *pfwlen; i < roundup(*pfwlen, 4); i++)
+ pfwbuf[i] = 0;
- while (remain > 0) {
- pfwbuf[fwlen] = 0;
- fwlen++;
- remain--;
- }
-
- *pfwlen = fwlen;
+ *pfwlen = i;
}
static void _rtl88e_fw_page_write(struct adapter *adapt,
@@ -190,7 +178,6 @@ int rtl88eu_download_fw(struct adapter *adapt)
struct rtl92c_firmware_header *pfwheader = NULL;
u8 *pfwdata;
u32 fwsize;
- int err;
if (request_firmware(&fw, fw_name, device)) {
dev_err(device, "Firmware %s not available\n", fw_name);
@@ -229,7 +216,5 @@ int rtl88eu_download_fw(struct adapter *adapt)
_rtl88e_write_fw(adapt, pfwdata, fwsize);
_rtl88e_enable_fw_download(adapt, false);
- err = _rtl88e_fw_free_to_go(adapt);
-
- return err;
+ return _rtl88e_fw_free_to_go(adapt);
}
diff --git a/drivers/staging/rtl8188eu/hal/hal_com.c b/drivers/staging/rtl8188eu/hal/hal_com.c
index 38e9fdc312d3..3871cda2eec2 100644
--- a/drivers/staging/rtl8188eu/hal/hal_com.c
+++ b/drivers/staging/rtl8188eu/hal/hal_com.c
@@ -32,19 +32,19 @@ void dump_chip_info(struct HAL_VERSION chip_vers)
char buf[128];
cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
- cnt += sprintf((buf+cnt), "%s_", IS_NORMAL_CHIP(chip_vers) ?
+ cnt += sprintf((buf+cnt), "%s_", chip_vers.ChipType == NORMAL_CHIP ?
"Normal_Chip" : "Test_Chip");
- cnt += sprintf((buf+cnt), "%s_", IS_CHIP_VENDOR_TSMC(chip_vers) ?
+ cnt += sprintf((buf+cnt), "%s_", chip_vers.VendorType == CHIP_VENDOR_TSMC ?
"TSMC" : "UMC");
- if (IS_A_CUT(chip_vers))
+ if (chip_vers.CUTVersion == A_CUT_VERSION)
cnt += sprintf((buf+cnt), "A_CUT_");
- else if (IS_B_CUT(chip_vers))
+ else if (chip_vers.CUTVersion == B_CUT_VERSION)
cnt += sprintf((buf+cnt), "B_CUT_");
- else if (IS_C_CUT(chip_vers))
+ else if (chip_vers.CUTVersion == C_CUT_VERSION)
cnt += sprintf((buf+cnt), "C_CUT_");
- else if (IS_D_CUT(chip_vers))
+ else if (chip_vers.CUTVersion == D_CUT_VERSION)
cnt += sprintf((buf+cnt), "D_CUT_");
- else if (IS_E_CUT(chip_vers))
+ else if (chip_vers.CUTVersion == E_CUT_VERSION)
cnt += sprintf((buf+cnt), "E_CUT_");
else
cnt += sprintf((buf+cnt), "UNKNOWN_CUT(%d)_",
diff --git a/drivers/staging/rtl8188eu/hal/mac_cfg.c b/drivers/staging/rtl8188eu/hal/mac_cfg.c
index febc83a5adb8..0bc1b215219a 100644
--- a/drivers/staging/rtl8188eu/hal/mac_cfg.c
+++ b/drivers/staging/rtl8188eu/hal/mac_cfg.c
@@ -123,10 +123,10 @@ bool rtl88eu_phy_mac_config(struct adapter *adapt)
u32 arraylength;
u32 *ptrarray;
- arraylength = sizeof(array_MAC_REG_8188E)/sizeof(u32);
+ arraylength = ARRAY_SIZE(array_MAC_REG_8188E);
ptrarray = array_MAC_REG_8188E;
- for (i = 0; i < arraylength; i = i + 2)
+ for (i = 0; i < arraylength; i += 2)
usb_write8(adapt, ptrarray[i], (u8)ptrarray[i + 1]);
usb_write8(adapt, REG_MAX_AGGR_NUM, MAX_AGGR_NUM);
diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
index 46be4de50629..2c25d3b02036 100644
--- a/drivers/staging/rtl8188eu/hal/odm.c
+++ b/drivers/staging/rtl8188eu/hal/odm.c
@@ -437,7 +437,7 @@ void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm)
{
struct adapter *adapter = pDM_Odm->Adapter;
- pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT9);
+ pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT(9));
pDM_Odm->RFPathRxEnable = (u8)phy_query_bb_reg(adapter, 0xc04, 0x0F);
ODM_InitDebugSetting(pDM_Odm);
@@ -736,8 +736,8 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
return;
/* hold ofdm counter */
- phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); /* hold page C counter */
- phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); /* hold page D counter */
+ phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */
+ phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */
ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
@@ -760,8 +760,8 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
FalseAlmCnt->Cnt_BW_USC = (ret_value & 0xffff0000)>>16;
/* hold cck counter */
- phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
FalseAlmCnt->Cnt_Cck_fail = ret_value;
@@ -853,7 +853,7 @@ void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
}
if (pDM_PSTable->initialize == 0) {
pDM_PSTable->Reg874 = (phy_query_bb_reg(adapter, 0x874, bMaskDWord)&0x1CC000)>>14;
- pDM_PSTable->RegC70 = (phy_query_bb_reg(adapter, 0xc70, bMaskDWord)&BIT3)>>3;
+ pDM_PSTable->RegC70 = (phy_query_bb_reg(adapter, 0xc70, bMaskDWord) & BIT(3))>>3;
pDM_PSTable->Reg85C = (phy_query_bb_reg(adapter, 0x85c, bMaskDWord)&0xFF000000)>>24;
pDM_PSTable->RegA74 = (phy_query_bb_reg(adapter, 0xa74, bMaskDWord)&0xF000)>>12;
pDM_PSTable->initialize = 1;
@@ -882,18 +882,18 @@ void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
if (pDM_PSTable->CurRFState == RF_Save) {
phy_set_bb_reg(adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */
- phy_set_bb_reg(adapter, 0xc70, BIT3, 0); /* RegC70[3]=1'b0 */
+ phy_set_bb_reg(adapter, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */
phy_set_bb_reg(adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */
phy_set_bb_reg(adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */
phy_set_bb_reg(adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */
- phy_set_bb_reg(adapter, 0x818, BIT28, 0x0); /* Reg818[28]=1'b0 */
- phy_set_bb_reg(adapter, 0x818, BIT28, 0x1); /* Reg818[28]=1'b1 */
+ phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */
+ phy_set_bb_reg(adapter, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */
} else {
phy_set_bb_reg(adapter, 0x874, 0x1CC000, pDM_PSTable->Reg874);
- phy_set_bb_reg(adapter, 0xc70, BIT3, pDM_PSTable->RegC70);
+ phy_set_bb_reg(adapter, 0xc70, BIT(3), pDM_PSTable->RegC70);
phy_set_bb_reg(adapter, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
phy_set_bb_reg(adapter, 0xa74, 0xF000, pDM_PSTable->RegA74);
- phy_set_bb_reg(adapter, 0x818, BIT28, 0x0);
+ phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0);
}
pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
}
@@ -1229,7 +1229,7 @@ void odm_TXPowerTrackingCheckCE(struct odm_dm_struct *pDM_Odm)
return;
if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */
- phy_set_rf_reg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT17 | BIT16, 0x03);
+ phy_set_rf_reg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT(17) | BIT(16), 0x03);
pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
return;
diff --git a/drivers/staging/rtl8188eu/hal/odm_HWConfig.c b/drivers/staging/rtl8188eu/hal/odm_HWConfig.c
index 36afe45d1c9a..28b9f7f591c0 100644
--- a/drivers/staging/rtl8188eu/hal/odm_HWConfig.c
+++ b/drivers/staging/rtl8188eu/hal/odm_HWConfig.c
@@ -362,7 +362,7 @@ static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
}
}
- pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0;
+ pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT(0);
} else {
RSSI_Ave = pPhyInfo->RxPWDBAll;
@@ -391,10 +391,10 @@ static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
pEntry->rssi_stat.ValidBit++;
for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
- OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0;
+ OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i) & BIT(0);
if (pEntry->rssi_stat.ValidBit == 64) {
- Weighting = ((OFDM_pkt<<4) > 64) ? 64 : (OFDM_pkt<<4);
+ Weighting = min_t(u32, OFDM_pkt << 4, 64);
UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6;
} else {
if (pEntry->rssi_stat.ValidBit != 0)
diff --git a/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c b/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c
index d3c6873925ba..c0242a095c19 100644
--- a/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c
+++ b/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c
@@ -28,26 +28,26 @@ static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
if (*(dm_odm->mp_mode) == 1) {
dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 1);
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
return;
}
/* MAC Setting */
value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
- value32|(BIT23|BIT25));
+ value32|(BIT(23) | BIT(25)));
/* Pin Settings */
- phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT22, 1);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 1);
+ phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
/* OFDM Settings */
phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
0x000000a0);
/* CCK Settings */
- phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT7, 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1);
+ phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
}
@@ -59,37 +59,37 @@ static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
if (*(dm_odm->mp_mode) == 1) {
dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT5|BIT4|BIT3, 0);
+ BIT(5) | BIT(4) | BIT(3), 0);
return;
}
/* MAC Setting */
value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
- value32|(BIT23|BIT25));
+ value32|(BIT(23) | BIT(25)));
/* Pin Settings */
- phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT22, 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 1);
+ phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
/* OFDM Settings */
phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
0x000000a0);
/* CCK Settings */
- phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT7, 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1);
+ phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
/* Tx Settings */
- phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT21, 0);
+ phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
/* antenna mapping table */
if (!dm_odm->bIsMPChip) { /* testchip */
phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
- BIT10|BIT9|BIT8, 1);
+ BIT(10) | BIT(9) | BIT(8), 1);
phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
- BIT13|BIT12|BIT11, 2);
+ BIT(13) | BIT(12) | BIT(11), 2);
} else { /* MPchip */
phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
0x0201);
@@ -118,40 +118,40 @@ static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
/* MAC Setting */
value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
- phy_set_bb_reg(adapter, 0x4c, bMaskDWord, value32|(BIT23|BIT25));
+ phy_set_bb_reg(adapter, 0x4c, bMaskDWord, value32|(BIT(23) | BIT(25)));
value32 = phy_query_bb_reg(adapter, 0x7B4, bMaskDWord);
- phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT16|BIT17));
+ phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT(16) | BIT(17)));
/* Match MAC ADDR */
phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
- phy_set_bb_reg(adapter, 0x870, BIT9|BIT8, 0);
- phy_set_bb_reg(adapter, 0x864, BIT10, 0);
- phy_set_bb_reg(adapter, 0xb2c, BIT22, 0);
- phy_set_bb_reg(adapter, 0xb2c, BIT31, 1);
+ phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
+ phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
+ phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
/* antenna mapping table */
if (AntCombination == 2) {
if (!dm_odm->bIsMPChip) { /* testchip */
- phy_set_bb_reg(adapter, 0x858, BIT10|BIT9|BIT8, 1);
- phy_set_bb_reg(adapter, 0x858, BIT13|BIT12|BIT11, 2);
+ phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
+ phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
} else { /* MPchip */
phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
}
} else if (AntCombination == 7) {
if (!dm_odm->bIsMPChip) { /* testchip */
- phy_set_bb_reg(adapter, 0x858, BIT10|BIT9|BIT8, 0);
- phy_set_bb_reg(adapter, 0x858, BIT13|BIT12|BIT11, 1);
- phy_set_bb_reg(adapter, 0x878, BIT16, 0);
- phy_set_bb_reg(adapter, 0x858, BIT15|BIT14, 2);
- phy_set_bb_reg(adapter, 0x878, BIT19|BIT18|BIT17, 3);
- phy_set_bb_reg(adapter, 0x878, BIT22|BIT21|BIT20, 4);
- phy_set_bb_reg(adapter, 0x878, BIT25|BIT24|BIT23, 5);
- phy_set_bb_reg(adapter, 0x878, BIT28|BIT27|BIT26, 6);
- phy_set_bb_reg(adapter, 0x878, BIT31|BIT30|BIT29, 7);
+ phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 1);
+ phy_set_bb_reg(adapter, 0x878, BIT(16), 0);
+ phy_set_bb_reg(adapter, 0x858, BIT(15) | BIT(14), 2);
+ phy_set_bb_reg(adapter, 0x878, BIT(19) | BIT(18) | BIT(17), 3);
+ phy_set_bb_reg(adapter, 0x878, BIT(22) | BIT(21) | BIT(20), 4);
+ phy_set_bb_reg(adapter, 0x878, BIT(25) | BIT(24) | BIT(23), 5);
+ phy_set_bb_reg(adapter, 0x878, BIT(28) | BIT(27) | BIT(26), 6);
+ phy_set_bb_reg(adapter, 0x878, BIT(31) | BIT(30) | BIT(29), 7);
} else { /* MPchip */
phy_set_bb_reg(adapter, 0x914, bMaskByte0, 0);
phy_set_bb_reg(adapter, 0x914, bMaskByte1, 1);
@@ -165,13 +165,13 @@ static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
}
/* Default Ant Setting when no fast training */
- phy_set_bb_reg(adapter, 0x80c, BIT21, 1);
- phy_set_bb_reg(adapter, 0x864, BIT5|BIT4|BIT3, 0);
- phy_set_bb_reg(adapter, 0x864, BIT8|BIT7|BIT6, 1);
+ phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
+ phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
+ phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
/* Enter Traing state */
- phy_set_bb_reg(adapter, 0x864, BIT2|BIT1|BIT0, (AntCombination-1));
- phy_set_bb_reg(adapter, 0xc50, BIT7, 1);
+ phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), (AntCombination-1));
+ phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
}
void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
@@ -205,18 +205,18 @@ void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT5|BIT4|BIT3, default_ant);
+ BIT(5) | BIT(4) | BIT(3), default_ant);
phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT8|BIT7|BIT6, optional_ant);
+ BIT(8) | BIT(7) | BIT(6), optional_ant);
phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
- BIT14|BIT13|BIT12, default_ant);
+ BIT(14) | BIT(13) | BIT(12), default_ant);
phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
- BIT6|BIT7, default_ant);
+ BIT(6) | BIT(7), default_ant);
} else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT5|BIT4|BIT3, default_ant);
+ BIT(5) | BIT(4) | BIT(3), default_ant);
phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT8|BIT7|BIT6, optional_ant);
+ BIT(8) | BIT(7) | BIT(6), optional_ant);
}
}
dm_fat_tbl->RxIdleAnt = ant;
@@ -231,9 +231,9 @@ static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
target_ant = MAIN_ANT_CG_TRX;
else
target_ant = AUX_ANT_CG_TRX;
- dm_fat_tbl->antsel_a[mac_id] = target_ant&BIT0;
- dm_fat_tbl->antsel_b[mac_id] = (target_ant&BIT1)>>1;
- dm_fat_tbl->antsel_c[mac_id] = (target_ant&BIT2)>>2;
+ dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
+ dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1))>>1;
+ dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2))>>2;
}
void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
@@ -292,8 +292,7 @@ static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
(dm_fat_tbl->AuxAnt_Sum[i]/dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
target_ant = (main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT;
/* 2 Select max_rssi for DIG */
- local_max_rssi = (main_rssi > aux_rssi) ?
- main_rssi : aux_rssi;
+ local_max_rssi = max(main_rssi, aux_rssi);
if ((local_max_rssi > ant_div_max_rssi) &&
(local_max_rssi < 40))
ant_div_max_rssi = local_max_rssi;
@@ -308,8 +307,7 @@ static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
(aux_rssi == 0))
aux_rssi = main_rssi;
- local_min_rssi = (main_rssi > aux_rssi) ?
- aux_rssi : main_rssi;
+ local_min_rssi = min(main_rssi, aux_rssi);
if (local_min_rssi < min_rssi) {
min_rssi = local_min_rssi;
RxIdleAnt = target_ant;
@@ -344,12 +342,12 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
if (dm_fat_tbl->bBecomeLinked) {
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("Need to Turn off HW AntDiv\n"));
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
- BIT15, 0);
+ BIT(15), 0);
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
- BIT21, 0);
+ BIT(21), 0);
dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
}
return;
@@ -357,12 +355,12 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
if (!dm_fat_tbl->bBecomeLinked) {
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("Need to Turn on HW AntDiv\n"));
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 1);
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
- BIT15, 1);
+ BIT(15), 1);
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
- BIT21, 1);
+ BIT(21), 1);
dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
}
}
diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c
index 2eafa503f343..d3e8a8ea1829 100644
--- a/drivers/staging/rtl8188eu/hal/phy.c
+++ b/drivers/staging/rtl8188eu/hal/phy.c
@@ -97,9 +97,9 @@ static u32 rf_serial_read(struct adapter *adapt,
udelay(10);
if (rfpath == RF_PATH_A)
- rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT8);
+ rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
else if (rfpath == RF_PATH_B)
- rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT8);
+ rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
if (rfpi_enable)
ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
@@ -293,7 +293,7 @@ static void phy_set_bw_mode_callback(struct adapter *adapt)
(hal_data->nCur40MhzPrimeSC>>1));
phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
hal_data->nCur40MhzPrimeSC);
- phy_set_bb_reg(adapt, 0x818, (BIT26 | BIT27),
+ phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
(hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
break;
default:
@@ -652,7 +652,7 @@ static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
- if (!(reg_eac & BIT28) &&
+ if (!(reg_eac & BIT(28)) &&
(((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
(((reg_e9c & 0x03FF0000)>>16) != 0x42))
result |= 0x01;
@@ -705,7 +705,7 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
- if (!(reg_eac & BIT28) &&
+ if (!(reg_eac & BIT(28)) &&
(((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
(((reg_e9c & 0x03FF0000)>>16) != 0x42))
result |= 0x01;
@@ -753,7 +753,7 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
- if (!(reg_eac & BIT27) && /* if Tx is OK, check whether Rx is OK */
+ if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
(((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
(((reg_eac & 0x03FF0000)>>16) != 0x36))
result |= 0x02;
@@ -783,14 +783,14 @@ static u8 phy_path_b_iqk(struct adapter *adapt)
regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
- if (!(regeac & BIT31) &&
+ if (!(regeac & BIT(31)) &&
(((regeb4 & 0x03FF0000)>>16) != 0x142) &&
(((regebc & 0x03FF0000)>>16) != 0x42))
result |= 0x01;
else
return result;
- if (!(regeac & BIT30) &&
+ if (!(regeac & BIT(30)) &&
(((regec4 & 0x03FF0000)>>16) != 0x132) &&
(((regecc & 0x03FF0000)>>16) != 0x36))
result |= 0x02;
@@ -959,9 +959,9 @@ static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *ba
usb_write8(adapt, mac_reg[i], 0x3F);
for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
- usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT3)));
+ usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
}
- usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT5)));
+ usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
}
static void path_a_standby(struct adapter *adapt)
@@ -1013,7 +1013,7 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
tmp2 = resulta[c2][i];
}
- diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
+ diff = abs(tmp1 - tmp2);
if (diff > MAX_TOLERANCE) {
if ((i == 2 || i == 6) && !sim_bitmap) {
@@ -1117,15 +1117,15 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
}
/* BB setting */
- phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT24, 0x00);
+ phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
- phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
- phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
- phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
- phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
+ phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
+ phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
+ phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
+ phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
if (is2t) {
phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c
index 067649a7fbec..44945427cc34 100644
--- a/drivers/staging/rtl8188eu/hal/rf_cfg.c
+++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c
@@ -198,7 +198,7 @@ static void rtl8188e_config_rf_reg(struct adapter *adapt,
static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt)
{
u32 i;
- u32 array_len = sizeof(Array_RadioA_1T_8188E)/sizeof(u32);
+ u32 array_len = ARRAY_SIZE(Array_RadioA_1T_8188E);
u32 *array = Array_RadioA_1T_8188E;
for (i = 0; i < array_len; i += 2) {
@@ -214,7 +214,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt)
while (v2 != 0xDEAD && v2 != 0xCDEF &&
v2 != 0xCDCD && i < array_len - 2)
READ_NEXT_PAIR(v1, v2, i);
- i -= 2;
+ i -= 2;
} else {
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD && v2 != 0xCDEF &&
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index d5281409168d..580876313e98 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -149,7 +149,7 @@ void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi
init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
- shortGIrate = (arg&BIT(5)) ? true : false;
+ shortGIrate = (arg & BIT(5)) ? true : false;
if (shortGIrate)
init_rate |= BIT(6);
@@ -277,7 +277,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(u32, rate_len, 8), cur_network->SupportedRates, &pktlen);
/* DS parameter set */
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
@@ -577,23 +577,23 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
/* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
/* Set REG_CR bit 8. DMA beacon by SW. */
- haldata->RegCR_1 |= BIT0;
+ haldata->RegCR_1 |= BIT(0);
usb_write8(adapt, REG_CR+1, haldata->RegCR_1);
/* Disable Hw protection for a time which revserd for Hw sending beacon. */
/* Fix download reserved page packet fail that access collision with the protection time. */
/* 2010.05.11. Added by tynli. */
usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
- usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)|BIT(4));
+ usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(4));
- if (haldata->RegFwHwTxQCtrl&BIT6) {
+ if (haldata->RegFwHwTxQCtrl & BIT(6)) {
DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
bSendBeacon = true;
}
/* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
- usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT6)));
- haldata->RegFwHwTxQCtrl &= (~BIT6);
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT(6))));
+ haldata->RegFwHwTxQCtrl &= (~BIT(6));
/* Clear beacon valid check bit. */
rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
@@ -626,7 +626,7 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
/* */
/* Enable Bcn */
- usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)|BIT(3));
+ usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(3));
usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
/* To make sure that if there exists an adapter which would like to send beacon. */
@@ -635,8 +635,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
/* the beacon cannot be sent by HW. */
/* 2010.06.23. Added by tynli. */
if (bSendBeacon) {
- usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl|BIT6));
- haldata->RegFwHwTxQCtrl |= BIT6;
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl | BIT(6)));
+ haldata->RegFwHwTxQCtrl |= BIT(6);
}
/* Update RSVD page location H2C to Fw. */
@@ -647,7 +647,7 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
/* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
/* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
- haldata->RegCR_1 &= (~BIT0);
+ haldata->RegCR_1 &= (~BIT(0));
usb_write8(adapt, REG_CR+1, haldata->RegCR_1);
}
}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
index fca590949409..199a77acd7a9 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
@@ -67,7 +67,7 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_FAB_VER, fab_ver);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_CUT_VER, cut_ver);
- ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(hal_data->VersionID));
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, hal_data->VersionID.ChipType == NORMAL_CHIP ? true : false);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PATCH_ID, hal_data->CustomerID);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
index a6295ca6a73e..2592bc298f84 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -53,7 +53,7 @@ s32 iol_execute(struct adapter *padapter, u8 control)
{
s32 status = _FAIL;
u8 reg_0x88 = 0;
- u32 start = 0, passing_time = 0;
+ unsigned long start = 0;
control = control&0x0f;
reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
@@ -61,8 +61,8 @@ s32 iol_execute(struct adapter *padapter, u8 control)
start = jiffies;
while ((reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0)) & control &&
- (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
- ;
+ jiffies_to_msecs(jiffies - start) < 1000) {
+ udelay(5);
}
reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
@@ -106,8 +106,8 @@ void _8051Reset88E(struct adapter *padapter)
u8 u1bTmp;
u1bTmp = usb_read8(padapter, REG_SYS_FUNC_EN+1);
- usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
- usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT2));
+ usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT(2)));
+ usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT(2)));
DBG_88E("=====> _8051Reset88E(): 8051 reset success .\n");
}
@@ -184,10 +184,10 @@ static void hal_notch_filter_8188e(struct adapter *adapter, bool enable)
{
if (enable) {
DBG_88E("Enable notch filter\n");
- usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
+ usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) | BIT(1));
} else {
DBG_88E("Disable notch filter\n");
- usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
+ usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT(1));
}
}
void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
@@ -242,6 +242,7 @@ static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data)
status = _FAIL;
break;
}
+ udelay(5);
} while (count++);
return status;
@@ -372,7 +373,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
} else {
pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
- if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
}
@@ -380,7 +381,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
} else {
pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
- if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
}
pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
@@ -390,7 +391,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
} else {
pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
- if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
}
@@ -398,7 +399,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
} else {
pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
- if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
}
eeAddr++;
@@ -407,7 +408,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
} else {
pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
- if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
}
@@ -415,7 +416,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
} else {
pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
- if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
}
eeAddr++;
@@ -444,6 +445,9 @@ static u8 Hal_GetChnlGroup88E(u8 chnl, u8 *pGroup)
else if (chnl == 14) /* Channel 14 */
*pGroup = 5;
} else {
+
+ /* probably, this branch is suitable only for 5 GHz */
+
bIn24G = false;
if (chnl <= 40)
@@ -485,13 +489,13 @@ void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoL
/* hw power down mode selection , 0:rf-off / 1:power down */
if (padapter->registrypriv.hwpdn_mode == 2)
- padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT4);
+ padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT(4));
else
padapter->pwrctrlpriv.bHWPowerdown = padapter->registrypriv.hwpdn_mode;
/* decide hw if support remote wakeup function */
/* if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */
- padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT1) ? true : false;
+ padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false;
DBG_88E("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) , bSupportRemoteWakeup(%x)\n", __func__,
padapter->pwrctrlpriv.bHWPwrPindetect, padapter->pwrctrlpriv.bHWPowerdown , padapter->pwrctrlpriv.bSupportRemoteWakeup);
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
index 81d691ddd6c6..564cf53bff1b 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
@@ -36,7 +36,7 @@ void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
return;
LedCfg = usb_read8(padapter, REG_LEDCFG2);
- usb_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
+ usb_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0) | BIT(5) | BIT(6)); /* SW control led0 on. */
pLed->bLedOn = true;
}
@@ -55,12 +55,12 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
if (pHalData->bLedOpenDrain) {
/* Open-drain arrangement for controlling the LED) */
LedCfg &= 0x90; /* Set to software control. */
- usb_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3));
+ usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
LedCfg = usb_read8(padapter, REG_MAC_PINMUX_CFG);
LedCfg &= 0xFE;
usb_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
} else {
- usb_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3|BIT5|BIT6));
+ usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3) | BIT(5) | BIT(6)));
}
exit:
pLed->bLedOn = false;
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
index 7c5086ecff17..e04303ce80af 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
@@ -463,30 +463,26 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp
}
/* 3 1. pick up first frame */
- do {
- rtw_free_xmitframe(pxmitpriv, pxmitframe);
-
- pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
- if (pxmitframe == NULL) {
- /* no more xmit frame, release xmit buffer */
- rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitframe->buf_addr = pxmitbuf->pbuf;
- pxmitbuf->priv_data = pxmitframe;
+ pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+ if (pxmitframe == NULL) {
+ /* no more xmit frame, release xmit buffer */
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ return false;
+ }
- pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
- pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pxmitframe;
- rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
+ pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
+ pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
- /* always return ndis_packet after rtw_xmitframe_coalesce */
- rtw_os_xmit_complete(adapt, pxmitframe);
+ rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
- break;
- } while (1);
+ /* always return ndis_packet after rtw_xmitframe_coalesce */
+ rtw_os_xmit_complete(adapt, pxmitframe);
/* 3 2. aggregate same priority and same DA(AP or STA) frames */
pfirstframe = pxmitframe;
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
index 1ef878fd997b..5789e1e23f0a 100644
--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
+++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
@@ -607,7 +607,7 @@ static void _InitBeaconParameters(struct adapter *Adapter)
static void _BeaconFunctionEnable(struct adapter *Adapter,
bool Enable, bool Linked)
{
- usb_write8(Adapter, REG_BCN_CTRL, (BIT4 | BIT3 | BIT1));
+ usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1)));
usb_write8(Adapter, REG_RD_CTRL+1, 0x6F);
}
@@ -632,8 +632,8 @@ static void _InitAntenna_Selection(struct adapter *Adapter)
return;
DBG_88E("==> %s ....\n", __func__);
- usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0)|BIT23);
- phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT13, 0x01);
+ usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0) | BIT(23));
+ phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
if (phy_query_bb_reg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A)
haldata->CurAntenna = Antenna_A;
@@ -664,13 +664,13 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt)
if (adapt->pwrctrlpriv.bHWPowerdown) {
val8 = usb_read8(adapt, REG_HSISR);
- DBG_88E("pwrdown, 0x5c(BIT7)=%02x\n", val8);
- rfpowerstate = (val8 & BIT7) ? rf_off : rf_on;
+ DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8);
+ rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on;
} else { /* rf on/off */
- usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT3));
+ usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT(3)));
val8 = usb_read8(adapt, REG_GPIO_IO_SEL);
DBG_88E("GPIO_IN=%02x\n", val8);
- rfpowerstate = (val8 & BIT3) ? rf_on : rf_off;
+ rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off;
}
return rfpowerstate;
} /* HalDetectPwrDownMode */
@@ -684,7 +684,7 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
- u32 init_start_time = jiffies;
+ unsigned long init_start_time = jiffies;
#define HAL_INIT_PROFILE_TAG(stage) do {} while (0)
@@ -805,7 +805,7 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
/* Enable TX Report */
/* Enable Tx Report Timer */
value8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
- usb_write8(Adapter, REG_TX_RPT_CTRL, (value8|BIT1|BIT0));
+ usb_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0)));
/* Set MAX RPT MACID */
usb_write8(Adapter, REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
/* Tx RPT Timer. Unit: 32us */
@@ -898,12 +898,13 @@ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
usb_write8(Adapter, REG_USB_HRPWM, 0);
/* ack for xmit mgmt frames. */
- usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
+ usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12));
exit:
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
- DBG_88E("%s in %dms\n", __func__, rtw_get_passing_time_ms(init_start_time));
+ DBG_88E("%s in %dms\n", __func__,
+ jiffies_to_msecs(jiffies - init_start_time));
return status;
@@ -918,7 +919,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter)
/* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
val8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
- usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT1));
+ usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT(1)));
/* stop rx */
usb_write8(Adapter, REG_CR, 0x0);
@@ -944,7 +945,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter)
/* YJ,add,111212 */
/* Disable 32k */
val8 = usb_read8(Adapter, REG_32K_CTRL);
- usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT0));
+ usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT(0)));
/* Card disable power action flow */
rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK,
@@ -953,9 +954,9 @@ static void CardDisableRTL8188EU(struct adapter *Adapter)
/* Reset MCU IO Wrapper */
val8 = usb_read8(Adapter, REG_RSV_CTRL+1);
- usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT3)));
+ usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT(3))));
val8 = usb_read8(Adapter, REG_RSV_CTRL+1);
- usb_write8(Adapter, REG_RSV_CTRL+1, val8|BIT3);
+ usb_write8(Adapter, REG_RSV_CTRL+1, val8 | BIT(3));
/* YJ,test add, 111207. For Power Consumption. */
val8 = usb_read8(Adapter, GPIO_IN);
@@ -1149,14 +1150,15 @@ static void _ReadRFType(struct adapter *Adapter)
static void _ReadAdapterInfo8188EU(struct adapter *Adapter)
{
- u32 start = jiffies;
+ unsigned long start = jiffies;
MSG_88E("====> %s\n", __func__);
_ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
_ReadPROMContent(Adapter);
- MSG_88E("<==== %s in %d ms\n", __func__, rtw_get_passing_time_ms(start));
+ MSG_88E("<==== %s in %d ms\n", __func__,
+ jiffies_to_msecs(jiffies - start));
}
#define GPIO_DEBUG_PORT_NUM 0
@@ -1171,10 +1173,10 @@ static void ResumeTxBeacon(struct adapter *adapt)
/* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
/* which should be read from register to a global variable. */
- usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT6);
- haldata->RegFwHwTxQCtrl |= BIT6;
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT(6));
+ haldata->RegFwHwTxQCtrl |= BIT(6);
usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff);
- haldata->RegReg542 |= BIT0;
+ haldata->RegReg542 |= BIT(0);
usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
}
@@ -1185,10 +1187,10 @@ static void StopTxBeacon(struct adapter *adapt)
/* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
/* which should be read from register to a global variable. */
- usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT6));
- haldata->RegFwHwTxQCtrl &= (~BIT6);
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
+ haldata->RegFwHwTxQCtrl &= (~BIT(6));
usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64);
- haldata->RegReg542 &= ~(BIT0);
+ haldata->RegReg542 &= ~(BIT(0));
usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
/* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */
@@ -1200,7 +1202,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val)
u8 mode = *((u8 *)val);
/* disable Port0 TSF update */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
/* set net_type */
val8 = usb_read8(Adapter, MSR)&0x0c;
@@ -1378,7 +1380,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
usb_write32(Adapter, REG_TSFTR+4, tsf>>32);
/* enable related TSF function */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(3));
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3));
if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
ResumeTxBeacon(Adapter);
@@ -1403,10 +1405,10 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
/* reset TSF */
- usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1)));
+ usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
/* disable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
break;
case HW_VAR_MLME_SITESURVEY:
if (*((u8 *)val)) { /* under sitesurvey */
@@ -1418,7 +1420,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
/* disable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
} else { /* sitesurvey done */
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -1578,7 +1580,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
}
break;
case HW_VAR_CAM_INVALID_ALL:
- usb_write32(Adapter, RWCAM, BIT(31)|BIT(30));
+ usb_write32(Adapter, RWCAM, BIT(31) | BIT(30));
break;
case HW_VAR_CAM_WRITE:
{
@@ -1795,7 +1797,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
break;
case HW_VAR_BCN_VALID:
/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
- usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT0);
+ usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT(0));
break;
default:
break;
@@ -1815,7 +1817,7 @@ static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
break;
case HW_VAR_BCN_VALID:
/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
- val[0] = (BIT0 & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false;
+ val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false;
break;
case HW_VAR_DM_FLAG:
val[0] = podmpriv->SupportAbility;
@@ -2052,7 +2054,7 @@ static void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt)
ResumeTxBeacon(adapt);
- usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg)|BIT(1));
+ usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg) | BIT(1));
}
static void rtl8188eu_init_default_value(struct adapter *adapt)
diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
index 20e6b40fc35c..e058162fe2ba 100644
--- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
+++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
@@ -87,13 +87,13 @@ enum rf_radio_path {
enum wireless_mode {
WIRELESS_MODE_UNKNOWN = 0x00,
- WIRELESS_MODE_A = BIT2,
- WIRELESS_MODE_B = BIT0,
- WIRELESS_MODE_G = BIT1,
- WIRELESS_MODE_AUTO = BIT5,
- WIRELESS_MODE_N_24G = BIT3,
- WIRELESS_MODE_N_5G = BIT4,
- WIRELESS_MODE_AC = BIT6
+ WIRELESS_MODE_A = BIT(2),
+ WIRELESS_MODE_B = BIT(0),
+ WIRELESS_MODE_G = BIT(1),
+ WIRELESS_MODE_AUTO = BIT(5),
+ WIRELESS_MODE_N_24G = BIT(3),
+ WIRELESS_MODE_N_5G = BIT(4),
+ WIRELESS_MODE_AC = BIT(6)
};
enum phy_rate_tx_offset_area {
diff --git a/drivers/staging/rtl8188eu/include/HalVerDef.h b/drivers/staging/rtl8188eu/include/HalVerDef.h
index 56b4ff08e509..6f2b2a436b04 100644
--- a/drivers/staging/rtl8188eu/include/HalVerDef.h
+++ b/drivers/staging/rtl8188eu/include/HalVerDef.h
@@ -47,37 +47,4 @@ struct HAL_VERSION {
enum HAL_VENDOR VendorType;
};
-/* Get element */
-#define GET_CVID_CHIP_TYPE(version) (((version).ChipType))
-#define GET_CVID_MANUFACTUER(version) (((version).VendorType))
-#define GET_CVID_CUT_VERSION(version) (((version).CUTVersion))
-
-/* Common Macro. -- */
-/* HAL_VERSION VersionID */
-
-/* HAL_CHIP_TYPE_E */
-#define IS_TEST_CHIP(version) \
- ((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false)
-#define IS_NORMAL_CHIP(version) \
- ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false)
-
-/* HAL_CUT_VERSION_E */
-#define IS_A_CUT(version) \
- ((GET_CVID_CUT_VERSION(version) == A_CUT_VERSION) ? true : false)
-#define IS_B_CUT(version) \
- ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true : false)
-#define IS_C_CUT(version) \
- ((GET_CVID_CUT_VERSION(version) == C_CUT_VERSION) ? true : false)
-#define IS_D_CUT(version) \
- ((GET_CVID_CUT_VERSION(version) == D_CUT_VERSION) ? true : false)
-#define IS_E_CUT(version) \
- ((GET_CVID_CUT_VERSION(version) == E_CUT_VERSION) ? true : false)
-
-
-/* HAL_VENDOR_E */
-#define IS_CHIP_VENDOR_TSMC(version) \
- ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_TSMC) ? true : false)
-#define IS_CHIP_VENDOR_UMC(version) \
- ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
-
#endif
diff --git a/drivers/staging/rtl8188eu/include/basic_types.h b/drivers/staging/rtl8188eu/include/basic_types.h
index 8a7ca992674a..6a2a147e6d15 100644
--- a/drivers/staging/rtl8188eu/include/basic_types.h
+++ b/drivers/staging/rtl8188eu/include/basic_types.h
@@ -20,9 +20,6 @@
#ifndef __BASIC_TYPES_H__
#define __BASIC_TYPES_H__
-#define SUCCESS 0
-#define FAIL (-1)
-
#include <linux/types.h>
#define NDIS_OID uint
@@ -30,9 +27,6 @@ typedef void (*proc_t)(void *);
#define FIELD_OFFSET(s, field) ((ssize_t)&((s *)(0))->field)
-#define MEM_ALIGNMENT_OFFSET (sizeof(size_t))
-#define MEM_ALIGNMENT_PADDING (sizeof(size_t) - 1)
-
/* port from fw */
/* TODO: Macros Below are Sync from SD7-Driver. It is necessary
* to check correctness */
diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h
index e73c6341248e..1b1c10292456 100644
--- a/drivers/staging/rtl8188eu/include/hal_intf.h
+++ b/drivers/staging/rtl8188eu/include/hal_intf.h
@@ -25,10 +25,10 @@
#include <Hal8188EPhyCfg.h>
enum RTL871X_HCI_TYPE {
- RTW_PCIE = BIT0,
- RTW_USB = BIT1,
- RTW_SDIO = BIT2,
- RTW_GSPI = BIT3,
+ RTW_PCIE = BIT(0),
+ RTW_USB = BIT(1),
+ RTW_SDIO = BIT(2),
+ RTW_GSPI = BIT(3),
};
enum _CHIP_TYPE {
@@ -226,10 +226,10 @@ enum rt_eeprom_type {
};
#define RF_CHANGE_BY_INIT 0
-#define RF_CHANGE_BY_IPS BIT28
-#define RF_CHANGE_BY_PS BIT29
-#define RF_CHANGE_BY_HW BIT30
-#define RF_CHANGE_BY_SW BIT31
+#define RF_CHANGE_BY_IPS BIT(28)
+#define RF_CHANGE_BY_PS BIT(29)
+#define RF_CHANGE_BY_HW BIT(30)
+#define RF_CHANGE_BY_SW BIT(31)
enum hardware_type {
HARDWARE_TYPE_RTL8188EU,
diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h
index 73ef9c7596c1..bc970caf7eda 100644
--- a/drivers/staging/rtl8188eu/include/odm.h
+++ b/drivers/staging/rtl8188eu/include/odm.h
@@ -414,31 +414,31 @@ enum odm_common_info_def {
enum odm_ability_def {
/* BB ODM section BIT 0-15 */
- ODM_BB_DIG = BIT0,
- ODM_BB_RA_MASK = BIT1,
- ODM_BB_DYNAMIC_TXPWR = BIT2,
- ODM_BB_FA_CNT = BIT3,
- ODM_BB_RSSI_MONITOR = BIT4,
- ODM_BB_CCK_PD = BIT5,
- ODM_BB_ANT_DIV = BIT6,
- ODM_BB_PWR_SAVE = BIT7,
- ODM_BB_PWR_TRA = BIT8,
- ODM_BB_RATE_ADAPTIVE = BIT9,
- ODM_BB_PATH_DIV = BIT10,
- ODM_BB_PSD = BIT11,
- ODM_BB_RXHP = BIT12,
+ ODM_BB_DIG = BIT(0),
+ ODM_BB_RA_MASK = BIT(1),
+ ODM_BB_DYNAMIC_TXPWR = BIT(2),
+ ODM_BB_FA_CNT = BIT(3),
+ ODM_BB_RSSI_MONITOR = BIT(4),
+ ODM_BB_CCK_PD = BIT(5),
+ ODM_BB_ANT_DIV = BIT(6),
+ ODM_BB_PWR_SAVE = BIT(7),
+ ODM_BB_PWR_TRA = BIT(8),
+ ODM_BB_RATE_ADAPTIVE = BIT(9),
+ ODM_BB_PATH_DIV = BIT(10),
+ ODM_BB_PSD = BIT(11),
+ ODM_BB_RXHP = BIT(12),
/* MAC DM section BIT 16-23 */
- ODM_MAC_EDCA_TURBO = BIT16,
- ODM_MAC_EARLY_MODE = BIT17,
+ ODM_MAC_EDCA_TURBO = BIT(16),
+ ODM_MAC_EARLY_MODE = BIT(17),
/* RF ODM section BIT 24-31 */
- ODM_RF_TX_PWR_TRACK = BIT24,
- ODM_RF_RX_GAIN_TRACK = BIT25,
- ODM_RF_CALIBRATION = BIT26,
+ ODM_RF_TX_PWR_TRACK = BIT(24),
+ ODM_RF_RX_GAIN_TRACK = BIT(25),
+ ODM_RF_CALIBRATION = BIT(26),
};
-#define ODM_RTL8188E BIT4
+#define ODM_RTL8188E BIT(4)
/* ODM_CMNINFO_CUT_VER */
enum odm_cut_version {
@@ -460,14 +460,14 @@ enum odm_fab_Version {
/* ODM_CMNINFO_RF_TYPE */
/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
enum odm_rf_path {
- ODM_RF_TX_A = BIT0,
- ODM_RF_TX_B = BIT1,
- ODM_RF_TX_C = BIT2,
- ODM_RF_TX_D = BIT3,
- ODM_RF_RX_A = BIT4,
- ODM_RF_RX_B = BIT5,
- ODM_RF_RX_C = BIT6,
- ODM_RF_RX_D = BIT7,
+ ODM_RF_TX_A = BIT(0),
+ ODM_RF_TX_B = BIT(1),
+ ODM_RF_TX_C = BIT(2),
+ ODM_RF_TX_D = BIT(3),
+ ODM_RF_RX_A = BIT(4),
+ ODM_RF_RX_B = BIT(5),
+ ODM_RF_RX_C = BIT(6),
+ ODM_RF_RX_D = BIT(7),
};
enum odm_rf_type {
@@ -498,33 +498,33 @@ enum odm_bt_coexist {
/* ODM_CMNINFO_OP_MODE */
enum odm_operation_mode {
- ODM_NO_LINK = BIT0,
- ODM_LINK = BIT1,
- ODM_SCAN = BIT2,
- ODM_POWERSAVE = BIT3,
- ODM_AP_MODE = BIT4,
- ODM_CLIENT_MODE = BIT5,
- ODM_AD_HOC = BIT6,
- ODM_WIFI_DIRECT = BIT7,
- ODM_WIFI_DISPLAY = BIT8,
+ ODM_NO_LINK = BIT(0),
+ ODM_LINK = BIT(1),
+ ODM_SCAN = BIT(2),
+ ODM_POWERSAVE = BIT(3),
+ ODM_AP_MODE = BIT(4),
+ ODM_CLIENT_MODE = BIT(5),
+ ODM_AD_HOC = BIT(6),
+ ODM_WIFI_DIRECT = BIT(7),
+ ODM_WIFI_DISPLAY = BIT(8),
};
/* ODM_CMNINFO_WM_MODE */
enum odm_wireless_mode {
ODM_WM_UNKNOW = 0x0,
- ODM_WM_B = BIT0,
- ODM_WM_G = BIT1,
- ODM_WM_A = BIT2,
- ODM_WM_N24G = BIT3,
- ODM_WM_N5G = BIT4,
- ODM_WM_AUTO = BIT5,
- ODM_WM_AC = BIT6,
+ ODM_WM_B = BIT(0),
+ ODM_WM_G = BIT(1),
+ ODM_WM_A = BIT(2),
+ ODM_WM_N24G = BIT(3),
+ ODM_WM_N5G = BIT(4),
+ ODM_WM_AUTO = BIT(5),
+ ODM_WM_AC = BIT(6),
};
/* ODM_CMNINFO_BAND */
enum odm_band_type {
- ODM_BAND_2_4G = BIT0,
- ODM_BAND_5G = BIT1,
+ ODM_BAND_2_4G = BIT(0),
+ ODM_BAND_5G = BIT(1),
};
/* ODM_CMNINFO_SEC_CHNL_OFFSET */
diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h
index 914f831a5b77..e9390963d6ff 100644
--- a/drivers/staging/rtl8188eu/include/odm_debug.h
+++ b/drivers/staging/rtl8188eu/include/odm_debug.h
@@ -57,30 +57,30 @@
/* Define the tracing components */
/* BB Functions */
-#define ODM_COMP_DIG BIT0
-#define ODM_COMP_RA_MASK BIT1
-#define ODM_COMP_DYNAMIC_TXPWR BIT2
-#define ODM_COMP_FA_CNT BIT3
-#define ODM_COMP_RSSI_MONITOR BIT4
-#define ODM_COMP_CCK_PD BIT5
-#define ODM_COMP_ANT_DIV BIT6
-#define ODM_COMP_PWR_SAVE BIT7
-#define ODM_COMP_PWR_TRA BIT8
-#define ODM_COMP_RATE_ADAPTIVE BIT9
-#define ODM_COMP_PATH_DIV BIT10
-#define ODM_COMP_PSD BIT11
-#define ODM_COMP_DYNAMIC_PRICCA BIT12
-#define ODM_COMP_RXHP BIT13
+#define ODM_COMP_DIG BIT(0)
+#define ODM_COMP_RA_MASK BIT(1)
+#define ODM_COMP_DYNAMIC_TXPWR BIT(2)
+#define ODM_COMP_FA_CNT BIT(3)
+#define ODM_COMP_RSSI_MONITOR BIT(4)
+#define ODM_COMP_CCK_PD BIT(5)
+#define ODM_COMP_ANT_DIV BIT(6)
+#define ODM_COMP_PWR_SAVE BIT(7)
+#define ODM_COMP_PWR_TRA BIT(8)
+#define ODM_COMP_RATE_ADAPTIVE BIT(9)
+#define ODM_COMP_PATH_DIV BIT(10)
+#define ODM_COMP_PSD BIT(11)
+#define ODM_COMP_DYNAMIC_PRICCA BIT(12)
+#define ODM_COMP_RXHP BIT(13)
/* MAC Functions */
-#define ODM_COMP_EDCA_TURBO BIT16
-#define ODM_COMP_EARLY_MODE BIT17
+#define ODM_COMP_EDCA_TURBO BIT(16)
+#define ODM_COMP_EARLY_MODE BIT(17)
/* RF Functions */
-#define ODM_COMP_TX_PWR_TRACK BIT24
-#define ODM_COMP_RX_GAIN_TRACK BIT25
-#define ODM_COMP_CALIBRATION BIT26
+#define ODM_COMP_TX_PWR_TRACK BIT(24)
+#define ODM_COMP_RX_GAIN_TRACK BIT(25)
+#define ODM_COMP_CALIBRATION BIT(26)
/* Common Functions */
-#define ODM_COMP_COMMON BIT30
-#define ODM_COMP_INIT BIT31
+#define ODM_COMP_COMMON BIT(30)
+#define ODM_COMP_INIT BIT(31)
/*------------------------Export Marco Definition---------------------------*/
#define RT_PRINTK(fmt, args...) \
diff --git a/drivers/staging/rtl8188eu/include/odm_reg.h b/drivers/staging/rtl8188eu/include/odm_reg.h
index 89bc46bc71b0..7f10b695cf9d 100644
--- a/drivers/staging/rtl8188eu/include/odm_reg.h
+++ b/drivers/staging/rtl8188eu/include/odm_reg.h
@@ -112,7 +112,7 @@
/* Bitmap Definition */
/* */
-#define BIT_FA_RESET BIT0
+#define BIT_FA_RESET BIT(0)
diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h
index 96505a6dbe2c..22de53d6539a 100644
--- a/drivers/staging/rtl8188eu/include/osdep_service.h
+++ b/drivers/staging/rtl8188eu/include/osdep_service.h
@@ -75,45 +75,6 @@ static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3));
}
-
-#define BIT0 0x00000001
-#define BIT1 0x00000002
-#define BIT2 0x00000004
-#define BIT3 0x00000008
-#define BIT4 0x00000010
-#define BIT5 0x00000020
-#define BIT6 0x00000040
-#define BIT7 0x00000080
-#define BIT8 0x00000100
-#define BIT9 0x00000200
-#define BIT10 0x00000400
-#define BIT11 0x00000800
-#define BIT12 0x00001000
-#define BIT13 0x00002000
-#define BIT14 0x00004000
-#define BIT15 0x00008000
-#define BIT16 0x00010000
-#define BIT17 0x00020000
-#define BIT18 0x00040000
-#define BIT19 0x00080000
-#define BIT20 0x00100000
-#define BIT21 0x00200000
-#define BIT22 0x00400000
-#define BIT23 0x00800000
-#define BIT24 0x01000000
-#define BIT25 0x02000000
-#define BIT26 0x04000000
-#define BIT27 0x08000000
-#define BIT28 0x10000000
-#define BIT29 0x20000000
-#define BIT30 0x40000000
-#define BIT31 0x80000000
-#define BIT32 0x0100000000
-#define BIT33 0x0200000000
-#define BIT34 0x0400000000
-#define BIT35 0x0800000000
-#define BIT36 0x1000000000
-
int RTW_STATUS_CODE(int error_code);
#define rtw_update_mem_stat(flag, sz) do {} while (0)
@@ -126,8 +87,6 @@ u32 _rtw_down_sema(struct semaphore *sema);
void _rtw_init_queue(struct __queue *pqueue);
-s32 rtw_get_passing_time_ms(u32 start);
-
struct rtw_netdev_priv_indicator {
void *priv;
u32 sizeof_priv;
diff --git a/drivers/staging/rtl8188eu/include/pwrseq.h b/drivers/staging/rtl8188eu/include/pwrseq.h
index 43db92dcb8b3..8c876c6c7a4f 100644
--- a/drivers/staging/rtl8188eu/include/pwrseq.h
+++ b/drivers/staging/rtl8188eu/include/pwrseq.h
@@ -65,31 +65,31 @@
* comment here
*/ \
{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1}, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
/* wait till 0x04[17] = 1 power ready*/ \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0|BIT1, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0) | BIT(1), 0}, \
/* 0x02[1:0] = 0 reset BB*/ \
{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
/*0x24[23] = 2b'01 schmit trigger */ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \
/* 0x04[15] = 0 disable HWPDN (control by DRV)*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4|BIT3, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4) | BIT(3), 0}, \
/*0x04[12:11] = 2b'00 disable WL suspend*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
/*0x04[8] = 1 polling until return 0*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, \
/*wait till 0x04[8] = 0*/ \
{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \
/*LDO normal mode*/ \
{0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
/*SDIO Driving*/
#define RTL8188E_TRANS_ACT_TO_CARDEMU \
@@ -102,13 +102,13 @@
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \
/*0x1F[7:0] = 0 turn off RF*/ \
{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
/*LDO Sleep mode*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
/*0x04[9] = 1 turn off MAC by HW state machine*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, \
/*wait till 0x04[9] = 0 polling until return 0 to disable*/
#define RTL8188E_TRANS_CARDEMU_TO_SUS \
@@ -119,28 +119,28 @@
*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
- PWR_CMD_WRITE, BIT3|BIT4, BIT3}, \
+ PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \
/* 0x04[12:11] = 2b'01enable WL suspend */ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3|BIT4}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)}, \
/* 0x04[12:11] = 2b'11enable WL suspend for PCIe */ \
{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
- PWR_CMD_WRITE, 0xFF, BIT7}, \
+ PWR_CMD_WRITE, 0xFF, BIT(7)}, \
/* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
- PWR_CMD_WRITE, BIT4, 0}, \
+ PWR_CMD_WRITE, BIT(4), 0}, \
/*Clear SIC_EN register 0x40[12] = 1'b0 */ \
{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
- PWR_CMD_WRITE, BIT4, BIT4}, \
+ PWR_CMD_WRITE, BIT(4), BIT(4)}, \
/*Set USB suspend enable local register 0xfe10[4]=1 */ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
/*Set SDIO suspend local register*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, \
/*wait power state to suspend*/
#define RTL8188E_TRANS_SUS_TO_CARDEMU \
@@ -150,13 +150,13 @@
* comments here
*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \
/*Set SDIO suspend local register*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
/*wait power state to suspend*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, \
/*0x04[12:11] = 2b'01enable WL suspend*/
#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \
@@ -166,11 +166,11 @@
* comments here
*/ \
{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
/*0x24[23] = 2b'01 schmit trigger */ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
- PWR_CMD_WRITE, BIT3|BIT4, BIT3}, \
+ PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \
/*0x04[12:11] = 2b'01 enable WL suspend*/ \
{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
@@ -178,16 +178,16 @@
/* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \
- PWR_CMD_WRITE, BIT4, 0}, \
+ PWR_CMD_WRITE, BIT(4), 0}, \
/*Clear SIC_EN register 0x40[12] = 1'b0 */ \
{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
/*Set USB suspend enable local register 0xfe10[4]=1 */ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
/*Set SDIO suspend local register*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, \
/*wait power state to suspend*/
#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \
@@ -197,13 +197,13 @@
* comments here
*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \
/*Set SDIO suspend local register*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
- PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1}, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
/*wait power state to suspend*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, \
/*0x04[12:11] = 2b'01enable WL suspend*/
#define RTL8188E_TRANS_CARDEMU_TO_PDN \
@@ -213,10 +213,10 @@
* comments here
*/ \
{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \
/* 0x04[16] = 0*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
/* 0x04[15] = 1*/
#define RTL8188E_TRANS_PDN_TO_CARDEMU \
@@ -226,7 +226,7 @@
* comments here
*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \
/* 0x04[15] = 0*/
/* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */
@@ -251,7 +251,7 @@
PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
/*Should be zero if no packet is transmitting*/ \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \
/*CCK and OFDM are disabled,and clock are gated*/ \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, \
@@ -259,9 +259,9 @@
{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \
{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0},/*check if removed later*/\
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/\
{0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, \
/*Respond TxOK to scheduler*/
@@ -280,22 +280,22 @@
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/ \
{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \
/* 0x08[4] = 0 switch TSF to 40M */ \
{0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \
/* Polling 0x109[7]=0 TSF in 40M */ \
{0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6) | BIT(7), 0}, \
/* 0x29[7:6] = 2b'00 enable BB clock */ \
{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
/* 0x101[1] = 1 */ \
{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \
/* 0x100[7:0] = 0xFF enable WMAC TRX */ \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
- PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0}, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)}, \
/* 0x02[1:0] = 2b'11 enable BB macro */ \
{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
index e99179a794af..beeee4a6b0bc 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
@@ -19,39 +19,6 @@
#ifndef __RTL8188E_SPEC_H__
#define __RTL8188E_SPEC_H__
-#define BIT0 0x00000001
-#define BIT1 0x00000002
-#define BIT2 0x00000004
-#define BIT3 0x00000008
-#define BIT4 0x00000010
-#define BIT5 0x00000020
-#define BIT6 0x00000040
-#define BIT7 0x00000080
-#define BIT8 0x00000100
-#define BIT9 0x00000200
-#define BIT10 0x00000400
-#define BIT11 0x00000800
-#define BIT12 0x00001000
-#define BIT13 0x00002000
-#define BIT14 0x00004000
-#define BIT15 0x00008000
-#define BIT16 0x00010000
-#define BIT17 0x00020000
-#define BIT18 0x00040000
-#define BIT19 0x00080000
-#define BIT20 0x00100000
-#define BIT21 0x00200000
-#define BIT22 0x00400000
-#define BIT23 0x00800000
-#define BIT24 0x01000000
-#define BIT25 0x02000000
-#define BIT26 0x04000000
-#define BIT27 0x08000000
-#define BIT28 0x10000000
-#define BIT29 0x20000000
-#define BIT30 0x40000000
-#define BIT31 0x80000000
-
/* 8192C Regsiter offset definition */
#define HAL_PS_TIMER_INT_DELAY 50 /* 50 microseconds */
@@ -477,14 +444,14 @@
#define MAX_MSS_DENSITY_1T 0x0A
/* EEPROM enable when set 1 */
-#define CmdEEPROM_En BIT5
+#define CmdEEPROM_En BIT(5)
/* System EEPROM select, 0: boot from E-FUSE, 1: The EEPROM used is 9346 */
-#define CmdEERPOMSEL BIT4
-#define Cmd9346CR_9356SEL BIT4
+#define CmdEERPOMSEL BIT(4)
+#define Cmd9346CR_9356SEL BIT(4)
/* 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */
#define GPIOSEL_GPIO 0
-#define GPIOSEL_ENBT BIT5
+#define GPIOSEL_ENBT BIT(5)
/* 8192C GPIO PIN Control Register (offset 0x44, 4 byte) */
/* GPIO pins input value */
@@ -497,18 +464,18 @@
#define GPIO_MOD (REG_GPIO_PIN_CTRL+3)
/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */
-#define HSIMR_GPIO12_0_INT_EN BIT0
-#define HSIMR_SPS_OCP_INT_EN BIT5
-#define HSIMR_RON_INT_EN BIT6
-#define HSIMR_PDN_INT_EN BIT7
-#define HSIMR_GPIO9_INT_EN BIT25
+#define HSIMR_GPIO12_0_INT_EN BIT(0)
+#define HSIMR_SPS_OCP_INT_EN BIT(5)
+#define HSIMR_RON_INT_EN BIT(6)
+#define HSIMR_PDN_INT_EN BIT(7)
+#define HSIMR_GPIO9_INT_EN BIT(25)
/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */
-#define HSISR_GPIO12_0_INT BIT0
-#define HSISR_SPS_OCP_INT BIT5
-#define HSISR_RON_INT_EN BIT6
-#define HSISR_PDNINT BIT7
-#define HSISR_GPIO9_INT BIT25
+#define HSISR_GPIO12_0_INT BIT(0)
+#define HSISR_SPS_OCP_INT BIT(5)
+#define HSISR_RON_INT_EN BIT(6)
+#define HSISR_PDNINT BIT(7)
+#define HSISR_GPIO9_INT BIT(25)
/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */
/*
@@ -533,51 +500,51 @@ Default: 00b.
/* 88E Driver Initialization Offload REG_FDHM0(Offset 0x88, 8 bits) */
/* IOL config for REG_FDHM0(Reg0x88) */
-#define CMD_INIT_LLT BIT0
-#define CMD_READ_EFUSE_MAP BIT1
-#define CMD_EFUSE_PATCH BIT2
-#define CMD_IOCONFIG BIT3
-#define CMD_INIT_LLT_ERR BIT4
-#define CMD_READ_EFUSE_MAP_ERR BIT5
-#define CMD_EFUSE_PATCH_ERR BIT6
-#define CMD_IOCONFIG_ERR BIT7
+#define CMD_INIT_LLT BIT(0)
+#define CMD_READ_EFUSE_MAP BIT(1)
+#define CMD_EFUSE_PATCH BIT(2)
+#define CMD_IOCONFIG BIT(3)
+#define CMD_INIT_LLT_ERR BIT(4)
+#define CMD_READ_EFUSE_MAP_ERR BIT(5)
+#define CMD_EFUSE_PATCH_ERR BIT(6)
+#define CMD_IOCONFIG_ERR BIT(7)
/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
/* 8192C Response Rate Set Register (offset 0x181, 24bits) */
-#define RRSR_1M BIT0
-#define RRSR_2M BIT1
-#define RRSR_5_5M BIT2
-#define RRSR_11M BIT3
-#define RRSR_6M BIT4
-#define RRSR_9M BIT5
-#define RRSR_12M BIT6
-#define RRSR_18M BIT7
-#define RRSR_24M BIT8
-#define RRSR_36M BIT9
-#define RRSR_48M BIT10
-#define RRSR_54M BIT11
-#define RRSR_MCS0 BIT12
-#define RRSR_MCS1 BIT13
-#define RRSR_MCS2 BIT14
-#define RRSR_MCS3 BIT15
-#define RRSR_MCS4 BIT16
-#define RRSR_MCS5 BIT17
-#define RRSR_MCS6 BIT18
-#define RRSR_MCS7 BIT19
+#define RRSR_1M BIT(0)
+#define RRSR_2M BIT(1)
+#define RRSR_5_5M BIT(2)
+#define RRSR_11M BIT(3)
+#define RRSR_6M BIT(4)
+#define RRSR_9M BIT(5)
+#define RRSR_12M BIT(6)
+#define RRSR_18M BIT(7)
+#define RRSR_24M BIT(8)
+#define RRSR_36M BIT(9)
+#define RRSR_48M BIT(10)
+#define RRSR_54M BIT(11)
+#define RRSR_MCS0 BIT(12)
+#define RRSR_MCS1 BIT(13)
+#define RRSR_MCS2 BIT(14)
+#define RRSR_MCS3 BIT(15)
+#define RRSR_MCS4 BIT(16)
+#define RRSR_MCS5 BIT(17)
+#define RRSR_MCS6 BIT(18)
+#define RRSR_MCS7 BIT(19)
/* 8192C Response Rate Set Register (offset 0x1BF, 8bits) */
/* WOL bit information */
-#define HAL92C_WOL_PTK_UPDATE_EVENT BIT0
-#define HAL92C_WOL_GTK_UPDATE_EVENT BIT1
+#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0)
+#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1)
/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */
-#define BW_OPMODE_20MHZ BIT2
-#define BW_OPMODE_5G BIT1
+#define BW_OPMODE_20MHZ BIT(2)
+#define BW_OPMODE_5G BIT(1)
/* 8192C CAM Config Setting (offset 0x250, 1 byte) */
-#define CAM_VALID BIT15
+#define CAM_VALID BIT(15)
#define CAM_NOTVALID 0x0000
-#define CAM_USEDK BIT5
+#define CAM_USEDK BIT(5)
#define CAM_CONTENT_COUNT 8
@@ -594,69 +561,69 @@ Default: 00b.
#define CAM_CONFIG_USEDK true
#define CAM_CONFIG_NO_USEDK false
-#define CAM_WRITE BIT16
+#define CAM_WRITE BIT(16)
#define CAM_READ 0x00000000
-#define CAM_POLLINIG BIT31
+#define CAM_POLLINIG BIT(31)
#define SCR_UseDK 0x01
#define SCR_TxSecEnable 0x02
#define SCR_RxSecEnable 0x04
/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */
-#define WOW_PMEN BIT0 /* Power management Enable. */
-#define WOW_WOMEN BIT1 /* WoW function on or off. */
-#define WOW_MAGIC BIT2 /* Magic packet */
-#define WOW_UWF BIT3 /* Unicast Wakeup frame. */
+#define WOW_PMEN BIT(0) /* Power management Enable. */
+#define WOW_WOMEN BIT(1) /* WoW function on or off. */
+#define WOW_MAGIC BIT(2) /* Magic packet */
+#define WOW_UWF BIT(3) /* Unicast Wakeup frame. */
/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */
/* 8188 IMR/ISR bits */
#define IMR_DISABLED_88E 0x0
/* IMR DW0(0x0060-0063) Bit 0-31 */
-#define IMR_TXCCK_88E BIT30 /* TXRPT interrupt when CCX bit of the packet is set */
-#define IMR_PSTIMEOUT_88E BIT29 /* Power Save Time Out Interrupt */
-#define IMR_GTINT4_88E BIT28 /* When GTIMER4 expires, this bit is set to 1 */
-#define IMR_GTINT3_88E BIT27 /* When GTIMER3 expires, this bit is set to 1 */
-#define IMR_TBDER_88E BIT26 /* Transmit Beacon0 Error */
-#define IMR_TBDOK_88E BIT25 /* Transmit Beacon0 OK */
-#define IMR_TSF_BIT32_TOGGLE_88E BIT24 /* TSF Timer BIT32 toggle indication interrupt */
-#define IMR_BCNDMAINT0_88E BIT20 /* Beacon DMA Interrupt 0 */
-#define IMR_BCNDERR0_88E BIT16 /* Beacon Queue DMA Error 0 */
-#define IMR_HSISR_IND_ON_INT_88E BIT15 /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
-#define IMR_BCNDMAINT_E_88E BIT14 /* Beacon DMA Interrupt Extension for Win7 */
-#define IMR_ATIMEND_88E BIT12 /* CTWidnow End or ATIM Window End */
-#define IMR_HISR1_IND_INT_88E BIT11 /* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) */
-#define IMR_C2HCMD_88E BIT10 /* CPU to Host Command INT Status, Write 1 clear */
-#define IMR_CPWM2_88E BIT9 /* CPU power Mode exchange INT Status, Write 1 clear */
-#define IMR_CPWM_88E BIT8 /* CPU power Mode exchange INT Status, Write 1 clear */
-#define IMR_HIGHDOK_88E BIT7 /* High Queue DMA OK */
-#define IMR_MGNTDOK_88E BIT6 /* Management Queue DMA OK */
-#define IMR_BKDOK_88E BIT5 /* AC_BK DMA OK */
-#define IMR_BEDOK_88E BIT4 /* AC_BE DMA OK */
-#define IMR_VIDOK_88E BIT3 /* AC_VI DMA OK */
-#define IMR_VODOK_88E BIT2 /* AC_VO DMA OK */
-#define IMR_RDU_88E BIT1 /* Rx Descriptor Unavailable */
-#define IMR_ROK_88E BIT0 /* Receive DMA OK */
+#define IMR_TXCCK_88E BIT(30) /* TXRPT interrupt when CCX bit of the packet is set */
+#define IMR_PSTIMEOUT_88E BIT(29) /* Power Save Time Out Interrupt */
+#define IMR_GTINT4_88E BIT(28) /* When GTIMER4 expires, this bit is set to 1 */
+#define IMR_GTINT3_88E BIT(27) /* When GTIMER3 expires, this bit is set to 1 */
+#define IMR_TBDER_88E BIT(26) /* Transmit Beacon0 Error */
+#define IMR_TBDOK_88E BIT(25) /* Transmit Beacon0 OK */
+#define IMR_TSF_BIT32_TOGGLE_88E BIT(24) /* TSF Timer BIT32 toggle indication interrupt */
+#define IMR_BCNDMAINT0_88E BIT(20) /* Beacon DMA Interrupt 0 */
+#define IMR_BCNDERR0_88E BIT(16) /* Beacon Queue DMA Error 0 */
+#define IMR_HSISR_IND_ON_INT_88E BIT(15) /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
+#define IMR_BCNDMAINT_E_88E BIT(14) /* Beacon DMA Interrupt Extension for Win7 */
+#define IMR_ATIMEND_88E BIT(12) /* CTWidnow End or ATIM Window End */
+#define IMR_HISR1_IND_INT_88E BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) */
+#define IMR_C2HCMD_88E BIT(10) /* CPU to Host Command INT Status, Write 1 clear */
+#define IMR_CPWM2_88E BIT(9) /* CPU power Mode exchange INT Status, Write 1 clear */
+#define IMR_CPWM_88E BIT(8) /* CPU power Mode exchange INT Status, Write 1 clear */
+#define IMR_HIGHDOK_88E BIT(7) /* High Queue DMA OK */
+#define IMR_MGNTDOK_88E BIT(6) /* Management Queue DMA OK */
+#define IMR_BKDOK_88E BIT(5) /* AC_BK DMA OK */
+#define IMR_BEDOK_88E BIT(4) /* AC_BE DMA OK */
+#define IMR_VIDOK_88E BIT(3) /* AC_VI DMA OK */
+#define IMR_VODOK_88E BIT(2) /* AC_VO DMA OK */
+#define IMR_RDU_88E BIT(1) /* Rx Descriptor Unavailable */
+#define IMR_ROK_88E BIT(0) /* Receive DMA OK */
/* IMR DW1(0x00B4-00B7) Bit 0-31 */
-#define IMR_BCNDMAINT7_88E BIT27 /* Beacon DMA Interrupt 7 */
-#define IMR_BCNDMAINT6_88E BIT26 /* Beacon DMA Interrupt 6 */
-#define IMR_BCNDMAINT5_88E BIT25 /* Beacon DMA Interrupt 5 */
-#define IMR_BCNDMAINT4_88E BIT24 /* Beacon DMA Interrupt 4 */
-#define IMR_BCNDMAINT3_88E BIT23 /* Beacon DMA Interrupt 3 */
-#define IMR_BCNDMAINT2_88E BIT22 /* Beacon DMA Interrupt 2 */
-#define IMR_BCNDMAINT1_88E BIT21 /* Beacon DMA Interrupt 1 */
-#define IMR_BCNDERR7_88E BIT20 /* Beacon DMA Error Int 7 */
-#define IMR_BCNDERR6_88E BIT19 /* Beacon DMA Error Int 6 */
-#define IMR_BCNDERR5_88E BIT18 /* Beacon DMA Error Int 5 */
-#define IMR_BCNDERR4_88E BIT17 /* Beacon DMA Error Int 4 */
-#define IMR_BCNDERR3_88E BIT16 /* Beacon DMA Error Int 3 */
-#define IMR_BCNDERR2_88E BIT15 /* Beacon DMA Error Int 2 */
-#define IMR_BCNDERR1_88E BIT14 /* Beacon DMA Error Int 1 */
-#define IMR_ATIMEND_E_88E BIT13 /* ATIM Window End Ext for Win7 */
-#define IMR_TXERR_88E BIT11 /* Tx Err Flag Int Status, write 1 clear. */
-#define IMR_RXERR_88E BIT10 /* Rx Err Flag INT Status, Write 1 clear */
-#define IMR_TXFOVW_88E BIT9 /* Transmit FIFO Overflow */
-#define IMR_RXFOVW_88E BIT8 /* Receive FIFO Overflow */
+#define IMR_BCNDMAINT7_88E BIT(27) /* Beacon DMA Interrupt 7 */
+#define IMR_BCNDMAINT6_88E BIT(26) /* Beacon DMA Interrupt 6 */
+#define IMR_BCNDMAINT5_88E BIT(25) /* Beacon DMA Interrupt 5 */
+#define IMR_BCNDMAINT4_88E BIT(24) /* Beacon DMA Interrupt 4 */
+#define IMR_BCNDMAINT3_88E BIT(23) /* Beacon DMA Interrupt 3 */
+#define IMR_BCNDMAINT2_88E BIT(22) /* Beacon DMA Interrupt 2 */
+#define IMR_BCNDMAINT1_88E BIT(21) /* Beacon DMA Interrupt 1 */
+#define IMR_BCNDERR7_88E BIT(20) /* Beacon DMA Error Int 7 */
+#define IMR_BCNDERR6_88E BIT(19) /* Beacon DMA Error Int 6 */
+#define IMR_BCNDERR5_88E BIT(18) /* Beacon DMA Error Int 5 */
+#define IMR_BCNDERR4_88E BIT(17) /* Beacon DMA Error Int 4 */
+#define IMR_BCNDERR3_88E BIT(16) /* Beacon DMA Error Int 3 */
+#define IMR_BCNDERR2_88E BIT(15) /* Beacon DMA Error Int 2 */
+#define IMR_BCNDERR1_88E BIT(14) /* Beacon DMA Error Int 1 */
+#define IMR_ATIMEND_E_88E BIT(13) /* ATIM Window End Ext for Win7 */
+#define IMR_TXERR_88E BIT(11) /* Tx Err Flag Int Status, write 1 clear. */
+#define IMR_RXERR_88E BIT(10) /* Rx Err Flag INT Status, Write 1 clear */
+#define IMR_TXFOVW_88E BIT(9) /* Transmit FIFO Overflow */
+#define IMR_RXFOVW_88E BIT(8) /* Receive FIFO Overflow */
#define HAL_NIC_UNPLUG_ISR 0xFFFFFFFF /* The value when the NIC is unplugged for PCI. */
@@ -692,40 +659,40 @@ Current IOREG MAP
/* the correct arragement is VO - Bit0, VI - Bit1, BE - Bit2,
* and BK - Bit3. */
/* 8723 and 88E may be not correct either in the earlier version. */
-#define StopBecon BIT6
-#define StopHigh BIT5
-#define StopMgt BIT4
-#define StopBK BIT3
-#define StopBE BIT2
-#define StopVI BIT1
-#define StopVO BIT0
+#define StopBecon BIT(6)
+#define StopHigh BIT(5)
+#define StopMgt BIT(4)
+#define StopBK BIT(3)
+#define StopBE BIT(2)
+#define StopVI BIT(1)
+#define StopVO BIT(0)
/* 8192C (RCR) Receive Configuration Register(Offset 0x608, 32 bits) */
-#define RCR_APPFCS BIT31 /* WMAC append FCS after payload */
-#define RCR_APP_MIC BIT30
-#define RCR_APP_PHYSTS BIT28
-#define RCR_APP_ICV BIT29
-#define RCR_APP_PHYST_RXFF BIT28
-#define RCR_APP_BA_SSN BIT27 /* Accept BA SSN */
-#define RCR_ENMBID BIT24 /* Enable Multiple BssId. */
-#define RCR_LSIGEN BIT23
-#define RCR_MFBEN BIT22
-#define RCR_HTC_LOC_CTRL BIT14 /* MFC<--HTC=1 MFC-->HTC=0 */
-#define RCR_AMF BIT13 /* Accept management type frame */
-#define RCR_ACF BIT12 /* Accept control type frame */
-#define RCR_ADF BIT11 /* Accept data type frame */
-#define RCR_AICV BIT9 /* Accept ICV error packet */
-#define RCR_ACRC32 BIT8 /* Accept CRC32 error packet */
-#define RCR_CBSSID_BCN BIT7 /* Accept BSSID match packet
+#define RCR_APPFCS BIT(31) /* WMAC append FCS after payload */
+#define RCR_APP_MIC BIT(30)
+#define RCR_APP_PHYSTS BIT(28)
+#define RCR_APP_ICV BIT(29)
+#define RCR_APP_PHYST_RXFF BIT(28)
+#define RCR_APP_BA_SSN BIT(27) /* Accept BA SSN */
+#define RCR_ENMBID BIT(24) /* Enable Multiple BssId. */
+#define RCR_LSIGEN BIT(23)
+#define RCR_MFBEN BIT(22)
+#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */
+#define RCR_AMF BIT(13) /* Accept management type frame */
+#define RCR_ACF BIT(12) /* Accept control type frame */
+#define RCR_ADF BIT(11) /* Accept data type frame */
+#define RCR_AICV BIT(9) /* Accept ICV error packet */
+#define RCR_ACRC32 BIT(8) /* Accept CRC32 error packet */
+#define RCR_CBSSID_BCN BIT(7) /* Accept BSSID match packet
* (Rx beacon, probe rsp) */
-#define RCR_CBSSID_DATA BIT6 /* Accept BSSID match (Data)*/
+#define RCR_CBSSID_DATA BIT(6) /* Accept BSSID match (Data)*/
#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match */
-#define RCR_APWRMGT BIT5 /* Accept power management pkt*/
-#define RCR_ADD3 BIT4 /* Accept address 3 match pkt */
-#define RCR_AB BIT3 /* Accept broadcast packet */
-#define RCR_AM BIT2 /* Accept multicast packet */
-#define RCR_APM BIT1 /* Accept physical match pkt */
-#define RCR_AAP BIT0 /* Accept all unicast packet */
+#define RCR_APWRMGT BIT(5) /* Accept power management pkt*/
+#define RCR_ADD3 BIT(4) /* Accept address 3 match pkt */
+#define RCR_AB BIT(3) /* Accept broadcast packet */
+#define RCR_AM BIT(2) /* Accept multicast packet */
+#define RCR_APM BIT(1) /* Accept physical match pkt */
+#define RCR_AAP BIT(0) /* Accept all unicast packet */
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
@@ -1193,56 +1160,56 @@ Current IOREG MAP
#define SDIO_HIMR_DISABLED 0
/* RTL8188E SDIO Host Interrupt Mask Register */
-#define SDIO_HIMR_RX_REQUEST_MSK BIT0
-#define SDIO_HIMR_AVAL_MSK BIT1
-#define SDIO_HIMR_TXERR_MSK BIT2
-#define SDIO_HIMR_RXERR_MSK BIT3
-#define SDIO_HIMR_TXFOVW_MSK BIT4
-#define SDIO_HIMR_RXFOVW_MSK BIT5
-#define SDIO_HIMR_TXBCNOK_MSK BIT6
-#define SDIO_HIMR_TXBCNERR_MSK BIT7
-#define SDIO_HIMR_BCNERLY_INT_MSK BIT16
-#define SDIO_HIMR_C2HCMD_MSK BIT17
-#define SDIO_HIMR_CPWM1_MSK BIT18
-#define SDIO_HIMR_CPWM2_MSK BIT19
-#define SDIO_HIMR_HSISR_IND_MSK BIT20
-#define SDIO_HIMR_GTINT3_IND_MSK BIT21
-#define SDIO_HIMR_GTINT4_IND_MSK BIT22
-#define SDIO_HIMR_PSTIMEOUT_MSK BIT23
-#define SDIO_HIMR_OCPINT_MSK BIT24
-#define SDIO_HIMR_ATIMEND_MSK BIT25
-#define SDIO_HIMR_ATIMEND_E_MSK BIT26
-#define SDIO_HIMR_CTWEND_MSK BIT27
+#define SDIO_HIMR_RX_REQUEST_MSK BIT(0)
+#define SDIO_HIMR_AVAL_MSK BIT(1)
+#define SDIO_HIMR_TXERR_MSK BIT(2)
+#define SDIO_HIMR_RXERR_MSK BIT(3)
+#define SDIO_HIMR_TXFOVW_MSK BIT(4)
+#define SDIO_HIMR_RXFOVW_MSK BIT(5)
+#define SDIO_HIMR_TXBCNOK_MSK BIT(6)
+#define SDIO_HIMR_TXBCNERR_MSK BIT(7)
+#define SDIO_HIMR_BCNERLY_INT_MSK BIT(16)
+#define SDIO_HIMR_C2HCMD_MSK BIT(17)
+#define SDIO_HIMR_CPWM1_MSK BIT(18)
+#define SDIO_HIMR_CPWM2_MSK BIT(19)
+#define SDIO_HIMR_HSISR_IND_MSK BIT(20)
+#define SDIO_HIMR_GTINT3_IND_MSK BIT(21)
+#define SDIO_HIMR_GTINT4_IND_MSK BIT(22)
+#define SDIO_HIMR_PSTIMEOUT_MSK BIT(23)
+#define SDIO_HIMR_OCPINT_MSK BIT(24)
+#define SDIO_HIMR_ATIMEND_MSK BIT(25)
+#define SDIO_HIMR_ATIMEND_E_MSK BIT(26)
+#define SDIO_HIMR_CTWEND_MSK BIT(27)
/* RTL8188E SDIO Specific */
-#define SDIO_HIMR_MCU_ERR_MSK BIT28
-#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT29
+#define SDIO_HIMR_MCU_ERR_MSK BIT(28)
+#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT(29)
/* SDIO Host Interrupt Service Routine */
-#define SDIO_HISR_RX_REQUEST BIT0
-#define SDIO_HISR_AVAL BIT1
-#define SDIO_HISR_TXERR BIT2
-#define SDIO_HISR_RXERR BIT3
-#define SDIO_HISR_TXFOVW BIT4
-#define SDIO_HISR_RXFOVW BIT5
-#define SDIO_HISR_TXBCNOK BIT6
-#define SDIO_HISR_TXBCNERR BIT7
-#define SDIO_HISR_BCNERLY_INT BIT16
-#define SDIO_HISR_C2HCMD BIT17
-#define SDIO_HISR_CPWM1 BIT18
-#define SDIO_HISR_CPWM2 BIT19
-#define SDIO_HISR_HSISR_IND BIT20
-#define SDIO_HISR_GTINT3_IND BIT21
-#define SDIO_HISR_GTINT4_IND BIT22
-#define SDIO_HISR_PSTIME BIT23
-#define SDIO_HISR_OCPINT BIT24
-#define SDIO_HISR_ATIMEND BIT25
-#define SDIO_HISR_ATIMEND_E BIT26
-#define SDIO_HISR_CTWEND BIT27
+#define SDIO_HISR_RX_REQUEST BIT(0)
+#define SDIO_HISR_AVAL BIT(1)
+#define SDIO_HISR_TXERR BIT(2)
+#define SDIO_HISR_RXERR BIT(3)
+#define SDIO_HISR_TXFOVW BIT(4)
+#define SDIO_HISR_RXFOVW BIT(5)
+#define SDIO_HISR_TXBCNOK BIT(6)
+#define SDIO_HISR_TXBCNERR BIT(7)
+#define SDIO_HISR_BCNERLY_INT BIT(16)
+#define SDIO_HISR_C2HCMD BIT(17)
+#define SDIO_HISR_CPWM1 BIT(18)
+#define SDIO_HISR_CPWM2 BIT(19)
+#define SDIO_HISR_HSISR_IND BIT(20)
+#define SDIO_HISR_GTINT3_IND BIT(21)
+#define SDIO_HISR_GTINT4_IND BIT(22)
+#define SDIO_HISR_PSTIME BIT(23)
+#define SDIO_HISR_OCPINT BIT(24)
+#define SDIO_HISR_ATIMEND BIT(25)
+#define SDIO_HISR_ATIMEND_E BIT(26)
+#define SDIO_HISR_CTWEND BIT(27)
/* RTL8188E SDIO Specific */
-#define SDIO_HISR_MCU_ERR BIT28
-#define SDIO_HISR_TSF_BIT32_TOGGLE BIT29
+#define SDIO_HISR_MCU_ERR BIT(28)
+#define SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
#define MASK_SDIO_HISR_CLEAR \
(SDIO_HISR_TXERR | SDIO_HISR_RXERR | SDIO_HISR_TXFOVW |\
@@ -1252,8 +1219,8 @@ Current IOREG MAP
SDIO_HISR_PSTIMEOUT | SDIO_HISR_OCPINT)
/* SDIO HCI Suspend Control Register */
-#define HCI_RESUME_PWR_RDY BIT1
-#define HCI_SUS_CTRL BIT0
+#define HCI_RESUME_PWR_RDY BIT(1)
+#define HCI_SUS_CTRL BIT(0)
/* SDIO Tx FIFO related */
/* The number of Tx FIFO free page */
@@ -1287,33 +1254,33 @@ Current IOREG MAP
/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
/* Enable GPIO[9] as WiFi HW PDn source */
-#define WL_HWPDN_EN BIT0
+#define WL_HWPDN_EN BIT(0)
/* WiFi HW PDn polarity control */
-#define WL_HWPDN_SL BIT1
+#define WL_HWPDN_SL BIT(1)
/* WiFi function enable */
-#define WL_FUNC_EN BIT2
+#define WL_FUNC_EN BIT(2)
/* Enable GPIO[9] as WiFi RF HW PDn source */
-#define WL_HWROF_EN BIT3
+#define WL_HWROF_EN BIT(3)
/* Enable GPIO[11] as BT HW PDn source */
-#define BT_HWPDN_EN BIT16
+#define BT_HWPDN_EN BIT(16)
/* BT HW PDn polarity control */
-#define BT_HWPDN_SL BIT17
+#define BT_HWPDN_SL BIT(17)
/* BT function enable */
-#define BT_FUNC_EN BIT18
+#define BT_FUNC_EN BIT(18)
/* Enable GPIO[11] as BT/GPS RF HW PDn source */
-#define BT_HWROF_EN BIT19
+#define BT_HWROF_EN BIT(19)
/* Enable GPIO[10] as GPS HW PDn source */
-#define GPS_HWPDN_EN BIT20
+#define GPS_HWPDN_EN BIT(20)
/* GPS HW PDn polarity control */
-#define GPS_HWPDN_SL BIT21
+#define GPS_HWPDN_SL BIT(21)
/* GPS function enable */
-#define GPS_FUNC_EN BIT22
+#define GPS_FUNC_EN BIT(22)
/* 3 REG_LIFECTRL_CTRL */
-#define HAL92C_EN_PKT_LIFE_TIME_BK BIT3
-#define HAL92C_EN_PKT_LIFE_TIME_BE BIT2
-#define HAL92C_EN_PKT_LIFE_TIME_VI BIT1
-#define HAL92C_EN_PKT_LIFE_TIME_VO BIT0
+#define HAL92C_EN_PKT_LIFE_TIME_BK BIT(3)
+#define HAL92C_EN_PKT_LIFE_TIME_BE BIT(2)
+#define HAL92C_EN_PKT_LIFE_TIME_VI BIT(1)
+#define HAL92C_EN_PKT_LIFE_TIME_VO BIT(0)
#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us */
@@ -1323,7 +1290,7 @@ Current IOREG MAP
#define POLLING_LLT_THRESHOLD 20
#define POLLING_READY_TIMEOUT_COUNT 1000
/* GPIO BIT */
-#define HAL_8192C_HW_GPIO_WPS_BIT BIT2
+#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2)
/* 8192C EEPROM/EFUSE share register definition. */
diff --git a/drivers/staging/rtl8188eu/include/rtw_security.h b/drivers/staging/rtl8188eu/include/rtw_security.h
index abe7e21e6e20..a1aebe6c8452 100644
--- a/drivers/staging/rtl8188eu/include/rtw_security.h
+++ b/drivers/staging/rtl8188eu/include/rtw_security.h
@@ -336,9 +336,6 @@ static const unsigned long K[64] = {
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-#ifndef MIN
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#endif
void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key);
void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b);
diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h
index 580e850511a7..3a62ed010875 100644
--- a/drivers/staging/rtl8188eu/include/rtw_sreset.h
+++ b/drivers/staging/rtl8188eu/include/rtw_sreset.h
@@ -30,13 +30,13 @@ struct sreset_priv {
#include <rtl8188e_hal.h>
#define WIFI_STATUS_SUCCESS 0
-#define USB_VEN_REQ_CMD_FAIL BIT0
-#define USB_READ_PORT_FAIL BIT1
-#define USB_WRITE_PORT_FAIL BIT2
-#define WIFI_MAC_TXDMA_ERROR BIT3
-#define WIFI_TX_HANG BIT4
-#define WIFI_RX_HANG BIT5
-#define WIFI_IF_NOT_EXIST BIT6
+#define USB_VEN_REQ_CMD_FAIL BIT(0)
+#define USB_READ_PORT_FAIL BIT(1)
+#define USB_WRITE_PORT_FAIL BIT(2)
+#define WIFI_MAC_TXDMA_ERROR BIT(3)
+#define WIFI_TX_HANG BIT(4)
+#define WIFI_RX_HANG BIT(5)
+#define WIFI_IF_NOT_EXIST BIT(6)
void sreset_init_value(struct adapter *padapter);
u8 sreset_get_wifi_status(struct adapter *padapter);
diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h
index 62f5db169523..b7c20883d355 100644
--- a/drivers/staging/rtl8188eu/include/rtw_xmit.h
+++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h
@@ -197,7 +197,6 @@ enum {
void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms);
int rtw_sctx_wait(struct submit_ctx *sctx);
void rtw_sctx_done_err(struct submit_ctx **sctx, int status);
-void rtw_sctx_done(struct submit_ctx **sctx);
struct xmit_buf {
struct list_head list;
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 969574926e21..a076ede50b22 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -457,7 +457,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
if (param->u.crypt.set_tx == 1) { /* pairwise key */
- memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
@@ -469,7 +469,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
} else { /* group key */
- memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16 ));
memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
padapter->securitypriv.binstallGrpkey = true;
@@ -604,7 +604,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie
if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
DBG_88E("SET WPS_IE\n");
- padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2) : (MAX_WPA_IE_LEN<<2);
+ padapter->securitypriv.wps_ie_len = min(buf[cnt + 1] + 2, MAX_WPA_IE_LEN << 2);
memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
@@ -1321,7 +1321,7 @@ static int rtw_wx_set_essid(struct net_device *dev,
authmode = padapter->securitypriv.ndisauthtype;
DBG_88E("=>%s\n", __func__);
if (wrqu->essid.flags && wrqu->essid.length) {
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
+ len = min_t(uint, wrqu->essid.length, IW_ESSID_MAX_SIZE);
if (wrqu->essid.length != 33)
DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
@@ -2335,7 +2335,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
DBG_88E("%s, set group_key, WEP\n", __func__);
memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
if (param->u.crypt.key_len == 13)
@@ -2344,7 +2344,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
DBG_88E("%s, set group_key, TKIP\n", __func__);
psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
/* set mic key */
memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
@@ -2354,7 +2354,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
DBG_88E("%s, set group_key, CCMP\n", __func__);
psecuritypriv->dot118021XGrpPrivacy = _AES_;
memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
} else {
DBG_88E("%s, set group_key, none\n", __func__);
psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
@@ -2375,7 +2375,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
if (param->u.crypt.set_tx == 1) {
- memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
if (strcmp(param->u.crypt.alg, "WEP") == 0) {
DBG_88E("%s, set pairwise key, WEP\n", __func__);
@@ -2409,7 +2409,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
} else { /* group key??? */
if (strcmp(param->u.crypt.alg, "WEP") == 0) {
memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
if (param->u.crypt.key_len == 13)
psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
@@ -2417,7 +2417,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
/* set mic key */
memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
@@ -2428,7 +2428,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
psecuritypriv->dot118021XGrpPrivacy = _AES_;
memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
} else {
psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
}
@@ -2669,7 +2669,7 @@ static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
int copy_len;
wpa_ie_len = psta->wpa_ie[1];
- copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2);
+ copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
param->u.wpa_ie.len = copy_len;
memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
} else {
@@ -2974,7 +2974,7 @@ static int rtw_wx_set_priv(struct net_device *dev,
if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
(!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
- cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
+ cp_sz = min(probereq_wpsie_len, MAX_WPS_IE_LEN);
pmlmepriv->wps_probe_req_ie_len = 0;
kfree(pmlmepriv->wps_probe_req_ie);
@@ -3091,7 +3091,7 @@ static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
struct iw_handler_def rtw_handlers_def = {
.standard = rtw_handlers,
- .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
+ .num_standard = ARRAY_SIZE(rtw_handlers),
.get_wireless_stats = rtw_get_wireless_stats,
};
diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
index eb8ecb7fbd16..08bfa76f4975 100644
--- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
@@ -116,14 +116,13 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
p = buff;
p += sprintf(p, "ASSOCINFO(ReqIEs =");
len = sec_ie[1]+2;
- len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
+ 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 = (wrqu.data.length < IW_CUSTOM_MAX) ?
- wrqu.data.length : IW_CUSTOM_MAX;
+ wrqu.data.length = min_t(__u16, wrqu.data.length, IW_CUSTOM_MAX);
wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
kfree(buff);
}
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index d063d02db7f0..9201b94d017c 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -1100,7 +1100,7 @@ netdev_open_error:
int rtw_ips_pwr_up(struct adapter *padapter)
{
int result;
- u32 start_time = jiffies;
+ unsigned long start_time = jiffies;
DBG_88E("===> rtw_ips_pwr_up..............\n");
rtw_reset_drv_sw(padapter);
@@ -1109,13 +1109,14 @@ int rtw_ips_pwr_up(struct adapter *padapter)
rtw_led_control(padapter, LED_CTL_NO_LINK);
- DBG_88E("<=== rtw_ips_pwr_up.............. in %dms\n", rtw_get_passing_time_ms(start_time));
+ DBG_88E("<=== rtw_ips_pwr_up.............. in %dms\n",
+ jiffies_to_msecs(jiffies - start_time));
return result;
}
void rtw_ips_pwr_down(struct adapter *padapter)
{
- u32 start_time = jiffies;
+ unsigned long start_time = jiffies;
DBG_88E("===> rtw_ips_pwr_down...................\n");
@@ -1124,7 +1125,8 @@ void rtw_ips_pwr_down(struct adapter *padapter)
rtw_led_control(padapter, LED_CTL_POWER_OFF);
rtw_ips_dev_unload(padapter);
- DBG_88E("<=== rtw_ips_pwr_down..................... in %dms\n", rtw_get_passing_time_ms(start_time));
+ DBG_88E("<=== rtw_ips_pwr_down..................... in %dms\n",
+ jiffies_to_msecs(jiffies - start_time));
}
void rtw_ips_dev_unload(struct adapter *padapter)
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
index 466cd76fc1c4..d87b54711c0d 100644
--- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
@@ -77,12 +77,6 @@ void _rtw_init_queue(struct __queue *pqueue)
spin_lock_init(&(pqueue->lock));
}
-/* the input parameter start must be in jiffies */
-inline s32 rtw_get_passing_time_ms(u32 start)
-{
- return jiffies_to_msecs(jiffies-start);
-}
-
struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
void *old_priv)
{
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 82a7c27c517f..01d50f7c1667 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -227,7 +227,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
struct net_device *pnetdev = padapter->pnetdev;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- u32 start_time = jiffies;
+ unsigned long start_time = jiffies;
pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
@@ -282,7 +282,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
exit:
pr_debug("<=== %s .............. in %dms\n", __func__,
- rtw_get_passing_time_ms(start_time));
+ jiffies_to_msecs(jiffies - start_time));
return 0;
}
@@ -292,7 +292,7 @@ static int rtw_resume_process(struct adapter *padapter)
struct net_device *pnetdev;
struct pwrctrl_priv *pwrpriv = NULL;
int ret = -1;
- u32 start_time = jiffies;
+ unsigned long start_time = jiffies;
pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
@@ -323,7 +323,7 @@ exit:
if (pwrpriv)
pwrpriv->bInSuspend = false;
pr_debug("<=== %s return %d.............. in %dms\n", __func__,
- ret, rtw_get_passing_time_ms(start_time));
+ ret, jiffies_to_msecs(jiffies - start_time));
return ret;
}
diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
index 5acf9a9dddeb..1593e280e060 100644
--- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
@@ -52,7 +52,7 @@ uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
len = rtw_remainder_len(pfile);
- len = (rlen > len) ? len : rlen;
+ len = min(rlen, len);
if (rmem)
skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len, rmem, len);
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
index 6f5839f43c5c..f9003a28cae2 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
@@ -17,15 +17,13 @@
#include "r8192E_hw.h"
#include "r8192E_cmdpkt.h"
-bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *code_virtual_address,
- u32 packettype, u32 buffer_len)
+bool rtl92e_send_cmd_pkt(struct net_device *dev, u32 type, const void *data,
+ u32 len)
{
bool rt_status = true;
struct r8192_priv *priv = rtllib_priv(dev);
- u16 frag_threshold;
u16 frag_length = 0, frag_offset = 0;
- struct rt_firmware *pfirmware = priv->pFirmware;
struct sk_buff *skb;
unsigned char *seg_ptr;
struct cb_desc *tcb_desc;
@@ -33,22 +31,23 @@ bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *code_virtual_address,
struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
- RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len);
- rtl92e_init_fw_param(dev);
- frag_threshold = pfirmware->cmdpacket_frag_thresold;
+ RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, len);
do {
- if ((buffer_len - frag_offset) > frag_threshold) {
- frag_length = frag_threshold;
+ if ((len - frag_offset) > CMDPACKET_FRAG_SIZE) {
+ frag_length = CMDPACKET_FRAG_SIZE;
bLastIniPkt = 0;
} else {
- frag_length = (u16)(buffer_len - frag_offset);
+ frag_length = (u16)(len - frag_offset);
bLastIniPkt = 1;
}
- skb = dev_alloc_skb(frag_length +
- priv->rtllib->tx_headroom + 4);
+ if (type == DESC_PACKET_TYPE_NORMAL)
+ skb = dev_alloc_skb(frag_length +
+ priv->rtllib->tx_headroom + 4);
+ else
+ skb = dev_alloc_skb(frag_length + 4);
if (skb == NULL) {
rt_status = false;
@@ -58,24 +57,37 @@ bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *code_virtual_address,
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
- tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
+ tcb_desc->bCmdOrInit = type;
tcb_desc->bLastIniPkt = bLastIniPkt;
- tcb_desc->pkt_size = frag_length;
- seg_ptr = skb_put(skb, priv->rtllib->tx_headroom);
- pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr;
- memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci));
- memset(pTxFwInfo, 0x12, 8);
+ if (type == DESC_PACKET_TYPE_NORMAL) {
+ tcb_desc->pkt_size = frag_length;
- seg_ptr = skb_put(skb, frag_length);
- memcpy(seg_ptr, code_virtual_address, (u32)frag_length);
+ seg_ptr = skb_put(skb, priv->rtllib->tx_headroom);
+ pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr;
+ memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci));
+ memset(pTxFwInfo, 0x12, 8);
+ } else {
+ tcb_desc->txbuf_size = (u16)frag_length;
+ }
- priv->rtllib->softmac_hard_start_xmit(skb, dev);
+ seg_ptr = skb_put(skb, frag_length);
+ memcpy(seg_ptr, data, (u32)frag_length);
+
+ if (type == DESC_PACKET_TYPE_INIT &&
+ (!priv->rtllib->check_nic_enough_desc(dev, TXCMD_QUEUE) ||
+ (!skb_queue_empty(&priv->rtllib->skb_waitQ[TXCMD_QUEUE])) ||
+ (priv->rtllib->queue_stop))) {
+ skb_queue_tail(&priv->rtllib->skb_waitQ[TXCMD_QUEUE],
+ skb);
+ } else {
+ priv->rtllib->softmac_hard_start_xmit(skb, dev);
+ }
- code_virtual_address += frag_length;
+ data += frag_length;
frag_offset += frag_length;
- } while (frag_offset < buffer_len);
+ } while (frag_offset < len);
rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
Failed:
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
index 31303a14c7fb..7dd15d993481 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
@@ -15,6 +15,6 @@
#ifndef R819XUSB_CMDPKT_H
#define R819XUSB_CMDPKT_H
-bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *codevirtualaddress,
- u32 packettype, u32 buffer_len);
+bool rtl92e_send_cmd_pkt(struct net_device *dev, u32 type, const void *data,
+ u32 len);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index dad63c210303..e9c4f973bba9 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -719,19 +719,19 @@ start:
rtl92e_writeb(dev, ANAPAR, 0x37);
mdelay(500);
}
- priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
+ priv->pFirmware->status = FW_STATUS_0_INIT;
if (priv->RegRfOff)
priv->rtllib->eRFPowerState = eRfOff;
ulRegRead = rtl92e_readl(dev, CPU_GEN);
- if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
+ if (priv->pFirmware->status == FW_STATUS_0_INIT)
ulRegRead |= CPU_GEN_SYSTEM_RESET;
- else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
+ else if (priv->pFirmware->status == FW_STATUS_5_READY)
ulRegRead |= CPU_GEN_FIRMWARE_RESET;
else
netdev_err(dev, "%s(): undefined firmware state: %d.\n",
- __func__, priv->pFirmware->firmware_status);
+ __func__, priv->pFirmware->status);
rtl92e_writel(dev, CPU_GEN, ulRegRead);
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
index dab67c12ccc2..9aaa85526eb8 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
@@ -17,160 +17,44 @@
#include "r8192E_hw.h"
#include "r8192E_hwimg.h"
#include "r8192E_firmware.h"
+#include "r8192E_cmdpkt.h"
#include <linux/firmware.h>
-void rtl92e_init_fw_param(struct net_device *dev)
+static bool _rtl92e_wait_for_fw(struct net_device *dev, u32 mask, u32 timeout)
{
- struct r8192_priv *priv = rtllib_priv(dev);
- struct rt_firmware *pfirmware = priv->pFirmware;
-
- pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(
- MAX_TRANSMIT_BUFFER_SIZE);
-}
-
-static bool _rtl92e_fw_download_code(struct net_device *dev,
- u8 *code_virtual_address, u32 buffer_len)
-{
- struct r8192_priv *priv = rtllib_priv(dev);
- u16 frag_threshold;
- u16 frag_length, frag_offset = 0;
- int i;
-
- struct rt_firmware *pfirmware = priv->pFirmware;
- struct sk_buff *skb;
- unsigned char *seg_ptr;
- struct cb_desc *tcb_desc;
- u8 bLastIniPkt;
-
- rtl92e_init_fw_param(dev);
- frag_threshold = pfirmware->cmdpacket_frag_thresold;
- do {
- if ((buffer_len - frag_offset) > frag_threshold) {
- frag_length = frag_threshold;
- bLastIniPkt = 0;
-
- } else {
- frag_length = buffer_len - frag_offset;
- bLastIniPkt = 1;
-
- }
-
- skb = dev_alloc_skb(frag_length + 4);
- memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
- tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
- tcb_desc->queue_index = TXCMD_QUEUE;
- tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
- tcb_desc->bLastIniPkt = bLastIniPkt;
-
- seg_ptr = skb->data;
- for (i = 0; i < frag_length; i += 4) {
- *seg_ptr++ = ((i+0) < frag_length) ?
- code_virtual_address[i+3] : 0;
- *seg_ptr++ = ((i+1) < frag_length) ?
- code_virtual_address[i+2] : 0;
- *seg_ptr++ = ((i+2) < frag_length) ?
- code_virtual_address[i+1] : 0;
- *seg_ptr++ = ((i+3) < frag_length) ?
- code_virtual_address[i+0] : 0;
- }
- tcb_desc->txbuf_size = (u16)i;
- skb_put(skb, i);
-
- if (!priv->rtllib->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
- (!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index])) ||
- (priv->rtllib->queue_stop)) {
- RT_TRACE(COMP_FIRMWARE,
- "===================> tx full!\n");
- skb_queue_tail(&priv->rtllib->skb_waitQ
- [tcb_desc->queue_index], skb);
- } else {
- priv->rtllib->softmac_hard_start_xmit(skb, dev);
- }
-
- code_virtual_address += frag_length;
- frag_offset += frag_length;
-
- } while (frag_offset < buffer_len);
-
- rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
+ unsigned long deadline = jiffies + msecs_to_jiffies(timeout);
- return true;
+ while (time_before(jiffies, deadline)) {
+ if (rtl92e_readl(dev, CPU_GEN) & mask)
+ return true;
+ mdelay(2);
+ }
+ return false;
}
static bool _rtl92e_fw_boot_cpu(struct net_device *dev)
{
- bool rt_status = true;
u32 CPU_status = 0;
- unsigned long timeout;
- timeout = jiffies + msecs_to_jiffies(200);
- while (time_before(jiffies, timeout)) {
- CPU_status = rtl92e_readl(dev, CPU_GEN);
- if (CPU_status & CPU_GEN_PUT_CODE_OK)
- break;
- mdelay(2);
- }
-
- if (!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
+ if (!_rtl92e_wait_for_fw(dev, CPU_GEN_PUT_CODE_OK, 200)) {
netdev_err(dev, "Firmware download failed.\n");
- goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
- } else {
- RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
+ return false;
}
+ netdev_dbg(dev, "Download Firmware: Put code ok!\n");
CPU_status = rtl92e_readl(dev, CPU_GEN);
rtl92e_writeb(dev, CPU_GEN,
(u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
mdelay(1);
- timeout = jiffies + msecs_to_jiffies(200);
- while (time_before(jiffies, timeout)) {
- CPU_status = rtl92e_readl(dev, CPU_GEN);
- if (CPU_status&CPU_GEN_BOOT_RDY)
- break;
- mdelay(2);
- }
-
- if (!(CPU_status&CPU_GEN_BOOT_RDY)) {
+ if (!_rtl92e_wait_for_fw(dev, CPU_GEN_BOOT_RDY, 200)) {
netdev_err(dev, "Firmware boot failed.\n");
- goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
- }
-
- RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
-
- return rt_status;
-
-CPUCheckMainCodeOKAndTurnOnCPU_Fail:
- rt_status = false;
- return rt_status;
-}
-
-static bool _rtl92e_is_fw_ready(struct net_device *dev)
-{
-
- bool rt_status = true;
- u32 CPU_status = 0;
- unsigned long timeout;
-
- timeout = jiffies + msecs_to_jiffies(20);
- while (time_before(jiffies, timeout)) {
- CPU_status = rtl92e_readl(dev, CPU_GEN);
- if (CPU_status&CPU_GEN_FIRM_RDY)
- break;
- mdelay(2);
+ return false;
}
- if (!(CPU_status&CPU_GEN_FIRM_RDY))
- goto CPUCheckFirmwareReady_Fail;
- else
- RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
-
- return rt_status;
-
-CPUCheckFirmwareReady_Fail:
- rt_status = false;
- return rt_status;
+ netdev_dbg(dev, "Download Firmware: Boot ready!\n");
+ return true;
}
static bool _rtl92e_fw_check_ready(struct net_device *dev,
@@ -182,42 +66,77 @@ static bool _rtl92e_fw_check_ready(struct net_device *dev,
switch (load_fw_status) {
case FW_INIT_STEP0_BOOT:
- pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
+ pfirmware->status = FW_STATUS_1_MOVE_BOOT_CODE;
break;
case FW_INIT_STEP1_MAIN:
- pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
+ pfirmware->status = FW_STATUS_2_MOVE_MAIN_CODE;
rt_status = _rtl92e_fw_boot_cpu(dev);
if (rt_status)
- pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
+ pfirmware->status = FW_STATUS_3_TURNON_CPU;
else
- RT_TRACE(COMP_FIRMWARE, "_rtl92e_fw_boot_cpu fail!\n");
+ netdev_dbg(dev, "_rtl92e_fw_boot_cpu fail!\n");
break;
case FW_INIT_STEP2_DATA:
- pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
+ pfirmware->status = FW_STATUS_4_MOVE_DATA_CODE;
mdelay(1);
- rt_status = _rtl92e_is_fw_ready(dev);
+ rt_status = _rtl92e_wait_for_fw(dev, CPU_GEN_FIRM_RDY, 20);
if (rt_status)
- pfirmware->firmware_status = FW_STATUS_5_READY;
+ pfirmware->status = FW_STATUS_5_READY;
else
RT_TRACE(COMP_FIRMWARE,
"_rtl92e_is_fw_ready fail(%d)!\n",
rt_status);
-
break;
default:
rt_status = false;
- RT_TRACE(COMP_FIRMWARE, "Unknown firmware status");
+ netdev_dbg(dev, "Unknown firmware status");
break;
}
return rt_status;
}
+static bool _rtl92e_fw_prepare(struct net_device *dev, struct rt_fw_blob *blob,
+ const char *name, u8 padding)
+{
+ const struct firmware *fw;
+ int rc, i;
+ bool ret = true;
+
+ rc = request_firmware(&fw, name, &dev->dev);
+ if (rc < 0)
+ return false;
+
+ if (round_up(fw->size, 4) > MAX_FW_SIZE - padding) {
+ netdev_err(dev, "Firmware image %s too big for the device.\n",
+ name);
+ ret = false;
+ goto out;
+ }
+
+ if (padding)
+ memset(blob->data, 0, padding);
+ if (fw->size % 4)
+ memset(blob->data + padding + fw->size, 0, 4);
+ memcpy(blob->data + padding, fw->data, fw->size);
+
+ blob->size = round_up(fw->size, 4) + padding;
+
+ /* Swap endian - firmware is packaged in invalid endiannes*/
+ for (i = padding; i < blob->size; i += 4) {
+ u32 *data = (u32 *)(blob->data + i);
+ *data = swab32p(data);
+ }
+out:
+ release_firmware(fw);
+ return ret;
+}
+
bool rtl92e_init_fw(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -231,13 +150,13 @@ bool rtl92e_init_fw(struct net_device *dev)
struct rt_firmware *pfirmware = priv->pFirmware;
- RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
+ netdev_dbg(dev, " PlatformInitFirmware()==>\n");
- if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
+ if (pfirmware->status == FW_STATUS_0_INIT) {
rst_opt = OPT_SYSTEM_RESET;
starting_state = FW_INIT_STEP0_BOOT;
- } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
+ } else if (pfirmware->status == FW_STATUS_5_READY) {
rst_opt = OPT_FIRMWARE_RESET;
starting_state = FW_INIT_STEP2_DATA;
} else {
@@ -247,56 +166,30 @@ bool rtl92e_init_fw(struct net_device *dev)
for (i = starting_state; i <= FW_INIT_STEP2_DATA; i++) {
if (rst_opt == OPT_SYSTEM_RESET) {
- if (pfirmware->firmware_buf_size[i] == 0) {
+ if (pfirmware->blobs[i].size == 0) {
const char *fw_name[3] = {
RTL8192E_BOOT_IMG_FW,
RTL8192E_MAIN_IMG_FW,
RTL8192E_DATA_IMG_FW
};
- const struct firmware *fw_entry;
- int rc;
-
- rc = request_firmware(&fw_entry,
- fw_name[i],
- &priv->pdev->dev);
- if (rc < 0) {
- RT_TRACE(COMP_FIRMWARE,
- "request firmware fail!\n");
- goto download_firmware_fail;
- }
- if (fw_entry->size >
- sizeof(pfirmware->firmware_buf[i])) {
- RT_TRACE(COMP_FIRMWARE,
- "img file size exceed the container struct buffer fail!\n");
- release_firmware(fw_entry);
+ int pad = 0;
+
+ if (i == FW_INIT_STEP1_MAIN)
+ pad = 128;
+
+ if (!_rtl92e_fw_prepare(dev,
+ &pfirmware->blobs[i],
+ fw_name[i],
+ pad))
goto download_firmware_fail;
- }
-
- if (i != FW_INIT_STEP1_MAIN) {
- memcpy(pfirmware->firmware_buf[i],
- fw_entry->data, fw_entry->size);
- pfirmware->firmware_buf_size[i] =
- fw_entry->size;
-
- } else {
- memset(pfirmware->firmware_buf[i],
- 0, 128);
- memcpy(&pfirmware->firmware_buf[i][128],
- fw_entry->data, fw_entry->size);
- pfirmware->firmware_buf_size[i] =
- fw_entry->size + 128;
- }
-
- if (rst_opt == OPT_SYSTEM_RESET)
- release_firmware(fw_entry);
}
}
- mapped_file = pfirmware->firmware_buf[i];
- file_length = pfirmware->firmware_buf_size[i];
+ mapped_file = pfirmware->blobs[i].data;
+ file_length = pfirmware->blobs[i].size;
- rt_status = _rtl92e_fw_download_code(dev, mapped_file,
- file_length);
+ rt_status = rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_INIT,
+ mapped_file, file_length);
if (!rt_status)
goto download_firmware_fail;
@@ -304,7 +197,7 @@ bool rtl92e_init_fw(struct net_device *dev)
goto download_firmware_fail;
}
- RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
+ netdev_dbg(dev, "Firmware Download Success\n");
return rt_status;
download_firmware_fail:
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
index 10aac8c17f5b..b48ec9410c09 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
@@ -15,8 +15,6 @@
#ifndef __INC_FIRMWARE_H
#define __INC_FIRMWARE_H
-#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8)
-
#define RTL8192E_BOOT_IMG_FW "RTL8192E/boot.img"
#define RTL8192E_MAIN_IMG_FW "RTL8192E/main.img"
#define RTL8192E_DATA_IMG_FW "RTL8192E/data.img"
@@ -46,16 +44,17 @@ enum firmware_status {
FW_STATUS_5_READY = 5,
};
+#define MAX_FW_SIZE 64000
+struct rt_fw_blob {
+ u16 size;
+ u8 data[MAX_FW_SIZE];
+};
+
+#define FW_BLOBS 3
struct rt_firmware {
- enum firmware_status firmware_status;
- u16 cmdpacket_frag_thresold;
-#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000
-#define MAX_FW_INIT_STEP 3
- u8 firmware_buf[MAX_FW_INIT_STEP][RTL8190_MAX_FIRMWARE_CODE_SIZE];
- u16 firmware_buf_size[MAX_FW_INIT_STEP];
+ enum firmware_status status;
+ struct rt_fw_blob blobs[FW_BLOBS];
};
bool rtl92e_init_fw(struct net_device *dev);
-void rtl92e_init_fw_param(struct net_device *dev);
-
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
index 0b407feb5407..5e3bbe5c3ca4 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -90,13 +90,12 @@ void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
{
- u32 Ret = 0, OriginalValue, BitShift;
+ u32 OriginalValue, BitShift;
OriginalValue = rtl92e_readl(dev, dwRegAddr);
BitShift = _rtl92e_calculate_bit_shift(dwBitMask);
- Ret = (OriginalValue & dwBitMask) >> BitShift;
- return Ret;
+ return (OriginalValue & dwBitMask) >> BitShift;
}
static u32 _rtl92e_phy_rf_read(struct net_device *dev,
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 2e3c25c37e36..8f989a95a019 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -2775,24 +2775,7 @@ bool rtl92e_disable_nic(struct net_device *dev)
return true;
}
-static int __init _rtl92e_pci_module_init(void)
-{
- pr_info("\nLinux kernel driver for RTL8192E WLAN cards\n");
- pr_info("Copyright (c) 2007-2008, Realsil Wlan Driver\n");
-
- if (0 != pci_register_driver(&rtl8192_pci_driver)) {
- /*pci_unregister_driver (&rtl8192_pci_driver);*/
- return -ENODEV;
- }
- return 0;
-}
-
-static void __exit _rtl92e_pci_module_exit(void)
-{
- pci_unregister_driver(&rtl8192_pci_driver);
-
- RT_TRACE(COMP_DOWN, "Exiting");
-}
+module_pci_driver(rtl8192_pci_driver);
void rtl92e_check_rfctrl_gpio_timer(unsigned long data)
{
@@ -2809,9 +2792,6 @@ void rtl92e_check_rfctrl_gpio_timer(unsigned long data)
/***************************************************************************
------------------- module init / exit stubs ----------------
****************************************************************************/
-module_init(_rtl92e_pci_module_init);
-module_exit(_rtl92e_pci_module_exit);
-
MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards");
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index 1ddf42a83fb4..a7777a319c02 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -91,6 +91,8 @@
(1600 + (MAX_802_11_HEADER_LENGTH + ENCRYPTION_MAX_OVERHEAD) * \
MAX_FRAGMENT_COUNT)
+#define CMDPACKET_FRAG_SIZE (4 * (MAX_TRANSMIT_BUFFER_SIZE / 4) - 8)
+
#define DEFAULT_FRAG_THRESHOLD 2342U
#define MIN_FRAG_THRESHOLD 256U
#define DEFAULT_BEACONINTERVAL 0x64U
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index efa57d814186..ef03242113be 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -655,7 +655,7 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev)
tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING;
tx_cmd.Length = 4;
tx_cmd.Value = Value;
- rtl92e_send_cmd_pkt(dev, (u8 *)&tx_cmd, DESC_PACKET_TYPE_INIT,
+ rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_NORMAL, (u8 *)&tx_cmd,
sizeof(struct dcmd_txcmd));
mdelay(1);
for (i = 0; i <= 30; i++) {
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index 1f80c52a49c4..908bc2eb4d29 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -185,8 +185,7 @@ static inline u16 Mk16_le(u16 *v)
}
-static const u16 Sbox[256] =
-{
+static const u16 Sbox[256] = {
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
@@ -257,8 +256,10 @@ static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
u16 IV16)
{
- /* Make temporary area overlap WEP seed so that the final copy can be
- * avoided on little endian hosts. */
+ /*
+ * Make temporary area overlap WEP seed so that the final copy can be
+ * avoided on little endian hosts.
+ */
u16 *PPK = (u16 *) &WEPSeed[4];
/* Step 1 - make copy of TTAK and bring in TSC */
@@ -284,8 +285,10 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
PPK[4] += RotR1(PPK[3]);
PPK[5] += RotR1(PPK[4]);
- /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
- * WEPSeed[0..2] is transmitted as WEP IV */
+ /*
+ * Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
+ * WEPSeed[0..2] is transmitted as WEP IV
+ */
WEPSeed[0] = Hi8(IV16);
WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
WEPSeed[2] = Lo8(IV16);
@@ -294,6 +297,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
#ifdef __BIG_ENDIAN
{
int i;
+
for (i = 0; i < 6; i++)
PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
}
@@ -304,7 +308,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
- int len;
+ int len;
u8 *pos;
struct rtl_80211_hdr_4addr *hdr;
cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
@@ -320,17 +324,15 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
hdr = (struct rtl_80211_hdr_4addr *) skb->data;
- if (!tcb_desc->bHwSec)
- {
+ if (!tcb_desc->bHwSec) {
if (!tkey->tx_phase1_done) {
tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
- tkey->tx_iv32);
+ tkey->tx_iv32);
tkey->tx_phase1_done = 1;
}
tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
- }
- else
- tkey->tx_phase1_done = 1;
+ } else
+ tkey->tx_phase1_done = 1;
len = skb->len - hdr_len;
@@ -338,14 +340,11 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
memmove(pos, pos + 8, hdr_len);
pos += hdr_len;
- if (tcb_desc->bHwSec)
- {
+ if (tcb_desc->bHwSec) {
*pos++ = Hi8(tkey->tx_iv16);
*pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
*pos++ = Lo8(tkey->tx_iv16);
- }
- else
- {
+ } else {
*pos++ = rc4key[0];
*pos++ = rc4key[1];
*pos++ = rc4key[2];
@@ -357,8 +356,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
*pos++ = (tkey->tx_iv32 >> 24) & 0xff;
- if (!tcb_desc->bHwSec)
- {
+ if (!tcb_desc->bHwSec) {
icv = skb_put(skb, 4);
crc = ~crc32_le(~0, pos, len);
icv[0] = crc;
@@ -367,7 +365,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
icv[3] = crc >> 24;
crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
sg_init_one(&sg, pos, len+4);
- ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
+ ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
}
tkey->tx_iv16++;
@@ -398,6 +396,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
u32 crc;
struct scatterlist sg;
int plen;
+
if (skb->len < hdr_len + 8 + 4)
return -1;
@@ -429,8 +428,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
pos += 8;
- if (!tcb_desc->bHwSec)
- {
+ if (!tcb_desc->bHwSec) {
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
@@ -471,8 +469,11 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(icv, pos + plen, 4) != 0) {
if (iv32 != tkey->rx_iv32) {
- /* Previously cached Phase1 result was already lost, so
- * it needs to be recalculated for the next packet. */
+ /*
+ * Previously cached Phase1 result was already
+ * lost, so it needs to be recalculated for the
+ * next packet.
+ */
tkey->rx_phase1_done = 0;
}
if (net_ratelimit()) {
@@ -485,8 +486,10 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
- /* Update real counters only after Michael MIC verification has
- * completed */
+ /*
+ * Update real counters only after Michael MIC verification has
+ * completed.
+ */
tkey->rx_iv32_new = iv32;
tkey->rx_iv16_new = iv16;
@@ -571,9 +574,8 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *pri
// { david, 2006.9.1
// fix the wpa process with wmm enabled.
- if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
+ if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
- }
// }
pos = skb_put(skb, 8);
@@ -606,7 +608,7 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
}
static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
- int hdr_len, void *priv)
+ int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
u8 mic[8];
@@ -620,17 +622,17 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
michael_mic_hdr(skb, tkey->rx_hdr);
// { david, 2006.9.1
// fix the wpa process with wmm enabled.
- if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
+ if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
- }
// }
if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
- skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
+ skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
return -1;
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
struct rtl_80211_hdr_4addr *hdr;
hdr = (struct rtl_80211_hdr_4addr *) skb->data;
+
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
"MSDU from %pM keyidx=%d\n",
skb->dev ? skb->dev->name : "N/A", hdr->addr2,
@@ -641,8 +643,10 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
return -1;
}
- /* Update TSC counters for RX now that the packet verification has
- * completed. */
+ /*
+ * Update TSC counters for RX now that the packet verification has
+ * completed.
+ */
tkey->rx_iv32 = tkey->rx_iv32_new;
tkey->rx_iv16 = tkey->rx_iv16_new;
@@ -702,6 +706,7 @@ static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
/* Return the sequence number of the last transmitted frame. */
u16 iv16 = tkey->tx_iv16;
u32 iv32 = tkey->tx_iv32;
+
if (iv16 == 0)
iv32--;
iv16--;
@@ -720,6 +725,7 @@ static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
static char *ieee80211_tkip_print_stats(char *p, void *priv)
{
struct ieee80211_tkip_data *tkip = priv;
+
p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
"tx_pn=%02x%02x%02x%02x%02x%02x "
"rx_pn=%02x%02x%02x%02x%02x%02x "
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index fcbd59f9d6e9..38c3eb78094e 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -417,7 +417,6 @@ static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
ieee80211_send_probe(ieee);
}
}
-EXPORT_SYMBOL(ieee80211_send_probe_requests);
/* this performs syncro scan blocking the caller until all channels
* in the allowed channel map has been checked.
@@ -466,13 +465,9 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
/* this prevent excessive time wait when we
* need to wait for a syncro scan to end..
*/
- if(ieee->state < IEEE80211_LINKED)
- ;
- else
- if (ieee->sync_scan_hurryup)
+ if (ieee->state >= IEEE80211_LINKED && ieee->sync_scan_hurryup)
goto out;
-
msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
}
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 678ecf6d2b79..f4a4eae72aa4 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -3516,7 +3516,7 @@ static void watch_dog_timer_callback(unsigned long data)
queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
mod_timer(&priv->watch_dog_timer,
- jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
+ jiffies + msecs_to_jiffies(IEEE80211_WATCH_DOG_TIME));
}
static int _rtl8192_up(struct net_device *dev)
{
@@ -5114,21 +5114,6 @@ static void __exit rtl8192_usb_module_exit(void)
RT_TRACE(COMP_DOWN, "Exiting");
}
-
-void rtl8192_try_wake_queue(struct net_device *dev, int pri)
-{
- unsigned long flags;
- short enough_desc;
- struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-
- spin_lock_irqsave(&priv->tx_lock, flags);
- enough_desc = check_nic_enough_desc(dev, pri);
- spin_unlock_irqrestore(&priv->tx_lock, flags);
-
- if (enough_desc)
- ieee80211_wake_queue(priv->ieee80211);
-}
-
void EnableHWSecurityConfig8192(struct net_device *dev)
{
u8 SECR_value = 0x0;
diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c
index 70656441c145..f264d88364a1 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.c
+++ b/drivers/staging/rtl8192u/r819xU_phy.c
@@ -38,21 +38,6 @@ static u32 RF_CHANNEL_TABLE_ZEBRA[] = {
#define rtl819XAGCTAB_Array Rtl8192UsbAGCTAB_Array
/******************************************************************************
- * function: This function reads BB parameters from header file we generate,
- * and does register read/write
- * input: u32 bitmask //taget bit pos in the addr to be modified
- * output: none
- * return: u32 return the shift bit position of the mask
- ******************************************************************************/
-static u32 rtl8192_CalculateBitShift(u32 bitmask)
-{
- u32 i;
-
- i = ffs(bitmask) - 1;
- return i;
-}
-
-/******************************************************************************
* function: This function checks different RF type to execute legal judgement.
* If RF Path is illegal, we will return false.
* input: net_device *dev
@@ -94,7 +79,7 @@ void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr, u32 bitmask,
if (bitmask != bMaskDWord) {
read_nic_dword(dev, reg_addr, &reg);
- bitshift = rtl8192_CalculateBitShift(bitmask);
+ bitshift = ffs(bitmask) - 1;
reg &= ~bitmask;
reg |= data << bitshift;
write_nic_dword(dev, reg_addr, reg);
@@ -117,7 +102,7 @@ u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr, u32 bitmask)
u32 reg, bitshift;
read_nic_dword(dev, reg_addr, &reg);
- bitshift = rtl8192_CalculateBitShift(bitmask);
+ bitshift = ffs(bitmask) - 1;
return (reg & bitmask) >> bitshift;
}
@@ -306,7 +291,7 @@ void rtl8192_phy_SetRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
if (bitmask != bMask12Bits) {
/* RF data is 12 bits only */
reg = phy_FwRFSerialRead(dev, eRFPath, reg_addr);
- bitshift = rtl8192_CalculateBitShift(bitmask);
+ bitshift = ffs(bitmask) - 1;
reg &= ~bitmask;
reg |= data << bitshift;
@@ -321,7 +306,7 @@ void rtl8192_phy_SetRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
if (bitmask != bMask12Bits) {
/* RF data is 12 bits only */
reg = rtl8192_phy_RFSerialRead(dev, eRFPath, reg_addr);
- bitshift = rtl8192_CalculateBitShift(bitmask);
+ bitshift = ffs(bitmask) - 1;
reg &= ~bitmask;
reg |= data << bitshift;
@@ -356,7 +341,7 @@ u32 rtl8192_phy_QueryRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
} else {
reg = rtl8192_phy_RFSerialRead(dev, eRFPath, reg_addr);
}
- bitshift = rtl8192_CalculateBitShift(bitmask);
+ bitshift = ffs(bitmask) - 1;
reg = (reg & bitmask) >> bitshift;
return reg;
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
index e0ae57d32fa1..8008efe5686d 100644
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -191,9 +191,9 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
imem_sz = fwhdr.img_IMEM_size;
do {
memset(ptx_desc, 0, TXDESC_SIZE);
- if (imem_sz > MAX_DUMP_FWSZ/*49152*/)
+ if (imem_sz > MAX_DUMP_FWSZ/*49152*/) {
dump_imem_sz = MAX_DUMP_FWSZ;
- else {
+ } else {
dump_imem_sz = imem_sz;
ptx_desc->txdw0 |= cpu_to_le32(BIT(28));
}
@@ -309,8 +309,9 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
}
if (i == 0)
goto exit_fail;
- } else
+ } else {
goto exit_fail;
+ }
ret = _SUCCESS;
exit_fail:
@@ -386,9 +387,9 @@ uint rtl871x_hal_init(struct _adapter *padapter)
return _FAIL;
if (padapter->halpriv.hal_bus_init(padapter) != _SUCCESS)
return _FAIL;
- if (rtl8712_hal_init(padapter) == _SUCCESS)
+ if (rtl8712_hal_init(padapter) == _SUCCESS) {
padapter->hw_init_completed = true;
- else {
+ } else {
padapter->hw_init_completed = false;
return _FAIL;
}
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
index 261a97304dfe..974ca021ccef 100644
--- a/drivers/staging/rtl8712/ieee80211.c
+++ b/drivers/staging/rtl8712/ieee80211.c
@@ -304,8 +304,9 @@ int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
*group_cipher = r8712_get_wpa_cipher_suite(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
- } else if (left > 0)
+ } else if (left > 0) {
return _FAIL;
+ }
/*pairwise_cipher*/
if (left >= 2) {
count = le16_to_cpu(*(u16 *)pos);
@@ -318,8 +319,9 @@ int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
- } else if (left == 1)
+ } else if (left == 1) {
return _FAIL;
+ }
return _SUCCESS;
}
@@ -334,7 +336,8 @@ int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
/* No RSN IE - fail silently */
return _FAIL;
}
- if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2)))
+ if ((*rsn_ie != _WPA2_IE_ID_) ||
+ (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
return _FAIL;
pos = rsn_ie;
pos += 4;
@@ -344,8 +347,9 @@ int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
*group_cipher = r8712_get_wpa2_cipher_suite(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
- } else if (left > 0)
+ } else if (left > 0) {
return _FAIL;
+ }
/*pairwise_cipher*/
if (left >= 2) {
count = le16_to_cpu(*(u16 *)pos);
@@ -358,8 +362,9 @@ int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
}
- } else if (left == 1)
+ } else if (left == 1) {
return _FAIL;
+ }
return _SUCCESS;
}
@@ -377,16 +382,17 @@ int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
if ((authmode == _WPA_IE_ID_) &&
(!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
- *wpa_len = in_ie[cnt+1]+2;
+ *wpa_len = in_ie[cnt + 1] + 2;
cnt += in_ie[cnt + 1] + 2; /*get next */
} else {
if (authmode == _WPA2_IE_ID_) {
memcpy(rsn_ie, &in_ie[cnt],
in_ie[cnt + 1] + 2);
- *rsn_len = in_ie[cnt+1] + 2;
- cnt += in_ie[cnt+1] + 2; /*get next*/
- } else
- cnt += in_ie[cnt+1] + 2; /*get next*/
+ *rsn_len = in_ie[cnt + 1] + 2;
+ cnt += in_ie[cnt + 1] + 2; /*get next*/
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /*get next*/
+ }
}
}
return *rsn_len + *wpa_len;
@@ -403,14 +409,14 @@ int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
while (cnt < in_len) {
eid = in_ie[cnt];
if ((eid == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt+2], wps_oui, 4))) {
- memcpy(wps_ie, &in_ie[cnt], in_ie[cnt+1]+2);
- *wps_ielen = in_ie[cnt+1]+2;
- cnt += in_ie[cnt+1]+2;
+ (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
+ memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+ *wps_ielen = in_ie[cnt + 1] + 2;
+ cnt += in_ie[cnt + 1] + 2;
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/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c
index 6d253bf6021e..e4e4bdee78be 100644
--- a/drivers/staging/rtl8712/mlme_linux.c
+++ b/drivers/staging/rtl8712/mlme_linux.c
@@ -163,7 +163,7 @@ void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie)
p += sprintf(p, "%02x", sec_ie[i]);
p += sprintf(p, ")");
memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = p-buff;
+ wrqu.data.length = p - buff;
wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
wrqu.data.length : IW_CUSTOM_MAX;
wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 6805f79ae00a..b89e2d3c4fe1 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -97,7 +97,7 @@ static char *initmac;
*/
static int wifi_test;
-module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR);
+module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO | S_IWUSR);
module_param(wifi_test, int, 0644);
module_param(initmac, charp, 0644);
module_param(video_mode, int, 0644);
@@ -177,7 +177,7 @@ static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
struct _adapter *padapter = netdev_priv(pnetdev);
struct sockaddr *addr = p;
- if (padapter->bup == false)
+ if (!padapter->bup)
ether_addr_copy(pnetdev->dev_addr, addr->sa_data);
return 0;
}
@@ -384,7 +384,7 @@ static int netdev_open(struct net_device *pnetdev)
struct _adapter *padapter = netdev_priv(pnetdev);
mutex_lock(&padapter->mutex_start);
- if (padapter->bup == false) {
+ if (!padapter->bup) {
padapter->bDriverStopped = false;
padapter->bSurpriseRemoved = false;
padapter->bup = true;
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c
index f70235c8683d..9b9160947943 100644
--- a/drivers/staging/rtl8712/rtl8712_cmd.c
+++ b/drivers/staging/rtl8712/rtl8712_cmd.c
@@ -62,7 +62,7 @@ static void check_hw_pbc(struct _adapter *padapter)
tmp1byte = r8712_read8(padapter, GPIO_CTRL);
if (tmp1byte == 0xff)
return;
- if (tmp1byte&HAL_8192S_HW_GPIO_WPS_BIT) {
+ if (tmp1byte & HAL_8192S_HW_GPIO_WPS_BIT) {
/* Here we only set bPbcPressed to true
* After trigger PBC, the variable will be set to false
*/
@@ -85,7 +85,7 @@ static void query_fw_rx_phy_status(struct _adapter *padapter)
u32 val32 = 0;
int pollingcnts = 50;
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
r8712_write32(padapter, IOCMD_CTRL_REG, 0xf4000001);
msleep(100);
/* Wait FW complete IO Cmd */
@@ -324,8 +324,7 @@ int r8712_cmd_thread(void *context)
while (1) {
if ((_down_sema(&(pcmdpriv->cmd_queue_sema))) == _FAIL)
break;
- if ((padapter->bDriverStopped == true) ||
- (padapter->bSurpriseRemoved == true))
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
break;
if (r8712_register_cmd_alive(padapter) != _SUCCESS)
continue;
@@ -346,7 +345,7 @@ _next:
pcmdpriv->cmd_issued_cnt++;
cmdsz = round_up(pcmd->cmdsz, 8);
wr_sz = TXDESC_SIZE + 8 + cmdsz;
- pdesc->txdw0 |= cpu_to_le32((wr_sz-TXDESC_SIZE) &
+ pdesc->txdw0 |= cpu_to_le32((wr_sz - TXDESC_SIZE) &
0x0000ffff);
if (pdvobj->ishighspeed) {
if ((wr_sz % 512) == 0)
@@ -375,8 +374,8 @@ _next:
pcmdbuf += 2; /* 8 bytes alignment */
memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
while (check_cmd_fifo(padapter, wr_sz) == _FAIL) {
- if ((padapter->bDriverStopped == true) ||
- (padapter->bSurpriseRemoved == true))
+ if (padapter->bDriverStopped ||
+ padapter->bSurpriseRemoved)
break;
msleep(100);
continue;
@@ -406,10 +405,12 @@ _next:
if (list_empty(&pcmdpriv->cmd_queue.queue)) {
r8712_unregister_cmd_alive(padapter);
continue;
- } else
+ } else {
goto _next;
- } else
+ }
+ } else {
goto _next;
+ }
flush_signals_thread();
}
/* free all cmd_obj resources */
@@ -442,20 +443,20 @@ void r8712_event_handle(struct _adapter *padapter, uint *peventbuf)
}
/* checking if event code is valid */
if (evt_code >= MAX_C2HEVT) {
- pevt_priv->event_seq = ((evt_seq+1) & 0x7f);
+ pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
goto _abort_event_;
} else if ((evt_code == GEN_EVT_CODE(_Survey)) &&
(evt_sz > sizeof(struct wlan_bssid_ex))) {
- pevt_priv->event_seq = ((evt_seq+1)&0x7f);
+ pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
goto _abort_event_;
}
/* checking if event size match the event parm size */
if ((wlanevents[evt_code].parmsize) &&
(wlanevents[evt_code].parmsize != evt_sz)) {
- pevt_priv->event_seq = ((evt_seq+1)&0x7f);
+ pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
goto _abort_event_;
} else if ((evt_sz == 0) && (evt_code != GEN_EVT_CODE(_WPS_PBC))) {
- pevt_priv->event_seq = ((evt_seq+1)&0x7f);
+ pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
goto _abort_event_;
}
pevt_priv->event_seq++; /* update evt_seq */
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
index d95716999498..eaa93fbb95a3 100644
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ b/drivers/staging/rtl8712/rtl8712_efuse.c
@@ -39,7 +39,7 @@ static void efuse_reg_ctrl(struct _adapter *padapter, u8 bPowerOn)
{
u8 tmpu8 = 0;
- if (true == bPowerOn) {
+ if (bPowerOn) {
/* -----------------e-fuse pwr & clk reg ctrl ---------------
* Enable LDOE25 Macro Block
*/
@@ -80,12 +80,13 @@ static u8 efuse_one_byte_read(struct _adapter *padapter, u16 addr, u8 *data)
u8 tmpidx = 0, bResult;
/* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
- r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) |
- (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC));
- r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */
+ r8712_write8(padapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
+ r8712_write8(padapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
+ (r8712_read8(padapter, EFUSE_CTRL + 2) & 0xFC));
+ r8712_write8(padapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
/* wait for complete */
- while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100))
+ while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL + 3)) &&
+ (tmpidx < 100))
tmpidx++;
if (tmpidx < 100) {
*data = r8712_read8(padapter, EFUSE_CTRL);
@@ -102,13 +103,14 @@ static u8 efuse_one_byte_write(struct _adapter *padapter, u16 addr, u8 data)
u8 tmpidx = 0, bResult;
/* -----------------e-fuse reg ctrl -------------------------------- */
- r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
- r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) |
- (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC));
+ r8712_write8(padapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
+ r8712_write8(padapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
+ (r8712_read8(padapter, EFUSE_CTRL + 2) & 0xFC));
r8712_write8(padapter, EFUSE_CTRL, data); /* data */
- r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */
+ r8712_write8(padapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
/* wait for complete */
- while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100))
+ while ((0x80 & r8712_read8(padapter, EFUSE_CTRL + 3)) &&
+ (tmpidx < 100))
tmpidx++;
if (tmpidx < 100)
bResult = true;
@@ -123,13 +125,13 @@ static u8 efuse_one_byte_rw(struct _adapter *padapter, u8 bRead, u16 addr,
u8 tmpidx = 0, tmpv8 = 0, bResult;
/* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
+ r8712_write8(padapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
tmpv8 = ((u8)((addr >> 8) & 0x03)) |
(r8712_read8(padapter, EFUSE_CTRL + 2) & 0xFC);
- r8712_write8(padapter, EFUSE_CTRL+2, tmpv8);
- if (true == bRead) {
- r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */
- while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) &&
+ r8712_write8(padapter, EFUSE_CTRL + 2, tmpv8);
+ if (bRead) {
+ r8712_write8(padapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
+ while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL + 3)) &&
(tmpidx < 100))
tmpidx++;
if (tmpidx < 100) {
@@ -141,8 +143,8 @@ static u8 efuse_one_byte_rw(struct _adapter *padapter, u8 bRead, u16 addr,
}
} else {
r8712_write8(padapter, EFUSE_CTRL, *data); /* data */
- r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */
- while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) &&
+ r8712_write8(padapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
+ while ((0x80 & r8712_read8(padapter, EFUSE_CTRL + 3)) &&
(tmpidx < 100))
tmpidx++;
if (tmpidx < 100)
@@ -158,13 +160,14 @@ static u8 efuse_is_empty(struct _adapter *padapter, u8 *empty)
u8 value, ret = true;
/* read one byte to check if E-Fuse is empty */
- if (efuse_one_byte_rw(padapter, true, 0, &value) == true) {
+ if (efuse_one_byte_rw(padapter, true, 0, &value)) {
if (0xFF == value)
*empty = true;
else
*empty = false;
- } else
+ } else {
ret = false;
+ }
return ret;
}
@@ -207,7 +210,7 @@ static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata,
u8 word_idx, byte_idx;
for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) {
- if (!(word_en&BIT(word_idx))) {
+ if (!(word_en & BIT(word_idx))) {
byte_idx = word_idx * 2;
targetdata[byte_idx] = sourdata[tmpindex++];
targetdata[byte_idx + 1] = sourdata[tmpindex++];
@@ -229,8 +232,9 @@ u16 r8712_efuse_get_current_size(struct _adapter *padapter)
word_cnts = calculate_word_cnts(hworden);
/* read next header */
efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- } else
+ } else {
bContinual = false;
+ }
}
return efuse_addr;
}
@@ -248,10 +252,9 @@ u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data)
return false;
if (offset > 0x0f)
return false;
- memset(data, 0xFF, sizeof(u8)*PGPKT_DATA_SIZE);
+ memset(data, 0xFF, sizeof(u8) * PGPKT_DATA_SIZE);
while (efuse_addr < efuse_available_max_size) {
- if (efuse_one_byte_read(padapter, efuse_addr, &efuse_data) ==
- true) {
+ if (efuse_one_byte_read(padapter, efuse_addr, &efuse_data)) {
if (efuse_data == 0xFF)
break;
hoffset = (efuse_data >> 4) & 0x0F;
@@ -262,15 +265,16 @@ u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data)
for (tmpidx = 0; tmpidx < word_cnts * 2;
tmpidx++) {
if (efuse_one_byte_read(padapter,
- efuse_addr+1+tmpidx, &efuse_data) ==
- true) {
+ efuse_addr + 1 + tmpidx,
+ &efuse_data)) {
tmpdata[tmpidx] = efuse_data;
- } else
+ } else {
ret = false;
+ }
}
pgpacket_copy_data(hworden, tmpdata, data);
}
- efuse_addr += 1 + (word_cnts*2);
+ efuse_addr += 1 + (word_cnts * 2);
} else {
ret = false;
break;
@@ -295,14 +299,14 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr)
/* retrieve original data */
addr = 0;
while (addr < header_addr) {
- if (efuse_one_byte_read(padapter, addr++, &value) == false) {
+ if (!efuse_one_byte_read(padapter, addr++, &value)) {
ret = false;
break;
}
offset = GET_EFUSE_OFFSET(value);
word_en = GET_EFUSE_WORD_EN(value);
if (pkt.offset != offset) {
- addr += calculate_word_cnts(word_en)*2;
+ addr += calculate_word_cnts(word_en) * 2;
continue;
}
for (i = 0; i < PGPKG_MAX_WORDS; i++) {
@@ -310,15 +314,15 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr)
if (BIT(i) & pkt.word_en) {
if (efuse_one_byte_read(
padapter, addr,
- &value) == true)
- pkt.data[i*2] = value;
+ &value))
+ pkt.data[i * 2] = value;
else
return false;
if (efuse_one_byte_read(
padapter,
addr + 1,
- &value) == true)
- pkt.data[i*2 + 1] =
+ &value))
+ pkt.data[i * 2 + 1] =
value;
else
return false;
@@ -333,27 +337,26 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr)
/* fill original data */
for (i = 0; i < PGPKG_MAX_WORDS; i++) {
if (BIT(i) & pkt.word_en) {
- efuse_one_byte_write(padapter, addr, pkt.data[i*2]);
- efuse_one_byte_write(padapter, addr+1,
- pkt.data[i*2 + 1]);
+ efuse_one_byte_write(padapter, addr, pkt.data[i * 2]);
+ efuse_one_byte_write(padapter, addr + 1,
+ pkt.data[i * 2 + 1]);
/* additional check */
- if (efuse_one_byte_read(padapter, addr, &value)
- == false)
+ if (!efuse_one_byte_read(padapter, addr, &value)) {
ret = false;
- else if (pkt.data[i*2] != value) {
+ } else if (pkt.data[i * 2] != value) {
ret = false;
if (0xFF == value) /* write again */
efuse_one_byte_write(padapter, addr,
pkt.data[i * 2]);
}
- if (efuse_one_byte_read(padapter, addr+1, &value) ==
- false)
+ if (!efuse_one_byte_read(padapter, addr + 1, &value)) {
ret = false;
- else if (pkt.data[i*2 + 1] != value) {
+ } else if (pkt.data[i * 2 + 1] != value) {
ret = false;
if (0xFF == value) /* write again */
- efuse_one_byte_write(padapter, addr+1,
- pkt.data[i*2 + 1]);
+ efuse_one_byte_write(padapter, addr + 1,
+ pkt.data[i * 2 +
+ 1]);
}
}
addr += 2;
@@ -388,8 +391,8 @@ u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset,
efuse_one_byte_write(padapter, efuse_addr, pg_header); /*hdr*/
sub_repeat = 0;
/* check if what we read is what we write */
- while (efuse_one_byte_read(padapter, efuse_addr,
- &efuse_data) == false) {
+ while (!efuse_one_byte_read(padapter, efuse_addr,
+ &efuse_data)) {
if (++sub_repeat > _REPEAT_THRESHOLD_) {
bResult = false; /* continue to blind write */
break; /* continue to blind write */
@@ -402,14 +405,15 @@ u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset,
/* go to next address */
efuse_addr++;
- for (i = 0; i < target_word_cnts*2; i++) {
+ for (i = 0; i < target_word_cnts * 2; i++) {
efuse_one_byte_write(padapter,
efuse_addr + i,
*(data + i));
- if (efuse_one_byte_read(padapter,
- efuse_addr + i, &efuse_data) == false)
+ if (!efuse_one_byte_read(padapter,
+ efuse_addr + i,
+ &efuse_data))
bResult = false;
- else if (*(data+i) != efuse_data) /* fail */
+ else if (*(data + i) != efuse_data) /* fail */
bResult = false;
}
break;
@@ -437,10 +441,10 @@ u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead, u16 start_addr,
if (start_addr > EFUSE_MAX_SIZE)
return false;
- if ((bRead == false) && ((start_addr + cnts) >
+ if (!bRead && ((start_addr + cnts) >
efuse_available_max_size))
return false;
- if ((false == bRead) && (r8712_efuse_reg_init(padapter) == false))
+ if (!bRead && !r8712_efuse_reg_init(padapter))
return false;
/* -----------------e-fuse one byte read / write ---------------------*/
for (i = 0; i < cnts; i++) {
@@ -450,10 +454,10 @@ u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead, u16 start_addr,
}
res = efuse_one_byte_rw(padapter, bRead, start_addr + i,
data + i);
- if ((false == bRead) && (false == res))
+ if (!bRead && !res)
break;
}
- if (false == bRead)
+ if (!bRead)
r8712_efuse_reg_uninit(padapter);
return res;
}
@@ -466,8 +470,7 @@ u8 r8712_efuse_map_read(struct _adapter *padapter, u16 addr, u16 cnts, u8 *data)
if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
return false;
- if ((efuse_is_empty(padapter, &offset) == true) && (offset ==
- true)) {
+ if (efuse_is_empty(padapter, &offset) && offset) {
for (i = 0; i < cnts; i++)
data[i] = 0xFF;
return ret;
@@ -504,13 +507,14 @@ u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr, u16 cnts,
empty = r8712_read8(padapter, EFUSE_CLK_CTRL);
if (empty != 0x03)
return false;
- if (efuse_is_empty(padapter, &empty) == true) {
- if (true == empty)
+ if (efuse_is_empty(padapter, &empty)) {
+ if (empty)
memset(pktdata, 0xFF, PGPKT_DATA_SIZE);
- } else
+ } else {
return false;
+ }
offset = (addr >> 3) & 0xF;
- if (empty == false)
+ if (!empty)
if (!r8712_efuse_pg_packet_read(padapter, offset, pktdata))
return false;
word_en = 0xF;
@@ -541,8 +545,8 @@ u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr, u16 cnts,
break;
}
- if ((data[idx] != pktdata[i]) || (data[idx+1] !=
- pktdata[i+1])) {
+ if ((data[idx] != pktdata[i]) || (data[idx + 1] !=
+ pktdata[i + 1])) {
word_en &= ~BIT(i >> 1);
newdata[j++] = data[idx];
newdata[j++] = data[idx + 1];
@@ -554,13 +558,13 @@ u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr, u16 cnts,
}
if (word_en != 0xF)
- if (r8712_efuse_pg_packet_write(padapter, offset,
- word_en, newdata) == false)
+ if (!r8712_efuse_pg_packet_write(padapter, offset,
+ word_en, newdata))
return false;
if (idx == cnts)
break;
offset++;
- if (empty == false)
+ if (!empty)
if (!r8712_efuse_pg_packet_read(padapter, offset,
pktdata))
return false;
diff --git a/drivers/staging/rtl8712/rtl8712_io.c b/drivers/staging/rtl8712/rtl8712_io.c
index b9abe05e6078..4148d48ece62 100644
--- a/drivers/staging/rtl8712/rtl8712_io.c
+++ b/drivers/staging/rtl8712/rtl8712_io.c
@@ -102,8 +102,7 @@ void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
u8 *pmem);
- if ((adapter->bDriverStopped == true) ||
- (adapter->bSurpriseRemoved == true))
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
return;
_read_mem = pintfhdl->io_ops._read_mem;
_read_mem(pintfhdl, addr, cnt, pmem);
@@ -127,8 +126,7 @@ void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
u8 *pmem);
- if ((adapter->bDriverStopped == true) ||
- (adapter->bSurpriseRemoved == true))
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
return;
_read_port = pintfhdl->io_ops._read_port;
_read_port(pintfhdl, addr, cnt, pmem);
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index ada8d5dafd49..9055827cccf8 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -122,8 +122,7 @@ static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed)
{
u8 LedCfg;
- if ((padapter->bSurpriseRemoved == true) ||
- (padapter->bDriverStopped == true))
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
return;
LedCfg = r8712_read8(padapter, LEDCFG);
switch (pLed->LedPin) {
@@ -131,11 +130,11 @@ static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed)
break;
case LED_PIN_LED0:
/* SW control led0 on.*/
- r8712_write8(padapter, LEDCFG, LedCfg&0xf0);
+ r8712_write8(padapter, LEDCFG, LedCfg & 0xf0);
break;
case LED_PIN_LED1:
/* SW control led1 on.*/
- r8712_write8(padapter, LEDCFG, LedCfg&0x0f);
+ r8712_write8(padapter, LEDCFG, LedCfg & 0x0f);
break;
default:
break;
@@ -151,8 +150,7 @@ static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed)
{
u8 LedCfg;
- if ((padapter->bSurpriseRemoved == true) ||
- (padapter->bDriverStopped == true))
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
return;
LedCfg = r8712_read8(padapter, LEDCFG);
switch (pLed->LedPin) {
@@ -160,11 +158,11 @@ static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed)
break;
case LED_PIN_LED0:
LedCfg &= 0xf0; /* Set to software control.*/
- r8712_write8(padapter, LEDCFG, (LedCfg|BIT(3)));
+ r8712_write8(padapter, LEDCFG, (LedCfg | BIT(3)));
break;
case LED_PIN_LED1:
LedCfg &= 0x0f; /* Set to software control.*/
- r8712_write8(padapter, LEDCFG, (LedCfg|BIT(7)));
+ r8712_write8(padapter, LEDCFG, (LedCfg | BIT(7)));
break;
default:
break;
@@ -222,11 +220,11 @@ static void SwLedBlink(struct LED_871x *pLed)
bStopBlinking = true;
break;
case LED_BLINK_StartToBlink:
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) &&
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
(pmlmepriv->fw_state & WIFI_STATION_STATE))
bStopBlinking = true;
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) &&
- ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) ||
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) ||
(pmlmepriv->fw_state & WIFI_ADHOC_MASTER_STATE)))
bStopBlinking = true;
else if (pLed->BlinkTimes == 0)
@@ -241,11 +239,10 @@ static void SwLedBlink(struct LED_871x *pLed)
break;
}
if (bStopBlinking) {
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) &&
- (pLed->bLedOn == false))
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ !pLed->bLedOn)
SwLedOn(padapter, pLed);
- else if ((check_fwstate(pmlmepriv, _FW_LINKED) ==
- true) && pLed->bLedOn == true)
+ else if (check_fwstate(pmlmepriv, _FW_LINKED) && pLed->bLedOn)
SwLedOff(padapter, pLed);
pLed->BlinkTimes = 0;
pLed->bLedBlinkInProgress = false;
@@ -296,18 +293,20 @@ static void SwLedBlink1(struct LED_871x *pLed)
else
SwLedOff(padapter, pLed);
if (peeprompriv->CustomerID == RT_CID_DEFAULT) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
if (!pLed1->bSWLedCtrl) {
SwLedOn(padapter, pLed1);
pLed1->bSWLedCtrl = true;
- } else if (!pLed1->bLedOn)
+ } else if (!pLed1->bLedOn) {
SwLedOn(padapter, pLed1);
+ }
} else {
if (!pLed1->bSWLedCtrl) {
SwLedOff(padapter, pLed1);
pLed1->bSWLedCtrl = true;
- } else if (pLed1->bLedOn)
+ } else if (pLed1->bLedOn) {
SwLedOff(padapter, pLed1);
+ }
}
}
switch (pLed->CurrLedState) {
@@ -332,7 +331,7 @@ static void SwLedBlink1(struct LED_871x *pLed)
if (pLed->BlinkTimes == 0)
bStopBlinking = true;
if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
pLed->bLedLinkBlinkInProgress = true;
pLed->CurrLedState = LED_BLINK_NORMAL;
if (pLed->bLedOn)
@@ -366,7 +365,7 @@ static void SwLedBlink1(struct LED_871x *pLed)
if (pLed->BlinkTimes == 0)
bStopBlinking = true;
if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
pLed->bLedLinkBlinkInProgress = true;
pLed->CurrLedState = LED_BLINK_NORMAL;
if (pLed->bLedOn)
@@ -410,8 +409,9 @@ static void SwLedBlink1(struct LED_871x *pLed)
mod_timer(&pLed->BlinkTimer, jiffies +
msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
bStopBlinking = false;
- } else
+ } else {
bStopBlinking = true;
+ }
if (bStopBlinking) {
pLed->bLedLinkBlinkInProgress = true;
pLed->CurrLedState = LED_BLINK_NORMAL;
@@ -446,7 +446,7 @@ static void SwLedBlink2(struct LED_871x *pLed)
if (pLed->BlinkTimes == 0)
bStopBlinking = true;
if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
SwLedOn(padapter, pLed);
@@ -470,7 +470,7 @@ static void SwLedBlink2(struct LED_871x *pLed)
if (pLed->BlinkTimes == 0)
bStopBlinking = true;
if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
SwLedOn(padapter, pLed);
@@ -512,7 +512,7 @@ static void SwLedBlink3(struct LED_871x *pLed)
if (pLed->BlinkTimes == 0)
bStopBlinking = true;
if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
if (!pLed->bLedOn)
@@ -538,7 +538,7 @@ static void SwLedBlink3(struct LED_871x *pLed)
if (pLed->BlinkTimes == 0)
bStopBlinking = true;
if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
if (!pLed->bLedOn)
@@ -573,8 +573,9 @@ static void SwLedBlink3(struct LED_871x *pLed)
mod_timer(&pLed->BlinkTimer, jiffies +
msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
bStopBlinking = false;
- } else
+ } else {
bStopBlinking = true;
+ }
if (bStopBlinking) {
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
@@ -827,8 +828,7 @@ static void BlinkTimerCallback(unsigned long data)
/* This fixed the crash problem on Fedora 12 when trying to do the
* insmod;ifconfig up;rmmod commands. */
- if ((pLed->padapter->bSurpriseRemoved == true) ||
- (pLed->padapter->bDriverStopped == true))
+ if (pLed->padapter->bSurpriseRemoved || pLed->padapter->bDriverStopped)
return;
schedule_work(&pLed->BlinkWorkItem);
}
@@ -893,15 +893,15 @@ static void SwLedControlMode1(struct _adapter *padapter,
switch (LedAction) {
case LED_CTL_START_TO_LINK:
case LED_CTL_NO_LINK:
- if (pLed->bLedNoLinkBlinkInProgress == false) {
+ if (!pLed->bLedNoLinkBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedLinkBlinkInProgress == true) {
+ if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -916,15 +916,15 @@ static void SwLedControlMode1(struct _adapter *padapter,
}
break;
case LED_CTL_LINK:
- if (pLed->bLedLinkBlinkInProgress == false) {
+ if (!pLed->bLedLinkBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -939,21 +939,21 @@ static void SwLedControlMode1(struct _adapter *padapter,
}
break;
case LED_CTL_SITE_SURVEY:
- if ((psitesurveyctrl->traffic_busy) &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true))
+ if (psitesurveyctrl->traffic_busy &&
+ check_fwstate(pmlmepriv, _FW_LINKED))
; /* dummy branch */
- else if (pLed->bLedScanBlinkInProgress == false) {
+ else if (!pLed->bLedScanBlinkInProgress) {
if (IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedLinkBlinkInProgress == true) {
+ if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -970,15 +970,15 @@ static void SwLedControlMode1(struct _adapter *padapter,
break;
case LED_CTL_TX:
case LED_CTL_RX:
- if (pLed->bLedBlinkInProgress == false) {
+ if (!pLed->bLedBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedLinkBlinkInProgress == true) {
+ if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
@@ -996,20 +996,20 @@ static void SwLedControlMode1(struct _adapter *padapter,
case LED_CTL_START_WPS: /*wait until xinpin finish */
case LED_CTL_START_WPS_BOTTON:
- if (pLed->bLedWPSBlinkInProgress == false) {
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedLinkBlinkInProgress == true) {
+ if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
- if (pLed->bLedScanBlinkInProgress == true) {
+ if (pLed->bLedScanBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
@@ -1024,19 +1024,19 @@ static void SwLedControlMode1(struct _adapter *padapter,
}
break;
case LED_CTL_STOP_WPS:
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedLinkBlinkInProgress == true) {
+ if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
- if (pLed->bLedScanBlinkInProgress == true) {
+ if (pLed->bLedScanBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
@@ -1111,11 +1111,11 @@ static void SwLedControlMode2(struct _adapter *padapter,
case LED_CTL_SITE_SURVEY:
if (pmlmepriv->sitesurveyctrl.traffic_busy)
; /* dummy branch */
- else if (pLed->bLedScanBlinkInProgress == false) {
+ else if (!pLed->bLedScanBlinkInProgress) {
if (IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -1133,8 +1133,8 @@ static void SwLedControlMode2(struct _adapter *padapter,
case LED_CTL_TX:
case LED_CTL_RX:
- if ((pLed->bLedBlinkInProgress == false) &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
+ if (!pLed->bLedBlinkInProgress &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
@@ -1168,12 +1168,12 @@ static void SwLedControlMode2(struct _adapter *padapter,
case LED_CTL_START_WPS: /*wait until xinpin finish*/
case LED_CTL_START_WPS_BOTTON:
- if (pLed->bLedWPSBlinkInProgress == false) {
- if (pLed->bLedBlinkInProgress == true) {
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
- if (pLed->bLedScanBlinkInProgress == true) {
+ if (pLed->bLedScanBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
@@ -1244,10 +1244,10 @@ static void SwLedControlMode3(struct _adapter *padapter,
case LED_CTL_SITE_SURVEY:
if (pmlmepriv->sitesurveyctrl.traffic_busy)
; /* dummy branch */
- else if (pLed->bLedScanBlinkInProgress == false) {
+ else if (!pLed->bLedScanBlinkInProgress) {
if (IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -1264,8 +1264,8 @@ static void SwLedControlMode3(struct _adapter *padapter,
break;
case LED_CTL_TX:
case LED_CTL_RX:
- if ((pLed->bLedBlinkInProgress == false) &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
+ if (!pLed->bLedBlinkInProgress &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
@@ -1298,12 +1298,12 @@ static void SwLedControlMode3(struct _adapter *padapter,
break;
case LED_CTL_START_WPS: /* wait until xinpin finish */
case LED_CTL_START_WPS_BOTTON:
- if (pLed->bLedWPSBlinkInProgress == false) {
- if (pLed->bLedBlinkInProgress == true) {
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
- if (pLed->bLedScanBlinkInProgress == true) {
+ if (pLed->bLedScanBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
@@ -1321,8 +1321,9 @@ static void SwLedControlMode3(struct _adapter *padapter,
if (pLed->bLedWPSBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
- } else
+ } else {
pLed->bLedWPSBlinkInProgress = true;
+ }
pLed->CurrLedState = LED_BLINK_WPS_STOP;
if (pLed->bLedOn) {
pLed->BlinkingLedState = LED_OFF;
@@ -1395,15 +1396,15 @@ static void SwLedControlMode4(struct _adapter *padapter,
mod_timer(&pLed->BlinkTimer,
jiffies + msecs_to_jiffies(0));
}
- if (pLed->bLedStartToLinkBlinkInProgress == false) {
+ if (!pLed->bLedStartToLinkBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
@@ -1434,11 +1435,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
jiffies + msecs_to_jiffies(0));
}
}
- if (pLed->bLedNoLinkBlinkInProgress == false) {
+ if (!pLed->bLedNoLinkBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -1453,17 +1454,17 @@ static void SwLedControlMode4(struct _adapter *padapter,
}
break;
case LED_CTL_SITE_SURVEY:
- if ((pmlmepriv->sitesurveyctrl.traffic_busy) &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true))
+ if (pmlmepriv->sitesurveyctrl.traffic_busy &&
+ check_fwstate(pmlmepriv, _FW_LINKED))
;
- else if (pLed->bLedScanBlinkInProgress == false) {
+ else if (!pLed->bLedScanBlinkInProgress) {
if (IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -1480,11 +1481,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
break;
case LED_CTL_TX:
case LED_CTL_RX:
- if (pLed->bLedBlinkInProgress == false) {
+ if (!pLed->bLedBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK ||
IS_LED_WPS_BLINKING(pLed))
return;
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
@@ -1510,16 +1511,16 @@ static void SwLedControlMode4(struct _adapter *padapter,
mod_timer(&pLed->BlinkTimer,
jiffies + msecs_to_jiffies(0));
}
- if (pLed->bLedWPSBlinkInProgress == false) {
- if (pLed->bLedNoLinkBlinkInProgress == true) {
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
- if (pLed->bLedBlinkInProgress == true) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
- if (pLed->bLedScanBlinkInProgress == true) {
+ if (pLed->bLedScanBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
@@ -1666,11 +1667,11 @@ static void SwLedControlMode5(struct _adapter *padapter,
jiffies + msecs_to_jiffies(0));
break;
case LED_CTL_SITE_SURVEY:
- if ((pmlmepriv->sitesurveyctrl.traffic_busy) &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true))
+ if (pmlmepriv->sitesurveyctrl.traffic_busy &&
+ check_fwstate(pmlmepriv, _FW_LINKED))
; /* dummy branch */
- else if (pLed->bLedScanBlinkInProgress == false) {
- if (pLed->bLedBlinkInProgress == true) {
+ else if (!pLed->bLedScanBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -1687,7 +1688,7 @@ static void SwLedControlMode5(struct _adapter *padapter,
break;
case LED_CTL_TX:
case LED_CTL_RX:
- if (pLed->bLedBlinkInProgress == false) {
+ if (!pLed->bLedBlinkInProgress) {
if (pLed->CurrLedState == LED_SCAN_BLINK)
return;
pLed->bLedBlinkInProgress = true;
@@ -1737,8 +1738,8 @@ static void SwLedControlMode6(struct _adapter *padapter,
break;
case LED_CTL_TX:
case LED_CTL_RX:
- if (pLed->bLedBlinkInProgress == false &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
+ if (!pLed->bLedBlinkInProgress &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
if (IS_LED_WPS_BLINKING(pLed))
return;
pLed->bLedBlinkInProgress = true;
@@ -1754,8 +1755,8 @@ static void SwLedControlMode6(struct _adapter *padapter,
break;
case LED_CTL_START_WPS: /*wait until xinpin finish*/
case LED_CTL_START_WPS_BOTTON:
- if (pLed->bLedWPSBlinkInProgress == false) {
- if (pLed->bLedBlinkInProgress == true) {
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
@@ -1805,7 +1806,7 @@ void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction)
{
struct led_priv *ledpriv = &(padapter->ledpriv);
- if (ledpriv->bRegUseLed == false)
+ if (!ledpriv->bRegUseLed)
return;
switch (ledpriv->LedStrategy) {
case SW_LED_MODE0:
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index 534dc04d51a6..d187508dd1e0 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -89,7 +89,7 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter)
RECVBUFF_ALIGN_SZ);
if (pskb) {
tmpaddr = (addr_t)pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
}
@@ -160,7 +160,7 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
{
u16 drvinfo_sz;
- drvinfo_sz = (le32_to_cpu(prxstat->rxdw0)&0x000f0000)>>16;
+ drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
drvinfo_sz <<= 3;
/*TODO:
* Offset 0 */
@@ -180,8 +180,9 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
pattrib->ip_chkrpt = 1; /* correct */
else
pattrib->ip_chkrpt = 0; /* incorrect */
- } else
+ } else {
pattrib->tcpchk_valid = 0; /* invalid */
+ }
pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f);
pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 14) & 0x1);
/*Offset 16*/
@@ -217,7 +218,7 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter,
curfragnum++;
plist = &defrag_q->queue;
plist = plist->next;
- while (end_of_queue_search(phead, plist) == false) {
+ while (!end_of_queue_search(phead, plist)) {
pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
pnfhdr = &pnextrframe->u.hdr;
/*check the fragment sequence (2nd ~n fragment frame) */
@@ -414,8 +415,9 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe)
if ((pattrib->tcpchk_valid == 1) &&
(pattrib->tcp_chkrpt == 1)) {
sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else
+ } else {
sub_skb->ip_summed = CHECKSUM_NONE;
+ }
netif_rx(sub_skb);
}
}
@@ -489,7 +491,7 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
phead = &ppending_recvframe_queue->queue;
plist = phead->next;
- while (end_of_queue_search(phead, plist) == false) {
+ while (!end_of_queue_search(phead, plist)) {
pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
pnextattrib = &pnextrframe->u.hdr.attrib;
if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
@@ -519,7 +521,7 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
phead = &ppending_recvframe_queue->queue;
plist = phead->next;
/* Handling some condition for forced indicate case.*/
- if (bforced == true) {
+ if (bforced) {
if (list_empty(phead))
return true;
@@ -541,8 +543,8 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
(preorder_ctrl->indicate_seq + 1) % 4096;
/*indicate this recv_frame*/
if (!pattrib->amsdu) {
- if ((padapter->bDriverStopped == false) &&
- (padapter->bSurpriseRemoved == false)) {
+ if (!padapter->bDriverStopped &&
+ !padapter->bSurpriseRemoved) {
/* indicate this recv_frame */
r8712_recv_indicatepkt(padapter,
prframe);
@@ -576,12 +578,13 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter,
/* s1. */
r8712_wlanhdr_to_ethhdr(prframe);
if (pattrib->qos != 1) {
- if ((padapter->bDriverStopped == false) &&
- (padapter->bSurpriseRemoved == false)) {
+ if (!padapter->bDriverStopped &&
+ !padapter->bSurpriseRemoved) {
r8712_recv_indicatepkt(padapter, prframe);
return _SUCCESS;
- } else
+ } else {
return _FAIL;
+ }
}
}
spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
@@ -643,20 +646,20 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter,
if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
/* including perform A-MPDU Rx Ordering Buffer Control*/
- if ((padapter->bDriverStopped == false) &&
- (padapter->bSurpriseRemoved == false))
+ if (!padapter->bDriverStopped &&
+ !padapter->bSurpriseRemoved)
return _FAIL;
}
} else { /*B/G mode*/
retval = r8712_wlanhdr_to_ethhdr(prframe);
if (retval != _SUCCESS)
return retval;
- if ((padapter->bDriverStopped == false) &&
- (padapter->bSurpriseRemoved == false)) {
+ if (!padapter->bDriverStopped && !padapter->bSurpriseRemoved) {
/* indicate this recv_frame */
r8712_recv_indicatepkt(padapter, prframe);
- } else
+ } else {
return _FAIL;
+ }
}
return retval;
}
@@ -813,16 +816,16 @@ static void query_rx_phy_status(struct _adapter *padapter,
/*
* (3) Get Signal Quality (EVM)
*/
- if (pwdb_all > 40)
+ if (pwdb_all > 40) {
sq = 100;
- else {
+ } else {
sq = pcck_buf->sq_rpt;
if (pcck_buf->sq_rpt > 64)
sq = 0;
else if (pcck_buf->sq_rpt < 20)
sq = 100;
else
- sq = ((64-sq) * 100) / 44;
+ sq = ((64 - sq) * 100) / 44;
}
prframe->u.hdr.attrib.signal_qual = sq;
prframe->u.hdr.attrib.rx_mimo_signal_qual[0] = sq;
@@ -962,12 +965,12 @@ int recv_func(struct _adapter *padapter, void *pcontext)
prframe = (union recv_frame *)pcontext;
orig_prframe = prframe;
pattrib = &prframe->u.hdr.attrib;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
if (pattrib->crc_err == 1)
padapter->mppriv.rx_crcerrpktcount++;
else
padapter->mppriv.rx_pktcount++;
- if (check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE) == false) {
+ if (!check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE)) {
/* free this recv_frame */
r8712_free_recvframe(orig_prframe, pfree_recv_queue);
goto _exit_recv_func;
@@ -1019,8 +1022,8 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
pfree_recv_queue = &(precvpriv->free_recv_queue);
pbuf = pskb->data;
prxstat = (struct recv_stat *)pbuf;
- pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16)&0xff;
- pkt_len = le32_to_cpu(prxstat->rxdw0)&0x00003fff;
+ pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
+ pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
transfer_len = pskb->len;
/* Test throughput with Netgear 3700 (No security) with Chariot 3T3R
* pairs. The packet count will be a big number so that the containing
@@ -1032,7 +1035,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
}
do {
prxstat = (struct recv_stat *)pbuf;
- pkt_len = le32_to_cpu(prxstat->rxdw0)&0x00003fff;
+ pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
/* more fragment bit */
mf = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1;
/* ragmentation number */
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c
index 27b121398027..b21a60e9f8a9 100644
--- a/drivers/staging/rtl8712/rtl8712_xmit.c
+++ b/drivers/staging/rtl8712/rtl8712_xmit.c
@@ -98,11 +98,11 @@ static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe)
struct _adapter *padapter = pxmitframe->padapter;
struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- if (pxmitframe->frame_tag == TXAGG_FRAMETAG)
+ if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
addr = RTL8712_DMA_H2CCMD;
- else if (pxmitframe->frame_tag == MGNT_FRAMETAG)
+ } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
addr = RTL8712_DMA_MGTQ;
- else if (pdvobj->nr_endpoint == 6) {
+ } else if (pdvobj->nr_endpoint == 6) {
switch (pattrib->priority) {
case 0:
case 3:
@@ -168,7 +168,7 @@ static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv,
xmitframe_phead = &pframe_queue->queue;
xmitframe_plist = xmitframe_phead->next;
- if ((end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false) {
+ if (!end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
pxmitframe = LIST_CONTAINOR(xmitframe_plist,
struct xmit_frame, list);
list_del_init(&pxmitframe->list);
@@ -208,7 +208,7 @@ static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv,
phwxmit = phwxmit_i + inx[i];
sta_phead = &phwxmit->sta_queue->queue;
sta_plist = sta_phead->next;
- while ((end_of_queue_search(sta_phead, sta_plist)) == false) {
+ while (!end_of_queue_search(sta_phead, sta_plist)) {
ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq,
tx_pending);
pframe_queue = &ptxservq->sta_pending;
@@ -239,9 +239,9 @@ void r8712_do_queue_select(struct _adapter *padapter,
unsigned int qsel = 0;
struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- if (pdvobj->nr_endpoint == 6)
+ if (pdvobj->nr_endpoint == 6) {
qsel = (unsigned int) pattrib->priority;
- else if (pdvobj->nr_endpoint == 4) {
+ } else if (pdvobj->nr_endpoint == 4) {
qsel = (unsigned int) pattrib->priority;
if (qsel == 0 || qsel == 3)
qsel = 3;
@@ -264,13 +264,14 @@ u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf)
/* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/
/* dw0 */
- ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ&0xffff);
+ ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff);
ptx_desc->txdw0 |=
- cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);
+ cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
+ 0x00ff0000);
ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
/* dw1 */
- ptx_desc->txdw1 |= cpu_to_le32((0x13<<QSEL_SHT)&0x00001f00);
+ ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00);
return _SUCCESS;
}
@@ -322,12 +323,14 @@ u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf,
int i;
for (i = 0; i < padding_sz; i++)
- *(pxmitframe->buf_addr+TXDESC_SIZE+last_txcmdsz+i) = 0;
+ *(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz +
+ i) = 0;
}
/* Add the new mpdu's length */
- ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0&0xffff0000) |
- ((ptx_desc->txdw0&0x0000ffff)+
- ((TXDESC_SIZE+last_txcmdsz+padding_sz)&0x0000ffff)));
+ ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) |
+ ((ptx_desc->txdw0 & 0x0000ffff) +
+ ((TXDESC_SIZE + last_txcmdsz + padding_sz) &
+ 0x0000ffff)));
return _SUCCESS;
}
@@ -341,7 +344,7 @@ u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
pxmitbuf->priv_data = pxmitframe;
pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
/* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf+TXDESC_SIZE+CMD_HDR_SZ;
+ pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ;
/*RTL8712_DMA_H2CCMD */
r8712_construct_txaggr_cmd_desc(pxmitbuf);
r8712_construct_txaggr_cmd_hdr(pxmitbuf);
@@ -382,29 +385,32 @@ u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
/* use 1st xmitframe as media */
xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length-CMD_HDR_SZ)&0x0000ffff)|
- (pcmd_hdr->cmd_dw0&0xffff0000));
+ pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) &
+ 0x0000ffff) | (pcmd_hdr->cmd_dw0 &
+ 0xffff0000));
/* urb length in cmd_dw1 */
pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff)|
- ((total_length+TXDESC_SIZE) << 16));
+ ((total_length + TXDESC_SIZE) << 16));
pxmitframe->last[0] = 1;
pxmitframe->bpending[0] = false;
pxmitframe->mem_addr = pxmitbuf->pbuf;
- if ((pdvobj->ishighspeed && ((total_length+TXDESC_SIZE)%0x200) == 0) ||
- ((!pdvobj->ishighspeed &&
- ((total_length+TXDESC_SIZE)%0x40) == 0))) {
+ if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) ==
+ 0) || ((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) %
+ 0x40) == 0))) {
ptxdesc->txdw0 |= cpu_to_le32
- (((TXDESC_SIZE+OFFSET_SZ+8)<<OFFSET_SHT)&0x00ff0000);
+ (((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) &
+ 0x00ff0000);
/*32 bytes for TX Desc + 8 bytes pending*/
} else {
ptxdesc->txdw0 |= cpu_to_le32
- (((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);
+ (((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
+ 0x00ff0000);
/*default = 32 bytes for TX Desc*/
}
r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD,
- total_length+TXDESC_SIZE, (u8 *)pxmitframe);
+ total_length + TXDESC_SIZE, (u8 *)pxmitframe);
return _SUCCESS;
}
@@ -432,7 +438,7 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc));
memset(ptxdesc, 0, sizeof(struct tx_desc));
/* offset 0 */
- ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff);
+ ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);
if (pdvobj->ishighspeed) {
if (((sz + TXDESC_SIZE) % 512) == 0)
blnSetTxDescOffset = 1;
@@ -446,42 +452,42 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
}
if (blnSetTxDescOffset) {
/* 32 bytes for TX Desc + 8 bytes pending */
- ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ + 8) <<
+ ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ + 8) <<
OFFSET_SHT) & 0x00ff0000);
} else {
/* default = 32 bytes for TX Desc */
- ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ) <<
+ ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
OFFSET_SHT) & 0x00ff0000);
}
ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
if (pxmitframe->frame_tag == DATA_FRAMETAG) {
/* offset 4 */
- ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id)&0x1f);
+ ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x1f);
#ifdef CONFIG_R8712_TX_AGGR
/* dirty workaround, need to check if it is aggr cmd. */
if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) {
ptxdesc->txdw0 |= cpu_to_le32
- ((0x3 << TYPE_SHT)&TYPE_MSK);
+ ((0x3 << TYPE_SHT) & TYPE_MSK);
qsel = (uint)(pattrib->qsel & 0x0000001f);
if (qsel == 2)
qsel = 0;
ptxdesc->txdw1 |= cpu_to_le32
((qsel << QSEL_SHT) & 0x00001f00);
ptxdesc->txdw2 = cpu_to_le32
- ((qsel << RTS_RC_SHT)&0x001f0000);
+ ((qsel << RTS_RC_SHT) & 0x001f0000);
ptxdesc->txdw6 |= cpu_to_le32
- ((0x5 << RSVD6_SHT)&RSVD6_MSK);
+ ((0x5 << RSVD6_SHT) & RSVD6_MSK);
} else {
ptxdesc->txdw0 |= cpu_to_le32
- ((0x3 << TYPE_SHT)&TYPE_MSK);
+ ((0x3 << TYPE_SHT) & TYPE_MSK);
ptxdesc->txdw1 |= cpu_to_le32
((0x13 << QSEL_SHT) & 0x00001f00);
qsel = (uint)(pattrib->qsel & 0x0000001f);
if (qsel == 2)
qsel = 0;
ptxdesc->txdw2 = cpu_to_le32
- ((qsel << RTS_RC_SHT)&0x0001f000);
+ ((qsel << RTS_RC_SHT) & 0x0001f000);
ptxdesc->txdw7 |= cpu_to_le32
(pcmdpriv->cmd_seq << 24);
pcmdpriv->cmd_seq++;
@@ -593,7 +599,7 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
} else {
/* offset 4 */
- qsel = (uint)(pattrib->priority&0x0000001f);
+ qsel = (uint)(pattrib->priority & 0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
/*offset 8*/
/*offset 12*/
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index ef7182961002..562a10203127 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -70,7 +70,7 @@ static sint _init_cmd_priv(struct cmd_priv *pcmdpriv)
return _FAIL;
pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ -
((addr_t)(pcmdpriv->cmd_allocated_buf) &
- (CMDBUFF_ALIGN_SZ-1));
+ (CMDBUFF_ALIGN_SZ - 1));
pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC);
if (pcmdpriv->rsp_allocated_buf == NULL)
return _FAIL;
@@ -137,9 +137,9 @@ static struct cmd_obj *_dequeue_cmd(struct __queue *queue)
struct cmd_obj *obj;
spin_lock_irqsave(&(queue->lock), irqL);
- if (list_empty(&(queue->queue)))
+ if (list_empty(&(queue->queue))) {
obj = NULL;
- else {
+ } else {
obj = LIST_CONTAINOR(queue->queue.next,
struct cmd_obj, list);
list_del_init(&obj->list);
@@ -172,7 +172,7 @@ u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
{
int res;
- if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag == true)
+ if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
return _FAIL;
res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj);
up(&pcmdpriv->cmd_queue_sema);
@@ -186,7 +186,7 @@ u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
if (obj == NULL)
return _SUCCESS;
- if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag == true)
+ if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
return _FAIL;
queue = &pcmdpriv->cmd_queue;
spin_lock_irqsave(&queue->lock, irqL);
@@ -485,7 +485,7 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
return _FAIL;
/* for hidden ap to set fw_state here */
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) !=
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) !=
true) {
switch (ndis_network_mode) {
case Ndis802_11IBSS:
@@ -508,18 +508,18 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
psecuritypriv->authenticator_ie[0] = (unsigned char)
psecnetwork->IELength;
- if ((psecnetwork->IELength-12) < (256 - 1))
+ if ((psecnetwork->IELength - 12) < (256 - 1))
memcpy(&psecuritypriv->authenticator_ie[1],
- &psecnetwork->IEs[12], psecnetwork->IELength-12);
+ &psecnetwork->IEs[12], psecnetwork->IELength - 12);
else
memcpy(&psecuritypriv->authenticator_ie[1],
- &psecnetwork->IEs[12], (256-1));
+ &psecnetwork->IEs[12], (256 - 1));
psecnetwork->IELength = 0;
/* If the driver wants to use the bssid to create the connection.
* If not, we copy the connecting AP's MAC address to it so that
* the driver just has the bssid information for PMKIDList searching.
*/
- if (pmlmepriv->assoc_by_bssid == false)
+ if (!pmlmepriv->assoc_by_bssid)
ether_addr_copy(&pmlmepriv->assoc_bssid[0],
&pnetwork->network.MacAddress[0]);
psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
@@ -538,8 +538,9 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
if (psecnetwork->IELength != tmp_len) {
psecnetwork->IELength = tmp_len;
pqospriv->qos_option = 1; /* WMM IE in beacon */
- } else
+ } else {
pqospriv->qos_option = 0; /* no WMM IE in beacon */
+ }
}
if (pregistrypriv->ht_enable) {
/* For WEP mode, we will use the bg mode to do the connection
@@ -679,7 +680,7 @@ u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
else
GET_ENCRY_ALGO(psecuritypriv, sta,
psetstakey_para->algorithm, false);
- if (unicast_key == true)
+ if (unicast_key)
memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
else
memcpy(&psetstakey_para->key,
diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.c b/drivers/staging/rtl8712/rtl871x_eeprom.c
index 50339e67da07..4e713610ad8b 100644
--- a/drivers/staging/rtl8712/rtl871x_eeprom.c
+++ b/drivers/staging/rtl8712/rtl871x_eeprom.c
@@ -49,7 +49,7 @@ static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
{
u16 x, mask;
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
mask = 0x01 << (count - 1);
x = r8712_read8(padapter, EE_9346CR);
@@ -58,7 +58,7 @@ static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
x &= ~_EEDI;
if (data & mask)
x |= _EEDI;
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
r8712_write8(padapter, EE_9346CR, (u8)x);
udelay(CLOCK_RATE);
@@ -66,7 +66,7 @@ static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
down_clk(padapter, &x);
mask >>= 1;
} while (mask);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
x &= ~_EEDI;
r8712_write8(padapter, EE_9346CR, (u8)x);
@@ -77,7 +77,7 @@ static u16 shift_in_bits(struct _adapter *padapter)
{
u16 x, d = 0, i;
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
x = r8712_read8(padapter, EE_9346CR);
x &= ~(_EEDO | _EEDI);
@@ -85,7 +85,7 @@ static u16 shift_in_bits(struct _adapter *padapter)
for (i = 0; i < 16; i++) {
d <<= 1;
up_clk(padapter, &x);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
x = r8712_read8(padapter, EE_9346CR);
x &= ~(_EEDI);
@@ -129,17 +129,17 @@ static void eeprom_clean(struct _adapter *padapter)
{
u16 x;
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
return;
x = r8712_read8(padapter, EE_9346CR);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
return;
x &= ~(_EECS | _EEDI);
r8712_write8(padapter, EE_9346CR, (u8)x);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
return;
up_clk(padapter, &x);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
return;
down_clk(padapter, &x);
}
@@ -206,11 +206,11 @@ u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg) /*ReadEEprom*/
tmp8_clk_new = tmp8_clk_ori | 0x20;
if (tmp8_clk_new != tmp8_clk_ori)
r8712_write8(padapter, 0x10250003, tmp8_clk_new);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
/* select EEPROM, reset bits, set _EECS */
x = r8712_read8(padapter, EE_9346CR);
- if (padapter->bSurpriseRemoved == true)
+ if (padapter->bSurpriseRemoved)
goto out;
x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
x |= _EEM1 | _EECS;
diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h
index 070cc03ce374..26dd24cddd38 100644
--- a/drivers/staging/rtl8712/rtl871x_io.h
+++ b/drivers/staging/rtl8712/rtl871x_io.h
@@ -232,14 +232,6 @@ struct io_queue {
struct intf_hdl intf;
};
-static inline u32 _RND4(u32 sz)
-{
- u32 val;
-
- val = ((sz >> 2) + ((sz & 3) ? 1 : 0)) << 2;
- return val;
-}
-
u8 r8712_read8(struct _adapter *adapter, u32 addr);
u16 r8712_read16(struct _adapter *adapter, u32 addr);
u32 r8712_read32(struct _adapter *adapter, u32 addr);
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index a96481609f39..edfc6805e012 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -118,12 +118,13 @@ static inline void handle_group_key(struct ieee_param *param,
param->u.crypt.idx < 3) {
/* group key idx is 1 or 2 */
memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
- idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
- > 16 ? 16 : param->u.crypt.key_len));
+ idx - 1].skey, param->u.crypt.key,
+ (param->u.crypt.key_len > 16 ? 16 :
+ param->u.crypt.key_len));
memcpy(padapter->securitypriv.XGrptxmickey[param->
- u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
+ u.crypt.idx - 1].skey, &(param->u.crypt.key[16]), 8);
memcpy(padapter->securitypriv. XGrprxmickey[param->
- u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
+ u.crypt.idx - 1].skey, &(param->u.crypt.key[24]), 8);
padapter->securitypriv.binstallGrpkey = true;
r8712_set_key(padapter, &padapter->securitypriv,
param->u.crypt.idx);
@@ -178,17 +179,17 @@ static inline char *translate_scan(struct _adapter *padapter,
/* Add the protocol name */
iwe.cmd = SIOCGIWNAME;
if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
- if (ht_cap == true)
+ if (ht_cap)
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
else
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
} else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
- if (ht_cap == true)
+ if (ht_cap)
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
else
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
} else {
- if (ht_cap == true)
+ if (ht_cap)
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
else
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
@@ -199,7 +200,7 @@ static inline char *translate_scan(struct _adapter *padapter,
memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
2);
cap = le16_to_cpu(cap);
- if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
+ if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
if (cap & WLAN_CAPABILITY_BSS)
iwe.u.mode = (u32)IW_MODE_MASTER;
else
@@ -310,7 +311,7 @@ static inline char *translate_scan(struct _adapter *padapter,
if (r8712_get_wps_ie(pnetwork->network.IEs,
pnetwork->network.IELength,
- wps_ie, &wps_ielen) == true) {
+ wps_ie, &wps_ielen)) {
if (wps_ielen > 2) {
iwe.cmd = IWEVGENIE;
iwe.u.data.length = (u16)wps_ielen;
@@ -356,8 +357,9 @@ static int wpa_set_auth_algs(struct net_device *dev, u32 value)
Ndis802_11AuthModeOpen;
padapter->securitypriv.AuthAlgrthm = 0;
}
- } else
+ } else {
ret = -EINVAL;
+ }
return ret;
}
@@ -381,8 +383,9 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
/* for large key indices, set the default (0) */
param->u.crypt.idx = 0;
}
- } else
+ } else {
return -EINVAL;
+ }
if (strcmp(param->u.crypt.alg, "WEP") == 0) {
netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
padapter->securitypriv.ndisencryptstatus =
@@ -411,8 +414,9 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
padapter->securitypriv.XGrpPrivacy =
_WEP104_;
}
- } else
+ } else {
return -EINVAL;
+ }
pwep->KeyIndex = wep_key_idx;
pwep->KeyIndex |= 0x80000000;
memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
@@ -443,7 +447,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
struct sta_priv *pstapriv = &padapter->stapriv;
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
- WIFI_MP_STATE) == true) { /* sta mode */
+ WIFI_MP_STATE)) { /* sta mode */
psta = r8712_get_stainfo(pstapriv,
get_bssid(pmlmepriv));
if (psta) {
@@ -572,10 +576,10 @@ static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
eid = buf[cnt];
if ((eid == _VENDOR_SPECIFIC_IE_) &&
- (!memcmp(&buf[cnt+2], wps_oui, 4))) {
+ (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
padapter->securitypriv.wps_ie_len =
- ((buf[cnt+1] + 2) <
+ ((buf[cnt + 1] + 2) <
(MAX_WPA_IE_LEN << 2)) ?
(buf[cnt + 1] + 2) :
(MAX_WPA_IE_LEN << 2);
@@ -585,10 +589,11 @@ static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
padapter->securitypriv.wps_phase =
true;
netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
- cnt += buf[cnt+1]+2;
+ cnt += buf[cnt + 1] + 2;
break;
- } else
+ } else {
cnt += buf[cnt + 1] + 2;
+ }
}
}
}
@@ -609,7 +614,7 @@ static int r8711_wx_get_name(struct net_device *dev,
struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
u8 *prates;
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
true) {
/* parsing HT_CAP_IE */
p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
@@ -617,30 +622,31 @@ static int r8711_wx_get_name(struct net_device *dev,
if (p && ht_ielen > 0)
ht_cap = true;
prates = pcur_bss->rates;
- if (r8712_is_cckratesonly_included(prates) == true) {
- if (ht_cap == true)
+ if (r8712_is_cckratesonly_included(prates)) {
+ if (ht_cap)
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11bn");
else
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11b");
- } else if ((r8712_is_cckrates_included(prates)) == true) {
- if (ht_cap == true)
+ } else if (r8712_is_cckrates_included(prates)) {
+ if (ht_cap)
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11bgn");
else
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11bg");
} else {
- if (ht_cap == true)
+ if (ht_cap)
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11gn");
else
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11g");
}
- } else
+ } else {
snprintf(wrqu->name, IFNAMSIZ, "unassociated");
+ }
return 0;
}
@@ -674,14 +680,14 @@ static int r8711_wx_set_freq(struct net_device *dev,
fwrq->m = c + 1;
}
/* Setting by channel number */
- if ((fwrq->m > 14) || (fwrq->e > 0))
+ if ((fwrq->m > 14) || (fwrq->e > 0)) {
rc = -EOPNOTSUPP;
- else {
+ } else {
int channel = fwrq->m;
- if ((channel < 1) || (channel > 14))
+ if ((channel < 1) || (channel > 14)) {
rc = -EINVAL;
- else {
+ } else {
/* Yes ! We can set it !!! */
padapter->registrypriv.channel = channel;
}
@@ -697,9 +703,9 @@ static int r8711_wx_get_freq(struct net_device *dev,
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
wrqu->freq.m = ieee80211_wlan_frequencies[
- pcur_bss->Configuration.DSConfig-1] * 100000;
+ pcur_bss->Configuration.DSConfig - 1] * 100000;
wrqu->freq.e = 1;
wrqu->freq.i = pcur_bss->Configuration.DSConfig;
} else {
@@ -746,12 +752,12 @@ static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
struct _adapter *padapter = netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
wrqu->mode = IW_MODE_INFRA;
else if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
+ WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
wrqu->mode = IW_MODE_ADHOC;
- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+ else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
wrqu->mode = IW_MODE_MASTER;
else
wrqu->mode = IW_MODE_AUTO;
@@ -940,11 +946,11 @@ static int r871x_wx_set_priv(struct net_device *dev,
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct wlan_network *pcur_network = &pmlmepriv->cur_network;
/*static u8 xxxx; */
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
sprintf(ext, "%s rssi %d",
pcur_network->network.Ssid.Ssid,
/*(xxxx=xxxx+10) */
- ((padapter->recvpriv.fw_rssi)>>1)-95
+ ((padapter->recvpriv.fw_rssi) >> 1) - 95
/*pcur_network->network.Rssi */
);
} else {
@@ -1007,7 +1013,7 @@ static int r871x_wx_set_priv(struct net_device *dev,
goto FREE_EXT;
}
if (copy_to_user(dwrq->pointer, ext,
- min(dwrq->length, (__u16)(strlen(ext)+1))))
+ min(dwrq->length, (__u16)(strlen(ext) + 1))))
ret = -EFAULT;
FREE_EXT:
@@ -1044,9 +1050,9 @@ static int r8711_wx_set_wap(struct net_device *dev,
struct wlan_network *pnetwork = NULL;
enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
return -EBUSY;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
return ret;
if (temp->sa_family != ARPHRD_ETHER)
return -EINVAL;
@@ -1055,7 +1061,7 @@ static int r8711_wx_set_wap(struct net_device *dev,
phead = &queue->queue;
pmlmepriv->pscanned = phead->next;
while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
+ if (end_of_queue_search(phead, pmlmepriv->pscanned))
break;
pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
struct wlan_network, list);
@@ -1069,9 +1075,9 @@ static int r8711_wx_set_wap(struct net_device *dev,
}
spin_unlock_irqrestore(&queue->lock, irqL);
if (!ret) {
- if (!r8712_set_802_11_authentication_mode(padapter, authmode))
+ if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
ret = -ENOMEM;
- else {
+ } else {
if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
ret = -1;
}
@@ -1137,17 +1143,17 @@ static int r8711_wx_set_scan(struct net_device *dev,
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 status = true;
- if (padapter->bDriverStopped == true) {
+ if (padapter->bDriverStopped) {
netdev_info(dev, "In %s: bDriverStopped=%d\n",
__func__, padapter->bDriverStopped);
return -1;
}
- if (padapter->bup == false)
+ if (!padapter->bup)
return -ENETDOWN;
- if (padapter->hw_init_completed == false)
+ if (!padapter->hw_init_completed)
return -1;
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy == true))
+ if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
+ (pmlmepriv->sitesurveyctrl.traffic_busy))
return 0;
if (wrqu->data.length == sizeof(struct iw_scan_req)) {
struct iw_scan_req *req = (struct iw_scan_req *)extra;
@@ -1164,16 +1170,18 @@ static int r8711_wx_set_scan(struct net_device *dev,
spin_lock_irqsave(&pmlmepriv->lock, irqL);
if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
_FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
+ (pmlmepriv->sitesurveyctrl.traffic_busy)) {
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
status = false;
- } else
+ } else {
status = r8712_sitesurvey_cmd(padapter, &ssid);
+ }
spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
}
- } else
+ } else {
status = r8712_set_802_11_bssid_list_scan(padapter);
- if (status == false)
+ }
+ if (!status)
return -1;
return 0;
}
@@ -1194,7 +1202,8 @@ static int r8711_wx_get_scan(struct net_device *dev,
if (padapter->bDriverStopped)
return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
+ while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
+ _FW_UNDER_LINKING)) {
msleep(30);
cnt++;
if (cnt > 100)
@@ -1204,7 +1213,7 @@ static int r8711_wx_get_scan(struct net_device *dev,
phead = &queue->queue;
plist = phead->next;
while (1) {
- if (end_of_queue_search(phead, plist) == true)
+ if (end_of_queue_search(phead, plist))
break;
if ((stop - ev) < SCAN_ITEM_SIZE) {
ret = -E2BIG;
@@ -1304,7 +1313,7 @@ static int r8711_wx_get_essid(struct net_device *dev,
struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
u32 len, ret = 0;
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
len = pcur_bss->Ssid.SsidLength;
wrqu->essid.length = len;
memcpy(extra, pcur_bss->Ssid.Ssid, len);
@@ -1379,8 +1388,9 @@ set_rate:
datarates[i] = mpdatarate[i];
if (fixed == 0)
break;
- } else
+ } else {
datarates[i] = 0xff;
+ }
}
if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
ret = -ENOMEM;
@@ -1404,7 +1414,7 @@ static int r8711_wx_get_rate(struct net_device *dev,
u16 mcs_rate = 0;
i = 0;
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
p = r8712_get_ie(&pcur_bss->IEs[12],
_HT_CAPABILITY_IE_, &ht_ielen,
pcur_bss->IELength - 12);
@@ -1424,10 +1434,10 @@ static int r8711_wx_get_rate(struct net_device *dev,
if (rate > max_rate)
max_rate = rate;
wrqu->bitrate.fixed = 0; /* no auto select */
- wrqu->bitrate.value = rate*500000;
+ wrqu->bitrate.value = rate * 500000;
i++;
}
- if (ht_cap == true) {
+ if (ht_cap) {
if (mcs_rate & 0x8000 /* MCS15 */
&&
rf_type == RTL8712_RF_2T2R)
@@ -1439,8 +1449,9 @@ static int r8711_wx_get_rate(struct net_device *dev,
max_rate *= 2; /* Mbps/2 */
}
wrqu->bitrate.value = max_rate * 500000;
- } else
+ } else {
return -ENOLINK;
+ }
return 0;
}
@@ -1461,9 +1472,9 @@ static int r8711_wx_set_frag(struct net_device *dev,
{
struct _adapter *padapter = netdev_priv(dev);
- if (wrqu->frag.disabled)
+ if (wrqu->frag.disabled) {
padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- else {
+ } else {
if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
wrqu->frag.value > MAX_FRAG_THRESHOLD)
return -EINVAL;
@@ -1599,7 +1610,7 @@ static int r8711_wx_get_enc(struct net_device *dev,
struct iw_point *erq = &(wrqu->encoding);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
+ if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
erq->length = 0;
erq->flags |= IW_ENCODE_DISABLED;
@@ -1844,7 +1855,7 @@ static int r8711_wx_write32(struct net_device *dev,
u32 data32;
get_user(addr, (u32 __user *)wrqu->data.pointer);
- data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
+ data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
r8712_write32(padapter, addr, data32);
return 0;
}
@@ -1898,9 +1909,9 @@ static int r871x_mp_ioctl_hdl(struct net_device *dev,
ret = -EINVAL;
goto _r871x_mp_ioctl_hdl_exit;
}
- if (phandler->oid == 0 && phandler->handler)
+ if (phandler->oid == 0 && phandler->handler) {
status = phandler->handler(&oid_par);
- else if (phandler->handler) {
+ } else if (phandler->handler) {
oid_par.adapter_context = padapter;
oid_par.oid = phandler->oid;
oid_par.information_buf = poidparam->data;
@@ -1957,7 +1968,8 @@ static int r871x_get_ap_info(struct net_device *dev,
if (padapter->bDriverStopped || (pdata == NULL))
return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
+ while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
+ _FW_UNDER_LINKING)) {
msleep(30);
cnt++;
if (cnt > 100)
@@ -1967,13 +1979,14 @@ static int r871x_get_ap_info(struct net_device *dev,
if (pdata->length >= 32) {
if (copy_from_user(data, pdata->pointer, 32))
return -EINVAL;
- } else
+ } else {
return -EINVAL;
+ }
spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
phead = &queue->queue;
plist = phead->next;
while (1) {
- if (end_of_queue_search(phead, plist) == true)
+ if (end_of_queue_search(phead, plist))
break;
pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
if (!mac_pton(data, bssid)) {
@@ -1987,13 +2000,13 @@ static int r871x_get_ap_info(struct net_device *dev,
if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
/* BSSID match, then check if supporting wpa/wpa2 */
pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
- &wpa_ielen, pnetwork->network.IELength-12);
+ &wpa_ielen, pnetwork->network.IELength - 12);
if (pbuf && (wpa_ielen > 0)) {
pdata->flags = 1;
break;
}
pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
- &wpa_ielen, pnetwork->network.IELength-12);
+ &wpa_ielen, pnetwork->network.IELength - 12);
if (pbuf && (wpa_ielen > 0)) {
pdata->flags = 2;
break;
@@ -2078,7 +2091,7 @@ static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
switch (name) {
case IEEE_PARAM_WPA_ENABLED:
padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
- switch ((value)&0xff) {
+ switch ((value) & 0xff) {
case 1: /* WPA */
padapter->securitypriv.ndisauthtype =
Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
index ac0baff7f090..7c346a405a20 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
@@ -58,8 +58,9 @@ uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
*(u32 *)poid_par_priv->information_buf =
padapter->recvpriv.rx_smallpacket_crcerr;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -74,8 +75,9 @@ uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
*(u32 *)poid_par_priv->information_buf =
padapter->recvpriv.rx_middlepacket_crcerr;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -90,8 +92,9 @@ uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
*(u32 *)poid_par_priv->information_buf =
padapter->recvpriv.rx_largepacket_crcerr;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -122,8 +125,9 @@ uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
padapter->recvpriv.rx_pkts +
padapter->recvpriv.rx_drop;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -152,8 +156,9 @@ uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
*(uint *)poid_par_priv->information_buf =
padapter->recvpriv.rx_icv_err;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -182,8 +187,9 @@ uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
preamblemode = 2;
*(u32 *)poid_par_priv->information_buf = preamblemode;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -239,8 +245,9 @@ uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
padapter->registrypriv.preamble = PREAMBLE_SHORT;
*(u32 *)poid_par_priv->information_buf = preamblemode;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -269,8 +276,9 @@ uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
*(u32 *)poid_par_priv->information_buf =
padapter->xmitpriv.tx_bytes;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -287,8 +295,9 @@ uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
padapter->recvpriv.rx_bytes;
*poid_par_priv->bytes_rw = poid_par_priv->
information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -324,8 +333,8 @@ uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
pnic_Config = &pmlmepriv->cur_network.network.Configuration;
else
pnic_Config = &padapter->registrypriv.dev_network.
@@ -364,8 +373,9 @@ uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
ulInfo |= 0x0400; /* WIRELESS_MODE_A */
*(u32 *) poid_par_priv->information_buf = ulInfo;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
return RNDIS_STATUS_INVALID_LENGTH;
+ }
return RNDIS_STATUS_SUCCESS;
}
@@ -451,8 +461,9 @@ uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
(unsigned long)(*((unsigned long *)
poid_par_priv->information_buf + 2))))
status = RNDIS_STATUS_NOT_ACCEPTED;
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
return status;
}
@@ -464,10 +475,11 @@ uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len == (sizeof(unsigned long)*3)) {
- if (Adapter->mppriv.act_in_progress == true)
+ if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
+ 3)) {
+ if (Adapter->mppriv.act_in_progress) {
status = RNDIS_STATUS_NOT_ACCEPTED;
- else {
+ } else {
/* init workparam */
Adapter->mppriv.act_in_progress = true;
Adapter->mppriv.workparam.bcompleted = false;
@@ -489,8 +501,9 @@ uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
io_value))
status = RNDIS_STATUS_NOT_ACCEPTED;
}
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
return status;
}
@@ -515,11 +528,11 @@ uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
* nStatus==2 AdHocMode
* nStatus==3 NotAssociated
*/
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
ulInfo = CHECKINGSTATUS;
- else if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
+ else if (check_fwstate(pmlmepriv, _FW_LINKED))
ulInfo = ASSOCIATED;
- else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
+ else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
ulInfo = ADHOCMODE;
else
ulInfo = NOTASSOCIATED;
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
index 22262b3558ba..f772675ae9cd 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
@@ -136,12 +136,12 @@ u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid)
}
spin_lock_irqsave(&pmlmepriv->lock, irqL);
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING) == true) {
+ _FW_UNDER_LINKING)) {
status = check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
goto _Abort_Set_BSSID;
}
if (check_fwstate(pmlmepriv,
- _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
+ _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid,
ETH_ALEN)) {
if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
@@ -149,7 +149,7 @@ u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid)
* WIFI_ADHOC_MASTER_STATE */
} else {
r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
r8712_ind_disconnect(padapter);
r8712_free_assoc_resources(padapter);
if ((check_fwstate(pmlmepriv,
@@ -180,11 +180,11 @@ void r8712_set_802_11_ssid(struct _adapter *padapter,
if (!padapter->hw_init_completed)
return;
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
goto _Abort_Set_SSID;
}
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
(!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid,
ssid->SsidLength))) {
@@ -197,7 +197,7 @@ void r8712_set_802_11_ssid(struct _adapter *padapter,
*/
r8712_disassoc_cmd(padapter);
if (check_fwstate(pmlmepriv,
- _FW_LINKED) == true)
+ _FW_LINKED))
r8712_ind_disconnect(padapter);
r8712_free_assoc_resources(padapter);
if (check_fwstate(pmlmepriv,
@@ -207,24 +207,25 @@ void r8712_set_802_11_ssid(struct _adapter *padapter,
set_fwstate(pmlmepriv,
WIFI_ADHOC_STATE);
}
- } else
+ } else {
goto _Abort_Set_SSID; /* driver is in
* WIFI_ADHOC_MASTER_STATE */
+ }
}
} else {
r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
r8712_ind_disconnect(padapter);
r8712_free_assoc_resources(padapter);
if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE) == true) {
+ WIFI_ADHOC_MASTER_STATE)) {
_clr_fwstate_(pmlmepriv,
WIFI_ADHOC_MASTER_STATE);
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
}
}
}
- if (padapter->securitypriv.btkip_countermeasure == true)
+ if (padapter->securitypriv.btkip_countermeasure)
goto _Abort_Set_SSID;
if (!validate_ssid(ssid))
goto _Abort_Set_SSID;
@@ -248,13 +249,13 @@ void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
if (*pold_state != networktype) {
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
(*pold_state == Ndis802_11IBSS))
r8712_disassoc_cmd(padapter);
if (check_fwstate(pmlmepriv,
- _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true)
+ _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
r8712_free_assoc_resources(padapter);
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
(*pold_state == Ndis802_11Infrastructure) ||
(*pold_state == Ndis802_11IBSS)) {
/* will clr Linked_state before this function,
@@ -291,7 +292,7 @@ u8 r8712_set_802_11_disassociate(struct _adapter *padapter)
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
r8712_disassoc_cmd(padapter);
r8712_ind_disconnect(padapter);
r8712_free_assoc_resources(padapter);
@@ -312,8 +313,8 @@ u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter)
if (!padapter->hw_init_completed)
return false;
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
+ pmlmepriv->sitesurveyctrl.traffic_busy) {
/* Scan or linking is in progress, do nothing. */
ret = (u8)check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
} else {
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index fbcb248b0235..04f727fc95ea 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -62,8 +62,8 @@ static sint _init_mlme_priv(struct _adapter *padapter)
_init_queue(&(pmlmepriv->scanned_queue));
set_scanned_network_val(pmlmepriv, 0);
memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- pbuf = kmalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)),
- GFP_ATOMIC);
+ pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
+ GFP_ATOMIC);
if (pbuf == NULL)
return _FAIL;
pmlmepriv->free_bss_buf = pbuf;
@@ -110,7 +110,7 @@ static void _free_network(struct mlme_priv *pmlmepriv,
if (pnetwork == NULL)
return;
- if (pnetwork->fixed == true)
+ if (pnetwork->fixed)
return;
curr_time = jiffies;
delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
@@ -123,14 +123,14 @@ static void _free_network(struct mlme_priv *pmlmepriv,
spin_unlock_irqrestore(&free_queue->lock, irqL);
}
-static void _free_network_nolock(struct mlme_priv *pmlmepriv,
+static void free_network_nolock(struct mlme_priv *pmlmepriv,
struct wlan_network *pnetwork)
{
struct __queue *free_queue = &pmlmepriv->free_bss_pool;
if (pnetwork == NULL)
return;
- if (pnetwork->fixed == true)
+ if (pnetwork->fixed)
return;
list_del_init(&pnetwork->list);
list_add_tail(&pnetwork->list, &free_queue->queue);
@@ -176,7 +176,7 @@ static void _free_network_queue(struct _adapter *padapter)
spin_lock_irqsave(&scanned_queue->lock, irqL);
phead = &scanned_queue->queue;
plist = phead->next;
- while (end_of_queue_search(phead, plist) == false) {
+ while (!end_of_queue_search(phead, plist)) {
pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
plist = plist->next;
_free_network(pmlmepriv, pnetwork);
@@ -189,10 +189,11 @@ sint r8712_if_up(struct _adapter *padapter)
sint res;
if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
- (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == false)) {
+ !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
res = false;
- } else
+ } else {
res = true;
+ }
return res;
}
@@ -204,8 +205,8 @@ void r8712_generate_random_ibss(u8 *pibss)
pibss[1] = 0x11;
pibss[2] = 0x87;
pibss[3] = (u8)(curtime & 0xff);
- pibss[4] = (u8)((curtime>>8) & 0xff);
- pibss[5] = (u8)((curtime>>16) & 0xff);
+ pibss[4] = (u8)((curtime >> 8) & 0xff);
+ pibss[5] = (u8)((curtime >> 16) & 0xff);
}
uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
@@ -233,12 +234,6 @@ static struct wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
return _r8712_alloc_network(pmlmepriv);
}
-static void free_network_nolock(struct mlme_priv *pmlmepriv,
- struct wlan_network *pnetwork)
-{
- _free_network_nolock(pmlmepriv, pnetwork);
-}
-
void r8712_free_network_queue(struct _adapter *dev)
{
_free_network_queue(dev);
@@ -354,8 +349,9 @@ static void update_network(struct wlan_bssid_ex *dst,
padapter->recvpriv.signal = (u8)tmpVal;
src->Rssi = padapter->recvpriv.signal;
- } else
+ } else {
src->Rssi = (src->Rssi + dst->Rssi) / 2;
+ }
memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
}
@@ -392,7 +388,7 @@ static void update_scanned_network(struct _adapter *adapter,
plist = phead->next;
while (1) {
- if (end_of_queue_search(phead, plist) == true)
+ if (end_of_queue_search(phead, plist))
break;
pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
@@ -409,7 +405,7 @@ static void update_scanned_network(struct _adapter *adapter,
/* If we didn't find a match, then get a new network slot to initialize
* with this beacon's information */
- if (end_of_queue_search(phead, plist) == true) {
+ if (end_of_queue_search(phead, plist)) {
if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
/* If there are no more slots, expire the oldest */
pnetwork = oldest;
@@ -468,10 +464,10 @@ static int is_desired_network(struct _adapter *adapter,
int bselected = true;
struct security_priv *psecuritypriv = &adapter->securitypriv;
- if (psecuritypriv->wps_phase == true) {
+ if (psecuritypriv->wps_phase) {
if (r8712_get_wps_ie(pnetwork->network.IEs,
pnetwork->network.IELength, wps_ie,
- &wps_ielen) == true)
+ &wps_ielen))
return true;
else
return false;
@@ -479,7 +475,7 @@ static int is_desired_network(struct _adapter *adapter,
if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
(pnetwork->network.Privacy == 0))
bselected = false;
- if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE) == true) {
+ if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
if (pnetwork->network.InfrastructureMode !=
adapter->mlmepriv.cur_network.network.
InfrastructureMode)
@@ -533,7 +529,7 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
return;
spin_lock_irqsave(&pmlmepriv->lock2, flags);
/* update IBSS_network 's timestamp */
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
pnetwork->MacAddress, ETH_ALEN)) {
struct wlan_network *ibss_wlan = NULL;
@@ -551,10 +547,10 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
}
}
/* lock pmlmepriv->lock when you accessing network_q */
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == false) {
- if (pnetwork->Ssid.Ssid[0] != 0)
+ if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
+ if (pnetwork->Ssid.Ssid[0] != 0) {
rtl8711_add_network(adapter, pnetwork);
- else {
+ } else {
pnetwork->Ssid.SsidLength = 8;
memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
rtl8711_add_network(adapter, pnetwork);
@@ -571,15 +567,15 @@ void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
del_timer(&pmlmepriv->scan_to_timer);
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
}
- if (pmlmepriv->to_join == true) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
+ if (pmlmepriv->to_join) {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
if (r8712_select_and_join_from_scan(pmlmepriv)
@@ -633,7 +629,7 @@ void r8712_free_assoc_resources(struct _adapter *adapter)
pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
tgt_network->network.MacAddress);
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
struct sta_info *psta;
psta = r8712_get_stainfo(&adapter->stapriv,
@@ -645,7 +641,7 @@ void r8712_free_assoc_resources(struct _adapter *adapter)
}
if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
+ WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
r8712_free_all_stainfo(adapter);
if (pwlan)
pwlan->fixed = false;
@@ -679,7 +675,7 @@ void r8712_ind_disconnect(struct _adapter *padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
_clr_fwstate_(pmlmepriv, _FW_LINKED);
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
r8712_os_indicate_disconnect(padapter);
@@ -717,10 +713,11 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
if (!pnetwork)
return;
- memcpy((u8 *)pnetwork+16, (u8 *)pbuf + 8,
- sizeof(struct wlan_network) - 16);
- } else
+ memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
+ sizeof(struct wlan_network) - 16);
+ } else {
pnetwork = (struct wlan_network *)pbuf;
+ }
#ifdef __BIG_ENDIAN
/* endian_convert */
@@ -764,15 +761,15 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
goto ignore_joinbss_callback;
if (pnetwork->join_res > 0) {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
/*s1. find ptarget_wlan*/
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
- if (the_same_macaddr == true)
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ if (the_same_macaddr) {
ptarget_wlan =
r8712_find_network(&pmlmepriv->
scanned_queue,
cur_network->network.MacAddress);
- else {
+ } else {
pcur_wlan =
r8712_find_network(&pmlmepriv->
scanned_queue,
@@ -813,7 +810,7 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
/*s2. find ptarget_sta & update ptarget_sta*/
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (the_same_macaddr == true) {
+ if (the_same_macaddr) {
ptarget_sta =
r8712_get_stainfo(pstapriv,
pnetwork->network.MacAddress);
@@ -821,10 +818,11 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
ptarget_sta =
r8712_alloc_stainfo(pstapriv,
pnetwork->network.MacAddress);
- } else
+ } else {
ptarget_sta =
r8712_alloc_stainfo(pstapriv,
pnetwork->network.MacAddress);
+ }
if (ptarget_sta) /*update ptarget_sta*/ {
ptarget_sta->aid = pnetwork->join_res;
ptarget_sta->qos_option = 1;
@@ -897,14 +895,14 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
update_ht_cap(adapter, cur_network->network.IEs,
cur_network->network.IELength);
/*indicate connect*/
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
- == true)
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
r8712_indicate_connect(adapter);
del_timer(&pmlmepriv->assoc_timer);
- } else
+ } else {
goto ignore_joinbss_callback;
+ }
} else {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
mod_timer(&pmlmepriv->assoc_timer,
jiffies + msecs_to_jiffies(1));
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
@@ -924,7 +922,7 @@ void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
/* to do: */
- if (r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr) == false)
+ if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
return;
psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
if (psta != NULL) {
@@ -946,8 +944,8 @@ void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
psta->ieee8021x_blocked = false;
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
if (adapter->stapriv.asoc_sta_count == 2) {
/* a sta + bc/mc_stainfo (not Ibss_stainfo) */
r8712_indicate_connect(adapter);
@@ -969,7 +967,7 @@ void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
struct wlan_network *tgt_network = &pmlmepriv->cur_network;
spin_lock_irqsave(&pmlmepriv->lock, irqL2);
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
r8712_ind_disconnect(adapter);
r8712_free_assoc_resources(adapter);
}
@@ -1046,7 +1044,7 @@ void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
{
- if (adapter->securitypriv.wps_hw_pbc_pressed == false)
+ if (!adapter->securitypriv.wps_hw_pbc_pressed)
adapter->securitypriv.wps_hw_pbc_pressed = true;
}
@@ -1081,7 +1079,7 @@ void _r8712_join_timeout_handler(struct _adapter *adapter)
spin_lock_irqsave(&pmlmepriv->lock, irqL);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
pmlmepriv->to_join = false;
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
r8712_os_indicate_disconnect(adapter);
_clr_fwstate_(pmlmepriv, _FW_LINKED);
}
@@ -1131,8 +1129,8 @@ int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
phead = &queue->queue;
pmlmepriv->pscanned = phead->next;
while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned) == true) {
- if ((pmlmepriv->assoc_by_rssi == true) &&
+ if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
+ if ((pmlmepriv->assoc_by_rssi) &&
(pnetwork_max_rssi != NULL)) {
pnetwork = pnetwork_max_rssi;
goto ask_for_joinbss;
@@ -1144,7 +1142,7 @@ int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
if (pnetwork == NULL)
return _FAIL;
pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- if (pmlmepriv->assoc_by_bssid == true) {
+ if (pmlmepriv->assoc_by_bssid) {
dst_ssid = pnetwork->network.MacAddress;
src_ssid = pmlmepriv->assoc_bssid;
if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
@@ -1164,23 +1162,25 @@ int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
}
goto ask_for_joinbss;
}
- } else if (pmlmepriv->assoc_ssid.SsidLength == 0)
+ } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
goto ask_for_joinbss;
+ }
dst_ssid = pnetwork->network.Ssid.Ssid;
src_ssid = pmlmepriv->assoc_ssid.Ssid;
if ((pnetwork->network.Ssid.SsidLength ==
pmlmepriv->assoc_ssid.SsidLength) &&
(!memcmp(dst_ssid, src_ssid,
pmlmepriv->assoc_ssid.SsidLength))) {
- if (pmlmepriv->assoc_by_rssi == true) {
+ if (pmlmepriv->assoc_by_rssi) {
/* if the ssid is the same, select the bss
* which has the max rssi*/
if (pnetwork_max_rssi) {
if (pnetwork->network.Rssi >
pnetwork_max_rssi->network.Rssi)
pnetwork_max_rssi = pnetwork;
- } else
+ } else {
pnetwork_max_rssi = pnetwork;
+ }
} else if (is_desired_network(adapter, pnetwork)) {
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
r8712_disassoc_cmd(adapter);
@@ -1408,7 +1408,7 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
while (cnt < in_len) {
if (in_ie[cnt] == authmode) {
if ((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) {
+ (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
memcpy(&sec_ie[0], &in_ie[cnt],
in_ie[cnt + 1] + 2);
match = true;
@@ -1426,10 +1426,10 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
memcpy(&bkup_ie[0], &in_ie[cnt],
in_ie[cnt + 1] + 2);
}
- cnt += in_ie[cnt+1] + 2; /*get next*/
+ cnt += in_ie[cnt + 1] + 2; /*get next*/
}
/*restruct WPA IE or WPA2 IE in sec_ie[] */
- if (match == true) {
+ if (match) {
if (sec_ie[0] == _WPA_IE_ID_) {
/* parsing SSN IE to select required encryption
* algorithm, and set the bc/mc encryption algorithm */
@@ -1486,7 +1486,7 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
/*select the uncst_oui and remove
* the other uncst_oui*/
cnt = sec_ie[12];
- remove_cnt = (cnt-1) * 4;
+ remove_cnt = (cnt - 1) * 4;
sec_ie[12] = 0x01;
memcpy(&sec_ie[14], &uncst_oui[0], 4);
/*remove the other unicast suit*/
@@ -1547,7 +1547,7 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
/*select the uncst_oui and remove the
* other uncst_oui*/
cnt = sec_ie[8];
- remove_cnt = (cnt-1)*4;
+ remove_cnt = (cnt - 1) * 4;
sec_ie[8] = 0x01;
memcpy(&sec_ie[10], &uncst_oui[0], 4);
/*remove the other unicast suit*/
@@ -1555,7 +1555,7 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
&sec_ie[14 + remove_cnt],
(sec_ie[1] - 14 + 2 -
remove_cnt));
- sec_ie[1] = sec_ie[1]-remove_cnt;
+ sec_ie[1] = sec_ie[1] - remove_cnt;
}
break;
}
@@ -1566,8 +1566,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
memcpy(out_ie, in_ie, 12);
ielength = 12;
/*copy RSN or SSN*/
- if (match == true) {
- memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1]+2);
+ if (match) {
+ memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
ielength += sec_ie[1] + 2;
if (authmode == _WPA2_IE_ID_) {
/*the Pre-Authentication bit should be zero*/
@@ -1580,9 +1580,9 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
/*copy fixed ie only*/
memcpy(out_ie, in_ie, 12);
ielength = 12;
- if (psecuritypriv->wps_phase == true) {
- memcpy(out_ie+ielength, psecuritypriv->wps_ie,
- psecuritypriv->wps_ie_len);
+ if (psecuritypriv->wps_phase) {
+ memcpy(out_ie + ielength, psecuritypriv->wps_ie,
+ psecuritypriv->wps_ie_len);
ielength += psecuritypriv->wps_ie_len;
}
}
@@ -1696,11 +1696,11 @@ unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
phtpriv->ht_option = 0;
- p = r8712_get_ie(in_ie+12, _HT_CAPABILITY_IE_, &ielen, in_len-12);
+ p = r8712_get_ie(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
if (p && (ielen > 0)) {
if (pqospriv->qos_option == 0) {
out_len = *pout_len;
- r8712_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_,
+ r8712_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_,
_WMM_IE_Length_, WMM_IE, pout_len);
pqospriv->qos_option = 1;
}
@@ -1714,7 +1714,7 @@ unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
IEEE80211_HT_CAP_DSSSCCK40;
ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR &
0x03) | (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
- r8712_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_,
+ r8712_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_,
sizeof(struct ieee80211_ht_cap),
(unsigned char *)&ht_capie, pout_len);
phtpriv->ht_option = 1;
@@ -1738,7 +1738,7 @@ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
if (!phtpriv->ht_option)
return;
/* maybe needs check if ap supports rx ampdu. */
- if ((phtpriv->ampdu_enable == false) &&
+ if (!phtpriv->ampdu_enable &&
(pregistrypriv->ampdu_enable == 1))
phtpriv->ampdu_enable = true;
/*check Max Rx A-MPDU Size*/
@@ -1748,11 +1748,11 @@ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
&len, ie_len -
sizeof(struct NDIS_802_11_FIXED_IEs));
if (p && len > 0) {
- pht_capie = (struct ieee80211_ht_cap *)(p+2);
+ pht_capie = (struct ieee80211_ht_cap *)(p + 2);
max_ampdu_sz = (pht_capie->ampdu_params_info &
IEEE80211_HT_CAP_AMPDU_FACTOR);
/* max_ampdu_sz (kbytes); */
- max_ampdu_sz = 1 << (max_ampdu_sz+3);
+ max_ampdu_sz = 1 << (max_ampdu_sz + 3);
phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
}
/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
@@ -1780,7 +1780,7 @@ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
len = 0;
p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
_HT_ADD_INFO_IE_, &len,
- ie_len-sizeof(struct NDIS_802_11_FIXED_IEs));
+ ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
}
void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
@@ -1788,8 +1788,8 @@ void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable == true)) {
- if (phtpriv->baddbareq_issued[priority] == false) {
+ if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
+ if (!phtpriv->baddbareq_issued[priority]) {
r8712_addbareq_cmd(padapter, (u8)priority);
phtpriv->baddbareq_issued[priority] = true;
}
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h
index 08d6c986c11e..61e0eb745d21 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.h
+++ b/drivers/staging/rtl8712/rtl871x_mlme.h
@@ -153,7 +153,7 @@ static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state)
unsigned long irqL;
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, state) == true)
+ if (check_fwstate(pmlmepriv, state))
pmlmepriv->fw_state ^= state;
spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
}
diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c
index 26201ea3cca6..44da4fe89381 100644
--- a/drivers/staging/rtl8712/rtl871x_mp.c
+++ b/drivers/staging/rtl8712/rtl871x_mp.c
@@ -211,19 +211,18 @@ static u32 bitshift(u32 bitmask)
u32 i;
for (i = 0; i <= 31; i++)
- if (((bitmask>>i) & 0x1) == 1)
+ if (((bitmask >> i) & 0x1) == 1)
break;
return i;
}
static u32 get_bb_reg(struct _adapter *pAdapter, u16 offset, u32 bitmask)
{
- u32 org_value, bit_shift, new_value;
+ u32 org_value, bit_shift;
org_value = r8712_bb_reg_read(pAdapter, offset);
bit_shift = bitshift(bitmask);
- new_value = (org_value & bitmask) >> bit_shift;
- return new_value;
+ return (org_value & bitmask) >> bit_shift;
}
static u8 set_bb_reg(struct _adapter *pAdapter,
@@ -237,20 +236,20 @@ static u8 set_bb_reg(struct _adapter *pAdapter,
org_value = r8712_bb_reg_read(pAdapter, offset);
bit_shift = bitshift(bitmask);
new_value = ((org_value & (~bitmask)) | (value << bit_shift));
- } else
+ } else {
new_value = value;
+ }
return r8712_bb_reg_write(pAdapter, offset, new_value);
}
static u32 get_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset,
u32 bitmask)
{
- u32 org_value, bit_shift, new_value;
+ u32 org_value, bit_shift;
org_value = r8712_rf_reg_read(pAdapter, path, offset);
bit_shift = bitshift(bitmask);
- new_value = (org_value & bitmask) >> bit_shift;
- return new_value;
+ return (org_value & bitmask) >> bit_shift;
}
static u8 set_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset, u32 bitmask,
@@ -262,8 +261,9 @@ static u8 set_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset, u32 bitmask,
org_value = r8712_rf_reg_read(pAdapter, path, offset);
bit_shift = bitshift(bitmask);
new_value = ((org_value & (~bitmask)) | (value << bit_shift));
- } else
+ } else {
new_value = value;
+ }
return r8712_rf_reg_write(pAdapter, path, offset, new_value);
}
@@ -305,7 +305,8 @@ static void SetOFDMTxPower(struct _adapter *pAdapter, u8 TxPower)
{
u32 TxAGC = 0;
- TxAGC |= ((TxPower<<24)|(TxPower<<16)|(TxPower<<8)|TxPower);
+ TxAGC |= ((TxPower << 24) | (TxPower << 16) | (TxPower << 8) |
+ TxPower);
set_bb_reg(pAdapter, rTxAGC_Rate18_06, bTxAGCRate18_06, TxAGC);
set_bb_reg(pAdapter, rTxAGC_Rate54_24, bTxAGCRate54_24, TxAGC);
set_bb_reg(pAdapter, rTxAGC_Mcs03_Mcs00, bTxAGCRateMCS3_MCS0, TxAGC);
@@ -326,12 +327,12 @@ void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset)
{
u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D, tmpAGC;
- TxAGCOffset_B = (ulTxAGCOffset&0x000000ff);
- TxAGCOffset_C = (ulTxAGCOffset & 0x0000ff00)>>8;
- TxAGCOffset_D = (ulTxAGCOffset & 0x00ff0000)>>16;
- tmpAGC = (TxAGCOffset_D<<8 | TxAGCOffset_C<<4 | TxAGCOffset_B);
+ TxAGCOffset_B = (ulTxAGCOffset & 0x000000ff);
+ TxAGCOffset_C = (ulTxAGCOffset & 0x0000ff00) >> 8;
+ TxAGCOffset_D = (ulTxAGCOffset & 0x00ff0000) >> 16;
+ tmpAGC = (TxAGCOffset_D << 8 | TxAGCOffset_C << 4 | TxAGCOffset_B);
set_bb_reg(pAdapter, rFPGA0_TxGainStage,
- (bXBTxAGC|bXCTxAGC|bXDTxAGC), tmpAGC);
+ (bXBTxAGC | bXCTxAGC | bXDTxAGC), tmpAGC);
}
void r8712_SetDataRate(struct _adapter *pAdapter)
@@ -377,7 +378,7 @@ void r8712_SwitchBandwidth(struct _adapter *pAdapter)
* Set Control channel to upper or lower. These settings are
* required only for 40MHz */
set_bb_reg(pAdapter, rCCK0_System, bCCKSideBand,
- (HAL_PRIME_CHNL_OFFSET_DONT_CARE>>1));
+ (HAL_PRIME_CHNL_OFFSET_DONT_CARE >> 1));
set_bb_reg(pAdapter, rOFDM1_LSTF, 0xC00,
HAL_PRIME_CHNL_OFFSET_DONT_CARE);
set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x18);
@@ -490,12 +491,6 @@ void r8712_SwitchAntenna(struct _adapter *pAdapter)
set_bb_reg(pAdapter, rCCK0_AFESetting, bMaskByte3, cck_ant_sel_val);
}
-void r8712_SetCrystalCap(struct _adapter *pAdapter)
-{
- set_bb_reg(pAdapter, rFPGA0_AnalogParameter1, bXtalCap,
- pAdapter->mppriv.curr_crystalcap);
-}
-
static void TriggerRFThermalMeter(struct _adapter *pAdapter)
{
/* 0x24: RF Reg[6:5] */
diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h
index 75893f225dc0..3f3b2e73b7d2 100644
--- a/drivers/staging/rtl8712/rtl871x_mp.h
+++ b/drivers/staging/rtl8712/rtl871x_mp.h
@@ -272,7 +272,6 @@ void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset);
void r8712_SetDataRate(struct _adapter *pAdapter);
void r8712_SwitchBandwidth(struct _adapter *pAdapter);
void r8712_SwitchAntenna(struct _adapter *pAdapter);
-void r8712_SetCrystalCap(struct _adapter *pAdapter);
void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value);
void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart);
void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart);
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
index 77f01bf1ca3c..b98a596757f5 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
+++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
@@ -56,8 +56,9 @@ uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
Adapter->registrypriv.wireless_mode;
*poid_par_priv->bytes_rw =
poid_par_priv->information_buf_len;
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
} else {
status = RNDIS_STATUS_NOT_ACCEPTED;
}
@@ -178,10 +179,11 @@ static int mp_start_test(struct _adapter *padapter)
if (length % 4) {
/*round up to multiple of 4 bytes.*/
bssid.Length = ((length >> 2) + 1) << 2;
- } else
+ } else {
bssid.Length = length;
+ }
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
goto end_of_mp_start_test;
/*init mp_start_test status*/
pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
@@ -223,7 +225,7 @@ static int mp_stop_test(struct _adapter *padapter)
unsigned long irqL;
spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
+ if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
goto end_of_mp_stop_test;
/* 3 1. disconnect psudo AdHoc */
r8712_os_indicate_disconnect(padapter);
@@ -247,9 +249,9 @@ int mp_start_joinbss(struct _adapter *padapter, struct ndis_802_11_ssid *pssid)
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
unsigned char res = _SUCCESS;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
+ if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
return _FAIL;
- if (check_fwstate(pmlmepriv, _FW_LINKED) == false)
+ if (!check_fwstate(pmlmepriv, _FW_LINKED))
return _FAIL;
_clr_fwstate_(pmlmepriv, _FW_LINKED);
res = r8712_setassocsta_cmd(padapter, pmppriv->network_macaddr);
@@ -293,7 +295,7 @@ uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
r8712_write8(Adapter, MSR, 1); /* Link in ad hoc network, 0x1025004C */
r8712_write8(Adapter, RCR, 0); /* RCR : disable all pkt, 0x10250048 */
/* RCR disable Check BSSID, 0x1025004a */
- r8712_write8(Adapter, RCR+2, 0x57);
+ r8712_write8(Adapter, RCR + 2, 0x57);
/* disable RX filter map , mgt frames will put in RX FIFO 0 */
r8712_write16(Adapter, RXFLTMAP0, 0x0);
val8 = r8712_read8(Adapter, EE_9346CR);
@@ -388,8 +390,9 @@ uint oid_rt_pro_query_tx_packet_sent_hdl(
*(u32 *)poid_par_priv->information_buf =
Adapter->mppriv.tx_pktcount;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
return status;
}
@@ -408,8 +411,9 @@ uint oid_rt_pro_query_rx_packet_received_hdl(
*(u32 *)poid_par_priv->information_buf =
Adapter->mppriv.rx_pktcount;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
return status;
}
@@ -428,8 +432,9 @@ uint oid_rt_pro_query_rx_packet_crc32_error_hdl(
*(u32 *)poid_par_priv->information_buf =
Adapter->mppriv.rx_crcerrpktcount;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
return status;
}
@@ -457,8 +462,9 @@ uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv
if (poid_par_priv->information_buf_len == sizeof(u32)) {
Adapter->mppriv.rx_pktcount = 0;
Adapter->mppriv.rx_crcerrpktcount = 0;
- } else
+ } else {
status = RNDIS_STATUS_INVALID_LENGTH;
+ }
return status;
}
@@ -684,7 +690,7 @@ uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
- if (Adapter->mppriv.act_in_progress == true)
+ if (Adapter->mppriv.act_in_progress)
return RNDIS_STATUS_NOT_ACCEPTED;
if (poid_par_priv->information_buf_len < sizeof(u8))
@@ -728,7 +734,7 @@ uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
if ((addr > 511) || (cnts < 1) || (cnts > 512) || (addr + cnts) >
EFUSE_MAX_SIZE)
return RNDIS_STATUS_NOT_ACCEPTED;
- if (r8712_efuse_access(Adapter, true, addr, cnts, data) == false)
+ if (!r8712_efuse_access(Adapter, true, addr, cnts, data))
status = RNDIS_STATUS_FAILURE;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
return status;
@@ -756,7 +762,7 @@ uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
if ((addr > 511) || (cnts < 1) || (cnts > 512) ||
(addr + cnts) > r8712_efuse_get_max_size(Adapter))
return RNDIS_STATUS_NOT_ACCEPTED;
- if (r8712_efuse_access(Adapter, false, addr, cnts, data) == false)
+ if (!r8712_efuse_access(Adapter, false, addr, cnts, data))
status = RNDIS_STATUS_FAILURE;
return status;
}
@@ -824,7 +830,7 @@ uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
status = RNDIS_STATUS_FAILURE;
} else {
/* SET_OID */
- if (r8712_efuse_reg_init(Adapter) == true) {
+ if (r8712_efuse_reg_init(Adapter)) {
if (r8712_efuse_map_write(Adapter, 0,
EFUSE_MAP_MAX_SIZE, data))
*poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
@@ -879,7 +885,7 @@ uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv
rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
break;
case RX_PKT_PHY_MATCH:
- rcr_val32 |= (RCR_APM|RCR_ACRC32);
+ rcr_val32 |= (RCR_APM | RCR_ACRC32);
break;
default:
rcr_val32 &= ~(RCR_AAP |
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
index 9bc04f474d18..bf10d6db50e8 100644
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c
+++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
@@ -44,8 +44,7 @@ void r8712_set_rpwm(struct _adapter *padapter, u8 val8)
if (pwrpriv->rpwm_retry == 0)
return;
}
- if ((padapter->bDriverStopped == true) ||
- (padapter->bSurpriseRemoved == true))
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
return;
rpwm = val8 | pwrpriv->tog;
switch (val8) {
@@ -129,8 +128,7 @@ static void _rpwm_check_handler (struct _adapter *padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- if (padapter->bDriverStopped == true ||
- padapter->bSurpriseRemoved == true)
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
return;
if (pwrpriv->cpwm != pwrpriv->rpwm)
schedule_work(&pwrpriv->rpwm_workitem);
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index 046a46c4cd7f..4ff530155187 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -83,7 +83,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv,
precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
RXFRAME_ALIGN_SZ -
((addr_t)(precvpriv->pallocated_frame_buf) &
- (RXFRAME_ALIGN_SZ-1));
+ (RXFRAME_ALIGN_SZ - 1));
precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
for (i = 0; i < NR_RECVFRAME; i++) {
INIT_LIST_HEAD(&(precvframe->u.list));
@@ -112,9 +112,9 @@ union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
struct recv_priv *precvpriv;
spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
- if (list_empty(&pfree_recv_queue->queue))
+ if (list_empty(&pfree_recv_queue->queue)) {
precvframe = NULL;
- else {
+ } else {
phead = &pfree_recv_queue->queue;
plist = phead->next;
precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
@@ -147,7 +147,7 @@ void r8712_free_recvframe_queue(struct __queue *pframequeue,
spin_lock(&pframequeue->lock);
phead = &pframequeue->queue;
plist = phead->next;
- while (end_of_queue_search(phead, plist) == false) {
+ while (!end_of_queue_search(phead, plist)) {
precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
plist = plist->next;
r8712_free_recvframe(precvframe, pfree_recv_queue);
@@ -178,10 +178,11 @@ sint r8712_recvframe_chkmic(struct _adapter *adapter,
idx = iv[3];
mickey = &psecuritypriv->XGrprxmickey[(((idx >>
6) & 0x3)) - 1].skey[0];
- if (psecuritypriv->binstallGrpkey == false)
+ if (!psecuritypriv->binstallGrpkey)
return _FAIL;
- } else
+ } else {
mickey = &stainfo->tkiprxmickey.skey[0];
+ }
/*icv_len included the mic code*/
datalen = precvframe->u.hdr.len - prxattrib->hdrlen -
prxattrib->iv_len - prxattrib->icv_len - 8;
@@ -197,16 +198,15 @@ sint r8712_recvframe_chkmic(struct _adapter *adapter,
if (miccode[i] != *(pframemic + i))
bmic_err = true;
}
- if (bmic_err == true) {
- if (prxattrib->bdecrypted == true)
+ if (bmic_err) {
+ if (prxattrib->bdecrypted)
r8712_handle_tkip_mic_err(adapter,
(u8)IS_MCAST(prxattrib->ra));
res = _FAIL;
} else {
/* mic checked ok */
- if ((psecuritypriv->bcheck_grpkey ==
- false) && (IS_MCAST(prxattrib->ra) ==
- true))
+ if (!psecuritypriv->bcheck_grpkey &&
+ IS_MCAST(prxattrib->ra))
psecuritypriv->bcheck_grpkey = true;
}
recvframe_pull_tail(precvframe, 8);
@@ -224,7 +224,7 @@ union recv_frame *r8712_decryptor(struct _adapter *padapter,
union recv_frame *return_packet = precv_frame;
if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) ||
- (psecuritypriv->sw_decrypt == true))) {
+ psecuritypriv->sw_decrypt)) {
psecuritypriv->hw_decrypted = false;
switch (prxattrib->encrypt) {
case _WEP40_:
@@ -240,8 +240,9 @@ union recv_frame *r8712_decryptor(struct _adapter *padapter,
default:
break;
}
- } else if (prxattrib->bdecrypted == 1)
+ } else if (prxattrib->bdecrypted == 1) {
psecuritypriv->hw_decrypted = true;
+ }
return return_packet;
}
/*###set the security information in the recv_frame */
@@ -271,9 +272,9 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
if ((psta != NULL) && (psta->ieee8021x_blocked)) {
/* blocked
* only accept EAPOL frame */
- if (ether_type == 0x888e)
+ if (ether_type == 0x888e) {
prtnframe = precv_frame;
- else {
+ } else {
/*free this frame*/
r8712_free_recvframe(precv_frame,
&adapter->recvpriv.free_recv_queue);
@@ -290,8 +291,9 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
prtnframe = precv_frame;
}
}
- } else
+ } else {
prtnframe = precv_frame;
+ }
return prtnframe;
}
@@ -299,7 +301,7 @@ static sint recv_decache(union recv_frame *precv_frame, u8 bretry,
struct stainfo_rxcache *prxcache)
{
sint tid = precv_frame->u.hdr.attrib.priority;
- u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
+ u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |
(precv_frame->u.hdr.attrib.frag_num & 0xf);
if (tid > 15)
@@ -324,8 +326,8 @@ static sint sta2sta_data_frame(struct _adapter *adapter,
u8 *sta_addr = NULL;
sint bmcast = IS_MCAST(pattrib->dst);
- if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
/* filter packets that SA is myself or multicast or broadcast */
if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
return _FAIL;
@@ -336,13 +338,13 @@ static sint sta2sta_data_frame(struct _adapter *adapter,
(memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
return _FAIL;
sta_addr = pattrib->src;
- } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
+ } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
/* For Station mode, sa and bssid should always be BSSID,
* and DA is my mac-address */
if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
return _FAIL;
sta_addr = pattrib->bssid;
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
if (bmcast) {
/* For AP mode, if DA == MCAST, then BSSID should
* be also MCAST */
@@ -355,21 +357,22 @@ static sint sta2sta_data_frame(struct _adapter *adapter,
return _FAIL;
sta_addr = pattrib->src;
}
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
sta_addr = mybssid;
- } else
+ } else {
ret = _FAIL;
+ }
if (bmcast)
*psta = r8712_get_bcmc_stainfo(adapter);
else
*psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */
if (*psta == NULL) {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
adapter->mppriv.rx_pktloss++;
return _FAIL;
}
@@ -388,8 +391,8 @@ static sint ap2sta_data_frame(struct _adapter *adapter,
u8 *myhwaddr = myid(&adapter->eeprompriv);
sint bmcast = IS_MCAST(pattrib->dst);
- if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
- && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
/* if NULL-frame, drop packet */
if ((GetFrameSubType(ptr)) == WIFI_DATA_NULL)
return _FAIL;
@@ -419,8 +422,8 @@ static sint ap2sta_data_frame(struct _adapter *adapter,
*psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
if (*psta == NULL)
return _FAIL;
- } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
- (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
@@ -430,8 +433,9 @@ static sint ap2sta_data_frame(struct _adapter *adapter,
*psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
if (*psta == NULL)
return _FAIL;
- } else
+ } else {
return _FAIL;
+ }
return _SUCCESS;
}
@@ -444,7 +448,7 @@ static sint sta2ap_data_frame(struct _adapter *adapter,
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
unsigned char *mybssid = get_bssid(pmlmepriv);
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
/* For AP mode, if DA is non-MCAST, then it must be BSSID,
* and bssid == BSSID
* For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR */
@@ -630,10 +634,10 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe)
rmv_len = pattrib->hdrlen + pattrib->iv_len +
(bsnaphdr ? SNAP_SIZE : 0);
len = precvframe->u.hdr.len - rmv_len;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
ptr += rmv_len;
*ptr = 0x87;
- *(ptr+1) = 0x12;
+ *(ptr + 1) = 0x12;
/* append rx status for mp test packets */
ptr = recvframe_pull(precvframe, (rmv_len -
sizeof(struct ethhdr) + 2) - 24);
@@ -644,7 +648,7 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe)
sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
memcpy(ptr, pattrib->dst, ETH_ALEN);
- memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
+ memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
if (!bsnaphdr) {
len = htons(len);
memcpy(ptr + 12, &len, 2);
diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c
index 862792826dc5..09242425dad4 100644
--- a/drivers/staging/rtl8712/rtl871x_security.c
+++ b/drivers/staging/rtl8712/rtl871x_security.c
@@ -175,22 +175,22 @@ void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
return;
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr+TXDESC_OFFSET;
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
/*start to encrypt each fragment*/
if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
keylength = psecuritypriv->DefKeylen[psecuritypriv->
PrivacyKeyIndex];
for (curfragnum = 0; curfragnum < pattrib->nr_frags;
curfragnum++) {
- iv = pframe+pattrib->hdrlen;
+ iv = pframe + pattrib->hdrlen;
memcpy(&wepkey[0], iv, 3);
memcpy(&wepkey[3], &psecuritypriv->DefKey[
psecuritypriv->PrivacyKeyIndex].skey[0],
keylength);
- payload = pframe+pattrib->iv_len+pattrib->hdrlen;
+ payload = pframe + pattrib->iv_len + pattrib->hdrlen;
if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz-pattrib->
- hdrlen-pattrib->iv_len -
+ length = pattrib->last_txcmdsz - pattrib->
+ hdrlen - pattrib->iv_len -
pattrib->icv_len;
*((u32 *)crc) = cpu_to_le32(getcrc32(
payload, length));
@@ -200,14 +200,15 @@ void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
arcfour_encrypt(&mycontext, payload + length,
crc, 4);
} else {
- length = pxmitpriv->frag_len-pattrib->hdrlen -
- pattrib->iv_len-pattrib->icv_len;
+ length = pxmitpriv->frag_len -
+ pattrib->hdrlen - pattrib->iv_len -
+ pattrib->icv_len;
*((u32 *)crc) = cpu_to_le32(getcrc32(
payload, length));
arcfour_init(&mycontext, wepkey, 3 + keylength);
arcfour_encrypt(&mycontext, payload, payload,
length);
- arcfour_encrypt(&mycontext, payload+length,
+ arcfour_encrypt(&mycontext, payload + length,
crc, 4);
pframe += pxmitpriv->frag_len;
pframe = (u8 *)RND4((addr_t)(pframe));
@@ -241,8 +242,8 @@ void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe)
psecuritypriv->PrivacyKeyIndex].skey[0],
keylength);
length = ((union recv_frame *)precvframe)->
- u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
- payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
+ u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len;
+ payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
/* decrypt payload include icv */
arcfour_init(&mycontext, wepkey, 3 + keylength);
arcfour_encrypt(&mycontext, payload, payload, length);
@@ -495,11 +496,11 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
/* Now compute an unbalanced Feistel cipher with 80-bit block */
/* size on the 80-bit block P1K[], using the 128-bit key TK[] */
for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add is mod 2**16 */
- p1k[0] += _S_(p1k[4] ^ TK16((i&1) + 0));
- p1k[1] += _S_(p1k[0] ^ TK16((i&1) + 2));
- p1k[2] += _S_(p1k[1] ^ TK16((i&1) + 4));
- p1k[3] += _S_(p1k[2] ^ TK16((i&1) + 6));
- p1k[4] += _S_(p1k[3] ^ TK16((i&1) + 0));
+ p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0));
+ p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2));
+ p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4));
+ p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6));
+ p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0));
p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
}
}
@@ -587,7 +588,7 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
return _FAIL;
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr+TXDESC_OFFSET;
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
/* 4 start to encrypt each fragment */
if (pattrib->encrypt == _TKIP_) {
if (pattrib->psta)
@@ -600,7 +601,7 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
for (curfragnum = 0; curfragnum < pattrib->nr_frags;
curfragnum++) {
iv = pframe + pattrib->hdrlen;
- payload = pframe+pattrib->iv_len +
+ payload = pframe + pattrib->iv_len +
pattrib->hdrlen;
GET_TKIP_PN(iv, txpn);
pnl = (u16)(txpn.val);
@@ -612,7 +613,8 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
if ((curfragnum + 1) == pattrib->nr_frags) {
/* 4 the last fragment */
length = pattrib->last_txcmdsz -
- pattrib->hdrlen-pattrib->iv_len -
+ pattrib->hdrlen -
+ pattrib->iv_len -
pattrib->icv_len;
*((u32 *)crc) = cpu_to_le32(
getcrc32(payload, length));
@@ -622,22 +624,25 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
arcfour_encrypt(&mycontext, payload +
length, crc, 4);
} else {
- length = pxmitpriv->frag_len-pattrib->
- hdrlen-pattrib->
- iv_len-pattrib->icv_len;
+ length = pxmitpriv->frag_len -
+ pattrib->hdrlen -
+ pattrib->iv_len -
+ pattrib->icv_len;
*((u32 *)crc) = cpu_to_le32(getcrc32(
payload, length));
arcfour_init(&mycontext, rc4key, 16);
arcfour_encrypt(&mycontext, payload,
payload, length);
arcfour_encrypt(&mycontext,
- payload+length, crc, 4);
+ payload + length, crc,
+ 4);
pframe += pxmitpriv->frag_len;
pframe = (u8 *)RND4((addr_t)(pframe));
}
}
- } else
+ } else {
res = _FAIL;
+ }
}
return res;
}
@@ -666,8 +671,9 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe)
stainfo = r8712_get_stainfo(&padapter->stapriv,
&prxattrib->ta[0]);
if (stainfo != NULL) {
- iv = pframe+prxattrib->hdrlen;
- payload = pframe+prxattrib->iv_len + prxattrib->hdrlen;
+ iv = pframe + prxattrib->hdrlen;
+ payload = pframe + prxattrib->iv_len +
+ prxattrib->hdrlen;
length = ((union recv_frame *)precvframe)->
u.hdr.len - prxattrib->hdrlen -
prxattrib->iv_len;
@@ -675,10 +681,11 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe)
idx = iv[3];
prwskey = &psecuritypriv->XGrpKey[
((idx >> 6) & 0x3) - 1].skey[0];
- if (psecuritypriv->binstallGrpkey == false)
+ if (!psecuritypriv->binstallGrpkey)
return _FAIL;
- } else
+ } else {
prwskey = &stainfo->x_UncstKey.skey[0];
+ }
GET_TKIP_PN(iv, txpn);
pnl = (u16)(txpn.val);
pnh = (u32)(txpn.val >> 16);
@@ -696,8 +703,9 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe)
crc[1] != payload[length - 3] ||
crc[0] != payload[length - 4])
return _FAIL;
- } else
+ } else {
return _FAIL;
+ }
}
return _SUCCESS;
}
@@ -851,7 +859,7 @@ static void mix_column(u8 *in, u8 *out)
andf7[3] = in[3] & 0x7f;
for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
andf7[i] = andf7[i] << 1;
- if ((andf7[i-1] & 0x80) == 0x80)
+ if ((andf7[i - 1] & 0x80) == 0x80)
andf7[i] = (andf7[i] | 0x01);
}
andf7[0] = andf7[0] << 1;
@@ -1069,14 +1077,15 @@ static sint aes_cipher(u8 *key, uint hdrlen,
if (hdrlen != WLAN_HDR_A3_QOS_LEN)
hdrlen += 2;
qc_exists = 1;
- } else
+ } else {
qc_exists = 0;
+ }
pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen+1];
- pn_vector[2] = pframe[hdrlen+4];
- pn_vector[3] = pframe[hdrlen+5];
- pn_vector[4] = pframe[hdrlen+6];
- pn_vector[5] = pframe[hdrlen+7];
+ pn_vector[1] = pframe[hdrlen + 1];
+ pn_vector[2] = pframe[hdrlen + 4];
+ pn_vector[3] = pframe[hdrlen + 5];
+ pn_vector[4] = pframe[hdrlen + 6];
+ pn_vector[5] = pframe[hdrlen + 7];
construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
construct_mic_header1(mic_header1, hdrlen, pframe);
construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
@@ -1108,7 +1117,7 @@ static sint aes_cipher(u8 *key, uint hdrlen,
mic[j] = aes_out[j];
/* Insert MIC into payload */
for (j = 0; j < 8; j++)
- pframe[payload_index+j] = mic[j];
+ pframe[payload_index + j] = mic[j];
payload_index = hdrlen + 8;
for (i = 0; i < num_blocks; i++) {
construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
@@ -1121,11 +1130,11 @@ static sint aes_cipher(u8 *key, uint hdrlen,
if (payload_remainder > 0) { /* If short final block, then pad it,*/
/* encrypt and copy unpadded part back */
construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, num_blocks+1);
+ pframe, pn_vector, num_blocks + 1);
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index+j];
+ padded_buffer[j] = pframe[payload_index + j];
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, padded_buffer, chain_buffer);
for (j = 0; j < payload_remainder; j++)
@@ -1137,7 +1146,7 @@ static sint aes_cipher(u8 *key, uint hdrlen,
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < 8; j++)
- padded_buffer[j] = pframe[j+hdrlen+8+plen];
+ padded_buffer[j] = pframe[j + hdrlen + 8 + plen];
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, padded_buffer, chain_buffer);
for (j = 0; j < 8; j++)
@@ -1188,8 +1197,9 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe)
pframe = (u8 *)RND4((addr_t)(pframe));
}
}
- } else
+ } else {
res = _FAIL;
+ }
}
return res;
}
@@ -1224,13 +1234,13 @@ static sint aes_decipher(u8 *key, uint hdrlen,
/* start to decrypt the payload */
/*(plen including llc, payload and mic) */
num_blocks = (plen - 8) / 16;
- payload_remainder = (plen-8) % 16;
+ payload_remainder = (plen - 8) % 16;
pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen+1];
- pn_vector[2] = pframe[hdrlen+4];
- pn_vector[3] = pframe[hdrlen+5];
- pn_vector[4] = pframe[hdrlen+6];
- pn_vector[5] = pframe[hdrlen+7];
+ pn_vector[1] = pframe[hdrlen + 1];
+ pn_vector[2] = pframe[hdrlen + 4];
+ pn_vector[3] = pframe[hdrlen + 5];
+ pn_vector[4] = pframe[hdrlen + 6];
+ pn_vector[5] = pframe[hdrlen + 7];
if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
a4_exists = 0;
else
@@ -1264,7 +1274,7 @@ static sint aes_decipher(u8 *key, uint hdrlen,
if (payload_remainder > 0) { /* If short final block, pad it,*/
/* encrypt it and copy the unpadded part back */
construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, num_blocks+1);
+ pframe, pn_vector, num_blocks + 1);
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++)
@@ -1277,12 +1287,12 @@ static sint aes_decipher(u8 *key, uint hdrlen,
/* start to calculate the mic */
memcpy((void *)message, pframe, (hdrlen + plen + 8));
pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen+1];
- pn_vector[2] = pframe[hdrlen+4];
- pn_vector[3] = pframe[hdrlen+5];
- pn_vector[4] = pframe[hdrlen+6];
- pn_vector[5] = pframe[hdrlen+7];
- construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen-8,
+ pn_vector[1] = pframe[hdrlen + 1];
+ pn_vector[2] = pframe[hdrlen + 4];
+ pn_vector[3] = pframe[hdrlen + 5];
+ pn_vector[4] = pframe[hdrlen + 6];
+ pn_vector[5] = pframe[hdrlen + 7];
+ construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8,
pn_vector);
construct_mic_header1(mic_header1, hdrlen, message);
construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
@@ -1314,7 +1324,7 @@ static sint aes_decipher(u8 *key, uint hdrlen,
mic[j] = aes_out[j];
/* Insert MIC into payload */
for (j = 0; j < 8; j++)
- message[payload_index+j] = mic[j];
+ message[payload_index + j] = mic[j];
payload_index = hdrlen + 8;
for (i = 0; i < num_blocks; i++) {
construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
@@ -1327,7 +1337,7 @@ static sint aes_decipher(u8 *key, uint hdrlen,
if (payload_remainder > 0) { /* If short final block, pad it,*/
/* encrypt and copy unpadded part back */
construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- message, pn_vector, num_blocks+1);
+ message, pn_vector, num_blocks + 1);
for (j = 0; j < 16; j++)
padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++)
@@ -1370,21 +1380,24 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe)
&prxattrib->ta[0]);
if (stainfo != NULL) {
if (IS_MCAST(prxattrib->ra)) {
- iv = pframe+prxattrib->hdrlen;
+ iv = pframe + prxattrib->hdrlen;
idx = iv[3];
prwskey = &psecuritypriv->XGrpKey[
((idx >> 6) & 0x3) - 1].skey[0];
- if (psecuritypriv->binstallGrpkey == false)
+ if (!psecuritypriv->binstallGrpkey)
return _FAIL;
- } else
+ } else {
prwskey = &stainfo->x_UncstKey.skey[0];
+ }
length = ((union recv_frame *)precvframe)->
- u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+ u.hdr.len - prxattrib->hdrlen -
+ prxattrib->iv_len;
aes_decipher(prwskey, prxattrib->hdrlen, pframe,
length);
- } else
+ } else {
return _FAIL;
+ }
}
return _SUCCESS;
}
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
index 6ae8cdc1bfd1..162e61c6ea06 100644
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
@@ -83,7 +83,7 @@ static void mfree_all_stainfo(struct sta_priv *pstapriv)
spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
phead = &pstapriv->free_sta_queue.queue;
plist = phead->next;
- while ((end_of_queue_search(phead, plist)) == false)
+ while (!end_of_queue_search(phead, plist))
plist = plist->next;
spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
@@ -117,9 +117,9 @@ struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
pfree_sta_queue = &pstapriv->free_sta_queue;
spin_lock_irqsave(&(pfree_sta_queue->lock), flags);
- if (list_empty(&pfree_sta_queue->queue))
+ if (list_empty(&pfree_sta_queue->queue)) {
psta = NULL;
- else {
+ } else {
psta = LIST_CONTAINOR(pfree_sta_queue->queue.next,
struct sta_info, list);
list_del_init(&(psta->list));
@@ -222,7 +222,7 @@ void r8712_free_all_stainfo(struct _adapter *padapter)
for (index = 0; index < NUM_STA; index++) {
phead = &(pstapriv->sta_hash[index]);
plist = phead->next;
- while ((end_of_queue_search(phead, plist)) == false) {
+ while (!end_of_queue_search(phead, plist)) {
psta = LIST_CONTAINOR(plist,
struct sta_info, hash_list);
plist = plist->next;
@@ -247,7 +247,7 @@ struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
phead = &(pstapriv->sta_hash[index]);
plist = phead->next;
- while ((end_of_queue_search(phead, plist)) == false) {
+ while (!end_of_queue_search(phead, plist)) {
psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) {
/* if found the matched address */
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
index 2e4fa88951ad..68d65d230fe3 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ b/drivers/staging/rtl8712/rtl871x_xmit.c
@@ -217,8 +217,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
pattrib->pctrl = 0;
- if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
} else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
@@ -227,7 +227,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
/*firstly, filter packet not belongs to mp*/
if (pattrib->ether_type != 0x8712)
return _FAIL;
@@ -267,7 +267,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
psta = r8712_get_bcmc_stainfo(padapter);
pattrib->mac_id = 4;
} else {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
psta = r8712_get_stainfo(pstapriv,
get_bssid(pmlmepriv));
pattrib->mac_id = 5;
@@ -293,20 +293,21 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
/* get ether_hdr_len */
pattrib->pkt_hdrlen = ETH_HLEN;
- if (pqospriv->qos_option)
+ if (pqospriv->qos_option) {
r8712_set_qos(&pktfile, pattrib);
- else {
+ } else {
pattrib->hdrlen = WLAN_HDR_A3_LEN;
pattrib->subtype = WIFI_DATA_TYPE;
pattrib->priority = 0;
}
- if (psta->ieee8021x_blocked == true) {
+ if (psta->ieee8021x_blocked) {
pattrib->encrypt = 0;
if ((pattrib->ether_type != 0x888e) &&
- (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false))
+ !check_fwstate(pmlmepriv, WIFI_MP_STATE))
return _FAIL;
- } else
+ } else {
GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
+ }
switch (pattrib->encrypt) {
case _WEP40_:
case _WEP104_:
@@ -330,14 +331,14 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
}
if (pattrib->encrypt &&
- ((padapter->securitypriv.sw_encrypt == true) ||
- (psecuritypriv->hw_decrypted == false)))
+ (padapter->securitypriv.sw_encrypt ||
+ !psecuritypriv->hw_decrypted))
pattrib->bswenc = true;
else
pattrib->bswenc = false;
/* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
* some settings above.*/
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
pattrib->priority = (txdesc.txdw1 >> QSEL_SHT) & 0x1f;
return _SUCCESS;
}
@@ -389,7 +390,7 @@ static sint xmitframe_addmic(struct _adapter *padapter,
if (pframe[1] & 1) { /* ToDS==1 */
r8712_secmicappend(&micdata,
&pframe[16], 6); /*DA*/
- if (pframe[1]&2) /* From Ds==1 */
+ if (pframe[1] & 2) /* From Ds==1 */
r8712_secmicappend(&micdata,
&pframe[24], 6);
else
@@ -398,7 +399,7 @@ static sint xmitframe_addmic(struct _adapter *padapter,
} else { /* ToDS==0 */
r8712_secmicappend(&micdata,
&pframe[4], 6); /* DA */
- if (pframe[1]&2) /* From Ds==1 */
+ if (pframe[1] & 2) /* From Ds==1 */
r8712_secmicappend(&micdata,
&pframe[16], 6);
else
@@ -413,8 +414,8 @@ static sint xmitframe_addmic(struct _adapter *padapter,
for (curfragnum = 0; curfragnum < pattrib->nr_frags;
curfragnum++) {
payload = (u8 *)RND4((addr_t)(payload));
- payload = payload+pattrib->
- hdrlen+pattrib->iv_len;
+ payload = payload + pattrib->
+ hdrlen + pattrib->iv_len;
if ((curfragnum + 1) == pattrib->nr_frags) {
length = pattrib->last_txcmdsz -
pattrib->hdrlen -
@@ -423,10 +424,10 @@ static sint xmitframe_addmic(struct _adapter *padapter,
? pattrib->icv_len : 0);
r8712_secmicappend(&micdata, payload,
length);
- payload = payload+length;
+ payload = payload + length;
} else{
length = pxmitpriv->frag_len -
- pattrib->hdrlen-pattrib->iv_len -
+ pattrib->hdrlen - pattrib->iv_len -
((psecuritypriv->sw_encrypt) ?
pattrib->icv_len : 0);
r8712_secmicappend(&micdata, payload,
@@ -440,7 +441,7 @@ static sint xmitframe_addmic(struct _adapter *padapter,
* last_txcmdsz */
memcpy(payload, &(mic[0]), 8);
pattrib->last_txcmdsz += 8;
- payload = payload-pattrib->last_txcmdsz + 8;
+ payload = payload - pattrib->last_txcmdsz + 8;
}
}
return _SUCCESS;
@@ -483,34 +484,35 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr,
memset(hdr, 0, WLANHDR_OFFSET);
SetFrameSubType(fctrl, pattrib->subtype);
if (pattrib->subtype & WIFI_DATA_TYPE) {
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
/* to_ds = 1, fr_ds = 0; */
SetToDs(fctrl);
memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv),
ETH_ALEN);
memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
/* to_ds = 0, fr_ds = 1; */
SetFrDs(fctrl);
memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv),
ETH_ALEN);
memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
- } else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
- || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)
- == true)) {
+ } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv,
+ WIFI_ADHOC_MASTER_STATE)) {
memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv),
ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv),
ETH_ALEN);
- } else
+ } else {
return _FAIL;
+ }
if (pattrib->encrypt)
SetPrivacy(fctrl);
@@ -526,9 +528,9 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr,
struct sta_info *psta;
sint bmcst = IS_MCAST(pattrib->ra);
- if (pattrib->psta)
+ if (pattrib->psta) {
psta = pattrib->psta;
- else {
+ } else {
if (bmcst)
psta = r8712_get_bcmc_stainfo(padapter);
else
@@ -609,7 +611,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
return _FAIL;
_r8712_open_pktfile(pkt, &pktfile);
_r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
/* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
if (pattrib->ether_type == 0x8712) {
/* take care - update_txdesc overwrite this */
@@ -680,7 +682,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
pframe += pattrib->icv_len;
}
frg_inx++;
- if (bmcst || (r8712_endofpktfile(&pktfile) == true)) {
+ if (bmcst || r8712_endofpktfile(&pktfile)) {
pattrib->nr_frags = frg_inx;
pattrib->last_txcmdsz = pattrib->hdrlen +
pattrib->iv_len +
@@ -719,17 +721,18 @@ void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len)
case AUTO_VCS:
default:
perp = r8712_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
- if (perp == NULL)
+ if (perp == NULL) {
pxmitpriv->vcs = NONE_VCS;
- else {
+ } else {
protection = (*(perp + 2)) & BIT(1);
if (protection) {
if (pregistrypriv->vcs_type == RTS_CTS)
pxmitpriv->vcs = RTS_CTS;
else
pxmitpriv->vcs = CTS_TO_SELF;
- } else
+ } else {
pxmitpriv->vcs = NONE_VCS;
+ }
}
break;
}
@@ -743,9 +746,9 @@ struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
- if (list_empty(&pfree_xmitbuf_queue->queue))
+ if (list_empty(&pfree_xmitbuf_queue->queue)) {
pxmitbuf = NULL;
- else {
+ } else {
phead = &pfree_xmitbuf_queue->queue;
plist = phead->next;
pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
@@ -797,9 +800,9 @@ struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv)
struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
- if (list_empty(&pfree_xmit_queue->queue))
+ if (list_empty(&pfree_xmit_queue->queue)) {
pxframe = NULL;
- else {
+ } else {
phead = &pfree_xmit_queue->queue;
plist = phead->next;
pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
@@ -855,7 +858,7 @@ void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
spin_lock_irqsave(&(pframequeue->lock), irqL);
phead = &pframequeue->queue;
plist = phead->next;
- while (end_of_queue_search(phead, plist) == false) {
+ while (!end_of_queue_search(phead, plist)) {
pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
plist = plist->next;
r8712_free_xmitframe(pxmitpriv, pxmitframe);
@@ -876,19 +879,19 @@ static inline struct tx_servq *get_sta_pending(struct _adapter *padapter,
case 2:
ptxservq = &(psta->sta_xmitpriv.bk_q);
*ppstapending = &padapter->xmitpriv.bk_pending;
- (phwxmits+3)->accnt++;
+ (phwxmits + 3)->accnt++;
break;
case 4:
case 5:
ptxservq = &(psta->sta_xmitpriv.vi_q);
*ppstapending = &padapter->xmitpriv.vi_pending;
- (phwxmits+1)->accnt++;
+ (phwxmits + 1)->accnt++;
break;
case 6:
case 7:
ptxservq = &(psta->sta_xmitpriv.vo_q);
*ppstapending = &padapter->xmitpriv.vo_pending;
- (phwxmits+0)->accnt++;
+ (phwxmits + 0)->accnt++;
break;
case 0:
case 3:
@@ -917,13 +920,13 @@ sint r8712_xmit_classifier(struct _adapter *padapter,
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
sint bmcst = IS_MCAST(pattrib->ra);
- if (pattrib->psta)
+ if (pattrib->psta) {
psta = pattrib->psta;
- else {
- if (bmcst)
+ } else {
+ if (bmcst) {
psta = r8712_get_bcmc_stainfo(padapter);
- else {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
+ } else {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
psta = r8712_get_stainfo(pstapriv,
get_bssid(pmlmepriv));
else
diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c
index b4ae11a78b46..ad21df16c2bd 100644
--- a/drivers/staging/rtl8712/usb_halinit.c
+++ b/drivers/staging/rtl8712/usb_halinit.c
@@ -167,12 +167,12 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter)
r8712_write8(padapter, CR + 1, 0x37);
/* Fix the RX FIFO issue(usb error), */
val8 = r8712_read8(padapter, 0x1025FE5c);
- r8712_write8(padapter, 0x1025FE5c, (val8|BIT(7)));
+ r8712_write8(padapter, 0x1025FE5c, (val8 | BIT(7)));
val8 = r8712_read8(padapter, 0x102500ab);
- r8712_write8(padapter, 0x102500ab, (val8|BIT(6)|BIT(7)));
+ r8712_write8(padapter, 0x102500ab, (val8 | BIT(6) | BIT(7)));
/* For power save, used this in the bit file after 970621 */
val8 = r8712_read8(padapter, SYS_CLKR);
- r8712_write8(padapter, SYS_CLKR, val8&(~CPU_CLKSEL));
+ r8712_write8(padapter, SYS_CLKR, val8 & (~CPU_CLKSEL));
} else if (pregistrypriv->chip_version == RTL8712_2ndCUT ||
pregistrypriv->chip_version == RTL8712_3rdCUT) {
/* Initialization for power on sequence,
@@ -280,13 +280,14 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter)
if (PollingCnt <= 0) {
val8 = r8712_read8(padapter, CR);
- r8712_write8(padapter, CR, val8&(~_TXDMA_EN));
+ r8712_write8(padapter, CR, val8 & (~_TXDMA_EN));
udelay(2); /* PlatformStallExecution(2); */
/* Reset TxDMA */
- r8712_write8(padapter, CR, val8|_TXDMA_EN);
+ r8712_write8(padapter, CR, val8 | _TXDMA_EN);
}
- } else
+ } else {
ret = _FAIL;
+ }
return ret;
}
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index 4c63baa66335..c71333fbe823 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -144,6 +144,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
{USB_DEVICE(0x0DF6, 0x0058)},
{USB_DEVICE(0x0DF6, 0x0049)},
{USB_DEVICE(0x0DF6, 0x004C)},
+ {USB_DEVICE(0x0DF6, 0x006C)},
{USB_DEVICE(0x0DF6, 0x0064)},
/* Skyworth */
{USB_DEVICE(0x14b2, 0x3300)},
@@ -301,7 +302,7 @@ void rtl871x_intf_stop(struct _adapter *padapter)
void r871x_dev_unload(struct _adapter *padapter)
{
- if (padapter->bup == true) {
+ if (padapter->bup) {
/*s1.*/
padapter->bDriverStopped = true;
@@ -338,7 +339,7 @@ static void disable_ht_for_spec_devid(const struct usb_device_id *pdid,
flags = specific_device_id_tbl[i].flags;
if ((pdid->idVendor == vid) && (pdid->idProduct == pid) &&
- (flags&SPEC_DEV_ID_DISABLE_HT)) {
+ (flags & SPEC_DEV_ID_DISABLE_HT)) {
padapter->registrypriv.ht_enable = 0;
padapter->registrypriv.cbw40_enable = 0;
padapter->registrypriv.ampdu_enable = 0;
@@ -394,9 +395,9 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
/* step 3.
* initialize the dvobj_priv
*/
- if (!padapter->dvobj_init)
- goto error;
- else {
+ if (!padapter->dvobj_init) {
+ goto error;
+ } else {
status = padapter->dvobj_init(padapter);
if (status != _SUCCESS)
goto error;
@@ -425,7 +426,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
/* The following operations prevent Efuse leakage by
* turning on 2.5V.
*/
- tmpU1b = r8712_read8(padapter, EFUSE_TEST+3);
+ tmpU1b = r8712_read8(padapter, EFUSE_TEST + 3);
r8712_write8(padapter, EFUSE_TEST + 3, tmpU1b | 0x80);
msleep(20);
r8712_write8(padapter, EFUSE_TEST + 3,
@@ -552,8 +553,9 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
padapter->ledpriv.bRegUseLed = false;
break;
}
- } else
+ } else {
AutoloadFail = false;
+ }
if (((mac[0] == 0xff) && (mac[1] == 0xff) &&
(mac[2] == 0xff) && (mac[3] == 0xff) &&
(mac[4] == 0xff) && (mac[5] == 0xff)) ||
@@ -610,7 +612,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
release_firmware(padapter->fw);
/* never exit with a firmware callback pending */
wait_for_completion(&padapter->rtl8712_fw_ready);
- if (drvpriv.drv_registered == true)
+ if (drvpriv.drv_registered)
padapter->bSurpriseRemoved = true;
unregister_netdev(pnetdev); /* will call netdev_close() */
flush_scheduled_work();
diff --git a/drivers/staging/rtl8712/usb_ops.c b/drivers/staging/rtl8712/usb_ops.c
index c03508d935f2..856f257bb77e 100644
--- a/drivers/staging/rtl8712/usb_ops.c
+++ b/drivers/staging/rtl8712/usb_ops.c
@@ -47,11 +47,11 @@ static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
request = 0x05;
requesttype = 0x01; /* read_in */
index = 0;
- wvalue = (u16)(addr&0x0000ffff);
+ wvalue = (u16)(addr & 0x0000ffff);
len = 1;
r8712_usbctrl_vendorreq(pintfpriv, request, wvalue, index, &data, len,
requesttype);
- return (u8)(le32_to_cpu(data)&0x0ff);
+ return (u8)(le32_to_cpu(data) & 0x0ff);
}
static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
@@ -67,11 +67,11 @@ static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
request = 0x05;
requesttype = 0x01; /* read_in */
index = 0;
- wvalue = (u16)(addr&0x0000ffff);
+ wvalue = (u16)(addr & 0x0000ffff);
len = 2;
r8712_usbctrl_vendorreq(pintfpriv, request, wvalue, index, &data, len,
requesttype);
- return (u16)(le32_to_cpu(data)&0xffff);
+ return (u16)(le32_to_cpu(data) & 0xffff);
}
static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
@@ -87,7 +87,7 @@ static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
request = 0x05;
requesttype = 0x01; /* read_in */
index = 0;
- wvalue = (u16)(addr&0x0000ffff);
+ wvalue = (u16)(addr & 0x0000ffff);
len = 4;
r8712_usbctrl_vendorreq(pintfpriv, request, wvalue, index, &data, len,
requesttype);
@@ -107,10 +107,10 @@ static void usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
request = 0x05;
requesttype = 0x00; /* write_out */
index = 0;
- wvalue = (u16)(addr&0x0000ffff);
+ wvalue = (u16)(addr & 0x0000ffff);
len = 1;
data = val;
- data = cpu_to_le32(data&0x000000ff);
+ data = cpu_to_le32(data & 0x000000ff);
r8712_usbctrl_vendorreq(pintfpriv, request, wvalue, index, &data, len,
requesttype);
}
@@ -128,10 +128,10 @@ static void usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
request = 0x05;
requesttype = 0x00; /* write_out */
index = 0;
- wvalue = (u16)(addr&0x0000ffff);
+ wvalue = (u16)(addr & 0x0000ffff);
len = 2;
data = val;
- data = cpu_to_le32(data&0x0000ffff);
+ data = cpu_to_le32(data & 0x0000ffff);
r8712_usbctrl_vendorreq(pintfpriv, request, wvalue, index, &data, len,
requesttype);
}
@@ -149,7 +149,7 @@ static void usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
request = 0x05;
requesttype = 0x00; /* write_out */
index = 0;
- wvalue = (u16)(addr&0x0000ffff);
+ wvalue = (u16)(addr & 0x0000ffff);
len = 4;
data = cpu_to_le32(val);
r8712_usbctrl_vendorreq(pintfpriv, request, wvalue, index, &data, len,
diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
index c940722fbfd3..489a9e6d52fc 100644
--- a/drivers/staging/rtl8712/usb_ops_linux.c
+++ b/drivers/staging/rtl8712/usb_ops_linux.c
@@ -144,8 +144,9 @@ static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
pipe = usb_sndbulkpipe(pusbd, 0x0d);
break;
}
- } else
+ } else {
pipe = 0;
+ }
return pipe;
}
@@ -266,7 +267,7 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
adapter->pwrctrlpriv.pnp_bstop_trx)
return _FAIL;
- if (!precvbuf->reuse == false || !precvbuf->pskb) {
+ if (precvbuf->reuse || !precvbuf->pskb) {
precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
if (precvbuf->pskb != NULL)
precvbuf->reuse = true;
@@ -280,7 +281,7 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
if (!precvbuf->pskb)
return _FAIL;
tmpaddr = (addr_t)precvbuf->pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
skb_reserve(precvbuf->pskb,
(RECVBUFF_ALIGN_SZ - alignment));
precvbuf->phead = precvbuf->pskb->head;
@@ -306,8 +307,9 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
err = usb_submit_urb(purb, GFP_ATOMIC);
if ((err) && (err != (-EPERM)))
ret = _FAIL;
- } else
+ } else {
ret = _FAIL;
+ }
return ret;
}
@@ -330,13 +332,13 @@ void r8712_xmit_bh(void *priv)
struct _adapter *padapter = (struct _adapter *)priv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- if ((padapter->bDriverStopped == true) ||
- (padapter->bSurpriseRemoved == true)) {
+ if (padapter->bDriverStopped ||
+ padapter->bSurpriseRemoved) {
netdev_err(padapter->pnetdev, "xmit_bh => bDriverStopped or bSurpriseRemoved\n");
return;
}
ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL);
- if (ret == false)
+ if (!ret)
return;
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
}
@@ -410,7 +412,7 @@ u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
(padapter->pwrctrlpriv.pnp_bstop_trx))
return _FAIL;
for (i = 0; i < 8; i++) {
- if (pxmitframe->bpending[i] == false) {
+ if (!pxmitframe->bpending[i]) {
spin_lock_irqsave(&pxmitpriv->lock, irqL);
pxmitpriv->txirp_cnt++;
pxmitframe->bpending[i] = true;
@@ -449,7 +451,7 @@ u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
}
/* translate DMA FIFO addr to pipehandle */
pipe = ffaddr2pipehdl(pdvobj, addr);
- if (pxmitpriv->free_xmitbuf_cnt%NR_XMITBUFF == 0)
+ if (pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0)
purb->transfer_flags &= (~URB_NO_INTERRUPT);
else
purb->transfer_flags |= URB_NO_INTERRUPT;
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
index d15fb1ad45b9..d3981836ce26 100644
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ b/drivers/staging/rtl8712/xmit_linux.c
@@ -166,7 +166,7 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev)
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
int ret = 0;
- if (r8712_if_up(padapter) == false) {
+ if (!r8712_if_up(padapter)) {
ret = 0;
goto _xmit_entry_drop;
}
@@ -181,7 +181,7 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev)
}
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_TX);
pxmitframe->pkt = pkt;
- if (r8712_pre_xmit(padapter, pxmitframe) == true) {
+ if (r8712_pre_xmit(padapter, pxmitframe)) {
/*dump xmitframe directly or drop xframe*/
dev_kfree_skb_any(pkt);
pxmitframe->pkt = NULL;
diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c
index a0b68451abf0..1aa9b267c30e 100644
--- a/drivers/staging/rtl8723au/core/rtw_ap.c
+++ b/drivers/staging/rtl8723au/core/rtw_ap.c
@@ -21,10 +21,7 @@
#include <rtl8723a_cmd.h>
#include <rtl8723a_hal.h>
#include <asm/unaligned.h>
-
-extern unsigned char WMM_OUI23A[];
-extern unsigned char WPS_OUI23A[];
-extern unsigned char P2P_OUI23A[];
+#include <rtw_mlme_ext.h>
void init_mlme_ap_info23a(struct rtw_adapter *padapter)
{
@@ -132,11 +129,11 @@ static void update_BCNTIM(struct rtw_adapter *padapter)
*dst_ie++ = tim_ielen;
- *dst_ie++ = 0;/* DTIM count */
- *dst_ie++ = 1;/* DTIM period */
+ *dst_ie++ = 0; /* DTIM count */
+ *dst_ie++ = 1; /* DTIM period */
- if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
- *dst_ie++ = BIT(0);/* bitmap ctrl */
+ if (pstapriv->tim_bitmap & BIT(0)) /* for bc/mc frames */
+ *dst_ie++ = BIT(0); /* bitmap ctrl */
else
*dst_ie++ = 0;
@@ -239,11 +236,16 @@ void expire_timeout_chk23a(struct rtw_adapter *padapter)
if (psta->state & WIFI_SLEEP_STATE) {
if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
- /* to check if alive by another methods if station is at ps mode. */
+ /*
+ * check if alive by another method
+ * if station is at ps mode.
+ */
psta->expire_to = pstapriv->expire_to;
psta->state |= WIFI_STA_ALIVE_CHK_STATE;
-
- /* to update bcn with tim_bitmap for this station */
+ /*
+ * update bcn with tim_bitmap
+ * for this station
+ */
pstapriv->tim_bitmap |= CHKBIT(psta->aid);
update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
@@ -264,7 +266,10 @@ void expire_timeout_chk23a(struct rtw_adapter *padapter)
psta->hwaddr, psta->state);
updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
} else {
- /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
+ /*
+ * TODO: Aging mechanism to digest frames in
+ * sleep_q to avoid running out of xmitframe
+ */
if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
&& padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
) {
@@ -285,13 +290,16 @@ void expire_timeout_chk23a(struct rtw_adapter *padapter)
u8 backup_oper_channel = 0;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- /* switch to correct channel of current network before issue keep-alive frames */
+ /*
+ * switch to correct channel of current
+ * network before issue keep-alive frames
+ */
if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) {
backup_oper_channel = rtw_get_oper_ch23a(padapter);
SelectChannel23a(padapter, pmlmeext->cur_channel);
}
- /* issue null data to check sta alive*/
+ /* issue null data to check sta alive */
for (i = 0; i < chk_alive_num; i++) {
int ret = _FAIL;
@@ -332,7 +340,7 @@ void expire_timeout_chk23a(struct rtw_adapter *padapter)
}
- if (backup_oper_channel > 0) /* back to the original operation channel */
+ if (backup_oper_channel > 0) /* back to original operation channel */
SelectChannel23a(padapter, backup_oper_channel);
}
@@ -369,9 +377,9 @@ void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_l
rf_type = rtl8723a_get_rf_type(padapter);
if (rf_type == RF_2T2R)
- limit = 16;/* 2R */
+ limit = 16; /* 2R */
else
- limit = 8;/* 1R */
+ limit = 8; /* 1R */
for (i = 0; i < limit; i++) {
if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8))
@@ -407,7 +415,7 @@ void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_l
arg = psta->mac_id&0x1f;
- arg |= BIT(7);/* support entry 2~31 */
+ arg |= BIT(7); /* support entry 2~31 */
if (shortGIrate == true)
arg |= BIT(5);
@@ -446,7 +454,7 @@ static void update_bmc_sta(struct rtw_adapter *padapter)
struct sta_info *psta = rtw_get_bcmc_stainfo23a(padapter);
if (psta) {
- psta->aid = 0;/* default set to 0 */
+ psta->aid = 0; /* default set to 0 */
psta->mac_id = psta->aid + 1;
psta->qos_option = 0;
@@ -473,7 +481,7 @@ static void update_bmc_sta(struct rtw_adapter *padapter)
if (pcur_network->DSConfig > 14) {
/* force to A mode. 5G doesn't support CCK rates */
network_type = WIRELESS_11A;
- tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */
+ tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */
} else {
/* force to b mode */
network_type = WIRELESS_11B;
@@ -516,13 +524,13 @@ static void update_bmc_sta(struct rtw_adapter *padapter)
DBG_8723A("add_RATid23a_bmc_sta error!\n");
}
-/* notes: */
-/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
-/* MAC_ID = AID+1 for sta in ap/adhoc mode */
-/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
-/* MAC_ID = 0 for bssid for sta/ap/adhoc */
-/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
-
+/*
+ * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode
+ * MAC_ID = AID+1 for sta in ap/adhoc mode
+ * MAC_ID = 1 for bc/mc for sta/ap/adhoc
+ * MAC_ID = 0 for bssid for sta/ap/adhoc
+ * CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid + 1;
+ */
void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -556,7 +564,7 @@ void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info
if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
phtpriv_sta->sgi = true;
- /* bwmode */
+ /* bwmode */
if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
/* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */
phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
@@ -575,10 +583,10 @@ void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info
}
/* Rx AMPDU */
- send_delba23a(padapter, 0, psta->hwaddr);/* recipient */
+ send_delba23a(padapter, 0, psta->hwaddr); /* recipient */
/* TX AMPDU */
- send_delba23a(padapter, 1, psta->hwaddr);/* originator */
+ send_delba23a(padapter, 1, psta->hwaddr); /* originator */
phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
@@ -599,11 +607,10 @@ static void update_hw_ht_param(struct rtw_adapter *padapter)
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
DBG_8723A("%s\n", __func__);
-
- /* handle A-MPDU parameter field */
/*
- AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
- AMPDU_para [4:2]:Min MPDU Start Spacing
+ * handle A-MPDU parameter field
+ * AMPDU_para [1:0]:Max AMPDU Len => 0:8k, 1:16k, 2:32k, 3:64k
+ * AMPDU_para [4:2]:Min MPDU Start Spacing
*/
max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info &
IEEE80211_HT_AMPDU_PARM_FACTOR;
@@ -614,7 +621,7 @@ static void update_hw_ht_param(struct rtw_adapter *padapter)
rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
- /* Config SM Power Save setting */
+ /* Config SM Power Save setting */
pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
IEEE80211_HT_CAP_SM_PS) >> 2;
if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
@@ -641,13 +648,17 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
cur_bwmode = HT_CHANNEL_WIDTH_20;
cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- /* check if there is wps ie, */
- /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
- /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
- if (NULL == cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
- WLAN_OUI_TYPE_MICROSOFT_WPS,
- pnetwork->IEs,
- pnetwork->IELength))
+ /*
+ * check if there is wps ie
+ * if there is wpsie in beacon the hostapd will
+ * update beacon twice when stating hostapd
+ * and at first time the security
+ * ie (RSN/WPA IE) will not include in beacon
+ */
+ if (!cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WPS,
+ pnetwork->IEs,
+ pnetwork->IELength))
pmlmeext->bstart_bss = true;
/* todo: update wmm, ht cap */
@@ -663,8 +674,11 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
}
if (pmlmepriv->cur_network.join_res != true) {
- /* setting only at first time */
- /* WEP Key will be set before this function, do not clear CAM. */
+ /*
+ * setting only at first time
+ * WEP Key will be set before this
+ * function, do not clear CAM.
+ */
if (psecuritypriv->dot11PrivacyAlgrthm !=
WLAN_CIPHER_SUITE_WEP40 &&
psecuritypriv->dot11PrivacyAlgrthm !=
@@ -679,13 +693,13 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
hw_var_set_bssid(padapter, pnetwork->MacAddress);
/* Set EDCA param reg */
- acparm = 0x002F3217; /* VO */
+ acparm = 0x002F3217; /* VO */
rtl8723a_set_ac_param_vo(padapter, acparm);
- acparm = 0x005E4317; /* VI */
+ acparm = 0x005E4317; /* VI */
rtl8723a_set_ac_param_vi(padapter, acparm);
acparm = 0x005ea42b;
rtl8723a_set_ac_param_be(padapter, acparm);
- acparm = 0x0000A444; /* BK */
+ acparm = 0x0000A444; /* BK */
rtl8723a_set_ac_param_bk(padapter, acparm);
/* Set Security */
@@ -722,8 +736,10 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
switch (pht_info->ht_param &
IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- /* pmlmeext->cur_ch_offset =
- HAL_PRIME_CHNL_OFFSET_LOWER; */
+ /*
+ * pmlmeext->cur_ch_offset =
+ * HAL_PRIME_CHNL_OFFSET_LOWER;
+ */
cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
break;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
@@ -735,7 +751,10 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
}
}
}
- /* TODO: need to judge the phy parameters on concurrent mode for single phy */
+ /*
+ * TODO: need to judge the phy parameters
+ * on concurrent mode for single phy
+ */
set_channel_bwmode23a(padapter, cur_channel, cur_ch_offset, cur_bwmode);
DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode,
@@ -886,7 +905,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter,
&pairwise_cipher, NULL) == _SUCCESS) {
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
- psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
+ psecuritypriv->dot8021xalg = 1; /* psk, todo:802.1x */
psecuritypriv->wpa_psk |= BIT(1);
psecuritypriv->wpa2_group_cipher = group_cipher;
@@ -934,7 +953,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter,
if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
pmlmepriv->qos_option = 1;
- *(p+8) |= BIT(7);/* QoS Info, support U-APSD */
+ *(p + 8) |= BIT(7);/* QoS Info:support U-APSD */
/* disable all ACM bits since the WMM admission
* control is not supported
@@ -1135,11 +1154,6 @@ int rtw_acl_remove_sta23a(struct rtw_adapter *padapter, u8 *addr)
return 0;
}
-static void update_bcn_fixed_ie(struct rtw_adapter *padapter)
-{
- DBG_8723A("%s\n", __func__);
-}
-
static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -1173,21 +1187,6 @@ static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter)
}
}
-static void update_bcn_htcap_ie(struct rtw_adapter *padapter)
-{
- DBG_8723A("%s\n", __func__);
-}
-
-static void update_bcn_htinfo_ie(struct rtw_adapter *padapter)
-{
- DBG_8723A("%s\n", __func__);
-}
-
-static void update_bcn_rsn_ie(struct rtw_adapter *padapter)
-{
- DBG_8723A("%s\n", __func__);
-}
-
static void update_bcn_wpa_ie(struct rtw_adapter *padapter)
{
DBG_8723A("%s\n", __func__);
@@ -1244,11 +1243,6 @@ void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
spin_lock_bh(&pmlmepriv->bcn_update_lock);
switch (ie_id) {
- case 0xFF:
- /* 8: TimeStamp, 2: Beacon Interval 2:Capability */
- update_bcn_fixed_ie(padapter);
- break;
-
case WLAN_EID_TIM:
update_BCNTIM(padapter);
break;
@@ -1257,18 +1251,6 @@ void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
update_bcn_erpinfo_ie(padapter);
break;
- case WLAN_EID_HT_CAPABILITY:
- update_bcn_htcap_ie(padapter);
- break;
-
- case WLAN_EID_RSN:
- update_bcn_rsn_ie(padapter);
- break;
-
- case WLAN_EID_HT_OPERATION:
- update_bcn_htinfo_ie(padapter);
- break;
-
case WLAN_EID_VENDOR_SPECIFIC:
update_bcn_vendor_spec_ie(padapter, oui);
break;
@@ -1286,16 +1268,16 @@ void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
}
/*
-op_mode
-Set to 0 (HT pure) under the following conditions
- - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
- - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
-Set to 1 (HT non-member protection) if there may be non-HT STAs
- in both the primary and the secondary channel
-Set to 2 if only HT STAs are associated in BSS,
- however and at least one 20 MHz HT STA is associated
-Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
- (currently non-GF HT station is considered as non-HT STA also)
+ * op_mode
+ * Set to 0 (HT pure) under the following conditions
+ * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
+ * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
+ * Set to 1 (HT non-member protection) if there may be non-HT STAs
+ * in both the primary and the secondary channel
+ * Set to 2 if only HT STAs are associated in BSS,
+ * however and at least one 20 MHz HT STA is associated
+ * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
+ * (currently non-GF HT station is considered as non-HT STA also)
*/
static int rtw_ht_operation_update(struct rtw_adapter *padapter)
{
@@ -1338,7 +1320,8 @@ static int rtw_ht_operation_update(struct rtw_adapter *padapter)
op_mode_changes++;
}
- /* Note: currently we switch to the MIXED op mode if HT non-greenfield
+ /*
+ * Note: currently we switch to the MIXED op mode if HT non-greenfield
* station is associated. Probably it's a theoretical case, since
* it looks like all known HT STAs support greenfield.
*/
@@ -1389,7 +1372,7 @@ void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated)
}
}
-/* called > TSR LEVEL for USB or SDIO Interface*/
+/* called > TSR LEVEL for USB or SDIO Interface */
void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta)
{
u8 beacon_updated = false;
@@ -1607,16 +1590,16 @@ u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool acti
if (active) {
/* tear down Rx AMPDU */
- send_delba23a(padapter, 0, psta->hwaddr);/* recipient */
+ send_delba23a(padapter, 0, psta->hwaddr); /* recipient */
/* tear down TX AMPDU */
- send_delba23a(padapter, 1, psta->hwaddr);/* originator */
+ send_delba23a(padapter, 1, psta->hwaddr); /* originator */
issue_deauth23a(padapter, psta->hwaddr, reason);
}
- psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
- psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
+ psta->htpriv.agg_enable_bitmap = 0x0; /* reset */
+ psta->htpriv.candidate_tid_bitmap = 0x0; /* reset */
/* report_del_sta_event23a(padapter, psta->hwaddr, reason); */
@@ -1717,7 +1700,7 @@ int rtw_sta_flush23a(struct rtw_adapter *padapter)
return 0;
}
-/* called > TSR LEVEL for USB or SDIO Interface*/
+/* called > TSR LEVEL for USB or SDIO Interface */
void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
{
int flags = psta->flags;
@@ -1746,7 +1729,7 @@ void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
update_sta_info23a_apmode23a(padapter, psta);
}
-/* called >= TSR LEVEL for USB or SDIO Interface*/
+/* called >= TSR LEVEL for USB or SDIO Interface */
void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
{
if (psta->state & _FW_LINKED) {
@@ -1870,7 +1853,10 @@ void stop_ap_mode23a(struct rtw_adapter *padapter)
pmlmepriv->update_bcn = false;
pmlmeext->bstart_bss = false;
- /* reset and init security priv , this can refine with rtw_reset_securitypriv23a */
+ /*
+ * reset and init security priv , this can
+ * refine with rtw_reset_securitypriv23a
+ */
memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c
index 46aea16cbf78..3035bb864c39 100644
--- a/drivers/staging/rtl8723au/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723au/core/rtw_cmd.c
@@ -236,7 +236,8 @@ int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
res = queue_work(pcmdpriv->wq, &cmd_obj->work);
if (!res) {
- printk(KERN_ERR "%s: Call to queue_work() failed\n", __func__);
+ netdev_err(pcmdpriv->padapter->pnetdev,
+ "%s: Call to queue_work() failed\n", __func__);
res = _FAIL;
} else
res = _SUCCESS;
@@ -620,7 +621,7 @@ int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms,
} else {
/* no need to enqueue, do the cmd hdl directly and
free cmd parameter */
- if (H2C_SUCCESS != disconnect_hdl23a(padapter, (u8 *)param))
+ if (disconnect_hdl23a(padapter, (u8 *)param) != H2C_SUCCESS)
res = _FAIL;
kfree(param);
}
@@ -1342,6 +1343,7 @@ void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+ struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
if (pcmd->res != H2C_SUCCESS) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
@@ -1371,19 +1373,19 @@ void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
spin_unlock_bh(&pmlmepriv->lock);
} else {
pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL);
- spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ spin_lock_bh(&scanned_queue->lock);
if (!pwlan) {
- pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue);
+ pwlan = rtw_get_oldest_wlan_network23a(scanned_queue);
if (!pwlan) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
"Error: can't get pwlan in rtw23a_joinbss_event_cb\n");
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ spin_unlock_bh(&scanned_queue->lock);
goto createbss_cmd_fail;
}
pwlan->last_scanned = jiffies;
} else {
list_add_tail(&pwlan->list,
- &pmlmepriv->scanned_queue.queue);
+ &scanned_queue->queue);
}
pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
@@ -1402,9 +1404,9 @@ void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
clr_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
/* we will set _FW_LINKED when there is one more sat to
join us (rtw_stassoc_event_callback23a) */
+ spin_unlock_bh(&scanned_queue->lock);
}
createbss_cmd_fail:
diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c
index 92a34db3bd4e..f174b4d1a018 100644
--- a/drivers/staging/rtl8723au/core/rtw_efuse.c
+++ b/drivers/staging/rtl8723au/core/rtw_efuse.c
@@ -21,34 +21,17 @@
#include <rtl8723a_hal.h>
#include <usb_ops_linux.h>
-/*------------------------Define local variable------------------------------*/
-
-/* */
#define REG_EFUSE_CTRL 0x0030
-#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
-/* */
+#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control */
#define VOLTAGE_V25 0x03
#define LDOE25_SHIFT 28
-/*-----------------------------------------------------------------------------
- * Function: Efuse_PowerSwitch
- *
- * Overview: When we want to enable write operation, we should change to
- * pwr on state. When we stop write, we should switch to 500k mode
- * and disable LDO 2.5V.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/17/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
+/*
+ * When we want to enable write operation, we should change to
+ * pwr on state. When we stop write, we should switch to 500k mode
+ * and disable LDO 2.5V.
+ */
static void Efuse_PowerSwitch(struct rtw_adapter *padapter,
u8 bWrite, u8 PwrState)
{
@@ -58,22 +41,26 @@ static void Efuse_PowerSwitch(struct rtw_adapter *padapter,
if (PwrState == true) {
rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
- /* 1.2V Power: From VDDON with Power
- Cut(0x0000h[15]), default valid */
+ /*
+ * 1.2V Power: From VDDON with Power
+ * Cut(0x0000h[15]), default valid
+ */
tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL);
if (!(tmpV16 & PWC_EV12V)) {
tmpV16 |= PWC_EV12V;
rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
}
- /* Reset: 0x0000h[28], default valid */
+ /* Reset: 0x0000h[28], default valid */
tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN);
if (!(tmpV16 & FEN_ELDR)) {
tmpV16 |= FEN_ELDR;
rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
}
- /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock
- from ANA, default valid */
+ /*
+ * Clock: Gated(0x0008h[5]) 8M(0x0008h[1])
+ * clock from ANA, default valid
+ */
tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR);
if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
tmpV16 |= (LOADER_CLK_EN | ANA8M);
@@ -100,8 +87,7 @@ static void Efuse_PowerSwitch(struct rtw_adapter *padapter,
}
}
-u16
-Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
+u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
{
u16 ret = 0;
@@ -113,26 +99,19 @@ Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
return ret;
}
-/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
-u8
-Efuse_CalculateWordCnts23a(u8 word_en)
+/* Get current efuse area enabled word */
+u8 Efuse_CalculateWordCnts23a(u8 word_en)
{
return hweight8((~word_en) & 0xf);
}
-/* */
-/* Description: */
-/* Execute E-Fuse read byte operation. */
-/* Referred from SD1 Richard. */
-/* */
-/* Assumption: */
-/* 1. Boot from E-Fuse and successfully auto-load. */
-/* 2. PASSIVE_LEVEL (USB interface) */
-/* */
-/* Created by Roger, 2008.10.21. */
-/* */
-void
-ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
+/*
+ * Description: Execute E-Fuse read byte operation.
+ *
+ * Assumptions: 1. Boot from E-Fuse and successfully auto-load.
+ * 2. PASSIVE_LEVEL (USB interface)
+ */
+void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
{
u32 value32;
u8 readbyte;
@@ -156,19 +135,21 @@ ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
retry++;
}
- /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
- /* This fix the problem that Efuse read error in high temperature condition. */
- /* Designer says that there shall be some delay after ready bit is set, or the */
- /* result will always stay on last data we read. */
+ /*
+ * Added suggested delay. This fixes the problem that
+ * Efuse read error in high temperature condition.
+ * Designer says that there shall be some delay after
+ * ready bit is set, or the result will always stay
+ * on last data we read.
+ */
udelay(50);
value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
*pbuf = (u8)(value32 & 0xff);
}
-void
-EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
- u8 type, void *pOut)
+void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
+ u8 type, void *pOut)
{
u8 *pu1Tmp;
u16 *pu2Tmp;
@@ -249,24 +230,8 @@ EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
}
}
-/*-----------------------------------------------------------------------------
- * Function: EFUSE_Read1Byte23a
- *
- * Overview: Copy from WMAC fot EFUSE read 1 byte.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 09/23/2008 MHC Copy from WMAC.
- *
- *---------------------------------------------------------------------------*/
-u8
-EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
+/* Copy from WMAC for EFUSE read 1 byte. */
+u8 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
{
u8 data;
u8 Bytetemp = {0x00};
@@ -306,85 +271,25 @@ EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
return data;
} else
return 0xFF;
-}/* EFUSE_Read1Byte23a */
-
-/*-----------------------------------------------------------------------------
- * Function: EFUSE_Write1Byte
- *
- * Overview: Copy from WMAC fot EFUSE write 1 byte.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 09/23/2008 MHC Copy from WMAC.
- *
- *---------------------------------------------------------------------------*/
-
-void
-EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value);
-void
-EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value)
-{
- u8 Bytetemp = {0x00};
- u8 temp = {0x00};
- u32 k = 0;
- u16 contentLen = 0;
-
- EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
- TYPE_EFUSE_REAL_CONTENT_LEN,
- (void *)&contentLen);
-
- if (Address < contentLen) { /* E-fuse 512Byte */
- rtl8723au_write8(Adapter, EFUSE_CTRL, Value);
-
- /* Write E-fuse Register address bit0~7 */
- temp = Address & 0xFF;
- rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
- Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
-
- /* Write E-fuse Register address bit8~9 */
- temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
- rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
-
- /* Write 0x30[31]= 1 */
- Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
- temp = Bytetemp | 0x80;
- rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
-
- /* Wait Write-ready (0x30[31]= 0) */
- Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
- while (Bytetemp & 0x80) {
- Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
- k++;
- if (k == 100) {
- k = 0;
- break;
- }
- }
- }
-}/* EFUSE_Write1Byte */
+}
-/* 11/16/2008 MH Read one byte from real Efuse. */
-int
-efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
+/* Read one byte from real Efuse. */
+int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
{
u8 tmpidx = 0;
int bResult;
- /* -----------------e-fuse reg ctrl --------------------------------- */
+ /* -----------------e-fuse reg ctrl ---------------------------- */
/* address */
- rtl8723au_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
- rtl8723au_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
- (rtl8723au_read8(pAdapter, EFUSE_CTRL+2)&0xFC));
+ rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
+ rtl8723au_write8(pAdapter, EFUSE_CTRL + 2,
+ ((u8)((addr >> 8) & 0x03)) |
+ (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
- rtl8723au_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
+ rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
- while(!(0x80 &rtl8723au_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100))
+ while (!(0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) &&
+ (tmpidx < 100))
tmpidx++;
if (tmpidx < 100) {
*data = rtl8723au_read8(pAdapter, EFUSE_CTRL);
@@ -396,26 +301,26 @@ efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
return bResult;
}
-/* 11/16/2008 MH Write one byte to reald Efuse. */
-int
-efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
+/* Write one byte to reald Efuse. */
+int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
{
u8 tmpidx = 0;
int bResult;
/* return 0; */
- /* -----------------e-fuse reg ctrl --------------------------------- */
+ /* -----------------e-fuse reg ctrl ------------------------- */
/* address */
- rtl8723au_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
- rtl8723au_write8(pAdapter, EFUSE_CTRL+2,
- (rtl8723au_read8(pAdapter, EFUSE_CTRL+2)&0xFC)|(u8)((addr>>8)&0x03));
- rtl8723au_write8(pAdapter, EFUSE_CTRL, data);/* data */
+ rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
+ rtl8723au_write8(pAdapter, EFUSE_CTRL + 2,
+ (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
+ (u8)((addr >> 8) & 0x03));
+ rtl8723au_write8(pAdapter, EFUSE_CTRL, data); /* data */
- rtl8723au_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
+ rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
- while((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL+3)) &&
- (tmpidx<100)) {
+ while ((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) &&
+ (tmpidx < 100)) {
tmpidx++;
}
@@ -427,27 +332,8 @@ efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
return bResult;
}
-/*-----------------------------------------------------------------------------
- * Function: efuse_WordEnableDataRead23a
- *
- * Overview: Read allowed word in current efuse section data.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/16/2008 MHC Create Version 0.
- * 11/21/2008 MHC Fix Write bug when we only enable late word.
- *
- *---------------------------------------------------------------------------*/
-void
-efuse_WordEnableDataRead23a(u8 word_en,
- u8 *sourdata,
- u8 *targetdata)
+/* Read allowed word in current efuse section data. */
+void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata)
{
if (!(word_en&BIT(0))) {
targetdata[0] = sourdata[0];
@@ -477,15 +363,13 @@ static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
return efuse_OneByteWrite23a(padapter, address, *value);
}
-/*
- * read/write raw efuse data
- */
+/* read/write raw efuse data */
int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
u16 cnts, u8 *data)
{
int i = 0;
u16 real_content_len = 0, max_available_size = 0;
- int res = _FAIL ;
+ int res = _FAIL;
int (*rw8)(struct rtw_adapter *, u16, u8*);
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
@@ -507,7 +391,7 @@ int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
Efuse_PowerSwitch(padapter, bWrite, true);
- /* e-fuse one byte read / write */
+ /* e-fuse one byte read/write */
for (i = 0; i < cnts; i++) {
if (start_addr >= real_content_len) {
res = _FAIL;
@@ -523,16 +407,17 @@ int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
return res;
}
-/* */
+
u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
{
u16 max_size;
+
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
(void *)&max_size);
return max_size;
}
-/* */
+
int rtw_efuse_map_read23a(struct rtw_adapter *padapter,
u16 addr, u16 cnts, u8 *data)
{
@@ -573,26 +458,9 @@ int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter,
return _SUCCESS;
}
-/*-----------------------------------------------------------------------------
- * Function: Efuse_ReadAllMap
- *
- * Overview: Read All Efuse content
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/11/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-void
-Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
-void
-Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
+/* Read All Efuse content */
+static void Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType,
+ u8 *Efuse)
{
u16 mapLen = 0;
@@ -606,45 +474,32 @@ Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
Efuse_PowerSwitch(pAdapter, false, false);
}
-/*-----------------------------------------------------------------------------
- * Function: efuse_ShadowRead1Byte
- * efuse_ShadowRead2Byte
- * efuse_ShadowRead4Byte
- *
- * Overview: Read from efuse init map by one/two/four bytes !!!!!
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/12/2008 MHC Create Version 0.
+/*
+ * Functions: efuse_ShadowRead1Byte
+ * efuse_ShadowRead2Byte
+ * efuse_ShadowRead4Byte
*
- *---------------------------------------------------------------------------*/
-static void
-efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, u8 *Value)
+ * Read from efuse init map by one/two/four bytes
+ */
+static void efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset,
+ u8 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
*Value = pEEPROM->efuse_eeprom_data[Offset];
-} /* EFUSE_ShadowRead23a1Byte */
+}
-/* Read Two Bytes */
-static void
-efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, u16 *Value)
+static void efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset,
+ u16 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
*Value = pEEPROM->efuse_eeprom_data[Offset];
*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
-} /* EFUSE_ShadowRead23a2Byte */
+}
-/* Read Four Bytes */
-static void
-efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, u32 *Value)
+static void efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset,
+ u32 *Value)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
@@ -652,24 +507,9 @@ efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, u32 *Value)
*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
*Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
*Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
-} /* efuse_ShadowRead4Byte */
+}
-/*-----------------------------------------------------------------------------
- * Function: EFUSE_ShadowMapUpdate23a
- *
- * Overview: Transfer current EFUSE content to shadow init and modify map.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/13/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
+/* Transfer current EFUSE content to shadow init and modify map. */
void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
@@ -683,28 +523,11 @@ void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
else
Efuse_ReadAllMap(pAdapter, efuseType,
pEEPROM->efuse_eeprom_data);
+}
-}/* EFUSE_ShadowMapUpdate23a */
-
-/*-----------------------------------------------------------------------------
- * Function: EFUSE_ShadowRead23a
- *
- * Overview: Read from efuse init map !!!!!
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/12/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-void
-EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter,
- u8 Type, u16 Offset, u32 *Value)
+/* Read from efuse init map */
+void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type,
+ u16 Offset, u32 *Value)
{
if (Type == 1)
efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
@@ -712,4 +535,4 @@ EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter,
efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
else if (Type == 4)
efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
-} /* EFUSE_ShadowRead23a */
+}
diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
index 5e8736092720..cc2b84be9774 100644
--- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
@@ -525,7 +525,7 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
else
aSifsTime = 16;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < 4; i++) {
ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
index 9733aa6ef908..1662c03c1323 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
@@ -127,8 +127,7 @@ int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
u8 buf[5];
memset(buf, 0, 5);
- mask = cpu_to_le32(mask);
- memcpy(buf, &mask, 4);
+ put_unaligned_le32(mask, buf);
buf[4] = arg;
FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
diff --git a/drivers/staging/skein/skein_api.c b/drivers/staging/skein/skein_api.c
index 46a74fc40375..36f849fbba5e 100644
--- a/drivers/staging/skein/skein_api.c
+++ b/drivers/staging/skein/skein_api.c
@@ -50,7 +50,7 @@ int skein_init(struct skein_ctx *ctx, size_t hash_bit_len)
* memory available. The beauty of C :-) .
*/
x = ctx->m.s256.x;
- x_len = ctx->skein_size/8;
+ x_len = ctx->skein_size / 8;
/*
* If size is the same and hash bit length is zero then reuse
* the save chaining variables.
@@ -91,7 +91,7 @@ int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len,
skein_assert_ret(ctx, SKEIN_FAIL);
x = ctx->m.s256.x;
- x_len = ctx->skein_size/8;
+ x_len = ctx->skein_size / 8;
skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN);
@@ -135,7 +135,7 @@ void skein_reset(struct skein_ctx *ctx)
* memory available. The beautiy of C :-) .
*/
x = ctx->m.s256.x;
- x_len = ctx->skein_size/8;
+ x_len = ctx->skein_size / 8;
/* Restore the chaing variable, reset byte counter */
memcpy(x, ctx->x_save, x_len);
@@ -212,7 +212,7 @@ int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
/* partial byte bit mask */
mask = (u8) (1u << (7 - (msg_bit_cnt & 7)));
/* apply bit padding on final byte (in the buffer) */
- up[length-1] = (u8)((up[length-1] & (0-mask))|mask);
+ up[length - 1] = (u8)((up[length - 1] & (0 - mask)) | mask);
return SKEIN_SUCCESS;
}
diff --git a/drivers/staging/skein/skein_block.c b/drivers/staging/skein/skein_block.c
index dda5c003ad31..45b47327e024 100644
--- a/drivers/staging/skein/skein_block.c
+++ b/drivers/staging/skein/skein_block.c
@@ -212,7 +212,7 @@
#undef RCNT
#define RCNT (SKEIN_1024_ROUNDS_TOTAL/8)
#ifdef SKEIN_LOOP /* configure how much to unroll the loop */
-#define SKEIN_UNROLL_1024 ((SKEIN_LOOP)%10)
+#define SKEIN_UNROLL_1024 ((SKEIN_LOOP) % 10)
#else
#define SKEIN_UNROLL_1024 (0)
#endif
diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h
index 00b8af63e7ff..c95b3abad646 100644
--- a/drivers/staging/slicoss/slic.h
+++ b/drivers/staging/slicoss/slic.h
@@ -93,10 +93,10 @@ struct slic_rcvbuf_info {
u32 lastid;
};
/*
- SLIC Handle structure. Used to restrict handle values to
- 32 bits by using an index rather than an address.
- Simplifies ucode in 64-bit systems
-*/
+ * SLIC Handle structure. Used to restrict handle values to
+ * 32 bits by using an index rather than an address.
+ * Simplifies ucode in 64-bit systems
+ */
struct slic_handle_word {
union {
struct {
@@ -166,7 +166,6 @@ struct slic_cmdqueue {
#define SLIC_MAX_CARDS 32
#define SLIC_MAX_PORTS 4 /* Max # of ports per card */
-
struct mcast_address {
unsigned char address[6];
struct mcast_address *next;
@@ -334,10 +333,11 @@ struct physcard {
struct physcard *next;
uint adapters_allocd;
-/* the following is not currently needed
- u32 bridge_busnum;
- u32 bridge_cfg[NUM_CFG_SPACES][NUM_CFG_REG_ULONGS];
-*/
+/*
+ * the following is not currently needed
+ * u32 bridge_busnum;
+ * u32 bridge_cfg[NUM_CFG_SPACES][NUM_CFG_REG_ULONGS];
+ */
};
struct base_driver {
@@ -447,7 +447,7 @@ struct adapter {
* SLIC Handles
*/
/* Object handles*/
- struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1];
+ struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS + 1];
/* Free object handles*/
struct slic_handle *pfree_slic_handles;
/* Object handle list lock*/
@@ -485,7 +485,6 @@ struct adapter {
struct slicnet_stats slic_stats;
};
-
#define UPDATE_STATS(largestat, newstat, oldstat) \
{ \
if ((newstat) < (oldstat)) \
@@ -514,6 +513,6 @@ struct adapter {
#define FLUSH true
#define DONT_FLUSH false
-#define SIOCSLICSETINTAGG (SIOCDEVPRIVATE+10)
+#define SIOCSLICSETINTAGG (SIOCDEVPRIVATE + 10)
#endif /* __SLIC_DRIVER_H__ */
diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h
index 21cd02b8b7eb..9723b4a104f7 100644
--- a/drivers/staging/slicoss/slichw.h
+++ b/drivers/staging/slicoss/slichw.h
@@ -307,9 +307,11 @@ struct slic_regs {
u32 slic_hbar; /* Header buffer address reg */
u32 pad4;
- /* 31-8 - phy addr of set of contiguous hdr buffers
- 7-0 - number of buffers passed
- Buffers are 256 bytes long on 256-byte boundaries. */
+ /*
+ * 31-8 - phy addr of set of contiguous hdr buffers
+ * 7-0 - number of buffers passed
+ * Buffers are 256 bytes long on 256-byte boundaries.
+ */
#define SLIC_HBAR 0x0020
#define SLIC_HBAR_CNT_MSK 0x000000FF
@@ -321,10 +323,12 @@ struct slic_regs {
#define SLIC_DBAR_SIZE 2048
u32 slic_cbar; /* Xmt Cmd buf addr regs.*/
- /* 1 per XMT interface
- 31-5 - phy addr of host command buffer
- 4-0 - length of cmd in multiples of 32 bytes
- Buffers are 32 bytes up to 512 bytes long */
+ /*
+ * 1 per XMT interface
+ * 31-5 - phy addr of host command buffer
+ * 4-0 - length of cmd in multiples of 32 bytes
+ * Buffers are 32 bytes up to 512 bytes long
+ */
#define SLIC_CBAR 0x0030
#define SLIC_CBAR_LEN_MSK 0x0000001F
#define SLIC_CBAR_ALIGN 0x00000020
@@ -336,9 +340,11 @@ struct slic_regs {
u32 slic_rbar; /* Response buffer address reg.*/
u32 pad7;
- /*31-8 - phy addr of set of contiguous response buffers
- 7-0 - number of buffers passed
- Buffers are 32 bytes long on 32-byte boundaries.*/
+ /*
+ * 31-8 - phy addr of set of contiguous response buffers
+ * 7-0 - number of buffers passed
+ * Buffers are 32 bytes long on 32-byte boundaries.
+ */
#define SLIC_RBAR 0x0038
#define SLIC_RBAR_CNT_MSK 0x000000FF
#define SLIC_RBAR_SIZE 32
@@ -430,7 +436,8 @@ struct slic_regs {
#define SLIC_LOW_POWER 0x00e0
u32 slic_quiesce; /* force slic into quiescent state
- before soft reset */
+ * before soft reset
+ */
u32 pad30;
#define SLIC_QUIESCE 0x00e8
@@ -718,7 +725,8 @@ struct slic_eeprom {
u16 DSize2Pci; /* 15 DRAM size to PCI (bytes * 64K) */
u16 RSize2Pci; /* 16 ROM extension size to PCI (bytes * 4k) */
u8 NetIntPin1; /* 17 Network Interface Pin 1
- (simba/leone only) */
+ * (simba/leone only)
+ */
u8 NetIntPin2; /* Network Interface Pin 2 (simba/leone only)*/
union {
u8 NetIntPin3; /* 18 Network Interface Pin 3 (simba only) */
@@ -748,7 +756,8 @@ struct slic_eeprom {
union oemfru OemFru; /* optional OEM FRU information */
u8 Pad[4]; /* Pad to 128 bytes - includes 2 cksum bytes
* (if OEM FRU info exists) and two unusable
- * bytes at the end */
+ * bytes at the end
+ */
};
/* SLIC EEPROM structure for Oasis */
@@ -772,7 +781,8 @@ struct oslic_eeprom {
u16 FlashSize; /* 14 Flash size (bytes / 4K) */
u16 DSize2Pci; /* 15 DRAM size to PCI (bytes / 64K) */
u16 RSize2Pci; /* 16 Flash (ROM extension) size to PCI
- (bytes / 4K) */
+ * (bytes / 4K)
+ */
u16 DeviceId1; /* 17 Device Id (function 1) */
u16 DeviceId2; /* 18 Device Id (function 2) */
u16 CfgByte6; /* 19 Device Status Config Bytes 6-7 */
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 36001762fe20..b23a2d1f61a2 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -54,7 +54,6 @@
* IS-NIC driver.
*/
-
#define KLUDGE_FOR_4GB_BOUNDARY 1
#define DEBUG_MICROCODE 1
#define DBG 1
@@ -159,17 +158,20 @@ static void slic_mcast_set_bit(struct adapter *adapter, char *address)
unsigned char crcpoly;
/* Get the CRC polynomial for the mac address */
- /* we use bits 1-8 (lsb), bitwise reversed,
- * msb (= lsb bit 0 before bitrev) is automatically discarded */
- crcpoly = ether_crc(ETH_ALEN, address)>>23;
+ /*
+ * we use bits 1-8 (lsb), bitwise reversed,
+ * msb (= lsb bit 0 before bitrev) is automatically discarded
+ */
+ crcpoly = ether_crc(ETH_ALEN, address) >> 23;
- /* We only have space on the SLIC for 64 entries. Lop
+ /*
+ * We only have space on the SLIC for 64 entries. Lop
* off the top two bits. (2^6 = 64)
*/
crcpoly &= 0x3F;
/* OR in the new bit into our 64 bit mask. */
- adapter->mcastmask |= (u64) 1 << crcpoly;
+ adapter->mcastmask |= (u64)1 << crcpoly;
}
static void slic_mcast_set_mask(struct adapter *adapter)
@@ -177,7 +179,8 @@ static void slic_mcast_set_mask(struct adapter *adapter)
__iomem struct slic_regs *slic_regs = adapter->slic_regs;
if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) {
- /* Turn on all multicast addresses. We have to do this for
+ /*
+ * Turn on all multicast addresses. We have to do this for
* promiscuous mode as well as ALLMCAST mode. It saves the
* Microcode from having to keep state about the MAC
* configuration.
@@ -186,7 +189,8 @@ static void slic_mcast_set_mask(struct adapter *adapter)
slic_reg32_write(&slic_regs->slic_mcasthigh, 0xFFFFFFFF,
FLUSH);
} else {
- /* Commit our multicast mast to the SLIC by writing to the
+ /*
+ * Commit our multicast mast to the SLIC by writing to the
* multicast address mask registers
*/
slic_reg32_write(&slic_regs->slic_mcastlow,
@@ -243,7 +247,8 @@ static void slic_link_config(struct adapter *adapter,
if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) {
if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) {
- /* We've got a fiber gigabit interface, and register
+ /*
+ * We've got a fiber gigabit interface, and register
* 4 is different in fiber mode than in copper mode
*/
@@ -261,16 +266,22 @@ static void slic_link_config(struct adapter *adapter,
PCR_AUTONEG_RST));
slic_reg32_write(wphy, phy_config, FLUSH);
} else { /* forced 1000 Mb FD*/
- /* power down phy to break link
- this may not work) */
+ /*
+ * power down phy to break link
+ * this may not work)
+ */
phy_config = (MIICR_REG_PCR | PCR_POWERDOWN);
slic_reg32_write(wphy, phy_config, FLUSH);
- /* wait, Marvell says 1 sec,
- try to get away with 10 ms */
+ /*
+ * wait, Marvell says 1 sec,
+ * try to get away with 10 ms
+ */
mdelay(10);
- /* disable auto-neg, set speed/duplex,
- soft reset phy, powerup */
+ /*
+ * disable auto-neg, set speed/duplex,
+ * soft reset phy, powerup
+ */
phy_config =
(MIICR_REG_PCR |
(PCR_RESET | PCR_SPEED_1000 |
@@ -279,7 +290,8 @@ static void slic_link_config(struct adapter *adapter,
}
} else { /* copper gigabit */
- /* Auto-Negotiate or 1000 Mb must be auto negotiated
+ /*
+ * Auto-Negotiate or 1000 Mb must be auto negotiated
* We've got a copper gigabit interface, and
* register 4 is different in copper mode than
* in fiber mode
@@ -291,8 +303,10 @@ static void slic_link_config(struct adapter *adapter,
(PAR_ADV100FD | PAR_ADV100HD | PAR_ADV10FD
| PAR_ADV10HD));
} else {
- /* linkspeed == LINK_1000MB -
- don't advertise 10/100 Mb modes */
+ /*
+ * linkspeed == LINK_1000MB -
+ * don't advertise 10/100 Mb modes
+ */
phy_advreg = MIICR_REG_4;
}
/* enable PAUSE frames */
@@ -305,8 +319,10 @@ static void slic_link_config(struct adapter *adapter,
slic_reg32_write(wphy, phy_gctlreg, FLUSH);
if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
- /* if a Marvell PHY
- enable auto crossover */
+ /*
+ * if a Marvell PHY
+ * enable auto crossover
+ */
phy_config =
(MIICR_REG_16 | (MRV_REG16_XOVERON));
slic_reg32_write(wphy, phy_config, FLUSH);
@@ -337,8 +353,10 @@ static void slic_link_config(struct adapter *adapter,
duplex = PCR_DUPLEX_FULL;
if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
- /* if a Marvell PHY
- disable auto crossover */
+ /*
+ * if a Marvell PHY
+ * disable auto crossover
+ */
phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF));
slic_reg32_write(wphy, phy_config, FLUSH);
}
@@ -351,9 +369,11 @@ static void slic_link_config(struct adapter *adapter,
mdelay(10);
if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
- /* if a Marvell PHY
- disable auto-neg, set speed,
- soft reset phy, powerup */
+ /*
+ * if a Marvell PHY
+ * disable auto-neg, set speed,
+ * soft reset phy, powerup
+ */
phy_config =
(MIICR_REG_PCR | (PCR_RESET | speed | duplex));
slic_reg32_write(wphy, phy_config, FLUSH);
@@ -530,11 +550,13 @@ static int slic_card_download(struct adapter *adapter)
index += 4;
/* Check SRAM location zero. If it is non-zero. Abort.*/
-/* failure = readl((u32 __iomem *)&slic_regs->slic_reset);
- if (failure) {
- release_firmware(fw);
- return -EIO;
- }*/
+ /*
+ * failure = readl((u32 __iomem *)&slic_regs->slic_reset);
+ * if (failure) {
+ * release_firmware(fw);
+ * return -EIO;
+ * }
+ */
}
}
release_firmware(fw);
@@ -542,8 +564,10 @@ static int slic_card_download(struct adapter *adapter)
mdelay(10);
slic_reg32_write(&slic_regs->slic_wcs, SLIC_WCS_START, FLUSH);
- /* stall for 20 ms, long enough for ucode to init card
- and reach mainloop */
+ /*
+ * stall for 20 ms, long enough for ucode to init card
+ * and reach mainloop
+ */
mdelay(20);
return 0;
@@ -593,19 +617,21 @@ static void slic_mac_address_config(struct adapter *adapter)
u32 value2;
__iomem struct slic_regs *slic_regs = adapter->slic_regs;
- value = ntohl(*(__be32 *) &adapter->currmacaddr[2]);
+ value = ntohl(*(__be32 *)&adapter->currmacaddr[2]);
slic_reg32_write(&slic_regs->slic_wraddral, value, FLUSH);
slic_reg32_write(&slic_regs->slic_wraddrbl, value, FLUSH);
- value2 = (u32) ((adapter->currmacaddr[0] << 8 |
+ value2 = (u32)((adapter->currmacaddr[0] << 8 |
adapter->currmacaddr[1]) & 0xFFFF);
slic_reg32_write(&slic_regs->slic_wraddrah, value2, FLUSH);
slic_reg32_write(&slic_regs->slic_wraddrbh, value2, FLUSH);
- /* Write our multicast mask out to the card. This is done */
- /* here in addition to the slic_mcast_addr_set routine */
- /* because ALL_MCAST may have been enabled or disabled */
+ /*
+ * Write our multicast mask out to the card. This is done
+ * here in addition to the slic_mcast_addr_set routine
+ * because ALL_MCAST may have been enabled or disabled
+ */
slic_mcast_set_mask(adapter);
}
@@ -886,10 +912,10 @@ static void slic_upr_start(struct adapter *adapter)
struct slic_upr *upr;
__iomem struct slic_regs *slic_regs = adapter->slic_regs;
/*
- char * ptr1;
- char * ptr2;
- uint cmdoffset;
-*/
+ * char * ptr1;
+ * char * ptr2;
+ * uint cmdoffset;
+ */
upr = adapter->upr_list;
if (!upr)
return;
@@ -971,7 +997,7 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
#else
slic_upr_queue_request(adapter,
SLIC_UPR_RLSR,
- (u32) &pshmem->linkstatus,
+ (u32)&pshmem->linkstatus,
SLIC_GET_ADDR_HIGH(pshmem), 0, 0);
#endif
return;
@@ -1041,7 +1067,7 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
case SLIC_UPR_STATS:
{
struct slic_stats *slicstats =
- (struct slic_stats *) &adapter->pshmem->inicstats;
+ (struct slic_stats *)&adapter->pshmem->inicstats;
struct slic_stats *newstats = slicstats;
struct slic_stats *old = &adapter->inicstats_prev;
struct slicnet_stats *stst = &adapter->slic_stats;
@@ -1147,8 +1173,7 @@ static u16 slic_eeprom_cksum(void *eeprom, unsigned len)
}
if (len > 0)
- checksum += *(u8 *) wp;
-
+ checksum += *(u8 *)wp;
while (checksum >> 16)
checksum = (checksum & 0xFFFF) + ((checksum >> 16) & 0xFFFF);
@@ -1246,7 +1271,7 @@ static void slic_cmdqmem_free(struct adapter *adapter)
if (cmdqmem->pages[i]) {
pci_free_consistent(adapter->pcidev,
PAGE_SIZE,
- (void *) cmdqmem->pages[i],
+ (void *)cmdqmem->pages[i],
cmdqmem->dma_pages[i]);
}
}
@@ -1326,8 +1351,8 @@ static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page)
adapter->pfree_slic_handles = pslic_handle->next;
spin_unlock_irqrestore(&adapter->handle_lock, flags);
pslic_handle->type = SLIC_HANDLE_CMD;
- pslic_handle->address = (void *) cmd;
- pslic_handle->offset = (ushort) adapter->slic_handle_ix++;
+ pslic_handle->address = (void *)cmd;
+ pslic_handle->offset = (ushort)adapter->slic_handle_ix++;
pslic_handle->other_handle = NULL;
pslic_handle->next = NULL;
@@ -1737,7 +1762,7 @@ static int slic_link_event_handler(struct adapter *adapter)
0, 0);
#else
status = slic_upr_request(adapter, SLIC_UPR_RLSR,
- (u32) &pshmem->linkstatus, /* no 4GB wrap guaranteed */
+ (u32)&pshmem->linkstatus, /* no 4GB wrap guaranteed */
0, 0, 0);
#endif
return status;
@@ -1805,7 +1830,7 @@ static void slic_mcast_set_list(struct net_device *dev)
struct netdev_hw_addr *ha;
netdev_for_each_mc_addr(ha, dev) {
- addresses = (char *) &ha->addr;
+ addresses = (char *)&ha->addr;
status = slic_mcast_add_list(adapter, addresses);
if (status != 0)
break;
@@ -1853,8 +1878,8 @@ static void slic_xmit_build_request(struct adapter *adapter,
ihcmd->u.slic_buffers.bufs[0].paddrh = SLIC_GET_ADDR_HIGH(phys_addr);
ihcmd->u.slic_buffers.bufs[0].length = skb->len;
#if BITS_PER_LONG == 64
- hcmd->cmdsize = (u32) ((((u64)&ihcmd->u.slic_buffers.bufs[1] -
- (u64) hcmd) + 31) >> 5);
+ hcmd->cmdsize = (u32)((((u64)&ihcmd->u.slic_buffers.bufs[1] -
+ (u64)hcmd) + 31) >> 5);
#else
hcmd->cmdsize = (((u32)&ihcmd->u.slic_buffers.bufs[1] -
(u32)hcmd) + 31) >> 5;
@@ -2051,8 +2076,8 @@ static void slic_xmit_complete(struct adapter *adapter)
adapter->xmit_completes++;
adapter->card->events++;
/*
- Get the complete host command buffer
- */
+ * Get the complete host command buffer
+ */
slic_handle_word.handle_token = rspbuf->hosthandle;
hcmd =
adapter->slic_handles[slic_handle_word.handle_index].
@@ -2131,7 +2156,6 @@ static void slic_interrupt_card_up(u32 isr, struct adapter *adapter,
}
}
-
static irqreturn_t slic_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
@@ -2228,7 +2252,6 @@ xmit_fail:
goto xmit_done;
}
-
static void slic_adapter_freeresources(struct adapter *adapter)
{
slic_init_cleanup(adapter);
@@ -2753,7 +2776,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter)
/* Oasis card */
case SLIC_2GB_DEVICE_ID:
/* extract EEPROM data and pointers to EEPROM data */
- pOeeprom = (struct oslic_eeprom *) peeprom;
+ pOeeprom = (struct oslic_eeprom *)peeprom;
eecodesize = pOeeprom->EecodeSize;
dramsize = pOeeprom->DramSize;
pmac = pOeeprom->MacInfo;
@@ -2762,10 +2785,12 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter)
oemfruformat = pOeeprom->OemFruFormat;
poemfru = &pOeeprom->OemFru;
macaddrs = 2;
- /* Minor kludge for Oasis card
- get 2 MAC addresses from the
- EEPROM to ensure that function 1
- gets the Port 1 MAC address */
+ /*
+ * Minor kludge for Oasis card
+ * get 2 MAC addresses from the
+ * EEPROM to ensure that function 1
+ * gets the Port 1 MAC address
+ */
break;
default:
/* extract EEPROM data and pointers to EEPROM data */
@@ -2786,16 +2811,16 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter)
(eecodesize >= MIN_EECODE_SIZE)) {
ee_chksum =
- *(u16 *) ((char *) peeprom + (eecodesize - 2));
+ *(u16 *)((char *)peeprom + (eecodesize - 2));
/*
- calculate the EEPROM checksum
- */
+ * calculate the EEPROM checksum
+ */
calc_chksum = slic_eeprom_cksum(peeprom,
eecodesize - 2);
/*
- if the ucdoe chksum flag bit worked,
- we wouldn't need this
- */
+ * if the ucdoe chksum flag bit worked,
+ * we wouldn't need this
+ */
if (ee_chksum == calc_chksum)
card->config.EepromValid = true;
}
@@ -2894,11 +2919,11 @@ static void slic_init_adapter(struct net_device *netdev,
adapter->card_size = 1;
/*
- Initialize slic_handle array
- */
+ * Initialize slic_handle array
+ */
/*
- Start with 1. 0 is an invalid host handle.
- */
+ * Start with 1. 0 is an invalid host handle.
+ */
for (index = 1, pslic_handle = &adapter->slic_handles[1];
index < SLIC_CMDQ_MAXCMDS; index++, pslic_handle++) {
@@ -2949,11 +2974,11 @@ static u32 slic_card_locate(struct adapter *adapter)
}
hostid_reg =
- (u16 __iomem *) (((u8 __iomem *) (adapter->slic_regs)) +
+ (u16 __iomem *)(((u8 __iomem *)(adapter->slic_regs)) +
rdhostid_offset);
/* read the 16 bit hostid from SRAM */
- card_hostid = (ushort) readw(hostid_reg);
+ card_hostid = (ushort)readw(hostid_reg);
/* Initialize a new card structure if need be */
if (card_hostid == SLIC_HOSTID_DEFAULT) {
@@ -3099,7 +3124,6 @@ static int slic_entry_probe(struct pci_dev *pcidev,
mmio_start = pci_resource_start(pcidev, 0);
mmio_len = pci_resource_len(pcidev, 0);
-
/* memmapped_ioaddr = (u32)ioremap_nocache(mmio_start, mmio_len);*/
memmapped_ioaddr = ioremap(mmio_start, mmio_len);
if (!memmapped_ioaddr) {
@@ -3135,7 +3159,7 @@ static int slic_entry_probe(struct pci_dev *pcidev,
slic_adapter_set_hwaddr(adapter);
- netdev->base_addr = (unsigned long) memmapped_ioaddr;
+ netdev->base_addr = (unsigned long)memmapped_ioaddr;
netdev->irq = adapter->irq;
netdev->netdev_ops = &slic_netdev_ops;
diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c
index bab3d91c70bf..0331d34458ae 100644
--- a/drivers/staging/sm750fb/ddk750_chip.c
+++ b/drivers/staging/sm750fb/ddk750_chip.c
@@ -4,13 +4,6 @@
#include "ddk750_reg.h"
#include "ddk750_chip.h"
#include "ddk750_power.h"
-typedef struct _pllcalparam {
- unsigned char power;/* d : 0~ 6*/
- unsigned char pod;
- unsigned char od;
- unsigned char value;/* value of 2 power d (2^d) */
-}
-pllcalparam;
logical_chip_type_t getChipType(void)
{
@@ -60,11 +53,10 @@ static void setChipClock(unsigned int frequency)
{
pll_value_t pll;
unsigned int ulActualMxClk;
-#if 1
+
/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
return;
-#endif
if (frequency) {
/*
@@ -88,11 +80,11 @@ static void setChipClock(unsigned int frequency)
static void setMemoryClock(unsigned int frequency)
{
unsigned int ulReg, divisor;
- #if 1
+
/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
return;
-#endif
+
if (frequency) {
/* Set the frequency to the maximum frequency that the DDR Memory can take
which is 336MHz. */
@@ -135,11 +127,11 @@ static void setMemoryClock(unsigned int frequency)
static void setMasterClock(unsigned int frequency)
{
unsigned int ulReg, divisor;
-#if 1
+
/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
return;
-#endif
+
if (frequency) {
/* Set the frequency to the maximum frequency that the SM750 engine can
run, which is about 190 MHz. */
@@ -304,41 +296,20 @@ int ddk750_initHw(initchip_param_t *pInitParam)
*/
unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
{
- /* used for primary and secondary channel pixel clock pll */
- static pllcalparam xparm_PIXEL[] = {
- /* 2^0 = 1*/ {0, 0, 0, 1},
- /* 2^ 1 =2*/ {1, 0, 1, 2},
- /* 2^ 2 = 4*/ {2, 0, 2, 4},
- {3, 0, 3, 8},
- {4, 1, 3, 16},
- {5, 2, 3, 32},
- /* 2^6 = 64 */ {6, 3, 3, 64},
- };
-
- /* used for MXCLK (chip clock) */
- static pllcalparam xparm_MXCLK[] = {
- /* 2^0 = 1*/ {0, 0, 0, 1},
- /* 2^ 1 =2*/ {1, 0, 1, 2},
- /* 2^ 2 = 4*/ {2, 0, 2, 4},
- {3, 0, 3, 8},
- };
-
/* as sm750 register definition, N located in 2,15 and M located in 1,255 */
int N, M, X, d;
- int xcnt;
int mini_diff;
unsigned int RN, quo, rem, fl_quo;
unsigned int input, request;
unsigned int tmpClock, ret;
- pllcalparam *xparm;
+ const int max_OD = 3;
+ int max_d;
-#if 1
if (getChipType() == SM750LE) {
/* SM750LE don't have prgrammable PLL and M/N values to work on.
Just return the requested clock. */
return request_orig;
}
-#endif
ret = 0;
mini_diff = ~0;
@@ -346,15 +317,8 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
input = pll->inputFreq / 1000;
/* for MXCLK register , no POD provided, so need be treated differently */
-
- if (pll->clockType != MXCLK_PLL) {
- xparm = &xparm_PIXEL[0];
- xcnt = ARRAY_SIZE(xparm_PIXEL);
- } else {
- xparm = &xparm_MXCLK[0];
- xcnt = ARRAY_SIZE(xparm_MXCLK);
- }
-
+ if (pll->clockType == MXCLK_PLL)
+ max_d = 3;
for (N = 15; N > 1; N--) {
/* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
@@ -363,8 +327,8 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
rem = RN % input;/* rem always small than 14318181 */
fl_quo = (rem * 10000 / input);
- for (d = xcnt - 1; d >= 0; d--) {
- X = xparm[d].value;
+ for (d = max_d; d >= 0; d--) {
+ X = (1 << d);
M = quo * X;
M += fl_quo * X / 10000;
/* round step */
@@ -377,8 +341,10 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
if (diff < mini_diff) {
pll->M = M;
pll->N = N;
- pll->OD = xparm[d].od;
- pll->POD = xparm[d].pod;
+ pll->POD = 0;
+ if (d > max_OD)
+ pll->POD = d - max_OD;
+ pll->OD = d - pll->POD;
mini_diff = diff;
ret = tmpClock;
}
diff --git a/drivers/staging/sm750fb/ddk750_help.h b/drivers/staging/sm750fb/ddk750_help.h
index 9b2d2d2c899b..5be814eed735 100644
--- a/drivers/staging/sm750fb/ddk750_help.h
+++ b/drivers/staging/sm750fb/ddk750_help.h
@@ -4,8 +4,8 @@
#ifndef USE_INTERNAL_REGISTER_ACCESS
#include <linux/ioport.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
#include "sm750_help.h"
/* software control endianness */
diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c
index 2399b175ade0..fa35926680ab 100644
--- a/drivers/staging/sm750fb/ddk750_mode.c
+++ b/drivers/staging/sm750fb/ddk750_mode.c
@@ -168,14 +168,13 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
*/
POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
-#if 1
+
while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
cnt++;
if (cnt > 1000)
break;
POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
}
-#endif
} else {
ret = -1;
}
diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c
index 198ff81161b1..667e4f822544 100644
--- a/drivers/staging/sm750fb/ddk750_power.c
+++ b/drivers/staging/sm750fb/ddk750_power.c
@@ -108,7 +108,7 @@ void setCurrentGate(unsigned int gate)
*/
void enable2DEngine(unsigned int enable)
{
- uint32_t gate;
+ u32 gate;
gate = PEEK32(CURRENT_GATE);
if (enable) {
@@ -124,7 +124,7 @@ void enable2DEngine(unsigned int enable)
void enableDMA(unsigned int enable)
{
- uint32_t gate;
+ u32 gate;
/* Enable DMA Gate */
gate = PEEK32(CURRENT_GATE);
@@ -141,7 +141,7 @@ void enableDMA(unsigned int enable)
*/
void enableGPIO(unsigned int enable)
{
- uint32_t gate;
+ u32 gate;
/* Enable GPIO Gate */
gate = PEEK32(CURRENT_GATE);
@@ -158,7 +158,7 @@ void enableGPIO(unsigned int enable)
*/
void enableI2C(unsigned int enable)
{
- uint32_t gate;
+ u32 gate;
/* Enable I2C Gate */
gate = PEEK32(CURRENT_GATE);
diff --git a/drivers/staging/sm750fb/modedb.h b/drivers/staging/sm750fb/modedb.h
deleted file mode 100644
index 83cb2e2ae51a..000000000000
--- a/drivers/staging/sm750fb/modedb.h
+++ /dev/null
@@ -1,233 +0,0 @@
-
-static const struct fb_videomode modedb2[] = {
- {
- /* 640x400 @ 70 Hz, 31.5 kHz hsync */
- NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x480 @ 60 Hz, 31.5 kHz hsync */
- NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 800x600 @ 56 Hz, 35.15 kHz hsync */
- NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
- NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8,
- 0, FB_VMODE_INTERLACED
- }, {
- /* 640x400 @ 85 Hz, 37.86 kHz hsync */
- NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
- FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
- }, {
- /* 640x480 @ 72 Hz, 36.5 kHz hsync */
- NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x480 @ 75 Hz, 37.50 kHz hsync */
- NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 800x600 @ 60 Hz, 37.8 kHz hsync */
- NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 640x480 @ 85 Hz, 43.27 kHz hsync */
- NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
- NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
- 0, FB_VMODE_INTERLACED
- }, {
- /* 800x600 @ 72 Hz, 48.0 kHz hsync */
- NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1024x768 @ 60 Hz, 48.4 kHz hsync */
- NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x480 @ 100 Hz, 53.01 kHz hsync */
- NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1152x864 @ 60 Hz, 53.5 kHz hsync */
- NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 800x600 @ 85 Hz, 55.84 kHz hsync */
- NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1024x768 @ 70 Hz, 56.5 kHz hsync */
- NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x960-60 VESA */
- NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA
- }, {
- /* 1280x1024-60 VESA */
- NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA
- }, {
- /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
- NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,
- 0, FB_VMODE_INTERLACED
- }, {
- /* 800x600 @ 100 Hz, 64.02 kHz hsync */
- NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1024x768 @ 76 Hz, 62.5 kHz hsync */
- NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1152x864 @ 70 Hz, 62.4 kHz hsync */
- NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
- NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1400x1050 @ 60Hz, 63.9 kHz hsync */
- NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
- NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
- NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1024x768 @ 85 Hz, 70.24 kHz hsync */
- NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1152x864 @ 78 Hz, 70.8 kHz hsync */
- NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
- NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1600x1200 @ 60Hz, 75.00 kHz hsync */
- NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1152x864 @ 84 Hz, 76.0 kHz hsync */
- NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
- NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1024x768 @ 100Hz, 80.21 kHz hsync */
- NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
- NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
- NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1152x864 @ 100 Hz, 89.62 kHz hsync */
- NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
- NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
- NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
- NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
- NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1800x1440 @ 64Hz, 96.15 kHz hsync */
- NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 1800x1440 @ 70Hz, 104.52 kHz hsync */
- NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, {
- /* 512x384 @ 78 Hz, 31.50 kHz hsync */
- NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 512x384 @ 85 Hz, 34.38 kHz hsync */
- NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
- NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
- NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 320x240 @ 72 Hz, 36.5 kHz hsync */
- NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
- NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 400x300 @ 60 Hz, 37.8 kHz hsync */
- NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 400x300 @ 72 Hz, 48.0 kHz hsync */
- NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
- NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 480x300 @ 60 Hz, 37.8 kHz hsync */
- NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 480x300 @ 63 Hz, 39.6 kHz hsync */
- NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2,
- 0, FB_VMODE_DOUBLE
- }, {
- /* 480x300 @ 72 Hz, 48.0 kHz hsync */
- NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
- 0, FB_VMODE_DOUBLE
- },
-};
-static const int nmodedb2 = sizeof(modedb2);
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 805a403eaba4..c78421b5b0e7 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -18,14 +18,9 @@
#include <linux/console.h>
#include <asm/fb.h>
#include "sm750.h"
-#include "sm750_hw.h"
#include "sm750_accel.h"
#include "sm750_cursor.h"
-#include "modedb.h"
-
-int smi_indent;
-
/*
* #ifdef __BIG_ENDIAN
* ssize_t lynxfb_ops_write(struct fb_info *info, const char __user *buf,
@@ -35,10 +30,6 @@ int smi_indent;
* #endif
*/
-typedef void (*PROC_SPEC_SETUP)(struct lynx_share*, char *);
-typedef int (*PROC_SPEC_MAP)(struct lynx_share*, struct pci_dev*);
-typedef int (*PROC_SPEC_INITHW)(struct lynx_share*, struct pci_dev*);
-
/* common var for all device */
static int g_hwcursor = 1;
static int g_noaccel;
@@ -129,16 +120,16 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
return -ENXIO;
}
- cursor->disable(cursor);
+ hw_cursor_disable(cursor);
if (fbcursor->set & FB_CUR_SETSIZE)
- cursor->setSize(cursor,
- fbcursor->image.width,
- fbcursor->image.height);
+ hw_cursor_setSize(cursor,
+ fbcursor->image.width,
+ fbcursor->image.height);
if (fbcursor->set & FB_CUR_SETPOS)
- cursor->setPos(cursor,
- fbcursor->image.dx - info->var.xoffset,
- fbcursor->image.dy - info->var.yoffset);
+ hw_cursor_setPos(cursor,
+ fbcursor->image.dx - info->var.xoffset,
+ fbcursor->image.dy - info->var.yoffset);
if (fbcursor->set & FB_CUR_SETCMAP) {
/* get the 16bit color of kernel means */
@@ -152,18 +143,18 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5) |
((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11);
- cursor->setColor(cursor, fg, bg);
+ hw_cursor_setColor(cursor, fg, bg);
}
if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
- cursor->setData(cursor,
- fbcursor->rop,
- fbcursor->image.data,
- fbcursor->mask);
+ hw_cursor_setData(cursor,
+ fbcursor->rop,
+ fbcursor->image.data,
+ fbcursor->mask);
}
if (fbcursor->enable)
- cursor->enable(cursor);
+ hw_cursor_enable(cursor);
return 0;
}
@@ -172,7 +163,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info,
const struct fb_fillrect *region)
{
struct lynxfb_par *par;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
unsigned int base, pitch, Bpp, rop;
u32 color;
@@ -180,7 +171,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info,
return;
par = info->par;
- share = par->share;
+ sm750_dev = par->dev;
/*
* each time 2d function begin to work,below three variable always need
@@ -198,27 +189,27 @@ static void lynxfb_ops_fillrect(struct fb_info *info,
* If not use spin_lock,system will die if user load driver
* and immediately unload driver frequently (dual)
*/
- if (share->dual)
- spin_lock(&share->slock);
-
- share->accel.de_fillrect(&share->accel,
- base, pitch, Bpp,
- region->dx, region->dy,
- region->width, region->height,
- color, rop);
- if (share->dual)
- spin_unlock(&share->slock);
+ if (sm750_dev->dual)
+ spin_lock(&sm750_dev->slock);
+
+ sm750_dev->accel.de_fillrect(&sm750_dev->accel,
+ base, pitch, Bpp,
+ region->dx, region->dy,
+ region->width, region->height,
+ color, rop);
+ if (sm750_dev->dual)
+ spin_unlock(&sm750_dev->slock);
}
static void lynxfb_ops_copyarea(struct fb_info *info,
const struct fb_copyarea *region)
{
struct lynxfb_par *par;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
unsigned int base, pitch, Bpp;
par = info->par;
- share = par->share;
+ sm750_dev = par->dev;
/*
* each time 2d function begin to work,below three variable always need
@@ -232,15 +223,16 @@ static void lynxfb_ops_copyarea(struct fb_info *info,
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
*/
- if (share->dual)
- spin_lock(&share->slock);
-
- share->accel.de_copyarea(&share->accel,
- base, pitch, region->sx, region->sy,
- base, pitch, Bpp, region->dx, region->dy,
- region->width, region->height, HW_ROP2_COPY);
- if (share->dual)
- spin_unlock(&share->slock);
+ if (sm750_dev->dual)
+ spin_lock(&sm750_dev->slock);
+
+ sm750_dev->accel.de_copyarea(&sm750_dev->accel,
+ base, pitch, region->sx, region->sy,
+ base, pitch, Bpp, region->dx, region->dy,
+ region->width, region->height,
+ HW_ROP2_COPY);
+ if (sm750_dev->dual)
+ spin_unlock(&sm750_dev->slock);
}
static void lynxfb_ops_imageblit(struct fb_info *info,
@@ -249,10 +241,10 @@ static void lynxfb_ops_imageblit(struct fb_info *info,
unsigned int base, pitch, Bpp;
unsigned int fgcol, bgcol;
struct lynxfb_par *par;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
par = info->par;
- share = par->share;
+ sm750_dev = par->dev;
/*
* each time 2d function begin to work,below three variable always need
* be set, seems we can put them together in some place
@@ -280,17 +272,17 @@ static void lynxfb_ops_imageblit(struct fb_info *info,
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
*/
- if (share->dual)
- spin_lock(&share->slock);
-
- share->accel.de_imageblit(&share->accel,
- image->data, image->width >> 3, 0,
- base, pitch, Bpp,
- image->dx, image->dy,
- image->width, image->height,
- fgcol, bgcol, HW_ROP2_COPY);
- if (share->dual)
- spin_unlock(&share->slock);
+ if (sm750_dev->dual)
+ spin_lock(&sm750_dev->slock);
+
+ sm750_dev->accel.de_imageblit(&sm750_dev->accel,
+ image->data, image->width >> 3, 0,
+ base, pitch, Bpp,
+ image->dx, image->dy,
+ image->width, image->height,
+ fgcol, bgcol, HW_ROP2_COPY);
+ if (sm750_dev->dual)
+ spin_unlock(&sm750_dev->slock);
}
static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var,
@@ -304,13 +296,12 @@ static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var,
par = info->par;
crtc = &par->crtc;
- return crtc->proc_panDisplay(crtc, var, info);
+ return hw_sm750_pan_display(crtc, var, info);
}
static int lynxfb_ops_set_par(struct fb_info *info)
{
struct lynxfb_par *par;
- struct lynx_share *share;
struct lynxfb_crtc *crtc;
struct lynxfb_output *output;
struct fb_var_screeninfo *var;
@@ -323,7 +314,6 @@ static int lynxfb_ops_set_par(struct fb_info *info)
ret = 0;
par = info->par;
- share = par->share;
crtc = &par->crtc;
output = &par->output;
var = &info->var;
@@ -331,7 +321,7 @@ static int lynxfb_ops_set_par(struct fb_info *info)
/* fix structur is not so FIX ... */
line_length = var->xres_virtual * var->bits_per_pixel / 8;
- line_length = PADDING(crtc->line_pad, line_length);
+ line_length = ALIGN(line_length, crtc->line_pad);
fix->line_length = line_length;
pr_info("fix->line_length = %d\n", fix->line_length);
@@ -384,9 +374,9 @@ static int lynxfb_ops_set_par(struct fb_info *info)
pr_err("pixel bpp format not satisfied\n.");
return ret;
}
- ret = crtc->proc_setMode(crtc, var, fix);
+ ret = hw_sm750_crtc_setMode(crtc, var, fix);
if (!ret)
- ret = output->proc_setMode(output, var, fix);
+ ret = hw_sm750_output_setMode(output, var, fix);
return ret;
}
@@ -402,14 +392,14 @@ static inline unsigned int chan_to_field(unsigned int chan,
static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
struct fb_info *info;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
int ret;
if (mesg.event == pdev->dev.power.power_state.event)
return 0;
ret = 0;
- share = pci_get_drvdata(pdev);
+ sm750_dev = pci_get_drvdata(pdev);
switch (mesg.event) {
case PM_EVENT_FREEZE:
case PM_EVENT_PRETHAW:
@@ -419,11 +409,11 @@ static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
console_lock();
if (mesg.event & PM_EVENT_SLEEP) {
- info = share->fbinfo[0];
+ info = sm750_dev->fbinfo[0];
if (info)
/* 1 means do suspend */
fb_set_suspend(info, 1);
- info = share->fbinfo[1];
+ info = sm750_dev->fbinfo[1];
if (info)
/* 1 means do suspend */
fb_set_suspend(info, 1);
@@ -434,10 +424,6 @@ static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
return ret;
}
- /* set chip to sleep mode */
- if (share->suspend)
- (*share->suspend)(share);
-
pci_disable_device(pdev);
ret = pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
if (ret) {
@@ -454,7 +440,7 @@ static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
static int lynxfb_resume(struct pci_dev *pdev)
{
struct fb_info *info;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
struct lynxfb_par *par;
struct lynxfb_crtc *crtc;
@@ -463,7 +449,7 @@ static int lynxfb_resume(struct pci_dev *pdev)
int ret;
ret = 0;
- share = pci_get_drvdata(pdev);
+ sm750_dev = pci_get_drvdata(pdev);
console_lock();
@@ -482,12 +468,10 @@ static int lynxfb_resume(struct pci_dev *pdev)
}
pci_set_master(pdev);
}
- if (share->resume)
- (*share->resume)(share);
- hw_sm750_inithw(share, pdev);
+ hw_sm750_inithw(sm750_dev, pdev);
- info = share->fbinfo[0];
+ info = sm750_dev->fbinfo[0];
if (info) {
par = info->par;
@@ -499,7 +483,7 @@ static int lynxfb_resume(struct pci_dev *pdev)
fb_set_suspend(info, 0);
}
- info = share->fbinfo[1];
+ info = sm750_dev->fbinfo[1];
if (info) {
par = info->par;
@@ -523,13 +507,11 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
struct lynxfb_par *par;
struct lynxfb_crtc *crtc;
struct lynxfb_output *output;
- struct lynx_share *share;
resource_size_t request;
par = info->par;
crtc = &par->crtc;
output = &par->output;
- share = par->share;
pr_debug("check var:%dx%d-%d\n",
var->xres,
@@ -580,14 +562,14 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
request = var->xres_virtual * (var->bits_per_pixel >> 3);
/* defaulty crtc->channel go with par->index */
- request = PADDING(crtc->line_pad, request);
+ request = ALIGN(request, crtc->line_pad);
request = request * var->yres_virtual;
if (crtc->vidmem_size < request) {
pr_err("not enough video memory for mode\n");
return -ENOMEM;
}
- return crtc->proc_checkMode(crtc, var);
+ return hw_sm750_crtc_checkMode(crtc, var);
}
static int lynxfb_ops_setcolreg(unsigned regno,
@@ -620,7 +602,7 @@ static int lynxfb_ops_setcolreg(unsigned regno,
red >>= 8;
green >>= 8;
blue >>= 8;
- ret = crtc->proc_setColReg(crtc, regno, red, green, blue);
+ ret = hw_sm750_setColReg(crtc, regno, red, green, blue);
goto exit;
}
@@ -658,65 +640,57 @@ static int lynxfb_ops_blank(int blank, struct fb_info *info)
static int sm750fb_set_drv(struct lynxfb_par *par)
{
int ret;
- struct lynx_share *share;
- struct sm750_share *spec_share;
+ struct sm750_dev *sm750_dev;
struct lynxfb_output *output;
struct lynxfb_crtc *crtc;
ret = 0;
- share = par->share;
- spec_share = container_of(share, struct sm750_share, share);
+ sm750_dev = par->dev;
output = &par->output;
crtc = &par->crtc;
- crtc->vidmem_size = (share->dual) ? share->vidmem_size >> 1 :
- share->vidmem_size;
+ crtc->vidmem_size = (sm750_dev->dual) ? sm750_dev->vidmem_size >> 1 :
+ sm750_dev->vidmem_size;
/* setup crtc and output member */
- spec_share->hwCursor = g_hwcursor;
+ sm750_dev->hwCursor = g_hwcursor;
- crtc->proc_setMode = hw_sm750_crtc_setMode;
- crtc->proc_checkMode = hw_sm750_crtc_checkMode;
- crtc->proc_setColReg = hw_sm750_setColReg;
- crtc->proc_panDisplay = hw_sm750_pan_display;
crtc->line_pad = 16;
crtc->xpanstep = 8;
crtc->ypanstep = 1;
crtc->ywrapstep = 0;
- output->proc_setMode = hw_sm750_output_setMode;
-
- output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID) ?
+ output->proc_setBLANK = (sm750_dev->revid == SM750LE_REVISION_ID) ?
hw_sm750le_setBLANK : hw_sm750_setBLANK;
/* chip specific phase */
- share->accel.de_wait = (share->revid == SM750LE_REVISION_ID) ?
- hw_sm750le_deWait : hw_sm750_deWait;
- switch (spec_share->state.dataflow) {
+ sm750_dev->accel.de_wait = (sm750_dev->revid == SM750LE_REVISION_ID) ?
+ hw_sm750le_deWait : hw_sm750_deWait;
+ switch (sm750_dev->dataflow) {
case sm750_simul_pri:
output->paths = sm750_pnc;
crtc->channel = sm750_primary;
crtc->oScreen = 0;
- crtc->vScreen = share->pvMem;
+ crtc->vScreen = sm750_dev->pvMem;
pr_info("use simul primary mode\n");
break;
case sm750_simul_sec:
output->paths = sm750_pnc;
crtc->channel = sm750_secondary;
crtc->oScreen = 0;
- crtc->vScreen = share->pvMem;
+ crtc->vScreen = sm750_dev->pvMem;
break;
case sm750_dual_normal:
if (par->index == 0) {
output->paths = sm750_panel;
crtc->channel = sm750_primary;
crtc->oScreen = 0;
- crtc->vScreen = share->pvMem;
+ crtc->vScreen = sm750_dev->pvMem;
} else {
output->paths = sm750_crt;
crtc->channel = sm750_secondary;
/* not consider of padding stuffs for oScreen,need fix */
- crtc->oScreen = (share->vidmem_size >> 1);
- crtc->vScreen = share->pvMem + crtc->oScreen;
+ crtc->oScreen = (sm750_dev->vidmem_size >> 1);
+ crtc->vScreen = sm750_dev->pvMem + crtc->oScreen;
}
break;
case sm750_dual_swap:
@@ -724,13 +698,13 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
output->paths = sm750_panel;
crtc->channel = sm750_secondary;
crtc->oScreen = 0;
- crtc->vScreen = share->pvMem;
+ crtc->vScreen = sm750_dev->pvMem;
} else {
output->paths = sm750_crt;
crtc->channel = sm750_primary;
/* not consider of padding stuffs for oScreen,need fix */
- crtc->oScreen = (share->vidmem_size >> 1);
- crtc->vScreen = share->pvMem + crtc->oScreen;
+ crtc->oScreen = (sm750_dev->vidmem_size >> 1);
+ crtc->vScreen = sm750_dev->pvMem + crtc->oScreen;
}
break;
default:
@@ -757,7 +731,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
{
int i;
struct lynxfb_par *par;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
struct lynxfb_crtc *crtc;
struct lynxfb_output *output;
struct fb_var_screeninfo *var;
@@ -781,7 +755,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
ret = 0;
par = (struct lynxfb_par *)info->par;
- share = par->share;
+ sm750_dev = par->dev;
crtc = &par->crtc;
output = &par->output;
var = &info->var;
@@ -798,28 +772,22 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
* must be set after crtc member initialized
*/
crtc->cursor.offset = crtc->oScreen + crtc->vidmem_size - 1024;
- crtc->cursor.mmio = share->pvReg + 0x800f0 + (int)crtc->channel * 0x140;
+ crtc->cursor.mmio = sm750_dev->pvReg +
+ 0x800f0 + (int)crtc->channel * 0x140;
pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
crtc->cursor.maxH = crtc->cursor.maxW = 64;
crtc->cursor.size = crtc->cursor.maxH * crtc->cursor.maxW * 2 / 8;
- crtc->cursor.disable = hw_cursor_disable;
- crtc->cursor.enable = hw_cursor_enable;
- crtc->cursor.setColor = hw_cursor_setColor;
- crtc->cursor.setPos = hw_cursor_setPos;
- crtc->cursor.setSize = hw_cursor_setSize;
- crtc->cursor.setData = hw_cursor_setData;
- crtc->cursor.vstart = share->pvMem + crtc->cursor.offset;
-
- crtc->cursor.share = share;
- memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
+ crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset;
+
+ memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
if (!g_hwcursor) {
lynxfb_ops.fb_cursor = NULL;
- crtc->cursor.disable(&crtc->cursor);
+ hw_cursor_disable(&crtc->cursor);
}
/* set info->fbops, must be set before fb_find_mode */
- if (!share->accel_off) {
+ if (!sm750_dev->accel_off) {
/* use 2d acceleration */
lynxfb_ops.fb_fillrect = lynxfb_ops_fillrect;
lynxfb_ops.fb_copyarea = lynxfb_ops_copyarea;
@@ -883,8 +851,8 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
par->info = info;
/* set info */
- line_length = PADDING(crtc->line_pad,
- (var->xres_virtual * var->bits_per_pixel / 8));
+ line_length = ALIGN((var->xres_virtual * var->bits_per_pixel / 8),
+ crtc->line_pad);
info->pseudo_palette = &par->pseudo_palette[0];
info->screen_base = crtc->vScreen;
@@ -902,7 +870,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
strlcpy(fix->id, fixId[index], sizeof(fix->id));
- fix->smem_start = crtc->oScreen + share->vidmem_start;
+ fix->smem_start = crtc->oScreen + sm750_dev->vidmem_start;
pr_info("fix->smem_start = %lx\n", fix->smem_start);
/*
* according to mmap experiment from user space application,
@@ -915,9 +883,9 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
pr_info("fix->smem_len = %x\n", fix->smem_len);
info->screen_size = fix->smem_len;
fix->line_length = line_length;
- fix->mmio_start = share->vidreg_start;
+ fix->mmio_start = sm750_dev->vidreg_start;
pr_info("fix->mmio_start = %lx\n", fix->mmio_start);
- fix->mmio_len = share->vidreg_size;
+ fix->mmio_len = sm750_dev->vidreg_size;
pr_info("fix->mmio_len = %x\n", fix->mmio_len);
switch (var->bits_per_pixel) {
case 8:
@@ -956,27 +924,19 @@ exit:
}
/* chip specific g_option configuration routine */
-static void sm750fb_setup(struct lynx_share *share, char *src)
+static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
{
- struct sm750_share *spec_share;
char *opt;
-#ifdef CAP_EXPENSION
- char *exp_res;
-#endif
int swap;
- spec_share = container_of(share, struct sm750_share, share);
-#ifdef CAP_EXPENSIION
- exp_res = NULL;
-#endif
swap = 0;
- spec_share->state.initParm.chip_clk = 0;
- spec_share->state.initParm.mem_clk = 0;
- spec_share->state.initParm.master_clk = 0;
- spec_share->state.initParm.powerMode = 0;
- spec_share->state.initParm.setAllEngOff = 0;
- spec_share->state.initParm.resetMemory = 1;
+ sm750_dev->initParm.chip_clk = 0;
+ sm750_dev->initParm.mem_clk = 0;
+ sm750_dev->initParm.master_clk = 0;
+ sm750_dev->initParm.powerMode = 0;
+ sm750_dev->initParm.setAllEngOff = 0;
+ sm750_dev->initParm.resetMemory = 1;
/* defaultly turn g_hwcursor on for both view */
g_hwcursor = 3;
@@ -993,17 +953,13 @@ static void sm750fb_setup(struct lynx_share *share, char *src)
if (!strncmp(opt, "swap", strlen("swap")))
swap = 1;
else if (!strncmp(opt, "nocrt", strlen("nocrt")))
- spec_share->state.nocrt = 1;
+ sm750_dev->nocrt = 1;
else if (!strncmp(opt, "36bit", strlen("36bit")))
- spec_share->state.pnltype = sm750_doubleTFT;
+ sm750_dev->pnltype = sm750_doubleTFT;
else if (!strncmp(opt, "18bit", strlen("18bit")))
- spec_share->state.pnltype = sm750_dualTFT;
+ sm750_dev->pnltype = sm750_dualTFT;
else if (!strncmp(opt, "24bit", strlen("24bit")))
- spec_share->state.pnltype = sm750_24TFT;
-#ifdef CAP_EXPANSION
- else if (!strncmp(opt, "exp:", strlen("exp:")))
- exp_res = opt + strlen("exp:");
-#endif
+ sm750_dev->pnltype = sm750_24TFT;
else if (!strncmp(opt, "nohwc0", strlen("nohwc0")))
g_hwcursor &= ~0x1;
else if (!strncmp(opt, "nohwc1", strlen("nohwc1")))
@@ -1022,33 +978,25 @@ static void sm750fb_setup(struct lynx_share *share, char *src)
}
}
}
-#ifdef CAP_EXPANSION
- if (getExpRes(exp_res,
- &spec_share->state.xLCD,
- &spec_share->state.yLCD)) {
- /* seems exp_res is not valid */
- spec_share->state.xLCD = spec_share->state.yLCD = 0;
- }
-#endif
NO_PARAM:
- if (share->revid != SM750LE_REVISION_ID) {
- if (share->dual) {
+ if (sm750_dev->revid != SM750LE_REVISION_ID) {
+ if (sm750_dev->dual) {
if (swap)
- spec_share->state.dataflow = sm750_dual_swap;
+ sm750_dev->dataflow = sm750_dual_swap;
else
- spec_share->state.dataflow = sm750_dual_normal;
+ sm750_dev->dataflow = sm750_dual_normal;
} else {
if (swap)
- spec_share->state.dataflow = sm750_simul_sec;
+ sm750_dev->dataflow = sm750_simul_sec;
else
- spec_share->state.dataflow = sm750_simul_pri;
+ sm750_dev->dataflow = sm750_simul_pri;
}
} else {
/* SM750LE only have one crt channel */
- spec_share->state.dataflow = sm750_simul_sec;
+ sm750_dev->dataflow = sm750_simul_sec;
/* sm750le do not have complex attributes */
- spec_share->state.nocrt = 0;
+ sm750_dev->nocrt = 0;
}
}
@@ -1056,10 +1004,7 @@ static int lynxfb_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct fb_info *info[] = {NULL, NULL};
- struct lynx_share *share = NULL;
-
- struct sm750_share *spec_share = NULL;
- size_t spec_offset = 0;
+ struct sm750_dev *sm750_dev = NULL;
int fbidx;
/* enable device */
@@ -1068,69 +1013,62 @@ static int lynxfb_pci_probe(struct pci_dev *pdev,
goto err_enable;
}
- /*
- * though offset of share in sm750_share is 0,
- * we use this marcro as the same
- */
- spec_offset = offsetof(struct sm750_share, share);
-
- spec_share = kzalloc(sizeof(*spec_share), GFP_KERNEL);
- if (!spec_share) {
+ sm750_dev = kzalloc(sizeof(*sm750_dev), GFP_KERNEL);
+ if (!sm750_dev) {
pr_err("Could not allocate memory for share.\n");
goto err_share;
}
- /* setting share structure */
- share = (struct lynx_share *)(&(spec_share->share));
- share->fbinfo[0] = share->fbinfo[1] = NULL;
- share->devid = pdev->device;
- share->revid = pdev->revision;
-
- pr_info("share->revid = %02x\n", share->revid);
- share->pdev = pdev;
- share->mtrr_off = g_nomtrr;
- share->mtrr.vram = 0;
- share->accel_off = g_noaccel;
- share->dual = g_dualview;
- spin_lock_init(&share->slock);
-
- if (!share->accel_off) {
+ sm750_dev->fbinfo[0] = sm750_dev->fbinfo[1] = NULL;
+ sm750_dev->devid = pdev->device;
+ sm750_dev->revid = pdev->revision;
+
+ pr_info("share->revid = %02x\n", sm750_dev->revid);
+ sm750_dev->pdev = pdev;
+ sm750_dev->mtrr_off = g_nomtrr;
+ sm750_dev->mtrr.vram = 0;
+ sm750_dev->accel_off = g_noaccel;
+ sm750_dev->dual = g_dualview;
+ spin_lock_init(&sm750_dev->slock);
+
+ if (!sm750_dev->accel_off) {
/*
* hook deInit and 2d routines, notes that below hw_xxx
* routine can work on most of lynx chips
* if some chip need specific function,
* please hook it in smXXX_set_drv routine
*/
- share->accel.de_init = hw_de_init;
- share->accel.de_fillrect = hw_fillrect;
- share->accel.de_copyarea = hw_copyarea;
- share->accel.de_imageblit = hw_imageblit;
+ sm750_dev->accel.de_init = hw_de_init;
+ sm750_dev->accel.de_fillrect = hw_fillrect;
+ sm750_dev->accel.de_copyarea = hw_copyarea;
+ sm750_dev->accel.de_imageblit = hw_imageblit;
pr_info("enable 2d acceleration\n");
} else {
pr_info("disable 2d acceleration\n");
}
/* call chip specific setup routine */
- sm750fb_setup(share, g_settings);
+ sm750fb_setup(sm750_dev, g_settings);
/* call chip specific mmap routine */
- if (hw_sm750_map(share, pdev)) {
+ if (hw_sm750_map(sm750_dev, pdev)) {
pr_err("Memory map failed\n");
goto err_map;
}
- if (!share->mtrr_off)
- share->mtrr.vram = arch_phys_wc_add(share->vidmem_start,
- share->vidmem_size);
+ if (!sm750_dev->mtrr_off)
+ sm750_dev->mtrr.vram = arch_phys_wc_add(sm750_dev->vidmem_start,
+ sm750_dev->vidmem_size);
- memset_io(share->pvMem, 0, share->vidmem_size);
+ memset_io(sm750_dev->pvMem, 0, sm750_dev->vidmem_size);
- pr_info("sm%3x mmio address = %p\n", share->devid, share->pvReg);
+ pr_info("sm%3x mmio address = %p\n", sm750_dev->devid,
+ sm750_dev->pvReg);
- pci_set_drvdata(pdev, share);
+ pci_set_drvdata(pdev, sm750_dev);
/* call chipInit routine */
- hw_sm750_inithw(share, pdev);
+ hw_sm750_inithw(sm750_dev, pdev);
/* allocate frame buffer info structor according to g_dualview */
fbidx = 0;
@@ -1147,9 +1085,9 @@ ALLOC_FB:
int errno;
pr_info("framebuffer #%d alloc okay\n", fbidx);
- share->fbinfo[fbidx] = info[fbidx];
+ sm750_dev->fbinfo[fbidx] = info[fbidx];
par = info[fbidx]->par;
- par->share = share;
+ par->dev = sm750_dev;
/* set fb_info structure */
if (lynxfb_set_fbinfo(info[fbidx], fbidx)) {
@@ -1177,7 +1115,7 @@ ALLOC_FB:
/* no dual view by far */
fbidx++;
- if (share->dual && fbidx < 2)
+ if (sm750_dev->dual && fbidx < 2)
goto ALLOC_FB;
return 0;
@@ -1192,7 +1130,7 @@ err_info0_set:
framebuffer_release(info[0]);
err_info0_alloc:
err_map:
- kfree(spec_share);
+ kfree(sm750_dev);
err_share:
err_enable:
return -ENODEV;
@@ -1201,16 +1139,15 @@ err_enable:
static void lynxfb_pci_remove(struct pci_dev *pdev)
{
struct fb_info *info;
- struct lynx_share *share;
- void *spec_share;
+ struct sm750_dev *sm750_dev;
struct lynxfb_par *par;
int cnt;
cnt = 2;
- share = pci_get_drvdata(pdev);
+ sm750_dev = pci_get_drvdata(pdev);
while (cnt-- > 0) {
- info = share->fbinfo[cnt];
+ info = sm750_dev->fbinfo[cnt];
if (!info)
continue;
par = info->par;
@@ -1219,13 +1156,12 @@ static void lynxfb_pci_remove(struct pci_dev *pdev)
/* release frame buffer */
framebuffer_release(info);
}
- arch_phys_wc_del(share->mtrr.vram);
+ arch_phys_wc_del(sm750_dev->mtrr.vram);
- iounmap(share->pvReg);
- iounmap(share->pvMem);
- spec_share = container_of(share, struct sm750_share, share);
+ iounmap(sm750_dev->pvReg);
+ iounmap(sm750_dev->pvMem);
kfree(g_settings);
- kfree(spec_share);
+ kfree(sm750_dev);
pci_set_drvdata(pdev, NULL);
}
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
index 52fe945101c8..b0a93cdc7292 100644
--- a/drivers/staging/sm750fb/sm750.h
+++ b/drivers/staging/sm750fb/sm750.h
@@ -1,17 +1,51 @@
#ifndef LYNXDRV_H_
#define LYNXDRV_H_
-
-
#define FB_ACCEL_SMI 0xab
-/* please use revision id to distinguish sm750le and sm750*/
-#define SPC_SM750 0
#define MHZ(x) ((x) * 1000000)
-/* align should be 2,4,8,16 */
-#define PADDING(align, data) (((data)+(align)-1)&(~((align) - 1)))
-extern int smi_indent;
+#define DEFAULT_SM750_CHIP_CLOCK 290
+#define DEFAULT_SM750LE_CHIP_CLOCK 333
+#ifndef SM750LE_REVISION_ID
+#define SM750LE_REVISION_ID ((unsigned char)0xfe)
+#endif
+
+enum sm750_pnltype {
+ sm750_24TFT = 0, /* 24bit tft */
+ sm750_dualTFT = 2, /* dual 18 bit tft */
+ sm750_doubleTFT = 1, /* 36 bit double pixel tft */
+};
+
+/* vga channel is not concerned */
+enum sm750_dataflow {
+ sm750_simul_pri, /* primary => all head */
+ sm750_simul_sec, /* secondary => all head */
+ sm750_dual_normal, /* primary => panel head and secondary => crt */
+ sm750_dual_swap, /* primary => crt head and secondary => panel */
+};
+
+enum sm750_channel {
+ sm750_primary = 0,
+ /* enum value equal to the register filed data */
+ sm750_secondary = 1,
+};
+
+enum sm750_path {
+ sm750_panel = 1,
+ sm750_crt = 2,
+ sm750_pnc = 3, /* panel and crt */
+};
+
+struct init_status {
+ ushort powerMode;
+ /* below three clocks are in unit of MHZ*/
+ ushort chip_clk;
+ ushort mem_clk;
+ ushort master_clk;
+ ushort setAllEngOff;
+ ushort resetMemory;
+};
struct lynx_accel {
/* base virtual address of DPR registers */
@@ -37,10 +71,7 @@ struct lynx_accel {
};
-/* lynx_share stands for a presentation of two frame buffer
- that use one smi adaptor , it is similar to a basic class of C++
-*/
-struct lynx_share {
+struct sm750_dev {
/* common members */
u16 devid;
u8 revid;
@@ -49,10 +80,10 @@ struct lynx_share {
struct lynx_accel accel;
int accel_off;
int dual;
- int mtrr_off;
- struct{
- int vram;
- } mtrr;
+ int mtrr_off;
+ struct{
+ int vram;
+ } mtrr;
/* all smi graphic adaptor got below attributes */
unsigned long vidmem_start;
unsigned long vidreg_start;
@@ -62,9 +93,19 @@ struct lynx_share {
unsigned char __iomem *pvMem;
/* locks*/
spinlock_t slock;
- /* function pointers */
- void (*suspend)(struct lynx_share *);
- void (*resume)(struct lynx_share *);
+
+ struct init_status initParm;
+ enum sm750_pnltype pnltype;
+ enum sm750_dataflow dataflow;
+ int nocrt;
+
+ /*
+ * 0: no hardware cursor
+ * 1: primary crtc hw cursor enabled,
+ * 2: secondary crtc hw cursor enabled
+ * 3: both ctrc hw cursor enabled
+ */
+ int hwCursor;
};
struct lynx_cursor {
@@ -80,15 +121,6 @@ struct lynx_cursor {
int offset;
/* mmio addr of hw cursor */
volatile char __iomem *mmio;
- /* the lynx_share of this adaptor */
- struct lynx_share *share;
- /* proc_routines */
- void (*enable)(struct lynx_cursor *);
- void (*disable)(struct lynx_cursor *);
- void (*setSize)(struct lynx_cursor *, int, int);
- void (*setPos)(struct lynx_cursor *, int, int);
- void (*setColor)(struct lynx_cursor *, u32, u32);
- void (*setData)(struct lynx_cursor *, u16, const u8*, const u8*);
};
struct lynxfb_crtc {
@@ -107,16 +139,6 @@ struct lynxfb_crtc {
void *priv;
- int (*proc_setMode)(struct lynxfb_crtc*,
- struct fb_var_screeninfo*,
- struct fb_fix_screeninfo*);
-
- int (*proc_checkMode)(struct lynxfb_crtc*, struct fb_var_screeninfo*);
- int (*proc_setColReg)(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
- /* pan display */
- int (*proc_panDisplay)(struct lynxfb_crtc *,
- const struct fb_var_screeninfo *,
- const struct fb_info *);
/* cursor information */
struct lynx_cursor cursor;
};
@@ -138,10 +160,6 @@ struct lynxfb_output {
*/
void *priv;
- int (*proc_setMode)(struct lynxfb_output*,
- struct fb_var_screeninfo*,
- struct fb_fix_screeninfo*);
-
int (*proc_setBLANK)(struct lynxfb_output*, int);
};
@@ -152,13 +170,9 @@ struct lynxfb_par {
struct lynxfb_crtc crtc;
struct lynxfb_output output;
struct fb_info *info;
- struct lynx_share *share;
+ struct sm750_dev *dev;
};
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-
static inline unsigned long ps_to_hz(unsigned int psvalue)
{
unsigned long long numerator = 1000*1000*1000*1000ULL;
@@ -167,5 +181,22 @@ static inline unsigned long ps_to_hz(unsigned int psvalue)
return (unsigned long)numerator;
}
+int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev);
+int hw_sm750_inithw(struct sm750_dev*, struct pci_dev *);
+void hw_sm750_initAccel(struct sm750_dev *);
+int hw_sm750_deWait(void);
+int hw_sm750le_deWait(void);
+
+int hw_sm750_output_setMode(struct lynxfb_output*, struct fb_var_screeninfo*,
+ struct fb_fix_screeninfo*);
+int hw_sm750_crtc_checkMode(struct lynxfb_crtc*, struct fb_var_screeninfo*);
+int hw_sm750_crtc_setMode(struct lynxfb_crtc*, struct fb_var_screeninfo*,
+ struct fb_fix_screeninfo*);
+int hw_sm750_setColReg(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
+int hw_sm750_setBLANK(struct lynxfb_output*, int);
+int hw_sm750le_setBLANK(struct lynxfb_output*, int);
+int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
+ const struct fb_var_screeninfo *var,
+ const struct fb_info *info);
#endif
diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c
index 92e194ddb15a..41822c6c0380 100644
--- a/drivers/staging/sm750fb/sm750_hw.c
+++ b/drivers/staging/sm750fb/sm750_hw.c
@@ -21,23 +21,19 @@
#include <linux/sizes.h>
#include "sm750.h"
-#include "sm750_hw.h"
#include "ddk750.h"
#include "sm750_accel.h"
-int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev)
+int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
{
int ret;
- struct sm750_share *spec_share;
-
- spec_share = container_of(share, struct sm750_share, share);
ret = 0;
- share->vidreg_start = pci_resource_start(pdev, 1);
- share->vidreg_size = SZ_2M;
+ sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
+ sm750_dev->vidreg_size = SZ_2M;
- pr_info("mmio phyAddr = %lx\n", share->vidreg_start);
+ pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
/* reserve the vidreg space of smi adaptor
* if you do this, u need to add release region code
@@ -51,40 +47,41 @@ int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev)
}
/* now map mmio and vidmem*/
- share->pvReg = ioremap_nocache(share->vidreg_start, share->vidreg_size);
- if (!share->pvReg) {
+ sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
+ sm750_dev->vidreg_size);
+ if (!sm750_dev->pvReg) {
pr_err("mmio failed\n");
ret = -EFAULT;
goto exit;
} else {
- pr_info("mmio virtual addr = %p\n", share->pvReg);
+ pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
}
- share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1;
- share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1;
+ sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
+ sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
- ddk750_set_mmio(share->pvReg, share->devid, share->revid);
+ ddk750_set_mmio(sm750_dev->pvReg, sm750_dev->devid, sm750_dev->revid);
- share->vidmem_start = pci_resource_start(pdev, 0);
+ sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
/* don't use pdev_resource[x].end - resource[x].start to
* calculate the resource size,its only the maximum available
* size but not the actual size,use
- * @hw_sm750_getVMSize function can be safe.
+ * @ddk750_getVMSize function can be safe.
* */
- share->vidmem_size = hw_sm750_getVMSize(share);
+ sm750_dev->vidmem_size = ddk750_getVMSize();
pr_info("video memory phyAddr = %lx, size = %u bytes\n",
- share->vidmem_start, share->vidmem_size);
+ sm750_dev->vidmem_start, sm750_dev->vidmem_size);
/* reserve the vidmem space of smi adaptor */
- share->pvMem = ioremap_wc(share->vidmem_start, share->vidmem_size);
-
- if (!share->pvMem) {
+ sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
+ sm750_dev->vidmem_size);
+ if (!sm750_dev->pvMem) {
pr_err("Map video memory failed\n");
ret = -EFAULT;
goto exit;
} else {
- pr_info("video memory vaddr = %p\n", share->pvMem);
+ pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
}
exit:
return ret;
@@ -92,13 +89,11 @@ exit:
-int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
+int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
{
- struct sm750_share *spec_share;
struct init_status *parm;
- spec_share = container_of(share, struct sm750_share, share);
- parm = &spec_share->state.initParm;
+ parm = &sm750_dev->initParm;
if (parm->chip_clk == 0)
parm->chip_clk = (getChipType() == SM750LE) ?
DEFAULT_SM750LE_CHIP_CLOCK :
@@ -109,16 +104,16 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
if (parm->master_clk == 0)
parm->master_clk = parm->chip_clk/3;
- ddk750_initHw((initchip_param_t *)&spec_share->state.initParm);
+ ddk750_initHw((initchip_param_t *)&sm750_dev->initParm);
/* for sm718,open pci burst */
- if (share->devid == 0x718) {
+ if (sm750_dev->devid == 0x718) {
POKE32(SYSTEM_CTRL,
FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
}
if (getChipType() != SM750LE) {
/* does user need CRT ?*/
- if (spec_share->state.nocrt) {
+ if (sm750_dev->nocrt) {
POKE32(MISC_CTRL,
FIELD_SET(PEEK32(MISC_CTRL),
MISC_CTRL,
@@ -140,7 +135,7 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
DPMS, VPHP));
}
- switch (spec_share->state.pnltype) {
+ switch (sm750_dev->pnltype) {
case sm750_doubleTFT:
case sm750_24TFT:
case sm750_dualTFT:
@@ -148,7 +143,7 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
PANEL_DISPLAY_CTRL,
TFT_DISP,
- spec_share->state.pnltype));
+ sm750_dev->pnltype));
break;
}
} else {
@@ -175,21 +170,12 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
}
/* init 2d engine */
- if (!share->accel_off)
- hw_sm750_initAccel(share);
+ if (!sm750_dev->accel_off)
+ hw_sm750_initAccel(sm750_dev);
return 0;
}
-
-resource_size_t hw_sm750_getVMSize(struct lynx_share *share)
-{
- resource_size_t ret;
-
- ret = ddk750_getVMSize();
- return ret;
-}
-
int hw_sm750_output_setMode(struct lynxfb_output *output,
struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
{
@@ -234,17 +220,17 @@ int hw_sm750_output_setMode(struct lynxfb_output *output,
int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
{
- struct lynx_share *share;
-
+ struct sm750_dev *sm750_dev;
+ struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
- share = container_of(crtc, struct lynxfb_par, crtc)->share;
+ sm750_dev = par->dev;
switch (var->bits_per_pixel) {
case 8:
case 16:
break;
case 32:
- if (share->revid == SM750LE_REVISION_ID) {
+ if (sm750_dev->revid == SM750LE_REVISION_ID) {
pr_debug("750le do not support 32bpp\n");
return -EINVAL;
}
@@ -269,15 +255,15 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
u32 reg;
mode_parameter_t modparm;
clock_type_t clock;
- struct lynx_share *share;
+ struct sm750_dev *sm750_dev;
struct lynxfb_par *par;
ret = 0;
par = container_of(crtc, struct lynxfb_par, crtc);
- share = par->share;
-#if 1
- if (!share->accel_off) {
+ sm750_dev = par->dev;
+
+ if (!sm750_dev->accel_off) {
/* set 2d engine pixel format according to mode bpp */
switch (var->bits_per_pixel) {
case 8:
@@ -291,9 +277,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
fmt = 2;
break;
}
- hw_set2dformat(&share->accel, fmt);
+ hw_set2dformat(&sm750_dev->accel, fmt);
}
-#endif
/* set timing */
modparm.pixel_clock = ps_to_hz(var->pixclock);
@@ -331,7 +316,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
reg = var->xres * (var->bits_per_pixel >> 3);
/* crtc->channel is not equal to par->index on numeric,be aware of that */
- reg = PADDING(crtc->line_pad, reg);
+ reg = ALIGN(reg, crtc->line_pad);
POKE32(PANEL_FB_WIDTH,
FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)|
@@ -363,7 +348,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
POKE32(CRT_FB_ADDRESS, crtc->oScreen);
reg = var->xres * (var->bits_per_pixel >> 3);
/* crtc->channel is not equal to par->index on numeric,be aware of that */
- reg = PADDING(crtc->line_pad, reg);
+ reg = ALIGN(reg, crtc->line_pad);
POKE32(CRT_FB_WIDTH,
FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)|
@@ -395,41 +380,23 @@ int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
int dpms, crtdb;
switch (blank) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_UNBLANK:
-#else
- case VESA_NO_BLANKING:
-#endif
dpms = CRT_DISPLAY_CTRL_DPMS_0;
crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_NORMAL:
dpms = CRT_DISPLAY_CTRL_DPMS_0;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_VSYNC_SUSPEND:
-#else
- case VESA_VSYNC_SUSPEND:
-#endif
dpms = CRT_DISPLAY_CTRL_DPMS_2;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_HSYNC_SUSPEND:
-#else
- case VESA_HSYNC_SUSPEND:
-#endif
dpms = CRT_DISPLAY_CTRL_DPMS_1;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_POWERDOWN:
-#else
- case VESA_POWERDOWN:
-#endif
dpms = CRT_DISPLAY_CTRL_DPMS_3;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
@@ -451,47 +418,29 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
dpms = pps = crtdb = 0;
switch (blank) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_UNBLANK:
-#else
- case VESA_NO_BLANKING:
-#endif
pr_info("flag = FB_BLANK_UNBLANK\n");
dpms = SYSTEM_CTRL_DPMS_VPHP;
pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_NORMAL:
pr_info("flag = FB_BLANK_NORMAL\n");
dpms = SYSTEM_CTRL_DPMS_VPHP;
pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_VSYNC_SUSPEND:
-#else
- case VESA_VSYNC_SUSPEND:
-#endif
dpms = SYSTEM_CTRL_DPMS_VNHP;
pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_HSYNC_SUSPEND:
-#else
- case VESA_HSYNC_SUSPEND:
-#endif
dpms = SYSTEM_CTRL_DPMS_VPHN;
pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
case FB_BLANK_POWERDOWN:
-#else
- case VESA_POWERDOWN:
-#endif
dpms = SYSTEM_CTRL_DPMS_VNHN;
pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
@@ -511,7 +460,7 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
}
-void hw_sm750_initAccel(struct lynx_share *share)
+void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
{
u32 reg;
@@ -538,7 +487,7 @@ void hw_sm750_initAccel(struct lynx_share *share)
}
/* call 2d init */
- share->accel.de_init(&share->accel);
+ sm750_dev->accel.de_init(&sm750_dev->accel);
}
int hw_sm750le_deWait(void)
diff --git a/drivers/staging/sm750fb/sm750_hw.h b/drivers/staging/sm750fb/sm750_hw.h
deleted file mode 100644
index cc8c76d0c1d2..000000000000
--- a/drivers/staging/sm750fb/sm750_hw.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef LYNX_HW750_H__
-#define LYNX_HW750_H__
-
-
-#define DEFAULT_SM750_CHIP_CLOCK 290
-#define DEFAULT_SM750LE_CHIP_CLOCK 333
-#ifndef SM750LE_REVISION_ID
-#define SM750LE_REVISION_ID (unsigned char)0xfe
-#endif
-
-
-enum sm750_pnltype {
-
- sm750_24TFT = 0,/* 24bit tft */
-
- sm750_dualTFT = 2,/* dual 18 bit tft */
-
- sm750_doubleTFT = 1,/* 36 bit double pixel tft */
-};
-
-/* vga channel is not concerned */
-enum sm750_dataflow {
- sm750_simul_pri,/* primary => all head */
-
- sm750_simul_sec,/* secondary => all head */
-
- sm750_dual_normal,/* primary => panel head and secondary => crt */
-
- sm750_dual_swap,/* primary => crt head and secondary => panel */
-};
-
-
-enum sm750_channel {
- sm750_primary = 0,
- /* enum value equal to the register filed data */
- sm750_secondary = 1,
-};
-
-enum sm750_path {
- sm750_panel = 1,
- sm750_crt = 2,
- sm750_pnc = 3,/* panel and crt */
-};
-
-struct init_status {
- ushort powerMode;
- /* below three clocks are in unit of MHZ*/
- ushort chip_clk;
- ushort mem_clk;
- ushort master_clk;
- ushort setAllEngOff;
- ushort resetMemory;
-};
-
-struct sm750_state {
- struct init_status initParm;
- enum sm750_pnltype pnltype;
- enum sm750_dataflow dataflow;
- int nocrt;
- int xLCD;
- int yLCD;
-};
-
-/* sm750_share stands for a presentation of two frame buffer
- that use one sm750 adaptor, it is similar to the super class of lynx_share
- in C++
- */
-
-struct sm750_share {
- /* it's better to put lynx_share struct to the first place of sm750_share */
- struct lynx_share share;
- struct sm750_state state;
- int hwCursor;
- /* 0: no hardware cursor
- 1: primary crtc hw cursor enabled,
- 2: secondary crtc hw cursor enabled
- 3: both ctrc hw cursor enabled
- */
-};
-
-int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev);
-int hw_sm750_inithw(struct lynx_share*, struct pci_dev *);
-void hw_sm750_initAccel(struct lynx_share *);
-int hw_sm750_deWait(void);
-int hw_sm750le_deWait(void);
-
-resource_size_t hw_sm750_getVMSize(struct lynx_share *);
-int hw_sm750_output_setMode(struct lynxfb_output*, struct fb_var_screeninfo*, struct fb_fix_screeninfo*);
-int hw_sm750_crtc_checkMode(struct lynxfb_crtc*, struct fb_var_screeninfo*);
-int hw_sm750_crtc_setMode(struct lynxfb_crtc*, struct fb_var_screeninfo*, struct fb_fix_screeninfo*);
-int hw_sm750_setColReg(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
-int hw_sm750_setBLANK(struct lynxfb_output*, int);
-int hw_sm750le_setBLANK(struct lynxfb_output*, int);
-int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
- const struct fb_var_screeninfo *var,
- const struct fb_info *info);
-
-#endif
diff --git a/drivers/staging/speakup/buffers.c b/drivers/staging/speakup/buffers.c
index d4d45989b605..8565c2343968 100644
--- a/drivers/staging/speakup/buffers.c
+++ b/drivers/staging/speakup/buffers.c
@@ -101,6 +101,7 @@ EXPORT_SYMBOL_GPL(synth_buffer_peek);
void synth_buffer_clear(void)
{
- buff_in = buff_out = synth_buffer;
+ buff_in = synth_buffer;
+ buff_out = synth_buffer;
}
EXPORT_SYMBOL_GPL(synth_buffer_clear);
diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c
index 98af3b1f2d2a..aa5ab6c80ed4 100644
--- a/drivers/staging/speakup/selection.c
+++ b/drivers/staging/speakup/selection.c
@@ -7,7 +7,7 @@
#include <linux/workqueue.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include <asm/cmpxchg.h>
+#include <linux/atomic.h>
#include "speakup.h"
diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h
index c6c24423a7f0..5af59a5fce61 100644
--- a/drivers/staging/unisys/include/channel.h
+++ b/drivers/staging/unisys/include/channel.h
@@ -60,15 +60,19 @@ enum channel_clientstate {
CHANNELCLI_DISABLED = 1, /* client can see channel but is NOT
* allowed to use it unless given TBD
* explicit request (should actually be
- * < DETACHED) */
+ * < DETACHED)
+ */
CHANNELCLI_ATTACHING = 2, /* legacy EFI client request
- * for EFI server to attach */
+ * for EFI server to attach
+ */
CHANNELCLI_ATTACHED = 3, /* idle, but client may want
- * to use channel any time */
+ * to use channel any time
+ */
CHANNELCLI_BUSY = 4, /* client either wants to use or is
- * using channel */
- CHANNELCLI_OWNED = 5 /* "no worries" state - client can
- * access channel anytime */
+ * using channel
+ */
+ CHANNELCLI_OWNED = 5 /* "no worries" state - client can */
+ /* access channel anytime */
};
static inline const u8 *
@@ -116,11 +120,13 @@ ULTRA_CHANNELCLI_STRING(u32 v)
/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
/* throttling invalid boot channel statetransition error due to client
- * disabled */
+ * disabled
+ */
#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01
/* throttling invalid boot channel statetransition error due to client
- * not attached */
+ * not attached
+ */
#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
/* throttling invalid boot channel statetransition error due to busy channel */
@@ -128,24 +134,28 @@ ULTRA_CHANNELCLI_STRING(u32 v)
/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */
/* throttling invalid guest OS channel statetransition error due to
- * client disabled */
+ * client disabled
+ */
#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01
/* throttling invalid guest OS channel statetransition error due to
- * client not attached */
+ * client not attached
+ */
#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02
/* throttling invalid guest OS channel statetransition error due to
- * busy channel */
+ * busy channel
+ */
#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04
/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
-* that windows guest can look at the FeatureFlags in the io channel,
-* and configure the windows driver to use interrupts or not based on
-* this setting. This flag is set in uislib after the
-* ULTRA_VHBA_init_channel is called. All feature bits for all
-* channels should be defined here. The io channel feature bits are
-* defined right here */
+ * that windows guest can look at the FeatureFlags in the io channel,
+ * and configure the windows driver to use interrupts or not based on
+ * this setting. This flag is set in uislib after the
+ * ULTRA_VHBA_init_channel is called. All feature bits for all
+ * channels should be defined here. The io channel feature bits are
+ * defined right here
+ */
#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
@@ -156,7 +166,7 @@ ULTRA_CHANNELCLI_STRING(u32 v)
struct channel_header {
u64 signature; /* Signature */
u32 legacy_state; /* DEPRECATED - being replaced by */
- /* / SrvState, CliStateBoot, and CliStateOS below */
+ /* SrvState, CliStateBoot, and CliStateOS below */
u32 header_size; /* sizeof(struct channel_header) */
u64 size; /* Total size of this channel in bytes */
u64 features; /* Flags to modify behavior */
@@ -169,25 +179,32 @@ struct channel_header {
uuid_le zone_uuid; /* Guid of Channel's zone */
u32 cli_str_offset; /* offset from channel header to
* nul-terminated ClientString (0 if
- * ClientString not present) */
+ * ClientString not present)
+ */
u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot
- * EFI client of this channel */
+ * EFI client of this channel
+ */
u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in
* Windows drivers, see ServerStateUp,
- * ServerStateDown, etc) */
+ * ServerStateDown, etc)
+ */
u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS
- * client of this channel */
+ * client of this channel
+ */
u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_<xxx> */
u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in
* Windows drivers, see ServerStateUp,
- * ServerStateDown, etc) */
+ * ServerStateDown, etc)
+ */
u32 srv_state; /* CHANNEL_SERVERSTATE */
u8 cli_error_boot; /* bits to indicate err states for
* boot clients, so err messages can
- * be throttled */
+ * be throttled
+ */
u8 cli_error_os; /* bits to indicate err states for OS
* clients, so err messages can be
- * throttled */
+ * throttled
+ */
u8 filler[1]; /* Pad out to 128 byte cacheline */
/* Please add all new single-byte values below here */
u8 recover_channel;
@@ -205,29 +222,33 @@ struct signal_queue_header {
u64 features; /* Flags to modify behavior */
u64 num_sent; /* Total # of signals placed in this queue */
u64 num_overflows; /* Total # of inserts failed due to
- * full queue */
+ * full queue
+ */
u32 signal_size; /* Total size of a signal for this queue */
u32 max_slots; /* Max # of slots in queue, 1 slot is
- * always empty */
+ * always empty
+ */
u32 max_signals; /* Max # of signals in queue
- * (MaxSignalSlots-1) */
+ * (MaxSignalSlots-1)
+ */
u32 head; /* Queue head signal # */
/* 2nd cache line */
u64 num_received; /* Total # of signals removed from this queue */
- u32 tail; /* Queue tail signal # (on separate
- * cache line) */
+ u32 tail; /* Queue tail signal */
u32 reserved1; /* Reserved field */
u64 reserved2; /* Reserved field */
u64 client_queue;
u64 num_irq_received; /* Total # of Interrupts received. This
- * is incremented by the ISR in the
- * guest windows driver */
+ * is incremented by the ISR in the
+ * guest windows driver
+ */
u64 num_empty; /* Number of times that visor_signal_remove
- * is called and returned Empty
- * Status. */
+ * is called and returned Empty Status.
+ */
u32 errorflags; /* Error bits set during SignalReinit
* to denote trouble with client's
- * fields */
+ * fields
+ */
u8 filler[12]; /* Pad out to 64 byte cacheline */
} __packed;
@@ -272,8 +293,7 @@ spar_check_channel_client(void __iomem *ch,
return 0;
}
}
- if (expected_min_bytes > 0) { /* caller wants us to verify
- * channel size */
+ if (expected_min_bytes > 0) { /* verify channel size */
unsigned long long bytes =
readq(&((struct channel_header __iomem *)
(ch))->size);
@@ -284,8 +304,7 @@ spar_check_channel_client(void __iomem *ch,
return 0;
}
}
- if (expected_version > 0) { /* caller wants us to verify
- * channel version */
+ if (expected_version > 0) { /* verify channel version */
unsigned long ver = readl(&((struct channel_header __iomem *)
(ch))->version_id);
if (ver != expected_version) {
@@ -295,8 +314,7 @@ spar_check_channel_client(void __iomem *ch,
return 0;
}
}
- if (expected_signature > 0) { /* caller wants us to verify
- * channel signature */
+ if (expected_signature > 0) { /* verify channel signature */
unsigned long long sig =
readq(&((struct channel_header __iomem *)
(ch))->signature);
@@ -319,8 +337,7 @@ static inline int spar_check_channel_server(uuid_le typeuuid, char *name,
u64 expected_min_bytes,
u64 actual_bytes)
{
- if (expected_min_bytes > 0) /* caller wants us to verify
- * channel size */
+ if (expected_min_bytes > 0) /* verify channel size */
if (actual_bytes < expected_min_bytes) {
pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n",
name, &typeuuid, expected_min_bytes,
@@ -354,7 +371,8 @@ pathname_last_n_nodes(u8 *s, unsigned int n)
if (p == s)
break; /* should never happen, unless someone
* is changing the string while we are
- * looking at it!! */
+ * looking at it!!
+ */
if ((*p == '/') || (*p == '\\'))
n--;
}
@@ -395,7 +413,8 @@ spar_channel_client_acquire_os(void __iomem *ch, u8 *id)
if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) {
if (readb(&hdr->cli_error_os) != 0) {
/* we are in an error msg throttling state;
- * come out of it */
+ * come out of it
+ */
pr_info("%s Channel OS client acquire now successful\n",
id);
writeb(0, &hdr->cli_error_os);
@@ -404,8 +423,9 @@ spar_channel_client_acquire_os(void __iomem *ch, u8 *id)
}
/* We have to do it the "hard way". We transition to BUSY,
- * and can use the channel iff our competitor has not also
- * transitioned to BUSY. */
+ * and can use the channel iff our competitor has not also
+ * transitioned to BUSY.
+ */
if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) {
if ((readb(&hdr->cli_error_os)
& ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) {
diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h
index 14e656ff73ec..162ca187a66b 100644
--- a/drivers/staging/unisys/include/iochannel.h
+++ b/drivers/staging/unisys/include/iochannel.h
@@ -6,7 +6,8 @@
/*
* Everything needed for IOPart-GuestPart communication is define in
* this file. Note: Everything is OS-independent because this file is
- * used by Windows, Linux and possible EFI drivers. */
+ * used by Windows, Linux and possible EFI drivers.
+ */
/*
* Communication flow between the IOPart and GuestPart uses the channel headers
@@ -66,21 +67,15 @@
* IO Partition is defined below.
*/
-/*
- * Defines and enums.
- */
-
+/* Defines and enums. */
#define MINNUM(a, b) (((a) < (b)) ? (a) : (b))
#define MAXNUM(a, b) (((a) > (b)) ? (a) : (b))
-/* these define the two queues per data channel between iopart and
- * ioguestparts
- */
-#define IOCHAN_TO_IOPART 0 /* used by ioguestpart to 'insert' signals to
- * iopart */
-
-#define IOCHAN_FROM_IOPART 1 /* used by ioguestpart to 'remove' signals from
- * iopart - same queue as previous queue */
+/* define the two queues per data channel between iopart and ioguestparts */
+/* used by ioguestpart to 'insert' signals to iopart */
+#define IOCHAN_TO_IOPART 0
+/* used by ioguestpart to 'remove' signals from iopart, same previous queue */
+#define IOCHAN_FROM_IOPART 1
/* size of cdb - i.e., scsi cmnd */
#define MAX_CMND_SIZE 16
@@ -92,26 +87,29 @@
/* various types of network packets that can be sent in cmdrsp */
enum net_types {
NET_RCV_POST = 0, /* submit buffer to hold receiving
- * incoming packet */
+ * incoming packet
+ */
/* virtnic -> uisnic */
NET_RCV, /* incoming packet received */
/* uisnic -> virtpci */
- NET_XMIT, /* for outgoing net packets */
+ NET_XMIT, /* for outgoing net packets */
/* virtnic -> uisnic */
NET_XMIT_DONE, /* outgoing packet xmitted */
/* uisnic -> virtpci */
NET_RCV_ENBDIS, /* enable/disable packet reception */
/* virtnic -> uisnic */
- NET_RCV_ENBDIS_ACK, /* acknowledge enable/disable packet
- * reception */
+ NET_RCV_ENBDIS_ACK, /* acknowledge enable/disable packet */
+ /* reception */
/* uisnic -> virtnic */
NET_RCV_PROMISC, /* enable/disable promiscuous mode */
/* virtnic -> uisnic */
NET_CONNECT_STATUS, /* indicate the loss or restoration of a network
- * connection */
+ * connection
+ */
/* uisnic -> virtnic */
NET_MACADDR, /* indicates the client has requested to update
- * its MAC addr */
+ * its MAC addr
+ */
NET_MACADDR_ACK, /* MAC address */
};
@@ -170,51 +168,43 @@ struct vhba_wwnn {
} __packed;
/* WARNING: Values stired in this structure must contain maximum counts (not
- * maximum values). */
-struct vhba_config_max { /* 20 bytes */
- u32 max_channel; /* maximum channel for devices attached to this
- * bus */
- u32 max_id; /* maximum SCSI ID for devices attached to this
- * bus */
- u32 max_lun; /* maximum SCSI LUN for devices attached to this
- * bus */
- u32 cmd_per_lun; /* maximum number of outstanding commands per
- * lun that are allowed at one time */
- u32 max_io_size; /* maximum io size for devices attached to this
- * bus */
+ * maximum values).
+ */
+struct vhba_config_max {/* 20 bytes */
+ u32 max_channel;/* maximum channel for devices attached to this bus */
+ u32 max_id; /* maximum SCSI ID for devices attached to bus */
+ u32 max_lun; /* maximum SCSI LUN for devices attached to bus */
+ u32 cmd_per_lun;/* maximum number of outstanding commands per LUN */
+ u32 max_io_size;/* maximum io size for devices attached to this bus */
/* max io size is often determined by the resource of the hba. e.g */
/* max scatter gather list length * page size / sector size */
} __packed;
struct uiscmdrsp_scsi {
- u64 handle; /* the handle to the cmd that was received -
- * send it back as is in the rsp packet. */
+ u64 handle; /* the handle to the cmd that was received */
+ /* send it back as is in the rsp packet. */
u8 cmnd[MAX_CMND_SIZE]; /* the cdb for the command */
u32 bufflen; /* length of data to be transferred out or in */
- u16 guest_phys_entries; /* Number of entries in scatter-gather (sg)
- * list */
+ u16 guest_phys_entries; /* Number of entries in scatter-gather list */
struct guest_phys_info gpi_list[MAX_PHYS_INFO]; /* physical address
* information for each
- * fragment */
+ * fragment
+ */
enum dma_data_direction data_dir; /* direction of the data, if any */
- struct uisscsi_dest vdest; /* identifies the virtual hba, id,
- * channel, lun to which cmd was sent */
+ struct uisscsi_dest vdest; /* identifies the virtual hba, id, */
+ /* channel, lun to which cmd was sent */
- /* the following fields are needed to queue the rsp back to cmd
- * originator */
- int linuxstat; /* the original Linux status - for use by linux
- * vdisk code */
+ /* Needed to queue the rsp back to cmd originator */
+ int linuxstat; /* original Linux status used by linux vdisk */
u8 scsistat; /* the scsi status */
- u8 addlstat; /* non-scsi status - covers cases like timeout
- * needed by windows guests */
+ u8 addlstat; /* non-scsi status */
#define ADDL_SEL_TIMEOUT 4
/* the following fields are need to determine the result of command */
u8 sensebuf[MAX_SENSE_SIZE]; /* sense info in case cmd failed; */
/* it holds the sense_data struct; */
/* see that struct for details. */
- void *vdisk; /* contains pointer to the vdisk so that we can clean up
- * when the IO completes. */
+ void *vdisk; /* pointer to the vdisk to clean up when IO completes. */
int no_disk_result;
/* used to return no disk inquiry result
* when no_disk_result is set to 1,
@@ -258,15 +248,15 @@ struct uiscmdrsp_scsi {
*/
#define NO_DISK_INQUIRY_RESULT_LEN 36
-#define MIN_INQUIRY_RESULT_LEN 5 /* we need at least 5 bytes minimum for inquiry
- * result */
+#define MIN_INQUIRY_RESULT_LEN 5 /* 5 bytes minimum for inquiry result */
/* SCSI device version for no disk inquiry result */
#define SCSI_SPC2_VER 4 /* indicates SCSI SPC2 (SPC3 is 5) */
/* Windows and Linux want different things for a non-existent lun. So, we'll let
* caller pass in the peripheral qualifier and type.
- * NOTE:[4] SCSI returns (n-4); so we return length-1-4 or length-5. */
+ * NOTE:[4] SCSI returns (n-4); so we return length-1-4 or length-5.
+ */
#define SET_NO_DISK_INQUIRY_RESULT(buf, len, lun, lun0notpresent, notpresent) \
do { \
@@ -305,9 +295,7 @@ struct uiscmdrsp_scsi {
} \
} while (0)
-/*
- * Struct & Defines to support sense information.
- */
+/* Struct & Defines to support sense information. */
/* The following struct is returned in sensebuf field in uiscmdrsp_scsi. It is
* initialized in exactly the manner that is recommended in Windows (hence the
@@ -342,13 +330,11 @@ struct sense_data {
struct net_pkt_xmt {
int len; /* full length of data in the packet */
int num_frags; /* number of fragments in frags containing data */
- struct phys_info frags[MAX_PHYS_INFO]; /* physical page information for
- * each fragment */
+ struct phys_info frags[MAX_PHYS_INFO]; /* physical page information */
char ethhdr[ETH_HEADER_SIZE]; /* the ethernet header */
struct {
- /* these are needed for csum at uisnic end */
- u8 valid; /* 1 = rest of this struct is valid - else
- * ignore */
+ /* these are needed for csum at uisnic end */
+ u8 valid; /* 1 = struct is valid - else ignore */
u8 hrawoffv; /* 1 = hwrafoff is valid */
u8 nhrawoffv; /* 1 = nhwrafoff is valid */
u16 protocol; /* specifies packet protocol */
@@ -380,16 +366,18 @@ struct net_pkt_xmtdone {
*/
#define RCVPOST_BUF_SIZE 4032
#define MAX_NET_RCV_CHAIN \
- ((ETH_MAX_MTU+ETH_HEADER_SIZE + RCVPOST_BUF_SIZE-1) / RCVPOST_BUF_SIZE)
+ ((ETH_MAX_MTU + ETH_HEADER_SIZE + RCVPOST_BUF_SIZE - 1) \
+ / RCVPOST_BUF_SIZE)
struct net_pkt_rcvpost {
/* rcv buf size must be large enough to include ethernet data len +
* ethernet header len - we are choosing 2K because it is guaranteed
- * to be describable */
- struct phys_info frag; /* physical page information for the
- * single fragment 2K rcv buf */
- u64 unique_num; /* This is used to make sure that
- * receive posts are returned to */
+ * to be describable
+ */
+ struct phys_info frag; /* physical page information for the */
+ /* single fragment 2K rcv buf */
+ u64 unique_num;
+ /* unique_num ensure that receive posts are returned to */
/* the Adapter which we sent them originally. */
} __packed;
@@ -399,8 +387,7 @@ struct net_pkt_rcv {
u32 rcv_done_len; /* length of received data */
u8 numrcvbufs; /* number of receive buffers that contain the */
/* incoming data; guest end MUST chain these together. */
- void *rcvbuf[MAX_NET_RCV_CHAIN]; /* the list of receive buffers
- * that must be chained; */
+ void *rcvbuf[MAX_NET_RCV_CHAIN]; /* list of chained rcvbufs */
/* each entry is a receive buffer provided by NET_RCV_POST. */
/* NOTE: first rcvbuf in the chain will also be provided in net.buf. */
u64 unique_num;
@@ -469,18 +456,17 @@ struct uiscmdrsp_scsitaskmgmt {
#define TASK_MGMT_FAILED 0
} __packed;
-/* The following is used by uissd to send disk add/remove notifications to
- * Guest */
+/* Used by uissd to send disk add/remove notifications to Guest */
/* Note that the vHba pointer is not used by the Client/Guest side. */
struct uiscmdrsp_disknotify {
u8 add; /* 0-remove, 1-add */
- void *v_hba; /* Pointer to vhba_info for channel info to
- * route msg */
+ void *v_hba; /* channel info to route msg */
u32 channel, id, lun; /* SCSI Path of Disk to added or removed */
} __packed;
/* The following is used by virthba/vSCSI to send the Acquire/Release commands
- * to the IOVM. */
+ * to the IOVM.
+ */
struct uiscmdrsp_vdiskmgmt {
enum vdisk_mgmt_types vdisktype;
@@ -533,8 +519,8 @@ struct uiscmdrsp {
struct uiscmdrsp_disknotify disknotify;
struct uiscmdrsp_vdiskmgmt vdiskmgmt;
};
- void *private_data; /* used to send the response when the cmd is
- * done (scsi & scsittaskmgmt). */
+ void *private_data; /* send the response when the cmd is */
+ /* done (scsi & scsittaskmgmt). */
struct uiscmdrsp *next; /* General Purpose Queue Link */
struct uiscmdrsp *activeQ_next; /* Used to track active commands */
struct uiscmdrsp *activeQ_prev; /* Used to track active commands */
@@ -564,15 +550,11 @@ struct spar_io_channel_protocol {
} __packed;
#define MAX_CLIENTSTRING_LEN 1024
- u8 client_string[MAX_CLIENTSTRING_LEN];/* NULL terminated - so holds
- * max - 1 bytes */
+ /* client_string is NULL termimated so holds max -1 bytes */
+ u8 client_string[MAX_CLIENTSTRING_LEN];
} __packed;
-
-/*
- * INLINE functions for initializing and accessing I/O data channels
- */
-
+/* INLINE functions for initializing and accessing I/O data channels */
#define SIZEOF_PROTOCOL (COVER(sizeof(struct spar_io_channel_protocol), 64))
#define SIZEOF_CMDRSP (COVER(sizeof(struct uiscmdrsp), 64))
@@ -584,8 +566,7 @@ struct spar_io_channel_protocol {
* pfn-off-size entires.
*/
-/* we deal with 4K page sizes when we it comes to passing page information
- * between */
+/* use 4K page sizes when we it comes to passing page information between */
/* Guest and IOPartition. */
#define PI_PAGE_SIZE 0x1000
#define PI_PAGE_MASK 0x0FFF
@@ -594,18 +575,8 @@ struct spar_io_channel_protocol {
* room)
*/
static inline u16
-add_physinfo_entries(u32 inp_pfn, /* input - specifies the pfn to be used
- * to add entries */
- u16 inp_off, /* input - specifies the off to be used
- * to add entries */
- u32 inp_len, /* input - specifies the len to be used
- * to add entries */
- u16 index, /* input - index in array at which new
- * entries are added */
- u16 max_pi_arr_entries, /* input - specifies the maximum
- * entries pi_arr can hold */
- struct phys_info pi_arr[]) /* input & output - array to
- * which entries are added */
+add_physinfo_entries(u32 inp_pfn, u16 inp_off, u32 inp_len, u16 index,
+ u16 max_pi_arr_entries, struct phys_info pi_arr[])
{
u32 len;
u16 i, firstlen;
diff --git a/drivers/staging/unisys/include/vbushelper.h b/drivers/staging/unisys/include/vbushelper.h
index f272975b2920..f1b6aacb79d7 100644
--- a/drivers/staging/unisys/include/vbushelper.h
+++ b/drivers/staging/unisys/include/vbushelper.h
@@ -19,7 +19,8 @@
#define __VBUSHELPER_H__
/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
- * command line */
+ * command line
+ */
#define TARGET_HOSTNAME "linuxguest"
diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h
index 9235536fa75f..2a64a9ce0208 100644
--- a/drivers/staging/unisys/include/visorbus.h
+++ b/drivers/staging/unisys/include/visorbus.h
@@ -140,8 +140,8 @@ struct visor_device {
struct {
int major, minor;
void *attr; /* private use by devmajorminor_attr.c you can
- * change this constant to whatever you
- * want; */
+ * change this constant to whatever you want
+ */
} devnodes[5];
/* the code will detect and behave appropriately) */
struct semaphore visordriver_callback_lock;
diff --git a/drivers/staging/unisys/visorbus/Kconfig b/drivers/staging/unisys/visorbus/Kconfig
index 9b299ac86015..511388075ffa 100644
--- a/drivers/staging/unisys/visorbus/Kconfig
+++ b/drivers/staging/unisys/visorbus/Kconfig
@@ -6,4 +6,9 @@ config UNISYS_VISORBUS
tristate "Unisys visorbus driver"
depends on UNISYSSPAR
---help---
- If you say Y here, you will enable the Unisys visorbus driver.
+ The visorbus driver is a virtualized bus for the Unisys s-Par firmware.
+ Virtualized devices allow Linux guests on a system to share disks and
+ network cards that do not have SR-IOV support, and to be accessed using
+ the partition desktop application. The visorbus driver is required to
+ discover devices on an s-Par guest, and must be present for any other
+ s-Par guest driver to function correctly.
diff --git a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
index 3c97ebac4f32..23ad0ea6c9fc 100644
--- a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
+++ b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
@@ -39,7 +39,8 @@
#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */
/* Payload and Parameter Related------------------------------------[400-499] */
#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT,
- * DEVICE_CONFIGURE */
+ * DEVICE_CONFIGURE
+ */
#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401 /* Multiple */
#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */
#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */
@@ -48,36 +49,43 @@
* BUS_CONFIGURE,
* DEVICE_CREATE,
* DEVICE_CONFIG
- * DEVICE_DESTROY */
+ * DEVICE_DESTROY
+ */
#define CONTROLVM_RESP_ERROR_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT */
/* DEVICE_CREATE,
* DEVICE_CONFIGURE,
- * DEVICE_DESTROY */
+ * DEVICE_DESTROY
+ */
#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID 502 /* DEVICE_CREATE,
- * DEVICE_CONFIGURE */
+ * DEVICE_CONFIGURE
+ */
/* Partition Driver Callback Interface----------------------[600-699] */
#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE,
* BUS_DESTROY,
* DEVICE_CREATE,
- * DEVICE_DESTROY */
+ * DEVICE_DESTROY
+ */
/* Unable to invoke VIRTPCI callback */
#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605
/* BUS_CREATE,
* BUS_DESTROY,
* DEVICE_CREATE,
- * DEVICE_DESTROY */
+ * DEVICE_DESTROY
+ */
/* VIRTPCI Callback returned error */
#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606
/* SWITCH_ATTACHEXTPORT,
* SWITCH_DETACHEXTPORT
- * DEVICE_CONFIGURE */
+ * DEVICE_CONFIGURE
+ */
/* generic device callback returned error */
/* Bus Related------------------------------------------------------[700-799] */
#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */
/* Channel Related--------------------------------------------------[800-899] */
#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO,
- * DEVICE_DESTROY */
+ * DEVICE_DESTROY
+ */
#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */
/* Chipset Shutdown Related---------------------------------------[1000-1099] */
#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED 1000
diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c
index 115b7aa9560a..00b152764f84 100644
--- a/drivers/staging/unisys/visorbus/periodic_work.c
+++ b/drivers/staging/unisys/visorbus/periodic_work.c
@@ -43,11 +43,12 @@ static void periodic_work_func(struct work_struct *work)
(*pw->workfunc)(pw->workfuncarg);
}
-struct periodic_work *visor_periodic_work_create(ulong jiffy_interval,
- struct workqueue_struct *workqueue,
- void (*workfunc)(void *),
- void *workfuncarg,
- const char *devnam)
+struct periodic_work
+*visor_periodic_work_create(ulong jiffy_interval,
+ struct workqueue_struct *workqueue,
+ void (*workfunc)(void *),
+ void *workfuncarg,
+ const char *devnam)
{
struct periodic_work *pw;
diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h
index 80e64477e547..90fa12e62f26 100644
--- a/drivers/staging/unisys/visorbus/vbuschannel.h
+++ b/drivers/staging/unisys/visorbus/vbuschannel.h
@@ -36,10 +36,11 @@ static const uuid_le spar_vbus_channel_protocol_uuid =
#define SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
/* Must increment this whenever you insert or delete fields within this channel
-* struct. Also increment whenever you change the meaning of fields within this
-* channel struct so as to break pre-existing software. Note that you can
-* usually add fields to the END of the channel struct withOUT needing to
-* increment this. */
+ * struct. Also increment whenever you change the meaning of fields within this
+ * channel struct so as to break pre-existing software. Note that you can
+ * usually add fields to the END of the channel struct withOUT needing to
+ * increment this.
+ */
#define SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID 1
#define SPAR_VBUS_CHANNEL_OK_CLIENT(ch) \
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
index a272b48bab28..eac97d22278a 100644
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ b/drivers/staging/unisys/visorbus/visorbus_main.c
@@ -1078,7 +1078,8 @@ away:
}
/* Write the contents of <info> to the struct
- * spar_vbus_channel_protocol.chp_info. */
+ * spar_vbus_channel_protocol.chp_info.
+ */
static int
write_vbus_chp_info(struct visorchannel *chan,
@@ -1096,7 +1097,8 @@ write_vbus_chp_info(struct visorchannel *chan,
}
/* Write the contents of <info> to the struct
- * spar_vbus_channel_protocol.bus_info. */
+ * spar_vbus_channel_protocol.bus_info.
+ */
static int
write_vbus_bus_info(struct visorchannel *chan,
@@ -1370,7 +1372,8 @@ pause_state_change_complete(struct visor_device *dev, int status)
/* Notify the chipset driver that the pause is complete, which
* will presumably want to send some sort of response to the
- * initiator. */
+ * initiator.
+ */
(*chipset_responders.device_pause) (dev, status);
}
@@ -1390,7 +1393,8 @@ resume_state_change_complete(struct visor_device *dev, int status)
/* Notify the chipset driver that the resume is complete,
* which will presumably want to send some sort of response to
- * the initiator. */
+ * the initiator.
+ */
(*chipset_responders.device_resume) (dev, status);
}
@@ -1437,7 +1441,8 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
* existing problem prevents us from ever getting a bus
* resume... This hack would fail to work should we
* ever have a bus that contains NO devices, since we
- * would never even get here in that case. */
+ * would never even get here in that case.
+ */
fix_vbus_dev_info(dev);
if (!drv->resume)
goto away;
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
index a4e117f101cf..891b8db7c5ec 100644
--- a/drivers/staging/unisys/visorbus/visorchannel.c
+++ b/drivers/staging/unisys/visorbus/visorchannel.c
@@ -41,8 +41,8 @@ struct visorchannel {
struct channel_header chan_hdr;
uuid_le guid;
ulong size;
- bool needs_lock; /* channel creator knows if more than one
- * thread will be inserting or removing */
+ bool needs_lock; /* channel creator knows if more than one */
+ /* thread will be inserting or removing */
spinlock_t insert_lock; /* protect head writes in chan_hdr */
spinlock_t remove_lock; /* protect tail writes in chan_hdr */
diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h
index c8d8483bd4df..c043fa41ceda 100644
--- a/drivers/staging/unisys/visorbus/vmcallinterface.h
+++ b/drivers/staging/unisys/visorbus/vmcallinterface.h
@@ -43,20 +43,15 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */
* - the 0x01 identifies it as the 1st instance of a VMCALL_VIRTPART
* type of VMCALL
*/
-
- VMCALL_IO_CONTROLVM_ADDR = 0x0501, /* used by all Guests, not just
- * IO */
- VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708, /* Allow caller to
- * query virtual time
- * offset */
- VMCALL_POST_CODE_LOGEVENT = 0x070B, /* LOGEVENT Post Code (RDX) with
- * specified subsystem mask (RCX
- * - monitor_subsystems.h) and
- * severity (RDX) */
- VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02 /* Allow
- * ULTRA_SERVICE_CAPABILITY_TIME
- * capable guest to make
- * VMCALL */
+ /* used by all Guests, not just IO */
+ VMCALL_IO_CONTROLVM_ADDR = 0x0501,
+ /* Allow caller to query virtual time offset */
+ VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708,
+ /* LOGEVENT Post Code (RDX) with specified subsystem mask */
+ /* (RCX - monitor_subsystems.h) and severity (RDX) */
+ VMCALL_POST_CODE_LOGEVENT = 0x070B,
+ /* Allow ULTRA_SERVICE_CAPABILITY_TIME capable guest to make VMCALL */
+ VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02
};
#define VMCALL_SUCCESS 0
@@ -74,7 +69,8 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */
unisys_extended_vmcall(method, param1, param2, param3)
/* The following uses VMCALL_POST_CODE_LOGEVENT interface but is currently
- * not used much */
+ * not used much
+ */
#define ISSUE_IO_VMCALL_POSTCODE_SEVERITY(postcode, severity) \
ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity, \
MDS_APPOS, postcode)
@@ -84,11 +80,11 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */
/* Parameters to VMCALL_IO_CONTROLVM_ADDR interface */
struct vmcall_io_controlvm_addr_params {
- /* The Guest-relative physical address of the ControlVm channel.
- * This VMCall fills this in with the appropriate address. */
+ /* The Guest-relative physical address of the ControlVm channel. */
+ /* This VMCall fills this in with the appropriate address. */
u64 address; /* contents provided by this VMCALL (OUT) */
- /* the size of the ControlVm channel in bytes This VMCall fills this
- * in with the appropriate address. */
+ /* the size of the ControlVm channel in bytes This VMCall fills this */
+ /* in with the appropriate address. */
u32 channel_bytes; /* contents provided by this VMCALL (OUT) */
u8 unused[4]; /* Unused Bytes in the 64-Bit Aligned Struct */
} __packed;
diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c
index c119f20dfd44..d5178b44ba8c 100644
--- a/drivers/staging/unisys/visorhba/visorhba_main.c
+++ b/drivers/staging/unisys/visorhba/visorhba_main.c
@@ -453,7 +453,6 @@ visorhba_queue_command_lck(struct scsi_cmnd *scsicmd,
struct uiscmdrsp *cmdrsp;
struct scsi_device *scsidev = scsicmd->device;
int insert_location;
- unsigned char op;
unsigned char *cdb = scsicmd->cmnd;
struct Scsi_Host *scsihost = scsidev->host;
unsigned int i;
@@ -461,7 +460,6 @@ visorhba_queue_command_lck(struct scsi_cmnd *scsicmd,
(struct visorhba_devdata *)scsihost->hostdata;
struct scatterlist *sg = NULL;
struct scatterlist *sglist = NULL;
- int err = 0;
if (devdata->serverdown || devdata->serverchangingstate)
return SCSI_MLQUEUE_DEVICE_BUSY;
@@ -496,10 +494,8 @@ visorhba_queue_command_lck(struct scsi_cmnd *scsicmd,
if (cmdrsp->scsi.bufflen > devdata->max_buff_len)
devdata->max_buff_len = cmdrsp->scsi.bufflen;
- if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) {
- err = SCSI_MLQUEUE_DEVICE_BUSY;
+ if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO)
goto err_del_scsipending_ent;
- }
/* convert buffer to phys information */
/* buffer is scatterlist - copy it out */
@@ -511,19 +507,17 @@ visorhba_queue_command_lck(struct scsi_cmnd *scsicmd,
}
cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd);
- op = cdb[0];
if (!visorchannel_signalinsert(devdata->dev->visorchannel,
IOCHAN_TO_IOPART,
- cmdrsp)) {
+ cmdrsp))
/* queue must be full and we aren't going to wait */
- err = SCSI_MLQUEUE_DEVICE_BUSY;
goto err_del_scsipending_ent;
- }
+
return 0;
err_del_scsipending_ent:
del_scsipending_ent(devdata, insert_location);
- return err;
+ return SCSI_MLQUEUE_DEVICE_BUSY;
}
/**
@@ -759,11 +753,9 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
struct visorhba_devdata *devdata;
struct visordisk_info *vdisk;
struct scsi_device *scsidev;
- struct sense_data *sd;
scsidev = scsicmd->device;
memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE);
- sd = (struct sense_data *)scsicmd->sense_buffer;
/* Do not log errors for disk-not-present inquiries */
if ((cmdrsp->scsi.cmnd[0] == INQUIRY) &&
diff --git a/drivers/staging/unisys/visorinput/Kconfig b/drivers/staging/unisys/visorinput/Kconfig
index d83deb4137e8..3476d419d32c 100644
--- a/drivers/staging/unisys/visorinput/Kconfig
+++ b/drivers/staging/unisys/visorinput/Kconfig
@@ -6,5 +6,10 @@ config UNISYS_VISORINPUT
tristate "Unisys visorinput driver"
depends on UNISYSSPAR && UNISYS_VISORBUS && FB
---help---
- If you say Y here, you will enable the Unisys visorinput driver.
+ The Unisys s-Par visorinput driver provides a virtualized system
+ console (keyboard and mouse) that is accessible through the
+ s-Par firmware's user interface. s-Par provides video using the EFI
+ GOP protocol, so If this driver is not present, the Linux guest should
+ still boot with visible output in the partition desktop, but keyboard
+ and mouse interaction will not be available.
diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c
index 5c16f6634368..38d4d5b884df 100644
--- a/drivers/staging/unisys/visorinput/visorinput.c
+++ b/drivers/staging/unisys/visorinput/visorinput.c
@@ -523,7 +523,7 @@ visorinput_channel_interrupt(struct visor_device *dev)
struct ultra_inputreport r;
int scancode, keycode;
struct input_dev *visorinput_dev;
- int xmotion, ymotion, zmotion, button;
+ int xmotion, ymotion, button;
int i;
struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device);
@@ -604,12 +604,10 @@ visorinput_channel_interrupt(struct visor_device *dev)
}
break;
case inputaction_wheel_rotate_away:
- zmotion = r.activity.arg1;
input_report_rel(visorinput_dev, REL_WHEEL, 1);
input_sync(visorinput_dev);
break;
case inputaction_wheel_rotate_toward:
- zmotion = r.activity.arg1;
input_report_rel(visorinput_dev, REL_WHEEL, -1);
input_sync(visorinput_dev);
break;
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index 296b11cea247..05194707278a 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -1742,7 +1742,6 @@ poll_for_irq(unsigned long v)
atomic_set(&devdata->interrupt_rcvd, 0);
mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
-
}
/**
diff --git a/drivers/staging/vme/devices/vme_pio2_cntr.c b/drivers/staging/vme/devices/vme_pio2_cntr.c
index 6335471faa36..486c30c4956f 100644
--- a/drivers/staging/vme/devices/vme_pio2_cntr.c
+++ b/drivers/staging/vme/devices/vme_pio2_cntr.c
@@ -61,7 +61,7 @@ int pio2_cntr_reset(struct pio2_card *card)
/* Ensure all counter interrupts are cleared */
do {
retval = vme_master_read(card->window, &reg, 1,
- PIO2_REGS_INT_STAT_CNTR);
+ PIO2_REGS_INT_STAT_CNTR);
if (retval < 0)
return retval;
} while (reg != 0);
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
index 35c6ce5047de..4f3cdbcedb3e 100644
--- a/drivers/staging/vme/devices/vme_pio2_core.c
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -90,7 +90,7 @@ static void pio2_int(int level, int vector, void *ptr)
case 4:
/* Channels 0 to 7 */
retval = vme_master_read(card->window, &reg, 1,
- PIO2_REGS_INT_STAT[vec - 1]);
+ PIO2_REGS_INT_STAT[vec - 1]);
if (retval < 0) {
dev_err(&card->vdev->dev,
"Unable to read IRQ status register\n");
@@ -100,8 +100,8 @@ static void pio2_int(int level, int vector, void *ptr)
channel = ((vec - 1) * 8) + i;
if (reg & PIO2_CHANNEL_BIT[channel])
dev_info(&card->vdev->dev,
- "Interrupt on I/O channel %d\n",
- channel);
+ "Interrupt on I/O channel %d\n",
+ channel);
}
break;
case 5:
@@ -215,7 +215,7 @@ static int pio2_probe(struct vme_dev *vdev)
u8 reg;
int vec;
- card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL);
+ card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card) {
retval = -ENOMEM;
goto err_struct;
@@ -230,7 +230,7 @@ static int pio2_probe(struct vme_dev *vdev)
card->vdev = vdev;
for (i = 0; i < PIO2_VARIANT_LENGTH; i++) {
- if (isdigit(card->variant[i]) == 0) {
+ if (!isdigit(card->variant[i])) {
dev_err(&card->vdev->dev, "Variant invalid\n");
retval = -EINVAL;
goto err_variant;
@@ -289,7 +289,7 @@ static int pio2_probe(struct vme_dev *vdev)
}
retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24,
- (VME_SCT | VME_USER | VME_DATA), VME_D16);
+ VME_SCT | VME_USER | VME_DATA, VME_D16);
if (retval) {
dev_err(&card->vdev->dev,
"Unable to configure VME master resource\n");
@@ -335,7 +335,7 @@ static int pio2_probe(struct vme_dev *vdev)
/* Set VME vector */
retval = vme_master_write(card->window, &card->irq_vector, 1,
- PIO2_REGS_VME_VECTOR);
+ PIO2_REGS_VME_VECTOR);
if (retval < 0)
return retval;
@@ -343,7 +343,7 @@ static int pio2_probe(struct vme_dev *vdev)
vec = card->irq_vector | PIO2_VME_VECTOR_SPUR;
retval = vme_irq_request(vdev, card->irq_level, vec,
- &pio2_int, (void *)card);
+ &pio2_int, card);
if (retval < 0) {
dev_err(&card->vdev->dev,
"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
@@ -356,7 +356,7 @@ static int pio2_probe(struct vme_dev *vdev)
vec = card->irq_vector | PIO2_VECTOR_BANK[i];
retval = vme_irq_request(vdev, card->irq_level, vec,
- &pio2_int, (void *)card);
+ &pio2_int, card);
if (retval < 0) {
dev_err(&card->vdev->dev,
"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
@@ -370,7 +370,7 @@ static int pio2_probe(struct vme_dev *vdev)
vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
retval = vme_irq_request(vdev, card->irq_level, vec,
- &pio2_int, (void *)card);
+ &pio2_int, card);
if (retval < 0) {
dev_err(&card->vdev->dev,
"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
@@ -397,7 +397,7 @@ static int pio2_probe(struct vme_dev *vdev)
dev_set_drvdata(&card->vdev->dev, card);
dev_info(&card->vdev->dev,
- "PIO2 (variant %s) configured at 0x%lx\n", card->variant,
+ "PIO2 (variant %s) configured at 0x%lx\n", card->variant,
card->base);
return 0;
diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c
index 77901b345a71..df992c3cb5ce 100644
--- a/drivers/staging/vme/devices/vme_pio2_gpio.c
+++ b/drivers/staging/vme/devices/vme_pio2_gpio.c
@@ -37,14 +37,13 @@ static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
struct pio2_card *card = gpio_to_pio2_card(chip);
if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
- (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
-
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
dev_err(&card->vdev->dev, "Channel not available as input\n");
return 0;
}
retval = vme_master_read(card->window, &reg, 1,
- PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
+ PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
if (retval < 0) {
dev_err(&card->vdev->dev, "Unable to read from GPIO\n");
return 0;
@@ -67,16 +66,15 @@ static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
return 0;
}
-static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset,
- int value)
+static void pio2_gpio_set(struct gpio_chip *chip,
+ unsigned int offset, int value)
{
u8 reg;
int retval;
struct pio2_card *card = gpio_to_pio2_card(chip);
if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
- (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
-
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
dev_err(&card->vdev->dev, "Channel not available as output\n");
return;
}
@@ -89,7 +87,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset,
~PIO2_CHANNEL_BIT[offset];
retval = vme_master_write(card->window, &reg, 1,
- PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
+ PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
if (retval < 0) {
dev_err(&card->vdev->dev, "Unable to write to GPIO\n");
return;
@@ -105,7 +103,7 @@ static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
struct pio2_card *card = gpio_to_pio2_card(chip);
if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
- (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
dev_err(&card->vdev->dev,
"Channel directionality not configurable at runtime\n");
@@ -124,7 +122,7 @@ static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
struct pio2_card *card = gpio_to_pio2_card(chip);
if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
- (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
dev_err(&card->vdev->dev,
"Channel directionality not configurable at runtime\n");
@@ -150,7 +148,7 @@ int pio2_gpio_reset(struct pio2_card *card)
/* Zero output registers */
for (i = 0; i < 4; i++) {
retval = vme_master_write(card->window, &data, 1,
- PIO2_REGS_DATA[i]);
+ PIO2_REGS_DATA[i]);
if (retval < 0)
return retval;
card->bank[i].value = 0;
@@ -159,12 +157,12 @@ int pio2_gpio_reset(struct pio2_card *card)
/* Set input interrupt masks */
for (i = 0; i < 4; i++) {
retval = vme_master_write(card->window, &data, 1,
- PIO2_REGS_INT_MASK[i * 2]);
+ PIO2_REGS_INT_MASK[i * 2]);
if (retval < 0)
return retval;
retval = vme_master_write(card->window, &data, 1,
- PIO2_REGS_INT_MASK[(i * 2) + 1]);
+ PIO2_REGS_INT_MASK[(i * 2) + 1]);
if (retval < 0)
return retval;
@@ -176,7 +174,7 @@ int pio2_gpio_reset(struct pio2_card *card)
for (i = 0; i < 4; i++) {
do {
retval = vme_master_read(card->window, &data, 1,
- PIO2_REGS_INT_STAT[i]);
+ PIO2_REGS_INT_STAT[i]);
if (retval < 0)
return retval;
} while (data != 0);
@@ -192,7 +190,7 @@ int pio2_gpio_init(struct pio2_card *card)
label = kasprintf(GFP_KERNEL,
"%s@%s", driver_name, dev_name(&card->vdev->dev));
- if (label == NULL)
+ if (!label)
return -ENOMEM;
card->gc.label = label;
@@ -207,7 +205,7 @@ int pio2_gpio_init(struct pio2_card *card)
card->gc.set = pio2_gpio_set;
/* This function adds a memory mapped GPIO chip */
- retval = gpiochip_add(&(card->gc));
+ retval = gpiochip_add(&card->gc);
if (retval) {
dev_err(&card->vdev->dev, "Unable to register GPIO\n");
kfree(card->gc.label);
@@ -220,7 +218,7 @@ void pio2_gpio_exit(struct pio2_card *card)
{
const char *label = card->gc.label;
- gpiochip_remove(&(card->gc));
+ gpiochip_remove(&card->gc);
kfree(label);
}
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 8e61a3b3e7e4..b95883bc68fe 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -308,8 +308,8 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case VME_IRQ_GEN:
copied = copy_from_user(&irq_req, argp,
- sizeof(struct vme_irq_id));
- if (copied != 0) {
+ sizeof(irq_req));
+ if (copied) {
pr_warn("Partial copy from userspace\n");
return -EFAULT;
}
@@ -322,7 +322,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
case MASTER_MINOR:
switch (cmd) {
case VME_GET_MASTER:
- memset(&master, 0, sizeof(struct vme_master));
+ memset(&master, 0, sizeof(master));
/* XXX We do not want to push aspace, cycle and width
* to userspace as they are
@@ -334,8 +334,8 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
&master.cycle, &master.dwidth);
copied = copy_to_user(argp, &master,
- sizeof(struct vme_master));
- if (copied != 0) {
+ sizeof(master));
+ if (copied) {
pr_warn("Partial copy to userspace\n");
return -EFAULT;
}
@@ -350,7 +350,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
}
copied = copy_from_user(&master, argp, sizeof(master));
- if (copied != 0) {
+ if (copied) {
pr_warn("Partial copy from userspace\n");
return -EFAULT;
}
@@ -368,7 +368,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
case SLAVE_MINOR:
switch (cmd) {
case VME_GET_SLAVE:
- memset(&slave, 0, sizeof(struct vme_slave));
+ memset(&slave, 0, sizeof(slave));
/* XXX We do not want to push aspace, cycle and width
* to userspace as they are
@@ -379,8 +379,8 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
&slave.aspace, &slave.cycle);
copied = copy_to_user(argp, &slave,
- sizeof(struct vme_slave));
- if (copied != 0) {
+ sizeof(slave));
+ if (copied) {
pr_warn("Partial copy to userspace\n");
return -EFAULT;
}
@@ -390,7 +390,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
case VME_SET_SLAVE:
copied = copy_from_user(&slave, argp, sizeof(slave));
- if (copied != 0) {
+ if (copied) {
pr_warn("Partial copy from userspace\n");
return -EFAULT;
}
@@ -757,7 +757,7 @@ static int __init vme_user_init(void)
* we just change the code in vme_user_match().
*/
retval = vme_register_driver(&vme_user_driver, VME_MAX_SLOTS);
- if (retval != 0)
+ if (retval)
goto err_reg;
return retval;
diff --git a/drivers/staging/vme/devices/vme_user.h b/drivers/staging/vme/devices/vme_user.h
index b8cc7bc78a73..a6cb75686fa4 100644
--- a/drivers/staging/vme/devices/vme_user.h
+++ b/drivers/staging/vme/devices/vme_user.h
@@ -20,7 +20,6 @@ struct vme_master {
#endif
} __packed;
-
/*
* IOCTL Commands and structures
*/
@@ -28,7 +27,6 @@ struct vme_master {
/* Magic number for use in ioctls */
#define VME_IOC_MAGIC 0xAE
-
/* VMEbus Slave Window Configuration Structure */
struct vme_slave {
__u32 enable; /* State of Window */
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index 76ad036cbbaa..b6730a8068fd 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -238,7 +238,7 @@ bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type)
BBbWriteEmbedded(priv, 0x88, 0x03);
bySlot = C_SLOT_SHORT;
bySIFS = C_SIFS_A;
- byDIFS = C_SIFS_A + 2*C_SLOT_SHORT;
+ byDIFS = C_SIFS_A + 2 * C_SLOT_SHORT;
byCWMaxMin = 0xA4;
} else if (bb_type == BB_TYPE_11B) {
MACvSetBBType(priv->PortOffset, BB_TYPE_11B);
@@ -286,7 +286,7 @@ bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type)
if (priv->bShortSlotTime) {
bySlot = C_SLOT_SHORT;
- byDIFS = C_SIFS_BG + 2*C_SLOT_SHORT;
+ byDIFS = C_SIFS_BG + 2 * C_SLOT_SHORT;
} else {
bySlot = C_SLOT_LONG;
byDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index e5be261f2e69..9417c935fc30 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: baseband.c
*
diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h
index 771ea4054174..807a5809b5d9 100644
--- a/drivers/staging/vt6656/baseband.h
+++ b/drivers/staging/vt6656/baseband.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: baseband.h
*
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index 70685e5a79a9..a382fc6aa9d3 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: card.c
* Purpose: Provide functions to setup NIC operation mode
@@ -82,7 +79,7 @@ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel)
connection_channel, 0, 0, NULL);
vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL,
- (u8)(connection_channel|0x80));
+ (u8)(connection_channel | 0x80));
}
/*
@@ -285,7 +282,6 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type)
vnt_get_phy_field(priv, 14,
vnt_get_cck_rate(priv, RATE_11M), PK_TYPE_11B, &phy[3]);
-
/*RSPINF_a_6*/
vnt_calculate_ofdm_rate(RATE_6M, bb_type, &tx_rate[0], &rsv_time[0]);
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
index 03fc1678896b..c2cde7e92c8f 100644
--- a/drivers/staging/vt6656/card.h
+++ b/drivers/staging/vt6656/card.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: card.h
*
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
index 8412d0532fb2..a0fe288c1322 100644
--- a/drivers/staging/vt6656/channel.c
+++ b/drivers/staging/vt6656/channel.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: channel.c
*
diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h
index 21c080803714..fcea6995fe26 100644
--- a/drivers/staging/vt6656/channel.h
+++ b/drivers/staging/vt6656/channel.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: channel.h
*
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index f79af8513ff2..59e3071021bd 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: desc.h
*
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index dec36f296f3d..76b5f4127f95 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: device.h
*
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index e6367ed3b0bb..6019aac8bdd5 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: dpc.c
*
diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h
index 95e0e83a487e..5a92bd86cee2 100644
--- a/drivers/staging/vt6656/dpc.h
+++ b/drivers/staging/vt6656/dpc.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: dpc.h
*
diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c
index d440f284bf18..1b48f9c86f63 100644
--- a/drivers/staging/vt6656/firmware.c
+++ b/drivers/staging/vt6656/firmware.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: baseband.c
*
diff --git a/drivers/staging/vt6656/firmware.h b/drivers/staging/vt6656/firmware.h
index d594dbe1c147..e2b54acb8fdb 100644
--- a/drivers/staging/vt6656/firmware.h
+++ b/drivers/staging/vt6656/firmware.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: firmware.h
*
diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c
index 14b8ebc6508d..8d05acbc0e23 100644
--- a/drivers/staging/vt6656/int.c
+++ b/drivers/staging/vt6656/int.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: int.c
*
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h
index 154605c63947..97e55bacbb7c 100644
--- a/drivers/staging/vt6656/int.h
+++ b/drivers/staging/vt6656/int.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: int.h
*
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 181745d8e250..0246a8fc47fe 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: key.c
*
@@ -163,7 +159,6 @@ int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
}
-
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE,
key_dec_mode, true);
diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h
index 3cb1291055ed..7861faf5138f 100644
--- a/drivers/staging/vt6656/key.h
+++ b/drivers/staging/vt6656/key.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: key.h
*
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
index 5dfac05b9cf1..eeed16e9124e 100644
--- a/drivers/staging/vt6656/mac.c
+++ b/drivers/staging/vt6656/mac.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: mac.c
*
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
index d53fcef87b4a..4c6e610f1bc1 100644
--- a/drivers/staging/vt6656/mac.h
+++ b/drivers/staging/vt6656/mac.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: mac.h
*
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 01e642db311e..ee8d1e1a24c2 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: main_usb.c
*
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
index d5912d23aa0d..c025dab0f62c 100644
--- a/drivers/staging/vt6656/power.c
+++ b/drivers/staging/vt6656/power.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: power.c
*
@@ -59,10 +55,9 @@ void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval)
/* set period of power up before TBTT */
vnt_mac_write_word(priv, MAC_REG_PWBT, C_PWBT);
- if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
+ if (priv->op_mode != NL80211_IFTYPE_ADHOC)
/* set AID */
vnt_mac_write_word(priv, MAC_REG_AIDATIM, aid);
- }
/* Warren:06-18-2004,the sequence must follow
* PSEN->AUTOSLEEP->GO2DOZE
@@ -85,11 +80,10 @@ void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval)
/* first time set listen next beacon */
vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN);
- } else {
+ } else
/* always listen beacon */
vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
- }
dev_dbg(&priv->usb->dev, "PS:Power Saving Mode Enable...\n");
}
@@ -109,7 +103,7 @@ void vnt_disable_power_saving(struct vnt_private *priv)
/* disable power saving hw function */
vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0,
- 0, 0, NULL);
+ 0, 0, NULL);
/* clear AutoSleep */
vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h
index 7696b714850c..9d1ebb695f9d 100644
--- a/drivers/staging/vt6656/power.h
+++ b/drivers/staging/vt6656/power.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: power.h
*
diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c
index c4286ccac320..816206c92f57 100644
--- a/drivers/staging/vt6656/rf.c
+++ b/drivers/staging/vt6656/rf.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: rf.c
*
diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h
index 3acdc65b1e56..c3d4f06d65f4 100644
--- a/drivers/staging/vt6656/rf.h
+++ b/drivers/staging/vt6656/rf.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: rf.h
*
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index efb54f53b4f9..a0c69b697901 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: rxtx.c
*
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 90b34ab2f6ce..4a79c404275b 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: rxtx.h
*
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index c975c3b87093..351a99f3d684 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: usbpipe.c
*
diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h
index e74aa0809928..8bafd9aee1fa 100644
--- a/drivers/staging/vt6656/usbpipe.h
+++ b/drivers/staging/vt6656/usbpipe.h
@@ -12,10 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*
* File: usbpipe.h
*
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 3cbf4791bac1..4846a898d39b 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: wcmd.c
*
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
index 2b0ee285eb0b..764c09ccd42d 100644
--- a/drivers/staging/vt6656/wcmd.h
+++ b/drivers/staging/vt6656/wcmd.h
@@ -12,9 +12,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* File: wcmd.h
*
diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile
index 64c2f1b83dfb..650123df0b4c 100644
--- a/drivers/staging/wilc1000/Makefile
+++ b/drivers/staging/wilc1000/Makefile
@@ -21,8 +21,8 @@ ccflags-$(CONFIG_WILC1000_DYNAMICALLY_ALLOCATE_MEMROY) += -DWILC_NORMAL_ALLOC
wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
wilc_msgqueue.o \
coreconfigurator.o host_interface.o \
- wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o \
+ wilc_wlan_cfg.o wilc_debugfs.o \
wilc_wlan.o
-wilc1000-$(CONFIG_WILC1000_SDIO) += linux_wlan_sdio.o
-wilc1000-$(CONFIG_WILC1000_SPI) += linux_wlan_spi.o
+wilc1000-$(CONFIG_WILC1000_SDIO) += linux_wlan_sdio.o wilc_sdio.o
+wilc1000-$(CONFIG_WILC1000_SPI) += linux_wlan_spi.o wilc_spi.o
diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c
index 427adfd295da..56e0cf90fde6 100644
--- a/drivers/staging/wilc1000/coreconfigurator.c
+++ b/drivers/staging/wilc1000/coreconfigurator.c
@@ -333,13 +333,6 @@ u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen)
return 0; /* no MIB here */
}
-u8 get_current_channel(u8 *pu8msa, u16 u16RxLen)
-{
- /* Extract current channel information from */
- /* the beacon/probe response frame */
- return get_current_channel_802_11n(pu8msa, u16RxLen);
-}
-
/**
* @brief parses the received 'N' message
* @details
@@ -427,18 +420,22 @@ s32 parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
/* Get BSSID */
get_BSSID(pu8msa, pstrNetworkInfo->au8bssid);
- /* Get the current channel */
- pstrNetworkInfo->u8channel = get_current_channel(pu8msa, (u16RxLen + FCS_LEN));
+ /*
+ * Extract current channel information from
+ * the beacon/probe response frame
+ */
+ pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa,
+ u16RxLen + FCS_LEN);
/* Get beacon period */
- u8index = (MAC_HDR_LEN + TIME_STAMP_LEN);
+ u8index = MAC_HDR_LEN + TIME_STAMP_LEN;
pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index);
u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
/* Get DTIM Period */
- pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index);
+ pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index);
if (pu8TimElm != NULL)
pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
@@ -614,7 +611,6 @@ s32 send_config_pkt(u8 mode, struct wid *wids, u32 count, u32 drv)
wids[counter].id,
wids[counter].val,
wids[counter].size);
-
}
} else if (mode == SET_CFG) {
for (counter = 0; counter < count; counter++) {
diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h
index 6294d929a800..3253f6f1393a 100644
--- a/drivers/staging/wilc1000/coreconfigurator.h
+++ b/drivers/staging/wilc1000/coreconfigurator.h
@@ -72,7 +72,7 @@ typedef enum {
struct wid {
u16 id;
- enum WID_TYPE type;
+ enum wid_type type;
s32 size;
s8 *val;
};
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 38fead44cce0..d5b7725ec2bf 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -7,6 +7,7 @@
#include "wilc_wlan_if.h"
#include "wilc_msgqueue.h"
#include <linux/etherdevice.h>
+#include "wilc_wfi_netdevice.h"
extern u8 connecting;
@@ -60,6 +61,7 @@ extern u8 g_wilc_initialized;
#define BA_SESSION_DEFAULT_BUFFER_SIZE 16
#define BA_SESSION_DEFAULT_TIMEOUT 1000
#define BLOCK_ACK_REQ_SIZE 0x14
+#define FALSE_FRMWR_CHANNEL 100
struct cfg_param_attr {
struct cfg_param_val cfg_attr_info;
@@ -226,7 +228,7 @@ struct join_bss_param {
u8 idx;
u8 duration[4];
u8 interval[4];
- u8 au8StartTime[4];
+ u8 start_time[4];
};
static struct host_if_drv *wfidrv_list[NUM_CONCURRENT_IFC + 1];
@@ -241,7 +243,7 @@ static struct semaphore hif_sema_wait_response;
static struct semaphore hif_sema_deinit;
static struct timer_list periodic_rssi;
-u8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
+u8 multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
@@ -254,6 +256,7 @@ static u8 set_ip[2][4];
static u8 get_ip[2][4];
static u32 inactive_time;
static u8 del_beacon;
+static u32 clients_count;
static u8 *join_req;
u8 *info_element;
@@ -268,7 +271,6 @@ static struct host_if_drv *join_req_drv;
static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo);
-extern void chip_sleep_manually(u32 u32SleepTime);
extern int linux_wlan_get_num_conn_ifcs(void);
static int add_handler_in_list(struct host_if_drv *handler)
@@ -321,142 +323,136 @@ static struct host_if_drv *get_handler_from_id(int id)
return wfidrv_list[id];
}
-static s32 Handle_SetChannel(struct host_if_drv *hif_drv,
- struct channel_attr *pstrHostIFSetChan)
+static s32 handle_set_channel(struct host_if_drv *hif_drv,
+ struct channel_attr *hif_set_ch)
{
+ s32 result = 0;
+ struct wid wid;
- s32 s32Error = 0;
- struct wid strWID;
-
- strWID.id = (u16)WID_CURRENT_CHANNEL;
- strWID.type = WID_CHAR;
- strWID.val = (char *)&(pstrHostIFSetChan->set_ch);
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_CURRENT_CHANNEL;
+ wid.type = WID_CHAR;
+ wid.val = (char *)&hif_set_ch->set_ch;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Setting channel\n");
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+
+ if (result) {
PRINT_ER("Failed to set channel\n");
return -EINVAL;
}
- return s32Error;
+ return result;
}
-static s32 Handle_SetWfiDrvHandler(struct host_if_drv *hif_drv,
- struct drv_handler *pstrHostIfSetDrvHandler)
+static s32 handle_set_wfi_drv_handler(struct host_if_drv *hif_drv,
+ struct drv_handler *hif_drv_handler)
{
+ s32 result = 0;
+ struct wid wid;
- s32 s32Error = 0;
- struct wid strWID;
-
- strWID.id = (u16)WID_SET_DRV_HANDLER;
- strWID.type = WID_INT;
- strWID.val = (s8 *)&(pstrHostIfSetDrvHandler->u32Address);
- strWID.size = sizeof(u32);
+ wid.id = (u16)WID_SET_DRV_HANDLER;
+ wid.type = WID_INT;
+ wid.val = (s8 *)&hif_drv_handler->handler;
+ wid.size = sizeof(u32);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- pstrHostIfSetDrvHandler->u32Address);
+ result = send_config_pkt(SET_CFG, &wid, 1, hif_drv_handler->handler);
if (!hif_drv)
up(&hif_sema_driver);
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to set driver handler\n");
return -EINVAL;
}
- return s32Error;
+ return result;
}
-static s32 Handle_SetOperationMode(struct host_if_drv *hif_drv,
- struct op_mode *pstrHostIfSetOperationMode)
+static s32 handle_set_operation_mode(struct host_if_drv *hif_drv,
+ struct op_mode *hif_op_mode)
{
+ s32 result = 0;
+ struct wid wid;
- s32 s32Error = 0;
- struct wid strWID;
-
- strWID.id = (u16)WID_SET_OPERATION_MODE;
- strWID.type = WID_INT;
- strWID.val = (s8 *)&(pstrHostIfSetOperationMode->u32Mode);
- strWID.size = sizeof(u32);
-
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ wid.id = (u16)WID_SET_OPERATION_MODE;
+ wid.type = WID_INT;
+ wid.val = (s8 *)&hif_op_mode->mode;
+ wid.size = sizeof(u32);
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- if ((pstrHostIfSetOperationMode->u32Mode) == IDLE_MODE)
+ if ((hif_op_mode->mode) == IDLE_MODE)
up(&hif_sema_driver);
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to set driver handler\n");
return -EINVAL;
}
- return s32Error;
+ return result;
}
-s32 Handle_set_IPAddress(struct host_if_drv *hif_drv, u8 *pu8IPAddr, u8 idx)
+s32 handle_set_ip_address(struct host_if_drv *hif_drv, u8 *ip_addr, u8 idx)
{
+ s32 result = 0;
+ struct wid wid;
+ char firmware_ip_addr[4] = {0};
- s32 s32Error = 0;
- struct wid strWID;
- char firmwareIPAddress[4] = {0};
-
- if (pu8IPAddr[0] < 192)
- pu8IPAddr[0] = 0;
-
- PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %pI4\n", idx, pu8IPAddr);
+ if (ip_addr[0] < 192)
+ ip_addr[0] = 0;
- memcpy(set_ip[idx], pu8IPAddr, IP_ALEN);
+ PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %pI4\n",
+ idx, ip_addr);
- strWID.id = (u16)WID_IP_ADDRESS;
- strWID.type = WID_STR;
- strWID.val = (u8 *)pu8IPAddr;
- strWID.size = IP_ALEN;
+ memcpy(set_ip[idx], ip_addr, IP_ALEN);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ wid.id = (u16)WID_IP_ADDRESS;
+ wid.type = WID_STR;
+ wid.val = (u8 *)ip_addr;
+ wid.size = IP_ALEN;
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- host_int_get_ipaddress(hif_drv, firmwareIPAddress, idx);
+ host_int_get_ipaddress(hif_drv, firmware_ip_addr, idx);
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to set IP address\n");
return -EINVAL;
}
PRINT_INFO(HOSTINF_DBG, "IP address set\n");
- return s32Error;
+ return result;
}
-s32 Handle_get_IPAddress(struct host_if_drv *hif_drv, u8 *pu8IPAddr, u8 idx)
+s32 handle_get_ip_address(struct host_if_drv *hif_drv, u8 idx)
{
+ s32 result = 0;
+ struct wid wid;
- s32 s32Error = 0;
- struct wid strWID;
-
- strWID.id = (u16)WID_IP_ADDRESS;
- strWID.type = WID_STR;
- strWID.val = kmalloc(IP_ALEN, GFP_KERNEL);
- strWID.size = IP_ALEN;
+ wid.id = (u16)WID_IP_ADDRESS;
+ wid.type = WID_STR;
+ wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
+ wid.size = IP_ALEN;
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- PRINT_INFO(HOSTINF_DBG, "%pI4\n", strWID.val);
+ PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val);
- memcpy(get_ip[idx], strWID.val, IP_ALEN);
+ memcpy(get_ip[idx], wid.val, IP_ALEN);
- kfree(strWID.val);
+ kfree(wid.val);
if (memcmp(get_ip[idx], set_ip[idx], IP_ALEN) != 0)
host_int_setup_ipaddress(hif_drv, set_ip[idx], idx);
- if (s32Error != 0) {
+ if (result != 0) {
PRINT_ER("Failed to get IP address\n");
return -EINVAL;
}
@@ -465,357 +461,366 @@ s32 Handle_get_IPAddress(struct host_if_drv *hif_drv, u8 *pu8IPAddr, u8 idx)
PRINT_INFO(HOSTINF_DBG, "%pI4\n", get_ip[idx]);
PRINT_INFO(HOSTINF_DBG, "\n");
- return s32Error;
+ return result;
}
-static s32 Handle_SetMacAddress(struct host_if_drv *hif_drv,
- struct set_mac_addr *pstrHostIfSetMacAddress)
+static s32 handle_set_mac_address(struct host_if_drv *hif_drv,
+ struct set_mac_addr *set_mac_addr)
{
-
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *mac_buf = kmalloc(ETH_ALEN, GFP_KERNEL);
- if (mac_buf == NULL) {
+ if (!mac_buf) {
PRINT_ER("No buffer to send mac address\n");
return -EFAULT;
}
- memcpy(mac_buf, pstrHostIfSetMacAddress->u8MacAddress, ETH_ALEN);
+ memcpy(mac_buf, set_mac_addr->mac_addr, ETH_ALEN);
- strWID.id = (u16)WID_MAC_ADDR;
- strWID.type = WID_STR;
- strWID.val = mac_buf;
- strWID.size = ETH_ALEN;
- PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", strWID.val);
+ wid.id = (u16)WID_MAC_ADDR;
+ wid.type = WID_STR;
+ wid.val = mac_buf;
+ wid.size = ETH_ALEN;
+ PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result) {
PRINT_ER("Failed to set mac address\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
kfree(mac_buf);
- return s32Error;
+ return result;
}
-static s32 Handle_GetMacAddress(struct host_if_drv *hif_drv,
- struct get_mac_addr *pstrHostIfGetMacAddress)
+static s32 handle_get_mac_address(struct host_if_drv *hif_drv,
+ struct get_mac_addr *get_mac_addr)
{
+ s32 result = 0;
+ struct wid wid;
- s32 s32Error = 0;
- struct wid strWID;
+ wid.id = (u16)WID_MAC_ADDR;
+ wid.type = WID_STR;
+ wid.val = get_mac_addr->mac_addr;
+ wid.size = ETH_ALEN;
- strWID.id = (u16)WID_MAC_ADDR;
- strWID.type = WID_STR;
- strWID.val = pstrHostIfGetMacAddress->u8MacAddress;
- strWID.size = ETH_ALEN;
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to get mac address\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
up(&hif_sema_wait_response);
- return s32Error;
+ return result;
}
-static s32 Handle_CfgParam(struct host_if_drv *hif_drv,
- struct cfg_param_attr *strHostIFCfgParamAttr)
+static s32 handle_cfg_param(struct host_if_drv *hif_drv,
+ struct cfg_param_attr *cfg_param_attr)
{
- s32 s32Error = 0;
- struct wid strWIDList[32];
- u8 u8WidCnt = 0;
-
- down(&hif_drv->gtOsCfgValuesSem);
+ s32 result = 0;
+ struct wid wid_list[32];
+ u8 wid_cnt = 0;
+ down(&hif_drv->sem_cfg_values);
PRINT_D(HOSTINF_DBG, "Setting CFG params\n");
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & BSS_TYPE) {
- if (strHostIFCfgParamAttr->cfg_attr_info.bss_type < 6) {
- strWIDList[u8WidCnt].id = WID_BSS_TYPE;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.bss_type;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.bss_type = (u8)strHostIFCfgParamAttr->cfg_attr_info.bss_type;
+ if (cfg_param_attr->cfg_attr_info.flag & BSS_TYPE) {
+ if (cfg_param_attr->cfg_attr_info.bss_type < 6) {
+ wid_list[wid_cnt].id = WID_BSS_TYPE;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.bss_type;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.bss_type = (u8)cfg_param_attr->cfg_attr_info.bss_type;
} else {
PRINT_ER("check value 6 over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & AUTH_TYPE) {
- if ((strHostIFCfgParamAttr->cfg_attr_info.auth_type) == 1 || (strHostIFCfgParamAttr->cfg_attr_info.auth_type) == 2 || (strHostIFCfgParamAttr->cfg_attr_info.auth_type) == 5) {
- strWIDList[u8WidCnt].id = WID_AUTH_TYPE;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.auth_type;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.auth_type = (u8)strHostIFCfgParamAttr->cfg_attr_info.auth_type;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & AUTH_TYPE) {
+ if (cfg_param_attr->cfg_attr_info.auth_type == 1 ||
+ cfg_param_attr->cfg_attr_info.auth_type == 2 ||
+ cfg_param_attr->cfg_attr_info.auth_type == 5) {
+ wid_list[wid_cnt].id = WID_AUTH_TYPE;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.auth_type;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.auth_type = (u8)cfg_param_attr->cfg_attr_info.auth_type;
} else {
PRINT_ER("Impossible value \n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & AUTHEN_TIMEOUT) {
- if (strHostIFCfgParamAttr->cfg_attr_info.auth_timeout > 0 && strHostIFCfgParamAttr->cfg_attr_info.auth_timeout < 65536) {
- strWIDList[u8WidCnt].id = WID_AUTH_TIMEOUT;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.auth_timeout;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.auth_timeout = strHostIFCfgParamAttr->cfg_attr_info.auth_timeout;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & AUTHEN_TIMEOUT) {
+ if (cfg_param_attr->cfg_attr_info.auth_timeout > 0 &&
+ cfg_param_attr->cfg_attr_info.auth_timeout < 65536) {
+ wid_list[wid_cnt].id = WID_AUTH_TIMEOUT;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.auth_timeout;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.auth_timeout = cfg_param_attr->cfg_attr_info.auth_timeout;
} else {
PRINT_ER("Range(1 ~ 65535) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & POWER_MANAGEMENT) {
- if (strHostIFCfgParamAttr->cfg_attr_info.power_mgmt_mode < 5) {
- strWIDList[u8WidCnt].id = WID_POWER_MANAGEMENT;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.power_mgmt_mode;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.power_mgmt_mode = (u8)strHostIFCfgParamAttr->cfg_attr_info.power_mgmt_mode;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & POWER_MANAGEMENT) {
+ if (cfg_param_attr->cfg_attr_info.power_mgmt_mode < 5) {
+ wid_list[wid_cnt].id = WID_POWER_MANAGEMENT;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.power_mgmt_mode;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.power_mgmt_mode = (u8)cfg_param_attr->cfg_attr_info.power_mgmt_mode;
} else {
PRINT_ER("Invalide power mode\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & RETRY_SHORT) {
- if ((strHostIFCfgParamAttr->cfg_attr_info.short_retry_limit > 0) && (strHostIFCfgParamAttr->cfg_attr_info.short_retry_limit < 256)) {
- strWIDList[u8WidCnt].id = WID_SHORT_RETRY_LIMIT;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.short_retry_limit;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.short_retry_limit = strHostIFCfgParamAttr->cfg_attr_info.short_retry_limit;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & RETRY_SHORT) {
+ if (cfg_param_attr->cfg_attr_info.short_retry_limit > 0 &&
+ cfg_param_attr->cfg_attr_info.short_retry_limit < 256) {
+ wid_list[wid_cnt].id = WID_SHORT_RETRY_LIMIT;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.short_retry_limit;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.short_retry_limit = cfg_param_attr->cfg_attr_info.short_retry_limit;
} else {
PRINT_ER("Range(1~256) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & RETRY_LONG) {
- if ((strHostIFCfgParamAttr->cfg_attr_info.long_retry_limit > 0) && (strHostIFCfgParamAttr->cfg_attr_info.long_retry_limit < 256)) {
- strWIDList[u8WidCnt].id = WID_LONG_RETRY_LIMIT;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.long_retry_limit;
-
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.long_retry_limit = strHostIFCfgParamAttr->cfg_attr_info.long_retry_limit;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & RETRY_LONG) {
+ if (cfg_param_attr->cfg_attr_info.long_retry_limit > 0 &&
+ cfg_param_attr->cfg_attr_info.long_retry_limit < 256) {
+ wid_list[wid_cnt].id = WID_LONG_RETRY_LIMIT;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.long_retry_limit;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.long_retry_limit = cfg_param_attr->cfg_attr_info.long_retry_limit;
} else {
PRINT_ER("Range(1~256) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & FRAG_THRESHOLD) {
-
- if (strHostIFCfgParamAttr->cfg_attr_info.frag_threshold > 255 && strHostIFCfgParamAttr->cfg_attr_info.frag_threshold < 7937) {
- strWIDList[u8WidCnt].id = WID_FRAG_THRESHOLD;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.frag_threshold;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.frag_threshold = strHostIFCfgParamAttr->cfg_attr_info.frag_threshold;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & FRAG_THRESHOLD) {
+ if (cfg_param_attr->cfg_attr_info.frag_threshold > 255 &&
+ cfg_param_attr->cfg_attr_info.frag_threshold < 7937) {
+ wid_list[wid_cnt].id = WID_FRAG_THRESHOLD;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.frag_threshold;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.frag_threshold = cfg_param_attr->cfg_attr_info.frag_threshold;
} else {
PRINT_ER("Threshold Range fail\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & RTS_THRESHOLD) {
- if (strHostIFCfgParamAttr->cfg_attr_info.rts_threshold > 255 && strHostIFCfgParamAttr->cfg_attr_info.rts_threshold < 65536) {
- strWIDList[u8WidCnt].id = WID_RTS_THRESHOLD;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.rts_threshold;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.rts_threshold = strHostIFCfgParamAttr->cfg_attr_info.rts_threshold;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & RTS_THRESHOLD) {
+ if (cfg_param_attr->cfg_attr_info.rts_threshold > 255 &&
+ cfg_param_attr->cfg_attr_info.rts_threshold < 65536) {
+ wid_list[wid_cnt].id = WID_RTS_THRESHOLD;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.rts_threshold;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.rts_threshold = cfg_param_attr->cfg_attr_info.rts_threshold;
} else {
PRINT_ER("Threshold Range fail\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & PREAMBLE) {
- if (strHostIFCfgParamAttr->cfg_attr_info.preamble_type < 3) {
- strWIDList[u8WidCnt].id = WID_PREAMBLE;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.preamble_type;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.preamble_type = strHostIFCfgParamAttr->cfg_attr_info.preamble_type;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & PREAMBLE) {
+ if (cfg_param_attr->cfg_attr_info.preamble_type < 3) {
+ wid_list[wid_cnt].id = WID_PREAMBLE;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.preamble_type;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.preamble_type = cfg_param_attr->cfg_attr_info.preamble_type;
} else {
PRINT_ER("Preamle Range(0~2) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & SHORT_SLOT_ALLOWED) {
- if (strHostIFCfgParamAttr->cfg_attr_info.short_slot_allowed < 2) {
- strWIDList[u8WidCnt].id = WID_SHORT_SLOT_ALLOWED;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.short_slot_allowed;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.short_slot_allowed = (u8)strHostIFCfgParamAttr->cfg_attr_info.short_slot_allowed;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & SHORT_SLOT_ALLOWED) {
+ if (cfg_param_attr->cfg_attr_info.short_slot_allowed < 2) {
+ wid_list[wid_cnt].id = WID_SHORT_SLOT_ALLOWED;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.short_slot_allowed;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.short_slot_allowed = (u8)cfg_param_attr->cfg_attr_info.short_slot_allowed;
} else {
PRINT_ER("Short slot(2) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & TXOP_PROT_DISABLE) {
- if (strHostIFCfgParamAttr->cfg_attr_info.txop_prot_disabled < 2) {
- strWIDList[u8WidCnt].id = WID_11N_TXOP_PROT_DISABLE;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.txop_prot_disabled;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.txop_prot_disabled = (u8)strHostIFCfgParamAttr->cfg_attr_info.txop_prot_disabled;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & TXOP_PROT_DISABLE) {
+ if (cfg_param_attr->cfg_attr_info.txop_prot_disabled < 2) {
+ wid_list[wid_cnt].id = WID_11N_TXOP_PROT_DISABLE;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.txop_prot_disabled;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.txop_prot_disabled = (u8)cfg_param_attr->cfg_attr_info.txop_prot_disabled;
} else {
PRINT_ER("TXOP prot disable\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & BEACON_INTERVAL) {
- if (strHostIFCfgParamAttr->cfg_attr_info.beacon_interval > 0 && strHostIFCfgParamAttr->cfg_attr_info.beacon_interval < 65536) {
- strWIDList[u8WidCnt].id = WID_BEACON_INTERVAL;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.beacon_interval;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.beacon_interval = strHostIFCfgParamAttr->cfg_attr_info.beacon_interval;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & BEACON_INTERVAL) {
+ if (cfg_param_attr->cfg_attr_info.beacon_interval > 0 &&
+ cfg_param_attr->cfg_attr_info.beacon_interval < 65536) {
+ wid_list[wid_cnt].id = WID_BEACON_INTERVAL;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.beacon_interval;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.beacon_interval = cfg_param_attr->cfg_attr_info.beacon_interval;
} else {
PRINT_ER("Beacon interval(1~65535) fail\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & DTIM_PERIOD) {
- if (strHostIFCfgParamAttr->cfg_attr_info.dtim_period > 0 && strHostIFCfgParamAttr->cfg_attr_info.dtim_period < 256) {
- strWIDList[u8WidCnt].id = WID_DTIM_PERIOD;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.dtim_period;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.dtim_period = strHostIFCfgParamAttr->cfg_attr_info.dtim_period;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & DTIM_PERIOD) {
+ if (cfg_param_attr->cfg_attr_info.dtim_period > 0 &&
+ cfg_param_attr->cfg_attr_info.dtim_period < 256) {
+ wid_list[wid_cnt].id = WID_DTIM_PERIOD;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.dtim_period;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.dtim_period = cfg_param_attr->cfg_attr_info.dtim_period;
} else {
PRINT_ER("DTIM range(1~255) fail\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & SITE_SURVEY) {
- if (strHostIFCfgParamAttr->cfg_attr_info.site_survey_enabled < 3) {
- strWIDList[u8WidCnt].id = WID_SITE_SURVEY;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.site_survey_enabled;
- strWIDList[u8WidCnt].type = WID_CHAR;
- strWIDList[u8WidCnt].size = sizeof(char);
- hif_drv->strCfgValues.site_survey_enabled = (u8)strHostIFCfgParamAttr->cfg_attr_info.site_survey_enabled;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & SITE_SURVEY) {
+ if (cfg_param_attr->cfg_attr_info.site_survey_enabled < 3) {
+ wid_list[wid_cnt].id = WID_SITE_SURVEY;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.site_survey_enabled;
+ wid_list[wid_cnt].type = WID_CHAR;
+ wid_list[wid_cnt].size = sizeof(char);
+ hif_drv->cfg_values.site_survey_enabled = (u8)cfg_param_attr->cfg_attr_info.site_survey_enabled;
} else {
PRINT_ER("Site survey disable\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & SITE_SURVEY_SCAN_TIME) {
- if (strHostIFCfgParamAttr->cfg_attr_info.site_survey_scan_time > 0 && strHostIFCfgParamAttr->cfg_attr_info.site_survey_scan_time < 65536) {
- strWIDList[u8WidCnt].id = WID_SITE_SURVEY_SCAN_TIME;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.site_survey_scan_time;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.site_survey_scan_time = strHostIFCfgParamAttr->cfg_attr_info.site_survey_scan_time;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & SITE_SURVEY_SCAN_TIME) {
+ if (cfg_param_attr->cfg_attr_info.site_survey_scan_time > 0 &&
+ cfg_param_attr->cfg_attr_info.site_survey_scan_time < 65536) {
+ wid_list[wid_cnt].id = WID_SITE_SURVEY_SCAN_TIME;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.site_survey_scan_time;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.site_survey_scan_time = cfg_param_attr->cfg_attr_info.site_survey_scan_time;
} else {
PRINT_ER("Site survey scan time(1~65535) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & ACTIVE_SCANTIME) {
- if (strHostIFCfgParamAttr->cfg_attr_info.active_scan_time > 0 && strHostIFCfgParamAttr->cfg_attr_info.active_scan_time < 65536) {
- strWIDList[u8WidCnt].id = WID_ACTIVE_SCAN_TIME;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.active_scan_time;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.active_scan_time = strHostIFCfgParamAttr->cfg_attr_info.active_scan_time;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & ACTIVE_SCANTIME) {
+ if (cfg_param_attr->cfg_attr_info.active_scan_time > 0 &&
+ cfg_param_attr->cfg_attr_info.active_scan_time < 65536) {
+ wid_list[wid_cnt].id = WID_ACTIVE_SCAN_TIME;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.active_scan_time;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.active_scan_time = cfg_param_attr->cfg_attr_info.active_scan_time;
} else {
PRINT_ER("Active scan time(1~65535) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
- }
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & PASSIVE_SCANTIME) {
- if (strHostIFCfgParamAttr->cfg_attr_info.passive_scan_time > 0 && strHostIFCfgParamAttr->cfg_attr_info.passive_scan_time < 65536) {
- strWIDList[u8WidCnt].id = WID_PASSIVE_SCAN_TIME;
- strWIDList[u8WidCnt].val = (s8 *)&strHostIFCfgParamAttr->cfg_attr_info.passive_scan_time;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.passive_scan_time = strHostIFCfgParamAttr->cfg_attr_info.passive_scan_time;
+ wid_cnt++;
+ }
+ if (cfg_param_attr->cfg_attr_info.flag & PASSIVE_SCANTIME) {
+ if (cfg_param_attr->cfg_attr_info.passive_scan_time > 0 &&
+ cfg_param_attr->cfg_attr_info.passive_scan_time < 65536) {
+ wid_list[wid_cnt].id = WID_PASSIVE_SCAN_TIME;
+ wid_list[wid_cnt].val = (s8 *)&cfg_param_attr->cfg_attr_info.passive_scan_time;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.passive_scan_time = cfg_param_attr->cfg_attr_info.passive_scan_time;
} else {
PRINT_ER("Passive scan time(1~65535) over\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
+ wid_cnt++;
}
- if (strHostIFCfgParamAttr->cfg_attr_info.flag & CURRENT_TX_RATE) {
- enum CURRENT_TXRATE curr_tx_rate = strHostIFCfgParamAttr->cfg_attr_info.curr_tx_rate;
+ if (cfg_param_attr->cfg_attr_info.flag & CURRENT_TX_RATE) {
+ enum CURRENT_TXRATE curr_tx_rate = cfg_param_attr->cfg_attr_info.curr_tx_rate;
+
if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1
|| curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5
|| curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6
|| curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12
|| curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24
|| curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 || curr_tx_rate == MBPS_54) {
- strWIDList[u8WidCnt].id = WID_CURRENT_TX_RATE;
- strWIDList[u8WidCnt].val = (s8 *)&curr_tx_rate;
- strWIDList[u8WidCnt].type = WID_SHORT;
- strWIDList[u8WidCnt].size = sizeof(u16);
- hif_drv->strCfgValues.curr_tx_rate = (u8)curr_tx_rate;
+ wid_list[wid_cnt].id = WID_CURRENT_TX_RATE;
+ wid_list[wid_cnt].val = (s8 *)&curr_tx_rate;
+ wid_list[wid_cnt].type = WID_SHORT;
+ wid_list[wid_cnt].size = sizeof(u16);
+ hif_drv->cfg_values.curr_tx_rate = (u8)curr_tx_rate;
} else {
PRINT_ER("out of TX rate\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto ERRORHANDLER;
}
- u8WidCnt++;
+ wid_cnt++;
}
- s32Error = send_config_pkt(SET_CFG, strWIDList, u8WidCnt,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, wid_list, wid_cnt,
+ get_id_from_handler(hif_drv));
+
+ if (result)
PRINT_ER("Error in setting CFG params\n");
ERRORHANDLER:
- up(&hif_drv->gtOsCfgValuesSem);
- return s32Error;
+ up(&hif_drv->sem_cfg_values);
+ return result;
}
-static s32 Handle_wait_msg_q_empty(void)
+static void Handle_wait_msg_q_empty(void)
{
g_wilc_initialized = 0;
up(&hif_sema_wait_response);
- return 0;
}
static s32 Handle_Scan(struct host_if_drv *hif_drv,
struct scan_attr *pstrHostIFscanAttr)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct wid strWIDList[5];
u32 u32WidsCount = 0;
u32 i;
@@ -824,29 +829,30 @@ static s32 Handle_Scan(struct host_if_drv *hif_drv,
u8 *pu8HdnNtwrksWidVal = NULL;
PRINT_D(HOSTINF_DBG, "Setting SCAN params\n");
- PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", hif_drv->enuHostIFstate);
+ PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", hif_drv->hif_state);
- hif_drv->strWILC_UsrScanReq.pfUserScanResult = pstrHostIFscanAttr->result;
- hif_drv->strWILC_UsrScanReq.u32UserScanPvoid = pstrHostIFscanAttr->arg;
+ hif_drv->usr_scan_req.scan_result = pstrHostIFscanAttr->result;
+ hif_drv->usr_scan_req.arg = pstrHostIFscanAttr->arg;
- if ((hif_drv->enuHostIFstate >= HOST_IF_SCANNING) && (hif_drv->enuHostIFstate < HOST_IF_CONNECTED)) {
- PRINT_D(GENERIC_DBG, "Don't scan we are already in [%d] state\n", hif_drv->enuHostIFstate);
+ if ((hif_drv->hif_state >= HOST_IF_SCANNING) &&
+ (hif_drv->hif_state < HOST_IF_CONNECTED)) {
+ PRINT_D(GENERIC_DBG, "Don't scan already in [%d] state\n",
+ hif_drv->hif_state);
PRINT_ER("Already scan\n");
- s32Error = -EBUSY;
+ result = -EBUSY;
goto ERRORHANDLER;
}
if (g_obtainingIP || connecting) {
PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n");
PRINT_ER("Don't do obss scan\n");
- s32Error = -EBUSY;
+ result = -EBUSY;
goto ERRORHANDLER;
}
PRINT_D(HOSTINF_DBG, "Setting SCAN params\n");
-
- hif_drv->strWILC_UsrScanReq.u32RcvdChCount = 0;
+ hif_drv->usr_scan_req.rcvd_ch_cnt = 0;
strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ;
strWIDList[u32WidsCount].type = WID_STR;
@@ -855,7 +861,7 @@ static s32 Handle_Scan(struct host_if_drv *hif_drv,
valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen) + 1);
pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL);
strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal;
- if (strWIDList[u32WidsCount].val != NULL) {
+ if (strWIDList[u32WidsCount].val) {
pu8Buffer = strWIDList[u32WidsCount].val;
*pu8Buffer++ = pstrHostIFscanAttr->hidden_network.u8ssidnum;
@@ -868,8 +874,6 @@ static s32 Handle_Scan(struct host_if_drv *hif_drv,
pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen;
}
-
-
strWIDList[u32WidsCount].size = (s32)(valuesize + 1);
u32WidsCount++;
}
@@ -885,13 +889,14 @@ static s32 Handle_Scan(struct host_if_drv *hif_drv,
strWIDList[u32WidsCount].id = WID_SCAN_TYPE;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrHostIFscanAttr->type));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrHostIFscanAttr->type;
u32WidsCount++;
strWIDList[u32WidsCount].id = WID_SCAN_CHANNEL_LIST;
strWIDList[u32WidsCount].type = WID_BIN_DATA;
- if (pstrHostIFscanAttr->ch_freq_list != NULL && pstrHostIFscanAttr->ch_list_len > 0) {
+ if (pstrHostIFscanAttr->ch_freq_list &&
+ pstrHostIFscanAttr->ch_list_len > 0) {
int i;
for (i = 0; i < pstrHostIFscanAttr->ch_list_len; i++) {
@@ -907,25 +912,25 @@ static s32 Handle_Scan(struct host_if_drv *hif_drv,
strWIDList[u32WidsCount].id = WID_START_SCAN_REQ;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrHostIFscanAttr->src));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrHostIFscanAttr->src;
u32WidsCount++;
- if (hif_drv->enuHostIFstate == HOST_IF_CONNECTED)
+ if (hif_drv->hif_state == HOST_IF_CONNECTED)
scan_while_connected = true;
- else if (hif_drv->enuHostIFstate == HOST_IF_IDLE)
+ else if (hif_drv->hif_state == HOST_IF_IDLE)
scan_while_connected = false;
- s32Error = send_config_pkt(SET_CFG, strWIDList, u32WidsCount,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, strWIDList, u32WidsCount,
+ get_id_from_handler(hif_drv));
- if (s32Error)
+ if (result)
PRINT_ER("Failed to send scan paramters config packet\n");
else
PRINT_D(HOSTINF_DBG, "Successfully sent SCAN params config packet\n");
ERRORHANDLER:
- if (s32Error) {
- del_timer(&hif_drv->hScanTimer);
+ if (result) {
+ del_timer(&hif_drv->scan_timer);
Handle_ScanDone(hif_drv, SCAN_EVENT_ABORTED);
}
@@ -939,54 +944,54 @@ ERRORHANDLER:
kfree(pu8HdnNtwrksWidVal);
- return s32Error;
+ return result;
}
static s32 Handle_ScanDone(struct host_if_drv *hif_drv,
enum scan_event enuEvent)
{
- s32 s32Error = 0;
+ s32 result = 0;
u8 u8abort_running_scan;
- struct wid strWID;
-
+ struct wid wid;
PRINT_D(HOSTINF_DBG, "in Handle_ScanDone()\n");
if (enuEvent == SCAN_EVENT_ABORTED) {
PRINT_D(GENERIC_DBG, "Abort running scan\n");
u8abort_running_scan = 1;
- strWID.id = (u16)WID_ABORT_RUNNING_SCAN;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)&u8abort_running_scan;
- strWID.size = sizeof(char);
-
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ wid.id = (u16)WID_ABORT_RUNNING_SCAN;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&u8abort_running_scan;
+ wid.size = sizeof(char);
+
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+
+ if (result) {
PRINT_ER("Failed to set abort running scan\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
}
if (!hif_drv) {
PRINT_ER("Driver handler is NULL\n");
- return s32Error;
+ return result;
}
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
- hif_drv->strWILC_UsrScanReq.pfUserScanResult(enuEvent, NULL,
- hif_drv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
- hif_drv->strWILC_UsrScanReq.pfUserScanResult = NULL;
+ if (hif_drv->usr_scan_req.scan_result) {
+ hif_drv->usr_scan_req.scan_result(enuEvent, NULL,
+ hif_drv->usr_scan_req.arg, NULL);
+ hif_drv->usr_scan_req.scan_result = NULL;
}
- return s32Error;
+ return result;
}
u8 u8ConnectedSSID[6] = {0};
static s32 Handle_Connect(struct host_if_drv *hif_drv,
struct connect_attr *pstrHostIFconnectAttr)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct wid strWIDList[8];
u32 u32WidsCount = 0, dummyval = 0;
u8 *pu8CurrByte = NULL;
@@ -995,45 +1000,46 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
PRINT_D(GENERIC_DBG, "Handling connect request\n");
if (memcmp(pstrHostIFconnectAttr->bssid, u8ConnectedSSID, ETH_ALEN) == 0) {
-
- s32Error = 0;
+ result = 0;
PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n");
- return s32Error;
+ return result;
}
PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n");
ptstrJoinBssParam = (struct join_bss_param *)pstrHostIFconnectAttr->params;
- if (ptstrJoinBssParam == NULL) {
+ if (!ptstrJoinBssParam) {
PRINT_ER("Required BSSID not found\n");
- s32Error = -ENOENT;
+ result = -ENOENT;
goto ERRORHANDLER;
}
- if (pstrHostIFconnectAttr->bssid != NULL) {
- hif_drv->strWILC_UsrConnReq.pu8bssid = kmalloc(6, GFP_KERNEL);
- memcpy(hif_drv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->bssid, 6);
+ if (pstrHostIFconnectAttr->bssid) {
+ hif_drv->usr_conn_req.pu8bssid = kmalloc(6, GFP_KERNEL);
+ memcpy(hif_drv->usr_conn_req.pu8bssid, pstrHostIFconnectAttr->bssid, 6);
}
- hif_drv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssid_len;
- if (pstrHostIFconnectAttr->ssid != NULL) {
- hif_drv->strWILC_UsrConnReq.pu8ssid = kmalloc(pstrHostIFconnectAttr->ssid_len + 1, GFP_KERNEL);
- memcpy(hif_drv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->ssid,
- pstrHostIFconnectAttr->ssid_len);
- hif_drv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssid_len] = '\0';
+ hif_drv->usr_conn_req.ssid_len = pstrHostIFconnectAttr->ssid_len;
+ if (pstrHostIFconnectAttr->ssid) {
+ hif_drv->usr_conn_req.pu8ssid = kmalloc(pstrHostIFconnectAttr->ssid_len + 1, GFP_KERNEL);
+ memcpy(hif_drv->usr_conn_req.pu8ssid,
+ pstrHostIFconnectAttr->ssid,
+ pstrHostIFconnectAttr->ssid_len);
+ hif_drv->usr_conn_req.pu8ssid[pstrHostIFconnectAttr->ssid_len] = '\0';
}
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->ies_len;
- if (pstrHostIFconnectAttr->ies != NULL) {
- hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs = kmalloc(pstrHostIFconnectAttr->ies_len, GFP_KERNEL);
- memcpy(hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->ies,
- pstrHostIFconnectAttr->ies_len);
+ hif_drv->usr_conn_req.ies_len = pstrHostIFconnectAttr->ies_len;
+ if (pstrHostIFconnectAttr->ies) {
+ hif_drv->usr_conn_req.ies = kmalloc(pstrHostIFconnectAttr->ies_len, GFP_KERNEL);
+ memcpy(hif_drv->usr_conn_req.ies,
+ pstrHostIFconnectAttr->ies,
+ pstrHostIFconnectAttr->ies_len);
}
- hif_drv->strWILC_UsrConnReq.u8security = pstrHostIFconnectAttr->security;
- hif_drv->strWILC_UsrConnReq.tenuAuth_type = pstrHostIFconnectAttr->auth_type;
- hif_drv->strWILC_UsrConnReq.pfUserConnectResult = pstrHostIFconnectAttr->result;
- hif_drv->strWILC_UsrConnReq.u32UserConnectPvoid = pstrHostIFconnectAttr->arg;
+ hif_drv->usr_conn_req.u8security = pstrHostIFconnectAttr->security;
+ hif_drv->usr_conn_req.auth_type = pstrHostIFconnectAttr->auth_type;
+ hif_drv->usr_conn_req.conn_result = pstrHostIFconnectAttr->result;
+ hif_drv->usr_conn_req.arg = pstrHostIFconnectAttr->arg;
strWIDList[u32WidsCount].id = WID_SUCCESS_FRAME_COUNT;
strWIDList[u32WidsCount].type = WID_INT;
@@ -1056,41 +1062,41 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
{
strWIDList[u32WidsCount].id = WID_INFO_ELEMENT_ASSOCIATE;
strWIDList[u32WidsCount].type = WID_BIN_DATA;
- strWIDList[u32WidsCount].val = hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs;
- strWIDList[u32WidsCount].size = hif_drv->strWILC_UsrConnReq.ConnReqIEsLen;
+ strWIDList[u32WidsCount].val = hif_drv->usr_conn_req.ies;
+ strWIDList[u32WidsCount].size = hif_drv->usr_conn_req.ies_len;
u32WidsCount++;
if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) {
- info_element_size = hif_drv->strWILC_UsrConnReq.ConnReqIEsLen;
+ info_element_size = hif_drv->usr_conn_req.ies_len;
info_element = kmalloc(info_element_size, GFP_KERNEL);
- memcpy(info_element, hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs,
+ memcpy(info_element, hif_drv->usr_conn_req.ies,
info_element_size);
}
}
strWIDList[u32WidsCount].id = (u16)WID_11I_MODE;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
- strWIDList[u32WidsCount].val = (s8 *)(&(hif_drv->strWILC_UsrConnReq.u8security));
+ strWIDList[u32WidsCount].val = (s8 *)&hif_drv->usr_conn_req.u8security;
u32WidsCount++;
if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7))
- mode_11i = hif_drv->strWILC_UsrConnReq.u8security;
-
- PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", hif_drv->strWILC_UsrConnReq.u8security);
+ mode_11i = hif_drv->usr_conn_req.u8security;
+ PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", hif_drv->usr_conn_req.u8security);
strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
- strWIDList[u32WidsCount].val = (s8 *)(&hif_drv->strWILC_UsrConnReq.tenuAuth_type);
+ strWIDList[u32WidsCount].val = (s8 *)&hif_drv->usr_conn_req.auth_type;
u32WidsCount++;
if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7))
- auth_type = (u8)hif_drv->strWILC_UsrConnReq.tenuAuth_type;
+ auth_type = (u8)hif_drv->usr_conn_req.auth_type;
- PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", hif_drv->strWILC_UsrConnReq.tenuAuth_type);
+ PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n",
+ hif_drv->usr_conn_req.auth_type);
PRINT_D(HOSTINF_DBG, "Connecting to network of SSID %s on channel %d\n",
- hif_drv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->ch);
+ hif_drv->usr_conn_req.pu8ssid, pstrHostIFconnectAttr->ch);
strWIDList[u32WidsCount].id = (u16)WID_JOIN_REQ_EXTENDED;
strWIDList[u32WidsCount].type = WID_STR;
@@ -1101,15 +1107,14 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
join_req_size = strWIDList[u32WidsCount].size;
join_req = kmalloc(join_req_size, GFP_KERNEL);
}
- if (strWIDList[u32WidsCount].val == NULL) {
- s32Error = -EFAULT;
+ if (!strWIDList[u32WidsCount].val) {
+ result = -EFAULT;
goto ERRORHANDLER;
}
pu8CurrByte = strWIDList[u32WidsCount].val;
-
- if (pstrHostIFconnectAttr->ssid != NULL) {
+ if (pstrHostIFconnectAttr->ssid) {
memcpy(pu8CurrByte, pstrHostIFconnectAttr->ssid, pstrHostIFconnectAttr->ssid_len);
pu8CurrByte[pstrHostIFconnectAttr->ssid_len] = '\0';
}
@@ -1126,7 +1131,11 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
*(pu8CurrByte++) = ((ptstrJoinBssParam->cap_info) >> 8) & 0xFF;
PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8)));
- if (pstrHostIFconnectAttr->bssid != NULL)
+ if (pstrHostIFconnectAttr->bssid)
+ memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6);
+ pu8CurrByte += 6;
+
+ if (pstrHostIFconnectAttr->bssid)
memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6);
pu8CurrByte += 6;
@@ -1144,7 +1153,7 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
*(pu8CurrByte++) = ptstrJoinBssParam->uapsd_cap;
*(pu8CurrByte++) = ptstrJoinBssParam->ht_capable;
- hif_drv->strWILC_UsrConnReq.IsHTCapable = ptstrJoinBssParam->ht_capable;
+ hif_drv->usr_conn_req.ht_capable = ptstrJoinBssParam->ht_capable;
*(pu8CurrByte++) = ptstrJoinBssParam->rsn_found;
PRINT_D(HOSTINF_DBG, "* rsn found %d*\n", *(pu8CurrByte - 1));
@@ -1187,10 +1196,8 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
memcpy(pu8CurrByte, ptstrJoinBssParam->interval, sizeof(ptstrJoinBssParam->interval));
pu8CurrByte += sizeof(ptstrJoinBssParam->interval);
- memcpy(pu8CurrByte, ptstrJoinBssParam->au8StartTime, sizeof(ptstrJoinBssParam->au8StartTime));
-
- pu8CurrByte += sizeof(ptstrJoinBssParam->au8StartTime);
-
+ memcpy(pu8CurrByte, ptstrJoinBssParam->start_time, sizeof(ptstrJoinBssParam->start_time));
+ pu8CurrByte += sizeof(ptstrJoinBssParam->start_time);
} else
PRINT_D(HOSTINF_DBG, "NOA not present\n");
@@ -1204,44 +1211,44 @@ static s32 Handle_Connect(struct host_if_drv *hif_drv,
PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n");
- if (pstrHostIFconnectAttr->bssid != NULL) {
+ if (pstrHostIFconnectAttr->bssid) {
memcpy(u8ConnectedSSID, pstrHostIFconnectAttr->bssid, ETH_ALEN);
PRINT_D(GENERIC_DBG, "save Bssid = %pM\n", pstrHostIFconnectAttr->bssid);
PRINT_D(GENERIC_DBG, "save bssid = %pM\n", u8ConnectedSSID);
}
- s32Error = send_config_pkt(SET_CFG, strWIDList, u32WidsCount,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(SET_CFG, strWIDList, u32WidsCount,
+ get_id_from_handler(hif_drv));
+ if (result) {
PRINT_ER("failed to send config packet\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
goto ERRORHANDLER;
} else {
PRINT_D(GENERIC_DBG, "set HOST_IF_WAITING_CONN_RESP\n");
- hif_drv->enuHostIFstate = HOST_IF_WAITING_CONN_RESP;
+ hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
}
ERRORHANDLER:
- if (s32Error) {
+ if (result) {
tstrConnectInfo strConnectInfo;
- del_timer(&hif_drv->hConnectTimer);
+ del_timer(&hif_drv->connect_timer);
PRINT_D(HOSTINF_DBG, "could not start connecting to the required network\n");
memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
- if (pstrHostIFconnectAttr->result != NULL) {
- if (pstrHostIFconnectAttr->bssid != NULL)
+ if (pstrHostIFconnectAttr->result) {
+ if (pstrHostIFconnectAttr->bssid)
memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->bssid, 6);
- if (pstrHostIFconnectAttr->ies != NULL) {
+ if (pstrHostIFconnectAttr->ies) {
strConnectInfo.ReqIEsLen = pstrHostIFconnectAttr->ies_len;
strConnectInfo.pu8ReqIEs = kmalloc(pstrHostIFconnectAttr->ies_len, GFP_KERNEL);
memcpy(strConnectInfo.pu8ReqIEs,
- pstrHostIFconnectAttr->ies,
- pstrHostIFconnectAttr->ies_len);
+ pstrHostIFconnectAttr->ies,
+ pstrHostIFconnectAttr->ies_len);
}
pstrHostIFconnectAttr->result(CONN_DISCONN_EVENT_CONN_RESP,
@@ -1249,7 +1256,7 @@ ERRORHANDLER:
MAC_DISCONNECTED,
NULL,
pstrHostIFconnectAttr->arg);
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
+ hif_drv->hif_state = HOST_IF_IDLE;
kfree(strConnectInfo.pu8ReqIEs);
strConnectInfo.pu8ReqIEs = NULL;
@@ -1269,12 +1276,12 @@ ERRORHANDLER:
pstrHostIFconnectAttr->ies = NULL;
kfree(pu8CurrByte);
- return s32Error;
+ return result;
}
static s32 Handle_FlushConnect(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct wid strWIDList[5];
u32 u32WidsCount = 0;
u8 *pu8CurrByte = NULL;
@@ -1291,8 +1298,6 @@ static s32 Handle_FlushConnect(struct host_if_drv *hif_drv)
strWIDList[u32WidsCount].val = (s8 *)(&(mode_11i));
u32WidsCount++;
-
-
strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
@@ -1310,53 +1315,53 @@ static s32 Handle_FlushConnect(struct host_if_drv *hif_drv)
u32WidsCount++;
- s32Error = send_config_pkt(SET_CFG, strWIDList, u32WidsCount,
- get_id_from_handler(join_req_drv));
- if (s32Error) {
+ result = send_config_pkt(SET_CFG, strWIDList, u32WidsCount,
+ get_id_from_handler(join_req_drv));
+ if (result) {
PRINT_ER("failed to send config packet\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
}
- return s32Error;
+ return result;
}
static s32 Handle_ConnectTimeout(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
+ s32 result = 0;
tstrConnectInfo strConnectInfo;
- struct wid strWID;
+ struct wid wid;
u16 u16DummyReasonCode = 0;
if (!hif_drv) {
PRINT_ER("Driver handler is NULL\n");
- return s32Error;
+ return result;
}
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
+ hif_drv->hif_state = HOST_IF_IDLE;
scan_while_connected = false;
memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
- if (hif_drv->strWILC_UsrConnReq.pfUserConnectResult != NULL) {
- if (hif_drv->strWILC_UsrConnReq.pu8bssid != NULL) {
+ if (hif_drv->usr_conn_req.conn_result) {
+ if (hif_drv->usr_conn_req.pu8bssid) {
memcpy(strConnectInfo.au8bssid,
- hif_drv->strWILC_UsrConnReq.pu8bssid, 6);
+ hif_drv->usr_conn_req.pu8bssid, 6);
}
- if (hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
- strConnectInfo.ReqIEsLen = hif_drv->strWILC_UsrConnReq.ConnReqIEsLen;
- strConnectInfo.pu8ReqIEs = kmalloc(hif_drv->strWILC_UsrConnReq.ConnReqIEsLen, GFP_KERNEL);
+ if (hif_drv->usr_conn_req.ies) {
+ strConnectInfo.ReqIEsLen = hif_drv->usr_conn_req.ies_len;
+ strConnectInfo.pu8ReqIEs = kmalloc(hif_drv->usr_conn_req.ies_len, GFP_KERNEL);
memcpy(strConnectInfo.pu8ReqIEs,
- hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs,
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen);
+ hif_drv->usr_conn_req.ies,
+ hif_drv->usr_conn_req.ies_len);
}
- hif_drv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_CONN_RESP,
- &strConnectInfo,
- MAC_DISCONNECTED,
- NULL,
- hif_drv->strWILC_UsrConnReq.u32UserConnectPvoid);
+ hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
+ &strConnectInfo,
+ MAC_DISCONNECTED,
+ NULL,
+ hif_drv->usr_conn_req.arg);
kfree(strConnectInfo.pu8ReqIEs);
strConnectInfo.pu8ReqIEs = NULL;
@@ -1364,37 +1369,37 @@ static s32 Handle_ConnectTimeout(struct host_if_drv *hif_drv)
PRINT_ER("Connect callback function pointer is NULL\n");
}
- strWID.id = (u16)WID_DISCONNECT;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)&u16DummyReasonCode;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_DISCONNECT;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&u16DummyReasonCode;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send dissconect config packet\n");
- hif_drv->strWILC_UsrConnReq.ssidLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ssid);
- kfree(hif_drv->strWILC_UsrConnReq.pu8bssid);
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ hif_drv->usr_conn_req.ssid_len = 0;
+ kfree(hif_drv->usr_conn_req.pu8ssid);
+ kfree(hif_drv->usr_conn_req.pu8bssid);
+ hif_drv->usr_conn_req.ies_len = 0;
+ kfree(hif_drv->usr_conn_req.ies);
eth_zero_addr(u8ConnectedSSID);
- if (join_req != NULL && join_req_drv == hif_drv) {
+ if (join_req && join_req_drv == hif_drv) {
kfree(join_req);
join_req = NULL;
}
- if (info_element != NULL && join_req_drv == hif_drv) {
+ if (info_element && join_req_drv == hif_drv) {
kfree(info_element);
info_element = NULL;
}
- return s32Error;
+ return result;
}
static s32 Handle_RcvdNtwrkInfo(struct host_if_drv *hif_drv,
@@ -1402,37 +1407,33 @@ static s32 Handle_RcvdNtwrkInfo(struct host_if_drv *hif_drv,
{
u32 i;
bool bNewNtwrkFound;
-
-
-
- s32 s32Error = 0;
+ s32 result = 0;
tstrNetworkInfo *pstrNetworkInfo = NULL;
void *pJoinParams = NULL;
bNewNtwrkFound = true;
PRINT_INFO(HOSTINF_DBG, "Handling received network info\n");
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
+ if (hif_drv->usr_scan_req.scan_result) {
PRINT_D(HOSTINF_DBG, "State: Scanning, parsing network information received\n");
parse_network_info(pstrRcvdNetworkInfo->buffer, &pstrNetworkInfo);
- if ((pstrNetworkInfo == NULL)
- || (hif_drv->strWILC_UsrScanReq.pfUserScanResult == NULL)) {
+ if ((!pstrNetworkInfo) ||
+ (!hif_drv->usr_scan_req.scan_result)) {
PRINT_ER("driver is null\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
goto done;
}
- for (i = 0; i < hif_drv->strWILC_UsrScanReq.u32RcvdChCount; i++) {
-
- if ((hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid != NULL) &&
- (pstrNetworkInfo->au8bssid != NULL)) {
- if (memcmp(hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid,
- pstrNetworkInfo->au8bssid, 6) == 0) {
- if (pstrNetworkInfo->s8rssi <= hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi) {
+ for (i = 0; i < hif_drv->usr_scan_req.rcvd_ch_cnt; i++) {
+ if ((hif_drv->usr_scan_req.net_info[i].au8bssid) &&
+ (pstrNetworkInfo->au8bssid)) {
+ if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid,
+ pstrNetworkInfo->au8bssid, 6) == 0) {
+ if (pstrNetworkInfo->s8rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) {
PRINT_D(HOSTINF_DBG, "Network previously discovered\n");
goto done;
} else {
- hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi = pstrNetworkInfo->s8rssi;
+ hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->s8rssi;
bNewNtwrkFound = false;
break;
}
@@ -1440,35 +1441,33 @@ static s32 Handle_RcvdNtwrkInfo(struct host_if_drv *hif_drv,
}
}
- if (bNewNtwrkFound == true) {
+ if (bNewNtwrkFound) {
PRINT_D(HOSTINF_DBG, "New network found\n");
- if (hif_drv->strWILC_UsrScanReq.u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
- hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[hif_drv->strWILC_UsrScanReq.u32RcvdChCount].s8rssi = pstrNetworkInfo->s8rssi;
+ if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
+ hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->s8rssi;
- if ((hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[hif_drv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid != NULL)
- && (pstrNetworkInfo->au8bssid != NULL)) {
- memcpy(hif_drv->strWILC_UsrScanReq.astrFoundNetworkInfo[hif_drv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid,
- pstrNetworkInfo->au8bssid, 6);
+ if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid &&
+ pstrNetworkInfo->au8bssid) {
+ memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid,
+ pstrNetworkInfo->au8bssid, 6);
- hif_drv->strWILC_UsrScanReq.u32RcvdChCount++;
+ hif_drv->usr_scan_req.rcvd_ch_cnt++;
pstrNetworkInfo->bNewNetwork = true;
pJoinParams = host_int_ParseJoinBssParam(pstrNetworkInfo);
- hif_drv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
- hif_drv->strWILC_UsrScanReq.u32UserScanPvoid,
- pJoinParams);
-
-
+ hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
+ hif_drv->usr_scan_req.arg,
+ pJoinParams);
}
} else {
PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit\n");
}
} else {
pstrNetworkInfo->bNewNetwork = false;
- hif_drv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
- hif_drv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
+ hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
+ hif_drv->usr_scan_req.arg, NULL);
}
}
@@ -1476,18 +1475,18 @@ done:
kfree(pstrRcvdNetworkInfo->buffer);
pstrRcvdNetworkInfo->buffer = NULL;
- if (pstrNetworkInfo != NULL) {
+ if (pstrNetworkInfo) {
DeallocateNetworkInfo(pstrNetworkInfo);
pstrNetworkInfo = NULL;
}
- return s32Error;
+ return result;
}
static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
struct rcvd_async_info *pstrRcvdGnrlAsyncInfo)
{
- s32 s32Error = 0;
+ s32 result = 0;
u8 u8MsgType = 0;
u8 u8MsgID = 0;
u16 u16MsgLen = 0;
@@ -1504,14 +1503,14 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
PRINT_ER("Driver handler is NULL\n");
return -ENODEV;
}
- PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n", hif_drv->enuHostIFstate,
- pstrRcvdGnrlAsyncInfo->buffer[7]);
+ PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n",
+ hif_drv->hif_state, pstrRcvdGnrlAsyncInfo->buffer[7]);
- if ((hif_drv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) ||
- (hif_drv->enuHostIFstate == HOST_IF_CONNECTED) ||
- hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
- if ((pstrRcvdGnrlAsyncInfo->buffer == NULL) ||
- (hif_drv->strWILC_UsrConnReq.pfUserConnectResult == NULL)) {
+ 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 (!pstrRcvdGnrlAsyncInfo->buffer ||
+ !hif_drv->usr_conn_req.conn_result) {
PRINT_ER("driver is null\n");
return -EINVAL;
}
@@ -1531,7 +1530,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
u8MacStatusReasonCode = pstrRcvdGnrlAsyncInfo->buffer[8];
u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9];
PRINT_INFO(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Info = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo);
- if (hif_drv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) {
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
u32 u32RcvdAssocRespInfoLen;
tstrConnectRespInfo *pstrConnectRespInfo = NULL;
@@ -1550,7 +1549,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
PRINT_INFO(HOSTINF_DBG, "Received association response with length = %d\n", u32RcvdAssocRespInfoLen);
if (u32RcvdAssocRespInfoLen != 0) {
-
PRINT_D(HOSTINF_DBG, "Parsing association response\n");
s32Err = ParseAssocRespInfo(rcv_assoc_resp, u32RcvdAssocRespInfoLen,
&pstrConnectRespInfo);
@@ -1561,17 +1559,15 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
PRINT_INFO(HOSTINF_DBG, "Association response received : Successful connection status\n");
- if (pstrConnectRespInfo->pu8RespIEs != NULL) {
+ if (pstrConnectRespInfo->pu8RespIEs) {
strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen;
-
-
strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->u16RespIEsLen, GFP_KERNEL);
memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs,
pstrConnectRespInfo->u16RespIEsLen);
}
}
- if (pstrConnectRespInfo != NULL) {
+ if (pstrConnectRespInfo) {
DeallocateAssocRespInfo(pstrConnectRespInfo);
pstrConnectRespInfo = NULL;
}
@@ -1589,40 +1585,38 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
eth_zero_addr(u8ConnectedSSID);
}
- if (hif_drv->strWILC_UsrConnReq.pu8bssid != NULL) {
+ if (hif_drv->usr_conn_req.pu8bssid) {
PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n");
- memcpy(strConnectInfo.au8bssid, hif_drv->strWILC_UsrConnReq.pu8bssid, 6);
+ memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.pu8bssid, 6);
if ((u8MacStatus == MAC_CONNECTED) &&
(strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
- memcpy(hif_drv->au8AssociatedBSSID,
- hif_drv->strWILC_UsrConnReq.pu8bssid, ETH_ALEN);
+ memcpy(hif_drv->assoc_bssid,
+ hif_drv->usr_conn_req.pu8bssid, ETH_ALEN);
}
}
-
- if (hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
- strConnectInfo.ReqIEsLen = hif_drv->strWILC_UsrConnReq.ConnReqIEsLen;
- strConnectInfo.pu8ReqIEs = kmalloc(hif_drv->strWILC_UsrConnReq.ConnReqIEsLen, GFP_KERNEL);
+ if (hif_drv->usr_conn_req.ies) {
+ strConnectInfo.ReqIEsLen = hif_drv->usr_conn_req.ies_len;
+ strConnectInfo.pu8ReqIEs = kmalloc(hif_drv->usr_conn_req.ies_len, GFP_KERNEL);
memcpy(strConnectInfo.pu8ReqIEs,
- hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs,
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen);
+ hif_drv->usr_conn_req.ies,
+ hif_drv->usr_conn_req.ies_len);
}
-
- del_timer(&hif_drv->hConnectTimer);
- hif_drv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_CONN_RESP,
- &strConnectInfo,
- u8MacStatus,
- NULL,
- hif_drv->strWILC_UsrConnReq.u32UserConnectPvoid);
+ del_timer(&hif_drv->connect_timer);
+ hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
+ &strConnectInfo,
+ u8MacStatus,
+ NULL,
+ hif_drv->usr_conn_req.arg);
if ((u8MacStatus == MAC_CONNECTED) &&
(strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
host_int_set_power_mgmt(hif_drv, 0, 0);
PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n");
- hif_drv->enuHostIFstate = HOST_IF_CONNECTED;
+ hif_drv->hif_state = HOST_IF_CONNECTED;
PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n");
g_obtainingIP = true;
@@ -1630,7 +1624,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
jiffies + msecs_to_jiffies(10000));
} else {
PRINT_D(HOSTINF_DBG, "MAC status : %d and Connect Status : %d\n", u8MacStatus, strConnectInfo.u16ConnectStatus);
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
+ hif_drv->hif_state = HOST_IF_IDLE;
scan_while_connected = false;
}
@@ -1639,20 +1633,20 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
kfree(strConnectInfo.pu8ReqIEs);
strConnectInfo.pu8ReqIEs = NULL;
- hif_drv->strWILC_UsrConnReq.ssidLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ssid);
- kfree(hif_drv->strWILC_UsrConnReq.pu8bssid);
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ hif_drv->usr_conn_req.ssid_len = 0;
+ kfree(hif_drv->usr_conn_req.pu8ssid);
+ kfree(hif_drv->usr_conn_req.pu8bssid);
+ hif_drv->usr_conn_req.ies_len = 0;
+ kfree(hif_drv->usr_conn_req.ies);
} else if ((u8MacStatus == MAC_DISCONNECTED) &&
- (hif_drv->enuHostIFstate == HOST_IF_CONNECTED)) {
+ (hif_drv->hif_state == HOST_IF_CONNECTED)) {
PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n");
memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
+ if (hif_drv->usr_scan_req.scan_result) {
PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n");
- del_timer(&hif_drv->hScanTimer);
+ del_timer(&hif_drv->scan_timer);
Handle_ScanDone((void *)hif_drv, SCAN_EVENT_ABORTED);
}
@@ -1660,65 +1654,62 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct host_if_drv *hif_drv,
strDisconnectNotifInfo.ie = NULL;
strDisconnectNotifInfo.ie_len = 0;
- if (hif_drv->strWILC_UsrConnReq.pfUserConnectResult != NULL) {
+ if (hif_drv->usr_conn_req.conn_result) {
g_obtainingIP = false;
host_int_set_power_mgmt(hif_drv, 0, 0);
- hif_drv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF,
- NULL,
- 0,
- &strDisconnectNotifInfo,
- hif_drv->strWILC_UsrConnReq.u32UserConnectPvoid);
-
+ hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
+ NULL,
+ 0,
+ &strDisconnectNotifInfo,
+ hif_drv->usr_conn_req.arg);
} else {
PRINT_ER("Connect result callback function is NULL\n");
}
- eth_zero_addr(hif_drv->au8AssociatedBSSID);
+ eth_zero_addr(hif_drv->assoc_bssid);
- hif_drv->strWILC_UsrConnReq.ssidLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ssid);
- kfree(hif_drv->strWILC_UsrConnReq.pu8bssid);
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ hif_drv->usr_conn_req.ssid_len = 0;
+ kfree(hif_drv->usr_conn_req.pu8ssid);
+ kfree(hif_drv->usr_conn_req.pu8bssid);
+ hif_drv->usr_conn_req.ies_len = 0;
+ kfree(hif_drv->usr_conn_req.ies);
- if (join_req != NULL && join_req_drv == hif_drv) {
+ if (join_req && join_req_drv == hif_drv) {
kfree(join_req);
join_req = NULL;
}
- if (info_element != NULL && join_req_drv == hif_drv) {
+ if (info_element && join_req_drv == hif_drv) {
kfree(info_element);
info_element = NULL;
}
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
+ hif_drv->hif_state = HOST_IF_IDLE;
scan_while_connected = false;
} else if ((u8MacStatus == MAC_DISCONNECTED) &&
- (hif_drv->strWILC_UsrScanReq.pfUserScanResult != NULL)) {
+ (hif_drv->usr_scan_req.scan_result)) {
PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW while scanning\n");
PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >>\n\n");
- del_timer(&hif_drv->hScanTimer);
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult)
+ del_timer(&hif_drv->scan_timer);
+ if (hif_drv->usr_scan_req.scan_result)
Handle_ScanDone(hif_drv, SCAN_EVENT_ABORTED);
-
}
-
}
kfree(pstrRcvdGnrlAsyncInfo->buffer);
pstrRcvdGnrlAsyncInfo->buffer = NULL;
- return s32Error;
+ return result;
}
static int Handle_Key(struct host_if_drv *hif_drv,
struct key_attr *pstrHostIFkeyAttr)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
struct wid strWIDList[5];
u8 i;
u8 *pu8keybuf;
@@ -1726,28 +1717,25 @@ static int Handle_Key(struct host_if_drv *hif_drv,
s8 ret = 0;
switch (pstrHostIFkeyAttr->type) {
-
-
case WEP:
if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
-
PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
- PRINT_D(GENERIC_DBG, "ID Hostint is %d\n", (pstrHostIFkeyAttr->attr.wep.index));
+ PRINT_D(GENERIC_DBG, "ID Hostint is %d\n", pstrHostIFkeyAttr->attr.wep.index);
strWIDList[0].id = (u16)WID_11I_MODE;
strWIDList[0].type = WID_CHAR;
strWIDList[0].size = sizeof(char);
- strWIDList[0].val = (s8 *)(&(pstrHostIFkeyAttr->attr.wep.mode));
+ strWIDList[0].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.mode;
strWIDList[1].id = WID_AUTH_TYPE;
strWIDList[1].type = WID_CHAR;
strWIDList[1].size = sizeof(char);
- strWIDList[1].val = (s8 *)(&(pstrHostIFkeyAttr->attr.wep.auth_type));
+ strWIDList[1].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.auth_type;
strWIDList[2].id = (u16)WID_KEY_ID;
strWIDList[2].type = WID_CHAR;
- strWIDList[2].val = (s8 *)(&(pstrHostIFkeyAttr->attr.wep.index));
+ strWIDList[2].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index;
strWIDList[2].size = sizeof(char);
pu8keybuf = kmemdup(pstrHostIFkeyAttr->attr.wep.key,
@@ -1756,7 +1744,7 @@ static int Handle_Key(struct host_if_drv *hif_drv,
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send Key\n");
- return -1;
+ return -ENOMEM;
}
kfree(pstrHostIFkeyAttr->attr.wep.key);
@@ -1766,93 +1754,89 @@ static int Handle_Key(struct host_if_drv *hif_drv,
strWIDList[3].size = pstrHostIFkeyAttr->attr.wep.key_len;
strWIDList[3].val = (s8 *)pu8keybuf;
-
- s32Error = send_config_pkt(SET_CFG, strWIDList, 4,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, strWIDList, 4,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
-
-
}
if (pstrHostIFkeyAttr->action & ADDKEY) {
PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL);
- if (pu8keybuf == NULL) {
+ if (!pu8keybuf) {
PRINT_ER("No buffer to send Key\n");
- return -1;
+ return -ENOMEM;
}
pu8keybuf[0] = pstrHostIFkeyAttr->attr.wep.index;
memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->attr.wep.key_len, 1);
memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->attr.wep.key,
- pstrHostIFkeyAttr->attr.wep.key_len);
+ pstrHostIFkeyAttr->attr.wep.key_len);
kfree(pstrHostIFkeyAttr->attr.wep.key);
- strWID.id = (u16)WID_ADD_WEP_KEY;
- strWID.type = WID_STR;
- strWID.val = (s8 *)pu8keybuf;
- strWID.size = pstrHostIFkeyAttr->attr.wep.key_len + 2;
+ wid.id = (u16)WID_ADD_WEP_KEY;
+ wid.type = WID_STR;
+ wid.val = (s8 *)pu8keybuf;
+ wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
} else if (pstrHostIFkeyAttr->action & REMOVEKEY) {
-
PRINT_D(HOSTINF_DBG, "Removing key\n");
- strWID.id = (u16)WID_REMOVE_WEP_KEY;
- strWID.type = WID_STR;
+ wid.id = (u16)WID_REMOVE_WEP_KEY;
+ wid.type = WID_STR;
s8idxarray[0] = (s8)pstrHostIFkeyAttr->attr.wep.index;
- strWID.val = s8idxarray;
- strWID.size = 1;
+ wid.val = s8idxarray;
+ wid.size = 1;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
} else {
- strWID.id = (u16)WID_KEY_ID;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)(&(pstrHostIFkeyAttr->attr.wep.index));
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_KEY_ID;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Setting default key index\n");
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
}
- up(&hif_drv->hSemTestKeyBlock);
+ up(&hif_drv->sem_test_key_block);
break;
- case WPARxGtk:
+ case WPA_RX_GTK:
if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
- if (pu8keybuf == NULL) {
+ if (!pu8keybuf) {
PRINT_ER("No buffer to send RxGTK Key\n");
- ret = -1;
+ ret = -ENOMEM;
goto _WPARxGtk_end_case_;
}
- if (pstrHostIFkeyAttr->attr.wpa.seq != NULL)
+ if (pstrHostIFkeyAttr->attr.wpa.seq)
memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->attr.wpa.seq, 8);
memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->attr.wpa.index, 1);
memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->attr.wpa.key,
- pstrHostIFkeyAttr->attr.wpa.key_len);
+ pstrHostIFkeyAttr->attr.wpa.key_len);
strWIDList[0].id = (u16)WID_11I_MODE;
strWIDList[0].type = WID_CHAR;
strWIDList[0].size = sizeof(char);
- strWIDList[0].val = (s8 *)(&(pstrHostIFkeyAttr->attr.wpa.mode));
+ strWIDList[0].val = (s8 *)&pstrHostIFkeyAttr->attr.wpa.mode;
strWIDList[1].id = (u16)WID_ADD_RX_GTK;
strWIDList[1].type = WID_STR;
strWIDList[1].val = (s8 *)pu8keybuf;
strWIDList[1].size = RX_MIC_KEY_MSG_LEN;
- s32Error = send_config_pkt(SET_CFG, strWIDList, 2,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, strWIDList, 2,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
- up(&hif_drv->hSemTestKeyBlock);
+ up(&hif_drv->sem_test_key_block);
}
if (pstrHostIFkeyAttr->action & ADDKEY) {
@@ -1861,122 +1845,109 @@ static int Handle_Key(struct host_if_drv *hif_drv,
pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send RxGTK Key\n");
- ret = -1;
+ ret = -ENOMEM;
goto _WPARxGtk_end_case_;
}
- if (hif_drv->enuHostIFstate == HOST_IF_CONNECTED)
- memcpy(pu8keybuf, hif_drv->au8AssociatedBSSID, ETH_ALEN);
+ if (hif_drv->hif_state == HOST_IF_CONNECTED)
+ memcpy(pu8keybuf, hif_drv->assoc_bssid, ETH_ALEN);
else
- PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED\n");
+ PRINT_ER("Couldn't handle WPARxGtk while state is not HOST_IF_CONNECTED\n");
memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->attr.wpa.seq, 8);
memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->attr.wpa.index, 1);
memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->attr.wpa.key,
- pstrHostIFkeyAttr->attr.wpa.key_len);
+ pstrHostIFkeyAttr->attr.wpa.key_len);
- strWID.id = (u16)WID_ADD_RX_GTK;
- strWID.type = WID_STR;
- strWID.val = (s8 *)pu8keybuf;
- strWID.size = RX_MIC_KEY_MSG_LEN;
+ wid.id = (u16)WID_ADD_RX_GTK;
+ wid.type = WID_STR;
+ wid.val = (s8 *)pu8keybuf;
+ wid.size = RX_MIC_KEY_MSG_LEN;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
- up(&hif_drv->hSemTestKeyBlock);
+ up(&hif_drv->sem_test_key_block);
}
_WPARxGtk_end_case_:
kfree(pstrHostIFkeyAttr->attr.wpa.key);
kfree(pstrHostIFkeyAttr->attr.wpa.seq);
- if (ret == -1)
+ if (ret)
return ret;
break;
- case WPAPtk:
+ case WPA_PTK:
if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
-
-
pu8keybuf = kmalloc(PTK_KEY_MSG_LEN + 1, GFP_KERNEL);
-
-
-
- if (pu8keybuf == NULL) {
+ if (!pu8keybuf) {
PRINT_ER("No buffer to send PTK Key\n");
- ret = -1;
+ ret = -ENOMEM;
goto _WPAPtk_end_case_;
-
}
memcpy(pu8keybuf, pstrHostIFkeyAttr->attr.wpa.mac_addr, 6);
memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->attr.wpa.index, 1);
memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->attr.wpa.key,
- pstrHostIFkeyAttr->attr.wpa.key_len);
+ pstrHostIFkeyAttr->attr.wpa.key_len);
strWIDList[0].id = (u16)WID_11I_MODE;
strWIDList[0].type = WID_CHAR;
strWIDList[0].size = sizeof(char);
- strWIDList[0].val = (s8 *)(&(pstrHostIFkeyAttr->attr.wpa.mode));
+ strWIDList[0].val = (s8 *)&pstrHostIFkeyAttr->attr.wpa.mode;
strWIDList[1].id = (u16)WID_ADD_PTK;
strWIDList[1].type = WID_STR;
strWIDList[1].val = (s8 *)pu8keybuf;
strWIDList[1].size = PTK_KEY_MSG_LEN + 1;
- s32Error = send_config_pkt(SET_CFG, strWIDList, 2,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, strWIDList, 2,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
- up(&hif_drv->hSemTestKeyBlock);
+ up(&hif_drv->sem_test_key_block);
}
if (pstrHostIFkeyAttr->action & ADDKEY) {
-
-
pu8keybuf = kmalloc(PTK_KEY_MSG_LEN, GFP_KERNEL);
-
-
-
- if (pu8keybuf == NULL) {
+ if (!pu8keybuf) {
PRINT_ER("No buffer to send PTK Key\n");
- ret = -1;
+ ret = -ENOMEM;
goto _WPAPtk_end_case_;
-
}
memcpy(pu8keybuf, pstrHostIFkeyAttr->attr.wpa.mac_addr, 6);
memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->attr.wpa.key,
- pstrHostIFkeyAttr->attr.wpa.key_len);
+ pstrHostIFkeyAttr->attr.wpa.key_len);
- strWID.id = (u16)WID_ADD_PTK;
- strWID.type = WID_STR;
- strWID.val = (s8 *)pu8keybuf;
- strWID.size = PTK_KEY_MSG_LEN;
+ wid.id = (u16)WID_ADD_PTK;
+ wid.type = WID_STR;
+ wid.val = (s8 *)pu8keybuf;
+ wid.size = PTK_KEY_MSG_LEN;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
- up(&hif_drv->hSemTestKeyBlock);
+ up(&hif_drv->sem_test_key_block);
}
_WPAPtk_end_case_:
kfree(pstrHostIFkeyAttr->attr.wpa.key);
- if (ret == -1)
+ if (ret)
return ret;
break;
-
case PMKSA:
PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n");
pu8keybuf = kmalloc((pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL);
- if (pu8keybuf == NULL) {
+ if (!pu8keybuf) {
PRINT_ER("No buffer to send PMKSA Key\n");
- return -1;
+ return -ENOMEM;
}
pu8keybuf[0] = pstrHostIFkeyAttr->attr.pmkid.numpmkid;
@@ -1986,38 +1957,35 @@ _WPAPtk_end_case_:
memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->attr.pmkid.pmkidlist[i].pmkid, PMKID_LEN);
}
- strWID.id = (u16)WID_PMKID_INFO;
- strWID.type = WID_STR;
- strWID.val = (s8 *)pu8keybuf;
- strWID.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
+ wid.id = (u16)WID_PMKID_INFO;
+ wid.type = WID_STR;
+ wid.val = (s8 *)pu8keybuf;
+ wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
kfree(pu8keybuf);
break;
}
- if (s32Error)
+ if (result)
PRINT_ER("Failed to send key config packet\n");
-
- return s32Error;
+ return result;
}
static void Handle_Disconnect(struct host_if_drv *hif_drv)
{
- struct wid strWID;
+ struct wid wid;
- s32 s32Error = 0;
+ s32 result = 0;
u16 u16DummyReasonCode = 0;
- strWID.id = (u16)WID_DISCONNECT;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)&u16DummyReasonCode;
- strWID.size = sizeof(char);
-
-
+ wid.id = (u16)WID_DISCONNECT;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&u16DummyReasonCode;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
@@ -2026,10 +1994,10 @@ static void Handle_Disconnect(struct host_if_drv *hif_drv)
eth_zero_addr(u8ConnectedSSID);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to send dissconect config packet\n");
} else {
tstrDisconnectNotifInfo strDisconnectNotifInfo;
@@ -2040,59 +2008,62 @@ static void Handle_Disconnect(struct host_if_drv *hif_drv)
strDisconnectNotifInfo.ie = NULL;
strDisconnectNotifInfo.ie_len = 0;
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
- del_timer(&hif_drv->hScanTimer);
- hif_drv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, NULL,
- hif_drv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
-
- hif_drv->strWILC_UsrScanReq.pfUserScanResult = NULL;
+ if (hif_drv->usr_scan_req.scan_result) {
+ del_timer(&hif_drv->scan_timer);
+ hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED,
+ NULL,
+ hif_drv->usr_scan_req.arg,
+ NULL);
+ hif_drv->usr_scan_req.scan_result = NULL;
}
- if (hif_drv->strWILC_UsrConnReq.pfUserConnectResult != NULL) {
- if (hif_drv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) {
+ if (hif_drv->usr_conn_req.conn_result) {
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n");
- del_timer(&hif_drv->hConnectTimer);
+ del_timer(&hif_drv->connect_timer);
}
- hif_drv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
- 0, &strDisconnectNotifInfo, hif_drv->strWILC_UsrConnReq.u32UserConnectPvoid);
+ hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
+ NULL,
+ 0,
+ &strDisconnectNotifInfo,
+ hif_drv->usr_conn_req.arg);
} else {
- PRINT_ER("strWILC_UsrConnReq.pfUserConnectResult = NULL\n");
+ PRINT_ER("usr_conn_req.conn_result = NULL\n");
}
scan_while_connected = false;
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
+ hif_drv->hif_state = HOST_IF_IDLE;
- eth_zero_addr(hif_drv->au8AssociatedBSSID);
+ eth_zero_addr(hif_drv->assoc_bssid);
- hif_drv->strWILC_UsrConnReq.ssidLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ssid);
- kfree(hif_drv->strWILC_UsrConnReq.pu8bssid);
- hif_drv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
- kfree(hif_drv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ hif_drv->usr_conn_req.ssid_len = 0;
+ kfree(hif_drv->usr_conn_req.pu8ssid);
+ kfree(hif_drv->usr_conn_req.pu8bssid);
+ hif_drv->usr_conn_req.ies_len = 0;
+ kfree(hif_drv->usr_conn_req.ies);
- if (join_req != NULL && join_req_drv == hif_drv) {
+ if (join_req && join_req_drv == hif_drv) {
kfree(join_req);
join_req = NULL;
}
- if (info_element != NULL && join_req_drv == hif_drv) {
+ if (info_element && join_req_drv == hif_drv) {
kfree(info_element);
info_element = NULL;
}
-
}
- up(&hif_drv->hSemTestDisconnectBlock);
+ up(&hif_drv->sem_test_disconn_block);
}
-
void resolve_disconnect_aberration(struct host_if_drv *hif_drv)
{
if (!hif_drv)
return;
- if ((hif_drv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) || (hif_drv->enuHostIFstate == HOST_IF_CONNECTING)) {
+ if ((hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
+ (hif_drv->hif_state == HOST_IF_CONNECTING)) {
PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n");
host_int_disconnect(hif_drv, 1);
}
@@ -2100,201 +2071,182 @@ void resolve_disconnect_aberration(struct host_if_drv *hif_drv)
static s32 Handle_GetChnl(struct host_if_drv *hif_drv)
{
+ s32 result = 0;
+ struct wid wid;
- s32 s32Error = 0;
- struct wid strWID;
-
- strWID.id = (u16)WID_CURRENT_CHANNEL;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)&ch_no;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_CURRENT_CHANNEL;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&ch_no;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Getting channel value\n");
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to get channel number\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
- up(&hif_drv->hSemGetCHNL);
-
- return s32Error;
-
-
+ up(&hif_drv->sem_get_chnl);
+ return result;
}
static void Handle_GetRssi(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
- strWID.id = (u16)WID_RSSI;
- strWID.type = WID_CHAR;
- strWID.val = &rssi;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_RSSI;
+ wid.type = WID_CHAR;
+ wid.val = &rssi;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Getting RSSI value\n");
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result) {
PRINT_ER("Failed to get RSSI value\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
- up(&hif_drv->hSemGetRSSI);
-
-
+ up(&hif_drv->sem_get_rssi);
}
-
static void Handle_GetLinkspeed(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
link_speed = 0;
- strWID.id = (u16)WID_LINKSPEED;
- strWID.type = WID_CHAR;
- strWID.val = &link_speed;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_LINKSPEED;
+ wid.type = WID_CHAR;
+ wid.val = &link_speed;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n");
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result) {
PRINT_ER("Failed to get LINKSPEED value\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
- up(&(hif_drv->hSemGetLINKSPEED));
-
-
+ up(&hif_drv->sem_get_link_speed);
}
s32 Handle_GetStatistics(struct host_if_drv *hif_drv, struct rf_info *pstrStatistics)
{
struct wid strWIDList[5];
- u32 u32WidsCount = 0, s32Error = 0;
+ u32 u32WidsCount = 0, result = 0;
strWIDList[u32WidsCount].id = WID_LINKSPEED;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrStatistics->u8LinkSpeed));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->link_speed;
u32WidsCount++;
strWIDList[u32WidsCount].id = WID_RSSI;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrStatistics->s8RSSI));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->rssi;
u32WidsCount++;
strWIDList[u32WidsCount].id = WID_SUCCESS_FRAME_COUNT;
strWIDList[u32WidsCount].type = WID_INT;
strWIDList[u32WidsCount].size = sizeof(u32);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrStatistics->u32TxCount));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_cnt;
u32WidsCount++;
strWIDList[u32WidsCount].id = WID_RECEIVED_FRAGMENT_COUNT;
strWIDList[u32WidsCount].type = WID_INT;
strWIDList[u32WidsCount].size = sizeof(u32);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrStatistics->u32RxCount));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->rx_cnt;
u32WidsCount++;
strWIDList[u32WidsCount].id = WID_FAILED_COUNT;
strWIDList[u32WidsCount].type = WID_INT;
strWIDList[u32WidsCount].size = sizeof(u32);
- strWIDList[u32WidsCount].val = (s8 *)(&(pstrStatistics->u32TxFailureCount));
+ strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_fail_cnt;
u32WidsCount++;
- s32Error = send_config_pkt(GET_CFG, strWIDList, u32WidsCount,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(GET_CFG, strWIDList, u32WidsCount,
+ get_id_from_handler(hif_drv));
- if (s32Error)
+ if (result)
PRINT_ER("Failed to send scan paramters config packet\n");
up(&hif_sema_wait_response);
return 0;
-
}
static s32 Handle_Get_InActiveTime(struct host_if_drv *hif_drv,
struct sta_inactive_t *strHostIfStaInactiveT)
{
-
- s32 s32Error = 0;
+ s32 result = 0;
u8 *stamac;
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
- strWID.type = WID_STR;
- strWID.size = ETH_ALEN;
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
+ wid.id = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
+ wid.type = WID_STR;
+ wid.size = ETH_ALEN;
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
-
- stamac = strWID.val;
+ stamac = wid.val;
memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN);
-
PRINT_D(CFG80211_DBG, "SETING STA inactive time\n");
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
-
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to SET incative time\n");
return -EFAULT;
}
+ wid.id = (u16)WID_GET_INACTIVE_TIME;
+ wid.type = WID_INT;
+ wid.val = (s8 *)&inactive_time;
+ wid.size = sizeof(u32);
- strWID.id = (u16)WID_GET_INACTIVE_TIME;
- strWID.type = WID_INT;
- strWID.val = (s8 *)&inactive_time;
- strWID.size = sizeof(u32);
-
-
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to get incative time\n");
return -EFAULT;
}
PRINT_D(CFG80211_DBG, "Getting inactive time : %d\n", inactive_time);
- up(&hif_drv->hSemInactiveTime);
-
- return s32Error;
-
-
+ up(&hif_drv->sem_inactive_time);
+ return result;
}
static void Handle_AddBeacon(struct host_if_drv *hif_drv,
struct beacon_attr *pstrSetBeaconParam)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
PRINT_D(HOSTINF_DBG, "Adding BEACON\n");
- strWID.id = (u16)WID_ADD_BEACON;
- strWID.type = WID_BIN;
- strWID.size = pstrSetBeaconParam->head_len + pstrSetBeaconParam->tail_len + 16;
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.id = (u16)WID_ADD_BEACON;
+ wid.type = WID_BIN;
+ wid.size = pstrSetBeaconParam->head_len + pstrSetBeaconParam->tail_len + 16;
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
+ if (!wid.val)
goto ERRORHANDLER;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
*pu8CurrByte++ = (pstrSetBeaconParam->interval & 0xFF);
*pu8CurrByte++ = ((pstrSetBeaconParam->interval >> 8) & 0xFF);
*pu8CurrByte++ = ((pstrSetBeaconParam->interval >> 16) & 0xFF);
@@ -2322,38 +2274,38 @@ static void Handle_AddBeacon(struct host_if_drv *hif_drv,
memcpy(pu8CurrByte, pstrSetBeaconParam->tail, pstrSetBeaconParam->tail_len);
pu8CurrByte += pstrSetBeaconParam->tail_len;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send add beacon config packet\n");
ERRORHANDLER:
- kfree(strWID.val);
+ kfree(wid.val);
kfree(pstrSetBeaconParam->head);
kfree(pstrSetBeaconParam->tail);
}
static void Handle_DelBeacon(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
- strWID.id = (u16)WID_DEL_BEACON;
- strWID.type = WID_CHAR;
- strWID.size = sizeof(char);
- strWID.val = &del_beacon;
+ wid.id = (u16)WID_DEL_BEACON;
+ wid.type = WID_CHAR;
+ wid.size = sizeof(char);
+ wid.val = &del_beacon;
- if (strWID.val == NULL)
+ if (!wid.val)
return;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
PRINT_D(HOSTINF_DBG, "Deleting BEACON\n");
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send delete beacon config packet\n");
}
@@ -2365,40 +2317,42 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer,
pu8CurrByte = pu8Buffer;
PRINT_D(HOSTINF_DBG, "Packing STA params\n");
- memcpy(pu8CurrByte, pstrStationParam->au8BSSID, ETH_ALEN);
+ memcpy(pu8CurrByte, pstrStationParam->bssid, ETH_ALEN);
pu8CurrByte += ETH_ALEN;
- *pu8CurrByte++ = pstrStationParam->u16AssocID & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u16AssocID >> 8) & 0xFF;
+ *pu8CurrByte++ = pstrStationParam->aid & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->aid >> 8) & 0xFF;
- *pu8CurrByte++ = pstrStationParam->u8NumRates;
- if (pstrStationParam->u8NumRates > 0)
- memcpy(pu8CurrByte, pstrStationParam->pu8Rates, pstrStationParam->u8NumRates);
- pu8CurrByte += pstrStationParam->u8NumRates;
+ *pu8CurrByte++ = pstrStationParam->rates_len;
+ if (pstrStationParam->rates_len > 0)
+ memcpy(pu8CurrByte, pstrStationParam->rates,
+ pstrStationParam->rates_len);
+ pu8CurrByte += pstrStationParam->rates_len;
- *pu8CurrByte++ = pstrStationParam->bIsHTSupported;
- *pu8CurrByte++ = pstrStationParam->u16HTCapInfo & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u16HTCapInfo >> 8) & 0xFF;
+ *pu8CurrByte++ = pstrStationParam->ht_supported;
+ *pu8CurrByte++ = pstrStationParam->ht_capa_info & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->ht_capa_info >> 8) & 0xFF;
- *pu8CurrByte++ = pstrStationParam->u8AmpduParams;
- memcpy(pu8CurrByte, pstrStationParam->au8SuppMCsSet, WILC_SUPP_MCS_SET_SIZE);
+ *pu8CurrByte++ = pstrStationParam->ht_ampdu_params;
+ memcpy(pu8CurrByte, pstrStationParam->ht_supp_mcs_set,
+ WILC_SUPP_MCS_SET_SIZE);
pu8CurrByte += WILC_SUPP_MCS_SET_SIZE;
- *pu8CurrByte++ = pstrStationParam->u16HTExtParams & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u16HTExtParams >> 8) & 0xFF;
+ *pu8CurrByte++ = pstrStationParam->ht_ext_params & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->ht_ext_params >> 8) & 0xFF;
- *pu8CurrByte++ = pstrStationParam->u32TxBeamformingCap & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u32TxBeamformingCap >> 8) & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u32TxBeamformingCap >> 16) & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u32TxBeamformingCap >> 24) & 0xFF;
+ *pu8CurrByte++ = pstrStationParam->ht_tx_bf_cap & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 8) & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 16) & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 24) & 0xFF;
- *pu8CurrByte++ = pstrStationParam->u8ASELCap;
+ *pu8CurrByte++ = pstrStationParam->ht_ante_sel;
- *pu8CurrByte++ = pstrStationParam->u16FlagsMask & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u16FlagsMask >> 8) & 0xFF;
+ *pu8CurrByte++ = pstrStationParam->flags_mask & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->flags_mask >> 8) & 0xFF;
- *pu8CurrByte++ = pstrStationParam->u16FlagsSet & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->u16FlagsSet >> 8) & 0xFF;
+ *pu8CurrByte++ = pstrStationParam->flags_set & 0xFF;
+ *pu8CurrByte++ = (pstrStationParam->flags_set >> 8) & 0xFF;
return pu8CurrByte - pu8Buffer;
}
@@ -2406,53 +2360,52 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer,
static void Handle_AddStation(struct host_if_drv *hif_drv,
struct add_sta_param *pstrStationParam)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
PRINT_D(HOSTINF_DBG, "Handling add station\n");
- strWID.id = (u16)WID_ADD_STA;
- strWID.type = WID_BIN;
- strWID.size = WILC_ADD_STA_LENGTH + pstrStationParam->u8NumRates;
+ wid.id = (u16)WID_ADD_STA;
+ wid.type = WID_BIN;
+ wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len;
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
+ if (!wid.val)
goto ERRORHANDLER;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error != 0)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result != 0)
PRINT_ER("Failed to send add station config packet\n");
ERRORHANDLER:
- kfree(pstrStationParam->pu8Rates);
- kfree(strWID.val);
+ kfree(pstrStationParam->rates);
+ kfree(wid.val);
}
static void Handle_DelAllSta(struct host_if_drv *hif_drv,
struct del_all_sta *pstrDelAllStaParam)
{
- s32 s32Error = 0;
-
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
u8 i;
u8 au8Zero_Buff[6] = {0};
- strWID.id = (u16)WID_DEL_ALL_STA;
- strWID.type = WID_STR;
- strWID.size = (pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1;
+ wid.id = (u16)WID_DEL_ALL_STA;
+ wid.type = WID_STR;
+ wid.size = (pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1;
PRINT_D(HOSTINF_DBG, "Handling delete station\n");
- strWID.val = kmalloc((pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.val = kmalloc((pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
+ if (!wid.val)
goto ERRORHANDLER;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
*(pu8CurrByte++) = pstrDelAllStaParam->assoc_sta;
@@ -2465,13 +2418,13 @@ static void Handle_DelAllSta(struct host_if_drv *hif_drv,
pu8CurrByte += ETH_ALEN;
}
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send add station config packet\n");
ERRORHANDLER:
- kfree(strWID.val);
+ kfree(wid.val);
up(&hif_sema_wait_response);
}
@@ -2479,274 +2432,274 @@ ERRORHANDLER:
static void Handle_DelStation(struct host_if_drv *hif_drv,
struct del_sta *pstrDelStaParam)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
- strWID.id = (u16)WID_REMOVE_STA;
- strWID.type = WID_BIN;
- strWID.size = ETH_ALEN;
+ wid.id = (u16)WID_REMOVE_STA;
+ wid.type = WID_BIN;
+ wid.size = ETH_ALEN;
PRINT_D(HOSTINF_DBG, "Handling delete station\n");
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
+ if (!wid.val)
goto ERRORHANDLER;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send add station config packet\n");
ERRORHANDLER:
- kfree(strWID.val);
+ kfree(wid.val);
}
static void Handle_EditStation(struct host_if_drv *hif_drv,
struct add_sta_param *pstrStationParam)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
- strWID.id = (u16)WID_EDIT_STA;
- strWID.type = WID_BIN;
- strWID.size = WILC_ADD_STA_LENGTH + pstrStationParam->u8NumRates;
+ wid.id = (u16)WID_EDIT_STA;
+ wid.type = WID_BIN;
+ wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len;
PRINT_D(HOSTINF_DBG, "Handling edit station\n");
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
+ if (!wid.val)
goto ERRORHANDLER;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send edit station config packet\n");
ERRORHANDLER:
- kfree(pstrStationParam->pu8Rates);
- kfree(strWID.val);
+ kfree(pstrStationParam->rates);
+ kfree(wid.val);
}
static int Handle_RemainOnChan(struct host_if_drv *hif_drv,
struct remain_ch *pstrHostIfRemainOnChan)
{
- s32 s32Error = 0;
+ s32 result = 0;
u8 u8remain_on_chan_flag;
- struct wid strWID;
-
- if (!hif_drv->u8RemainOnChan_pendingreq) {
- hif_drv->strHostIfRemainOnChan.pVoid = pstrHostIfRemainOnChan->pVoid;
- hif_drv->strHostIfRemainOnChan.pRemainOnChanExpired = pstrHostIfRemainOnChan->pRemainOnChanExpired;
- hif_drv->strHostIfRemainOnChan.pRemainOnChanReady = pstrHostIfRemainOnChan->pRemainOnChanReady;
- hif_drv->strHostIfRemainOnChan.u16Channel = pstrHostIfRemainOnChan->u16Channel;
- hif_drv->strHostIfRemainOnChan.u32ListenSessionID = pstrHostIfRemainOnChan->u32ListenSessionID;
+ struct wid wid;
+
+ if (!hif_drv->remain_on_ch_pending) {
+ hif_drv->remain_on_ch.arg = pstrHostIfRemainOnChan->arg;
+ hif_drv->remain_on_ch.expired = pstrHostIfRemainOnChan->expired;
+ hif_drv->remain_on_ch.ready = pstrHostIfRemainOnChan->ready;
+ hif_drv->remain_on_ch.ch = pstrHostIfRemainOnChan->ch;
+ hif_drv->remain_on_ch.id = pstrHostIfRemainOnChan->id;
} else {
- pstrHostIfRemainOnChan->u16Channel = hif_drv->strHostIfRemainOnChan.u16Channel;
+ pstrHostIfRemainOnChan->ch = hif_drv->remain_on_ch.ch;
}
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult != NULL) {
+ if (hif_drv->usr_scan_req.scan_result) {
PRINT_INFO(GENERIC_DBG, "Required to remain on chan while scanning return\n");
- hif_drv->u8RemainOnChan_pendingreq = 1;
- s32Error = -EBUSY;
+ hif_drv->remain_on_ch_pending = 1;
+ result = -EBUSY;
goto ERRORHANDLER;
}
- if (hif_drv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) {
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
PRINT_INFO(GENERIC_DBG, "Required to remain on chan while connecting return\n");
- s32Error = -EBUSY;
+ result = -EBUSY;
goto ERRORHANDLER;
}
if (g_obtainingIP || connecting) {
PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n");
- s32Error = -EBUSY;
+ result = -EBUSY;
goto ERRORHANDLER;
}
- PRINT_D(HOSTINF_DBG, "Setting channel :%d\n", pstrHostIfRemainOnChan->u16Channel);
+ PRINT_D(HOSTINF_DBG, "Setting channel :%d\n",
+ pstrHostIfRemainOnChan->ch);
u8remain_on_chan_flag = true;
- strWID.id = (u16)WID_REMAIN_ON_CHAN;
- strWID.type = WID_STR;
- strWID.size = 2;
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
-
- if (strWID.val == NULL) {
- s32Error = -ENOMEM;
+ wid.id = (u16)WID_REMAIN_ON_CHAN;
+ wid.type = WID_STR;
+ wid.size = 2;
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
+ if (!wid.val) {
+ result = -ENOMEM;
goto ERRORHANDLER;
}
- strWID.val[0] = u8remain_on_chan_flag;
- strWID.val[1] = (s8)pstrHostIfRemainOnChan->u16Channel;
+ wid.val[0] = u8remain_on_chan_flag;
+ wid.val[1] = (s8)pstrHostIfRemainOnChan->ch;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error != 0)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result != 0)
PRINT_ER("Failed to set remain on channel\n");
ERRORHANDLER:
{
P2P_LISTEN_STATE = 1;
- hif_drv->hRemainOnChannel.data = (unsigned long)hif_drv;
- mod_timer(&hif_drv->hRemainOnChannel,
+ hif_drv->remain_on_ch_timer.data = (unsigned long)hif_drv;
+ mod_timer(&hif_drv->remain_on_ch_timer,
jiffies +
msecs_to_jiffies(pstrHostIfRemainOnChan->u32duration));
- if (hif_drv->strHostIfRemainOnChan.pRemainOnChanReady)
- hif_drv->strHostIfRemainOnChan.pRemainOnChanReady(hif_drv->strHostIfRemainOnChan.pVoid);
+ if (hif_drv->remain_on_ch.ready)
+ hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
- if (hif_drv->u8RemainOnChan_pendingreq)
- hif_drv->u8RemainOnChan_pendingreq = 0;
+ if (hif_drv->remain_on_ch_pending)
+ hif_drv->remain_on_ch_pending = 0;
}
- return s32Error;
+
+ return result;
}
static int Handle_RegisterFrame(struct host_if_drv *hif_drv,
struct reg_frame *pstrHostIfRegisterFrame)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
- PRINT_D(HOSTINF_DBG, "Handling frame register Flag : %d FrameType: %d\n", pstrHostIfRegisterFrame->bReg, pstrHostIfRegisterFrame->u16FrameType);
+ PRINT_D(HOSTINF_DBG, "Handling frame register : %d FrameType: %d\n",
+ pstrHostIfRegisterFrame->reg,
+ pstrHostIfRegisterFrame->frame_type);
- strWID.id = (u16)WID_REGISTER_FRAME;
- strWID.type = WID_STR;
- strWID.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.id = (u16)WID_REGISTER_FRAME;
+ wid.type = WID_STR;
+ wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
+ if (!wid.val)
return -ENOMEM;
- pu8CurrByte = strWID.val;
-
- *pu8CurrByte++ = pstrHostIfRegisterFrame->bReg;
- *pu8CurrByte++ = pstrHostIfRegisterFrame->u8Regid;
- memcpy(pu8CurrByte, &(pstrHostIfRegisterFrame->u16FrameType), sizeof(u16));
+ pu8CurrByte = wid.val;
+ *pu8CurrByte++ = pstrHostIfRegisterFrame->reg;
+ *pu8CurrByte++ = pstrHostIfRegisterFrame->reg_id;
+ memcpy(pu8CurrByte, &pstrHostIfRegisterFrame->frame_type, sizeof(u16));
- strWID.size = sizeof(u16) + 2;
+ wid.size = sizeof(u16) + 2;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result) {
PRINT_ER("Failed to frame register config packet\n");
- s32Error = -EINVAL;
+ result = -EINVAL;
}
- return s32Error;
-
+ return result;
}
-#define FALSE_FRMWR_CHANNEL 100
static u32 Handle_ListenStateExpired(struct host_if_drv *hif_drv,
struct remain_ch *pstrHostIfRemainOnChan)
{
u8 u8remain_on_chan_flag;
- struct wid strWID;
- s32 s32Error = 0;
+ struct wid wid;
+ s32 result = 0;
PRINT_D(HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n");
if (P2P_LISTEN_STATE) {
u8remain_on_chan_flag = false;
- strWID.id = (u16)WID_REMAIN_ON_CHAN;
- strWID.type = WID_STR;
- strWID.size = 2;
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
+ wid.id = (u16)WID_REMAIN_ON_CHAN;
+ wid.type = WID_STR;
+ wid.size = 2;
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
- if (strWID.val == NULL)
+ if (!wid.val)
PRINT_ER("Failed to allocate memory\n");
- strWID.val[0] = u8remain_on_chan_flag;
- strWID.val[1] = FALSE_FRMWR_CHANNEL;
+ wid.val[0] = u8remain_on_chan_flag;
+ wid.val[1] = FALSE_FRMWR_CHANNEL;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error != 0) {
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result != 0) {
PRINT_ER("Failed to set remain on channel\n");
goto _done_;
}
- if (hif_drv->strHostIfRemainOnChan.pRemainOnChanExpired) {
- hif_drv->strHostIfRemainOnChan.pRemainOnChanExpired(hif_drv->strHostIfRemainOnChan.pVoid
- , pstrHostIfRemainOnChan->u32ListenSessionID);
+ if (hif_drv->remain_on_ch.expired) {
+ hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
+ pstrHostIfRemainOnChan->id);
}
P2P_LISTEN_STATE = 0;
} else {
PRINT_D(GENERIC_DBG, "Not in listen state\n");
- s32Error = -EFAULT;
+ result = -EFAULT;
}
_done_:
- return s32Error;
+ return result;
}
static void ListenTimerCB(unsigned long arg)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
- del_timer(&hif_drv->hRemainOnChannel);
+ del_timer(&hif_drv->remain_on_ch_timer);
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
msg.drv = hif_drv;
- msg.body.remain_on_ch.u32ListenSessionID = hif_drv->strHostIfRemainOnChan.u32ListenSessionID;
+ msg.body.remain_on_ch.id = hif_drv->remain_on_ch.id;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
}
static void Handle_PowerManagement(struct host_if_drv *hif_drv,
struct power_mgmt_param *strPowerMgmtParam)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
s8 s8PowerMode;
- strWID.id = (u16)WID_POWER_MANAGEMENT;
+ wid.id = (u16)WID_POWER_MANAGEMENT;
- if (strPowerMgmtParam->enabled == true)
+ if (strPowerMgmtParam->enabled)
s8PowerMode = MIN_FAST_PS;
else
s8PowerMode = NO_POWERSAVE;
PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode);
- strWID.val = &s8PowerMode;
- strWID.size = sizeof(char);
+ wid.val = &s8PowerMode;
+ wid.size = sizeof(char);
PRINT_D(HOSTINF_DBG, "Handling Power Management\n");
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send power management config packet\n");
}
static void Handle_SetMulticastFilter(struct host_if_drv *hif_drv,
struct set_multicast *strHostIfSetMulti)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
u8 *pu8CurrByte;
PRINT_D(HOSTINF_DBG, "Setup Multicast Filter\n");
- strWID.id = (u16)WID_SETUP_MULTICAST_FILTER;
- strWID.type = WID_BIN;
- strWID.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN);
- strWID.val = kmalloc(strWID.size, GFP_KERNEL);
- if (strWID.val == NULL)
+ wid.id = (u16)WID_SETUP_MULTICAST_FILTER;
+ wid.type = WID_BIN;
+ wid.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN);
+ wid.val = kmalloc(wid.size, GFP_KERNEL);
+ if (!wid.val)
goto ERRORHANDLER;
- pu8CurrByte = strWID.val;
+ pu8CurrByte = wid.val;
*pu8CurrByte++ = (strHostIfSetMulti->enabled & 0xFF);
*pu8CurrByte++ = ((strHostIfSetMulti->enabled >> 8) & 0xFF);
*pu8CurrByte++ = ((strHostIfSetMulti->enabled >> 16) & 0xFF);
@@ -2758,123 +2711,119 @@ static void Handle_SetMulticastFilter(struct host_if_drv *hif_drv,
*pu8CurrByte++ = ((strHostIfSetMulti->cnt >> 24) & 0xFF);
if ((strHostIfSetMulti->cnt) > 0)
- memcpy(pu8CurrByte, gau8MulticastMacAddrList, ((strHostIfSetMulti->cnt) * ETH_ALEN));
+ memcpy(pu8CurrByte, multicast_mac_addr_list,
+ ((strHostIfSetMulti->cnt) * ETH_ALEN));
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_ER("Failed to send setup multicast config packet\n");
ERRORHANDLER:
- kfree(strWID.val);
-
+ kfree(wid.val);
}
static s32 Handle_AddBASession(struct host_if_drv *hif_drv,
struct ba_session_info *strHostIfBASessionInfo)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
int AddbaTimeout = 100;
char *ptr = NULL;
PRINT_D(HOSTINF_DBG, "Opening Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\nBufferSize == %d\nSessionTimeOut = %d\n",
- strHostIfBASessionInfo->au8Bssid[0],
- strHostIfBASessionInfo->au8Bssid[1],
- strHostIfBASessionInfo->au8Bssid[2],
- strHostIfBASessionInfo->u16BufferSize,
- strHostIfBASessionInfo->u16SessionTimeout,
- strHostIfBASessionInfo->u8Ted);
-
- strWID.id = (u16)WID_11E_P_ACTION_REQ;
- strWID.type = WID_STR;
- strWID.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL);
- strWID.size = BLOCK_ACK_REQ_SIZE;
- ptr = strWID.val;
+ strHostIfBASessionInfo->bssid[0],
+ strHostIfBASessionInfo->bssid[1],
+ strHostIfBASessionInfo->bssid[2],
+ strHostIfBASessionInfo->buf_size,
+ strHostIfBASessionInfo->time_out,
+ strHostIfBASessionInfo->tid);
+
+ wid.id = (u16)WID_11E_P_ACTION_REQ;
+ wid.type = WID_STR;
+ wid.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL);
+ wid.size = BLOCK_ACK_REQ_SIZE;
+ ptr = wid.val;
*ptr++ = 0x14;
*ptr++ = 0x3;
*ptr++ = 0x0;
- memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->bssid, ETH_ALEN);
ptr += ETH_ALEN;
- *ptr++ = strHostIfBASessionInfo->u8Ted;
+ *ptr++ = strHostIfBASessionInfo->tid;
*ptr++ = 1;
- *ptr++ = (strHostIfBASessionInfo->u16BufferSize & 0xFF);
- *ptr++ = ((strHostIfBASessionInfo->u16BufferSize >> 16) & 0xFF);
- *ptr++ = (strHostIfBASessionInfo->u16SessionTimeout & 0xFF);
- *ptr++ = ((strHostIfBASessionInfo->u16SessionTimeout >> 16) & 0xFF);
+ *ptr++ = (strHostIfBASessionInfo->buf_size & 0xFF);
+ *ptr++ = ((strHostIfBASessionInfo->buf_size >> 16) & 0xFF);
+ *ptr++ = (strHostIfBASessionInfo->time_out & 0xFF);
+ *ptr++ = ((strHostIfBASessionInfo->time_out >> 16) & 0xFF);
*ptr++ = (AddbaTimeout & 0xFF);
*ptr++ = ((AddbaTimeout >> 16) & 0xFF);
*ptr++ = 8;
*ptr++ = 0;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_D(HOSTINF_DBG, "Couldn't open BA Session\n");
-
- strWID.id = (u16)WID_11E_P_ACTION_REQ;
- strWID.type = WID_STR;
- strWID.size = 15;
- ptr = strWID.val;
+ wid.id = (u16)WID_11E_P_ACTION_REQ;
+ wid.type = WID_STR;
+ wid.size = 15;
+ ptr = wid.val;
*ptr++ = 15;
*ptr++ = 7;
*ptr++ = 0x2;
- memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->bssid, ETH_ALEN);
ptr += ETH_ALEN;
- *ptr++ = strHostIfBASessionInfo->u8Ted;
+ *ptr++ = strHostIfBASessionInfo->tid;
*ptr++ = 8;
- *ptr++ = (strHostIfBASessionInfo->u16BufferSize & 0xFF);
- *ptr++ = ((strHostIfBASessionInfo->u16SessionTimeout >> 16) & 0xFF);
+ *ptr++ = (strHostIfBASessionInfo->buf_size & 0xFF);
+ *ptr++ = ((strHostIfBASessionInfo->time_out >> 16) & 0xFF);
*ptr++ = 3;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
-
- kfree(strWID.val);
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- return s32Error;
+ kfree(wid.val);
+ return result;
}
static s32 Handle_DelAllRxBASessions(struct host_if_drv *hif_drv,
struct ba_session_info *strHostIfBASessionInfo)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
char *ptr = NULL;
PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n",
- strHostIfBASessionInfo->au8Bssid[0],
- strHostIfBASessionInfo->au8Bssid[1],
- strHostIfBASessionInfo->au8Bssid[2],
- strHostIfBASessionInfo->u8Ted);
-
- strWID.id = (u16)WID_DEL_ALL_RX_BA;
- strWID.type = WID_STR;
- strWID.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL);
- strWID.size = BLOCK_ACK_REQ_SIZE;
- ptr = strWID.val;
+ strHostIfBASessionInfo->bssid[0],
+ strHostIfBASessionInfo->bssid[1],
+ strHostIfBASessionInfo->bssid[2],
+ strHostIfBASessionInfo->tid);
+
+ wid.id = (u16)WID_DEL_ALL_RX_BA;
+ wid.type = WID_STR;
+ wid.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL);
+ wid.size = BLOCK_ACK_REQ_SIZE;
+ ptr = wid.val;
*ptr++ = 0x14;
*ptr++ = 0x3;
*ptr++ = 0x2;
- memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->bssid, ETH_ALEN);
ptr += ETH_ALEN;
- *ptr++ = strHostIfBASessionInfo->u8Ted;
+ *ptr++ = strHostIfBASessionInfo->tid;
*ptr++ = 0;
*ptr++ = 32;
- s32Error = send_config_pkt(SET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error)
+ result = send_config_pkt(SET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result)
PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n");
-
- kfree(strWID.val);
+ kfree(wid.val);
up(&hif_sema_wait_response);
- return s32Error;
-
+ return result;
}
static int hostIFthread(void *pvArg)
@@ -2900,7 +2849,8 @@ static int hostIFthread(void *pvArg)
continue;
}
- if (msg.id == HOST_IF_MSG_CONNECT && hif_drv->strWILC_UsrScanReq.pfUserScanResult != NULL) {
+ if (msg.id == HOST_IF_MSG_CONNECT &&
+ hif_drv->usr_scan_req.scan_result) {
PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n");
wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
usleep_range(2 * 1000, 2 * 1000);
@@ -2937,12 +2887,11 @@ static int hostIFthread(void *pvArg)
break;
case HOST_IF_MSG_CFG_PARAMS:
-
- Handle_CfgParam(msg.drv, &msg.body.cfg_info);
+ handle_cfg_param(msg.drv, &msg.body.cfg_info);
break;
case HOST_IF_MSG_SET_CHANNEL:
- Handle_SetChannel(msg.drv, &msg.body.channel_info);
+ handle_set_channel(msg.drv, &msg.body.channel_info);
break;
case HOST_IF_MSG_DISCONNECT:
@@ -2950,15 +2899,15 @@ static int hostIFthread(void *pvArg)
break;
case HOST_IF_MSG_RCVD_SCAN_COMPLETE:
- del_timer(&hif_drv->hScanTimer);
+ del_timer(&hif_drv->scan_timer);
PRINT_D(HOSTINF_DBG, "scan completed successfully\n");
if (!linux_wlan_get_num_conn_ifcs())
- chip_sleep_manually(INFINITE_SLEEP_TIME);
+ chip_sleep_manually();
Handle_ScanDone(msg.drv, SCAN_EVENT_DONE);
- if (hif_drv->u8RemainOnChan_pendingreq)
+ if (hif_drv->remain_on_ch_pending)
Handle_RemainOnChan(msg.drv, &msg.body.remain_on_ch);
break;
@@ -3019,30 +2968,33 @@ static int hostIFthread(void *pvArg)
break;
case HOST_IF_MSG_SET_WFIDRV_HANDLER:
- Handle_SetWfiDrvHandler(msg.drv,
- &msg.body.drv);
+ handle_set_wfi_drv_handler(msg.drv, &msg.body.drv);
break;
case HOST_IF_MSG_SET_OPERATION_MODE:
- Handle_SetOperationMode(msg.drv, &msg.body.mode);
+ handle_set_operation_mode(msg.drv, &msg.body.mode);
break;
case HOST_IF_MSG_SET_IPADDRESS:
PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n");
- Handle_set_IPAddress(msg.drv, msg.body.ip_info.ip_addr, msg.body.ip_info.idx);
+ handle_set_ip_address(msg.drv,
+ msg.body.ip_info.ip_addr,
+ msg.body.ip_info.idx);
break;
case HOST_IF_MSG_GET_IPADDRESS:
PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n");
- Handle_get_IPAddress(msg.drv, msg.body.ip_info.ip_addr, msg.body.ip_info.idx);
+ handle_get_ip_address(msg.drv, msg.body.ip_info.idx);
break;
case HOST_IF_MSG_SET_MAC_ADDRESS:
- Handle_SetMacAddress(msg.drv, &msg.body.set_mac_info);
+ handle_set_mac_address(msg.drv,
+ &msg.body.set_mac_info);
break;
case HOST_IF_MSG_GET_MAC_ADDRESS:
- Handle_GetMacAddress(msg.drv, &msg.body.get_mac_info);
+ handle_get_mac_address(msg.drv,
+ &msg.body.get_mac_info);
break;
case HOST_IF_MSG_REMAIN_ON_CHAN:
@@ -3113,12 +3065,12 @@ static void TimerCB_Connect(unsigned long arg)
s32 host_int_remove_key(struct host_if_drv *hif_drv, const u8 *pu8StaAddress)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_REMOVE_KEY;
- strWID.type = WID_STR;
- strWID.val = (s8 *)pu8StaAddress;
- strWID.size = 6;
+ wid.id = (u16)WID_REMOVE_KEY;
+ wid.type = WID_STR;
+ wid.val = (s8 *)pu8StaAddress;
+ wid.size = 6;
return 0;
}
@@ -3145,119 +3097,114 @@ int host_int_remove_wep_key(struct host_if_drv *hif_drv, u8 index)
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
PRINT_ER("Error in sending message queue : Request to remove WEP key\n");
- down(&hif_drv->hSemTestKeyBlock);
+ down(&hif_drv->sem_test_key_block);
return result;
}
-s32 host_int_set_WEPDefaultKeyID(struct host_if_drv *hif_drv, u8 u8Index)
+int host_int_set_wep_default_key(struct host_if_drv *hif_drv, u8 index)
{
- s32 s32Error = 0;
+ int result = 0;
struct host_if_msg msg;
-
if (!hif_drv) {
- s32Error = -EFAULT;
+ result = -EFAULT;
PRINT_ER("driver is null\n");
- return s32Error;
+ return result;
}
memset(&msg, 0, sizeof(struct host_if_msg));
-
msg.id = HOST_IF_MSG_KEY;
msg.body.key_info.type = WEP;
msg.body.key_info.action = DEFAULTKEY;
msg.drv = hif_drv;
- msg.body.key_info.attr.wep.index = u8Index;
+ msg.body.key_info.attr.wep.index = index;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("Error in sending message queue : Default key index\n");
- down(&hif_drv->hSemTestKeyBlock);
+ down(&hif_drv->sem_test_key_block);
- return s32Error;
+ return result;
}
-s32 host_int_add_wep_key_bss_sta(struct host_if_drv *hif_drv,
- const u8 *pu8WepKey,
- u8 u8WepKeylen,
- u8 u8Keyidx)
+int host_int_add_wep_key_bss_sta(struct host_if_drv *hif_drv,
+ const u8 *key,
+ u8 len,
+ u8 index)
{
-
- s32 s32Error = 0;
+ int result = 0;
struct host_if_msg msg;
if (!hif_drv) {
- s32Error = -EFAULT;
PRINT_ER("driver is null\n");
- return s32Error;
+ return -EFAULT;
}
memset(&msg, 0, sizeof(struct host_if_msg));
-
msg.id = HOST_IF_MSG_KEY;
msg.body.key_info.type = WEP;
msg.body.key_info.action = ADDKEY;
msg.drv = hif_drv;
- msg.body.key_info.attr.wep.key = kmalloc(u8WepKeylen, GFP_KERNEL);
- memcpy(msg.body.key_info.attr.wep.key, pu8WepKey, u8WepKeylen);
- msg.body.key_info.attr.wep.key_len = (u8WepKeylen);
- msg.body.key_info.attr.wep.index = u8Keyidx;
+ msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
+ if (!msg.body.key_info.attr.wep.key)
+ return -ENOMEM;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
- PRINT_ER("Error in sending message queue :WEP Key\n");
- down(&hif_drv->hSemTestKeyBlock);
+ msg.body.key_info.attr.wep.key_len = len;
+ msg.body.key_info.attr.wep.index = index;
- return s32Error;
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
+ PRINT_ER("Error in sending message queue :WEP Key\n");
+ down(&hif_drv->sem_test_key_block);
+ return result;
}
-s32 host_int_add_wep_key_bss_ap(struct host_if_drv *hif_drv,
- const u8 *pu8WepKey,
- u8 u8WepKeylen,
- u8 u8Keyidx,
- u8 u8mode,
- enum AUTHTYPE tenuAuth_type)
+int host_int_add_wep_key_bss_ap(struct host_if_drv *hif_drv,
+ const u8 *key,
+ u8 len,
+ u8 index,
+ u8 mode,
+ enum AUTHTYPE auth_type)
{
-
- s32 s32Error = 0;
+ int result = 0;
struct host_if_msg msg;
- u8 i;
+ int i;
if (!hif_drv) {
- s32Error = -EFAULT;
PRINT_ER("driver is null\n");
- return s32Error;
+ return -EFAULT;
}
memset(&msg, 0, sizeof(struct host_if_msg));
if (INFO) {
- for (i = 0; i < u8WepKeylen; i++)
- PRINT_INFO(HOSTAPD_DBG, "KEY is %x\n", pu8WepKey[i]);
+ for (i = 0; i < len; i++)
+ PRINT_INFO(HOSTAPD_DBG, "KEY is %x\n", key[i]);
}
msg.id = HOST_IF_MSG_KEY;
msg.body.key_info.type = WEP;
msg.body.key_info.action = ADDKEY_AP;
msg.drv = hif_drv;
- msg.body.key_info.attr.wep.key = kmalloc(u8WepKeylen, GFP_KERNEL);
- memcpy(msg.body.key_info.attr.wep.key, pu8WepKey, (u8WepKeylen));
- msg.body.key_info.attr.wep.key_len = (u8WepKeylen);
- msg.body.key_info.attr.wep.index = u8Keyidx;
- msg.body.key_info.attr.wep.mode = u8mode;
- msg.body.key_info.attr.wep.auth_type = tenuAuth_type;
+ msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
+ if (!msg.body.key_info.attr.wep.key)
+ return -ENOMEM;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ msg.body.key_info.attr.wep.key_len = len;
+ msg.body.key_info.attr.wep.index = index;
+ msg.body.key_info.attr.wep.mode = mode;
+ msg.body.key_info.attr.wep.auth_type = auth_type;
- if (s32Error)
- PRINT_ER("Error in sending message queue :WEP Key\n");
- down(&hif_drv->hSemTestKeyBlock);
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- return s32Error;
+ if (result)
+ PRINT_ER("Error in sending message queue :WEP Key\n");
+ down(&hif_drv->sem_test_key_block);
+ return result;
}
s32 host_int_add_ptk(struct host_if_drv *hif_drv, const u8 *pu8Ptk,
@@ -3265,26 +3212,26 @@ s32 host_int_add_ptk(struct host_if_drv *hif_drv, const u8 *pu8Ptk,
const u8 *pu8RxMic, const u8 *pu8TxMic,
u8 mode, u8 u8Ciphermode, u8 u8Idx)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
u8 u8KeyLen = u8PtkKeylen;
u32 i;
if (!hif_drv) {
- s32Error = -EFAULT;
PRINT_ER("driver is null\n");
- return s32Error;
+ return -EFAULT;
}
- if (pu8RxMic != NULL)
+
+ if (pu8RxMic)
u8KeyLen += RX_MIC_KEY_LEN;
- if (pu8TxMic != NULL)
+
+ if (pu8TxMic)
u8KeyLen += TX_MIC_KEY_LEN;
memset(&msg, 0, sizeof(struct host_if_msg));
-
msg.id = HOST_IF_MSG_KEY;
- msg.body.key_info.type = WPAPtk;
+ msg.body.key_info.type = WPA_PTK;
if (mode == AP_MODE) {
msg.body.key_info.action = ADDKEY_AP;
msg.body.key_info.attr.wpa.index = u8Idx;
@@ -3295,14 +3242,14 @@ s32 host_int_add_ptk(struct host_if_drv *hif_drv, const u8 *pu8Ptk,
msg.body.key_info.attr.wpa.key = kmalloc(u8PtkKeylen, GFP_KERNEL);
memcpy(msg.body.key_info.attr.wpa.key, pu8Ptk, u8PtkKeylen);
- if (pu8RxMic != NULL) {
+ if (pu8RxMic) {
memcpy(msg.body.key_info.attr.wpa.key + 16, pu8RxMic, RX_MIC_KEY_LEN);
if (INFO) {
for (i = 0; i < RX_MIC_KEY_LEN; i++)
PRINT_INFO(CFG80211_DBG, "PairwiseRx[%d] = %x\n", i, pu8RxMic[i]);
}
}
- if (pu8TxMic != NULL) {
+ if (pu8TxMic) {
memcpy(msg.body.key_info.attr.wpa.key + 24, pu8TxMic, TX_MIC_KEY_LEN);
if (INFO) {
for (i = 0; i < TX_MIC_KEY_LEN; i++)
@@ -3315,14 +3262,14 @@ s32 host_int_add_ptk(struct host_if_drv *hif_drv, const u8 *pu8Ptk,
msg.body.key_info.attr.wpa.mode = u8Ciphermode;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ if (result)
PRINT_ER("Error in sending message queue: PTK Key\n");
- down(&hif_drv->hSemTestKeyBlock);
+ down(&hif_drv->sem_test_key_block);
- return s32Error;
+ return result;
}
s32 host_int_add_rx_gtk(struct host_if_drv *hif_drv, const u8 *pu8RxGtk,
@@ -3331,30 +3278,29 @@ s32 host_int_add_rx_gtk(struct host_if_drv *hif_drv, const u8 *pu8RxGtk,
const u8 *pu8RxMic, const u8 *pu8TxMic,
u8 mode, u8 u8Ciphermode)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
u8 u8KeyLen = u8GtkKeylen;
if (!hif_drv) {
- s32Error = -EFAULT;
PRINT_ER("driver is null\n");
- return s32Error;
+ return -EFAULT;
}
memset(&msg, 0, sizeof(struct host_if_msg));
-
- if (pu8RxMic != NULL)
+ if (pu8RxMic)
u8KeyLen += RX_MIC_KEY_LEN;
- if (pu8TxMic != NULL)
+
+ if (pu8TxMic)
u8KeyLen += TX_MIC_KEY_LEN;
- if (KeyRSC != NULL) {
+
+ if (KeyRSC) {
msg.body.key_info.attr.wpa.seq = kmalloc(u32KeyRSClen, GFP_KERNEL);
memcpy(msg.body.key_info.attr.wpa.seq, KeyRSC, u32KeyRSClen);
}
-
msg.id = HOST_IF_MSG_KEY;
- msg.body.key_info.type = WPARxGtk;
+ msg.body.key_info.type = WPA_RX_GTK;
msg.drv = hif_drv;
if (mode == AP_MODE) {
@@ -3367,37 +3313,36 @@ s32 host_int_add_rx_gtk(struct host_if_drv *hif_drv, const u8 *pu8RxGtk,
msg.body.key_info.attr.wpa.key = kmalloc(u8KeyLen, GFP_KERNEL);
memcpy(msg.body.key_info.attr.wpa.key, pu8RxGtk, u8GtkKeylen);
- if (pu8RxMic != NULL) {
- memcpy(msg.body.key_info.attr.wpa.key + 16, pu8RxMic, RX_MIC_KEY_LEN);
- }
- if (pu8TxMic != NULL) {
- memcpy(msg.body.key_info.attr.wpa.key + 24, pu8TxMic, TX_MIC_KEY_LEN);
- }
+ if (pu8RxMic)
+ memcpy(msg.body.key_info.attr.wpa.key + 16, pu8RxMic,
+ RX_MIC_KEY_LEN);
+
+ if (pu8TxMic)
+ memcpy(msg.body.key_info.attr.wpa.key + 24, pu8TxMic,
+ TX_MIC_KEY_LEN);
msg.body.key_info.attr.wpa.index = u8KeyIdx;
msg.body.key_info.attr.wpa.key_len = u8KeyLen;
msg.body.key_info.attr.wpa.seq_len = u32KeyRSClen;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("Error in sending message queue: RX GTK\n");
- down(&hif_drv->hSemTestKeyBlock);
+ down(&hif_drv->sem_test_key_block);
- return s32Error;
+ return result;
}
s32 host_int_set_pmkid_info(struct host_if_drv *hif_drv, struct host_if_pmkid_attr *pu8PmkidInfoArray)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
u32 i;
-
if (!hif_drv) {
- s32Error = -EFAULT;
PRINT_ER("driver is null\n");
- return s32Error;
+ return -EFAULT;
}
memset(&msg, 0, sizeof(struct host_if_msg));
@@ -3408,29 +3353,29 @@ s32 host_int_set_pmkid_info(struct host_if_drv *hif_drv, struct host_if_pmkid_at
msg.drv = hif_drv;
for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) {
- memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid, &pu8PmkidInfoArray->pmkidlist[i].bssid,
- ETH_ALEN);
- memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid, &pu8PmkidInfoArray->pmkidlist[i].pmkid,
- PMKID_LEN);
+ memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid,
+ &pu8PmkidInfoArray->pmkidlist[i].bssid, ETH_ALEN);
+ memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid,
+ &pu8PmkidInfoArray->pmkidlist[i].pmkid, PMKID_LEN);
}
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER(" Error in sending messagequeue: PMKID Info\n");
- return s32Error;
+ return result;
}
s32 host_int_get_pmkid_info(struct host_if_drv *hif_drv,
u8 *pu8PmkidInfoArray,
u32 u32PmkidInfoLen)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_PMKID_INFO;
- strWID.type = WID_STR;
- strWID.size = u32PmkidInfoLen;
- strWID.val = pu8PmkidInfoArray;
+ wid.id = (u16)WID_PMKID_INFO;
+ wid.type = WID_STR;
+ wid.size = u32PmkidInfoLen;
+ wid.val = pu8PmkidInfoArray;
return 0;
}
@@ -3439,92 +3384,91 @@ s32 host_int_set_RSNAConfigPSKPassPhrase(struct host_if_drv *hif_drv,
u8 *pu8PassPhrase,
u8 u8Psklength)
{
- struct wid strWID;
+ struct wid wid;
if ((u8Psklength > 7) && (u8Psklength < 65)) {
- strWID.id = (u16)WID_11I_PSK;
- strWID.type = WID_STR;
- strWID.val = pu8PassPhrase;
- strWID.size = u8Psklength;
+ wid.id = (u16)WID_11I_PSK;
+ wid.type = WID_STR;
+ wid.val = pu8PassPhrase;
+ wid.size = u8Psklength;
}
return 0;
}
-s32 host_int_get_MacAddress(struct host_if_drv *hif_drv, u8 *pu8MacAddress)
+s32 hif_get_mac_address(struct host_if_drv *hif_drv, u8 *pu8MacAddress)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_GET_MAC_ADDRESS;
- msg.body.get_mac_info.u8MacAddress = pu8MacAddress;
+ msg.body.get_mac_info.mac_addr = pu8MacAddress;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send get mac address\n");
return -EFAULT;
}
down(&hif_sema_wait_response);
- return s32Error;
+ return result;
}
s32 host_int_set_MacAddress(struct host_if_drv *hif_drv, u8 *pu8MacAddress)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]);
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_SET_MAC_ADDRESS;
- memcpy(msg.body.set_mac_info.u8MacAddress, pu8MacAddress, ETH_ALEN);
+ memcpy(msg.body.set_mac_info.mac_addr, pu8MacAddress, ETH_ALEN);
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("Failed to send message queue: Set mac address\n");
- return s32Error;
-
+ return result;
}
s32 host_int_get_RSNAConfigPSKPassPhrase(struct host_if_drv *hif_drv,
u8 *pu8PassPhrase, u8 u8Psklength)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_11I_PSK;
- strWID.type = WID_STR;
- strWID.size = u8Psklength;
- strWID.val = pu8PassPhrase;
+ wid.id = (u16)WID_11I_PSK;
+ wid.type = WID_STR;
+ wid.size = u8Psklength;
+ wid.val = pu8PassPhrase;
return 0;
}
s32 host_int_set_start_scan_req(struct host_if_drv *hif_drv, u8 scanSource)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_START_SCAN_REQ;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)&scanSource;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_START_SCAN_REQ;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&scanSource;
+ wid.size = sizeof(char);
return 0;
}
s32 host_int_get_start_scan_req(struct host_if_drv *hif_drv, u8 *pu8ScanSource)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_START_SCAN_REQ;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)pu8ScanSource;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_START_SCAN_REQ;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)pu8ScanSource;
+ wid.size = sizeof(char);
return 0;
}
@@ -3536,16 +3480,15 @@ s32 host_int_set_join_req(struct host_if_drv *hif_drv, u8 *pu8bssid,
u8 u8security, enum AUTHTYPE tenuAuth_type,
u8 u8channel, void *pJoinParams)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
- if (!hif_drv || pfConnectResult == NULL) {
- s32Error = -EFAULT;
+ if (!hif_drv || !pfConnectResult) {
PRINT_ER("Driver is null\n");
- return s32Error;
+ return -EFAULT;
}
- if (pJoinParams == NULL) {
+ if (!pJoinParams) {
PRINT_ER("Unable to Join - JoinParams is NULL\n");
return -EFAULT;
}
@@ -3562,72 +3505,69 @@ s32 host_int_set_join_req(struct host_if_drv *hif_drv, u8 *pu8bssid,
msg.body.con_info.params = pJoinParams;
msg.drv = hif_drv ;
- if (pu8bssid != NULL) {
+ if (pu8bssid) {
msg.body.con_info.bssid = kmalloc(6, GFP_KERNEL);
memcpy(msg.body.con_info.bssid, pu8bssid, 6);
}
- if (pu8ssid != NULL) {
+ if (pu8ssid) {
msg.body.con_info.ssid_len = ssidLen;
msg.body.con_info.ssid = kmalloc(ssidLen, GFP_KERNEL);
memcpy(msg.body.con_info.ssid, pu8ssid, ssidLen);
}
- if (pu8IEs != NULL) {
+ if (pu8IEs) {
msg.body.con_info.ies_len = IEsLen;
msg.body.con_info.ies = kmalloc(IEsLen, GFP_KERNEL);
memcpy(msg.body.con_info.ies, pu8IEs, IEsLen);
}
- if (hif_drv->enuHostIFstate < HOST_IF_CONNECTING)
- hif_drv->enuHostIFstate = HOST_IF_CONNECTING;
+ if (hif_drv->hif_state < HOST_IF_CONNECTING)
+ hif_drv->hif_state = HOST_IF_CONNECTING;
else
- PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' as state is %d\n", hif_drv->enuHostIFstate);
+ PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' : %d\n",
+ hif_drv->hif_state);
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send message queue: Set join request\n");
return -EFAULT;
}
- hif_drv->hConnectTimer.data = (unsigned long)hif_drv;
- mod_timer(&hif_drv->hConnectTimer,
+ hif_drv->connect_timer.data = (unsigned long)hif_drv;
+ mod_timer(&hif_drv->connect_timer,
jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
- return s32Error;
+ return result;
}
s32 host_int_flush_join_req(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
- if (!join_req) {
- s32Error = -EFAULT;
- return s32Error;
- }
-
+ if (!join_req)
+ return -EFAULT;
if (!hif_drv) {
- s32Error = -EFAULT;
PRINT_ER("Driver is null\n");
- return s32Error;
+ return -EFAULT;
}
msg.id = HOST_IF_MSG_FLUSH_CONNECT;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send message queue: Flush join request\n");
return -EFAULT;
}
- return s32Error;
+ return result;
}
s32 host_int_disconnect(struct host_if_drv *hif_drv, u16 u16ReasonCode)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -3640,78 +3580,82 @@ s32 host_int_disconnect(struct host_if_drv *hif_drv, u16 u16ReasonCode)
msg.id = HOST_IF_MSG_DISCONNECT;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("Failed to send message queue: disconnect\n");
- down(&hif_drv->hSemTestDisconnectBlock);
+ down(&hif_drv->sem_test_disconn_block);
- return s32Error;
+ return result;
}
s32 host_int_disconnect_station(struct host_if_drv *hif_drv, u8 assoc_id)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_DISCONNECT;
- strWID.type = WID_CHAR;
- strWID.val = (s8 *)&assoc_id;
- strWID.size = sizeof(char);
+ wid.id = (u16)WID_DISCONNECT;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)&assoc_id;
+ wid.size = sizeof(char);
return 0;
}
-s32 host_int_get_assoc_req_info(struct host_if_drv *hif_drv, u8 *pu8AssocReqInfo,
- u32 u32AssocReqInfoLen)
+s32 host_int_get_assoc_req_info(struct host_if_drv *hif_drv,
+ u8 *pu8AssocReqInfo,
+ u32 u32AssocReqInfoLen)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_ASSOC_REQ_INFO;
- strWID.type = WID_STR;
- strWID.val = pu8AssocReqInfo;
- strWID.size = u32AssocReqInfoLen;
+ wid.id = (u16)WID_ASSOC_REQ_INFO;
+ wid.type = WID_STR;
+ wid.val = pu8AssocReqInfo;
+ wid.size = u32AssocReqInfoLen;
return 0;
}
-s32 host_int_get_assoc_res_info(struct host_if_drv *hif_drv, u8 *pu8AssocRespInfo,
- u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen)
+s32 host_int_get_assoc_res_info(struct host_if_drv *hif_drv,
+ u8 *pu8AssocRespInfo,
+ u32 u32MaxAssocRespInfoLen,
+ u32 *pu32RcvdAssocRespInfoLen)
{
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
if (!hif_drv) {
PRINT_ER("Driver is null\n");
return -EFAULT;
}
- strWID.id = (u16)WID_ASSOC_RES_INFO;
- strWID.type = WID_STR;
- strWID.val = pu8AssocRespInfo;
- strWID.size = u32MaxAssocRespInfoLen;
+ wid.id = (u16)WID_ASSOC_RES_INFO;
+ wid.type = WID_STR;
+ wid.val = pu8AssocRespInfo;
+ wid.size = u32MaxAssocRespInfoLen;
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
- if (s32Error) {
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
+ if (result) {
*pu32RcvdAssocRespInfoLen = 0;
PRINT_ER("Failed to send association response config packet\n");
return -EINVAL;
} else {
- *pu32RcvdAssocRespInfoLen = strWID.size;
+ *pu32RcvdAssocRespInfoLen = wid.size;
}
- return s32Error;
+ return result;
}
-s32 host_int_get_rx_power_level(struct host_if_drv *hif_drv, u8 *pu8RxPowerLevel,
- u32 u32RxPowerLevelLen)
+s32 host_int_get_rx_power_level(struct host_if_drv *hif_drv,
+ u8 *pu8RxPowerLevel,
+ u32 u32RxPowerLevelLen)
{
- struct wid strWID;
+ struct wid wid;
- strWID.id = (u16)WID_RX_POWER_LEVEL;
- strWID.type = WID_STR;
- strWID.val = pu8RxPowerLevel;
- strWID.size = u32RxPowerLevelLen;
+ wid.id = (u16)WID_RX_POWER_LEVEL;
+ wid.type = WID_STR;
+ wid.val = pu8RxPowerLevel;
+ wid.size = u32RxPowerLevelLen;
return 0;
}
@@ -3743,8 +3687,8 @@ int host_int_set_mac_chnl_num(struct host_if_drv *hif_drv, u8 channel)
int host_int_wait_msg_queue_idle(void)
{
int result = 0;
-
struct host_if_msg msg;
+
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_Q_IDLE;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
@@ -3761,11 +3705,11 @@ int host_int_wait_msg_queue_idle(void)
int host_int_set_wfi_drv_handler(struct host_if_drv *hif_drv)
{
int result = 0;
-
struct host_if_msg msg;
+
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER;
- msg.body.drv.u32Address = get_id_from_handler(hif_drv);
+ msg.body.drv.handler = get_id_from_handler(hif_drv);
msg.drv = hif_drv;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
@@ -3780,11 +3724,11 @@ int host_int_set_wfi_drv_handler(struct host_if_drv *hif_drv)
int host_int_set_operation_mode(struct host_if_drv *hif_drv, u32 mode)
{
int result = 0;
-
struct host_if_msg msg;
+
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_SET_OPERATION_MODE;
- msg.body.mode.u32Mode = mode;
+ msg.body.mode.mode = mode;
msg.drv = hif_drv;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
@@ -3798,7 +3742,7 @@ int host_int_set_operation_mode(struct host_if_drv *hif_drv, u32 mode)
s32 host_int_get_host_chnl_num(struct host_if_drv *hif_drv, u8 *pu8ChNo)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -3811,22 +3755,20 @@ s32 host_int_get_host_chnl_num(struct host_if_drv *hif_drv, u8 *pu8ChNo)
msg.id = HOST_IF_MSG_GET_CHNL;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc mq send fail\n");
- down(&hif_drv->hSemGetCHNL);
+ down(&hif_drv->sem_get_chnl);
*pu8ChNo = ch_no;
- return s32Error;
-
-
+ return result;
}
s32 host_int_get_inactive_time(struct host_if_drv *hif_drv,
const u8 *mac, u32 *pu32InactiveTime)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -3835,129 +3777,122 @@ s32 host_int_get_inactive_time(struct host_if_drv *hif_drv,
}
memset(&msg, 0, sizeof(struct host_if_msg));
-
-
- memcpy(msg.body.mac_info.mac,
- mac, ETH_ALEN);
+ memcpy(msg.body.mac_info.mac, mac, ETH_ALEN);
msg.id = HOST_IF_MSG_GET_INACTIVETIME;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("Failed to send get host channel param's message queue ");
- down(&hif_drv->hSemInactiveTime);
+ down(&hif_drv->sem_inactive_time);
*pu32InactiveTime = inactive_time;
- return s32Error;
+ return result;
}
s32 host_int_test_get_int_wid(struct host_if_drv *hif_drv, u32 *pu32TestMemAddr)
{
-
- s32 s32Error = 0;
- struct wid strWID;
+ s32 result = 0;
+ struct wid wid;
if (!hif_drv) {
PRINT_ER("driver is null\n");
return -EFAULT;
}
- strWID.id = (u16)WID_MEMORY_ADDRESS;
- strWID.type = WID_INT;
- strWID.val = (s8 *)pu32TestMemAddr;
- strWID.size = sizeof(u32);
+ wid.id = (u16)WID_MEMORY_ADDRESS;
+ wid.type = WID_INT;
+ wid.val = (s8 *)pu32TestMemAddr;
+ wid.size = sizeof(u32);
- s32Error = send_config_pkt(GET_CFG, &strWID, 1,
- get_id_from_handler(hif_drv));
+ result = send_config_pkt(GET_CFG, &wid, 1,
+ get_id_from_handler(hif_drv));
- if (s32Error) {
+ if (result) {
PRINT_ER("Failed to get wid value\n");
return -EINVAL;
} else {
PRINT_D(HOSTINF_DBG, "Successfully got wid value\n");
-
}
- return s32Error;
+ return result;
}
s32 host_int_get_rssi(struct host_if_drv *hif_drv, s8 *ps8Rssi)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
- memset(&msg, 0, sizeof(struct host_if_msg));
+ memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_GET_RSSI;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send get host channel param's message queue ");
return -EFAULT;
}
- down(&hif_drv->hSemGetRSSI);
+ down(&hif_drv->sem_get_rssi);
-
- if (ps8Rssi == NULL) {
+ if (!ps8Rssi) {
PRINT_ER("RSS pointer value is null");
return -EFAULT;
}
*ps8Rssi = rssi;
- return s32Error;
+ return result;
}
s32 host_int_get_link_speed(struct host_if_drv *hif_drv, s8 *ps8lnkspd)
{
struct host_if_msg msg;
- s32 s32Error = 0;
- memset(&msg, 0, sizeof(struct host_if_msg));
+ s32 result = 0;
+ memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_GET_LINKSPEED;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send GET_LINKSPEED to message queue ");
return -EFAULT;
}
- down(&hif_drv->hSemGetLINKSPEED);
+ down(&hif_drv->sem_get_link_speed);
-
- if (ps8lnkspd == NULL) {
+ if (!ps8lnkspd) {
PRINT_ER("LINKSPEED pointer value is null");
return -EFAULT;
}
*ps8lnkspd = link_speed;
- return s32Error;
+ return result;
}
s32 host_int_get_statistics(struct host_if_drv *hif_drv, struct rf_info *pstrStatistics)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
- memset(&msg, 0, sizeof(struct host_if_msg));
+ memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_GET_STATISTICS;
msg.body.data = (char *)pstrStatistics;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send get host channel param's message queue ");
return -EFAULT;
}
down(&hif_sema_wait_response);
- return s32Error;
+ return result;
}
s32 host_int_scan(struct host_if_drv *hif_drv, u8 u8ScanSource,
@@ -3966,10 +3901,10 @@ s32 host_int_scan(struct host_if_drv *hif_drv, u8 u8ScanSource,
size_t IEsLen, wilc_scan_result ScanResult,
void *pvUserArg, struct hidden_network *pstrHiddenNetwork)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
- if (!hif_drv || ScanResult == NULL) {
+ if (!hif_drv || !ScanResult) {
PRINT_ER("hif_drv or ScanResult = NULL\n");
return -EFAULT;
}
@@ -3978,7 +3913,7 @@ s32 host_int_scan(struct host_if_drv *hif_drv, u8 u8ScanSource,
msg.id = HOST_IF_MSG_SCAN;
- if (pstrHiddenNetwork != NULL) {
+ if (pstrHiddenNetwork) {
msg.body.scan_info.hidden_network.pstrHiddenNetworkInfo = pstrHiddenNetwork->pstrHiddenNetworkInfo;
msg.body.scan_info.hidden_network.u8ssidnum = pstrHiddenNetwork->u8ssidnum;
@@ -3999,29 +3934,26 @@ s32 host_int_scan(struct host_if_drv *hif_drv, u8 u8ScanSource,
msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL);
memcpy(msg.body.scan_info.ies, pu8IEs, IEsLen);
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Error in sending message queue\n");
return -EINVAL;
}
PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n");
- hif_drv->hScanTimer.data = (unsigned long)hif_drv;
- mod_timer(&hif_drv->hScanTimer,
+ hif_drv->scan_timer.data = (unsigned long)hif_drv;
+ mod_timer(&hif_drv->scan_timer,
jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
- return s32Error;
-
+ return result;
}
s32 hif_set_cfg(struct host_if_drv *hif_drv,
struct cfg_param_val *pstrCfgParamVal)
{
-
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
-
if (!hif_drv) {
PRINT_ER("hif_drv NULL\n");
return -EFAULT;
@@ -4032,17 +3964,16 @@ s32 hif_set_cfg(struct host_if_drv *hif_drv,
msg.body.cfg_info.cfg_attr_info = *pstrCfgParamVal;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
-
- return s32Error;
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ return result;
}
s32 hif_get_cfg(struct host_if_drv *hif_drv, u16 u16WID, u16 *pu16WID_Value)
{
- s32 s32Error = 0;
+ s32 result = 0;
- down(&hif_drv->gtOsCfgValuesSem);
+ down(&hif_drv->sem_cfg_values);
if (!hif_drv) {
PRINT_ER("hif_drv NULL\n");
@@ -4050,92 +3981,85 @@ s32 hif_get_cfg(struct host_if_drv *hif_drv, u16 u16WID, u16 *pu16WID_Value)
}
PRINT_D(HOSTINF_DBG, "Getting configuration parameters\n");
switch (u16WID) {
-
case WID_BSS_TYPE:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.bss_type;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.bss_type;
break;
case WID_AUTH_TYPE:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.auth_type;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.auth_type;
break;
case WID_AUTH_TIMEOUT:
- *pu16WID_Value = hif_drv->strCfgValues.auth_timeout;
+ *pu16WID_Value = hif_drv->cfg_values.auth_timeout;
break;
case WID_POWER_MANAGEMENT:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.power_mgmt_mode;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.power_mgmt_mode;
break;
case WID_SHORT_RETRY_LIMIT:
- *pu16WID_Value = hif_drv->strCfgValues.short_retry_limit;
+ *pu16WID_Value = hif_drv->cfg_values.short_retry_limit;
break;
case WID_LONG_RETRY_LIMIT:
- *pu16WID_Value = hif_drv->strCfgValues.long_retry_limit;
+ *pu16WID_Value = hif_drv->cfg_values.long_retry_limit;
break;
case WID_FRAG_THRESHOLD:
- *pu16WID_Value = hif_drv->strCfgValues.frag_threshold;
+ *pu16WID_Value = hif_drv->cfg_values.frag_threshold;
break;
case WID_RTS_THRESHOLD:
- *pu16WID_Value = hif_drv->strCfgValues.rts_threshold;
+ *pu16WID_Value = hif_drv->cfg_values.rts_threshold;
break;
case WID_PREAMBLE:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.preamble_type;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.preamble_type;
break;
case WID_SHORT_SLOT_ALLOWED:
- *pu16WID_Value = (u16) hif_drv->strCfgValues.short_slot_allowed;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.short_slot_allowed;
break;
case WID_11N_TXOP_PROT_DISABLE:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.txop_prot_disabled;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.txop_prot_disabled;
break;
case WID_BEACON_INTERVAL:
- *pu16WID_Value = hif_drv->strCfgValues.beacon_interval;
+ *pu16WID_Value = hif_drv->cfg_values.beacon_interval;
break;
case WID_DTIM_PERIOD:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.dtim_period;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.dtim_period;
break;
case WID_SITE_SURVEY:
- *pu16WID_Value = (u16)hif_drv->strCfgValues.site_survey_enabled;
+ *pu16WID_Value = (u16)hif_drv->cfg_values.site_survey_enabled;
break;
case WID_SITE_SURVEY_SCAN_TIME:
- *pu16WID_Value = hif_drv->strCfgValues.site_survey_scan_time;
+ *pu16WID_Value = hif_drv->cfg_values.site_survey_scan_time;
break;
case WID_ACTIVE_SCAN_TIME:
- *pu16WID_Value = hif_drv->strCfgValues.active_scan_time;
+ *pu16WID_Value = hif_drv->cfg_values.active_scan_time;
break;
case WID_PASSIVE_SCAN_TIME:
- *pu16WID_Value = hif_drv->strCfgValues.passive_scan_time;
+ *pu16WID_Value = hif_drv->cfg_values.passive_scan_time;
break;
case WID_CURRENT_TX_RATE:
- *pu16WID_Value = hif_drv->strCfgValues.curr_tx_rate;
+ *pu16WID_Value = hif_drv->cfg_values.curr_tx_rate;
break;
default:
break;
}
- up(&hif_drv->gtOsCfgValuesSem);
+ up(&hif_drv->sem_cfg_values);
- return s32Error;
-
-}
-
-void host_int_send_join_leave_info_to_host
- (u16 assocId, u8 *stationAddr, bool joining)
-{
+ return result;
}
static void GetPeriodicRSSI(unsigned long arg)
@@ -4147,8 +4071,8 @@ static void GetPeriodicRSSI(unsigned long arg)
return;
}
- if (hif_drv->enuHostIFstate == HOST_IF_CONNECTED) {
- s32 s32Error = 0;
+ if (hif_drv->hif_state == HOST_IF_CONNECTED) {
+ s32 result = 0;
struct host_if_msg msg;
memset(&msg, 0, sizeof(struct host_if_msg));
@@ -4156,8 +4080,8 @@ static void GetPeriodicRSSI(unsigned long arg)
msg.id = HOST_IF_MSG_GET_RSSI;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error) {
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result) {
PRINT_ER("Failed to send get host channel param's message queue ");
return;
}
@@ -4166,19 +4090,16 @@ static void GetPeriodicRSSI(unsigned long arg)
mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
}
-
-void host_int_send_network_info_to_host
- (u8 *macStartAddress, u16 u16RxFrameLen, s8 s8Rssi)
-{
-}
-
-static u32 clients_count;
-
-s32 host_int_init(struct host_if_drv **hif_drv_handler)
+s32 host_int_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
{
s32 result = 0;
struct host_if_drv *hif_drv;
int err;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
PRINT_D(HOSTINF_DBG, "Initializing host interface for client %d\n", clients_count + 1);
@@ -4207,12 +4128,12 @@ s32 host_int_init(struct host_if_drv **hif_drv_handler)
sema_init(&hif_sema_deinit, 1);
}
- sema_init(&hif_drv->hSemTestKeyBlock, 0);
- sema_init(&hif_drv->hSemTestDisconnectBlock, 0);
- sema_init(&hif_drv->hSemGetRSSI, 0);
- sema_init(&hif_drv->hSemGetLINKSPEED, 0);
- sema_init(&hif_drv->hSemGetCHNL, 0);
- sema_init(&hif_drv->hSemInactiveTime, 0);
+ sema_init(&hif_drv->sem_test_key_block, 0);
+ sema_init(&hif_drv->sem_test_disconn_block, 0);
+ sema_init(&hif_drv->sem_get_rssi, 0);
+ sema_init(&hif_drv->sem_get_link_speed, 0);
+ sema_init(&hif_drv->sem_get_chnl, 0);
+ sema_init(&hif_drv->sem_inactive_time, 0);
PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count);
@@ -4224,7 +4145,8 @@ s32 host_int_init(struct host_if_drv **hif_drv_handler)
goto _fail_;
}
- hif_thread_handler = kthread_run(hostIFthread, NULL, "WILC_kthread");
+ hif_thread_handler = kthread_run(hostIFthread, wilc,
+ "WILC_kthread");
if (IS_ERR(hif_thread_handler)) {
PRINT_ER("Failed to creat Thread\n");
@@ -4236,40 +4158,39 @@ s32 host_int_init(struct host_if_drv **hif_drv_handler)
mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
}
- setup_timer(&hif_drv->hScanTimer, TimerCB_Scan, 0);
-
- setup_timer(&hif_drv->hConnectTimer, TimerCB_Connect, 0);
+ setup_timer(&hif_drv->scan_timer, TimerCB_Scan, 0);
+ setup_timer(&hif_drv->connect_timer, TimerCB_Connect, 0);
+ setup_timer(&hif_drv->remain_on_ch_timer, ListenTimerCB, 0);
- setup_timer(&hif_drv->hRemainOnChannel, ListenTimerCB, 0);
+ sema_init(&hif_drv->sem_cfg_values, 1);
+ down(&hif_drv->sem_cfg_values);
- sema_init(&(hif_drv->gtOsCfgValuesSem), 1);
- down(&hif_drv->gtOsCfgValuesSem);
+ hif_drv->hif_state = HOST_IF_IDLE;
+ hif_drv->cfg_values.site_survey_enabled = SITE_SURVEY_OFF;
+ hif_drv->cfg_values.scan_source = DEFAULT_SCAN;
+ hif_drv->cfg_values.active_scan_time = ACTIVE_SCAN_TIME;
+ hif_drv->cfg_values.passive_scan_time = PASSIVE_SCAN_TIME;
+ hif_drv->cfg_values.curr_tx_rate = AUTORATE;
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
- hif_drv->strCfgValues.site_survey_enabled = SITE_SURVEY_OFF;
- hif_drv->strCfgValues.scan_source = DEFAULT_SCAN;
- hif_drv->strCfgValues.active_scan_time = ACTIVE_SCAN_TIME;
- hif_drv->strCfgValues.passive_scan_time = PASSIVE_SCAN_TIME;
- hif_drv->strCfgValues.curr_tx_rate = AUTORATE;
-
- hif_drv->u64P2p_MgmtTimeout = 0;
+ hif_drv->p2p_timeout = 0;
PRINT_INFO(HOSTINF_DBG, "Initialization values, Site survey value: %d\n Scan source: %d\n Active scan time: %d\n Passive scan time: %d\nCurrent tx Rate = %d\n",
+ hif_drv->cfg_values.site_survey_enabled,
+ hif_drv->cfg_values.scan_source,
+ hif_drv->cfg_values.active_scan_time,
+ hif_drv->cfg_values.passive_scan_time,
+ hif_drv->cfg_values.curr_tx_rate);
- hif_drv->strCfgValues.site_survey_enabled, hif_drv->strCfgValues.scan_source,
- hif_drv->strCfgValues.active_scan_time, hif_drv->strCfgValues.passive_scan_time,
- hif_drv->strCfgValues.curr_tx_rate);
-
- up(&hif_drv->gtOsCfgValuesSem);
+ up(&hif_drv->sem_cfg_values);
clients_count++;
return result;
_fail_timer_2:
- up(&hif_drv->gtOsCfgValuesSem);
- del_timer_sync(&hif_drv->hConnectTimer);
- del_timer_sync(&hif_drv->hScanTimer);
+ up(&hif_drv->sem_cfg_values);
+ del_timer_sync(&hif_drv->connect_timer);
+ del_timer_sync(&hif_drv->scan_timer);
kthread_stop(hif_thread_handler);
_fail_mq_:
wilc_mq_destroy(&hif_msg_q);
@@ -4279,7 +4200,7 @@ _fail_:
s32 host_int_deinit(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
int ret;
@@ -4293,30 +4214,27 @@ s32 host_int_deinit(struct host_if_drv *hif_drv)
terminated_handle = hif_drv;
PRINT_D(HOSTINF_DBG, "De-initializing host interface for client %d\n", clients_count);
- if (del_timer_sync(&hif_drv->hScanTimer)) {
+ if (del_timer_sync(&hif_drv->scan_timer))
PRINT_D(HOSTINF_DBG, ">> Scan timer is active\n");
- }
- if (del_timer_sync(&hif_drv->hConnectTimer)) {
+ if (del_timer_sync(&hif_drv->connect_timer))
PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
- }
if (del_timer_sync(&periodic_rssi))
PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
- del_timer_sync(&hif_drv->hRemainOnChannel);
+ del_timer_sync(&hif_drv->remain_on_ch_timer);
host_int_set_wfi_drv_handler(NULL);
down(&hif_sema_driver);
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
- hif_drv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, NULL,
- hif_drv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
-
- hif_drv->strWILC_UsrScanReq.pfUserScanResult = NULL;
+ 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.scan_result = NULL;
}
- hif_drv->enuHostIFstate = HOST_IF_IDLE;
+ hif_drv->hif_state = HOST_IF_IDLE;
scan_while_connected = false;
@@ -4329,32 +4247,32 @@ s32 host_int_deinit(struct host_if_drv *hif_drv)
msg.id = HOST_IF_MSG_EXIT;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error != 0)
- PRINT_ER("Error in sending deinit's message queue message function: Error(%d)\n", s32Error);
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result != 0)
+ PRINT_ER("Error in sending deinit's message queue message function: Error(%d)\n", result);
down(&hif_sema_thread);
wilc_mq_destroy(&hif_msg_q);
}
- down(&(hif_drv->gtOsCfgValuesSem));
+ down(&hif_drv->sem_cfg_values);
ret = remove_handler_in_list(hif_drv);
if (ret)
- s32Error = -ENOENT;
+ result = -ENOENT;
kfree(hif_drv);
clients_count--;
terminated_handle = NULL;
up(&hif_sema_deinit);
- return s32Error;
+ return result;
}
void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
int id;
struct host_if_drv *hif_drv = NULL;
@@ -4362,9 +4280,6 @@ void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length)
id = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
hif_drv = get_handler_from_id(id);
-
-
-
if (!hif_drv || hif_drv == terminated_handle) {
PRINT_ER("NetworkInfo received but driver not init[%p]\n", hif_drv);
return;
@@ -4379,14 +4294,14 @@ void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length)
msg.body.net_info.buffer = kmalloc(u32Length, GFP_KERNEL);
memcpy(msg.body.net_info.buffer, pu8Buffer, u32Length);
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
- PRINT_ER("Error in sending network info message queue message parameters: Error(%d)\n", s32Error);
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
+ PRINT_ER("Error in sending network info message queue message parameters: Error(%d)\n", result);
}
void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
int id;
struct host_if_drv *hif_drv = NULL;
@@ -4397,14 +4312,13 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
hif_drv = get_handler_from_id(id);
PRINT_D(HOSTINF_DBG, "General asynchronous info packet received\n");
-
if (!hif_drv || hif_drv == terminated_handle) {
PRINT_D(HOSTINF_DBG, "Wifi driver handler is equal to NULL\n");
up(&hif_sema_deinit);
return;
}
- if (!hif_drv->strWILC_UsrConnReq.pfUserConnectResult) {
+ if (!hif_drv->usr_conn_req.conn_result) {
PRINT_ER("Received mac status is not needed when there is no current Connect Reques\n");
up(&hif_sema_deinit);
return;
@@ -4412,7 +4326,6 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
memset(&msg, 0, sizeof(struct host_if_msg));
-
msg.id = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO;
msg.drv = hif_drv;
@@ -4420,16 +4333,16 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
msg.body.async_info.buffer = kmalloc(u32Length, GFP_KERNEL);
memcpy(msg.body.async_info.buffer, pu8Buffer, u32Length);
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
- PRINT_ER("Error in sending message queue asynchronous message info: Error(%d)\n", s32Error);
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
+ PRINT_ER("Error in sending message queue asynchronous message info: Error(%d)\n", result);
up(&hif_sema_deinit);
}
void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
int id;
struct host_if_drv *hif_drv = NULL;
@@ -4437,26 +4350,23 @@ void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length)
id = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
hif_drv = get_handler_from_id(id);
-
PRINT_D(GENERIC_DBG, "Scan notification received %p\n", hif_drv);
if (!hif_drv || hif_drv == terminated_handle)
return;
- if (hif_drv->strWILC_UsrScanReq.pfUserScanResult) {
+ if (hif_drv->usr_scan_req.scan_result) {
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_RCVD_SCAN_COMPLETE;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
- PRINT_ER("Error in sending message queue scan complete parameters: Error(%d)\n", s32Error);
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
+ PRINT_ER("Error in sending message queue scan complete parameters: Error(%d)\n", result);
}
-
return;
-
}
s32 host_int_remain_on_channel(struct host_if_drv *hif_drv, u32 u32SessionID,
@@ -4465,7 +4375,7 @@ s32 host_int_remain_on_channel(struct host_if_drv *hif_drv, u32 u32SessionID,
wilc_remain_on_chan_ready RemainOnChanReady,
void *pvUserArg)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -4476,24 +4386,24 @@ s32 host_int_remain_on_channel(struct host_if_drv *hif_drv, u32 u32SessionID,
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_REMAIN_ON_CHAN;
- msg.body.remain_on_ch.u16Channel = chan;
- msg.body.remain_on_ch.pRemainOnChanExpired = RemainOnChanExpired;
- msg.body.remain_on_ch.pRemainOnChanReady = RemainOnChanReady;
- msg.body.remain_on_ch.pVoid = pvUserArg;
+ msg.body.remain_on_ch.ch = chan;
+ msg.body.remain_on_ch.expired = RemainOnChanExpired;
+ msg.body.remain_on_ch.ready = RemainOnChanReady;
+ msg.body.remain_on_ch.arg = pvUserArg;
msg.body.remain_on_ch.u32duration = u32duration;
- msg.body.remain_on_ch.u32ListenSessionID = u32SessionID;
+ msg.body.remain_on_ch.id = u32SessionID;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc mq send fail\n");
- return s32Error;
+ return result;
}
s32 host_int_ListenStateExpired(struct host_if_drv *hif_drv, u32 u32SessionID)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -4501,23 +4411,23 @@ s32 host_int_ListenStateExpired(struct host_if_drv *hif_drv, u32 u32SessionID)
return -EFAULT;
}
- del_timer(&hif_drv->hRemainOnChannel);
+ del_timer(&hif_drv->remain_on_ch_timer);
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
msg.drv = hif_drv;
- msg.body.remain_on_ch.u32ListenSessionID = u32SessionID;
+ msg.body.remain_on_ch.id = u32SessionID;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc mq send fail\n");
- return s32Error;
+ return result;
}
s32 host_int_frame_register(struct host_if_drv *hif_drv, u16 u16FrameType, bool bReg)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -4531,36 +4441,34 @@ s32 host_int_frame_register(struct host_if_drv *hif_drv, u16 u16FrameType, bool
switch (u16FrameType) {
case ACTION:
PRINT_D(HOSTINF_DBG, "ACTION\n");
- msg.body.reg_frame.u8Regid = ACTION_FRM_IDX;
+ msg.body.reg_frame.reg_id = ACTION_FRM_IDX;
break;
case PROBE_REQ:
PRINT_D(HOSTINF_DBG, "PROBE REQ\n");
- msg.body.reg_frame.u8Regid = PROBE_REQ_IDX;
+ msg.body.reg_frame.reg_id = PROBE_REQ_IDX;
break;
default:
PRINT_D(HOSTINF_DBG, "Not valid frame type\n");
break;
}
- msg.body.reg_frame.u16FrameType = u16FrameType;
- msg.body.reg_frame.bReg = bReg;
+ msg.body.reg_frame.frame_type = u16FrameType;
+ msg.body.reg_frame.reg = bReg;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc mq send fail\n");
- return s32Error;
-
-
+ return result;
}
s32 host_int_add_beacon(struct host_if_drv *hif_drv, u32 u32Interval,
u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head,
u32 u32TailLen, u8 *pu8Tail)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct beacon_attr *pstrSetBeaconParam = &msg.body.beacon_info;
@@ -4579,8 +4487,8 @@ s32 host_int_add_beacon(struct host_if_drv *hif_drv, u32 u32Interval,
pstrSetBeaconParam->dtim_period = u32DTIMPeriod;
pstrSetBeaconParam->head_len = u32HeadLen;
pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL);
- if (pstrSetBeaconParam->head == NULL) {
- s32Error = -ENOMEM;
+ if (!pstrSetBeaconParam->head) {
+ result = -ENOMEM;
goto ERRORHANDLER;
}
pstrSetBeaconParam->tail_len = u32TailLen;
@@ -4588,32 +4496,31 @@ s32 host_int_add_beacon(struct host_if_drv *hif_drv, u32 u32Interval,
if (u32TailLen > 0) {
pstrSetBeaconParam->tail = kmemdup(pu8Tail, u32TailLen,
GFP_KERNEL);
- if (pstrSetBeaconParam->tail == NULL) {
- s32Error = -ENOMEM;
+ if (!pstrSetBeaconParam->tail) {
+ result = -ENOMEM;
goto ERRORHANDLER;
}
} else {
pstrSetBeaconParam->tail = NULL;
}
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc mq send fail\n");
ERRORHANDLER:
- if (s32Error) {
+ if (result) {
kfree(pstrSetBeaconParam->head);
kfree(pstrSetBeaconParam->tail);
}
- return s32Error;
-
+ return result;
}
-s32 host_int_del_beacon(struct host_if_drv *hif_drv)
+int host_int_del_beacon(struct host_if_drv *hif_drv)
{
- s32 s32Error = 0;
+ int result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -4625,20 +4532,19 @@ s32 host_int_del_beacon(struct host_if_drv *hif_drv)
msg.drv = hif_drv;
PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n");
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
+ return result;
}
-s32 host_int_add_station(struct host_if_drv *hif_drv,
- struct add_sta_param *pstrStaParams)
+int host_int_add_station(struct host_if_drv *hif_drv,
+ struct add_sta_param *sta_param)
{
- s32 s32Error = 0;
+ int result = 0;
struct host_if_msg msg;
- struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info;
-
+ struct add_sta_param *add_sta_info = &msg.body.add_sta_info;
if (!hif_drv) {
PRINT_ER("driver is null\n");
@@ -4652,28 +4558,26 @@ s32 host_int_add_station(struct host_if_drv *hif_drv,
msg.id = HOST_IF_MSG_ADD_STATION;
msg.drv = hif_drv;
- memcpy(pstrAddStationMsg, pstrStaParams, sizeof(struct add_sta_param));
- if (pstrAddStationMsg->u8NumRates > 0) {
- u8 *rates = kmalloc(pstrAddStationMsg->u8NumRates, GFP_KERNEL);
-
- if (!rates)
+ memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
+ if (add_sta_info->rates_len > 0) {
+ add_sta_info->rates = kmemdup(sta_param->rates,
+ add_sta_info->rates_len,
+ GFP_KERNEL);
+ if (!add_sta_info->rates)
return -ENOMEM;
-
- memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
- pstrAddStationMsg->pu8Rates = rates;
}
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
+ return result;
}
-s32 host_int_del_station(struct host_if_drv *hif_drv, const u8 *pu8MacAddr)
+int host_int_del_station(struct host_if_drv *hif_drv, const u8 *mac_addr)
{
- s32 s32Error = 0;
+ int result = 0;
struct host_if_msg msg;
- struct del_sta *pstrDelStationMsg = &msg.body.del_sta_info;
+ struct del_sta *del_sta_info = &msg.body.del_sta_info;
if (!hif_drv) {
PRINT_ER("driver is null\n");
@@ -4687,28 +4591,27 @@ s32 host_int_del_station(struct host_if_drv *hif_drv, const u8 *pu8MacAddr)
msg.id = HOST_IF_MSG_DEL_STATION;
msg.drv = hif_drv;
- if (pu8MacAddr == NULL)
- memset(pstrDelStationMsg->mac_addr, 255, ETH_ALEN);
+ if (!mac_addr)
+ eth_broadcast_addr(del_sta_info->mac_addr);
else
- memcpy(pstrDelStationMsg->mac_addr, pu8MacAddr, ETH_ALEN);
+ memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN);
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
+ return result;
}
s32 host_int_del_allstation(struct host_if_drv *hif_drv,
u8 pu8MacAddr[][ETH_ALEN])
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct del_all_sta *pstrDelAllStationMsg = &msg.body.del_all_sta_info;
u8 au8Zero_Buff[ETH_ALEN] = {0};
u32 i;
u8 u8AssocNumb = 0;
-
if (!hif_drv) {
PRINT_ER("driver is null\n");
return -EFAULT;
@@ -4736,25 +4639,24 @@ s32 host_int_del_allstation(struct host_if_drv *hif_drv,
}
if (!u8AssocNumb) {
PRINT_D(CFG80211_DBG, "NO ASSOCIATED STAS\n");
- return s32Error;
+ return result;
}
pstrDelAllStationMsg->assoc_sta = u8AssocNumb;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
down(&hif_sema_wait_response);
- return s32Error;
-
+ return result;
}
s32 host_int_edit_station(struct host_if_drv *hif_drv,
struct add_sta_param *pstrStaParams)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info;
@@ -4771,28 +4673,29 @@ s32 host_int_edit_station(struct host_if_drv *hif_drv,
msg.drv = hif_drv;
memcpy(pstrAddStationMsg, pstrStaParams, sizeof(struct add_sta_param));
- if (pstrAddStationMsg->u8NumRates > 0) {
- u8 *rates = kmalloc(pstrAddStationMsg->u8NumRates, GFP_KERNEL);
+ if (pstrAddStationMsg->rates_len > 0) {
+ u8 *rates = kmalloc(pstrAddStationMsg->rates_len, GFP_KERNEL);
if (!rates)
return -ENOMEM;
- memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
- pstrAddStationMsg->pu8Rates = rates;
+ memcpy(rates, pstrStaParams->rates,
+ pstrAddStationMsg->rates_len);
+ pstrAddStationMsg->rates = rates;
}
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
+ return result;
}
s32 host_int_set_power_mgmt(struct host_if_drv *hif_drv,
bool bIsEnabled,
u32 u32Timeout)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info;
@@ -4813,21 +4716,20 @@ s32 host_int_set_power_mgmt(struct host_if_drv *hif_drv,
pstrPowerMgmtParam->enabled = bIsEnabled;
pstrPowerMgmtParam->timeout = u32Timeout;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
+ return result;
}
s32 host_int_setup_multicast_filter(struct host_if_drv *hif_drv,
bool bIsEnabled,
u32 u32count)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct set_multicast *pstrMulticastFilterParam = &msg.body.multicast_info;
-
if (!hif_drv) {
PRINT_ER("driver is null\n");
return -EFAULT;
@@ -4843,10 +4745,10 @@ s32 host_int_setup_multicast_filter(struct host_if_drv *hif_drv,
pstrMulticastFilterParam->enabled = bIsEnabled;
pstrMulticastFilterParam->cnt = u32count;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
+ return result;
}
static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
@@ -4868,7 +4770,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
u16IEsLen = ptstrNetworkInfo->u16IEsLen;
pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL);
- if (pNewJoinBssParam != NULL) {
+ if (pNewJoinBssParam) {
pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod;
pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod;
pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo;
@@ -4884,9 +4786,9 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
pNewJoinBssParam->supp_rates[0] = suppRatesNo;
index += 2;
- for (i = 0; i < suppRatesNo; i++) {
+ for (i = 0; i < suppRatesNo; i++)
pNewJoinBssParam->supp_rates[i + 1] = pu8IEs[index + i];
- }
+
index += suppRatesNo;
continue;
} else if (pu8IEs[index] == EXT_SUPP_RATES_IE) {
@@ -4896,9 +4798,9 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
else
pNewJoinBssParam->supp_rates[0] += extSuppRatesNo;
index += 2;
- for (i = 0; i < (pNewJoinBssParam->supp_rates[0] - suppRatesNo); i++) {
+ for (i = 0; i < (pNewJoinBssParam->supp_rates[0] - suppRatesNo); i++)
pNewJoinBssParam->supp_rates[suppRatesNo + i + 1] = pu8IEs[index + i];
- }
+
index += extSuppRatesNo;
continue;
} else if (pu8IEs[index] == HT_CAPABILITY_IE) {
@@ -4947,7 +4849,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
memcpy(pNewJoinBssParam->interval, pu8IEs + u16P2P_count, 4);
u16P2P_count += 4;
- memcpy(pNewJoinBssParam->au8StartTime, pu8IEs + u16P2P_count, 4);
+ memcpy(pNewJoinBssParam->start_time, pu8IEs + u16P2P_count, 4);
index += pu8IEs[index + 1] + 2;
continue;
@@ -4973,9 +4875,9 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
pcipherCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex];
rsnIndex += 2;
- for (i = pcipherTotalCount, j = 0; i < pcipherCount + pcipherTotalCount && i < 3; i++, j++) {
+ for (i = pcipherTotalCount, j = 0; i < pcipherCount + pcipherTotalCount && i < 3; i++, j++)
pNewJoinBssParam->rsn_pcip_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1];
- }
+
pcipherTotalCount += pcipherCount;
rsnIndex += jumpOffset;
@@ -4984,9 +4886,9 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
authCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex];
rsnIndex += 2;
- for (i = authTotalCount, j = 0; i < authTotalCount + authCount; i++, j++) {
+ for (i = authTotalCount, j = 0; i < authTotalCount + authCount; i++, j++)
pNewJoinBssParam->rsn_auth_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1];
- }
+
authTotalCount += authCount;
rsnIndex += jumpOffset;
@@ -5000,19 +4902,15 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
continue;
} else
index += pu8IEs[index + 1] + 2;
-
}
-
-
}
return (void *)pNewJoinBssParam;
-
}
void host_int_freeJoinParams(void *pJoinParams)
{
- if ((struct bss_param *)pJoinParams != NULL)
+ if ((struct bss_param *)pJoinParams)
kfree((struct bss_param *)pJoinParams);
else
PRINT_ER("Unable to FREE null pointer\n");
@@ -5020,7 +4918,7 @@ void host_int_freeJoinParams(void *pJoinParams)
s32 host_int_delBASession(struct host_if_drv *hif_drv, char *pBSSID, char TID)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct ba_session_info *pBASessionInfo = &msg.body.session_info;
@@ -5033,24 +4931,24 @@ s32 host_int_delBASession(struct host_if_drv *hif_drv, char *pBSSID, char TID)
msg.id = HOST_IF_MSG_DEL_BA_SESSION;
- memcpy(pBASessionInfo->au8Bssid, pBSSID, ETH_ALEN);
- pBASessionInfo->u8Ted = TID;
+ memcpy(pBASessionInfo->bssid, pBSSID, ETH_ALEN);
+ pBASessionInfo->tid = TID;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
down(&hif_sema_wait_response);
- return s32Error;
+ return result;
}
s32 host_int_del_All_Rx_BASession(struct host_if_drv *hif_drv,
char *pBSSID,
char TID)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
struct ba_session_info *pBASessionInfo = &msg.body.session_info;
@@ -5063,22 +4961,22 @@ s32 host_int_del_All_Rx_BASession(struct host_if_drv *hif_drv,
msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS;
- memcpy(pBASessionInfo->au8Bssid, pBSSID, ETH_ALEN);
- pBASessionInfo->u8Ted = TID;
+ memcpy(pBASessionInfo->bssid, pBSSID, ETH_ALEN);
+ pBASessionInfo->tid = TID;
msg.drv = hif_drv;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
down(&hif_sema_wait_response);
- return s32Error;
+ return result;
}
s32 host_int_setup_ipaddress(struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
return 0;
@@ -5096,18 +4994,16 @@ s32 host_int_setup_ipaddress(struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx)
msg.drv = hif_drv;
msg.body.ip_info.idx = idx;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
-
-
+ return result;
}
s32 host_int_get_ipaddress(struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx)
{
- s32 s32Error = 0;
+ s32 result = 0;
struct host_if_msg msg;
if (!hif_drv) {
@@ -5123,11 +5019,9 @@ s32 host_int_get_ipaddress(struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx)
msg.drv = hif_drv;
msg.body.ip_info.idx = idx;
- s32Error = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (s32Error)
+ result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (result)
PRINT_ER("wilc_mq_send fail\n");
- return s32Error;
-
-
+ return result;
}
diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h
index 146a60f52cb7..57e1d424afdc 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -1,12 +1,3 @@
-/*!
- * @file host_interface.h
- * @brief File containg host interface APIs
- * @author zsalah
- * @sa host_interface.c
- * @date 8 March 2012
- * @version 1.0
- */
-
#ifndef HOST_INT_H
#define HOST_INT_H
@@ -19,8 +10,12 @@
#define STATION_MODE 0x02
#define GO_MODE 0x03
#define CLIENT_MODE 0x04
+#define ACTION 0xD0
+#define PROBE_REQ 0x40
+#define PROBE_RESP 0x50
-
+#define ACTION_FRM_IDX 0
+#define PROBE_REQ_IDX 1
#define MAX_NUM_STA 9
#define ACTIVE_SCAN_TIME 10
#define PASSIVE_SCAN_TIME 1200
@@ -58,11 +53,11 @@
#define NUM_CONCURRENT_IFC 2
struct rf_info {
- u8 u8LinkSpeed;
- s8 s8RSSI;
- u32 u32TxCount;
- u32 u32RxCount;
- u32 u32TxFailureCount;
+ u8 link_speed;
+ s8 rssi;
+ u32 tx_cnt;
+ u32 rx_cnt;
+ u32 tx_fail_cnt;
};
enum host_if_state {
@@ -168,36 +163,23 @@ enum conn_event {
enum KEY_TYPE {
WEP,
- WPARxGtk,
- WPAPtk,
+ WPA_RX_GTK,
+ WPA_PTK,
PMKSA,
};
-
-/*Scan callBack function definition*/
typedef void (*wilc_scan_result)(enum scan_event, tstrNetworkInfo *,
void *, void *);
-/*Connect callBack function definition*/
typedef void (*wilc_connect_result)(enum conn_event,
tstrConnectInfo *,
u8,
tstrDisconnectNotifInfo *,
void *);
-typedef void (*wilc_remain_on_chan_expired)(void *, u32); /*Remain on channel expiration callback function*/
-typedef void (*wilc_remain_on_chan_ready)(void *); /*Remain on channel callback function*/
+typedef void (*wilc_remain_on_chan_expired)(void *, u32);
+typedef void (*wilc_remain_on_chan_ready)(void *);
-/*!
- * @struct rcvd_net_info
- * @brief Structure to hold Received Asynchronous Network info
- * @details
- * @todo
- * @sa
- * @author Mostafa Abu Bakr
- * @date 25 March 2012
- * @version 1.0
- */
struct rcvd_net_info {
u8 *buffer;
u32 len;
@@ -214,77 +196,63 @@ struct hidden_network {
};
struct user_scan_req {
- /* Scan user call back function */
- wilc_scan_result pfUserScanResult;
-
- /* User specific parameter to be delivered through the Scan User Callback function */
- void *u32UserScanPvoid;
-
- u32 u32RcvdChCount;
- struct found_net_info astrFoundNetworkInfo[MAX_NUM_SCANNED_NETWORKS];
+ wilc_scan_result scan_result;
+ void *arg;
+ u32 rcvd_ch_cnt;
+ struct found_net_info net_info[MAX_NUM_SCANNED_NETWORKS];
};
struct user_conn_req {
u8 *pu8bssid;
u8 *pu8ssid;
u8 u8security;
- enum AUTHTYPE tenuAuth_type;
- size_t ssidLen;
- u8 *pu8ConnReqIEs;
- size_t ConnReqIEsLen;
- /* Connect user call back function */
- wilc_connect_result pfUserConnectResult;
- bool IsHTCapable;
- /* User specific parameter to be delivered through the Connect User Callback function */
- void *u32UserConnectPvoid;
+ enum AUTHTYPE auth_type;
+ size_t ssid_len;
+ u8 *ies;
+ size_t ies_len;
+ wilc_connect_result conn_result;
+ bool ht_capable;
+ void *arg;
};
struct drv_handler {
- u32 u32Address;
+ u32 handler;
};
struct op_mode {
- u32 u32Mode;
+ u32 mode;
};
struct set_mac_addr {
- u8 u8MacAddress[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
};
struct get_mac_addr {
- u8 *u8MacAddress;
+ u8 *mac_addr;
};
struct ba_session_info {
- u8 au8Bssid[ETH_ALEN];
- u8 u8Ted;
- u16 u16BufferSize;
- u16 u16SessionTimeout;
+ u8 bssid[ETH_ALEN];
+ u8 tid;
+ u16 buf_size;
+ u16 time_out;
};
struct remain_ch {
- u16 u16Channel;
+ u16 ch;
u32 u32duration;
- wilc_remain_on_chan_expired pRemainOnChanExpired;
- wilc_remain_on_chan_ready pRemainOnChanReady;
- void *pVoid;
- u32 u32ListenSessionID;
+ wilc_remain_on_chan_expired expired;
+ wilc_remain_on_chan_ready ready;
+ void *arg;
+ u32 id;
};
struct reg_frame {
- bool bReg;
- u16 u16FrameType;
- u8 u8Regid;
+ bool reg;
+ u16 frame_type;
+ u8 reg_id;
};
-
-#define ACTION 0xD0
-#define PROBE_REQ 0x40
-#define PROBE_RESP 0x50
-#define ACTION_FRM_IDX 0
-#define PROBE_REQ_IDX 1
-
-
enum p2p_listen_state {
P2P_IDLE,
P2P_LISTEN,
@@ -292,872 +260,165 @@ enum p2p_listen_state {
};
struct host_if_drv {
- struct user_scan_req strWILC_UsrScanReq;
- struct user_conn_req strWILC_UsrConnReq;
-
- /*Remain on channel struvture*/
- struct remain_ch strHostIfRemainOnChan;
- u8 u8RemainOnChan_pendingreq;
- u64 u64P2p_MgmtTimeout;
- u8 u8P2PConnect;
-
- enum host_if_state enuHostIFstate;
-
- u8 au8AssociatedBSSID[ETH_ALEN];
- struct cfg_param_val strCfgValues;
-/* semaphores */
- struct semaphore gtOsCfgValuesSem;
- struct semaphore hSemTestKeyBlock;
-
- struct semaphore hSemTestDisconnectBlock;
- struct semaphore hSemGetRSSI;
- struct semaphore hSemGetLINKSPEED;
- struct semaphore hSemGetCHNL;
- struct semaphore hSemInactiveTime;
-/* timer handlers */
- struct timer_list hScanTimer;
- struct timer_list hConnectTimer;
- struct timer_list hRemainOnChannel;
+ 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;
+ u64 p2p_timeout;
+ u8 p2p_connect;
+
+ enum host_if_state hif_state;
+
+ u8 assoc_bssid[ETH_ALEN];
+ struct cfg_param_val cfg_values;
+
+ struct semaphore sem_cfg_values;
+ struct semaphore sem_test_key_block;
+ struct semaphore sem_test_disconn_block;
+ struct semaphore sem_get_rssi;
+ struct semaphore sem_get_link_speed;
+ struct semaphore sem_get_chnl;
+ struct semaphore sem_inactive_time;
+
+ struct timer_list scan_timer;
+ struct timer_list connect_timer;
+ struct timer_list remain_on_ch_timer;
bool IFC_UP;
};
struct add_sta_param {
- u8 au8BSSID[ETH_ALEN];
- u16 u16AssocID;
- u8 u8NumRates;
- const u8 *pu8Rates;
- bool bIsHTSupported;
- u16 u16HTCapInfo;
- u8 u8AmpduParams;
- u8 au8SuppMCsSet[16];
- u16 u16HTExtParams;
- u32 u32TxBeamformingCap;
- u8 u8ASELCap;
- u16 u16FlagsMask; /*<! Determines which of u16FlagsSet were changed>*/
- u16 u16FlagsSet; /*<! Decoded according to tenuWILC_StaFlag */
+ u8 bssid[ETH_ALEN];
+ u16 aid;
+ u8 rates_len;
+ const u8 *rates;
+ bool ht_supported;
+ u16 ht_capa_info;
+ u8 ht_ampdu_params;
+ u8 ht_supp_mcs_set[16];
+ u16 ht_ext_params;
+ u32 ht_tx_bf_cap;
+ u8 ht_ante_sel;
+ u16 flags_mask;
+ u16 flags_set;
};
-/*****************************************************************************/
-/* */
-/* Host Interface API */
-/* */
-/*****************************************************************************/
-
-/**
- * @brief removes wpa/wpa2 keys
- * @details only in BSS STA mode if External Supplicant support is enabled.
- * removes all WPA/WPA2 station key entries from MAC hardware.
- * @param[in,out] handle to the wifi driver
- * @param[in] 6 bytes of Station Adress in the station entry table
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_remove_key(struct host_if_drv *hWFIDrv, const u8 *pu8StaAddress);
-/**
- * @brief removes WEP key
- * @details valid only in BSS STA mode if External Supplicant support is enabled.
- * remove a WEP key entry from MAC HW.
- * The BSS Station automatically finds the index of the entry using its
- * BSS ID and removes that entry from the MAC hardware.
- * @param[in,out] handle to the wifi driver
- * @param[in] 6 bytes of Station Adress in the station entry table
- * @return Error code indicating success/failure
- * @note NO need for the STA add since it is not used for processing
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
int host_int_remove_wep_key(struct host_if_drv *wfi_drv, u8 index);
-/**
- * @brief sets WEP deafault key
- * @details Sets the index of the WEP encryption key in use,
- * in the key table
- * @param[in,out] handle to the wifi driver
- * @param[in] key index ( 0, 1, 2, 3)
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_set_WEPDefaultKeyID(struct host_if_drv *hWFIDrv, u8 u8Index);
-
-/**
- * @brief sets WEP deafault key
- * @details valid only in BSS STA mode if External Supplicant support is enabled.
- * sets WEP key entry into MAC hardware when it receives the
- * corresponding request from NDIS.
- * @param[in,out] handle to the wifi driver
- * @param[in] message containing WEP Key in the following format
- *|---------------------------------------|
- *|Key ID Value | Key Length | Key |
- *|-------------|------------|------------|
- | 1byte | 1byte | Key Length |
- ||---------------------------------------|
- |
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_add_wep_key_bss_sta(struct host_if_drv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx);
-/**
- * @brief host_int_add_wep_key_bss_ap
- * @details valid only in AP mode if External Supplicant support is enabled.
- * sets WEP key entry into MAC hardware when it receives the
- * corresponding request from NDIS.
- * @param[in,out] handle to the wifi driver
- *
- *
- * @return Error code indicating success/failure
- * @note
- * @author mdaftedar
- * @date 28 Feb 2013
- * @version 1.0
- */
-s32 host_int_add_wep_key_bss_ap(struct host_if_drv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, enum AUTHTYPE tenuAuth_type);
-
-/**
- * @brief adds ptk Key
- * @details
- * @param[in,out] handle to the wifi driver
- * @param[in] message containing PTK Key in the following format
- *|-------------------------------------------------------------------------|
- *|Sta Adress | Key Length | Temporal Key | Rx Michael Key |Tx Michael Key |
- *|-----------|------------|---------------|----------------|---------------|
- | 6 bytes | 1byte | 16 bytes | 8 bytes | 8 bytes |
- ||-------------------------------------------------------------------------|
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_add_ptk(struct host_if_drv *hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
- const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx);
-
-/**
- * @brief host_int_get_inactive_time
- * @details
- * @param[in,out] handle to the wifi driver
- * @param[in] message containing inactive time
- *
- * @return Error code indicating success/failure
- * @note
- * @author mdaftedar
- * @date 15 April 2013
- * @version 1.0
- */
-s32 host_int_get_inactive_time(struct host_if_drv *hWFIDrv, const u8 *mac, u32 *pu32InactiveTime);
-
-/**
- * @brief adds Rx GTk Key
- * @details
- * @param[in,out] handle to the wifi driver
- * @param[in] message containing Rx GTK Key in the following format
- *|----------------------------------------------------------------------------|
- *|Sta Address | Key RSC | KeyID | Key Length | Temporal Key | Rx Michael Key |
- *|------------|---------|-------|------------|---------------|----------------|
- | 6 bytes | 8 byte |1 byte | 1 byte | 16 bytes | 8 bytes |
- ||----------------------------------------------------------------------------|
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_add_rx_gtk(struct host_if_drv *hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
- u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
- const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode);
-
-
-/**
- * @brief adds Tx GTk Key
- * @details
- * @param[in,out] handle to the wifi driver
- * @param[in] message containing Tx GTK Key in the following format
- *|----------------------------------------------------|
- | KeyID | Key Length | Temporal Key | Tx Michael Key |
- ||-------|------------|--------------|----------------|
- ||1 byte | 1 byte | 16 bytes | 8 bytes |
- ||----------------------------------------------------|
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx);
-
-/**
- * @brief caches the pmkid
- * @details valid only in BSS STA mode if External Supplicant
- * support is enabled. This Function sets the PMKID in firmware
- * when host drivr receives the corresponding request from NDIS.
- * The firmware then includes theset PMKID in the appropriate
- * management frames
- * @param[in,out] handle to the wifi driver
- * @param[in] message containing PMKID Info in the following format
- *|-----------------------------------------------------------------|
- *|NumEntries | BSSID[1] | PMKID[1] | ... | BSSID[K] | PMKID[K] |
- *|-----------|------------|----------|-------|----------|----------|
- | 1 | 6 | 16 | ... | 6 | 16 |
- ||-----------------------------------------------------------------|
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-
-s32 host_int_set_pmkid_info(struct host_if_drv *hWFIDrv, struct host_if_pmkid_attr *pu8PmkidInfoArray);
-/**
- * @brief gets the cached the pmkid info
- * @details valid only in BSS STA mode if External Supplicant
- * support is enabled. This Function sets the PMKID in firmware
- * when host drivr receives the corresponding request from NDIS.
- * The firmware then includes theset PMKID in the appropriate
- * management frames
- * @param[in,out] handle to the wifi driver,
- *
- * message containing PMKID Info in the following format
- *|-----------------------------------------------------------------|
- *|NumEntries | BSSID[1] | PMKID[1] | ... | BSSID[K] | PMKID[K] |
- *|-----------|------------|----------|-------|----------|----------|
- | 1 | 6 | 16 | ... | 6 | 16 |
- ||-----------------------------------------------------------------|
- * @param[in]
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-
+int host_int_set_wep_default_key(struct host_if_drv *hif_drv, u8 index);
+int host_int_add_wep_key_bss_sta(struct host_if_drv *hif_drv,
+ const u8 *key, u8 len, u8 index);
+int host_int_add_wep_key_bss_ap(struct host_if_drv *hif_drv,
+ const u8 *key, u8 len, u8 index, u8 mode,
+ enum AUTHTYPE auth_type);
+s32 host_int_add_ptk(struct host_if_drv *hWFIDrv, const u8 *pu8Ptk,
+ u8 u8PtkKeylen, const u8 *mac_addr,
+ const u8 *pu8RxMic, const u8 *pu8TxMic,
+ u8 mode, u8 u8Ciphermode, u8 u8Idx);
+s32 host_int_get_inactive_time(struct host_if_drv *hWFIDrv, const u8 *mac,
+ u32 *pu32InactiveTime);
+s32 host_int_add_rx_gtk(struct host_if_drv *hWFIDrv, const u8 *pu8RxGtk,
+ u8 u8GtkKeylen, u8 u8KeyIdx,
+ u32 u32KeyRSClen, const u8 *KeyRSC,
+ const u8 *pu8RxMic, const u8 *pu8TxMic,
+ u8 mode, u8 u8Ciphermode);
+s32 host_int_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen,
+ u8 *pu8TxGtk, u8 u8KeyIdx);
+s32 host_int_set_pmkid_info(struct host_if_drv *hWFIDrv,
+ struct host_if_pmkid_attr *pu8PmkidInfoArray);
s32 host_int_get_pmkid_info(struct host_if_drv *hWFIDrv, u8 *pu8PmkidInfoArray,
- u32 u32PmkidInfoLen);
-
-/**
- * @brief sets the pass phrase
- * @details AP/STA mode. This function gives the pass phrase used to
- * generate the Pre-Shared Key when WPA/WPA2 is enabled
- * The length of the field can vary from 8 to 64 bytes,
- * the lower layer should get the
- * @param[in,out] handle to the wifi driver,
- * @param[in] String containing PSK
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_set_RSNAConfigPSKPassPhrase(struct host_if_drv *hWFIDrv, u8 *pu8PassPhrase,
- u8 u8Psklength);
-/**
- * @brief gets the pass phrase
- * @details AP/STA mode. This function gets the pass phrase used to
- * generate the Pre-Shared Key when WPA/WPA2 is enabled
- * The length of the field can vary from 8 to 64 bytes,
- * the lower layer should get the
- * @param[in,out] handle to the wifi driver,
- * String containing PSK
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
+ u32 u32PmkidInfoLen);
+s32 host_int_set_RSNAConfigPSKPassPhrase(struct host_if_drv *hWFIDrv,
+ u8 *pu8PassPhrase,
+ u8 u8Psklength);
s32 host_int_get_RSNAConfigPSKPassPhrase(struct host_if_drv *hWFIDrv,
- u8 *pu8PassPhrase, u8 u8Psklength);
-
-/**
- * @brief gets mac address
- * @details
- * @param[in,out] handle to the wifi driver,
- *
- * @return Error code indicating success/failure
- * @note
- * @author mdaftedar
- * @date 19 April 2012
- * @version 1.0
- */
-s32 host_int_get_MacAddress(struct host_if_drv *hWFIDrv, u8 *pu8MacAddress);
-
-/**
- * @brief sets mac address
- * @details
- * @param[in,out] handle to the wifi driver,
- *
- * @return Error code indicating success/failure
- * @note
- * @author mabubakr
- * @date 16 July 2012
- * @version 1.0
- */
+ u8 *pu8PassPhrase, u8 u8Psklength);
+s32 hif_get_mac_address(struct host_if_drv *hWFIDrv, u8 *pu8MacAddress);
s32 host_int_set_MacAddress(struct host_if_drv *hWFIDrv, u8 *pu8MacAddress);
-
-/**
- * @brief wait until msg q is empty
- * @details
- * @param[in,out]
- *
- * @return Error code indicating success/failure
- * @note
- * @author asobhy
- * @date 19 march 2014
- * @version 1.0
- */
int host_int_wait_msg_queue_idle(void);
-
-/**
- * @brief sets a start scan request
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] Scan Source one of the following values
- * DEFAULT_SCAN 0
- * USER_SCAN BIT0
- * OBSS_PERIODIC_SCAN BIT1
- * OBSS_ONETIME_SCAN BIT2
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-
s32 host_int_set_start_scan_req(struct host_if_drv *hWFIDrv, u8 scanSource);
-/**
- * @brief gets scan source of the last scan
- * @details
- * @param[in,out] handle to the wifi driver,
- * Scan Source one of the following values
- * DEFAULT_SCAN 0
- * USER_SCAN BIT0
- * OBSS_PERIODIC_SCAN BIT1
- * OBSS_ONETIME_SCAN BIT2
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_get_start_scan_req(struct host_if_drv *hWFIDrv, u8 *pu8ScanSource);
-
-/**
- * @brief sets a join request
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] Index of the bss descriptor
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-
s32 host_int_set_join_req(struct host_if_drv *hWFIDrv, u8 *pu8bssid,
- const u8 *pu8ssid, size_t ssidLen,
- const u8 *pu8IEs, size_t IEsLen,
- wilc_connect_result pfConnectResult, void *pvUserArg,
- u8 u8security, enum AUTHTYPE tenuAuth_type,
- u8 u8channel,
- void *pJoinParams);
-
-/**
- * @brief Flush a join request parameters to FW, but actual connection
- * @details The function is called in situation where WILC is connected to AP and
- * required to switch to hybrid FW for P2P connection
- * @param[in] handle to the wifi driver,
- * @return Error code indicating success/failure
- * @note
- * @author Amr Abdel-Moghny
- * @date 19 DEC 2013
- * @version 8.0
- */
-
+ const u8 *pu8ssid, size_t ssidLen,
+ const u8 *pu8IEs, size_t IEsLen,
+ wilc_connect_result pfConnectResult, void *pvUserArg,
+ u8 u8security, enum AUTHTYPE tenuAuth_type,
+ u8 u8channel, void *pJoinParams);
s32 host_int_flush_join_req(struct host_if_drv *hWFIDrv);
-
-
-/**
- * @brief disconnects from the currently associated network
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] Reason Code of the Disconnection
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_disconnect(struct host_if_drv *hWFIDrv, u16 u16ReasonCode);
-
-/**
- * @brief disconnects a sta
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] Association Id of the station to be disconnected
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_disconnect_station(struct host_if_drv *hWFIDrv, u8 assoc_id);
-/**
- * @brief gets a Association request info
- * @details
- * @param[in,out] handle to the wifi driver,
- * Message containg assoc. req info in the following format
- * ------------------------------------------------------------------------
- | Management Frame Format |
- ||-------------------------------------------------------------------|
- ||Frame Control|Duration|DA|SA|BSSID|Sequence Control|Frame Body|FCS |
- ||-------------|--------|--|--|-----|----------------|----------|----|
- | 2 |2 |6 |6 |6 | 2 |0 - 2312 | 4 |
- ||-------------------------------------------------------------------|
- | |
- | Association Request Frame - Frame Body |
- ||-------------------------------------------------------------------|
- | Capability Information | Listen Interval | SSID | Supported Rates |
- ||------------------------|-----------------|------|-----------------|
- | 2 | 2 | 2-34 | 3-10 |
- | ---------------------------------------------------------------------
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-
-s32 host_int_get_assoc_req_info(struct host_if_drv *hWFIDrv, u8 *pu8AssocReqInfo,
- u32 u32AssocReqInfoLen);
-/**
- * @brief gets a Association Response info
- * @details
- * @param[in,out] handle to the wifi driver,
- * Message containg assoc. resp info
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-
-s32 host_int_get_assoc_res_info(struct host_if_drv *hWFIDrv, u8 *pu8AssocRespInfo,
- u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen);
-/**
- * @brief gets a Association Response info
- * @details Valid only in STA mode. This function gives the RSSI
- * values observed in all the channels at the time of scanning.
- * The length of the field is 1 greater that the total number of
- * channels supported. Byte 0 contains the number of channels while
- * each of Byte N contains the observed RSSI value for the channel index N.
- * @param[in,out] handle to the wifi driver,
- * array of scanned channels' RSSI
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_get_rx_power_level(struct host_if_drv *hWFIDrv, u8 *pu8RxPowerLevel,
- u32 u32RxPowerLevelLen);
-
-/**
- * @brief sets a channel
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] Index of the channel to be set
- *|-------------------------------------------------------------------|
- | CHANNEL1 CHANNEL2 .... CHANNEL14 |
- | Input: 1 2 14 |
- ||-------------------------------------------------------------------|
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
+s32 host_int_get_assoc_req_info(struct host_if_drv *hWFIDrv,
+ u8 *pu8AssocReqInfo,
+ u32 u32AssocReqInfoLen);
+s32 host_int_get_assoc_res_info(struct host_if_drv *hWFIDrv,
+ u8 *pu8AssocRespInfo,
+ u32 u32MaxAssocRespInfoLen,
+ u32 *pu32RcvdAssocRespInfoLen);
+s32 host_int_get_rx_power_level(struct host_if_drv *hWFIDrv,
+ u8 *pu8RxPowerLevel,
+ u32 u32RxPowerLevelLen);
int host_int_set_mac_chnl_num(struct host_if_drv *wfi_drv, u8 channel);
-
-/**
- * @brief gets the current channel index
- * @details
- * @param[in,out] handle to the wifi driver,
- * current channel index
- *|-----------------------------------------------------------------------|
- | CHANNEL1 CHANNEL2 .... CHANNEL14 |
- | Input: 1 2 14 |
- ||-----------------------------------------------------------------------|
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_get_host_chnl_num(struct host_if_drv *hWFIDrv, u8 *pu8ChNo);
-/**
- * @brief gets the sta rssi
- * @details gets the currently maintained RSSI value for the station.
- * The received signal strength value in dB.
- * The range of valid values is -128 to 0.
- * @param[in,out] handle to the wifi driver,
- * rssi value in dB
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_get_rssi(struct host_if_drv *hWFIDrv, s8 *ps8Rssi);
s32 host_int_get_link_speed(struct host_if_drv *hWFIDrv, s8 *ps8lnkspd);
-/**
- * @brief scans a set of channels
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] Scan source
- * Scan Type PASSIVE_SCAN = 0,
- * ACTIVE_SCAN = 1
- * Channels Array
- * Channels Array length
- * Scan Callback function
- * User Argument to be delivered back through the Scan Cllback function
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
s32 host_int_scan(struct host_if_drv *hWFIDrv, u8 u8ScanSource,
- u8 u8ScanType, u8 *pu8ChnlFreqList,
- u8 u8ChnlListLen, const u8 *pu8IEs,
- size_t IEsLen, wilc_scan_result ScanResult,
- void *pvUserArg,
- struct hidden_network *pstrHiddenNetwork);
-/**
- * @brief sets configuration wids values
- * @details
- * @param[in,out] handle to the wifi driver,
- * @param[in] WID, WID value
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 hif_set_cfg(struct host_if_drv *hWFIDrv, struct cfg_param_val *pstrCfgParamVal);
-
-/**
- * @brief gets configuration wids values
- * @details
- * @param[in,out] handle to the wifi driver,
- * WID value
- * @param[in] WID,
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
+ u8 u8ScanType, u8 *pu8ChnlFreqList,
+ u8 u8ChnlListLen, const u8 *pu8IEs,
+ size_t IEsLen, wilc_scan_result ScanResult,
+ void *pvUserArg, struct hidden_network *pstrHiddenNetwork);
+s32 hif_set_cfg(struct host_if_drv *hWFIDrv,
+ struct cfg_param_val *pstrCfgParamVal);
s32 hif_get_cfg(struct host_if_drv *hWFIDrv, u16 u16WID, u16 *pu16WID_Value);
-/*****************************************************************************/
-/* Notification Functions */
-/*****************************************************************************/
-/**
- * @brief notifies host with join and leave requests
- * @details This function prepares an Information frame having the
- * information about a joining/leaving station.
- * @param[in,out] handle to the wifi driver,
- * @param[in] 6 byte Sta Adress
- * Join or leave flag:
- * Join = 1,
- * Leave =0
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-void host_int_send_join_leave_info_to_host
- (u16 assocId, u8 *stationAddr, bool joining);
-
-/**
- * @brief notifies host with stations found in scan
- * @details sends the beacon/probe response from scan
- * @param[in,out] handle to the wifi driver,
- * @param[in] Sta Address,
- * Frame length,
- * Rssi of the Station found
- * @return Error code indicating success/failure
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-void host_int_send_network_info_to_host
- (u8 *macStartAddress, u16 u16RxFrameLen, s8 s8Rssi);
-
-/**
- * @brief host interface initialization function
- * @details
- * @param[in,out] handle to the wifi driver,
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
-s32 host_int_init(struct host_if_drv **phWFIDrv);
-
-/**
- * @brief host interface initialization function
- * @details
- * @param[in,out] handle to the wifi driver,
- * @note
- * @author zsalah
- * @date 8 March 2012
- * @version 1.0
- */
+s32 host_int_init(struct net_device *dev, struct host_if_drv **phWFIDrv);
s32 host_int_deinit(struct host_if_drv *hWFIDrv);
-
-
-/*!
- * @fn s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv,u8 u8Index)
- * @brief Sends a beacon to the firmware to be transmitted over the air
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] u32Interval Beacon Interval. Period between two successive beacons on air
- * @param[in] u32DTIMPeriod DTIM Period. Indicates how many Beacon frames
- * (including the current frame) appear before the next DTIM
- * @param[in] u32Headlen Length of the head buffer in bytes
- * @param[in] pu8Head Pointer to the beacon's head buffer. Beacon's head
- * is the part from the beacon's start till the TIM element, NOT including the TIM
- * @param[in] u32Taillen Length of the tail buffer in bytes
- * @param[in] pu8Tail Pointer to the beacon's tail buffer. Beacon's tail
- * starts just after the TIM inormation element
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 10 Julys 2012
- * @version 1.0 Description
- *
- */
s32 host_int_add_beacon(struct host_if_drv *hWFIDrv, u32 u32Interval,
- u32 u32DTIMPeriod,
- u32 u32HeadLen, u8 *pu8Head,
- u32 u32TailLen, u8 *pu8tail);
-
-
-/*!
- * @fn s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv)
- * @brief Removes the beacon and stops trawilctting it over the air
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 10 Julys 2012
- * @version 1.0 Description
- */
-s32 host_int_del_beacon(struct host_if_drv *hWFIDrv);
-
-/*!
- * @fn s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv,
- * struct add_sta_param *pstrStaParams)
- * @brief Notifies the firmware with a new associated stations
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] pstrStaParams Station's parameters
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 12 July 2012
- * @version 1.0 Description
- */
-s32 host_int_add_station(struct host_if_drv *hWFIDrv,
- struct add_sta_param *pstrStaParams);
-
-/*!
- * @fn s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, const u8* pu8MacAddr)
- * @brief Deauthenticates clients when group is terminating
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] pu8MacAddr Station's mac address
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Mai Daftedar
- * @date 09 April 2014
- * @version 1.0 Description
- */
-s32 host_int_del_allstation(struct host_if_drv *hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]);
-
-/*!
- * @fn s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, u8* pu8MacAddr)
- * @brief Notifies the firmware with a new deleted station
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] pu8MacAddr Station's mac address
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 15 July 2012
- * @version 1.0 Description
- */
-s32 host_int_del_station(struct host_if_drv *hWFIDrv, const u8 *pu8MacAddr);
-
-/*!
- * @fn s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv,
- * struct add_sta_param *pstrStaParams)
- * @brief Notifies the firmware with new parameters of an already associated station
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] pstrStaParams Station's parameters
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 15 July 2012
- * @version 1.0 Description
- */
+ u32 u32DTIMPeriod,
+ u32 u32HeadLen,
+ u8 *pu8Head,
+ u32 u32TailLen,
+ u8 *pu8tail);
+int host_int_del_beacon(struct host_if_drv *hif_drv);
+int host_int_add_station(struct host_if_drv *hif_drv,
+ struct add_sta_param *sta_param);
+s32 host_int_del_allstation(struct host_if_drv *hWFIDrv,
+ u8 pu8MacAddr[][ETH_ALEN]);
+int host_int_del_station(struct host_if_drv *hif_drv, const u8 *mac_addr);
s32 host_int_edit_station(struct host_if_drv *hWFIDrv,
struct add_sta_param *pstrStaParams);
-
-/*!
- * @fn s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
- * @brief Set the power management mode to enabled or disabled
- * @details
- * @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] bIsEnabled TRUE if enabled, FALSE otherwise
- * @param[in] u32Timeout A timeout value of -1 allows the driver to adjust
- * the dynamic ps timeout value
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 24 November 2012
- * @version 1.0 Description
- */
-s32 host_int_set_power_mgmt(struct host_if_drv *hWFIDrv, bool bIsEnabled, u32 u32Timeout);
-/* @param[in,out] hWFIDrv handle to the wifi driver
- * @param[in] bIsEnabled TRUE if enabled, FALSE otherwise
- * @param[in] u8count count of mac address entries in the filter table
- *
- * @return 0 for Success, error otherwise
- * @todo
- * @sa
- * @author Adham Abozaeid
- * @date 24 November 2012
- * @version 1.0 Description
- */
-s32 host_int_setup_multicast_filter(struct host_if_drv *hWFIDrv, bool bIsEnabled, u32 u32count);
-/**
- * @brief host_int_setup_ipaddress
- * @details set IP address on firmware
- * @param[in]
- * @return Error code.
- * @author Abdelrahman Sobhy
- * @date
- * @version 1.0
- */
-s32 host_int_setup_ipaddress(struct host_if_drv *hWFIDrv, u8 *pu8IPAddr, u8 idx);
-
-
-/**
- * @brief host_int_delBASession
- * @details Delete single Rx BA session
- * @param[in]
- * @return Error code.
- * @author Abdelrahman Sobhy
- * @date
- * @version 1.0
- */
+s32 host_int_set_power_mgmt(struct host_if_drv *hWFIDrv,
+ bool bIsEnabled,
+ u32 u32Timeout);
+s32 host_int_setup_multicast_filter(struct host_if_drv *hWFIDrv,
+ bool bIsEnabled,
+ u32 u32count);
+s32 host_int_setup_ipaddress(struct host_if_drv *hWFIDrv,
+ u8 *pu8IPAddr,
+ u8 idx);
s32 host_int_delBASession(struct host_if_drv *hWFIDrv, char *pBSSID, char TID);
-
-/**
- * @brief host_int_delBASession
- * @details Delete all Rx BA session
- * @param[in]
- * @return Error code.
- * @author Abdelrahman Sobhy
- * @date
- * @version 1.0
- */
-s32 host_int_del_All_Rx_BASession(struct host_if_drv *hWFIDrv, char *pBSSID, char TID);
-
-
-/**
- * @brief host_int_get_ipaddress
- * @details get IP address on firmware
- * @param[in]
- * @return Error code.
- * @author Abdelrahman Sobhy
- * @date
- * @version 1.0
- */
+s32 host_int_del_All_Rx_BASession(struct host_if_drv *hWFIDrv,
+ char *pBSSID,
+ char TID);
s32 host_int_get_ipaddress(struct host_if_drv *hWFIDrv, u8 *pu8IPAddr, u8 idx);
-
-/**
- * @brief host_int_remain_on_channel
- * @details
- * @param[in]
- * @return Error code.
- * @author
- * @date
- * @version 1.0
- */
-s32 host_int_remain_on_channel(struct host_if_drv *hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg);
-
-/**
- * @brief host_int_ListenStateExpired
- * @details
- * @param[in] Handle to wifi driver
- * Duration to remain on channel
- * Channel to remain on
- * Pointer to fn to be called on receive frames in listen state
- * Pointer to remain-on-channel expired fn
- * Priv
- * @return Error code.
- * @author
- * @date
- * @version 1.0
- */
+s32 host_int_remain_on_channel(struct host_if_drv *hWFIDrv,
+ u32 u32SessionID,
+ u32 u32duration,
+ u16 chan,
+ wilc_remain_on_chan_expired RemainOnChanExpired,
+ wilc_remain_on_chan_ready RemainOnChanReady,
+ void *pvUserArg);
s32 host_int_ListenStateExpired(struct host_if_drv *hWFIDrv, u32 u32SessionID);
-
-/**
- * @brief host_int_frame_register
- * @details
- * @param[in]
- * @return Error code.
- * @author
- * @date
- * @version 1.0
- */
-s32 host_int_frame_register(struct host_if_drv *hWFIDrv, u16 u16FrameType, bool bReg);
-/**
- * @brief host_int_set_wfi_drv_handler
- * @details
- * @param[in]
- * @return Error code.
- * @author
- * @date
- * @version 1.0
- */
+s32 host_int_frame_register(struct host_if_drv *hWFIDrv,
+ u16 u16FrameType,
+ bool bReg);
int host_int_set_wfi_drv_handler(struct host_if_drv *address);
int host_int_set_operation_mode(struct host_if_drv *wfi_drv, u32 mode);
-static s32 Handle_ScanDone(struct host_if_drv *drvHandler, enum scan_event enuEvent);
+static s32 Handle_ScanDone(struct host_if_drv *drvHandler,
+ enum scan_event enuEvent);
void host_int_freeJoinParams(void *pJoinParams);
-s32 host_int_get_statistics(struct host_if_drv *hWFIDrv, struct rf_info *pstrStatistics);
-
+s32 host_int_get_statistics(struct host_if_drv *hWFIDrv,
+ struct rf_info *pstrStatistics);
+void resolve_disconnect_aberration(struct host_if_drv *hif_drv);
#endif
diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c
index 450af1b77f99..589a11fd977c 100644
--- a/drivers/staging/wilc1000/linux_mon.c
+++ b/drivers/staging/wilc1000/linux_mon.c
@@ -195,7 +195,7 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
mgmt_tx->size = len;
memcpy(mgmt_tx->buff, buf, len);
- wilc_wlan_txq_add_mgmt_pkt(mgmt_tx, mgmt_tx->buff, mgmt_tx->size,
+ wilc_wlan_txq_add_mgmt_pkt(dev, mgmt_tx, mgmt_tx->buff, mgmt_tx->size,
mgmt_tx_complete);
netif_wake_queue(dev);
diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c
index b879b8be0f3f..086f1dbfb157 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -23,7 +23,6 @@
#include <linux/kernel.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
#include <linux/semaphore.h>
#ifdef WILC_SDIO
@@ -32,24 +31,14 @@
#include "linux_wlan_spi.h"
#endif
-#if defined(CUSTOMER_PLATFORM)
-/*
- TODO : Write power control functions as customer platform.
- */
-#else
-
#define _linux_wlan_device_power_on() {}
#define _linux_wlan_device_power_off() {}
#define _linux_wlan_device_detection() {}
#define _linux_wlan_device_removal() {}
-#endif
extern bool g_obtainingIP;
-extern u16 Set_machw_change_vir_if(bool bValue);
-extern void resolve_disconnect_aberration(void *drvHandler);
-extern u8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
-void wilc1000_wlan_deinit(struct wilc *nic);
+extern u8 multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
extern struct timer_list hDuringIpTimer;
static int linux_wlan_device_power(int on_off)
@@ -88,16 +77,10 @@ static struct notifier_block g_dev_notifier = {
#define IRQ_WAIT 1
#define IRQ_NO_WAIT 0
-/*
- * to sync between mac_close and module exit.
- * don't initialize or de-initialize from init/deinitlocks
- * to be initialized from module wilc_netdev_init and
- * deinitialized from mdoule_exit
- */
static struct semaphore close_exit_sync;
-static int wlan_deinit_locks(struct wilc *nic);
-static void wlan_deinitialize_threads(struct wilc *nic);
+static int wlan_deinit_locks(struct net_device *dev);
+static void wlan_deinitialize_threads(struct net_device *dev);
extern void WILC_WFI_monitor_rx(u8 *buff, u32 size);
extern void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
@@ -109,11 +92,6 @@ int mac_close(struct net_device *ndev);
static struct net_device_stats *mac_stats(struct net_device *dev);
static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd);
static void wilc_set_multicast_list(struct net_device *dev);
-
-/*
- * for now - in frmw_to_linux there should be private data to be passed to it
- * and this data should be pointer to net device
- */
struct wilc *g_linux_wlan;
bool bEnablePS = true;
@@ -132,108 +110,116 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event
{
struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr;
struct wilc_priv *priv;
- struct host_if_drv *pstrWFIDrv;
+ struct host_if_drv *hif_drv;
struct net_device *dev;
- u8 *pIP_Add_buff;
+ u8 *ip_addr_buf;
perInterface_wlan_t *nic;
u8 null_ip[4] = {0};
char wlan_dev_name[5] = "wlan0";
- if (dev_iface == NULL || dev_iface->ifa_dev == NULL || dev_iface->ifa_dev->dev == NULL) {
+ if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) {
PRINT_D(GENERIC_DBG, "dev_iface = NULL\n");
return NOTIFY_DONE;
}
- if ((memcmp(dev_iface->ifa_label, "wlan0", 5)) && (memcmp(dev_iface->ifa_label, "p2p0", 4))) {
+ if (memcmp(dev_iface->ifa_label, "wlan0", 5) &&
+ memcmp(dev_iface->ifa_label, "p2p0", 4)) {
PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n");
return NOTIFY_DONE;
}
dev = (struct net_device *)dev_iface->ifa_dev->dev;
- if (dev->ieee80211_ptr == NULL || dev->ieee80211_ptr->wiphy == NULL) {
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) {
PRINT_D(GENERIC_DBG, "No Wireless registerd\n");
return NOTIFY_DONE;
}
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- if (priv == NULL) {
+ if (!priv) {
PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
return NOTIFY_DONE;
}
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
nic = netdev_priv(dev);
- if (nic == NULL || pstrWFIDrv == NULL) {
+ if (!nic || !hif_drv) {
PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
return NOTIFY_DONE;
}
- PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n"); /* tony */
+ PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n");
switch (event) {
case NETDEV_UP:
- PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev); /* tony */
+ PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev);
PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n");
- /*If we are in station mode or client mode*/
if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
- pstrWFIDrv->IFC_UP = 1;
+ hif_drv->IFC_UP = 1;
g_obtainingIP = false;
del_timer(&hDuringIpTimer);
PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
}
if (bEnablePS)
- host_int_set_power_mgmt(pstrWFIDrv, 1, 0);
+ host_int_set_power_mgmt(hif_drv, 1, 0);
PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
- pIP_Add_buff = (char *) (&(dev_iface->ifa_address));
- PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
- host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+ ip_addr_buf = (char *)&dev_iface->ifa_address;
+ PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n",
+ ip_addr_buf[0], ip_addr_buf[1],
+ ip_addr_buf[2], ip_addr_buf[3]);
+ host_int_setup_ipaddress(hif_drv, ip_addr_buf, nic->u8IfIdx);
break;
case NETDEV_DOWN:
- PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev); /* tony */
+ PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev);
PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n");
if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
- pstrWFIDrv->IFC_UP = 0;
+ hif_drv->IFC_UP = 0;
g_obtainingIP = false;
}
if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
- host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
+ host_int_set_power_mgmt(hif_drv, 0, 0);
- resolve_disconnect_aberration(pstrWFIDrv);
+ resolve_disconnect_aberration(hif_drv);
PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label);
- pIP_Add_buff = null_ip;
- PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
+ ip_addr_buf = null_ip;
+ PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n",
+ ip_addr_buf[0], ip_addr_buf[1],
+ ip_addr_buf[2], ip_addr_buf[3]);
- host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+ host_int_setup_ipaddress(hif_drv, ip_addr_buf, nic->u8IfIdx);
break;
default:
- PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n"); /* tony */
+ PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n");
PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event);
break;
}
return NOTIFY_DONE;
-
}
#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
static irqreturn_t isr_uh_routine(int irq, void *user_data)
{
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
+ struct net_device *dev = (struct net_device *)user_data;
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
PRINT_D(INT_DBG, "Interrupt received UH\n");
- /*While mac is closing cacncel the handling of any interrupts received*/
- if (g_linux_wlan->close) {
+ if (wilc->close) {
PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n");
return IRQ_HANDLED;
}
@@ -243,77 +229,74 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data)
irqreturn_t isr_bh_routine(int irq, void *userdata)
{
- struct wilc *nic;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- nic = (struct wilc *)userdata;
+ nic = netdev_priv(userdata);
+ wilc = nic->wilc;
- /*While mac is closing cacncel the handling of any interrupts received*/
- if (g_linux_wlan->close) {
+ if (wilc->close) {
PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n");
return IRQ_HANDLED;
}
PRINT_D(INT_DBG, "Interrupt received BH\n");
- wilc_handle_isr();
+ wilc_handle_isr(wilc);
return IRQ_HANDLED;
}
#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
-static int init_irq(struct wilc *p_nic)
+static int init_irq(struct net_device *dev)
{
int ret = 0;
- struct wilc *nic = p_nic;
+ perInterface_wlan_t *nic;
+ struct wilc *wl;
+
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
- /*initialize GPIO and register IRQ num*/
- /*GPIO request*/
if ((gpio_request(GPIO_NUM, "WILC_INTR") == 0) &&
(gpio_direction_input(GPIO_NUM) == 0)) {
-#if defined(CUSTOMER_PLATFORM)
-/*
- TODO : save the registerd irq number to the private wilc context in kernel.
- *
- * ex) nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
- */
-#else
- nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
-#endif
+ wl->dev_irq_num = gpio_to_irq(GPIO_NUM);
} else {
ret = -1;
PRINT_ER("could not obtain gpio for WILC_INTR\n");
}
- if ((ret != -1) && (request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/
- "WILC_IRQ", nic)) < 0) {
-
+ if (ret != -1 && request_threaded_irq(wl->dev_irq_num,
+ isr_uh_routine,
+ isr_bh_routine,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "WILC_IRQ", dev) < 0) {
PRINT_ER("Failed to request IRQ for GPIO: %d\n", GPIO_NUM);
ret = -1;
} else {
-
PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
- nic->dev_irq_num, GPIO_NUM);
+ wl->dev_irq_num, GPIO_NUM);
}
return ret;
}
#endif
-static void deinit_irq(struct wilc *nic)
+static void deinit_irq(struct net_device *dev)
{
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
- /* Deintialize IRQ */
- if (&nic->dev_irq_num != 0) {
- free_irq(nic->dev_irq_num, g_linux_wlan);
+ if (&wilc->dev_irq_num != 0) {
+ free_irq(wilc->dev_irq_num, wilc);
gpio_free(GPIO_NUM);
}
#endif
}
-/*
- * OS functions
- */
void linux_wlan_dbg(u8 *buff)
{
PRINT_D(INIT_DBG, "%d\n", *buff);
@@ -324,98 +307,89 @@ int linux_wlan_lock_timeout(void *vp, u32 timeout)
int error = -1;
PRINT_D(LOCK_DBG, "Locking %p\n", vp);
- if (vp != NULL)
- error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout));
+ if (vp)
+ error = down_timeout((struct semaphore *)vp,
+ msecs_to_jiffies(timeout));
else
PRINT_ER("Failed, mutex is NULL\n");
return error;
}
-void linux_wlan_mac_indicate(int flag)
+void linux_wlan_mac_indicate(struct wilc *wilc, int flag)
{
- /*I have to do it that way becuase there is no mean to encapsulate device pointer
- * as a parameter
- */
- struct wilc *pd = g_linux_wlan;
int status;
if (flag == WILC_MAC_INDICATE_STATUS) {
- wilc_wlan_cfg_get_val(WID_STATUS, (unsigned char *)&status, 4);
- if (pd->mac_status == WILC_MAC_STATUS_INIT) {
- pd->mac_status = status;
- up(&pd->sync_event);
+ wilc_wlan_cfg_get_val(WID_STATUS,
+ (unsigned char *)&status, 4);
+ if (wilc->mac_status == WILC_MAC_STATUS_INIT) {
+ wilc->mac_status = status;
+ up(&wilc->sync_event);
} else {
- pd->mac_status = status;
+ wilc->mac_status = status;
}
-
- if (pd->mac_status == WILC_MAC_STATUS_CONNECT) { /* Connect */
- }
-
} else if (flag == WILC_MAC_INDICATE_SCAN) {
PRINT_D(GENERIC_DBG, "Scanning ...\n");
-
}
-
}
-struct net_device *GetIfHandler(u8 *pMacHeader)
+struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
{
- u8 *Bssid, *Bssid1;
+ u8 *bssid, *bssid1;
int i = 0;
- Bssid = pMacHeader + 10;
- Bssid1 = pMacHeader + 4;
+ bssid = mac_header + 10;
+ bssid1 = mac_header + 4;
+
+ for (i = 0; i < wilc->vif_num; i++)
+ if (!memcmp(bssid1, wilc->vif[i].bssid, ETH_ALEN) ||
+ !memcmp(bssid, wilc->vif[i].bssid, ETH_ALEN))
+ return wilc->vif[i].ndev;
- for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- if (!memcmp(Bssid1, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN) ||
- !memcmp(Bssid, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN)) {
- return g_linux_wlan->strInterfaceInfo[i].wilc_netdev;
- }
- }
PRINT_INFO(INIT_DBG, "Invalide handle\n");
for (i = 0; i < 25; i++)
- PRINT_D(INIT_DBG, "%02x ", pMacHeader[i]);
- Bssid = pMacHeader + 18;
- Bssid1 = pMacHeader + 12;
- for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- if (!memcmp(Bssid1, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN) ||
- !memcmp(Bssid, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN)) {
- PRINT_D(INIT_DBG, "Ctx [%p]\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- return g_linux_wlan->strInterfaceInfo[i].wilc_netdev;
- }
- }
+ PRINT_D(INIT_DBG, "%02x ", mac_header[i]);
+ bssid = mac_header + 18;
+ bssid1 = mac_header + 12;
+ for (i = 0; i < wilc->vif_num; i++)
+ if (!memcmp(bssid1, wilc->vif[i].bssid, ETH_ALEN) ||
+ !memcmp(bssid, wilc->vif[i].bssid, ETH_ALEN))
+ return wilc->vif[i].ndev;
+
PRINT_INFO(INIT_DBG, "\n");
return NULL;
}
-int linux_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID)
+int linux_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid)
{
int i = 0;
int ret = -1;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- PRINT_D(INIT_DBG, "set bssid on[%p]\n", wilc_netdev);
- for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev == wilc_netdev) {
- PRINT_D(INIT_DBG, "set bssid [%x][%x][%x]\n", pBSSID[0], pBSSID[1], pBSSID[2]);
- memcpy(g_linux_wlan->strInterfaceInfo[i].aBSSID, pBSSID, 6);
+ nic = netdev_priv(wilc_netdev);
+ wilc = nic->wilc;
+
+ for (i = 0; i < wilc->vif_num; i++)
+ if (wilc->vif[i].ndev == wilc_netdev) {
+ memcpy(wilc->vif[i].bssid, bssid, 6);
ret = 0;
break;
}
- }
+
return ret;
}
-/*Function to get number of connected interfaces*/
int linux_wlan_get_num_conn_ifcs(void)
{
u8 i = 0;
u8 null_bssid[6] = {0};
u8 ret_val = 0;
- for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6))
+ for (i = 0; i < g_linux_wlan->vif_num; i++)
+ if (memcmp(g_linux_wlan->vif[i].bssid, null_bssid, 6))
ret_val++;
- }
+
return ret_val;
}
@@ -424,7 +398,9 @@ int linux_wlan_get_num_conn_ifcs(void)
static int linux_wlan_txq_task(void *vp)
{
int ret, txq_count;
-
+ perInterface_wlan_t *nic;
+ struct wilc *wl;
+ struct net_device *dev = vp;
#if defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
#define TX_BACKOFF_WEIGHT_INCR_STEP (1)
#define TX_BACKOFF_WEIGHT_DECR_STEP (1)
@@ -434,18 +410,17 @@ static int linux_wlan_txq_task(void *vp)
int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
#endif
- /* inform wilc1000_wlan_init that TXQ task is started. */
- up(&g_linux_wlan->txq_thread_started);
- while (1) {
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
+ up(&wl->txq_thread_started);
+ while (1) {
PRINT_D(TX_DBG, "txq_task Taking a nap :)\n");
- down(&g_linux_wlan->txq_event);
- /* wait_for_completion(&pd->txq_event); */
+ down(&wl->txq_event);
PRINT_D(TX_DBG, "txq_task Who waked me up :$\n");
- if (g_linux_wlan->close) {
- /*Unlock the mutex in the mac_close function to indicate the exiting of the TX thread */
- up(&g_linux_wlan->txq_thread_started);
+ if (wl->close) {
+ up(&wl->txq_thread_started);
while (!kthread_should_stop())
schedule();
@@ -455,27 +430,23 @@ static int linux_wlan_txq_task(void *vp)
}
PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n");
#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
- ret = wilc_wlan_handle_txq(&txq_count);
+ ret = wilc_wlan_handle_txq(dev, &txq_count);
#else
do {
- ret = wilc_wlan_handle_txq(&txq_count);
- if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD /* && netif_queue_stopped(pd->wilc_netdev)*/) {
+ ret = wilc_wlan_handle_txq(dev, &txq_count);
+ if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
PRINT_D(TX_DBG, "Waking up queue\n");
- /* netif_wake_queue(pd->wilc_netdev); */
- if (netif_queue_stopped(g_linux_wlan->strInterfaceInfo[0].wilc_netdev))
- netif_wake_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev);
- if (netif_queue_stopped(g_linux_wlan->strInterfaceInfo[1].wilc_netdev))
- netif_wake_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev);
+
+ if (netif_queue_stopped(wl->vif[0].ndev))
+ netif_wake_queue(wl->vif[0].ndev);
+ if (netif_queue_stopped(wl->vif[1].ndev))
+ netif_wake_queue(wl->vif[1].ndev);
}
- if (ret == WILC_TX_ERR_NO_BUF) { /* failed to allocate buffers in chip. */
+ if (ret == WILC_TX_ERR_NO_BUF) {
do {
- /* Back off from sending packets for some time. */
- /* schedule_timeout will allow RX task to run and free buffers.*/
- /* set_current_state(TASK_UNINTERRUPTIBLE); */
- /* timeout = schedule_timeout(timeout); */
msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
- } while (/*timeout*/ 0);
+ } while (0);
backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
if (backoff_weight > TX_BACKOFF_WEIGHT_MAX)
backoff_weight = TX_BACKOFF_WEIGHT_MAX;
@@ -486,8 +457,7 @@ static int linux_wlan_txq_task(void *vp)
backoff_weight = TX_BACKOFF_WEIGHT_MIN;
}
}
- /*TODO: drop packets after a certain time/number of retry count. */
- } while (ret == WILC_TX_ERR_NO_BUF && !g_linux_wlan->close); /* retry sending packets if no more buffers in chip. */
+ } while (ret == WILC_TX_ERR_NO_BUF && !wl->close);
#endif
}
return 0;
@@ -498,151 +468,129 @@ void linux_wlan_rx_complete(void)
PRINT_D(RX_DBG, "RX completed\n");
}
-int linux_wlan_get_firmware(perInterface_wlan_t *p_nic)
+int linux_wlan_get_firmware(struct net_device *dev)
{
-
- perInterface_wlan_t *nic = p_nic;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
int ret = 0;
const struct firmware *wilc_firmware;
char *firmware;
- if (nic->iftype == AP_MODE)
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ if (nic->iftype == AP_MODE) {
firmware = AP_FIRMWARE;
- else if (nic->iftype == STATION_MODE)
+ } else if (nic->iftype == STATION_MODE) {
firmware = STA_FIRMWARE;
-
- else {
+ } else {
PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n");
firmware = P2P_CONCURRENCY_FIRMWARE;
}
- if (nic == NULL) {
+ if (!nic) {
PRINT_ER("NIC is NULL\n");
goto _fail_;
}
- if (&nic->wilc_netdev->dev == NULL) {
+ if (!(&nic->wilc_netdev->dev)) {
PRINT_ER("&nic->wilc_netdev->dev is NULL\n");
goto _fail_;
}
- /* the firmare should be located in /lib/firmware in
- * root file system with the name specified above */
-
#ifdef WILC_SDIO
- if (request_firmware(&wilc_firmware, firmware, &g_linux_wlan->wilc_sdio_func->dev) != 0) {
+ if (request_firmware(&wilc_firmware, firmware, &wilc->wilc_sdio_func->dev) != 0) {
PRINT_ER("%s - firmare not available\n", firmware);
ret = -1;
goto _fail_;
}
#else
- if (request_firmware(&wilc_firmware, firmware, &g_linux_wlan->wilc_spidev->dev) != 0) {
+ if (request_firmware(&wilc_firmware, firmware, &wilc->wilc_spidev->dev) != 0) {
PRINT_ER("%s - firmare not available\n", firmware);
ret = -1;
goto _fail_;
}
#endif
- g_linux_wlan->wilc_firmware = wilc_firmware;
+ wilc->firmware = wilc_firmware;
_fail_:
return ret;
-
}
-#ifdef COMPLEMENT_BOOT
-int repeat_power_cycle(perInterface_wlan_t *nic);
-#endif
-
-static int linux_wlan_start_firmware(perInterface_wlan_t *nic)
+static int linux_wlan_start_firmware(struct net_device *dev)
{
-
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
int ret = 0;
- /* start firmware */
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
PRINT_D(INIT_DBG, "Starting Firmware ...\n");
ret = wilc_wlan_start();
if (ret < 0) {
PRINT_ER("Failed to start Firmware\n");
- goto _fail_;
+ return ret;
}
- /* wait for mac ready */
PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n");
- ret = linux_wlan_lock_timeout(&g_linux_wlan->sync_event, 5000);
+ ret = linux_wlan_lock_timeout(&wilc->sync_event, 5000);
if (ret) {
-#ifdef COMPLEMENT_BOOT
- static int timeout = 5;
-
- if (timeout--) {
- PRINT_D(INIT_DBG, "repeat power cycle[%d]", timeout);
- ret = repeat_power_cycle(nic);
- } else {
- timeout = 5;
- ret = -1;
- goto _fail_;
- }
-#endif
PRINT_D(INIT_DBG, "Firmware start timed out");
- goto _fail_;
+ return ret;
}
- /*
- * TODO: Driver shouoldn't wait forever for firmware to get started -
- * in case of timeout this should be handled properly
- */
PRINT_D(INIT_DBG, "Firmware successfully started\n");
-_fail_:
- return ret;
+ return 0;
}
-static int linux_wlan_firmware_download(struct wilc *p_nic)
-{
+static int linux_wlan_firmware_download(struct net_device *dev)
+{
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
int ret = 0;
- if (g_linux_wlan->wilc_firmware == NULL) {
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ if (!wilc->firmware) {
PRINT_ER("Firmware buffer is NULL\n");
- ret = -ENOBUFS;
- goto _FAIL_;
+ return -ENOBUFS;
}
- /**
- * do the firmware download
- **/
PRINT_D(INIT_DBG, "Downloading Firmware ...\n");
- ret = wilc_wlan_firmware_download(g_linux_wlan->wilc_firmware->data,
- g_linux_wlan->wilc_firmware->size);
+ ret = wilc_wlan_firmware_download(wilc->firmware->data,
+ wilc->firmware->size);
if (ret < 0)
- goto _FAIL_;
+ return ret;
- /* Freeing FW buffer */
PRINT_D(INIT_DBG, "Freeing FW buffer ...\n");
PRINT_D(INIT_DBG, "Releasing firmware\n");
- release_firmware(g_linux_wlan->wilc_firmware);
- g_linux_wlan->wilc_firmware = NULL;
+ release_firmware(wilc->firmware);
PRINT_D(INIT_DBG, "Download Succeeded\n");
-_FAIL_:
- return ret;
+ return 0;
}
-/* startup configuration - could be changed later using iconfig*/
static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_nic)
{
-
unsigned char c_val[64];
unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff};
struct wilc_priv *priv;
- struct host_if_drv *pstrWFIDrv;
+ struct host_if_drv *hif_drv;
PRINT_D(TX_DBG, "Start configuring Firmware\n");
get_random_bytes(&mac_add[5], 1);
get_random_bytes(&mac_add[4], 1);
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
- PRINT_D(INIT_DBG, "Host = %p\n", pstrWFIDrv);
+ hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ PRINT_D(INIT_DBG, "Host = %p\n", hif_drv);
- PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]);
+ PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n",
+ mac_add[0], mac_add[1], mac_add[2],
+ mac_add[3], mac_add[4], mac_add[5]);
wilc_get_chipid(0);
*(int *)c_val = 1;
@@ -650,7 +598,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
goto _fail_;
- /*to tell fw that we are going to use PC test - WILC specific*/
c_val[0] = 0;
if (!wilc_wlan_cfg_set(0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
goto _fail_;
@@ -659,7 +606,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0))
goto _fail_;
- /* c_val[0] = RATE_AUTO; */
c_val[0] = RATE_AUTO;
if (!wilc_wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
goto _fail_;
@@ -688,7 +634,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_SITE_SURVEY, c_val, 1, 0, 0))
goto _fail_;
- *((int *)c_val) = 0xffff; /* Never use RTS-CTS */
+ *((int *)c_val) = 0xffff;
if (!wilc_wlan_cfg_set(0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
goto _fail_;
@@ -696,13 +642,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
goto _fail_;
- /* SSID */
- /* -------------------------------------------------------------- */
- /* Configuration : String with length less than 32 bytes */
- /* Values to set : Any string with length less than 32 bytes */
- /* ( In BSS Station Set SSID to "" (null string) */
- /* to enable Broadcast SSID suppport ) */
- /* -------------------------------------------------------------- */
c_val[0] = 0;
if (!wilc_wlan_cfg_set(0, WID_BCAST_SSID, c_val, 1, 0, 0))
goto _fail_;
@@ -715,7 +654,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
goto _fail_;
- c_val[0] = NO_ENCRYPT; /* NO_ENCRYPT, 0x79 */
+ c_val[0] = NO_ENCRYPT;
if (!wilc_wlan_cfg_set(0, WID_11I_MODE, c_val, 1, 0, 0))
goto _fail_;
@@ -723,43 +662,18 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_AUTH_TYPE, c_val, 1, 0, 0))
goto _fail_;
- /* WEP/802 11I Configuration */
- /* ------------------------------------------------------------------ */
- /* Configuration : WEP Key */
- /* Values (0x) : 5 byte for WEP40 and 13 bytes for WEP104 */
- /* In case more than 5 bytes are passed on for WEP 40 */
- /* only first 5 bytes will be used as the key */
- /* ------------------------------------------------------------------ */
-
strcpy(c_val, "123456790abcdef1234567890");
if (!wilc_wlan_cfg_set(0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val) + 1), 0, 0))
goto _fail_;
- /* WEP/802 11I Configuration */
- /* ------------------------------------------------------------------ */
- /* Configuration : AES/TKIP WPA/RSNA Pre-Shared Key */
- /* Values to set : Any string with length greater than equal to 8 bytes */
- /* and less than 64 bytes */
- /* ------------------------------------------------------------------ */
strcpy(c_val, "12345678");
if (!wilc_wlan_cfg_set(0, WID_11I_PSK, c_val, (strlen(c_val)), 0, 0))
goto _fail_;
- /* IEEE802.1X Key Configuration */
- /* ------------------------------------------------------------------ */
- /* Configuration : Radius Server Access Secret Key */
- /* Values to set : Any string with length greater than equal to 8 bytes */
- /* and less than 65 bytes */
- /* ------------------------------------------------------------------ */
strcpy(c_val, "password");
if (!wilc_wlan_cfg_set(0, WID_1X_KEY, c_val, (strlen(c_val) + 1), 0, 0))
goto _fail_;
- /* IEEE802.1X Server Address Configuration */
- /* ------------------------------------------------------------------ */
- /* Configuration : Radius Server IP Address */
- /* Values to set : Any valid IP Address */
- /* ------------------------------------------------------------------ */
c_val[0] = 192;
c_val[1] = 168;
c_val[2] = 1;
@@ -791,12 +705,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, 0))
goto _fail_;
- /* Beacon Interval */
- /* -------------------------------------------------------------------- */
- /* Configuration : Sets the beacon interval value */
- /* Values to set : Any 16-bit value */
- /* -------------------------------------------------------------------- */
-
*((int *)c_val) = 100;
if (!wilc_wlan_cfg_set(0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
goto _fail_;
@@ -805,20 +713,10 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_REKEY_POLICY, c_val, 1, 0, 0))
goto _fail_;
- /* Rekey Time (s) (Used only when the Rekey policy is 2 or 4) */
- /* -------------------------------------------------------------------- */
- /* Configuration : Sets the Rekey Time (s) */
- /* Values to set : 32-bit value */
- /* -------------------------------------------------------------------- */
*((int *)c_val) = 84600;
if (!wilc_wlan_cfg_set(0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
goto _fail_;
- /* Rekey Packet Count (in 1000s; used when Rekey Policy is 3) */
- /* -------------------------------------------------------------------- */
- /* Configuration : Sets Rekey Group Packet count */
- /* Values to set : 32-bit Value */
- /* -------------------------------------------------------------------- */
*((int *)c_val) = 500;
if (!wilc_wlan_cfg_set(0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, 0))
goto _fail_;
@@ -831,7 +729,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
goto _fail_;
- c_val[0] = 1; /* Enable N */
+ c_val[0] = 1;
if (!wilc_wlan_cfg_set(0, WID_11N_ENABLE, c_val, 1, 0, 0))
goto _fail_;
@@ -839,7 +737,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_11N_OPERATING_MODE, c_val, 1, 0, 0))
goto _fail_;
- c_val[0] = 1; /* TXOP Prot disable in N mode: No RTS-CTS on TX A-MPDUs to save air-time. */
+ c_val[0] = 1;
if (!wilc_wlan_cfg_set(0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, 0))
goto _fail_;
@@ -848,9 +746,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_MAC_ADDR, c_val, 6, 0, 0))
goto _fail_;
- /**
- * AP only
- **/
c_val[0] = DETECT_PROTECT_REPORT;
if (!wilc_wlan_cfg_set(0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0, 0))
goto _fail_;
@@ -871,7 +766,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_ni
if (!wilc_wlan_cfg_set(0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, 0))
goto _fail_;
- c_val[0] = 1; /* Enable N with immediate block ack. */
+ c_val[0] = 1;
if (!wilc_wlan_cfg_set(0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 1, 1))
goto _fail_;
@@ -881,21 +776,23 @@ _fail_:
return -1;
}
-/**************************/
-void wilc1000_wlan_deinit(struct wilc *nic)
+void wilc1000_wlan_deinit(struct net_device *dev)
{
+ perInterface_wlan_t *nic;
+ struct wilc *wl;
- if (g_linux_wlan->wilc1000_initialized) {
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
- printk("Deinitializing wilc1000 ...\n");
+ if (!wl) {
+ netdev_err(dev, "wl is NULL\n");
+ return;
+ }
- if (nic == NULL) {
- PRINT_ER("nic is NULL\n");
- return;
- }
+ if (wl->initialized) {
+ netdev_info(dev, "Deinitializing wilc1000...\n");
#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
- /* johnny : remove */
PRINT_D(INIT_DBG, "skip wilc_bus_set_default_speed\n");
#else
wilc_bus_set_default_speed();
@@ -903,39 +800,37 @@ void wilc1000_wlan_deinit(struct wilc *nic)
PRINT_D(INIT_DBG, "Disabling IRQ\n");
#ifdef WILC_SDIO
- mutex_lock(&g_linux_wlan->hif_cs);
+ mutex_lock(&wl->hif_cs);
disable_sdio_interrupt();
- mutex_unlock(&g_linux_wlan->hif_cs);
+ mutex_unlock(&wl->hif_cs);
#endif
- if (&g_linux_wlan->txq_event != NULL)
- up(&g_linux_wlan->txq_event);
+ if (&wl->txq_event)
+ up(&wl->txq_event);
PRINT_D(INIT_DBG, "Deinitializing Threads\n");
- wlan_deinitialize_threads(nic);
+ wlan_deinitialize_threads(dev);
PRINT_D(INIT_DBG, "Deinitializing IRQ\n");
- deinit_irq(g_linux_wlan);
+ deinit_irq(dev);
wilc_wlan_stop();
PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n");
- wilc_wlan_cleanup();
+ wilc_wlan_cleanup(dev);
#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
PRINT_D(INIT_DBG, "Disabling IRQ 2\n");
- mutex_lock(&g_linux_wlan->hif_cs);
+ mutex_lock(&wl->hif_cs);
disable_sdio_interrupt();
- mutex_unlock(&g_linux_wlan->hif_cs);
+ mutex_unlock(&wl->hif_cs);
#endif
#endif
- /*De-Initialize locks*/
PRINT_D(INIT_DBG, "Deinitializing Locks\n");
- wlan_deinit_locks(g_linux_wlan);
+ wlan_deinit_locks(dev);
- /* announce that wilc1000 is not initialized */
- g_linux_wlan->wilc1000_initialized = 0;
+ wl->initialized = false;
PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n");
@@ -944,243 +839,140 @@ void wilc1000_wlan_deinit(struct wilc *nic)
}
}
-int wlan_init_locks(struct wilc *p_nic)
+int wlan_init_locks(struct net_device *dev)
{
+ perInterface_wlan_t *nic;
+ struct wilc *wl;
+
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
PRINT_D(INIT_DBG, "Initializing Locks ...\n");
- mutex_init(&g_linux_wlan->hif_cs);
- mutex_init(&g_linux_wlan->rxq_cs);
+ mutex_init(&wl->hif_cs);
+ mutex_init(&wl->rxq_cs);
- spin_lock_init(&g_linux_wlan->txq_spinlock);
- sema_init(&g_linux_wlan->txq_add_to_head_cs, 1);
+ spin_lock_init(&wl->txq_spinlock);
+ sema_init(&wl->txq_add_to_head_cs, 1);
- sema_init(&g_linux_wlan->txq_event, 0);
+ sema_init(&wl->txq_event, 0);
- sema_init(&g_linux_wlan->cfg_event, 0);
- sema_init(&g_linux_wlan->sync_event, 0);
+ sema_init(&wl->cfg_event, 0);
+ sema_init(&wl->sync_event, 0);
- sema_init(&g_linux_wlan->txq_thread_started, 0);
+ sema_init(&wl->txq_thread_started, 0);
return 0;
}
-static int wlan_deinit_locks(struct wilc *nic)
+static int wlan_deinit_locks(struct net_device *dev)
{
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
PRINT_D(INIT_DBG, "De-Initializing Locks\n");
- if (&g_linux_wlan->hif_cs != NULL)
- mutex_destroy(&g_linux_wlan->hif_cs);
+ if (&wilc->hif_cs)
+ mutex_destroy(&wilc->hif_cs);
- if (&g_linux_wlan->rxq_cs != NULL)
- mutex_destroy(&g_linux_wlan->rxq_cs);
+ if (&wilc->rxq_cs)
+ mutex_destroy(&wilc->rxq_cs);
return 0;
}
+
void linux_to_wlan(wilc_wlan_inp_t *nwi, struct wilc *nic)
{
-
PRINT_D(INIT_DBG, "Linux to Wlan services ...\n");
- nwi->os_context.os_private = (void *)nic;
-
#ifdef WILC_SDIO
nwi->io_func.io_type = HIF_SDIO;
- nwi->io_func.io_init = linux_sdio_init;
- nwi->io_func.io_deinit = linux_sdio_deinit;
- nwi->io_func.u.sdio.sdio_cmd52 = linux_sdio_cmd52;
- nwi->io_func.u.sdio.sdio_cmd53 = linux_sdio_cmd53;
- nwi->io_func.u.sdio.sdio_set_max_speed = linux_sdio_set_max_speed;
- nwi->io_func.u.sdio.sdio_set_default_speed = linux_sdio_set_default_speed;
#else
nwi->io_func.io_type = HIF_SPI;
- nwi->io_func.io_init = linux_spi_init;
- nwi->io_func.io_deinit = linux_spi_deinit;
- nwi->io_func.u.spi.spi_tx = linux_spi_write;
- nwi->io_func.u.spi.spi_rx = linux_spi_read;
- nwi->io_func.u.spi.spi_trx = linux_spi_write_read;
- nwi->io_func.u.spi.spi_max_speed = linux_spi_set_max_speed;
#endif
}
-int wlan_initialize_threads(perInterface_wlan_t *nic)
+int wlan_initialize_threads(struct net_device *dev)
{
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- int ret = 0;
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
PRINT_D(INIT_DBG, "Initializing Threads ...\n");
-
- /* create tx task */
PRINT_D(INIT_DBG, "Creating kthread for transmission\n");
- g_linux_wlan->txq_thread = kthread_run(linux_wlan_txq_task, (void *)g_linux_wlan, "K_TXQ_TASK");
- if (g_linux_wlan->txq_thread == NULL) {
+ wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev,
+ "K_TXQ_TASK");
+ if (!wilc->txq_thread) {
PRINT_ER("couldn't create TXQ thread\n");
- ret = -ENOBUFS;
- goto _fail_2;
+ wilc->close = 0;
+ return -ENOBUFS;
}
- /* wait for TXQ task to start. */
- down(&g_linux_wlan->txq_thread_started);
+ down(&wilc->txq_thread_started);
return 0;
-
-_fail_2:
- /*De-Initialize 2nd thread*/
- g_linux_wlan->close = 1;
-
- g_linux_wlan->close = 0;
- return ret;
-}
-
-static void wlan_deinitialize_threads(struct wilc *nic)
-{
-
- g_linux_wlan->close = 1;
- PRINT_D(INIT_DBG, "Deinitializing Threads\n");
-
- if (&g_linux_wlan->txq_event != NULL)
- up(&g_linux_wlan->txq_event);
-
- if (g_linux_wlan->txq_thread != NULL) {
- kthread_stop(g_linux_wlan->txq_thread);
- g_linux_wlan->txq_thread = NULL;
- }
}
-#ifdef COMPLEMENT_BOOT
-
-extern volatile int probe;
-extern u8 core_11b_ready(void);
-
-#define READY_CHECK_THRESHOLD 30
-extern void wilc_wlan_global_reset(void);
-u8 wilc1000_prepare_11b_core(wilc_wlan_inp_t *nwi, struct wilc *nic)
+static void wlan_deinitialize_threads(struct net_device *dev)
{
- u8 trials = 0;
-
- while ((core_11b_ready() && (READY_CHECK_THRESHOLD > (trials++)))) {
- PRINT_D(INIT_DBG, "11b core not ready yet: %u\n", trials);
- wilc_wlan_cleanup();
- wilc_wlan_global_reset();
- sdio_unregister_driver(&wilc_bus);
-
- linux_wlan_device_detection(0);
-
- mdelay(100);
-
- linux_wlan_device_detection(1);
-
- sdio_register_driver(&wilc_bus);
-
- while (!probe)
- msleep(100);
- probe = 0;
- g_linux_wlan->wilc_sdio_func = local_sdio_func;
- linux_to_wlan(nwi, nic);
- wilc_wlan_init(nwi);
- }
-
- if (READY_CHECK_THRESHOLD <= trials)
- return 1;
- else
- return 0;
-
-}
-
-int repeat_power_cycle(perInterface_wlan_t *nic)
-{
- int ret = 0;
- wilc_wlan_inp_t nwi;
-
- sdio_unregister_driver(&wilc_bus);
-
- linux_wlan_device_detection(0);
- linux_wlan_device_power(0);
- msleep(100);
- linux_wlan_device_power(1);
- msleep(80);
- linux_wlan_device_detection(1);
- msleep(20);
-
- sdio_register_driver(&wilc_bus);
+ perInterface_wlan_t *nic;
+ struct wilc *wl;
- /* msleep(1000); */
- while (!probe)
- msleep(100);
- probe = 0;
- g_linux_wlan->wilc_sdio_func = local_sdio_func;
- linux_to_wlan(&nwi, g_linux_wlan);
- ret = wilc_wlan_init(&nwi);
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
- g_linux_wlan->mac_status = WILC_MAC_STATUS_INIT;
- #if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
- enable_sdio_interrupt();
- #endif
+ wl->close = 1;
+ PRINT_D(INIT_DBG, "Deinitializing Threads\n");
- if (linux_wlan_get_firmware(nic)) {
- PRINT_ER("Can't get firmware\n");
- ret = -1;
- goto __fail__;
- }
+ if (&wl->txq_event)
+ up(&wl->txq_event);
- /*Download firmware*/
- ret = linux_wlan_firmware_download(g_linux_wlan);
- if (ret < 0) {
- PRINT_ER("Failed to download firmware\n");
- goto __fail__;
+ if (wl->txq_thread) {
+ kthread_stop(wl->txq_thread);
+ wl->txq_thread = NULL;
}
- /* Start firmware*/
- ret = linux_wlan_start_firmware(nic);
- if (ret < 0)
- PRINT_ER("Failed to start firmware\n");
-__fail__:
- return ret;
}
-#endif
int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
{
wilc_wlan_inp_t nwi;
perInterface_wlan_t *nic = p_nic;
int ret = 0;
+ struct wilc *wl = nic->wilc;
- if (!g_linux_wlan->wilc1000_initialized) {
- g_linux_wlan->mac_status = WILC_MAC_STATUS_INIT;
- g_linux_wlan->close = 0;
- g_linux_wlan->wilc1000_initialized = 0;
+ if (!wl->initialized) {
+ wl->mac_status = WILC_MAC_STATUS_INIT;
+ wl->close = 0;
- wlan_init_locks(g_linux_wlan);
+ wlan_init_locks(dev);
- linux_to_wlan(&nwi, g_linux_wlan);
+ linux_to_wlan(&nwi, wl);
- ret = wilc_wlan_init(&nwi);
+ ret = wilc_wlan_init(dev, &nwi);
if (ret < 0) {
PRINT_ER("Initializing WILC_Wlan FAILED\n");
ret = -EIO;
goto _fail_locks_;
}
- ret = wlan_initialize_threads(nic);
- if (ret < 0) {
- PRINT_ER("Initializing Threads FAILED\n");
- ret = -EIO;
- goto _fail_wilc_wlan_;
- }
-
-#if (defined WILC_SDIO) && (defined COMPLEMENT_BOOT)
- if (wilc1000_prepare_11b_core(&nwi, g_linux_wlan)) {
- PRINT_ER("11b Core is not ready\n");
+#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
+ if (init_irq(dev)) {
+ PRINT_ER("couldn't initialize IRQ\n");
ret = -EIO;
- goto _fail_threads_;
+ goto _fail_locks_;
}
#endif
-#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
- if (init_irq(g_linux_wlan)) {
- PRINT_ER("couldn't initialize IRQ\n");
+ ret = wlan_initialize_threads(dev);
+ if (ret < 0) {
+ PRINT_ER("Initializing Threads FAILED\n");
ret = -EIO;
- goto _fail_threads_;
+ goto _fail_wilc_wlan_;
}
-#endif
#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
if (enable_sdio_interrupt()) {
@@ -1190,22 +982,20 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
}
#endif
- if (linux_wlan_get_firmware(nic)) {
+ if (linux_wlan_get_firmware(dev)) {
PRINT_ER("Can't get firmware\n");
ret = -EIO;
goto _fail_irq_enable_;
}
- /*Download firmware*/
- ret = linux_wlan_firmware_download(g_linux_wlan);
+ ret = linux_wlan_firmware_download(dev);
if (ret < 0) {
PRINT_ER("Failed to download firmware\n");
ret = -EIO;
goto _fail_irq_enable_;
}
- /* Start firmware*/
- ret = linux_wlan_start_firmware(nic);
+ ret = linux_wlan_start_firmware(dev);
if (ret < 0) {
PRINT_ER("Failed to start firmware\n");
ret = -EIO;
@@ -1224,8 +1014,7 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
Firmware_ver[size] = '\0';
PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver);
}
- /* Initialize firmware with default configuration */
- ret = linux_wlan_init_test_config(dev, g_linux_wlan);
+ ret = linux_wlan_init_test_config(dev, wl);
if (ret < 0) {
PRINT_ER("Failed to configure firmware\n");
@@ -1233,8 +1022,8 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
goto _fail_fw_start_;
}
- g_linux_wlan->wilc1000_initialized = 1;
- return 0; /*success*/
+ wl->initialized = true;
+ return 0;
_fail_fw_start_:
wilc_wlan_stop();
@@ -1245,15 +1034,14 @@ _fail_irq_enable_:
_fail_irq_init_:
#endif
#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
- deinit_irq(g_linux_wlan);
+ deinit_irq(dev);
#endif
-_fail_threads_:
- wlan_deinitialize_threads(g_linux_wlan);
+ wlan_deinitialize_threads(dev);
_fail_wilc_wlan_:
- wilc_wlan_cleanup();
+ wilc_wlan_cleanup(dev);
_fail_locks_:
- wlan_deinit_locks(g_linux_wlan);
+ wlan_deinit_locks(dev);
PRINT_ER("WLAN Iinitialization FAILED\n");
} else {
PRINT_D(INIT_DBG, "wilc1000 already initialized\n");
@@ -1261,34 +1049,29 @@ _fail_locks_:
return ret;
}
-/*
- * - this function will be called automatically by OS when module inserted.
- */
-
int mac_init_fn(struct net_device *ndev)
{
-
- /*Why we do this !!!*/
- netif_start_queue(ndev); /* ma */
- netif_stop_queue(ndev); /* ma */
+ netif_start_queue(ndev);
+ netif_stop_queue(ndev);
return 0;
}
-/* This fn is called, when this device is setup using ifconfig */
int mac_open(struct net_device *ndev)
{
perInterface_wlan_t *nic;
- /*No need for setting mac address here anymore,*/
- /*Just set it in init_test_config()*/
unsigned char mac_add[ETH_ALEN] = {0};
int ret = 0;
int i = 0;
struct wilc_priv *priv;
+ struct wilc *wl;
+
+ nic = netdev_priv(ndev);
+ wl = nic->wilc;
#ifdef WILC_SPI
- if (!g_linux_wlan || !g_linux_wlan->wilc_spidev) {
+ if (!wl || !wl->wilc_spidev) {
netdev_err(ndev, "wilc1000: SPI device not ready\n");
return -ENODEV;
}
@@ -1304,7 +1087,6 @@ int mac_open(struct net_device *ndev)
return ret;
}
- /*initialize platform*/
PRINT_D(INIT_DBG, "*** re-init ***\n");
ret = wilc1000_wlan_init(ndev, nic);
if (ret < 0) {
@@ -1313,42 +1095,40 @@ int mac_open(struct net_device *ndev)
return ret;
}
- Set_machw_change_vir_if(false);
+ set_machw_change_vir_if(ndev, false);
- host_int_get_MacAddress(priv->hWILCWFIDrv, mac_add);
+ hif_get_mac_address(priv->hWILCWFIDrv, mac_add);
PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add);
- /* loop through the NUM of supported devices and set the MAC address */
- for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- if (ndev == g_linux_wlan->strInterfaceInfo[i].wilc_netdev) {
- memcpy(g_linux_wlan->strInterfaceInfo[i].aSrcAddress, mac_add, ETH_ALEN);
- g_linux_wlan->strInterfaceInfo[i].drvHandler = priv->hWILCWFIDrv;
+ for (i = 0; i < wl->vif_num; i++) {
+ if (ndev == wl->vif[i].ndev) {
+ memcpy(wl->vif[i].src_addr, mac_add, ETH_ALEN);
+ wl->vif[i].hif_drv = priv->hWILCWFIDrv;
break;
}
}
- /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/
- memcpy(ndev->dev_addr, g_linux_wlan->strInterfaceInfo[i].aSrcAddress, ETH_ALEN);
+ memcpy(ndev->dev_addr, wl->vif[i].src_addr, ETH_ALEN);
if (!is_valid_ether_addr(ndev->dev_addr)) {
PRINT_ER("Error: Wrong MAC address\n");
- ret = -EINVAL;
- goto _err_;
- }
-
- wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev->ieee80211_ptr,
- nic->g_struct_frame_reg[0].frame_type, nic->g_struct_frame_reg[0].reg);
- wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev->ieee80211_ptr,
- nic->g_struct_frame_reg[1].frame_type, nic->g_struct_frame_reg[1].reg);
+ wilc_deinit_host_int(ndev);
+ wilc1000_wlan_deinit(ndev);
+ return -EINVAL;
+ }
+
+ wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy,
+ nic->wilc_netdev->ieee80211_ptr,
+ nic->g_struct_frame_reg[0].frame_type,
+ nic->g_struct_frame_reg[0].reg);
+ wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy,
+ nic->wilc_netdev->ieee80211_ptr,
+ nic->g_struct_frame_reg[1].frame_type,
+ nic->g_struct_frame_reg[1].reg);
netif_wake_queue(ndev);
- g_linux_wlan->open_ifcs++;
+ wl->open_ifcs++;
nic->mac_opened = 1;
return 0;
-
-_err_:
- wilc_deinit_host_int(ndev);
- wilc1000_wlan_deinit(g_linux_wlan);
- return ret;
}
struct net_device_stats *mac_stats(struct net_device *dev)
@@ -1358,72 +1138,65 @@ struct net_device_stats *mac_stats(struct net_device *dev)
return &nic->netstats;
}
-/* Setup the multicast filter */
static void wilc_set_multicast_list(struct net_device *dev)
{
-
struct netdev_hw_addr *ha;
struct wilc_priv *priv;
- struct host_if_drv *pstrWFIDrv;
+ struct host_if_drv *hif_drv;
int i = 0;
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
if (!dev)
return;
- PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", dev->mc.count);
+ PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n",
+ dev->mc.count);
if (dev->flags & IFF_PROMISC) {
- /* Normally, we should configure the chip to retrive all packets
- * but we don't wanna support this right now */
- /* TODO: add promiscuous mode support */
PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n");
return;
}
- /* If there's more addresses than we handle, get all multicast
- * packets and sort them out in software. */
- if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
+ if ((dev->flags & IFF_ALLMULTI) ||
+ (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n");
- /* get all multicast packets */
- host_int_setup_multicast_filter(pstrWFIDrv, false, 0);
+ host_int_setup_multicast_filter(hif_drv, false, 0);
return;
}
- /* No multicast? Just get our own stuff */
if ((dev->mc.count) == 0) {
PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n");
- host_int_setup_multicast_filter(pstrWFIDrv, true, 0);
+ host_int_setup_multicast_filter(hif_drv, true, 0);
return;
}
- /* Store all of the multicast addresses in the hardware filter */
- netdev_for_each_mc_addr(ha, dev)
- {
- memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN);
+ netdev_for_each_mc_addr(ha, dev) {
+ memcpy(multicast_mac_addr_list[i], ha->addr, ETH_ALEN);
PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
- gau8MulticastMacAddrList[i][0], gau8MulticastMacAddrList[i][1], gau8MulticastMacAddrList[i][2], gau8MulticastMacAddrList[i][3], gau8MulticastMacAddrList[i][4], gau8MulticastMacAddrList[i][5]);
+ multicast_mac_addr_list[i][0],
+ multicast_mac_addr_list[i][1],
+ multicast_mac_addr_list[i][2],
+ multicast_mac_addr_list[i][3],
+ multicast_mac_addr_list[i][4],
+ multicast_mac_addr_list[i][5]);
i++;
}
- host_int_setup_multicast_filter(pstrWFIDrv, true, (dev->mc.count));
+ host_int_setup_multicast_filter(hif_drv, true, (dev->mc.count));
return;
-
}
static void linux_wlan_tx_complete(void *priv, int status)
{
-
struct tx_complete_data *pv_data = (struct tx_complete_data *)priv;
if (status == 1)
PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
else
PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
- /* Free the SK Buffer, its work is done */
dev_kfree_skb(pv_data->skb);
kfree(pv_data);
}
@@ -1432,23 +1205,24 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
{
perInterface_wlan_t *nic;
struct tx_complete_data *tx_data = NULL;
- int QueueCount;
- char *pu8UdpBuffer;
+ int queue_count;
+ char *udp_buf;
struct iphdr *ih;
struct ethhdr *eth_h;
+ struct wilc *wilc;
nic = netdev_priv(ndev);
+ wilc = nic->wilc;
PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n");
- /* Stop the network interface queue */
if (skb->dev != ndev) {
PRINT_ER("Packet not destined to this device\n");
return 0;
}
- tx_data = kmalloc(sizeof(struct tx_complete_data), GFP_ATOMIC);
- if (tx_data == NULL) {
+ tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
+ if (!tx_data) {
PRINT_ER("Failed to allocate memory for tx_data structure\n");
dev_kfree_skb(skb);
netif_wake_queue(ndev);
@@ -1463,31 +1237,26 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
if (eth_h->h_proto == 0x8e88)
PRINT_D(INIT_DBG, "EAPOL transmitted\n");
- /*get source and dest ip addresses*/
ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
- pu8UdpBuffer = (char *)ih + sizeof(struct iphdr);
- if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68))
- PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", pu8UdpBuffer[248], pu8UdpBuffer[249], pu8UdpBuffer[250]);
+ udp_buf = (char *)ih + sizeof(struct iphdr);
+ if ((udp_buf[1] == 68 && udp_buf[3] == 67) ||
+ (udp_buf[1] == 67 && udp_buf[3] == 68))
+ PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n",
+ udp_buf[248], udp_buf[249], udp_buf[250]);
PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb);
-
- /* Send packet to MAC HW - for now the tx_complete function will be just status
- * indicator. still not sure if I need to suspend host transmission till the tx_complete
- * function called or not?
- * allocated buffer will be freed in tx_complete function.
- */
PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n");
nic->netstats.tx_packets++;
nic->netstats.tx_bytes += tx_data->size;
- tx_data->pBssid = g_linux_wlan->strInterfaceInfo[nic->u8IfIdx].aBSSID;
- QueueCount = wilc_wlan_txq_add_net_pkt((void *)tx_data, tx_data->buff,
- tx_data->size,
- linux_wlan_tx_complete);
-
- if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) {
- netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev);
- netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev);
+ tx_data->pBssid = wilc->vif[nic->u8IfIdx].bssid;
+ queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
+ tx_data->buff, tx_data->size,
+ linux_wlan_tx_complete);
+
+ if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
+ netif_stop_queue(wilc->vif[0].ndev);
+ netif_stop_queue(wilc->vif[1].ndev);
}
return 0;
@@ -1497,54 +1266,56 @@ int mac_close(struct net_device *ndev)
{
struct wilc_priv *priv;
perInterface_wlan_t *nic;
- struct host_if_drv *pstrWFIDrv;
+ struct host_if_drv *hif_drv;
+ struct wilc *wl;
nic = netdev_priv(ndev);
- if ((nic == NULL) || (nic->wilc_netdev == NULL) || (nic->wilc_netdev->ieee80211_ptr == NULL) || (nic->wilc_netdev->ieee80211_ptr->wiphy == NULL)) {
+ if (!nic || !nic->wilc_netdev || !nic->wilc_netdev->ieee80211_ptr ||
+ !nic->wilc_netdev->ieee80211_ptr->wiphy) {
PRINT_ER("nic = NULL\n");
return 0;
}
priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
+ wl = nic->wilc;
- if (priv == NULL) {
+ if (!priv) {
PRINT_ER("priv = NULL\n");
return 0;
}
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
PRINT_D(GENERIC_DBG, "Mac close\n");
- if (g_linux_wlan == NULL) {
- PRINT_ER("g_linux_wlan = NULL\n");
+ if (!wl) {
+ PRINT_ER("wl = NULL\n");
return 0;
}
- if (pstrWFIDrv == NULL) {
- PRINT_ER("pstrWFIDrv = NULL\n");
+ if (!hif_drv) {
+ PRINT_ER("hif_drv = NULL\n");
return 0;
}
- if ((g_linux_wlan->open_ifcs) > 0) {
- g_linux_wlan->open_ifcs--;
+ if ((wl->open_ifcs) > 0) {
+ wl->open_ifcs--;
} else {
PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n");
return 0;
}
- if (nic->wilc_netdev != NULL) {
- /* Stop the network interface queue */
+ if (nic->wilc_netdev) {
netif_stop_queue(nic->wilc_netdev);
wilc_deinit_host_int(nic->wilc_netdev);
}
- if (g_linux_wlan->open_ifcs == 0) {
+ if (wl->open_ifcs == 0) {
PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n");
- g_linux_wlan->close = 1;
- wilc1000_wlan_deinit(g_linux_wlan);
+ wl->close = 1;
+ wilc1000_wlan_deinit(ndev);
WILC_WFI_deinit_mon_interface();
}
@@ -1556,50 +1327,48 @@ int mac_close(struct net_device *ndev)
int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
{
-
u8 *buff = NULL;
s8 rssi;
u32 size = 0, length = 0;
perInterface_wlan_t *nic;
struct wilc_priv *priv;
- s32 s32Error = 0;
+ s32 ret = 0;
+ struct wilc *wilc;
- /* struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV */
nic = netdev_priv(ndev);
+ wilc = nic->wilc;
- if (!g_linux_wlan->wilc1000_initialized)
+ if (!wilc->initialized)
return 0;
switch (cmd) {
-
- /* ]] 2013-06-24 */
case SIOCSIWPRIV:
{
- struct iwreq *wrq = (struct iwreq *) req; /* added by tony */
+ struct iwreq *wrq = (struct iwreq *) req;
size = wrq->u.data.length;
if (size && wrq->u.data.pointer) {
-
- buff = memdup_user(wrq->u.data.pointer, wrq->u.data.length);
+ buff = memdup_user(wrq->u.data.pointer,
+ wrq->u.data.length);
if (IS_ERR(buff))
return PTR_ERR(buff);
if (strncasecmp(buff, "RSSI", length) == 0) {
priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
- s32Error = host_int_get_rssi(priv->hWILCWFIDrv, &(rssi));
- if (s32Error)
+ ret = host_int_get_rssi(priv->hWILCWFIDrv,
+ &rssi);
+ if (ret)
PRINT_ER("Failed to send get rssi param's message queue ");
PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi);
- /*Rounding up the rssi negative value*/
rssi += 5;
snprintf(buff, size, "rssi %d", rssi);
if (copy_to_user(wrq->u.data.pointer, buff, size)) {
PRINT_ER("%s: failed to copy data to user buffer\n", __func__);
- s32Error = -EFAULT;
+ ret = -EFAULT;
goto done;
}
}
@@ -1610,7 +1379,7 @@ int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
default:
{
PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd);
- s32Error = -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
goto done;
}
}
@@ -1619,12 +1388,11 @@ done:
kfree(buff);
- return s32Error;
+ return ret;
}
-void frmw_to_linux(u8 *buff, u32 size, u32 pkt_offset)
+void frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset)
{
-
unsigned int frame_len = 0;
int stats;
unsigned char *buff_to_send = NULL;
@@ -1632,49 +1400,33 @@ void frmw_to_linux(u8 *buff, u32 size, u32 pkt_offset)
struct net_device *wilc_netdev;
perInterface_wlan_t *nic;
- wilc_netdev = GetIfHandler(buff);
- if (wilc_netdev == NULL)
+ wilc_netdev = get_if_handler(wilc, buff);
+ if (!wilc_netdev)
return;
buff += pkt_offset;
nic = netdev_priv(wilc_netdev);
if (size > 0) {
-
frame_len = size;
buff_to_send = buff;
- /* Need to send the packet up to the host, allocate a skb buffer */
skb = dev_alloc_skb(frame_len);
- if (skb == NULL) {
+ if (!skb) {
PRINT_ER("Low memory - packet droped\n");
return;
}
- if (g_linux_wlan == NULL || wilc_netdev == NULL)
- PRINT_ER("wilc_netdev in g_linux_wlan is NULL");
+ if (!wilc || !wilc_netdev)
+ PRINT_ER("wilc_netdev in wilc is NULL");
skb->dev = wilc_netdev;
- if (skb->dev == NULL)
+ if (!skb->dev)
PRINT_ER("skb->dev is NULL\n");
- /*
- * for(i=0;i<40;i++)
- * {
- * if(i<frame_len)
- * WILC_PRINTF("buff_to_send[%d]=%2x\n",i,buff_to_send[i]);
- *
- * }*/
-
- /* skb_put(skb, frame_len); */
memcpy(skb_put(skb, frame_len), buff_to_send, frame_len);
- /* WILC_PRINTF("After MEM_CPY\n"); */
-
- /* nic = netdev_priv(wilc_netdev); */
-
skb->protocol = eth_type_trans(skb, wilc_netdev);
- /* Send the packet to the stack by giving it to the bridge */
nic->netstats.rx_packets++;
nic->netstats.rx_bytes += frame_len;
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1683,45 +1435,81 @@ void frmw_to_linux(u8 *buff, u32 size, u32 pkt_offset)
}
}
-void WILC_WFI_mgmt_rx(u8 *buff, u32 size)
+void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
{
int i = 0;
perInterface_wlan_t *nic;
- /*Pass the frame on the monitor interface, if any.*/
- /*Otherwise, pass it on p2p0 netdev, if registered on it*/
- for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- nic = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
+ for (i = 0; i < wilc->vif_num; i++) {
+ nic = netdev_priv(wilc->vif[i].ndev);
if (nic->monitor_flag) {
WILC_WFI_monitor_rx(buff, size);
return;
}
}
- nic = netdev_priv(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); /* p2p0 */
+ nic = netdev_priv(wilc->vif[1].ndev);
if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) ||
(buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg))
- WILC_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[1].wilc_netdev, buff, size);
+ WILC_WFI_p2p_rx(wilc->vif[1].ndev, buff, size);
}
-int wilc_netdev_init(void)
+void wl_wlan_cleanup(struct wilc *wilc)
{
+ int i = 0;
+ perInterface_wlan_t *nic[NUM_CONCURRENT_IFC];
+
+ if (wilc && (wilc->vif[0].ndev || wilc->vif[1].ndev)) {
+ unregister_inetaddr_notifier(&g_dev_notifier);
+
+ for (i = 0; i < NUM_CONCURRENT_IFC; i++)
+ nic[i] = netdev_priv(wilc->vif[i].ndev);
+ }
+
+ if (wilc && wilc->firmware)
+ release_firmware(wilc->firmware);
+
+ if (wilc && (wilc->vif[0].ndev || wilc->vif[1].ndev)) {
+ linux_wlan_lock_timeout(&close_exit_sync, 12 * 1000);
+
+ for (i = 0; i < NUM_CONCURRENT_IFC; i++)
+ if (wilc->vif[i].ndev)
+ if (nic[i]->mac_opened)
+ mac_close(wilc->vif[i].ndev);
+
+ for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
+ unregister_netdev(wilc->vif[i].ndev);
+ wilc_free_wiphy(wilc->vif[i].ndev);
+ free_netdev(wilc->vif[i].ndev);
+ }
+ }
+
+ kfree(wilc);
+
+#if defined(WILC_DEBUGFS)
+ wilc_debugfs_remove();
+#endif
+ linux_wlan_device_detection(0);
+ linux_wlan_device_power(0);
+}
+int wilc_netdev_init(struct wilc **wilc)
+{
int i;
perInterface_wlan_t *nic;
struct net_device *ndev;
sema_init(&close_exit_sync, 0);
- /*create the common structure*/
g_linux_wlan = kzalloc(sizeof(*g_linux_wlan), GFP_KERNEL);
if (!g_linux_wlan)
return -ENOMEM;
+ *wilc = g_linux_wlan;
+
register_inetaddr_notifier(&g_dev_notifier);
for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
- /*allocate first ethernet device with perinterface_wlan_t as its private data*/
ndev = alloc_etherdev(sizeof(perInterface_wlan_t));
if (!ndev) {
PRINT_ER("Failed to allocate ethernet dev\n");
@@ -1731,40 +1519,31 @@ int wilc_netdev_init(void)
nic = netdev_priv(ndev);
memset(nic, 0, sizeof(perInterface_wlan_t));
- /*Name the Devices*/
- if (i == 0) {
- #if defined(NM73131) /* tony, 2012-09-20 */
- strcpy(ndev->name, "wilc_eth%d");
- #elif defined(PLAT_CLM9722) /* rachel */
- strcpy(ndev->name, "eth%d");
- #else /* PANDA_BOARD, PLAT_ALLWINNER_A10, PLAT_ALLWINNER_A20, PLAT_ALLWINNER_A31, PLAT_AML8726_M3 or PLAT_WMS8304 */
+ if (i == 0)
strcpy(ndev->name, "wlan%d");
- #endif
- } else
+ else
strcpy(ndev->name, "p2p%d");
- nic->u8IfIdx = g_linux_wlan->u8NoIfcs;
+ nic->u8IfIdx = g_linux_wlan->vif_num;
nic->wilc_netdev = ndev;
- g_linux_wlan->strInterfaceInfo[g_linux_wlan->u8NoIfcs].wilc_netdev = ndev;
- g_linux_wlan->u8NoIfcs++;
+ nic->wilc = *wilc;
+ g_linux_wlan->vif[g_linux_wlan->vif_num].ndev = ndev;
+ g_linux_wlan->vif_num++;
ndev->netdev_ops = &wilc_netdev_ops;
{
struct wireless_dev *wdev;
- /*Register WiFi*/
wdev = wilc_create_wiphy(ndev);
#ifdef WILC_SDIO
- /* set netdev, tony */
SET_NETDEV_DEV(ndev, &local_sdio_func->dev);
#endif
- if (wdev == NULL) {
+ if (!wdev) {
PRINT_ER("Can't register WILC Wiphy\n");
return -1;
}
- /*linking the wireless_dev structure with the netdevice*/
nic->wilc_netdev->ieee80211_ptr = wdev;
nic->wilc_netdev->ml_priv = nic;
wdev->netdev = nic->wilc_netdev;
@@ -1772,23 +1551,22 @@ int wilc_netdev_init(void)
nic->netstats.tx_packets = 0;
nic->netstats.rx_bytes = 0;
nic->netstats.tx_bytes = 0;
-
}
if (register_netdev(ndev)) {
- PRINT_ER("Device couldn't be registered - %s\n", ndev->name);
- return -1; /* ERROR */
+ PRINT_ER("Device couldn't be registered - %s\n",
+ ndev->name);
+ return -1;
}
nic->iftype = STATION_MODE;
nic->mac_opened = 0;
-
}
#ifndef WILC_SDIO
- if (!linux_spi_init(&g_linux_wlan->wilc_spidev)) {
+ if (!linux_spi_init()) {
PRINT_ER("Can't initialize SPI\n");
- return -1; /* ERROR */
+ return -1;
}
g_linux_wlan->wilc_spidev = wilc_spi_dev;
#else
@@ -1798,9 +1576,12 @@ int wilc_netdev_init(void)
return 0;
}
-/*The 1st function called after module inserted*/
static int __init init_wilc_driver(void)
{
+#ifdef WILC_SPI
+ struct wilc *wilc;
+#endif
+
#if defined(WILC_DEBUGFS)
if (wilc_debugfs_init() < 0) {
PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n");
@@ -1827,7 +1608,7 @@ static int __init init_wilc_driver(void)
}
#else
PRINT_D(INIT_DBG, "Initializing netdev\n");
- if (wilc_netdev_init())
+ if (wilc_netdev_init(&wilc))
PRINT_ER("Couldn't initialize netdev\n");
return 0;
#endif
@@ -1836,67 +1617,13 @@ late_initcall(init_wilc_driver);
static void __exit exit_wilc_driver(void)
{
- int i = 0;
- perInterface_wlan_t *nic[NUM_CONCURRENT_IFC] = {NULL,};
- #define CLOSE_TIMEOUT (12 * 1000)
-
- if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL)
- || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) {
- unregister_inetaddr_notifier(&g_dev_notifier);
-
- for (i = 0; i < NUM_CONCURRENT_IFC; i++)
- nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- }
-
- if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) {
- release_firmware(g_linux_wlan->wilc_firmware);
- g_linux_wlan->wilc_firmware = NULL;
- }
-
- if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL)
- || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) {
- PRINT_D(INIT_DBG, "Waiting for mac_close ....\n");
-
- if (linux_wlan_lock_timeout(&close_exit_sync, CLOSE_TIMEOUT) < 0)
- PRINT_D(INIT_DBG, "Closed TimedOUT\n");
- else
- PRINT_D(INIT_DBG, "mac_closed\n");
-
- for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
- /* close all opened interfaces */
- if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) {
- if (nic[i]->mac_opened)
- mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- }
- }
- for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
- PRINT_D(INIT_DBG, "Unregistering netdev %p\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- unregister_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- PRINT_D(INIT_DBG, "Freeing Wiphy...\n");
- wilc_free_wiphy(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- PRINT_D(INIT_DBG, "Freeing netdev...\n");
- free_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- }
- }
-
#ifndef WILC_SDIO
- PRINT_D(INIT_DBG, "SPI unregsiter...\n");
+ PRINT_D(INIT_DBG, "SPI unregister...\n");
spi_unregister_driver(&wilc_bus);
#else
- PRINT_D(INIT_DBG, "SDIO unregsiter...\n");
+ PRINT_D(INIT_DBG, "SDIO unregister...\n");
sdio_unregister_driver(&wilc_bus);
#endif
-
- kfree(g_linux_wlan);
- g_linux_wlan = NULL;
- printk("Module_exit Done.\n");
-
-#if defined(WILC_DEBUGFS)
- wilc_debugfs_remove();
-#endif
-
- linux_wlan_device_detection(0);
- linux_wlan_device_power(0);
}
module_exit(exit_wilc_driver);
diff --git a/drivers/staging/wilc1000/linux_wlan_sdio.c b/drivers/staging/wilc1000/linux_wlan_sdio.c
index ebacd297abca..e854d376878f 100644
--- a/drivers/staging/wilc1000/linux_wlan_sdio.c
+++ b/drivers/staging/wilc1000/linux_wlan_sdio.c
@@ -21,10 +21,12 @@
#define MAX_SPEED (6 * 1000000) /* Max 50M */
#endif
+struct wilc_sdio {
+ struct sdio_func *func;
+ struct wilc *wilc;
+};
struct sdio_func *local_sdio_func;
-extern int wilc_netdev_init(void);
-extern void wilc_handle_isr(void);
static unsigned int sdio_default_speed;
@@ -39,9 +41,13 @@ static const struct sdio_device_id wilc_sdio_ids[] = {
static void wilc_sdio_interrupt(struct sdio_func *func)
{
+ struct wilc_sdio *wl_sdio;
+
+ wl_sdio = sdio_get_drvdata(func);
+
#ifndef WILC_SDIO_IRQ_GPIO
sdio_release_host(func);
- wilc_handle_isr();
+ wilc_handle_isr(wl_sdio->wilc);
sdio_claim_host(func);
#endif
}
@@ -110,25 +116,26 @@ int linux_sdio_cmd53(sdio_cmd53_t *cmd)
return 1;
}
-volatile int probe; /* COMPLEMENT_BOOT */
static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
{
+ struct wilc_sdio *wl_sdio;
+ struct wilc *wilc;
+
PRINT_D(INIT_DBG, "probe function\n");
+ wl_sdio = kzalloc(sizeof(struct wilc_sdio), GFP_KERNEL);
+ if (!wl_sdio)
+ return -ENOMEM;
-#ifdef COMPLEMENT_BOOT
- if (local_sdio_func != NULL) {
- local_sdio_func = func;
- probe = 1;
- PRINT_D(INIT_DBG, "local_sdio_func isn't NULL\n");
- return 0;
- }
-#endif
PRINT_D(INIT_DBG, "Initializing netdev\n");
local_sdio_func = func;
- if (wilc_netdev_init()) {
+ if (wilc_netdev_init(&wilc)) {
PRINT_ER("Couldn't initialize netdev\n");
+ kfree(wl_sdio);
return -1;
}
+ wl_sdio->func = func;
+ wl_sdio->wilc = wilc;
+ sdio_set_drvdata(func, wl_sdio);
printk("Driver Initializing success\n");
return 0;
@@ -136,10 +143,11 @@ static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id
static void linux_sdio_remove(struct sdio_func *func)
{
- /**
- * TODO
- **/
+ struct wilc_sdio *wl_sdio;
+ wl_sdio = sdio_get_drvdata(func);
+ wl_wlan_cleanup(wl_sdio->wilc);
+ kfree(wl_sdio);
}
struct sdio_driver wilc_bus = {
@@ -206,7 +214,7 @@ static int linux_sdio_get_speed(void)
return local_sdio_func->card->host->ios.clock;
}
-int linux_sdio_init(void *pv)
+int linux_sdio_init(void)
{
/**
diff --git a/drivers/staging/wilc1000/linux_wlan_sdio.h b/drivers/staging/wilc1000/linux_wlan_sdio.h
index 4b515f5108e7..6f42bc75b507 100644
--- a/drivers/staging/wilc1000/linux_wlan_sdio.h
+++ b/drivers/staging/wilc1000/linux_wlan_sdio.h
@@ -3,7 +3,7 @@ extern struct sdio_driver wilc_bus;
#include <linux/mmc/sdio_func.h>
-int linux_sdio_init(void *);
+int linux_sdio_init(void);
void linux_sdio_deinit(void *);
int linux_sdio_cmd52(sdio_cmd52_t *cmd);
int linux_sdio_cmd53(sdio_cmd53_t *cmd);
diff --git a/drivers/staging/wilc1000/linux_wlan_spi.c b/drivers/staging/wilc1000/linux_wlan_spi.c
index 039d06192d6b..73c788f602c0 100644
--- a/drivers/staging/wilc1000/linux_wlan_spi.c
+++ b/drivers/staging/wilc1000/linux_wlan_spi.c
@@ -93,7 +93,7 @@ void linux_spi_deinit(void *vp)
-int linux_spi_init(void *vp)
+int linux_spi_init(void)
{
int ret = 1;
static int called;
diff --git a/drivers/staging/wilc1000/linux_wlan_spi.h b/drivers/staging/wilc1000/linux_wlan_spi.h
index 7356785296f9..b9561003ecf0 100644
--- a/drivers/staging/wilc1000/linux_wlan_spi.h
+++ b/drivers/staging/wilc1000/linux_wlan_spi.h
@@ -5,7 +5,7 @@
extern struct spi_device *wilc_spi_dev;
extern struct spi_driver wilc_bus;
-int linux_spi_init(void *vp);
+int linux_spi_init(void);
void linux_spi_deinit(void *vp);
int linux_spi_write(u8 *b, u32 len);
int linux_spi_read(u8 *rb, u32 rlen);
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c
index b13809a4b556..0eff121b8291 100644
--- a/drivers/staging/wilc1000/wilc_msgqueue.c
+++ b/drivers/staging/wilc1000/wilc_msgqueue.c
@@ -56,37 +56,35 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle)
int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
const void *pvSendBuffer, u32 u32SendBufferSize)
{
- int result = 0;
unsigned long flags;
Message *pstrMessage = NULL;
if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) {
PRINT_ER("pHandle or pvSendBuffer is null\n");
- result = -EFAULT;
- goto ERRORHANDLER;
+ return -EFAULT;
}
if (pHandle->bExiting) {
PRINT_ER("pHandle fail\n");
- result = -EFAULT;
- goto ERRORHANDLER;
+ return -EFAULT;
}
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
-
/* construct a new message */
pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
if (!pstrMessage)
return -ENOMEM;
+
pstrMessage->u32Length = u32SendBufferSize;
pstrMessage->pstrNext = NULL;
pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize,
GFP_ATOMIC);
if (!pstrMessage->pvBuffer) {
- result = -ENOMEM;
- goto ERRORHANDLER;
+ kfree(pstrMessage);
+ return -ENOMEM;
}
+ spin_lock_irqsave(&pHandle->strCriticalSection, flags);
+
/* add it to the message queue */
if (!pHandle->pstrMessageList) {
pHandle->pstrMessageList = pstrMessage;
@@ -103,14 +101,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
up(&pHandle->hSem);
-ERRORHANDLER:
- /* error occured, free any allocations */
- if (pstrMessage) {
- kfree(pstrMessage->pvBuffer);
- kfree(pstrMessage);
- }
-
- return result;
+ return 0;
}
/*!
diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c
index 300c571e4e2d..8aacf55e5eb8 100644
--- a/drivers/staging/wilc1000/wilc_sdio.c
+++ b/drivers/staging/wilc1000/wilc_sdio.c
@@ -10,16 +10,13 @@
#include <linux/string.h>
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
+#include "linux_wlan_sdio.h"
+#include "wilc_wfi_netdevice.h"
#define WILC_SDIO_BLOCK_SIZE 512
typedef struct {
- void *os_context;
u32 block_size;
- int (*sdio_cmd52)(sdio_cmd52_t *);
- int (*sdio_cmd53)(sdio_cmd53_t *);
- int (*sdio_set_max_speed)(void);
- int (*sdio_set_default_speed)(void);
wilc_debug_func dPrint;
int nint;
#define MAX_NUN_INT_THRPT_ENH2 (5) /* Max num interrupts allowed in registers 0xf7, 0xf8 */
@@ -51,21 +48,21 @@ static int sdio_set_func0_csa_address(u32 adr)
cmd.raw = 0;
cmd.address = 0x10c;
cmd.data = (u8)adr;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10c data...\n");
goto _fail_;
}
cmd.address = 0x10d;
cmd.data = (u8)(adr >> 8);
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10d data...\n");
goto _fail_;
}
cmd.address = 0x10e;
cmd.data = (u8)(adr >> 16);
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10e data...\n");
goto _fail_;
}
@@ -84,14 +81,14 @@ static int sdio_set_func0_block_size(u32 block_size)
cmd.raw = 0;
cmd.address = 0x10;
cmd.data = (u8)block_size;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10 data...\n");
goto _fail_;
}
cmd.address = 0x11;
cmd.data = (u8)(block_size >> 8);
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x11 data...\n");
goto _fail_;
}
@@ -116,13 +113,13 @@ static int sdio_set_func1_block_size(u32 block_size)
cmd.raw = 0;
cmd.address = 0x110;
cmd.data = (u8)block_size;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x110 data...\n");
goto _fail_;
}
cmd.address = 0x111;
cmd.data = (u8)(block_size >> 8);
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x111 data...\n");
goto _fail_;
}
@@ -143,7 +140,7 @@ static int sdio_clear_int(void)
cmd.raw = 0;
cmd.address = 0x4;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
return cmd.data;
#else
@@ -170,7 +167,7 @@ u32 sdio_xfer_cnt(void)
cmd.raw = 0;
cmd.address = 0x1C;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
cnt = cmd.data;
cmd.read_write = 0;
@@ -178,7 +175,7 @@ u32 sdio_xfer_cnt(void)
cmd.raw = 0;
cmd.address = 0x1D;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
cnt |= (cmd.data << 8);
cmd.read_write = 0;
@@ -186,7 +183,7 @@ u32 sdio_xfer_cnt(void)
cmd.raw = 0;
cmd.address = 0x1E;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
cnt |= (cmd.data << 16);
return cnt;
@@ -209,7 +206,7 @@ int sdio_check_bs(void)
cmd.raw = 0;
cmd.address = 0xc;
cmd.data = 0;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get BS register...\n");
goto _fail_;
}
@@ -235,7 +232,7 @@ static int sdio_write_reg(u32 addr, u32 data)
cmd.raw = 0;
cmd.address = addr;
cmd.data = data;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr);
goto _fail_;
}
@@ -257,7 +254,7 @@ static int sdio_write_reg(u32 addr, u32 data)
cmd.buffer = (u8 *)&data;
cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */
- if (!g_sdio.sdio_cmd53(&cmd)) {
+ if (!linux_sdio_cmd53(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, write reg (%08x)...\n", addr);
goto _fail_;
}
@@ -320,7 +317,7 @@ static int sdio_write(u32 addr, u8 *buf, u32 size)
if (!sdio_set_func0_csa_address(addr))
goto _fail_;
}
- if (!g_sdio.sdio_cmd53(&cmd)) {
+ if (!linux_sdio_cmd53(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr);
goto _fail_;
}
@@ -341,7 +338,7 @@ static int sdio_write(u32 addr, u8 *buf, u32 size)
if (!sdio_set_func0_csa_address(addr))
goto _fail_;
}
- if (!g_sdio.sdio_cmd53(&cmd)) {
+ if (!linux_sdio_cmd53(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr);
goto _fail_;
}
@@ -363,7 +360,7 @@ static int sdio_read_reg(u32 addr, u32 *data)
cmd.function = 0;
cmd.raw = 0;
cmd.address = addr;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr);
goto _fail_;
}
@@ -384,7 +381,7 @@ static int sdio_read_reg(u32 addr, u32 *data)
cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */
- if (!g_sdio.sdio_cmd53(&cmd)) {
+ if (!linux_sdio_cmd53(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, read reg (%08x)...\n", addr);
goto _fail_;
}
@@ -451,7 +448,7 @@ static int sdio_read(u32 addr, u8 *buf, u32 size)
if (!sdio_set_func0_csa_address(addr))
goto _fail_;
}
- if (!g_sdio.sdio_cmd53(&cmd)) {
+ if (!linux_sdio_cmd53(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
goto _fail_;
}
@@ -472,7 +469,7 @@ static int sdio_read(u32 addr, u8 *buf, u32 size)
if (!sdio_set_func0_csa_address(addr))
goto _fail_;
}
- if (!g_sdio.sdio_cmd53(&cmd)) {
+ if (!linux_sdio_cmd53(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes read...\n", addr);
goto _fail_;
}
@@ -554,7 +551,7 @@ static int sdio_sync(void)
return 1;
}
-static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
+static int sdio_init(struct wilc *wilc, wilc_debug_func func)
{
sdio_cmd52_t cmd;
int loop;
@@ -563,22 +560,14 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
memset(&g_sdio, 0, sizeof(wilc_sdio_t));
g_sdio.dPrint = func;
- g_sdio.os_context = inp->os_context.os_private;
- if (inp->io_func.io_init) {
- if (!inp->io_func.io_init(g_sdio.os_context)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed io init bus...\n");
- return 0;
- }
+ if (!linux_sdio_init()) {
+ g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed io init bus...\n");
+ return 0;
} else {
return 0;
}
- g_sdio.sdio_cmd52 = inp->io_func.u.sdio.sdio_cmd52;
- g_sdio.sdio_cmd53 = inp->io_func.u.sdio.sdio_cmd53;
- g_sdio.sdio_set_max_speed = inp->io_func.u.sdio.sdio_set_max_speed;
- g_sdio.sdio_set_default_speed = inp->io_func.u.sdio.sdio_set_default_speed;
-
/**
* function 0 csa enable
**/
@@ -587,7 +576,7 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
cmd.raw = 1;
cmd.address = 0x100;
cmd.data = 0x80;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, enable csa...\n");
goto _fail_;
}
@@ -609,7 +598,7 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
cmd.raw = 1;
cmd.address = 0x2;
cmd.data = 0x2;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio] Fail cmd 52, set IOE register...\n");
goto _fail_;
}
@@ -624,7 +613,7 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
loop = 3;
do {
cmd.data = 0;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get IOR register...\n");
goto _fail_;
}
@@ -653,7 +642,7 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
cmd.raw = 1;
cmd.address = 0x4;
cmd.data = 0x3;
- if (!g_sdio.sdio_cmd52(&cmd)) {
+ if (!linux_sdio_cmd52(&cmd)) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set IEN register...\n");
goto _fail_;
}
@@ -681,12 +670,12 @@ _fail_:
static void sdio_set_max_speed(void)
{
- g_sdio.sdio_set_max_speed();
+ linux_sdio_set_max_speed();
}
static void sdio_set_default_speed(void)
{
- g_sdio.sdio_set_default_speed();
+ linux_sdio_set_default_speed();
}
static int sdio_read_size(u32 *size)
@@ -703,7 +692,7 @@ static int sdio_read_size(u32 *size)
cmd.raw = 0;
cmd.address = 0xf2;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
tmp = cmd.data;
/* cmd.read_write = 0; */
@@ -711,7 +700,7 @@ static int sdio_read_size(u32 *size)
/* cmd.raw = 0; */
cmd.address = 0xf3;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
tmp |= (cmd.data << 8);
*size = tmp;
@@ -733,7 +722,7 @@ static int sdio_read_int(u32 *int_status)
cmd.function = 1;
cmd.address = 0x04;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
if (cmd.data & BIT(0))
tmp |= INT_0;
@@ -766,7 +755,7 @@ static int sdio_read_int(u32 *int_status)
cmd.raw = 0;
cmd.address = 0xf7;
cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
+ linux_sdio_cmd52(&cmd);
irq_flags = cmd.data & 0x1f;
tmp |= ((irq_flags >> 0) << IRG_FLAGS_OFFSET);
}
@@ -813,7 +802,7 @@ static int sdio_clear_int_ext(u32 val)
cmd.address = 0xf8;
cmd.data = reg;
- ret = g_sdio.sdio_cmd52(&cmd);
+ ret = linux_sdio_cmd52(&cmd);
if (!ret) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__);
goto _fail_;
@@ -842,7 +831,7 @@ static int sdio_clear_int_ext(u32 val)
cmd.address = 0xf8;
cmd.data = BIT(i);
- ret = g_sdio.sdio_cmd52(&cmd);
+ ret = linux_sdio_cmd52(&cmd);
if (!ret) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__);
goto _fail_;
@@ -886,7 +875,7 @@ static int sdio_clear_int_ext(u32 val)
cmd.raw = 0;
cmd.address = 0xf6;
cmd.data = vmm_ctl;
- ret = g_sdio.sdio_cmd52(&cmd);
+ ret = linux_sdio_cmd52(&cmd);
if (!ret) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf6 data (%d) ...\n", __LINE__);
goto _fail_;
@@ -992,7 +981,7 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */)
*
********************************************/
-wilc_hif_func_t hif_sdio = {
+struct wilc_hif_func hif_sdio = {
sdio_init,
sdio_deinit,
sdio_read_reg,
diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c
index 599508beabf8..3741836dad41 100644
--- a/drivers/staging/wilc1000/wilc_spi.c
+++ b/drivers/staging/wilc1000/wilc_spi.c
@@ -10,13 +10,10 @@
#include <linux/string.h>
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
+#include "linux_wlan_spi.h"
+#include "wilc_wfi_netdevice.h"
typedef struct {
- void *os_context;
- int (*spi_tx)(u8 *, u32);
- int (*spi_rx)(u8 *, u32);
- int (*spi_trx)(u8 *, u8 *, u32);
- int (*spi_max_speed)(void);
wilc_debug_func dPrint;
int crc_off;
int nint;
@@ -25,8 +22,8 @@ typedef struct {
static wilc_spi_t g_spi;
-static int spi_read(u32, u8 *, u32);
-static int spi_write(u32, u8 *, u32);
+static int wilc_spi_read(u32, u8 *, u32);
+static int wilc_spi_write(u32, u8 *, u32);
/********************************************
*
@@ -211,7 +208,7 @@ static int spi_cmd(u8 cmd, u32 adr, u32 data, u32 sz, u8 clockless)
else
len -= 1;
- if (!g_spi.spi_tx(bc, len)) {
+ if (!linux_spi_write(bc, len)) {
PRINT_ER("[wilc spi]: Failed cmd write, bus error...\n");
result = N_FAIL;
}
@@ -231,13 +228,13 @@ static int spi_cmd_rsp(u8 cmd)
if ((cmd == CMD_RESET) ||
(cmd == CMD_TERMINATE) ||
(cmd == CMD_REPEAT)) {
- if (!g_spi.spi_rx(&rsp, 1)) {
+ if (!linux_spi_read(&rsp, 1)) {
result = N_FAIL;
goto _fail_;
}
}
- if (!g_spi.spi_rx(&rsp, 1)) {
+ if (!linux_spi_read(&rsp, 1)) {
PRINT_ER("[wilc spi]: Failed cmd response read, bus error...\n");
result = N_FAIL;
goto _fail_;
@@ -252,7 +249,7 @@ static int spi_cmd_rsp(u8 cmd)
/**
* State response
**/
- if (!g_spi.spi_rx(&rsp, 1)) {
+ if (!linux_spi_read(&rsp, 1)) {
PRINT_ER("[wilc spi]: Failed cmd state read, bus error...\n");
result = N_FAIL;
goto _fail_;
@@ -409,7 +406,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
}
rix = len;
- if (!g_spi.spi_trx(wb, rb, len2)) {
+ if (!linux_spi_write_read(wb, rb, len2)) {
PRINT_ER("[wilc spi]: Failed cmd write, bus error...\n");
result = N_FAIL;
return result;
@@ -524,7 +521,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
/**
* Read bytes
**/
- if (!g_spi.spi_rx(&b[ix], nbytes)) {
+ if (!linux_spi_read(&b[ix], nbytes)) {
PRINT_ER("[wilc spi]: Failed data block read, bus error...\n");
result = N_FAIL;
goto _error_;
@@ -534,7 +531,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
* Read Crc
**/
if (!g_spi.crc_off) {
- if (!g_spi.spi_rx(crc, 2)) {
+ if (!linux_spi_read(crc, 2)) {
PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n");
result = N_FAIL;
goto _error_;
@@ -565,7 +562,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
**/
retry = 10;
do {
- if (!g_spi.spi_rx(&rsp, 1)) {
+ if (!linux_spi_read(&rsp, 1)) {
PRINT_ER("[wilc spi]: Failed data response read, bus error...\n");
result = N_FAIL;
break;
@@ -581,7 +578,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
/**
* Read bytes
**/
- if (!g_spi.spi_rx(&b[ix], nbytes)) {
+ if (!linux_spi_read(&b[ix], nbytes)) {
PRINT_ER("[wilc spi]: Failed data block read, bus error...\n");
result = N_FAIL;
break;
@@ -591,7 +588,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
* Read Crc
**/
if (!g_spi.crc_off) {
- if (!g_spi.spi_rx(crc, 2)) {
+ if (!linux_spi_read(crc, 2)) {
PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n");
result = N_FAIL;
break;
@@ -629,7 +626,7 @@ static int spi_data_read(u8 *b, u32 sz)
**/
retry = 10;
do {
- if (!g_spi.spi_rx(&rsp, 1)) {
+ if (!linux_spi_read(&rsp, 1)) {
PRINT_ER("[wilc spi]: Failed data response read, bus error...\n");
result = N_FAIL;
break;
@@ -650,7 +647,7 @@ static int spi_data_read(u8 *b, u32 sz)
/**
* Read bytes
**/
- if (!g_spi.spi_rx(&b[ix], nbytes)) {
+ if (!linux_spi_read(&b[ix], nbytes)) {
PRINT_ER("[wilc spi]: Failed data block read, bus error...\n");
result = N_FAIL;
break;
@@ -660,7 +657,7 @@ static int spi_data_read(u8 *b, u32 sz)
* Read Crc
**/
if (!g_spi.crc_off) {
- if (!g_spi.spi_rx(crc, 2)) {
+ if (!linux_spi_read(crc, 2)) {
PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n");
result = N_FAIL;
break;
@@ -709,7 +706,7 @@ static int spi_data_write(u8 *b, u32 sz)
order = 0x2;
}
cmd |= order;
- if (!g_spi.spi_tx(&cmd, 1)) {
+ if (!linux_spi_write(&cmd, 1)) {
PRINT_ER("[wilc spi]: Failed data block cmd write, bus error...\n");
result = N_FAIL;
break;
@@ -718,7 +715,7 @@ static int spi_data_write(u8 *b, u32 sz)
/**
* Write data
**/
- if (!g_spi.spi_tx(&b[ix], nbytes)) {
+ if (!linux_spi_write(&b[ix], nbytes)) {
PRINT_ER("[wilc spi]: Failed data block write, bus error...\n");
result = N_FAIL;
break;
@@ -728,7 +725,7 @@ static int spi_data_write(u8 *b, u32 sz)
* Write Crc
**/
if (!g_spi.crc_off) {
- if (!g_spi.spi_tx(crc, 2)) {
+ if (!linux_spi_write(crc, 2)) {
PRINT_ER("[wilc spi]: Failed data block crc write, bus error...\n");
result = N_FAIL;
break;
@@ -790,7 +787,7 @@ static int spi_internal_read(u32 adr, u32 *data)
*
********************************************/
-static int spi_write_reg(u32 addr, u32 data)
+static int wilc_spi_write_reg(u32 addr, u32 data)
{
int result = N_OK;
u8 cmd = CMD_SINGLE_WRITE;
@@ -813,7 +810,7 @@ static int spi_write_reg(u32 addr, u32 data)
return result;
}
-static int spi_write(u32 addr, u8 *buf, u32 size)
+static int wilc_spi_write(u32 addr, u8 *buf, u32 size)
{
int result;
u8 cmd = CMD_DMA_EXT_WRITE;
@@ -841,7 +838,7 @@ static int spi_write(u32 addr, u8 *buf, u32 size)
return 1;
}
-static int spi_read_reg(u32 addr, u32 *data)
+static int wilc_spi_read_reg(u32 addr, u32 *data)
{
int result = N_OK;
u8 cmd = CMD_SINGLE_READ;
@@ -867,7 +864,7 @@ static int spi_read_reg(u32 addr, u32 *data)
return 1;
}
-static int spi_read(u32 addr, u8 *buf, u32 size)
+static int wilc_spi_read(u32 addr, u8 *buf, u32 size)
{
u8 cmd = CMD_DMA_EXT_READ;
int result;
@@ -890,20 +887,20 @@ static int spi_read(u32 addr, u8 *buf, u32 size)
*
********************************************/
-static int spi_clear_int(void)
+static int wilc_spi_clear_int(void)
{
u32 reg;
- if (!spi_read_reg(WILC_HOST_RX_CTRL_0, &reg)) {
+ if (!wilc_spi_read_reg(WILC_HOST_RX_CTRL_0, &reg)) {
PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0);
return 0;
}
reg &= ~0x1;
- spi_write_reg(WILC_HOST_RX_CTRL_0, reg);
+ wilc_spi_write_reg(WILC_HOST_RX_CTRL_0, reg);
return 1;
}
-static int spi_deinit(void *pv)
+static int wilc_spi_deinit(void *pv)
{
/**
* TODO:
@@ -911,7 +908,7 @@ static int spi_deinit(void *pv)
return 1;
}
-static int spi_sync(void)
+static int wilc_spi_sync(void)
{
u32 reg;
int ret;
@@ -919,13 +916,13 @@ static int spi_sync(void)
/**
* interrupt pin mux select
**/
- ret = spi_read_reg(WILC_PIN_MUX_0, &reg);
+ ret = wilc_spi_read_reg(WILC_PIN_MUX_0, &reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
return 0;
}
reg |= BIT(8);
- ret = spi_write_reg(WILC_PIN_MUX_0, reg);
+ ret = wilc_spi_write_reg(WILC_PIN_MUX_0, reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
return 0;
@@ -934,13 +931,13 @@ static int spi_sync(void)
/**
* interrupt enable
**/
- ret = spi_read_reg(WILC_INTR_ENABLE, &reg);
+ ret = wilc_spi_read_reg(WILC_INTR_ENABLE, &reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
return 0;
}
reg |= BIT(16);
- ret = spi_write_reg(WILC_INTR_ENABLE, reg);
+ ret = wilc_spi_write_reg(WILC_INTR_ENABLE, reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
return 0;
@@ -949,7 +946,7 @@ static int spi_sync(void)
return 1;
}
-static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
+static int wilc_spi_init(struct wilc *wilc, wilc_debug_func func)
{
u32 reg;
u32 chipid;
@@ -958,7 +955,7 @@ static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
if (isinit) {
- if (!spi_read_reg(0x1000, &chipid)) {
+ if (!wilc_spi_read_reg(0x1000, &chipid)) {
PRINT_ER("[wilc spi]: Fail cmd read chip id...\n");
return 0;
}
@@ -968,19 +965,12 @@ static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
memset(&g_spi, 0, sizeof(wilc_spi_t));
g_spi.dPrint = func;
- g_spi.os_context = inp->os_context.os_private;
- if (inp->io_func.io_init) {
- if (!inp->io_func.io_init(g_spi.os_context)) {
- PRINT_ER("[wilc spi]: Failed io init bus...\n");
- return 0;
- }
+ if (!linux_spi_init()) {
+ PRINT_ER("[wilc spi]: Failed io init bus...\n");
+ return 0;
} else {
return 0;
}
- g_spi.spi_tx = inp->io_func.u.spi.spi_tx;
- g_spi.spi_rx = inp->io_func.u.spi.spi_rx;
- g_spi.spi_trx = inp->io_func.u.spi.spi_trx;
- g_spi.spi_max_speed = inp->io_func.u.spi.spi_max_speed;
/**
* configure protocol
@@ -1015,7 +1005,7 @@ static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
/**
* make sure can read back chip id correctly
**/
- if (!spi_read_reg(0x1000, &chipid)) {
+ if (!wilc_spi_read_reg(0x1000, &chipid)) {
PRINT_ER("[wilc spi]: Fail cmd read chip id...\n");
return 0;
}
@@ -1028,16 +1018,16 @@ static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
return 1;
}
-static void spi_max_bus_speed(void)
+static void wilc_spi_max_bus_speed(void)
{
- g_spi.spi_max_speed();
+ linux_spi_set_max_speed();
}
-static void spi_default_bus_speed(void)
+static void wilc_spi_default_bus_speed(void)
{
}
-static int spi_read_size(u32 *size)
+static int wilc_spi_read_size(u32 *size)
{
int ret;
@@ -1048,7 +1038,7 @@ static int spi_read_size(u32 *size)
u32 tmp;
u32 byte_cnt;
- ret = spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt);
+ ret = wilc_spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read WILC_VMM_TO_HOST_SIZE ...\n");
goto _fail_;
@@ -1065,7 +1055,7 @@ _fail_:
-static int spi_read_int(u32 *int_status)
+static int wilc_spi_read_int(u32 *int_status)
{
int ret;
@@ -1075,7 +1065,7 @@ static int spi_read_int(u32 *int_status)
u32 tmp;
u32 byte_cnt;
- ret = spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt);
+ ret = wilc_spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read WILC_VMM_TO_HOST_SIZE ...\n");
goto _fail_;
@@ -1091,11 +1081,11 @@ static int spi_read_int(u32 *int_status)
happended = 0;
- spi_read_reg(0x1a90, &irq_flags);
+ wilc_spi_read_reg(0x1a90, &irq_flags);
tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET);
if (g_spi.nint > 5) {
- spi_read_reg(0x1a94, &irq_flags);
+ wilc_spi_read_reg(0x1a94, &irq_flags);
tmp |= (((irq_flags >> 0) & 0x7) << (IRG_FLAGS_OFFSET + 5));
}
@@ -1121,7 +1111,7 @@ _fail_:
return ret;
}
-static int spi_clear_int_ext(u32 val)
+static int wilc_spi_clear_int_ext(u32 val)
{
int ret;
@@ -1138,13 +1128,13 @@ static int spi_clear_int_ext(u32 val)
for (i = 0; i < g_spi.nint; i++) {
/* No matter what you write 1 or 0, it will clear interrupt. */
if (flags & 1)
- ret = spi_write_reg(0x10c8 + i * 4, 1);
+ ret = wilc_spi_write_reg(0x10c8 + i * 4, 1);
if (!ret)
break;
flags >>= 1;
}
if (!ret) {
- PRINT_ER("[wilc spi]: Failed spi_write_reg, set reg %x ...\n", 0x10c8 + i * 4);
+ PRINT_ER("[wilc spi]: Failed wilc_spi_write_reg, set reg %x ...\n", 0x10c8 + i * 4);
goto _fail_;
}
for (i = g_spi.nint; i < MAX_NUM_INT; i++) {
@@ -1165,7 +1155,7 @@ static int spi_clear_int_ext(u32 val)
if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
tbl_ctl |= BIT(1);
- ret = spi_write_reg(WILC_VMM_TBL_CTL, tbl_ctl);
+ ret = wilc_spi_write_reg(WILC_VMM_TBL_CTL, tbl_ctl);
if (!ret) {
PRINT_ER("[wilc spi]: fail write reg vmm_tbl_ctl...\n");
goto _fail_;
@@ -1175,7 +1165,7 @@ static int spi_clear_int_ext(u32 val)
/**
* enable vmm transfer.
**/
- ret = spi_write_reg(WILC_VMM_CORE_CTL, 1);
+ ret = wilc_spi_write_reg(WILC_VMM_CORE_CTL, 1);
if (!ret) {
PRINT_ER("[wilc spi]: fail write reg vmm_core_ctl...\n");
goto _fail_;
@@ -1187,7 +1177,7 @@ _fail_:
return ret;
}
-static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
+static int wilc_spi_sync_ext(int nint /* how mant interrupts to enable. */)
{
u32 reg;
int ret, i;
@@ -1202,13 +1192,13 @@ static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
/**
* interrupt pin mux select
**/
- ret = spi_read_reg(WILC_PIN_MUX_0, &reg);
+ ret = wilc_spi_read_reg(WILC_PIN_MUX_0, &reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
return 0;
}
reg |= BIT(8);
- ret = spi_write_reg(WILC_PIN_MUX_0, reg);
+ ret = wilc_spi_write_reg(WILC_PIN_MUX_0, reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
return 0;
@@ -1217,7 +1207,7 @@ static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
/**
* interrupt enable
**/
- ret = spi_read_reg(WILC_INTR_ENABLE, &reg);
+ ret = wilc_spi_read_reg(WILC_INTR_ENABLE, &reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
return 0;
@@ -1226,13 +1216,13 @@ static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
for (i = 0; (i < 5) && (nint > 0); i++, nint--) {
reg |= (BIT((27 + i)));
}
- ret = spi_write_reg(WILC_INTR_ENABLE, reg);
+ ret = wilc_spi_write_reg(WILC_INTR_ENABLE, reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
return 0;
}
if (nint) {
- ret = spi_read_reg(WILC_INTR2_ENABLE, &reg);
+ ret = wilc_spi_read_reg(WILC_INTR2_ENABLE, &reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR2_ENABLE);
return 0;
@@ -1242,7 +1232,7 @@ static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
reg |= BIT(i);
}
- ret = spi_read_reg(WILC_INTR2_ENABLE, &reg);
+ ret = wilc_spi_read_reg(WILC_INTR2_ENABLE, &reg);
if (!ret) {
PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR2_ENABLE);
return 0;
@@ -1256,21 +1246,21 @@ static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
* Global spi HIF function table
*
********************************************/
-wilc_hif_func_t hif_spi = {
- spi_init,
- spi_deinit,
- spi_read_reg,
- spi_write_reg,
- spi_read,
- spi_write,
- spi_sync,
- spi_clear_int,
- spi_read_int,
- spi_clear_int_ext,
- spi_read_size,
- spi_write,
- spi_read,
- spi_sync_ext,
- spi_max_bus_speed,
- spi_default_bus_speed,
+struct wilc_hif_func hif_spi = {
+ wilc_spi_init,
+ wilc_spi_deinit,
+ wilc_spi_read_reg,
+ wilc_spi_write_reg,
+ wilc_spi_read,
+ wilc_spi_write,
+ wilc_spi_sync,
+ wilc_spi_clear_int,
+ wilc_spi_read_int,
+ wilc_spi_clear_int_ext,
+ wilc_spi_read_size,
+ wilc_spi_write,
+ wilc_spi_read,
+ wilc_spi_sync_ext,
+ wilc_spi_max_bus_speed,
+ wilc_spi_default_bus_speed,
};
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index bcbf1bd29a50..6f405221030c 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -21,9 +21,6 @@
#define IS_MGMT_STATUS_SUCCES 0x040
#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
-extern int linux_wlan_get_firmware(perInterface_wlan_t *p_nic);
-extern u16 Set_machw_change_vir_if(bool bValue);
-
extern int mac_open(struct net_device *ndev);
extern int mac_close(struct net_device *ndev);
@@ -508,8 +505,6 @@ int WILC_WFI_Set_PMKSA(u8 *bssid, struct wilc_priv *priv)
}
-int linux_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID);
-
/**
* @brief CfgConnectResult
@@ -537,11 +532,15 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
struct net_device *dev;
struct host_if_drv *pstrWFIDrv;
u8 NullBssid[ETH_ALEN] = {0};
+ struct wilc *wl;
+ perInterface_wlan_t *nic;
connecting = 0;
priv = (struct wilc_priv *)pUserVoid;
dev = priv->dev;
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
@@ -561,7 +560,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
eth_zero_addr(u8ConnectedSSID);
/*Invalidate u8WLANChannel value on wlan0 disconnect*/
- if (!pstrWFIDrv->u8P2PConnect)
+ if (!pstrWFIDrv->p2p_connect)
u8WLANChannel = INVALID_CHANNEL;
PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus);
@@ -620,16 +619,16 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
eth_zero_addr(u8ConnectedSSID);
/*Invalidate u8WLANChannel value on wlan0 disconnect*/
- if (!pstrWFIDrv->u8P2PConnect)
+ if (!pstrWFIDrv->p2p_connect)
u8WLANChannel = INVALID_CHANNEL;
/*Incase "P2P CLIENT Connected" send deauthentication reason by 3 to force the WPA_SUPPLICANT to directly change
* virtual interface to station*/
- if ((pstrWFIDrv->IFC_UP) && (dev == g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) {
+ if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1].ndev)) {
pstrDisconnectNotifInfo->u16reason = 3;
}
/*Incase "P2P CLIENT during connection(not connected)" send deauthentication reason by 1 to force the WPA_SUPPLICANT
* to scan again and retry the connection*/
- else if ((!pstrWFIDrv->IFC_UP) && (dev == g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) {
+ else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1].ndev)) {
pstrDisconnectNotifInfo->u16reason = 1;
}
cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
@@ -801,9 +800,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv);
if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
- pstrWFIDrv->u8P2PConnect = 1;
- } else
- pstrWFIDrv->u8P2PConnect = 0;
+ pstrWFIDrv->p2p_connect = 1;
+ } else {
+ pstrWFIDrv->p2p_connect = 0;
+ }
PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
@@ -888,7 +888,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
g_key_wep_params.key_idx = sme->key_idx;
g_wep_keys_saved = true;
- host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, sme->key_idx);
+ host_int_set_wep_default_key(priv->hWILCWFIDrv, sme->key_idx);
host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx);
} else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) {
u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
@@ -905,7 +905,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
g_key_wep_params.key_idx = sme->key_idx;
g_wep_keys_saved = true;
- host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, sme->key_idx);
+ host_int_set_wep_default_key(priv->hWILCWFIDrv, sme->key_idx);
host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx);
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
@@ -994,9 +994,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
curr_channel = pstrNetworkInfo->u8channel;
- if (!pstrWFIDrv->u8P2PConnect) {
+ if (!pstrWFIDrv->p2p_connect)
u8WLANChannel = pstrNetworkInfo->u8channel;
- }
linux_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid);
@@ -1038,7 +1037,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co
/*Invalidate u8WLANChannel value on wlan0 disconnect*/
pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
- if (!pstrWFIDrv->u8P2PConnect)
+ if (!pstrWFIDrv->p2p_connect)
u8WLANChannel = INVALID_CHANNEL;
linux_wlan_set_bssid(priv->dev, NullBssid);
@@ -1047,7 +1046,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co
u8P2Plocalrandom = 0x01;
u8P2Precvrandom = 0x00;
bWilc_ie = false;
- pstrWFIDrv->u64P2p_MgmtTimeout = 0;
+ pstrWFIDrv->p2p_timeout = 0;
s32Error = host_int_disconnect(priv->hWILCWFIDrv, reason_code);
if (s32Error != 0) {
@@ -1082,8 +1081,12 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
u8 u8gmode = NO_ENCRYPT;
u8 u8pmode = NO_ENCRYPT;
enum AUTHTYPE tenuAuth_type = ANY;
+ struct wilc *wl;
+ perInterface_wlan_t *nic;
priv = wiphy_priv(wiphy);
+ nic = netdev_priv(netdev);
+ wl = nic->wilc;
PRINT_D(CFG80211_DBG, "Adding key with cipher suite = %x\n", params->cipher);
@@ -1255,7 +1258,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
}
/*save keys only on interface 0 (wifi interface)*/
- if (!g_gtk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) {
+ if (!g_gtk_keys_saved && netdev == wl->vif[0].ndev) {
g_add_gtk_key_params.key_idx = key_index;
g_add_gtk_key_params.pairwise = pairwise;
if (!mac_addr) {
@@ -1291,7 +1294,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
}
/*save keys only on interface 0 (wifi interface)*/
- if (!g_ptk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) {
+ if (!g_ptk_keys_saved && netdev == wl->vif[0].ndev) {
g_add_ptk_key_params.key_idx = key_index;
g_add_ptk_key_params.pairwise = pairwise;
if (!mac_addr) {
@@ -1352,11 +1355,15 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
const u8 *mac_addr)
{
struct wilc_priv *priv;
+ struct wilc *wl;
+ perInterface_wlan_t *nic;
priv = wiphy_priv(wiphy);
+ nic = netdev_priv(netdev);
+ wl = nic->wilc;
/*delete saved keys, if any*/
- if (netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) {
+ if (netdev == wl->vif[0].ndev) {
g_ptk_keys_saved = false;
g_gtk_keys_saved = false;
g_wep_keys_saved = false;
@@ -1401,7 +1408,7 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
g_key_gtk_params.seq = NULL;
/*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
- Set_machw_change_vir_if(false);
+ set_machw_change_vir_if(netdev, false);
}
if (key_index >= 0 && key_index <= 3) {
@@ -1490,7 +1497,7 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 ke
if (key_index != priv->WILC_WFI_wep_default) {
- host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, key_index);
+ host_int_set_wep_default_key(priv->hWILCWFIDrv, key_index);
}
return 0;
@@ -1555,16 +1562,17 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev,
BIT(NL80211_STA_INFO_TX_FAILED) |
BIT(NL80211_STA_INFO_TX_BITRATE);
- sinfo->signal = strStatistics.s8RSSI;
- sinfo->rx_packets = strStatistics.u32RxCount;
- sinfo->tx_packets = strStatistics.u32TxCount + strStatistics.u32TxFailureCount;
- sinfo->tx_failed = strStatistics.u32TxFailureCount;
- sinfo->txrate.legacy = strStatistics.u8LinkSpeed * 10;
+ sinfo->signal = strStatistics.rssi;
+ sinfo->rx_packets = strStatistics.rx_cnt;
+ sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
+ sinfo->tx_failed = strStatistics.tx_fail_cnt;
+ sinfo->txrate.legacy = strStatistics.link_speed * 10;
- if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED))
- Enable_TCP_ACK_Filter(true);
- else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)
- Enable_TCP_ACK_Filter(false);
+ if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
+ (strStatistics.link_speed != DEFAULT_LINK_SPEED))
+ enable_tcp_ack_filter(true);
+ else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
+ enable_tcp_ack_filter(false);
PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets,
sinfo->tx_failed, sinfo->txrate.legacy);
@@ -1946,7 +1954,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size)
if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]);
- if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->u64P2p_MgmtTimeout)) {
+ if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n");
return;
}
@@ -2168,20 +2176,6 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
return s32Error;
}
/**
- * @brief WILC_WFI_add_wilcvendorspec
- * @details Adding WILC information elemet to allow two WILC devices to
- * identify each other and connect
- * @param[in] u8 * buf
- * @return void
- * @author mdaftedar
- * @date 01 JAN 2014
- * @version 1.0
- */
-void WILC_WFI_add_wilcvendorspec(u8 *buff)
-{
- memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
-}
-/**
* @brief WILC_WFI_mgmt_tx_frame
* @details
*
@@ -2304,7 +2298,11 @@ static int mgmt_tx(struct wiphy *wiphy,
}
if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
- WILC_WFI_add_wilcvendorspec(&mgmt_tx->buff[len]);
+ /*
+ * Adding WILC information element to allow two WILC devices to
+ * identify each other and connect
+ */
+ memcpy(&mgmt_tx->buff[len], u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
mgmt_tx->buff[len + sizeof(u8P2P_vendorspec)] = u8P2Plocalrandom;
mgmt_tx->size = buf_len;
}
@@ -2329,14 +2327,14 @@ static int mgmt_tx(struct wiphy *wiphy,
}
PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value);
- pstrWFIDrv->u64P2p_MgmtTimeout = (jiffies + msecs_to_jiffies(wait));
-
- PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n", jiffies, pstrWFIDrv->u64P2p_MgmtTimeout);
+ pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
+ PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n",
+ jiffies, pstrWFIDrv->p2p_timeout);
}
- wilc_wlan_txq_add_mgmt_pkt(mgmt_tx, mgmt_tx->buff,
- mgmt_tx->size,
+ wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
+ mgmt_tx->buff, mgmt_tx->size,
WILC_WFI_mgmt_tx_complete);
} else {
PRINT_D(GENERIC_DBG, "This function transmits only management frames\n");
@@ -2356,7 +2354,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies);
- pstrWFIDrv->u64P2p_MgmtTimeout = jiffies;
+ pstrWFIDrv->p2p_timeout = jiffies;
if (!priv->bInP2PlistenState) {
cfg80211_remain_on_channel_expired(priv->wdev,
@@ -2385,12 +2383,11 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
struct wilc_priv *priv;
perInterface_wlan_t *nic;
-
+ struct wilc *wl;
priv = wiphy_priv(wiphy);
nic = netdev_priv(priv->wdev->netdev);
-
-
+ wl = nic->wilc;
if (!frame_type)
return;
@@ -2418,7 +2415,7 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
}
/*If mac is closed, then return*/
- if (!g_linux_wlan->wilc1000_initialized) {
+ if (!wl->initialized) {
PRINT_D(GENERIC_DBG, "Return since mac is closed\n");
return;
}
@@ -2523,7 +2520,6 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
* @date 01 MAR 2012
* @version 1.0
*/
-void wilc1000_wlan_deinit(struct wilc *nic);
int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic);
static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
@@ -2534,9 +2530,11 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
u8 interface_type;
u16 TID = 0;
u8 i;
+ struct wilc *wl;
nic = netdev_priv(dev);
priv = wiphy_priv(wiphy);
+ wl = nic->wilc;
PRINT_D(HOSTAPD_DBG, "In Change virtual interface function\n");
PRINT_D(HOSTAPD_DBG, "Wireless interface name =%s\n", dev->name);
@@ -2550,7 +2548,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
/*Set WILC_CHANGING_VIR_IF register to disallow adding futrue keys to CE H/W*/
if (g_ptk_keys_saved && g_gtk_keys_saved) {
- Set_machw_change_vir_if(true);
+ set_machw_change_vir_if(dev, true);
}
switch (type) {
@@ -2571,30 +2569,31 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
interface_type = nic->iftype;
nic->iftype = STATION_MODE;
- if (g_linux_wlan->wilc1000_initialized) {
- host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID);
+ if (wl->initialized) {
+ host_int_del_All_Rx_BASession(priv->hWILCWFIDrv,
+ wl->vif[0].bssid, TID);
/* ensure that the message Q is empty */
host_int_wait_msg_queue_idle();
/*Eliminate host interface blocking state*/
- up(&g_linux_wlan->cfg_event);
+ up(&wl->cfg_event);
- wilc1000_wlan_deinit(g_linux_wlan);
+ wilc1000_wlan_deinit(dev);
wilc1000_wlan_init(dev, nic);
g_wilc_initialized = 1;
nic->iftype = interface_type;
/*Setting interface 1 drv handler and mac address in newly downloaded FW*/
- host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
- host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
- g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ host_int_set_wfi_drv_handler(wl->vif[0].hif_drv);
+ host_int_set_MacAddress(wl->vif[0].hif_drv,
+ wl->vif[0].src_addr);
host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
/*Add saved WEP keys, if any*/
if (g_wep_keys_saved) {
- host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
+ host_int_set_wep_default_key(wl->vif[0].hif_drv,
g_key_wep_params.key_idx);
- host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
+ host_int_add_wep_key_bss_sta(wl->vif[0].hif_drv,
g_key_wep_params.key,
g_key_wep_params.key_len,
g_key_wep_params.key_idx);
@@ -2612,22 +2611,22 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
g_key_gtk_params.key[1],
g_key_gtk_params.key[2]);
- add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
- g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
+ add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
+ wl->vif[0].ndev,
g_add_ptk_key_params.key_idx,
g_add_ptk_key_params.pairwise,
g_add_ptk_key_params.mac_addr,
(struct key_params *)(&g_key_ptk_params));
- add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
- g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
+ add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
+ wl->vif[0].ndev,
g_add_gtk_key_params.key_idx,
g_add_gtk_key_params.pairwise,
g_add_gtk_key_params.mac_addr,
(struct key_params *)(&g_key_gtk_params));
}
- if (g_linux_wlan->wilc1000_initialized) {
+ if (wl->initialized) {
for (i = 0; i < num_reg_frame; i++) {
PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
nic->g_struct_frame_reg[i].reg);
@@ -2648,7 +2647,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
connecting = 0;
PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
- host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID);
+ host_int_del_All_Rx_BASession(priv->hWILCWFIDrv,
+ wl->vif[0].bssid, TID);
dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type;
@@ -2658,24 +2658,24 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
nic->iftype = CLIENT_MODE;
- if (g_linux_wlan->wilc1000_initialized) {
+ if (wl->initialized) {
/* ensure that the message Q is empty */
host_int_wait_msg_queue_idle();
- wilc1000_wlan_deinit(g_linux_wlan);
+ wilc1000_wlan_deinit(dev);
wilc1000_wlan_init(dev, nic);
g_wilc_initialized = 1;
- host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
- host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
- g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ host_int_set_wfi_drv_handler(wl->vif[0].hif_drv);
+ host_int_set_MacAddress(wl->vif[0].hif_drv,
+ wl->vif[0].src_addr);
host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
/*Add saved WEP keys, if any*/
if (g_wep_keys_saved) {
- host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
+ host_int_set_wep_default_key(wl->vif[0].hif_drv,
g_key_wep_params.key_idx);
- host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
+ host_int_add_wep_key_bss_sta(wl->vif[0].hif_drv,
g_key_wep_params.key,
g_key_wep_params.key_len,
g_key_wep_params.key_idx);
@@ -2693,15 +2693,15 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
g_key_gtk_params.key[1],
g_key_gtk_params.key[2]);
- add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
- g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
+ add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
+ wl->vif[0].ndev,
g_add_ptk_key_params.key_idx,
g_add_ptk_key_params.pairwise,
g_add_ptk_key_params.mac_addr,
(struct key_params *)(&g_key_ptk_params));
- add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
- g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
+ add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
+ wl->vif[0].ndev,
g_add_gtk_key_params.key_idx,
g_add_gtk_key_params.pairwise,
g_add_gtk_key_params.mac_addr,
@@ -2710,9 +2710,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
/*Refresh scan, to refresh the scan results to the wpa_supplicant. Set MachHw to false to enable further key installments*/
refresh_scan(priv, 1, true);
- Set_machw_change_vir_if(false);
+ set_machw_change_vir_if(dev, false);
- if (g_linux_wlan->wilc1000_initialized) {
+ if (wl->initialized) {
for (i = 0; i < num_reg_frame; i++) {
PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
nic->g_struct_frame_reg[i].reg);
@@ -2733,11 +2733,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n");
- linux_wlan_get_firmware(nic);
+ linux_wlan_get_firmware(dev);
/*If wilc is running, then close-open to actually get new firmware running (serves P2P)*/
- if (g_linux_wlan->wilc1000_initialized) {
+ if (wl->initialized) {
nic->iftype = AP_MODE;
- g_linux_wlan->wilc1000_initialized = 1;
mac_close(dev);
mac_open(dev);
@@ -2761,7 +2760,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
/*sent before downloading new FW. This is because it blocks on*/
/*hWaitResponse semaphore, which allows previous config*/
/*packets to actually take action on old FW*/
- host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID);
+ host_int_del_All_Rx_BASession(priv->hWILCWFIDrv,
+ wl->vif[0].bssid, TID);
bEnablePS = false;
PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n");
dev->ieee80211_ptr->iftype = type;
@@ -2776,22 +2776,22 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
/* ensure that the message Q is empty */
host_int_wait_msg_queue_idle();
- wilc1000_wlan_deinit(g_linux_wlan);
+ wilc1000_wlan_deinit(dev);
wilc1000_wlan_init(dev, nic);
g_wilc_initialized = 1;
/*Setting interface 1 drv handler and mac address in newly downloaded FW*/
- host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
- host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
- g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ host_int_set_wfi_drv_handler(wl->vif[0].hif_drv);
+ host_int_set_MacAddress(wl->vif[0].hif_drv,
+ wl->vif[0].src_addr);
host_int_set_operation_mode(priv->hWILCWFIDrv, AP_MODE);
/*Add saved WEP keys, if any*/
if (g_wep_keys_saved) {
- host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
+ host_int_set_wep_default_key(wl->vif[0].hif_drv,
g_key_wep_params.key_idx);
- host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
+ host_int_add_wep_key_bss_sta(wl->vif[0].hif_drv,
g_key_wep_params.key,
g_key_wep_params.key_len,
g_key_wep_params.key_idx);
@@ -2811,22 +2811,22 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
g_key_gtk_params.key[1],
g_key_gtk_params.key[2],
g_key_gtk_params.cipher);
- add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
- g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
+ add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
+ wl->vif[0].ndev,
g_add_ptk_key_params.key_idx,
g_add_ptk_key_params.pairwise,
g_add_ptk_key_params.mac_addr,
(struct key_params *)(&g_key_ptk_params));
- add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
- g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
+ add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
+ wl->vif[0].ndev,
g_add_gtk_key_params.key_idx,
g_add_gtk_key_params.pairwise,
g_add_gtk_key_params.mac_addr,
(struct key_params *)(&g_key_gtk_params));
}
- if (g_linux_wlan->wilc1000_initialized) {
+ if (wl->initialized) {
for (i = 0; i < num_reg_frame; i++) {
PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
nic->g_struct_frame_reg[i].reg);
@@ -2877,8 +2877,12 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_beacon_data *beacon = &(settings->beacon);
struct wilc_priv *priv;
s32 s32Error = 0;
+ struct wilc *wl;
+ perInterface_wlan_t *nic;
priv = wiphy_priv(wiphy);
+ nic = netdev_priv(dev);
+ wl = nic->wilc;
PRINT_D(HOSTAPD_DBG, "Starting ap\n");
PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
@@ -2889,7 +2893,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
if (s32Error != 0)
PRINT_ER("Error in setting channel\n");
- linux_wlan_set_bssid(dev, g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
+ linux_wlan_set_bssid(dev, wl->vif[0].src_addr);
s32Error = host_int_add_beacon(priv->hWILCWFIDrv,
settings->beacon_interval,
@@ -2987,42 +2991,53 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
nic = netdev_priv(dev);
if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
- memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
+ memcpy(strStaParams.bssid, mac, ETH_ALEN);
memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
- strStaParams.u16AssocID = params->aid;
- strStaParams.u8NumRates = params->supported_rates_len;
- strStaParams.pu8Rates = params->supported_rates;
+ strStaParams.aid = params->aid;
+ strStaParams.rates_len = params->supported_rates_len;
+ strStaParams.rates = params->supported_rates;
PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid);
PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4],
priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]);
- PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.u16AssocID);
- PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n", strStaParams.u8NumRates);
+ PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.aid);
+ PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n",
+ strStaParams.rates_len);
if (params->ht_capa == NULL) {
- strStaParams.bIsHTSupported = false;
+ strStaParams.ht_supported = false;
} else {
- strStaParams.bIsHTSupported = true;
- strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
- strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
- memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
- strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
- strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
- strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
+ strStaParams.ht_supported = true;
+ strStaParams.ht_capa_info = params->ht_capa->cap_info;
+ strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
+ memcpy(strStaParams.ht_supp_mcs_set,
+ &params->ht_capa->mcs,
+ WILC_SUPP_MCS_SET_SIZE);
+ strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
+ strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
+ strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
}
- strStaParams.u16FlagsMask = params->sta_flags_mask;
- strStaParams.u16FlagsSet = params->sta_flags_set;
-
- PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n", strStaParams.bIsHTSupported);
- PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n", strStaParams.u16HTCapInfo);
- PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n", strStaParams.u8AmpduParams);
- PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n", strStaParams.u16HTExtParams);
- PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n", strStaParams.u32TxBeamformingCap);
- PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n", strStaParams.u8ASELCap);
- PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n", strStaParams.u16FlagsMask);
- PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n", strStaParams.u16FlagsSet);
+ strStaParams.flags_mask = params->sta_flags_mask;
+ strStaParams.flags_set = params->sta_flags_set;
+
+ PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n",
+ strStaParams.ht_supported);
+ PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n",
+ strStaParams.ht_capa_info);
+ PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n",
+ strStaParams.ht_ampdu_params);
+ PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n",
+ strStaParams.ht_ext_params);
+ PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n",
+ strStaParams.ht_tx_bf_cap);
+ PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n",
+ strStaParams.ht_ante_sel);
+ PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n",
+ strStaParams.flags_mask);
+ PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n",
+ strStaParams.flags_set);
s32Error = host_int_add_station(priv->hWILCWFIDrv, &strStaParams);
if (s32Error)
@@ -3101,40 +3116,52 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
nic = netdev_priv(dev);
if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
- memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
- strStaParams.u16AssocID = params->aid;
- strStaParams.u8NumRates = params->supported_rates_len;
- strStaParams.pu8Rates = params->supported_rates;
-
- PRINT_D(HOSTAPD_DBG, "BSSID = %x%x%x%x%x%x\n", strStaParams.au8BSSID[0], strStaParams.au8BSSID[1], strStaParams.au8BSSID[2], strStaParams.au8BSSID[3], strStaParams.au8BSSID[4],
- strStaParams.au8BSSID[5]);
- PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.u16AssocID);
- PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n", strStaParams.u8NumRates);
+ memcpy(strStaParams.bssid, mac, ETH_ALEN);
+ strStaParams.aid = params->aid;
+ strStaParams.rates_len = params->supported_rates_len;
+ strStaParams.rates = params->supported_rates;
+
+ PRINT_D(HOSTAPD_DBG, "BSSID = %x%x%x%x%x%x\n",
+ strStaParams.bssid[0], strStaParams.bssid[1],
+ strStaParams.bssid[2], strStaParams.bssid[3],
+ strStaParams.bssid[4], strStaParams.bssid[5]);
+ PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.aid);
+ PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n",
+ strStaParams.rates_len);
if (params->ht_capa == NULL) {
- strStaParams.bIsHTSupported = false;
+ strStaParams.ht_supported = false;
} else {
- strStaParams.bIsHTSupported = true;
- strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
- strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
- memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
- strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
- strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
- strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
-
+ strStaParams.ht_supported = true;
+ strStaParams.ht_capa_info = params->ht_capa->cap_info;
+ strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
+ memcpy(strStaParams.ht_supp_mcs_set,
+ &params->ht_capa->mcs,
+ WILC_SUPP_MCS_SET_SIZE);
+ strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
+ strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
+ strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
}
- strStaParams.u16FlagsMask = params->sta_flags_mask;
- strStaParams.u16FlagsSet = params->sta_flags_set;
-
- PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n", strStaParams.bIsHTSupported);
- PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n", strStaParams.u16HTCapInfo);
- PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n", strStaParams.u8AmpduParams);
- PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n", strStaParams.u16HTExtParams);
- PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n", strStaParams.u32TxBeamformingCap);
- PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n", strStaParams.u8ASELCap);
- PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n", strStaParams.u16FlagsMask);
- PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n", strStaParams.u16FlagsSet);
+ strStaParams.flags_mask = params->sta_flags_mask;
+ strStaParams.flags_set = params->sta_flags_set;
+
+ PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n",
+ strStaParams.ht_supported);
+ PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n",
+ strStaParams.ht_capa_info);
+ PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n",
+ strStaParams.ht_ampdu_params);
+ PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n",
+ strStaParams.ht_ext_params);
+ PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n",
+ strStaParams.ht_tx_bf_cap);
+ PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n",
+ strStaParams.ht_ante_sel);
+ PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n",
+ strStaParams.flags_mask);
+ PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n",
+ strStaParams.flags_set);
s32Error = host_int_edit_station(priv->hWILCWFIDrv, &strStaParams);
if (s32Error)
@@ -3446,7 +3473,7 @@ int wilc_init_host_int(struct net_device *net)
priv->bInP2PlistenState = false;
sema_init(&(priv->hSemScanReq), 1);
- s32Error = host_int_init(&priv->hWILCWFIDrv);
+ s32Error = host_int_init(net, &priv->hWILCWFIDrv);
if (s32Error)
PRINT_ER("Error while initializing hostinterface\n");
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
index 39cd8e1b5675..d7bdca1f4c5b 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
@@ -104,6 +104,6 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
#define DEFAULT_LINK_SPEED 72
-void Enable_TCP_ACK_Filter(bool value);
+void enable_tcp_ack_filter(bool value);
#endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index c5061fd07312..54ed72336775 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -149,21 +149,21 @@ typedef struct {
} struct_frame_reg;
struct wilc_vif {
- u8 aSrcAddress[ETH_ALEN];
- u8 aBSSID[ETH_ALEN];
- struct host_if_drv *drvHandler;
- struct net_device *wilc_netdev;
+ u8 src_addr[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ struct host_if_drv *hif_drv;
+ struct net_device *ndev;
};
struct wilc {
int mac_status;
- int wilc1000_initialized;
+ bool initialized;
#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
unsigned short dev_irq_num;
#endif
int close;
- u8 u8NoIfcs;
- struct wilc_vif strInterfaceInfo[NUM_CONCURRENT_IFC];
+ u8 vif_num;
+ struct wilc_vif vif[NUM_CONCURRENT_IFC];
u8 open_ifcs;
struct semaphore txq_add_to_head_cs;
@@ -182,7 +182,7 @@ struct wilc {
unsigned char eth_src_address[NUM_CONCURRENT_IFC][6];
- const struct firmware *wilc_firmware;
+ const struct firmware *firmware;
#ifdef WILC_SDIO
struct sdio_func *wilc_sdio_func;
@@ -199,7 +199,7 @@ typedef struct {
struct_frame_reg g_struct_frame_reg[num_reg_frame];
struct net_device *wilc_netdev;
struct net_device_stats netstats;
-
+ struct wilc *wilc;
} perInterface_wlan_t;
struct WILC_WFI_mon_priv {
@@ -208,10 +208,16 @@ struct WILC_WFI_mon_priv {
extern struct wilc *g_linux_wlan;
extern struct net_device *WILC_WFI_devs[];
-void frmw_to_linux(u8 *buff, u32 size, u32 pkt_offset);
-void linux_wlan_mac_indicate(int flag);
+void frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
+void linux_wlan_mac_indicate(struct wilc *wilc, int flag);
void linux_wlan_rx_complete(void);
void linux_wlan_dbg(u8 *buff);
int linux_wlan_lock_timeout(void *vp, u32 timeout);
-
+void wl_wlan_cleanup(struct wilc *wilc);
+int wilc_netdev_init(struct wilc **wilc);
+void wilc1000_wlan_deinit(struct net_device *dev);
+void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
+u16 set_machw_change_vir_if(struct net_device *dev, bool value);
+int linux_wlan_get_firmware(struct net_device *dev);
+int linux_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid);
#endif
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index c73164165323..9d257b06c853 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -1,67 +1,30 @@
-/* ////////////////////////////////////////////////////////////////////////// */
-/* */
-/* Copyright (c) Atmel Corporation. All rights reserved. */
-/* */
-/* Module Name: wilc_wlan.c */
-/* */
-/* */
-/* //////////////////////////////////////////////////////////////////////////// */
-
#include "wilc_wlan_if.h"
#include "wilc_wfi_netdevice.h"
#include "wilc_wlan_cfg.h"
-/********************************************
- *
- * Global
- *
- ********************************************/
-extern wilc_hif_func_t hif_sdio;
-extern wilc_hif_func_t hif_spi;
-extern void WILC_WFI_mgmt_rx(u8 *buff, u32 size);
+#ifdef WILC_SDIO
+extern struct wilc_hif_func hif_sdio;
+#else
+extern struct wilc_hif_func hif_spi;
+#endif
u32 wilc_get_chipid(u8 update);
-u16 Set_machw_change_vir_if(bool bValue);
-
-
typedef struct {
int quit;
-
- /**
- * input interface functions
- **/
wilc_wlan_io_func_t io_func;
-
- /**
- * host interface functions
- **/
- wilc_hif_func_t hif_func;
-
- /**
- * configuration interface functions
- **/
+ struct wilc_hif_func hif_func;
int cfg_frame_in_use;
- wilc_cfg_frame_t cfg_frame;
+ struct wilc_cfg_frame cfg_frame;
u32 cfg_frame_offset;
int cfg_seq_no;
- /**
- * RX buffer
- **/
#ifdef MEMORY_STATIC
u8 *rx_buffer;
u32 rx_buffer_offset;
#endif
- /**
- * TX buffer
- **/
u8 *tx_buffer;
u32 tx_buffer_offset;
- /**
- * TX queue
- **/
-
unsigned long txq_spinlock_flags;
struct txq_entry_t *txq_head;
@@ -69,27 +32,16 @@ typedef struct {
int txq_entries;
int txq_exit;
- /**
- * RX queue
- **/
struct rxq_entry_t *rxq_head;
struct rxq_entry_t *rxq_tail;
int rxq_entries;
int rxq_exit;
-
-
} wilc_wlan_dev_t;
static wilc_wlan_dev_t g_wlan;
static inline void chip_allow_sleep(void);
static inline void chip_wakeup(void);
-/********************************************
- *
- * Debug
- *
- ********************************************/
-
static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
static void wilc_debug(u32 flag, char *fmt, ...)
@@ -106,24 +58,20 @@ static void wilc_debug(u32 flag, char *fmt, ...)
}
}
-static CHIP_PS_STATE_T genuChipPSstate = CHIP_WAKEDUP;
+static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP;
-/*acquire_bus() and release_bus() are made static inline functions*/
-/*as a temporary workaround to fix a problem of receiving*/
-/*unknown interrupt from FW*/
static inline void acquire_bus(BUS_ACQUIRE_T acquire)
{
-
mutex_lock(&g_linux_wlan->hif_cs);
#ifndef WILC_OPTIMIZE_SLEEP_INT
- if (genuChipPSstate != CHIP_WAKEDUP)
+ if (chip_ps_state != CHIP_WAKEDUP)
#endif
{
if (acquire == ACQUIRE_AND_WAKEUP)
chip_wakeup();
}
-
}
+
static inline void release_bus(BUS_RELEASE_T release)
{
#ifdef WILC_OPTIMIZE_SLEEP_INT
@@ -132,23 +80,15 @@ static inline void release_bus(BUS_RELEASE_T release)
#endif
mutex_unlock(&g_linux_wlan->hif_cs);
}
-/********************************************
- *
- * Queue
- *
- ********************************************/
static void wilc_wlan_txq_remove(struct txq_entry_t *tqe)
{
-
wilc_wlan_dev_t *p = &g_wlan;
- if (tqe == p->txq_head) {
+ if (tqe == p->txq_head) {
p->txq_head = tqe->next;
if (p->txq_head)
p->txq_head->prev = NULL;
-
-
} else if (tqe == p->txq_tail) {
p->txq_tail = (tqe->prev);
if (p->txq_tail)
@@ -158,16 +98,21 @@ static void wilc_wlan_txq_remove(struct txq_entry_t *tqe)
tqe->next->prev = tqe->prev;
}
p->txq_entries -= 1;
-
}
-static struct txq_entry_t *wilc_wlan_txq_remove_from_head(void)
+static struct txq_entry_t *
+wilc_wlan_txq_remove_from_head(struct net_device *dev)
{
struct txq_entry_t *tqe;
wilc_wlan_dev_t *p = &g_wlan;
unsigned long flags;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ spin_lock_irqsave(&wilc->txq_spinlock, flags);
if (p->txq_head) {
tqe = p->txq_head;
p->txq_head = tqe->next;
@@ -175,24 +120,27 @@ static struct txq_entry_t *wilc_wlan_txq_remove_from_head(void)
p->txq_head->prev = NULL;
p->txq_entries -= 1;
-
-
-
-
} else {
tqe = NULL;
}
- spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
+ spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
return tqe;
}
-static void wilc_wlan_txq_add_to_tail(struct txq_entry_t *tqe)
+static void wilc_wlan_txq_add_to_tail(struct net_device *dev,
+ struct txq_entry_t *tqe)
{
wilc_wlan_dev_t *p = &g_wlan;
unsigned long flags;
- spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- if (p->txq_head == NULL) {
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ spin_lock_irqsave(&wilc->txq_spinlock, flags);
+
+ if (!p->txq_head) {
tqe->next = NULL;
tqe->prev = NULL;
p->txq_head = tqe;
@@ -206,14 +154,11 @@ static void wilc_wlan_txq_add_to_tail(struct txq_entry_t *tqe)
p->txq_entries += 1;
PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
- spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
+ spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
- /**
- * wake up TX queue
- **/
PRINT_D(TX_DBG, "Wake the txq_handling\n");
- up(&g_linux_wlan->txq_event);
+ up(&wilc->txq_event);
}
static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe)
@@ -226,7 +171,7 @@ static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe)
spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
- if (p->txq_head == NULL) {
+ if (!p->txq_head) {
tqe->next = NULL;
tqe->prev = NULL;
p->txq_head = tqe;
@@ -242,93 +187,75 @@ static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe)
spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
up(&g_linux_wlan->txq_add_to_head_cs);
-
-
- /**
- * wake up TX queue
- **/
up(&g_linux_wlan->txq_event);
PRINT_D(TX_DBG, "Wake up the txq_handler\n");
return 0;
-
}
-u32 Statisitcs_totalAcks = 0, Statisitcs_DroppedAcks = 0;
+u32 total_acks = 0, dropped_acks = 0;
#ifdef TCP_ACK_FILTER
-struct Ack_session_info;
-struct Ack_session_info {
- u32 Ack_seq_num;
- u32 Bigger_Ack_num;
+struct ack_session_info;
+struct ack_session_info {
+ u32 seq_num;
+ u32 bigger_ack_num;
u16 src_port;
u16 dst_port;
u16 status;
};
-typedef struct {
+struct pending_acks_info {
u32 ack_num;
- u32 Session_index;
+ u32 session_index;
struct txq_entry_t *txqe;
-} Pending_Acks_info_t /*Ack_info_t*/;
-
-
-
-
-struct Ack_session_info *Free_head;
-struct Ack_session_info *Alloc_head;
+};
#define NOT_TCP_ACK (-1)
#define MAX_TCP_SESSION 25
#define MAX_PENDING_ACKS 256
-struct Ack_session_info Acks_keep_track_info[2 * MAX_TCP_SESSION];
-Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS];
-
-u32 PendingAcks_arrBase;
-u32 Opened_TCP_session;
-u32 Pending_Acks;
-
+struct ack_session_info ack_session_info[2 * MAX_TCP_SESSION];
+struct pending_acks_info pending_acks_info[MAX_PENDING_ACKS];
+u32 pending_base;
+u32 tcp_session;
+u32 pending_acks;
-static inline int Init_TCP_tracking(void)
+static inline int init_tcp_tracking(void)
{
-
return 0;
-
}
-static inline int add_TCP_track_session(u32 src_prt, u32 dst_prt, u32 seq)
+
+static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq)
{
- Acks_keep_track_info[Opened_TCP_session].Ack_seq_num = seq;
- Acks_keep_track_info[Opened_TCP_session].Bigger_Ack_num = 0;
- Acks_keep_track_info[Opened_TCP_session].src_port = src_prt;
- Acks_keep_track_info[Opened_TCP_session].dst_port = dst_prt;
- Opened_TCP_session++;
+ ack_session_info[tcp_session].seq_num = seq;
+ ack_session_info[tcp_session].bigger_ack_num = 0;
+ ack_session_info[tcp_session].src_port = src_prt;
+ ack_session_info[tcp_session].dst_port = dst_prt;
+ tcp_session++;
- PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", Opened_TCP_session, seq);
+ PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq);
return 0;
}
-static inline int Update_TCP_track_session(u32 index, u32 Ack)
+static inline int update_tcp_session(u32 index, u32 ack)
{
-
- if (Ack > Acks_keep_track_info[index].Bigger_Ack_num)
- Acks_keep_track_info[index].Bigger_Ack_num = Ack;
+ if (ack > ack_session_info[index].bigger_ack_num)
+ ack_session_info[index].bigger_ack_num = ack;
return 0;
-
}
-static inline int add_TCP_Pending_Ack(u32 Ack, u32 Session_index, struct txq_entry_t *txqe)
-{
- Statisitcs_totalAcks++;
- if (Pending_Acks < MAX_PENDING_ACKS) {
- Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].ack_num = Ack;
- Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].txqe = txqe;
- Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].Session_index = Session_index;
- txqe->tcp_PendingAck_index = PendingAcks_arrBase + Pending_Acks;
- Pending_Acks++;
-
- } else {
+static inline int add_tcp_pending_ack(u32 ack, u32 session_index,
+ struct txq_entry_t *txqe)
+{
+ total_acks++;
+ if (pending_acks < MAX_PENDING_ACKS) {
+ pending_acks_info[pending_base + pending_acks].ack_num = ack;
+ pending_acks_info[pending_base + pending_acks].txqe = txqe;
+ pending_acks_info[pending_base + pending_acks].session_index = session_index;
+ txqe->index = pending_base + pending_acks;
+ pending_acks++;
}
return 0;
}
@@ -343,7 +270,7 @@ static inline int remove_TCP_related(void)
return 0;
}
-static inline int tcp_process(struct txq_entry_t *tqe)
+static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
{
int ret;
u8 *eth_hdr_ptr;
@@ -352,47 +279,55 @@ static inline int tcp_process(struct txq_entry_t *tqe)
int i;
wilc_wlan_dev_t *p = &g_wlan;
unsigned long flags;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ spin_lock_irqsave(&wilc->txq_spinlock, flags);
eth_hdr_ptr = &buffer[0];
h_proto = ntohs(*((unsigned short *)&eth_hdr_ptr[12]));
- if (h_proto == 0x0800) { /* IP */
+ if (h_proto == 0x0800) {
u8 *ip_hdr_ptr;
u8 protocol;
ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
protocol = ip_hdr_ptr[9];
-
if (protocol == 0x06) {
u8 *tcp_hdr_ptr;
- u32 IHL, Total_Length, Data_offset;
+ u32 IHL, total_length, data_offset;
tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN];
IHL = (ip_hdr_ptr[0] & 0xf) << 2;
- Total_Length = (((u32)ip_hdr_ptr[2]) << 8) + ((u32)ip_hdr_ptr[3]);
- Data_offset = (((u32)tcp_hdr_ptr[12] & 0xf0) >> 2);
- if (Total_Length == (IHL + Data_offset)) { /*we want to recognize the clear Acks(packet only carry Ack infos not with data) so data size must be equal zero*/
- u32 seq_no, Ack_no;
-
- seq_no = (((u32)tcp_hdr_ptr[4]) << 24) + (((u32)tcp_hdr_ptr[5]) << 16) + (((u32)tcp_hdr_ptr[6]) << 8) + ((u32)tcp_hdr_ptr[7]);
-
- Ack_no = (((u32)tcp_hdr_ptr[8]) << 24) + (((u32)tcp_hdr_ptr[9]) << 16) + (((u32)tcp_hdr_ptr[10]) << 8) + ((u32)tcp_hdr_ptr[11]);
-
-
- for (i = 0; i < Opened_TCP_session; i++) {
- if (Acks_keep_track_info[i].Ack_seq_num == seq_no) {
- Update_TCP_track_session(i, Ack_no);
+ total_length = ((u32)ip_hdr_ptr[2] << 8) +
+ (u32)ip_hdr_ptr[3];
+ data_offset = ((u32)tcp_hdr_ptr[12] & 0xf0) >> 2;
+ if (total_length == (IHL + data_offset)) {
+ u32 seq_no, ack_no;
+
+ seq_no = ((u32)tcp_hdr_ptr[4] << 24) +
+ ((u32)tcp_hdr_ptr[5] << 16) +
+ ((u32)tcp_hdr_ptr[6] << 8) +
+ (u32)tcp_hdr_ptr[7];
+
+ ack_no = ((u32)tcp_hdr_ptr[8] << 24) +
+ ((u32)tcp_hdr_ptr[9] << 16) +
+ ((u32)tcp_hdr_ptr[10] << 8) +
+ (u32)tcp_hdr_ptr[11];
+
+ for (i = 0; i < tcp_session; i++) {
+ if (ack_session_info[i].seq_num == seq_no) {
+ update_tcp_session(i, ack_no);
break;
}
}
- if (i == Opened_TCP_session)
- add_TCP_track_session(0, 0, seq_no);
-
- add_TCP_Pending_Ack(Ack_no, i, tqe);
-
+ if (i == tcp_session)
+ add_tcp_session(0, 0, seq_no);
+ add_tcp_pending_ack(ack_no, i, tqe);
}
} else {
@@ -401,68 +336,70 @@ static inline int tcp_process(struct txq_entry_t *tqe)
} else {
ret = 0;
}
- spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
+ spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
return ret;
}
-
-static int wilc_wlan_txq_filter_dup_tcp_ack(void)
+static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
{
-
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
u32 i = 0;
- u32 Dropped = 0;
+ u32 dropped = 0;
wilc_wlan_dev_t *p = &g_wlan;
- spin_lock_irqsave(&g_linux_wlan->txq_spinlock, p->txq_spinlock_flags);
- for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) {
- if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) {
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ spin_lock_irqsave(&wilc->txq_spinlock, p->txq_spinlock_flags);
+ for (i = pending_base; i < (pending_base + pending_acks); i++) {
+ if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) {
struct txq_entry_t *tqe;
- PRINT_D(TCP_ENH, "DROP ACK: %u\n", Pending_Acks_info[i].ack_num);
- tqe = Pending_Acks_info[i].txqe;
+ PRINT_D(TCP_ENH, "DROP ACK: %u\n",
+ pending_acks_info[i].ack_num);
+ tqe = pending_acks_info[i].txqe;
if (tqe) {
wilc_wlan_txq_remove(tqe);
- Statisitcs_DroppedAcks++;
- tqe->status = 1; /* mark the packet send */
+ dropped_acks++;
+ tqe->status = 1;
if (tqe->tx_complete_func)
- tqe->tx_complete_func(tqe->priv, tqe->status);
+ tqe->tx_complete_func(tqe->priv,
+ tqe->status);
kfree(tqe);
- Dropped++;
+ dropped++;
}
}
}
- Pending_Acks = 0;
- Opened_TCP_session = 0;
+ pending_acks = 0;
+ tcp_session = 0;
- if (PendingAcks_arrBase == 0)
- PendingAcks_arrBase = MAX_TCP_SESSION;
+ if (pending_base == 0)
+ pending_base = MAX_TCP_SESSION;
else
- PendingAcks_arrBase = 0;
-
+ pending_base = 0;
- spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock,
- p->txq_spinlock_flags);
+ spin_unlock_irqrestore(&wilc->txq_spinlock, p->txq_spinlock_flags);
- while (Dropped > 0) {
- /*consume the semaphore count of the removed packet*/
- linux_wlan_lock_timeout(&g_linux_wlan->txq_event, 1);
- Dropped--;
+ while (dropped > 0) {
+ linux_wlan_lock_timeout(&wilc->txq_event, 1);
+ dropped--;
}
return 1;
}
#endif
-bool EnableTCPAckFilter = false;
+bool enabled = false;
-void Enable_TCP_ACK_Filter(bool value)
+void enable_tcp_ack_filter(bool value)
{
- EnableTCPAckFilter = value;
+ enabled = value;
}
-bool is_TCP_ACK_Filter_Enabled(void)
+bool is_tcp_ack_filter_enabled(void)
{
- return EnableTCPAckFilter;
+ return enabled;
}
static int wilc_wlan_txq_add_cfg_pkt(u8 *buffer, u32 buffer_size)
@@ -477,8 +414,8 @@ static int wilc_wlan_txq_add_cfg_pkt(u8 *buffer, u32 buffer_size)
return 0;
}
- tqe = kmalloc(sizeof(struct txq_entry_t), GFP_ATOMIC);
- if (tqe == NULL) {
+ tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
+ if (!tqe) {
PRINT_ER("Failed to allocate memory\n");
return 0;
}
@@ -489,11 +426,8 @@ static int wilc_wlan_txq_add_cfg_pkt(u8 *buffer, u32 buffer_size)
tqe->tx_complete_func = NULL;
tqe->priv = NULL;
#ifdef TCP_ACK_FILTER
- tqe->tcp_PendingAck_index = NOT_TCP_ACK;
+ tqe->index = NOT_TCP_ACK;
#endif
- /**
- * Configuration packet always at the front
- **/
PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n");
if (wilc_wlan_txq_add_to_head(tqe))
@@ -501,8 +435,8 @@ static int wilc_wlan_txq_add_cfg_pkt(u8 *buffer, u32 buffer_size)
return 1;
}
-int wilc_wlan_txq_add_net_pkt(void *priv, u8 *buffer, u32 buffer_size,
- wilc_tx_complete_func_t func)
+int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
+ u32 buffer_size, wilc_tx_complete_func_t func)
{
wilc_wlan_dev_t *p = &g_wlan;
struct txq_entry_t *tqe;
@@ -510,9 +444,9 @@ int wilc_wlan_txq_add_net_pkt(void *priv, u8 *buffer, u32 buffer_size,
if (p->quit)
return 0;
- tqe = kmalloc(sizeof(struct txq_entry_t), GFP_ATOMIC);
+ tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
- if (tqe == NULL)
+ if (!tqe)
return 0;
tqe->type = WILC_NET_PKT;
tqe->buffer = buffer;
@@ -522,27 +456,26 @@ int wilc_wlan_txq_add_net_pkt(void *priv, u8 *buffer, u32 buffer_size,
PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
#ifdef TCP_ACK_FILTER
- tqe->tcp_PendingAck_index = NOT_TCP_ACK;
- if (is_TCP_ACK_Filter_Enabled())
- tcp_process(tqe);
+ tqe->index = NOT_TCP_ACK;
+ if (is_tcp_ack_filter_enabled())
+ tcp_process(dev, tqe);
#endif
- wilc_wlan_txq_add_to_tail(tqe);
- /*return number of itemes in the queue*/
+ wilc_wlan_txq_add_to_tail(dev, tqe);
return p->txq_entries;
}
-int wilc_wlan_txq_add_mgmt_pkt(void *priv, u8 *buffer, u32 buffer_size, wilc_tx_complete_func_t func)
+int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
+ u32 buffer_size, wilc_tx_complete_func_t func)
{
-
wilc_wlan_dev_t *p = &g_wlan;
struct txq_entry_t *tqe;
if (p->quit)
return 0;
- tqe = kmalloc(sizeof(struct txq_entry_t), GFP_KERNEL);
+ tqe = kmalloc(sizeof(*tqe), GFP_KERNEL);
- if (tqe == NULL)
+ if (!tqe)
return 0;
tqe->type = WILC_MGMT_PKT;
tqe->buffer = buffer;
@@ -550,50 +483,50 @@ int wilc_wlan_txq_add_mgmt_pkt(void *priv, u8 *buffer, u32 buffer_size, wilc_tx_
tqe->tx_complete_func = func;
tqe->priv = priv;
#ifdef TCP_ACK_FILTER
- tqe->tcp_PendingAck_index = NOT_TCP_ACK;
+ tqe->index = NOT_TCP_ACK;
#endif
PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n");
- wilc_wlan_txq_add_to_tail(tqe);
+ wilc_wlan_txq_add_to_tail(dev, tqe);
return 1;
}
-static struct txq_entry_t *wilc_wlan_txq_get_first(void)
+static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
{
wilc_wlan_dev_t *p = &g_wlan;
struct txq_entry_t *tqe;
unsigned long flags;
- spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
+ spin_lock_irqsave(&wilc->txq_spinlock, flags);
tqe = p->txq_head;
- spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
-
+ spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
return tqe;
}
-static struct txq_entry_t *wilc_wlan_txq_get_next(struct txq_entry_t *tqe)
+static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
+ struct txq_entry_t *tqe)
{
unsigned long flags;
- spin_lock_irqsave(&g_linux_wlan->txq_spinlock, flags);
- tqe = tqe->next;
- spin_unlock_irqrestore(&g_linux_wlan->txq_spinlock, flags);
+ spin_lock_irqsave(&wilc->txq_spinlock, flags);
+ tqe = tqe->next;
+ spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
return tqe;
}
-static int wilc_wlan_rxq_add(struct rxq_entry_t *rqe)
+static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
{
wilc_wlan_dev_t *p = &g_wlan;
if (p->quit)
return 0;
- mutex_lock(&g_linux_wlan->rxq_cs);
- if (p->rxq_head == NULL) {
+ mutex_lock(&wilc->rxq_cs);
+ if (!p->rxq_head) {
PRINT_D(RX_DBG, "Add to Queue head\n");
rqe->next = NULL;
p->rxq_head = rqe;
@@ -606,11 +539,11 @@ static int wilc_wlan_rxq_add(struct rxq_entry_t *rqe)
}
p->rxq_entries += 1;
PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries);
- mutex_unlock(&g_linux_wlan->rxq_cs);
+ mutex_unlock(&wilc->rxq_cs);
return p->rxq_entries;
}
-static struct rxq_entry_t *wilc_wlan_rxq_remove(void)
+static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
{
wilc_wlan_dev_t *p = &g_wlan;
@@ -618,34 +551,24 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(void)
if (p->rxq_head) {
struct rxq_entry_t *rqe;
- mutex_lock(&g_linux_wlan->rxq_cs);
+ mutex_lock(&wilc->rxq_cs);
rqe = p->rxq_head;
p->rxq_head = p->rxq_head->next;
p->rxq_entries -= 1;
PRINT_D(RX_DBG, "RXQ entries decreased\n");
- mutex_unlock(&g_linux_wlan->rxq_cs);
+ mutex_unlock(&wilc->rxq_cs);
return rqe;
}
PRINT_D(RX_DBG, "Nothing to get from Q\n");
return NULL;
}
-
-/********************************************
- *
- * Power Save handle functions
- *
- ********************************************/
-
-
-
#ifdef WILC_OPTIMIZE_SLEEP_INT
static inline void chip_allow_sleep(void)
{
u32 reg = 0;
- /* Clear bit 1 */
g_wlan.hif_func.hif_read_reg(0xf0, &reg);
g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
@@ -659,17 +582,11 @@ static inline void chip_wakeup(void)
if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
do {
g_wlan.hif_func.hif_read_reg(1, &reg);
- /* Set bit 1 */
g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
-
- /* Clear bit 1*/
g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
do {
- /* Wait for the chip to stabilize*/
usleep_range(2 * 1000, 2 * 1000);
- /* Make sure chip is awake. This is an extra step that can be removed */
- /* later to avoid the bus access overhead */
if ((wilc_get_chipid(true) == 0))
wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
@@ -679,44 +596,30 @@ static inline void chip_wakeup(void)
} else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
g_wlan.hif_func.hif_read_reg(0xf0, &reg);
do {
- /* Set bit 1 */
g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
-
- /* Check the clock status */
g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
- /* in case of clocks off, wait 2ms, and check it again. */
- /* if still off, wait for another 2ms, for a total wait of 6ms. */
- /* If still off, redo the wake up sequence */
while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
- /* Wait for the chip to stabilize*/
usleep_range(2 * 1000, 2 * 1000);
- /* Make sure chip is awake. This is an extra step that can be removed */
- /* later to avoid the bus access overhead */
g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
if ((clk_status_reg & 0x1) == 0)
wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n");
-
}
- /* in case of failure, Reset the wakeup bit to introduce a new edge on the next loop */
if ((clk_status_reg & 0x1) == 0) {
- /* Reset bit 0 */
g_wlan.hif_func.hif_write_reg(0xf0, reg &
(~BIT(0)));
}
} while ((clk_status_reg & 0x1) == 0);
}
-
- if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
+ if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
reg &= ~BIT(0);
g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
if (wilc_get_chipid(false) >= 0x1002b0) {
- /* Enable PALDO back right after wakeup */
u32 val32;
g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
@@ -728,7 +631,7 @@ static inline void chip_wakeup(void)
g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
}
}
- genuChipPSstate = CHIP_WAKEDUP;
+ chip_ps_state = CHIP_WAKEDUP;
}
#else
static inline void chip_wakeup(void)
@@ -738,28 +641,19 @@ static inline void chip_wakeup(void)
do {
if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
g_wlan.hif_func.hif_read_reg(1, &reg);
- /* Make sure bit 1 is 0 before we start. */
g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
- /* Set bit 1 */
g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
- /* Clear bit 1*/
g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
} else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO) {
- /* Make sure bit 0 is 0 before we start. */
g_wlan.hif_func.hif_read_reg(0xf0, &reg);
g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
- /* Set bit 1 */
g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
- /* Clear bit 1 */
g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
}
do {
- /* Wait for the chip to stabilize*/
mdelay(3);
- /* Make sure chip is awake. This is an extra step that can be removed */
- /* later to avoid the bus access overhead */
if ((wilc_get_chipid(true) == 0))
wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
@@ -767,13 +661,12 @@ static inline void chip_wakeup(void)
} while (wilc_get_chipid(true) == 0);
- if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
+ if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
reg &= ~BIT(0);
g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
if (wilc_get_chipid(false) >= 0x1002b0) {
- /* Enable PALDO back right after wakeup */
u32 val32;
g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
@@ -785,36 +678,25 @@ static inline void chip_wakeup(void)
g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
}
}
- genuChipPSstate = CHIP_WAKEDUP;
+ chip_ps_state = CHIP_WAKEDUP;
}
#endif
-void chip_sleep_manually(u32 u32SleepTime)
+void chip_sleep_manually(void)
{
- if (genuChipPSstate != CHIP_WAKEDUP) {
- /* chip is already sleeping. Do nothing */
+ if (chip_ps_state != CHIP_WAKEDUP)
return;
- }
acquire_bus(ACQUIRE_ONLY);
#ifdef WILC_OPTIMIZE_SLEEP_INT
chip_allow_sleep();
#endif
-
- /* Trigger the manual sleep interrupt */
g_wlan.hif_func.hif_write_reg(0x10a8, 1);
- genuChipPSstate = CHIP_SLEEPING_MANUAL;
+ chip_ps_state = CHIP_SLEEPING_MANUAL;
release_bus(RELEASE_ONLY);
-
}
-
-/********************************************
- *
- * Tx, Rx queue handle functions
- *
- ********************************************/
-int wilc_wlan_handle_txq(u32 *pu32TxqCount)
+int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
{
wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
int i, entries = 0;
@@ -828,27 +710,28 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
int counter;
int timeout;
u32 vmm_table[WILC_VMM_TBL_SIZE];
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
p->txq_exit = 0;
do {
if (p->quit)
break;
- linux_wlan_lock_timeout(&g_linux_wlan->txq_add_to_head_cs,
+ linux_wlan_lock_timeout(&wilc->txq_add_to_head_cs,
CFG_PKTS_TIMEOUT);
#ifdef TCP_ACK_FILTER
- wilc_wlan_txq_filter_dup_tcp_ack();
+ wilc_wlan_txq_filter_dup_tcp_ack(dev);
#endif
- /**
- * build the vmm list
- **/
PRINT_D(TX_DBG, "Getting the head of the TxQ\n");
- tqe = wilc_wlan_txq_get_first();
+ tqe = wilc_wlan_txq_get_first(wilc);
i = 0;
sum = 0;
do {
- if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE - 1)) /* reserve last entry to 0 */) {
-
+ if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) {
if (tqe->type == WILC_CFG_PKT)
vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
@@ -860,15 +743,16 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
vmm_sz += tqe->buffer_size;
PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz);
- if (vmm_sz & 0x3) { /* has to be word aligned */
+ if (vmm_sz & 0x3)
vmm_sz = (vmm_sz + 4) & ~0x3;
- }
+
if ((sum + vmm_sz) > LINUX_TX_SIZE)
break;
PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz);
- vmm_table[i] = vmm_sz / 4; /* table take the word size */
- PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]);
+ vmm_table[i] = vmm_sz / 4;
+ PRINT_D(TX_DBG, "VMMTable entry size = %d\n",
+ vmm_table[i]);
if (tqe->type == WILC_CFG_PKT) {
vmm_table[i] |= BIT(10);
@@ -881,23 +765,22 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
i++;
sum += vmm_sz;
PRINT_D(TX_DBG, "sum = %d\n", sum);
- tqe = wilc_wlan_txq_get_next(tqe);
+ tqe = wilc_wlan_txq_get_next(wilc, tqe);
} else {
break;
}
} while (1);
- if (i == 0) { /* nothing in the queue */
+ if (i == 0) {
PRINT_D(TX_DBG, "Nothing in TX-Q\n");
break;
} else {
PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i);
- vmm_table[i] = 0x0; /* mark the last element to 0 */
+ vmm_table[i] = 0x0;
}
acquire_bus(ACQUIRE_AND_WAKEUP);
counter = 0;
do {
-
ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
if (!ret) {
wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n");
@@ -905,9 +788,6 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
}
if ((reg & 0x1) == 0) {
- /**
- * write to vmm table
- **/
PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4));
break;
} else {
@@ -918,9 +798,6 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, 0);
break;
}
- /**
- * wait for vmm table is ready
- **/
PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n");
release_bus(RELEASE_ALLOW_SLEEP);
usleep_range(3000, 3000);
@@ -933,30 +810,18 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
timeout = 200;
do {
-
- /**
- * write to vmm table
- **/
ret = p->hif_func.hif_block_tx(WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4));
if (!ret) {
wilc_debug(N_ERR, "ERR block TX of VMM table.\n");
break;
}
-
- /**
- * interrupt firmware
- **/
ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x2);
if (!ret) {
wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n");
break;
}
- /**
- * wait for confirm...
- **/
-
do {
ret = p->hif_func.hif_read_reg(WILC_HOST_VMM_CTL, &reg);
if (!ret) {
@@ -964,9 +829,6 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
break;
}
if ((reg >> 2) & 0x1) {
- /**
- * Get the entries
- **/
entries = ((reg >> 3) & 0x3f);
break;
} else {
@@ -987,7 +849,6 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
if (entries == 0) {
PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]);
- /* undo the transaction. */
ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
if (!ret) {
wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
@@ -1013,26 +874,23 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
goto _end_;
}
- /* since copying data into txb takes some time, then
- * allow the bus lock to be released let the RX task go. */
release_bus(RELEASE_ALLOW_SLEEP);
- /**
- * Copy data to the TX buffer
- **/
offset = 0;
i = 0;
do {
- tqe = wilc_wlan_txq_remove_from_head();
- if (tqe != NULL && (vmm_table[i] != 0)) {
+ tqe = wilc_wlan_txq_remove_from_head(dev);
+ if (tqe && (vmm_table[i] != 0)) {
u32 header, buffer_offset;
#ifdef BIG_ENDIAN
vmm_table[i] = BYTE_SWAP(vmm_table[i]);
#endif
- vmm_sz = (vmm_table[i] & 0x3ff); /* in word unit */
+ vmm_sz = (vmm_table[i] & 0x3ff);
vmm_sz *= 4;
- header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz;
+ header = (tqe->type << 31) |
+ (tqe->buffer_size << 15) |
+ vmm_sz;
if (tqe->type == WILC_MGMT_PKT)
header |= BIT(30);
else
@@ -1044,27 +902,26 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
memcpy(&txb[offset], &header, 4);
if (tqe->type == WILC_CFG_PKT) {
buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
- }
- else if (tqe->type == WILC_NET_PKT) {
- char *pBSSID = ((struct tx_complete_data *)(tqe->priv))->pBssid;
+ } else if (tqe->type == WILC_NET_PKT) {
+ char *bssid = ((struct tx_complete_data *)(tqe->priv))->pBssid;
buffer_offset = ETH_ETHERNET_HDR_OFFSET;
- /* copy the bssid at the sart of the buffer */
- memcpy(&txb[offset + 4], pBSSID, 6);
- }
- else {
+ memcpy(&txb[offset + 4], bssid, 6);
+ } else {
buffer_offset = HOST_HDR_OFFSET;
}
- memcpy(&txb[offset + buffer_offset], tqe->buffer, tqe->buffer_size);
+ memcpy(&txb[offset + buffer_offset],
+ tqe->buffer, tqe->buffer_size);
offset += vmm_sz;
i++;
- tqe->status = 1; /* mark the packet send */
+ tqe->status = 1;
if (tqe->tx_complete_func)
- tqe->tx_complete_func(tqe->priv, tqe->status);
+ tqe->tx_complete_func(tqe->priv,
+ tqe->status);
#ifdef TCP_ACK_FILTER
- if (tqe->tcp_PendingAck_index != NOT_TCP_ACK)
- Pending_Acks_info[tqe->tcp_PendingAck_index].txqe = NULL;
+ if (tqe->index != NOT_TCP_ACK)
+ pending_acks_info[tqe->index].txqe = NULL;
#endif
kfree(tqe);
} else {
@@ -1072,9 +929,6 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
}
} while (--entries);
- /**
- * lock the bus
- **/
acquire_bus(ACQUIRE_AND_WAKEUP);
ret = p->hif_func.hif_clear_int_ext(ENABLE_TX_VMM);
@@ -1083,9 +937,6 @@ int wilc_wlan_handle_txq(u32 *pu32TxqCount)
goto _end_;
}
- /**
- * transfer
- **/
ret = p->hif_func.hif_block_tx_ext(0, txb, offset);
if (!ret) {
wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n");
@@ -1098,16 +949,15 @@ _end_:
if (ret != 1)
break;
} while (0);
- up(&g_linux_wlan->txq_add_to_head_cs);
+ up(&wilc->txq_add_to_head_cs);
p->txq_exit = 1;
PRINT_D(TX_DBG, "THREAD: Exiting txq\n");
- /* return tx[]q count */
- *pu32TxqCount = p->txq_entries;
+ *txq_count = p->txq_entries;
return ret;
}
-static void wilc_wlan_handle_rxq(void)
+static void wilc_wlan_handle_rxq(struct wilc *wilc)
{
wilc_wlan_dev_t *p = &g_wlan;
int offset = 0, size, has_packet = 0;
@@ -1116,27 +966,23 @@ static void wilc_wlan_handle_rxq(void)
p->rxq_exit = 0;
-
-
-
do {
if (p->quit) {
PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n");
- up(&g_linux_wlan->cfg_event);
+ up(&wilc->cfg_event);
break;
}
- rqe = wilc_wlan_rxq_remove();
- if (rqe == NULL) {
+ rqe = wilc_wlan_rxq_remove(wilc);
+ if (!rqe) {
PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n");
break;
}
buffer = rqe->buffer;
size = rqe->buffer_size;
- PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", size, buffer);
+ PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n",
+ size, buffer);
offset = 0;
-
-
do {
u32 header;
u32 pkt_len, pkt_offset, tp_len;
@@ -1147,9 +993,8 @@ static void wilc_wlan_handle_rxq(void)
#ifdef BIG_ENDIAN
header = BYTE_SWAP(header);
#endif
- PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", header, offset);
-
-
+ PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n",
+ header, offset);
is_cfg_packet = (header >> 31) & 0x1;
pkt_offset = (header >> 22) & 0x1ff;
@@ -1165,44 +1010,34 @@ static void wilc_wlan_handle_rxq(void)
#define IS_MANAGMEMENT_CALLBACK 0x080
#define IS_MGMT_STATUS_SUCCES 0x040
-
if (pkt_offset & IS_MANAGMEMENT) {
- /* reset mgmt indicator bit, to use pkt_offeset in furthur calculations */
- pkt_offset &= ~(IS_MANAGMEMENT | IS_MANAGMEMENT_CALLBACK | IS_MGMT_STATUS_SUCCES);
-
- WILC_WFI_mgmt_rx(&buffer[offset + HOST_HDR_OFFSET], pkt_len);
- }
- else
- {
+ pkt_offset &= ~(IS_MANAGMEMENT |
+ IS_MANAGMEMENT_CALLBACK |
+ IS_MGMT_STATUS_SUCCES);
+ WILC_WFI_mgmt_rx(wilc, &buffer[offset + HOST_HDR_OFFSET], pkt_len);
+ } else {
if (!is_cfg_packet) {
if (pkt_len > 0) {
- frmw_to_linux(&buffer[offset],
+ frmw_to_linux(wilc,
+ &buffer[offset],
pkt_len,
pkt_offset);
has_packet = 1;
}
} else {
- wilc_cfg_rsp_t rsp;
-
-
+ struct wilc_cfg_rsp rsp;
wilc_wlan_cfg_indicate_rx(&buffer[pkt_offset + offset], pkt_len, &rsp);
if (rsp.type == WILC_CFG_RSP) {
- /**
- * wake up the waiting task...
- **/
PRINT_D(RX_DBG, "p->cfg_seq_no = %d - rsp.seq_no = %d\n", p->cfg_seq_no, rsp.seq_no);
if (p->cfg_seq_no == rsp.seq_no)
- up(&g_linux_wlan->cfg_event);
+ up(&wilc->cfg_event);
} else if (rsp.type == WILC_CFG_RSP_STATUS) {
- /**
- * Call back to indicate status...
- **/
- linux_wlan_mac_indicate(WILC_MAC_INDICATE_STATUS);
+ linux_wlan_mac_indicate(wilc, WILC_MAC_INDICATE_STATUS);
} else if (rsp.type == WILC_CFG_RSP_SCAN) {
- linux_wlan_mac_indicate(WILC_MAC_INDICATE_SCAN);
+ linux_wlan_mac_indicate(wilc, WILC_MAC_INDICATE_SCAN);
}
}
}
@@ -1210,8 +1045,6 @@ static void wilc_wlan_handle_rxq(void)
if (offset >= size)
break;
} while (1);
-
-
#ifndef MEMORY_STATIC
kfree(buffer);
#endif
@@ -1226,26 +1059,19 @@ static void wilc_wlan_handle_rxq(void)
PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n");
}
-/********************************************
- *
- * Fast DMA Isr
- *
- ********************************************/
static void wilc_unknown_isr_ext(void)
{
g_wlan.hif_func.hif_clear_int_ext(0);
}
+
static void wilc_pllupdate_isr_ext(u32 int_stats)
{
-
int trials = 10;
g_wlan.hif_func.hif_clear_int_ext(PLL_INT_CLR);
- /* Waiting for PLL */
mdelay(WILC_PLL_TO);
- /* poll till read a valid data */
while (!(ISWILC1000(wilc_get_chipid(true)) && --trials)) {
PRINT_D(TX_DBG, "PLL update retrying\n");
mdelay(1);
@@ -1256,11 +1082,11 @@ static void wilc_sleeptimer_isr_ext(u32 int_stats1)
{
g_wlan.hif_func.hif_clear_int_ext(SLEEP_INT_CLR);
#ifndef WILC_OPTIMIZE_SLEEP_INT
- genuChipPSstate = CHIP_SLEEPING_AUTO;
+ chip_ps_state = CHIP_SLEEPING_AUTO;
#endif
}
-static void wilc_wlan_handle_isr_ext(u32 int_status)
+static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
{
wilc_wlan_dev_t *p = &g_wlan;
#ifdef MEMORY_STATIC
@@ -1272,22 +1098,15 @@ static void wilc_wlan_handle_isr_ext(u32 int_status)
int ret = 0;
struct rxq_entry_t *rqe;
-
- /**
- * Get the rx size
- **/
-
size = ((int_status & 0x7fff) << 2);
while (!size && retries < 10) {
u32 time = 0;
- /*looping more secure*/
- /*zero size make a crashe because the dma will not happen and that will block the firmware*/
+
wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++);
p->hif_func.hif_read_size(&size);
size = ((size & 0x7fff) << 2);
retries++;
-
}
if (size > 0) {
@@ -1295,31 +1114,21 @@ static void wilc_wlan_handle_isr_ext(u32 int_status)
if (LINUX_RX_SIZE - offset < size)
offset = 0;
- if (p->rx_buffer)
+ if (p->rx_buffer) {
buffer = &p->rx_buffer[offset];
- else {
+ } else {
wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size);
goto _end_;
}
#else
buffer = kmalloc(size, GFP_KERNEL);
- if (buffer == NULL) {
- wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
+ if (!buffer) {
usleep_range(100 * 1000, 100 * 1000);
goto _end_;
}
#endif
-
- /**
- * clear the chip's interrupt after getting size some register getting corrupted after clear the interrupt
- **/
p->hif_func.hif_clear_int_ext(DATA_INT_CLR | ENABLE_RX_VMM);
-
-
- /**
- * start transfer
- **/
ret = p->hif_func.hif_block_rx_ext(0, buffer, size);
if (!ret) {
@@ -1327,22 +1136,17 @@ static void wilc_wlan_handle_isr_ext(u32 int_status)
goto _end_;
}
_end_:
-
-
if (ret) {
#ifdef MEMORY_STATIC
offset += size;
p->rx_buffer_offset = offset;
#endif
- /**
- * add to rx queue
- **/
- rqe = kmalloc(sizeof(struct rxq_entry_t), GFP_KERNEL);
- if (rqe != NULL) {
+ rqe = kmalloc(sizeof(*rqe), GFP_KERNEL);
+ if (rqe) {
rqe->buffer = buffer;
rqe->buffer_size = size;
PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer);
- wilc_wlan_rxq_add(rqe);
+ wilc_wlan_rxq_add(wilc, rqe);
}
} else {
#ifndef MEMORY_STATIC
@@ -1350,10 +1154,10 @@ _end_:
#endif
}
}
- wilc_wlan_handle_rxq();
+ wilc_wlan_handle_rxq(wilc);
}
-void wilc_handle_isr(void)
+void wilc_handle_isr(void *wilc)
{
u32 int_status;
@@ -1364,10 +1168,9 @@ void wilc_handle_isr(void)
wilc_pllupdate_isr_ext(int_status);
if (int_status & DATA_INT_EXT) {
- wilc_wlan_handle_isr_ext(int_status);
+ wilc_wlan_handle_isr_ext(wilc, int_status);
#ifndef WILC_OPTIMIZE_SLEEP_INT
- /* Chip is up and talking*/
- genuChipPSstate = CHIP_WAKEDUP;
+ chip_ps_state = CHIP_WAKEDUP;
#endif
}
if (int_status & SLEEP_INT_EXT)
@@ -1382,11 +1185,6 @@ void wilc_handle_isr(void)
release_bus(RELEASE_ALLOW_SLEEP);
}
-/********************************************
- *
- * Firmware download
- *
- ********************************************/
int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
{
wilc_wlan_dev_t *p = &g_wlan;
@@ -1396,20 +1194,16 @@ int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
int ret = 0;
blksz = BIT(12);
- /* Allocate a DMA coherent buffer. */
dma_buffer = kmalloc(blksz, GFP_KERNEL);
- if (dma_buffer == NULL) {
- /*EIO 5*/
- ret = -5;
+ if (!dma_buffer) {
+ ret = -EIO;
PRINT_ER("Can't allocate buffer for firmware download IO error\n ");
goto _fail_1;
}
PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size);
- /**
- * load the firmware
- **/
+
offset = 0;
do {
memcpy(&addr, &buffer[offset], 4);
@@ -1425,7 +1219,7 @@ int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
size2 = size;
else
size2 = blksz;
- /* Copy firmware into a DMA coherent buffer */
+
memcpy(dma_buffer, &buffer[offset], size2);
ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
if (!ret)
@@ -1438,8 +1232,7 @@ int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
release_bus(RELEASE_ONLY);
if (!ret) {
- /*EIO 5*/
- ret = -5;
+ ret = -EIO;
PRINT_ER("Can't download firmware IO error\n ");
goto _fail_;
}
@@ -1455,11 +1248,6 @@ _fail_1:
return (ret < 0) ? ret : 0;
}
-/********************************************
- *
- * Common
- *
- ********************************************/
int wilc_wlan_start(void)
{
wilc_wlan_dev_t *p = &g_wlan;
@@ -1467,12 +1255,9 @@ int wilc_wlan_start(void)
int ret;
u32 chipid;
- /**
- * Set the host interface
- **/
if (p->io_func.io_type == HIF_SDIO) {
reg = 0;
- reg |= BIT(3); /* bug 4456 and 4557 */
+ reg |= BIT(3);
} else if (p->io_func.io_type == HIF_SPI) {
reg = 1;
}
@@ -1481,8 +1266,7 @@ int wilc_wlan_start(void)
if (!ret) {
wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n");
release_bus(RELEASE_ONLY);
- /* EIO 5*/
- ret = -5;
+ ret = -EIO;
return ret;
}
reg = 0;
@@ -1506,14 +1290,9 @@ int wilc_wlan_start(void)
#endif
reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
-
-
-/*Set oscillator frequency*/
#ifdef XTAL_24
reg |= WILC_HAVE_XTAL_24;
#endif
-
-/*Enable/Disable GPIO configuration for FW logs*/
#ifdef DISABLE_WILC_UART
reg |= WILC_HAVE_DISABLE_WILC_UART;
#endif
@@ -1522,30 +1301,20 @@ int wilc_wlan_start(void)
if (!ret) {
wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n");
release_bus(RELEASE_ONLY);
- /* EIO 5*/
- ret = -5;
+ ret = -EIO;
return ret;
}
- /**
- * Bus related
- **/
p->hif_func.hif_sync_ext(NUM_INT_EXT);
ret = p->hif_func.hif_read_reg(0x1000, &chipid);
if (!ret) {
wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n");
release_bus(RELEASE_ONLY);
- /* EIO 5*/
- ret = -5;
+ ret = -EIO;
return ret;
}
- /**
- * Go...
- **/
-
-
p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
if ((reg & BIT(10)) == BIT(10)) {
reg &= ~BIT(10);
@@ -1576,9 +1345,6 @@ int wilc_wlan_stop(void)
u32 reg = 0;
int ret;
u8 timeout = 10;
- /**
- * TODO: stop the firmware, need a re-download
- **/
acquire_bus(ACQUIRE_AND_WAKEUP);
ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
@@ -1589,8 +1355,6 @@ int wilc_wlan_stop(void)
}
reg &= ~BIT(10);
-
-
ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
if (!ret) {
PRINT_ER("Error while writing reg\n");
@@ -1598,8 +1362,6 @@ int wilc_wlan_stop(void)
return ret;
}
-
-
do {
ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
if (!ret) {
@@ -1607,22 +1369,26 @@ int wilc_wlan_stop(void)
release_bus(RELEASE_ALLOW_SLEEP);
return ret;
}
- PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
- /*Workaround to ensure that the chip is actually reset*/
+ PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n",
+ reg, timeout);
+
if ((reg & BIT(10))) {
- PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout);
+ PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n",
+ timeout);
reg &= ~BIT(10);
ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
timeout--;
} else {
- PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout);
+ PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n",
+ timeout);
ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
if (!ret) {
PRINT_ER("Error while reading reg\n");
release_bus(RELEASE_ALLOW_SLEEP);
return ret;
}
- PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
+ PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n",
+ reg, timeout);
break;
}
@@ -1640,18 +1406,23 @@ int wilc_wlan_stop(void)
return ret;
}
-void wilc_wlan_cleanup(void)
+void wilc_wlan_cleanup(struct net_device *dev)
{
wilc_wlan_dev_t *p = &g_wlan;
struct txq_entry_t *tqe;
struct rxq_entry_t *rqe;
u32 reg = 0;
int ret;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
+
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
p->quit = 1;
do {
- tqe = wilc_wlan_txq_remove_from_head();
- if (tqe == NULL)
+ tqe = wilc_wlan_txq_remove_from_head(dev);
+ if (!tqe)
break;
if (tqe->tx_complete_func)
tqe->tx_complete_func(tqe->priv, 0);
@@ -1659,8 +1430,8 @@ void wilc_wlan_cleanup(void)
} while (1);
do {
- rqe = wilc_wlan_rxq_remove();
- if (rqe == NULL)
+ rqe = wilc_wlan_rxq_remove(wilc);
+ if (!rqe)
break;
#ifndef MEMORY_STATIC
kfree(rqe->buffer);
@@ -1668,10 +1439,6 @@ void wilc_wlan_cleanup(void)
kfree(rqe);
} while (1);
- /**
- * clean up buffer
- **/
-
#ifdef MEMORY_STATIC
kfree(p->rx_buffer);
p->rx_buffer = NULL;
@@ -1680,7 +1447,6 @@ void wilc_wlan_cleanup(void)
acquire_bus(ACQUIRE_AND_WAKEUP);
-
ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, &reg);
if (!ret) {
PRINT_ER("Error while reading reg\n");
@@ -1693,31 +1459,22 @@ void wilc_wlan_cleanup(void)
release_bus(RELEASE_ALLOW_SLEEP);
}
release_bus(RELEASE_ALLOW_SLEEP);
- /**
- * io clean up
- **/
p->hif_func.hif_deinit(NULL);
-
}
-static int wilc_wlan_cfg_commit(int type, u32 drvHandler)
+static int wilc_wlan_cfg_commit(int type, u32 drv_handler)
{
wilc_wlan_dev_t *p = &g_wlan;
- wilc_cfg_frame_t *cfg = &p->cfg_frame;
+ struct wilc_cfg_frame *cfg = &p->cfg_frame;
int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
int seq_no = p->cfg_seq_no % 256;
- int driver_handler = (u32)drvHandler;
+ int driver_handler = (u32)drv_handler;
-
- /**
- * Set up header
- **/
- if (type == WILC_CFG_SET) { /* Set */
+ if (type == WILC_CFG_SET)
cfg->wid_header[0] = 'W';
- } else { /* Query */
+ else
cfg->wid_header[0] = 'Q';
- }
- cfg->wid_header[1] = seq_no; /* sequence number */
+ 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;
@@ -1726,10 +1483,6 @@ static int wilc_wlan_cfg_commit(int type, u32 drvHandler)
cfg->wid_header[7] = (u8)(driver_handler >> 24);
p->cfg_seq_no = seq_no;
- /**
- * Add to TX queue
- **/
-
if (!wilc_wlan_txq_add_cfg_pkt(&cfg->wid_header[0], total_len))
return -1;
@@ -1737,13 +1490,12 @@ static int wilc_wlan_cfg_commit(int type, u32 drvHandler)
}
int wilc_wlan_cfg_set(int start, u32 wid, u8 *buffer, u32 buffer_size,
- int commit, u32 drvHandler)
+ int commit, u32 drv_handler)
{
wilc_wlan_dev_t *p = &g_wlan;
u32 offset;
int ret_size;
-
if (p->cfg_frame_in_use)
return 0;
@@ -1757,11 +1509,12 @@ int wilc_wlan_cfg_set(int start, u32 wid, u8 *buffer, u32 buffer_size,
p->cfg_frame_offset = offset;
if (commit) {
- PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", p->cfg_seq_no);
+ PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n",
+ p->cfg_seq_no);
PRINT_D(RX_DBG, "Processing cfg_set()\n");
p->cfg_frame_in_use = 1;
- if (wilc_wlan_cfg_commit(WILC_CFG_SET, drvHandler))
+ if (wilc_wlan_cfg_commit(WILC_CFG_SET, drv_handler))
ret_size = 0;
if (linux_wlan_lock_timeout(&g_linux_wlan->cfg_event,
@@ -1772,18 +1525,17 @@ int wilc_wlan_cfg_set(int start, u32 wid, u8 *buffer, u32 buffer_size,
p->cfg_frame_in_use = 0;
p->cfg_frame_offset = 0;
p->cfg_seq_no += 1;
-
}
return ret_size;
}
-int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drvHandler)
+
+int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drv_handler)
{
wilc_wlan_dev_t *p = &g_wlan;
u32 offset;
int ret_size;
-
if (p->cfg_frame_in_use)
return 0;
@@ -1798,10 +1550,9 @@ int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drvHandler)
if (commit) {
p->cfg_frame_in_use = 1;
- if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drvHandler))
+ if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drv_handler))
ret_size = 0;
-
if (linux_wlan_lock_timeout(&g_linux_wlan->cfg_event,
CFG_PKTS_TIMEOUT)) {
PRINT_D(TX_DBG, "Get Timed Out\n");
@@ -1827,18 +1578,15 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size)
void wilc_bus_set_max_speed(void)
{
-
- /* Increase bus speed to max possible. */
g_wlan.hif_func.hif_set_max_bus_speed();
}
void wilc_bus_set_default_speed(void)
{
-
- /* Restore bus speed to default. */
g_wlan.hif_func.hif_set_default_bus_speed();
}
-u32 init_chip(void)
+
+u32 init_chip(struct net_device *dev)
{
u32 chipid;
u32 reg, ret = 0;
@@ -1847,14 +1595,7 @@ u32 init_chip(void)
chipid = wilc_get_chipid(true);
-
-
if ((chipid & 0xfff) != 0xa0) {
- /**
- * Avoid booting from boot ROM. Make sure that Drive IRQN [SDIO platform]
- * or SD_DAT3 [SPI platform] to ?1?
- **/
- /* Set cortus reset register to register control. */
ret = g_wlan.hif_func.hif_read_reg(0x1118, &reg);
if (!ret) {
wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n");
@@ -1866,10 +1607,6 @@ u32 init_chip(void)
wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n");
return ret;
}
- /**
- * Write branch intruction to IRAM (0x71 trap) at location 0xFFFF0000
- * (Cortus map) or C0000 (AHB map).
- **/
ret = g_wlan.hif_func.hif_write_reg(0xc0000, 0x71);
if (!ret) {
wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n");
@@ -1880,14 +1617,11 @@ u32 init_chip(void)
release_bus(RELEASE_ONLY);
return ret;
-
}
u32 wilc_get_chipid(u8 update)
{
static u32 chipid;
- /* SDIO can't read into global variables */
- /* Use this variable as a temp, then copy to the global */
u32 tempchipid = 0;
u32 rfrevid;
@@ -1899,18 +1633,17 @@ u32 wilc_get_chipid(u8 update)
goto _fail_;
}
if (tempchipid == 0x1002a0) {
- if (rfrevid == 0x1) { /* 1002A0 */
- } else { /* if (rfrevid == 0x2) */ /* 1002A1 */
+ if (rfrevid == 0x1) {
+ } else {
tempchipid = 0x1002a1;
}
} else if (tempchipid == 0x1002b0) {
- if (rfrevid == 3) { /* 1002B0 */
- } else if (rfrevid == 4) { /* 1002B1 */
+ if (rfrevid == 3) {
+ } else if (rfrevid == 4) {
tempchipid = 0x1002b1;
- } else { /* if(rfrevid == 5) */ /* 1002B2 */
+ } else {
tempchipid = 0x1002b2;
}
- } else {
}
chipid = tempchipid;
@@ -1919,108 +1652,68 @@ _fail_:
return chipid;
}
-#ifdef COMPLEMENT_BOOT
-u8 core_11b_ready(void)
+int wilc_wlan_init(struct net_device *dev, wilc_wlan_inp_t *inp)
{
- u32 reg_val;
-
- acquire_bus(ACQUIRE_ONLY);
- g_wlan.hif_func.hif_write_reg(0x16082c, 1);
- g_wlan.hif_func.hif_write_reg(0x161600, 0x90);
- g_wlan.hif_func.hif_read_reg(0x161600, &reg_val);
- release_bus(RELEASE_ONLY);
-
- if (reg_val == 0x90)
- return 0;
- else
- return 1;
-}
-#endif
-
-int wilc_wlan_init(wilc_wlan_inp_t *inp)
-{
-
int ret = 0;
+ perInterface_wlan_t *nic = netdev_priv(dev);
+ struct wilc *wilc;
+
+ wilc = nic->wilc;
PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n");
memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t));
+ memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func,
+ sizeof(wilc_wlan_io_func_t));
- /**
- * store the input
- **/
- memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func, sizeof(wilc_wlan_io_func_t));
- /***
- * host interface init
- **/
- if ((inp->io_func.io_type & 0x1) == HIF_SDIO) {
- if (!hif_sdio.hif_init(inp, wilc_debug)) {
- /* EIO 5 */
- ret = -5;
- goto _fail_;
- }
- memcpy((void *)&g_wlan.hif_func, &hif_sdio, sizeof(wilc_hif_func_t));
- } else {
- if ((inp->io_func.io_type & 0x1) == HIF_SPI) {
- /**
- * TODO:
- **/
- if (!hif_spi.hif_init(inp, wilc_debug)) {
- /* EIO 5 */
- ret = -5;
- goto _fail_;
- }
- memcpy((void *)&g_wlan.hif_func, &hif_spi, sizeof(wilc_hif_func_t));
- } else {
- /* EIO 5 */
- ret = -5;
- goto _fail_;
- }
+#ifdef WILC_SDIO
+ if (!hif_sdio.hif_init(wilc, wilc_debug)) {
+ ret = -EIO;
+ goto _fail_;
+ }
+ memcpy((void *)&g_wlan.hif_func, &hif_sdio,
+ sizeof(struct wilc_hif_func));
+#else
+ if (!hif_spi.hif_init(wilc, wilc_debug)) {
+ ret = -EIO;
+ goto _fail_;
}
+ memcpy((void *)&g_wlan.hif_func, &hif_spi,
+ sizeof(struct wilc_hif_func));
+#endif
- /***
- * mac interface init
- **/
if (!wilc_wlan_cfg_init(wilc_debug)) {
- /* ENOBUFS 105 */
- ret = -105;
+ ret = -ENOBUFS;
goto _fail_;
}
- /**
- * alloc tx, rx buffer
- **/
- if (g_wlan.tx_buffer == NULL)
+ if (!g_wlan.tx_buffer)
g_wlan.tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL);
PRINT_D(TX_DBG, "g_wlan.tx_buffer = %p\n", g_wlan.tx_buffer);
- if (g_wlan.tx_buffer == NULL) {
- /* ENOBUFS 105 */
- ret = -105;
+ if (!g_wlan.tx_buffer) {
+ ret = -ENOBUFS;
PRINT_ER("Can't allocate Tx Buffer");
goto _fail_;
}
-/* rx_buffer is not used unless we activate USE_MEM STATIC which is not applicable, allocating such memory is useless*/
-#if defined (MEMORY_STATIC)
- if (g_wlan.rx_buffer == NULL)
+#if defined(MEMORY_STATIC)
+ if (!g_wlan.rx_buffer)
g_wlan.rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL);
PRINT_D(TX_DBG, "g_wlan.rx_buffer =%p\n", g_wlan.rx_buffer);
- if (g_wlan.rx_buffer == NULL) {
- /* ENOBUFS 105 */
- ret = -105;
+ if (!g_wlan.rx_buffer) {
+ ret = -ENOBUFS;
PRINT_ER("Can't allocate Rx Buffer");
goto _fail_;
}
#endif
- if (!init_chip()) {
- /* EIO 5 */
- ret = -5;
+ if (!init_chip(dev)) {
+ ret = -EIO;
goto _fail_;
}
#ifdef TCP_ACK_FILTER
- Init_TCP_tracking();
+ init_tcp_tracking();
#endif
return 1;
@@ -2035,21 +1728,24 @@ _fail_:
g_wlan.tx_buffer = NULL;
return ret;
-
}
-u16 Set_machw_change_vir_if(bool bValue)
+u16 set_machw_change_vir_if(struct net_device *dev, bool value)
{
u16 ret;
u32 reg;
+ perInterface_wlan_t *nic;
+ struct wilc *wilc;
- /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
- mutex_lock(&g_linux_wlan->hif_cs);
+ nic = netdev_priv(dev);
+ wilc = nic->wilc;
+
+ mutex_lock(&wilc->hif_cs);
ret = (&g_wlan)->hif_func.hif_read_reg(WILC_CHANGING_VIR_IF, &reg);
if (!ret)
PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
- if (bValue)
+ if (value)
reg |= BIT(31);
else
reg &= ~BIT(31);
@@ -2059,7 +1755,7 @@ u16 Set_machw_change_vir_if(bool bValue)
if (!ret)
PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n");
- mutex_unlock(&g_linux_wlan->hif_cs);
+ mutex_unlock(&wilc->hif_cs);
return ret;
}
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
index bd89689fbf10..64fd019595ce 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wilc_wlan.h
@@ -1,37 +1,36 @@
#ifndef WILC_WLAN_H
#define WILC_WLAN_H
-
-
-#define ISWILC1000(id) (((id & 0xfffff000) == 0x100000) ? 1 : 0)
-
-
+#define ISWILC1000(id) ((id & 0xfffff000) == 0x100000 ? 1 : 0)
/********************************************
*
* 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
-#define ETHERNET_HDR_LEN 14
-#define WORD_ALIGNMENT_PAD 0
-
-#define ETH_ETHERNET_HDR_OFFSET (MAX_MAC_HDR_LEN + SUB_MSDU_HEADER_LENGTH + \
- SNAP_HDR_LEN - ETHERNET_HDR_LEN + WORD_ALIGNMENT_PAD)
-
-#define HOST_HDR_OFFSET 4
-#define ETHERNET_HDR_LEN 14
-#define IP_HDR_LEN 20
-#define IP_HDR_OFFSET ETHERNET_HDR_LEN
-#define UDP_HDR_OFFSET (IP_HDR_LEN + IP_HDR_OFFSET)
-#define UDP_HDR_LEN 8
-#define UDP_DATA_OFFSET (UDP_HDR_OFFSET + UDP_HDR_LEN)
-#define ETH_CONFIG_PKT_HDR_LEN UDP_DATA_OFFSET
-
-#define ETH_CONFIG_PKT_HDR_OFFSET (ETH_ETHERNET_HDR_OFFSET + \
- ETH_CONFIG_PKT_HDR_LEN)
+#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
+#define ETHERNET_HDR_LEN 14
+#define WORD_ALIGNMENT_PAD 0
+
+#define ETH_ETHERNET_HDR_OFFSET (MAX_MAC_HDR_LEN + \
+ SUB_MSDU_HEADER_LENGTH + \
+ SNAP_HDR_LEN - \
+ ETHERNET_HDR_LEN + \
+ WORD_ALIGNMENT_PAD)
+
+#define HOST_HDR_OFFSET 4
+#define ETHERNET_HDR_LEN 14
+#define IP_HDR_LEN 20
+#define IP_HDR_OFFSET ETHERNET_HDR_LEN
+#define UDP_HDR_OFFSET (IP_HDR_LEN + IP_HDR_OFFSET)
+#define UDP_HDR_LEN 8
+#define UDP_DATA_OFFSET (UDP_HDR_OFFSET + UDP_HDR_LEN)
+#define ETH_CONFIG_PKT_HDR_LEN UDP_DATA_OFFSET
+
+#define ETH_CONFIG_PKT_HDR_OFFSET (ETH_ETHERNET_HDR_OFFSET + \
+ ETH_CONFIG_PKT_HDR_LEN)
/********************************************
*
@@ -39,117 +38,105 @@
*
********************************************/
-#define BYTE_SWAP(val) ((((val) & 0x000000FF) << 24) + \
- (((val) & 0x0000FF00) << 8) + \
- (((val) & 0x00FF0000) >> 8) + \
- (((val) & 0xFF000000) >> 24))
+#define BYTE_SWAP(val) (((val & 0x000000FF) << 24) + \
+ ((val & 0x0000FF00) << 8) + \
+ ((val & 0x00FF0000) >> 8) + \
+ ((val & 0xFF000000) >> 24))
/********************************************
*
* Register Defines
*
********************************************/
-#define WILC_PERIPH_REG_BASE 0x1000
-#define WILC_CHANGING_VIR_IF (0x108c)
-#define WILC_CHIPID (WILC_PERIPH_REG_BASE)
-#define WILC_GLB_RESET_0 (WILC_PERIPH_REG_BASE + 0x400)
-#define WILC_PIN_MUX_0 (WILC_PERIPH_REG_BASE + 0x408)
-#define WILC_HOST_TX_CTRL (WILC_PERIPH_REG_BASE + 0x6c)
-#define WILC_HOST_RX_CTRL_0 (WILC_PERIPH_REG_BASE + 0x70)
-#define WILC_HOST_RX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x74)
-#define WILC_HOST_VMM_CTL (WILC_PERIPH_REG_BASE + 0x78)
-#define WILC_HOST_RX_CTRL (WILC_PERIPH_REG_BASE + 0x80)
-#define WILC_HOST_RX_EXTRA_SIZE (WILC_PERIPH_REG_BASE + 0x84)
-#define WILC_HOST_TX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x88)
-#define WILC_MISC (WILC_PERIPH_REG_BASE + 0x428)
-#define WILC_INTR_REG_BASE (WILC_PERIPH_REG_BASE + 0xa00)
-#define WILC_INTR_ENABLE (WILC_INTR_REG_BASE)
-#define WILC_INTR2_ENABLE (WILC_INTR_REG_BASE + 4)
-
-#define WILC_INTR_POLARITY (WILC_INTR_REG_BASE + 0x10)
-#define WILC_INTR_TYPE (WILC_INTR_REG_BASE + 0x20)
-#define WILC_INTR_CLEAR (WILC_INTR_REG_BASE + 0x30)
-#define WILC_INTR_STATUS (WILC_INTR_REG_BASE + 0x40)
-
-#define WILC_VMM_TBL_SIZE 64
-#define WILC_VMM_TX_TBL_BASE (0x150400)
-#define WILC_VMM_RX_TBL_BASE (0x150500)
-
-#define WILC_VMM_BASE 0x150000
-#define WILC_VMM_CORE_CTL (WILC_VMM_BASE)
-#define WILC_VMM_TBL_CTL (WILC_VMM_BASE + 0x4)
-#define WILC_VMM_TBL_ENTRY (WILC_VMM_BASE + 0x8)
-#define WILC_VMM_TBL0_SIZE (WILC_VMM_BASE + 0xc)
-#define WILC_VMM_TO_HOST_SIZE (WILC_VMM_BASE + 0x10)
-#define WILC_VMM_CORE_CFG (WILC_VMM_BASE + 0x14)
-#define WILC_VMM_TBL_ACTIVE (WILC_VMM_BASE + 040)
-#define WILC_VMM_TBL_STATUS (WILC_VMM_BASE + 0x44)
-
-#define WILC_SPI_REG_BASE 0xe800
-#define WILC_SPI_CTL (WILC_SPI_REG_BASE)
-#define WILC_SPI_MASTER_DMA_ADDR (WILC_SPI_REG_BASE + 0x4)
-#define WILC_SPI_MASTER_DMA_COUNT (WILC_SPI_REG_BASE + 0x8)
-#define WILC_SPI_SLAVE_DMA_ADDR (WILC_SPI_REG_BASE + 0xc)
-#define WILC_SPI_SLAVE_DMA_COUNT (WILC_SPI_REG_BASE + 0x10)
-#define WILC_SPI_TX_MODE (WILC_SPI_REG_BASE + 0x20)
-#define WILC_SPI_PROTOCOL_CONFIG (WILC_SPI_REG_BASE + 0x24)
-#define WILC_SPI_INTR_CTL (WILC_SPI_REG_BASE + 0x2c)
-
-#define WILC_SPI_PROTOCOL_OFFSET (WILC_SPI_PROTOCOL_CONFIG - WILC_SPI_REG_BASE)
-
-#define WILC_AHB_DATA_MEM_BASE 0x30000
-#define WILC_AHB_SHARE_MEM_BASE 0xd0000
-
-#define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE
-#define WILC_VMM_TBL_RX_SHADOW_SIZE (256)
-
-#define WILC_GP_REG_0 0x149c
-#define WILC_GP_REG_1 0x14a0
-
-#define rHAVE_SDIO_IRQ_GPIO_BIT (0)
-#define rHAVE_USE_PMU_BIT (1)
-#define rHAVE_SLEEP_CLK_SRC_RTC_BIT (2)
-#define rHAVE_SLEEP_CLK_SRC_XO_BIT (3)
-#define rHAVE_EXT_PA_INV_TX_RX_BIT (4)
-#define rHAVE_LEGACY_RF_SETTINGS_BIT (5)
-#define rHAVE_XTAL_24_BIT (6)
-#define rHAVE_DISABLE_WILC_UART_BIT (7)
-
-
-#define WILC_HAVE_SDIO_IRQ_GPIO (1 << rHAVE_SDIO_IRQ_GPIO_BIT)
-#define WILC_HAVE_USE_PMU (1 << rHAVE_USE_PMU_BIT)
-#define WILC_HAVE_SLEEP_CLK_SRC_RTC (1 << rHAVE_SLEEP_CLK_SRC_RTC_BIT)
-#define WILC_HAVE_SLEEP_CLK_SRC_XO (1 << rHAVE_SLEEP_CLK_SRC_XO_BIT)
-#define WILC_HAVE_EXT_PA_INV_TX_RX (1 << rHAVE_EXT_PA_INV_TX_RX_BIT)
-#define WILC_HAVE_LEGACY_RF_SETTINGS (1 << rHAVE_LEGACY_RF_SETTINGS_BIT)
-#define WILC_HAVE_XTAL_24 (1 << rHAVE_XTAL_24_BIT)
-#define WILC_HAVE_DISABLE_WILC_UART (1 << rHAVE_DISABLE_WILC_UART_BIT)
-
+#define WILC_PERIPH_REG_BASE 0x1000
+#define WILC_CHANGING_VIR_IF 0x108c
+#define WILC_CHIPID WILC_PERIPH_REG_BASE
+#define WILC_GLB_RESET_0 (WILC_PERIPH_REG_BASE + 0x400)
+#define WILC_PIN_MUX_0 (WILC_PERIPH_REG_BASE + 0x408)
+#define WILC_HOST_TX_CTRL (WILC_PERIPH_REG_BASE + 0x6c)
+#define WILC_HOST_RX_CTRL_0 (WILC_PERIPH_REG_BASE + 0x70)
+#define WILC_HOST_RX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x74)
+#define WILC_HOST_VMM_CTL (WILC_PERIPH_REG_BASE + 0x78)
+#define WILC_HOST_RX_CTRL (WILC_PERIPH_REG_BASE + 0x80)
+#define WILC_HOST_RX_EXTRA_SIZE (WILC_PERIPH_REG_BASE + 0x84)
+#define WILC_HOST_TX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x88)
+#define WILC_MISC (WILC_PERIPH_REG_BASE + 0x428)
+#define WILC_INTR_REG_BASE (WILC_PERIPH_REG_BASE + 0xa00)
+#define WILC_INTR_ENABLE WILC_INTR_REG_BASE
+#define WILC_INTR2_ENABLE (WILC_INTR_REG_BASE + 4)
+
+#define WILC_INTR_POLARITY (WILC_INTR_REG_BASE + 0x10)
+#define WILC_INTR_TYPE (WILC_INTR_REG_BASE + 0x20)
+#define WILC_INTR_CLEAR (WILC_INTR_REG_BASE + 0x30)
+#define WILC_INTR_STATUS (WILC_INTR_REG_BASE + 0x40)
+
+#define WILC_VMM_TBL_SIZE 64
+#define WILC_VMM_TX_TBL_BASE 0x150400
+#define WILC_VMM_RX_TBL_BASE 0x150500
+
+#define WILC_VMM_BASE 0x150000
+#define WILC_VMM_CORE_CTL WILC_VMM_BASE
+#define WILC_VMM_TBL_CTL (WILC_VMM_BASE + 0x4)
+#define WILC_VMM_TBL_ENTRY (WILC_VMM_BASE + 0x8)
+#define WILC_VMM_TBL0_SIZE (WILC_VMM_BASE + 0xc)
+#define WILC_VMM_TO_HOST_SIZE (WILC_VMM_BASE + 0x10)
+#define WILC_VMM_CORE_CFG (WILC_VMM_BASE + 0x14)
+#define WILC_VMM_TBL_ACTIVE (WILC_VMM_BASE + 040)
+#define WILC_VMM_TBL_STATUS (WILC_VMM_BASE + 0x44)
+
+#define WILC_SPI_REG_BASE 0xe800
+#define WILC_SPI_CTL WILC_SPI_REG_BASE
+#define WILC_SPI_MASTER_DMA_ADDR (WILC_SPI_REG_BASE + 0x4)
+#define WILC_SPI_MASTER_DMA_COUNT (WILC_SPI_REG_BASE + 0x8)
+#define WILC_SPI_SLAVE_DMA_ADDR (WILC_SPI_REG_BASE + 0xc)
+#define WILC_SPI_SLAVE_DMA_COUNT (WILC_SPI_REG_BASE + 0x10)
+#define WILC_SPI_TX_MODE (WILC_SPI_REG_BASE + 0x20)
+#define WILC_SPI_PROTOCOL_CONFIG (WILC_SPI_REG_BASE + 0x24)
+#define WILC_SPI_INTR_CTL (WILC_SPI_REG_BASE + 0x2c)
+
+#define WILC_SPI_PROTOCOL_OFFSET (WILC_SPI_PROTOCOL_CONFIG - \
+ WILC_SPI_REG_BASE)
+
+#define WILC_AHB_DATA_MEM_BASE 0x30000
+#define WILC_AHB_SHARE_MEM_BASE 0xd0000
+
+#define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE
+#define WILC_VMM_TBL_RX_SHADOW_SIZE 256
+
+#define WILC_GP_REG_0 0x149c
+#define WILC_GP_REG_1 0x14a0
+
+#define WILC_HAVE_SDIO_IRQ_GPIO BIT(0)
+#define WILC_HAVE_USE_PMU BIT(1)
+#define WILC_HAVE_SLEEP_CLK_SRC_RTC BIT(2)
+#define WILC_HAVE_SLEEP_CLK_SRC_XO BIT(3)
+#define WILC_HAVE_EXT_PA_INV_TX_RX BIT(4)
+#define WILC_HAVE_LEGACY_RF_SETTINGS BIT(5)
+#define WILC_HAVE_XTAL_24 BIT(6)
+#define WILC_HAVE_DISABLE_WILC_UART BIT(7)
/********************************************
*
* Wlan Defines
*
********************************************/
-#define WILC_CFG_PKT 1
-#define WILC_NET_PKT 0
-#define WILC_MGMT_PKT 2
+#define WILC_CFG_PKT 1
+#define WILC_NET_PKT 0
+#define WILC_MGMT_PKT 2
-#define WILC_CFG_SET 1
-#define WILC_CFG_QUERY 0
+#define WILC_CFG_SET 1
+#define WILC_CFG_QUERY 0
-#define WILC_CFG_RSP 1
-#define WILC_CFG_RSP_STATUS 2
-#define WILC_CFG_RSP_SCAN 3
+#define WILC_CFG_RSP 1
+#define WILC_CFG_RSP_STATUS 2
+#define WILC_CFG_RSP_SCAN 3
#ifdef WILC_SDIO
-#define WILC_PLL_TO 4
+#define WILC_PLL_TO 4
#else
-#define WILC_PLL_TO 2
+#define WILC_PLL_TO 2
#endif
-
-
-#define ABORT_INT BIT(31)
+#define ABORT_INT BIT(31)
/*******************************************/
/* E0 and later Interrupt flags. */
@@ -165,15 +152,15 @@
/* 20: INT4 flag */
/* 21: INT5 flag */
/*******************************************/
-#define IRG_FLAGS_OFFSET 16
-#define IRQ_DMA_WD_CNT_MASK ((1ul << IRG_FLAGS_OFFSET) - 1)
-#define INT_0 (1 << (IRG_FLAGS_OFFSET))
-#define INT_1 (1 << (IRG_FLAGS_OFFSET + 1))
-#define INT_2 (1 << (IRG_FLAGS_OFFSET + 2))
-#define INT_3 (1 << (IRG_FLAGS_OFFSET + 3))
-#define INT_4 (1 << (IRG_FLAGS_OFFSET + 4))
-#define INT_5 (1 << (IRG_FLAGS_OFFSET + 5))
-#define MAX_NUM_INT (6)
+#define IRG_FLAGS_OFFSET 16
+#define IRQ_DMA_WD_CNT_MASK ((1ul << IRG_FLAGS_OFFSET) - 1)
+#define INT_0 BIT(IRG_FLAGS_OFFSET)
+#define INT_1 BIT(IRG_FLAGS_OFFSET + 1)
+#define INT_2 BIT(IRG_FLAGS_OFFSET + 2)
+#define INT_3 BIT(IRG_FLAGS_OFFSET + 3)
+#define INT_4 BIT(IRG_FLAGS_OFFSET + 4)
+#define INT_5 BIT(IRG_FLAGS_OFFSET + 5)
+#define MAX_NUM_INT 6
/*******************************************/
/* E0 and later Interrupt flags. */
@@ -188,30 +175,28 @@
/* 7: Select VMM table 2 */
/* 8: Enable VMM */
/*******************************************/
-#define CLR_INT0 BIT(0)
-#define CLR_INT1 BIT(1)
-#define CLR_INT2 BIT(2)
-#define CLR_INT3 BIT(3)
-#define CLR_INT4 BIT(4)
-#define CLR_INT5 BIT(5)
-#define SEL_VMM_TBL0 BIT(6)
-#define SEL_VMM_TBL1 BIT(7)
-#define EN_VMM BIT(8)
-
-#define DATA_INT_EXT INT_0
-#define PLL_INT_EXT INT_1
-#define SLEEP_INT_EXT INT_2
-#define ALL_INT_EXT (DATA_INT_EXT | PLL_INT_EXT | SLEEP_INT_EXT)
-#define NUM_INT_EXT (3)
-
-#define DATA_INT_CLR CLR_INT0
-#define PLL_INT_CLR CLR_INT1
-#define SLEEP_INT_CLR CLR_INT2
-
-#define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM)
-#define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM)
-
-
+#define CLR_INT0 BIT(0)
+#define CLR_INT1 BIT(1)
+#define CLR_INT2 BIT(2)
+#define CLR_INT3 BIT(3)
+#define CLR_INT4 BIT(4)
+#define CLR_INT5 BIT(5)
+#define SEL_VMM_TBL0 BIT(6)
+#define SEL_VMM_TBL1 BIT(7)
+#define EN_VMM BIT(8)
+
+#define DATA_INT_EXT INT_0
+#define PLL_INT_EXT INT_1
+#define SLEEP_INT_EXT INT_2
+#define ALL_INT_EXT (DATA_INT_EXT | PLL_INT_EXT | SLEEP_INT_EXT)
+#define NUM_INT_EXT 3
+
+#define DATA_INT_CLR CLR_INT0
+#define PLL_INT_CLR CLR_INT1
+#define SLEEP_INT_CLR CLR_INT2
+
+#define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM)
+#define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM)
/*time for expiring the semaphores of cfg packets*/
#define CFG_PKTS_TIMEOUT 2000
/********************************************
@@ -231,7 +216,7 @@ struct txq_entry_t {
struct txq_entry_t *next;
struct txq_entry_t *prev;
int type;
- int tcp_PendingAck_index;
+ int index;
u8 *buffer;
int buffer_size;
void *priv;
@@ -250,9 +235,9 @@ struct rxq_entry_t {
* Host IF Structure
*
********************************************/
-
-typedef struct {
- int (*hif_init)(wilc_wlan_inp_t *, wilc_debug_func);
+struct wilc;
+struct wilc_hif_func {
+ int (*hif_init)(struct wilc *, wilc_debug_func);
int (*hif_deinit)(void *);
int (*hif_read_reg)(u32, u32 *);
int (*hif_write_reg)(u32, u32);
@@ -268,7 +253,7 @@ typedef struct {
int (*hif_sync_ext)(int);
void (*hif_set_max_bus_speed)(void);
void (*hif_set_default_bus_speed)(void);
-} wilc_hif_func_t;
+};
/********************************************
*
@@ -276,37 +261,34 @@ typedef struct {
*
********************************************/
-#define MAX_CFG_FRAME_SIZE 1468
+#define MAX_CFG_FRAME_SIZE 1468
-typedef struct {
+struct wilc_cfg_frame {
u8 ether_header[14];
u8 ip_header[20];
u8 udp_header[8];
u8 wid_header[8];
u8 frame[MAX_CFG_FRAME_SIZE];
-} wilc_cfg_frame_t;
-
-typedef struct {
- int (*wlan_tx)(u8 *, u32, wilc_tx_complete_func_t);
-} wilc_wlan_cfg_func_t;
+};
-typedef struct {
+struct wilc_cfg_rsp {
int type;
u32 seq_no;
-} wilc_cfg_rsp_t;
+};
int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size);
int wilc_wlan_start(void);
int wilc_wlan_stop(void);
-int wilc_wlan_txq_add_net_pkt(void *priv, u8 *buffer, u32 buffer_size,
- wilc_tx_complete_func_t func);
-int wilc_wlan_handle_txq(u32 *pu32TxqCount);
-void wilc_handle_isr(void);
-void wilc_wlan_cleanup(void);
+int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
+ u32 buffer_size, wilc_tx_complete_func_t func);
+int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count);
+void wilc_handle_isr(void *wilc);
+void wilc_wlan_cleanup(struct net_device *dev);
int wilc_wlan_cfg_set(int start, u32 wid, u8 *buffer, u32 buffer_size,
- int commit, u32 drvHandler);
-int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drvHandler);
+ int commit, u32 drv_handler);
+int wilc_wlan_cfg_get(int start, u32 wid, int commit, u32 drv_handler);
int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size);
-int wilc_wlan_txq_add_mgmt_pkt(void *priv, u8 *buffer, u32 buffer_size,
- wilc_tx_complete_func_t func);
+int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
+ u32 buffer_size, wilc_tx_complete_func_t func);
+void chip_sleep_manually(void);
#endif
diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c
index a34a81cdeb5e..e23796392e9c 100644
--- a/drivers/staging/wilc1000/wilc_wlan_cfg.c
+++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c
@@ -505,7 +505,7 @@ int wilc_wlan_cfg_get_wid_value(u16 wid, u8 *buffer, u32 buffer_size)
return ret;
}
-int wilc_wlan_cfg_indicate_rx(u8 *frame, int size, wilc_cfg_rsp_t *rsp)
+int wilc_wlan_cfg_indicate_rx(u8 *frame, int size, struct wilc_cfg_rsp *rsp)
{
int ret = 1;
u8 msg_type;
diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wilc_wlan_cfg.h
index 30e60ec4d29f..443b2d5b6db8 100644
--- a/drivers/staging/wilc1000/wilc_wlan_cfg.h
+++ b/drivers/staging/wilc1000/wilc_wlan_cfg.h
@@ -33,7 +33,7 @@ typedef struct {
int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size);
int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id);
int wilc_wlan_cfg_get_wid_value(u16 wid, u8 *buffer, u32 buffer_size);
-int wilc_wlan_cfg_indicate_rx(u8 *frame, int size, wilc_cfg_rsp_t *rsp);
+int wilc_wlan_cfg_indicate_rx(u8 *frame, int size, struct wilc_cfg_rsp *rsp);
int wilc_wlan_cfg_init(wilc_debug_func func);
#endif
diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h
index be972afe6e62..5980ece49daa 100644
--- a/drivers/staging/wilc1000/wilc_wlan_if.h
+++ b/drivers/staging/wilc1000/wilc_wlan_if.h
@@ -12,6 +12,7 @@
#include <linux/semaphore.h>
#include "linux_wlan_common.h"
+#include <linux/netdevice.h>
/********************************************
*
@@ -73,22 +74,6 @@ typedef struct {
typedef struct {
int io_type;
- int (*io_init)(void *);
- void (*io_deinit)(void *);
- union {
- struct {
- int (*sdio_cmd52)(sdio_cmd52_t *);
- int (*sdio_cmd53)(sdio_cmd53_t *);
- int (*sdio_set_max_speed)(void);
- int (*sdio_set_default_speed)(void);
- } sdio;
- struct {
- int (*spi_max_speed)(void);
- int (*spi_tx)(u8 *, u32);
- int (*spi_rx)(u8 *, u32);
- int (*spi_trx)(u8 *, u8 *, u32);
- } spi;
- } u;
} wilc_wlan_io_func_t;
#define WILC_MAC_INDICATE_STATUS 0x1
@@ -99,11 +84,6 @@ typedef struct {
#define WILC_MAC_INDICATE_SCAN 0x2
typedef struct {
- void *os_private;
-} wilc_wlan_os_context_t;
-
-typedef struct {
- wilc_wlan_os_context_t os_context;
wilc_wlan_io_func_t io_func;
} wilc_wlan_inp_t;
@@ -315,7 +295,7 @@ typedef enum {
SW_TRIGGER_ABORT,
} TX_ABORT_OPTION_T;
-enum WID_TYPE {
+enum wid_type {
WID_CHAR = 0,
WID_SHORT = 1,
WID_INT = 2,
@@ -937,7 +917,7 @@ typedef enum {
WID_MAX = 0xFFFF
} WID_T;
-int wilc_wlan_init(wilc_wlan_inp_t *inp);
+int wilc_wlan_init(struct net_device *dev, wilc_wlan_inp_t *inp);
void wilc_bus_set_max_speed(void);
void wilc_bus_set_default_speed(void);
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index 342e2b30c48f..8c1e3f06a215 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -2,7 +2,6 @@
#include "hfa384x.h"
#include "prism2mgmt.h"
-
/* Prism2 channel/frequency/bitrate declarations */
static const struct ieee80211_channel prism2_channels[] = {
{ .center_freq = 2412 },
@@ -34,7 +33,6 @@ static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = {
WLAN_CIPHER_SUITE_WEP104
};
-
/* prism2 device private data */
struct prism2_wiphy_private {
wlandevice_t *wlandev;
@@ -48,7 +46,6 @@ struct prism2_wiphy_private {
static const void * const prism2_wiphy_privid = &prism2_wiphy_privid;
-
/* Helper Functions */
static int prism2_result2err(int prism2_result)
{
@@ -100,7 +97,6 @@ static int prism2_domibset_pstr32(wlandevice_t *wlandev,
return p80211req_dorequest(wlandev, (u8 *) &msg);
}
-
/* The interface functions, called by the cfg80211 layer */
static int prism2_change_virtual_intf(struct wiphy *wiphy,
struct net_device *dev,
@@ -298,7 +294,6 @@ static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
return err;
}
-
static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
const u8 *mac, struct station_info *sinfo)
{
@@ -322,7 +317,6 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality);
-
if (result == 0) {
sinfo->txrate.legacy = quality.txrate.data;
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
@@ -623,7 +617,6 @@ static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
int result;
int err = 0;
-
/* Do a join, with a bogus ssid. Thats the only way I can think of */
msg_join.msgcode = DIDmsg_lnxreq_autojoin;
@@ -638,7 +631,6 @@ static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
return err;
}
-
static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
@@ -650,7 +642,6 @@ static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
return -EOPNOTSUPP;
}
-
static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
@@ -706,9 +697,6 @@ exit:
return err;
}
-
-
-
/* Interface callback functions, passing data back up to the cfg80211 layer */
void prism2_connect_result(wlandevice_t *wlandev, u8 failed)
{
@@ -731,7 +719,6 @@ void prism2_roamed(wlandevice_t *wlandev)
NULL, 0, NULL, 0, GFP_KERNEL);
}
-
/* Structures for declaring wiphy interface */
static const struct cfg80211_ops prism2_usb_cfg_ops = {
.change_virtual_intf = prism2_change_virtual_intf,
@@ -750,7 +737,6 @@ static const struct cfg80211_ops prism2_usb_cfg_ops = {
.get_tx_power = prism2_get_tx_power,
};
-
/* Functions to create/free wiphy interface */
static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev)
{
@@ -788,7 +774,6 @@ static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev
return wiphy;
}
-
static void wlan_free_wiphy(struct wiphy *wiphy)
{
wiphy_unregister(wiphy);
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index 444ebed7313a..7551ac25d89d 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -177,9 +177,6 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb);
static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);
-static void
-hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout);
-
static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin,
int urb_status);
@@ -3504,7 +3501,7 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb)
rxmeta->signal = usbin->rxfrm.desc.signal - hw->dbmadjust;
rxmeta->noise = usbin->rxfrm.desc.silence - hw->dbmadjust;
- prism2sta_ev_rx(wlandev, skb);
+ p80211netdev_rx(wlandev, skb);
break;
@@ -3628,7 +3625,7 @@ static void hfa384x_int_rxmonitor(wlandevice_t *wlandev,
}
/* pass it back up */
- prism2sta_ev_rx(wlandev, skb);
+ p80211netdev_rx(wlandev, skb);
}
/*----------------------------------------------------------------
@@ -3674,7 +3671,6 @@ static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin)
static void hfa384x_usbout_callback(struct urb *urb)
{
wlandevice_t *wlandev = urb->context;
- hfa384x_usbout_t *usbout = urb->transfer_buffer;
#ifdef DEBUG_USB
dbprint_urb(urb);
@@ -3683,7 +3679,7 @@ static void hfa384x_usbout_callback(struct urb *urb)
if (wlandev && wlandev->netdev) {
switch (urb->status) {
case 0:
- hfa384x_usbout_tx(wlandev, usbout);
+ prism2sta_ev_alloc(wlandev);
break;
case -EPIPE:
@@ -4038,30 +4034,6 @@ static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx)
}
/*----------------------------------------------------------------
-* hfa384x_usbout_tx
-*
-* At this point we have finished a send of a frame. Mark the URB
-* as available and call ev_alloc to notify higher layers we're
-* ready for more.
-*
-* Arguments:
-* wlandev wlan device
-* usbout ptr to the usb transfer buffer
-*
-* Returns:
-* nothing
-*
-* Side effects:
-*
-* Call context:
-* interrupt
-----------------------------------------------------------------*/
-static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout)
-{
- prism2sta_ev_alloc(wlandev);
-}
-
-/*----------------------------------------------------------------
* hfa384x_isgood_pdrcore
*
* Quick check of PDR codes.
diff --git a/drivers/staging/wlan-ng/p80211meta.h b/drivers/staging/wlan-ng/p80211meta.h
deleted file mode 100644
index c5f1a63add97..000000000000
--- a/drivers/staging/wlan-ng/p80211meta.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* p80211meta.h
-*
-* Macros, constants, types, and funcs for p80211 metadata
-*
-* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
-* --------------------------------------------------------------------
-*
-* linux-wlan
-*
-* The contents of this file are subject to the Mozilla Public
-* License Version 1.1 (the "License"); you may not use this file
-* except in compliance with the License. You may obtain a copy of
-* the License at http://www.mozilla.org/MPL/
-*
-* Software distributed under the License is distributed on an "AS
-* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-* implied. See the License for the specific language governing
-* rights and limitations under the License.
-*
-* Alternatively, the contents of this file may be used under the
-* terms of the GNU Public License version 2 (the "GPL"), in which
-* case the provisions of the GPL are applicable instead of the
-* above. If you wish to allow the use of your version of this file
-* only under the terms of the GPL and not to allow others to use
-* your version of this file under the MPL, indicate your decision
-* by deleting the provisions above and replace them with the notice
-* and other provisions required by the GPL. If you do not delete
-* the provisions above, a recipient may use your version of this
-* file under either the MPL or the GPL.
-*
-* --------------------------------------------------------------------
-*
-* Inquiries regarding the linux-wlan Open Source project can be
-* made directly to:
-*
-* AbsoluteValue Systems Inc.
-* info@linux-wlan.com
-* http://www.linux-wlan.com
-*
-* --------------------------------------------------------------------
-*
-* Portions of the development of this software were funded by
-* Intersil Corporation as part of PRISM(R) chipset product development.
-*
-* --------------------------------------------------------------------
-*
-* This file declares some of the constants and types used in various
-* parts of the linux-wlan system.
-*
-* Notes:
-* - Constant values are always in HOST byte order.
-*
-* All functions and statics declared here are implemented in p80211types.c
-* --------------------------------------------------------------------
-*/
-
-#ifndef _P80211META_H
-#define _P80211META_H
-
-/*----------------------------------------------------------------*/
-/* The following structure types are used for the metadata */
-/* representation of category list metadata, group list metadata, */
-/* and data item metadata for both Mib and Messages. */
-
-struct p80211meta {
- char *name; /* data item name */
- u32 did; /* partial did */
- u32 flags; /* set of various flag bits */
- u32 min; /* min value of a BOUNDEDint */
- u32 max; /* max value of a BOUNDEDint */
-
- u32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */
- u32 minlen; /* minlen of a OCTETSTR or DISPLAYSTR */
- p80211enum_t *enumptr; /* ptr to the enum type for ENUMint */
- p80211_totext_t totextptr; /* ptr to totext conversion function */
- p80211_fromtext_t fromtextptr; /* ptr to totext conversion function */
- p80211_valid_t validfunptr; /* ptr to totext conversion function */
-};
-
-struct grplistitem {
- char *name;
- struct p80211meta *itemlist;
-};
-
-struct catlistitem {
- char *name;
- struct grplistitem *grplist;
-};
-
-#endif /* _P80211META_H */
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
index c547e1cb4c0d..810ee68aa18e 100644
--- a/drivers/staging/wlan-ng/p80211netdev.h
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -141,7 +141,6 @@ typedef struct p80211_frmrx_t {
struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev);
/* wireless extensions' ioctls */
extern struct iw_handler_def p80211wext_handler_def;
-int p80211wext_event_associated(struct wlandevice *wlandev, int assoc);
/* WEP stuff */
#define NUM_WEPKEYS 4
diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h
index 16f123959104..7a9f424607b7 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.h
+++ b/drivers/staging/wlan-ng/prism2mgmt.h
@@ -68,7 +68,6 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate);
void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status);
void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status);
-void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
void prism2sta_ev_alloc(wlandevice_t *wlandev);
int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp);
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index b4a15ef3a405..cdda07d1c268 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -660,7 +660,6 @@ static int prism2mib_fragmentationthreshold(struct mibrec *mib,
struct p80211msg_dot11req_mibset *msg,
void *data)
{
- int result;
u32 *uint32 = (u32 *) data;
if (!isget)
@@ -672,9 +671,7 @@ static int prism2mib_fragmentationthreshold(struct mibrec *mib,
return 0;
}
- result = prism2mib_uint32(mib, isget, wlandev, hw, msg, data);
-
- return result;
+ return prism2mib_uint32(mib, isget, wlandev, hw, msg, data);
}
/*----------------------------------------------------------------
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index c57f48a1d8df..131223afd918 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -1837,27 +1837,6 @@ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status)
}
/*
- * prism2sta_ev_rx
- *
- * Handles the Rx event.
- *
- * Arguments:
- * wlandev wlan device structure
- *
- * Returns:
- * nothing
- *
- * Side effects:
- *
- * Call context:
- * interrupt
- */
-void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb)
-{
- p80211netdev_rx(wlandev, skb);
-}
-
-/*
* prism2sta_ev_alloc
*
* Handles the Alloc event.
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
index e92bbc12bb06..8abf3f87a2d5 100644
--- a/drivers/staging/wlan-ng/prism2usb.c
+++ b/drivers/staging/wlan-ng/prism2usb.c
@@ -6,7 +6,7 @@
#define PRISM_DEV(vid, pid, name) \
{ USB_DEVICE(vid, pid), \
- .driver_info = (unsigned long) name }
+ .driver_info = (unsigned long)name }
static struct usb_device_id usb_prism_tbl[] = {
PRISM_DEV(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS"),
@@ -136,7 +136,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface)
{
wlandevice_t *wlandev;
- wlandev = (wlandevice_t *) usb_get_intfdata(interface);
+ wlandev = (wlandevice_t *)usb_get_intfdata(interface);
if (wlandev != NULL) {
LIST_HEAD(cleanlist);
struct list_head *entry;
@@ -229,7 +229,7 @@ static int prism2sta_suspend(struct usb_interface *interface,
hfa384x_t *hw = NULL;
wlandevice_t *wlandev;
- wlandev = (wlandevice_t *) usb_get_intfdata(interface);
+ wlandev = (wlandevice_t *)usb_get_intfdata(interface);
if (!wlandev)
return -ENODEV;
@@ -252,7 +252,7 @@ static int prism2sta_resume(struct usb_interface *interface)
hfa384x_t *hw = NULL;
wlandevice_t *wlandev;
- wlandev = (wlandevice_t *) usb_get_intfdata(interface);
+ wlandev = (wlandevice_t *)usb_get_intfdata(interface);
if (!wlandev)
return -ENODEV;
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 5a6251a45112..89f5b55ed546 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -1548,7 +1548,7 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
}
}
-static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
+static bool XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
{
u8 vb_chipid;
@@ -1562,9 +1562,9 @@ static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
break;
default:
xgifb_info->hasVB = HASVB_NONE;
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 2b233af8eb80..879a7e6751ac 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -51,7 +51,7 @@ XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
} else if (HwDeviceExtension->jChipType == XG21) {
/* Independent GPIO control */
xgifb_reg_and(pVBInfo->P3d4, 0xB4, ~0x02);
- udelay(800);
+ 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);
@@ -80,20 +80,20 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
xgifb_reg_set(P3c4, 0x16, 0x00);
xgifb_reg_set(P3c4, 0x16, 0x80);
- mdelay(3);
+ 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);
- udelay(60);
+ 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);
- mdelay(1);
+ usleep_range(1, 1001);
xgifb_reg_set(P3c4, 0x1B, 0x03);
- udelay(500);
+ 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);
@@ -136,66 +136,65 @@ static void XGINew_DDRII_Bootup_XG27(
/* Set Double Frequency */
xgifb_reg_set(P3d4, 0x97, pVBInfo->XGINew_CR97); /* CR97 */
- udelay(200);
+ 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 */
- udelay(15);
+ usleep_range(15, 1015);
xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- udelay(15);
+ 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 */
- udelay(15);
+ usleep_range(15, 1015);
xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- udelay(15);
+ 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 */
- udelay(30);
+ usleep_range(30, 1030);
xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- udelay(15);
+ 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 */
- udelay(30);
+ 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 */
- udelay(60);
+ 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 */
- udelay(30);
+ usleep_range(30, 1030);
xgifb_reg_set(P3c4, 0x16, 0x83); /* Set SR16 */
- udelay(15);
+ 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 */
- udelay(30);
+ usleep_range(30, 1030);
xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- udelay(15);
+ 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 */
- udelay(30);
+ usleep_range(30, 1030);
xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- udelay(15);
+ usleep_range(15, 1015);
/* Set SR1B refresh control 000:close; 010:open */
xgifb_reg_set(P3c4, 0x1B, 0x04);
- udelay(200);
-
+ usleep_range(200, 1200);
}
static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
@@ -208,7 +207,7 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(P3d4, 0x97, 0x11); /* CR97 */
- udelay(200);
+ usleep_range(200, 1200);
xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS2 */
xgifb_reg_set(P3c4, 0x19, 0x80);
xgifb_reg_set(P3c4, 0x16, 0x05);
@@ -229,18 +228,18 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(P3c4, 0x16, 0x05);
xgifb_reg_set(P3c4, 0x16, 0x85);
- udelay(15);
+ usleep_range(15, 1015);
xgifb_reg_set(P3c4, 0x1B, 0x04); /* SR1B */
- udelay(30);
+ usleep_range(30, 1030);
xgifb_reg_set(P3c4, 0x1B, 0x00); /* SR1B */
- udelay(100);
+ 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);
- udelay(200);
+ usleep_range(200, 1200);
}
static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4,
@@ -250,20 +249,20 @@ static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4,
xgifb_reg_set(P3c4, 0x19, 0x40);
xgifb_reg_set(P3c4, 0x16, 0x00);
xgifb_reg_set(P3c4, 0x16, 0x80);
- udelay(60);
+ 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);
- udelay(60);
+ 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);
- mdelay(1);
+ usleep_range(1, 1001);
xgifb_reg_set(P3c4, 0x1B, 0x03);
- udelay(500);
+ 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);
@@ -499,7 +498,6 @@ static void XGINew_SetDRAMDefaultRegister340(
xgifb_reg_set(P3c4, 0x1B, 0x03); /* SR1B */
}
-
static unsigned short XGINew_SetDRAMSize20Reg(
unsigned short dram_size,
struct vb_device_info *pVBInfo)
@@ -533,7 +531,7 @@ static unsigned short XGINew_SetDRAMSize20Reg(
0x14,
(xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) |
(data & 0xF0));
- udelay(15);
+ usleep_range(15, 1015);
}
return memsize;
}
@@ -552,7 +550,7 @@ static int XGINew_ReadWriteRest(unsigned short StopAddr,
writel(Position, fbaddr + Position);
}
- udelay(500); /* Fix #1759 Memory Size error in Multi-Adapter. */
+ usleep_range(500, 1500); /* Fix #1759 Memory Size error in Multi-Adapter. */
Position = 0;
@@ -597,12 +595,11 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
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);
- udelay(15);
+ usleep_range(15, 1015);
if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
return;
@@ -616,7 +613,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4,
0x14,
0x42);
- udelay(15);
+ usleep_range(15, 1015);
if (XGINew_ReadWriteRest(23,
23,
@@ -631,14 +628,14 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
/* 22bit + 2 rank + 16bit */
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41);
- udelay(15);
+ usleep_range(15, 1015);
if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
return;
xgifb_reg_set(pVBInfo->P3c4,
0x13,
0x31);
- udelay(15);
+ usleep_range(15, 1015);
}
} else { /* Dual_16_8 */
@@ -649,7 +646,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
/* 0x41:16Mx16 bit*/
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41);
- udelay(15);
+ usleep_range(15, 1015);
if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
return;
@@ -664,7 +661,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4,
0x14,
0x31);
- udelay(15);
+ usleep_range(15, 1015);
if (XGINew_ReadWriteRest(22,
22,
@@ -680,7 +677,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
/* 0x30:8Mx8 bit*/
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x30);
- udelay(15);
+ usleep_range(15, 1015);
if (XGINew_ReadWriteRest(22, 21, pVBInfo) == 1)
return;
@@ -689,7 +686,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4,
0x13,
0x31);
- udelay(15);
+ usleep_range(15, 1015);
}
}
break;
@@ -808,7 +805,7 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
for (i = 0; i < size; i++) {
/* SetDRAMSizingType */
xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, dram_table[i][1]);
- udelay(15); /* should delay 50 ns */
+ usleep_range(50, 1050); /* should delay 50 ns */
memsize = XGINew_SetDRAMSize20Reg(dram_table[i][0], pVBInfo);
@@ -817,7 +814,7 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
memsize += (pVBInfo->ram_channel - 2) + 20;
if ((HwDeviceExtension->ulVideoMemorySize - 1) <
- (unsigned long) (1 << memsize))
+ (unsigned long)(1 << memsize))
continue;
if (XGINew_ReadWriteRest(memsize, start_addr, pVBInfo) == 1)
@@ -838,13 +835,13 @@ static void XGINew_SetDRAMSize_340(struct xgifb_video_info *xgifb_info,
data = xgifb_reg_get(pVBInfo->P3c4, 0x21);
/* disable read cache */
- xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data & 0xDF));
+ 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));
+ xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short)(data | 0x20));
}
static u8 *xgifb_copy_rom(struct pci_dev *dev, size_t *rom_size)
@@ -853,11 +850,11 @@ static u8 *xgifb_copy_rom(struct pci_dev *dev, size_t *rom_size)
u8 *rom_copy;
rom_address = pci_map_rom(dev, rom_size);
- if (rom_address == NULL)
+ if (!rom_address)
return NULL;
rom_copy = vzalloc(XGIFB_ROM_SIZE);
- if (rom_copy == NULL)
+ if (!rom_copy)
goto done;
*rom_size = min_t(size_t, *rom_size, XGIFB_ROM_SIZE);
@@ -879,7 +876,7 @@ static bool xgifb_read_vbios(struct pci_dev *pdev)
int entry;
vbios = xgifb_copy_rom(pdev, &vbios_size);
- if (vbios == NULL) {
+ if (!vbios) {
dev_err(&pdev->dev, "Video BIOS not available\n");
return false;
}
@@ -1059,7 +1056,6 @@ static void XGINew_SetModeScratch(struct vb_device_info *pVBInfo)
CR38Data &= ~SetYPbPr;
CR38Data |= tempch;
xgifb_reg_set(pVBInfo->P3d4, 0x38, CR38Data);
-
}
static unsigned short XGINew_SenseLCD(struct xgi_hw_device_info
@@ -1134,7 +1130,6 @@ static void XGINew_GetXG27Sense(struct vb_device_info *pVBInfo)
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)
@@ -1191,7 +1186,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
- if (pVBInfo->FBAddr == NULL) {
+ if (!pVBInfo->FBAddr) {
dev_dbg(&pdev->dev, "pVBInfo->FBAddr == 0\n");
return 0;
}
@@ -1329,14 +1324,12 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
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,
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index c7461d770d3a..255204cc43e6 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -23,8 +23,6 @@
#include <linux/inet.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include <target/iscsi/iscsi_transport.h>
#include <target/iscsi/iscsi_target_core.h>
@@ -37,20 +35,17 @@
#include "iscsi_target.h"
#include <target/iscsi/iscsi_target_stat.h>
-struct lio_target_configfs_attribute {
- struct configfs_attribute attr;
- ssize_t (*show)(void *, char *);
- ssize_t (*store)(void *, const char *, size_t);
-};
/* Start items for lio_target_portal_cit */
-static ssize_t lio_target_np_show_sctp(
- struct se_tpg_np *se_tpg_np,
- char *page)
+static inline struct iscsi_tpg_np *to_iscsi_tpg_np(struct config_item *item)
+{
+ return container_of(to_tpg_np(item), struct iscsi_tpg_np, se_tpg_np);
+}
+
+static ssize_t lio_target_np_sctp_show(struct config_item *item, char *page)
{
- struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
- struct iscsi_tpg_np, se_tpg_np);
+ struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
struct iscsi_tpg_np *tpg_np_sctp;
ssize_t rb;
@@ -63,15 +58,12 @@ static ssize_t lio_target_np_show_sctp(
return rb;
}
-static ssize_t lio_target_np_store_sctp(
- struct se_tpg_np *se_tpg_np,
- const char *page,
- size_t count)
+static ssize_t lio_target_np_sctp_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
struct iscsi_np *np;
struct iscsi_portal_group *tpg;
- struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
- struct iscsi_tpg_np, se_tpg_np);
struct iscsi_tpg_np *tpg_np_sctp = NULL;
u32 op;
int ret;
@@ -119,14 +111,9 @@ out:
return -EINVAL;
}
-TF_NP_BASE_ATTR(lio_target, sctp, S_IRUGO | S_IWUSR);
-
-static ssize_t lio_target_np_show_iser(
- struct se_tpg_np *se_tpg_np,
- char *page)
+static ssize_t lio_target_np_iser_show(struct config_item *item, char *page)
{
- struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
- struct iscsi_tpg_np, se_tpg_np);
+ struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
struct iscsi_tpg_np *tpg_np_iser;
ssize_t rb;
@@ -139,15 +126,12 @@ static ssize_t lio_target_np_show_iser(
return rb;
}
-static ssize_t lio_target_np_store_iser(
- struct se_tpg_np *se_tpg_np,
- const char *page,
- size_t count)
+static ssize_t lio_target_np_iser_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
struct iscsi_np *np;
struct iscsi_portal_group *tpg;
- struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
- struct iscsi_tpg_np, se_tpg_np);
struct iscsi_tpg_np *tpg_np_iser = NULL;
char *endptr;
u32 op;
@@ -198,11 +182,12 @@ out:
return rc;
}
-TF_NP_BASE_ATTR(lio_target, iser, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(lio_target_np_, sctp);
+CONFIGFS_ATTR(lio_target_np_, iser);
static struct configfs_attribute *lio_target_portal_attrs[] = {
- &lio_target_np_sctp.attr,
- &lio_target_np_iser.attr,
+ &lio_target_np_attr_sctp,
+ &lio_target_np_attr_iser,
NULL,
};
@@ -360,22 +345,21 @@ out:
/* Start items for lio_target_nacl_attrib_cit */
-#define DEF_NACL_ATTRIB(name) \
-static ssize_t iscsi_nacl_attrib_show_##name( \
- struct se_node_acl *se_nacl, \
- char *page) \
+#define ISCSI_NACL_ATTR(name) \
+static ssize_t iscsi_nacl_attrib_##name##_show(struct config_item *item,\
+ char *page) \
{ \
+ struct se_node_acl *se_nacl = attrib_to_nacl(item); \
struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
se_node_acl); \
\
return sprintf(page, "%u\n", nacl->node_attrib.name); \
} \
\
-static ssize_t iscsi_nacl_attrib_store_##name( \
- struct se_node_acl *se_nacl, \
- const char *page, \
- size_t count) \
+static ssize_t iscsi_nacl_attrib_##name##_store(struct config_item *item,\
+ const char *page, size_t count) \
{ \
+ struct se_node_acl *se_nacl = attrib_to_nacl(item); \
struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
se_node_acl); \
u32 val; \
@@ -389,59 +373,28 @@ static ssize_t iscsi_nacl_attrib_store_##name( \
return ret; \
\
return count; \
-}
+} \
+ \
+CONFIGFS_ATTR(iscsi_nacl_attrib_, name)
-#define NACL_ATTR(_name, _mode) TF_NACL_ATTRIB_ATTR(iscsi, _name, _mode);
-/*
- * Define iscsi_node_attrib_s_dataout_timeout
- */
-DEF_NACL_ATTRIB(dataout_timeout);
-NACL_ATTR(dataout_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_dataout_timeout_retries
- */
-DEF_NACL_ATTRIB(dataout_timeout_retries);
-NACL_ATTR(dataout_timeout_retries, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_default_erl
- */
-DEF_NACL_ATTRIB(default_erl);
-NACL_ATTR(default_erl, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_nopin_timeout
- */
-DEF_NACL_ATTRIB(nopin_timeout);
-NACL_ATTR(nopin_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_nopin_response_timeout
- */
-DEF_NACL_ATTRIB(nopin_response_timeout);
-NACL_ATTR(nopin_response_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_random_datain_pdu_offsets
- */
-DEF_NACL_ATTRIB(random_datain_pdu_offsets);
-NACL_ATTR(random_datain_pdu_offsets, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_random_datain_seq_offsets
- */
-DEF_NACL_ATTRIB(random_datain_seq_offsets);
-NACL_ATTR(random_datain_seq_offsets, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_random_r2t_offsets
- */
-DEF_NACL_ATTRIB(random_r2t_offsets);
-NACL_ATTR(random_r2t_offsets, S_IRUGO | S_IWUSR);
+ISCSI_NACL_ATTR(dataout_timeout);
+ISCSI_NACL_ATTR(dataout_timeout_retries);
+ISCSI_NACL_ATTR(default_erl);
+ISCSI_NACL_ATTR(nopin_timeout);
+ISCSI_NACL_ATTR(nopin_response_timeout);
+ISCSI_NACL_ATTR(random_datain_pdu_offsets);
+ISCSI_NACL_ATTR(random_datain_seq_offsets);
+ISCSI_NACL_ATTR(random_r2t_offsets);
static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = {
- &iscsi_nacl_attrib_dataout_timeout.attr,
- &iscsi_nacl_attrib_dataout_timeout_retries.attr,
- &iscsi_nacl_attrib_default_erl.attr,
- &iscsi_nacl_attrib_nopin_timeout.attr,
- &iscsi_nacl_attrib_nopin_response_timeout.attr,
- &iscsi_nacl_attrib_random_datain_pdu_offsets.attr,
- &iscsi_nacl_attrib_random_datain_seq_offsets.attr,
- &iscsi_nacl_attrib_random_r2t_offsets.attr,
+ &iscsi_nacl_attrib_attr_dataout_timeout,
+ &iscsi_nacl_attrib_attr_dataout_timeout_retries,
+ &iscsi_nacl_attrib_attr_default_erl,
+ &iscsi_nacl_attrib_attr_nopin_timeout,
+ &iscsi_nacl_attrib_attr_nopin_response_timeout,
+ &iscsi_nacl_attrib_attr_random_datain_pdu_offsets,
+ &iscsi_nacl_attrib_attr_random_datain_seq_offsets,
+ &iscsi_nacl_attrib_attr_random_r2t_offsets,
NULL,
};
@@ -450,7 +403,7 @@ static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = {
/* Start items for lio_target_nacl_auth_cit */
#define __DEF_NACL_AUTH_STR(prefix, name, flags) \
-static ssize_t __iscsi_##prefix##_show_##name( \
+static ssize_t __iscsi_##prefix##_##name##_show( \
struct iscsi_node_acl *nacl, \
char *page) \
{ \
@@ -461,7 +414,7 @@ static ssize_t __iscsi_##prefix##_show_##name( \
return snprintf(page, PAGE_SIZE, "%s\n", auth->name); \
} \
\
-static ssize_t __iscsi_##prefix##_store_##name( \
+static ssize_t __iscsi_##prefix##_##name##_store( \
struct iscsi_node_acl *nacl, \
const char *page, \
size_t count) \
@@ -487,8 +440,35 @@ static ssize_t __iscsi_##prefix##_store_##name( \
return count; \
}
+#define DEF_NACL_AUTH_STR(name, flags) \
+ __DEF_NACL_AUTH_STR(nacl_auth, name, flags) \
+static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct se_node_acl *nacl = auth_to_nacl(item); \
+ return __iscsi_nacl_auth_##name##_show(container_of(nacl, \
+ struct iscsi_node_acl, se_node_acl), page); \
+} \
+static ssize_t iscsi_nacl_auth_##name##_store(struct config_item *item, \
+ const char *page, size_t count) \
+{ \
+ struct se_node_acl *nacl = auth_to_nacl(item); \
+ return __iscsi_nacl_auth_##name##_store(container_of(nacl, \
+ struct iscsi_node_acl, se_node_acl), page, count); \
+} \
+ \
+CONFIGFS_ATTR(iscsi_nacl_auth_, name)
+
+/*
+ * One-way authentication userid
+ */
+DEF_NACL_AUTH_STR(userid, NAF_USERID_SET);
+DEF_NACL_AUTH_STR(password, NAF_PASSWORD_SET);
+DEF_NACL_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DEF_NACL_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
+
#define __DEF_NACL_AUTH_INT(prefix, name) \
-static ssize_t __iscsi_##prefix##_show_##name( \
+static ssize_t __iscsi_##prefix##_##name##_show( \
struct iscsi_node_acl *nacl, \
char *page) \
{ \
@@ -500,69 +480,26 @@ static ssize_t __iscsi_##prefix##_show_##name( \
return snprintf(page, PAGE_SIZE, "%d\n", auth->name); \
}
-#define DEF_NACL_AUTH_STR(name, flags) \
- __DEF_NACL_AUTH_STR(nacl_auth, name, flags) \
-static ssize_t iscsi_nacl_auth_show_##name( \
- struct se_node_acl *nacl, \
- char *page) \
-{ \
- return __iscsi_nacl_auth_show_##name(container_of(nacl, \
- struct iscsi_node_acl, se_node_acl), page); \
-} \
-static ssize_t iscsi_nacl_auth_store_##name( \
- struct se_node_acl *nacl, \
- const char *page, \
- size_t count) \
-{ \
- return __iscsi_nacl_auth_store_##name(container_of(nacl, \
- struct iscsi_node_acl, se_node_acl), page, count); \
-}
-
#define DEF_NACL_AUTH_INT(name) \
__DEF_NACL_AUTH_INT(nacl_auth, name) \
-static ssize_t iscsi_nacl_auth_show_##name( \
- struct se_node_acl *nacl, \
- char *page) \
+static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \
+ char *page) \
{ \
- return __iscsi_nacl_auth_show_##name(container_of(nacl, \
- struct iscsi_node_acl, se_node_acl), page); \
-}
-
-#define AUTH_ATTR(_name, _mode) TF_NACL_AUTH_ATTR(iscsi, _name, _mode);
-#define AUTH_ATTR_RO(_name) TF_NACL_AUTH_ATTR_RO(iscsi, _name);
+ struct se_node_acl *nacl = auth_to_nacl(item); \
+ return __iscsi_nacl_auth_##name##_show(container_of(nacl, \
+ struct iscsi_node_acl, se_node_acl), page); \
+} \
+ \
+CONFIGFS_ATTR_RO(iscsi_nacl_auth_, name)
-/*
- * One-way authentication userid
- */
-DEF_NACL_AUTH_STR(userid, NAF_USERID_SET);
-AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
-/*
- * One-way authentication password
- */
-DEF_NACL_AUTH_STR(password, NAF_PASSWORD_SET);
-AUTH_ATTR(password, S_IRUGO | S_IWUSR);
-/*
- * Enforce mutual authentication
- */
DEF_NACL_AUTH_INT(authenticate_target);
-AUTH_ATTR_RO(authenticate_target);
-/*
- * Mutual authentication userid
- */
-DEF_NACL_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
-AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
-/*
- * Mutual authentication password
- */
-DEF_NACL_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
-AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
static struct configfs_attribute *lio_target_nacl_auth_attrs[] = {
- &iscsi_nacl_auth_userid.attr,
- &iscsi_nacl_auth_password.attr,
- &iscsi_nacl_auth_authenticate_target.attr,
- &iscsi_nacl_auth_userid_mutual.attr,
- &iscsi_nacl_auth_password_mutual.attr,
+ &iscsi_nacl_auth_attr_userid,
+ &iscsi_nacl_auth_attr_password,
+ &iscsi_nacl_auth_attr_authenticate_target,
+ &iscsi_nacl_auth_attr_userid_mutual,
+ &iscsi_nacl_auth_attr_password_mutual,
NULL,
};
@@ -570,11 +507,11 @@ static struct configfs_attribute *lio_target_nacl_auth_attrs[] = {
/* Start items for lio_target_nacl_param_cit */
-#define DEF_NACL_PARAM(name) \
-static ssize_t iscsi_nacl_param_show_##name( \
- struct se_node_acl *se_nacl, \
- char *page) \
+#define ISCSI_NACL_PARAM(name) \
+static ssize_t iscsi_nacl_param_##name##_show(struct config_item *item, \
+ char *page) \
{ \
+ struct se_node_acl *se_nacl = param_to_nacl(item); \
struct iscsi_session *sess; \
struct se_session *se_sess; \
ssize_t rb; \
@@ -592,55 +529,34 @@ static ssize_t iscsi_nacl_param_show_##name( \
spin_unlock_bh(&se_nacl->nacl_sess_lock); \
\
return rb; \
-}
-
-#define NACL_PARAM_ATTR(_name) TF_NACL_PARAM_ATTR_RO(iscsi, _name);
-
-DEF_NACL_PARAM(MaxConnections);
-NACL_PARAM_ATTR(MaxConnections);
-
-DEF_NACL_PARAM(InitialR2T);
-NACL_PARAM_ATTR(InitialR2T);
-
-DEF_NACL_PARAM(ImmediateData);
-NACL_PARAM_ATTR(ImmediateData);
-
-DEF_NACL_PARAM(MaxBurstLength);
-NACL_PARAM_ATTR(MaxBurstLength);
-
-DEF_NACL_PARAM(FirstBurstLength);
-NACL_PARAM_ATTR(FirstBurstLength);
-
-DEF_NACL_PARAM(DefaultTime2Wait);
-NACL_PARAM_ATTR(DefaultTime2Wait);
-
-DEF_NACL_PARAM(DefaultTime2Retain);
-NACL_PARAM_ATTR(DefaultTime2Retain);
-
-DEF_NACL_PARAM(MaxOutstandingR2T);
-NACL_PARAM_ATTR(MaxOutstandingR2T);
-
-DEF_NACL_PARAM(DataPDUInOrder);
-NACL_PARAM_ATTR(DataPDUInOrder);
-
-DEF_NACL_PARAM(DataSequenceInOrder);
-NACL_PARAM_ATTR(DataSequenceInOrder);
-
-DEF_NACL_PARAM(ErrorRecoveryLevel);
-NACL_PARAM_ATTR(ErrorRecoveryLevel);
+} \
+ \
+CONFIGFS_ATTR_RO(iscsi_nacl_param_, name)
+
+ISCSI_NACL_PARAM(MaxConnections);
+ISCSI_NACL_PARAM(InitialR2T);
+ISCSI_NACL_PARAM(ImmediateData);
+ISCSI_NACL_PARAM(MaxBurstLength);
+ISCSI_NACL_PARAM(FirstBurstLength);
+ISCSI_NACL_PARAM(DefaultTime2Wait);
+ISCSI_NACL_PARAM(DefaultTime2Retain);
+ISCSI_NACL_PARAM(MaxOutstandingR2T);
+ISCSI_NACL_PARAM(DataPDUInOrder);
+ISCSI_NACL_PARAM(DataSequenceInOrder);
+ISCSI_NACL_PARAM(ErrorRecoveryLevel);
static struct configfs_attribute *lio_target_nacl_param_attrs[] = {
- &iscsi_nacl_param_MaxConnections.attr,
- &iscsi_nacl_param_InitialR2T.attr,
- &iscsi_nacl_param_ImmediateData.attr,
- &iscsi_nacl_param_MaxBurstLength.attr,
- &iscsi_nacl_param_FirstBurstLength.attr,
- &iscsi_nacl_param_DefaultTime2Wait.attr,
- &iscsi_nacl_param_DefaultTime2Retain.attr,
- &iscsi_nacl_param_MaxOutstandingR2T.attr,
- &iscsi_nacl_param_DataPDUInOrder.attr,
- &iscsi_nacl_param_DataSequenceInOrder.attr,
- &iscsi_nacl_param_ErrorRecoveryLevel.attr,
+ &iscsi_nacl_param_attr_MaxConnections,
+ &iscsi_nacl_param_attr_InitialR2T,
+ &iscsi_nacl_param_attr_ImmediateData,
+ &iscsi_nacl_param_attr_MaxBurstLength,
+ &iscsi_nacl_param_attr_FirstBurstLength,
+ &iscsi_nacl_param_attr_DefaultTime2Wait,
+ &iscsi_nacl_param_attr_DefaultTime2Retain,
+ &iscsi_nacl_param_attr_MaxOutstandingR2T,
+ &iscsi_nacl_param_attr_DataPDUInOrder,
+ &iscsi_nacl_param_attr_DataSequenceInOrder,
+ &iscsi_nacl_param_attr_ErrorRecoveryLevel,
NULL,
};
@@ -648,10 +564,9 @@ static struct configfs_attribute *lio_target_nacl_param_attrs[] = {
/* Start items for lio_target_acl_cit */
-static ssize_t lio_target_nacl_show_info(
- struct se_node_acl *se_nacl,
- char *page)
+static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
struct iscsi_session *sess;
struct iscsi_conn *conn;
struct se_session *se_sess;
@@ -766,20 +681,16 @@ static ssize_t lio_target_nacl_show_info(
return rb;
}
-TF_NACL_BASE_ATTR_RO(lio_target, info);
-
-static ssize_t lio_target_nacl_show_cmdsn_depth(
- struct se_node_acl *se_nacl,
- char *page)
+static ssize_t lio_target_nacl_cmdsn_depth_show(struct config_item *item,
+ char *page)
{
- return sprintf(page, "%u\n", se_nacl->queue_depth);
+ return sprintf(page, "%u\n", acl_to_nacl(item)->queue_depth);
}
-static ssize_t lio_target_nacl_store_cmdsn_depth(
- struct se_node_acl *se_nacl,
- const char *page,
- size_t count)
+static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
struct se_portal_group *se_tpg = se_nacl->se_tpg;
struct iscsi_portal_group *tpg = container_of(se_tpg,
struct iscsi_portal_group, tpg_se_tpg);
@@ -829,20 +740,15 @@ static ssize_t lio_target_nacl_store_cmdsn_depth(
return (!ret) ? count : (ssize_t)ret;
}
-TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR);
-
-static ssize_t lio_target_nacl_show_tag(
- struct se_node_acl *se_nacl,
- char *page)
+static ssize_t lio_target_nacl_tag_show(struct config_item *item, char *page)
{
- return snprintf(page, PAGE_SIZE, "%s", se_nacl->acl_tag);
+ return snprintf(page, PAGE_SIZE, "%s", acl_to_nacl(item)->acl_tag);
}
-static ssize_t lio_target_nacl_store_tag(
- struct se_node_acl *se_nacl,
- const char *page,
- size_t count)
+static ssize_t lio_target_nacl_tag_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
int ret;
ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page);
@@ -852,12 +758,14 @@ static ssize_t lio_target_nacl_store_tag(
return count;
}
-TF_NACL_BASE_ATTR(lio_target, tag, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR_RO(lio_target_nacl_, info);
+CONFIGFS_ATTR(lio_target_nacl_, cmdsn_depth);
+CONFIGFS_ATTR(lio_target_nacl_, tag);
static struct configfs_attribute *lio_target_initiator_attrs[] = {
- &lio_target_nacl_info.attr,
- &lio_target_nacl_cmdsn_depth.attr,
- &lio_target_nacl_tag.attr,
+ &lio_target_nacl_attr_info,
+ &lio_target_nacl_attr_cmdsn_depth,
+ &lio_target_nacl_attr_tag,
NULL,
};
@@ -907,10 +815,10 @@ static void lio_target_cleanup_nodeacl( struct se_node_acl *se_nacl)
#define DEF_TPG_ATTRIB(name) \
\
-static ssize_t iscsi_tpg_attrib_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
+static ssize_t iscsi_tpg_attrib_##name##_show(struct config_item *item, \
+ char *page) \
{ \
+ struct se_portal_group *se_tpg = attrib_to_tpg(item); \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
ssize_t rb; \
@@ -923,11 +831,10 @@ static ssize_t iscsi_tpg_attrib_show_##name( \
return rb; \
} \
\
-static ssize_t iscsi_tpg_attrib_store_##name( \
- struct se_portal_group *se_tpg, \
- const char *page, \
- size_t count) \
+static ssize_t iscsi_tpg_attrib_##name##_store(struct config_item *item,\
+ const char *page, size_t count) \
{ \
+ struct se_portal_group *se_tpg = attrib_to_tpg(item); \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
u32 val; \
@@ -948,90 +855,37 @@ static ssize_t iscsi_tpg_attrib_store_##name( \
out: \
iscsit_put_tpg(tpg); \
return ret; \
-}
-
-#define TPG_ATTR(_name, _mode) TF_TPG_ATTRIB_ATTR(iscsi, _name, _mode);
+} \
+CONFIGFS_ATTR(iscsi_tpg_attrib_, name)
-/*
- * Define iscsi_tpg_attrib_s_authentication
- */
DEF_TPG_ATTRIB(authentication);
-TPG_ATTR(authentication, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_login_timeout
- */
DEF_TPG_ATTRIB(login_timeout);
-TPG_ATTR(login_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_netif_timeout
- */
DEF_TPG_ATTRIB(netif_timeout);
-TPG_ATTR(netif_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_generate_node_acls
- */
DEF_TPG_ATTRIB(generate_node_acls);
-TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_default_cmdsn_depth
- */
DEF_TPG_ATTRIB(default_cmdsn_depth);
-TPG_ATTR(default_cmdsn_depth, S_IRUGO | S_IWUSR);
-/*
- Define iscsi_tpg_attrib_s_cache_dynamic_acls
- */
DEF_TPG_ATTRIB(cache_dynamic_acls);
-TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_demo_mode_write_protect
- */
DEF_TPG_ATTRIB(demo_mode_write_protect);
-TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_prod_mode_write_protect
- */
DEF_TPG_ATTRIB(prod_mode_write_protect);
-TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_demo_mode_discovery,
- */
DEF_TPG_ATTRIB(demo_mode_discovery);
-TPG_ATTR(demo_mode_discovery, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_default_erl
- */
DEF_TPG_ATTRIB(default_erl);
-TPG_ATTR(default_erl, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_t10_pi
- */
DEF_TPG_ATTRIB(t10_pi);
-TPG_ATTR(t10_pi, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_fabric_prot_type
- */
DEF_TPG_ATTRIB(fabric_prot_type);
-TPG_ATTR(fabric_prot_type, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_tpg_enabled_sendtargets
- */
DEF_TPG_ATTRIB(tpg_enabled_sendtargets);
-TPG_ATTR(tpg_enabled_sendtargets, S_IRUGO | S_IWUSR);
static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
- &iscsi_tpg_attrib_authentication.attr,
- &iscsi_tpg_attrib_login_timeout.attr,
- &iscsi_tpg_attrib_netif_timeout.attr,
- &iscsi_tpg_attrib_generate_node_acls.attr,
- &iscsi_tpg_attrib_default_cmdsn_depth.attr,
- &iscsi_tpg_attrib_cache_dynamic_acls.attr,
- &iscsi_tpg_attrib_demo_mode_write_protect.attr,
- &iscsi_tpg_attrib_prod_mode_write_protect.attr,
- &iscsi_tpg_attrib_demo_mode_discovery.attr,
- &iscsi_tpg_attrib_default_erl.attr,
- &iscsi_tpg_attrib_t10_pi.attr,
- &iscsi_tpg_attrib_fabric_prot_type.attr,
- &iscsi_tpg_attrib_tpg_enabled_sendtargets.attr,
+ &iscsi_tpg_attrib_attr_authentication,
+ &iscsi_tpg_attrib_attr_login_timeout,
+ &iscsi_tpg_attrib_attr_netif_timeout,
+ &iscsi_tpg_attrib_attr_generate_node_acls,
+ &iscsi_tpg_attrib_attr_default_cmdsn_depth,
+ &iscsi_tpg_attrib_attr_cache_dynamic_acls,
+ &iscsi_tpg_attrib_attr_demo_mode_write_protect,
+ &iscsi_tpg_attrib_attr_prod_mode_write_protect,
+ &iscsi_tpg_attrib_attr_demo_mode_discovery,
+ &iscsi_tpg_attrib_attr_default_erl,
+ &iscsi_tpg_attrib_attr_t10_pi,
+ &iscsi_tpg_attrib_attr_fabric_prot_type,
+ &iscsi_tpg_attrib_attr_tpg_enabled_sendtargets,
NULL,
};
@@ -1040,9 +894,8 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
/* Start items for lio_target_tpg_auth_cit */
#define __DEF_TPG_AUTH_STR(prefix, name, flags) \
-static ssize_t __iscsi_##prefix##_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
+static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, \
+ char *page) \
{ \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
@@ -1054,10 +907,8 @@ static ssize_t __iscsi_##prefix##_show_##name( \
return snprintf(page, PAGE_SIZE, "%s\n", auth->name); \
} \
\
-static ssize_t __iscsi_##prefix##_store_##name( \
- struct se_portal_group *se_tpg, \
- const char *page, \
- size_t count) \
+static ssize_t __iscsi_##prefix##_##name##_store(struct se_portal_group *se_tpg,\
+ const char *page, size_t count) \
{ \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
@@ -1081,10 +932,31 @@ static ssize_t __iscsi_##prefix##_store_##name( \
return count; \
}
+#define DEF_TPG_AUTH_STR(name, flags) \
+ __DEF_TPG_AUTH_STR(tpg_auth, name, flags) \
+static ssize_t iscsi_tpg_auth_##name##_show(struct config_item *item, \
+ char *page) \
+{ \
+ return __iscsi_tpg_auth_##name##_show(auth_to_tpg(item), page); \
+} \
+ \
+static ssize_t iscsi_tpg_auth_##name##_store(struct config_item *item, \
+ const char *page, size_t count) \
+{ \
+ return __iscsi_tpg_auth_##name##_store(auth_to_tpg(item), page, count); \
+} \
+ \
+CONFIGFS_ATTR(iscsi_tpg_auth_, name);
+
+
+DEF_TPG_AUTH_STR(userid, NAF_USERID_SET);
+DEF_TPG_AUTH_STR(password, NAF_PASSWORD_SET);
+DEF_TPG_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
+
#define __DEF_TPG_AUTH_INT(prefix, name) \
-static ssize_t __iscsi_##prefix##_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
+static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, \
+ char *page) \
{ \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
@@ -1096,67 +968,23 @@ static ssize_t __iscsi_##prefix##_show_##name( \
return snprintf(page, PAGE_SIZE, "%d\n", auth->name); \
}
-#define DEF_TPG_AUTH_STR(name, flags) \
- __DEF_TPG_AUTH_STR(tpg_auth, name, flags) \
-static ssize_t iscsi_tpg_auth_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
-{ \
- return __iscsi_tpg_auth_show_##name(se_tpg, page); \
-} \
- \
-static ssize_t iscsi_tpg_auth_store_##name( \
- struct se_portal_group *se_tpg, \
- const char *page, \
- size_t count) \
-{ \
- return __iscsi_tpg_auth_store_##name(se_tpg, page, count); \
-}
-
#define DEF_TPG_AUTH_INT(name) \
__DEF_TPG_AUTH_INT(tpg_auth, name) \
-static ssize_t iscsi_tpg_auth_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
+static ssize_t iscsi_tpg_auth_##name##_show(struct config_item *item, \
+ char *page) \
{ \
- return __iscsi_tpg_auth_show_##name(se_tpg, page); \
-}
-
-#define TPG_AUTH_ATTR(_name, _mode) TF_TPG_AUTH_ATTR(iscsi, _name, _mode);
-#define TPG_AUTH_ATTR_RO(_name) TF_TPG_AUTH_ATTR_RO(iscsi, _name);
+ return __iscsi_tpg_auth_##name##_show(auth_to_tpg(item), page); \
+} \
+CONFIGFS_ATTR_RO(iscsi_tpg_auth_, name);
-/*
- * * One-way authentication userid
- * */
-DEF_TPG_AUTH_STR(userid, NAF_USERID_SET);
-TPG_AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
-/*
- * * One-way authentication password
- * */
-DEF_TPG_AUTH_STR(password, NAF_PASSWORD_SET);
-TPG_AUTH_ATTR(password, S_IRUGO | S_IWUSR);
-/*
- * * Enforce mutual authentication
- * */
DEF_TPG_AUTH_INT(authenticate_target);
-TPG_AUTH_ATTR_RO(authenticate_target);
-/*
- * * Mutual authentication userid
- * */
-DEF_TPG_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
-TPG_AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
-/*
- * * Mutual authentication password
- * */
-DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
-TPG_AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
static struct configfs_attribute *lio_target_tpg_auth_attrs[] = {
- &iscsi_tpg_auth_userid.attr,
- &iscsi_tpg_auth_password.attr,
- &iscsi_tpg_auth_authenticate_target.attr,
- &iscsi_tpg_auth_userid_mutual.attr,
- &iscsi_tpg_auth_password_mutual.attr,
+ &iscsi_tpg_auth_attr_userid,
+ &iscsi_tpg_auth_attr_password,
+ &iscsi_tpg_auth_attr_authenticate_target,
+ &iscsi_tpg_auth_attr_userid_mutual,
+ &iscsi_tpg_auth_attr_password_mutual,
NULL,
};
@@ -1165,10 +993,10 @@ static struct configfs_attribute *lio_target_tpg_auth_attrs[] = {
/* Start items for lio_target_tpg_param_cit */
#define DEF_TPG_PARAM(name) \
-static ssize_t iscsi_tpg_param_show_##name( \
- struct se_portal_group *se_tpg, \
- char *page) \
+static ssize_t iscsi_tpg_param_##name##_show(struct config_item *item, \
+ char *page) \
{ \
+ struct se_portal_group *se_tpg = param_to_tpg(item); \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
struct iscsi_param *param; \
@@ -1188,11 +1016,10 @@ static ssize_t iscsi_tpg_param_show_##name( \
iscsit_put_tpg(tpg); \
return rb; \
} \
-static ssize_t iscsi_tpg_param_store_##name( \
- struct se_portal_group *se_tpg, \
- const char *page, \
- size_t count) \
+static ssize_t iscsi_tpg_param_##name##_store(struct config_item *item, \
+ const char *page, size_t count) \
{ \
+ struct se_portal_group *se_tpg = param_to_tpg(item); \
struct iscsi_portal_group *tpg = container_of(se_tpg, \
struct iscsi_portal_group, tpg_se_tpg); \
char *buf; \
@@ -1220,96 +1047,54 @@ static ssize_t iscsi_tpg_param_store_##name( \
out: \
kfree(buf); \
iscsit_put_tpg(tpg); \
- return -EINVAL; \
-}
-
-#define TPG_PARAM_ATTR(_name, _mode) TF_TPG_PARAM_ATTR(iscsi, _name, _mode);
+ return -EINVAL; \
+} \
+CONFIGFS_ATTR(iscsi_tpg_param_, name)
DEF_TPG_PARAM(AuthMethod);
-TPG_PARAM_ATTR(AuthMethod, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(HeaderDigest);
-TPG_PARAM_ATTR(HeaderDigest, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(DataDigest);
-TPG_PARAM_ATTR(DataDigest, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(MaxConnections);
-TPG_PARAM_ATTR(MaxConnections, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(TargetAlias);
-TPG_PARAM_ATTR(TargetAlias, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(InitialR2T);
-TPG_PARAM_ATTR(InitialR2T, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(ImmediateData);
-TPG_PARAM_ATTR(ImmediateData, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(MaxRecvDataSegmentLength);
-TPG_PARAM_ATTR(MaxRecvDataSegmentLength, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(MaxXmitDataSegmentLength);
-TPG_PARAM_ATTR(MaxXmitDataSegmentLength, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(MaxBurstLength);
-TPG_PARAM_ATTR(MaxBurstLength, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(FirstBurstLength);
-TPG_PARAM_ATTR(FirstBurstLength, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(DefaultTime2Wait);
-TPG_PARAM_ATTR(DefaultTime2Wait, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(DefaultTime2Retain);
-TPG_PARAM_ATTR(DefaultTime2Retain, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(MaxOutstandingR2T);
-TPG_PARAM_ATTR(MaxOutstandingR2T, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(DataPDUInOrder);
-TPG_PARAM_ATTR(DataPDUInOrder, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(DataSequenceInOrder);
-TPG_PARAM_ATTR(DataSequenceInOrder, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(ErrorRecoveryLevel);
-TPG_PARAM_ATTR(ErrorRecoveryLevel, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(IFMarker);
-TPG_PARAM_ATTR(IFMarker, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(OFMarker);
-TPG_PARAM_ATTR(OFMarker, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(IFMarkInt);
-TPG_PARAM_ATTR(IFMarkInt, S_IRUGO | S_IWUSR);
-
DEF_TPG_PARAM(OFMarkInt);
-TPG_PARAM_ATTR(OFMarkInt, S_IRUGO | S_IWUSR);
static struct configfs_attribute *lio_target_tpg_param_attrs[] = {
- &iscsi_tpg_param_AuthMethod.attr,
- &iscsi_tpg_param_HeaderDigest.attr,
- &iscsi_tpg_param_DataDigest.attr,
- &iscsi_tpg_param_MaxConnections.attr,
- &iscsi_tpg_param_TargetAlias.attr,
- &iscsi_tpg_param_InitialR2T.attr,
- &iscsi_tpg_param_ImmediateData.attr,
- &iscsi_tpg_param_MaxRecvDataSegmentLength.attr,
- &iscsi_tpg_param_MaxXmitDataSegmentLength.attr,
- &iscsi_tpg_param_MaxBurstLength.attr,
- &iscsi_tpg_param_FirstBurstLength.attr,
- &iscsi_tpg_param_DefaultTime2Wait.attr,
- &iscsi_tpg_param_DefaultTime2Retain.attr,
- &iscsi_tpg_param_MaxOutstandingR2T.attr,
- &iscsi_tpg_param_DataPDUInOrder.attr,
- &iscsi_tpg_param_DataSequenceInOrder.attr,
- &iscsi_tpg_param_ErrorRecoveryLevel.attr,
- &iscsi_tpg_param_IFMarker.attr,
- &iscsi_tpg_param_OFMarker.attr,
- &iscsi_tpg_param_IFMarkInt.attr,
- &iscsi_tpg_param_OFMarkInt.attr,
+ &iscsi_tpg_param_attr_AuthMethod,
+ &iscsi_tpg_param_attr_HeaderDigest,
+ &iscsi_tpg_param_attr_DataDigest,
+ &iscsi_tpg_param_attr_MaxConnections,
+ &iscsi_tpg_param_attr_TargetAlias,
+ &iscsi_tpg_param_attr_InitialR2T,
+ &iscsi_tpg_param_attr_ImmediateData,
+ &iscsi_tpg_param_attr_MaxRecvDataSegmentLength,
+ &iscsi_tpg_param_attr_MaxXmitDataSegmentLength,
+ &iscsi_tpg_param_attr_MaxBurstLength,
+ &iscsi_tpg_param_attr_FirstBurstLength,
+ &iscsi_tpg_param_attr_DefaultTime2Wait,
+ &iscsi_tpg_param_attr_DefaultTime2Retain,
+ &iscsi_tpg_param_attr_MaxOutstandingR2T,
+ &iscsi_tpg_param_attr_DataPDUInOrder,
+ &iscsi_tpg_param_attr_DataSequenceInOrder,
+ &iscsi_tpg_param_attr_ErrorRecoveryLevel,
+ &iscsi_tpg_param_attr_IFMarker,
+ &iscsi_tpg_param_attr_OFMarker,
+ &iscsi_tpg_param_attr_IFMarkInt,
+ &iscsi_tpg_param_attr_OFMarkInt,
NULL,
};
@@ -1317,10 +1102,9 @@ static struct configfs_attribute *lio_target_tpg_param_attrs[] = {
/* Start items for lio_target_tpg_cit */
-static ssize_t lio_target_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t lio_target_tpg_enable_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct iscsi_portal_group *tpg = container_of(se_tpg,
struct iscsi_portal_group, tpg_se_tpg);
ssize_t len;
@@ -1333,11 +1117,10 @@ static ssize_t lio_target_tpg_show_enable(
return len;
}
-static ssize_t lio_target_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t lio_target_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct iscsi_portal_group *tpg = container_of(se_tpg,
struct iscsi_portal_group, tpg_se_tpg);
u32 op;
@@ -1375,20 +1158,19 @@ out:
return -EINVAL;
}
-TF_TPG_BASE_ATTR(lio_target, enable, S_IRUGO | S_IWUSR);
-static ssize_t lio_target_tpg_show_dynamic_sessions(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t lio_target_tpg_dynamic_sessions_show(struct config_item *item,
+ char *page)
{
- return target_show_dynamic_sessions(se_tpg, page);
+ return target_show_dynamic_sessions(to_tpg(item), page);
}
-TF_TPG_BASE_ATTR_RO(lio_target, dynamic_sessions);
+CONFIGFS_ATTR(lio_target_tpg_, enable);
+CONFIGFS_ATTR_RO(lio_target_tpg_, dynamic_sessions);
static struct configfs_attribute *lio_target_tpg_attrs[] = {
- &lio_target_tpg_enable.attr,
- &lio_target_tpg_dynamic_sessions.attr,
+ &lio_target_tpg_attr_enable,
+ &lio_target_tpg_attr_dynamic_sessions,
NULL,
};
@@ -1463,17 +1245,16 @@ static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg)
/* Start LIO-Target TIQN struct contig_item lio_target_cit */
-static ssize_t lio_target_wwn_show_attr_lio_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t lio_target_wwn_lio_version_show(struct config_item *item,
+ char *page)
{
return sprintf(page, "Datera Inc. iSCSI Target "ISCSIT_VERSION"\n");
}
-TF_WWN_ATTR_RO(lio_target, lio_version);
+CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version);
static struct configfs_attribute *lio_target_wwn_attrs[] = {
- &lio_target_wwn_lio_version.attr,
+ &lio_target_wwn_attr_lio_version,
NULL,
};
@@ -1552,77 +1333,47 @@ static void lio_target_call_coredeltiqn(
#define DEF_DISC_AUTH_STR(name, flags) \
__DEF_NACL_AUTH_STR(disc, name, flags) \
-static ssize_t iscsi_disc_show_##name( \
- struct target_fabric_configfs *tf, \
- char *page) \
+static ssize_t iscsi_disc_##name##_show(struct config_item *item, char *page) \
{ \
- return __iscsi_disc_show_##name(&iscsit_global->discovery_acl, \
+ return __iscsi_disc_##name##_show(&iscsit_global->discovery_acl,\
page); \
} \
-static ssize_t iscsi_disc_store_##name( \
- struct target_fabric_configfs *tf, \
- const char *page, \
- size_t count) \
+static ssize_t iscsi_disc_##name##_store(struct config_item *item, \
+ const char *page, size_t count) \
{ \
- return __iscsi_disc_store_##name(&iscsit_global->discovery_acl, \
+ return __iscsi_disc_##name##_store(&iscsit_global->discovery_acl, \
page, count); \
-}
+ \
+} \
+CONFIGFS_ATTR(iscsi_disc_, name)
+
+DEF_DISC_AUTH_STR(userid, NAF_USERID_SET);
+DEF_DISC_AUTH_STR(password, NAF_PASSWORD_SET);
+DEF_DISC_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DEF_DISC_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
#define DEF_DISC_AUTH_INT(name) \
__DEF_NACL_AUTH_INT(disc, name) \
-static ssize_t iscsi_disc_show_##name( \
- struct target_fabric_configfs *tf, \
- char *page) \
+static ssize_t iscsi_disc_##name##_show(struct config_item *item, char *page) \
{ \
- return __iscsi_disc_show_##name(&iscsit_global->discovery_acl, \
+ return __iscsi_disc_##name##_show(&iscsit_global->discovery_acl, \
page); \
-}
-
-#define DISC_AUTH_ATTR(_name, _mode) TF_DISC_ATTR(iscsi, _name, _mode)
-#define DISC_AUTH_ATTR_RO(_name) TF_DISC_ATTR_RO(iscsi, _name)
+} \
+CONFIGFS_ATTR_RO(iscsi_disc_, name)
-/*
- * One-way authentication userid
- */
-DEF_DISC_AUTH_STR(userid, NAF_USERID_SET);
-DISC_AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
-/*
- * One-way authentication password
- */
-DEF_DISC_AUTH_STR(password, NAF_PASSWORD_SET);
-DISC_AUTH_ATTR(password, S_IRUGO | S_IWUSR);
-/*
- * Enforce mutual authentication
- */
DEF_DISC_AUTH_INT(authenticate_target);
-DISC_AUTH_ATTR_RO(authenticate_target);
-/*
- * Mutual authentication userid
- */
-DEF_DISC_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
-DISC_AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
-/*
- * Mutual authentication password
- */
-DEF_DISC_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
-DISC_AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
-/*
- * enforce_discovery_auth
- */
-static ssize_t iscsi_disc_show_enforce_discovery_auth(
- struct target_fabric_configfs *tf,
- char *page)
+
+static ssize_t iscsi_disc_enforce_discovery_auth_show(struct config_item *item,
+ char *page)
{
struct iscsi_node_auth *discovery_auth = &iscsit_global->discovery_acl.node_auth;
return sprintf(page, "%d\n", discovery_auth->enforce_discovery_auth);
}
-static ssize_t iscsi_disc_store_enforce_discovery_auth(
- struct target_fabric_configfs *tf,
- const char *page,
- size_t count)
+static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
+ const char *page, size_t count)
{
struct iscsi_param *param;
struct iscsi_portal_group *discovery_tpg = iscsit_global->discovery_tpg;
@@ -1677,15 +1428,15 @@ static ssize_t iscsi_disc_store_enforce_discovery_auth(
return count;
}
-DISC_AUTH_ATTR(enforce_discovery_auth, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(iscsi_disc_, enforce_discovery_auth);
static struct configfs_attribute *lio_target_discovery_auth_attrs[] = {
- &iscsi_disc_userid.attr,
- &iscsi_disc_password.attr,
- &iscsi_disc_authenticate_target.attr,
- &iscsi_disc_userid_mutual.attr,
- &iscsi_disc_password_mutual.attr,
- &iscsi_disc_enforce_discovery_auth.attr,
+ &iscsi_disc_attr_userid,
+ &iscsi_disc_attr_password,
+ &iscsi_disc_attr_authenticate_target,
+ &iscsi_disc_attr_userid_mutual,
+ &iscsi_disc_attr_password_mutual,
+ &iscsi_disc_attr_enforce_discovery_auth,
NULL,
};
diff --git a/drivers/target/iscsi/iscsi_target_stat.c b/drivers/target/iscsi/iscsi_target_stat.c
index 9dd94ff0b62c..411cb266a47d 100644
--- a/drivers/target/iscsi/iscsi_target_stat.c
+++ b/drivers/target/iscsi/iscsi_target_stat.c
@@ -21,7 +21,6 @@
#include <linux/export.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/configfs_macros.h>
#include <target/iscsi/iscsi_target_core.h>
#include "iscsi_target_parameters.h"
@@ -50,76 +49,56 @@
/*
* Instance Attributes Table
*/
-CONFIGFS_EATTR_STRUCT(iscsi_stat_instance, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_INSTANCE_ATTR(_name, _mode) \
-static struct iscsi_stat_instance_attribute \
- iscsi_stat_instance_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- iscsi_stat_instance_show_attr_##_name, \
- iscsi_stat_instance_store_attr_##_name);
-
-#define ISCSI_STAT_INSTANCE_ATTR_RO(_name) \
-static struct iscsi_stat_instance_attribute \
- iscsi_stat_instance_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- iscsi_stat_instance_show_attr_##_name);
-
-static ssize_t iscsi_stat_instance_show_attr_inst(
- struct iscsi_wwn_stat_grps *igrps, char *page)
-{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_instance_tiqn(struct config_item *item)
+{
+ struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+ struct iscsi_wwn_stat_grps, iscsi_instance_group);
+ return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_instance_inst_show(struct config_item *item,
+ char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_instance_tiqn(item)->tiqn_index);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(inst);
-static ssize_t iscsi_stat_instance_show_attr_min_ver(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_min_ver_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(min_ver);
-static ssize_t iscsi_stat_instance_show_attr_max_ver(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_max_ver_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(max_ver);
-static ssize_t iscsi_stat_instance_show_attr_portals(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_portals_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
-
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_num_tpg_nps);
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_instance_tiqn(item)->tiqn_num_tpg_nps);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(portals);
-static ssize_t iscsi_stat_instance_show_attr_nodes(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_nodes_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_INST_NUM_NODES);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(nodes);
-static ssize_t iscsi_stat_instance_show_attr_sessions(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_sessions_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
-
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_nsessions);
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_instance_tiqn(item)->tiqn_nsessions);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(sessions);
-static ssize_t iscsi_stat_instance_show_attr_fail_sess(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_fail_sess_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
u32 sess_err_count;
@@ -131,88 +110,84 @@ static ssize_t iscsi_stat_instance_show_attr_fail_sess(
return snprintf(page, PAGE_SIZE, "%u\n", sess_err_count);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(fail_sess);
-static ssize_t iscsi_stat_instance_show_attr_fail_type(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_fail_type_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
return snprintf(page, PAGE_SIZE, "%u\n",
sess_err->last_sess_failure_type);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(fail_type);
-static ssize_t iscsi_stat_instance_show_attr_fail_rem_name(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_fail_rem_name_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
return snprintf(page, PAGE_SIZE, "%s\n",
sess_err->last_sess_fail_rem_name[0] ?
sess_err->last_sess_fail_rem_name : NONE);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(fail_rem_name);
-static ssize_t iscsi_stat_instance_show_attr_disc_time(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_disc_time_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DISCONTINUITY_TIME);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(disc_time);
-static ssize_t iscsi_stat_instance_show_attr_description(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_description_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%s\n", ISCSI_INST_DESCR);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(description);
-static ssize_t iscsi_stat_instance_show_attr_vendor(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_vendor_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "Datera, Inc. iSCSI-Target\n");
}
-ISCSI_STAT_INSTANCE_ATTR_RO(vendor);
-static ssize_t iscsi_stat_instance_show_attr_version(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_version_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%s\n", ISCSIT_VERSION);
}
-ISCSI_STAT_INSTANCE_ATTR_RO(version);
-CONFIGFS_EATTR_OPS(iscsi_stat_instance, iscsi_wwn_stat_grps,
- iscsi_instance_group);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, min_ver);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, max_ver);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, portals);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, nodes);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, sessions);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_sess);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_type);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_rem_name);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, disc_time);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, description);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, vendor);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, version);
static struct configfs_attribute *iscsi_stat_instance_attrs[] = {
- &iscsi_stat_instance_inst.attr,
- &iscsi_stat_instance_min_ver.attr,
- &iscsi_stat_instance_max_ver.attr,
- &iscsi_stat_instance_portals.attr,
- &iscsi_stat_instance_nodes.attr,
- &iscsi_stat_instance_sessions.attr,
- &iscsi_stat_instance_fail_sess.attr,
- &iscsi_stat_instance_fail_type.attr,
- &iscsi_stat_instance_fail_rem_name.attr,
- &iscsi_stat_instance_disc_time.attr,
- &iscsi_stat_instance_description.attr,
- &iscsi_stat_instance_vendor.attr,
- &iscsi_stat_instance_version.attr,
+ &iscsi_stat_instance_attr_inst,
+ &iscsi_stat_instance_attr_min_ver,
+ &iscsi_stat_instance_attr_max_ver,
+ &iscsi_stat_instance_attr_portals,
+ &iscsi_stat_instance_attr_nodes,
+ &iscsi_stat_instance_attr_sessions,
+ &iscsi_stat_instance_attr_fail_sess,
+ &iscsi_stat_instance_attr_fail_type,
+ &iscsi_stat_instance_attr_fail_rem_name,
+ &iscsi_stat_instance_attr_disc_time,
+ &iscsi_stat_instance_attr_description,
+ &iscsi_stat_instance_attr_vendor,
+ &iscsi_stat_instance_attr_version,
NULL,
};
-static struct configfs_item_operations iscsi_stat_instance_item_ops = {
- .show_attribute = iscsi_stat_instance_attr_show,
- .store_attribute = iscsi_stat_instance_attr_store,
-};
-
struct config_item_type iscsi_stat_instance_cit = {
- .ct_item_ops = &iscsi_stat_instance_item_ops,
.ct_attrs = iscsi_stat_instance_attrs,
.ct_owner = THIS_MODULE,
};
@@ -220,81 +195,61 @@ struct config_item_type iscsi_stat_instance_cit = {
/*
* Instance Session Failure Stats Table
*/
-CONFIGFS_EATTR_STRUCT(iscsi_stat_sess_err, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_SESS_ERR_ATTR(_name, _mode) \
-static struct iscsi_stat_sess_err_attribute \
- iscsi_stat_sess_err_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- iscsi_stat_sess_err_show_attr_##_name, \
- iscsi_stat_sess_err_store_attr_##_name);
-
-#define ISCSI_STAT_SESS_ERR_ATTR_RO(_name) \
-static struct iscsi_stat_sess_err_attribute \
- iscsi_stat_sess_err_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- iscsi_stat_sess_err_show_attr_##_name);
-
-static ssize_t iscsi_stat_sess_err_show_attr_inst(
- struct iscsi_wwn_stat_grps *igrps, char *page)
-{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_sess_err_tiqn(struct config_item *item)
+{
+ struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+ struct iscsi_wwn_stat_grps, iscsi_sess_err_group);
+ return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_sess_err_inst_show(struct config_item *item,
+ char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_sess_err_tiqn(item)->tiqn_index);
}
-ISCSI_STAT_SESS_ERR_ATTR_RO(inst);
-static ssize_t iscsi_stat_sess_err_show_attr_digest_errors(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_err_digest_errors_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
return snprintf(page, PAGE_SIZE, "%u\n", sess_err->digest_errors);
}
-ISCSI_STAT_SESS_ERR_ATTR_RO(digest_errors);
-static ssize_t iscsi_stat_sess_err_show_attr_cxn_errors(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_err_cxn_errors_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
return snprintf(page, PAGE_SIZE, "%u\n", sess_err->cxn_timeout_errors);
}
-ISCSI_STAT_SESS_ERR_ATTR_RO(cxn_errors);
-static ssize_t iscsi_stat_sess_err_show_attr_format_errors(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_err_format_errors_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
return snprintf(page, PAGE_SIZE, "%u\n", sess_err->pdu_format_errors);
}
-ISCSI_STAT_SESS_ERR_ATTR_RO(format_errors);
-CONFIGFS_EATTR_OPS(iscsi_stat_sess_err, iscsi_wwn_stat_grps,
- iscsi_sess_err_group);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, digest_errors);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, cxn_errors);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, format_errors);
static struct configfs_attribute *iscsi_stat_sess_err_attrs[] = {
- &iscsi_stat_sess_err_inst.attr,
- &iscsi_stat_sess_err_digest_errors.attr,
- &iscsi_stat_sess_err_cxn_errors.attr,
- &iscsi_stat_sess_err_format_errors.attr,
+ &iscsi_stat_sess_err_attr_inst,
+ &iscsi_stat_sess_err_attr_digest_errors,
+ &iscsi_stat_sess_err_attr_cxn_errors,
+ &iscsi_stat_sess_err_attr_format_errors,
NULL,
};
-static struct configfs_item_operations iscsi_stat_sess_err_item_ops = {
- .show_attribute = iscsi_stat_sess_err_attr_show,
- .store_attribute = iscsi_stat_sess_err_attr_store,
-};
-
struct config_item_type iscsi_stat_sess_err_cit = {
- .ct_item_ops = &iscsi_stat_sess_err_item_ops,
.ct_attrs = iscsi_stat_sess_err_attrs,
.ct_owner = THIS_MODULE,
};
@@ -302,42 +257,30 @@ struct config_item_type iscsi_stat_sess_err_cit = {
/*
* Target Attributes Table
*/
-CONFIGFS_EATTR_STRUCT(iscsi_stat_tgt_attr, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_TGT_ATTR(_name, _mode) \
-static struct iscsi_stat_tgt_attr_attribute \
- iscsi_stat_tgt_attr_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- iscsi_stat_tgt-attr_show_attr_##_name, \
- iscsi_stat_tgt_attr_store_attr_##_name);
-
-#define ISCSI_STAT_TGT_ATTR_RO(_name) \
-static struct iscsi_stat_tgt_attr_attribute \
- iscsi_stat_tgt_attr_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- iscsi_stat_tgt_attr_show_attr_##_name);
-
-static ssize_t iscsi_stat_tgt_attr_show_attr_inst(
- struct iscsi_wwn_stat_grps *igrps, char *page)
-{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_tgt_attr_tiqn(struct config_item *item)
+{
+ struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+ struct iscsi_wwn_stat_grps, iscsi_tgt_attr_group);
+ return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_tgt_attr_inst_show(struct config_item *item,
+ char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_tgt_attr_tiqn(item)->tiqn_index);
}
-ISCSI_STAT_TGT_ATTR_RO(inst);
-static ssize_t iscsi_stat_tgt_attr_show_attr_indx(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_indx_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
}
-ISCSI_STAT_TGT_ATTR_RO(indx);
-static ssize_t iscsi_stat_tgt_attr_show_attr_login_fails(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_login_fails_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
u32 fail_count;
@@ -349,13 +292,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_login_fails(
return snprintf(page, PAGE_SIZE, "%u\n", fail_count);
}
-ISCSI_STAT_TGT_ATTR_RO(login_fails);
-static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_time(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_last_fail_time_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
u32 last_fail_time;
@@ -367,13 +308,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_time(
return snprintf(page, PAGE_SIZE, "%u\n", last_fail_time);
}
-ISCSI_STAT_TGT_ATTR_RO(last_fail_time);
-static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_type(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_last_fail_type_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
u32 last_fail_type;
@@ -383,13 +322,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_type(
return snprintf(page, PAGE_SIZE, "%u\n", last_fail_type);
}
-ISCSI_STAT_TGT_ATTR_RO(last_fail_type);
-static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_name(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_fail_intr_name_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
unsigned char buf[224];
@@ -400,13 +337,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_name(
return snprintf(page, PAGE_SIZE, "%s\n", buf);
}
-ISCSI_STAT_TGT_ATTR_RO(fail_intr_name);
-static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr_type(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_fail_intr_addr_type_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
int ret;
@@ -419,13 +354,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr_type(
return ret;
}
-ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr_type);
-static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_fail_intr_addr_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
int ret;
@@ -435,30 +368,29 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
return ret;
}
-ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr);
-CONFIGFS_EATTR_OPS(iscsi_stat_tgt_attr, iscsi_wwn_stat_grps,
- iscsi_tgt_attr_group);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, login_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, last_fail_time);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, last_fail_type);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_name);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_addr_type);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_addr);
static struct configfs_attribute *iscsi_stat_tgt_attr_attrs[] = {
- &iscsi_stat_tgt_attr_inst.attr,
- &iscsi_stat_tgt_attr_indx.attr,
- &iscsi_stat_tgt_attr_login_fails.attr,
- &iscsi_stat_tgt_attr_last_fail_time.attr,
- &iscsi_stat_tgt_attr_last_fail_type.attr,
- &iscsi_stat_tgt_attr_fail_intr_name.attr,
- &iscsi_stat_tgt_attr_fail_intr_addr_type.attr,
- &iscsi_stat_tgt_attr_fail_intr_addr.attr,
+ &iscsi_stat_tgt_attr_attr_inst,
+ &iscsi_stat_tgt_attr_attr_indx,
+ &iscsi_stat_tgt_attr_attr_login_fails,
+ &iscsi_stat_tgt_attr_attr_last_fail_time,
+ &iscsi_stat_tgt_attr_attr_last_fail_type,
+ &iscsi_stat_tgt_attr_attr_fail_intr_name,
+ &iscsi_stat_tgt_attr_attr_fail_intr_addr_type,
+ &iscsi_stat_tgt_attr_attr_fail_intr_addr,
NULL,
};
-static struct configfs_item_operations iscsi_stat_tgt_attr_item_ops = {
- .show_attribute = iscsi_stat_tgt_attr_attr_show,
- .store_attribute = iscsi_stat_tgt_attr_attr_store,
-};
-
struct config_item_type iscsi_stat_tgt_attr_cit = {
- .ct_item_ops = &iscsi_stat_tgt_attr_item_ops,
.ct_attrs = iscsi_stat_tgt_attr_attrs,
.ct_owner = THIS_MODULE,
};
@@ -466,42 +398,29 @@ struct config_item_type iscsi_stat_tgt_attr_cit = {
/*
* Target Login Stats Table
*/
-CONFIGFS_EATTR_STRUCT(iscsi_stat_login, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_LOGIN(_name, _mode) \
-static struct iscsi_stat_login_attribute \
- iscsi_stat_login_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- iscsi_stat_login_show_attr_##_name, \
- iscsi_stat_login_store_attr_##_name);
-
-#define ISCSI_STAT_LOGIN_RO(_name) \
-static struct iscsi_stat_login_attribute \
- iscsi_stat_login_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- iscsi_stat_login_show_attr_##_name);
-
-static ssize_t iscsi_stat_login_show_attr_inst(
- struct iscsi_wwn_stat_grps *igrps, char *page)
-{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_login_stat_tiqn(struct config_item *item)
+{
+ struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+ struct iscsi_wwn_stat_grps, iscsi_login_stats_group);
+ return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_login_inst_show(struct config_item *item, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_login_stat_tiqn(item)->tiqn_index);
}
-ISCSI_STAT_LOGIN_RO(inst);
-static ssize_t iscsi_stat_login_show_attr_indx(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_indx_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
}
-ISCSI_STAT_LOGIN_RO(indx);
-static ssize_t iscsi_stat_login_show_attr_accepts(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_accepts_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
ssize_t ret;
@@ -511,13 +430,11 @@ static ssize_t iscsi_stat_login_show_attr_accepts(
return ret;
}
-ISCSI_STAT_LOGIN_RO(accepts);
-static ssize_t iscsi_stat_login_show_attr_other_fails(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_other_fails_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
ssize_t ret;
@@ -527,13 +444,11 @@ static ssize_t iscsi_stat_login_show_attr_other_fails(
return ret;
}
-ISCSI_STAT_LOGIN_RO(other_fails);
-static ssize_t iscsi_stat_login_show_attr_redirects(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_redirects_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
ssize_t ret;
@@ -543,13 +458,11 @@ static ssize_t iscsi_stat_login_show_attr_redirects(
return ret;
}
-ISCSI_STAT_LOGIN_RO(redirects);
-static ssize_t iscsi_stat_login_show_attr_authorize_fails(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_authorize_fails_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
ssize_t ret;
@@ -559,13 +472,11 @@ static ssize_t iscsi_stat_login_show_attr_authorize_fails(
return ret;
}
-ISCSI_STAT_LOGIN_RO(authorize_fails);
-static ssize_t iscsi_stat_login_show_attr_authenticate_fails(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_authenticate_fails_show(
+ struct config_item *item, char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
ssize_t ret;
@@ -575,13 +486,11 @@ static ssize_t iscsi_stat_login_show_attr_authenticate_fails(
return ret;
}
-ISCSI_STAT_LOGIN_RO(authenticate_fails);
-static ssize_t iscsi_stat_login_show_attr_negotiate_fails(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_negotiate_fails_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
struct iscsi_login_stats *lstat = &tiqn->login_stats;
ssize_t ret;
@@ -591,30 +500,29 @@ static ssize_t iscsi_stat_login_show_attr_negotiate_fails(
return ret;
}
-ISCSI_STAT_LOGIN_RO(negotiate_fails);
-CONFIGFS_EATTR_OPS(iscsi_stat_login, iscsi_wwn_stat_grps,
- iscsi_login_stats_group);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, accepts);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, other_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, redirects);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, authorize_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, authenticate_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, negotiate_fails);
static struct configfs_attribute *iscsi_stat_login_stats_attrs[] = {
- &iscsi_stat_login_inst.attr,
- &iscsi_stat_login_indx.attr,
- &iscsi_stat_login_accepts.attr,
- &iscsi_stat_login_other_fails.attr,
- &iscsi_stat_login_redirects.attr,
- &iscsi_stat_login_authorize_fails.attr,
- &iscsi_stat_login_authenticate_fails.attr,
- &iscsi_stat_login_negotiate_fails.attr,
+ &iscsi_stat_login_attr_inst,
+ &iscsi_stat_login_attr_indx,
+ &iscsi_stat_login_attr_accepts,
+ &iscsi_stat_login_attr_other_fails,
+ &iscsi_stat_login_attr_redirects,
+ &iscsi_stat_login_attr_authorize_fails,
+ &iscsi_stat_login_attr_authenticate_fails,
+ &iscsi_stat_login_attr_negotiate_fails,
NULL,
};
-static struct configfs_item_operations iscsi_stat_login_stats_item_ops = {
- .show_attribute = iscsi_stat_login_attr_show,
- .store_attribute = iscsi_stat_login_attr_store,
-};
-
struct config_item_type iscsi_stat_login_cit = {
- .ct_item_ops = &iscsi_stat_login_stats_item_ops,
.ct_attrs = iscsi_stat_login_stats_attrs,
.ct_owner = THIS_MODULE,
};
@@ -622,78 +530,56 @@ struct config_item_type iscsi_stat_login_cit = {
/*
* Target Logout Stats Table
*/
-
-CONFIGFS_EATTR_STRUCT(iscsi_stat_logout, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_LOGOUT(_name, _mode) \
-static struct iscsi_stat_logout_attribute \
- iscsi_stat_logout_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- iscsi_stat_logout_show_attr_##_name, \
- iscsi_stat_logout_store_attr_##_name);
-
-#define ISCSI_STAT_LOGOUT_RO(_name) \
-static struct iscsi_stat_logout_attribute \
- iscsi_stat_logout_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- iscsi_stat_logout_show_attr_##_name);
-
-static ssize_t iscsi_stat_logout_show_attr_inst(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static struct iscsi_tiqn *iscsi_logout_stat_tiqn(struct config_item *item)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+ struct iscsi_wwn_stat_grps, iscsi_logout_stats_group);
+ return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
- return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_logout_inst_show(struct config_item *item, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ iscsi_logout_stat_tiqn(item)->tiqn_index);
}
-ISCSI_STAT_LOGOUT_RO(inst);
-static ssize_t iscsi_stat_logout_show_attr_indx(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_logout_indx_show(struct config_item *item, char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
}
-ISCSI_STAT_LOGOUT_RO(indx);
-static ssize_t iscsi_stat_logout_show_attr_normal_logouts(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_logout_normal_logouts_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_logout_stat_tiqn(item);
struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
return snprintf(page, PAGE_SIZE, "%u\n", lstats->normal_logouts);
}
-ISCSI_STAT_LOGOUT_RO(normal_logouts);
-static ssize_t iscsi_stat_logout_show_attr_abnormal_logouts(
- struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_logout_abnormal_logouts_show(struct config_item *item,
+ char *page)
{
- struct iscsi_tiqn *tiqn = container_of(igrps,
- struct iscsi_tiqn, tiqn_stat_grps);
+ struct iscsi_tiqn *tiqn = iscsi_logout_stat_tiqn(item);
struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
return snprintf(page, PAGE_SIZE, "%u\n", lstats->abnormal_logouts);
}
-ISCSI_STAT_LOGOUT_RO(abnormal_logouts);
-CONFIGFS_EATTR_OPS(iscsi_stat_logout, iscsi_wwn_stat_grps,
- iscsi_logout_stats_group);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, normal_logouts);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, abnormal_logouts);
static struct configfs_attribute *iscsi_stat_logout_stats_attrs[] = {
- &iscsi_stat_logout_inst.attr,
- &iscsi_stat_logout_indx.attr,
- &iscsi_stat_logout_normal_logouts.attr,
- &iscsi_stat_logout_abnormal_logouts.attr,
+ &iscsi_stat_logout_attr_inst,
+ &iscsi_stat_logout_attr_indx,
+ &iscsi_stat_logout_attr_normal_logouts,
+ &iscsi_stat_logout_attr_abnormal_logouts,
NULL,
};
-static struct configfs_item_operations iscsi_stat_logout_stats_item_ops = {
- .show_attribute = iscsi_stat_logout_attr_show,
- .store_attribute = iscsi_stat_logout_attr_store,
-};
-
struct config_item_type iscsi_stat_logout_cit = {
- .ct_item_ops = &iscsi_stat_logout_stats_item_ops,
.ct_attrs = iscsi_stat_logout_stats_attrs,
.ct_owner = THIS_MODULE,
};
@@ -701,39 +587,26 @@ struct config_item_type iscsi_stat_logout_cit = {
/*
* Session Stats Table
*/
+static struct iscsi_node_acl *iscsi_stat_nacl(struct config_item *item)
+{
+ struct iscsi_node_stat_grps *igrps = container_of(to_config_group(item),
+ struct iscsi_node_stat_grps, iscsi_sess_stats_group);
+ return container_of(igrps, struct iscsi_node_acl, node_stat_grps);
+}
-CONFIGFS_EATTR_STRUCT(iscsi_stat_sess, iscsi_node_stat_grps);
-#define ISCSI_STAT_SESS(_name, _mode) \
-static struct iscsi_stat_sess_attribute \
- iscsi_stat_sess_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- iscsi_stat_sess_show_attr_##_name, \
- iscsi_stat_sess_store_attr_##_name);
-
-#define ISCSI_STAT_SESS_RO(_name) \
-static struct iscsi_stat_sess_attribute \
- iscsi_stat_sess_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- iscsi_stat_sess_show_attr_##_name);
-
-static ssize_t iscsi_stat_sess_show_attr_inst(
- struct iscsi_node_stat_grps *igrps, char *page)
-{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+static ssize_t iscsi_stat_sess_inst_show(struct config_item *item, char *page)
+{
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_wwn *wwn = acl->se_node_acl.se_tpg->se_tpg_wwn;
struct iscsi_tiqn *tiqn = container_of(wwn,
struct iscsi_tiqn, tiqn_wwn);
return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
}
-ISCSI_STAT_SESS_RO(inst);
-static ssize_t iscsi_stat_sess_show_attr_node(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_node_show(struct config_item *item, char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -751,13 +624,10 @@ static ssize_t iscsi_stat_sess_show_attr_node(
return ret;
}
-ISCSI_STAT_SESS_RO(node);
-static ssize_t iscsi_stat_sess_show_attr_indx(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_indx_show(struct config_item *item, char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -775,13 +645,11 @@ static ssize_t iscsi_stat_sess_show_attr_indx(
return ret;
}
-ISCSI_STAT_SESS_RO(indx);
-static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_cmd_pdus_show(struct config_item *item,
+ char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -799,13 +667,11 @@ static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
return ret;
}
-ISCSI_STAT_SESS_RO(cmd_pdus);
-static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_rsp_pdus_show(struct config_item *item,
+ char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -823,13 +689,11 @@ static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
return ret;
}
-ISCSI_STAT_SESS_RO(rsp_pdus);
-static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_txdata_octs_show(struct config_item *item,
+ char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -847,13 +711,11 @@ static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
return ret;
}
-ISCSI_STAT_SESS_RO(txdata_octs);
-static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_rxdata_octs_show(struct config_item *item,
+ char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -871,13 +733,11 @@ static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
return ret;
}
-ISCSI_STAT_SESS_RO(rxdata_octs);
-static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_conn_digest_errors_show(struct config_item *item,
+ char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -895,13 +755,11 @@ static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
return ret;
}
-ISCSI_STAT_SESS_RO(conn_digest_errors);
-static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
- struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_conn_timeout_errors_show(
+ struct config_item *item, char *page)
{
- struct iscsi_node_acl *acl = container_of(igrps,
- struct iscsi_node_acl, node_stat_grps);
+ struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
struct se_node_acl *se_nacl = &acl->se_node_acl;
struct iscsi_session *sess;
struct se_session *se_sess;
@@ -919,31 +777,31 @@ static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
return ret;
}
-ISCSI_STAT_SESS_RO(conn_timeout_errors);
-CONFIGFS_EATTR_OPS(iscsi_stat_sess, iscsi_node_stat_grps,
- iscsi_sess_stats_group);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, node);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, cmd_pdus);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, rsp_pdus);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, txdata_octs);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, rxdata_octs);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, conn_digest_errors);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, conn_timeout_errors);
static struct configfs_attribute *iscsi_stat_sess_stats_attrs[] = {
- &iscsi_stat_sess_inst.attr,
- &iscsi_stat_sess_node.attr,
- &iscsi_stat_sess_indx.attr,
- &iscsi_stat_sess_cmd_pdus.attr,
- &iscsi_stat_sess_rsp_pdus.attr,
- &iscsi_stat_sess_txdata_octs.attr,
- &iscsi_stat_sess_rxdata_octs.attr,
- &iscsi_stat_sess_conn_digest_errors.attr,
- &iscsi_stat_sess_conn_timeout_errors.attr,
+ &iscsi_stat_sess_attr_inst,
+ &iscsi_stat_sess_attr_node,
+ &iscsi_stat_sess_attr_indx,
+ &iscsi_stat_sess_attr_cmd_pdus,
+ &iscsi_stat_sess_attr_rsp_pdus,
+ &iscsi_stat_sess_attr_txdata_octs,
+ &iscsi_stat_sess_attr_rxdata_octs,
+ &iscsi_stat_sess_attr_conn_digest_errors,
+ &iscsi_stat_sess_attr_conn_timeout_errors,
NULL,
};
-static struct configfs_item_operations iscsi_stat_sess_stats_item_ops = {
- .show_attribute = iscsi_stat_sess_attr_show,
- .store_attribute = iscsi_stat_sess_attr_store,
-};
-
struct config_item_type iscsi_stat_sess_cit = {
- .ct_item_ops = &iscsi_stat_sess_stats_item_ops,
.ct_attrs = iscsi_stat_sess_stats_attrs,
.ct_owner = THIS_MODULE,
};
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 5bc85ffed720..4fb0eca86857 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -34,7 +34,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
#include "tcm_loop.h"
@@ -377,7 +376,6 @@ static struct scsi_host_template tcm_loop_driver_template = {
.use_clustering = DISABLE_CLUSTERING,
.slave_alloc = tcm_loop_slave_alloc,
.module = THIS_MODULE,
- .use_blk_tags = 1,
.track_queue_depth = 1,
};
@@ -763,21 +761,20 @@ static void tcm_loop_port_unlink(
/* End items for tcm_loop_port_cit */
-static ssize_t tcm_loop_tpg_attrib_show_fabric_prot_type(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_loop_tpg_attrib_fabric_prot_type_show(
+ struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
tl_se_tpg);
return sprintf(page, "%d\n", tl_tpg->tl_fabric_prot_type);
}
-static ssize_t tcm_loop_tpg_attrib_store_fabric_prot_type(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_loop_tpg_attrib_fabric_prot_type_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
tl_se_tpg);
unsigned long val;
@@ -796,10 +793,10 @@ static ssize_t tcm_loop_tpg_attrib_store_fabric_prot_type(
return count;
}
-TF_TPG_ATTRIB_ATTR(tcm_loop, fabric_prot_type, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(tcm_loop_tpg_attrib_, fabric_prot_type);
static struct configfs_attribute *tcm_loop_tpg_attrib_attrs[] = {
- &tcm_loop_tpg_attrib_fabric_prot_type.attr,
+ &tcm_loop_tpg_attrib_attr_fabric_prot_type,
NULL,
};
@@ -894,10 +891,9 @@ static int tcm_loop_drop_nexus(
/* End items for tcm_loop_nexus_cit */
-static ssize_t tcm_loop_tpg_show_nexus(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_loop_tpg_nexus_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
struct tcm_loop_tpg, tl_se_tpg);
struct tcm_loop_nexus *tl_nexus;
@@ -913,11 +909,10 @@ static ssize_t tcm_loop_tpg_show_nexus(
return ret;
}
-static ssize_t tcm_loop_tpg_store_nexus(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_loop_tpg_nexus_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
struct tcm_loop_tpg, tl_se_tpg);
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
@@ -992,12 +987,10 @@ check_newline:
return count;
}
-TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
-
-static ssize_t tcm_loop_tpg_show_transport_status(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_loop_tpg_transport_status_show(struct config_item *item,
+ char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
struct tcm_loop_tpg, tl_se_tpg);
const char *status = NULL;
@@ -1020,11 +1013,10 @@ static ssize_t tcm_loop_tpg_show_transport_status(
return ret;
}
-static ssize_t tcm_loop_tpg_store_transport_status(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_loop_tpg_transport_status_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
struct tcm_loop_tpg, tl_se_tpg);
@@ -1044,11 +1036,12 @@ static ssize_t tcm_loop_tpg_store_transport_status(
return -EINVAL;
}
-TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(tcm_loop_tpg_, nexus);
+CONFIGFS_ATTR(tcm_loop_tpg_, transport_status);
static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
- &tcm_loop_tpg_nexus.attr,
- &tcm_loop_tpg_transport_status.attr,
+ &tcm_loop_tpg_attr_nexus,
+ &tcm_loop_tpg_attr_transport_status,
NULL,
};
@@ -1216,17 +1209,15 @@ static void tcm_loop_drop_scsi_hba(
}
/* Start items for tcm_loop_cit */
-static ssize_t tcm_loop_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t tcm_loop_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "TCM Loopback Fabric module %s\n", TCM_LOOP_VERSION);
}
-TF_WWN_ATTR_RO(tcm_loop, version);
+CONFIGFS_ATTR_RO(tcm_loop_wwn_, version);
static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
- &tcm_loop_wwn_version.attr,
+ &tcm_loop_wwn_attr_version,
NULL,
};
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 0edf320fb685..35f7d31b29d2 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -35,8 +35,6 @@
#include <target/target_core_base.h>
#include <target/target_core_backend.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include <asm/unaligned.h>
#include "sbp_target.h"
@@ -2111,24 +2109,21 @@ static void sbp_drop_tport(struct se_wwn *wwn)
kfree(tport);
}
-static ssize_t sbp_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t sbp_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "FireWire SBP fabric module %s\n", SBP_VERSION);
}
-TF_WWN_ATTR_RO(sbp, version);
+CONFIGFS_ATTR_RO(sbp_wwn_, version);
static struct configfs_attribute *sbp_wwn_attrs[] = {
- &sbp_wwn_version.attr,
+ &sbp_wwn_attr_version,
NULL,
};
-static ssize_t sbp_tpg_show_directory_id(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t sbp_tpg_directory_id_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
@@ -2138,11 +2133,10 @@ static ssize_t sbp_tpg_show_directory_id(
return sprintf(page, "%06x\n", tport->directory_id);
}
-static ssize_t sbp_tpg_store_directory_id(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t sbp_tpg_directory_id_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
unsigned long val;
@@ -2166,20 +2160,18 @@ static ssize_t sbp_tpg_store_directory_id(
return count;
}
-static ssize_t sbp_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t sbp_tpg_enable_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
return sprintf(page, "%d\n", tport->enable);
}
-static ssize_t sbp_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t sbp_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
unsigned long val;
@@ -2219,29 +2211,28 @@ static ssize_t sbp_tpg_store_enable(
return count;
}
-TF_TPG_BASE_ATTR(sbp, directory_id, S_IRUGO | S_IWUSR);
-TF_TPG_BASE_ATTR(sbp, enable, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(sbp_tpg_, directory_id);
+CONFIGFS_ATTR(sbp_tpg_, enable);
static struct configfs_attribute *sbp_tpg_base_attrs[] = {
- &sbp_tpg_directory_id.attr,
- &sbp_tpg_enable.attr,
+ &sbp_tpg_attr_directory_id,
+ &sbp_tpg_attr_enable,
NULL,
};
-static ssize_t sbp_tpg_attrib_show_mgt_orb_timeout(
- struct se_portal_group *se_tpg,
+static ssize_t sbp_tpg_attrib_mgt_orb_timeout_show(struct config_item *item,
char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
return sprintf(page, "%d\n", tport->mgt_orb_timeout);
}
-static ssize_t sbp_tpg_attrib_store_mgt_orb_timeout(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t sbp_tpg_attrib_mgt_orb_timeout_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
unsigned long val;
@@ -2264,20 +2255,19 @@ static ssize_t sbp_tpg_attrib_store_mgt_orb_timeout(
return count;
}
-static ssize_t sbp_tpg_attrib_show_max_reconnect_timeout(
- struct se_portal_group *se_tpg,
+static ssize_t sbp_tpg_attrib_max_reconnect_timeout_show(struct config_item *item,
char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
return sprintf(page, "%d\n", tport->max_reconnect_timeout);
}
-static ssize_t sbp_tpg_attrib_store_max_reconnect_timeout(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t sbp_tpg_attrib_max_reconnect_timeout_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
unsigned long val;
@@ -2300,20 +2290,19 @@ static ssize_t sbp_tpg_attrib_store_max_reconnect_timeout(
return count;
}
-static ssize_t sbp_tpg_attrib_show_max_logins_per_lun(
- struct se_portal_group *se_tpg,
+static ssize_t sbp_tpg_attrib_max_logins_per_lun_show(struct config_item *item,
char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
return sprintf(page, "%d\n", tport->max_logins_per_lun);
}
-static ssize_t sbp_tpg_attrib_store_max_logins_per_lun(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t sbp_tpg_attrib_max_logins_per_lun_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
struct sbp_tport *tport = tpg->tport;
unsigned long val;
@@ -2330,14 +2319,14 @@ static ssize_t sbp_tpg_attrib_store_max_logins_per_lun(
return count;
}
-TF_TPG_ATTRIB_ATTR(sbp, mgt_orb_timeout, S_IRUGO | S_IWUSR);
-TF_TPG_ATTRIB_ATTR(sbp, max_reconnect_timeout, S_IRUGO | S_IWUSR);
-TF_TPG_ATTRIB_ATTR(sbp, max_logins_per_lun, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(sbp_tpg_attrib_, mgt_orb_timeout);
+CONFIGFS_ATTR(sbp_tpg_attrib_, max_reconnect_timeout);
+CONFIGFS_ATTR(sbp_tpg_attrib_, max_logins_per_lun);
static struct configfs_attribute *sbp_tpg_attrib_attrs[] = {
- &sbp_tpg_attrib_mgt_orb_timeout.attr,
- &sbp_tpg_attrib_max_reconnect_timeout.attr,
- &sbp_tpg_attrib_max_logins_per_lun.attr,
+ &sbp_tpg_attrib_attr_mgt_orb_timeout,
+ &sbp_tpg_attrib_attr_max_reconnect_timeout,
+ &sbp_tpg_attrib_attr_max_logins_per_lun,
NULL,
};
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 860e84046177..b9b9ffde4c7a 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -40,8 +40,6 @@
#include <target/target_core_base.h>
#include <target/target_core_backend.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include "target_core_internal.h"
#include "target_core_alua.h"
@@ -78,12 +76,6 @@ extern struct t10_alua_lu_gp *default_lu_gp;
static LIST_HEAD(g_tf_list);
static DEFINE_MUTEX(g_tf_lock);
-struct target_core_configfs_attribute {
- struct configfs_attribute attr;
- ssize_t (*show)(void *, char *);
- ssize_t (*store)(void *, const char *, size_t);
-};
-
static struct config_group target_core_hbagroup;
static struct config_group alua_group;
static struct config_group alua_lu_gps_group;
@@ -97,24 +89,15 @@ item_to_hba(struct config_item *item)
/*
* Attributes for /sys/kernel/config/target/
*/
-static ssize_t target_core_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
+static ssize_t target_core_item_version_show(struct config_item *item,
+ char *page)
{
return sprintf(page, "Target Engine Core ConfigFS Infrastructure %s"
" on %s/%s on "UTS_RELEASE"\n", TARGET_CORE_VERSION,
utsname()->sysname, utsname()->machine);
}
-static struct configfs_item_operations target_core_fabric_item_ops = {
- .show_attribute = target_core_attr_show,
-};
-
-static struct configfs_attribute target_core_item_attr_version = {
- .ca_owner = THIS_MODULE,
- .ca_name = "version",
- .ca_mode = S_IRUGO,
-};
+CONFIGFS_ATTR_RO(target_core_item_, version);
static struct target_fabric_configfs *target_core_get_fabric(
const char *name)
@@ -273,7 +256,6 @@ static struct configfs_attribute *target_core_fabric_item_attrs[] = {
* Provides Fabrics Groups and Item Attributes for /sys/kernel/config/target/
*/
static struct config_item_type target_core_fabrics_item = {
- .ct_item_ops = &target_core_fabric_item_ops,
.ct_group_ops = &target_core_fabric_group_ops,
.ct_attrs = target_core_fabric_item_attrs,
.ct_owner = THIS_MODULE,
@@ -476,47 +458,54 @@ EXPORT_SYMBOL(target_unregister_template);
// Stop functions called by external Target Fabrics Modules
//############################################################################*/
+static inline struct se_dev_attrib *to_attrib(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct se_dev_attrib,
+ da_group);
+}
+
/* Start functions for struct config_item_type tb_dev_attrib_cit */
-#define DEF_TB_DEV_ATTRIB_SHOW(_name) \
-static ssize_t show_##_name(struct se_dev_attrib *da, char *page) \
+#define DEF_CONFIGFS_ATTRIB_SHOW(_name) \
+static ssize_t _name##_show(struct config_item *item, char *page) \
{ \
- return snprintf(page, PAGE_SIZE, "%u\n", da->_name); \
-}
-
-DEF_TB_DEV_ATTRIB_SHOW(emulate_model_alias);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_dpo);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_fua_write);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_fua_read);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_write_cache);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_ua_intlck_ctrl);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_tas);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_tpu);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_tpws);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_caw);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_3pc);
-DEF_TB_DEV_ATTRIB_SHOW(pi_prot_type);
-DEF_TB_DEV_ATTRIB_SHOW(hw_pi_prot_type);
-DEF_TB_DEV_ATTRIB_SHOW(pi_prot_format);
-DEF_TB_DEV_ATTRIB_SHOW(enforce_pr_isids);
-DEF_TB_DEV_ATTRIB_SHOW(is_nonrot);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_rest_reord);
-DEF_TB_DEV_ATTRIB_SHOW(force_pr_aptpl);
-DEF_TB_DEV_ATTRIB_SHOW(hw_block_size);
-DEF_TB_DEV_ATTRIB_SHOW(block_size);
-DEF_TB_DEV_ATTRIB_SHOW(hw_max_sectors);
-DEF_TB_DEV_ATTRIB_SHOW(optimal_sectors);
-DEF_TB_DEV_ATTRIB_SHOW(hw_queue_depth);
-DEF_TB_DEV_ATTRIB_SHOW(queue_depth);
-DEF_TB_DEV_ATTRIB_SHOW(max_unmap_lba_count);
-DEF_TB_DEV_ATTRIB_SHOW(max_unmap_block_desc_count);
-DEF_TB_DEV_ATTRIB_SHOW(unmap_granularity);
-DEF_TB_DEV_ATTRIB_SHOW(unmap_granularity_alignment);
-DEF_TB_DEV_ATTRIB_SHOW(max_write_same_len);
-
-#define DEF_TB_DEV_ATTRIB_STORE_U32(_name) \
-static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
+ return snprintf(page, PAGE_SIZE, "%u\n", to_attrib(item)->_name); \
+}
+
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_model_alias);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_dpo);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_fua_write);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_fua_read);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_write_cache);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_ua_intlck_ctrl);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_tas);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpu);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpws);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_caw);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_3pc);
+DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_type);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_pi_prot_type);
+DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_format);
+DEF_CONFIGFS_ATTRIB_SHOW(enforce_pr_isids);
+DEF_CONFIGFS_ATTRIB_SHOW(is_nonrot);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_rest_reord);
+DEF_CONFIGFS_ATTRIB_SHOW(force_pr_aptpl);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_block_size);
+DEF_CONFIGFS_ATTRIB_SHOW(block_size);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_max_sectors);
+DEF_CONFIGFS_ATTRIB_SHOW(optimal_sectors);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_queue_depth);
+DEF_CONFIGFS_ATTRIB_SHOW(queue_depth);
+DEF_CONFIGFS_ATTRIB_SHOW(max_unmap_lba_count);
+DEF_CONFIGFS_ATTRIB_SHOW(max_unmap_block_desc_count);
+DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity);
+DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment);
+DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
+
+#define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \
+static ssize_t _name##_store(struct config_item *item, const char *page,\
size_t count) \
{ \
+ struct se_dev_attrib *da = to_attrib(item); \
u32 val; \
int ret; \
\
@@ -527,16 +516,17 @@ static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
return count; \
}
-DEF_TB_DEV_ATTRIB_STORE_U32(max_unmap_lba_count);
-DEF_TB_DEV_ATTRIB_STORE_U32(max_unmap_block_desc_count);
-DEF_TB_DEV_ATTRIB_STORE_U32(unmap_granularity);
-DEF_TB_DEV_ATTRIB_STORE_U32(unmap_granularity_alignment);
-DEF_TB_DEV_ATTRIB_STORE_U32(max_write_same_len);
+DEF_CONFIGFS_ATTRIB_STORE_U32(max_unmap_lba_count);
+DEF_CONFIGFS_ATTRIB_STORE_U32(max_unmap_block_desc_count);
+DEF_CONFIGFS_ATTRIB_STORE_U32(unmap_granularity);
+DEF_CONFIGFS_ATTRIB_STORE_U32(unmap_granularity_alignment);
+DEF_CONFIGFS_ATTRIB_STORE_U32(max_write_same_len);
-#define DEF_TB_DEV_ATTRIB_STORE_BOOL(_name) \
-static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
+#define DEF_CONFIGFS_ATTRIB_STORE_BOOL(_name) \
+static ssize_t _name##_store(struct config_item *item, const char *page, \
size_t count) \
{ \
+ struct se_dev_attrib *da = to_attrib(item); \
bool flag; \
int ret; \
\
@@ -547,14 +537,14 @@ static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
return count; \
}
-DEF_TB_DEV_ATTRIB_STORE_BOOL(emulate_fua_write);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(emulate_caw);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(emulate_3pc);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(enforce_pr_isids);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(is_nonrot);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_fua_write);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_caw);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_3pc);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(enforce_pr_isids);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(is_nonrot);
-#define DEF_TB_DEV_ATTRIB_STORE_STUB(_name) \
-static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
+#define DEF_CONFIGFS_ATTRIB_STORE_STUB(_name) \
+static ssize_t _name##_store(struct config_item *item, const char *page,\
size_t count) \
{ \
printk_once(KERN_WARNING \
@@ -562,8 +552,8 @@ static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
return count; \
}
-DEF_TB_DEV_ATTRIB_STORE_STUB(emulate_dpo);
-DEF_TB_DEV_ATTRIB_STORE_STUB(emulate_fua_read);
+DEF_CONFIGFS_ATTRIB_STORE_STUB(emulate_dpo);
+DEF_CONFIGFS_ATTRIB_STORE_STUB(emulate_fua_read);
static void dev_set_t10_wwn_model_alias(struct se_device *dev)
{
@@ -578,9 +568,10 @@ static void dev_set_t10_wwn_model_alias(struct se_device *dev)
snprintf(&dev->t10_wwn.model[0], 16, "%s", configname);
}
-static ssize_t store_emulate_model_alias(struct se_dev_attrib *da,
+static ssize_t emulate_model_alias_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
struct se_device *dev = da->da_dev;
bool flag;
int ret;
@@ -606,9 +597,10 @@ static ssize_t store_emulate_model_alias(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_emulate_write_cache(struct se_dev_attrib *da,
+static ssize_t emulate_write_cache_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
bool flag;
int ret;
@@ -627,9 +619,10 @@ static ssize_t store_emulate_write_cache(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_emulate_ua_intlck_ctrl(struct se_dev_attrib *da,
+static ssize_t emulate_ua_intlck_ctrl_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
u32 val;
int ret;
@@ -654,9 +647,10 @@ static ssize_t store_emulate_ua_intlck_ctrl(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_emulate_tas(struct se_dev_attrib *da,
+static ssize_t emulate_tas_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
bool flag;
int ret;
@@ -677,9 +671,10 @@ static ssize_t store_emulate_tas(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_emulate_tpu(struct se_dev_attrib *da,
+static ssize_t emulate_tpu_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
bool flag;
int ret;
@@ -702,9 +697,10 @@ static ssize_t store_emulate_tpu(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_emulate_tpws(struct se_dev_attrib *da,
+static ssize_t emulate_tpws_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
bool flag;
int ret;
@@ -727,9 +723,10 @@ static ssize_t store_emulate_tpws(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_pi_prot_type(struct se_dev_attrib *da,
+static ssize_t pi_prot_type_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
int old_prot = da->pi_prot_type, ret;
struct se_device *dev = da->da_dev;
u32 flag;
@@ -787,9 +784,10 @@ static ssize_t store_pi_prot_type(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_pi_prot_format(struct se_dev_attrib *da,
+static ssize_t pi_prot_format_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
struct se_device *dev = da->da_dev;
bool flag;
int ret;
@@ -824,9 +822,10 @@ static ssize_t store_pi_prot_format(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_force_pr_aptpl(struct se_dev_attrib *da,
+static ssize_t force_pr_aptpl_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
bool flag;
int ret;
@@ -845,9 +844,10 @@ static ssize_t store_force_pr_aptpl(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_emulate_rest_reord(struct se_dev_attrib *da,
+static ssize_t emulate_rest_reord_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
bool flag;
int ret;
@@ -869,9 +869,10 @@ static ssize_t store_emulate_rest_reord(struct se_dev_attrib *da,
/*
* Note, this can only be called on unexported SE Device Object.
*/
-static ssize_t store_queue_depth(struct se_dev_attrib *da,
+static ssize_t queue_depth_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
struct se_device *dev = da->da_dev;
u32 val;
int ret;
@@ -905,9 +906,10 @@ static ssize_t store_queue_depth(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_optimal_sectors(struct se_dev_attrib *da,
+static ssize_t optimal_sectors_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
u32 val;
int ret;
@@ -934,9 +936,10 @@ static ssize_t store_optimal_sectors(struct se_dev_attrib *da,
return count;
}
-static ssize_t store_block_size(struct se_dev_attrib *da,
+static ssize_t block_size_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_dev_attrib *da = to_attrib(item);
u32 val;
int ret;
@@ -967,50 +970,35 @@ static ssize_t store_block_size(struct se_dev_attrib *da,
return count;
}
-CONFIGFS_EATTR_STRUCT(target_backend_dev_attrib, se_dev_attrib);
-#define TB_DEV_ATTR(_backend, _name, _mode) \
-static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- show_##_name, \
- store_##_name);
-
-#define TB_DEV_ATTR_RO(_backend, _name) \
-static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- show_##_name);
-
-TB_DEV_ATTR(target_core, emulate_model_alias, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_dpo, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_fua_write, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_fua_read, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_write_cache, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_ua_intlck_ctrl, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_tas, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_tpu, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_tpws, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_caw, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_3pc, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, pi_prot_type, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR_RO(target_core, hw_pi_prot_type);
-TB_DEV_ATTR(target_core, pi_prot_format, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, enforce_pr_isids, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, is_nonrot, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_rest_reord, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, force_pr_aptpl, S_IRUGO | S_IWUSR)
-TB_DEV_ATTR_RO(target_core, hw_block_size);
-TB_DEV_ATTR(target_core, block_size, S_IRUGO | S_IWUSR)
-TB_DEV_ATTR_RO(target_core, hw_max_sectors);
-TB_DEV_ATTR(target_core, optimal_sectors, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR_RO(target_core, hw_queue_depth);
-TB_DEV_ATTR(target_core, queue_depth, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, max_unmap_lba_count, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, max_unmap_block_desc_count, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, unmap_granularity, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, unmap_granularity_alignment, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, max_write_same_len, S_IRUGO | S_IWUSR);
-
-CONFIGFS_EATTR_STRUCT(target_core_dev_attrib, se_dev_attrib);
-CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
+CONFIGFS_ATTR(, emulate_model_alias);
+CONFIGFS_ATTR(, emulate_dpo);
+CONFIGFS_ATTR(, emulate_fua_write);
+CONFIGFS_ATTR(, emulate_fua_read);
+CONFIGFS_ATTR(, emulate_write_cache);
+CONFIGFS_ATTR(, emulate_ua_intlck_ctrl);
+CONFIGFS_ATTR(, emulate_tas);
+CONFIGFS_ATTR(, emulate_tpu);
+CONFIGFS_ATTR(, emulate_tpws);
+CONFIGFS_ATTR(, emulate_caw);
+CONFIGFS_ATTR(, emulate_3pc);
+CONFIGFS_ATTR(, pi_prot_type);
+CONFIGFS_ATTR_RO(, hw_pi_prot_type);
+CONFIGFS_ATTR(, pi_prot_format);
+CONFIGFS_ATTR(, enforce_pr_isids);
+CONFIGFS_ATTR(, is_nonrot);
+CONFIGFS_ATTR(, emulate_rest_reord);
+CONFIGFS_ATTR(, force_pr_aptpl);
+CONFIGFS_ATTR_RO(, hw_block_size);
+CONFIGFS_ATTR(, block_size);
+CONFIGFS_ATTR_RO(, hw_max_sectors);
+CONFIGFS_ATTR(, optimal_sectors);
+CONFIGFS_ATTR_RO(, hw_queue_depth);
+CONFIGFS_ATTR(, queue_depth);
+CONFIGFS_ATTR(, max_unmap_lba_count);
+CONFIGFS_ATTR(, max_unmap_block_desc_count);
+CONFIGFS_ATTR(, unmap_granularity);
+CONFIGFS_ATTR(, unmap_granularity_alignment);
+CONFIGFS_ATTR(, max_write_same_len);
/*
* dev_attrib attributes for devices using the target core SBC/SPC
@@ -1018,100 +1006,78 @@ CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
* these.
*/
struct configfs_attribute *sbc_attrib_attrs[] = {
- &target_core_dev_attrib_emulate_model_alias.attr,
- &target_core_dev_attrib_emulate_dpo.attr,
- &target_core_dev_attrib_emulate_fua_write.attr,
- &target_core_dev_attrib_emulate_fua_read.attr,
- &target_core_dev_attrib_emulate_write_cache.attr,
- &target_core_dev_attrib_emulate_ua_intlck_ctrl.attr,
- &target_core_dev_attrib_emulate_tas.attr,
- &target_core_dev_attrib_emulate_tpu.attr,
- &target_core_dev_attrib_emulate_tpws.attr,
- &target_core_dev_attrib_emulate_caw.attr,
- &target_core_dev_attrib_emulate_3pc.attr,
- &target_core_dev_attrib_pi_prot_type.attr,
- &target_core_dev_attrib_hw_pi_prot_type.attr,
- &target_core_dev_attrib_pi_prot_format.attr,
- &target_core_dev_attrib_enforce_pr_isids.attr,
- &target_core_dev_attrib_is_nonrot.attr,
- &target_core_dev_attrib_emulate_rest_reord.attr,
- &target_core_dev_attrib_force_pr_aptpl.attr,
- &target_core_dev_attrib_hw_block_size.attr,
- &target_core_dev_attrib_block_size.attr,
- &target_core_dev_attrib_hw_max_sectors.attr,
- &target_core_dev_attrib_optimal_sectors.attr,
- &target_core_dev_attrib_hw_queue_depth.attr,
- &target_core_dev_attrib_queue_depth.attr,
- &target_core_dev_attrib_max_unmap_lba_count.attr,
- &target_core_dev_attrib_max_unmap_block_desc_count.attr,
- &target_core_dev_attrib_unmap_granularity.attr,
- &target_core_dev_attrib_unmap_granularity_alignment.attr,
- &target_core_dev_attrib_max_write_same_len.attr,
+ &attr_emulate_model_alias,
+ &attr_emulate_dpo,
+ &attr_emulate_fua_write,
+ &attr_emulate_fua_read,
+ &attr_emulate_write_cache,
+ &attr_emulate_ua_intlck_ctrl,
+ &attr_emulate_tas,
+ &attr_emulate_tpu,
+ &attr_emulate_tpws,
+ &attr_emulate_caw,
+ &attr_emulate_3pc,
+ &attr_pi_prot_type,
+ &attr_hw_pi_prot_type,
+ &attr_pi_prot_format,
+ &attr_enforce_pr_isids,
+ &attr_is_nonrot,
+ &attr_emulate_rest_reord,
+ &attr_force_pr_aptpl,
+ &attr_hw_block_size,
+ &attr_block_size,
+ &attr_hw_max_sectors,
+ &attr_optimal_sectors,
+ &attr_hw_queue_depth,
+ &attr_queue_depth,
+ &attr_max_unmap_lba_count,
+ &attr_max_unmap_block_desc_count,
+ &attr_unmap_granularity,
+ &attr_unmap_granularity_alignment,
+ &attr_max_write_same_len,
NULL,
};
EXPORT_SYMBOL(sbc_attrib_attrs);
-TB_DEV_ATTR_RO(target_pt, hw_pi_prot_type);
-TB_DEV_ATTR_RO(target_pt, hw_block_size);
-TB_DEV_ATTR_RO(target_pt, hw_max_sectors);
-TB_DEV_ATTR_RO(target_pt, hw_queue_depth);
-
/*
* Minimal dev_attrib attributes for devices passing through CDBs.
* In this case we only provide a few read-only attributes for
* backwards compatibility.
*/
struct configfs_attribute *passthrough_attrib_attrs[] = {
- &target_pt_dev_attrib_hw_pi_prot_type.attr,
- &target_pt_dev_attrib_hw_block_size.attr,
- &target_pt_dev_attrib_hw_max_sectors.attr,
- &target_pt_dev_attrib_hw_queue_depth.attr,
+ &attr_hw_pi_prot_type,
+ &attr_hw_block_size,
+ &attr_hw_max_sectors,
+ &attr_hw_queue_depth,
NULL,
};
EXPORT_SYMBOL(passthrough_attrib_attrs);
-static struct configfs_item_operations target_core_dev_attrib_ops = {
- .show_attribute = target_core_dev_attrib_attr_show,
- .store_attribute = target_core_dev_attrib_attr_store,
-};
-
-TB_CIT_SETUP_DRV(dev_attrib, &target_core_dev_attrib_ops, NULL);
+TB_CIT_SETUP_DRV(dev_attrib, NULL, NULL);
/* End functions for struct config_item_type tb_dev_attrib_cit */
/* Start functions for struct config_item_type tb_dev_wwn_cit */
-CONFIGFS_EATTR_STRUCT(target_core_dev_wwn, t10_wwn);
-#define SE_DEV_WWN_ATTR(_name, _mode) \
-static struct target_core_dev_wwn_attribute target_core_dev_wwn_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_core_dev_wwn_show_attr_##_name, \
- target_core_dev_wwn_store_attr_##_name);
-
-#define SE_DEV_WWN_ATTR_RO(_name); \
-do { \
- static struct target_core_dev_wwn_attribute \
- target_core_dev_wwn_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_core_dev_wwn_show_attr_##_name); \
-} while (0);
+static struct t10_wwn *to_t10_wwn(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct t10_wwn, t10_wwn_group);
+}
/*
* VPD page 0x80 Unit serial
*/
-static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial(
- struct t10_wwn *t10_wwn,
- char *page)
+static ssize_t target_wwn_vpd_unit_serial_show(struct config_item *item,
+ char *page)
{
return sprintf(page, "T10 VPD Unit Serial Number: %s\n",
- &t10_wwn->unit_serial[0]);
+ &to_t10_wwn(item)->unit_serial[0]);
}
-static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
- struct t10_wwn *t10_wwn,
- const char *page,
- size_t count)
+static ssize_t target_wwn_vpd_unit_serial_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct t10_wwn *t10_wwn = to_t10_wwn(item);
struct se_device *dev = t10_wwn->t10_dev;
unsigned char buf[INQUIRY_VPD_SERIAL_LEN];
@@ -1167,15 +1133,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
return count;
}
-SE_DEV_WWN_ATTR(vpd_unit_serial, S_IRUGO | S_IWUSR);
-
/*
* VPD page 0x83 Protocol Identifier
*/
-static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
- struct t10_wwn *t10_wwn,
- char *page)
+static ssize_t target_wwn_vpd_protocol_identifier_show(struct config_item *item,
+ char *page)
{
+ struct t10_wwn *t10_wwn = to_t10_wwn(item);
struct t10_vpd *vpd;
unsigned char buf[VPD_TMP_BUF_SIZE];
ssize_t len = 0;
@@ -1199,25 +1163,15 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
return len;
}
-static ssize_t target_core_dev_wwn_store_attr_vpd_protocol_identifier(
- struct t10_wwn *t10_wwn,
- const char *page,
- size_t count)
-{
- return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_protocol_identifier, S_IRUGO | S_IWUSR);
-
/*
* Generic wrapper for dumping VPD identifiers by association.
*/
#define DEF_DEV_WWN_ASSOC_SHOW(_name, _assoc) \
-static ssize_t target_core_dev_wwn_show_attr_##_name( \
- struct t10_wwn *t10_wwn, \
- char *page) \
+static ssize_t target_wwn_##_name##_show(struct config_item *item, \
+ char *page) \
{ \
- struct t10_vpd *vpd; \
+ struct t10_wwn *t10_wwn = to_t10_wwn(item); \
+ struct t10_vpd *vpd; \
unsigned char buf[VPD_TMP_BUF_SIZE]; \
ssize_t len = 0; \
\
@@ -1249,84 +1203,39 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \
return len; \
}
-/*
- * VPD page 0x83 Association: Logical Unit
- */
+/* VPD page 0x83 Association: Logical Unit */
DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_logical_unit, 0x00);
-
-static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_logical_unit(
- struct t10_wwn *t10_wwn,
- const char *page,
- size_t count)
-{
- return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_assoc_logical_unit, S_IRUGO | S_IWUSR);
-
-/*
- * VPD page 0x83 Association: Target Port
- */
+/* VPD page 0x83 Association: Target Port */
DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_target_port, 0x10);
-
-static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_target_port(
- struct t10_wwn *t10_wwn,
- const char *page,
- size_t count)
-{
- return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_assoc_target_port, S_IRUGO | S_IWUSR);
-
-/*
- * VPD page 0x83 Association: SCSI Target Device
- */
+/* VPD page 0x83 Association: SCSI Target Device */
DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_scsi_target_device, 0x20);
-static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_scsi_target_device(
- struct t10_wwn *t10_wwn,
- const char *page,
- size_t count)
-{
- return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_assoc_scsi_target_device, S_IRUGO | S_IWUSR);
-
-CONFIGFS_EATTR_OPS(target_core_dev_wwn, t10_wwn, t10_wwn_group);
+CONFIGFS_ATTR(target_wwn_, vpd_unit_serial);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_protocol_identifier);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_logical_unit);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_target_port);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_scsi_target_device);
static struct configfs_attribute *target_core_dev_wwn_attrs[] = {
- &target_core_dev_wwn_vpd_unit_serial.attr,
- &target_core_dev_wwn_vpd_protocol_identifier.attr,
- &target_core_dev_wwn_vpd_assoc_logical_unit.attr,
- &target_core_dev_wwn_vpd_assoc_target_port.attr,
- &target_core_dev_wwn_vpd_assoc_scsi_target_device.attr,
+ &target_wwn_attr_vpd_unit_serial,
+ &target_wwn_attr_vpd_protocol_identifier,
+ &target_wwn_attr_vpd_assoc_logical_unit,
+ &target_wwn_attr_vpd_assoc_target_port,
+ &target_wwn_attr_vpd_assoc_scsi_target_device,
NULL,
};
-static struct configfs_item_operations target_core_dev_wwn_ops = {
- .show_attribute = target_core_dev_wwn_attr_show,
- .store_attribute = target_core_dev_wwn_attr_store,
-};
-
-TB_CIT_SETUP(dev_wwn, &target_core_dev_wwn_ops, NULL, target_core_dev_wwn_attrs);
+TB_CIT_SETUP(dev_wwn, NULL, NULL, target_core_dev_wwn_attrs);
/* End functions for struct config_item_type tb_dev_wwn_cit */
/* Start functions for struct config_item_type tb_dev_pr_cit */
-CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device);
-#define SE_DEV_PR_ATTR(_name, _mode) \
-static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_core_dev_pr_show_attr_##_name, \
- target_core_dev_pr_store_attr_##_name);
-
-#define SE_DEV_PR_ATTR_RO(_name); \
-static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_core_dev_pr_show_attr_##_name);
+static struct se_device *pr_to_dev(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct se_device,
+ dev_pr_group);
+}
static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev,
char *page)
@@ -1367,9 +1276,9 @@ static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev,
return len;
}
-static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
- char *page)
+static ssize_t target_pr_res_holder_show(struct config_item *item, char *page)
{
+ struct se_device *dev = pr_to_dev(item);
int ret;
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
@@ -1384,11 +1293,10 @@ static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
return ret;
}
-SE_DEV_PR_ATTR_RO(res_holder);
-
-static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_all_tgt_pts_show(struct config_item *item,
+ char *page)
{
+ struct se_device *dev = pr_to_dev(item);
ssize_t len = 0;
spin_lock(&dev->dev_reservation_lock);
@@ -1406,22 +1314,17 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
return len;
}
-SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts);
-
-static ssize_t target_core_dev_pr_show_attr_res_pr_generation(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_generation_show(struct config_item *item,
+ char *page)
{
- return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation);
+ return sprintf(page, "0x%08x\n", pr_to_dev(item)->t10_pr.pr_generation);
}
-SE_DEV_PR_ATTR_RO(res_pr_generation);
-/*
- * res_pr_holder_tg_port
- */
-static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_holder_tg_port_show(struct config_item *item,
+ char *page)
{
+ struct se_device *dev = pr_to_dev(item);
struct se_node_acl *se_nacl;
struct se_portal_group *se_tpg;
struct t10_pr_registration *pr_reg;
@@ -1453,11 +1356,11 @@ out_unlock:
return len;
}
-SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port);
-static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_registered_i_pts_show(struct config_item *item,
+ char *page)
{
+ struct se_device *dev = pr_to_dev(item);
const struct target_core_fabric_ops *tfo;
struct t10_pr_registration *pr_reg;
unsigned char buf[384];
@@ -1495,11 +1398,9 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
return len;
}
-SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts);
-
-static ssize_t target_core_dev_pr_show_attr_res_pr_type(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_type_show(struct config_item *item, char *page)
{
+ struct se_device *dev = pr_to_dev(item);
struct t10_pr_registration *pr_reg;
ssize_t len = 0;
@@ -1516,11 +1417,10 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type(
return len;
}
-SE_DEV_PR_ATTR_RO(res_pr_type);
-
-static ssize_t target_core_dev_pr_show_attr_res_type(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_type_show(struct config_item *item, char *page)
{
+ struct se_device *dev = pr_to_dev(item);
+
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return sprintf(page, "SPC_PASSTHROUGH\n");
else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
@@ -1529,11 +1429,11 @@ static ssize_t target_core_dev_pr_show_attr_res_type(
return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
}
-SE_DEV_PR_ATTR_RO(res_type);
-
-static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
+ char *page)
{
+ struct se_device *dev = pr_to_dev(item);
+
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0;
@@ -1541,14 +1441,11 @@ static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
(dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled");
}
-SE_DEV_PR_ATTR_RO(res_aptpl_active);
-
-/*
- * res_aptpl_metadata
- */
-static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
- struct se_device *dev, char *page)
+static ssize_t target_pr_res_aptpl_metadata_show(struct config_item *item,
+ char *page)
{
+ struct se_device *dev = pr_to_dev(item);
+
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0;
@@ -1580,11 +1477,10 @@ static match_table_t tokens = {
{Opt_err, NULL}
};
-static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
- struct se_device *dev,
- const char *page,
- size_t count)
+static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_device *dev = pr_to_dev(item);
unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL;
unsigned char *t_fabric = NULL, *t_port = NULL;
char *orig, *ptr, *opts;
@@ -1765,37 +1661,44 @@ out:
return (ret == 0) ? count : ret;
}
-SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR);
-CONFIGFS_EATTR_OPS(target_core_dev_pr, se_device, dev_pr_group);
+CONFIGFS_ATTR_RO(target_pr_, res_holder);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_all_tgt_pts);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_generation);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_holder_tg_port);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_registered_i_pts);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_type);
+CONFIGFS_ATTR_RO(target_pr_, res_type);
+CONFIGFS_ATTR_RO(target_pr_, res_aptpl_active);
+CONFIGFS_ATTR(target_pr_, res_aptpl_metadata);
static struct configfs_attribute *target_core_dev_pr_attrs[] = {
- &target_core_dev_pr_res_holder.attr,
- &target_core_dev_pr_res_pr_all_tgt_pts.attr,
- &target_core_dev_pr_res_pr_generation.attr,
- &target_core_dev_pr_res_pr_holder_tg_port.attr,
- &target_core_dev_pr_res_pr_registered_i_pts.attr,
- &target_core_dev_pr_res_pr_type.attr,
- &target_core_dev_pr_res_type.attr,
- &target_core_dev_pr_res_aptpl_active.attr,
- &target_core_dev_pr_res_aptpl_metadata.attr,
+ &target_pr_attr_res_holder,
+ &target_pr_attr_res_pr_all_tgt_pts,
+ &target_pr_attr_res_pr_generation,
+ &target_pr_attr_res_pr_holder_tg_port,
+ &target_pr_attr_res_pr_registered_i_pts,
+ &target_pr_attr_res_pr_type,
+ &target_pr_attr_res_type,
+ &target_pr_attr_res_aptpl_active,
+ &target_pr_attr_res_aptpl_metadata,
NULL,
};
-static struct configfs_item_operations target_core_dev_pr_ops = {
- .show_attribute = target_core_dev_pr_attr_show,
- .store_attribute = target_core_dev_pr_attr_store,
-};
-
-TB_CIT_SETUP(dev_pr, &target_core_dev_pr_ops, NULL, target_core_dev_pr_attrs);
+TB_CIT_SETUP(dev_pr, NULL, NULL, target_core_dev_pr_attrs);
/* End functions for struct config_item_type tb_dev_pr_cit */
/* Start functions for struct config_item_type tb_dev_cit */
-static ssize_t target_core_show_dev_info(void *p, char *page)
+static inline struct se_device *to_device(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct se_device, dev_group);
+}
+
+static ssize_t target_dev_info_show(struct config_item *item, char *page)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
int bl = 0;
ssize_t read_bytes = 0;
@@ -1806,35 +1709,17 @@ static ssize_t target_core_show_dev_info(void *p, char *page)
return read_bytes;
}
-static struct target_core_configfs_attribute target_core_attr_dev_info = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "info",
- .ca_mode = S_IRUGO },
- .show = target_core_show_dev_info,
- .store = NULL,
-};
-
-static ssize_t target_core_store_dev_control(
- void *p,
- const char *page,
- size_t count)
+static ssize_t target_dev_control_store(struct config_item *item,
+ const char *page, size_t count)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
return dev->transport->set_configfs_dev_params(dev, page, count);
}
-static struct target_core_configfs_attribute target_core_attr_dev_control = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "control",
- .ca_mode = S_IWUSR },
- .show = NULL,
- .store = target_core_store_dev_control,
-};
-
-static ssize_t target_core_show_dev_alias(void *p, char *page)
+static ssize_t target_dev_alias_show(struct config_item *item, char *page)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
if (!(dev->dev_flags & DF_USING_ALIAS))
return 0;
@@ -1842,12 +1727,10 @@ static ssize_t target_core_show_dev_alias(void *p, char *page)
return snprintf(page, PAGE_SIZE, "%s\n", dev->dev_alias);
}
-static ssize_t target_core_store_dev_alias(
- void *p,
- const char *page,
- size_t count)
+static ssize_t target_dev_alias_store(struct config_item *item,
+ const char *page, size_t count)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
struct se_hba *hba = dev->se_hba;
ssize_t read_bytes;
@@ -1874,17 +1757,9 @@ static ssize_t target_core_store_dev_alias(
return read_bytes;
}
-static struct target_core_configfs_attribute target_core_attr_dev_alias = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "alias",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = target_core_show_dev_alias,
- .store = target_core_store_dev_alias,
-};
-
-static ssize_t target_core_show_dev_udev_path(void *p, char *page)
+static ssize_t target_dev_udev_path_show(struct config_item *item, char *page)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
if (!(dev->dev_flags & DF_USING_UDEV_PATH))
return 0;
@@ -1892,12 +1767,10 @@ static ssize_t target_core_show_dev_udev_path(void *p, char *page)
return snprintf(page, PAGE_SIZE, "%s\n", dev->udev_path);
}
-static ssize_t target_core_store_dev_udev_path(
- void *p,
- const char *page,
- size_t count)
+static ssize_t target_dev_udev_path_store(struct config_item *item,
+ const char *page, size_t count)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
struct se_hba *hba = dev->se_hba;
ssize_t read_bytes;
@@ -1925,27 +1798,17 @@ static ssize_t target_core_store_dev_udev_path(
return read_bytes;
}
-static struct target_core_configfs_attribute target_core_attr_dev_udev_path = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "udev_path",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = target_core_show_dev_udev_path,
- .store = target_core_store_dev_udev_path,
-};
-
-static ssize_t target_core_show_dev_enable(void *p, char *page)
+static ssize_t target_dev_enable_show(struct config_item *item, char *page)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
return snprintf(page, PAGE_SIZE, "%d\n", !!(dev->dev_flags & DF_CONFIGURED));
}
-static ssize_t target_core_store_dev_enable(
- void *p,
- const char *page,
- size_t count)
+static ssize_t target_dev_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
char *ptr;
int ret;
@@ -1962,17 +1825,9 @@ static ssize_t target_core_store_dev_enable(
return count;
}
-static struct target_core_configfs_attribute target_core_attr_dev_enable = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "enable",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = target_core_show_dev_enable,
- .store = target_core_store_dev_enable,
-};
-
-static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
+static ssize_t target_dev_alua_lu_gp_show(struct config_item *item, char *page)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
struct config_item *lu_ci;
struct t10_alua_lu_gp *lu_gp;
struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -1994,12 +1849,10 @@ static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
return len;
}
-static ssize_t target_core_store_alua_lu_gp(
- void *p,
- const char *page,
- size_t count)
+static ssize_t target_dev_alua_lu_gp_store(struct config_item *item,
+ const char *page, size_t count)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
struct se_hba *hba = dev->se_hba;
struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL;
struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -2076,17 +1929,9 @@ static ssize_t target_core_store_alua_lu_gp(
return count;
}
-static struct target_core_configfs_attribute target_core_attr_dev_alua_lu_gp = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "alua_lu_gp",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = target_core_show_alua_lu_gp,
- .store = target_core_store_alua_lu_gp,
-};
-
-static ssize_t target_core_show_dev_lba_map(void *p, char *page)
+static ssize_t target_dev_lba_map_show(struct config_item *item, char *page)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
struct t10_alua_lba_map *map;
struct t10_alua_lba_map_member *mem;
char *b = page;
@@ -2129,12 +1974,10 @@ static ssize_t target_core_show_dev_lba_map(void *p, char *page)
return bl;
}
-static ssize_t target_core_store_dev_lba_map(
- void *p,
- const char *page,
- size_t count)
+static ssize_t target_dev_lba_map_store(struct config_item *item,
+ const char *page, size_t count)
{
- struct se_device *dev = p;
+ struct se_device *dev = to_device(item);
struct t10_alua_lba_map *lba_map = NULL;
struct list_head lba_list;
char *map_entries, *ptr;
@@ -2246,22 +2089,22 @@ out:
return count;
}
-static struct target_core_configfs_attribute target_core_attr_dev_lba_map = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "lba_map",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = target_core_show_dev_lba_map,
- .store = target_core_store_dev_lba_map,
-};
+CONFIGFS_ATTR_RO(target_dev_, info);
+CONFIGFS_ATTR_WO(target_dev_, control);
+CONFIGFS_ATTR(target_dev_, alias);
+CONFIGFS_ATTR(target_dev_, udev_path);
+CONFIGFS_ATTR(target_dev_, enable);
+CONFIGFS_ATTR(target_dev_, alua_lu_gp);
+CONFIGFS_ATTR(target_dev_, lba_map);
static struct configfs_attribute *target_core_dev_attrs[] = {
- &target_core_attr_dev_info.attr,
- &target_core_attr_dev_control.attr,
- &target_core_attr_dev_alias.attr,
- &target_core_attr_dev_udev_path.attr,
- &target_core_attr_dev_enable.attr,
- &target_core_attr_dev_alua_lu_gp.attr,
- &target_core_attr_dev_lba_map.attr,
+ &target_dev_attr_info,
+ &target_dev_attr_control,
+ &target_dev_attr_alias,
+ &target_dev_attr_udev_path,
+ &target_dev_attr_enable,
+ &target_dev_attr_alua_lu_gp,
+ &target_dev_attr_lba_map,
NULL,
};
@@ -2275,42 +2118,8 @@ static void target_core_dev_release(struct config_item *item)
target_free_device(dev);
}
-static ssize_t target_core_dev_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct config_group *dev_cg = to_config_group(item);
- struct se_device *dev =
- container_of(dev_cg, struct se_device, dev_group);
- struct target_core_configfs_attribute *tc_attr = container_of(
- attr, struct target_core_configfs_attribute, attr);
-
- if (!tc_attr->show)
- return -EINVAL;
-
- return tc_attr->show(dev, page);
-}
-
-static ssize_t target_core_dev_store(struct config_item *item,
- struct configfs_attribute *attr,
- const char *page, size_t count)
-{
- struct config_group *dev_cg = to_config_group(item);
- struct se_device *dev =
- container_of(dev_cg, struct se_device, dev_group);
- struct target_core_configfs_attribute *tc_attr = container_of(
- attr, struct target_core_configfs_attribute, attr);
-
- if (!tc_attr->store)
- return -EINVAL;
-
- return tc_attr->store(dev, page, count);
-}
-
static struct configfs_item_operations target_core_dev_item_ops = {
.release = target_core_dev_release,
- .show_attribute = target_core_dev_show,
- .store_attribute = target_core_dev_store,
};
TB_CIT_SETUP(dev, &target_core_dev_item_ops, NULL, target_core_dev_attrs);
@@ -2319,38 +2128,25 @@ TB_CIT_SETUP(dev, &target_core_dev_item_ops, NULL, target_core_dev_attrs);
/* Start functions for struct config_item_type target_core_alua_lu_gp_cit */
-CONFIGFS_EATTR_STRUCT(target_core_alua_lu_gp, t10_alua_lu_gp);
-#define SE_DEV_ALUA_LU_ATTR(_name, _mode) \
-static struct target_core_alua_lu_gp_attribute \
- target_core_alua_lu_gp_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_core_alua_lu_gp_show_attr_##_name, \
- target_core_alua_lu_gp_store_attr_##_name);
-
-#define SE_DEV_ALUA_LU_ATTR_RO(_name) \
-static struct target_core_alua_lu_gp_attribute \
- target_core_alua_lu_gp_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_core_alua_lu_gp_show_attr_##_name);
+static inline struct t10_alua_lu_gp *to_lu_gp(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct t10_alua_lu_gp,
+ lu_gp_group);
+}
-/*
- * lu_gp_id
- */
-static ssize_t target_core_alua_lu_gp_show_attr_lu_gp_id(
- struct t10_alua_lu_gp *lu_gp,
- char *page)
+static ssize_t target_lu_gp_lu_gp_id_show(struct config_item *item, char *page)
{
+ struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
+
if (!lu_gp->lu_gp_valid_id)
return 0;
-
return sprintf(page, "%hu\n", lu_gp->lu_gp_id);
}
-static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id(
- struct t10_alua_lu_gp *lu_gp,
- const char *page,
- size_t count)
+static ssize_t target_lu_gp_lu_gp_id_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
struct config_group *alua_lu_gp_cg = &lu_gp->lu_gp_group;
unsigned long lu_gp_id;
int ret;
@@ -2379,15 +2175,9 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id(
return count;
}
-SE_DEV_ALUA_LU_ATTR(lu_gp_id, S_IRUGO | S_IWUSR);
-
-/*
- * members
- */
-static ssize_t target_core_alua_lu_gp_show_attr_members(
- struct t10_alua_lu_gp *lu_gp,
- char *page)
+static ssize_t target_lu_gp_members_show(struct config_item *item, char *page)
{
+ struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
struct se_device *dev;
struct se_hba *hba;
struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -2419,13 +2209,12 @@ static ssize_t target_core_alua_lu_gp_show_attr_members(
return len;
}
-SE_DEV_ALUA_LU_ATTR_RO(members);
-
-CONFIGFS_EATTR_OPS(target_core_alua_lu_gp, t10_alua_lu_gp, lu_gp_group);
+CONFIGFS_ATTR(target_lu_gp_, lu_gp_id);
+CONFIGFS_ATTR_RO(target_lu_gp_, members);
static struct configfs_attribute *target_core_alua_lu_gp_attrs[] = {
- &target_core_alua_lu_gp_lu_gp_id.attr,
- &target_core_alua_lu_gp_members.attr,
+ &target_lu_gp_attr_lu_gp_id,
+ &target_lu_gp_attr_members,
NULL,
};
@@ -2439,8 +2228,6 @@ static void target_core_alua_lu_gp_release(struct config_item *item)
static struct configfs_item_operations target_core_alua_lu_gp_ops = {
.release = target_core_alua_lu_gp_release,
- .show_attribute = target_core_alua_lu_gp_attr_show,
- .store_attribute = target_core_alua_lu_gp_attr_store,
};
static struct config_item_type target_core_alua_lu_gp_cit = {
@@ -2511,36 +2298,23 @@ static struct config_item_type target_core_alua_lu_gps_cit = {
/* Start functions for struct config_item_type target_core_alua_tg_pt_gp_cit */
-CONFIGFS_EATTR_STRUCT(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp);
-#define SE_DEV_ALUA_TG_PT_ATTR(_name, _mode) \
-static struct target_core_alua_tg_pt_gp_attribute \
- target_core_alua_tg_pt_gp_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_core_alua_tg_pt_gp_show_attr_##_name, \
- target_core_alua_tg_pt_gp_store_attr_##_name);
-
-#define SE_DEV_ALUA_TG_PT_ATTR_RO(_name) \
-static struct target_core_alua_tg_pt_gp_attribute \
- target_core_alua_tg_pt_gp_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_core_alua_tg_pt_gp_show_attr_##_name);
+static inline struct t10_alua_tg_pt_gp *to_tg_pt_gp(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct t10_alua_tg_pt_gp,
+ tg_pt_gp_group);
+}
-/*
- * alua_access_state
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_state(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_alua_access_state_show(struct config_item *item,
+ char *page)
{
return sprintf(page, "%d\n",
- atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state));
+ atomic_read(&to_tg_pt_gp(item)->tg_pt_gp_alua_access_state));
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_alua_access_state_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
unsigned long tmp;
int new_state, ret;
@@ -2582,24 +2356,18 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
return (!ret) ? count : -EINVAL;
}
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_state, S_IRUGO | S_IWUSR);
-
-/*
- * alua_access_status
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_status(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_alua_access_status_show(struct config_item *item,
+ char *page)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
return sprintf(page, "%s\n",
core_alua_dump_status(tg_pt_gp->tg_pt_gp_alua_access_status));
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_alua_access_status_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
unsigned long tmp;
int new_status, ret;
@@ -2630,43 +2398,31 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
return count;
}
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_status, S_IRUGO | S_IWUSR);
-
-/*
- * alua_access_type
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_type(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_alua_access_type_show(struct config_item *item,
+ char *page)
{
- return core_alua_show_access_type(tg_pt_gp, page);
+ return core_alua_show_access_type(to_tg_pt_gp(item), page);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_alua_access_type_store(struct config_item *item,
+ const char *page, size_t count)
{
- return core_alua_store_access_type(tg_pt_gp, page, count);
+ return core_alua_store_access_type(to_tg_pt_gp(item), page, count);
}
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
-
-/*
- * alua_supported_states
- */
-
-#define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit) \
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_support_##_name( \
- struct t10_alua_tg_pt_gp *t, char *p) \
+#define ALUA_SUPPORTED_STATE_ATTR(_name, _bit) \
+static ssize_t target_tg_pt_gp_alua_support_##_name##_show( \
+ struct config_item *item, char *p) \
{ \
- return sprintf(p, "%d\n", !!(t->_var & _bit)); \
-}
-
-#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit) \
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
- struct t10_alua_tg_pt_gp *t, const char *p, size_t c) \
+ struct t10_alua_tg_pt_gp *t = to_tg_pt_gp(item); \
+ return sprintf(p, "%d\n", \
+ !!(t->tg_pt_gp_alua_supported_states & _bit)); \
+} \
+ \
+static ssize_t target_tg_pt_gp_alua_support_##_name##_store( \
+ struct config_item *item, const char *p, size_t c) \
{ \
+ struct t10_alua_tg_pt_gp *t = to_tg_pt_gp(item); \
unsigned long tmp; \
int ret; \
\
@@ -2687,70 +2443,32 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
return -EINVAL; \
} \
if (tmp) \
- t->_var |= _bit; \
+ t->tg_pt_gp_alua_supported_states |= _bit; \
else \
- t->_var &= ~_bit; \
+ t->tg_pt_gp_alua_supported_states &= ~_bit; \
\
return c; \
}
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(transitioning,
- tg_pt_gp_alua_supported_states, ALUA_T_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(transitioning,
- tg_pt_gp_alua_supported_states, ALUA_T_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_transitioning, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(offline,
- tg_pt_gp_alua_supported_states, ALUA_O_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(offline,
- tg_pt_gp_alua_supported_states, ALUA_O_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_offline, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent,
- tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent,
- tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable,
- tg_pt_gp_alua_supported_states, ALUA_U_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(unavailable,
- tg_pt_gp_alua_supported_states, ALUA_U_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_unavailable, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(standby,
- tg_pt_gp_alua_supported_states, ALUA_S_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(standby,
- tg_pt_gp_alua_supported_states, ALUA_S_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_standby, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_optimized,
- tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(active_optimized,
- tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_optimized, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_nonoptimized,
- tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(active_nonoptimized,
- tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_nonoptimized, S_IRUGO | S_IWUSR);
+ALUA_SUPPORTED_STATE_ATTR(transitioning, ALUA_T_SUP);
+ALUA_SUPPORTED_STATE_ATTR(offline, ALUA_O_SUP);
+ALUA_SUPPORTED_STATE_ATTR(lba_dependent, ALUA_LBD_SUP);
+ALUA_SUPPORTED_STATE_ATTR(unavailable, ALUA_U_SUP);
+ALUA_SUPPORTED_STATE_ATTR(standby, ALUA_S_SUP);
+ALUA_SUPPORTED_STATE_ATTR(active_optimized, ALUA_AO_SUP);
+ALUA_SUPPORTED_STATE_ATTR(active_nonoptimized, ALUA_AN_SUP);
-/*
- * alua_write_metadata
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_alua_write_metadata_show(
+ struct config_item *item, char *page)
{
- return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_write_metadata);
+ return sprintf(page, "%d\n",
+ to_tg_pt_gp(item)->tg_pt_gp_write_metadata);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_alua_write_metadata_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
unsigned long tmp;
int ret;
@@ -2770,110 +2488,71 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata(
return count;
}
-SE_DEV_ALUA_TG_PT_ATTR(alua_write_metadata, S_IRUGO | S_IWUSR);
-
-
-
-/*
- * nonop_delay_msecs
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_nonop_delay_msecs(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_nonop_delay_msecs_show(struct config_item *item,
+ char *page)
{
- return core_alua_show_nonop_delay_msecs(tg_pt_gp, page);
-
+ return core_alua_show_nonop_delay_msecs(to_tg_pt_gp(item), page);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_nonop_delay_msecs(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_nonop_delay_msecs_store(struct config_item *item,
+ const char *page, size_t count)
{
- return core_alua_store_nonop_delay_msecs(tg_pt_gp, page, count);
+ return core_alua_store_nonop_delay_msecs(to_tg_pt_gp(item), page,
+ count);
}
-SE_DEV_ALUA_TG_PT_ATTR(nonop_delay_msecs, S_IRUGO | S_IWUSR);
-
-/*
- * trans_delay_msecs
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_trans_delay_msecs(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_trans_delay_msecs_show(struct config_item *item,
+ char *page)
{
- return core_alua_show_trans_delay_msecs(tg_pt_gp, page);
+ return core_alua_show_trans_delay_msecs(to_tg_pt_gp(item), page);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_trans_delay_msecs_store(struct config_item *item,
+ const char *page, size_t count)
{
- return core_alua_store_trans_delay_msecs(tg_pt_gp, page, count);
+ return core_alua_store_trans_delay_msecs(to_tg_pt_gp(item), page,
+ count);
}
-SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
-
-/*
- * implicit_trans_secs
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_implicit_trans_secs(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_implicit_trans_secs_show(
+ struct config_item *item, char *page)
{
- return core_alua_show_implicit_trans_secs(tg_pt_gp, page);
+ return core_alua_show_implicit_trans_secs(to_tg_pt_gp(item), page);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_implicit_trans_secs(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_implicit_trans_secs_store(
+ struct config_item *item, const char *page, size_t count)
{
- return core_alua_store_implicit_trans_secs(tg_pt_gp, page, count);
+ return core_alua_store_implicit_trans_secs(to_tg_pt_gp(item), page,
+ count);
}
-SE_DEV_ALUA_TG_PT_ATTR(implicit_trans_secs, S_IRUGO | S_IWUSR);
-
-/*
- * preferred
- */
-
-static ssize_t target_core_alua_tg_pt_gp_show_attr_preferred(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_preferred_show(struct config_item *item,
+ char *page)
{
- return core_alua_show_preferred_bit(tg_pt_gp, page);
+ return core_alua_show_preferred_bit(to_tg_pt_gp(item), page);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_preferred(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_preferred_store(struct config_item *item,
+ const char *page, size_t count)
{
- return core_alua_store_preferred_bit(tg_pt_gp, page, count);
+ return core_alua_store_preferred_bit(to_tg_pt_gp(item), page, count);
}
-SE_DEV_ALUA_TG_PT_ATTR(preferred, S_IRUGO | S_IWUSR);
-
-/*
- * tg_pt_gp_id
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_tg_pt_gp_id(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_tg_pt_gp_id_show(struct config_item *item,
+ char *page)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
+
if (!tg_pt_gp->tg_pt_gp_valid_id)
return 0;
-
return sprintf(page, "%hu\n", tg_pt_gp->tg_pt_gp_id);
}
-static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- const char *page,
- size_t count)
+static ssize_t target_tg_pt_gp_tg_pt_gp_id_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
struct config_group *alua_tg_pt_gp_cg = &tg_pt_gp->tg_pt_gp_group;
unsigned long tg_pt_gp_id;
int ret;
@@ -2902,15 +2581,10 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id(
return count;
}
-SE_DEV_ALUA_TG_PT_ATTR(tg_pt_gp_id, S_IRUGO | S_IWUSR);
-
-/*
- * members
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_members(
- struct t10_alua_tg_pt_gp *tg_pt_gp,
- char *page)
+static ssize_t target_tg_pt_gp_members_show(struct config_item *item,
+ char *page)
{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
struct se_lun *lun;
ssize_t len = 0, cur_len;
unsigned char buf[TG_PT_GROUP_NAME_BUF];
@@ -2942,29 +2616,42 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_members(
return len;
}
-SE_DEV_ALUA_TG_PT_ATTR_RO(members);
-
-CONFIGFS_EATTR_OPS(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp,
- tg_pt_gp_group);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_access_state);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_access_status);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_access_type);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_transitioning);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_offline);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_lba_dependent);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_unavailable);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_standby);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_active_optimized);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_active_nonoptimized);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_write_metadata);
+CONFIGFS_ATTR(target_tg_pt_gp_, nonop_delay_msecs);
+CONFIGFS_ATTR(target_tg_pt_gp_, trans_delay_msecs);
+CONFIGFS_ATTR(target_tg_pt_gp_, implicit_trans_secs);
+CONFIGFS_ATTR(target_tg_pt_gp_, preferred);
+CONFIGFS_ATTR(target_tg_pt_gp_, tg_pt_gp_id);
+CONFIGFS_ATTR_RO(target_tg_pt_gp_, members);
static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
- &target_core_alua_tg_pt_gp_alua_access_state.attr,
- &target_core_alua_tg_pt_gp_alua_access_status.attr,
- &target_core_alua_tg_pt_gp_alua_access_type.attr,
- &target_core_alua_tg_pt_gp_alua_support_transitioning.attr,
- &target_core_alua_tg_pt_gp_alua_support_offline.attr,
- &target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr,
- &target_core_alua_tg_pt_gp_alua_support_unavailable.attr,
- &target_core_alua_tg_pt_gp_alua_support_standby.attr,
- &target_core_alua_tg_pt_gp_alua_support_active_nonoptimized.attr,
- &target_core_alua_tg_pt_gp_alua_support_active_optimized.attr,
- &target_core_alua_tg_pt_gp_alua_write_metadata.attr,
- &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
- &target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
- &target_core_alua_tg_pt_gp_implicit_trans_secs.attr,
- &target_core_alua_tg_pt_gp_preferred.attr,
- &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
- &target_core_alua_tg_pt_gp_members.attr,
+ &target_tg_pt_gp_attr_alua_access_state,
+ &target_tg_pt_gp_attr_alua_access_status,
+ &target_tg_pt_gp_attr_alua_access_type,
+ &target_tg_pt_gp_attr_alua_support_transitioning,
+ &target_tg_pt_gp_attr_alua_support_offline,
+ &target_tg_pt_gp_attr_alua_support_lba_dependent,
+ &target_tg_pt_gp_attr_alua_support_unavailable,
+ &target_tg_pt_gp_attr_alua_support_standby,
+ &target_tg_pt_gp_attr_alua_support_active_nonoptimized,
+ &target_tg_pt_gp_attr_alua_support_active_optimized,
+ &target_tg_pt_gp_attr_alua_write_metadata,
+ &target_tg_pt_gp_attr_nonop_delay_msecs,
+ &target_tg_pt_gp_attr_trans_delay_msecs,
+ &target_tg_pt_gp_attr_implicit_trans_secs,
+ &target_tg_pt_gp_attr_preferred,
+ &target_tg_pt_gp_attr_tg_pt_gp_id,
+ &target_tg_pt_gp_attr_members,
NULL,
};
@@ -2978,8 +2665,6 @@ static void target_core_alua_tg_pt_gp_release(struct config_item *item)
static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = {
.release = target_core_alua_tg_pt_gp_release,
- .show_attribute = target_core_alua_tg_pt_gp_attr_show,
- .store_attribute = target_core_alua_tg_pt_gp_attr_store,
};
static struct config_item_type target_core_alua_tg_pt_gp_cit = {
@@ -3237,34 +2922,24 @@ static struct configfs_group_operations target_core_hba_group_ops = {
.drop_item = target_core_drop_subdev,
};
-CONFIGFS_EATTR_STRUCT(target_core_hba, se_hba);
-#define SE_HBA_ATTR(_name, _mode) \
-static struct target_core_hba_attribute \
- target_core_hba_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_core_hba_show_attr_##_name, \
- target_core_hba_store_attr_##_name);
-#define SE_HBA_ATTR_RO(_name) \
-static struct target_core_hba_attribute \
- target_core_hba_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_core_hba_show_attr_##_name);
+static inline struct se_hba *to_hba(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct se_hba, hba_group);
+}
-static ssize_t target_core_hba_show_attr_hba_info(
- struct se_hba *hba,
- char *page)
+static ssize_t target_hba_info_show(struct config_item *item, char *page)
{
+ struct se_hba *hba = to_hba(item);
+
return sprintf(page, "HBA Index: %d plugin: %s version: %s\n",
hba->hba_id, hba->backend->ops->name,
TARGET_CORE_VERSION);
}
-SE_HBA_ATTR_RO(hba_info);
-
-static ssize_t target_core_hba_show_attr_hba_mode(struct se_hba *hba,
- char *page)
+static ssize_t target_hba_mode_show(struct config_item *item, char *page)
{
+ struct se_hba *hba = to_hba(item);
int hba_mode = 0;
if (hba->hba_flags & HBA_FLAGS_PSCSI_MODE)
@@ -3273,9 +2948,10 @@ static ssize_t target_core_hba_show_attr_hba_mode(struct se_hba *hba,
return sprintf(page, "%d\n", hba_mode);
}
-static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba,
- const char *page, size_t count)
+static ssize_t target_hba_mode_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_hba *hba = to_hba(item);
unsigned long mode_flag;
int ret;
@@ -3304,9 +2980,8 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba,
return count;
}
-SE_HBA_ATTR(hba_mode, S_IRUGO | S_IWUSR);
-
-CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group);
+CONFIGFS_ATTR_RO(target_, hba_info);
+CONFIGFS_ATTR(target_, hba_mode);
static void target_core_hba_release(struct config_item *item)
{
@@ -3316,15 +2991,13 @@ static void target_core_hba_release(struct config_item *item)
}
static struct configfs_attribute *target_core_hba_attrs[] = {
- &target_core_hba_hba_info.attr,
- &target_core_hba_hba_mode.attr,
+ &target_attr_hba_info,
+ &target_attr_hba_mode,
NULL,
};
static struct configfs_item_operations target_core_hba_item_ops = {
.release = target_core_hba_release,
- .show_attribute = target_core_hba_attr_show,
- .store_attribute = target_core_hba_attr_store,
};
static struct config_item_type target_core_hba_cit = {
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index be42429468e2..f916d18ccb48 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -35,8 +35,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include "target_core_internal.h"
#include "target_core_alua.h"
@@ -152,17 +150,16 @@ static int target_fabric_mappedlun_unlink(
return core_dev_del_initiator_node_lun_acl(lun, lacl);
}
-CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl);
-#define TCM_MAPPEDLUN_ATTR(_name, _mode) \
-static struct target_fabric_mappedlun_attribute target_fabric_mappedlun_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_fabric_mappedlun_show_##_name, \
- target_fabric_mappedlun_store_##_name);
+static struct se_lun_acl *item_to_lun_acl(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct se_lun_acl,
+ se_lun_group);
+}
-static ssize_t target_fabric_mappedlun_show_write_protect(
- struct se_lun_acl *lacl,
- char *page)
+static ssize_t target_fabric_mappedlun_write_protect_show(
+ struct config_item *item, char *page)
{
+ struct se_lun_acl *lacl = item_to_lun_acl(item);
struct se_node_acl *se_nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t len = 0;
@@ -178,11 +175,10 @@ static ssize_t target_fabric_mappedlun_show_write_protect(
return len;
}
-static ssize_t target_fabric_mappedlun_store_write_protect(
- struct se_lun_acl *lacl,
- const char *page,
- size_t count)
+static ssize_t target_fabric_mappedlun_write_protect_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct se_lun_acl *lacl = item_to_lun_acl(item);
struct se_node_acl *se_nacl = lacl->se_lun_nacl;
struct se_portal_group *se_tpg = se_nacl->se_tpg;
unsigned long op;
@@ -209,9 +205,12 @@ static ssize_t target_fabric_mappedlun_store_write_protect(
}
-TCM_MAPPEDLUN_ATTR(write_protect, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(target_fabric_mappedlun_, write_protect);
-CONFIGFS_EATTR_OPS(target_fabric_mappedlun, se_lun_acl, se_lun_group);
+static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
+ &target_fabric_mappedlun_attr_write_protect,
+ NULL,
+};
static void target_fabric_mappedlun_release(struct config_item *item)
{
@@ -222,15 +221,8 @@ static void target_fabric_mappedlun_release(struct config_item *item)
core_dev_free_initiator_node_lun_acl(se_tpg, lacl);
}
-static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
- &target_fabric_mappedlun_write_protect.attr,
- NULL,
-};
-
static struct configfs_item_operations target_fabric_mappedlun_item_ops = {
.release = target_fabric_mappedlun_release,
- .show_attribute = target_fabric_mappedlun_attr_show,
- .store_attribute = target_fabric_mappedlun_attr_store,
.allow_link = target_fabric_mappedlun_link,
.drop_link = target_fabric_mappedlun_unlink,
};
@@ -266,49 +258,12 @@ TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
/* End of tfc_tpg_mappedlun_port_cit */
-/* Start of tfc_tpg_nacl_attrib_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
-
-static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = {
- .show_attribute = target_fabric_nacl_attrib_attr_show,
- .store_attribute = target_fabric_nacl_attrib_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL);
-
-/* End of tfc_tpg_nacl_attrib_cit */
-
-/* Start of tfc_tpg_nacl_auth_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_nacl_auth, se_node_acl, acl_auth_group);
-
-static struct configfs_item_operations target_fabric_nacl_auth_item_ops = {
- .show_attribute = target_fabric_nacl_auth_attr_show,
- .store_attribute = target_fabric_nacl_auth_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL);
-
-/* End of tfc_tpg_nacl_auth_cit */
-
-/* Start of tfc_tpg_nacl_param_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_nacl_param, se_node_acl, acl_param_group);
-
-static struct configfs_item_operations target_fabric_nacl_param_item_ops = {
- .show_attribute = target_fabric_nacl_param_attr_show,
- .store_attribute = target_fabric_nacl_param_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL);
-
-/* End of tfc_tpg_nacl_param_cit */
+TF_CIT_SETUP_DRV(tpg_nacl_attrib, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_auth, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_param, NULL, NULL);
/* Start of tfc_tpg_nacl_base_cit */
-CONFIGFS_EATTR_OPS(target_fabric_nacl_base, se_node_acl, acl_group);
-
static struct config_group *target_fabric_make_mappedlun(
struct config_group *group,
const char *name)
@@ -438,8 +393,6 @@ static void target_fabric_nacl_base_release(struct config_item *item)
static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
.release = target_fabric_nacl_base_release,
- .show_attribute = target_fabric_nacl_base_attr_show,
- .store_attribute = target_fabric_nacl_base_attr_store,
};
static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
@@ -540,8 +493,6 @@ TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL);
/* Start of tfc_tpg_np_base_cit */
-CONFIGFS_EATTR_OPS(target_fabric_np_base, se_tpg_np, tpg_np_group);
-
static void target_fabric_np_base_release(struct config_item *item)
{
struct se_tpg_np *se_tpg_np = container_of(to_config_group(item),
@@ -554,8 +505,6 @@ static void target_fabric_np_base_release(struct config_item *item)
static struct configfs_item_operations target_fabric_np_base_item_ops = {
.release = target_fabric_np_base_release,
- .show_attribute = target_fabric_np_base_attr_show,
- .store_attribute = target_fabric_np_base_attr_store,
};
TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);
@@ -610,132 +559,113 @@ TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL);
/* Start of tfc_tpg_port_cit */
-CONFIGFS_EATTR_STRUCT(target_fabric_port, se_lun);
-#define TCM_PORT_ATTR(_name, _mode) \
-static struct target_fabric_port_attribute target_fabric_port_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_fabric_port_show_attr_##_name, \
- target_fabric_port_store_attr_##_name);
-
-#define TCM_PORT_ATTOR_RO(_name) \
- __CONFIGFS_EATTR_RO(_name, \
- target_fabric_port_show_attr_##_name);
+static struct se_lun *item_to_lun(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct se_lun,
+ lun_group);
+}
-/*
- * alua_tg_pt_gp
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp(
- struct se_lun *lun,
- char *page)
+static ssize_t target_fabric_port_alua_tg_pt_gp_show(struct config_item *item,
+ char *page)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_show_tg_pt_gp_info(lun, page);
}
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
- struct se_lun *lun,
- const char *page,
- size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_gp_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_store_tg_pt_gp_info(lun, page, count);
}
-TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR);
-
-/*
- * alua_tg_pt_offline
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline(
- struct se_lun *lun,
- char *page)
+static ssize_t target_fabric_port_alua_tg_pt_offline_show(
+ struct config_item *item, char *page)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_show_offline_bit(lun, page);
}
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline(
- struct se_lun *lun,
- const char *page,
- size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_offline_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_store_offline_bit(lun, page, count);
}
-TCM_PORT_ATTR(alua_tg_pt_offline, S_IRUGO | S_IWUSR);
-
-/*
- * alua_tg_pt_status
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_status(
- struct se_lun *lun,
- char *page)
+static ssize_t target_fabric_port_alua_tg_pt_status_show(
+ struct config_item *item, char *page)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_show_secondary_status(lun, page);
}
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_status(
- struct se_lun *lun,
- const char *page,
- size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_status_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_store_secondary_status(lun, page, count);
}
-TCM_PORT_ATTR(alua_tg_pt_status, S_IRUGO | S_IWUSR);
-
-/*
- * alua_tg_pt_write_md
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md(
- struct se_lun *lun,
- char *page)
+static ssize_t target_fabric_port_alua_tg_pt_write_md_show(
+ struct config_item *item, char *page)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_show_secondary_write_metadata(lun, page);
}
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md(
- struct se_lun *lun,
- const char *page,
- size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_write_md_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct se_lun *lun = item_to_lun(item);
+
if (!lun || !lun->lun_se_dev)
return -ENODEV;
return core_alua_store_secondary_write_metadata(lun, page, count);
}
-TCM_PORT_ATTR(alua_tg_pt_write_md, S_IRUGO | S_IWUSR);
-
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_gp);
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_offline);
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_status);
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_write_md);
static struct configfs_attribute *target_fabric_port_attrs[] = {
- &target_fabric_port_alua_tg_pt_gp.attr,
- &target_fabric_port_alua_tg_pt_offline.attr,
- &target_fabric_port_alua_tg_pt_status.attr,
- &target_fabric_port_alua_tg_pt_write_md.attr,
+ &target_fabric_port_attr_alua_tg_pt_gp,
+ &target_fabric_port_attr_alua_tg_pt_offline,
+ &target_fabric_port_attr_alua_tg_pt_status,
+ &target_fabric_port_attr_alua_tg_pt_write_md,
NULL,
};
-CONFIGFS_EATTR_OPS(target_fabric_port, se_lun, lun_group);
-
static int target_fabric_port_link(
struct config_item *lun_ci,
struct config_item *se_dev_ci)
@@ -821,8 +751,6 @@ static void target_fabric_port_release(struct config_item *item)
}
static struct configfs_item_operations target_fabric_port_item_ops = {
- .show_attribute = target_fabric_port_attr_show,
- .store_attribute = target_fabric_port_attr_store,
.release = target_fabric_port_release,
.allow_link = target_fabric_port_link,
.drop_link = target_fabric_port_unlink,
@@ -952,50 +880,11 @@ TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);
/* End of tfc_tpg_lun_cit */
-/* Start of tfc_tpg_attrib_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_tpg_attrib, se_portal_group, tpg_attrib_group);
-
-static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = {
- .show_attribute = target_fabric_tpg_attrib_attr_show,
- .store_attribute = target_fabric_tpg_attrib_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL);
-
-/* End of tfc_tpg_attrib_cit */
-
-/* Start of tfc_tpg_auth_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_tpg_auth, se_portal_group, tpg_auth_group);
-
-static struct configfs_item_operations target_fabric_tpg_auth_item_ops = {
- .show_attribute = target_fabric_tpg_auth_attr_show,
- .store_attribute = target_fabric_tpg_auth_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL);
-
-/* End of tfc_tpg_attrib_cit */
-
-/* Start of tfc_tpg_param_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group);
-
-static struct configfs_item_operations target_fabric_tpg_param_item_ops = {
- .show_attribute = target_fabric_tpg_param_attr_show,
- .store_attribute = target_fabric_tpg_param_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_param, &target_fabric_tpg_param_item_ops, NULL);
-
-/* End of tfc_tpg_param_cit */
+TF_CIT_SETUP_DRV(tpg_attrib, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_auth, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_param, NULL, NULL);
/* Start of tfc_tpg_base_cit */
-/*
- * For use with TF_TPG_ATTR() and TF_TPG_ATTR_RO()
- */
-CONFIGFS_EATTR_OPS(target_fabric_tpg, se_portal_group, tpg_group);
static void target_fabric_tpg_release(struct config_item *item)
{
@@ -1009,8 +898,6 @@ static void target_fabric_tpg_release(struct config_item *item)
static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
.release = target_fabric_tpg_release,
- .show_attribute = target_fabric_tpg_attr_show,
- .store_attribute = target_fabric_tpg_attr_store,
};
TF_CIT_SETUP_DRV(tpg_base, &target_fabric_tpg_base_item_ops, NULL);
@@ -1176,33 +1063,9 @@ static struct configfs_group_operations target_fabric_wwn_group_ops = {
.make_group = target_fabric_make_wwn,
.drop_item = target_fabric_drop_wwn,
};
-/*
- * For use with TF_WWN_ATTR() and TF_WWN_ATTR_RO()
- */
-CONFIGFS_EATTR_OPS(target_fabric_wwn, target_fabric_configfs, tf_group);
-
-static struct configfs_item_operations target_fabric_wwn_item_ops = {
- .show_attribute = target_fabric_wwn_attr_show,
- .store_attribute = target_fabric_wwn_attr_store,
-};
-
-TF_CIT_SETUP_DRV(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops);
-
-/* End of tfc_wwn_cit */
-
-/* Start of tfc_discovery_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_discovery, target_fabric_configfs,
- tf_disc_group);
-
-static struct configfs_item_operations target_fabric_discovery_item_ops = {
- .show_attribute = target_fabric_discovery_attr_show,
- .store_attribute = target_fabric_discovery_attr_store,
-};
-
-TF_CIT_SETUP_DRV(discovery, &target_fabric_discovery_item_ops, NULL);
-/* End of tfc_discovery_cit */
+TF_CIT_SETUP_DRV(wwn, NULL, &target_fabric_wwn_group_ops);
+TF_CIT_SETUP_DRV(discovery, NULL, NULL);
int target_fabric_setup_cits(struct target_fabric_configfs *tf)
{
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 0f19e11acac2..f29c69120054 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -155,17 +155,17 @@ static int iblock_configure_device(struct se_device *dev)
if (bi) {
struct bio_set *bs = ib_dev->ibd_bio_set;
- if (!strcmp(bi->name, "T10-DIF-TYPE3-IP") ||
- !strcmp(bi->name, "T10-DIF-TYPE1-IP")) {
+ if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-IP") ||
+ !strcmp(bi->profile->name, "T10-DIF-TYPE1-IP")) {
pr_err("IBLOCK export of blk_integrity: %s not"
- " supported\n", bi->name);
+ " supported\n", bi->profile->name);
ret = -ENOSYS;
goto out_blkdev_put;
}
- if (!strcmp(bi->name, "T10-DIF-TYPE3-CRC")) {
+ if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-CRC")) {
dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT;
- } else if (!strcmp(bi->name, "T10-DIF-TYPE1-CRC")) {
+ } else if (!strcmp(bi->profile->name, "T10-DIF-TYPE1-CRC")) {
dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT;
}
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 99c24acfe676..dae0750c2032 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -87,6 +87,9 @@ void target_free_device(struct se_device *);
/* target_core_configfs.c */
void target_setup_backend_cits(struct target_backend *);
+/* target_core_fabric_configfs.c */
+int target_fabric_setup_cits(struct target_fabric_configfs *);
+
/* target_core_fabric_lib.c */
int target_get_pr_transport_id_len(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code);
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c
index 20ed5d2e151a..273c72b2b83d 100644
--- a/drivers/target/target_core_stat.c
+++ b/drivers/target/target_core_stat.c
@@ -37,7 +37,6 @@
#include <target/target_core_base.h>
#include <target/target_core_backend.h>
#include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
#include "target_core_internal.h"
@@ -55,75 +54,49 @@
* SCSI Device Table
*/
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_dev, se_dev_stat_grps);
-#define DEV_STAT_SCSI_DEV_ATTR(_name, _mode) \
-static struct target_stat_scsi_dev_attribute \
- target_stat_scsi_dev_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_dev_show_attr_##_name, \
- target_stat_scsi_dev_store_attr_##_name);
-
-#define DEV_STAT_SCSI_DEV_ATTR_RO(_name) \
-static struct target_stat_scsi_dev_attribute \
- target_stat_scsi_dev_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_dev_show_attr_##_name);
+static struct se_device *to_stat_dev(struct config_item *item)
+{
+ struct se_dev_stat_grps *sgrps = container_of(to_config_group(item),
+ struct se_dev_stat_grps, scsi_dev_group);
+ return container_of(sgrps, struct se_device, dev_stat_grps);
+}
-static ssize_t target_stat_scsi_dev_show_attr_inst(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_inst_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
- struct se_hba *hba = dev->se_hba;
+ struct se_hba *hba = to_stat_dev(item)->se_hba;
return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
}
-DEV_STAT_SCSI_DEV_ATTR_RO(inst);
-static ssize_t target_stat_scsi_dev_show_attr_indx(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_indx_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
-
- return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
+ return snprintf(page, PAGE_SIZE, "%u\n", to_stat_dev(item)->dev_index);
}
-DEV_STAT_SCSI_DEV_ATTR_RO(indx);
-static ssize_t target_stat_scsi_dev_show_attr_role(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_role_show(struct config_item *item, char *page)
{
return snprintf(page, PAGE_SIZE, "Target\n");
}
-DEV_STAT_SCSI_DEV_ATTR_RO(role);
-static ssize_t target_stat_scsi_dev_show_attr_ports(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_ports_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
-
- return snprintf(page, PAGE_SIZE, "%u\n", dev->export_count);
+ return snprintf(page, PAGE_SIZE, "%u\n", to_stat_dev(item)->export_count);
}
-DEV_STAT_SCSI_DEV_ATTR_RO(ports);
-CONFIGFS_EATTR_OPS(target_stat_scsi_dev, se_dev_stat_grps, scsi_dev_group);
+CONFIGFS_ATTR_RO(target_stat_, inst);
+CONFIGFS_ATTR_RO(target_stat_, indx);
+CONFIGFS_ATTR_RO(target_stat_, role);
+CONFIGFS_ATTR_RO(target_stat_, ports);
static struct configfs_attribute *target_stat_scsi_dev_attrs[] = {
- &target_stat_scsi_dev_inst.attr,
- &target_stat_scsi_dev_indx.attr,
- &target_stat_scsi_dev_role.attr,
- &target_stat_scsi_dev_ports.attr,
+ &target_stat_attr_inst,
+ &target_stat_attr_indx,
+ &target_stat_attr_role,
+ &target_stat_attr_ports,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_dev_attrib_ops = {
- .show_attribute = target_stat_scsi_dev_attr_show,
- .store_attribute = target_stat_scsi_dev_attr_store,
-};
-
static struct config_item_type target_stat_scsi_dev_cit = {
- .ct_item_ops = &target_stat_scsi_dev_attrib_ops,
.ct_attrs = target_stat_scsi_dev_attrs,
.ct_owner = THIS_MODULE,
};
@@ -131,109 +104,78 @@ static struct config_item_type target_stat_scsi_dev_cit = {
/*
* SCSI Target Device Table
*/
+static struct se_device *to_stat_tgt_dev(struct config_item *item)
+{
+ struct se_dev_stat_grps *sgrps = container_of(to_config_group(item),
+ struct se_dev_stat_grps, scsi_tgt_dev_group);
+ return container_of(sgrps, struct se_device, dev_stat_grps);
+}
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_dev, se_dev_stat_grps);
-#define DEV_STAT_SCSI_TGT_DEV_ATTR(_name, _mode) \
-static struct target_stat_scsi_tgt_dev_attribute \
- target_stat_scsi_tgt_dev_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_tgt_dev_show_attr_##_name, \
- target_stat_scsi_tgt_dev_store_attr_##_name);
-
-#define DEV_STAT_SCSI_TGT_DEV_ATTR_RO(_name) \
-static struct target_stat_scsi_tgt_dev_attribute \
- target_stat_scsi_tgt_dev_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_tgt_dev_show_attr_##_name);
-
-static ssize_t target_stat_scsi_tgt_dev_show_attr_inst(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_inst_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
- struct se_hba *hba = dev->se_hba;
+ struct se_hba *hba = to_stat_tgt_dev(item)->se_hba;
return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
}
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst);
-static ssize_t target_stat_scsi_tgt_dev_show_attr_indx(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_indx_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
-
- return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
+ return snprintf(page, PAGE_SIZE, "%u\n", to_stat_tgt_dev(item)->dev_index);
}
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx);
-static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_num_lus_show(struct config_item *item,
+ char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT);
}
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus);
-static ssize_t target_stat_scsi_tgt_dev_show_attr_status(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_status_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
-
- if (dev->export_count)
+ if (to_stat_tgt_dev(item)->export_count)
return snprintf(page, PAGE_SIZE, "activated");
else
return snprintf(page, PAGE_SIZE, "deactivated");
}
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status);
-static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_non_access_lus_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
int non_accessible_lus;
- if (dev->export_count)
+ if (to_stat_tgt_dev(item)->export_count)
non_accessible_lus = 0;
else
non_accessible_lus = 1;
return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus);
}
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus);
-static ssize_t target_stat_scsi_tgt_dev_show_attr_resets(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_resets_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
-
return snprintf(page, PAGE_SIZE, "%lu\n",
- atomic_long_read(&dev->num_resets));
+ atomic_long_read(&to_stat_tgt_dev(item)->num_resets));
}
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(resets);
-
-CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_dev, se_dev_stat_grps, scsi_tgt_dev_group);
+CONFIGFS_ATTR_RO(target_stat_tgt_, inst);
+CONFIGFS_ATTR_RO(target_stat_tgt_, indx);
+CONFIGFS_ATTR_RO(target_stat_tgt_, num_lus);
+CONFIGFS_ATTR_RO(target_stat_tgt_, status);
+CONFIGFS_ATTR_RO(target_stat_tgt_, non_access_lus);
+CONFIGFS_ATTR_RO(target_stat_tgt_, resets);
static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
- &target_stat_scsi_tgt_dev_inst.attr,
- &target_stat_scsi_tgt_dev_indx.attr,
- &target_stat_scsi_tgt_dev_num_lus.attr,
- &target_stat_scsi_tgt_dev_status.attr,
- &target_stat_scsi_tgt_dev_non_access_lus.attr,
- &target_stat_scsi_tgt_dev_resets.attr,
+ &target_stat_tgt_attr_inst,
+ &target_stat_tgt_attr_indx,
+ &target_stat_tgt_attr_num_lus,
+ &target_stat_tgt_attr_status,
+ &target_stat_tgt_attr_non_access_lus,
+ &target_stat_tgt_attr_resets,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_tgt_dev_attrib_ops = {
- .show_attribute = target_stat_scsi_tgt_dev_attr_show,
- .store_attribute = target_stat_scsi_tgt_dev_attr_store,
-};
-
static struct config_item_type target_stat_scsi_tgt_dev_cit = {
- .ct_item_ops = &target_stat_scsi_tgt_dev_attrib_ops,
.ct_attrs = target_stat_scsi_tgt_dev_attrs,
.ct_owner = THIS_MODULE,
};
@@ -242,72 +184,50 @@ static struct config_item_type target_stat_scsi_tgt_dev_cit = {
* SCSI Logical Unit Table
*/
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_lu, se_dev_stat_grps);
-#define DEV_STAT_SCSI_LU_ATTR(_name, _mode) \
-static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_lu_show_attr_##_name, \
- target_stat_scsi_lu_store_attr_##_name);
-
-#define DEV_STAT_SCSI_LU_ATTR_RO(_name) \
-static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_lu_show_attr_##_name);
+static struct se_device *to_stat_lu_dev(struct config_item *item)
+{
+ struct se_dev_stat_grps *sgrps = container_of(to_config_group(item),
+ struct se_dev_stat_grps, scsi_lu_group);
+ return container_of(sgrps, struct se_device, dev_stat_grps);
+}
-static ssize_t target_stat_scsi_lu_show_attr_inst(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_inst_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
- struct se_hba *hba = dev->se_hba;
+ struct se_hba *hba = to_stat_lu_dev(item)->se_hba;
return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
}
-DEV_STAT_SCSI_LU_ATTR_RO(inst);
-static ssize_t target_stat_scsi_lu_show_attr_dev(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_dev_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
-
- return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
+ return snprintf(page, PAGE_SIZE, "%u\n",
+ to_stat_lu_dev(item)->dev_index);
}
-DEV_STAT_SCSI_LU_ATTR_RO(dev);
-static ssize_t target_stat_scsi_lu_show_attr_indx(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_indx_show(struct config_item *item, char *page)
{
return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX);
}
-DEV_STAT_SCSI_LU_ATTR_RO(indx);
-static ssize_t target_stat_scsi_lu_show_attr_lun(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_lun_show(struct config_item *item, char *page)
{
/* FIXME: scsiLuDefaultLun */
return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0);
}
-DEV_STAT_SCSI_LU_ATTR_RO(lun);
-static ssize_t target_stat_scsi_lu_show_attr_lu_name(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_lu_name_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuWwnName */
return snprintf(page, PAGE_SIZE, "%s\n",
(strlen(dev->t10_wwn.unit_serial)) ?
dev->t10_wwn.unit_serial : "None");
}
-DEV_STAT_SCSI_LU_ATTR_RO(lu_name);
-static ssize_t target_stat_scsi_lu_show_attr_vend(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_vend_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
int i;
char str[sizeof(dev->t10_wwn.vendor)+1];
@@ -318,13 +238,10 @@ static ssize_t target_stat_scsi_lu_show_attr_vend(
str[i] = '\0';
return snprintf(page, PAGE_SIZE, "%s\n", str);
}
-DEV_STAT_SCSI_LU_ATTR_RO(vend);
-static ssize_t target_stat_scsi_lu_show_attr_prod(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_prod_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
int i;
char str[sizeof(dev->t10_wwn.model)+1];
@@ -335,13 +252,10 @@ static ssize_t target_stat_scsi_lu_show_attr_prod(
str[i] = '\0';
return snprintf(page, PAGE_SIZE, "%s\n", str);
}
-DEV_STAT_SCSI_LU_ATTR_RO(prod);
-static ssize_t target_stat_scsi_lu_show_attr_rev(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_rev_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
int i;
char str[sizeof(dev->t10_wwn.revision)+1];
@@ -352,146 +266,137 @@ static ssize_t target_stat_scsi_lu_show_attr_rev(
str[i] = '\0';
return snprintf(page, PAGE_SIZE, "%s\n", str);
}
-DEV_STAT_SCSI_LU_ATTR_RO(rev);
-static ssize_t target_stat_scsi_lu_show_attr_dev_type(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_dev_type_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuPeripheralType */
return snprintf(page, PAGE_SIZE, "%u\n",
dev->transport->get_device_type(dev));
}
-DEV_STAT_SCSI_LU_ATTR_RO(dev_type);
-static ssize_t target_stat_scsi_lu_show_attr_status(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_status_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuStatus */
return snprintf(page, PAGE_SIZE, "%s\n",
(dev->export_count) ? "available" : "notavailable");
}
-DEV_STAT_SCSI_LU_ATTR_RO(status);
-static ssize_t target_stat_scsi_lu_show_attr_state_bit(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_state_bit_show(struct config_item *item,
+ char *page)
{
/* scsiLuState */
return snprintf(page, PAGE_SIZE, "exposed\n");
}
-DEV_STAT_SCSI_LU_ATTR_RO(state_bit);
-static ssize_t target_stat_scsi_lu_show_attr_num_cmds(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_num_cmds_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuNumCommands */
return snprintf(page, PAGE_SIZE, "%lu\n",
atomic_long_read(&dev->num_cmds));
}
-DEV_STAT_SCSI_LU_ATTR_RO(num_cmds);
-static ssize_t target_stat_scsi_lu_show_attr_read_mbytes(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_read_mbytes_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuReadMegaBytes */
return snprintf(page, PAGE_SIZE, "%lu\n",
atomic_long_read(&dev->read_bytes) >> 20);
}
-DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes);
-static ssize_t target_stat_scsi_lu_show_attr_write_mbytes(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_write_mbytes_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuWrittenMegaBytes */
return snprintf(page, PAGE_SIZE, "%lu\n",
atomic_long_read(&dev->write_bytes) >> 20);
}
-DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes);
-static ssize_t target_stat_scsi_lu_show_attr_resets(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuInResets */
- return snprintf(page, PAGE_SIZE, "%lu\n", atomic_long_read(&dev->num_resets));
+ return snprintf(page, PAGE_SIZE, "%lu\n",
+ atomic_long_read(&dev->num_resets));
}
-DEV_STAT_SCSI_LU_ATTR_RO(resets);
-static ssize_t target_stat_scsi_lu_show_attr_full_stat(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_full_stat_show(struct config_item *item,
+ char *page)
{
/* FIXME: scsiLuOutTaskSetFullStatus */
return snprintf(page, PAGE_SIZE, "%u\n", 0);
}
-DEV_STAT_SCSI_LU_ATTR_RO(full_stat);
-static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_hs_num_cmds_show(struct config_item *item,
+ char *page)
{
/* FIXME: scsiLuHSInCommands */
return snprintf(page, PAGE_SIZE, "%u\n", 0);
}
-DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds);
-static ssize_t target_stat_scsi_lu_show_attr_creation_time(
- struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_creation_time_show(struct config_item *item,
+ char *page)
{
- struct se_device *dev =
- container_of(sgrps, struct se_device, dev_stat_grps);
+ struct se_device *dev = to_stat_lu_dev(item);
/* scsiLuCreationTime */
return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time -
INITIAL_JIFFIES) * 100 / HZ));
}
-DEV_STAT_SCSI_LU_ATTR_RO(creation_time);
-CONFIGFS_EATTR_OPS(target_stat_scsi_lu, se_dev_stat_grps, scsi_lu_group);
+CONFIGFS_ATTR_RO(target_stat_lu_, inst);
+CONFIGFS_ATTR_RO(target_stat_lu_, dev);
+CONFIGFS_ATTR_RO(target_stat_lu_, indx);
+CONFIGFS_ATTR_RO(target_stat_lu_, lun);
+CONFIGFS_ATTR_RO(target_stat_lu_, lu_name);
+CONFIGFS_ATTR_RO(target_stat_lu_, vend);
+CONFIGFS_ATTR_RO(target_stat_lu_, prod);
+CONFIGFS_ATTR_RO(target_stat_lu_, rev);
+CONFIGFS_ATTR_RO(target_stat_lu_, dev_type);
+CONFIGFS_ATTR_RO(target_stat_lu_, status);
+CONFIGFS_ATTR_RO(target_stat_lu_, state_bit);
+CONFIGFS_ATTR_RO(target_stat_lu_, num_cmds);
+CONFIGFS_ATTR_RO(target_stat_lu_, read_mbytes);
+CONFIGFS_ATTR_RO(target_stat_lu_, write_mbytes);
+CONFIGFS_ATTR_RO(target_stat_lu_, resets);
+CONFIGFS_ATTR_RO(target_stat_lu_, full_stat);
+CONFIGFS_ATTR_RO(target_stat_lu_, hs_num_cmds);
+CONFIGFS_ATTR_RO(target_stat_lu_, creation_time);
static struct configfs_attribute *target_stat_scsi_lu_attrs[] = {
- &target_stat_scsi_lu_inst.attr,
- &target_stat_scsi_lu_dev.attr,
- &target_stat_scsi_lu_indx.attr,
- &target_stat_scsi_lu_lun.attr,
- &target_stat_scsi_lu_lu_name.attr,
- &target_stat_scsi_lu_vend.attr,
- &target_stat_scsi_lu_prod.attr,
- &target_stat_scsi_lu_rev.attr,
- &target_stat_scsi_lu_dev_type.attr,
- &target_stat_scsi_lu_status.attr,
- &target_stat_scsi_lu_state_bit.attr,
- &target_stat_scsi_lu_num_cmds.attr,
- &target_stat_scsi_lu_read_mbytes.attr,
- &target_stat_scsi_lu_write_mbytes.attr,
- &target_stat_scsi_lu_resets.attr,
- &target_stat_scsi_lu_full_stat.attr,
- &target_stat_scsi_lu_hs_num_cmds.attr,
- &target_stat_scsi_lu_creation_time.attr,
+ &target_stat_lu_attr_inst,
+ &target_stat_lu_attr_dev,
+ &target_stat_lu_attr_indx,
+ &target_stat_lu_attr_lun,
+ &target_stat_lu_attr_lu_name,
+ &target_stat_lu_attr_vend,
+ &target_stat_lu_attr_prod,
+ &target_stat_lu_attr_rev,
+ &target_stat_lu_attr_dev_type,
+ &target_stat_lu_attr_status,
+ &target_stat_lu_attr_state_bit,
+ &target_stat_lu_attr_num_cmds,
+ &target_stat_lu_attr_read_mbytes,
+ &target_stat_lu_attr_write_mbytes,
+ &target_stat_lu_attr_resets,
+ &target_stat_lu_attr_full_stat,
+ &target_stat_lu_attr_hs_num_cmds,
+ &target_stat_lu_attr_creation_time,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_lu_attrib_ops = {
- .show_attribute = target_stat_scsi_lu_attr_show,
- .store_attribute = target_stat_scsi_lu_attr_store,
-};
-
static struct config_item_type target_stat_scsi_lu_cit = {
- .ct_item_ops = &target_stat_scsi_lu_attrib_ops,
.ct_attrs = target_stat_scsi_lu_attrs,
.ct_owner = THIS_MODULE,
};
@@ -521,24 +426,16 @@ void target_stat_setup_dev_default_groups(struct se_device *dev)
* SCSI Port Table
*/
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_port, se_port_stat_grps);
-#define DEV_STAT_SCSI_PORT_ATTR(_name, _mode) \
-static struct target_stat_scsi_port_attribute \
- target_stat_scsi_port_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_port_show_attr_##_name, \
- target_stat_scsi_port_store_attr_##_name);
-
-#define DEV_STAT_SCSI_PORT_ATTR_RO(_name) \
-static struct target_stat_scsi_port_attribute \
- target_stat_scsi_port_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_port_show_attr_##_name);
+static struct se_lun *to_stat_port(struct config_item *item)
+{
+ struct se_port_stat_grps *pgrps = container_of(to_config_group(item),
+ struct se_port_stat_grps, scsi_port_group);
+ return container_of(pgrps, struct se_lun, port_stat_grps);
+}
-static ssize_t target_stat_scsi_port_show_attr_inst(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_inst_show(struct config_item *item, char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -549,12 +446,10 @@ static ssize_t target_stat_scsi_port_show_attr_inst(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_PORT_ATTR_RO(inst);
-static ssize_t target_stat_scsi_port_show_attr_dev(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_dev_show(struct config_item *item, char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -565,12 +460,10 @@ static ssize_t target_stat_scsi_port_show_attr_dev(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_PORT_ATTR_RO(dev);
-static ssize_t target_stat_scsi_port_show_attr_indx(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_indx_show(struct config_item *item, char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -581,12 +474,10 @@ static ssize_t target_stat_scsi_port_show_attr_indx(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_PORT_ATTR_RO(indx);
-static ssize_t target_stat_scsi_port_show_attr_role(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_role_show(struct config_item *item, char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -597,12 +488,11 @@ static ssize_t target_stat_scsi_port_show_attr_role(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_PORT_ATTR_RO(role);
-static ssize_t target_stat_scsi_port_show_attr_busy_count(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_busy_count_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -615,26 +505,23 @@ static ssize_t target_stat_scsi_port_show_attr_busy_count(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_PORT_ATTR_RO(busy_count);
-CONFIGFS_EATTR_OPS(target_stat_scsi_port, se_port_stat_grps, scsi_port_group);
+CONFIGFS_ATTR_RO(target_stat_port_, inst);
+CONFIGFS_ATTR_RO(target_stat_port_, dev);
+CONFIGFS_ATTR_RO(target_stat_port_, indx);
+CONFIGFS_ATTR_RO(target_stat_port_, role);
+CONFIGFS_ATTR_RO(target_stat_port_, busy_count);
static struct configfs_attribute *target_stat_scsi_port_attrs[] = {
- &target_stat_scsi_port_inst.attr,
- &target_stat_scsi_port_dev.attr,
- &target_stat_scsi_port_indx.attr,
- &target_stat_scsi_port_role.attr,
- &target_stat_scsi_port_busy_count.attr,
+ &target_stat_port_attr_inst,
+ &target_stat_port_attr_dev,
+ &target_stat_port_attr_indx,
+ &target_stat_port_attr_role,
+ &target_stat_port_attr_busy_count,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_port_attrib_ops = {
- .show_attribute = target_stat_scsi_port_attr_show,
- .store_attribute = target_stat_scsi_port_attr_store,
-};
-
static struct config_item_type target_stat_scsi_port_cit = {
- .ct_item_ops = &target_stat_scsi_port_attrib_ops,
.ct_attrs = target_stat_scsi_port_attrs,
.ct_owner = THIS_MODULE,
};
@@ -642,24 +529,17 @@ static struct config_item_type target_stat_scsi_port_cit = {
/*
* SCSI Target Port Table
*/
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_port, se_port_stat_grps);
-#define DEV_STAT_SCSI_TGT_PORT_ATTR(_name, _mode) \
-static struct target_stat_scsi_tgt_port_attribute \
- target_stat_scsi_tgt_port_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_tgt_port_show_attr_##_name, \
- target_stat_scsi_tgt_port_store_attr_##_name);
-
-#define DEV_STAT_SCSI_TGT_PORT_ATTR_RO(_name) \
-static struct target_stat_scsi_tgt_port_attribute \
- target_stat_scsi_tgt_port_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_tgt_port_show_attr_##_name);
-
-static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
- struct se_port_stat_grps *pgrps, char *page)
-{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+static struct se_lun *to_stat_tgt_port(struct config_item *item)
+{
+ struct se_port_stat_grps *pgrps = container_of(to_config_group(item),
+ struct se_port_stat_grps, scsi_tgt_port_group);
+ return container_of(pgrps, struct se_lun, port_stat_grps);
+}
+
+static ssize_t target_stat_tgt_port_inst_show(struct config_item *item,
+ char *page)
+{
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -670,12 +550,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst);
-static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_dev_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -686,12 +565,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev);
-static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_indx_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -702,12 +580,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx);
-static ssize_t target_stat_scsi_tgt_port_show_attr_name(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_name_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_portal_group *tpg = lun->lun_tpg;
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -721,12 +598,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_name(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name);
-static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_port_index_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_portal_group *tpg = lun->lun_tpg;
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -740,12 +616,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index);
-static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_in_cmds_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -757,12 +632,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds);
-static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_write_mbytes_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -774,12 +648,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes);
-static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_read_mbytes_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -791,12 +664,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes);
-static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_hs_in_cmds_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_stat_tgt_port(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -809,57 +681,49 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds);
-CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_port, se_port_stat_grps,
- scsi_tgt_port_group);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, inst);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, dev);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, indx);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, name);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, port_index);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, in_cmds);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, write_mbytes);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, read_mbytes);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, hs_in_cmds);
static struct configfs_attribute *target_stat_scsi_tgt_port_attrs[] = {
- &target_stat_scsi_tgt_port_inst.attr,
- &target_stat_scsi_tgt_port_dev.attr,
- &target_stat_scsi_tgt_port_indx.attr,
- &target_stat_scsi_tgt_port_name.attr,
- &target_stat_scsi_tgt_port_port_index.attr,
- &target_stat_scsi_tgt_port_in_cmds.attr,
- &target_stat_scsi_tgt_port_write_mbytes.attr,
- &target_stat_scsi_tgt_port_read_mbytes.attr,
- &target_stat_scsi_tgt_port_hs_in_cmds.attr,
+ &target_stat_tgt_port_attr_inst,
+ &target_stat_tgt_port_attr_dev,
+ &target_stat_tgt_port_attr_indx,
+ &target_stat_tgt_port_attr_name,
+ &target_stat_tgt_port_attr_port_index,
+ &target_stat_tgt_port_attr_in_cmds,
+ &target_stat_tgt_port_attr_write_mbytes,
+ &target_stat_tgt_port_attr_read_mbytes,
+ &target_stat_tgt_port_attr_hs_in_cmds,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_tgt_port_attrib_ops = {
- .show_attribute = target_stat_scsi_tgt_port_attr_show,
- .store_attribute = target_stat_scsi_tgt_port_attr_store,
-};
-
static struct config_item_type target_stat_scsi_tgt_port_cit = {
- .ct_item_ops = &target_stat_scsi_tgt_port_attrib_ops,
.ct_attrs = target_stat_scsi_tgt_port_attrs,
.ct_owner = THIS_MODULE,
};
/*
* SCSI Transport Table
-o */
-
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_transport, se_port_stat_grps);
-#define DEV_STAT_SCSI_TRANSPORT_ATTR(_name, _mode) \
-static struct target_stat_scsi_transport_attribute \
- target_stat_scsi_transport_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_transport_show_attr_##_name, \
- target_stat_scsi_transport_store_attr_##_name);
-
-#define DEV_STAT_SCSI_TRANSPORT_ATTR_RO(_name) \
-static struct target_stat_scsi_transport_attribute \
- target_stat_scsi_transport_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_transport_show_attr_##_name);
-
-static ssize_t target_stat_scsi_transport_show_attr_inst(
- struct se_port_stat_grps *pgrps, char *page)
-{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ */
+static struct se_lun *to_transport_stat(struct config_item *item)
+{
+ struct se_port_stat_grps *pgrps = container_of(to_config_group(item),
+ struct se_port_stat_grps, scsi_transport_group);
+ return container_of(pgrps, struct se_lun, port_stat_grps);
+}
+
+static ssize_t target_stat_transport_inst_show(struct config_item *item,
+ char *page)
+{
+ struct se_lun *lun = to_transport_stat(item);
struct se_device *dev;
ssize_t ret = -ENODEV;
@@ -870,12 +734,11 @@ static ssize_t target_stat_scsi_transport_show_attr_inst(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst);
-static ssize_t target_stat_scsi_transport_show_attr_device(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_transport_device_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_transport_stat(item);
struct se_device *dev;
struct se_portal_group *tpg = lun->lun_tpg;
ssize_t ret = -ENODEV;
@@ -890,12 +753,11 @@ static ssize_t target_stat_scsi_transport_show_attr_device(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device);
-static ssize_t target_stat_scsi_transport_show_attr_indx(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_transport_indx_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_transport_stat(item);
struct se_device *dev;
struct se_portal_group *tpg = lun->lun_tpg;
ssize_t ret = -ENODEV;
@@ -908,12 +770,11 @@ static ssize_t target_stat_scsi_transport_show_attr_indx(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(indx);
-static ssize_t target_stat_scsi_transport_show_attr_dev_name(
- struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_transport_dev_name_show(struct config_item *item,
+ char *page)
{
- struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ struct se_lun *lun = to_transport_stat(item);
struct se_device *dev;
struct se_portal_group *tpg = lun->lun_tpg;
struct t10_wwn *wwn;
@@ -932,26 +793,21 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(dev_name);
-CONFIGFS_EATTR_OPS(target_stat_scsi_transport, se_port_stat_grps,
- scsi_transport_group);
+CONFIGFS_ATTR_RO(target_stat_transport_, inst);
+CONFIGFS_ATTR_RO(target_stat_transport_, device);
+CONFIGFS_ATTR_RO(target_stat_transport_, indx);
+CONFIGFS_ATTR_RO(target_stat_transport_, dev_name);
static struct configfs_attribute *target_stat_scsi_transport_attrs[] = {
- &target_stat_scsi_transport_inst.attr,
- &target_stat_scsi_transport_device.attr,
- &target_stat_scsi_transport_indx.attr,
- &target_stat_scsi_transport_dev_name.attr,
+ &target_stat_transport_attr_inst,
+ &target_stat_transport_attr_device,
+ &target_stat_transport_attr_indx,
+ &target_stat_transport_attr_dev_name,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_transport_attrib_ops = {
- .show_attribute = target_stat_scsi_transport_attr_show,
- .store_attribute = target_stat_scsi_transport_attr_store,
-};
-
static struct config_item_type target_stat_scsi_transport_cit = {
- .ct_item_ops = &target_stat_scsi_transport_attrib_ops,
.ct_attrs = target_stat_scsi_transport_attrs,
.ct_owner = THIS_MODULE,
};
@@ -981,25 +837,17 @@ void target_stat_setup_port_default_groups(struct se_lun *lun)
* SCSI Authorized Initiator Table
*/
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_auth_intr, se_ml_stat_grps);
-#define DEV_STAT_SCSI_AUTH_INTR_ATTR(_name, _mode) \
-static struct target_stat_scsi_auth_intr_attribute \
- target_stat_scsi_auth_intr_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_auth_intr_show_attr_##_name, \
- target_stat_scsi_auth_intr_store_attr_##_name);
-
-#define DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(_name) \
-static struct target_stat_scsi_auth_intr_attribute \
- target_stat_scsi_auth_intr_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_auth_intr_show_attr_##_name);
-
-static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
- struct se_ml_stat_grps *lgrps, char *page)
-{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+static struct se_lun_acl *auth_to_lacl(struct config_item *item)
+{
+ struct se_ml_stat_grps *lgrps = container_of(to_config_group(item),
+ struct se_ml_stat_grps, scsi_auth_intr_group);
+ return container_of(lgrps, struct se_lun_acl, ml_stat_grps);
+}
+
+static ssize_t target_stat_auth_inst_show(struct config_item *item,
+ char *page)
+{
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
struct se_portal_group *tpg;
@@ -1018,13 +866,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(inst);
-static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_dev_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
struct se_lun *lun;
@@ -1042,13 +888,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev);
-static ssize_t target_stat_scsi_auth_intr_show_attr_port(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_port_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
struct se_portal_group *tpg;
@@ -1066,13 +910,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_port(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(port);
-static ssize_t target_stat_scsi_auth_intr_show_attr_indx(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_indx_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1088,13 +930,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_indx(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(indx);
-static ssize_t target_stat_scsi_auth_intr_show_attr_dev_or_port(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_dev_or_port_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1110,13 +950,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev_or_port(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev_or_port);
-static ssize_t target_stat_scsi_auth_intr_show_attr_intr_name(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_intr_name_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1132,13 +970,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_intr_name(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(intr_name);
-static ssize_t target_stat_scsi_auth_intr_show_attr_map_indx(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_map_indx_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1154,13 +990,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_map_indx(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(map_indx);
-static ssize_t target_stat_scsi_auth_intr_show_attr_att_count(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_att_count_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1176,13 +1010,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_att_count(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(att_count);
-static ssize_t target_stat_scsi_auth_intr_show_attr_num_cmds(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_num_cmds_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1199,13 +1031,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_num_cmds(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(num_cmds);
-static ssize_t target_stat_scsi_auth_intr_show_attr_read_mbytes(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1222,13 +1052,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_read_mbytes(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(read_mbytes);
-static ssize_t target_stat_scsi_auth_intr_show_attr_write_mbytes(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1245,13 +1073,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_write_mbytes(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(write_mbytes);
-static ssize_t target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1267,13 +1093,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(hs_num_cmds);
-static ssize_t target_stat_scsi_auth_intr_show_attr_creation_time(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_creation_time_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1290,13 +1114,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_creation_time(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(creation_time);
-static ssize_t target_stat_scsi_auth_intr_show_attr_row_status(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_row_status_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1312,36 +1134,41 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_row_status(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(row_status);
-CONFIGFS_EATTR_OPS(target_stat_scsi_auth_intr, se_ml_stat_grps,
- scsi_auth_intr_group);
+CONFIGFS_ATTR_RO(target_stat_auth_, inst);
+CONFIGFS_ATTR_RO(target_stat_auth_, dev);
+CONFIGFS_ATTR_RO(target_stat_auth_, port);
+CONFIGFS_ATTR_RO(target_stat_auth_, indx);
+CONFIGFS_ATTR_RO(target_stat_auth_, dev_or_port);
+CONFIGFS_ATTR_RO(target_stat_auth_, intr_name);
+CONFIGFS_ATTR_RO(target_stat_auth_, map_indx);
+CONFIGFS_ATTR_RO(target_stat_auth_, att_count);
+CONFIGFS_ATTR_RO(target_stat_auth_, num_cmds);
+CONFIGFS_ATTR_RO(target_stat_auth_, read_mbytes);
+CONFIGFS_ATTR_RO(target_stat_auth_, write_mbytes);
+CONFIGFS_ATTR_RO(target_stat_auth_, hs_num_cmds);
+CONFIGFS_ATTR_RO(target_stat_auth_, creation_time);
+CONFIGFS_ATTR_RO(target_stat_auth_, row_status);
static struct configfs_attribute *target_stat_scsi_auth_intr_attrs[] = {
- &target_stat_scsi_auth_intr_inst.attr,
- &target_stat_scsi_auth_intr_dev.attr,
- &target_stat_scsi_auth_intr_port.attr,
- &target_stat_scsi_auth_intr_indx.attr,
- &target_stat_scsi_auth_intr_dev_or_port.attr,
- &target_stat_scsi_auth_intr_intr_name.attr,
- &target_stat_scsi_auth_intr_map_indx.attr,
- &target_stat_scsi_auth_intr_att_count.attr,
- &target_stat_scsi_auth_intr_num_cmds.attr,
- &target_stat_scsi_auth_intr_read_mbytes.attr,
- &target_stat_scsi_auth_intr_write_mbytes.attr,
- &target_stat_scsi_auth_intr_hs_num_cmds.attr,
- &target_stat_scsi_auth_intr_creation_time.attr,
- &target_stat_scsi_auth_intr_row_status.attr,
+ &target_stat_auth_attr_inst,
+ &target_stat_auth_attr_dev,
+ &target_stat_auth_attr_port,
+ &target_stat_auth_attr_indx,
+ &target_stat_auth_attr_dev_or_port,
+ &target_stat_auth_attr_intr_name,
+ &target_stat_auth_attr_map_indx,
+ &target_stat_auth_attr_att_count,
+ &target_stat_auth_attr_num_cmds,
+ &target_stat_auth_attr_read_mbytes,
+ &target_stat_auth_attr_write_mbytes,
+ &target_stat_auth_attr_hs_num_cmds,
+ &target_stat_auth_attr_creation_time,
+ &target_stat_auth_attr_row_status,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_auth_intr_attrib_ops = {
- .show_attribute = target_stat_scsi_auth_intr_attr_show,
- .store_attribute = target_stat_scsi_auth_intr_attr_store,
-};
-
static struct config_item_type target_stat_scsi_auth_intr_cit = {
- .ct_item_ops = &target_stat_scsi_auth_intr_attrib_ops,
.ct_attrs = target_stat_scsi_auth_intr_attrs,
.ct_owner = THIS_MODULE,
};
@@ -1350,25 +1177,17 @@ static struct config_item_type target_stat_scsi_auth_intr_cit = {
* SCSI Attached Initiator Port Table
*/
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_att_intr_port, se_ml_stat_grps);
-#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR(_name, _mode) \
-static struct target_stat_scsi_att_intr_port_attribute \
- target_stat_scsi_att_intr_port_##_name = \
- __CONFIGFS_EATTR(_name, _mode, \
- target_stat_scsi_att_intr_port_show_attr_##_name, \
- target_stat_scsi_att_intr_port_store_attr_##_name);
-
-#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(_name) \
-static struct target_stat_scsi_att_intr_port_attribute \
- target_stat_scsi_att_intr_port_##_name = \
- __CONFIGFS_EATTR_RO(_name, \
- target_stat_scsi_att_intr_port_show_attr_##_name);
-
-static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
- struct se_ml_stat_grps *lgrps, char *page)
-{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+static struct se_lun_acl *iport_to_lacl(struct config_item *item)
+{
+ struct se_ml_stat_grps *lgrps = container_of(to_config_group(item),
+ struct se_ml_stat_grps, scsi_att_intr_port_group);
+ return container_of(lgrps, struct se_lun_acl, ml_stat_grps);
+}
+
+static ssize_t target_stat_iport_inst_show(struct config_item *item,
+ char *page)
+{
+ struct se_lun_acl *lacl = iport_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
struct se_portal_group *tpg;
@@ -1387,13 +1206,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(inst);
-static ssize_t target_stat_scsi_att_intr_port_show_attr_dev(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_dev_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = iport_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
struct se_lun *lun;
@@ -1411,13 +1228,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_dev(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(dev);
-static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_port_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = iport_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
struct se_portal_group *tpg;
@@ -1435,13 +1250,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port);
-static ssize_t target_stat_scsi_att_intr_port_show_attr_indx(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_indx_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = iport_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_session *se_sess;
struct se_portal_group *tpg;
@@ -1461,13 +1274,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_indx(
spin_unlock_irq(&nacl->nacl_sess_lock);
return ret;
}
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(indx);
-static ssize_t target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_port_auth_indx_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = iport_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve;
ssize_t ret;
@@ -1483,13 +1294,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
rcu_read_unlock();
return ret;
}
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_auth_indx);
-static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
- struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_port_ident_show(struct config_item *item,
+ char *page)
{
- struct se_lun_acl *lacl = container_of(lgrps,
- struct se_lun_acl, ml_stat_grps);
+ struct se_lun_acl *lacl = iport_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_session *se_sess;
struct se_portal_group *tpg;
@@ -1513,28 +1322,25 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
spin_unlock_irq(&nacl->nacl_sess_lock);
return ret;
}
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_ident);
-CONFIGFS_EATTR_OPS(target_stat_scsi_att_intr_port, se_ml_stat_grps,
- scsi_att_intr_port_group);
+CONFIGFS_ATTR_RO(target_stat_iport_, inst);
+CONFIGFS_ATTR_RO(target_stat_iport_, dev);
+CONFIGFS_ATTR_RO(target_stat_iport_, port);
+CONFIGFS_ATTR_RO(target_stat_iport_, indx);
+CONFIGFS_ATTR_RO(target_stat_iport_, port_auth_indx);
+CONFIGFS_ATTR_RO(target_stat_iport_, port_ident);
static struct configfs_attribute *target_stat_scsi_ath_intr_port_attrs[] = {
- &target_stat_scsi_att_intr_port_inst.attr,
- &target_stat_scsi_att_intr_port_dev.attr,
- &target_stat_scsi_att_intr_port_port.attr,
- &target_stat_scsi_att_intr_port_indx.attr,
- &target_stat_scsi_att_intr_port_port_auth_indx.attr,
- &target_stat_scsi_att_intr_port_port_ident.attr,
+ &target_stat_iport_attr_inst,
+ &target_stat_iport_attr_dev,
+ &target_stat_iport_attr_port,
+ &target_stat_iport_attr_indx,
+ &target_stat_iport_attr_port_auth_indx,
+ &target_stat_iport_attr_port_ident,
NULL,
};
-static struct configfs_item_operations target_stat_scsi_att_intr_port_attrib_ops = {
- .show_attribute = target_stat_scsi_att_intr_port_attr_show,
- .store_attribute = target_stat_scsi_att_intr_port_attr_store,
-};
-
static struct config_item_type target_stat_scsi_att_intr_port_cit = {
- .ct_item_ops = &target_stat_scsi_att_intr_port_attrib_ops,
.ct_attrs = target_stat_scsi_ath_intr_port_attrs,
.ct_owner = THIS_MODULE,
};
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index aa3caca8bace..064d6dfb5b6d 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -36,7 +36,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
#include "tcm_fc.h"
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 16670933013b..85aeaa0ad303 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -38,8 +38,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include "tcm_fc.h"
@@ -131,55 +129,51 @@ static ssize_t ft_wwn_store(void *arg, const char *buf, size_t len)
* ACL auth ops.
*/
-static ssize_t ft_nacl_show_port_name(
- struct se_node_acl *se_nacl,
- char *page)
+static ssize_t ft_nacl_port_name_show(struct config_item *item, char *page)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
struct ft_node_acl *acl = container_of(se_nacl,
struct ft_node_acl, se_node_acl);
return ft_wwn_show(&acl->node_auth.port_name, page);
}
-static ssize_t ft_nacl_store_port_name(
- struct se_node_acl *se_nacl,
- const char *page,
- size_t count)
+static ssize_t ft_nacl_port_name_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
struct ft_node_acl *acl = container_of(se_nacl,
struct ft_node_acl, se_node_acl);
return ft_wwn_store(&acl->node_auth.port_name, page, count);
}
-TF_NACL_BASE_ATTR(ft, port_name, S_IRUGO | S_IWUSR);
-
-static ssize_t ft_nacl_show_node_name(
- struct se_node_acl *se_nacl,
- char *page)
+static ssize_t ft_nacl_node_name_show(struct config_item *item,
+ char *page)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
struct ft_node_acl *acl = container_of(se_nacl,
struct ft_node_acl, se_node_acl);
return ft_wwn_show(&acl->node_auth.node_name, page);
}
-static ssize_t ft_nacl_store_node_name(
- struct se_node_acl *se_nacl,
- const char *page,
- size_t count)
+static ssize_t ft_nacl_node_name_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_node_acl *se_nacl = acl_to_nacl(item);
struct ft_node_acl *acl = container_of(se_nacl,
struct ft_node_acl, se_node_acl);
return ft_wwn_store(&acl->node_auth.node_name, page, count);
}
-TF_NACL_BASE_ATTR(ft, node_name, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(ft_nacl_, node_name);
+CONFIGFS_ATTR(ft_nacl_, port_name);
static struct configfs_attribute *ft_nacl_base_attrs[] = {
- &ft_nacl_port_name.attr,
- &ft_nacl_node_name.attr,
+ &ft_nacl_attr_port_name,
+ &ft_nacl_attr_node_name,
NULL,
};
@@ -386,18 +380,16 @@ static void ft_del_wwn(struct se_wwn *wwn)
kfree(ft_wwn);
}
-static ssize_t ft_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t ft_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "TCM FC " FT_VERSION " on %s/%s on "
""UTS_RELEASE"\n", utsname()->sysname, utsname()->machine);
}
-TF_WWN_ATTR_RO(ft, version);
+CONFIGFS_ATTR_RO(ft_wwn_, version);
static struct configfs_attribute *ft_wwn_attrs[] = {
- &ft_wwn_version.attr,
+ &ft_wwn_attr_version,
NULL,
};
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index 4b0fedd6bd4b..847c1aa6fbf4 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -44,7 +44,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
#include "tcm_fc.h"
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 31a9e3fb98c5..7b934eac995d 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -36,7 +36,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
#include "tcm_fc.h"
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5aabc4bc0d75..c463c89b90ef 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -147,6 +147,20 @@ config CLOCK_THERMAL
device that is configured to use this cooling mechanism will be
controlled to reduce clock frequency whenever temperature is high.
+config DEVFREQ_THERMAL
+ bool "Generic device cooling support"
+ depends on PM_DEVFREQ
+ depends on PM_OPP
+ help
+ This implements the generic devfreq cooling mechanism through
+ frequency reduction for devices using devfreq.
+
+ This will throttle the device by limiting the maximum allowed DVFS
+ frequency corresponding to the cooling level.
+
+ In order to use the power extensions of the cooling device,
+ devfreq should use the simple_ondemand governor.
+
If you want this support, you should say Y here.
config THERMAL_EMULATION
@@ -275,6 +289,7 @@ config X86_PKG_TEMP_THERMAL
tristate "X86 package temperature thermal driver"
depends on X86_THERMAL_VECTOR
select THERMAL_GOV_USER_SPACE
+ select THERMAL_WRITABLE_TRIPS
default m
help
Enable this to register CPU digital sensor for package temperature as
@@ -296,6 +311,7 @@ config INTEL_SOC_DTS_THERMAL
tristate "Intel SoCs DTS thermal driver"
depends on X86
select INTEL_SOC_DTS_IOSF_CORE
+ select THERMAL_WRITABLE_TRIPS
help
Enable this to register Intel SoCs (e.g. Bay Trail) platform digital
temperature sensor (DTS). These SoCs have two additional DTSs in
@@ -322,6 +338,7 @@ config INT340X_THERMAL
select ACPI_THERMAL_REL
select ACPI_FAN
select INTEL_SOC_DTS_IOSF_CORE
+ select THERMAL_WRITABLE_TRIPS
help
Newer laptops and tablets that use ACPI may have thermal sensors and
other devices with thermal control capabilities outside the core
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 26f160809959..cfae6a654793 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -22,6 +22,9 @@ thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
# clock cooling
thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
+# devfreq cooling
+thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
+
# platform thermal drivers
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 26b8d326546a..ae75328945f7 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -224,9 +224,9 @@ static const struct armada_thermal_data armada380_data = {
.is_valid_shift = 10,
.temp_shift = 0,
.temp_mask = 0x3ff,
- .coef_b = 2931108200UL,
- .coef_m = 5000000UL,
- .coef_div = 10502,
+ .coef_b = 1172499100UL,
+ .coef_m = 2000096UL,
+ .coef_div = 4201,
.inverted = true,
};
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 42c6f71bdcc1..e3fbc5a5d88f 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -591,8 +591,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
if (trace_thermal_power_cpu_get_power_enabled()) {
u32 ncpus = cpumask_weight(&cpufreq_device->allowed_cpus);
- load_cpu = devm_kcalloc(&cdev->device, ncpus, sizeof(*load_cpu),
- GFP_KERNEL);
+ load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
}
for_each_cpu(cpu, &cpufreq_device->allowed_cpus) {
@@ -615,8 +614,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
dynamic_power = get_dynamic_power(cpufreq_device, freq);
ret = get_static_power(cpufreq_device, tz, freq, &static_power);
if (ret) {
- if (load_cpu)
- devm_kfree(&cdev->device, load_cpu);
+ kfree(load_cpu);
return ret;
}
@@ -625,7 +623,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
&cpufreq_device->allowed_cpus,
freq, load_cpu, i, dynamic_power, static_power);
- devm_kfree(&cdev->device, load_cpu);
+ kfree(load_cpu);
}
*power = static_power + dynamic_power;
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
new file mode 100644
index 000000000000..01f0015f80dc
--- /dev/null
+++ b/drivers/thermal/devfreq_cooling.c
@@ -0,0 +1,573 @@
+/*
+ * devfreq_cooling: Thermal cooling device implementation for devices using
+ * devfreq
+ *
+ * Copyright (C) 2014-2015 ARM Limited
+ *
+ * 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 "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.
+ *
+ * TODO:
+ * - If OPPs are added or removed after devfreq cooling has
+ * registered, the devfreq cooling won't react to it.
+ */
+
+#include <linux/devfreq.h>
+#include <linux/devfreq_cooling.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/pm_opp.h>
+#include <linux/thermal.h>
+
+#include <trace/events/thermal.h>
+
+static DEFINE_MUTEX(devfreq_lock);
+static DEFINE_IDR(devfreq_idr);
+
+/**
+ * struct devfreq_cooling_device - Devfreq cooling device
+ * @id: unique integer value corresponding to each
+ * devfreq_cooling_device registered.
+ * @cdev: Pointer to associated thermal cooling device.
+ * @devfreq: Pointer to associated devfreq device.
+ * @cooling_state: Current cooling state.
+ * @power_table: Pointer to table with maximum power draw for each
+ * cooling state. State is the index into the table, and
+ * the power is in mW.
+ * @freq_table: Pointer to a table with the frequencies sorted in descending
+ * order. You can index the table by cooling device state
+ * @freq_table_size: Size of the @freq_table and @power_table
+ * @power_ops: Pointer to devfreq_cooling_power, used to generate the
+ * @power_table.
+ */
+struct devfreq_cooling_device {
+ int id;
+ struct thermal_cooling_device *cdev;
+ struct devfreq *devfreq;
+ unsigned long cooling_state;
+ u32 *power_table;
+ u32 *freq_table;
+ size_t freq_table_size;
+ struct devfreq_cooling_power *power_ops;
+};
+
+/**
+ * get_idr - function to get a unique id.
+ * @idr: struct idr * handle used to create a id.
+ * @id: int * value generated by this function.
+ *
+ * This function will populate @id with an unique
+ * id, using the idr API.
+ *
+ * Return: 0 on success, an error code on failure.
+ */
+static int get_idr(struct idr *idr, int *id)
+{
+ int ret;
+
+ mutex_lock(&devfreq_lock);
+ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ mutex_unlock(&devfreq_lock);
+ if (unlikely(ret < 0))
+ return ret;
+ *id = ret;
+
+ return 0;
+}
+
+/**
+ * release_idr - function to free the unique id.
+ * @idr: struct idr * handle used for creating the id.
+ * @id: int value representing the unique id.
+ */
+static void release_idr(struct idr *idr, int id)
+{
+ mutex_lock(&devfreq_lock);
+ idr_remove(idr, id);
+ mutex_unlock(&devfreq_lock);
+}
+
+/**
+ * partition_enable_opps() - disable all opps above a given state
+ * @dfc: Pointer to devfreq we are operating on
+ * @cdev_state: cooling device state we're setting
+ *
+ * Go through the OPPs of the device, enabling all OPPs until
+ * @cdev_state and disabling those frequencies above it.
+ */
+static int partition_enable_opps(struct devfreq_cooling_device *dfc,
+ unsigned long cdev_state)
+{
+ int i;
+ struct device *dev = dfc->devfreq->dev.parent;
+
+ for (i = 0; i < dfc->freq_table_size; i++) {
+ struct dev_pm_opp *opp;
+ int ret = 0;
+ unsigned int freq = dfc->freq_table[i];
+ bool want_enable = i >= cdev_state ? true : false;
+
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable);
+ rcu_read_unlock();
+
+ if (PTR_ERR(opp) == -ERANGE)
+ continue;
+ else if (IS_ERR(opp))
+ return PTR_ERR(opp);
+
+ if (want_enable)
+ ret = dev_pm_opp_enable(dev, freq);
+ else
+ ret = dev_pm_opp_disable(dev, freq);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct devfreq_cooling_device *dfc = cdev->devdata;
+
+ *state = dfc->freq_table_size - 1;
+
+ return 0;
+}
+
+static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct devfreq_cooling_device *dfc = cdev->devdata;
+
+ *state = dfc->cooling_state;
+
+ return 0;
+}
+
+static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+{
+ struct devfreq_cooling_device *dfc = cdev->devdata;
+ struct devfreq *df = dfc->devfreq;
+ struct device *dev = df->dev.parent;
+ int ret;
+
+ if (state == dfc->cooling_state)
+ return 0;
+
+ dev_dbg(dev, "Setting cooling state %lu\n", state);
+
+ if (state >= dfc->freq_table_size)
+ return -EINVAL;
+
+ ret = partition_enable_opps(dfc, state);
+ if (ret)
+ return ret;
+
+ dfc->cooling_state = state;
+
+ return 0;
+}
+
+/**
+ * freq_get_state() - get the cooling state corresponding to a frequency
+ * @dfc: Pointer to devfreq cooling device
+ * @freq: frequency in Hz
+ *
+ * Return: the cooling state associated with the @freq, or
+ * THERMAL_CSTATE_INVALID if it wasn't found.
+ */
+static unsigned long
+freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq)
+{
+ int i;
+
+ for (i = 0; i < dfc->freq_table_size; i++) {
+ if (dfc->freq_table[i] == freq)
+ return i;
+ }
+
+ return THERMAL_CSTATE_INVALID;
+}
+
+/**
+ * get_static_power() - calculate the static power
+ * @dfc: Pointer to devfreq cooling device
+ * @freq: Frequency in Hz
+ *
+ * Calculate the static power in milliwatts using the supplied
+ * get_static_power(). The current voltage is calculated using the
+ * OPP library. If no get_static_power() was supplied, assume the
+ * static power is negligible.
+ */
+static unsigned long
+get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
+{
+ struct devfreq *df = dfc->devfreq;
+ struct device *dev = df->dev.parent;
+ unsigned long voltage;
+ struct dev_pm_opp *opp;
+
+ if (!dfc->power_ops->get_static_power)
+ return 0;
+
+ rcu_read_lock();
+
+ opp = dev_pm_opp_find_freq_exact(dev, freq, true);
+ if (IS_ERR(opp) && (PTR_ERR(opp) == -ERANGE))
+ opp = dev_pm_opp_find_freq_exact(dev, freq, false);
+
+ voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
+
+ rcu_read_unlock();
+
+ if (voltage == 0) {
+ dev_warn_ratelimited(dev,
+ "Failed to get voltage for frequency %lu: %ld\n",
+ freq, IS_ERR(opp) ? PTR_ERR(opp) : 0);
+ return 0;
+ }
+
+ return dfc->power_ops->get_static_power(voltage);
+}
+
+/**
+ * get_dynamic_power - calculate the dynamic power
+ * @dfc: Pointer to devfreq cooling device
+ * @freq: Frequency in Hz
+ * @voltage: Voltage in millivolts
+ *
+ * Calculate the dynamic power in milliwatts consumed by the device at
+ * frequency @freq and voltage @voltage. If the get_dynamic_power()
+ * was supplied as part of the devfreq_cooling_power struct, then that
+ * function is used. Otherwise, a simple power model (Pdyn = Coeff *
+ * Voltage^2 * Frequency) is used.
+ */
+static unsigned long
+get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq,
+ unsigned long voltage)
+{
+ u64 power;
+ u32 freq_mhz;
+ struct devfreq_cooling_power *dfc_power = dfc->power_ops;
+
+ if (dfc_power->get_dynamic_power)
+ return dfc_power->get_dynamic_power(freq, voltage);
+
+ freq_mhz = freq / 1000000;
+ power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage;
+ do_div(power, 1000000000);
+
+ return power;
+}
+
+static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz,
+ u32 *power)
+{
+ struct devfreq_cooling_device *dfc = cdev->devdata;
+ struct devfreq *df = dfc->devfreq;
+ struct devfreq_dev_status *status = &df->last_status;
+ unsigned long state;
+ unsigned long freq = status->current_frequency;
+ u32 dyn_power, static_power;
+
+ /* Get dynamic power for state */
+ state = freq_get_state(dfc, freq);
+ if (state == THERMAL_CSTATE_INVALID)
+ return -EAGAIN;
+
+ dyn_power = dfc->power_table[state];
+
+ /* Scale dynamic power for utilization */
+ dyn_power = (dyn_power * status->busy_time) / status->total_time;
+
+ /* Get static power */
+ static_power = get_static_power(dfc, freq);
+
+ trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power,
+ static_power);
+
+ *power = dyn_power + static_power;
+
+ return 0;
+}
+
+static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz,
+ unsigned long state,
+ u32 *power)
+{
+ struct devfreq_cooling_device *dfc = cdev->devdata;
+ unsigned long freq;
+ u32 static_power;
+
+ if (state < 0 || state >= dfc->freq_table_size)
+ return -EINVAL;
+
+ freq = dfc->freq_table[state];
+ static_power = get_static_power(dfc, freq);
+
+ *power = dfc->power_table[state] + static_power;
+ return 0;
+}
+
+static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz,
+ u32 power, unsigned long *state)
+{
+ struct devfreq_cooling_device *dfc = cdev->devdata;
+ struct devfreq *df = dfc->devfreq;
+ struct devfreq_dev_status *status = &df->last_status;
+ unsigned long freq = status->current_frequency;
+ unsigned long busy_time;
+ s32 dyn_power;
+ u32 static_power;
+ int i;
+
+ static_power = get_static_power(dfc, freq);
+
+ dyn_power = power - static_power;
+ dyn_power = dyn_power > 0 ? dyn_power : 0;
+
+ /* Scale dynamic power for utilization */
+ busy_time = status->busy_time ?: 1;
+ dyn_power = (dyn_power * status->total_time) / busy_time;
+
+ /*
+ * Find the first cooling state that is within the power
+ * budget for dynamic power.
+ */
+ for (i = 0; i < dfc->freq_table_size - 1; i++)
+ if (dyn_power >= dfc->power_table[i])
+ break;
+
+ *state = i;
+ trace_thermal_power_devfreq_limit(cdev, freq, *state, power);
+ return 0;
+}
+
+static struct thermal_cooling_device_ops devfreq_cooling_ops = {
+ .get_max_state = devfreq_cooling_get_max_state,
+ .get_cur_state = devfreq_cooling_get_cur_state,
+ .set_cur_state = devfreq_cooling_set_cur_state,
+};
+
+/**
+ * devfreq_cooling_gen_tables() - Generate power and freq tables.
+ * @dfc: Pointer to devfreq cooling device.
+ *
+ * Generate power and frequency tables: the power table hold the
+ * device's maximum power usage at each cooling state (OPP). The
+ * static and dynamic power using the appropriate voltage and
+ * frequency for the state, is acquired from the struct
+ * devfreq_cooling_power, and summed to make the maximum power draw.
+ *
+ * The frequency table holds the frequencies in descending order.
+ * That way its indexed by cooling device state.
+ *
+ * The tables are malloced, and pointers put in dfc. They must be
+ * freed when unregistering the devfreq cooling device.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
+{
+ struct devfreq *df = dfc->devfreq;
+ struct device *dev = df->dev.parent;
+ int ret, num_opps;
+ unsigned long freq;
+ u32 *power_table = NULL;
+ u32 *freq_table;
+ int i;
+
+ num_opps = dev_pm_opp_get_opp_count(dev);
+
+ if (dfc->power_ops) {
+ power_table = kcalloc(num_opps, sizeof(*power_table),
+ GFP_KERNEL);
+ if (!power_table)
+ return -ENOMEM;
+ }
+
+ freq_table = kcalloc(num_opps, sizeof(*freq_table),
+ GFP_KERNEL);
+ if (!freq_table) {
+ ret = -ENOMEM;
+ goto free_power_table;
+ }
+
+ for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) {
+ unsigned long power_dyn, voltage;
+ struct dev_pm_opp *opp;
+
+ rcu_read_lock();
+
+ opp = dev_pm_opp_find_freq_floor(dev, &freq);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ ret = PTR_ERR(opp);
+ goto free_tables;
+ }
+
+ voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
+
+ rcu_read_unlock();
+
+ if (dfc->power_ops) {
+ power_dyn = get_dynamic_power(dfc, freq, voltage);
+
+ dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n",
+ freq / 1000000, voltage, power_dyn, power_dyn);
+
+ power_table[i] = power_dyn;
+ }
+
+ freq_table[i] = freq;
+ }
+
+ if (dfc->power_ops)
+ dfc->power_table = power_table;
+
+ dfc->freq_table = freq_table;
+ dfc->freq_table_size = num_opps;
+
+ return 0;
+
+free_tables:
+ kfree(freq_table);
+free_power_table:
+ kfree(power_table);
+
+ return ret;
+}
+
+/**
+ * of_devfreq_cooling_register_power() - Register devfreq cooling device,
+ * with OF and power information.
+ * @np: Pointer to OF device_node.
+ * @df: Pointer to devfreq device.
+ * @dfc_power: Pointer to devfreq_cooling_power.
+ *
+ * Register a devfreq cooling device. The available OPPs must be
+ * registered on the device.
+ *
+ * If @dfc_power is provided, the cooling device is registered with the
+ * power extensions. For the power extensions to work correctly,
+ * devfreq should use the simple_ondemand governor, other governors
+ * are not currently supported.
+ */
+struct thermal_cooling_device *
+of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
+ struct devfreq_cooling_power *dfc_power)
+{
+ struct thermal_cooling_device *cdev;
+ struct devfreq_cooling_device *dfc;
+ char dev_name[THERMAL_NAME_LENGTH];
+ int err;
+
+ dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);
+ if (!dfc)
+ return ERR_PTR(-ENOMEM);
+
+ dfc->devfreq = df;
+
+ if (dfc_power) {
+ dfc->power_ops = dfc_power;
+
+ devfreq_cooling_ops.get_requested_power =
+ devfreq_cooling_get_requested_power;
+ devfreq_cooling_ops.state2power = devfreq_cooling_state2power;
+ devfreq_cooling_ops.power2state = devfreq_cooling_power2state;
+ }
+
+ err = devfreq_cooling_gen_tables(dfc);
+ if (err)
+ goto free_dfc;
+
+ err = get_idr(&devfreq_idr, &dfc->id);
+ if (err)
+ goto free_tables;
+
+ snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id);
+
+ cdev = thermal_of_cooling_device_register(np, dev_name, dfc,
+ &devfreq_cooling_ops);
+ if (IS_ERR(cdev)) {
+ err = PTR_ERR(cdev);
+ dev_err(df->dev.parent,
+ "Failed to register devfreq cooling device (%d)\n",
+ err);
+ goto release_idr;
+ }
+
+ dfc->cdev = cdev;
+
+ return cdev;
+
+release_idr:
+ release_idr(&devfreq_idr, dfc->id);
+free_tables:
+ kfree(dfc->power_table);
+ kfree(dfc->freq_table);
+free_dfc:
+ kfree(dfc);
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power);
+
+/**
+ * of_devfreq_cooling_register() - Register devfreq cooling device,
+ * with OF information.
+ * @np: Pointer to OF device_node.
+ * @df: Pointer to devfreq device.
+ */
+struct thermal_cooling_device *
+of_devfreq_cooling_register(struct device_node *np, struct devfreq *df)
+{
+ return of_devfreq_cooling_register_power(np, df, NULL);
+}
+EXPORT_SYMBOL_GPL(of_devfreq_cooling_register);
+
+/**
+ * devfreq_cooling_register() - Register devfreq cooling device.
+ * @df: Pointer to devfreq device.
+ */
+struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df)
+{
+ return of_devfreq_cooling_register(NULL, df);
+}
+EXPORT_SYMBOL_GPL(devfreq_cooling_register);
+
+/**
+ * devfreq_cooling_unregister() - Unregister devfreq cooling device.
+ * @dfc: Pointer to devfreq cooling device to unregister.
+ */
+void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
+{
+ struct devfreq_cooling_device *dfc;
+
+ if (!cdev)
+ return;
+
+ dfc = cdev->devdata;
+
+ thermal_cooling_device_unregister(dfc->cdev);
+ release_idr(&devfreq_idr, dfc->id);
+ kfree(dfc->power_table);
+ kfree(dfc->freq_table);
+
+ kfree(dfc);
+}
+EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 4bec1d3c3d27..c8fe3cac2e0e 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -288,7 +288,7 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
if (trip == IMX_TRIP_CRITICAL)
return -EPERM;
- if (temp > IMX_TEMP_PASSIVE)
+ if (temp < 0 || temp > IMX_TEMP_PASSIVE)
return -EINVAL;
data->temp_passive = temp;
@@ -487,14 +487,6 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (data->irq < 0)
return data->irq;
- ret = devm_request_threaded_irq(&pdev->dev, data->irq,
- imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
- 0, "imx_thermal", data);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
- return ret;
- }
-
platform_set_drvdata(pdev, data);
ret = imx_get_sensor_data(pdev);
@@ -571,6 +563,17 @@ static int imx_thermal_probe(struct platform_device *pdev)
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ ret = devm_request_threaded_irq(&pdev->dev, data->irq,
+ imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
+ 0, "imx_thermal", data);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
+ clk_disable_unprepare(data->thermal_clk);
+ thermal_zone_device_unregister(data->tz);
+ cpufreq_cooling_unregister(data->cdev);
+ return ret;
+ }
+
data->irq_enabled = true;
data->mode = THERMAL_DEVICE_ENABLED;
diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c
index e570ff084add..f0fbea386869 100644
--- a/drivers/thermal/power_allocator.c
+++ b/drivers/thermal/power_allocator.c
@@ -228,7 +228,7 @@ static u32 pid_controller(struct thermal_zone_device *tz,
if (err < int_to_frac(tz->tzp->integral_cutoff)) {
s64 i_next = i + mul_frac(tz->tzp->k_i, err);
- if (abs64(i_next) < max_power_frac) {
+ if (abs(i_next) < max_power_frac) {
i = i_next;
params->err_integral += err;
}
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index c89ffb26a354..9787e8aa509f 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/thermal.h>
+#include <linux/pinctrl/consumer.h>
/**
* If the temperature over a period of time High,
@@ -106,16 +107,14 @@ struct rockchip_thermal_data {
#define TSADCV2_AUTO_PERIOD_HT 0x6c
#define TSADCV2_AUTO_EN BIT(0)
-#define TSADCV2_AUTO_DISABLE ~BIT(0)
#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
-#define TSADCV2_AUTO_TSHUT_POLARITY_LOW ~BIT(8)
#define TSADCV2_INT_SRC_EN(chn) BIT(chn)
#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
-#define TSADCV2_INT_PD_CLEAR ~BIT(8)
+#define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)
#define TSADCV2_DATA_MASK 0xfff
#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
@@ -124,7 +123,7 @@ struct rockchip_thermal_data {
#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */
struct tsadc_table {
- unsigned long code;
+ u32 code;
long temp;
};
@@ -164,7 +163,6 @@ static const struct tsadc_table v2_code_table[] = {
{3452, 115000},
{3437, 120000},
{3421, 125000},
- {0, 125000},
};
static u32 rk_tsadcv2_temp_to_code(long temp)
@@ -191,19 +189,21 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
return 0;
}
-static int rk_tsadcv2_code_to_temp(u32 code)
+static int rk_tsadcv2_code_to_temp(u32 code, int *temp)
{
- unsigned int low = 0;
+ unsigned int low = 1;
unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
unsigned int mid = (low + high) / 2;
unsigned int num;
unsigned long denom;
- /* Invalid code, return -EAGAIN */
- if (code > TSADCV2_DATA_MASK)
- return -EAGAIN;
+ BUILD_BUG_ON(ARRAY_SIZE(v2_code_table) < 2);
- while (low <= high && mid) {
+ code &= TSADCV2_DATA_MASK;
+ if (code < v2_code_table[high].code)
+ return -EAGAIN; /* Incorrect reading */
+
+ while (low <= high) {
if (code >= v2_code_table[mid].code &&
code < v2_code_table[mid - 1].code)
break;
@@ -223,7 +223,9 @@ static int rk_tsadcv2_code_to_temp(u32 code)
num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp;
num *= v2_code_table[mid - 1].code - code;
denom = v2_code_table[mid - 1].code - v2_code_table[mid].code;
- return v2_code_table[mid - 1].temp + (num / denom);
+ *temp = v2_code_table[mid - 1].temp + (num / denom);
+
+ return 0;
}
/**
@@ -241,10 +243,10 @@ static void rk_tsadcv2_initialize(void __iomem *regs,
enum tshut_polarity tshut_polarity)
{
if (tshut_polarity == TSHUT_HIGH_ACTIVE)
- writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_HIGH),
+ writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
regs + TSADCV2_AUTO_CON);
else
- writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_LOW),
+ writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
regs + TSADCV2_AUTO_CON);
writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
@@ -261,7 +263,7 @@ static void rk_tsadcv2_irq_ack(void __iomem *regs)
u32 val;
val = readl_relaxed(regs + TSADCV2_INT_PD);
- writel_relaxed(val & TSADCV2_INT_PD_CLEAR, regs + TSADCV2_INT_PD);
+ writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
}
static void rk_tsadcv2_control(void __iomem *regs, bool enable)
@@ -281,14 +283,9 @@ static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, int *temp)
{
u32 val;
- /* the A/D value of the channel last conversion need some time */
val = readl_relaxed(regs + TSADCV2_DATA(chn));
- if (val == 0)
- return -EAGAIN;
- *temp = rk_tsadcv2_code_to_temp(val);
-
- return 0;
+ return rk_tsadcv2_code_to_temp(val, temp);
}
static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long temp)
@@ -642,6 +639,8 @@ static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
clk_disable(thermal->pclk);
clk_disable(thermal->clk);
+ pinctrl_pm_select_sleep_state(dev);
+
return 0;
}
@@ -678,6 +677,8 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
+ pinctrl_pm_select_default_state(dev);
+
return 0;
}
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 0bae8cc6c23a..fa61eff88496 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -548,7 +548,7 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev)
default:
pdata->cal_type = TYPE_ONE_POINT_TRIMMING;
break;
- };
+ }
dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
cal_type ? 2 : 1);
@@ -608,7 +608,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
unsigned int trim_info = 0, con, rising_threshold;
- int ret = 0, threshold_code;
+ int threshold_code;
int crit_temp = 0;
/*
@@ -651,7 +651,8 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
/* Clear the PMIN in the common TMU register */
if (!data->id)
writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
- return ret;
+
+ return 0;
}
static int exynos7_tmu_initialize(struct platform_device *pdev)
@@ -932,7 +933,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
if (data->soc == SOC_ARCH_EXYNOS5260)
emul_con = EXYNOS5260_EMUL_CON;
- if (data->soc == SOC_ARCH_EXYNOS5433)
+ else if (data->soc == SOC_ARCH_EXYNOS5433)
emul_con = EXYNOS5433_TMU_EMUL_CON;
else if (data->soc == SOC_ARCH_EXYNOS7)
emul_con = EXYNOS7_TMU_REG_EMUL_CON;
@@ -1168,27 +1169,10 @@ static int exynos_map_dt_data(struct platform_device *pdev)
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct exynos_tmu_platform_data *pdata;
struct resource res;
- int ret;
if (!data || !pdev->dev.of_node)
return -ENODEV;
- /*
- * Try enabling the regulator if found
- * TODO: Add regulator as an SOC feature, so that regulator enable
- * is a compulsory call.
- */
- data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
- if (!IS_ERR(data->regulator)) {
- ret = regulator_enable(data->regulator);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable vtmu\n");
- return ret;
- }
- } else {
- dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
- }
-
data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
if (data->id < 0)
data->id = 0;
@@ -1306,12 +1290,22 @@ static int exynos_tmu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
mutex_init(&data->lock);
- data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
- &exynos_sensor_ops);
- if (IS_ERR(data->tzd)) {
- pr_err("thermal: tz: %p ERROR\n", data->tzd);
- return PTR_ERR(data->tzd);
+ /*
+ * Try enabling the regulator if found
+ * TODO: Add regulator as an SOC feature, so that regulator enable
+ * is a compulsory call.
+ */
+ data->regulator = devm_regulator_get(&pdev->dev, "vtmu");
+ if (!IS_ERR(data->regulator)) {
+ ret = regulator_enable(data->regulator);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable vtmu\n");
+ return ret;
+ }
+ } else {
+ dev_info(&pdev->dev, "Regulator node (vtmu) not found\n");
}
+
ret = exynos_map_dt_data(pdev);
if (ret)
goto err_sensor;
@@ -1363,23 +1357,38 @@ static int exynos_tmu_probe(struct platform_device *pdev)
break;
default:
break;
- };
+ }
+
+ /*
+ * data->tzd must be registered before calling exynos_tmu_initialize(),
+ * requesting irq and calling exynos_tmu_control().
+ */
+ data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
+ &exynos_sensor_ops);
+ if (IS_ERR(data->tzd)) {
+ ret = PTR_ERR(data->tzd);
+ dev_err(&pdev->dev, "Failed to register sensor: %d\n", ret);
+ goto err_sclk;
+ }
ret = exynos_tmu_initialize(pdev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize TMU\n");
- goto err_sclk;
+ goto err_thermal;
}
ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
- goto err_sclk;
+ goto err_thermal;
}
exynos_tmu_control(pdev, true);
return 0;
+
+err_thermal:
+ thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
err_sclk:
clk_disable_unprepare(data->sclk);
err_clk:
@@ -1388,9 +1397,8 @@ err_clk_sec:
if (!IS_ERR(data->clk_sec))
clk_unprepare(data->clk_sec);
err_sensor:
- if (!IS_ERR_OR_NULL(data->regulator))
+ if (!IS_ERR(data->regulator))
regulator_disable(data->regulator);
- thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
return ret;
}
diff --git a/drivers/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig
index cb6686ff09ae..ea8283f08aa6 100644
--- a/drivers/thermal/ti-soc-thermal/Kconfig
+++ b/drivers/thermal/ti-soc-thermal/Kconfig
@@ -19,6 +19,21 @@ config TI_THERMAL
This includes trip points definitions, extrapolation rules and
CPU cooling device bindings.
+config OMAP3_THERMAL
+ bool "Texas Instruments OMAP3 thermal support"
+ depends on TI_SOC_THERMAL
+ depends on ARCH_OMAP3 || COMPILE_TEST
+ help
+ If you say yes here you get thermal support for the Texas Instruments
+ OMAP3 SoC family. The current chips supported are:
+ - OMAP3430
+
+ OMAP3 chips normally don't need thermal management, and sensors in
+ this generation are not accurate, nor they are very close to
+ the important hotspots.
+
+ Say 'N' here.
+
config OMAP4_THERMAL
bool "Texas Instruments OMAP4 thermal support"
depends on TI_SOC_THERMAL
diff --git a/drivers/thermal/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile
index 1226b2484e55..0f89bdf03790 100644
--- a/drivers/thermal/ti-soc-thermal/Makefile
+++ b/drivers/thermal/ti-soc-thermal/Makefile
@@ -2,5 +2,6 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o
ti-soc-thermal-y := ti-bandgap.o
ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o
ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o
+ti-soc-thermal-$(CONFIG_OMAP3_THERMAL) += omap3-thermal-data.o
ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o
ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o
diff --git a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
new file mode 100644
index 000000000000..3ee34340edab
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
@@ -0,0 +1,176 @@
+/*
+ * OMAP3 thermal driver.
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Inc.
+ * Copyright (C) 2014 Pavel Machek <pavel@ucw.cz>
+ *
+ * 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.
+ *
+ * Note
+ * http://www.ti.com/lit/er/sprz278f/sprz278f.pdf "Advisory
+ * 3.1.1.186 MMC OCP Clock Not Gated When Thermal Sensor Is Used"
+ *
+ * Also TI says:
+ * Just be careful when you try to make thermal policy like decisions
+ * based on this sensor. Placement of the sensor w.r.t the actual logic
+ * generating heat has to be a factor as well. If you are just looking
+ * for an approximation temperature (thermometerish kind), you might be
+ * ok with this. I am not sure we'd find any TI data around this.. just a
+ * heads up.
+ */
+
+#include "ti-thermal.h"
+#include "ti-bandgap.h"
+
+/*
+ * OMAP34XX has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap34xx_mpu_temp_sensor_registers = {
+ .temp_sensor_ctrl = 0,
+ .bgap_soc_mask = BIT(8),
+ .bgap_eocz_mask = BIT(7),
+ .bgap_dtemp_mask = 0x7f,
+
+ .bgap_mode_ctrl = 0,
+ .mode_ctrl_mask = BIT(9),
+};
+
+/* Thresholds and limits for OMAP34XX MPU temperature sensor */
+static struct temp_sensor_data omap34xx_mpu_temp_sensor_data = {
+ .min_freq = 32768,
+ .max_freq = 32768,
+ .max_temp = 125000,
+ .min_temp = -40000,
+ .hyst_val = 5000,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ */
+static const int
+omap34xx_adc_to_temp[128] = {
+ -40000, -40000, -40000, -40000, -40000, -39000, -38000, -36000,
+ -34000, -32000, -31000, -29000, -28000, -26000, -25000, -24000,
+ -22000, -21000, -19000, -18000, -17000, -15000, -14000, -12000,
+ -11000, -9000, -8000, -7000, -5000, -4000, -2000, -1000, 0000,
+ 1000, 3000, 4000, 5000, 7000, 8000, 10000, 11000, 13000, 14000,
+ 15000, 17000, 18000, 20000, 21000, 22000, 24000, 25000, 27000,
+ 28000, 30000, 31000, 32000, 34000, 35000, 37000, 38000, 39000,
+ 41000, 42000, 44000, 45000, 47000, 48000, 49000, 51000, 52000,
+ 53000, 55000, 56000, 58000, 59000, 60000, 62000, 63000, 65000,
+ 66000, 67000, 69000, 70000, 72000, 73000, 74000, 76000, 77000,
+ 79000, 80000, 81000, 83000, 84000, 85000, 87000, 88000, 89000,
+ 91000, 92000, 94000, 95000, 96000, 98000, 99000, 100000,
+ 102000, 103000, 105000, 106000, 107000, 109000, 110000, 111000,
+ 113000, 114000, 116000, 117000, 118000, 120000, 121000, 122000,
+ 124000, 124000, 125000, 125000, 125000, 125000, 125000
+};
+
+/* OMAP34XX data */
+const struct ti_bandgap_data omap34xx_data = {
+ .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE,
+ .fclock_name = "ts_fck",
+ .div_ck_name = "ts_fck",
+ .conv_table = omap34xx_adc_to_temp,
+ .adc_start_val = 0,
+ .adc_end_val = 127,
+ .expose_sensor = ti_thermal_expose_sensor,
+ .remove_sensor = ti_thermal_remove_sensor,
+
+ .sensors = {
+ {
+ .registers = &omap34xx_mpu_temp_sensor_registers,
+ .ts_data = &omap34xx_mpu_temp_sensor_data,
+ .domain = "cpu",
+ .slope = 0,
+ .constant = 20000,
+ .slope_pcb = 0,
+ .constant_pcb = 20000,
+ .register_cooling = NULL,
+ .unregister_cooling = NULL,
+ },
+ },
+ .sensor_count = 1,
+};
+
+/*
+ * OMAP36XX has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap36xx_mpu_temp_sensor_registers = {
+ .temp_sensor_ctrl = 0,
+ .bgap_soc_mask = BIT(9),
+ .bgap_eocz_mask = BIT(8),
+ .bgap_dtemp_mask = 0xFF,
+
+ .bgap_mode_ctrl = 0,
+ .mode_ctrl_mask = BIT(10),
+};
+
+/* Thresholds and limits for OMAP36XX MPU temperature sensor */
+static struct temp_sensor_data omap36xx_mpu_temp_sensor_data = {
+ .min_freq = 32768,
+ .max_freq = 32768,
+ .max_temp = 125000,
+ .min_temp = -40000,
+ .hyst_val = 5000,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ */
+static const int
+omap36xx_adc_to_temp[128] = {
+ -40000, -40000, -40000, -40000, -40000, -40000, -40000, -40000,
+ -40000, -40000, -40000, -40000, -40000, -38000, -35000, -34000,
+ -32000, -30000, -28000, -26000, -24000, -22000, -20000, -18500,
+ -17000, -15000, -13500, -12000, -10000, -8000, -6500, -5000, -3500,
+ -1500, 0, 2000, 3500, 5000, 6500, 8500, 10000, 12000, 13500,
+ 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28500, 30000,
+ 32000, 33500, 35000, 37000, 38500, 40000, 42000, 43500, 45000,
+ 47000, 48500, 50000, 52000, 53500, 55000, 57000, 58500, 60000,
+ 62000, 64000, 66000, 68000, 70000, 71500, 73500, 75000, 77000,
+ 78500, 80000, 82000, 83500, 85000, 87000, 88500, 90000, 92000,
+ 93500, 95000, 97000, 98500, 100000, 102000, 103500, 105000, 107000,
+ 109000, 111000, 113000, 115000, 117000, 118500, 120000, 122000,
+ 123500, 125000, 125000, 125000, 125000, 125000, 125000, 125000,
+ 125000, 125000, 125000, 125000, 125000, 125000, 125000, 125000,
+ 125000, 125000, 125000, 125000, 125000, 125000, 125000
+};
+
+/* OMAP36XX data */
+const struct ti_bandgap_data omap36xx_data = {
+ .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE,
+ .fclock_name = "ts_fck",
+ .div_ck_name = "ts_fck",
+ .conv_table = omap36xx_adc_to_temp,
+ .adc_start_val = 0,
+ .adc_end_val = 127,
+ .expose_sensor = ti_thermal_expose_sensor,
+ .remove_sensor = ti_thermal_remove_sensor,
+
+ .sensors = {
+ {
+ .registers = &omap36xx_mpu_temp_sensor_registers,
+ .ts_data = &omap36xx_mpu_temp_sensor_data,
+ .domain = "cpu",
+ .slope = 0,
+ .constant = 20000,
+ .slope_pcb = 0,
+ .constant_pcb = 20000,
+ .register_cooling = NULL,
+ .unregister_cooling = NULL,
+ },
+ },
+ .sensor_count = 1,
+};
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index 10c47c048f7a..1e34a1efc554 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -1274,6 +1274,10 @@ int ti_bandgap_probe(struct platform_device *pdev)
}
bgp->dev = &pdev->dev;
+ if (TI_BANDGAP_HAS(bgp, UNRELIABLE))
+ dev_warn(&pdev->dev,
+ "This OMAP thermal sensor is unreliable. You've been warned\n");
+
if (TI_BANDGAP_HAS(bgp, TSHUT)) {
ret = ti_bandgap_tshut_init(bgp, pdev);
if (ret) {
@@ -1579,6 +1583,16 @@ static SIMPLE_DEV_PM_OPS(ti_bandgap_dev_pm_ops, ti_bandgap_suspend,
#endif
static const struct of_device_id of_ti_bandgap_match[] = {
+#ifdef CONFIG_OMAP3_THERMAL
+ {
+ .compatible = "ti,omap34xx-bandgap",
+ .data = (void *)&omap34xx_data,
+ },
+ {
+ .compatible = "ti,omap36xx-bandgap",
+ .data = (void *)&omap36xx_data,
+ },
+#endif
#ifdef CONFIG_OMAP4_THERMAL
{
.compatible = "ti,omap4430-bandgap",
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
index 0c52f7afba00..fe0adb898764 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
@@ -322,6 +322,8 @@ struct ti_temp_sensor {
* has Errata 814
* TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device
* has Errata 813
+ * TI_BANDGAP_FEATURE_UNRELIABLE - used when the sensor readings are too
+ * inaccurate.
* TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a
* specific feature (above) or not. Return non-zero, if yes.
*/
@@ -337,6 +339,7 @@ struct ti_temp_sensor {
#define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9)
#define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10)
#define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11)
+#define TI_BANDGAP_FEATURE_UNRELIABLE BIT(12)
#define TI_BANDGAP_HAS(b, f) \
((b)->conf->features & TI_BANDGAP_FEATURE_ ## f)
@@ -390,6 +393,14 @@ int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data);
void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id);
int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend);
+#ifdef CONFIG_OMAP3_THERMAL
+extern const struct ti_bandgap_data omap34xx_data;
+extern const struct ti_bandgap_data omap36xx_data;
+#else
+#define omap34xx_data NULL
+#define omap36xx_data NULL
+#endif
+
#ifdef CONFIG_OMAP4_THERMAL
extern const struct ti_bandgap_data omap4430_data;
extern const struct ti_bandgap_data omap4460_data;
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 87f6578c6f4a..d4a1331675ed 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1577,15 +1577,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
#endif
/*
- * If the port is the middle of closing, bail out now
- */
- if (info->port.flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(tty, info->port.close_wait,
- !(info->port.flags & ASYNC_CLOSING));
- return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
- }
-
- /*
* Start up serial port
*/
retval = cy_startup(info, tty);
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 2509d057b99c..574da15fe618 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -81,7 +81,7 @@ config HVC_UDBG
config HVC_DCC
bool "ARM JTAG DCC console"
- depends on ARM
+ depends on ARM || ARM64
select HVC_DRIVER
help
This console uses the JTAG DCC on ARM to create a console under the HVC
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 4e9c4cc9e1b5..e46d628998f5 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -29,7 +29,7 @@
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/list.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/major.h>
#include <linux/atomic.h>
#include <linux/sysrq.h>
@@ -418,7 +418,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
* there is no buffered data otherwise sleeps on a wait queue
* waking periodically to check chars_in_buffer().
*/
- tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT);
+ tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
} else {
if (hp->port.count < 0)
printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
@@ -1005,19 +1005,3 @@ put_tty:
out:
return err;
}
-
-/* This isn't particularly necessary due to this being a console driver
- * but it is nice to be thorough.
- */
-static void __exit hvc_exit(void)
-{
- if (hvc_driver) {
- kthread_stop(hvc_task);
-
- tty_unregister_driver(hvc_driver);
- /* return tty_struct instances allocated in hvc_init(). */
- put_tty_driver(hvc_driver);
- unregister_console(&hvc_console);
- }
-}
-module_exit(hvc_exit);
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c
index 809920d80a66..82f240fb98f0 100644
--- a/drivers/tty/hvc/hvc_dcc.c
+++ b/drivers/tty/hvc/hvc_dcc.c
@@ -70,20 +70,27 @@ static const struct hv_ops hvc_dcc_get_put_ops = {
static int __init hvc_dcc_console_init(void)
{
+ int ret;
+
if (!hvc_dcc_check())
return -ENODEV;
- hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
- return 0;
+ /* Returns -1 if error */
+ ret = hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
+
+ return ret < 0 ? -ENODEV : 0;
}
console_initcall(hvc_dcc_console_init);
static int __init hvc_dcc_init(void)
{
+ struct hvc_struct *p;
+
if (!hvc_dcc_check())
return -ENODEV;
- hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
- return 0;
+ p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
+
+ return PTR_ERR_OR_ZERO(p);
}
device_initcall(hvc_dcc_init);
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
index bb809cf36617..8b70a1627356 100644
--- a/drivers/tty/hvc/hvc_iucv.c
+++ b/drivers/tty/hvc/hvc_iucv.c
@@ -88,8 +88,8 @@ struct iucv_tty_buffer {
};
/* IUCV callback handler */
-static int hvc_iucv_path_pending(struct iucv_path *, u8[8], u8[16]);
-static void hvc_iucv_path_severed(struct iucv_path *, u8[16]);
+static int hvc_iucv_path_pending(struct iucv_path *, u8 *, u8 *);
+static void hvc_iucv_path_severed(struct iucv_path *, u8 *);
static void hvc_iucv_msg_pending(struct iucv_path *, struct iucv_message *);
static void hvc_iucv_msg_complete(struct iucv_path *, struct iucv_message *);
@@ -782,8 +782,8 @@ static int hvc_iucv_filter_connreq(u8 ipvmid[8])
*
* Locking: struct hvc_iucv_private->lock
*/
-static int hvc_iucv_path_pending(struct iucv_path *path,
- u8 ipvmid[8], u8 ipuser[16])
+static int hvc_iucv_path_pending(struct iucv_path *path, u8 *ipvmid,
+ u8 *ipuser)
{
struct hvc_iucv_private *priv, *tmp;
u8 wildcard[9] = "lnxhvc ";
@@ -881,7 +881,7 @@ out_path_handled:
*
* Locking: struct hvc_iucv_private->lock
*/
-static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
+static void hvc_iucv_path_severed(struct iucv_path *path, u8 *ipuser)
{
struct hvc_iucv_private *priv = path->private;
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 10beb1589d83..fa816b7193b6 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -230,7 +230,7 @@ static int xen_hvm_console_init(void)
if (r < 0 || v == 0)
goto err;
gfn = v;
- info->intf = xen_remap(gfn << PAGE_SHIFT, PAGE_SIZE);
+ info->intf = xen_remap(gfn << XEN_PAGE_SHIFT, XEN_PAGE_SIZE);
if (info->intf == NULL)
goto err;
info->vtermno = HVC_COOKIE;
@@ -472,7 +472,7 @@ static int xencons_resume(struct xenbus_device *dev)
struct xencons_info *info = dev_get_drvdata(&dev->dev);
xencons_disconnect_backend(info);
- memset(info->intf, 0, PAGE_SIZE);
+ memset(info->intf, 0, XEN_PAGE_SIZE);
return xencons_connect_backend(dev, info);
}
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index f7ff97c0ad34..5997b1731111 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1230,7 +1230,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
irq = hvcsd->vdev->irq;
spin_unlock_irqrestore(&hvcsd->lock, flags);
- tty_wait_until_sent_from_close(tty, HVCS_CLOSE_WAIT);
+ tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
/*
* This line is important because it tells hvcs_open that this
diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c
index a8c8cfd52a23..a119176a1855 100644
--- a/drivers/tty/mips_ejtag_fdc.c
+++ b/drivers/tty/mips_ejtag_fdc.c
@@ -977,7 +977,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
/* Try requesting the IRQ */
if (priv->irq >= 0) {
/*
- * IRQF_SHARED, IRQF_NO_SUSPEND: The FDC IRQ may be shared with
+ * IRQF_SHARED, IRQF_COND_SUSPEND: The FDC IRQ may be shared with
* other local interrupts such as the timer which sets
* IRQF_TIMER (including IRQF_NO_SUSPEND).
*
@@ -987,7 +987,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
*/
ret = devm_request_irq(priv->dev, priv->irq, mips_ejtag_fdc_isr,
IRQF_PERCPU | IRQF_SHARED |
- IRQF_NO_THREAD | IRQF_NO_SUSPEND,
+ IRQF_NO_THREAD | IRQF_COND_SUSPEND,
priv->fdc_name, priv);
if (ret)
priv->irq = -1;
@@ -1048,38 +1048,6 @@ err_destroy_ports:
return ret;
}
-static int mips_ejtag_fdc_tty_remove(struct mips_cdmm_device *dev)
-{
- struct mips_ejtag_fdc_tty *priv = mips_cdmm_get_drvdata(dev);
- struct mips_ejtag_fdc_tty_port *dport;
- int nport;
- unsigned int cfg;
-
- if (priv->irq >= 0) {
- raw_spin_lock_irq(&priv->lock);
- cfg = mips_ejtag_fdc_read(priv, REG_FDCFG);
- /* Disable interrupts */
- cfg &= ~(REG_FDCFG_TXINTTHRES | REG_FDCFG_RXINTTHRES);
- cfg |= REG_FDCFG_TXINTTHRES_DISABLED;
- cfg |= REG_FDCFG_RXINTTHRES_DISABLED;
- mips_ejtag_fdc_write(priv, REG_FDCFG, cfg);
- raw_spin_unlock_irq(&priv->lock);
- } else {
- priv->removing = true;
- del_timer_sync(&priv->poll_timer);
- }
- kthread_stop(priv->thread);
- if (dev->cpu == 0)
- mips_ejtag_fdc_con.tty_drv = NULL;
- tty_unregister_driver(priv->driver);
- for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) {
- dport = &priv->ports[nport];
- tty_port_destroy(&dport->port);
- }
- put_tty_driver(priv->driver);
- return 0;
-}
-
static int mips_ejtag_fdc_tty_cpu_down(struct mips_cdmm_device *dev)
{
struct mips_ejtag_fdc_tty *priv = mips_cdmm_get_drvdata(dev);
@@ -1152,12 +1120,11 @@ static struct mips_cdmm_driver mips_ejtag_fdc_tty_driver = {
.name = "mips_ejtag_fdc",
},
.probe = mips_ejtag_fdc_tty_probe,
- .remove = mips_ejtag_fdc_tty_remove,
.cpu_down = mips_ejtag_fdc_tty_cpu_down,
.cpu_up = mips_ejtag_fdc_tty_cpu_up,
.id_table = mips_ejtag_fdc_tty_ids,
};
-module_mips_cdmm_driver(mips_ejtag_fdc_tty_driver);
+builtin_mips_cdmm_driver(mips_ejtag_fdc_tty_driver);
static int __init mips_ejtag_fdc_init_console(void)
{
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 8b157d68a03e..345111467b85 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -276,7 +276,7 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
error_code, NULL);
}
- wake_up_interruptible(&pInfo->read_wait);
+ wake_up_interruptible(&pInfo->tty->read_wait);
}
spin_lock_irqsave(&pInfo->lock, flags);
@@ -542,7 +542,7 @@ static void on_receive_block(struct r3964_info *pInfo)
pBlock);
}
}
- wake_up_interruptible(&pInfo->read_wait);
+ wake_up_interruptible(&pInfo->tty->read_wait);
pInfo->state = R3964_IDLE;
@@ -978,8 +978,8 @@ static int r3964_open(struct tty_struct *tty)
}
spin_lock_init(&pInfo->lock);
+ mutex_init(&pInfo->read_lock);
pInfo->tty = tty;
- init_waitqueue_head(&pInfo->read_wait);
pInfo->priority = R3964_MASTER;
pInfo->rx_first = pInfo->rx_last = NULL;
pInfo->tx_first = pInfo->tx_last = NULL;
@@ -1045,7 +1045,6 @@ static void r3964_close(struct tty_struct *tty)
}
/* Free buffers: */
- wake_up_interruptible(&pInfo->read_wait);
kfree(pInfo->rx_buf);
TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
kfree(pInfo->tx_buf);
@@ -1065,7 +1064,16 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()");
- tty_lock(tty);
+ /*
+ * Internal serialization of reads.
+ */
+ if (file->f_flags & O_NONBLOCK) {
+ if (!mutex_trylock(&pInfo->read_lock))
+ return -EAGAIN;
+ } else {
+ if (mutex_lock_interruptible(&pInfo->read_lock))
+ return -ERESTARTSYS;
+ }
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1077,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock;
}
/* block until there is a message: */
- wait_event_interruptible_tty(tty, pInfo->read_wait,
+ wait_event_interruptible(tty->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
@@ -1107,7 +1115,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
}
ret = -EPERM;
unlock:
- tty_unlock(tty);
+ mutex_unlock(&pInfo->read_lock);
return ret;
}
@@ -1156,8 +1164,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0;
pHeader->owner = NULL;
- tty_lock(tty);
-
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
pHeader->owner = pClient;
@@ -1175,8 +1181,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
- tty_unlock(tty);
-
return 0;
}
@@ -1227,7 +1231,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
- poll_wait(file, &pInfo->read_wait, wait);
+ poll_wait(file, &tty->read_wait, wait);
spin_lock_irqsave(&pInfo->lock, flags);
pMsg = pClient->first_msg;
spin_unlock_irqrestore(&pInfo->lock, flags);
diff --git a/drivers/tty/n_tracerouter.c b/drivers/tty/n_tracerouter.c
index 1f063d3aa32f..ac5716979bc1 100644
--- a/drivers/tty/n_tracerouter.c
+++ b/drivers/tty/n_tracerouter.c
@@ -34,7 +34,7 @@
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/slab.h>
-#include <asm-generic/bug.h>
+#include <linux/bug.h>
#include "n_tracesink.h"
/*
diff --git a/drivers/tty/n_tracesink.c b/drivers/tty/n_tracesink.c
index ddce58b973d2..4616870a6b1b 100644
--- a/drivers/tty/n_tracesink.c
+++ b/drivers/tty/n_tracesink.c
@@ -34,7 +34,7 @@
#include <linux/tty_ldisc.h>
#include <linux/errno.h>
#include <linux/string.h>
-#include <asm-generic/bug.h>
+#include <linux/bug.h>
#include "n_tracesink.h"
/*
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index b09023b07169..ed776149261e 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -169,7 +169,7 @@ static inline int tty_copy_to_user(struct tty_struct *tty,
{
struct n_tty_data *ldata = tty->disc_data;
- tty_audit_add_data(tty, to, n, ldata->icanon);
+ tty_audit_add_data(tty, from, n, ldata->icanon);
return copy_to_user(to, from, n);
}
@@ -201,7 +201,7 @@ static void n_tty_kick_worker(struct tty_struct *tty)
*/
WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
"scheduling buffer work for halted ldisc\n");
- queue_work(system_unbound_wq, &tty->port->buf.work);
+ tty_buffer_restart_work(tty->port);
}
}
@@ -1179,8 +1179,6 @@ static void n_tty_receive_break(struct tty_struct *tty)
put_tty_queue('\0', ldata);
}
put_tty_queue('\0', ldata);
- if (waitqueue_active(&tty->read_wait))
- wake_up_interruptible_poll(&tty->read_wait, POLLIN);
}
/**
@@ -1237,8 +1235,6 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
put_tty_queue('\0', ldata);
} else
put_tty_queue(c, ldata);
- if (waitqueue_active(&tty->read_wait))
- wake_up_interruptible_poll(&tty->read_wait, POLLIN);
}
static void
@@ -2142,37 +2138,15 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
static int job_control(struct tty_struct *tty, struct file *file)
{
- struct pid *pgrp;
-
/* Job control check -- must be done at start and after
every sleep (POSIX.1 7.1.1.4). */
/* NOTE: not yet done after every sleep pending a thorough
check of the logic of this change. -- jlc */
/* don't stop on /dev/console */
- if (file->f_op->write == redirected_tty_write ||
- current->signal->tty != tty)
+ if (file->f_op->write == redirected_tty_write)
return 0;
- rcu_read_lock();
- pgrp = task_pgrp(current);
-
- spin_lock_irq(&tty->ctrl_lock);
- if (!tty->pgrp)
- printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
- else if (pgrp != tty->pgrp) {
- spin_unlock_irq(&tty->ctrl_lock);
- if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
- rcu_read_unlock();
- return -EIO;
- }
- kill_pgrp(pgrp, SIGTTIN, 1);
- rcu_read_unlock();
- set_thread_flag(TIF_SIGPENDING);
- return -ERESTARTSYS;
- }
- spin_unlock_irq(&tty->ctrl_lock);
- rcu_read_unlock();
- return 0;
+ return __tty_check_change(tty, SIGTTIN);
}
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 4d5937c185c1..a45660f62db5 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -7,7 +7,6 @@
*/
#include <linux/module.h>
-
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
@@ -501,6 +500,10 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
}
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
+/*
+ * not really modular, but the easiest way to keep compat with existing
+ * bootargs behaviour is to continue using module_param here.
+ */
module_param(legacy_count, int, 0);
/*
@@ -877,4 +880,4 @@ static int __init pty_init(void)
unix98_pty_init();
return 0;
}
-module_init(pty_init);
+device_initcall(pty_init);
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index c8dd8dc31086..802eac7e561b 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -895,14 +895,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
if (!page)
return -ENOMEM;
- if (port->flags & ASYNC_CLOSING) {
- retval = wait_for_completion_interruptible(&info->close_wait);
- free_page(page);
- if (retval)
- return retval;
- return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- }
-
/*
* We must not sleep from here until the port is marked fully in use.
*/
@@ -1057,7 +1049,6 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
mutex_unlock(&port->mutex);
tty_port_tty_set(port, NULL);
- wake_up_interruptible(&port->close_wait);
complete_all(&info->close_wait);
atomic_dec(&rp_num_ports_open);
@@ -1511,10 +1502,6 @@ static void rp_hangup(struct tty_struct *tty)
#endif
rp_flush_buffer(tty);
spin_lock_irqsave(&info->port.lock, flags);
- if (info->port.flags & ASYNC_CLOSING) {
- spin_unlock_irqrestore(&info->port.lock, flags);
- return;
- }
if (info->port.count)
atomic_dec(&rp_num_ports_open);
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 748c18f8c8cd..0140ba4aacde 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -560,8 +560,8 @@ static void rs_fair_output(void)
struct m68k_serial *info = &m68k_soft[0];
char c;
- if (info == 0) return;
- if (info->xmit_buf == 0) return;
+ if (info == NULL) return;
+ if (info->xmit_buf == NULL) return;
local_irq_save(flags);
left = info->xmit_cnt;
@@ -1071,7 +1071,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
wake_up_interruptible(&port->open_wait);
}
port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&port->close_wait);
local_irq_restore(flags);
}
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 271d12137649..39126460c1f5 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -569,6 +569,9 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
+ if (up->port.type == PORT_8250_CIR)
+ continue;
+
if (up->port.dev)
continue;
@@ -1027,13 +1030,24 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (up->dl_write)
uart->dl_write = up->dl_write;
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(0, &uart->port,
- &uart->capabilities);
+ if (uart->port.type != PORT_8250_CIR) {
+ if (serial8250_isa_config != NULL)
+ serial8250_isa_config(0, &uart->port,
+ &uart->capabilities);
+
+ ret = uart_add_one_port(&serial8250_reg,
+ &uart->port);
+ if (ret == 0)
+ ret = uart->port.line;
+ } else {
+ dev_info(uart->port.dev,
+ "skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
+ uart->port.iobase,
+ (unsigned long long)uart->port.mapbase,
+ uart->port.irq);
- ret = uart_add_one_port(&serial8250_reg, &uart->port);
- if (ret == 0)
- ret = uart->port.line;
+ ret = 0;
+ }
}
mutex_unlock(&serial_mutex);
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 21d01a491405..78259d3c6a55 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -54,9 +54,6 @@ static void __dma_rx_complete(void *param)
struct dma_tx_state state;
int count;
- dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
- dma->rx_size, DMA_FROM_DEVICE);
-
dma->rx_running = 0;
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
@@ -80,10 +77,6 @@ int serial8250_tx_dma(struct uart_8250_port *p)
return 0;
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- if (dma->tx_size < p->port.fifosize) {
- ret = -EINVAL;
- goto err;
- }
desc = dmaengine_prep_slave_single(dma->txchan,
dma->tx_addr + xmit->tail,
@@ -156,9 +149,6 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
dma->rx_cookie = dmaengine_submit(desc);
- dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
- dma->rx_size, DMA_FROM_DEVICE);
-
dma_async_issue_pending(dma->rxchan);
return 0;
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 06324f17a0cb..a5d319e4aae6 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -63,6 +63,9 @@ struct dw8250_data {
struct clk *pclk;
struct reset_control *rst;
struct uart_8250_dma dma;
+
+ unsigned int skip_autocfg:1;
+ unsigned int uart_16550_compatible:1;
};
#define BYT_PRV_CLK 0x800
@@ -224,10 +227,6 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
if (IS_ERR(d->clk) || !old)
goto out;
- /* Not requesting clock rates below 1.8432Mhz */
- if (baud < 115200)
- baud = 115200;
-
clk_disable_unprepare(d->clk);
rate = clk_round_rate(d->clk, baud * 16);
ret = clk_set_rate(d->clk, rate);
@@ -244,24 +243,77 @@ out:
serial8250_do_set_termios(p, termios, old);
}
-static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
+/*
+ * dw8250_fallback_dma_filter will prevent the UART from getting just any free
+ * channel on platforms that have DMA engines, but don't have any channels
+ * assigned to the UART.
+ *
+ * REVISIT: This is a work around for limitation in the DMA Engine API. Once the
+ * core problem is fixed, this function is no longer needed.
+ */
+static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param)
{
return false;
}
-static void dw8250_setup_port(struct uart_8250_port *up)
+static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
+{
+ return param == chan->device->dev->parent;
+}
+
+static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
- struct uart_port *p = &up->port;
- u32 reg = readl(p->membase + DW_UART_UCV);
+ if (p->dev->of_node) {
+ struct device_node *np = p->dev->of_node;
+ int id;
+
+ /* get index of serial line, if found in DT aliases */
+ id = of_alias_get_id(np, "serial");
+ if (id >= 0)
+ p->line = id;
+#ifdef CONFIG_64BIT
+ if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
+ p->serial_in = dw8250_serial_inq;
+ p->serial_out = dw8250_serial_outq;
+ p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+ p->type = PORT_OCTEON;
+ data->usr_reg = 0x27;
+ data->skip_autocfg = true;
+ }
+#endif
+ } else if (has_acpi_companion(p->dev)) {
+ p->iotype = UPIO_MEM32;
+ p->regshift = 2;
+ p->serial_in = dw8250_serial_in32;
+ p->set_termios = dw8250_set_termios;
+ /* So far none of there implement the Busy Functionality */
+ data->uart_16550_compatible = true;
+ }
+
+ /* Platforms with iDMA */
+ if (platform_get_resource_byname(to_platform_device(p->dev),
+ IORESOURCE_MEM, "lpss_priv")) {
+ p->set_termios = dw8250_set_termios;
+ data->dma.rx_param = p->dev->parent;
+ data->dma.tx_param = p->dev->parent;
+ data->dma.fn = dw8250_idma_filter;
+ }
+}
+
+static void dw8250_setup_port(struct uart_port *p)
+{
+ struct uart_8250_port *up = up_to_u8250p(p);
+ u32 reg;
/*
* If the Component Version Register returns zero, we know that
* ADDITIONAL_FEATURES are not enabled. No need to go any further.
*/
+ reg = readl(p->membase + DW_UART_UCV);
if (!reg)
return;
- dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
+ dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
reg = readl(p->membase + DW_UART_CPR);
@@ -273,7 +325,6 @@ static void dw8250_setup_port(struct uart_8250_port *up)
p->type = PORT_16550A;
p->flags |= UPF_FIXED_TYPE;
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
- up->tx_loadsz = p->fifosize;
up->capabilities = UART_CAP_FIFO;
}
@@ -281,166 +332,91 @@ static void dw8250_setup_port(struct uart_8250_port *up)
up->capabilities |= UART_CAP_AFE;
}
-static int dw8250_probe_of(struct uart_port *p,
- struct dw8250_data *data)
+static int dw8250_probe(struct platform_device *pdev)
{
- struct device_node *np = p->dev->of_node;
- struct uart_8250_port *up = up_to_u8250p(p);
- u32 val;
- bool has_ucv = true;
- int id;
+ struct uart_8250_port uart = {};
+ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int irq = platform_get_irq(pdev, 0);
+ struct uart_port *p = &uart.port;
+ struct dw8250_data *data;
+ int err;
+ u32 val;
-#ifdef CONFIG_64BIT
- if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
- p->serial_in = dw8250_serial_inq;
- p->serial_out = dw8250_serial_outq;
- p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
- p->type = PORT_OCTEON;
- data->usr_reg = 0x27;
- has_ucv = false;
- } else
-#endif
- if (!of_property_read_u32(np, "reg-io-width", &val)) {
- switch (val) {
- case 1:
- break;
- case 4:
- p->iotype = UPIO_MEM32;
- p->serial_in = dw8250_serial_in32;
- p->serial_out = dw8250_serial_out32;
- break;
- default:
- dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
- return -EINVAL;
- }
+ if (!regs) {
+ dev_err(&pdev->dev, "no registers defined\n");
+ return -EINVAL;
}
- if (has_ucv)
- dw8250_setup_port(up);
-
- /* if we have a valid fifosize, try hooking up DMA here */
- if (p->fifosize) {
- up->dma = &data->dma;
- up->dma->rxconf.src_maxburst = p->fifosize / 4;
- up->dma->txconf.dst_maxburst = p->fifosize / 4;
+ if (irq < 0) {
+ if (irq != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "cannot get irq\n");
+ return irq;
}
- if (!of_property_read_u32(np, "reg-shift", &val))
+ spin_lock_init(&p->lock);
+ p->mapbase = regs->start;
+ p->irq = irq;
+ p->handle_irq = dw8250_handle_irq;
+ p->pm = dw8250_do_pm;
+ p->type = PORT_8250;
+ p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT;
+ p->dev = &pdev->dev;
+ p->iotype = UPIO_MEM;
+ p->serial_in = dw8250_serial_in;
+ p->serial_out = dw8250_serial_out;
+
+ p->membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+ if (!p->membase)
+ return -ENOMEM;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->dma.fn = dw8250_fallback_dma_filter;
+ data->usr_reg = DW_UART_USR;
+ p->private_data = data;
+
+ data->uart_16550_compatible = device_property_read_bool(p->dev,
+ "snps,uart-16550-compatible");
+
+ err = device_property_read_u32(p->dev, "reg-shift", &val);
+ if (!err)
p->regshift = val;
- /* get index of serial line, if found in DT aliases */
- id = of_alias_get_id(np, "serial");
- if (id >= 0)
- p->line = id;
+ err = device_property_read_u32(p->dev, "reg-io-width", &val);
+ if (!err && val == 4) {
+ p->iotype = UPIO_MEM32;
+ p->serial_in = dw8250_serial_in32;
+ p->serial_out = dw8250_serial_out32;
+ }
- if (of_property_read_bool(np, "dcd-override")) {
+ if (device_property_read_bool(p->dev, "dcd-override")) {
/* Always report DCD as active */
data->msr_mask_on |= UART_MSR_DCD;
data->msr_mask_off |= UART_MSR_DDCD;
}
- if (of_property_read_bool(np, "dsr-override")) {
+ if (device_property_read_bool(p->dev, "dsr-override")) {
/* Always report DSR as active */
data->msr_mask_on |= UART_MSR_DSR;
data->msr_mask_off |= UART_MSR_DDSR;
}
- if (of_property_read_bool(np, "cts-override")) {
+ if (device_property_read_bool(p->dev, "cts-override")) {
/* Always report CTS as active */
data->msr_mask_on |= UART_MSR_CTS;
data->msr_mask_off |= UART_MSR_DCTS;
}
- if (of_property_read_bool(np, "ri-override")) {
+ if (device_property_read_bool(p->dev, "ri-override")) {
/* Always report Ring indicator as inactive */
data->msr_mask_off |= UART_MSR_RI;
data->msr_mask_off |= UART_MSR_TERI;
}
- return 0;
-}
-
-static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
-{
- struct device *dev = param;
-
- if (dev != chan->device->dev->parent)
- return false;
-
- return true;
-}
-
-static int dw8250_probe_acpi(struct uart_8250_port *up,
- struct dw8250_data *data)
-{
- struct uart_port *p = &up->port;
-
- dw8250_setup_port(up);
-
- p->iotype = UPIO_MEM32;
- p->serial_in = dw8250_serial_in32;
- p->serial_out = dw8250_serial_out32;
- p->regshift = 2;
-
- /* Platforms with iDMA */
- if (platform_get_resource_byname(to_platform_device(up->port.dev),
- IORESOURCE_MEM, "lpss_priv")) {
- data->dma.rx_param = up->port.dev->parent;
- data->dma.tx_param = up->port.dev->parent;
- data->dma.fn = dw8250_idma_filter;
- }
-
- up->dma = &data->dma;
- up->dma->rxconf.src_maxburst = p->fifosize / 4;
- up->dma->txconf.dst_maxburst = p->fifosize / 4;
-
- up->port.set_termios = dw8250_set_termios;
-
- return 0;
-}
-
-static int dw8250_probe(struct platform_device *pdev)
-{
- struct uart_8250_port uart = {};
- struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- int irq = platform_get_irq(pdev, 0);
- struct dw8250_data *data;
- int err;
-
- if (!regs) {
- dev_err(&pdev->dev, "no registers defined\n");
- return -EINVAL;
- }
-
- if (irq < 0) {
- if (irq != -EPROBE_DEFER)
- dev_err(&pdev->dev, "cannot get irq\n");
- return irq;
- }
-
- spin_lock_init(&uart.port.lock);
- uart.port.mapbase = regs->start;
- uart.port.irq = irq;
- uart.port.handle_irq = dw8250_handle_irq;
- uart.port.pm = dw8250_do_pm;
- uart.port.type = PORT_8250;
- uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
- uart.port.dev = &pdev->dev;
-
- uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
- resource_size(regs));
- if (!uart.port.membase)
- return -ENOMEM;
-
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- data->usr_reg = DW_UART_USR;
-
/* Always ask for fixed clock rate from a property. */
- device_property_read_u32(&pdev->dev, "clock-frequency",
- &uart.port.uartclk);
+ device_property_read_u32(p->dev, "clock-frequency", &p->uartclk);
/* If there is separate baudclk, get the rate from it. */
data->clk = devm_clk_get(&pdev->dev, "baudclk");
@@ -454,11 +430,11 @@ static int dw8250_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
err);
else
- uart.port.uartclk = clk_get_rate(data->clk);
+ p->uartclk = clk_get_rate(data->clk);
}
/* If no clock rate is defined, fail. */
- if (!uart.port.uartclk) {
+ if (!p->uartclk) {
dev_err(&pdev->dev, "clock rate not defined\n");
return -EINVAL;
}
@@ -484,26 +460,22 @@ static int dw8250_probe(struct platform_device *pdev)
if (!IS_ERR(data->rst))
reset_control_deassert(data->rst);
- data->dma.rx_param = data;
- data->dma.tx_param = data;
- data->dma.fn = dw8250_dma_filter;
+ dw8250_quirks(p, data);
- uart.port.iotype = UPIO_MEM;
- uart.port.serial_in = dw8250_serial_in;
- uart.port.serial_out = dw8250_serial_out;
- uart.port.private_data = data;
+ /* If the Busy Functionality is not implemented, don't handle it */
+ if (data->uart_16550_compatible) {
+ p->serial_out = NULL;
+ p->handle_irq = NULL;
+ }
- if (pdev->dev.of_node) {
- err = dw8250_probe_of(&uart.port, data);
- if (err)
- goto err_reset;
- } else if (ACPI_HANDLE(&pdev->dev)) {
- err = dw8250_probe_acpi(&uart, data);
- if (err)
- goto err_reset;
- } else {
- err = -ENODEV;
- goto err_reset;
+ if (!data->skip_autocfg)
+ dw8250_setup_port(p);
+
+ /* If we have a valid fifosize, try hooking up DMA */
+ if (p->fifosize) {
+ data->dma.rxconf.src_maxburst = p->fifosize / 4;
+ data->dma.txconf.dst_maxburst = p->fifosize / 4;
+ uart.dma = &data->dma;
}
data->line = serial8250_register_8250_port(&uart);
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index faed05f25bc2..ceb85792a5cf 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -29,6 +29,8 @@
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/console.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/serial_reg.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
@@ -152,3 +154,5 @@ int __init early_serial8250_setup(struct earlycon_device *device,
}
EARLYCON_DECLARE(uart8250, early_serial8250_setup);
EARLYCON_DECLARE(uart, early_serial8250_setup);
+OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
+OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index c0533a57ec53..910bfee5a88b 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -60,3 +60,4 @@ int fsl8250_handle_irq(struct uart_port *port)
spin_unlock_irqrestore(&up->port.lock, flags);
return 1;
}
+EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 7c1e4be48e7b..49394b4c5cfd 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -21,19 +21,33 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
+#include "8250.h"
+
+/** ingenic_uart_config: SOC specific config data. */
+struct ingenic_uart_config {
+ int tx_loadsz;
+ int fifosize;
+};
+
struct ingenic_uart_data {
struct clk *clk_module;
struct clk *clk_baud;
int line;
};
+static const struct of_device_id of_match[];
+
#define UART_FCR_UME BIT(4)
+#define UART_MCR_MDCE BIT(7)
+#define UART_MCR_FCM BIT(6)
+
static struct earlycon_device *early_device;
static uint8_t __init early_in(struct uart_port *port, int offset)
@@ -129,6 +143,8 @@ OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
{
+ int ier;
+
switch (offset) {
case UART_FCR:
/* UART module enable */
@@ -136,9 +152,22 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
break;
case UART_IER:
+ /* Enable receive timeout interrupt with the
+ * receive line status interrupt */
value |= (value & 0x4) << 2;
break;
+ case UART_MCR:
+ /* If we have enabled modem status IRQs we should enable modem
+ * mode. */
+ ier = p->serial_in(p, UART_IER);
+
+ if (ier & UART_IER_MSI)
+ value |= UART_MCR_MDCE | UART_MCR_FCM;
+ else
+ value &= ~(UART_MCR_MDCE | UART_MCR_FCM);
+ break;
+
default:
break;
}
@@ -146,14 +175,45 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
writeb(value, p->membase + (offset << p->regshift));
}
+static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset)
+{
+ unsigned int value;
+
+ value = readb(p->membase + (offset << p->regshift));
+
+ /* Hide non-16550 compliant bits from higher levels */
+ switch (offset) {
+ case UART_FCR:
+ value &= ~UART_FCR_UME;
+ break;
+
+ case UART_MCR:
+ value &= ~(UART_MCR_MDCE | UART_MCR_FCM);
+ break;
+
+ default:
+ break;
+ }
+ return value;
+}
+
static int ingenic_uart_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct ingenic_uart_data *data;
+ const struct ingenic_uart_config *cdata;
+ const struct of_device_id *match;
int err, line;
+ match = of_match_device(of_match, &pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "Error: No device match found\n");
+ return -ENODEV;
+ }
+ cdata = match->data;
+
if (!regs || !irq) {
dev_err(&pdev->dev, "no registers/irq defined\n");
return -EINVAL;
@@ -164,14 +224,18 @@ static int ingenic_uart_probe(struct platform_device *pdev)
return -ENOMEM;
spin_lock_init(&uart.port.lock);
- uart.port.type = PORT_16550;
+ uart.port.type = PORT_16550A;
uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
uart.port.iotype = UPIO_MEM;
uart.port.mapbase = regs->start;
uart.port.regshift = 2;
uart.port.serial_out = ingenic_uart_serial_out;
+ uart.port.serial_in = ingenic_uart_serial_in;
uart.port.irq = irq->start;
uart.port.dev = &pdev->dev;
+ uart.port.fifosize = cdata->fifosize;
+ uart.tx_loadsz = cdata->tx_loadsz;
+ uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE;
/* Check for a fixed line number */
line = of_alias_get_id(pdev->dev.of_node, "serial");
@@ -241,10 +305,26 @@ static int ingenic_uart_remove(struct platform_device *pdev)
return 0;
}
+static const struct ingenic_uart_config jz4740_uart_config = {
+ .tx_loadsz = 8,
+ .fifosize = 16,
+};
+
+static const struct ingenic_uart_config jz4760_uart_config = {
+ .tx_loadsz = 16,
+ .fifosize = 32,
+};
+
+static const struct ingenic_uart_config jz4780_uart_config = {
+ .tx_loadsz = 32,
+ .fifosize = 64,
+};
+
static const struct of_device_id of_match[] = {
- { .compatible = "ingenic,jz4740-uart" },
- { .compatible = "ingenic,jz4775-uart" },
- { .compatible = "ingenic,jz4780-uart" },
+ { .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config },
+ { .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config },
+ { .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config },
+ { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match);
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
new file mode 100644
index 000000000000..88531a36b69c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -0,0 +1,326 @@
+/*
+ * 8250_mid.c - Driver for UART on Intel Penwell and various other Intel SOCs
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/rational.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <linux/dma/hsu.h>
+
+#include "8250.h"
+
+#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b
+#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c
+#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d
+#define PCI_DEVICE_ID_INTEL_TNG_UART 0x1191
+#define PCI_DEVICE_ID_INTEL_DNV_UART 0x19d8
+
+/* Intel MID Specific registers */
+#define INTEL_MID_UART_PS 0x30
+#define INTEL_MID_UART_MUL 0x34
+#define INTEL_MID_UART_DIV 0x38
+
+struct mid8250;
+
+struct mid8250_board {
+ unsigned long freq;
+ unsigned int base_baud;
+ int (*setup)(struct mid8250 *, struct uart_port *p);
+ void (*exit)(struct mid8250 *);
+};
+
+struct mid8250 {
+ int line;
+ int dma_index;
+ struct pci_dev *dma_dev;
+ struct uart_8250_dma dma;
+ struct mid8250_board *board;
+ struct hsu_dma_chip dma_chip;
+};
+
+/*****************************************************************************/
+
+static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
+{
+ struct pci_dev *pdev = to_pci_dev(p->dev);
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_PNW_UART1:
+ mid->dma_index = 0;
+ break;
+ case PCI_DEVICE_ID_INTEL_PNW_UART2:
+ mid->dma_index = 1;
+ break;
+ case PCI_DEVICE_ID_INTEL_PNW_UART3:
+ mid->dma_index = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mid->dma_dev = pci_get_slot(pdev->bus,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
+ return 0;
+}
+
+static int tng_setup(struct mid8250 *mid, struct uart_port *p)
+{
+ struct pci_dev *pdev = to_pci_dev(p->dev);
+ int index = PCI_FUNC(pdev->devfn);
+
+ /* Currently no support for HSU port0 */
+ if (index-- == 0)
+ return -ENODEV;
+
+ mid->dma_index = index;
+ mid->dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
+ return 0;
+}
+
+static int dnv_handle_irq(struct uart_port *p)
+{
+ struct mid8250 *mid = p->private_data;
+ int ret;
+
+ ret = hsu_dma_irq(&mid->dma_chip, 0);
+ ret |= hsu_dma_irq(&mid->dma_chip, 1);
+
+ /* For now, letting the HW generate separate interrupt for the UART */
+ if (ret)
+ return ret;
+
+ return serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+}
+
+#define DNV_DMA_CHAN_OFFSET 0x80
+
+static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
+{
+ struct hsu_dma_chip *chip = &mid->dma_chip;
+ struct pci_dev *pdev = to_pci_dev(p->dev);
+ int ret;
+
+ chip->dev = &pdev->dev;
+ chip->irq = pdev->irq;
+ chip->regs = p->membase;
+ chip->length = pci_resource_len(pdev, 0);
+ chip->offset = DNV_DMA_CHAN_OFFSET;
+
+ /* Falling back to PIO mode if DMA probing fails */
+ ret = hsu_dma_probe(chip);
+ if (ret)
+ return 0;
+
+ mid->dma_dev = pdev;
+
+ p->handle_irq = dnv_handle_irq;
+ return 0;
+}
+
+static void dnv_exit(struct mid8250 *mid)
+{
+ if (!mid->dma_dev)
+ return;
+ hsu_dma_remove(&mid->dma_chip);
+}
+
+/*****************************************************************************/
+
+static void mid8250_set_termios(struct uart_port *p,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned int baud = tty_termios_baud_rate(termios);
+ struct mid8250 *mid = p->private_data;
+ unsigned short ps = 16;
+ unsigned long fuart = baud * ps;
+ unsigned long w = BIT(24) - 1;
+ unsigned long mul, div;
+
+ if (mid->board->freq < fuart) {
+ /* Find prescaler value that satisfies Fuart < Fref */
+ if (mid->board->freq > baud)
+ ps = mid->board->freq / baud; /* baud rate too high */
+ else
+ ps = 1; /* PLL case */
+ fuart = baud * ps;
+ } else {
+ /* Get Fuart closer to Fref */
+ fuart *= rounddown_pow_of_two(mid->board->freq / fuart);
+ }
+
+ rational_best_approximation(fuart, mid->board->freq, w, w, &mul, &div);
+ p->uartclk = fuart * 16 / ps; /* core uses ps = 16 always */
+
+ writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */
+ writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */
+ writel(div, p->membase + INTEL_MID_UART_DIV);
+
+ serial8250_do_set_termios(p, termios, old);
+}
+
+static bool mid8250_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct hsu_dma_slave *s = param;
+
+ if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
+ return false;
+
+ chan->private = s;
+ return true;
+}
+
+static int mid8250_dma_setup(struct mid8250 *mid, struct uart_8250_port *port)
+{
+ struct uart_8250_dma *dma = &mid->dma;
+ struct device *dev = port->port.dev;
+ struct hsu_dma_slave *rx_param;
+ struct hsu_dma_slave *tx_param;
+
+ if (!mid->dma_dev)
+ return 0;
+
+ rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
+ if (!rx_param)
+ return -ENOMEM;
+
+ tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
+ if (!tx_param)
+ return -ENOMEM;
+
+ rx_param->chan_id = mid->dma_index * 2 + 1;
+ tx_param->chan_id = mid->dma_index * 2;
+
+ dma->rxconf.src_maxburst = 64;
+ dma->txconf.dst_maxburst = 64;
+
+ rx_param->dma_dev = &mid->dma_dev->dev;
+ tx_param->dma_dev = &mid->dma_dev->dev;
+
+ dma->fn = mid8250_dma_filter;
+ dma->rx_param = rx_param;
+ dma->tx_param = tx_param;
+
+ port->dma = dma;
+ return 0;
+}
+
+static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct uart_8250_port uart;
+ struct mid8250 *mid;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ pci_set_master(pdev);
+
+ mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
+ if (!mid)
+ return -ENOMEM;
+
+ mid->board = (struct mid8250_board *)id->driver_data;
+
+ memset(&uart, 0, sizeof(struct uart_8250_port));
+
+ uart.port.dev = &pdev->dev;
+ uart.port.irq = pdev->irq;
+ uart.port.private_data = mid;
+ uart.port.type = PORT_16750;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.uartclk = mid->board->base_baud * 16;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
+ uart.port.set_termios = mid8250_set_termios;
+
+ uart.port.mapbase = pci_resource_start(pdev, 0);
+ uart.port.membase = pcim_iomap(pdev, 0, 0);
+ if (!uart.port.membase)
+ return -ENOMEM;
+
+ if (mid->board->setup) {
+ ret = mid->board->setup(mid, &uart.port);
+ if (ret)
+ return ret;
+ }
+
+ ret = mid8250_dma_setup(mid, &uart);
+ if (ret)
+ goto err;
+
+ ret = serial8250_register_8250_port(&uart);
+ if (ret < 0)
+ goto err;
+
+ mid->line = ret;
+
+ pci_set_drvdata(pdev, mid);
+ return 0;
+err:
+ if (mid->board->exit)
+ mid->board->exit(mid);
+ return ret;
+}
+
+static void mid8250_remove(struct pci_dev *pdev)
+{
+ struct mid8250 *mid = pci_get_drvdata(pdev);
+
+ if (mid->board->exit)
+ mid->board->exit(mid);
+
+ serial8250_unregister_port(mid->line);
+}
+
+static const struct mid8250_board pnw_board = {
+ .freq = 50000000,
+ .base_baud = 115200,
+ .setup = pnw_setup,
+};
+
+static const struct mid8250_board tng_board = {
+ .freq = 38400000,
+ .base_baud = 1843200,
+ .setup = tng_setup,
+};
+
+static const struct mid8250_board dnv_board = {
+ .freq = 133333333,
+ .base_baud = 115200,
+ .setup = dnv_setup,
+ .exit = dnv_exit,
+};
+
+#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
+
+static const struct pci_device_id pci_ids[] = {
+ MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART1, pnw_board),
+ MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
+ MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
+ MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
+ MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
+ { },
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver mid8250_pci_driver = {
+ .name = "8250_mid",
+ .id_table = pci_ids,
+ .probe = mid8250_probe,
+ .remove = mid8250_remove,
+};
+
+module_pci_driver(mid8250_pci_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel MID UART driver");
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 826c5c4a2103..a2c0734c76e2 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -439,7 +439,6 @@ static void omap_8250_set_termios(struct uart_port *port,
priv->xoff = termios->c_cc[VSTOP];
priv->efr = 0;
- up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY);
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
@@ -726,6 +725,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
struct dma_tx_state state;
int count;
unsigned long flags;
+ int ret;
dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
@@ -741,8 +741,10 @@ static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
count = dma->rx_size - state.residue;
- tty_insert_flip_string(tty_port, dma->rx_buf, count);
- p->port.icount.rx += count;
+ ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);
+
+ p->port.icount.rx += ret;
+ p->port.icount.buf_overrun += count - ret;
unlock:
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 68042dd1c525..4097f3f65b3b 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -28,7 +28,6 @@
#include <linux/dmaengine.h>
#include <linux/platform_data/dma-dw.h>
-#include <linux/platform_data/dma-hsu.h>
#include "8250.h"
@@ -1508,167 +1507,6 @@ byt_serial_setup(struct serial_private *priv,
return ret;
}
-#define INTEL_MID_UART_PS 0x30
-#define INTEL_MID_UART_MUL 0x34
-#define INTEL_MID_UART_DIV 0x38
-
-static void intel_mid_set_termios(struct uart_port *p,
- struct ktermios *termios,
- struct ktermios *old,
- unsigned long fref)
-{
- unsigned int baud = tty_termios_baud_rate(termios);
- unsigned short ps = 16;
- unsigned long fuart = baud * ps;
- unsigned long w = BIT(24) - 1;
- unsigned long mul, div;
-
- if (fref < fuart) {
- /* Find prescaler value that satisfies Fuart < Fref */
- if (fref > baud)
- ps = fref / baud; /* baud rate too high */
- else
- ps = 1; /* PLL case */
- fuart = baud * ps;
- } else {
- /* Get Fuart closer to Fref */
- fuart *= rounddown_pow_of_two(fref / fuart);
- }
-
- rational_best_approximation(fuart, fref, w, w, &mul, &div);
- p->uartclk = fuart * 16 / ps; /* core uses ps = 16 always */
-
- writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */
- writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */
- writel(div, p->membase + INTEL_MID_UART_DIV);
-
- serial8250_do_set_termios(p, termios, old);
-}
-
-static void intel_mid_set_termios_38_4M(struct uart_port *p,
- struct ktermios *termios,
- struct ktermios *old)
-{
- intel_mid_set_termios(p, termios, old, 38400000);
-}
-
-static void intel_mid_set_termios_50M(struct uart_port *p,
- struct ktermios *termios,
- struct ktermios *old)
-{
- /*
- * The uart clk is 50Mhz, and the baud rate come from:
- * baud = 50M * MUL / (DIV * PS * DLAB)
- */
- intel_mid_set_termios(p, termios, old, 50000000);
-}
-
-static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)
-{
- struct hsu_dma_slave *s = param;
-
- if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
- return false;
-
- chan->private = s;
- return true;
-}
-
-static int intel_mid_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx,
- int index, struct pci_dev *dma_dev)
-{
- struct device *dev = port->port.dev;
- struct uart_8250_dma *dma;
- struct hsu_dma_slave *tx_param, *rx_param;
-
- dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
- if (!dma)
- return -ENOMEM;
-
- tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
- if (!tx_param)
- return -ENOMEM;
-
- rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
- if (!rx_param)
- return -ENOMEM;
-
- rx_param->chan_id = index * 2 + 1;
- tx_param->chan_id = index * 2;
-
- dma->rxconf.src_maxburst = 64;
- dma->txconf.dst_maxburst = 64;
-
- rx_param->dma_dev = &dma_dev->dev;
- tx_param->dma_dev = &dma_dev->dev;
-
- dma->fn = intel_mid_dma_filter;
- dma->rx_param = rx_param;
- dma->tx_param = tx_param;
-
- port->port.type = PORT_16750;
- port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port->dma = dma;
-
- return pci_default_setup(priv, board, port, idx);
-}
-
-#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b
-#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c
-#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d
-
-static int pnw_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
-{
- struct pci_dev *pdev = priv->dev;
- struct pci_dev *dma_dev;
- int index;
-
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_PNW_UART1:
- index = 0;
- break;
- case PCI_DEVICE_ID_INTEL_PNW_UART2:
- index = 1;
- break;
- case PCI_DEVICE_ID_INTEL_PNW_UART3:
- index = 2;
- break;
- default:
- return -EINVAL;
- }
-
- dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
-
- port->port.set_termios = intel_mid_set_termios_50M;
-
- return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
-}
-
-#define PCI_DEVICE_ID_INTEL_TNG_UART 0x1191
-
-static int tng_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
-{
- struct pci_dev *pdev = priv->dev;
- struct pci_dev *dma_dev;
- int index = PCI_FUNC(pdev->devfn);
-
- /* Currently no support for HSU port0 */
- if (index-- == 0)
- return -ENODEV;
-
- dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
-
- port->port.set_termios = intel_mid_set_termios_38_4M;
-
- return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
-}
-
static int
pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board,
@@ -2212,34 +2050,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
},
{
.vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_PNW_UART1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pnw_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_PNW_UART2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pnw_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_PNW_UART3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pnw_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_TNG_UART,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = tng_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BSW_UART1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
@@ -3119,8 +2929,6 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200,
pbn_byt,
- pbn_pnw,
- pbn_tng,
pbn_qrk,
pbn_omegapci,
pbn_NETMOS9900_2s_115200,
@@ -3907,16 +3715,6 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 0x80,
.reg_shift = 2,
},
- [pbn_pnw] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 115200,
- },
- [pbn_tng] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 1843200,
- },
[pbn_qrk] = {
.flags = FL_BASE0,
.num_ports = 1,
@@ -4005,6 +3803,13 @@ static const struct pci_device_id blacklist[] = {
{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
{ PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */
+
+ /* Intel platforms with MID UART */
+ { PCI_VDEVICE(INTEL, 0x081b), },
+ { PCI_VDEVICE(INTEL, 0x081c), },
+ { PCI_VDEVICE(INTEL, 0x081d), },
+ { PCI_VDEVICE(INTEL, 0x1191), },
+ { PCI_VDEVICE(INTEL, 0x19d8), },
};
/*
@@ -5702,26 +5507,6 @@ static struct pci_device_id serial_pci_tbl[] = {
pbn_byt },
/*
- * Intel Penwell
- */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pnw},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pnw},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pnw},
-
- /*
- * Intel Tangier
- */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TNG_UART,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_tng},
-
- /*
* Intel Quark x1000
*/
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART,
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 0bbf34035d6a..52d82d2ac726 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -284,7 +284,7 @@ static void default_serial_dl_write(struct uart_8250_port *up, int value)
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#ifdef CONFIG_SERIAL_8250_RT288X
/* Au1x00/RT288x UART hardware has a weird register layout */
static const s8 au_io_in_map[8] = {
@@ -435,7 +435,7 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_out = mem32be_serial_out;
break;
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#ifdef CONFIG_SERIAL_8250_RT288X
case UPIO_AU:
p->serial_in = au_serial_in;
p->serial_out = au_serial_out;
@@ -1246,6 +1246,9 @@ static void autoconfig_irq(struct uart_8250_port *up)
inb_p(ICP);
}
+ if (uart_console(port))
+ console_lock();
+
/* forget possible initially masked and pending IRQ */
probe_irq_off(probe_irq_on());
save_mcr = serial_in(up, UART_MCR);
@@ -1277,6 +1280,9 @@ static void autoconfig_irq(struct uart_8250_port *up)
if (port->flags & UPF_FOURPORT)
outb_p(save_ICP, ICP);
+ if (uart_console(port))
+ console_unlock();
+
port->irq = (irq > 0) ? irq : 0;
}
@@ -1807,9 +1813,6 @@ int serial8250_do_startup(struct uart_port *port)
unsigned char lsr, iir;
int retval;
- if (port->type == PORT_8250_CIR)
- return -ENODEV;
-
if (!port->fifosize)
port->fifosize = uart_config[port->type].fifo_size;
if (!up->tx_loadsz)
@@ -2230,6 +2233,23 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
serial_port_out(port, 0x2, quot_frac);
}
+static unsigned int
+serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned int tolerance = port->uartclk / 100;
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ * Allow 1% tolerance at the upper limit so uart clks marginally
+ * slower than nominal still match standard baud rates without
+ * causing transmission errors.
+ */
+ return uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ (port->uartclk + tolerance) / 16);
+}
+
void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
@@ -2241,12 +2261,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
cval = serial8250_compute_lcr(up, termios->c_cflag);
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
+ baud = serial8250_get_baud_rate(port, termios, old);
quot = serial8250_get_divisor(up, baud, &frac);
/*
@@ -2513,14 +2528,8 @@ static void serial8250_release_port(struct uart_port *port)
static int serial8250_request_port(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
- int ret;
-
- if (port->type == PORT_8250_CIR)
- return -ENODEV;
-
- ret = serial8250_request_std_resource(up);
- return ret;
+ return serial8250_request_std_resource(up);
}
static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
@@ -2668,9 +2677,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
struct uart_8250_port *up = up_to_u8250p(port);
int ret;
- if (port->type == PORT_8250_CIR)
- return;
-
/*
* Find the region that we can probe for. This in turn
* tells us whether we can probe for the type of port.
@@ -2805,6 +2811,27 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
}
/*
+ * Restore serial console when h/w power-off detected
+ */
+static void serial8250_console_restore(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ struct ktermios termios;
+ unsigned int baud, quot, frac = 0;
+
+ termios.c_cflag = port->cons->cflag;
+ if (port->state->port.tty && termios.c_cflag == 0)
+ termios.c_cflag = port->state->port.tty->termios.c_cflag;
+
+ baud = serial8250_get_baud_rate(port, &termios, NULL);
+ quot = serial8250_get_divisor(up, baud, &frac);
+
+ serial8250_set_divisor(port, baud, quot, frac);
+ serial_port_out(port, UART_LCR, up->lcr);
+ serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+}
+
+/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
@@ -2841,22 +2868,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
/* check scratch reg to see if port powered off during system sleep */
if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
- struct ktermios termios;
- unsigned int baud, quot, frac = 0;
-
- termios.c_cflag = port->cons->cflag;
- if (port->state->port.tty && termios.c_cflag == 0)
- termios.c_cflag = port->state->port.tty->termios.c_cflag;
-
- baud = uart_get_baud_rate(port, &termios, NULL,
- port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
- quot = serial8250_get_divisor(up, baud, &frac);
-
- serial8250_set_divisor(port, baud, quot, frac);
- serial_port_out(port, UART_LCR, up->lcr);
- serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
-
+ serial8250_console_restore(up);
up->canary = 0;
}
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index e1de1181b322..6412f1455beb 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -274,8 +274,8 @@ config SERIAL_8250_ACORN
config SERIAL_8250_FSL
bool
- depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
- default PPC
+ depends on SERIAL_8250_CONSOLE
+ default PPC || ARM || ARM64
config SERIAL_8250_DW
tristate "Support for Synopsys DesignWare 8250 quirks"
@@ -294,11 +294,12 @@ config SERIAL_8250_EM
config SERIAL_8250_RT288X
bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support"
- depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620)
+ depends on SERIAL_8250
+ default y if MIPS_ALCHEMY || SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
help
- If you have a Ralink RT288x/RT305x SoC based board and want to use the
- serial port, say Y to this option. The driver can handle up to 2 serial
- ports. If unsure, say N.
+ Selecting this option will add support for the alternate register
+ layout used by Ralink RT288x/RT305x, Alchemy Au1xxx, and some others.
+ If unsure, say N.
config SERIAL_8250_OMAP
tristate "Support for OMAP internal UART (8250 based driver)"
@@ -337,7 +338,7 @@ config SERIAL_8250_FINTEK
through the PNP driver. If unsure, say N.
config SERIAL_8250_LPC18XX
- bool "NXP LPC18xx/43xx serial port support"
+ tristate "NXP LPC18xx/43xx serial port support"
depends on SERIAL_8250 && OF && (ARCH_LPC18XX || COMPILE_TEST)
default ARCH_LPC18XX
help
@@ -366,3 +367,14 @@ config SERIAL_8250_INGENIC
help
If you have a system using an Ingenic SoC and wish to make use of
its UARTs, say Y to this option. If unsure, say N.
+
+config SERIAL_8250_MID
+ tristate "Support for serial ports on Intel MID platforms"
+ depends on SERIAL_8250 && PCI
+ select HSU_DMA if SERIAL_8250_DMA
+ select HSU_DMA_PCI if X86_INTEL_MID
+ select RATIONAL
+ help
+ Selecting this option will enable handling of the extra features
+ present on the UART found on Intel Medfield SOC and various other
+ Intel platforms.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 39c6d2277570..e177f8681ada 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -27,5 +27,6 @@ obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o
obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
+obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 687b1ea294b7..f38beb28e7ae 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -115,9 +115,9 @@ config SERIAL_SB1250_DUART_CONSOLE
config SERIAL_ATMEL
bool "AT91 / AT32 on-chip serial port support"
- depends on ARCH_AT91 || AVR32
+ depends on ARCH_AT91 || AVR32 || COMPILE_TEST
select SERIAL_CORE
- select SERIAL_MCTRL_GPIO
+ select SERIAL_MCTRL_GPIO if GPIOLIB
help
This enables the driver for the on-chip UARTs of the Atmel
AT91 and AT32 processors.
@@ -571,7 +571,7 @@ config BFIN_UART3_CTSRTS
config SERIAL_IMX
tristate "IMX serial port support"
- depends on ARCH_MXC
+ depends on ARCH_MXC || COMPILE_TEST
select SERIAL_CORE
select RATIONAL
help
@@ -582,6 +582,7 @@ config SERIAL_IMX_CONSOLE
bool "Console on IMX serial port"
depends on SERIAL_IMX=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON if OF
help
If you have enabled the serial port on the Freescale IMX
CPU you can make it the console by answering Y to this option.
@@ -743,7 +744,7 @@ config SERIAL_SH_SCI_CONSOLE
config SERIAL_SH_SCI_DMA
bool "DMA support"
- depends on SERIAL_SH_SCI && SH_DMAE
+ depends on SERIAL_SH_SCI && DMA_ENGINE
config SERIAL_PNX8XXX
bool "Enable PNX8XXX SoCs' UART Support"
@@ -1408,7 +1409,7 @@ config SERIAL_PCH_UART_CONSOLE
warnings and which allows logins in single user mode).
config SERIAL_MXS_AUART
- depends on ARCH_MXS
+ depends on ARCH_MXS || COMPILE_TEST
tristate "MXS AUART support"
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
@@ -1545,6 +1546,7 @@ config SERIAL_FSL_LPUART_CONSOLE
bool "Console on Freescale lpuart serial port"
depends on SERIAL_FSL_LPUART=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
help
If you have enabled the lpuart serial port on the Freescale SoCs,
you can make it the console by answering Y to this option.
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index fd87a6f574e3..61b607f2488e 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -508,29 +508,6 @@ static struct uart_driver altera_uart_driver = {
.cons = ALTERA_UART_CONSOLE,
};
-#ifdef CONFIG_OF
-static int altera_uart_get_of_uartclk(struct platform_device *pdev,
- struct uart_port *port)
-{
- int len;
- const __be32 *clk;
-
- clk = of_get_property(pdev->dev.of_node, "clock-frequency", &len);
- if (!clk || len < sizeof(__be32))
- return -ENODEV;
-
- port->uartclk = be32_to_cpup(clk);
-
- return 0;
-}
-#else
-static int altera_uart_get_of_uartclk(struct platform_device *pdev,
- struct uart_port *port)
-{
- return -ENODEV;
-}
-#endif /* CONFIG_OF */
-
static int altera_uart_probe(struct platform_device *pdev)
{
struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
@@ -570,7 +547,8 @@ static int altera_uart_probe(struct platform_device *pdev)
if (platp)
port->uartclk = platp->uartclk;
else {
- ret = altera_uart_get_of_uartclk(pdev, port);
+ ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+ &port->uartclk);
if (ret)
return ret;
}
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index fd27e986b1dd..899a77187bde 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -191,8 +191,8 @@ struct uart_amba_port {
*/
static int pl011_fifo_to_tty(struct uart_amba_port *uap)
{
- u16 status, ch;
- unsigned int flag, max_count = 256;
+ u16 status;
+ unsigned int ch, flag, max_count = 256;
int fifotaken = 0;
while (max_count--) {
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index f3af317131ac..75eb083b3361 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -581,6 +581,7 @@ static const struct of_device_id apbuart_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, apbuart_match);
static struct platform_driver grlib_apbuart_of_driver = {
.probe = apbuart_probe,
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 538ea03bc101..94294558943c 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -112,6 +112,12 @@ struct atmel_uart_char {
#define ATMEL_SERIAL_RINGSIZE 1024
/*
+ * at91: 6 USARTs and one DBGU port (SAM9260)
+ * avr32: 4
+ */
+#define ATMEL_MAX_UART 7
+
+/*
* We wrap our port structure around the generic uart_port.
*/
struct atmel_uart_port {
@@ -921,7 +927,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
sg_set_page(&atmel_port->sg_tx,
virt_to_page(port->state->xmit.buf),
UART_XMIT_SIZE,
- (int)port->state->xmit.buf & ~PAGE_MASK);
+ (unsigned long)port->state->xmit.buf & ~PAGE_MASK);
nent = dma_map_sg(port->dev,
&atmel_port->sg_tx,
1,
@@ -931,10 +937,10 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
dev_dbg(port->dev, "need to release resource of dma\n");
goto chan_err;
} else {
- dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+ dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
sg_dma_len(&atmel_port->sg_tx),
port->state->xmit.buf,
- sg_dma_address(&atmel_port->sg_tx));
+ &sg_dma_address(&atmel_port->sg_tx));
}
/* Configure the slave DMA */
@@ -1103,7 +1109,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
sg_set_page(&atmel_port->sg_rx,
virt_to_page(ring->buf),
sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
- (int)ring->buf & ~PAGE_MASK);
+ (unsigned long)ring->buf & ~PAGE_MASK);
nent = dma_map_sg(port->dev,
&atmel_port->sg_rx,
1,
@@ -1113,10 +1119,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
dev_dbg(port->dev, "need to release resource of dma\n");
goto chan_err;
} else {
- dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+ dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
sg_dma_len(&atmel_port->sg_rx),
ring->buf,
- sg_dma_address(&atmel_port->sg_rx));
+ &sg_dma_address(&atmel_port->sg_rx));
}
/* Configure the slave DMA */
@@ -1676,15 +1682,15 @@ static void atmel_init_rs485(struct uart_port *port,
struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
if (np) {
+ struct serial_rs485 *rs485conf = &port->rs485;
u32 rs485_delay[2];
/* rs485 properties */
if (of_property_read_u32_array(np, "rs485-rts-delay",
rs485_delay, 2) == 0) {
- struct serial_rs485 *rs485conf = &port->rs485;
-
rs485conf->delay_rts_before_send = rs485_delay[0];
rs485conf->delay_rts_after_send = rs485_delay[1];
rs485conf->flags = 0;
+ }
if (of_get_property(np, "rs485-rx-during-tx", NULL))
rs485conf->flags |= SER_RS485_RX_DURING_TX;
@@ -1692,7 +1698,6 @@ static void atmel_init_rs485(struct uart_port *port,
if (of_get_property(np, "linux,rs485-enabled-at-boot-time",
NULL))
rs485conf->flags |= SER_RS485_ENABLED;
- }
} else {
port->rs485 = pdata->rs485;
}
@@ -2296,7 +2301,7 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (port->uartclk / 16 != ser->baud_base)
ret = -EINVAL;
- if ((void *)port->mapbase != ser->iomem_base)
+ if (port->mapbase != (unsigned long)ser->iomem_base)
ret = -EINVAL;
if (port->iobase != ser->port)
ret = -EINVAL;
@@ -2686,7 +2691,7 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
enum mctrl_gpio_idx i;
struct gpio_desc *gpiod;
- p->gpios = mctrl_gpio_init(dev, 0);
+ p->gpios = mctrl_gpio_init_noauto(dev, 0);
if (IS_ERR(p->gpios))
return PTR_ERR(p->gpios);
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index 681e0f3d5e0e..a1c0a89d9c7f 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -474,7 +474,7 @@ static int bcm_uart_startup(struct uart_port *port)
/* register irq and enable rx interrupts */
ret = request_irq(port->irq, bcm_uart_interrupt, 0,
- bcm_uart_type(port), port);
+ dev_name(port->dev), port);
if (ret)
return ret;
bcm_uart_writel(port, UART_RX_INT_MASK, UART_IR_REG);
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index d5d2dd7c7917..b3a4e0cdddaa 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -500,7 +500,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s);
- s->gpios = mctrl_gpio_init(&pdev->dev, 0);
+ s->gpios = mctrl_gpio_init_noauto(&pdev->dev, 0);
if (IS_ERR(s->gpios))
return PTR_ERR(s->gpios);
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 08431adeacd5..d3e3d42c0c12 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1450,6 +1450,7 @@ static const struct of_device_id cpm_uart_match[] = {
},
{}
};
+MODULE_DEVICE_TABLE(of, cpm_uart_match);
static struct platform_driver cpm_uart_driver = {
.driver = {
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 3e4470af5c50..f13f2ebd215b 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -3655,7 +3655,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
wake_up_interruptible(&info->port.open_wait);
}
info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->port.close_wait);
local_irq_restore(flags);
/* port closed */
@@ -3759,23 +3758,6 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
int do_clocal = 0;
/*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (info->port.flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(tty, info->port.close_wait,
- !(info->port.flags & ASYNC_CLOSING));
-#ifdef SERIAL_DO_RESTART
- if (info->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
*/
@@ -3825,7 +3807,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
#endif
break;
}
- if (!(info->port.flags & ASYNC_CLOSING) && do_clocal)
+ if (do_clocal)
/* && (do_clocal || DCD_IS_ASSERTED) */
break;
if (signal_pending(current)) {
@@ -3895,20 +3877,6 @@ rs_open(struct tty_struct *tty, struct file * filp)
info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
/*
- * If the port is in the middle of closing, bail out now
- */
- if (info->port.flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(tty, info->port.close_wait,
- !(info->port.flags & ASYNC_CLOSING));
-#ifdef SERIAL_DO_RESTART
- return ((info->port.flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
* If DMA is enabled try to allocate the irq's.
*/
if (info->port.count == 1) {
diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c
index 6813e316e9ff..2f80bc7e44fb 100644
--- a/drivers/tty/serial/etraxfs-uart.c
+++ b/drivers/tty/serial/etraxfs-uart.c
@@ -894,7 +894,7 @@ static int etraxfs_uart_probe(struct platform_device *pdev)
up->regi_ser = of_iomap(np, 0);
up->port.dev = &pdev->dev;
- up->gpios = mctrl_gpio_init(&pdev->dev, 0);
+ up->gpios = mctrl_gpio_init_noauto(&pdev->dev, 0);
if (IS_ERR(up->gpios))
return PTR_ERR(up->gpios);
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 08ce76f4f261..3d790033744e 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1746,6 +1746,45 @@ static struct console lpuart32_console = {
.data = &lpuart_reg,
};
+static void lpuart_early_write(struct console *con, const char *s, unsigned n)
+{
+ struct earlycon_device *dev = con->data;
+
+ uart_console_write(&dev->port, s, n, lpuart_console_putchar);
+}
+
+static void lpuart32_early_write(struct console *con, const char *s, unsigned n)
+{
+ struct earlycon_device *dev = con->data;
+
+ uart_console_write(&dev->port, s, n, lpuart32_console_putchar);
+}
+
+static int __init lpuart_early_console_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->con->write = lpuart_early_write;
+ return 0;
+}
+
+static int __init lpuart32_early_console_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->con->write = lpuart32_early_write;
+ return 0;
+}
+
+OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
+EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
+
#define LPUART_CONSOLE (&lpuart_console)
#define LPUART32_CONSOLE (&lpuart32_console)
#else
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 536a33b99be9..88246f7e435a 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -1362,7 +1362,7 @@ static struct spi_driver ifx_spi_driver = {
.driver = {
.name = DRVNAME,
.pm = &ifx_spi_pm,
- .owner = THIS_MODULE},
+ },
.probe = ifx_spi_spi_probe,
.shutdown = ifx_spi_spi_shutdown,
.remove = ifx_spi_spi_remove,
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d0388a071ba1..016e4be05cec 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -139,6 +139,7 @@
#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
+#define USR1_AGTIM (1<<8) /* Ageing timer interrupt flag */
#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
@@ -728,11 +729,15 @@ static void imx_dma_rxint(struct imx_port *sport)
if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
sport->dma_is_rxing = 1;
- /* disable the `Recerver Ready Interrrupt` */
+ /* disable the receiver ready and aging timer interrupts */
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_RRDYEN);
writel(temp, sport->port.membase + UCR1);
+ temp = readl(sport->port.membase + UCR2);
+ temp &= ~(UCR2_ATEN);
+ writel(temp, sport->port.membase + UCR2);
+
/* tell the DMA to receive the data. */
start_rx_dma(sport);
}
@@ -749,7 +754,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
sts = readl(sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
- if (sts & USR1_RRDY) {
+ if (sts & (USR1_RRDY | USR1_AGTIM)) {
if (sport->dma_is_enabled)
imx_dma_rxint(sport);
else
@@ -852,19 +857,6 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&sport->port.lock, flags);
}
-#define TXTL 2 /* reset default */
-#define RXTL 1 /* reset default */
-
-static void imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
-{
- unsigned int val;
-
- /* set receiver / transmitter trigger level */
- val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
- val |= TXTL << UFCR_TXTL_SHF | RXTL;
- writel(val, sport->port.membase + UFCR);
-}
-
#define RX_BUF_SIZE (PAGE_SIZE)
static void imx_rx_dma_done(struct imx_port *sport)
{
@@ -873,11 +865,15 @@ static void imx_rx_dma_done(struct imx_port *sport)
spin_lock_irqsave(&sport->port.lock, flags);
- /* Enable this interrupt when the RXFIFO is empty. */
+ /* re-enable interrupts to get notified when new symbols are incoming */
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN;
writel(temp, sport->port.membase + UCR1);
+ temp = readl(sport->port.membase + UCR2);
+ temp |= UCR2_ATEN;
+ writel(temp, sport->port.membase + UCR2);
+
sport->dma_is_rxing = 0;
/* Is the shutdown waiting for us? */
@@ -888,14 +884,12 @@ static void imx_rx_dma_done(struct imx_port *sport)
}
/*
- * There are three kinds of RX DMA interrupts(such as in the MX6Q):
+ * There are two kinds of RX DMA interrupts(such as in the MX6Q):
* [1] the RX DMA buffer is full.
- * [2] the Aging timer expires(wait for 8 bytes long)
- * [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
+ * [2] the aging timer expires
*
- * The [2] is trigger when a character was been sitting in the FIFO
- * meanwhile [3] can wait for 32 bytes long when the RX line is
- * on IDLE state and RxFIFO is empty.
+ * Condition [2] is triggered when a character has been sitting in the FIFO
+ * for at least 8 byte durations.
*/
static void dma_rx_callback(void *data)
{
@@ -913,13 +907,6 @@ static void dma_rx_callback(void *data)
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue;
- if (readl(sport->port.membase + USR2) & USR2_IDLE) {
- /* In condition [3] the SDMA counted up too early */
- count--;
-
- writel(USR2_IDLE, sport->port.membase + USR2);
- }
-
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) {
@@ -931,23 +918,21 @@ static void dma_rx_callback(void *data)
sport->port.icount.buf_overrun++;
}
tty_flip_buffer_push(port);
+ sport->port.icount.rx += count;
+ }
+ /*
+ * Restart RX DMA directly if more data is available in order to skip
+ * the roundtrip through the IRQ handler. If there is some data already
+ * in the FIFO, DMA needs to be restarted soon anyways.
+ *
+ * Otherwise stop the DMA and reactivate FIFO IRQs to restart DMA once
+ * data starts to arrive again.
+ */
+ if (readl(sport->port.membase + USR2) & USR2_RDR)
start_rx_dma(sport);
- } else if (readl(sport->port.membase + USR2) & USR2_RDR) {
- /*
- * start rx_dma directly once data in RXFIFO, more efficient
- * than before:
- * 1. call imx_rx_dma_done to stop dma if no data received
- * 2. wait next RDR interrupt to start dma transfer.
- */
- start_rx_dma(sport);
- } else {
- /*
- * stop dma to prevent too many IDLE event trigged if no data
- * in RXFIFO
- */
+ else
imx_rx_dma_done(sport);
- }
}
static int start_rx_dma(struct imx_port *sport)
@@ -980,6 +965,22 @@ static int start_rx_dma(struct imx_port *sport)
return 0;
}
+#define TXTL_DEFAULT 2 /* reset default */
+#define RXTL_DEFAULT 1 /* reset default */
+#define TXTL_DMA 8 /* DMA burst setting */
+#define RXTL_DMA 9 /* DMA burst setting */
+
+static void imx_setup_ufcr(struct imx_port *sport,
+ unsigned char txwl, unsigned char rxwl)
+{
+ unsigned int val;
+
+ /* set receiver / transmitter trigger level */
+ val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+ val |= txwl << UFCR_TXTL_SHF | rxwl;
+ writel(val, sport->port.membase + UFCR);
+}
+
static void imx_uart_dma_exit(struct imx_port *sport)
{
if (sport->dma_chan_rx) {
@@ -1015,7 +1016,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = sport->port.mapbase + URXD0;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- slave_config.src_maxburst = RXTL;
+ /* one byte less than the watermark level to enable the aging timer */
+ slave_config.src_maxburst = RXTL_DMA - 1;
ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
if (ret) {
dev_err(dev, "error in RX dma configuration.\n");
@@ -1039,7 +1041,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = sport->port.mapbase + URTX0;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- slave_config.dst_maxburst = TXTL;
+ slave_config.dst_maxburst = TXTL_DMA;
ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
if (ret) {
dev_err(dev, "error in TX dma configuration.");
@@ -1062,15 +1064,14 @@ static void imx_enable_dma(struct imx_port *sport)
/* set UCR1 */
temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
- /* wait for 32 idle frames for IDDMA interrupt */
- UCR1_ICD_REG(3);
+ temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
writel(temp, sport->port.membase + UCR1);
- /* set UCR4 */
- temp = readl(sport->port.membase + UCR4);
- temp |= UCR4_IDDMAEN;
- writel(temp, sport->port.membase + UCR4);
+ temp = readl(sport->port.membase + UCR2);
+ temp |= UCR2_ATEN;
+ writel(temp, sport->port.membase + UCR2);
+
+ imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
sport->dma_is_enabled = 1;
}
@@ -1086,13 +1087,10 @@ static void imx_disable_dma(struct imx_port *sport)
/* clear UCR2 */
temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_CTSC | UCR2_CTS);
+ temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
writel(temp, sport->port.membase + UCR2);
- /* clear UCR4 */
- temp = readl(sport->port.membase + UCR4);
- temp &= ~UCR4_IDDMAEN;
- writel(temp, sport->port.membase + UCR4);
+ imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
sport->dma_is_enabled = 0;
}
@@ -1115,7 +1113,7 @@ static int imx_startup(struct uart_port *port)
return retval;
}
- imx_setup_ufcr(sport, 0);
+ imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
/* disable the DREN bit (Data Ready interrupt enable) before
* requesting IRQs
@@ -1128,6 +1126,11 @@ static int imx_startup(struct uart_port *port)
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
+ /* Can we enable the DMA support? */
+ if (is_imx6q_uart(sport) && !uart_console(port) &&
+ !sport->dma_is_inited)
+ imx_uart_dma_init(sport);
+
spin_lock_irqsave(&sport->port.lock, flags);
/* Reset fifo's and state machines */
i = 100;
@@ -1145,6 +1148,9 @@ static int imx_startup(struct uart_port *port)
writel(USR1_RTSD, sport->port.membase + USR1);
writel(USR2_ORE, sport->port.membase + USR2);
+ if (sport->dma_is_inited && !sport->dma_is_enabled)
+ imx_enable_dma(sport);
+
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
@@ -1278,7 +1284,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
- unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
+ unsigned int ucr2, old_ucr1, old_ucr2, baud, quot;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
unsigned int div, ufcr;
unsigned long num, denom;
@@ -1315,11 +1321,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
} else {
ucr2 |= UCR2_CTSC;
}
-
- /* Can we enable the DMA support? */
- if (is_imx6q_uart(sport) && !uart_console(port)
- && !sport->dma_is_inited)
- imx_uart_dma_init(sport);
} else {
termios->c_cflag &= ~CRTSCTS;
}
@@ -1387,10 +1388,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
barrier();
/* then, disable everything */
- old_txrxen = readl(sport->port.membase + UCR2);
- writel(old_txrxen & ~(UCR2_TXEN | UCR2_RXEN),
+ old_ucr2 = readl(sport->port.membase + UCR2);
+ writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
sport->port.membase + UCR2);
- old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
+ old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
@@ -1431,13 +1432,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
writel(old_ucr1, sport->port.membase + UCR1);
/* set the parity, stop bits and data size */
- writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
+ writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
imx_enable_ms(&sport->port);
- if (sport->dma_is_inited && !sport->dma_is_enabled)
- imx_enable_dma(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@@ -1503,7 +1502,7 @@ static int imx_poll_init(struct uart_port *port)
if (retval)
clk_disable_unprepare(sport->clk_ipg);
- imx_setup_ufcr(sport, 0);
+ imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
spin_lock_irqsave(&sport->port.lock, flags);
@@ -1773,7 +1772,7 @@ imx_console_setup(struct console *co, char *options)
else
imx_console_get_options(sport, &baud, &parity, &bits);
- imx_setup_ufcr(sport, 0);
+ imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
@@ -1803,6 +1802,38 @@ static struct console imx_console = {
};
#define IMX_CONSOLE &imx_console
+
+#ifdef CONFIG_OF
+static void imx_console_early_putchar(struct uart_port *port, int ch)
+{
+ while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
+ cpu_relax();
+
+ writel_relaxed(ch, port->membase + URTX0);
+}
+
+static void imx_console_early_write(struct console *con, const char *s,
+ unsigned count)
+{
+ struct earlycon_device *dev = con->data;
+
+ uart_console_write(&dev->port, s, count, imx_console_early_putchar);
+}
+
+static int __init
+imx_console_early_setup(struct earlycon_device *dev, const char *opt)
+{
+ if (!dev->port.membase)
+ return -ENODEV;
+
+ dev->con->write = imx_console_early_write;
+
+ return 0;
+}
+OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
+OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
+#endif
+
#else
#define IMX_CONSOLE NULL
#endif
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index e92d7ebe9e77..7eb04ae71cc8 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -691,12 +691,13 @@ static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
p->port.mapbase = res->start;
p->port.membase = NULL;
- p->port.irq = platform_get_irq(pdev, 0);
- if (p->port.irq < 0) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
uarts_registered);
- return p->port.irq;
+ return ret;
}
+ p->port.irq = ret;
p->port.iotype = UPIO_MEM32;
p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 077377259a2c..5c4c280b3207 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -904,7 +904,6 @@ static SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume);
static struct spi_driver max3100_driver = {
.driver = {
.name = "max3100",
- .owner = THIS_MODULE,
.pm = MAX3100_PM_OPS,
},
.probe = max3100_probe,
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 182549f55904..d45133056f51 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1338,7 +1338,6 @@ MODULE_DEVICE_TABLE(spi, max310x_id_table);
static struct spi_driver max310x_uart_driver = {
.driver = {
.name = MAX310X_NAME,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(max310x_dt_ids),
.pm = &max310x_pm_ops,
},
diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c
index b90e7b30468b..3141aa20843d 100644
--- a/drivers/tty/serial/men_z135_uart.c
+++ b/drivers/tty/serial/men_z135_uart.c
@@ -35,8 +35,6 @@
#define MEN_Z135_BAUD_REG 0x810
#define MEN_Z135_TIMEOUT 0x814
-#define MEN_Z135_MEM_SIZE 0x818
-
#define IRQ_ID(x) ((x) & 0x1f)
#define MEN_Z135_IER_RXCIEN BIT(0) /* RX Space IRQ */
@@ -124,6 +122,7 @@ MODULE_PARM_DESC(rx_timeout, "RX timeout. "
struct men_z135_port {
struct uart_port port;
struct mcb_device *mdev;
+ struct resource *mem;
unsigned char *rxbuf;
u32 stat_reg;
spinlock_t lock;
@@ -734,22 +733,30 @@ static const char *men_z135_type(struct uart_port *port)
static void men_z135_release_port(struct uart_port *port)
{
+ struct men_z135_port *uart = to_men_z135(port);
+
iounmap(port->membase);
port->membase = NULL;
- release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
+ mcb_release_mem(uart->mem);
}
static int men_z135_request_port(struct uart_port *port)
{
- int size = MEN_Z135_MEM_SIZE;
+ struct men_z135_port *uart = to_men_z135(port);
+ struct mcb_device *mdev = uart->mdev;
+ struct resource *mem;
+
+ mem = mcb_request_mem(uart->mdev, dev_name(&mdev->dev));
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
- if (!request_mem_region(port->mapbase, size, "men_z135_port"))
- return -EBUSY;
+ port->mapbase = mem->start;
+ uart->mem = mem;
- port->membase = ioremap(port->mapbase, MEN_Z135_MEM_SIZE);
+ port->membase = ioremap(mem->start, resource_size(mem));
if (port->membase == NULL) {
- release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
+ mcb_release_mem(mem);
return -ENOMEM;
}
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 41de374d9784..8c3e51314470 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1135,6 +1135,13 @@ mpc52xx_uart_startup(struct uart_port *port)
psc_ops->command(port, MPC52xx_PSC_RST_RX);
psc_ops->command(port, MPC52xx_PSC_RST_TX);
+ /*
+ * According to Freescale's support the RST_TX command can produce a
+ * spike on the TX pin. So they recommend to delay "for one character".
+ * One millisecond should be enough for everyone.
+ */
+ msleep(1);
+
psc_ops->set_sicr(port, 0); /* UART mode DCD ignored */
psc_ops->fifo_init(port);
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index 82bb6d1fe23b..cadfd1cfae2b 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -55,8 +55,6 @@
#define SUPPORT_SYSRQ
#endif
-#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/ioport.h>
@@ -755,7 +753,7 @@ static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
pi->port.line);
if (!pi->dma_region) {
- if (!dma_supported(pi->port.dev, 0xffffffff)) {
+ if (!dma_set_mask(pi->port.dev, 0xffffffff)) {
printk(KERN_ERR "MPSC: Inadequate DMA support\n");
rc = -ENXIO;
} else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
@@ -2108,26 +2106,11 @@ static int mpsc_drv_probe(struct platform_device *dev)
return rc;
}
-static int mpsc_drv_remove(struct platform_device *dev)
-{
- pr_debug("mpsc_drv_exit: Removing MPSC %d\n", dev->id);
-
- if (dev->id < MPSC_NUM_CTLRS) {
- uart_remove_one_port(&mpsc_reg, &mpsc_ports[dev->id].port);
- mpsc_release_port((struct uart_port *)
- &mpsc_ports[dev->id].port);
- mpsc_drv_unmap_regs(&mpsc_ports[dev->id]);
- return 0;
- } else {
- return -ENODEV;
- }
-}
-
static struct platform_driver mpsc_driver = {
.probe = mpsc_drv_probe,
- .remove = mpsc_drv_remove,
.driver = {
- .name = MPSC_CTLR_NAME,
+ .name = MPSC_CTLR_NAME,
+ .suppress_bind_attrs = true,
},
};
@@ -2156,22 +2139,10 @@ static int __init mpsc_drv_init(void)
return rc;
}
+device_initcall(mpsc_drv_init);
-static void __exit mpsc_drv_exit(void)
-{
- platform_driver_unregister(&mpsc_driver);
- platform_driver_unregister(&mpsc_shared_driver);
- uart_unregister_driver(&mpsc_reg);
- memset(mpsc_ports, 0, sizeof(mpsc_ports));
- memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
-}
-
-module_init(mpsc_drv_init);
-module_exit(mpsc_drv_exit);
-
+/*
MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver");
-MODULE_VERSION(MPSC_VERSION);
MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(MPSC_MAJOR);
-MODULE_ALIAS("platform:" MPSC_CTLR_NAME);
+*/
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b73889c8ed4b..dcde955475dc 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -20,6 +20,8 @@
#endif
#include <linux/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/io.h>
@@ -31,6 +33,7 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
@@ -39,6 +42,11 @@
#include "msm_serial.h"
+#define UARTDM_BURST_SIZE 16 /* in bytes */
+#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
+#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
+#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
+
enum {
UARTDM_1P1 = 1,
UARTDM_1P2,
@@ -46,6 +54,17 @@ enum {
UARTDM_1P4,
};
+struct msm_dma {
+ struct dma_chan *chan;
+ enum dma_data_direction dir;
+ dma_addr_t phys;
+ unsigned char *virt;
+ dma_cookie_t cookie;
+ u32 enable_bit;
+ unsigned int count;
+ struct dma_async_tx_descriptor *desc;
+};
+
struct msm_port {
struct uart_port uart;
char name[16];
@@ -55,9 +74,153 @@ struct msm_port {
int is_uartdm;
unsigned int old_snap_state;
bool break_detected;
+ struct msm_dma tx_dma;
+ struct msm_dma rx_dma;
};
-static inline void wait_for_xmitr(struct uart_port *port)
+static void msm_handle_tx(struct uart_port *port);
+static void msm_start_rx_dma(struct msm_port *msm_port);
+
+void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
+{
+ struct device *dev = port->dev;
+ unsigned int mapped;
+ u32 val;
+
+ mapped = dma->count;
+ dma->count = 0;
+
+ dmaengine_terminate_all(dma->chan);
+
+ /*
+ * DMA Stall happens if enqueue and flush command happens concurrently.
+ * For example before changing the baud rate/protocol configuration and
+ * sending flush command to ADM, disable the channel of UARTDM.
+ * Note: should not reset the receiver here immediately as it is not
+ * suggested to do disable/reset or reset/disable at the same time.
+ */
+ val = msm_read(port, UARTDM_DMEN);
+ val &= ~dma->enable_bit;
+ msm_write(port, val, UARTDM_DMEN);
+
+ if (mapped)
+ dma_unmap_single(dev, dma->phys, mapped, dma->dir);
+}
+
+static void msm_release_dma(struct msm_port *msm_port)
+{
+ struct msm_dma *dma;
+
+ dma = &msm_port->tx_dma;
+ if (dma->chan) {
+ msm_stop_dma(&msm_port->uart, dma);
+ dma_release_channel(dma->chan);
+ }
+
+ memset(dma, 0, sizeof(*dma));
+
+ dma = &msm_port->rx_dma;
+ if (dma->chan) {
+ msm_stop_dma(&msm_port->uart, dma);
+ dma_release_channel(dma->chan);
+ kfree(dma->virt);
+ }
+
+ memset(dma, 0, sizeof(*dma));
+}
+
+static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
+{
+ struct device *dev = msm_port->uart.dev;
+ struct dma_slave_config conf;
+ struct msm_dma *dma;
+ u32 crci = 0;
+ int ret;
+
+ dma = &msm_port->tx_dma;
+
+ /* allocate DMA resources, if available */
+ dma->chan = dma_request_slave_channel_reason(dev, "tx");
+ if (IS_ERR(dma->chan))
+ goto no_tx;
+
+ of_property_read_u32(dev->of_node, "qcom,tx-crci", &crci);
+
+ memset(&conf, 0, sizeof(conf));
+ conf.direction = DMA_MEM_TO_DEV;
+ conf.device_fc = true;
+ conf.dst_addr = base + UARTDM_TF;
+ conf.dst_maxburst = UARTDM_BURST_SIZE;
+ conf.slave_id = crci;
+
+ ret = dmaengine_slave_config(dma->chan, &conf);
+ if (ret)
+ goto rel_tx;
+
+ dma->dir = DMA_TO_DEVICE;
+
+ if (msm_port->is_uartdm < UARTDM_1P4)
+ dma->enable_bit = UARTDM_DMEN_TX_DM_ENABLE;
+ else
+ dma->enable_bit = UARTDM_DMEN_TX_BAM_ENABLE;
+
+ return;
+
+rel_tx:
+ dma_release_channel(dma->chan);
+no_tx:
+ memset(dma, 0, sizeof(*dma));
+}
+
+static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
+{
+ struct device *dev = msm_port->uart.dev;
+ struct dma_slave_config conf;
+ struct msm_dma *dma;
+ u32 crci = 0;
+ int ret;
+
+ dma = &msm_port->rx_dma;
+
+ /* allocate DMA resources, if available */
+ dma->chan = dma_request_slave_channel_reason(dev, "rx");
+ if (IS_ERR(dma->chan))
+ goto no_rx;
+
+ of_property_read_u32(dev->of_node, "qcom,rx-crci", &crci);
+
+ dma->virt = kzalloc(UARTDM_RX_SIZE, GFP_KERNEL);
+ if (!dma->virt)
+ goto rel_rx;
+
+ memset(&conf, 0, sizeof(conf));
+ conf.direction = DMA_DEV_TO_MEM;
+ conf.device_fc = true;
+ conf.src_addr = base + UARTDM_RF;
+ conf.src_maxburst = UARTDM_BURST_SIZE;
+ conf.slave_id = crci;
+
+ ret = dmaengine_slave_config(dma->chan, &conf);
+ if (ret)
+ goto err;
+
+ dma->dir = DMA_FROM_DEVICE;
+
+ if (msm_port->is_uartdm < UARTDM_1P4)
+ dma->enable_bit = UARTDM_DMEN_RX_DM_ENABLE;
+ else
+ dma->enable_bit = UARTDM_DMEN_RX_BAM_ENABLE;
+
+ return;
+err:
+ kfree(dma->virt);
+rel_rx:
+ dma_release_channel(dma->chan);
+no_rx:
+ memset(dma, 0, sizeof(*dma));
+}
+
+static inline void msm_wait_for_xmitr(struct uart_port *port)
{
while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
@@ -78,17 +241,277 @@ static void msm_stop_tx(struct uart_port *port)
static void msm_start_tx(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
+ struct msm_dma *dma = &msm_port->tx_dma;
+
+ /* Already started in DMA mode */
+ if (dma->count)
+ return;
+
+ msm_port->imr |= UART_IMR_TXLEV;
+ msm_write(port, msm_port->imr, UART_IMR);
+}
+
+static void msm_reset_dm_count(struct uart_port *port, int count)
+{
+ msm_wait_for_xmitr(port);
+ msm_write(port, count, UARTDM_NCF_TX);
+ msm_read(port, UARTDM_NCF_TX);
+}
+
+static void msm_complete_tx_dma(void *args)
+{
+ struct msm_port *msm_port = args;
+ struct uart_port *port = &msm_port->uart;
+ struct circ_buf *xmit = &port->state->xmit;
+ struct msm_dma *dma = &msm_port->tx_dma;
+ struct dma_tx_state state;
+ enum dma_status status;
+ unsigned long flags;
+ unsigned int count;
+ u32 val;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Already stopped */
+ if (!dma->count)
+ goto done;
+
+ status = dmaengine_tx_status(dma->chan, dma->cookie, &state);
+
+ dma_unmap_single(port->dev, dma->phys, dma->count, dma->dir);
+ val = msm_read(port, UARTDM_DMEN);
+ val &= ~dma->enable_bit;
+ msm_write(port, val, UARTDM_DMEN);
+
+ if (msm_port->is_uartdm > UARTDM_1P3) {
+ msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
+ msm_write(port, UART_CR_TX_ENABLE, UART_CR);
+ }
+
+ count = dma->count - state.residue;
+ port->icount.tx += count;
+ dma->count = 0;
+
+ xmit->tail += count;
+ xmit->tail &= UART_XMIT_SIZE - 1;
+
+ /* Restore "Tx FIFO below watermark" interrupt */
msm_port->imr |= UART_IMR_TXLEV;
msm_write(port, msm_port->imr, UART_IMR);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ msm_handle_tx(port);
+done:
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count)
+{
+ struct circ_buf *xmit = &msm_port->uart.state->xmit;
+ struct uart_port *port = &msm_port->uart;
+ struct msm_dma *dma = &msm_port->tx_dma;
+ void *cpu_addr;
+ int ret;
+ u32 val;
+
+ cpu_addr = &xmit->buf[xmit->tail];
+
+ dma->phys = dma_map_single(port->dev, cpu_addr, count, dma->dir);
+ ret = dma_mapping_error(port->dev, dma->phys);
+ if (ret)
+ return ret;
+
+ dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys,
+ count, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT |
+ DMA_PREP_FENCE);
+ if (!dma->desc) {
+ ret = -EIO;
+ goto unmap;
+ }
+
+ dma->desc->callback = msm_complete_tx_dma;
+ dma->desc->callback_param = msm_port;
+
+ dma->cookie = dmaengine_submit(dma->desc);
+ ret = dma_submit_error(dma->cookie);
+ if (ret)
+ goto unmap;
+
+ /*
+ * Using DMA complete for Tx FIFO reload, no need for
+ * "Tx FIFO below watermark" one, disable it
+ */
+ msm_port->imr &= ~UART_IMR_TXLEV;
+ msm_write(port, msm_port->imr, UART_IMR);
+
+ dma->count = count;
+
+ val = msm_read(port, UARTDM_DMEN);
+ val |= dma->enable_bit;
+
+ if (msm_port->is_uartdm < UARTDM_1P4)
+ msm_write(port, val, UARTDM_DMEN);
+
+ msm_reset_dm_count(port, count);
+
+ if (msm_port->is_uartdm > UARTDM_1P3)
+ msm_write(port, val, UARTDM_DMEN);
+
+ dma_async_issue_pending(dma->chan);
+ return 0;
+unmap:
+ dma_unmap_single(port->dev, dma->phys, count, dma->dir);
+ return ret;
+}
+
+static void msm_complete_rx_dma(void *args)
+{
+ struct msm_port *msm_port = args;
+ struct uart_port *port = &msm_port->uart;
+ struct tty_port *tport = &port->state->port;
+ struct msm_dma *dma = &msm_port->rx_dma;
+ int count = 0, i, sysrq;
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Already stopped */
+ if (!dma->count)
+ goto done;
+
+ val = msm_read(port, UARTDM_DMEN);
+ val &= ~dma->enable_bit;
+ msm_write(port, val, UARTDM_DMEN);
+
+ /* Restore interrupts */
+ msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
+ msm_write(port, msm_port->imr, UART_IMR);
+
+ if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
+ port->icount.overrun++;
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+ msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
+ }
+
+ count = msm_read(port, UARTDM_RX_TOTAL_SNAP);
+
+ port->icount.rx += count;
+
+ dma->count = 0;
+
+ dma_unmap_single(port->dev, dma->phys, UARTDM_RX_SIZE, dma->dir);
+
+ for (i = 0; i < count; i++) {
+ char flag = TTY_NORMAL;
+
+ if (msm_port->break_detected && dma->virt[i] == 0) {
+ port->icount.brk++;
+ flag = TTY_BREAK;
+ msm_port->break_detected = false;
+ if (uart_handle_break(port))
+ continue;
+ }
+
+ if (!(port->read_status_mask & UART_SR_RX_BREAK))
+ flag = TTY_NORMAL;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ sysrq = uart_handle_sysrq_char(port, dma->virt[i]);
+ spin_lock_irqsave(&port->lock, flags);
+ if (!sysrq)
+ tty_insert_flip_char(tport, dma->virt[i], flag);
+ }
+
+ msm_start_rx_dma(msm_port);
+done:
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (count)
+ tty_flip_buffer_push(tport);
+}
+
+static void msm_start_rx_dma(struct msm_port *msm_port)
+{
+ struct msm_dma *dma = &msm_port->rx_dma;
+ struct uart_port *uart = &msm_port->uart;
+ u32 val;
+ int ret;
+
+ if (!dma->chan)
+ return;
+
+ dma->phys = dma_map_single(uart->dev, dma->virt,
+ UARTDM_RX_SIZE, dma->dir);
+ ret = dma_mapping_error(uart->dev, dma->phys);
+ if (ret)
+ return;
+
+ dma->desc = dmaengine_prep_slave_single(dma->chan, dma->phys,
+ UARTDM_RX_SIZE, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT);
+ if (!dma->desc)
+ goto unmap;
+
+ dma->desc->callback = msm_complete_rx_dma;
+ dma->desc->callback_param = msm_port;
+
+ dma->cookie = dmaengine_submit(dma->desc);
+ ret = dma_submit_error(dma->cookie);
+ if (ret)
+ goto unmap;
+ /*
+ * Using DMA for FIFO off-load, no need for "Rx FIFO over
+ * watermark" or "stale" interrupts, disable them
+ */
+ msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
+
+ /*
+ * Well, when DMA is ADM3 engine(implied by <= UARTDM v1.3),
+ * we need RXSTALE to flush input DMA fifo to memory
+ */
+ if (msm_port->is_uartdm < UARTDM_1P4)
+ msm_port->imr |= UART_IMR_RXSTALE;
+
+ msm_write(uart, msm_port->imr, UART_IMR);
+
+ dma->count = UARTDM_RX_SIZE;
+
+ dma_async_issue_pending(dma->chan);
+
+ msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR);
+ msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+
+ val = msm_read(uart, UARTDM_DMEN);
+ val |= dma->enable_bit;
+
+ if (msm_port->is_uartdm < UARTDM_1P4)
+ msm_write(uart, val, UARTDM_DMEN);
+
+ msm_write(uart, UARTDM_RX_SIZE, UARTDM_DMRX);
+
+ if (msm_port->is_uartdm > UARTDM_1P3)
+ msm_write(uart, val, UARTDM_DMEN);
+
+ return;
+unmap:
+ dma_unmap_single(uart->dev, dma->phys, UARTDM_RX_SIZE, dma->dir);
}
static void msm_stop_rx(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
+ struct msm_dma *dma = &msm_port->rx_dma;
msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
msm_write(port, msm_port->imr, UART_IMR);
+
+ if (dma->chan)
+ msm_stop_dma(port, dma);
}
static void msm_enable_ms(struct uart_port *port)
@@ -99,7 +522,7 @@ static void msm_enable_ms(struct uart_port *port)
msm_write(port, msm_port->imr, UART_IMR);
}
-static void handle_rx_dm(struct uart_port *port, unsigned int misr)
+static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
{
struct tty_port *tport = &port->state->port;
unsigned int sr;
@@ -169,9 +592,12 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
msm_write(port, 0xFFFFFF, UARTDM_DMRX);
msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+
+ /* Try to use DMA */
+ msm_start_rx_dma(msm_port);
}
-static void handle_rx(struct uart_port *port)
+static void msm_handle_rx(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
unsigned int sr;
@@ -224,18 +650,11 @@ static void handle_rx(struct uart_port *port)
spin_lock(&port->lock);
}
-static void reset_dm_count(struct uart_port *port, int count)
-{
- wait_for_xmitr(port);
- msm_write(port, count, UARTDM_NCF_TX);
- msm_read(port, UARTDM_NCF_TX);
-}
-
-static void handle_tx(struct uart_port *port)
+static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)
{
struct circ_buf *xmit = &port->state->xmit;
struct msm_port *msm_port = UART_TO_MSM(port);
- unsigned int tx_count, num_chars;
+ unsigned int num_chars;
unsigned int tf_pointer = 0;
void __iomem *tf;
@@ -244,20 +663,8 @@ static void handle_tx(struct uart_port *port)
else
tf = port->membase + UART_TF;
- tx_count = uart_circ_chars_pending(xmit);
- tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
- port->fifosize);
-
- if (port->x_char) {
- if (msm_port->is_uartdm)
- reset_dm_count(port, tx_count + 1);
-
- iowrite8_rep(tf, &port->x_char, 1);
- port->icount.tx++;
- port->x_char = 0;
- } else if (tx_count && msm_port->is_uartdm) {
- reset_dm_count(port, tx_count);
- }
+ if (tx_count && msm_port->is_uartdm)
+ msm_reset_dm_count(port, tx_count);
while (tf_pointer < tx_count) {
int i;
@@ -290,20 +697,76 @@ static void handle_tx(struct uart_port *port)
uart_write_wakeup(port);
}
-static void handle_delta_cts(struct uart_port *port)
+static void msm_handle_tx(struct uart_port *port)
+{
+ struct msm_port *msm_port = UART_TO_MSM(port);
+ struct circ_buf *xmit = &msm_port->uart.state->xmit;
+ struct msm_dma *dma = &msm_port->tx_dma;
+ unsigned int pio_count, dma_count, dma_min;
+ void __iomem *tf;
+ int err = 0;
+
+ if (port->x_char) {
+ if (msm_port->is_uartdm)
+ tf = port->membase + UARTDM_TF;
+ else
+ tf = port->membase + UART_TF;
+
+ if (msm_port->is_uartdm)
+ msm_reset_dm_count(port, 1);
+
+ iowrite8_rep(tf, &port->x_char, 1);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ msm_stop_tx(port);
+ return;
+ }
+
+ pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+
+ dma_min = 1; /* Always DMA */
+ if (msm_port->is_uartdm > UARTDM_1P3) {
+ dma_count = UARTDM_TX_AIGN(dma_count);
+ dma_min = UARTDM_BURST_SIZE;
+ } else {
+ if (dma_count > UARTDM_TX_MAX)
+ dma_count = UARTDM_TX_MAX;
+ }
+
+ if (pio_count > port->fifosize)
+ pio_count = port->fifosize;
+
+ if (!dma->chan || dma_count < dma_min)
+ msm_handle_tx_pio(port, pio_count);
+ else
+ err = msm_handle_tx_dma(msm_port, dma_count);
+
+ if (err) /* fall back to PIO mode */
+ msm_handle_tx_pio(port, pio_count);
+}
+
+static void msm_handle_delta_cts(struct uart_port *port)
{
msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
port->icount.cts++;
wake_up_interruptible(&port->state->port.delta_msr_wait);
}
-static irqreturn_t msm_irq(int irq, void *dev_id)
+static irqreturn_t msm_uart_irq(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
struct msm_port *msm_port = UART_TO_MSM(port);
+ struct msm_dma *dma = &msm_port->rx_dma;
+ unsigned long flags;
unsigned int misr;
+ u32 val;
- spin_lock(&port->lock);
+ spin_lock_irqsave(&port->lock, flags);
misr = msm_read(port, UART_MISR);
msm_write(port, 0, UART_IMR); /* disable interrupt */
@@ -313,18 +776,29 @@ static irqreturn_t msm_irq(int irq, void *dev_id)
}
if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) {
- if (msm_port->is_uartdm)
- handle_rx_dm(port, misr);
- else
- handle_rx(port);
+ if (dma->count) {
+ val = UART_CR_CMD_STALE_EVENT_DISABLE;
+ msm_write(port, val, UART_CR);
+ val = UART_CR_CMD_RESET_STALE_INT;
+ msm_write(port, val, UART_CR);
+ /*
+ * Flush DMA input fifo to memory, this will also
+ * trigger DMA RX completion
+ */
+ dmaengine_terminate_all(dma->chan);
+ } else if (msm_port->is_uartdm) {
+ msm_handle_rx_dm(port, misr);
+ } else {
+ msm_handle_rx(port);
+ }
}
if (misr & UART_IMR_TXLEV)
- handle_tx(port);
+ msm_handle_tx(port);
if (misr & UART_IMR_DELTA_CTS)
- handle_delta_cts(port);
+ msm_handle_delta_cts(port);
msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
- spin_unlock(&port->lock);
+ spin_unlock_irqrestore(&port->lock, flags);
return IRQ_HANDLED;
}
@@ -408,6 +882,7 @@ msm_find_best_baud(struct uart_port *port, unsigned int baud)
{ 3, 0xdd, 8 },
{ 2, 0xee, 16 },
{ 1, 0xff, 31 },
+ { 0, 0xff, 31 },
};
divisor = uart_get_divisor(port, baud);
@@ -419,21 +894,41 @@ msm_find_best_baud(struct uart_port *port, unsigned int baud)
return entry; /* Default to smallest divider */
}
-static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
+static int msm_set_baud_rate(struct uart_port *port, unsigned int baud,
+ unsigned long *saved_flags)
{
- unsigned int rxstale, watermark;
+ unsigned int rxstale, watermark, mask;
struct msm_port *msm_port = UART_TO_MSM(port);
const struct msm_baud_map *entry;
+ unsigned long flags;
entry = msm_find_best_baud(port, baud);
msm_write(port, entry->code, UART_CSR);
+ if (baud > 460800)
+ port->uartclk = baud * 16;
+
+ flags = *saved_flags;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ clk_set_rate(msm_port->clk, port->uartclk);
+
+ spin_lock_irqsave(&port->lock, flags);
+ *saved_flags = flags;
+
/* RX stale watermark */
rxstale = entry->rxstale;
watermark = UART_IPR_STALE_LSB & rxstale;
- watermark |= UART_IPR_RXSTALE_LAST;
- watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
+ if (msm_port->is_uartdm) {
+ mask = UART_DM_IPR_STALE_TIMEOUT_MSB;
+ } else {
+ watermark |= UART_IPR_RXSTALE_LAST;
+ mask = UART_IPR_STALE_TIMEOUT_MSB;
+ }
+
+ watermark |= mask & (rxstale << 2);
+
msm_write(port, watermark, UART_IPR);
/* set RX watermark */
@@ -476,13 +971,13 @@ static void msm_init_clock(struct uart_port *port)
static int msm_startup(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
- unsigned int data, rfr_level;
+ unsigned int data, rfr_level, mask;
int ret;
snprintf(msm_port->name, sizeof(msm_port->name),
"msm_serial%d", port->line);
- ret = request_irq(port->irq, msm_irq, IRQF_TRIGGER_HIGH,
+ ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH,
msm_port->name, port);
if (unlikely(ret))
return ret;
@@ -496,11 +991,23 @@ static int msm_startup(struct uart_port *port)
/* set automatic RFR level */
data = msm_read(port, UART_MR1);
- data &= ~UART_MR1_AUTO_RFR_LEVEL1;
+
+ if (msm_port->is_uartdm)
+ mask = UART_DM_MR1_AUTO_RFR_LEVEL1;
+ else
+ mask = UART_MR1_AUTO_RFR_LEVEL1;
+
+ data &= ~mask;
data &= ~UART_MR1_AUTO_RFR_LEVEL0;
- data |= UART_MR1_AUTO_RFR_LEVEL1 & (rfr_level << 2);
+ data |= mask & (rfr_level << 2);
data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level;
msm_write(port, data, UART_MR1);
+
+ if (msm_port->is_uartdm) {
+ msm_request_tx_dma(msm_port, msm_port->uart.mapbase);
+ msm_request_rx_dma(msm_port, msm_port->uart.mapbase);
+ }
+
return 0;
}
@@ -511,6 +1018,9 @@ static void msm_shutdown(struct uart_port *port)
msm_port->imr = 0;
msm_write(port, 0, UART_IMR); /* disable interrupts */
+ if (msm_port->is_uartdm)
+ msm_release_dma(msm_port);
+
clk_disable_unprepare(msm_port->clk);
free_irq(port->irq, port);
@@ -519,14 +1029,19 @@ static void msm_shutdown(struct uart_port *port)
static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
+ struct msm_port *msm_port = UART_TO_MSM(port);
+ struct msm_dma *dma = &msm_port->rx_dma;
unsigned long flags;
unsigned int baud, mr;
spin_lock_irqsave(&port->lock, flags);
+ if (dma->chan) /* Terminate if any */
+ msm_stop_dma(port, dma);
+
/* calculate and set baud rate */
- baud = uart_get_baud_rate(port, termios, old, 300, 115200);
- baud = msm_set_baud_rate(port, baud);
+ baud = uart_get_baud_rate(port, termios, old, 300, 4000000);
+ baud = msm_set_baud_rate(port, baud, &flags);
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
@@ -588,6 +1103,9 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
uart_update_timeout(port, termios->c_cflag, baud);
+ /* Try to use DMA */
+ msm_start_rx_dma(msm_port);
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -765,7 +1283,7 @@ static void msm_poll_put_char(struct uart_port *port, unsigned char c)
msm_write(port, 0, UART_IMR);
if (msm_port->is_uartdm)
- reset_dm_count(port, 1);
+ msm_reset_dm_count(port, 1);
/* Wait until FIFO is empty */
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
@@ -839,7 +1357,7 @@ static struct msm_port msm_uart_ports[] = {
#define UART_NR ARRAY_SIZE(msm_uart_ports)
-static inline struct uart_port *get_port_from_line(unsigned int line)
+static inline struct uart_port *msm_get_port_from_line(unsigned int line)
{
return &msm_uart_ports[line].uart;
}
@@ -866,7 +1384,7 @@ static void __msm_console_write(struct uart_port *port, const char *s,
spin_lock(&port->lock);
if (is_uartdm)
- reset_dm_count(port, count);
+ msm_reset_dm_count(port, count);
i = 0;
while (i < count) {
@@ -911,7 +1429,7 @@ static void msm_console_write(struct console *co, const char *s,
BUG_ON(co->index < 0 || co->index >= UART_NR);
- port = get_port_from_line(co->index);
+ port = msm_get_port_from_line(co->index);
msm_port = UART_TO_MSM(port);
__msm_console_write(port, s, count, msm_port->is_uartdm);
@@ -928,7 +1446,7 @@ static int __init msm_console_setup(struct console *co, char *options)
if (unlikely(co->index >= UART_NR || co->index < 0))
return -ENXIO;
- port = get_port_from_line(co->index);
+ port = msm_get_port_from_line(co->index);
if (unlikely(!port->membase))
return -ENXIO;
@@ -1043,7 +1561,7 @@ static int msm_serial_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "msm_serial: detected port #%d\n", line);
- port = get_port_from_line(line);
+ port = msm_get_port_from_line(line);
port->dev = &pdev->dev;
msm_port = UART_TO_MSM(port);
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index 737f69fe7113..178645826f16 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -20,11 +20,12 @@
#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
-#define UART_MR1_RX_RDY_CTL (1 << 7)
-#define UART_MR1_CTS_CTL (1 << 6)
+#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
+#define UART_MR1_RX_RDY_CTL BIT(7)
+#define UART_MR1_CTS_CTL BIT(6)
#define UART_MR2 0x0004
-#define UART_MR2_ERROR_MODE (1 << 6)
+#define UART_MR2_ERROR_MODE BIT(6)
#define UART_MR2_BITS_PER_CHAR 0x30
#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
@@ -58,26 +59,28 @@
#define UART_CR_CMD_SET_RFR (13 << 4)
#define UART_CR_CMD_RESET_RFR (14 << 4)
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
+#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
#define UART_CR_CMD_FORCE_STALE (4 << 8)
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
-#define UART_CR_TX_DISABLE (1 << 3)
-#define UART_CR_TX_ENABLE (1 << 2)
-#define UART_CR_RX_DISABLE (1 << 1)
-#define UART_CR_RX_ENABLE (1 << 0)
+#define UART_CR_TX_DISABLE BIT(3)
+#define UART_CR_TX_ENABLE BIT(2)
+#define UART_CR_RX_DISABLE BIT(1)
+#define UART_CR_RX_ENABLE BIT(0)
#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
#define UART_IMR 0x0014
-#define UART_IMR_TXLEV (1 << 0)
-#define UART_IMR_RXSTALE (1 << 3)
-#define UART_IMR_RXLEV (1 << 4)
-#define UART_IMR_DELTA_CTS (1 << 5)
-#define UART_IMR_CURRENT_CTS (1 << 6)
-#define UART_IMR_RXBREAK_START (1 << 10)
+#define UART_IMR_TXLEV BIT(0)
+#define UART_IMR_RXSTALE BIT(3)
+#define UART_IMR_RXLEV BIT(4)
+#define UART_IMR_DELTA_CTS BIT(5)
+#define UART_IMR_CURRENT_CTS BIT(6)
+#define UART_IMR_RXBREAK_START BIT(10)
#define UART_IPR_RXSTALE_LAST 0x20
#define UART_IPR_STALE_LSB 0x1F
#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
+#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
#define UART_IPR 0x0018
#define UART_TFWR 0x001C
@@ -96,20 +99,20 @@
#define UART_TEST_CTRL 0x0050
#define UART_SR 0x0008
-#define UART_SR_HUNT_CHAR (1 << 7)
-#define UART_SR_RX_BREAK (1 << 6)
-#define UART_SR_PAR_FRAME_ERR (1 << 5)
-#define UART_SR_OVERRUN (1 << 4)
-#define UART_SR_TX_EMPTY (1 << 3)
-#define UART_SR_TX_READY (1 << 2)
-#define UART_SR_RX_FULL (1 << 1)
-#define UART_SR_RX_READY (1 << 0)
+#define UART_SR_HUNT_CHAR BIT(7)
+#define UART_SR_RX_BREAK BIT(6)
+#define UART_SR_PAR_FRAME_ERR BIT(5)
+#define UART_SR_OVERRUN BIT(4)
+#define UART_SR_TX_EMPTY BIT(3)
+#define UART_SR_TX_READY BIT(2)
+#define UART_SR_RX_FULL BIT(1)
+#define UART_SR_RX_READY BIT(0)
#define UART_RF 0x000C
#define UARTDM_RF 0x0070
#define UART_MISR 0x0010
#define UART_ISR 0x0014
-#define UART_ISR_TX_READY (1 << 7)
+#define UART_ISR_TX_READY BIT(7)
#define UARTDM_RXFS 0x50
#define UARTDM_RXFS_BUF_SHIFT 0x7
@@ -119,6 +122,12 @@
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
+#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
+#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
+
+#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
+#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
+
#define UARTDM_DMRX 0x34
#define UARTDM_NCF_TX 0x40
#define UARTDM_RX_TOTAL_SNAP 0x38
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
index dd26511ad875..8a4be4b73723 100644
--- a/drivers/tty/serial/mux.c
+++ b/drivers/tty/serial/mux.c
@@ -412,19 +412,14 @@ static int mux_console_setup(struct console *co, char *options)
return 0;
}
-struct tty_driver *mux_console_device(struct console *co, int *index)
-{
- *index = co->index;
- return mux_driver.tty_driver;
-}
-
static struct console mux_console = {
.name = "ttyB",
.write = mux_console_write,
- .device = mux_console_device,
+ .device = uart_console_device,
.setup = mux_console_setup,
.flags = CON_ENABLED | CON_PRINTBUFFER,
.index = 0,
+ .data = &mux_driver,
};
#define MUX_CONSOLE &mux_console
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 7c7f30809849..cd0414bbe094 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1196,7 +1196,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
enum mctrl_gpio_idx i;
struct gpio_desc *gpiod;
- s->gpios = mctrl_gpio_init(dev, 0);
+ s->gpios = mctrl_gpio_init_noauto(dev, 0);
if (IS_ERR(s->gpios))
return PTR_ERR(s->gpios);
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 6823df99bd76..de5029649795 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -21,6 +21,10 @@
#include <linux/nwpserial.h>
#include <linux/clk.h>
+#ifdef CONFIG_SERIAL_8250_MODULE
+#define CONFIG_SERIAL_8250 CONFIG_SERIAL_8250_MODULE
+#endif
+
#include "8250/8250.h"
struct of_serial_info {
@@ -150,6 +154,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
break;
}
+ if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) &&
+ (of_device_is_compatible(np, "fsl,ns16550") ||
+ of_device_is_compatible(np, "fsl,16550-FIFO64")))
+ port->handle_irq = fsl8250_handle_irq;
+
return 0;
out:
if (info->clk)
@@ -350,6 +359,7 @@ static const struct of_device_id of_platform_serial_table[] = {
#endif
{ /* end of list */ },
};
+MODULE_DEVICE_TABLE(of, of_platform_serial_table);
static struct platform_driver of_platform_serial_driver = {
.driver = {
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7a2172b5e93c..9d4c84f7485f 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -199,6 +199,7 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
serial_out(up, UART_FCR, 0);
}
+#ifdef CONFIG_PM
static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
@@ -219,6 +220,7 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
pdata->enable_wakeup(up->dev, enable);
}
+#endif /* CONFIG_PM */
/*
* Calculate the absolute difference between the desired and actual baud
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 856686d6dcdb..d72cd736bdc6 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -385,32 +385,6 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
}
}
-static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
- unsigned long ufstat);
-
-static void uart_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
-{
- struct uart_port *port = &ourport->port;
- struct tty_port *tty = &port->state->port;
- unsigned int ch, ufstat;
- unsigned int count;
-
- ufstat = rd_regl(port, S3C2410_UFSTAT);
- count = s3c24xx_serial_rx_fifocnt(ourport, ufstat);
-
- if (!count)
- return;
-
- while (count-- > 0) {
- ch = rd_regb(port, S3C2410_URXH);
-
- ourport->port.icount.rx++;
- tty_insert_flip_char(tty, ch, TTY_NORMAL);
- }
-
- tty_flip_buffer_push(tty);
-}
-
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -573,7 +547,9 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
ourport->rx_mode = S3C24XX_RX_PIO;
}
-static irqreturn_t s3c24xx_serial_rx_chars_dma(int irq, void *dev_id)
+static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
+
+static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
{
unsigned int utrstat, ufstat, received;
struct s3c24xx_uart_port *ourport = dev_id;
@@ -606,7 +582,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(int irq, void *dev_id)
enable_rx_pio(ourport);
}
- uart_rx_drain_fifo(ourport);
+ s3c24xx_serial_rx_drain_fifo(ourport);
if (tty) {
tty_flip_buffer_push(t);
@@ -621,16 +597,12 @@ finish:
return IRQ_HANDLED;
}
-static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
+static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
{
- struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
unsigned int ufcon, ch, flag, ufstat, uerstat;
- unsigned long flags;
int max_count = port->fifosize;
- spin_lock_irqsave(&port->lock, flags);
-
while (max_count-- > 0) {
ufcon = rd_regl(port, S3C2410_UFCON);
ufstat = rd_regl(port, S3C2410_UFSTAT);
@@ -654,9 +626,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
ufcon |= S3C2410_UFCON_RESETRX;
wr_regl(port, S3C2410_UFCON, ufcon);
rx_enabled(port) = 1;
- spin_unlock_irqrestore(&port->lock,
- flags);
- goto out;
+ return;
}
continue;
}
@@ -676,7 +646,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
dbg("break!\n");
port->icount.brk++;
if (uart_handle_break(port))
- goto ignore_char;
+ continue; /* Ignore character */
}
if (uerstat & S3C2410_UERSTAT_FRAME)
@@ -696,19 +666,25 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(int irq, void *dev_id)
}
if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
+ continue; /* Ignore character */
uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
ch, flag);
-
-ignore_char:
- continue;
}
- spin_unlock_irqrestore(&port->lock, flags);
tty_flip_buffer_push(&port->state->port);
+}
+
+static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
+{
+ struct s3c24xx_uart_port *ourport = dev_id;
+ struct uart_port *port = &ourport->port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ s3c24xx_serial_rx_drain_fifo(ourport);
+ spin_unlock_irqrestore(&port->lock, flags);
-out:
return IRQ_HANDLED;
}
@@ -718,8 +694,8 @@ static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
struct s3c24xx_uart_port *ourport = dev_id;
if (ourport->dma && ourport->dma->rx_chan)
- return s3c24xx_serial_rx_chars_dma(irq, dev_id);
- return s3c24xx_serial_rx_chars_pio(irq, dev_id);
+ return s3c24xx_serial_rx_chars_dma(dev_id);
+ return s3c24xx_serial_rx_chars_pio(dev_id);
}
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 72ffd0dcab78..edb5305b9d4d 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1321,6 +1321,9 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
const struct of_device_id *of_id =
of_match_device(sc16is7xx_dt_ids, &spi->dev);
+ if (!of_id)
+ return -ENODEV;
+
devtype = (struct sc16is7xx_devtype *)of_id->data;
} else {
const struct spi_device_id *id_entry = spi_get_device_id(spi);
@@ -1357,7 +1360,6 @@ MODULE_DEVICE_TABLE(spi, sc16is7xx_spi_id_table);
static struct spi_driver sc16is7xx_spi_uart_driver = {
.driver = {
.name = SC16IS7XX_NAME,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(sc16is7xx_dt_ids),
},
.probe = sc16is7xx_spi_probe,
@@ -1380,6 +1382,9 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
const struct of_device_id *of_id =
of_match_device(sc16is7xx_dt_ids, &i2c->dev);
+ if (!of_id)
+ return -ENODEV;
+
devtype = (struct sc16is7xx_devtype *)of_id->data;
} else {
devtype = (struct sc16is7xx_devtype *)id->driver_data;
@@ -1420,7 +1425,6 @@ static struct i2c_driver sc16is7xx_i2c_uart_driver = {
.id_table = sc16is7xx_i2c_id_table,
};
-MODULE_ALIAS("i2c:sc16is7xx");
#endif
static int __init sc16is7xx_init(void)
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index cf0133ae762d..1d6fc60ed013 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -186,7 +186,6 @@ static void set_rts(struct tegra_uart_port *tup, bool active)
tegra_uart_write(tup, mcr, UART_MCR);
tup->mcr_shadow = mcr;
}
- return;
}
static void set_dtr(struct tegra_uart_port *tup, bool active)
@@ -202,7 +201,6 @@ static void set_dtr(struct tegra_uart_port *tup, bool active)
tegra_uart_write(tup, mcr, UART_MCR);
tup->mcr_shadow = mcr;
}
- return;
}
static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl)
@@ -217,7 +215,6 @@ static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl)
dtr_enable = !!(mctrl & TIOCM_DTR);
set_dtr(tup, dtr_enable);
- return;
}
static void tegra_uart_break_ctl(struct uart_port *u, int break_ctl)
@@ -511,7 +508,6 @@ static void tegra_uart_stop_tx(struct uart_port *u)
async_tx_ack(tup->tx_dma_desc);
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
tup->tx_in_progress = 0;
- return;
}
static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
@@ -523,7 +519,6 @@ static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&tup->uport);
tegra_uart_start_next_tx(tup);
- return;
}
static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
@@ -545,8 +540,6 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
if (!uart_handle_sysrq_char(&tup->uport, ch) && tty)
tty_insert_flip_char(tty, ch, flag);
} while (1);
-
- return;
}
static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
@@ -576,13 +569,30 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
TEGRA_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
}
+static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup,
+ unsigned int residue)
+{
+ struct tty_port *port = &tup->uport.state->port;
+ struct tty_struct *tty = tty_port_tty_get(port);
+ unsigned int count;
+
+ async_tx_ack(tup->rx_dma_desc);
+ count = tup->rx_bytes_requested - residue;
+
+ /* If we are here, DMA is stopped */
+ tegra_uart_copy_rx_to_tty(tup, port, count);
+
+ tegra_uart_handle_rx_pio(tup, port);
+ if (tty) {
+ tty_flip_buffer_push(port);
+ tty_kref_put(tty);
+ }
+}
+
static void tegra_uart_rx_dma_complete(void *args)
{
struct tegra_uart_port *tup = args;
struct uart_port *u = &tup->uport;
- unsigned int count = tup->rx_bytes_requested;
- struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
- struct tty_port *port = &u->state->port;
unsigned long flags;
struct dma_tx_state state;
enum dma_status status;
@@ -596,22 +606,11 @@ static void tegra_uart_rx_dma_complete(void *args)
goto done;
}
- async_tx_ack(tup->rx_dma_desc);
-
/* Deactivate flow control to stop sender */
if (tup->rts_active)
set_rts(tup, false);
- /* If we are here, DMA is stopped */
- tegra_uart_copy_rx_to_tty(tup, port, count);
-
- tegra_uart_handle_rx_pio(tup, port);
- if (tty) {
- spin_unlock_irqrestore(&u->lock, flags);
- tty_flip_buffer_push(port);
- spin_lock_irqsave(&u->lock, flags);
- tty_kref_put(tty);
- }
+ tegra_uart_rx_buffer_push(tup, 0);
tegra_uart_start_rx_dma(tup);
/* Activate flow control to start transfer */
@@ -622,34 +621,17 @@ done:
spin_unlock_irqrestore(&u->lock, flags);
}
-static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
- unsigned long *flags)
+static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup)
{
struct dma_tx_state state;
- struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
- struct tty_port *port = &tup->uport.state->port;
- struct uart_port *u = &tup->uport;
- unsigned int count;
/* Deactivate flow control to stop sender */
if (tup->rts_active)
set_rts(tup, false);
dmaengine_terminate_all(tup->rx_dma_chan);
- dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
- async_tx_ack(tup->rx_dma_desc);
- count = tup->rx_bytes_requested - state.residue;
-
- /* If we are here, DMA is stopped */
- tegra_uart_copy_rx_to_tty(tup, port, count);
-
- tegra_uart_handle_rx_pio(tup, port);
- if (tty) {
- spin_unlock_irqrestore(&u->lock, *flags);
- tty_flip_buffer_push(port);
- spin_lock_irqsave(&u->lock, *flags);
- tty_kref_put(tty);
- }
+ dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+ tegra_uart_rx_buffer_push(tup, state.residue);
tegra_uart_start_rx_dma(tup);
if (tup->rts_active)
@@ -697,7 +679,6 @@ static void tegra_uart_handle_modem_signal_change(struct uart_port *u)
/* Will start/stop_tx accordingly */
if (msr & UART_MSR_DCTS)
uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
- return;
}
static irqreturn_t tegra_uart_isr(int irq, void *data)
@@ -714,7 +695,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
iir = tegra_uart_read(tup, UART_IIR);
if (iir & UART_IIR_NO_INT) {
if (is_rx_int) {
- tegra_uart_handle_rx_dma(tup, &flags);
+ tegra_uart_handle_rx_dma(tup);
if (tup->rx_in_progress) {
ier = tup->ier_shadow;
ier |= (UART_IER_RLSI | UART_IER_RTOIE |
@@ -769,11 +750,8 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
static void tegra_uart_stop_rx(struct uart_port *u)
{
struct tegra_uart_port *tup = to_tegra_uport(u);
- struct tty_struct *tty;
- struct tty_port *port = &u->state->port;
struct dma_tx_state state;
unsigned long ier;
- int count;
if (tup->rts_active)
set_rts(tup, false);
@@ -781,8 +759,6 @@ static void tegra_uart_stop_rx(struct uart_port *u)
if (!tup->rx_in_progress)
return;
- tty = tty_port_tty_get(&tup->uport.state->port);
-
tegra_uart_wait_sym_time(tup, 1); /* wait a character interval */
ier = tup->ier_shadow;
@@ -791,21 +767,9 @@ static void tegra_uart_stop_rx(struct uart_port *u)
tup->ier_shadow = ier;
tegra_uart_write(tup, ier, UART_IER);
tup->rx_in_progress = 0;
- if (tup->rx_dma_chan) {
- dmaengine_terminate_all(tup->rx_dma_chan);
- dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
- async_tx_ack(tup->rx_dma_desc);
- count = tup->rx_bytes_requested - state.residue;
- tegra_uart_copy_rx_to_tty(tup, port, count);
- tegra_uart_handle_rx_pio(tup, port);
- } else {
- tegra_uart_handle_rx_pio(tup, port);
- }
- if (tty) {
- tty_flip_buffer_push(port);
- tty_kref_put(tty);
- }
- return;
+ dmaengine_terminate_all(tup->rx_dma_chan);
+ dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+ tegra_uart_rx_buffer_push(tup, state.residue);
}
static void tegra_uart_hw_deinit(struct tegra_uart_port *tup)
@@ -1083,7 +1047,6 @@ static void tegra_uart_flush_buffer(struct uart_port *u)
tup->tx_bytes = 0;
if (tup->tx_dma_chan)
dmaengine_terminate_all(tup->tx_dma_chan);
- return;
}
static void tegra_uart_shutdown(struct uart_port *u)
@@ -1223,7 +1186,6 @@ static void tegra_uart_set_termios(struct uart_port *u,
tegra_uart_read(tup, UART_IER);
spin_unlock_irqrestore(&u->lock, flags);
- return;
}
static const char *tegra_uart_type(struct uart_port *u)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 603d2cc3f424..def5199ca004 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1437,7 +1437,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
clear_bit(ASYNCB_CLOSING, &port->flags);
spin_unlock_irq(&port->lock);
wake_up_interruptible(&port->open_wait);
- wake_up_interruptible(&port->close_wait);
mutex_unlock(&port->mutex);
@@ -1819,8 +1818,8 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
* @options: ptr for <options> field; NULL if not present (out)
*
* Decodes earlycon kernel command line parameters of the form
- * earlycon=<name>,io|mmio|mmio32|mmio32be,<addr>,<options>
- * console=<name>,io|mmio|mmio32|mmio32be,<addr>,<options>
+ * earlycon=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
+ * console=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
*
* The optional form
* earlycon=<name>,0x<addr>,<options>
@@ -1841,6 +1840,10 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
} else if (strncmp(p, "mmio32be,", 9) == 0) {
*iotype = UPIO_MEM32BE;
p += 9;
+ } else if (strncmp(p, "mmio32native,", 13) == 0) {
+ *iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
+ UPIO_MEM32BE : UPIO_MEM32;
+ p += 13;
} else if (strncmp(p, "io,", 3) == 0) {
*iotype = UPIO_PORT;
p += 3;
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
index 402f7fb54133..3eb57eb532f1 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.c
+++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -12,18 +12,23 @@
* but WITHOUT 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/err.h>
#include <linux/device.h>
+#include <linux/irq.h>
#include <linux/gpio/consumer.h>
#include <linux/termios.h>
+#include <linux/serial_core.h>
#include "serial_mctrl_gpio.h"
struct mctrl_gpios {
+ struct uart_port *port;
struct gpio_desc *gpio[UART_GPIO_MAX];
+ int irq[UART_GPIO_MAX];
+ unsigned int mctrl_prev;
+ bool mctrl_on;
};
static const struct {
@@ -82,7 +87,7 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
}
EXPORT_SYMBOL_GPL(mctrl_gpio_get);
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
{
struct mctrl_gpios *gpios;
enum mctrl_gpio_idx i;
@@ -110,15 +115,135 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
return gpios;
}
-EXPORT_SYMBOL_GPL(mctrl_gpio_init);
+EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto);
+
+#define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
+static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context)
+{
+ struct mctrl_gpios *gpios = context;
+ struct uart_port *port = gpios->port;
+ u32 mctrl = gpios->mctrl_prev;
+ u32 mctrl_diff;
+
+ mctrl_gpio_get(gpios, &mctrl);
+
+ mctrl_diff = mctrl ^ gpios->mctrl_prev;
+ gpios->mctrl_prev = mctrl;
+
+ if (mctrl_diff & MCTRL_ANY_DELTA && port->state != NULL) {
+ if ((mctrl_diff & mctrl) & TIOCM_RI)
+ port->icount.rng++;
+
+ if ((mctrl_diff & mctrl) & TIOCM_DSR)
+ port->icount.dsr++;
+
+ if (mctrl_diff & TIOCM_CD)
+ uart_handle_dcd_change(port, mctrl & TIOCM_CD);
+
+ if (mctrl_diff & TIOCM_CTS)
+ uart_handle_cts_change(port, mctrl & TIOCM_CTS);
+
+ wake_up_interruptible(&port->state->port.delta_msr_wait);
+ }
+
+ return IRQ_HANDLED;
+}
+
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
+{
+ struct mctrl_gpios *gpios;
+ enum mctrl_gpio_idx i;
+
+ gpios = mctrl_gpio_init_noauto(port->dev, idx);
+ if (IS_ERR(gpios))
+ return gpios;
+
+ gpios->port = port;
+
+ for (i = 0; i < UART_GPIO_MAX; ++i) {
+ int ret;
+
+ if (!gpios->gpio[i] || mctrl_gpios_desc[i].dir_out)
+ continue;
+
+ ret = gpiod_to_irq(gpios->gpio[i]);
+ if (ret <= 0) {
+ dev_err(port->dev,
+ "failed to find corresponding irq for %s (idx=%d, err=%d)\n",
+ mctrl_gpios_desc[i].name, idx, ret);
+ return ERR_PTR(ret);
+ }
+ gpios->irq[i] = ret;
+
+ /* irqs should only be enabled in .enable_ms */
+ irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN);
+
+ ret = devm_request_irq(port->dev, gpios->irq[i],
+ mctrl_gpio_irq_handle,
+ IRQ_TYPE_EDGE_BOTH, dev_name(port->dev),
+ gpios);
+ if (ret) {
+ /* alternatively implement polling */
+ dev_err(port->dev,
+ "failed to request irq for %s (idx=%d, err=%d)\n",
+ mctrl_gpios_desc[i].name, idx, ret);
+ return ERR_PTR(ret);
+ }
+ }
+
+ return gpios;
+}
void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
- for (i = 0; i < UART_GPIO_MAX; i++)
+ for (i = 0; i < UART_GPIO_MAX; i++) {
+ if (gpios->irq[i])
+ devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
+
if (gpios->gpio[i])
devm_gpiod_put(dev, gpios->gpio[i]);
+ }
devm_kfree(dev, gpios);
}
EXPORT_SYMBOL_GPL(mctrl_gpio_free);
+
+void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+{
+ enum mctrl_gpio_idx i;
+
+ /* .enable_ms may be called multiple times */
+ if (gpios->mctrl_on)
+ return;
+
+ gpios->mctrl_on = true;
+
+ /* get initial status of modem lines GPIOs */
+ mctrl_gpio_get(gpios, &gpios->mctrl_prev);
+
+ for (i = 0; i < UART_GPIO_MAX; ++i) {
+ if (!gpios->irq[i])
+ continue;
+
+ enable_irq(gpios->irq[i]);
+ }
+}
+EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms);
+
+void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+{
+ enum mctrl_gpio_idx i;
+
+ if (!gpios->mctrl_on)
+ return;
+
+ gpios->mctrl_on = false;
+
+ for (i = 0; i < UART_GPIO_MAX; ++i) {
+ if (!gpios->irq[i])
+ continue;
+
+ disable_irq(gpios->irq[i]);
+ }
+}
diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h
index 400ba0494a17..9716db283290 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.h
+++ b/drivers/tty/serial/serial_mctrl_gpio.h
@@ -22,6 +22,8 @@
#include <linux/device.h>
#include <linux/gpio/consumer.h>
+struct uart_port;
+
enum mctrl_gpio_idx {
UART_GPIO_CTS,
UART_GPIO_DSR,
@@ -60,12 +62,22 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
enum mctrl_gpio_idx gidx);
/*
+ * Request and set direction of modem control lines GPIOs and sets up irq
+ * handling.
+ * devm_* functions are used, so there's no need to call mctrl_gpio_free().
+ * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
+ * allocation error.
+ */
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx);
+
+/*
* Request and set direction of modem control lines GPIOs.
* devm_* functions are used, so there's no need to call mctrl_gpio_free().
* Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
* allocation error.
*/
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx);
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev,
+ unsigned int idx);
/*
* Free the mctrl_gpios structure.
@@ -74,6 +86,16 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx);
*/
void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios);
+/*
+ * Enable gpio interrupts to report status line changes.
+ */
+void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios);
+
+/*
+ * Disable gpio interrupts to report status line changes.
+ */
+void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios);
+
#else /* GPIOLIB */
static inline
@@ -95,7 +117,13 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
}
static inline
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
{
return ERR_PTR(-ENOSYS);
}
@@ -105,6 +133,14 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
{
}
+static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+{
+}
+
+static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+{
+}
+
#endif /* GPIOLIB */
#endif
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 1b2f894bdc9e..960e50a97558 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -84,6 +84,7 @@ struct sci_port {
unsigned int overrun_reg;
unsigned int overrun_mask;
unsigned int error_mask;
+ unsigned int error_clear;
unsigned int sampling_rate;
resource_size_t reg_size;
@@ -103,19 +104,15 @@ struct sci_port {
struct dma_chan *chan_rx;
#ifdef CONFIG_SERIAL_SH_SCI_DMA
- struct dma_async_tx_descriptor *desc_tx;
- struct dma_async_tx_descriptor *desc_rx[2];
dma_cookie_t cookie_tx;
dma_cookie_t cookie_rx[2];
dma_cookie_t active_rx;
- struct scatterlist sg_tx;
- unsigned int sg_len_tx;
+ dma_addr_t tx_dma_addr;
+ unsigned int tx_dma_len;
struct scatterlist sg_rx[2];
+ void *rx_buf[2];
size_t buf_len_rx;
- struct sh_dmae_slave param_tx;
- struct sh_dmae_slave param_rx;
struct work_struct work_tx;
- struct work_struct work_rx;
struct timer_list rx_timer;
unsigned int rx_timeout;
#endif
@@ -123,11 +120,6 @@ struct sci_port {
struct notifier_block freq_transition;
};
-/* Function prototypes */
-static void sci_start_tx(struct uart_port *port);
-static void sci_stop_tx(struct uart_port *port);
-static void sci_start_rx(struct uart_port *port);
-
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
static struct sci_port sci_ports[SCI_NPORTS];
@@ -146,7 +138,7 @@ struct plat_sci_reg {
/* Helper for invalidating specific entries of an inherited map. */
#define sci_reg_invalid { .offset = 0, .size = 0 }
-static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
+static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCIx_PROBE_REGTYPE] = {
[0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
},
@@ -399,7 +391,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
*/
static unsigned int sci_serial_in(struct uart_port *p, int offset)
{
- struct plat_sci_reg *reg = sci_getreg(p, offset);
+ const struct plat_sci_reg *reg = sci_getreg(p, offset);
if (reg->size == 8)
return ioread8(p->membase + (reg->offset << p->regshift));
@@ -413,7 +405,7 @@ static unsigned int sci_serial_in(struct uart_port *p, int offset)
static void sci_serial_out(struct uart_port *p, int offset, int value)
{
- struct plat_sci_reg *reg = sci_getreg(p, offset);
+ const struct plat_sci_reg *reg = sci_getreg(p, offset);
if (reg->size == 8)
iowrite8(value, p->membase + (reg->offset << p->regshift));
@@ -489,6 +481,105 @@ static void sci_port_disable(struct sci_port *sci_port)
pm_runtime_put_sync(sci_port->port.dev);
}
+static inline unsigned long port_rx_irq_mask(struct uart_port *port)
+{
+ /*
+ * Not all ports (such as SCIFA) will support REIE. Rather than
+ * special-casing the port type, we check the port initialization
+ * IRQ enable mask to see whether the IRQ is desired at all. If
+ * it's unset, it's logically inferred that there's no point in
+ * testing for it.
+ */
+ return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
+}
+
+static void sci_start_tx(struct uart_port *port)
+{
+ struct sci_port *s = to_sci_port(port);
+ unsigned short ctrl;
+
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+ u16 new, scr = serial_port_in(port, SCSCR);
+ if (s->chan_tx)
+ new = scr | SCSCR_TDRQE;
+ else
+ new = scr & ~SCSCR_TDRQE;
+ if (new != scr)
+ serial_port_out(port, SCSCR, new);
+ }
+
+ if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
+ dma_submit_error(s->cookie_tx)) {
+ s->cookie_tx = 0;
+ schedule_work(&s->work_tx);
+ }
+#endif
+
+ if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+ /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
+ ctrl = serial_port_in(port, SCSCR);
+ serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
+ }
+}
+
+static void sci_stop_tx(struct uart_port *port)
+{
+ unsigned short ctrl;
+
+ /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
+ ctrl = serial_port_in(port, SCSCR);
+
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+ ctrl &= ~SCSCR_TDRQE;
+
+ ctrl &= ~SCSCR_TIE;
+
+ serial_port_out(port, SCSCR, ctrl);
+}
+
+static void sci_start_rx(struct uart_port *port)
+{
+ unsigned short ctrl;
+
+ ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
+
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+ ctrl &= ~SCSCR_RDRQE;
+
+ serial_port_out(port, SCSCR, ctrl);
+}
+
+static void sci_stop_rx(struct uart_port *port)
+{
+ unsigned short ctrl;
+
+ ctrl = serial_port_in(port, SCSCR);
+
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+ ctrl &= ~SCSCR_RDRQE;
+
+ ctrl &= ~port_rx_irq_mask(port);
+
+ serial_port_out(port, SCSCR, ctrl);
+}
+
+static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
+{
+ if (port->type == PORT_SCI) {
+ /* Just store the mask */
+ serial_port_out(port, SCxSR, mask);
+ } else if (to_sci_port(port)->overrun_mask == SCIFA_ORER) {
+ /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
+ /* Only clear the status bits we want to clear */
+ serial_port_out(port, SCxSR,
+ serial_port_in(port, SCxSR) & mask);
+ } else {
+ /* Store the mask, clear parity/framing errors */
+ serial_port_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
+ }
+}
+
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
#ifdef CONFIG_CONSOLE_POLL
@@ -500,7 +591,7 @@ static int sci_poll_get_char(struct uart_port *port)
do {
status = serial_port_in(port, SCxSR);
if (status & SCxSR_ERRORS(port)) {
- serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
continue;
}
break;
@@ -513,7 +604,7 @@ static int sci_poll_get_char(struct uart_port *port)
/* Dummy read */
serial_port_in(port, SCxSR);
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
return c;
}
@@ -528,14 +619,14 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
} while (!(status & SCxSR_TDxE(port)));
serial_port_out(port, SCxTDR, c);
- serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
+ sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
}
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
static void sci_init_pins(struct uart_port *port, unsigned int cflag)
{
struct sci_port *s = to_sci_port(port);
- struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
+ const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
/*
* Use port-specific handler if provided.
@@ -565,7 +656,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
static int sci_txfill(struct uart_port *port)
{
- struct plat_sci_reg *reg;
+ const struct plat_sci_reg *reg;
reg = sci_getreg(port, SCTFDR);
if (reg->size)
@@ -585,7 +676,7 @@ static int sci_txroom(struct uart_port *port)
static int sci_rxfill(struct uart_port *port)
{
- struct plat_sci_reg *reg;
+ const struct plat_sci_reg *reg;
reg = sci_getreg(port, SCRFDR);
if (reg->size)
@@ -655,7 +746,7 @@ static void sci_transmit_chars(struct uart_port *port)
port->icount.tx++;
} while (--count > 0);
- serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
@@ -666,7 +757,7 @@ static void sci_transmit_chars(struct uart_port *port)
if (port->type != PORT_SCI) {
serial_port_in(port, SCxSR); /* Dummy read */
- serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
}
ctrl |= SCSCR_TIE;
@@ -750,7 +841,7 @@ static void sci_receive_chars(struct uart_port *port)
}
serial_port_in(port, SCxSR); /* dummy read */
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
copied += count;
port->icount.rx += count;
@@ -761,7 +852,7 @@ static void sci_receive_chars(struct uart_port *port)
tty_flip_buffer_push(tport);
} else {
serial_port_in(port, SCxSR); /* dummy read */
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
}
}
@@ -866,7 +957,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
struct sci_port *s = to_sci_port(port);
- struct plat_sci_reg *reg;
+ const struct plat_sci_reg *reg;
int copied = 0;
u16 status;
@@ -924,6 +1015,460 @@ static int sci_handle_breaks(struct uart_port *port)
return copied;
}
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+static void sci_dma_tx_complete(void *arg)
+{
+ struct sci_port *s = arg;
+ struct uart_port *port = &s->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned long flags;
+
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ xmit->tail += s->tx_dma_len;
+ xmit->tail &= UART_XMIT_SIZE - 1;
+
+ port->icount.tx += s->tx_dma_len;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (!uart_circ_empty(xmit)) {
+ s->cookie_tx = 0;
+ schedule_work(&s->work_tx);
+ } else {
+ s->cookie_tx = -EINVAL;
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+ u16 ctrl = serial_port_in(port, SCSCR);
+ serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+ }
+ }
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Locking: called with port lock held */
+static int sci_dma_rx_push(struct sci_port *s, void *buf, size_t count)
+{
+ struct uart_port *port = &s->port;
+ struct tty_port *tport = &port->state->port;
+ int copied;
+
+ copied = tty_insert_flip_string(tport, buf, count);
+ if (copied < count) {
+ dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
+ count - copied);
+ port->icount.buf_overrun++;
+ }
+
+ port->icount.rx += copied;
+
+ return copied;
+}
+
+static int sci_dma_rx_find_active(struct sci_port *s)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->cookie_rx); i++)
+ if (s->active_rx == s->cookie_rx[i])
+ return i;
+
+ dev_err(s->port.dev, "%s: Rx cookie %d not found!\n", __func__,
+ s->active_rx);
+ return -1;
+}
+
+static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
+{
+ struct dma_chan *chan = s->chan_rx;
+ struct uart_port *port = &s->port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ s->chan_rx = NULL;
+ s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
+ spin_unlock_irqrestore(&port->lock, flags);
+ dmaengine_terminate_all(chan);
+ dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0],
+ sg_dma_address(&s->sg_rx[0]));
+ dma_release_channel(chan);
+ if (enable_pio)
+ sci_start_rx(port);
+}
+
+static void sci_dma_rx_complete(void *arg)
+{
+ struct sci_port *s = arg;
+ struct dma_chan *chan = s->chan_rx;
+ struct uart_port *port = &s->port;
+ struct dma_async_tx_descriptor *desc;
+ unsigned long flags;
+ int active, count = 0;
+
+ dev_dbg(port->dev, "%s(%d) active cookie %d\n", __func__, port->line,
+ s->active_rx);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ active = sci_dma_rx_find_active(s);
+ if (active >= 0)
+ count = sci_dma_rx_push(s, s->rx_buf[active], s->buf_len_rx);
+
+ mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
+
+ if (count)
+ tty_flip_buffer_push(&port->state->port);
+
+ desc = dmaengine_prep_slave_sg(s->chan_rx, &s->sg_rx[active], 1,
+ DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc)
+ goto fail;
+
+ desc->callback = sci_dma_rx_complete;
+ desc->callback_param = s;
+ s->cookie_rx[active] = dmaengine_submit(desc);
+ if (dma_submit_error(s->cookie_rx[active]))
+ goto fail;
+
+ s->active_rx = s->cookie_rx[!active];
+
+ dma_async_issue_pending(chan);
+
+ dev_dbg(port->dev, "%s: cookie %d #%d, new active cookie %d\n",
+ __func__, s->cookie_rx[active], active, s->active_rx);
+ spin_unlock_irqrestore(&port->lock, flags);
+ return;
+
+fail:
+ spin_unlock_irqrestore(&port->lock, flags);
+ dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
+ sci_rx_dma_release(s, true);
+}
+
+static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
+{
+ struct dma_chan *chan = s->chan_tx;
+ struct uart_port *port = &s->port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ s->chan_tx = NULL;
+ s->cookie_tx = -EINVAL;
+ spin_unlock_irqrestore(&port->lock, flags);
+ dmaengine_terminate_all(chan);
+ dma_unmap_single(chan->device->dev, s->tx_dma_addr, UART_XMIT_SIZE,
+ DMA_TO_DEVICE);
+ dma_release_channel(chan);
+ if (enable_pio)
+ sci_start_tx(port);
+}
+
+static void sci_submit_rx(struct sci_port *s)
+{
+ struct dma_chan *chan = s->chan_rx;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ struct scatterlist *sg = &s->sg_rx[i];
+ struct dma_async_tx_descriptor *desc;
+
+ desc = dmaengine_prep_slave_sg(chan,
+ sg, 1, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc)
+ goto fail;
+
+ desc->callback = sci_dma_rx_complete;
+ desc->callback_param = s;
+ s->cookie_rx[i] = dmaengine_submit(desc);
+ if (dma_submit_error(s->cookie_rx[i]))
+ goto fail;
+
+ dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
+ s->cookie_rx[i], i);
+ }
+
+ s->active_rx = s->cookie_rx[0];
+
+ dma_async_issue_pending(chan);
+ return;
+
+fail:
+ if (i)
+ dmaengine_terminate_all(chan);
+ for (i = 0; i < 2; i++)
+ s->cookie_rx[i] = -EINVAL;
+ s->active_rx = -EINVAL;
+ dev_warn(s->port.dev, "Failed to re-start Rx DMA, using PIO\n");
+ sci_rx_dma_release(s, true);
+}
+
+static void work_fn_tx(struct work_struct *work)
+{
+ struct sci_port *s = container_of(work, struct sci_port, work_tx);
+ struct dma_async_tx_descriptor *desc;
+ struct dma_chan *chan = s->chan_tx;
+ struct uart_port *port = &s->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ dma_addr_t buf;
+
+ /*
+ * DMA is idle now.
+ * Port xmit buffer is already mapped, and it is one page... Just adjust
+ * offsets and lengths. Since it is a circular buffer, we have to
+ * transmit till the end, and then the rest. Take the port lock to get a
+ * consistent xmit buffer state.
+ */
+ spin_lock_irq(&port->lock);
+ buf = s->tx_dma_addr + (xmit->tail & (UART_XMIT_SIZE - 1));
+ s->tx_dma_len = min_t(unsigned int,
+ CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
+ CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
+ spin_unlock_irq(&port->lock);
+
+ desc = dmaengine_prep_slave_single(chan, buf, s->tx_dma_len,
+ DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_warn(port->dev, "Failed preparing Tx DMA descriptor\n");
+ /* switch to PIO */
+ sci_tx_dma_release(s, true);
+ return;
+ }
+
+ dma_sync_single_for_device(chan->device->dev, buf, s->tx_dma_len,
+ DMA_TO_DEVICE);
+
+ spin_lock_irq(&port->lock);
+ desc->callback = sci_dma_tx_complete;
+ desc->callback_param = s;
+ spin_unlock_irq(&port->lock);
+ s->cookie_tx = dmaengine_submit(desc);
+ if (dma_submit_error(s->cookie_tx)) {
+ dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
+ /* switch to PIO */
+ sci_tx_dma_release(s, true);
+ return;
+ }
+
+ dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
+ __func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
+
+ dma_async_issue_pending(chan);
+}
+
+static void rx_timer_fn(unsigned long arg)
+{
+ struct sci_port *s = (struct sci_port *)arg;
+ struct dma_chan *chan = s->chan_rx;
+ struct uart_port *port = &s->port;
+ struct dma_tx_state state;
+ enum dma_status status;
+ unsigned long flags;
+ unsigned int read;
+ int active, count;
+ u16 scr;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ dev_dbg(port->dev, "DMA Rx timed out\n");
+
+ active = sci_dma_rx_find_active(s);
+ if (active < 0) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ return;
+ }
+
+ status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
+ if (status == DMA_COMPLETE) {
+ dev_dbg(port->dev, "Cookie %d #%d has already completed\n",
+ s->active_rx, active);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Let packet complete handler take care of the packet */
+ return;
+ }
+
+ dmaengine_pause(chan);
+
+ /*
+ * sometimes DMA transfer doesn't stop even if it is stopped and
+ * data keeps on coming until transaction is complete so check
+ * for DMA_COMPLETE again
+ * Let packet complete handler take care of the packet
+ */
+ status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
+ if (status == DMA_COMPLETE) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ dev_dbg(port->dev, "Transaction complete after DMA engine was stopped");
+ return;
+ }
+
+ /* Handle incomplete DMA receive */
+ dmaengine_terminate_all(s->chan_rx);
+ read = sg_dma_len(&s->sg_rx[active]) - state.residue;
+ dev_dbg(port->dev, "Read %u bytes with cookie %d\n", read,
+ s->active_rx);
+
+ if (read) {
+ count = sci_dma_rx_push(s, s->rx_buf[active], read);
+ if (count)
+ tty_flip_buffer_push(&port->state->port);
+ }
+
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+ sci_submit_rx(s);
+
+ /* 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);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
+ enum dma_transfer_direction dir,
+ unsigned int id)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+ struct dma_slave_config cfg;
+ int ret;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+ (void *)(unsigned long)id, port->dev,
+ dir == DMA_MEM_TO_DEV ? "tx" : "rx");
+ if (!chan) {
+ dev_warn(port->dev,
+ "dma_request_slave_channel_compat failed\n");
+ return NULL;
+ }
+
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.direction = dir;
+ if (dir == DMA_MEM_TO_DEV) {
+ cfg.dst_addr = port->mapbase +
+ (sci_getreg(port, SCxTDR)->offset << port->regshift);
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ } else {
+ cfg.src_addr = port->mapbase +
+ (sci_getreg(port, SCxRDR)->offset << port->regshift);
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ }
+
+ ret = dmaengine_slave_config(chan, &cfg);
+ if (ret) {
+ dev_warn(port->dev, "dmaengine_slave_config failed %d\n", ret);
+ dma_release_channel(chan);
+ return NULL;
+ }
+
+ return chan;
+}
+
+static void sci_request_dma(struct uart_port *port)
+{
+ struct sci_port *s = to_sci_port(port);
+ struct dma_chan *chan;
+
+ dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
+
+ if (!port->dev->of_node &&
+ (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0))
+ return;
+
+ s->cookie_tx = -EINVAL;
+ chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV, s->cfg->dma_slave_tx);
+ dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
+ if (chan) {
+ s->chan_tx = chan;
+ /* UART circular tx buffer is an aligned page. */
+ s->tx_dma_addr = dma_map_single(chan->device->dev,
+ port->state->xmit.buf,
+ UART_XMIT_SIZE,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(chan->device->dev, s->tx_dma_addr)) {
+ dev_warn(port->dev, "Failed mapping Tx DMA descriptor\n");
+ dma_release_channel(chan);
+ s->chan_tx = NULL;
+ } else {
+ dev_dbg(port->dev, "%s: mapped %lu@%p to %pad\n",
+ __func__, UART_XMIT_SIZE,
+ port->state->xmit.buf, &s->tx_dma_addr);
+ }
+
+ INIT_WORK(&s->work_tx, work_fn_tx);
+ }
+
+ chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM, s->cfg->dma_slave_rx);
+ dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
+ if (chan) {
+ unsigned int i;
+ dma_addr_t dma;
+ void *buf;
+
+ s->chan_rx = chan;
+
+ s->buf_len_rx = 2 * max_t(size_t, 16, port->fifosize);
+ buf = dma_alloc_coherent(chan->device->dev, s->buf_len_rx * 2,
+ &dma, GFP_KERNEL);
+ if (!buf) {
+ dev_warn(port->dev,
+ "Failed to allocate Rx dma buffer, using PIO\n");
+ dma_release_channel(chan);
+ s->chan_rx = NULL;
+ return;
+ }
+
+ for (i = 0; i < 2; i++) {
+ struct scatterlist *sg = &s->sg_rx[i];
+
+ sg_init_table(sg, 1);
+ s->rx_buf[i] = buf;
+ sg_dma_address(sg) = dma;
+ sg->length = s->buf_len_rx;
+
+ buf += s->buf_len_rx;
+ dma += s->buf_len_rx;
+ }
+
+ setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
+
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+ sci_submit_rx(s);
+ }
+}
+
+static void sci_free_dma(struct uart_port *port)
+{
+ struct sci_port *s = to_sci_port(port);
+
+ if (s->chan_tx)
+ sci_tx_dma_release(s, false);
+ if (s->chan_rx)
+ sci_rx_dma_release(s, false);
+}
+#else
+static inline void sci_request_dma(struct uart_port *port)
+{
+}
+
+static inline void sci_free_dma(struct uart_port *port)
+{
+}
+#endif
+
static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
{
#ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -940,10 +1485,12 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
scr |= SCSCR_RDRQE;
} else {
scr &= ~SCSCR_RIE;
+ sci_submit_rx(s);
}
serial_port_out(port, SCSCR, scr);
/* Clear current interrupt */
- serial_port_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
+ serial_port_out(port, SCxSR,
+ ssr & ~(SCIF_DR | SCxSR_RDxF(port)));
dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
jiffies, s->rx_timeout);
mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
@@ -976,23 +1523,26 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
static irqreturn_t sci_er_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
+ struct sci_port *s = to_sci_port(port);
/* Handle errors */
if (port->type == PORT_SCI) {
if (sci_handle_errors(port)) {
/* discard character in rx buffer */
serial_port_in(port, SCxSR);
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
}
} else {
sci_handle_fifo_overrun(port);
- sci_rx_interrupt(irq, ptr);
+ if (!s->chan_rx)
+ sci_receive_chars(ptr);
}
- serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
/* Kick the transmission */
- sci_tx_interrupt(irq, ptr);
+ if (!s->chan_tx)
+ sci_tx_interrupt(irq, ptr);
return IRQ_HANDLED;
}
@@ -1003,23 +1553,11 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
/* Handle BREAKs */
sci_handle_breaks(port);
- serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
return IRQ_HANDLED;
}
-static inline unsigned long port_rx_irq_mask(struct uart_port *port)
-{
- /*
- * Not all ports (such as SCIFA) will support REIE. Rather than
- * special-casing the port type, we check the port initialization
- * IRQ enable mask to see whether the IRQ is desired at all. If
- * it's unset, it's logically inferred that there's no point in
- * testing for it.
- */
- return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
-}
-
static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
{
unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
@@ -1048,11 +1586,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
* DR flags
*/
if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
- (scr_status & SCSCR_RIE)) {
- if (port->type == PORT_SCIF || port->type == PORT_HSCIF)
- sci_handle_fifo_overrun(port);
+ (scr_status & SCSCR_RIE))
ret = sci_rx_interrupt(irq, ptr);
- }
/* Error Interrupt */
if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
@@ -1063,8 +1598,10 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
ret = sci_br_interrupt(irq, ptr);
/* Overrun Interrupt */
- if (orer_status & s->overrun_mask)
+ if (orer_status & s->overrun_mask) {
sci_handle_fifo_overrun(port);
+ ret = IRQ_HANDLED;
+ }
return ret;
}
@@ -1092,7 +1629,7 @@ static int sci_notifier(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct sci_irq_desc {
+static const struct sci_irq_desc {
const char *desc;
irq_handler_t handler;
} sci_irq_desc[] = {
@@ -1134,7 +1671,7 @@ static int sci_request_irq(struct sci_port *port)
int i, j, ret = 0;
for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
- struct sci_irq_desc *desc;
+ const struct sci_irq_desc *desc;
int irq;
if (SCIx_IRQ_IS_MUXED(port)) {
@@ -1154,11 +1691,8 @@ static int sci_request_irq(struct sci_port *port)
desc = sci_irq_desc + i;
port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
dev_name(up->dev), desc->desc);
- if (!port->irqstr[j]) {
- dev_err(up->dev, "Failed to allocate %s IRQ string\n",
- desc->desc);
+ if (!port->irqstr[j])
goto out_nomem;
- }
ret = request_irq(irq, desc->handler, up->irqflags,
port->irqstr[j], port);
@@ -1232,7 +1766,7 @@ static unsigned int sci_tx_empty(struct uart_port *port)
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
if (mctrl & TIOCM_LOOP) {
- struct plat_sci_reg *reg;
+ const struct plat_sci_reg *reg;
/*
* Standard loopback mode for SCFCR ports.
@@ -1254,356 +1788,10 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
return TIOCM_DSR | TIOCM_CAR;
}
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-static void sci_dma_tx_complete(void *arg)
-{
- struct sci_port *s = arg;
- struct uart_port *port = &s->port;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned long flags;
-
- dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
-
- spin_lock_irqsave(&port->lock, flags);
-
- xmit->tail += sg_dma_len(&s->sg_tx);
- xmit->tail &= UART_XMIT_SIZE - 1;
-
- port->icount.tx += sg_dma_len(&s->sg_tx);
-
- async_tx_ack(s->desc_tx);
- s->desc_tx = NULL;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (!uart_circ_empty(xmit)) {
- s->cookie_tx = 0;
- schedule_work(&s->work_tx);
- } else {
- s->cookie_tx = -EINVAL;
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 ctrl = serial_port_in(port, SCSCR);
- serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
- }
- }
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-/* Locking: called with port lock held */
-static int sci_dma_rx_push(struct sci_port *s, size_t count)
-{
- struct uart_port *port = &s->port;
- struct tty_port *tport = &port->state->port;
- int i, active, room;
-
- room = tty_buffer_request_room(tport, count);
-
- if (s->active_rx == s->cookie_rx[0]) {
- active = 0;
- } else if (s->active_rx == s->cookie_rx[1]) {
- active = 1;
- } else {
- dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
- return 0;
- }
-
- if (room < count)
- dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
- count - room);
- if (!room)
- return room;
-
- for (i = 0; i < room; i++)
- tty_insert_flip_char(tport, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
- TTY_NORMAL);
-
- port->icount.rx += room;
-
- return room;
-}
-
-static void sci_dma_rx_complete(void *arg)
-{
- struct sci_port *s = arg;
- struct uart_port *port = &s->port;
- unsigned long flags;
- int count;
-
- dev_dbg(port->dev, "%s(%d) active #%d\n",
- __func__, port->line, s->active_rx);
-
- spin_lock_irqsave(&port->lock, flags);
-
- count = sci_dma_rx_push(s, s->buf_len_rx);
-
- mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (count)
- tty_flip_buffer_push(&port->state->port);
-
- schedule_work(&s->work_rx);
-}
-
-static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
-{
- struct dma_chan *chan = s->chan_rx;
- struct uart_port *port = &s->port;
-
- s->chan_rx = NULL;
- s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
- dma_release_channel(chan);
- if (sg_dma_address(&s->sg_rx[0]))
- dma_free_coherent(port->dev, s->buf_len_rx * 2,
- sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
- if (enable_pio)
- sci_start_rx(port);
-}
-
-static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
-{
- struct dma_chan *chan = s->chan_tx;
- struct uart_port *port = &s->port;
-
- s->chan_tx = NULL;
- s->cookie_tx = -EINVAL;
- dma_release_channel(chan);
- if (enable_pio)
- sci_start_tx(port);
-}
-
-static void sci_submit_rx(struct sci_port *s)
-{
- struct dma_chan *chan = s->chan_rx;
- int i;
-
- for (i = 0; i < 2; i++) {
- struct scatterlist *sg = &s->sg_rx[i];
- struct dma_async_tx_descriptor *desc;
-
- desc = dmaengine_prep_slave_sg(chan,
- sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
-
- if (desc) {
- s->desc_rx[i] = desc;
- desc->callback = sci_dma_rx_complete;
- desc->callback_param = s;
- s->cookie_rx[i] = desc->tx_submit(desc);
- }
-
- if (!desc || s->cookie_rx[i] < 0) {
- if (i) {
- async_tx_ack(s->desc_rx[0]);
- s->cookie_rx[0] = -EINVAL;
- }
- if (desc) {
- async_tx_ack(desc);
- s->cookie_rx[i] = -EINVAL;
- }
- dev_warn(s->port.dev,
- "failed to re-start DMA, using PIO\n");
- sci_rx_dma_release(s, true);
- return;
- }
- dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n",
- __func__, s->cookie_rx[i], i);
- }
-
- s->active_rx = s->cookie_rx[0];
-
- dma_async_issue_pending(chan);
-}
-
-static void work_fn_rx(struct work_struct *work)
-{
- struct sci_port *s = container_of(work, struct sci_port, work_rx);
- struct uart_port *port = &s->port;
- struct dma_async_tx_descriptor *desc;
- int new;
-
- if (s->active_rx == s->cookie_rx[0]) {
- new = 0;
- } else if (s->active_rx == s->cookie_rx[1]) {
- new = 1;
- } else {
- dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
- return;
- }
- desc = s->desc_rx[new];
-
- if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) !=
- DMA_COMPLETE) {
- /* Handle incomplete DMA receive */
- struct dma_chan *chan = s->chan_rx;
- struct shdma_desc *sh_desc = container_of(desc,
- struct shdma_desc, async_tx);
- unsigned long flags;
- int count;
-
- dmaengine_terminate_all(chan);
- dev_dbg(port->dev, "Read %zu bytes with cookie %d\n",
- sh_desc->partial, sh_desc->cookie);
-
- spin_lock_irqsave(&port->lock, flags);
- count = sci_dma_rx_push(s, sh_desc->partial);
- spin_unlock_irqrestore(&port->lock, flags);
-
- if (count)
- tty_flip_buffer_push(&port->state->port);
-
- sci_submit_rx(s);
-
- return;
- }
-
- s->cookie_rx[new] = desc->tx_submit(desc);
- if (s->cookie_rx[new] < 0) {
- dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
- sci_rx_dma_release(s, true);
- return;
- }
-
- s->active_rx = s->cookie_rx[!new];
-
- dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n",
- __func__, s->cookie_rx[new], new, s->active_rx);
-}
-
-static void work_fn_tx(struct work_struct *work)
-{
- struct sci_port *s = container_of(work, struct sci_port, work_tx);
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *chan = s->chan_tx;
- struct uart_port *port = &s->port;
- struct circ_buf *xmit = &port->state->xmit;
- struct scatterlist *sg = &s->sg_tx;
-
- /*
- * DMA is idle now.
- * Port xmit buffer is already mapped, and it is one page... Just adjust
- * offsets and lengths. Since it is a circular buffer, we have to
- * transmit till the end, and then the rest. Take the port lock to get a
- * consistent xmit buffer state.
- */
- spin_lock_irq(&port->lock);
- sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
- sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
- sg->offset;
- sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
- CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
- spin_unlock_irq(&port->lock);
-
- BUG_ON(!sg_dma_len(sg));
-
- desc = dmaengine_prep_slave_sg(chan,
- sg, s->sg_len_tx, DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- /* switch to PIO */
- sci_tx_dma_release(s, true);
- return;
- }
-
- dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
-
- spin_lock_irq(&port->lock);
- s->desc_tx = desc;
- desc->callback = sci_dma_tx_complete;
- desc->callback_param = s;
- spin_unlock_irq(&port->lock);
- s->cookie_tx = desc->tx_submit(desc);
- if (s->cookie_tx < 0) {
- dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
- /* switch to PIO */
- sci_tx_dma_release(s, true);
- return;
- }
-
- dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
- __func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
-
- dma_async_issue_pending(chan);
-}
-#endif
-
-static void sci_start_tx(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
- unsigned short ctrl;
-
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 new, scr = serial_port_in(port, SCSCR);
- if (s->chan_tx)
- new = scr | SCSCR_TDRQE;
- else
- new = scr & ~SCSCR_TDRQE;
- if (new != scr)
- serial_port_out(port, SCSCR, new);
- }
-
- if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
- s->cookie_tx < 0) {
- s->cookie_tx = 0;
- schedule_work(&s->work_tx);
- }
-#endif
-
- if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
- ctrl = serial_port_in(port, SCSCR);
- serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
- }
-}
-
-static void sci_stop_tx(struct uart_port *port)
-{
- unsigned short ctrl;
-
- /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
- ctrl = serial_port_in(port, SCSCR);
-
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- ctrl &= ~SCSCR_TDRQE;
-
- ctrl &= ~SCSCR_TIE;
-
- serial_port_out(port, SCSCR, ctrl);
-}
-
-static void sci_start_rx(struct uart_port *port)
-{
- unsigned short ctrl;
-
- ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
-
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- ctrl &= ~SCSCR_RDRQE;
-
- serial_port_out(port, SCSCR, ctrl);
-}
-
-static void sci_stop_rx(struct uart_port *port)
-{
- unsigned short ctrl;
-
- ctrl = serial_port_in(port, SCSCR);
-
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- ctrl &= ~SCSCR_RDRQE;
-
- ctrl &= ~port_rx_irq_mask(port);
-
- serial_port_out(port, SCSCR, ctrl);
-}
-
static void sci_break_ctl(struct uart_port *port, int break_state)
{
struct sci_port *s = to_sci_port(port);
- struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
+ const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
unsigned short scscr, scsptr;
/* check wheter the port has SCSPTR */
@@ -1630,142 +1818,6 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
serial_port_out(port, SCSCR, scscr);
}
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-static bool filter(struct dma_chan *chan, void *slave)
-{
- struct sh_dmae_slave *param = slave;
-
- dev_dbg(chan->device->dev, "%s: slave ID %d\n",
- __func__, param->shdma_slave.slave_id);
-
- chan->private = &param->shdma_slave;
- return true;
-}
-
-static void rx_timer_fn(unsigned long arg)
-{
- struct sci_port *s = (struct sci_port *)arg;
- struct uart_port *port = &s->port;
- u16 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);
- dev_dbg(port->dev, "DMA Rx timed out\n");
- schedule_work(&s->work_rx);
-}
-
-static void sci_request_dma(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
- struct sh_dmae_slave *param;
- struct dma_chan *chan;
- dma_cap_mask_t mask;
- int nent;
-
- dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
-
- if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)
- return;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- param = &s->param_tx;
-
- /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
- param->shdma_slave.slave_id = s->cfg->dma_slave_tx;
-
- s->cookie_tx = -EINVAL;
- chan = dma_request_channel(mask, filter, param);
- dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
- if (chan) {
- s->chan_tx = chan;
- sg_init_table(&s->sg_tx, 1);
- /* UART circular tx buffer is an aligned page. */
- BUG_ON((uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
- sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
- UART_XMIT_SIZE,
- (uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
- nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
- if (!nent)
- sci_tx_dma_release(s, false);
- else
- dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n",
- __func__,
- sg_dma_len(&s->sg_tx), port->state->xmit.buf,
- &sg_dma_address(&s->sg_tx));
-
- s->sg_len_tx = nent;
-
- INIT_WORK(&s->work_tx, work_fn_tx);
- }
-
- param = &s->param_rx;
-
- /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
- param->shdma_slave.slave_id = s->cfg->dma_slave_rx;
-
- chan = dma_request_channel(mask, filter, param);
- dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
- if (chan) {
- dma_addr_t dma[2];
- void *buf[2];
- int i;
-
- s->chan_rx = chan;
-
- s->buf_len_rx = 2 * max(16, (int)port->fifosize);
- buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
- &dma[0], GFP_KERNEL);
-
- if (!buf[0]) {
- dev_warn(port->dev,
- "failed to allocate dma buffer, using PIO\n");
- sci_rx_dma_release(s, true);
- return;
- }
-
- buf[1] = buf[0] + s->buf_len_rx;
- dma[1] = dma[0] + s->buf_len_rx;
-
- for (i = 0; i < 2; i++) {
- struct scatterlist *sg = &s->sg_rx[i];
-
- sg_init_table(sg, 1);
- sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
- (uintptr_t)buf[i] & ~PAGE_MASK);
- sg_dma_address(sg) = dma[i];
- }
-
- INIT_WORK(&s->work_rx, work_fn_rx);
- setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
-
- sci_submit_rx(s);
- }
-}
-
-static void sci_free_dma(struct uart_port *port)
-{
- struct sci_port *s = to_sci_port(port);
-
- if (s->chan_tx)
- sci_tx_dma_release(s, false);
- if (s->chan_rx)
- sci_rx_dma_release(s, false);
-}
-#else
-static inline void sci_request_dma(struct uart_port *port)
-{
-}
-
-static inline void sci_free_dma(struct uart_port *port)
-{
-}
-#endif
-
static int sci_startup(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
@@ -1800,6 +1852,14 @@ static void sci_shutdown(struct uart_port *port)
sci_stop_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ if (s->chan_rx) {
+ dev_dbg(port->dev, "%s(%d) deleting rx_timer\n", __func__,
+ port->line);
+ del_timer_sync(&s->rx_timer);
+ }
+#endif
+
sci_free_dma(port);
sci_free_irq(s);
}
@@ -1892,7 +1952,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
static void sci_reset(struct uart_port *port)
{
- struct plat_sci_reg *reg;
+ const struct plat_sci_reg *reg;
unsigned int status;
do {
@@ -1910,7 +1970,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct sci_port *s = to_sci_port(port);
- struct plat_sci_reg *reg;
+ const struct plat_sci_reg *reg;
unsigned int baud, smr_val = 0, max_baud, cks = 0;
int t = -1;
unsigned int srr = 15;
@@ -1951,7 +2011,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_reset(port);
- smr_val |= serial_port_in(port, SCSMR) & 3;
+ smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
uart_update_timeout(port, termios->c_cflag, baud);
@@ -1996,13 +2056,13 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
#ifdef CONFIG_SERIAL_SH_SCI_DMA
/*
* Calculate delay for 2 DMA buffers (4 FIFO).
- * See drivers/serial/serial_core.c::uart_update_timeout(). With 10
- * bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
- * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
- * Then below we calculate 5 jiffies (20ms) for 2 DMA buffers (4 FIFO
- * sizes), but when performing a faster transfer, value obtained by
- * this formula is may not enough. Therefore, if value is smaller than
- * 20msec, this sets 20msec as timeout of DMA.
+ * See serial_core.c::uart_update_timeout().
+ * With 10 bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above
+ * function calculates 1 jiffie for the data plus 5 jiffies for the
+ * "slop(e)." Then below we calculate 5 jiffies (20ms) for 2 DMA
+ * buffers (4 FIFO sizes), but when performing a faster transfer, the
+ * value obtained by this formula is too small. Therefore, if the value
+ * is smaller than 20ms, use 20ms as the timeout value for DMA.
*/
if (s->chan_rx) {
unsigned int bits;
@@ -2187,7 +2247,6 @@ static int sci_init_single(struct platform_device *dev,
{
struct uart_port *port = &sci_port->port;
const struct resource *res;
- unsigned int sampling_rate;
unsigned int i;
int ret;
@@ -2232,37 +2291,37 @@ static int sci_init_single(struct platform_device *dev,
port->fifosize = 256;
sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCIFA_ORER;
- sampling_rate = 16;
+ sci_port->sampling_rate = 16;
break;
case PORT_HSCIF:
port->fifosize = 128;
- sampling_rate = 0;
sci_port->overrun_reg = SCLSR;
sci_port->overrun_mask = SCLSR_ORER;
+ sci_port->sampling_rate = 0;
break;
case PORT_SCIFA:
port->fifosize = 64;
sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCIFA_ORER;
- sampling_rate = 16;
+ sci_port->sampling_rate = 16;
break;
case PORT_SCIF:
port->fifosize = 16;
if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCIFA_ORER;
- sampling_rate = 16;
+ sci_port->sampling_rate = 16;
} else {
sci_port->overrun_reg = SCLSR;
sci_port->overrun_mask = SCLSR_ORER;
- sampling_rate = 32;
+ sci_port->sampling_rate = 32;
}
break;
default:
port->fifosize = 1;
sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCI_ORER;
- sampling_rate = 32;
+ sci_port->sampling_rate = 32;
break;
}
@@ -2270,8 +2329,8 @@ static int sci_init_single(struct platform_device *dev,
* match the SoC datasheet, this should be investigated. Let platform
* data override the sampling rate for now.
*/
- sci_port->sampling_rate = p->sampling_rate ? p->sampling_rate
- : sampling_rate;
+ if (p->sampling_rate)
+ sci_port->sampling_rate = p->sampling_rate;
if (!early) {
sci_port->iclk = clk_get(&dev->dev, "sci_ick");
@@ -2303,15 +2362,22 @@ static int sci_init_single(struct platform_device *dev,
/*
* Establish some sensible defaults for the error detection.
*/
- sci_port->error_mask = (p->type == PORT_SCI) ?
- SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;
+ if (p->type == PORT_SCI) {
+ sci_port->error_mask = SCI_DEFAULT_ERROR_MASK;
+ sci_port->error_clear = SCI_ERROR_CLEAR;
+ } else {
+ sci_port->error_mask = SCIF_DEFAULT_ERROR_MASK;
+ sci_port->error_clear = SCIF_ERROR_CLEAR;
+ }
/*
* Make the error mask inclusive of overrun detection, if
* supported.
*/
- if (sci_port->overrun_reg == SCxSR)
+ if (sci_port->overrun_reg == SCxSR) {
sci_port->error_mask |= sci_port->overrun_mask;
+ sci_port->error_clear &= ~sci_port->overrun_mask;
+ }
port->type = p->type;
port->flags = UPF_FIXED_PORT | p->flags;
@@ -2564,10 +2630,8 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
info = match->data;
p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
- if (!p) {
- dev_err(&pdev->dev, "failed to allocate DT config data\n");
+ if (!p)
return NULL;
- }
/* Get the line number for the aliases node. */
id = of_alias_get_id(np, "serial");
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index 3393f67b4e84..bf69bbdcc1f9 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -54,10 +54,10 @@ enum {
#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
-#define SCI_RDxF_CLEAR ~(SCI_RESERVED | SCI_RDRF)
-#define SCI_ERROR_CLEAR ~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER)
-#define SCI_TDxE_CLEAR ~(SCI_RESERVED | SCI_TEND | SCI_TDRE)
-#define SCI_BREAK_CLEAR ~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER)
+#define SCI_RDxF_CLEAR (u32)(~(SCI_RESERVED | SCI_RDRF))
+#define SCI_ERROR_CLEAR (u32)(~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER))
+#define SCI_TDxE_CLEAR (u32)(~(SCI_RESERVED | SCI_TEND | SCI_TDRE))
+#define SCI_BREAK_CLEAR (u32)(~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER))
/* SCxSR (Serial Status Register) on SCIF, SCIFA, SCIFB, HSCIF */
#define SCIF_ER BIT(7) /* Receive Error */
@@ -76,10 +76,10 @@ enum {
#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_BRK | SCIF_ER)
-#define SCIF_RDxF_CLEAR ~(SCIF_DR | SCIF_RDF)
-#define SCIF_ERROR_CLEAR ~(SCIFA_ORER | SCIF_PER | SCIF_FER | SCIF_ER)
-#define SCIF_TDxE_CLEAR ~(SCIF_TDFE)
-#define SCIF_BREAK_CLEAR ~(SCIF_PER | SCIF_FER | SCIF_BRK)
+#define SCIF_RDxF_CLEAR (u32)(~(SCIF_DR | SCIF_RDF))
+#define SCIF_ERROR_CLEAR (u32)(~(SCIF_PER | SCIF_FER | SCIF_ER))
+#define SCIF_TDxE_CLEAR (u32)(~(SCIF_TDFE))
+#define SCIF_BREAK_CLEAR (u32)(~(SCIF_PER | SCIF_FER | SCIF_BRK))
/* SCFCR (FIFO Control Register) */
#define SCFCR_MCE BIT(3) /* Modem Control Enable */
@@ -119,28 +119,11 @@ enum {
#define SCxSR_ERRORS(port) (to_sci_port(port)->error_mask)
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_R8A7740)
-
-# define SCxSR_RDxF_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_RDxF_CLEAR)
-# define SCxSR_ERROR_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_ERROR_CLEAR)
-# define SCxSR_TDxE_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_TDxE_CLEAR)
-# define SCxSR_BREAK_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_BREAK_CLEAR)
-#else
-# define SCxSR_RDxF_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR) & 0xff)
-# define SCxSR_ERROR_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_ERROR_CLEAR : SCIF_ERROR_CLEAR) & 0xff)
-# define SCxSR_TDxE_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR) & 0xff)
-# define SCxSR_BREAK_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR) & 0xff)
-#endif
-
+#define SCxSR_RDxF_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR)
+#define SCxSR_ERROR_CLEAR(port) \
+ (to_sci_port(port)->error_clear)
+#define SCxSR_TDxE_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR)
+#define SCxSR_BREAK_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR)
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 3866516c2926..9dbae01d41ce 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -782,6 +782,7 @@ static const struct of_device_id serial_ids[] = {
{.compatible = "sprd,sc9836-uart",},
{}
};
+MODULE_DEVICE_TABLE(of, serial_ids);
static struct platform_driver sprd_platform_driver = {
.probe = sprd_probe,
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index d625664ce1b5..2d78cb3627ae 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -430,7 +430,7 @@ static void asc_break_ctl(struct uart_port *port, int break_state)
*/
static int asc_startup(struct uart_port *port)
{
- if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND,
+ if (request_irq(port->irq, asc_interrupt, 0,
asc_port_name(port), port)) {
dev_err(port->dev, "cannot allocate irq.\n");
return -ENODEV;
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e3de9c6d2226..f89d1f79be18 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -322,8 +322,7 @@ static int stm32_startup(struct uart_port *port)
u32 val;
int ret;
- ret = request_irq(port->irq, stm32_interrupt, IRQF_NO_SUSPEND,
- name, port);
+ ret = request_irq(port->irq, stm32_interrupt, 0, name, port);
if (ret)
return ret;
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 2fac7123b274..6188059fd523 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3314,12 +3314,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
-EAGAIN : -ERESTARTSYS;
break;
}
-
+
dcd = tty_port_carrier_raised(&info->port);
-
- if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
- break;
-
+ if (do_clocal || dcd)
+ break;
+
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
@@ -3398,15 +3397,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
__FILE__,__LINE__,tty->driver->name, info->port.count);
- /* If port is closing, signal caller to try again */
- if (info->port.flags & ASYNC_CLOSING){
- wait_event_interruptible_tty(tty, info->port.close_wait,
- !(info->port.flags & ASYNC_CLOSING));
- retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- goto cleanup;
- }
-
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
@@ -6635,7 +6625,7 @@ static bool mgsl_get_rx_frame(struct mgsl_struct *info)
unsigned char *ptmp = info->intermediate_rxbuffer;
if ( !(status & RXSTATUS_CRC_ERROR))
- info->icount.rxok++;
+ info->icount.rxok++;
while(copy_count) {
int partial_count;
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 0ea8eee00178..6fc39fbfc275 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -672,15 +672,6 @@ static int open(struct tty_struct *tty, struct file *filp)
DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
- /* If port is closing, signal caller to try again */
- if (info->port.flags & ASYNC_CLOSING){
- wait_event_interruptible_tty(tty, info->port.close_wait,
- !(info->port.flags & ASYNC_CLOSING));
- retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- goto cleanup;
- }
-
mutex_lock(&info->port.mutex);
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
@@ -3320,9 +3311,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
cd = tty_port_carrier_raised(port);
-
- if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
- break;
+ if (do_clocal || cd)
+ break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index 08633a8139ff..fb00a06dfa4b 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -752,15 +752,6 @@ static int open(struct tty_struct *tty, struct file *filp)
printk("%s(%d):%s open(), old ref count = %d\n",
__FILE__,__LINE__,tty->driver->name, info->port.count);
- /* If port is closing, signal caller to try again */
- if (info->port.flags & ASYNC_CLOSING){
- wait_event_interruptible_tty(tty, info->port.close_wait,
- !(info->port.flags & ASYNC_CLOSING));
- retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- goto cleanup;
- }
-
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
@@ -3341,9 +3332,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
cd = tty_port_carrier_raised(port);
-
- if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
- break;
+ if (do_clocal || cd)
+ break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 95b330a9ea98..5381a728d23e 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -1003,6 +1003,10 @@ static const struct kernel_param_ops param_ops_sysrq_reset_seq = {
#define param_check_sysrq_reset_seq(name, p) \
__param_check(name, p, unsigned short)
+/*
+ * not really modular, but the easiest way to keep compat with existing
+ * bootargs behaviour is to continue using module_param here.
+ */
module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
&sysrq_reset_seq_len, 0644);
@@ -1119,4 +1123,4 @@ static int __init sysrq_init(void)
return 0;
}
-module_init(sysrq_init);
+device_initcall(sysrq_init);
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index 90ca082935f6..3d245cd3d8e6 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -265,7 +265,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
*
* Audit @data of @size from @tty, if necessary.
*/
-void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+void tty_audit_add_data(struct tty_struct *tty, const void *data,
size_t size, unsigned icanon)
{
struct tty_audit_buf *buf;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index a660ab181cca..9a479e61791a 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -403,7 +403,7 @@ void tty_schedule_flip(struct tty_port *port)
* flush_to_ldisc() sees buffer data.
*/
smp_store_release(&buf->tail->commit, buf->tail->used);
- schedule_work(&buf->work);
+ queue_work(system_unbound_wq, &buf->work);
}
EXPORT_SYMBOL(tty_schedule_flip);
@@ -587,3 +587,13 @@ void tty_buffer_set_lock_subclass(struct tty_port *port)
{
lockdep_set_subclass(&port->buf.lock, TTY_LOCK_SLAVE);
}
+
+bool tty_buffer_restart_work(struct tty_port *port)
+{
+ return queue_work(system_unbound_wq, &port->buf.work);
+}
+
+bool tty_buffer_cancel_work(struct tty_port *port)
+{
+ return cancel_work_sync(&port->buf.work);
+}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 2eefaa6e3e3a..bcc8e1e8bb72 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -390,10 +390,10 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
* Locking: ctrl_lock
*/
-int tty_check_change(struct tty_struct *tty)
+int __tty_check_change(struct tty_struct *tty, int sig)
{
unsigned long flags;
- struct pid *pgrp;
+ struct pid *pgrp, *tty_pgrp;
int ret = 0;
if (current->signal->tty != tty)
@@ -403,33 +403,35 @@ int tty_check_change(struct tty_struct *tty)
pgrp = task_pgrp(current);
spin_lock_irqsave(&tty->ctrl_lock, flags);
-
- if (!tty->pgrp) {
- printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
- goto out_unlock;
- }
- if (pgrp == tty->pgrp)
- goto out_unlock;
+ tty_pgrp = tty->pgrp;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- if (is_ignored(SIGTTOU))
- goto out_rcuunlock;
- if (is_current_pgrp_orphaned()) {
- ret = -EIO;
- goto out_rcuunlock;
+ if (tty_pgrp && pgrp != tty->pgrp) {
+ if (is_ignored(sig)) {
+ if (sig == SIGTTIN)
+ ret = -EIO;
+ } else if (is_current_pgrp_orphaned())
+ ret = -EIO;
+ else {
+ kill_pgrp(pgrp, sig, 1);
+ set_thread_flag(TIF_SIGPENDING);
+ ret = -ERESTARTSYS;
+ }
}
- kill_pgrp(pgrp, SIGTTOU, 1);
- rcu_read_unlock();
- set_thread_flag(TIF_SIGPENDING);
- ret = -ERESTARTSYS;
- return ret;
-out_unlock:
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-out_rcuunlock:
rcu_read_unlock();
+
+ if (!tty_pgrp) {
+ pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n",
+ tty_name(tty), sig);
+ }
+
return ret;
}
+int tty_check_change(struct tty_struct *tty)
+{
+ return __tty_check_change(tty, SIGTTOU);
+}
EXPORT_SYMBOL(tty_check_change);
static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
@@ -1198,11 +1200,9 @@ void tty_write_message(struct tty_struct *tty, char *msg)
if (tty) {
mutex_lock(&tty->atomic_write_lock);
tty_lock(tty);
- if (tty->ops->write && tty->count > 0) {
- tty_unlock(tty);
+ if (tty->ops->write && tty->count > 0)
tty->ops->write(tty, msg, strlen(msg));
- } else
- tty_unlock(tty);
+ tty_unlock(tty);
tty_write_unlock(tty);
}
return;
@@ -1282,18 +1282,22 @@ int tty_send_xchar(struct tty_struct *tty, char ch)
int was_stopped = tty->stopped;
if (tty->ops->send_xchar) {
+ down_read(&tty->termios_rwsem);
tty->ops->send_xchar(tty, ch);
+ up_read(&tty->termios_rwsem);
return 0;
}
if (tty_write_lock(tty, 0) < 0)
return -ERESTARTSYS;
+ down_read(&tty->termios_rwsem);
if (was_stopped)
start_tty(tty);
tty->ops->write(tty, &ch, 1);
if (was_stopped)
stop_tty(tty);
+ up_read(&tty->termios_rwsem);
tty_write_unlock(tty);
return 0;
}
@@ -1689,7 +1693,7 @@ static void release_tty(struct tty_struct *tty, int idx)
tty->port->itty = NULL;
if (tty->link)
tty->link->port->itty = NULL;
- cancel_work_sync(&tty->port->buf.work);
+ tty_buffer_cancel_work(tty->port);
tty_kref_put(tty->link);
tty_kref_put(tty);
@@ -2569,7 +2573,6 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
struct pid *pgrp;
pid_t pgrp_nr;
int retval = tty_check_change(real_tty);
- unsigned long flags;
if (retval == -EIO)
return -ENOTTY;
@@ -2592,10 +2595,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
if (session_of_pgrp(pgrp) != task_session(current))
goto out_unlock;
retval = 0;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
+ spin_lock_irq(&tty->ctrl_lock);
put_pid(real_tty->pgrp);
real_tty->pgrp = get_pid(pgrp);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_unlock_irq(&tty->ctrl_lock);
out_unlock:
rcu_read_unlock();
return retval;
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 9c5aebfe7053..1445dd39aa62 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -1147,16 +1147,12 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
spin_unlock_irq(&tty->flow_lock);
break;
case TCIOFF:
- down_read(&tty->termios_rwsem);
if (STOP_CHAR(tty) != __DISABLED_CHAR)
retval = tty_send_xchar(tty, STOP_CHAR(tty));
- up_read(&tty->termios_rwsem);
break;
case TCION:
- down_read(&tty->termios_rwsem);
if (START_CHAR(tty) != __DISABLED_CHAR)
retval = tty_send_xchar(tty, START_CHAR(tty));
- up_read(&tty->termios_rwsem);
break;
default:
return -EINVAL;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 71750cbac31f..629e3c865072 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -319,7 +319,7 @@ __tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout)
static inline void __tty_ldisc_unlock(struct tty_struct *tty)
{
- return ldsem_up_write(&tty->ldisc_sem);
+ ldsem_up_write(&tty->ldisc_sem);
}
static int __lockfunc
@@ -592,7 +592,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
/* Restart the work queue in case no characters kick it off. Safe if
already running */
- schedule_work(&tty->port->buf.work);
+ tty_buffer_restart_work(tty->port);
tty_unlock(tty);
return retval;
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 40b31835f80b..482f33f20043 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -22,7 +22,6 @@ void tty_port_init(struct tty_port *port)
memset(port, 0, sizeof(*port));
tty_buffer_init(port);
init_waitqueue_head(&port->open_wait);
- init_waitqueue_head(&port->close_wait);
init_waitqueue_head(&port->delta_msr_wait);
mutex_init(&port->mutex);
mutex_init(&port->buf_mutex);
@@ -131,7 +130,7 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf);
*/
void tty_port_destroy(struct tty_port *port)
{
- cancel_work_sync(&port->buf.work);
+ tty_buffer_cancel_work(port);
tty_buffer_free_all(port);
}
EXPORT_SYMBOL(tty_port_destroy);
@@ -363,16 +362,6 @@ int tty_port_block_til_ready(struct tty_port *port,
unsigned long flags;
DEFINE_WAIT(wait);
- /* block if port is in the process of being closed */
- if (port->flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(tty, port->close_wait,
- !(port->flags & ASYNC_CLOSING));
- if (port->flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
- }
-
/* if non-blocking mode is set we can pass directly to open unless
the port has just hung up or is in another error state */
if (tty->flags & (1 << TTY_IO_ERROR)) {
@@ -423,8 +412,7 @@ int tty_port_block_til_ready(struct tty_port *port,
* Never ask drivers if CLOCAL is set, this causes troubles
* on some hardware.
*/
- if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || tty_port_carrier_raised(port)))
+ if (do_clocal || tty_port_carrier_raised(port))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -463,10 +451,7 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
schedule_timeout_interruptible(timeout);
}
-/* Caller holds tty lock.
- * NB: may drop and reacquire tty lock (in tty_wait_until_sent_from_close())
- * so tty and tty port may have changed state (but not hung up or reopened).
- */
+/* Caller holds tty lock. */
int tty_port_close_start(struct tty_port *port,
struct tty_struct *tty, struct file *filp)
{
@@ -502,7 +487,7 @@ int tty_port_close_start(struct tty_port *port,
if (tty->flow_stopped)
tty_driver_flush_buffer(tty);
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent_from_close(tty, port->closing_wait);
+ tty_wait_until_sent(tty, port->closing_wait);
if (port->drain_delay)
tty_port_drain_delay(port, tty);
}
@@ -534,7 +519,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
wake_up_interruptible(&port->open_wait);
}
port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
- wake_up_interruptible(&port->close_wait);
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL(tty_port_close_end);
@@ -543,10 +527,6 @@ EXPORT_SYMBOL(tty_port_close_end);
* tty_port_close
*
* Caller holds tty lock
- *
- * NB: may drop and reacquire tty lock (in tty_port_close_start()->
- * tty_wait_until_sent_from_close()) so tty and tty_port may have changed
- * state (but not hung up or reopened).
*/
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 8196581f54c2..bcc1fc027311 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -524,6 +524,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
event_count = atomic_read(&idev->event);
if (event_count != listener->event_count) {
+ __set_current_state(TASK_RUNNING);
if (copy_to_user(buf, &event_count, count))
retval = -EFAULT;
else {
diff --git a/drivers/uio/uio_fsl_elbc_gpcm.c b/drivers/uio/uio_fsl_elbc_gpcm.c
index 2bcf80c159c1..b46323d9dc18 100644
--- a/drivers/uio/uio_fsl_elbc_gpcm.c
+++ b/drivers/uio/uio_fsl_elbc_gpcm.c
@@ -470,6 +470,7 @@ static const struct of_device_id uio_fsl_elbc_gpcm_match[] = {
{ .compatible = "fsl,elbc-gpcm-uio", },
{}
};
+MODULE_DEVICE_TABLE(of, uio_fsl_elbc_gpcm_match);
static struct platform_driver uio_fsl_elbc_gpcm_driver = {
.driver = {
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index d8926c6cd2a8..d5c57f1e98fd 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -27,7 +27,6 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_HWA_HCD) += host/
obj-$(CONFIG_USB_IMX21_HCD) += host/
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
-obj-$(CONFIG_USB_FUSBH200_HCD) += host/
obj-$(CONFIG_USB_FOTG210_HCD) += host/
obj-$(CONFIG_USB_MAX3421_HCD) += host/
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 5ce3f1d6a6ed..5619b8ca3bf3 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -1,6 +1,7 @@
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
+ select EXTCON
help
Say Y here if your system has a dual role high speed USB
controller based on ChipIdea silicon IP. Currently, only the
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index dcc50c878159..5a048b7b92e8 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -56,12 +56,23 @@ static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
CI_HDRC_DISABLE_HOST_STREAMING,
};
+static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = {
+ .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+ CI_HDRC_TURN_VBUS_EARLY_ON,
+};
+
+static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
+ .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
+};
+
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
{ .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
{ .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
{ .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
{ .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
+ { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
+ { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
@@ -73,6 +84,12 @@ struct ci_hdrc_imx_data {
struct imx_usbmisc_data *usbmisc_data;
bool supports_runtime_pm;
bool in_lpm;
+ /* SoC before i.mx6 (except imx23/imx28) needs three clks */
+ bool need_three_clks;
+ struct clk *clk_ipg;
+ struct clk *clk_ahb;
+ struct clk *clk_per;
+ /* --------------------------------- */
};
/* Common functions shared by usbmisc drivers */
@@ -124,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
}
/* End of common functions shared by usbmisc drivers*/
+static int imx_get_clks(struct device *dev)
+{
+ struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+ int ret = 0;
+
+ data->clk_ipg = devm_clk_get(dev, "ipg");
+ if (IS_ERR(data->clk_ipg)) {
+ /* If the platform only needs one clocks */
+ data->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(data->clk)) {
+ ret = PTR_ERR(data->clk);
+ dev_err(dev,
+ "Failed to get clks, err=%ld,%ld\n",
+ PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
+ return ret;
+ }
+ return ret;
+ }
+
+ data->clk_ahb = devm_clk_get(dev, "ahb");
+ if (IS_ERR(data->clk_ahb)) {
+ ret = PTR_ERR(data->clk_ahb);
+ dev_err(dev,
+ "Failed to get ahb clock, err=%d\n", ret);
+ return ret;
+ }
+
+ data->clk_per = devm_clk_get(dev, "per");
+ if (IS_ERR(data->clk_per)) {
+ ret = PTR_ERR(data->clk_per);
+ dev_err(dev,
+ "Failed to get per clock, err=%d\n", ret);
+ return ret;
+ }
+
+ data->need_three_clks = true;
+ return ret;
+}
+
+static int imx_prepare_enable_clks(struct device *dev)
+{
+ struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (data->need_three_clks) {
+ ret = clk_prepare_enable(data->clk_ipg);
+ if (ret) {
+ dev_err(dev,
+ "Failed to prepare/enable ipg clk, err=%d\n",
+ ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->clk_ahb);
+ if (ret) {
+ dev_err(dev,
+ "Failed to prepare/enable ahb clk, err=%d\n",
+ ret);
+ clk_disable_unprepare(data->clk_ipg);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->clk_per);
+ if (ret) {
+ dev_err(dev,
+ "Failed to prepare/enable per clk, err=%d\n",
+ ret);
+ clk_disable_unprepare(data->clk_ahb);
+ clk_disable_unprepare(data->clk_ipg);
+ return ret;
+ }
+ } else {
+ ret = clk_prepare_enable(data->clk);
+ if (ret) {
+ dev_err(dev,
+ "Failed to prepare/enable clk, err=%d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static void imx_disable_unprepare_clks(struct device *dev)
+{
+ struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+
+ if (data->need_three_clks) {
+ clk_disable_unprepare(data->clk_per);
+ clk_disable_unprepare(data->clk_ahb);
+ clk_disable_unprepare(data->clk_ipg);
+ } else {
+ clk_disable_unprepare(data->clk);
+ }
+}
static int ci_hdrc_imx_probe(struct platform_device *pdev)
{
@@ -134,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
.flags = CI_HDRC_SET_NON_ZERO_TTHA,
};
int ret;
- const struct of_device_id *of_id =
- of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
- const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
+ const struct of_device_id *of_id;
+ const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
+
+ of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
+ if (!of_id)
+ return -ENODEV;
+
+ imx_platform_flag = of_id->data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ platform_set_drvdata(pdev, data);
data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
if (IS_ERR(data->usbmisc_data))
return PTR_ERR(data->usbmisc_data);
- data->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(data->clk)) {
- dev_err(&pdev->dev,
- "Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
- return PTR_ERR(data->clk);
- }
+ ret = imx_get_clks(&pdev->dev);
+ if (ret)
+ return ret;
- ret = clk_prepare_enable(data->clk);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to prepare or enable clock, err=%d\n", ret);
+ ret = imx_prepare_enable_clks(&pdev->dev);
+ if (ret)
return ret;
- }
data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
if (IS_ERR(data->phy)) {
@@ -201,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
goto disable_device;
}
- platform_set_drvdata(pdev, data);
-
if (data->supports_runtime_pm) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -215,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device:
ci_hdrc_remove_device(data->ci_pdev);
err_clk:
- clk_disable_unprepare(data->clk);
+ imx_disable_unprepare_clks(&pdev->dev);
return ret;
}
@@ -229,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
}
ci_hdrc_remove_device(data->ci_pdev);
- clk_disable_unprepare(data->clk);
+ imx_disable_unprepare_clks(&pdev->dev);
return 0;
}
@@ -241,7 +352,7 @@ static int imx_controller_suspend(struct device *dev)
dev_dbg(dev, "at %s\n", __func__);
- clk_disable_unprepare(data->clk);
+ imx_disable_unprepare_clks(dev);
data->in_lpm = true;
return 0;
@@ -259,7 +370,7 @@ static int imx_controller_resume(struct device *dev)
return 0;
}
- ret = clk_prepare_enable(data->clk);
+ ret = imx_prepare_enable_clks(dev);
if (ret)
return ret;
@@ -274,7 +385,7 @@ static int imx_controller_resume(struct device *dev)
return 0;
clk_disable:
- clk_disable_unprepare(data->clk);
+ imx_disable_unprepare_clks(dev);
return ret;
}
diff --git a/drivers/usb/chipidea/ci_hdrc_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c
index 773d150512fa..b59195edf636 100644
--- a/drivers/usb/chipidea/ci_hdrc_pci.c
+++ b/drivers/usb/chipidea/ci_hdrc_pci.c
@@ -142,16 +142,16 @@ static const struct pci_device_id ci_hdrc_pci_id_table[] = {
.driver_data = (kernel_ulong_t)&pci_platdata,
},
{
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
+ PCI_VDEVICE(INTEL, 0x0811),
.driver_data = (kernel_ulong_t)&langwell_pci_platdata,
},
{
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
+ PCI_VDEVICE(INTEL, 0x0829),
.driver_data = (kernel_ulong_t)&penwell_pci_platdata,
},
{
/* Intel Clovertrail */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe006),
+ PCI_VDEVICE(INTEL, 0xe006),
.driver_data = (kernel_ulong_t)&penwell_pci_platdata,
},
{ 0 } /* end: all zeroes */
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 3feebf7f31f0..965d0e240dcb 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -47,6 +47,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/extcon.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -602,16 +603,52 @@ static irqreturn_t ci_irq(int irq, void *data)
return ret;
}
+static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event,
+ void *ptr)
+{
+ struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb);
+ struct ci_hdrc *ci = vbus->ci;
+
+ if (event)
+ vbus->state = true;
+ else
+ vbus->state = false;
+
+ vbus->changed = true;
+
+ ci_irq(ci->irq, ci);
+ return NOTIFY_DONE;
+}
+
+static int ci_id_notifier(struct notifier_block *nb, unsigned long event,
+ void *ptr)
+{
+ struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb);
+ struct ci_hdrc *ci = id->ci;
+
+ if (event)
+ id->state = false;
+ else
+ id->state = true;
+
+ id->changed = true;
+
+ ci_irq(ci->irq, ci);
+ return NOTIFY_DONE;
+}
+
static int ci_get_platdata(struct device *dev,
struct ci_hdrc_platform_data *platdata)
{
+ struct extcon_dev *ext_vbus, *ext_id;
+ struct ci_hdrc_cable *cable;
int ret;
if (!platdata->phy_mode)
platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
if (!platdata->dr_mode)
- platdata->dr_mode = of_usb_get_dr_mode(dev->of_node);
+ platdata->dr_mode = usb_get_dr_mode(dev);
if (platdata->dr_mode == USB_DR_MODE_UNKNOWN)
platdata->dr_mode = USB_DR_MODE_OTG;
@@ -648,9 +685,13 @@ static int ci_get_platdata(struct device *dev,
return ret;
}
- if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
+ if (usb_get_maximum_speed(dev) == USB_SPEED_FULL)
platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
+ if (of_find_property(dev->of_node, "phy-clkgate-delay-us", NULL))
+ of_property_read_u32(dev->of_node, "phy-clkgate-delay-us",
+ &platdata->phy_clkgate_delay_us);
+
platdata->itc_setting = 1;
if (of_find_property(dev->of_node, "itc-setting", NULL)) {
ret = of_property_read_u32(dev->of_node, "itc-setting",
@@ -695,9 +736,91 @@ static int ci_get_platdata(struct device *dev,
platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST;
}
+ ext_id = ERR_PTR(-ENODEV);
+ ext_vbus = ERR_PTR(-ENODEV);
+ if (of_property_read_bool(dev->of_node, "extcon")) {
+ /* Each one of them is not mandatory */
+ ext_vbus = extcon_get_edev_by_phandle(dev, 0);
+ if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
+ return PTR_ERR(ext_vbus);
+
+ ext_id = extcon_get_edev_by_phandle(dev, 1);
+ if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
+ return PTR_ERR(ext_id);
+ }
+
+ cable = &platdata->vbus_extcon;
+ cable->nb.notifier_call = ci_vbus_notifier;
+ cable->edev = ext_vbus;
+
+ if (!IS_ERR(ext_vbus)) {
+ ret = extcon_get_cable_state_(cable->edev, EXTCON_USB);
+ if (ret)
+ cable->state = true;
+ else
+ cable->state = false;
+ }
+
+ cable = &platdata->id_extcon;
+ cable->nb.notifier_call = ci_id_notifier;
+ cable->edev = ext_id;
+
+ if (!IS_ERR(ext_id)) {
+ ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST);
+ if (ret)
+ cable->state = false;
+ else
+ cable->state = true;
+ }
+ return 0;
+}
+
+static int ci_extcon_register(struct ci_hdrc *ci)
+{
+ struct ci_hdrc_cable *id, *vbus;
+ int ret;
+
+ id = &ci->platdata->id_extcon;
+ id->ci = ci;
+ if (!IS_ERR(id->edev)) {
+ ret = extcon_register_notifier(id->edev, EXTCON_USB_HOST,
+ &id->nb);
+ if (ret < 0) {
+ dev_err(ci->dev, "register ID failed\n");
+ return ret;
+ }
+ }
+
+ vbus = &ci->platdata->vbus_extcon;
+ vbus->ci = ci;
+ if (!IS_ERR(vbus->edev)) {
+ ret = extcon_register_notifier(vbus->edev, EXTCON_USB,
+ &vbus->nb);
+ if (ret < 0) {
+ extcon_unregister_notifier(id->edev, EXTCON_USB_HOST,
+ &id->nb);
+ dev_err(ci->dev, "register VBUS failed\n");
+ return ret;
+ }
+ }
+
return 0;
}
+static void ci_extcon_unregister(struct ci_hdrc *ci)
+{
+ struct ci_hdrc_cable *cable;
+
+ cable = &ci->platdata->id_extcon;
+ if (!IS_ERR(cable->edev))
+ extcon_unregister_notifier(cable->edev, EXTCON_USB_HOST,
+ &cable->nb);
+
+ cable = &ci->platdata->vbus_extcon;
+ if (!IS_ERR(cable->edev))
+ extcon_unregister_notifier(cable->edev, EXTCON_USB, &cable->nb);
+}
+
static DEFINE_IDA(ci_ida);
struct platform_device *ci_hdrc_add_device(struct device *dev,
@@ -921,6 +1044,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ret)
goto stop;
+ ret = ci_extcon_register(ci);
+ if (ret)
+ goto stop;
+
if (ci->supports_runtime_pm) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -938,6 +1065,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (!ret)
return 0;
+ ci_extcon_unregister(ci);
stop:
ci_role_destroy(ci);
deinit_phy:
@@ -957,6 +1085,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
}
dbg_remove_files(ci);
+ ci_extcon_unregister(ci);
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
ci_usb_phy_exit(ci);
@@ -996,6 +1125,9 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
{
disable_irq(ci->irq);
ci_hdrc_enter_lpm(ci, true);
+ if (ci->platdata->phy_clkgate_delay_us)
+ usleep_range(ci->platdata->phy_clkgate_delay_us,
+ ci->platdata->phy_clkgate_delay_us + 50);
usb_phy_set_suspend(ci->usb_phy, 1);
ci->in_lpm = true;
enable_irq(ci->irq);
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 080b7be3daf0..58c8485a0715 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
return -EINVAL;
pm_runtime_get_sync(ci->dev);
+ disable_irq(ci->irq);
ci_role_stop(ci);
ret = ci_role_start(ci, role);
+ enable_irq(ci->irq);
pm_runtime_put_sync(ci->dev);
return ret ? ret : count;
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index ad6c87a4653c..45f86da1d6d3 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -30,7 +30,44 @@
*/
u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
{
- return hw_read(ci, OP_OTGSC, mask);
+ struct ci_hdrc_cable *cable;
+ u32 val = hw_read(ci, OP_OTGSC, mask);
+
+ /*
+ * If using extcon framework for VBUS and/or ID signal
+ * detection overwrite OTGSC register value
+ */
+ cable = &ci->platdata->vbus_extcon;
+ if (!IS_ERR(cable->edev)) {
+ if (cable->changed)
+ val |= OTGSC_BSVIS;
+ else
+ val &= ~OTGSC_BSVIS;
+
+ cable->changed = false;
+
+ if (cable->state)
+ val |= OTGSC_BSV;
+ else
+ val &= ~OTGSC_BSV;
+ }
+
+ cable = &ci->platdata->id_extcon;
+ if (!IS_ERR(cable->edev)) {
+ if (cable->changed)
+ val |= OTGSC_IDIS;
+ else
+ val &= ~OTGSC_IDIS;
+
+ cable->changed = false;
+
+ if (cable->state)
+ val |= OTGSC_ID;
+ else
+ val &= ~OTGSC_ID;
+ }
+
+ return val;
}
/**
@@ -77,9 +114,12 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
ci_role(ci)->name, ci->roles[role]->name);
ci_role_stop(ci);
- /* wait vbus lower than OTGSC_BSV */
- hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
- CI_VBUS_STABLE_TIMEOUT_MS);
+
+ if (role == CI_ROLE_GADGET)
+ /* wait vbus lower than OTGSC_BSV */
+ hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
+ CI_VBUS_STABLE_TIMEOUT_MS);
+
ci_role_start(ci, role);
}
}
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 8223fe73ea85..391a1225b0ba 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget,
return retval;
}
+static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci)
+{
+ if (!ci_otg_is_fsm_mode(ci))
+ return;
+
+ mutex_lock(&ci->fsm.lock);
+ if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
+ ci->fsm.a_bidl_adis_tmout = 1;
+ ci_hdrc_otg_fsm_start(ci);
+ } else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
+ ci->fsm.protocol = PROTO_UNDEF;
+ ci->fsm.otg->state = OTG_STATE_UNDEFINED;
+ }
+ mutex_unlock(&ci->fsm.lock);
+}
+
/**
* ci_udc_stop: unregister a gadget driver
*/
@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags);
+ ci_udc_stop_for_otg_fsm(ci);
return 0;
}
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 5ddab30ee240..ab8b027e8cc8 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -72,6 +72,14 @@
#define VF610_OVER_CUR_DIS BIT(7)
+#define MX7D_USBNC_USB_CTRL2 0x4
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3
+#define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3)
+
struct usbmisc_ops {
/* It's called once when probe a usb device */
int (*init)(struct imx_usbmisc_data *data);
@@ -324,6 +332,55 @@ static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_imx7d_set_wakeup
+ (struct imx_usbmisc_data *data, bool enabled)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 val;
+ u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
+ MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ val = readl(usbmisc->base);
+ if (enabled) {
+ writel(val | wakeup_setting, usbmisc->base);
+ } else {
+ if (val & MX6_BM_WAKEUP_INTR)
+ dev_dbg(data->dev, "wakeup int\n");
+ writel(val & ~wakeup_setting, usbmisc->base);
+ }
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
+static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 reg;
+
+ if (data->index >= 1)
+ return -EINVAL;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ if (data->disable_oc) {
+ reg = readl(usbmisc->base);
+ writel(reg | MX6_BM_OVER_CUR_DIS, usbmisc->base);
+ }
+
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
+ writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ usbmisc_imx7d_set_wakeup(data, false);
+
+ return 0;
+}
+
static const struct usbmisc_ops imx25_usbmisc_ops = {
.init = usbmisc_imx25_init,
.post = usbmisc_imx25_post,
@@ -351,6 +408,11 @@ static const struct usbmisc_ops imx6sx_usbmisc_ops = {
.init = usbmisc_imx6sx_init,
};
+static const struct usbmisc_ops imx7d_usbmisc_ops = {
+ .init = usbmisc_imx7d_init,
+ .set_wakeup = usbmisc_imx7d_set_wakeup,
+};
+
int imx_usbmisc_init(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc;
@@ -426,6 +488,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx6sx-usbmisc",
.data = &imx6sx_usbmisc_ops,
},
+ {
+ .compatible = "fsl,imx6ul-usbmisc",
+ .data = &imx6sx_usbmisc_ops,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
@@ -434,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
{
struct resource *res;
struct imx_usbmisc *data;
- struct of_device_id *tmp_dev;
+ const struct of_device_id *of_id;
+
+ of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
+ if (!of_id)
+ return -ENODEV;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -447,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
if (IS_ERR(data->base))
return PTR_ERR(data->base);
- tmp_dev = (struct of_device_id *)
- of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
- data->ops = (const struct usbmisc_ops *)tmp_dev->data;
+ data->ops = (const struct usbmisc_ops *)of_id->data;
platform_set_drvdata(pdev, data);
return 0;
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 433bbc34a8a4..071964c7847f 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -884,11 +884,11 @@ static int usblp_wwait(struct usblp *usblp, int nonblock)
add_wait_queue(&usblp->wwait, &waita);
for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
if (mutex_lock_interruptible(&usblp->mut)) {
rc = -EINTR;
break;
}
+ set_current_state(TASK_INTERRUPTIBLE);
rc = usblp_wtest(usblp, nonblock);
mutex_unlock(&usblp->mut);
if (rc <= 0)
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 9e39286a4e5a..673d53038ed2 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -60,6 +60,24 @@ const char *usb_speed_string(enum usb_device_speed speed)
}
EXPORT_SYMBOL_GPL(usb_speed_string);
+enum usb_device_speed usb_get_maximum_speed(struct device *dev)
+{
+ const char *maximum_speed;
+ int err;
+ int i;
+
+ err = device_property_read_string(dev, "maximum-speed", &maximum_speed);
+ if (err < 0)
+ return USB_SPEED_UNKNOWN;
+
+ for (i = 0; i < ARRAY_SIZE(speed_names); i++)
+ if (strcmp(maximum_speed, speed_names[i]) == 0)
+ return i;
+
+ return USB_SPEED_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(usb_get_maximum_speed);
+
const char *usb_state_string(enum usb_device_state state)
{
static const char *const names[] = {
@@ -81,7 +99,6 @@ const char *usb_state_string(enum usb_device_state state)
}
EXPORT_SYMBOL_GPL(usb_state_string);
-#ifdef CONFIG_OF
static const char *const usb_dr_modes[] = {
[USB_DR_MODE_UNKNOWN] = "",
[USB_DR_MODE_HOST] = "host",
@@ -89,19 +106,12 @@ static const char *const usb_dr_modes[] = {
[USB_DR_MODE_OTG] = "otg",
};
-/**
- * of_usb_get_dr_mode - Get dual role mode for given device_node
- * @np: Pointer to the given device_node
- *
- * The function gets phy interface string from property 'dr_mode',
- * and returns the correspondig enum usb_dr_mode
- */
-enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
+enum usb_dr_mode usb_get_dr_mode(struct device *dev)
{
const char *dr_mode;
int err, i;
- err = of_property_read_string(np, "dr_mode", &dr_mode);
+ err = device_property_read_string(dev, "dr_mode", &dr_mode);
if (err < 0)
return USB_DR_MODE_UNKNOWN;
@@ -111,34 +121,9 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
return USB_DR_MODE_UNKNOWN;
}
-EXPORT_SYMBOL_GPL(of_usb_get_dr_mode);
-
-/**
- * of_usb_get_maximum_speed - Get maximum requested speed for a given USB
- * controller.
- * @np: Pointer to the given device_node
- *
- * The function gets the maximum speed string from property "maximum-speed",
- * and returns the corresponding enum usb_device_speed.
- */
-enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np)
-{
- const char *maximum_speed;
- int err;
- int i;
-
- err = of_property_read_string(np, "maximum-speed", &maximum_speed);
- if (err < 0)
- return USB_SPEED_UNKNOWN;
-
- for (i = 0; i < ARRAY_SIZE(speed_names); i++)
- if (strcmp(maximum_speed, speed_names[i]) == 0)
- return i;
-
- return USB_SPEED_UNKNOWN;
-}
-EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
+EXPORT_SYMBOL_GPL(usb_get_dr_mode);
+#ifdef CONFIG_OF
/**
* of_usb_host_tpl_support - to get if Targeted Peripheral List is supported
* for given targeted hosts (non-PC hosts)
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index a99c89e78126..dd280108758f 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -77,8 +77,7 @@ config USB_OTG_BLACKLIST_HUB
config USB_OTG_FSM
tristate "USB 2.0 OTG FSM implementation"
- depends on USB
- select USB_OTG
+ depends on USB && USB_OTG
select USB_PHY
help
Implements OTG Finite State Machine as specified in On-The-Go
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index b9ddf0c1ffe5..7caff020106e 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -853,6 +853,10 @@ int usb_get_bos_descriptor(struct usb_device *dev)
dev->bos->ss_cap =
(struct usb_ss_cap_descriptor *)buffer;
break;
+ case USB_SSP_CAP_TYPE:
+ dev->bos->ssp_cap =
+ (struct usb_ssp_cap_descriptor *)buffer;
+ break;
case CONTAINER_ID_TYPE:
dev->bos->ss_id =
(struct usb_ss_container_id_descriptor *)buffer;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 6b5063e7943f..56593a9a8726 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -296,6 +296,10 @@ static int usb_probe_interface(struct device *dev)
if (udev->authorized == 0) {
dev_err(&intf->dev, "Device is not authorized for usage\n");
return error;
+ } else if (intf->authorized == 0) {
+ dev_err(&intf->dev, "Interface %d is not authorized for usage\n",
+ intf->altsetting->desc.bInterfaceNumber);
+ return error;
}
id = usb_match_dynamic_id(intf, driver);
@@ -417,12 +421,10 @@ static int usb_unbind_interface(struct device *dev)
if (ep->streams == 0)
continue;
if (j == 0) {
- eps = kmalloc(USB_MAXENDPOINTS * sizeof(void *),
+ eps = kmalloc_array(USB_MAXENDPOINTS, sizeof(void *),
GFP_KERNEL);
- if (!eps) {
- dev_warn(dev, "oom, leaking streams\n");
+ if (!eps)
break;
- }
}
eps[j++] = ep;
}
@@ -508,6 +510,10 @@ int usb_driver_claim_interface(struct usb_driver *driver,
if (dev->driver)
return -EBUSY;
+ /* reject claim if interface is not authorized */
+ if (!iface->authorized)
+ return -ENODEV;
+
udev = interface_to_usbdev(iface);
dev->driver = &driver->drvwrap.driver;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 4d64e5c499e1..1c102d60cd9f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -131,7 +131,7 @@ static inline int is_root_hub(struct usb_device *udev)
/* usb 3.0 root hub device descriptor */
static const u8 usb3_rh_dev_descriptor[18] = {
0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
+ USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
0x00, 0x03, /* __le16 bcdUSB; v3.0 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
@@ -152,7 +152,7 @@ static const u8 usb3_rh_dev_descriptor[18] = {
/* usb 2.5 (wireless USB 1.0) root hub device descriptor */
static const u8 usb25_rh_dev_descriptor[18] = {
0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
+ USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
0x50, 0x02, /* __le16 bcdUSB; v2.5 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
@@ -173,7 +173,7 @@ static const u8 usb25_rh_dev_descriptor[18] = {
/* usb 2.0 root hub device descriptor */
static const u8 usb2_rh_dev_descriptor[18] = {
0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
+ USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
0x00, 0x02, /* __le16 bcdUSB; v2.0 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
@@ -196,7 +196,7 @@ static const u8 usb2_rh_dev_descriptor[18] = {
/* usb 1.1 root hub device descriptor */
static const u8 usb11_rh_dev_descriptor[18] = {
0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
+ USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
0x10, 0x01, /* __le16 bcdUSB; v1.1 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
@@ -223,7 +223,7 @@ static const u8 fs_rh_config_descriptor[] = {
/* one configuration */
0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
+ USB_DT_CONFIG, /* __u8 bDescriptorType; Configuration */
0x19, 0x00, /* __le16 wTotalLength; */
0x01, /* __u8 bNumInterfaces; (1) */
0x01, /* __u8 bConfigurationValue; */
@@ -248,7 +248,7 @@ static const u8 fs_rh_config_descriptor[] = {
/* one interface */
0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
+ USB_DT_INTERFACE, /* __u8 if_bDescriptorType; Interface */
0x00, /* __u8 if_bInterfaceNumber; */
0x00, /* __u8 if_bAlternateSetting; */
0x01, /* __u8 if_bNumEndpoints; */
@@ -259,7 +259,7 @@ static const u8 fs_rh_config_descriptor[] = {
/* one endpoint (status change endpoint) */
0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ USB_DT_ENDPOINT, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
@@ -270,7 +270,7 @@ static const u8 hs_rh_config_descriptor[] = {
/* one configuration */
0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
+ USB_DT_CONFIG, /* __u8 bDescriptorType; Configuration */
0x19, 0x00, /* __le16 wTotalLength; */
0x01, /* __u8 bNumInterfaces; (1) */
0x01, /* __u8 bConfigurationValue; */
@@ -295,7 +295,7 @@ static const u8 hs_rh_config_descriptor[] = {
/* one interface */
0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
+ USB_DT_INTERFACE, /* __u8 if_bDescriptorType; Interface */
0x00, /* __u8 if_bInterfaceNumber; */
0x00, /* __u8 if_bAlternateSetting; */
0x01, /* __u8 if_bNumEndpoints; */
@@ -306,7 +306,7 @@ static const u8 hs_rh_config_descriptor[] = {
/* one endpoint (status change endpoint) */
0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ USB_DT_ENDPOINT, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
/* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
@@ -318,7 +318,7 @@ static const u8 hs_rh_config_descriptor[] = {
static const u8 ss_rh_config_descriptor[] = {
/* one configuration */
0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
+ USB_DT_CONFIG, /* __u8 bDescriptorType; Configuration */
0x1f, 0x00, /* __le16 wTotalLength; */
0x01, /* __u8 bNumInterfaces; (1) */
0x01, /* __u8 bConfigurationValue; */
@@ -332,7 +332,7 @@ static const u8 ss_rh_config_descriptor[] = {
/* one interface */
0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
+ USB_DT_INTERFACE, /* __u8 if_bDescriptorType; Interface */
0x00, /* __u8 if_bInterfaceNumber; */
0x00, /* __u8 if_bAlternateSetting; */
0x01, /* __u8 if_bNumEndpoints; */
@@ -343,7 +343,7 @@ static const u8 ss_rh_config_descriptor[] = {
/* one endpoint (status change endpoint) */
0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ USB_DT_ENDPOINT, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
/* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
@@ -353,7 +353,8 @@ static const u8 ss_rh_config_descriptor[] = {
/* one SuperSpeed endpoint companion descriptor */
0x06, /* __u8 ss_bLength */
- 0x30, /* __u8 ss_bDescriptorType; SuperSpeed EP Companion */
+ USB_DT_SS_ENDPOINT_COMP, /* __u8 ss_bDescriptorType; SuperSpeed EP */
+ /* Companion */
0x00, /* __u8 ss_bMaxBurst; allows 1 TX between ACKs */
0x00, /* __u8 ss_bmAttributes; 1 packet per service interval */
0x02, 0x00 /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
@@ -555,6 +556,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
switch (wValue & 0xff00) {
case USB_DT_DEVICE << 8:
switch (hcd->speed) {
+ case HCD_USB31:
case HCD_USB3:
bufp = usb3_rh_dev_descriptor;
break;
@@ -576,6 +578,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
break;
case USB_DT_CONFIG << 8:
switch (hcd->speed) {
+ case HCD_USB31:
case HCD_USB3:
bufp = ss_rh_config_descriptor;
len = sizeof ss_rh_config_descriptor;
@@ -854,10 +857,10 @@ static ssize_t authorized_default_show(struct device *dev,
{
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
- struct usb_hcd *usb_hcd;
+ struct usb_hcd *hcd;
- usb_hcd = bus_to_hcd(usb_bus);
- return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
+ hcd = bus_to_hcd(usb_bus);
+ return snprintf(buf, PAGE_SIZE, "%u\n", !!HCD_DEV_AUTHORIZED(hcd));
}
static ssize_t authorized_default_store(struct device *dev,
@@ -868,12 +871,16 @@ static ssize_t authorized_default_store(struct device *dev,
unsigned val;
struct usb_device *rh_usb_dev = to_usb_device(dev);
struct usb_bus *usb_bus = rh_usb_dev->bus;
- struct usb_hcd *usb_hcd;
+ struct usb_hcd *hcd;
- usb_hcd = bus_to_hcd(usb_bus);
+ hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
- usb_hcd->authorized_default = val ? 1 : 0;
+ if (val)
+ set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+ else
+ clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+
result = size;
} else {
result = -EINVAL;
@@ -882,9 +889,53 @@ static ssize_t authorized_default_store(struct device *dev,
}
static DEVICE_ATTR_RW(authorized_default);
+/*
+ * interface_authorized_default_show - show default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ * for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_device *usb_dev = to_usb_device(dev);
+ struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+
+ return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
+}
+
+/*
+ * interface_authorized_default_store - store default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ * for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_device *usb_dev = to_usb_device(dev);
+ struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+ int rc = count;
+ bool val;
+
+ if (strtobool(buf, &val) != 0)
+ return -EINVAL;
+
+ if (val)
+ set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+ else
+ clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
+ return rc;
+}
+static DEVICE_ATTR_RW(interface_authorized_default);
+
/* Group all the USB bus attributes */
static struct attribute *usb_bus_attrs[] = {
&dev_attr_authorized_default.attr,
+ &dev_attr_interface_authorized_default.attr,
NULL,
};
@@ -2676,12 +2727,22 @@ 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)
- hcd->authorized_default = hcd->wireless ? 0 : 1;
- else
- hcd->authorized_default = authorized_default;
+ 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);
+ }
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ /* per default all interfaces are authorized */
+ set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
/* HC is in reset state, but accessible. Now do the one-time init,
* bottom up so that hcds can customize the root hubs before hub_wq
* starts talking to them. (Note, bus id is assigned early too.)
@@ -2717,6 +2778,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
rhdev->speed = USB_SPEED_WIRELESS;
break;
case HCD_USB3:
+ case HCD_USB31:
rhdev->speed = USB_SPEED_SUPER;
break;
default:
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 431839bd291f..bdeadc112d29 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1070,7 +1070,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
* for HUB_POST_RESET, but it's easier not to.
*/
if (type == HUB_INIT) {
- unsigned delay = hub_power_on_good_delay(hub);
+ delay = hub_power_on_good_delay(hub);
hub_power_on(hub, false);
INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
@@ -1404,7 +1404,6 @@ static int hub_configure(struct usb_hub *hub,
/* FIXME for USB 3.0, skip for now */
if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&
!(hub_is_superspeed(hdev))) {
- int i;
char portstr[USB_MAXCHILDREN + 1];
for (i = 0; i < maxchild; i++)
@@ -2240,39 +2239,49 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
&& udev->parent == udev->bus->root_hub) {
struct usb_otg_descriptor *desc = NULL;
struct usb_bus *bus = udev->bus;
+ unsigned port1 = udev->portnum;
/* descriptor may appear anywhere in config */
- if (__usb_get_extra_descriptor(udev->rawdescriptors[0],
- le16_to_cpu(udev->config[0].desc.wTotalLength),
- USB_DT_OTG, (void **) &desc) == 0) {
- if (desc->bmAttributes & USB_OTG_HNP) {
- unsigned port1 = udev->portnum;
+ err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
+ le16_to_cpu(udev->config[0].desc.wTotalLength),
+ USB_DT_OTG, (void **) &desc);
+ if (err || !(desc->bmAttributes & USB_OTG_HNP))
+ return 0;
- dev_info(&udev->dev,
- "Dual-Role OTG device on %sHNP port\n",
- (port1 == bus->otg_port)
- ? "" : "non-");
-
- /* enable HNP before suspend, it's simpler */
- if (port1 == bus->otg_port)
- bus->b_hnp_enable = 1;
- err = usb_control_msg(udev,
- usb_sndctrlpipe(udev, 0),
- USB_REQ_SET_FEATURE, 0,
- bus->b_hnp_enable
- ? USB_DEVICE_B_HNP_ENABLE
- : USB_DEVICE_A_ALT_HNP_SUPPORT,
- 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
- if (err < 0) {
- /* OTG MESSAGE: report errors here,
- * customize to match your product.
- */
- dev_info(&udev->dev,
- "can't set HNP mode: %d\n",
- err);
- bus->b_hnp_enable = 0;
- }
+ dev_info(&udev->dev, "Dual-Role OTG device on %sHNP port\n",
+ (port1 == bus->otg_port) ? "" : "non-");
+
+ /* enable HNP before suspend, it's simpler */
+ if (port1 == bus->otg_port) {
+ bus->b_hnp_enable = 1;
+ err = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_FEATURE, 0,
+ USB_DEVICE_B_HNP_ENABLE,
+ 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (err < 0) {
+ /*
+ * OTG MESSAGE: report errors here,
+ * customize to match your product.
+ */
+ dev_err(&udev->dev, "can't set HNP mode: %d\n",
+ err);
+ bus->b_hnp_enable = 0;
}
+ } else if (desc->bLength == sizeof
+ (struct usb_otg_descriptor)) {
+ /* Set a_alt_hnp_support for legacy otg device */
+ err = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_FEATURE, 0,
+ USB_DEVICE_A_ALT_HNP_SUPPORT,
+ 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (err < 0)
+ dev_err(&udev->dev,
+ "set a_alt_hnp_support failed: %d\n",
+ err);
}
}
#endif
@@ -4222,7 +4231,7 @@ static int hub_enable_device(struct usb_device *udev)
* but it is still necessary to lock the port.
*/
static int
-hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
int retry_counter)
{
struct usb_device *hdev = hub->hdev;
@@ -4526,7 +4535,7 @@ fail:
}
static void
-check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
+check_highspeed(struct usb_hub *hub, struct usb_device *udev, int port1)
{
struct usb_qualifier_descriptor *qual;
int status;
@@ -4534,11 +4543,11 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER)
return;
- qual = kmalloc (sizeof *qual, GFP_KERNEL);
+ qual = kmalloc(sizeof *qual, GFP_KERNEL);
if (qual == NULL)
return;
- status = usb_get_descriptor (udev, USB_DT_DEVICE_QUALIFIER, 0,
+ status = usb_get_descriptor(udev, USB_DT_DEVICE_QUALIFIER, 0,
qual, sizeof *qual);
if (status == sizeof *qual) {
dev_info(&udev->dev, "not running at top speed; "
@@ -4554,7 +4563,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
}
static unsigned
-hub_power_remaining (struct usb_hub *hub)
+hub_power_remaining(struct usb_hub *hub)
{
struct usb_device *hdev = hub->hdev;
int remaining;
@@ -4741,7 +4750,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200
&& udev->speed == USB_SPEED_FULL
&& highspeed_hubs != 0)
- check_highspeed (hub, udev, port1);
+ check_highspeed(hub, udev, port1);
/* Store the parent's children[] pointer. At this point
* udev becomes globally accessible, although presumably
@@ -5115,7 +5124,7 @@ static const struct usb_device_id hub_id_table[] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, hub_id_table);
+MODULE_DEVICE_TABLE(usb, hub_id_table);
static struct usb_driver hub_driver = {
.name = "hub",
@@ -5227,7 +5236,7 @@ static int descriptors_changed(struct usb_device *udev,
changed = 1;
break;
}
- if (memcmp (buf, udev->rawdescriptors[index], old_length)
+ if (memcmp(buf, udev->rawdescriptors[index], old_length)
!= 0) {
dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
index,
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f368d2053da5..8e641b5893ed 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1387,8 +1387,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* new altsetting.
*/
if (manual) {
- int i;
-
for (i = 0; i < alt->desc.bNumEndpoints; i++) {
epaddr = alt->endpoint[i].desc.bEndpointAddress;
pipe = __create_pipe(dev,
@@ -1555,6 +1553,44 @@ static void usb_release_interface(struct device *dev)
kfree(intf);
}
+/*
+ * usb_deauthorize_interface - deauthorize an USB interface
+ *
+ * @intf: USB interface structure
+ */
+void usb_deauthorize_interface(struct usb_interface *intf)
+{
+ struct device *dev = &intf->dev;
+
+ device_lock(dev->parent);
+
+ if (intf->authorized) {
+ device_lock(dev);
+ intf->authorized = 0;
+ device_unlock(dev);
+
+ usb_forced_unbind_intf(intf);
+ }
+
+ device_unlock(dev->parent);
+}
+
+/*
+ * usb_authorize_interface - authorize an USB interface
+ *
+ * @intf: USB interface structure
+ */
+void usb_authorize_interface(struct usb_interface *intf)
+{
+ struct device *dev = &intf->dev;
+
+ if (!intf->authorized) {
+ device_lock(dev);
+ intf->authorized = 1; /* authorize interface */
+ device_unlock(dev);
+ }
+}
+
static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
@@ -1807,6 +1843,7 @@ free_interfaces:
intfc = cp->intf_cache[i];
intf->altsetting = intfc->altsetting;
intf->num_altsetting = intfc->num_altsetting;
+ intf->authorized = !!HCD_INTF_AUTHORIZED(hcd);
kref_get(&intfc->ref);
alt = usb_altnum_to_altsetting(intf, 0);
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index cfc68c11c3f5..d9ec2de6c4cf 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -957,6 +957,41 @@ static ssize_t supports_autosuspend_show(struct device *dev,
}
static DEVICE_ATTR_RO(supports_autosuspend);
+/*
+ * interface_authorized_show - show authorization status of an USB interface
+ * 1 is authorized, 0 is deauthorized
+ */
+static ssize_t interface_authorized_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+
+ return sprintf(buf, "%u\n", intf->authorized);
+}
+
+/*
+ * interface_authorized_store - authorize or deauthorize an USB interface
+ */
+static ssize_t interface_authorized_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ bool val;
+
+ if (strtobool(buf, &val) != 0)
+ return -EINVAL;
+
+ if (val)
+ usb_authorize_interface(intf);
+ else
+ usb_deauthorize_interface(intf);
+
+ return count;
+}
+static struct device_attribute dev_attr_interface_authorized =
+ __ATTR(authorized, S_IRUGO | S_IWUSR,
+ interface_authorized_show, interface_authorized_store);
+
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
&dev_attr_bAlternateSetting.attr,
@@ -966,6 +1001,7 @@ static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceProtocol.attr,
&dev_attr_modalias.attr,
&dev_attr_supports_autosuspend.attr,
+ &dev_attr_interface_authorized.attr,
NULL,
};
static struct attribute_group intf_attr_grp = {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c9e8ee81b6b7..3d274778caaf 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -129,9 +129,8 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
list_add_tail(&urb->anchor_list, &anchor->urb_list);
urb->anchor = anchor;
- if (unlikely(anchor->poisoned)) {
+ if (unlikely(anchor->poisoned))
atomic_inc(&urb->reject);
- }
spin_unlock_irqrestore(&anchor->lock, flags);
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8d5b2f4113cd..f8bbd0b6d9fe 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -510,7 +510,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
if (root_hub) /* Root hub always ok [and always wired] */
dev->authorized = 1;
else {
- dev->authorized = usb_hcd->authorized_default;
+ dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd);
dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
}
return dev;
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 457255a3306a..05b5e17abf92 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -27,6 +27,8 @@ extern void usb_release_interface_cache(struct kref *ref);
extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
extern int usb_deauthorize_device(struct usb_device *);
extern int usb_authorize_device(struct usb_device *);
+extern void usb_deauthorize_interface(struct usb_interface *);
+extern void usb_authorize_interface(struct usb_interface *);
extern void usb_detect_quirks(struct usb_device *udev);
extern void usb_detect_interface_quirks(struct usb_device *udev);
extern int usb_remove_device(struct usb_device *udev);
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index b00fe9539184..ef73e498e98f 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -73,13 +73,13 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
/* Backup Host regs */
hr = &hsotg->hr_backup;
- hr->hcfg = readl(hsotg->regs + HCFG);
- hr->haintmsk = readl(hsotg->regs + HAINTMSK);
+ hr->hcfg = dwc2_readl(hsotg->regs + HCFG);
+ hr->haintmsk = dwc2_readl(hsotg->regs + HAINTMSK);
for (i = 0; i < hsotg->core_params->host_channels; ++i)
- hr->hcintmsk[i] = readl(hsotg->regs + HCINTMSK(i));
+ hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i));
- hr->hprt0 = readl(hsotg->regs + HPRT0);
- hr->hfir = readl(hsotg->regs + HFIR);
+ hr->hprt0 = dwc2_read_hprt0(hsotg);
+ hr->hfir = dwc2_readl(hsotg->regs + HFIR);
hr->valid = true;
return 0;
@@ -108,14 +108,15 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
}
hr->valid = false;
- writel(hr->hcfg, hsotg->regs + HCFG);
- writel(hr->haintmsk, hsotg->regs + HAINTMSK);
+ dwc2_writel(hr->hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hr->haintmsk, hsotg->regs + HAINTMSK);
for (i = 0; i < hsotg->core_params->host_channels; ++i)
- writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i));
+ dwc2_writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i));
- writel(hr->hprt0, hsotg->regs + HPRT0);
- writel(hr->hfir, hsotg->regs + HFIR);
+ dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+ hsotg->frame_number = 0;
return 0;
}
@@ -146,15 +147,15 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
/* Backup dev regs */
dr = &hsotg->dr_backup;
- dr->dcfg = readl(hsotg->regs + DCFG);
- dr->dctl = readl(hsotg->regs + DCTL);
- dr->daintmsk = readl(hsotg->regs + DAINTMSK);
- dr->diepmsk = readl(hsotg->regs + DIEPMSK);
- dr->doepmsk = readl(hsotg->regs + DOEPMSK);
+ dr->dcfg = dwc2_readl(hsotg->regs + DCFG);
+ dr->dctl = dwc2_readl(hsotg->regs + DCTL);
+ dr->daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+ dr->diepmsk = dwc2_readl(hsotg->regs + DIEPMSK);
+ dr->doepmsk = dwc2_readl(hsotg->regs + DOEPMSK);
for (i = 0; i < hsotg->num_of_eps; i++) {
/* Backup IN EPs */
- dr->diepctl[i] = readl(hsotg->regs + DIEPCTL(i));
+ dr->diepctl[i] = dwc2_readl(hsotg->regs + DIEPCTL(i));
/* Ensure DATA PID is correctly configured */
if (dr->diepctl[i] & DXEPCTL_DPID)
@@ -162,11 +163,11 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
else
dr->diepctl[i] |= DXEPCTL_SETD0PID;
- dr->dieptsiz[i] = readl(hsotg->regs + DIEPTSIZ(i));
- dr->diepdma[i] = readl(hsotg->regs + DIEPDMA(i));
+ dr->dieptsiz[i] = dwc2_readl(hsotg->regs + DIEPTSIZ(i));
+ dr->diepdma[i] = dwc2_readl(hsotg->regs + DIEPDMA(i));
/* Backup OUT EPs */
- dr->doepctl[i] = readl(hsotg->regs + DOEPCTL(i));
+ dr->doepctl[i] = dwc2_readl(hsotg->regs + DOEPCTL(i));
/* Ensure DATA PID is correctly configured */
if (dr->doepctl[i] & DXEPCTL_DPID)
@@ -174,8 +175,8 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
else
dr->doepctl[i] |= DXEPCTL_SETD0PID;
- dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i));
- dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i));
+ dr->doeptsiz[i] = dwc2_readl(hsotg->regs + DOEPTSIZ(i));
+ dr->doepdma[i] = dwc2_readl(hsotg->regs + DOEPDMA(i));
}
dr->valid = true;
return 0;
@@ -205,28 +206,28 @@ static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
}
dr->valid = false;
- writel(dr->dcfg, hsotg->regs + DCFG);
- writel(dr->dctl, hsotg->regs + DCTL);
- writel(dr->daintmsk, hsotg->regs + DAINTMSK);
- writel(dr->diepmsk, hsotg->regs + DIEPMSK);
- writel(dr->doepmsk, hsotg->regs + DOEPMSK);
+ dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
+ dwc2_writel(dr->dctl, hsotg->regs + DCTL);
+ dwc2_writel(dr->daintmsk, hsotg->regs + DAINTMSK);
+ dwc2_writel(dr->diepmsk, hsotg->regs + DIEPMSK);
+ dwc2_writel(dr->doepmsk, hsotg->regs + DOEPMSK);
for (i = 0; i < hsotg->num_of_eps; i++) {
/* Restore IN EPs */
- writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i));
- writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i));
- writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i));
+ dwc2_writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i));
+ dwc2_writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i));
+ dwc2_writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i));
/* Restore OUT EPs */
- writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i));
- writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i));
- writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i));
+ dwc2_writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i));
+ dwc2_writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i));
+ dwc2_writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i));
}
/* Set the Power-On Programming done bit */
- dctl = readl(hsotg->regs + DCTL);
+ dctl = dwc2_readl(hsotg->regs + DCTL);
dctl |= DCTL_PWRONPRGDONE;
- writel(dctl, hsotg->regs + DCTL);
+ dwc2_writel(dctl, hsotg->regs + DCTL);
return 0;
}
@@ -253,16 +254,16 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
/* Backup global regs */
gr = &hsotg->gr_backup;
- gr->gotgctl = readl(hsotg->regs + GOTGCTL);
- gr->gintmsk = readl(hsotg->regs + GINTMSK);
- gr->gahbcfg = readl(hsotg->regs + GAHBCFG);
- gr->gusbcfg = readl(hsotg->regs + GUSBCFG);
- gr->grxfsiz = readl(hsotg->regs + GRXFSIZ);
- gr->gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ);
- gr->hptxfsiz = readl(hsotg->regs + HPTXFSIZ);
- gr->gdfifocfg = readl(hsotg->regs + GDFIFOCFG);
+ gr->gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+ gr->gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+ gr->gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
+ gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+ gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
+ gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
+ gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
+ gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
for (i = 0; i < MAX_EPS_CHANNELS; i++)
- gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i));
+ gr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
gr->valid = true;
return 0;
@@ -291,17 +292,17 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
}
gr->valid = false;
- writel(0xffffffff, hsotg->regs + GINTSTS);
- writel(gr->gotgctl, hsotg->regs + GOTGCTL);
- writel(gr->gintmsk, hsotg->regs + GINTMSK);
- writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
- writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
- writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
- writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
- writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
- writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
+ dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+ dwc2_writel(gr->gotgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(gr->gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
+ dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
+ dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
+ dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
+ dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
for (i = 0; i < MAX_EPS_CHANNELS; i++)
- writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
+ dwc2_writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
return 0;
}
@@ -320,17 +321,17 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
if (!hsotg->core_params->hibernation)
return -ENOTSUPP;
- pcgcctl = readl(hsotg->regs + PCGCTL);
+ pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgcctl &= ~PCGCTL_STOPPCLK;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
- pcgcctl = readl(hsotg->regs + PCGCTL);
+ pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgcctl &= ~PCGCTL_PWRCLMP;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
- pcgcctl = readl(hsotg->regs + PCGCTL);
+ pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
udelay(100);
if (restore) {
@@ -397,19 +398,25 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
}
}
+ /*
+ * Clear any pending interrupts since dwc2 will not be able to
+ * clear them after entering hibernation.
+ */
+ dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+
/* Put the controller in low power state */
- pcgcctl = readl(hsotg->regs + PCGCTL);
+ pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgcctl |= PCGCTL_PWRCLMP;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
ndelay(20);
pcgcctl |= PCGCTL_RSTPDWNMODULE;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
ndelay(20);
pcgcctl |= PCGCTL_STOPPCLK;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
return ret;
}
@@ -425,10 +432,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
u32 intmsk;
/* Clear any pending OTG Interrupts */
- writel(0xffffffff, hsotg->regs + GOTGINT);
+ dwc2_writel(0xffffffff, hsotg->regs + GOTGINT);
/* Clear any pending interrupts */
- writel(0xffffffff, hsotg->regs + GINTSTS);
+ dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
/* Enable the interrupts in the GINTMSK */
intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT;
@@ -441,7 +448,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP |
GINTSTS_SESSREQINT;
- writel(intmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(intmsk, hsotg->regs + GINTMSK);
}
/*
@@ -464,10 +471,10 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
}
dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT;
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
}
/*
@@ -485,7 +492,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
/* Wait for AHB master IDLE state */
do {
usleep_range(20000, 40000);
- greset = readl(hsotg->regs + GRSTCTL);
+ greset = dwc2_readl(hsotg->regs + GRSTCTL);
if (++count > 50) {
dev_warn(hsotg->dev,
"%s() HANG! AHB Idle GRSTCTL=%0x\n",
@@ -497,10 +504,10 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
/* Core Soft Reset */
count = 0;
greset |= GRSTCTL_CSFTRST;
- writel(greset, hsotg->regs + GRSTCTL);
+ dwc2_writel(greset, hsotg->regs + GRSTCTL);
do {
usleep_range(20000, 40000);
- greset = readl(hsotg->regs + GRSTCTL);
+ greset = dwc2_readl(hsotg->regs + GRSTCTL);
if (++count > 50) {
dev_warn(hsotg->dev,
"%s() HANG! Soft Reset GRSTCTL=%0x\n",
@@ -510,20 +517,20 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
} while (greset & GRSTCTL_CSFTRST);
if (hsotg->dr_mode == USB_DR_MODE_HOST) {
- gusbcfg = readl(hsotg->regs + GUSBCFG);
+ gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
gusbcfg |= GUSBCFG_FORCEHOSTMODE;
- writel(gusbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
} else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
- gusbcfg = readl(hsotg->regs + GUSBCFG);
+ gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
gusbcfg |= GUSBCFG_FORCEDEVMODE;
- writel(gusbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
} else if (hsotg->dr_mode == USB_DR_MODE_OTG) {
- gusbcfg = readl(hsotg->regs + GUSBCFG);
+ gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
- writel(gusbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
}
/*
@@ -546,9 +553,9 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
*/
if (select_phy) {
dev_dbg(hsotg->dev, "FS PHY selected\n");
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg |= GUSBCFG_PHYSEL;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Reset after a PHY select */
retval = dwc2_core_reset(hsotg);
@@ -571,18 +578,18 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
/* Program GUSBCFG.OtgUtmiFsSel to I2C */
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Program GI2CCTL.I2CEn */
- i2cctl = readl(hsotg->regs + GI2CCTL);
+ i2cctl = dwc2_readl(hsotg->regs + GI2CCTL);
i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
i2cctl &= ~GI2CCTL_I2CEN;
- writel(i2cctl, hsotg->regs + GI2CCTL);
+ dwc2_writel(i2cctl, hsotg->regs + GI2CCTL);
i2cctl |= GI2CCTL_I2CEN;
- writel(i2cctl, hsotg->regs + GI2CCTL);
+ dwc2_writel(i2cctl, hsotg->regs + GI2CCTL);
}
return retval;
@@ -596,7 +603,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
if (!select_phy)
return 0;
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
/*
* HS PHY parameters. These parameters are preserved during soft reset
@@ -624,7 +631,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
break;
}
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Reset after setting the PHY parameters */
retval = dwc2_core_reset(hsotg);
@@ -659,15 +666,15 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->core_params->ulpi_fs_ls > 0) {
dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg |= GUSBCFG_ULPI_FS_LS;
usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
} else {
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg &= ~GUSBCFG_ULPI_FS_LS;
usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
}
return retval;
@@ -675,7 +682,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
{
- u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+ u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
switch (hsotg->hw_params.arch) {
case GHWCFG2_EXT_DMA_ARCH:
@@ -714,7 +721,7 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
if (hsotg->core_params->dma_enable > 0)
ahbcfg |= GAHBCFG_DMA_EN;
- writel(ahbcfg, hsotg->regs + GAHBCFG);
+ dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
return 0;
}
@@ -723,7 +730,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
{
u32 usbcfg;
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP);
switch (hsotg->hw_params.op_mode) {
@@ -751,7 +758,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
break;
}
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
}
/**
@@ -769,7 +776,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
/* Set ULPI External VBUS bit if needed */
usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV;
@@ -782,7 +789,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
if (hsotg->core_params->ts_dline > 0)
usbcfg |= GUSBCFG_TERMSELDLPULSE;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Reset the Controller */
retval = dwc2_core_reset(hsotg);
@@ -808,11 +815,11 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
dwc2_gusbcfg_init(hsotg);
/* Program the GOTGCTL register */
- otgctl = readl(hsotg->regs + GOTGCTL);
+ otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
otgctl &= ~GOTGCTL_OTGVER;
if (hsotg->core_params->otg_ver > 0)
otgctl |= GOTGCTL_OTGVER;
- writel(otgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->core_params->otg_ver);
/* Clear the SRP success bit for FS-I2c */
@@ -848,16 +855,16 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "%s()\n", __func__);
/* Disable all interrupts */
- writel(0, hsotg->regs + GINTMSK);
- writel(0, hsotg->regs + HAINTMSK);
+ dwc2_writel(0, hsotg->regs + GINTMSK);
+ dwc2_writel(0, hsotg->regs + HAINTMSK);
/* Enable the common interrupts */
dwc2_enable_common_interrupts(hsotg);
/* Enable host mode interrupts without disturbing common interrupts */
- intmsk = readl(hsotg->regs + GINTMSK);
+ intmsk = dwc2_readl(hsotg->regs + GINTMSK);
intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
- writel(intmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(intmsk, hsotg->regs + GINTMSK);
}
/**
@@ -867,12 +874,12 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
*/
void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
{
- u32 intmsk = readl(hsotg->regs + GINTMSK);
+ u32 intmsk = dwc2_readl(hsotg->regs + GINTMSK);
/* Disable host mode interrupts without disturbing common interrupts */
intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT |
- GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
- writel(intmsk, hsotg->regs + GINTMSK);
+ GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT);
+ dwc2_writel(intmsk, hsotg->regs + GINTMSK);
}
/*
@@ -952,36 +959,37 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
dwc2_calculate_dynamic_fifo(hsotg);
/* Rx FIFO */
- grxfsiz = readl(hsotg->regs + GRXFSIZ);
+ grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz);
grxfsiz &= ~GRXFSIZ_DEPTH_MASK;
grxfsiz |= params->host_rx_fifo_size <<
GRXFSIZ_DEPTH_SHIFT & GRXFSIZ_DEPTH_MASK;
- writel(grxfsiz, hsotg->regs + GRXFSIZ);
- dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", readl(hsotg->regs + GRXFSIZ));
+ dwc2_writel(grxfsiz, hsotg->regs + GRXFSIZ);
+ dev_dbg(hsotg->dev, "new grxfsiz=%08x\n",
+ dwc2_readl(hsotg->regs + GRXFSIZ));
/* Non-periodic Tx FIFO */
dev_dbg(hsotg->dev, "initial gnptxfsiz=%08x\n",
- readl(hsotg->regs + GNPTXFSIZ));
+ dwc2_readl(hsotg->regs + GNPTXFSIZ));
nptxfsiz = params->host_nperio_tx_fifo_size <<
FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
nptxfsiz |= params->host_rx_fifo_size <<
FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
- writel(nptxfsiz, hsotg->regs + GNPTXFSIZ);
+ dwc2_writel(nptxfsiz, hsotg->regs + GNPTXFSIZ);
dev_dbg(hsotg->dev, "new gnptxfsiz=%08x\n",
- readl(hsotg->regs + GNPTXFSIZ));
+ dwc2_readl(hsotg->regs + GNPTXFSIZ));
/* Periodic Tx FIFO */
dev_dbg(hsotg->dev, "initial hptxfsiz=%08x\n",
- readl(hsotg->regs + HPTXFSIZ));
+ dwc2_readl(hsotg->regs + HPTXFSIZ));
hptxfsiz = params->host_perio_tx_fifo_size <<
FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
hptxfsiz |= (params->host_rx_fifo_size +
params->host_nperio_tx_fifo_size) <<
FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
- writel(hptxfsiz, hsotg->regs + HPTXFSIZ);
+ dwc2_writel(hptxfsiz, hsotg->regs + HPTXFSIZ);
dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n",
- readl(hsotg->regs + HPTXFSIZ));
+ dwc2_readl(hsotg->regs + HPTXFSIZ));
if (hsotg->core_params->en_multiple_tx_fifo > 0 &&
hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) {
@@ -989,14 +997,14 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
* Global DFIFOCFG calculation for Host mode -
* include RxFIFO, NPTXFIFO and HPTXFIFO
*/
- dfifocfg = readl(hsotg->regs + GDFIFOCFG);
+ dfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK;
dfifocfg |= (params->host_rx_fifo_size +
params->host_nperio_tx_fifo_size +
params->host_perio_tx_fifo_size) <<
GDFIFOCFG_EPINFOBASE_SHIFT &
GDFIFOCFG_EPINFOBASE_MASK;
- writel(dfifocfg, hsotg->regs + GDFIFOCFG);
+ dwc2_writel(dfifocfg, hsotg->regs + GDFIFOCFG);
}
}
@@ -1017,14 +1025,14 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
/* Restart the Phy Clock */
- writel(0, hsotg->regs + PCGCTL);
+ dwc2_writel(0, hsotg->regs + PCGCTL);
/* Initialize Host Configuration Register */
dwc2_init_fs_ls_pclk_sel(hsotg);
if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL) {
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_FSLSSUPP;
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
}
/*
@@ -1033,9 +1041,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
* and its value must not be changed during runtime.
*/
if (hsotg->core_params->reload_ctl > 0) {
- hfir = readl(hsotg->regs + HFIR);
+ hfir = dwc2_readl(hsotg->regs + HFIR);
hfir |= HFIR_RLDCTRL;
- writel(hfir, hsotg->regs + HFIR);
+ dwc2_writel(hfir, hsotg->regs + HFIR);
}
if (hsotg->core_params->dma_desc_enable > 0) {
@@ -1051,9 +1059,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
"falling back to buffer DMA mode.\n");
hsotg->core_params->dma_desc_enable = 0;
} else {
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_DESCDMA;
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
}
}
@@ -1062,18 +1070,18 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
/* TODO - check this */
/* Clear Host Set HNP Enable in the OTG Control Register */
- otgctl = readl(hsotg->regs + GOTGCTL);
+ otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
otgctl &= ~GOTGCTL_HSTSETHNPEN;
- writel(otgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
/* Make sure the FIFOs are flushed */
dwc2_flush_tx_fifo(hsotg, 0x10 /* all TX FIFOs */);
dwc2_flush_rx_fifo(hsotg);
/* Clear Host Set HNP Enable in the OTG Control Register */
- otgctl = readl(hsotg->regs + GOTGCTL);
+ otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
otgctl &= ~GOTGCTL_HSTSETHNPEN;
- writel(otgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
if (hsotg->core_params->dma_desc_enable <= 0) {
int num_channels, i;
@@ -1082,25 +1090,25 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
/* Flush out any leftover queued requests */
num_channels = hsotg->core_params->host_channels;
for (i = 0; i < num_channels; i++) {
- hcchar = readl(hsotg->regs + HCCHAR(i));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
hcchar &= ~HCCHAR_CHENA;
hcchar |= HCCHAR_CHDIS;
hcchar &= ~HCCHAR_EPDIR;
- writel(hcchar, hsotg->regs + HCCHAR(i));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
}
/* Halt all channels to put them into a known state */
for (i = 0; i < num_channels; i++) {
int count = 0;
- hcchar = readl(hsotg->regs + HCCHAR(i));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS;
hcchar &= ~HCCHAR_EPDIR;
- writel(hcchar, hsotg->regs + HCCHAR(i));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
dev_dbg(hsotg->dev, "%s: Halt channel %d\n",
__func__, i);
do {
- hcchar = readl(hsotg->regs + HCCHAR(i));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
if (++count > 1000) {
dev_err(hsotg->dev,
"Unable to clear enable on channel %d\n",
@@ -1121,7 +1129,7 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
!!(hprt0 & HPRT0_PWR));
if (!(hprt0 & HPRT0_PWR)) {
hprt0 |= HPRT0_PWR;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
}
}
@@ -1201,7 +1209,7 @@ static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg,
break;
}
- writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+ dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk);
}
@@ -1238,7 +1246,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg,
}
}
- writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+ dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk);
}
@@ -1259,16 +1267,16 @@ static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg,
}
/* Enable the top level host channel interrupt */
- intmsk = readl(hsotg->regs + HAINTMSK);
+ intmsk = dwc2_readl(hsotg->regs + HAINTMSK);
intmsk |= 1 << chan->hc_num;
- writel(intmsk, hsotg->regs + HAINTMSK);
+ dwc2_writel(intmsk, hsotg->regs + HAINTMSK);
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "set HAINTMSK to %08x\n", intmsk);
/* Make sure host channel interrupts are enabled */
- intmsk = readl(hsotg->regs + GINTMSK);
+ intmsk = dwc2_readl(hsotg->regs + GINTMSK);
intmsk |= GINTSTS_HCHINT;
- writel(intmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(intmsk, hsotg->regs + GINTMSK);
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "set GINTMSK to %08x\n", intmsk);
}
@@ -1297,7 +1305,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
/* Clear old interrupt conditions for this host channel */
hcintmsk = 0xffffffff;
hcintmsk &= ~HCINTMSK_RESERVED14_31;
- writel(hcintmsk, hsotg->regs + HCINT(hc_num));
+ dwc2_writel(hcintmsk, hsotg->regs + HCINT(hc_num));
/* Enable channel interrupts required for this transfer */
dwc2_hc_enable_ints(hsotg, chan);
@@ -1314,7 +1322,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
hcchar |= HCCHAR_LSPDDEV;
hcchar |= chan->ep_type << HCCHAR_EPTYPE_SHIFT & HCCHAR_EPTYPE_MASK;
hcchar |= chan->max_packet << HCCHAR_MPS_SHIFT & HCCHAR_MPS_MASK;
- writel(hcchar, hsotg->regs + HCCHAR(hc_num));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(hc_num));
if (dbg_hc(chan)) {
dev_vdbg(hsotg->dev, "set HCCHAR(%d) to %08x\n",
hc_num, hcchar);
@@ -1368,7 +1376,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
}
}
- writel(hcsplt, hsotg->regs + HCSPLT(hc_num));
+ dwc2_writel(hcsplt, hsotg->regs + HCSPLT(hc_num));
}
/**
@@ -1420,14 +1428,14 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
u32 hcintmsk = HCINTMSK_CHHLTD;
dev_vdbg(hsotg->dev, "dequeue/error\n");
- writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+ dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
/*
* Make sure no other interrupts besides halt are currently
* pending. Handling another interrupt could cause a crash due
* to the QTD and QH state.
*/
- writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num));
+ dwc2_writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num));
/*
* Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
@@ -1436,7 +1444,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
*/
chan->halt_status = halt_status;
- hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
if (!(hcchar & HCCHAR_CHENA)) {
/*
* The channel is either already halted or it hasn't
@@ -1464,7 +1472,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
return;
}
- hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
/* No need to set the bit in DDMA for disabling the channel */
/* TODO check it everywhere channel is disabled */
@@ -1487,7 +1495,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL ||
chan->ep_type == USB_ENDPOINT_XFER_BULK) {
dev_vdbg(hsotg->dev, "control/bulk\n");
- nptxsts = readl(hsotg->regs + GNPTXSTS);
+ nptxsts = dwc2_readl(hsotg->regs + GNPTXSTS);
if ((nptxsts & TXSTS_QSPCAVAIL_MASK) == 0) {
dev_vdbg(hsotg->dev, "Disabling channel\n");
hcchar &= ~HCCHAR_CHENA;
@@ -1495,7 +1503,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
} else {
if (dbg_perio())
dev_vdbg(hsotg->dev, "isoc/intr\n");
- hptxsts = readl(hsotg->regs + HPTXSTS);
+ hptxsts = dwc2_readl(hsotg->regs + HPTXSTS);
if ((hptxsts & TXSTS_QSPCAVAIL_MASK) == 0 ||
hsotg->queuing_high_bandwidth) {
if (dbg_perio())
@@ -1508,7 +1516,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
dev_vdbg(hsotg->dev, "DMA enabled\n");
}
- writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
chan->halt_status = halt_status;
if (hcchar & HCCHAR_CHENA) {
@@ -1555,10 +1563,10 @@ void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
* Clear channel interrupt enables and any unhandled channel interrupt
* conditions
*/
- writel(0, hsotg->regs + HCINTMSK(chan->hc_num));
+ dwc2_writel(0, hsotg->regs + HCINTMSK(chan->hc_num));
hcintmsk = 0xffffffff;
hcintmsk &= ~HCINTMSK_RESERVED14_31;
- writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num));
+ dwc2_writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num));
}
/**
@@ -1644,13 +1652,13 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
if (((unsigned long)data_buf & 0x3) == 0) {
/* xfer_buf is DWORD aligned */
for (i = 0; i < dword_count; i++, data_buf++)
- writel(*data_buf, data_fifo);
+ dwc2_writel(*data_buf, data_fifo);
} else {
/* xfer_buf is not DWORD aligned */
for (i = 0; i < dword_count; i++, data_buf++) {
u32 data = data_buf[0] | data_buf[1] << 8 |
data_buf[2] << 16 | data_buf[3] << 24;
- writel(data, data_fifo);
+ dwc2_writel(data, data_fifo);
}
}
@@ -1803,7 +1811,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
hctsiz |= num_packets << TSIZ_PKTCNT_SHIFT & TSIZ_PKTCNT_MASK;
hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT &
TSIZ_SC_MC_PID_MASK;
- writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+ dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
if (dbg_hc(chan)) {
dev_vdbg(hsotg->dev, "Wrote %08x to HCTSIZ(%d)\n",
hctsiz, chan->hc_num);
@@ -1831,7 +1839,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
} else {
dma_addr = chan->xfer_dma;
}
- writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
+ dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
(unsigned long)dma_addr, chan->hc_num);
@@ -1839,13 +1847,13 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
/* Start the split */
if (chan->do_split) {
- u32 hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num));
+ u32 hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num));
hcsplt |= HCSPLT_SPLTENA;
- writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num));
+ dwc2_writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num));
}
- hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
hcchar &= ~HCCHAR_MULTICNT_MASK;
hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT &
HCCHAR_MULTICNT_MASK;
@@ -1865,7 +1873,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
(hcchar & HCCHAR_MULTICNT_MASK) >>
HCCHAR_MULTICNT_SHIFT);
- writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar,
chan->hc_num);
@@ -1924,18 +1932,18 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, " NTD: %d\n", chan->ntd - 1);
}
- writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+ dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
hc_dma = (u32)chan->desc_list_addr & HCDMA_DMA_ADDR_MASK;
/* Always start from first descriptor */
hc_dma &= ~HCDMA_CTD_MASK;
- writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num));
+ dwc2_writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num));
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "Wrote %08x to HCDMA(%d)\n",
hc_dma, chan->hc_num);
- hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
hcchar &= ~HCCHAR_MULTICNT_MASK;
hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT &
HCCHAR_MULTICNT_MASK;
@@ -1954,7 +1962,7 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
(hcchar & HCCHAR_MULTICNT_MASK) >>
HCCHAR_MULTICNT_SHIFT);
- writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar,
chan->hc_num);
@@ -2011,7 +2019,7 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
* transfer completes, the extra requests for the channel will
* be flushed.
*/
- u32 hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+ u32 hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar);
hcchar |= HCCHAR_CHENA;
@@ -2019,7 +2027,7 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, " IN xfer: hcchar = 0x%08x\n",
hcchar);
- writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
chan->requests++;
return 1;
}
@@ -2029,8 +2037,8 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
if (chan->xfer_count < chan->xfer_len) {
if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
- u32 hcchar = readl(hsotg->regs +
- HCCHAR(chan->hc_num));
+ u32 hcchar = dwc2_readl(hsotg->regs +
+ HCCHAR(chan->hc_num));
dwc2_hc_set_even_odd_frame(hsotg, chan,
&hcchar);
@@ -2066,12 +2074,12 @@ void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
hctsiz = TSIZ_DOPNG;
hctsiz |= 1 << TSIZ_PKTCNT_SHIFT;
- writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+ dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
- hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
hcchar |= HCCHAR_CHENA;
hcchar &= ~HCCHAR_CHDIS;
- writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
}
/**
@@ -2090,8 +2098,8 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg)
u32 hprt0;
int clock = 60; /* default value */
- usbcfg = readl(hsotg->regs + GUSBCFG);
- hprt0 = readl(hsotg->regs + HPRT0);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+ hprt0 = dwc2_readl(hsotg->regs + HPRT0);
if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) &&
!(usbcfg & GUSBCFG_PHYIF16))
@@ -2147,7 +2155,7 @@ void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes)
dev_vdbg(hsotg->dev, "%s(%p,%p,%d)\n", __func__, hsotg, dest, bytes);
for (i = 0; i < word_count; i++, data_buf++)
- *data_buf = readl(fifo);
+ *data_buf = dwc2_readl(fifo);
}
/**
@@ -2167,56 +2175,56 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "Host Global Registers\n");
addr = hsotg->regs + HCFG;
dev_dbg(hsotg->dev, "HCFG @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HFIR;
dev_dbg(hsotg->dev, "HFIR @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HFNUM;
dev_dbg(hsotg->dev, "HFNUM @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HPTXSTS;
dev_dbg(hsotg->dev, "HPTXSTS @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HAINT;
dev_dbg(hsotg->dev, "HAINT @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HAINTMSK;
dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
if (hsotg->core_params->dma_desc_enable > 0) {
addr = hsotg->regs + HFLBADDR;
dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
}
addr = hsotg->regs + HPRT0;
dev_dbg(hsotg->dev, "HPRT0 @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
for (i = 0; i < hsotg->core_params->host_channels; i++) {
dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i);
addr = hsotg->regs + HCCHAR(i);
dev_dbg(hsotg->dev, "HCCHAR @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HCSPLT(i);
dev_dbg(hsotg->dev, "HCSPLT @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HCINT(i);
dev_dbg(hsotg->dev, "HCINT @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HCINTMSK(i);
dev_dbg(hsotg->dev, "HCINTMSK @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HCTSIZ(i);
dev_dbg(hsotg->dev, "HCTSIZ @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HCDMA(i);
dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
if (hsotg->core_params->dma_desc_enable > 0) {
addr = hsotg->regs + HCDMAB(i);
dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
}
}
#endif
@@ -2238,80 +2246,80 @@ void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "Core Global Registers\n");
addr = hsotg->regs + GOTGCTL;
dev_dbg(hsotg->dev, "GOTGCTL @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GOTGINT;
dev_dbg(hsotg->dev, "GOTGINT @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GAHBCFG;
dev_dbg(hsotg->dev, "GAHBCFG @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GUSBCFG;
dev_dbg(hsotg->dev, "GUSBCFG @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GRSTCTL;
dev_dbg(hsotg->dev, "GRSTCTL @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GINTSTS;
dev_dbg(hsotg->dev, "GINTSTS @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GINTMSK;
dev_dbg(hsotg->dev, "GINTMSK @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GRXSTSR;
dev_dbg(hsotg->dev, "GRXSTSR @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GRXFSIZ;
dev_dbg(hsotg->dev, "GRXFSIZ @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GNPTXFSIZ;
dev_dbg(hsotg->dev, "GNPTXFSIZ @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GNPTXSTS;
dev_dbg(hsotg->dev, "GNPTXSTS @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GI2CCTL;
dev_dbg(hsotg->dev, "GI2CCTL @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GPVNDCTL;
dev_dbg(hsotg->dev, "GPVNDCTL @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GGPIO;
dev_dbg(hsotg->dev, "GGPIO @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GUID;
dev_dbg(hsotg->dev, "GUID @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GSNPSID;
dev_dbg(hsotg->dev, "GSNPSID @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GHWCFG1;
dev_dbg(hsotg->dev, "GHWCFG1 @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GHWCFG2;
dev_dbg(hsotg->dev, "GHWCFG2 @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GHWCFG3;
dev_dbg(hsotg->dev, "GHWCFG3 @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GHWCFG4;
dev_dbg(hsotg->dev, "GHWCFG4 @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GLPMCFG;
dev_dbg(hsotg->dev, "GLPMCFG @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GPWRDN;
dev_dbg(hsotg->dev, "GPWRDN @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + GDFIFOCFG;
dev_dbg(hsotg->dev, "GDFIFOCFG @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + HPTXFSIZ;
dev_dbg(hsotg->dev, "HPTXFSIZ @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
addr = hsotg->regs + PCGCTL;
dev_dbg(hsotg->dev, "PCGCTL @0x%08lX : 0x%08X\n",
- (unsigned long)addr, readl(addr));
+ (unsigned long)addr, dwc2_readl(addr));
#endif
}
@@ -2330,15 +2338,15 @@ void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num)
greset = GRSTCTL_TXFFLSH;
greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK;
- writel(greset, hsotg->regs + GRSTCTL);
+ dwc2_writel(greset, hsotg->regs + GRSTCTL);
do {
- greset = readl(hsotg->regs + GRSTCTL);
+ greset = dwc2_readl(hsotg->regs + GRSTCTL);
if (++count > 10000) {
dev_warn(hsotg->dev,
"%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
__func__, greset,
- readl(hsotg->regs + GNPTXSTS));
+ dwc2_readl(hsotg->regs + GNPTXSTS));
break;
}
udelay(1);
@@ -2361,10 +2369,10 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
dev_vdbg(hsotg->dev, "%s()\n", __func__);
greset = GRSTCTL_RXFFLSH;
- writel(greset, hsotg->regs + GRSTCTL);
+ dwc2_writel(greset, hsotg->regs + GRSTCTL);
do {
- greset = readl(hsotg->regs + GRSTCTL);
+ greset = dwc2_readl(hsotg->regs + GRSTCTL);
if (++count > 10000) {
dev_warn(hsotg->dev, "%s() HANG! GRSTCTL=%0x\n",
__func__, greset);
@@ -3062,7 +3070,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
* 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3",
* as in "OTG version 2.xx" or "OTG version 3.xx".
*/
- hw->snpsid = readl(hsotg->regs + GSNPSID);
+ hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID);
if ((hw->snpsid & 0xfffff000) != 0x4f542000 &&
(hw->snpsid & 0xfffff000) != 0x4f543000) {
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
@@ -3074,11 +3082,11 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
- hwcfg1 = readl(hsotg->regs + GHWCFG1);
- hwcfg2 = readl(hsotg->regs + GHWCFG2);
- hwcfg3 = readl(hsotg->regs + GHWCFG3);
- hwcfg4 = readl(hsotg->regs + GHWCFG4);
- grxfsiz = readl(hsotg->regs + GRXFSIZ);
+ hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1);
+ hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
+ hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3);
+ hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
+ grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1);
dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2);
@@ -3087,18 +3095,18 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz);
/* Force host mode to get HPTXFSIZ / GNPTXFSIZ exact power on value */
- gusbcfg = readl(hsotg->regs + GUSBCFG);
+ gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gusbcfg |= GUSBCFG_FORCEHOSTMODE;
- writel(gusbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
usleep_range(100000, 150000);
- gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ);
- hptxfsiz = readl(hsotg->regs + HPTXFSIZ);
+ gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
+ hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz);
- gusbcfg = readl(hsotg->regs + GUSBCFG);
+ gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
- writel(gusbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
usleep_range(100000, 150000);
/* hwcfg2 */
@@ -3233,7 +3241,7 @@ u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg)
bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
{
- if (readl(hsotg->regs + GSNPSID) == 0xffffffff)
+ if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
return false;
else
return true;
@@ -3247,10 +3255,10 @@ bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
*/
void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
{
- u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+ u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
ahbcfg |= GAHBCFG_GLBL_INTR_EN;
- writel(ahbcfg, hsotg->regs + GAHBCFG);
+ dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
}
/**
@@ -3261,10 +3269,10 @@ void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
*/
void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg)
{
- u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+ u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
- writel(ahbcfg, hsotg->regs + GAHBCFG);
+ dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
}
MODULE_DESCRIPTION("DESIGNWARE HS OTG Core");
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 0ed87620941b..a66d3cb62b65 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -44,22 +44,38 @@
#include <linux/usb/phy.h>
#include "hw.h"
-#ifdef DWC2_LOG_WRITES
-static inline void do_write(u32 value, void *addr)
+static inline u32 dwc2_readl(const void __iomem *addr)
{
- writel(value, addr);
- pr_info("INFO:: wrote %08x to %p\n", value, addr);
+ u32 value = __raw_readl(addr);
+
+ /* In order to preserve endianness __raw_* operation is used. Therefore
+ * a barrier is needed to ensure IO access is not re-ordered across
+ * reads or writes
+ */
+ mb();
+ return value;
}
-#undef writel
-#define writel(v, a) do_write(v, a)
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+ __raw_writel(value, addr);
+
+ /*
+ * In order to preserve endianness __raw_* operation is used. Therefore
+ * a barrier is needed to ensure IO access is not re-ordered across
+ * reads or writes
+ */
+ mb();
+#ifdef DWC2_LOG_WRITES
+ pr_info("INFO:: wrote %08x to %p\n", value, addr);
#endif
+}
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
-/* s3c-hsotg declarations */
-static const char * const s3c_hsotg_supply_names[] = {
+/* dwc2-hsotg declarations */
+static const char * const dwc2_hsotg_supply_names[] = {
"vusb_d", /* digital USB supply, 1.2V */
"vusb_a", /* analog USB supply, 1.1V */
};
@@ -85,10 +101,10 @@ static const char * const s3c_hsotg_supply_names[] = {
#define EP0_MPS_LIMIT 64
struct dwc2_hsotg;
-struct s3c_hsotg_req;
+struct dwc2_hsotg_req;
/**
- * struct s3c_hsotg_ep - driver endpoint definition.
+ * struct dwc2_hsotg_ep - driver endpoint definition.
* @ep: The gadget layer representation of the endpoint.
* @name: The driver generated name for the endpoint.
* @queue: Queue of requests for this endpoint.
@@ -127,11 +143,11 @@ struct s3c_hsotg_req;
* as in shared-fifo mode periodic in acts like a single-frame packet
* buffer than a fifo)
*/
-struct s3c_hsotg_ep {
+struct dwc2_hsotg_ep {
struct usb_ep ep;
struct list_head queue;
struct dwc2_hsotg *parent;
- struct s3c_hsotg_req *req;
+ struct dwc2_hsotg_req *req;
struct dentry *debugfs;
unsigned long total_data;
@@ -150,17 +166,18 @@ struct s3c_hsotg_ep {
unsigned int periodic:1;
unsigned int isochronous:1;
unsigned int send_zlp:1;
+ unsigned int has_correct_parity:1;
char name[10];
};
/**
- * struct s3c_hsotg_req - data transfer request
+ * struct dwc2_hsotg_req - data transfer request
* @req: The USB gadget request
* @queue: The list of requests for the endpoint this is queued for.
* @saved_req_buf: variable to save req.buf when bounce buffers are used.
*/
-struct s3c_hsotg_req {
+struct dwc2_hsotg_req {
struct usb_request req;
struct list_head queue;
void *saved_req_buf;
@@ -562,6 +579,15 @@ struct dwc2_hregs_backup {
* - USB_DR_MODE_PERIPHERAL
* - USB_DR_MODE_HOST
* - USB_DR_MODE_OTG
+ * @hcd_enabled Host mode sub-driver initialization indicator.
+ * @gadget_enabled Peripheral mode sub-driver initialization indicator.
+ * @ll_hw_enabled Status of low-level hardware resources.
+ * @phy: The otg phy transceiver structure for phy control.
+ * @uphy: The otg phy transceiver structure for old USB phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
+ * @supplies: Definition of USB power supplies
+ * @phyif: PHY interface width
* @lock: Spinlock that protects all the driver data structures
* @priv: Stores a pointer to the struct usb_hcd
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
@@ -654,12 +680,6 @@ struct dwc2_hregs_backup {
* These are for peripheral mode:
*
* @driver: USB gadget driver
- * @phy: The otg phy transceiver structure for phy control.
- * @uphy: The otg phy transceiver structure for old USB phy control.
- * @plat: The platform specific configuration data. This can be removed once
- * all SoCs support usb transceiver.
- * @supplies: Definition of USB power supplies
- * @phyif: PHY interface width
* @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
* @num_of_eps: Number of available EPs (excluding EP0)
* @debug_root: Root directrory for debugfs.
@@ -672,7 +692,6 @@ struct dwc2_hregs_backup {
* @ctrl_req: Request for EP0 control packets.
* @ep0_state: EP0 control transfers state
* @test_mode: USB test mode requested by the host
- * @last_rst: Time of last reset
* @eps: The endpoints being supplied to the gadget framework
* @g_using_dma: Indicate if dma usage is enabled
* @g_rx_fifo_sz: Contains rx fifo size value
@@ -690,13 +709,15 @@ struct dwc2_hsotg {
enum usb_dr_mode dr_mode;
unsigned int hcd_enabled:1;
unsigned int gadget_enabled:1;
+ unsigned int ll_hw_enabled:1;
struct phy *phy;
struct usb_phy *uphy;
- struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+ struct dwc2_hsotg_plat *plat;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)];
+ u32 phyif;
spinlock_t lock;
- struct mutex init_mutex;
void *priv;
int irq;
struct clk *clk;
@@ -748,6 +769,7 @@ struct dwc2_hsotg {
u16 frame_usecs[8];
u16 frame_number;
u16 periodic_qh_count;
+ bool bus_suspended;
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
#define FRAME_NUM_ARRAY_SIZE 1000
@@ -796,9 +818,6 @@ struct dwc2_hsotg {
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
/* Gadget structures */
struct usb_gadget_driver *driver;
- struct s3c_hsotg_plat *plat;
-
- u32 phyif;
int fifo_mem;
unsigned int dedicated_fifos:1;
unsigned char num_of_eps;
@@ -814,9 +833,8 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
- unsigned long last_rst;
- struct s3c_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
- struct s3c_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
+ struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
+ struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
u32 g_rx_fifo_sz;
u32 g_np_g_tx_fifo_sz;
@@ -1088,7 +1106,8 @@ extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
-
+extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg);
+extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg);
/*
* Dump core registers and SPRAM
@@ -1104,30 +1123,30 @@ extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
/* Gadget defines */
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
-extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
-extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
-extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg);
+extern int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2);
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
-extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+extern void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset);
-extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
-extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2);
-extern int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
+extern void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg);
+extern void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
#define dwc2_is_device_connected(hsotg) (hsotg->connected)
#else
-static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
-static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2)
{ return 0; }
-static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
-static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset) {}
-static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
-static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
-static inline int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
+static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
+static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
int testmode)
{ return 0; }
#define dwc2_is_device_connected(hsotg) (0)
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 927be1e8b3dc..27daa42788b1 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -80,15 +80,15 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
*/
static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
{
- u32 hprt0 = readl(hsotg->regs + HPRT0);
+ u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
if (hprt0 & HPRT0_ENACHG) {
hprt0 &= ~HPRT0_ENA;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
}
/* Clear interrupt */
- writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
}
/**
@@ -102,7 +102,7 @@ static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
dwc2_is_host_mode(hsotg) ? "Host" : "Device");
/* Clear interrupt */
- writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
}
/**
@@ -117,8 +117,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
u32 gotgctl;
u32 gintmsk;
- gotgint = readl(hsotg->regs + GOTGINT);
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgint = dwc2_readl(hsotg->regs + GOTGINT);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
dwc2_op_state_str(hsotg));
@@ -126,10 +126,10 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev,
" ++OTG Interrupt: Session End Detected++ (%s)\n",
dwc2_op_state_str(hsotg));
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
if (dwc2_is_device_mode(hsotg))
- s3c_hsotg_disconnect(hsotg);
+ dwc2_hsotg_disconnect(hsotg);
if (hsotg->op_state == OTG_STATE_B_HOST) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
@@ -152,15 +152,15 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
hsotg->lx_state = DWC2_L0;
}
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
gotgctl &= ~GOTGCTL_DEVHNPEN;
- writel(gotgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
}
if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
dev_dbg(hsotg->dev,
" ++OTG Interrupt: Session Request Success Status Change++\n");
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
if (gotgctl & GOTGCTL_SESREQSCS) {
if (hsotg->core_params->phy_type ==
DWC2_PHY_TYPE_PARAM_FS
@@ -168,9 +168,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
hsotg->srp_success = 1;
} else {
/* Clear Session Request */
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
gotgctl &= ~GOTGCTL_SESREQ;
- writel(gotgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
}
}
}
@@ -180,7 +180,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
* Print statements during the HNP interrupt handling
* can cause it to fail
*/
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
/*
* WA for 3.00a- HW is not setting cur_mode, even sometimes
* this does not help
@@ -200,9 +200,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
* interrupt does not get handled and Linux
* complains loudly.
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk &= ~GINTSTS_SOF;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
/*
* Call callback function with spin lock
@@ -216,9 +216,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
hsotg->op_state = OTG_STATE_B_HOST;
}
} else {
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
- writel(gotgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
dev_dbg(hsotg->dev, "HNP Failed\n");
dev_err(hsotg->dev,
"Device Not Connected/Responding\n");
@@ -244,9 +244,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
hsotg->op_state = OTG_STATE_A_PERIPHERAL;
} else {
/* Need to disable SOF interrupt immediately */
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk &= ~GINTSTS_SOF;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
spin_unlock(&hsotg->lock);
dwc2_hcd_start(hsotg);
spin_lock(&hsotg->lock);
@@ -261,7 +261,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
/* Clear GOTGINT */
- writel(gotgint, hsotg->regs + GOTGINT);
+ dwc2_writel(gotgint, hsotg->regs + GOTGINT);
}
/**
@@ -276,11 +276,11 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
*/
static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
{
- u32 gintmsk = readl(hsotg->regs + GINTMSK);
+ u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
/* Need to disable SOF interrupt immediately */
gintmsk &= ~GINTSTS_SOF;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++ (%s)\n",
dwc2_is_host_mode(hsotg) ? "Host" : "Device");
@@ -297,7 +297,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
}
/* Clear interrupt */
- writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
}
/**
@@ -313,16 +313,28 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
*/
static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
{
- dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");
+ int ret;
+
+ dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
+ hsotg->lx_state);
/* Clear interrupt */
- writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
- /*
- * Report disconnect if there is any previous session established
- */
- if (dwc2_is_device_mode(hsotg))
- s3c_hsotg_disconnect(hsotg);
+ if (dwc2_is_device_mode(hsotg)) {
+ if (hsotg->lx_state == DWC2_L2) {
+ ret = dwc2_exit_hibernation(hsotg, true);
+ if (ret && (ret != -ENOTSUPP))
+ dev_err(hsotg->dev,
+ "exit hibernation failed\n");
+ }
+
+ /*
+ * Report disconnect if there is any previous session
+ * established
+ */
+ dwc2_hsotg_disconnect(hsotg);
+ }
}
/*
@@ -339,13 +351,14 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
if (dwc2_is_device_mode(hsotg)) {
- dev_dbg(hsotg->dev, "DSTS=0x%0x\n", readl(hsotg->regs + DSTS));
+ dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
+ dwc2_readl(hsotg->regs + DSTS));
if (hsotg->lx_state == DWC2_L2) {
- u32 dctl = readl(hsotg->regs + DCTL);
+ u32 dctl = dwc2_readl(hsotg->regs + DCTL);
/* Clear Remote Wakeup Signaling */
dctl &= ~DCTL_RMTWKUPSIG;
- writel(dctl, hsotg->regs + DCTL);
+ dwc2_writel(dctl, hsotg->regs + DCTL);
ret = dwc2_exit_hibernation(hsotg, true);
if (ret && (ret != -ENOTSUPP))
dev_err(hsotg->dev, "exit hibernation failed\n");
@@ -355,12 +368,16 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
} else {
+ if (hsotg->core_params->hibernation) {
+ dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+ return;
+ }
if (hsotg->lx_state != DWC2_L1) {
- u32 pcgcctl = readl(hsotg->regs + PCGCTL);
+ u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
/* Restart the Phy Clock */
pcgcctl &= ~PCGCTL_STOPPCLK;
- writel(pcgcctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
mod_timer(&hsotg->wkp_timer,
jiffies + msecs_to_jiffies(71));
} else {
@@ -370,7 +387,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
}
/* Clear interrupt */
- writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
}
/*
@@ -386,10 +403,7 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
if (hsotg->op_state == OTG_STATE_A_HOST)
dwc2_hcd_disconnect(hsotg);
- /* Change to L3 (OFF) state */
- hsotg->lx_state = DWC2_L3;
-
- writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
}
/*
@@ -412,7 +426,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
* Check the Device status register to determine if the Suspend
* state is active
*/
- dsts = readl(hsotg->regs + DSTS);
+ dsts = dwc2_readl(hsotg->regs + DSTS);
dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts);
dev_dbg(hsotg->dev,
"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
@@ -465,7 +479,7 @@ skip_power_saving:
clear_int:
/* Clear interrupt */
- writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
}
#define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \
@@ -483,9 +497,9 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
u32 gahbcfg;
u32 gintmsk_common = GINTMSK_COMMON;
- gintsts = readl(hsotg->regs + GINTSTS);
- gintmsk = readl(hsotg->regs + GINTMSK);
- gahbcfg = readl(hsotg->regs + GAHBCFG);
+ gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+ gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
/* If any common interrupts set */
if (gintsts & gintmsk_common)
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index ef2ee3d9a25d..55d91f24f94a 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -57,7 +57,7 @@ static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t
testmode = 0;
spin_lock_irqsave(&hsotg->lock, flags);
- s3c_hsotg_set_test_mode(hsotg, testmode);
+ dwc2_hsotg_set_test_mode(hsotg, testmode);
spin_unlock_irqrestore(&hsotg->lock, flags);
return count;
}
@@ -76,7 +76,7 @@ static int testmode_show(struct seq_file *s, void *unused)
int dctl;
spin_lock_irqsave(&hsotg->lock, flags);
- dctl = readl(hsotg->regs + DCTL);
+ dctl = dwc2_readl(hsotg->regs + DCTL);
dctl &= DCTL_TSTCTL_MASK;
dctl >>= DCTL_TSTCTL_SHIFT;
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -137,38 +137,38 @@ static int state_show(struct seq_file *seq, void *v)
int idx;
seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
- readl(regs + DCFG),
- readl(regs + DCTL),
- readl(regs + DSTS));
+ dwc2_readl(regs + DCFG),
+ dwc2_readl(regs + DCTL),
+ dwc2_readl(regs + DSTS));
seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
- readl(regs + DIEPMSK), readl(regs + DOEPMSK));
+ dwc2_readl(regs + DIEPMSK), dwc2_readl(regs + DOEPMSK));
seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
- readl(regs + GINTMSK),
- readl(regs + GINTSTS));
+ dwc2_readl(regs + GINTMSK),
+ dwc2_readl(regs + GINTSTS));
seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
- readl(regs + DAINTMSK),
- readl(regs + DAINT));
+ dwc2_readl(regs + DAINTMSK),
+ dwc2_readl(regs + DAINT));
seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
- readl(regs + GNPTXSTS),
- readl(regs + GRXSTSR));
+ dwc2_readl(regs + GNPTXSTS),
+ dwc2_readl(regs + GRXSTSR));
seq_puts(seq, "\nEndpoint status:\n");
for (idx = 0; idx < hsotg->num_of_eps; idx++) {
u32 in, out;
- in = readl(regs + DIEPCTL(idx));
- out = readl(regs + DOEPCTL(idx));
+ in = dwc2_readl(regs + DIEPCTL(idx));
+ out = dwc2_readl(regs + DOEPCTL(idx));
seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
idx, in, out);
- in = readl(regs + DIEPTSIZ(idx));
- out = readl(regs + DOEPTSIZ(idx));
+ in = dwc2_readl(regs + DIEPTSIZ(idx));
+ out = dwc2_readl(regs + DOEPTSIZ(idx));
seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
in, out);
@@ -208,9 +208,9 @@ static int fifo_show(struct seq_file *seq, void *v)
int idx;
seq_puts(seq, "Non-periodic FIFOs:\n");
- seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
+ seq_printf(seq, "RXFIFO: Size %d\n", dwc2_readl(regs + GRXFSIZ));
- val = readl(regs + GNPTXFSIZ);
+ val = dwc2_readl(regs + GNPTXFSIZ);
seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
val >> FIFOSIZE_DEPTH_SHIFT,
val & FIFOSIZE_DEPTH_MASK);
@@ -218,7 +218,7 @@ static int fifo_show(struct seq_file *seq, void *v)
seq_puts(seq, "\nPeriodic TXFIFOs:\n");
for (idx = 1; idx < hsotg->num_of_eps; idx++) {
- val = readl(regs + DPTXFSIZN(idx));
+ val = dwc2_readl(regs + DPTXFSIZN(idx));
seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
val >> FIFOSIZE_DEPTH_SHIFT,
@@ -256,9 +256,9 @@ static const char *decode_direction(int is_in)
*/
static int ep_show(struct seq_file *seq, void *v)
{
- struct s3c_hsotg_ep *ep = seq->private;
+ struct dwc2_hsotg_ep *ep = seq->private;
struct dwc2_hsotg *hsotg = ep->parent;
- struct s3c_hsotg_req *req;
+ struct dwc2_hsotg_req *req;
void __iomem *regs = hsotg->regs;
int index = ep->index;
int show_limit = 15;
@@ -270,20 +270,20 @@ static int ep_show(struct seq_file *seq, void *v)
/* first show the register state */
seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
- readl(regs + DIEPCTL(index)),
- readl(regs + DOEPCTL(index)));
+ dwc2_readl(regs + DIEPCTL(index)),
+ dwc2_readl(regs + DOEPCTL(index)));
seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
- readl(regs + DIEPDMA(index)),
- readl(regs + DOEPDMA(index)));
+ dwc2_readl(regs + DIEPDMA(index)),
+ dwc2_readl(regs + DOEPDMA(index)));
seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
- readl(regs + DIEPINT(index)),
- readl(regs + DOEPINT(index)));
+ dwc2_readl(regs + DIEPINT(index)),
+ dwc2_readl(regs + DOEPINT(index)));
seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
- readl(regs + DIEPTSIZ(index)),
- readl(regs + DOEPTSIZ(index)));
+ dwc2_readl(regs + DIEPTSIZ(index)),
+ dwc2_readl(regs + DOEPTSIZ(index)));
seq_puts(seq, "\n");
seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
@@ -326,7 +326,7 @@ static const struct file_operations ep_fops = {
};
/**
- * s3c_hsotg_create_debug - create debugfs directory and files
+ * dwc2_hsotg_create_debug - create debugfs directory and files
* @hsotg: The driver state
*
* Create the debugfs files to allow the user to get information
@@ -334,7 +334,7 @@ static const struct file_operations ep_fops = {
* with the same name as the device itself, in case we end up
* with multiple blocks in future systems.
*/
-static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg)
{
struct dentry *root;
struct dentry *file;
@@ -360,7 +360,7 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
/* Create one file for each out endpoint */
for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
- struct s3c_hsotg_ep *ep;
+ struct dwc2_hsotg_ep *ep;
ep = hsotg->eps_out[epidx];
if (ep) {
@@ -373,7 +373,7 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
}
/* Create one file for each in endpoint. EP0 is handled with out eps */
for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) {
- struct s3c_hsotg_ep *ep;
+ struct dwc2_hsotg_ep *ep;
ep = hsotg->eps_in[epidx];
if (ep) {
@@ -386,10 +386,10 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
}
}
#else
-static inline void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) {}
#endif
-/* s3c_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */
+/* dwc2_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */
#define dump_register(nm) \
{ \
@@ -737,7 +737,7 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
}
/* Add gadget debugfs nodes */
- s3c_hsotg_create_debug(hsotg);
+ dwc2_hsotg_create_debug(hsotg);
hsotg->regset = devm_kzalloc(hsotg->dev, sizeof(*hsotg->regset),
GFP_KERNEL);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3ee5b4c77a1f..0abf73c91beb 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -25,28 +25,24 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
#include <linux/of_platform.h>
-#include <linux/phy/phy.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/phy.h>
-#include <linux/platform_data/s3c-hsotg.h>
#include "core.h"
#include "hw.h"
/* conversion functions */
-static inline struct s3c_hsotg_req *our_req(struct usb_request *req)
+static inline struct dwc2_hsotg_req *our_req(struct usb_request *req)
{
- return container_of(req, struct s3c_hsotg_req, req);
+ return container_of(req, struct dwc2_hsotg_req, req);
}
-static inline struct s3c_hsotg_ep *our_ep(struct usb_ep *ep)
+static inline struct dwc2_hsotg_ep *our_ep(struct usb_ep *ep)
{
- return container_of(ep, struct s3c_hsotg_ep, ep);
+ return container_of(ep, struct dwc2_hsotg_ep, ep);
}
static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget)
@@ -56,15 +52,15 @@ static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget)
static inline void __orr32(void __iomem *ptr, u32 val)
{
- writel(readl(ptr) | val, ptr);
+ dwc2_writel(dwc2_readl(ptr) | val, ptr);
}
static inline void __bic32(void __iomem *ptr, u32 val)
{
- writel(readl(ptr) & ~val, ptr);
+ dwc2_writel(dwc2_readl(ptr) & ~val, ptr);
}
-static inline struct s3c_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
+static inline struct dwc2_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
u32 ep_index, u32 dir_in)
{
if (dir_in)
@@ -74,7 +70,7 @@ static inline struct s3c_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
}
/* forward declaration of functions */
-static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg);
+static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg);
/**
* using_dma - return the DMA status of the driver.
@@ -101,41 +97,41 @@ static inline bool using_dma(struct dwc2_hsotg *hsotg)
}
/**
- * s3c_hsotg_en_gsint - enable one or more of the general interrupt
+ * dwc2_hsotg_en_gsint - enable one or more of the general interrupt
* @hsotg: The device state
* @ints: A bitmask of the interrupts to enable
*/
-static void s3c_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
+static void dwc2_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
{
- u32 gsintmsk = readl(hsotg->regs + GINTMSK);
+ u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK);
u32 new_gsintmsk;
new_gsintmsk = gsintmsk | ints;
if (new_gsintmsk != gsintmsk) {
dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk);
- writel(new_gsintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK);
}
}
/**
- * s3c_hsotg_disable_gsint - disable one or more of the general interrupt
+ * dwc2_hsotg_disable_gsint - disable one or more of the general interrupt
* @hsotg: The device state
* @ints: A bitmask of the interrupts to enable
*/
-static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
+static void dwc2_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
{
- u32 gsintmsk = readl(hsotg->regs + GINTMSK);
+ u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK);
u32 new_gsintmsk;
new_gsintmsk = gsintmsk & ~ints;
if (new_gsintmsk != gsintmsk)
- writel(new_gsintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK);
}
/**
- * s3c_hsotg_ctrl_epint - enable/disable an endpoint irq
+ * dwc2_hsotg_ctrl_epint - enable/disable an endpoint irq
* @hsotg: The device state
* @ep: The endpoint index
* @dir_in: True if direction is in.
@@ -144,7 +140,7 @@ static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
* Set or clear the mask for an individual endpoint's interrupt
* request.
*/
-static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
+static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
unsigned int ep, unsigned int dir_in,
unsigned int en)
{
@@ -156,20 +152,20 @@ static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
bit <<= 16;
local_irq_save(flags);
- daint = readl(hsotg->regs + DAINTMSK);
+ daint = dwc2_readl(hsotg->regs + DAINTMSK);
if (en)
daint |= bit;
else
daint &= ~bit;
- writel(daint, hsotg->regs + DAINTMSK);
+ dwc2_writel(daint, hsotg->regs + DAINTMSK);
local_irq_restore(flags);
}
/**
- * s3c_hsotg_init_fifo - initialise non-periodic FIFOs
+ * dwc2_hsotg_init_fifo - initialise non-periodic FIFOs
* @hsotg: The device instance.
*/
-static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
{
unsigned int ep;
unsigned int addr;
@@ -181,8 +177,8 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
hsotg->fifo_map = 0;
/* set RX/NPTX FIFO sizes */
- writel(hsotg->g_rx_fifo_sz, hsotg->regs + GRXFSIZ);
- writel((hsotg->g_rx_fifo_sz << FIFOSIZE_STARTADDR_SHIFT) |
+ dwc2_writel(hsotg->g_rx_fifo_sz, hsotg->regs + GRXFSIZ);
+ dwc2_writel((hsotg->g_rx_fifo_sz << FIFOSIZE_STARTADDR_SHIFT) |
(hsotg->g_np_g_tx_fifo_sz << FIFOSIZE_DEPTH_SHIFT),
hsotg->regs + GNPTXFSIZ);
@@ -210,7 +206,7 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
"insufficient fifo memory");
addr += hsotg->g_tx_fifo_sz[ep];
- writel(val, hsotg->regs + DPTXFSIZN(ep));
+ dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep));
}
/*
@@ -218,13 +214,13 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
* all fifos are flushed before continuing
*/
- writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
+ dwc2_writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
GRSTCTL_RXFFLSH, hsotg->regs + GRSTCTL);
/* wait until the fifos are both flushed */
timeout = 100;
while (1) {
- val = readl(hsotg->regs + GRSTCTL);
+ val = dwc2_readl(hsotg->regs + GRSTCTL);
if ((val & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) == 0)
break;
@@ -248,12 +244,12 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
*
* Allocate a new USB request structure appropriate for the specified endpoint
*/
-static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
+static struct usb_request *dwc2_hsotg_ep_alloc_request(struct usb_ep *ep,
gfp_t flags)
{
- struct s3c_hsotg_req *req;
+ struct dwc2_hsotg_req *req;
- req = kzalloc(sizeof(struct s3c_hsotg_req), flags);
+ req = kzalloc(sizeof(struct dwc2_hsotg_req), flags);
if (!req)
return NULL;
@@ -269,23 +265,23 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
* Returns true if the endpoint is in periodic mode, meaning it is being
* used for an Interrupt or ISO transfer.
*/
-static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep)
+static inline int is_ep_periodic(struct dwc2_hsotg_ep *hs_ep)
{
return hs_ep->periodic;
}
/**
- * s3c_hsotg_unmap_dma - unmap the DMA memory being used for the request
+ * dwc2_hsotg_unmap_dma - unmap the DMA memory being used for the request
* @hsotg: The device state.
* @hs_ep: The endpoint for the request
* @hs_req: The request being processed.
*
- * This is the reverse of s3c_hsotg_map_dma(), called for the completion
+ * This is the reverse of dwc2_hsotg_map_dma(), called for the completion
* of a request to ensure the buffer is ready for access by the caller.
*/
-static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep,
- struct s3c_hsotg_req *hs_req)
+static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep,
+ struct dwc2_hsotg_req *hs_req)
{
struct usb_request *req = &hs_req->req;
@@ -297,7 +293,7 @@ static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
}
/**
- * s3c_hsotg_write_fifo - write packet Data to the TxFIFO
+ * dwc2_hsotg_write_fifo - write packet Data to the TxFIFO
* @hsotg: The controller state.
* @hs_ep: The endpoint we're going to write for.
* @hs_req: The request to write data for.
@@ -312,12 +308,12 @@ static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
*
* This routine is only needed for PIO
*/
-static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep,
- struct s3c_hsotg_req *hs_req)
+static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep,
+ struct dwc2_hsotg_req *hs_req)
{
bool periodic = is_ep_periodic(hs_ep);
- u32 gnptxsts = readl(hsotg->regs + GNPTXSTS);
+ u32 gnptxsts = dwc2_readl(hsotg->regs + GNPTXSTS);
int buf_pos = hs_req->req.actual;
int to_write = hs_ep->size_loaded;
void *data;
@@ -332,7 +328,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
return 0;
if (periodic && !hsotg->dedicated_fifos) {
- u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
+ u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
int size_left;
int size_done;
@@ -348,7 +344,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
* previous data has been completely sent.
*/
if (hs_ep->fifo_load != 0) {
- s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
+ dwc2_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
return -ENOSPC;
}
@@ -369,11 +365,11 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
__func__, can_write);
if (can_write <= 0) {
- s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
+ dwc2_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
return -ENOSPC;
}
} else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
- can_write = readl(hsotg->regs + DTXFSTS(hs_ep->index));
+ can_write = dwc2_readl(hsotg->regs + DTXFSTS(hs_ep->index));
can_write &= 0xffff;
can_write *= 4;
@@ -383,7 +379,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
"%s: no queue slots available (0x%08x)\n",
__func__, gnptxsts);
- s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP);
+ dwc2_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP);
return -ENOSPC;
}
@@ -414,7 +410,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
/* it's needed only when we do not use dedicated fifos */
if (!hsotg->dedicated_fifos)
- s3c_hsotg_en_gsint(hsotg,
+ dwc2_hsotg_en_gsint(hsotg,
periodic ? GINTSTS_PTXFEMP :
GINTSTS_NPTXFEMP);
}
@@ -443,7 +439,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
/* it's needed only when we do not use dedicated fifos */
if (!hsotg->dedicated_fifos)
- s3c_hsotg_en_gsint(hsotg,
+ dwc2_hsotg_en_gsint(hsotg,
periodic ? GINTSTS_PTXFEMP :
GINTSTS_NPTXFEMP);
}
@@ -475,7 +471,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
* Return the maximum data that can be queued in one go on a given endpoint
* so that transfers that are too long can be split.
*/
-static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
+static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep)
{
int index = hs_ep->index;
unsigned maxsize;
@@ -508,7 +504,7 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
}
/**
- * s3c_hsotg_start_req - start a USB request from an endpoint's queue
+ * dwc2_hsotg_start_req - start a USB request from an endpoint's queue
* @hsotg: The controller state.
* @hs_ep: The endpoint to process a request for
* @hs_req: The request to start.
@@ -517,9 +513,9 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
* Start the given request running by setting the endpoint registers
* appropriately, and writing any data to the FIFOs.
*/
-static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep,
- struct s3c_hsotg_req *hs_req,
+static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep,
+ struct dwc2_hsotg_req *hs_req,
bool continuing)
{
struct usb_request *ureq = &hs_req->req;
@@ -550,13 +546,13 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index);
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n",
- __func__, readl(hsotg->regs + epctrl_reg), index,
+ __func__, dwc2_readl(hsotg->regs + epctrl_reg), index,
hs_ep->dir_in ? "in" : "out");
/* If endpoint is stalled, we will restart request later */
- ctrl = readl(hsotg->regs + epctrl_reg);
+ ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
- if (ctrl & DXEPCTL_STALL) {
+ if (index && ctrl & DXEPCTL_STALL) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
@@ -618,18 +614,18 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
hs_ep->req = hs_req;
/* write size / packets */
- writel(epsize, hsotg->regs + epsize_reg);
+ dwc2_writel(epsize, hsotg->regs + epsize_reg);
if (using_dma(hsotg) && !continuing) {
unsigned int dma_reg;
/*
* write DMA address to control register, buffer already
- * synced by s3c_hsotg_ep_queue().
+ * synced by dwc2_hsotg_ep_queue().
*/
dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index);
- writel(ureq->dma, hsotg->regs + dma_reg);
+ dwc2_writel(ureq->dma, hsotg->regs + dma_reg);
dev_dbg(hsotg->dev, "%s: %pad => 0x%08x\n",
__func__, &ureq->dma, dma_reg);
@@ -645,7 +641,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
ctrl |= DXEPCTL_CNAK; /* clear NAK set by core */
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
- writel(ctrl, hsotg->regs + epctrl_reg);
+ dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
/*
* set these, it seems that DMA support increments past the end
@@ -659,7 +655,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
/* set these anyway, we may need them for non-periodic in */
hs_ep->fifo_load = 0;
- s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req);
+ dwc2_hsotg_write_fifo(hsotg, hs_ep, hs_req);
}
/*
@@ -667,7 +663,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
* to debugging to see what is going on.
*/
if (dir_in)
- writel(DIEPMSK_INTKNTXFEMPMSK,
+ dwc2_writel(DIEPMSK_INTKNTXFEMPMSK,
hsotg->regs + DIEPINT(index));
/*
@@ -676,20 +672,20 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
*/
/* check ep is enabled */
- if (!(readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
+ if (!(dwc2_readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
dev_dbg(hsotg->dev,
"ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n",
- index, readl(hsotg->regs + epctrl_reg));
+ index, dwc2_readl(hsotg->regs + epctrl_reg));
dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n",
- __func__, readl(hsotg->regs + epctrl_reg));
+ __func__, dwc2_readl(hsotg->regs + epctrl_reg));
/* enable ep interrupts */
- s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1);
+ dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1);
}
/**
- * s3c_hsotg_map_dma - map the DMA memory being used for the request
+ * dwc2_hsotg_map_dma - map the DMA memory being used for the request
* @hsotg: The device state.
* @hs_ep: The endpoint the request is on.
* @req: The request being processed.
@@ -700,11 +696,11 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
* DMA memory, then we map the memory and mark our request to allow us to
* cleanup on completion.
*/
-static int s3c_hsotg_map_dma(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep,
+static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep,
struct usb_request *req)
{
- struct s3c_hsotg_req *hs_req = our_req(req);
+ struct dwc2_hsotg_req *hs_req = our_req(req);
int ret;
/* if the length is zero, ignore the DMA data */
@@ -724,8 +720,8 @@ dma_error:
return -EIO;
}
-static int s3c_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req)
+static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req)
{
void *req_buf = hs_req->req.buf;
@@ -755,8 +751,8 @@ static int s3c_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
return 0;
}
-static void s3c_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req)
+static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req)
{
/* If dma is not being used or buffer was aligned */
if (!using_dma(hsotg) || !hs_req->saved_req_buf)
@@ -777,11 +773,11 @@ static void s3c_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
hs_req->saved_req_buf = NULL;
}
-static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
+static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags)
{
- struct s3c_hsotg_req *hs_req = our_req(req);
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_req *hs_req = our_req(req);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hs = hs_ep->parent;
bool first;
int ret;
@@ -802,13 +798,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
req->actual = 0;
req->status = -EINPROGRESS;
- ret = s3c_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req);
+ ret = dwc2_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req);
if (ret)
return ret;
/* if we're using DMA, sync the buffers as necessary */
if (using_dma(hs)) {
- ret = s3c_hsotg_map_dma(hs, hs_ep, req);
+ ret = dwc2_hsotg_map_dma(hs, hs_ep, req);
if (ret)
return ret;
}
@@ -817,51 +813,51 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
list_add_tail(&hs_req->queue, &hs_ep->queue);
if (first)
- s3c_hsotg_start_req(hs, hs_ep, hs_req, false);
+ dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
return 0;
}
-static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
+static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hs = hs_ep->parent;
unsigned long flags = 0;
int ret = 0;
spin_lock_irqsave(&hs->lock, flags);
- ret = s3c_hsotg_ep_queue(ep, req, gfp_flags);
+ ret = dwc2_hsotg_ep_queue(ep, req, gfp_flags);
spin_unlock_irqrestore(&hs->lock, flags);
return ret;
}
-static void s3c_hsotg_ep_free_request(struct usb_ep *ep,
+static void dwc2_hsotg_ep_free_request(struct usb_ep *ep,
struct usb_request *req)
{
- struct s3c_hsotg_req *hs_req = our_req(req);
+ struct dwc2_hsotg_req *hs_req = our_req(req);
kfree(hs_req);
}
/**
- * s3c_hsotg_complete_oursetup - setup completion callback
+ * dwc2_hsotg_complete_oursetup - setup completion callback
* @ep: The endpoint the request was on.
* @req: The request completed.
*
* Called on completion of any requests the driver itself
* submitted that need cleaning up.
*/
-static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
+static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep,
struct usb_request *req)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
dev_dbg(hsotg->dev, "%s: ep %p, req %p\n", __func__, ep, req);
- s3c_hsotg_ep_free_request(ep, req);
+ dwc2_hsotg_ep_free_request(ep, req);
}
/**
@@ -872,10 +868,10 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
* Convert the given wIndex into a pointer to an driver endpoint
* structure, or return NULL if it is not a valid endpoint.
*/
-static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
+static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
u32 windex)
{
- struct s3c_hsotg_ep *ep;
+ struct dwc2_hsotg_ep *ep;
int dir = (windex & USB_DIR_IN) ? 1 : 0;
int idx = windex & 0x7F;
@@ -894,14 +890,14 @@ static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
}
/**
- * s3c_hsotg_set_test_mode - Enable usb Test Modes
+ * dwc2_hsotg_set_test_mode - Enable usb Test Modes
* @hsotg: The driver state.
* @testmode: requested usb test mode
* Enable usb Test Mode requested by the Host.
*/
-int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
+int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
{
- int dctl = readl(hsotg->regs + DCTL);
+ int dctl = dwc2_readl(hsotg->regs + DCTL);
dctl &= ~DCTL_TSTCTL_MASK;
switch (testmode) {
@@ -915,12 +911,12 @@ int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
default:
return -EINVAL;
}
- writel(dctl, hsotg->regs + DCTL);
+ dwc2_writel(dctl, hsotg->regs + DCTL);
return 0;
}
/**
- * s3c_hsotg_send_reply - send reply to control request
+ * dwc2_hsotg_send_reply - send reply to control request
* @hsotg: The device state
* @ep: Endpoint 0
* @buff: Buffer for request
@@ -929,8 +925,8 @@ int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
* Create a request and queue it on the given endpoint. This is useful as
* an internal method of sending replies to certain control requests, etc.
*/
-static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *ep,
+static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *ep,
void *buff,
int length)
{
@@ -939,7 +935,7 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "%s: buff %p, len %d\n", __func__, buff, length);
- req = s3c_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC);
+ req = dwc2_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC);
hsotg->ep0_reply = req;
if (!req) {
dev_warn(hsotg->dev, "%s: cannot alloc req\n", __func__);
@@ -953,12 +949,12 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
* STATUS stage.
*/
req->zero = 0;
- req->complete = s3c_hsotg_complete_oursetup;
+ req->complete = dwc2_hsotg_complete_oursetup;
if (length)
memcpy(req->buf, buff, length);
- ret = s3c_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC);
+ ret = dwc2_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC);
if (ret) {
dev_warn(hsotg->dev, "%s: cannot queue req\n", __func__);
return ret;
@@ -968,15 +964,15 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
}
/**
- * s3c_hsotg_process_req_status - process request GET_STATUS
+ * dwc2_hsotg_process_req_status - process request GET_STATUS
* @hsotg: The device state
* @ctrl: USB control request
*/
-static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
+static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
- struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
- struct s3c_hsotg_ep *ep;
+ struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
+ struct dwc2_hsotg_ep *ep;
__le16 reply;
int ret;
@@ -1013,7 +1009,7 @@ static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
if (le16_to_cpu(ctrl->wLength) != 2)
return -EINVAL;
- ret = s3c_hsotg_send_reply(hsotg, ep0, &reply, 2);
+ ret = dwc2_hsotg_send_reply(hsotg, ep0, &reply, 2);
if (ret) {
dev_err(hsotg->dev, "%s: failed to send reply\n", __func__);
return ret;
@@ -1022,7 +1018,7 @@ static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
return 1;
}
-static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value);
+static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value);
/**
* get_ep_head - return the first request on the endpoint
@@ -1030,27 +1026,27 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value);
*
* Get the first request on the endpoint.
*/
-static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep)
+static struct dwc2_hsotg_req *get_ep_head(struct dwc2_hsotg_ep *hs_ep)
{
if (list_empty(&hs_ep->queue))
return NULL;
- return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue);
+ return list_first_entry(&hs_ep->queue, struct dwc2_hsotg_req, queue);
}
/**
- * s3c_hsotg_process_req_feature - process request {SET,CLEAR}_FEATURE
+ * dwc2_hsotg_process_req_feature - process request {SET,CLEAR}_FEATURE
* @hsotg: The device state
* @ctrl: USB control request
*/
-static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
+static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
- struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
- struct s3c_hsotg_req *hs_req;
+ struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
+ struct dwc2_hsotg_req *hs_req;
bool restart;
bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE);
- struct s3c_hsotg_ep *ep;
+ struct dwc2_hsotg_ep *ep;
int ret;
bool halted;
u32 recip;
@@ -1074,7 +1070,7 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
return -EINVAL;
hsotg->test_mode = wIndex >> 8;
- ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
+ ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
if (ret) {
dev_err(hsotg->dev,
"%s: failed to send reply\n", __func__);
@@ -1098,9 +1094,9 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
case USB_ENDPOINT_HALT:
halted = ep->halted;
- s3c_hsotg_ep_sethalt(&ep->ep, set);
+ dwc2_hsotg_ep_sethalt(&ep->ep, set);
- ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
+ ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
if (ret) {
dev_err(hsotg->dev,
"%s: failed to send reply\n", __func__);
@@ -1134,7 +1130,7 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
restart = !list_empty(&ep->queue);
if (restart) {
hs_req = get_ep_head(ep);
- s3c_hsotg_start_req(hsotg, ep,
+ dwc2_hsotg_start_req(hsotg, ep,
hs_req, false);
}
}
@@ -1152,17 +1148,17 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
return 1;
}
-static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg);
+static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg);
/**
- * s3c_hsotg_stall_ep0 - stall ep0
+ * dwc2_hsotg_stall_ep0 - stall ep0
* @hsotg: The device state
*
* Set stall for ep0 as response for setup request.
*/
-static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
{
- struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
+ struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
u32 reg;
u32 ctrl;
@@ -1174,24 +1170,24 @@ static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
* taken effect, so no need to clear later.
*/
- ctrl = readl(hsotg->regs + reg);
+ ctrl = dwc2_readl(hsotg->regs + reg);
ctrl |= DXEPCTL_STALL;
ctrl |= DXEPCTL_CNAK;
- writel(ctrl, hsotg->regs + reg);
+ dwc2_writel(ctrl, hsotg->regs + reg);
dev_dbg(hsotg->dev,
"written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n",
- ctrl, reg, readl(hsotg->regs + reg));
+ ctrl, reg, dwc2_readl(hsotg->regs + reg));
/*
* complete won't be called, so we enqueue
* setup request here
*/
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_enqueue_setup(hsotg);
}
/**
- * s3c_hsotg_process_control - process a control request
+ * dwc2_hsotg_process_control - process a control request
* @hsotg: The device state
* @ctrl: The control request received
*
@@ -1199,16 +1195,17 @@ static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
* needs to work out what to do next (and whether to pass it on to the
* gadget driver).
*/
-static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
+static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
- struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
+ struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
int ret = 0;
u32 dcfg;
- dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n",
- ctrl->bRequest, ctrl->bRequestType,
- ctrl->wValue, ctrl->wLength);
+ dev_dbg(hsotg->dev,
+ "ctrl Type=%02x, Req=%02x, V=%04x, I=%04x, L=%04x\n",
+ ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+ ctrl->wIndex, ctrl->wLength);
if (ctrl->wLength == 0) {
ep0->dir_in = 1;
@@ -1225,24 +1222,24 @@ static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
switch (ctrl->bRequest) {
case USB_REQ_SET_ADDRESS:
hsotg->connected = 1;
- dcfg = readl(hsotg->regs + DCFG);
+ dcfg = dwc2_readl(hsotg->regs + DCFG);
dcfg &= ~DCFG_DEVADDR_MASK;
dcfg |= (le16_to_cpu(ctrl->wValue) <<
DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK;
- writel(dcfg, hsotg->regs + DCFG);
+ dwc2_writel(dcfg, hsotg->regs + DCFG);
dev_info(hsotg->dev, "new address %d\n", ctrl->wValue);
- ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
+ ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
return;
case USB_REQ_GET_STATUS:
- ret = s3c_hsotg_process_req_status(hsotg, ctrl);
+ ret = dwc2_hsotg_process_req_status(hsotg, ctrl);
break;
case USB_REQ_CLEAR_FEATURE:
case USB_REQ_SET_FEATURE:
- ret = s3c_hsotg_process_req_feature(hsotg, ctrl);
+ ret = dwc2_hsotg_process_req_feature(hsotg, ctrl);
break;
}
}
@@ -1263,21 +1260,21 @@ static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
*/
if (ret < 0)
- s3c_hsotg_stall_ep0(hsotg);
+ dwc2_hsotg_stall_ep0(hsotg);
}
/**
- * s3c_hsotg_complete_setup - completion of a setup transfer
+ * dwc2_hsotg_complete_setup - completion of a setup transfer
* @ep: The endpoint the request was on.
* @req: The request completed.
*
* Called on completion of any requests the driver itself submitted for
* EP0 setup packets
*/
-static void s3c_hsotg_complete_setup(struct usb_ep *ep,
+static void dwc2_hsotg_complete_setup(struct usb_ep *ep,
struct usb_request *req)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
if (req->status < 0) {
@@ -1287,23 +1284,23 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
spin_lock(&hsotg->lock);
if (req->actual == 0)
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_enqueue_setup(hsotg);
else
- s3c_hsotg_process_control(hsotg, req->buf);
+ dwc2_hsotg_process_control(hsotg, req->buf);
spin_unlock(&hsotg->lock);
}
/**
- * s3c_hsotg_enqueue_setup - start a request for EP0 packets
+ * dwc2_hsotg_enqueue_setup - start a request for EP0 packets
* @hsotg: The device state.
*
* Enqueue a request on EP0 if necessary to received any SETUP packets
* received from the host.
*/
-static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
{
struct usb_request *req = hsotg->ctrl_req;
- struct s3c_hsotg_req *hs_req = our_req(req);
+ struct dwc2_hsotg_req *hs_req = our_req(req);
int ret;
dev_dbg(hsotg->dev, "%s: queueing setup request\n", __func__);
@@ -1311,7 +1308,7 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
req->zero = 0;
req->length = 8;
req->buf = hsotg->ctrl_buff;
- req->complete = s3c_hsotg_complete_setup;
+ req->complete = dwc2_hsotg_complete_setup;
if (!list_empty(&hs_req->queue)) {
dev_dbg(hsotg->dev, "%s already queued???\n", __func__);
@@ -1322,7 +1319,7 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
hsotg->eps_out[0]->send_zlp = 0;
hsotg->ep0_state = DWC2_EP0_SETUP;
- ret = s3c_hsotg_ep_queue(&hsotg->eps_out[0]->ep, req, GFP_ATOMIC);
+ ret = dwc2_hsotg_ep_queue(&hsotg->eps_out[0]->ep, req, GFP_ATOMIC);
if (ret < 0) {
dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret);
/*
@@ -1332,8 +1329,8 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
}
}
-static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep)
+static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep)
{
u32 ctrl;
u8 index = hs_ep->index;
@@ -1347,19 +1344,19 @@ static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
index);
- writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
- DXEPTSIZ_XFERSIZE(0), hsotg->regs +
- epsiz_reg);
+ dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+ DXEPTSIZ_XFERSIZE(0), hsotg->regs +
+ epsiz_reg);
- ctrl = readl(hsotg->regs + epctl_reg);
+ ctrl = dwc2_readl(hsotg->regs + epctl_reg);
ctrl |= DXEPCTL_CNAK; /* clear NAK set by core */
ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
ctrl |= DXEPCTL_USBACTEP;
- writel(ctrl, hsotg->regs + epctl_reg);
+ dwc2_writel(ctrl, hsotg->regs + epctl_reg);
}
/**
- * s3c_hsotg_complete_request - complete a request given to us
+ * dwc2_hsotg_complete_request - complete a request given to us
* @hsotg: The device state.
* @hs_ep: The endpoint the request was on.
* @hs_req: The request to complete.
@@ -1371,9 +1368,9 @@ static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
*
* Note, expects the ep to already be locked as appropriate.
*/
-static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep,
- struct s3c_hsotg_req *hs_req,
+static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep,
+ struct dwc2_hsotg_req *hs_req,
int result)
{
bool restart;
@@ -1394,14 +1391,14 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
if (hs_req->req.status == -EINPROGRESS)
hs_req->req.status = result;
- s3c_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req);
+ if (using_dma(hsotg))
+ dwc2_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
+
+ dwc2_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req);
hs_ep->req = NULL;
list_del_init(&hs_req->queue);
- if (using_dma(hsotg))
- s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
-
/*
* call the complete request with the locks off, just in case the
* request tries to queue more work for this endpoint.
@@ -1423,13 +1420,13 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
restart = !list_empty(&hs_ep->queue);
if (restart) {
hs_req = get_ep_head(hs_ep);
- s3c_hsotg_start_req(hsotg, hs_ep, hs_req, false);
+ dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, false);
}
}
}
/**
- * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint
+ * dwc2_hsotg_rx_data - receive data from the FIFO for an endpoint
* @hsotg: The device state.
* @ep_idx: The endpoint index for the data
* @size: The size of data in the fifo, in bytes
@@ -1438,10 +1435,10 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
* endpoint, so sort out whether we need to read the data into a request
* that has been made for that endpoint.
*/
-static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
+static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
{
- struct s3c_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx];
- struct s3c_hsotg_req *hs_req = hs_ep->req;
+ struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx];
+ struct dwc2_hsotg_req *hs_req = hs_ep->req;
void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx);
int to_read;
int max_req;
@@ -1449,7 +1446,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
if (!hs_req) {
- u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
+ u32 epctl = dwc2_readl(hsotg->regs + DOEPCTL(ep_idx));
int ptr;
dev_dbg(hsotg->dev,
@@ -1458,7 +1455,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
/* dump the data from the FIFO, we've nothing we can do */
for (ptr = 0; ptr < size; ptr += 4)
- (void)readl(fifo);
+ (void)dwc2_readl(fifo);
return;
}
@@ -1492,7 +1489,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
}
/**
- * s3c_hsotg_ep0_zlp - send/receive zero-length packet on control endpoint
+ * dwc2_hsotg_ep0_zlp - send/receive zero-length packet on control endpoint
* @hsotg: The device instance
* @dir_in: If IN zlp
*
@@ -1503,17 +1500,30 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
* currently believed that we do not need to wait for any space in
* the TxFIFO.
*/
-static void s3c_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
+static void dwc2_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
{
/* eps_out[0] is used in both directions */
hsotg->eps_out[0]->dir_in = dir_in;
hsotg->ep0_state = dir_in ? DWC2_EP0_STATUS_IN : DWC2_EP0_STATUS_OUT;
- s3c_hsotg_program_zlp(hsotg, hsotg->eps_out[0]);
+ dwc2_hsotg_program_zlp(hsotg, hsotg->eps_out[0]);
+}
+
+static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg,
+ u32 epctl_reg)
+{
+ u32 ctrl;
+
+ ctrl = dwc2_readl(hsotg->regs + epctl_reg);
+ if (ctrl & DXEPCTL_EOFRNUM)
+ ctrl |= DXEPCTL_SETEVENFR;
+ else
+ ctrl |= DXEPCTL_SETODDFR;
+ dwc2_writel(ctrl, hsotg->regs + epctl_reg);
}
/**
- * s3c_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO
+ * dwc2_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO
* @hsotg: The device instance
* @epnum: The endpoint received from
*
@@ -1521,11 +1531,11 @@ static void s3c_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
* transfer for an OUT endpoint has been completed, either by a short
* packet or by the finish of a transfer.
*/
-static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
+static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
{
- u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum));
- struct s3c_hsotg_ep *hs_ep = hsotg->eps_out[epnum];
- struct s3c_hsotg_req *hs_req = hs_ep->req;
+ u32 epsize = dwc2_readl(hsotg->regs + DOEPTSIZ(epnum));
+ struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[epnum];
+ struct dwc2_hsotg_req *hs_req = hs_ep->req;
struct usb_request *req = &hs_req->req;
unsigned size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
int result = 0;
@@ -1537,8 +1547,8 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
if (epnum == 0 && hsotg->ep0_state == DWC2_EP0_STATUS_OUT) {
dev_dbg(hsotg->dev, "zlp packet received\n");
- s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+ dwc2_hsotg_enqueue_setup(hsotg);
return;
}
@@ -1562,7 +1572,7 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
/* if there is more request to do, schedule new transfer */
if (req->actual < req->length && size_left == 0) {
- s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
+ dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, true);
return;
}
@@ -1578,24 +1588,34 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
if (epnum == 0 && hsotg->ep0_state == DWC2_EP0_DATA_OUT) {
/* Move to STATUS IN */
- s3c_hsotg_ep0_zlp(hsotg, true);
+ dwc2_hsotg_ep0_zlp(hsotg, true);
return;
}
- s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
+ /*
+ * Slave mode OUT transfers do not go through XferComplete so
+ * adjust the ISOC parity here.
+ */
+ if (!using_dma(hsotg)) {
+ hs_ep->has_correct_parity = 1;
+ if (hs_ep->isochronous && hs_ep->interval == 1)
+ dwc2_hsotg_change_ep_iso_parity(hsotg, DOEPCTL(epnum));
+ }
+
+ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
}
/**
- * s3c_hsotg_read_frameno - read current frame number
+ * dwc2_hsotg_read_frameno - read current frame number
* @hsotg: The device instance
*
* Return the current frame number
*/
-static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
+static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
{
u32 dsts;
- dsts = readl(hsotg->regs + DSTS);
+ dsts = dwc2_readl(hsotg->regs + DSTS);
dsts &= DSTS_SOFFN_MASK;
dsts >>= DSTS_SOFFN_SHIFT;
@@ -1603,7 +1623,7 @@ static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
}
/**
- * s3c_hsotg_handle_rx - RX FIFO has data
+ * dwc2_hsotg_handle_rx - RX FIFO has data
* @hsotg: The device instance
*
* The IRQ handler has detected that the RX FIFO has some data in it
@@ -1618,9 +1638,9 @@ static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
* as the actual data should be sent to the memory directly and we turn
* on the completion interrupts to get notifications of transfer completion.
*/
-static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
{
- u32 grxstsr = readl(hsotg->regs + GRXSTSP);
+ u32 grxstsr = dwc2_readl(hsotg->regs + GRXSTSP);
u32 epnum, status, size;
WARN_ON(using_dma(hsotg));
@@ -1641,55 +1661,55 @@ static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
case GRXSTS_PKTSTS_OUTDONE:
dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n",
- s3c_hsotg_read_frameno(hsotg));
+ dwc2_hsotg_read_frameno(hsotg));
if (!using_dma(hsotg))
- s3c_hsotg_handle_outdone(hsotg, epnum);
+ dwc2_hsotg_handle_outdone(hsotg, epnum);
break;
case GRXSTS_PKTSTS_SETUPDONE:
dev_dbg(hsotg->dev,
"SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
- s3c_hsotg_read_frameno(hsotg),
- readl(hsotg->regs + DOEPCTL(0)));
+ dwc2_hsotg_read_frameno(hsotg),
+ dwc2_readl(hsotg->regs + DOEPCTL(0)));
/*
- * Call s3c_hsotg_handle_outdone here if it was not called from
+ * Call dwc2_hsotg_handle_outdone here if it was not called from
* GRXSTS_PKTSTS_OUTDONE. That is, if the core didn't
* generate GRXSTS_PKTSTS_OUTDONE for setup packet.
*/
if (hsotg->ep0_state == DWC2_EP0_SETUP)
- s3c_hsotg_handle_outdone(hsotg, epnum);
+ dwc2_hsotg_handle_outdone(hsotg, epnum);
break;
case GRXSTS_PKTSTS_OUTRX:
- s3c_hsotg_rx_data(hsotg, epnum, size);
+ dwc2_hsotg_rx_data(hsotg, epnum, size);
break;
case GRXSTS_PKTSTS_SETUPRX:
dev_dbg(hsotg->dev,
"SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
- s3c_hsotg_read_frameno(hsotg),
- readl(hsotg->regs + DOEPCTL(0)));
+ dwc2_hsotg_read_frameno(hsotg),
+ dwc2_readl(hsotg->regs + DOEPCTL(0)));
WARN_ON(hsotg->ep0_state != DWC2_EP0_SETUP);
- s3c_hsotg_rx_data(hsotg, epnum, size);
+ dwc2_hsotg_rx_data(hsotg, epnum, size);
break;
default:
dev_warn(hsotg->dev, "%s: unknown status %08x\n",
__func__, grxstsr);
- s3c_hsotg_dump(hsotg);
+ dwc2_hsotg_dump(hsotg);
break;
}
}
/**
- * s3c_hsotg_ep0_mps - turn max packet size into register setting
+ * dwc2_hsotg_ep0_mps - turn max packet size into register setting
* @mps: The maximum packet size in bytes.
*/
-static u32 s3c_hsotg_ep0_mps(unsigned int mps)
+static u32 dwc2_hsotg_ep0_mps(unsigned int mps)
{
switch (mps) {
case 64:
@@ -1708,7 +1728,7 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps)
}
/**
- * s3c_hsotg_set_ep_maxpacket - set endpoint's max-packet field
+ * dwc2_hsotg_set_ep_maxpacket - set endpoint's max-packet field
* @hsotg: The driver state.
* @ep: The index number of the endpoint
* @mps: The maximum packet size in bytes
@@ -1716,10 +1736,10 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps)
* Configure the maximum packet size for the given endpoint, updating
* the hardware control registers to reflect this.
*/
-static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
+static void dwc2_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
unsigned int ep, unsigned int mps, unsigned int dir_in)
{
- struct s3c_hsotg_ep *hs_ep;
+ struct dwc2_hsotg_ep *hs_ep;
void __iomem *regs = hsotg->regs;
u32 mpsval;
u32 mcval;
@@ -1731,7 +1751,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
if (ep == 0) {
/* EP0 is a special case */
- mpsval = s3c_hsotg_ep0_mps(mps);
+ mpsval = dwc2_hsotg_ep0_mps(mps);
if (mpsval > 3)
goto bad_mps;
hs_ep->ep.maxpacket = mps;
@@ -1748,15 +1768,15 @@ static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
}
if (dir_in) {
- reg = readl(regs + DIEPCTL(ep));
+ reg = dwc2_readl(regs + DIEPCTL(ep));
reg &= ~DXEPCTL_MPS_MASK;
reg |= mpsval;
- writel(reg, regs + DIEPCTL(ep));
+ dwc2_writel(reg, regs + DIEPCTL(ep));
} else {
- reg = readl(regs + DOEPCTL(ep));
+ reg = dwc2_readl(regs + DOEPCTL(ep));
reg &= ~DXEPCTL_MPS_MASK;
reg |= mpsval;
- writel(reg, regs + DOEPCTL(ep));
+ dwc2_writel(reg, regs + DOEPCTL(ep));
}
return;
@@ -1766,23 +1786,23 @@ bad_mps:
}
/**
- * s3c_hsotg_txfifo_flush - flush Tx FIFO
+ * dwc2_hsotg_txfifo_flush - flush Tx FIFO
* @hsotg: The driver state
* @idx: The index for the endpoint (0..15)
*/
-static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
+static void dwc2_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
{
int timeout;
int val;
- writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
- hsotg->regs + GRSTCTL);
+ dwc2_writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
+ hsotg->regs + GRSTCTL);
/* wait until the fifo is flushed */
timeout = 100;
while (1) {
- val = readl(hsotg->regs + GRSTCTL);
+ val = dwc2_readl(hsotg->regs + GRSTCTL);
if ((val & (GRSTCTL_TXFFLSH)) == 0)
break;
@@ -1799,17 +1819,17 @@ static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
}
/**
- * s3c_hsotg_trytx - check to see if anything needs transmitting
+ * dwc2_hsotg_trytx - check to see if anything needs transmitting
* @hsotg: The driver state
* @hs_ep: The driver endpoint to check.
*
* Check to see if there is a request that has data to send, and if so
* make an attempt to write data into the FIFO.
*/
-static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep)
+static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep)
{
- struct s3c_hsotg_req *hs_req = hs_ep->req;
+ struct dwc2_hsotg_req *hs_req = hs_ep->req;
if (!hs_ep->dir_in || !hs_req) {
/**
@@ -1817,7 +1837,7 @@ static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
* for endpoints, excepting ep0
*/
if (hs_ep->index != 0)
- s3c_hsotg_ctrl_epint(hsotg, hs_ep->index,
+ dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index,
hs_ep->dir_in, 0);
return 0;
}
@@ -1825,25 +1845,25 @@ static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
if (hs_req->req.actual < hs_req->req.length) {
dev_dbg(hsotg->dev, "trying to write more for ep%d\n",
hs_ep->index);
- return s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req);
+ return dwc2_hsotg_write_fifo(hsotg, hs_ep, hs_req);
}
return 0;
}
/**
- * s3c_hsotg_complete_in - complete IN transfer
+ * dwc2_hsotg_complete_in - complete IN transfer
* @hsotg: The device state.
* @hs_ep: The endpoint that has just completed.
*
* An IN transfer has been completed, update the transfer's state and then
* call the relevant completion routines.
*/
-static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep)
+static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep)
{
- struct s3c_hsotg_req *hs_req = hs_ep->req;
- u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
+ struct dwc2_hsotg_req *hs_req = hs_ep->req;
+ u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
int size_left, size_done;
if (!hs_req) {
@@ -1854,19 +1874,19 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
/* Finish ZLP handling for IN EP0 transactions */
if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_STATUS_IN) {
dev_dbg(hsotg->dev, "zlp packet sent\n");
- s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
if (hsotg->test_mode) {
int ret;
- ret = s3c_hsotg_set_test_mode(hsotg, hsotg->test_mode);
+ ret = dwc2_hsotg_set_test_mode(hsotg, hsotg->test_mode);
if (ret < 0) {
dev_dbg(hsotg->dev, "Invalid Test #%d\n",
hsotg->test_mode);
- s3c_hsotg_stall_ep0(hsotg);
+ dwc2_hsotg_stall_ep0(hsotg);
return;
}
}
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_enqueue_setup(hsotg);
return;
}
@@ -1895,13 +1915,13 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
if (!size_left && hs_req->req.actual < hs_req->req.length) {
dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
- s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
+ dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, true);
return;
}
/* Zlp for all endpoints, for ep0 only in DATA IN stage */
if (hs_ep->send_zlp) {
- s3c_hsotg_program_zlp(hsotg, hs_ep);
+ dwc2_hsotg_program_zlp(hsotg, hs_ep);
hs_ep->send_zlp = 0;
/* transfer will be completed on next complete interrupt */
return;
@@ -1909,36 +1929,36 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_DATA_IN) {
/* Move to STATUS OUT */
- s3c_hsotg_ep0_zlp(hsotg, false);
+ dwc2_hsotg_ep0_zlp(hsotg, false);
return;
}
- s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
}
/**
- * s3c_hsotg_epint - handle an in/out endpoint interrupt
+ * dwc2_hsotg_epint - handle an in/out endpoint interrupt
* @hsotg: The driver state
* @idx: The index for the endpoint (0..15)
* @dir_in: Set if this is an IN endpoint
*
* Process and clear any interrupt pending for an individual endpoint
*/
-static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
+static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
int dir_in)
{
- struct s3c_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in);
+ struct dwc2_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in);
u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx);
u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx);
u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx);
u32 ints;
u32 ctrl;
- ints = readl(hsotg->regs + epint_reg);
- ctrl = readl(hsotg->regs + epctl_reg);
+ ints = dwc2_readl(hsotg->regs + epint_reg);
+ ctrl = dwc2_readl(hsotg->regs + epctl_reg);
/* Clear endpoint interrupts */
- writel(ints, hsotg->regs + epint_reg);
+ dwc2_writel(ints, hsotg->regs + epint_reg);
if (!hs_ep) {
dev_err(hsotg->dev, "%s:Interrupt for unconfigured ep%d(%s)\n",
@@ -1954,35 +1974,31 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
ints &= ~DXEPINT_XFERCOMPL;
if (ints & DXEPINT_XFERCOMPL) {
- if (hs_ep->isochronous && hs_ep->interval == 1) {
- if (ctrl & DXEPCTL_EOFRNUM)
- ctrl |= DXEPCTL_SETEVENFR;
- else
- ctrl |= DXEPCTL_SETODDFR;
- writel(ctrl, hsotg->regs + epctl_reg);
- }
+ hs_ep->has_correct_parity = 1;
+ if (hs_ep->isochronous && hs_ep->interval == 1)
+ dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
dev_dbg(hsotg->dev,
"%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n",
- __func__, readl(hsotg->regs + epctl_reg),
- readl(hsotg->regs + epsiz_reg));
+ __func__, dwc2_readl(hsotg->regs + epctl_reg),
+ dwc2_readl(hsotg->regs + epsiz_reg));
/*
* we get OutDone from the FIFO, so we only need to look
* at completing IN requests here
*/
if (dir_in) {
- s3c_hsotg_complete_in(hsotg, hs_ep);
+ dwc2_hsotg_complete_in(hsotg, hs_ep);
if (idx == 0 && !hs_ep->req)
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_enqueue_setup(hsotg);
} else if (using_dma(hsotg)) {
/*
* We're using DMA, we need to fire an OutDone here
* as we ignore the RXFIFO.
*/
- s3c_hsotg_handle_outdone(hsotg, idx);
+ dwc2_hsotg_handle_outdone(hsotg, idx);
}
}
@@ -1990,16 +2006,16 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
if (dir_in) {
- int epctl = readl(hsotg->regs + epctl_reg);
+ int epctl = dwc2_readl(hsotg->regs + epctl_reg);
- s3c_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
+ dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
if ((epctl & DXEPCTL_STALL) &&
(epctl & DXEPCTL_EPTYPE_BULK)) {
- int dctl = readl(hsotg->regs + DCTL);
+ int dctl = dwc2_readl(hsotg->regs + DCTL);
dctl |= DCTL_CGNPINNAK;
- writel(dctl, hsotg->regs + DCTL);
+ dwc2_writel(dctl, hsotg->regs + DCTL);
}
}
}
@@ -2021,7 +2037,7 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
if (dir_in)
WARN_ON_ONCE(1);
else
- s3c_hsotg_handle_outdone(hsotg, 0);
+ dwc2_hsotg_handle_outdone(hsotg, 0);
}
}
@@ -2047,21 +2063,21 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
__func__, idx);
if (!using_dma(hsotg))
- s3c_hsotg_trytx(hsotg, hs_ep);
+ dwc2_hsotg_trytx(hsotg, hs_ep);
}
}
}
/**
- * s3c_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done)
+ * dwc2_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done)
* @hsotg: The device state.
*
* Handle updating the device settings after the enumeration phase has
* been completed.
*/
-static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
{
- u32 dsts = readl(hsotg->regs + DSTS);
+ u32 dsts = dwc2_readl(hsotg->regs + DSTS);
int ep0_mps = 0, ep_mps = 8;
/*
@@ -2113,23 +2129,23 @@ static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
if (ep0_mps) {
int i;
/* Initialize ep0 for both in and out directions */
- s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 1);
- s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 0);
+ dwc2_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 1);
+ dwc2_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 0);
for (i = 1; i < hsotg->num_of_eps; i++) {
if (hsotg->eps_in[i])
- s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 1);
+ dwc2_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 1);
if (hsotg->eps_out[i])
- s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 0);
+ dwc2_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 0);
}
}
/* ensure after enumeration our EP0 is active */
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_enqueue_setup(hsotg);
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- readl(hsotg->regs + DIEPCTL0),
- readl(hsotg->regs + DOEPCTL0));
+ dwc2_readl(hsotg->regs + DIEPCTL0),
+ dwc2_readl(hsotg->regs + DOEPCTL0));
}
/**
@@ -2142,34 +2158,34 @@ static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
* completed with the given result code.
*/
static void kill_all_requests(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *ep,
+ struct dwc2_hsotg_ep *ep,
int result)
{
- struct s3c_hsotg_req *req, *treq;
+ struct dwc2_hsotg_req *req, *treq;
unsigned size;
ep->req = NULL;
list_for_each_entry_safe(req, treq, &ep->queue, queue)
- s3c_hsotg_complete_request(hsotg, ep, req,
+ dwc2_hsotg_complete_request(hsotg, ep, req,
result);
if (!hsotg->dedicated_fifos)
return;
- size = (readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4;
+ size = (dwc2_readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4;
if (size < ep->fifo_size)
- s3c_hsotg_txfifo_flush(hsotg, ep->fifo_index);
+ dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
}
/**
- * s3c_hsotg_disconnect - disconnect service
+ * dwc2_hsotg_disconnect - disconnect service
* @hsotg: The device state.
*
* The device has been disconnected. Remove all current
* transactions and signal the gadget driver that this
* has happened.
*/
-void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
+void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
{
unsigned ep;
@@ -2189,16 +2205,17 @@ void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
}
call_gadget(hsotg, disconnect);
+ hsotg->lx_state = DWC2_L3;
}
/**
- * s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler
+ * dwc2_hsotg_irq_fifoempty - TX FIFO empty interrupt handler
* @hsotg: The device state:
* @periodic: True if this is a periodic FIFO interrupt
*/
-static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
+static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
{
- struct s3c_hsotg_ep *ep;
+ struct dwc2_hsotg_ep *ep;
int epno, ret;
/* look through for any more data to transmit */
@@ -2215,7 +2232,7 @@ static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
(!periodic && ep->periodic))
continue;
- ret = s3c_hsotg_trytx(hsotg, ep);
+ ret = dwc2_hsotg_trytx(hsotg, ep);
if (ret < 0)
break;
}
@@ -2227,12 +2244,12 @@ static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
GINTSTS_RXFLVL)
/**
- * s3c_hsotg_corereset - issue softreset to the core
+ * dwc2_hsotg_corereset - issue softreset to the core
* @hsotg: The device state
*
* Issue a soft reset to the core, and await the core finishing it.
*/
-static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
+static int dwc2_hsotg_corereset(struct dwc2_hsotg *hsotg)
{
int timeout;
u32 grstctl;
@@ -2240,11 +2257,11 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "resetting core\n");
/* issue soft reset */
- writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL);
+ dwc2_writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL);
timeout = 10000;
do {
- grstctl = readl(hsotg->regs + GRSTCTL);
+ grstctl = dwc2_readl(hsotg->regs + GRSTCTL);
} while ((grstctl & GRSTCTL_CSFTRST) && timeout-- > 0);
if (grstctl & GRSTCTL_CSFTRST) {
@@ -2255,7 +2272,7 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
timeout = 10000;
while (1) {
- u32 grstctl = readl(hsotg->regs + GRSTCTL);
+ u32 grstctl = dwc2_readl(hsotg->regs + GRSTCTL);
if (timeout-- < 0) {
dev_info(hsotg->dev,
@@ -2275,18 +2292,23 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
}
/**
- * s3c_hsotg_core_init - issue softreset to the core
+ * dwc2_hsotg_core_init - issue softreset to the core
* @hsotg: The device state
*
* Issue a soft reset to the core, and await the core finishing it.
*/
-void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
+void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
bool is_usb_reset)
{
+ u32 intmsk;
u32 val;
+ /* Kill any ep0 requests as controller will be reinitialized */
+ kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+
if (!is_usb_reset)
- s3c_hsotg_corereset(hsotg);
+ if (dwc2_hsotg_corereset(hsotg))
+ return;
/*
* we must now enable ep0 ready for host detection and then
@@ -2295,39 +2317,42 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
/* set the PLL on, remove the HNP/SRP and set the PHY */
val = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
- writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
+ dwc2_writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
(val << GUSBCFG_USBTRDTIM_SHIFT), hsotg->regs + GUSBCFG);
- s3c_hsotg_init_fifo(hsotg);
+ dwc2_hsotg_init_fifo(hsotg);
if (!is_usb_reset)
__orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
- writel(DCFG_EPMISCNT(1) | DCFG_DEVSPD_HS, hsotg->regs + DCFG);
+ dwc2_writel(DCFG_EPMISCNT(1) | DCFG_DEVSPD_HS, hsotg->regs + DCFG);
/* Clear any pending OTG interrupts */
- writel(0xffffffff, hsotg->regs + GOTGINT);
+ dwc2_writel(0xffffffff, hsotg->regs + GOTGINT);
/* Clear any pending interrupts */
- writel(0xffffffff, hsotg->regs + GINTSTS);
-
- writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
+ dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+ intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
- GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST |
- GINTSTS_RESETDET | GINTSTS_ENUMDONE |
- GINTSTS_OTGINT | GINTSTS_USBSUSP |
- GINTSTS_WKUPINT,
- hsotg->regs + GINTMSK);
+ GINTSTS_USBRST | GINTSTS_RESETDET |
+ GINTSTS_ENUMDONE | GINTSTS_OTGINT |
+ GINTSTS_USBSUSP | GINTSTS_WKUPINT |
+ GINTSTS_INCOMPL_SOIN | GINTSTS_INCOMPL_SOOUT;
+
+ if (hsotg->core_params->external_id_pin_ctl <= 0)
+ intmsk |= GINTSTS_CONIDSTSCHNG;
+
+ dwc2_writel(intmsk, hsotg->regs + GINTMSK);
if (using_dma(hsotg))
- writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
- (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT),
- hsotg->regs + GAHBCFG);
+ dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
+ (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT),
+ hsotg->regs + GAHBCFG);
else
- writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NP_TXF_EMP_LVL |
- GAHBCFG_P_TXF_EMP_LVL) : 0) |
- GAHBCFG_GLBL_INTR_EN,
- hsotg->regs + GAHBCFG);
+ dwc2_writel(((hsotg->dedicated_fifos) ?
+ (GAHBCFG_NP_TXF_EMP_LVL |
+ GAHBCFG_P_TXF_EMP_LVL) : 0) |
+ GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG);
/*
* If INTknTXFEmpMsk is enabled, it's important to disable ep interrupts
@@ -2335,7 +2360,7 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
* interrupts.
*/
- writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
+ dwc2_writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
DIEPMSK_TXFIFOEMPTY | DIEPMSK_INTKNTXFEMPMSK : 0) |
DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK |
DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
@@ -2346,20 +2371,20 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
* don't need XferCompl, we get that from RXFIFO in slave mode. In
* DMA mode we may need this.
*/
- writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
+ dwc2_writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
DIEPMSK_TIMEOUTMSK) : 0) |
DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK |
DOEPMSK_SETUPMSK,
hsotg->regs + DOEPMSK);
- writel(0, hsotg->regs + DAINTMSK);
+ dwc2_writel(0, hsotg->regs + DAINTMSK);
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- readl(hsotg->regs + DIEPCTL0),
- readl(hsotg->regs + DOEPCTL0));
+ dwc2_readl(hsotg->regs + DIEPCTL0),
+ dwc2_readl(hsotg->regs + DOEPCTL0));
/* enable in and out endpoint interrupts */
- s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT);
+ dwc2_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT);
/*
* Enable the RXFIFO when in slave mode, as this is how we collect
@@ -2367,11 +2392,11 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
* things we cannot process, so do not use it.
*/
if (!using_dma(hsotg))
- s3c_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL);
+ dwc2_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL);
/* Enable interrupts for EP0 in and out */
- s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
- s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
+ dwc2_hsotg_ctrl_epint(hsotg, 0, 0, 1);
+ dwc2_hsotg_ctrl_epint(hsotg, 0, 1, 1);
if (!is_usb_reset) {
__orr32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
@@ -2379,7 +2404,7 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
__bic32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
}
- dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL));
+ dev_dbg(hsotg->dev, "DCTL=0x%08x\n", dwc2_readl(hsotg->regs + DCTL));
/*
* DxEPCTL_USBActEp says RO in manual, but seems to be set by
@@ -2387,23 +2412,23 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
*/
/* set to read 1 8byte packet */
- writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+ dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
DXEPTSIZ_XFERSIZE(8), hsotg->regs + DOEPTSIZ0);
- writel(s3c_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
+ dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
DXEPCTL_CNAK | DXEPCTL_EPENA |
DXEPCTL_USBACTEP,
hsotg->regs + DOEPCTL0);
/* enable, but don't activate EP0in */
- writel(s3c_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
+ dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
- s3c_hsotg_enqueue_setup(hsotg);
+ dwc2_hsotg_enqueue_setup(hsotg);
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- readl(hsotg->regs + DIEPCTL0),
- readl(hsotg->regs + DOEPCTL0));
+ dwc2_readl(hsotg->regs + DIEPCTL0),
+ dwc2_readl(hsotg->regs + DOEPCTL0));
/* clear global NAKs */
val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
@@ -2414,27 +2439,27 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
/* must be at-least 3ms to allow bus to see disconnect */
mdelay(3);
- hsotg->last_rst = jiffies;
+ hsotg->lx_state = DWC2_L0;
}
-static void s3c_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
{
/* set the soft-disconnect bit */
__orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
}
-void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg)
+void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg)
{
/* remove the soft-disconnect and let's go */
__bic32(hsotg->regs + DCTL, DCTL_SFTDISCON);
}
/**
- * s3c_hsotg_irq - handle device interrupt
+ * dwc2_hsotg_irq - handle device interrupt
* @irq: The IRQ number triggered
* @pw: The pw value when registered the handler.
*/
-static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
+static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
{
struct dwc2_hsotg *hsotg = pw;
int retry_count = 8;
@@ -2443,49 +2468,18 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
spin_lock(&hsotg->lock);
irq_retry:
- gintsts = readl(hsotg->regs + GINTSTS);
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n",
__func__, gintsts, gintsts & gintmsk, gintmsk, retry_count);
gintsts &= gintmsk;
- if (gintsts & GINTSTS_ENUMDONE) {
- writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
-
- s3c_hsotg_irq_enumdone(hsotg);
- }
-
- if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
- u32 daint = readl(hsotg->regs + DAINT);
- u32 daintmsk = readl(hsotg->regs + DAINTMSK);
- u32 daint_out, daint_in;
- int ep;
-
- daint &= daintmsk;
- daint_out = daint >> DAINT_OUTEP_SHIFT;
- daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
-
- dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
-
- for (ep = 0; ep < hsotg->num_of_eps && daint_out;
- ep++, daint_out >>= 1) {
- if (daint_out & 1)
- s3c_hsotg_epint(hsotg, ep, 0);
- }
-
- for (ep = 0; ep < hsotg->num_of_eps && daint_in;
- ep++, daint_in >>= 1) {
- if (daint_in & 1)
- s3c_hsotg_epint(hsotg, ep, 1);
- }
- }
-
if (gintsts & GINTSTS_RESETDET) {
dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
- writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
/* This event must be used only if controller is suspended */
if (hsotg->lx_state == DWC2_L2) {
@@ -2496,27 +2490,50 @@ irq_retry:
if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
- u32 usb_status = readl(hsotg->regs + GOTGCTL);
+ u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+ u32 connected = hsotg->connected;
dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
- readl(hsotg->regs + GNPTXSTS));
+ dwc2_readl(hsotg->regs + GNPTXSTS));
- writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
/* Report disconnection if it is not already done. */
- s3c_hsotg_disconnect(hsotg);
+ dwc2_hsotg_disconnect(hsotg);
+
+ if (usb_status & GOTGCTL_BSESVLD && connected)
+ dwc2_hsotg_core_init_disconnected(hsotg, true);
+ }
- if (usb_status & GOTGCTL_BSESVLD) {
- if (time_after(jiffies, hsotg->last_rst +
- msecs_to_jiffies(200))) {
+ if (gintsts & GINTSTS_ENUMDONE) {
+ dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
- kill_all_requests(hsotg, hsotg->eps_out[0],
- -ECONNRESET);
+ dwc2_hsotg_irq_enumdone(hsotg);
+ }
- hsotg->lx_state = DWC2_L0;
- s3c_hsotg_core_init_disconnected(hsotg, true);
- }
+ if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
+ u32 daint = dwc2_readl(hsotg->regs + DAINT);
+ u32 daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+ u32 daint_out, daint_in;
+ int ep;
+
+ daint &= daintmsk;
+ daint_out = daint >> DAINT_OUTEP_SHIFT;
+ daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
+
+ dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
+
+ for (ep = 0; ep < hsotg->num_of_eps && daint_out;
+ ep++, daint_out >>= 1) {
+ if (daint_out & 1)
+ dwc2_hsotg_epint(hsotg, ep, 0);
+ }
+
+ for (ep = 0; ep < hsotg->num_of_eps && daint_in;
+ ep++, daint_in >>= 1) {
+ if (daint_in & 1)
+ dwc2_hsotg_epint(hsotg, ep, 1);
}
}
@@ -2531,8 +2548,8 @@ irq_retry:
* it needs re-enabling
*/
- s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
- s3c_hsotg_irq_fifoempty(hsotg, false);
+ dwc2_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
+ dwc2_hsotg_irq_fifoempty(hsotg, false);
}
if (gintsts & GINTSTS_PTXFEMP) {
@@ -2540,23 +2557,23 @@ irq_retry:
/* See note in GINTSTS_NPTxFEmp */
- s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
- s3c_hsotg_irq_fifoempty(hsotg, true);
+ dwc2_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
+ dwc2_hsotg_irq_fifoempty(hsotg, true);
}
if (gintsts & GINTSTS_RXFLVL) {
/*
* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
- * we need to retry s3c_hsotg_handle_rx if this is still
+ * we need to retry dwc2_hsotg_handle_rx if this is still
* set.
*/
- s3c_hsotg_handle_rx(hsotg);
+ dwc2_hsotg_handle_rx(hsotg);
}
if (gintsts & GINTSTS_ERLYSUSP) {
dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
- writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
}
/*
@@ -2568,17 +2585,51 @@ irq_retry:
if (gintsts & GINTSTS_GOUTNAKEFF) {
dev_info(hsotg->dev, "GOUTNakEff triggered\n");
- writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
+ dwc2_writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
- s3c_hsotg_dump(hsotg);
+ dwc2_hsotg_dump(hsotg);
}
if (gintsts & GINTSTS_GINNAKEFF) {
dev_info(hsotg->dev, "GINNakEff triggered\n");
- writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
+ dwc2_writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
+
+ dwc2_hsotg_dump(hsotg);
+ }
+
+ if (gintsts & GINTSTS_INCOMPL_SOIN) {
+ u32 idx, epctl_reg;
+ struct dwc2_hsotg_ep *hs_ep;
+
+ dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOIN\n", __func__);
+ for (idx = 1; idx < hsotg->num_of_eps; idx++) {
+ hs_ep = hsotg->eps_in[idx];
+
+ if (!hs_ep->isochronous || hs_ep->has_correct_parity)
+ continue;
+
+ epctl_reg = DIEPCTL(idx);
+ dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
+ }
+ dwc2_writel(GINTSTS_INCOMPL_SOIN, hsotg->regs + GINTSTS);
+ }
+
+ if (gintsts & GINTSTS_INCOMPL_SOOUT) {
+ u32 idx, epctl_reg;
+ struct dwc2_hsotg_ep *hs_ep;
- s3c_hsotg_dump(hsotg);
+ dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOOUT\n", __func__);
+ for (idx = 1; idx < hsotg->num_of_eps; idx++) {
+ hs_ep = hsotg->eps_out[idx];
+
+ if (!hs_ep->isochronous || hs_ep->has_correct_parity)
+ continue;
+
+ epctl_reg = DOEPCTL(idx);
+ dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
+ }
+ dwc2_writel(GINTSTS_INCOMPL_SOOUT, hsotg->regs + GINTSTS);
}
/*
@@ -2595,16 +2646,16 @@ irq_retry:
}
/**
- * s3c_hsotg_ep_enable - enable the given endpoint
+ * dwc2_hsotg_ep_enable - enable the given endpoint
* @ep: The USB endpint to configure
* @desc: The USB endpoint descriptor to configure with.
*
* This is called from the USB gadget code's usb_ep_enable().
*/
-static int s3c_hsotg_ep_enable(struct usb_ep *ep,
+static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
unsigned long flags;
unsigned int index = hs_ep->index;
@@ -2631,10 +2682,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
mps = usb_endpoint_maxp(desc);
- /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */
+ /* note, we handle this here instead of dwc2_hsotg_set_ep_maxpacket */
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
- epctrl = readl(hsotg->regs + epctrl_reg);
+ epctrl = dwc2_readl(hsotg->regs + epctrl_reg);
dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
__func__, epctrl, epctrl_reg);
@@ -2660,13 +2711,14 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
epctrl |= DXEPCTL_SNAK;
/* update the endpoint state */
- s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in);
+ dwc2_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in);
/* default, set to non-periodic */
hs_ep->isochronous = 0;
hs_ep->periodic = 0;
hs_ep->halted = 0;
hs_ep->interval = desc->bInterval;
+ hs_ep->has_correct_parity = 0;
if (hs_ep->interval > 1 && hs_ep->mc > 1)
dev_err(hsotg->dev, "MC > 1 when interval is not 1\n");
@@ -2718,7 +2770,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
for (i = 1; i < hsotg->num_of_eps; ++i) {
if (hsotg->fifo_map & (1<<i))
continue;
- val = readl(hsotg->regs + DPTXFSIZN(i));
+ val = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
val = (val >> FIFOSIZE_DEPTH_SHIFT)*4;
if (val < size)
continue;
@@ -2747,12 +2799,12 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
__func__, epctrl);
- writel(epctrl, hsotg->regs + epctrl_reg);
+ dwc2_writel(epctrl, hsotg->regs + epctrl_reg);
dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x\n",
- __func__, readl(hsotg->regs + epctrl_reg));
+ __func__, dwc2_readl(hsotg->regs + epctrl_reg));
/* enable the endpoint interrupt */
- s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
+ dwc2_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
error:
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2760,12 +2812,12 @@ error:
}
/**
- * s3c_hsotg_ep_disable - disable given endpoint
+ * dwc2_hsotg_ep_disable - disable given endpoint
* @ep: The endpoint to disable.
*/
-static int s3c_hsotg_ep_disable(struct usb_ep *ep)
+static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
int dir_in = hs_ep->dir_in;
int index = hs_ep->index;
@@ -2788,16 +2840,16 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
hs_ep->fifo_index = 0;
hs_ep->fifo_size = 0;
- ctrl = readl(hsotg->regs + epctrl_reg);
+ ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
ctrl &= ~DXEPCTL_EPENA;
ctrl &= ~DXEPCTL_USBACTEP;
ctrl |= DXEPCTL_SNAK;
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
- writel(ctrl, hsotg->regs + epctrl_reg);
+ dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
/* disable endpoint interrupts */
- s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
+ dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
/* terminate all requests with shutdown */
kill_all_requests(hsotg, hs_ep, -ESHUTDOWN);
@@ -2811,9 +2863,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
* @ep: The endpoint to check.
* @test: The request to test if it is on the endpoint.
*/
-static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
+static bool on_list(struct dwc2_hsotg_ep *ep, struct dwc2_hsotg_req *test)
{
- struct s3c_hsotg_req *req, *treq;
+ struct dwc2_hsotg_req *req, *treq;
list_for_each_entry_safe(req, treq, &ep->queue, queue) {
if (req == test)
@@ -2823,15 +2875,88 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
return false;
}
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+ u32 bit, u32 timeout)
+{
+ u32 i;
+
+ for (i = 0; i < timeout; i++) {
+ if (dwc2_readl(hs_otg->regs + reg) & bit)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep)
+{
+ u32 epctrl_reg;
+ u32 epint_reg;
+
+ epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
+ DOEPCTL(hs_ep->index);
+ epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
+ DOEPINT(hs_ep->index);
+
+ dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
+ hs_ep->name);
+ if (hs_ep->dir_in) {
+ __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+ /* Wait for Nak effect */
+ if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
+ DXEPINT_INEPNAKEFF, 100))
+ dev_warn(hsotg->dev,
+ "%s: timeout DIEPINT.NAKEFF\n", __func__);
+ } else {
+ /* Clear any pending nak effect interrupt */
+ dwc2_writel(GINTSTS_GINNAKEFF, hsotg->regs + GINTSTS);
+
+ __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+
+ /* Wait for global nak to take effect */
+ if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+ GINTSTS_GINNAKEFF, 100))
+ dev_warn(hsotg->dev,
+ "%s: timeout GINTSTS.GINNAKEFF\n", __func__);
+ }
+
+ /* Disable ep */
+ __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+
+ /* Wait for ep to be disabled */
+ if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
+ dev_warn(hsotg->dev,
+ "%s: timeout DOEPCTL.EPDisable\n", __func__);
+
+ if (hs_ep->dir_in) {
+ if (hsotg->dedicated_fifos) {
+ dwc2_writel(GRSTCTL_TXFNUM(hs_ep->fifo_index) |
+ GRSTCTL_TXFFLSH, hsotg->regs + GRSTCTL);
+ /* Wait for fifo flush */
+ if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL,
+ GRSTCTL_TXFFLSH, 100))
+ dev_warn(hsotg->dev,
+ "%s: timeout flushing fifos\n",
+ __func__);
+ }
+ /* TODO: Flush shared tx fifo */
+ } else {
+ /* Remove global NAKs */
+ __bic32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+ }
+}
+
/**
- * s3c_hsotg_ep_dequeue - dequeue given endpoint
+ * dwc2_hsotg_ep_dequeue - dequeue given endpoint
* @ep: The endpoint to dequeue.
* @req: The request to be removed from a queue.
*/
-static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
+static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
- struct s3c_hsotg_req *hs_req = our_req(req);
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_req *hs_req = our_req(req);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hs = hs_ep->parent;
unsigned long flags;
@@ -2844,20 +2969,24 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
return -EINVAL;
}
- s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
+ /* Dequeue already started request */
+ if (req == &hs_ep->req->req)
+ dwc2_hsotg_ep_stop_xfr(hs, hs_ep);
+
+ dwc2_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
spin_unlock_irqrestore(&hs->lock, flags);
return 0;
}
/**
- * s3c_hsotg_ep_sethalt - set halt on a given endpoint
+ * dwc2_hsotg_ep_sethalt - set halt on a given endpoint
* @ep: The endpoint to set halt.
* @value: Set or unset the halt.
*/
-static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
+static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hs = hs_ep->parent;
int index = hs_ep->index;
u32 epreg;
@@ -2868,7 +2997,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
if (index == 0) {
if (value)
- s3c_hsotg_stall_ep0(hs);
+ dwc2_hsotg_stall_ep0(hs);
else
dev_warn(hs->dev,
"%s: can't clear halt on ep0\n", __func__);
@@ -2877,7 +3006,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
if (hs_ep->dir_in) {
epreg = DIEPCTL(index);
- epctl = readl(hs->regs + epreg);
+ epctl = dwc2_readl(hs->regs + epreg);
if (value) {
epctl |= DXEPCTL_STALL | DXEPCTL_SNAK;
@@ -2890,11 +3019,11 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
epctl |= DXEPCTL_SETD0PID;
}
- writel(epctl, hs->regs + epreg);
+ dwc2_writel(epctl, hs->regs + epreg);
} else {
epreg = DOEPCTL(index);
- epctl = readl(hs->regs + epreg);
+ epctl = dwc2_readl(hs->regs + epreg);
if (value)
epctl |= DXEPCTL_STALL;
@@ -2905,7 +3034,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
epctl |= DXEPCTL_SETD0PID;
}
- writel(epctl, hs->regs + epreg);
+ dwc2_writel(epctl, hs->regs + epreg);
}
hs_ep->halted = value;
@@ -2914,97 +3043,53 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
}
/**
- * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held
+ * dwc2_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held
* @ep: The endpoint to set halt.
* @value: Set or unset the halt.
*/
-static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
+static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
{
- struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hs = hs_ep->parent;
unsigned long flags = 0;
int ret = 0;
spin_lock_irqsave(&hs->lock, flags);
- ret = s3c_hsotg_ep_sethalt(ep, value);
+ ret = dwc2_hsotg_ep_sethalt(ep, value);
spin_unlock_irqrestore(&hs->lock, flags);
return ret;
}
-static struct usb_ep_ops s3c_hsotg_ep_ops = {
- .enable = s3c_hsotg_ep_enable,
- .disable = s3c_hsotg_ep_disable,
- .alloc_request = s3c_hsotg_ep_alloc_request,
- .free_request = s3c_hsotg_ep_free_request,
- .queue = s3c_hsotg_ep_queue_lock,
- .dequeue = s3c_hsotg_ep_dequeue,
- .set_halt = s3c_hsotg_ep_sethalt_lock,
+static struct usb_ep_ops dwc2_hsotg_ep_ops = {
+ .enable = dwc2_hsotg_ep_enable,
+ .disable = dwc2_hsotg_ep_disable,
+ .alloc_request = dwc2_hsotg_ep_alloc_request,
+ .free_request = dwc2_hsotg_ep_free_request,
+ .queue = dwc2_hsotg_ep_queue_lock,
+ .dequeue = dwc2_hsotg_ep_dequeue,
+ .set_halt = dwc2_hsotg_ep_sethalt_lock,
/* note, don't believe we have any call for the fifo routines */
};
/**
- * s3c_hsotg_phy_enable - enable platform phy dev
- * @hsotg: The driver state
- *
- * A wrapper for platform code responsible for controlling
- * low-level USB code
- */
-static void s3c_hsotg_phy_enable(struct dwc2_hsotg *hsotg)
-{
- struct platform_device *pdev = to_platform_device(hsotg->dev);
-
- dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
-
- if (hsotg->uphy)
- usb_phy_init(hsotg->uphy);
- else if (hsotg->plat && hsotg->plat->phy_init)
- hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
- else {
- phy_init(hsotg->phy);
- phy_power_on(hsotg->phy);
- }
-}
-
-/**
- * s3c_hsotg_phy_disable - disable platform phy dev
- * @hsotg: The driver state
- *
- * A wrapper for platform code responsible for controlling
- * low-level USB code
- */
-static void s3c_hsotg_phy_disable(struct dwc2_hsotg *hsotg)
-{
- struct platform_device *pdev = to_platform_device(hsotg->dev);
-
- if (hsotg->uphy)
- usb_phy_shutdown(hsotg->uphy);
- else if (hsotg->plat && hsotg->plat->phy_exit)
- hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
- else {
- phy_power_off(hsotg->phy);
- phy_exit(hsotg->phy);
- }
-}
-
-/**
- * s3c_hsotg_init - initalize the usb core
+ * dwc2_hsotg_init - initalize the usb core
* @hsotg: The driver state
*/
-static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
{
u32 trdtim;
/* unmask subset of endpoint interrupts */
- writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
- DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK,
- hsotg->regs + DIEPMSK);
+ dwc2_writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
+ DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK,
+ hsotg->regs + DIEPMSK);
- writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
- DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK,
- hsotg->regs + DOEPMSK);
+ dwc2_writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
+ DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK,
+ hsotg->regs + DOEPMSK);
- writel(0, hsotg->regs + DAINTMSK);
+ dwc2_writel(0, hsotg->regs + DAINTMSK);
/* Be in disconnected state until gadget is registered */
__orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
@@ -3012,14 +3097,14 @@ static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
/* setup fifos */
dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
- readl(hsotg->regs + GRXFSIZ),
- readl(hsotg->regs + GNPTXFSIZ));
+ dwc2_readl(hsotg->regs + GRXFSIZ),
+ dwc2_readl(hsotg->regs + GNPTXFSIZ));
- s3c_hsotg_init_fifo(hsotg);
+ dwc2_hsotg_init_fifo(hsotg);
/* set the PLL on, remove the HNP/SRP and set the PHY */
trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
- writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
+ dwc2_writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
(trdtim << GUSBCFG_USBTRDTIM_SHIFT),
hsotg->regs + GUSBCFG);
@@ -3028,14 +3113,14 @@ static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
}
/**
- * s3c_hsotg_udc_start - prepare the udc for work
+ * dwc2_hsotg_udc_start - prepare the udc for work
* @gadget: The usb gadget state
* @driver: The usb gadget driver
*
* Perform initialization to prepare udc device and driver
* to work.
*/
-static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
+static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
@@ -3060,7 +3145,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
return -EINVAL;
}
- mutex_lock(&hsotg->init_mutex);
WARN_ON(hsotg->driver);
driver->driver.bus = NULL;
@@ -3068,45 +3152,38 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
hsotg->gadget.dev.of_node = hsotg->dev->of_node;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
- clk_enable(hsotg->clk);
-
- ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- if (ret) {
- dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
- goto err;
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
+ ret = dwc2_lowlevel_hw_enable(hsotg);
+ if (ret)
+ goto err;
}
- s3c_hsotg_phy_enable(hsotg);
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
spin_lock_irqsave(&hsotg->lock, flags);
- s3c_hsotg_init(hsotg);
- s3c_hsotg_core_init_disconnected(hsotg, false);
+ dwc2_hsotg_init(hsotg);
+ dwc2_hsotg_core_init_disconnected(hsotg, false);
hsotg->enabled = 0;
spin_unlock_irqrestore(&hsotg->lock, flags);
dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
- mutex_unlock(&hsotg->init_mutex);
-
return 0;
err:
- mutex_unlock(&hsotg->init_mutex);
hsotg->driver = NULL;
return ret;
}
/**
- * s3c_hsotg_udc_stop - stop the udc
+ * dwc2_hsotg_udc_stop - stop the udc
* @gadget: The usb gadget state
* @driver: The usb gadget driver
*
* Stop udc hw block and stay tunned for future transmissions
*/
-static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
+static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
@@ -3115,14 +3192,12 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
if (!hsotg)
return -ENODEV;
- mutex_lock(&hsotg->init_mutex);
-
/* all endpoints should be shutdown */
for (ep = 1; ep < hsotg->num_of_eps; ep++) {
if (hsotg->eps_in[ep])
- s3c_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
if (hsotg->eps_out[ep])
- s3c_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
}
spin_lock_irqsave(&hsotg->lock, flags);
@@ -3135,64 +3210,63 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_peripheral(hsotg->uphy->otg, NULL);
- s3c_hsotg_phy_disable(hsotg);
- regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-
- clk_disable(hsotg->clk);
-
- mutex_unlock(&hsotg->init_mutex);
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+ dwc2_lowlevel_hw_disable(hsotg);
return 0;
}
/**
- * s3c_hsotg_gadget_getframe - read the frame number
+ * dwc2_hsotg_gadget_getframe - read the frame number
* @gadget: The usb gadget state
*
* Read the {micro} frame number
*/
-static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
+static int dwc2_hsotg_gadget_getframe(struct usb_gadget *gadget)
{
- return s3c_hsotg_read_frameno(to_hsotg(gadget));
+ return dwc2_hsotg_read_frameno(to_hsotg(gadget));
}
/**
- * s3c_hsotg_pullup - connect/disconnect the USB PHY
+ * dwc2_hsotg_pullup - connect/disconnect the USB PHY
* @gadget: The usb gadget state
* @is_on: Current state of the USB PHY
*
* Connect/Disconnect the USB PHY pullup
*/
-static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
+static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
- dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on);
+ dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on,
+ hsotg->op_state);
+
+ /* Don't modify pullup state while in host mode */
+ if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
+ hsotg->enabled = is_on;
+ return 0;
+ }
- mutex_lock(&hsotg->init_mutex);
spin_lock_irqsave(&hsotg->lock, flags);
if (is_on) {
- clk_enable(hsotg->clk);
hsotg->enabled = 1;
- s3c_hsotg_core_init_disconnected(hsotg, false);
- s3c_hsotg_core_connect(hsotg);
+ dwc2_hsotg_core_init_disconnected(hsotg, false);
+ dwc2_hsotg_core_connect(hsotg);
} else {
- s3c_hsotg_core_disconnect(hsotg);
- s3c_hsotg_disconnect(hsotg);
+ dwc2_hsotg_core_disconnect(hsotg);
+ dwc2_hsotg_disconnect(hsotg);
hsotg->enabled = 0;
- clk_disable(hsotg->clk);
}
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock_irqrestore(&hsotg->lock, flags);
- mutex_unlock(&hsotg->init_mutex);
return 0;
}
-static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
+static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags;
@@ -3200,23 +3274,22 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active);
spin_lock_irqsave(&hsotg->lock, flags);
+ /*
+ * If controller is hibernated, it must exit from hibernation
+ * before being initialized / de-initialized
+ */
+ if (hsotg->lx_state == DWC2_L2)
+ dwc2_exit_hibernation(hsotg, false);
+
if (is_active) {
- /*
- * If controller is hibernated, it must exit from hibernation
- * before being initialized
- */
- if (hsotg->lx_state == DWC2_L2) {
- dwc2_exit_hibernation(hsotg, false);
- hsotg->lx_state = DWC2_L0;
- }
- /* Kill any ep0 requests as controller will be reinitialized */
- kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
- s3c_hsotg_core_init_disconnected(hsotg, false);
+ hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+
+ dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
- s3c_hsotg_core_connect(hsotg);
+ dwc2_hsotg_core_connect(hsotg);
} else {
- s3c_hsotg_core_disconnect(hsotg);
- s3c_hsotg_disconnect(hsotg);
+ dwc2_hsotg_core_disconnect(hsotg);
+ dwc2_hsotg_disconnect(hsotg);
}
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -3224,13 +3297,13 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
}
/**
- * s3c_hsotg_vbus_draw - report bMaxPower field
+ * dwc2_hsotg_vbus_draw - report bMaxPower field
* @gadget: The usb gadget state
* @mA: Amount of current
*
* Report how much power the device may consume to the phy.
*/
-static int s3c_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
@@ -3239,17 +3312,17 @@ static int s3c_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
return usb_phy_set_power(hsotg->uphy, mA);
}
-static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
- .get_frame = s3c_hsotg_gadget_getframe,
- .udc_start = s3c_hsotg_udc_start,
- .udc_stop = s3c_hsotg_udc_stop,
- .pullup = s3c_hsotg_pullup,
- .vbus_session = s3c_hsotg_vbus_session,
- .vbus_draw = s3c_hsotg_vbus_draw,
+static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
+ .get_frame = dwc2_hsotg_gadget_getframe,
+ .udc_start = dwc2_hsotg_udc_start,
+ .udc_stop = dwc2_hsotg_udc_stop,
+ .pullup = dwc2_hsotg_pullup,
+ .vbus_session = dwc2_hsotg_vbus_session,
+ .vbus_draw = dwc2_hsotg_vbus_draw,
};
/**
- * s3c_hsotg_initep - initialise a single endpoint
+ * dwc2_hsotg_initep - initialise a single endpoint
* @hsotg: The device state.
* @hs_ep: The endpoint to be initialised.
* @epnum: The endpoint number
@@ -3258,8 +3331,8 @@ static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
* creation) to give to the gadget driver. Setup the endpoint name, any
* direction information and other state that may be required.
*/
-static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
- struct s3c_hsotg_ep *hs_ep,
+static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg,
+ struct dwc2_hsotg_ep *hs_ep,
int epnum,
bool dir_in)
{
@@ -3287,7 +3360,7 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
hs_ep->parent = hsotg;
hs_ep->ep.name = hs_ep->name;
usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT);
- hs_ep->ep.ops = &s3c_hsotg_ep_ops;
+ hs_ep->ep.ops = &dwc2_hsotg_ep_ops;
if (epnum == 0) {
hs_ep->ep.caps.type_control = true;
@@ -3310,19 +3383,19 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
if (using_dma(hsotg)) {
u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15);
if (dir_in)
- writel(next, hsotg->regs + DIEPCTL(epnum));
+ dwc2_writel(next, hsotg->regs + DIEPCTL(epnum));
else
- writel(next, hsotg->regs + DOEPCTL(epnum));
+ dwc2_writel(next, hsotg->regs + DOEPCTL(epnum));
}
}
/**
- * s3c_hsotg_hw_cfg - read HW configuration registers
+ * dwc2_hsotg_hw_cfg - read HW configuration registers
* @param: The device state
*
* Read the USB core HW configuration registers
*/
-static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
+static int dwc2_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
{
u32 cfg;
u32 ep_type;
@@ -3330,41 +3403,41 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
/* check hardware configuration */
- cfg = readl(hsotg->regs + GHWCFG2);
+ cfg = dwc2_readl(hsotg->regs + GHWCFG2);
hsotg->num_of_eps = (cfg >> GHWCFG2_NUM_DEV_EP_SHIFT) & 0xF;
/* Add ep0 */
hsotg->num_of_eps++;
- hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct s3c_hsotg_ep),
+ hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct dwc2_hsotg_ep),
GFP_KERNEL);
if (!hsotg->eps_in[0])
return -ENOMEM;
- /* Same s3c_hsotg_ep is used in both directions for ep0 */
+ /* Same dwc2_hsotg_ep is used in both directions for ep0 */
hsotg->eps_out[0] = hsotg->eps_in[0];
- cfg = readl(hsotg->regs + GHWCFG1);
+ cfg = dwc2_readl(hsotg->regs + GHWCFG1);
for (i = 1, cfg >>= 2; i < hsotg->num_of_eps; i++, cfg >>= 2) {
ep_type = cfg & 3;
/* Direction in or both */
if (!(ep_type & 2)) {
hsotg->eps_in[i] = devm_kzalloc(hsotg->dev,
- sizeof(struct s3c_hsotg_ep), GFP_KERNEL);
+ sizeof(struct dwc2_hsotg_ep), GFP_KERNEL);
if (!hsotg->eps_in[i])
return -ENOMEM;
}
/* Direction out or both */
if (!(ep_type & 1)) {
hsotg->eps_out[i] = devm_kzalloc(hsotg->dev,
- sizeof(struct s3c_hsotg_ep), GFP_KERNEL);
+ sizeof(struct dwc2_hsotg_ep), GFP_KERNEL);
if (!hsotg->eps_out[i])
return -ENOMEM;
}
}
- cfg = readl(hsotg->regs + GHWCFG3);
+ cfg = dwc2_readl(hsotg->regs + GHWCFG3);
hsotg->fifo_mem = (cfg >> GHWCFG3_DFIFO_DEPTH_SHIFT);
- cfg = readl(hsotg->regs + GHWCFG4);
+ cfg = dwc2_readl(hsotg->regs + GHWCFG4);
hsotg->dedicated_fifos = (cfg >> GHWCFG4_DED_FIFO_SHIFT) & 1;
dev_info(hsotg->dev, "EPs: %d, %s fifos, %d entries in SPRAM\n",
@@ -3375,10 +3448,10 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
}
/**
- * s3c_hsotg_dump - dump state of the udc
+ * dwc2_hsotg_dump - dump state of the udc
* @param: The device state
*/
-static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
{
#ifdef DEBUG
struct device *dev = hsotg->dev;
@@ -3387,19 +3460,19 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
int idx;
dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n",
- readl(regs + DCFG), readl(regs + DCTL),
- readl(regs + DIEPMSK));
+ dwc2_readl(regs + DCFG), dwc2_readl(regs + DCTL),
+ dwc2_readl(regs + DIEPMSK));
dev_info(dev, "GAHBCFG=0x%08x, GHWCFG1=0x%08x\n",
- readl(regs + GAHBCFG), readl(regs + GHWCFG1));
+ dwc2_readl(regs + GAHBCFG), dwc2_readl(regs + GHWCFG1));
dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
- readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ));
+ dwc2_readl(regs + GRXFSIZ), dwc2_readl(regs + GNPTXFSIZ));
/* show periodic fifo settings */
for (idx = 1; idx < hsotg->num_of_eps; idx++) {
- val = readl(regs + DPTXFSIZN(idx));
+ val = dwc2_readl(regs + DPTXFSIZN(idx));
dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx,
val >> FIFOSIZE_DEPTH_SHIFT,
val & FIFOSIZE_STARTADDR_MASK);
@@ -3408,26 +3481,26 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
for (idx = 0; idx < hsotg->num_of_eps; idx++) {
dev_info(dev,
"ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx,
- readl(regs + DIEPCTL(idx)),
- readl(regs + DIEPTSIZ(idx)),
- readl(regs + DIEPDMA(idx)));
+ dwc2_readl(regs + DIEPCTL(idx)),
+ dwc2_readl(regs + DIEPTSIZ(idx)),
+ dwc2_readl(regs + DIEPDMA(idx)));
- val = readl(regs + DOEPCTL(idx));
+ val = dwc2_readl(regs + DOEPCTL(idx));
dev_info(dev,
"ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n",
- idx, readl(regs + DOEPCTL(idx)),
- readl(regs + DOEPTSIZ(idx)),
- readl(regs + DOEPDMA(idx)));
+ idx, dwc2_readl(regs + DOEPCTL(idx)),
+ dwc2_readl(regs + DOEPTSIZ(idx)),
+ dwc2_readl(regs + DOEPDMA(idx)));
}
dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
- readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE));
+ dwc2_readl(regs + DVBUSDIS), dwc2_readl(regs + DVBUSPULSE));
#endif
}
#ifdef CONFIG_OF
-static void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg)
{
struct device_node *np = hsotg->dev->of_node;
u32 len = 0;
@@ -3468,7 +3541,7 @@ rx_fifo:
&hsotg->g_np_g_tx_fifo_sz);
}
#else
-static inline void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
+static inline void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
#endif
/**
@@ -3479,23 +3552,17 @@ static inline void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{
struct device *dev = hsotg->dev;
- struct s3c_hsotg_plat *plat = dev->platform_data;
int epnum;
int ret;
int i;
u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
- /* Set default UTMI width */
- hsotg->phyif = GUSBCFG_PHYIF16;
-
- s3c_hsotg_of_probe(hsotg);
-
/* Initialize to legacy fifo configuration values */
hsotg->g_rx_fifo_sz = 2048;
hsotg->g_np_g_tx_fifo_sz = 1024;
memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo));
/* Device tree specific probe */
- s3c_hsotg_of_probe(hsotg);
+ dwc2_hsotg_of_probe(hsotg);
/* Dump fifo information */
dev_dbg(dev, "NonPeriodic TXFIFO size: %d\n",
hsotg->g_np_g_tx_fifo_sz);
@@ -3503,70 +3570,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
for (i = 0; i < MAX_EPS_CHANNELS; i++)
dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i,
hsotg->g_tx_fifo_sz[i]);
- /*
- * If platform probe couldn't find a generic PHY or an old style
- * USB PHY, fall back to pdata
- */
- if (IS_ERR_OR_NULL(hsotg->phy) && IS_ERR_OR_NULL(hsotg->uphy)) {
- plat = dev_get_platdata(dev);
- if (!plat) {
- dev_err(dev,
- "no platform data or transceiver defined\n");
- return -EPROBE_DEFER;
- }
- hsotg->plat = plat;
- } else if (hsotg->phy) {
- /*
- * If using the generic PHY framework, check if the PHY bus
- * width is 8-bit and set the phyif appropriately.
- */
- if (phy_get_bus_width(hsotg->phy) == 8)
- hsotg->phyif = GUSBCFG_PHYIF8;
- }
-
- hsotg->clk = devm_clk_get(dev, "otg");
- if (IS_ERR(hsotg->clk)) {
- hsotg->clk = NULL;
- dev_dbg(dev, "cannot get otg clock\n");
- }
hsotg->gadget.max_speed = USB_SPEED_HIGH;
- hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
+ hsotg->gadget.ops = &dwc2_hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev);
if (hsotg->dr_mode == USB_DR_MODE_OTG)
hsotg->gadget.is_otg = 1;
-
- /* reset the system */
-
- ret = clk_prepare_enable(hsotg->clk);
- if (ret) {
- dev_err(dev, "failed to enable otg clk\n");
- goto err_clk;
- }
-
-
- /* regulators */
-
- for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
- hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
-
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- if (ret) {
- dev_err(dev, "failed to request supplies: %d\n", ret);
- goto err_clk;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
-
- if (ret) {
- dev_err(dev, "failed to enable supplies: %d\n", ret);
- goto err_clk;
- }
-
- /* usb phy enable */
- s3c_hsotg_phy_enable(hsotg);
+ else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+ hsotg->op_state = OTG_STATE_B_PERIPHERAL;
/*
* Force Device mode before initialization.
@@ -3581,14 +3592,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
*/
msleep(25);
- s3c_hsotg_corereset(hsotg);
- ret = s3c_hsotg_hw_cfg(hsotg);
+ dwc2_hsotg_corereset(hsotg);
+ ret = dwc2_hsotg_hw_cfg(hsotg);
if (ret) {
dev_err(hsotg->dev, "Hardware configuration failed: %d\n", ret);
- goto err_clk;
+ return ret;
}
- s3c_hsotg_init(hsotg);
+ dwc2_hsotg_init(hsotg);
/* Switch back to default configuration */
__bic32(hsotg->regs + GUSBCFG, GUSBCFG_FORCEDEVMODE);
@@ -3597,35 +3608,28 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
DWC2_CTRL_BUFF_SIZE, GFP_KERNEL);
if (!hsotg->ctrl_buff) {
dev_err(dev, "failed to allocate ctrl request buff\n");
- ret = -ENOMEM;
- goto err_supplies;
+ return -ENOMEM;
}
hsotg->ep0_buff = devm_kzalloc(hsotg->dev,
DWC2_CTRL_BUFF_SIZE, GFP_KERNEL);
if (!hsotg->ep0_buff) {
dev_err(dev, "failed to allocate ctrl reply buff\n");
- ret = -ENOMEM;
- goto err_supplies;
+ return -ENOMEM;
}
- ret = devm_request_irq(hsotg->dev, irq, s3c_hsotg_irq, IRQF_SHARED,
+ ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED,
dev_name(hsotg->dev), hsotg);
if (ret < 0) {
- s3c_hsotg_phy_disable(hsotg);
- clk_disable_unprepare(hsotg->clk);
- regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
dev_err(dev, "cannot claim IRQ for gadget\n");
- goto err_supplies;
+ return ret;
}
/* hsotg->num_of_eps holds number of EPs other than ep0 */
if (hsotg->num_of_eps == 0) {
dev_err(dev, "wrong number of EPs (zero)\n");
- ret = -EINVAL;
- goto err_supplies;
+ return -EINVAL;
}
/* setup endpoint information */
@@ -3635,71 +3639,49 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
/* allocate EP0 request */
- hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps_out[0]->ep,
+ hsotg->ctrl_req = dwc2_hsotg_ep_alloc_request(&hsotg->eps_out[0]->ep,
GFP_KERNEL);
if (!hsotg->ctrl_req) {
dev_err(dev, "failed to allocate ctrl req\n");
- ret = -ENOMEM;
- goto err_supplies;
+ return -ENOMEM;
}
/* initialise the endpoints now the core has been initialised */
for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) {
if (hsotg->eps_in[epnum])
- s3c_hsotg_initep(hsotg, hsotg->eps_in[epnum],
+ dwc2_hsotg_initep(hsotg, hsotg->eps_in[epnum],
epnum, 1);
if (hsotg->eps_out[epnum])
- s3c_hsotg_initep(hsotg, hsotg->eps_out[epnum],
+ dwc2_hsotg_initep(hsotg, hsotg->eps_out[epnum],
epnum, 0);
}
- /* disable power and clock */
- s3c_hsotg_phy_disable(hsotg);
-
- ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- if (ret) {
- dev_err(dev, "failed to disable supplies: %d\n", ret);
- goto err_supplies;
- }
-
ret = usb_add_gadget_udc(dev, &hsotg->gadget);
if (ret)
- goto err_supplies;
+ return ret;
- s3c_hsotg_dump(hsotg);
+ dwc2_hsotg_dump(hsotg);
return 0;
-
-err_supplies:
- s3c_hsotg_phy_disable(hsotg);
-err_clk:
- clk_disable_unprepare(hsotg->clk);
-
- return ret;
}
/**
- * s3c_hsotg_remove - remove function for hsotg driver
+ * dwc2_hsotg_remove - remove function for hsotg driver
* @pdev: The platform information for the driver
*/
-int s3c_hsotg_remove(struct dwc2_hsotg *hsotg)
+int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg)
{
usb_del_gadget_udc(&hsotg->gadget);
- clk_disable_unprepare(hsotg->clk);
return 0;
}
-int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)
+int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
{
unsigned long flags;
- int ret = 0;
if (hsotg->lx_state != DWC2_L0)
- return ret;
-
- mutex_lock(&hsotg->init_mutex);
+ return 0;
if (hsotg->driver) {
int ep;
@@ -3709,57 +3691,39 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)
spin_lock_irqsave(&hsotg->lock, flags);
if (hsotg->enabled)
- s3c_hsotg_core_disconnect(hsotg);
- s3c_hsotg_disconnect(hsotg);
+ dwc2_hsotg_core_disconnect(hsotg);
+ dwc2_hsotg_disconnect(hsotg);
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock_irqrestore(&hsotg->lock, flags);
- s3c_hsotg_phy_disable(hsotg);
-
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
if (hsotg->eps_in[ep])
- s3c_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
if (hsotg->eps_out[ep])
- s3c_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
}
-
- ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
- clk_disable(hsotg->clk);
}
- mutex_unlock(&hsotg->init_mutex);
-
- return ret;
+ return 0;
}
-int s3c_hsotg_resume(struct dwc2_hsotg *hsotg)
+int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg)
{
unsigned long flags;
- int ret = 0;
if (hsotg->lx_state == DWC2_L2)
- return ret;
-
- mutex_lock(&hsotg->init_mutex);
+ return 0;
if (hsotg->driver) {
dev_info(hsotg->dev, "resuming usb gadget %s\n",
hsotg->driver->driver.name);
- clk_enable(hsotg->clk);
- ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
- hsotg->supplies);
-
- s3c_hsotg_phy_enable(hsotg);
-
spin_lock_irqsave(&hsotg->lock, flags);
- s3c_hsotg_core_init_disconnected(hsotg, false);
+ dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
- s3c_hsotg_core_connect(hsotg);
+ dwc2_hsotg_core_connect(hsotg);
spin_unlock_irqrestore(&hsotg->lock, flags);
}
- mutex_unlock(&hsotg->init_mutex);
- return ret;
+ return 0;
}
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index f845c41fe9e5..571c21727ff9 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -80,10 +80,10 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg,
if (chan == NULL)
return;
- hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
- hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num));
- hctsiz = readl(hsotg->regs + HCTSIZ(chan->hc_num));
- hc_dma = readl(hsotg->regs + HCDMA(chan->hc_num));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
+ hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chan->hc_num));
+ hc_dma = dwc2_readl(hsotg->regs + HCDMA(chan->hc_num));
dev_dbg(hsotg->dev, " Assigned to channel %p:\n", chan);
dev_dbg(hsotg->dev, " hcchar 0x%08x, hcsplt 0x%08x\n",
@@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg,
list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
qtd_list_entry) {
- dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
+ dwc2_host_complete(hsotg, qtd, -ECONNRESET);
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
}
}
@@ -207,7 +207,7 @@ void dwc2_hcd_start(struct dwc2_hsotg *hsotg)
*/
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 |= HPRT0_RST;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
}
queue_delayed_work(hsotg->wq_otg, &hsotg->start_work,
@@ -228,11 +228,11 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
channel = hsotg->hc_ptr_array[i];
if (!list_empty(&channel->hc_list_entry))
continue;
- hcchar = readl(hsotg->regs + HCCHAR(i));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
if (hcchar & HCCHAR_CHENA) {
hcchar &= ~(HCCHAR_CHENA | HCCHAR_EPDIR);
hcchar |= HCCHAR_CHDIS;
- writel(hcchar, hsotg->regs + HCCHAR(i));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
}
}
}
@@ -241,11 +241,11 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
channel = hsotg->hc_ptr_array[i];
if (!list_empty(&channel->hc_list_entry))
continue;
- hcchar = readl(hsotg->regs + HCCHAR(i));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
if (hcchar & HCCHAR_CHENA) {
/* Halt the channel */
hcchar |= HCCHAR_CHDIS;
- writel(hcchar, hsotg->regs + HCCHAR(i));
+ dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
}
dwc2_hc_cleanup(hsotg, channel);
@@ -287,11 +287,11 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
* interrupt mask and status bits and disabling subsequent host
* channel interrupts.
*/
- intr = readl(hsotg->regs + GINTMSK);
+ intr = dwc2_readl(hsotg->regs + GINTMSK);
intr &= ~(GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT);
- writel(intr, hsotg->regs + GINTMSK);
+ dwc2_writel(intr, hsotg->regs + GINTMSK);
intr = GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT;
- writel(intr, hsotg->regs + GINTSTS);
+ dwc2_writel(intr, hsotg->regs + GINTSTS);
/*
* Turn off the vbus power only if the core has transitioned to device
@@ -301,7 +301,7 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
if (dwc2_is_device_mode(hsotg)) {
if (hsotg->op_state != OTG_STATE_A_SUSPEND) {
dev_dbg(hsotg->dev, "Disconnect: PortPower off\n");
- writel(0, hsotg->regs + HPRT0);
+ dwc2_writel(0, hsotg->regs + HPRT0);
}
dwc2_disable_host_interrupts(hsotg);
@@ -324,12 +324,13 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
*/
static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg)
{
- if (hsotg->lx_state == DWC2_L2) {
+ if (hsotg->bus_suspended) {
hsotg->flags.b.port_suspend_change = 1;
usb_hcd_resume_root_hub(hsotg->priv);
- } else {
- hsotg->flags.b.port_l1_change = 1;
}
+
+ if (hsotg->lx_state == DWC2_L1)
+ hsotg->flags.b.port_l1_change = 1;
}
/**
@@ -354,7 +355,7 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg)
/* Turn off the vbus power */
dev_dbg(hsotg->dev, "PortPower off\n");
- writel(0, hsotg->regs + HPRT0);
+ dwc2_writel(0, hsotg->regs + HPRT0);
}
/* Caller must hold driver lock */
@@ -378,7 +379,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
if ((dev_speed == USB_SPEED_LOW) &&
(hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) &&
(hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI)) {
- u32 hprt0 = readl(hsotg->regs + HPRT0);
+ u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
u32 prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
if (prtspd == HPRT0_SPD_FULL_SPEED)
@@ -397,7 +398,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
return retval;
}
- intr_mask = readl(hsotg->regs + GINTMSK);
+ intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
if (!(intr_mask & GINTSTS_SOF)) {
enum dwc2_transaction_type tr_type;
@@ -1070,7 +1071,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
if (dbg_perio())
dev_vdbg(hsotg->dev, "Queue periodic transactions\n");
- tx_status = readl(hsotg->regs + HPTXSTS);
+ tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1085,7 +1086,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
qh_ptr = hsotg->periodic_sched_assigned.next;
while (qh_ptr != &hsotg->periodic_sched_assigned) {
- tx_status = readl(hsotg->regs + HPTXSTS);
+ tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
if (qspcavail == 0) {
@@ -1145,7 +1146,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
}
if (hsotg->core_params->dma_enable <= 0) {
- tx_status = readl(hsotg->regs + HPTXSTS);
+ tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1168,9 +1169,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
* level to ensure that new requests are loaded as
* soon as possible.)
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk |= GINTSTS_PTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
} else {
/*
* Disable the Tx FIFO empty interrupt since there are
@@ -1179,9 +1180,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
* handlers to queue more transactions as transfer
* states change.
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk &= ~GINTSTS_PTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
}
}
}
@@ -1210,7 +1211,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
dev_vdbg(hsotg->dev, "Queue non-periodic transactions\n");
- tx_status = readl(hsotg->regs + GNPTXSTS);
+ tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1233,7 +1234,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
* available in the request queue or the Tx FIFO
*/
do {
- tx_status = readl(hsotg->regs + GNPTXSTS);
+ tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
if (hsotg->core_params->dma_enable <= 0 && qspcavail == 0) {
@@ -1270,7 +1271,7 @@ next:
} while (hsotg->non_periodic_qh_ptr != orig_qh_ptr);
if (hsotg->core_params->dma_enable <= 0) {
- tx_status = readl(hsotg->regs + GNPTXSTS);
+ tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1290,9 +1291,9 @@ next:
* level to ensure that new requests are loaded as
* soon as possible.)
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk |= GINTSTS_NPTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
} else {
/*
* Disable the Tx FIFO empty interrupt since there are
@@ -1301,9 +1302,9 @@ next:
* handlers to queue more transactions as transfer
* states change.
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk &= ~GINTSTS_NPTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
}
}
}
@@ -1341,10 +1342,10 @@ void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
* Ensure NP Tx FIFO empty interrupt is disabled when
* there are no non-periodic transfers to process
*/
- u32 gintmsk = readl(hsotg->regs + GINTMSK);
+ u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk &= ~GINTSTS_NPTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
}
}
}
@@ -1355,10 +1356,11 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
wf_otg);
u32 count = 0;
u32 gotgctl;
+ unsigned long flags;
dev_dbg(hsotg->dev, "%s()\n", __func__);
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
!!(gotgctl & GOTGCTL_CONID_B));
@@ -1382,8 +1384,10 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false, -1);
dwc2_enable_global_interrupts(hsotg);
- s3c_hsotg_core_init_disconnected(hsotg, false);
- s3c_hsotg_core_connect(hsotg);
+ spin_lock_irqsave(&hsotg->lock, flags);
+ dwc2_hsotg_core_init_disconnected(hsotg, false);
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+ dwc2_hsotg_core_connect(hsotg);
} else {
/* A-Device connector (Host Mode) */
dev_dbg(hsotg->dev, "connId A\n");
@@ -1421,11 +1425,12 @@ static void dwc2_wakeup_detected(unsigned long data)
hprt0 = dwc2_read_hprt0(hsotg);
dev_dbg(hsotg->dev, "Resume: HPRT0=%0x\n", hprt0);
hprt0 &= ~HPRT0_RES;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
- readl(hsotg->regs + HPRT0));
+ dwc2_readl(hsotg->regs + HPRT0));
dwc2_hcd_rem_wakeup(hsotg);
+ hsotg->bus_suspended = 0;
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
@@ -1451,30 +1456,35 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
spin_lock_irqsave(&hsotg->lock, flags);
if (windex == hsotg->otg_port && dwc2_host_is_b_hnp_enabled(hsotg)) {
- gotgctl = readl(hsotg->regs + GOTGCTL);
+ gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
gotgctl |= GOTGCTL_HSTSETHNPEN;
- writel(gotgctl, hsotg->regs + GOTGCTL);
+ dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
hsotg->op_state = OTG_STATE_A_SUSPEND;
}
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 |= HPRT0_SUSP;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
- /* Update lx_state */
- hsotg->lx_state = DWC2_L2;
+ hsotg->bus_suspended = 1;
- /* Suspend the Phy Clock */
- pcgctl = readl(hsotg->regs + PCGCTL);
- pcgctl |= PCGCTL_STOPPCLK;
- writel(pcgctl, hsotg->regs + PCGCTL);
- udelay(10);
+ /*
+ * If hibernation is supported, Phy clock will be suspended
+ * after registers are backuped.
+ */
+ if (!hsotg->core_params->hibernation) {
+ /* Suspend the Phy Clock */
+ pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+ pcgctl |= PCGCTL_STOPPCLK;
+ dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+ udelay(10);
+ }
/* For HNP the bus must be suspended for at least 200ms */
if (dwc2_host_is_b_hnp_enabled(hsotg)) {
- pcgctl = readl(hsotg->regs + PCGCTL);
+ pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgctl &= ~PCGCTL_STOPPCLK;
- writel(pcgctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -1484,6 +1494,44 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
}
}
+/* Must NOT be called with interrupt disabled or spinlock held */
+static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
+{
+ unsigned long flags;
+ u32 hprt0;
+ u32 pcgctl;
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+
+ /*
+ * If hibernation is supported, Phy clock is already resumed
+ * after registers restore.
+ */
+ if (!hsotg->core_params->hibernation) {
+ pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+ pcgctl &= ~PCGCTL_STOPPCLK;
+ dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+ usleep_range(20000, 40000);
+ spin_lock_irqsave(&hsotg->lock, flags);
+ }
+
+ hprt0 = dwc2_read_hprt0(hsotg);
+ hprt0 |= HPRT0_RES;
+ hprt0 &= ~HPRT0_SUSP;
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+ msleep(USB_RESUME_TIMEOUT);
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+ hprt0 = dwc2_read_hprt0(hsotg);
+ hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
+ hsotg->bus_suspended = 0;
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
/* Handles hub class-specific requests */
static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
u16 wvalue, u16 windex, char *buf, u16 wlength)
@@ -1523,23 +1571,15 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
"ClearPortFeature USB_PORT_FEAT_ENABLE\n");
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 |= HPRT0_ENA;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
break;
case USB_PORT_FEAT_SUSPEND:
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
- writel(0, hsotg->regs + PCGCTL);
- usleep_range(20000, 40000);
- hprt0 = dwc2_read_hprt0(hsotg);
- hprt0 |= HPRT0_RES;
- writel(hprt0, hsotg->regs + HPRT0);
- hprt0 &= ~HPRT0_SUSP;
- msleep(USB_RESUME_TIMEOUT);
-
- hprt0 &= ~HPRT0_RES;
- writel(hprt0, hsotg->regs + HPRT0);
+ if (hsotg->bus_suspended)
+ dwc2_port_resume(hsotg);
break;
case USB_PORT_FEAT_POWER:
@@ -1547,7 +1587,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
"ClearPortFeature USB_PORT_FEAT_POWER\n");
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 &= ~HPRT0_PWR;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
break;
case USB_PORT_FEAT_INDICATOR:
@@ -1668,7 +1708,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
break;
}
- hprt0 = readl(hsotg->regs + HPRT0);
+ hprt0 = dwc2_readl(hsotg->regs + HPRT0);
dev_vdbg(hsotg->dev, " HPRT0: 0x%08x\n", hprt0);
if (hprt0 & HPRT0_CONNSTS)
@@ -1733,18 +1773,18 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
"SetPortFeature - USB_PORT_FEAT_POWER\n");
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 |= HPRT0_PWR;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
break;
case USB_PORT_FEAT_RESET:
hprt0 = dwc2_read_hprt0(hsotg);
dev_dbg(hsotg->dev,
"SetPortFeature - USB_PORT_FEAT_RESET\n");
- pcgctl = readl(hsotg->regs + PCGCTL);
+ pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgctl &= ~(PCGCTL_ENBL_SLEEP_GATING | PCGCTL_STOPPCLK);
- writel(pcgctl, hsotg->regs + PCGCTL);
+ dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
/* ??? Original driver does this */
- writel(0, hsotg->regs + PCGCTL);
+ dwc2_writel(0, hsotg->regs + PCGCTL);
hprt0 = dwc2_read_hprt0(hsotg);
/* Clear suspend bit if resetting from suspend state */
@@ -1759,13 +1799,13 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
hprt0 |= HPRT0_PWR | HPRT0_RST;
dev_dbg(hsotg->dev,
"In host mode, hprt0=%08x\n", hprt0);
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
}
/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
usleep_range(50000, 70000);
hprt0 &= ~HPRT0_RST;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
hsotg->lx_state = DWC2_L0; /* Now back to On state */
break;
@@ -1781,7 +1821,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
"SetPortFeature - USB_PORT_FEAT_TEST\n");
hprt0 &= ~HPRT0_TSTCTL_MASK;
hprt0 |= (windex >> 8) << HPRT0_TSTCTL_SHIFT;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
break;
default:
@@ -1838,7 +1878,7 @@ static int dwc2_hcd_is_status_changed(struct dwc2_hsotg *hsotg, int port)
int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
{
- u32 hfnum = readl(hsotg->regs + HFNUM);
+ u32 hfnum = dwc2_readl(hsotg->regs + HFNUM);
#ifdef DWC2_DEBUG_SOF
dev_vdbg(hsotg->dev, "DWC OTG HCD GET FRAME NUMBER %d\n",
@@ -1941,11 +1981,11 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
if (chan->xfer_started) {
u32 hfnum, hcchar, hctsiz, hcint, hcintmsk;
- hfnum = readl(hsotg->regs + HFNUM);
- hcchar = readl(hsotg->regs + HCCHAR(i));
- hctsiz = readl(hsotg->regs + HCTSIZ(i));
- hcint = readl(hsotg->regs + HCINT(i));
- hcintmsk = readl(hsotg->regs + HCINTMSK(i));
+ hfnum = dwc2_readl(hsotg->regs + HFNUM);
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(i));
+ hcint = dwc2_readl(hsotg->regs + HCINT(i));
+ hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(i));
dev_dbg(hsotg->dev, " hfnum: 0x%08x\n", hfnum);
dev_dbg(hsotg->dev, " hcchar: 0x%08x\n", hcchar);
dev_dbg(hsotg->dev, " hctsiz: 0x%08x\n", hctsiz);
@@ -1993,12 +2033,12 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, " periodic_channels: %d\n",
hsotg->periodic_channels);
dev_dbg(hsotg->dev, " periodic_usecs: %d\n", hsotg->periodic_usecs);
- np_tx_status = readl(hsotg->regs + GNPTXSTS);
+ np_tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
dev_dbg(hsotg->dev, " NP Tx Req Queue Space Avail: %d\n",
(np_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT);
dev_dbg(hsotg->dev, " NP Tx FIFO Space Avail: %d\n",
(np_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT);
- p_tx_status = readl(hsotg->regs + HPTXSTS);
+ p_tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
dev_dbg(hsotg->dev, " P Tx Req Queue Space Avail: %d\n",
(p_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT);
dev_dbg(hsotg->dev, " P Tx FIFO Space Avail: %d\n",
@@ -2194,11 +2234,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
usb_pipein(urb->pipe) ? "IN" : "OUT", status,
urb->actual_length);
- if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
- for (i = 0; i < urb->number_of_packets; i++)
- dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
- i, urb->iso_frame_desc[i].status);
- }
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
@@ -2211,6 +2246,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
}
}
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
+ for (i = 0; i < urb->number_of_packets; i++)
+ dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
+ i, urb->iso_frame_desc[i].status);
+ }
+
urb->status = status;
if (!status) {
if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
@@ -2262,7 +2303,7 @@ static void dwc2_hcd_reset_func(struct work_struct *work)
dev_dbg(hsotg->dev, "USB RESET function called\n");
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 &= ~HPRT0_RST;
- writel(hprt0, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
hsotg->flags.b.port_reset_change = 1;
}
@@ -2286,8 +2327,9 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
spin_lock_irqsave(&hsotg->lock, flags);
-
+ hsotg->lx_state = DWC2_L0;
hcd->state = HC_STATE_RUNNING;
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
if (dwc2_is_device_mode(hsotg)) {
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2316,8 +2358,19 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
+ /* Turn off all host-specific interrupts */
+ dwc2_disable_host_interrupts(hsotg);
+
+ /* Wait for interrupt processing to finish */
+ synchronize_irq(hcd->irq);
+
spin_lock_irqsave(&hsotg->lock, flags);
+ /* Ensure hcd is disconnected */
+ dwc2_hcd_disconnect(hsotg);
dwc2_hcd_stop(hsotg);
+ hsotg->lx_state = DWC2_L3;
+ hcd->state = HC_STATE_HALT;
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore(&hsotg->lock, flags);
usleep_range(1000, 3000);
@@ -2326,17 +2379,125 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
{
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+ unsigned long flags;
+ int ret = 0;
+ u32 hprt0;
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+
+ if (hsotg->lx_state != DWC2_L0)
+ goto unlock;
+
+ if (!HCD_HW_ACCESSIBLE(hcd))
+ goto unlock;
+
+ if (!hsotg->core_params->hibernation)
+ goto skip_power_saving;
+
+ /*
+ * Drive USB suspend and disable port Power
+ * if usb bus is not suspended.
+ */
+ if (!hsotg->bus_suspended) {
+ hprt0 = dwc2_read_hprt0(hsotg);
+ hprt0 |= HPRT0_SUSP;
+ hprt0 &= ~HPRT0_PWR;
+ dwc2_writel(hprt0, hsotg->regs + HPRT0);
+ }
+ /* Enter hibernation */
+ ret = dwc2_enter_hibernation(hsotg);
+ if (ret) {
+ if (ret != -ENOTSUPP)
+ dev_err(hsotg->dev,
+ "enter hibernation failed\n");
+ goto skip_power_saving;
+ }
+
+ /* Ask phy to be suspended */
+ if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+ usb_phy_set_suspend(hsotg->uphy, true);
+ spin_lock_irqsave(&hsotg->lock, flags);
+ }
+
+ /* After entering hibernation, hardware is no more accessible */
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+skip_power_saving:
hsotg->lx_state = DWC2_L2;
- return 0;
+unlock:
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+ return ret;
}
static int _dwc2_hcd_resume(struct usb_hcd *hcd)
{
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+
+ if (hsotg->lx_state != DWC2_L2)
+ goto unlock;
+
+ if (!hsotg->core_params->hibernation) {
+ hsotg->lx_state = DWC2_L0;
+ goto unlock;
+ }
+
+ /*
+ * Set HW accessible bit before powering on the controller
+ * since an interrupt may rise.
+ */
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ /*
+ * Enable power if not already done.
+ * This must not be spinlocked since duration
+ * of this call is unknown.
+ */
+ if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+ usb_phy_set_suspend(hsotg->uphy, false);
+ spin_lock_irqsave(&hsotg->lock, flags);
+ }
+
+ /* Exit hibernation */
+ ret = dwc2_exit_hibernation(hsotg, true);
+ if (ret && (ret != -ENOTSUPP))
+ dev_err(hsotg->dev, "exit hibernation failed\n");
hsotg->lx_state = DWC2_L0;
- return 0;
+
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+ if (hsotg->bus_suspended) {
+ spin_lock_irqsave(&hsotg->lock, flags);
+ hsotg->flags.b.port_suspend_change = 1;
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+ dwc2_port_resume(hsotg);
+ } else {
+ /* Wait for controller to correctly update D+/D- level */
+ usleep_range(3000, 5000);
+
+ /*
+ * Clear Port Enable and Port Status changes.
+ * Enable Port Power.
+ */
+ dwc2_writel(HPRT0_PWR | HPRT0_CONNDET |
+ HPRT0_ENACHG, hsotg->regs + HPRT0);
+ /* Wait for controller to detect Port Connect */
+ usleep_range(5000, 7000);
+ }
+
+ return ret;
+unlock:
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+ return ret;
}
/* Returns the current frame number */
@@ -2790,17 +2951,17 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
hsotg->status_buf = NULL;
}
- ahbcfg = readl(hsotg->regs + GAHBCFG);
+ ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
/* Disable all interrupts */
ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
- writel(ahbcfg, hsotg->regs + GAHBCFG);
- writel(0, hsotg->regs + GINTMSK);
+ dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
+ dwc2_writel(0, hsotg->regs + GINTMSK);
if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) {
- dctl = readl(hsotg->regs + DCTL);
+ dctl = dwc2_readl(hsotg->regs + DCTL);
dctl |= DCTL_SFTDISCON;
- writel(dctl, hsotg->regs + DCTL);
+ dwc2_writel(dctl, hsotg->regs + DCTL);
}
if (hsotg->wq_otg) {
@@ -2841,7 +3002,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
retval = -ENOMEM;
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index fc1054965552..f105bada2fd1 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -371,10 +371,10 @@ static inline struct usb_hcd *dwc2_hsotg_to_hcd(struct dwc2_hsotg *hsotg)
*/
static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
{
- u32 mask = readl(hsotg->regs + HCINTMSK(chnum));
+ u32 mask = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
mask &= ~intr;
- writel(mask, hsotg->regs + HCINTMSK(chnum));
+ dwc2_writel(mask, hsotg->regs + HCINTMSK(chnum));
}
/*
@@ -382,11 +382,11 @@ static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
*/
static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg)
{
- return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
+ return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
}
static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
{
- return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
+ return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
}
/*
@@ -395,7 +395,7 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
*/
static inline u32 dwc2_read_hprt0(struct dwc2_hsotg *hsotg)
{
- u32 hprt0 = readl(hsotg->regs + HPRT0);
+ u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
return hprt0;
@@ -580,7 +580,8 @@ static inline u16 dwc2_micro_frame_num(u16 frame)
*/
static inline u32 dwc2_read_core_intr(struct dwc2_hsotg *hsotg)
{
- return readl(hsotg->regs + GINTSTS) & readl(hsotg->regs + GINTMSK);
+ return dwc2_readl(hsotg->regs + GINTSTS) &
+ dwc2_readl(hsotg->regs + GINTMSK);
}
static inline u32 dwc2_hcd_urb_get_status(struct dwc2_hcd_urb *dwc2_urb)
@@ -732,7 +733,7 @@ do { \
qtd_list_entry); \
if (usb_pipeint(_qtd_->urb->pipe) && \
(_qh_)->start_split_frame != 0 && !_qtd_->complete_split) { \
- _hfnum_.d32 = readl((_hcd_)->regs + HFNUM); \
+ _hfnum_.d32 = dwc2_readl((_hcd_)->regs + HFNUM); \
switch (_hfnum_.b.frnum & 0x7) { \
case 7: \
(_hcd_)->hfnum_7_samples_##_letter_++; \
diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c
index 3376177e4d3c..78993aba9335 100644
--- a/drivers/usb/dwc2/hcd_ddma.c
+++ b/drivers/usb/dwc2/hcd_ddma.c
@@ -169,19 +169,19 @@ static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en)
spin_lock_irqsave(&hsotg->lock, flags);
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
if (hcfg & HCFG_PERSCHEDENA) {
/* already enabled */
spin_unlock_irqrestore(&hsotg->lock, flags);
return;
}
- writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR);
+ dwc2_writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR);
hcfg &= ~HCFG_FRLISTEN_MASK;
hcfg |= fr_list_en | HCFG_PERSCHEDENA;
dev_vdbg(hsotg->dev, "Enabling Periodic schedule\n");
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
spin_unlock_irqrestore(&hsotg->lock, flags);
}
@@ -193,7 +193,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg)
spin_lock_irqsave(&hsotg->lock, flags);
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
if (!(hcfg & HCFG_PERSCHEDENA)) {
/* already disabled */
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -202,7 +202,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg)
hcfg &= ~HCFG_PERSCHEDENA;
dev_vdbg(hsotg->dev, "Disabling Periodic schedule\n");
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
spin_unlock_irqrestore(&hsotg->lock, flags);
}
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 4cc95df4262d..bda0b21b850f 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -148,7 +148,7 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg)
dwc2_hcd_queue_transactions(hsotg, tr_type);
/* Clear interrupt */
- writel(GINTSTS_SOF, hsotg->regs + GINTSTS);
+ dwc2_writel(GINTSTS_SOF, hsotg->regs + GINTSTS);
}
/*
@@ -164,7 +164,7 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg)
if (dbg_perio())
dev_vdbg(hsotg->dev, "--RxFIFO Level Interrupt--\n");
- grxsts = readl(hsotg->regs + GRXSTSP);
+ grxsts = dwc2_readl(hsotg->regs + GRXSTSP);
chnum = (grxsts & GRXSTS_HCHNUM_MASK) >> GRXSTS_HCHNUM_SHIFT;
chan = hsotg->hc_ptr_array[chnum];
if (!chan) {
@@ -247,11 +247,11 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
dev_vdbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
/* Every time when port enables calculate HFIR.FrInterval */
- hfir = readl(hsotg->regs + HFIR);
+ hfir = dwc2_readl(hsotg->regs + HFIR);
hfir &= ~HFIR_FRINT_MASK;
hfir |= dwc2_calc_frame_interval(hsotg) << HFIR_FRINT_SHIFT &
HFIR_FRINT_MASK;
- writel(hfir, hsotg->regs + HFIR);
+ dwc2_writel(hfir, hsotg->regs + HFIR);
/* Check if we need to adjust the PHY clock speed for low power */
if (!params->host_support_fs_ls_low_power) {
@@ -260,7 +260,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
return;
}
- usbcfg = readl(hsotg->regs + GUSBCFG);
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
if (prtspd == HPRT0_SPD_LOW_SPEED || prtspd == HPRT0_SPD_FULL_SPEED) {
@@ -268,11 +268,11 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL)) {
/* Set PHY low power clock select for FS/LS devices */
usbcfg |= GUSBCFG_PHY_LP_CLK_SEL;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
do_reset = 1;
}
- hcfg = readl(hsotg->regs + HCFG);
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
fslspclksel = (hcfg & HCFG_FSLSPCLKSEL_MASK) >>
HCFG_FSLSPCLKSEL_SHIFT;
@@ -286,7 +286,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
fslspclksel = HCFG_FSLSPCLKSEL_6_MHZ;
hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT;
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
do_reset = 1;
}
} else {
@@ -297,7 +297,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
fslspclksel = HCFG_FSLSPCLKSEL_48_MHZ;
hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT;
- writel(hcfg, hsotg->regs + HCFG);
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
do_reset = 1;
}
}
@@ -305,7 +305,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
/* Not low power */
if (usbcfg & GUSBCFG_PHY_LP_CLK_SEL) {
usbcfg &= ~GUSBCFG_PHY_LP_CLK_SEL;
- writel(usbcfg, hsotg->regs + GUSBCFG);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
do_reset = 1;
}
}
@@ -332,7 +332,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
dev_vdbg(hsotg->dev, "--Port Interrupt--\n");
- hprt0 = readl(hsotg->regs + HPRT0);
+ hprt0 = dwc2_readl(hsotg->regs + HPRT0);
hprt0_modify = hprt0;
/*
@@ -388,7 +388,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
}
/* Clear Port Interrupts */
- writel(hprt0_modify, hsotg->regs + HPRT0);
+ dwc2_writel(hprt0_modify, hsotg->regs + HPRT0);
}
/*
@@ -408,7 +408,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg,
{
u32 hctsiz, count, length;
- hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
if (halt_status == DWC2_HC_XFER_COMPLETE) {
if (chan->ep_is_in) {
@@ -491,7 +491,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
urb->status = 0;
}
- hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n",
__func__, (chan->ep_is_in ? "IN" : "OUT"), chnum);
dev_vdbg(hsotg->dev, " chan->xfer_len %d\n", chan->xfer_len);
@@ -514,7 +514,7 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan, int chnum,
struct dwc2_qtd *qtd)
{
- u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+ u32 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT;
if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) {
@@ -771,9 +771,9 @@ cleanup:
}
}
- haintmsk = readl(hsotg->regs + HAINTMSK);
+ haintmsk = dwc2_readl(hsotg->regs + HAINTMSK);
haintmsk &= ~(1 << chan->hc_num);
- writel(haintmsk, hsotg->regs + HAINTMSK);
+ dwc2_writel(haintmsk, hsotg->regs + HAINTMSK);
/* Try to queue more transfers now that there's a free channel */
tr_type = dwc2_hcd_select_transactions(hsotg);
@@ -820,9 +820,9 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
* is enabled so that the non-periodic schedule will
* be processed
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk |= GINTSTS_NPTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
} else {
dev_vdbg(hsotg->dev, "isoc/intr\n");
/*
@@ -839,9 +839,9 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
* enabled so that the periodic schedule will be
* processed
*/
- gintmsk = readl(hsotg->regs + GINTMSK);
+ gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk |= GINTSTS_PTXFEMP;
- writel(gintmsk, hsotg->regs + GINTMSK);
+ dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
}
}
}
@@ -906,7 +906,7 @@ static void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg,
struct dwc2_qtd *qtd,
enum dwc2_halt_status halt_status)
{
- u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+ u32 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
qtd->error_count = 0;
@@ -1184,7 +1184,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
urb->actual_length += xfer_length;
- hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n",
__func__, (chan->ep_is_in ? "IN" : "OUT"), chnum);
dev_vdbg(hsotg->dev, " chan->start_pkt_count %d\n",
@@ -1505,10 +1505,10 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
- hcchar = readl(hsotg->regs + HCCHAR(chnum));
- hcsplt = readl(hsotg->regs + HCSPLT(chnum));
- hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
- hc_dma = readl(hsotg->regs + HCDMA(chnum));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum));
+ hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chnum));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
+ hc_dma = dwc2_readl(hsotg->regs + HCDMA(chnum));
dev_err(hsotg->dev, "AHB ERROR, Channel %d\n", chnum);
dev_err(hsotg->dev, " hcchar 0x%08x, hcsplt 0x%08x\n", hcchar, hcsplt);
@@ -1721,10 +1721,10 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg,
* This code is here only as a check. This condition should
* never happen. Ignore the halt if it does occur.
*/
- hcchar = readl(hsotg->regs + HCCHAR(chnum));
- hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
- hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
- hcsplt = readl(hsotg->regs + HCSPLT(chnum));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum));
+ hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
+ hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
+ hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chnum));
dev_dbg(hsotg->dev,
"%s: chan->halt_status DWC2_HC_XFER_NO_HALT_STATUS,\n",
__func__);
@@ -1748,7 +1748,7 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg,
* when the halt interrupt occurs. Halt the channel again if it does
* occur.
*/
- hcchar = readl(hsotg->regs + HCCHAR(chnum));
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum));
if (hcchar & HCCHAR_CHDIS) {
dev_warn(hsotg->dev,
"%s: hcchar.chdis set unexpectedly, hcchar 0x%08x, trying to halt again\n",
@@ -1808,7 +1808,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
return;
}
- hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+ hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
if (chan->hcint & HCINTMSK_XFERCOMPL) {
/*
@@ -1903,7 +1903,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
dev_err(hsotg->dev,
"hcint 0x%08x, intsts 0x%08x\n",
chan->hcint,
- readl(hsotg->regs + GINTSTS));
+ dwc2_readl(hsotg->regs + GINTSTS));
goto error;
}
}
@@ -1949,6 +1949,24 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg,
}
}
+/*
+ * Check if the given qtd is still the top of the list (and thus valid).
+ *
+ * If dwc2_hcd_qtd_unlink_and_free() has been called since we grabbed
+ * the qtd from the top of the list, this will return false (otherwise true).
+ */
+static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh)
+{
+ struct dwc2_qtd *cur_head;
+
+ if (qh == NULL)
+ return false;
+
+ cur_head = list_first_entry(&qh->qtd_list, struct dwc2_qtd,
+ qtd_list_entry);
+ return (cur_head == qtd);
+}
+
/* Handles interrupt for a specific Host Channel */
static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
{
@@ -1958,11 +1976,11 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
chan = hsotg->hc_ptr_array[chnum];
- hcint = readl(hsotg->regs + HCINT(chnum));
- hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+ hcint = dwc2_readl(hsotg->regs + HCINT(chnum));
+ hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
if (!chan) {
dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
- writel(hcint, hsotg->regs + HCINT(chnum));
+ dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
return;
}
@@ -1974,7 +1992,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
hcint, hcintmsk, hcint & hcintmsk);
}
- writel(hcint, hsotg->regs + HCINT(chnum));
+ dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
chan->hcint = hcint;
hcint &= hcintmsk;
@@ -2031,27 +2049,59 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
*/
hcint &= ~HCINTMSK_NYET;
}
- if (hcint & HCINTMSK_CHHLTD)
+
+ if (hcint & HCINTMSK_CHHLTD) {
dwc2_hc_chhltd_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_AHBERR)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_AHBERR) {
dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_STALL)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_STALL) {
dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_NAK)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_NAK) {
dwc2_hc_nak_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_ACK)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_ACK) {
dwc2_hc_ack_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_NYET)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_NYET) {
dwc2_hc_nyet_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_XACTERR)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_XACTERR) {
dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_BBLERR)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_BBLERR) {
dwc2_hc_babble_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_FRMOVRUN)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_FRMOVRUN) {
dwc2_hc_frmovrun_intr(hsotg, chan, chnum, qtd);
- if (hcint & HCINTMSK_DATATGLERR)
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+ if (hcint & HCINTMSK_DATATGLERR) {
dwc2_hc_datatglerr_intr(hsotg, chan, chnum, qtd);
+ if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+ goto exit;
+ }
+exit:
chan->hcint = 0;
}
@@ -2066,7 +2116,7 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg)
u32 haint;
int i;
- haint = readl(hsotg->regs + HAINT);
+ haint = dwc2_readl(hsotg->regs + HAINT);
if (dbg_perio()) {
dev_vdbg(hsotg->dev, "%s()\n", __func__);
@@ -2134,8 +2184,8 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg)
"DWC OTG HCD Finished Servicing Interrupts\n");
dev_vdbg(hsotg->dev,
"DWC OTG HCD gintsts=0x%08x gintmsk=0x%08x\n",
- readl(hsotg->regs + GINTSTS),
- readl(hsotg->regs + GINTMSK));
+ dwc2_readl(hsotg->regs + GINTSTS),
+ dwc2_readl(hsotg->regs + GINTMSK));
}
}
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 3ad63d392e13..7d8d06cfe3c1 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -106,6 +106,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
qh->ep_type == USB_ENDPOINT_XFER_ISOC,
bytecount));
+
+ /* Ensure frame_number corresponds to the reality */
+ hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
/* Start in a slightly future (micro)frame */
qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
SCHEDULE_SLOP);
@@ -115,7 +118,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
if (qh->ep_type == USB_ENDPOINT_XFER_INT)
qh->interval = 8;
#endif
- hprt = readl(hsotg->regs + HPRT0);
+ hprt = dwc2_readl(hsotg->regs + HPRT0);
prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
if (prtspd == HPRT0_SPD_HIGH_SPEED &&
(dev_speed == USB_SPEED_LOW ||
@@ -583,6 +586,14 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
/* QH already in a schedule */
return 0;
+ if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) &&
+ !hsotg->frame_number) {
+ dev_dbg(hsotg->dev,
+ "reset frame number counter\n");
+ qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
+ SCHEDULE_SLOP);
+ }
+
/* Add the new QH to the appropriate schedule */
if (dwc2_qh_is_non_per(qh)) {
/* Always start in inactive schedule */
@@ -595,9 +606,9 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
if (status)
return status;
if (!hsotg->periodic_qh_count) {
- intr_mask = readl(hsotg->regs + GINTMSK);
+ intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
intr_mask |= GINTSTS_SOF;
- writel(intr_mask, hsotg->regs + GINTMSK);
+ dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
}
hsotg->periodic_qh_count++;
@@ -632,9 +643,9 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
dwc2_deschedule_periodic(hsotg, qh);
hsotg->periodic_qh_count--;
if (!hsotg->periodic_qh_count) {
- intr_mask = readl(hsotg->regs + GINTMSK);
+ intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
intr_mask &= ~GINTSTS_SOF;
- writel(intr_mask, hsotg->regs + GINTMSK);
+ dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
}
}
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index d0a5ed8fa15a..553f24606c43 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -142,6 +142,7 @@
#define GINTSTS_RESETDET (1 << 23)
#define GINTSTS_FET_SUSP (1 << 22)
#define GINTSTS_INCOMPL_IP (1 << 21)
+#define GINTSTS_INCOMPL_SOOUT (1 << 21)
#define GINTSTS_INCOMPL_SOIN (1 << 20)
#define GINTSTS_OEPINT (1 << 19)
#define GINTSTS_IEPINT (1 << 18)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 90935304185a..e61d773cf65e 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -37,11 +37,14 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/of_device.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_data/s3c-hsotg.h>
#include <linux/usb/of.h>
@@ -105,12 +108,152 @@ static const struct dwc2_core_params params_rk3066 = {
.host_ls_low_power_phy_clk = -1,
.ts_dline = -1,
.reload_ctl = -1,
- .ahbcfg = 0x7, /* INCR16 */
+ .ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
+ GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = -1,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
+static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
+{
+ struct platform_device *pdev = to_platform_device(hsotg->dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(hsotg->clk);
+ if (ret)
+ return ret;
+
+ if (hsotg->uphy)
+ ret = usb_phy_init(hsotg->uphy);
+ else if (hsotg->plat && hsotg->plat->phy_init)
+ ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
+ else {
+ ret = phy_power_on(hsotg->phy);
+ if (ret == 0)
+ ret = phy_init(hsotg->phy);
+ }
+
+ return ret;
+}
+
+/**
+ * dwc2_lowlevel_hw_enable - enable platform lowlevel hw resources
+ * @hsotg: The driver state
+ *
+ * A wrapper for platform code responsible for controlling
+ * low-level USB platform resources (phy, clock, regulators)
+ */
+int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
+{
+ int ret = __dwc2_lowlevel_hw_enable(hsotg);
+
+ if (ret == 0)
+ hsotg->ll_hw_enabled = true;
+ return ret;
+}
+
+static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
+{
+ struct platform_device *pdev = to_platform_device(hsotg->dev);
+ int ret = 0;
+
+ if (hsotg->uphy)
+ usb_phy_shutdown(hsotg->uphy);
+ else if (hsotg->plat && hsotg->plat->phy_exit)
+ ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
+ else {
+ ret = phy_exit(hsotg->phy);
+ if (ret == 0)
+ ret = phy_power_off(hsotg->phy);
+ }
+ if (ret)
+ return ret;
+
+ clk_disable_unprepare(hsotg->clk);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+
+ return ret;
+}
+
+/**
+ * dwc2_lowlevel_hw_disable - disable platform lowlevel hw resources
+ * @hsotg: The driver state
+ *
+ * A wrapper for platform code responsible for controlling
+ * low-level USB platform resources (phy, clock, regulators)
+ */
+int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
+{
+ int ret = __dwc2_lowlevel_hw_disable(hsotg);
+
+ if (ret == 0)
+ hsotg->ll_hw_enabled = false;
+ return ret;
+}
+
+static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
+{
+ int i, ret;
+
+ /* Set default UTMI width */
+ hsotg->phyif = GUSBCFG_PHYIF16;
+
+ /*
+ * Attempt to find a generic PHY, then look for an old style
+ * USB PHY and then fall back to pdata
+ */
+ hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy");
+ if (IS_ERR(hsotg->phy)) {
+ hsotg->phy = NULL;
+ hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR(hsotg->uphy))
+ hsotg->uphy = NULL;
+ else
+ hsotg->plat = dev_get_platdata(hsotg->dev);
+ }
+
+ if (hsotg->phy) {
+ /*
+ * If using the generic PHY framework, check if the PHY bus
+ * width is 8-bit and set the phyif appropriately.
+ */
+ if (phy_get_bus_width(hsotg->phy) == 8)
+ hsotg->phyif = GUSBCFG_PHYIF8;
+ }
+
+ if (!hsotg->phy && !hsotg->uphy && !hsotg->plat) {
+ dev_err(hsotg->dev, "no platform data or transceiver defined\n");
+ return -EPROBE_DEFER;
+ }
+
+ /* Clock */
+ hsotg->clk = devm_clk_get(hsotg->dev, "otg");
+ if (IS_ERR(hsotg->clk)) {
+ hsotg->clk = NULL;
+ dev_dbg(hsotg->dev, "cannot get otg clock\n");
+ }
+
+ /* Regulators */
+ for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
+ hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
+
+ ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ if (ret) {
+ dev_err(hsotg->dev, "failed to request supplies: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
/**
* dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the
* DWC_otg driver
@@ -130,7 +273,10 @@ static int dwc2_driver_remove(struct platform_device *dev)
if (hsotg->hcd_enabled)
dwc2_hcd_remove(hsotg);
if (hsotg->gadget_enabled)
- s3c_hsotg_remove(hsotg);
+ dwc2_hsotg_remove(hsotg);
+
+ if (hsotg->ll_hw_enabled)
+ dwc2_lowlevel_hw_disable(hsotg);
return 0;
}
@@ -163,8 +309,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
struct dwc2_core_params defparams;
struct dwc2_hsotg *hsotg;
struct resource *res;
- struct phy *phy;
- struct usb_phy *uphy;
int retval;
int irq;
@@ -220,34 +364,25 @@ static int dwc2_driver_probe(struct platform_device *dev)
dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n",
(unsigned long)res->start, hsotg->regs);
- hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
-
- /*
- * Attempt to find a generic PHY, then look for an old style
- * USB PHY
- */
- phy = devm_phy_get(&dev->dev, "usb2-phy");
- if (IS_ERR(phy)) {
- hsotg->phy = NULL;
- uphy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR(uphy))
- hsotg->uphy = NULL;
- else
- hsotg->uphy = uphy;
- } else {
- hsotg->phy = phy;
- phy_power_on(hsotg->phy);
- phy_init(hsotg->phy);
+ hsotg->dr_mode = usb_get_dr_mode(&dev->dev);
+ if (IS_ENABLED(CONFIG_USB_DWC2_HOST) &&
+ hsotg->dr_mode != USB_DR_MODE_HOST) {
+ hsotg->dr_mode = USB_DR_MODE_HOST;
+ dev_warn(hsotg->dev,
+ "Configuration mismatch. Forcing host mode\n");
+ } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) &&
+ hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+ hsotg->dr_mode = USB_DR_MODE_PERIPHERAL;
+ dev_warn(hsotg->dev,
+ "Configuration mismatch. Forcing peripheral mode\n");
}
- spin_lock_init(&hsotg->lock);
- mutex_init(&hsotg->init_mutex);
-
- /* Detect config values from hardware */
- retval = dwc2_get_hwparams(hsotg);
+ retval = dwc2_lowlevel_hw_init(hsotg);
if (retval)
return retval;
+ spin_lock_init(&hsotg->lock);
+
hsotg->core_params = devm_kzalloc(&dev->dev,
sizeof(*hsotg->core_params), GFP_KERNEL);
if (!hsotg->core_params)
@@ -255,13 +390,22 @@ static int dwc2_driver_probe(struct platform_device *dev)
dwc2_set_all_params(hsotg->core_params, -1);
+ retval = dwc2_lowlevel_hw_enable(hsotg);
+ if (retval)
+ return retval;
+
+ /* Detect config values from hardware */
+ retval = dwc2_get_hwparams(hsotg);
+ if (retval)
+ goto error;
+
/* Validate parameter values */
dwc2_set_parameters(hsotg, params);
if (hsotg->dr_mode != USB_DR_MODE_HOST) {
retval = dwc2_gadget_init(hsotg, irq);
if (retval)
- return retval;
+ goto error;
hsotg->gadget_enabled = 1;
}
@@ -269,8 +413,8 @@ static int dwc2_driver_probe(struct platform_device *dev)
retval = dwc2_hcd_init(hsotg, irq);
if (retval) {
if (hsotg->gadget_enabled)
- s3c_hsotg_remove(hsotg);
- return retval;
+ dwc2_hsotg_remove(hsotg);
+ goto error;
}
hsotg->hcd_enabled = 1;
}
@@ -279,6 +423,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
dwc2_debugfs_init(hsotg);
+ /* Gadget code manages lowlevel hw on its own */
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+ dwc2_lowlevel_hw_disable(hsotg);
+
+ return 0;
+
+error:
+ dwc2_lowlevel_hw_disable(hsotg);
return retval;
}
@@ -287,15 +439,12 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;
- if (dwc2_is_device_mode(dwc2)) {
- ret = s3c_hsotg_suspend(dwc2);
- } else {
- if (dwc2->lx_state == DWC2_L0)
- return 0;
- phy_exit(dwc2->phy);
- phy_power_off(dwc2->phy);
+ if (dwc2_is_device_mode(dwc2))
+ dwc2_hsotg_suspend(dwc2);
+
+ if (dwc2->ll_hw_enabled)
+ ret = __dwc2_lowlevel_hw_disable(dwc2);
- }
return ret;
}
@@ -304,13 +453,15 @@ static int __maybe_unused dwc2_resume(struct device *dev)
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;
- if (dwc2_is_device_mode(dwc2)) {
- ret = s3c_hsotg_resume(dwc2);
- } else {
- phy_power_on(dwc2->phy);
- phy_init(dwc2->phy);
-
+ if (dwc2->ll_hw_enabled) {
+ ret = __dwc2_lowlevel_hw_enable(dwc2);
+ if (ret)
+ return ret;
}
+
+ if (dwc2_is_device_mode(dwc2))
+ ret = dwc2_hsotg_resume(dwc2);
+
return ret;
}
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 064123e44566..22b4797383cd 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -34,6 +34,7 @@
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/acpi.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@@ -143,6 +144,32 @@ static int dwc3_soft_reset(struct dwc3 *dwc)
return 0;
}
+/*
+ * dwc3_frame_length_adjustment - Adjusts frame length if required
+ * @dwc3: Pointer to our controller context structure
+ * @fladj: Value of GFLADJ_30MHZ to adjust frame length
+ */
+static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
+{
+ u32 reg;
+ u32 dft;
+
+ if (dwc->revision < DWC3_REVISION_250A)
+ return;
+
+ if (fladj == 0)
+ return;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
+ dft = reg & DWC3_GFLADJ_30MHZ_MASK;
+ if (!dev_WARN_ONCE(dwc->dev, dft == fladj,
+ "request value same as default, ignoring\n")) {
+ reg &= ~DWC3_GFLADJ_30MHZ_MASK;
+ reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
+ dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
+ }
+}
+
/**
* dwc3_free_one_event_buffer - Frees one event buffer
* @dwc: Pointer to our controller context structure
@@ -488,6 +515,9 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
if (dwc->dis_u2_susphy_quirk)
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+ if (dwc->dis_enblslpm_quirk)
+ reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
+
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
return 0;
@@ -507,12 +537,18 @@ static int dwc3_core_init(struct dwc3 *dwc)
reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
/* This should read as U3 followed by revision number */
- if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
+ if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
+ /* Detected DWC_usb3 IP */
+ dwc->revision = reg;
+ } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
+ /* Detected DWC_usb31 IP */
+ dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
+ dwc->revision |= DWC3_REVISION_IS_DWC31;
+ } else {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
ret = -ENODEV;
goto err0;
}
- dwc->revision = reg;
/*
* Write Linux Version Code to our GUID register so it's easy to figure
@@ -773,12 +809,12 @@ static int dwc3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dwc3_platform_data *pdata = dev_get_platdata(dev);
- struct device_node *node = dev->of_node;
struct resource *res;
struct dwc3 *dwc;
u8 lpm_nyet_threshold;
u8 tx_de_emphasis;
u8 hird_threshold;
+ u32 fladj = 0;
int ret;
@@ -842,51 +878,56 @@ static int dwc3_probe(struct platform_device *pdev)
*/
hird_threshold = 12;
- if (node) {
- dwc->maximum_speed = of_usb_get_maximum_speed(node);
- dwc->has_lpm_erratum = of_property_read_bool(node,
+ dwc->maximum_speed = usb_get_maximum_speed(dev);
+ dwc->dr_mode = usb_get_dr_mode(dev);
+
+ dwc->has_lpm_erratum = device_property_read_bool(dev,
"snps,has-lpm-erratum");
- of_property_read_u8(node, "snps,lpm-nyet-threshold",
+ device_property_read_u8(dev, "snps,lpm-nyet-threshold",
&lpm_nyet_threshold);
- dwc->is_utmi_l1_suspend = of_property_read_bool(node,
+ dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
"snps,is-utmi-l1-suspend");
- of_property_read_u8(node, "snps,hird-threshold",
+ device_property_read_u8(dev, "snps,hird-threshold",
&hird_threshold);
- dwc->usb3_lpm_capable = of_property_read_bool(node,
+ dwc->usb3_lpm_capable = device_property_read_bool(dev,
"snps,usb3_lpm_capable");
- dwc->needs_fifo_resize = of_property_read_bool(node,
+ dwc->needs_fifo_resize = device_property_read_bool(dev,
"tx-fifo-resize");
- dwc->dr_mode = of_usb_get_dr_mode(node);
- dwc->disable_scramble_quirk = of_property_read_bool(node,
+ dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
- dwc->u2exit_lfps_quirk = of_property_read_bool(node,
+ dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
"snps,u2exit_lfps_quirk");
- dwc->u2ss_inp3_quirk = of_property_read_bool(node,
+ dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
"snps,u2ss_inp3_quirk");
- dwc->req_p1p2p3_quirk = of_property_read_bool(node,
+ dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
"snps,req_p1p2p3_quirk");
- dwc->del_p1p2p3_quirk = of_property_read_bool(node,
+ dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
"snps,del_p1p2p3_quirk");
- dwc->del_phy_power_chg_quirk = of_property_read_bool(node,
+ dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,del_phy_power_chg_quirk");
- dwc->lfps_filter_quirk = of_property_read_bool(node,
+ dwc->lfps_filter_quirk = device_property_read_bool(dev,
"snps,lfps_filter_quirk");
- dwc->rx_detect_poll_quirk = of_property_read_bool(node,
+ dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
"snps,rx_detect_poll_quirk");
- dwc->dis_u3_susphy_quirk = of_property_read_bool(node,
+ dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
"snps,dis_u3_susphy_quirk");
- dwc->dis_u2_susphy_quirk = of_property_read_bool(node,
+ dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
"snps,dis_u2_susphy_quirk");
+ dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
+ "snps,dis_enblslpm_quirk");
- dwc->tx_de_emphasis_quirk = of_property_read_bool(node,
+ dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
"snps,tx_de_emphasis_quirk");
- of_property_read_u8(node, "snps,tx_de_emphasis",
+ device_property_read_u8(dev, "snps,tx_de_emphasis",
&tx_de_emphasis);
- of_property_read_string(node, "snps,hsphy_interface",
- &dwc->hsphy_interface);
- } else if (pdata) {
+ device_property_read_string(dev, "snps,hsphy_interface",
+ &dwc->hsphy_interface);
+ device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
+ &fladj);
+
+ if (pdata) {
dwc->maximum_speed = pdata->maximum_speed;
dwc->has_lpm_erratum = pdata->has_lpm_erratum;
if (pdata->lpm_nyet_threshold)
@@ -909,12 +950,14 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk;
dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk;
dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk;
+ dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk;
dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk;
if (pdata->tx_de_emphasis)
tx_de_emphasis = pdata->tx_de_emphasis;
dwc->hsphy_interface = pdata->hsphy_interface;
+ fladj = pdata->fladj_value;
}
/* default to superspeed if no maximum_speed passed */
@@ -971,6 +1014,9 @@ static int dwc3_probe(struct platform_device *pdev)
goto err1;
}
+ /* Adjust Frame Length */
+ dwc3_frame_length_adjustment(dwc, fladj);
+
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
ret = phy_power_on(dwc->usb2_generic_phy);
@@ -1091,6 +1137,8 @@ static int dwc3_suspend(struct device *dev)
phy_exit(dwc->usb2_generic_phy);
phy_exit(dwc->usb3_generic_phy);
+ pinctrl_pm_select_sleep_state(dev);
+
return 0;
}
@@ -1100,6 +1148,8 @@ static int dwc3_resume(struct device *dev)
unsigned long flags;
int ret;
+ pinctrl_pm_select_default_state(dev);
+
usb_phy_init(dwc->usb3_phy);
usb_phy_init(dwc->usb2_phy);
ret = phy_init(dwc->usb2_generic_phy);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 044778884585..36f1cb74588c 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -108,6 +108,9 @@
#define DWC3_GPRTBIMAP_FS0 0xc188
#define DWC3_GPRTBIMAP_FS1 0xc18c
+#define DWC3_VER_NUMBER 0xc1a0
+#define DWC3_VER_TYPE 0xc1a4
+
#define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04))
#define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04))
@@ -124,6 +127,7 @@
#define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10))
#define DWC3_GHWPARAMS8 0xc600
+#define DWC3_GFLADJ 0xc630
/* Device Registers */
#define DWC3_DCFG 0xc700
@@ -175,6 +179,7 @@
#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6)
#define DWC3_GUSB2PHYCFG_ULPI_UTMI (1 << 4)
+#define DWC3_GUSB2PHYCFG_ENBLSLPM (1 << 8)
/* Global USB2 PHY Vendor Control Register */
#define DWC3_GUSB2PHYACC_NEWREGREQ (1 << 25)
@@ -234,6 +239,10 @@
/* Global HWPARAMS6 Register */
#define DWC3_GHWPARAMS6_EN_FPGA (1 << 7)
+/* Global Frame Length Adjustment Register */
+#define DWC3_GFLADJ_30MHZ_SDBND_SEL (1 << 7)
+#define DWC3_GFLADJ_30MHZ_MASK 0x3f
+
/* Device Configuration Register */
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
@@ -712,6 +721,8 @@ struct dwc3_scratchpad_array {
* @rx_detect_poll_quirk: set if we enable rx_detect to polling lfps quirk
* @dis_u3_susphy_quirk: set if we disable usb3 suspend phy
* @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
+ * @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG,
+ * disabling the suspend signal to the PHY.
* @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk
* @tx_de_emphasis: Tx de-emphasis value
* 0 - -6dB de-emphasis
@@ -766,6 +777,14 @@ struct dwc3 {
u32 num_event_buffers;
u32 u1u2;
u32 maximum_speed;
+
+ /*
+ * All 3.1 IP version constants are greater than the 3.0 IP
+ * version constants. This works for most version checks in
+ * dwc3. However, in the future, this may not apply as
+ * features may be developed on newer versions of the 3.0 IP
+ * that are not in the 3.1 IP.
+ */
u32 revision;
#define DWC3_REVISION_173A 0x5533173a
@@ -788,6 +807,13 @@ struct dwc3 {
#define DWC3_REVISION_270A 0x5533270a
#define DWC3_REVISION_280A 0x5533280a
+/*
+ * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really
+ * just so dwc31 revisions are always larger than dwc3.
+ */
+#define DWC3_REVISION_IS_DWC31 0x80000000
+#define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_USB31)
+
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state;
@@ -841,6 +867,7 @@ struct dwc3 {
unsigned rx_detect_poll_quirk:1;
unsigned dis_u3_susphy_quirk:1;
unsigned dis_u2_susphy_quirk:1;
+ unsigned dis_enblslpm_quirk:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index f62617999f3c..009d83048c8c 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -26,12 +26,16 @@
#include "platform_data.h"
-#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
-#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
-#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
-#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
-#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
-#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
+#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
+#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI 0xabce
+#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31 0xabcf
+#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
+#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
+#define PCI_DEVICE_ID_INTEL_BSW 0x22b7
+#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
+#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
+#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
+#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
@@ -106,6 +110,22 @@ static int dwc3_pci_quirks(struct pci_dev *pdev)
}
}
+ if (pdev->vendor == PCI_VENDOR_ID_SYNOPSYS &&
+ (pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 ||
+ pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI ||
+ pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31)) {
+
+ struct dwc3_platform_data pdata;
+
+ memset(&pdata, 0, sizeof(pdata));
+ pdata.usb3_lpm_capable = true;
+ pdata.has_lpm_erratum = true;
+ pdata.dis_enblslpm_quirk = true;
+
+ return platform_device_add_data(pci_get_drvdata(pdev), &pdata,
+ sizeof(pdata));
+ }
+
return 0;
}
@@ -154,6 +174,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
goto err;
dwc3->dev.parent = dev;
+ ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev));
ret = platform_device_add(dwc3);
if (ret) {
@@ -178,11 +199,21 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
},
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
+ PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI),
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
+ PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31),
+ },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
{ } /* Terminating Entry */
};
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index de4d52f62517..5c0adb9c6fb2 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -195,6 +195,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
struct resource *res;
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node, *child;
+ struct platform_device *child_pdev;
struct regmap *regmap;
int ret;
@@ -253,8 +254,6 @@ static int st_dwc3_probe(struct platform_device *pdev)
goto undo_softreset;
}
- dwc3_data->dr_mode = of_usb_get_dr_mode(child);
-
/* Allocate and initialize the core */
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
@@ -262,6 +261,15 @@ static int st_dwc3_probe(struct platform_device *pdev)
goto undo_softreset;
}
+ child_pdev = of_find_device_by_node(child);
+ if (!child_pdev) {
+ dev_err(dev, "failed to find dwc3 core device\n");
+ ret = -ENODEV;
+ goto undo_softreset;
+ }
+
+ dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev);
+
/*
* Configure the USB port as device or host according to the static
* configuration passed from DT.
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1e8bdf817811..e24a01cc98df 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -948,7 +948,6 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
dwc3_trace(trace_dwc3_gadget, "%s: endpoint busy", dep->name);
return -EBUSY;
}
- dep->flags &= ~DWC3_EP_PENDING_REQUEST;
/*
* If we are getting here after a short-out-packet we don't enqueue any
@@ -1050,6 +1049,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
req->direction = dep->direction;
req->epnum = dep->number;
+ trace_dwc3_ep_queue(req);
+
/*
* We only add to our list of requests now and
* start consuming the list once we get XferNotReady
@@ -1070,6 +1071,19 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
list_add_tail(&req->list, &dep->request_list);
/*
+ * If there are no pending requests and the endpoint isn't already
+ * busy, we will just start the request straight away.
+ *
+ * This will save one IRQ (XFER_NOT_READY) and possibly make it a
+ * little bit faster.
+ */
+ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+ !(dep->flags & DWC3_EP_BUSY)) {
+ ret = __dwc3_gadget_kick_transfer(dep, 0, true);
+ goto out;
+ }
+
+ /*
* There are a few special cases:
*
* 1. XferNotReady with empty list of requests. We need to kick the
@@ -1096,10 +1110,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
}
ret = __dwc3_gadget_kick_transfer(dep, 0, true);
- if (ret && ret != -EBUSY)
- dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
- dep->name);
- return ret;
+ if (!ret)
+ dep->flags &= ~DWC3_EP_PENDING_REQUEST;
+
+ goto out;
}
/*
@@ -1113,10 +1127,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
WARN_ON_ONCE(!dep->resource_index);
ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index,
false);
- if (ret && ret != -EBUSY)
- dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
- dep->name);
- return ret;
+ goto out;
}
/*
@@ -1124,14 +1135,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
* right away, otherwise host will not know we have streams to be
* handled.
*/
- if (dep->stream_capable) {
+ if (dep->stream_capable)
ret = __dwc3_gadget_kick_transfer(dep, 0, true);
- if (ret && ret != -EBUSY)
- dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
- dep->name);
- }
- return 0;
+out:
+ if (ret && ret != -EBUSY)
+ dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
+ dep->name);
+ if (ret == -EBUSY)
+ ret = 0;
+
+ return ret;
}
static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
@@ -1159,8 +1173,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
goto out;
}
- trace_dwc3_ep_queue(req);
-
ret = __dwc3_gadget_ep_queue(dep, req);
out:
@@ -1872,27 +1884,32 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
unsigned int i;
int ret;
- req = next_request(&dep->req_queued);
- if (!req) {
- WARN_ON_ONCE(1);
- return 1;
- }
- i = 0;
do {
- slot = req->start_slot + i;
- if ((slot == DWC3_TRB_NUM - 1) &&
+ req = next_request(&dep->req_queued);
+ if (!req) {
+ WARN_ON_ONCE(1);
+ return 1;
+ }
+ i = 0;
+ do {
+ slot = req->start_slot + i;
+ if ((slot == DWC3_TRB_NUM - 1) &&
usb_endpoint_xfer_isoc(dep->endpoint.desc))
- slot++;
- slot %= DWC3_TRB_NUM;
- trb = &dep->trb_pool[slot];
+ slot++;
+ slot %= DWC3_TRB_NUM;
+ trb = &dep->trb_pool[slot];
+
+ ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+ event, status);
+ if (ret)
+ break;
+ } while (++i < req->request.num_mapped_sgs);
+
+ dwc3_gadget_giveback(dep, req, status);
- ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
- event, status);
if (ret)
break;
- } while (++i < req->request.num_mapped_sgs);
-
- dwc3_gadget_giveback(dep, req, status);
+ } while (1);
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
list_empty(&dep->req_queued)) {
@@ -1955,6 +1972,14 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
dwc->u1u2 = 0;
}
+
+ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+ int ret;
+
+ ret = __dwc3_gadget_kick_transfer(dep, 0, is_xfer_complete);
+ if (!ret || ret == -EBUSY)
+ return;
+ }
}
static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
@@ -1992,15 +2017,16 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dwc3_gadget_start_isoc(dwc, dep, event);
} else {
+ int active;
int ret;
+ active = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
+
dwc3_trace(trace_dwc3_gadget, "%s: reason %s",
- dep->name, event->status &
- DEPEVT_STATUS_TRANSFER_ACTIVE
- ? "Transfer Active"
+ dep->name, active ? "Transfer Active"
: "Transfer Not Active");
- ret = __dwc3_gadget_kick_transfer(dep, 0, 1);
+ ret = __dwc3_gadget_kick_transfer(dep, 0, !active);
if (!ret || ret == -EBUSY)
return;
@@ -2718,12 +2744,34 @@ int dwc3_gadget_init(struct dwc3 *dwc)
}
dwc->gadget.ops = &dwc3_gadget_ops;
- dwc->gadget.max_speed = USB_SPEED_SUPER;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.sg_supported = true;
dwc->gadget.name = "dwc3-gadget";
/*
+ * FIXME We might be setting max_speed to <SUPER, however versions
+ * <2.20a of dwc3 have an issue with metastability (documented
+ * elsewhere in this driver) which tells us we can't set max speed to
+ * anything lower than SUPER.
+ *
+ * Because gadget.max_speed is only used by composite.c and function
+ * drivers (i.e. it won't go into dwc3's registers) we are allowing this
+ * to happen so we avoid sending SuperSpeed Capability descriptor
+ * together with our BOS descriptor as that could confuse host into
+ * thinking we can handle super speed.
+ *
+ * Note that, in fact, we won't even support GetBOS requests when speed
+ * is less than super speed because we don't have means, yet, to tell
+ * composite.c that we are USB 2.0 + LPM ECN.
+ */
+ if (dwc->revision < DWC3_REVISION_220A)
+ dwc3_trace(trace_dwc3_gadget,
+ "Changing max_speed on rev %08x\n",
+ dwc->revision);
+
+ dwc->gadget.max_speed = dwc->maximum_speed;
+
+ /*
* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
* on ep out.
*/
diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
index d3614ecbb9ca..2bb4d3ad0e6b 100644
--- a/drivers/usb/dwc3/platform_data.h
+++ b/drivers/usb/dwc3/platform_data.h
@@ -42,9 +42,12 @@ struct dwc3_platform_data {
unsigned rx_detect_poll_quirk:1;
unsigned dis_u3_susphy_quirk:1;
unsigned dis_u2_susphy_quirk:1;
+ unsigned dis_enblslpm_quirk:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
+ u32 fladj_value;
+
const char *hsphy_interface;
};
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bcf83c0a6e62..33834aa09ed4 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -113,7 +113,7 @@ config USB_GADGET_VBUS_DRAW
config USB_GADGET_STORAGE_NUM_BUFFERS
int "Number of storage pipeline buffers"
- range 2 4
+ range 2 32
default 2
help
Usually 2 buffers are enough to establish a good buffering
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index b474499839d3..8b14c2a13ac5 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -839,9 +839,7 @@ int usb_add_config(struct usb_composite_dev *cdev,
}
}
- /* set_alt(), or next bind(), sets up
- * ep->driver_data as needed.
- */
+ /* set_alt(), or next bind(), sets up ep->claimed as needed */
usb_ep_autoconfig_reset(cdev->gadget);
done:
@@ -1506,6 +1504,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
} else {
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
}
+ } else {
+ cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
value = min(w_length, (u16) sizeof cdev->desc);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 294eb74fb078..163d305e1200 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -64,6 +64,11 @@ struct gadget_info {
char qw_sign[OS_STRING_QW_SIGN_LEN];
};
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct gadget_info, group);
+}
+
struct config_usb_cfg {
struct config_group group;
struct config_group strings_group;
@@ -74,6 +79,12 @@ struct config_usb_cfg {
struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
};
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct config_usb_cfg,
+ group);
+}
+
struct gadget_strings {
struct usb_gadget_strings stringtab_dev;
struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
@@ -117,32 +128,25 @@ static int usb_string_copy(const char *s, char **s_copy)
return 0;
}
-CONFIGFS_ATTR_STRUCT(gadget_info);
-CONFIGFS_ATTR_STRUCT(config_usb_cfg);
-
-#define GI_DEVICE_DESC_ITEM_ATTR(name) \
- static struct gadget_info_attribute gadget_cdev_desc_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- gadget_dev_desc_##name##_show, \
- gadget_dev_desc_##name##_store)
-
#define GI_DEVICE_DESC_SIMPLE_R_u8(__name) \
- static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
char *page) \
{ \
- return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \
+ return sprintf(page, "0x%02x\n", \
+ to_gadget_info(item)->cdev.desc.__name); \
}
#define GI_DEVICE_DESC_SIMPLE_R_u16(__name) \
- static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
char *page) \
{ \
- return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+ return sprintf(page, "0x%04x\n", \
+ le16_to_cpup(&to_gadget_info(item)->cdev.desc.__name)); \
}
#define GI_DEVICE_DESC_SIMPLE_W_u8(_name) \
- static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
u8 val; \
@@ -150,12 +154,12 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
ret = kstrtou8(page, 0, &val); \
if (ret) \
return ret; \
- gi->cdev.desc._name = val; \
+ to_gadget_info(item)->cdev.desc._name = val; \
return len; \
}
#define GI_DEVICE_DESC_SIMPLE_W_u16(_name) \
- static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
u16 val; \
@@ -163,7 +167,7 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
ret = kstrtou16(page, 0, &val); \
if (ret) \
return ret; \
- gi->cdev.desc._name = cpu_to_le16p(&val); \
+ to_gadget_info(item)->cdev.desc._name = cpu_to_le16p(&val); \
return len; \
}
@@ -193,7 +197,7 @@ static ssize_t is_valid_bcd(u16 bcd_val)
return 0;
}
-static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdDevice_store(struct config_item *item,
const char *page, size_t len)
{
u16 bcdDevice;
@@ -206,11 +210,11 @@ static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
if (ret)
return ret;
- gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+ to_gadget_info(item)->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
return len;
}
-static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdUSB_store(struct config_item *item,
const char *page, size_t len)
{
u16 bcdUSB;
@@ -223,13 +227,13 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
if (ret)
return ret;
- gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+ to_gadget_info(item)->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
return len;
}
-static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page)
{
- return sprintf(page, "%s\n", gi->udc_name ?: "");
+ return sprintf(page, "%s\n", to_gadget_info(item)->udc_name ?: "");
}
static int unregister_gadget(struct gadget_info *gi)
@@ -247,9 +251,10 @@ static int unregister_gadget(struct gadget_info *gi)
return 0;
}
-static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
const char *page, size_t len)
{
+ struct gadget_info *gi = to_gadget_info(item);
char *name;
int ret;
@@ -283,34 +288,29 @@ err:
return ret;
}
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
-GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
-GI_DEVICE_DESC_ITEM_ATTR(idVendor);
-GI_DEVICE_DESC_ITEM_ATTR(idProduct);
-GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
-GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
-GI_DEVICE_DESC_ITEM_ATTR(UDC);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
+CONFIGFS_ATTR(gadget_dev_desc_, bMaxPacketSize0);
+CONFIGFS_ATTR(gadget_dev_desc_, idVendor);
+CONFIGFS_ATTR(gadget_dev_desc_, idProduct);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
+CONFIGFS_ATTR(gadget_dev_desc_, UDC);
static struct configfs_attribute *gadget_root_attrs[] = {
- &gadget_cdev_desc_bDeviceClass.attr,
- &gadget_cdev_desc_bDeviceSubClass.attr,
- &gadget_cdev_desc_bDeviceProtocol.attr,
- &gadget_cdev_desc_bMaxPacketSize0.attr,
- &gadget_cdev_desc_idVendor.attr,
- &gadget_cdev_desc_idProduct.attr,
- &gadget_cdev_desc_bcdDevice.attr,
- &gadget_cdev_desc_bcdUSB.attr,
- &gadget_cdev_desc_UDC.attr,
+ &gadget_dev_desc_attr_bDeviceClass,
+ &gadget_dev_desc_attr_bDeviceSubClass,
+ &gadget_dev_desc_attr_bDeviceProtocol,
+ &gadget_dev_desc_attr_bMaxPacketSize0,
+ &gadget_dev_desc_attr_idVendor,
+ &gadget_dev_desc_attr_idProduct,
+ &gadget_dev_desc_attr_bcdDevice,
+ &gadget_dev_desc_attr_bcdUSB,
+ &gadget_dev_desc_attr_UDC,
NULL,
};
-static inline struct gadget_info *to_gadget_info(struct config_item *item)
-{
- return container_of(to_config_group(item), struct gadget_info, group);
-}
-
static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
{
return container_of(to_config_group(item), struct gadget_strings,
@@ -324,12 +324,6 @@ static inline struct gadget_config_name *to_gadget_config_name(
group);
}
-static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
-{
- return container_of(to_config_group(item), struct config_usb_cfg,
- group);
-}
-
static inline struct usb_function_instance *to_usb_function_instance(
struct config_item *item)
{
@@ -348,12 +342,8 @@ static void gadget_info_attr_release(struct config_item *item)
kfree(gi);
}
-CONFIGFS_ATTR_OPS(gadget_info);
-
static struct configfs_item_operations gadget_root_item_ops = {
.release = gadget_info_attr_release,
- .show_attribute = gadget_info_attr_show,
- .store_attribute = gadget_info_attr_store,
};
static void gadget_config_attr_release(struct config_item *item)
@@ -454,24 +444,20 @@ static int config_usb_cfg_unlink(
return 0;
}
-CONFIGFS_ATTR_OPS(config_usb_cfg);
-
static struct configfs_item_operations gadget_config_item_ops = {
.release = gadget_config_attr_release,
- .show_attribute = config_usb_cfg_attr_show,
- .store_attribute = config_usb_cfg_attr_store,
.allow_link = config_usb_cfg_link,
.drop_link = config_usb_cfg_unlink,
};
-static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_show(struct config_item *item,
char *page)
{
- return sprintf(page, "%u\n", cfg->c.MaxPower);
+ return sprintf(page, "%u\n", to_config_usb_cfg(item)->c.MaxPower);
}
-static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_store(struct config_item *item,
const char *page, size_t len)
{
u16 val;
@@ -481,17 +467,18 @@ static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
return ret;
if (DIV_ROUND_UP(val, 8) > 0xff)
return -ERANGE;
- cfg->c.MaxPower = val;
+ to_config_usb_cfg(item)->c.MaxPower = val;
return len;
}
-static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_item *item,
char *page)
{
- return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+ return sprintf(page, "0x%02x\n",
+ to_config_usb_cfg(item)->c.bmAttributes);
}
-static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_item *item,
const char *page, size_t len)
{
u8 val;
@@ -504,22 +491,16 @@ static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
USB_CONFIG_ATT_WAKEUP))
return -EINVAL;
- cfg->c.bmAttributes = val;
+ to_config_usb_cfg(item)->c.bmAttributes = val;
return len;
}
-#define CFG_CONFIG_DESC_ITEM_ATTR(name) \
- static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- gadget_config_desc_##name##_show, \
- gadget_config_desc_##name##_store)
-
-CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
-CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+CONFIGFS_ATTR(gadget_config_desc_, MaxPower);
+CONFIGFS_ATTR(gadget_config_desc_, bmAttributes);
static struct configfs_attribute *gadget_config_attrs[] = {
- &gadget_usb_cfg_MaxPower.attr,
- &gadget_usb_cfg_bmAttributes.attr,
+ &gadget_config_desc_attr_MaxPower,
+ &gadget_config_desc_attr_bmAttributes,
NULL,
};
@@ -616,11 +597,10 @@ static struct config_item_type functions_type = {
.ct_owner = THIS_MODULE,
};
-CONFIGFS_ATTR_STRUCT(gadget_config_name);
GS_STRINGS_RW(gadget_config_name, configuration);
static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
- &gadget_config_name_configuration.attr,
+ &gadget_config_name_attr_configuration,
NULL,
};
@@ -719,15 +699,14 @@ static struct config_item_type config_desc_type = {
.ct_owner = THIS_MODULE,
};
-CONFIGFS_ATTR_STRUCT(gadget_strings);
GS_STRINGS_RW(gadget_strings, manufacturer);
GS_STRINGS_RW(gadget_strings, product);
GS_STRINGS_RW(gadget_strings, serialnumber);
static struct configfs_attribute *gadget_strings_langid_attrs[] = {
- &gadget_strings_manufacturer.attr,
- &gadget_strings_product.attr,
- &gadget_strings_serialnumber.attr,
+ &gadget_strings_attr_manufacturer,
+ &gadget_strings_attr_product,
+ &gadget_strings_attr_serialnumber,
NULL,
};
@@ -751,27 +730,25 @@ static inline struct os_desc *to_os_desc(struct config_item *item)
return container_of(to_config_group(item), struct os_desc, group);
}
-CONFIGFS_ATTR_STRUCT(os_desc);
-CONFIGFS_ATTR_OPS(os_desc);
-
-static ssize_t os_desc_use_show(struct os_desc *os_desc, char *page)
+static inline struct gadget_info *os_desc_item_to_gadget_info(
+ struct config_item *item)
{
- struct gadget_info *gi;
-
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+ return to_gadget_info(to_os_desc(item)->group.cg_item.ci_parent);
+}
- return sprintf(page, "%d", gi->use_os_desc);
+static ssize_t os_desc_use_show(struct config_item *item, char *page)
+{
+ return sprintf(page, "%d",
+ os_desc_item_to_gadget_info(item)->use_os_desc);
}
-static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_use_store(struct config_item *item, const char *page,
size_t len)
{
- struct gadget_info *gi;
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int ret;
bool use;
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
mutex_lock(&gi->lock);
ret = strtobool(page, &use);
if (!ret) {
@@ -783,29 +760,19 @@ static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
return ret;
}
-static struct os_desc_attribute os_desc_use =
- __CONFIGFS_ATTR(use, S_IRUGO | S_IWUSR,
- os_desc_use_show,
- os_desc_use_store);
-
-static ssize_t os_desc_b_vendor_code_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page)
{
- struct gadget_info *gi;
-
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
- return sprintf(page, "%d", gi->b_vendor_code);
+ return sprintf(page, "%d",
+ os_desc_item_to_gadget_info(item)->b_vendor_code);
}
-static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
+static ssize_t os_desc_b_vendor_code_store(struct config_item *item,
const char *page, size_t len)
{
- struct gadget_info *gi;
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int ret;
u8 b_vendor_code;
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
mutex_lock(&gi->lock);
ret = kstrtou8(page, 0, &b_vendor_code);
if (!ret) {
@@ -817,29 +784,20 @@ static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
return ret;
}
-static struct os_desc_attribute os_desc_b_vendor_code =
- __CONFIGFS_ATTR(b_vendor_code, S_IRUGO | S_IWUSR,
- os_desc_b_vendor_code_show,
- os_desc_b_vendor_code_store);
-
-static ssize_t os_desc_qw_sign_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)
{
- struct gadget_info *gi;
-
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
-
return OS_STRING_QW_SIGN_LEN;
}
-static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
size_t len)
{
- struct gadget_info *gi;
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int res, l;
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
if (page[l - 1] == '\n')
--l;
@@ -855,15 +813,14 @@ static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
return res;
}
-static struct os_desc_attribute os_desc_qw_sign =
- __CONFIGFS_ATTR(qw_sign, S_IRUGO | S_IWUSR,
- os_desc_qw_sign_show,
- os_desc_qw_sign_store);
+CONFIGFS_ATTR(os_desc_, use);
+CONFIGFS_ATTR(os_desc_, b_vendor_code);
+CONFIGFS_ATTR(os_desc_, qw_sign);
static struct configfs_attribute *os_desc_attrs[] = {
- &os_desc_use.attr,
- &os_desc_b_vendor_code.attr,
- &os_desc_qw_sign.attr,
+ &os_desc_attr_use,
+ &os_desc_attr_b_vendor_code,
+ &os_desc_attr_qw_sign,
NULL,
};
@@ -926,8 +883,6 @@ static int os_desc_unlink(struct config_item *os_desc_ci,
static struct configfs_item_operations os_desc_ops = {
.release = os_desc_attr_release,
- .show_attribute = os_desc_attr_show,
- .store_attribute = os_desc_attr_store,
.allow_link = os_desc_link,
.drop_link = os_desc_unlink,
};
@@ -938,28 +893,21 @@ static struct config_item_type os_desc_type = {
.ct_owner = THIS_MODULE,
};
-CONFIGFS_ATTR_STRUCT(usb_os_desc);
-CONFIGFS_ATTR_OPS(usb_os_desc);
-
-
static inline struct usb_os_desc_ext_prop
*to_usb_os_desc_ext_prop(struct config_item *item)
{
return container_of(item, struct usb_os_desc_ext_prop, item);
}
-CONFIGFS_ATTR_STRUCT(usb_os_desc_ext_prop);
-CONFIGFS_ATTR_OPS(usb_os_desc_ext_prop);
-
-static ssize_t ext_prop_type_show(struct usb_os_desc_ext_prop *ext_prop,
- char *page)
+static ssize_t ext_prop_type_show(struct config_item *item, char *page)
{
- return sprintf(page, "%d", ext_prop->type);
+ return sprintf(page, "%d", to_usb_os_desc_ext_prop(item)->type);
}
-static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_type_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
u8 type;
int ret;
@@ -997,9 +945,9 @@ end:
return ret;
}
-static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
- char *page)
+static ssize_t ext_prop_data_show(struct config_item *item, char *page)
{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
int len = ext_prop->data_len;
if (ext_prop->type == USB_EXT_PROP_UNICODE ||
@@ -1011,9 +959,10 @@ static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
return len;
}
-static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_data_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
char *new_data;
size_t ret_len = len;
@@ -1044,17 +993,12 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
return ret_len;
}
-static struct usb_os_desc_ext_prop_attribute ext_prop_type =
- __CONFIGFS_ATTR(type, S_IRUGO | S_IWUSR,
- ext_prop_type_show, ext_prop_type_store);
-
-static struct usb_os_desc_ext_prop_attribute ext_prop_data =
- __CONFIGFS_ATTR(data, S_IRUGO | S_IWUSR,
- ext_prop_data_show, ext_prop_data_store);
+CONFIGFS_ATTR(ext_prop_, type);
+CONFIGFS_ATTR(ext_prop_, data);
static struct configfs_attribute *ext_prop_attrs[] = {
- &ext_prop_type.attr,
- &ext_prop_data.attr,
+ &ext_prop_attr_type,
+ &ext_prop_attr_data,
NULL,
};
@@ -1067,8 +1011,6 @@ static void usb_os_desc_ext_prop_release(struct config_item *item)
static struct configfs_item_operations ext_prop_ops = {
.release = usb_os_desc_ext_prop_release,
- .show_attribute = usb_os_desc_ext_prop_attr_show,
- .store_attribute = usb_os_desc_ext_prop_attr_store,
};
static struct config_item *ext_prop_make(
@@ -1137,21 +1079,17 @@ static struct configfs_group_operations interf_grp_ops = {
.drop_item = &ext_prop_drop,
};
-static struct configfs_item_operations interf_item_ops = {
- .show_attribute = usb_os_desc_attr_show,
- .store_attribute = usb_os_desc_attr_store,
-};
-
-static ssize_t interf_grp_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_show(struct config_item *item,
char *page)
{
- memcpy(page, desc->ext_compat_id, 8);
+ memcpy(page, to_usb_os_desc(item)->ext_compat_id, 8);
return 8;
}
-static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc *desc = to_usb_os_desc(item);
int l;
l = min_t(int, 8, len);
@@ -1167,21 +1105,17 @@ static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
return len;
}
-static struct usb_os_desc_attribute interf_grp_attr_compatible_id =
- __CONFIGFS_ATTR(compatible_id, S_IRUGO | S_IWUSR,
- interf_grp_compatible_id_show,
- interf_grp_compatible_id_store);
-
-static ssize_t interf_grp_sub_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_show(struct config_item *item,
char *page)
{
- memcpy(page, desc->ext_compat_id + 8, 8);
+ memcpy(page, to_usb_os_desc(item)->ext_compat_id + 8, 8);
return 8;
}
-static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc *desc = to_usb_os_desc(item);
int l;
l = min_t(int, 8, len);
@@ -1197,14 +1131,12 @@ static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
return len;
}
-static struct usb_os_desc_attribute interf_grp_attr_sub_compatible_id =
- __CONFIGFS_ATTR(sub_compatible_id, S_IRUGO | S_IWUSR,
- interf_grp_sub_compatible_id_show,
- interf_grp_sub_compatible_id_store);
+CONFIGFS_ATTR(interf_grp_, compatible_id);
+CONFIGFS_ATTR(interf_grp_, sub_compatible_id);
static struct configfs_attribute *interf_grp_attrs[] = {
- &interf_grp_attr_compatible_id.attr,
- &interf_grp_attr_sub_compatible_id.attr,
+ &interf_grp_attr_compatible_id,
+ &interf_grp_attr_sub_compatible_id,
NULL
};
@@ -1242,7 +1174,6 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
f_default_groups[0] = os_desc_group;
os_desc_group->default_groups = interface_groups;
- interface_type->ct_item_ops = &interf_item_ops;
interface_type->ct_group_ops = &interf_grp_ops;
interface_type->ct_attrs = interf_grp_attrs;
interface_type->ct_owner = owner;
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 6399c106a3a5..30fdab0ae383 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -53,13 +53,13 @@
* the restrictions that may apply. Some combinations of driver
* and hardware won't be able to autoconfigure.
*
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * 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 and
* the bmAttribute field in the ep companion descriptor is
* updated with the assigned number of streams if it is
* different from the original value. To prevent the endpoint
- * from being returned by a later autoconfig call, claim it by
+ * from being returned by a later autoconfig call, claims it by
* assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
@@ -154,10 +154,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
* USB controller, and it can't know all the restrictions that may apply.
* Some combinations of driver and hardware won't be able to autoconfigure.
*
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * 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, claim it
+ * 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.
@@ -172,6 +172,23 @@ struct usb_ep *usb_ep_autoconfig(
EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
/**
+ * usb_ep_autoconfig_release - releases endpoint and set it to initial state
+ * @ep: endpoint which should be released
+ *
+ * This function can be used during function bind for endpoints obtained
+ * from usb_ep_autoconfig(). It unclaims endpoint claimed by
+ * usb_ep_autoconfig() to make it available for other functions. Endpoint
+ * which was released is no longer invalid and shouldn't be used in
+ * context of function which released it.
+ */
+void usb_ep_autoconfig_release(struct usb_ep *ep)
+{
+ ep->claimed = false;
+ ep->driver_data = NULL;
+}
+EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release);
+
+/**
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
* @gadget: device for which autoconfig state will be reset
*
diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c
index be9df09fde26..2fa1e80a3ce7 100644
--- a/drivers/usb/gadget/function/f_acm.c
+++ b/drivers/usb/gadget/function/f_acm.c
@@ -428,21 +428,18 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
if (intf == acm->ctrl_id) {
- if (acm->notify->driver_data) {
- dev_vdbg(&cdev->gadget->dev,
- "reset acm control interface %d\n", intf);
- usb_ep_disable(acm->notify);
- }
+ dev_vdbg(&cdev->gadget->dev,
+ "reset acm control interface %d\n", intf);
+ usb_ep_disable(acm->notify);
if (!acm->notify->desc)
if (config_ep_by_speed(cdev->gadget, f, acm->notify))
return -EINVAL;
usb_ep_enable(acm->notify);
- acm->notify->driver_data = acm;
} else if (intf == acm->data_id) {
- if (acm->port.in->driver_data) {
+ if (acm->notify->enabled) {
dev_dbg(&cdev->gadget->dev,
"reset acm ttyGS%d\n", acm->port_num);
gserial_disconnect(&acm->port);
@@ -475,7 +472,6 @@ static void acm_disable(struct usb_function *f)
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n", acm->port_num);
gserial_disconnect(&acm->port);
usb_ep_disable(acm->notify);
- acm->notify->driver_data = NULL;
}
/*-------------------------------------------------------------------------*/
@@ -655,19 +651,16 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
acm->port.in = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
if (!ep)
goto fail;
acm->port.out = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
if (!ep)
goto fail;
acm->notify = ep;
- ep->driver_data = cdev; /* claim */
/* allocate notification */
acm->notify_req = gs_alloc_req(ep,
@@ -709,14 +702,6 @@ fail:
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
- /* we might as well release our claims on endpoints */
- if (acm->notify)
- acm->notify->driver_data = NULL;
- if (acm->port.out)
- acm->port.out->driver_data = NULL;
- if (acm->port.in)
- acm->port.in->driver_data = NULL;
-
ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
return status;
@@ -776,21 +761,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_acm_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_serial_opts *opts = to_f_serial_opts(item);
- struct f_serial_opts_attribute *f_serial_opts_attr =
- container_of(attr, struct f_serial_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_serial_opts_attr->show)
- ret = f_serial_opts_attr->show(opts, page);
- return ret;
-}
-
static void acm_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -800,20 +770,17 @@ static void acm_attr_release(struct config_item *item)
static struct configfs_item_operations acm_item_ops = {
.release = acm_attr_release,
- .show_attribute = f_acm_attr_show,
};
-static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_acm_port_num_show(struct config_item *item, char *page)
{
- return sprintf(page, "%u\n", opts->port_num);
+ return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
}
-static struct f_serial_opts_attribute f_acm_port_num =
- __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
-
+CONFIGFS_ATTR_RO(f_acm_port_, num);
static struct configfs_attribute *acm_attrs[] = {
- &f_acm_port_num.attr,
+ &f_acm_port_attr_num,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c
index 7b7424f10ddd..7ad60ee41914 100644
--- a/drivers/usb/gadget/function/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
@@ -541,24 +541,21 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt != 0)
goto fail;
- if (ecm->notify->driver_data) {
- VDBG(cdev, "reset ecm control %d\n", intf);
- usb_ep_disable(ecm->notify);
- }
+ VDBG(cdev, "reset ecm control %d\n", intf);
+ usb_ep_disable(ecm->notify);
if (!(ecm->notify->desc)) {
VDBG(cdev, "init ecm ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
goto fail;
}
usb_ep_enable(ecm->notify);
- ecm->notify->driver_data = ecm;
/* Data interface has two altsettings, 0 and 1 */
} else if (intf == ecm->data_id) {
if (alt > 1)
goto fail;
- if (ecm->port.in_ep->driver_data) {
+ if (ecm->port.in_ep->enabled) {
DBG(cdev, "reset ecm\n");
gether_disconnect(&ecm->port);
}
@@ -618,7 +615,7 @@ static int ecm_get_alt(struct usb_function *f, unsigned intf)
if (intf == ecm->ctrl_id)
return 0;
- return ecm->port.in_ep->driver_data ? 1 : 0;
+ return ecm->port.in_ep->enabled ? 1 : 0;
}
static void ecm_disable(struct usb_function *f)
@@ -628,14 +625,11 @@ static void ecm_disable(struct usb_function *f)
DBG(cdev, "ecm deactivated\n");
- if (ecm->port.in_ep->driver_data)
+ if (ecm->port.in_ep->enabled)
gether_disconnect(&ecm->port);
- if (ecm->notify->driver_data) {
- usb_ep_disable(ecm->notify);
- ecm->notify->driver_data = NULL;
- ecm->notify->desc = NULL;
- }
+ usb_ep_disable(ecm->notify);
+ ecm->notify->desc = NULL;
}
/*-------------------------------------------------------------------------*/
@@ -750,13 +744,11 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
ecm->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
if (!ep)
goto fail;
ecm->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
/* NOTE: a status/notification endpoint is *OPTIONAL* but we
* don't treat it that way. It's simpler, and some newer CDC
@@ -766,7 +758,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
ecm->notify = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -820,14 +811,6 @@ fail:
usb_ep_free_request(ecm->notify, ecm->notify_req);
}
- /* we might as well release our claims on endpoints */
- if (ecm->notify)
- ecm->notify->driver_data = NULL;
- if (ecm->port.out_ep)
- ecm->port.out_ep->driver_data = NULL;
- if (ecm->port.in_ep)
- ecm->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -855,10 +838,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm);
static struct configfs_attribute *ecm_attrs[] = {
- &f_ecm_opts_dev_addr.attr,
- &f_ecm_opts_host_addr.attr,
- &f_ecm_opts_qmult.attr,
- &f_ecm_opts_ifname.attr,
+ &ecm_opts_attr_dev_addr,
+ &ecm_opts_attr_host_addr,
+ &ecm_opts_attr_qmult,
+ &ecm_opts_attr_ifname,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c
index c9e90de5bdd9..cad35a502d3f 100644
--- a/drivers/usb/gadget/function/f_eem.c
+++ b/drivers/usb/gadget/function/f_eem.c
@@ -195,11 +195,8 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
goto fail;
if (intf == eem->ctrl_id) {
-
- if (eem->port.in_ep->driver_data) {
- DBG(cdev, "reset eem\n");
- gether_disconnect(&eem->port);
- }
+ DBG(cdev, "reset eem\n");
+ gether_disconnect(&eem->port);
if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) {
DBG(cdev, "init eem\n");
@@ -237,7 +234,7 @@ static void eem_disable(struct usb_function *f)
DBG(cdev, "eem deactivated\n");
- if (eem->port.in_ep->driver_data)
+ if (eem->port.in_ep->enabled)
gether_disconnect(&eem->port);
}
@@ -293,13 +290,11 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
eem->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &eem_fs_out_desc);
if (!ep)
goto fail;
eem->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -325,11 +320,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (eem->port.out_ep)
- eem->port.out_ep->driver_data = NULL;
- if (eem->port.in_ep)
- eem->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -555,10 +545,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(eem);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(eem);
static struct configfs_attribute *eem_attrs[] = {
- &f_eem_opts_dev_addr.attr,
- &f_eem_opts_host_addr.attr,
- &f_eem_opts_qmult.attr,
- &f_eem_opts_ifname.attr,
+ &eem_opts_attr_dev_addr,
+ &eem_opts_attr_host_addr,
+ &eem_opts_attr_qmult,
+ &eem_opts_attr_ifname,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index 6df9715a4bcd..99285b416308 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -492,10 +492,7 @@ static void hidg_disable(struct usb_function *f)
struct f_hidg_req_list *list, *next;
usb_ep_disable(hidg->in_ep);
- hidg->in_ep->driver_data = NULL;
-
usb_ep_disable(hidg->out_ep);
- hidg->out_ep->driver_data = NULL;
list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
list_del(&list->list);
@@ -513,8 +510,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (hidg->in_ep != NULL) {
/* restart endpoint */
- if (hidg->in_ep->driver_data != NULL)
- usb_ep_disable(hidg->in_ep);
+ usb_ep_disable(hidg->in_ep);
status = config_ep_by_speed(f->config->cdev->gadget, f,
hidg->in_ep);
@@ -533,8 +529,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (hidg->out_ep != NULL) {
/* restart endpoint */
- if (hidg->out_ep->driver_data != NULL)
- usb_ep_disable(hidg->out_ep);
+ usb_ep_disable(hidg->out_ep);
status = config_ep_by_speed(f->config->cdev->gadget, f,
hidg->out_ep);
@@ -566,7 +561,6 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
hidg->out_ep->name, status);
} else {
usb_ep_disable(hidg->out_ep);
- hidg->out_ep->driver_data = NULL;
status = -ENOMEM;
goto fail;
}
@@ -614,13 +608,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
if (!ep)
goto fail;
- ep->driver_data = c->cdev; /* claim */
hidg->in_ep = ep;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
if (!ep)
goto fail;
- ep->driver_data = c->cdev; /* claim */
hidg->out_ep = ep;
/* preallocate request and buffer */
@@ -713,9 +705,6 @@ static inline struct f_hid_opts *to_f_hid_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_hid_opts);
-CONFIGFS_ATTR_OPS(f_hid_opts);
-
static void hid_attr_release(struct config_item *item)
{
struct f_hid_opts *opts = to_f_hid_opts(item);
@@ -725,13 +714,12 @@ static void hid_attr_release(struct config_item *item)
static struct configfs_item_operations hidg_item_ops = {
.release = hid_attr_release,
- .show_attribute = f_hid_opts_attr_show,
- .store_attribute = f_hid_opts_attr_store,
};
#define F_HID_OPT(name, prec, limit) \
-static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\
+static ssize_t f_hid_opts_##name##_show(struct config_item *item, char *page)\
{ \
+ struct f_hid_opts *opts = to_f_hid_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -741,9 +729,10 @@ static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\
return result; \
} \
\
-static ssize_t f_hid_opts_##name##_store(struct f_hid_opts *opts, \
+static ssize_t f_hid_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_hid_opts *opts = to_f_hid_opts(item); \
int ret; \
u##prec num; \
\
@@ -769,16 +758,15 @@ end: \
return ret; \
} \
\
-static struct f_hid_opts_attribute f_hid_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_hid_opts_##name##_show,\
- f_hid_opts_##name##_store)
+CONFIGFS_ATTR(f_hid_opts_, name)
F_HID_OPT(subclass, 8, 255);
F_HID_OPT(protocol, 8, 255);
F_HID_OPT(report_length, 16, 65535);
-static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page)
+static ssize_t f_hid_opts_report_desc_show(struct config_item *item, char *page)
{
+ struct f_hid_opts *opts = to_f_hid_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -789,9 +777,10 @@ static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page)
return result;
}
-static ssize_t f_hid_opts_report_desc_store(struct f_hid_opts *opts,
+static ssize_t f_hid_opts_report_desc_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_hid_opts *opts = to_f_hid_opts(item);
int ret = -EBUSY;
char *d;
@@ -818,16 +807,13 @@ end:
return ret;
}
-static struct f_hid_opts_attribute f_hid_opts_report_desc =
- __CONFIGFS_ATTR(report_desc, S_IRUGO | S_IWUSR,
- f_hid_opts_report_desc_show,
- f_hid_opts_report_desc_store);
+CONFIGFS_ATTR(f_hid_opts_, report_desc);
static struct configfs_attribute *hid_attrs[] = {
- &f_hid_opts_subclass.attr,
- &f_hid_opts_protocol.attr,
- &f_hid_opts_report_length.attr,
- &f_hid_opts_report_desc.attr,
+ &f_hid_opts_attr_subclass,
+ &f_hid_opts_attr_protocol,
+ &f_hid_opts_attr_report_length,
+ &f_hid_opts_attr_report_desc,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c
index 6e2fe63b9267..ddc3aad886b7 100644
--- a/drivers/usb/gadget/function/f_loopback.c
+++ b/drivers/usb/gadget/function/f_loopback.c
@@ -34,6 +34,9 @@ struct f_loopback {
struct usb_ep *in_ep;
struct usb_ep *out_ep;
+
+ unsigned qlen;
+ unsigned buflen;
};
static inline struct f_loopback *func_to_loop(struct usb_function *f)
@@ -41,13 +44,10 @@ static inline struct f_loopback *func_to_loop(struct usb_function *f)
return container_of(f, struct f_loopback, function);
}
-static unsigned qlen;
-static unsigned buflen;
-
/*-------------------------------------------------------------------------*/
static struct usb_interface_descriptor loopback_intf = {
- .bLength = sizeof loopback_intf,
+ .bLength = sizeof(loopback_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bNumEndpoints = 2,
@@ -195,12 +195,10 @@ autoconf_fail:
f->name, cdev->gadget->name);
return -ENODEV;
}
- loop->in_ep->driver_data = cdev; /* claim */
loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
if (!loop->out_ep)
goto autoconf_fail;
- loop->out_ep->driver_data = cdev; /* claim */
/* support high speed hardware */
hs_loop_source_desc.bEndpointAddress =
@@ -245,22 +243,38 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
int status = req->status;
switch (status) {
-
case 0: /* normal completion? */
if (ep == loop->out_ep) {
- req->zero = (req->actual < req->length);
- req->length = req->actual;
+ /*
+ * We received some data from the host so let's
+ * queue it so host can read the from our in ep
+ */
+ struct usb_request *in_req = req->context;
+
+ in_req->zero = (req->actual < req->length);
+ in_req->length = req->actual;
+ ep = loop->in_ep;
+ req = in_req;
+ } else {
+ /*
+ * We have just looped back a bunch of data
+ * to host. Now let's wait for some more data.
+ */
+ req = req->context;
+ ep = loop->out_ep;
}
- /* queue the buffer for some later OUT packet */
- req->length = buflen;
+ /* queue the buffer back to host or for next bunch of data */
status = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (status == 0)
+ if (status == 0) {
return;
+ } else {
+ ERROR(cdev, "Unable to loop back buffer to %s: %d\n",
+ ep->name, status);
+ goto free_req;
+ }
/* "should never get here" */
- /* FALLTHROUGH */
-
default:
ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
status, req->actual, req->length);
@@ -274,6 +288,10 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
+free_req:
+ usb_ep_free_request(ep == loop->in_ep ?
+ loop->out_ep : loop->in_ep,
+ req->context);
free_ep_req(ep, req);
return;
}
@@ -290,53 +308,77 @@ static void disable_loopback(struct f_loopback *loop)
static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
{
- return alloc_ep_req(ep, len, buflen);
+ struct f_loopback *loop = ep->driver_data;
+
+ return alloc_ep_req(ep, len, loop->buflen);
}
-static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop,
- struct usb_ep *ep)
+static int alloc_requests(struct usb_composite_dev *cdev,
+ struct f_loopback *loop)
{
- struct usb_request *req;
- unsigned i;
- int result;
-
- /*
- * one endpoint writes data back IN to the host while another endpoint
- * just reads OUT packets
- */
- result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
- if (result)
- goto fail0;
- result = usb_ep_enable(ep);
- if (result < 0)
- goto fail0;
- ep->driver_data = loop;
+ struct usb_request *in_req, *out_req;
+ int i;
+ int result = 0;
/*
* allocate a bunch of read buffers and queue them all at once.
- * we buffer at most 'qlen' transfers; fewer if any need more
- * than 'buflen' bytes each.
+ * we buffer at most 'qlen' transfers; We allocate buffers only
+ * for out transfer and reuse them in IN transfers to implement
+ * our loopback functionality
*/
- for (i = 0; i < qlen && result == 0; i++) {
- req = lb_alloc_ep_req(ep, 0);
- if (!req)
- goto fail1;
+ for (i = 0; i < loop->qlen && result == 0; i++) {
+ result = -ENOMEM;
+
+ in_req = usb_ep_alloc_request(loop->in_ep, GFP_ATOMIC);
+ if (!in_req)
+ goto fail;
+
+ out_req = lb_alloc_ep_req(loop->out_ep, 0);
+ if (!out_req)
+ goto fail_in;
+
+ in_req->complete = loopback_complete;
+ out_req->complete = loopback_complete;
- req->complete = loopback_complete;
- result = usb_ep_queue(ep, req, GFP_ATOMIC);
+ in_req->buf = out_req->buf;
+ /* length will be set in complete routine */
+ in_req->context = out_req;
+ out_req->context = in_req;
+
+ result = usb_ep_queue(loop->out_ep, out_req, GFP_ATOMIC);
if (result) {
ERROR(cdev, "%s queue req --> %d\n",
- ep->name, result);
- goto fail1;
+ loop->out_ep->name, result);
+ goto fail_out;
}
}
return 0;
-fail1:
- usb_ep_disable(ep);
+fail_out:
+ free_ep_req(loop->out_ep, out_req);
+fail_in:
+ usb_ep_free_request(loop->in_ep, in_req);
+fail:
+ return result;
+}
+
+static int enable_endpoint(struct usb_composite_dev *cdev,
+ struct f_loopback *loop, struct usb_ep *ep)
+{
+ int result;
+
+ result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
+ if (result)
+ goto out;
-fail0:
+ result = usb_ep_enable(ep);
+ if (result < 0)
+ goto out;
+ ep->driver_data = loop;
+ result = 0;
+
+out:
return result;
}
@@ -347,13 +389,24 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
result = enable_endpoint(cdev, loop, loop->in_ep);
if (result)
- return result;
+ goto out;
result = enable_endpoint(cdev, loop, loop->out_ep);
if (result)
- return result;
+ goto disable_in;
+
+ result = alloc_requests(cdev, loop);
+ if (result)
+ goto disable_out;
DBG(cdev, "%s enabled\n", loop->function.name);
+ return 0;
+
+disable_out:
+ usb_ep_disable(loop->out_ep);
+disable_in:
+ usb_ep_disable(loop->in_ep);
+out:
return result;
}
@@ -364,8 +417,7 @@ static int loopback_set_alt(struct usb_function *f,
struct usb_composite_dev *cdev = f->config->cdev;
/* we know alt is zero */
- if (loop->in_ep->driver_data)
- disable_loopback(loop);
+ disable_loopback(loop);
return enable_loopback(cdev, loop);
}
@@ -391,10 +443,10 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
lb_opts->refcnt++;
mutex_unlock(&lb_opts->lock);
- buflen = lb_opts->bulk_buflen;
- qlen = lb_opts->qlen;
- if (!qlen)
- qlen = 32;
+ loop->buflen = lb_opts->bulk_buflen;
+ loop->qlen = lb_opts->qlen;
+ if (!loop->qlen)
+ loop->qlen = 32;
loop->function.name = "loopback";
loop->function.bind = loopback_bind;
@@ -413,9 +465,6 @@ static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_lb_opts);
-CONFIGFS_ATTR_OPS(f_lb_opts);
-
static void lb_attr_release(struct config_item *item)
{
struct f_lb_opts *lb_opts = to_f_lb_opts(item);
@@ -425,24 +474,24 @@ static void lb_attr_release(struct config_item *item)
static struct configfs_item_operations lb_item_ops = {
.release = lb_attr_release,
- .show_attribute = f_lb_opts_attr_show,
- .store_attribute = f_lb_opts_attr_store,
};
-static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
+static ssize_t f_lb_opts_qlen_show(struct config_item *item, char *page)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%d", opts->qlen);
+ result = sprintf(page, "%d\n", opts->qlen);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
+static ssize_t f_lb_opts_qlen_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int ret;
u32 num;
@@ -463,25 +512,24 @@ end:
return ret;
}
-static struct f_lb_opts_attribute f_lb_opts_qlen =
- __CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR,
- f_lb_opts_qlen_show,
- f_lb_opts_qlen_store);
+CONFIGFS_ATTR(f_lb_opts_, qlen);
-static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
+static ssize_t f_lb_opts_bulk_buflen_show(struct config_item *item, char *page)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%d", opts->bulk_buflen);
+ result = sprintf(page, "%d\n", opts->bulk_buflen);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
+static ssize_t f_lb_opts_bulk_buflen_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int ret;
u32 num;
@@ -502,14 +550,11 @@ end:
return ret;
}
-static struct f_lb_opts_attribute f_lb_opts_bulk_buflen =
- __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
- f_lb_opts_bulk_buflen_show,
- f_lb_opts_bulk_buflen_store);
+CONFIGFS_ATTR(f_lb_opts_, bulk_buflen);
static struct configfs_attribute *lb_attrs[] = {
- &f_lb_opts_qlen.attr,
- &f_lb_opts_bulk_buflen.attr,
+ &f_lb_opts_attr_qlen,
+ &f_lb_opts_attr_bulk_buflen,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index a6eb537d7768..223ccf89d226 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2258,12 +2258,10 @@ reset:
/* Disable the endpoints */
if (fsg->bulk_in_enabled) {
usb_ep_disable(fsg->bulk_in);
- fsg->bulk_in->driver_data = NULL;
fsg->bulk_in_enabled = 0;
}
if (fsg->bulk_out_enabled) {
usb_ep_disable(fsg->bulk_out);
- fsg->bulk_out->driver_data = NULL;
fsg->bulk_out_enabled = 0;
}
@@ -2347,7 +2345,6 @@ static void fsg_disable(struct usb_function *f)
static void handle_exception(struct fsg_common *common)
{
- siginfo_t info;
int i;
struct fsg_buffhd *bh;
enum fsg_state old_state;
@@ -2359,8 +2356,7 @@ static void handle_exception(struct fsg_common *common)
* into a high-priority EXIT exception.
*/
for (;;) {
- int sig =
- dequeue_signal_lock(current, &current->blocked, &info);
+ int sig = kernel_dequeue_signal(NULL);
if (!sig)
break;
if (sig != SIGUSR1) {
@@ -2662,10 +2658,12 @@ EXPORT_SYMBOL_GPL(fsg_common_put);
/* check if fsg_num_buffers is within a valid range */
static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
{
- if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
+#define FSG_MAX_NUM_BUFFERS 32
+
+ if (fsg_num_buffers >= 2 && fsg_num_buffers <= FSG_MAX_NUM_BUFFERS)
return 0;
pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
- fsg_num_buffers, 2, 4);
+ fsg_num_buffers, 2, FSG_MAX_NUM_BUFFERS);
return -EINVAL;
}
@@ -3070,13 +3068,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
if (!ep)
goto autoconf_fail;
- ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_in = ep;
ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
if (!ep)
goto autoconf_fail;
- ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
/* Assume endpoint addresses are the same for both speeds */
@@ -3144,9 +3140,6 @@ static inline struct fsg_opts *to_fsg_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(fsg_lun_opts);
-CONFIGFS_ATTR_OPS(fsg_lun_opts);
-
static void fsg_lun_attr_release(struct config_item *item)
{
struct fsg_lun_opts *lun_opts;
@@ -3157,110 +3150,93 @@ static void fsg_lun_attr_release(struct config_item *item)
static struct configfs_item_operations fsg_lun_item_ops = {
.release = fsg_lun_attr_release,
- .show_attribute = fsg_lun_opts_attr_show,
- .store_attribute = fsg_lun_opts_attr_store,
};
-static ssize_t fsg_lun_opts_file_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_file_show(struct config_item *item, char *page)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_show_file(opts->lun, &fsg_opts->common->filesem, page);
}
-static ssize_t fsg_lun_opts_file_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_file_store(struct config_item *item,
const char *page, size_t len)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_file(opts->lun, &fsg_opts->common->filesem, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_file =
- __CONFIGFS_ATTR(file, S_IRUGO | S_IWUSR, fsg_lun_opts_file_show,
- fsg_lun_opts_file_store);
+CONFIGFS_ATTR(fsg_lun_opts_, file);
-static ssize_t fsg_lun_opts_ro_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_ro_show(struct config_item *item, char *page)
{
- return fsg_show_ro(opts->lun, page);
+ return fsg_show_ro(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_ro_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_ro_store(struct config_item *item,
const char *page, size_t len)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_ro(opts->lun, &fsg_opts->common->filesem, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_ro =
- __CONFIGFS_ATTR(ro, S_IRUGO | S_IWUSR, fsg_lun_opts_ro_show,
- fsg_lun_opts_ro_store);
+CONFIGFS_ATTR(fsg_lun_opts_, ro);
-static ssize_t fsg_lun_opts_removable_show(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_removable_show(struct config_item *item,
char *page)
{
- return fsg_show_removable(opts->lun, page);
+ return fsg_show_removable(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_removable_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_removable_store(struct config_item *item,
const char *page, size_t len)
{
- return fsg_store_removable(opts->lun, page, len);
+ return fsg_store_removable(to_fsg_lun_opts(item)->lun, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_removable =
- __CONFIGFS_ATTR(removable, S_IRUGO | S_IWUSR,
- fsg_lun_opts_removable_show,
- fsg_lun_opts_removable_store);
+CONFIGFS_ATTR(fsg_lun_opts_, removable);
-static ssize_t fsg_lun_opts_cdrom_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_cdrom_show(struct config_item *item, char *page)
{
- return fsg_show_cdrom(opts->lun, page);
+ return fsg_show_cdrom(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_cdrom_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_cdrom_store(struct config_item *item,
const char *page, size_t len)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_cdrom(opts->lun, &fsg_opts->common->filesem, page,
len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_cdrom =
- __CONFIGFS_ATTR(cdrom, S_IRUGO | S_IWUSR, fsg_lun_opts_cdrom_show,
- fsg_lun_opts_cdrom_store);
+CONFIGFS_ATTR(fsg_lun_opts_, cdrom);
-static ssize_t fsg_lun_opts_nofua_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_nofua_show(struct config_item *item, char *page)
{
- return fsg_show_nofua(opts->lun, page);
+ return fsg_show_nofua(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_nofua_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_nofua_store(struct config_item *item,
const char *page, size_t len)
{
- return fsg_store_nofua(opts->lun, page, len);
+ return fsg_store_nofua(to_fsg_lun_opts(item)->lun, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_nofua =
- __CONFIGFS_ATTR(nofua, S_IRUGO | S_IWUSR, fsg_lun_opts_nofua_show,
- fsg_lun_opts_nofua_store);
+CONFIGFS_ATTR(fsg_lun_opts_, nofua);
static struct configfs_attribute *fsg_lun_attrs[] = {
- &fsg_lun_opts_file.attr,
- &fsg_lun_opts_ro.attr,
- &fsg_lun_opts_removable.attr,
- &fsg_lun_opts_cdrom.attr,
- &fsg_lun_opts_nofua.attr,
+ &fsg_lun_opts_attr_file,
+ &fsg_lun_opts_attr_ro,
+ &fsg_lun_opts_attr_removable,
+ &fsg_lun_opts_attr_cdrom,
+ &fsg_lun_opts_attr_nofua,
NULL,
};
@@ -3352,9 +3328,6 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item)
config_item_put(item);
}
-CONFIGFS_ATTR_STRUCT(fsg_opts);
-CONFIGFS_ATTR_OPS(fsg_opts);
-
static void fsg_attr_release(struct config_item *item)
{
struct fsg_opts *opts = to_fsg_opts(item);
@@ -3364,12 +3337,11 @@ static void fsg_attr_release(struct config_item *item)
static struct configfs_item_operations fsg_item_ops = {
.release = fsg_attr_release,
- .show_attribute = fsg_opts_attr_show,
- .store_attribute = fsg_opts_attr_store,
};
-static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
+static ssize_t fsg_opts_stall_show(struct config_item *item, char *page)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -3379,9 +3351,10 @@ static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
return result;
}
-static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
+static ssize_t fsg_opts_stall_store(struct config_item *item, const char *page,
size_t len)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int ret;
bool stall;
@@ -3403,13 +3376,12 @@ static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
return ret;
}
-static struct fsg_opts_attribute fsg_opts_stall =
- __CONFIGFS_ATTR(stall, S_IRUGO | S_IWUSR, fsg_opts_stall_show,
- fsg_opts_stall_store);
+CONFIGFS_ATTR(fsg_opts_, stall);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
+static ssize_t fsg_opts_num_buffers_show(struct config_item *item, char *page)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -3419,9 +3391,10 @@ static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
return result;
}
-static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts,
+static ssize_t fsg_opts_num_buffers_store(struct config_item *item,
const char *page, size_t len)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int ret;
u8 num;
@@ -3446,17 +3419,13 @@ end:
return ret;
}
-static struct fsg_opts_attribute fsg_opts_num_buffers =
- __CONFIGFS_ATTR(num_buffers, S_IRUGO | S_IWUSR,
- fsg_opts_num_buffers_show,
- fsg_opts_num_buffers_store);
-
+CONFIGFS_ATTR(fsg_opts_, num_buffers);
#endif
static struct configfs_attribute *fsg_attrs[] = {
- &fsg_opts_stall.attr,
+ &fsg_opts_attr_stall,
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- &fsg_opts_num_buffers.attr,
+ &fsg_opts_attr_num_buffers,
#endif
NULL,
};
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index a287a4829273..42acb45e1ab4 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -302,8 +302,7 @@ static int f_midi_start_ep(struct f_midi *midi,
int err;
struct usb_composite_dev *cdev = f->config->cdev;
- if (ep->driver_data)
- usb_ep_disable(ep);
+ usb_ep_disable(ep);
err = config_ep_by_speed(midi->gadget, f, ep);
if (err) {
@@ -341,8 +340,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (err)
return err;
- if (midi->out_ep->driver_data)
- usb_ep_disable(midi->out_ep);
+ usb_ep_disable(midi->out_ep);
err = config_ep_by_speed(midi->gadget, f, midi->out_ep);
if (err) {
@@ -547,10 +545,16 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
}
}
- if (req->length > 0)
- usb_ep_queue(ep, req, GFP_ATOMIC);
- else
+ if (req->length > 0) {
+ int err;
+
+ err = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (err < 0)
+ ERROR(midi, "%s queue req: %d\n",
+ midi->in_ep->name, err);
+ } else {
free_ep_req(ep, req);
+ }
}
static void f_midi_in_tasklet(unsigned long data)
@@ -757,12 +761,10 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc);
if (!midi->in_ep)
goto fail;
- midi->in_ep->driver_data = cdev; /* claim */
midi->out_ep = usb_ep_autoconfig(cdev->gadget, &bulk_out_desc);
if (!midi->out_ep)
goto fail;
- midi->out_ep->driver_data = cdev; /* claim */
/* allocate temporary function list */
midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
@@ -889,12 +891,6 @@ fail_f_midi:
fail:
f_midi_unregister_card(midi);
fail_register:
- /* we might as well release our claims on endpoints */
- if (midi->out_ep)
- midi->out_ep->driver_data = NULL;
- if (midi->in_ep)
- midi->in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -906,9 +902,6 @@ static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_midi_opts);
-CONFIGFS_ATTR_OPS(f_midi_opts);
-
static void midi_attr_release(struct config_item *item)
{
struct f_midi_opts *opts = to_f_midi_opts(item);
@@ -918,13 +911,12 @@ static void midi_attr_release(struct config_item *item)
static struct configfs_item_operations midi_item_ops = {
.release = midi_attr_release,
- .show_attribute = f_midi_opts_attr_show,
- .store_attribute = f_midi_opts_attr_store,
};
#define F_MIDI_OPT(name, test_limit, limit) \
-static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
+static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \
{ \
+ struct f_midi_opts *opts = to_f_midi_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -934,9 +926,10 @@ static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
return result; \
} \
\
-static ssize_t f_midi_opts_##name##_store(struct f_midi_opts *opts, \
+static ssize_t f_midi_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_midi_opts *opts = to_f_midi_opts(item); \
int ret; \
u32 num; \
\
@@ -962,9 +955,7 @@ end: \
return ret; \
} \
\
-static struct f_midi_opts_attribute f_midi_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_midi_opts_##name##_show, \
- f_midi_opts_##name##_store)
+CONFIGFS_ATTR(f_midi_opts_, name);
F_MIDI_OPT(index, true, SNDRV_CARDS);
F_MIDI_OPT(buflen, false, 0);
@@ -972,8 +963,9 @@ F_MIDI_OPT(qlen, false, 0);
F_MIDI_OPT(in_ports, true, MAX_PORTS);
F_MIDI_OPT(out_ports, true, MAX_PORTS);
-static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
+static ssize_t f_midi_opts_id_show(struct config_item *item, char *page)
{
+ struct f_midi_opts *opts = to_f_midi_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -989,9 +981,10 @@ static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
return result;
}
-static ssize_t f_midi_opts_id_store(struct f_midi_opts *opts,
+static ssize_t f_midi_opts_id_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_midi_opts *opts = to_f_midi_opts(item);
int ret;
char *c;
@@ -1016,17 +1009,15 @@ end:
return ret;
}
-static struct f_midi_opts_attribute f_midi_opts_id =
- __CONFIGFS_ATTR(id, S_IRUGO | S_IWUSR, f_midi_opts_id_show,
- f_midi_opts_id_store);
+CONFIGFS_ATTR(f_midi_opts_, id);
static struct configfs_attribute *midi_attrs[] = {
- &f_midi_opts_index.attr,
- &f_midi_opts_buflen.attr,
- &f_midi_opts_qlen.attr,
- &f_midi_opts_in_ports.attr,
- &f_midi_opts_out_ports.attr,
- &f_midi_opts_id.attr,
+ &f_midi_opts_attr_index,
+ &f_midi_opts_attr_buflen,
+ &f_midi_opts_attr_qlen,
+ &f_midi_opts_attr_in_ports,
+ &f_midi_opts_attr_out_ports,
+ &f_midi_opts_attr_id,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 3f05c6bd57f0..7ad798ace1e5 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -586,7 +586,7 @@ static void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
unsigned in_size;
struct usb_function *f = req->context;
struct f_ncm *ncm = func_to_ncm(f);
- struct usb_composite_dev *cdev = ep->driver_data;
+ struct usb_composite_dev *cdev = f->config->cdev;
req->context = NULL;
if (req->status || req->actual != req->length) {
@@ -803,10 +803,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt != 0)
goto fail;
- if (ncm->notify->driver_data) {
- DBG(cdev, "reset ncm control %d\n", intf);
- usb_ep_disable(ncm->notify);
- }
+ DBG(cdev, "reset ncm control %d\n", intf);
+ usb_ep_disable(ncm->notify);
if (!(ncm->notify->desc)) {
DBG(cdev, "init ncm ctrl %d\n", intf);
@@ -814,14 +812,13 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
goto fail;
}
usb_ep_enable(ncm->notify);
- ncm->notify->driver_data = ncm;
/* Data interface has two altsettings, 0 and 1 */
} else if (intf == ncm->data_id) {
if (alt > 1)
goto fail;
- if (ncm->port.in_ep->driver_data) {
+ if (ncm->port.in_ep->enabled) {
DBG(cdev, "reset ncm\n");
ncm->timer_stopping = true;
ncm->netdev = NULL;
@@ -885,7 +882,7 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
if (intf == ncm->ctrl_id)
return 0;
- return ncm->port.in_ep->driver_data ? 1 : 0;
+ return ncm->port.in_ep->enabled ? 1 : 0;
}
static struct sk_buff *package_for_tx(struct f_ncm *ncm)
@@ -1276,15 +1273,14 @@ static void ncm_disable(struct usb_function *f)
DBG(cdev, "ncm deactivated\n");
- if (ncm->port.in_ep->driver_data) {
+ if (ncm->port.in_ep->enabled) {
ncm->timer_stopping = true;
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
}
- if (ncm->notify->driver_data) {
+ if (ncm->notify->enabled) {
usb_ep_disable(ncm->notify);
- ncm->notify->driver_data = NULL;
ncm->notify->desc = NULL;
}
}
@@ -1402,19 +1398,16 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
ncm->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc);
if (!ep)
goto fail;
ncm->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc);
if (!ep)
goto fail;
ncm->notify = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -1468,14 +1461,6 @@ fail:
usb_ep_free_request(ncm->notify, ncm->notify_req);
}
- /* we might as well release our claims on endpoints */
- if (ncm->notify)
- ncm->notify->driver_data = NULL;
- if (ncm->port.out_ep)
- ncm->port.out_ep->driver_data = NULL;
- if (ncm->port.in_ep)
- ncm->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -1503,10 +1488,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm);
static struct configfs_attribute *ncm_attrs[] = {
- &f_ncm_opts_dev_addr.attr,
- &f_ncm_opts_host_addr.attr,
- &f_ncm_opts_qmult.attr,
- &f_ncm_opts_ifname.attr,
+ &ncm_opts_attr_dev_addr,
+ &ncm_opts_attr_host_addr,
+ &ncm_opts_attr_qmult,
+ &ncm_opts_attr_ifname,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c
index 5460426057eb..d6396e0909ee 100644
--- a/drivers/usb/gadget/function/f_obex.c
+++ b/drivers/usb/gadget/function/f_obex.c
@@ -206,7 +206,7 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt > 1)
goto fail;
- if (obex->port.in->driver_data) {
+ if (obex->port.in->enabled) {
dev_dbg(&cdev->gadget->dev,
"reset obex ttyGS%d\n", obex->port_num);
gserial_disconnect(&obex->port);
@@ -348,13 +348,11 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
obex->port.in = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc);
if (!ep)
goto fail;
obex->port.out = ep;
- ep->driver_data = cdev; /* claim */
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@@ -378,12 +376,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- /* we might as well release our claims on endpoints */
- if (obex->port.out)
- obex->port.out->driver_data = NULL;
- if (obex->port.in)
- obex->port.in->driver_data = NULL;
-
ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
return status;
@@ -395,22 +387,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_obex_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_serial_opts *opts = to_f_serial_opts(item);
- struct f_serial_opts_attribute *f_serial_opts_attr =
- container_of(attr, struct f_serial_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_serial_opts_attr->show)
- ret = f_serial_opts_attr->show(opts, page);
-
- return ret;
-}
-
static void obex_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -420,19 +396,17 @@ static void obex_attr_release(struct config_item *item)
static struct configfs_item_operations obex_item_ops = {
.release = obex_attr_release,
- .show_attribute = f_obex_attr_show,
};
-static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_obex_port_num_show(struct config_item *item, char *page)
{
- return sprintf(page, "%u\n", opts->port_num);
+ return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
}
-static struct f_serial_opts_attribute f_obex_port_num =
- __CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+CONFIGFS_ATTR_RO(f_obex_, port_num);
static struct configfs_attribute *acm_attrs[] = {
- &f_obex_port_num.attr,
+ &f_obex_attr_port_num,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c
index c0c3ef272714..157441dbfeba 100644
--- a/drivers/usb/gadget/function/f_phonet.c
+++ b/drivers/usb/gadget/function/f_phonet.c
@@ -418,7 +418,7 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
spin_lock(&port->lock);
- if (fp->in_ep->driver_data)
+ if (fp->in_ep->enabled)
__pn_reset(f);
if (alt == 1) {
@@ -530,13 +530,11 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto err;
fp->out_ep = ep;
- ep->driver_data = fp; /* Claim */
ep = usb_ep_autoconfig(gadget, &pn_fs_source_desc);
if (!ep)
goto err;
fp->in_ep = ep;
- ep->driver_data = fp; /* Claim */
pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
@@ -575,10 +573,6 @@ err_req:
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
usb_free_all_descriptors(f);
err:
- if (fp->out_ep)
- fp->out_ep->driver_data = NULL;
- if (fp->in_ep)
- fp->in_ep->driver_data = NULL;
ERROR(cdev, "USB CDC Phonet: cannot autoconfigure\n");
return status;
}
@@ -589,21 +583,6 @@ static inline struct f_phonet_opts *to_f_phonet_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_phonet_opts);
-static ssize_t f_phonet_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_phonet_opts *opts = to_f_phonet_opts(item);
- struct f_phonet_opts_attribute *f_phonet_opts_attr =
- container_of(attr, struct f_phonet_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_phonet_opts_attr->show)
- ret = f_phonet_opts_attr->show(opts, page);
- return ret;
-}
-
static void phonet_attr_release(struct config_item *item)
{
struct f_phonet_opts *opts = to_f_phonet_opts(item);
@@ -613,19 +592,17 @@ static void phonet_attr_release(struct config_item *item)
static struct configfs_item_operations phonet_item_ops = {
.release = phonet_attr_release,
- .show_attribute = f_phonet_attr_show,
};
-static ssize_t f_phonet_ifname_show(struct f_phonet_opts *opts, char *page)
+static ssize_t f_phonet_ifname_show(struct config_item *item, char *page)
{
- return gether_get_ifname(opts->net, page, PAGE_SIZE);
+ return gether_get_ifname(to_f_phonet_opts(item)->net, page, PAGE_SIZE);
}
-static struct f_phonet_opts_attribute f_phonet_ifname =
- __CONFIGFS_ATTR_RO(ifname, f_phonet_ifname_show);
+CONFIGFS_ATTR_RO(f_phonet_, ifname);
static struct configfs_attribute *phonet_attrs[] = {
- &f_phonet_ifname.attr,
+ &f_phonet_attr_ifname,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 8e2b6bea07bc..0fbfb2b2aa08 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -1039,12 +1039,10 @@ autoconf_fail:
cdev->gadget->name);
return -ENODEV;
}
- in_ep->driver_data = in_ep; /* claim */
out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
if (!out_ep)
goto autoconf_fail;
- out_ep->driver_data = out_ep; /* claim */
/* assumes that all endpoints are dual-speed */
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
@@ -1148,9 +1146,6 @@ static inline struct f_printer_opts
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_printer_opts);
-CONFIGFS_ATTR_OPS(f_printer_opts);
-
static void printer_attr_release(struct config_item *item)
{
struct f_printer_opts *opts = to_f_printer_opts(item);
@@ -1160,13 +1155,12 @@ static void printer_attr_release(struct config_item *item)
static struct configfs_item_operations printer_item_ops = {
.release = printer_attr_release,
- .show_attribute = f_printer_opts_attr_show,
- .store_attribute = f_printer_opts_attr_store,
};
-static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
char *page)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -1176,9 +1170,10 @@ static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
return result;
}
-static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_pnp_string_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int result, l;
mutex_lock(&opts->lock);
@@ -1191,14 +1186,12 @@ static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
return result;
}
-static struct f_printer_opts_attribute f_printer_opts_pnp_string =
- __CONFIGFS_ATTR(pnp_string, S_IRUGO | S_IWUSR,
- f_printer_opts_pnp_string_show,
- f_printer_opts_pnp_string_store);
+CONFIGFS_ATTR(f_printer_opts_, pnp_string);
-static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_q_len_show(struct config_item *item,
char *page)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -1208,9 +1201,10 @@ static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
return result;
}
-static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_q_len_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int ret;
u16 num;
@@ -1231,13 +1225,11 @@ end:
return ret;
}
-static struct f_printer_opts_attribute f_printer_opts_q_len =
- __CONFIGFS_ATTR(q_len, S_IRUGO | S_IWUSR, f_printer_opts_q_len_show,
- f_printer_opts_q_len_store);
+CONFIGFS_ATTR(f_printer_opts_, q_len);
static struct configfs_attribute *printer_attrs[] = {
- &f_printer_opts_pnp_string.attr,
- &f_printer_opts_q_len.attr,
+ &f_printer_opts_attr_pnp_string,
+ &f_printer_opts_attr_q_len,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index 32985dade838..e587767e374c 100644
--- a/drivers/usb/gadget/function/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -543,22 +543,20 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0 */
if (intf == rndis->ctrl_id) {
- if (rndis->notify->driver_data) {
- VDBG(cdev, "reset rndis control %d\n", intf);
- usb_ep_disable(rndis->notify);
- }
+ VDBG(cdev, "reset rndis control %d\n", intf);
+ usb_ep_disable(rndis->notify);
+
if (!rndis->notify->desc) {
VDBG(cdev, "init rndis ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
goto fail;
}
usb_ep_enable(rndis->notify);
- rndis->notify->driver_data = rndis;
} else if (intf == rndis->data_id) {
struct net_device *net;
- if (rndis->port.in_ep->driver_data) {
+ if (rndis->port.in_ep->enabled) {
DBG(cdev, "reset rndis\n");
gether_disconnect(&rndis->port);
}
@@ -612,7 +610,7 @@ static void rndis_disable(struct usb_function *f)
struct f_rndis *rndis = func_to_rndis(f);
struct usb_composite_dev *cdev = f->config->cdev;
- if (!rndis->notify->driver_data)
+ if (!rndis->notify->enabled)
return;
DBG(cdev, "rndis deactivated\n");
@@ -621,7 +619,6 @@ static void rndis_disable(struct usb_function *f)
gether_disconnect(&rndis->port);
usb_ep_disable(rndis->notify);
- rndis->notify->driver_data = NULL;
}
/*-------------------------------------------------------------------------*/
@@ -745,13 +742,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
rndis->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
if (!ep)
goto fail;
rndis->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
/* NOTE: a status/notification endpoint is, strictly speaking,
* optional. We don't treat it that way though! It's simpler,
@@ -761,7 +756,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
rndis->notify = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -829,14 +823,6 @@ fail:
usb_ep_free_request(rndis->notify, rndis->notify_req);
}
- /* we might as well release our claims on endpoints */
- if (rndis->notify)
- rndis->notify->driver_data = NULL;
- if (rndis->port.out_ep)
- rndis->port.out_ep->driver_data = NULL;
- if (rndis->port.in_ep)
- rndis->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -878,10 +864,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
static struct configfs_attribute *rndis_attrs[] = {
- &f_rndis_opts_dev_addr.attr,
- &f_rndis_opts_host_addr.attr,
- &f_rndis_opts_qmult.attr,
- &f_rndis_opts_ifname.attr,
+ &rndis_opts_attr_dev_addr,
+ &rndis_opts_attr_host_addr,
+ &rndis_opts_attr_qmult,
+ &rndis_opts_attr_ifname,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c
index 1d162e200e83..6bb44d613bab 100644
--- a/drivers/usb/gadget/function/f_serial.c
+++ b/drivers/usb/gadget/function/f_serial.c
@@ -153,7 +153,7 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
- if (gser->port.in->driver_data) {
+ if (gser->port.in->enabled) {
dev_dbg(&cdev->gadget->dev,
"reset generic ttyGS%d\n", gser->port_num);
gserial_disconnect(&gser->port);
@@ -219,13 +219,11 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
gser->port.in = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
if (!ep)
goto fail;
gser->port.out = ep;
- ep->driver_data = cdev; /* claim */
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@@ -249,12 +247,6 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- /* we might as well release our claims on endpoints */
- if (gser->port.out)
- gser->port.out->driver_data = NULL;
- if (gser->port.in)
- gser->port.in->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -266,22 +258,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_serial_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_serial_opts *opts = to_f_serial_opts(item);
- struct f_serial_opts_attribute *f_serial_opts_attr =
- container_of(attr, struct f_serial_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_serial_opts_attr->show)
- ret = f_serial_opts_attr->show(opts, page);
-
- return ret;
-}
-
static void serial_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -291,19 +267,17 @@ static void serial_attr_release(struct config_item *item)
static struct configfs_item_operations serial_item_ops = {
.release = serial_attr_release,
- .show_attribute = f_serial_attr_show,
};
-static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_serial_port_num_show(struct config_item *item, char *page)
{
- return sprintf(page, "%u\n", opts->port_num);
+ return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
}
-static struct f_serial_opts_attribute f_serial_port_num =
- __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+CONFIGFS_ATTR_RO(f_serial_, port_num);
static struct configfs_attribute *acm_attrs[] = {
- &f_serial_port_num.attr,
+ &f_serial_attr_port_num,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index cbfaf86fe456..9f3ced62d916 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -50,6 +50,13 @@ struct f_sourcesink {
struct usb_ep *iso_in_ep;
struct usb_ep *iso_out_ep;
int cur_alt;
+
+ unsigned pattern;
+ unsigned isoc_interval;
+ unsigned isoc_maxpacket;
+ unsigned isoc_mult;
+ unsigned isoc_maxburst;
+ unsigned buflen;
};
static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -57,13 +64,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
return container_of(f, struct f_sourcesink, function);
}
-static unsigned pattern;
-static unsigned isoc_interval;
-static unsigned isoc_maxpacket;
-static unsigned isoc_mult;
-static unsigned isoc_maxburst;
-static unsigned buflen;
-
/*-------------------------------------------------------------------------*/
static struct usb_interface_descriptor source_sink_intf_alt0 = {
@@ -298,7 +298,9 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
{
- return alloc_ep_req(ep, len, buflen);
+ struct f_sourcesink *ss = ep->driver_data;
+
+ return alloc_ep_req(ep, len, ss->buflen);
}
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@@ -311,13 +313,9 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
{
int value;
- if (ep->driver_data) {
- value = usb_ep_disable(ep);
- if (value < 0)
- DBG(cdev, "disable %s --> %d\n",
- ep->name, value);
- ep->driver_data = NULL;
- }
+ value = usb_ep_disable(ep);
+ if (value < 0)
+ DBG(cdev, "disable %s --> %d\n", ep->name, value);
}
void disable_endpoints(struct usb_composite_dev *cdev,
@@ -355,42 +353,37 @@ autoconf_fail:
f->name, cdev->gadget->name);
return -ENODEV;
}
- ss->in_ep->driver_data = cdev; /* claim */
ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
if (!ss->out_ep)
goto autoconf_fail;
- ss->out_ep->driver_data = cdev; /* claim */
/* sanity check the isoc module parameters */
- if (isoc_interval < 1)
- isoc_interval = 1;
- if (isoc_interval > 16)
- isoc_interval = 16;
- if (isoc_mult > 2)
- isoc_mult = 2;
- if (isoc_maxburst > 15)
- isoc_maxburst = 15;
+ if (ss->isoc_interval < 1)
+ ss->isoc_interval = 1;
+ if (ss->isoc_interval > 16)
+ ss->isoc_interval = 16;
+ if (ss->isoc_mult > 2)
+ ss->isoc_mult = 2;
+ if (ss->isoc_maxburst > 15)
+ ss->isoc_maxburst = 15;
/* fill in the FS isoc descriptors from the module parameters */
- fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
- 1023 : isoc_maxpacket;
- fs_iso_source_desc.bInterval = isoc_interval;
- fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
- 1023 : isoc_maxpacket;
- fs_iso_sink_desc.bInterval = isoc_interval;
+ fs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket > 1023 ?
+ 1023 : ss->isoc_maxpacket;
+ fs_iso_source_desc.bInterval = ss->isoc_interval;
+ fs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket > 1023 ?
+ 1023 : ss->isoc_maxpacket;
+ fs_iso_sink_desc.bInterval = ss->isoc_interval;
/* allocate iso endpoints */
ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc);
if (!ss->iso_in_ep)
goto no_iso;
- ss->iso_in_ep->driver_data = cdev; /* claim */
ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc);
- if (ss->iso_out_ep) {
- ss->iso_out_ep->driver_data = cdev; /* claim */
- } else {
- ss->iso_in_ep->driver_data = NULL;
+ if (!ss->iso_out_ep) {
+ usb_ep_autoconfig_release(ss->iso_in_ep);
ss->iso_in_ep = NULL;
no_iso:
/*
@@ -403,8 +396,8 @@ no_iso:
ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
}
- if (isoc_maxpacket > 1024)
- isoc_maxpacket = 1024;
+ if (ss->isoc_maxpacket > 1024)
+ ss->isoc_maxpacket = 1024;
/* support high speed hardware */
hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
@@ -415,15 +408,15 @@ no_iso:
* We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
- hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
- hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
- hs_iso_source_desc.bInterval = isoc_interval;
+ hs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
+ hs_iso_source_desc.wMaxPacketSize |= ss->isoc_mult << 11;
+ hs_iso_source_desc.bInterval = ss->isoc_interval;
hs_iso_source_desc.bEndpointAddress =
fs_iso_source_desc.bEndpointAddress;
- hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
- hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
- hs_iso_sink_desc.bInterval = isoc_interval;
+ hs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
+ hs_iso_sink_desc.wMaxPacketSize |= ss->isoc_mult << 11;
+ hs_iso_sink_desc.bInterval = ss->isoc_interval;
hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
/* support super speed hardware */
@@ -437,21 +430,21 @@ no_iso:
* We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
- ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
- ss_iso_source_desc.bInterval = isoc_interval;
- ss_iso_source_comp_desc.bmAttributes = isoc_mult;
- ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
- ss_iso_source_comp_desc.wBytesPerInterval =
- isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+ ss_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
+ ss_iso_source_desc.bInterval = ss->isoc_interval;
+ ss_iso_source_comp_desc.bmAttributes = ss->isoc_mult;
+ ss_iso_source_comp_desc.bMaxBurst = ss->isoc_maxburst;
+ ss_iso_source_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
+ (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
ss_iso_source_desc.bEndpointAddress =
fs_iso_source_desc.bEndpointAddress;
- ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
- ss_iso_sink_desc.bInterval = isoc_interval;
- ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
- ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
- ss_iso_sink_comp_desc.wBytesPerInterval =
- isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+ ss_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
+ ss_iso_sink_desc.bInterval = ss->isoc_interval;
+ ss_iso_sink_comp_desc.bmAttributes = ss->isoc_mult;
+ ss_iso_sink_comp_desc.bMaxBurst = ss->isoc_maxburst;
+ ss_iso_sink_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
+ (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
ret = usb_assign_descriptors(f, fs_source_sink_descs,
@@ -489,12 +482,13 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
unsigned i;
u8 *buf = req->buf;
struct usb_composite_dev *cdev = ss->function.config->cdev;
+ int max_packet_size = le16_to_cpu(ss->out_ep->desc->wMaxPacketSize);
- if (pattern == 2)
+ if (ss->pattern == 2)
return 0;
for (i = 0; i < req->actual; i++, buf++) {
- switch (pattern) {
+ switch (ss->pattern) {
/* all-zeroes has no synchronization issues */
case 0:
@@ -510,7 +504,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
* stutter for any reason, including buffer duplication...)
*/
case 1:
- if (*buf == (u8)(i % 63))
+ if (*buf == (u8)((i % max_packet_size) % 63))
continue;
break;
}
@@ -525,14 +519,16 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
{
unsigned i;
u8 *buf = req->buf;
+ int max_packet_size = le16_to_cpu(ep->desc->wMaxPacketSize);
+ struct f_sourcesink *ss = ep->driver_data;
- switch (pattern) {
+ switch (ss->pattern) {
case 0:
memset(req->buf, 0, req->length);
break;
case 1:
for (i = 0; i < req->length; i++)
- *buf++ = (u8) (i % 63);
+ *buf++ = (u8) ((i % max_packet_size) % 63);
break;
case 2:
break;
@@ -556,7 +552,7 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
case 0: /* normal completion? */
if (ep == ss->out_ep) {
check_read_data(ss, req);
- if (pattern != 2)
+ if (ss->pattern != 2)
memset(req->buf, 0x55, req->length);
}
break;
@@ -605,15 +601,16 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
if (is_iso) {
switch (speed) {
case USB_SPEED_SUPER:
- size = isoc_maxpacket * (isoc_mult + 1) *
- (isoc_maxburst + 1);
+ size = ss->isoc_maxpacket *
+ (ss->isoc_mult + 1) *
+ (ss->isoc_maxburst + 1);
break;
case USB_SPEED_HIGH:
- size = isoc_maxpacket * (isoc_mult + 1);
+ size = ss->isoc_maxpacket * (ss->isoc_mult + 1);
break;
default:
- size = isoc_maxpacket > 1023 ?
- 1023 : isoc_maxpacket;
+ size = ss->isoc_maxpacket > 1023 ?
+ 1023 : ss->isoc_maxpacket;
break;
}
ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
@@ -629,7 +626,7 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
req->complete = source_sink_complete;
if (is_in)
reinit_write_data(ep, req);
- else if (pattern != 2)
+ else if (ss->pattern != 2)
memset(req->buf, 0x55, req->length);
status = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -683,7 +680,6 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
fail:
ep = ss->in_ep;
usb_ep_disable(ep);
- ep->driver_data = NULL;
return result;
}
@@ -702,7 +698,6 @@ fail:
fail2:
ep = ss->out_ep;
usb_ep_disable(ep);
- ep->driver_data = NULL;
goto fail;
}
@@ -724,10 +719,8 @@ fail2:
if (result < 0) {
fail3:
ep = ss->iso_in_ep;
- if (ep) {
+ if (ep)
usb_ep_disable(ep);
- ep->driver_data = NULL;
- }
goto fail2;
}
}
@@ -746,7 +739,6 @@ fail3:
result = source_sink_start_ep(ss, false, true, speed);
if (result < 0) {
usb_ep_disable(ep);
- ep->driver_data = NULL;
goto fail3;
}
}
@@ -763,8 +755,7 @@ static int sourcesink_set_alt(struct usb_function *f,
struct f_sourcesink *ss = func_to_ss(f);
struct usb_composite_dev *cdev = f->config->cdev;
- if (ss->in_ep->driver_data)
- disable_source_sink(ss);
+ disable_source_sink(ss);
return enable_source_sink(cdev, ss, alt);
}
@@ -872,12 +863,12 @@ static struct usb_function *source_sink_alloc_func(
ss_opts->refcnt++;
mutex_unlock(&ss_opts->lock);
- pattern = ss_opts->pattern;
- isoc_interval = ss_opts->isoc_interval;
- isoc_maxpacket = ss_opts->isoc_maxpacket;
- isoc_mult = ss_opts->isoc_mult;
- isoc_maxburst = ss_opts->isoc_maxburst;
- buflen = ss_opts->bulk_buflen;
+ ss->pattern = ss_opts->pattern;
+ ss->isoc_interval = ss_opts->isoc_interval;
+ ss->isoc_maxpacket = ss_opts->isoc_maxpacket;
+ ss->isoc_mult = ss_opts->isoc_mult;
+ ss->isoc_maxburst = ss_opts->isoc_maxburst;
+ ss->buflen = ss_opts->bulk_buflen;
ss->function.name = "source/sink";
ss->function.bind = sourcesink_bind;
@@ -898,9 +889,6 @@ static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_ss_opts);
-CONFIGFS_ATTR_OPS(f_ss_opts);
-
static void ss_attr_release(struct config_item *item)
{
struct f_ss_opts *ss_opts = to_f_ss_opts(item);
@@ -910,24 +898,24 @@ static void ss_attr_release(struct config_item *item)
static struct configfs_item_operations ss_item_ops = {
.release = ss_attr_release,
- .show_attribute = f_ss_opts_attr_show,
- .store_attribute = f_ss_opts_attr_store,
};
-static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_pattern_show(struct config_item *item, char *page)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%u", opts->pattern);
+ result = sprintf(page, "%u\n", opts->pattern);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_pattern_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int ret;
u8 num;
@@ -953,25 +941,24 @@ end:
return ret;
}
-static struct f_ss_opts_attribute f_ss_opts_pattern =
- __CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR,
- f_ss_opts_pattern_show,
- f_ss_opts_pattern_store);
+CONFIGFS_ATTR(f_ss_opts_, pattern);
-static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_interval_show(struct config_item *item, char *page)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%u", opts->isoc_interval);
+ result = sprintf(page, "%u\n", opts->isoc_interval);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_interval_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int ret;
u8 num;
@@ -997,25 +984,24 @@ end:
return ret;
}
-static struct f_ss_opts_attribute f_ss_opts_isoc_interval =
- __CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR,
- f_ss_opts_isoc_interval_show,
- f_ss_opts_isoc_interval_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_interval);
-static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_maxpacket_show(struct config_item *item, char *page)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%u", opts->isoc_maxpacket);
+ result = sprintf(page, "%u\n", opts->isoc_maxpacket);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_maxpacket_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int ret;
u16 num;
@@ -1041,25 +1027,24 @@ end:
return ret;
}
-static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket =
- __CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR,
- f_ss_opts_isoc_maxpacket_show,
- f_ss_opts_isoc_maxpacket_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_maxpacket);
-static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_mult_show(struct config_item *item, char *page)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%u", opts->isoc_mult);
+ result = sprintf(page, "%u\n", opts->isoc_mult);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_mult_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int ret;
u8 num;
@@ -1085,25 +1070,24 @@ end:
return ret;
}
-static struct f_ss_opts_attribute f_ss_opts_isoc_mult =
- __CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR,
- f_ss_opts_isoc_mult_show,
- f_ss_opts_isoc_mult_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_mult);
-static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_maxburst_show(struct config_item *item, char *page)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%u", opts->isoc_maxburst);
+ result = sprintf(page, "%u\n", opts->isoc_maxburst);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_maxburst_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int ret;
u8 num;
@@ -1129,25 +1113,24 @@ end:
return ret;
}
-static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst =
- __CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR,
- f_ss_opts_isoc_maxburst_show,
- f_ss_opts_isoc_maxburst_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_maxburst);
-static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_bulk_buflen_show(struct config_item *item, char *page)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%u", opts->bulk_buflen);
+ result = sprintf(page, "%u\n", opts->bulk_buflen);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_bulk_buflen_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_ss_opts *opts = to_f_ss_opts(item);
int ret;
u32 num;
@@ -1168,18 +1151,15 @@ end:
return ret;
}
-static struct f_ss_opts_attribute f_ss_opts_bulk_buflen =
- __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
- f_ss_opts_bulk_buflen_show,
- f_ss_opts_bulk_buflen_store);
+CONFIGFS_ATTR(f_ss_opts_, bulk_buflen);
static struct configfs_attribute *ss_attrs[] = {
- &f_ss_opts_pattern.attr,
- &f_ss_opts_isoc_interval.attr,
- &f_ss_opts_isoc_maxpacket.attr,
- &f_ss_opts_isoc_mult.attr,
- &f_ss_opts_isoc_maxburst.attr,
- &f_ss_opts_bulk_buflen.attr,
+ &f_ss_opts_attr_pattern,
+ &f_ss_opts_attr_isoc_interval,
+ &f_ss_opts_attr_isoc_maxpacket,
+ &f_ss_opts_attr_isoc_mult,
+ &f_ss_opts_attr_isoc_maxburst,
+ &f_ss_opts_attr_bulk_buflen,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_subset.c b/drivers/usb/gadget/function/f_subset.c
index e3dfa675ff06..829c78de9eba 100644
--- a/drivers/usb/gadget/function/f_subset.c
+++ b/drivers/usb/gadget/function/f_subset.c
@@ -262,7 +262,7 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
- if (geth->port.in_ep->driver_data) {
+ if (geth->port.in_ep->enabled) {
DBG(cdev, "reset cdc subset\n");
gether_disconnect(&geth->port);
}
@@ -343,13 +343,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
geth->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc);
if (!ep)
goto fail;
geth->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@@ -380,12 +378,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- /* we might as well release our claims on endpoints */
- if (geth->port.out_ep)
- geth->port.out_ep->driver_data = NULL;
- if (geth->port.in_ep)
- geth->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -413,10 +405,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether);
static struct configfs_attribute *gether_attrs[] = {
- &f_gether_opts_dev_addr.attr,
- &f_gether_opts_host_addr.attr,
- &f_gether_opts_qmult.attr,
- &f_gether_opts_ifname.attr,
+ &gether_opts_attr_dev_addr,
+ &gether_opts_attr_host_addr,
+ &gether_opts_attr_qmult,
+ &gether_opts_attr_ifname,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index 7856b3394494..6a2346b99f55 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -593,7 +593,6 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
return err;
usb_ep_enable(out_ep);
- out_ep->driver_data = audio;
audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
if (IS_ERR(audio->copy_buf))
return -ENOMEM;
@@ -718,7 +717,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
audio->out_ep = ep;
audio->out_ep->desc = &as_out_ep_desc;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -730,8 +728,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
fail:
gaudio_cleanup(&audio->card);
- if (ep)
- ep->driver_data = NULL;
return status;
}
@@ -773,9 +769,6 @@ static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_uac1_opts);
-CONFIGFS_ATTR_OPS(f_uac1_opts);
-
static void f_uac1_attr_release(struct config_item *item)
{
struct f_uac1_opts *opts = to_f_uac1_opts(item);
@@ -785,14 +778,13 @@ static void f_uac1_attr_release(struct config_item *item)
static struct configfs_item_operations f_uac1_item_ops = {
.release = f_uac1_attr_release,
- .show_attribute = f_uac1_opts_attr_show,
- .store_attribute = f_uac1_opts_attr_store,
};
#define UAC1_INT_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -802,9 +794,10 @@ static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
return result; \
} \
\
-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int ret; \
u32 num; \
\
@@ -826,19 +819,17 @@ end: \
return ret; \
} \
\
-static struct f_uac1_opts_attribute f_uac1_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- f_uac1_opts_##name##_show, \
- f_uac1_opts_##name##_store)
+CONFIGFS_ATTR(f_uac1_opts_, name)
UAC1_INT_ATTRIBUTE(req_buf_size);
UAC1_INT_ATTRIBUTE(req_count);
UAC1_INT_ATTRIBUTE(audio_buf_size);
#define UAC1_STR_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -848,9 +839,10 @@ static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
return result; \
} \
\
-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int ret = -EBUSY; \
char *tmp; \
\
@@ -874,22 +866,19 @@ end: \
return ret; \
} \
\
-static struct f_uac1_opts_attribute f_uac1_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- f_uac1_opts_##name##_show, \
- f_uac1_opts_##name##_store)
+CONFIGFS_ATTR(f_uac1_opts_, name)
UAC1_STR_ATTRIBUTE(fn_play);
UAC1_STR_ATTRIBUTE(fn_cap);
UAC1_STR_ATTRIBUTE(fn_cntl);
static struct configfs_attribute *f_uac1_attrs[] = {
- &f_uac1_opts_req_buf_size.attr,
- &f_uac1_opts_req_count.attr,
- &f_uac1_opts_audio_buf_size.attr,
- &f_uac1_opts_fn_play.attr,
- &f_uac1_opts_fn_cap.attr,
- &f_uac1_opts_fn_cntl.attr,
+ &f_uac1_opts_attr_req_buf_size,
+ &f_uac1_opts_attr_req_count,
+ &f_uac1_opts_attr_audio_buf_size,
+ &f_uac1_opts_attr_fn_play,
+ &f_uac1_opts_attr_fn_cap,
+ &f_uac1_opts_attr_fn_cntl,
NULL,
};
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index f8de7ea2a0c1..044ca79d3cb5 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -1081,14 +1081,12 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
goto err;
}
- agdev->out_ep->driver_data = agdev;
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
if (!agdev->in_ep) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
goto err;
}
- agdev->in_ep->driver_data = agdev;
uac2->p_prm.uac2 = uac2;
uac2->c_prm.uac2 = uac2;
@@ -1132,10 +1130,6 @@ err_free_descs:
err:
kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf);
- if (agdev->in_ep)
- agdev->in_ep->driver_data = NULL;
- if (agdev->out_ep)
- agdev->out_ep->driver_data = NULL;
return -EINVAL;
}
@@ -1445,9 +1439,6 @@ static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_uac2_opts);
-CONFIGFS_ATTR_OPS(f_uac2_opts);
-
static void f_uac2_attr_release(struct config_item *item)
{
struct f_uac2_opts *opts = to_f_uac2_opts(item);
@@ -1457,14 +1448,13 @@ static void f_uac2_attr_release(struct config_item *item)
static struct configfs_item_operations f_uac2_item_ops = {
.release = f_uac2_attr_release,
- .show_attribute = f_uac2_opts_attr_show,
- .store_attribute = f_uac2_opts_attr_store,
};
#define UAC2_ATTRIBUTE(name) \
-static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts, \
+static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
+ struct f_uac2_opts *opts = to_f_uac2_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -1474,9 +1464,10 @@ static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts, \
return result; \
} \
\
-static ssize_t f_uac2_opts_##name##_store(struct f_uac2_opts *opts, \
+static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uac2_opts *opts = to_f_uac2_opts(item); \
int ret; \
u32 num; \
\
@@ -1498,10 +1489,7 @@ end: \
return ret; \
} \
\
-static struct f_uac2_opts_attribute f_uac2_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- f_uac2_opts_##name##_show, \
- f_uac2_opts_##name##_store)
+CONFIGFS_ATTR(f_uac2_opts_, name)
UAC2_ATTRIBUTE(p_chmask);
UAC2_ATTRIBUTE(p_srate);
@@ -1511,12 +1499,12 @@ UAC2_ATTRIBUTE(c_srate);
UAC2_ATTRIBUTE(c_ssize);
static struct configfs_attribute *f_uac2_attrs[] = {
- &f_uac2_opts_p_chmask.attr,
- &f_uac2_opts_p_srate.attr,
- &f_uac2_opts_p_ssize.attr,
- &f_uac2_opts_c_chmask.attr,
- &f_uac2_opts_c_srate.attr,
- &f_uac2_opts_c_ssize.attr,
+ &f_uac2_opts_attr_p_chmask,
+ &f_uac2_opts_attr_p_srate,
+ &f_uac2_opts_attr_p_ssize,
+ &f_uac2_opts_attr_c_chmask,
+ &f_uac2_opts_attr_c_srate,
+ &f_uac2_opts_attr_c_ssize,
NULL,
};
@@ -1583,11 +1571,6 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
prm = &agdev->uac2.c_prm;
kfree(prm->rbuf);
usb_free_all_descriptors(f);
-
- if (agdev->in_ep)
- agdev->in_ep->driver_data = NULL;
- if (agdev->out_ep)
- agdev->out_ep->driver_data = NULL;
}
static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 743be34605dc..29b41b5dee04 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -280,7 +280,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
else if (interface != uvc->streaming_intf)
return -EINVAL;
else
- return uvc->video.ep->driver_data ? 1 : 0;
+ return uvc->video.ep->enabled ? 1 : 0;
}
static int
@@ -298,18 +298,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (alt)
return -EINVAL;
- if (uvc->control_ep->driver_data) {
- INFO(cdev, "reset UVC Control\n");
- usb_ep_disable(uvc->control_ep);
- uvc->control_ep->driver_data = NULL;
- }
+ INFO(cdev, "reset UVC Control\n");
+ usb_ep_disable(uvc->control_ep);
if (!uvc->control_ep->desc)
if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
return -EINVAL;
usb_ep_enable(uvc->control_ep);
- uvc->control_ep->driver_data = uvc;
if (uvc->state == UVC_STATE_DISCONNECTED) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
@@ -336,10 +332,8 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (uvc->state != UVC_STATE_STREAMING)
return 0;
- if (uvc->video.ep) {
+ if (uvc->video.ep)
usb_ep_disable(uvc->video.ep);
- uvc->video.ep->driver_data = NULL;
- }
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMOFF;
@@ -355,18 +349,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (!uvc->video.ep)
return -EINVAL;
- if (uvc->video.ep->driver_data) {
- INFO(cdev, "reset UVC\n");
- usb_ep_disable(uvc->video.ep);
- uvc->video.ep->driver_data = NULL;
- }
+ INFO(cdev, "reset UVC\n");
+ usb_ep_disable(uvc->video.ep);
ret = config_ep_by_speed(f->config->cdev->gadget,
&(uvc->func), uvc->video.ep);
if (ret)
return ret;
usb_ep_enable(uvc->video.ep);
- uvc->video.ep->driver_data = uvc;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
@@ -392,15 +382,8 @@ uvc_function_disable(struct usb_function *f)
uvc->state = UVC_STATE_DISCONNECTED;
- if (uvc->video.ep->driver_data) {
- usb_ep_disable(uvc->video.ep);
- uvc->video.ep->driver_data = NULL;
- }
-
- if (uvc->control_ep->driver_data) {
- usb_ep_disable(uvc->control_ep);
- uvc->control_ep->driver_data = NULL;
- }
+ usb_ep_disable(uvc->video.ep);
+ usb_ep_disable(uvc->control_ep);
}
/* --------------------------------------------------------------------------
@@ -651,7 +634,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
uvc->control_ep = ep;
- ep->driver_data = uvc;
if (gadget_is_superspeed(c->cdev->gadget))
ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
@@ -666,7 +648,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
uvc->video.ep = ep;
- ep->driver_data = uvc;
uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
@@ -755,11 +736,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
error:
v4l2_device_unregister(&uvc->v4l2_dev);
- if (uvc->control_ep)
- uvc->control_ep->driver_data = NULL;
- if (uvc->video.ep)
- uvc->video.ep->driver_data = NULL;
-
if (uvc->control_req)
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
@@ -886,8 +862,6 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
video_unregister_device(&uvc->vdev);
v4l2_device_unregister(&uvc->v4l2_dev);
- uvc->control_ep->driver_data = NULL;
- uvc->video.ep->driver_data = NULL;
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index f1fd777ef4ec..6554322af2c1 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -48,6 +48,11 @@
#define UETH__VERSION "29-May-2008"
+/* Experiments show that both Linux and Windows hosts allow up to 16k
+ * frame sizes. Set the max size to 15k+52 to prevent allocating 32k
+ * blocks and still have efficient handling. */
+#define GETHER_MAX_ETH_FRAME_LEN 15412
+
struct eth_dev {
/* lock is held while accessing port_usb
*/
@@ -146,7 +151,7 @@ static int ueth_change_mtu(struct net_device *net, int new_mtu)
spin_lock_irqsave(&dev->lock, flags);
if (dev->port_usb)
status = -EBUSY;
- else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
+ else if (new_mtu <= ETH_HLEN || new_mtu > GETHER_MAX_ETH_FRAME_LEN)
status = -ERANGE;
else
net->mtu = new_mtu;
@@ -294,7 +299,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
while (skb2) {
if (status < 0
|| ETH_HLEN > skb2->len
- || skb2->len > VLAN_ETH_FRAME_LEN) {
+ || skb2->len > GETHER_MAX_ETH_FRAME_LEN) {
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
DBG(dev, "rx length %d\n", skb2->len);
@@ -1144,7 +1149,6 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->req_lock);
}
spin_unlock(&dev->req_lock);
- link->in_ep->driver_data = NULL;
link->in_ep->desc = NULL;
usb_ep_disable(link->out_ep);
@@ -1159,7 +1163,6 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->req_lock);
}
spin_unlock(&dev->req_lock);
- link->out_ep->driver_data = NULL;
link->out_ep->desc = NULL;
/* finish forgetting about this USB link episode */
diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h
index bcbd30146cfd..4f47289fcf7c 100644
--- a/drivers/usb/gadget/function/u_ether_configfs.h
+++ b/drivers/usb/gadget/function/u_ether_configfs.h
@@ -17,9 +17,6 @@
#define __U_ETHER_CONFIGFS_H
#define USB_ETHERNET_CONFIGFS_ITEM(_f_) \
- CONFIGFS_ATTR_STRUCT(f_##_f_##_opts); \
- CONFIGFS_ATTR_OPS(f_##_f_##_opts); \
- \
static void _f_##_attr_release(struct config_item *item) \
{ \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
@@ -29,14 +26,13 @@
\
static struct configfs_item_operations _f_##_item_ops = { \
.release = _f_##_attr_release, \
- .show_attribute = f_##_f_##_opts_attr_show, \
- .store_attribute = f_##_f_##_opts_attr_store, \
}
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \
- static ssize_t _f_##_opts_dev_addr_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -46,9 +42,10 @@
return result; \
} \
\
- static ssize_t _f_##_opts_dev_addr_store(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
@@ -64,15 +61,13 @@
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_dev_addr = \
- __CONFIGFS_ATTR(dev_addr, S_IRUGO | S_IWUSR, \
- _f_##_opts_dev_addr_show, \
- _f_##_opts_dev_addr_store)
+ CONFIGFS_ATTR(_f_##_opts_, dev_addr)
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \
- static ssize_t _f_##_opts_host_addr_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -82,9 +77,10 @@
return result; \
} \
\
- static ssize_t _f_##_opts_host_addr_store(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
@@ -100,15 +96,13 @@
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_host_addr = \
- __CONFIGFS_ATTR(host_addr, S_IRUGO | S_IWUSR, \
- _f_##_opts_host_addr_show, \
- _f_##_opts_host_addr_store)
+ CONFIGFS_ATTR(_f_##_opts_, host_addr)
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \
- static ssize_t _f_##_opts_qmult_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_qmult_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
unsigned qmult; \
\
mutex_lock(&opts->lock); \
@@ -117,9 +111,10 @@
return sprintf(page, "%d", qmult); \
} \
\
- static ssize_t _f_##_opts_qmult_store(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_qmult_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
u8 val; \
int ret; \
\
@@ -140,15 +135,13 @@ out: \
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_qmult = \
- __CONFIGFS_ATTR(qmult, S_IRUGO | S_IWUSR, \
- _f_##_opts_qmult_show, \
- _f_##_opts_qmult_store)
+ CONFIGFS_ATTR(_f_##_opts_, qmult)
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \
- static ssize_t _f_##_opts_ifname_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_ifname_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
@@ -158,7 +151,6 @@ out: \
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_ifname = \
- __CONFIGFS_ATTR_RO(ifname, _f_##_opts_ifname_show)
+ CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
#endif /* __U_ETHER_CONFIGFS_H */
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 7ee057930ae7..f7771d86ad6c 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -114,6 +114,7 @@ struct gs_port {
struct gs_buf port_write_buf;
wait_queue_head_t drain_wait; /* wait while writes drain */
bool write_busy;
+ wait_queue_head_t close_wait;
/* REVISIT this state ... */
struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
@@ -876,7 +877,6 @@ static void gs_close(struct tty_struct *tty, struct file *file)
else
gs_buf_clear(&port->port_write_buf);
- tty->driver_data = NULL;
port->port.tty = NULL;
port->openclose = false;
@@ -884,7 +884,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
port->port_num, tty, file);
- wake_up(&port->port.close_wait);
+ wake_up(&port->close_wait);
exit:
spin_unlock_irq(&port->port_lock);
}
@@ -1044,6 +1044,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
tty_port_init(&port->port);
spin_lock_init(&port->port_lock);
init_waitqueue_head(&port->drain_wait);
+ init_waitqueue_head(&port->close_wait);
tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
@@ -1074,7 +1075,7 @@ static void gserial_free_port(struct gs_port *port)
{
tasklet_kill(&port->push);
/* wait for old opens to finish */
- wait_event(port->port.close_wait, gs_closed(port));
+ wait_event(port->close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL);
tty_port_destroy(&port->port);
kfree(port);
@@ -1224,7 +1225,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
fail_out:
usb_ep_disable(gser->in);
- gser->in->driver_data = NULL;
return status;
}
EXPORT_SYMBOL_GPL(gserial_connect);
@@ -1264,10 +1264,7 @@ void gserial_disconnect(struct gserial *gser)
/* disable endpoints, aborting down any active I/O */
usb_ep_disable(gser->out);
- gser->out->driver_data = NULL;
-
usb_ep_disable(gser->in);
- gser->in->driver_data = NULL;
/* finally, free any unused/unusable I/O buffers */
spin_lock_irqsave(&port->port_lock, flags);
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 3c0467bcb14f..289ebca316d3 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -17,19 +17,21 @@
#define UVCG_STREAMING_CONTROL_SIZE 1
-#define CONFIGFS_ATTR_OPS_RO(_item) \
-static ssize_t _item##_attr_show(struct config_item *item, \
- struct configfs_attribute *attr, \
- char *page) \
-{ \
- struct _item *_item = to_##_item(item); \
- struct _item##_attribute *_item##_attr = \
- container_of(attr, struct _item##_attribute, attr); \
- ssize_t ret = 0; \
- \
- if (_item##_attr->show) \
- ret = _item##_attr->show(_item, page); \
- return ret; \
+#define UVC_ATTR(prefix, cname, aname) \
+static struct configfs_attribute prefix##attr_##cname = { \
+ .ca_name = __stringify(aname), \
+ .ca_mode = S_IRUGO, \
+ .ca_owner = THIS_MODULE, \
+ .show = prefix##cname##_show, \
+ .store = prefix##cname##_store, \
+}
+
+#define UVC_ATTR_RO(prefix, cname, aname) \
+static struct configfs_attribute prefix##attr_##cname = { \
+ .ca_name = __stringify(aname), \
+ .ca_mode = S_IRUGO, \
+ .ca_owner = THIS_MODULE, \
+ .show = prefix##cname##_show, \
}
static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item);
@@ -48,18 +50,11 @@ static struct uvcg_control_header *to_uvcg_control_header(struct config_item *it
return container_of(item, struct uvcg_control_header, item);
}
-CONFIGFS_ATTR_STRUCT(uvcg_control_header);
-CONFIGFS_ATTR_OPS(uvcg_control_header);
-
-static struct configfs_item_operations uvcg_control_header_item_ops = {
- .show_attribute = uvcg_control_header_attr_show,
- .store_attribute = uvcg_control_header_attr_store,
-};
-
#define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
static ssize_t uvcg_control_header_##cname##_show( \
- struct uvcg_control_header *ch, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_control_header *ch = to_uvcg_control_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
@@ -79,9 +74,10 @@ static ssize_t uvcg_control_header_##cname##_show( \
} \
\
static ssize_t \
-uvcg_control_header_##cname##_store(struct uvcg_control_header *ch, \
+uvcg_control_header_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct uvcg_control_header *ch = to_uvcg_control_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
@@ -115,11 +111,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_control_header_attribute \
- uvcg_control_header_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_control_header_##cname##_show, \
- uvcg_control_header_##cname##_store)
+UVC_ATTR(uvcg_control_header_, cname, aname)
UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
0xffff);
@@ -130,13 +122,12 @@ UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32,
#undef UVCG_CTRL_HDR_ATTR
static struct configfs_attribute *uvcg_control_header_attrs[] = {
- &uvcg_control_header_bcd_uvc.attr,
- &uvcg_control_header_dw_clock_frequency.attr,
+ &uvcg_control_header_attr_bcd_uvc,
+ &uvcg_control_header_attr_dw_clock_frequency,
NULL,
};
static struct config_item_type uvcg_control_header_type = {
- .ct_item_ops = &uvcg_control_header_item_ops,
.ct_attrs = uvcg_control_header_attrs,
.ct_owner = THIS_MODULE,
};
@@ -196,17 +187,11 @@ static inline struct uvcg_default_processing
struct uvcg_default_processing, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_processing);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_processing);
-
-static struct configfs_item_operations uvcg_default_processing_item_ops = {
- .show_attribute = uvcg_default_processing_attr_show,
-};
-
#define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_processing_##cname##_show( \
- struct uvcg_default_processing *dp, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
@@ -227,9 +212,7 @@ static ssize_t uvcg_default_processing_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_processing_attribute \
- uvcg_default_processing_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_processing_##cname##_show)
+UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
#define identity_conv(x) (x)
@@ -243,8 +226,9 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv);
#undef UVCG_DEFAULT_PROCESSING_ATTR
static ssize_t uvcg_default_processing_bm_controls_show(
- struct uvcg_default_processing *dp, char *page)
+ struct config_item *item, char *page)
{
+ struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
@@ -270,22 +254,18 @@ static ssize_t uvcg_default_processing_bm_controls_show(
return result;
}
-static struct uvcg_default_processing_attribute
- uvcg_default_processing_bm_controls =
- __CONFIGFS_ATTR_RO(bmControls,
- uvcg_default_processing_bm_controls_show);
+UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
static struct configfs_attribute *uvcg_default_processing_attrs[] = {
- &uvcg_default_processing_b_unit_id.attr,
- &uvcg_default_processing_b_source_id.attr,
- &uvcg_default_processing_w_max_multiplier.attr,
- &uvcg_default_processing_bm_controls.attr,
- &uvcg_default_processing_i_processing.attr,
+ &uvcg_default_processing_attr_b_unit_id,
+ &uvcg_default_processing_attr_b_source_id,
+ &uvcg_default_processing_attr_w_max_multiplier,
+ &uvcg_default_processing_attr_bm_controls,
+ &uvcg_default_processing_attr_i_processing,
NULL,
};
static struct config_item_type uvcg_default_processing_type = {
- .ct_item_ops = &uvcg_default_processing_item_ops,
.ct_attrs = uvcg_default_processing_attrs,
.ct_owner = THIS_MODULE,
};
@@ -318,17 +298,11 @@ static inline struct uvcg_default_camera
struct uvcg_default_camera, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_camera);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_camera);
-
-static struct configfs_item_operations uvcg_default_camera_item_ops = {
- .show_attribute = uvcg_default_camera_attr_show,
-};
-
#define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_camera_##cname##_show( \
- struct uvcg_default_camera *dc, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
@@ -351,9 +325,7 @@ static ssize_t uvcg_default_camera_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_camera_attribute \
- uvcg_default_camera_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_camera_##cname##_show)
+UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
#define identity_conv(x) (x)
@@ -373,8 +345,9 @@ UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
#undef UVCG_DEFAULT_CAMERA_ATTR
static ssize_t uvcg_default_camera_bm_controls_show(
- struct uvcg_default_camera *dc, char *page)
+ struct config_item *item, char *page)
{
+ struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
@@ -400,24 +373,21 @@ static ssize_t uvcg_default_camera_bm_controls_show(
return result;
}
-static struct uvcg_default_camera_attribute
- uvcg_default_camera_bm_controls =
- __CONFIGFS_ATTR_RO(bmControls, uvcg_default_camera_bm_controls_show);
+UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
static struct configfs_attribute *uvcg_default_camera_attrs[] = {
- &uvcg_default_camera_b_terminal_id.attr,
- &uvcg_default_camera_w_terminal_type.attr,
- &uvcg_default_camera_b_assoc_terminal.attr,
- &uvcg_default_camera_i_terminal.attr,
- &uvcg_default_camera_w_objective_focal_length_min.attr,
- &uvcg_default_camera_w_objective_focal_length_max.attr,
- &uvcg_default_camera_w_ocular_focal_length.attr,
- &uvcg_default_camera_bm_controls.attr,
+ &uvcg_default_camera_attr_b_terminal_id,
+ &uvcg_default_camera_attr_w_terminal_type,
+ &uvcg_default_camera_attr_b_assoc_terminal,
+ &uvcg_default_camera_attr_i_terminal,
+ &uvcg_default_camera_attr_w_objective_focal_length_min,
+ &uvcg_default_camera_attr_w_objective_focal_length_max,
+ &uvcg_default_camera_attr_w_ocular_focal_length,
+ &uvcg_default_camera_attr_bm_controls,
NULL,
};
static struct config_item_type uvcg_default_camera_type = {
- .ct_item_ops = &uvcg_default_camera_item_ops,
.ct_attrs = uvcg_default_camera_attrs,
.ct_owner = THIS_MODULE,
};
@@ -450,17 +420,11 @@ static inline struct uvcg_default_output
struct uvcg_default_output, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_output);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_output);
-
-static struct configfs_item_operations uvcg_default_output_item_ops = {
- .show_attribute = uvcg_default_output_attr_show,
-};
-
#define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_output_##cname##_show( \
- struct uvcg_default_output *dout, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_output *dout = to_uvcg_default_output(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
@@ -483,9 +447,7 @@ static ssize_t uvcg_default_output_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_output_attribute \
- uvcg_default_output_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_output_##cname##_show)
+UVC_ATTR_RO(uvcg_default_output_, cname, aname)
#define identity_conv(x) (x)
@@ -500,16 +462,15 @@ UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv);
#undef UVCG_DEFAULT_OUTPUT_ATTR
static struct configfs_attribute *uvcg_default_output_attrs[] = {
- &uvcg_default_output_b_terminal_id.attr,
- &uvcg_default_output_w_terminal_type.attr,
- &uvcg_default_output_b_assoc_terminal.attr,
- &uvcg_default_output_b_source_id.attr,
- &uvcg_default_output_i_terminal.attr,
+ &uvcg_default_output_attr_b_terminal_id,
+ &uvcg_default_output_attr_w_terminal_type,
+ &uvcg_default_output_attr_b_assoc_terminal,
+ &uvcg_default_output_attr_b_source_id,
+ &uvcg_default_output_attr_i_terminal,
NULL,
};
static struct config_item_type uvcg_default_output_type = {
- .ct_item_ops = &uvcg_default_output_item_ops,
.ct_attrs = uvcg_default_output_attrs,
.ct_owner = THIS_MODULE,
};
@@ -800,9 +761,6 @@ static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item
return container_of(item, struct uvcg_streaming_header, item);
}
-CONFIGFS_ATTR_STRUCT(uvcg_streaming_header);
-CONFIGFS_ATTR_OPS(uvcg_streaming_header);
-
static int uvcg_streaming_header_allow_link(struct config_item *src,
struct config_item *target)
{
@@ -893,16 +851,15 @@ out:
}
static struct configfs_item_operations uvcg_streaming_header_item_ops = {
- .show_attribute = uvcg_streaming_header_attr_show,
- .store_attribute = uvcg_streaming_header_attr_store,
.allow_link = uvcg_streaming_header_allow_link,
.drop_link = uvcg_streaming_header_drop_link,
};
#define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
static ssize_t uvcg_streaming_header_##cname##_show( \
- struct uvcg_streaming_header *sh, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
@@ -921,9 +878,7 @@ static ssize_t uvcg_streaming_header_##cname##_show( \
return result; \
} \
\
-static struct uvcg_streaming_header_attribute \
- uvcg_streaming_header_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_streaming_header_##cname##_show)
+UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
#define identity_conv(x) (x)
@@ -939,11 +894,11 @@ UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv);
#undef UVCG_STREAMING_HEADER_ATTR
static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
- &uvcg_streaming_header_bm_info.attr,
- &uvcg_streaming_header_b_terminal_link.attr,
- &uvcg_streaming_header_b_still_capture_method.attr,
- &uvcg_streaming_header_b_trigger_support.attr,
- &uvcg_streaming_header_b_trigger_usage.attr,
+ &uvcg_streaming_header_attr_bm_info,
+ &uvcg_streaming_header_attr_b_terminal_link,
+ &uvcg_streaming_header_attr_b_still_capture_method,
+ &uvcg_streaming_header_attr_b_trigger_support,
+ &uvcg_streaming_header_attr_b_trigger_usage,
NULL,
};
@@ -1022,17 +977,10 @@ static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
return container_of(item, struct uvcg_frame, item);
}
-CONFIGFS_ATTR_STRUCT(uvcg_frame);
-CONFIGFS_ATTR_OPS(uvcg_frame);
-
-static struct configfs_item_operations uvcg_frame_item_ops = {
- .show_attribute = uvcg_frame_attr_show,
- .store_attribute = uvcg_frame_attr_store,
-};
-
#define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
-static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
+static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
{ \
+ struct uvcg_frame *f = to_uvcg_frame(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
@@ -1051,9 +999,10 @@ static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
return result; \
} \
\
-static ssize_t uvcg_frame_##cname##_store(struct uvcg_frame *f, \
+static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct uvcg_frame *f = to_uvcg_frame(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct uvcg_format *fmt; \
@@ -1085,11 +1034,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_frame_attribute \
- uvcg_frame_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_frame_##cname##_show, \
- uvcg_frame_##cname##_store)
+UVC_ATTR(uvcg_frame_, cname, aname);
#define noop_conversion(x) (x)
@@ -1108,9 +1053,10 @@ UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
#undef UVCG_FRAME_ATTR
-static ssize_t uvcg_frame_dw_frame_interval_show(struct uvcg_frame *frm,
+static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
char *page)
{
+ struct uvcg_frame *frm = to_uvcg_frame(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
@@ -1185,9 +1131,10 @@ static int __uvcg_iter_frm_intrv(const char *page, size_t len,
return 0;
}
-static ssize_t uvcg_frame_dw_frame_interval_store(struct uvcg_frame *ch,
+static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
const char *page, size_t len)
{
+ struct uvcg_frame *ch = to_uvcg_frame(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct uvcg_format *fmt;
@@ -1234,26 +1181,21 @@ end:
return ret;
}
-static struct uvcg_frame_attribute
- uvcg_frame_dw_frame_interval =
- __CONFIGFS_ATTR(dwFrameInterval, S_IRUGO | S_IWUSR,
- uvcg_frame_dw_frame_interval_show,
- uvcg_frame_dw_frame_interval_store);
+UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
static struct configfs_attribute *uvcg_frame_attrs[] = {
- &uvcg_frame_bm_capabilities.attr,
- &uvcg_frame_w_width.attr,
- &uvcg_frame_w_height.attr,
- &uvcg_frame_dw_min_bit_rate.attr,
- &uvcg_frame_dw_max_bit_rate.attr,
- &uvcg_frame_dw_max_video_frame_buffer_size.attr,
- &uvcg_frame_dw_default_frame_interval.attr,
- &uvcg_frame_dw_frame_interval.attr,
+ &uvcg_frame_attr_bm_capabilities,
+ &uvcg_frame_attr_w_width,
+ &uvcg_frame_attr_w_height,
+ &uvcg_frame_attr_dw_min_bit_rate,
+ &uvcg_frame_attr_dw_max_bit_rate,
+ &uvcg_frame_attr_dw_max_video_frame_buffer_size,
+ &uvcg_frame_attr_dw_default_frame_interval,
+ &uvcg_frame_attr_dw_frame_interval,
NULL,
};
static struct config_item_type uvcg_frame_type = {
- .ct_item_ops = &uvcg_frame_item_ops,
.ct_attrs = uvcg_frame_attrs,
.ct_owner = THIS_MODULE,
};
@@ -1333,22 +1275,15 @@ static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item)
struct uvcg_uncompressed, fmt);
}
-CONFIGFS_ATTR_STRUCT(uvcg_uncompressed);
-CONFIGFS_ATTR_OPS(uvcg_uncompressed);
-
-static struct configfs_item_operations uvcg_uncompressed_item_ops = {
- .show_attribute = uvcg_uncompressed_attr_show,
- .store_attribute = uvcg_uncompressed_attr_store,
-};
-
static struct configfs_group_operations uvcg_uncompressed_group_ops = {
.make_item = uvcg_frame_make,
.drop_item = uvcg_frame_drop,
};
-static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch,
+static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
char *page)
{
+ struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
@@ -1367,9 +1302,10 @@ static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch,
return sizeof(ch->desc.guidFormat);
}
-static ssize_t uvcg_uncompressed_guid_format_store(struct uvcg_uncompressed *ch,
+static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
const char *page, size_t len)
{
+ struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
@@ -1396,16 +1332,13 @@ end:
return ret;
}
-static struct uvcg_uncompressed_attribute uvcg_uncompressed_guid_format =
- __CONFIGFS_ATTR(guidFormat, S_IRUGO | S_IWUSR,
- uvcg_uncompressed_guid_format_show,
- uvcg_uncompressed_guid_format_store);
-
+UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
static ssize_t uvcg_uncompressed_##cname##_show( \
- struct uvcg_uncompressed *u, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1424,14 +1357,13 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
return result; \
} \
\
-static struct uvcg_uncompressed_attribute \
- uvcg_uncompressed_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_uncompressed_##cname##_show)
+UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
#define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
static ssize_t uvcg_uncompressed_##cname##_show( \
- struct uvcg_uncompressed *u, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1451,9 +1383,10 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
} \
\
static ssize_t \
-uvcg_uncompressed_##cname##_store(struct uvcg_uncompressed *u, \
+uvcg_uncompressed_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1487,11 +1420,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_uncompressed_attribute \
- uvcg_uncompressed_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_uncompressed_##cname##_show, \
- uvcg_uncompressed_##cname##_store)
+UVC_ATTR(uvcg_uncompressed_, cname, aname);
#define identity_conv(x) (x)
@@ -1508,36 +1437,34 @@ UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
#undef UVCG_UNCOMPRESSED_ATTR_RO
static inline ssize_t
-uvcg_uncompressed_bma_controls_show(struct uvcg_uncompressed *unc, char *page)
+uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
{
+ struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
return uvcg_format_bma_controls_show(&unc->fmt, page);
}
static inline ssize_t
-uvcg_uncompressed_bma_controls_store(struct uvcg_uncompressed *ch,
+uvcg_uncompressed_bma_controls_store(struct config_item *item,
const char *page, size_t len)
{
- return uvcg_format_bma_controls_store(&ch->fmt, page, len);
+ struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
+ return uvcg_format_bma_controls_store(&unc->fmt, page, len);
}
-static struct uvcg_uncompressed_attribute uvcg_uncompressed_bma_controls =
- __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR,
- uvcg_uncompressed_bma_controls_show,
- uvcg_uncompressed_bma_controls_store);
+UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
- &uvcg_uncompressed_guid_format.attr,
- &uvcg_uncompressed_b_bits_per_pixel.attr,
- &uvcg_uncompressed_b_default_frame_index.attr,
- &uvcg_uncompressed_b_aspect_ratio_x.attr,
- &uvcg_uncompressed_b_aspect_ratio_y.attr,
- &uvcg_uncompressed_bm_interface_flags.attr,
- &uvcg_uncompressed_bma_controls.attr,
+ &uvcg_uncompressed_attr_guid_format,
+ &uvcg_uncompressed_attr_b_bits_per_pixel,
+ &uvcg_uncompressed_attr_b_default_frame_index,
+ &uvcg_uncompressed_attr_b_aspect_ratio_x,
+ &uvcg_uncompressed_attr_b_aspect_ratio_y,
+ &uvcg_uncompressed_attr_bm_interface_flags,
+ &uvcg_uncompressed_attr_bma_controls,
NULL,
};
static struct config_item_type uvcg_uncompressed_type = {
- .ct_item_ops = &uvcg_uncompressed_item_ops,
.ct_group_ops = &uvcg_uncompressed_group_ops,
.ct_attrs = uvcg_uncompressed_attrs,
.ct_owner = THIS_MODULE,
@@ -1605,22 +1532,15 @@ static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
struct uvcg_mjpeg, fmt);
}
-CONFIGFS_ATTR_STRUCT(uvcg_mjpeg);
-CONFIGFS_ATTR_OPS(uvcg_mjpeg);
-
-static struct configfs_item_operations uvcg_mjpeg_item_ops = {
- .show_attribute = uvcg_mjpeg_attr_show,
- .store_attribute = uvcg_mjpeg_attr_store,
-};
-
static struct configfs_group_operations uvcg_mjpeg_group_ops = {
.make_item = uvcg_frame_make,
.drop_item = uvcg_frame_drop,
};
#define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
-static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
+static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
{ \
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1639,13 +1559,12 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
return result; \
} \
\
-static struct uvcg_mjpeg_attribute \
- uvcg_mjpeg_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_mjpeg_##cname##_show)
+UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
#define UVCG_MJPEG_ATTR(cname, aname, conv) \
-static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
+static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
{ \
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1665,9 +1584,10 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
} \
\
static ssize_t \
-uvcg_mjpeg_##cname##_store(struct uvcg_mjpeg *u, \
+uvcg_mjpeg_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1701,11 +1621,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_mjpeg_attribute \
- uvcg_mjpeg_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_mjpeg_##cname##_show, \
- uvcg_mjpeg_##cname##_store)
+UVC_ATTR(uvcg_mjpeg_, cname, aname)
#define identity_conv(x) (x)
@@ -1722,35 +1638,33 @@ UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
#undef UVCG_MJPEG_ATTR_RO
static inline ssize_t
-uvcg_mjpeg_bma_controls_show(struct uvcg_mjpeg *unc, char *page)
+uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
{
- return uvcg_format_bma_controls_show(&unc->fmt, page);
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
+ return uvcg_format_bma_controls_show(&u->fmt, page);
}
static inline ssize_t
-uvcg_mjpeg_bma_controls_store(struct uvcg_mjpeg *ch,
+uvcg_mjpeg_bma_controls_store(struct config_item *item,
const char *page, size_t len)
{
- return uvcg_format_bma_controls_store(&ch->fmt, page, len);
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
+ return uvcg_format_bma_controls_store(&u->fmt, page, len);
}
-static struct uvcg_mjpeg_attribute uvcg_mjpeg_bma_controls =
- __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR,
- uvcg_mjpeg_bma_controls_show,
- uvcg_mjpeg_bma_controls_store);
+UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
- &uvcg_mjpeg_b_default_frame_index.attr,
- &uvcg_mjpeg_bm_flags.attr,
- &uvcg_mjpeg_b_aspect_ratio_x.attr,
- &uvcg_mjpeg_b_aspect_ratio_y.attr,
- &uvcg_mjpeg_bm_interface_flags.attr,
- &uvcg_mjpeg_bma_controls.attr,
+ &uvcg_mjpeg_attr_b_default_frame_index,
+ &uvcg_mjpeg_attr_bm_flags,
+ &uvcg_mjpeg_attr_b_aspect_ratio_x,
+ &uvcg_mjpeg_attr_b_aspect_ratio_y,
+ &uvcg_mjpeg_attr_bm_interface_flags,
+ &uvcg_mjpeg_attr_bma_controls,
NULL,
};
static struct config_item_type uvcg_mjpeg_type = {
- .ct_item_ops = &uvcg_mjpeg_item_ops,
.ct_group_ops = &uvcg_mjpeg_group_ops,
.ct_attrs = uvcg_mjpeg_attrs,
.ct_owner = THIS_MODULE,
@@ -1811,17 +1725,12 @@ static inline struct uvcg_default_color_matching
struct uvcg_default_color_matching, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_color_matching);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_color_matching);
-
-static struct configfs_item_operations uvcg_default_color_matching_item_ops = {
- .show_attribute = uvcg_default_color_matching_attr_show,
-};
-
#define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_color_matching_##cname##_show( \
- struct uvcg_default_color_matching *dc, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_color_matching *dc = \
+ to_uvcg_default_color_matching(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
@@ -1842,9 +1751,7 @@ static ssize_t uvcg_default_color_matching_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_color_matching_attribute \
- uvcg_default_color_matching_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_color_matching_##cname##_show)
+UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
#define identity_conv(x) (x)
@@ -1860,14 +1767,13 @@ UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients,
#undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
- &uvcg_default_color_matching_b_color_primaries.attr,
- &uvcg_default_color_matching_b_transfer_characteristics.attr,
- &uvcg_default_color_matching_b_matrix_coefficients.attr,
+ &uvcg_default_color_matching_attr_b_color_primaries,
+ &uvcg_default_color_matching_attr_b_transfer_characteristics,
+ &uvcg_default_color_matching_attr_b_matrix_coefficients,
NULL,
};
static struct config_item_type uvcg_default_color_matching_type = {
- .ct_item_ops = &uvcg_default_color_matching_item_ops,
.ct_attrs = uvcg_default_color_matching_attrs,
.ct_owner = THIS_MODULE,
};
@@ -2285,9 +2191,6 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_uvc_opts);
-CONFIGFS_ATTR_OPS(f_uvc_opts);
-
static void uvc_attr_release(struct config_item *item)
{
struct f_uvc_opts *opts = to_f_uvc_opts(item);
@@ -2297,14 +2200,13 @@ static void uvc_attr_release(struct config_item *item)
static struct configfs_item_operations uvc_item_ops = {
.release = uvc_attr_release,
- .show_attribute = f_uvc_opts_attr_show,
- .store_attribute = f_uvc_opts_attr_store,
};
#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \
static ssize_t f_uvc_opts_##cname##_show( \
- struct f_uvc_opts *opts, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct f_uvc_opts *opts = to_f_uvc_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -2315,9 +2217,10 @@ static ssize_t f_uvc_opts_##cname##_show( \
} \
\
static ssize_t \
-f_uvc_opts_##cname##_store(struct f_uvc_opts *opts, \
+f_uvc_opts_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uvc_opts *opts = to_f_uvc_opts(item); \
int ret; \
uxx num; \
\
@@ -2342,11 +2245,7 @@ end: \
return ret; \
} \
\
-static struct f_uvc_opts_attribute \
- f_uvc_opts_attribute_##cname = \
- __CONFIGFS_ATTR(cname, S_IRUGO | S_IWUSR, \
- f_uvc_opts_##cname##_show, \
- f_uvc_opts_##cname##_store)
+UVC_ATTR(f_uvc_opts_, cname, aname)
#define identity_conv(x) (x)
@@ -2362,9 +2261,9 @@ UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv,
#undef UVCG_OPTS_ATTR
static struct configfs_attribute *uvc_attrs[] = {
- &f_uvc_opts_attribute_streaming_interval.attr,
- &f_uvc_opts_attribute_streaming_maxpacket.attr,
- &f_uvc_opts_attribute_streaming_maxburst.attr,
+ &f_uvc_opts_attr_streaming_interval,
+ &f_uvc_opts_attr_streaming_maxpacket,
+ &f_uvc_opts_attr_streaming_maxburst,
NULL,
};
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index d617c39a0052..51d4a1703af2 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -41,7 +41,7 @@
* videobuf2 queue operations
*/
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -61,9 +61,10 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
- if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
return -EINVAL;
@@ -75,7 +76,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
buf->state = UVC_BUF_STATE_QUEUED;
buf->mem = vb2_plane_vaddr(vb, 0);
buf->length = vb2_plane_size(vb, 0);
- if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
else
buf->bytesused = vb2_get_plane_payload(vb, 0);
@@ -86,7 +87,8 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
static void uvc_buffer_queue(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
@@ -98,7 +100,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
* directly. The next QBUF call will fail with -ENODEV.
*/
buf->state = UVC_BUF_STATE_ERROR;
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -242,7 +244,7 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
@@ -314,7 +316,7 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->length != buf->bytesused) {
buf->state = UVC_BUF_STATE_QUEUED;
- vb2_set_plane_payload(&buf->buf, 0, 0);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
return buf;
}
@@ -325,12 +327,12 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
else
nextbuf = NULL;
- buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
- buf->buf.v4l2_buf.sequence = queue->sequence++;
- v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
+ buf->buf.field = V4L2_FIELD_NONE;
+ buf->buf.sequence = queue->sequence++;
+ v4l2_get_timestamp(&buf->buf.timestamp);
- vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
return nextbuf;
}
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 01ca9eab3481..ac461a9a1a70 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -6,7 +6,7 @@
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/videodev2.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
/* Maximum frame size in bytes, for sanity checking. */
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
@@ -26,7 +26,7 @@ enum uvc_buffer_state {
};
struct uvc_buffer {
- struct vb2_buffer buf;
+ struct vb2_v4l2_buffer buf;
struct list_head queue;
enum uvc_buffer_state state;
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index 5231a32aef55..99ca3dabc4f3 100644
--- a/drivers/usb/gadget/legacy/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
@@ -79,10 +79,7 @@ static int dbgp_consume(char *buf, unsigned len)
static void __disable_ep(struct usb_ep *ep)
{
- if (ep && ep->driver_data == dbgp.gadget) {
- usb_ep_disable(ep);
- ep->driver_data = NULL;
- }
+ usb_ep_disable(ep);
}
static void dbgp_disable_ep(void)
@@ -171,7 +168,6 @@ static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
int err;
ep->desc = desc;
err = usb_ep_enable(ep);
- ep->driver_data = dbgp.gadget;
return err;
}
@@ -229,8 +225,6 @@ static void dbgp_unbind(struct usb_gadget *gadget)
usb_ep_free_request(gadget->ep0, dbgp.req);
dbgp.req = NULL;
}
-
- gadget->ep0->driver_data = NULL;
}
#ifdef CONFIG_USB_G_DBGP_SERIAL
@@ -249,18 +243,15 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
goto fail_1;
}
- dbgp.i_ep->driver_data = gadget;
i_desc.wMaxPacketSize =
cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
if (!dbgp.o_ep) {
- dbgp.i_ep->driver_data = NULL;
stp = 2;
- goto fail_2;
+ goto fail_1;
}
- dbgp.o_ep->driver_data = gadget;
o_desc.wMaxPacketSize =
cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
@@ -277,8 +268,6 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
return 0;
-fail_2:
- dbgp.i_ep->driver_data = NULL;
fail_1:
dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp);
return -ENODEV;
@@ -306,7 +295,6 @@ static int dbgp_bind(struct usb_gadget *gadget,
}
dbgp.req->length = DBGP_REQ_EP0_LEN;
- gadget->ep0->driver_data = gadget;
#ifdef CONFIG_USB_G_DBGP_SERIAL
dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
@@ -356,8 +344,6 @@ static int dbgp_setup(struct usb_gadget *gadget,
void *data = NULL;
u16 len = 0;
- gadget->ep0->driver_data = gadget;
-
if (request == USB_REQ_GET_DESCRIPTOR) {
switch (value>>8) {
case USB_DT_DEVICE:
diff --git a/drivers/usb/gadget/legacy/tcm_usb_gadget.c b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
index c3c48088fced..22e56158d585 100644
--- a/drivers/usb/gadget/legacy/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
@@ -19,8 +19,6 @@
#include <scsi/scsi_tcq.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include <asm/unaligned.h>
#include "tcm_usb_gadget.h"
@@ -1467,23 +1465,21 @@ static void usbg_drop_tport(struct se_wwn *wwn)
/*
* If somebody feels like dropping the version property, go ahead.
*/
-static ssize_t usbg_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t usbg_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "usb-gadget fabric module\n");
}
-TF_WWN_ATTR_RO(usbg, version);
+
+CONFIGFS_ATTR_RO(usbg_wwn_, version);
static struct configfs_attribute *usbg_wwn_attrs[] = {
- &usbg_wwn_version.attr,
+ &usbg_wwn_attr_version,
NULL,
};
-static ssize_t tcm_usbg_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_usbg_tpg_enable_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
@@ -1492,11 +1488,10 @@ static ssize_t tcm_usbg_tpg_show_enable(
static int usbg_attach(struct usbg_tpg *);
static void usbg_detach(struct usbg_tpg *);
-static ssize_t tcm_usbg_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_usbg_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
unsigned long op;
ssize_t ret;
@@ -1523,12 +1518,10 @@ static ssize_t tcm_usbg_tpg_store_enable(
out:
return count;
}
-TF_TPG_BASE_ATTR(tcm_usbg, enable, S_IRUGO | S_IWUSR);
-static ssize_t tcm_usbg_tpg_show_nexus(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_usbg_tpg_nexus_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
struct tcm_usbg_nexus *tv_nexus;
ssize_t ret;
@@ -1636,11 +1629,10 @@ out:
return ret;
}
-static ssize_t tcm_usbg_tpg_store_nexus(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_usbg_tpg_nexus_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
unsigned char i_port[USBG_NAMELEN], *ptr;
int ret;
@@ -1670,11 +1662,13 @@ static ssize_t tcm_usbg_tpg_store_nexus(
return ret;
return count;
}
-TF_TPG_BASE_ATTR(tcm_usbg, nexus, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR(tcm_usbg_tpg_, enable);
+CONFIGFS_ATTR(tcm_usbg_tpg_, nexus);
static struct configfs_attribute *usbg_base_attrs[] = {
- &tcm_usbg_tpg_enable.attr,
- &tcm_usbg_tpg_nexus.attr,
+ &tcm_usbg_tpg_attr_enable,
+ &tcm_usbg_tpg_attr_nexus,
NULL,
};
@@ -2018,14 +2012,6 @@ static struct usb_configuration usbg_config_driver = {
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
-static void give_back_ep(struct usb_ep **pep)
-{
- struct usb_ep *ep = *pep;
- if (!ep)
- return;
- ep->driver_data = NULL;
-}
-
static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct f_uas *fu = to_f_uas(f);
@@ -2045,29 +2031,24 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
&uasp_bi_ep_comp_desc);
if (!ep)
goto ep_fail;
-
- ep->driver_data = fu;
fu->ep_in = ep;
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
&uasp_bo_ep_comp_desc);
if (!ep)
goto ep_fail;
- ep->driver_data = fu;
fu->ep_out = ep;
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
&uasp_status_in_ep_comp_desc);
if (!ep)
goto ep_fail;
- ep->driver_data = fu;
fu->ep_status = ep;
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
&uasp_cmd_comp_desc);
if (!ep)
goto ep_fail;
- ep->driver_data = fu;
fu->ep_cmd = ep;
/* Assume endpoint addresses are the same for both speeds */
@@ -2091,11 +2072,6 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
ep_fail:
pr_err("Can't claim all required eps\n");
-
- give_back_ep(&fu->ep_in);
- give_back_ep(&fu->ep_out);
- give_back_ep(&fu->ep_status);
- give_back_ep(&fu->ep_cmd);
return -ENOTSUPP;
}
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 9a3a6b00391a..cdbff54e07ac 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -55,7 +55,7 @@ config USB_LPC32XX
config USB_ATMEL_USBA
tristate "Atmel USBA"
- depends on AVR32 || ARCH_AT91
+ depends on ((AVR32 && !OF) || ARCH_AT91)
help
USBA is the integrated high-speed USB Device controller on
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
index 175ca93fe5e2..cd8764150861 100644
--- a/drivers/usb/gadget/udc/amd5536udc.c
+++ b/drivers/usb/gadget/udc/amd5536udc.c
@@ -65,18 +65,10 @@
static void udc_tasklet_disconnect(unsigned long);
static void empty_req_queue(struct udc_ep *);
-static int udc_probe(struct udc *dev);
-static void udc_basic_init(struct udc *dev);
static void udc_setup_endpoints(struct udc *dev);
static void udc_soft_reset(struct udc *dev);
static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
-static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
- unsigned long buf_len, gfp_t gfp_flags);
-static int udc_remote_wakeup(struct udc *dev);
-static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void udc_pci_remove(struct pci_dev *pdev);
/* description */
static const char mod_desc[] = UDC_MOD_DESCRIPTION;
@@ -615,6 +607,30 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
return &req->req;
}
+/* frees pci pool descriptors of a DMA chain */
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
+{
+ int ret_val = 0;
+ struct udc_data_dma *td;
+ struct udc_data_dma *td_last = NULL;
+ unsigned int i;
+
+ DBG(dev, "free chain req = %p\n", req);
+
+ /* do not free first desc., will be done by free for request */
+ td_last = req->td_data;
+ td = phys_to_virt(td_last->next);
+
+ for (i = 1; i < req->chain_len; i++) {
+ pci_pool_free(dev->data_requests, td,
+ (dma_addr_t)td_last->next);
+ td_last = td;
+ td = phys_to_virt(td_last->next);
+ }
+
+ return ret_val;
+}
+
/* Frees request packet, called by gadget driver */
static void
udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -789,6 +805,123 @@ udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
return finished;
}
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+ struct udc_ep *ep,
+ struct udc_request *req,
+ unsigned long buf_len, gfp_t gfp_flags
+)
+{
+ unsigned long bytes = req->req.length;
+ unsigned int i;
+ dma_addr_t dma_addr;
+ struct udc_data_dma *td = NULL;
+ struct udc_data_dma *last = NULL;
+ unsigned long txbytes;
+ unsigned create_new_chain = 0;
+ unsigned len;
+
+ VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
+ bytes, buf_len);
+ dma_addr = DMA_DONT_USE;
+
+ /* unset L bit in first desc for OUT */
+ if (!ep->in)
+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+
+ /* alloc only new desc's if not already available */
+ len = req->req.length / ep->ep.maxpacket;
+ if (req->req.length % ep->ep.maxpacket)
+ len++;
+
+ if (len > req->chain_len) {
+ /* shorter chain already allocated before */
+ if (req->chain_len > 1)
+ udc_free_dma_chain(ep->dev, req);
+ req->chain_len = len;
+ create_new_chain = 1;
+ }
+
+ td = req->td_data;
+ /* gen. required number of descriptors and buffers */
+ for (i = buf_len; i < bytes; i += buf_len) {
+ /* create or determine next desc. */
+ if (create_new_chain) {
+ td = pci_pool_alloc(ep->dev->data_requests,
+ gfp_flags, &dma_addr);
+ if (!td)
+ return -ENOMEM;
+
+ td->status = 0;
+ } else if (i == buf_len) {
+ /* first td */
+ td = (struct udc_data_dma *)phys_to_virt(
+ req->td_data->next);
+ td->status = 0;
+ } else {
+ td = (struct udc_data_dma *)phys_to_virt(last->next);
+ td->status = 0;
+ }
+
+ if (td)
+ td->bufptr = req->req.dma + i; /* assign buffer */
+ else
+ break;
+
+ /* short packet ? */
+ if ((bytes - i) >= buf_len) {
+ txbytes = buf_len;
+ } else {
+ /* short packet */
+ txbytes = bytes - i;
+ }
+
+ /* link td and assign tx bytes */
+ if (i == buf_len) {
+ if (create_new_chain)
+ req->td_data->next = dma_addr;
+ /*
+ * else
+ * req->td_data->next = virt_to_phys(td);
+ */
+ /* write tx bytes */
+ if (ep->in) {
+ /* first desc */
+ req->td_data->status =
+ AMD_ADDBITS(req->td_data->status,
+ ep->ep.maxpacket,
+ UDC_DMA_IN_STS_TXBYTES);
+ /* second desc */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+ } else {
+ if (create_new_chain)
+ last->next = dma_addr;
+ /*
+ * else
+ * last->next = virt_to_phys(td);
+ */
+ if (ep->in) {
+ /* write tx bytes */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+ }
+ last = td;
+ }
+ /* set last bit */
+ if (td) {
+ td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+ /* last desc. points to itself */
+ req->td_data_last = td;
+ }
+
+ return 0;
+}
+
/* create/re-init a DMA descriptor or a DMA descriptor chain */
static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
{
@@ -913,32 +1046,6 @@ __acquires(ep->dev->lock)
ep->halted = halted;
}
-/* frees pci pool descriptors of a DMA chain */
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
-{
-
- int ret_val = 0;
- struct udc_data_dma *td;
- struct udc_data_dma *td_last = NULL;
- unsigned int i;
-
- DBG(dev, "free chain req = %p\n", req);
-
- /* do not free first desc., will be done by free for request */
- td_last = req->td_data;
- td = phys_to_virt(td_last->next);
-
- for (i = 1; i < req->chain_len; i++) {
-
- pci_pool_free(dev->data_requests, td,
- (dma_addr_t) td_last->next);
- td_last = td;
- td = phys_to_virt(td_last->next);
- }
-
- return ret_val;
-}
-
/* Iterates to the end of a DMA chain and returns last descriptor */
static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
{
@@ -975,125 +1082,6 @@ static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
}
-/* Creates or re-inits a DMA chain */
-static int udc_create_dma_chain(
- struct udc_ep *ep,
- struct udc_request *req,
- unsigned long buf_len, gfp_t gfp_flags
-)
-{
- unsigned long bytes = req->req.length;
- unsigned int i;
- dma_addr_t dma_addr;
- struct udc_data_dma *td = NULL;
- struct udc_data_dma *last = NULL;
- unsigned long txbytes;
- unsigned create_new_chain = 0;
- unsigned len;
-
- VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
- bytes, buf_len);
- dma_addr = DMA_DONT_USE;
-
- /* unset L bit in first desc for OUT */
- if (!ep->in)
- req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-
- /* alloc only new desc's if not already available */
- len = req->req.length / ep->ep.maxpacket;
- if (req->req.length % ep->ep.maxpacket)
- len++;
-
- if (len > req->chain_len) {
- /* shorter chain already allocated before */
- if (req->chain_len > 1)
- udc_free_dma_chain(ep->dev, req);
- req->chain_len = len;
- create_new_chain = 1;
- }
-
- td = req->td_data;
- /* gen. required number of descriptors and buffers */
- for (i = buf_len; i < bytes; i += buf_len) {
- /* create or determine next desc. */
- if (create_new_chain) {
-
- td = pci_pool_alloc(ep->dev->data_requests,
- gfp_flags, &dma_addr);
- if (!td)
- return -ENOMEM;
-
- td->status = 0;
- } else if (i == buf_len) {
- /* first td */
- td = (struct udc_data_dma *) phys_to_virt(
- req->td_data->next);
- td->status = 0;
- } else {
- td = (struct udc_data_dma *) phys_to_virt(last->next);
- td->status = 0;
- }
-
-
- if (td)
- td->bufptr = req->req.dma + i; /* assign buffer */
- else
- break;
-
- /* short packet ? */
- if ((bytes - i) >= buf_len) {
- txbytes = buf_len;
- } else {
- /* short packet */
- txbytes = bytes - i;
- }
-
- /* link td and assign tx bytes */
- if (i == buf_len) {
- if (create_new_chain)
- req->td_data->next = dma_addr;
- /*
- else
- req->td_data->next = virt_to_phys(td);
- */
- /* write tx bytes */
- if (ep->in) {
- /* first desc */
- req->td_data->status =
- AMD_ADDBITS(req->td_data->status,
- ep->ep.maxpacket,
- UDC_DMA_IN_STS_TXBYTES);
- /* second desc */
- td->status = AMD_ADDBITS(td->status,
- txbytes,
- UDC_DMA_IN_STS_TXBYTES);
- }
- } else {
- if (create_new_chain)
- last->next = dma_addr;
- /*
- else
- last->next = virt_to_phys(td);
- */
- if (ep->in) {
- /* write tx bytes */
- td->status = AMD_ADDBITS(td->status,
- txbytes,
- UDC_DMA_IN_STS_TXBYTES);
- }
- }
- last = td;
- }
- /* set last bit */
- if (td) {
- td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
- /* last desc. points to itself */
- req->td_data_last = td;
- }
-
- return 0;
-}
-
/* Enabling RX DMA */
static void udc_set_rde(struct udc *dev)
{
@@ -1453,6 +1441,26 @@ static int udc_get_frame(struct usb_gadget *gadget)
return -EOPNOTSUPP;
}
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ DBG(dev, "UDC initiates remote wakeup\n");
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ tmp = readl(&dev->regs->ctl);
+ tmp |= AMD_BIT(UDC_DEVCTL_RES);
+ writel(tmp, &dev->regs->ctl);
+ tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+ writel(tmp, &dev->regs->ctl);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return 0;
+}
+
/* Remote wakeup gadget interface */
static int udc_wakeup(struct usb_gadget *gadget)
{
@@ -1498,33 +1506,6 @@ static void make_ep_lists(struct udc *dev)
dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
}
-/* init registers at driver load time */
-static int startup_registers(struct udc *dev)
-{
- u32 tmp;
-
- /* init controller by soft reset */
- udc_soft_reset(dev);
-
- /* mask not needed interrupts */
- udc_mask_unused_interrupts(dev);
-
- /* put into initial config */
- udc_basic_init(dev);
- /* link up all endpoints */
- udc_setup_endpoints(dev);
-
- /* program speed */
- tmp = readl(&dev->regs->cfg);
- if (use_fullspeed)
- tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
- else
- tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
- writel(tmp, &dev->regs->cfg);
-
- return 0;
-}
-
/* Inits UDC context */
static void udc_basic_init(struct udc *dev)
{
@@ -1563,6 +1544,33 @@ static void udc_basic_init(struct udc *dev)
dev->data_ep_queued = 0;
}
+/* init registers at driver load time */
+static int startup_registers(struct udc *dev)
+{
+ u32 tmp;
+
+ /* init controller by soft reset */
+ udc_soft_reset(dev);
+
+ /* mask not needed interrupts */
+ udc_mask_unused_interrupts(dev);
+
+ /* put into initial config */
+ udc_basic_init(dev);
+ /* link up all endpoints */
+ udc_setup_endpoints(dev);
+
+ /* program speed */
+ tmp = readl(&dev->regs->cfg);
+ if (use_fullspeed)
+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+ else
+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
+ writel(tmp, &dev->regs->cfg);
+
+ return 0;
+}
+
/* Sets initial endpoint parameters */
static void udc_setup_endpoints(struct udc *dev)
{
@@ -2177,7 +2185,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
}
/* DMA */
- } else if (!ep->cancel_transfer && req != NULL) {
+ } else if (!ep->cancel_transfer && req) {
ret_val = IRQ_HANDLED;
/* check for DMA done */
@@ -3107,6 +3115,17 @@ static void udc_remove(struct udc *dev)
udc = NULL;
}
+/* free all the dma pools */
+static void free_dma_pools(struct udc *dev)
+{
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td,
+ dev->ep[UDC_EP0OUT_IX].td_phys);
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+ dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+ dma_pool_destroy(dev->stp_requests);
+ dma_pool_destroy(dev->data_requests);
+}
+
/* Reset all pci context */
static void udc_pci_remove(struct pci_dev *pdev)
{
@@ -3116,35 +3135,19 @@ static void udc_pci_remove(struct pci_dev *pdev)
usb_del_gadget_udc(&udc->gadget);
/* gadget driver must not be registered */
- BUG_ON(dev->driver != NULL);
+ if (WARN_ON(dev->driver))
+ return;
/* dma pool cleanup */
- if (dev->data_requests)
- pci_pool_destroy(dev->data_requests);
-
- if (dev->stp_requests) {
- /* cleanup DMA desc's for ep0in */
- pci_pool_free(dev->stp_requests,
- dev->ep[UDC_EP0OUT_IX].td_stp,
- dev->ep[UDC_EP0OUT_IX].td_stp_dma);
- pci_pool_free(dev->stp_requests,
- dev->ep[UDC_EP0OUT_IX].td,
- dev->ep[UDC_EP0OUT_IX].td_phys);
-
- pci_pool_destroy(dev->stp_requests);
- }
+ free_dma_pools(dev);
/* reset controller */
writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
- if (dev->irq_registered)
- free_irq(pdev->irq, dev);
- if (dev->virt_addr)
- iounmap(dev->virt_addr);
- if (dev->mem_region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (dev->active)
- pci_disable_device(pdev);
+ free_irq(pdev->irq, dev);
+ iounmap(dev->virt_addr);
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
udc_remove(dev);
}
@@ -3169,8 +3172,7 @@ static int init_dma_pools(struct udc *dev)
sizeof(struct udc_data_dma), 0, 0);
if (!dev->data_requests) {
DBG(dev, "can't get request data pool\n");
- retval = -ENOMEM;
- goto finished;
+ return -ENOMEM;
}
/* EP0 in dma regs = dev control regs */
@@ -3182,27 +3184,101 @@ static int init_dma_pools(struct udc *dev)
if (!dev->stp_requests) {
DBG(dev, "can't get stp request pool\n");
retval = -ENOMEM;
- goto finished;
+ goto err_create_dma_pool;
}
/* setup */
td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
&dev->ep[UDC_EP0OUT_IX].td_stp_dma);
- if (td_stp == NULL) {
+ if (!td_stp) {
retval = -ENOMEM;
- goto finished;
+ goto err_alloc_dma;
}
dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
/* data: 0 packets !? */
td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
&dev->ep[UDC_EP0OUT_IX].td_phys);
- if (td_data == NULL) {
+ if (!td_data) {
retval = -ENOMEM;
- goto finished;
+ goto err_alloc_phys;
}
dev->ep[UDC_EP0OUT_IX].td = td_data;
return 0;
+err_alloc_phys:
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+ dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+err_alloc_dma:
+ dma_pool_destroy(dev->stp_requests);
+ dev->stp_requests = NULL;
+err_create_dma_pool:
+ dma_pool_destroy(dev->data_requests);
+ dev->data_requests = NULL;
+ return retval;
+}
+
+/* general probe */
+static int udc_probe(struct udc *dev)
+{
+ char tmp[128];
+ u32 reg;
+ int retval;
+
+ /* mark timer as not initialized */
+ udc_timer.data = 0;
+ udc_pollstall_timer.data = 0;
+
+ /* device struct setup */
+ dev->gadget.ops = &udc_ops;
+
+ dev_set_name(&dev->gadget.dev, "gadget");
+ dev->gadget.name = name;
+ dev->gadget.max_speed = USB_SPEED_HIGH;
+
+ /* init registers, interrupts, ... */
+ startup_registers(dev);
+
+ dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+ snprintf(tmp, sizeof(tmp), "%d", dev->irq);
+ dev_info(&dev->pdev->dev,
+ "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+ tmp, dev->phys_addr, dev->chiprev,
+ (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+ if (dev->chiprev == UDC_HSA0_REV) {
+ dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+ retval = -ENODEV;
+ goto finished;
+ }
+ dev_info(&dev->pdev->dev,
+ "driver version: %s(for Geode5536 B1)\n", tmp);
+ udc = dev;
+
+ retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+ gadget_release);
+ if (retval)
+ goto finished;
+
+ /* timer init */
+ init_timer(&udc_timer);
+ udc_timer.function = udc_timer_function;
+ udc_timer.data = 1;
+ /* timer pollstall init */
+ init_timer(&udc_pollstall_timer);
+ udc_pollstall_timer.function = udc_pollstall_timer_function;
+ udc_pollstall_timer.data = 1;
+
+ /* set SD */
+ reg = readl(&dev->regs->ctl);
+ reg |= AMD_BIT(UDC_DEVCTL_SD);
+ writel(reg, &dev->regs->ctl);
+
+ /* print dev register info */
+ print_regs(dev);
+
+ return 0;
+
finished:
return retval;
}
@@ -3234,7 +3310,6 @@ static int udc_pci_probe(
retval = -ENODEV;
goto err_pcidev;
}
- dev->active = 1;
/* PCI resource allocation */
resource = pci_resource_start(pdev, 0);
@@ -3245,10 +3320,9 @@ static int udc_pci_probe(
retval = -EBUSY;
goto err_memreg;
}
- dev->mem_region = 1;
dev->virt_addr = ioremap_nocache(resource, len);
- if (dev->virt_addr == NULL) {
+ if (!dev->virt_addr) {
dev_dbg(&pdev->dev, "start address cannot be mapped\n");
retval = -EFAULT;
goto err_ioremap;
@@ -3276,7 +3350,6 @@ static int udc_pci_probe(
retval = -EBUSY;
goto err_irq;
}
- dev->irq_registered = 1;
pci_set_drvdata(pdev, dev);
@@ -3290,7 +3363,7 @@ static int udc_pci_probe(
if (use_dma) {
retval = init_dma_pools(dev);
if (retval != 0)
- goto finished;
+ goto err_dma;
}
dev->phys_addr = resource;
@@ -3298,13 +3371,17 @@ static int udc_pci_probe(
dev->pdev = pdev;
/* general probing */
- if (udc_probe(dev) == 0)
- return 0;
-
-finished:
- udc_pci_remove(pdev);
- return retval;
+ if (udc_probe(dev)) {
+ retval = -ENODEV;
+ goto err_probe;
+ }
+ return 0;
+err_probe:
+ if (use_dma)
+ free_dma_pools(dev);
+err_dma:
+ free_irq(pdev->irq, dev);
err_irq:
iounmap(dev->virt_addr);
err_ioremap:
@@ -3316,92 +3393,6 @@ err_pcidev:
return retval;
}
-/* general probe */
-static int udc_probe(struct udc *dev)
-{
- char tmp[128];
- u32 reg;
- int retval;
-
- /* mark timer as not initialized */
- udc_timer.data = 0;
- udc_pollstall_timer.data = 0;
-
- /* device struct setup */
- dev->gadget.ops = &udc_ops;
-
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.name = name;
- dev->gadget.max_speed = USB_SPEED_HIGH;
-
- /* init registers, interrupts, ... */
- startup_registers(dev);
-
- dev_info(&dev->pdev->dev, "%s\n", mod_desc);
-
- snprintf(tmp, sizeof tmp, "%d", dev->irq);
- dev_info(&dev->pdev->dev,
- "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
- tmp, dev->phys_addr, dev->chiprev,
- (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
- strcpy(tmp, UDC_DRIVER_VERSION_STRING);
- if (dev->chiprev == UDC_HSA0_REV) {
- dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
- retval = -ENODEV;
- goto finished;
- }
- dev_info(&dev->pdev->dev,
- "driver version: %s(for Geode5536 B1)\n", tmp);
- udc = dev;
-
- retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
- gadget_release);
- if (retval)
- goto finished;
-
- /* timer init */
- init_timer(&udc_timer);
- udc_timer.function = udc_timer_function;
- udc_timer.data = 1;
- /* timer pollstall init */
- init_timer(&udc_pollstall_timer);
- udc_pollstall_timer.function = udc_pollstall_timer_function;
- udc_pollstall_timer.data = 1;
-
- /* set SD */
- reg = readl(&dev->regs->ctl);
- reg |= AMD_BIT(UDC_DEVCTL_SD);
- writel(reg, &dev->regs->ctl);
-
- /* print dev register info */
- print_regs(dev);
-
- return 0;
-
-finished:
- return retval;
-}
-
-/* Initiates a remote wakeup */
-static int udc_remote_wakeup(struct udc *dev)
-{
- unsigned long flags;
- u32 tmp;
-
- DBG(dev, "UDC initiates remote wakeup\n");
-
- spin_lock_irqsave(&dev->lock, flags);
-
- tmp = readl(&dev->regs->ctl);
- tmp |= AMD_BIT(UDC_DEVCTL_RES);
- writel(tmp, &dev->regs->ctl);
- tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
- writel(tmp, &dev->regs->ctl);
-
- spin_unlock_irqrestore(&dev->lock, flags);
- return 0;
-}
-
/* PCI device parameters */
static const struct pci_device_id pci_id[] = {
{
diff --git a/drivers/usb/gadget/udc/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
index 6744d3b83109..4638d707f169 100644
--- a/drivers/usb/gadget/udc/amd5536udc.h
+++ b/drivers/usb/gadget/udc/amd5536udc.h
@@ -526,14 +526,11 @@ struct udc {
struct udc_ep ep[UDC_EP_NUM];
struct usb_gadget_driver *driver;
/* operational flags */
- unsigned active : 1,
- stall_ep0in : 1,
+ unsigned stall_ep0in : 1,
waiting_zlp_ack_ep0in : 1,
set_cfg_not_acked : 1,
- irq_registered : 1,
data_ep_enabled : 1,
data_ep_queued : 1,
- mem_region : 1,
sys_suspended : 1,
connected;
diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h
index 2679c8b217cc..0a433e6b346b 100644
--- a/drivers/usb/gadget/udc/at91_udc.h
+++ b/drivers/usb/gadget/udc/at91_udc.h
@@ -112,6 +112,14 @@ struct at91_udc_caps {
void (*pullup)(struct at91_udc *udc, int is_on);
};
+struct at91_udc_data {
+ int vbus_pin; /* high == host powering us */
+ u8 vbus_active_low; /* vbus polarity */
+ u8 vbus_polled; /* Use polling, not interrupt */
+ int pullup_pin; /* active == D+ pulled up */
+ u8 pullup_active_low; /* true == pullup_pin is active low */
+};
+
/*
* driver is non-SMP, and just blocks IRQs whenever it needs
* access protection for chip registers or driver state
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index f0f2b066ac08..f92f5aff0dd5 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1633,7 +1633,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
spin_lock(&udc->lock);
int_enb = usba_int_enb_get(udc);
- status = usba_readl(udc, INT_STA) & int_enb;
+ status = usba_readl(udc, INT_STA) & (int_enb | USBA_HIGH_SPEED);
DBG(DBG_INT, "irq, status=%#08x\n", status);
if (status & USBA_DET_SUSPEND) {
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 27af0f008b57..dde44450dfa9 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -833,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
/* there are both host and device side versions of this call ... */
static int dummy_g_get_frame(struct usb_gadget *_gadget)
{
- struct timeval tv;
+ struct timespec64 ts64;
- do_gettimeofday(&tv);
- return tv.tv_usec / 1000;
+ ktime_get_ts64(&ts64);
+ return ts64.tv_nsec / NSEC_PER_MSEC;
}
static int dummy_wakeup(struct usb_gadget *_gadget)
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index cf0ed42f5591..6706aef907f4 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -1913,7 +1913,7 @@ static void defect7374_disable_data_eps(struct net2280 *dev)
for (i = 1; i < 5; i++) {
ep = &dev->ep[i];
- writel(0, &ep->cfg->ep_cfg);
+ writel(i, &ep->cfg->ep_cfg);
}
/* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c
index e5f4c5274298..7a04157ff579 100644
--- a/drivers/usb/gadget/udc/pch_udc.c
+++ b/drivers/usb/gadget/udc/pch_udc.c
@@ -330,7 +330,7 @@ struct pch_vbus_gpio_data {
* @prot_stall: protcol stall requested
* @irq_registered: irq registered with system
* @mem_region: device memory mapped
- * @registered: driver regsitered with system
+ * @registered: driver registered with system
* @suspended: driver in suspended state
* @connected: gadget driver associated
* @vbus_session: required vbus_session state
@@ -2747,18 +2747,18 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
if (dev_intr & UDC_DEVINT_US) {
if (dev->driver
&& dev->driver->suspend) {
- spin_lock(&dev->lock);
- dev->driver->suspend(&dev->gadget);
spin_unlock(&dev->lock);
+ dev->driver->suspend(&dev->gadget);
+ spin_lock(&dev->lock);
}
vbus = pch_vbus_gpio_get_value(dev);
if ((dev->vbus_session == 0)
&& (vbus != 1)) {
if (dev->driver && dev->driver->disconnect) {
- spin_lock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_unlock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
}
pch_udc_reconnect(dev);
} else if ((dev->vbus_session == 0)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 079991e283e9..3bb08870148f 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -348,16 +348,6 @@ config USB_ISP1362_HCD
To compile this driver as a module, choose M here: the
module will be called isp1362-hcd.
-config USB_FUSBH200_HCD
- tristate "FUSBH200 HCD support"
- depends on USB
- ---help---
- Faraday FUSBH200 is designed to meet USB2.0 EHCI specification
- with minor modification.
-
- To compile this driver as a module, choose M here: the
- module will be called fusbh200-hcd.
-
config USB_FOTG210_HCD
tristate "FOTG210 HCD support"
depends on USB
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 754efaa8ccf8..e7558abc994d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -28,9 +28,6 @@ ifneq ($(CONFIG_USB), )
obj-$(CONFIG_PCI) += pci-quirks.o
endif
-obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
-obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
-
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
@@ -65,6 +62,8 @@ obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o
+obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
+obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
@@ -75,6 +74,5 @@ obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
obj-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o
obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o
-obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o
obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o
obj-$(CONFIG_USB_MAX3421_HCD) += max3421-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c63d82c91f10..48c92bf78bd0 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -589,7 +589,7 @@ static int ehci_run (struct usb_hcd *hcd)
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
- * NOTE: the dma mask is visible through dma_supported(), so
+ * NOTE: the dma mask is visible through dev->dma_mask, so
* drivers can pass this info along ... like NETIF_F_HIGHDMA,
* Scsi_Host.highmem_io, and so forth. It's readonly to all
* host side drivers though.
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 275c92e53a59..c4f84c81de01 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -80,12 +80,12 @@ static int ehci_msm_probe(struct platform_device *pdev)
return -ENOMEM;
}
- hcd->irq = platform_get_irq(pdev, 0);
- if (hcd->irq < 0) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
dev_err(&pdev->dev, "Unable to get IRQ resource\n");
- ret = hcd->irq;
goto put_hcd;
}
+ hcd->irq = ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index bfcbb9aa8816..ee8d5faa0194 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -224,7 +224,8 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
priv->phy = devm_phy_optional_get(&pdev->dev, "usb");
if (IS_ERR(priv->phy)) {
err = PTR_ERR(priv->phy);
- goto err_phy_get;
+ if (err != -ENOSYS)
+ goto err_phy_get;
} else {
err = phy_init(priv->phy);
if (err)
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 5c3c08598682..bd7082f297bb 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -19,6 +19,7 @@
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@@ -162,8 +163,10 @@ static int ehci_platform_probe(struct platform_device *dev)
err = dma_coerce_mask_and_coherent(&dev->dev,
pdata->dma_mask_64 ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32));
- if (err)
+ if (err) {
+ dev_err(&dev->dev, "Error: DMA mask configuration failed\n");
return err;
+ }
irq = platform_get_irq(dev, 0);
if (irq < 0) {
@@ -385,6 +388,12 @@ static const struct of_device_id vt8500_ehci_ids[] = {
};
MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
+static const struct acpi_device_id ehci_acpi_match[] = {
+ { "PNP0D20", 0 }, /* EHCI controller without debug */
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, ehci_acpi_match);
+
static const struct platform_device_id ehci_platform_table[] = {
{ "ehci-platform", 0 },
{ }
@@ -403,6 +412,7 @@ static struct platform_driver ehci_platform_driver = {
.name = "ehci-platform",
.pm = &ehci_platform_pm_ops,
.of_match_table = vt8500_ehci_ids,
+ .acpi_match_table = ACPI_PTR(ehci_acpi_match),
}
};
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 34e14746b92e..3c4e5253955c 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -149,6 +149,7 @@ static const struct of_device_id spear_ehci_id_table[] = {
{ .compatible = "st,spear600-ehci", },
{ },
};
+MODULE_DEVICE_TABLE(of, spear_ehci_id_table);
static struct platform_driver spear_ehci_hcd_driver = {
.probe = spear_ehci_hcd_drv_probe,
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 000ed80ab592..2341af4f3490 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -1,5 +1,4 @@
-/*
- * Faraday FOTG210 EHCI-like driver
+/* Faraday FOTG210 EHCI-like driver
*
* Copyright (c) 2013 Faraday Technology Corporation
*
@@ -50,32 +49,29 @@
#include <asm/irq.h>
#include <asm/unaligned.h>
-/*-------------------------------------------------------------------------*/
#define DRIVER_AUTHOR "Yuan-Hsin Chen"
#define DRIVER_DESC "FOTG210 Host Controller (EHCI) Driver"
-
-static const char hcd_name[] = "fotg210_hcd";
+static const char hcd_name[] = "fotg210_hcd";
#undef FOTG210_URB_TRACE
-
#define FOTG210_STATS
/* magic numbers that can affect system performance */
-#define FOTG210_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
-#define FOTG210_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
-#define FOTG210_TUNE_RL_TT 0
-#define FOTG210_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
-#define FOTG210_TUNE_MULT_TT 1
-/*
- * Some drivers think it's safe to schedule isochronous transfers more than
- * 256 ms into the future (partly as a result of an old bug in the scheduling
+#define FOTG210_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
+#define FOTG210_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
+#define FOTG210_TUNE_RL_TT 0
+#define FOTG210_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
+#define FOTG210_TUNE_MULT_TT 1
+
+/* Some drivers think it's safe to schedule isochronous transfers more than 256
+ * ms into the future (partly as a result of an old bug in the scheduling
* code). In an attempt to avoid trouble, we will use a minimum scheduling
* length of 512 frames instead of 256.
*/
-#define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */
+#define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */
/* Initial IRQ latency: faster than hw default */
-static int log2_irq_thresh; /* 0 to 6 */
+static int log2_irq_thresh; /* 0 to 6 */
module_param(log2_irq_thresh, int, S_IRUGO);
MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
@@ -89,66 +85,57 @@ static unsigned int hird;
module_param(hird, int, S_IRUGO);
MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
-#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
+#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
#include "fotg210.h"
-/*-------------------------------------------------------------------------*/
-
#define fotg210_dbg(fotg210, fmt, args...) \
- dev_dbg(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+ dev_dbg(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
#define fotg210_err(fotg210, fmt, args...) \
- dev_err(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+ dev_err(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
#define fotg210_info(fotg210, fmt, args...) \
- dev_info(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+ dev_info(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
#define fotg210_warn(fotg210, fmt, args...) \
- dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+ dev_warn(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
-/* check the values in the HCSPARAMS register
- * (host controller _Structural_ parameters)
- * see EHCI spec, Table 2-4 for each value
+/* check the values in the HCSPARAMS register (host controller _Structural_
+ * parameters) see EHCI spec, Table 2-4 for each value
*/
static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label)
{
- u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
+ u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
- fotg210_dbg(fotg210,
- "%s hcs_params 0x%x ports=%d\n",
- label, params,
- HCS_N_PORTS(params)
- );
+ fotg210_dbg(fotg210, "%s hcs_params 0x%x ports=%d\n", label, params,
+ HCS_N_PORTS(params));
}
-/* check the values in the HCCPARAMS register
- * (host controller _Capability_ parameters)
- * see EHCI Spec, Table 2-5 for each value
- * */
+/* check the values in the HCCPARAMS register (host controller _Capability_
+ * parameters) see EHCI Spec, Table 2-5 for each value
+ */
static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label)
{
- u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
+ u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
- fotg210_dbg(fotg210,
- "%s hcc_params %04x uframes %s%s\n",
- label,
- params,
- HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
- HCC_CANPARK(params) ? " park" : "");
+ fotg210_dbg(fotg210, "%s hcc_params %04x uframes %s%s\n", label,
+ params,
+ HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+ HCC_CANPARK(params) ? " park" : "");
}
static void __maybe_unused
dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd)
{
fotg210_dbg(fotg210, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
- hc32_to_cpup(fotg210, &qtd->hw_next),
- hc32_to_cpup(fotg210, &qtd->hw_alt_next),
- hc32_to_cpup(fotg210, &qtd->hw_token),
- hc32_to_cpup(fotg210, &qtd->hw_buf[0]));
+ hc32_to_cpup(fotg210, &qtd->hw_next),
+ hc32_to_cpup(fotg210, &qtd->hw_alt_next),
+ hc32_to_cpup(fotg210, &qtd->hw_token),
+ hc32_to_cpup(fotg210, &qtd->hw_buf[0]));
if (qtd->hw_buf[1])
fotg210_dbg(fotg210, " p1=%08x p2=%08x p3=%08x p4=%08x\n",
- hc32_to_cpup(fotg210, &qtd->hw_buf[1]),
- hc32_to_cpup(fotg210, &qtd->hw_buf[2]),
- hc32_to_cpup(fotg210, &qtd->hw_buf[3]),
- hc32_to_cpup(fotg210, &qtd->hw_buf[4]));
+ hc32_to_cpup(fotg210, &qtd->hw_buf[1]),
+ hc32_to_cpup(fotg210, &qtd->hw_buf[2]),
+ hc32_to_cpup(fotg210, &qtd->hw_buf[3]),
+ hc32_to_cpup(fotg210, &qtd->hw_buf[4]));
}
static void __maybe_unused
@@ -156,101 +143,100 @@ dbg_qh(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{
struct fotg210_qh_hw *hw = qh->hw;
- fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label,
- qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
+ fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label, qh,
+ hw->hw_next, hw->hw_info1, hw->hw_info2,
+ hw->hw_current);
+
dbg_qtd("overlay", fotg210, (struct fotg210_qtd *) &hw->hw_qtd_next);
}
static void __maybe_unused
dbg_itd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
{
- fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n",
- label, itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next),
- itd->urb);
+ fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n", label,
+ itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next),
+ itd->urb);
+
fotg210_dbg(fotg210,
- " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
- hc32_to_cpu(fotg210, itd->hw_transaction[0]),
- hc32_to_cpu(fotg210, itd->hw_transaction[1]),
- hc32_to_cpu(fotg210, itd->hw_transaction[2]),
- hc32_to_cpu(fotg210, itd->hw_transaction[3]),
- hc32_to_cpu(fotg210, itd->hw_transaction[4]),
- hc32_to_cpu(fotg210, itd->hw_transaction[5]),
- hc32_to_cpu(fotg210, itd->hw_transaction[6]),
- hc32_to_cpu(fotg210, itd->hw_transaction[7]));
+ " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ hc32_to_cpu(fotg210, itd->hw_transaction[0]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[1]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[2]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[3]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[4]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[5]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[6]),
+ hc32_to_cpu(fotg210, itd->hw_transaction[7]));
+
fotg210_dbg(fotg210,
- " buf: %08x %08x %08x %08x %08x %08x %08x\n",
- hc32_to_cpu(fotg210, itd->hw_bufp[0]),
- hc32_to_cpu(fotg210, itd->hw_bufp[1]),
- hc32_to_cpu(fotg210, itd->hw_bufp[2]),
- hc32_to_cpu(fotg210, itd->hw_bufp[3]),
- hc32_to_cpu(fotg210, itd->hw_bufp[4]),
- hc32_to_cpu(fotg210, itd->hw_bufp[5]),
- hc32_to_cpu(fotg210, itd->hw_bufp[6]));
+ " buf: %08x %08x %08x %08x %08x %08x %08x\n",
+ hc32_to_cpu(fotg210, itd->hw_bufp[0]),
+ hc32_to_cpu(fotg210, itd->hw_bufp[1]),
+ hc32_to_cpu(fotg210, itd->hw_bufp[2]),
+ hc32_to_cpu(fotg210, itd->hw_bufp[3]),
+ hc32_to_cpu(fotg210, itd->hw_bufp[4]),
+ hc32_to_cpu(fotg210, itd->hw_bufp[5]),
+ hc32_to_cpu(fotg210, itd->hw_bufp[6]));
+
fotg210_dbg(fotg210, " index: %d %d %d %d %d %d %d %d\n",
- itd->index[0], itd->index[1], itd->index[2],
- itd->index[3], itd->index[4], itd->index[5],
- itd->index[6], itd->index[7]);
+ itd->index[0], itd->index[1], itd->index[2],
+ itd->index[3], itd->index[4], itd->index[5],
+ itd->index[6], itd->index[7]);
}
static int __maybe_unused
dbg_status_buf(char *buf, unsigned len, const char *label, u32 status)
{
- return scnprintf(buf, len,
- "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
- label, label[0] ? " " : "", status,
- (status & STS_ASS) ? " Async" : "",
- (status & STS_PSS) ? " Periodic" : "",
- (status & STS_RECL) ? " Recl" : "",
- (status & STS_HALT) ? " Halt" : "",
- (status & STS_IAA) ? " IAA" : "",
- (status & STS_FATAL) ? " FATAL" : "",
- (status & STS_FLR) ? " FLR" : "",
- (status & STS_PCD) ? " PCD" : "",
- (status & STS_ERR) ? " ERR" : "",
- (status & STS_INT) ? " INT" : ""
- );
+ return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
+ label, label[0] ? " " : "", status,
+ (status & STS_ASS) ? " Async" : "",
+ (status & STS_PSS) ? " Periodic" : "",
+ (status & STS_RECL) ? " Recl" : "",
+ (status & STS_HALT) ? " Halt" : "",
+ (status & STS_IAA) ? " IAA" : "",
+ (status & STS_FATAL) ? " FATAL" : "",
+ (status & STS_FLR) ? " FLR" : "",
+ (status & STS_PCD) ? " PCD" : "",
+ (status & STS_ERR) ? " ERR" : "",
+ (status & STS_INT) ? " INT" : "");
}
static int __maybe_unused
dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable)
{
- return scnprintf(buf, len,
- "%s%sintrenable %02x%s%s%s%s%s%s",
- label, label[0] ? " " : "", enable,
- (enable & STS_IAA) ? " IAA" : "",
- (enable & STS_FATAL) ? " FATAL" : "",
- (enable & STS_FLR) ? " FLR" : "",
- (enable & STS_PCD) ? " PCD" : "",
- (enable & STS_ERR) ? " ERR" : "",
- (enable & STS_INT) ? " INT" : ""
- );
+ return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s",
+ label, label[0] ? " " : "", enable,
+ (enable & STS_IAA) ? " IAA" : "",
+ (enable & STS_FATAL) ? " FATAL" : "",
+ (enable & STS_FLR) ? " FLR" : "",
+ (enable & STS_PCD) ? " PCD" : "",
+ (enable & STS_ERR) ? " ERR" : "",
+ (enable & STS_INT) ? " INT" : "");
}
static const char *const fls_strings[] = { "1024", "512", "256", "??" };
-static int
-dbg_command_buf(char *buf, unsigned len, const char *label, u32 command)
+static int dbg_command_buf(char *buf, unsigned len, const char *label,
+ u32 command)
{
return scnprintf(buf, len,
- "%s%scommand %07x %s=%d ithresh=%d%s%s%s "
- "period=%s%s %s",
- label, label[0] ? " " : "", command,
- (command & CMD_PARK) ? " park" : "(park)",
- CMD_PARK_CNT(command),
- (command >> 16) & 0x3f,
- (command & CMD_IAAD) ? " IAAD" : "",
- (command & CMD_ASE) ? " Async" : "",
- (command & CMD_PSE) ? " Periodic" : "",
- fls_strings[(command >> 2) & 0x3],
- (command & CMD_RESET) ? " Reset" : "",
- (command & CMD_RUN) ? "RUN" : "HALT"
- );
-}
-
-static char
-*dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status)
-{
- char *sig;
+ "%s%scommand %07x %s=%d ithresh=%d%s%s%s period=%s%s %s",
+ label, label[0] ? " " : "", command,
+ (command & CMD_PARK) ? " park" : "(park)",
+ CMD_PARK_CNT(command),
+ (command >> 16) & 0x3f,
+ (command & CMD_IAAD) ? " IAAD" : "",
+ (command & CMD_ASE) ? " Async" : "",
+ (command & CMD_PSE) ? " Periodic" : "",
+ fls_strings[(command >> 2) & 0x3],
+ (command & CMD_RESET) ? " Reset" : "",
+ (command & CMD_RUN) ? "RUN" : "HALT");
+}
+
+static char *dbg_port_buf(char *buf, unsigned len, const char *label, int port,
+ u32 status)
+{
+ char *sig;
/* signaling state */
switch (status & (3 << 10)) {
@@ -268,44 +254,41 @@ static char
break;
}
- scnprintf(buf, len,
- "%s%sport:%d status %06x %d "
- "sig=%s%s%s%s%s%s%s%s",
- label, label[0] ? " " : "", port, status,
- status>>25,/*device address */
- sig,
- (status & PORT_RESET) ? " RESET" : "",
- (status & PORT_SUSPEND) ? " SUSPEND" : "",
- (status & PORT_RESUME) ? " RESUME" : "",
- (status & PORT_PEC) ? " PEC" : "",
- (status & PORT_PE) ? " PE" : "",
- (status & PORT_CSC) ? " CSC" : "",
- (status & PORT_CONNECT) ? " CONNECT" : "");
+ scnprintf(buf, len, "%s%sport:%d status %06x %d sig=%s%s%s%s%s%s%s%s",
+ label, label[0] ? " " : "", port, status,
+ status >> 25, /*device address */
+ sig,
+ (status & PORT_RESET) ? " RESET" : "",
+ (status & PORT_SUSPEND) ? " SUSPEND" : "",
+ (status & PORT_RESUME) ? " RESUME" : "",
+ (status & PORT_PEC) ? " PEC" : "",
+ (status & PORT_PE) ? " PE" : "",
+ (status & PORT_CSC) ? " CSC" : "",
+ (status & PORT_CONNECT) ? " CONNECT" : "");
+
return buf;
}
/* functions have the "wrong" filename when they're output... */
-#define dbg_status(fotg210, label, status) { \
- char _buf[80]; \
- dbg_status_buf(_buf, sizeof(_buf), label, status); \
- fotg210_dbg(fotg210, "%s\n", _buf); \
+#define dbg_status(fotg210, label, status) { \
+ char _buf[80]; \
+ dbg_status_buf(_buf, sizeof(_buf), label, status); \
+ fotg210_dbg(fotg210, "%s\n", _buf); \
}
-#define dbg_cmd(fotg210, label, command) { \
- char _buf[80]; \
- dbg_command_buf(_buf, sizeof(_buf), label, command); \
- fotg210_dbg(fotg210, "%s\n", _buf); \
+#define dbg_cmd(fotg210, label, command) { \
+ char _buf[80]; \
+ dbg_command_buf(_buf, sizeof(_buf), label, command); \
+ fotg210_dbg(fotg210, "%s\n", _buf); \
}
-#define dbg_port(fotg210, label, port, status) { \
- char _buf[80]; \
- fotg210_dbg(fotg210, "%s\n", dbg_port_buf(_buf, sizeof(_buf), label, port, status) ); \
+#define dbg_port(fotg210, label, port, status) { \
+ char _buf[80]; \
+ fotg210_dbg(fotg210, "%s\n", \
+ dbg_port_buf(_buf, sizeof(_buf), label, port, status));\
}
-/*-------------------------------------------------------------------------*/
-
/* troubleshooting help: expose state in debugfs */
-
static int debug_async_open(struct inode *, struct file *);
static int debug_periodic_open(struct inode *, struct file *);
static int debug_registers_open(struct inode *, struct file *);
@@ -347,17 +330,22 @@ struct debug_buffer {
size_t alloc_size;
};
-#define speed_char(info1)({ char tmp; \
- switch (info1 & (3 << 12)) { \
- case QH_FULL_SPEED: \
- tmp = 'f'; break; \
- case QH_LOW_SPEED: \
- tmp = 'l'; break; \
- case QH_HIGH_SPEED: \
- tmp = 'h'; break; \
- default: \
- tmp = '?'; break; \
- } tmp; })
+static inline char speed_char(u32 scratch)
+{
+ switch (scratch & (3 << 12)) {
+ case QH_FULL_SPEED:
+ return 'f';
+
+ case QH_LOW_SPEED:
+ return 'l';
+
+ case QH_HIGH_SPEED:
+ return 'h';
+
+ default:
+ return '?';
+ }
+}
static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token)
{
@@ -373,33 +361,29 @@ static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token)
return '/';
}
-static void qh_lines(
- struct fotg210_hcd *fotg210,
- struct fotg210_qh *qh,
- char **nextp,
- unsigned *sizep
-)
-{
- u32 scratch;
- u32 hw_curr;
- struct fotg210_qtd *td;
- unsigned temp;
- unsigned size = *sizep;
- char *next = *nextp;
- char mark;
- __le32 list_end = FOTG210_LIST_END(fotg210);
- struct fotg210_qh_hw *hw = qh->hw;
-
- if (hw->hw_qtd_next == list_end) /* NEC does this */
+static void qh_lines(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
+ char **nextp, unsigned *sizep)
+{
+ u32 scratch;
+ u32 hw_curr;
+ struct fotg210_qtd *td;
+ unsigned temp;
+ unsigned size = *sizep;
+ char *next = *nextp;
+ char mark;
+ __le32 list_end = FOTG210_LIST_END(fotg210);
+ struct fotg210_qh_hw *hw = qh->hw;
+
+ if (hw->hw_qtd_next == list_end) /* NEC does this */
mark = '@';
else
mark = token_mark(fotg210, hw->hw_token);
- if (mark == '/') { /* qh_alt_next controls qh advance? */
- if ((hw->hw_alt_next & QTD_MASK(fotg210))
- == fotg210->async->hw->hw_alt_next)
- mark = '#'; /* blocked */
+ if (mark == '/') { /* qh_alt_next controls qh advance? */
+ if ((hw->hw_alt_next & QTD_MASK(fotg210)) ==
+ fotg210->async->hw->hw_alt_next)
+ mark = '#'; /* blocked */
else if (hw->hw_alt_next == list_end)
- mark = '.'; /* use hw_qtd_next */
+ mark = '.'; /* use hw_qtd_next */
/* else alt_next points to some other qtd */
}
scratch = hc32_to_cpup(fotg210, &hw->hw_info1);
@@ -462,6 +446,7 @@ static void qh_lines(
temp = snprintf(next, size, "\n");
if (size < temp)
temp = size;
+
size -= temp;
next += temp;
@@ -472,12 +457,12 @@ done:
static ssize_t fill_async_buffer(struct debug_buffer *buf)
{
- struct usb_hcd *hcd;
- struct fotg210_hcd *fotg210;
- unsigned long flags;
- unsigned temp, size;
- char *next;
- struct fotg210_qh *qh;
+ struct usb_hcd *hcd;
+ struct fotg210_hcd *fotg210;
+ unsigned long flags;
+ unsigned temp, size;
+ char *next;
+ struct fotg210_qh *qh;
hcd = bus_to_hcd(buf->bus);
fotg210 = hcd_to_fotg210(hcd);
@@ -492,7 +477,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
*/
spin_lock_irqsave(&fotg210->lock, flags);
for (qh = fotg210->async->qh_next.qh; size > 0 && qh;
- qh = qh->qh_next.qh)
+ qh = qh->qh_next.qh)
qh_lines(fotg210, qh, &next, &size);
if (fotg210->async_unlink && size > 0) {
temp = scnprintf(next, size, "\nunlink =\n");
@@ -508,21 +493,50 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
return strlen(buf->output_buf);
}
+/* count tds, get ep direction */
+static unsigned output_buf_tds_dir(char *buf, struct fotg210_hcd *fotg210,
+ struct fotg210_qh_hw *hw, struct fotg210_qh *qh, unsigned size)
+{
+ u32 scratch = hc32_to_cpup(fotg210, &hw->hw_info1);
+ struct fotg210_qtd *qtd;
+ char *type = "";
+ unsigned temp = 0;
+
+ /* count tds, get ep direction */
+ list_for_each_entry(qtd, &qh->qtd_list, qtd_list) {
+ temp++;
+ switch ((hc32_to_cpu(fotg210, qtd->hw_token) >> 8) & 0x03) {
+ case 0:
+ type = "out";
+ continue;
+ case 1:
+ type = "in";
+ continue;
+ }
+ }
+
+ return scnprintf(buf, size, "(%c%d ep%d%s [%d/%d] q%d p%d)",
+ speed_char(scratch), scratch & 0x007f,
+ (scratch >> 8) & 0x000f, type, qh->usecs,
+ qh->c_usecs, temp, (scratch >> 16) & 0x7ff);
+}
+
#define DBG_SCHED_LIMIT 64
static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
{
- struct usb_hcd *hcd;
- struct fotg210_hcd *fotg210;
- unsigned long flags;
- union fotg210_shadow p, *seen;
- unsigned temp, size, seen_count;
- char *next;
- unsigned i;
- __hc32 tag;
-
- seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC);
+ struct usb_hcd *hcd;
+ struct fotg210_hcd *fotg210;
+ unsigned long flags;
+ union fotg210_shadow p, *seen;
+ unsigned temp, size, seen_count;
+ char *next;
+ unsigned i;
+ __hc32 tag;
+
+ seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC);
if (!seen)
return 0;
+
seen_count = 0;
hcd = bus_to_hcd(buf->bus);
@@ -542,6 +556,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
p = fotg210->pshadow[i];
if (likely(!p.ptr))
continue;
+
tag = Q_NEXT_TYPE(fotg210, fotg210->periodic[i]);
temp = scnprintf(next, size, "%4d: ", i);
@@ -569,7 +584,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
continue;
if (p.qh->qh_next.ptr) {
temp = scnprintf(next, size,
- " ...");
+ " ...");
size -= temp;
next += temp;
}
@@ -577,38 +592,9 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
}
/* show more info the first time around */
if (temp == seen_count) {
- u32 scratch = hc32_to_cpup(fotg210,
- &hw->hw_info1);
- struct fotg210_qtd *qtd;
- char *type = "";
-
- /* count tds, get ep direction */
- temp = 0;
- list_for_each_entry(qtd,
- &p.qh->qtd_list,
- qtd_list) {
- temp++;
- switch (0x03 & (hc32_to_cpu(
- fotg210,
- qtd->hw_token) >> 8)) {
- case 0:
- type = "out";
- continue;
- case 1:
- type = "in";
- continue;
- }
- }
-
- temp = scnprintf(next, size,
- "(%c%d ep%d%s "
- "[%d/%d] q%d p%d)",
- speed_char(scratch),
- scratch & 0x007f,
- (scratch >> 8) & 0x000f, type,
- p.qh->usecs, p.qh->c_usecs,
- temp,
- 0x7ff & (scratch >> 16));
+ temp = output_buf_tds_dir(next,
+ fotg210, hw,
+ p.qh, size);
if (seen_count < DBG_SCHED_LIMIT)
seen[seen_count++].qh = p.qh;
@@ -619,14 +605,14 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
break;
case Q_TYPE_FSTN:
temp = scnprintf(next, size,
- " fstn-%8x/%p", p.fstn->hw_prev,
- p.fstn);
+ " fstn-%8x/%p",
+ p.fstn->hw_prev, p.fstn);
tag = Q_NEXT_TYPE(fotg210, p.fstn->hw_next);
p = p.fstn->fstn_next;
break;
case Q_TYPE_ITD:
temp = scnprintf(next, size,
- " itd/%p", p.itd);
+ " itd/%p", p.itd);
tag = Q_NEXT_TYPE(fotg210, p.itd->hw_next);
p = p.itd->itd_next;
break;
@@ -663,13 +649,13 @@ static const char *rh_state_string(struct fotg210_hcd *fotg210)
static ssize_t fill_registers_buffer(struct debug_buffer *buf)
{
- struct usb_hcd *hcd;
- struct fotg210_hcd *fotg210;
- unsigned long flags;
- unsigned temp, size, i;
- char *next, scratch[80];
- static const char fmt[] = "%*s\n";
- static const char label[] = "";
+ struct usb_hcd *hcd;
+ struct fotg210_hcd *fotg210;
+ unsigned long flags;
+ unsigned temp, size, i;
+ char *next, scratch[80];
+ static const char fmt[] = "%*s\n";
+ static const char label[] = "";
hcd = bus_to_hcd(buf->bus);
fotg210 = hcd_to_fotg210(hcd);
@@ -680,26 +666,26 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
if (!HCD_HW_ACCESSIBLE(hcd)) {
size = scnprintf(next, size,
- "bus %s, device %s\n"
- "%s\n"
- "SUSPENDED(no register access)\n",
- hcd->self.controller->bus->name,
- dev_name(hcd->self.controller),
- hcd->product_desc);
+ "bus %s, device %s\n"
+ "%s\n"
+ "SUSPENDED(no register access)\n",
+ hcd->self.controller->bus->name,
+ dev_name(hcd->self.controller),
+ hcd->product_desc);
goto done;
}
/* Capability Registers */
i = HC_VERSION(fotg210, fotg210_readl(fotg210,
- &fotg210->caps->hc_capbase));
+ &fotg210->caps->hc_capbase));
temp = scnprintf(next, size,
- "bus %s, device %s\n"
- "%s\n"
- "EHCI %x.%02x, rh state %s\n",
- hcd->self.controller->bus->name,
- dev_name(hcd->self.controller),
- hcd->product_desc,
- i >> 8, i & 0x0ff, rh_state_string(fotg210));
+ "bus %s, device %s\n"
+ "%s\n"
+ "EHCI %x.%02x, rh state %s\n",
+ hcd->self.controller->bus->name,
+ dev_name(hcd->self.controller),
+ hcd->product_desc,
+ i >> 8, i & 0x0ff, rh_state_string(fotg210));
size -= temp;
next += temp;
@@ -747,14 +733,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
#ifdef FOTG210_STATS
temp = scnprintf(next, size,
- "irq normal %ld err %ld iaa %ld(lost %ld)\n",
- fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa,
- fotg210->stats.lost_iaa);
+ "irq normal %ld err %ld iaa %ld(lost %ld)\n",
+ fotg210->stats.normal, fotg210->stats.error,
+ fotg210->stats.iaa, fotg210->stats.lost_iaa);
size -= temp;
next += temp;
temp = scnprintf(next, size, "complete %ld unlink %ld\n",
- fotg210->stats.complete, fotg210->stats.unlink);
+ fotg210->stats.complete, fotg210->stats.unlink);
size -= temp;
next += temp;
#endif
@@ -765,8 +751,8 @@ done:
return buf->alloc_size - size;
}
-static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
- ssize_t (*fill_func)(struct debug_buffer *))
+static struct debug_buffer
+*alloc_buffer(struct usb_bus *bus, ssize_t (*fill_func)(struct debug_buffer *))
{
struct debug_buffer *buf;
@@ -806,7 +792,7 @@ out:
}
static ssize_t debug_output(struct file *file, char __user *user_buf,
- size_t len, loff_t *offset)
+ size_t len, loff_t *offset)
{
struct debug_buffer *buf = file->private_data;
int ret = 0;
@@ -822,7 +808,7 @@ static ssize_t debug_output(struct file *file, char __user *user_buf,
mutex_unlock(&buf->mutex);
ret = simple_read_from_buffer(user_buf, len, offset,
- buf->output_buf, buf->count);
+ buf->output_buf, buf->count);
out:
return ret;
@@ -850,6 +836,7 @@ static int debug_async_open(struct inode *inode, struct file *file)
static int debug_periodic_open(struct inode *inode, struct file *file)
{
struct debug_buffer *buf;
+
buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
if (!buf)
return -ENOMEM;
@@ -862,7 +849,7 @@ static int debug_periodic_open(struct inode *inode, struct file *file)
static int debug_registers_open(struct inode *inode, struct file *file)
{
file->private_data = alloc_buffer(inode->i_private,
- fill_registers_buffer);
+ fill_registers_buffer);
return file->private_data ? 0 : -ENOMEM;
}
@@ -872,20 +859,20 @@ static inline void create_debug_files(struct fotg210_hcd *fotg210)
struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self;
fotg210->debug_dir = debugfs_create_dir(bus->bus_name,
- fotg210_debug_root);
+ fotg210_debug_root);
if (!fotg210->debug_dir)
return;
if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus,
- &debug_async_fops))
+ &debug_async_fops))
goto file_error;
if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus,
- &debug_periodic_fops))
+ &debug_periodic_fops))
goto file_error;
if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus,
- &debug_registers_fops))
+ &debug_registers_fops))
goto file_error;
return;
@@ -899,10 +886,7 @@ static inline void remove_debug_files(struct fotg210_hcd *fotg210)
debugfs_remove_recursive(fotg210->debug_dir);
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * handshake - spin reading hc until handshake completes or fails
+/* handshake - spin reading hc until handshake completes or fails
* @ptr: address of hc register to be read
* @mask: bits to look at in result of read
* @done: value of those bits when handshake succeeds
@@ -919,9 +903,9 @@ static inline void remove_debug_files(struct fotg210_hcd *fotg210)
* bridge shutdown: shutting down the bridge before the devices using it.
*/
static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr,
- u32 mask, u32 done, int usec)
+ u32 mask, u32 done, int usec)
{
- u32 result;
+ u32 result;
do {
result = fotg210_readl(fotg210, ptr);
@@ -936,13 +920,12 @@ static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr,
return -ETIMEDOUT;
}
-/*
- * Force HC to halt state from unknown (EHCI spec section 2.3).
+/* Force HC to halt state from unknown (EHCI spec section 2.3).
* Must be called with interrupts enabled and the lock not held.
*/
static int fotg210_halt(struct fotg210_hcd *fotg210)
{
- u32 temp;
+ u32 temp;
spin_lock_irq(&fotg210->lock);
@@ -962,20 +945,20 @@ static int fotg210_halt(struct fotg210_hcd *fotg210)
synchronize_irq(fotg210_to_hcd(fotg210)->irq);
return handshake(fotg210, &fotg210->regs->status,
- STS_HALT, STS_HALT, 16 * 125);
+ STS_HALT, STS_HALT, 16 * 125);
}
-/*
- * Reset a non-running (STS_HALT == 1) controller.
+/* Reset a non-running (STS_HALT == 1) controller.
* Must be called with interrupts enabled and the lock not held.
*/
static int fotg210_reset(struct fotg210_hcd *fotg210)
{
- int retval;
- u32 command = fotg210_readl(fotg210, &fotg210->regs->command);
+ int retval;
+ u32 command = fotg210_readl(fotg210, &fotg210->regs->command);
/* If the EHCI debug controller is active, special care must be
- * taken before and after a host controller reset */
+ * taken before and after a host controller reset
+ */
if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210)))
fotg210->debug = NULL;
@@ -985,7 +968,7 @@ static int fotg210_reset(struct fotg210_hcd *fotg210)
fotg210->rh_state = FOTG210_RH_HALTED;
fotg210->next_statechange = jiffies;
retval = handshake(fotg210, &fotg210->regs->command,
- CMD_RESET, 0, 250 * 1000);
+ CMD_RESET, 0, 250 * 1000);
if (retval)
return retval;
@@ -998,13 +981,12 @@ static int fotg210_reset(struct fotg210_hcd *fotg210)
return retval;
}
-/*
- * Idle the controller (turn off the schedules).
+/* Idle the controller (turn off the schedules).
* Must be called with interrupts enabled and the lock not held.
*/
static void fotg210_quiesce(struct fotg210_hcd *fotg210)
{
- u32 temp;
+ u32 temp;
if (fotg210->rh_state != FOTG210_RH_RUNNING)
return;
@@ -1012,7 +994,7 @@ static void fotg210_quiesce(struct fotg210_hcd *fotg210)
/* wait for any schedule enables/disables to take effect */
temp = (fotg210->command << 10) & (STS_ASS | STS_PSS);
handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp,
- 16 * 125);
+ 16 * 125);
/* then disable anything that's still active */
spin_lock_irq(&fotg210->lock);
@@ -1022,11 +1004,9 @@ static void fotg210_quiesce(struct fotg210_hcd *fotg210)
/* hardware can take 16 microframes to turn off ... */
handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0,
- 16 * 125);
+ 16 * 125);
}
-/*-------------------------------------------------------------------------*/
-
static void end_unlink_async(struct fotg210_hcd *fotg210);
static void unlink_empty_async(struct fotg210_hcd *fotg210);
static void fotg210_work(struct fotg210_hcd *fotg210);
@@ -1034,8 +1014,6 @@ static void start_unlink_intr(struct fotg210_hcd *fotg210,
struct fotg210_qh *qh);
static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
-/*-------------------------------------------------------------------------*/
-
/* Set a bit in the USBCMD register */
static void fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit)
{
@@ -1056,10 +1034,7 @@ static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit)
fotg210_readl(fotg210, &fotg210->regs->command);
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI timer support... Now using hrtimers.
+/* EHCI timer support... Now using hrtimers.
*
* Lots of different events are triggered from fotg210->hrtimer. Whenever
* the timer routine runs, it checks each possible event; events that are
@@ -1081,8 +1056,7 @@ static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit)
* allow for an expiration range of 1 ms.
*/
-/*
- * Delay lengths for the hrtimer event types.
+/* Delay lengths for the hrtimer event types.
* Keep this list sorted by delay length, in the same order as
* the event types indexed by enum fotg210_hrtimer_event in fotg210.h.
*/
@@ -1103,7 +1077,7 @@ static unsigned event_delays_ns[] = {
static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event,
bool resched)
{
- ktime_t *timeout = &fotg210->hr_timeouts[event];
+ ktime_t *timeout = &fotg210->hr_timeouts[event];
if (resched)
*timeout = ktime_add(ktime_get(),
@@ -1122,7 +1096,7 @@ static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event,
/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */
static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
{
- unsigned actual, want;
+ unsigned actual, want;
/* Don't enable anything if the controller isn't running (e.g., died) */
if (fotg210->rh_state != FOTG210_RH_RUNNING)
@@ -1136,7 +1110,7 @@ static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
/* Poll again later, but give up after about 20 ms */
if (fotg210->ASS_poll_count++ < 20) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS,
- true);
+ true);
return;
}
fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n",
@@ -1154,8 +1128,8 @@ static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
/* Turn off the schedule after a while */
fotg210_enable_event(fotg210,
- FOTG210_HRTIMER_DISABLE_ASYNC,
- true);
+ FOTG210_HRTIMER_DISABLE_ASYNC,
+ true);
}
}
}
@@ -1170,7 +1144,7 @@ static void fotg210_disable_ASE(struct fotg210_hcd *fotg210)
/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
{
- unsigned actual, want;
+ unsigned actual, want;
/* Don't do anything if the controller isn't running (e.g., died) */
if (fotg210->rh_state != FOTG210_RH_RUNNING)
@@ -1184,7 +1158,7 @@ static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
/* Poll again later, but give up after about 20 ms */
if (fotg210->PSS_poll_count++ < 20) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS,
- true);
+ true);
return;
}
fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
@@ -1202,8 +1176,8 @@ static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
/* Turn off the schedule after a while */
fotg210_enable_event(fotg210,
- FOTG210_HRTIMER_DISABLE_PERIODIC,
- true);
+ FOTG210_HRTIMER_DISABLE_PERIODIC,
+ true);
}
}
}
@@ -1224,7 +1198,7 @@ static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210)
if (fotg210->died_poll_count++ < 5) {
/* Try again later */
fotg210_enable_event(fotg210,
- FOTG210_HRTIMER_POLL_DEAD, true);
+ FOTG210_HRTIMER_POLL_DEAD, true);
return;
}
fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n");
@@ -1243,7 +1217,7 @@ static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210)
/* Handle unlinked interrupt QHs once they are gone from the hardware */
static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
{
- bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
+ bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
/*
* Process all the QHs on the intr_unlink list that were added
@@ -1254,7 +1228,7 @@ static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
*/
fotg210->intr_unlinking = true;
while (fotg210->intr_unlink) {
- struct fotg210_qh *qh = fotg210->intr_unlink;
+ struct fotg210_qh *qh = fotg210->intr_unlink;
if (!stopped && qh->unlink_cycle == fotg210->intr_unlink_cycle)
break;
@@ -1266,7 +1240,7 @@ static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
/* Handle remaining entries later */
if (fotg210->intr_unlink) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR,
- true);
+ true);
++fotg210->intr_unlink_cycle;
}
fotg210->intr_unlinking = false;
@@ -1288,7 +1262,7 @@ static void start_free_itds(struct fotg210_hcd *fotg210)
/* Wait for controller to stop using old iTDs and siTDs */
static void end_free_itds(struct fotg210_hcd *fotg210)
{
- struct fotg210_itd *itd, *n;
+ struct fotg210_itd *itd, *n;
if (fotg210->rh_state < FOTG210_RH_RUNNING)
fotg210->last_itd_to_free = NULL;
@@ -1339,7 +1313,7 @@ static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210)
if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
COUNT(fotg210->stats.lost_iaa);
fotg210_writel(fotg210, STS_IAA,
- &fotg210->regs->status);
+ &fotg210->regs->status);
}
fotg210_dbg(fotg210, "IAA watchdog: status %x cmd %x\n",
@@ -1355,7 +1329,7 @@ static void turn_on_io_watchdog(struct fotg210_hcd *fotg210)
/* Not needed if the controller isn't running or it's already enabled */
if (fotg210->rh_state != FOTG210_RH_RUNNING ||
(fotg210->enabled_hrtimer_events &
- BIT(FOTG210_HRTIMER_IO_WATCHDOG)))
+ BIT(FOTG210_HRTIMER_IO_WATCHDOG)))
return;
/*
@@ -1365,12 +1339,11 @@ static void turn_on_io_watchdog(struct fotg210_hcd *fotg210)
if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog &&
fotg210->async_count + fotg210->intr_count > 0))
fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG,
- true);
+ true);
}
-/*
- * Handler functions for the hrtimer event types.
+/* Handler functions for the hrtimer event types.
* Keep this array in the same order as the event types indexed by
* enum fotg210_hrtimer_event in fotg210.h.
*/
@@ -1391,10 +1364,10 @@ static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t)
{
struct fotg210_hcd *fotg210 =
container_of(t, struct fotg210_hcd, hrtimer);
- ktime_t now;
- unsigned long events;
- unsigned long flags;
- unsigned e;
+ ktime_t now;
+ unsigned long events;
+ unsigned long flags;
+ unsigned e;
spin_lock_irqsave(&fotg210->lock, flags);
@@ -1418,50 +1391,37 @@ static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t)
return HRTIMER_NORESTART;
}
-/*-------------------------------------------------------------------------*/
-
-#define fotg210_bus_suspend NULL
-#define fotg210_bus_resume NULL
+#define fotg210_bus_suspend NULL
+#define fotg210_bus_resume NULL
-/*-------------------------------------------------------------------------*/
-
-static int check_reset_complete(
- struct fotg210_hcd *fotg210,
- int index,
- u32 __iomem *status_reg,
- int port_status
-) {
+static int check_reset_complete(struct fotg210_hcd *fotg210, int index,
+ u32 __iomem *status_reg, int port_status)
+{
if (!(port_status & PORT_CONNECT))
return port_status;
/* if reset finished and it's still not enabled -- handoff */
- if (!(port_status & PORT_PE)) {
+ if (!(port_status & PORT_PE))
/* with integrated TT, there's nobody to hand it to! */
- fotg210_dbg(fotg210,
- "Failed to enable port %d on root hub TT\n",
- index+1);
- return port_status;
- } else {
+ fotg210_dbg(fotg210, "Failed to enable port %d on root hub TT\n",
+ index + 1);
+ else
fotg210_dbg(fotg210, "port %d reset complete, port enabled\n",
- index + 1);
- }
+ index + 1);
return port_status;
}
-/*-------------------------------------------------------------------------*/
-
/* build "status change" packet (one or two bytes) from HC registers */
-static int
-fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
+static int fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- u32 temp, status;
- u32 mask;
- int retval = 1;
- unsigned long flags;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ u32 temp, status;
+ u32 mask;
+ int retval = 1;
+ unsigned long flags;
/* init status to no-changes */
buf[0] = 0;
@@ -1488,9 +1448,9 @@ fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
* controller by the user.
*/
- if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend)
- || (fotg210->reset_done[0] && time_after_eq(
- jiffies, fotg210->reset_done[0]))) {
+ if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend) ||
+ (fotg210->reset_done[0] &&
+ time_after_eq(jiffies, fotg210->reset_done[0]))) {
buf[0] |= 1 << 1;
status = STS_PCD;
}
@@ -1499,15 +1459,11 @@ fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
return status ? retval : 0;
}
-/*-------------------------------------------------------------------------*/
-
-static void
-fotg210_hub_descriptor(
- struct fotg210_hcd *fotg210,
- struct usb_hub_descriptor *desc
-) {
- int ports = HCS_N_PORTS(fotg210->hcs_params);
- u16 temp;
+static void fotg210_hub_descriptor(struct fotg210_hcd *fotg210,
+ struct usb_hub_descriptor *desc)
+{
+ int ports = HCS_N_PORTS(fotg210->hcs_params);
+ u16 temp;
desc->bDescriptorType = USB_DT_HUB;
desc->bPwrOn2PwrGood = 10; /* fotg210 1.0, 2.3.9 says 20ms max */
@@ -1526,23 +1482,16 @@ fotg210_hub_descriptor(
desc->wHubCharacteristics = cpu_to_le16(temp);
}
-/*-------------------------------------------------------------------------*/
-
-static int fotg210_hub_control(
- struct usb_hcd *hcd,
- u16 typeReq,
- u16 wValue,
- u16 wIndex,
- char *buf,
- u16 wLength
-) {
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- int ports = HCS_N_PORTS(fotg210->hcs_params);
- u32 __iomem *status_reg = &fotg210->regs->port_status;
- u32 temp, temp1, status;
- unsigned long flags;
- int retval = 0;
- unsigned selector;
+static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength)
+{
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ int ports = HCS_N_PORTS(fotg210->hcs_params);
+ u32 __iomem *status_reg = &fotg210->regs->port_status;
+ u32 temp, temp1, status;
+ unsigned long flags;
+ int retval = 0;
+ unsigned selector;
/*
* FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -1605,7 +1554,7 @@ static int fotg210_hub_control(
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
fotg210_writel(fotg210, temp | OTGISR_OVC,
- &fotg210->regs->otgisr);
+ &fotg210->regs->otgisr);
break;
case USB_PORT_FEAT_C_RESET:
/* GetPortStatus clears reset */
@@ -1617,7 +1566,7 @@ static int fotg210_hub_control(
break;
case GetHubDescriptor:
fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *)
- buf);
+ buf);
break;
case GetHubStatus:
/* no hub-wide feature/status flags */
@@ -1663,16 +1612,16 @@ static int fotg210_hub_control(
/* stop resume signaling */
temp = fotg210_readl(fotg210, status_reg);
- fotg210_writel(fotg210,
- temp & ~(PORT_RWC_BITS | PORT_RESUME),
- status_reg);
+ fotg210_writel(fotg210, temp &
+ ~(PORT_RWC_BITS | PORT_RESUME),
+ status_reg);
clear_bit(wIndex, &fotg210->resuming_ports);
retval = handshake(fotg210, status_reg,
- PORT_RESUME, 0, 2000 /* 2msec */);
+ PORT_RESUME, 0, 2000);/* 2ms */
if (retval != 0) {
fotg210_err(fotg210,
- "port %d resume error %d\n",
- wIndex + 1, retval);
+ "port %d resume error %d\n",
+ wIndex + 1, retval);
goto error;
}
temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
@@ -1680,17 +1629,16 @@ static int fotg210_hub_control(
}
/* whoever resets must GetPortStatus to complete it!! */
- if ((temp & PORT_RESET)
- && time_after_eq(jiffies,
- fotg210->reset_done[wIndex])) {
+ if ((temp & PORT_RESET) && time_after_eq(jiffies,
+ fotg210->reset_done[wIndex])) {
status |= USB_PORT_STAT_C_RESET << 16;
fotg210->reset_done[wIndex] = 0;
clear_bit(wIndex, &fotg210->resuming_ports);
/* force reset to complete */
fotg210_writel(fotg210,
- temp & ~(PORT_RWC_BITS | PORT_RESET),
- status_reg);
+ temp & ~(PORT_RWC_BITS | PORT_RESET),
+ status_reg);
/* REVISIT: some hardware needs 550+ usec to clear
* this bit; seems too long to spin routinely...
*/
@@ -1698,7 +1646,7 @@ static int fotg210_hub_control(
PORT_RESET, 0, 1000);
if (retval != 0) {
fotg210_err(fotg210, "port %d reset error %d\n",
- wIndex + 1, retval);
+ wIndex + 1, retval);
goto error;
}
@@ -1718,7 +1666,7 @@ static int fotg210_hub_control(
temp &= ~PORT_RWC_BITS;
fotg210_writel(fotg210, temp, status_reg);
fotg210_dbg(fotg210, "port %d --> companion\n",
- wIndex + 1);
+ wIndex + 1);
temp = fotg210_readl(fotg210, status_reg);
}
@@ -1788,7 +1736,7 @@ static int fotg210_hub_control(
* mode if we have hostpc feature
*/
fotg210_writel(fotg210, temp | PORT_SUSPEND,
- status_reg);
+ status_reg);
set_bit(wIndex, &fotg210->suspended_ports);
break;
case USB_PORT_FEAT_RESET:
@@ -1866,9 +1814,8 @@ static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd,
{
return 0;
}
-/*-------------------------------------------------------------------------*/
-/*
- * There's basically three types of memory:
+
+/* There's basically three types of memory:
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use dma_pool or dma_alloc_coherent
@@ -1878,12 +1825,9 @@ static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd,
* No memory seen by this driver is pageable.
*/
-/*-------------------------------------------------------------------------*/
-
/* Allocate the key transfer structures from the previously allocated pool */
-
static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210,
- struct fotg210_qtd *qtd, dma_addr_t dma)
+ struct fotg210_qtd *qtd, dma_addr_t dma)
{
memset(qtd, 0, sizeof(*qtd));
qtd->qtd_dma = dma;
@@ -1894,10 +1838,10 @@ static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210,
}
static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210,
- gfp_t flags)
+ gfp_t flags)
{
- struct fotg210_qtd *qtd;
- dma_addr_t dma;
+ struct fotg210_qtd *qtd;
+ dma_addr_t dma;
qtd = dma_pool_alloc(fotg210->qtd_pool, flags, &dma);
if (qtd != NULL)
@@ -1907,7 +1851,7 @@ static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210,
}
static inline void fotg210_qtd_free(struct fotg210_hcd *fotg210,
- struct fotg210_qtd *qtd)
+ struct fotg210_qtd *qtd)
{
dma_pool_free(fotg210->qtd_pool, qtd, qtd->qtd_dma);
}
@@ -1927,10 +1871,10 @@ static void qh_destroy(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
}
static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210,
- gfp_t flags)
+ gfp_t flags)
{
- struct fotg210_qh *qh;
- dma_addr_t dma;
+ struct fotg210_qh *qh;
+ dma_addr_t dma;
qh = kzalloc(sizeof(*qh), GFP_ATOMIC);
if (!qh)
@@ -1958,8 +1902,6 @@ fail:
return NULL;
}
-/*-------------------------------------------------------------------------*/
-
/* The queue heads and transfer descriptors are managed from pools tied
* to each of the "per device" structures.
* This is the initialisation and cleanup code.
@@ -1976,23 +1918,19 @@ static void fotg210_mem_cleanup(struct fotg210_hcd *fotg210)
fotg210->dummy = NULL;
/* DMA consistent memory and pools */
- if (fotg210->qtd_pool)
- dma_pool_destroy(fotg210->qtd_pool);
+ dma_pool_destroy(fotg210->qtd_pool);
fotg210->qtd_pool = NULL;
- if (fotg210->qh_pool) {
- dma_pool_destroy(fotg210->qh_pool);
- fotg210->qh_pool = NULL;
- }
+ dma_pool_destroy(fotg210->qh_pool);
+ fotg210->qh_pool = NULL;
- if (fotg210->itd_pool)
- dma_pool_destroy(fotg210->itd_pool);
+ dma_pool_destroy(fotg210->itd_pool);
fotg210->itd_pool = NULL;
if (fotg210->periodic)
dma_free_coherent(fotg210_to_hcd(fotg210)->self.controller,
- fotg210->periodic_size * sizeof(u32),
- fotg210->periodic, fotg210->periodic_dma);
+ fotg210->periodic_size * sizeof(u32),
+ fotg210->periodic, fotg210->periodic_dma);
fotg210->periodic = NULL;
/* shadow periodic table */
@@ -2039,8 +1977,8 @@ static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags)
/* Hardware periodic table */
fotg210->periodic = (__le32 *)
dma_alloc_coherent(fotg210_to_hcd(fotg210)->self.controller,
- fotg210->periodic_size * sizeof(__le32),
- &fotg210->periodic_dma, 0);
+ fotg210->periodic_size * sizeof(__le32),
+ &fotg210->periodic_dma, 0);
if (fotg210->periodic == NULL)
goto fail;
@@ -2049,7 +1987,7 @@ static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags)
/* software shadow of hardware table */
fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *),
- flags);
+ flags);
if (fotg210->pshadow != NULL)
return 0;
@@ -2058,9 +1996,7 @@ fail:
fotg210_mem_cleanup(fotg210);
return -ENOMEM;
}
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI hardware queue manipulation ... the core. QH/QTD manipulation.
+/* EHCI hardware queue manipulation ... the core. QH/QTD manipulation.
*
* Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd"
* entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
@@ -2077,16 +2013,12 @@ fail:
* buffer low/full speed data so the host collects it at high speed.
*/
-/*-------------------------------------------------------------------------*/
-
/* fill a qtd, returning how much of the buffer we were able to queue up */
-
-static int
-qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf,
- size_t len, int token, int maxpacket)
+static int qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd,
+ dma_addr_t buf, size_t len, int token, int maxpacket)
{
- int i, count;
- u64 addr = buf;
+ int i, count;
+ u64 addr = buf;
/* one buffer entry per 4K ... first might be short or unaligned */
qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr);
@@ -2121,11 +2053,8 @@ qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf,
return count;
}
-/*-------------------------------------------------------------------------*/
-
-static inline void
-qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
- struct fotg210_qtd *qtd)
+static inline void qh_update(struct fotg210_hcd *fotg210,
+ struct fotg210_qh *qh, struct fotg210_qtd *qtd)
{
struct fotg210_qh_hw *hw = qh->hw;
@@ -2141,7 +2070,7 @@ qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
* ever clear it.
*/
if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) {
- unsigned is_out, epnum;
+ unsigned is_out, epnum;
is_out = qh->is_out;
epnum = (hc32_to_cpup(fotg210, &hw->hw_info1) >> 8) & 0x0f;
@@ -2158,8 +2087,7 @@ qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
* overlay, so qh->hw_token wrongly becomes inactive/halted), only fault
* recovery (including urb dequeue) would need software changes to a QH...
*/
-static void
-qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+static void qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{
struct fotg210_qtd *qtd;
@@ -2185,16 +2113,14 @@ qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
qh_update(fotg210, qh, qtd);
}
-/*-------------------------------------------------------------------------*/
-
static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- struct fotg210_qh *qh = ep->hcpriv;
- unsigned long flags;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct fotg210_qh *qh = ep->hcpriv;
+ unsigned long flags;
spin_lock_irqsave(&fotg210->lock, flags);
qh->clearing_tt = 0;
@@ -2205,8 +2131,7 @@ static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd,
}
static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210,
- struct fotg210_qh *qh,
- struct urb *urb, u32 token)
+ struct fotg210_qh *qh, struct urb *urb, u32 token)
{
/* If an async split transaction gets an error or is unlinked,
@@ -2217,27 +2142,24 @@ static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210,
*/
if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
struct usb_device *tt = urb->dev->tt->hub;
+
dev_dbg(&tt->dev,
- "clear tt buffer port %d, a%d ep%d t%08x\n",
- urb->dev->ttport, urb->dev->devnum,
- usb_pipeendpoint(urb->pipe), token);
+ "clear tt buffer port %d, a%d ep%d t%08x\n",
+ urb->dev->ttport, urb->dev->devnum,
+ usb_pipeendpoint(urb->pipe), token);
if (urb->dev->tt->hub !=
- fotg210_to_hcd(fotg210)->self.root_hub) {
+ fotg210_to_hcd(fotg210)->self.root_hub) {
if (usb_hub_clear_tt_buffer(urb) == 0)
qh->clearing_tt = 1;
}
}
}
-static int qtd_copy_status(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- size_t length,
- u32 token
-)
+static int qtd_copy_status(struct fotg210_hcd *fotg210, struct urb *urb,
+ size_t length, u32 token)
{
- int status = -EINPROGRESS;
+ int status = -EINPROGRESS;
/* count IN/OUT bytes, not SETUP (even short packets) */
if (likely(QTD_PID(token) != 2))
@@ -2274,32 +2196,32 @@ static int qtd_copy_status(
} else if (token & QTD_STS_XACT) {
/* timeout, bad CRC, wrong PID, etc */
fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n",
- urb->dev->devpath,
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out");
+ urb->dev->devpath,
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out");
status = -EPROTO;
} else { /* unknown */
status = -EPROTO;
}
fotg210_dbg(fotg210,
- "dev%d ep%d%s qtd token %08x --> status %d\n",
- usb_pipedevice(urb->pipe),
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out",
- token, status);
+ "dev%d ep%d%s qtd token %08x --> status %d\n",
+ usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ token, status);
}
return status;
}
-static void
-fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb, int status)
+static void fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb,
+ int status)
__releases(fotg210->lock)
__acquires(fotg210->lock)
{
if (likely(urb->hcpriv != NULL)) {
- struct fotg210_qh *qh = (struct fotg210_qh *) urb->hcpriv;
+ struct fotg210_qh *qh = (struct fotg210_qh *) urb->hcpriv;
/* S-mask in a QH means it's an interrupt urb */
if ((qh->hw->hw_info2 & cpu_to_hc32(fotg210, QH_SMASK)) != 0) {
@@ -2320,12 +2242,12 @@ __acquires(fotg210->lock)
#ifdef FOTG210_URB_TRACE
fotg210_dbg(fotg210,
- "%s %s urb %p ep%d%s status %d len %d/%d\n",
- __func__, urb->dev->devpath, urb,
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out",
- status,
- urb->actual_length, urb->transfer_buffer_length);
+ "%s %s urb %p ep%d%s status %d len %d/%d\n",
+ __func__, urb->dev->devpath, urb,
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ status,
+ urb->actual_length, urb->transfer_buffer_length);
#endif
/* complete() can reenter this HCD */
@@ -2337,21 +2259,20 @@ __acquires(fotg210->lock)
static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
-/*
- * Process and free completed qtds for a qh, returning URBs to drivers.
+/* Process and free completed qtds for a qh, returning URBs to drivers.
* Chases up to qh->hw_current. Returns number of completions called,
* indicating how much "real" work we did.
*/
-static unsigned
-qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+static unsigned qh_completions(struct fotg210_hcd *fotg210,
+ struct fotg210_qh *qh)
{
- struct fotg210_qtd *last, *end = qh->dummy;
- struct list_head *entry, *tmp;
- int last_status;
- int stopped;
- unsigned count = 0;
- u8 state;
- struct fotg210_qh_hw *hw = qh->hw;
+ struct fotg210_qtd *last, *end = qh->dummy;
+ struct list_head *entry, *tmp;
+ int last_status;
+ int stopped;
+ unsigned count = 0;
+ u8 state;
+ struct fotg210_qh_hw *hw = qh->hw;
if (unlikely(list_empty(&qh->qtd_list)))
return count;
@@ -2370,7 +2291,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
qh->qh_state = QH_STATE_COMPLETING;
stopped = (state == QH_STATE_IDLE);
- rescan:
+rescan:
last = NULL;
last_status = -EINPROGRESS;
qh->needs_rescan = 0;
@@ -2381,9 +2302,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
* if queue is stopped, handles unlinks.
*/
list_for_each_safe(entry, tmp, &qh->qtd_list) {
- struct fotg210_qtd *qtd;
- struct urb *urb;
- u32 token = 0;
+ struct fotg210_qtd *qtd;
+ struct urb *urb;
+ u32 token = 0;
qtd = list_entry(entry, struct fotg210_qtd, qtd_list);
urb = qtd->urb;
@@ -2392,7 +2313,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
if (last) {
if (likely(last->urb != urb)) {
fotg210_urb_done(fotg210, last->urb,
- last_status);
+ last_status);
count++;
last_status = -EINPROGRESS;
}
@@ -2409,20 +2330,17 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
token = hc32_to_cpu(fotg210, qtd->hw_token);
/* always clean up qtds the hc de-activated */
- retry_xacterr:
+retry_xacterr:
if ((token & QTD_STS_ACTIVE) == 0) {
/* Report Data Buffer Error: non-fatal but useful */
if (token & QTD_STS_DBE)
fotg210_dbg(fotg210,
"detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
- urb,
- usb_endpoint_num(&urb->ep->desc),
+ urb, usb_endpoint_num(&urb->ep->desc),
usb_endpoint_dir_in(&urb->ep->desc)
? "in" : "out",
- urb->transfer_buffer_length,
- qtd,
- qh);
+ urb->transfer_buffer_length, qtd, qh);
/* on STALL, error, and short reads this urb must
* complete and all its qtds must be recycled.
@@ -2433,12 +2351,14 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
* reach the software xacterr limit
*/
if ((token & QTD_STS_XACT) &&
- QTD_CERR(token) == 0 &&
- ++qh->xacterrs < QH_XACTERR_MAX &&
- !urb->unlinked) {
+ QTD_CERR(token) == 0 &&
+ ++qh->xacterrs < QH_XACTERR_MAX &&
+ !urb->unlinked) {
fotg210_dbg(fotg210,
- "detected XactErr len %zu/%zu retry %d\n",
- qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
+ "detected XactErr len %zu/%zu retry %d\n",
+ qtd->length - QTD_LENGTH(token),
+ qtd->length,
+ qh->xacterrs);
/* reset the token in the qtd and the
* qh overlay (which still contains
@@ -2466,9 +2386,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
* URB_SHORT_NOT_OK was set so the driver submitting
* the urbs could clean it up.
*/
- } else if (IS_SHORT_READ(token)
- && !(qtd->hw_alt_next
- & FOTG210_LIST_END(fotg210))) {
+ } else if (IS_SHORT_READ(token) &&
+ !(qtd->hw_alt_next &
+ FOTG210_LIST_END(fotg210))) {
stopped = 1;
}
@@ -2492,9 +2412,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
continue;
/* qh unlinked; token in overlay may be most current */
- if (state == QH_STATE_IDLE
- && cpu_to_hc32(fotg210, qtd->qtd_dma)
- == hw->hw_current) {
+ if (state == QH_STATE_IDLE &&
+ cpu_to_hc32(fotg210, qtd->qtd_dma)
+ == hw->hw_current) {
token = hc32_to_cpu(fotg210, hw->hw_token);
/* An unlink may leave an incomplete
@@ -2502,7 +2422,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
* We have to clear it.
*/
fotg210_clear_tt_buffer(fotg210, qh, urb,
- token);
+ token);
}
}
@@ -2516,9 +2436,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
if (last_status == -EINPROGRESS) {
last_status = qtd_copy_status(fotg210, urb,
qtd->length, token);
- if (last_status == -EREMOTEIO
- && (qtd->hw_alt_next
- & FOTG210_LIST_END(fotg210)))
+ if (last_status == -EREMOTEIO &&
+ (qtd->hw_alt_next &
+ FOTG210_LIST_END(fotg210)))
last_status = -EINPROGRESS;
/* As part of low/full-speed endpoint-halt processing
@@ -2537,7 +2457,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
*/
if (last_status != -EPIPE)
fotg210_clear_tt_buffer(fotg210, qh,
- urb, token);
+ urb, token);
}
}
@@ -2615,26 +2535,21 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
return count;
}
-/*-------------------------------------------------------------------------*/
-
/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
/* ... and packet size, for any kind of endpoint descriptor */
#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
-/*
- * reverse of qh_urb_transaction: free a list of TDs.
+/* reverse of qh_urb_transaction: free a list of TDs.
* used for cleanup after errors, before HC sees an URB's TDs.
*/
-static void qtd_list_free(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- struct list_head *qtd_list
-) {
- struct list_head *entry, *temp;
+static void qtd_list_free(struct fotg210_hcd *fotg210, struct urb *urb,
+ struct list_head *qtd_list)
+{
+ struct list_head *entry, *temp;
list_for_each_safe(entry, temp, qtd_list) {
- struct fotg210_qtd *qtd;
+ struct fotg210_qtd *qtd;
qtd = list_entry(entry, struct fotg210_qtd, qtd_list);
list_del(&qtd->qtd_list);
@@ -2642,23 +2557,18 @@ static void qtd_list_free(
}
}
-/*
- * create a list of filled qtds for this URB; won't link into qh.
+/* create a list of filled qtds for this URB; won't link into qh.
*/
-static struct list_head *
-qh_urb_transaction(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- struct list_head *head,
- gfp_t flags
-) {
- struct fotg210_qtd *qtd, *qtd_prev;
- dma_addr_t buf;
- int len, this_sg_len, maxpacket;
- int is_input;
- u32 token;
- int i;
- struct scatterlist *sg;
+static struct list_head *qh_urb_transaction(struct fotg210_hcd *fotg210,
+ struct urb *urb, struct list_head *head, gfp_t flags)
+{
+ struct fotg210_qtd *qtd, *qtd_prev;
+ dma_addr_t buf;
+ int len, this_sg_len, maxpacket;
+ int is_input;
+ u32 token;
+ int i;
+ struct scatterlist *sg;
/*
* URBs map to sequences of QTDs: one logical transaction
@@ -2768,8 +2678,8 @@ qh_urb_transaction(
* have the alt_next mechanism keep the queue running after the
* last data qtd (the only one, for control and most other cases).
*/
- if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
- || usb_pipecontrol(urb->pipe)))
+ if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 ||
+ usb_pipecontrol(urb->pipe)))
qtd->hw_alt_next = FOTG210_LIST_END(fotg210);
/*
@@ -2778,7 +2688,7 @@ qh_urb_transaction(
* (zero length).
*/
if (likely(urb->transfer_buffer_length != 0)) {
- int one_more = 0;
+ int one_more = 0;
if (usb_pipecontrol(urb->pipe)) {
one_more = 1;
@@ -2813,9 +2723,7 @@ cleanup:
return NULL;
}
-/*-------------------------------------------------------------------------*/
-/*
- * Would be best to create all qh's from config descriptors,
+/* Would be best to create all qh's from config descriptors,
* when each interface/altsetting is established. Unlink
* any previous qh and cancel its urbs first; endpoints are
* implicitly reset then (data toggle too).
@@ -2823,26 +2731,22 @@ cleanup:
*/
-/*
- * Each QH holds a qtd list; a QH is used for everything except iso.
+/* Each QH holds a qtd list; a QH is used for everything except iso.
*
* For interrupt urbs, the scheduler must set the microframe scheduling
* mask(s) each time the QH gets scheduled. For highspeed, that's
* just one microframe in the s-mask. For split interrupt transactions
* there are additional complications: c-mask, maybe FSTNs.
*/
-static struct fotg210_qh *
-qh_make(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- gfp_t flags
-) {
- struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags);
- u32 info1 = 0, info2 = 0;
- int is_input, type;
- int maxp = 0;
- struct usb_tt *tt = urb->dev->tt;
- struct fotg210_qh_hw *hw;
+static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
+ gfp_t flags)
+{
+ struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags);
+ u32 info1 = 0, info2 = 0;
+ int is_input, type;
+ int maxp = 0;
+ struct usb_tt *tt = urb->dev->tt;
+ struct fotg210_qh_hw *hw;
if (!qh)
return qh;
@@ -2862,7 +2766,7 @@ qh_make(
*/
if (max_packet(maxp) > 1024) {
fotg210_dbg(fotg210, "bogus qh maxpacket %d\n",
- max_packet(maxp));
+ max_packet(maxp));
goto done;
}
@@ -2896,7 +2800,7 @@ qh_make(
urb->interval = qh->period << 3;
}
} else {
- int think_time;
+ int think_time;
/* gap is f(FS/LS transfer times) */
qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed,
@@ -2986,7 +2890,7 @@ qh_make(
break;
default:
fotg210_dbg(fotg210, "bogus dev %p speed %d\n", urb->dev,
- urb->dev->speed);
+ urb->dev->speed);
done:
qh_destroy(fotg210, qh);
return NULL;
@@ -3005,8 +2909,6 @@ done:
return qh;
}
-/*-------------------------------------------------------------------------*/
-
static void enable_async(struct fotg210_hcd *fotg210)
{
if (fotg210->async_count++)
@@ -3036,8 +2938,8 @@ static void disable_async(struct fotg210_hcd *fotg210)
static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{
- __hc32 dma = QH_NEXT(fotg210, qh->qh_dma);
- struct fotg210_qh *head;
+ __hc32 dma = QH_NEXT(fotg210, qh->qh_dma);
+ struct fotg210_qh *head;
/* Don't link a QH if there's a Clear-TT-Buffer pending */
if (unlikely(qh->clearing_tt))
@@ -3064,24 +2966,17 @@ static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
enable_async(fotg210);
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * For control/bulk/interrupt, return QH with these TDs appended.
+/* For control/bulk/interrupt, return QH with these TDs appended.
* Allocates and initializes the QH if necessary.
* Returns null if it can't allocate a QH it needs to.
* If the QH has TDs (urbs) already, that's great.
*/
-static struct fotg210_qh *qh_append_tds(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- struct list_head *qtd_list,
- int epnum,
- void **ptr
-)
+static struct fotg210_qh *qh_append_tds(struct fotg210_hcd *fotg210,
+ struct urb *urb, struct list_head *qtd_list,
+ int epnum, void **ptr)
{
- struct fotg210_qh *qh = NULL;
- __hc32 qh_addr_mask = cpu_to_hc32(fotg210, 0x7f);
+ struct fotg210_qh *qh = NULL;
+ __hc32 qh_addr_mask = cpu_to_hc32(fotg210, 0x7f);
qh = (struct fotg210_qh *) *ptr;
if (unlikely(qh == NULL)) {
@@ -3090,7 +2985,7 @@ static struct fotg210_qh *qh_append_tds(
*ptr = qh;
}
if (likely(qh != NULL)) {
- struct fotg210_qtd *qtd;
+ struct fotg210_qtd *qtd;
if (unlikely(list_empty(qtd_list)))
qtd = NULL;
@@ -3109,9 +3004,9 @@ static struct fotg210_qh *qh_append_tds(
* only hc or qh_refresh() ever modify the overlay.
*/
if (likely(qtd != NULL)) {
- struct fotg210_qtd *dummy;
- dma_addr_t dma;
- __hc32 token;
+ struct fotg210_qtd *dummy;
+ dma_addr_t dma;
+ __hc32 token;
/* to avoid racing the HC, use the dummy td instead of
* the first td of our list (becomes new dummy). both
@@ -3150,32 +3045,28 @@ static struct fotg210_qh *qh_append_tds(
return qh;
}
-/*-------------------------------------------------------------------------*/
-
-static int
-submit_async(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- struct list_head *qtd_list,
- gfp_t mem_flags
-) {
- int epnum;
- unsigned long flags;
- struct fotg210_qh *qh = NULL;
- int rc;
+static int submit_async(struct fotg210_hcd *fotg210, struct urb *urb,
+ struct list_head *qtd_list, gfp_t mem_flags)
+{
+ int epnum;
+ unsigned long flags;
+ struct fotg210_qh *qh = NULL;
+ int rc;
epnum = urb->ep->desc.bEndpointAddress;
#ifdef FOTG210_URB_TRACE
{
struct fotg210_qtd *qtd;
+
qtd = list_entry(qtd_list->next, struct fotg210_qtd, qtd_list);
fotg210_dbg(fotg210,
- "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
- __func__, urb->dev->devpath, urb,
- epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
- urb->transfer_buffer_length,
- qtd, urb->ep->hcpriv);
+ "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+ __func__, urb->dev->devpath, urb,
+ epnum & 0x0f, (epnum & USB_DIR_IN)
+ ? "in" : "out",
+ urb->transfer_buffer_length,
+ qtd, urb->ep->hcpriv);
}
#endif
@@ -3200,19 +3091,17 @@ submit_async(
*/
if (likely(qh->qh_state == QH_STATE_IDLE))
qh_link_async(fotg210, qh);
- done:
+done:
spin_unlock_irqrestore(&fotg210->lock, flags);
if (unlikely(qh == NULL))
qtd_list_free(fotg210, urb, qtd_list);
return rc;
}
-/*-------------------------------------------------------------------------*/
-
static void single_unlink_async(struct fotg210_hcd *fotg210,
- struct fotg210_qh *qh)
+ struct fotg210_qh *qh)
{
- struct fotg210_qh *prev;
+ struct fotg210_qh *prev;
/* Add to the end of the list of QHs waiting for the next IAAD */
qh->qh_state = QH_STATE_UNLINK;
@@ -3260,7 +3149,7 @@ static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested)
&fotg210->regs->command);
fotg210_readl(fotg210, &fotg210->regs->command);
fotg210_enable_event(fotg210, FOTG210_HRTIMER_IAA_WATCHDOG,
- true);
+ true);
}
}
@@ -3268,10 +3157,10 @@ static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested)
static void end_unlink_async(struct fotg210_hcd *fotg210)
{
- struct fotg210_qh *qh;
+ struct fotg210_qh *qh;
/* Process the idle QHs */
- restart:
+restart:
fotg210->async_unlinking = true;
while (fotg210->async_iaa) {
qh = fotg210->async_iaa;
@@ -3326,7 +3215,7 @@ static void unlink_empty_async(struct fotg210_hcd *fotg210)
/* QHs that haven't been empty for long enough will be handled later */
if (check_unlinks_later) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_ASYNC_UNLINKS,
- true);
+ true);
++fotg210->async_unlink_cycle;
}
}
@@ -3335,7 +3224,7 @@ static void unlink_empty_async(struct fotg210_hcd *fotg210)
/* caller must own fotg210->lock */
static void start_unlink_async(struct fotg210_hcd *fotg210,
- struct fotg210_qh *qh)
+ struct fotg210_qh *qh)
{
/*
* If the QH isn't linked then there's nothing we can do
@@ -3352,18 +3241,16 @@ static void start_unlink_async(struct fotg210_hcd *fotg210,
start_iaa_cycle(fotg210, false);
}
-/*-------------------------------------------------------------------------*/
-
static void scan_async(struct fotg210_hcd *fotg210)
{
- struct fotg210_qh *qh;
- bool check_unlinks_later = false;
+ struct fotg210_qh *qh;
+ bool check_unlinks_later = false;
fotg210->qh_scan_next = fotg210->async->qh_next.qh;
while (fotg210->qh_scan_next) {
qh = fotg210->qh_scan_next;
fotg210->qh_scan_next = qh->qh_next.qh;
- rescan:
+rescan:
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list)) {
int temp;
@@ -3395,15 +3282,13 @@ static void scan_async(struct fotg210_hcd *fotg210)
*/
if (check_unlinks_later && fotg210->rh_state == FOTG210_RH_RUNNING &&
!(fotg210->enabled_hrtimer_events &
- BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) {
+ BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) {
fotg210_enable_event(fotg210,
- FOTG210_HRTIMER_ASYNC_UNLINKS, true);
+ FOTG210_HRTIMER_ASYNC_UNLINKS, true);
++fotg210->async_unlink_cycle;
}
}
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI scheduled transaction support: interrupt, iso, split iso
+/* EHCI scheduled transaction support: interrupt, iso, split iso
* These are called "periodic" transactions in the EHCI spec.
*
* Note that for interrupt transfers, the QH/QTD manipulation is shared
@@ -3414,19 +3299,14 @@ static void scan_async(struct fotg210_hcd *fotg210)
* It keeps track of every ITD (or SITD) that's linked, and holds enough
* pre-calculated schedule data to make appending to the queue be quick.
*/
-
static int fotg210_get_frame(struct usb_hcd *hcd);
-/*-------------------------------------------------------------------------*/
-
-/*
- * periodic_next_shadow - return "next" pointer on shadow list
+/* periodic_next_shadow - return "next" pointer on shadow list
* @periodic: host pointer to qh/itd
* @tag: hardware tag for type of this record
*/
-static union fotg210_shadow *
-periodic_next_shadow(struct fotg210_hcd *fotg210,
- union fotg210_shadow *periodic, __hc32 tag)
+static union fotg210_shadow *periodic_next_shadow(struct fotg210_hcd *fotg210,
+ union fotg210_shadow *periodic, __hc32 tag)
{
switch (hc32_to_cpu(fotg210, tag)) {
case Q_TYPE_QH:
@@ -3438,9 +3318,8 @@ periodic_next_shadow(struct fotg210_hcd *fotg210,
}
}
-static __hc32 *
-shadow_next_periodic(struct fotg210_hcd *fotg210,
- union fotg210_shadow *periodic, __hc32 tag)
+static __hc32 *shadow_next_periodic(struct fotg210_hcd *fotg210,
+ union fotg210_shadow *periodic, __hc32 tag)
{
switch (hc32_to_cpu(fotg210, tag)) {
/* our fotg210_shadow.qh is actually software part */
@@ -3454,11 +3333,11 @@ shadow_next_periodic(struct fotg210_hcd *fotg210,
/* caller must hold fotg210->lock */
static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame,
- void *ptr)
+ void *ptr)
{
- union fotg210_shadow *prev_p = &fotg210->pshadow[frame];
- __hc32 *hw_p = &fotg210->periodic[frame];
- union fotg210_shadow here = *prev_p;
+ union fotg210_shadow *prev_p = &fotg210->pshadow[frame];
+ __hc32 *hw_p = &fotg210->periodic[frame];
+ union fotg210_shadow here = *prev_p;
/* find predecessor of "ptr"; hw and shadow lists are in sync */
while (here.ptr && here.ptr != ptr) {
@@ -3479,17 +3358,17 @@ static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame,
Q_NEXT_TYPE(fotg210, *hw_p));
*hw_p = *shadow_next_periodic(fotg210, &here,
- Q_NEXT_TYPE(fotg210, *hw_p));
+ Q_NEXT_TYPE(fotg210, *hw_p));
}
/* how many of the uframe's 125 usecs are allocated? */
-static unsigned short
-periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe)
+static unsigned short periodic_usecs(struct fotg210_hcd *fotg210,
+ unsigned frame, unsigned uframe)
{
- __hc32 *hw_p = &fotg210->periodic[frame];
- union fotg210_shadow *q = &fotg210->pshadow[frame];
- unsigned usecs = 0;
- struct fotg210_qh_hw *hw;
+ __hc32 *hw_p = &fotg210->periodic[frame];
+ union fotg210_shadow *q = &fotg210->pshadow[frame];
+ unsigned usecs = 0;
+ struct fotg210_qh_hw *hw;
while (q->ptr) {
switch (hc32_to_cpu(fotg210, Q_NEXT_TYPE(fotg210, *hw_p))) {
@@ -3526,12 +3405,10 @@ periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe)
}
if (usecs > fotg210->uframe_periodic_max)
fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n",
- frame * 8 + uframe, usecs);
+ frame * 8 + uframe, usecs);
return usecs;
}
-/*-------------------------------------------------------------------------*/
-
static int same_tt(struct usb_device *dev1, struct usb_device *dev2)
{
if (!dev1->tt || !dev2->tt)
@@ -3548,13 +3425,8 @@ static int same_tt(struct usb_device *dev1, struct usb_device *dev2)
* for a periodic transfer starting at the specified frame, using
* all the uframes in the mask.
*/
-static int tt_no_collision(
- struct fotg210_hcd *fotg210,
- unsigned period,
- struct usb_device *dev,
- unsigned frame,
- u32 uf_mask
-)
+static int tt_no_collision(struct fotg210_hcd *fotg210, unsigned period,
+ struct usb_device *dev, unsigned frame, u32 uf_mask)
{
if (period == 0) /* error */
return 0;
@@ -3564,9 +3436,9 @@ static int tt_no_collision(
* calling convention doesn't make that distinction.
*/
for (; frame < fotg210->periodic_size; frame += period) {
- union fotg210_shadow here;
- __hc32 type;
- struct fotg210_qh_hw *hw;
+ union fotg210_shadow here;
+ __hc32 type;
+ struct fotg210_qh_hw *hw;
here = fotg210->pshadow[frame];
type = Q_NEXT_TYPE(fotg210, fotg210->periodic[frame]);
@@ -3579,7 +3451,7 @@ static int tt_no_collision(
case Q_TYPE_QH:
hw = here.qh->hw;
if (same_tt(dev, here.qh->dev)) {
- u32 mask;
+ u32 mask;
mask = hc32_to_cpu(fotg210,
hw->hw_info2);
@@ -3594,8 +3466,8 @@ static int tt_no_collision(
/* case Q_TYPE_FSTN: */
default:
fotg210_dbg(fotg210,
- "periodic frame %d bogus type %d\n",
- frame, type);
+ "periodic frame %d bogus type %d\n",
+ frame, type);
}
/* collision or error */
@@ -3607,8 +3479,6 @@ static int tt_no_collision(
return 1;
}
-/*-------------------------------------------------------------------------*/
-
static void enable_periodic(struct fotg210_hcd *fotg210)
{
if (fotg210->periodic_count++)
@@ -3632,8 +3502,6 @@ static void disable_periodic(struct fotg210_hcd *fotg210)
fotg210_poll_PSS(fotg210);
}
-/*-------------------------------------------------------------------------*/
-
/* periodic schedule slots have iso tds (normal or split) first, then a
* sparse tree for active interrupt transfers.
*
@@ -3642,24 +3510,24 @@ static void disable_periodic(struct fotg210_hcd *fotg210)
*/
static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{
- unsigned i;
- unsigned period = qh->period;
+ unsigned i;
+ unsigned period = qh->period;
dev_dbg(&qh->dev->dev,
- "link qh%d-%04x/%p start %d [%d/%d us]\n",
- period, hc32_to_cpup(fotg210, &qh->hw->hw_info2)
- & (QH_CMASK | QH_SMASK),
- qh, qh->start, qh->usecs, qh->c_usecs);
+ "link qh%d-%04x/%p start %d [%d/%d us]\n", period,
+ hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
+ (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs,
+ qh->c_usecs);
/* high bandwidth, or otherwise every microframe */
if (period == 0)
period = 1;
for (i = qh->start; i < fotg210->periodic_size; i += period) {
- union fotg210_shadow *prev = &fotg210->pshadow[i];
- __hc32 *hw_p = &fotg210->periodic[i];
- union fotg210_shadow here = *prev;
- __hc32 type = 0;
+ union fotg210_shadow *prev = &fotg210->pshadow[i];
+ __hc32 *hw_p = &fotg210->periodic[i];
+ union fotg210_shadow here = *prev;
+ __hc32 type = 0;
/* skip the iso nodes at list head */
while (here.ptr) {
@@ -3707,10 +3575,10 @@ static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
}
static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
- struct fotg210_qh *qh)
+ struct fotg210_qh *qh)
{
- unsigned i;
- unsigned period;
+ unsigned i;
+ unsigned period;
/*
* If qh is for a low/full-speed device, simply unlinking it
@@ -3741,10 +3609,10 @@ static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
: (qh->usecs * 8);
dev_dbg(&qh->dev->dev,
- "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
- qh->period,
- hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
- (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs);
+ "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
+ qh->period, hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
+ (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs,
+ qh->c_usecs);
/* qh->qh_next still "live" to HC */
qh->qh_state = QH_STATE_UNLINK;
@@ -3757,7 +3625,7 @@ static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
}
static void start_unlink_intr(struct fotg210_hcd *fotg210,
- struct fotg210_qh *qh)
+ struct fotg210_qh *qh)
{
/* If the QH isn't linked then there's nothing we can do
* unless we were called during a giveback, in which case
@@ -3794,15 +3662,15 @@ static void start_unlink_intr(struct fotg210_hcd *fotg210,
fotg210_handle_intr_unlinks(fotg210);
else if (fotg210->intr_unlink == qh) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR,
- true);
+ true);
++fotg210->intr_unlink_cycle;
}
}
static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{
- struct fotg210_qh_hw *hw = qh->hw;
- int rc;
+ struct fotg210_qh_hw *hw = qh->hw;
+ int rc;
qh->qh_state = QH_STATE_IDLE;
hw->hw_next = FOTG210_LIST_END(fotg210);
@@ -3811,7 +3679,7 @@ static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
/* reschedule QH iff another request is queued */
if (!list_empty(&qh->qtd_list) &&
- fotg210->rh_state == FOTG210_RH_RUNNING) {
+ fotg210->rh_state == FOTG210_RH_RUNNING) {
rc = qh_schedule(fotg210, qh);
/* An error here likely indicates handshake failure
@@ -3830,16 +3698,10 @@ static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
disable_periodic(fotg210);
}
-/*-------------------------------------------------------------------------*/
-
-static int check_period(
- struct fotg210_hcd *fotg210,
- unsigned frame,
- unsigned uframe,
- unsigned period,
- unsigned usecs
-) {
- int claimed;
+static int check_period(struct fotg210_hcd *fotg210, unsigned frame,
+ unsigned uframe, unsigned period, unsigned usecs)
+{
+ int claimed;
/* complete split running into next frame?
* given FSTN support, we could sometimes check...
@@ -3857,7 +3719,7 @@ static int check_period(
do {
for (uframe = 0; uframe < 7; uframe++) {
claimed = periodic_usecs(fotg210, frame,
- uframe);
+ uframe);
if (claimed > usecs)
return 0;
}
@@ -3876,16 +3738,11 @@ static int check_period(
return 1;
}
-static int check_intr_schedule(
- struct fotg210_hcd *fotg210,
- unsigned frame,
- unsigned uframe,
- const struct fotg210_qh *qh,
- __hc32 *c_maskp
-)
+static int check_intr_schedule(struct fotg210_hcd *fotg210, unsigned frame,
+ unsigned uframe, const struct fotg210_qh *qh, __hc32 *c_maskp)
{
- int retval = -ENOSPC;
- u8 mask = 0;
+ int retval = -ENOSPC;
+ u8 mask = 0;
if (qh->c_usecs && uframe >= 6) /* FSTN territory? */
goto done;
@@ -3911,10 +3768,10 @@ static int check_intr_schedule(
mask |= 1 << uframe;
if (tt_no_collision(fotg210, qh->period, qh->dev, frame, mask)) {
if (!check_period(fotg210, frame, uframe + qh->gap_uf + 1,
- qh->period, qh->c_usecs))
+ qh->period, qh->c_usecs))
goto done;
if (!check_period(fotg210, frame, uframe + qh->gap_uf,
- qh->period, qh->c_usecs))
+ qh->period, qh->c_usecs))
goto done;
retval = 0;
}
@@ -3927,11 +3784,11 @@ done:
*/
static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{
- int status;
- unsigned uframe;
- __hc32 c_mask;
- unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
- struct fotg210_qh_hw *hw = qh->hw;
+ int status;
+ unsigned uframe;
+ __hc32 c_mask;
+ unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
+ struct fotg210_qh_hw *hw = qh->hw;
qh_refresh(fotg210, qh);
hw->hw_next = FOTG210_LIST_END(fotg210);
@@ -3954,7 +3811,7 @@ static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
if (status) {
/* "normal" case, uframing flexible except with splits */
if (qh->period) {
- int i;
+ int i;
for (i = qh->period; status && i > 0; --i) {
frame = ++fotg210->random_frame % qh->period;
@@ -3971,7 +3828,7 @@ static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
} else {
frame = 0;
status = check_intr_schedule(fotg210, 0, 0, qh,
- &c_mask);
+ &c_mask);
}
if (status)
goto done;
@@ -3992,17 +3849,14 @@ done:
return status;
}
-static int intr_submit(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- struct list_head *qtd_list,
- gfp_t mem_flags
-) {
- unsigned epnum;
- unsigned long flags;
- struct fotg210_qh *qh;
- int status;
- struct list_head empty;
+static int intr_submit(struct fotg210_hcd *fotg210, struct urb *urb,
+ struct list_head *qtd_list, gfp_t mem_flags)
+{
+ unsigned epnum;
+ unsigned long flags;
+ struct fotg210_qh *qh;
+ int status;
+ struct list_head empty;
/* get endpoint and transfer/schedule data */
epnum = urb->ep->desc.bEndpointAddress;
@@ -4050,11 +3904,11 @@ done_not_linked:
static void scan_intr(struct fotg210_hcd *fotg210)
{
- struct fotg210_qh *qh;
+ struct fotg210_qh *qh;
list_for_each_entry_safe(qh, fotg210->qh_scan_next,
- &fotg210->intr_qh_list, intr_node) {
- rescan:
+ &fotg210->intr_qh_list, intr_node) {
+rescan:
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list)) {
int temp;
@@ -4069,7 +3923,7 @@ static void scan_intr(struct fotg210_hcd *fotg210)
temp = qh_completions(fotg210, qh);
if (unlikely(qh->needs_rescan ||
(list_empty(&qh->qtd_list) &&
- qh->qh_state == QH_STATE_LINKED)))
+ qh->qh_state == QH_STATE_LINKED)))
start_unlink_intr(fotg210, qh);
else if (temp != 0)
goto rescan;
@@ -4077,12 +3931,9 @@ static void scan_intr(struct fotg210_hcd *fotg210)
}
}
-/*-------------------------------------------------------------------------*/
-
/* fotg210_iso_stream ops work with both ITD and SITD */
-static struct fotg210_iso_stream *
-iso_stream_alloc(gfp_t mem_flags)
+static struct fotg210_iso_stream *iso_stream_alloc(gfp_t mem_flags)
{
struct fotg210_iso_stream *stream;
@@ -4095,20 +3946,15 @@ iso_stream_alloc(gfp_t mem_flags)
return stream;
}
-static void
-iso_stream_init(
- struct fotg210_hcd *fotg210,
- struct fotg210_iso_stream *stream,
- struct usb_device *dev,
- int pipe,
- unsigned interval
-)
+static void iso_stream_init(struct fotg210_hcd *fotg210,
+ struct fotg210_iso_stream *stream, struct usb_device *dev,
+ int pipe, unsigned interval)
{
- u32 buf1;
- unsigned epnum, maxp;
- int is_input;
- long bandwidth;
- unsigned multi;
+ u32 buf1;
+ unsigned epnum, maxp;
+ int is_input;
+ long bandwidth;
+ unsigned multi;
/*
* this might be a "high bandwidth" highspeed endpoint,
@@ -4153,13 +3999,13 @@ iso_stream_init(
stream->maxp = maxp;
}
-static struct fotg210_iso_stream *
-iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
+static struct fotg210_iso_stream *iso_stream_find(struct fotg210_hcd *fotg210,
+ struct urb *urb)
{
- unsigned epnum;
- struct fotg210_iso_stream *stream;
+ unsigned epnum;
+ struct fotg210_iso_stream *stream;
struct usb_host_endpoint *ep;
- unsigned long flags;
+ unsigned long flags;
epnum = usb_pipeendpoint(urb->pipe);
if (usb_pipein(urb->pipe))
@@ -4182,8 +4028,8 @@ iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
/* if dev->ep[epnum] is a QH, hw is set */
} else if (unlikely(stream->hw != NULL)) {
fotg210_dbg(fotg210, "dev %s ep%d%s, not iso??\n",
- urb->dev->devpath, epnum,
- usb_pipein(urb->pipe) ? "in" : "out");
+ urb->dev->devpath, epnum,
+ usb_pipein(urb->pipe) ? "in" : "out");
stream = NULL;
}
@@ -4191,15 +4037,13 @@ iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
return stream;
}
-/*-------------------------------------------------------------------------*/
-
/* fotg210_iso_sched ops can be ITD-only or SITD-only */
-static struct fotg210_iso_sched *
-iso_sched_alloc(unsigned packets, gfp_t mem_flags)
+static struct fotg210_iso_sched *iso_sched_alloc(unsigned packets,
+ gfp_t mem_flags)
{
- struct fotg210_iso_sched *iso_sched;
- int size = sizeof(*iso_sched);
+ struct fotg210_iso_sched *iso_sched;
+ int size = sizeof(*iso_sched);
size += packets * sizeof(struct fotg210_iso_packet);
iso_sched = kzalloc(size, mem_flags);
@@ -4209,16 +4053,12 @@ iso_sched_alloc(unsigned packets, gfp_t mem_flags)
return iso_sched;
}
-static inline void
-itd_sched_init(
- struct fotg210_hcd *fotg210,
- struct fotg210_iso_sched *iso_sched,
- struct fotg210_iso_stream *stream,
- struct urb *urb
-)
+static inline void itd_sched_init(struct fotg210_hcd *fotg210,
+ struct fotg210_iso_sched *iso_sched,
+ struct fotg210_iso_stream *stream, struct urb *urb)
{
- unsigned i;
- dma_addr_t dma = urb->transfer_dma;
+ unsigned i;
+ dma_addr_t dma = urb->transfer_dma;
/* how many uframes are needed for these transfers */
iso_sched->span = urb->number_of_packets * stream->interval;
@@ -4227,10 +4067,10 @@ itd_sched_init(
* when we fit new itds into the schedule.
*/
for (i = 0; i < urb->number_of_packets; i++) {
- struct fotg210_iso_packet *uframe = &iso_sched->packet[i];
- unsigned length;
- dma_addr_t buf;
- u32 trans;
+ struct fotg210_iso_packet *uframe = &iso_sched->packet[i];
+ unsigned length;
+ dma_addr_t buf;
+ u32 trans;
length = urb->iso_frame_desc[i].length;
buf = dma + urb->iso_frame_desc[i].offset;
@@ -4251,11 +4091,8 @@ itd_sched_init(
}
}
-static void
-iso_sched_free(
- struct fotg210_iso_stream *stream,
- struct fotg210_iso_sched *iso_sched
-)
+static void iso_sched_free(struct fotg210_iso_stream *stream,
+ struct fotg210_iso_sched *iso_sched)
{
if (!iso_sched)
return;
@@ -4264,20 +4101,15 @@ iso_sched_free(
kfree(iso_sched);
}
-static int
-itd_urb_transaction(
- struct fotg210_iso_stream *stream,
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- gfp_t mem_flags
-)
+static int itd_urb_transaction(struct fotg210_iso_stream *stream,
+ struct fotg210_hcd *fotg210, struct urb *urb, gfp_t mem_flags)
{
- struct fotg210_itd *itd;
- dma_addr_t itd_dma;
- int i;
- unsigned num_itds;
- struct fotg210_iso_sched *sched;
- unsigned long flags;
+ struct fotg210_itd *itd;
+ dma_addr_t itd_dma;
+ int i;
+ unsigned num_itds;
+ struct fotg210_iso_sched *sched;
+ unsigned long flags;
sched = iso_sched_alloc(urb->number_of_packets, mem_flags);
if (unlikely(sched == NULL))
@@ -4306,7 +4138,7 @@ itd_urb_transaction(
list_del(&itd->itd_list);
itd_dma = itd->itd_dma;
} else {
- alloc_itd:
+alloc_itd:
spin_unlock_irqrestore(&fotg210->lock, flags);
itd = dma_pool_alloc(fotg210->itd_pool, mem_flags,
&itd_dma);
@@ -4330,16 +4162,8 @@ itd_urb_transaction(
return 0;
}
-/*-------------------------------------------------------------------------*/
-
-static inline int
-itd_slot_ok(
- struct fotg210_hcd *fotg210,
- u32 mod,
- u32 uframe,
- u8 usecs,
- u32 period
-)
+static inline int itd_slot_ok(struct fotg210_hcd *fotg210, u32 mod, u32 uframe,
+ u8 usecs, u32 period)
{
uframe %= period;
do {
@@ -4354,8 +4178,7 @@ itd_slot_ok(
return 1;
}
-/*
- * This scheduler plans almost as far into the future as it has actual
+/* This scheduler plans almost as far into the future as it has actual
* periodic schedule slots. (Affected by TUNE_FLS, which defaults to
* "as small as possible" to be cache-friendlier.) That limits the size
* transfers you can stream reliably; avoid more than 64 msec per urb.
@@ -4365,19 +4188,15 @@ itd_slot_ok(
* given FOTG210_TUNE_FLS and the slop). Or, write a smarter scheduler!
*/
-#define SCHEDULE_SLOP 80 /* microframes */
+#define SCHEDULE_SLOP 80 /* microframes */
-static int
-iso_stream_schedule(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- struct fotg210_iso_stream *stream
-)
+static int iso_stream_schedule(struct fotg210_hcd *fotg210, struct urb *urb,
+ struct fotg210_iso_stream *stream)
{
- u32 now, next, start, period, span;
- int status;
- unsigned mod = fotg210->periodic_size << 3;
- struct fotg210_iso_sched *sched = urb->hcpriv;
+ u32 now, next, start, period, span;
+ int status;
+ unsigned mod = fotg210->periodic_size << 3;
+ struct fotg210_iso_sched *sched = urb->hcpriv;
period = urb->interval;
span = sched->span;
@@ -4396,7 +4215,7 @@ iso_stream_schedule(
* slot in the schedule, implicitly assuming URB_ISO_ASAP.
*/
if (likely(!list_empty(&stream->td_list))) {
- u32 excess;
+ u32 excess;
/* For high speed devices, allow scheduling within the
* isochronous scheduling threshold. For full speed devices
@@ -4435,6 +4254,7 @@ iso_stream_schedule(
*/
else {
int done = 0;
+
start = SCHEDULE_SLOP + (now & ~0x07);
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
@@ -4457,15 +4277,15 @@ iso_stream_schedule(
/* no room in the schedule */
if (!done) {
fotg210_dbg(fotg210, "iso resched full %p (now %d max %d)\n",
- urb, now, now + mod);
+ urb, now, now + mod);
status = -ENOSPC;
goto fail;
}
}
/* Tried to schedule too far into the future? */
- if (unlikely(start - now + span - period
- >= mod - 2 * SCHEDULE_SLOP)) {
+ if (unlikely(start - now + span - period >=
+ mod - 2 * SCHEDULE_SLOP)) {
fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n",
urb, start - now, span - period,
mod - 2 * SCHEDULE_SLOP);
@@ -4485,17 +4305,14 @@ iso_stream_schedule(
fotg210->next_frame = now >> 3;
return 0;
- fail:
+fail:
iso_sched_free(stream, sched);
urb->hcpriv = NULL;
return status;
}
-/*-------------------------------------------------------------------------*/
-
-static inline void
-itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream,
- struct fotg210_itd *itd)
+static inline void itd_init(struct fotg210_hcd *fotg210,
+ struct fotg210_iso_stream *stream, struct fotg210_itd *itd)
{
int i;
@@ -4511,17 +4328,12 @@ itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream,
/* All other fields are filled when scheduling */
}
-static inline void
-itd_patch(
- struct fotg210_hcd *fotg210,
- struct fotg210_itd *itd,
- struct fotg210_iso_sched *iso_sched,
- unsigned index,
- u16 uframe
-)
+static inline void itd_patch(struct fotg210_hcd *fotg210,
+ struct fotg210_itd *itd, struct fotg210_iso_sched *iso_sched,
+ unsigned index, u16 uframe)
{
- struct fotg210_iso_packet *uf = &iso_sched->packet[index];
- unsigned pg = itd->pg;
+ struct fotg210_iso_packet *uf = &iso_sched->packet[index];
+ unsigned pg = itd->pg;
uframe &= 0x07;
itd->index[uframe] = index;
@@ -4533,7 +4345,7 @@ itd_patch(
/* iso_frame_desc[].offset must be strictly increasing */
if (unlikely(uf->cross)) {
- u64 bufp = uf->bufp + 4096;
+ u64 bufp = uf->bufp + 4096;
itd->pg = ++pg;
itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, bufp & ~(u32)0);
@@ -4541,13 +4353,13 @@ itd_patch(
}
}
-static inline void
-itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd)
+static inline void itd_link(struct fotg210_hcd *fotg210, unsigned frame,
+ struct fotg210_itd *itd)
{
- union fotg210_shadow *prev = &fotg210->pshadow[frame];
- __hc32 *hw_p = &fotg210->periodic[frame];
- union fotg210_shadow here = *prev;
- __hc32 type = 0;
+ union fotg210_shadow *prev = &fotg210->pshadow[frame];
+ __hc32 *hw_p = &fotg210->periodic[frame];
+ union fotg210_shadow here = *prev;
+ __hc32 type = 0;
/* skip any iso nodes which might belong to previous microframes */
while (here.ptr) {
@@ -4568,17 +4380,13 @@ itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd)
}
/* fit urb's itds into the selected schedule slot; activate as needed */
-static void itd_link_urb(
- struct fotg210_hcd *fotg210,
- struct urb *urb,
- unsigned mod,
- struct fotg210_iso_stream *stream
-)
-{
- int packet;
- unsigned next_uframe, uframe, frame;
- struct fotg210_iso_sched *iso_sched = urb->hcpriv;
- struct fotg210_itd *itd;
+static void itd_link_urb(struct fotg210_hcd *fotg210, struct urb *urb,
+ unsigned mod, struct fotg210_iso_stream *stream)
+{
+ int packet;
+ unsigned next_uframe, uframe, frame;
+ struct fotg210_iso_sched *iso_sched = urb->hcpriv;
+ struct fotg210_itd *itd;
next_uframe = stream->next_uframe & (mod - 1);
@@ -4621,7 +4429,7 @@ static void itd_link_urb(
if (((next_uframe >> 3) != frame)
|| packet == urb->number_of_packets) {
itd_link(fotg210, frame & (fotg210->periodic_size - 1),
- itd);
+ itd);
itd = NULL;
}
}
@@ -4635,8 +4443,8 @@ static void itd_link_urb(
enable_periodic(fotg210);
}
-#define ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\
- FOTG210_ISOC_XACTERR)
+#define ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\
+ FOTG210_ISOC_XACTERR)
/* Process and recycle a completed ITD. Return true iff its urb completed,
* and hence its completion callback probably added things to the hardware
@@ -4650,14 +4458,14 @@ static void itd_link_urb(
*/
static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
{
- struct urb *urb = itd->urb;
- struct usb_iso_packet_descriptor *desc;
- u32 t;
- unsigned uframe;
- int urb_index = -1;
- struct fotg210_iso_stream *stream = itd->stream;
- struct usb_device *dev;
- bool retval = false;
+ struct urb *urb = itd->urb;
+ struct usb_iso_packet_descriptor *desc;
+ u32 t;
+ unsigned uframe;
+ int urb_index = -1;
+ struct fotg210_iso_stream *stream = itd->stream;
+ struct usb_device *dev;
+ bool retval = false;
/* for each uframe with a packet */
for (uframe = 0; uframe < 8; uframe++) {
@@ -4702,8 +4510,8 @@ static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
goto done;
/* ASSERT: it's really the last itd for this urb
- list_for_each_entry (itd, &stream->td_list, itd_list)
- BUG_ON (itd->urb == urb);
+ * list_for_each_entry (itd, &stream->td_list, itd_list)
+ * BUG_ON (itd->urb == urb);
*/
/* give urb back to the driver; completion often (re)submits */
@@ -4740,14 +4548,12 @@ done:
return retval;
}
-/*-------------------------------------------------------------------------*/
-
static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
- gfp_t mem_flags)
+ gfp_t mem_flags)
{
- int status = -EINVAL;
- unsigned long flags;
- struct fotg210_iso_stream *stream;
+ int status = -EINVAL;
+ unsigned long flags;
+ struct fotg210_iso_stream *stream;
/* Get iso_stream head */
stream = iso_stream_find(fotg210, urb);
@@ -4756,22 +4562,22 @@ static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
return -ENOMEM;
}
if (unlikely(urb->interval != stream->interval &&
- fotg210_port_speed(fotg210, 0) ==
- USB_PORT_STAT_HIGH_SPEED)) {
- fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n",
+ fotg210_port_speed(fotg210, 0) ==
+ USB_PORT_STAT_HIGH_SPEED)) {
+ fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n",
stream->interval, urb->interval);
- goto done;
+ goto done;
}
#ifdef FOTG210_URB_TRACE
fotg210_dbg(fotg210,
- "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n",
- __func__, urb->dev->devpath, urb,
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out",
- urb->transfer_buffer_length,
- urb->number_of_packets, urb->interval,
- stream);
+ "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n",
+ __func__, urb->dev->devpath, urb,
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->transfer_buffer_length,
+ urb->number_of_packets, urb->interval,
+ stream);
#endif
/* allocate ITDs w/o locking anything */
@@ -4795,19 +4601,87 @@ static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
itd_link_urb(fotg210, urb, fotg210->periodic_size << 3, stream);
else
usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
- done_not_linked:
+done_not_linked:
spin_unlock_irqrestore(&fotg210->lock, flags);
- done:
+done:
return status;
}
-/*-------------------------------------------------------------------------*/
+static inline int scan_frame_queue(struct fotg210_hcd *fotg210, unsigned frame,
+ unsigned now_frame, bool live)
+{
+ unsigned uf;
+ bool modified;
+ union fotg210_shadow q, *q_p;
+ __hc32 type, *hw_p;
+
+ /* scan each element in frame's queue for completions */
+ q_p = &fotg210->pshadow[frame];
+ hw_p = &fotg210->periodic[frame];
+ q.ptr = q_p->ptr;
+ type = Q_NEXT_TYPE(fotg210, *hw_p);
+ modified = false;
+
+ while (q.ptr) {
+ switch (hc32_to_cpu(fotg210, type)) {
+ case Q_TYPE_ITD:
+ /* If this ITD is still active, leave it for
+ * later processing ... check the next entry.
+ * No need to check for activity unless the
+ * frame is current.
+ */
+ if (frame == now_frame && live) {
+ rmb();
+ for (uf = 0; uf < 8; uf++) {
+ if (q.itd->hw_transaction[uf] &
+ ITD_ACTIVE(fotg210))
+ break;
+ }
+ if (uf < 8) {
+ q_p = &q.itd->itd_next;
+ hw_p = &q.itd->hw_next;
+ type = Q_NEXT_TYPE(fotg210,
+ q.itd->hw_next);
+ q = *q_p;
+ break;
+ }
+ }
+
+ /* Take finished ITDs out of the schedule
+ * and process them: recycle, maybe report
+ * URB completion. HC won't cache the
+ * pointer for much longer, if at all.
+ */
+ *q_p = q.itd->itd_next;
+ *hw_p = q.itd->hw_next;
+ type = Q_NEXT_TYPE(fotg210, q.itd->hw_next);
+ wmb();
+ modified = itd_complete(fotg210, q.itd);
+ q = *q_p;
+ break;
+ default:
+ fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n",
+ type, frame, q.ptr);
+ /* FALL THROUGH */
+ case Q_TYPE_QH:
+ case Q_TYPE_FSTN:
+ /* End of the iTDs and siTDs */
+ q.ptr = NULL;
+ break;
+ }
+
+ /* assume completion callbacks modify the queue */
+ if (unlikely(modified && fotg210->isoc_count > 0))
+ return -EINVAL;
+ }
+ return 0;
+}
static void scan_isoc(struct fotg210_hcd *fotg210)
{
- unsigned uf, now_frame, frame;
- unsigned fmask = fotg210->periodic_size - 1;
- bool modified, live;
+ unsigned uf, now_frame, frame, ret;
+ unsigned fmask = fotg210->periodic_size - 1;
+ bool live;
/*
* When running, scan from last scan point up to "now"
@@ -4826,69 +4700,10 @@ static void scan_isoc(struct fotg210_hcd *fotg210)
frame = fotg210->next_frame;
for (;;) {
- union fotg210_shadow q, *q_p;
- __hc32 type, *hw_p;
-
-restart:
- /* scan each element in frame's queue for completions */
- q_p = &fotg210->pshadow[frame];
- hw_p = &fotg210->periodic[frame];
- q.ptr = q_p->ptr;
- type = Q_NEXT_TYPE(fotg210, *hw_p);
- modified = false;
-
- while (q.ptr != NULL) {
- switch (hc32_to_cpu(fotg210, type)) {
- case Q_TYPE_ITD:
- /* If this ITD is still active, leave it for
- * later processing ... check the next entry.
- * No need to check for activity unless the
- * frame is current.
- */
- if (frame == now_frame && live) {
- rmb();
- for (uf = 0; uf < 8; uf++) {
- if (q.itd->hw_transaction[uf] &
- ITD_ACTIVE(fotg210))
- break;
- }
- if (uf < 8) {
- q_p = &q.itd->itd_next;
- hw_p = &q.itd->hw_next;
- type = Q_NEXT_TYPE(fotg210,
- q.itd->hw_next);
- q = *q_p;
- break;
- }
- }
-
- /* Take finished ITDs out of the schedule
- * and process them: recycle, maybe report
- * URB completion. HC won't cache the
- * pointer for much longer, if at all.
- */
- *q_p = q.itd->itd_next;
- *hw_p = q.itd->hw_next;
- type = Q_NEXT_TYPE(fotg210, q.itd->hw_next);
- wmb();
- modified = itd_complete(fotg210, q.itd);
- q = *q_p;
- break;
- default:
- fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n",
- type, frame, q.ptr);
- /* FALL THROUGH */
- case Q_TYPE_QH:
- case Q_TYPE_FSTN:
- /* End of the iTDs and siTDs */
- q.ptr = NULL;
- break;
- }
-
- /* assume completion callbacks modify the queue */
- if (unlikely(modified && fotg210->isoc_count > 0))
- goto restart;
- }
+ ret = 1;
+ while (ret != 0)
+ ret = scan_frame_queue(fotg210, frame,
+ now_frame, live);
/* Stop when we have reached the current frame */
if (frame == now_frame)
@@ -4897,16 +4712,14 @@ restart:
}
fotg210->next_frame = now_frame;
}
-/*-------------------------------------------------------------------------*/
-/*
- * Display / Set uframe_periodic_max
+
+/* Display / Set uframe_periodic_max
*/
static ssize_t show_uframe_periodic_max(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr, char *buf)
{
- struct fotg210_hcd *fotg210;
- int n;
+ struct fotg210_hcd *fotg210;
+ int n;
fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev)));
n = scnprintf(buf, PAGE_SIZE, "%d\n", fotg210->uframe_periodic_max);
@@ -4915,15 +4728,14 @@ static ssize_t show_uframe_periodic_max(struct device *dev,
static ssize_t store_uframe_periodic_max(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ struct device_attribute *attr, const char *buf, size_t count)
{
- struct fotg210_hcd *fotg210;
- unsigned uframe_periodic_max;
- unsigned frame, uframe;
- unsigned short allocated_max;
- unsigned long flags;
- ssize_t ret;
+ struct fotg210_hcd *fotg210;
+ unsigned uframe_periodic_max;
+ unsigned frame, uframe;
+ unsigned short allocated_max;
+ unsigned long flags;
+ ssize_t ret;
fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev)));
if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
@@ -4931,7 +4743,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
fotg210_info(fotg210, "rejecting invalid request for uframe_periodic_max=%u\n",
- uframe_periodic_max);
+ uframe_periodic_max);
return -EINVAL;
}
@@ -4954,22 +4766,22 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
for (frame = 0; frame < fotg210->periodic_size; ++frame)
for (uframe = 0; uframe < 7; ++uframe)
allocated_max = max(allocated_max,
- periodic_usecs(fotg210, frame, uframe));
+ periodic_usecs(fotg210, frame,
+ uframe));
if (allocated_max > uframe_periodic_max) {
fotg210_info(fotg210,
- "cannot decrease uframe_periodic_max because "
- "periodic bandwidth is already allocated "
- "(%u > %u)\n",
- allocated_max, uframe_periodic_max);
+ "cannot decrease uframe_periodic_max because periodic bandwidth is already allocated (%u > %u)\n",
+ allocated_max, uframe_periodic_max);
goto out_unlock;
}
}
/* increasing is always ok */
- fotg210_info(fotg210, "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n",
- 100 * uframe_periodic_max/125, uframe_periodic_max);
+ fotg210_info(fotg210,
+ "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n",
+ 100 * uframe_periodic_max/125, uframe_periodic_max);
if (uframe_periodic_max != 100)
fotg210_warn(fotg210, "max periodic bandwidth set is non-standard\n");
@@ -4987,8 +4799,8 @@ static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max,
static inline int create_sysfs_files(struct fotg210_hcd *fotg210)
{
- struct device *controller = fotg210_to_hcd(fotg210)->self.controller;
- int i = 0;
+ struct device *controller = fotg210_to_hcd(fotg210)->self.controller;
+ int i = 0;
if (i)
goto out;
@@ -5000,12 +4812,10 @@ out:
static inline void remove_sysfs_files(struct fotg210_hcd *fotg210)
{
- struct device *controller = fotg210_to_hcd(fotg210)->self.controller;
+ struct device *controller = fotg210_to_hcd(fotg210)->self.controller;
device_remove_file(controller, &dev_attr_uframe_periodic_max);
}
-/*-------------------------------------------------------------------------*/
-
/* On some systems, leaving remote wakeup enabled prevents system shutdown.
* The firmware seems to think that powering off is a wakeup event!
* This routine turns off remote wakeup and everything else, on all ports.
@@ -5017,8 +4827,7 @@ static void fotg210_turn_off_all_ports(struct fotg210_hcd *fotg210)
fotg210_writel(fotg210, PORT_RWC_BITS, status_reg);
}
-/*
- * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
+/* Halt HC, turn off all ports, and let the BIOS use the companion controllers.
* Must be called with interrupts enabled and the lock not held.
*/
static void fotg210_silence_controller(struct fotg210_hcd *fotg210)
@@ -5037,7 +4846,7 @@ static void fotg210_silence_controller(struct fotg210_hcd *fotg210)
*/
static void fotg210_shutdown(struct usb_hcd *hcd)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
spin_lock_irq(&fotg210->lock);
fotg210->shutdown = true;
@@ -5050,10 +4859,7 @@ static void fotg210_shutdown(struct usb_hcd *hcd)
hrtimer_cancel(&fotg210->hrtimer);
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * fotg210_work is called from some interrupts, timers, and so on.
+/* fotg210_work is called from some interrupts, timers, and so on.
* it calls driver completion functions, after dropping fotg210->lock.
*/
static void fotg210_work(struct fotg210_hcd *fotg210)
@@ -5068,7 +4874,7 @@ static void fotg210_work(struct fotg210_hcd *fotg210)
}
fotg210->scanning = true;
- rescan:
+rescan:
fotg210->need_rescan = false;
if (fotg210->async_count)
scan_async(fotg210);
@@ -5087,12 +4893,11 @@ static void fotg210_work(struct fotg210_hcd *fotg210)
turn_on_io_watchdog(fotg210);
}
-/*
- * Called when the fotg210_hcd module is removed.
+/* Called when the fotg210_hcd module is removed.
*/
static void fotg210_stop(struct usb_hcd *hcd)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
fotg210_dbg(fotg210, "stop\n");
@@ -5116,26 +4921,26 @@ static void fotg210_stop(struct usb_hcd *hcd)
spin_unlock_irq(&fotg210->lock);
fotg210_mem_cleanup(fotg210);
-#ifdef FOTG210_STATS
+#ifdef FOTG210_STATS
fotg210_dbg(fotg210, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
- fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa,
- fotg210->stats.lost_iaa);
+ fotg210->stats.normal, fotg210->stats.error,
+ fotg210->stats.iaa, fotg210->stats.lost_iaa);
fotg210_dbg(fotg210, "complete %ld unlink %ld\n",
- fotg210->stats.complete, fotg210->stats.unlink);
+ fotg210->stats.complete, fotg210->stats.unlink);
#endif
dbg_status(fotg210, "fotg210_stop completed",
- fotg210_readl(fotg210, &fotg210->regs->status));
+ fotg210_readl(fotg210, &fotg210->regs->status));
}
/* one-time init, only for memory state */
static int hcd_fotg210_init(struct usb_hcd *hcd)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- u32 temp;
- int retval;
- u32 hcc_params;
- struct fotg210_qh_hw *hw;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ u32 temp;
+ int retval;
+ u32 hcc_params;
+ struct fotg210_qh_hw *hw;
spin_lock_init(&fotg210->lock);
@@ -5238,18 +5043,18 @@ static int hcd_fotg210_init(struct usb_hcd *hcd)
/* start HC running; it's halted, hcd_fotg210_init() has been run (once) */
static int fotg210_run(struct usb_hcd *hcd)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- u32 temp;
- u32 hcc_params;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ u32 temp;
+ u32 hcc_params;
hcd->uses_new_polling = 1;
/* EHCI spec section 4.1 */
fotg210_writel(fotg210, fotg210->periodic_dma,
- &fotg210->regs->frame_list);
+ &fotg210->regs->frame_list);
fotg210_writel(fotg210, (u32)fotg210->async->qh_dma,
- &fotg210->regs->async_next);
+ &fotg210->regs->async_next);
/*
* hcc_params controls whether fotg210->regs->segment must (!!!)
@@ -5258,7 +5063,7 @@ static int fotg210_run(struct usb_hcd *hcd)
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
- * NOTE: the dma mask is visible through dma_supported(), so
+ * NOTE: the dma mask is visible through dev->dma_mask, so
* drivers can pass this info along ... like NETIF_F_HIGHDMA,
* Scsi_Host.highmem_io, and so forth. It's readonly to all
* host side drivers though.
@@ -5292,19 +5097,19 @@ static int fotg210_run(struct usb_hcd *hcd)
fotg210->rh_state = FOTG210_RH_RUNNING;
/* unblock posted writes */
fotg210_readl(fotg210, &fotg210->regs->command);
- msleep(5);
+ usleep_range(5000, 10000);
up_write(&ehci_cf_port_reset_rwsem);
fotg210->last_periodic_enable = ktime_get_real();
temp = HC_VERSION(fotg210,
- fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
+ fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
fotg210_info(fotg210,
- "USB %x.%x started, EHCI %x.%02x\n",
- ((fotg210->sbrn & 0xf0)>>4), (fotg210->sbrn & 0x0f),
- temp >> 8, temp & 0xff);
+ "USB %x.%x started, EHCI %x.%02x\n",
+ ((fotg210->sbrn & 0xf0) >> 4), (fotg210->sbrn & 0x0f),
+ temp >> 8, temp & 0xff);
fotg210_writel(fotg210, INTR_MASK,
- &fotg210->regs->intr_enable); /* Turn On Interrupts */
+ &fotg210->regs->intr_enable); /* Turn On Interrupts */
/* GRR this is run-once init(), being done every time the HC starts.
* So long as they're part of class devices, we can't do it init()
@@ -5322,14 +5127,14 @@ static int fotg210_setup(struct usb_hcd *hcd)
int retval;
fotg210->regs = (void __iomem *)fotg210->caps +
- HC_LENGTH(fotg210,
- fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
+ HC_LENGTH(fotg210,
+ fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
dbg_hcs_params(fotg210, "reset");
dbg_hcc_params(fotg210, "reset");
/* cache this readonly data; minimize chip reads */
fotg210->hcs_params = fotg210_readl(fotg210,
- &fotg210->caps->hcs_params);
+ &fotg210->caps->hcs_params);
fotg210->sbrn = HCD_USB2;
@@ -5347,13 +5152,11 @@ static int fotg210_setup(struct usb_hcd *hcd)
return 0;
}
-/*-------------------------------------------------------------------------*/
-
static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- u32 status, masked_status, pcd_status = 0, cmd;
- int bh;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ u32 status, masked_status, pcd_status = 0, cmd;
+ int bh;
spin_lock(&fotg210->lock);
@@ -5373,7 +5176,7 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
/* Shared IRQ? */
if (!masked_status ||
- unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) {
+ unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) {
spin_unlock(&fotg210->lock);
return IRQ_NONE;
}
@@ -5440,7 +5243,7 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
if (test_bit(0, &fotg210->suspended_ports) &&
((pstatus & PORT_RESUME) ||
- !(pstatus & PORT_SUSPEND)) &&
+ !(pstatus & PORT_SUSPEND)) &&
(pstatus & PORT_PE) &&
fotg210->reset_done[0] == 0) {
@@ -5469,7 +5272,7 @@ dead:
fotg210->rh_state = FOTG210_RH_STOPPING;
fotg210->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
fotg210_writel(fotg210, fotg210->command,
- &fotg210->regs->command);
+ &fotg210->regs->command);
fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
fotg210_handle_controller_death(fotg210);
@@ -5485,10 +5288,7 @@ dead:
return IRQ_HANDLED;
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * non-error returns are a promise to giveback() the urb later
+/* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
*
* urb + dev is in hcd.self.controller.urb_list
@@ -5499,13 +5299,11 @@ dead:
* NOTE: control, bulk, and interrupt share the same code to append TDs
* to a (possibly active) QH, and the same QH scanning code.
*/
-static int fotg210_urb_enqueue(
- struct usb_hcd *hcd,
- struct urb *urb,
- gfp_t mem_flags
-) {
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- struct list_head qtd_list;
+static int fotg210_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct list_head qtd_list;
INIT_LIST_HEAD(&qtd_list);
@@ -5539,10 +5337,10 @@ static int fotg210_urb_enqueue(
static int fotg210_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- struct fotg210_qh *qh;
- unsigned long flags;
- int rc;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct fotg210_qh *qh;
+ unsigned long flags;
+ int rc;
spin_lock_irqsave(&fotg210->lock, flags);
rc = usb_hcd_check_unlink_urb(hcd, urb, status);
@@ -5603,16 +5401,14 @@ done:
return rc;
}
-/*-------------------------------------------------------------------------*/
-
/* bulk qh holds the data toggle */
-static void
-fotg210_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+static void fotg210_endpoint_disable(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- unsigned long flags;
- struct fotg210_qh *qh, *tmp;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ unsigned long flags;
+ struct fotg210_qh *qh, *tmp;
/* ASSERT: any requests/urbs are being unlinked */
/* ASSERT: nobody can be submitting urbs for this any more */
@@ -5627,7 +5423,7 @@ rescan:
* accelerate iso completions ... so spin a while.
*/
if (qh->hw == NULL) {
- struct fotg210_iso_stream *stream = ep->hcpriv;
+ struct fotg210_iso_stream *stream = ep->hcpriv;
if (!list_empty(&stream->td_list))
goto idle_timeout;
@@ -5671,24 +5467,24 @@ idle_timeout:
* that's not our job. just leak this memory.
*/
fotg210_err(fotg210, "qh %p (#%02x) state %d%s\n",
- qh, ep->desc.bEndpointAddress, qh->qh_state,
- list_empty(&qh->qtd_list) ? "" : "(has tds)");
+ qh, ep->desc.bEndpointAddress, qh->qh_state,
+ list_empty(&qh->qtd_list) ? "" : "(has tds)");
break;
}
- done:
+done:
ep->hcpriv = NULL;
spin_unlock_irqrestore(&fotg210->lock, flags);
}
-static void
-fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+static void fotg210_endpoint_reset(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
- struct fotg210_qh *qh;
- int eptype = usb_endpoint_type(&ep->desc);
- int epnum = usb_endpoint_num(&ep->desc);
- int is_out = usb_endpoint_dir_out(&ep->desc);
- unsigned long flags;
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct fotg210_qh *qh;
+ int eptype = usb_endpoint_type(&ep->desc);
+ int epnum = usb_endpoint_num(&ep->desc);
+ int is_out = usb_endpoint_dir_out(&ep->desc);
+ unsigned long flags;
if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
return;
@@ -5723,15 +5519,13 @@ fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
static int fotg210_get_frame(struct usb_hcd *hcd)
{
- struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+ struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+
return (fotg210_read_frame_index(fotg210) >> 3) %
fotg210->periodic_size;
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+/* The EHCI in ChipIdea HDRC cannot be a separate module or device,
* because its registers (and irq) are shared between host/gadget/otg
* functions and in order to facilitate role switching we cannot
* give the fotg210 driver exclusive access to those.
@@ -5791,7 +5585,7 @@ static void fotg210_init(struct fotg210_hcd *fotg210)
u32 value;
iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
- &fotg210->regs->gmir);
+ &fotg210->regs->gmir);
value = ioread32(&fotg210->regs->otgcsr);
value &= ~OTGCSR_A_BUS_DROP;
@@ -5808,12 +5602,12 @@ static void fotg210_init(struct fotg210_hcd *fotg210)
*/
static int fotg210_hcd_probe(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd;
- struct resource *res;
- int irq;
- int retval = -ENODEV;
- struct fotg210_hcd *fotg210;
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd;
+ struct resource *res;
+ int irq;
+ int retval = -ENODEV;
+ struct fotg210_hcd *fotg210;
if (usb_disabled())
return -ENODEV;
@@ -5822,9 +5616,8 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
- dev_err(dev,
- "Found HC with no IRQ. Check %s setup!\n",
- dev_name(dev));
+ dev_err(dev, "Found HC with no IRQ. Check %s setup!\n",
+ dev_name(dev));
return -ENODEV;
}
@@ -5883,8 +5676,8 @@ fail_create_hcd:
*/
static int fotg210_hcd_remove(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
if (!hcd)
return 0;
@@ -5914,12 +5707,12 @@ static int __init fotg210_hcd_init(void)
set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
- pr_warn(KERN_WARNING "Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n");
+ pr_warn("Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n");
pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n",
- hcd_name,
- sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd),
- sizeof(struct fotg210_itd));
+ hcd_name, sizeof(struct fotg210_qh),
+ sizeof(struct fotg210_qtd),
+ sizeof(struct fotg210_itd));
fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root);
if (!fotg210_debug_root) {
@@ -5932,7 +5725,6 @@ static int __init fotg210_hcd_init(void)
goto clean;
return retval;
- platform_driver_unregister(&fotg210_hcd_driver);
clean:
debugfs_remove(fotg210_debug_root);
fotg210_debug_root = NULL;
diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h
index 3bad17859cd7..b5cfa7aeb277 100644
--- a/drivers/usb/host/fotg210.h
+++ b/drivers/usb/host/fotg210.h
@@ -137,19 +137,25 @@ struct fotg210_hcd { /* one per controller */
/* per root hub port */
unsigned long reset_done[FOTG210_MAX_ROOT_PORTS];
- /* bit vectors (one bit per port) */
- unsigned long bus_suspended; /* which ports were
- already suspended at the start of a bus suspend */
- unsigned long companion_ports; /* which ports are
- dedicated to the companion controller */
- unsigned long owned_ports; /* which ports are
- owned by the companion during a bus suspend */
- unsigned long port_c_suspend; /* which ports have
- the change-suspend feature turned on */
- unsigned long suspended_ports; /* which ports are
- suspended */
- unsigned long resuming_ports; /* which ports have
- started to resume */
+ /* bit vectors (one bit per port)
+ * which ports were already suspended at the start of a bus suspend
+ */
+ unsigned long bus_suspended;
+
+ /* which ports are edicated to the companion controller */
+ unsigned long companion_ports;
+
+ /* which ports are owned by the companion during a bus suspend */
+ unsigned long owned_ports;
+
+ /* which ports have the change-suspend feature turned on */
+ unsigned long port_c_suspend;
+
+ /* which ports are suspended */
+ unsigned long suspended_ports;
+
+ /* which ports have started to resume */
+ unsigned long resuming_ports;
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
@@ -585,10 +591,10 @@ struct fotg210_fstn {
/* Prepare the PORTSC wakeup flags during controller suspend/resume */
#define fotg210_prepare_ports_for_controller_suspend(fotg210, do_wakeup) \
- fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup);
+ fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup)
#define fotg210_prepare_ports_for_controller_resume(fotg210) \
- fotg210_adjust_port_wakeup_flags(fotg210, false, false);
+ fotg210_adjust_port_wakeup_flags(fotg210, false, false)
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 534c4c5d278a..0c382652a399 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -351,6 +351,7 @@ static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
#endif
{},
};
+MODULE_DEVICE_TABLE(of, fsl_usb2_mph_dr_of_match);
static struct platform_driver fsl_usb2_mph_dr_driver = {
.driver = {
diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c
deleted file mode 100644
index 1fd8718a9f11..000000000000
--- a/drivers/usb/host/fusbh200-hcd.c
+++ /dev/null
@@ -1,5894 +0,0 @@
-/*
- * Faraday FUSBH200 EHCI-like driver
- *
- * Copyright (c) 2013 Faraday Technology Corporation
- *
- * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com>
- * Feng-Hsin Chiang <john453@faraday-tech.com>
- * Po-Yu Chuang <ratbert.chuang@gmail.com>
- *
- * Most of code borrowed from the Linux-3.7 EHCI driver
- *
- * 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>
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/hrtimer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-/*-------------------------------------------------------------------------*/
-#define DRIVER_AUTHOR "Yuan-Hsin Chen"
-#define DRIVER_DESC "FUSBH200 Host Controller (EHCI) Driver"
-
-static const char hcd_name [] = "fusbh200_hcd";
-
-#undef FUSBH200_URB_TRACE
-
-/* magic numbers that can affect system performance */
-#define FUSBH200_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
-#define FUSBH200_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
-#define FUSBH200_TUNE_RL_TT 0
-#define FUSBH200_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
-#define FUSBH200_TUNE_MULT_TT 1
-/*
- * Some drivers think it's safe to schedule isochronous transfers more than
- * 256 ms into the future (partly as a result of an old bug in the scheduling
- * code). In an attempt to avoid trouble, we will use a minimum scheduling
- * length of 512 frames instead of 256.
- */
-#define FUSBH200_TUNE_FLS 1 /* (medium) 512-frame schedule */
-
-/* Initial IRQ latency: faster than hw default */
-static int log2_irq_thresh = 0; // 0 to 6
-module_param (log2_irq_thresh, int, S_IRUGO);
-MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
-
-/* initial park setting: slower than hw default */
-static unsigned park = 0;
-module_param (park, uint, S_IRUGO);
-MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
-
-/* for link power management(LPM) feature */
-static unsigned int hird;
-module_param(hird, int, S_IRUGO);
-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
-
-#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
-
-#include "fusbh200.h"
-
-/*-------------------------------------------------------------------------*/
-
-#define fusbh200_dbg(fusbh200, fmt, args...) \
- dev_dbg (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-#define fusbh200_err(fusbh200, fmt, args...) \
- dev_err (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-#define fusbh200_info(fusbh200, fmt, args...) \
- dev_info (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-#define fusbh200_warn(fusbh200, fmt, args...) \
- dev_warn (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-
-/* check the values in the HCSPARAMS register
- * (host controller _Structural_ parameters)
- * see EHCI spec, Table 2-4 for each value
- */
-static void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label)
-{
- u32 params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
-
- fusbh200_dbg (fusbh200,
- "%s hcs_params 0x%x ports=%d\n",
- label, params,
- HCS_N_PORTS (params)
- );
-}
-
-/* check the values in the HCCPARAMS register
- * (host controller _Capability_ parameters)
- * see EHCI Spec, Table 2-5 for each value
- * */
-static void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label)
-{
- u32 params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-
- fusbh200_dbg (fusbh200,
- "%s hcc_params %04x uframes %s%s\n",
- label,
- params,
- HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
- HCC_CANPARK(params) ? " park" : "");
-}
-
-static void __maybe_unused
-dbg_qtd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd)
-{
- fusbh200_dbg(fusbh200, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
- hc32_to_cpup(fusbh200, &qtd->hw_next),
- hc32_to_cpup(fusbh200, &qtd->hw_alt_next),
- hc32_to_cpup(fusbh200, &qtd->hw_token),
- hc32_to_cpup(fusbh200, &qtd->hw_buf [0]));
- if (qtd->hw_buf [1])
- fusbh200_dbg(fusbh200, " p1=%08x p2=%08x p3=%08x p4=%08x\n",
- hc32_to_cpup(fusbh200, &qtd->hw_buf[1]),
- hc32_to_cpup(fusbh200, &qtd->hw_buf[2]),
- hc32_to_cpup(fusbh200, &qtd->hw_buf[3]),
- hc32_to_cpup(fusbh200, &qtd->hw_buf[4]));
-}
-
-static void __maybe_unused
-dbg_qh (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- struct fusbh200_qh_hw *hw = qh->hw;
-
- fusbh200_dbg (fusbh200, "%s qh %p n%08x info %x %x qtd %x\n", label,
- qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
- dbg_qtd("overlay", fusbh200, (struct fusbh200_qtd *) &hw->hw_qtd_next);
-}
-
-static void __maybe_unused
-dbg_itd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd)
-{
- fusbh200_dbg (fusbh200, "%s [%d] itd %p, next %08x, urb %p\n",
- label, itd->frame, itd, hc32_to_cpu(fusbh200, itd->hw_next),
- itd->urb);
- fusbh200_dbg (fusbh200,
- " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
- hc32_to_cpu(fusbh200, itd->hw_transaction[0]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[1]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[2]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[3]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[4]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[5]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[6]),
- hc32_to_cpu(fusbh200, itd->hw_transaction[7]));
- fusbh200_dbg (fusbh200,
- " buf: %08x %08x %08x %08x %08x %08x %08x\n",
- hc32_to_cpu(fusbh200, itd->hw_bufp[0]),
- hc32_to_cpu(fusbh200, itd->hw_bufp[1]),
- hc32_to_cpu(fusbh200, itd->hw_bufp[2]),
- hc32_to_cpu(fusbh200, itd->hw_bufp[3]),
- hc32_to_cpu(fusbh200, itd->hw_bufp[4]),
- hc32_to_cpu(fusbh200, itd->hw_bufp[5]),
- hc32_to_cpu(fusbh200, itd->hw_bufp[6]));
- fusbh200_dbg (fusbh200, " index: %d %d %d %d %d %d %d %d\n",
- itd->index[0], itd->index[1], itd->index[2],
- itd->index[3], itd->index[4], itd->index[5],
- itd->index[6], itd->index[7]);
-}
-
-static int __maybe_unused
-dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
-{
- return scnprintf (buf, len,
- "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
- label, label [0] ? " " : "", status,
- (status & STS_ASS) ? " Async" : "",
- (status & STS_PSS) ? " Periodic" : "",
- (status & STS_RECL) ? " Recl" : "",
- (status & STS_HALT) ? " Halt" : "",
- (status & STS_IAA) ? " IAA" : "",
- (status & STS_FATAL) ? " FATAL" : "",
- (status & STS_FLR) ? " FLR" : "",
- (status & STS_PCD) ? " PCD" : "",
- (status & STS_ERR) ? " ERR" : "",
- (status & STS_INT) ? " INT" : ""
- );
-}
-
-static int __maybe_unused
-dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
-{
- return scnprintf (buf, len,
- "%s%sintrenable %02x%s%s%s%s%s%s",
- label, label [0] ? " " : "", enable,
- (enable & STS_IAA) ? " IAA" : "",
- (enable & STS_FATAL) ? " FATAL" : "",
- (enable & STS_FLR) ? " FLR" : "",
- (enable & STS_PCD) ? " PCD" : "",
- (enable & STS_ERR) ? " ERR" : "",
- (enable & STS_INT) ? " INT" : ""
- );
-}
-
-static const char *const fls_strings [] =
- { "1024", "512", "256", "??" };
-
-static int
-dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
-{
- return scnprintf (buf, len,
- "%s%scommand %07x %s=%d ithresh=%d%s%s%s "
- "period=%s%s %s",
- label, label [0] ? " " : "", command,
- (command & CMD_PARK) ? " park" : "(park)",
- CMD_PARK_CNT (command),
- (command >> 16) & 0x3f,
- (command & CMD_IAAD) ? " IAAD" : "",
- (command & CMD_ASE) ? " Async" : "",
- (command & CMD_PSE) ? " Periodic" : "",
- fls_strings [(command >> 2) & 0x3],
- (command & CMD_RESET) ? " Reset" : "",
- (command & CMD_RUN) ? "RUN" : "HALT"
- );
-}
-
-static int
-dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
-{
- char *sig;
-
- /* signaling state */
- switch (status & (3 << 10)) {
- case 0 << 10: sig = "se0"; break;
- case 1 << 10: sig = "k"; break; /* low speed */
- case 2 << 10: sig = "j"; break;
- default: sig = "?"; break;
- }
-
- return scnprintf (buf, len,
- "%s%sport:%d status %06x %d "
- "sig=%s%s%s%s%s%s%s%s",
- label, label [0] ? " " : "", port, status,
- status>>25,/*device address */
- sig,
- (status & PORT_RESET) ? " RESET" : "",
- (status & PORT_SUSPEND) ? " SUSPEND" : "",
- (status & PORT_RESUME) ? " RESUME" : "",
- (status & PORT_PEC) ? " PEC" : "",
- (status & PORT_PE) ? " PE" : "",
- (status & PORT_CSC) ? " CSC" : "",
- (status & PORT_CONNECT) ? " CONNECT" : "");
-}
-
-/* functions have the "wrong" filename when they're output... */
-#define dbg_status(fusbh200, label, status) { \
- char _buf [80]; \
- dbg_status_buf (_buf, sizeof _buf, label, status); \
- fusbh200_dbg (fusbh200, "%s\n", _buf); \
-}
-
-#define dbg_cmd(fusbh200, label, command) { \
- char _buf [80]; \
- dbg_command_buf (_buf, sizeof _buf, label, command); \
- fusbh200_dbg (fusbh200, "%s\n", _buf); \
-}
-
-#define dbg_port(fusbh200, label, port, status) { \
- char _buf [80]; \
- dbg_port_buf (_buf, sizeof _buf, label, port, status); \
- fusbh200_dbg (fusbh200, "%s\n", _buf); \
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* troubleshooting help: expose state in debugfs */
-
-static int debug_async_open(struct inode *, struct file *);
-static int debug_periodic_open(struct inode *, struct file *);
-static int debug_registers_open(struct inode *, struct file *);
-static int debug_async_open(struct inode *, struct file *);
-
-static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
-static int debug_close(struct inode *, struct file *);
-
-static const struct file_operations debug_async_fops = {
- .owner = THIS_MODULE,
- .open = debug_async_open,
- .read = debug_output,
- .release = debug_close,
- .llseek = default_llseek,
-};
-static const struct file_operations debug_periodic_fops = {
- .owner = THIS_MODULE,
- .open = debug_periodic_open,
- .read = debug_output,
- .release = debug_close,
- .llseek = default_llseek,
-};
-static const struct file_operations debug_registers_fops = {
- .owner = THIS_MODULE,
- .open = debug_registers_open,
- .read = debug_output,
- .release = debug_close,
- .llseek = default_llseek,
-};
-
-static struct dentry *fusbh200_debug_root;
-
-struct debug_buffer {
- ssize_t (*fill_func)(struct debug_buffer *); /* fill method */
- struct usb_bus *bus;
- struct mutex mutex; /* protect filling of buffer */
- size_t count; /* number of characters filled into buffer */
- char *output_buf;
- size_t alloc_size;
-};
-
-#define speed_char(info1) ({ char tmp; \
- switch (info1 & (3 << 12)) { \
- case QH_FULL_SPEED: tmp = 'f'; break; \
- case QH_LOW_SPEED: tmp = 'l'; break; \
- case QH_HIGH_SPEED: tmp = 'h'; break; \
- default: tmp = '?'; break; \
- } tmp; })
-
-static inline char token_mark(struct fusbh200_hcd *fusbh200, __hc32 token)
-{
- __u32 v = hc32_to_cpu(fusbh200, token);
-
- if (v & QTD_STS_ACTIVE)
- return '*';
- if (v & QTD_STS_HALT)
- return '-';
- if (!IS_SHORT_READ (v))
- return ' ';
- /* tries to advance through hw_alt_next */
- return '/';
-}
-
-static void qh_lines (
- struct fusbh200_hcd *fusbh200,
- struct fusbh200_qh *qh,
- char **nextp,
- unsigned *sizep
-)
-{
- u32 scratch;
- u32 hw_curr;
- struct fusbh200_qtd *td;
- unsigned temp;
- unsigned size = *sizep;
- char *next = *nextp;
- char mark;
- __le32 list_end = FUSBH200_LIST_END(fusbh200);
- struct fusbh200_qh_hw *hw = qh->hw;
-
- if (hw->hw_qtd_next == list_end) /* NEC does this */
- mark = '@';
- else
- mark = token_mark(fusbh200, hw->hw_token);
- if (mark == '/') { /* qh_alt_next controls qh advance? */
- if ((hw->hw_alt_next & QTD_MASK(fusbh200))
- == fusbh200->async->hw->hw_alt_next)
- mark = '#'; /* blocked */
- else if (hw->hw_alt_next == list_end)
- mark = '.'; /* use hw_qtd_next */
- /* else alt_next points to some other qtd */
- }
- scratch = hc32_to_cpup(fusbh200, &hw->hw_info1);
- hw_curr = (mark == '*') ? hc32_to_cpup(fusbh200, &hw->hw_current) : 0;
- temp = scnprintf (next, size,
- "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
- qh, scratch & 0x007f,
- speed_char (scratch),
- (scratch >> 8) & 0x000f,
- scratch, hc32_to_cpup(fusbh200, &hw->hw_info2),
- hc32_to_cpup(fusbh200, &hw->hw_token), mark,
- (cpu_to_hc32(fusbh200, QTD_TOGGLE) & hw->hw_token)
- ? "data1" : "data0",
- (hc32_to_cpup(fusbh200, &hw->hw_alt_next) >> 1) & 0x0f);
- size -= temp;
- next += temp;
-
- /* hc may be modifying the list as we read it ... */
- list_for_each_entry(td, &qh->qtd_list, qtd_list) {
- scratch = hc32_to_cpup(fusbh200, &td->hw_token);
- mark = ' ';
- if (hw_curr == td->qtd_dma)
- mark = '*';
- else if (hw->hw_qtd_next == cpu_to_hc32(fusbh200, td->qtd_dma))
- mark = '+';
- else if (QTD_LENGTH (scratch)) {
- if (td->hw_alt_next == fusbh200->async->hw->hw_alt_next)
- mark = '#';
- else if (td->hw_alt_next != list_end)
- mark = '/';
- }
- temp = snprintf (next, size,
- "\n\t%p%c%s len=%d %08x urb %p",
- td, mark, ({ char *tmp;
- switch ((scratch>>8)&0x03) {
- case 0: tmp = "out"; break;
- case 1: tmp = "in"; break;
- case 2: tmp = "setup"; break;
- default: tmp = "?"; break;
- } tmp;}),
- (scratch >> 16) & 0x7fff,
- scratch,
- td->urb);
- if (size < temp)
- temp = size;
- size -= temp;
- next += temp;
- if (temp == size)
- goto done;
- }
-
- temp = snprintf (next, size, "\n");
- if (size < temp)
- temp = size;
- size -= temp;
- next += temp;
-
-done:
- *sizep = size;
- *nextp = next;
-}
-
-static ssize_t fill_async_buffer(struct debug_buffer *buf)
-{
- struct usb_hcd *hcd;
- struct fusbh200_hcd *fusbh200;
- unsigned long flags;
- unsigned temp, size;
- char *next;
- struct fusbh200_qh *qh;
-
- hcd = bus_to_hcd(buf->bus);
- fusbh200 = hcd_to_fusbh200 (hcd);
- next = buf->output_buf;
- size = buf->alloc_size;
-
- *next = 0;
-
- /* dumps a snapshot of the async schedule.
- * usually empty except for long-term bulk reads, or head.
- * one QH per line, and TDs we know about
- */
- spin_lock_irqsave (&fusbh200->lock, flags);
- for (qh = fusbh200->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
- qh_lines (fusbh200, qh, &next, &size);
- if (fusbh200->async_unlink && size > 0) {
- temp = scnprintf(next, size, "\nunlink =\n");
- size -= temp;
- next += temp;
-
- for (qh = fusbh200->async_unlink; size > 0 && qh;
- qh = qh->unlink_next)
- qh_lines (fusbh200, qh, &next, &size);
- }
- spin_unlock_irqrestore (&fusbh200->lock, flags);
-
- return strlen(buf->output_buf);
-}
-
-#define DBG_SCHED_LIMIT 64
-static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
-{
- struct usb_hcd *hcd;
- struct fusbh200_hcd *fusbh200;
- unsigned long flags;
- union fusbh200_shadow p, *seen;
- unsigned temp, size, seen_count;
- char *next;
- unsigned i;
- __hc32 tag;
-
- seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC);
- if (!seen)
- return 0;
- seen_count = 0;
-
- hcd = bus_to_hcd(buf->bus);
- fusbh200 = hcd_to_fusbh200 (hcd);
- next = buf->output_buf;
- size = buf->alloc_size;
-
- temp = scnprintf (next, size, "size = %d\n", fusbh200->periodic_size);
- size -= temp;
- next += temp;
-
- /* dump a snapshot of the periodic schedule.
- * iso changes, interrupt usually doesn't.
- */
- spin_lock_irqsave (&fusbh200->lock, flags);
- for (i = 0; i < fusbh200->periodic_size; i++) {
- p = fusbh200->pshadow [i];
- if (likely (!p.ptr))
- continue;
- tag = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [i]);
-
- temp = scnprintf (next, size, "%4d: ", i);
- size -= temp;
- next += temp;
-
- do {
- struct fusbh200_qh_hw *hw;
-
- switch (hc32_to_cpu(fusbh200, tag)) {
- case Q_TYPE_QH:
- hw = p.qh->hw;
- temp = scnprintf (next, size, " qh%d-%04x/%p",
- p.qh->period,
- hc32_to_cpup(fusbh200,
- &hw->hw_info2)
- /* uframe masks */
- & (QH_CMASK | QH_SMASK),
- p.qh);
- size -= temp;
- next += temp;
- /* don't repeat what follows this qh */
- for (temp = 0; temp < seen_count; temp++) {
- if (seen [temp].ptr != p.ptr)
- continue;
- if (p.qh->qh_next.ptr) {
- temp = scnprintf (next, size,
- " ...");
- size -= temp;
- next += temp;
- }
- break;
- }
- /* show more info the first time around */
- if (temp == seen_count) {
- u32 scratch = hc32_to_cpup(fusbh200,
- &hw->hw_info1);
- struct fusbh200_qtd *qtd;
- char *type = "";
-
- /* count tds, get ep direction */
- temp = 0;
- list_for_each_entry (qtd,
- &p.qh->qtd_list,
- qtd_list) {
- temp++;
- switch (0x03 & (hc32_to_cpu(
- fusbh200,
- qtd->hw_token) >> 8)) {
- case 0: type = "out"; continue;
- case 1: type = "in"; continue;
- }
- }
-
- temp = scnprintf (next, size,
- " (%c%d ep%d%s "
- "[%d/%d] q%d p%d)",
- speed_char (scratch),
- scratch & 0x007f,
- (scratch >> 8) & 0x000f, type,
- p.qh->usecs, p.qh->c_usecs,
- temp,
- 0x7ff & (scratch >> 16));
-
- if (seen_count < DBG_SCHED_LIMIT)
- seen [seen_count++].qh = p.qh;
- } else
- temp = 0;
- tag = Q_NEXT_TYPE(fusbh200, hw->hw_next);
- p = p.qh->qh_next;
- break;
- case Q_TYPE_FSTN:
- temp = scnprintf (next, size,
- " fstn-%8x/%p", p.fstn->hw_prev,
- p.fstn);
- tag = Q_NEXT_TYPE(fusbh200, p.fstn->hw_next);
- p = p.fstn->fstn_next;
- break;
- case Q_TYPE_ITD:
- temp = scnprintf (next, size,
- " itd/%p", p.itd);
- tag = Q_NEXT_TYPE(fusbh200, p.itd->hw_next);
- p = p.itd->itd_next;
- break;
- }
- size -= temp;
- next += temp;
- } while (p.ptr);
-
- temp = scnprintf (next, size, "\n");
- size -= temp;
- next += temp;
- }
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- kfree (seen);
-
- return buf->alloc_size - size;
-}
-#undef DBG_SCHED_LIMIT
-
-static const char *rh_state_string(struct fusbh200_hcd *fusbh200)
-{
- switch (fusbh200->rh_state) {
- case FUSBH200_RH_HALTED:
- return "halted";
- case FUSBH200_RH_SUSPENDED:
- return "suspended";
- case FUSBH200_RH_RUNNING:
- return "running";
- case FUSBH200_RH_STOPPING:
- return "stopping";
- }
- return "?";
-}
-
-static ssize_t fill_registers_buffer(struct debug_buffer *buf)
-{
- struct usb_hcd *hcd;
- struct fusbh200_hcd *fusbh200;
- unsigned long flags;
- unsigned temp, size, i;
- char *next, scratch [80];
- static char fmt [] = "%*s\n";
- static char label [] = "";
-
- hcd = bus_to_hcd(buf->bus);
- fusbh200 = hcd_to_fusbh200 (hcd);
- next = buf->output_buf;
- size = buf->alloc_size;
-
- spin_lock_irqsave (&fusbh200->lock, flags);
-
- if (!HCD_HW_ACCESSIBLE(hcd)) {
- size = scnprintf (next, size,
- "bus %s, device %s\n"
- "%s\n"
- "SUSPENDED (no register access)\n",
- hcd->self.controller->bus->name,
- dev_name(hcd->self.controller),
- hcd->product_desc);
- goto done;
- }
-
- /* Capability Registers */
- i = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
- temp = scnprintf (next, size,
- "bus %s, device %s\n"
- "%s\n"
- "EHCI %x.%02x, rh state %s\n",
- hcd->self.controller->bus->name,
- dev_name(hcd->self.controller),
- hcd->product_desc,
- i >> 8, i & 0x0ff, rh_state_string(fusbh200));
- size -= temp;
- next += temp;
-
- // FIXME interpret both types of params
- i = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
- temp = scnprintf (next, size, "structural params 0x%08x\n", i);
- size -= temp;
- next += temp;
-
- i = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
- temp = scnprintf (next, size, "capability params 0x%08x\n", i);
- size -= temp;
- next += temp;
-
- /* Operational Registers */
- temp = dbg_status_buf (scratch, sizeof scratch, label,
- fusbh200_readl(fusbh200, &fusbh200->regs->status));
- temp = scnprintf (next, size, fmt, temp, scratch);
- size -= temp;
- next += temp;
-
- temp = dbg_command_buf (scratch, sizeof scratch, label,
- fusbh200_readl(fusbh200, &fusbh200->regs->command));
- temp = scnprintf (next, size, fmt, temp, scratch);
- size -= temp;
- next += temp;
-
- temp = dbg_intr_buf (scratch, sizeof scratch, label,
- fusbh200_readl(fusbh200, &fusbh200->regs->intr_enable));
- temp = scnprintf (next, size, fmt, temp, scratch);
- size -= temp;
- next += temp;
-
- temp = scnprintf (next, size, "uframe %04x\n",
- fusbh200_read_frame_index(fusbh200));
- size -= temp;
- next += temp;
-
- if (fusbh200->async_unlink) {
- temp = scnprintf(next, size, "async unlink qh %p\n",
- fusbh200->async_unlink);
- size -= temp;
- next += temp;
- }
-
- temp = scnprintf (next, size,
- "irq normal %ld err %ld iaa %ld (lost %ld)\n",
- fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa,
- fusbh200->stats.lost_iaa);
- size -= temp;
- next += temp;
-
- temp = scnprintf (next, size, "complete %ld unlink %ld\n",
- fusbh200->stats.complete, fusbh200->stats.unlink);
- size -= temp;
- next += temp;
-
-done:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
-
- return buf->alloc_size - size;
-}
-
-static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
- ssize_t (*fill_func)(struct debug_buffer *))
-{
- struct debug_buffer *buf;
-
- buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
-
- if (buf) {
- buf->bus = bus;
- buf->fill_func = fill_func;
- mutex_init(&buf->mutex);
- buf->alloc_size = PAGE_SIZE;
- }
-
- return buf;
-}
-
-static int fill_buffer(struct debug_buffer *buf)
-{
- int ret = 0;
-
- if (!buf->output_buf)
- buf->output_buf = vmalloc(buf->alloc_size);
-
- if (!buf->output_buf) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = buf->fill_func(buf);
-
- if (ret >= 0) {
- buf->count = ret;
- ret = 0;
- }
-
-out:
- return ret;
-}
-
-static ssize_t debug_output(struct file *file, char __user *user_buf,
- size_t len, loff_t *offset)
-{
- struct debug_buffer *buf = file->private_data;
- int ret = 0;
-
- mutex_lock(&buf->mutex);
- if (buf->count == 0) {
- ret = fill_buffer(buf);
- if (ret != 0) {
- mutex_unlock(&buf->mutex);
- goto out;
- }
- }
- mutex_unlock(&buf->mutex);
-
- ret = simple_read_from_buffer(user_buf, len, offset,
- buf->output_buf, buf->count);
-
-out:
- return ret;
-
-}
-
-static int debug_close(struct inode *inode, struct file *file)
-{
- struct debug_buffer *buf = file->private_data;
-
- if (buf) {
- vfree(buf->output_buf);
- kfree(buf);
- }
-
- return 0;
-}
-static int debug_async_open(struct inode *inode, struct file *file)
-{
- file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
-
- return file->private_data ? 0 : -ENOMEM;
-}
-
-static int debug_periodic_open(struct inode *inode, struct file *file)
-{
- struct debug_buffer *buf;
- buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
- if (!buf)
- return -ENOMEM;
-
- buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE;
- file->private_data = buf;
- return 0;
-}
-
-static int debug_registers_open(struct inode *inode, struct file *file)
-{
- file->private_data = alloc_buffer(inode->i_private,
- fill_registers_buffer);
-
- return file->private_data ? 0 : -ENOMEM;
-}
-
-static inline void create_debug_files (struct fusbh200_hcd *fusbh200)
-{
- struct usb_bus *bus = &fusbh200_to_hcd(fusbh200)->self;
-
- fusbh200->debug_dir = debugfs_create_dir(bus->bus_name, fusbh200_debug_root);
- if (!fusbh200->debug_dir)
- return;
-
- if (!debugfs_create_file("async", S_IRUGO, fusbh200->debug_dir, bus,
- &debug_async_fops))
- goto file_error;
-
- if (!debugfs_create_file("periodic", S_IRUGO, fusbh200->debug_dir, bus,
- &debug_periodic_fops))
- goto file_error;
-
- if (!debugfs_create_file("registers", S_IRUGO, fusbh200->debug_dir, bus,
- &debug_registers_fops))
- goto file_error;
-
- return;
-
-file_error:
- debugfs_remove_recursive(fusbh200->debug_dir);
-}
-
-static inline void remove_debug_files (struct fusbh200_hcd *fusbh200)
-{
- debugfs_remove_recursive(fusbh200->debug_dir);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * handshake - spin reading hc until handshake completes or fails
- * @ptr: address of hc register to be read
- * @mask: bits to look at in result of read
- * @done: value of those bits when handshake succeeds
- * @usec: timeout in microseconds
- *
- * Returns negative errno, or zero on success
- *
- * Success happens when the "mask" bits have the specified value (hardware
- * handshake done). There are two failure modes: "usec" have passed (major
- * hardware flakeout), or the register reads as all-ones (hardware removed).
- *
- * That last failure should_only happen in cases like physical cardbus eject
- * before driver shutdown. But it also seems to be caused by bugs in cardbus
- * bridge shutdown: shutting down the bridge before the devices using it.
- */
-static int handshake (struct fusbh200_hcd *fusbh200, void __iomem *ptr,
- u32 mask, u32 done, int usec)
-{
- u32 result;
-
- do {
- result = fusbh200_readl(fusbh200, ptr);
- if (result == ~(u32)0) /* card removed */
- return -ENODEV;
- result &= mask;
- if (result == done)
- return 0;
- udelay (1);
- usec--;
- } while (usec > 0);
- return -ETIMEDOUT;
-}
-
-/*
- * Force HC to halt state from unknown (EHCI spec section 2.3).
- * Must be called with interrupts enabled and the lock not held.
- */
-static int fusbh200_halt (struct fusbh200_hcd *fusbh200)
-{
- u32 temp;
-
- spin_lock_irq(&fusbh200->lock);
-
- /* disable any irqs left enabled by previous code */
- fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
-
- /*
- * This routine gets called during probe before fusbh200->command
- * has been initialized, so we can't rely on its value.
- */
- fusbh200->command &= ~CMD_RUN;
- temp = fusbh200_readl(fusbh200, &fusbh200->regs->command);
- temp &= ~(CMD_RUN | CMD_IAAD);
- fusbh200_writel(fusbh200, temp, &fusbh200->regs->command);
-
- spin_unlock_irq(&fusbh200->lock);
- synchronize_irq(fusbh200_to_hcd(fusbh200)->irq);
-
- return handshake(fusbh200, &fusbh200->regs->status,
- STS_HALT, STS_HALT, 16 * 125);
-}
-
-/*
- * Reset a non-running (STS_HALT == 1) controller.
- * Must be called with interrupts enabled and the lock not held.
- */
-static int fusbh200_reset (struct fusbh200_hcd *fusbh200)
-{
- int retval;
- u32 command = fusbh200_readl(fusbh200, &fusbh200->regs->command);
-
- /* If the EHCI debug controller is active, special care must be
- * taken before and after a host controller reset */
- if (fusbh200->debug && !dbgp_reset_prep(fusbh200_to_hcd(fusbh200)))
- fusbh200->debug = NULL;
-
- command |= CMD_RESET;
- dbg_cmd (fusbh200, "reset", command);
- fusbh200_writel(fusbh200, command, &fusbh200->regs->command);
- fusbh200->rh_state = FUSBH200_RH_HALTED;
- fusbh200->next_statechange = jiffies;
- retval = handshake (fusbh200, &fusbh200->regs->command,
- CMD_RESET, 0, 250 * 1000);
-
- if (retval)
- return retval;
-
- if (fusbh200->debug)
- dbgp_external_startup(fusbh200_to_hcd(fusbh200));
-
- fusbh200->port_c_suspend = fusbh200->suspended_ports =
- fusbh200->resuming_ports = 0;
- return retval;
-}
-
-/*
- * Idle the controller (turn off the schedules).
- * Must be called with interrupts enabled and the lock not held.
- */
-static void fusbh200_quiesce (struct fusbh200_hcd *fusbh200)
-{
- u32 temp;
-
- if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
- return;
-
- /* wait for any schedule enables/disables to take effect */
- temp = (fusbh200->command << 10) & (STS_ASS | STS_PSS);
- handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
-
- /* then disable anything that's still active */
- spin_lock_irq(&fusbh200->lock);
- fusbh200->command &= ~(CMD_ASE | CMD_PSE);
- fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
- spin_unlock_irq(&fusbh200->lock);
-
- /* hardware can take 16 microframes to turn off ... */
- handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void end_unlink_async(struct fusbh200_hcd *fusbh200);
-static void unlink_empty_async(struct fusbh200_hcd *fusbh200);
-static void fusbh200_work(struct fusbh200_hcd *fusbh200);
-static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-
-/*-------------------------------------------------------------------------*/
-
-/* Set a bit in the USBCMD register */
-static void fusbh200_set_command_bit(struct fusbh200_hcd *fusbh200, u32 bit)
-{
- fusbh200->command |= bit;
- fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-
- /* unblock posted write */
- fusbh200_readl(fusbh200, &fusbh200->regs->command);
-}
-
-/* Clear a bit in the USBCMD register */
-static void fusbh200_clear_command_bit(struct fusbh200_hcd *fusbh200, u32 bit)
-{
- fusbh200->command &= ~bit;
- fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-
- /* unblock posted write */
- fusbh200_readl(fusbh200, &fusbh200->regs->command);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI timer support... Now using hrtimers.
- *
- * Lots of different events are triggered from fusbh200->hrtimer. Whenever
- * the timer routine runs, it checks each possible event; events that are
- * currently enabled and whose expiration time has passed get handled.
- * The set of enabled events is stored as a collection of bitflags in
- * fusbh200->enabled_hrtimer_events, and they are numbered in order of
- * increasing delay values (ranging between 1 ms and 100 ms).
- *
- * Rather than implementing a sorted list or tree of all pending events,
- * we keep track only of the lowest-numbered pending event, in
- * fusbh200->next_hrtimer_event. Whenever fusbh200->hrtimer gets restarted, its
- * expiration time is set to the timeout value for this event.
- *
- * As a result, events might not get handled right away; the actual delay
- * could be anywhere up to twice the requested delay. This doesn't
- * matter, because none of the events are especially time-critical. The
- * ones that matter most all have a delay of 1 ms, so they will be
- * handled after 2 ms at most, which is okay. In addition to this, we
- * allow for an expiration range of 1 ms.
- */
-
-/*
- * Delay lengths for the hrtimer event types.
- * Keep this list sorted by delay length, in the same order as
- * the event types indexed by enum fusbh200_hrtimer_event in fusbh200.h.
- */
-static unsigned event_delays_ns[] = {
- 1 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_POLL_ASS */
- 1 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_POLL_PSS */
- 1 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_POLL_DEAD */
- 1125 * NSEC_PER_USEC, /* FUSBH200_HRTIMER_UNLINK_INTR */
- 2 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_FREE_ITDS */
- 6 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_ASYNC_UNLINKS */
- 10 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_IAA_WATCHDOG */
- 10 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_DISABLE_PERIODIC */
- 15 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_DISABLE_ASYNC */
- 100 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_IO_WATCHDOG */
-};
-
-/* Enable a pending hrtimer event */
-static void fusbh200_enable_event(struct fusbh200_hcd *fusbh200, unsigned event,
- bool resched)
-{
- ktime_t *timeout = &fusbh200->hr_timeouts[event];
-
- if (resched)
- *timeout = ktime_add(ktime_get(),
- ktime_set(0, event_delays_ns[event]));
- fusbh200->enabled_hrtimer_events |= (1 << event);
-
- /* Track only the lowest-numbered pending event */
- if (event < fusbh200->next_hrtimer_event) {
- fusbh200->next_hrtimer_event = event;
- hrtimer_start_range_ns(&fusbh200->hrtimer, *timeout,
- NSEC_PER_MSEC, HRTIMER_MODE_ABS);
- }
-}
-
-
-/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */
-static void fusbh200_poll_ASS(struct fusbh200_hcd *fusbh200)
-{
- unsigned actual, want;
-
- /* Don't enable anything if the controller isn't running (e.g., died) */
- if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
- return;
-
- want = (fusbh200->command & CMD_ASE) ? STS_ASS : 0;
- actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_ASS;
-
- if (want != actual) {
-
- /* Poll again later, but give up after about 20 ms */
- if (fusbh200->ASS_poll_count++ < 20) {
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_ASS, true);
- return;
- }
- fusbh200_dbg(fusbh200, "Waited too long for the async schedule status (%x/%x), giving up\n",
- want, actual);
- }
- fusbh200->ASS_poll_count = 0;
-
- /* The status is up-to-date; restart or stop the schedule as needed */
- if (want == 0) { /* Stopped */
- if (fusbh200->async_count > 0)
- fusbh200_set_command_bit(fusbh200, CMD_ASE);
-
- } else { /* Running */
- if (fusbh200->async_count == 0) {
-
- /* Turn off the schedule after a while */
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_ASYNC,
- true);
- }
- }
-}
-
-/* Turn off the async schedule after a brief delay */
-static void fusbh200_disable_ASE(struct fusbh200_hcd *fusbh200)
-{
- fusbh200_clear_command_bit(fusbh200, CMD_ASE);
-}
-
-
-/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
-static void fusbh200_poll_PSS(struct fusbh200_hcd *fusbh200)
-{
- unsigned actual, want;
-
- /* Don't do anything if the controller isn't running (e.g., died) */
- if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
- return;
-
- want = (fusbh200->command & CMD_PSE) ? STS_PSS : 0;
- actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_PSS;
-
- if (want != actual) {
-
- /* Poll again later, but give up after about 20 ms */
- if (fusbh200->PSS_poll_count++ < 20) {
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_PSS, true);
- return;
- }
- fusbh200_dbg(fusbh200, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
- want, actual);
- }
- fusbh200->PSS_poll_count = 0;
-
- /* The status is up-to-date; restart or stop the schedule as needed */
- if (want == 0) { /* Stopped */
- if (fusbh200->periodic_count > 0)
- fusbh200_set_command_bit(fusbh200, CMD_PSE);
-
- } else { /* Running */
- if (fusbh200->periodic_count == 0) {
-
- /* Turn off the schedule after a while */
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_PERIODIC,
- true);
- }
- }
-}
-
-/* Turn off the periodic schedule after a brief delay */
-static void fusbh200_disable_PSE(struct fusbh200_hcd *fusbh200)
-{
- fusbh200_clear_command_bit(fusbh200, CMD_PSE);
-}
-
-
-/* Poll the STS_HALT status bit; see when a dead controller stops */
-static void fusbh200_handle_controller_death(struct fusbh200_hcd *fusbh200)
-{
- if (!(fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_HALT)) {
-
- /* Give up after a few milliseconds */
- if (fusbh200->died_poll_count++ < 5) {
- /* Try again later */
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_DEAD, true);
- return;
- }
- fusbh200_warn(fusbh200, "Waited too long for the controller to stop, giving up\n");
- }
-
- /* Clean up the mess */
- fusbh200->rh_state = FUSBH200_RH_HALTED;
- fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
- fusbh200_work(fusbh200);
- end_unlink_async(fusbh200);
-
- /* Not in process context, so don't try to reset the controller */
-}
-
-
-/* Handle unlinked interrupt QHs once they are gone from the hardware */
-static void fusbh200_handle_intr_unlinks(struct fusbh200_hcd *fusbh200)
-{
- bool stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING);
-
- /*
- * Process all the QHs on the intr_unlink list that were added
- * before the current unlink cycle began. The list is in
- * temporal order, so stop when we reach the first entry in the
- * current cycle. But if the root hub isn't running then
- * process all the QHs on the list.
- */
- fusbh200->intr_unlinking = true;
- while (fusbh200->intr_unlink) {
- struct fusbh200_qh *qh = fusbh200->intr_unlink;
-
- if (!stopped && qh->unlink_cycle == fusbh200->intr_unlink_cycle)
- break;
- fusbh200->intr_unlink = qh->unlink_next;
- qh->unlink_next = NULL;
- end_unlink_intr(fusbh200, qh);
- }
-
- /* Handle remaining entries later */
- if (fusbh200->intr_unlink) {
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true);
- ++fusbh200->intr_unlink_cycle;
- }
- fusbh200->intr_unlinking = false;
-}
-
-
-/* Start another free-iTDs/siTDs cycle */
-static void start_free_itds(struct fusbh200_hcd *fusbh200)
-{
- if (!(fusbh200->enabled_hrtimer_events & BIT(FUSBH200_HRTIMER_FREE_ITDS))) {
- fusbh200->last_itd_to_free = list_entry(
- fusbh200->cached_itd_list.prev,
- struct fusbh200_itd, itd_list);
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_FREE_ITDS, true);
- }
-}
-
-/* Wait for controller to stop using old iTDs and siTDs */
-static void end_free_itds(struct fusbh200_hcd *fusbh200)
-{
- struct fusbh200_itd *itd, *n;
-
- if (fusbh200->rh_state < FUSBH200_RH_RUNNING) {
- fusbh200->last_itd_to_free = NULL;
- }
-
- list_for_each_entry_safe(itd, n, &fusbh200->cached_itd_list, itd_list) {
- list_del(&itd->itd_list);
- dma_pool_free(fusbh200->itd_pool, itd, itd->itd_dma);
- if (itd == fusbh200->last_itd_to_free)
- break;
- }
-
- if (!list_empty(&fusbh200->cached_itd_list))
- start_free_itds(fusbh200);
-}
-
-
-/* Handle lost (or very late) IAA interrupts */
-static void fusbh200_iaa_watchdog(struct fusbh200_hcd *fusbh200)
-{
- if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
- return;
-
- /*
- * Lost IAA irqs wedge things badly; seen first with a vt8235.
- * So we need this watchdog, but must protect it against both
- * (a) SMP races against real IAA firing and retriggering, and
- * (b) clean HC shutdown, when IAA watchdog was pending.
- */
- if (fusbh200->async_iaa) {
- u32 cmd, status;
-
- /* If we get here, IAA is *REALLY* late. It's barely
- * conceivable that the system is so busy that CMD_IAAD
- * is still legitimately set, so let's be sure it's
- * clear before we read STS_IAA. (The HC should clear
- * CMD_IAAD when it sets STS_IAA.)
- */
- cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command);
-
- /*
- * If IAA is set here it either legitimately triggered
- * after the watchdog timer expired (_way_ late, so we'll
- * still count it as lost) ... or a silicon erratum:
- * - VIA seems to set IAA without triggering the IRQ;
- * - IAAD potentially cleared without setting IAA.
- */
- status = fusbh200_readl(fusbh200, &fusbh200->regs->status);
- if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
- COUNT(fusbh200->stats.lost_iaa);
- fusbh200_writel(fusbh200, STS_IAA, &fusbh200->regs->status);
- }
-
- fusbh200_dbg(fusbh200, "IAA watchdog: status %x cmd %x\n",
- status, cmd);
- end_unlink_async(fusbh200);
- }
-}
-
-
-/* Enable the I/O watchdog, if appropriate */
-static void turn_on_io_watchdog(struct fusbh200_hcd *fusbh200)
-{
- /* Not needed if the controller isn't running or it's already enabled */
- if (fusbh200->rh_state != FUSBH200_RH_RUNNING ||
- (fusbh200->enabled_hrtimer_events &
- BIT(FUSBH200_HRTIMER_IO_WATCHDOG)))
- return;
-
- /*
- * Isochronous transfers always need the watchdog.
- * For other sorts we use it only if the flag is set.
- */
- if (fusbh200->isoc_count > 0 || (fusbh200->need_io_watchdog &&
- fusbh200->async_count + fusbh200->intr_count > 0))
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IO_WATCHDOG, true);
-}
-
-
-/*
- * Handler functions for the hrtimer event types.
- * Keep this array in the same order as the event types indexed by
- * enum fusbh200_hrtimer_event in fusbh200.h.
- */
-static void (*event_handlers[])(struct fusbh200_hcd *) = {
- fusbh200_poll_ASS, /* FUSBH200_HRTIMER_POLL_ASS */
- fusbh200_poll_PSS, /* FUSBH200_HRTIMER_POLL_PSS */
- fusbh200_handle_controller_death, /* FUSBH200_HRTIMER_POLL_DEAD */
- fusbh200_handle_intr_unlinks, /* FUSBH200_HRTIMER_UNLINK_INTR */
- end_free_itds, /* FUSBH200_HRTIMER_FREE_ITDS */
- unlink_empty_async, /* FUSBH200_HRTIMER_ASYNC_UNLINKS */
- fusbh200_iaa_watchdog, /* FUSBH200_HRTIMER_IAA_WATCHDOG */
- fusbh200_disable_PSE, /* FUSBH200_HRTIMER_DISABLE_PERIODIC */
- fusbh200_disable_ASE, /* FUSBH200_HRTIMER_DISABLE_ASYNC */
- fusbh200_work, /* FUSBH200_HRTIMER_IO_WATCHDOG */
-};
-
-static enum hrtimer_restart fusbh200_hrtimer_func(struct hrtimer *t)
-{
- struct fusbh200_hcd *fusbh200 = container_of(t, struct fusbh200_hcd, hrtimer);
- ktime_t now;
- unsigned long events;
- unsigned long flags;
- unsigned e;
-
- spin_lock_irqsave(&fusbh200->lock, flags);
-
- events = fusbh200->enabled_hrtimer_events;
- fusbh200->enabled_hrtimer_events = 0;
- fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT;
-
- /*
- * Check each pending event. If its time has expired, handle
- * the event; otherwise re-enable it.
- */
- now = ktime_get();
- for_each_set_bit(e, &events, FUSBH200_HRTIMER_NUM_EVENTS) {
- if (now.tv64 >= fusbh200->hr_timeouts[e].tv64)
- event_handlers[e](fusbh200);
- else
- fusbh200_enable_event(fusbh200, e, false);
- }
-
- spin_unlock_irqrestore(&fusbh200->lock, flags);
- return HRTIMER_NORESTART;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define fusbh200_bus_suspend NULL
-#define fusbh200_bus_resume NULL
-
-/*-------------------------------------------------------------------------*/
-
-static int check_reset_complete (
- struct fusbh200_hcd *fusbh200,
- int index,
- u32 __iomem *status_reg,
- int port_status
-) {
- if (!(port_status & PORT_CONNECT))
- return port_status;
-
- /* if reset finished and it's still not enabled -- handoff */
- if (!(port_status & PORT_PE)) {
- /* with integrated TT, there's nobody to hand it to! */
- fusbh200_dbg (fusbh200,
- "Failed to enable port %d on root hub TT\n",
- index+1);
- return port_status;
- } else {
- fusbh200_dbg(fusbh200, "port %d reset complete, port enabled\n",
- index + 1);
- }
-
- return port_status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-
-/* build "status change" packet (one or two bytes) from HC registers */
-
-static int
-fusbh200_hub_status_data (struct usb_hcd *hcd, char *buf)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- u32 temp, status;
- u32 mask;
- int retval = 1;
- unsigned long flags;
-
- /* init status to no-changes */
- buf [0] = 0;
-
- /* Inform the core about resumes-in-progress by returning
- * a non-zero value even if there are no status changes.
- */
- status = fusbh200->resuming_ports;
-
- mask = PORT_CSC | PORT_PEC;
- // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
-
- /* no hub change reports (bit 0) for now (power, ...) */
-
- /* port N changes (bit N)? */
- spin_lock_irqsave (&fusbh200->lock, flags);
-
- temp = fusbh200_readl(fusbh200, &fusbh200->regs->port_status);
-
- /*
- * Return status information even for ports with OWNER set.
- * Otherwise hub_wq wouldn't see the disconnect event when a
- * high-speed device is switched over to the companion
- * controller by the user.
- */
-
- if ((temp & mask) != 0 || test_bit(0, &fusbh200->port_c_suspend)
- || (fusbh200->reset_done[0] && time_after_eq(
- jiffies, fusbh200->reset_done[0]))) {
- buf [0] |= 1 << 1;
- status = STS_PCD;
- }
- /* FIXME autosuspend idle root hubs */
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- return status ? retval : 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-fusbh200_hub_descriptor (
- struct fusbh200_hcd *fusbh200,
- struct usb_hub_descriptor *desc
-) {
- int ports = HCS_N_PORTS (fusbh200->hcs_params);
- u16 temp;
-
- desc->bDescriptorType = USB_DT_HUB;
- desc->bPwrOn2PwrGood = 10; /* fusbh200 1.0, 2.3.9 says 20ms max */
- desc->bHubContrCurrent = 0;
-
- desc->bNbrPorts = ports;
- temp = 1 + (ports / 8);
- desc->bDescLength = 7 + 2 * temp;
-
- /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
- memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
- memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
-
- temp = HUB_CHAR_INDV_PORT_OCPM; /* per-port overcurrent reporting */
- temp |= HUB_CHAR_NO_LPSM; /* no power switching */
- desc->wHubCharacteristics = cpu_to_le16(temp);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int fusbh200_hub_control (
- struct usb_hcd *hcd,
- u16 typeReq,
- u16 wValue,
- u16 wIndex,
- char *buf,
- u16 wLength
-) {
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- int ports = HCS_N_PORTS (fusbh200->hcs_params);
- u32 __iomem *status_reg = &fusbh200->regs->port_status;
- u32 temp, temp1, status;
- unsigned long flags;
- int retval = 0;
- unsigned selector;
-
- /*
- * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
- * HCS_INDICATOR may say we can change LEDs to off/amber/green.
- * (track current state ourselves) ... blink for diagnostics,
- * power, "this is the one", etc. EHCI spec supports this.
- */
-
- spin_lock_irqsave (&fusbh200->lock, flags);
- switch (typeReq) {
- case ClearHubFeature:
- switch (wValue) {
- case C_HUB_LOCAL_POWER:
- case C_HUB_OVER_CURRENT:
- /* no hub-wide feature/status flags */
- break;
- default:
- goto error;
- }
- break;
- case ClearPortFeature:
- if (!wIndex || wIndex > ports)
- goto error;
- wIndex--;
- temp = fusbh200_readl(fusbh200, status_reg);
- temp &= ~PORT_RWC_BITS;
-
- /*
- * Even if OWNER is set, so the port is owned by the
- * companion controller, hub_wq needs to be able to clear
- * the port-change status bits (especially
- * USB_PORT_STAT_C_CONNECTION).
- */
-
- switch (wValue) {
- case USB_PORT_FEAT_ENABLE:
- fusbh200_writel(fusbh200, temp & ~PORT_PE, status_reg);
- break;
- case USB_PORT_FEAT_C_ENABLE:
- fusbh200_writel(fusbh200, temp | PORT_PEC, status_reg);
- break;
- case USB_PORT_FEAT_SUSPEND:
- if (temp & PORT_RESET)
- goto error;
- if (!(temp & PORT_SUSPEND))
- break;
- if ((temp & PORT_PE) == 0)
- goto error;
-
- fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
- fusbh200->reset_done[wIndex] = jiffies
- + msecs_to_jiffies(USB_RESUME_TIMEOUT);
- break;
- case USB_PORT_FEAT_C_SUSPEND:
- clear_bit(wIndex, &fusbh200->port_c_suspend);
- break;
- case USB_PORT_FEAT_C_CONNECTION:
- fusbh200_writel(fusbh200, temp | PORT_CSC, status_reg);
- break;
- case USB_PORT_FEAT_C_OVER_CURRENT:
- fusbh200_writel(fusbh200, temp | BMISR_OVC, &fusbh200->regs->bmisr);
- break;
- case USB_PORT_FEAT_C_RESET:
- /* GetPortStatus clears reset */
- break;
- default:
- goto error;
- }
- fusbh200_readl(fusbh200, &fusbh200->regs->command); /* unblock posted write */
- break;
- case GetHubDescriptor:
- fusbh200_hub_descriptor (fusbh200, (struct usb_hub_descriptor *)
- buf);
- break;
- case GetHubStatus:
- /* no hub-wide feature/status flags */
- memset (buf, 0, 4);
- //cpu_to_le32s ((u32 *) buf);
- break;
- case GetPortStatus:
- if (!wIndex || wIndex > ports)
- goto error;
- wIndex--;
- status = 0;
- temp = fusbh200_readl(fusbh200, status_reg);
-
- // wPortChange bits
- if (temp & PORT_CSC)
- status |= USB_PORT_STAT_C_CONNECTION << 16;
- if (temp & PORT_PEC)
- status |= USB_PORT_STAT_C_ENABLE << 16;
-
- temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr);
- if (temp1 & BMISR_OVC)
- status |= USB_PORT_STAT_C_OVERCURRENT << 16;
-
- /* whoever resumes must GetPortStatus to complete it!! */
- if (temp & PORT_RESUME) {
-
- /* Remote Wakeup received? */
- if (!fusbh200->reset_done[wIndex]) {
- /* resume signaling for 20 msec */
- fusbh200->reset_done[wIndex] = jiffies
- + msecs_to_jiffies(20);
- /* check the port again */
- mod_timer(&fusbh200_to_hcd(fusbh200)->rh_timer,
- fusbh200->reset_done[wIndex]);
- }
-
- /* resume completed? */
- else if (time_after_eq(jiffies,
- fusbh200->reset_done[wIndex])) {
- clear_bit(wIndex, &fusbh200->suspended_ports);
- set_bit(wIndex, &fusbh200->port_c_suspend);
- fusbh200->reset_done[wIndex] = 0;
-
- /* stop resume signaling */
- temp = fusbh200_readl(fusbh200, status_reg);
- fusbh200_writel(fusbh200,
- temp & ~(PORT_RWC_BITS | PORT_RESUME),
- status_reg);
- clear_bit(wIndex, &fusbh200->resuming_ports);
- retval = handshake(fusbh200, status_reg,
- PORT_RESUME, 0, 2000 /* 2msec */);
- if (retval != 0) {
- fusbh200_err(fusbh200,
- "port %d resume error %d\n",
- wIndex + 1, retval);
- goto error;
- }
- temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
- }
- }
-
- /* whoever resets must GetPortStatus to complete it!! */
- if ((temp & PORT_RESET)
- && time_after_eq(jiffies,
- fusbh200->reset_done[wIndex])) {
- status |= USB_PORT_STAT_C_RESET << 16;
- fusbh200->reset_done [wIndex] = 0;
- clear_bit(wIndex, &fusbh200->resuming_ports);
-
- /* force reset to complete */
- fusbh200_writel(fusbh200, temp & ~(PORT_RWC_BITS | PORT_RESET),
- status_reg);
- /* REVISIT: some hardware needs 550+ usec to clear
- * this bit; seems too long to spin routinely...
- */
- retval = handshake(fusbh200, status_reg,
- PORT_RESET, 0, 1000);
- if (retval != 0) {
- fusbh200_err (fusbh200, "port %d reset error %d\n",
- wIndex + 1, retval);
- goto error;
- }
-
- /* see what we found out */
- temp = check_reset_complete (fusbh200, wIndex, status_reg,
- fusbh200_readl(fusbh200, status_reg));
- }
-
- if (!(temp & (PORT_RESUME|PORT_RESET))) {
- fusbh200->reset_done[wIndex] = 0;
- clear_bit(wIndex, &fusbh200->resuming_ports);
- }
-
- /* transfer dedicated ports to the companion hc */
- if ((temp & PORT_CONNECT) &&
- test_bit(wIndex, &fusbh200->companion_ports)) {
- temp &= ~PORT_RWC_BITS;
- fusbh200_writel(fusbh200, temp, status_reg);
- fusbh200_dbg(fusbh200, "port %d --> companion\n", wIndex + 1);
- temp = fusbh200_readl(fusbh200, status_reg);
- }
-
- /*
- * Even if OWNER is set, there's no harm letting hub_wq
- * see the wPortStatus values (they should all be 0 except
- * for PORT_POWER anyway).
- */
-
- if (temp & PORT_CONNECT) {
- status |= USB_PORT_STAT_CONNECTION;
- status |= fusbh200_port_speed(fusbh200, temp);
- }
- if (temp & PORT_PE)
- status |= USB_PORT_STAT_ENABLE;
-
- /* maybe the port was unsuspended without our knowledge */
- if (temp & (PORT_SUSPEND|PORT_RESUME)) {
- status |= USB_PORT_STAT_SUSPEND;
- } else if (test_bit(wIndex, &fusbh200->suspended_ports)) {
- clear_bit(wIndex, &fusbh200->suspended_ports);
- clear_bit(wIndex, &fusbh200->resuming_ports);
- fusbh200->reset_done[wIndex] = 0;
- if (temp & PORT_PE)
- set_bit(wIndex, &fusbh200->port_c_suspend);
- }
-
- temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr);
- if (temp1 & BMISR_OVC)
- status |= USB_PORT_STAT_OVERCURRENT;
- if (temp & PORT_RESET)
- status |= USB_PORT_STAT_RESET;
- if (test_bit(wIndex, &fusbh200->port_c_suspend))
- status |= USB_PORT_STAT_C_SUSPEND << 16;
-
- if (status & ~0xffff) /* only if wPortChange is interesting */
- dbg_port(fusbh200, "GetStatus", wIndex + 1, temp);
- put_unaligned_le32(status, buf);
- break;
- case SetHubFeature:
- switch (wValue) {
- case C_HUB_LOCAL_POWER:
- case C_HUB_OVER_CURRENT:
- /* no hub-wide feature/status flags */
- break;
- default:
- goto error;
- }
- break;
- case SetPortFeature:
- selector = wIndex >> 8;
- wIndex &= 0xff;
-
- if (!wIndex || wIndex > ports)
- goto error;
- wIndex--;
- temp = fusbh200_readl(fusbh200, status_reg);
- temp &= ~PORT_RWC_BITS;
- switch (wValue) {
- case USB_PORT_FEAT_SUSPEND:
- if ((temp & PORT_PE) == 0
- || (temp & PORT_RESET) != 0)
- goto error;
-
- /* After above check the port must be connected.
- * Set appropriate bit thus could put phy into low power
- * mode if we have hostpc feature
- */
- fusbh200_writel(fusbh200, temp | PORT_SUSPEND, status_reg);
- set_bit(wIndex, &fusbh200->suspended_ports);
- break;
- case USB_PORT_FEAT_RESET:
- if (temp & PORT_RESUME)
- goto error;
- /* line status bits may report this as low speed,
- * which can be fine if this root hub has a
- * transaction translator built in.
- */
- fusbh200_dbg(fusbh200, "port %d reset\n", wIndex + 1);
- temp |= PORT_RESET;
- temp &= ~PORT_PE;
-
- /*
- * caller must wait, then call GetPortStatus
- * usb 2.0 spec says 50 ms resets on root
- */
- fusbh200->reset_done [wIndex] = jiffies
- + msecs_to_jiffies (50);
- fusbh200_writel(fusbh200, temp, status_reg);
- break;
-
- /* For downstream facing ports (these): one hub port is put
- * into test mode according to USB2 11.24.2.13, then the hub
- * must be reset (which for root hub now means rmmod+modprobe,
- * or else system reboot). See EHCI 2.3.9 and 4.14 for info
- * about the EHCI-specific stuff.
- */
- case USB_PORT_FEAT_TEST:
- if (!selector || selector > 5)
- goto error;
- spin_unlock_irqrestore(&fusbh200->lock, flags);
- fusbh200_quiesce(fusbh200);
- spin_lock_irqsave(&fusbh200->lock, flags);
-
- /* Put all enabled ports into suspend */
- temp = fusbh200_readl(fusbh200, status_reg) & ~PORT_RWC_BITS;
- if (temp & PORT_PE)
- fusbh200_writel(fusbh200, temp | PORT_SUSPEND,
- status_reg);
-
- spin_unlock_irqrestore(&fusbh200->lock, flags);
- fusbh200_halt(fusbh200);
- spin_lock_irqsave(&fusbh200->lock, flags);
-
- temp = fusbh200_readl(fusbh200, status_reg);
- temp |= selector << 16;
- fusbh200_writel(fusbh200, temp, status_reg);
- break;
-
- default:
- goto error;
- }
- fusbh200_readl(fusbh200, &fusbh200->regs->command); /* unblock posted writes */
- break;
-
- default:
-error:
- /* "stall" on error */
- retval = -EPIPE;
- }
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- return retval;
-}
-
-static void __maybe_unused fusbh200_relinquish_port(struct usb_hcd *hcd,
- int portnum)
-{
- return;
-}
-
-static int __maybe_unused fusbh200_port_handed_over(struct usb_hcd *hcd,
- int portnum)
-{
- return 0;
-}
-/*-------------------------------------------------------------------------*/
-/*
- * There's basically three types of memory:
- * - data used only by the HCD ... kmalloc is fine
- * - async and periodic schedules, shared by HC and HCD ... these
- * need to use dma_pool or dma_alloc_coherent
- * - driver buffers, read/written by HC ... single shot DMA mapped
- *
- * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
- * No memory seen by this driver is pageable.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* Allocate the key transfer structures from the previously allocated pool */
-
-static inline void fusbh200_qtd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd,
- dma_addr_t dma)
-{
- memset (qtd, 0, sizeof *qtd);
- qtd->qtd_dma = dma;
- qtd->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT);
- qtd->hw_next = FUSBH200_LIST_END(fusbh200);
- qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200);
- INIT_LIST_HEAD (&qtd->qtd_list);
-}
-
-static struct fusbh200_qtd *fusbh200_qtd_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags)
-{
- struct fusbh200_qtd *qtd;
- dma_addr_t dma;
-
- qtd = dma_pool_alloc (fusbh200->qtd_pool, flags, &dma);
- if (qtd != NULL) {
- fusbh200_qtd_init(fusbh200, qtd, dma);
- }
- return qtd;
-}
-
-static inline void fusbh200_qtd_free (struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd)
-{
- dma_pool_free (fusbh200->qtd_pool, qtd, qtd->qtd_dma);
-}
-
-
-static void qh_destroy(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- /* clean qtds first, and know this is not linked */
- if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
- fusbh200_dbg (fusbh200, "unused qh not empty!\n");
- BUG ();
- }
- if (qh->dummy)
- fusbh200_qtd_free (fusbh200, qh->dummy);
- dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma);
- kfree(qh);
-}
-
-static struct fusbh200_qh *fusbh200_qh_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags)
-{
- struct fusbh200_qh *qh;
- dma_addr_t dma;
-
- qh = kzalloc(sizeof *qh, GFP_ATOMIC);
- if (!qh)
- goto done;
- qh->hw = (struct fusbh200_qh_hw *)
- dma_pool_alloc(fusbh200->qh_pool, flags, &dma);
- if (!qh->hw)
- goto fail;
- memset(qh->hw, 0, sizeof *qh->hw);
- qh->qh_dma = dma;
- // INIT_LIST_HEAD (&qh->qh_list);
- INIT_LIST_HEAD (&qh->qtd_list);
-
- /* dummy td enables safe urb queuing */
- qh->dummy = fusbh200_qtd_alloc (fusbh200, flags);
- if (qh->dummy == NULL) {
- fusbh200_dbg (fusbh200, "no dummy td\n");
- goto fail1;
- }
-done:
- return qh;
-fail1:
- dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma);
-fail:
- kfree(qh);
- return NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* The queue heads and transfer descriptors are managed from pools tied
- * to each of the "per device" structures.
- * This is the initialisation and cleanup code.
- */
-
-static void fusbh200_mem_cleanup (struct fusbh200_hcd *fusbh200)
-{
- if (fusbh200->async)
- qh_destroy(fusbh200, fusbh200->async);
- fusbh200->async = NULL;
-
- if (fusbh200->dummy)
- qh_destroy(fusbh200, fusbh200->dummy);
- fusbh200->dummy = NULL;
-
- /* DMA consistent memory and pools */
- if (fusbh200->qtd_pool)
- dma_pool_destroy (fusbh200->qtd_pool);
- fusbh200->qtd_pool = NULL;
-
- if (fusbh200->qh_pool) {
- dma_pool_destroy (fusbh200->qh_pool);
- fusbh200->qh_pool = NULL;
- }
-
- if (fusbh200->itd_pool)
- dma_pool_destroy (fusbh200->itd_pool);
- fusbh200->itd_pool = NULL;
-
- if (fusbh200->periodic)
- dma_free_coherent (fusbh200_to_hcd(fusbh200)->self.controller,
- fusbh200->periodic_size * sizeof (u32),
- fusbh200->periodic, fusbh200->periodic_dma);
- fusbh200->periodic = NULL;
-
- /* shadow periodic table */
- kfree(fusbh200->pshadow);
- fusbh200->pshadow = NULL;
-}
-
-/* remember to add cleanup code (above) if you add anything here */
-static int fusbh200_mem_init (struct fusbh200_hcd *fusbh200, gfp_t flags)
-{
- int i;
-
- /* QTDs for control/bulk/intr transfers */
- fusbh200->qtd_pool = dma_pool_create ("fusbh200_qtd",
- fusbh200_to_hcd(fusbh200)->self.controller,
- sizeof (struct fusbh200_qtd),
- 32 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- if (!fusbh200->qtd_pool) {
- goto fail;
- }
-
- /* QHs for control/bulk/intr transfers */
- fusbh200->qh_pool = dma_pool_create ("fusbh200_qh",
- fusbh200_to_hcd(fusbh200)->self.controller,
- sizeof(struct fusbh200_qh_hw),
- 32 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- if (!fusbh200->qh_pool) {
- goto fail;
- }
- fusbh200->async = fusbh200_qh_alloc (fusbh200, flags);
- if (!fusbh200->async) {
- goto fail;
- }
-
- /* ITD for high speed ISO transfers */
- fusbh200->itd_pool = dma_pool_create ("fusbh200_itd",
- fusbh200_to_hcd(fusbh200)->self.controller,
- sizeof (struct fusbh200_itd),
- 64 /* byte alignment (for hw parts) */,
- 4096 /* can't cross 4K */);
- if (!fusbh200->itd_pool) {
- goto fail;
- }
-
- /* Hardware periodic table */
- fusbh200->periodic = (__le32 *)
- dma_alloc_coherent (fusbh200_to_hcd(fusbh200)->self.controller,
- fusbh200->periodic_size * sizeof(__le32),
- &fusbh200->periodic_dma, 0);
- if (fusbh200->periodic == NULL) {
- goto fail;
- }
-
- for (i = 0; i < fusbh200->periodic_size; i++)
- fusbh200->periodic[i] = FUSBH200_LIST_END(fusbh200);
-
- /* software shadow of hardware table */
- fusbh200->pshadow = kcalloc(fusbh200->periodic_size, sizeof(void *), flags);
- if (fusbh200->pshadow != NULL)
- return 0;
-
-fail:
- fusbh200_dbg (fusbh200, "couldn't init memory\n");
- fusbh200_mem_cleanup (fusbh200);
- return -ENOMEM;
-}
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI hardware queue manipulation ... the core. QH/QTD manipulation.
- *
- * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd"
- * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
- * buffers needed for the larger number). We use one QH per endpoint, queue
- * multiple urbs (all three types) per endpoint. URBs may need several qtds.
- *
- * ISO traffic uses "ISO TD" (itd) records, and (along with
- * interrupts) needs careful scheduling. Performance improvements can be
- * an ongoing challenge. That's in "ehci-sched.c".
- *
- * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
- * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
- * (b) special fields in qh entries or (c) split iso entries. TTs will
- * buffer low/full speed data so the host collects it at high speed.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* fill a qtd, returning how much of the buffer we were able to queue up */
-
-static int
-qtd_fill(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd, dma_addr_t buf,
- size_t len, int token, int maxpacket)
-{
- int i, count;
- u64 addr = buf;
-
- /* one buffer entry per 4K ... first might be short or unaligned */
- qtd->hw_buf[0] = cpu_to_hc32(fusbh200, (u32)addr);
- qtd->hw_buf_hi[0] = cpu_to_hc32(fusbh200, (u32)(addr >> 32));
- count = 0x1000 - (buf & 0x0fff); /* rest of that page */
- if (likely (len < count)) /* ... iff needed */
- count = len;
- else {
- buf += 0x1000;
- buf &= ~0x0fff;
-
- /* per-qtd limit: from 16K to 20K (best alignment) */
- for (i = 1; count < len && i < 5; i++) {
- addr = buf;
- qtd->hw_buf[i] = cpu_to_hc32(fusbh200, (u32)addr);
- qtd->hw_buf_hi[i] = cpu_to_hc32(fusbh200,
- (u32)(addr >> 32));
- buf += 0x1000;
- if ((count + 0x1000) < len)
- count += 0x1000;
- else
- count = len;
- }
-
- /* short packets may only terminate transfers */
- if (count != len)
- count -= (count % maxpacket);
- }
- qtd->hw_token = cpu_to_hc32(fusbh200, (count << 16) | token);
- qtd->length = count;
-
- return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline void
-qh_update (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh, struct fusbh200_qtd *qtd)
-{
- struct fusbh200_qh_hw *hw = qh->hw;
-
- /* writes to an active overlay are unsafe */
- BUG_ON(qh->qh_state != QH_STATE_IDLE);
-
- hw->hw_qtd_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
- hw->hw_alt_next = FUSBH200_LIST_END(fusbh200);
-
- /* Except for control endpoints, we make hardware maintain data
- * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
- * and set the pseudo-toggle in udev. Only usb_clear_halt() will
- * ever clear it.
- */
- if (!(hw->hw_info1 & cpu_to_hc32(fusbh200, QH_TOGGLE_CTL))) {
- unsigned is_out, epnum;
-
- is_out = qh->is_out;
- epnum = (hc32_to_cpup(fusbh200, &hw->hw_info1) >> 8) & 0x0f;
- if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
- hw->hw_token &= ~cpu_to_hc32(fusbh200, QTD_TOGGLE);
- usb_settoggle (qh->dev, epnum, is_out, 1);
- }
- }
-
- hw->hw_token &= cpu_to_hc32(fusbh200, QTD_TOGGLE | QTD_STS_PING);
-}
-
-/* if it weren't for a common silicon quirk (writing the dummy into the qh
- * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault
- * recovery (including urb dequeue) would need software changes to a QH...
- */
-static void
-qh_refresh (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- struct fusbh200_qtd *qtd;
-
- if (list_empty (&qh->qtd_list))
- qtd = qh->dummy;
- else {
- qtd = list_entry (qh->qtd_list.next,
- struct fusbh200_qtd, qtd_list);
- /*
- * first qtd may already be partially processed.
- * If we come here during unlink, the QH overlay region
- * might have reference to the just unlinked qtd. The
- * qtd is updated in qh_completions(). Update the QH
- * overlay here.
- */
- if (cpu_to_hc32(fusbh200, qtd->qtd_dma) == qh->hw->hw_current) {
- qh->hw->hw_qtd_next = qtd->hw_next;
- qtd = NULL;
- }
- }
-
- if (qtd)
- qh_update (fusbh200, qh, qtd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void qh_link_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-
-static void fusbh200_clear_tt_buffer_complete(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
- struct fusbh200_qh *qh = ep->hcpriv;
- unsigned long flags;
-
- spin_lock_irqsave(&fusbh200->lock, flags);
- qh->clearing_tt = 0;
- if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
- && fusbh200->rh_state == FUSBH200_RH_RUNNING)
- qh_link_async(fusbh200, qh);
- spin_unlock_irqrestore(&fusbh200->lock, flags);
-}
-
-static void fusbh200_clear_tt_buffer(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh,
- struct urb *urb, u32 token)
-{
-
- /* If an async split transaction gets an error or is unlinked,
- * the TT buffer may be left in an indeterminate state. We
- * have to clear the TT buffer.
- *
- * Note: this routine is never called for Isochronous transfers.
- */
- if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
- struct usb_device *tt = urb->dev->tt->hub;
-
- dev_dbg(&tt->dev,
- "clear tt buffer port %d, a%d ep%d t%08x\n",
- urb->dev->ttport, urb->dev->devnum,
- usb_pipeendpoint(urb->pipe), token);
-
- if (urb->dev->tt->hub !=
- fusbh200_to_hcd(fusbh200)->self.root_hub) {
- if (usb_hub_clear_tt_buffer(urb) == 0)
- qh->clearing_tt = 1;
- }
- }
-}
-
-static int qtd_copy_status (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- size_t length,
- u32 token
-)
-{
- int status = -EINPROGRESS;
-
- /* count IN/OUT bytes, not SETUP (even short packets) */
- if (likely (QTD_PID (token) != 2))
- urb->actual_length += length - QTD_LENGTH (token);
-
- /* don't modify error codes */
- if (unlikely(urb->unlinked))
- return status;
-
- /* force cleanup after short read; not always an error */
- if (unlikely (IS_SHORT_READ (token)))
- status = -EREMOTEIO;
-
- /* serious "can't proceed" faults reported by the hardware */
- if (token & QTD_STS_HALT) {
- if (token & QTD_STS_BABBLE) {
- /* FIXME "must" disable babbling device's port too */
- status = -EOVERFLOW;
- /* CERR nonzero + halt --> stall */
- } else if (QTD_CERR(token)) {
- status = -EPIPE;
-
- /* In theory, more than one of the following bits can be set
- * since they are sticky and the transaction is retried.
- * Which to test first is rather arbitrary.
- */
- } else if (token & QTD_STS_MMF) {
- /* fs/ls interrupt xfer missed the complete-split */
- status = -EPROTO;
- } else if (token & QTD_STS_DBE) {
- status = (QTD_PID (token) == 1) /* IN ? */
- ? -ENOSR /* hc couldn't read data */
- : -ECOMM; /* hc couldn't write data */
- } else if (token & QTD_STS_XACT) {
- /* timeout, bad CRC, wrong PID, etc */
- fusbh200_dbg(fusbh200, "devpath %s ep%d%s 3strikes\n",
- urb->dev->devpath,
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out");
- status = -EPROTO;
- } else { /* unknown */
- status = -EPROTO;
- }
-
- fusbh200_dbg(fusbh200,
- "dev%d ep%d%s qtd token %08x --> status %d\n",
- usb_pipedevice (urb->pipe),
- usb_pipeendpoint (urb->pipe),
- usb_pipein (urb->pipe) ? "in" : "out",
- token, status);
- }
-
- return status;
-}
-
-static void
-fusbh200_urb_done(struct fusbh200_hcd *fusbh200, struct urb *urb, int status)
-__releases(fusbh200->lock)
-__acquires(fusbh200->lock)
-{
- if (likely (urb->hcpriv != NULL)) {
- struct fusbh200_qh *qh = (struct fusbh200_qh *) urb->hcpriv;
-
- /* S-mask in a QH means it's an interrupt urb */
- if ((qh->hw->hw_info2 & cpu_to_hc32(fusbh200, QH_SMASK)) != 0) {
-
- /* ... update hc-wide periodic stats (for usbfs) */
- fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs--;
- }
- }
-
- if (unlikely(urb->unlinked)) {
- COUNT(fusbh200->stats.unlink);
- } else {
- /* report non-error and short read status as zero */
- if (status == -EINPROGRESS || status == -EREMOTEIO)
- status = 0;
- COUNT(fusbh200->stats.complete);
- }
-
-#ifdef FUSBH200_URB_TRACE
- fusbh200_dbg (fusbh200,
- "%s %s urb %p ep%d%s status %d len %d/%d\n",
- __func__, urb->dev->devpath, urb,
- usb_pipeendpoint (urb->pipe),
- usb_pipein (urb->pipe) ? "in" : "out",
- status,
- urb->actual_length, urb->transfer_buffer_length);
-#endif
-
- /* complete() can reenter this HCD */
- usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
- spin_unlock (&fusbh200->lock);
- usb_hcd_giveback_urb(fusbh200_to_hcd(fusbh200), urb, status);
- spin_lock (&fusbh200->lock);
-}
-
-static int qh_schedule (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-
-/*
- * Process and free completed qtds for a qh, returning URBs to drivers.
- * Chases up to qh->hw_current. Returns number of completions called,
- * indicating how much "real" work we did.
- */
-static unsigned
-qh_completions (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- struct fusbh200_qtd *last, *end = qh->dummy;
- struct list_head *entry, *tmp;
- int last_status;
- int stopped;
- unsigned count = 0;
- u8 state;
- struct fusbh200_qh_hw *hw = qh->hw;
-
- if (unlikely (list_empty (&qh->qtd_list)))
- return count;
-
- /* completions (or tasks on other cpus) must never clobber HALT
- * till we've gone through and cleaned everything up, even when
- * they add urbs to this qh's queue or mark them for unlinking.
- *
- * NOTE: unlinking expects to be done in queue order.
- *
- * It's a bug for qh->qh_state to be anything other than
- * QH_STATE_IDLE, unless our caller is scan_async() or
- * scan_intr().
- */
- state = qh->qh_state;
- qh->qh_state = QH_STATE_COMPLETING;
- stopped = (state == QH_STATE_IDLE);
-
- rescan:
- last = NULL;
- last_status = -EINPROGRESS;
- qh->needs_rescan = 0;
-
- /* remove de-activated QTDs from front of queue.
- * after faults (including short reads), cleanup this urb
- * then let the queue advance.
- * if queue is stopped, handles unlinks.
- */
- list_for_each_safe (entry, tmp, &qh->qtd_list) {
- struct fusbh200_qtd *qtd;
- struct urb *urb;
- u32 token = 0;
-
- qtd = list_entry (entry, struct fusbh200_qtd, qtd_list);
- urb = qtd->urb;
-
- /* clean up any state from previous QTD ...*/
- if (last) {
- if (likely (last->urb != urb)) {
- fusbh200_urb_done(fusbh200, last->urb, last_status);
- count++;
- last_status = -EINPROGRESS;
- }
- fusbh200_qtd_free (fusbh200, last);
- last = NULL;
- }
-
- /* ignore urbs submitted during completions we reported */
- if (qtd == end)
- break;
-
- /* hardware copies qtd out of qh overlay */
- rmb ();
- token = hc32_to_cpu(fusbh200, qtd->hw_token);
-
- /* always clean up qtds the hc de-activated */
- retry_xacterr:
- if ((token & QTD_STS_ACTIVE) == 0) {
-
- /* Report Data Buffer Error: non-fatal but useful */
- if (token & QTD_STS_DBE)
- fusbh200_dbg(fusbh200,
- "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
- urb,
- usb_endpoint_num(&urb->ep->desc),
- usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out",
- urb->transfer_buffer_length,
- qtd,
- qh);
-
- /* on STALL, error, and short reads this urb must
- * complete and all its qtds must be recycled.
- */
- if ((token & QTD_STS_HALT) != 0) {
-
- /* retry transaction errors until we
- * reach the software xacterr limit
- */
- if ((token & QTD_STS_XACT) &&
- QTD_CERR(token) == 0 &&
- ++qh->xacterrs < QH_XACTERR_MAX &&
- !urb->unlinked) {
- fusbh200_dbg(fusbh200,
- "detected XactErr len %zu/%zu retry %d\n",
- qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
-
- /* reset the token in the qtd and the
- * qh overlay (which still contains
- * the qtd) so that we pick up from
- * where we left off
- */
- token &= ~QTD_STS_HALT;
- token |= QTD_STS_ACTIVE |
- (FUSBH200_TUNE_CERR << 10);
- qtd->hw_token = cpu_to_hc32(fusbh200,
- token);
- wmb();
- hw->hw_token = cpu_to_hc32(fusbh200,
- token);
- goto retry_xacterr;
- }
- stopped = 1;
-
- /* magic dummy for some short reads; qh won't advance.
- * that silicon quirk can kick in with this dummy too.
- *
- * other short reads won't stop the queue, including
- * control transfers (status stage handles that) or
- * most other single-qtd reads ... the queue stops if
- * URB_SHORT_NOT_OK was set so the driver submitting
- * the urbs could clean it up.
- */
- } else if (IS_SHORT_READ (token)
- && !(qtd->hw_alt_next
- & FUSBH200_LIST_END(fusbh200))) {
- stopped = 1;
- }
-
- /* stop scanning when we reach qtds the hc is using */
- } else if (likely (!stopped
- && fusbh200->rh_state >= FUSBH200_RH_RUNNING)) {
- break;
-
- /* scan the whole queue for unlinks whenever it stops */
- } else {
- stopped = 1;
-
- /* cancel everything if we halt, suspend, etc */
- if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
- last_status = -ESHUTDOWN;
-
- /* this qtd is active; skip it unless a previous qtd
- * for its urb faulted, or its urb was canceled.
- */
- else if (last_status == -EINPROGRESS && !urb->unlinked)
- continue;
-
- /* qh unlinked; token in overlay may be most current */
- if (state == QH_STATE_IDLE
- && cpu_to_hc32(fusbh200, qtd->qtd_dma)
- == hw->hw_current) {
- token = hc32_to_cpu(fusbh200, hw->hw_token);
-
- /* An unlink may leave an incomplete
- * async transaction in the TT buffer.
- * We have to clear it.
- */
- fusbh200_clear_tt_buffer(fusbh200, qh, urb, token);
- }
- }
-
- /* unless we already know the urb's status, collect qtd status
- * and update count of bytes transferred. in common short read
- * cases with only one data qtd (including control transfers),
- * queue processing won't halt. but with two or more qtds (for
- * example, with a 32 KB transfer), when the first qtd gets a
- * short read the second must be removed by hand.
- */
- if (last_status == -EINPROGRESS) {
- last_status = qtd_copy_status(fusbh200, urb,
- qtd->length, token);
- if (last_status == -EREMOTEIO
- && (qtd->hw_alt_next
- & FUSBH200_LIST_END(fusbh200)))
- last_status = -EINPROGRESS;
-
- /* As part of low/full-speed endpoint-halt processing
- * we must clear the TT buffer (11.17.5).
- */
- if (unlikely(last_status != -EINPROGRESS &&
- last_status != -EREMOTEIO)) {
- /* The TT's in some hubs malfunction when they
- * receive this request following a STALL (they
- * stop sending isochronous packets). Since a
- * STALL can't leave the TT buffer in a busy
- * state (if you believe Figures 11-48 - 11-51
- * in the USB 2.0 spec), we won't clear the TT
- * buffer in this case. Strictly speaking this
- * is a violation of the spec.
- */
- if (last_status != -EPIPE)
- fusbh200_clear_tt_buffer(fusbh200, qh, urb,
- token);
- }
- }
-
- /* if we're removing something not at the queue head,
- * patch the hardware queue pointer.
- */
- if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
- last = list_entry (qtd->qtd_list.prev,
- struct fusbh200_qtd, qtd_list);
- last->hw_next = qtd->hw_next;
- }
-
- /* remove qtd; it's recycled after possible urb completion */
- list_del (&qtd->qtd_list);
- last = qtd;
-
- /* reinit the xacterr counter for the next qtd */
- qh->xacterrs = 0;
- }
-
- /* last urb's completion might still need calling */
- if (likely (last != NULL)) {
- fusbh200_urb_done(fusbh200, last->urb, last_status);
- count++;
- fusbh200_qtd_free (fusbh200, last);
- }
-
- /* Do we need to rescan for URBs dequeued during a giveback? */
- if (unlikely(qh->needs_rescan)) {
- /* If the QH is already unlinked, do the rescan now. */
- if (state == QH_STATE_IDLE)
- goto rescan;
-
- /* Otherwise we have to wait until the QH is fully unlinked.
- * Our caller will start an unlink if qh->needs_rescan is
- * set. But if an unlink has already started, nothing needs
- * to be done.
- */
- if (state != QH_STATE_LINKED)
- qh->needs_rescan = 0;
- }
-
- /* restore original state; caller must unlink or relink */
- qh->qh_state = state;
-
- /* be sure the hardware's done with the qh before refreshing
- * it after fault cleanup, or recovering from silicon wrongly
- * overlaying the dummy qtd (which reduces DMA chatter).
- */
- if (stopped != 0 || hw->hw_qtd_next == FUSBH200_LIST_END(fusbh200)) {
- switch (state) {
- case QH_STATE_IDLE:
- qh_refresh(fusbh200, qh);
- break;
- case QH_STATE_LINKED:
- /* We won't refresh a QH that's linked (after the HC
- * stopped the queue). That avoids a race:
- * - HC reads first part of QH;
- * - CPU updates that first part and the token;
- * - HC reads rest of that QH, including token
- * Result: HC gets an inconsistent image, and then
- * DMAs to/from the wrong memory (corrupting it).
- *
- * That should be rare for interrupt transfers,
- * except maybe high bandwidth ...
- */
-
- /* Tell the caller to start an unlink */
- qh->needs_rescan = 1;
- break;
- /* otherwise, unlink already started */
- }
- }
-
- return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// high bandwidth multiplier, as encoded in highspeed endpoint descriptors
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-// ... and packet size, for any kind of endpoint descriptor
-#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
-
-/*
- * reverse of qh_urb_transaction: free a list of TDs.
- * used for cleanup after errors, before HC sees an URB's TDs.
- */
-static void qtd_list_free (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- struct list_head *qtd_list
-) {
- struct list_head *entry, *temp;
-
- list_for_each_safe (entry, temp, qtd_list) {
- struct fusbh200_qtd *qtd;
-
- qtd = list_entry (entry, struct fusbh200_qtd, qtd_list);
- list_del (&qtd->qtd_list);
- fusbh200_qtd_free (fusbh200, qtd);
- }
-}
-
-/*
- * create a list of filled qtds for this URB; won't link into qh.
- */
-static struct list_head *
-qh_urb_transaction (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- struct list_head *head,
- gfp_t flags
-) {
- struct fusbh200_qtd *qtd, *qtd_prev;
- dma_addr_t buf;
- int len, this_sg_len, maxpacket;
- int is_input;
- u32 token;
- int i;
- struct scatterlist *sg;
-
- /*
- * URBs map to sequences of QTDs: one logical transaction
- */
- qtd = fusbh200_qtd_alloc (fusbh200, flags);
- if (unlikely (!qtd))
- return NULL;
- list_add_tail (&qtd->qtd_list, head);
- qtd->urb = urb;
-
- token = QTD_STS_ACTIVE;
- token |= (FUSBH200_TUNE_CERR << 10);
- /* for split transactions, SplitXState initialized to zero */
-
- len = urb->transfer_buffer_length;
- is_input = usb_pipein (urb->pipe);
- if (usb_pipecontrol (urb->pipe)) {
- /* SETUP pid */
- qtd_fill(fusbh200, qtd, urb->setup_dma,
- sizeof (struct usb_ctrlrequest),
- token | (2 /* "setup" */ << 8), 8);
-
- /* ... and always at least one more pid */
- token ^= QTD_TOGGLE;
- qtd_prev = qtd;
- qtd = fusbh200_qtd_alloc (fusbh200, flags);
- if (unlikely (!qtd))
- goto cleanup;
- qtd->urb = urb;
- qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
- list_add_tail (&qtd->qtd_list, head);
-
- /* for zero length DATA stages, STATUS is always IN */
- if (len == 0)
- token |= (1 /* "in" */ << 8);
- }
-
- /*
- * data transfer stage: buffer setup
- */
- i = urb->num_mapped_sgs;
- if (len > 0 && i > 0) {
- sg = urb->sg;
- buf = sg_dma_address(sg);
-
- /* urb->transfer_buffer_length may be smaller than the
- * size of the scatterlist (or vice versa)
- */
- this_sg_len = min_t(int, sg_dma_len(sg), len);
- } else {
- sg = NULL;
- buf = urb->transfer_dma;
- this_sg_len = len;
- }
-
- if (is_input)
- token |= (1 /* "in" */ << 8);
- /* else it's already initted to "out" pid (0 << 8) */
-
- maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
-
- /*
- * buffer gets wrapped in one or more qtds;
- * last one may be "short" (including zero len)
- * and may serve as a control status ack
- */
- for (;;) {
- int this_qtd_len;
-
- this_qtd_len = qtd_fill(fusbh200, qtd, buf, this_sg_len, token,
- maxpacket);
- this_sg_len -= this_qtd_len;
- len -= this_qtd_len;
- buf += this_qtd_len;
-
- /*
- * short reads advance to a "magic" dummy instead of the next
- * qtd ... that forces the queue to stop, for manual cleanup.
- * (this will usually be overridden later.)
- */
- if (is_input)
- qtd->hw_alt_next = fusbh200->async->hw->hw_alt_next;
-
- /* qh makes control packets use qtd toggle; maybe switch it */
- if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
- token ^= QTD_TOGGLE;
-
- if (likely(this_sg_len <= 0)) {
- if (--i <= 0 || len <= 0)
- break;
- sg = sg_next(sg);
- buf = sg_dma_address(sg);
- this_sg_len = min_t(int, sg_dma_len(sg), len);
- }
-
- qtd_prev = qtd;
- qtd = fusbh200_qtd_alloc (fusbh200, flags);
- if (unlikely (!qtd))
- goto cleanup;
- qtd->urb = urb;
- qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
- list_add_tail (&qtd->qtd_list, head);
- }
-
- /*
- * unless the caller requires manual cleanup after short reads,
- * have the alt_next mechanism keep the queue running after the
- * last data qtd (the only one, for control and most other cases).
- */
- if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
- || usb_pipecontrol (urb->pipe)))
- qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200);
-
- /*
- * control requests may need a terminating data "status" ack;
- * other OUT ones may need a terminating short packet
- * (zero length).
- */
- if (likely (urb->transfer_buffer_length != 0)) {
- int one_more = 0;
-
- if (usb_pipecontrol (urb->pipe)) {
- one_more = 1;
- token ^= 0x0100; /* "in" <--> "out" */
- token |= QTD_TOGGLE; /* force DATA1 */
- } else if (usb_pipeout(urb->pipe)
- && (urb->transfer_flags & URB_ZERO_PACKET)
- && !(urb->transfer_buffer_length % maxpacket)) {
- one_more = 1;
- }
- if (one_more) {
- qtd_prev = qtd;
- qtd = fusbh200_qtd_alloc (fusbh200, flags);
- if (unlikely (!qtd))
- goto cleanup;
- qtd->urb = urb;
- qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
- list_add_tail (&qtd->qtd_list, head);
-
- /* never any data in such packets */
- qtd_fill(fusbh200, qtd, 0, 0, token, 0);
- }
- }
-
- /* by default, enable interrupt on urb completion */
- if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
- qtd->hw_token |= cpu_to_hc32(fusbh200, QTD_IOC);
- return head;
-
-cleanup:
- qtd_list_free (fusbh200, urb, head);
- return NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// Would be best to create all qh's from config descriptors,
-// when each interface/altsetting is established. Unlink
-// any previous qh and cancel its urbs first; endpoints are
-// implicitly reset then (data toggle too).
-// That'd mean updating how usbcore talks to HCDs. (2.7?)
-
-
-/*
- * Each QH holds a qtd list; a QH is used for everything except iso.
- *
- * For interrupt urbs, the scheduler must set the microframe scheduling
- * mask(s) each time the QH gets scheduled. For highspeed, that's
- * just one microframe in the s-mask. For split interrupt transactions
- * there are additional complications: c-mask, maybe FSTNs.
- */
-static struct fusbh200_qh *
-qh_make (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- gfp_t flags
-) {
- struct fusbh200_qh *qh = fusbh200_qh_alloc (fusbh200, flags);
- u32 info1 = 0, info2 = 0;
- int is_input, type;
- int maxp = 0;
- struct usb_tt *tt = urb->dev->tt;
- struct fusbh200_qh_hw *hw;
-
- if (!qh)
- return qh;
-
- /*
- * init endpoint/device data for this QH
- */
- info1 |= usb_pipeendpoint (urb->pipe) << 8;
- info1 |= usb_pipedevice (urb->pipe) << 0;
-
- is_input = usb_pipein (urb->pipe);
- type = usb_pipetype (urb->pipe);
- maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
-
- /* 1024 byte maxpacket is a hardware ceiling. High bandwidth
- * acts like up to 3KB, but is built from smaller packets.
- */
- if (max_packet(maxp) > 1024) {
- fusbh200_dbg(fusbh200, "bogus qh maxpacket %d\n", max_packet(maxp));
- goto done;
- }
-
- /* Compute interrupt scheduling parameters just once, and save.
- * - allowing for high bandwidth, how many nsec/uframe are used?
- * - split transactions need a second CSPLIT uframe; same question
- * - splits also need a schedule gap (for full/low speed I/O)
- * - qh has a polling interval
- *
- * For control/bulk requests, the HC or TT handles these.
- */
- if (type == PIPE_INTERRUPT) {
- qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
- is_input, 0,
- hb_mult(maxp) * max_packet(maxp)));
- qh->start = NO_FRAME;
-
- if (urb->dev->speed == USB_SPEED_HIGH) {
- qh->c_usecs = 0;
- qh->gap_uf = 0;
-
- qh->period = urb->interval >> 3;
- if (qh->period == 0 && urb->interval != 1) {
- /* NOTE interval 2 or 4 uframes could work.
- * But interval 1 scheduling is simpler, and
- * includes high bandwidth.
- */
- urb->interval = 1;
- } else if (qh->period > fusbh200->periodic_size) {
- qh->period = fusbh200->periodic_size;
- urb->interval = qh->period << 3;
- }
- } else {
- int think_time;
-
- /* gap is f(FS/LS transfer times) */
- qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
- is_input, 0, maxp) / (125 * 1000);
-
- /* FIXME this just approximates SPLIT/CSPLIT times */
- if (is_input) { // SPLIT, gap, CSPLIT+DATA
- qh->c_usecs = qh->usecs + HS_USECS (0);
- qh->usecs = HS_USECS (1);
- } else { // SPLIT+DATA, gap, CSPLIT
- qh->usecs += HS_USECS (1);
- qh->c_usecs = HS_USECS (0);
- }
-
- think_time = tt ? tt->think_time : 0;
- qh->tt_usecs = NS_TO_US (think_time +
- usb_calc_bus_time (urb->dev->speed,
- is_input, 0, max_packet (maxp)));
- qh->period = urb->interval;
- if (qh->period > fusbh200->periodic_size) {
- qh->period = fusbh200->periodic_size;
- urb->interval = qh->period;
- }
- }
- }
-
- /* support for tt scheduling, and access to toggles */
- qh->dev = urb->dev;
-
- /* using TT? */
- switch (urb->dev->speed) {
- case USB_SPEED_LOW:
- info1 |= QH_LOW_SPEED;
- /* FALL THROUGH */
-
- case USB_SPEED_FULL:
- /* EPS 0 means "full" */
- if (type != PIPE_INTERRUPT)
- info1 |= (FUSBH200_TUNE_RL_TT << 28);
- if (type == PIPE_CONTROL) {
- info1 |= QH_CONTROL_EP; /* for TT */
- info1 |= QH_TOGGLE_CTL; /* toggle from qtd */
- }
- info1 |= maxp << 16;
-
- info2 |= (FUSBH200_TUNE_MULT_TT << 30);
-
- /* Some Freescale processors have an erratum in which the
- * port number in the queue head was 0..N-1 instead of 1..N.
- */
- if (fusbh200_has_fsl_portno_bug(fusbh200))
- info2 |= (urb->dev->ttport-1) << 23;
- else
- info2 |= urb->dev->ttport << 23;
-
- /* set the address of the TT; for TDI's integrated
- * root hub tt, leave it zeroed.
- */
- if (tt && tt->hub != fusbh200_to_hcd(fusbh200)->self.root_hub)
- info2 |= tt->hub->devnum << 16;
-
- /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */
-
- break;
-
- case USB_SPEED_HIGH: /* no TT involved */
- info1 |= QH_HIGH_SPEED;
- if (type == PIPE_CONTROL) {
- info1 |= (FUSBH200_TUNE_RL_HS << 28);
- info1 |= 64 << 16; /* usb2 fixed maxpacket */
- info1 |= QH_TOGGLE_CTL; /* toggle from qtd */
- info2 |= (FUSBH200_TUNE_MULT_HS << 30);
- } else if (type == PIPE_BULK) {
- info1 |= (FUSBH200_TUNE_RL_HS << 28);
- /* The USB spec says that high speed bulk endpoints
- * always use 512 byte maxpacket. But some device
- * vendors decided to ignore that, and MSFT is happy
- * to help them do so. So now people expect to use
- * such nonconformant devices with Linux too; sigh.
- */
- info1 |= max_packet(maxp) << 16;
- info2 |= (FUSBH200_TUNE_MULT_HS << 30);
- } else { /* PIPE_INTERRUPT */
- info1 |= max_packet (maxp) << 16;
- info2 |= hb_mult (maxp) << 30;
- }
- break;
- default:
- fusbh200_dbg(fusbh200, "bogus dev %p speed %d\n", urb->dev,
- urb->dev->speed);
-done:
- qh_destroy(fusbh200, qh);
- return NULL;
- }
-
- /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */
-
- /* init as live, toggle clear, advance to dummy */
- qh->qh_state = QH_STATE_IDLE;
- hw = qh->hw;
- hw->hw_info1 = cpu_to_hc32(fusbh200, info1);
- hw->hw_info2 = cpu_to_hc32(fusbh200, info2);
- qh->is_out = !is_input;
- usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
- qh_refresh (fusbh200, qh);
- return qh;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void enable_async(struct fusbh200_hcd *fusbh200)
-{
- if (fusbh200->async_count++)
- return;
-
- /* Stop waiting to turn off the async schedule */
- fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_ASYNC);
-
- /* Don't start the schedule until ASS is 0 */
- fusbh200_poll_ASS(fusbh200);
- turn_on_io_watchdog(fusbh200);
-}
-
-static void disable_async(struct fusbh200_hcd *fusbh200)
-{
- if (--fusbh200->async_count)
- return;
-
- /* The async schedule and async_unlink list are supposed to be empty */
- WARN_ON(fusbh200->async->qh_next.qh || fusbh200->async_unlink);
-
- /* Don't turn off the schedule until ASS is 1 */
- fusbh200_poll_ASS(fusbh200);
-}
-
-/* move qh (and its qtds) onto async queue; maybe enable queue. */
-
-static void qh_link_async (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- __hc32 dma = QH_NEXT(fusbh200, qh->qh_dma);
- struct fusbh200_qh *head;
-
- /* Don't link a QH if there's a Clear-TT-Buffer pending */
- if (unlikely(qh->clearing_tt))
- return;
-
- WARN_ON(qh->qh_state != QH_STATE_IDLE);
-
- /* clear halt and/or toggle; and maybe recover from silicon quirk */
- qh_refresh(fusbh200, qh);
-
- /* splice right after start */
- head = fusbh200->async;
- qh->qh_next = head->qh_next;
- qh->hw->hw_next = head->hw->hw_next;
- wmb ();
-
- head->qh_next.qh = qh;
- head->hw->hw_next = dma;
-
- qh->xacterrs = 0;
- qh->qh_state = QH_STATE_LINKED;
- /* qtd completions reported later by interrupt */
-
- enable_async(fusbh200);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * For control/bulk/interrupt, return QH with these TDs appended.
- * Allocates and initializes the QH if necessary.
- * Returns null if it can't allocate a QH it needs to.
- * If the QH has TDs (urbs) already, that's great.
- */
-static struct fusbh200_qh *qh_append_tds (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- struct list_head *qtd_list,
- int epnum,
- void **ptr
-)
-{
- struct fusbh200_qh *qh = NULL;
- __hc32 qh_addr_mask = cpu_to_hc32(fusbh200, 0x7f);
-
- qh = (struct fusbh200_qh *) *ptr;
- if (unlikely (qh == NULL)) {
- /* can't sleep here, we have fusbh200->lock... */
- qh = qh_make (fusbh200, urb, GFP_ATOMIC);
- *ptr = qh;
- }
- if (likely (qh != NULL)) {
- struct fusbh200_qtd *qtd;
-
- if (unlikely (list_empty (qtd_list)))
- qtd = NULL;
- else
- qtd = list_entry (qtd_list->next, struct fusbh200_qtd,
- qtd_list);
-
- /* control qh may need patching ... */
- if (unlikely (epnum == 0)) {
-
- /* usb_reset_device() briefly reverts to address 0 */
- if (usb_pipedevice (urb->pipe) == 0)
- qh->hw->hw_info1 &= ~qh_addr_mask;
- }
-
- /* just one way to queue requests: swap with the dummy qtd.
- * only hc or qh_refresh() ever modify the overlay.
- */
- if (likely (qtd != NULL)) {
- struct fusbh200_qtd *dummy;
- dma_addr_t dma;
- __hc32 token;
-
- /* to avoid racing the HC, use the dummy td instead of
- * the first td of our list (becomes new dummy). both
- * tds stay deactivated until we're done, when the
- * HC is allowed to fetch the old dummy (4.10.2).
- */
- token = qtd->hw_token;
- qtd->hw_token = HALT_BIT(fusbh200);
-
- dummy = qh->dummy;
-
- dma = dummy->qtd_dma;
- *dummy = *qtd;
- dummy->qtd_dma = dma;
-
- list_del (&qtd->qtd_list);
- list_add (&dummy->qtd_list, qtd_list);
- list_splice_tail(qtd_list, &qh->qtd_list);
-
- fusbh200_qtd_init(fusbh200, qtd, qtd->qtd_dma);
- qh->dummy = qtd;
-
- /* hc must see the new dummy at list end */
- dma = qtd->qtd_dma;
- qtd = list_entry (qh->qtd_list.prev,
- struct fusbh200_qtd, qtd_list);
- qtd->hw_next = QTD_NEXT(fusbh200, dma);
-
- /* let the hc process these next qtds */
- wmb ();
- dummy->hw_token = token;
-
- urb->hcpriv = qh;
- }
- }
- return qh;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-submit_async (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- struct list_head *qtd_list,
- gfp_t mem_flags
-) {
- int epnum;
- unsigned long flags;
- struct fusbh200_qh *qh = NULL;
- int rc;
-
- epnum = urb->ep->desc.bEndpointAddress;
-
-#ifdef FUSBH200_URB_TRACE
- {
- struct fusbh200_qtd *qtd;
- qtd = list_entry(qtd_list->next, struct fusbh200_qtd, qtd_list);
- fusbh200_dbg(fusbh200,
- "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
- __func__, urb->dev->devpath, urb,
- epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
- urb->transfer_buffer_length,
- qtd, urb->ep->hcpriv);
- }
-#endif
-
- spin_lock_irqsave (&fusbh200->lock, flags);
- if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
- rc = -ESHUTDOWN;
- goto done;
- }
- rc = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
- if (unlikely(rc))
- goto done;
-
- qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv);
- if (unlikely(qh == NULL)) {
- usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
- rc = -ENOMEM;
- goto done;
- }
-
- /* Control/bulk operations through TTs don't need scheduling,
- * the HC and TT handle it when the TT has a buffer ready.
- */
- if (likely (qh->qh_state == QH_STATE_IDLE))
- qh_link_async(fusbh200, qh);
- done:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- if (unlikely (qh == NULL))
- qtd_list_free (fusbh200, urb, qtd_list);
- return rc;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void single_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- struct fusbh200_qh *prev;
-
- /* Add to the end of the list of QHs waiting for the next IAAD */
- qh->qh_state = QH_STATE_UNLINK;
- if (fusbh200->async_unlink)
- fusbh200->async_unlink_last->unlink_next = qh;
- else
- fusbh200->async_unlink = qh;
- fusbh200->async_unlink_last = qh;
-
- /* Unlink it from the schedule */
- prev = fusbh200->async;
- while (prev->qh_next.qh != qh)
- prev = prev->qh_next.qh;
-
- prev->hw->hw_next = qh->hw->hw_next;
- prev->qh_next = qh->qh_next;
- if (fusbh200->qh_scan_next == qh)
- fusbh200->qh_scan_next = qh->qh_next.qh;
-}
-
-static void start_iaa_cycle(struct fusbh200_hcd *fusbh200, bool nested)
-{
- /*
- * Do nothing if an IAA cycle is already running or
- * if one will be started shortly.
- */
- if (fusbh200->async_iaa || fusbh200->async_unlinking)
- return;
-
- /* Do all the waiting QHs at once */
- fusbh200->async_iaa = fusbh200->async_unlink;
- fusbh200->async_unlink = NULL;
-
- /* If the controller isn't running, we don't have to wait for it */
- if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING)) {
- if (!nested) /* Avoid recursion */
- end_unlink_async(fusbh200);
-
- /* Otherwise start a new IAA cycle */
- } else if (likely(fusbh200->rh_state == FUSBH200_RH_RUNNING)) {
- /* Make sure the unlinks are all visible to the hardware */
- wmb();
-
- fusbh200_writel(fusbh200, fusbh200->command | CMD_IAAD,
- &fusbh200->regs->command);
- fusbh200_readl(fusbh200, &fusbh200->regs->command);
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IAA_WATCHDOG, true);
- }
-}
-
-/* the async qh for the qtds being unlinked are now gone from the HC */
-
-static void end_unlink_async(struct fusbh200_hcd *fusbh200)
-{
- struct fusbh200_qh *qh;
-
- /* Process the idle QHs */
- restart:
- fusbh200->async_unlinking = true;
- while (fusbh200->async_iaa) {
- qh = fusbh200->async_iaa;
- fusbh200->async_iaa = qh->unlink_next;
- qh->unlink_next = NULL;
-
- qh->qh_state = QH_STATE_IDLE;
- qh->qh_next.qh = NULL;
-
- qh_completions(fusbh200, qh);
- if (!list_empty(&qh->qtd_list) &&
- fusbh200->rh_state == FUSBH200_RH_RUNNING)
- qh_link_async(fusbh200, qh);
- disable_async(fusbh200);
- }
- fusbh200->async_unlinking = false;
-
- /* Start a new IAA cycle if any QHs are waiting for it */
- if (fusbh200->async_unlink) {
- start_iaa_cycle(fusbh200, true);
- if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING))
- goto restart;
- }
-}
-
-static void unlink_empty_async(struct fusbh200_hcd *fusbh200)
-{
- struct fusbh200_qh *qh, *next;
- bool stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING);
- bool check_unlinks_later = false;
-
- /* Unlink all the async QHs that have been empty for a timer cycle */
- next = fusbh200->async->qh_next.qh;
- while (next) {
- qh = next;
- next = qh->qh_next.qh;
-
- if (list_empty(&qh->qtd_list) &&
- qh->qh_state == QH_STATE_LINKED) {
- if (!stopped && qh->unlink_cycle ==
- fusbh200->async_unlink_cycle)
- check_unlinks_later = true;
- else
- single_unlink_async(fusbh200, qh);
- }
- }
-
- /* Start a new IAA cycle if any QHs are waiting for it */
- if (fusbh200->async_unlink)
- start_iaa_cycle(fusbh200, false);
-
- /* QHs that haven't been empty for long enough will be handled later */
- if (check_unlinks_later) {
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true);
- ++fusbh200->async_unlink_cycle;
- }
-}
-
-/* makes sure the async qh will become idle */
-/* caller must own fusbh200->lock */
-
-static void start_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- /*
- * If the QH isn't linked then there's nothing we can do
- * unless we were called during a giveback, in which case
- * qh_completions() has to deal with it.
- */
- if (qh->qh_state != QH_STATE_LINKED) {
- if (qh->qh_state == QH_STATE_COMPLETING)
- qh->needs_rescan = 1;
- return;
- }
-
- single_unlink_async(fusbh200, qh);
- start_iaa_cycle(fusbh200, false);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void scan_async (struct fusbh200_hcd *fusbh200)
-{
- struct fusbh200_qh *qh;
- bool check_unlinks_later = false;
-
- fusbh200->qh_scan_next = fusbh200->async->qh_next.qh;
- while (fusbh200->qh_scan_next) {
- qh = fusbh200->qh_scan_next;
- fusbh200->qh_scan_next = qh->qh_next.qh;
- rescan:
- /* clean any finished work for this qh */
- if (!list_empty(&qh->qtd_list)) {
- int temp;
-
- /*
- * Unlinks could happen here; completion reporting
- * drops the lock. That's why fusbh200->qh_scan_next
- * always holds the next qh to scan; if the next qh
- * gets unlinked then fusbh200->qh_scan_next is adjusted
- * in single_unlink_async().
- */
- temp = qh_completions(fusbh200, qh);
- if (qh->needs_rescan) {
- start_unlink_async(fusbh200, qh);
- } else if (list_empty(&qh->qtd_list)
- && qh->qh_state == QH_STATE_LINKED) {
- qh->unlink_cycle = fusbh200->async_unlink_cycle;
- check_unlinks_later = true;
- } else if (temp != 0)
- goto rescan;
- }
- }
-
- /*
- * Unlink empty entries, reducing DMA usage as well
- * as HCD schedule-scanning costs. Delay for any qh
- * we just scanned, there's a not-unusual case that it
- * doesn't stay idle for long.
- */
- if (check_unlinks_later && fusbh200->rh_state == FUSBH200_RH_RUNNING &&
- !(fusbh200->enabled_hrtimer_events &
- BIT(FUSBH200_HRTIMER_ASYNC_UNLINKS))) {
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true);
- ++fusbh200->async_unlink_cycle;
- }
-}
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI scheduled transaction support: interrupt, iso, split iso
- * These are called "periodic" transactions in the EHCI spec.
- *
- * Note that for interrupt transfers, the QH/QTD manipulation is shared
- * with the "asynchronous" transaction support (control/bulk transfers).
- * The only real difference is in how interrupt transfers are scheduled.
- *
- * For ISO, we make an "iso_stream" head to serve the same role as a QH.
- * It keeps track of every ITD (or SITD) that's linked, and holds enough
- * pre-calculated schedule data to make appending to the queue be quick.
- */
-
-static int fusbh200_get_frame (struct usb_hcd *hcd);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * periodic_next_shadow - return "next" pointer on shadow list
- * @periodic: host pointer to qh/itd
- * @tag: hardware tag for type of this record
- */
-static union fusbh200_shadow *
-periodic_next_shadow(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic,
- __hc32 tag)
-{
- switch (hc32_to_cpu(fusbh200, tag)) {
- case Q_TYPE_QH:
- return &periodic->qh->qh_next;
- case Q_TYPE_FSTN:
- return &periodic->fstn->fstn_next;
- default:
- return &periodic->itd->itd_next;
- }
-}
-
-static __hc32 *
-shadow_next_periodic(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic,
- __hc32 tag)
-{
- switch (hc32_to_cpu(fusbh200, tag)) {
- /* our fusbh200_shadow.qh is actually software part */
- case Q_TYPE_QH:
- return &periodic->qh->hw->hw_next;
- /* others are hw parts */
- default:
- return periodic->hw_next;
- }
-}
-
-/* caller must hold fusbh200->lock */
-static void periodic_unlink (struct fusbh200_hcd *fusbh200, unsigned frame, void *ptr)
-{
- union fusbh200_shadow *prev_p = &fusbh200->pshadow[frame];
- __hc32 *hw_p = &fusbh200->periodic[frame];
- union fusbh200_shadow here = *prev_p;
-
- /* find predecessor of "ptr"; hw and shadow lists are in sync */
- while (here.ptr && here.ptr != ptr) {
- prev_p = periodic_next_shadow(fusbh200, prev_p,
- Q_NEXT_TYPE(fusbh200, *hw_p));
- hw_p = shadow_next_periodic(fusbh200, &here,
- Q_NEXT_TYPE(fusbh200, *hw_p));
- here = *prev_p;
- }
- /* an interrupt entry (at list end) could have been shared */
- if (!here.ptr)
- return;
-
- /* update shadow and hardware lists ... the old "next" pointers
- * from ptr may still be in use, the caller updates them.
- */
- *prev_p = *periodic_next_shadow(fusbh200, &here,
- Q_NEXT_TYPE(fusbh200, *hw_p));
-
- *hw_p = *shadow_next_periodic(fusbh200, &here,
- Q_NEXT_TYPE(fusbh200, *hw_p));
-}
-
-/* how many of the uframe's 125 usecs are allocated? */
-static unsigned short
-periodic_usecs (struct fusbh200_hcd *fusbh200, unsigned frame, unsigned uframe)
-{
- __hc32 *hw_p = &fusbh200->periodic [frame];
- union fusbh200_shadow *q = &fusbh200->pshadow [frame];
- unsigned usecs = 0;
- struct fusbh200_qh_hw *hw;
-
- while (q->ptr) {
- switch (hc32_to_cpu(fusbh200, Q_NEXT_TYPE(fusbh200, *hw_p))) {
- case Q_TYPE_QH:
- hw = q->qh->hw;
- /* is it in the S-mask? */
- if (hw->hw_info2 & cpu_to_hc32(fusbh200, 1 << uframe))
- usecs += q->qh->usecs;
- /* ... or C-mask? */
- if (hw->hw_info2 & cpu_to_hc32(fusbh200,
- 1 << (8 + uframe)))
- usecs += q->qh->c_usecs;
- hw_p = &hw->hw_next;
- q = &q->qh->qh_next;
- break;
- // case Q_TYPE_FSTN:
- default:
- /* for "save place" FSTNs, count the relevant INTR
- * bandwidth from the previous frame
- */
- if (q->fstn->hw_prev != FUSBH200_LIST_END(fusbh200)) {
- fusbh200_dbg (fusbh200, "ignoring FSTN cost ...\n");
- }
- hw_p = &q->fstn->hw_next;
- q = &q->fstn->fstn_next;
- break;
- case Q_TYPE_ITD:
- if (q->itd->hw_transaction[uframe])
- usecs += q->itd->stream->usecs;
- hw_p = &q->itd->hw_next;
- q = &q->itd->itd_next;
- break;
- }
- }
- if (usecs > fusbh200->uframe_periodic_max)
- fusbh200_err (fusbh200, "uframe %d sched overrun: %d usecs\n",
- frame * 8 + uframe, usecs);
- return usecs;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
-{
- if (!dev1->tt || !dev2->tt)
- return 0;
- if (dev1->tt != dev2->tt)
- return 0;
- if (dev1->tt->multi)
- return dev1->ttport == dev2->ttport;
- else
- return 1;
-}
-
-/* return true iff the device's transaction translator is available
- * for a periodic transfer starting at the specified frame, using
- * all the uframes in the mask.
- */
-static int tt_no_collision (
- struct fusbh200_hcd *fusbh200,
- unsigned period,
- struct usb_device *dev,
- unsigned frame,
- u32 uf_mask
-)
-{
- if (period == 0) /* error */
- return 0;
-
- /* note bandwidth wastage: split never follows csplit
- * (different dev or endpoint) until the next uframe.
- * calling convention doesn't make that distinction.
- */
- for (; frame < fusbh200->periodic_size; frame += period) {
- union fusbh200_shadow here;
- __hc32 type;
- struct fusbh200_qh_hw *hw;
-
- here = fusbh200->pshadow [frame];
- type = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [frame]);
- while (here.ptr) {
- switch (hc32_to_cpu(fusbh200, type)) {
- case Q_TYPE_ITD:
- type = Q_NEXT_TYPE(fusbh200, here.itd->hw_next);
- here = here.itd->itd_next;
- continue;
- case Q_TYPE_QH:
- hw = here.qh->hw;
- if (same_tt (dev, here.qh->dev)) {
- u32 mask;
-
- mask = hc32_to_cpu(fusbh200,
- hw->hw_info2);
- /* "knows" no gap is needed */
- mask |= mask >> 8;
- if (mask & uf_mask)
- break;
- }
- type = Q_NEXT_TYPE(fusbh200, hw->hw_next);
- here = here.qh->qh_next;
- continue;
- // case Q_TYPE_FSTN:
- default:
- fusbh200_dbg (fusbh200,
- "periodic frame %d bogus type %d\n",
- frame, type);
- }
-
- /* collision or error */
- return 0;
- }
- }
-
- /* no collision */
- return 1;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void enable_periodic(struct fusbh200_hcd *fusbh200)
-{
- if (fusbh200->periodic_count++)
- return;
-
- /* Stop waiting to turn off the periodic schedule */
- fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_PERIODIC);
-
- /* Don't start the schedule until PSS is 0 */
- fusbh200_poll_PSS(fusbh200);
- turn_on_io_watchdog(fusbh200);
-}
-
-static void disable_periodic(struct fusbh200_hcd *fusbh200)
-{
- if (--fusbh200->periodic_count)
- return;
-
- /* Don't turn off the schedule until PSS is 1 */
- fusbh200_poll_PSS(fusbh200);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* periodic schedule slots have iso tds (normal or split) first, then a
- * sparse tree for active interrupt transfers.
- *
- * this just links in a qh; caller guarantees uframe masks are set right.
- * no FSTN support (yet; fusbh200 0.96+)
- */
-static void qh_link_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- unsigned i;
- unsigned period = qh->period;
-
- dev_dbg (&qh->dev->dev,
- "link qh%d-%04x/%p start %d [%d/%d us]\n",
- period, hc32_to_cpup(fusbh200, &qh->hw->hw_info2)
- & (QH_CMASK | QH_SMASK),
- qh, qh->start, qh->usecs, qh->c_usecs);
-
- /* high bandwidth, or otherwise every microframe */
- if (period == 0)
- period = 1;
-
- for (i = qh->start; i < fusbh200->periodic_size; i += period) {
- union fusbh200_shadow *prev = &fusbh200->pshadow[i];
- __hc32 *hw_p = &fusbh200->periodic[i];
- union fusbh200_shadow here = *prev;
- __hc32 type = 0;
-
- /* skip the iso nodes at list head */
- while (here.ptr) {
- type = Q_NEXT_TYPE(fusbh200, *hw_p);
- if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH))
- break;
- prev = periodic_next_shadow(fusbh200, prev, type);
- hw_p = shadow_next_periodic(fusbh200, &here, type);
- here = *prev;
- }
-
- /* sorting each branch by period (slow-->fast)
- * enables sharing interior tree nodes
- */
- while (here.ptr && qh != here.qh) {
- if (qh->period > here.qh->period)
- break;
- prev = &here.qh->qh_next;
- hw_p = &here.qh->hw->hw_next;
- here = *prev;
- }
- /* link in this qh, unless some earlier pass did that */
- if (qh != here.qh) {
- qh->qh_next = here;
- if (here.qh)
- qh->hw->hw_next = *hw_p;
- wmb ();
- prev->qh = qh;
- *hw_p = QH_NEXT (fusbh200, qh->qh_dma);
- }
- }
- qh->qh_state = QH_STATE_LINKED;
- qh->xacterrs = 0;
-
- /* update per-qh bandwidth for usbfs */
- fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated += qh->period
- ? ((qh->usecs + qh->c_usecs) / qh->period)
- : (qh->usecs * 8);
-
- list_add(&qh->intr_node, &fusbh200->intr_qh_list);
-
- /* maybe enable periodic schedule processing */
- ++fusbh200->intr_count;
- enable_periodic(fusbh200);
-}
-
-static void qh_unlink_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- unsigned i;
- unsigned period;
-
- /*
- * If qh is for a low/full-speed device, simply unlinking it
- * could interfere with an ongoing split transaction. To unlink
- * it safely would require setting the QH_INACTIVATE bit and
- * waiting at least one frame, as described in EHCI 4.12.2.5.
- *
- * We won't bother with any of this. Instead, we assume that the
- * only reason for unlinking an interrupt QH while the current URB
- * is still active is to dequeue all the URBs (flush the whole
- * endpoint queue).
- *
- * If rebalancing the periodic schedule is ever implemented, this
- * approach will no longer be valid.
- */
-
- /* high bandwidth, or otherwise part of every microframe */
- if ((period = qh->period) == 0)
- period = 1;
-
- for (i = qh->start; i < fusbh200->periodic_size; i += period)
- periodic_unlink (fusbh200, i, qh);
-
- /* update per-qh bandwidth for usbfs */
- fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated -= qh->period
- ? ((qh->usecs + qh->c_usecs) / qh->period)
- : (qh->usecs * 8);
-
- dev_dbg (&qh->dev->dev,
- "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
- qh->period,
- hc32_to_cpup(fusbh200, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
- qh, qh->start, qh->usecs, qh->c_usecs);
-
- /* qh->qh_next still "live" to HC */
- qh->qh_state = QH_STATE_UNLINK;
- qh->qh_next.ptr = NULL;
-
- if (fusbh200->qh_scan_next == qh)
- fusbh200->qh_scan_next = list_entry(qh->intr_node.next,
- struct fusbh200_qh, intr_node);
- list_del(&qh->intr_node);
-}
-
-static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- /* If the QH isn't linked then there's nothing we can do
- * unless we were called during a giveback, in which case
- * qh_completions() has to deal with it.
- */
- if (qh->qh_state != QH_STATE_LINKED) {
- if (qh->qh_state == QH_STATE_COMPLETING)
- qh->needs_rescan = 1;
- return;
- }
-
- qh_unlink_periodic (fusbh200, qh);
-
- /* Make sure the unlinks are visible before starting the timer */
- wmb();
-
- /*
- * The EHCI spec doesn't say how long it takes the controller to
- * stop accessing an unlinked interrupt QH. The timer delay is
- * 9 uframes; presumably that will be long enough.
- */
- qh->unlink_cycle = fusbh200->intr_unlink_cycle;
-
- /* New entries go at the end of the intr_unlink list */
- if (fusbh200->intr_unlink)
- fusbh200->intr_unlink_last->unlink_next = qh;
- else
- fusbh200->intr_unlink = qh;
- fusbh200->intr_unlink_last = qh;
-
- if (fusbh200->intr_unlinking)
- ; /* Avoid recursive calls */
- else if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
- fusbh200_handle_intr_unlinks(fusbh200);
- else if (fusbh200->intr_unlink == qh) {
- fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true);
- ++fusbh200->intr_unlink_cycle;
- }
-}
-
-static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- struct fusbh200_qh_hw *hw = qh->hw;
- int rc;
-
- qh->qh_state = QH_STATE_IDLE;
- hw->hw_next = FUSBH200_LIST_END(fusbh200);
-
- qh_completions(fusbh200, qh);
-
- /* reschedule QH iff another request is queued */
- if (!list_empty(&qh->qtd_list) && fusbh200->rh_state == FUSBH200_RH_RUNNING) {
- rc = qh_schedule(fusbh200, qh);
-
- /* An error here likely indicates handshake failure
- * or no space left in the schedule. Neither fault
- * should happen often ...
- *
- * FIXME kill the now-dysfunctional queued urbs
- */
- if (rc != 0)
- fusbh200_err(fusbh200, "can't reschedule qh %p, err %d\n",
- qh, rc);
- }
-
- /* maybe turn off periodic schedule */
- --fusbh200->intr_count;
- disable_periodic(fusbh200);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int check_period (
- struct fusbh200_hcd *fusbh200,
- unsigned frame,
- unsigned uframe,
- unsigned period,
- unsigned usecs
-) {
- int claimed;
-
- /* complete split running into next frame?
- * given FSTN support, we could sometimes check...
- */
- if (uframe >= 8)
- return 0;
-
- /* convert "usecs we need" to "max already claimed" */
- usecs = fusbh200->uframe_periodic_max - usecs;
-
- /* we "know" 2 and 4 uframe intervals were rejected; so
- * for period 0, check _every_ microframe in the schedule.
- */
- if (unlikely (period == 0)) {
- do {
- for (uframe = 0; uframe < 7; uframe++) {
- claimed = periodic_usecs (fusbh200, frame, uframe);
- if (claimed > usecs)
- return 0;
- }
- } while ((frame += 1) < fusbh200->periodic_size);
-
- /* just check the specified uframe, at that period */
- } else {
- do {
- claimed = periodic_usecs (fusbh200, frame, uframe);
- if (claimed > usecs)
- return 0;
- } while ((frame += period) < fusbh200->periodic_size);
- }
-
- // success!
- return 1;
-}
-
-static int check_intr_schedule (
- struct fusbh200_hcd *fusbh200,
- unsigned frame,
- unsigned uframe,
- const struct fusbh200_qh *qh,
- __hc32 *c_maskp
-)
-{
- int retval = -ENOSPC;
- u8 mask = 0;
-
- if (qh->c_usecs && uframe >= 6) /* FSTN territory? */
- goto done;
-
- if (!check_period (fusbh200, frame, uframe, qh->period, qh->usecs))
- goto done;
- if (!qh->c_usecs) {
- retval = 0;
- *c_maskp = 0;
- goto done;
- }
-
- /* Make sure this tt's buffer is also available for CSPLITs.
- * We pessimize a bit; probably the typical full speed case
- * doesn't need the second CSPLIT.
- *
- * NOTE: both SPLIT and CSPLIT could be checked in just
- * one smart pass...
- */
- mask = 0x03 << (uframe + qh->gap_uf);
- *c_maskp = cpu_to_hc32(fusbh200, mask << 8);
-
- mask |= 1 << uframe;
- if (tt_no_collision (fusbh200, qh->period, qh->dev, frame, mask)) {
- if (!check_period (fusbh200, frame, uframe + qh->gap_uf + 1,
- qh->period, qh->c_usecs))
- goto done;
- if (!check_period (fusbh200, frame, uframe + qh->gap_uf,
- qh->period, qh->c_usecs))
- goto done;
- retval = 0;
- }
-done:
- return retval;
-}
-
-/* "first fit" scheduling policy used the first time through,
- * or when the previous schedule slot can't be re-used.
- */
-static int qh_schedule(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
- int status;
- unsigned uframe;
- __hc32 c_mask;
- unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
- struct fusbh200_qh_hw *hw = qh->hw;
-
- qh_refresh(fusbh200, qh);
- hw->hw_next = FUSBH200_LIST_END(fusbh200);
- frame = qh->start;
-
- /* reuse the previous schedule slots, if we can */
- if (frame < qh->period) {
- uframe = ffs(hc32_to_cpup(fusbh200, &hw->hw_info2) & QH_SMASK);
- status = check_intr_schedule (fusbh200, frame, --uframe,
- qh, &c_mask);
- } else {
- uframe = 0;
- c_mask = 0;
- status = -ENOSPC;
- }
-
- /* else scan the schedule to find a group of slots such that all
- * uframes have enough periodic bandwidth available.
- */
- if (status) {
- /* "normal" case, uframing flexible except with splits */
- if (qh->period) {
- int i;
-
- for (i = qh->period; status && i > 0; --i) {
- frame = ++fusbh200->random_frame % qh->period;
- for (uframe = 0; uframe < 8; uframe++) {
- status = check_intr_schedule (fusbh200,
- frame, uframe, qh,
- &c_mask);
- if (status == 0)
- break;
- }
- }
-
- /* qh->period == 0 means every uframe */
- } else {
- frame = 0;
- status = check_intr_schedule (fusbh200, 0, 0, qh, &c_mask);
- }
- if (status)
- goto done;
- qh->start = frame;
-
- /* reset S-frame and (maybe) C-frame masks */
- hw->hw_info2 &= cpu_to_hc32(fusbh200, ~(QH_CMASK | QH_SMASK));
- hw->hw_info2 |= qh->period
- ? cpu_to_hc32(fusbh200, 1 << uframe)
- : cpu_to_hc32(fusbh200, QH_SMASK);
- hw->hw_info2 |= c_mask;
- } else
- fusbh200_dbg (fusbh200, "reused qh %p schedule\n", qh);
-
- /* stuff into the periodic schedule */
- qh_link_periodic(fusbh200, qh);
-done:
- return status;
-}
-
-static int intr_submit (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- struct list_head *qtd_list,
- gfp_t mem_flags
-) {
- unsigned epnum;
- unsigned long flags;
- struct fusbh200_qh *qh;
- int status;
- struct list_head empty;
-
- /* get endpoint and transfer/schedule data */
- epnum = urb->ep->desc.bEndpointAddress;
-
- spin_lock_irqsave (&fusbh200->lock, flags);
-
- if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
- status = -ESHUTDOWN;
- goto done_not_linked;
- }
- status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
- if (unlikely(status))
- goto done_not_linked;
-
- /* get qh and force any scheduling errors */
- INIT_LIST_HEAD (&empty);
- qh = qh_append_tds(fusbh200, urb, &empty, epnum, &urb->ep->hcpriv);
- if (qh == NULL) {
- status = -ENOMEM;
- goto done;
- }
- if (qh->qh_state == QH_STATE_IDLE) {
- if ((status = qh_schedule (fusbh200, qh)) != 0)
- goto done;
- }
-
- /* then queue the urb's tds to the qh */
- qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv);
- BUG_ON (qh == NULL);
-
- /* ... update usbfs periodic stats */
- fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs++;
-
-done:
- if (unlikely(status))
- usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
-done_not_linked:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- if (status)
- qtd_list_free (fusbh200, urb, qtd_list);
-
- return status;
-}
-
-static void scan_intr(struct fusbh200_hcd *fusbh200)
-{
- struct fusbh200_qh *qh;
-
- list_for_each_entry_safe(qh, fusbh200->qh_scan_next, &fusbh200->intr_qh_list,
- intr_node) {
- rescan:
- /* clean any finished work for this qh */
- if (!list_empty(&qh->qtd_list)) {
- int temp;
-
- /*
- * Unlinks could happen here; completion reporting
- * drops the lock. That's why fusbh200->qh_scan_next
- * always holds the next qh to scan; if the next qh
- * gets unlinked then fusbh200->qh_scan_next is adjusted
- * in qh_unlink_periodic().
- */
- temp = qh_completions(fusbh200, qh);
- if (unlikely(qh->needs_rescan ||
- (list_empty(&qh->qtd_list) &&
- qh->qh_state == QH_STATE_LINKED)))
- start_unlink_intr(fusbh200, qh);
- else if (temp != 0)
- goto rescan;
- }
- }
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* fusbh200_iso_stream ops work with both ITD and SITD */
-
-static struct fusbh200_iso_stream *
-iso_stream_alloc (gfp_t mem_flags)
-{
- struct fusbh200_iso_stream *stream;
-
- stream = kzalloc(sizeof *stream, mem_flags);
- if (likely (stream != NULL)) {
- INIT_LIST_HEAD(&stream->td_list);
- INIT_LIST_HEAD(&stream->free_list);
- stream->next_uframe = -1;
- }
- return stream;
-}
-
-static void
-iso_stream_init (
- struct fusbh200_hcd *fusbh200,
- struct fusbh200_iso_stream *stream,
- struct usb_device *dev,
- int pipe,
- unsigned interval
-)
-{
- u32 buf1;
- unsigned epnum, maxp;
- int is_input;
- long bandwidth;
- unsigned multi;
-
- /*
- * this might be a "high bandwidth" highspeed endpoint,
- * as encoded in the ep descriptor's wMaxPacket field
- */
- epnum = usb_pipeendpoint (pipe);
- is_input = usb_pipein (pipe) ? USB_DIR_IN : 0;
- maxp = usb_maxpacket(dev, pipe, !is_input);
- if (is_input) {
- buf1 = (1 << 11);
- } else {
- buf1 = 0;
- }
-
- maxp = max_packet(maxp);
- multi = hb_mult(maxp);
- buf1 |= maxp;
- maxp *= multi;
-
- stream->buf0 = cpu_to_hc32(fusbh200, (epnum << 8) | dev->devnum);
- stream->buf1 = cpu_to_hc32(fusbh200, buf1);
- stream->buf2 = cpu_to_hc32(fusbh200, multi);
-
- /* usbfs wants to report the average usecs per frame tied up
- * when transfers on this endpoint are scheduled ...
- */
- if (dev->speed == USB_SPEED_FULL) {
- interval <<= 3;
- stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed,
- is_input, 1, maxp));
- stream->usecs /= 8;
- } else {
- stream->highspeed = 1;
- stream->usecs = HS_USECS_ISO (maxp);
- }
- bandwidth = stream->usecs * 8;
- bandwidth /= interval;
-
- stream->bandwidth = bandwidth;
- stream->udev = dev;
- stream->bEndpointAddress = is_input | epnum;
- stream->interval = interval;
- stream->maxp = maxp;
-}
-
-static struct fusbh200_iso_stream *
-iso_stream_find (struct fusbh200_hcd *fusbh200, struct urb *urb)
-{
- unsigned epnum;
- struct fusbh200_iso_stream *stream;
- struct usb_host_endpoint *ep;
- unsigned long flags;
-
- epnum = usb_pipeendpoint (urb->pipe);
- if (usb_pipein(urb->pipe))
- ep = urb->dev->ep_in[epnum];
- else
- ep = urb->dev->ep_out[epnum];
-
- spin_lock_irqsave (&fusbh200->lock, flags);
- stream = ep->hcpriv;
-
- if (unlikely (stream == NULL)) {
- stream = iso_stream_alloc(GFP_ATOMIC);
- if (likely (stream != NULL)) {
- ep->hcpriv = stream;
- stream->ep = ep;
- iso_stream_init(fusbh200, stream, urb->dev, urb->pipe,
- urb->interval);
- }
-
- /* if dev->ep [epnum] is a QH, hw is set */
- } else if (unlikely (stream->hw != NULL)) {
- fusbh200_dbg (fusbh200, "dev %s ep%d%s, not iso??\n",
- urb->dev->devpath, epnum,
- usb_pipein(urb->pipe) ? "in" : "out");
- stream = NULL;
- }
-
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- return stream;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* fusbh200_iso_sched ops can be ITD-only or SITD-only */
-
-static struct fusbh200_iso_sched *
-iso_sched_alloc (unsigned packets, gfp_t mem_flags)
-{
- struct fusbh200_iso_sched *iso_sched;
- int size = sizeof *iso_sched;
-
- size += packets * sizeof (struct fusbh200_iso_packet);
- iso_sched = kzalloc(size, mem_flags);
- if (likely (iso_sched != NULL)) {
- INIT_LIST_HEAD (&iso_sched->td_list);
- }
- return iso_sched;
-}
-
-static inline void
-itd_sched_init(
- struct fusbh200_hcd *fusbh200,
- struct fusbh200_iso_sched *iso_sched,
- struct fusbh200_iso_stream *stream,
- struct urb *urb
-)
-{
- unsigned i;
- dma_addr_t dma = urb->transfer_dma;
-
- /* how many uframes are needed for these transfers */
- iso_sched->span = urb->number_of_packets * stream->interval;
-
- /* figure out per-uframe itd fields that we'll need later
- * when we fit new itds into the schedule.
- */
- for (i = 0; i < urb->number_of_packets; i++) {
- struct fusbh200_iso_packet *uframe = &iso_sched->packet [i];
- unsigned length;
- dma_addr_t buf;
- u32 trans;
-
- length = urb->iso_frame_desc [i].length;
- buf = dma + urb->iso_frame_desc [i].offset;
-
- trans = FUSBH200_ISOC_ACTIVE;
- trans |= buf & 0x0fff;
- if (unlikely (((i + 1) == urb->number_of_packets))
- && !(urb->transfer_flags & URB_NO_INTERRUPT))
- trans |= FUSBH200_ITD_IOC;
- trans |= length << 16;
- uframe->transaction = cpu_to_hc32(fusbh200, trans);
-
- /* might need to cross a buffer page within a uframe */
- uframe->bufp = (buf & ~(u64)0x0fff);
- buf += length;
- if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
- uframe->cross = 1;
- }
-}
-
-static void
-iso_sched_free (
- struct fusbh200_iso_stream *stream,
- struct fusbh200_iso_sched *iso_sched
-)
-{
- if (!iso_sched)
- return;
- // caller must hold fusbh200->lock!
- list_splice (&iso_sched->td_list, &stream->free_list);
- kfree (iso_sched);
-}
-
-static int
-itd_urb_transaction (
- struct fusbh200_iso_stream *stream,
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- gfp_t mem_flags
-)
-{
- struct fusbh200_itd *itd;
- dma_addr_t itd_dma;
- int i;
- unsigned num_itds;
- struct fusbh200_iso_sched *sched;
- unsigned long flags;
-
- sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
- if (unlikely (sched == NULL))
- return -ENOMEM;
-
- itd_sched_init(fusbh200, sched, stream, urb);
-
- if (urb->interval < 8)
- num_itds = 1 + (sched->span + 7) / 8;
- else
- num_itds = urb->number_of_packets;
-
- /* allocate/init ITDs */
- spin_lock_irqsave (&fusbh200->lock, flags);
- for (i = 0; i < num_itds; i++) {
-
- /*
- * Use iTDs from the free list, but not iTDs that may
- * still be in use by the hardware.
- */
- if (likely(!list_empty(&stream->free_list))) {
- itd = list_first_entry(&stream->free_list,
- struct fusbh200_itd, itd_list);
- if (itd->frame == fusbh200->now_frame)
- goto alloc_itd;
- list_del (&itd->itd_list);
- itd_dma = itd->itd_dma;
- } else {
- alloc_itd:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- itd = dma_pool_alloc (fusbh200->itd_pool, mem_flags,
- &itd_dma);
- spin_lock_irqsave (&fusbh200->lock, flags);
- if (!itd) {
- iso_sched_free(stream, sched);
- spin_unlock_irqrestore(&fusbh200->lock, flags);
- return -ENOMEM;
- }
- }
-
- memset (itd, 0, sizeof *itd);
- itd->itd_dma = itd_dma;
- list_add (&itd->itd_list, &sched->td_list);
- }
- spin_unlock_irqrestore (&fusbh200->lock, flags);
-
- /* temporarily store schedule info in hcpriv */
- urb->hcpriv = sched;
- urb->error_count = 0;
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-itd_slot_ok (
- struct fusbh200_hcd *fusbh200,
- u32 mod,
- u32 uframe,
- u8 usecs,
- u32 period
-)
-{
- uframe %= period;
- do {
- /* can't commit more than uframe_periodic_max usec */
- if (periodic_usecs (fusbh200, uframe >> 3, uframe & 0x7)
- > (fusbh200->uframe_periodic_max - usecs))
- return 0;
-
- /* we know urb->interval is 2^N uframes */
- uframe += period;
- } while (uframe < mod);
- return 1;
-}
-
-/*
- * This scheduler plans almost as far into the future as it has actual
- * periodic schedule slots. (Affected by TUNE_FLS, which defaults to
- * "as small as possible" to be cache-friendlier.) That limits the size
- * transfers you can stream reliably; avoid more than 64 msec per urb.
- * Also avoid queue depths of less than fusbh200's worst irq latency (affected
- * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter,
- * and other factors); or more than about 230 msec total (for portability,
- * given FUSBH200_TUNE_FLS and the slop). Or, write a smarter scheduler!
- */
-
-#define SCHEDULE_SLOP 80 /* microframes */
-
-static int
-iso_stream_schedule (
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- struct fusbh200_iso_stream *stream
-)
-{
- u32 now, next, start, period, span;
- int status;
- unsigned mod = fusbh200->periodic_size << 3;
- struct fusbh200_iso_sched *sched = urb->hcpriv;
-
- period = urb->interval;
- span = sched->span;
-
- if (span > mod - SCHEDULE_SLOP) {
- fusbh200_dbg (fusbh200, "iso request %p too long\n", urb);
- status = -EFBIG;
- goto fail;
- }
-
- now = fusbh200_read_frame_index(fusbh200) & (mod - 1);
-
- /* Typical case: reuse current schedule, stream is still active.
- * Hopefully there are no gaps from the host falling behind
- * (irq delays etc), but if there are we'll take the next
- * slot in the schedule, implicitly assuming URB_ISO_ASAP.
- */
- if (likely (!list_empty (&stream->td_list))) {
- u32 excess;
-
- /* For high speed devices, allow scheduling within the
- * isochronous scheduling threshold. For full speed devices
- * and Intel PCI-based controllers, don't (work around for
- * Intel ICH9 bug).
- */
- if (!stream->highspeed && fusbh200->fs_i_thresh)
- next = now + fusbh200->i_thresh;
- else
- next = now;
-
- /* Fell behind (by up to twice the slop amount)?
- * We decide based on the time of the last currently-scheduled
- * slot, not the time of the next available slot.
- */
- excess = (stream->next_uframe - period - next) & (mod - 1);
- if (excess >= mod - 2 * SCHEDULE_SLOP)
- start = next + excess - mod + period *
- DIV_ROUND_UP(mod - excess, period);
- else
- start = next + excess + period;
- if (start - now >= mod) {
- fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n",
- urb, start - now - period, period,
- mod);
- status = -EFBIG;
- goto fail;
- }
- }
-
- /* need to schedule; when's the next (u)frame we could start?
- * this is bigger than fusbh200->i_thresh allows; scheduling itself
- * isn't free, the slop should handle reasonably slow cpus. it
- * can also help high bandwidth if the dma and irq loads don't
- * jump until after the queue is primed.
- */
- else {
- int done = 0;
- start = SCHEDULE_SLOP + (now & ~0x07);
-
- /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
-
- /* find a uframe slot with enough bandwidth.
- * Early uframes are more precious because full-speed
- * iso IN transfers can't use late uframes,
- * and therefore they should be allocated last.
- */
- next = start;
- start += period;
- do {
- start--;
- /* check schedule: enough space? */
- if (itd_slot_ok(fusbh200, mod, start,
- stream->usecs, period))
- done = 1;
- } while (start > next && !done);
-
- /* no room in the schedule */
- if (!done) {
- fusbh200_dbg(fusbh200, "iso resched full %p (now %d max %d)\n",
- urb, now, now + mod);
- status = -ENOSPC;
- goto fail;
- }
- }
-
- /* Tried to schedule too far into the future? */
- if (unlikely(start - now + span - period
- >= mod - 2 * SCHEDULE_SLOP)) {
- fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n",
- urb, start - now, span - period,
- mod - 2 * SCHEDULE_SLOP);
- status = -EFBIG;
- goto fail;
- }
-
- stream->next_uframe = start & (mod - 1);
-
- /* report high speed start in uframes; full speed, in frames */
- urb->start_frame = stream->next_uframe;
- if (!stream->highspeed)
- urb->start_frame >>= 3;
-
- /* Make sure scan_isoc() sees these */
- if (fusbh200->isoc_count == 0)
- fusbh200->next_frame = now >> 3;
- return 0;
-
- fail:
- iso_sched_free(stream, sched);
- urb->hcpriv = NULL;
- return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline void
-itd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_iso_stream *stream,
- struct fusbh200_itd *itd)
-{
- int i;
-
- /* it's been recently zeroed */
- itd->hw_next = FUSBH200_LIST_END(fusbh200);
- itd->hw_bufp [0] = stream->buf0;
- itd->hw_bufp [1] = stream->buf1;
- itd->hw_bufp [2] = stream->buf2;
-
- for (i = 0; i < 8; i++)
- itd->index[i] = -1;
-
- /* All other fields are filled when scheduling */
-}
-
-static inline void
-itd_patch(
- struct fusbh200_hcd *fusbh200,
- struct fusbh200_itd *itd,
- struct fusbh200_iso_sched *iso_sched,
- unsigned index,
- u16 uframe
-)
-{
- struct fusbh200_iso_packet *uf = &iso_sched->packet [index];
- unsigned pg = itd->pg;
-
- // BUG_ON (pg == 6 && uf->cross);
-
- uframe &= 0x07;
- itd->index [uframe] = index;
-
- itd->hw_transaction[uframe] = uf->transaction;
- itd->hw_transaction[uframe] |= cpu_to_hc32(fusbh200, pg << 12);
- itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, uf->bufp & ~(u32)0);
- itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(uf->bufp >> 32));
-
- /* iso_frame_desc[].offset must be strictly increasing */
- if (unlikely (uf->cross)) {
- u64 bufp = uf->bufp + 4096;
-
- itd->pg = ++pg;
- itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, bufp & ~(u32)0);
- itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(bufp >> 32));
- }
-}
-
-static inline void
-itd_link (struct fusbh200_hcd *fusbh200, unsigned frame, struct fusbh200_itd *itd)
-{
- union fusbh200_shadow *prev = &fusbh200->pshadow[frame];
- __hc32 *hw_p = &fusbh200->periodic[frame];
- union fusbh200_shadow here = *prev;
- __hc32 type = 0;
-
- /* skip any iso nodes which might belong to previous microframes */
- while (here.ptr) {
- type = Q_NEXT_TYPE(fusbh200, *hw_p);
- if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH))
- break;
- prev = periodic_next_shadow(fusbh200, prev, type);
- hw_p = shadow_next_periodic(fusbh200, &here, type);
- here = *prev;
- }
-
- itd->itd_next = here;
- itd->hw_next = *hw_p;
- prev->itd = itd;
- itd->frame = frame;
- wmb ();
- *hw_p = cpu_to_hc32(fusbh200, itd->itd_dma | Q_TYPE_ITD);
-}
-
-/* fit urb's itds into the selected schedule slot; activate as needed */
-static void itd_link_urb(
- struct fusbh200_hcd *fusbh200,
- struct urb *urb,
- unsigned mod,
- struct fusbh200_iso_stream *stream
-)
-{
- int packet;
- unsigned next_uframe, uframe, frame;
- struct fusbh200_iso_sched *iso_sched = urb->hcpriv;
- struct fusbh200_itd *itd;
-
- next_uframe = stream->next_uframe & (mod - 1);
-
- if (unlikely (list_empty(&stream->td_list))) {
- fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated
- += stream->bandwidth;
- fusbh200_dbg(fusbh200,
- "schedule devp %s ep%d%s-iso period %d start %d.%d\n",
- urb->dev->devpath, stream->bEndpointAddress & 0x0f,
- (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
- urb->interval,
- next_uframe >> 3, next_uframe & 0x7);
- }
-
- /* fill iTDs uframe by uframe */
- for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
- if (itd == NULL) {
- /* ASSERT: we have all necessary itds */
- // BUG_ON (list_empty (&iso_sched->td_list));
-
- /* ASSERT: no itds for this endpoint in this uframe */
-
- itd = list_entry (iso_sched->td_list.next,
- struct fusbh200_itd, itd_list);
- list_move_tail (&itd->itd_list, &stream->td_list);
- itd->stream = stream;
- itd->urb = urb;
- itd_init (fusbh200, stream, itd);
- }
-
- uframe = next_uframe & 0x07;
- frame = next_uframe >> 3;
-
- itd_patch(fusbh200, itd, iso_sched, packet, uframe);
-
- next_uframe += stream->interval;
- next_uframe &= mod - 1;
- packet++;
-
- /* link completed itds into the schedule */
- if (((next_uframe >> 3) != frame)
- || packet == urb->number_of_packets) {
- itd_link(fusbh200, frame & (fusbh200->periodic_size - 1), itd);
- itd = NULL;
- }
- }
- stream->next_uframe = next_uframe;
-
- /* don't need that schedule data any more */
- iso_sched_free (stream, iso_sched);
- urb->hcpriv = NULL;
-
- ++fusbh200->isoc_count;
- enable_periodic(fusbh200);
-}
-
-#define ISO_ERRS (FUSBH200_ISOC_BUF_ERR | FUSBH200_ISOC_BABBLE | FUSBH200_ISOC_XACTERR)
-
-/* Process and recycle a completed ITD. Return true iff its urb completed,
- * and hence its completion callback probably added things to the hardware
- * schedule.
- *
- * Note that we carefully avoid recycling this descriptor until after any
- * completion callback runs, so that it won't be reused quickly. That is,
- * assuming (a) no more than two urbs per frame on this endpoint, and also
- * (b) only this endpoint's completions submit URBs. It seems some silicon
- * corrupts things if you reuse completed descriptors very quickly...
- */
-static bool itd_complete(struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd)
-{
- struct urb *urb = itd->urb;
- struct usb_iso_packet_descriptor *desc;
- u32 t;
- unsigned uframe;
- int urb_index = -1;
- struct fusbh200_iso_stream *stream = itd->stream;
- struct usb_device *dev;
- bool retval = false;
-
- /* for each uframe with a packet */
- for (uframe = 0; uframe < 8; uframe++) {
- if (likely (itd->index[uframe] == -1))
- continue;
- urb_index = itd->index[uframe];
- desc = &urb->iso_frame_desc [urb_index];
-
- t = hc32_to_cpup(fusbh200, &itd->hw_transaction [uframe]);
- itd->hw_transaction [uframe] = 0;
-
- /* report transfer status */
- if (unlikely (t & ISO_ERRS)) {
- urb->error_count++;
- if (t & FUSBH200_ISOC_BUF_ERR)
- desc->status = usb_pipein (urb->pipe)
- ? -ENOSR /* hc couldn't read */
- : -ECOMM; /* hc couldn't write */
- else if (t & FUSBH200_ISOC_BABBLE)
- desc->status = -EOVERFLOW;
- else /* (t & FUSBH200_ISOC_XACTERR) */
- desc->status = -EPROTO;
-
- /* HC need not update length with this error */
- if (!(t & FUSBH200_ISOC_BABBLE)) {
- desc->actual_length = fusbh200_itdlen(urb, desc, t);
- urb->actual_length += desc->actual_length;
- }
- } else if (likely ((t & FUSBH200_ISOC_ACTIVE) == 0)) {
- desc->status = 0;
- desc->actual_length = fusbh200_itdlen(urb, desc, t);
- urb->actual_length += desc->actual_length;
- } else {
- /* URB was too late */
- desc->status = -EXDEV;
- }
- }
-
- /* handle completion now? */
- if (likely ((urb_index + 1) != urb->number_of_packets))
- goto done;
-
- /* ASSERT: it's really the last itd for this urb
- list_for_each_entry (itd, &stream->td_list, itd_list)
- BUG_ON (itd->urb == urb);
- */
-
- /* give urb back to the driver; completion often (re)submits */
- dev = urb->dev;
- fusbh200_urb_done(fusbh200, urb, 0);
- retval = true;
- urb = NULL;
-
- --fusbh200->isoc_count;
- disable_periodic(fusbh200);
-
- if (unlikely(list_is_singular(&stream->td_list))) {
- fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated
- -= stream->bandwidth;
- fusbh200_dbg(fusbh200,
- "deschedule devp %s ep%d%s-iso\n",
- dev->devpath, stream->bEndpointAddress & 0x0f,
- (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
- }
-
-done:
- itd->urb = NULL;
-
- /* Add to the end of the free list for later reuse */
- list_move_tail(&itd->itd_list, &stream->free_list);
-
- /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */
- if (list_empty(&stream->td_list)) {
- list_splice_tail_init(&stream->free_list,
- &fusbh200->cached_itd_list);
- start_free_itds(fusbh200);
- }
-
- return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int itd_submit (struct fusbh200_hcd *fusbh200, struct urb *urb,
- gfp_t mem_flags)
-{
- int status = -EINVAL;
- unsigned long flags;
- struct fusbh200_iso_stream *stream;
-
- /* Get iso_stream head */
- stream = iso_stream_find (fusbh200, urb);
- if (unlikely (stream == NULL)) {
- fusbh200_dbg (fusbh200, "can't get iso stream\n");
- return -ENOMEM;
- }
- if (unlikely (urb->interval != stream->interval &&
- fusbh200_port_speed(fusbh200, 0) == USB_PORT_STAT_HIGH_SPEED)) {
- fusbh200_dbg (fusbh200, "can't change iso interval %d --> %d\n",
- stream->interval, urb->interval);
- goto done;
- }
-
-#ifdef FUSBH200_URB_TRACE
- fusbh200_dbg (fusbh200,
- "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
- __func__, urb->dev->devpath, urb,
- usb_pipeendpoint (urb->pipe),
- usb_pipein (urb->pipe) ? "in" : "out",
- urb->transfer_buffer_length,
- urb->number_of_packets, urb->interval,
- stream);
-#endif
-
- /* allocate ITDs w/o locking anything */
- status = itd_urb_transaction (stream, fusbh200, urb, mem_flags);
- if (unlikely (status < 0)) {
- fusbh200_dbg (fusbh200, "can't init itds\n");
- goto done;
- }
-
- /* schedule ... need to lock */
- spin_lock_irqsave (&fusbh200->lock, flags);
- if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
- status = -ESHUTDOWN;
- goto done_not_linked;
- }
- status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
- if (unlikely(status))
- goto done_not_linked;
- status = iso_stream_schedule(fusbh200, urb, stream);
- if (likely (status == 0))
- itd_link_urb (fusbh200, urb, fusbh200->periodic_size << 3, stream);
- else
- usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
- done_not_linked:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- done:
- return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void scan_isoc(struct fusbh200_hcd *fusbh200)
-{
- unsigned uf, now_frame, frame;
- unsigned fmask = fusbh200->periodic_size - 1;
- bool modified, live;
-
- /*
- * When running, scan from last scan point up to "now"
- * else clean up by scanning everything that's left.
- * Touches as few pages as possible: cache-friendly.
- */
- if (fusbh200->rh_state >= FUSBH200_RH_RUNNING) {
- uf = fusbh200_read_frame_index(fusbh200);
- now_frame = (uf >> 3) & fmask;
- live = true;
- } else {
- now_frame = (fusbh200->next_frame - 1) & fmask;
- live = false;
- }
- fusbh200->now_frame = now_frame;
-
- frame = fusbh200->next_frame;
- for (;;) {
- union fusbh200_shadow q, *q_p;
- __hc32 type, *hw_p;
-
-restart:
- /* scan each element in frame's queue for completions */
- q_p = &fusbh200->pshadow [frame];
- hw_p = &fusbh200->periodic [frame];
- q.ptr = q_p->ptr;
- type = Q_NEXT_TYPE(fusbh200, *hw_p);
- modified = false;
-
- while (q.ptr != NULL) {
- switch (hc32_to_cpu(fusbh200, type)) {
- case Q_TYPE_ITD:
- /* If this ITD is still active, leave it for
- * later processing ... check the next entry.
- * No need to check for activity unless the
- * frame is current.
- */
- if (frame == now_frame && live) {
- rmb();
- for (uf = 0; uf < 8; uf++) {
- if (q.itd->hw_transaction[uf] &
- ITD_ACTIVE(fusbh200))
- break;
- }
- if (uf < 8) {
- q_p = &q.itd->itd_next;
- hw_p = &q.itd->hw_next;
- type = Q_NEXT_TYPE(fusbh200,
- q.itd->hw_next);
- q = *q_p;
- break;
- }
- }
-
- /* Take finished ITDs out of the schedule
- * and process them: recycle, maybe report
- * URB completion. HC won't cache the
- * pointer for much longer, if at all.
- */
- *q_p = q.itd->itd_next;
- *hw_p = q.itd->hw_next;
- type = Q_NEXT_TYPE(fusbh200, q.itd->hw_next);
- wmb();
- modified = itd_complete (fusbh200, q.itd);
- q = *q_p;
- break;
- default:
- fusbh200_dbg(fusbh200, "corrupt type %d frame %d shadow %p\n",
- type, frame, q.ptr);
- // BUG ();
- /* FALL THROUGH */
- case Q_TYPE_QH:
- case Q_TYPE_FSTN:
- /* End of the iTDs and siTDs */
- q.ptr = NULL;
- break;
- }
-
- /* assume completion callbacks modify the queue */
- if (unlikely(modified && fusbh200->isoc_count > 0))
- goto restart;
- }
-
- /* Stop when we have reached the current frame */
- if (frame == now_frame)
- break;
- frame = (frame + 1) & fmask;
- }
- fusbh200->next_frame = now_frame;
-}
-/*-------------------------------------------------------------------------*/
-/*
- * Display / Set uframe_periodic_max
- */
-static ssize_t show_uframe_periodic_max(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct fusbh200_hcd *fusbh200;
- int n;
-
- fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev)));
- n = scnprintf(buf, PAGE_SIZE, "%d\n", fusbh200->uframe_periodic_max);
- return n;
-}
-
-
-static ssize_t store_uframe_periodic_max(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fusbh200_hcd *fusbh200;
- unsigned uframe_periodic_max;
- unsigned frame, uframe;
- unsigned short allocated_max;
- unsigned long flags;
- ssize_t ret;
-
- fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev)));
- if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
- return -EINVAL;
-
- if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
- fusbh200_info(fusbh200, "rejecting invalid request for "
- "uframe_periodic_max=%u\n", uframe_periodic_max);
- return -EINVAL;
- }
-
- ret = -EINVAL;
-
- /*
- * lock, so that our checking does not race with possible periodic
- * bandwidth allocation through submitting new urbs.
- */
- spin_lock_irqsave (&fusbh200->lock, flags);
-
- /*
- * for request to decrease max periodic bandwidth, we have to check
- * every microframe in the schedule to see whether the decrease is
- * possible.
- */
- if (uframe_periodic_max < fusbh200->uframe_periodic_max) {
- allocated_max = 0;
-
- for (frame = 0; frame < fusbh200->periodic_size; ++frame)
- for (uframe = 0; uframe < 7; ++uframe)
- allocated_max = max(allocated_max,
- periodic_usecs (fusbh200, frame, uframe));
-
- if (allocated_max > uframe_periodic_max) {
- fusbh200_info(fusbh200,
- "cannot decrease uframe_periodic_max because "
- "periodic bandwidth is already allocated "
- "(%u > %u)\n",
- allocated_max, uframe_periodic_max);
- goto out_unlock;
- }
- }
-
- /* increasing is always ok */
-
- fusbh200_info(fusbh200, "setting max periodic bandwidth to %u%% "
- "(== %u usec/uframe)\n",
- 100*uframe_periodic_max/125, uframe_periodic_max);
-
- if (uframe_periodic_max != 100)
- fusbh200_warn(fusbh200, "max periodic bandwidth set is non-standard\n");
-
- fusbh200->uframe_periodic_max = uframe_periodic_max;
- ret = count;
-
-out_unlock:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- return ret;
-}
-static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max);
-
-
-static inline int create_sysfs_files(struct fusbh200_hcd *fusbh200)
-{
- struct device *controller = fusbh200_to_hcd(fusbh200)->self.controller;
- int i = 0;
-
- if (i)
- goto out;
-
- i = device_create_file(controller, &dev_attr_uframe_periodic_max);
-out:
- return i;
-}
-
-static inline void remove_sysfs_files(struct fusbh200_hcd *fusbh200)
-{
- struct device *controller = fusbh200_to_hcd(fusbh200)->self.controller;
-
- device_remove_file(controller, &dev_attr_uframe_periodic_max);
-}
-/*-------------------------------------------------------------------------*/
-
-/* On some systems, leaving remote wakeup enabled prevents system shutdown.
- * The firmware seems to think that powering off is a wakeup event!
- * This routine turns off remote wakeup and everything else, on all ports.
- */
-static void fusbh200_turn_off_all_ports(struct fusbh200_hcd *fusbh200)
-{
- u32 __iomem *status_reg = &fusbh200->regs->port_status;
-
- fusbh200_writel(fusbh200, PORT_RWC_BITS, status_reg);
-}
-
-/*
- * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
- * Must be called with interrupts enabled and the lock not held.
- */
-static void fusbh200_silence_controller(struct fusbh200_hcd *fusbh200)
-{
- fusbh200_halt(fusbh200);
-
- spin_lock_irq(&fusbh200->lock);
- fusbh200->rh_state = FUSBH200_RH_HALTED;
- fusbh200_turn_off_all_ports(fusbh200);
- spin_unlock_irq(&fusbh200->lock);
-}
-
-/* fusbh200_shutdown kick in for silicon on any bus (not just pci, etc).
- * This forcibly disables dma and IRQs, helping kexec and other cases
- * where the next system software may expect clean state.
- */
-static void fusbh200_shutdown(struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
-
- spin_lock_irq(&fusbh200->lock);
- fusbh200->shutdown = true;
- fusbh200->rh_state = FUSBH200_RH_STOPPING;
- fusbh200->enabled_hrtimer_events = 0;
- spin_unlock_irq(&fusbh200->lock);
-
- fusbh200_silence_controller(fusbh200);
-
- hrtimer_cancel(&fusbh200->hrtimer);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * fusbh200_work is called from some interrupts, timers, and so on.
- * it calls driver completion functions, after dropping fusbh200->lock.
- */
-static void fusbh200_work (struct fusbh200_hcd *fusbh200)
-{
- /* another CPU may drop fusbh200->lock during a schedule scan while
- * it reports urb completions. this flag guards against bogus
- * attempts at re-entrant schedule scanning.
- */
- if (fusbh200->scanning) {
- fusbh200->need_rescan = true;
- return;
- }
- fusbh200->scanning = true;
-
- rescan:
- fusbh200->need_rescan = false;
- if (fusbh200->async_count)
- scan_async(fusbh200);
- if (fusbh200->intr_count > 0)
- scan_intr(fusbh200);
- if (fusbh200->isoc_count > 0)
- scan_isoc(fusbh200);
- if (fusbh200->need_rescan)
- goto rescan;
- fusbh200->scanning = false;
-
- /* the IO watchdog guards against hardware or driver bugs that
- * misplace IRQs, and should let us run completely without IRQs.
- * such lossage has been observed on both VT6202 and VT8235.
- */
- turn_on_io_watchdog(fusbh200);
-}
-
-/*
- * Called when the fusbh200_hcd module is removed.
- */
-static void fusbh200_stop (struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
-
- fusbh200_dbg (fusbh200, "stop\n");
-
- /* no more interrupts ... */
-
- spin_lock_irq(&fusbh200->lock);
- fusbh200->enabled_hrtimer_events = 0;
- spin_unlock_irq(&fusbh200->lock);
-
- fusbh200_quiesce(fusbh200);
- fusbh200_silence_controller(fusbh200);
- fusbh200_reset (fusbh200);
-
- hrtimer_cancel(&fusbh200->hrtimer);
- remove_sysfs_files(fusbh200);
- remove_debug_files (fusbh200);
-
- /* root hub is shut down separately (first, when possible) */
- spin_lock_irq (&fusbh200->lock);
- end_free_itds(fusbh200);
- spin_unlock_irq (&fusbh200->lock);
- fusbh200_mem_cleanup (fusbh200);
-
- fusbh200_dbg(fusbh200, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
- fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa,
- fusbh200->stats.lost_iaa);
- fusbh200_dbg (fusbh200, "complete %ld unlink %ld\n",
- fusbh200->stats.complete, fusbh200->stats.unlink);
-
- dbg_status (fusbh200, "fusbh200_stop completed",
- fusbh200_readl(fusbh200, &fusbh200->regs->status));
-}
-
-/* one-time init, only for memory state */
-static int hcd_fusbh200_init(struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
- u32 temp;
- int retval;
- u32 hcc_params;
- struct fusbh200_qh_hw *hw;
-
- spin_lock_init(&fusbh200->lock);
-
- /*
- * keep io watchdog by default, those good HCDs could turn off it later
- */
- fusbh200->need_io_watchdog = 1;
-
- hrtimer_init(&fusbh200->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- fusbh200->hrtimer.function = fusbh200_hrtimer_func;
- fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT;
-
- hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-
- /*
- * by default set standard 80% (== 100 usec/uframe) max periodic
- * bandwidth as required by USB 2.0
- */
- fusbh200->uframe_periodic_max = 100;
-
- /*
- * hw default: 1K periodic list heads, one per frame.
- * periodic_size can shrink by USBCMD update if hcc_params allows.
- */
- fusbh200->periodic_size = DEFAULT_I_TDPS;
- INIT_LIST_HEAD(&fusbh200->intr_qh_list);
- INIT_LIST_HEAD(&fusbh200->cached_itd_list);
-
- if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
- /* periodic schedule size can be smaller than default */
- switch (FUSBH200_TUNE_FLS) {
- case 0: fusbh200->periodic_size = 1024; break;
- case 1: fusbh200->periodic_size = 512; break;
- case 2: fusbh200->periodic_size = 256; break;
- default: BUG();
- }
- }
- if ((retval = fusbh200_mem_init(fusbh200, GFP_KERNEL)) < 0)
- return retval;
-
- /* controllers may cache some of the periodic schedule ... */
- fusbh200->i_thresh = 2;
-
- /*
- * dedicate a qh for the async ring head, since we couldn't unlink
- * a 'real' qh without stopping the async schedule [4.8]. use it
- * as the 'reclamation list head' too.
- * its dummy is used in hw_alt_next of many tds, to prevent the qh
- * from automatically advancing to the next td after short reads.
- */
- fusbh200->async->qh_next.qh = NULL;
- hw = fusbh200->async->hw;
- hw->hw_next = QH_NEXT(fusbh200, fusbh200->async->qh_dma);
- hw->hw_info1 = cpu_to_hc32(fusbh200, QH_HEAD);
- hw->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT);
- hw->hw_qtd_next = FUSBH200_LIST_END(fusbh200);
- fusbh200->async->qh_state = QH_STATE_LINKED;
- hw->hw_alt_next = QTD_NEXT(fusbh200, fusbh200->async->dummy->qtd_dma);
-
- /* clear interrupt enables, set irq latency */
- if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
- log2_irq_thresh = 0;
- temp = 1 << (16 + log2_irq_thresh);
- if (HCC_CANPARK(hcc_params)) {
- /* HW default park == 3, on hardware that supports it (like
- * NVidia and ALI silicon), maximizes throughput on the async
- * schedule by avoiding QH fetches between transfers.
- *
- * With fast usb storage devices and NForce2, "park" seems to
- * make problems: throughput reduction (!), data errors...
- */
- if (park) {
- park = min(park, (unsigned) 3);
- temp |= CMD_PARK;
- temp |= park << 8;
- }
- fusbh200_dbg(fusbh200, "park %d\n", park);
- }
- if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
- /* periodic schedule size can be smaller than default */
- temp &= ~(3 << 2);
- temp |= (FUSBH200_TUNE_FLS << 2);
- }
- fusbh200->command = temp;
-
- /* Accept arbitrarily long scatter-gather lists */
- if (!(hcd->driver->flags & HCD_LOCAL_MEM))
- hcd->self.sg_tablesize = ~0;
- return 0;
-}
-
-/* start HC running; it's halted, hcd_fusbh200_init() has been run (once) */
-static int fusbh200_run (struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- u32 temp;
- u32 hcc_params;
-
- hcd->uses_new_polling = 1;
-
- /* EHCI spec section 4.1 */
-
- fusbh200_writel(fusbh200, fusbh200->periodic_dma, &fusbh200->regs->frame_list);
- fusbh200_writel(fusbh200, (u32)fusbh200->async->qh_dma, &fusbh200->regs->async_next);
-
- /*
- * hcc_params controls whether fusbh200->regs->segment must (!!!)
- * be used; it constrains QH/ITD/SITD and QTD locations.
- * pci_pool consistent memory always uses segment zero.
- * streaming mappings for I/O buffers, like pci_map_single(),
- * can return segments above 4GB, if the device allows.
- *
- * NOTE: the dma mask is visible through dma_supported(), so
- * drivers can pass this info along ... like NETIF_F_HIGHDMA,
- * Scsi_Host.highmem_io, and so forth. It's readonly to all
- * host side drivers though.
- */
- hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-
- // Philips, Intel, and maybe others need CMD_RUN before the
- // root hub will detect new devices (why?); NEC doesn't
- fusbh200->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
- fusbh200->command |= CMD_RUN;
- fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
- dbg_cmd (fusbh200, "init", fusbh200->command);
-
- /*
- * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
- * are explicitly handed to companion controller(s), so no TT is
- * involved with the root hub. (Except where one is integrated,
- * and there's no companion controller unless maybe for USB OTG.)
- *
- * Turning on the CF flag will transfer ownership of all ports
- * from the companions to the EHCI controller. If any of the
- * companions are in the middle of a port reset at the time, it
- * could cause trouble. Write-locking ehci_cf_port_reset_rwsem
- * guarantees that no resets are in progress. After we set CF,
- * a short delay lets the hardware catch up; new resets shouldn't
- * be started before the port switching actions could complete.
- */
- down_write(&ehci_cf_port_reset_rwsem);
- fusbh200->rh_state = FUSBH200_RH_RUNNING;
- fusbh200_readl(fusbh200, &fusbh200->regs->command); /* unblock posted writes */
- msleep(5);
- up_write(&ehci_cf_port_reset_rwsem);
- fusbh200->last_periodic_enable = ktime_get_real();
-
- temp = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
- fusbh200_info (fusbh200,
- "USB %x.%x started, EHCI %x.%02x\n",
- ((fusbh200->sbrn & 0xf0)>>4), (fusbh200->sbrn & 0x0f),
- temp >> 8, temp & 0xff);
-
- fusbh200_writel(fusbh200, INTR_MASK,
- &fusbh200->regs->intr_enable); /* Turn On Interrupts */
-
- /* GRR this is run-once init(), being done every time the HC starts.
- * So long as they're part of class devices, we can't do it init()
- * since the class device isn't created that early.
- */
- create_debug_files(fusbh200);
- create_sysfs_files(fusbh200);
-
- return 0;
-}
-
-static int fusbh200_setup(struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
- int retval;
-
- fusbh200->regs = (void __iomem *)fusbh200->caps +
- HC_LENGTH(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
- dbg_hcs_params(fusbh200, "reset");
- dbg_hcc_params(fusbh200, "reset");
-
- /* cache this readonly data; minimize chip reads */
- fusbh200->hcs_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
-
- fusbh200->sbrn = HCD_USB2;
-
- /* data structure init */
- retval = hcd_fusbh200_init(hcd);
- if (retval)
- return retval;
-
- retval = fusbh200_halt(fusbh200);
- if (retval)
- return retval;
-
- fusbh200_reset(fusbh200);
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static irqreturn_t fusbh200_irq (struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- u32 status, masked_status, pcd_status = 0, cmd;
- int bh;
-
- spin_lock (&fusbh200->lock);
-
- status = fusbh200_readl(fusbh200, &fusbh200->regs->status);
-
- /* e.g. cardbus physical eject */
- if (status == ~(u32) 0) {
- fusbh200_dbg (fusbh200, "device removed\n");
- goto dead;
- }
-
- /*
- * We don't use STS_FLR, but some controllers don't like it to
- * remain on, so mask it out along with the other status bits.
- */
- masked_status = status & (INTR_MASK | STS_FLR);
-
- /* Shared IRQ? */
- if (!masked_status || unlikely(fusbh200->rh_state == FUSBH200_RH_HALTED)) {
- spin_unlock(&fusbh200->lock);
- return IRQ_NONE;
- }
-
- /* clear (just) interrupts */
- fusbh200_writel(fusbh200, masked_status, &fusbh200->regs->status);
- cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command);
- bh = 0;
-
- /* normal [4.15.1.2] or error [4.15.1.1] completion */
- if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
- if (likely ((status & STS_ERR) == 0))
- COUNT (fusbh200->stats.normal);
- else
- COUNT (fusbh200->stats.error);
- bh = 1;
- }
-
- /* complete the unlinking of some qh [4.15.2.3] */
- if (status & STS_IAA) {
-
- /* Turn off the IAA watchdog */
- fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_IAA_WATCHDOG);
-
- /*
- * Mild optimization: Allow another IAAD to reset the
- * hrtimer, if one occurs before the next expiration.
- * In theory we could always cancel the hrtimer, but
- * tests show that about half the time it will be reset
- * for some other event anyway.
- */
- if (fusbh200->next_hrtimer_event == FUSBH200_HRTIMER_IAA_WATCHDOG)
- ++fusbh200->next_hrtimer_event;
-
- /* guard against (alleged) silicon errata */
- if (cmd & CMD_IAAD)
- fusbh200_dbg(fusbh200, "IAA with IAAD still set?\n");
- if (fusbh200->async_iaa) {
- COUNT(fusbh200->stats.iaa);
- end_unlink_async(fusbh200);
- } else
- fusbh200_dbg(fusbh200, "IAA with nothing unlinked?\n");
- }
-
- /* remote wakeup [4.3.1] */
- if (status & STS_PCD) {
- int pstatus;
- u32 __iomem *status_reg = &fusbh200->regs->port_status;
-
- /* kick root hub later */
- pcd_status = status;
-
- /* resume root hub? */
- if (fusbh200->rh_state == FUSBH200_RH_SUSPENDED)
- usb_hcd_resume_root_hub(hcd);
-
- pstatus = fusbh200_readl(fusbh200, status_reg);
-
- if (test_bit(0, &fusbh200->suspended_ports) &&
- ((pstatus & PORT_RESUME) ||
- !(pstatus & PORT_SUSPEND)) &&
- (pstatus & PORT_PE) &&
- fusbh200->reset_done[0] == 0) {
-
- /* start 20 msec resume signaling from this port,
- * and make hub_wq collect PORT_STAT_C_SUSPEND to
- * stop that signaling. Use 5 ms extra for safety,
- * like usb_port_resume() does.
- */
- fusbh200->reset_done[0] = jiffies + msecs_to_jiffies(25);
- set_bit(0, &fusbh200->resuming_ports);
- fusbh200_dbg (fusbh200, "port 1 remote wakeup\n");
- mod_timer(&hcd->rh_timer, fusbh200->reset_done[0]);
- }
- }
-
- /* PCI errors [4.15.2.4] */
- if (unlikely ((status & STS_FATAL) != 0)) {
- fusbh200_err(fusbh200, "fatal error\n");
- dbg_cmd(fusbh200, "fatal", cmd);
- dbg_status(fusbh200, "fatal", status);
-dead:
- usb_hc_died(hcd);
-
- /* Don't let the controller do anything more */
- fusbh200->shutdown = true;
- fusbh200->rh_state = FUSBH200_RH_STOPPING;
- fusbh200->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
- fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
- fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
- fusbh200_handle_controller_death(fusbh200);
-
- /* Handle completions when the controller stops */
- bh = 0;
- }
-
- if (bh)
- fusbh200_work (fusbh200);
- spin_unlock (&fusbh200->lock);
- if (pcd_status)
- usb_hcd_poll_rh_status(hcd);
- return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * non-error returns are a promise to giveback() the urb later
- * we drop ownership so next owner (or urb unlink) can get it
- *
- * urb + dev is in hcd.self.controller.urb_list
- * we're queueing TDs onto software and hardware lists
- *
- * hcd-specific init for hcpriv hasn't been done yet
- *
- * NOTE: control, bulk, and interrupt share the same code to append TDs
- * to a (possibly active) QH, and the same QH scanning code.
- */
-static int fusbh200_urb_enqueue (
- struct usb_hcd *hcd,
- struct urb *urb,
- gfp_t mem_flags
-) {
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- struct list_head qtd_list;
-
- INIT_LIST_HEAD (&qtd_list);
-
- switch (usb_pipetype (urb->pipe)) {
- case PIPE_CONTROL:
- /* qh_completions() code doesn't handle all the fault cases
- * in multi-TD control transfers. Even 1KB is rare anyway.
- */
- if (urb->transfer_buffer_length > (16 * 1024))
- return -EMSGSIZE;
- /* FALLTHROUGH */
- /* case PIPE_BULK: */
- default:
- if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags))
- return -ENOMEM;
- return submit_async(fusbh200, urb, &qtd_list, mem_flags);
-
- case PIPE_INTERRUPT:
- if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags))
- return -ENOMEM;
- return intr_submit(fusbh200, urb, &qtd_list, mem_flags);
-
- case PIPE_ISOCHRONOUS:
- return itd_submit (fusbh200, urb, mem_flags);
- }
-}
-
-/* remove from hardware lists
- * completions normally happen asynchronously
- */
-
-static int fusbh200_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- struct fusbh200_qh *qh;
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave (&fusbh200->lock, flags);
- rc = usb_hcd_check_unlink_urb(hcd, urb, status);
- if (rc)
- goto done;
-
- switch (usb_pipetype (urb->pipe)) {
- // case PIPE_CONTROL:
- // case PIPE_BULK:
- default:
- qh = (struct fusbh200_qh *) urb->hcpriv;
- if (!qh)
- break;
- switch (qh->qh_state) {
- case QH_STATE_LINKED:
- case QH_STATE_COMPLETING:
- start_unlink_async(fusbh200, qh);
- break;
- case QH_STATE_UNLINK:
- case QH_STATE_UNLINK_WAIT:
- /* already started */
- break;
- case QH_STATE_IDLE:
- /* QH might be waiting for a Clear-TT-Buffer */
- qh_completions(fusbh200, qh);
- break;
- }
- break;
-
- case PIPE_INTERRUPT:
- qh = (struct fusbh200_qh *) urb->hcpriv;
- if (!qh)
- break;
- switch (qh->qh_state) {
- case QH_STATE_LINKED:
- case QH_STATE_COMPLETING:
- start_unlink_intr(fusbh200, qh);
- break;
- case QH_STATE_IDLE:
- qh_completions (fusbh200, qh);
- break;
- default:
- fusbh200_dbg (fusbh200, "bogus qh %p state %d\n",
- qh, qh->qh_state);
- goto done;
- }
- break;
-
- case PIPE_ISOCHRONOUS:
- // itd...
-
- // wait till next completion, do it then.
- // completion irqs can wait up to 1024 msec,
- break;
- }
-done:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- return rc;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// bulk qh holds the data toggle
-
-static void
-fusbh200_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- unsigned long flags;
- struct fusbh200_qh *qh, *tmp;
-
- /* ASSERT: any requests/urbs are being unlinked */
- /* ASSERT: nobody can be submitting urbs for this any more */
-
-rescan:
- spin_lock_irqsave (&fusbh200->lock, flags);
- qh = ep->hcpriv;
- if (!qh)
- goto done;
-
- /* endpoints can be iso streams. for now, we don't
- * accelerate iso completions ... so spin a while.
- */
- if (qh->hw == NULL) {
- struct fusbh200_iso_stream *stream = ep->hcpriv;
-
- if (!list_empty(&stream->td_list))
- goto idle_timeout;
-
- /* BUG_ON(!list_empty(&stream->free_list)); */
- kfree(stream);
- goto done;
- }
-
- if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
- qh->qh_state = QH_STATE_IDLE;
- switch (qh->qh_state) {
- case QH_STATE_LINKED:
- case QH_STATE_COMPLETING:
- for (tmp = fusbh200->async->qh_next.qh;
- tmp && tmp != qh;
- tmp = tmp->qh_next.qh)
- continue;
- /* periodic qh self-unlinks on empty, and a COMPLETING qh
- * may already be unlinked.
- */
- if (tmp)
- start_unlink_async(fusbh200, qh);
- /* FALL THROUGH */
- case QH_STATE_UNLINK: /* wait for hw to finish? */
- case QH_STATE_UNLINK_WAIT:
-idle_timeout:
- spin_unlock_irqrestore (&fusbh200->lock, flags);
- schedule_timeout_uninterruptible(1);
- goto rescan;
- case QH_STATE_IDLE: /* fully unlinked */
- if (qh->clearing_tt)
- goto idle_timeout;
- if (list_empty (&qh->qtd_list)) {
- qh_destroy(fusbh200, qh);
- break;
- }
- /* else FALL THROUGH */
- default:
- /* caller was supposed to have unlinked any requests;
- * that's not our job. just leak this memory.
- */
- fusbh200_err (fusbh200, "qh %p (#%02x) state %d%s\n",
- qh, ep->desc.bEndpointAddress, qh->qh_state,
- list_empty (&qh->qtd_list) ? "" : "(has tds)");
- break;
- }
- done:
- ep->hcpriv = NULL;
- spin_unlock_irqrestore (&fusbh200->lock, flags);
-}
-
-static void
-fusbh200_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
- struct fusbh200_qh *qh;
- int eptype = usb_endpoint_type(&ep->desc);
- int epnum = usb_endpoint_num(&ep->desc);
- int is_out = usb_endpoint_dir_out(&ep->desc);
- unsigned long flags;
-
- if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
- return;
-
- spin_lock_irqsave(&fusbh200->lock, flags);
- qh = ep->hcpriv;
-
- /* For Bulk and Interrupt endpoints we maintain the toggle state
- * in the hardware; the toggle bits in udev aren't used at all.
- * When an endpoint is reset by usb_clear_halt() we must reset
- * the toggle bit in the QH.
- */
- if (qh) {
- usb_settoggle(qh->dev, epnum, is_out, 0);
- if (!list_empty(&qh->qtd_list)) {
- WARN_ONCE(1, "clear_halt for a busy endpoint\n");
- } else if (qh->qh_state == QH_STATE_LINKED ||
- qh->qh_state == QH_STATE_COMPLETING) {
-
- /* The toggle value in the QH can't be updated
- * while the QH is active. Unlink it now;
- * re-linking will call qh_refresh().
- */
- if (eptype == USB_ENDPOINT_XFER_BULK)
- start_unlink_async(fusbh200, qh);
- else
- start_unlink_intr(fusbh200, qh);
- }
- }
- spin_unlock_irqrestore(&fusbh200->lock, flags);
-}
-
-static int fusbh200_get_frame (struct usb_hcd *hcd)
-{
- struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
- return (fusbh200_read_frame_index(fusbh200) >> 3) % fusbh200->periodic_size;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
- * because its registers (and irq) are shared between host/gadget/otg
- * functions and in order to facilitate role switching we cannot
- * give the fusbh200 driver exclusive access to those.
- */
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_LICENSE ("GPL");
-
-static const struct hc_driver fusbh200_fusbh200_hc_driver = {
- .description = hcd_name,
- .product_desc = "Faraday USB2.0 Host Controller",
- .hcd_priv_size = sizeof(struct fusbh200_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = fusbh200_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = hcd_fusbh200_init,
- .start = fusbh200_run,
- .stop = fusbh200_stop,
- .shutdown = fusbh200_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = fusbh200_urb_enqueue,
- .urb_dequeue = fusbh200_urb_dequeue,
- .endpoint_disable = fusbh200_endpoint_disable,
- .endpoint_reset = fusbh200_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = fusbh200_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = fusbh200_hub_status_data,
- .hub_control = fusbh200_hub_control,
- .bus_suspend = fusbh200_bus_suspend,
- .bus_resume = fusbh200_bus_resume,
-
- .relinquish_port = fusbh200_relinquish_port,
- .port_handed_over = fusbh200_port_handed_over,
-
- .clear_tt_buffer_complete = fusbh200_clear_tt_buffer_complete,
-};
-
-static void fusbh200_init(struct fusbh200_hcd *fusbh200)
-{
- u32 reg;
-
- reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmcsr);
- reg |= BMCSR_INT_POLARITY;
- reg &= ~BMCSR_VBUS_OFF;
- fusbh200_writel(fusbh200, reg, &fusbh200->regs->bmcsr);
-
- reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmier);
- fusbh200_writel(fusbh200, reg | BMIER_OVC_EN | BMIER_VBUS_ERR_EN,
- &fusbh200->regs->bmier);
-}
-
-/**
- * fusbh200_hcd_probe - initialize faraday FUSBH200 HCDs
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- */
-static int fusbh200_hcd_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd;
- struct resource *res;
- int irq;
- int retval = -ENODEV;
- struct fusbh200_hcd *fusbh200;
-
- if (usb_disabled())
- return -ENODEV;
-
- pdev->dev.power.power_state = PMSG_ON;
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(dev,
- "Found HC with no IRQ. Check %s setup!\n",
- dev_name(dev));
- return -ENODEV;
- }
-
- irq = res->start;
-
- hcd = usb_create_hcd(&fusbh200_fusbh200_hc_driver, dev,
- dev_name(dev));
- if (!hcd) {
- dev_err(dev, "failed to create hcd with err %d\n", retval);
- retval = -ENOMEM;
- goto fail_create_hcd;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(dev));
- retval = -ENODEV;
- goto fail_request_resource;
- }
-
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
- hcd->has_tt = 1;
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- fusbh200_fusbh200_hc_driver.description)) {
- dev_dbg(dev, "controller already in use\n");
- retval = -EBUSY;
- goto fail_request_resource;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!res) {
- dev_err(dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(dev));
- retval = -ENODEV;
- goto fail_request_resource;
- }
-
- hcd->regs = ioremap_nocache(res->start, resource_size(res));
- if (hcd->regs == NULL) {
- dev_dbg(dev, "error mapping memory\n");
- retval = -EFAULT;
- goto fail_ioremap;
- }
-
- fusbh200 = hcd_to_fusbh200(hcd);
-
- fusbh200->caps = hcd->regs;
-
- retval = fusbh200_setup(hcd);
- if (retval)
- goto fail_add_hcd;
-
- fusbh200_init(fusbh200);
-
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (retval) {
- dev_err(dev, "failed to add hcd with err %d\n", retval);
- goto fail_add_hcd;
- }
- device_wakeup_enable(hcd->self.controller);
-
- return retval;
-
-fail_add_hcd:
- iounmap(hcd->regs);
-fail_ioremap:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
- usb_put_hcd(hcd);
-fail_create_hcd:
- dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
- return retval;
-}
-
-/**
- * fusbh200_hcd_remove - shutdown processing for EHCI HCDs
- * @dev: USB Host Controller being removed
- *
- * Reverses the effect of fotg2xx_usb_hcd_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- */
-static int fusbh200_hcd_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
-
- if (!hcd)
- return 0;
-
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
-
- return 0;
-}
-
-static struct platform_driver fusbh200_hcd_fusbh200_driver = {
- .driver = {
- .name = "fusbh200",
- },
- .probe = fusbh200_hcd_probe,
- .remove = fusbh200_hcd_remove,
-};
-
-static int __init fusbh200_hcd_init(void)
-{
- int retval = 0;
-
- if (usb_disabled())
- return -ENODEV;
-
- printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
- set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
- if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
- test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
- printk(KERN_WARNING "Warning! fusbh200_hcd should always be loaded"
- " before uhci_hcd and ohci_hcd, not after\n");
-
- pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n",
- hcd_name,
- sizeof(struct fusbh200_qh), sizeof(struct fusbh200_qtd),
- sizeof(struct fusbh200_itd));
-
- fusbh200_debug_root = debugfs_create_dir("fusbh200", usb_debug_root);
- if (!fusbh200_debug_root) {
- retval = -ENOENT;
- goto err_debug;
- }
-
- retval = platform_driver_register(&fusbh200_hcd_fusbh200_driver);
- if (retval < 0)
- goto clean;
- return retval;
-
- platform_driver_unregister(&fusbh200_hcd_fusbh200_driver);
-clean:
- debugfs_remove(fusbh200_debug_root);
- fusbh200_debug_root = NULL;
-err_debug:
- clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
- return retval;
-}
-module_init(fusbh200_hcd_init);
-
-static void __exit fusbh200_hcd_cleanup(void)
-{
- platform_driver_unregister(&fusbh200_hcd_fusbh200_driver);
- debugfs_remove(fusbh200_debug_root);
- clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
-}
-module_exit(fusbh200_hcd_cleanup);
diff --git a/drivers/usb/host/fusbh200.h b/drivers/usb/host/fusbh200.h
deleted file mode 100644
index d6e5b3d4aa68..000000000000
--- a/drivers/usb/host/fusbh200.h
+++ /dev/null
@@ -1,675 +0,0 @@
-#ifndef __LINUX_FUSBH200_H
-#define __LINUX_FUSBH200_H
-
-#include <linux/usb/ehci-dbgp.h>
-
-/* definitions used for the EHCI driver */
-
-/*
- * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
- * __leXX (normally) or __beXX (given FUSBH200_BIG_ENDIAN_DESC), depending on
- * the host controller implementation.
- *
- * To facilitate the strongest possible byte-order checking from "sparse"
- * and so on, we use __leXX unless that's not practical.
- */
-#define __hc32 __le32
-#define __hc16 __le16
-
-/* statistics can be kept for tuning/monitoring */
-struct fusbh200_stats {
- /* irq usage */
- unsigned long normal;
- unsigned long error;
- unsigned long iaa;
- unsigned long lost_iaa;
-
- /* termination of urbs from core */
- unsigned long complete;
- unsigned long unlink;
-};
-
-/* fusbh200_hcd->lock guards shared data against other CPUs:
- * fusbh200_hcd: async, unlink, periodic (and shadow), ...
- * usb_host_endpoint: hcpriv
- * fusbh200_qh: qh_next, qtd_list
- * fusbh200_qtd: qtd_list
- *
- * Also, hold this lock when talking to HC registers or
- * when updating hw_* fields in shared qh/qtd/... structures.
- */
-
-#define FUSBH200_MAX_ROOT_PORTS 1 /* see HCS_N_PORTS */
-
-/*
- * fusbh200_rh_state values of FUSBH200_RH_RUNNING or above mean that the
- * controller may be doing DMA. Lower values mean there's no DMA.
- */
-enum fusbh200_rh_state {
- FUSBH200_RH_HALTED,
- FUSBH200_RH_SUSPENDED,
- FUSBH200_RH_RUNNING,
- FUSBH200_RH_STOPPING
-};
-
-/*
- * Timer events, ordered by increasing delay length.
- * Always update event_delays_ns[] and event_handlers[] (defined in
- * ehci-timer.c) in parallel with this list.
- */
-enum fusbh200_hrtimer_event {
- FUSBH200_HRTIMER_POLL_ASS, /* Poll for async schedule off */
- FUSBH200_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */
- FUSBH200_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */
- FUSBH200_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */
- FUSBH200_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */
- FUSBH200_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */
- FUSBH200_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */
- FUSBH200_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */
- FUSBH200_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */
- FUSBH200_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */
- FUSBH200_HRTIMER_NUM_EVENTS /* Must come last */
-};
-#define FUSBH200_HRTIMER_NO_EVENT 99
-
-struct fusbh200_hcd { /* one per controller */
- /* timing support */
- enum fusbh200_hrtimer_event next_hrtimer_event;
- unsigned enabled_hrtimer_events;
- ktime_t hr_timeouts[FUSBH200_HRTIMER_NUM_EVENTS];
- struct hrtimer hrtimer;
-
- int PSS_poll_count;
- int ASS_poll_count;
- int died_poll_count;
-
- /* glue to PCI and HCD framework */
- struct fusbh200_caps __iomem *caps;
- struct fusbh200_regs __iomem *regs;
- struct ehci_dbg_port __iomem *debug;
-
- __u32 hcs_params; /* cached register copy */
- spinlock_t lock;
- enum fusbh200_rh_state rh_state;
-
- /* general schedule support */
- bool scanning:1;
- bool need_rescan:1;
- bool intr_unlinking:1;
- bool async_unlinking:1;
- bool shutdown:1;
- struct fusbh200_qh *qh_scan_next;
-
- /* async schedule support */
- struct fusbh200_qh *async;
- struct fusbh200_qh *dummy; /* For AMD quirk use */
- struct fusbh200_qh *async_unlink;
- struct fusbh200_qh *async_unlink_last;
- struct fusbh200_qh *async_iaa;
- unsigned async_unlink_cycle;
- unsigned async_count; /* async activity count */
-
- /* periodic schedule support */
-#define DEFAULT_I_TDPS 1024 /* some HCs can do less */
- unsigned periodic_size;
- __hc32 *periodic; /* hw periodic table */
- dma_addr_t periodic_dma;
- struct list_head intr_qh_list;
- unsigned i_thresh; /* uframes HC might cache */
-
- union fusbh200_shadow *pshadow; /* mirror hw periodic table */
- struct fusbh200_qh *intr_unlink;
- struct fusbh200_qh *intr_unlink_last;
- unsigned intr_unlink_cycle;
- unsigned now_frame; /* frame from HC hardware */
- unsigned next_frame; /* scan periodic, start here */
- unsigned intr_count; /* intr activity count */
- unsigned isoc_count; /* isoc activity count */
- unsigned periodic_count; /* periodic activity count */
- unsigned uframe_periodic_max; /* max periodic time per uframe */
-
-
- /* list of itds completed while now_frame was still active */
- struct list_head cached_itd_list;
- struct fusbh200_itd *last_itd_to_free;
-
- /* per root hub port */
- unsigned long reset_done [FUSBH200_MAX_ROOT_PORTS];
-
- /* bit vectors (one bit per port) */
- unsigned long bus_suspended; /* which ports were
- already suspended at the start of a bus suspend */
- unsigned long companion_ports; /* which ports are
- dedicated to the companion controller */
- unsigned long owned_ports; /* which ports are
- owned by the companion during a bus suspend */
- unsigned long port_c_suspend; /* which ports have
- the change-suspend feature turned on */
- unsigned long suspended_ports; /* which ports are
- suspended */
- unsigned long resuming_ports; /* which ports have
- started to resume */
-
- /* per-HC memory pools (could be per-bus, but ...) */
- struct dma_pool *qh_pool; /* qh per active urb */
- struct dma_pool *qtd_pool; /* one or more per qh */
- struct dma_pool *itd_pool; /* itd per iso urb */
-
- unsigned random_frame;
- unsigned long next_statechange;
- ktime_t last_periodic_enable;
- u32 command;
-
- /* SILICON QUIRKS */
- unsigned need_io_watchdog:1;
- unsigned fs_i_thresh:1; /* Intel iso scheduling */
-
- u8 sbrn; /* packed release number */
-
- /* irq statistics */
- struct fusbh200_stats stats;
-# define COUNT(x) do { (x)++; } while (0)
-
- /* debug files */
- struct dentry *debug_dir;
-};
-
-/* convert between an HCD pointer and the corresponding FUSBH200_HCD */
-static inline struct fusbh200_hcd *hcd_to_fusbh200 (struct usb_hcd *hcd)
-{
- return (struct fusbh200_hcd *) (hcd->hcd_priv);
-}
-static inline struct usb_hcd *fusbh200_to_hcd (struct fusbh200_hcd *fusbh200)
-{
- return container_of ((void *) fusbh200, struct usb_hcd, hcd_priv);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
-
-/* Section 2.2 Host Controller Capability Registers */
-struct fusbh200_caps {
- /* these fields are specified as 8 and 16 bit registers,
- * but some hosts can't perform 8 or 16 bit PCI accesses.
- * some hosts treat caplength and hciversion as parts of a 32-bit
- * register, others treat them as two separate registers, this
- * affects the memory map for big endian controllers.
- */
- u32 hc_capbase;
-#define HC_LENGTH(fusbh200, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \
- (fusbh200_big_endian_capbase(fusbh200) ? 24 : 0)))
-#define HC_VERSION(fusbh200, p) (0xffff&((p) >> /* bits 31:16 / offset 02h */ \
- (fusbh200_big_endian_capbase(fusbh200) ? 0 : 16)))
- u32 hcs_params; /* HCSPARAMS - offset 0x4 */
-#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */
-
- u32 hcc_params; /* HCCPARAMS - offset 0x8 */
-#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */
-#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/
- u8 portroute[8]; /* nibbles for routing - offset 0xC */
-};
-
-
-/* Section 2.3 Host Controller Operational Registers */
-struct fusbh200_regs {
-
- /* USBCMD: offset 0x00 */
- u32 command;
-
-/* EHCI 1.1 addendum */
-/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
-#define CMD_PARK (1<<11) /* enable "park" on async qh */
-#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */
-#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */
-#define CMD_ASE (1<<5) /* async schedule enable */
-#define CMD_PSE (1<<4) /* periodic schedule enable */
-/* 3:2 is periodic frame list size */
-#define CMD_RESET (1<<1) /* reset HC not bus */
-#define CMD_RUN (1<<0) /* start/stop HC */
-
- /* USBSTS: offset 0x04 */
- u32 status;
-#define STS_ASS (1<<15) /* Async Schedule Status */
-#define STS_PSS (1<<14) /* Periodic Schedule Status */
-#define STS_RECL (1<<13) /* Reclamation */
-#define STS_HALT (1<<12) /* Not running (any reason) */
-/* some bits reserved */
- /* these STS_* flags are also intr_enable bits (USBINTR) */
-#define STS_IAA (1<<5) /* Interrupted on async advance */
-#define STS_FATAL (1<<4) /* such as some PCI access errors */
-#define STS_FLR (1<<3) /* frame list rolled over */
-#define STS_PCD (1<<2) /* port change detect */
-#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
-#define STS_INT (1<<0) /* "normal" completion (short, ...) */
-
- /* USBINTR: offset 0x08 */
- u32 intr_enable;
-
- /* FRINDEX: offset 0x0C */
- u32 frame_index; /* current microframe number */
- /* CTRLDSSEGMENT: offset 0x10 */
- u32 segment; /* address bits 63:32 if needed */
- /* PERIODICLISTBASE: offset 0x14 */
- u32 frame_list; /* points to periodic list */
- /* ASYNCLISTADDR: offset 0x18 */
- u32 async_next; /* address of next async queue head */
-
- u32 reserved1;
- /* PORTSC: offset 0x20 */
- u32 port_status;
-/* 31:23 reserved */
-#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */
-#define PORT_RESET (1<<8) /* reset port */
-#define PORT_SUSPEND (1<<7) /* suspend port */
-#define PORT_RESUME (1<<6) /* resume it */
-#define PORT_PEC (1<<3) /* port enable change */
-#define PORT_PE (1<<2) /* port enable */
-#define PORT_CSC (1<<1) /* connect status change */
-#define PORT_CONNECT (1<<0) /* device connected */
-#define PORT_RWC_BITS (PORT_CSC | PORT_PEC)
-
- u32 reserved2[3];
-
- /* BMCSR: offset 0x30 */
- u32 bmcsr; /* Bus Moniter Control/Status Register */
-#define BMCSR_HOST_SPD_TYP (3<<9)
-#define BMCSR_VBUS_OFF (1<<4)
-#define BMCSR_INT_POLARITY (1<<3)
-
- /* BMISR: offset 0x34 */
- u32 bmisr; /* Bus Moniter Interrupt Status Register*/
-#define BMISR_OVC (1<<1)
-
- /* BMIER: offset 0x38 */
- u32 bmier; /* Bus Moniter Interrupt Enable Register */
-#define BMIER_OVC_EN (1<<1)
-#define BMIER_VBUS_ERR_EN (1<<0)
-};
-
-/*-------------------------------------------------------------------------*/
-
-#define QTD_NEXT(fusbh200, dma) cpu_to_hc32(fusbh200, (u32)dma)
-
-/*
- * EHCI Specification 0.95 Section 3.5
- * QTD: describe data transfer components (buffer, direction, ...)
- * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
- *
- * These are associated only with "QH" (Queue Head) structures,
- * used with control, bulk, and interrupt transfers.
- */
-struct fusbh200_qtd {
- /* first part defined by EHCI spec */
- __hc32 hw_next; /* see EHCI 3.5.1 */
- __hc32 hw_alt_next; /* see EHCI 3.5.2 */
- __hc32 hw_token; /* see EHCI 3.5.3 */
-#define QTD_TOGGLE (1 << 31) /* data toggle */
-#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
-#define QTD_IOC (1 << 15) /* interrupt on complete */
-#define QTD_CERR(tok) (((tok)>>10) & 0x3)
-#define QTD_PID(tok) (((tok)>>8) & 0x3)
-#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */
-#define QTD_STS_HALT (1 << 6) /* halted on error */
-#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */
-#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */
-#define QTD_STS_XACT (1 << 3) /* device gave illegal response */
-#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */
-#define QTD_STS_STS (1 << 1) /* split transaction state */
-#define QTD_STS_PING (1 << 0) /* issue PING? */
-
-#define ACTIVE_BIT(fusbh200) cpu_to_hc32(fusbh200, QTD_STS_ACTIVE)
-#define HALT_BIT(fusbh200) cpu_to_hc32(fusbh200, QTD_STS_HALT)
-#define STATUS_BIT(fusbh200) cpu_to_hc32(fusbh200, QTD_STS_STS)
-
- __hc32 hw_buf [5]; /* see EHCI 3.5.4 */
- __hc32 hw_buf_hi [5]; /* Appendix B */
-
- /* the rest is HCD-private */
- dma_addr_t qtd_dma; /* qtd address */
- struct list_head qtd_list; /* sw qtd list */
- struct urb *urb; /* qtd's urb */
- size_t length; /* length of buffer */
-} __attribute__ ((aligned (32)));
-
-/* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK(fusbh200) cpu_to_hc32 (fusbh200, ~0x1f)
-
-#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
-
-/*-------------------------------------------------------------------------*/
-
-/* type tag from {qh,itd,fstn}->hw_next */
-#define Q_NEXT_TYPE(fusbh200,dma) ((dma) & cpu_to_hc32(fusbh200, 3 << 1))
-
-/*
- * Now the following defines are not converted using the
- * cpu_to_le32() macro anymore, since we have to support
- * "dynamic" switching between be and le support, so that the driver
- * can be used on one system with SoC EHCI controller using big-endian
- * descriptors as well as a normal little-endian PCI EHCI controller.
- */
-/* values for that type tag */
-#define Q_TYPE_ITD (0 << 1)
-#define Q_TYPE_QH (1 << 1)
-#define Q_TYPE_SITD (2 << 1)
-#define Q_TYPE_FSTN (3 << 1)
-
-/* next async queue entry, or pointer to interrupt/periodic QH */
-#define QH_NEXT(fusbh200,dma) (cpu_to_hc32(fusbh200, (((u32)dma)&~0x01f)|Q_TYPE_QH))
-
-/* for periodic/async schedules and qtd lists, mark end of list */
-#define FUSBH200_LIST_END(fusbh200) cpu_to_hc32(fusbh200, 1) /* "null pointer" to hw */
-
-/*
- * Entries in periodic shadow table are pointers to one of four kinds
- * of data structure. That's dictated by the hardware; a type tag is
- * encoded in the low bits of the hardware's periodic schedule. Use
- * Q_NEXT_TYPE to get the tag.
- *
- * For entries in the async schedule, the type tag always says "qh".
- */
-union fusbh200_shadow {
- struct fusbh200_qh *qh; /* Q_TYPE_QH */
- struct fusbh200_itd *itd; /* Q_TYPE_ITD */
- struct fusbh200_fstn *fstn; /* Q_TYPE_FSTN */
- __hc32 *hw_next; /* (all types) */
- void *ptr;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.6
- * QH: describes control/bulk/interrupt endpoints
- * See Fig 3-7 "Queue Head Structure Layout".
- *
- * These appear in both the async and (for interrupt) periodic schedules.
- */
-
-/* first part defined by EHCI spec */
-struct fusbh200_qh_hw {
- __hc32 hw_next; /* see EHCI 3.6.1 */
- __hc32 hw_info1; /* see EHCI 3.6.2 */
-#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */
-#define QH_HEAD (1 << 15) /* Head of async reclamation list */
-#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */
-#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */
-#define QH_LOW_SPEED (1 << 12)
-#define QH_FULL_SPEED (0 << 12)
-#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */
- __hc32 hw_info2; /* see EHCI 3.6.2 */
-#define QH_SMASK 0x000000ff
-#define QH_CMASK 0x0000ff00
-#define QH_HUBADDR 0x007f0000
-#define QH_HUBPORT 0x3f800000
-#define QH_MULT 0xc0000000
- __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */
-
- /* qtd overlay (hardware parts of a struct fusbh200_qtd) */
- __hc32 hw_qtd_next;
- __hc32 hw_alt_next;
- __hc32 hw_token;
- __hc32 hw_buf [5];
- __hc32 hw_buf_hi [5];
-} __attribute__ ((aligned(32)));
-
-struct fusbh200_qh {
- struct fusbh200_qh_hw *hw; /* Must come first */
- /* the rest is HCD-private */
- dma_addr_t qh_dma; /* address of qh */
- union fusbh200_shadow qh_next; /* ptr to qh; or periodic */
- struct list_head qtd_list; /* sw qtd list */
- struct list_head intr_node; /* list of intr QHs */
- struct fusbh200_qtd *dummy;
- struct fusbh200_qh *unlink_next; /* next on unlink list */
-
- unsigned unlink_cycle;
-
- u8 needs_rescan; /* Dequeue during giveback */
- u8 qh_state;
-#define QH_STATE_LINKED 1 /* HC sees this */
-#define QH_STATE_UNLINK 2 /* HC may still see this */
-#define QH_STATE_IDLE 3 /* HC doesn't see this */
-#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink q */
-#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */
-
- u8 xacterrs; /* XactErr retry counter */
-#define QH_XACTERR_MAX 32 /* XactErr retry limit */
-
- /* periodic schedule info */
- u8 usecs; /* intr bandwidth */
- u8 gap_uf; /* uframes split/csplit gap */
- u8 c_usecs; /* ... split completion bw */
- u16 tt_usecs; /* tt downstream bandwidth */
- unsigned short period; /* polling interval */
- unsigned short start; /* where polling starts */
-#define NO_FRAME ((unsigned short)~0) /* pick new start */
-
- struct usb_device *dev; /* access to TT */
- unsigned is_out:1; /* bulk or intr OUT */
- unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* description of one iso transaction (up to 3 KB data if highspeed) */
-struct fusbh200_iso_packet {
- /* These will be copied to iTD when scheduling */
- u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */
- __hc32 transaction; /* itd->hw_transaction[i] |= */
- u8 cross; /* buf crosses pages */
- /* for full speed OUT splits */
- u32 buf1;
-};
-
-/* temporary schedule data for packets from iso urbs (both speeds)
- * each packet is one logical usb transaction to the device (not TT),
- * beginning at stream->next_uframe
- */
-struct fusbh200_iso_sched {
- struct list_head td_list;
- unsigned span;
- struct fusbh200_iso_packet packet [0];
-};
-
-/*
- * fusbh200_iso_stream - groups all (s)itds for this endpoint.
- * acts like a qh would, if EHCI had them for ISO.
- */
-struct fusbh200_iso_stream {
- /* first field matches fusbh200_hq, but is NULL */
- struct fusbh200_qh_hw *hw;
-
- u8 bEndpointAddress;
- u8 highspeed;
- struct list_head td_list; /* queued itds */
- struct list_head free_list; /* list of unused itds */
- struct usb_device *udev;
- struct usb_host_endpoint *ep;
-
- /* output of (re)scheduling */
- int next_uframe;
- __hc32 splits;
-
- /* the rest is derived from the endpoint descriptor,
- * trusting urb->interval == f(epdesc->bInterval) and
- * including the extra info for hw_bufp[0..2]
- */
- u8 usecs, c_usecs;
- u16 interval;
- u16 tt_usecs;
- u16 maxp;
- u16 raw_mask;
- unsigned bandwidth;
-
- /* This is used to initialize iTD's hw_bufp fields */
- __hc32 buf0;
- __hc32 buf1;
- __hc32 buf2;
-
- /* this is used to initialize sITD's tt info */
- __hc32 address;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.3
- * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
- *
- * Schedule records for high speed iso xfers
- */
-struct fusbh200_itd {
- /* first part defined by EHCI spec */
- __hc32 hw_next; /* see EHCI 3.3.1 */
- __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */
-#define FUSBH200_ISOC_ACTIVE (1<<31) /* activate transfer this slot */
-#define FUSBH200_ISOC_BUF_ERR (1<<30) /* Data buffer error */
-#define FUSBH200_ISOC_BABBLE (1<<29) /* babble detected */
-#define FUSBH200_ISOC_XACTERR (1<<28) /* XactErr - transaction error */
-#define FUSBH200_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff)
-#define FUSBH200_ITD_IOC (1 << 15) /* interrupt on complete */
-
-#define ITD_ACTIVE(fusbh200) cpu_to_hc32(fusbh200, FUSBH200_ISOC_ACTIVE)
-
- __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */
- __hc32 hw_bufp_hi [7]; /* Appendix B */
-
- /* the rest is HCD-private */
- dma_addr_t itd_dma; /* for this itd */
- union fusbh200_shadow itd_next; /* ptr to periodic q entry */
-
- struct urb *urb;
- struct fusbh200_iso_stream *stream; /* endpoint's queue */
- struct list_head itd_list; /* list of stream's itds */
-
- /* any/all hw_transactions here may be used by that urb */
- unsigned frame; /* where scheduled */
- unsigned pg;
- unsigned index[8]; /* in urb->iso_frame_desc */
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.96 Section 3.7
- * Periodic Frame Span Traversal Node (FSTN)
- *
- * Manages split interrupt transactions (using TT) that span frame boundaries
- * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN
- * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
- * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
- */
-struct fusbh200_fstn {
- __hc32 hw_next; /* any periodic q entry */
- __hc32 hw_prev; /* qh or FUSBH200_LIST_END */
-
- /* the rest is HCD-private */
- dma_addr_t fstn_dma;
- union fusbh200_shadow fstn_next; /* ptr to periodic q entry */
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/* Prepare the PORTSC wakeup flags during controller suspend/resume */
-
-#define fusbh200_prepare_ports_for_controller_suspend(fusbh200, do_wakeup) \
- fusbh200_adjust_port_wakeup_flags(fusbh200, true, do_wakeup);
-
-#define fusbh200_prepare_ports_for_controller_resume(fusbh200) \
- fusbh200_adjust_port_wakeup_flags(fusbh200, false, false);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Some EHCI controllers have a Transaction Translator built into the
- * root hub. This is a non-standard feature. Each controller will need
- * to add code to the following inline functions, and call them as
- * needed (mostly in root hub code).
- */
-
-static inline unsigned int
-fusbh200_get_speed(struct fusbh200_hcd *fusbh200, unsigned int portsc)
-{
- return (readl(&fusbh200->regs->bmcsr)
- & BMCSR_HOST_SPD_TYP) >> 9;
-}
-
-/* Returns the speed of a device attached to a port on the root hub. */
-static inline unsigned int
-fusbh200_port_speed(struct fusbh200_hcd *fusbh200, unsigned int portsc)
-{
- switch (fusbh200_get_speed(fusbh200, portsc)) {
- case 0:
- return 0;
- case 1:
- return USB_PORT_STAT_LOW_SPEED;
- case 2:
- default:
- return USB_PORT_STAT_HIGH_SPEED;
- }
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define fusbh200_has_fsl_portno_bug(e) (0)
-
-/*
- * While most USB host controllers implement their registers in
- * little-endian format, a minority (celleb companion chip) implement
- * them in big endian format.
- *
- * This attempts to support either format at compile time without a
- * runtime penalty, or both formats with the additional overhead
- * of checking a flag bit.
- *
- */
-
-#define fusbh200_big_endian_mmio(e) 0
-#define fusbh200_big_endian_capbase(e) 0
-
-static inline unsigned int fusbh200_readl(const struct fusbh200_hcd *fusbh200,
- __u32 __iomem * regs)
-{
- return readl(regs);
-}
-
-static inline void fusbh200_writel(const struct fusbh200_hcd *fusbh200,
- const unsigned int val, __u32 __iomem *regs)
-{
- writel(val, regs);
-}
-
-/* cpu to fusbh200 */
-static inline __hc32 cpu_to_hc32 (const struct fusbh200_hcd *fusbh200, const u32 x)
-{
- return cpu_to_le32(x);
-}
-
-/* fusbh200 to cpu */
-static inline u32 hc32_to_cpu (const struct fusbh200_hcd *fusbh200, const __hc32 x)
-{
- return le32_to_cpu(x);
-}
-
-static inline u32 hc32_to_cpup (const struct fusbh200_hcd *fusbh200, const __hc32 *x)
-{
- return le32_to_cpup(x);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline unsigned fusbh200_read_frame_index(struct fusbh200_hcd *fusbh200)
-{
- return fusbh200_readl(fusbh200, &fusbh200->regs->frame_index);
-}
-
-#define fusbh200_itdlen(urb, desc, t) ({ \
- usb_pipein((urb)->pipe) ? \
- (desc)->length - FUSBH200_ITD_LENGTH(t) : \
- FUSBH200_ITD_LENGTH(t); \
-})
-/*-------------------------------------------------------------------------*/
-
-#endif /* __LINUX_FUSBH200_H */
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c
index fc1fd403973a..bd98706d1ce9 100644
--- a/drivers/usb/host/max3421-hcd.c
+++ b/drivers/usb/host/max3421-hcd.c
@@ -1944,7 +1944,6 @@ static struct spi_driver max3421_driver = {
.remove = max3421_remove,
.driver = {
.name = "max3421-hcd",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index d9f0481d7258..cfa94275c52c 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -203,7 +203,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
goto fail_disable;
}
- ret = clk_enable(usb_pll_clk);
+ ret = clk_prepare_enable(usb_pll_clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to start USB PLL\n");
goto fail_disable;
@@ -223,7 +223,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
goto fail_rate;
}
- ret = clk_enable(usb_dev_clk);
+ ret = clk_prepare_enable(usb_dev_clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to start USB DEV Clock\n");
goto fail_rate;
@@ -239,7 +239,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
__raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
- ret = clk_enable(usb_otg_clk);
+ ret = clk_prepare_enable(usb_otg_clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to start USB DEV Clock\n");
goto fail_otg;
@@ -283,11 +283,11 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
fail_resource:
usb_put_hcd(hcd);
fail_hcd:
- clk_disable(usb_otg_clk);
+ clk_disable_unprepare(usb_otg_clk);
fail_otg:
- clk_disable(usb_dev_clk);
+ clk_disable_unprepare(usb_dev_clk);
fail_rate:
- clk_disable(usb_pll_clk);
+ clk_disable_unprepare(usb_pll_clk);
fail_disable:
isp1301_i2c_client = NULL;
return ret;
@@ -300,9 +300,9 @@ static int ohci_hcd_nxp_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
ohci_nxp_stop_hc();
usb_put_hcd(hcd);
- clk_disable(usb_pll_clk);
- clk_disable(usb_dev_clk);
- i2c_unregister_device(isp1301_i2c_client);
+ clk_disable_unprepare(usb_otg_clk);
+ clk_disable_unprepare(usb_dev_clk);
+ clk_disable_unprepare(usb_pll_clk);
isp1301_i2c_client = NULL;
return 0;
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 707437c88d03..56478ed2f932 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -161,6 +161,7 @@ static const struct of_device_id spear_ohci_id_table[] = {
{ .compatible = "st,spear600-ohci", },
{ },
};
+MODULE_DEVICE_TABLE(of, spear_ohci_id_table);
/* Driver definition to register with the platform bus */
static struct platform_driver spear_ohci_hcd_driver = {
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index fe3bd1cb8b6b..1f139d82cee0 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -2721,7 +2721,7 @@ static int oxu_run(struct usb_hcd *hcd)
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
- * NOTE: the dma mask is visible through dma_supported(), so
+ * NOTE: the dma mask is visible through dev->dma_mask, so
* drivers can pass this info along ... like NETIF_F_HIGHDMA,
* Scsi_Host.highmem_io, and so forth. It's readonly to all
* host side drivers though.
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index a67bd5090330..692ccc69345e 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2244,9 +2244,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
{
struct u132 *u132 = hcd_to_u132(hcd);
if (irqs_disabled()) {
- if (__GFP_WAIT & mem_flags) {
- printk(KERN_ERR "invalid context for function that migh"
- "t sleep\n");
+ if (gfpflags_allow_blocking(mem_flags)) {
+ printk(KERN_ERR "invalid context for function that might sleep\n");
return -EINVAL;
}
}
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 3a3e3eeba291..32a6f3d8deec 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -140,6 +140,7 @@ static const struct of_device_id platform_uhci_ids[] = {
{ .compatible = "platform-uhci", },
{}
};
+MODULE_DEVICE_TABLE(of, platform_uhci_ids);
static struct platform_driver uhci_platform_driver = {
.probe = uhci_hcd_platform_probe,
diff --git a/drivers/usb/host/whci/init.c b/drivers/usb/host/whci/init.c
index d3e13b640d4b..e36372393bb1 100644
--- a/drivers/usb/host/whci/init.c
+++ b/drivers/usb/host/whci/init.c
@@ -175,8 +175,7 @@ void whc_clean_up(struct whc *whc)
pzl_clean_up(whc);
asl_clean_up(whc);
- if (whc->qset_pool)
- dma_pool_destroy(whc->qset_pool);
+ dma_pool_destroy(whc->qset_pool);
len = resource_size(&whc->umc->resource);
if (whc->base)
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 2d16faefb429..74c42f722678 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -58,16 +58,17 @@ void xhci_dbg_regs(struct xhci_hcd *xhci)
static void xhci_print_cap_regs(struct xhci_hcd *xhci)
{
u32 temp;
+ u32 hci_version;
xhci_dbg(xhci, "xHCI capability registers at %p:\n", xhci->cap_regs);
temp = readl(&xhci->cap_regs->hc_capbase);
+ hci_version = HC_VERSION(temp);
xhci_dbg(xhci, "CAPLENGTH AND HCIVERSION 0x%x:\n",
(unsigned int) temp);
xhci_dbg(xhci, "CAPLENGTH: 0x%x\n",
(unsigned int) HC_LENGTH(temp));
- xhci_dbg(xhci, "HCIVERSION: 0x%x\n",
- (unsigned int) HC_VERSION(temp));
+ xhci_dbg(xhci, "HCIVERSION: 0x%x\n", hci_version);
temp = readl(&xhci->cap_regs->hcs_params1);
xhci_dbg(xhci, "HCSPARAMS 1: 0x%x\n",
@@ -108,6 +109,18 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci)
temp = readl(&xhci->cap_regs->run_regs_off);
xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK);
+
+ /* xhci 1.1 controllers have the HCCPARAMS2 register */
+ if (hci_version > 100) {
+ temp = readl(&xhci->cap_regs->hcc_params2);
+ xhci_dbg(xhci, "HCC PARAMS2 0x%x:\n", (unsigned int) temp);
+ xhci_dbg(xhci, " HC %s Force save context capability",
+ HCC2_FSC(temp) ? "supports" : "doesn't support");
+ xhci_dbg(xhci, " HC %s Large ESIT Payload Capability",
+ HCC2_LEC(temp) ? "supports" : "doesn't support");
+ xhci_dbg(xhci, " HC %s Extended TBC capability",
+ HCC2_ETC(temp) ? "supports" : "doesn't support");
+ }
}
static void xhci_print_command_reg(struct xhci_hcd *xhci)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 78241b5550df..0230965fb78c 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -31,13 +31,15 @@
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
PORT_RC | PORT_PLC | PORT_PE)
-/* USB 3.0 BOS descriptor and a capability descriptor, combined */
+/* USB 3 BOS descriptor and a capability descriptors, combined.
+ * Fields will be adjusted and added later in xhci_create_usb3_bos_desc()
+ */
static u8 usb_bos_descriptor [] = {
USB_DT_BOS_SIZE, /* __u8 bLength, 5 bytes */
USB_DT_BOS, /* __u8 bDescriptorType */
0x0F, 0x00, /* __le16 wTotalLength, 15 bytes */
0x1, /* __u8 bNumDeviceCaps */
- /* First device capability */
+ /* First device capability, SuperSpeed */
USB_DT_USB_SS_CAP_SIZE, /* __u8 bLength, 10 bytes */
USB_DT_DEVICE_CAPABILITY, /* Device Capability */
USB_SS_CAP_TYPE, /* bDevCapabilityType, SUPERSPEED_USB */
@@ -46,9 +48,108 @@ static u8 usb_bos_descriptor [] = {
0x03, /* bFunctionalitySupport,
USB 3.0 speed only */
0x00, /* bU1DevExitLat, set later. */
- 0x00, 0x00 /* __le16 bU2DevExitLat, set later. */
+ 0x00, 0x00, /* __le16 bU2DevExitLat, set later. */
+ /* Second device capability, SuperSpeedPlus */
+ 0x0c, /* bLength 12, will be adjusted later */
+ USB_DT_DEVICE_CAPABILITY, /* Device Capability */
+ USB_SSP_CAP_TYPE, /* bDevCapabilityType SUPERSPEED_PLUS */
+ 0x00, /* bReserved 0 */
+ 0x00, 0x00, 0x00, 0x00, /* bmAttributes, get from xhci psic */
+ 0x00, 0x00, /* wFunctionalitySupport */
+ 0x00, 0x00, /* wReserved 0 */
+ /* Sublink Speed Attributes are added in xhci_create_usb3_bos_desc() */
};
+static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
+ u16 wLength)
+{
+ int i, ssa_count;
+ u32 temp;
+ u16 desc_size, ssp_cap_size, ssa_size = 0;
+ bool usb3_1 = false;
+
+ desc_size = USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
+ ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size;
+
+ /* does xhci support USB 3.1 Enhanced SuperSpeed */
+ if (xhci->usb3_rhub.min_rev >= 0x01 && xhci->usb3_rhub.psi_uid_count) {
+ /* two SSA entries for each unique PSI ID, one RX and one TX */
+ ssa_count = xhci->usb3_rhub.psi_uid_count * 2;
+ ssa_size = ssa_count * sizeof(u32);
+ desc_size += ssp_cap_size;
+ usb3_1 = true;
+ }
+ memcpy(buf, &usb_bos_descriptor, min(desc_size, wLength));
+
+ if (usb3_1) {
+ /* modify bos descriptor bNumDeviceCaps and wTotalLength */
+ buf[4] += 1;
+ put_unaligned_le16(desc_size + ssa_size, &buf[2]);
+ }
+
+ if (wLength < USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE)
+ return wLength;
+
+ /* Indicate whether the host has LTM support. */
+ temp = readl(&xhci->cap_regs->hcc_params);
+ if (HCC_LTC(temp))
+ buf[8] |= USB_LTM_SUPPORT;
+
+ /* Set the U1 and U2 exit latencies. */
+ if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
+ temp = readl(&xhci->cap_regs->hcs_params3);
+ buf[12] = HCS_U1_LATENCY(temp);
+ put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
+ }
+
+ if (usb3_1) {
+ u32 ssp_cap_base, bm_attrib, psi;
+ int offset;
+
+ ssp_cap_base = USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
+
+ if (wLength < desc_size)
+ return wLength;
+ buf[ssp_cap_base] = ssp_cap_size + ssa_size;
+
+ /* attribute count SSAC bits 4:0 and ID count SSIC bits 8:5 */
+ bm_attrib = (ssa_count - 1) & 0x1f;
+ bm_attrib |= (xhci->usb3_rhub.psi_uid_count - 1) << 5;
+ put_unaligned_le32(bm_attrib, &buf[ssp_cap_base + 4]);
+
+ if (wLength < desc_size + ssa_size)
+ return wLength;
+ /*
+ * Create the Sublink Speed Attributes (SSA) array.
+ * The xhci PSI field and USB 3.1 SSA fields are very similar,
+ * but link type bits 7:6 differ for values 01b and 10b.
+ * xhci has also only one PSI entry for a symmetric link when
+ * USB 3.1 requires two SSA entries (RX and TX) for every link
+ */
+ offset = desc_size;
+ for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
+ psi = xhci->usb3_rhub.psi[i];
+ psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
+ if ((psi & PLT_MASK) == PLT_SYM) {
+ /* Symmetric, create SSA RX and TX from one PSI entry */
+ put_unaligned_le32(psi, &buf[offset]);
+ psi |= 1 << 7; /* turn entry to TX */
+ offset += 4;
+ if (offset >= desc_size + ssa_size)
+ return desc_size + ssa_size;
+ } else if ((psi & PLT_MASK) == PLT_ASYM_RX) {
+ /* Asymetric RX, flip bits 7:6 for SSA */
+ psi ^= PLT_MASK;
+ }
+ put_unaligned_le32(psi, &buf[offset]);
+ offset += 4;
+ if (offset >= desc_size + ssa_size)
+ return desc_size + ssa_size;
+ }
+ }
+ /* ssa_size is 0 for other than usb 3.1 hosts */
+ return desc_size + ssa_size;
+}
static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
struct usb_hub_descriptor *desc, int ports)
@@ -161,7 +262,7 @@ static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
struct usb_hub_descriptor *desc)
{
- if (hcd->speed == HCD_USB3)
+ if (hcd->speed >= HCD_USB3)
xhci_usb3_hub_descriptor(hcd, xhci, desc);
else
xhci_usb2_hub_descriptor(hcd, xhci, desc);
@@ -250,7 +351,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
if (!xhci->devs[i])
continue;
speed = xhci->devs[i]->udev->speed;
- if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3))
+ if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))
&& xhci->devs[i]->fake_port == port) {
slot_id = i;
break;
@@ -339,7 +440,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
/* Don't allow the USB core to disable SuperSpeed ports. */
- if (hcd->speed == HCD_USB3) {
+ if (hcd->speed >= HCD_USB3) {
xhci_dbg(xhci, "Ignoring request to disable "
"SuperSpeed port.\n");
return;
@@ -407,7 +508,7 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array)
int max_ports;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- if (hcd->speed == HCD_USB3) {
+ if (hcd->speed >= HCD_USB3) {
max_ports = xhci->num_usb3_ports;
*port_array = xhci->usb3_ports;
} else {
@@ -558,6 +659,22 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
}
}
+static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li)
+{
+ u32 ext_stat = 0;
+ int speed_id;
+
+ /* only support rx and tx lane counts of 1 in usb3.1 spec */
+ speed_id = DEV_PORT_SPEED(raw_port_status);
+ ext_stat |= speed_id; /* bits 3:0, RX speed id */
+ ext_stat |= speed_id << 4; /* bits 7:4, TX speed id */
+
+ ext_stat |= PORT_RX_LANES(port_li) << 8; /* bits 11:8 Rx lane count */
+ ext_stat |= PORT_TX_LANES(port_li) << 12; /* bits 15:12 Tx lane count */
+
+ return ext_stat;
+}
+
/*
* Converts a raw xHCI port status into the format that external USB 2.0 or USB
* 3.0 hubs use.
@@ -590,7 +707,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
if ((raw_port_status & PORT_RC))
status |= USB_PORT_STAT_C_RESET << 16;
/* USB3.0 only */
- if (hcd->speed == HCD_USB3) {
+ if (hcd->speed >= HCD_USB3) {
/* Port link change with port in resume state should not be
* reported to usbcore, as this is an internal state to be
* handled by xhci driver. Reporting PLC to usbcore may
@@ -606,13 +723,13 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
}
- if (hcd->speed != HCD_USB3) {
+ if (hcd->speed < HCD_USB3) {
if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3
&& (raw_port_status & PORT_POWER))
status |= USB_PORT_STAT_SUSPEND;
}
if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
- !DEV_SUPERSPEED(raw_port_status)) {
+ !DEV_SUPERSPEED_ANY(raw_port_status)) {
if ((raw_port_status & PORT_RESET) ||
!(raw_port_status & PORT_PE))
return 0xffffffff;
@@ -665,12 +782,15 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
status |= USB_PORT_STAT_SUSPEND;
}
}
- if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0
- && (raw_port_status & PORT_POWER)
- && (bus_state->suspended_ports & (1 << wIndex))) {
- bus_state->suspended_ports &= ~(1 << wIndex);
- if (hcd->speed != HCD_USB3)
- bus_state->port_c_suspend |= 1 << wIndex;
+ if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
+ (raw_port_status & PORT_POWER)) {
+ if (bus_state->suspended_ports & (1 << wIndex)) {
+ bus_state->suspended_ports &= ~(1 << wIndex);
+ if (hcd->speed < HCD_USB3)
+ bus_state->port_c_suspend |= 1 << wIndex;
+ }
+ bus_state->resume_done[wIndex] = 0;
+ clear_bit(wIndex, &bus_state->resuming_ports);
}
if (raw_port_status & PORT_CONNECT) {
status |= USB_PORT_STAT_CONNECTION;
@@ -683,13 +803,13 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
if (raw_port_status & PORT_RESET)
status |= USB_PORT_STAT_RESET;
if (raw_port_status & PORT_POWER) {
- if (hcd->speed == HCD_USB3)
+ if (hcd->speed >= HCD_USB3)
status |= USB_SS_PORT_STAT_POWER;
else
status |= USB_PORT_STAT_POWER;
}
/* Update Port Link State */
- if (hcd->speed == HCD_USB3) {
+ if (hcd->speed >= HCD_USB3) {
xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status);
/*
* Verify if all USB3 Ports Have entered U0 already.
@@ -734,7 +854,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
* descriptor for the USB 3.0 roothub. If not, we stall the
* endpoint, like external hubs do.
*/
- if (hcd->speed == HCD_USB3 &&
+ if (hcd->speed >= HCD_USB3 &&
(wLength < USB_DT_SS_HUB_SIZE ||
wValue != (USB_DT_SS_HUB << 8))) {
xhci_dbg(xhci, "Wrong hub descriptor type for "
@@ -748,25 +868,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if ((wValue & 0xff00) != (USB_DT_BOS << 8))
goto error;
- if (hcd->speed != HCD_USB3)
+ if (hcd->speed < HCD_USB3)
goto error;
- /* Set the U1 and U2 exit latencies. */
- memcpy(buf, &usb_bos_descriptor,
- USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
- if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
- temp = readl(&xhci->cap_regs->hcs_params3);
- buf[12] = HCS_U1_LATENCY(temp);
- put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
- }
-
- /* Indicate whether the host has LTM support. */
- temp = readl(&xhci->cap_regs->hcc_params);
- if (HCC_LTC(temp))
- buf[8] |= USB_LTM_SUPPORT;
-
+ retval = xhci_create_usb3_bos_desc(xhci, buf, wLength);
spin_unlock_irqrestore(&xhci->lock, flags);
- return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
+ return retval;
case GetPortStatus:
if (!wIndex || wIndex > max_ports)
goto error;
@@ -786,6 +893,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
+ /* if USB 3.1 extended port status return additional 4 bytes */
+ if (wValue == 0x02) {
+ u32 port_li;
+
+ if (hcd->speed < HCD_USB31 || wLength != 8) {
+ xhci_err(xhci, "get ext port status invalid parameter\n");
+ retval = -EINVAL;
+ break;
+ }
+ port_li = readl(port_array[wIndex] + PORTLI);
+ status = xhci_get_ext_port_status(temp, port_li);
+ put_unaligned_le32(cpu_to_le32(status), &buf[4]);
+ }
break;
case SetPortFeature:
if (wValue == USB_PORT_FEAT_LINK_STATE)
@@ -952,7 +1072,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = readl(port_array[wIndex]);
break;
case USB_PORT_FEAT_U1_TIMEOUT:
- if (hcd->speed != HCD_USB3)
+ if (hcd->speed < HCD_USB3)
goto error;
temp = readl(port_array[wIndex] + PORTPMSC);
temp &= ~PORT_U1_TIMEOUT_MASK;
@@ -960,7 +1080,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
writel(temp, port_array[wIndex] + PORTPMSC);
break;
case USB_PORT_FEAT_U2_TIMEOUT:
- if (hcd->speed != HCD_USB3)
+ if (hcd->speed < HCD_USB3)
goto error;
temp = readl(port_array[wIndex] + PORTPMSC);
temp &= ~PORT_U2_TIMEOUT_MASK;
@@ -1223,14 +1343,14 @@ int xhci_bus_resume(struct usb_hcd *hcd)
u32 temp;
temp = readl(port_array[port_index]);
- if (DEV_SUPERSPEED(temp))
+ if (DEV_SUPERSPEED_ANY(temp))
temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
else
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
if (test_bit(port_index, &bus_state->bus_suspended) &&
(temp & PORT_PLS_MASK)) {
set_bit(port_index, &port_was_suspended);
- if (!DEV_SUPERSPEED(temp)) {
+ if (!DEV_SUPERSPEED_ANY(temp)) {
xhci_set_link_state(xhci, port_array,
port_index, XDEV_RESUME);
need_usb2_u3_exit = true;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 41f841fa6c4d..c48cbe731356 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1828,24 +1828,20 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
for (i = 1; i < MAX_HC_SLOTS; ++i)
xhci_free_virt_device(xhci, i);
- if (xhci->segment_pool)
- dma_pool_destroy(xhci->segment_pool);
+ dma_pool_destroy(xhci->segment_pool);
xhci->segment_pool = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed segment pool");
- if (xhci->device_pool)
- dma_pool_destroy(xhci->device_pool);
+ dma_pool_destroy(xhci->device_pool);
xhci->device_pool = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed device context pool");
- if (xhci->small_streams_pool)
- dma_pool_destroy(xhci->small_streams_pool);
+ dma_pool_destroy(xhci->small_streams_pool);
xhci->small_streams_pool = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Freed small stream array pool");
- if (xhci->medium_streams_pool)
- dma_pool_destroy(xhci->medium_streams_pool);
+ dma_pool_destroy(xhci->medium_streams_pool);
xhci->medium_streams_pool = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Freed medium stream array pool");
@@ -2072,14 +2068,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
{
u32 temp, port_offset, port_count;
int i;
+ struct xhci_hub *rhub;
- if (major_revision > 0x03) {
+ temp = readl(addr);
+
+ if (XHCI_EXT_PORT_MAJOR(temp) == 0x03) {
+ rhub = &xhci->usb3_rhub;
+ } else if (XHCI_EXT_PORT_MAJOR(temp) <= 0x02) {
+ rhub = &xhci->usb2_rhub;
+ } else {
xhci_warn(xhci, "Ignoring unknown port speed, "
"Ext Cap %p, revision = 0x%x\n",
addr, major_revision);
/* Ignoring port protocol we can't understand. FIXME */
return;
}
+ rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
+ rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
/* Port offset and count in the third dword, see section 7.2 */
temp = readl(addr + 2);
@@ -2094,6 +2099,33 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
/* WTF? "Valid values are ‘1’ to MaxPorts" */
return;
+ rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
+ if (rhub->psi_count) {
+ rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi),
+ GFP_KERNEL);
+ if (!rhub->psi)
+ rhub->psi_count = 0;
+
+ rhub->psi_uid_count++;
+ for (i = 0; i < rhub->psi_count; i++) {
+ rhub->psi[i] = readl(addr + 4 + i);
+
+ /* count unique ID values, two consecutive entries can
+ * have the same ID if link is assymetric
+ */
+ if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
+ XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
+ rhub->psi_uid_count++;
+
+ xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
+ XHCI_EXT_PORT_PSIV(rhub->psi[i]),
+ XHCI_EXT_PORT_PSIE(rhub->psi[i]),
+ XHCI_EXT_PORT_PLT(rhub->psi[i]),
+ XHCI_EXT_PORT_PFD(rhub->psi[i]),
+ XHCI_EXT_PORT_LP(rhub->psi[i]),
+ XHCI_EXT_PORT_PSIM(rhub->psi[i]));
+ }
+ }
/* cache usb2 port capabilities */
if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
xhci->ext_caps[xhci->num_ext_caps++] = temp;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c79d33676672..17f6897acde2 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+ xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
@@ -200,15 +201,17 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval;
+ xhci = hcd_to_xhci(hcd);
+ if (!xhci->sbrn)
+ pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
+
retval = xhci_gen_setup(hcd, xhci_pci_quirks);
if (retval)
return retval;
- xhci = hcd_to_xhci(hcd);
if (!usb_hcd_is_primary_hcd(hcd))
return 0;
- pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
/* Find any debug ports */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 890ad9d9d329..05647e6753cd 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -19,6 +19,7 @@
#include <linux/usb/phy.h>
#include <linux/slab.h>
#include <linux/usb/xhci_pdriver.h>
+#include <linux/acpi.h>
#include "xhci.h"
#include "xhci-mvebu.h"
@@ -93,14 +94,20 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (irq < 0)
return -ENODEV;
- /* Initialize dma_mask and coherent_dma_mask to 32-bits */
- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
- if (!pdev->dev.dma_mask)
- pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+ /* Try to set 64-bit DMA first */
+ if (WARN_ON(!pdev->dev.dma_mask))
+ /* Platform did not initialize dma_mask */
+ ret = dma_coerce_mask_and_coherent(&pdev->dev,
+ DMA_BIT_MASK(64));
else
- dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+ /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+ if (ret) {
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+ }
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd)
@@ -262,6 +269,13 @@ static const struct of_device_id usb_xhci_of_match[] = {
MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
#endif
+static const struct acpi_device_id usb_xhci_acpi_match[] = {
+ /* XHCI-compliant USB Controller */
+ { "PNP0D10", },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
+
static struct platform_driver usb_xhci_driver = {
.probe = xhci_plat_probe,
.remove = xhci_plat_remove,
@@ -269,6 +283,7 @@ static struct platform_driver usb_xhci_driver = {
.name = "xhci-hcd",
.pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(usb_xhci_of_match),
+ .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
};
MODULE_ALIAS("platform:xhci-hcd");
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 43291f93afeb..6c5e8133cf87 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1453,7 +1453,7 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
* 1.1 ports are under the USB 2.0 hub. If the port speed
* matches the device speed, it's a similar speed port.
*/
- if ((port_speed == 0x03) == (hcd->speed == HCD_USB3))
+ if ((port_speed == 0x03) == (hcd->speed >= HCD_USB3))
num_similar_speed_ports++;
}
return num_similar_speed_ports;
@@ -1515,7 +1515,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
/* Find the right roothub. */
hcd = xhci_to_hcd(xhci);
- if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
+ if ((major_revision == 0x03) != (hcd->speed >= HCD_USB3))
hcd = xhci->shared_hcd;
if (major_revision == 0) {
@@ -1541,7 +1541,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
* correct bus_state structure.
*/
bus_state = &xhci->bus_state[hcd_index(hcd)];
- if (hcd->speed == HCD_USB3)
+ if (hcd->speed >= HCD_USB3)
port_array = xhci->usb3_ports;
else
port_array = xhci->usb2_ports;
@@ -1555,7 +1555,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
usb_hcd_resume_root_hub(hcd);
}
- if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE)
+ if (hcd->speed >= HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE)
bus_state->port_remote_wakeup &= ~(1 << faked_port_index);
if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
@@ -1567,7 +1567,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
goto cleanup;
}
- if (DEV_SUPERSPEED(temp)) {
+ if (DEV_SUPERSPEED_ANY(temp)) {
xhci_dbg(xhci, "remote wake SS port %d\n", port_id);
/* Set a flag to say the port signaled remote wakeup,
* so we can tell the difference between the end of
@@ -1595,7 +1595,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
}
if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 &&
- DEV_SUPERSPEED(temp)) {
+ DEV_SUPERSPEED_ANY(temp)) {
xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
/* We've just brought the device into U0 through either the
* Resume state after a device remote wakeup, or through the
@@ -1625,7 +1625,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
* RExit to a disconnect state). If so, let the the driver know it's
* out of the RExit state.
*/
- if (!DEV_SUPERSPEED(temp) &&
+ if (!DEV_SUPERSPEED_ANY(temp) &&
test_and_clear_bit(faked_port_index,
&bus_state->rexit_ports)) {
complete(&bus_state->rexit_done[faked_port_index]);
@@ -1633,7 +1633,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
goto cleanup;
}
- if (hcd->speed != HCD_USB3)
+ if (hcd->speed < HCD_USB3)
xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
PORT_PLC);
@@ -2191,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
}
/* Fast path - was this the last TRB in the TD for this URB? */
} else if (event_trb == td->last_trb) {
+ if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+ return finish_td(xhci, td, event_trb, event, ep,
+ status, false);
+
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
@@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+ if (trb_comp_code == COMP_SHORT_TX) {
+ xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+ td->urb_length_set = true;
+ return 0;
+ }
}
return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
u32 trb_comp_code;
int ret = 0;
int td_num = 0;
+ bool handling_skipped_tds = false;
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
@@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep->skip = true;
xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
goto cleanup;
+ case COMP_PING_ERR:
+ ep->skip = true;
+ xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+ goto cleanup;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
@@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep, &status);
cleanup:
+
+
+ handling_skipped_tds = ep->skip &&
+ trb_comp_code != COMP_MISSED_INT &&
+ trb_comp_code != COMP_PING_ERR;
+
/*
- * Do not update event ring dequeue pointer if ep->skip is set.
- * Will roll back to continue process missed tds.
+ * Do not update event ring dequeue pointer if we're in a loop
+ * processing missed tds.
*/
- if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+ if (!handling_skipped_tds)
inc_deq(xhci, xhci->event_ring);
- }
if (ret) {
urb = td->urb;
@@ -2587,7 +2607,7 @@ cleanup:
* Process them as short transfer until reach the td pointed by
* the event.
*/
- } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+ } while (handling_skipped_tds);
return 0;
}
@@ -3029,21 +3049,6 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
}
/*
- * The TD size is the number of bytes remaining in the TD (including this TRB),
- * right shifted by 10.
- * It must fit in bits 21:17, so it can't be bigger than 31.
- */
-static u32 xhci_td_remainder(unsigned int remainder)
-{
- u32 max = (1 << (21 - 17 + 1)) - 1;
-
- if ((remainder >> 10) >= max)
- return max << 17;
- else
- return (remainder >> 10) << 17;
-}
-
-/*
* For xHCI 1.0 host controllers, TD size is the number of max packet sized
* packets remaining in the TD (*not* including this TRB).
*
@@ -3055,30 +3060,36 @@ static u32 xhci_td_remainder(unsigned int remainder)
*
* TD size = total_packet_count - packets_transferred
*
- * It must fit in bits 21:17, so it can't be bigger than 31.
+ * For xHCI 0.96 and older, TD size field should be the remaining bytes
+ * including this TRB, right shifted by 10
+ *
+ * For all hosts it must fit in bits 21:17, so it can't be bigger than 31.
+ * This is taken care of in the TRB_TD_SIZE() macro
+ *
* The last TRB in a TD must have the TD size set to zero.
*/
-static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
- unsigned int total_packet_count, struct urb *urb,
- unsigned int num_trbs_left)
+static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
+ int trb_buff_len, unsigned int td_total_len,
+ struct urb *urb, unsigned int num_trbs_left)
{
- int packets_transferred;
+ u32 maxp, total_packet_count;
+
+ if (xhci->hci_version < 0x100)
+ return ((td_total_len - transferred) >> 10);
+
+ maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
+ total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
/* One TRB with a zero-length data packet. */
- if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
+ if (num_trbs_left == 0 || (transferred == 0 && trb_buff_len == 0) ||
+ trb_buff_len == td_total_len)
return 0;
- /* All the TRB queueing functions don't count the current TRB in
- * running_total.
- */
- packets_transferred = (running_total + trb_buff_len) /
- GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
-
- if ((total_packet_count - packets_transferred) > 31)
- return 31 << 17;
- return (total_packet_count - packets_transferred) << 17;
+ /* Queueing functions don't count the current TRB into transferred */
+ return (total_packet_count - ((transferred + trb_buff_len) / maxp));
}
+
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
{
@@ -3200,17 +3211,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
}
/* Set the TRB length, TD size, and interrupter fields. */
- if (xhci->hci_version < 0x100) {
- remainder = xhci_td_remainder(
- urb->transfer_buffer_length -
- running_total);
- } else {
- remainder = xhci_v1_0_td_remainder(running_total,
- trb_buff_len, total_packet_count, urb,
- num_trbs - 1);
- }
+ remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
+ urb->transfer_buffer_length,
+ urb, num_trbs - 1);
+
length_field = TRB_LEN(trb_buff_len) |
- remainder |
+ TRB_TD_SIZE(remainder) |
TRB_INTR_TARGET(0);
if (num_trbs > 1)
@@ -3373,17 +3379,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field |= TRB_ISP;
/* Set the TRB length, TD size, and interrupter fields. */
- if (xhci->hci_version < 0x100) {
- remainder = xhci_td_remainder(
- urb->transfer_buffer_length -
- running_total);
- } else {
- remainder = xhci_v1_0_td_remainder(running_total,
- trb_buff_len, total_packet_count, urb,
- num_trbs - 1);
- }
+ remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
+ urb->transfer_buffer_length,
+ urb, num_trbs - 1);
+
length_field = TRB_LEN(trb_buff_len) |
- remainder |
+ TRB_TD_SIZE(remainder) |
TRB_INTR_TARGET(0);
if (num_trbs > 1)
@@ -3421,7 +3422,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct usb_ctrlrequest *setup;
struct xhci_generic_trb *start_trb;
int start_cycle;
- u32 field, length_field;
+ u32 field, length_field, remainder;
struct urb_priv *urb_priv;
struct xhci_td *td;
@@ -3494,9 +3495,15 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
else
field = TRB_TYPE(TRB_DATA);
+ remainder = xhci_td_remainder(xhci, 0,
+ urb->transfer_buffer_length,
+ urb->transfer_buffer_length,
+ urb, 1);
+
length_field = TRB_LEN(urb->transfer_buffer_length) |
- xhci_td_remainder(urb->transfer_buffer_length) |
+ TRB_TD_SIZE(remainder) |
TRB_INTR_TARGET(0);
+
if (urb->transfer_buffer_length > 0) {
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN;
@@ -3825,17 +3832,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
trb_buff_len = td_remain_len;
/* Set the TRB length, TD size, & interrupter fields. */
- if (xhci->hci_version < 0x100) {
- remainder = xhci_td_remainder(
- td_len - running_total);
- } else {
- remainder = xhci_v1_0_td_remainder(
- running_total, trb_buff_len,
- total_packet_count, urb,
- (trbs_per_td - j - 1));
- }
+ remainder = xhci_td_remainder(xhci, running_total,
+ trb_buff_len, td_len,
+ urb, trbs_per_td - j - 1);
+
length_field = TRB_LEN(trb_buff_len) |
- remainder |
+ TRB_TD_SIZE(remainder) |
TRB_INTR_TARGET(0);
queue_trb(xhci, ep_ring, more_trbs_coming,
@@ -3894,28 +3896,6 @@ cleanup:
return ret;
}
-static int ep_ring_is_processing(struct xhci_hcd *xhci,
- int slot_id, unsigned int ep_index)
-{
- struct xhci_virt_device *xdev;
- struct xhci_ring *ep_ring;
- struct xhci_ep_ctx *ep_ctx;
- struct xhci_virt_ep *xep;
- dma_addr_t hw_deq;
-
- xdev = xhci->devs[slot_id];
- xep = &xhci->devs[slot_id]->eps[ep_index];
- ep_ring = xep->ring;
- ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
-
- if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING)
- return 0;
-
- hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
- return (hw_deq !=
- xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue));
-}
-
/*
* Check transfer ring to guarantee there is enough room for the urb.
* Update ISO URB start_frame and interval.
@@ -3981,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
}
/* Calculate the start frame and put it in urb->start_frame. */
- if (HCC_CFC(xhci->hcc_params) &&
- ep_ring_is_processing(xhci, slot_id, ep_index)) {
- urb->start_frame = xep->next_frame_id;
- goto skip_start_over;
+ if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) {
+ if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
+ EP_STATE_RUNNING) {
+ urb->start_frame = xep->next_frame_id;
+ goto skip_start_over;
+ }
}
start_frame = readl(&xhci->run_regs->microframe_index);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9957bd96d4bc..dfa44d3e8eee 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -175,6 +175,16 @@ int xhci_reset(struct xhci_hcd *xhci)
command |= CMD_RESET;
writel(command, &xhci->op_regs->command);
+ /* Existing Intel xHCI controllers require a delay of 1 mS,
+ * after setting the CMD_RESET bit, and before accessing any
+ * HC registers. This allows the HC to complete the
+ * reset operation and be ready for HC register access.
+ * Without this delay, the subsequent HC register access,
+ * may result in a system hang very rarely.
+ */
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ udelay(1000);
+
ret = xhci_handshake(&xhci->op_regs->command,
CMD_RESET, 0, 10 * 1000 * 1000);
if (ret)
@@ -3973,7 +3983,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
__le32 __iomem *addr;
int raw_port;
- if (hcd->speed != HCD_USB3)
+ if (hcd->speed < HCD_USB3)
addr = xhci->usb2_ports[port1 - 1];
else
addr = xhci->usb3_ports[port1 - 1];
@@ -4124,7 +4134,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
int hird, exit_latency;
int ret;
- if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support ||
+ if (hcd->speed >= HCD_USB3 || !xhci->hw_lpm_support ||
!udev->lpm_capable)
return -EPERM;
@@ -4241,7 +4251,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int portnum = udev->portnum - 1;
- if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
+ if (hcd->speed >= HCD_USB3 || !xhci->sw_lpm_support ||
!udev->lpm_capable)
return 0;
@@ -4841,8 +4851,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
/* XHCI controllers don't stop the ep queue on short packets :| */
hcd->self.no_stop_on_short = 1;
+ xhci = hcd_to_xhci(hcd);
+
if (usb_hcd_is_primary_hcd(hcd)) {
- xhci = hcd_to_xhci(hcd);
xhci->main_hcd = hcd;
/* Mark the first roothub as being USB 2.0.
* The xHCI driver will register the USB 3.0 roothub.
@@ -4856,6 +4867,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
*/
hcd->has_tt = 1;
} else {
+ if (xhci->sbrn == 0x31) {
+ xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n");
+ hcd->speed = HCD_USB31;
+ }
/* xHCI private pointer was set in xhci_pci_probe for the second
* registered roothub.
*/
@@ -4875,6 +4890,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
xhci->hcc_params = readl(&xhci->cap_regs->hc_capbase);
xhci->hci_version = HC_VERSION(xhci->hcc_params);
xhci->hcc_params = readl(&xhci->cap_regs->hcc_params);
+ if (xhci->hci_version > 0x100)
+ xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
xhci_print_registers(xhci);
xhci->quirks = quirks;
@@ -4906,6 +4923,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
!dma_set_mask(dev, DMA_BIT_MASK(64))) {
xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+ } else {
+ /*
+ * This is to avoid error in cases where a 32-bit USB
+ * controller is used on a 64-bit capable system.
+ */
+ retval = dma_set_mask(dev, DMA_BIT_MASK(32));
+ if (retval)
+ return retval;
+ xhci_dbg(xhci, "Enabling 32-bit DMA addresses.\n");
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
}
xhci_dbg(xhci, "Calling HCD init\n");
@@ -5020,7 +5047,7 @@ static int __init xhci_hcd_init(void)
BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
- BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 7*32/8);
+ BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 8*32/8);
BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
/* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index dbda41e91c84..0b9451250e33 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -28,6 +28,7 @@
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/usb/hcd.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
/* Code sharing between pci-quirks and xhci hcd */
#include "xhci-ext-caps.h"
@@ -56,6 +57,7 @@
* @hcc_params: HCCPARAMS - Capability Parameters
* @db_off: DBOFF - Doorbell array offset
* @run_regs_off: RTSOFF - Runtime register space offset
+ * @hcc_params2: HCCPARAMS2 Capability Parameters 2, xhci 1.1 only
*/
struct xhci_cap_regs {
__le32 hc_capbase;
@@ -65,6 +67,7 @@ struct xhci_cap_regs {
__le32 hcc_params;
__le32 db_off;
__le32 run_regs_off;
+ __le32 hcc_params2; /* xhci 1.1 */
/* Reserved up to (CAPLENGTH - 0x1C) */
};
@@ -134,6 +137,21 @@ struct xhci_cap_regs {
/* run_regs_off bitmask - bits 0:4 reserved */
#define RTSOFF_MASK (~0x1f)
+/* HCCPARAMS2 - hcc_params2 - bitmasks */
+/* true: HC supports U3 entry Capability */
+#define HCC2_U3C(p) ((p) & (1 << 0))
+/* true: HC supports Configure endpoint command Max exit latency too large */
+#define HCC2_CMC(p) ((p) & (1 << 1))
+/* true: HC supports Force Save context Capability */
+#define HCC2_FSC(p) ((p) & (1 << 2))
+/* true: HC supports Compliance Transition Capability */
+#define HCC2_CTC(p) ((p) & (1 << 3))
+/* true: HC support Large ESIT payload Capability > 48k */
+#define HCC2_LEC(p) ((p) & (1 << 4))
+/* true: HC support Configuration Information Capability */
+#define HCC2_CIC(p) ((p) & (1 << 5))
+/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */
+#define HCC2_ETC(p) ((p) & (1 << 6))
/* Number of registers per port */
#define NUM_PORT_REGS 4
@@ -269,7 +287,11 @@ struct xhci_op_regs {
/* CONFIG - Configure Register - config_reg bitmasks */
/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
#define MAX_DEVS(p) ((p) & 0xff)
-/* bits 8:31 - reserved and should be preserved */
+/* bit 8: U3 Entry Enabled, assert PLC when root port enters U3, xhci 1.1 */
+#define CONFIG_U3E (1 << 8)
+/* bit 9: Configuration Information Enable, xhci 1.1 */
+#define CONFIG_CIE (1 << 9)
+/* bits 10:31 - reserved and should be preserved */
/* PORTSC - Port Status and Control Register - port_status_base bitmasks */
/* true: device connected */
@@ -306,11 +328,16 @@ struct xhci_op_regs {
#define XDEV_LS (0x2 << 10)
#define XDEV_HS (0x3 << 10)
#define XDEV_SS (0x4 << 10)
+#define XDEV_SSP (0x5 << 10)
#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0<<10))
#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS)
#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_LS)
#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS)
#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS)
+#define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP)
+#define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS)
+#define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f)
+
/* Bits 20:23 in the Slot Context are the speed for the device */
#define SLOT_SPEED_FS (XDEV_FS << 10)
#define SLOT_SPEED_LS (XDEV_LS << 10)
@@ -394,6 +421,9 @@ struct xhci_op_regs {
#define PORT_L1DS(p) (((p) & 0xff) << 8)
#define PORT_HLE (1 << 16)
+/* USB3 Protocol PORTLI Port Link Information */
+#define PORT_RX_LANES(p) (((p) >> 16) & 0xf)
+#define PORT_TX_LANES(p) (((p) >> 20) & 0xf)
/* USB2 Protocol PORTHLPMC */
#define PORT_HIRDM(p)((p) & 3)
@@ -519,9 +549,23 @@ struct xhci_protocol_caps {
};
#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff)
+#define XHCI_EXT_PORT_MINOR(x) (((x) >> 16) & 0xff)
+#define XHCI_EXT_PORT_PSIC(x) (((x) >> 28) & 0x0f)
#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff)
#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff)
+#define XHCI_EXT_PORT_PSIV(x) (((x) >> 0) & 0x0f)
+#define XHCI_EXT_PORT_PSIE(x) (((x) >> 4) & 0x03)
+#define XHCI_EXT_PORT_PLT(x) (((x) >> 6) & 0x03)
+#define XHCI_EXT_PORT_PFD(x) (((x) >> 8) & 0x01)
+#define XHCI_EXT_PORT_LP(x) (((x) >> 14) & 0x03)
+#define XHCI_EXT_PORT_PSIM(x) (((x) >> 16) & 0xffff)
+
+#define PLT_MASK (0x03 << 6)
+#define PLT_SYM (0x00 << 6)
+#define PLT_ASYM_RX (0x02 << 6)
+#define PLT_ASYM_TX (0x03 << 6)
+
/**
* struct xhci_container_ctx
* @type: Type of context. Used to calculated offsets to contained contexts.
@@ -1136,6 +1180,8 @@ enum xhci_setup_dev {
/* Normal TRB fields */
/* transfer_len bitmasks - bits 0:16 */
#define TRB_LEN(p) ((p) & 0x1ffff)
+/* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */
+#define TRB_TD_SIZE(p) (min((p), (u32)31) << 17)
/* Interrupter Target - which MSI-X vector to target the completion event at */
#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22)
#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff)
@@ -1448,6 +1494,14 @@ static inline unsigned int hcd_index(struct usb_hcd *hcd)
return 1;
}
+struct xhci_hub {
+ u8 maj_rev;
+ u8 min_rev;
+ u32 *psi; /* array of protocol speed ID entries */
+ u8 psi_count;
+ u8 psi_uid_count;
+};
+
/* There is one xhci_hcd structure per controller */
struct xhci_hcd {
struct usb_hcd *main_hcd;
@@ -1465,6 +1519,7 @@ struct xhci_hcd {
__u32 hcs_params2;
__u32 hcs_params3;
__u32 hcc_params;
+ __u32 hcc_params2;
spinlock_t lock;
@@ -1586,6 +1641,8 @@ struct xhci_hcd {
unsigned int num_usb3_ports;
/* Array of pointers to USB 2.0 PORTSC registers */
__le32 __iomem **usb2_ports;
+ struct xhci_hub usb2_rhub;
+ struct xhci_hub usb3_rhub;
unsigned int num_usb2_ports;
/* support xHCI 0.96 spec USB2 software LPM */
unsigned sw_lpm_support:1;
@@ -1651,20 +1708,12 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
__le64 __iomem *regs)
{
- __u32 __iomem *ptr = (__u32 __iomem *) regs;
- u64 val_lo = readl(ptr);
- u64 val_hi = readl(ptr + 1);
- return val_lo + (val_hi << 32);
+ return lo_hi_readq(regs);
}
static inline void xhci_write_64(struct xhci_hcd *xhci,
const u64 val, __le64 __iomem *regs)
{
- __u32 __iomem *ptr = (__u32 __iomem *) regs;
- u32 val_lo = lower_32_bits(val);
- u32 val_hi = upper_32_bits(val);
-
- writel(val_lo, ptr);
- writel(val_hi, ptr + 1);
+ lo_hi_writeq(val, regs);
}
static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index 64ff5b91752d..b45cb77c0744 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -410,7 +410,7 @@ static int __init usb3503_init(void)
{
int err;
- err = i2c_register_driver(THIS_MODULE, &usb3503_i2c_driver);
+ err = i2c_add_driver(&usb3503_i2c_driver);
if (err != 0)
pr_err("usb3503: Failed to register I2C driver: %d\n", err);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 9517812a50e2..637f3f7cfce8 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -17,6 +17,7 @@
static int override_alt = -1;
module_param_named(alt, override_alt, int, 0644);
MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection");
+static void complicated_callback(struct urb *urb);
/*-------------------------------------------------------------------------*/
@@ -95,6 +96,7 @@ static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test)
dev_warn(&(tdev)->intf->dev , fmt , ## args)
#define GUARD_BYTE 0xA5
+#define MAX_SGLEN 128
/*-------------------------------------------------------------------------*/
@@ -238,7 +240,8 @@ static struct urb *usbtest_alloc_urb(
unsigned long bytes,
unsigned transfer_flags,
unsigned offset,
- u8 bInterval)
+ u8 bInterval,
+ usb_complete_t complete_fn)
{
struct urb *urb;
@@ -247,10 +250,10 @@ static struct urb *usbtest_alloc_urb(
return urb;
if (bInterval)
- usb_fill_int_urb(urb, udev, pipe, NULL, bytes, simple_callback,
+ usb_fill_int_urb(urb, udev, pipe, NULL, bytes, complete_fn,
NULL, bInterval);
else
- usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback,
+ usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, complete_fn,
NULL);
urb->interval = (udev->speed == USB_SPEED_HIGH)
@@ -295,7 +298,17 @@ static struct urb *simple_alloc_urb(
u8 bInterval)
{
return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0,
- bInterval);
+ bInterval, simple_callback);
+}
+
+static struct urb *complicated_alloc_urb(
+ struct usb_device *udev,
+ int pipe,
+ unsigned long bytes,
+ u8 bInterval)
+{
+ return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0,
+ bInterval, complicated_callback);
}
static unsigned pattern;
@@ -303,11 +316,20 @@ static unsigned mod_pattern;
module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)");
-static inline void simple_fill_buf(struct urb *urb)
+static unsigned get_maxpacket(struct usb_device *udev, int pipe)
+{
+ struct usb_host_endpoint *ep;
+
+ ep = usb_pipe_endpoint(udev, pipe);
+ return le16_to_cpup(&ep->desc.wMaxPacketSize);
+}
+
+static void simple_fill_buf(struct urb *urb)
{
unsigned i;
u8 *buf = urb->transfer_buffer;
unsigned len = urb->transfer_buffer_length;
+ unsigned maxpacket;
switch (pattern) {
default:
@@ -316,8 +338,9 @@ static inline void simple_fill_buf(struct urb *urb)
memset(buf, 0, len);
break;
case 1: /* mod63 */
+ maxpacket = get_maxpacket(urb->dev, urb->pipe);
for (i = 0; i < len; i++)
- *buf++ = (u8) (i % 63);
+ *buf++ = (u8) ((i % maxpacket) % 63);
break;
}
}
@@ -349,6 +372,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
u8 expected;
u8 *buf = urb->transfer_buffer;
unsigned len = urb->actual_length;
+ unsigned maxpacket = get_maxpacket(urb->dev, urb->pipe);
int ret = check_guard_bytes(tdev, urb);
if (ret)
@@ -366,7 +390,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
* with set_interface or set_config.
*/
case 1: /* mod63 */
- expected = i % 63;
+ expected = (i % maxpacket) % 63;
break;
/* always fail unsupported patterns */
default:
@@ -478,11 +502,13 @@ static void free_sglist(struct scatterlist *sg, int nents)
}
static struct scatterlist *
-alloc_sglist(int nents, int max, int vary)
+alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe)
{
struct scatterlist *sg;
unsigned i;
unsigned size = max;
+ unsigned maxpacket =
+ get_maxpacket(interface_to_usbdev(dev->intf), pipe);
if (max == 0)
return NULL;
@@ -511,7 +537,7 @@ alloc_sglist(int nents, int max, int vary)
break;
case 1:
for (j = 0; j < size; j++)
- *buf++ = (u8) (j % 63);
+ *buf++ = (u8) ((j % maxpacket) % 63);
break;
}
@@ -1719,7 +1745,7 @@ static int ctrl_out(struct usbtest_dev *dev,
for (i = 0; i < count; i++) {
/* write patterned data */
for (j = 0; j < len; j++)
- buf[j] = i + j;
+ buf[j] = (u8)(i + j);
retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
@@ -1749,9 +1775,9 @@ static int ctrl_out(struct usbtest_dev *dev,
/* fail if we can't verify */
for (j = 0; j < len; j++) {
- if (buf[j] != (u8) (i + j)) {
+ if (buf[j] != (u8)(i + j)) {
ERROR(dev, "ctrl_out, byte %d is %d not %d\n",
- j, buf[j], (u8) i + j);
+ j, buf[j], (u8)(i + j));
retval = -EBADMSG;
break;
}
@@ -1781,12 +1807,12 @@ static int ctrl_out(struct usbtest_dev *dev,
/*-------------------------------------------------------------------------*/
-/* ISO tests ... mimics common usage
+/* ISO/BULK tests ... mimics common usage
* - buffer length is split into N packets (mostly maxpacket sized)
* - multi-buffers according to sglen
*/
-struct iso_context {
+struct transfer_context {
unsigned count;
unsigned pending;
spinlock_t lock;
@@ -1795,11 +1821,12 @@ struct iso_context {
unsigned long errors;
unsigned long packet_count;
struct usbtest_dev *dev;
+ bool is_iso;
};
-static void iso_callback(struct urb *urb)
+static void complicated_callback(struct urb *urb)
{
- struct iso_context *ctx = urb->context;
+ struct transfer_context *ctx = urb->context;
spin_lock(&ctx->lock);
ctx->count--;
@@ -1808,7 +1835,7 @@ static void iso_callback(struct urb *urb)
if (urb->error_count > 0)
ctx->errors += urb->error_count;
else if (urb->status != 0)
- ctx->errors += urb->number_of_packets;
+ ctx->errors += (ctx->is_iso ? urb->number_of_packets : 1);
else if (urb->actual_length != urb->transfer_buffer_length)
ctx->errors++;
else if (check_guard_bytes(ctx->dev, urb) != 0)
@@ -1895,7 +1922,7 @@ static struct urb *iso_alloc_urb(
urb->iso_frame_desc[i].offset = maxp * i;
}
- urb->complete = iso_callback;
+ urb->complete = complicated_callback;
/* urb->context = SET BY CALLER */
urb->interval = 1 << (desc->bInterval - 1);
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@@ -1903,37 +1930,33 @@ static struct urb *iso_alloc_urb(
}
static int
-test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
+test_queue(struct usbtest_dev *dev, struct usbtest_param *param,
int pipe, struct usb_endpoint_descriptor *desc, unsigned offset)
{
- struct iso_context context;
+ struct transfer_context context;
struct usb_device *udev;
unsigned i;
unsigned long packets = 0;
int status = 0;
- struct urb *urbs[10]; /* FIXME no limit */
-
- if (param->sglen > 10)
- return -EDOM;
+ struct urb *urbs[param->sglen];
memset(&context, 0, sizeof(context));
context.count = param->iterations * param->sglen;
context.dev = dev;
+ context.is_iso = !!desc;
init_completion(&context.done);
spin_lock_init(&context.lock);
- memset(urbs, 0, sizeof(urbs));
udev = testdev_to_usbdev(dev);
- dev_info(&dev->intf->dev,
- "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
- 1 << (desc->bInterval - 1),
- (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
- usb_endpoint_maxp(desc) & 0x7ff,
- 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
for (i = 0; i < param->sglen; i++) {
- urbs[i] = iso_alloc_urb(udev, pipe, desc,
+ if (context.is_iso)
+ urbs[i] = iso_alloc_urb(udev, pipe, desc,
param->length, offset);
+ else
+ urbs[i] = complicated_alloc_urb(udev, pipe,
+ param->length, 0);
+
if (!urbs[i]) {
status = -ENOMEM;
goto fail;
@@ -1942,11 +1965,21 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
urbs[i]->context = &context;
}
packets *= param->iterations;
- dev_info(&dev->intf->dev,
- "total %lu msec (%lu packets)\n",
- (packets * (1 << (desc->bInterval - 1)))
- / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
- packets);
+
+ if (context.is_iso) {
+ dev_info(&dev->intf->dev,
+ "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
+ 1 << (desc->bInterval - 1),
+ (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
+ usb_endpoint_maxp(desc) & 0x7ff,
+ 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
+
+ dev_info(&dev->intf->dev,
+ "total %lu msec (%lu packets)\n",
+ (packets * (1 << (desc->bInterval - 1)))
+ / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
+ packets);
+ }
spin_lock_irq(&context.lock);
for (i = 0; i < param->sglen; i++) {
@@ -1983,7 +2016,8 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
;
else if (context.submit_error)
status = -EACCES;
- else if (context.errors > context.packet_count / 10)
+ else if (context.errors >
+ (context.is_iso ? context.packet_count / 10 : 0))
status = -EIO;
return status;
@@ -2004,8 +2038,8 @@ static int test_unaligned_bulk(
const char *label)
{
int retval;
- struct urb *urb = usbtest_alloc_urb(
- testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1, 0);
+ struct urb *urb = usbtest_alloc_urb(testdev_to_usbdev(tdev),
+ pipe, length, transfer_flags, 1, 0, simple_callback);
if (!urb)
return -ENOMEM;
@@ -2061,6 +2095,9 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
if (param->iterations <= 0)
return -EINVAL;
+ if (param->sglen > MAX_SGLEN)
+ return -EINVAL;
+
if (mutex_lock_interruptible(&dev->lock))
return -ERESTARTSYS;
@@ -2176,7 +2213,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
"TEST 5: write %d sglists %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
- sg = alloc_sglist(param->sglen, param->length, 0);
+ sg = alloc_sglist(param->sglen, param->length,
+ 0, dev, dev->out_pipe);
if (!sg) {
retval = -ENOMEM;
break;
@@ -2194,7 +2232,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
"TEST 6: read %d sglists %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
- sg = alloc_sglist(param->sglen, param->length, 0);
+ sg = alloc_sglist(param->sglen, param->length,
+ 0, dev, dev->in_pipe);
if (!sg) {
retval = -ENOMEM;
break;
@@ -2211,7 +2250,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
"TEST 7: write/%d %d sglists %d entries 0..%d bytes\n",
param->vary, param->iterations,
param->sglen, param->length);
- sg = alloc_sglist(param->sglen, param->length, param->vary);
+ sg = alloc_sglist(param->sglen, param->length,
+ param->vary, dev, dev->out_pipe);
if (!sg) {
retval = -ENOMEM;
break;
@@ -2228,7 +2268,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
"TEST 8: read/%d %d sglists %d entries 0..%d bytes\n",
param->vary, param->iterations,
param->sglen, param->length);
- sg = alloc_sglist(param->sglen, param->length, param->vary);
+ sg = alloc_sglist(param->sglen, param->length,
+ param->vary, dev, dev->in_pipe);
if (!sg) {
retval = -ENOMEM;
break;
@@ -2325,7 +2366,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
param->iterations,
param->sglen, param->length);
/* FIRMWARE: iso sink */
- retval = test_iso_queue(dev, param,
+ retval = test_queue(dev, param,
dev->out_iso_pipe, dev->iso_out, 0);
break;
@@ -2338,7 +2379,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
param->iterations,
param->sglen, param->length);
/* FIRMWARE: iso source */
- retval = test_iso_queue(dev, param,
+ retval = test_queue(dev, param,
dev->in_iso_pipe, dev->iso_in, 0);
break;
@@ -2419,7 +2460,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
"TEST 22: write %d iso odd, %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
- retval = test_iso_queue(dev, param,
+ retval = test_queue(dev, param,
dev->out_iso_pipe, dev->iso_out, 1);
break;
@@ -2430,7 +2471,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
"TEST 23: read %d iso odd, %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
- retval = test_iso_queue(dev, param,
+ retval = test_queue(dev, param,
dev->in_iso_pipe, dev->iso_in, 1);
break;
@@ -2487,6 +2528,25 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
retval = simple_io(dev, urb, param->iterations, 0, 0, "test26");
simple_free_urb(urb);
break;
+ case 27:
+ /* We do performance test, so ignore data compare */
+ if (dev->out_pipe == 0 || param->sglen == 0 || pattern != 0)
+ break;
+ dev_info(&intf->dev,
+ "TEST 27: bulk write %dMbytes\n", (param->iterations *
+ param->sglen * param->length) / (1024 * 1024));
+ retval = test_queue(dev, param,
+ dev->out_pipe, NULL, 0);
+ break;
+ case 28:
+ if (dev->in_pipe == 0 || param->sglen == 0 || pattern != 0)
+ break;
+ dev_info(&intf->dev,
+ "TEST 28: bulk read %dMbytes\n", (param->iterations *
+ param->sglen * param->length) / (1024 * 1024));
+ retval = test_queue(dev, param,
+ dev->in_pipe, NULL, 0);
+ break;
}
do_gettimeofday(&param->duration);
param->duration.tv_sec -= start.tv_sec;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 4a518ff12310..18cfc0a361cb 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -132,7 +132,7 @@ static inline struct musb *dev_to_musb(struct device *dev)
/*-------------------------------------------------------------------------*/
#ifndef CONFIG_BLACKFIN
-static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
+static int musb_ulpi_read(struct usb_phy *phy, u32 reg)
{
void __iomem *addr = phy->io_priv;
int i = 0;
@@ -151,7 +151,7 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
* ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
*/
- musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
@@ -176,7 +176,7 @@ out:
return ret;
}
-static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
+static int musb_ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
{
void __iomem *addr = phy->io_priv;
int i = 0;
@@ -191,8 +191,8 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
power &= ~MUSB_POWER_SUSPENDM;
musb_writeb(addr, MUSB_POWER, power);
- musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
- musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
+ musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)val);
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
@@ -1028,18 +1028,22 @@ void musb_start(struct musb *musb)
{
void __iomem *regs = musb->mregs;
u8 devctl = musb_readb(regs, MUSB_DEVCTL);
+ u8 power;
dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
musb_enable_interrupts(musb);
musb_writeb(regs, MUSB_TESTMODE, 0);
- /* put into basic highspeed mode and start session */
- musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
- | MUSB_POWER_HSENAB
- /* ENSUSPEND wedges tusb */
- /* | MUSB_POWER_ENSUSPEND */
- );
+ power = MUSB_POWER_ISOUPDATE;
+ /*
+ * treating UNKNOWN as unspecified maximum speed, in which case
+ * we will default to high-speed.
+ */
+ if (musb->config->maximum_speed == USB_SPEED_HIGH ||
+ musb->config->maximum_speed == USB_SPEED_UNKNOWN)
+ power |= MUSB_POWER_HSENAB;
+ musb_writeb(regs, MUSB_POWER, power);
musb->is_active = 0;
devctl = musb_readb(regs, MUSB_DEVCTL);
@@ -1664,7 +1668,7 @@ EXPORT_SYMBOL_GPL(musb_interrupt);
static bool use_dma = 1;
/* "modprobe ... use_dma=0" etc */
-module_param(use_dma, bool, 0);
+module_param(use_dma, bool, 0644);
MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
@@ -1771,13 +1775,20 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
unsigned long flags;
unsigned long val;
int vbus;
+ u8 devctl;
spin_lock_irqsave(&musb->lock, flags);
val = musb->a_wait_bcon;
- /* FIXME get_vbus_status() is normally #defined as false...
- * and is effectively TUSB-specific.
- */
vbus = musb_platform_get_vbus_status(musb);
+ if (vbus < 0) {
+ /* Use default MUSB method by means of DEVCTL register */
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if ((devctl & MUSB_DEVCTL_VBUS)
+ == (3 << MUSB_DEVCTL_VBUS_SHIFT))
+ vbus = 1;
+ else
+ vbus = 0;
+ }
spin_unlock_irqrestore(&musb->lock, flags);
return sprintf(buf, "Vbus %s, timeout %lu msec\n",
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 4b886d0f6bdf..2337d7a7d62d 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -579,7 +579,7 @@ static inline int musb_platform_recover(struct musb *musb)
static inline int musb_platform_get_vbus_status(struct musb *musb)
{
if (!musb->ops->vbus_status)
- return 0;
+ return -EINVAL;
return musb->ops->vbus_status(musb);
}
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 84512d1d5eee..eeb7d9ecf7df 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -666,7 +666,7 @@ static int get_musb_port_mode(struct device *dev)
{
enum usb_dr_mode mode;
- mode = of_usb_get_dr_mode(dev->of_node);
+ mode = usb_get_dr_mode(dev);
switch (mode) {
case USB_DR_MODE_HOST:
return MUSB_PORT_MODE_HOST;
@@ -747,6 +747,19 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
if (!ret && val)
config->multipoint = true;
+ config->maximum_speed = usb_get_maximum_speed(&parent->dev);
+ switch (config->maximum_speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ break;
+ case USB_SPEED_SUPER:
+ dev_warn(dev, "ignore incorrect maximum_speed "
+ "(super-speed) setting in dts");
+ /* fall through */
+ default:
+ config->maximum_speed = USB_SPEED_HIGH;
+ }
+
ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
if (ret) {
dev_err(dev, "failed to add platform_data\n");
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 26c65e66cc0f..795a45b1b25b 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -112,22 +112,32 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
struct musb *musb = ep->musb;
void __iomem *epio = ep->regs;
u16 csr;
- u16 lastcsr = 0;
int retries = 1000;
csr = musb_readw(epio, MUSB_TXCSR);
while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
- if (csr != lastcsr)
- dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
- lastcsr = csr;
csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
musb_writew(epio, MUSB_TXCSR, csr);
csr = musb_readw(epio, MUSB_TXCSR);
- if (WARN(retries-- < 1,
+
+ /*
+ * FIXME: sometimes the tx fifo flush failed, it has been
+ * observed during device disconnect on AM335x.
+ *
+ * To reproduce the issue, ensure tx urb(s) are queued when
+ * unplug the usb device which is connected to AM335x usb
+ * host port.
+ *
+ * I found using a usb-ethernet device and running iperf
+ * (client on AM335x) has very high chance to trigger it.
+ *
+ * Better to turn on dev_dbg() in musb_cleanup_urb() with
+ * CPPI enabled to see the issue when aborting the tx channel.
+ */
+ if (dev_WARN_ONCE(musb->controller, retries-- < 1,
"Could not flush host TX%d fifo: csr: %04x\n",
ep->epnum, csr))
return;
- mdelay(1);
}
}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 70f2b8a2e6cf..1bd9232ff76f 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -391,9 +391,20 @@ static int omap2430_musb_init(struct musb *musb)
}
musb->isr = omap2430_musb_interrupt;
+ /*
+ * Enable runtime PM for musb parent (this driver). We can't
+ * do it earlier as struct musb is not yet allocated and we
+ * need to touch the musb registers for runtime PM.
+ */
+ pm_runtime_enable(glue->dev);
+ status = pm_runtime_get_sync(glue->dev);
+ if (status < 0)
+ goto err1;
+
status = pm_runtime_get_sync(dev);
if (status < 0) {
dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
+ pm_runtime_put_sync(glue->dev);
goto err1;
}
@@ -426,6 +437,7 @@ static int omap2430_musb_init(struct musb *musb)
phy_power_on(musb->phy);
pm_runtime_put_noidle(musb->controller);
+ pm_runtime_put_noidle(glue->dev);
return 0;
err1:
@@ -626,7 +638,11 @@ static int omap2430_probe(struct platform_device *pdev)
goto err2;
}
- pm_runtime_enable(&pdev->dev);
+ /*
+ * Note that we cannot enable PM runtime yet for this
+ * driver as we need struct musb initialized first.
+ * See omap2430_musb_init above.
+ */
ret = platform_device_add(musb);
if (ret) {
@@ -675,11 +691,12 @@ static int omap2430_runtime_resume(struct device *dev)
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- if (musb) {
- omap2430_low_level_init(musb);
- musb_writel(musb->mregs, OTG_INTERFSEL,
- musb->context.otg_interfsel);
- }
+ if (!musb)
+ return -EPROBE_DEFER;
+
+ omap2430_low_level_init(musb);
+ musb_writel(musb->mregs, OTG_INTERFSEL,
+ musb->context.otg_interfsel);
return 0;
}
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index f9f6304ad854..d9b0dc461439 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -341,6 +341,16 @@ static void sunxi_musb_disable(struct musb *musb)
clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
}
+struct dma_controller *sunxi_musb_dma_controller_create(struct musb *musb,
+ void __iomem *base)
+{
+ return NULL;
+}
+
+void sunxi_musb_dma_controller_destroy(struct dma_controller *c)
+{
+}
+
/*
* sunxi musb register layout
* 0x00 - 0x17 fifo regs, 1 long per fifo
@@ -566,6 +576,8 @@ static const struct musb_platform_ops sunxi_musb_ops = {
.writeb = sunxi_musb_writeb,
.readw = sunxi_musb_readw,
.writew = sunxi_musb_writew,
+ .dma_init = sunxi_musb_dma_controller_create,
+ .dma_exit = sunxi_musb_dma_controller_destroy,
.set_vbus = sunxi_musb_set_vbus,
.pre_root_reset_end = sunxi_musb_pre_root_reset_end,
.post_root_reset_end = sunxi_musb_post_root_reset_end,
@@ -617,7 +629,7 @@ static int sunxi_musb_probe(struct platform_device *pdev)
return -ENOMEM;
memset(&pdata, 0, sizeof(pdata));
- switch (of_usb_get_dr_mode(np)) {
+ switch (usb_get_dr_mode(&pdev->dev)) {
#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
case USB_DR_MODE_HOST:
pdata.mode = MUSB_PORT_MODE_HOST;
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 173132416170..22e8ecb6bfbd 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -21,7 +21,6 @@ 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
- select USB_OTG
select USB_PHY
help
Enable this to support Freescale USB OTG transceiver.
@@ -168,8 +167,7 @@ config USB_QCOM_8X16_PHY
config USB_MV_OTG
tristate "Marvell USB OTG support"
- depends on USB_EHCI_MV && USB_MV_UDC && PM
- select USB_OTG
+ depends on USB_EHCI_MV && USB_MV_UDC && PM && USB_OTG
select USB_PHY
help
Say Y here if you want to build Marvell USB OTG transciever
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index c58c3c0dbe35..80eb991c2506 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1529,7 +1529,7 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
if (IS_ERR(motg->phy_rst))
motg->phy_rst = NULL;
- pdata->mode = of_usb_get_dr_mode(node);
+ pdata->mode = usb_get_dr_mode(&pdev->dev);
if (pdata->mode == USB_DR_MODE_UNKNOWN)
pdata->mode = USB_DR_MODE_OTG;
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 4d863ebc117c..b7536af777ab 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -452,10 +452,13 @@ static int mxs_phy_probe(struct platform_device *pdev)
struct clk *clk;
struct mxs_phy *mxs_phy;
int ret;
- const struct of_device_id *of_id =
- of_match_device(mxs_phy_dt_ids, &pdev->dev);
+ const struct of_device_id *of_id;
struct device_node *np = pdev->dev.of_node;
+ of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
+ if (!of_id)
+ return -ENODEV;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c
index 1270906ccb95..c4bf2de6d14e 100644
--- a/drivers/usb/phy/phy-omap-otg.c
+++ b/drivers/usb/phy/phy-omap-otg.c
@@ -105,7 +105,6 @@ static int omap_otg_probe(struct platform_device *pdev)
extcon = extcon_get_extcon_dev(config->extcon);
if (!extcon)
return -EPROBE_DEFER;
- otg_dev->extcon = extcon;
otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
if (!otg_dev)
@@ -115,6 +114,7 @@ static int omap_otg_probe(struct platform_device *pdev)
if (IS_ERR(otg_dev->base))
return PTR_ERR(otg_dev->base);
+ otg_dev->extcon = extcon;
otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;
diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c
index 5d357a94599e..579587d97217 100644
--- a/drivers/usb/phy/phy-qcom-8x16-usb.c
+++ b/drivers/usb/phy/phy-qcom-8x16-usb.c
@@ -71,7 +71,7 @@ struct phy_8x16 {
struct reset_control *phy_reset;
- struct extcon_specific_cable_nb vbus_cable;
+ struct extcon_dev *vbus_edev;
struct notifier_block vbus_notify;
struct gpio_desc *switch_gpio;
@@ -234,7 +234,7 @@ static int phy_8x16_init(struct usb_phy *phy)
val = ULPI_PWR_OTG_COMP_DISABLE;
usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG));
- state = extcon_get_cable_state(qphy->vbus_cable.edev, "USB");
+ state = extcon_get_cable_state_(qphy->vbus_edev, EXTCON_USB);
if (state)
phy_8x16_vbus_on(qphy);
else
@@ -314,7 +314,6 @@ static int phy_8x16_reboot_notify(struct notifier_block *this,
static int phy_8x16_probe(struct platform_device *pdev)
{
- struct extcon_dev *edev;
struct phy_8x16 *qphy;
struct resource *res;
struct usb_phy *phy;
@@ -349,9 +348,9 @@ static int phy_8x16_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- edev = extcon_get_edev_by_phandle(phy->dev, 0);
- if (IS_ERR(edev))
- return PTR_ERR(edev);
+ qphy->vbus_edev = extcon_get_edev_by_phandle(phy->dev, 0);
+ if (IS_ERR(qphy->vbus_edev))
+ return PTR_ERR(qphy->vbus_edev);
ret = clk_set_rate(qphy->core_clk, INT_MAX);
if (ret < 0)
@@ -370,8 +369,8 @@ static int phy_8x16_probe(struct platform_device *pdev)
goto off_clks;
qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
- ret = extcon_register_interest(&qphy->vbus_cable, edev->name,
- "USB", &qphy->vbus_notify);
+ ret = extcon_register_notifier(qphy->vbus_edev, EXTCON_USB,
+ &qphy->vbus_notify);
if (ret < 0)
goto off_power;
@@ -385,7 +384,8 @@ static int phy_8x16_probe(struct platform_device *pdev)
return 0;
off_extcon:
- extcon_unregister_interest(&qphy->vbus_cable);
+ extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB,
+ &qphy->vbus_notify);
off_power:
phy_8x16_regulators_disable(qphy);
off_clks:
@@ -400,7 +400,8 @@ static int phy_8x16_remove(struct platform_device *pdev)
struct phy_8x16 *qphy = platform_get_drvdata(pdev);
unregister_reboot_notifier(&qphy->reboot_notify);
- extcon_unregister_interest(&qphy->vbus_cable);
+ extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB,
+ &qphy->vbus_notify);
/*
* Ensure that D+/D- lines are routed to uB connector, so
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index ab025b00964c..5fe4a5704bde 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1029,7 +1029,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
}
if (of_find_property(np, "dr_mode", NULL))
- tegra_phy->mode = of_usb_get_dr_mode(np);
+ tegra_phy->mode = usb_get_dr_mode(&pdev->dev);
else
tegra_phy->mode = USB_DR_MODE_HOST;
diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c
index 8fc15c0ba339..277160bc6f25 100644
--- a/drivers/usb/renesas_usbhs/rcar2.c
+++ b/drivers/usb/renesas_usbhs/rcar2.c
@@ -13,7 +13,6 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/phy/phy.h>
-#include <linux/platform_data/gpio-rcar.h>
#include <linux/usb/phy.h>
#include "common.h"
#include "rcar2.h"
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 0ac1b10be1f7..fce82fd79f77 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -54,8 +54,10 @@
#define TI_MODE_CONFIGURING 0 /* Device has not entered start device */
#define TI_MODE_BOOT 1 /* Staying in boot mode */
#define TI_MODE_DOWNLOAD 2 /* Made it to download mode */
-#define TI_MODE_TRANSITIONING 3 /* Currently in boot mode but
- transitioning to download mode */
+#define TI_MODE_TRANSITIONING 3 /*
+ * Currently in boot mode but
+ * transitioning to download mode
+ */
/* read urb state */
#define EDGE_READ_URB_RUNNING 0
@@ -97,9 +99,11 @@ struct edgeport_port {
__u8 shadow_mcr;
__u8 shadow_lsr;
__u8 lsr_mask;
- __u32 ump_read_timeout; /* Number of milliseconds the UMP will
- wait without data before completing
- a read short */
+ __u32 ump_read_timeout; /*
+ * Number of milliseconds the UMP will
+ * wait without data before completing
+ * a read short
+ */
int baud_rate;
int close_pending;
int lsr_event;
@@ -115,8 +119,10 @@ struct edgeport_port {
struct edgeport_serial {
struct product_info product_info;
u8 TI_I2C_Type; /* Type of I2C in UMP */
- u8 TiReadI2C; /* Set to TRUE if we have read the
- I2c in Boot Mode */
+ u8 TiReadI2C; /*
+ * Set to TRUE if we have read the
+ * I2c in Boot Mode
+ */
struct mutex es_lock;
int num_ports_open;
struct usb_serial *serial;
@@ -223,6 +229,11 @@ static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
+static int do_download_mode(struct edgeport_serial *serial,
+ const struct firmware *fw);
+static int do_boot_mode(struct edgeport_serial *serial,
+ const struct firmware *fw);
+
/* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
@@ -324,7 +335,8 @@ static int read_download_mem(struct usb_device *dev, int start_address,
dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
- /* Read in blocks of 64 bytes
+ /*
+ * Read in blocks of 64 bytes
* (TI firmware can't handle more than 64 byte reads)
*/
while (length) {
@@ -430,7 +442,6 @@ static int write_boot_mem(struct edgeport_serial *serial,
return status;
}
-
/* Write edgeport I2C memory to TI chip */
static int write_i2c_mem(struct edgeport_serial *serial,
int start_address, int length, __u8 address_type, __u8 *buffer)
@@ -472,8 +483,10 @@ static int write_i2c_mem(struct edgeport_serial *serial,
start_address += write_length;
buffer += write_length;
- /* We should be aligned now -- can write
- max page size bytes at a time */
+ /*
+ * We should be aligned now -- can write max page size bytes at a
+ * time.
+ */
while (length) {
if (length > EPROM_PAGE_SIZE)
write_length = EPROM_PAGE_SIZE;
@@ -506,7 +519,8 @@ static int write_i2c_mem(struct edgeport_serial *serial,
return status;
}
-/* Examine the UMP DMA registers and LSR
+/*
+ * Examine the UMP DMA registers and LSR
*
* Check the MSBit of the X and Y DMA byte count registers.
* A zero in this bit indicates that the TX DMA buffers are empty
@@ -523,9 +537,11 @@ static int tx_active(struct edgeport_port *port)
if (!oedb)
return -ENOMEM;
- lsr = kmalloc(1, GFP_KERNEL); /* Sigh, that's right, just one byte,
- as not all platforms can do DMA
- from stack */
+ /*
+ * Sigh, that's right, just one byte, as not all platforms can
+ * do DMA from stack
+ */
+ lsr = kmalloc(1, GFP_KERNEL);
if (!lsr) {
kfree(oedb);
return -ENOMEM;
@@ -615,8 +631,6 @@ static int write_rom(struct edgeport_serial *serial, int start_address,
return -EINVAL;
}
-
-
/* Read a descriptor header from I2C based on type */
static int get_descriptor_addr(struct edgeport_serial *serial,
int desc_type, struct ti_i2c_desc *rom_desc)
@@ -785,8 +799,7 @@ exit:
}
/* Build firmware header used for firmware update */
-static int build_i2c_fw_hdr(u8 *header, struct device *dev,
- const struct firmware *fw)
+static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
{
__u8 *buffer;
int buffer_size;
@@ -797,7 +810,8 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
struct ti_i2c_firmware_rec *firmware_rec;
struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
- /* In order to update the I2C firmware we must change the type 2 record
+ /*
+ * In order to update the I2C firmware we must change the type 2 record
* to type 0xF2. This will force the UMP to come up in Boot Mode.
* Then while in boot mode, the driver will download the latest
* firmware (padded to 15.5k) into the UMP ram. And finally when the
@@ -806,8 +820,10 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
* update the record type from 0xf2 to 0x02.
*/
- /* Allocate a 15.5k buffer + 2 bytes for version number
- * (Firmware Record) */
+ /*
+ * Allocate a 15.5k buffer + 2 bytes for version number (Firmware
+ * Record)
+ */
buffer_size = (((1024 * 16) - 512 ) +
sizeof(struct ti_i2c_firmware_rec));
@@ -815,7 +831,7 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
if (!buffer)
return -ENOMEM;
- // Set entire image of 0xffs
+ /* Set entire image of 0xffs */
memset(buffer, 0xff, buffer_size);
/* Copy version number into firmware record */
@@ -981,32 +997,41 @@ static int check_fw_sanity(struct edgeport_serial *serial,
return 0;
}
-/**
+/*
* DownloadTIFirmware - Download run-time operating firmware to the TI5052
*
* This routine downloads the main operating code into the TI5052, using the
* boot code already burned into E2PROM or ROM.
*/
-static int download_fw(struct edgeport_serial *serial,
- const struct firmware *fw)
+static int download_fw(struct edgeport_serial *serial)
{
- struct device *dev = &serial->serial->dev->dev;
+ struct device *dev = &serial->serial->interface->dev;
int status = 0;
- int start_address;
- struct edge_ti_manuf_descriptor *ti_manuf_desc;
struct usb_interface_descriptor *interface;
- int download_cur_ver;
- int download_new_ver;
- struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+ const struct firmware *fw;
+ const char *fw_name = "edgeport/down3.bin";
+ struct edgeport_fw_hdr *fw_hdr;
- if (check_fw_sanity(serial, fw))
- return -EINVAL;
+ status = request_firmware(&fw, fw_name, dev);
+ if (status) {
+ dev_err(dev, "Failed to load image \"%s\" err %d\n",
+ fw_name, status);
+ return status;
+ }
+
+ if (check_fw_sanity(serial, fw)) {
+ status = -EINVAL;
+ goto out;
+ }
- /* If on-board version is newer, "fw_version" will be updated below. */
+ fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+ /* If on-board version is newer, "fw_version" will be updated later. */
serial->fw_version = (fw_hdr->major_version << 8) +
fw_hdr->minor_version;
- /* This routine is entered by both the BOOT mode and the Download mode
+ /*
+ * This routine is entered by both the BOOT mode and the Download mode
* We can determine which code is running by the reading the config
* descriptor and if we have only one bulk pipe it is in boot mode
*/
@@ -1017,12 +1042,13 @@ static int download_fw(struct edgeport_serial *serial,
status = choose_config(serial->serial->dev);
if (status)
- return status;
+ goto out;
interface = &serial->serial->interface->cur_altsetting->desc;
if (!interface) {
dev_err(dev, "%s - no interface set, error!\n", __func__);
- return -ENODEV;
+ status = -ENODEV;
+ goto out;
}
/*
@@ -1030,190 +1056,219 @@ static int download_fw(struct edgeport_serial *serial,
* if we have more than one endpoint we are definitely in download
* mode
*/
- if (interface->bNumEndpoints > 1)
+ if (interface->bNumEndpoints > 1) {
serial->product_info.TiMode = TI_MODE_DOWNLOAD;
- else
+ status = do_download_mode(serial, fw);
+ } else {
/* Otherwise we will remain in configuring mode */
serial->product_info.TiMode = TI_MODE_CONFIGURING;
+ status = do_boot_mode(serial, fw);
+ }
- /********************************************************************/
- /* Download Mode */
- /********************************************************************/
- if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
- struct ti_i2c_desc *rom_desc;
+out:
+ release_firmware(fw);
+ return status;
+}
- dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
+static int do_download_mode(struct edgeport_serial *serial,
+ const struct firmware *fw)
+{
+ struct device *dev = &serial->serial->interface->dev;
+ int status = 0;
+ int start_address;
+ struct edge_ti_manuf_descriptor *ti_manuf_desc;
+ int download_cur_ver;
+ int download_new_ver;
+ struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+ struct ti_i2c_desc *rom_desc;
- status = check_i2c_image(serial);
- if (status) {
- dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
- return status;
- }
+ dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
- /* Validate Hardware version number
- * Read Manufacturing Descriptor from TI Based Edgeport
- */
- ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
- if (!ti_manuf_desc)
+ status = check_i2c_image(serial);
+ if (status) {
+ dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
+ return status;
+ }
+
+ /*
+ * Validate Hardware version number
+ * Read Manufacturing Descriptor from TI Based Edgeport
+ */
+ ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
+ if (!ti_manuf_desc)
+ return -ENOMEM;
+
+ status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
+ if (status) {
+ kfree(ti_manuf_desc);
+ return status;
+ }
+
+ /* Check version number of ION descriptor */
+ if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+ dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
+ __func__, ti_cpu_rev(ti_manuf_desc));
+ kfree(ti_manuf_desc);
+ return -EINVAL;
+ }
+
+ rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+ kfree(ti_manuf_desc);
+ return -ENOMEM;
+ }
+
+ /* Search for type 2 record (firmware record) */
+ start_address = get_descriptor_addr(serial,
+ I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
+ if (start_address != 0) {
+ struct ti_i2c_firmware_rec *firmware_version;
+ u8 *record;
+
+ dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n",
+ __func__);
+
+ firmware_version = kmalloc(sizeof(*firmware_version),
+ GFP_KERNEL);
+ if (!firmware_version) {
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return -ENOMEM;
+ }
- status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
+ /*
+ * Validate version number
+ * Read the descriptor data
+ */
+ status = read_rom(serial, start_address +
+ sizeof(struct ti_i2c_desc),
+ sizeof(struct ti_i2c_firmware_rec),
+ (__u8 *)firmware_version);
if (status) {
+ kfree(firmware_version);
+ kfree(rom_desc);
kfree(ti_manuf_desc);
return status;
}
- /* Check version number of ION descriptor */
- if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
- dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
- __func__, ti_cpu_rev(ti_manuf_desc));
- kfree(ti_manuf_desc);
- return -EINVAL;
- }
+ /*
+ * Check version number of download with current
+ * version in I2c
+ */
+ download_cur_ver = (firmware_version->Ver_Major << 8) +
+ (firmware_version->Ver_Minor);
+ download_new_ver = (fw_hdr->major_version << 8) +
+ (fw_hdr->minor_version);
- rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
- if (!rom_desc) {
- kfree(ti_manuf_desc);
- return -ENOMEM;
- }
+ dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n",
+ __func__, firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ fw_hdr->major_version, fw_hdr->minor_version);
- /* Search for type 2 record (firmware record) */
- start_address = get_descriptor_addr(serial,
- I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
- if (start_address != 0) {
- struct ti_i2c_firmware_rec *firmware_version;
- u8 *record;
-
- dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__);
+ /*
+ * Check if we have an old version in the I2C and
+ * update if necessary
+ */
+ if (download_cur_ver < download_new_ver) {
+ dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
+ __func__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ fw_hdr->major_version,
+ fw_hdr->minor_version);
- firmware_version = kmalloc(sizeof(*firmware_version),
- GFP_KERNEL);
- if (!firmware_version) {
+ record = kmalloc(1, GFP_KERNEL);
+ if (!record) {
+ kfree(firmware_version);
kfree(rom_desc);
kfree(ti_manuf_desc);
return -ENOMEM;
}
+ /*
+ * In order to update the I2C firmware we must
+ * change the type 2 record to type 0xF2. This
+ * will force the UMP to come up in Boot Mode.
+ * Then while in boot mode, the driver will
+ * download the latest firmware (padded to
+ * 15.5k) into the UMP ram. Finally when the
+ * device comes back up in download mode the
+ * driver will cause the new firmware to be
+ * copied from the UMP Ram to I2C and the
+ * firmware will update the record type from
+ * 0xf2 to 0x02.
+ */
+ *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
- /* Validate version number
- * Read the descriptor data
+ /*
+ * Change the I2C Firmware record type to
+ * 0xf2 to trigger an update
*/
- status = read_rom(serial, start_address +
- sizeof(struct ti_i2c_desc),
- sizeof(struct ti_i2c_firmware_rec),
- (__u8 *)firmware_version);
+ status = write_rom(serial, start_address,
+ sizeof(*record), record);
if (status) {
+ kfree(record);
kfree(firmware_version);
kfree(rom_desc);
kfree(ti_manuf_desc);
return status;
}
- /* Check version number of download with current
- version in I2c */
- download_cur_ver = (firmware_version->Ver_Major << 8) +
- (firmware_version->Ver_Minor);
- download_new_ver = (fw_hdr->major_version << 8) +
- (fw_hdr->minor_version);
-
- dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n",
- __func__, firmware_version->Ver_Major,
- firmware_version->Ver_Minor,
- fw_hdr->major_version, fw_hdr->minor_version);
+ /*
+ * verify the write -- must do this in order
+ * for write to complete before we do the
+ * hardware reset
+ */
+ status = read_rom(serial,
+ start_address,
+ sizeof(*record),
+ record);
+ if (status) {
+ kfree(record);
+ kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
+ return status;
+ }
- /* Check if we have an old version in the I2C and
- update if necessary */
- if (download_cur_ver < download_new_ver) {
- dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
- __func__,
- firmware_version->Ver_Major,
- firmware_version->Ver_Minor,
- fw_hdr->major_version,
- fw_hdr->minor_version);
-
- record = kmalloc(1, GFP_KERNEL);
- if (!record) {
- kfree(firmware_version);
- kfree(rom_desc);
- kfree(ti_manuf_desc);
- return -ENOMEM;
- }
- /* In order to update the I2C firmware we must
- * change the type 2 record to type 0xF2. This
- * will force the UMP to come up in Boot Mode.
- * Then while in boot mode, the driver will
- * download the latest firmware (padded to
- * 15.5k) into the UMP ram. Finally when the
- * device comes back up in download mode the
- * driver will cause the new firmware to be
- * copied from the UMP Ram to I2C and the
- * firmware will update the record type from
- * 0xf2 to 0x02.
- */
- *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
-
- /* Change the I2C Firmware record type to
- 0xf2 to trigger an update */
- status = write_rom(serial, start_address,
- sizeof(*record), record);
- if (status) {
- kfree(record);
- kfree(firmware_version);
- kfree(rom_desc);
- kfree(ti_manuf_desc);
- return status;
- }
-
- /* verify the write -- must do this in order
- * for write to complete before we do the
- * hardware reset
- */
- status = read_rom(serial,
- start_address,
- sizeof(*record),
- record);
- if (status) {
- kfree(record);
- kfree(firmware_version);
- kfree(rom_desc);
- kfree(ti_manuf_desc);
- return status;
- }
-
- if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
- dev_err(dev, "%s - error resetting device\n", __func__);
- kfree(record);
- kfree(firmware_version);
- kfree(rom_desc);
- kfree(ti_manuf_desc);
- return -ENODEV;
- }
-
- dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
-
- /* Reset UMP -- Back to BOOT MODE */
- status = ti_vsend_sync(serial->serial->dev,
- UMPC_HARDWARE_RESET,
- 0, 0, NULL, 0,
- TI_VSEND_TIMEOUT_DEFAULT);
-
- dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
-
- /* return an error on purpose. */
+ if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+ dev_err(dev, "%s - error resetting device\n",
+ __func__);
kfree(record);
kfree(firmware_version);
kfree(rom_desc);
kfree(ti_manuf_desc);
return -ENODEV;
- } else {
- /* Same or newer fw version is already loaded */
- serial->fw_version = download_cur_ver;
}
+
+ dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
+
+ /* Reset UMP -- Back to BOOT MODE */
+ status = ti_vsend_sync(serial->serial->dev,
+ UMPC_HARDWARE_RESET,
+ 0, 0, NULL, 0,
+ TI_VSEND_TIMEOUT_DEFAULT);
+
+ dev_dbg(dev, "%s - HARDWARE RESET return %d\n",
+ __func__, status);
+
+ /* return an error on purpose. */
+ kfree(record);
kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
+ return -ENODEV;
}
- /* Search for type 0xF2 record (firmware blank record) */
- else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
+ /* Same or newer fw version is already loaded */
+ serial->fw_version = download_cur_ver;
+ kfree(firmware_version);
+ }
+ /* Search for type 0xF2 record (firmware blank record) */
+ else {
+ start_address = get_descriptor_addr(serial,
+ I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc);
+ if (start_address != 0) {
#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \
- sizeof(struct ti_i2c_firmware_rec))
+ sizeof(struct ti_i2c_firmware_rec))
__u8 *header;
__u8 *vheader;
@@ -1232,7 +1287,8 @@ static int download_fw(struct edgeport_serial *serial,
return -ENOMEM;
}
- dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__);
+ dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n",
+ __func__);
/*
* In order to update the I2C firmware we must change
@@ -1245,7 +1301,7 @@ static int download_fw(struct edgeport_serial *serial,
* UMP Ram to I2C and the firmware will update the
* record type from 0xf2 to 0x02.
*/
- status = build_i2c_fw_hdr(header, dev, fw);
+ status = build_i2c_fw_hdr(header, fw);
if (status) {
kfree(vheader);
kfree(header);
@@ -1254,8 +1310,10 @@ static int download_fw(struct edgeport_serial *serial,
return -EINVAL;
}
- /* Update I2C with type 0xf2 record with correct
- size and checksum */
+ /*
+ * Update I2C with type 0xf2 record with correct
+ * size and checksum
+ */
status = write_rom(serial,
start_address,
HEADER_SIZE,
@@ -1268,13 +1326,16 @@ static int download_fw(struct edgeport_serial *serial,
return -EINVAL;
}
- /* verify the write -- must do this in order for
- write to complete before we do the hardware reset */
+ /*
+ * verify the write -- must do this in order for
+ * write to complete before we do the hardware reset
+ */
status = read_rom(serial, start_address,
HEADER_SIZE, vheader);
if (status) {
- dev_dbg(dev, "%s - can't read header back\n", __func__);
+ dev_dbg(dev, "%s - can't read header back\n",
+ __func__);
kfree(vheader);
kfree(header);
kfree(rom_desc);
@@ -1282,7 +1343,8 @@ static int download_fw(struct edgeport_serial *serial,
return status;
}
if (memcmp(vheader, header, HEADER_SIZE)) {
- dev_dbg(dev, "%s - write download record failed\n", __func__);
+ dev_dbg(dev, "%s - write download record failed\n",
+ __func__);
kfree(vheader);
kfree(header);
kfree(rom_desc);
@@ -1301,26 +1363,33 @@ static int download_fw(struct edgeport_serial *serial,
0, 0, NULL, 0,
TI_VSEND_TIMEOUT_FW_DOWNLOAD);
- dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status);
+ dev_dbg(dev, "%s - Update complete 0x%x\n", __func__,
+ status);
if (status) {
dev_err(dev,
"%s - UMPC_COPY_DNLD_TO_I2C failed\n",
- __func__);
+ __func__);
kfree(rom_desc);
kfree(ti_manuf_desc);
return status;
}
}
-
- // The device is running the download code
- kfree(rom_desc);
- kfree(ti_manuf_desc);
- return 0;
}
- /********************************************************************/
- /* Boot Mode */
- /********************************************************************/
+ /* The device is running the download code */
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
+ return 0;
+}
+
+static int do_boot_mode(struct edgeport_serial *serial,
+ const struct firmware *fw)
+{
+ struct device *dev = &serial->serial->interface->dev;
+ int status = 0;
+ struct edge_ti_manuf_descriptor *ti_manuf_desc;
+ struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__);
/* Configure the TI device so we can use the BULK pipes for download */
@@ -1336,8 +1405,10 @@ static int download_fw(struct edgeport_serial *serial,
goto stayinbootmode;
}
- /* We have an ION device (I2c Must be programmed)
- Determine I2C image type */
+ /*
+ * We have an ION device (I2c Must be programmed)
+ * Determine I2C image type
+ */
if (i2c_type_bootmode(serial))
goto stayinbootmode;
@@ -1349,7 +1420,8 @@ static int download_fw(struct edgeport_serial *serial,
__u8 *buffer;
int buffer_size;
- /* Validate Hardware version number
+ /*
+ * Validate Hardware version number
* Read Manufacturing Descriptor from TI Based Edgeport
*/
ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
@@ -1439,7 +1511,6 @@ stayinbootmode:
return 0;
}
-
static int ti_do_config(struct edgeport_port *port, int feature, int on)
{
int port_number = port->port->port_number;
@@ -1450,7 +1521,6 @@ static int ti_do_config(struct edgeport_port *port, int feature, int on)
on, NULL, 0);
}
-
static int restore_mcr(struct edgeport_port *port, __u8 mcr)
{
int status = 0;
@@ -1556,7 +1626,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
icount->frame++;
}
-
static void edge_interrupt_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
@@ -1616,8 +1685,9 @@ static void edge_interrupt_callback(struct urb *urb)
case TIUMP_INTERRUPT_CODE_LSR:
lsr = map_line_status(data[1]);
if (lsr & UMP_UART_LSR_DATA_MASK) {
- /* Save the LSR event for bulk read
- completion routine */
+ /*
+ * Save the LSR event for bulk read completion routine
+ */
dev_dbg(dev, "%s - LSR Event Port %u LSR Status = %02x\n",
__func__, port_number, lsr);
edge_port->lsr_event = 1;
@@ -1925,8 +1995,10 @@ static void edge_close(struct usb_serial_port *port)
if (edge_serial == NULL || edge_port == NULL)
return;
- /* The bulkreadcompletion routine will check
- * this flag and dump add read data */
+ /*
+ * The bulkreadcompletion routine will check
+ * this flag and dump add read data
+ */
edge_port->close_pending = 1;
usb_kill_urb(port->read_urb);
@@ -2016,8 +2088,10 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
} else
edge_port->port->icount.tx += count;
- /* wakeup any process waiting for writes to complete */
- /* there is now more room in the buffer for new writes */
+ /*
+ * wakeup any process waiting for writes to complete
+ * there is now more room in the buffer for new writes
+ */
if (tty)
tty_wakeup(tty);
}
@@ -2089,8 +2163,10 @@ static void edge_throttle(struct tty_struct *tty)
}
}
- /* if we are implementing RTS/CTS, stop reads */
- /* and the Edgeport will clear the RTS line */
+ /*
+ * if we are implementing RTS/CTS, stop reads
+ * and the Edgeport will clear the RTS line
+ */
if (C_CRTSCTS(tty))
stop_read(edge_port);
@@ -2113,8 +2189,10 @@ static void edge_unthrottle(struct tty_struct *tty)
dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
}
}
- /* if we are implementing RTS/CTS, restart reads */
- /* are the Edgeport will assert the RTS line */
+ /*
+ * if we are implementing RTS/CTS, restart reads
+ * are the Edgeport will assert the RTS line
+ */
if (C_CRTSCTS(tty)) {
status = restart_read(edge_port);
if (status)
@@ -2236,8 +2314,10 @@ static void change_port_settings(struct tty_struct *tty,
restart_read(edge_port);
}
- /* if we are implementing XON/XOFF, set the start and stop
- character in the device */
+ /*
+ * if we are implementing XON/XOFF, set the start and stop
+ * character in the device
+ */
config->cXon = START_CHAR(tty);
config->cXoff = STOP_CHAR(tty);
@@ -2467,9 +2547,6 @@ static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
int status;
- const struct firmware *fw;
- const char *fw_name = "edgeport/down3.bin";
- struct device *dev = &serial->interface->dev;
u16 product_id;
/* create our private serial structure */
@@ -2481,16 +2558,7 @@ static int edge_startup(struct usb_serial *serial)
edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial);
- status = request_firmware(&fw, fw_name, dev);
- if (status) {
- dev_err(dev, "Failed to load image \"%s\" err %d\n",
- fw_name, status);
- kfree(edge_serial);
- return status;
- }
-
- status = download_fw(edge_serial, fw);
- release_firmware(fw);
+ status = download_fw(edge_serial);
if (status) {
kfree(edge_serial);
return status;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 6956c4f62216..f2280606b73c 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -48,7 +48,6 @@ static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id);
static int option_attach(struct usb_serial *serial);
static void option_release(struct usb_serial *serial);
-static int option_send_setup(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb);
/* Vendor and product IDs */
@@ -162,6 +161,7 @@ static void option_instat_callback(struct urb *urb);
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
#define NOVATELWIRELESS_PRODUCT_E362 0x9010
#define NOVATELWIRELESS_PRODUCT_E371 0x9011
+#define NOVATELWIRELESS_PRODUCT_U620L 0x9022
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
#define NOVATELWIRELESS_PRODUCT_MC551 0xB001
@@ -234,8 +234,6 @@ static void option_instat_callback(struct urb *urb);
#define QUALCOMM_VENDOR_ID 0x05C6
-#define SIERRA_VENDOR_ID 0x1199
-
#define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6001 0x6001
#define CMOTECH_PRODUCT_CMU_300 0x6002
@@ -357,6 +355,7 @@ static void option_instat_callback(struct urb *urb);
/* This is the 4G XS Stick W14 a.k.a. Mobilcom Debitel Surf-Stick *
* It seems to contain a Qualcomm QSC6240/6290 chipset */
#define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603
+#define FOUR_G_SYSTEMS_PRODUCT_W100 0x9b01
/* iBall 3.5G connect wireless modem */
#define IBALL_3_5G_CONNECT 0x9605
@@ -522,6 +521,11 @@ static const struct option_blacklist_info four_g_w14_blacklist = {
.sendsetup = BIT(0) | BIT(1),
};
+static const struct option_blacklist_info four_g_w100_blacklist = {
+ .sendsetup = BIT(1) | BIT(2),
+ .reserved = BIT(3),
+};
+
static const struct option_blacklist_info alcatel_x200_blacklist = {
.sendsetup = BIT(0) | BIT(1),
.reserved = BIT(4),
@@ -611,11 +615,6 @@ static const struct option_blacklist_info telit_le920_blacklist = {
.reserved = BIT(1) | BIT(5),
};
-static const struct option_blacklist_info sierra_mc73xx_blacklist = {
- .sendsetup = BIT(0) | BIT(2),
- .reserved = BIT(8) | BIT(10) | BIT(11),
-};
-
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1060,6 +1059,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U620L, 0xff, 0x00, 0x00) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -1113,10 +1113,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
- { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff),
- .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */
- { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x9041, 0xff),
- .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC7305/MC7355 */
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1653,6 +1649,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
.driver_info = (kernel_ulong_t)&four_g_w14_blacklist
},
+ { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W100),
+ .driver_info = (kernel_ulong_t)&four_g_w100_blacklist
+ },
{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
@@ -1835,10 +1834,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
&option_1port_device, NULL
};
-struct option_private {
- u8 bInterfaceNumber;
-};
-
module_usb_serial_driver(serial_drivers, option_ids);
static int option_probe(struct usb_serial *serial,
@@ -1882,29 +1877,19 @@ static int option_attach(struct usb_serial *serial)
struct usb_interface_descriptor *iface_desc;
const struct option_blacklist_info *blacklist;
struct usb_wwan_intf_private *data;
- struct option_private *priv;
data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
if (!data)
return -ENOMEM;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- kfree(data);
- return -ENOMEM;
- }
-
/* Retrieve blacklist info stored at probe. */
blacklist = usb_get_serial_data(serial);
iface_desc = &serial->interface->cur_altsetting->desc;
- priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
- data->private = priv;
-
if (!blacklist || !test_bit(iface_desc->bInterfaceNumber,
&blacklist->sendsetup)) {
- data->send_setup = option_send_setup;
+ data->use_send_setup = 1;
}
spin_lock_init(&data->susp_lock);
@@ -1916,9 +1901,7 @@ static int option_attach(struct usb_serial *serial)
static void option_release(struct usb_serial *serial)
{
struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
- struct option_private *priv = intfdata->private;
- kfree(priv);
kfree(intfdata);
}
@@ -1977,40 +1960,6 @@ static void option_instat_callback(struct urb *urb)
}
}
-/** send RTS/DTR state to the port.
- *
- * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
- * CDC.
-*/
-static int option_send_setup(struct usb_serial_port *port)
-{
- struct usb_serial *serial = port->serial;
- struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
- struct option_private *priv = intfdata->private;
- struct usb_wwan_port_private *portdata;
- int val = 0;
- int res;
-
- portdata = usb_get_serial_port_data(port);
-
- if (portdata->dtr_state)
- val |= 0x01;
- if (portdata->rts_state)
- val |= 0x02;
-
- res = usb_autopm_get_interface(serial->interface);
- if (res)
- return res;
-
- res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, priv->bInterfaceNumber, NULL,
- 0, USB_CTRL_SET_TIMEOUT);
-
- usb_autopm_put_interface(serial->interface);
-
- return res;
-}
-
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index ebcec8cda858..9919d2a9faf2 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -22,6 +22,8 @@
#define DRIVER_AUTHOR "Qualcomm Inc"
#define DRIVER_DESC "Qualcomm USB Serial driver"
+#define QUECTEL_EC20_PID 0x9215
+
/* standard device layouts supported by this driver */
enum qcserial_layouts {
QCSERIAL_G2K = 0, /* Gobi 2000 */
@@ -143,9 +145,11 @@ static const struct usb_device_id id_table[] = {
{DEVICE_SWI(0x0f3d, 0x68a2)}, /* Sierra Wireless MC7700 */
{DEVICE_SWI(0x114f, 0x68a2)}, /* Sierra Wireless MC7750 */
{DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */
+ {DEVICE_SWI(0x1199, 0x68c0)}, /* Sierra Wireless MC7304/MC7354 */
{DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */
{DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */
{DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */
{DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */
{DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */
@@ -153,6 +157,8 @@ static const struct usb_device_id id_table[] = {
{DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx/EM74xx */
+ {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx/EM74xx */
{DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
@@ -167,6 +173,38 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
+static int handle_quectel_ec20(struct device *dev, int ifnum)
+{
+ int altsetting = 0;
+
+ /*
+ * Quectel EC20 Mini PCIe LTE module layout:
+ * 0: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 1: NMEA
+ * 2: AT-capable modem port
+ * 3: Modem interface
+ * 4: NDIS
+ */
+ switch (ifnum) {
+ case 0:
+ dev_dbg(dev, "Quectel EC20 DM/DIAG interface found\n");
+ break;
+ case 1:
+ dev_dbg(dev, "Quectel EC20 NMEA GPS interface found\n");
+ break;
+ case 2:
+ case 3:
+ dev_dbg(dev, "Quectel EC20 Modem port found\n");
+ break;
+ case 4:
+ /* Don't claim the QMI/net interface */
+ altsetting = -1;
+ break;
+ }
+
+ return altsetting;
+}
+
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
struct usb_host_interface *intf = serial->interface->cur_altsetting;
@@ -175,6 +213,11 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
__u8 nintf;
__u8 ifnum;
int altsetting = -1;
+ bool sendsetup = false;
+
+ /* we only support vendor specific functions */
+ if (intf->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+ goto done;
nintf = serial->dev->actconfig->desc.bNumInterfaces;
dev_dbg(dev, "Num Interfaces = %d\n", nintf);
@@ -235,6 +278,12 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
altsetting = -1;
break;
case QCSERIAL_G2K:
+ /* handle non-standard layouts */
+ if (nintf == 5 && id->idProduct == QUECTEL_EC20_PID) {
+ altsetting = handle_quectel_ec20(dev, ifnum);
+ goto done;
+ }
+
/*
* Gobi 2K+ USB layout:
* 0: QMI/net
@@ -286,6 +335,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
break;
case 3:
dev_dbg(dev, "Modem port found\n");
+ sendsetup = true;
break;
default:
/* don't claim any unsupported interface */
@@ -295,29 +345,39 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
break;
case QCSERIAL_HWI:
/*
- * Huawei layout:
- * 0: AT-capable modem port
- * 1: DM/DIAG
- * 2: AT-capable modem port
- * 3: CCID-compatible PCSC interface
- * 4: QMI/net
- * 5: NMEA
+ * Huawei devices map functions by subclass + protocol
+ * instead of interface numbers. The protocol identify
+ * a specific function, while the subclass indicate a
+ * specific firmware source
+ *
+ * This is a blacklist of functions known to be
+ * non-serial. The rest are assumed to be serial and
+ * will be handled by this driver
*/
- switch (ifnum) {
- case 0:
- case 2:
- dev_dbg(dev, "Modem port found\n");
- break;
- case 1:
- dev_dbg(dev, "DM/DIAG interface found\n");
- break;
- case 5:
- dev_dbg(dev, "NMEA GPS interface found\n");
- break;
- default:
- /* don't claim any unsupported interface */
+ switch (intf->desc.bInterfaceProtocol) {
+ /* QMI combined (qmi_wwan) */
+ case 0x07:
+ case 0x37:
+ case 0x67:
+ /* QMI data (qmi_wwan) */
+ case 0x08:
+ case 0x38:
+ case 0x68:
+ /* QMI control (qmi_wwan) */
+ case 0x09:
+ case 0x39:
+ case 0x69:
+ /* NCM like (huawei_cdc_ncm) */
+ case 0x16:
+ case 0x46:
+ case 0x76:
altsetting = -1;
break;
+ default:
+ dev_dbg(dev, "Huawei type serial port found (%02x/%02x/%02x)\n",
+ intf->desc.bInterfaceClass,
+ intf->desc.bInterfaceSubClass,
+ intf->desc.bInterfaceProtocol);
}
break;
default:
@@ -337,17 +397,25 @@ done:
}
}
+ if (!retval)
+ usb_set_serial_data(serial, (void *)(unsigned long)sendsetup);
+
return retval;
}
static int qc_attach(struct usb_serial *serial)
{
struct usb_wwan_intf_private *data;
+ bool sendsetup;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ sendsetup = !!(unsigned long)(usb_get_serial_data(serial));
+ if (sendsetup)
+ data->use_send_setup = 1;
+
spin_lock_init(&data->susp_lock);
usb_set_serial_data(serial, data);
@@ -374,6 +442,7 @@ static struct usb_serial_driver qcdevice = {
.probe = qcprobe,
.open = usb_wwan_open,
.close = usb_wwan_close,
+ .dtr_rts = usb_wwan_dtr_rts,
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index e9da41d9fe7f..2694df2f4559 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -159,6 +159,7 @@ static const struct usb_device_id ti_id_table_3410[] = {
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+ { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) },
{ } /* terminator */
};
@@ -191,6 +192,7 @@ static const struct usb_device_id ti_id_table_combined[] = {
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+ { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) },
{ } /* terminator */
};
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 4a2423e84d55..98f35c656c02 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -56,6 +56,10 @@
#define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID
#define ABBOTT_STRIP_PORT_ID 0x3420
+/* Honeywell vendor and product IDs */
+#define HONEYWELL_VENDOR_ID 0x10ac
+#define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */
+
/* Commands */
#define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index f22dff58b587..44b25c08c68a 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -34,9 +34,9 @@ extern int usb_wwan_resume(struct usb_serial *serial);
struct usb_wwan_intf_private {
spinlock_t susp_lock;
unsigned int suspended:1;
+ unsigned int use_send_setup:1;
int in_flight;
unsigned int open_ports;
- int (*send_setup) (struct usb_serial_port *port);
void *private;
};
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 825305cb71d9..be9cb61b4d19 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -36,6 +36,40 @@
#include <linux/serial.h>
#include "usb-wwan.h"
+/*
+ * Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
+ * in CDC ACM.
+ */
+static int usb_wwan_send_setup(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct usb_wwan_port_private *portdata;
+ int val = 0;
+ int ifnum;
+ int res;
+
+ portdata = usb_get_serial_port_data(port);
+
+ if (portdata->dtr_state)
+ val |= 0x01;
+ if (portdata->rts_state)
+ val |= 0x02;
+
+ ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+ res = usb_autopm_get_interface(serial->interface);
+ if (res)
+ return res;
+
+ res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, ifnum, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+
+ usb_autopm_put_interface(port->serial->interface);
+
+ return res;
+}
+
void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_wwan_port_private *portdata;
@@ -43,7 +77,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
intfdata = usb_get_serial_data(port->serial);
- if (!intfdata->send_setup)
+ if (!intfdata->use_send_setup)
return;
portdata = usb_get_serial_port_data(port);
@@ -51,7 +85,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
portdata->rts_state = on;
portdata->dtr_state = on;
- intfdata->send_setup(port);
+ usb_wwan_send_setup(port);
}
EXPORT_SYMBOL(usb_wwan_dtr_rts);
@@ -84,7 +118,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
portdata = usb_get_serial_port_data(port);
intfdata = usb_get_serial_data(port->serial);
- if (!intfdata->send_setup)
+ if (!intfdata->use_send_setup)
return -EINVAL;
/* FIXME: what locks portdata fields ? */
@@ -97,7 +131,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return intfdata->send_setup(port);
+ return usb_wwan_send_setup(port);
}
EXPORT_SYMBOL(usb_wwan_tiocmset);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 1bac215202d2..39afd7045c43 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1456,30 +1456,26 @@ static void isd200_free_info_ptrs(void *info_)
*/
static int isd200_init_info(struct us_data *us)
{
- int retStatus = ISD200_GOOD;
struct isd200_info *info;
info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL);
if (!info)
- retStatus = ISD200_ERROR;
- else {
- info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
- info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
- info->srb.sense_buffer =
- kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
- if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
- isd200_free_info_ptrs(info);
- kfree(info);
- retStatus = ISD200_ERROR;
- }
- }
+ return ISD200_ERROR;
- if (retStatus == ISD200_GOOD) {
- us->extra = info;
- us->extra_destructor = isd200_free_info_ptrs;
+ info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
+ info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+ info->srb.sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+
+ if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
+ isd200_free_info_ptrs(info);
+ kfree(info);
+ return ISD200_ERROR;
}
- return retStatus;
+ us->extra = info;
+ us->extra_destructor = isd200_free_info_ptrs;
+
+ return ISD200_GOOD;
}
/**************************************************************************
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index f68921909552..e69151664436 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -257,17 +257,16 @@ static void uas_stat_cmplt(struct urb *urb)
struct uas_cmd_info *cmdinfo;
unsigned long flags;
unsigned int idx;
+ int status = urb->status;
spin_lock_irqsave(&devinfo->lock, flags);
if (devinfo->resetting)
goto out;
- if (urb->status) {
- if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
- dev_err(&urb->dev->dev, "stat urb: status %d\n",
- urb->status);
- }
+ if (status) {
+ if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
+ dev_err(&urb->dev->dev, "stat urb: status %d\n", status);
goto out;
}
@@ -348,6 +347,7 @@ static void uas_data_cmplt(struct urb *urb)
struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
struct scsi_data_buffer *sdb = NULL;
unsigned long flags;
+ int status = urb->status;
spin_lock_irqsave(&devinfo->lock, flags);
@@ -374,9 +374,9 @@ static void uas_data_cmplt(struct urb *urb)
goto out;
}
- if (urb->status) {
- if (urb->status != -ENOENT && urb->status != -ECONNRESET)
- uas_log_cmd_state(cmnd, "data cmplt err", urb->status);
+ if (status) {
+ if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
+ uas_log_cmd_state(cmnd, "data cmplt err", status);
/* error: no data transfered */
sdb->resid = sdb->length;
} else {
@@ -812,7 +812,6 @@ static struct scsi_host_template uas_host_template = {
.this_id = -1,
.sg_tablesize = SG_NONE,
.skip_settle_delay = 1,
- .use_blk_tags = 1,
};
#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
@@ -929,10 +928,6 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (result)
goto set_alt0;
- result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
- if (result)
- goto free_streams;
-
usb_set_intfdata(intf, shost);
result = scsi_add_host(shost, &intf->dev);
if (result)
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index e9ef1eccdace..7fbe19d5279e 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -218,7 +218,7 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
memset(desc, 0, sizeof(*desc));
desc->bDescriptorType = USB_DT_HUB;
desc->bDescLength = 9;
- desc->wHubCharacteristics = __constant_cpu_to_le16(
+ desc->wHubCharacteristics = cpu_to_le16(
HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
desc->bNbrPorts = VHCI_NPORTS;
desc->u.hs.DeviceRemovable[0] = 0xff;
@@ -565,7 +565,9 @@ no_need_xmit:
usb_hcd_unlink_urb_from_ep(hcd, urb);
no_need_unlink:
spin_unlock(&the_controller->lock);
- usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+ if (!ret)
+ usb_hcd_giveback_urb(vhci_to_hcd(the_controller),
+ urb, urb->status);
return ret;
}
@@ -629,7 +631,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
/* URB was never linked! or will be soon given back by
* vhci_rx. */
spin_unlock(&the_controller->lock);
- return 0;
+ return -EIDRM;
}
{
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c
index 8fc1b787dced..38d0504a1bbc 100644
--- a/drivers/uwb/drp.c
+++ b/drivers/uwb/drp.c
@@ -642,9 +642,7 @@ static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_i
}
INIT_LIST_HEAD(&cnflt->rc_node);
- init_timer(&cnflt->timer);
- cnflt->timer.function = uwb_cnflt_timer;
- cnflt->timer.data = (unsigned long)cnflt;
+ setup_timer(&cnflt->timer, uwb_cnflt_timer, (unsigned long)cnflt);
cnflt->rc = rc;
INIT_WORK(&cnflt->cnflt_update_work, uwb_cnflt_update_work);
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c
index 8cb71bb333c2..36b5cb62c15d 100644
--- a/drivers/uwb/neh.c
+++ b/drivers/uwb/neh.c
@@ -223,9 +223,7 @@ struct uwb_rc_neh *uwb_rc_neh_add(struct uwb_rc *rc, struct uwb_rccb *cmd,
kref_init(&neh->kref);
INIT_LIST_HEAD(&neh->list_node);
- init_timer(&neh->timer);
- neh->timer.function = uwb_rc_neh_timer;
- neh->timer.data = (unsigned long)neh;
+ setup_timer(&neh->timer, uwb_rc_neh_timer, (unsigned long)neh);
neh->rc = rc;
neh->evt_type = expected_type;
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index 536ad42b0a4b..f5e27247a38f 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -470,9 +470,7 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
INIT_LIST_HEAD(&rsv->rc_node);
INIT_LIST_HEAD(&rsv->pal_node);
kref_init(&rsv->kref);
- init_timer(&rsv->timer);
- rsv->timer.function = uwb_rsv_timer;
- rsv->timer.data = (unsigned long)rsv;
+ setup_timer(&rsv->timer, uwb_rsv_timer, (unsigned long)rsv);
rsv->rc = rc;
INIT_WORK(&rsv->handle_timeout_work, uwb_rsv_handle_timeout_work);
@@ -989,9 +987,8 @@ void uwb_rsv_init(struct uwb_rc *rc)
rc->bow.can_reserve_extra_mases = true;
rc->bow.total_expired = 0;
rc->bow.window = UWB_DRP_BACKOFF_WIN_MIN >> 1;
- init_timer(&rc->bow.timer);
- rc->bow.timer.function = uwb_rsv_backoff_win_timer;
- rc->bow.timer.data = (unsigned long)&rc->bow;
+ setup_timer(&rc->bow.timer, uwb_rsv_backoff_win_timer,
+ (unsigned long)&rc->bow);
bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS);
}
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index 0b1e5a9449b5..991374b13571 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -55,7 +55,7 @@
struct uwb_dbg {
struct uwb_pal pal;
- u32 accept;
+ bool accept;
struct list_head rsvs;
struct dentry *root_d;
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 454017928ed0..da6e2ce77495 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -31,5 +31,21 @@ menuconfig VFIO
If you don't know what to do here, say N.
+menuconfig VFIO_NOIOMMU
+ bool "VFIO No-IOMMU support"
+ depends on VFIO
+ help
+ VFIO is built on the ability to isolate devices using the IOMMU.
+ Only with an IOMMU can userspace access to DMA capable devices be
+ considered secure. VFIO No-IOMMU mode enables IOMMU groups for
+ devices without IOMMU backing for the purpose of re-using the VFIO
+ infrastructure in a non-secure mode. Use of this mode will result
+ in an unsupportable kernel and will therefore taint the kernel.
+ Device assignment to virtual machines is also not possible with
+ this mode since there is no IOMMU to provide DMA translation.
+
+ If you don't know what to do here, say N.
+
source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
+source "virt/lib/Kconfig"
diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
index 579d83bf5358..02912f180c6d 100644
--- a/drivers/vfio/pci/Kconfig
+++ b/drivers/vfio/pci/Kconfig
@@ -2,6 +2,7 @@ config VFIO_PCI
tristate "VFIO support for PCI devices"
depends on VFIO && PCI && EVENTFD
select VFIO_VIRQFD
+ select IRQ_BYPASS_MANAGER
help
Support for the PCI VFIO bus driver. This is required to make
use of PCI drivers using the VFIO framework.
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 964ad572aaee..32b88bd2c82c 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
return -EINVAL;
- group = iommu_group_get(&pdev->dev);
+ group = vfio_iommu_group_get(&pdev->dev);
if (!group)
return -EINVAL;
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
if (!vdev) {
- iommu_group_put(group);
+ vfio_iommu_group_put(group, &pdev->dev);
return -ENOMEM;
}
@@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
if (ret) {
- iommu_group_put(group);
+ vfio_iommu_group_put(group, &pdev->dev);
kfree(vdev);
return ret;
}
@@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
if (!vdev)
return;
- iommu_group_put(pdev->dev.iommu_group);
+ vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
kfree(vdev);
if (vfio_pci_is_vga(pdev)) {
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index ff75ca31a199..fe2b470d7ec6 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -46,7 +46,7 @@
* 0: Removed from the user visible capability list
* FF: Variable length
*/
-static u8 pci_cap_length[] = {
+static const u8 pci_cap_length[PCI_CAP_ID_MAX + 1] = {
[PCI_CAP_ID_BASIC] = PCI_STD_HEADER_SIZEOF, /* pci config header */
[PCI_CAP_ID_PM] = PCI_PM_SIZEOF,
[PCI_CAP_ID_AGP] = PCI_AGP_SIZEOF,
@@ -74,7 +74,7 @@ static u8 pci_cap_length[] = {
* 0: Removed or masked from the user visible capabilty list
* FF: Variable length
*/
-static u16 pci_ext_cap_length[] = {
+static const u16 pci_ext_cap_length[PCI_EXT_CAP_ID_MAX + 1] = {
[PCI_EXT_CAP_ID_ERR] = PCI_ERR_ROOT_COMMAND,
[PCI_EXT_CAP_ID_VC] = 0xFF,
[PCI_EXT_CAP_ID_DSN] = PCI_EXT_CAP_DSN_SIZEOF,
@@ -671,6 +671,73 @@ static int __init init_pci_cap_pm_perm(struct perm_bits *perm)
return 0;
}
+static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos,
+ int count, struct perm_bits *perm,
+ int offset, __le32 val)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ __le16 *paddr = (__le16 *)(vdev->vconfig + pos - offset + PCI_VPD_ADDR);
+ __le32 *pdata = (__le32 *)(vdev->vconfig + pos - offset + PCI_VPD_DATA);
+ u16 addr;
+ u32 data;
+
+ /*
+ * Write through to emulation. If the write includes the upper byte
+ * of PCI_VPD_ADDR, then the PCI_VPD_ADDR_F bit is written and we
+ * have work to do.
+ */
+ count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
+ if (count < 0 || offset > PCI_VPD_ADDR + 1 ||
+ offset + count <= PCI_VPD_ADDR + 1)
+ return count;
+
+ addr = le16_to_cpu(*paddr);
+
+ if (addr & PCI_VPD_ADDR_F) {
+ data = le32_to_cpu(*pdata);
+ if (pci_write_vpd(pdev, addr & ~PCI_VPD_ADDR_F, 4, &data) != 4)
+ return count;
+ } else {
+ if (pci_read_vpd(pdev, addr, 4, &data) != 4)
+ return count;
+ *pdata = cpu_to_le32(data);
+ }
+
+ /*
+ * Toggle PCI_VPD_ADDR_F in the emulated PCI_VPD_ADDR register to
+ * signal completion. If an error occurs above, we assume that not
+ * toggling this bit will induce a driver timeout.
+ */
+ addr ^= PCI_VPD_ADDR_F;
+ *paddr = cpu_to_le16(addr);
+
+ return count;
+}
+
+/* Permissions for Vital Product Data capability */
+static int __init init_pci_cap_vpd_perm(struct perm_bits *perm)
+{
+ if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_VPD]))
+ return -ENOMEM;
+
+ perm->writefn = vfio_vpd_config_write;
+
+ /*
+ * We always virtualize the next field so we can remove
+ * capabilities from the chain if we want to.
+ */
+ p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE);
+
+ /*
+ * Both the address and data registers are virtualized to
+ * enable access through the pci_vpd_read/write functions
+ */
+ p_setw(perm, PCI_VPD_ADDR, (u16)ALL_VIRT, (u16)ALL_WRITE);
+ p_setd(perm, PCI_VPD_DATA, ALL_VIRT, ALL_WRITE);
+
+ return 0;
+}
+
/* Permissions for PCI-X capability */
static int __init init_pci_cap_pcix_perm(struct perm_bits *perm)
{
@@ -790,6 +857,7 @@ void vfio_pci_uninit_perm_bits(void)
free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]);
free_perm_bits(&cap_perms[PCI_CAP_ID_PM]);
+ free_perm_bits(&cap_perms[PCI_CAP_ID_VPD]);
free_perm_bits(&cap_perms[PCI_CAP_ID_PCIX]);
free_perm_bits(&cap_perms[PCI_CAP_ID_EXP]);
free_perm_bits(&cap_perms[PCI_CAP_ID_AF]);
@@ -807,7 +875,7 @@ int __init vfio_pci_init_perm_bits(void)
/* Capabilities */
ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]);
- cap_perms[PCI_CAP_ID_VPD].writefn = vfio_raw_config_write;
+ ret |= init_pci_cap_vpd_perm(&cap_perms[PCI_CAP_ID_VPD]);
ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]);
cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_raw_config_write;
ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]);
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 1f577b4ac126..3b3ba15558b7 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -319,6 +319,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
if (vdev->ctx[vector].trigger) {
free_irq(irq, vdev->ctx[vector].trigger);
+ irq_bypass_unregister_producer(&vdev->ctx[vector].producer);
kfree(vdev->ctx[vector].name);
eventfd_ctx_put(vdev->ctx[vector].trigger);
vdev->ctx[vector].trigger = NULL;
@@ -360,6 +361,14 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
return ret;
}
+ vdev->ctx[vector].producer.token = trigger;
+ vdev->ctx[vector].producer.irq = irq;
+ ret = irq_bypass_register_producer(&vdev->ctx[vector].producer);
+ if (unlikely(ret))
+ dev_info(&pdev->dev,
+ "irq bypass producer (token %p) registration fails: %d\n",
+ vdev->ctx[vector].producer.token, ret);
+
vdev->ctx[vector].trigger = trigger;
return 0;
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index ae0e1b4c1711..0e7394f8f69b 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -13,6 +13,7 @@
#include <linux/mutex.h>
#include <linux/pci.h>
+#include <linux/irqbypass.h>
#ifndef VFIO_PCI_PRIVATE_H
#define VFIO_PCI_PRIVATE_H
@@ -29,6 +30,7 @@ struct vfio_pci_irq_ctx {
struct virqfd *mask;
char *name;
bool masked;
+ struct irq_bypass_producer producer;
};
struct vfio_pci_device {
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 9ce8afe28450..41a6224f5e6b 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,10 +1,12 @@
-
-vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-y := vfio_platform.o
obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o
obj-$(CONFIG_VFIO_PLATFORM) += reset/
vfio-amba-y := vfio_amba.o
obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
+obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o
obj-$(CONFIG_VFIO_AMBA) += reset/
diff --git a/drivers/vfio/platform/reset/Kconfig b/drivers/vfio/platform/reset/Kconfig
index 746b96b0003b..70cccc582bee 100644
--- a/drivers/vfio/platform/reset/Kconfig
+++ b/drivers/vfio/platform/reset/Kconfig
@@ -5,3 +5,11 @@ config VFIO_PLATFORM_CALXEDAXGMAC_RESET
Enables the VFIO platform driver to handle reset for Calxeda xgmac
If you don't know what to do here, say N.
+
+config VFIO_PLATFORM_AMDXGBE_RESET
+ tristate "VFIO support for AMD XGBE reset"
+ depends on VFIO_PLATFORM
+ help
+ Enables the VFIO platform driver to handle reset for AMD XGBE
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/reset/Makefile b/drivers/vfio/platform/reset/Makefile
index 2a486af9f8fa..93f4e232697b 100644
--- a/drivers/vfio/platform/reset/Makefile
+++ b/drivers/vfio/platform/reset/Makefile
@@ -1,5 +1,7 @@
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
diff --git a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
new file mode 100644
index 000000000000..da5356f48d0b
--- /dev/null
+++ b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
@@ -0,0 +1,127 @@
+/*
+ * VFIO platform driver specialized for AMD xgbe reset
+ * reset code is inherited from AMD xgbe native driver
+ *
+ * Copyright (c) 2015 Linaro Ltd.
+ * www.linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <uapi/linux/mdio.h>
+#include <linux/delay.h>
+
+#include "vfio_platform_private.h"
+
+#define DMA_MR 0x3000
+#define MAC_VR 0x0110
+#define DMA_ISR 0x3008
+#define MAC_ISR 0x00b0
+#define PCS_MMD_SELECT 0xff
+#define MDIO_AN_INT 0x8002
+#define MDIO_AN_INTMASK 0x8001
+
+static unsigned int xmdio_read(void *ioaddr, unsigned int mmd,
+ unsigned int reg)
+{
+ unsigned int mmd_address, value;
+
+ mmd_address = (mmd << 16) | ((reg) & 0xffff);
+ iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
+ value = ioread32(ioaddr + ((mmd_address & 0xff) << 2));
+ return value;
+}
+
+static void xmdio_write(void *ioaddr, unsigned int mmd,
+ unsigned int reg, unsigned int value)
+{
+ unsigned int mmd_address;
+
+ mmd_address = (mmd << 16) | ((reg) & 0xffff);
+ iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
+ iowrite32(value, ioaddr + ((mmd_address & 0xff) << 2));
+}
+
+int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev)
+{
+ struct vfio_platform_region *xgmac_regs = &vdev->regions[0];
+ struct vfio_platform_region *xpcs_regs = &vdev->regions[1];
+ u32 dma_mr_value, pcs_value, value;
+ unsigned int count;
+
+ if (!xgmac_regs->ioaddr) {
+ xgmac_regs->ioaddr =
+ ioremap_nocache(xgmac_regs->addr, xgmac_regs->size);
+ if (!xgmac_regs->ioaddr)
+ return -ENOMEM;
+ }
+ if (!xpcs_regs->ioaddr) {
+ xpcs_regs->ioaddr =
+ ioremap_nocache(xpcs_regs->addr, xpcs_regs->size);
+ if (!xpcs_regs->ioaddr)
+ return -ENOMEM;
+ }
+
+ /* reset the PHY through MDIO*/
+ pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1);
+ pcs_value |= MDIO_CTRL1_RESET;
+ xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1, pcs_value);
+
+ count = 50;
+ do {
+ msleep(20);
+ pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS,
+ MDIO_CTRL1);
+ } while ((pcs_value & MDIO_CTRL1_RESET) && --count);
+
+ if (pcs_value & MDIO_CTRL1_RESET)
+ pr_warn("%s XGBE PHY reset timeout\n", __func__);
+
+ /* disable auto-negotiation */
+ value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1);
+ value &= ~MDIO_AN_CTRL1_ENABLE;
+ xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1, value);
+
+ /* disable AN IRQ */
+ xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+
+ /* clear AN IRQ */
+ xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INT, 0);
+
+ /* MAC software reset */
+ dma_mr_value = ioread32(xgmac_regs->ioaddr + DMA_MR);
+ dma_mr_value |= 0x1;
+ iowrite32(dma_mr_value, xgmac_regs->ioaddr + DMA_MR);
+
+ usleep_range(10, 15);
+
+ count = 2000;
+ while (count-- && (ioread32(xgmac_regs->ioaddr + DMA_MR) & 1))
+ usleep_range(500, 600);
+
+ if (!count)
+ pr_warn("%s MAC SW reset failed\n", __func__);
+
+ return 0;
+}
+
+module_vfio_reset_handler("amd,xgbe-seattle-v1a", vfio_platform_amdxgbe_reset);
+
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Eric Auger <eric.auger@linaro.org>");
+MODULE_DESCRIPTION("Reset support for AMD xgbe vfio platform device");
diff --git a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
index 619dc7d22082..e3d3d948e661 100644
--- a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
+++ b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
@@ -30,8 +30,6 @@
#define DRIVER_AUTHOR "Eric Auger <eric.auger@linaro.org>"
#define DRIVER_DESC "Reset support for Calxeda xgmac vfio platform device"
-#define CALXEDAXGMAC_COMPAT "calxeda,hb-xgmac"
-
/* XGMAC Register definitions */
#define XGMAC_CONTROL 0x00000000 /* MAC Configuration */
@@ -61,24 +59,25 @@ static inline void xgmac_mac_disable(void __iomem *ioaddr)
int vfio_platform_calxedaxgmac_reset(struct vfio_platform_device *vdev)
{
- struct vfio_platform_region reg = vdev->regions[0];
+ struct vfio_platform_region *reg = &vdev->regions[0];
- if (!reg.ioaddr) {
- reg.ioaddr =
- ioremap_nocache(reg.addr, reg.size);
- if (!reg.ioaddr)
+ if (!reg->ioaddr) {
+ reg->ioaddr =
+ ioremap_nocache(reg->addr, reg->size);
+ if (!reg->ioaddr)
return -ENOMEM;
}
/* disable IRQ */
- writel(0, reg.ioaddr + XGMAC_DMA_INTR_ENA);
+ writel(0, reg->ioaddr + XGMAC_DMA_INTR_ENA);
/* Disable the MAC core */
- xgmac_mac_disable(reg.ioaddr);
+ xgmac_mac_disable(reg->ioaddr);
return 0;
}
-EXPORT_SYMBOL_GPL(vfio_platform_calxedaxgmac_reset);
+
+module_vfio_reset_handler("calxeda,hb-xgmac", vfio_platform_calxedaxgmac_reset);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
index ff0331f72526..a66479bd0edf 100644
--- a/drivers/vfio/platform/vfio_amba.c
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -67,6 +67,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
vdev->get_resource = get_amba_resource;
vdev->get_irq = get_amba_irq;
+ vdev->parent_module = THIS_MODULE;
ret = vfio_platform_probe_common(vdev, &adev->dev);
if (ret) {
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index cef645c83996..f1625dcfbb23 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -65,6 +65,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
vdev->get_resource = get_platform_resource;
vdev->get_irq = get_platform_irq;
+ vdev->parent_module = THIS_MODULE;
ret = vfio_platform_probe_common(vdev, &pdev->dev);
if (ret)
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index e43efb5e92bf..a1c50d630792 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -23,44 +23,50 @@
#include "vfio_platform_private.h"
-static DEFINE_MUTEX(driver_lock);
+#define DRIVER_VERSION "0.10"
+#define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>"
+#define DRIVER_DESC "VFIO platform base module"
-static const struct vfio_platform_reset_combo reset_lookup_table[] = {
- {
- .compat = "calxeda,hb-xgmac",
- .reset_function_name = "vfio_platform_calxedaxgmac_reset",
- .module_name = "vfio-platform-calxedaxgmac",
- },
-};
+static LIST_HEAD(reset_list);
+static DEFINE_MUTEX(driver_lock);
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev,
- struct device *dev)
+static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
+ struct module **module)
{
- const char *compat;
- int (*reset)(struct vfio_platform_device *);
- int ret, i;
-
- ret = device_property_read_string(dev, "compatible", &compat);
- if (ret)
- return;
-
- for (i = 0 ; i < ARRAY_SIZE(reset_lookup_table); i++) {
- if (!strcmp(reset_lookup_table[i].compat, compat)) {
- request_module(reset_lookup_table[i].module_name);
- reset = __symbol_get(
- reset_lookup_table[i].reset_function_name);
- if (reset) {
- vdev->reset = reset;
- return;
- }
+ struct vfio_platform_reset_node *iter;
+ vfio_platform_reset_fn_t reset_fn = NULL;
+
+ mutex_lock(&driver_lock);
+ list_for_each_entry(iter, &reset_list, link) {
+ if (!strcmp(iter->compat, compat) &&
+ try_module_get(iter->owner)) {
+ *module = iter->owner;
+ reset_fn = iter->reset;
+ break;
}
}
+ mutex_unlock(&driver_lock);
+ return reset_fn;
+}
+
+static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+{
+ char modname[256];
+
+ vdev->reset = vfio_platform_lookup_reset(vdev->compat,
+ &vdev->reset_module);
+ if (!vdev->reset) {
+ snprintf(modname, 256, "vfio-reset:%s", vdev->compat);
+ request_module(modname);
+ vdev->reset = vfio_platform_lookup_reset(vdev->compat,
+ &vdev->reset_module);
+ }
}
static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
{
if (vdev->reset)
- symbol_put_addr(vdev->reset);
+ module_put(vdev->reset_module);
}
static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
@@ -138,15 +144,19 @@ static void vfio_platform_release(void *device_data)
mutex_lock(&driver_lock);
if (!(--vdev->refcnt)) {
- if (vdev->reset)
+ if (vdev->reset) {
+ dev_info(vdev->device, "reset\n");
vdev->reset(vdev);
+ } else {
+ dev_warn(vdev->device, "no reset function found!\n");
+ }
vfio_platform_regions_cleanup(vdev);
vfio_platform_irq_cleanup(vdev);
}
mutex_unlock(&driver_lock);
- module_put(THIS_MODULE);
+ module_put(vdev->parent_module);
}
static int vfio_platform_open(void *device_data)
@@ -154,7 +164,7 @@ static int vfio_platform_open(void *device_data)
struct vfio_platform_device *vdev = device_data;
int ret;
- if (!try_module_get(THIS_MODULE))
+ if (!try_module_get(vdev->parent_module))
return -ENODEV;
mutex_lock(&driver_lock);
@@ -168,8 +178,12 @@ static int vfio_platform_open(void *device_data)
if (ret)
goto err_irq;
- if (vdev->reset)
+ if (vdev->reset) {
+ dev_info(vdev->device, "reset\n");
vdev->reset(vdev);
+ } else {
+ dev_warn(vdev->device, "no reset function found!\n");
+ }
}
vdev->refcnt++;
@@ -307,17 +321,17 @@ static long vfio_platform_ioctl(void *device_data,
return -ENOTTY;
}
-static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg,
char __user *buf, size_t count,
loff_t off)
{
unsigned int done = 0;
- if (!reg.ioaddr) {
- reg.ioaddr =
- ioremap_nocache(reg.addr, reg.size);
+ if (!reg->ioaddr) {
+ reg->ioaddr =
+ ioremap_nocache(reg->addr, reg->size);
- if (!reg.ioaddr)
+ if (!reg->ioaddr)
return -ENOMEM;
}
@@ -327,7 +341,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
if (count >= 4 && !(off % 4)) {
u32 val;
- val = ioread32(reg.ioaddr + off);
+ val = ioread32(reg->ioaddr + off);
if (copy_to_user(buf, &val, 4))
goto err;
@@ -335,7 +349,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
} else if (count >= 2 && !(off % 2)) {
u16 val;
- val = ioread16(reg.ioaddr + off);
+ val = ioread16(reg->ioaddr + off);
if (copy_to_user(buf, &val, 2))
goto err;
@@ -343,7 +357,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
} else {
u8 val;
- val = ioread8(reg.ioaddr + off);
+ val = ioread8(reg->ioaddr + off);
if (copy_to_user(buf, &val, 1))
goto err;
@@ -376,7 +390,7 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
return -EINVAL;
if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
- return vfio_platform_read_mmio(vdev->regions[index],
+ return vfio_platform_read_mmio(&vdev->regions[index],
buf, count, off);
else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
return -EINVAL; /* not implemented */
@@ -384,17 +398,17 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
return -EINVAL;
}
-static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg,
const char __user *buf, size_t count,
loff_t off)
{
unsigned int done = 0;
- if (!reg.ioaddr) {
- reg.ioaddr =
- ioremap_nocache(reg.addr, reg.size);
+ if (!reg->ioaddr) {
+ reg->ioaddr =
+ ioremap_nocache(reg->addr, reg->size);
- if (!reg.ioaddr)
+ if (!reg->ioaddr)
return -ENOMEM;
}
@@ -406,7 +420,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
if (copy_from_user(&val, buf, 4))
goto err;
- iowrite32(val, reg.ioaddr + off);
+ iowrite32(val, reg->ioaddr + off);
filled = 4;
} else if (count >= 2 && !(off % 2)) {
@@ -414,7 +428,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
if (copy_from_user(&val, buf, 2))
goto err;
- iowrite16(val, reg.ioaddr + off);
+ iowrite16(val, reg->ioaddr + off);
filled = 2;
} else {
@@ -422,7 +436,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
if (copy_from_user(&val, buf, 1))
goto err;
- iowrite8(val, reg.ioaddr + off);
+ iowrite8(val, reg->ioaddr + off);
filled = 1;
}
@@ -452,7 +466,7 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
return -EINVAL;
if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
- return vfio_platform_write_mmio(vdev->regions[index],
+ return vfio_platform_write_mmio(&vdev->regions[index],
buf, count, off);
else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
return -EINVAL; /* not implemented */
@@ -539,6 +553,14 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
if (!vdev)
return -EINVAL;
+ ret = device_property_read_string(dev, "compatible", &vdev->compat);
+ if (ret) {
+ pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
+ return -EINVAL;
+ }
+
+ vdev->device = dev;
+
group = iommu_group_get(dev);
if (!group) {
pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
@@ -551,7 +573,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
return ret;
}
- vfio_platform_get_reset(vdev, dev);
+ vfio_platform_get_reset(vdev);
mutex_init(&vdev->igate);
@@ -573,3 +595,34 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
return vdev;
}
EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
+
+void __vfio_platform_register_reset(struct vfio_platform_reset_node *node)
+{
+ mutex_lock(&driver_lock);
+ list_add(&node->link, &reset_list);
+ mutex_unlock(&driver_lock);
+}
+EXPORT_SYMBOL_GPL(__vfio_platform_register_reset);
+
+void vfio_platform_unregister_reset(const char *compat,
+ vfio_platform_reset_fn_t fn)
+{
+ struct vfio_platform_reset_node *iter, *temp;
+
+ mutex_lock(&driver_lock);
+ list_for_each_entry_safe(iter, temp, &reset_list, link) {
+ if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
+ list_del(&iter->link);
+ break;
+ }
+ }
+
+ mutex_unlock(&driver_lock);
+
+}
+EXPORT_SYMBOL_GPL(vfio_platform_unregister_reset);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
index 88bba57b30a8..46d4750f43a8 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -185,6 +185,7 @@ static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
int ret;
if (irq->trigger) {
+ irq_clear_status_flags(irq->hwirq, IRQ_NOAUTOEN);
free_irq(irq->hwirq, irq);
kfree(irq->name);
eventfd_ctx_put(irq->trigger);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 1c9b3d59543c..42816dd280cb 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -56,6 +56,10 @@ struct vfio_platform_device {
u32 num_irqs;
int refcnt;
struct mutex igate;
+ struct module *parent_module;
+ const char *compat;
+ struct module *reset_module;
+ struct device *device;
/*
* These fields should be filled by the bus specific binder
@@ -70,10 +74,13 @@ struct vfio_platform_device {
int (*reset)(struct vfio_platform_device *vdev);
};
-struct vfio_platform_reset_combo {
- const char *compat;
- const char *reset_function_name;
- const char *module_name;
+typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
+
+struct vfio_platform_reset_node {
+ struct list_head link;
+ char *compat;
+ struct module *owner;
+ vfio_platform_reset_fn_t reset;
};
extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
@@ -89,4 +96,29 @@ extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
unsigned start, unsigned count,
void *data);
+extern void __vfio_platform_register_reset(struct vfio_platform_reset_node *n);
+extern void vfio_platform_unregister_reset(const char *compat,
+ vfio_platform_reset_fn_t fn);
+#define vfio_platform_register_reset(__compat, __reset) \
+static struct vfio_platform_reset_node __reset ## _node = { \
+ .owner = THIS_MODULE, \
+ .compat = __compat, \
+ .reset = __reset, \
+}; \
+__vfio_platform_register_reset(&__reset ## _node)
+
+#define module_vfio_reset_handler(compat, reset) \
+MODULE_ALIAS("vfio-reset:" compat); \
+static int __init reset ## _module_init(void) \
+{ \
+ vfio_platform_register_reset(compat, reset); \
+ return 0; \
+}; \
+static void __exit reset ## _module_exit(void) \
+{ \
+ vfio_platform_unregister_reset(compat, reset); \
+}; \
+module_init(reset ## _module_init); \
+module_exit(reset ## _module_exit)
+
#endif /* VFIO_PLATFORM_PRIVATE_H */
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 563c510f285c..de632da2e22f 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -25,6 +25,7 @@
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/pci.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -61,6 +62,7 @@ struct vfio_container {
struct rw_semaphore group_lock;
struct vfio_iommu_driver *iommu_driver;
void *iommu_data;
+ bool noiommu;
};
struct vfio_unbound_dev {
@@ -83,6 +85,7 @@ struct vfio_group {
struct list_head unbound_list;
struct mutex unbound_lock;
atomic_t opened;
+ bool noiommu;
};
struct vfio_device {
@@ -94,6 +97,147 @@ struct vfio_device {
void *device_data;
};
+#ifdef CONFIG_VFIO_NOIOMMU
+static bool noiommu __read_mostly;
+module_param_named(enable_unsafe_noiommu_support,
+ noiommu, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)");
+#endif
+
+/*
+ * vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
+ * and remove functions, any use cases other than acquiring the first
+ * reference for the purpose of calling vfio_add_group_dev() or removing
+ * that symmetric reference after vfio_del_group_dev() should use the raw
+ * iommu_group_{get,put} functions. In particular, vfio_iommu_group_put()
+ * removes the device from the dummy group and cannot be nested.
+ */
+struct iommu_group *vfio_iommu_group_get(struct device *dev)
+{
+ struct iommu_group *group;
+ int __maybe_unused ret;
+
+ group = iommu_group_get(dev);
+
+#ifdef CONFIG_VFIO_NOIOMMU
+ /*
+ * With noiommu enabled, an IOMMU group will be created for a device
+ * that doesn't already have one and doesn't have an iommu_ops on their
+ * bus. We use iommu_present() again in the main code to detect these
+ * fake groups.
+ */
+ if (group || !noiommu || iommu_present(dev->bus))
+ return group;
+
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
+ return NULL;
+
+ iommu_group_set_name(group, "vfio-noiommu");
+ ret = iommu_group_add_device(group, dev);
+ iommu_group_put(group);
+ if (ret)
+ return NULL;
+
+ /*
+ * Where to taint? At this point we've added an IOMMU group for a
+ * device that is not backed by iommu_ops, therefore any iommu_
+ * callback using iommu_ops can legitimately Oops. So, while we may
+ * be about to give a DMA capable device to a user without IOMMU
+ * protection, which is clearly taint-worthy, let's go ahead and do
+ * it here.
+ */
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+ dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n");
+#endif
+
+ return group;
+}
+EXPORT_SYMBOL_GPL(vfio_iommu_group_get);
+
+void vfio_iommu_group_put(struct iommu_group *group, struct device *dev)
+{
+#ifdef CONFIG_VFIO_NOIOMMU
+ if (!iommu_present(dev->bus))
+ iommu_group_remove_device(dev);
+#endif
+
+ iommu_group_put(group);
+}
+EXPORT_SYMBOL_GPL(vfio_iommu_group_put);
+
+#ifdef CONFIG_VFIO_NOIOMMU
+static void *vfio_noiommu_open(unsigned long arg)
+{
+ if (arg != VFIO_NOIOMMU_IOMMU)
+ return ERR_PTR(-EINVAL);
+ if (!capable(CAP_SYS_RAWIO))
+ return ERR_PTR(-EPERM);
+
+ return NULL;
+}
+
+static void vfio_noiommu_release(void *iommu_data)
+{
+}
+
+static long vfio_noiommu_ioctl(void *iommu_data,
+ unsigned int cmd, unsigned long arg)
+{
+ if (cmd == VFIO_CHECK_EXTENSION)
+ return arg == VFIO_NOIOMMU_IOMMU ? 1 : 0;
+
+ return -ENOTTY;
+}
+
+static int vfio_iommu_present(struct device *dev, void *unused)
+{
+ return iommu_present(dev->bus) ? 1 : 0;
+}
+
+static int vfio_noiommu_attach_group(void *iommu_data,
+ struct iommu_group *iommu_group)
+{
+ return iommu_group_for_each_dev(iommu_group, NULL,
+ vfio_iommu_present) ? -EINVAL : 0;
+}
+
+static void vfio_noiommu_detach_group(void *iommu_data,
+ struct iommu_group *iommu_group)
+{
+}
+
+static struct vfio_iommu_driver_ops vfio_noiommu_ops = {
+ .name = "vfio-noiommu",
+ .owner = THIS_MODULE,
+ .open = vfio_noiommu_open,
+ .release = vfio_noiommu_release,
+ .ioctl = vfio_noiommu_ioctl,
+ .attach_group = vfio_noiommu_attach_group,
+ .detach_group = vfio_noiommu_detach_group,
+};
+
+static struct vfio_iommu_driver vfio_noiommu_driver = {
+ .ops = &vfio_noiommu_ops,
+};
+
+/*
+ * Wrap IOMMU drivers, the noiommu driver is the one and only driver for
+ * noiommu groups (and thus containers) and not available for normal groups.
+ */
+#define vfio_for_each_iommu_driver(con, pos) \
+ for (pos = con->noiommu ? &vfio_noiommu_driver : \
+ list_first_entry(&vfio.iommu_drivers_list, \
+ struct vfio_iommu_driver, vfio_next); \
+ (con->noiommu ? pos != NULL : \
+ &pos->vfio_next != &vfio.iommu_drivers_list); \
+ pos = con->noiommu ? NULL : list_next_entry(pos, vfio_next))
+#else
+#define vfio_for_each_iommu_driver(con, pos) \
+ list_for_each_entry(pos, &vfio.iommu_drivers_list, vfio_next)
+#endif
+
+
/**
* IOMMU driver registration
*/
@@ -198,7 +342,8 @@ static void vfio_group_unlock_and_free(struct vfio_group *group)
/**
* Group objects - create, release, get, put, search
*/
-static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
+static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
+ bool noiommu)
{
struct vfio_group *group, *tmp;
struct device *dev;
@@ -216,6 +361,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
atomic_set(&group->container_users, 0);
atomic_set(&group->opened, 0);
group->iommu_group = iommu_group;
+ group->noiommu = noiommu;
group->nb.notifier_call = vfio_iommu_group_notifier;
@@ -251,7 +397,8 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
dev = device_create(vfio.class, NULL,
MKDEV(MAJOR(vfio.group_devt), minor),
- group, "%d", iommu_group_id(iommu_group));
+ group, "%s%d", noiommu ? "noiommu-" : "",
+ iommu_group_id(iommu_group));
if (IS_ERR(dev)) {
vfio_free_group_minor(minor);
vfio_group_unlock_and_free(group);
@@ -438,16 +585,33 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group,
}
/*
- * Whitelist some drivers that we know are safe (no dma) or just sit on
- * a device. It's not always practical to leave a device within a group
- * driverless as it could get re-bound to something unsafe.
+ * Some drivers, like pci-stub, are only used to prevent other drivers from
+ * claiming a device and are therefore perfectly legitimate for a user owned
+ * group. The pci-stub driver has no dependencies on DMA or the IOVA mapping
+ * of the device, but it does prevent the user from having direct access to
+ * the device, which is useful in some circumstances.
+ *
+ * We also assume that we can include PCI interconnect devices, ie. bridges.
+ * IOMMU grouping on PCI necessitates that if we lack isolation on a bridge
+ * then all of the downstream devices will be part of the same IOMMU group as
+ * the bridge. Thus, if placing the bridge into the user owned IOVA space
+ * breaks anything, it only does so for user owned devices downstream. Note
+ * that error notification via MSI can be affected for platforms that handle
+ * MSI within the same IOVA space as DMA.
*/
-static const char * const vfio_driver_whitelist[] = { "pci-stub", "pcieport" };
+static const char * const vfio_driver_whitelist[] = { "pci-stub" };
-static bool vfio_whitelisted_driver(struct device_driver *drv)
+static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
{
int i;
+ if (dev_is_pci(dev)) {
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
+ return true;
+ }
+
for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) {
if (!strcmp(drv->name, vfio_driver_whitelist[i]))
return true;
@@ -462,6 +626,7 @@ static bool vfio_whitelisted_driver(struct device_driver *drv)
* - driver-less
* - bound to a vfio driver
* - bound to a whitelisted driver
+ * - a PCI interconnect device
*
* We use two methods to determine whether a device is bound to a vfio
* driver. The first is to test whether the device exists in the vfio
@@ -486,7 +651,7 @@ static int vfio_dev_viable(struct device *dev, void *data)
}
mutex_unlock(&group->unbound_lock);
- if (!ret || !drv || vfio_whitelisted_driver(drv))
+ if (!ret || !drv || vfio_dev_whitelisted(dev, drv))
return 0;
device = vfio_group_get_device(group, dev);
@@ -621,7 +786,8 @@ int vfio_add_group_dev(struct device *dev,
group = vfio_group_get_from_iommu(iommu_group);
if (!group) {
- group = vfio_create_group(iommu_group);
+ group = vfio_create_group(iommu_group,
+ !iommu_present(dev->bus));
if (IS_ERR(group)) {
iommu_group_put(iommu_group);
return PTR_ERR(group);
@@ -692,11 +858,12 @@ EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
char *buf)
{
- struct vfio_device *device;
+ struct vfio_device *it, *device = NULL;
mutex_lock(&group->device_lock);
- list_for_each_entry(device, &group->device_list, group_next) {
- if (!strcmp(dev_name(device->dev), buf)) {
+ list_for_each_entry(it, &group->device_list, group_next) {
+ if (!strcmp(dev_name(it->dev), buf)) {
+ device = it;
vfio_device_get(device);
break;
}
@@ -832,8 +999,7 @@ static long vfio_ioctl_check_extension(struct vfio_container *container,
*/
if (!driver) {
mutex_lock(&vfio.iommu_drivers_lock);
- list_for_each_entry(driver, &vfio.iommu_drivers_list,
- vfio_next) {
+ vfio_for_each_iommu_driver(container, driver) {
if (!try_module_get(driver->ops->owner))
continue;
@@ -902,7 +1068,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
}
mutex_lock(&vfio.iommu_drivers_lock);
- list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) {
+ vfio_for_each_iommu_driver(container, driver) {
void *data;
if (!try_module_get(driver->ops->owner))
@@ -1167,6 +1333,9 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
if (atomic_read(&group->container_users))
return -EINVAL;
+ if (group->noiommu && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
f = fdget(container_fd);
if (!f.file)
return -EBADF;
@@ -1182,6 +1351,13 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
down_write(&container->group_lock);
+ /* Real groups and fake groups cannot mix */
+ if (!list_empty(&container->group_list) &&
+ container->noiommu != group->noiommu) {
+ ret = -EPERM;
+ goto unlock_out;
+ }
+
driver = container->iommu_driver;
if (driver) {
ret = driver->ops->attach_group(container->iommu_data,
@@ -1191,6 +1367,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
}
group->container = container;
+ container->noiommu = group->noiommu;
list_add(&group->container_next, &container->group_list);
/* Get a reference on the container and mark a user within the group */
@@ -1221,6 +1398,9 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
!group->container->iommu_driver || !vfio_group_viable(group))
return -EINVAL;
+ if (group->noiommu && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
device = vfio_device_get_from_name(group, buf);
if (!device)
return -ENODEV;
@@ -1263,6 +1443,10 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
fd_install(ret, filep);
+ if (group->noiommu)
+ dev_warn(device->dev, "vfio-noiommu device opened by user "
+ "(%s:%d)\n", current->comm, task_pid_nr(current));
+
return ret;
}
@@ -1351,6 +1535,11 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
if (!group)
return -ENODEV;
+ if (group->noiommu && !capable(CAP_SYS_RAWIO)) {
+ vfio_group_put(group);
+ return -EPERM;
+ }
+
/* Do we need multiple instances of the group open? Seems not. */
opened = atomic_cmpxchg(&group->opened, 0, 1);
if (opened) {
@@ -1513,6 +1702,11 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
if (!atomic_inc_not_zero(&group->container_users))
return ERR_PTR(-EINVAL);
+ if (group->noiommu) {
+ atomic_dec(&group->container_users);
+ return ERR_PTR(-EPERM);
+ }
+
if (!group->container->iommu_driver ||
!vfio_group_viable(group)) {
atomic_dec(&group->container_users);
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 57d8c37a002b..59d47cb638d5 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -403,13 +403,26 @@ static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu)
{
struct vfio_domain *domain;
- unsigned long bitmap = PAGE_MASK;
+ unsigned long bitmap = ULONG_MAX;
mutex_lock(&iommu->lock);
list_for_each_entry(domain, &iommu->domain_list, next)
bitmap &= domain->domain->ops->pgsize_bitmap;
mutex_unlock(&iommu->lock);
+ /*
+ * In case the IOMMU supports page sizes smaller than PAGE_SIZE
+ * we pretend PAGE_SIZE is supported and hide sub-PAGE_SIZE sizes.
+ * That way the user will be able to map/unmap buffers whose size/
+ * start address is aligned with PAGE_SIZE. Pinning code uses that
+ * granularity while iommu driver can use the sub-PAGE_SIZE size
+ * to map the buffer.
+ */
+ if (bitmap & ~PAGE_MASK) {
+ bitmap &= PAGE_MASK;
+ bitmap |= PAGE_SIZE;
+ }
+
return bitmap;
}
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index e25a23692822..29cfc57d496e 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -42,8 +42,6 @@
#include <scsi/scsi_proto.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
#include <linux/vhost.h>
#include <linux/virtio_scsi.h>
#include <linux/llist.h>
@@ -1684,11 +1682,10 @@ static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus,
}
}
-static ssize_t vhost_scsi_tpg_attrib_store_fabric_prot_type(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_store(
+ struct config_item *item, const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
unsigned long val;
@@ -1707,19 +1704,20 @@ static ssize_t vhost_scsi_tpg_attrib_store_fabric_prot_type(
return count;
}
-static ssize_t vhost_scsi_tpg_attrib_show_fabric_prot_type(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_show(
+ struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = attrib_to_tpg(item);
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
return sprintf(page, "%d\n", tpg->tv_fabric_prot_type);
}
-TF_TPG_ATTRIB_ATTR(vhost_scsi, fabric_prot_type, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR(vhost_scsi_tpg_attrib_, fabric_prot_type);
static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = {
- &vhost_scsi_tpg_attrib_fabric_prot_type.attr,
+ &vhost_scsi_tpg_attrib_attr_fabric_prot_type,
NULL,
};
@@ -1867,9 +1865,9 @@ static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg)
return 0;
}
-static ssize_t vhost_scsi_tpg_show_nexus(struct se_portal_group *se_tpg,
- char *page)
+static ssize_t vhost_scsi_tpg_nexus_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
struct vhost_scsi_nexus *tv_nexus;
@@ -1888,10 +1886,10 @@ static ssize_t vhost_scsi_tpg_show_nexus(struct se_portal_group *se_tpg,
return ret;
}
-static ssize_t vhost_scsi_tpg_store_nexus(struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t vhost_scsi_tpg_nexus_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
struct vhost_scsi_tport *tport_wwn = tpg->tport;
@@ -1966,10 +1964,10 @@ check_newline:
return count;
}
-TF_TPG_BASE_ATTR(vhost_scsi, nexus, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(vhost_scsi_tpg_, nexus);
static struct configfs_attribute *vhost_scsi_tpg_attrs[] = {
- &vhost_scsi_tpg_nexus.attr,
+ &vhost_scsi_tpg_attr_nexus,
NULL,
};
@@ -2105,18 +2103,17 @@ static void vhost_scsi_drop_tport(struct se_wwn *wwn)
}
static ssize_t
-vhost_scsi_wwn_show_attr_version(struct target_fabric_configfs *tf,
- char *page)
+vhost_scsi_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "TCM_VHOST fabric module %s on %s/%s"
"on "UTS_RELEASE"\n", VHOST_SCSI_VERSION, utsname()->sysname,
utsname()->machine);
}
-TF_WWN_ATTR_RO(vhost_scsi, version);
+CONFIGFS_ATTR_RO(vhost_scsi_wwn_, version);
static struct configfs_attribute *vhost_scsi_wwn_attrs[] = {
- &vhost_scsi_wwn_version.attr,
+ &vhost_scsi_wwn_attr_version,
NULL,
};
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 4772862b71a7..d3f767448a72 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -183,10 +183,17 @@ static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
return vq->acked_features & (1ULL << bit);
}
+#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
{
return vq->is_le;
}
+#else
+static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
+{
+ return virtio_legacy_is_little_endian() || vq->is_le;
+}
+#endif
/* Memory accessors */
static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index 2da5862876d1..6d8dc2c77520 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -180,6 +180,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
data->iset = PM8606_WLED_CURRENT(iset);
of_property_read_u32(np, "marvell,88pm860x-pwm",
&data->pwm);
+ of_node_put(np);
break;
}
}
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 71147f4461b8..98ffe71e8af2 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -819,4 +819,3 @@ module_i2c_driver(adp8860_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADP8860 Backlight driver");
-MODULE_ALIAS("i2c:adp8860-backlight");
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 037e43083343..9d738352d7d4 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -992,4 +992,3 @@ module_i2c_driver(adp8870_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADP8870 Backlight driver");
-MODULE_ALIAS("i2c:adp8870-backlight");
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index 5f897f99cc9b..5cca8ce45d4d 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -556,7 +556,6 @@ static void ams369fg06_shutdown(struct spi_device *spi)
static struct spi_driver ams369fg06_driver = {
.driver = {
.name = "ams369fg06",
- .owner = THIS_MODULE,
.pm = &ams369fg06_pm_ops,
},
.probe = ams369fg06_probe,
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index d7c37a8ccd1f..d7c239ea3d09 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -598,7 +598,6 @@ static int corgi_lcd_remove(struct spi_device *spi)
static struct spi_driver corgi_lcd_driver = {
.driver = {
.name = "corgi-lcd",
- .owner = THIS_MODULE,
.pm = &corgi_lcd_pm_ops,
},
.probe = corgi_lcd_probe,
diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c
index e7f0890cc211..a9e9cef20ed6 100644
--- a/drivers/video/backlight/ili922x.c
+++ b/drivers/video/backlight/ili922x.c
@@ -536,7 +536,6 @@ static int ili922x_remove(struct spi_device *spi)
static struct spi_driver ili922x_driver = {
.driver = {
.name = "ili922x",
- .owner = THIS_MODULE,
},
.probe = ili922x_probe,
.remove = ili922x_remove,
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 5fa2649c9631..e6054e2492c5 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -255,7 +255,6 @@ static void l4f00242t03_shutdown(struct spi_device *spi)
static struct spi_driver l4f00242t03_driver = {
.driver = {
.name = "l4f00242t03",
- .owner = THIS_MODULE,
},
.probe = l4f00242t03_probe,
.remove = l4f00242t03_remove,
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index f71eaf10c4eb..677f8abba27c 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -797,7 +797,6 @@ static void ld9040_shutdown(struct spi_device *spi)
static struct spi_driver ld9040_driver = {
.driver = {
.name = "ld9040",
- .owner = THIS_MODULE,
.pm = &ld9040_pm_ops,
},
.probe = ld9040_probe,
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index 14590c54aedf..4237aaa7f269 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -192,7 +192,6 @@ static int lms283gf05_probe(struct spi_device *spi)
static struct spi_driver lms283gf05_driver = {
.driver = {
.name = "lms283gf05",
- .owner = THIS_MODULE,
},
.probe = lms283gf05_probe,
};
diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c
index 7e3810308c3e..8aa3e7662496 100644
--- a/drivers/video/backlight/lms501kf03.c
+++ b/drivers/video/backlight/lms501kf03.c
@@ -422,7 +422,6 @@ static void lms501kf03_shutdown(struct spi_device *spi)
static struct spi_driver lms501kf03_driver = {
.driver = {
.name = "lms501kf03",
- .owner = THIS_MODULE,
.pm = &lms501kf03_pm_ops,
},
.probe = lms501kf03_probe,
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index f88df9ec08d0..daca9e6a2bb3 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -283,6 +283,7 @@ static int lp855x_backlight_register(struct lp855x *lp)
struct lp855x_platform_data *pdata = lp->pdata;
const char *name = pdata->name ? : DEFAULT_BL_NAME;
+ memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = MAX_BRIGHTNESS;
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 383f550e165e..885612cc1008 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -295,7 +295,6 @@ static void ltv350qv_shutdown(struct spi_device *spi)
static struct spi_driver ltv350qv_driver = {
.driver = {
.name = "ltv350qv",
- .owner = THIS_MODULE,
.pm = &ltv350qv_pm_ops,
},
diff --git a/drivers/video/backlight/pm8941-wled.c b/drivers/video/backlight/pm8941-wled.c
index c704c3236034..0b6d21955d91 100644
--- a/drivers/video/backlight/pm8941-wled.c
+++ b/drivers/video/backlight/pm8941-wled.c
@@ -17,6 +17,9 @@
#include <linux/of_device.h>
#include <linux/regmap.h>
+/* From DT binding */
+#define PM8941_WLED_DEFAULT_BRIGHTNESS 2048
+
#define PM8941_WLED_REG_VAL_BASE 0x40
#define PM8941_WLED_REG_VAL_MAX 0xFFF
@@ -373,6 +376,7 @@ static int pm8941_wled_probe(struct platform_device *pdev)
struct backlight_device *bl;
struct pm8941_wled *wled;
struct regmap *regmap;
+ u32 val;
int rc;
regmap = dev_get_regmap(pdev->dev.parent, NULL);
@@ -395,16 +399,17 @@ static int pm8941_wled_probe(struct platform_device *pdev)
if (rc)
return rc;
+ val = PM8941_WLED_DEFAULT_BRIGHTNESS;
+ of_property_read_u32(pdev->dev.of_node, "default-brightness", &val);
+
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
+ props.brightness = val;
props.max_brightness = PM8941_WLED_REG_VAL_MAX;
bl = devm_backlight_device_register(&pdev->dev, wled->name,
&pdev->dev, wled,
&pm8941_wled_ops, &props);
- if (IS_ERR(bl))
- return PTR_ERR(bl);
-
- return 0;
+ return PTR_ERR_OR_ZERO(bl);
};
static const struct of_device_id pm8941_wled_match_table[] = {
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index eff379b234cc..ae3c6b6fd5db 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -271,19 +271,18 @@ static int pwm_backlight_probe(struct platform_device *pdev)
}
pb->pwm = devm_pwm_get(&pdev->dev, NULL);
- if (IS_ERR(pb->pwm)) {
- ret = PTR_ERR(pb->pwm);
- if (ret == -EPROBE_DEFER)
- goto err_alloc;
-
+ if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER
+ && !pdev->dev.of_node) {
dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
pb->legacy = true;
pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
- if (IS_ERR(pb->pwm)) {
- dev_err(&pdev->dev, "unable to request legacy PWM\n");
- ret = PTR_ERR(pb->pwm);
- goto err_alloc;
- }
+ }
+
+ if (IS_ERR(pb->pwm)) {
+ ret = PTR_ERR(pb->pwm);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "unable to request PWM\n");
+ goto err_alloc;
}
dev_dbg(&pdev->dev, "got pwm for backlight\n");
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 28bfa127fee4..3c4a22a3063a 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -842,7 +842,6 @@ static void s6e63m0_shutdown(struct spi_device *spi)
static struct spi_driver s6e63m0_driver = {
.driver = {
.name = "s6e63m0",
- .owner = THIS_MODULE,
.pm = &s6e63m0_pm_ops,
},
.probe = s6e63m0_probe,
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 30afce33ef2a..eab1f842f9c0 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -437,7 +437,6 @@ static void tdo24m_shutdown(struct spi_device *spi)
static struct spi_driver tdo24m_driver = {
.driver = {
.name = "tdo24m",
- .owner = THIS_MODULE,
.pm = &tdo24m_pm_ops,
},
.probe = tdo24m_probe,
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index f08d641ccd01..6a41ea92737a 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -263,7 +263,6 @@ static SIMPLE_DEV_PM_OPS(tosa_lcd_pm_ops, tosa_lcd_suspend, tosa_lcd_resume);
static struct spi_driver tosa_lcd_driver = {
.driver = {
.name = "tosa-lcd",
- .owner = THIS_MODULE,
.pm = &tosa_lcd_pm_ops,
},
.probe = tosa_lcd_probe,
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index d538947a67d3..242a9948f57f 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -251,7 +251,6 @@ static SIMPLE_DEV_PM_OPS(vgg2432a4_pm_ops, vgg2432a4_suspend, vgg2432a4_resume);
static struct spi_driver vgg2432a4_driver = {
.driver = {
.name = "VGG2432A4",
- .owner = THIS_MODULE,
.pm = &vgg2432a4_pm_ops,
},
.probe = vgg2432a4_probe,
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 1aaf89300621..92f394927f24 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1093,6 +1093,7 @@ static void fbcon_init(struct vc_data *vc, int init)
con_copy_unimap(vc, svc);
ops = info->fbcon_par;
+ ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
p->con_rotate = initial_rotation;
set_blitting_type(vc, info);
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 8b1d371b5404..e6d16d65e4e6 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1666,6 +1666,8 @@ config FB_TRIDENT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select FB_DDC
+ select FB_MODE_HELPERS
---help---
This is the frame buffer device driver for Trident PCI/AGP chipsets.
Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
@@ -2132,7 +2134,7 @@ config FB_UDL
config FB_IBM_GXT4500
tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
- depends on FB && PPC
+ depends on FB
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -2140,7 +2142,8 @@ config FB_IBM_GXT4500
Say Y here to enable support for the IBM GXT4000P/6000P and
GXT4500P/6500P display adaptor based on Raster Engine RC1000,
found on some IBM System P (pSeries) machines. This driver
- doesn't use Geometry Engine GT1000.
+ doesn't use Geometry Engine GT1000. This driver also supports
+ AGP Fire GL2/3/4 cards on x86.
config FB_PS3
tristate "PS3 GPU framebuffer driver"
diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c
index 2bdb070707e4..ce0b1d05a388 100644
--- a/drivers/video/fbdev/aty/radeon_base.c
+++ b/drivers/video/fbdev/aty/radeon_base.c
@@ -276,9 +276,138 @@ static int backlight = 1;
static int backlight = 0;
#endif
-/*
- * prototypes
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mechanism. At this point, interrupts are off
+ * and scheduling is not permitted
*/
+void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+ if (rinfo->no_schedule || oops_in_progress)
+ mdelay(ms);
+ else
+ msleep(ms);
+}
+
+void radeon_pll_errata_after_index_slow(struct radeonfb_info *rinfo)
+{
+ /* Called if (rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS) is set */
+ (void)INREG(CLOCK_CNTL_DATA);
+ (void)INREG(CRTC_GEN_CNTL);
+}
+
+void radeon_pll_errata_after_data_slow(struct radeonfb_info *rinfo)
+{
+ if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+ /* we can't deal with posted writes here ... */
+ _radeon_msleep(rinfo, 5);
+ }
+ if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+ u32 save, tmp;
+ save = INREG(CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | PLL_WR_EN);
+ OUTREG(CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(CLOCK_CNTL_DATA);
+ OUTREG(CLOCK_CNTL_INDEX, save);
+ }
+}
+
+void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, u32 val, u32 mask)
+{
+ unsigned long flags;
+ unsigned int tmp;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
+ tmp = INREG(addr);
+ tmp &= (mask);
+ tmp |= (val);
+ OUTREG(addr, tmp);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+}
+
+u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+ u32 data;
+
+ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+ radeon_pll_errata_after_index(rinfo);
+ data = INREG(CLOCK_CNTL_DATA);
+ radeon_pll_errata_after_data(rinfo);
+ return data;
+}
+
+void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
+{
+ OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+ radeon_pll_errata_after_index(rinfo);
+ OUTREG(CLOCK_CNTL_DATA, val);
+ radeon_pll_errata_after_data(rinfo);
+}
+
+void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
+{
+ unsigned int tmp;
+
+ tmp = __INPLL(rinfo, index);
+ tmp &= (mask);
+ tmp |= (val);
+ __OUTPLL(rinfo, index, tmp);
+}
+
+void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+ int i;
+
+ for (i=0; i<2000000; i++) {
+ if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+}
+
+void radeon_engine_flush(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* Initiate flush */
+ OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+ ~RB2D_DC_FLUSH_ALL);
+
+ /* Ensure FIFO is empty, ie, make sure the flush commands
+ * has reached the cache
+ */
+ _radeon_fifo_wait(rinfo, 64);
+
+ /* Wait for the flush to complete */
+ for (i=0; i < 2000000; i++) {
+ if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: Flush Timeout !\n");
+}
+
+void _radeon_engine_idle(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* ensure FIFO is empty before waiting for idle */
+ _radeon_fifo_wait(rinfo, 64);
+
+ for (i=0; i<2000000; i++) {
+ if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
+ radeon_engine_flush(rinfo);
+ return;
+ }
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: Idle Timeout !\n");
+}
+
+
static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
{
diff --git a/drivers/video/fbdev/aty/radeonfb.h b/drivers/video/fbdev/aty/radeonfb.h
index 5bc1944ea1a9..962e31263225 100644
--- a/drivers/video/fbdev/aty/radeonfb.h
+++ b/drivers/video/fbdev/aty/radeonfb.h
@@ -370,20 +370,7 @@ struct radeonfb_info {
* IO macros
*/
-/* Note about this function: we have some rare cases where we must not schedule,
- * this typically happen with our special "wake up early" hook which allows us to
- * wake up the graphic chip (and thus get the console back) before everything else
- * on some machines that support that mechanism. At this point, interrupts are off
- * and scheduling is not permitted
- */
-static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
-{
- if (rinfo->no_schedule || oops_in_progress)
- mdelay(ms);
- else
- msleep(ms);
-}
-
+void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms);
#define INREG8(addr) readb((rinfo->mmio_base)+addr)
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
@@ -392,19 +379,7 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
#define INREG(addr) readl((rinfo->mmio_base)+addr)
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
-static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
- u32 val, u32 mask)
-{
- unsigned long flags;
- unsigned int tmp;
-
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- tmp = INREG(addr);
- tmp &= (mask);
- tmp |= (val);
- OUTREG(addr, tmp);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
-}
+void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, u32 val, u32 mask);
#define OUTREGP(addr,val,mask) _OUTREGP(rinfo, addr, val,mask)
@@ -425,64 +400,24 @@ static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
* possible exception to this rule is the call to unblank(), which may
* be done at irq time if an oops is in progress.
*/
+void radeon_pll_errata_after_index_slow(struct radeonfb_info *rinfo);
static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
{
- if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
- return;
-
- (void)INREG(CLOCK_CNTL_DATA);
- (void)INREG(CRTC_GEN_CNTL);
+ if (rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS)
+ radeon_pll_errata_after_index_slow(rinfo);
}
+void radeon_pll_errata_after_data_slow(struct radeonfb_info *rinfo);
static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
{
- if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
- /* we can't deal with posted writes here ... */
- _radeon_msleep(rinfo, 5);
- }
- if (rinfo->errata & CHIP_ERRATA_R300_CG) {
- u32 save, tmp;
- save = INREG(CLOCK_CNTL_INDEX);
- tmp = save & ~(0x3f | PLL_WR_EN);
- OUTREG(CLOCK_CNTL_INDEX, tmp);
- tmp = INREG(CLOCK_CNTL_DATA);
- OUTREG(CLOCK_CNTL_INDEX, save);
- }
-}
-
-static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
- u32 data;
-
- OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
- radeon_pll_errata_after_index(rinfo);
- data = INREG(CLOCK_CNTL_DATA);
- radeon_pll_errata_after_data(rinfo);
- return data;
-}
-
-static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
- u32 val)
-{
-
- OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
- radeon_pll_errata_after_index(rinfo);
- OUTREG(CLOCK_CNTL_DATA, val);
- radeon_pll_errata_after_data(rinfo);
-}
-
-
-static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
- u32 val, u32 mask)
-{
- unsigned int tmp;
-
- tmp = __INPLL(rinfo, index);
- tmp &= (mask);
- tmp |= (val);
- __OUTPLL(rinfo, index, tmp);
+ if (rinfo->errata & (CHIP_ERRATA_PLL_DELAY|CHIP_ERRATA_R300_CG))
+ radeon_pll_errata_after_data_slow(rinfo);
}
+u32 __INPLL(struct radeonfb_info *rinfo, u32 addr);
+void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val);
+void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask);
#define INPLL(addr) __INPLL(rinfo, addr)
#define OUTPLL(index, val) __OUTPLL(rinfo, index, val)
@@ -532,58 +467,9 @@ static inline u32 radeon_get_dstbpp(u16 depth)
* 2D Engine helper routines
*/
-static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
-{
- int i;
-
- for (i=0; i<2000000; i++) {
- if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
- return;
- udelay(1);
- }
- printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
-}
-
-static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
-{
- int i;
-
- /* Initiate flush */
- OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
- ~RB2D_DC_FLUSH_ALL);
-
- /* Ensure FIFO is empty, ie, make sure the flush commands
- * has reached the cache
- */
- _radeon_fifo_wait (rinfo, 64);
-
- /* Wait for the flush to complete */
- for (i=0; i < 2000000; i++) {
- if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
- return;
- udelay(1);
- }
- printk(KERN_ERR "radeonfb: Flush Timeout !\n");
-}
-
-
-static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
-{
- int i;
-
- /* ensure FIFO is empty before waiting for idle */
- _radeon_fifo_wait (rinfo, 64);
-
- for (i=0; i<2000000; i++) {
- if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
- radeon_engine_flush (rinfo);
- return;
- }
- udelay(1);
- }
- printk(KERN_ERR "radeonfb: Idle Timeout !\n");
-}
-
+void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries);
+void radeon_engine_flush(struct radeonfb_info *rinfo);
+void _radeon_engine_idle(struct radeonfb_info *rinfo);
#define radeon_engine_idle() _radeon_engine_idle(rinfo)
#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
diff --git a/drivers/video/fbdev/core/fb_ddc.c b/drivers/video/fbdev/core/fb_ddc.c
index 94322ccfedde..8bf5f2f54be7 100644
--- a/drivers/video/fbdev/core/fb_ddc.c
+++ b/drivers/video/fbdev/core/fb_ddc.c
@@ -67,13 +67,17 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
msleep(13);
algo_data->setscl(algo_data->data, 1);
- for (j = 0; j < 5; j++) {
- msleep(10);
- if (algo_data->getscl(algo_data->data))
- break;
+ if (algo_data->getscl) {
+ for (j = 0; j < 5; j++) {
+ msleep(10);
+ if (algo_data->getscl(algo_data->data))
+ break;
+ }
+ if (j == 5)
+ continue;
+ } else {
+ udelay(algo_data->udelay);
}
- if (j == 5)
- continue;
algo_data->setsda(algo_data->data, 0);
msleep(15);
@@ -89,10 +93,14 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
msleep(15);
algo_data->setscl(algo_data->data, 1);
- for (j = 0; j < 10; j++) {
- msleep(10);
- if (algo_data->getscl(algo_data->data))
- break;
+ if (algo_data->getscl) {
+ for (j = 0; j < 10; j++) {
+ msleep(10);
+ if (algo_data->getscl(algo_data->data))
+ break;
+ }
+ } else {
+ udelay(algo_data->udelay);
}
algo_data->setsda(algo_data->data, 1);
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 4bfff349b1fb..95d293b7445a 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -114,6 +114,20 @@ static int efifb_setup(char *options)
return 0;
}
+static inline bool fb_base_is_valid(void)
+{
+ if (screen_info.lfb_base)
+ return true;
+
+ if (!(screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE))
+ return false;
+
+ if (screen_info.ext_lfb_base)
+ return true;
+
+ return false;
+}
+
static int efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
@@ -141,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
screen_info.lfb_depth = 32;
if (!screen_info.pages)
screen_info.pages = 1;
- if (!screen_info.lfb_base) {
+ if (!fb_base_is_valid()) {
printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
return -ENODEV;
}
@@ -160,6 +174,14 @@ static int efifb_probe(struct platform_device *dev)
}
efifb_fix.smem_start = screen_info.lfb_base;
+
+ if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
+ u64 ext_lfb_base;
+
+ ext_lfb_base = (u64)(unsigned long)screen_info.ext_lfb_base << 32;
+ efifb_fix.smem_start |= ext_lfb_base;
+ }
+
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
efifb_defined.xres = screen_info.lfb_width;
efifb_defined.yres = screen_info.lfb_height;
diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c
index f19133a80e8c..f438546290df 100644
--- a/drivers/video/fbdev/gxt4500.c
+++ b/drivers/video/fbdev/gxt4500.c
@@ -142,7 +142,7 @@ static const unsigned char watfmt[] = {
struct gxt4500_par {
void __iomem *regs;
-
+ int wc_cookie;
int pixfmt; /* pixel format, see DFA_PIX_* values */
/* PLL parameters */
@@ -347,11 +347,12 @@ static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var,
break;
}
if (pixfmt != DFA_PIX_8BIT) {
- var->green.offset = var->red.length;
- var->blue.offset = var->green.offset + var->green.length;
+ var->blue.offset = 0;
+ var->green.offset = var->blue.length;
+ var->red.offset = var->green.offset + var->green.length;
if (var->transp.length)
var->transp.offset =
- var->blue.offset + var->blue.length;
+ var->red.offset + var->red.length;
}
}
@@ -525,7 +526,7 @@ static int gxt4500_setcolreg(unsigned int reg, unsigned int red,
u32 val = reg;
switch (par->pixfmt) {
case DFA_PIX_16BIT_565:
- val |= (reg << 11) | (reg << 6);
+ val |= (reg << 11) | (reg << 5);
break;
case DFA_PIX_16BIT_1555:
val |= (reg << 10) | (reg << 5);
@@ -670,11 +671,22 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, info);
+ par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
+ info->fix.smem_len);
+
+#ifdef __BIG_ENDIAN
/* Set byte-swapping for DFA aperture for all pixel sizes */
pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300);
+#else /* __LITTLE_ENDIAN */
+ /* not sure what this means but fgl23 driver does that */
+ pci_write_config_dword(pdev, CFG_ENDIAN0, 0x2300);
+/* pci_write_config_dword(pdev, CFG_ENDIAN0 + 4, 0x400000);*/
+ pci_write_config_dword(pdev, CFG_ENDIAN0 + 8, 0x98530000);
+#endif
info->fbops = &gxt4500_ops;
- info->flags = FBINFO_FLAG_DEFAULT;
+ info->flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_XPAN |
+ FBINFO_HWACCEL_YPAN;
err = fb_alloc_cmap(&info->cmap, 256, 0);
if (err) {
@@ -727,6 +739,7 @@ static void gxt4500_remove(struct pci_dev *pdev)
return;
par = info->par;
unregister_framebuffer(info);
+ arch_phys_wc_del(par->wc_cookie);
fb_dealloc_cmap(&info->cmap);
iounmap(par->regs);
iounmap(info->screen_base);
diff --git a/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
index 998978b08f5e..f7e85d1c9f9c 100644
--- a/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
+++ b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
@@ -175,7 +175,6 @@ static int tpohvga_probe(struct spi_device *spi)
static struct spi_driver panel_tpohvga_driver = {
.driver = {
.name = "tpo-hvga",
- .owner = THIS_MODULE,
},
.probe = tpohvga_probe,
};
diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c
index 803fee618d57..0e4cee9a8d79 100644
--- a/drivers/video/fbdev/omap/lcd_mipid.c
+++ b/drivers/video/fbdev/omap/lcd_mipid.c
@@ -603,7 +603,6 @@ static int mipid_spi_remove(struct spi_device *spi)
static struct spi_driver mipid_spi_driver = {
.driver = {
.name = MIPID_MODULE_NAME,
- .owner = THIS_MODULE,
},
.probe = mipid_spi_probe,
.remove = mipid_spi_remove,
diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
index 1fb3ea3c98a1..393ae1bc07e8 100644
--- a/drivers/video/fbdev/omap/omapfb_main.c
+++ b/drivers/video/fbdev/omap/omapfb_main.c
@@ -276,11 +276,6 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
if (r != 0)
break;
- if (regno < 0) {
- r = -EINVAL;
- break;
- }
-
if (regno < 16) {
u16 pal;
pal = ((red >> (16 - var->red.length)) <<
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
index 6a1b6a89a928..18eb60e9c9ec 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
@@ -391,7 +391,6 @@ static struct spi_driver lb035q02_spi_driver = {
.remove = lb035q02_panel_spi_remove,
.driver = {
.name = "panel_lgphilips_lb035q02",
- .owner = THIS_MODULE,
.of_match_table = lb035q02_of_match,
.suppress_bind_attrs = true,
},
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
index ccf3f4f3c703..8a928c9a2fc9 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
@@ -421,7 +421,6 @@ MODULE_DEVICE_TABLE(of, nec_8048_of_match);
static struct spi_driver nec_8048_driver = {
.driver = {
.name = "panel-nec-nl8048hl11",
- .owner = THIS_MODULE,
.pm = NEC_8048_PM_OPS,
.of_match_table = nec_8048_of_match,
.suppress_bind_attrs = true,
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
index c581231c74a5..31efcca801bd 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
@@ -903,7 +903,6 @@ MODULE_DEVICE_TABLE(of, acx565akm_of_match);
static struct spi_driver acx565akm_driver = {
.driver = {
.name = "acx565akm",
- .owner = THIS_MODULE,
.of_match_table = acx565akm_of_match,
.suppress_bind_attrs = true,
},
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
index 9edc51133c59..4d657f3ab679 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
@@ -498,7 +498,6 @@ static struct spi_driver td028ttec1_spi_driver = {
.driver = {
.name = "panel-tpo-td028ttec1",
- .owner = THIS_MODULE,
.of_match_table = td028ttec1_of_match,
.suppress_bind_attrs = true,
},
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
index 79e4a029aab9..68e3b68a2920 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
@@ -670,7 +670,6 @@ MODULE_DEVICE_TABLE(of, tpo_td043_of_match);
static struct spi_driver tpo_td043_spi_driver = {
.driver = {
.name = "panel-tpo-td043mtea1",
- .owner = THIS_MODULE,
.pm = &tpo_td043_spi_pm,
.of_match_table = tpo_td043_of_match,
.suppress_bind_attrs = true,
diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h
index e4a32fe77b02..53616b02b613 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi.h
@@ -351,13 +351,20 @@ struct omap_hdmi {
struct regulator *vdda_reg;
bool core_enabled;
- bool display_enabled;
struct omap_dss_device output;
struct platform_device *audio_pdev;
void (*audio_abort_cb)(struct device *dev);
int wp_idlemode;
+
+ bool audio_configured;
+ struct omap_dss_audio audio_config;
+
+ /* This lock should be taken when booleans bellow are touched. */
+ spinlock_t audio_playing_lock;
+ bool audio_playing;
+ bool display_enabled;
};
#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c
index 6d3aa3f51c20..94c8d5549b4c 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
@@ -321,9 +321,22 @@ static int read_edid(u8 *buf, int len)
return r;
}
+static void hdmi_start_audio_stream(struct omap_hdmi *hd)
+{
+ hdmi_wp_audio_enable(&hd->wp, true);
+ hdmi4_audio_start(&hd->core, &hd->wp);
+}
+
+static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
+{
+ hdmi4_audio_stop(&hd->core, &hd->wp);
+ hdmi_wp_audio_enable(&hd->wp, false);
+}
+
static int hdmi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &hdmi.output;
+ unsigned long flags;
int r = 0;
DSSDBG("ENTER hdmi_display_enable\n");
@@ -342,7 +355,21 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
goto err0;
}
+ if (hdmi.audio_configured) {
+ r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
+ hdmi.cfg.timings.pixelclock);
+ if (r) {
+ DSSERR("Error restoring audio configuration: %d", r);
+ hdmi.audio_abort_cb(&hdmi.pdev->dev);
+ hdmi.audio_configured = false;
+ }
+ }
+
+ spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
+ if (hdmi.audio_configured && hdmi.audio_playing)
+ hdmi_start_audio_stream(&hdmi);
hdmi.display_enabled = true;
+ spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
mutex_unlock(&hdmi.lock);
return 0;
@@ -354,17 +381,19 @@ err0:
static void hdmi_display_disable(struct omap_dss_device *dssdev)
{
+ unsigned long flags;
+
DSSDBG("Enter hdmi_display_disable\n");
mutex_lock(&hdmi.lock);
- if (hdmi.audio_pdev && hdmi.audio_abort_cb)
- hdmi.audio_abort_cb(&hdmi.audio_pdev->dev);
+ spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
+ hdmi_stop_audio_stream(&hdmi);
+ hdmi.display_enabled = false;
+ spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
hdmi_power_off_full(dssdev);
- hdmi.display_enabled = false;
-
mutex_unlock(&hdmi.lock);
}
@@ -568,6 +597,8 @@ static int hdmi_audio_shutdown(struct device *dev)
mutex_lock(&hd->lock);
hd->audio_abort_cb = NULL;
+ hd->audio_configured = false;
+ hd->audio_playing = false;
mutex_unlock(&hd->lock);
return 0;
@@ -576,25 +607,34 @@ static int hdmi_audio_shutdown(struct device *dev)
static int hdmi_audio_start(struct device *dev)
{
struct omap_hdmi *hd = dev_get_drvdata(dev);
+ unsigned long flags;
WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
- WARN_ON(!hd->display_enabled);
- hdmi_wp_audio_enable(&hd->wp, true);
- hdmi4_audio_start(&hd->core, &hd->wp);
+ spin_lock_irqsave(&hd->audio_playing_lock, flags);
+
+ if (hd->display_enabled)
+ hdmi_start_audio_stream(hd);
+ hd->audio_playing = true;
+ spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
return 0;
}
static void hdmi_audio_stop(struct device *dev)
{
struct omap_hdmi *hd = dev_get_drvdata(dev);
+ unsigned long flags;
WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
- WARN_ON(!hd->display_enabled);
- hdmi4_audio_stop(&hd->core, &hd->wp);
- hdmi_wp_audio_enable(&hd->wp, false);
+ spin_lock_irqsave(&hd->audio_playing_lock, flags);
+
+ if (hd->display_enabled)
+ hdmi_stop_audio_stream(hd);
+ hd->audio_playing = false;
+
+ spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
}
static int hdmi_audio_config(struct device *dev,
@@ -612,7 +652,10 @@ static int hdmi_audio_config(struct device *dev,
ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,
hd->cfg.timings.pixelclock);
-
+ if (!ret) {
+ hd->audio_configured = true;
+ hd->audio_config = *dss_audio;
+ }
out:
mutex_unlock(&hd->lock);
@@ -657,6 +700,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
dev_set_drvdata(&pdev->dev, &hdmi);
mutex_init(&hdmi.lock);
+ spin_lock_init(&hdmi.audio_playing_lock);
if (pdev->dev.of_node) {
r = hdmi_probe_of(pdev);
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c
index 7f875788edbc..b59ba7902be1 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi5.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi5.c
@@ -349,9 +349,24 @@ static int read_edid(u8 *buf, int len)
return r;
}
+static void hdmi_start_audio_stream(struct omap_hdmi *hd)
+{
+ REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+ hdmi_wp_audio_enable(&hd->wp, true);
+ hdmi_wp_audio_core_req_enable(&hd->wp, true);
+}
+
+static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
+{
+ hdmi_wp_audio_core_req_enable(&hd->wp, false);
+ hdmi_wp_audio_enable(&hd->wp, false);
+ REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
+}
+
static int hdmi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &hdmi.output;
+ unsigned long flags;
int r = 0;
DSSDBG("ENTER hdmi_display_enable\n");
@@ -370,7 +385,21 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
goto err0;
}
+ if (hdmi.audio_configured) {
+ r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
+ hdmi.cfg.timings.pixelclock);
+ if (r) {
+ DSSERR("Error restoring audio configuration: %d", r);
+ hdmi.audio_abort_cb(&hdmi.pdev->dev);
+ hdmi.audio_configured = false;
+ }
+ }
+
+ spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
+ if (hdmi.audio_configured && hdmi.audio_playing)
+ hdmi_start_audio_stream(&hdmi);
hdmi.display_enabled = true;
+ spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
mutex_unlock(&hdmi.lock);
return 0;
@@ -382,17 +411,19 @@ err0:
static void hdmi_display_disable(struct omap_dss_device *dssdev)
{
+ unsigned long flags;
+
DSSDBG("Enter hdmi_display_disable\n");
mutex_lock(&hdmi.lock);
- if (hdmi.audio_pdev && hdmi.audio_abort_cb)
- hdmi.audio_abort_cb(&hdmi.audio_pdev->dev);
+ spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
+ hdmi_stop_audio_stream(&hdmi);
+ hdmi.display_enabled = false;
+ spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
hdmi_power_off_full(dssdev);
- hdmi.display_enabled = false;
-
mutex_unlock(&hdmi.lock);
}
@@ -596,6 +627,8 @@ static int hdmi_audio_shutdown(struct device *dev)
mutex_lock(&hd->lock);
hd->audio_abort_cb = NULL;
+ hd->audio_configured = false;
+ hd->audio_playing = false;
mutex_unlock(&hd->lock);
return 0;
@@ -604,32 +637,34 @@ static int hdmi_audio_shutdown(struct device *dev)
static int hdmi_audio_start(struct device *dev)
{
struct omap_hdmi *hd = dev_get_drvdata(dev);
+ unsigned long flags;
WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
- WARN_ON(!hd->display_enabled);
- /* No-idle while playing audio, store the old value */
- hd->wp_idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
- REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+ spin_lock_irqsave(&hd->audio_playing_lock, flags);
- hdmi_wp_audio_enable(&hd->wp, true);
- hdmi_wp_audio_core_req_enable(&hd->wp, true);
+ if (hd->display_enabled)
+ hdmi_start_audio_stream(hd);
+ hd->audio_playing = true;
+ spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
return 0;
}
static void hdmi_audio_stop(struct device *dev)
{
struct omap_hdmi *hd = dev_get_drvdata(dev);
+ unsigned long flags;
WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
- WARN_ON(!hd->display_enabled);
- hdmi_wp_audio_core_req_enable(&hd->wp, false);
- hdmi_wp_audio_enable(&hd->wp, false);
+ spin_lock_irqsave(&hd->audio_playing_lock, flags);
+
+ if (hd->display_enabled)
+ hdmi_stop_audio_stream(hd);
+ hd->audio_playing = false;
- /* Playback stopped, restore original idlemode */
- REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
+ spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
}
static int hdmi_audio_config(struct device *dev,
@@ -648,6 +683,10 @@ static int hdmi_audio_config(struct device *dev,
ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
hd->cfg.timings.pixelclock);
+ if (!ret) {
+ hd->audio_configured = true;
+ hd->audio_config = *dss_audio;
+ }
out:
mutex_unlock(&hd->lock);
@@ -678,6 +717,11 @@ static int hdmi_audio_register(struct device *dev)
if (IS_ERR(hdmi.audio_pdev))
return PTR_ERR(hdmi.audio_pdev);
+ hdmi_runtime_get();
+ hdmi.wp_idlemode =
+ REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+ hdmi_runtime_put();
+
return 0;
}
@@ -692,6 +736,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
dev_set_drvdata(&pdev->dev, &hdmi);
mutex_init(&hdmi.lock);
+ spin_lock_init(&hdmi.audio_playing_lock);
if (pdev->dev.of_node) {
r = hdmi_probe_of(pdev);
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 93f4c902d0f9..fa3480815cdb 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -6,16 +6,16 @@
* Licensed under the GPLv2 or later.
*/
-#include <linux/module.h>
#include <linux/backlight.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
+#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pwm.h>
-#include <linux/delay.h>
+#include <linux/uaccess.h>
#define SSD1307FB_DATA 0x40
#define SSD1307FB_COMMAND 0x80
@@ -495,6 +495,12 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
.need_pwm = 1,
};
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1309_deviceinfo = {
+ .default_vcomh = 0x34,
+ .default_dclk_div = 1,
+ .default_dclk_frq = 10,
+};
+
static const struct of_device_id ssd1307fb_of_match[] = {
{
.compatible = "solomon,ssd1305fb-i2c",
@@ -508,6 +514,10 @@ static const struct of_device_id ssd1307fb_of_match[] = {
.compatible = "solomon,ssd1307fb-i2c",
.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
},
+ {
+ .compatible = "solomon,ssd1309fb-i2c",
+ .data = (void *)&ssd1307fb_ssd1309_deviceinfo,
+ },
{},
};
MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
@@ -709,6 +719,7 @@ static const struct i2c_device_id ssd1307fb_i2c_id[] = {
{ "ssd1305fb", 0 },
{ "ssd1306fb", 0 },
{ "ssd1307fb", 0 },
+ { "ssd1309fb", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c
index 01b43e9ce941..8a5bbc13082e 100644
--- a/drivers/video/fbdev/tridentfb.c
+++ b/drivers/video/fbdev/tridentfb.c
@@ -25,6 +25,9 @@
#include <video/vga.h>
#include <video/trident.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
struct tridentfb_par {
void __iomem *io_virt; /* iospace virtual memory address */
u32 pseudo_pal[16];
@@ -40,6 +43,9 @@ struct tridentfb_par {
(struct tridentfb_par *par, const char*,
u32, u32, u32, u32, u32, u32);
unsigned char eng_oper; /* engine operation... */
+ bool ddc_registered;
+ struct i2c_adapter ddc_adapter;
+ struct i2c_algo_bit_data ddc_algo;
};
static struct fb_fix_screeninfo tridentfb_fix = {
@@ -53,7 +59,7 @@ static struct fb_fix_screeninfo tridentfb_fix = {
/* defaults which are normally overriden by user values */
/* video mode */
-static char *mode_option = "640x480-8@60";
+static char *mode_option;
static int bpp = 8;
static int noaccel;
@@ -174,6 +180,121 @@ static inline u32 readmmr(struct tridentfb_par *par, u16 r)
return fb_readl(par->io_virt + r);
}
+#define DDC_SDA_TGUI BIT(0)
+#define DDC_SCL_TGUI BIT(1)
+#define DDC_SCL_DRIVE_TGUI BIT(2)
+#define DDC_SDA_DRIVE_TGUI BIT(3)
+#define DDC_MASK_TGUI (DDC_SCL_DRIVE_TGUI | DDC_SDA_DRIVE_TGUI)
+
+static void tridentfb_ddc_setscl_tgui(void *data, int val)
+{
+ struct tridentfb_par *par = data;
+ u8 reg = vga_mm_rcrt(par->io_virt, I2C) & DDC_MASK_TGUI;
+
+ if (val)
+ reg &= ~DDC_SCL_DRIVE_TGUI; /* disable drive - don't drive hi */
+ else
+ reg |= DDC_SCL_DRIVE_TGUI; /* drive low */
+
+ vga_mm_wcrt(par->io_virt, I2C, reg);
+}
+
+static void tridentfb_ddc_setsda_tgui(void *data, int val)
+{
+ struct tridentfb_par *par = data;
+ u8 reg = vga_mm_rcrt(par->io_virt, I2C) & DDC_MASK_TGUI;
+
+ if (val)
+ reg &= ~DDC_SDA_DRIVE_TGUI; /* disable drive - don't drive hi */
+ else
+ reg |= DDC_SDA_DRIVE_TGUI; /* drive low */
+
+ vga_mm_wcrt(par->io_virt, I2C, reg);
+}
+
+static int tridentfb_ddc_getsda_tgui(void *data)
+{
+ struct tridentfb_par *par = data;
+
+ return !!(vga_mm_rcrt(par->io_virt, I2C) & DDC_SDA_TGUI);
+}
+
+#define DDC_SDA_IN BIT(0)
+#define DDC_SCL_OUT BIT(1)
+#define DDC_SDA_OUT BIT(3)
+#define DDC_SCL_IN BIT(6)
+#define DDC_MASK (DDC_SCL_OUT | DDC_SDA_OUT)
+
+static void tridentfb_ddc_setscl(void *data, int val)
+{
+ struct tridentfb_par *par = data;
+ unsigned char reg;
+
+ reg = vga_mm_rcrt(par->io_virt, I2C) & DDC_MASK;
+ if (val)
+ reg |= DDC_SCL_OUT;
+ else
+ reg &= ~DDC_SCL_OUT;
+ vga_mm_wcrt(par->io_virt, I2C, reg);
+}
+
+static void tridentfb_ddc_setsda(void *data, int val)
+{
+ struct tridentfb_par *par = data;
+ unsigned char reg;
+
+ reg = vga_mm_rcrt(par->io_virt, I2C) & DDC_MASK;
+ if (!val)
+ reg |= DDC_SDA_OUT;
+ else
+ reg &= ~DDC_SDA_OUT;
+ vga_mm_wcrt(par->io_virt, I2C, reg);
+}
+
+static int tridentfb_ddc_getscl(void *data)
+{
+ struct tridentfb_par *par = data;
+
+ return !!(vga_mm_rcrt(par->io_virt, I2C) & DDC_SCL_IN);
+}
+
+static int tridentfb_ddc_getsda(void *data)
+{
+ struct tridentfb_par *par = data;
+
+ return !!(vga_mm_rcrt(par->io_virt, I2C) & DDC_SDA_IN);
+}
+
+static int tridentfb_setup_ddc_bus(struct fb_info *info)
+{
+ struct tridentfb_par *par = info->par;
+
+ strlcpy(par->ddc_adapter.name, info->fix.id,
+ sizeof(par->ddc_adapter.name));
+ par->ddc_adapter.owner = THIS_MODULE;
+ par->ddc_adapter.class = I2C_CLASS_DDC;
+ par->ddc_adapter.algo_data = &par->ddc_algo;
+ par->ddc_adapter.dev.parent = info->device;
+ if (is_oldclock(par->chip_id)) { /* not sure if this check is OK */
+ par->ddc_algo.setsda = tridentfb_ddc_setsda_tgui;
+ par->ddc_algo.setscl = tridentfb_ddc_setscl_tgui;
+ par->ddc_algo.getsda = tridentfb_ddc_getsda_tgui;
+ /* no getscl */
+ } else {
+ par->ddc_algo.setsda = tridentfb_ddc_setsda;
+ par->ddc_algo.setscl = tridentfb_ddc_setscl;
+ par->ddc_algo.getsda = tridentfb_ddc_getsda;
+ par->ddc_algo.getscl = tridentfb_ddc_getscl;
+ }
+ par->ddc_algo.udelay = 10;
+ par->ddc_algo.timeout = 20;
+ par->ddc_algo.data = par;
+
+ i2c_set_adapdata(&par->ddc_adapter, par);
+
+ return i2c_bit_add_bus(&par->ddc_adapter);
+}
+
/*
* Blade specific acceleration.
*/
@@ -1346,6 +1467,7 @@ static int trident_pci_probe(struct pci_dev *dev,
struct tridentfb_par *default_par;
int chip3D;
int chip_id;
+ bool found = false;
err = pci_enable_device(dev);
if (err)
@@ -1499,6 +1621,7 @@ static int trident_pci_probe(struct pci_dev *dev,
info->pixmap.scan_align = 1;
info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->var.bits_per_pixel = 8;
if (default_par->image_blit) {
info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
@@ -1511,11 +1634,56 @@ static int trident_pci_probe(struct pci_dev *dev,
info->pixmap.scan_align = 1;
}
- if (!fb_find_mode(&info->var, info,
- mode_option, NULL, 0, NULL, bpp)) {
- err = -EINVAL;
- goto out_unmap2;
+ if (tridentfb_setup_ddc_bus(info) == 0) {
+ u8 *edid = fb_ddc_read(&default_par->ddc_adapter);
+
+ default_par->ddc_registered = true;
+ if (edid) {
+ fb_edid_to_monspecs(edid, &info->monspecs);
+ kfree(edid);
+ if (!info->monspecs.modedb)
+ dev_err(info->device, "error getting mode database\n");
+ else {
+ const struct fb_videomode *m;
+
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ &info->modelist);
+ m = fb_find_best_display(&info->monspecs,
+ &info->modelist);
+ if (m) {
+ fb_videomode_to_var(&info->var, m);
+ /* fill all other info->var's fields */
+ if (tridentfb_check_var(&info->var,
+ info) == 0)
+ found = true;
+ }
+ }
+ }
}
+
+ if (!mode_option && !found)
+ mode_option = "640x480-8@60";
+
+ /* Prepare startup mode */
+ if (mode_option) {
+ err = fb_find_mode(&info->var, info, mode_option,
+ info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ NULL, info->var.bits_per_pixel);
+ if (!err || err == 4) {
+ err = -EINVAL;
+ dev_err(info->device, "mode %s not found\n",
+ mode_option);
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+ goto out_unmap2;
+ }
+ }
+
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
err = fb_alloc_cmap(&info->cmap, 256, 0);
if (err < 0)
goto out_unmap2;
@@ -1536,6 +1704,8 @@ static int trident_pci_probe(struct pci_dev *dev,
return 0;
out_unmap2:
+ if (default_par->ddc_registered)
+ i2c_del_adapter(&default_par->ddc_adapter);
kfree(info->pixmap.addr);
if (info->screen_base)
iounmap(info->screen_base);
@@ -1555,6 +1725,8 @@ static void trident_pci_remove(struct pci_dev *dev)
struct tridentfb_par *par = info->par;
unregister_framebuffer(info);
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
iounmap(par->io_virt);
iounmap(info->screen_base);
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c
index 6b70d7f62b2f..1c1e95a0b8fa 100644
--- a/drivers/video/fbdev/vermilion/vermilion.c
+++ b/drivers/video/fbdev/vermilion/vermilion.c
@@ -99,7 +99,7 @@ static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order,
* below the first 16MB.
*/
- flags = __GFP_DMA | __GFP_HIGH;
+ flags = __GFP_DMA | __GFP_HIGH | __GFP_KSWAPD_RECLAIM;
va->logical =
__get_free_pages(flags, --max_order);
} while (va->logical == 0 && max_order > min_order);
diff --git a/drivers/vme/vme_bridge.h b/drivers/vme/vme_bridge.h
index 397578a73883..b59cbee231dd 100644
--- a/drivers/vme/vme_bridge.h
+++ b/drivers/vme/vme_bridge.h
@@ -1,6 +1,8 @@
#ifndef _VME_BRIDGE_H_
#define _VME_BRIDGE_H_
+#include <linux/vme.h>
+
#define VME_CRCSR_BUF_SIZE (508*1024)
/*
* Resource structures
@@ -91,7 +93,7 @@ struct vme_callback {
struct vme_irq {
int count;
- struct vme_callback callback[255];
+ struct vme_callback callback[VME_NUM_STATUSID];
};
/* Allow 16 characters for name (including null character) */
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index e7d448963a24..0e2f43bccf1f 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/sched.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
#include "../w1.h"
#include "../w1_int.h"
@@ -27,21 +28,23 @@
#define OMAP_HDQ_TX_DATA 0x04
#define OMAP_HDQ_RX_DATA 0x08
#define OMAP_HDQ_CTRL_STATUS 0x0c
-#define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK (1<<6)
-#define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE (1<<5)
-#define OMAP_HDQ_CTRL_STATUS_GO (1<<4)
-#define OMAP_HDQ_CTRL_STATUS_INITIALIZATION (1<<2)
-#define OMAP_HDQ_CTRL_STATUS_DIR (1<<1)
-#define OMAP_HDQ_CTRL_STATUS_MODE (1<<0)
+#define OMAP_HDQ_CTRL_STATUS_SINGLE BIT(7)
+#define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK BIT(6)
+#define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE BIT(5)
+#define OMAP_HDQ_CTRL_STATUS_GO BIT(4)
+#define OMAP_HDQ_CTRL_STATUS_PRESENCE BIT(3)
+#define OMAP_HDQ_CTRL_STATUS_INITIALIZATION BIT(2)
+#define OMAP_HDQ_CTRL_STATUS_DIR BIT(1)
#define OMAP_HDQ_INT_STATUS 0x10
-#define OMAP_HDQ_INT_STATUS_TXCOMPLETE (1<<2)
-#define OMAP_HDQ_INT_STATUS_RXCOMPLETE (1<<1)
-#define OMAP_HDQ_INT_STATUS_TIMEOUT (1<<0)
+#define OMAP_HDQ_INT_STATUS_TXCOMPLETE BIT(2)
+#define OMAP_HDQ_INT_STATUS_RXCOMPLETE BIT(1)
+#define OMAP_HDQ_INT_STATUS_TIMEOUT BIT(0)
#define OMAP_HDQ_SYSCONFIG 0x14
-#define OMAP_HDQ_SYSCONFIG_SOFTRESET (1<<1)
-#define OMAP_HDQ_SYSCONFIG_AUTOIDLE (1<<0)
+#define OMAP_HDQ_SYSCONFIG_SOFTRESET BIT(1)
+#define OMAP_HDQ_SYSCONFIG_AUTOIDLE BIT(0)
+#define OMAP_HDQ_SYSCONFIG_NOIDLE 0x0
#define OMAP_HDQ_SYSSTATUS 0x18
-#define OMAP_HDQ_SYSSTATUS_RESETDONE (1<<0)
+#define OMAP_HDQ_SYSSTATUS_RESETDONE BIT(0)
#define OMAP_HDQ_FLAG_CLEAR 0
#define OMAP_HDQ_FLAG_SET 1
@@ -67,6 +70,10 @@ struct hdq_data {
* the data wrire or read.
*/
int init_trans;
+ int rrw;
+ /* mode: 0-HDQ 1-W1 */
+ int mode;
+
};
static int omap_hdq_probe(struct platform_device *pdev);
@@ -74,6 +81,7 @@ static int omap_hdq_remove(struct platform_device *pdev);
static const struct of_device_id omap_hdq_dt_ids[] = {
{ .compatible = "ti,omap3-1w" },
+ { .compatible = "ti,am4372-hdq" },
{}
};
MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids);
@@ -90,15 +98,12 @@ static struct platform_driver omap_hdq_driver = {
static u8 omap_w1_read_byte(void *_hdq);
static void omap_w1_write_byte(void *_hdq, u8 byte);
static u8 omap_w1_reset_bus(void *_hdq);
-static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
- u8 search_type, w1_slave_found_callback slave_found);
static struct w1_bus_master omap_w1_master = {
.read_byte = omap_w1_read_byte,
.write_byte = omap_w1_write_byte,
.reset_bus = omap_w1_reset_bus,
- .search = omap_w1_search_bus,
};
/* HDQ register I/O routines */
@@ -122,6 +127,15 @@ static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
return new_val;
}
+static void hdq_disable_interrupt(struct hdq_data *hdq_data, u32 offset,
+ u32 mask)
+{
+ u32 ie;
+
+ ie = readl(hdq_data->hdq_base + offset);
+ writel(ie & mask, hdq_data->hdq_base + offset);
+}
+
/*
* Wait for one or more bits in flag change.
* HDQ_FLAG_SET: wait until any bit in the flag is set.
@@ -229,13 +243,7 @@ static irqreturn_t hdq_isr(int irq, void *_hdq)
return IRQ_HANDLED;
}
-/* HDQ Mode: always return success */
-static u8 omap_w1_reset_bus(void *_hdq)
-{
- return 0;
-}
-
-/* W1 search callback function */
+/* W1 search callback function in HDQ mode */
static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
u8 search_type, w1_slave_found_callback slave_found)
{
@@ -262,9 +270,10 @@ static int _omap_hdq_reset(struct hdq_data *hdq_data)
int ret;
u8 tmp_status;
- hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET);
+ hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
+ OMAP_HDQ_SYSCONFIG_SOFTRESET);
/*
- * Select HDQ mode & enable clocks.
+ * Select HDQ/1W mode & enable clocks.
* It is observed that INT flags can't be cleared via a read and GO/INIT
* won't return to zero if interrupt is disabled. So we always enable
* interrupt.
@@ -282,7 +291,8 @@ static int _omap_hdq_reset(struct hdq_data *hdq_data)
else {
hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
- OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
+ OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK |
+ hdq_data->mode);
hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
OMAP_HDQ_SYSCONFIG_AUTOIDLE);
}
@@ -334,6 +344,18 @@ static int omap_hdq_break(struct hdq_data *hdq_data)
ret = -ETIMEDOUT;
goto out;
}
+
+ /*
+ * check for the presence detect bit to get
+ * set to show that the slave is responding
+ */
+ if (!(hdq_reg_in(hdq_data, OMAP_HDQ_CTRL_STATUS) &
+ OMAP_HDQ_CTRL_STATUS_PRESENCE)) {
+ dev_dbg(hdq_data->dev, "Presence bit not set\n");
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
/*
* wait for both INIT and GO bits rerurn to zero.
* zero wait time expected for interrupt mode.
@@ -368,6 +390,8 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)
goto out;
}
+ hdq_data->hdq_irqstatus = 0;
+
if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
@@ -400,7 +424,7 @@ rtn:
}
-/* Enable clocks and set the controller to HDQ mode */
+/* Enable clocks and set the controller to HDQ/1W mode */
static int omap_hdq_get(struct hdq_data *hdq_data)
{
int ret = 0;
@@ -422,7 +446,7 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
pm_runtime_get_sync(hdq_data->dev);
- /* make sure HDQ is out of reset */
+ /* make sure HDQ/1W is out of reset */
if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) &
OMAP_HDQ_SYSSTATUS_RESETDONE)) {
ret = _omap_hdq_reset(hdq_data);
@@ -430,12 +454,13 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
/* back up the count */
hdq_data->hdq_usecount--;
} else {
- /* select HDQ mode & enable clocks */
+ /* select HDQ/1W mode & enable clocks */
hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
- OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
+ OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK |
+ hdq_data->mode);
hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
- OMAP_HDQ_SYSCONFIG_AUTOIDLE);
+ OMAP_HDQ_SYSCONFIG_NOIDLE);
hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
}
}
@@ -456,6 +481,8 @@ static int omap_hdq_put(struct hdq_data *hdq_data)
if (ret < 0)
return -EINTR;
+ hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
+ OMAP_HDQ_SYSCONFIG_AUTOIDLE);
if (0 == hdq_data->hdq_usecount) {
dev_dbg(hdq_data->dev, "attempt to decrement use count"
" when it is zero");
@@ -471,6 +498,100 @@ static int omap_hdq_put(struct hdq_data *hdq_data)
return ret;
}
+/*
+ * W1 triplet callback function - used for searching ROM addresses.
+ * Registered only when controller is in 1-wire mode.
+ */
+static u8 omap_w1_triplet(void *_hdq, u8 bdir)
+{
+ u8 id_bit, comp_bit;
+ int err;
+ u8 ret = 0x3; /* no slaves responded */
+ struct hdq_data *hdq_data = _hdq;
+ u8 ctrl = OMAP_HDQ_CTRL_STATUS_SINGLE | OMAP_HDQ_CTRL_STATUS_GO |
+ OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK;
+ u8 mask = ctrl | OMAP_HDQ_CTRL_STATUS_DIR;
+
+ omap_hdq_get(_hdq);
+
+ err = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (err < 0) {
+ dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
+ goto rtn;
+ }
+
+ hdq_data->hdq_irqstatus = 0;
+ /* read id_bit */
+ hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS,
+ ctrl | OMAP_HDQ_CTRL_STATUS_DIR, mask);
+ err = wait_event_timeout(hdq_wait_queue,
+ (hdq_data->hdq_irqstatus
+ & OMAP_HDQ_INT_STATUS_RXCOMPLETE),
+ OMAP_HDQ_TIMEOUT);
+ if (err == 0) {
+ dev_dbg(hdq_data->dev, "RX wait elapsed\n");
+ goto out;
+ }
+ id_bit = (hdq_reg_in(_hdq, OMAP_HDQ_RX_DATA) & 0x01);
+
+ hdq_data->hdq_irqstatus = 0;
+ /* read comp_bit */
+ hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS,
+ ctrl | OMAP_HDQ_CTRL_STATUS_DIR, mask);
+ err = wait_event_timeout(hdq_wait_queue,
+ (hdq_data->hdq_irqstatus
+ & OMAP_HDQ_INT_STATUS_RXCOMPLETE),
+ OMAP_HDQ_TIMEOUT);
+ if (err == 0) {
+ dev_dbg(hdq_data->dev, "RX wait elapsed\n");
+ goto out;
+ }
+ comp_bit = (hdq_reg_in(_hdq, OMAP_HDQ_RX_DATA) & 0x01);
+
+ if (id_bit && comp_bit) {
+ ret = 0x03; /* no slaves responded */
+ goto out;
+ }
+ if (!id_bit && !comp_bit) {
+ /* Both bits are valid, take the direction given */
+ ret = bdir ? 0x04 : 0;
+ } else {
+ /* Only one bit is valid, take that direction */
+ bdir = id_bit;
+ ret = id_bit ? 0x05 : 0x02;
+ }
+
+ /* write bdir bit */
+ hdq_reg_out(_hdq, OMAP_HDQ_TX_DATA, bdir);
+ hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS, ctrl, mask);
+ err = wait_event_timeout(hdq_wait_queue,
+ (hdq_data->hdq_irqstatus
+ & OMAP_HDQ_INT_STATUS_TXCOMPLETE),
+ OMAP_HDQ_TIMEOUT);
+ if (err == 0) {
+ dev_dbg(hdq_data->dev, "TX wait elapsed\n");
+ goto out;
+ }
+
+ hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS, 0,
+ OMAP_HDQ_CTRL_STATUS_SINGLE);
+
+out:
+ mutex_unlock(&hdq_data->hdq_mutex);
+rtn:
+ omap_hdq_put(_hdq);
+ return ret;
+}
+
+/* reset callback */
+static u8 omap_w1_reset_bus(void *_hdq)
+{
+ omap_hdq_get(_hdq);
+ omap_hdq_break(_hdq);
+ omap_hdq_put(_hdq);
+ return 0;
+}
+
/* Read a byte of data from the device */
static u8 omap_w1_read_byte(void *_hdq)
{
@@ -478,6 +599,10 @@ static u8 omap_w1_read_byte(void *_hdq)
u8 val = 0;
int ret;
+ /* First write to initialize the transfer */
+ if (hdq_data->init_trans == 0)
+ omap_hdq_get(hdq_data);
+
ret = hdq_read_byte(hdq_data, &val);
if (ret) {
ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
@@ -491,6 +616,10 @@ static u8 omap_w1_read_byte(void *_hdq)
return -1;
}
+ hdq_disable_interrupt(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ ~OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
+ hdq_data->hdq_usecount = 0;
+
/* Write followed by a read, release the module */
if (hdq_data->init_trans) {
ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
@@ -517,6 +646,14 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
if (hdq_data->init_trans == 0)
omap_hdq_get(hdq_data);
+ /*
+ * We need to reset the slave before
+ * issuing the SKIP ROM command, else
+ * the slave will not work.
+ */
+ if (byte == W1_SKIP_ROM)
+ omap_hdq_break(hdq_data);
+
ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
if (ret < 0) {
dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
@@ -551,6 +688,7 @@ static int omap_hdq_probe(struct platform_device *pdev)
struct resource *res;
int ret, irq;
u8 rev;
+ const char *mode;
hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);
if (!hdq_data) {
@@ -567,10 +705,21 @@ static int omap_hdq_probe(struct platform_device *pdev)
return PTR_ERR(hdq_data->hdq_base);
hdq_data->hdq_usecount = 0;
+ hdq_data->rrw = 0;
mutex_init(&hdq_data->hdq_mutex);
pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "pm_runtime_get_sync failed\n");
+ goto err_w1;
+ }
+
+ ret = _omap_hdq_reset(hdq_data);
+ if (ret) {
+ dev_dbg(&pdev->dev, "reset failed\n");
+ return -EINVAL;
+ }
rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);
dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n",
@@ -594,6 +743,15 @@ static int omap_hdq_probe(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
+ ret = of_property_read_string(pdev->dev.of_node, "ti,mode", &mode);
+ if (ret < 0 || !strcmp(mode, "hdq")) {
+ hdq_data->mode = 0;
+ omap_w1_master.search = omap_w1_search_bus;
+ } else {
+ hdq_data->mode = 1;
+ omap_w1_master.triplet = omap_w1_triplet;
+ }
+
omap_w1_master.data = hdq_data;
ret = w1_add_master_device(&omap_w1_master);
@@ -635,8 +793,8 @@ static int omap_hdq_remove(struct platform_device *pdev)
module_platform_driver(omap_hdq_driver);
module_param(w1_id, int, S_IRUSR);
-MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
+MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection in HDQ mode");
MODULE_AUTHOR("Texas Instruments");
-MODULE_DESCRIPTION("HDQ driver Library");
+MODULE_DESCRIPTION("HDQ-1W driver Library");
MODULE_LICENSE("GPL");
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 8f7848c62811..a373ae69d9f6 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -198,11 +198,9 @@ static int w1_gpio_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-
-static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
+static int __maybe_unused w1_gpio_suspend(struct device *dev)
{
- struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0);
@@ -210,9 +208,9 @@ static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int w1_gpio_resume(struct platform_device *pdev)
+static int __maybe_unused w1_gpio_resume(struct device *dev)
{
- struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1);
@@ -220,20 +218,16 @@ static int w1_gpio_resume(struct platform_device *pdev)
return 0;
}
-#else
-#define w1_gpio_suspend NULL
-#define w1_gpio_resume NULL
-#endif
+static SIMPLE_DEV_PM_OPS(w1_gpio_pm_ops, w1_gpio_suspend, w1_gpio_resume);
static struct platform_driver w1_gpio_driver = {
.driver = {
.name = "w1-gpio",
+ .pm = &w1_gpio_pm_ops,
.of_match_table = of_match_ptr(w1_gpio_dt_ids),
},
.probe = w1_gpio_probe,
- .remove = w1_gpio_remove,
- .suspend = w1_gpio_suspend,
- .resume = w1_gpio_resume,
+ .remove = w1_gpio_remove,
};
module_platform_driver(w1_gpio_driver);
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c
index caafb1722783..9f4a86b754ba 100644
--- a/drivers/w1/slaves/w1_bq27000.c
+++ b/drivers/w1/slaves/w1_bq27000.c
@@ -15,7 +15,7 @@
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
-#include <linux/power/bq27x00_battery.h>
+#include <linux/power/bq27xxx_battery.h>
#include "../w1.h"
#include "../w1_int.h"
@@ -39,9 +39,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg)
return val;
}
-static struct bq27000_platform_data bq27000_battery_info = {
+static struct bq27xxx_platform_data bq27000_battery_info = {
.read = w1_bq27000_read,
.name = "bq27000-battery",
+ .chip = BQ27000,
};
static int w1_bq27000_add_slave(struct w1_slave *sl)
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 47249a30eae3..20f766afa4c7 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -91,8 +91,7 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
err = device_register(&dev->dev);
if (err) {
pr_err("Failed to register master device. err=%d\n", err);
- memset(dev, 0, sizeof(struct w1_master));
- kfree(dev);
+ put_device(&dev->dev);
dev = NULL;
}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 79e1aa1b0959..7a8a6c6952e9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1313,6 +1313,14 @@ config BCM_KONA_WDT_DEBUG
If in doubt, say 'N'.
+config BCM7038_WDT
+ tristate "BCM7038 Watchdog"
+ select WATCHDOG_CORE
+ help
+ Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
+
+ Say 'Y or 'M' here to enable the driver.
+
config IMGPDC_WDT
tristate "Imagination Technologies PDC Watchdog Timer"
depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 0c616e3f67bb..53d4827ddfe1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
+obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000000000000..4245b65d645c
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,237 @@
+/*
+ * 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; 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/clk.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/watchdog.h>
+
+#define WDT_START_1 0xff00
+#define WDT_START_2 0x00ff
+#define WDT_STOP_1 0xee00
+#define WDT_STOP_2 0x00ee
+
+#define WDT_TIMEOUT_REG 0x0
+#define WDT_CMD_REG 0x4
+
+#define WDT_MIN_TIMEOUT 1 /* seconds */
+#define WDT_DEFAULT_TIMEOUT 30 /* seconds */
+#define WDT_DEFAULT_RATE 27000000
+
+struct bcm7038_watchdog {
+ void __iomem *base;
+ struct watchdog_device wdd;
+ u32 rate;
+ struct clk *clk;
+};
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
+{
+ struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+ u32 timeout;
+
+ timeout = wdt->rate * wdog->timeout;
+
+ writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+}
+
+static int bcm7038_wdt_ping(struct watchdog_device *wdog)
+{
+ struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+ writel(WDT_START_1, wdt->base + WDT_CMD_REG);
+ writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+
+ return 0;
+}
+
+static int bcm7038_wdt_start(struct watchdog_device *wdog)
+{
+ bcm7038_wdt_set_timeout_reg(wdog);
+ bcm7038_wdt_ping(wdog);
+
+ return 0;
+}
+
+static int bcm7038_wdt_stop(struct watchdog_device *wdog)
+{
+ struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+
+ writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+ writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+
+ return 0;
+}
+
+static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
+ unsigned int t)
+{
+ /* Can't modify timeout value if watchdog timer is running */
+ bcm7038_wdt_stop(wdog);
+ wdog->timeout = t;
+ bcm7038_wdt_start(wdog);
+
+ return 0;
+}
+
+static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+ struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+ u32 time_left;
+
+ time_left = readl(wdt->base + WDT_CMD_REG);
+
+ return time_left / wdt->rate;
+}
+
+static struct watchdog_info bcm7038_wdt_info = {
+ .identity = "Broadcom BCM7038 Watchdog Timer",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE
+};
+
+static struct watchdog_ops bcm7038_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = bcm7038_wdt_start,
+ .stop = bcm7038_wdt_stop,
+ .set_timeout = bcm7038_wdt_set_timeout,
+ .get_timeleft = bcm7038_wdt_get_timeleft,
+};
+
+static int bcm7038_wdt_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcm7038_watchdog *wdt;
+ struct resource *res;
+ int err;
+
+ wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
+ if (!wdt)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, wdt);
+
+ 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->clk = devm_clk_get(dev, NULL);
+ /* If unable to get clock, use default frequency */
+ if (!IS_ERR(wdt->clk)) {
+ clk_prepare_enable(wdt->clk);
+ wdt->rate = clk_get_rate(wdt->clk);
+ /* Prevent divide-by-zero exception */
+ if (!wdt->rate)
+ wdt->rate = WDT_DEFAULT_RATE;
+ } else {
+ wdt->rate = WDT_DEFAULT_RATE;
+ wdt->clk = NULL;
+ }
+
+ wdt->wdd.info = &bcm7038_wdt_info;
+ wdt->wdd.ops = &bcm7038_wdt_ops;
+ wdt->wdd.min_timeout = WDT_MIN_TIMEOUT;
+ wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
+ wdt->wdd.max_timeout = 0xffffffff / wdt->rate;
+ wdt->wdd.parent = dev;
+ watchdog_set_drvdata(&wdt->wdd, wdt);
+
+ err = watchdog_register_device(&wdt->wdd);
+ if (err) {
+ dev_err(dev, "Failed to register watchdog device\n");
+ clk_disable_unprepare(wdt->clk);
+ return err;
+ }
+
+ dev_info(dev, "Registered BCM7038 Watchdog\n");
+
+ return 0;
+}
+
+static int bcm7038_wdt_remove(struct platform_device *pdev)
+{
+ struct bcm7038_watchdog *wdt = platform_get_drvdata(pdev);
+
+ if (!nowayout)
+ bcm7038_wdt_stop(&wdt->wdd);
+
+ watchdog_unregister_device(&wdt->wdd);
+ clk_disable_unprepare(wdt->clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bcm7038_wdt_suspend(struct device *dev)
+{
+ struct bcm7038_watchdog *wdt = dev_get_drvdata(dev);
+
+ if (watchdog_active(&wdt->wdd))
+ return bcm7038_wdt_stop(&wdt->wdd);
+
+ return 0;
+}
+
+static int bcm7038_wdt_resume(struct device *dev)
+{
+ struct bcm7038_watchdog *wdt = dev_get_drvdata(dev);
+
+ if (watchdog_active(&wdt->wdd))
+ return bcm7038_wdt_start(&wdt->wdd);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, bcm7038_wdt_suspend,
+ bcm7038_wdt_resume);
+
+static void bcm7038_wdt_shutdown(struct platform_device *pdev)
+{
+ struct bcm7038_watchdog *wdt = platform_get_drvdata(pdev);
+
+ if (watchdog_active(&wdt->wdd))
+ bcm7038_wdt_stop(&wdt->wdd);
+}
+
+static const struct of_device_id bcm7038_wdt_match[] = {
+ { .compatible = "brcm,bcm7038-wdt" },
+ {},
+};
+
+static struct platform_driver bcm7038_wdt_driver = {
+ .probe = bcm7038_wdt_probe,
+ .remove = bcm7038_wdt_remove,
+ .shutdown = bcm7038_wdt_shutdown,
+ .driver = {
+ .name = "bcm7038-wdt",
+ .of_match_table = bcm7038_wdt_match,
+ .pm = &bcm7038_wdt_pm_ops,
+ }
+};
+module_platform_driver(bcm7038_wdt_driver);
+
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Driver for Broadcom 7038 SoCs Watchdog");
+MODULE_AUTHOR("Justin Chen");
diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c
index a9a5210143ae..3db9d0e0673d 100644
--- a/drivers/watchdog/diag288_wdt.c
+++ b/drivers/watchdog/diag288_wdt.c
@@ -29,6 +29,7 @@
#include <linux/watchdog.h>
#include <linux/suspend.h>
#include <asm/ebcdic.h>
+#include <asm/diag.h>
#include <linux/io.h>
#include <linux/uaccess.h>
@@ -94,12 +95,14 @@ static int __diag288(unsigned int func, unsigned int timeout,
static int __diag288_vm(unsigned int func, unsigned int timeout,
char *cmd, size_t len)
{
+ diag_stat_inc(DIAG_STAT_X288);
return __diag288(func, timeout, virt_to_phys(cmd), len);
}
static int __diag288_lpar(unsigned int func, unsigned int timeout,
unsigned long action)
{
+ diag_stat_inc(DIAG_STAT_X288);
return __diag288(func, timeout, action, 0);
}
@@ -141,6 +144,7 @@ static int wdt_stop(struct watchdog_device *dev)
{
int ret;
+ diag_stat_inc(DIAG_STAT_X288);
ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0);
return ret;
}
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 0bb1a1d1b170..29ef719a6a3c 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -91,7 +91,7 @@ static int imx2_restart_handler(struct notifier_block *this, unsigned long mode,
struct imx2_wdt_device,
restart_handler);
/* Assert SRS signal */
- regmap_write(wdev->regmap, 0, wcr_enable);
+ regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
/*
* Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
* written twice), we add another two writes to ensure there must be at
@@ -99,8 +99,8 @@ static int imx2_restart_handler(struct notifier_block *this, unsigned long mode,
* the target check here, since the writes shouldn't be a huge burden
* for other platforms.
*/
- regmap_write(wdev->regmap, 0, wcr_enable);
- regmap_write(wdev->regmap, 0, wcr_enable);
+ regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
+ regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
/* wait for reset to assert... */
mdelay(500);
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c
index 0a436b5d1e84..db36d12e2b52 100644
--- a/drivers/watchdog/intel-mid_wdt.c
+++ b/drivers/watchdog/intel-mid_wdt.c
@@ -101,7 +101,7 @@ static irqreturn_t mid_wdt_irq(int irq, void *dev_id)
static const struct watchdog_info mid_wdt_info = {
.identity = "Intel MID SCU watchdog",
- .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
};
static const struct watchdog_ops mid_wdt_ops = {
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a8059455413..873f13972cf4 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
static int __watchdog_register_device(struct watchdog_device *wdd)
{
- int ret, id, devno;
+ int ret, id = -1, devno;
if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
return -EINVAL;
@@ -157,7 +157,18 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
*/
mutex_init(&wdd->lock);
- id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL);
+
+ /* Use alias for watchdog id if possible */
+ if (wdd->parent) {
+ ret = of_alias_get_id(wdd->parent->of_node, "watchdog");
+ if (ret >= 0)
+ id = ida_simple_get(&watchdog_ida, ret,
+ ret + 1, GFP_KERNEL);
+ }
+
+ if (id < 0)
+ id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL);
+
if (id < 0)
return id;
wdd->id = id;
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefbad303e..56a649e66eb2 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -51,7 +51,7 @@ static struct watchdog_device *old_wdd;
/*
* watchdog_ping: ping the watchdog.
- * @wddev: the watchdog device to ping
+ * @wdd: the watchdog device to ping
*
* If the watchdog has no own ping operation then it needs to be
* restarted via the start operation. This wrapper function does
@@ -59,65 +59,65 @@ static struct watchdog_device *old_wdd;
* We only ping when the watchdog device is running.
*/
-static int watchdog_ping(struct watchdog_device *wddev)
+static int watchdog_ping(struct watchdog_device *wdd)
{
int err = 0;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_ping;
}
- if (!watchdog_active(wddev))
+ if (!watchdog_active(wdd))
goto out_ping;
- if (wddev->ops->ping)
- err = wddev->ops->ping(wddev); /* ping the watchdog */
+ if (wdd->ops->ping)
+ err = wdd->ops->ping(wdd); /* ping the watchdog */
else
- err = wddev->ops->start(wddev); /* restart watchdog */
+ err = wdd->ops->start(wdd); /* restart watchdog */
out_ping:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
/*
* watchdog_start: wrapper to start the watchdog.
- * @wddev: the watchdog device to start
+ * @wdd: the watchdog device to start
*
* Start the watchdog if it is not active and mark it active.
* This function returns zero on success or a negative errno code for
* failure.
*/
-static int watchdog_start(struct watchdog_device *wddev)
+static int watchdog_start(struct watchdog_device *wdd)
{
int err = 0;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_start;
}
- if (watchdog_active(wddev))
+ if (watchdog_active(wdd))
goto out_start;
- err = wddev->ops->start(wddev);
+ err = wdd->ops->start(wdd);
if (err == 0)
- set_bit(WDOG_ACTIVE, &wddev->status);
+ set_bit(WDOG_ACTIVE, &wdd->status);
out_start:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
/*
* watchdog_stop: wrapper to stop the watchdog.
- * @wddev: the watchdog device to stop
+ * @wdd: the watchdog device to stop
*
* Stop the watchdog if it is still active and unmark it active.
* This function returns zero on success or a negative errno code for
@@ -125,155 +125,154 @@ out_start:
* If the 'nowayout' feature was set, the watchdog cannot be stopped.
*/
-static int watchdog_stop(struct watchdog_device *wddev)
+static int watchdog_stop(struct watchdog_device *wdd)
{
int err = 0;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_stop;
}
- if (!watchdog_active(wddev))
+ if (!watchdog_active(wdd))
goto out_stop;
- if (test_bit(WDOG_NO_WAY_OUT, &wddev->status)) {
- dev_info(wddev->dev, "nowayout prevents watchdog being stopped!\n");
+ if (test_bit(WDOG_NO_WAY_OUT, &wdd->status)) {
+ dev_info(wdd->dev, "nowayout prevents watchdog being stopped!\n");
err = -EBUSY;
goto out_stop;
}
- err = wddev->ops->stop(wddev);
+ err = wdd->ops->stop(wdd);
if (err == 0)
- clear_bit(WDOG_ACTIVE, &wddev->status);
+ clear_bit(WDOG_ACTIVE, &wdd->status);
out_stop:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
/*
* watchdog_get_status: wrapper to get the watchdog status
- * @wddev: the watchdog device to get the status from
+ * @wdd: the watchdog device to get the status from
* @status: the status of the watchdog device
*
* Get the watchdog's status flags.
*/
-static int watchdog_get_status(struct watchdog_device *wddev,
+static int watchdog_get_status(struct watchdog_device *wdd,
unsigned int *status)
{
int err = 0;
*status = 0;
- if (!wddev->ops->status)
+ if (!wdd->ops->status)
return -EOPNOTSUPP;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_status;
}
- *status = wddev->ops->status(wddev);
+ *status = wdd->ops->status(wdd);
out_status:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
/*
* watchdog_set_timeout: set the watchdog timer timeout
- * @wddev: the watchdog device to set the timeout for
+ * @wdd: the watchdog device to set the timeout for
* @timeout: timeout to set in seconds
*/
-static int watchdog_set_timeout(struct watchdog_device *wddev,
+static int watchdog_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
int err;
- if ((wddev->ops->set_timeout == NULL) ||
- !(wddev->info->options & WDIOF_SETTIMEOUT))
+ if (!wdd->ops->set_timeout || !(wdd->info->options & WDIOF_SETTIMEOUT))
return -EOPNOTSUPP;
- if (watchdog_timeout_invalid(wddev, timeout))
+ if (watchdog_timeout_invalid(wdd, timeout))
return -EINVAL;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_timeout;
}
- err = wddev->ops->set_timeout(wddev, timeout);
+ err = wdd->ops->set_timeout(wdd, timeout);
out_timeout:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
/*
* watchdog_get_timeleft: wrapper to get the time left before a reboot
- * @wddev: the watchdog device to get the remaining time from
+ * @wdd: the watchdog device to get the remaining time from
* @timeleft: the time that's left
*
* Get the time before a watchdog will reboot (if not pinged).
*/
-static int watchdog_get_timeleft(struct watchdog_device *wddev,
+static int watchdog_get_timeleft(struct watchdog_device *wdd,
unsigned int *timeleft)
{
int err = 0;
*timeleft = 0;
- if (!wddev->ops->get_timeleft)
+ if (!wdd->ops->get_timeleft)
return -EOPNOTSUPP;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_timeleft;
}
- *timeleft = wddev->ops->get_timeleft(wddev);
+ *timeleft = wdd->ops->get_timeleft(wdd);
out_timeleft:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
/*
* watchdog_ioctl_op: call the watchdog drivers ioctl op if defined
- * @wddev: the watchdog device to do the ioctl on
+ * @wdd: the watchdog device to do the ioctl on
* @cmd: watchdog command
* @arg: argument pointer
*/
-static int watchdog_ioctl_op(struct watchdog_device *wddev, unsigned int cmd,
+static int watchdog_ioctl_op(struct watchdog_device *wdd, unsigned int cmd,
unsigned long arg)
{
int err;
- if (!wddev->ops->ioctl)
+ if (!wdd->ops->ioctl)
return -ENOIOCTLCMD;
- mutex_lock(&wddev->lock);
+ mutex_lock(&wdd->lock);
- if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
err = -ENODEV;
goto out_ioctl;
}
- err = wddev->ops->ioctl(wddev, cmd, arg);
+ err = wdd->ops->ioctl(wdd, cmd, arg);
out_ioctl:
- mutex_unlock(&wddev->lock);
+ mutex_unlock(&wdd->lock);
return err;
}
@@ -295,6 +294,7 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
struct watchdog_device *wdd = file->private_data;
size_t i;
char c;
+ int err;
if (len == 0)
return 0;
@@ -314,7 +314,9 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
}
/* someone wrote to us, so we send the watchdog a keepalive ping */
- watchdog_ping(wdd);
+ err = watchdog_ping(wdd);
+ if (err < 0)
+ return err;
return len;
}
@@ -370,8 +372,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
case WDIOC_KEEPALIVE:
if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
return -EOPNOTSUPP;
- watchdog_ping(wdd);
- return 0;
+ return watchdog_ping(wdd);
case WDIOC_SETTIMEOUT:
if (get_user(val, p))
return -EFAULT;
@@ -381,7 +382,9 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
/* If the watchdog is active then we send a keepalive ping
* to make sure that the watchdog keep's running (and if
* possible that it takes the new timeout) */
- watchdog_ping(wdd);
+ err = watchdog_ping(wdd);
+ if (err < 0)
+ return err;
/* Fall */
case WDIOC_GETTIMEOUT:
/* timeout == 0 means that we don't know the timeout */
@@ -513,43 +516,43 @@ static struct miscdevice watchdog_miscdev = {
/*
* watchdog_dev_register: register a watchdog device
- * @watchdog: watchdog device
+ * @wdd: watchdog device
*
* Register a watchdog device including handling the legacy
* /dev/watchdog node. /dev/watchdog is actually a miscdevice and
* thus we set it up like that.
*/
-int watchdog_dev_register(struct watchdog_device *watchdog)
+int watchdog_dev_register(struct watchdog_device *wdd)
{
int err, devno;
- if (watchdog->id == 0) {
- old_wdd = watchdog;
- watchdog_miscdev.parent = watchdog->parent;
+ if (wdd->id == 0) {
+ old_wdd = wdd;
+ watchdog_miscdev.parent = wdd->parent;
err = misc_register(&watchdog_miscdev);
if (err != 0) {
pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
- watchdog->info->identity, WATCHDOG_MINOR, err);
+ wdd->info->identity, WATCHDOG_MINOR, err);
if (err == -EBUSY)
pr_err("%s: a legacy watchdog module is probably present.\n",
- watchdog->info->identity);
+ wdd->info->identity);
old_wdd = NULL;
return err;
}
}
/* Fill in the data structures */
- devno = MKDEV(MAJOR(watchdog_devt), watchdog->id);
- cdev_init(&watchdog->cdev, &watchdog_fops);
- watchdog->cdev.owner = watchdog->ops->owner;
+ devno = MKDEV(MAJOR(watchdog_devt), wdd->id);
+ cdev_init(&wdd->cdev, &watchdog_fops);
+ wdd->cdev.owner = wdd->ops->owner;
/* Add the device */
- err = cdev_add(&watchdog->cdev, devno, 1);
+ err = cdev_add(&wdd->cdev, devno, 1);
if (err) {
pr_err("watchdog%d unable to add device %d:%d\n",
- watchdog->id, MAJOR(watchdog_devt), watchdog->id);
- if (watchdog->id == 0) {
+ wdd->id, MAJOR(watchdog_devt), wdd->id);
+ if (wdd->id == 0) {
misc_deregister(&watchdog_miscdev);
old_wdd = NULL;
}
@@ -564,14 +567,14 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
* Unregister the watchdog and if needed the legacy /dev/watchdog device.
*/
-int watchdog_dev_unregister(struct watchdog_device *watchdog)
+int watchdog_dev_unregister(struct watchdog_device *wdd)
{
- mutex_lock(&watchdog->lock);
- set_bit(WDOG_UNREGISTERED, &watchdog->status);
- mutex_unlock(&watchdog->lock);
+ mutex_lock(&wdd->lock);
+ set_bit(WDOG_UNREGISTERED, &wdd->status);
+ mutex_unlock(&wdd->lock);
- cdev_del(&watchdog->cdev);
- if (watchdog->id == 0) {
+ cdev_del(&wdd->cdev);
+ if (wdd->id == 0) {
misc_deregister(&watchdog_miscdev);
old_wdd = NULL;
}
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index e293bc507cbc..aa8a7f71f310 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,6 +1,4 @@
-ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),)
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
-endif
obj-$(CONFIG_X86) += fallback.o
obj-y += grant-table.o features.o balloon.o manage.o preempt.o
obj-y += events/
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index c79329fcfa78..12eab503efd1 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -54,6 +54,8 @@
#include <linux/memory.h>
#include <linux/memory_hotplug.h>
#include <linux/percpu-defs.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
@@ -70,16 +72,64 @@
#include <xen/features.h>
#include <xen/page.h>
+static int xen_hotplug_unpopulated;
+
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+
+static int zero;
+static int one = 1;
+
+static struct ctl_table balloon_table[] = {
+ {
+ .procname = "hotplug_unpopulated",
+ .data = &xen_hotplug_unpopulated,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+ { }
+};
+
+static struct ctl_table balloon_root[] = {
+ {
+ .procname = "balloon",
+ .mode = 0555,
+ .child = balloon_table,
+ },
+ { }
+};
+
+static struct ctl_table xen_root[] = {
+ {
+ .procname = "xen",
+ .mode = 0555,
+ .child = balloon_root,
+ },
+ { }
+};
+
+#endif
+
+/*
+ * Use one extent per PAGE_SIZE to avoid to break down the page into
+ * multiple frame.
+ */
+#define EXTENT_ORDER (fls(XEN_PFN_PER_PAGE) - 1)
+
/*
* balloon_process() state:
*
* BP_DONE: done or nothing to do,
+ * BP_WAIT: wait to be rescheduled,
* BP_EAGAIN: error, go to sleep,
* BP_ECANCELED: error, balloon operation canceled.
*/
enum bp_state {
BP_DONE,
+ BP_WAIT,
BP_EAGAIN,
BP_ECANCELED
};
@@ -91,11 +141,12 @@ struct balloon_stats balloon_stats;
EXPORT_SYMBOL_GPL(balloon_stats);
/* We increase/decrease in batches which fit in a page */
-static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
+static xen_pfn_t frame_list[PAGE_SIZE / sizeof(xen_pfn_t)];
/* List of ballooned pages, threaded through the mem_map array. */
static LIST_HEAD(ballooned_pages);
+static DECLARE_WAIT_QUEUE_HEAD(balloon_wq);
/* Main work function, always executed in process context. */
static void balloon_process(struct work_struct *work);
@@ -124,6 +175,7 @@ static void __balloon_append(struct page *page)
list_add(&page->lru, &ballooned_pages);
balloon_stats.balloon_low++;
}
+ wake_up(&balloon_wq);
}
static void balloon_append(struct page *page)
@@ -133,17 +185,16 @@ static void balloon_append(struct page *page)
}
/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
-static struct page *balloon_retrieve(bool prefer_highmem)
+static struct page *balloon_retrieve(bool require_lowmem)
{
struct page *page;
if (list_empty(&ballooned_pages))
return NULL;
- if (prefer_highmem)
- page = list_entry(ballooned_pages.prev, struct page, lru);
- else
- page = list_entry(ballooned_pages.next, struct page, lru);
+ page = list_entry(ballooned_pages.next, struct page, lru);
+ if (require_lowmem && PageHighMem(page))
+ return NULL;
list_del(&page->lru);
if (PageHighMem(page))
@@ -166,6 +217,9 @@ static struct page *balloon_next_page(struct page *page)
static enum bp_state update_schedule(enum bp_state state)
{
+ if (state == BP_WAIT)
+ return BP_WAIT;
+
if (state == BP_ECANCELED)
return BP_ECANCELED;
@@ -193,43 +247,75 @@ static enum bp_state update_schedule(enum bp_state state)
}
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
-static long current_credit(void)
+static struct resource *additional_memory_resource(phys_addr_t size)
{
- return balloon_stats.target_pages - balloon_stats.current_pages -
- balloon_stats.hotplug_pages;
+ struct resource *res;
+ int ret;
+
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return NULL;
+
+ res->name = "System RAM";
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+ ret = allocate_resource(&iomem_resource, res,
+ size, 0, -1,
+ PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
+ if (ret < 0) {
+ pr_err("Cannot allocate new System RAM resource\n");
+ kfree(res);
+ return NULL;
+ }
+
+ return res;
}
-static bool balloon_is_inflated(void)
+static void release_memory_resource(struct resource *resource)
{
- if (balloon_stats.balloon_low || balloon_stats.balloon_high ||
- balloon_stats.balloon_hotplug)
- return true;
- else
- return false;
-}
+ if (!resource)
+ return;
-/*
- * reserve_additional_memory() adds memory region of size >= credit above
- * max_pfn. New region is section aligned and size is modified to be multiple
- * of section size. Those features allow optimal use of address space and
- * establish proper alignment when this function is called first time after
- * boot (last section not fully populated at boot time contains unused memory
- * pages with PG_reserved bit not set; online_pages_range() does not allow page
- * onlining in whole range if first onlined page does not have PG_reserved
- * bit set). Real size of added memory is established at page onlining stage.
- */
+ /*
+ * No need to reset region to identity mapped since we now
+ * know that no I/O can be in this region
+ */
+ release_resource(resource);
+ kfree(resource);
+}
-static enum bp_state reserve_additional_memory(long credit)
+static enum bp_state reserve_additional_memory(void)
{
+ long credit;
+ struct resource *resource;
int nid, rc;
- u64 hotplug_start_paddr;
- unsigned long balloon_hotplug = credit;
+ unsigned long balloon_hotplug;
+
+ credit = balloon_stats.target_pages + balloon_stats.target_unpopulated
+ - balloon_stats.total_pages;
+
+ /*
+ * Already hotplugged enough pages? Wait for them to be
+ * onlined.
+ */
+ if (credit <= 0)
+ return BP_WAIT;
- hotplug_start_paddr = PFN_PHYS(SECTION_ALIGN_UP(max_pfn));
- balloon_hotplug = round_up(balloon_hotplug, PAGES_PER_SECTION);
- nid = memory_add_physaddr_to_nid(hotplug_start_paddr);
+ balloon_hotplug = round_up(credit, PAGES_PER_SECTION);
+
+ resource = additional_memory_resource(balloon_hotplug * PAGE_SIZE);
+ if (!resource)
+ goto err;
+
+ nid = memory_add_physaddr_to_nid(resource->start);
#ifdef CONFIG_XEN_HAVE_PVMMU
+ /*
+ * We don't support PV MMU when Linux and Xen is using
+ * different page granularity.
+ */
+ BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);
+
/*
* add_memory() will build page tables for the new memory so
* the p2m must contain invalid entries so the correct
@@ -242,29 +328,28 @@ static enum bp_state reserve_additional_memory(long credit)
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
unsigned long pfn, i;
- pfn = PFN_DOWN(hotplug_start_paddr);
+ pfn = PFN_DOWN(resource->start);
for (i = 0; i < balloon_hotplug; i++) {
if (!set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY)) {
pr_warn("set_phys_to_machine() failed, no memory added\n");
- return BP_ECANCELED;
+ goto err;
}
}
}
#endif
- rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT);
-
+ rc = add_memory_resource(nid, resource);
if (rc) {
pr_warn("Cannot add additional memory (%i)\n", rc);
- return BP_ECANCELED;
+ goto err;
}
- balloon_hotplug -= credit;
+ balloon_stats.total_pages += balloon_hotplug;
- balloon_stats.hotplug_pages += credit;
- balloon_stats.balloon_hotplug = balloon_hotplug;
-
- return BP_DONE;
+ return BP_WAIT;
+ err:
+ release_memory_resource(resource);
+ return BP_ECANCELED;
}
static void xen_online_page(struct page *page)
@@ -275,11 +360,6 @@ static void xen_online_page(struct page *page)
__balloon_append(page);
- if (balloon_stats.hotplug_pages)
- --balloon_stats.hotplug_pages;
- else
- --balloon_stats.balloon_hotplug;
-
mutex_unlock(&balloon_mutex);
}
@@ -296,53 +376,34 @@ static struct notifier_block xen_memory_nb = {
.priority = 0
};
#else
-static long current_credit(void)
+static enum bp_state reserve_additional_memory(void)
{
- unsigned long target = balloon_stats.target_pages;
-
- target = min(target,
- balloon_stats.current_pages +
- balloon_stats.balloon_low +
- balloon_stats.balloon_high);
-
- return target - balloon_stats.current_pages;
+ balloon_stats.target_pages = balloon_stats.current_pages;
+ return BP_ECANCELED;
}
+#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
-static bool balloon_is_inflated(void)
+static long current_credit(void)
{
- if (balloon_stats.balloon_low || balloon_stats.balloon_high)
- return true;
- else
- return false;
+ return balloon_stats.target_pages - balloon_stats.current_pages;
}
-static enum bp_state reserve_additional_memory(long credit)
+static bool balloon_is_inflated(void)
{
- balloon_stats.target_pages = balloon_stats.current_pages;
- return BP_DONE;
+ return balloon_stats.balloon_low || balloon_stats.balloon_high;
}
-#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
static enum bp_state increase_reservation(unsigned long nr_pages)
{
int rc;
- unsigned long pfn, i;
+ unsigned long i;
struct page *page;
struct xen_memory_reservation reservation = {
.address_bits = 0,
- .extent_order = 0,
+ .extent_order = EXTENT_ORDER,
.domid = DOMID_SELF
};
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- if (!balloon_stats.balloon_low && !balloon_stats.balloon_high) {
- nr_pages = min(nr_pages, balloon_stats.balloon_hotplug);
- balloon_stats.hotplug_pages += nr_pages;
- balloon_stats.balloon_hotplug -= nr_pages;
- return BP_DONE;
- }
-#endif
-
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
@@ -352,7 +413,11 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
nr_pages = i;
break;
}
- frame_list[i] = page_to_pfn(page);
+
+ /* XENMEM_populate_physmap requires a PFN based on Xen
+ * granularity.
+ */
+ frame_list[i] = page_to_xen_pfn(page);
page = balloon_next_page(page);
}
@@ -366,10 +431,16 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
page = balloon_retrieve(false);
BUG_ON(page == NULL);
- pfn = page_to_pfn(page);
-
#ifdef CONFIG_XEN_HAVE_PVMMU
+ /*
+ * We don't support PV MMU when Linux and Xen is using
+ * different page granularity.
+ */
+ BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);
+
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ unsigned long pfn = page_to_pfn(page);
+
set_phys_to_machine(pfn, frame_list[i]);
/* Link back into the page tables if not highmem. */
@@ -396,23 +467,15 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
{
enum bp_state state = BP_DONE;
- unsigned long pfn, i;
- struct page *page;
+ unsigned long i;
+ struct page *page, *tmp;
int ret;
struct xen_memory_reservation reservation = {
.address_bits = 0,
- .extent_order = 0,
+ .extent_order = EXTENT_ORDER,
.domid = DOMID_SELF
};
-
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- if (balloon_stats.hotplug_pages) {
- nr_pages = min(nr_pages, balloon_stats.hotplug_pages);
- balloon_stats.hotplug_pages -= nr_pages;
- balloon_stats.balloon_hotplug += nr_pages;
- return BP_DONE;
- }
-#endif
+ LIST_HEAD(pages);
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
@@ -425,8 +488,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
break;
}
scrub_page(page);
-
- frame_list[i] = page_to_pfn(page);
+ list_add(&page->lru, &pages);
}
/*
@@ -438,14 +500,25 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
*/
kmap_flush_unused();
- /* Update direct mapping, invalidate P2M, and add to balloon. */
- for (i = 0; i < nr_pages; i++) {
- pfn = frame_list[i];
- frame_list[i] = pfn_to_gfn(pfn);
- page = pfn_to_page(pfn);
+ /*
+ * Setup the frame, update direct mapping, invalidate P2M,
+ * and add to balloon.
+ */
+ i = 0;
+ list_for_each_entry_safe(page, tmp, &pages, lru) {
+ /* XENMEM_decrease_reservation requires a GFN */
+ frame_list[i++] = xen_page_to_gfn(page);
#ifdef CONFIG_XEN_HAVE_PVMMU
+ /*
+ * We don't support PV MMU when Linux and Xen is using
+ * different page granularity.
+ */
+ BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);
+
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ unsigned long pfn = page_to_pfn(page);
+
if (!PageHighMem(page)) {
ret = HYPERVISOR_update_va_mapping(
(unsigned long)__va(pfn << PAGE_SHIFT),
@@ -455,6 +528,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
}
#endif
+ list_del(&page->lru);
balloon_append(page);
}
@@ -492,7 +566,7 @@ static void balloon_process(struct work_struct *work)
if (balloon_is_inflated())
state = increase_reservation(credit);
else
- state = reserve_additional_memory(credit);
+ state = reserve_additional_memory();
}
if (credit < 0)
@@ -520,41 +594,71 @@ void balloon_set_new_target(unsigned long target)
}
EXPORT_SYMBOL_GPL(balloon_set_new_target);
+static int add_ballooned_pages(int nr_pages)
+{
+ enum bp_state st;
+
+ if (xen_hotplug_unpopulated) {
+ st = reserve_additional_memory();
+ if (st != BP_ECANCELED) {
+ mutex_unlock(&balloon_mutex);
+ wait_event(balloon_wq,
+ !list_empty(&ballooned_pages));
+ mutex_lock(&balloon_mutex);
+ return 0;
+ }
+ }
+
+ st = decrease_reservation(nr_pages, GFP_USER);
+ if (st != BP_DONE)
+ return -ENOMEM;
+
+ return 0;
+}
+
/**
* alloc_xenballooned_pages - get pages that have been ballooned out
* @nr_pages: Number of pages to get
* @pages: pages returned
- * @highmem: allow highmem pages
* @return 0 on success, error otherwise
*/
-int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
+int alloc_xenballooned_pages(int nr_pages, struct page **pages)
{
int pgno = 0;
struct page *page;
+ int ret;
+
mutex_lock(&balloon_mutex);
+
+ balloon_stats.target_unpopulated += nr_pages;
+
while (pgno < nr_pages) {
- page = balloon_retrieve(highmem);
- if (page && (highmem || !PageHighMem(page))) {
+ page = balloon_retrieve(true);
+ if (page) {
pages[pgno++] = page;
+#ifdef CONFIG_XEN_HAVE_PVMMU
+ /*
+ * We don't support PV MMU when Linux and Xen is using
+ * different page granularity.
+ */
+ BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);
+
+ ret = xen_alloc_p2m_entry(page_to_pfn(page));
+ if (ret < 0)
+ goto out_undo;
+#endif
} else {
- enum bp_state st;
- if (page)
- balloon_append(page);
- st = decrease_reservation(nr_pages - pgno,
- highmem ? GFP_HIGHUSER : GFP_USER);
- if (st != BP_DONE)
+ ret = add_ballooned_pages(nr_pages - pgno);
+ if (ret < 0)
goto out_undo;
}
}
mutex_unlock(&balloon_mutex);
return 0;
out_undo:
- while (pgno)
- balloon_append(pages[--pgno]);
- /* Free the memory back to the kernel soon */
- schedule_delayed_work(&balloon_worker, 0);
mutex_unlock(&balloon_mutex);
- return -ENOMEM;
+ free_xenballooned_pages(pgno, pages);
+ return ret;
}
EXPORT_SYMBOL(alloc_xenballooned_pages);
@@ -574,6 +678,8 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
balloon_append(pages[i]);
}
+ balloon_stats.target_unpopulated -= nr_pages;
+
/* The balloon may be too large now. Shrink it if needed. */
if (current_credit())
schedule_delayed_work(&balloon_worker, 0);
@@ -602,6 +708,8 @@ static void __init balloon_add_region(unsigned long start_pfn,
don't subtract from it. */
__balloon_append(page);
}
+
+ balloon_stats.total_pages += extra_pfn_end - start_pfn;
}
static int __init balloon_init(void)
@@ -619,6 +727,7 @@ static int __init balloon_init(void)
balloon_stats.target_pages = balloon_stats.current_pages;
balloon_stats.balloon_low = 0;
balloon_stats.balloon_high = 0;
+ balloon_stats.total_pages = balloon_stats.current_pages;
balloon_stats.schedule_delay = 1;
balloon_stats.max_schedule_delay = 32;
@@ -626,11 +735,9 @@ static int __init balloon_init(void)
balloon_stats.max_retry_count = RETRY_UNLIMITED;
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- balloon_stats.hotplug_pages = 0;
- balloon_stats.balloon_hotplug = 0;
-
set_online_page_callback(&xen_online_page);
register_memory_notifier(&xen_memory_nb);
+ register_sysctl_table(xen_root);
#endif
/*
diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c
index 8ae2fc90e1ea..4da69dbf7dca 100644
--- a/drivers/xen/biomerge.c
+++ b/drivers/xen/biomerge.c
@@ -6,10 +6,18 @@
bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
const struct bio_vec *vec2)
{
+#if XEN_PAGE_SIZE == PAGE_SIZE
unsigned long bfn1 = pfn_to_bfn(page_to_pfn(vec1->bv_page));
unsigned long bfn2 = pfn_to_bfn(page_to_pfn(vec2->bv_page));
return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&
((bfn1 == bfn2) || ((bfn1+1) == bfn2));
+#else
+ /*
+ * XXX: Add support for merging bio_vec when using different page
+ * size in Xen and Linux.
+ */
+ return 0;
+#endif
}
EXPORT_SYMBOL(xen_biovec_phys_mergeable);
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index cc6513a176b0..5676aefdf2bc 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -11,15 +11,20 @@
static void enable_hotplug_cpu(int cpu)
{
if (!cpu_present(cpu))
- arch_register_cpu(cpu);
+ xen_arch_register_cpu(cpu);
set_cpu_present(cpu, true);
}
static void disable_hotplug_cpu(int cpu)
{
+ if (cpu_online(cpu)) {
+ lock_device_hotplug();
+ device_offline(get_cpu_device(cpu));
+ unlock_device_hotplug();
+ }
if (cpu_present(cpu))
- arch_unregister_cpu(cpu);
+ xen_arch_unregister_cpu(cpu);
set_cpu_present(cpu, false);
}
@@ -55,7 +60,6 @@ static void vcpu_hotplug(unsigned int cpu)
enable_hotplug_cpu(cpu);
break;
case 0:
- (void)cpu_down(cpu);
disable_hotplug_cpu(cpu);
break;
default:
@@ -102,7 +106,11 @@ static int __init setup_vcpu_hotplug_event(void)
static struct notifier_block xsn_cpu = {
.notifier_call = setup_cpu_watcher };
+#ifdef CONFIG_X86
if (!xen_pv_domain())
+#else
+ if (!xen_domain())
+#endif
return -ENODEV;
register_xenstore_notifier(&xsn_cpu);
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 6cd5e65c4aff..849500e4e14d 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -40,11 +40,11 @@
#include <asm/idle.h>
#include <asm/io_apic.h>
#include <asm/xen/pci.h>
-#include <xen/page.h>
#endif
#include <asm/sync_bitops.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/hypervisor.h>
+#include <xen/page.h>
#include <xen/xen.h>
#include <xen/hvm.h>
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 1d4baf56c36b..e3e9e3d46d1b 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -54,7 +54,7 @@
#include "events_internal.h"
-#define EVENT_WORDS_PER_PAGE (PAGE_SIZE / sizeof(event_word_t))
+#define EVENT_WORDS_PER_PAGE (XEN_PAGE_SIZE / sizeof(event_word_t))
#define MAX_EVENT_ARRAY_PAGES (EVTCHN_FIFO_NR_CHANNELS / EVENT_WORDS_PER_PAGE)
struct evtchn_fifo_queue {
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 62f591f8763c..c49f79ed58c5 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -642,7 +642,7 @@ int gnttab_setup_auto_xlat_frames(phys_addr_t addr)
if (xen_auto_xlat_grant_frames.count)
return -EINVAL;
- vaddr = xen_remap(addr, PAGE_SIZE * max_nr_gframes);
+ vaddr = xen_remap(addr, XEN_PAGE_SIZE * max_nr_gframes);
if (vaddr == NULL) {
pr_warn("Failed to ioremap gnttab share frames (addr=%pa)!\n",
&addr);
@@ -654,7 +654,7 @@ int gnttab_setup_auto_xlat_frames(phys_addr_t addr)
return -ENOMEM;
}
for (i = 0; i < max_nr_gframes; i++)
- pfn[i] = PFN_DOWN(addr) + i;
+ pfn[i] = XEN_PFN_DOWN(addr) + i;
xen_auto_xlat_grant_frames.vaddr = vaddr;
xen_auto_xlat_grant_frames.pfn = pfn;
@@ -687,7 +687,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
int i;
int ret;
- ret = alloc_xenballooned_pages(nr_pages, pages, false);
+ ret = alloc_xenballooned_pages(nr_pages, pages);
if (ret < 0)
return ret;
@@ -776,6 +776,54 @@ void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
}
EXPORT_SYMBOL_GPL(gnttab_batch_copy);
+void gnttab_foreach_grant_in_range(struct page *page,
+ unsigned int offset,
+ unsigned int len,
+ xen_grant_fn_t fn,
+ void *data)
+{
+ unsigned int goffset;
+ unsigned int glen;
+ unsigned long xen_pfn;
+
+ len = min_t(unsigned int, PAGE_SIZE - offset, len);
+ goffset = xen_offset_in_page(offset);
+
+ xen_pfn = page_to_xen_pfn(page) + XEN_PFN_DOWN(offset);
+
+ while (len) {
+ glen = min_t(unsigned int, XEN_PAGE_SIZE - goffset, len);
+ fn(pfn_to_gfn(xen_pfn), goffset, glen, data);
+
+ goffset = 0;
+ xen_pfn++;
+ len -= glen;
+ }
+}
+EXPORT_SYMBOL_GPL(gnttab_foreach_grant_in_range);
+
+void gnttab_foreach_grant(struct page **pages,
+ unsigned int nr_grefs,
+ xen_grant_fn_t fn,
+ void *data)
+{
+ unsigned int goffset = 0;
+ unsigned long xen_pfn = 0;
+ unsigned int i;
+
+ for (i = 0; i < nr_grefs; i++) {
+ if ((i % XEN_PFN_PER_PAGE) == 0) {
+ xen_pfn = page_to_xen_pfn(pages[i / XEN_PFN_PER_PAGE]);
+ goffset = 0;
+ }
+
+ fn(pfn_to_gfn(xen_pfn), goffset, XEN_PAGE_SIZE, data);
+
+ goffset += XEN_PAGE_SIZE;
+ xen_pfn++;
+ }
+}
+
int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
struct gnttab_map_grant_ref *kmap_ops,
struct page **pages, unsigned int count)
@@ -978,7 +1026,7 @@ static void gnttab_request_version(void)
{
/* Only version 1 is used, which will always be available. */
grant_table_version = 1;
- grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
+ grefs_per_grant_frame = XEN_PAGE_SIZE / sizeof(struct grant_entry_v1);
gnttab_interface = &gnttab_v1_ops;
pr_info("Grant tables using version %d layout\n", grant_table_version);
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 5e9adac928e6..df2e6f783318 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -401,7 +401,7 @@ static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
if (pages == NULL)
return -ENOMEM;
- rc = alloc_xenballooned_pages(numpgs, pages, 0);
+ rc = alloc_xenballooned_pages(numpgs, pages);
if (rc != 0) {
pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__,
numpgs, rc);
@@ -446,7 +446,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
return -EINVAL;
}
- nr_pages = m.num;
+ nr_pages = DIV_ROUND_UP(m.num, XEN_PFN_PER_PAGE);
if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT)))
return -EINVAL;
@@ -494,7 +494,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
goto out_unlock;
}
if (xen_feature(XENFEAT_auto_translated_physmap)) {
- ret = alloc_empty_pages(vma, m.num);
+ ret = alloc_empty_pages(vma, nr_pages);
if (ret < 0)
goto out_unlock;
} else
@@ -518,6 +518,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
state.global_error = 0;
state.version = version;
+ BUILD_BUG_ON(((PAGE_SIZE / sizeof(xen_pfn_t)) % XEN_PFN_PER_PAGE) != 0);
/* mmap_batch_fn guarantees ret == 0 */
BUG_ON(traverse_pages_block(m.num, sizeof(xen_pfn_t),
&pagelist, mmap_batch_fn, &state));
@@ -582,12 +583,13 @@ static void privcmd_close(struct vm_area_struct *vma)
{
struct page **pages = vma->vm_private_data;
int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ int numgfns = (vma->vm_end - vma->vm_start) >> XEN_PAGE_SHIFT;
int rc;
if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
return;
- rc = xen_unmap_domain_gfn_range(vma, numpgs, pages);
+ rc = xen_unmap_domain_gfn_range(vma, numgfns, pages);
if (rc == 0)
free_xenballooned_pages(numpgs, pages);
else
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 79bc4933b13e..7399782c0998 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -76,27 +76,27 @@ static unsigned long xen_io_tlb_nslabs;
static u64 start_dma_addr;
/*
- * Both of these functions should avoid PFN_PHYS because phys_addr_t
+ * Both of these functions should avoid XEN_PFN_PHYS because phys_addr_t
* can be 32bit when dma_addr_t is 64bit leading to a loss in
* information if the shift is done before casting to 64bit.
*/
static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr)
{
- unsigned long bfn = pfn_to_bfn(PFN_DOWN(paddr));
- dma_addr_t dma = (dma_addr_t)bfn << PAGE_SHIFT;
+ unsigned long bfn = pfn_to_bfn(XEN_PFN_DOWN(paddr));
+ dma_addr_t dma = (dma_addr_t)bfn << XEN_PAGE_SHIFT;
- dma |= paddr & ~PAGE_MASK;
+ dma |= paddr & ~XEN_PAGE_MASK;
return dma;
}
static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr)
{
- unsigned long pfn = bfn_to_pfn(PFN_DOWN(baddr));
- dma_addr_t dma = (dma_addr_t)pfn << PAGE_SHIFT;
+ unsigned long xen_pfn = bfn_to_pfn(XEN_PFN_DOWN(baddr));
+ dma_addr_t dma = (dma_addr_t)xen_pfn << XEN_PAGE_SHIFT;
phys_addr_t paddr = dma;
- paddr |= baddr & ~PAGE_MASK;
+ paddr |= baddr & ~XEN_PAGE_MASK;
return paddr;
}
@@ -106,7 +106,7 @@ static inline dma_addr_t xen_virt_to_bus(void *address)
return xen_phys_to_bus(virt_to_phys(address));
}
-static int check_pages_physically_contiguous(unsigned long pfn,
+static int check_pages_physically_contiguous(unsigned long xen_pfn,
unsigned int offset,
size_t length)
{
@@ -114,11 +114,11 @@ static int check_pages_physically_contiguous(unsigned long pfn,
int i;
int nr_pages;
- next_bfn = pfn_to_bfn(pfn);
- nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT;
+ next_bfn = pfn_to_bfn(xen_pfn);
+ nr_pages = (offset + length + XEN_PAGE_SIZE-1) >> XEN_PAGE_SHIFT;
for (i = 1; i < nr_pages; i++) {
- if (pfn_to_bfn(++pfn) != ++next_bfn)
+ if (pfn_to_bfn(++xen_pfn) != ++next_bfn)
return 0;
}
return 1;
@@ -126,28 +126,27 @@ static int check_pages_physically_contiguous(unsigned long pfn,
static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
{
- unsigned long pfn = PFN_DOWN(p);
- unsigned int offset = p & ~PAGE_MASK;
+ unsigned long xen_pfn = XEN_PFN_DOWN(p);
+ unsigned int offset = p & ~XEN_PAGE_MASK;
- if (offset + size <= PAGE_SIZE)
+ if (offset + size <= XEN_PAGE_SIZE)
return 0;
- if (check_pages_physically_contiguous(pfn, offset, size))
+ if (check_pages_physically_contiguous(xen_pfn, offset, size))
return 0;
return 1;
}
static int is_xen_swiotlb_buffer(dma_addr_t dma_addr)
{
- unsigned long bfn = PFN_DOWN(dma_addr);
- unsigned long pfn = bfn_to_local_pfn(bfn);
- phys_addr_t paddr;
+ unsigned long bfn = XEN_PFN_DOWN(dma_addr);
+ unsigned long xen_pfn = bfn_to_local_pfn(bfn);
+ phys_addr_t paddr = XEN_PFN_PHYS(xen_pfn);
/* If the address is outside our domain, it CAN
* have the same virtual address as another address
* in our domain. Therefore _only_ check address within our domain.
*/
- if (pfn_valid(pfn)) {
- paddr = PFN_PHYS(pfn);
+ if (pfn_valid(PFN_DOWN(paddr))) {
return paddr >= virt_to_phys(xen_io_tlb_start) &&
paddr < virt_to_phys(xen_io_tlb_end);
}
@@ -392,7 +391,7 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
*/
if (dma_capable(dev, dev_addr, size) &&
!range_straddles_page_boundary(phys, size) &&
- !xen_arch_need_swiotlb(dev, PFN_DOWN(phys), PFN_DOWN(dev_addr)) &&
+ !xen_arch_need_swiotlb(dev, phys, dev_addr) &&
!swiotlb_force) {
/* we are not interested in the dma_addr returned by
* xen_dma_map_page, only in the potential cache flushes executed
@@ -551,7 +550,7 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
dma_addr_t dev_addr = xen_phys_to_bus(paddr);
if (swiotlb_force ||
- xen_arch_need_swiotlb(hwdev, PFN_DOWN(paddr), PFN_DOWN(dev_addr)) ||
+ xen_arch_need_swiotlb(hwdev, paddr, dev_addr) ||
!dma_capable(hwdev, dev_addr, sg->length) ||
range_straddles_page_boundary(paddr, sg->length)) {
phys_addr_t map = swiotlb_tbl_map_single(hwdev,
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 9eeefd7cad41..43bcae852546 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -53,7 +53,6 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
#include <asm/hypervisor.h>
@@ -1438,9 +1437,10 @@ static void scsiback_aborted_task(struct se_cmd *se_cmd)
{
}
-static ssize_t scsiback_tpg_param_show_alias(struct se_portal_group *se_tpg,
+static ssize_t scsiback_tpg_param_alias_show(struct config_item *item,
char *page)
{
+ struct se_portal_group *se_tpg = param_to_tpg(item);
struct scsiback_tpg *tpg = container_of(se_tpg, struct scsiback_tpg,
se_tpg);
ssize_t rb;
@@ -1452,9 +1452,10 @@ static ssize_t scsiback_tpg_param_show_alias(struct se_portal_group *se_tpg,
return rb;
}
-static ssize_t scsiback_tpg_param_store_alias(struct se_portal_group *se_tpg,
+static ssize_t scsiback_tpg_param_alias_store(struct config_item *item,
const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = param_to_tpg(item);
struct scsiback_tpg *tpg = container_of(se_tpg, struct scsiback_tpg,
se_tpg);
int len;
@@ -1474,10 +1475,10 @@ static ssize_t scsiback_tpg_param_store_alias(struct se_portal_group *se_tpg,
return count;
}
-TF_TPG_PARAM_ATTR(scsiback, alias, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(scsiback_tpg_param_, alias);
static struct configfs_attribute *scsiback_param_attrs[] = {
- &scsiback_tpg_param_alias.attr,
+ &scsiback_tpg_param_attr_alias,
NULL,
};
@@ -1585,9 +1586,9 @@ static int scsiback_drop_nexus(struct scsiback_tpg *tpg)
return 0;
}
-static ssize_t scsiback_tpg_show_nexus(struct se_portal_group *se_tpg,
- char *page)
+static ssize_t scsiback_tpg_nexus_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct scsiback_tpg *tpg = container_of(se_tpg,
struct scsiback_tpg, se_tpg);
struct scsiback_nexus *tv_nexus;
@@ -1606,10 +1607,10 @@ static ssize_t scsiback_tpg_show_nexus(struct se_portal_group *se_tpg,
return ret;
}
-static ssize_t scsiback_tpg_store_nexus(struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t scsiback_tpg_nexus_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct scsiback_tpg *tpg = container_of(se_tpg,
struct scsiback_tpg, se_tpg);
struct scsiback_tport *tport_wwn = tpg->tport;
@@ -1681,26 +1682,25 @@ check_newline:
return count;
}
-TF_TPG_BASE_ATTR(scsiback, nexus, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(scsiback_tpg_, nexus);
static struct configfs_attribute *scsiback_tpg_attrs[] = {
- &scsiback_tpg_nexus.attr,
+ &scsiback_tpg_attr_nexus,
NULL,
};
static ssize_t
-scsiback_wwn_show_attr_version(struct target_fabric_configfs *tf,
- char *page)
+scsiback_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "xen-pvscsi fabric module %s on %s/%s on "
UTS_RELEASE"\n",
VSCSI_VERSION, utsname()->sysname, utsname()->machine);
}
-TF_WWN_ATTR_RO(scsiback, version);
+CONFIGFS_ATTR_RO(scsiback_wwn_, version);
static struct configfs_attribute *scsiback_wwn_attrs[] = {
- &scsiback_wwn_version.attr,
+ &scsiback_wwn_attr_version,
NULL,
};
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 2ba09c1195c8..056da6ee1a35 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -49,6 +49,10 @@
#include "xenbus_probe.h"
+#define XENBUS_PAGES(_grants) (DIV_ROUND_UP(_grants, XEN_PFN_PER_PAGE))
+
+#define XENBUS_MAX_RING_PAGES (XENBUS_PAGES(XENBUS_MAX_RING_GRANTS))
+
struct xenbus_map_node {
struct list_head next;
union {
@@ -57,10 +61,11 @@ struct xenbus_map_node {
} pv;
struct {
struct page *pages[XENBUS_MAX_RING_PAGES];
+ unsigned long addrs[XENBUS_MAX_RING_GRANTS];
void *addr;
} hvm;
};
- grant_handle_t handles[XENBUS_MAX_RING_PAGES];
+ grant_handle_t handles[XENBUS_MAX_RING_GRANTS];
unsigned int nr_handles;
};
@@ -388,7 +393,7 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr,
}
grefs[i] = err;
- vaddr = vaddr + PAGE_SIZE;
+ vaddr = vaddr + XEN_PAGE_SIZE;
}
return 0;
@@ -479,12 +484,12 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
unsigned int flags,
bool *leaked)
{
- struct gnttab_map_grant_ref map[XENBUS_MAX_RING_PAGES];
- struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_PAGES];
+ struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS];
+ struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
int i, j;
int err = GNTST_okay;
- if (nr_grefs > XENBUS_MAX_RING_PAGES)
+ if (nr_grefs > XENBUS_MAX_RING_GRANTS)
return -EINVAL;
for (i = 0; i < nr_grefs; i++) {
@@ -540,22 +545,22 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
{
struct xenbus_map_node *node;
struct vm_struct *area;
- pte_t *ptes[XENBUS_MAX_RING_PAGES];
- phys_addr_t phys_addrs[XENBUS_MAX_RING_PAGES];
+ pte_t *ptes[XENBUS_MAX_RING_GRANTS];
+ phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
int err = GNTST_okay;
int i;
bool leaked;
*vaddr = NULL;
- if (nr_grefs > XENBUS_MAX_RING_PAGES)
+ if (nr_grefs > XENBUS_MAX_RING_GRANTS)
return -EINVAL;
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return -ENOMEM;
- area = alloc_vm_area(PAGE_SIZE * nr_grefs, ptes);
+ area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes);
if (!area) {
kfree(node);
return -ENOMEM;
@@ -591,21 +596,44 @@ failed:
return err;
}
+struct map_ring_valloc_hvm
+{
+ unsigned int idx;
+
+ /* Why do we need two arrays? See comment of __xenbus_map_ring */
+ phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
+ unsigned long addrs[XENBUS_MAX_RING_GRANTS];
+};
+
+static void xenbus_map_ring_setup_grant_hvm(unsigned long gfn,
+ unsigned int goffset,
+ unsigned int len,
+ void *data)
+{
+ struct map_ring_valloc_hvm *info = data;
+ unsigned long vaddr = (unsigned long)gfn_to_virt(gfn);
+
+ info->phys_addrs[info->idx] = vaddr;
+ info->addrs[info->idx] = vaddr;
+
+ info->idx++;
+}
+
static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
grant_ref_t *gnt_ref,
unsigned int nr_grefs,
void **vaddr)
{
struct xenbus_map_node *node;
- int i;
int err;
void *addr;
bool leaked = false;
- /* Why do we need two arrays? See comment of __xenbus_map_ring */
- phys_addr_t phys_addrs[XENBUS_MAX_RING_PAGES];
- unsigned long addrs[XENBUS_MAX_RING_PAGES];
+ struct map_ring_valloc_hvm info = {
+ .idx = 0,
+ };
+ unsigned int nr_pages = XENBUS_PAGES(nr_grefs);
- if (nr_grefs > XENBUS_MAX_RING_PAGES)
+ if (nr_grefs > XENBUS_MAX_RING_GRANTS)
return -EINVAL;
*vaddr = NULL;
@@ -614,25 +642,22 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
if (!node)
return -ENOMEM;
- err = alloc_xenballooned_pages(nr_grefs, node->hvm.pages,
- false /* lowmem */);
+ err = alloc_xenballooned_pages(nr_pages, node->hvm.pages);
if (err)
goto out_err;
- for (i = 0; i < nr_grefs; i++) {
- unsigned long pfn = page_to_pfn(node->hvm.pages[i]);
- phys_addrs[i] = (unsigned long)pfn_to_kaddr(pfn);
- addrs[i] = (unsigned long)pfn_to_kaddr(pfn);
- }
+ gnttab_foreach_grant(node->hvm.pages, nr_grefs,
+ xenbus_map_ring_setup_grant_hvm,
+ &info);
err = __xenbus_map_ring(dev, gnt_ref, nr_grefs, node->handles,
- phys_addrs, GNTMAP_host_map, &leaked);
+ info.phys_addrs, GNTMAP_host_map, &leaked);
node->nr_handles = nr_grefs;
if (err)
goto out_free_ballooned_pages;
- addr = vmap(node->hvm.pages, nr_grefs, VM_MAP | VM_IOREMAP,
+ addr = vmap(node->hvm.pages, nr_pages, VM_MAP | VM_IOREMAP,
PAGE_KERNEL);
if (!addr) {
err = -ENOMEM;
@@ -650,14 +675,13 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
out_xenbus_unmap_ring:
if (!leaked)
- xenbus_unmap_ring(dev, node->handles, node->nr_handles,
- addrs);
+ xenbus_unmap_ring(dev, node->handles, nr_grefs, info.addrs);
else
pr_alert("leaking %p size %u page(s)",
- addr, nr_grefs);
+ addr, nr_pages);
out_free_ballooned_pages:
if (!leaked)
- free_xenballooned_pages(nr_grefs, node->hvm.pages);
+ free_xenballooned_pages(nr_pages, node->hvm.pages);
out_err:
kfree(node);
return err;
@@ -687,10 +711,10 @@ int xenbus_map_ring(struct xenbus_device *dev, grant_ref_t *gnt_refs,
unsigned int nr_grefs, grant_handle_t *handles,
unsigned long *vaddrs, bool *leaked)
{
- phys_addr_t phys_addrs[XENBUS_MAX_RING_PAGES];
+ phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
int i;
- if (nr_grefs > XENBUS_MAX_RING_PAGES)
+ if (nr_grefs > XENBUS_MAX_RING_GRANTS)
return -EINVAL;
for (i = 0; i < nr_grefs; i++)
@@ -723,7 +747,7 @@ EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
{
struct xenbus_map_node *node;
- struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_PAGES];
+ struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
unsigned int level;
int i;
bool leaked = false;
@@ -750,7 +774,7 @@ static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
unsigned long addr;
memset(&unmap[i], 0, sizeof(unmap[i]));
- addr = (unsigned long)vaddr + (PAGE_SIZE * i);
+ addr = (unsigned long)vaddr + (XEN_PAGE_SIZE * i);
unmap[i].host_addr = arbitrary_virt_to_machine(
lookup_address(addr, &level)).maddr;
unmap[i].dev_bus_addr = 0;
@@ -783,13 +807,33 @@ static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
return err;
}
+struct unmap_ring_vfree_hvm
+{
+ unsigned int idx;
+ unsigned long addrs[XENBUS_MAX_RING_GRANTS];
+};
+
+static void xenbus_unmap_ring_setup_grant_hvm(unsigned long gfn,
+ unsigned int goffset,
+ unsigned int len,
+ void *data)
+{
+ struct unmap_ring_vfree_hvm *info = data;
+
+ info->addrs[info->idx] = (unsigned long)gfn_to_virt(gfn);
+
+ info->idx++;
+}
+
static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr)
{
int rv;
struct xenbus_map_node *node;
void *addr;
- unsigned long addrs[XENBUS_MAX_RING_PAGES];
- int i;
+ struct unmap_ring_vfree_hvm info = {
+ .idx = 0,
+ };
+ unsigned int nr_pages;
spin_lock(&xenbus_valloc_lock);
list_for_each_entry(node, &xenbus_valloc_pages, next) {
@@ -809,18 +853,20 @@ static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr)
return GNTST_bad_virt_addr;
}
- for (i = 0; i < node->nr_handles; i++)
- addrs[i] = (unsigned long)pfn_to_kaddr(page_to_pfn(node->hvm.pages[i]));
+ nr_pages = XENBUS_PAGES(node->nr_handles);
+
+ gnttab_foreach_grant(node->hvm.pages, node->nr_handles,
+ xenbus_unmap_ring_setup_grant_hvm,
+ &info);
rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
- addrs);
+ info.addrs);
if (!rv) {
vunmap(vaddr);
- free_xenballooned_pages(node->nr_handles, node->hvm.pages);
+ free_xenballooned_pages(nr_pages, node->hvm.pages);
}
else
- WARN(1, "Leaking %p, size %u page(s)\n", vaddr,
- node->nr_handles);
+ WARN(1, "Leaking %p, size %u page(s)\n", vaddr, nr_pages);
kfree(node);
return rv;
@@ -841,11 +887,11 @@ int xenbus_unmap_ring(struct xenbus_device *dev,
grant_handle_t *handles, unsigned int nr_handles,
unsigned long *vaddrs)
{
- struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_PAGES];
+ struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS];
int i;
int err;
- if (nr_handles > XENBUS_MAX_RING_PAGES)
+ if (nr_handles > XENBUS_MAX_RING_GRANTS)
return -EINVAL;
for (i = 0; i < nr_handles; i++)
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 3cbe0556de26..33a31cfef55d 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -802,7 +802,8 @@ static int __init xenbus_init(void)
goto out_error;
xen_store_gfn = (unsigned long)v;
xen_store_interface =
- xen_remap(xen_store_gfn << PAGE_SHIFT, PAGE_SIZE);
+ xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
+ XEN_PAGE_SIZE);
break;
default:
pr_warn("Xenstore state unknown\n");
diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
index cff23872c5a9..5063c5e796b7 100644
--- a/drivers/xen/xlate_mmu.c
+++ b/drivers/xen/xlate_mmu.c
@@ -38,31 +38,28 @@
#include <xen/interface/xen.h>
#include <xen/interface/memory.h>
-/* map fgfn of domid to lpfn in the current domain */
-static int map_foreign_page(unsigned long lpfn, unsigned long fgfn,
- unsigned int domid)
-{
- int rc;
- struct xen_add_to_physmap_range xatp = {
- .domid = DOMID_SELF,
- .foreign_domid = domid,
- .size = 1,
- .space = XENMAPSPACE_gmfn_foreign,
- };
- xen_ulong_t idx = fgfn;
- xen_pfn_t gpfn = lpfn;
- int err = 0;
+typedef void (*xen_gfn_fn_t)(unsigned long gfn, void *data);
- set_xen_guest_handle(xatp.idxs, &idx);
- set_xen_guest_handle(xatp.gpfns, &gpfn);
- set_xen_guest_handle(xatp.errs, &err);
+/* Break down the pages in 4KB chunk and call fn for each gfn */
+static void xen_for_each_gfn(struct page **pages, unsigned nr_gfn,
+ xen_gfn_fn_t fn, void *data)
+{
+ unsigned long xen_pfn = 0;
+ struct page *page;
+ int i;
- rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
- return rc < 0 ? rc : err;
+ for (i = 0; i < nr_gfn; i++) {
+ if ((i % XEN_PFN_PER_PAGE) == 0) {
+ page = pages[i / XEN_PFN_PER_PAGE];
+ xen_pfn = page_to_xen_pfn(page);
+ }
+ fn(pfn_to_gfn(xen_pfn++), data);
+ }
}
struct remap_data {
xen_pfn_t *fgfn; /* foreign domain's gfn */
+ int nr_fgfn; /* Number of foreign gfn left to map */
pgprot_t prot;
domid_t domid;
struct vm_area_struct *vma;
@@ -71,24 +68,71 @@ struct remap_data {
struct xen_remap_gfn_info *info;
int *err_ptr;
int mapped;
+
+ /* Hypercall parameters */
+ int h_errs[XEN_PFN_PER_PAGE];
+ xen_ulong_t h_idxs[XEN_PFN_PER_PAGE];
+ xen_pfn_t h_gpfns[XEN_PFN_PER_PAGE];
+
+ int h_iter; /* Iterator */
};
+static void setup_hparams(unsigned long gfn, void *data)
+{
+ struct remap_data *info = data;
+
+ info->h_idxs[info->h_iter] = *info->fgfn;
+ info->h_gpfns[info->h_iter] = gfn;
+ info->h_errs[info->h_iter] = 0;
+
+ info->h_iter++;
+ info->fgfn++;
+}
+
static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
void *data)
{
struct remap_data *info = data;
struct page *page = info->pages[info->index++];
- unsigned long pfn = page_to_pfn(page);
- pte_t pte = pte_mkspecial(pfn_pte(pfn, info->prot));
- int rc;
+ pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), info->prot));
+ int rc, nr_gfn;
+ uint32_t i;
+ struct xen_add_to_physmap_range xatp = {
+ .domid = DOMID_SELF,
+ .foreign_domid = info->domid,
+ .space = XENMAPSPACE_gmfn_foreign,
+ };
- rc = map_foreign_page(pfn, *info->fgfn, info->domid);
- *info->err_ptr++ = rc;
- if (!rc) {
- set_pte_at(info->vma->vm_mm, addr, ptep, pte);
- info->mapped++;
+ nr_gfn = min_t(typeof(info->nr_fgfn), XEN_PFN_PER_PAGE, info->nr_fgfn);
+ info->nr_fgfn -= nr_gfn;
+
+ info->h_iter = 0;
+ xen_for_each_gfn(&page, nr_gfn, setup_hparams, info);
+ BUG_ON(info->h_iter != nr_gfn);
+
+ set_xen_guest_handle(xatp.idxs, info->h_idxs);
+ set_xen_guest_handle(xatp.gpfns, info->h_gpfns);
+ set_xen_guest_handle(xatp.errs, info->h_errs);
+ xatp.size = nr_gfn;
+
+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+
+ /* info->err_ptr expect to have one error status per Xen PFN */
+ for (i = 0; i < nr_gfn; i++) {
+ int err = (rc < 0) ? rc : info->h_errs[i];
+
+ *(info->err_ptr++) = err;
+ if (!err)
+ info->mapped++;
}
- info->fgfn++;
+
+ /*
+ * Note: The hypercall will return 0 in most of the case if even if
+ * all the fgmfn are not mapped. We still have to update the pte
+ * as the userspace may decide to continue.
+ */
+ if (!rc)
+ set_pte_at(info->vma->vm_mm, addr, ptep, pte);
return 0;
}
@@ -102,13 +146,14 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
{
int err;
struct remap_data data;
- unsigned long range = nr << PAGE_SHIFT;
+ unsigned long range = DIV_ROUND_UP(nr, XEN_PFN_PER_PAGE) << PAGE_SHIFT;
/* Kept here for the purpose of making sure code doesn't break
x86 PVOPS */
BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
data.fgfn = gfn;
+ data.nr_fgfn = nr;
data.prot = prot;
data.domid = domid;
data.vma = vma;
@@ -123,21 +168,20 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
}
EXPORT_SYMBOL_GPL(xen_xlate_remap_gfn_array);
-int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma,
- int nr, struct page **pages)
+static void unmap_gfn(unsigned long gfn, void *data)
{
- int i;
+ struct xen_remove_from_physmap xrp;
- for (i = 0; i < nr; i++) {
- struct xen_remove_from_physmap xrp;
- unsigned long pfn;
+ xrp.domid = DOMID_SELF;
+ xrp.gpfn = gfn;
+ (void)HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+}
- pfn = page_to_pfn(pages[i]);
+int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma,
+ int nr, struct page **pages)
+{
+ xen_for_each_gfn(pages, nr, unmap_gfn, NULL);
- xrp.domid = DOMID_SELF;
- xrp.gpfn = pfn;
- (void)HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
- }
return 0;
}
EXPORT_SYMBOL_GPL(xen_xlate_unmap_gfn_range);